summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.devcontainer/devcontainer.json32
-rw-r--r--.dir-locals.el1
-rw-r--r--.github/dockerfiles/Dockerfile.32-bit13
-rw-r--r--.github/dockerfiles/Dockerfile.64-bit46
-rw-r--r--.github/dockerfiles/Dockerfile.clang32
-rw-r--r--.github/dockerfiles/Dockerfile.cross-compile21
-rw-r--r--.github/dockerfiles/Dockerfile.documentation23
-rw-r--r--.github/dockerfiles/Dockerfile.ubuntu-base91
-rwxr-xr-x.github/dockerfiles/init.sh20
-rw-r--r--.github/dockerfiles/log4j.properties9
-rw-r--r--.github/dockerfiles/odbc.ini19
-rw-r--r--.github/dockerfiles/odbcinst.ini15
-rwxr-xr-x.github/scripts/base-tag20
-rwxr-xr-x.github/scripts/build-base-image.sh66
-rwxr-xr-x.github/scripts/build-macos-wxwidgets.sh28
-rwxr-xr-x.github/scripts/build-macos.sh12
-rwxr-xr-x.github/scripts/get-pr-number.es30
-rwxr-xr-x.github/scripts/path-filters.sh29
-rw-r--r--.github/scripts/pr-comment.js110
-rwxr-xr-x.github/scripts/restore-otp-image.sh13
-rwxr-xr-x.github/scripts/sync-github-prs.es144
-rwxr-xr-x.github/scripts/sync-github-releases.sh5
-rw-r--r--.github/workflows/main.yaml467
-rw-r--r--.github/workflows/pr-comment.yaml126
-rw-r--r--.github/workflows/sync-github-releases.yaml50
-rw-r--r--.github/workflows/update-base.yaml30
-rw-r--r--.gitignore58
-rw-r--r--.gitpod.yml7
-rw-r--r--CONTRIBUTING.md37
-rw-r--r--HOWTO/DEVELOPMENT.md597
-rw-r--r--HOWTO/INSTALL-ANDROID.md4
-rw-r--r--HOWTO/INSTALL-CROSS.md16
-rw-r--r--HOWTO/INSTALL-IOS.md119
-rw-r--r--HOWTO/INSTALL-RASPBERRYPI3.md6
-rw-r--r--HOWTO/INSTALL-WIN32-OLD.md4
-rw-r--r--HOWTO/INSTALL-WIN32.md4
-rw-r--r--HOWTO/INSTALL.md68
-rw-r--r--HOWTO/MARKDOWN.md2
-rw-r--r--HOWTO/SYSTEMTAP.md2
-rw-r--r--HOWTO/TESTING.md186
-rw-r--r--Makefile.in60
-rw-r--r--OTP_VERSION2
-rw-r--r--README.md46
-rw-r--r--bootstrap/bin/no_dot_erlang.bootbin6933 -> 7007 bytes
-rw-r--r--bootstrap/bin/start.bootbin6933 -> 7007 bytes
-rw-r--r--bootstrap/bin/start_clean.bootbin6933 -> 7007 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_a.beambin3124 -> 3220 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11056 -> 12076 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin3852 -> 4944 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bounds.beambin0 -> 5248 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_call_types.beambin13508 -> 18140 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_clean.beambin3868 -> 7136 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin4708 -> 5552 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_digraph.beambin3580 -> 3696 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin21720 -> 23532 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_flatten.beambin1692 -> 1720 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin10280 -> 11092 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_kernel_to_ssa.beambin27676 -> 26016 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_listing.beambin1632 -> 2200 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_opcodes.beambin7964 -> 8056 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_peep.beambin3560 -> 0 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa.beambin15196 -> 15476 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beambin9964 -> 10412 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_bool.beambin22844 -> 23256 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_bsm.beambin17924 -> 17608 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_codegen.beambin38552 -> 40128 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_dead.beambin12572 -> 16132 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_funs.beambin2572 -> 0 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_lint.beambin9344 -> 9508 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_opt.beambin50268 -> 50320 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_pp.beambin6040 -> 9172 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beambin47696 -> 45204 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_recv.beambin14004 -> 14396 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_share.beambin5428 -> 5912 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_throw.beambin7468 -> 7704 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_ssa_type.beambin35200 -> 35968 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_trim.beambin9524 -> 11964 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_types.beambin15584 -> 17432 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin3528 -> 3524 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin50264 -> 52224 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_z.beambin4776 -> 4044 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl.beambin28136 -> 28112 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_clauses.beambin2756 -> 2824 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_inline.beambin32804 -> 33172 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_trees.beambin19920 -> 20040 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin38448 -> 38004 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.app11
-rw-r--r--bootstrap/lib/compiler/ebin/compiler.appup2
-rw-r--r--bootstrap/lib/compiler/ebin/core_lib.beambin3588 -> 3780 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lint.beambin12500 -> 12696 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_parse.beambin83308 -> 83776 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin11600 -> 10492 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_scan.beambin6072 -> 6372 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/erl_bifs.beambin2088 -> 2180 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/rec_env.beambin4192 -> 4456 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_alias.beambin5576 -> 5352 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_bsm.beambin1580 -> 1668 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin42236 -> 42344 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold_lists.beambin3992 -> 4080 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_inline.beambin3448 -> 3500 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_prepare.beambin1680 -> 1744 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_messages.beambin3480 -> 3972 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_attributes.beambin2224 -> 2360 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin58324 -> 61640 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin41700 -> 43808 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel_pp.beambin11108 -> 10020 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application.beambin4328 -> 4512 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_controller.beambin35004 -> 35008 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_master.beambin6240 -> 6368 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_starter.beambin1204 -> 1308 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/auth.beambin6740 -> 7496 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin15296 -> 15728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin21880 -> 22168 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log.beambin28228 -> 28560 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_1.beambin21828 -> 22644 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_server.beambin3916 -> 4004 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_sup.beambin548 -> 624 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_ac.beambin23296 -> 23328 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_util.beambin16496 -> 15768 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_boot_server.beambin5604 -> 5724 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_compile_server.beambin4920 -> 5144 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_ddll.beambin2732 -> 2832 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_distribution.beambin2160 -> 2124 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_epmd.beambin7508 -> 7940 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_erts_errors.beambin19828 -> 22840 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_kernel_errors.beambin2436 -> 2944 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_reply.beambin856 -> 932 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erl_signal_handler.beambin1092 -> 1168 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erpc.beambin9016 -> 14112 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/error_handler.beambin1556 -> 1652 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/error_logger.beambin6200 -> 6368 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erts_debug.beambin8932 -> 9340 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file.beambin14328 -> 14768 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin15128 -> 15536 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_server.beambin4920 -> 5060 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_sctp.beambin3176 -> 5564 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_tcp.beambin2620 -> 3200 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_tcp_socket.beambin32048 -> 32944 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_udp.beambin2056 -> 2416 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/gen_udp_socket.beambin23860 -> 24348 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin32700 -> 38196 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_group.beambin15808 -> 19084 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_search.beambin2944 -> 3020 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin14000 -> 14128 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group_history.beambin7032 -> 7224 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/heart.beambin5160 -> 5412 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin26684 -> 28680 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_sctp.beambin1436 -> 1656 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp.beambin3132 -> 3892 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp_dist.beambin932 -> 1008 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_udp.beambin2164 -> 2648 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_config.beambin7252 -> 7476 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin26600 -> 26432 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_dns.beambin17728 -> 18416 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_gethost_native.beambin9760 -> 10584 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_hosts.beambin1600 -> 1768 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin12880 -> 13436 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_res.beambin13536 -> 14328 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_sctp.beambin2144 -> 2640 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp.beambin2872 -> 3528 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp_dist.beambin8020 -> 8748 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_udp.beambin2216 -> 2656 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.app11
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.appup107
-rw-r--r--bootstrap/lib/kernel/ebin/kernel.beambin3760 -> 4084 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel_config.beambin2672 -> 2788 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel_refc.beambin2220 -> 2316 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/local_tcp.beambin2148 -> 2244 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/local_udp.beambin1368 -> 1444 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger.beambin15852 -> 16292 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_backend.beambin2380 -> 2544 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_config.beambin3808 -> 3948 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_disk_log_h.beambin3264 -> 3344 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_filters.beambin1716 -> 1872 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_formatter.beambin8884 -> 9196 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_h_common.beambin7480 -> 7748 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_handler_watcher.beambin1328 -> 1420 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_olp.beambin7980 -> 8288 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_proxy.beambin2792 -> 2892 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_server.beambin11328 -> 11552 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_simple_h.beambin4588 -> 4804 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_std_h.beambin9668 -> 10172 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/logger_sup.beambin628 -> 704 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net.beambin3400 -> 12204 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_adm.beambin2816 -> 2908 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin27776 -> 31480 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/os.beambin5276 -> 6036 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/pg.beambin8168 -> 10972 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/pg2.beambin340 -> 416 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/ram_file.beambin5172 -> 5620 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/raw_file_io.beambin1516 -> 1464 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/raw_file_io_compressed.beambin2472 -> 2572 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/raw_file_io_deflate.beambin2576 -> 2712 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/raw_file_io_delayed.beambin5344 -> 5564 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/raw_file_io_inflate.beambin4120 -> 4440 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/raw_file_io_list.beambin2676 -> 2532 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/rpc.beambin14896 -> 11268 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/seq_trace.beambin1580 -> 1804 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/socket.beambin25216 -> 25704 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/standard_error.beambin3716 -> 3876 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin10996 -> 11312 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_drv.beambin11196 -> 11400 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_sup.beambin1700 -> 1836 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/wrap_log_reader.beambin2912 -> 3024 bytes
-rw-r--r--bootstrap/lib/kernel/include/dist.hrl115
-rw-r--r--bootstrap/lib/kernel/include/inet_sctp.hrl4
-rw-r--r--bootstrap/lib/stdlib/ebin/array.beambin11104 -> 12108 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/base64.beambin5844 -> 7320 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin18568 -> 19112 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/binary.beambin11284 -> 12180 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin18280 -> 18132 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/calendar.beambin8016 -> 9020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin45040 -> 45084 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_server.beambin6412 -> 6488 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_sup.beambin536 -> 612 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin24852 -> 26252 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin44020 -> 46200 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dict.beambin8648 -> 8932 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph.beambin7588 -> 7660 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6300 -> 6452 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin.beambin10300 -> 10768 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/edlin_expand.beambin4200 -> 4484 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin28696 -> 32476 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_abstract_code.beambin1024 -> 1116 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_anno.beambin3456 -> 3740 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_bits.beambin2388 -> 2512 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_compile.beambin6788 -> 8932 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_error.beambin10456 -> 11044 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin34952 -> 34864 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_expand_records.beambin19080 -> 19712 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_features.beambin0 -> 9188 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_internal.beambin6852 -> 7004 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin88076 -> 91980 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin140820 -> 145716 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_posix_msg.beambin5184 -> 5256 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin26664 -> 28460 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin25364 -> 27676 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_stdlib_errors.beambin16312 -> 17328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin30032 -> 31416 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_file_h.beambin3904 -> 4112 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/error_logger_tty_h.beambin4724 -> 4932 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/escript.beambin15588 -> 15812 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin20620 -> 21096 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/eval_bits.beambin7900 -> 8656 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin26864 -> 27640 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filelib.beambin11228 -> 11560 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/filename.beambin13740 -> 14100 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_sets.beambin7512 -> 7808 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gb_trees.beambin5064 -> 5316 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen.beambin6924 -> 9980 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_event.beambin14984 -> 17048 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_fsm.beambin13968 -> 14196 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_server.beambin17940 -> 20340 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_statem.beambin24604 -> 26732 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io.beambin7884 -> 8168 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib.beambin13104 -> 13608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_format.beambin15856 -> 12608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_format_ryu_table.beambin19156 -> 0 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_fread.beambin6272 -> 6552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin20516 -> 21980 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin28524 -> 30644 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/log_mf_h.beambin2340 -> 2520 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/maps.beambin5364 -> 6180 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/math.beambin1284 -> 1360 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin18348 -> 19068 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/orddict.beambin2872 -> 2948 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ordsets.beambin1832 -> 1900 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/otp_internal.beambin6028 -> 5948 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/peer.beambin0 -> 19136 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pool.beambin3572 -> 3660 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proc_lib.beambin14684 -> 15432 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proplists.beambin4768 -> 5040 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin63264 -> 63836 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin66924 -> 67828 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/queue.beambin8640 -> 8924 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/rand.beambin27928 -> 32776 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/random.beambin1700 -> 2044 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin12300 -> 12744 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sets.beambin8444 -> 8968 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin28796 -> 29440 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell_default.beambin4572 -> 4648 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell_docs.beambin17868 -> 18384 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/slave.beambin4716 -> 4924 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin34740 -> 35144 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.app9
-rw-r--r--bootstrap/lib/stdlib/ebin/stdlib.appup103
-rw-r--r--bootstrap/lib/stdlib/ebin/string.beambin33716 -> 35080 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin24848 -> 25268 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor_bridge.beambin5300 -> 5496 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin9152 -> 9280 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/timer.beambin5216 -> 5744 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin13112 -> 13444 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode_util.beambin201368 -> 205340 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/uri_string.beambin26604 -> 27532 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/win32reg.beambin5276 -> 5592 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin23928 -> 24352 bytes
-rwxr-xr-xconfigure6
-rw-r--r--configure.src6
-rw-r--r--erlang_ls.config10
-rw-r--r--erts/.gitignore2
-rw-r--r--erts/Makefile22
-rw-r--r--erts/autoconf/README.md10
-rw-r--r--erts/config.h.in61
-rwxr-xr-xerts/configure17334
-rw-r--r--erts/configure.ac (renamed from erts/configure.in)984
-rw-r--r--erts/doc/src/absform.xml15
-rw-r--r--erts/doc/src/alt_dist.xml34
-rw-r--r--erts/doc/src/erl_cmd.xml153
-rw-r--r--erts/doc/src/erl_dist_protocol.xml175
-rw-r--r--erts/doc/src/erl_ext_dist.xml51
-rw-r--r--erts/doc/src/erl_nif.xml48
-rw-r--r--erts/doc/src/erlang.xml356
-rw-r--r--erts/doc/src/erlc_cmd.xml45
-rw-r--r--erts/doc/src/erts_alloc.xml31
-rw-r--r--erts/doc/src/inet_cfg.xml4
-rw-r--r--erts/doc/src/init.xml4
-rw-r--r--erts/doc/src/match_spec.xml32
-rw-r--r--erts/doc/src/notes.xml2196
-rw-r--r--erts/doc/src/persistent_term.xml10
-rw-r--r--erts/emulator/Makefile4
-rw-r--r--erts/emulator/Makefile.in203
-rwxr-xr-xerts/emulator/asan/asan_logs_to_html22
-rw-r--r--erts/emulator/asan/suppress5
-rw-r--r--erts/emulator/beam/atom.c6
-rw-r--r--erts/emulator/beam/atom.h4
-rw-r--r--erts/emulator/beam/atom.names26
-rw-r--r--erts/emulator/beam/beam_bif_load.c163
-rw-r--r--erts/emulator/beam/beam_bp.c325
-rw-r--r--erts/emulator/beam/beam_bp.h5
-rw-r--r--erts/emulator/beam/beam_code.h7
-rw-r--r--erts/emulator/beam/beam_common.c576
-rw-r--r--erts/emulator/beam/beam_common.h112
-rw-r--r--erts/emulator/beam/beam_debug.c63
-rw-r--r--erts/emulator/beam/beam_file.c474
-rw-r--r--erts/emulator/beam/beam_file.h32
-rw-r--r--erts/emulator/beam/beam_load.c69
-rw-r--r--erts/emulator/beam/beam_load.h2
-rw-r--r--erts/emulator/beam/beam_ranges.c9
-rw-r--r--erts/emulator/beam/beam_transform_engine.c16
-rw-r--r--erts/emulator/beam/beam_types.c63
-rw-r--r--erts/emulator/beam/beam_types.h101
-rw-r--r--erts/emulator/beam/bif.c372
-rw-r--r--erts/emulator/beam/bif.h24
-rw-r--r--erts/emulator/beam/bif.tab5
-rw-r--r--erts/emulator/beam/big.c25
-rw-r--r--erts/emulator/beam/big.h6
-rw-r--r--erts/emulator/beam/binary.c8
-rw-r--r--erts/emulator/beam/break.c55
-rw-r--r--erts/emulator/beam/code_ix.c167
-rw-r--r--erts/emulator/beam/code_ix.h82
-rw-r--r--erts/emulator/beam/copy.c180
-rw-r--r--erts/emulator/beam/dist.c1216
-rw-r--r--erts/emulator/beam/dist.h106
-rw-r--r--erts/emulator/beam/emu/arith_instrs.tab4
-rw-r--r--erts/emulator/beam/emu/beam_emu.c103
-rw-r--r--erts/emulator/beam/emu/bif_instrs.tab5
-rw-r--r--erts/emulator/beam/emu/bs_instrs.tab639
-rw-r--r--erts/emulator/beam/emu/emu_load.c149
-rw-r--r--erts/emulator/beam/emu/float_instrs.tab10
-rw-r--r--erts/emulator/beam/emu/generators.tab204
-rw-r--r--erts/emulator/beam/emu/instrs.tab59
-rw-r--r--erts/emulator/beam/emu/load.h7
-rw-r--r--erts/emulator/beam/emu/macros.tab14
-rw-r--r--erts/emulator/beam/emu/map_instrs.tab10
-rw-r--r--erts/emulator/beam/emu/msg_instrs.tab6
-rw-r--r--erts/emulator/beam/emu/ops.tab669
-rw-r--r--erts/emulator/beam/emu/predicates.tab27
-rw-r--r--erts/emulator/beam/emu/trace_instrs.tab4
-rw-r--r--erts/emulator/beam/erl_alloc.c151
-rw-r--r--erts/emulator/beam/erl_alloc.h31
-rw-r--r--erts/emulator/beam/erl_alloc.types2
-rw-r--r--erts/emulator/beam/erl_alloc_util.c123
-rw-r--r--erts/emulator/beam/erl_alloc_util.h7
-rw-r--r--erts/emulator/beam/erl_ao_firstfit_alloc.c4
-rw-r--r--erts/emulator/beam/erl_arith.c4
-rw-r--r--erts/emulator/beam/erl_async.c28
-rw-r--r--erts/emulator/beam/erl_bestfit_alloc.c6
-rw-r--r--erts/emulator/beam/erl_bif_atomics.c32
-rw-r--r--erts/emulator/beam/erl_bif_binary.c2
-rw-r--r--erts/emulator/beam/erl_bif_chksum.c4
-rw-r--r--erts/emulator/beam/erl_bif_guard.c2
-rw-r--r--erts/emulator/beam/erl_bif_info.c673
-rw-r--r--erts/emulator/beam/erl_bif_op.c11
-rw-r--r--erts/emulator/beam/erl_bif_persistent.c35
-rw-r--r--erts/emulator/beam/erl_bif_port.c99
-rw-r--r--erts/emulator/beam/erl_bif_trace.c45
-rw-r--r--erts/emulator/beam/erl_bif_unique.c23
-rw-r--r--erts/emulator/beam/erl_bif_unique.h4
-rw-r--r--erts/emulator/beam/erl_binary.h34
-rw-r--r--erts/emulator/beam/erl_bits.c223
-rw-r--r--erts/emulator/beam/erl_bits.h29
-rw-r--r--erts/emulator/beam/erl_bits_f16.h4
-rw-r--r--erts/emulator/beam/erl_cpu_topology.c24
-rw-r--r--erts/emulator/beam/erl_cpu_topology.h5
-rw-r--r--erts/emulator/beam/erl_db.c773
-rw-r--r--erts/emulator/beam/erl_db.h15
-rw-r--r--erts/emulator/beam/erl_db_catree.c20
-rw-r--r--erts/emulator/beam/erl_db_hash.c469
-rw-r--r--erts/emulator/beam/erl_db_hash.h40
-rw-r--r--erts/emulator/beam/erl_db_tree.c16
-rw-r--r--erts/emulator/beam/erl_db_tree_util.h4
-rw-r--r--erts/emulator/beam/erl_db_util.c258
-rw-r--r--erts/emulator/beam/erl_db_util.h23
-rw-r--r--erts/emulator/beam/erl_debug.c2
-rw-r--r--erts/emulator/beam/erl_driver.h24
-rw-r--r--erts/emulator/beam/erl_drv_nif.h56
-rw-r--r--erts/emulator/beam/erl_flxctr.h4
-rw-r--r--erts/emulator/beam/erl_fun.c263
-rw-r--r--erts/emulator/beam/erl_fun.h95
-rw-r--r--erts/emulator/beam/erl_gc.c1103
-rw-r--r--erts/emulator/beam/erl_gc.h19
-rw-r--r--erts/emulator/beam/erl_global_literals.c8
-rw-r--r--erts/emulator/beam/erl_global_literals.h9
-rw-r--r--erts/emulator/beam/erl_hl_timer.c2
-rw-r--r--erts/emulator/beam/erl_init.c122
-rw-r--r--erts/emulator/beam/erl_io_queue.c2
-rw-r--r--erts/emulator/beam/erl_lock_check.c16
-rw-r--r--erts/emulator/beam/erl_lock_count.h4
-rw-r--r--erts/emulator/beam/erl_map.c241
-rw-r--r--erts/emulator/beam/erl_map.h24
-rw-r--r--erts/emulator/beam/erl_md5.c2
-rw-r--r--erts/emulator/beam/erl_message.c155
-rw-r--r--erts/emulator/beam/erl_message.h92
-rw-r--r--erts/emulator/beam/erl_monitor_link.c22
-rw-r--r--erts/emulator/beam/erl_monitor_link.h71
-rw-r--r--erts/emulator/beam/erl_msacc.c10
-rw-r--r--erts/emulator/beam/erl_msacc.h15
-rw-r--r--erts/emulator/beam/erl_mtrace.c1268
-rw-r--r--erts/emulator/beam/erl_mtrace.h52
-rw-r--r--erts/emulator/beam/erl_nfunc_sched.c19
-rw-r--r--erts/emulator/beam/erl_nfunc_sched.h20
-rw-r--r--erts/emulator/beam/erl_nif.c296
-rw-r--r--erts/emulator/beam/erl_nif.h31
-rw-r--r--erts/emulator/beam/erl_nif_api_funcs.h20
-rw-r--r--erts/emulator/beam/erl_node_container_utils.h4
-rw-r--r--erts/emulator/beam/erl_node_tables.c49
-rw-r--r--erts/emulator/beam/erl_node_tables.h17
-rw-r--r--erts/emulator/beam/erl_port_task.c32
-rw-r--r--erts/emulator/beam/erl_printf_term.c101
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c1913
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.h385
-rw-r--r--erts/emulator/beam/erl_process.c459
-rw-r--r--erts/emulator/beam/erl_process.h81
-rw-r--r--erts/emulator/beam/erl_process_dump.c19
-rw-r--r--erts/emulator/beam/erl_process_lock.c12
-rw-r--r--erts/emulator/beam/erl_process_lock.h52
-rw-r--r--erts/emulator/beam/erl_ptab.c8
-rw-r--r--erts/emulator/beam/erl_rbtree.h4
-rw-r--r--erts/emulator/beam/erl_term.c3
-rw-r--r--erts/emulator/beam/erl_term.h72
-rw-r--r--erts/emulator/beam/erl_thr_progress.c48
-rw-r--r--erts/emulator/beam/erl_thr_progress.h1
-rw-r--r--erts/emulator/beam/erl_thr_queue.c4
-rw-r--r--erts/emulator/beam/erl_threads.h29
-rw-r--r--erts/emulator/beam/erl_time_sup.c27
-rw-r--r--erts/emulator/beam/erl_trace.c18
-rw-r--r--erts/emulator/beam/erl_trace.h4
-rw-r--r--erts/emulator/beam/erl_unicode.c66
-rw-r--r--erts/emulator/beam/erl_unicode.h4
-rw-r--r--erts/emulator/beam/erl_utils.h5
-rw-r--r--erts/emulator/beam/erl_vm.h56
-rw-r--r--erts/emulator/beam/erlang_dtrace.d2
-rw-r--r--erts/emulator/beam/error.h6
-rw-r--r--erts/emulator/beam/export.c39
-rw-r--r--erts/emulator/beam/export.h21
-rw-r--r--erts/emulator/beam/external.c1053
-rw-r--r--erts/emulator/beam/generators.tab88
-rw-r--r--erts/emulator/beam/global.h52
-rw-r--r--erts/emulator/beam/hash.c2
-rw-r--r--erts/emulator/beam/io.c180
-rw-r--r--erts/emulator/beam/jit/arm/beam_asm.hpp1700
-rw-r--r--erts/emulator/beam/jit/arm/beam_asm_global.cpp349
-rw-r--r--erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl216
-rw-r--r--erts/emulator/beam/jit/arm/beam_asm_module.cpp837
-rw-r--r--erts/emulator/beam/jit/arm/generators.tab586
-rw-r--r--erts/emulator/beam/jit/arm/instr_arith.cpp1356
-rw-r--r--erts/emulator/beam/jit/arm/instr_bif.cpp995
-rw-r--r--erts/emulator/beam/jit/arm/instr_bs.cpp2023
-rw-r--r--erts/emulator/beam/jit/arm/instr_call.cpp217
-rw-r--r--erts/emulator/beam/jit/arm/instr_common.cpp1757
-rw-r--r--erts/emulator/beam/jit/arm/instr_float.cpp230
-rw-r--r--erts/emulator/beam/jit/arm/instr_fun.cpp453
-rw-r--r--erts/emulator/beam/jit/arm/instr_guard_bifs.cpp819
-rw-r--r--erts/emulator/beam/jit/arm/instr_map.cpp636
-rw-r--r--erts/emulator/beam/jit/arm/instr_msg.cpp385
-rw-r--r--erts/emulator/beam/jit/arm/instr_select.cpp498
-rw-r--r--erts/emulator/beam/jit/arm/instr_trace.cpp217
-rw-r--r--erts/emulator/beam/jit/arm/ops.tab1391
-rw-r--r--erts/emulator/beam/jit/arm/predicates.tab107
-rw-r--r--erts/emulator/beam/jit/arm/process_main.cpp314
-rw-r--r--erts/emulator/beam/jit/asm_load.c124
-rw-r--r--erts/emulator/beam/jit/beam_asm.h192
-rw-r--r--erts/emulator/beam/jit/beam_jit_args.hpp380
-rw-r--r--erts/emulator/beam/jit/beam_jit_common.c756
-rw-r--r--erts/emulator/beam/jit/beam_jit_common.cpp1310
-rw-r--r--erts/emulator/beam/jit/beam_jit_common.h101
-rw-r--r--erts/emulator/beam/jit/beam_jit_common.hpp290
-rw-r--r--erts/emulator/beam/jit/beam_jit_main.cpp592
-rw-r--r--erts/emulator/beam/jit/beam_jit_metadata.cpp541
-rw-r--r--erts/emulator/beam/jit/load.h14
-rw-r--r--erts/emulator/beam/jit/x86/beam_asm.cpp921
-rw-r--r--erts/emulator/beam/jit/x86/beam_asm.hpp919
-rw-r--r--erts/emulator/beam/jit/x86/beam_asm_global.cpp180
-rwxr-xr-xerts/emulator/beam/jit/x86/beam_asm_global.hpp.pl207
-rw-r--r--erts/emulator/beam/jit/x86/beam_asm_module.cpp494
-rw-r--r--erts/emulator/beam/jit/x86/beam_asm_perf.cpp254
-rw-r--r--erts/emulator/beam/jit/x86/generators.tab134
-rw-r--r--erts/emulator/beam/jit/x86/instr_arith.cpp796
-rw-r--r--erts/emulator/beam/jit/x86/instr_bif.cpp619
-rw-r--r--erts/emulator/beam/jit/x86/instr_bs.cpp1240
-rw-r--r--erts/emulator/beam/jit/x86/instr_call.cpp170
-rw-r--r--erts/emulator/beam/jit/x86/instr_common.cpp1227
-rw-r--r--erts/emulator/beam/jit/x86/instr_float.cpp253
-rw-r--r--erts/emulator/beam/jit/x86/instr_fun.cpp437
-rw-r--r--erts/emulator/beam/jit/x86/instr_guard_bifs.cpp225
-rw-r--r--erts/emulator/beam/jit/x86/instr_map.cpp524
-rw-r--r--erts/emulator/beam/jit/x86/instr_msg.cpp53
-rw-r--r--erts/emulator/beam/jit/x86/instr_select.cpp165
-rw-r--r--erts/emulator/beam/jit/x86/instr_trace.cpp84
-rw-r--r--erts/emulator/beam/jit/x86/ops.tab897
-rw-r--r--erts/emulator/beam/jit/x86/predicates.tab6
-rw-r--r--erts/emulator/beam/jit/x86/process_main.cpp348
-rw-r--r--erts/emulator/beam/predicates.tab53
-rw-r--r--erts/emulator/beam/sys.h67
-rw-r--r--erts/emulator/beam/time.c2
-rw-r--r--erts/emulator/beam/utils.c504
-rw-r--r--erts/emulator/drivers/common/inet_drv.c1932
-rw-r--r--erts/emulator/drivers/common/ram_file_drv.c4
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c41
-rw-r--r--erts/emulator/drivers/win32/ttsl_drv.c6
-rw-r--r--erts/emulator/drivers/win32/win_con.c2
-rw-r--r--erts/emulator/internal_doc/AutomaticYieldingOfCCode.md6
-rw-r--r--erts/emulator/internal_doc/BeamAsm.md215
-rw-r--r--erts/emulator/internal_doc/CodeLoading.md2
-rw-r--r--erts/emulator/internal_doc/DelayedDealloc.md4
-rw-r--r--erts/emulator/internal_doc/GarbageCollection.md4
-rw-r--r--erts/emulator/internal_doc/PTables.md8
-rw-r--r--erts/emulator/internal_doc/PortSignals.md4
-rw-r--r--erts/emulator/internal_doc/SuperCarrier.md14
-rw-r--r--erts/emulator/internal_doc/ThreadProgress.md6
-rw-r--r--erts/emulator/internal_doc/Tracing.md116
-rw-r--r--erts/emulator/internal_doc/beam_makeops.md207
-rw-r--r--erts/emulator/internal_doc/dec.erl4
-rw-r--r--erts/emulator/internal_doc/figures/beamasm-perf-annotate.pngbin100853 -> 108415 bytes
-rw-r--r--erts/emulator/internal_doc/figures/perf-beamasm.pngbin151978 -> 210188 bytes
-rw-r--r--erts/emulator/nifs/common/prim_file_nif.c11
-rw-r--r--erts/emulator/nifs/common/prim_file_nif.h11
-rw-r--r--erts/emulator/nifs/common/prim_net_nif.c2694
-rw-r--r--erts/emulator/nifs/common/prim_socket_nif.c216
-rw-r--r--erts/emulator/nifs/common/socket_dbg.c57
-rw-r--r--erts/emulator/nifs/common/socket_int.h50
-rw-r--r--erts/emulator/nifs/common/socket_tarray.c12
-rw-r--r--erts/emulator/nifs/common/socket_util.c554
-rw-r--r--erts/emulator/nifs/common/socket_util.h10
-rw-r--r--erts/emulator/nifs/unix/unix_prim_file.c24
-rw-r--r--erts/emulator/nifs/win32/win_prim_file.c11
-rw-r--r--erts/emulator/pcre/local_config.h3
-rw-r--r--erts/emulator/pcre/pcre_compile.c6
-rw-r--r--erts/emulator/pcre/pcre_exec.c10
-rw-r--r--erts/emulator/pcre/pcre_maketables.c2
-rw-r--r--erts/emulator/pcre/pcre_valid_utf8.c4
-rw-r--r--erts/emulator/ryu/README.ryu_update.md20
-rw-r--r--erts/emulator/ryu/common.h115
-rw-r--r--erts/emulator/ryu/d2s.c712
-rw-r--r--erts/emulator/ryu/d2s_full_table.h367
-rw-r--r--erts/emulator/ryu/d2s_intrinsics.h358
-rw-r--r--erts/emulator/ryu/digit_table.h35
-rw-r--r--erts/emulator/ryu/ryu.h36
-rw-r--r--erts/emulator/ryu/ryu.mk57
-rw-r--r--erts/emulator/sys/common/erl_check_io.c169
-rw-r--r--erts/emulator/sys/common/erl_check_io.h20
-rw-r--r--erts/emulator/sys/common/erl_mmap.c6
-rw-r--r--erts/emulator/sys/common/erl_mmap.h2
-rw-r--r--erts/emulator/sys/common/erl_mseg.c20
-rw-r--r--erts/emulator/sys/common/erl_mtrace_sys_wrap.c246
-rw-r--r--erts/emulator/sys/common/erl_poll.c12
-rw-r--r--erts/emulator/sys/unix/driver_int.h4
-rw-r--r--erts/emulator/sys/unix/erl_child_setup.c100
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h14
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys_ddll.c27
-rw-r--r--erts/emulator/sys/unix/sys_float.c2
-rw-r--r--erts/emulator/sys/unix/sys_signal_stack.c4
-rw-r--r--erts/emulator/sys/unix/sys_time.c8
-rw-r--r--erts/emulator/sys/win32/driver_int.h4
-rw-r--r--erts/emulator/sys/win32/erl_poll.c12
-rw-r--r--erts/emulator/sys/win32/erl_win32_sys_ddll.c4
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h4
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h4
-rw-r--r--erts/emulator/sys/win32/sys.c68
-rw-r--r--erts/emulator/sys/win32/sys_float.c2
-rw-r--r--erts/emulator/test/Makefile7
-rw-r--r--erts/emulator/test/alloc_SUITE.erl197
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.c2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.c8
-rw-r--r--erts/emulator/test/beam_SUITE.erl2
-rw-r--r--erts/emulator/test/bif_SUITE.erl109
-rw-r--r--erts/emulator/test/binary_SUITE.erl184
-rw-r--r--erts/emulator/test/bs_construct_SUITE.erl188
-rw-r--r--erts/emulator/test/bs_match_bin_SUITE.erl29
-rw-r--r--erts/emulator/test/bs_match_int_SUITE.erl10
-rw-r--r--erts/emulator/test/bs_match_tail_SUITE.erl43
-rw-r--r--erts/emulator/test/busy_port_SUITE.erl10
-rw-r--r--erts/emulator/test/code_SUITE.erl8
-rw-r--r--erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl29
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl8
-rw-r--r--erts/emulator/test/dirty_bif_SUITE.erl45
-rw-r--r--erts/emulator/test/dirty_nif_SUITE.erl43
-rw-r--r--erts/emulator/test/distribution_SUITE.erl1498
-rw-r--r--erts/emulator/test/distribution_SUITE_data/run.erl4
-rw-r--r--erts/emulator/test/driver_SUITE.erl195
-rw-r--r--erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c2
-rw-r--r--erts/emulator/test/dump_SUITE.erl34
-rw-r--r--erts/emulator/test/efile_SUITE.erl15
-rw-r--r--erts/emulator/test/emulator_bench.spec1
-rw-r--r--erts/emulator/test/emulator_gh.spec4
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/basic.c4
-rw-r--r--erts/emulator/test/erl_link_SUITE.erl113
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl35
-rw-r--r--erts/emulator/test/erts_test_utils.erl25
-rw-r--r--erts/emulator/test/estone_SUITE.erl4
-rw-r--r--erts/emulator/test/exception_SUITE.erl120
-rw-r--r--erts/emulator/test/float_SUITE.erl45
-rw-r--r--erts/emulator/test/fun_SUITE.erl25
-rw-r--r--erts/emulator/test/gc_SUITE.erl32
-rw-r--r--erts/emulator/test/guard_SUITE.erl16
-rw-r--r--erts/emulator/test/hash_SUITE.erl181
-rw-r--r--erts/emulator/test/hash_property_test_SUITE.erl54
-rw-r--r--erts/emulator/test/hello_SUITE_data/hello.erl6
-rw-r--r--erts/emulator/test/hibernate_SUITE.erl6
-rw-r--r--erts/emulator/test/hipe_SUITE_data/ref_cell.erl64
-rw-r--r--erts/emulator/test/hipe_SUITE_data/trycatch_1.erl13
-rw-r--r--erts/emulator/test/hipe_SUITE_data/trycatch_2.erl10
-rw-r--r--erts/emulator/test/hipe_SUITE_data/trycatch_3.erl9
-rw-r--r--erts/emulator/test/jit_SUITE.erl (renamed from erts/emulator/test/perf_SUITE.erl)144
-rw-r--r--erts/emulator/test/lcnt_SUITE.erl8
-rw-r--r--erts/emulator/test/list_bif_SUITE.erl46
-rw-r--r--erts/emulator/test/literal_area_collector_test.erl51
-rw-r--r--erts/emulator/test/lttng_SUITE.erl28
-rw-r--r--erts/emulator/test/map_SUITE.erl242
-rw-r--r--erts/emulator/test/map_SUITE_data/badmap_17.erl58
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl111
-rw-r--r--erts/emulator/test/message_queue_data_SUITE.erl32
-rw-r--r--erts/emulator/test/monitor_SUITE.erl308
-rw-r--r--erts/emulator/test/mtx_SUITE.erl4
-rw-r--r--erts/emulator/test/nif_SUITE.erl189
-rw-r--r--erts/emulator/test/nif_SUITE_data/Makefile.src2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c19
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.4.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.5.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.c7
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.erl12
-rw-r--r--erts/emulator/test/node_container_SUITE.erl62
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl72
-rw-r--r--erts/emulator/test/op_SUITE.erl296
-rw-r--r--erts/emulator/test/persistent_term_SUITE.erl4
-rw-r--r--erts/emulator/test/port_SUITE.erl57
-rw-r--r--erts/emulator/test/port_SUITE_data/port_test.c2
-rw-r--r--erts/emulator/test/port_bif_SUITE_data/port_test.c2
-rw-r--r--erts/emulator/test/process_SUITE.erl1315
-rw-r--r--erts/emulator/test/process_SUITE_data/Makefile.src39
-rw-r--r--erts/emulator/test/process_SUITE_data/fwd_node.c221
-rw-r--r--erts/emulator/test/random_iolist.erl7
-rw-r--r--erts/emulator/test/receive_SUITE.erl49
-rw-r--r--erts/emulator/test/ref_SUITE.erl30
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl361
-rw-r--r--erts/emulator/test/send_term_SUITE.erl13
-rw-r--r--erts/emulator/test/signal_SUITE.erl844
-rw-r--r--erts/emulator/test/small_SUITE.erl674
-rw-r--r--erts/emulator/test/smoke_test_SUITE.erl165
-rw-r--r--erts/emulator/test/system_info_SUITE.erl82
-rw-r--r--erts/emulator/test/time_SUITE.erl125
-rw-r--r--erts/emulator/test/timer_bif_SUITE.erl33
-rw-r--r--erts/emulator/test/trace_SUITE.erl32
-rw-r--r--erts/emulator/test/trace_local_SUITE.erl52
-rw-r--r--erts/emulator/test/tuple_SUITE.erl217
-rw-r--r--erts/emulator/test/unique_SUITE.erl31
-rw-r--r--erts/emulator/test/z_SUITE.erl11
-rwxr-xr-xerts/emulator/utils/beam_makeops236
-rwxr-xr-xerts/emulator/utils/count6
-rwxr-xr-xerts/emulator/utils/make_driver_tab29
-rwxr-xr-xerts/emulator/utils/make_preload4
-rw-r--r--erts/emulator/zlib/crc32.c1258
-rw-r--r--erts/emulator/zlib/crc32.h9877
-rw-r--r--erts/emulator/zlib/deflate.c108
-rw-r--r--erts/emulator/zlib/deflate.h27
-rw-r--r--erts/emulator/zlib/gzguts.h5
-rw-r--r--erts/emulator/zlib/inffast.c28
-rw-r--r--erts/emulator/zlib/inflate.c47
-rw-r--r--erts/emulator/zlib/inflate.h5
-rw-r--r--erts/emulator/zlib/inftrees.c8
-rw-r--r--erts/emulator/zlib/trees.c75
-rw-r--r--erts/emulator/zlib/zlib.h223
-rw-r--r--erts/emulator/zlib/zutil.c4
-rw-r--r--erts/emulator/zlib/zutil.h21
-rw-r--r--erts/epmd/src/epmd.c8
-rw-r--r--erts/epmd/src/epmd_int.h14
-rw-r--r--erts/epmd/src/epmd_srv.c2
-rw-r--r--erts/epmd/test/epmd.spec.vxworks2
-rw-r--r--erts/epmd/test/epmd_SUITE.erl4
-rw-r--r--erts/etc/Makefile3
-rw-r--r--erts/etc/common/Makefile.in7
-rw-r--r--erts/etc/common/erlexec.c47
-rw-r--r--erts/etc/common/etc_common.h9
-rw-r--r--erts/etc/common/heart.c27
-rw-r--r--erts/etc/common/inet_gethost.c10
-rw-r--r--erts/etc/unix/Install.src7
-rw-r--r--erts/etc/unix/Makefile4
-rw-r--r--erts/etc/unix/RELNOTES8
-rw-r--r--erts/etc/unix/cerl.src48
-rw-r--r--erts/etc/unix/dyn_erl.c9
-rw-r--r--erts/etc/unix/erl.src.src29
-rw-r--r--erts/etc/unix/etp-commands.in420
-rw-r--r--erts/etc/unix/etp-thr.py8
-rw-r--r--erts/etc/unix/etp.py2
-rw-r--r--erts/etc/unix/format_man_pages4
-rw-r--r--erts/etc/unix/jit-reader.c377
-rw-r--r--erts/etc/unix/makewhatis4
-rw-r--r--erts/etc/unix/run_erl.c6
-rw-r--r--erts/etc/unix/start.src24
-rw-r--r--erts/etc/unix/to_erl.c2
-rwxr-xr-xerts/etc/win32/cygwin_tools/mingw/cc.sh4
-rw-r--r--erts/etc/win32/cygwin_tools/mingw/coffix.c8
-rwxr-xr-xerts/etc/win32/cygwin_tools/vc/cc.sh6
-rw-r--r--erts/etc/win32/cygwin_tools/vc/coffix.c8
-rw-r--r--erts/etc/win32/erl.rc6
-rw-r--r--erts/etc/win32/erl_log.c2
-rw-r--r--erts/etc/win32/erlsrv/erlsrv_service.c16
-rw-r--r--erts/etc/win32/msys_tools/vc/cc.sh6
-rw-r--r--erts/etc/win32/msys_tools/vc/coffix.c8
-rw-r--r--erts/etc/win32/nsis/Makefile19
-rw-r--r--erts/etc/win32/nsis/erlang20.nsi83
-rwxr-xr-xerts/etc/win32/nsis/find_redist.sh2
-rw-r--r--erts/etc/win32/nsis/vsn_number.escript16
-rw-r--r--erts/etc/win32/port_entry.c4
-rw-r--r--erts/etc/win32/start_erl.c4
-rw-r--r--erts/etc/win32/version.h.src2
-rwxr-xr-xerts/etc/win32/wsl_tools/vc/cc.sh227
-rwxr-xr-xerts/etc/win32/wsl_tools/vc/coffix.c6
-rw-r--r--erts/example/matrix_nif.erl5
-rw-r--r--erts/example/time_compat.erl6
-rw-r--r--erts/include/erl_memory_trace_parser.h157
-rw-r--r--erts/include/internal/erl_memory_trace_protocol.h246
-rw-r--r--erts/include/internal/erl_misc_utils.h2
-rw-r--r--erts/include/internal/ethr_atomics.h4
-rw-r--r--erts/include/internal/ethr_internal.h32
-rw-r--r--erts/include/internal/ethr_mutex.h3
-rw-r--r--erts/include/internal/ethread.h15
-rw-r--r--erts/include/internal/ethread_header_config.h.in9
-rw-r--r--erts/include/internal/gcc/ethr_dw_atomic.h2
-rw-r--r--erts/include/internal/gcc/ethr_membar.h29
-rw-r--r--erts/include/internal/i386/ethr_dw_atomic.h8
-rw-r--r--erts/include/internal/i386/ethr_membar.h23
-rw-r--r--erts/include/internal/win/ethr_dw_atomic.h4
-rw-r--r--erts/include/internal/win/ethr_membar.h21
-rw-r--r--erts/lib_src/Makefile.in56
-rw-r--r--erts/lib_src/common/erl_memory_trace_parser.c1962
-rw-r--r--erts/lib_src/common/erl_misc_utils.c23
-rw-r--r--erts/lib_src/common/ethr_atomics.c4
-rw-r--r--erts/lib_src/common/ethr_aux.c6
-rw-r--r--erts/lib_src/common/ethr_cbf.c4
-rw-r--r--erts/lib_src/common/ethr_mutex.c33
-rw-r--r--erts/lib_src/pthread/ethread.c16
-rwxr-xr-xerts/lib_src/utils/make_atomics_api4
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md2
-rw-r--r--erts/lib_src/yielding_c_fun/lib/tiny_regex_c/UPGRADE_NOTE10
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c2
-rw-r--r--erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c2
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_lexer.c2
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_node.c2
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_printers.c2
-rw-r--r--erts/lib_src/yielding_c_fun/ycf_yield_fun.c4
-rw-r--r--erts/preloaded/ebin/atomics.beambin4628 -> 4692 bytes
-rw-r--r--erts/preloaded/ebin/counters.beambin4872 -> 4952 bytes
-rw-r--r--erts/preloaded/ebin/erl_init.beambin2832 -> 2912 bytes
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin59704 -> 60064 bytes
-rw-r--r--erts/preloaded/ebin/erl_tracer.beambin2452 -> 2524 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin132836 -> 132640 bytes
-rw-r--r--erts/preloaded/ebin/erts_code_purger.beambin14112 -> 14336 bytes
-rw-r--r--erts/preloaded/ebin/erts_dirty_process_signal_handler.beambin3032 -> 3108 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin27772 -> 28628 bytes
-rw-r--r--erts/preloaded/ebin/erts_literal_area_collector.beambin5464 -> 5932 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin61076 -> 61584 bytes
-rw-r--r--erts/preloaded/ebin/persistent_term.beambin2000 -> 2052 bytes
-rw-r--r--erts/preloaded/ebin/prim_buffer.beambin4064 -> 4208 bytes
-rw-r--r--erts/preloaded/ebin/prim_eval.beambin1660 -> 1652 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin32856 -> 33336 bytes
-rw-r--r--erts/preloaded/ebin/prim_inet.beambin94536 -> 102424 bytes
-rw-r--r--erts/preloaded/ebin/prim_net.beambin6212 -> 11812 bytes
-rw-r--r--erts/preloaded/ebin/prim_socket.beambin36556 -> 37004 bytes
-rw-r--r--erts/preloaded/ebin/prim_zip.beambin25868 -> 26256 bytes
-rw-r--r--erts/preloaded/ebin/socket_registry.beambin19836 -> 20080 bytes
-rw-r--r--erts/preloaded/ebin/zlib.beambin22536 -> 22660 bytes
-rw-r--r--erts/preloaded/src/Makefile14
-rw-r--r--erts/preloaded/src/add_abstract_code11
-rw-r--r--erts/preloaded/src/erl_tracer.erl2
-rw-r--r--erts/preloaded/src/erlang.erl185
-rw-r--r--erts/preloaded/src/erts.app.src2
-rw-r--r--erts/preloaded/src/erts_code_purger.erl2
-rw-r--r--erts/preloaded/src/erts_internal.erl39
-rw-r--r--erts/preloaded/src/erts_literal_area_collector.erl45
-rw-r--r--erts/preloaded/src/init.erl13
-rw-r--r--erts/preloaded/src/prim_buffer.erl7
-rw-r--r--erts/preloaded/src/prim_file.erl13
-rw-r--r--erts/preloaded/src/prim_inet.erl227
-rw-r--r--erts/preloaded/src/prim_net.erl412
-rw-r--r--erts/preloaded/src/prim_socket.erl83
-rw-r--r--erts/preloaded/src/prim_zip.erl8
-rw-r--r--erts/preloaded/src/zlib.erl10
-rw-r--r--erts/test/Makefile7
-rw-r--r--erts/test/erl_print_SUITE.erl4
-rw-r--r--erts/test/erlc_SUITE.erl695
-rw-r--r--erts/test/erlc_SUITE_data/src/enable.hrl1
-rw-r--r--erts/test/erlc_SUITE_data/src/exp2.hrl6
-rw-r--r--erts/test/erlc_SUITE_data/src/f_directives.erl67
-rw-r--r--erts/test/erlc_SUITE_data/src/f_disable.erl46
-rw-r--r--erts/test/erlc_SUITE_data/src/f_include_1.erl18
-rw-r--r--erts/test/erlc_SUITE_data/src/f_include_2.erl12
-rw-r--r--erts/test/erlc_SUITE_data/src/f_include_3.erl21
-rw-r--r--erts/test/erlc_SUITE_data/src/f_include_exp2.erl18
-rw-r--r--erts/test/erlc_SUITE_data/src/f_macros.erl65
-rw-r--r--erts/test/erlc_SUITE_data/src/foo.erl6
-rw-r--r--erts/test/erlc_SUITE_data/src/ignorant.erl (renamed from lib/diameter/test/diameter_ct.hrl)28
-rw-r--r--erts/test/erlc_SUITE_data/src/ignorant_directive.erl (renamed from erts/emulator/test/hipe_SUITE_data/literals.erl)26
-rw-r--r--erts/test/erlc_SUITE_data/src/is_enabled.hrl3
-rw-r--r--erts/test/erlc_SUITE_data/src/macro_enabled.hrl5
-rw-r--r--erts/test/erlc_SUITE_data/src/older.beambin0 -> 592 bytes
-rw-r--r--erts/test/erlc_SUITE_data/src/older.erl6
-rw-r--r--erts/test/erlexec_SUITE.erl2
-rw-r--r--erts/test/nt_SUITE.erl4
-rw-r--r--erts/test/otp_SUITE.erl340
-rw-r--r--erts/test/otp_SUITE_data/.keep (renamed from lib/dialyzer/test/race_SUITE_data/results/ets_insert_args3)0
-rw-r--r--erts/test/parallel_messages_SUITE.erl465
-rw-r--r--erts/test/parallel_messages_SUITE_data/visualize_throughput.html304
-rw-r--r--erts/test/upgrade_SUITE.erl2
-rw-r--r--erts/test/z_SUITE.erl60
-rw-r--r--erts/vsn.mk2
-rw-r--r--lib/asn1/c_src/Makefile5
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c8
-rw-r--r--lib/asn1/doc/src/asn1ct.xml9
-rw-r--r--lib/asn1/doc/src/notes.xml76
-rw-r--r--lib/asn1/examples/ecn_internaldoc.txt2
-rw-r--r--lib/asn1/examples/encode_decode_formats.txt2
-rw-r--r--lib/asn1/notes.html10
-rw-r--r--lib/asn1/src/Makefile16
-rw-r--r--lib/asn1/src/asn1ct.erl10
-rw-r--r--lib/asn1/src/asn1ct_check.erl18
-rw-r--r--lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl14
-rw-r--r--lib/asn1/src/asn1ct_constructed_per.erl89
-rw-r--r--lib/asn1/src/asn1ct_gen.erl22
-rw-r--r--lib/asn1/src/asn1ct_gen_ber_bin_v2.erl6
-rw-r--r--lib/asn1/src/asn1ct_gen_jer.erl2
-rw-r--r--lib/asn1/src/asn1ct_imm.erl107
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl4
-rw-r--r--lib/asn1/src/asn1ct_pretty_format.erl4
-rw-r--r--lib/asn1/src/asn1ct_tok.erl2
-rw-r--r--lib/asn1/src/asn1rt_nif.erl6
-rw-r--r--lib/asn1/src/asn1rtt_ber.erl6
-rw-r--r--lib/asn1/src/asn1rtt_per.erl32
-rw-r--r--lib/asn1/src/asn1rtt_real_common.erl4
-rw-r--r--lib/asn1/src/asn1rtt_uper.erl31
-rw-r--r--lib/asn1/test/Makefile5
-rw-r--r--lib/asn1/test/asn1_SUITE.erl20
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Comment.asn2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/CommonDataTypes.py6
-rw-r--r--lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Fragmented.asn19
-rw-r--r--lib/asn1/test/asn1_SUITE_data/H235-SECURITY-MESSAGES.asn2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Mvrasn-11-4.asn4
-rw-r--r--lib/asn1/test/asn1_SUITE_data/Nortel.asn4
-rw-r--r--lib/asn1/test/asn1_SUITE_data/PKIX1Explicit93.asn12
-rw-r--r--lib/asn1/test/asn1_SUITE_data/RANAP.asn14
-rw-r--r--lib/asn1/test/asn1_SUITE_data/SwCDR.py2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/nbapsystem/NBAP-PDU-Contents.asn6
-rw-r--r--lib/asn1/test/asn1_SUITE_data/rfcs/AlgorithmInformation-2009.asn12
-rw-r--r--lib/asn1/test/asn1_SUITE_data/rfcs/ISO8571-FTAM.asn16
-rw-r--r--lib/asn1/test/asn1_SUITE_data/tcapsystem/MAP-MS-DataTypes.asn2
-rw-r--r--lib/asn1/test/asn1_SUITE_data/testobj.erl12
-rw-r--r--lib/asn1/test/asn1_test_lib.erl11
-rw-r--r--lib/asn1/test/syntax_SUITE.erl2
-rw-r--r--lib/asn1/test/testFragmented.erl32
-rw-r--r--lib/asn1/test/test_compile_options.erl50
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/Makefile1
-rwxr-xr-xlib/common_test/configure1047
-rw-r--r--lib/common_test/configure.ac14
-rw-r--r--lib/common_test/configure.in14
-rw-r--r--lib/common_test/doc/src/ct.xml4
-rw-r--r--lib/common_test/doc/src/ct_hooks.xml4
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml4
-rw-r--r--lib/common_test/doc/src/ct_netconfc.xml4
-rw-r--r--lib/common_test/doc/src/ct_property_test.xml2
-rw-r--r--lib/common_test/doc/src/ct_ssh.xml4
-rw-r--r--lib/common_test/doc/src/ct_suite.xml4
-rw-r--r--lib/common_test/doc/src/dependencies_chapter.xml2
-rw-r--r--lib/common_test/doc/src/event_handler_chapter.xml4
-rw-r--r--lib/common_test/doc/src/notes.xml204
-rw-r--r--lib/common_test/doc/src/unix_telnet.xml4
-rw-r--r--lib/common_test/doc/src/write_test_chapter.xml20
-rw-r--r--lib/common_test/include/ct.hrl13
-rw-r--r--lib/common_test/src/Makefile4
-rw-r--r--lib/common_test/src/common_test.app.src14
-rw-r--r--lib/common_test/src/ct.erl6
-rw-r--r--lib/common_test/src/ct_config.erl2
-rw-r--r--lib/common_test/src/ct_framework.erl6
-rw-r--r--lib/common_test/src/ct_gen_conn.erl2
-rw-r--r--lib/common_test/src/ct_groups.erl2
-rw-r--r--lib/common_test/src/ct_hooks.erl8
-rw-r--r--lib/common_test/src/ct_hooks_lock.erl8
-rw-r--r--lib/common_test/src/ct_logs.erl2
-rw-r--r--lib/common_test/src/ct_netconfc.erl2
-rw-r--r--lib/common_test/src/ct_release_test.erl12
-rw-r--r--lib/common_test/src/ct_run.erl8
-rw-r--r--lib/common_test/src/ct_slave.erl4
-rw-r--r--lib/common_test/src/ct_snmp.erl4
-rw-r--r--lib/common_test/src/ct_telnet.erl6
-rw-r--r--lib/common_test/src/cth_log_redirect.erl10
-rw-r--r--lib/common_test/src/cth_surefire.erl177
-rw-r--r--lib/common_test/src/erl2html2.erl4
-rw-r--r--lib/common_test/src/test_server.erl153
-rw-r--r--lib/common_test/src/test_server_ctrl.erl163
-rw-r--r--lib/common_test/src/test_server_node.erl280
-rw-r--r--lib/common_test/src/test_server_sup.erl4
-rw-r--r--lib/common_test/test/Makefile5
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl4
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl13
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_8_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_surefire_SUITE.erl62
-rw-r--r--lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl12
-rw-r--r--lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_basic_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_timetrap_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_test_support.erl5
-rw-r--r--lib/common_test/test/erl2html2_SUITE.erl4
-rw-r--r--lib/common_test/test_server/Makefile9
-rwxr-xr-xlib/common_test/test_server/configure3075
-rw-r--r--lib/common_test/test_server/configure.ac (renamed from lib/common_test/test_server/configure.in)99
-rw-r--r--lib/common_test/test_server/ts.erl15
-rw-r--r--lib/common_test/test_server/ts.hrl6
-rw-r--r--lib/common_test/test_server/ts_install.erl8
-rw-r--r--lib/common_test/test_server/ts_run.erl4
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/Makefile8
-rw-r--r--lib/compiler/doc/src/compile.xml48
-rw-r--r--lib/compiler/doc/src/notes.xml468
-rw-r--r--lib/compiler/internal_doc/beam_ssa.md107
-rw-r--r--lib/compiler/src/Makefile31
-rw-r--r--lib/compiler/src/beam_asm.erl97
-rw-r--r--lib/compiler/src/beam_asm.hrl44
-rw-r--r--lib/compiler/src/beam_block.erl86
-rw-r--r--lib/compiler/src/beam_bounds.erl301
-rw-r--r--lib/compiler/src/beam_call_types.erl416
-rw-r--r--lib/compiler/src/beam_clean.erl145
-rw-r--r--lib/compiler/src/beam_dict.erl84
-rw-r--r--lib/compiler/src/beam_disasm.erl179
-rw-r--r--lib/compiler/src/beam_flatten.erl2
-rw-r--r--lib/compiler/src/beam_jump.erl126
-rw-r--r--lib/compiler/src/beam_kernel_to_ssa.erl281
-rw-r--r--lib/compiler/src/beam_listing.erl27
-rw-r--r--lib/compiler/src/beam_peep.erl223
-rw-r--r--lib/compiler/src/beam_ssa.erl36
-rw-r--r--lib/compiler/src/beam_ssa_bc_size.erl75
-rw-r--r--lib/compiler/src/beam_ssa_bool.erl21
-rw-r--r--lib/compiler/src/beam_ssa_bsm.erl31
-rw-r--r--lib/compiler/src/beam_ssa_codegen.erl323
-rw-r--r--lib/compiler/src/beam_ssa_dead.erl477
-rw-r--r--lib/compiler/src/beam_ssa_funs.erl152
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl941
-rw-r--r--lib/compiler/src/beam_ssa_pp.erl149
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl620
-rw-r--r--lib/compiler/src/beam_ssa_recv.erl52
-rw-r--r--lib/compiler/src/beam_ssa_share.erl47
-rw-r--r--lib/compiler/src/beam_ssa_throw.erl18
-rw-r--r--lib/compiler/src/beam_ssa_type.erl925
-rw-r--r--lib/compiler/src/beam_trim.erl709
-rw-r--r--lib/compiler/src/beam_types.erl159
-rw-r--r--lib/compiler/src/beam_types.hrl19
-rw-r--r--lib/compiler/src/beam_utils.erl35
-rw-r--r--lib/compiler/src/beam_validator.erl523
-rw-r--r--lib/compiler/src/beam_z.erl52
-rw-r--r--lib/compiler/src/cerl_inline.erl10
-rw-r--r--lib/compiler/src/compile.erl176
-rw-r--r--lib/compiler/src/compiler.app.src9
-rwxr-xr-xlib/compiler/src/genop.tab41
-rw-r--r--lib/compiler/src/rec_env.erl2
-rw-r--r--lib/compiler/src/sys_core_bsm.erl2
-rw-r--r--lib/compiler/src/sys_core_fold.erl92
-rw-r--r--lib/compiler/src/sys_core_fold_lists.erl16
-rw-r--r--lib/compiler/src/sys_messages.erl24
-rw-r--r--lib/compiler/src/v3_core.erl769
-rw-r--r--lib/compiler/src/v3_kernel.erl165
-rw-r--r--lib/compiler/src/v3_kernel.hrl4
-rw-r--r--lib/compiler/src/v3_kernel_pp.erl7
-rw-r--r--lib/compiler/test/Makefile41
-rw-r--r--lib/compiler/test/beam_bounds_SUITE.erl260
-rw-r--r--lib/compiler/test/beam_except_SUITE.erl26
-rw-r--r--lib/compiler/test/beam_jump_SUITE.erl49
-rw-r--r--lib/compiler/test/beam_ssa_SUITE.erl79
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl280
-rw-r--r--lib/compiler/test/beam_utils_SUITE.erl8
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl83
-rw-r--r--lib/compiler/test/bif_SUITE.erl60
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl12
-rw-r--r--lib/compiler/test/bs_construct_SUITE.erl17
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl50
-rw-r--r--lib/compiler/test/compilation_SUITE_data/compiler_1.erl10
-rw-r--r--lib/compiler/test/compilation_SUITE_data/convopts.erl4
-rw-r--r--lib/compiler/test/compilation_SUITE_data/opt_crash.erl4
-rw-r--r--lib/compiler/test/compilation_SUITE_data/otp_4790.erl4
-rw-r--r--lib/compiler/test/compile_SUITE.erl405
-rw-r--r--lib/compiler/test/compile_SUITE_data/asm_labels.erl47
-rw-r--r--lib/compiler/test/compile_SUITE_data/big.erl10
-rw-r--r--lib/compiler/test/compile_SUITE_data/bigE.erl22
-rw-r--r--lib/compiler/test/compile_SUITE_data/funs.erl8
-rw-r--r--lib/compiler/test/compile_SUITE_data/types_pp.erl127
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl41
-rw-r--r--lib/compiler/test/float_SUITE.erl10
-rw-r--r--lib/compiler/test/fun_SUITE.erl236
-rw-r--r--lib/compiler/test/guard_SUITE.erl246
-rw-r--r--lib/compiler/test/inline_SUITE.erl4
-rw-r--r--lib/compiler/test/lc_SUITE.erl4
-rw-r--r--lib/compiler/test/map_SUITE.erl426
-rw-r--r--lib/compiler/test/match_SUITE.erl38
-rw-r--r--lib/compiler/test/maybe_SUITE.erl285
-rw-r--r--lib/compiler/test/misc_SUITE.erl23
-rw-r--r--lib/compiler/test/property_test/compile_prop.erl76
-rw-r--r--lib/compiler/test/random_code_SUITE.erl28
-rw-r--r--lib/compiler/test/receive_SUITE.erl63
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl2
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl2
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_25.erl12
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_26.erl15
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_27.erl19
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_28.erl21
-rw-r--r--lib/compiler/test/record_SUITE.erl24
-rw-r--r--lib/compiler/test/record_SUITE_data/record_access_in_guards.erl4
-rw-r--r--lib/compiler/test/test_lib.erl37
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl81
-rw-r--r--lib/compiler/test/warnings_SUITE.erl163
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/crypto/c_src/Makefile.in12
-rw-r--r--lib/crypto/c_src/bn.c57
-rw-r--r--lib/crypto/c_src/bn.h11
-rw-r--r--lib/crypto/c_src/cipher.c28
-rw-r--r--lib/crypto/c_src/common.h4
-rw-r--r--lib/crypto/c_src/crypto.c21
-rw-r--r--lib/crypto/c_src/dh.c370
-rw-r--r--lib/crypto/c_src/dss.c117
-rw-r--r--lib/crypto/c_src/ec.c546
-rw-r--r--lib/crypto/c_src/ec.h19
-rw-r--r--lib/crypto/c_src/ecdh.c166
-rw-r--r--lib/crypto/c_src/engine.c596
-rw-r--r--lib/crypto/c_src/engine.h7
-rw-r--r--lib/crypto/c_src/evp.c69
-rw-r--r--lib/crypto/c_src/hash.c186
-rw-r--r--lib/crypto/c_src/hash_equals.c51
-rw-r--r--lib/crypto/c_src/hash_equals.h (renamed from erts/emulator/beam/erl_sock.h)35
-rw-r--r--lib/crypto/c_src/mac.c228
-rw-r--r--lib/crypto/c_src/otp_test_engine.c37
-rw-r--r--lib/crypto/c_src/pbkdf2_hmac.c38
-rw-r--r--lib/crypto/c_src/pkey.c1437
-rw-r--r--lib/crypto/c_src/rand.c6
-rw-r--r--lib/crypto/c_src/rsa.c320
-rwxr-xr-xlib/crypto/configure5698
-rw-r--r--lib/crypto/configure.ac960
-rw-r--r--lib/crypto/configure.in871
-rw-r--r--lib/crypto/doc/src/algorithm_details.xml5
-rw-r--r--lib/crypto/doc/src/crypto.xml321
-rw-r--r--lib/crypto/doc/src/crypto_app.xml7
-rw-r--r--lib/crypto/doc/src/engine_load.xml30
-rw-r--r--lib/crypto/doc/src/notes.xml440
-rw-r--r--lib/crypto/src/Makefile4
-rw-r--r--lib/crypto/src/crypto.app.src4
-rw-r--r--lib/crypto/src/crypto.erl424
-rw-r--r--lib/crypto/test/Makefile3
-rw-r--r--lib/crypto/test/crypto.spec4
-rw-r--r--lib/crypto/test/crypto_SUITE.erl399
-rw-r--r--lib/crypto/test/crypto_gh.spec5
-rw-r--r--lib/crypto/test/engine_SUITE.erl376
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_private_key.pem3
-rw-r--r--lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_public_key.pem3
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/notes.xml41
-rw-r--r--lib/debugger/priv/Makefile4
-rw-r--r--lib/debugger/src/Makefile4
-rw-r--r--lib/debugger/src/dbg_icmd.erl34
-rw-r--r--lib/debugger/src/dbg_ieval.erl17
-rw-r--r--lib/debugger/src/dbg_iload.erl2
-rw-r--r--lib/debugger/src/dbg_wx_break_win.erl6
-rw-r--r--lib/debugger/src/dbg_wx_settings.erl59
-rw-r--r--lib/debugger/src/dbg_wx_view.erl3
-rw-r--r--lib/debugger/src/i.erl4
-rw-r--r--lib/debugger/test/Makefile5
-rw-r--r--lib/debugger/test/bs_match_int_SUITE.erl4
-rw-r--r--lib/debugger/test/dbg_ui_SUITE.erl8
-rw-r--r--lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl6
-rw-r--r--lib/debugger/test/exception_SUITE.erl2
-rw-r--r--lib/debugger/test/fun_SUITE.erl4
-rw-r--r--lib/debugger/test/guard_SUITE.erl6
-rw-r--r--lib/debugger/test/int_SUITE_data/lists1.erl6
-rw-r--r--lib/debugger/test/int_SUITE_data/my_lists.erl18
-rw-r--r--lib/debugger/test/int_eval_SUITE.erl2
-rw-r--r--lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl2
-rw-r--r--lib/debugger/test/trycatch_SUITE.erl4
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/RELEASE_NOTES2
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml34
-rw-r--r--lib/dialyzer/doc/src/dialyzer_chapter.xml8
-rw-r--r--lib/dialyzer/doc/src/notes.xml262
-rw-r--r--lib/dialyzer/doc/src/typer_cmd.xml15
-rw-r--r--lib/dialyzer/src/Makefile15
-rw-r--r--lib/dialyzer/src/cerl_closurean.erl856
-rw-r--r--lib/dialyzer/src/cerl_lib.erl457
-rw-r--r--lib/dialyzer/src/cerl_pmatch.erl620
-rw-r--r--lib/dialyzer/src/cerl_typean.erl994
-rw-r--r--lib/dialyzer/src/dialyzer.app.src20
-rw-r--r--lib/dialyzer/src/dialyzer.erl7
-rw-r--r--lib/dialyzer/src/dialyzer.hrl14
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl37
-rw-r--r--lib/dialyzer/src/dialyzer_behaviours.erl145
-rw-r--r--lib/dialyzer/src/dialyzer_callgraph.erl236
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl27
-rw-r--r--lib/dialyzer/src/dialyzer_cl_parse.erl30
-rw-r--r--lib/dialyzer/src/dialyzer_clean_core.erl12
-rw-r--r--lib/dialyzer/src/dialyzer_codeserver.erl21
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl131
-rw-r--r--lib/dialyzer/src/dialyzer_coordinator.erl253
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl1329
-rw-r--r--lib/dialyzer/src/dialyzer_dep.erl98
-rw-r--r--lib/dialyzer/src/dialyzer_dot.erl8
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.erl3
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.hrl5
-rw-r--r--lib/dialyzer/src/dialyzer_options.erl38
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl45
-rw-r--r--lib/dialyzer/src/dialyzer_race_data_server.erl127
-rw-r--r--lib/dialyzer/src/dialyzer_races.erl2483
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl533
-rw-r--r--lib/dialyzer/src/dialyzer_typegraph.erl109
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl686
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl185
-rw-r--r--lib/dialyzer/src/dialyzer_worker.erl119
-rw-r--r--lib/dialyzer/src/erl_bif_types.erl42
-rw-r--r--lib/dialyzer/src/erl_types.erl720
-rw-r--r--lib/dialyzer/src/typer.erl987
-rw-r--r--lib/dialyzer/src/typer_core.erl1049
-rw-r--r--lib/dialyzer/test/Makefile3
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args2
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_not_exported3
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_not_exported.erl30
-rw-r--r--lib/dialyzer/test/dialyzer.spec6
-rw-r--r--lib/dialyzer/test/dialyzer_SUITE.erl65
-rw-r--r--lib/dialyzer/test/dialyzer_cl_SUITE.erl129
-rw-r--r--lib/dialyzer/test/dialyzer_cl_SUITE_data/call_to_missing_example.erl5
-rw-r--r--lib/dialyzer/test/dialyzer_cl_SUITE_data/previously_defined.erl5
-rw-r--r--lib/dialyzer/test/dialyzer_cl_SUITE_data/unknown_function_example.erl5
-rw-r--r--lib/dialyzer/test/dialyzer_common.erl25
-rw-r--r--lib/dialyzer/test/erl_types_SUITE.erl75
-rw-r--r--lib/dialyzer/test/extra_return_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/extra_return_SUITE_data/results/extra_return2
-rw-r--r--lib/dialyzer/test/extra_return_SUITE_data/src/extra_return.erl21
-rw-r--r--lib/dialyzer/test/indent_SUITE_data/dialyzer_options2
-rw-r--r--lib/dialyzer/test/indent_SUITE_data/results/whereis_control_flow14
-rw-r--r--lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl4
-rw-r--r--lib/dialyzer/test/indent_SUITE_data/src/whereis_control_flow1.erl17
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/opaque_key4
-rw-r--r--lib/dialyzer/test/missing_return_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/missing_return_SUITE_data/results/missing_return2
-rw-r--r--lib/dialyzer/test/missing_return_SUITE_data/src/missing_return.erl21
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/para32
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl4
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl4
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl10
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl10
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl4
-rw-r--r--lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl4
-rw-r--r--lib/dialyzer/test/plt_SUITE.erl481
-rw-r--r--lib/dialyzer/test/plt_SUITE_data/type_deps.erl18
-rw-r--r--lib/dialyzer/test/property_test/erl_types_prop.erl230
-rw-r--r--lib/dialyzer/test/race_SUITE_data/dialyzer_options1
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args102
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args72
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_args82
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow33
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow43
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow55
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_double14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_double24
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_new0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_param5
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/ets_insert_public2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/extract_translations5
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow43
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice3
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice3
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice3
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race0
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module72
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module82
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_param2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module2
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function72
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function82
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch3
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars10
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars102
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars110
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars122
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars132
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars142
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars152
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars162
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars172
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars180
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars190
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars200
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars210
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars222
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars42
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars52
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars62
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars72
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars82
-rw-r--r--lib/dialyzer/test/race_SUITE_data/results/whereis_vars92
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args10.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1_suppressed.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl16
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl26
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl31
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl31
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl34
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl28
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl28
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl15
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl26
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl293
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl33
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl37
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl34
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl30
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl20
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl27
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl21
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl32
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl29
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl16
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl26
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl12
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl8
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl8
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl8
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl21
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl16
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl16
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl11
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl27
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl14
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl16
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl8
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl13
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl24
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl27
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl27
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl21
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl24
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl19
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl25
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl17
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl23
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl27
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl18
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl22
-rw-r--r--lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/fun_hangs2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/gencall8
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/guards4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/try21
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl22
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl18
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/fun_named.erl10
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/gencall.erl4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/gh_6518.erl12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/guards.erl21
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/gh65807
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/gh6580.erl15
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl54
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/Makefile1
-rw-r--r--lib/diameter/doc/src/notes.xml55
-rw-r--r--lib/diameter/src/Makefile18
-rw-r--r--lib/diameter/src/base/diameter_callback.erl4
-rw-r--r--lib/diameter/src/base/diameter_reg.erl4
-rw-r--r--lib/diameter/src/base/diameter_service.erl6
-rw-r--r--lib/diameter/src/base/diameter_types.erl12
-rw-r--r--lib/diameter/src/diameter.app.src4
-rw-r--r--lib/diameter/src/diameter.appup.src18
-rw-r--r--lib/diameter/src/info/diameter_info.erl2
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl19
-rw-r--r--lib/diameter/test/Makefile42
-rw-r--r--lib/diameter/test/diameter.spec1
-rw-r--r--lib/diameter/test/diameter_3xxx_SUITE.erl152
-rw-r--r--lib/diameter/test/diameter_app_SUITE.erl118
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl208
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl167
-rw-r--r--lib/diameter/test/diameter_codec_test.erl4
-rw-r--r--lib/diameter/test/diameter_compiler_SUITE.erl135
-rw-r--r--lib/diameter/test/diameter_config_SUITE.erl74
-rw-r--r--lib/diameter/test/diameter_dist_SUITE.erl156
-rw-r--r--lib/diameter/test/diameter_distribution_SUITE.erl185
-rw-r--r--lib/diameter/test/diameter_dpr_SUITE.erl125
-rw-r--r--lib/diameter/test/diameter_event_SUITE.erl78
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl290
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl102
-rw-r--r--lib/diameter/test/diameter_gen_sctp_SUITE.erl39
-rw-r--r--lib/diameter/test/diameter_gen_tcp_SUITE.erl37
-rw-r--r--lib/diameter/test/diameter_gh.spec2
-rw-r--r--lib/diameter/test/diameter_length_SUITE.erl84
-rw-r--r--lib/diameter/test/diameter_pool_SUITE.erl97
-rw-r--r--lib/diameter/test/diameter_reg_SUITE.erl82
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl161
-rw-r--r--lib/diameter/test/diameter_stats_SUITE.erl71
-rw-r--r--lib/diameter/test/diameter_sync_SUITE.erl81
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl190
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl519
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl123
-rw-r--r--lib/diameter/test/diameter_util.erl241
-rw-r--r--lib/diameter/test/diameter_watchdog_SUITE.erl129
-rw-r--r--lib/diameter/test/modules.mk7
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/edoc/bin/Makefile4
-rw-r--r--lib/edoc/doc/Makefile2
-rw-r--r--lib/edoc/doc/src/notes.xml39
-rw-r--r--lib/edoc/include/Makefile2
-rw-r--r--lib/edoc/priv/Makefile2
-rw-r--r--lib/edoc/src/Makefile2
-rw-r--r--lib/edoc/src/edoc.app.src2
-rw-r--r--lib/edoc/src/edoc.erl2
-rw-r--r--lib/edoc/src/edoc_doclet_chunks.erl16
-rw-r--r--lib/edoc/src/edoc_layout_chunks.erl87
-rw-r--r--lib/edoc/src/edoc_tags.erl1
-rw-r--r--lib/edoc/src/edoc_types.erl28
-rw-r--r--lib/edoc/src/edoc_wiki.erl2
-rw-r--r--lib/edoc/test/Makefile3
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/eldap/doc/src/eldap.xml13
-rw-r--r--lib/eldap/src/Makefile6
-rw-r--r--lib/eldap/src/eldap.app.src2
-rw-r--r--lib/eldap/src/eldap.erl23
-rw-r--r--lib/eldap/test/Makefile5
-rw-r--r--lib/eldap/test/eldap_basic_SUITE.erl39
-rw-r--r--lib/erl_docgen/doc/src/doc_storage.xml2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml50
-rw-r--r--lib/erl_docgen/priv/bin/Makefile4
-rwxr-xr-xlib/erl_docgen/priv/bin/github_link.escript4
-rwxr-xr-xlib/erl_docgen/priv/bin/validate_links.escript23
-rw-r--r--lib/erl_docgen/priv/css/Makefile4
-rw-r--r--lib/erl_docgen/priv/dtd/Makefile4
-rw-r--r--lib/erl_docgen/priv/dtd/common.dtd2
-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/Makefile4
-rw-r--r--lib/erl_docgen/priv/js/flipmenu/Makefile4
-rw-r--r--lib/erl_docgen/priv/xsl/Makefile4
-rw-r--r--lib/erl_docgen/priv/xsl/db_html.xsl2
-rw-r--r--lib/erl_docgen/src/Makefile4
-rw-r--r--lib/erl_docgen/src/docgen_edoc_xml_cb.erl6
-rw-r--r--lib/erl_docgen/src/docgen_otp_specs.erl2
-rw-r--r--lib/erl_docgen/src/docgen_xml_to_chunk.erl74
-rw-r--r--lib/erl_docgen/src/erl_docgen.app.src2
-rw-r--r--lib/erl_docgen/test/Makefile3
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/config.h.in50
-rwxr-xr-xlib/erl_interface/configure6342
-rw-r--r--lib/erl_interface/configure.ac (renamed from lib/erl_interface/configure.in)76
-rw-r--r--lib/erl_interface/doc/src/ei_connect.xml30
-rw-r--r--lib/erl_interface/doc/src/ei_users_guide.xml4
-rw-r--r--lib/erl_interface/doc/src/notes.xml106
-rw-r--r--lib/erl_interface/include/ei.h8
-rw-r--r--lib/erl_interface/src/Makefile6
-rw-r--r--lib/erl_interface/src/Makefile.in7
-rw-r--r--lib/erl_interface/src/README.internal14
-rwxr-xr-xlib/erl_interface/src/auxdir/config.guess1700
-rwxr-xr-xlib/erl_interface/src/auxdir/config.sub1860
-rwxr-xr-xlib/erl_interface/src/auxdir/install-sh541
-rw-r--r--lib/erl_interface/src/connect/ei_connect.c276
-rw-r--r--lib/erl_interface/src/connect/ei_connect_int.h38
-rw-r--r--lib/erl_interface/src/connect/eirecv.c6
-rw-r--r--lib/erl_interface/src/connect/send_exit.c4
-rw-r--r--lib/erl_interface/src/decode/decode_atom.c4
-rw-r--r--lib/erl_interface/src/decode/decode_fun.c4
-rw-r--r--lib/erl_interface/src/encode/encode_atom.c4
-rw-r--r--lib/erl_interface/src/epmd/ei_epmd.h4
-rw-r--r--lib/erl_interface/src/epmd/epmd_publish.c6
-rw-r--r--lib/erl_interface/src/epmd/epmd_unpublish.c4
-rw-r--r--lib/erl_interface/src/misc/ei_compat.c8
-rw-r--r--lib/erl_interface/src/misc/ei_internal.h4
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c2
-rw-r--r--lib/erl_interface/src/misc/eimd5.c2
-rw-r--r--lib/erl_interface/src/misc/show_msg.c18
-rw-r--r--lib/erl_interface/src/prog/erl_call.c14
-rw-r--r--lib/erl_interface/test/Makefile4
-rw-r--r--lib/erl_interface/test/all_SUITE_data/ei_runner.c2
-rw-r--r--lib/erl_interface/test/all_SUITE_data/ei_runner.h3
-rw-r--r--lib/erl_interface/test/all_SUITE_data/reclaim.h152
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE.erl246
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c21
-rw-r--r--lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c4
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c2
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/einode.c2
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl4
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c2
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl277
-rw-r--r--lib/erl_interface/test/runner.erl17
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/et_desc.xmlsrc4
-rw-r--r--lib/et/examples/Makefile4
-rw-r--r--lib/et/src/Makefile6
-rw-r--r--lib/et/src/et.erl4
-rw-r--r--lib/et/src/et_selector.erl4
-rw-r--r--lib/et/src/et_wx_viewer.erl2
-rw-r--r--lib/et/test/Makefile4
-rw-r--r--lib/eunit/doc/src/notes.xml83
-rw-r--r--lib/eunit/examples/Makefile2
-rw-r--r--lib/eunit/src/Makefile4
-rw-r--r--lib/eunit/src/eunit.erl5
-rw-r--r--lib/eunit/src/eunit_data.erl282
-rw-r--r--lib/eunit/src/eunit_internal.hrl1
-rw-r--r--lib/eunit/src/eunit_lib.erl23
-rw-r--r--lib/eunit/src/eunit_proc.erl12
-rw-r--r--lib/eunit/src/eunit_server.erl3
-rw-r--r--lib/eunit/test/Makefile6
-rw-r--r--lib/eunit/test/eunit_SUITE.erl113
-rw-r--r--lib/eunit/test/eunit_test_listener.erl85
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/ftp/doc/src/notes.xml68
-rw-r--r--lib/ftp/src/Makefile4
-rw-r--r--lib/ftp/src/ftp.erl180
-rw-r--r--lib/ftp/src/ftp_progress.erl6
-rw-r--r--lib/ftp/src/ftp_response.erl12
-rw-r--r--lib/ftp/test/Makefile6
-rw-r--r--lib/ftp/test/erl_make_certs.erl474
-rw-r--r--lib/ftp/test/ftp_SUITE.erl39
-rw-r--r--lib/ftp/test/ftp_SUITE_data/vsftpd.conf2
-rw-r--r--lib/ftp/test/ftp_format_SUITE.erl22
-rw-r--r--lib/ftp/test/ftp_test_lib.erl33
-rw-r--r--lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf2
-rw-r--r--lib/ftp/vsn.mk2
-rw-r--r--lib/inets/AUTHORS2
-rw-r--r--lib/inets/doc/specs/.gitignore1
-rw-r--r--lib/inets/doc/src/Makefile19
-rw-r--r--lib/inets/doc/src/http_client.xml16
-rw-r--r--lib/inets/doc/src/http_uri.xml91
-rw-r--r--lib/inets/doc/src/httpc.xml905
-rw-r--r--lib/inets/doc/src/httpd.xml322
-rw-r--r--lib/inets/doc/src/httpd_util.xml10
-rw-r--r--lib/inets/doc/src/mod_esi.xml21
-rw-r--r--lib/inets/doc/src/notes.xml297
-rw-r--r--lib/inets/doc/src/specs.xml14
-rw-r--r--lib/inets/examples/httpd_load_test/Makefile6
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_ctrl.erl4
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_slave.erl4
-rw-r--r--lib/inets/examples/server_root/Makefile4
-rw-r--r--lib/inets/priv/Makefile4
-rw-r--r--lib/inets/src/http_client/Makefile4
-rw-r--r--lib/inets/src/http_client/httpc.erl601
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl94
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl4
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl6
-rw-r--r--lib/inets/src/http_client/httpc_request.erl6
-rw-r--r--lib/inets/src/http_client/httpc_response.erl30
-rw-r--r--lib/inets/src/http_lib/Makefile4
-rw-r--r--lib/inets/src/http_lib/http_chunk.erl8
-rw-r--r--lib/inets/src/http_lib/http_request.erl8
-rw-r--r--lib/inets/src/http_lib/http_transport.erl63
-rw-r--r--lib/inets/src/http_lib/http_uri.erl258
-rw-r--r--lib/inets/src/http_server/Makefile4
-rw-r--r--lib/inets/src/http_server/httpd.erl274
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl37
-rw-r--r--lib/inets/src/http_server/httpd_request.erl18
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl10
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl12
-rw-r--r--lib/inets/src/http_server/httpd_util.erl12
-rw-r--r--lib/inets/src/http_server/mod_alias.erl6
-rw-r--r--lib/inets/src/http_server/mod_cgi.erl10
-rw-r--r--lib/inets/src/inets_app/Makefile4
-rw-r--r--lib/inets/src/inets_app/inets.app.src6
-rw-r--r--lib/inets/src/inets_app/inets.appup.src4
-rw-r--r--lib/inets/test/Makefile3
-rw-r--r--lib/inets/test/httpc_SUITE.erl153
-rw-r--r--lib/inets/test/httpc_proxy_SUITE.erl22
-rw-r--r--lib/inets/test/httpd_1_1.erl2
-rw-r--r--lib/inets/test/httpd_SUITE.erl80
-rw-r--r--lib/inets/test/httpd_all.erl2
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl4
-rw-r--r--lib/inets/test/httpd_bench_SUITE.erl6
-rw-r--r--lib/inets/test/httpd_mod.erl2
-rw-r--r--lib/inets/test/httpd_poll.erl5
-rw-r--r--lib/inets/test/httpd_test_data/server_root/Makefile4
-rw-r--r--lib/inets/test/httpd_test_lib.erl4
-rw-r--r--lib/inets/test/httpd_time_test.erl5
-rw-r--r--lib/inets/test/uri_SUITE.erl257
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/Makefile4
-rw-r--r--lib/jinterface/doc/src/jinterface_users_guide.xml58
-rw-r--r--lib/jinterface/doc/src/notes.xml91
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java194
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java85
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile12
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java6
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangAtom.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangDouble.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java5
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java6
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java9
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpGenericTransportFactory.java87
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpLocalNode.java8
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java97
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpSelf.java20
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpServer.java4
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/java_files9
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/package.html4
-rw-r--r--lib/jinterface/test/Makefile4
-rw-r--r--lib/jinterface/test/jinterface_SUITE.erl32
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/GenericTransportFactoryTest.java99
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/Makefile.src8
-rw-r--r--lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java4
-rw-r--r--lib/jinterface/test/nc_SUITE.erl40
-rw-r--r--lib/jinterface/test/nc_SUITE_data/Makefile.src7
-rw-r--r--lib/jinterface/vsn.mk2
-rw-r--r--lib/kernel/Makefile1
-rw-r--r--lib/kernel/doc/src/code.xml6
-rw-r--r--lib/kernel/doc/src/config.xml2
-rw-r--r--lib/kernel/doc/src/erl_ddll.xml6
-rw-r--r--lib/kernel/doc/src/erpc.xml705
-rw-r--r--lib/kernel/doc/src/file.xml8
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml95
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml11
-rw-r--r--lib/kernel/doc/src/gen_udp.xml28
-rw-r--r--lib/kernel/doc/src/global.xml133
-rw-r--r--lib/kernel/doc/src/heart.xml2
-rw-r--r--lib/kernel/doc/src/inet.xml172
-rw-r--r--lib/kernel/doc/src/inet_res.xml35
-rw-r--r--lib/kernel/doc/src/kernel_app.xml128
-rw-r--r--lib/kernel/doc/src/logger.xml2
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml4
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml6
-rw-r--r--lib/kernel/doc/src/logger_std_h.xml4
-rw-r--r--lib/kernel/doc/src/net.xml28
-rw-r--r--lib/kernel/doc/src/net_kernel.xml334
-rw-r--r--lib/kernel/doc/src/notes.xml973
-rw-r--r--lib/kernel/doc/src/os.xml2
-rw-r--r--lib/kernel/doc/src/pg.xml53
-rw-r--r--lib/kernel/doc/src/rpc.xml6
-rw-r--r--lib/kernel/doc/src/seq_trace.xml4
-rw-r--r--lib/kernel/doc/src/socket.xml38
-rw-r--r--lib/kernel/doc/src/socket_usage.xml6
-rw-r--r--lib/kernel/examples/Makefile2
-rw-r--r--lib/kernel/examples/erl_uds_dist/src/erl_uds_dist.erl13
-rw-r--r--lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl28
-rw-r--r--lib/kernel/examples/uds_dist/c_src/uds_drv.c2
-rw-r--r--lib/kernel/examples/uds_dist/src/uds_server.erl2
-rw-r--r--lib/kernel/include/dist.hrl115
-rw-r--r--lib/kernel/include/inet_sctp.hrl4
-rw-r--r--lib/kernel/src/Makefile4
-rw-r--r--lib/kernel/src/application_controller.erl6
-rw-r--r--lib/kernel/src/auth.erl94
-rw-r--r--lib/kernel/src/code.erl38
-rw-r--r--lib/kernel/src/code_server.erl8
-rw-r--r--lib/kernel/src/disk_log.erl4
-rw-r--r--lib/kernel/src/disk_log.hrl2
-rw-r--r--lib/kernel/src/dist_ac.erl8
-rw-r--r--lib/kernel/src/dist_util.erl279
-rw-r--r--lib/kernel/src/erl_boot_server.erl6
-rw-r--r--lib/kernel/src/erl_erts_errors.erl148
-rw-r--r--lib/kernel/src/erl_kernel_errors.erl18
-rw-r--r--lib/kernel/src/erpc.erl351
-rw-r--r--lib/kernel/src/erts_debug.erl4
-rw-r--r--lib/kernel/src/file.erl4
-rw-r--r--lib/kernel/src/file_io_server.erl8
-rw-r--r--lib/kernel/src/gen_sctp.erl246
-rw-r--r--lib/kernel/src/gen_tcp.erl10
-rw-r--r--lib/kernel/src/gen_tcp_socket.erl32
-rw-r--r--lib/kernel/src/gen_udp.erl32
-rw-r--r--lib/kernel/src/gen_udp_socket.erl27
-rw-r--r--lib/kernel/src/global.erl953
-rw-r--r--lib/kernel/src/global_group.erl1410
-rw-r--r--lib/kernel/src/heart.erl2
-rw-r--r--lib/kernel/src/inet.erl74
-rw-r--r--lib/kernel/src/inet6_sctp.erl10
-rw-r--r--lib/kernel/src/inet_config.erl4
-rw-r--r--lib/kernel/src/inet_db.erl451
-rw-r--r--lib/kernel/src/inet_dns.hrl12
-rw-r--r--lib/kernel/src/inet_gethost_native.erl135
-rw-r--r--lib/kernel/src/inet_int.hrl25
-rw-r--r--lib/kernel/src/inet_res.erl330
-rw-r--r--lib/kernel/src/inet_res.hrl4
-rw-r--r--lib/kernel/src/inet_sctp.erl18
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl78
-rw-r--r--lib/kernel/src/kernel.app.src6
-rw-r--r--lib/kernel/src/kernel.appup.src44
-rw-r--r--lib/kernel/src/kernel.erl13
-rw-r--r--lib/kernel/src/logger.erl14
-rw-r--r--lib/kernel/src/logger_disk_log_h.erl115
-rw-r--r--lib/kernel/src/logger_h_common.erl62
-rw-r--r--lib/kernel/src/logger_internal.hrl4
-rw-r--r--lib/kernel/src/logger_olp.erl8
-rw-r--r--lib/kernel/src/logger_server.erl4
-rw-r--r--lib/kernel/src/logger_std_h.erl47
-rw-r--r--lib/kernel/src/net.erl692
-rw-r--r--lib/kernel/src/net_kernel.erl459
-rw-r--r--lib/kernel/src/os.erl75
-rw-r--r--lib/kernel/src/pg.erl399
-rw-r--r--lib/kernel/src/ram_file.erl4
-rw-r--r--lib/kernel/src/raw_file_io.erl3
-rw-r--r--lib/kernel/src/raw_file_io_inflate.erl15
-rw-r--r--lib/kernel/src/rpc.erl477
-rw-r--r--lib/kernel/src/socket.erl48
-rw-r--r--lib/kernel/test/Makefile23
-rw-r--r--lib/kernel/test/application_SUITE.erl31
-rw-r--r--lib/kernel/test/bif_SUITE.erl67
-rw-r--r--lib/kernel/test/code_SUITE.erl105
-rw-r--r--lib/kernel/test/code_SUITE_data/upgrade_client.erl406
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl12
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl430
-rw-r--r--lib/kernel/test/erl_distribution_wb_SUITE.erl318
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl132
-rw-r--r--lib/kernel/test/erpc_SUITE.erl1337
-rw-r--r--lib/kernel/test/erpc_SUITE_data/Makefile.src39
-rw-r--r--lib/kernel/test/erpc_SUITE_data/fwd_node.c221
-rw-r--r--lib/kernel/test/error_info_lib.erl115
-rw-r--r--lib/kernel/test/error_logger_SUITE.erl8
-rw-r--r--lib/kernel/test/file_SUITE.erl159
-rw-r--r--lib/kernel/test/file_SUITE_data/realmen.html6
-rw-r--r--lib/kernel/test/file_name_SUITE.erl31
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl117
-rw-r--r--lib/kernel/test/gen_tcp_api_SUITE.erl82
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl1345
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl268
-rw-r--r--lib/kernel/test/global_SUITE.erl457
-rw-r--r--lib/kernel/test/global_SUITE_data/global_trace.erl82
-rw-r--r--lib/kernel/test/global_group_SUITE.erl877
-rw-r--r--lib/kernel/test/heart_SUITE.erl574
-rw-r--r--lib/kernel/test/ignore_cores.erl4
-rw-r--r--lib/kernel/test/inet_SUITE.erl112
-rw-r--r--lib/kernel/test/inet_res_SUITE.erl409
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone2
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/0.0.127.in-addr.arpa.zone1
-rw-r--r--lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone3
-rwxr-xr-xlib/kernel/test/inet_res_SUITE_data/run-ns17
-rw-r--r--lib/kernel/test/init_SUITE.erl228
-rw-r--r--lib/kernel/test/interactive_shell_SUITE.erl1364
-rw-r--r--lib/kernel/test/kernel.spec3
-rw-r--r--lib/kernel/test/kernel_SUITE.erl110
-rw-r--r--lib/kernel/test/kernel_smoke.spec3
-rw-r--r--lib/kernel/test/kernel_test_global_sys_monitor.erl12
-rw-r--r--lib/kernel/test/kernel_test_lib.erl1210
-rw-r--r--lib/kernel/test/kernel_test_lib.hrl5
-rw-r--r--lib/kernel/test/logger_SUITE.erl148
-rw-r--r--lib/kernel/test/logger_disk_log_h_SUITE.erl29
-rw-r--r--lib/kernel/test/logger_env_var_SUITE.erl126
-rw-r--r--lib/kernel/test/logger_proxy_SUITE.erl17
-rw-r--r--lib/kernel/test/logger_simple_h_SUITE.erl17
-rw-r--r--lib/kernel/test/logger_std_h_SUITE.erl94
-rw-r--r--lib/kernel/test/logger_test_lib.erl56
-rw-r--r--lib/kernel/test/loose_node.erl202
-rw-r--r--lib/kernel/test/net_SUITE.erl597
-rw-r--r--lib/kernel/test/os_SUITE.erl50
-rw-r--r--lib/kernel/test/os_SUITE_data/my_fds.c7
-rw-r--r--lib/kernel/test/pg_SUITE.erl777
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl8
-rw-r--r--lib/kernel/test/prim_file_SUITE_data/realmen.html10
-rw-r--r--lib/kernel/test/ram_file_SUITE_data/realmen.html10
-rw-r--r--lib/kernel/test/rpc_SUITE.erl390
-rw-r--r--lib/kernel/test/sendfile_SUITE.erl11
-rw-r--r--lib/kernel/test/seq_trace_SUITE.erl123
-rw-r--r--lib/kernel/test/socket_SUITE.erl5336
-rw-r--r--lib/kernel/test/socket_test_evaluator.erl6
-rw-r--r--lib/kernel/test/socket_test_lib.erl9
-rw-r--r--lib/kernel/test/socket_test_ttest_tcp_client.erl20
-rw-r--r--lib/kernel/test/socket_test_ttest_tcp_server.erl64
-rw-r--r--lib/kernel/test/socket_test_ttest_tcp_socket.erl13
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/Makefile13
-rwxr-xr-xlib/megaco/configure4081
-rw-r--r--lib/megaco/configure.ac (renamed from lib/megaco/configure.in)32
-rw-r--r--lib/megaco/doc/src/notes.xml106
-rw-r--r--lib/megaco/examples/meas/Makefile.in47
-rw-r--r--lib/megaco/examples/meas/megaco_codec_meas.erl167
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone1.erl7
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone2.erl36
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone_lib.erl16
-rw-r--r--lib/megaco/examples/simple/Makefile52
-rw-r--r--lib/megaco/examples/simple/megaco_simple_mg.erl9
-rw-r--r--lib/megaco/examples/simple/megaco_simple_mgc.erl8
-rw-r--r--lib/megaco/src/app/Makefile6
-rw-r--r--lib/megaco/src/app/megaco.erl8
-rw-r--r--lib/megaco/src/app/megaco.mk8
-rw-r--r--lib/megaco/src/binary/Makefile6
-rw-r--r--lib/megaco/src/binary/depend.mk6
-rw-r--r--lib/megaco/src/engine/Makefile6
-rw-r--r--lib/megaco/src/engine/megaco_config.erl28
-rw-r--r--lib/megaco/src/engine/megaco_digit_map.erl4
-rw-r--r--lib/megaco/src/engine/megaco_filter.erl6
-rw-r--r--lib/megaco/src/engine/megaco_messenger.erl137
-rw-r--r--lib/megaco/src/engine/megaco_messenger_misc.erl4
-rw-r--r--lib/megaco/src/engine/megaco_monitor.erl6
-rw-r--r--lib/megaco/src/engine/megaco_stats.erl4
-rw-r--r--lib/megaco/src/engine/megaco_trans_sender.erl38
-rw-r--r--lib/megaco/src/flex/Makefile.in6
-rw-r--r--lib/megaco/src/flex/megaco_flex_scanner.erl16
-rw-r--r--lib/megaco/src/tcp/Makefile6
-rw-r--r--lib/megaco/src/tcp/megaco_tcp.erl24
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_connection.erl24
-rw-r--r--lib/megaco/src/text/Makefile6
-rw-r--r--lib/megaco/src/udp/Makefile6
-rw-r--r--lib/megaco/src/udp/megaco_udp.erl18
-rw-r--r--lib/megaco/src/udp/megaco_udp_server.erl14
-rw-r--r--lib/megaco/test/Makefile6
-rw-r--r--lib/megaco/test/megaco_actions_SUITE.erl119
-rw-r--r--lib/megaco/test/megaco_codec_v1_SUITE.erl19
-rw-r--r--lib/megaco/test/megaco_examples_SUITE.erl203
-rw-r--r--lib/megaco/test/megaco_load_SUITE.erl7
-rw-r--r--lib/megaco/test/megaco_mess_SUITE.erl58
-rw-r--r--lib/megaco/test/megaco_mib_SUITE.erl24
-rw-r--r--lib/megaco/test/megaco_pending_limit_SUITE.erl667
-rw-r--r--lib/megaco/test/megaco_tcp_SUITE.erl41
-rw-r--r--lib/megaco/test/megaco_test_lib.erl1128
-rw-r--r--lib/megaco/test/megaco_test_lib.hrl11
-rw-r--r--lib/megaco/test/megaco_timer_SUITE.erl82
-rw-r--r--lib/megaco/test/megaco_trans_SUITE.erl88
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap3.xmlsrc2
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap4.xmlsrc4
-rw-r--r--lib/mnesia/doc/src/Mnesia_chap7.xmlsrc4
-rw-r--r--lib/mnesia/doc/src/mnesia.xml26
-rw-r--r--lib/mnesia/doc/src/notes.xml158
-rw-r--r--lib/mnesia/examples/Makefile4
-rw-r--r--lib/mnesia/examples/bench/README6
-rw-r--r--lib/mnesia/examples/mnesia_tpcb.erl4
-rw-r--r--lib/mnesia/include/Makefile4
-rw-r--r--lib/mnesia/src/Makefile6
-rw-r--r--lib/mnesia/src/mnesia.erl2
-rw-r--r--lib/mnesia/src/mnesia_backup.erl4
-rw-r--r--lib/mnesia/src/mnesia_bup.erl4
-rw-r--r--lib/mnesia/src/mnesia_checkpoint.erl4
-rw-r--r--lib/mnesia/src/mnesia_controller.erl10
-rw-r--r--lib/mnesia/src/mnesia_dumper.erl14
-rw-r--r--lib/mnesia/src/mnesia_frag.erl4
-rw-r--r--lib/mnesia/src/mnesia_index.erl4
-rw-r--r--lib/mnesia/src/mnesia_lib.erl12
-rw-r--r--lib/mnesia/src/mnesia_loader.erl60
-rw-r--r--lib/mnesia/src/mnesia_locker.erl20
-rw-r--r--lib/mnesia/src/mnesia_log.erl6
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl4
-rw-r--r--lib/mnesia/src/mnesia_recover.erl14
-rw-r--r--lib/mnesia/src/mnesia_schema.erl48
-rw-r--r--lib/mnesia/src/mnesia_snmp_hook.erl10
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl6
-rw-r--r--lib/mnesia/src/mnesia_tm.erl106
-rw-r--r--lib/mnesia/test/Makefile5
-rw-r--r--lib/mnesia/test/mnesia_SUITE.erl8
-rw-r--r--lib/mnesia/test/mnesia_atomicity_test.erl24
-rw-r--r--lib/mnesia/test/mnesia_config_backup.erl4
-rw-r--r--lib/mnesia/test/mnesia_config_test.erl6
-rw-r--r--lib/mnesia/test/mnesia_consistency_test.erl33
-rw-r--r--lib/mnesia/test/mnesia_dbn_meters.erl10
-rw-r--r--lib/mnesia/test/mnesia_dirty_access_test.erl33
-rw-r--r--lib/mnesia/test/mnesia_durability_test.erl18
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl61
-rw-r--r--lib/mnesia/test/mnesia_examples_test.erl5
-rw-r--r--lib/mnesia/test/mnesia_frag_test.erl6
-rw-r--r--lib/mnesia/test/mnesia_isolation_test.erl25
-rw-r--r--lib/mnesia/test/mnesia_recovery_test.erl16
-rw-r--r--lib/mnesia/test/mnesia_test_lib.erl49
-rw-r--r--lib/mnesia/test/mnesia_tpcb.erl4
-rw-r--r--lib/mnesia/test/mnesia_trans_access_test.erl4
-rw-r--r--lib/mnesia/test/mt.erl26
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/notes.xml85
-rw-r--r--lib/observer/doc/src/observer_ug.xml6
-rw-r--r--lib/observer/doc/src/ttb_ug.xml2
-rw-r--r--lib/observer/src/Makefile4
-rw-r--r--lib/observer/src/cdv_proc_cb.erl2
-rw-r--r--lib/observer/src/crashdump_viewer.erl4
-rw-r--r--lib/observer/src/crashdump_viewer.hrl4
-rw-r--r--lib/observer/src/etop.erl4
-rw-r--r--lib/observer/src/observer.app.src6
-rw-r--r--lib/observer/src/observer_lib.erl14
-rw-r--r--lib/observer/src/observer_port_wx.erl21
-rw-r--r--lib/observer/src/observer_procinfo.erl2
-rw-r--r--lib/observer/src/observer_sock_wx.erl13
-rw-r--r--lib/observer/src/observer_sys_wx.erl10
-rw-r--r--lib/observer/src/observer_trace_wx.erl6
-rw-r--r--lib/observer/src/observer_wx.erl69
-rw-r--r--lib/observer/src/ttb.erl4
-rw-r--r--lib/observer/src/ttb_et.erl4
-rw-r--r--lib/observer/test/Makefile3
-rw-r--r--lib/observer/test/crashdump_helper.erl2
-rw-r--r--lib/observer/test/crashdump_viewer_SUITE.erl2
-rw-r--r--lib/observer/test/etop_SUITE.erl64
-rw-r--r--lib/observer/test/observer_SUITE.erl55
-rw-r--r--lib/observer/test/ttb_SUITE.erl1096
-rw-r--r--lib/observer/vsn.mk2
-rwxr-xr-xlib/odbc/configure4130
-rw-r--r--lib/odbc/configure.ac (renamed from lib/odbc/configure.in)106
-rw-r--r--lib/odbc/doc/src/notes.xml18
-rw-r--r--lib/odbc/src/Makefile4
-rw-r--r--lib/odbc/test/Makefile6
-rw-r--r--lib/odbc/test/mysql.erl4
-rw-r--r--lib/odbc/test/postgres.erl4
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/os_mon/c_src/memsup.c8
-rw-r--r--lib/os_mon/c_src/memsup.h4
-rw-r--r--lib/os_mon/c_src/nteventlog/elog_format.h4
-rw-r--r--lib/os_mon/c_src/nteventlog/elog_main.c2
-rw-r--r--lib/os_mon/c_src/nteventlog/elog_pipe_stdin.c4
-rw-r--r--lib/os_mon/c_src/nteventlog/elog_pipe_stdin.h8
-rw-r--r--lib/os_mon/c_src/win32sysinfo.c4
-rw-r--r--lib/os_mon/doc/src/disksup.xml41
-rw-r--r--lib/os_mon/doc/src/notes.xml37
-rw-r--r--lib/os_mon/include/memsup.hrl3
-rw-r--r--lib/os_mon/src/Makefile4
-rw-r--r--lib/os_mon/src/cpu_sup.erl13
-rw-r--r--lib/os_mon/src/disksup.erl40
-rw-r--r--lib/os_mon/src/memsup.erl34
-rw-r--r--lib/os_mon/src/os_mon.app.src2
-rw-r--r--lib/os_mon/test/Makefile5
-rw-r--r--lib/os_mon/test/cpu_sup_SUITE.erl5
-rw-r--r--lib/os_mon/test/disksup_SUITE.erl49
-rw-r--r--lib/os_mon/test/memsup_SUITE.erl31
-rw-r--r--lib/os_mon/test/os_mon_SUITE.erl4
-rw-r--r--lib/os_mon/test/os_sup_SUITE.erl6
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/leex.xml11
-rw-r--r--lib/parsetools/doc/src/notes.xml39
-rw-r--r--lib/parsetools/doc/src/yecc.xml9
-rw-r--r--lib/parsetools/include/leexinc.hrl2
-rw-r--r--lib/parsetools/src/Makefile4
-rw-r--r--lib/parsetools/src/leex.erl64
-rw-r--r--lib/parsetools/src/parsetools.app.src2
-rw-r--r--lib/parsetools/src/yecc.erl63
-rw-r--r--lib/parsetools/test/Makefile5
-rw-r--r--lib/parsetools/test/leex_SUITE.erl70
-rw-r--r--lib/parsetools/test/yecc_SUITE.erl73
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/public_key/.gitignore8
-rw-r--r--lib/public_key/Makefile4
-rw-r--r--lib/public_key/asn1/ECPrivateKey.asn12
-rw-r--r--lib/public_key/asn1/Makefile39
-rw-r--r--lib/public_key/c_src/Makefile127
-rw-r--r--lib/public_key/c_src/public_key.c107
-rw-r--r--lib/public_key/doc/src/notes.xml184
-rw-r--r--lib/public_key/doc/src/public_key.xml151
-rw-r--r--lib/public_key/doc/src/using_public_key.xml117
-rw-r--r--lib/public_key/src/Makefile7
-rw-r--r--lib/public_key/src/pubkey_cert.erl100
-rw-r--r--lib/public_key/src/pubkey_cert_records.erl23
-rw-r--r--lib/public_key/src/pubkey_crl.erl4
-rw-r--r--lib/public_key/src/pubkey_os_cacerts.erl215
-rw-r--r--lib/public_key/src/pubkey_pbe.erl6
-rw-r--r--lib/public_key/src/pubkey_pem.erl4
-rw-r--r--lib/public_key/src/pubkey_ssh.erl595
-rw-r--r--lib/public_key/src/public_key.app.src3
-rw-r--r--lib/public_key/src/public_key.erl209
-rw-r--r--lib/public_key/test/Makefile7
-rw-r--r--lib/public_key/test/erl_make_certs.erl4
-rw-r--r--lib/public_key/test/pbe_SUITE.erl18
-rw-r--r--lib/public_key/test/pkits_SUITE.erl63
-rw-r--r--lib/public_key/test/pubkey_cert_SUITE.erl178
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE.erl457
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/auth_keys7
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/known_hosts8
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_pub1
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_with_comment_pub3
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/openssh_ecdsa_pub1
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/openssh_rsa_pub1
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_auth_keys9
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_known_hosts3
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_comment_pub13
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_pub12
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_ecdsa_pub6
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_comment_pub7
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_pub13
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_subject_pub8
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_comment_pub9
-rw-r--r--lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_header_pub9
-rw-r--r--lib/public_key/test/public_key_SUITE.erl281
-rw-r--r--lib/public_key/test/public_key_SUITE_data/ldap_uri_cert.pem35
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/Makefile1
-rw-r--r--lib/reltool/doc/src/notes.xml22
-rw-r--r--lib/reltool/doc/src/reltool.xml6
-rw-r--r--lib/reltool/doc/src/reltool_examples.xml13
-rw-r--r--lib/reltool/doc/src/reltool_usage.xml4
-rw-r--r--lib/reltool/examples/Makefile4
-rw-r--r--lib/reltool/src/Makefile6
-rw-r--r--lib/reltool/src/reltool_app_win.erl3
-rw-r--r--lib/reltool/src/reltool_server.erl2
-rw-r--r--lib/reltool/src/reltool_target.erl2
-rw-r--r--lib/reltool/test/Makefile5
-rw-r--r--lib/reltool/test/reltool_server_SUITE.erl2
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/Makefile3
-rw-r--r--lib/runtime_tools/c_src/trace_file_drv.c4
-rw-r--r--lib/runtime_tools/c_src/trace_ip_drv.c10
-rw-r--r--lib/runtime_tools/doc/src/LTTng.xml2
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml18
-rw-r--r--lib/runtime_tools/doc/src/dyntrace.xml2
-rw-r--r--lib/runtime_tools/doc/src/erts_alloc_config.xml12
-rw-r--r--lib/runtime_tools/doc/src/notes.xml37
-rw-r--r--lib/runtime_tools/doc/src/system_information.xml2
-rw-r--r--lib/runtime_tools/src/Makefile4
-rw-r--r--lib/runtime_tools/src/appmon_info.erl10
-rw-r--r--lib/runtime_tools/src/dbg.erl18
-rw-r--r--lib/runtime_tools/src/dyntrace.erl12
-rw-r--r--lib/runtime_tools/src/erts_alloc_config.erl9
-rw-r--r--lib/runtime_tools/src/observer_backend.erl59
-rw-r--r--lib/runtime_tools/src/system_information.erl3
-rw-r--r--lib/runtime_tools/test/Makefile4
-rw-r--r--lib/runtime_tools/test/dbg_SUITE.erl53
-rw-r--r--lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl6
-rw-r--r--lib/runtime_tools/test/erts_alloc_config_SUITE.erl33
-rw-r--r--lib/runtime_tools/test/system_information_SUITE.erl13
-rw-r--r--lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat1
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/Makefile1
-rw-r--r--lib/sasl/doc/src/notes.xml34
-rw-r--r--lib/sasl/doc/src/release_handler.xml22
-rw-r--r--lib/sasl/examples/src/Makefile4
-rw-r--r--lib/sasl/examples/src/target_system.erl28
-rw-r--r--lib/sasl/src/Makefile4
-rw-r--r--lib/sasl/src/release_handler.erl163
-rw-r--r--lib/sasl/src/release_handler_1.erl20
-rw-r--r--lib/sasl/src/sasl.app.src4
-rw-r--r--lib/sasl/src/sasl.appup.src20
-rw-r--r--lib/sasl/src/systools.erl8
-rw-r--r--lib/sasl/src/systools_make.erl47
-rw-r--r--lib/sasl/test/Makefile13
-rw-r--r--lib/sasl/test/installer.erl14
-rw-r--r--lib/sasl/test/otp_vsns.erl160
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl493
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app2
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-A.rel.src8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-B.rel.src8
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/Emakefile2
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/.gitignore1
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/hello_server.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/app_callback_module.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/hello_server.erl20
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/Emakefile2
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/.gitignore1
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.app7
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.appup3
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/app_callback_module.erl26
-rw-r--r--lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/hello_server.erl20
-rw-r--r--lib/sasl/test/rh_test_lib.erl24
-rw-r--r--lib/sasl/test/sasl_SUITE.erl109
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl10
-rw-r--r--lib/sasl/test/systools_SUITE.erl22
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app2
-rw-r--r--lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl3
-rw-r--r--lib/sasl/test/test_lib.hrl3
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/.gitignore4
-rw-r--r--lib/snmp/bin/snmp-v2tov1.pl2
-rwxr-xr-xlib/snmp/configure1093
-rw-r--r--lib/snmp/configure.ac71
-rw-r--r--lib/snmp/configure.in28
-rw-r--r--lib/snmp/doc/src/files.mk3
-rw-r--r--lib/snmp/doc/src/notes.xml183
-rw-r--r--lib/snmp/doc/src/notes_history.xml12
-rw-r--r--lib/snmp/doc/src/part.xml3
-rw-r--r--lib/snmp/doc/src/snmp.xml2
-rw-r--r--lib/snmp/doc/src/snmp_app.xml44
-rw-r--r--lib/snmp/doc/src/snmp_app_c.xml53
-rw-r--r--lib/snmp/doc/src/snmp_config.xml40
-rw-r--r--lib/snmp/doc/src/snmp_def_instr_functions.xml8
-rw-r--r--lib/snmp/doc/src/snmp_index.xml4
-rw-r--r--lib/snmp/doc/src/snmp_manager_netif.xml6
-rw-r--r--lib/snmp/doc/src/snmpa.xml12
-rw-r--r--lib/snmp/doc/src/snmpa_mib_data.xml4
-rw-r--r--lib/snmp/doc/src/snmpa_mpd.xml4
-rw-r--r--lib/snmp/doc/src/snmpm.xml345
-rw-r--r--lib/snmp/doc/src/structure.fig2
-rw-r--r--lib/snmp/examples/ex1/Makefile4
-rw-r--r--lib/snmp/examples/ex2/Makefile40
-rw-r--r--lib/snmp/examples/ex2/snmp_ex2_manager.erl15
-rw-r--r--lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl46
-rw-r--r--lib/snmp/mibs/Makefile.in4
-rw-r--r--lib/snmp/priv/conf/agent/Makefile4
-rw-r--r--lib/snmp/priv/conf/manager/Makefile4
-rw-r--r--lib/snmp/src/agent/Makefile.in (renamed from lib/snmp/src/agent/Makefile)16
-rw-r--r--lib/snmp/src/agent/modules.mk6
-rw-r--r--lib/snmp/src/agent/snmp_framework_mib.erl4
-rw-r--r--lib/snmp/src/agent/snmp_generic.erl6
-rw-r--r--lib/snmp/src/agent/snmp_generic_mnesia.erl8
-rw-r--r--lib/snmp/src/agent/snmp_index.erl4
-rw-r--r--lib/snmp/src/agent/snmp_shadow_table.erl6
-rw-r--r--lib/snmp/src/agent/snmp_target_mib.erl6
-rw-r--r--lib/snmp/src/agent/snmp_user_based_sm_mib.erl6
-rw-r--r--lib/snmp/src/agent/snmp_view_based_acm_mib.erl8
-rw-r--r--lib/snmp/src/agent/snmpa.erl15
-rw-r--r--lib/snmp/src/agent/snmpa_acm.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl353
-rw-r--r--lib/snmp/src/agent/snmpa_agent_sup.erl12
-rw-r--r--lib/snmp/src/agent/snmpa_general_db.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_get.erl91
-rw-r--r--lib/snmp/src/agent/snmpa_local_db.erl8
-rw-r--r--lib/snmp/src/agent/snmpa_mib.erl24
-rw-r--r--lib/snmp/src/agent/snmpa_mib_data_ttln.erl22
-rw-r--r--lib/snmp/src/agent/snmpa_mib_data_tttn.erl22
-rw-r--r--lib/snmp/src/agent/snmpa_mib_lib.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_mib_storage.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_mpd.erl70
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl75
-rw-r--r--lib/snmp/src/agent/snmpa_network_interface_filter.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_set_lib.erl6
-rw-r--r--lib/snmp/src/agent/snmpa_supervisor.erl45
-rw-r--r--lib/snmp/src/agent/snmpa_svbl.erl6
-rw-r--r--lib/snmp/src/agent/snmpa_target_cache.erl8
-rw-r--r--lib/snmp/src/agent/snmpa_trap.erl30
-rw-r--r--lib/snmp/src/agent/snmpa_usm.erl4
-rw-r--r--lib/snmp/src/agent/snmpa_vacm.erl29
-rw-r--r--lib/snmp/src/app/Makefile6
-rw-r--r--lib/snmp/src/app/snmp.app.src2
-rw-r--r--lib/snmp/src/app/snmp.config8
-rw-r--r--lib/snmp/src/app/snmp.erl4
-rw-r--r--lib/snmp/src/app/snmp_app.erl11
-rw-r--r--lib/snmp/src/app/snmp_app_sup.erl16
-rw-r--r--lib/snmp/src/compile/Makefile10
-rw-r--r--lib/snmp/src/compile/snmpc.erl4
-rw-r--r--lib/snmp/src/compile/snmpc.src4
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl4
-rw-r--r--lib/snmp/src/compile/snmpc_mib_gram.yrl6
-rw-r--r--lib/snmp/src/compile/snmpc_mib_to_hrl.erl2
-rw-r--r--lib/snmp/src/compile/snmpc_tok.erl4
-rw-r--r--lib/snmp/src/manager/Makefile6
-rw-r--r--lib/snmp/src/manager/snmpm.erl263
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl90
-rw-r--r--lib/snmp/src/manager/snmpm_mpd.erl28
-rw-r--r--lib/snmp/src/manager/snmpm_net_if.erl18
-rw-r--r--lib/snmp/src/manager/snmpm_network_interface_filter.erl4
-rw-r--r--lib/snmp/src/manager/snmpm_server.erl264
-rw-r--r--lib/snmp/src/manager/snmpm_usm.erl4
-rw-r--r--lib/snmp/src/misc/Makefile6
-rw-r--r--lib/snmp/src/misc/snmp_conf.erl8
-rw-r--r--lib/snmp/src/misc/snmp_config.erl22
-rw-r--r--lib/snmp/src/misc/snmp_log.erl4
-rw-r--r--lib/snmp/src/misc/snmp_misc.erl2
-rw-r--r--lib/snmp/src/misc/snmp_note_store.erl10
-rw-r--r--lib/snmp/src/misc/snmp_pdus.erl6
-rw-r--r--lib/snmp/src/misc/snmp_usm.erl4
-rw-r--r--lib/snmp/test/Makefile5
-rw-r--r--lib/snmp/test/exp/.gitignore0
-rw-r--r--lib/snmp/test/exp/snmp_agent_bl_test.erl5634
-rw-r--r--lib/snmp/test/exp/snmp_agent_ms_test.erl5636
-rw-r--r--lib/snmp/test/exp/snmp_agent_mt_test.erl5636
-rw-r--r--lib/snmp/test/exp/snmp_agent_v1_test.erl2674
-rw-r--r--lib/snmp/test/exp/snmp_agent_v2_test.erl5636
-rw-r--r--lib/snmp/test/exp/snmp_agent_v3_test.erl5635
-rw-r--r--lib/snmp/test/klas3.erl4
-rw-r--r--lib/snmp/test/snmp_agent_SUITE.erl2200
-rw-r--r--lib/snmp/test/snmp_agent_mibs_SUITE.erl164
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl206
-rw-r--r--lib/snmp/test/snmp_compiler_SUITE.erl48
-rw-r--r--lib/snmp/test/snmp_conf_SUITE.erl336
-rw-r--r--lib/snmp/test/snmp_log_SUITE.erl100
-rw-r--r--lib/snmp/test/snmp_manager_SUITE.erl987
-rw-r--r--lib/snmp/test/snmp_manager_config_SUITE.erl654
-rw-r--r--lib/snmp/test/snmp_manager_user_SUITE.erl280
-rw-r--r--lib/snmp/test/snmp_note_store_SUITE.erl4
-rw-r--r--lib/snmp/test/snmp_test_data/RFC1213-MIB.mib6
-rw-r--r--lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib2
-rw-r--r--lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib4
-rw-r--r--lib/snmp/test/snmp_test_data/TestTrapv2.mib4
-rw-r--r--lib/snmp/test/snmp_test_global_sys_monitor.erl8
-rw-r--r--lib/snmp/test/snmp_test_lib.erl954
-rw-r--r--lib/snmp/test/snmp_test_lib.hrl11
-rw-r--r--lib/snmp/test/snmp_test_manager.erl2
-rw-r--r--lib/snmp/test/snmp_test_mgr.erl19
-rw-r--r--lib/snmp/test/snmp_test_mgr_counter_server.erl4
-rw-r--r--lib/snmp/test/snmp_test_mgr_misc.erl8
-rw-r--r--lib/snmp/test/snmp_test_server.erl4
-rw-r--r--lib/snmp/test/snmp_to_snmpnet_SUITE.erl2
-rw-r--r--lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib4
-rw-r--r--lib/snmp/test/test-mibs/RFC1213-MIB.mib6
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-MIB.mib4
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-TC.mib2
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-test.mib4
-rw-r--r--lib/snmp/test/test_config/Makefile4
-rw-r--r--lib/snmp/vsn.mk2
-rw-r--r--lib/ssh/doc/src/Makefile4
-rw-r--r--lib/ssh/doc/src/SSH_app.xml2
-rw-r--r--lib/ssh/doc/src/configurations.xml8
-rw-r--r--lib/ssh/doc/src/configure_algos.xml16
-rw-r--r--lib/ssh/doc/src/hardening.xml103
-rw-r--r--lib/ssh/doc/src/notes.xml280
-rw-r--r--lib/ssh/doc/src/ssh.xml213
-rw-r--r--lib/ssh/doc/src/ssh_agent.xml2
-rw-r--r--lib/ssh/doc/src/ssh_client_key_api.xml12
-rw-r--r--lib/ssh/doc/src/ssh_connection.xml4
-rw-r--r--lib/ssh/doc/src/ssh_file.xml26
-rw-r--r--lib/ssh/doc/src/ssh_sftp.xml4
-rw-r--r--lib/ssh/doc/src/ssh_timeouts.jpgbin0 -> 40281 bytes
-rw-r--r--lib/ssh/doc/src/ssh_timeouts.odpbin0 -> 13832 bytes
-rw-r--r--lib/ssh/doc/src/terminology.xml8
-rw-r--r--lib/ssh/doc/src/using_ssh.xml4
-rw-r--r--lib/ssh/examples/Makefile4
-rw-r--r--lib/ssh/src/Makefile2
-rw-r--r--lib/ssh/src/ssh.app.src4
-rw-r--r--lib/ssh/src/ssh.erl26
-rw-r--r--lib/ssh/src/ssh.hrl12
-rw-r--r--lib/ssh/src/ssh_agent.erl4
-rw-r--r--lib/ssh/src/ssh_auth.erl24
-rw-r--r--lib/ssh/src/ssh_auth.hrl4
-rw-r--r--lib/ssh/src/ssh_bits.erl12
-rw-r--r--lib/ssh/src/ssh_client_channel.erl20
-rw-r--r--lib/ssh/src/ssh_client_key_api.erl2
-rw-r--r--lib/ssh/src/ssh_connection.erl10
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl82
-rw-r--r--lib/ssh/src/ssh_daemon_channel.erl4
-rw-r--r--lib/ssh/src/ssh_dbg.erl26
-rw-r--r--lib/ssh/src/ssh_file.erl63
-rw-r--r--lib/ssh/src/ssh_fsm_userauth_client.erl6
-rw-r--r--lib/ssh/src/ssh_fsm_userauth_server.erl39
-rw-r--r--lib/ssh/src/ssh_info.erl2
-rw-r--r--lib/ssh/src/ssh_message.erl172
-rw-r--r--lib/ssh/src/ssh_options.erl59
-rw-r--r--lib/ssh/src/ssh_server_channel.erl2
-rw-r--r--lib/ssh/src/ssh_server_key_api.erl2
-rw-r--r--lib/ssh/src/ssh_sftp.erl54
-rw-r--r--lib/ssh/src/ssh_sftpd.erl2
-rw-r--r--lib/ssh/src/ssh_shell.erl4
-rw-r--r--lib/ssh/src/ssh_system_sup.erl36
-rw-r--r--lib/ssh/src/ssh_transport.erl122
-rw-r--r--lib/ssh/src/ssh_transport.hrl4
-rw-r--r--lib/ssh/src/ssh_xfer.erl18
-rw-r--r--lib/ssh/src/ssh_xfer.hrl4
-rw-r--r--lib/ssh/test/Makefile5
-rw-r--r--lib/ssh/test/property_test/ssh_eqc_client_server.erl4
-rw-r--r--lib/ssh/test/property_test/ssh_eqc_encode_decode.erl4
-rw-r--r--lib/ssh/test/ssh_agent_mock_server.erl4
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl87
-rw-r--r--lib/ssh/test/ssh_chan_behaviours_SUITE.erl4
-rw-r--r--lib/ssh/test/ssh_compat_SUITE.erl10
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl12
-rw-r--r--lib/ssh/test/ssh_options_SUITE.erl414
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl16
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE.erl22
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa28
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa.pub1
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key28
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key.pub1
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_comment_pub2
-rw-r--r--lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_header_pub2
-rw-r--r--lib/ssh/test/ssh_relay.erl2
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl8
-rw-r--r--lib/ssh/test/ssh_test_lib.erl6
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl2
-rw-r--r--lib/ssh/test/ssh_trpt_test_lib.erl16
-rw-r--r--lib/ssh/test/ssh_upgrade_SUITE.erl4
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml674
-rw-r--r--lib/ssl/doc/src/ssl.xml199
-rw-r--r--lib/ssl/doc/src/ssl_app.xml6
-rw-r--r--lib/ssl/doc/src/using_ssl.xml316
-rw-r--r--lib/ssl/examples/certs/Makefile4
-rw-r--r--lib/ssl/examples/src/Makefile4
-rw-r--r--lib/ssl/internal_doc/pem_and_cert_cache.md39
-rw-r--r--lib/ssl/src/Makefile2
-rw-r--r--lib/ssl/src/dtls_connection.erl112
-rw-r--r--lib/ssl/src/dtls_gen_connection.erl8
-rw-r--r--lib/ssl/src/dtls_packet_demux.erl148
-rw-r--r--lib/ssl/src/dtls_record.erl66
-rw-r--r--lib/ssl/src/inet_tls_dist.erl11
-rw-r--r--lib/ssl/src/ssl.app.src14
-rw-r--r--lib/ssl/src/ssl.erl163
-rw-r--r--lib/ssl/src/ssl_certificate.erl119
-rw-r--r--lib/ssl/src/ssl_cipher.erl16
-rw-r--r--lib/ssl/src/ssl_config.erl193
-rw-r--r--lib/ssl/src/ssl_connection.hrl21
-rw-r--r--lib/ssl/src/ssl_crl_cache.erl6
-rw-r--r--lib/ssl/src/ssl_gen_statem.erl84
-rw-r--r--lib/ssl/src/ssl_handshake.erl221
-rw-r--r--lib/ssl/src/ssl_handshake.hrl1
-rw-r--r--lib/ssl/src/ssl_internal.hrl54
-rw-r--r--lib/ssl/src/ssl_logger.erl6
-rw-r--r--lib/ssl/src/ssl_manager.erl18
-rw-r--r--lib/ssl/src/ssl_pem_cache.erl5
-rw-r--r--lib/ssl/src/ssl_pkix_db.erl76
-rw-r--r--lib/ssl/src/ssl_record.erl13
-rw-r--r--lib/ssl/src/ssl_session.erl106
-rw-r--r--lib/ssl/src/tls_client_ticket_store.erl14
-rw-r--r--lib/ssl/src/tls_connection.erl81
-rw-r--r--lib/ssl/src/tls_connection_1_3.erl301
-rw-r--r--lib/ssl/src/tls_dtls_connection.erl190
-rw-r--r--lib/ssl/src/tls_gen_connection.erl246
-rw-r--r--lib/ssl/src/tls_handshake.erl54
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl262
-rw-r--r--lib/ssl/src/tls_handshake_1_3.hrl6
-rw-r--r--lib/ssl/src/tls_record.erl8
-rw-r--r--lib/ssl/src/tls_record.hrl11
-rw-r--r--lib/ssl/src/tls_record_1_3.erl163
-rw-r--r--lib/ssl/src/tls_record_1_3.hrl4
-rw-r--r--lib/ssl/src/tls_sender.erl153
-rw-r--r--lib/ssl/src/tls_server_session_ticket.erl6
-rw-r--r--lib/ssl/src/tls_socket.erl4
-rw-r--r--lib/ssl/src/tls_v1.erl64
-rw-r--r--lib/ssl/test/Makefile10
-rw-r--r--lib/ssl/test/dtls_api_SUITE.erl144
-rw-r--r--lib/ssl/test/inet_crypto_dist.erl694
-rw-r--r--lib/ssl/test/openssl_ECC_SUITE.erl30
-rw-r--r--lib/ssl/test/openssl_alpn_SUITE.erl162
-rw-r--r--lib/ssl/test/openssl_cipher_suite_SUITE.erl385
-rw-r--r--lib/ssl/test/openssl_client_cert_SUITE.erl129
-rw-r--r--lib/ssl/test/openssl_key_update_SUITE.erl30
-rw-r--r--lib/ssl/test/openssl_mfl_SUITE.erl115
-rw-r--r--lib/ssl/test/openssl_npn_SUITE.erl31
-rw-r--r--lib/ssl/test/openssl_ocsp_SUITE.erl39
-rw-r--r--lib/ssl/test/openssl_reject_SUITE.erl75
-rw-r--r--lib/ssl/test/openssl_renegotiate_SUITE.erl26
-rw-r--r--lib/ssl/test/openssl_server_cert_SUITE.erl51
-rw-r--r--lib/ssl/test/openssl_session_SUITE.erl34
-rw-r--r--lib/ssl/test/openssl_session_ticket_SUITE.erl42
-rw-r--r--lib/ssl/test/openssl_sni_SUITE.erl39
-rw-r--r--lib/ssl/test/openssl_tls_1_3_version_SUITE.erl27
-rw-r--r--lib/ssl/test/property_test/ssl_eqc_handshake.erl13
-rw-r--r--lib/ssl/test/ssl.spec12
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl91
-rw-r--r--lib/ssl/test/ssl_alert_SUITE.erl15
-rw-r--r--lib/ssl/test/ssl_api_SUITE.erl510
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl452
-rw-r--r--lib/ssl/test/ssl_bench.spec5
-rw-r--r--lib/ssl/test/ssl_bench_SUITE.erl106
-rw-r--r--lib/ssl/test/ssl_bench_test_lib.erl59
-rw-r--r--lib/ssl/test/ssl_cert_SUITE.erl151
-rw-r--r--lib/ssl/test/ssl_cert_tests.erl145
-rw-r--r--lib/ssl/test/ssl_cipher_SUITE.erl12
-rw-r--r--lib/ssl/test/ssl_cipher_suite_SUITE.erl4
-rw-r--r--lib/ssl/test/ssl_crl_SUITE.erl48
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl169
-rw-r--r--lib/ssl/test/ssl_dist_bench_SUITE.erl422
-rw-r--r--lib/ssl/test/ssl_dist_test_lib.erl4
-rw-r--r--lib/ssl/test/ssl_eqc_SUITE.erl17
-rw-r--r--lib/ssl/test/ssl_gh.spec15
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl6
-rw-r--r--lib/ssl/test/ssl_key_update_SUITE.erl115
-rw-r--r--lib/ssl/test/ssl_mfl_SUITE.erl20
-rw-r--r--lib/ssl/test/ssl_npn_SUITE.erl10
-rw-r--r--lib/ssl/test/ssl_npn_hello_SUITE.erl10
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl903
-rw-r--r--lib/ssl/test/ssl_reject_SUITE.erl81
-rw-r--r--lib/ssl/test/ssl_session_cache_api_SUITE.erl21
-rw-r--r--lib/ssl/test/ssl_session_ticket_SUITE.erl275
-rw-r--r--lib/ssl/test/ssl_sni_SUITE.erl6
-rw-r--r--lib/ssl/test/ssl_test_lib.erl290
-rw-r--r--lib/ssl/test/tls_1_3_record_SUITE.erl6
-rw-r--r--lib/ssl/test/tls_1_3_version_SUITE.erl103
-rw-r--r--lib/ssl/test/tls_api_SUITE.erl163
-rw-r--r--lib/ssl/test/tls_client_ticket_store_SUITE.erl108
-rw-r--r--lib/ssl/test/tls_server_session_ticket_SUITE.erl59
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/Makefile11
-rw-r--r--lib/stdlib/doc/src/Makefile4
-rw-r--r--lib/stdlib/doc/src/array.xml2
-rw-r--r--lib/stdlib/doc/src/beam_lib.xml56
-rw-r--r--lib/stdlib/doc/src/c.xml31
-rw-r--r--lib/stdlib/doc/src/calendar.xml23
-rw-r--r--lib/stdlib/doc/src/epp.xml6
-rw-r--r--lib/stdlib/doc/src/erl_eval.xml13
-rw-r--r--lib/stdlib/doc/src/erl_features.xml114
-rw-r--r--lib/stdlib/doc/src/erl_pp.xml33
-rw-r--r--lib/stdlib/doc/src/erl_scan.xml19
-rw-r--r--lib/stdlib/doc/src/ets.xml276
-rw-r--r--lib/stdlib/doc/src/filelib.xml22
-rw-r--r--lib/stdlib/doc/src/filename.xml47
-rw-r--r--lib/stdlib/doc/src/gb_sets.xml22
-rw-r--r--lib/stdlib/doc/src/gen_event.xml699
-rw-r--r--lib/stdlib/doc/src/gen_server.xml2020
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml657
-rw-r--r--lib/stdlib/doc/src/lists.xml81
-rw-r--r--lib/stdlib/doc/src/maps.xml51
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml6
-rw-r--r--lib/stdlib/doc/src/notes.xml709
-rw-r--r--lib/stdlib/doc/src/ordsets.xml6
-rw-r--r--lib/stdlib/doc/src/peer.xml616
-rw-r--r--lib/stdlib/doc/src/queue.xml21
-rw-r--r--lib/stdlib/doc/src/rand.xml536
-rw-r--r--lib/stdlib/doc/src/ref_man.xml4
-rw-r--r--lib/stdlib/doc/src/sets.xml24
-rw-r--r--lib/stdlib/doc/src/shell.xml43
-rw-r--r--lib/stdlib/doc/src/sofs.xml39
-rw-r--r--lib/stdlib/doc/src/specs.xml2
-rw-r--r--lib/stdlib/doc/src/stdlib_app.xml16
-rw-r--r--lib/stdlib/doc/src/supervisor_bridge.xml4
-rw-r--r--lib/stdlib/doc/src/sys.xml34
-rw-r--r--lib/stdlib/doc/src/timer.xml33
-rw-r--r--lib/stdlib/doc/src/uri_string.xml79
-rw-r--r--lib/stdlib/doc/src/uri_string_usage.xml11
-rw-r--r--lib/stdlib/examples/Makefile2
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl11
-rwxr-xr-xlib/stdlib/scripts/generate_ryu_table.escript108
-rwxr-xr-xlib/stdlib/scripts/update_deprecations29
-rw-r--r--lib/stdlib/src/Makefile21
-rw-r--r--lib/stdlib/src/beam_lib.erl11
-rw-r--r--lib/stdlib/src/c.erl7
-rw-r--r--lib/stdlib/src/calendar.erl44
-rw-r--r--lib/stdlib/src/dets.erl8
-rw-r--r--lib/stdlib/src/digraph.erl8
-rw-r--r--lib/stdlib/src/epp.erl270
-rw-r--r--lib/stdlib/src/erl_anno.erl6
-rw-r--r--lib/stdlib/src/erl_compile.erl94
-rw-r--r--lib/stdlib/src/erl_error.erl6
-rw-r--r--lib/stdlib/src/erl_eval.erl1082
-rw-r--r--lib/stdlib/src/erl_expand_records.erl29
-rw-r--r--lib/stdlib/src/erl_features.erl570
-rw-r--r--lib/stdlib/src/erl_internal.erl3
-rw-r--r--lib/stdlib/src/erl_lint.erl291
-rw-r--r--lib/stdlib/src/erl_parse.yrl42
-rw-r--r--lib/stdlib/src/erl_posix_msg.erl4
-rw-r--r--lib/stdlib/src/erl_pp.erl84
-rw-r--r--lib/stdlib/src/erl_scan.erl174
-rw-r--r--lib/stdlib/src/erl_stdlib_errors.erl48
-rw-r--r--lib/stdlib/src/erl_tar.erl76
-rw-r--r--lib/stdlib/src/ets.erl531
-rw-r--r--lib/stdlib/src/eval_bits.erl150
-rw-r--r--lib/stdlib/src/filelib.erl59
-rw-r--r--lib/stdlib/src/filename.erl40
-rw-r--r--lib/stdlib/src/gb_sets.erl2
-rw-r--r--lib/stdlib/src/gen.erl318
-rw-r--r--lib/stdlib/src/gen_event.erl290
-rw-r--r--lib/stdlib/src/gen_server.erl738
-rw-r--r--lib/stdlib/src/gen_statem.erl820
-rw-r--r--lib/stdlib/src/io.erl3
-rw-r--r--lib/stdlib/src/io_lib_format.erl260
-rw-r--r--lib/stdlib/src/io_lib_format_ryu_table.erl686
-rw-r--r--lib/stdlib/src/lists.erl349
-rw-r--r--lib/stdlib/src/maps.erl68
-rw-r--r--lib/stdlib/src/ms_transform.erl28
-rw-r--r--lib/stdlib/src/otp_internal.erl136
-rw-r--r--lib/stdlib/src/peer.erl1185
-rw-r--r--lib/stdlib/src/pool.erl4
-rw-r--r--lib/stdlib/src/proc_lib.erl83
-rw-r--r--lib/stdlib/src/qlc.erl21
-rw-r--r--lib/stdlib/src/queue.erl12
-rw-r--r--lib/stdlib/src/rand.erl323
-rw-r--r--lib/stdlib/src/sets.erl16
-rw-r--r--lib/stdlib/src/shell.erl29
-rw-r--r--lib/stdlib/src/slave.erl4
-rw-r--r--lib/stdlib/src/stdlib.app.src7
-rw-r--r--lib/stdlib/src/stdlib.appup.src50
-rw-r--r--lib/stdlib/src/supervisor.erl45
-rw-r--r--lib/stdlib/src/sys.erl8
-rw-r--r--lib/stdlib/src/timer.erl722
-rw-r--r--lib/stdlib/src/unicode.erl19
-rw-r--r--lib/stdlib/src/uri_string.erl55
-rw-r--r--lib/stdlib/src/zip.erl20
-rw-r--r--lib/stdlib/test/Makefile20
-rw-r--r--lib/stdlib/test/base64_property_test_SUITE.erl86
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl69
-rw-r--r--lib/stdlib/test/c_SUITE.erl2
-rw-r--r--lib/stdlib/test/calendar_SUITE.erl73
-rw-r--r--lib/stdlib/test/dets_SUITE.erl24
-rw-r--r--lib/stdlib/test/dummy_h.erl9
-rw-r--r--lib/stdlib/test/epp_SUITE.erl132
-rw-r--r--lib/stdlib/test/epp_SUITE_data/deterministic_include.erl6
-rw-r--r--lib/stdlib/test/epp_SUITE_data/include/baz.hrl1
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl314
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl50
-rw-r--r--lib/stdlib/test/erl_internal_SUITE.erl14
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl260
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl98
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl80
-rw-r--r--lib/stdlib/test/error_info_lib.erl20
-rw-r--r--lib/stdlib/test/error_logger_h_SUITE.erl20
-rw-r--r--lib/stdlib/test/ets_SUITE.erl870
-rw-r--r--lib/stdlib/test/ets_SUITE_data/visualize_throughput.html18
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl121
-rw-r--r--lib/stdlib/test/filename_SUITE.erl71
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl388
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl12
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl627
-rw-r--r--lib/stdlib/test/gen_server_SUITE_data/format_status_server.erl55
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl600
-rw-r--r--lib/stdlib/test/gen_statem_SUITE_data/format_status_statem.erl40
-rw-r--r--lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl18
-rw-r--r--lib/stdlib/test/id_transform_SUITE.erl4
-rw-r--r--lib/stdlib/test/io_SUITE.erl66
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl51
-rw-r--r--lib/stdlib/test/lists_SUITE.erl48
-rw-r--r--lib/stdlib/test/maps_SUITE.erl25
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl99
-rw-r--r--lib/stdlib/test/peer_SUITE.erl655
-rw-r--r--lib/stdlib/test/pool_SUITE.erl19
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl43
-rw-r--r--lib/stdlib/test/property_test/base64_prop.erl429
-rw-r--r--lib/stdlib/test/property_test/queue_prop.erl898
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl54
-rw-r--r--lib/stdlib/test/queue_property_test_SUITE.erl327
-rw-r--r--lib/stdlib/test/rand_SUITE.erl1176
-rw-r--r--lib/stdlib/test/random_iolist.erl4
-rw-r--r--lib/stdlib/test/re_SUITE.erl4
-rw-r--r--lib/stdlib/test/shell_SUITE.erl51
-rw-r--r--lib/stdlib/test/shell_docs_SUITE.erl23
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/erlang.docs_v12
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/file.docs_v12
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_altname_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_copy_opened_3_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_1_func.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_2_func.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_3_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_int_3_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_open_2_func.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_path_eval_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_read_file_info_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_write_file_info_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_2_func.txt8
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_5_func.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_cb.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_interfaces_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_0_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_type.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/re.docs_v12
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/shell_docs_SUITE.docs_v11
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/sofs.docs_v12
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_re.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_grun_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_internal_run_4_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_ucompile_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_urun_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_fam2rel_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_rel2fam_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang.txt13
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_!_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_++_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_--_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_0_func.txt35
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_1_func.txt35
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_info_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_sizes_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_and_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_any_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_append_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_arity_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_atom_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_band_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_atom_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_1_func.txt7
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_2_func.txt10
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bitstring_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bnot_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_boolean_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bor_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsl_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsr_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bxor_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_byte_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_call_on_load_function_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_char_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_delay_trap_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_nl_0_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_string_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_1_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_notification_1_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_opt_2_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_input_handler_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_put_data_2_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_set_opt_3_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_get_stat_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_handle_0_type.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_div_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dmonitor_node_3_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_append_vm_tag_data_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_0_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_data_0_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_prepend_vm_tag_data_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_put_tag_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_restore_tag_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_spread_tag_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqcoloneq_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqeq_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqlt_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqslasheq_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_1_func.txt17
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_2_func.txt26
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_3_func.txt37
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_1_func.txt18
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_signal_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_after_on_load_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_loading_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_binary_2_func.txt8
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_list_2_func.txt16
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_format_cpu_topology_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_info_mfa_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_to_list_1_func.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_exported_3_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_garbage_collect_message_area_0_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gather_gc_info_result_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_cookie_1_func.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_group_leader_2_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gt_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gteq_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_has_prepared_code_on_load_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_hibernate_3_func.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_identifier_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_integer_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iodata_0_type.txt11
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_0_type.txt10
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_to_iovec_1_func.txt25
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_is_process_alive_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_link_1_func.txt60
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_1_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_atom_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_existing_atom_1_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_load_module_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_lt_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_fun_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_ref_0_func.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_map_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_2_type.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_memory_0_func.txt7
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_message_queue_data_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_mfa_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_module_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_2_func.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_3_func.txt80
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_node_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_neg_integer_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nif_resource_0_type.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nil_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_no_return_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_node_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_non_neg_integer_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_none_0_type.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_binary_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_bitstring_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_improper_list_2_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_1_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_2_type.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_string_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_not_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_number_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_open_port_2_func.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_or_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pid_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_call_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_get_data_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_set_data_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pos_integer_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_posixtime_to_universaltime_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pre_loaded_0_func.txt8
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_prepare_loading_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_flag_2_func.txt8
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_info_2_func.txt16
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_raise_3_func.txt17
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_reference_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_register_2_func.txt13
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_rem_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_send_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_info_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_2_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_1_func.txt12
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_2_func.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cpu_topology_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_3_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slash_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slasheq_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_spawn_opt_4_func.txt11
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_0_type.txt10
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_extrainfo_0_type.txt10
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_star_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_statistics_1_func.txt20
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_string_0_type.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_subtract_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_suspend_process_2_func.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_system_info_1_func.txt8
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_binary_2_func.txt17
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_iovec_2_func.txt1
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_timeout_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_3_func.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_info_2_func.txt2
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_tuple_0_type.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_type.txt108
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unalias_1_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_universaltime_to_posixtime_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unlink_1_func.txt51
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unregister_1_func.txt9
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_whereis_1_func.txt6
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_xor_2_func.txt5
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE.txt4
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_cb.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_type.txt3
-rw-r--r--lib/stdlib/test/shell_docs_SUITE_data/user_drv.docs_v11
-rw-r--r--lib/stdlib/test/stdlib_SUITE.erl112
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE.erl46
-rw-r--r--lib/stdlib/test/string_SUITE.erl22
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl4
-rw-r--r--lib/stdlib/test/tar_SUITE.erl111
-rw-r--r--lib/stdlib/test/tar_SUITE_data/example_pad.tgzbin0 -> 10240 bytes
-rw-r--r--lib/stdlib/test/timer_SUITE.erl12
-rw-r--r--lib/stdlib/test/timer_simple_SUITE.erl793
-rw-r--r--lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt6
-rw-r--r--lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt60
-rw-r--r--lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt849
-rw-r--r--lib/stdlib/test/uri_string_SUITE.erl189
-rw-r--r--lib/stdlib/uc_spec/CaseFolding.txt46
-rw-r--r--lib/stdlib/uc_spec/CompositionExclusions.txt12
-rw-r--r--lib/stdlib/uc_spec/GraphemeBreakProperty.txt33
-rw-r--r--lib/stdlib/uc_spec/PropList.txt100
-rw-r--r--lib/stdlib/uc_spec/README-UPDATE.txt52
-rw-r--r--lib/stdlib/uc_spec/SpecialCasing.txt6
-rw-r--r--lib/stdlib/uc_spec/UnicodeData.txt837
-rw-r--r--lib/stdlib/uc_spec/emoji-data.txt96
-rw-r--r--lib/stdlib/uc_spec/gen_unicode_mod.escript22
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/Makefile2
-rw-r--r--lib/syntax_tools/doc/src/notes.xml62
-rw-r--r--lib/syntax_tools/examples/Makefile2
-rw-r--r--lib/syntax_tools/src/Makefile2
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl20
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl36
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl245
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl48
-rw-r--r--lib/syntax_tools/src/merl.erl2
-rw-r--r--lib/syntax_tools/src/prettypr.erl2
-rw-r--r--lib/syntax_tools/src/syntax_tools.app.src2
-rw-r--r--lib/syntax_tools/test/Makefile3
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl59
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl47
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/tftp/doc/src/notes.xml36
-rw-r--r--lib/tftp/src/Makefile4
-rw-r--r--lib/tftp/src/tftp.erl6
-rw-r--r--lib/tftp/src/tftp_binary.erl12
-rw-r--r--lib/tftp/src/tftp_engine.erl12
-rw-r--r--lib/tftp/src/tftp_file.erl22
-rw-r--r--lib/tftp/src/tftp_lib.erl6
-rw-r--r--lib/tftp/test/Makefile5
-rw-r--r--lib/tftp/vsn.mk2
-rw-r--r--lib/tools/Makefile5
-rw-r--r--lib/tools/bin/.gitignore0
-rw-r--r--lib/tools/c_src/Makefile6
-rw-r--r--lib/tools/c_src/Makefile.in221
-rw-r--r--lib/tools/c_src/depend.mk17
-rw-r--r--lib/tools/c_src/erl_memory.c2947
-rw-r--r--lib/tools/c_src/erl_memory_trace_block_table.c762
-rw-r--r--lib/tools/c_src/erl_memory_trace_block_table.h74
-rw-r--r--lib/tools/doc/src/cover.xml4
-rw-r--r--lib/tools/doc/src/cprof_chapter.xml149
-rw-r--r--lib/tools/doc/src/eprof.xml4
-rw-r--r--lib/tools/doc/src/fprof.xml6
-rw-r--r--lib/tools/doc/src/fprof_chapter.xml4
-rw-r--r--lib/tools/doc/src/instrument.xml50
-rw-r--r--lib/tools/doc/src/lcnt_chapter.xml4
-rw-r--r--lib/tools/doc/src/notes.xml16
-rw-r--r--lib/tools/doc/src/notes_history.xml4
-rw-r--r--lib/tools/emacs/Makefile2
-rw-r--r--lib/tools/emacs/README8
-rw-r--r--lib/tools/emacs/erlang-eunit.el4
-rw-r--r--lib/tools/emacs/erlang-skels-old.el4
-rw-r--r--lib/tools/emacs/erlang-start.el4
-rw-r--r--lib/tools/emacs/erlang.el39
-rw-r--r--lib/tools/emacs/erlang_appwiz.el10
-rw-r--r--lib/tools/examples/Makefile2
-rw-r--r--lib/tools/obj/.gitignore0
-rw-r--r--lib/tools/src/Makefile4
-rw-r--r--lib/tools/src/cover.erl19
-rw-r--r--lib/tools/src/fprof.erl4
-rw-r--r--lib/tools/src/tags.erl4
-rw-r--r--lib/tools/test/Makefile6
-rw-r--r--lib/tools/test/cover_SUITE.erl185
-rw-r--r--lib/tools/test/cprof_SUITE.erl10
-rw-r--r--lib/tools/test/emacs_SUITE_data/comments6
-rw-r--r--lib/tools/test/emacs_SUITE_data/funcs2
-rw-r--r--lib/tools/test/emacs_SUITE_data/highlight4
-rw-r--r--lib/tools/test/emacs_SUITE_data/icr39
-rw-r--r--lib/tools/test/emem_SUITE.erl654
-rw-r--r--lib/tools/test/eprof_SUITE_data/eprof_suite_test.erl4
-rw-r--r--lib/tools/test/instrument_SUITE.erl35
-rw-r--r--lib/tools/test/make_SUITE.erl16
-rw-r--r--lib/tools/test/prof_bench_SUITE.erl57
-rw-r--r--lib/tools/test/tools.spec.win1
-rw-r--r--lib/tools/test/xref_SUITE.erl4
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/wx/Makefile7
-rw-r--r--lib/wx/api_gen/README2
-rw-r--r--lib/wx/api_gen/apidiff.escript2
-rw-r--r--lib/wx/api_gen/gl_gen_erl.erl5
-rw-r--r--lib/wx/api_gen/wx_doxygen.conf2
-rw-r--r--lib/wx/api_gen/wx_extra/added_func.h4
-rw-r--r--lib/wx/api_gen/wx_extra/wxEvtHandler.erl7
-rw-r--r--lib/wx/api_gen/wx_extra/wxe_evth.h2
-rw-r--r--lib/wx/api_gen/wx_gen.erl4
-rw-r--r--lib/wx/api_gen/wx_gen.hrl4
-rw-r--r--lib/wx/api_gen/wx_gen_erl.erl5
-rw-r--r--lib/wx/api_gen/wxapi.conf22
-rwxr-xr-xlib/wx/autoconf/config.guess1700
-rwxr-xr-xlib/wx/autoconf/config.sub1860
-rwxr-xr-xlib/wx/autoconf/install-sh541
-rw-r--r--lib/wx/c_src/Makefile.in20
-rw-r--r--lib/wx/c_src/egl_impl.c6
-rw-r--r--lib/wx/c_src/egl_impl.h6
-rw-r--r--lib/wx/c_src/gen/wxe_func_table.cpp6002
-rw-r--r--lib/wx/c_src/gen/wxe_init.cpp8
-rw-r--r--lib/wx/c_src/gen/wxe_wrapper_5.cpp108
-rw-r--r--lib/wx/c_src/wxe_callback_impl.cpp4
-rw-r--r--lib/wx/c_src/wxe_helpers.cpp6
-rw-r--r--lib/wx/c_src/wxe_impl.cpp39
-rw-r--r--lib/wx/c_src/wxe_impl.h3
-rw-r--r--lib/wx/c_src/wxe_nif.c3
-rw-r--r--lib/wx/c_src/wxe_nif.h8
-rw-r--r--lib/wx/c_src/wxe_return.cpp8
-rw-r--r--lib/wx/config.mk.in10
-rwxr-xr-xlib/wx/configure4246
-rw-r--r--lib/wx/configure.ac (renamed from lib/wx/configure.in)158
-rw-r--r--lib/wx/doc/src/notes.xml57
-rw-r--r--lib/wx/doc/src/wx.xml43
-rw-r--r--lib/wx/doc/src/wxEvtHandler.xml4
-rw-r--r--lib/wx/doc/src/wxMenuBar.xml19
-rw-r--r--lib/wx/doc/src/wxMouseEvent.xml44
-rw-r--r--lib/wx/examples/demo/Makefile4
-rw-r--r--lib/wx/examples/demo/demo.erl4
-rw-r--r--lib/wx/examples/demo/demo_html_tagger.erl4
-rw-r--r--lib/wx/examples/demo/ex_sashWindow.erl4
-rw-r--r--lib/wx/examples/demo/ex_sizers.erl6
-rw-r--r--lib/wx/examples/demo/ex_splitterWindow.erl8
-rw-r--r--lib/wx/examples/simple/Makefile4
-rw-r--r--lib/wx/examples/simple/menu.erl4
-rw-r--r--lib/wx/examples/simple/minimal.erl4
-rw-r--r--lib/wx/examples/sudoku/Makefile4
-rw-r--r--lib/wx/include/wx.hrl11
-rw-r--r--lib/wx/src/Makefile4
-rw-r--r--lib/wx/src/gen/gl.erl3
-rw-r--r--lib/wx/src/gen/glu.erl4
-rw-r--r--lib/wx/src/gen/wxEvtHandler.erl9
-rw-r--r--lib/wx/src/gen/wxMenuBar.erl20
-rw-r--r--lib/wx/src/gen/wxMouseEvent.erl53
-rw-r--r--lib/wx/src/gen/wxe_funcs.hrl5386
-rw-r--r--lib/wx/src/wx.app.src4
-rw-r--r--lib/wx/src/wx.erl12
-rw-r--r--lib/wx/src/wxe_master.erl17
-rw-r--r--lib/wx/src/wxe_server.erl6
-rw-r--r--lib/wx/src/wxe_util.erl11
-rw-r--r--lib/wx/test/wx_basic_SUITE.erl2
-rw-r--r--lib/wx/test/wx_class_SUITE.erl2
-rw-r--r--lib/wx/test/wx_opengl_SUITE.erl4
-rw-r--r--lib/wx/test/wx_xtra_SUITE.erl8
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--lib/xmerl/doc/examples/test_html.erl4
-rw-r--r--lib/xmerl/doc/examples/xml/xmerl.xml4
-rw-r--r--lib/xmerl/doc/src/notes.xml69
-rw-r--r--lib/xmerl/doc/src/xmerl_examples.html4
-rw-r--r--lib/xmerl/include/xmerl.hrl6
-rw-r--r--lib/xmerl/include/xmerl_xpath.hrl2
-rw-r--r--lib/xmerl/include/xmerl_xsd.hrl10
-rw-r--r--lib/xmerl/src/Makefile13
-rw-r--r--lib/xmerl/src/xmerl_eventp.erl10
-rw-r--r--lib/xmerl/src/xmerl_regexp.erl6
-rw-r--r--lib/xmerl/src/xmerl_sax_parser.erl4
-rw-r--r--lib/xmerl/src/xmerl_sax_parser.hrl6
-rw-r--r--lib/xmerl/src/xmerl_sax_parser_base.erlsrc12
-rw-r--r--lib/xmerl/src/xmerl_sax_parser_list.erlsrc4
-rw-r--r--lib/xmerl/src/xmerl_scan.erl28
-rw-r--r--lib/xmerl/src/xmerl_ucs.erl4
-rw-r--r--lib/xmerl/src/xmerl_validate.erl4
-rw-r--r--lib/xmerl/src/xmerl_xpath.erl4
-rw-r--r--lib/xmerl/src/xmerl_xsd.erl118
-rw-r--r--lib/xmerl/src/xmerl_xsd_type.erl4
-rw-r--r--lib/xmerl/test/Makefile5
-rw-r--r--lib/xmerl/test/xmerl_SUITE.erl12
-rw-r--r--lib/xmerl/test/xmerl_sax_std_SUITE.erl32
-rw-r--r--lib/xmerl/vsn.mk2
-rw-r--r--make/app_targets.mk3
-rwxr-xr-xmake/autoconf/config.guess (renamed from lib/common_test/priv/auxdir/config.guess)0
-rwxr-xr-xmake/autoconf/config.sub (renamed from lib/common_test/priv/auxdir/config.sub)0
-rwxr-xr-xmake/autoconf/install-sh (renamed from lib/common_test/priv/auxdir/install-sh)0
-rw-r--r--make/autoconf/otp.m4 (renamed from erts/aclocal.m4)820
-rwxr-xr-xmake/autoconf/win32.config.cache.static (renamed from erts/autoconf/win32.config.cache.static)6
-rwxr-xr-xmake/autoconf/win64.config.cache.static (renamed from erts/autoconf/win64.config.cache.static)6
-rwxr-xr-xmake/configure4417
-rw-r--r--make/configure.ac (renamed from make/configure.in)38
-rwxr-xr-xmake/cross_check_erl4
-rw-r--r--make/doc.mk8
-rwxr-xr-xmake/emd2exml.in4
-rwxr-xr-xmake/install_bin4
-rw-r--r--make/otp.mk.in15
-rw-r--r--make/otp_patch_solve_forward_merge_version2
-rw-r--r--make/otp_subdir.mk8
-rw-r--r--make/otp_version_tickets62
-rw-r--r--make/otp_version_tickets_in_merge2
-rw-r--r--make/run_make.mk2
-rw-r--r--make/target.mk4
-rwxr-xr-xmake/test_target_script.sh159
-rwxr-xr-xotp_build79
-rwxr-xr-xotp_patch_apply4
-rw-r--r--otp_versions.table33
-rwxr-xr-xscripts/build-otp-tar4
-rwxr-xr-xscripts/check_doc_since4
-rwxr-xr-xscripts/diffable90
-rwxr-xr-xscripts/otp_html_check26
-rwxr-xr-xscripts/pre-push6
-rwxr-xr-xscripts/run-dialyzer4
-rwxr-xr-xscripts/run-smoke-tests20
-rw-r--r--system/doc/design_principles/events.xml3
-rw-r--r--system/doc/design_principles/release_handling.xml4
-rw-r--r--system/doc/design_principles/spec_proc.xml2
-rw-r--r--system/doc/design_principles/statem.xml4
-rw-r--r--system/doc/design_principles/sup_princ.xml6
-rw-r--r--system/doc/efficiency_guide/advanced.xml6
-rw-r--r--system/doc/efficiency_guide/bench.erl4
-rw-r--r--system/doc/efficiency_guide/commoncaveats.xmlsrc19
-rw-r--r--system/doc/efficiency_guide/functions.xml40
-rw-r--r--system/doc/efficiency_guide/retired_myths.xml4
-rw-r--r--system/doc/efficiency_guide/tablesDatabases.xml4
-rw-r--r--system/doc/embedded/intro.xml4
-rw-r--r--system/doc/general_info/DEPRECATIONS24
-rw-r--r--system/doc/general_info/deprecations_23.inc4
-rw-r--r--system/doc/general_info/upcoming_incompatibilities.xml15
-rw-r--r--system/doc/programming_examples/bit_syntax.xml8
-rw-r--r--system/doc/reference_manual/data_types.xml16
-rw-r--r--system/doc/reference_manual/distributed.xml17
-rw-r--r--system/doc/reference_manual/expressions.xml161
-rw-r--r--system/doc/reference_manual/features.xml217
-rw-r--r--system/doc/reference_manual/macros.xml37
-rw-r--r--system/doc/reference_manual/modules.xml56
-rw-r--r--system/doc/reference_manual/opaques.xml141
-rw-r--r--system/doc/reference_manual/part.xml4
-rw-r--r--system/doc/reference_manual/processes.xml11
-rw-r--r--system/doc/reference_manual/typespec.xml16
-rw-r--r--system/doc/reference_manual/xmlfiles.mk6
-rw-r--r--system/doc/system_principles/system_principles.xml4
-rw-r--r--system/doc/top/src/erl_html_tools.erl2
-rw-r--r--system/doc/tutorial/c_port.xmlsrc2
-rw-r--r--system/doc/tutorial/complex6.erl1
-rw-r--r--system/doc/tutorial/debugging.xml348
-rw-r--r--system/doc/tutorial/nif.xmlsrc9
-rw-r--r--system/doc/tutorial/part.xml3
-rw-r--r--system/doc/tutorial/xmlfiles.mk6
-rw-r--r--xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf6
-rw-r--r--xcomp/erl-xcomp-arm-android.conf28
-rw-r--r--xcomp/erl-xcomp-arm-ios.conf268
-rw-r--r--xcomp/erl-xcomp-arm-linux.conf6
-rw-r--r--xcomp/erl-xcomp-arm64-android.conf32
-rw-r--r--xcomp/erl-xcomp-arm64-ios.conf269
-rw-r--r--xcomp/erl-xcomp-arm64-iossimulator.conf269
-rw-r--r--xcomp/erl-xcomp-armv8-rpi3-linux-gnueabihf.conf8
-rw-r--r--xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf6
-rw-r--r--xcomp/erl-xcomp-host-iossimulator.conf268
-rw-r--r--xcomp/erl-xcomp-mips-linux.conf6
-rw-r--r--xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf6
-rw-r--r--xcomp/erl-xcomp-powerpc64-bgq-linux.conf6
-rw-r--r--xcomp/erl-xcomp-x86_64-android.conf22
-rw-r--r--xcomp/erl-xcomp-x86_64-iossimulator.conf269
-rw-r--r--xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf6
-rw-r--r--xcomp/erl-xcomp.conf.template6
3045 files changed, 199343 insertions, 152102 deletions
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000..0e990b715a
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,32 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
+// https://github.com/microsoft/vscode-dev-containers/tree/v0.194.0/containers/cpp
+{
+ "name": "Erlang/OTP",
+ "build": {
+ "dockerfile": "../.github/dockerfiles/Dockerfile.ubuntu-base",
+ "context": "../.github",
+ "args": {
+ "BASE": "mcr.microsoft.com/vscode/devcontainers/base:focal",
+ "USER": "vscode",
+ "GROUP": "vscode"
+ }
+ },
+ "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
+
+ // Set *default* container specific settings.json values on container create.
+ "settings": {},
+
+ // Add the IDs of extensions you want installed when the container is created.
+ "extensions": [
+ "ms-vscode.cpptools",
+ "erlang-ls.erlang-ls" ],
+
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [],
+
+ // Use 'postCreateCommand' to run commands after the container is created.
+ // "postCreateCommand": "gcc -v",
+
+ // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
+ "remoteUser": "vscode"
+}
diff --git a/.dir-locals.el b/.dir-locals.el
index 09d02274c3..b6586cba03 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -2,6 +2,7 @@
(
(erlang-mode (indent-tabs-mode . nil))
(autoconf-mode (indent-tabs-mode . nil))
+ (m4-mode (indent-tabs-mode . nil))
(java-mode (indent-tabs-mode . nil))
(perl-mode (indent-tabs-mode . nil))
(xml-mode (indent-tabs-mode . nil))
diff --git a/.github/dockerfiles/Dockerfile.32-bit b/.github/dockerfiles/Dockerfile.32-bit
index 5949ecc335..f1ea96d5fb 100644
--- a/.github/dockerfiles/Dockerfile.32-bit
+++ b/.github/dockerfiles/Dockerfile.32-bit
@@ -1,4 +1,5 @@
-FROM docker.pkg.github.com/erlang/otp/i386-debian-base
+ARG BASE=docker.pkg.github.com/erlang/otp/i386-debian-base
+FROM $BASE
ARG MAKEFLAGS=-j4
ENV MAKEFLAGS=$MAKEFLAGS \
@@ -16,14 +17,8 @@ ENV CFLAGS="-O2 -g -Werror"
## Configure, check that no application are disabled, then make and then build doc chunks
RUN ./configure --with-ssl --prefix=/otp && \
- if cat lib/*/CONF_INFO || cat lib/*/SKIP || cat lib/SKIP-APPLICATIONS; then exit 1; fi
-
-RUN make && make install && \
- make install-docs DOC_TARGETS=chunks
+ if cat lib/*/CONF_INFO || cat lib/*/SKIP || cat lib/SKIP-APPLICATIONS; then exit 1; fi && \
+ make && make install
## Disable -Werror as testcases do not compile with it on
ENV CFLAGS="-O2 -g"
-
-RUN TESTSUITE_ROOT=/tests ./otp_build tests
-
-ENTRYPOINT ["bash","-c"]
diff --git a/.github/dockerfiles/Dockerfile.64-bit b/.github/dockerfiles/Dockerfile.64-bit
index 8d513d8c71..25aadc5e84 100644
--- a/.github/dockerfiles/Dockerfile.64-bit
+++ b/.github/dockerfiles/Dockerfile.64-bit
@@ -1,12 +1,10 @@
-FROM docker.pkg.github.com/erlang/otp/ubuntu-base
-## We do a SSA lint check here
-ENV ERL_COMPILER_OPTIONS=ssalint
+ARG BASE=docker.pkg.github.com/erlang/otp/ubuntu-base
+FROM $BASE
-ARG MAKEFLAGS=-j4
+ARG MAKEFLAGS=$MAKEFLAGS
ENV MAKEFLAGS=$MAKEFLAGS \
- ERLC_USE_SERVER=yes \
- ERL_TOP=/buildroot/otp \
- PATH=/buildroot/otp/bin:$PATH
+ ERL_TOP=/buildroot/otp \
+ PATH=/otp/bin:/buildroot/otp/bin:$PATH
ARG ARCHIVE=./otp.tar.gz
COPY $ARCHIVE /buildroot/otp.tar.gz
@@ -14,19 +12,37 @@ RUN cd /buildroot && tar -xzf ./otp.tar.gz
WORKDIR /buildroot/otp/
-ENV CC=clang CXX=clang++ \
- CFLAGS="-O2 -g -Werror"
+ENV CFLAGS="-O2 -g -Werror"
## Configure, check that no application are disabled and then make
-# We need --with-ssl-lib-subdir=lib/x86_64-linux-gnu since clang does not
-# give us this information such as gcc does...
-RUN ./configure --with-ssl --with-ssl-lib-subdir=lib/x86_64-linux-gnu --prefix=/otp && \
+RUN ./configure --prefix=/otp && \
if cat lib/*/CONF_INFO || cat lib/*/SKIP || cat lib/SKIP-APPLICATIONS; then exit 1; fi && \
- make && make install
+ make && sudo make install
## Disable -Werror as testcases do not compile with it on
ENV CFLAGS="-O2 -g"
-RUN TESTSUITE_ROOT=/tests ./otp_build tests
+WORKDIR /buildroot/
-ENTRYPOINT ["bash","-c"]
+## Install test tools rebar3, proper and jsx
+RUN latest () { \
+ local VSN=$(curl -sL "https://api.github.com/repos/$1/tags" | jq -r ".[] | .name" | grep -E '^v?[0-9]' | sort -V | tail -1); \
+ curl -sL "https://github.com/$1/archive/$VSN.tar.gz" > $(basename $1).tar.gz; \
+ } && \
+ latest erlang/rebar3 && ls -la && \
+ (tar xzf rebar3.tar.gz && cd rebar3-* && ./bootstrap && sudo cp rebar3 /usr/bin) && \
+ latest proper-testing/proper && \
+ (tar xzf proper.tar.gz && mv proper-* proper && cd proper && make) && \
+ latest talentdeficit/jsx && \
+ (tar xzf jsx.tar.gz && mv jsx-* jsx && cd jsx && rebar3 compile)
+
+ENV ERL_LIBS=/buildroot/proper:/buildroot/jsx
+
+WORKDIR /buildroot/otp/
+
+## Update init.sh with correct env vars
+RUN echo "export MAKEFLAGS=$MAKEFLAGS" > /buildroot/env.sh && \
+ echo "export ERLC_USE_SERVER=$ERLC_USE_SERVER" >> /buildroot/env.sh && \
+ echo "export ERL_TOP=$ERL_TOP" >> /buildroot/env.sh && \
+ echo "export PATH=$PATH" >> /buildroot/env.sh && \
+ echo "export ERL_LIBS=$ERL_LIBS" >> /buildroot/env.sh
diff --git a/.github/dockerfiles/Dockerfile.clang b/.github/dockerfiles/Dockerfile.clang
new file mode 100644
index 0000000000..92607dd6bb
--- /dev/null
+++ b/.github/dockerfiles/Dockerfile.clang
@@ -0,0 +1,32 @@
+ARG BASE=docker.pkg.github.com/erlang/otp/ubuntu-base
+FROM $BASE
+## We do a SSA lint check here
+ENV ERL_COMPILER_OPTIONS=ssalint
+
+ARG MAKEFLAGS=-j4
+ENV MAKEFLAGS=$MAKEFLAGS \
+ ERLC_USE_SERVER=yes \
+ ERL_TOP=/buildroot/otp \
+ PATH=/otp/bin:/buildroot/otp/bin:$PATH
+
+RUN sudo apt-get install -y clang
+
+ARG ARCHIVE=./otp.tar.gz
+COPY $ARCHIVE /buildroot/otp.tar.gz
+RUN cd /buildroot && tar -xzf ./otp.tar.gz
+
+WORKDIR /buildroot/otp/
+
+ENV CC=clang CXX=clang++ \
+ CFLAGS="-O2 -g -Werror"
+
+## Configure, check that no application are disabled and then make
+# We need --with-ssl-lib-subdir=lib/x86_64-linux-gnu since clang does not
+# give us this information such as gcc does...
+RUN ./configure --with-ssl --with-ssl-lib-subdir=lib/x86_64-linux-gnu --prefix=/otp && \
+ if cat lib/*/CONF_INFO || cat lib/*/SKIP || cat lib/SKIP-APPLICATIONS; then exit 1; fi && \
+ make && sudo make install && \
+ make FLAVOR=emu && sudo make install FLAVOR=emu
+
+## Disable -Werror as testcases do not compile with it on
+ENV CFLAGS="-O2 -g"
diff --git a/.github/dockerfiles/Dockerfile.cross-compile b/.github/dockerfiles/Dockerfile.cross-compile
index ca583e1857..75045f2c76 100644
--- a/.github/dockerfiles/Dockerfile.cross-compile
+++ b/.github/dockerfiles/Dockerfile.cross-compile
@@ -1,7 +1,8 @@
##
## This docker file will build Erlang on 32-bit to 64-bit x86
##
-FROM docker.pkg.github.com/erlang/otp/i386-debian-base as build
+ARG BASE=docker.pkg.github.com/erlang/otp/i386-debian-base
+FROM $BASE as build
ARG MAKEFLAGS=-j4
ENV MAKEFLAGS=$MAKEFLAGS \
@@ -17,13 +18,6 @@ RUN tar xzf ../otp.tar.gz
## Build the bootstrap system
RUN cd $ERL_TOP && CFLAGS="-Wall -O2 -g" ./configure && make && make install
-## Build pre-build tar ball
-RUN cd $ERL_TOP && scripts/build-otp-tar -o /buildroot/otp_clean_src.tar.gz /buildroot/otp_src.tar.gz \
- -b /buildroot/bootstrap/otp/ /buildroot/otp.tar.gz
-
-## Prepare for a new build using pre-built tar ball
-RUN cd ../ && tar -xzf ./otp_src.tar.gz
-
ENV HOST=$HOST_TRIP \
CC=$HOST_TRIP-gcc \
CPPFLAGS="--sysroot=/buildroot/sysroot" \
@@ -39,15 +33,16 @@ ENV HOST=$HOST_TRIP \
erl_xcomp_sysroot=/buildroot/sysroot \
ERL_TOP=/buildroot/otp
+RUN cd /buildroot && tar xzf otp.tar.gz
+
WORKDIR /buildroot/otp
## Build the cross system
# We cannot use config.guess for --build since its value clashes with the
# canonical value of host...
-RUN ./configure --prefix=/otp/ --host=$HOST --build=x86-pc-linux-gnu
-RUN OTP_SMALL_BUILD=true V=1 make
-
-RUN make odbc && make install
+RUN ./configure --prefix=/otp/ --host=$HOST --build=x86-pc-linux-gnu && \
+ OTP_SMALL_BUILD=true V=1 make && \
+ make install
## Build the cross tests
ENV CFLAGS="--sysroot=/buildroot/sysroot -O2 -g"
@@ -64,5 +59,3 @@ COPY --from=build /otp /otp
COPY --from=build /buildroot/otp/release/tests /tests
ENV PATH=/otp/bin:$PATH
-
-ENTRYPOINT ["bash","-c"]
diff --git a/.github/dockerfiles/Dockerfile.documentation b/.github/dockerfiles/Dockerfile.documentation
deleted file mode 100644
index b0c2eb8015..0000000000
--- a/.github/dockerfiles/Dockerfile.documentation
+++ /dev/null
@@ -1,23 +0,0 @@
-FROM docker.pkg.github.com/erlang/otp/ubuntu-base
-
-ARG MAKEFLAGS=-j4
-ENV MAKEFLAGS=$MAKEFLAGS \
- ERLC_USE_SERVER=yes \
- ERL_TOP=/buildroot/otp \
- PATH=/buildroot/otp/bin:$PATH
-
-ARG ARCHIVE=./otp.tar.gz
-COPY $ARCHIVE /buildroot/otp.tar.gz
-RUN cd /buildroot && tar -xzf ./otp.tar.gz
-
-WORKDIR /buildroot/otp/
-
-ENV RELEASE_ROOT=/otp
-
-RUN ./configure --prefix=/otp && make && make release
-
-RUN ./configure && make && make release
-
-RUN make docs release_docs
-
-ENTRYPOINT ["bash","-c"]
diff --git a/.github/dockerfiles/Dockerfile.ubuntu-base b/.github/dockerfiles/Dockerfile.ubuntu-base
index 20df3ab80d..c19537ef2a 100644
--- a/.github/dockerfiles/Dockerfile.ubuntu-base
+++ b/.github/dockerfiles/Dockerfile.ubuntu-base
@@ -1,16 +1,93 @@
##
## This docker file will build a base image for building Erlang/OTP
##
-ARG BASE=ubuntu:20.04
+ARG BASE=gitpod/workspace-full
FROM $BASE
-ENV INSTALL_LIBS="zlib1g-dev libncurses5-dev libssl-dev unixodbc-dev libgmp3-dev libwxbase3.0-dev libwxgtk3.0-gtk3-dev libwxgtk-webview3.0-gtk3-dev libsctp-dev lksctp-tools"
+ENV INSTALL_LIBS="zlib1g-dev libncurses5-dev libssl-dev unixodbc-dev libsctp-dev lksctp-tools libgmp3-dev libwxbase3.0-dev libwxgtk3.0-gtk3-dev libwxgtk-webview3.0-gtk3-dev"
+
+ARG EXTRA_LIBS="erlang erlang-doc"
+
+USER root
ENV DEBIAN_FRONTEND=noninteractive
+ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
+
+RUN apt-get update && apt-get -y upgrade && \
+ apt-get install -y build-essential m4 autoconf fop xsltproc \
+ default-jdk libxml2-utils flex pkg-config \
+ unixodbc odbc-postgresql postgresql \
+ tzdata ssh openssh-server groff-base sudo gdb tinyproxy bind9 nsd expect vsftpd python \
+ linux-tools-common linux-tools-generic linux-tools-`uname -r` curl jq \
+ xvfb libgl1-mesa-dri \
+ ${INSTALL_LIBS} && \
+ for lib in ${EXTRA_LIBS}; do apt-get install -y ${lib}; done && \
+ if [ ! -f /etc/apache2/apache2.conf ]; then apt-get install -y apache2; fi && \
+ sed -i 's@# en_US.UTF-8@en_US.UTF-8@g' /etc/locale.gen && locale-gen && \
+ update-alternatives --set wx-config /usr/lib/x86_64-linux-gnu/wx/config/gtk3-unicode-3.0
+
+## EXTRA_LIBS are installed using a for loop because of bugs in the erlang-doc deb package
+## Apache2 may already be installed, if so we do not want to install it again
+
+ARG MAKEFLAGS=-j4
+ENV MAKEFLAGS=$MAKEFLAGS \
+ ERLC_USE_SERVER=yes
+
+## We install the latest version of the previous three releases in order to do
+## backwards compatability testing of the Erlang distribution.
+RUN apt-get install -y git && \
+ curl -L https://raw.githubusercontent.com/kerl/kerl/master/kerl > /usr/bin/kerl && \
+ chmod +x /usr/bin/kerl && \
+ kerl update releases && \
+ LATEST=$(kerl list releases | tail -1 | awk -F '.' '{print $1}') && \
+ for release in $(seq $(( LATEST - 3 )) $(( LATEST - 1 ))); do \
+ VSN=$(kerl list releases | grep "^$release" | tail -1); \
+ kerl build ${VSN} ${VSN} && \
+ kerl install ${VSN} /usr/local/lib/erlang-${VSN}; \
+ done && \
+ rm -rf ~/.kerl
+
+ENV LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
+
+ARG USER=gitpod
+ARG GROUP=gitpod
+ARG gid=10
+ARG uid=421
+
+RUN echo "Europe/Stockholm" > /etc/timezone && \
+ ln -snf /usr/share/zoneinfo/$(cat /etc/timezone) /etc/localtime && \
+ if [ ! -d /home/${USER} ]; then useradd -rm -d /home/${USER} -s /bin/sh -g ${gid} -G ${gid},sudo -u ${uid} ${USER}; fi && \
+ echo "${USER} ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USER} && \
+ echo "/buildroot/** r," >> /etc/apparmor.d/local/usr.sbin.named && \
+ echo "/tests/** r," >> /etc/apparmor.d/local/usr.sbin.named
+
+## Setup progres so that the odbc test can run
+USER postgres
+
+RUN service postgresql start && \
+ psql -c "CREATE USER odbctest WITH SUPERUSER PASSWORD 'odbctest';" && \
+ createdb -O odbctest odbctest && \
+ service postgresql stop
+
+COPY --chown=root:${GROUP} dockerfiles/odbc.ini /etc/
+COPY --chown=root:${GROUP} dockerfiles/odbcinst.ini /etc/
+
+USER ${USER}
+
+## Need to set USER and create a keygen file for ssh tests to pass
+ENV USER=${USER}
+RUN ssh-keygen -q -t rsa -N '' -f $HOME/.ssh/id_rsa && \
+ cp $HOME/.ssh/id_rsa.pub $HOME/.ssh/authorized_keys
+
+## Java and log4j are used by fop to build documentation
+COPY --chown=${USER}:${GROUP} dockerfiles/log4j.properties /home/${USER}/
+ENV OTP_STRICT_INSTALL=yes \
+ JAVA_ARGS="-Dlog4j.configuration=file://home/${USER}/log4j.properties"
+
+RUN sudo mkdir /buildroot /tests /otp && sudo chown ${USER}:${GROUP} /buildroot /tests /otp
+
+COPY --chown=${USER}:${GROUP} dockerfiles/init.sh /buildroot/
-RUN apt-get update && \
- apt-get -y upgrade && \
- apt-get install -y build-essential m4 autoconf fop xsltproc clang clang-format \
- default-jdk libxml2-utils $INSTALL_LIBS
+## TODO: Build Erlang versions N, N-1 and N-2 for compatability testing.
-RUN update-alternatives --set wx-config /usr/lib/x86_64-linux-gnu/wx/config/gtk3-unicode-3.0
+ENTRYPOINT ["/buildroot/init.sh"]
diff --git a/.github/dockerfiles/init.sh b/.github/dockerfiles/init.sh
new file mode 100755
index 0000000000..8eb13abee2
--- /dev/null
+++ b/.github/dockerfiles/init.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+if [ -f "/buildroot/env.sh" ]; then
+ . "/buildroot/env.sh"
+fi
+
+sudo mkdir -p -m0755 /var/run/sshd
+
+sudo /usr/sbin/sshd
+
+sudo service postgresql start
+
+sudo -E bash -c "apt-get update && apt-get install -y linux-tools-common linux-tools-generic linux-tools-`uname -r`"
+
+sudo bash -c "Xvfb :99 -ac -screen 0 1920x1080x24 -nolisten tcp" &
+export DISPLAY=:99
+
+PATH=$PATH:$(ls -1d /usr/local/lib/erlang-*/bin | tr '\n' ':')
+
+exec /bin/bash -c "$1"
diff --git a/.github/dockerfiles/log4j.properties b/.github/dockerfiles/log4j.properties
new file mode 100644
index 0000000000..79b28f05e9
--- /dev/null
+++ b/.github/dockerfiles/log4j.properties
@@ -0,0 +1,9 @@
+log4j.rootLogger = INFO, console
+
+log4j.appender.console = org.apache.log4j.ConsoleAppender
+
+log4j.appender.console.layout = org.apache.log4j.PatternLayour
+log4j.appender.console.layout.ConversionPattern = %d [%t] %-5p %c{1} - %m%n
+
+log4j.logger.org.apache.fop = INFO
+log4j.logger.org.apache.fop.render = INFO
diff --git a/.github/dockerfiles/odbc.ini b/.github/dockerfiles/odbc.ini
new file mode 100644
index 0000000000..9a36ba48e1
--- /dev/null
+++ b/.github/dockerfiles/odbc.ini
@@ -0,0 +1,19 @@
+[PostgresLinux64Ubuntu]
+Driver = PostgreSQL64
+Description = PostgreSQL Data Source
+Servername = localhost
+Port = 5432
+Protocol = 10
+UserName = odbctest
+Password = odbctest
+Database = odbctest
+
+[PostgresLinuxUbuntu]
+Driver = PostgreSQL32
+Description = PostgreSQL Data Source
+Servername = localhost
+Port = 5432
+Protocol = 10
+UserName = odbctest
+Password = odbctest
+Database = odbctest
diff --git a/.github/dockerfiles/odbcinst.ini b/.github/dockerfiles/odbcinst.ini
new file mode 100644
index 0000000000..d26e6de7f4
--- /dev/null
+++ b/.github/dockerfiles/odbcinst.ini
@@ -0,0 +1,15 @@
+[PostgreSQL64]
+Description = PostgreSQL Data Source
+Driver = /usr/lib/x86_64-linux-gnu/odbc/psqlodbca.so
+Setup = /usr/lib/x86_64-linux-gnu/odbc/libodbcpsqlS.so
+Debug = 0
+CommLog = 1
+UsageCount = 2
+
+[PostgreSQL32]
+Description = PostgreSQL Data Source
+Driver = /usr/lib/i386-linux-gnu/odbc/psqlodbca.so
+Setup = /usr/lib/i386-linux-gnu/odbc/libodbcpsqlS.so
+Debug = 0
+CommLog = 1
+UsageCount = 2 \ No newline at end of file
diff --git a/.github/scripts/base-tag b/.github/scripts/base-tag
deleted file mode 100755
index b2a8017bfc..0000000000
--- a/.github/scripts/base-tag
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-set -x
-
-case "$1" in
- *i386-debian-base)
- BASE="i386/debian:bullseye"
- BASE_TYPE=debian-base
- ;;
- *debian-base)
- BASE="debian:bullseye"
- BASE_TYPE=debian-base
- ;;
- *ubuntu-base)
- BASE="ubuntu:20.04"
- BASE_TYPE=ubuntu-base
- ;;
-esac
-echo "::set-output name=BASE::${BASE}"
-echo "::set-output name=BASE_TYPE::${BASE_TYPE}"
diff --git a/.github/scripts/build-base-image.sh b/.github/scripts/build-base-image.sh
new file mode 100755
index 0000000000..543235e126
--- /dev/null
+++ b/.github/scripts/build-base-image.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+BASE_BRANCH="$1"
+
+case "${BASE_BRANCH}" in
+ master|maint|maint-*)
+ ;;
+ *)
+ BASE_BRANCH="master"
+ ;;
+esac
+
+if [ -z "${BASE_TAG}" ]; then
+ BASE_TAG=$(grep "ARG BASE=" ".github/dockerfiles/Dockerfile.${2}" | head -1 | tr '=' ' ' | awk '{print $3}')
+fi
+
+case "${BASE_TAG}" in
+ *i386-debian-base)
+ BASE="i386/debian:bullseye"
+ BASE_TYPE=debian-base
+ ;;
+ *debian-base)
+ BASE="debian:bullseye"
+ BASE_TYPE=debian-base
+ ;;
+ *ubuntu-base)
+ BASE="ubuntu:20.04"
+ BASE_TYPE=ubuntu-base
+ ;;
+esac
+
+echo "::set-output name=BASE::${BASE}"
+echo "::set-output name=BASE_TAG::${BASE_TAG}"
+echo "::set-output name=BASE_TYPE::${BASE_TYPE}"
+
+if [ -f "otp_docker_base.tar" ]; then
+ docker load -i "otp_docker_base.tar"
+ echo "::set-output name=BASE_BUILD::loaded"
+elif [ -f "otp_docker_base/otp_docker_base.tar" ]; then
+ docker load -i "otp_docker_base/otp_docker_base.tar"
+ echo "::set-output name=BASE_BUILD::loaded"
+else
+ if [ "${BASE_USE_CACHE}" != "false" ]; then
+ docker pull "${BASE_TAG}:${BASE_BRANCH}"
+ docker tag "${BASE_TAG}:${BASE_BRANCH}" "${BASE_TAG}:latest"
+ BASE_CACHE="--cache-from ${BASE_TAG}"
+ fi
+
+ BASE_IMAGE_ID=$(docker images -q "${BASE_TAG}:latest")
+
+ docker build --pull --tag "${BASE_TAG}:latest" \
+ ${BASE_CACHE} \
+ --file ".github/dockerfiles/Dockerfile.${BASE_TYPE}" \
+ --build-arg MAKEFLAGS=-j$(($(nproc) + 2)) \
+ --build-arg USER=otptest --build-arg GROUP=uucp \
+ --build-arg uid="$(id -u)" \
+ --build-arg BASE="${BASE}" .github/
+
+ NEW_BASE_IMAGE_ID=$(docker images -q "${BASE_TAG}:latest")
+ if [ "${BASE_IMAGE_ID}" = "${NEW_BASE_IMAGE_ID}" ]; then
+ echo "::set-output name=BASE_BUILD::cached"
+ else
+ echo "::set-output name=BASE_BUILD::re-built"
+ docker save "${BASE_TAG}:latest" > "otp_docker_base.tar"
+ fi
+fi
diff --git a/.github/scripts/build-macos-wxwidgets.sh b/.github/scripts/build-macos-wxwidgets.sh
new file mode 100755
index 0000000000..be087d9f9b
--- /dev/null
+++ b/.github/scripts/build-macos-wxwidgets.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -e
+
+export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN)
+
+if [ -z "$WXWIDGETS_VERSION" ]; then
+ WXWIDGETS_VERSION=3.1.5
+fi
+
+vsn=$WXWIDGETS_VERSION
+curl --fail -LO https://github.com/wxWidgets/wxWidgets/releases/download/v$vsn/wxWidgets-$vsn.tar.bz2
+tar -xf wxWidgets-$vsn.tar.bz2
+mv wxWidgets-$vsn/ wxWidgets
+
+cd wxWidgets
+./configure \
+ --disable-shared \
+ --prefix=$PWD/release \
+ --with-cocoa \
+ --with-macosx-version-min=10.15 \
+ --with-libjpeg=builtin \
+ --with-libtiff=builtin \
+ --with-libpng=builtin \
+ --with-liblzma=builtin \
+ --with-zlib=builtin \
+ --with-expat=builtin
+make
+make install
diff --git a/.github/scripts/build-macos.sh b/.github/scripts/build-macos.sh
new file mode 100755
index 0000000000..82b07bac7b
--- /dev/null
+++ b/.github/scripts/build-macos.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN)
+export ERL_TOP=`pwd`
+export RELEASE_ROOT=$ERL_TOP/release
+export ERLC_USE_SERVER=true
+
+./otp_build configure \
+ --disable-dynamic-ssl-lib
+./otp_build boot -a
+./otp_build release -a $RELEASE_ROOT
+make release_docs DOC_TARGETS=chunks
diff --git a/.github/scripts/get-pr-number.es b/.github/scripts/get-pr-number.es
new file mode 100755
index 0000000000..e925f95625
--- /dev/null
+++ b/.github/scripts/get-pr-number.es
@@ -0,0 +1,30 @@
+#!/usr/bin/env escript
+%%! -pa jsx/_build/default/lib/jsx/ebin/
+-mode(compile).
+
+main([Repo, HeadSha]) ->
+ io:format("Looking for: ~ts",[HeadSha]),
+ AllOpenPrs = ghapi("gh api --paginate -X GET /repos/"++Repo++"/pulls -f state=open"),
+ case lists:search(
+ fun(#{ <<"number">> := NR, <<"head">> := #{ <<"sha">> := Sha }}) ->
+ io:format("~p: Checking ~ts~n",[NR, Sha]),
+ string:equal(HeadSha, Sha)
+ end, AllOpenPrs) of
+ {value, #{ <<"number">> := Number } } ->
+ io:format("::set-output name=result::~p~n", [Number]);
+ false ->
+ io:format("::set-output name=result::~ts~n", [""])
+ end.
+
+ghapi(CMD) ->
+ Data = cmd(CMD),
+ try jsx:decode(Data, [{return_maps,true}])
+ catch E:R:ST ->
+ io:format("Failed to decode: ~ts",[Data]),
+ erlang:raise(E,R,ST)
+ end.
+
+cmd(CMD) ->
+ ListCmd = unicode:characters_to_list(CMD),
+ io:format("cmd: ~ts~n",[ListCmd]),
+ unicode:characters_to_binary(os:cmd(ListCmd)).
diff --git a/.github/scripts/path-filters.sh b/.github/scripts/path-filters.sh
new file mode 100755
index 0000000000..f55bd168cf
--- /dev/null
+++ b/.github/scripts/path-filters.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+cat <<EOF
+emulator: &emulator
+ - 'make/**'
+EOF
+
+for file in erts/*; do
+ if [ "$file" != "erts/epmd" ]; then
+ if [ -d "$file" ]; then
+ echo " - '$file/**'"
+ else
+ echo " - '$file'"
+ fi
+ fi
+done
+
+cat <<EOF
+debug:
+ - *emulator
+epmd:
+ - 'erts/epmd/**'
+EOF
+
+APPS=$(ls -d lib/*/doc | awk -F '/' '{print $2}')
+for app in $APPS; do
+ echo "$app:"
+ echo " - 'lib/$app/**'"
+done
diff --git a/.github/scripts/pr-comment.js b/.github/scripts/pr-comment.js
new file mode 100644
index 0000000000..9d03eb5487
--- /dev/null
+++ b/.github/scripts/pr-comment.js
@@ -0,0 +1,110 @@
+module.exports = async({ github, context, state, pr_number }) => {
+
+ console.log(`Workflow: ${JSON.stringify(context.payload.workflow_run,null,2)}`);
+
+ /* We use this link service as github does not (yet) expose an API where
+ you can download an artifact.
+ https://github.com/actions/upload-artifact/issues/50
+ */
+ var nightlyURL = (artifact) => {
+ return `https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${artifact.id}.zip`
+ };
+
+ const artifacts = await github.paginate(
+ github.rest.actions.listWorkflowRunArtifacts,
+ {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ run_id: context.payload.workflow_run.id,
+ per_page: 100
+ });
+
+ const ct_logs = artifacts.find(
+ (a) => { return a.name == 'test_results'; });
+ const html_docs = artifacts.find(
+ (a) => { return a.name == 'otp_doc_html'; });
+ const win_exe = artifacts.find(
+ (a) => { return a.name.match(/win32/); });
+
+ let gh_comments = await github.paginate(
+ github.rest.issues.listComments,
+ {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr_number,
+ per_page: 100
+ });
+
+ /* We find the newest comment by "github-actions[bot]". There really should
+ only be one, but the PR scripts may be buggy and if so we want to updated
+ the latest post. */
+ gh_comments.reverse();
+ const gh_comment = gh_comments.find(c => c.user.login == "github-actions[bot]");
+
+ console.log(`Comment to update: ${JSON.stringify(gh_comment,null,2)}`);
+
+ let ct_body;
+
+ /* The EnricoMi/publish-unit-test-result-action@v1 action creates/updates a comment
+ to always start with "## CT Test Results". Below we append some data to that
+ comment to further help the user.
+ */
+
+ if (gh_comment && !gh_comment.body.match("<!-- marker -->")) {
+ /* If the comment does not have a marker, it has been touched by
+ EnricoMi/publish-unit-test-result-action@v1 and then we need
+ to update the comment */
+ ct_body = gh_comment.body;
+ } else if (gh_comment && state == 'starting') {
+ /* If the comment exists and we are just starting the workflow we do nothing */
+ return;
+ } else {
+ /* if the comment does not exist we use a place holder comment. This
+ needs to start with "## CT Test Results" and
+ contain "Results for commit" as otherwise
+ EnricoMi/publish-unit-test-result-action@v1 will create a new comment. */
+ ct_body = "## CT Test Results\n\n";
+ if (state == 'starting') {
+ ct_body += `Tests are running... ${context.payload.workflow_run.html_url}\n\n`;
+ } else {
+ ct_body += "No tests were run for this PR. This is either because the build failed, or the PR is based on a branch without GH actions tests configured.\n\n";
+ }
+ ct_body += `Results for commit ${context.payload.workflow_run.head_sha}`;
+ }
+
+ console.log(`ct_body: ${ct_body}`);
+
+ const body = `${ct_body}
+
+<!-- marker -->
+
+To speed up review, make sure that you have read [Contributing to Erlang/OTP](/${context.repo.owner}/${context.repo.repo}/blob/master/CONTRIBUTING.md) and that all [checks](/${context.repo.owner}/${context.repo.repo}/pull/${pr_number}/checks) pass.
+
+See the [TESTING](/${context.repo.owner}/${context.repo.repo}/blob/master/HOWTO/TESTING.md) and [DEVELOPMENT](/${context.repo.owner}/${context.repo.repo}/blob/master/HOWTO/DEVELOPMENT.md) HowTo guides for details about how to run test locally.
+
+## Artifacts
+* ` + (ct_logs ? `[Complete CT logs](https://erlang.github.io/prs/${pr_number}/ct_logs/index.html) ([Download Logs](${nightlyURL(ct_logs)}))` : "No CT logs found") + `
+* ` + (html_docs ? `[HTML Documentation](https://erlang.github.io/prs/${pr_number}/doc/index.html) ([Download HTML Docs](${nightlyURL(html_docs)}))` : "No HTML docs found") + `
+* ` + (win_exe ? `[Windows Installer](${nightlyURL(win_exe)})` : "No Windows Installer found") + `
+
+// Erlang/OTP Github Action Bot
+`;
+ if (gh_comment) {
+ if (gh_comment.body != body) {
+ console.log("Update comment: " + gh_comment.id);
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: gh_comment.id,
+ body: body
+ });
+ }
+ } else {
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: pr_number,
+ body: body
+ });
+ }
+};
diff --git a/.github/scripts/restore-otp-image.sh b/.github/scripts/restore-otp-image.sh
new file mode 100755
index 0000000000..57621c25d5
--- /dev/null
+++ b/.github/scripts/restore-otp-image.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+BASE_BRANCH="$1"
+BASE_TAG=$(grep "ARG BASE=" ".github/dockerfiles/Dockerfile.64-bit" | head -1 | tr '=' ' ' | awk '{print $3}')
+
+BASE_TAG="$BASE_TAG" .github/scripts/build-base-image.sh "${BASE_BRANCH}"
+
+cat > Dockerfile <<EOF
+FROM ${BASE_TAG}
+ADD otp-ubuntu-20.04.tar.gz /
+WORKDIR /buildroot/otp/
+EOF
+docker build -t otp .
diff --git a/.github/scripts/sync-github-prs.es b/.github/scripts/sync-github-prs.es
new file mode 100755
index 0000000000..bc033c3efe
--- /dev/null
+++ b/.github/scripts/sync-github-prs.es
@@ -0,0 +1,144 @@
+#!/usr/bin/env escript
+%%! -pa jsx/_build/default/lib/jsx/ebin/
+%%
+%% This scripts downloads the docs + test results from an otp repo
+%% into the Target folder. It tries its best to not create too large
+%% files so that gh will still be happy with us when this is published to
+%% gh pages
+-mode(compile).
+
+main([Repo, Target]) ->
+ AllOpenPrs = ghapi("gh api --paginate -X GET /repos/"++Repo++"/pulls -f state=open"),
+ %% Download all updates, there really should not be any to download as they
+ %% are updated when a PR is updated, but we do it anyways just to be safe.
+ handle_prs(Repo, Target,AllOpenPrs),
+
+ %% Delete any PRs that have been closed
+ {ok, AllPrs} = file:list_dir(Target),
+ lists:foreach(
+ fun(PRNo) ->
+ case lists:search(
+ fun(#{ <<"number">> := No }) ->
+ No =:= list_to_integer(PRNo)
+ end, AllOpenPrs) of
+ {value, _} ->
+ ok;
+ false ->
+ cmd("rm -rf " ++ filename:join(Target,PRNo))
+ end
+ end, AllPrs);
+main([Repo, Target, PRNo]) ->
+ handle_prs(Repo, Target, [ghapi("gh api /repos/"++Repo++"/pulls/"++PRNo)]).
+
+handle_prs(Repo, Target, AllPRs) ->
+
+ %% We fetch all runs for the main.yaml repo. This takes a while,
+ %% but for some reason when we try to filter results using either
+ %% -f event=pull_request or -f branch=Ref github decides to not
+ %% return all the runs.... So we do it the slow way...
+ AllRuns = ghapi(["gh api --paginate -X GET /repos/"++Repo++"/actions/workflows/main.yaml/runs"]),
+
+ [handle_pr(Repo, Target, PR, AllRuns) || PR <- AllPRs],
+
+ %% Remove all links and files > 50MB
+ cmd(["find ",Target," -type l -exec rm -f {} \\;"]),
+ cmd(["find ",Target," -type f -size +50M -exec rm -f {} \\;"]),
+
+ ok.
+
+%% In order to get the latest gh actions run for a PR, we have to first list
+%% all workflow runs for that branch, and then look for a matching sha with the
+%% current top of the PR. Github does not have any API to find it any other way.
+%% See https://github.community/t/retrieve-workflow-id-for-a-given-pr/199745/4
+%% for a discussion about this.
+%%
+handle_pr(_Repo, Target,
+ #{ <<"number">> := Number,
+ <<"head">> := #{ <<"ref">> := _Ref, <<"sha">> := Sha } },
+ Runs) ->
+ PRDir = filename:join(Target,integer_to_list(Number)),
+ case lists:search(
+ fun(#{ <<"head_sha">> := HeadSha, <<"status">> := Status }) ->
+ string:equal(HeadSha, Sha) andalso string:equal(Status, <<"completed">>)
+ end, maps:get(<<"workflow_runs">>, Runs)) of
+ {value, Run} ->
+ Ident = integer_to_list(maps:get(<<"id">>,Run)),
+ io:format("Checking for ~ts~n", [filename:join(PRDir, Ident)]),
+ case file:read_file_info(filename:join(PRDir, Ident)) of
+ {error, enoent} ->
+ cmd("rm -rf "++PRDir),
+ ok = file:make_dir(PRDir),
+ ok = file:write_file(filename:join(PRDir,Ident), integer_to_list(Number)),
+
+ #{ <<"artifacts">> := Artifacts } =
+ ghapi(["gh api --paginate -X GET ",maps:get(<<"artifacts_url">>, Run)]),
+
+ lists:foreach(
+ fun(#{ <<"name">> := <<"test_results">>, <<"archive_download_url">> := Url }) ->
+ cmd(["gh api ", unicode:characters_to_list(Url), " > /tmp/test_results.zip"]),
+ cmd("unzip -d /tmp/test_results /tmp/test_results.zip"),
+ cmd(["tar xvzf /tmp/test_results/test_results.tar.gz "
+ "-C ",PRDir," make_test_dir/ct_logs --strip-components=1"]),
+ cmd("rm -rf /tmp/test_results*");
+ (#{ <<"name">> := <<"otp_doc_html">>, <<"archive_download_url">> := Url }) ->
+ cmd(["gh api ", unicode:characters_to_list(Url), " > /tmp/otp_doc_html.zip"]),
+ cmd("unzip -d /tmp/otp_doc_html /tmp/otp_doc_html.zip"),
+ cmd(["tar xvzf /tmp/otp_doc_html/otp_doc_html.tar.gz -C ",PRDir]),
+ cmd(["find ",PRDir," -name '*.pdf' -exec rm -f {} \\;"]),
+ cmd("rm -rf /tmp/otp_doc_html*");
+ (_) ->
+ ok
+ end, Artifacts),
+ CTLogsIndex = filename:join([PRDir,"ct_logs","index.html"]),
+ case file:read_file_info(CTLogsIndex) of
+ {ok, _} -> ok;
+ _ ->
+ ok = filelib:ensure_dir(CTLogsIndex),
+ ok = file:write_file(CTLogsIndex, ["No test logs found for ", Sha])
+ end,
+ DocIndex = filename:join([PRDir,"doc","index.html"]),
+ case file:read_file_info(DocIndex) of
+ {ok, _} -> ok;
+ _ -> ok = filelib:ensure_dir(DocIndex),
+ ok = file:write_file(DocIndex, ["No documentation found for ", Sha])
+ end;
+ {ok,_} ->
+ ok
+ end;
+ false ->
+ ok
+ end.
+
+ghapi(CMD) ->
+ decode(cmd(CMD)).
+
+decode(Data) ->
+ try jsx:decode(Data,[{return_maps, true}, return_tail]) of
+ {with_tail, Json, <<>>} ->
+ Json;
+ {with_tail, Json, Tail} ->
+ [Key] = maps:keys(maps:remove(<<"total_count">>, Json)),
+ #{ Key => lists:flatmap(
+ fun(J) -> maps:get(Key, J) end,
+ [Json | decodeTail(Tail)])
+ }
+ catch E:R:ST ->
+ io:format("Failed to decode: ~ts",[Data]),
+ erlang:raise(E,R,ST)
+ end.
+
+decodeTail(Data) ->
+ try jsx:decode(Data,[{return_maps, true}, return_tail]) of
+ {with_tail, Json, <<>>} ->
+ [Json];
+ {with_tail, Json, Tail} ->
+ [Json | decodeTail(Tail)]
+ catch E:R:ST ->
+ io:format("Failed to decode: ~ts",[Data]),
+ erlang:raise(E,R,ST)
+ end.
+
+cmd(CMD) ->
+ ListCmd = unicode:characters_to_list(CMD),
+ io:format("cmd: ~ts~n",[ListCmd]),
+ unicode:characters_to_binary(os:cmd(ListCmd)).
diff --git a/.github/scripts/sync-github-releases.sh b/.github/scripts/sync-github-releases.sh
index 763762234f..0cb2042f01 100755
--- a/.github/scripts/sync-github-releases.sh
+++ b/.github/scripts/sync-github-releases.sh
@@ -205,6 +205,11 @@ for name in "${ALL_TAGS[@]}"; do
_upload_artifacts ${name}
done
+## Rebuild erlang.org to get links to the new artifacts
+if [ ${UPLOADED} = true ]; then
+ curl -H "Authorization: token ${ERLANG_ORG_TOKEN}" -X POST -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/erlang/erlang-org/actions/workflows/update-gh-cache.yaml/dispatches" -d '{"ref":"master"}'
+fi
+
## If no assets were uploaded, we try to build one instead
if [ ${UPLOADED} = false ] && [ ${#MISSING_PREBUILD[0]} != 0 ]; then
name="${MISSING_PREBUILD[0]}"
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index 8489408911..ce50c86a1e 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -20,21 +20,170 @@ on:
push:
pull_request:
+env:
+ BASE_BRANCH: ${{ github.event_name == 'pull_request' && github.base_ref || github.ref_name }}
+
jobs:
pack:
- name: Pack the Erlang/OTP tar.gz
+ name: Build Erlang/OTP (64-bit)
runs-on: ubuntu-latest
+ outputs:
+ BASE_BUILD: ${{ steps.base-build.outputs.BASE_BUILD }}
steps:
- uses: actions/checkout@v2
- - name: Create initial pre-release tar
+ - name: Create initial pre-release tar
run: .github/scripts/init-pre-release.sh
- name: Upload source tar archive
uses: actions/upload-artifact@v2
with:
name: otp_git_archive
path: otp_src.tar.gz
+ - name: Docker login
+ uses: docker/login-action@v1
+ with:
+ registry: docker.pkg.github.com
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Build BASE image
+ id: base-build
+ run: .github/scripts/build-base-image.sh "${BASE_BRANCH}" 64-bit
+ - name: Save BASE image
+ if: steps.base-build.outputs.BASE_BUILD == 're-built'
+ uses: actions/upload-artifact@v2
+ with:
+ name: otp_docker_base
+ path: otp_docker_base.tar
+ - name: Build image
+ run: |
+ mv otp_src.tar.gz .github/otp.tar.gz
+ docker build --tag otp \
+ --build-arg MAKEFLAGS=-j$(($(nproc) + 2)) \
+ --file ".github/dockerfiles/Dockerfile.64-bit" \
+ .github/
+ - name: Save Erlang/OTP image
+ run: |
+ docker run -v $PWD:/github --entrypoint "" otp \
+ tar czf /github/otp-ubuntu-20.04.tar.gz /buildroot/ /otp/
+ - name: Upload otp ubuntu image
+ uses: actions/upload-artifact@v2
+ with:
+ name: otp-ubuntu-20.04
+ path: otp-ubuntu-20.04.tar.gz
+ - name: Build pre-built tar archives
+ run: |
+ docker run -v $PWD:/github --entrypoint "" otp \
+ scripts/build-otp-tar -o /github/otp_clean_src.tar.gz /github/otp_src.tar.gz -b /buildroot/otp/ /buildroot/otp.tar.gz
+ - name: Upload pre-built tar archive
+ uses: actions/upload-artifact@v2
+ with:
+ name: otp_prebuilt_no_chunks
+ path: otp_src.tar.gz
+
+ changed-apps:
+ name: Calculate changed applications
+ runs-on: ubuntu-latest
+ outputs:
+ changes: ${{ steps.changes.outputs.changes }}
+ all: ${{ steps.apps.outputs.all }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Get applications
+ id: apps
+ run: |
+ .github/scripts/path-filters.sh > .github/scripts/path-filters.yaml
+ ALL_APPS=$(grep '^[a-z_]*:' .github/scripts/path-filters.yaml | sed 's/:.*$//')
+ ALL_APPS=$(jq -n --arg inarr "${ALL_APPS}" '$inarr | split("\n")' | tr '\n' ' ')
+ echo "::set-output name=all::${ALL_APPS}"
+ - uses: dorny/paths-filter@v2
+ id: changes
+ with:
+ filters: .github/scripts/path-filters.yaml
+
+ build-macos:
+ name: Build Erlang/OTP (macOS)
+ runs-on: macos-12
+ needs: pack
+ env:
+ WXWIDGETS_VERSION: 3.1.5
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Download source archive
+ uses: actions/download-artifact@v2
+ with:
+ name: otp_prebuilt_no_chunks
+
+ - name: Cache wxWidgets
+ id: wxwidgets-cache
+ uses: actions/cache@v2
+ with:
+ path: wxWidgets
+ key: wxWidgets-${{ env.WXWIDGETS_VERSION }}-${{ runner.os }}-12
+
+ - name: Compile wxWidgets
+ if: steps.wxwidgets-cache.outputs.cache-hit != 'true'
+ run: .github/scripts/build-macos-wxwidgets.sh
+
+ - name: Compile Erlang
+ run: |
+ tar -xzf ./otp_src.tar.gz
+ export PATH=$PWD/wxWidgets/release/bin:$PATH
+ cd otp
+ $GITHUB_WORKSPACE/.github/scripts/build-macos.sh
+ tar -czf otp_macos_$(cat OTP_VERSION)_x86-64.tar.gz -C release .
+
+ - name: Test Erlang
+ run: |
+ cd otp/release
+ ./Install -sasl $PWD
+ ./bin/erl -noshell -eval 'io:format("~s", [erlang:system_info(system_version)]), halt().'
+ ./bin/erl -noshell -eval 'ok = crypto:start(), io:format("crypto ok~n"), halt().'
+ ./bin/erl -noshell -eval '{wx_ref,_,_,_} = wx:new(), io:format("wx ok~n"), halt().'
+
+ - name: Upload tarball
+ uses: actions/upload-artifact@v2
+ with:
+ name: otp_prebuilt_macos_x86-64
+ path: otp/otp_macos_*_x86-64.tar.gz
+
+ build-ios:
+ env:
+ RELEASE_LIBBEAM: yes
+ TARGET_ARCH: aarch64-apple-ios
+ name: Build Erlang/OTP (iOS)
+ runs-on: macos-12
+ needs: pack
+ steps:
+ - name: Download source archive
+ uses: actions/download-artifact@v2
+ with:
+ name: otp_prebuilt_no_chunks
+
+ - name: Compile Erlang
+ run: |
+ tar -xzf ./otp_src.tar.gz
+ cd otp
+ export ERL_TOP=`pwd`
+ export MAKEFLAGS="-j$(($(nproc) + 2)) -O"
+ export ERLC_USE_SERVER=true
+ ./otp_build configure --xcomp-conf=./xcomp/erl-xcomp-arm64-ios.conf --without-ssl
+ ./otp_build boot -a
+ ./otp_build release -a
+ - name: Package .xcframework
+ run: |
+ cd otp
+ export BUILD_ARCH=`./erts/autoconf/config.guess`
+ export LIBS=`find . -not -path "*${BUILD_ARCH}*" -path "*${TARGET_ARCH}*" -not -name "*_st.a" -not -name "*_r.a" -name "*.a" | awk '{ "basename " $1 | getline name; names[name] = $1 } END { for (n in names) { print names[n] }}'`
+ libtool -static -o liberlang.a $LIBS
+ xcodebuild -create-xcframework -output ./liberlang.xcframework -library liberlang.a
+
+ - name: Upload framework
+ uses: actions/upload-artifact@v2
+ with:
+ name: ios_framework_${{ env.TARGET_ARCH }}
+ path: otp/liberlang.xcframework
build-windows:
defaults:
@@ -42,11 +191,11 @@ jobs:
shell: wsl-bash {0}
env:
WXWIDGETS_VERSION: 3.1.4
- name: Build Erlang/OTP on Windows
+ name: Build Erlang/OTP (Windows)
runs-on: windows-2022
needs: pack
steps:
- - uses: Vampire/setup-wsl@v1
+ - uses: Vampire/setup-wsl@v1.2.1
with:
distribution: Ubuntu-18.04
@@ -102,7 +251,7 @@ jobs:
- name: Download source archive
uses: actions/download-artifact@v2
with:
- name: otp_git_archive
+ name: otp_prebuilt_no_chunks
- name: Compile Erlang
run: |
@@ -111,7 +260,7 @@ jobs:
tar -xzf ./otp_src.tar.gz
cd otp
export ERL_TOP=`pwd`
- export MAKEFLAGS=-j4
+ export MAKEFLAGS=-j$(($(nproc) + 2))
export ERLC_USE_SERVER=true
export ERTS_SKIP_DEPEND=true
eval `./otp_build env_win32 x64`
@@ -125,7 +274,7 @@ jobs:
- name: Upload installer
uses: actions/upload-artifact@v2
with:
- name: otp_prebuilt_win32
+ name: otp_win32_installer
path: otp/release/win32/otp*.exe
build:
@@ -135,7 +284,7 @@ jobs:
strategy:
matrix:
- type: [64-bit,32-bit,cross-compile,documentation]
+ type: [32-bit,cross-compile,clang]
fail-fast: false
steps:
@@ -143,87 +292,264 @@ jobs:
- name: Download source archive
uses: actions/download-artifact@v2
with:
- name: otp_git_archive
+ name: otp_prebuilt_no_chunks
- name: Docker login
uses: docker/login-action@v1
with:
registry: docker.pkg.github.com
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Calculate BASE image
- id: base
- run: |
- BASE_TAG=$(grep "^FROM" .github/dockerfiles/Dockerfile.${{ matrix.type }} | head -1 | awk '{print $2}')
- echo "::set-output name=BASE_TAG::${BASE_TAG}"
- .github/scripts/base-tag "${BASE_TAG}"
- - name: Pull BASE image
- run: docker pull ${{ steps.base.outputs.BASE_TAG }}
- - name: Build BASE image
- run: |
- docker build --pull --tag ${{ steps.base.outputs.BASE_TAG }} \
- --cache-from ${{ steps.base.outputs.BASE_TAG }} \
- --file .github/dockerfiles/Dockerfile.${{ steps.base.outputs.BASE_TYPE }} \
- --build-arg BASE=${{ steps.base.outputs.BASE }} .
+ - name: Build base image
+ run: .github/scripts/build-base-image.sh "${BASE_BRANCH}" ${{ matrix.type }}
- name: Build ${{ matrix.type }} image
run: |
+ mv otp_src.tar.gz .github/otp.tar.gz
docker build --tag otp --file .github/dockerfiles/Dockerfile.${{ matrix.type }} \
- --build-arg ARCHIVE=otp_src.tar.gz .
+ .github
- ## Smoke build tests
- - if: matrix.type == '32-bit' || matrix.type == '64-bit' || matrix.type == 'cross-compile'
- name: Run smoke test
- run: docker run -v $PWD/scripts:/scripts otp "cd /tests && /scripts/run-smoke-tests"
+ documentation:
+ name: Build and check documentation
+ runs-on: ubuntu-latest
+ needs: pack
+ steps:
+ - uses: actions/checkout@v2
+ ## Download docker images
+ - name: Docker login
+ uses: docker/login-action@v1
+ with:
+ registry: docker.pkg.github.com
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Download base build
+ if: needs.pack.outputs.BASE_BUILD == 're-built'
+ uses: actions/download-artifact@v2
+ with:
+ name: otp_docker_base
+ - name: Download otp build
+ uses: actions/download-artifact@v2
+ with:
+ name: otp-ubuntu-20.04
+ - name: Restore docker image
+ run: .github/scripts/restore-otp-image.sh "${BASE_BRANCH}"
- ## Documentation checks
- - if: matrix.type == 'documentation'
- name: Run xmllimt
- run: docker run otp "make xmllint"
- - if: matrix.type == 'documentation'
- name: Run html link check
- run: docker run -v $PWD/scripts:/scripts otp "/scripts/otp_html_check /otp doc/index.html"
- - if: matrix.type == 'documentation'
- name: Release docs to publish
- run: .github/scripts/release-docs.sh
- - if: matrix.type == 'documentation'
- name: Upload html documentation archive
+ ## Build pre-built tar with chunks
+ - name: Build doc chunks
+ run: |
+ docker build -t otp - <<EOF
+ FROM otp
+ RUN make docs DOC_TARGETS=chunks
+ EOF
+ - name: Build pre-built tar archives
+ run: |
+ docker run -v $PWD:/github otp \
+ "scripts/build-otp-tar -o /github/otp_clean_src.tar.gz /github/otp_src.tar.gz -b /buildroot/otp/ /buildroot/otp.tar.gz"
+ - name: Upload pre-built tar archive
+ uses: actions/upload-artifact@v2
+ with:
+ name: otp_prebuilt
+ path: otp_src.tar.gz
+ ## Build all the documentation
+ - name: Build documentation
+ run: |
+ docker build -t otp - <<EOF
+ FROM otp
+ RUN make docs
+ EOF
+ - name: Release docs to publish
+ run: |
+ docker run -v $PWD/:/github otp \
+ "make release docs release_docs && make release_docs DOC_TARGETS='man html pdf' RELEASE_ROOT=/github/docs"
+ sudo chown -R `whoami` docs
+ cd docs
+ tar czf ../otp_doc_man.tar.gz man
+ rm -rf man
+ tar czf ../otp_doc_html.tar.gz *
+ - name: Upload html documentation archive
uses: actions/upload-artifact@v2
with:
name: otp_doc_html
path: otp_doc_html.tar.gz
- - if: matrix.type == 'documentation'
- name: Upload man documentation archive
+ - name: Upload man documentation archive
uses: actions/upload-artifact@v2
with:
name: otp_doc_man
path: otp_doc_man.tar.gz
+ ## Documentation checks
+ - name: Run xmllint
+ run: docker run otp "make xmllint"
+ - name: Run html link check
+ run: docker run -v $PWD/:/github otp "scripts/otp_html_check /github/docs doc/index.html"
+ static:
+ name: Run static analysis
+ runs-on: ubuntu-latest
+ needs: pack
+ steps:
+ - uses: actions/checkout@v2
+ ## Download docker images
+ - name: Docker login
+ uses: docker/login-action@v1
+ with:
+ registry: docker.pkg.github.com
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Download base build
+ if: needs.pack.outputs.BASE_BUILD == 're-built'
+ uses: actions/download-artifact@v2
+ with:
+ name: otp_docker_base
+ - name: Download otp build
+ uses: actions/download-artifact@v2
+ with:
+ name: otp-ubuntu-20.04
+ - name: Restore docker image
+ run: .github/scripts/restore-otp-image.sh "${BASE_BRANCH}"
+ - name: Install clang-format
+ run: |
+ docker build -t otp - <<EOF
+ FROM otp
+ RUN sudo apt-get install -y clang-format
+ EOF
## Check formatting of cpp code
- - if: matrix.type == '64-bit'
- name: Check format
- run: docker run -v $PWD/scripts:/scripts otp "make format-check"
+ - name: Check format
+ run: docker run otp "make format-check"
## Run dialyzer
- - if: matrix.type == '64-bit'
- name: Run dialyzer
- run: docker run -v $PWD/scripts:/scripts otp "/scripts/run-dialyzer"
+ - name: Run dialyzer
+ run: docker run otp 'scripts/run-dialyzer'
- ## Build pre-built tar archives
- - if: matrix.type == '32-bit'
- name: Build pre-built tar archives
+ test:
+ name: Test Erlang/OTP
+ runs-on: ubuntu-latest
+ needs: [pack, changed-apps]
+ if: needs.changed-apps.outputs.changes != '[]'
+ strategy:
+ matrix:
+ # type: ${{ fromJson(needs.changed-apps.outputs.all) }}
+ type: ${{ fromJson(needs.changed-apps.outputs.changes) }}
+ # type: ["os_mon","sasl"]
+ fail-fast: false
+ steps:
+ - uses: actions/checkout@v2
+ ## Download docker images
+ - name: Download base build
+ if: needs.pack.outputs.BASE_BUILD == 're-built'
+ uses: actions/download-artifact@v2
+ with:
+ name: otp_docker_base
+ - name: Download otp build
+ uses: actions/download-artifact@v2
+ with:
+ name: otp-ubuntu-20.04
+ - name: Docker login
+ uses: docker/login-action@v1
+ with:
+ registry: docker.pkg.github.com
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Restore docker image
+ run: .github/scripts/restore-otp-image.sh "${BASE_BRANCH}"
+ - name: Run tests
+ id: run-tests
run: |
- docker run -v $PWD:/github otp \
- "scripts/build-otp-tar -o /github/otp_clean_src.tar.gz /github/otp_src.tar.gz -b /buildroot/otp/ /buildroot/otp.tar.gz"
- - if: matrix.type == '32-bit'
- name: Upload pre-built tar archive
+ set -x
+ mkdir $PWD/make_test_dir
+ APP="${{ matrix.type }}"
+ ## Need to specialize for epmd, emulator and debug
+ case "${APP}" in
+ emulator) DIR=erts/emulator/ ;;
+ epmd) DIR=erts/epmd ;;
+ debug) DIR=lib/os_mon; APP=os_mon; TYPE=debug ;;
+ *) DIR=lib/${{ matrix.type }} ;;
+ esac
+ sudo service apport stop
+ sudo bash -c "echo 'core.%p' > /proc/sys/kernel/core_pattern"
+ docker run --ulimit core=-1 --ulimit nofile=5000:5000 --pids-limit 512 \
+ -e CTRUN_TIMEOUT=90 -e SPEC_POSTFIX=gh \
+ -e EXTRA_ARGS="-ct_hooks cth_surefire [{path,\"/buildroot/otp/$DIR/make_test_dir/${{ matrix.type }}_junit.xml\"}]" \
+ -v "$PWD/make_test_dir:/buildroot/otp/$DIR/make_test_dir" \
+ otp "make TYPE=${TYPE} && make ${APP}_test TYPE=${TYPE}"
+ ## Rename os_mon to debug for debug build
+ if [ "$APP" != "${{ matrix.type }}" ]; then
+ mv make_test_dir/${APP}_test "make_test_dir/${{ matrix.type }}_test"
+ fi
+ - name: Cleanup tests
+ if: always()
+ run: |
+ rm -rf make_test_dir/otp || true
+ sudo bash -c "chown -R `whoami` make_test_dir && chmod -R +r make_test_dir"
+ tar czf ${{ matrix.type }}_test_results.tar.gz make_test_dir
+ - name: Upload test results
uses: actions/upload-artifact@v2
+ if: always()
with:
- name: otp_prebuilt
- path: otp_src.tar.gz
+ name: ${{ matrix.type }}_test_results
+ path: ${{ matrix.type }}_test_results.tar.gz
+
+ system-test:
+ name: Test Erlang/OTP (system)
+ runs-on: ubuntu-latest
+ if: always() # Run even if the need has failed
+ needs: test
+ steps:
+ - uses: actions/checkout@v2
+ - name: Docker login
+ uses: docker/login-action@v1
+ with:
+ registry: docker.pkg.github.com
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Download test results
+ uses: actions/download-artifact@v2
+ - run: mv otp-ubuntu-20.04/otp-ubuntu-20.04.tar.gz .
+ - name: Restore docker image
+ run: .github/scripts/restore-otp-image.sh "${BASE_BRANCH}"
+ - name: Merge test results
+ run: |
+ shopt -s nullglob
+ mkdir -p make_test_dir
+ for file in *_test_results/*.tar.gz; do
+ tar xzf $file
+ done
+ docker run -v $PWD/make_test_dir:/buildroot/otp/erts/make_test_dir otp \
+ "ct_run -refresh_logs /buildroot/otp/erts/make_test_dir"
+ - name: Run system tests
+ run: |
+ docker run --ulimit core=-1 --ulimit nofile=5000:5000 --pids-limit 512 \
+ -e CTRUN_TIMEOUT=90 -e SPEC_POSTFIX=gh \
+ -e EXTRA_ARGS="-ct_hooks cth_surefire [{path,\"/buildroot/otp/erts/make_test_dir/system_junit.xml\"}]" \
+ -e OTP_DAILY_BUILD_TOP_DIR=/buildroot/otp/erts/make_test_dir \
+ -v $PWD/make_test_dir:/buildroot/otp/erts/make_test_dir otp \
+ "make system_test"
+ - name: Cleanup tests
+ if: always()
+ run: |
+ rm -rf make_test_dir/otp || true
+ tar czf test_results.tar.gz make_test_dir
+ # Translate file="/buildroot/otp/lib/os_mon/make_test_dir/os_mon_test/cpu_sup_SUITE.erl"
+ # to file="lib/os_mon/test/cpu_sup_SUITE.erl"
+ sed -i -e 's:file="/buildroot/otp/:file=":g' \
+ -e 's:\(file="[^/]*/[^/]*/\)make_test_dir/[^/]*:\1test:g' \
+ -e 's:\(file="erts/\)make_test_dir/[^/]*:\1test:g' \
+ make_test_dir/*_junit.xml
+ - name: Upload test results
+ uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: test_results
+ path: test_results.tar.gz
+ - name: Upload Test Results
+ if: always()
+ uses: actions/upload-artifact@v2
+ with:
+ name: Unit Test Results
+ path: |
+ make_test_dir/*_junit.xml
## If this is a tag that has been pushed we do some release work
release:
name: Release Erlang/OTP
runs-on: ubuntu-latest
- needs: build
+ needs: documentation
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'erlang/otp'
steps:
## This step outputs the tag name and whether the tag is a release or patch
@@ -233,13 +559,10 @@ jobs:
id: tag
run: |
TAG=${GITHUB_REF#refs/tags/}
- IS_RELEASE=`$(echo $TAG | grep -E '^OTP-[0-9]+\.[0-9]+$' > /dev/null) \
- && echo "true" || echo "false"`
VSN=${TAG#OTP-}
echo "::set-output name=tag::${TAG}"
- echo "::set-output name=release::${IS_RELEASE}"
echo "::set-output name=vsn::${VSN}"
-
+
- uses: actions/checkout@v2
## Publish the pre-built archive and docs
@@ -261,18 +584,14 @@ jobs:
- name: Create pre-build and doc archives
run: .github/scripts/create-artifacts.sh artifacts ${{ steps.tag.outputs.tag }}
- - name: Build OTP Bundle
- if: steps.tag.outputs.release == 'true'
- run: |
- scripts/bundle-otp ${{ steps.tag.outputs.tag }}
-
## Create hash files
- name: Create pre-build and doc archives
run: |
shopt -s nullglob
cd artifacts
- md5sum {*.tar.gz,*.txt} > MD5.txt
- sha256sum {*.tar.gz,*.txt} > SHA256.txt
+ FILES=$(ls {*.tar.gz,*.txt})
+ md5sum $FILES > MD5.txt
+ sha256sum $FILES > SHA256.txt
- name: Upload pre-built and doc tar archives
uses: softprops/action-gh-release@v1
@@ -288,3 +607,13 @@ jobs:
GITHUB_TOKEN: ${{ secrets.TRIGGER_ERLANG_ORG_BUILD }}
run: |
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/erlang/erlang-org/actions/workflows/update-gh-cache.yaml/dispatches" -d '{"ref":"master"}'
+
+ event_file:
+ name: "Event File"
+ runs-on: ubuntu-latest
+ steps:
+ - name: Upload
+ uses: actions/upload-artifact@v2
+ with:
+ name: Event File
+ path: ${{ github.event_path }}
diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml
new file mode 100644
index 0000000000..b139d8232b
--- /dev/null
+++ b/.github/workflows/pr-comment.yaml
@@ -0,0 +1,126 @@
+name: Update PR details
+
+# read-write repo token
+# access to secrets
+on:
+ workflow_run:
+ workflows: ["Build and check Erlang/OTP"]
+ types:
+ - requested
+ - completed
+
+# Limit concurrency so that we don't get any races between parallel actions
+concurrency: pr-comment
+
+jobs:
+ pr-number:
+ runs-on: ubuntu-20.04
+ if: github.repository == 'erlang/otp'
+ outputs:
+ result: ${{ steps.pr-number.outputs.result }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: Fetch PR number
+ id: pr-number
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ run: |
+ git clone https://github.com/talentdeficit/jsx
+ (cd jsx && rebar3 compile)
+ .github/scripts/get-pr-number.es erlang/otp \
+ "${{ github.event.workflow_run.head_sha }}"
+
+ starting-tests:
+ runs-on: ubuntu-latest
+ needs: pr-number
+ if: github.event.action == 'requested' && needs.pr-number.outputs.result != ''
+ steps:
+ - uses: actions/checkout@v2
+ ## We create an initial comment with some useful help to the user
+ - uses: actions/github-script@v5
+ with:
+ script: |
+ const script = require('./.github/scripts/pr-comment.js');
+ return await script({github, context, state: 'starting',
+ pr_number: ${{ needs.pr-number.outputs.result }} });
+
+ finished-tests:
+ runs-on: ubuntu-20.04
+ needs: pr-number
+ ## Limit concurrency so that only one job deploys to erlang.github.io
+ concurrency: erlang.github.io-deploy
+ if: >-
+ github.event.action == 'completed' &&
+ needs.pr-number.outputs.result != '' &&
+ github.event.workflow_run.conclusion != 'skipped'
+ steps:
+ - uses: actions/checkout@v2
+ - name: Download and Extract Artifacts
+ id: extract
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ run: |
+ mkdir -p artifacts && cd artifacts
+
+ artifacts_url=${{ github.event.workflow_run.artifacts_url }}
+
+ gh api "$artifacts_url" --paginate -q '.artifacts[] | [.name, .archive_download_url] | @tsv' | while read artifact
+ do
+ IFS=$'\t' read name url <<< "$artifact"
+ if [ "$name" = "Unit Test Results" ] || [ "$name" = "Event File" ]; then
+ gh api $url > "$name.zip"
+ unzip -d "$name" "$name.zip"
+ fi
+ done
+
+ if [ -d "Unit Test Results" ]; then
+ echo "::set-output name=HAS_TEST_ARTIFACTS::true"
+ else
+ echo "::set-output name=HAS_TEST_ARTIFACTS::false"
+ fi
+
+ - uses: actions/checkout@v2
+ with:
+ token: ${{ secrets.ERLANG_TOKEN }}
+ repository: 'erlang/erlang.github.io'
+ path: erlang.github.io
+
+ - name: Publish CT Test Results
+ uses: EnricoMi/publish-unit-test-result-action@v1
+ if: steps.extract.outputs.HAS_TEST_ARTIFACTS == 'true'
+ with:
+ commit: ${{ github.event.workflow_run.head_sha }}
+ event_file: artifacts/Event File/event.json
+ event_name: ${{ github.event.workflow_run.event }}
+ check_name: "CT Test Results"
+ files: "artifacts/**/*.xml"
+
+ - name: Upload PR to github pages
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ run: |
+ git clone https://github.com/talentdeficit/jsx
+ (cd jsx && rebar3 compile)
+ mkdir -p "${GITHUB_WORKSPACE}/erlang.github.io/prs/"
+ .github/scripts/sync-github-prs.es erlang/otp \
+ "${GITHUB_WORKSPACE}/erlang.github.io/prs/" \
+ "${{ needs.pr-number.outputs.result }}"
+
+ - name: Deploy to github pages 🚀
+ uses: JamesIves/github-pages-deploy-action@v4.2.2
+ with:
+ token: ${{ secrets.ERLANG_TOKEN }}
+ branch: master # The branch the action should deploy to.
+ folder: erlang.github.io # The folder the action should deploy.
+ repository-name: erlang/erlang.github.io
+ single-commit: true
+
+ ## Append some usefull links and tips to the test results posted by
+ ## Publish CT Test Results
+ - uses: actions/github-script@v5
+ if: always()
+ with:
+ script: |
+ const script = require('./.github/scripts/pr-comment.js');
+ return await script({github, context, state: 'finished',
+ pr_number: ${{ needs.pr-number.outputs.result }} });
diff --git a/.github/workflows/sync-github-releases.yaml b/.github/workflows/sync-github-releases.yaml
index d3d3cf901c..af3245f1ba 100644
--- a/.github/workflows/sync-github-releases.yaml
+++ b/.github/workflows/sync-github-releases.yaml
@@ -1,6 +1,6 @@
name: Sync all github releases with erlang.org
-## Update the base image every day
+## Sync all github releases + prs every hour
on:
workflow_dispatch:
schedule:
@@ -10,22 +10,9 @@ on:
## Build base images to be used by other github workflows
jobs:
- # Wait for up to a minute for previous runs to complete, abort if not done by then
- pre-ci:
- if: github.repository == 'erlang/otp'
- runs-on: ubuntu-latest
- timeout-minutes: 1
- steps:
- - name: 'Block Concurrent Executions'
- uses: softprops/turnstyle@v1
- with:
- poll-interval-seconds: 10
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
sync-releases:
- needs: pre-ci
if: github.repository == 'erlang/otp'
+ concurrency: sync-github-releases
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@@ -34,6 +21,39 @@ jobs:
- name: Docker login
run: docker login https://docker.pkg.github.com -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
- name: Sync releases
+ env:
+ ERLANG_ORG_TOKEN: ${{ secrets.TRIGGER_ERLANG_ORG_BUILD }}
run: >
.github/scripts/sync-github-releases.sh ${{ github.repository }}
"Bearer ${{ secrets.GITHUB_TOKEN }}" "^[2-9][1-9]\\..*" 25m
+
+ sync-prs:
+ if: github.repository == 'erlang/otp'
+ concurrency: erlang.github.io-deploy
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ token: ${{ secrets.ERLANG_TOKEN }}
+ repository: 'erlang/erlang.github.io'
+ path: erlang.github.io
+ - uses: actions/checkout@v2
+ - name: Update PRs
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ run: |
+ git clone https://github.com/talentdeficit/jsx
+ (cd jsx && rebar3 compile)
+ rm -rf "${GITHUB_WORKSPACE}/erlang.github.io/.git"
+ mkdir -p "${GITHUB_WORKSPACE}/erlang.github.io/prs/"
+ touch "${GITHUB_WORKSPACE}/erlang.github.io/.nojekyll"
+ .github/scripts/sync-github-prs.es erlang/otp "${GITHUB_WORKSPACE}/erlang.github.io/prs/"
+
+ - name: Deploy to github pages 🚀
+ uses: JamesIves/github-pages-deploy-action@v4.2.2
+ with:
+ token: ${{ secrets.ERLANG_TOKEN }}
+ branch: master # The branch the action should deploy to.
+ folder: erlang.github.io # The folder the action should deploy.
+ repository-name: erlang/erlang.github.io
+ single-commit: true
diff --git a/.github/workflows/update-base.yaml b/.github/workflows/update-base.yaml
index 6ded954c2a..f043fab039 100644
--- a/.github/workflows/update-base.yaml
+++ b/.github/workflows/update-base.yaml
@@ -18,25 +18,29 @@ jobs:
strategy:
matrix:
type: [debian-base,ubuntu-base,i386-debian-base]
+ branch: [master, maint, maint-25]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ matrix.branch }}
- name: Docker login
- uses: docker/login-action@v1
+ uses: docker/login-action@v2
with:
registry: docker.pkg.github.com
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Calculate BASE image
- id: base
- run: |
- echo "::set-output name=BASE_TAG::docker.pkg.github.com/erlang/otp/${{ matrix.type }}"
- .github/scripts/base-tag "${{ matrix.type }}"
- name: Build base image
+ id: base
+ run: >-
+ BASE_TAG=docker.pkg.github.com/${{ github.repository_owner }}/otp/${{ matrix.type }}
+ BASE_USE_CACHE=false
+ .github/scripts/build-base-image.sh "${{ matrix.branch }}"
+ - name: Push master image
+ if: matrix.branch == 'master'
+ run: docker push ${{ steps.base.outputs.BASE_TAG }}:latest
+ - name: Tag and push base image
run: |
- docker build --pull --tag ${{ steps.base.outputs.BASE_TAG }} \
- --cache-from ${{ steps.base.outputs.BASE_TAG }} \
- --file .github/dockerfiles/Dockerfile.${{ steps.base.outputs.BASE_TYPE }} \
- --build-arg BASE=${{ steps.base.outputs.BASE }} .
- - name: Push base image
- run: docker push ${{ steps.base.outputs.BASE_TAG }}
+ docker tag ${{ steps.base.outputs.BASE_TAG }}:latest \
+ ${{ steps.base.outputs.BASE_TAG }}:${{ matrix.branch }}
+ docker push ${{ steps.base.outputs.BASE_TAG }}:${{ matrix.branch }}
diff --git a/.gitignore b/.gitignore
index 794d384b4d..c88056e46e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,9 @@ TAGS
# vscode
.vscode
+# IntelliJ IDEA
+.idea
+
autom4te.cache
*.beam
*.asn1db
@@ -46,11 +49,8 @@ i386-pc-solaris[0-9]*.[0-9]*
i386-unknown-freebsd[0-9]*.[0-9]*
x86_64-unknown-freebsd[0-9]*.[0-9]*
x86_64-unknown-openbsd[0-9]*.[0-9]*
-tile-tilera-linux-gnu
powerpc-unknown-linux-gnu
aarch64-unknown-linux-gnu
-i386-elf-ose
-powerpc-unknown-ose
# Mac OS X
a.out.dSYM/
@@ -59,8 +59,8 @@ a.out.dSYM/
*.pdb
local.static.config.cache
tcltk85_win32_bin.tar.gz
-erts/autoconf/win32.config.cache
-erts/autoconf/win64.config.cache
+make/autoconf/win32.config.cache
+make/autoconf/win64.config.cache
erts/emulator/obj/
erts/emulator/pcre/obj/
erts/emulator/pcre/win32/
@@ -92,8 +92,6 @@ lib/crypto/priv/obj/
lib/erl_interface/obj.md/
lib/erl_interface/obj.mdd/
lib/erl_interface/src/win32/
-lib/gs/priv/tcl/
-lib/gs/tcl/binaries/
lib/megaco/src/flex/win32/
lib/odbc/c_src/win32/
lib/odbc/priv/bin/odbcserver.exe
@@ -104,9 +102,6 @@ lib/os_mon/priv/obj/win32/
lib/runtime_tools/c_src/win32/
lib/runtime_tools/priv/lib/
lib/runtime_tools/priv/obj/
-lib/tools/bin/win32/
-lib/tools/c_src/win32/
-lib/tools/obj/win32/
lib/wx/c_src/win32/
lib/wx/priv/win32/
lib/wx/win32/
@@ -114,9 +109,6 @@ make/win32/
make/otp_built
make/otp_doc_built
-# OSE
-*.d
-
# Used by applications that run javadoc (e.g. ic).
JAVADOC-GENERATED
@@ -228,6 +220,8 @@ JAVADOC-GENERATED
/erts/test/install_SUITE_data/install_bin
/erts/test/autoimport_SUITE_data/erlang.xml
/erts/emulator/make_test_dir/
+/erts/epmd/make_test_dir/
+/erts/make_test_dir/
# common_test
@@ -244,7 +238,8 @@ JAVADOC-GENERATED
/lib/compiler/test/*_no_ssa_opt_SUITE.erl
/lib/compiler/test/*_post_opt_SUITE.erl
/lib/compiler/test/*_inline_SUITE.erl
-/lib/compiler/test/*_r21_SUITE.erl
+/lib/compiler/test/*_r23_SUITE.erl
+/lib/compiler/test/*_r24_SUITE.erl
/lib/compiler/test/*_no_module_opt_SUITE.erl
/lib/compiler/test/*_no_type_opt_SUITE.erl
/lib/compiler/test/*_dialyzer_SUITE.erl
@@ -282,35 +277,6 @@ JAVADOC-GENERATED
/lib/et/doc/html/*.png
-# gs
-
-/lib/gs/src/gstk_generic.hrl
-/lib/gs/contribs/ebin/*.gif
-/lib/gs/contribs/ebin/*.tool
-/lib/gs/doc/html/images/*.gif
-/lib/gs/tcl/win32/Makefile
-
-# hipe
-
-/lib/hipe/boot_ebin/hipe.app
-/lib/hipe/boot_ebin/hipe.appup
-/lib/hipe/main/hipe.hrl
-/lib/hipe/rtl/hipe_literals.hrl
-
-# ic
-
-/lib/ic/examples/pre_post_condition/m.hrl
-/lib/ic/examples/pre_post_condition/m_i.erl
-/lib/ic/examples/pre_post_condition/m_i.hrl
-/lib/ic/examples/pre_post_condition/m_NotAnInteger.erl
-/lib/ic/examples/pre_post_condition/oe_ex.erl
-/lib/ic/examples/pre_post_condition/oe_ex.hrl
-/lib/ic/priv/com/
-/lib/ic/priv/ic.jar
-/lib/ic/src/icparse.erl
-/lib/ic/doc/html/java
-/lib/ic/java_src/SKIP
-
# jinterface
/lib/jinterface/priv/OtpErlang.jar
@@ -331,12 +297,6 @@ JAVADOC-GENERATED
/lib/mnesia/test/Mnesia.*
/lib/mnesia/test/test_log*
-# otp_mibs
-
-/lib/otp_mibs/include/OTP*.hrl
-/lib/otp_mibs/mibs/v1/OTP*.mib.v1
-/lib/otp_mibs/priv/mibs/OTP*.bin
-
# os_mon
/lib/os_mon/include/OTP*.hrl
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 0000000000..74a5155ec3
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,7 @@
+image:
+ file: .github/dockerfiles/Dockerfile.ubuntu-base
+ context: .github
+vscode:
+ extensions:
+ - ms-vscode.cpptools
+ - erlang-ls.erlang-ls
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e7a69137c0..f78cef33db 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,7 +1,15 @@
# Contributing to Erlang/OTP
+1. [License](#license)
+2. [Reporting a bug](#reporting-a-bug)
+3. [Submitting Pull Requests](#submitting-pull-requests)
+ 1. [Fixing a bug](#fixing-a-bug)
+ 2. [Adding a new feature](#adding-a-new-feature)
+ 3. [Before you submit your pull request](#before-you-submit-your-pull-request)
+
## License
+```txt
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
@@ -26,18 +34,16 @@ By making a contribution to this project, I certify that:
sign-off) is maintained indefinitely and may be redistributed
consistent with this project or the open source license(s)
involved.
+```
-Erlang/otp is licensed under the
-Apache License 2.0
-
-As stated in: [LICENSE.txt](LICENSE.txt)
+See http://developercertificate.org/ for a copy of the Developer Certificate of Origin license.
-http://developercertificate.org/
+Erlang/OTP is licensed under the Apache License 2.0, as stated in: [LICENSE.txt](LICENSE.txt)
## Reporting a bug
-Report bugs at https://github.com/erlang/otp/issues. See [Bug reports](https://github.com/erlang/otp/wiki/Bug-reports)
-for more information.
+Report bugs at https://github.com/erlang/otp/issues.
+See [Bug reports](https://github.com/erlang/otp/wiki/Bug-reports) for more information.
## Submitting Pull Requests
@@ -47,7 +53,7 @@ Make sure you create a new branch for your pull request with `git checkout -b ne
Give the branch a short but descriptive name, like `stdlib/lists-length-fix`.
Never do your work directly on `maint` or `master`.
-## Fixing a bug
+### Fixing a bug
* In most cases, pull requests for bug fixes should be based on the `maint` branch.
There are exceptions, for example corrections to bugs that have been introduced in the `master` branch.
@@ -59,12 +65,11 @@ There are exceptions, for example corrections to bugs that have been introduced
* For applications without a test suite in the git repository, it would be appreciated if you provide a
small code sample in the commit message or email a module that will provoke the failure.
-## Adding a new feature
+### Adding a new feature
* In most cases, pull requests for new features should be based on the `master` branch.
-* It is recommended to discuss new features on
-[the erlang-questions mailing list](http://erlang.org/mailman/listinfo/erlang-questions),
+* It is recommended to discuss new features in the [erlang forums](https://erlangforums.com),
especially for major new features or any new features in ERTS, Kernel, or STDLIB.
* It is important to write a good commit message explaining **why** the feature is needed.
@@ -90,15 +95,17 @@ feature one or two releases beforehand.
can be included in OTP. Major changes or new features in ERTS, Kernel, or STDLIB will need an EEP or at least
a discussion on the mailing list.
-## Before you submit your pull request
+### Before you submit your pull request
* Make sure existing test cases don't fail. It is not necessary to run all tests (that would take many hours),
but you should at least run the tests for the application you have changed.
-See [Running tests](https://github.com/erlang/otp/wiki/Running-tests).
* Make sure the documentation builds and is according to the dtd. eg. `make xmllint` or `cd lib/stdlib/ && make xmllint`
* Make sure no new dialyzer warnings have been added. eg. `make dialyzer` or `cd lib/stdlib/ && make dialyzer`
* Make sure that github actions passes, if you go to https://github.com/$YOUR_GITHUB_USER/otp/actions you can enable github actions builds for you otp fork.
- * Note that this only builds Erlang/OTP, it does not run any tests.
+
+See the [Testing](https://github.com/erlang/otp/blob/master/HOWTO/TESTING.md) and
+[Development](https://github.com/erlang/otp/blob/master/HOWTO/DEVELOPMENT.md) howtos
+for details on how to use run tests and use the Erlang/OTP make system.
Make sure that your branch contains clean commits:
@@ -127,7 +134,7 @@ Check your coding style:
* In most code (Erlang and C), indentation is 4 steps. Indentation using only spaces is **strongly recommended**.
-### Configuring Emacs
+#### Configuring Emacs
If you use Emacs, use the Erlang mode, and add the following lines to `.emacs`:
diff --git a/HOWTO/DEVELOPMENT.md b/HOWTO/DEVELOPMENT.md
new file mode 100644
index 0000000000..2220d9ab71
--- /dev/null
+++ b/HOWTO/DEVELOPMENT.md
@@ -0,0 +1,597 @@
+# Developing Erlang/OTP
+
+The Erlang/OTP development repository is quite large and the make system
+contains a lot of functionality to help when a developing. This howto
+will try to showcase the most important features of the make system.
+
+The guide is mostly aimed towards development on a Unix platform, but
+most things should work also work using WSL on Windows. The guide also
+assumes that you are working in the git repositiory. Many of the
+scripts and tools described here are not available in the prebuilt tar
+archive that you can download for each release.
+
+*WARNING*: Only some of APIs mentioned in this guide are supported. This
+means that they may be removed or changed without prior notice, so do
+not depend on them in CI. For supported make targets see the
+[Install howto](INSTALL.md) and the [Testing howto](TESTING.md).
+
+The make system is not always as robust as one might like, so if for
+any reason something does not work, try doing a `git clean -Xfdq` and
+start from the beginning again. This normally only needs to be done when
+you jump in between different git branches, but it can a good thing to
+keep in mind whenever things do not work as you expect them to.
+
+*NOTE*: This instructions may vary for different versions of Erlang/OTP,
+so make sure to read the instructions for the version that you are working
+with.
+
+1. [Short version](#short-version)
+2. [Preparations](#preparations)
+ 1. [Faster builds](#faster-builds)
+3. [Configuring](#configuring)
+ 1. [Help](#help)
+4. [Building and testing](#building-and-testing)
+ 1. [Build and test a specific application](#build-and-test-a-specific-application)
+ 2. [Preloaded and Primary Bootstrap](#preloaded-and-primary-bootstrap)
+ 3. [Types and Flavors](#types-and-Flavors)
+ 4. [cerl](#cerl)
+ 5. [Static analysis](#static-analysis)
+5. [Running test cases](#running-test-cases)
+6. [Writing and building documentation](#writing-and-building-documentation)
+ 1. [Validating documentation](#validating-documentation)
+7. [Github Actions](#github-actions)
+ 1. [Debugging github actions failures](#debugging-github-actions-failures)
+8. [Using Docker](#using-docker)
+ 1. [Gidpod.io or VSCode dev container](#gitpod-io-or-vscode-dev-container)
+
+## Short version
+
+First make sure you have done all [preparations](#preparations) then
+do this:
+
+```bash
+git clone -b maint git@github.com:erlang/otp
+cd otp && export ERL_TOP=`pwd`
+./otp_build configure && make
+```
+
+When you have done changes, added tests or updated documentation, build and test like this:
+
+```bash
+cd lib/$APPLICATION_NAME
+make # Rebuid application
+make test # Run application tests
+make dialyzer # Run dialyzer
+make docs # Build the docs
+make xmllint # Run xmllint on the docs
+```
+
+Then enable [Github Actions](#github-actions) and push the changes to your fork
+of Erlang/OTP to check that you have not missed anything.
+
+## Preparations
+
+Before you start working you need to clone the Erlang/OTP git repository
+and install any dependencies that you do not have. See
+[Required Utilities](INSTALL.md#required-utilities) and
+[Optional Utilities](INSTALL.md#optional-utilities) in [INSTALL.md](INSTALL.md)
+for a list of utilities to install. (Windows has its own [INSTALL Guide](INSTALL-WIN32.md)
+with its own [Required Utilities](INSTALL-WIN32.md#tools-you-need-and-their-environment)).
+
+Then you need to set `ERL_TOP` to point at the repository you are developing in.
+Not all make commands needs this environment variable set, but many do so it is
+good to get into the habit of always setting it.
+
+```bash
+cd /path/to/repository/otp
+export ERL_TOP=`pwd`
+```
+
+Make sure that you have read the [Contributing to Erlang/OTP](../CONTRIBUTING.md)
+guide if you intend to make a contribution to Erlang/OTP.
+
+### Faster builds
+
+Both `configure` and `make` take advantage of running in parallel if told to,
+so in order to speed up your development environment make sure to set:
+
+```bash
+## Change N to be at least the number of cores or hyper-threads available
+export MAKEFLAGS=-jN
+```
+
+The Erlang compiler can be run using a [Compile Server](https://www.erlang.org/doc/man/erlc.html#compile-server),
+this can cut from the total build time of Erlang/OTP by quite a lot,
+especially if you have a relatively slow machine.
+To enable set this environment variable:
+
+```bash
+export ERLC_USE_SERVER=true
+```
+
+Re-building all application in Erlang/OTP can take a while so it is possible
+to build only a subset of the applications. This is done by setting either
+`OTP_SMALL_BUILD` or `OTP_TINY_BUILD` to `true` when doing make at the top
+level. However, the simplest way is probably to just use the `./otp_build`
+wrapper that takes the options `-t` (tiny) or `-a` (all) and defaults to
+a small build.
+
+```bash
+# You need to have done ./configure before calling make or boot.
+OTP_TINY_BUILD=true make ## Equivalent to ./otp_build boot -t
+OTP_SMALL_BUILD=true make ## Equivalent to ./otp_build boot
+./otp_build boot -a ## Equivalent to make
+```
+
+## Configuring
+
+You run configure by issuing the command:
+
+```bash
+./otp_build configure
+```
+
+On all operating systems except Windows you can also just run:
+
+```bash
+./configure
+```
+
+If you change any `Makefile`s you will need to re-run configure.
+If you update any `configure.ac` scripts you need to
+[update the configure scripts](INSTALL.md#updating-configure-scripts).
+
+### Help
+
+The toplevel configure will give help about the features that it provides.
+To get a full list of all features you need to use:
+
+```bash
+./configure --help=r
+```
+
+There is documentation for what most of the options mean in the
+[INSTALL.md](INSTALL.md#Configuring) howto.
+
+## Building and testing
+
+After you have done configure, you can do
+
+```bash
+make
+```
+
+on the top of this repository. That will compile all of Erlang/OTP.
+
+You can also build a specific application:
+
+```bash
+make stdlib
+make common_test
+```
+
+These make commands do not manage any dependencies, so if an application needs
+something from another you need to make sure that it is built. It is therefore
+good practice to first build all of Erlang/OTP and then build just the one that
+you are updating.
+
+You can also run tests from the top:
+
+```bash
+make test # Run all tests, takes a **very** long time
+make stdlib_test # Run only stdlib tests, takes less time
+ # Run only lists_SUITE, takes even less time
+make stdlib_test ARGS="-suite lists_SUITE"
+ # Run only member testcase in lists_SUITE
+make stdlib_test ARGS="-suite lists_SUITE -case member"
+```
+
+See [ct_run](https://www.erlang.org/doc/man/ct_run.html#) for a list of all options
+that you can pass to ARGS.
+
+You can run static analysis test:
+
+```bash
+make dialyzer # Checks all of Erlang/OTP source code
+make xmllint # Checks all documentation for xmllint errors
+```
+
+Most of the above targets also works for a "phony" target called `emulator` that
+represents erts and all its tools. So you can do this:
+
+```bash
+make emulator # Build erts, epmd etc
+make emulator_test # Run all emulator tests
+```
+
+If you want to pass a run-time flag to the emulator running the tests you can
+use the `ERL_ARGS` flags to `make test`. For example if you want to run tests
+using [off heap message queue data](https://www.erlang.org/doc/man/erlang.html#process_flag_message_queue_data)
+for all process you would do this:
+
+```bash
+ERL_ARGS="+hmqd off_heap" make emulator_test
+```
+
+### Build and test a specific application
+
+You can also build the application from within itself. Like this:
+
+```bash
+cd lib/stdlib && make
+```
+
+Each application has a bunch of make targets that you can use.
+
+```bash
+make # build all source for this application
+make test # run all tests for this application
+make test ARGS="-suite lists_SUITE" # run the lists_SUITE tests
+make dialyzer # run dialyzer for this application
+make docs # build all docs for this application
+make docs DOC_TARGETS="html" # build html docs for this application
+make xmllint # run xmllint on the docs for this application
+```
+
+If you want to view what the documentation looks like for only your application
+you can do this:
+
+```bash
+(cd doc/src && make local_docs)
+```
+
+and then view `doc/html/index.html`.
+
+### Preloaded and Primary Bootstrap
+
+The Erlang code loader and compiler are written in Erlang, so in order to
+[bootstrap](https://en.wikipedia.org/wiki/Bootstrapping_(compilers))
+the system a number of compiled `.beam` files are commited into the
+Erlang/OTP git repository.
+
+The Erlang code located in [erts/preloaded/src](../erts/preloaded/src)
+is compiled into the VM and used to load enough code so that the code
+loader in the `kernel` application can be loaded. If you update any of
+that code you need to do a special preloaded update for the changes to
+take effect. This is done like this:
+
+```bash
+./otp_build update_preloaded [--no-commit]
+make # Need to rebuild system after the preloaded has been updated
+```
+
+You need to have a working Erlang compiler in your path for this to work.
+In order to be able to compile the Erlang/OTP source code, there also needs
+to be a basic Erlang compiler committed into git. This is what is called the
+primary bootstrap. It is quite rare that you need to update this, but if you
+are extending the Erlang language and would like to use the new extensions
+in the Erlang/OTP source code you it needs to be updated. As an example, when
+we added `maps` to Erlang we first needed to have a commited primary bootstrap
+that could compile code with maps, before we actually could use maps anywhere.
+To update the primary bootstrap you do like this:
+
+```bash
+./otp_build update_primary [--no-commit]
+```
+
+*NOTE*: When submitting a PR to Erlang/OTP you will be asked to not include
+any commit updating preloaded or the primary bootstrap. This is because we
+cannot review the contents of binary files and thus cannot make sure they do
+not contain any malicious data.
+
+### Types and Flavors
+
+Erlang can be built using different types and flavors. Mostly the types and
+flavors change how the Erlang VM itself is built, but some also effect how
+application are built. Some of the types/flavors are:
+
+* Types
+ * opt (default)
+ * debug
+ * lcnt
+ * valgrind
+ * asan
+ * gcov
+* Flavor
+ * emu
+ * jit (default if available)
+
+To build using a type and or flavor you just pass it as a variable to make.
+For example:
+
+```bash
+make TYPE=debug
+make FLAVOR=emu
+make TYPE=lcnt FLAVOR=emu
+```
+
+As you can see it is possible to combine type and flavor to create many different
+versions of Erlang. You can then run these different versions by passing the
+`-emu_type` and/or `-emu_flavor` flags to `erl`. That is:
+
+```bash
+erl -emu_type lcnt
+erl -emu_flavor emu -emu_type debug
+```
+
+When running valgrind, asan or gcov those tools create special output files that
+need to be processed. To work with these files there is a special `erl` program
+called `cerl` that is only available in the source tree. You can read more about
+it in the [cerl section](#cerl) later in this guide.
+
+If you want to run the tests with a special flavor or type, the easiest way to
+do that is by setting the TYPE or FLAVOR when calling make. For example if you
+want to run the emulator tests using the debug emulator you can do it like this:
+
+```bash
+make emulator_test TYPE=debug
+```
+
+*NOTE*: Before you run tests using a TYPE or FLAVOR you need to build the **entire**
+Erlang/OTP repo using that TYPE or FLAVOR. That is `make TYPE=debug` for the example
+above.
+
+### cerl
+
+`cerl` is a program available in `$ERL_TOP/bin/` that has a number of features
+useful when developing the Erlang run-time system. It work just as normal `erl`,
+but accepts a couple of extra command line switches. Any other command line arguments
+passed to `cerl` will be passed on the Erlang as normal. The extra command line
+switches are:
+
+* -debug
+ * Start a debug run-time system.
+* -lcnt
+ * Start a lock count run-time system.
+* -valgrind
+ * Start valgrind with the correct settings and use the `valgrind` [type](types-and-flavors).
+ * Set environment variable `VALGRIND_LOG_XML` to true if want xml valgrind logs.
+ * Set environment variable `VALGRIND_LOG_DIR` to where you want valgrind logs.
+ * Set environment variable `VALGRIND_MISC_FLAGS` for any extra valgrind flags you want to pass.
+* -asan
+ * Start [Clang Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
+ with the the correct settings and use the `asan` [type](types-and-flavors).
+ * Set environment variable `ASAN_LOG_DIR` to where you want the logs.
+ * Set environment variable `ASAN_OPTIONS` for any extra asan options you want to pass.
+* -gcov
+ * Start a gcov run-time system.
+* -gdb
+ * Start an Emacs gdb debugging session. Can be combined with -debug.
+* -core /path/to/core/file
+ * Start an Emacs gdb debugging session for the core specified.
+* -rgdb
+ * Start a gdb debugging session in the current terminal. Can be combined with -debug.
+* -rcore /path/to/core/file
+ * Start a gdb debugging session in the current terminal for the core specified.
+* -lldb
+ * Start a lldb debugging session in the current terminal.
+* -rr
+ * Start Erlang under [rr](https://rr-project.org/) to record all events. Can be combined with -debug.
+* -rr replay [session]
+ * Load a recording session using `rr replay`, if no session is specified the latest run session is laoded.
+
+If you want to run tests using `cerl` (for example if you want to run asan on
+the nif_SUITE in emulator) you cannot use the `make test` approach to testing
+as that uses `ct_run` under the hood and `ct_run` does not support customizing
+the emulator start script. Instead you need to use the approach described in
+[Run tests with Address Sanitizer](INSTALL.md#run-tests-with-address-sanitizer).
+
+
+### Static analysis
+
+From the top level of Erlang/OTP you can run:
+
+```bash
+make xmllint
+make dialyzer
+make format-check
+```
+
+This will check that the documentation is correct and that there are no
+dialyzer errors. See also [Validating documentation](#validating-documentation)
+for more details.
+
+## Running test cases
+
+There is a detailed description about how to run tests in [TESTING.md](TESTING.md).
+
+## Writing and building documentation
+
+Most of the Erlang/OTP documentation is written in XML files located in
+`lib/$APPLICATION_NAME/doc/src`. The format of the XML is described in the
+[ErlDocgen User's Guide](https://www.erlang.org/doc/apps/erl_docgen/users_guide.html).
+
+There is also some documentation that is written using [edoc](https://www.erlang.org/doc/man/edoc.html).
+
+To view the documentation the simplest way is to release it. *NOTE*: The Erlang/OTP
+repository needs to have been [built](#building-and-testing) before you can build
+the documentation.
+
+```bash
+make release_docs
+```
+
+and then you can view `release/*/doc/index.html` in your favourite browser and
+make sure that it looks nice.
+
+This takes a while though and to speed up the edit-view cycle you can either
+limit what parts of the documentation is built using `DOC_TARGETS`. For example:
+
+```bash
+make release_docs DOC_TARGETS=html
+```
+
+The different `DOC_TARGETS` built are `html`, `man`, `pdf` and `chunks`.
+
+You can also build the docs only for a single application. For example:
+
+```bash
+cd lib/stdlib/doc/src && make local_docs DOC_TARGETS=html
+```
+
+and then view the results at `lib/stdlib/doc/html/index.html`.
+
+### Validating documentation
+
+In order to make sure that the documentation is correct you need to also
+validate it. Just building the documentation does not mean that it is
+correct. There are two steps that you need to do in order to validate
+the docs.
+
+First run the `xmllint`. This makes sure that the xml follows the
+[Erlang/OTP dtd](https://www.erlang.org/doc/apps/erl_docgen/overview.html)
+and does some extra checks to make sure all links are correct.
+
+You run the xmllint like this:
+
+```bash
+make xmllint # Run it at the top level
+cd lib/stdlib && make xmllint # Run it for only a single application
+```
+
+When the xml has been verified you also need to make sure that there
+are no broken links in the documentation. This is done by running
+[`otp_html_check`](https://github.com/erlang/otp/blob/master/scripts/otp_html_check).
+
+You run `otp_html_check` like this:
+
+```bash
+make release_docs DOC_TARGETS="html pdf" # First we need to release the pdf+html docs
+$ERL_TOP/scripts/otp_html_check $(pwd)/release/$($ERL_TOP/erts/autoconf/config.guess) doc/index.html
+```
+
+The output of `otp_html_check` will print a list of broken links and anchors, for example:
+
+```text
+**** Files not used (that I can see)
+....
+
+**** Broken links
+
+Broken Link: /lib/kernel-8.3.1/doc/html/inet.html -> "/lib/kernel-8.3.1/doc/html/files.html"
+
+**** References to missing anchors
+
+Missing Anchor: "/lib/kernel-8.3.1/doc/html/files.html#native_name_encoding-0" from /lib/kernel-8.3.1/doc/html/inet.html
+Missing Anchor: "/lib/kernel-8.3.1/doc/html/inet.html#type-ip_addres" from /lib/kernel-8.3.1/doc/html/inet.html
+```
+
+The `Files not used` section is mostly used to debug the documentation build
+process, so it can be ignored most of the time. The other to sections should
+however be empty for the documentation to be correct.
+
+All this validation is also done by [Github Actions](#github-actions).
+
+## Github Actions
+
+Erlang/OTP uses [Github Actions](https://github.com/features/actions) as a
+preliminary CI to check that nothing fundamental has been broken by the change.
+
+You can enable Github Actions on your own github fork in order to run the tests
+before opening a PR to the main repository.
+
+Github Actions does too many checks to list them all but the primary ones are:
+
+* Build on Ubuntu Linux and Windows
+* Cross build to Debian Linux on powerpc and iOS
+* Build and validate documentation
+* Run dialyzer on all of Erlang/OTP
+* Run the tests of the changed application
+
+Each run generates a bunch of artifacts. The most important ones are:
+
+* `test_results`
+ * An archive containing all the logs from all tests that have been run.
+ Navigate to `make_test_dir/ct_logs/index.html` within the archive to
+ view the Common Test summary of the tests.
+* `otp_win32_installer`
+ * A windows installer with the changes you have made.
+* `otp_doc_html`
+ * The HTML docs with the changes you have made.
+
+### Debugging Github Actions failures
+
+Debugging Github Actions is at best a very time-consuming endevour. So if there
+is an error in the build or tests that you don't easily understand I would
+recommend that you try to reproduce it locally.
+
+This is of course not always possible, for instance if it only fails on Windows
+and you do not have access to a Windows machine, but it may the worth it as the
+leadtime of re-running a test is roughly 30 minutes. See the [other sections of
+this guide](#developing-erlang-otp) for details on how to build and run tests
+locally.
+
+If testcases fail when running Github Actions, it is best to start by inspecting
+the logs of the test runs. The logs are attached to the finished run as
+`test_results`. You will find more details about why a testcase failed in
+the logs.
+
+## Using Docker
+
+In order to get a reproduceable environment for building and testing you can use
+[docker](https//www.docker.com). If you are not familiar with how to use it I
+would recommend [reading up a bit](https://www.docker.com/get-started) and trying
+some simple examples yourself before using it to build and test Erlang/OTP.
+
+There is a pre-built ubuntu base image available on github, but you can also
+build it locally if you want to.
+
+Using the pre-built base you build an image like this:
+
+```bash
+docker login docker.pkg.github.com
+git archive --prefix otp/ -o .github/otp.tar.gz HEAD
+docker build -t my_otp_image -f .github/dockerfiles/Dockerfile.64-bit .github/
+```
+
+This will fetch the ubuntu base image and build a 64-bit Erlang/OTP. You need to
+[login to the github container registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry)
+in order to fetch the base image. If you want to build the base image locally
+you can do that like this:
+
+```bash
+docker built -t docker.pkg.github.com/erlang/otp/ubuntu-base \
+ --build-arg BASE=ubuntu --build-arg USER=otptest --build-arg uid=$(id -u) \
+ --build-arg GROUP=uucp --build-arg gid=$(id -g) \
+ -f .github/dockerfiles/Dockerfile.ubuntu-base .github/
+```
+
+Which approach is fastest depends on the speed of your internet connection.
+
+When you have built the docker image you can run tests in it like this:
+
+```bash
+docker run my_otp_image "make stdlib_test"
+```
+
+or if you want to persist the test results outside the container:
+
+```bash
+mkdir -m 777 make_test_dir ## The 777 mode is needed to avoid permission problems
+docker run --init -v $PWD/make_test_dir:/buildroot/otp/lib/stdlib/make_test_dir \
+ my_otp_image "make stdlib_test"
+```
+
+The Common Test logs will be placed in `make_test_dir/ct_logs`.
+
+### Gidpod.io or VSCode dev container
+
+This git repository is also prepared to run using [Gitpod](https://gitpod.io/) or
+[VSCode Devcontainer](https://code.visualstudio.com/docs/remote/containers).
+
+The support for these environments is very early so it will be a bit unstable.
+
+To access the gitpod for Erlang/OTP you just navigate to
+[https://gitpod.io/#https://github.com/erlang/otp](https://gitpod.io/#https://github.com/erlang/otp).
+
+When using a VSCode dev container, you only need to open [VSCode](https://code.visualstudio.com/)
+in the Erlang/OTP repository and you should get a popup that asks if you want to
+run in a dev container.
+
+The gitpod and dev container both use the base ubuntu image built in [Using Docker](#using-docker).
+So it should be possible to run all tests inside the containers with all test
+dependencies available.
+
+*WARNING*: Using VSCode dev container on macOS can be very slow because of limitations
+in the filesystem. So I would recommend either using gitpod or just work locally without
+the dev container on macOS.
diff --git a/HOWTO/INSTALL-ANDROID.md b/HOWTO/INSTALL-ANDROID.md
index 4ca225ba3b..a4bca5ffed 100644
--- a/HOWTO/INSTALL-ANDROID.md
+++ b/HOWTO/INSTALL-ANDROID.md
@@ -4,7 +4,7 @@ Cross Compiling Erlang/OTP - ANDROID
Introduction
------------
-This document describes how to cross compile Erlang/OTP to Android/Rasberry Pi platforms.
+This document describes how to cross compile Erlang/OTP to Android/Raspberry Pi platforms.
### Download and Install the Android NDK ###
@@ -135,7 +135,7 @@ Use the following commands when compiling an x86 64-bit version.
$ make RELEASE_ROOT=/path/to/release/erlang release
-### Target Deployment for Rasberry Pi ###
+### Target Deployment for Raspberry Pi ###
Make a tarball out of /path/to/release/erlang and copy it to target
device. Extract it and install.
diff --git a/HOWTO/INSTALL-CROSS.md b/HOWTO/INSTALL-CROSS.md
index f2494e6f1c..d603986e34 100644
--- a/HOWTO/INSTALL-CROSS.md
+++ b/HOWTO/INSTALL-CROSS.md
@@ -57,9 +57,7 @@ cross compiling.
The build system, including cross compilation configuration variables used,
may be subject to non backward compatible changes without prior notice.
Current cross build system has been tested when cross compiling some Linux/GNU
-systems, but has only been partly tested for more esoteric platforms. The
-VxWorks example file is highly dependent on our environment and is here more
-or less only for internal use.
+systems, but has only been partly tested for more esoteric platforms.
### Patches ###
@@ -130,11 +128,11 @@ be built.
`<HOST>` is the host/target system that you build for. It does not have to be
a full `CPU-VENDOR-OS` triplet, but can be. The full canonicalized
`CPU-VENDOR-OS` triplet will be created by executing
-`$ERL_TOP/erts/autoconf/config.sub <HOST>`. If `config.sub` fails, you need
+`$ERL_TOP/make/autoconf/config.sub <HOST>`. If `config.sub` fails, you need
to be more specific.
`<BUILD>` should equal the `CPU-VENDOR-OS` triplet of the system that you
-build on. If you execute `$ERL_TOP/erts/autoconf/config.guess`, it will in
+build on. If you execute `$ERL_TOP/make/autoconf/config.guess`, it will in
most cases print the triplet you want to use for this.
The use of `<HOST>` and `<BUILD>` values that differ will trigger cross
@@ -265,7 +263,7 @@ have to be passed one way or the other; either by using `erl_xcomp_host=<HOST>`
and `erl_xcomp_build=<BUILD>` in the configuration file, or by using the
`--host=<HOST>`, and `--build=<BUILD>` command line arguments.
-`otp_build configure` will configure both for the boostrap system on the
+`otp_build configure` will configure both for the bootstrap system on the
build machine and the cross host system.
(10)
@@ -344,15 +342,15 @@ cross compilation using `$ERL_TOP/otp_build configure`.
`--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`,
+ `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build`. If set to `guess`,
the build system will be guessed using
- `$ERL_TOP/erts/autoconf/config.guess`.
+ `$ERL_TOP/make/autoconf/config.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_TOP/make/autoconf/config.sub $erl_xcomp_host`.
* `erl_xcomp_configure_flags` - Extra configure flags to pass to the
`configure` script.
diff --git a/HOWTO/INSTALL-IOS.md b/HOWTO/INSTALL-IOS.md
new file mode 100644
index 0000000000..3ec368ecc7
--- /dev/null
+++ b/HOWTO/INSTALL-IOS.md
@@ -0,0 +1,119 @@
+Cross Compiling Erlang/OTP - IOS
+====================================
+
+Introduction
+------------
+
+This document describes how to cross compile Erlang/OTP to iOS platforms. iOS has the peculiarity that it does not support the creation of shared libraries. So the build process needs to be amended to generate statically linkable and executable Erlang binaries.
+
+### Get Xcode Tools ###
+
+iOS binaries can only be cross-compiled from Apple macOS computers. For compilation the Xcode tools must be used.
+### Environment Variables ###
+
+In order to inform the build system that it should generate the static linkable `libbeam.a` add the following environment variable during configuration and compilation:
+
+ $ export RELEASE_LIBBEAM=yes
+
+### Configure Erlang/OTP ###
+
+ To build without without OpenSSL support, run `configure` like this:
+
+ $ ./otp_build configure \
+ --xcomp-conf=./xcomp/erl-xcomp-arm64-ios.conf \
+ --without-ssl
+
+
+To build with OpenSSL statically linked, run `configure` like this (note that 1.1.1k works, but needs a manual patch in ios cross build config to include engines):
+
+ $ ./otp_build configure \
+ --xcomp-conf=./xcomp/erl-xcomp-arm64-ios.conf \
+ --with-ssl=/path/to/libcrypto.a \
+ --disable-dynamic-ssl-lib
+
+
+### Compile Erlang/OTP ###
+
+ $ ./otp_build boot
+
+### Linking a binary with your App ###
+
+To use the resulting `libbeam.a` it needs to be packaged into a Xcode `.xcframework` package together with all other required `.a` files. These include:
+
+* `libbeam.a`
+* `libz.a`
+* `libcrypto.a`
+
+Basically all .a files that have been generated by the build.
+
+One way of creating a combined archive out of all of these is to use `libtool`:
+
+ $ libtool -static -o liberlang.a /Path/to/libbeam.a /Path/to/....a
+
+This list should also include static nifs you want to include:
+
+Finally packaging the archive into a `.xcframework` directory:
+
+ $ xcodebuild -create-xcframework -output ./liberlang.xcframework -library liberlang.a
+
+If you're building for multiple iOS targets (e.g. simulator and phone):
+
+ $ xcodebuild -create-xcframework -output ./liberlang.xcframework -library /Path/to/phonelib/liberlang.a -library /Path/to/simulatorlib/liberlang.a
+
+## Starting Erlang
+
+To execute erlang from within an iOS project a native C/C++ wrapper is needed that can call the function:
+
+ erl_start(int argc, char *argv[]);
+
+An example call could look like this:
+
+ $ const char *args[] = {
+ "my_main",
+ "-sbwt",
+ "none",
+ "--",
+ "-root",
+ root_dir.c_str(),
+ "-progname",
+ "erl",
+ "--",
+ "-home",
+ home_dir.c_str(),
+ "--",
+ "-kernel",
+ "shell_history",
+ "enabled",
+ "--",
+ "-start_epmd",
+ "false",
+ "-elixir",
+ "ansi_enabled",
+ "true",
+ "-noshell",
+ "-s",
+ "elixir",
+ "start_cli",
+ "-mode",
+ "interactive",
+ "-config",
+ config_path.c_str(),
+ "-boot",
+ boot_path.c_str(),
+ "-boot_var",
+ "RELEASE_LIB",
+ lib_path.c_str(),
+ "--",
+ "--",
+ "-extra",
+ "--no-halt",
+ };
+
+ erl_start(sizeof(args) / sizeof(args[0]), (char **)args);
+
+### Reference Example
+
+At the time of writing (October 2021) there is a full reference iOS application available at https://github.com/elixir-desktop/ios-example-app.
+
+An implementation of the native wrapper can be viewed at https://github.com/elixir-desktop/ios-example-app/blob/main/native-lib.cpp.
+
diff --git a/HOWTO/INSTALL-RASPBERRYPI3.md b/HOWTO/INSTALL-RASPBERRYPI3.md
index 810195c63a..a32bad052b 100644
--- a/HOWTO/INSTALL-RASPBERRYPI3.md
+++ b/HOWTO/INSTALL-RASPBERRYPI3.md
@@ -257,9 +257,9 @@ Uncheck option:
(20)
- $ wget http://zlib.net/zlib-1.2.11.tar.gz
- $ tar xf zlib-1.2.11.tar.gz
- $ pushd zlib-1.2.11
+ $ wget http://zlib.net/zlib-1.2.12.tar.gz
+ $ tar xf zlib-1.2.12.tar.gz
+ $ pushd zlib-1.2.12
$ CHOST=armv8-rpi3-linux-gnueabihf ./configure --prefix=/Volumes/xtools-build-env/local
$ make
$ make install
diff --git a/HOWTO/INSTALL-WIN32-OLD.md b/HOWTO/INSTALL-WIN32-OLD.md
index 4722771202..d2a0125ac7 100644
--- a/HOWTO/INSTALL-WIN32-OLD.md
+++ b/HOWTO/INSTALL-WIN32-OLD.md
@@ -47,7 +47,7 @@ to make the Erlang/OTP distribution for Windows better. Please submit
any suggestions or patches to our [git project] [2] 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, so that your changes
+same makefiles are used on Unix, 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
@@ -728,7 +728,7 @@ Lets get into more detail:
2. `$ ./otp_build boot -a` - This uses the bootstrap directory (shipped
with the source, `$ERL_TOP/bootstrap`) to build a complete OTP
system. When this is done you can run erl from within the source tree;
- just type `$ERL_TOP/bin/erl` and you whould have the prompt.
+ just type `$ERL_TOP/bin/erl` and you would have the prompt.
3. `$ ./otp_build release -a` - Builds a commercial release tree from the
source tree. The default is to put it in `$ERL_TOP/release/win32`. You can
diff --git a/HOWTO/INSTALL-WIN32.md b/HOWTO/INSTALL-WIN32.md
index c17cfbe5a3..4ad0159bcd 100644
--- a/HOWTO/INSTALL-WIN32.md
+++ b/HOWTO/INSTALL-WIN32.md
@@ -31,7 +31,7 @@ to make the Erlang/OTP distribution for Windows better. Please submit
any suggestions or patches to our [git project] [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, so that your changes
+same makefiles are used on Unix, 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
@@ -143,7 +143,7 @@ the different tools:
You need this to build crypto, ssh and ssl libs.
We recommend v1.1.1d or later.
- There are prebuilt avaiable binaries, which you can just
+ There are prebuilt available binaries, which you can just
download and install, available here:
URL: <http://wiki.openssl.org/index.php/Binaries>
diff --git a/HOWTO/INSTALL.md b/HOWTO/INSTALL.md
index e7fb4ad27a..e4e343aca3 100644
--- a/HOWTO/INSTALL.md
+++ b/HOWTO/INSTALL.md
@@ -47,7 +47,6 @@ Build the same way as when building the unpacked tar file.
* An `install` program that can take multiple file names.
-
Optional Utilities
------------------
@@ -85,8 +84,6 @@ also find the utilities needed for building the documentation.
Further instructions on wxWidgets, read [Building with wxErlang][].
-
-
### Building Documentation ###
* `xsltproc` -- A command line XSLT processor.
@@ -98,8 +95,6 @@ also find the utilities needed for building the documentation.
* `fop` -- Apache FOP print formatter (requires Java). Can be downloaded
from <http://xmlgraphics.apache.org/fop>.
-
-
How to Build and Install Erlang/OTP
-----------------------------------
@@ -137,14 +132,12 @@ set. If you get errors when building, try setting the LANG variable:
$ export LANG=C # Assuming bash/sh
-
### Building ###
Build the Erlang/OTP release.
$ make
-
### Testing ###
Before installation you should test whether your build is working properly
@@ -173,13 +166,11 @@ The following command will install the release on your system.
$ make install
-
### Running ###
You should now have a working release of Erlang/OTP!
Jump to [System Principles][] for instructions on running Erlang/OTP.
-
### How to Build the Documentation ###
Make sure you're in the top directory in the source tree.
@@ -396,11 +387,10 @@ Some of the available `configure` options are:
that do not support dynamic linking of libraries it is possible to statically
link nifs and drivers with the main Erlang VM binary. This is done by passing
a comma separated list to the archives that you want to statically link. e.g.
- `--enable-static-nifs=/home/$USER/my_nif.a`. The path has to be absolute and the
- name of the archive has to be the same as the module, i.e. `my_nif` in the
- example above. This is also true for drivers, but then it is the driver name
- that has to be the same as the filename. You also have to define
- `STATIC_ERLANG_{NIF,DRIVER}` when compiling the .o files for the nif/driver.
+ `--enable-static-nifs=/home/$USER/my_nif.a`. The paths have to be absolute.
+ For drivers, the driver name has to be the same as the filename. You also
+ have to define `STATIC_ERLANG_NIF_LIBNAME` (see `erl_nif` documentation) or
+ `STATIC_ERLANG_DRIVER` when compiling the .o files for the nif/driver.
If your nif/driver depends on some other dynamic library, you now have to link
that to the Erlang VM binary. This is easily achieved by passing `LIBS=-llibname`
to configure.
@@ -409,7 +399,7 @@ Some of the available `configure` options are:
should be compiled without one or more applications, i.e. `--without-wx`. There is
no automatic dependency handling between applications. If you disable
an application that another application depends on, you also have to disable the
- dependant application.
+ dependent application.
* `--enable-gettimeofday-as-os-system-time` - Force usage of `gettimeofday()` for
OS system time.
* `--enable-prefer-elapsed-monotonic-time-during-suspend` - Prefer an OS monotonic
@@ -751,33 +741,9 @@ passed to `configure`. One can force relative, or absolute links by passing
phase. Note that such a request might cause a failure if the request cannot
be satisfied.
+## Erlang/OTP test architectures ##
-### Running ###
-
- [$ERL_TOP/HOWTO/INSTALL-CROSS.md]: INSTALL-CROSS.md
- [$ERL_TOP/HOWTO/INSTALL-WIN32.md]: INSTALL-WIN32.md
- [DESTDIR]: http://www.gnu.org/prep/standards/html_node/DESTDIR.html
- [Building in Git]: #Advanced-configuration-and-build-of-ErlangOTP_Building_Within-Git
- [Advanced Configure]: #Advanced-configuration-and-build-of-ErlangOTP_Configuring
- [Pre-built Source Release]: #Advanced-configuration-and-build-of-ErlangOTP_Building_Prebuilt-Source-Release
- [make and $ERL_TOP]: #Advanced-configuration-and-build-of-ErlangOTP_make-and-ERLTOP
- [html documentation]: http://www.erlang.org/download/otp_doc_html_%OTP-VSN%.tar.gz
- [man pages]: http://www.erlang.org/download/otp_doc_man_%OTP-VSN%.tar.gz
- [the released source tar ball]: http://www.erlang.org/download/otp_src_%OTP-VSN%.tar.gz
- [System Principles]: system/system_principles:system_principles
- [native build]: #How-to-Build-and-Install-ErlangOTP
- [cross build]: INSTALL-CROSS.md
- [Required Utilities]: #Required-Utilities
- [Optional Utilities]: #Optional-Utilities
- [Building on a Mac]: #Advanced-configuration-and-build-of-ErlangOTP_Building_OS-X-Darwin
- [Building with wxErlang]: #Advanced-configuration-and-build-of-ErlangOTP_Building_Building-with-wxErlang
- [libatomic_ops]: https://github.com/ivmai/libatomic_ops/
-
-
-### Erlang/OTP test architectures ###
-
-
-Erlang/OTP are currently tested on the following hardware and Opererating systems.
+Erlang/OTP are currently tested on the following hardware and operating systems.
This is not an exhaustive list, but we try to keep it as up to date as possible.
Architecture
@@ -786,7 +752,7 @@ Architecture
* Aarch32, Aarch64
* powerpc, powerpc64le
-Operating System
+Operating system
* Fedora 31
* FreeBSD
@@ -799,3 +765,21 @@ Operating System
* Ubuntu 10.04 - 20.04
* Windows 10, Windows Server 2019
+ [$ERL_TOP/HOWTO/INSTALL-CROSS.md]: INSTALL-CROSS.md
+ [$ERL_TOP/HOWTO/INSTALL-WIN32.md]: INSTALL-WIN32.md
+ [DESTDIR]: http://www.gnu.org/prep/standards/html_node/DESTDIR.html
+ [Building in Git]: #Advanced-configuration-and-build-of-ErlangOTP_Building_Within-Git
+ [Advanced Configure]: #Advanced-configuration-and-build-of-ErlangOTP_Configuring
+ [Pre-built Source Release]: #Advanced-configuration-and-build-of-ErlangOTP_Building_Prebuilt-Source-Release
+ [make and $ERL_TOP]: #Advanced-configuration-and-build-of-ErlangOTP_make-and-ERLTOP
+ [html documentation]: https://github.com/erlang/otp/releases/download/OTP-%OTP-VSN%/otp_doc_html_%OTP-VSN%.tar.gz
+ [man pages]: https://github.com/erlang/otp/releases/download/OTP-%OTP-VSN%/otp_doc_man_%OTP-VSN%.tar.gz
+ [the released source tar ball]: https://github.com/erlang/otp/releases/download/OTP-%OTP-VSN%/otp_src_%OTP-VSN%.tar.gz
+ [System Principles]: system/system_principles:system_principles
+ [native build]: #How-to-Build-and-Install-ErlangOTP
+ [cross build]: INSTALL-CROSS.md
+ [Required Utilities]: #Required-Utilities
+ [Optional Utilities]: #Optional-Utilities
+ [Building on a Mac]: #Advanced-configuration-and-build-of-ErlangOTP_Building_OS-X-Darwin
+ [Building with wxErlang]: #Advanced-configuration-and-build-of-ErlangOTP_Building_Building-with-wxErlang
+ [libatomic_ops]: https://github.com/ivmai/libatomic_ops/
diff --git a/HOWTO/MARKDOWN.md b/HOWTO/MARKDOWN.md
index 36c2b9c775..91b5526bf9 100644
--- a/HOWTO/MARKDOWN.md
+++ b/HOWTO/MARKDOWN.md
@@ -202,7 +202,7 @@ places. Appropriate attributes to the `X` tag will also be generated.
This way it is relatively easy to make sure that all marker ids of a
document are unique, but there is of course no guarantee that they are.
- The upside of these auto generated markers is that we wont have to clutter
+ The upside of these auto generated markers is that we won't have to clutter
the document with XML or something else while being able to refer into
the document. The downside is that if you change a level 2 heading you
change a lot of marker ids which may break links into a document from
diff --git a/HOWTO/SYSTEMTAP.md b/HOWTO/SYSTEMTAP.md
index 76deac97e5..01b1fe8a47 100644
--- a/HOWTO/SYSTEMTAP.md
+++ b/HOWTO/SYSTEMTAP.md
@@ -43,7 +43,7 @@ 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
+therefore 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
diff --git a/HOWTO/TESTING.md b/HOWTO/TESTING.md
index f713f85231..66cc21f89a 100644
--- a/HOWTO/TESTING.md
+++ b/HOWTO/TESTING.md
@@ -5,17 +5,24 @@ Before you start testing you need to have the Erlang release which you
are going to test in your path. See [$ERL_TOP/HOWTO/INSTALL.md][] for
instructions on how to build an Erlang release.
+*NOTE*: This instructions may vary for different versions of Erlang/OTP,
+so make sure to read the instructions for the version that you are testing.
+
Short version
-------------
-Move to the top directory of the Erlang release you want to test, i.e.
-cd /ldisk/work/otp
+Move to the top directory of the Erlang release you want to test, for example:
+cd $HOME/git/otp
+
+```bash
+export ERL_TOP=`pwd` # Define where the build root is
+./configure && make # Build all of Erlang/OTP
+make test # Test all of Erlang/OTP
+```
- export ERL_TOP=`pwd`
- ./otp_build setup -a
- export PATH=`pwd`/bin:$PATH
- ./otp_build tests
- cd release/tests/test_server
- erl -s ts install -s ts run all_tests -s init stop
+The tests will take a long time to finish and will print a lot of logs to the
+console even if tests pass. A full run takes close about 6 hours on a relatively
+modern machine. See [Running tests while developing][] for details on how to run
+only a subset of the tests.
Where are the tests
-------------------
@@ -46,14 +53,57 @@ the erl_interface tests use this feature and it should remain that way.
[configuring the tests][]. These `Makefile`s are later run by the test suite
to compile whatever platform specific code the tests need to run.
+Running tests while developing
+------------------------------
+
+The `make test` command works when the current directory contains a directory
+called test and in the root directory of the source code tree.
+
+Below are some examples that illustrate how `make test` can be
+used:
+
+```bash
+# ERL_TOP needs to be set correctly
+cd /path/to/otp
+export ERL_TOP=`pwd`
+
+# Build Erlang/OTP
+#
+# Note that make test will only compile test code except when
+# make test is executed from $ERL_TOP.
+./otp_build setup -a
+
+# Run all test suites for an application
+(cd $ERL_TOP/lib/asn1 && make test)
+make asn1_test
+
+# Run a test suite (The ARGS variable is passed to ct_run)
+(cd $ERL_TOP/lib/stdlib && make test ARGS="-suite ets_SUITE")
+make stdlib_test ARGS="-suite ets_SUITE"
+
+# Run a test case
+(cd $ERL_TOP/erts/emulator && make test ARGS="-suite binary_SUITE -case deep_bitstr_lists")
+make emulator_test ARGS="-suite binary_SUITE -case deep_bitstr_lists"
+
+# Run all tests
+#
+# When executed from $ERL_TOP, "make test" will first release and
+# configure all tests and then attempt to run all tests with `ts:run`.
+# This will take several hours.
+(cd $ERL_TOP && make test)
+```
+
+For more examples see [DEVELOPMENT.md](DEVELOPMENT.md)
+
Releasing tests
---------------
-If you cannot use [ct_run][] in the source tree you have to release the tests
-into a common test directory. The easiest way to do this is to use `otp_build`
-like this:
+When not testing in the source tree, you first need to release all tests.
+The easiest way to do this is to use `otp_build` like this:
- export ERL_TOP=`pwd`; ./otp_build tests
+```bash
+export ERL_TOP=`pwd`; ./otp_build tests
+```
This will release all tests in Erlang/OTP to `$ERL_TOP/release/tests/`. If you
want to change the directory where the tests are released to use the `TESTROOT`
@@ -99,24 +149,31 @@ All variables created by `ts:install()` are found in
To run all test suites go to `$TESTROOT/test_server` fire up an Erlang shell and type:
- ts:run().
+```erlang
+ts:run().
+```
Note that running all tests will require several hours, so you may want to run
the test cases for a single application
- ts:run(Application, [batch]).
+```erlang
+ts:run(Application, [batch]).
+```
or even part of the test suite for an application, for example
- ts:run(emulator, bs, [batch]).
+```erlang
+ts:run(emulator, bs_construct_SUITE, [batch]).
+```
-to run all test suite modules starting with `bs` (i.e. all modules that test
-the bit syntax).
+to run the tests in the `bs_construct_SUITE` module (testing construction of
+binaries using the binary syntax).
-To run a specific test case in a module, the full name of the module and test
-case must be specified:
+It is also possible to run a single test case by the specifying the module name and a function name:
- ts:run(emulator, bs_bincomp_SUITE, byte_aligned, [batch]).
+```erlang
+ts:run(emulator, bs_bincomp_SUITE, byte_aligned, [batch]).
+```
Run `ts:help().` for more information.
@@ -124,66 +181,20 @@ As of R14B02 it is also possibly to start all tests but the erl_interface tests
by invoking Common Test directly from the released applications test directory,
i.e.
- cd $TESTROOT/test_server
- $ERL_TOP/bin/ct_run -suite ../compiler_test/andor_SUITE -case t_orelse
+```bash
+cd $TESTROOT/test_server
+$ERL_TOP/bin/ct_run -suite ../compiler_test/andor_SUITE -case t_orelse
+```
Running [ct_run][] from the command line still requires you to do the
`ts:install()` step above.
-### Convenience for running tests without the release and configuration steps
-
-It can be convenient to run tests with a single command. This way, one
-do not need to worry about missing to run `make release_tests` after
-changing a test suite. The `make test` command can be used for this
-purpose. The `make test` command works when the current directory
-contains a directory called test and in the root directory of the
-source code tree.
-
-*(Warning)* Some test cases do not run correctly or cannot be run at
-all through the `make test` command (typically test cases that require
-test specific C code to be compiled) because `make test` runs tests
-directly by invoking the `ct_run` command instead of using the `ts`
-wrapper. One has to follow the procedure described above to run test
-cases that do not work with `make test`.
-
-Below are some examples that illustrate how `make test` can be
-used:
-
- # ERL_TOP needs to be set correctly
- cd /path/to/otp
- export ERL_TOP=`pwd`
-
- # Build Erlang/OTP
- #
- # Note that make test will only compile test code except when
- # make test is executed from $ERL_TOP.
- ./otp_build setup -a
-
- # Run a test case (The ARGS variable is passed to ct_run)
- (cd $ERL_TOP/erts/emulator && make ARGS="-suite binary_SUITE -case deep_bitstr_lists" test)
-
- # Run a test suite
- (cd $ERL_TOP/lib/stdlib && make ARGS="-suite ets_SUITE" test)
-
- # Run all test suites for an application
- (cd $ERL_TOP/lib/asn1 && make test)
-
- # Run all tests
- #
- # When executed from $ERL_TOP, "make test" will first release and
- # configure all tests and then attempt to run all tests with `ts:run`.
- # This will take several hours.
- (cd $ERL_TOP && make test)
-
-
Examining the results
---------------------
-Open the file `release/tests/test_server/index.html` in a web browser. Or open
-`release/tests/test_server/last_test.html` when a test suite is running to
-examine the results so far for the currently executing test suite (in R14B02 and
-later you want to open the `release/tests/test_server/all_runs.html` file to
-get to the currently running test)
+Open the file `$ERL_TOP/release/tests/test_server/index.html` in a web browser. Or open
+`$ERL_TOP/release/tests/test_server/last_test.html` when a test suite is running to
+examine the results so far for the currently executing test suite.
Run tests with Address Sanitizer
@@ -195,15 +206,19 @@ See [$ERL_TOP/HOWTO/INSTALL.md][].
Set environment variable `ASAN_LOG_DIR` to the directory
where the error logs will be generated.
- export ASAN_LOG_DIR=$TESTROOT/test_server/asan_logs
- mkdir $ASAN_LOG_DIR
+```bash
+export ASAN_LOG_DIR=$TESTROOT/test_server/asan_logs
+mkdir $ASAN_LOG_DIR
+```
Set environment variable `TS_RUN_EMU` to `asan`.
- export TS_RUN_EMU=asan
+```bash
+export TS_RUN_EMU=asan
+```
-Then run the tests you want with `ts:run` as described above. Either
-inspect the log files directly or use the script at
+Then run the tests you want with `ts:run` as [described above](#running-the-tests).
+Either inspect the log files directly or use the script at
`$ERL_TOP/erts/emulator/asan/asan_logs_to_html` to read all log files
in `$ASAN_LOG_DIR` and distill them into one html page
`asan_summary.html`. Repeated reports from the same memory leak will
@@ -220,15 +235,19 @@ and build the emulator with `valgrind` build target. See
Set environment variable `VALGRIND_LOG_DIR` to the directory
where the valgrind error logs will be generated.
- export VALGRIND_LOG_DIR=$TESTROOT/test_server/vg_logs
- mkdir $VALGRIND_LOG_DIR
+```bash
+export VALGRIND_LOG_DIR=$TESTROOT/test_server/vg_logs
+mkdir $VALGRIND_LOG_DIR
+```
Set environment variable `TS_RUN_EMU` to `valgrind`.
- export TS_RUN_EMU=valgrind
+```bash
+export TS_RUN_EMU=valgrind
+```
-Then run the tests you want with `ts:run` as described above and
-inspect the log file(s) in `$VALGRIND_LOG_DIR`.
+Then run the tests you want with `ts:run` as [described above](#running-the-tests)
+and inspect the log file(s) in `$VALGRIND_LOG_DIR`.
[ct_run]: http://www.erlang.org/doc/man/ct_run.html
@@ -239,5 +258,6 @@ inspect the log file(s) in `$VALGRIND_LOG_DIR`.
[data_dir]: http://www.erlang.org/doc/apps/common_test/write_test_chapter.html#data_priv_dir
[configuring the tests]: #configuring-the-test-environment
[valgrind]: https://valgrind.org
+ [Running tests while developing]: #running-tests-while-developing
[?TOC]: true
diff --git a/Makefile.in b/Makefile.in
index 3746c703e1..cc92df3a21 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2021. All Rights Reserved.
+# Copyright Ericsson AB 1998-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -294,6 +294,13 @@ RELEASE_ROOT = $(TESTROOT)
endif
endif
+# ----------------------------------------------------------------------
+
+ifeq ($(ERL_DETERMINISTIC),yes)
+ DETERMINISM_FLAG = +deterministic
+else
+ DETERMINISM_FLAG =
+endif
# ----------------------------------------------------------------------
@@ -399,10 +406,16 @@ ifeq ($(OTP_SMALL_BUILD),true)
ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
$(MAKE) TESTROOT="$(RELEASE_ROOT)" release
else
+ifeq ($(OTP_TINY_BUILD),true)
+ cd $(ERL_TOP)/lib && \
+ ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
+ $(MAKE) TINY_BUILD=true 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
endif
+endif
cd $(ERL_TOP)/erts && \
ERL_TOP=$(ERL_TOP) PATH=$(INST_PATH_PREFIX)"$${PATH}" \
$(MAKE) BUILD_ALL=1 PROFILE=$(PROFILE) TESTROOT="$(RELEASE_ROOT)" release
@@ -466,7 +479,7 @@ BOOTSTRAP_COMPILER = $(BOOTSTRAP_TOP)/primary_compiler
# otp.mk is only used to figure out if we are doing PGO or not
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-.PHONY: emulator libs kernel preloaded
+.PHONY: emulator libs kernel preloaded system
ifeq ($(USE_PGO), true)
PROFILE=use
@@ -479,6 +492,13 @@ PROFILE=
PROFILE_EMU_DEPS=
endif
+emulator_test: emulator
+ $(make_verbose)cd erts/emulator && ERL_TOP=$(ERL_TOP) TYPE=$(TYPE) $(MAKE) test
+epmd_test:
+ $(make_verbose)cd erts/epmd && ERL_TOP=$(ERL_TOP) TYPE=$(TYPE) $(MAKE) test
+system_test:
+ $(make_verbose)cd erts && ERL_TOP=$(ERL_TOP) TYPE=$(TYPE) $(MAKE) test
+
emulator: $(PROFILE_EMU_DEPS)
$(make_verbose)cd erts && ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
$(MAKE) NO_START_SCRIPTS=true $(TYPE) FLAVOR=$(FLAVOR) PROFILE=$(PROFILE)
@@ -503,13 +523,14 @@ endif
endif
APPS=$(patsubst $(ERL_TOP)/lib/%/doc,%,$(wildcard $(ERL_TOP)/lib/*/doc))
+NO_DIALYZER_APPS=$(filter-out dialyzer, $(APPS)) ## The dialyzer make target should not build the app
-.PHONY: $(APPS)
+.PHONY: $(NO_DIALYZER_APPS)
-$(APPS):
+$(NO_DIALYZER_APPS):
$(make_verbose)cd lib/$@ && \
ERL_TOP=$(ERL_TOP) PATH=$(BOOT_PREFIX)"$${PATH}" \
- $(MAKE) $(TYPE) BUILD_ALL=true
+ $(MAKE) $(TYPE)
##
## Generate `otp_internal` from the -deprecated() attributes in source.
@@ -567,14 +588,18 @@ bootstrap_setup: check_recreate_primary_bootstrap bootstrap_setup_target
$(BOOTSTRAP_ROOT)/bootstrap/bin/escript.exe
@cp $(ERL_TOP)/erts/lib_src/yielding_c_fun/bin/$(TARGET)/yielding_c_fun.exe \
$(BOOTSTRAP_ROOT)/bootstrap/bin/yielding_c_fun.exe
+ @cp $(ERL_TOP)/bin/$(TARGET)/inet_gethost.exe \
+ $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET)/inet_gethost.exe
else
-bootstrap_setup: check_recreate_primary_bootstrap bootstrap_setup_target $(BOOTSTRAP_ROOT)/bootstrap/bin/erl $(BOOTSTRAP_ROOT)/bootstrap/bin/erlc $(BOOTSTRAP_ROOT)/bootstrap/bin/escript $(BOOTSTRAP_ROOT)/bootstrap/bin/yielding_c_fun
+bootstrap_setup: check_recreate_primary_bootstrap bootstrap_setup_target $(BOOTSTRAP_ROOT)/bootstrap/bin/erl $(BOOTSTRAP_ROOT)/bootstrap/bin/erlc $(BOOTSTRAP_ROOT)/bootstrap/bin/escript $(BOOTSTRAP_ROOT)/bootstrap/bin/yielding_c_fun $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET)/inet_gethost
$(BOOTSTRAP_ROOT)/bootstrap/bin/erl: $(ERL_TOP)/erts/etc/unix/erl.src.src $(BOOTSTRAP_ROOT)/bootstrap/target
- @rm -f $(BOOTSTRAP_ROOT)/bootstrap/bin/erl
+ @rm -f $(BOOTSTRAP_ROOT)/bootstrap/bin/erl
@sed -e "s;%FINAL_ROOTDIR%;$(BOOTSTRAP_ROOT)/bootstrap;" \
-e "s;\$$ROOTDIR/erts-.*/bin;$(ERL_TOP)/bin/$(TARGET);" \
-e "s;EMU=.*;EMU=beam$(TYPEMARKER);" \
+ -e "s;%DYN_ERL_PATH%;../../bin/$(TARGET)/dyn_erl;" \
+ -e "s;%DYN_ROOTDIR_BASE_EXT%;/bootstrap;" \
$(ERL_TOP)/erts/etc/unix/erl.src.src > \
$(BOOTSTRAP_ROOT)/bootstrap/bin/erl
@chmod 755 $(BOOTSTRAP_ROOT)/bootstrap/bin/erl
@@ -595,10 +620,17 @@ $(BOOTSTRAP_ROOT)/bootstrap/bin/yielding_c_fun: $(ERL_TOP)/bin/$(TARGET)/escript
@chmod 755 $(BOOTSTRAP_ROOT)/bootstrap/bin/yielding_c_fun
endif
+$(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET)/inet_gethost: $(ERL_TOP)/bin/$(TARGET)/inet_gethost $(BOOTSTRAP_ROOT)/bootstrap/target
+ @rm -f $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET)/inet_gethost
+ @cp $(ERL_TOP)/bin/$(TARGET)/inet_gethost $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET)/inet_gethost
+ @chmod 755 $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET)/inet_gethost
+
+
bootstrap_setup_target:
@{ test -r $(BOOTSTRAP_ROOT)/bootstrap/target && \
test $(TARGET) = `cat $(BOOTSTRAP_ROOT)/bootstrap/target`; } || \
echo $(TARGET) > $(BOOTSTRAP_ROOT)/bootstrap/target
+ if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET) ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/bin/$(TARGET) ; fi
tiny_secondary_bootstrap_build:
$(make_verbose)cd lib && \
@@ -1011,7 +1043,7 @@ primary_bootstrap:
primary_bootstrap_build: primary_bootstrap_mkdirs primary_bootstrap_compiler \
primary_bootstrap_stdlib
- $(make_verbose)cd lib && $(MAKE) ERLC_FLAGS='-pa $(BOOTSTRAP_COMPILER)/ebin' \
+ $(make_verbose)cd lib && $(MAKE) ERLC_FLAGS='-pa $(BOOTSTRAP_COMPILER)/ebin $(DETERMINISM_FLAG)' \
BOOTSTRAP_TOP=$(BOOTSTRAP_TOP) \
BOOTSTRAP=1 opt
@@ -1095,7 +1127,7 @@ tests release_tests: $(TEST_DIRS)
$(TEST_DIRS):
if test -f $@/Makefile; then \
- (cd $@; $(MAKE) TESTROOT="$(TESTSUITE_ROOT)" \
+ (cd $@; $(MAKE) TESTROOT="$(TESTSUITE_ROOT)" ERL_TOP="$(ERL_TOP)" \
PATH=$(TEST_PATH_PREFIX)$(BOOT_PREFIX)"$${PATH}" release_tests) || exit $$?; \
fi
@@ -1219,7 +1251,7 @@ bootstrap_clean:
$(V_at)rm -f $(ERL_TOP)/bootstrap/lib/*/include/*.hrl
$(V_at)rm -f $(ERL_TOP)/bootstrap/primary_compiler/ebin/*
$(V_at)rm -f $(ERL_TOP)/bootstrap/primary_compiler/egen/*
- $(V_at)rm -f $(ERL_TOP)/bootstrap/bin/*.*
+ $(V_at)rm -f $(ERL_TOP)/bootstrap/bin/*.boot
$(V_at)rm -f $(KERNEL_PRELOAD:%=$(ERL_TOP)/lib/kernel/ebin/%.beam)
$(V_at)test $(BOOTSTRAP_ROOT) = $(ERL_TOP) \
|| $(MAKE) BOOTSTRAP_ROOT=$(BOOTSTRAP_ROOT) bootstrap_root_clean
@@ -1231,5 +1263,13 @@ bootstrap_clean:
test: all release release_tests
$(ERL_TOP)/make/test_target_script.sh $(ERL_TOP)
+ifeq ($(TYPE),)
dialyzer: all
$(ERL_TOP)/scripts/run-dialyzer
+endif
+
+APPS_TEST=$(patsubst %, %_test,$(APPS))
+
+.SECONDEXPANSION:
+$(APPS_TEST): $$(patsubst %_test,%,$$@)
+ ERL_TOP=$(ERL_TOP) TYPE=$(TYPE) $(MAKE) -C lib/$< test
diff --git a/OTP_VERSION b/OTP_VERSION
index 849495a330..51fc50a418 100644
--- a/OTP_VERSION
+++ b/OTP_VERSION
@@ -1 +1 @@
-24.3.4
+25.3
diff --git a/README.md b/README.md
index 3530da4149..7a588204fe 100644
--- a/README.md
+++ b/README.md
@@ -4,58 +4,67 @@
**OTP** is a set of Erlang libraries, which consists of the Erlang runtime system, a number of ready-to-use components mainly written in Erlang, and a set of design principles for Erlang programs. [Learn more about Erlang and OTP](http://erlang.org/doc/system_architecture_intro/sys_arch_intro.html).
-[Release notes](http://erlang.org/download/otp_versions_tree.html) for all OTP versions.
-
-[Learn how to program in Erlang](http://learnyousomeerlang.com/content).
+[Learn how to program in Erlang](http://learnyousomeerlang.com/).
## Examples
+
There are several examples [on the website](http://erlang.org/faq/getting_started.html) to help you get started. The below example defines a function `world/0` that prints "Hello, world" in the Erlang shell:
+
```erlang
-module(hello).
-export([world/0]).
world() -> io:format("Hello, world\n").
```
+
Save the file as `hello.erl` and run `erl` to enter the Erlang shell to compile the module.
-```
-Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
-Eshell V8.2 (abort with ^G)
+```sh
+Erlang/OTP 24 [erts-12.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]
+
+Eshell V12.2 (abort with ^G)
1> c(hello).
{ok,hello}
2> hello:world().
Hello, world
ok
```
+
Learn more about the Erlang syntax of [modules](http://erlang.org/doc/reference_manual/modules.html), [functions](http://erlang.org/doc/reference_manual/functions.html) and [expressions](http://erlang.org/doc/reference_manual/expressions.html) on [Erlang.org](https://www.erlang.org).
## Installation
+
### Binary Distributions
+
Erlang/OTP is available as pre-built binary packages by most OS package managers.
-```
+
+```sh
apt-get install erlang
```
+
### Compiling from source
-To compile Erlang from source, run the following commands. The complete building and installation instructions [can be found here](HOWTO/INSTALL.md).
-```
+To compile Erlang from source, run the following commands. The complete building and installation instructions [can be found here](HOWTO/INSTALL.md).
+
+```sh
git clone https://github.com/erlang/otp.git
cd otp
```
+
Checkout the branch or tag of your choice
-```
+
+```sh
git checkout maint-24 # current latest stable version
```
-For older versions run autoconf
-```
-./otp_build autoconf
-```
+
Configure, build and install
-```
+
+```sh
./configure
make
make install
```
+
Alternatively, you can use [Kerl](https://github.com/kerl/kerl), a script that lets you easily build Erlang with a few commands.
## Bug Reports
@@ -78,6 +87,10 @@ Read our [contribution guide](CONTRIBUTING.md) to learn about our development pr
We have a list of [Help Wanted](https://github.com/erlang/otp/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) bugs that we would appreciate external help from the community. This is a great place to get involved.
+## Awesome-Erlang
+
+You can find more projects, tools and articles related to Erlang/OTP on the [awesome-erlang list](https://github.com/drobakowski/awesome-erlang). Add your project there.
+
## License
Erlang/OTP is released under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
@@ -99,6 +112,3 @@ Erlang/OTP is released under the [Apache License 2.0](http://www.apache.org/lice
> limitations under the License.
>
> %CopyrightEnd%
-
-## Awesome-Erlang
-You can find more projects, tools and articles related to Erlang/OTP on the [awesome-erlang list](https://github.com/drobakowski/awesome-erlang). Add your project there.
diff --git a/bootstrap/bin/no_dot_erlang.boot b/bootstrap/bin/no_dot_erlang.boot
index 4c9b49dbec..632e660dfd 100644
--- a/bootstrap/bin/no_dot_erlang.boot
+++ b/bootstrap/bin/no_dot_erlang.boot
Binary files differ
diff --git a/bootstrap/bin/start.boot b/bootstrap/bin/start.boot
index 4c9b49dbec..632e660dfd 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 4c9b49dbec..632e660dfd 100644
--- a/bootstrap/bin/start_clean.boot
+++ b/bootstrap/bin/start_clean.boot
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_a.beam b/bootstrap/lib/compiler/ebin/beam_a.beam
index 89d86ec819..d81e1e3e3b 100644
--- a/bootstrap/lib/compiler/ebin/beam_a.beam
+++ b/bootstrap/lib/compiler/ebin/beam_a.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index 559a6df9c3..13b170ef05 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 9dbed5dfa2..8587d9b27d 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_bounds.beam b/bootstrap/lib/compiler/ebin/beam_bounds.beam
new file mode 100644
index 0000000000..b94142c660
--- /dev/null
+++ b/bootstrap/lib/compiler/ebin/beam_bounds.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_call_types.beam b/bootstrap/lib/compiler/ebin/beam_call_types.beam
index 730610a94e..f6411aa457 100644
--- a/bootstrap/lib/compiler/ebin/beam_call_types.beam
+++ b/bootstrap/lib/compiler/ebin/beam_call_types.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_clean.beam b/bootstrap/lib/compiler/ebin/beam_clean.beam
index 7fad16c7d3..91a536bf46 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_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index 0b2a04a58b..c57682576f 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_digraph.beam b/bootstrap/lib/compiler/ebin/beam_digraph.beam
index 7809d5868b..b522dac9c3 100644
--- a/bootstrap/lib/compiler/ebin/beam_digraph.beam
+++ b/bootstrap/lib/compiler/ebin/beam_digraph.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index ddb3efd44e..9f591e9f70 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_flatten.beam b/bootstrap/lib/compiler/ebin/beam_flatten.beam
index bb4aad66dd..d98664ce03 100644
--- a/bootstrap/lib/compiler/ebin/beam_flatten.beam
+++ b/bootstrap/lib/compiler/ebin/beam_flatten.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index ea808d20bc..22dd3f82c3 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_kernel_to_ssa.beam b/bootstrap/lib/compiler/ebin/beam_kernel_to_ssa.beam
index 25b14e58a3..97c218480c 100644
--- a/bootstrap/lib/compiler/ebin/beam_kernel_to_ssa.beam
+++ b/bootstrap/lib/compiler/ebin/beam_kernel_to_ssa.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_listing.beam b/bootstrap/lib/compiler/ebin/beam_listing.beam
index fde816c110..f71f5d4bf5 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_opcodes.beam b/bootstrap/lib/compiler/ebin/beam_opcodes.beam
index 191fe66d77..1f42b157ff 100644
--- a/bootstrap/lib/compiler/ebin/beam_opcodes.beam
+++ b/bootstrap/lib/compiler/ebin/beam_opcodes.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_peep.beam b/bootstrap/lib/compiler/ebin/beam_peep.beam
deleted file mode 100644
index 8f3d8962b8..0000000000
--- a/bootstrap/lib/compiler/ebin/beam_peep.beam
+++ /dev/null
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa.beam b/bootstrap/lib/compiler/ebin/beam_ssa.beam
index b5ae0c8e0d..f489f46b98 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beam b/bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beam
index 9b91bd9bdc..ba37502190 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_bc_size.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_bool.beam b/bootstrap/lib/compiler/ebin/beam_ssa_bool.beam
index aabaf0b44d..e82b00aac9 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_bool.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_bool.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam b/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam
index 0b00d981f0..e0d4fac178 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
index f3f6a2483d..3f1ec45a9e 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam b/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
index 73a845193a..690e96e2d6 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_funs.beam b/bootstrap/lib/compiler/ebin/beam_ssa_funs.beam
deleted file mode 100644
index e442edfec8..0000000000
--- a/bootstrap/lib/compiler/ebin/beam_ssa_funs.beam
+++ /dev/null
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_lint.beam b/bootstrap/lib/compiler/ebin/beam_ssa_lint.beam
index 0ff61632c9..a1209d6fb5 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_lint.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_lint.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam b/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam
index cbbe63ae31..ae54b0a0f6 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_opt.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_pp.beam b/bootstrap/lib/compiler/ebin/beam_ssa_pp.beam
index 0da9e9d8a6..e4958e9b97 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_pp.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam b/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
index d75c4c55fc..ed20850651 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_pre_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_recv.beam b/bootstrap/lib/compiler/ebin/beam_ssa_recv.beam
index 0151a2e706..8fdaf19b9b 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_recv.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_recv.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_share.beam b/bootstrap/lib/compiler/ebin/beam_ssa_share.beam
index 4aa843a830..87861b519c 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_share.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_share.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_throw.beam b/bootstrap/lib/compiler/ebin/beam_ssa_throw.beam
index e794cb482f..65eba1cc55 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_throw.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_throw.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_ssa_type.beam b/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
index 697f8f6f23..24f1357882 100644
--- a/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
+++ b/bootstrap/lib/compiler/ebin/beam_ssa_type.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_trim.beam b/bootstrap/lib/compiler/ebin/beam_trim.beam
index 5d6d124132..403d14af8a 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_types.beam b/bootstrap/lib/compiler/ebin/beam_types.beam
index 00653a1588..50aa05ce7b 100644
--- a/bootstrap/lib/compiler/ebin/beam_types.beam
+++ b/bootstrap/lib/compiler/ebin/beam_types.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index 3c7d3aa3b5..43f43219ca 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 ffb43389a5..9dea06a177 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/beam_z.beam b/bootstrap/lib/compiler/ebin/beam_z.beam
index d8c4a6f648..0ad3c95960 100644
--- a/bootstrap/lib/compiler/ebin/beam_z.beam
+++ b/bootstrap/lib/compiler/ebin/beam_z.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl.beam b/bootstrap/lib/compiler/ebin/cerl.beam
index 6415ba73a5..c0e3654c1e 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 8f5d43d1a6..f1deadb265 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 0d6904e4fd..d3f8397584 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 03428f4bfb..79c464e800 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 279f5e194c..0057b1eea9 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compiler.app b/bootstrap/lib/compiler/ebin/compiler.app
index 516f28d4f3..0e749bb6cd 100644
--- a/bootstrap/lib/compiler/ebin/compiler.app
+++ b/bootstrap/lib/compiler/ebin/compiler.app
@@ -1,7 +1,7 @@
% This is an -*- erlang -*- file.
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,10 +19,11 @@
{application, compiler,
[{description, "ERTS CXC 138 10"},
- {vsn, "8.0.2"},
+ {vsn, "8.2"},
{modules, [
beam_a,
beam_asm,
+ beam_bounds,
beam_block,
beam_call_types,
beam_clean,
@@ -34,14 +35,12 @@
beam_kernel_to_ssa,
beam_listing,
beam_opcodes,
- beam_peep,
beam_ssa,
beam_ssa_bc_size,
beam_ssa_bool,
beam_ssa_bsm,
beam_ssa_codegen,
beam_ssa_dead,
- beam_ssa_funs,
beam_ssa_lint,
beam_ssa_opt,
beam_ssa_pp,
@@ -82,5 +81,5 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["stdlib-3.13","kernel-7.0","erts-11.0",
- "crypto-3.6"]}]}.
+ {runtime_dependencies, ["stdlib-4.0","kernel-8.4","erts-13.0",
+ "crypto-5.1"]}]}.
diff --git a/bootstrap/lib/compiler/ebin/compiler.appup b/bootstrap/lib/compiler/ebin/compiler.appup
index 3d4fe9c021..aa537986a5 100644
--- a/bootstrap/lib/compiler/ebin/compiler.appup
+++ b/bootstrap/lib/compiler/ebin/compiler.appup
@@ -16,7 +16,7 @@
%% limitations under the License.
%%
%% %CopyrightEnd%
-{"7.3.2",
+{"8.1",
[{<<".*">>,[{restart_application, compiler}]}],
[{<<".*">>,[{restart_application, compiler}]}]
}.
diff --git a/bootstrap/lib/compiler/ebin/core_lib.beam b/bootstrap/lib/compiler/ebin/core_lib.beam
index e28cc846ab..e316333572 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 5ee46bdf47..11c1ad9c82 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 4991cc4fd2..46ed9443dd 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 257ea98f47..f5b8955675 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 d02ac0d553..5da4515384 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 17c4e1c119..c858cbbfcd 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 befc454756..2147d61279 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_alias.beam b/bootstrap/lib/compiler/ebin/sys_core_alias.beam
index 4903bdf460..c8c0c54442 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_alias.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_alias.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_bsm.beam b/bootstrap/lib/compiler/ebin/sys_core_bsm.beam
index 0208755723..d51f74ccb1 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_bsm.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 422c67327a..bc2057d1c2 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_fold_lists.beam b/bootstrap/lib/compiler/ebin/sys_core_fold_lists.beam
index 93d66ba306..714ff86f48 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold_lists.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold_lists.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 020b5e1782..c142a3f22b 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_core_prepare.beam b/bootstrap/lib/compiler/ebin/sys_core_prepare.beam
index a56dc0d6ee..0e2debbfba 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_prepare.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_prepare.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_messages.beam b/bootstrap/lib/compiler/ebin/sys_messages.beam
index a73a6e16ab..1ed2960660 100644
--- a/bootstrap/lib/compiler/ebin/sys_messages.beam
+++ b/bootstrap/lib/compiler/ebin/sys_messages.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 c34e530cca..ef7de3c3ae 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/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index c0910c1482..ff06839fba 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 5d5034d574..d8e5208989 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 ffecc0c65c..cef39b84a4 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/kernel/ebin/application.beam b/bootstrap/lib/kernel/ebin/application.beam
index c483be1bfc..47e4cb5a17 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 c91dc12b66..5456b2be99 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 b33ffefe5a..2efaa70849 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/application_starter.beam b/bootstrap/lib/kernel/ebin/application_starter.beam
index 76389d5a52..30495729c3 100644
--- a/bootstrap/lib/kernel/ebin/application_starter.beam
+++ b/bootstrap/lib/kernel/ebin/application_starter.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/auth.beam b/bootstrap/lib/kernel/ebin/auth.beam
index 536caf55fd..d20b71f629 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 424cd89028..3341d51436 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 d9f205f7d7..8ecba51c72 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 5c135ebed8..55e6550c16 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 80f8427f8d..16961789dd 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 be0fa31c68..cb13107464 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/disk_log_sup.beam b/bootstrap/lib/kernel/ebin/disk_log_sup.beam
index 35077bcef7..396c8e7b4c 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_sup.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_sup.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_ac.beam b/bootstrap/lib/kernel/ebin/dist_ac.beam
index 7ad634716e..c9c404ae10 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 99af0b6a98..0098d533ea 100644
--- a/bootstrap/lib/kernel/ebin/dist_util.beam
+++ b/bootstrap/lib/kernel/ebin/dist_util.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_boot_server.beam b/bootstrap/lib/kernel/ebin/erl_boot_server.beam
index dae1ab427c..3d975d37a5 100644
--- a/bootstrap/lib/kernel/ebin/erl_boot_server.beam
+++ b/bootstrap/lib/kernel/ebin/erl_boot_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_compile_server.beam b/bootstrap/lib/kernel/ebin/erl_compile_server.beam
index d1d6bd6db3..f00652d7f0 100644
--- a/bootstrap/lib/kernel/ebin/erl_compile_server.beam
+++ b/bootstrap/lib/kernel/ebin/erl_compile_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_ddll.beam b/bootstrap/lib/kernel/ebin/erl_ddll.beam
index 7ae8ab499e..8910f69874 100644
--- a/bootstrap/lib/kernel/ebin/erl_ddll.beam
+++ b/bootstrap/lib/kernel/ebin/erl_ddll.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_distribution.beam b/bootstrap/lib/kernel/ebin/erl_distribution.beam
index 5d7f85ebef..cadf5947ad 100644
--- a/bootstrap/lib/kernel/ebin/erl_distribution.beam
+++ b/bootstrap/lib/kernel/ebin/erl_distribution.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_epmd.beam b/bootstrap/lib/kernel/ebin/erl_epmd.beam
index 0dcf03570d..9672775cb8 100644
--- a/bootstrap/lib/kernel/ebin/erl_epmd.beam
+++ b/bootstrap/lib/kernel/ebin/erl_epmd.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_erts_errors.beam b/bootstrap/lib/kernel/ebin/erl_erts_errors.beam
index e288e70af6..ae8bc9a019 100644
--- a/bootstrap/lib/kernel/ebin/erl_erts_errors.beam
+++ b/bootstrap/lib/kernel/ebin/erl_erts_errors.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_kernel_errors.beam b/bootstrap/lib/kernel/ebin/erl_kernel_errors.beam
index aa98334072..a4afe1ee3d 100644
--- a/bootstrap/lib/kernel/ebin/erl_kernel_errors.beam
+++ b/bootstrap/lib/kernel/ebin/erl_kernel_errors.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_reply.beam b/bootstrap/lib/kernel/ebin/erl_reply.beam
index 36d7d54dfc..81ca50c86d 100644
--- a/bootstrap/lib/kernel/ebin/erl_reply.beam
+++ b/bootstrap/lib/kernel/ebin/erl_reply.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erl_signal_handler.beam b/bootstrap/lib/kernel/ebin/erl_signal_handler.beam
index d73fde89f2..6ed5a62960 100644
--- a/bootstrap/lib/kernel/ebin/erl_signal_handler.beam
+++ b/bootstrap/lib/kernel/ebin/erl_signal_handler.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erpc.beam b/bootstrap/lib/kernel/ebin/erpc.beam
index 81048671a4..c081fa7ff5 100644
--- a/bootstrap/lib/kernel/ebin/erpc.beam
+++ b/bootstrap/lib/kernel/ebin/erpc.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/error_handler.beam b/bootstrap/lib/kernel/ebin/error_handler.beam
index 9d9adb5821..5e6481da1b 100644
--- a/bootstrap/lib/kernel/ebin/error_handler.beam
+++ b/bootstrap/lib/kernel/ebin/error_handler.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/error_logger.beam b/bootstrap/lib/kernel/ebin/error_logger.beam
index 0ffc0cbd33..2c4c9ae9e2 100644
--- a/bootstrap/lib/kernel/ebin/error_logger.beam
+++ b/bootstrap/lib/kernel/ebin/error_logger.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam
index b664ba005c..bba00e14cf 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 9e2ccc4384..d69b38b480 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 62e072baa7..cb8a5b7a37 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 bba2f326cb..f4a6071ae3 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 66396860ff..dfdbe10785 100644
--- a/bootstrap/lib/kernel/ebin/gen_sctp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_sctp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_tcp.beam b/bootstrap/lib/kernel/ebin/gen_tcp.beam
index d75a5929e7..5608de516d 100644
--- a/bootstrap/lib/kernel/ebin/gen_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_tcp_socket.beam b/bootstrap/lib/kernel/ebin/gen_tcp_socket.beam
index 81a7468900..adcec4c7be 100644
--- a/bootstrap/lib/kernel/ebin/gen_tcp_socket.beam
+++ b/bootstrap/lib/kernel/ebin/gen_tcp_socket.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_udp.beam b/bootstrap/lib/kernel/ebin/gen_udp.beam
index 7cdaa38fd1..48781ba99e 100644
--- a/bootstrap/lib/kernel/ebin/gen_udp.beam
+++ b/bootstrap/lib/kernel/ebin/gen_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/gen_udp_socket.beam b/bootstrap/lib/kernel/ebin/gen_udp_socket.beam
index 3ce5054285..a6a7d41527 100644
--- a/bootstrap/lib/kernel/ebin/gen_udp_socket.beam
+++ b/bootstrap/lib/kernel/ebin/gen_udp_socket.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index 845fb5a468..400fe44990 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 6d000d094b..bbd677f1e8 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/global_search.beam b/bootstrap/lib/kernel/ebin/global_search.beam
index b17d493d95..d5afafae8f 100644
--- a/bootstrap/lib/kernel/ebin/global_search.beam
+++ b/bootstrap/lib/kernel/ebin/global_search.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index bd8ad6948e..27539c6a71 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/group_history.beam b/bootstrap/lib/kernel/ebin/group_history.beam
index f95b1229ee..6bd7e769be 100644
--- a/bootstrap/lib/kernel/ebin/group_history.beam
+++ b/bootstrap/lib/kernel/ebin/group_history.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/heart.beam b/bootstrap/lib/kernel/ebin/heart.beam
index 487209598b..c72c5b0282 100644
--- a/bootstrap/lib/kernel/ebin/heart.beam
+++ b/bootstrap/lib/kernel/ebin/heart.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index c114a8912b..a1dfdf7386 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 936fcc48ba..4efce5fba3 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 8b10ad0dca..a96c63068e 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 76afbf35a5..a18f62b192 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 1e4d69b59d..fd6e7f85c0 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 f36e6c5592..0eaaa71602 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 cddd91d3d0..4ce7dd6734 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 9d7ef22eb9..bddba494d9 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 4103e7df17..751f7c14f6 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_hosts.beam b/bootstrap/lib/kernel/ebin/inet_hosts.beam
index d79726f6b9..5800de74dc 100644
--- a/bootstrap/lib/kernel/ebin/inet_hosts.beam
+++ b/bootstrap/lib/kernel/ebin/inet_hosts.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index e55e747bc7..397ec05343 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 19e502bb83..f034500a1a 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 4c72f7820c..1f79fea238 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 e3990c9f71..e46beb502c 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 30d1eedbc3..8d9610fade 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 f16a67b59f..0c04828317 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.app b/bootstrap/lib/kernel/ebin/kernel.app
index 8621630ad5..41e6a62a44 100644
--- a/bootstrap/lib/kernel/ebin/kernel.app
+++ b/bootstrap/lib/kernel/ebin/kernel.app
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
{application, kernel,
[
{description, "ERTS CXC 138 10"},
- {vsn, "8.0.2"},
+ {vsn, "8.4.2"},
{modules, [application,
application_controller,
application_master,
@@ -152,9 +152,12 @@
{applications, []},
{env, [{logger_level, notice},
{logger_sasl_compatible, false},
+ {net_tickintensity, 4},
+ {net_ticktime, 60},
+ {prevent_overlapping_partitions, true},
{shell_docs_ansi,auto}
]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-12.0", "stdlib-3.13", "sasl-3.0", "crypto-5.0"]}
- ]
+ {runtime_dependencies, ["erts-@OTP-17934@", "stdlib-4.0", "sasl-3.0", "crypto-5.0"]}
+ ]
}.
diff --git a/bootstrap/lib/kernel/ebin/kernel.appup b/bootstrap/lib/kernel/ebin/kernel.appup
index 5f6d9d3988..cf88faffac 100644
--- a/bootstrap/lib/kernel/ebin/kernel.appup
+++ b/bootstrap/lib/kernel/ebin/kernel.appup
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,49 +19,72 @@
%%
%% We allow upgrade from, and downgrade to all previous
%% versions from the following OTP releases:
-%% - OTP 20
-%% - OTP 21
+%% - OTP 22
+%% - OTP 23
+%% - OTP 24
%%
%% We also allow upgrade from, and downgrade to all
%% versions that have branched off from the above
%% stated previous versions.
%%
-{"6.3.1",
- [{<<"^5\\.3$">>,[restart_new_emulator]},
- {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^5\\.4$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.0$">>,[restart_new_emulator]},
- {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.1$">>,[restart_new_emulator]},
- {<<"^6\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.2$">>,[restart_new_emulator]},
- {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.3$">>,[restart_new_emulator]},
- {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
- [{<<"^5\\.3$">>,[restart_new_emulator]},
- {<<"^5\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^5\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^5\\.4$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^5\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.0$">>,[restart_new_emulator]},
- {<<"^6\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.1$">>,[restart_new_emulator]},
- {<<"^6\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.2$">>,[restart_new_emulator]},
- {<<"^6\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.3$">>,[restart_new_emulator]},
- {<<"^6\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
+{"8.3.1",
+ [{<<"^6\\.4$">>,[restart_new_emulator]},
+ {<<"^6\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.5$">>,[restart_new_emulator]},
+ {<<"^6\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.5\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^7\\.0$">>,[restart_new_emulator]},
+ {<<"^7\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.1$">>,[restart_new_emulator]},
+ {<<"^7\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.2$">>,[restart_new_emulator]},
+ {<<"^7\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^7\\.3$">>,[restart_new_emulator]},
+ {<<"^7\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.0$">>,[restart_new_emulator]},
+ {<<"^8\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.0\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.1$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.2$">>,[restart_new_emulator]},
+ {<<"^8\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.3$">>,[restart_new_emulator]},
+ {<<"^8\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
+ [{<<"^6\\.4$">>,[restart_new_emulator]},
+ {<<"^6\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.5$">>,[restart_new_emulator]},
+ {<<"^6\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^6\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^6\\.5\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^7\\.0$">>,[restart_new_emulator]},
+ {<<"^7\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.1$">>,[restart_new_emulator]},
+ {<<"^7\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.2$">>,[restart_new_emulator]},
+ {<<"^7\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.2\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^7\\.3$">>,[restart_new_emulator]},
+ {<<"^7\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^7\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.0$">>,[restart_new_emulator]},
+ {<<"^8\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.0\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.1$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.1\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.2$">>,[restart_new_emulator]},
+ {<<"^8\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.3$">>,[restart_new_emulator]},
+ {<<"^8\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
diff --git a/bootstrap/lib/kernel/ebin/kernel.beam b/bootstrap/lib/kernel/ebin/kernel.beam
index d217f6fcc4..d7e2514c41 100644
--- a/bootstrap/lib/kernel/ebin/kernel.beam
+++ b/bootstrap/lib/kernel/ebin/kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel_config.beam b/bootstrap/lib/kernel/ebin/kernel_config.beam
index 7850013863..fc20a076c5 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/kernel_refc.beam b/bootstrap/lib/kernel/ebin/kernel_refc.beam
index 31746a1ef8..85c941e15f 100644
--- a/bootstrap/lib/kernel/ebin/kernel_refc.beam
+++ b/bootstrap/lib/kernel/ebin/kernel_refc.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/local_tcp.beam b/bootstrap/lib/kernel/ebin/local_tcp.beam
index 1bd2d4186a..57db9ec840 100644
--- a/bootstrap/lib/kernel/ebin/local_tcp.beam
+++ b/bootstrap/lib/kernel/ebin/local_tcp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/local_udp.beam b/bootstrap/lib/kernel/ebin/local_udp.beam
index 948787c506..67aadf1bc4 100644
--- a/bootstrap/lib/kernel/ebin/local_udp.beam
+++ b/bootstrap/lib/kernel/ebin/local_udp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger.beam b/bootstrap/lib/kernel/ebin/logger.beam
index 6c6bb11c40..72301c71e9 100644
--- a/bootstrap/lib/kernel/ebin/logger.beam
+++ b/bootstrap/lib/kernel/ebin/logger.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_backend.beam b/bootstrap/lib/kernel/ebin/logger_backend.beam
index d414ca24ed..0c0a2720de 100644
--- a/bootstrap/lib/kernel/ebin/logger_backend.beam
+++ b/bootstrap/lib/kernel/ebin/logger_backend.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_config.beam b/bootstrap/lib/kernel/ebin/logger_config.beam
index afa44cdab1..aeef730533 100644
--- a/bootstrap/lib/kernel/ebin/logger_config.beam
+++ b/bootstrap/lib/kernel/ebin/logger_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_disk_log_h.beam b/bootstrap/lib/kernel/ebin/logger_disk_log_h.beam
index df2a359a78..9b0de072dd 100644
--- a/bootstrap/lib/kernel/ebin/logger_disk_log_h.beam
+++ b/bootstrap/lib/kernel/ebin/logger_disk_log_h.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_filters.beam b/bootstrap/lib/kernel/ebin/logger_filters.beam
index 99cb32c42b..d33846bd2a 100644
--- a/bootstrap/lib/kernel/ebin/logger_filters.beam
+++ b/bootstrap/lib/kernel/ebin/logger_filters.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_formatter.beam b/bootstrap/lib/kernel/ebin/logger_formatter.beam
index 0874f8de46..693d6d96ae 100644
--- a/bootstrap/lib/kernel/ebin/logger_formatter.beam
+++ b/bootstrap/lib/kernel/ebin/logger_formatter.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_h_common.beam b/bootstrap/lib/kernel/ebin/logger_h_common.beam
index 61aaf23b0a..22b9bc16b4 100644
--- a/bootstrap/lib/kernel/ebin/logger_h_common.beam
+++ b/bootstrap/lib/kernel/ebin/logger_h_common.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_handler_watcher.beam b/bootstrap/lib/kernel/ebin/logger_handler_watcher.beam
index ad8bbdd5a7..31c251072e 100644
--- a/bootstrap/lib/kernel/ebin/logger_handler_watcher.beam
+++ b/bootstrap/lib/kernel/ebin/logger_handler_watcher.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_olp.beam b/bootstrap/lib/kernel/ebin/logger_olp.beam
index f5b3861acc..bf3dd071e4 100644
--- a/bootstrap/lib/kernel/ebin/logger_olp.beam
+++ b/bootstrap/lib/kernel/ebin/logger_olp.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_proxy.beam b/bootstrap/lib/kernel/ebin/logger_proxy.beam
index b5bd6def77..886518885a 100644
--- a/bootstrap/lib/kernel/ebin/logger_proxy.beam
+++ b/bootstrap/lib/kernel/ebin/logger_proxy.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_server.beam b/bootstrap/lib/kernel/ebin/logger_server.beam
index e92a88dd30..3b1f42dd85 100644
--- a/bootstrap/lib/kernel/ebin/logger_server.beam
+++ b/bootstrap/lib/kernel/ebin/logger_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_simple_h.beam b/bootstrap/lib/kernel/ebin/logger_simple_h.beam
index f971063e01..cb5a4fb840 100644
--- a/bootstrap/lib/kernel/ebin/logger_simple_h.beam
+++ b/bootstrap/lib/kernel/ebin/logger_simple_h.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_std_h.beam b/bootstrap/lib/kernel/ebin/logger_std_h.beam
index 34d19eb954..d2c7d0eec9 100644
--- a/bootstrap/lib/kernel/ebin/logger_std_h.beam
+++ b/bootstrap/lib/kernel/ebin/logger_std_h.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/logger_sup.beam b/bootstrap/lib/kernel/ebin/logger_sup.beam
index 907dcd93fe..45e372bd1e 100644
--- a/bootstrap/lib/kernel/ebin/logger_sup.beam
+++ b/bootstrap/lib/kernel/ebin/logger_sup.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net.beam b/bootstrap/lib/kernel/ebin/net.beam
index a294780780..90bc08647f 100644
--- a/bootstrap/lib/kernel/ebin/net.beam
+++ b/bootstrap/lib/kernel/ebin/net.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_adm.beam b/bootstrap/lib/kernel/ebin/net_adm.beam
index 49611f3793..d75024222e 100644
--- a/bootstrap/lib/kernel/ebin/net_adm.beam
+++ b/bootstrap/lib/kernel/ebin/net_adm.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index 65a54f22e9..15a4a6cd13 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 a907f9f2c6..133cdf6a1e 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/pg.beam b/bootstrap/lib/kernel/ebin/pg.beam
index 2dd5265a20..4f9a42e674 100644
--- a/bootstrap/lib/kernel/ebin/pg.beam
+++ b/bootstrap/lib/kernel/ebin/pg.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/pg2.beam b/bootstrap/lib/kernel/ebin/pg2.beam
index bdd7cae857..fdfdb68586 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/ram_file.beam b/bootstrap/lib/kernel/ebin/ram_file.beam
index d1c4df77a4..b228ce08ad 100644
--- a/bootstrap/lib/kernel/ebin/ram_file.beam
+++ b/bootstrap/lib/kernel/ebin/ram_file.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/raw_file_io.beam b/bootstrap/lib/kernel/ebin/raw_file_io.beam
index 62ee19cba8..bdc921a5b7 100644
--- a/bootstrap/lib/kernel/ebin/raw_file_io.beam
+++ b/bootstrap/lib/kernel/ebin/raw_file_io.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/raw_file_io_compressed.beam b/bootstrap/lib/kernel/ebin/raw_file_io_compressed.beam
index 66339ffa5e..7b524c62e6 100644
--- a/bootstrap/lib/kernel/ebin/raw_file_io_compressed.beam
+++ b/bootstrap/lib/kernel/ebin/raw_file_io_compressed.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/raw_file_io_deflate.beam b/bootstrap/lib/kernel/ebin/raw_file_io_deflate.beam
index 6deb5b7a66..69037c86d3 100644
--- a/bootstrap/lib/kernel/ebin/raw_file_io_deflate.beam
+++ b/bootstrap/lib/kernel/ebin/raw_file_io_deflate.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/raw_file_io_delayed.beam b/bootstrap/lib/kernel/ebin/raw_file_io_delayed.beam
index d83bbec42f..51b0dd4e83 100644
--- a/bootstrap/lib/kernel/ebin/raw_file_io_delayed.beam
+++ b/bootstrap/lib/kernel/ebin/raw_file_io_delayed.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/raw_file_io_inflate.beam b/bootstrap/lib/kernel/ebin/raw_file_io_inflate.beam
index 352f905904..68cefab06f 100644
--- a/bootstrap/lib/kernel/ebin/raw_file_io_inflate.beam
+++ b/bootstrap/lib/kernel/ebin/raw_file_io_inflate.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/raw_file_io_list.beam b/bootstrap/lib/kernel/ebin/raw_file_io_list.beam
index e051c80ee9..4f68c9f208 100644
--- a/bootstrap/lib/kernel/ebin/raw_file_io_list.beam
+++ b/bootstrap/lib/kernel/ebin/raw_file_io_list.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/rpc.beam b/bootstrap/lib/kernel/ebin/rpc.beam
index 353f3d81d6..65985f0b84 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/seq_trace.beam b/bootstrap/lib/kernel/ebin/seq_trace.beam
index 6090ce2659..3420f59316 100644
--- a/bootstrap/lib/kernel/ebin/seq_trace.beam
+++ b/bootstrap/lib/kernel/ebin/seq_trace.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/socket.beam b/bootstrap/lib/kernel/ebin/socket.beam
index 609fb30f6a..8d9c933cb8 100644
--- a/bootstrap/lib/kernel/ebin/socket.beam
+++ b/bootstrap/lib/kernel/ebin/socket.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/standard_error.beam b/bootstrap/lib/kernel/ebin/standard_error.beam
index e42d15babc..6d8bb3ca9c 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 2d28cec7d3..a75e13ad1f 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 e3d5927875..94e7ecdf7e 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 3baabe7f8a..40ee18f38d 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/ebin/wrap_log_reader.beam b/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
index 59dcb3bb4c..ce175874ec 100644
--- a/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
+++ b/bootstrap/lib/kernel/ebin/wrap_log_reader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/include/dist.hrl b/bootstrap/lib/kernel/include/dist.hrl
index 10460ba3e8..16320b64e9 100644
--- a/bootstrap/lib/kernel/include/dist.hrl
+++ b/bootstrap/lib/kernel/include/dist.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,43 +22,90 @@
%% Distribution capabilities flags (corresponds with dist.h).
%%
--define(DFLAG_PUBLISHED,1).
--define(DFLAG_ATOM_CACHE,2).
--define(DFLAG_EXTENDED_REFERENCES,4).
--define(DFLAG_DIST_MONITOR,8).
--define(DFLAG_FUN_TAGS,16#10).
--define(DFLAG_DIST_MONITOR_NAME,16#20).
--define(DFLAG_HIDDEN_ATOM_CACHE,16#40).
--define(DFLAG_NEW_FUN_TAGS,16#80).
--define(DFLAG_EXTENDED_PIDS_PORTS,16#100).
--define(DFLAG_EXPORT_PTR_TAG,16#200).
--define(DFLAG_BIT_BINARIES,16#400).
--define(DFLAG_NEW_FLOATS,16#800).
--define(DFLAG_UNICODE_IO,16#1000).
--define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000).
--define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
--define(DFLAG_UTF8_ATOMS, 16#10000).
--define(DFLAG_MAP_TAG, 16#20000).
--define(DFLAG_BIG_CREATION, 16#40000).
--define(DFLAG_SEND_SENDER, 16#80000).
--define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000).
-%% -define(DFLAG_NO_MAGIC, 16#200000). %% Used internally only
--define(DFLAG_EXIT_PAYLOAD, 16#400000).
--define(DFLAG_FRAGMENTS, 16#00800000).
--define(DFLAG_HANDSHAKE_23, 16#01000000).
--define(DFLAG_RESERVED, 16#fe000000).
--define(DFLAG_SPAWN, 16#100000000).
--define(DFLAG_NAME_ME, 16#200000000).
--define(DFLAG_V4_NC, 16#400000000).
--define(DFLAG_ALIAS, 16#800000000).
+-define(DFLAG_PUBLISHED, 16#01).
+-define(DFLAG_ATOM_CACHE, 16#02).
+-define(DFLAG_EXTENDED_REFERENCES, 16#04).
+-define(DFLAG_DIST_MONITOR, 16#08).
+-define(DFLAG_FUN_TAGS, 16#10).
+-define(DFLAG_DIST_MONITOR_NAME, 16#20).
+-define(DFLAG_HIDDEN_ATOM_CACHE, 16#40).
+-define(DFLAG_NEW_FUN_TAGS, 16#80).
+-define(DFLAG_EXTENDED_PIDS_PORTS, 16#100).
+-define(DFLAG_EXPORT_PTR_TAG, 16#200).
+-define(DFLAG_BIT_BINARIES, 16#400).
+-define(DFLAG_NEW_FLOATS, 16#800).
+-define(DFLAG_UNICODE_IO, 16#1000).
+-define(DFLAG_DIST_HDR_ATOM_CACHE, 16#2000).
+-define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
+-define(DFLAG_UTF8_ATOMS, 16#10000).
+-define(DFLAG_MAP_TAG, 16#20000).
+-define(DFLAG_BIG_CREATION, 16#40000).
+-define(DFLAG_SEND_SENDER, 16#80000).
+-define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000).
+%% -define(DFLAG_NO_MAGIC, 16#200000). %% Used internally only
+-define(DFLAG_EXIT_PAYLOAD, 16#400000).
+-define(DFLAG_FRAGMENTS, 16#00800000).
+-define(DFLAG_HANDSHAKE_23, 16#01000000).
+-define(DFLAG_UNLINK_ID, 16#02000000).
+-define(DFLAG_MANDATORY_25_DIGEST, 16#04000000).
+-define(DFLAG_RESERVED, 16#f8000000).
+
+%% Second 32-bit flag word.
+-define(DFLAG_SPAWN, (16#01 bsl 32)).
+-define(DFLAG_NAME_ME, (16#02 bsl 32)).
+-define(DFLAG_V4_NC, (16#04 bsl 32)).
+-define(DFLAG_ALIAS, (16#08 bsl 32)).
+
+%% The following flags are mandatory in OTP 25. OTP 25 and higher
+%% will accept ?DFLAG_MANDATORY_25_DIGEST as a shorthand for all those
+%% flags.
+-define(MANDATORY_DFLAGS_25,
+ (?DFLAG_EXTENDED_REFERENCES bor
+ ?DFLAG_FUN_TAGS bor
+ ?DFLAG_EXTENDED_PIDS_PORTS bor
+ ?DFLAG_NEW_FUN_TAGS bor
+ ?DFLAG_EXPORT_PTR_TAG bor
+ ?DFLAG_BIT_BINARIES bor
+ ?DFLAG_NEW_FLOATS bor
+ ?DFLAG_UTF8_ATOMS bor
+ ?DFLAG_MAP_TAG bor
+ ?DFLAG_BIG_CREATION bor
+ ?DFLAG_HANDSHAKE_23)).
%% Also update dflag2str() in ../src/dist_util.erl
%% when adding flags...
+-define(ERL_DIST_VER_6, 6). % OTP-23 at least
--define(ERL_DIST_VER_5, 5). % OTP-22 or (much) older
--define(ERL_DIST_VER_6, 6). % OTP-23 (or maybe newer?)
-
--define(ERL_DIST_VER_LOW, ?ERL_DIST_VER_5).
+-define(ERL_DIST_VER_LOW, ?ERL_DIST_VER_6).
-define(ERL_DIST_VER_HIGH, ?ERL_DIST_VER_6).
+%%%
+%%% To avoid having to extend the number of distribution flags from 64
+%%% to 128, a scheme for garbage collection of the flags was
+%%% introduced in OTP 25.
+%%%
+%%% In OTP 25, ?DFLAG_MANDATORY_25_DIGEST was introduced as a synonym
+%%% for the flags defined by ?MANDATORY_DFLAGS_25. OTP 25/26 will
+%%% accept the old flags to support communication with 24 and earlier,
+%%% as well as ?DFLAG_MANDATORY_25_DIGEST.
+%%%
+%%% OTP 27 will make ?DFLAG_MANDATORY_25_DIGEST mandatory, meaning that an
+%%% OTP 27 node can only communicate with OTP 25 and higher.
+%%%
+%%% An OTP 27 node will also introduce the new flag
+%%% ?DFLAG_MANDATORY_27_DIGEST:
+%%%
+%%% * If ?DFLAG_MANDATORY_27_DIGEST is set, it means that all bit
+%%% numbers defined by ?MANDATORY_DFLAGS_25, as well as the bit
+%%% number defined by ?DFLAG_MANDATORY_25_DIGEST and any other bits
+%%% made mandatory in OTP 26/27, lose their previous meanings. New
+%%% meanings can then be assigned to those bit numbers as
+%%% needed. (This is for communication between nodes from OTP 27 and
+%%% up.)
+%%%
+%%% * If ?DFLAG_MANDATORY_27_DIGEST is not set, then
+%%% ?DFLAG_MANDATORY_25_DIGEST must be set and all bit numbers
+%%% defined by ?MANDATORY_DFLAGS_25 are ignored. (This is for
+%%% communication between an OTP 27 node and an OTP 25/26 node.)
+%%%
diff --git a/bootstrap/lib/kernel/include/inet_sctp.hrl b/bootstrap/lib/kernel/include/inet_sctp.hrl
index ddb3cdc26c..11b06fd8e6 100644
--- a/bootstrap/lib/kernel/include/inet_sctp.hrl
+++ b/bootstrap/lib/kernel/include/inet_sctp.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -120,7 +120,7 @@
}).
%% sctp_partial_delivery_event: XXX: Not clear whether it is delivered to
-%% the Sender or to the Recepient (probably the
+%% the Sender or to the Recipient (probably the
%% former). Currently, there is only 1 possible
%% value for "indication":
-record(sctp_pdapi_event,
diff --git a/bootstrap/lib/stdlib/ebin/array.beam b/bootstrap/lib/stdlib/ebin/array.beam
index e837453f20..524748417f 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 634e301aa2..11518d9f17 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 ed700d6ba8..3a1295416a 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/binary.beam b/bootstrap/lib/stdlib/ebin/binary.beam
index 7ec31e98b1..5a66369e6f 100644
--- a/bootstrap/lib/stdlib/ebin/binary.beam
+++ b/bootstrap/lib/stdlib/ebin/binary.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index d90c1727fd..7899bb9f36 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/calendar.beam b/bootstrap/lib/stdlib/ebin/calendar.beam
index 5915a4e686..cb9126dce9 100644
--- a/bootstrap/lib/stdlib/ebin/calendar.beam
+++ b/bootstrap/lib/stdlib/ebin/calendar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index 3e0f0f5b23..d14c8463eb 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 a00e8d91d9..e971702773 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_sup.beam b/bootstrap/lib/stdlib/ebin/dets_sup.beam
index 575f88338a..f2e6e08cc4 100644
--- a/bootstrap/lib/stdlib/ebin/dets_sup.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_sup.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index 8f93a0809f..952ea82f16 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_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index 8cf80d1a5c..a98b4fbeac 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 a630f87dd0..e1a8cf4730 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 d458194421..b74ee31cb7 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 8c0f7ffff4..8e85e8c45b 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/edlin.beam b/bootstrap/lib/stdlib/ebin/edlin.beam
index 4538f56b68..e043c8e023 100644
--- a/bootstrap/lib/stdlib/ebin/edlin.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/edlin_expand.beam b/bootstrap/lib/stdlib/ebin/edlin_expand.beam
index 82bd92df92..c2c1b4d05d 100644
--- a/bootstrap/lib/stdlib/ebin/edlin_expand.beam
+++ b/bootstrap/lib/stdlib/ebin/edlin_expand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index 78cc9153c4..3a1b9b2c51 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_abstract_code.beam b/bootstrap/lib/stdlib/ebin/erl_abstract_code.beam
index 9a7662ac94..1a93db5293 100644
--- a/bootstrap/lib/stdlib/ebin/erl_abstract_code.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_abstract_code.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_anno.beam b/bootstrap/lib/stdlib/ebin/erl_anno.beam
index ad2d06a96f..c454c5a045 100644
--- a/bootstrap/lib/stdlib/ebin/erl_anno.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_anno.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_bits.beam b/bootstrap/lib/stdlib/ebin/erl_bits.beam
index 46397437fc..61783aa8ac 100644
--- a/bootstrap/lib/stdlib/ebin/erl_bits.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_bits.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_compile.beam b/bootstrap/lib/stdlib/ebin/erl_compile.beam
index 17da56bdc8..d099a6f6dd 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_error.beam b/bootstrap/lib/stdlib/ebin/erl_error.beam
index 3a0a7d1110..635538c302 100644
--- a/bootstrap/lib/stdlib/ebin/erl_error.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_error.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 520a833887..67b6e845c4 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 d37758d1f0..9ad674ee8d 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_features.beam b/bootstrap/lib/stdlib/ebin/erl_features.beam
new file mode 100644
index 0000000000..514b284b0c
--- /dev/null
+++ b/bootstrap/lib/stdlib/ebin/erl_features.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_internal.beam b/bootstrap/lib/stdlib/ebin/erl_internal.beam
index bf480ea73b..3378f7da67 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 225ee318c2..04fc9beb5f 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 c0fe981ad4..87f83e0785 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_posix_msg.beam b/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam
index cf5239d693..b6a8d36cc4 100644
--- a/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_posix_msg.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index cf0edba32c..c92824793e 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 0bde6b6502..7539589cf2 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_stdlib_errors.beam b/bootstrap/lib/stdlib/ebin/erl_stdlib_errors.beam
index 58c370a6af..ebc80456ca 100644
--- a/bootstrap/lib/stdlib/ebin/erl_stdlib_errors.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_stdlib_errors.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index be66732e82..cdc886065a 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 036c8d418c..0043d2ef08 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 ce0d9a1d72..21bd44dbad 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 4c17b6ad2c..04ec6a6950 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 7579a1f031..c48177baad 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 28da62ef02..a91463ff94 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 ad98ee9aa3..fd5139a87f 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 4124948a8d..22007daa9c 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 f6e8bc2610..6720bb7dd1 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 bd84607fae..52d96aa43f 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 454ba0aa9f..5b37aa2d76 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 a989fa0f8a..6966526786 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 2e178c76cf..96713a520c 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 893084c55a..5b4d9a3ebb 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 65344338eb..7236b5869c 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/gen_statem.beam b/bootstrap/lib/stdlib/ebin/gen_statem.beam
index 14f6f1b4ca..fc6e8519fe 100644
--- a/bootstrap/lib/stdlib/ebin/gen_statem.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_statem.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io.beam b/bootstrap/lib/stdlib/ebin/io.beam
index a54a1e2865..0f5568c606 100644
--- a/bootstrap/lib/stdlib/ebin/io.beam
+++ b/bootstrap/lib/stdlib/ebin/io.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib.beam b/bootstrap/lib/stdlib/ebin/io_lib.beam
index 838e1764fe..db1f8aa987 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_format.beam b/bootstrap/lib/stdlib/ebin/io_lib_format.beam
index 988d41cb8a..4f12310de2 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_format.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_format.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_format_ryu_table.beam b/bootstrap/lib/stdlib/ebin/io_lib_format_ryu_table.beam
deleted file mode 100644
index 7d95fef996..0000000000
--- a/bootstrap/lib/stdlib/ebin/io_lib_format_ryu_table.beam
+++ /dev/null
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_fread.beam b/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
index 2b29e395c5..f25a79f330 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_fread.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_fread.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 1c0b4f9885..a8b6b41207 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/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index 95cfff6211..d321ccd6eb 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 30fc545d63..5a568cf644 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/maps.beam b/bootstrap/lib/stdlib/ebin/maps.beam
index 2a273d6d8e..0504de1ac9 100644
--- a/bootstrap/lib/stdlib/ebin/maps.beam
+++ b/bootstrap/lib/stdlib/ebin/maps.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/math.beam b/bootstrap/lib/stdlib/ebin/math.beam
index 7abbc9385b..e7c040cc4a 100644
--- a/bootstrap/lib/stdlib/ebin/math.beam
+++ b/bootstrap/lib/stdlib/ebin/math.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index 917fc45f40..7cd3c22c07 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 3d629804f7..9c642b7870 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/ordsets.beam b/bootstrap/lib/stdlib/ebin/ordsets.beam
index 3e904d7e86..efa72b347e 100644
--- a/bootstrap/lib/stdlib/ebin/ordsets.beam
+++ b/bootstrap/lib/stdlib/ebin/ordsets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam
index fd7795c36f..f2a9b45765 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/peer.beam b/bootstrap/lib/stdlib/ebin/peer.beam
new file mode 100644
index 0000000000..04b0178880
--- /dev/null
+++ b/bootstrap/lib/stdlib/ebin/peer.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/pool.beam b/bootstrap/lib/stdlib/ebin/pool.beam
index 04e83527a6..566c6e90eb 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 f15a7e2199..1a1f08b08f 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/proplists.beam b/bootstrap/lib/stdlib/ebin/proplists.beam
index e3d584e232..aa386d7655 100644
--- a/bootstrap/lib/stdlib/ebin/proplists.beam
+++ b/bootstrap/lib/stdlib/ebin/proplists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index cb59b4e6a2..6663fb5c23 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 4f5e240e4a..40cac7a2f9 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 f06730ff26..0ffc140ea9 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/rand.beam b/bootstrap/lib/stdlib/ebin/rand.beam
index 86e447a949..a7938b8762 100644
--- a/bootstrap/lib/stdlib/ebin/rand.beam
+++ b/bootstrap/lib/stdlib/ebin/rand.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/random.beam b/bootstrap/lib/stdlib/ebin/random.beam
index 82da848474..e1ba2deacb 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 4eb8ad8b32..3e577c8768 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/sets.beam b/bootstrap/lib/stdlib/ebin/sets.beam
index 8bd8c5dca4..a684a570bf 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 fe013f311b..a6f9c3e3a4 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/shell_default.beam b/bootstrap/lib/stdlib/ebin/shell_default.beam
index 6c66342b86..167512d9f1 100644
--- a/bootstrap/lib/stdlib/ebin/shell_default.beam
+++ b/bootstrap/lib/stdlib/ebin/shell_default.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell_docs.beam b/bootstrap/lib/stdlib/ebin/shell_docs.beam
index edd19f9c8d..8fee06ffcd 100644
--- a/bootstrap/lib/stdlib/ebin/shell_docs.beam
+++ b/bootstrap/lib/stdlib/ebin/shell_docs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/slave.beam b/bootstrap/lib/stdlib/ebin/slave.beam
index 271fedf8a8..30f8d8d154 100644
--- a/bootstrap/lib/stdlib/ebin/slave.beam
+++ b/bootstrap/lib/stdlib/ebin/slave.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index 9d5a0d4fa2..e99d617c91 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/stdlib.app b/bootstrap/lib/stdlib/ebin/stdlib.app
index dd1a969d3d..ce39d8fbdb 100644
--- a/bootstrap/lib/stdlib/ebin/stdlib.app
+++ b/bootstrap/lib/stdlib/ebin/stdlib.app
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
%%
{application, stdlib,
[{description, "ERTS CXC 138 10"},
- {vsn, "3.15.2"},
+ {vsn, "4.0.1"},
{modules, [array,
base64,
beam_lib,
@@ -46,6 +46,7 @@
erl_error,
erl_eval,
erl_expand_records,
+ erl_features,
erl_internal,
erl_lint,
erl_parse,
@@ -71,7 +72,6 @@
io,
io_lib,
io_lib_format,
- io_lib_format_ryu_table,
io_lib_fread,
io_lib_pretty,
lists,
@@ -82,6 +82,7 @@
orddict,
ordsets,
otp_internal,
+ peer,
pool,
proc_lib,
proplists,
@@ -111,6 +112,6 @@
dets]},
{applications, [kernel]},
{env, []},
- {runtime_dependencies, ["sasl-3.0","kernel-7.0","erts-12.0","crypto-3.3",
+ {runtime_dependencies, ["sasl-3.0","kernel-8.4","erts-@OTP-17934@","crypto-4.5",
"compiler-5.0"]}
]}.
diff --git a/bootstrap/lib/stdlib/ebin/stdlib.appup b/bootstrap/lib/stdlib/ebin/stdlib.appup
index cf693f332c..5c7e569773 100644
--- a/bootstrap/lib/stdlib/ebin/stdlib.appup
+++ b/bootstrap/lib/stdlib/ebin/stdlib.appup
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,45 +19,72 @@
%%
%% We allow upgrade from, and downgrade to all previous
%% versions from the following OTP releases:
-%% - OTP 20
-%% - OTP 21
+%% - OTP 22
+%% - OTP 23
+%% - OTP 24
%%
%% We also allow upgrade from, and downgrade to all
%% versions that have branched off from the above
%% stated previous versions.
%%
-{"3.8.1",
- [{<<"^3\\.4$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.5$">>,[restart_new_emulator]},
- {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.6$">>,[restart_new_emulator]},
- {<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.7$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.8$">>,[restart_new_emulator]},
- {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
- [{<<"^3\\.4$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.4(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.5(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.5$">>,[restart_new_emulator]},
- {<<"^3\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.6$">>,[restart_new_emulator]},
- {<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.7$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.8$">>,[restart_new_emulator]},
- {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
+{"3.17.1",
+ [{<<"^3\\.10$">>,[restart_new_emulator]},
+ {<<"^3\\.10\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.11$">>,[restart_new_emulator]},
+ {<<"^3\\.11\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.11\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.11\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.12$">>,[restart_new_emulator]},
+ {<<"^3\\.12\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.12\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.13$">>,[restart_new_emulator]},
+ {<<"^3\\.13\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.13\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.13\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.14$">>,[restart_new_emulator]},
+ {<<"^3\\.14\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.14\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.14\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.15$">>,[restart_new_emulator]},
+ {<<"^3\\.15\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.15\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.15\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.16$">>,[restart_new_emulator]},
+ {<<"^3\\.16\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.16\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.17$">>,[restart_new_emulator]},
+ {<<"^3\\.17\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.9$">>,[restart_new_emulator]},
+ {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.9\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.9\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
+ [{<<"^3\\.10$">>,[restart_new_emulator]},
+ {<<"^3\\.10\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.11$">>,[restart_new_emulator]},
+ {<<"^3\\.11\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.11\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.11\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.12$">>,[restart_new_emulator]},
+ {<<"^3\\.12\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.12\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.13$">>,[restart_new_emulator]},
+ {<<"^3\\.13\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.13\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.13\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.14$">>,[restart_new_emulator]},
+ {<<"^3\\.14\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.14\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.14\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.15$">>,[restart_new_emulator]},
+ {<<"^3\\.15\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.15\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.15\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.16$">>,[restart_new_emulator]},
+ {<<"^3\\.16\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.16\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.17$">>,[restart_new_emulator]},
+ {<<"^3\\.17\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.9$">>,[restart_new_emulator]},
+ {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^3\\.9\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.9\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam
index c1e09b2c27..330c4dd4ad 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 84bd2bac57..8a8f890e79 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 ad695813fc..007655f5cd 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 2ee1592d14..509e06b790 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 9fe97e284f..0191b0d795 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 e0bd7593d2..2c3e157da6 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/unicode_util.beam b/bootstrap/lib/stdlib/ebin/unicode_util.beam
index 0a150bf0e1..476c314d42 100644
--- a/bootstrap/lib/stdlib/ebin/unicode_util.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode_util.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/uri_string.beam b/bootstrap/lib/stdlib/ebin/uri_string.beam
index 076e3e74e8..e8db2b5215 100644
--- a/bootstrap/lib/stdlib/ebin/uri_string.beam
+++ b/bootstrap/lib/stdlib/ebin/uri_string.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/win32reg.beam b/bootstrap/lib/stdlib/ebin/win32reg.beam
index 96869dd3f1..93c861c238 100644
--- a/bootstrap/lib/stdlib/ebin/win32reg.beam
+++ b/bootstrap/lib/stdlib/ebin/win32reg.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index c957632721..01fbc51291 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/configure b/configure
index 19b4b01ec8..74dc69ed7a 100755
--- a/configure
+++ b/configure
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2018-2021. All Rights Reserved.
+# Copyright Ericsson AB 2018-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -139,6 +139,10 @@ while test $# != 0; do
pie_cflags="-fno-PIE"
pie_ldflags="-no-pie"
;;
+ --enable-deterministic-build)
+ config_arguments="$config_arguments --enable-deterministic-build";;
+ --disable-deterministic-build)
+ config_arguments="$config_arguments --disable-deterministic-build";;
CFLAGS=* | LDFLAGS=*)
flgs_var=`echo "$1" | sed 's/=.*$//'`
flgs_val=`echo "$1" | sed 's/^[^=]*=//'`
diff --git a/configure.src b/configure.src
index f0afd5c6ee..d320c4520b 100644
--- a/configure.src
+++ b/configure.src
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2018-2021. All Rights Reserved.
+# Copyright Ericsson AB 2018-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -139,6 +139,10 @@ while test $# != 0; do
pie_cflags="-fno-PIE"
pie_ldflags="-no-pie"
;;
+ --enable-deterministic-build)
+ config_arguments="$config_arguments --enable-deterministic-build";;
+ --disable-deterministic-build)
+ config_arguments="$config_arguments --disable-deterministic-build";;
CFLAGS=* | LDFLAGS=*)
flgs_var=`echo "$1" | sed 's/=.*$//'`
flgs_val=`echo "$1" | sed 's/^[^=]*=//'`
diff --git a/erlang_ls.config b/erlang_ls.config
new file mode 100644
index 0000000000..a695bbc92a
--- /dev/null
+++ b/erlang_ls.config
@@ -0,0 +1,10 @@
+apps_dirs:
+ - "lib/*"
+ - "erts/preloaded"
+include_dirs:
+ - "lib/*/src"
+ - "lib/*/include"
+ - "erts/preloaded/src"
+diagnostics:
+ enabled:
+ - bound_var_in_pattern
diff --git a/erts/.gitignore b/erts/.gitignore
index 8886a8855e..954e922492 100644
--- a/erts/.gitignore
+++ b/erts/.gitignore
@@ -22,3 +22,5 @@
/emulator/pcre/pcre_exec_loop_break_cases.inc
/emulator/beam/erl_db_insert_list.ycf.h
+/emulator/ryu/obj
+/obj.debug/
diff --git a/erts/Makefile b/erts/Makefile
index 4f083752a7..cbcdaa9163 100644
--- a/erts/Makefile
+++ b/erts/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2020. All Rights Reserved.
+# Copyright Ericsson AB 2006-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,8 +40,8 @@ all: $(if $(FLAVOR),$(FLAVOR),$(PRIMARY_FLAVOR))
docs:
$(V_at)( cd doc/src && $(MAKE) $@ )
-.PHONY: debug opt lcnt clean
-debug opt lcnt clean:
+.PHONY: debug opt lcnt clean test
+$(TYPES) clean:
$(V_at)for d in emulator $(ERTSDIRS); do \
if test -d $$d; then \
( cd $$d && $(MAKE) $@ ) || exit $$?; \
@@ -49,9 +49,15 @@ debug opt lcnt clean:
done
(cd preloaded/src && $(MAKE) ../ebin/erts.app)
+
+.PHONY: test
+test:
+ TEST_NEEDS_RELEASE=true TYPE=$(TYPE) \
+ $(ERL_TOP)/make/test_target_script.sh $(ERL_TOP)
+
.PHONY: $(FLAVORS)
$(FLAVORS):
- $(V_at)for type in $(TYPES); do \
+ $(V_at)for type in $(DEFAULT_TYPES); do \
( $(MAKE) FLAVOR=$@ $$type ) || exit $$?; \
done
@@ -87,13 +93,17 @@ local_setup:
make_local_ini.sh $(ERL_TOP); \
cp $(ERL_TOP)/bin/erl.ini $(ERL_TOP)/bin/$(TARGET)/erl.ini; \
else \
+ cd etc/unix && $(MAKE); \
sed -e "s;%FINAL_ROOTDIR%;$(ERL_TOP);" \
-e "s;erts-.*/bin;bin/$(TARGET);" \
-e "s;EMU=.*;EMU=beam$(TYPEMARKER);" \
+ -e "s;%DYN_ERL_PATH%;$(TARGET)/dyn_erl;" \
+ -e "s;%DYN_ROOTDIR_BASE_EXT%;;" \
$(ERL_TOP)/erts/etc/unix/erl.src.src > $(ERL_TOP)/bin/erl; \
sed -e "s;%SRC_ROOTDIR%;$(ERL_TOP);" \
-e "s;%TARGET%;$(TARGET);" \
-e "s;%VSN%;$(VSN);" \
+ -e "s;%DYN_ERL_PATH%;$(TARGET)/dyn_erl;" \
$(ERL_TOP)/erts/etc/unix/cerl.src > $(ERL_TOP)/bin/cerl; \
cp $(ERL_TOP)/bin/$(TARGET)/erl_call $(ERL_TOP)/bin/erl_call; \
cp $(ERL_TOP)/bin/$(TARGET)/dialyzer $(ERL_TOP)/bin/dialyzer; \
@@ -141,7 +151,7 @@ makefiles:
.PHONY: release
release:
ifeq ($(TYPE),)
- for t in $(TYPES); do \
+ for t in $(DEFAULT_TYPES); do \
( cd emulator && $(MAKE) release TYPE=$$t ) || exit $$?; \
done
else
@@ -164,5 +174,3 @@ release_docs:
.PHONY: xmllint
xmllint:
$(MAKE) -C doc/src $@
-
-include $(ERL_TOP)/make/app_targets.mk
diff --git a/erts/autoconf/README.md b/erts/autoconf/README.md
new file mode 100644
index 0000000000..4643e61f49
--- /dev/null
+++ b/erts/autoconf/README.md
@@ -0,0 +1,10 @@
+All files in this directory except for the README.md files are copies
+of primary files located in the `$ERL_TOP/make/autoconf` directory.
+Files in this directory are updated automatically when executing
+`$ERL_TOP/otp_build update_configure [--no-commit]`.
+
+The files in this directory are only kept here in order not to break
+external scripts that might depend on them being here. You typically
+want to use the files in the `$ERL_TOP/make/autoconf` directory and
+*not* the ones in this directory. The files in this directory will
+eventually be removed.
diff --git a/erts/config.h.in b/erts/config.h.in
index 8295b90410..0ec4a40761 100644
--- a/erts/config.h.in
+++ b/erts/config.h.in
@@ -1,4 +1,4 @@
-/* config.h.in. Generated from configure.in by autoheader. */
+/* config.h.in. Generated from configure.ac by autoheader. */
#ifndef __ERTS_CONFIG_H__
@@ -31,6 +31,9 @@
format (like some ARMs). */
#undef DOUBLE_MIDDLE_ENDIAN
+/* Define if we need frame pointers on the Erlang stack */
+#undef ERLANG_FRAME_POINTERS
+
/* Define if sbrk()/brk() wrappers can track malloc()s core memory use */
#undef ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC
@@ -80,6 +83,12 @@
/* ESOCK counter size */
#undef ESOCK_COUNTER_SIZE
+/* Enable esock */
+#undef ESOCK_ENABLE
+
+/* Socket address dl length */
+#undef ESOCK_SDL_LEN
+
/* Interface hwaddr supported */
#undef ESOCK_USE_HWADDR
@@ -101,7 +110,7 @@
/* Define if bigendian */
#undef ETHR_BIGENDIAN
-/* Define if gcc wont let you clobber ebx with cmpxchg8b and position
+/* Define if gcc won't let you clobber ebx with cmpxchg8b and position
independent code */
#undef ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX
@@ -130,6 +139,11 @@
#undef ETHR_HAVE_ETHREAD_DEFINES
/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'dc cvau' instruction, and are compiling for
+ an ARM processor with ARM DC instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION
+
+/* Define as a boolean indicating whether you have a gcc compatible compiler
capable of generating the ARM 'dmb sy' instruction, and are compiling for
an ARM processor with ARM DMB instruction support, or not */
#undef ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION
@@ -144,6 +158,16 @@
an ARM processor with ARM DMB instruction support, or not */
#undef ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION
+/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'ic ivau' instruction, and are compiling for
+ an ARM processor with ARM IC instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION
+
+/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'isb sy' instruction, and are compiling for
+ an ARM processor with ARM ISB instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION
+
/* Define as a boolean indicating whether you have a gcc __atomic builtins or
not */
#undef ETHR_HAVE_GCC___ATOMIC_BUILTINS
@@ -394,9 +418,6 @@
/* Define if only run in Sparc TSO mode */
#undef ETHR_SPARC_TSO
-/* Define if you can safely include both <sys/time.h> and <time.h>. */
-#undef ETHR_TIME_WITH_SYS_TIME
-
/* Define as a boolean indicating whether you trust gcc's __atomic_* builtins
memory barrier implementations, or not */
#undef ETHR_TRUST_GCC_ATOMIC_BUILTINS_MEMORY_BARRIERS
@@ -595,6 +616,9 @@
/* Define to 1 if you have the `dlopen' function. */
#undef HAVE_DLOPEN
+/* Define to 1 if you have the `dlvsym' function. */
+#undef HAVE_DLVSYM
+
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
@@ -800,9 +824,6 @@
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
/* Define if the pthread.h header file is in pthread/mit directory. */
#undef HAVE_MIT_PTHREAD_H
@@ -905,6 +926,9 @@
/* Define to 1 if you have the `sctp_bindx' function. */
#undef HAVE_SCTP_BINDX
+/* Define to 1 if you have the `sctp_connectx' function. */
+#undef HAVE_SCTP_CONNECTX
+
/* Define to 1 if you have the `sctp_freeladdrs' function. */
#undef HAVE_SCTP_FREELADDRS
@@ -959,6 +983,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -1001,6 +1028,9 @@
/* Define to 1 if `ifr_map' is a member of `struct ifreq'. */
#undef HAVE_STRUCT_IFREQ_IFR_MAP
+/* Define to 1 if the system has the type `struct ip_mreqn'. */
+#undef HAVE_STRUCT_IP_MREQN
+
/* Define to 1 if `assoc_id' is a member of `struct sctp_accoc_value'. */
#undef HAVE_STRUCT_SCTP_ACCOC_VALUE_ASSOC_ID
@@ -1027,6 +1057,9 @@
/* Define to 1 if `ssf_data' is a member of `struct sctp_send_failed'. */
#undef HAVE_STRUCT_SCTP_SEND_FAILED_SSF_DATA
+/* Define to 1 if `sdl_len' is a member of `struct sockaddr_dl'. */
+#undef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN
+
/* Define to 1 if `sun_path' is a member of `struct sockaddr_un'. */
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_PATH
@@ -1238,9 +1271,6 @@
*/
#undef REDEFINE_FD_SETSIZE
-/* Define as the return type of signal handlers (`int' or `void'). */
-#undef RETSIGTYPE
-
/* Define the sbrk() argument type. */
#undef SBRK_ARG_TYPE
@@ -1292,7 +1322,9 @@
/* The size of `__int64', as computed by sizeof. */
#undef SIZEOF___INT64
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* define if the variable sys_errlist is declared in a system header file */
@@ -1308,9 +1340,6 @@
clock_get_time() */
#undef SYS_HRTIME_USING_MACH_CLOCK_GET_TIME
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#undef TIME_WITH_SYS_TIME
-
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
@@ -1350,7 +1379,7 @@
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
diff --git a/erts/configure b/erts/configure
index 7da8d32a1b..a84ffe4342 100755
--- a/erts/configure
+++ b/erts/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +430,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +459,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +503,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +517,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +534,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,52 +606,51 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
-
-ac_unique_file="vsn.mk"
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="emulator/beam/erl_process.c"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
+ac_func_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
+DEBUG_CFLAGS
+ERL_DETERMINISTIC
CFLAGS32
CC32
JAVAC
@@ -636,7 +666,6 @@ FLAVORS
PRIMARY_FLAVOR
JIT_ARCH
JIT_ENABLED
-ac_ct_CXX
M4
LIBRT
BITS64
@@ -644,7 +673,6 @@ HAVE_VALGRIND
LIBSCTP
SYSTEMD_DAEMON_LIBS
SOCKET_LIBS
-USE_ESOCK
Z_LIB
TERMCAP_LIB
THR_DEFS
@@ -654,7 +682,7 @@ EMU_THR_DEFS
EMU_THR_LIBS
EMU_THR_X_LIBS
EMU_THR_LIB_NAME
-TYPES
+DEFAULT_TYPES
DIRTY_SCHEDULER_TEST
ETHR_X86_SSE2_ASM
ETHR_THR_LIB_BASE_DIR
@@ -668,36 +696,36 @@ DEXPORT
ERLANG_OSTYPE
HCFLAGS
HCC
-INSTALL_DIR
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
-XMLLINT
-FOP
-XSLTPROC
-LN_S
-PERL
-YFLAGS
-YACC
CP
MKDIR
LIBCARBON
ARCH
OPSYS
EXTERNAL_WORD_SIZE
-EGREP
-GREP
PROFILE_COMPILER
USE_PGO
XCRUN
LLVM_PROFDATA
WERRORFLAGS
WFLAGS
-DEBUG_CFLAGS
DEBUG_FLAGS
ERTS_CONFIG_H_IDIR
MIXED_MINGW
MIXED_VC
+INSTALL_DIR
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+XMLLINT
+FOP
+XSLTPROC
+LN_S
+PERL
+YFLAGS
+YACC
+EGREP
+GREP
+ac_ct_CXX
GCC
STATIC_DRIVERS
STATIC_NIFS
@@ -710,6 +738,10 @@ OBJEXT
EXEEXT
ac_ct_CC
CROSS_COMPILING
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -837,6 +869,7 @@ enable_prefer_elapsed_monotonic_time_during_suspend
enable_gettimeofday_as_os_system_time
with_javac
enable_sanitizers
+enable_deterministic_build
'
ac_precious_vars='build_alias
host_alias
@@ -878,9 +911,9 @@ erl_xcomp_gethrvtime_procfs_ioctl
erl_xcomp_clock_gettime_cpu_time
erl_xcomp_after_morecore_hook
erl_xcomp_dlsym_brk_wrappers
+CCC
YACC
-YFLAGS
-CCC'
+YFLAGS'
# Initialize some variables set by options.
@@ -949,8 +982,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -991,9 +1022,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1017,9 +1048,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1230,9 +1261,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1246,9 +1277,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1292,9 +1323,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1310,7 +1341,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1374,7 +1405,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1492,6 +1523,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1531,11 +1563,10 @@ Optional Features:
list of nifs that should be linked statically. The
list should be a comma separated and contain the
absolute path to a .a archive for each nif that is
- to be statically linked. The name of the .a archive
- has to be the same as the name of the nif. Note that
- you have to link any external dependencies that the
- nifs have to the main binary, so for the crypto nif
- you want to pass LIBS=-lcrypto to configure.
+ to be statically linked. Note that you have to link
+ any external dependencies, that the nifs have, to
+ the main binary. So for the crypto nifs you want to
+ pass LIBS=-lcrypto to configure.
--enable-static-drivers comma separated list of linked-in drivers to link
statically with the main binary. The list should
contain the absolute path to a .a archive for each
@@ -1581,6 +1612,9 @@ Optional Features:
Force usage of gettimeofday() for OS system time
--enable-sanitizers[=comma-separated list of sanitizers]
Default=address,undefined
+ --enable-deterministic-build
+ enable build determinism, stripping absolute paths
+ from build output
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1737,9 +1771,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1767,7 +1801,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1775,7 +1810,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1785,9 +1820,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1804,14 +1839,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1819,14 +1854,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1842,14 +1878,14 @@ fi
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1857,17 +1893,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1882,10 +1919,87 @@ fi
} # ac_fn_c_try_link
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
@@ -1895,25 +2009,26 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
@@ -1938,7 +2053,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -1948,14 +2063,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1965,9 +2081,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -1975,14 +2092,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -1992,14 +2109,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -2009,9 +2127,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -2019,14 +2138,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -2034,7 +2153,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2044,12 +2163,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -2059,12 +2179,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -2092,9 +2212,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -2107,43 +2228,6 @@ rm -f conftest.val
} # ac_fn_c_compute_int
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
@@ -2151,26 +2235,28 @@ fi
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
@@ -2181,11 +2267,12 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -2193,16 +2280,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -2220,115 +2300,29 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
# ----------------------------------------------------
# Tries to find if the field MEMBER exists in type AGGR, after including
@@ -2336,16 +2330,17 @@ fi
ac_fn_c_check_member ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
-$as_echo_n "checking for $2.$3... " >&6; }
-if eval \${$4+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+printf %s "checking for $2.$3... " >&6; }
+if eval test \${$4+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
-main ()
+main (void)
{
static $2 ac_aggr;
if (ac_aggr.$3)
@@ -2354,14 +2349,15 @@ return 0;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$4=yes"
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
-main ()
+main (void)
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
@@ -2370,68 +2366,23 @@ return 0;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$4=yes"
-else
+else $as_nop
eval "$4=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$4
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_member
-# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
-# ---------------------------------------------
-# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
-# accordingly.
-ac_fn_c_check_decl ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- as_decl_name=`echo $2|sed 's/ *(.*//'`
- as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
-$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-#ifndef $as_decl_name
-#ifdef __cplusplus
- (void) $as_decl_use;
-#else
- (void) $as_decl_name;
-#endif
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_decl
-
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
@@ -2439,17 +2390,18 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof ($2))
return 0;
@@ -2457,12 +2409,13 @@ if (sizeof ($2))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof (($2)))
return 0;
@@ -2470,67 +2423,102 @@ if (sizeof (($2)))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
eval "$3=yes"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
-# ac_fn_cxx_try_compile LINENO
-# ----------------------------
-# Try to compile conftest.$ac_ext, and return whether this succeeded.
-ac_fn_cxx_try_compile ()
+# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
+# ------------------------------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
+ac_fn_check_decl ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
- if { { ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compile") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_cxx_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+printf %s "checking whether $as_decl_name is declared... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ eval ac_save_FLAGS=\$$6
+ as_fn_append $6 " $5"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
- ac_retval=1
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ eval $6=\$ac_save_FLAGS
+
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-} # ac_fn_cxx_try_compile
+} # ac_fn_check_decl
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2563,8 +2551,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2599,7 +2591,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2634,11 +2626,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2649,8 +2643,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2674,7 +2668,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2682,14 +2676,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2697,15 +2691,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2713,8 +2707,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2728,63 +2722,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2794,19 +2773,652 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+# Test code for whether the C++ compiler supports C++98 (global declarations)
+ac_cxx_conftest_cxx98_globals='
+// Does the compiler advertise C++98 conformance?
+#if !defined __cplusplus || __cplusplus < 199711L
+# error "Compiler does not advertise C++98 conformance"
+#endif
+
+// These inclusions are to reject old compilers that
+// lack the unsuffixed header files.
+#include <cstdlib>
+#include <exception>
+
+// <cassert> and <cstring> are *not* freestanding headers in C++98.
+extern void assert (int);
+namespace std {
+ extern int strcmp (const char *, const char *);
+}
+
+// Namespaces, exceptions, and templates were all added after "C++ 2.0".
+using std::exception;
+using std::strcmp;
+
+namespace {
+
+void test_exception_syntax()
+{
+ try {
+ throw "test";
+ } catch (const char *s) {
+ // Extra parentheses suppress a warning when building autoconf itself,
+ // due to lint rules shared with more typical C programs.
+ assert (!(strcmp) (s, "test"));
+ }
+}
+
+template <typename T> struct test_template
+{
+ T const val;
+ explicit test_template(T t) : val(t) {}
+ template <typename U> T add(U u) { return static_cast<T>(u) + val; }
+};
+
+} // anonymous namespace
+'
+
+# Test code for whether the C++ compiler supports C++98 (body of main)
+ac_cxx_conftest_cxx98_main='
+ assert (argc);
+ assert (! argv[0]);
+{
+ test_exception_syntax ();
+ test_template<double> tt (2.0);
+ assert (tt.add (4) == 6.0);
+ assert (true && !false);
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (global declarations)
+ac_cxx_conftest_cxx11_globals='
+// Does the compiler advertise C++ 2011 conformance?
+#if !defined __cplusplus || __cplusplus < 201103L
+# error "Compiler does not advertise C++11 conformance"
+#endif
+
+namespace cxx11test
+{
+ constexpr int get_val() { return 20; }
+
+ struct testinit
+ {
+ int i;
+ double d;
+ };
+
+ class delegate
+ {
+ public:
+ delegate(int n) : n(n) {}
+ delegate(): delegate(2354) {}
+
+ virtual int getval() { return this->n; };
+ protected:
+ int n;
+ };
+
+ class overridden : public delegate
+ {
+ public:
+ overridden(int n): delegate(n) {}
+ virtual int getval() override final { return this->n * 2; }
+ };
+
+ class nocopy
+ {
+ public:
+ nocopy(int i): i(i) {}
+ nocopy() = default;
+ nocopy(const nocopy&) = delete;
+ nocopy & operator=(const nocopy&) = delete;
+ private:
+ int i;
+ };
+
+ // for testing lambda expressions
+ template <typename Ret, typename Fn> Ret eval(Fn f, Ret v)
+ {
+ return f(v);
+ }
+
+ // for testing variadic templates and trailing return types
+ template <typename V> auto sum(V first) -> V
+ {
+ return first;
+ }
+ template <typename V, typename... Args> auto sum(V first, Args... rest) -> V
+ {
+ return first + sum(rest...);
+ }
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (body of main)
+ac_cxx_conftest_cxx11_main='
+{
+ // Test auto and decltype
+ auto a1 = 6538;
+ auto a2 = 48573953.4;
+ auto a3 = "String literal";
+
+ int total = 0;
+ for (auto i = a3; *i; ++i) { total += *i; }
+
+ decltype(a2) a4 = 34895.034;
+}
+{
+ // Test constexpr
+ short sa[cxx11test::get_val()] = { 0 };
+}
+{
+ // Test initializer lists
+ cxx11test::testinit il = { 4323, 435234.23544 };
+}
+{
+ // Test range-based for
+ int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
+ 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
+ for (auto &x : array) { x += 23; }
+}
+{
+ // Test lambda expressions
+ using cxx11test::eval;
+ assert (eval ([](int x) { return x*2; }, 21) == 42);
+ double d = 2.0;
+ assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
+ assert (d == 5.0);
+ assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
+ assert (d == 5.0);
+}
+{
+ // Test use of variadic templates
+ using cxx11test::sum;
+ auto a = sum(1);
+ auto b = sum(1, 2);
+ auto c = sum(1.0, 2.0, 3.0);
+}
+{
+ // Test constructor delegation
+ cxx11test::delegate d1;
+ cxx11test::delegate d2();
+ cxx11test::delegate d3(45);
+}
+{
+ // Test override and final
+ cxx11test::overridden o1(55464);
+}
+{
+ // Test nullptr
+ char *c = nullptr;
+}
+{
+ // Test template brackets
+ test_template<::test_template<int>> v(test_template<int>(12));
+}
+{
+ // Unicode literals
+ char const *utf8 = u8"UTF-8 string \u2500";
+ char16_t const *utf16 = u"UTF-8 string \u2500";
+ char32_t const *utf32 = U"UTF-32 string \u2500";
+}
+'
+
+# Test code for whether the C compiler supports C++11 (complete).
+ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
+${ac_cxx_conftest_cxx11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ ${ac_cxx_conftest_cxx11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C++98 (complete).
+ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+as_fn_append ac_header_c_list " sys/time.h sys_time_h HAVE_SYS_TIME_H"
+as_fn_append ac_func_c_list " vprintf HAVE_VPRINTF"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="install-sh config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2817,12 +3429,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2831,24 +3443,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2858,11 +3470,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2922,8 +3535,100 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-no_werror_CFLAGS=$(echo "$CFLAGS" | sed 's/-Werror\([^=]\|$\)/ /g')
-if test "$CFLAGS" != "$no_werror_CFLAGS"; then
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+no_werror_CFLAGS=$(echo " $CFLAGS " | sed 's/ -Werror / /g')
+if test "X $CFLAGS " != "X$no_werror_CFLAGS"; then
CFLAGS="$no_werror_CFLAGS"
WERRORFLAGS=-Werror
fi
@@ -2965,61 +3670,33 @@ erl_top=${ERL_TOP}
# echo X
# echo XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-ac_aux_dir=
-for ac_dir in $srcdir/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in $srcdir/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-#
-# To configure for free source run ./configure --host=free_source
-#
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -3038,21 +3715,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -3071,10 +3749,108 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=$host
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
fi
+
if test "$cross_compiling" = "yes"; then
CROSS_COMPILING=yes
else
@@ -3093,6 +3869,15 @@ else
fi
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3101,11 +3886,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -3113,11 +3899,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3128,11 +3918,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3141,11 +3931,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -3153,11 +3944,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3168,11 +3963,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -3180,8 +3975,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -3194,11 +3989,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -3206,11 +4002,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3221,11 +4021,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3234,11 +4034,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -3247,15 +4048,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3271,18 +4076,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3293,11 +4098,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -3305,11 +4111,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3320,11 +4130,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3337,11 +4147,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -3349,11 +4160,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3364,11 +4179,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3380,34 +4195,138 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -3417,7 +4336,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -3425,7 +4344,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3437,9 +4356,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -3460,11 +4379,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -3481,7 +4401,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -3497,44 +4417,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -3548,15 +4470,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -3565,7 +4487,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3577,8 +4499,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -3586,10 +4508,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -3597,39 +4519,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3643,11 +4566,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -3656,31 +4580,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3690,29 +4615,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3721,57 +4650,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3786,94 +4718,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3883,11 +4865,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5
-$as_echo_n "checking for library containing strerror... " >&6; }
-if ${ac_cv_search_strerror+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5
+printf %s "checking for library containing strerror... " >&6; }
+if test ${ac_cv_search_strerror+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -3895,46 +4878,48 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char strerror ();
int
-main ()
+main (void)
{
return strerror ();
;
return 0;
}
_ACEOF
-for ac_lib in '' cposix; do
+for ac_lib in '' cposix
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_strerror=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_strerror+:} false; then :
+ if test ${ac_cv_search_strerror+y}
+then :
break
fi
done
-if ${ac_cv_search_strerror+:} false; then :
+if test ${ac_cv_search_strerror+y}
+then :
-else
+else $as_nop
ac_cv_search_strerror=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5
-$as_echo "$ac_cv_search_strerror" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5
+printf "%s\n" "$ac_cv_search_strerror" >&6; }
ac_res=$ac_cv_search_strerror
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
@@ -3946,7 +4931,8 @@ ENABLE_ALLOC_TYPE_VARS=
# Check whether --enable-bootstrap-only was given.
-if test "${enable_bootstrap_only+set}" = set; then :
+if test ${enable_bootstrap_only+y}
+then :
enableval=$enable_bootstrap_only; if test "X$enableval" = "Xyes"; then
# Disable stuff not necessary in a bootstrap only system in order
# to speed up things by reducing the amount of stuff needing to be
@@ -3962,73 +4948,80 @@ fi
# Check whether --enable-dirty-schedulers-test was given.
-if test "${enable_dirty_schedulers_test+set}" = set; then :
+if test ${enable_dirty_schedulers_test+y}
+then :
enableval=$enable_dirty_schedulers_test; case "$enableval" in
yes) enable_dirty_schedulers_test=yes ;;
*) enable_dirty_schedulers_test=no ;;
esac
-else
+else $as_nop
enable_dirty_schedulers_test=no
fi
# Check whether --enable-smp-require-native-atomics was given.
-if test "${enable_smp_require_native_atomics+set}" = set; then :
+if test ${enable_smp_require_native_atomics+y}
+then :
enableval=$enable_smp_require_native_atomics; case "$enableval" in
no) smp_require_native_atomics=no ;;
*) smp_require_native_atomics=yes ;;
esac
-else
+else $as_nop
smp_require_native_atomics=yes
fi
# Check whether --with-termcap was given.
-if test "${with_termcap+set}" = set; then :
+if test ${with_termcap+y}
+then :
withval=$with_termcap;
-else
+else $as_nop
with_termcap=yes
fi
# Check whether --enable-lock-checking was given.
-if test "${enable_lock_checking+set}" = set; then :
+if test ${enable_lock_checking+y}
+then :
enableval=$enable_lock_checking; case "$enableval" in
no) enable_lock_check=no ;;
*) enable_lock_check=yes ;;
esac
-else
+else $as_nop
enable_lock_check=no
fi
# Check whether --enable-lock-counter was given.
-if test "${enable_lock_counter+set}" = set; then :
+if test ${enable_lock_counter+y}
+then :
enableval=$enable_lock_counter; case "$enableval" in
no) enable_lock_count=no ;;
*) enable_lock_count=yes ;;
esac
-else
+else $as_nop
enable_lock_count=no
fi
# Check whether --enable-kernel-poll was given.
-if test "${enable_kernel_poll+set}" = set; then :
+if test ${enable_kernel_poll+y}
+then :
enableval=$enable_kernel_poll; case "$enableval" in
no) enable_kernel_poll=no ;;
*) enable_kernel_poll=yes ;;
esac
-else
+else $as_nop
enable_kernel_poll=unknown
fi
# Check whether --enable-sctp was given.
-if test "${enable_sctp+set}" = set; then :
+if test ${enable_sctp+y}
+then :
enableval=$enable_sctp; case "x$enableval" in
xno|xyes|xlib|x)
;;
@@ -4040,44 +5033,48 @@ fi
# Check whether --enable-jit was given.
-if test "${enable_jit+set}" = set; then :
+if test ${enable_jit+y}
+then :
enableval=$enable_jit; case "$enableval" in
no) enable_jit=no ;;
*) enable_jit=yes ;;
esac
-else
+else $as_nop
enable_jit=auto
fi
# Check whether --enable-m64-build was given.
-if test "${enable_m64_build+set}" = set; then :
+if test ${enable_m64_build+y}
+then :
enableval=$enable_m64_build; case "$enableval" in
no) enable_m64_build=no ;;
*) enable_m64_build=yes ;;
esac
-else
+else $as_nop
enable_m64_build=no
fi
# Check whether --enable-m32-build was given.
-if test "${enable_m32_build+set}" = set; then :
+if test ${enable_m32_build+y}
+then :
enableval=$enable_m32_build; case "$enableval" in
no) enable_m32_build=no ;;
*) enable_m32_build=yes ;;
esac
-else
+else $as_nop
enable_m32_build=no
fi
# Check whether --with-dynamic-trace was given.
-if test "${with_dynamic_trace+set}" = set; then :
+if test ${with_dynamic_trace+y}
+then :
withval=$with_dynamic_trace;
fi
@@ -4090,17 +5087,17 @@ case "$with_dynamic_trace" in
no) DYNAMIC_TRACE_FRAMEWORK=;;
lttng)
-$as_echo "#define USE_LTTNG 1" >>confdefs.h
+printf "%s\n" "#define USE_LTTNG 1" >>confdefs.h
DYNAMIC_TRACE_FRAMEWORK=lttng;;
dtrace)
-$as_echo "#define USE_DTRACE 1" >>confdefs.h
+printf "%s\n" "#define USE_DTRACE 1" >>confdefs.h
DYNAMIC_TRACE_FRAMEWORK=dtrace;;
systemtap)
-$as_echo "#define USE_SYSTEMTAP 1" >>confdefs.h
+printf "%s\n" "#define USE_SYSTEMTAP 1" >>confdefs.h
DYNAMIC_TRACE_FRAMEWORK=systemtap;;
*)
@@ -4109,12 +5106,13 @@ esac
if test X"$DYNAMIC_TRACE_FRAMEWORK" != X""; then
-$as_echo "#define USE_DYNAMIC_TRACE 1" >>confdefs.h
+printf "%s\n" "#define USE_DYNAMIC_TRACE 1" >>confdefs.h
fi
# Check whether --enable-vm-probes was given.
-if test "${enable_vm_probes+set}" = set; then :
+if test ${enable_vm_probes+y}
+then :
enableval=$enable_vm_probes; case "$enableval" in
no) use_vm_probes=no ;;
*)
@@ -4124,7 +5122,7 @@ if test "${enable_vm_probes+set}" = set; then :
as_fn_error $? "Can not enable VM probes without any dynamic tracing framework!" "$LINENO" 5;
fi;;
esac
-else
+else $as_nop
if test X"$DYNAMIC_TRACE_FRAMEWORK" != X""; then
use_vm_probes=yes ;
else
@@ -4138,14 +5136,15 @@ if test X"$DYNAMIC_TRACE_FRAMEWORK" != X"lttng"; then
if test X"$use_vm_probes" = X"yes"; then
USE_VM_PROBES=yes
-$as_echo "#define USE_VM_PROBES 1" >>confdefs.h
+printf "%s\n" "#define USE_VM_PROBES 1" >>confdefs.h
fi
fi
# Check whether --with-assumed-cache-line-size was given.
-if test "${with_assumed_cache_line_size+set}" = set; then :
+if test ${with_assumed_cache_line_size+y}
+then :
withval=$with_assumed_cache_line_size;
fi
@@ -4161,34 +5160,34 @@ case "$with_assumed_cache_line_size" in
esac
-cat >>confdefs.h <<_ACEOF
-#define ASSUMED_CACHE_LINE_SIZE $with_assumed_cache_line_size
-_ACEOF
+printf "%s\n" "#define ASSUMED_CACHE_LINE_SIZE $with_assumed_cache_line_size" >>confdefs.h
# Check whether --enable-systemd was given.
-if test "${enable_systemd+set}" = set; then :
+if test ${enable_systemd+y}
+then :
enableval=$enable_systemd;
-else
+else $as_nop
enable_systemd=no
fi
# Check whether --with-microstate-accounting was given.
-if test "${with_microstate_accounting+set}" = set; then :
+if test ${with_microstate_accounting+y}
+then :
withval=$with_microstate_accounting;
-else
+else $as_nop
with_microstate_accounting=yes
fi
case "$with_microstate_accounting" in
yes)
-$as_echo "#define ERTS_ENABLE_MSACC 1" >>confdefs.h
+printf "%s\n" "#define ERTS_ENABLE_MSACC 1" >>confdefs.h
;;
extra)
-$as_echo "#define ERTS_ENABLE_MSACC 2" >>confdefs.h
+printf "%s\n" "#define ERTS_ENABLE_MSACC 2" >>confdefs.h
;;
*) ;;
esac
@@ -4202,18 +5201,18 @@ else
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OTP release" >&5
-$as_echo_n "checking OTP release... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OTP release" >&5
+printf %s "checking OTP release... " >&6; }
SYSTEM_VSN=`cat $ERL_TOP/OTP_VERSION | sed "s|\([0-9]*\).*|\1|"`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYSTEM_VSN" >&5
-$as_echo "$SYSTEM_VSN" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SYSTEM_VSN" >&5
+printf "%s\n" "$SYSTEM_VSN" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OTP version" >&5
-$as_echo_n "checking OTP version... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OTP version" >&5
+printf %s "checking OTP version... " >&6; }
OTP_VERSION=`cat $ERL_TOP/OTP_VERSION`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTP_VERSION" >&5
-$as_echo "$OTP_VERSION" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTP_VERSION" >&5
+printf "%s\n" "$OTP_VERSION" >&6; }
if test X${enable_m64_build} = Xyes; then
@@ -4238,18 +5237,20 @@ else
fi
# Check whether --enable-static-nifs was given.
-if test "${enable_static_nifs+set}" = set; then :
+if test ${enable_static_nifs+y}
+then :
enableval=$enable_static_nifs; STATIC_NIFS="$enableval"
-else
+else $as_nop
STATIC_NIFS=no
fi
# Check whether --enable-static-drivers was given.
-if test "${enable_static_drivers+set}" = set; then :
+if test ${enable_static_drivers+y}
+then :
enableval=$enable_static_drivers; STATIC_DRIVERS="$enableval"
-else
+else $as_nop
STATIC_DRIVERS=no
fi
@@ -4257,24 +5258,24 @@ fi
# Check whether --with-ets-write-concurrency-locks was given.
-if test "${with_ets_write_concurrency_locks+set}" = set; then :
+if test ${with_ets_write_concurrency_locks+y}
+then :
withval=$with_ets_write_concurrency_locks;
fi
if test X"$with_ets_write_concurrency_locks" != X""; then
-cat >>confdefs.h <<_ACEOF
-#define ERTS_DB_HASH_LOCK_CNT $with_ets_write_concurrency_locks
-_ACEOF
+printf "%s\n" "#define ERTS_DB_HASH_LOCK_CNT $with_ets_write_concurrency_locks" >>confdefs.h
fi
# Check whether --with-spectre-mitigation was given.
-if test "${with_spectre_mitigation+set}" = set; then :
+if test ${with_spectre_mitigation+y}
+then :
withval=$with_spectre_mitigation;
-else
+else $as_nop
with_spectre_mitigation=no
fi
@@ -4288,31 +5289,36 @@ esac
i_noretpoline_attr=""
-if test X"$with_spectre_mitigation" != X"no"; then
+if test X"$with_spectre_mitigation" != X"no"
+then :
+
CFLAGS="$CFLAGS -mindirect-branch=thunk"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for spectre mitigation" >&5
-$as_echo_n "checking for spectre mitigation... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for spectre mitigation" >&5
+printf %s "checking for spectre mitigation... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
as_fn_error $? "no" "$LINENO" 5
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ if test X"$with_spectre_mitigation" = X"incomplete"
+then :
- if test X"$with_spectre_mitigation" = X"incomplete"; then
# gcc and clang support this attribute if they're recent enough. Note
# that we must compile with -Werror to check for actual support as they
# warn rather than error out on unsupported attributes.
@@ -4321,36 +5327,44 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
i_preserve_cflags="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether spectre mitigation can be disabled on a per-function basis" >&5
-$as_echo_n "checking whether spectre mitigation can be disabled on a per-function basis... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether spectre mitigation can be disabled on a per-function basis" >&5
+printf %s "checking whether spectre mitigation can be disabled on a per-function basis... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$i_noretpoline_attr
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
as_fn_error $? "no" "$LINENO" 5
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS="$i_preserve_cflags"
- fi
+
fi
+fi
-cat >>confdefs.h <<_ACEOF
-#define ERTS_NO_RETPOLINE $i_noretpoline_attr
-_ACEOF
+printf "%s\n" "#define ERTS_NO_RETPOLINE $i_noretpoline_attr" >>confdefs.h
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
@@ -4361,11 +5375,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -4373,11 +5388,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4388,11 +5407,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4401,11 +5420,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -4413,11 +5433,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4428,11 +5452,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -4440,8 +5464,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -4454,11 +5478,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -4466,11 +5491,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4481,11 +5510,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4494,11 +5523,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -4507,15 +5537,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4531,18 +5565,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4553,11 +5587,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -4565,11 +5600,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4580,11 +5619,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4597,11 +5636,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -4609,11 +5649,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4624,11 +5668,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4640,34 +5684,138 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -4677,20 +5825,21 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -4700,29 +5849,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -4731,57 +5884,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -4796,103 +5952,1457 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+printf "%s\n" "$CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+printf "%s\n" "$ac_ct_CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
+printf %s "checking whether the compiler supports GNU C++... " >&6; }
+if test ${ac_cv_cxx_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
{
- return p[i];
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
}
-static char *f (char * (*g) (char **, int), char **p, ...)
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else $as_nop
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+y}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+printf %s "checking whether $CXX accepts -g... " >&6; }
+if test ${ac_cv_prog_cxx_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
+
+ ;
+ return 0;
}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_g=yes
+else $as_nop
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+int
+main (void)
+{
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+
+else $as_nop
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
int
-main ()
+main (void)
{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+
;
return 0;
}
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
+if test $ac_test_CXXFLAGS; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_prog_cxx_stdcxx=no
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
+printf %s "checking for $CXX option to enable C++11 features... " >&6; }
+if test ${ac_cv_prog_cxx_11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_11=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx11_program
+_ACEOF
+for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
do
- CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_c89=$ac_arg
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx11=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c89" != "xno" && break
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
done
rm -f conftest.$ac_ext
-CC=$ac_save_CC
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx11"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
+ ac_prog_cxx_stdcxx=cxx11
+fi
+fi
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
+printf %s "checking for $CXX option to enable C++98 features... " >&6; }
+if test ${ac_cv_prog_cxx_98+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_98=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx98_program
+_ACEOF
+for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx98=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+if test "x$ac_cv_prog_cxx_cxx98" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx98" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx98"
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
+ ac_prog_cxx_stdcxx=cxx98
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_YACC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_YACC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+printf "%s\n" "$YACC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+for ac_prog in perl5 perl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PERL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $PERL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="/usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH}"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PERL="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PERL=$ac_cv_path_PERL
+if test -n "$PERL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
+printf "%s\n" "$PERL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$PERL" && break
+done
+test -n "$PERL" || PERL="false"
+
+if test "$PERL" = "false"; then
+ ac_cv_path_PERL=false
+ PERL=false
+fi
+
+if test "$ac_cv_path_PERL" = false; then
+ as_fn_error $? "Perl version 5 is required to build the emulator!" "$LINENO" 5
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+printf %s "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+printf "%s\n" "no, using $LN_S" >&6; }
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test "$ac_cv_prog_AR" = false; then
+ as_fn_error $? "No 'ar' command found in PATH" "$LINENO" 5
+fi
+
+
+#
+# Get programs needed for building the documentation
+#
+
+## Delete previous failed configure results
+if test -f doc/CONF_INFO; then
+ rm -f doc/CONF_INFO
+fi
+
+for ac_prog in xsltproc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_XSLTPROC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$XSLTPROC"; then
+ ac_cv_prog_XSLTPROC="$XSLTPROC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_XSLTPROC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+XSLTPROC=$ac_cv_prog_XSLTPROC
+if test -n "$XSLTPROC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5
+printf "%s\n" "$XSLTPROC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$XSLTPROC" && break
+done
+
+if test -z "$XSLTPROC"; then
+ echo "xsltproc" >> doc/CONF_INFO
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No 'xsltproc' command found: the documentation cannot be built" >&5
+printf "%s\n" "$as_me: WARNING: No 'xsltproc' command found: the documentation cannot be built" >&2;}
+fi
+
+for ac_prog in fop
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_FOP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$FOP"; then
+ ac_cv_prog_FOP="$FOP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FOP="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+FOP=$ac_cv_prog_FOP
+if test -n "$FOP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FOP" >&5
+printf "%s\n" "$FOP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$FOP" && break
+done
+
+if test -z "$FOP"; then
+ FOP="$ERL_TOP/make/fakefop"
+ echo "fop" >> doc/CONF_INFO
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No 'fop' command found: going to generate placeholder PDF files" >&5
+printf "%s\n" "$as_me: WARNING: No 'fop' command found: going to generate placeholder PDF files" >&2;}
+fi
+
+for ac_prog in xmllint
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_XMLLINT+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$XMLLINT"; then
+ ac_cv_prog_XMLLINT="$XMLLINT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_XMLLINT="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+XMLLINT=$ac_cv_prog_XMLLINT
+if test -n "$XMLLINT"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XMLLINT" >&5
+printf "%s\n" "$XMLLINT" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$XMLLINT" && break
+done
+
+if test -z "$XMLLINT"; then
+ echo "xmllint" >> doc/CONF_INFO
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No 'xmllint' command found: can't run the xmllint target for the documentation" >&5
+printf "%s\n" "$as_me: WARNING: No 'xmllint' command found: can't run the xmllint target for the documentation" >&2;}
+fi
+
+case $host in
+ *-*-solaris*|free_source)
+ if test -x /usr/ucb/install; then
+ INSTALL="/usr/ucb/install -c"
+ fi
+ ;;
+ *)
+ ;;
+esac
+
+ # Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test ${ac_cv_path_install+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+ ./ | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test ${ac_cv_path_install+y}; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to create a directory including parents" >&5
+printf %s "checking how to create a directory including parents... " >&6; }
+if test ${ac_cv_prog_mkdir_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+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
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_mkdir_p" >&5
+printf "%s\n" "$ac_cv_prog_mkdir_p" >&6; }
+
+case "${ac_cv_prog_mkdir_p}" in
+ none) as_fn_error $? "don't know how create directories with parents" "$LINENO" 5 ;;
+ *) INSTALL_DIR="$ac_cv_prog_mkdir_p" ;;
+esac
+
+
+case $host_os in
+ darwin*)
+ INSTALL_DATA="$INSTALL_DATA -p";;
+ *)
+ ;;
+esac
+case $build in
+ *tile*)
+ INSTALL_PROGRAM="$INSTALL_PROGRAM -m755"
+ INSTALL_SCRIPT="$INSTALL_SCRIPT -m755"
+ ;;
+ *)
+ ;;
+esac
case $host_os in
@@ -4924,111 +7434,111 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -5040,49 +7550,30 @@ ERTS_CONFIG_H_IDIR="-I${ERL_TOP}/erts/$host"
extra_flags="$ERTS_CONFIG_H_IDIR $OTP_EXTRA_FLAGS"
CFLAGS="$CFLAGS $extra_flags"
-DEBUG_CFLAGS="-g $CPPFLAGS $extra_flags $DEBUG_CFLAGS"
DEBUG_FLAGS=-g
-case $CFLAGS in
- *-m64*)
- case $DEBUG_CFLAGS in
- *-m64*)
- ;;
- *)
- DEBUG_CFLAGS="-m64 $DEBUG_CFLAGS"
- ;;
- esac
- ;;
- *-m32*)
- case $DEBUG_CFLAGS in
- *-m32*)
- ;;
- *)
- DEBUG_CFLAGS="-m32 $DEBUG_CFLAGS"
- ;;
- esac
- ;;
- *)
- ;;
-esac
-
lfs_conf=ok
lfs_source=none
-if test "${LFS_CFLAGS+set}" = "set" || \
- test "${LFS_LDFLAGS+set}" = "set" || \
- test "${LFS_LIBS+set}" = "set"; then
+if test "${LFS_CFLAGS+set}" = "set" || test "${LFS_LDFLAGS+set}" = "set" || test "${LFS_LIBS+set}" = "set"
+then :
+
lfs_source=user
-else
-if test "$cross_compiling" != "yes"; then
+else $as_nop
+
+
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -5090,11 +7581,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5106,23 +7601,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -5130,11 +7628,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5146,25 +7648,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -5175,11 +7680,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5191,11 +7700,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5204,11 +7713,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -5219,11 +7729,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5235,11 +7749,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -5247,8 +7761,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -5257,143 +7771,165 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
+fi
+
fi
test "$GETCONF" = "false" || lfs_source=getconf
+
fi
if test "$lfs_source" = "none"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to check for large file support flags; no getconf is available" >&5
-$as_echo "$as_me: WARNING: Do not know how to check for large file support flags; no getconf is available" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to check for large file support flags; no getconf is available" >&5
+printf "%s\n" "$as_me: WARNING: Do not know how to check for large file support flags; no getconf is available" >&2;}
else
for var in CFLAGS LDFLAGS LIBS; do
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for large file support $var" >&5
-$as_echo_n "checking for large file support $var... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for large file support $var" >&5
+printf %s "checking for large file support $var... " >&6; }
if test $lfs_source = user; then
eval "lfs_val=\"\$LFS_$var\""
else
eval "lfs_var=LFS_$var"
lfs_val=`$GETCONF $lfs_var 2>/dev/null` || lfs_conf=failed
if test $lfs_conf = failed; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
-$as_echo "failed" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+printf "%s\n" "failed" >&6; }
break
fi
eval "$lfs_var=\"$lfs_val\""
fi
test "$lfs_val" != "" || lfs_val=none
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lfs_val" >&5
-$as_echo "$lfs_val" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lfs_val" >&5
+printf "%s\n" "$lfs_val" >&6; }
done
if test $lfs_conf = failed; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check for large file support flags failed; $GETCONF failed" >&5
-$as_echo "$as_me: WARNING: Check for large file support flags failed; $GETCONF failed" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Check for large file support flags failed; $GETCONF failed" >&5
+printf "%s\n" "$as_me: WARNING: Check for large file support flags failed; $GETCONF failed" >&2;}
else
CFLAGS="$CFLAGS $LFS_CFLAGS"
- DEBUG_CFLAGS="$DEBUG_CFLAGS $LFS_CFLAGS"
LDFLAGS="$LDFLAGS $LFS_LDFLAGS"
LIBS="$LIBS $LFS_LIBS"
fi
fi
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Treat certain GCC warnings as errors
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
WERRORFLAGS="-Werror=return-type $WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=implicit to WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=implicit to WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=implicit $WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
WERRORFLAGS="-Werror=implicit $WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=undef to WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=undef to WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=undef $WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
WERRORFLAGS="-Werror=undef $WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
# until the emulator can handle this, I suggest we turn it off!
@@ -5415,19 +7951,20 @@ $as_echo "no" >&6; }
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
warn_decl_after_st=true
-else
+else $as_nop
warn_decl_after_st=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test "X$warn_decl_after_st" = "Xtrue"; then
WFLAGS="$WFLAGS -Wdeclaration-after-statement"
fi
@@ -5438,50 +7975,98 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-common to CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-common to CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-common $CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="-fno-common $CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
-else
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-strict-aliasing to CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-strict-aliasing to CFLAGS (via CFLAGS)... " >&6; }
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="-fno-strict-aliasing $CFLAGS";
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ can_enable_flag=true
+else $as_nop
+ can_enable_flag=false
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$saved_CFLAGS;
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ CFLAGS="-fno-strict-aliasing $CFLAGS"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+else $as_nop
+
WFLAGS=""
WERRORFLAGS=${WERRORFLAGS:-""}
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking C99 support" >&5
-$as_echo_n "checking C99 support... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking C99 support" >&5
+printf %s "checking C99 support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if __STDC_VERSION__ < 199901L
@@ -5491,29 +8076,16 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="-std=gnu99 $CFLAGS"
- DEBUG_CFLAGS="-std=gnu99 $DEBUG_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking CFLAGS for -O switch" >&5
-$as_echo_n "checking CFLAGS for -O switch... " >&6; }
-case "$CFLAGS" in
- *-O*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; } ;;
- *)
- as_fn_error $? "
- CFLAGS must contain a -O flag. If you need to edit the CFLAGS you probably
- also want to add the default CFLAGS. The default CFLAGS are \"-O2 -g\".
- If you want to build erts without any optimization, pass -O0 to CFLAGS." "$LINENO" 5 ;;
-esac
-
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
@@ -5521,20 +8093,22 @@ esac
## Check if we can do profile guided optimization of beam_emu
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-generate -Werror..." >&5
-$as_echo_n "checking whether $CC accepts -fprofile-generate -Werror...... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-generate -Werror..." >&5
+printf %s "checking whether $CC accepts -fprofile-generate -Werror...... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fprofile-generate -Werror $CFLAGS";
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
can_enable_flag=false
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
return 0;
-else
+else $as_nop
can_enable_flag=true
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -5542,31 +8116,38 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
PROFILE_GENERATE=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else $as_nop
+
PROFILE_GENERATE=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-use -Werror..." >&5
-$as_echo_n "checking whether $CC accepts -fprofile-use -Werror...... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-use -Werror..." >&5
+printf %s "checking whether $CC accepts -fprofile-use -Werror...... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fprofile-use -Werror $CFLAGS";
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
can_enable_flag=false
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
return 0;
-else
+else $as_nop
can_enable_flag=true
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -5574,31 +8155,38 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
PROFILE_USE=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else $as_nop
+
PROFILE_USE=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-use -fprofile-correction -Werror..." >&5
-$as_echo_n "checking whether $CC accepts -fprofile-use -fprofile-correction -Werror...... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-use -fprofile-correction -Werror..." >&5
+printf %s "checking whether $CC accepts -fprofile-use -fprofile-correction -Werror...... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fprofile-use -fprofile-correction -Werror $CFLAGS";
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
can_enable_flag=false
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
return 0;
-else
+else $as_nop
can_enable_flag=true
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -5606,112 +8194,132 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
PROFILE_CORRECTION=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else $as_nop
+
PROFILE_CORRECTION=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+if test "X$PROFILE_CORRECTION" = "Xtrue"
+then :
-if test "X$PROFILE_CORRECTION" = "Xtrue"; then
saved_CFLAGS=$CFLAGS
saved_LDFLAGS=$LDFLAGS
CFLAGS="-fprofile-generate $saved_CFLAGS"
LDFLAGS="-fprofile-generate $saved_LDFLAGS"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC links with -fprofile-generate" >&5
-$as_echo_n "checking whether $CC links with -fprofile-generate... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC links with -fprofile-generate" >&5
+printf %s "checking whether $CC links with -fprofile-generate... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+if ac_fn_c_try_link "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
PROFILE_GENERATE=true
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
PROFILE_GENERATE=false
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_CFLAGS
LDFLAGS=$saved_LDFLAGS
+
fi
## Check if this is clang
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-instr-generate -Werror..." >&5
-$as_echo_n "checking whether $CC accepts -fprofile-instr-generate -Werror...... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-instr-generate -Werror..." >&5
+printf %s "checking whether $CC accepts -fprofile-instr-generate -Werror...... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fprofile-instr-generate -Werror $CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
PROFILE_INSTR_GENERATE=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else $as_nop
+
PROFILE_INSTR_GENERATE=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+if test "X$PROFILE_INSTR_GENERATE" = "Xtrue"
+then :
-if test "X$PROFILE_INSTR_GENERATE" = "Xtrue"; then
# It was clang, now we also have to check if we have llvm-profdata and that
# we can link programs with -fprofile-instr-use
saved_CFLAGS=$CFLAGS;
CFLAGS="-fprofile-instr-generate -Werror $saved_CFLAGS"
- if test "$cross_compiling" = yes; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: Disabling PGO when cross-compiling" >&5
-$as_echo "$as_me: Disabling PGO when cross-compiling" >&6;}
-else
+ if test "$cross_compiling" = yes
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Disabling PGO when cross-compiling" >&5
+printf "%s\n" "$as_me: Disabling PGO when cross-compiling" >&6;}
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
# Extract the first word of "llvm-profdata", so it can be a program name with args.
set dummy llvm-profdata; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_LLVM_PROFDATA+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_LLVM_PROFDATA+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $LLVM_PROFDATA in
[\\/]* | ?:[\\/]*)
ac_cv_path_LLVM_PROFDATA="$LLVM_PROFDATA" # Let the user override the test with a path.
@@ -5722,11 +8330,15 @@ as_dummy="$PATH:/Library/Developer/CommandLineTools/usr/bin"
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_LLVM_PROFDATA="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_LLVM_PROFDATA="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5738,11 +8350,11 @@ esac
fi
LLVM_PROFDATA=$ac_cv_path_LLVM_PROFDATA
if test -n "$LLVM_PROFDATA"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LLVM_PROFDATA" >&5
-$as_echo "$LLVM_PROFDATA" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LLVM_PROFDATA" >&5
+printf "%s\n" "$LLVM_PROFDATA" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5750,11 +8362,12 @@ fi
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_XCRUN+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_XCRUN+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$XCRUN"; then
ac_cv_prog_XCRUN="$XCRUN" # Let the user override the test.
else
@@ -5762,11 +8375,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_XCRUN="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5777,58 +8394,70 @@ fi
fi
XCRUN=$ac_cv_prog_XCRUN
if test -n "$XCRUN"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XCRUN" >&5
-$as_echo "$XCRUN" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XCRUN" >&5
+printf "%s\n" "$XCRUN" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
test -n "$XCRUN" && break
done
- if test "X$XCRUN" != "X" -a "X$LLVM_PROFDATA" = "X"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $XCRUN $LLVM_PROFDATA" >&5
-$as_echo_n "checking for $XCRUN $LLVM_PROFDATA... " >&6; }
- if $XCRUN $LLVM_PROFDATA --help 2>& 5 >& 5; then
+ if test "X$XCRUN" != "X" -a "X$LLVM_PROFDATA" = "X"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $XCRUN $LLVM_PROFDATA" >&5
+printf %s "checking for $XCRUN $LLVM_PROFDATA... " >&6; }
+ if $XCRUN $LLVM_PROFDATA --help 2>& 5 >& 5
+then :
+
LLVM_PROFDATA="$XCRUN $LLVM_PROFDATA"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
- fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+fi
+
+ if test "X$LLVM_PROFDATA" != "X"
+then :
- if test "X$LLVM_PROFDATA" != "X"; then
CFLAGS="-fprofile-instr-use=default.profdata $saved_CFLAGS";
$LLVM_PROFDATA merge -output=default.profdata *.profraw;
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-instr-use=default.profdata -Werror" >&5
-$as_echo_n "checking whether $CC accepts -fprofile-instr-use=default.profdata -Werror... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -fprofile-instr-use=default.profdata -Werror" >&5
+printf %s "checking whether $CC accepts -fprofile-instr-use=default.profdata -Werror... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
PROFILE_INSTR_USE=true
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
PROFILE_INSTR_USE=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
rm -f default.profdata
- fi
+
+fi
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
@@ -5836,54 +8465,56 @@ fi
rm -f *.profraw
CFLAGS=$saved_CFLAGS;
+
fi
# Check whether --enable-pgo was given.
-if test "${enable_pgo+set}" = set; then :
+if test ${enable_pgo+y}
+then :
enableval=$enable_pgo; case "$enableval" in
no) enable_pgo=no ;;
*) enable_pgo=yes ;;
esac
-else
+else $as_nop
enable_pgo=default
fi
USE_PGO=false
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to do PGO of erts" >&5
-$as_echo_n "checking whether to do PGO of erts... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to do PGO of erts" >&5
+printf %s "checking whether to do PGO of erts... " >&6; }
if test $enable_pgo = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, disabled by user" >&5
-$as_echo "no, disabled by user" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, disabled by user" >&5
+printf "%s\n" "no, disabled by user" >&6; }
elif test $CROSS_COMPILING = yes; then
if test $enable_pgo = yes; then
as_fn_error $? "cannot use PGO when cross-compiling" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, cross compiling" >&5
-$as_echo "no, cross compiling" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, cross compiling" >&5
+printf "%s\n" "no, cross compiling" >&6; }
fi
elif test "X$host" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, not supported in windows" >&5
-$as_echo "no, not supported in windows" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, not supported in windows" >&5
+printf "%s\n" "no, not supported in windows" >&6; }
elif test "X$PROFILE_GENERATE" = "Xtrue" -a "X$PROFILE_USE" = "Xtrue" -a "X$PROFILE_CORRECTION" = "Xtrue"; then
## We need -fprofile-generate and -fprofile-correction support to use PGO with
## gcc as multiple threads run within the executed object files
USE_PGO=true
PROFILE_COMPILER=gcc
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, using -fprofile-generate -fprofile-correction" >&5
-$as_echo "yes, using -fprofile-generate -fprofile-correction" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, using -fprofile-generate -fprofile-correction" >&5
+printf "%s\n" "yes, using -fprofile-generate -fprofile-correction" >&6; }
elif test "X$PROFILE_INSTR_GENERATE" = "Xtrue" -a "X$PROFILE_INSTR_USE" = "Xtrue"; then
USE_PGO=true
PROFILE_COMPILER=clang
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, using -fprofile-instr-generate" >&5
-$as_echo "yes, using -fprofile-instr-generate" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, using -fprofile-instr-generate" >&5
+printf "%s\n" "yes, using -fprofile-instr-generate" >&6; }
else
if test $enable_pgo = yes; then
as_fn_error $? "cannot use PGO with this compiler" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -5892,418 +8523,52 @@ USE_PGO=false
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+done
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-
-done
-
-
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -6312,14 +8577,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
# Needed for ARCH and smp checks below
if test "x$ac_cv_sizeof_void_p" = x8; then
@@ -6351,8 +8614,8 @@ esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking target hardware architecture" >&5
-$as_echo_n "checking target hardware architecture... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target hardware architecture" >&5
+printf %s "checking target hardware architecture... " >&6; }
if test "x$host_alias" != "x" -a "x$host_cpu" != "x"; then
chk_arch_=$host_cpu
else
@@ -6394,50 +8657,50 @@ $as_echo_n "checking target hardware architecture... " >&6; }
e2k) ARCH=e2k;;
*) ARCH=noarch;;
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ARCH" >&5
-$as_echo "$ARCH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ARCH" >&5
+printf "%s\n" "$ARCH" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compilation mode forces ARCH adjustment" >&5
-$as_echo_n "checking whether compilation mode forces ARCH adjustment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compilation mode forces ARCH adjustment" >&5
+printf %s "checking whether compilation mode forces ARCH adjustment... " >&6; }
case "$ARCH-$ac_cv_sizeof_void_p" in
x86-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=x86 to ARCH=amd64" >&5
-$as_echo "yes: adjusting ARCH=x86 to ARCH=amd64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=x86 to ARCH=amd64" >&5
+printf "%s\n" "yes: adjusting ARCH=x86 to ARCH=amd64" >&6; }
ARCH=amd64
;;
amd64-4)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=amd64 to ARCH=x86" >&5
-$as_echo "yes: adjusting ARCH=amd64 to ARCH=x86" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=amd64 to ARCH=x86" >&5
+printf "%s\n" "yes: adjusting ARCH=amd64 to ARCH=x86" >&6; }
ARCH=x86
;;
ultrasparc-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&5
-$as_echo "yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&5
+printf "%s\n" "yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&6; }
ARCH=sparc64
;;
sparc64-4)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&5
-$as_echo "yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&5
+printf "%s\n" "yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&6; }
ARCH=ultrasparc
;;
ppc64-4)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc64 to ARCH=ppc" >&5
-$as_echo "yes: adjusting ARCH=ppc64 to ARCH=ppc" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc64 to ARCH=ppc" >&5
+printf "%s\n" "yes: adjusting ARCH=ppc64 to ARCH=ppc" >&6; }
ARCH=ppc
;;
ppc-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc to ARCH=ppc64" >&5
-$as_echo "yes: adjusting ARCH=ppc to ARCH=ppc64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc to ARCH=ppc64" >&5
+printf "%s\n" "yes: adjusting ARCH=ppc to ARCH=ppc64" >&6; }
ARCH=ppc64
;;
arm-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=arm to ARCH=arm64" >&5
-$as_echo "yes: adjusting ARCH=arm to ARCH=arm64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=arm to ARCH=arm64" >&5
+printf "%s\n" "yes: adjusting ARCH=arm to ARCH=arm64" >&6; }
ARCH=arm64
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no: ARCH is $ARCH" >&5
-$as_echo "no: ARCH is $ARCH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no: ARCH is $ARCH" >&5
+printf "%s\n" "no: ARCH is $ARCH" >&6; }
;;
esac
@@ -6449,8 +8712,8 @@ $as_echo "no: ARCH is $ARCH" >&6; }
case $ARCH-$OPSYS in
amd64-darwin*|arm64-darwin*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: Adjusting LDFLAGS to cope with 64bit Darwin" >&5
-$as_echo "$as_me: Adjusting LDFLAGS to cope with 64bit Darwin" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Adjusting LDFLAGS to cope with 64bit Darwin" >&5
+printf "%s\n" "$as_me: Adjusting LDFLAGS to cope with 64bit Darwin" >&6;}
case $LDFLAGS in
*-m64*)
;;
@@ -6470,8 +8733,8 @@ $as_echo "$as_me: Adjusting LDFLAGS to cope with 64bit Darwin" >&6;}
;;
*)
if test X${enable_m64_build} = Xyes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Adjusting LDFLAGS to use -m64" >&5
-$as_echo "$as_me: Adjusting LDFLAGS to use -m64" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Adjusting LDFLAGS to use -m64" >&5
+printf "%s\n" "$as_me: Adjusting LDFLAGS to use -m64" >&6;}
case $LDFLAGS in
*-m64*)
;;
@@ -6481,8 +8744,8 @@ $as_echo "$as_me: Adjusting LDFLAGS to use -m64" >&6;}
esac
fi;
if test X${enable_m32_build} = Xyes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Adjusting LDFLAGS to use -m32" >&5
-$as_echo "$as_me: Adjusting LDFLAGS to use -m32" >&6;} ;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Adjusting LDFLAGS to use -m32" >&5
+printf "%s\n" "$as_me: Adjusting LDFLAGS to use -m32" >&6;} ;
case $LDFLAGS in
*-m32*)
;;
@@ -6494,18 +8757,18 @@ $as_echo "$as_me: Adjusting LDFLAGS to use -m32" >&6;} ;
;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if VM has to be linked with Carbon framework" >&5
-$as_echo_n "checking if VM has to be linked with Carbon framework... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if VM has to be linked with Carbon framework" >&5
+printf %s "checking if VM has to be linked with Carbon framework... " >&6; }
case $ARCH-$OPSYS in
*-darwin*)
LIBCARBON="-framework Carbon -framework Cocoa"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
;;
*)
LIBCARBON=
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
;;
esac
@@ -6515,11 +8778,12 @@ _search_path=/bin:/usr/bin:/usr/local/bin:$PATH
# Extract the first word of "mkdir", so it can be a program name with args.
set dummy mkdir; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_MKDIR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_MKDIR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $MKDIR in
[\\/]* | ?:[\\/]*)
ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path.
@@ -6529,11 +8793,15 @@ else
for as_dir in $_search_path
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_MKDIR="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -6546,11 +8814,11 @@ esac
fi
MKDIR=$ac_cv_path_MKDIR
if test -n "$MKDIR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5
-$as_echo "$MKDIR" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5
+printf "%s\n" "$MKDIR" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -6560,11 +8828,12 @@ fi
# Extract the first word of "cp", so it can be a program name with args.
set dummy cp; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_CP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_CP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $CP in
[\\/]* | ?:[\\/]*)
ac_cv_path_CP="$CP" # Let the user override the test with a path.
@@ -6574,11 +8843,15 @@ else
for as_dir in $_search_path
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_CP="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -6591,11 +8864,11 @@ esac
fi
CP=$ac_cv_path_CP
if test -n "$CP"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CP" >&5
-$as_echo "$CP" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CP" >&5
+printf "%s\n" "$CP" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -6611,761 +8884,19 @@ _search_path=
# just the right place.
rm -f "$ERL_TOP/erts/CONF_INFO"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we are building a sharing-preserving emulator" >&5
-$as_echo_n "checking if we are building a sharing-preserving emulator... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we are building a sharing-preserving emulator" >&5
+printf %s "checking if we are building a sharing-preserving emulator... " >&6; }
if test "$enable_sharing_preserving" = "yes"; then
-$as_echo "#define SHCOPY 1" >>confdefs.h
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
+printf "%s\n" "#define SHCOPY 1" >>confdefs.h
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
- ac_ct_RANLIB=$RANLIB
- # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_RANLIB"; then
- ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_RANLIB" = x; then
- RANLIB=":"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- RANLIB=$ac_ct_RANLIB
- fi
-else
- RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-
-for ac_prog in 'bison -y' byacc
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_YACC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$YACC"; then
- ac_cv_prog_YACC="$YACC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_YACC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-YACC=$ac_cv_prog_YACC
-if test -n "$YACC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
-$as_echo "$YACC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$YACC" && break
-done
-test -n "$YACC" || YACC="yacc"
-
-for ac_prog in perl5 perl
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PERL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $PERL in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_dummy="/usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH}"
-for as_dir in $as_dummy
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-PERL=$ac_cv_path_PERL
-if test -n "$PERL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
-$as_echo "$PERL" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$PERL" && break
-done
-test -n "$PERL" || PERL="false"
-
-if test "$PERL" = "false"; then
- ac_cv_path_PERL=false
- PERL=false
-fi
-
-if test "$ac_cv_path_PERL" = false; then
- as_fn_error $? "Perl version 5 is required to build the emulator!" "$LINENO" 5
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
-fi
-
-
-
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$AR"; then
- ac_cv_prog_AR="$AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_AR="${ac_tool_prefix}ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-AR=$ac_cv_prog_AR
-if test -n "$AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_AR"; then
- ac_ct_AR=$AR
- # Extract the first word of "ar", so it can be a program name with args.
-set dummy ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_AR"; then
- ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_AR="ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_AR=$ac_cv_prog_ac_ct_AR
-if test -n "$ac_ct_AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_AR" = x; then
- AR="false"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- AR=$ac_ct_AR
- fi
-else
- AR="$ac_cv_prog_AR"
-fi
-
-if test "$ac_cv_prog_AR" = false; then
- as_fn_error $? "No 'ar' command found in PATH" "$LINENO" 5
-fi
-
-#
-# Get programs needed for building the documentation
-#
-
-## Delete previous failed configure results
-if test -f doc/CONF_INFO; then
- rm -f doc/CONF_INFO
-fi
-
-for ac_prog in xsltproc
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_XSLTPROC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$XSLTPROC"; then
- ac_cv_prog_XSLTPROC="$XSLTPROC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_XSLTPROC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-XSLTPROC=$ac_cv_prog_XSLTPROC
-if test -n "$XSLTPROC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5
-$as_echo "$XSLTPROC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$XSLTPROC" && break
-done
-
-if test -z "$XSLTPROC"; then
- echo "xsltproc" >> doc/CONF_INFO
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No 'xsltproc' command found: the documentation cannot be built" >&5
-$as_echo "$as_me: WARNING: No 'xsltproc' command found: the documentation cannot be built" >&2;}
-fi
-
-for ac_prog in fop
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_FOP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$FOP"; then
- ac_cv_prog_FOP="$FOP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_FOP="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-FOP=$ac_cv_prog_FOP
-if test -n "$FOP"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FOP" >&5
-$as_echo "$FOP" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$FOP" && break
-done
-
-if test -z "$FOP"; then
- FOP="$ERL_TOP/make/fakefop"
- echo "fop" >> doc/CONF_INFO
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No 'fop' command found: going to generate placeholder PDF files" >&5
-$as_echo "$as_me: WARNING: No 'fop' command found: going to generate placeholder PDF files" >&2;}
-fi
-
-for ac_prog in xmllint
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_XMLLINT+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$XMLLINT"; then
- ac_cv_prog_XMLLINT="$XMLLINT" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_XMLLINT="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-XMLLINT=$ac_cv_prog_XMLLINT
-if test -n "$XMLLINT"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XMLLINT" >&5
-$as_echo "$XMLLINT" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$XMLLINT" && break
-done
-
-if test -z "$XMLLINT"; then
- echo "xmllint" >> doc/CONF_INFO
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No 'xmllint' command found: can't run the xmllint target for the documentation" >&5
-$as_echo "$as_me: WARNING: No 'xmllint' command found: can't run the xmllint target for the documentation" >&2;}
-fi
-
-case $host in
- *-*-solaris*|free_source)
- if test -x /usr/ucb/install; then
- INSTALL="/usr/ucb/install -c"
- fi
- ;;
- *)
- ;;
-esac
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
-if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- rm -rf conftest.one conftest.two conftest.dir
- echo one > conftest.one
- echo two > conftest.two
- mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
- test -s conftest.one && test -s conftest.two &&
- test -s conftest.dir/conftest.one &&
- test -s conftest.dir/conftest.two
- then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- fi
- done
- done
- ;;
-esac
-
- done
-IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- INSTALL=$ac_install_sh
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a directory including parents" >&5
-$as_echo_n "checking how to create a directory including parents... " >&6; }
-if ${ac_cv_prog_mkdir_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
-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
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_mkdir_p" >&5
-$as_echo "$ac_cv_prog_mkdir_p" >&6; }
-
-case "${ac_cv_prog_mkdir_p}" in
- none) as_fn_error $? "don't know how create directories with parents" "$LINENO" 5 ;;
- *) INSTALL_DIR="$ac_cv_prog_mkdir_p" ;;
-esac
-
-
-case $host_os in
- darwin*)
- INSTALL_DATA="$INSTALL_DATA -p";;
- *)
- ;;
-esac
-
-
-case $build in
- *tile*)
- INSTALL_PROGRAM="$INSTALL_PROGRAM -m755"
- INSTALL_SCRIPT="$INSTALL_SCRIPT -m755"
- ;;
- *)
- ;;
-esac
-
HCC='$(CC)'
HCFLAGS=""
@@ -7397,68 +8928,79 @@ esac
# AIX 4.x (perhaps only for x>=2) wants -Wl,-bexpall,-brtl and doesn't
# reliably return an error for others, thus we separate it out.
# Otherwise we assume that if the linker accepts the flag, it is needed.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra flags needed to export symbols" >&5
-$as_echo_n "checking for extra flags needed to export symbols... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for extra flags needed to export symbols" >&5
+printf %s "checking for extra flags needed to export symbols... " >&6; }
DEXPORT=""
-case $host_os in
- aix*|os400*)
+case $host_os in #(
+ aix*|os400*) :
+
DEXPORT=-Wl,-bexpall,-brtl
- ;;
- bsdi*)
+ ;; #(
+ bsdi*) :
+
DEXPORT="-rdynamic "
- ;;
- win32)
+ ;; #(
+ win32) :
+
DEXPORT=""
- ;;
- *)
+ ;; #(
+ *) :
+
+ DEXPORT=
save_ldflags="$LDFLAGS"
LDFLAGS=-Wl,-export-dynamic
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- DEXPORT=-Wl,-export-dynamic
-else
+if ac_fn_c_try_link "$LINENO"
+then :
+ DEXPORT="$LDFLAGS"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "$DEXPORT" = ""
+then :
- LDFLAGS=-Wl,-Bexport
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ LDFLAGS=-Wl,-Bexport
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- DEXPORT=-Wl,-Bexport
+if ac_fn_c_try_link "$LINENO"
+then :
+ DEXPORT="$LDFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
+
fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
LDFLAGS="$save_ldflags"
- ;;
+ ;;
esac
+
case "x$DEXPORT" in
"x")
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
-$as_echo "none" >&6; };;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
+printf "%s\n" "none" >&6; };;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEXPORT" >&5
-$as_echo "$DEXPORT" >&6; };;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DEXPORT" >&5
+printf "%s\n" "$DEXPORT" >&6; };;
esac
# Check for Solaris/ultrasparc /dev/perfmon interface
@@ -7466,7 +9008,7 @@ esac
case "${host}:${GCC}" in
sparc-*-solaris*:yes)
-$as_echo "#define HAVE_SOLARIS_SPARC_PERFMON 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SOLARIS_SPARC_PERFMON 1" >>confdefs.h
;;
*)
@@ -7478,8 +9020,8 @@ case $host_os in
darwin19*)
# Disable stack checking to avoid crashing with a segment fault
# in macOS Catalina.
- { $as_echo "$as_me:${as_lineno-$LINENO}: Turning off stack check on macOS 10.15 (Catalina)" >&5
-$as_echo "$as_me: Turning off stack check on macOS 10.15 (Catalina)" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Turning off stack check on macOS 10.15 (Catalina)" >&5
+printf "%s\n" "$as_me: Turning off stack check on macOS 10.15 (Catalina)" >&6;}
CFLAGS="-fno-stack-check $CFLAGS"
;;
*)
@@ -7488,11 +9030,12 @@ esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
-$as_echo_n "checking for sin in -lm... " >&6; }
-if ${ac_cv_lib_m_sin+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
+printf %s "checking for sin in -lm... " >&6; }
+if test ${ac_cv_lib_m_sin+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7501,43 +9044,41 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sin ();
int
-main ()
+main (void)
{
return sin ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_m_sin=yes
-else
+else $as_nop
ac_cv_lib_m_sin=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5
-$as_echo "$ac_cv_lib_m_sin" >&6; }
-if test "x$ac_cv_lib_m_sin" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBM 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5
+printf "%s\n" "$ac_cv_lib_m_sin" >&6; }
+if test "x$ac_cv_lib_m_sin" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBM 1" >>confdefs.h
LIBS="-lm $LIBS"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7546,43 +9087,84 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char dlopen ();
int
-main ()
+main (void)
{
return dlopen ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_dl_dlopen=yes
-else
+else $as_nop
ac_cv_lib_dl_dlopen=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDL 1
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h
+
+ LIBS="-ldl $LIBS"
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlvsym in -ldl" >&5
+printf %s "checking for dlvsym in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlvsym+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char dlvsym ();
+int
+main (void)
+{
+return dlvsym ();
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dl_dlvsym=yes
+else $as_nop
+ ac_cv_lib_dl_dlvsym=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlvsym" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlvsym" >&6; }
+if test "x$ac_cv_lib_dl_dlvsym" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h
LIBS="-ldl $LIBS"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
-$as_echo_n "checking for main in -linet... " >&6; }
-if ${ac_cv_lib_inet_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
+printf %s "checking for main in -linet... " >&6; }
+if test ${ac_cv_lib_inet_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-linet $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7590,38 +9172,39 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_inet_main=yes
-else
+else $as_nop
ac_cv_lib_inet_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
-$as_echo "$ac_cv_lib_inet_main" >&6; }
-if test "x$ac_cv_lib_inet_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBINET 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
+printf "%s\n" "$ac_cv_lib_inet_main" >&6; }
+if test "x$ac_cv_lib_inet_main" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBINET 1" >>confdefs.h
LIBS="-linet $LIBS"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for openpty in -lutil" >&5
-$as_echo_n "checking for openpty in -lutil... " >&6; }
-if ${ac_cv_lib_util_openpty+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openpty in -lutil" >&5
+printf %s "checking for openpty in -lutil... " >&6; }
+if test ${ac_cv_lib_util_openpty+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lutil $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7630,33 +9213,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char openpty ();
int
-main ()
+main (void)
{
return openpty ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_util_openpty=yes
-else
+else $as_nop
ac_cv_lib_util_openpty=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_util_openpty" >&5
-$as_echo "$ac_cv_lib_util_openpty" >&6; }
-if test "x$ac_cv_lib_util_openpty" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBUTIL 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_util_openpty" >&5
+printf "%s\n" "$ac_cv_lib_util_openpty" >&6; }
+if test "x$ac_cv_lib_util_openpty" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBUTIL 1" >>confdefs.h
LIBS="-lutil $LIBS"
@@ -7666,97 +9246,104 @@ fi
# Check whether --enable-native-ethr-impls was given.
-if test "${enable_native_ethr_impls+set}" = set; then :
+if test ${enable_native_ethr_impls+y}
+then :
enableval=$enable_native_ethr_impls; case "$enableval" in
no) disable_native_ethr_impls=yes ;;
*) disable_native_ethr_impls=no ;;
esac
-else
+else $as_nop
disable_native_ethr_impls=no
fi
test "X$disable_native_ethr_impls" = "Xyes" &&
-$as_echo "#define ETHR_DISABLE_NATIVE_IMPLS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_DISABLE_NATIVE_IMPLS 1" >>confdefs.h
# Check whether --enable-x86-out-of-order was given.
-if test "${enable_x86_out_of_order+set}" = set; then :
+if test ${enable_x86_out_of_order+y}
+then :
enableval=$enable_x86_out_of_order;
fi
# Check whether --enable-prefer-gcc-native-ethr-impls was given.
-if test "${enable_prefer_gcc_native_ethr_impls+set}" = set; then :
+if test ${enable_prefer_gcc_native_ethr_impls+y}
+then :
enableval=$enable_prefer_gcc_native_ethr_impls; case "$enableval" in
yes) enable_prefer_gcc_native_ethr_impls=yes ;;
*) enable_prefer_gcc_native_ethr_impls=no ;;
esac
-else
+else $as_nop
enable_prefer_gcc_native_ethr_impls=no
fi
test $enable_prefer_gcc_native_ethr_impls = yes &&
-$as_echo "#define ETHR_PREFER_GCC_NATIVE_IMPLS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_PREFER_GCC_NATIVE_IMPLS 1" >>confdefs.h
# Check whether --enable-trust-gcc-atomic-builtins-memory-barriers was given.
-if test "${enable_trust_gcc_atomic_builtins_memory_barriers+set}" = set; then :
+if test ${enable_trust_gcc_atomic_builtins_memory_barriers+y}
+then :
enableval=$enable_trust_gcc_atomic_builtins_memory_barriers; case "$enableval" in
yes) trust_gcc_atomic_builtins_mbs=1 ;;
*) trust_gcc_atomic_builtins_mbs=0 ;;
esac
-else
+else $as_nop
trust_gcc_atomic_builtins_mbs=0
fi
-cat >>confdefs.h <<_ACEOF
-#define ETHR_TRUST_GCC_ATOMIC_BUILTINS_MEMORY_BARRIERS $trust_gcc_atomic_builtins_mbs
-_ACEOF
+printf "%s\n" "#define ETHR_TRUST_GCC_ATOMIC_BUILTINS_MEMORY_BARRIERS $trust_gcc_atomic_builtins_mbs" >>confdefs.h
# Check whether --with-libatomic_ops was given.
-if test "${with_libatomic_ops+set}" = set; then :
+if test ${with_libatomic_ops+y}
+then :
withval=$with_libatomic_ops;
fi
# Check whether --with-with_sparc_memory_order was given.
-if test "${with_with_sparc_memory_order+set}" = set; then :
+if test ${with_with_sparc_memory_order+y}
+then :
withval=$with_with_sparc_memory_order;
fi
# Check whether --enable-ppc-lwsync-instruction was given.
-if test "${enable_ppc_lwsync_instruction+set}" = set; then :
+if test ${enable_ppc_lwsync_instruction+y}
+then :
enableval=$enable_ppc_lwsync_instruction; case "$enableval" in
no) enable_lwsync=no ;;
*) enable_lwsync=yes ;;
esac
-else
+else $as_nop
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -7765,14 +9352,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
case $host_cpu-$ac_cv_sizeof_void_p in
@@ -7787,12 +9372,12 @@ fi
case $enable_lwsync in
no)
-$as_echo "#define ETHR_PPC_HAVE_NO_LWSYNC 1" >>confdefs.h
+printf "%s\n" "#define ETHR_PPC_HAVE_NO_LWSYNC 1" >>confdefs.h
;;
yes)
-$as_echo "#define ETHR_PPC_HAVE_LWSYNC 1" >>confdefs.h
+printf "%s\n" "#define ETHR_PPC_HAVE_LWSYNC 1" >>confdefs.h
;;
*)
@@ -7803,29 +9388,34 @@ esac
NEED_NPTL_PTHREAD_H=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
-$as_echo_n "checking for native win32 threads... " >&6; }
-if test "X$host_os" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
+printf %s "checking for native win32 threads... " >&6; }
+if test "X$host_os" = "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
THR_LIB_TYPE=posix_unknown
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7834,40 +9424,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pthread_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_pthread_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
THR_LIBS="-lpthread"
fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
-$as_echo_n "checking for pthread_create in -lc_r... " >&6; }
-if ${ac_cv_lib_c_r_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
+printf %s "checking for pthread_create in -lc_r... " >&6; }
+if test ${ac_cv_lib_c_r_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7876,96 +9468,112 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_c_r_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_c_r_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
-$as_echo "$ac_cv_lib_c_r_pthread_create" >&6; }
-if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_c_r_pthread_create" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_create" = xyes
+then :
THR_LIBS="-lc_r"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
-if test "x$ac_cv_func_pthread_create" = xyes; then :
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes
+then :
THR_LIBS="none_needed"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
-$as_echo_n "checking if the '-pthread' switch can be used... " >&6; }
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
+printf %s "checking if the '-pthread' switch can be used... " >&6; }
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -pthread"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_create((void*)0,(void*)0,(void*)0,(void*)0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
THR_DEFS="-pthread"
THR_LIBS="-pthread"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_cflags
if test "x$THR_LIBS" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- fi
- if test "x$THR_LIBS" != "x"; then
+fi
+
+ if test "x$THR_LIBS" != "x"
+then :
+
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ case $host_os in #(
+ solaris*) :
+
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ;; #(
+ linux*) :
+
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
-if test "$cross_compiling" != "yes"; then
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -7973,11 +9581,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -7989,23 +9601,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -8013,11 +9628,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -8029,25 +9648,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -8058,11 +9680,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -8074,11 +9700,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -8087,11 +9713,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -8102,11 +9729,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -8118,11 +9749,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -8130,8 +9761,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -8140,11 +9771,13 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
-$as_echo_n "checking for Native POSIX Thread Library... " >&6; }
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
+printf %s "checking for Native POSIX Thread Library... " >&6; }
libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
if test $? -eq 0; then
case "$libpthr_vsn" in
@@ -8160,24 +9793,28 @@ $as_echo_n "checking for Native POSIX Thread Library... " >&6; }
else
nptl=no
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
-$as_echo "$nptl" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
+printf "%s\n" "$nptl" >&6; }
if test $nptl = cross; then
nptl=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
- if test $nptl = yes; then
+ if test $nptl = yes
+then :
+
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- ac_fn_c_check_header_mongrel "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_nptl_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_nptl_pthread_h" = xyes
+then :
need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes
fi
+ if test $need_nptl_incldir = yes
+then :
- if test $need_nptl_incldir = yes; then
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -8198,13 +9835,13 @@ fi
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
nptl_incldir=$dir/nptl
fi
-
if test "x$nptl_incldir" != "x"; then
THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
break
@@ -8213,38 +9850,43 @@ fi
if test "x$nptl_incldir" = "x"; then
as_fn_error $? "Failed to locate nptl system include directory" "$LINENO" 5
fi
- fi
- fi
- ;;
- *) ;;
- esac
+
+fi
+
+fi
+ ;; #(
+ *) :
+ ;;
+esac
saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $THR_DEFS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
-$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
CPPFLAGS=$saved_cppflags
- fi
+
+fi
+
fi
@@ -8252,11 +9894,12 @@ fi
ERTS_INTERNAL_X_LIBS=
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
-$as_echo_n "checking for kstat_open in -lkstat... " >&6; }
-if ${ac_cv_lib_kstat_kstat_open+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
+printf %s "checking for kstat_open in -lkstat... " >&6; }
+if test ${ac_cv_lib_kstat_kstat_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lkstat $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8265,32 +9908,31 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char kstat_open ();
int
-main ()
+main (void)
{
return kstat_open ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_kstat_kstat_open=yes
-else
+else $as_nop
ac_cv_lib_kstat_kstat_open=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
-$as_echo "$ac_cv_lib_kstat_kstat_open" >&6; }
-if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
+printf "%s\n" "$ac_cv_lib_kstat_kstat_open" >&6; }
+if test "x$ac_cv_lib_kstat_kstat_open" = xyes
+then :
-$as_echo "#define HAVE_KSTAT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_KSTAT 1" >>confdefs.h
ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"
fi
@@ -8347,11 +9989,12 @@ fi
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8360,30 +10003,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -8397,11 +10039,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
-$as_echo_n "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_raw+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
+printf %s "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_raw+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -8410,7 +10053,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -8423,23 +10066,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_raw=yes
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_raw=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_raw" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_raw" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_try_find_pthread_compatible+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_try_find_pthread_compatible+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8449,7 +10094,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -8462,56 +10107,70 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_try_find_pthread_compatible=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_try_find_pthread_compatible=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_monotonic_try_find_pthread_compatible = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_try_find_pthread_compatible" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_try_find_pthread_compatible" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_try_find_pthread_compatible" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_try_find_pthread_compatible" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- for ac_func in clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ if test "$LD_MAY_BE_WEAK" != "no"
+then :
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
- else
- for ac_func in clock_getres clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+
+
+else $as_nop
+
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
- fi
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with monotonic clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_monotonic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
+printf %s "checking for mach clock_get_time() with monotonic clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_monotonic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -8520,7 +10179,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -8535,16 +10194,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_monotonic=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_monotonic=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
-$as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_monotonic" >&6; }
erl_corrected_monotonic_clock=no
case $erl_cv_clock_gettime_monotonic_try_find_pthread_compatible-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
@@ -8611,17 +10271,17 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
case $erl_monotonic_clock_func in
clock_gettime)
-$as_echo "#define ETHR_HAVE_CLOCK_GETTIME_MONOTONIC 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_CLOCK_GETTIME_MONOTONIC 1" >>confdefs.h
;;
mach_clock_get_time)
-$as_echo "#define ETHR_HAVE_MACH_CLOCK_GET_TIME 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_MACH_CLOCK_GET_TIME 1" >>confdefs.h
;;
gethrtime)
-$as_echo "#define ETHR_HAVE_GETHRTIME 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_GETHRTIME 1" >>confdefs.h
;;
*)
@@ -8630,9 +10290,7 @@ esac
if test "x$erl_monotonic_clock_id" != "x"; then
-cat >>confdefs.h <<_ACEOF
-#define ETHR_MONOTONIC_CLOCK_ID $erl_monotonic_clock_id
-_ACEOF
+printf "%s\n" "#define ETHR_MONOTONIC_CLOCK_ID $erl_monotonic_clock_id" >>confdefs.h
fi
@@ -8650,18 +10308,19 @@ ethr_modified_default_stack_size=
# Check whether --with-threadnames was given.
-if test "${with_threadnames+set}" = set; then :
+if test ${with_threadnames+y}
+then :
withval=$with_threadnames;
-else
+else $as_nop
with_threadnames=yes
fi
ethr_lib_name=ethread
-case "$THR_LIB_NAME" in
+case "$THR_LIB_NAME" in #(
+ win32_threads) :
- win32_threads)
ETHR_THR_LIB_BASE_DIR=win
# * _WIN32_WINNT >= 0x0400 is needed for
# TryEnterCriticalSection
@@ -8690,7 +10349,7 @@ case "$THR_LIB_NAME" in
fi
-$as_echo "#define ETHR_WIN32_THREADS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_WIN32_THREADS 1" >>confdefs.h
if test "X$disable_native_ethr_impls" = "Xyes"; then
@@ -8699,8 +10358,8 @@ $as_echo "#define ETHR_WIN32_THREADS 1" >>confdefs.h
else
ilckd="_InterlockedDecrement"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8716,7 +10375,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8729,23 +10388,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDDECREMENT 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDDECREMENT 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedDecrement_rel"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8761,7 +10419,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8774,23 +10432,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDDECREMENT_REL 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDDECREMENT_REL 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedIncrement"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8806,7 +10463,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8819,23 +10476,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDINCREMENT 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDINCREMENT 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedIncrement_acq"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8851,7 +10507,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8864,23 +10520,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedExchangeAdd"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8896,7 +10551,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8909,23 +10564,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedExchangeAdd_acq"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8941,7 +10595,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8954,23 +10608,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedAnd"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -8986,7 +10639,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -8999,23 +10652,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDAND 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDAND 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedOr"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -9031,7 +10683,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -9044,23 +10696,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDOR 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDOR 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedExchange"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -9076,7 +10727,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -9089,23 +10740,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDEXCHANGE 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDEXCHANGE 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedCompareExchange"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "3" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -9121,7 +10771,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -9134,24 +10784,23 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
ilckd="_InterlockedCompareExchange_acq"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "3" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -9167,7 +10816,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -9180,24 +10829,23 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
ilckd="_InterlockedCompareExchange_rel"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "3" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (long) 0);";;
@@ -9213,7 +10861,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile long *var;
@@ -9226,25 +10874,24 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
ilckd="_InterlockedDecrement64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9260,7 +10907,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9273,23 +10920,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDDECREMENT64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDDECREMENT64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedDecrement64_rel"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9305,7 +10951,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9318,23 +10964,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDDECREMENT64_REL 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDDECREMENT64_REL 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedIncrement64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9350,7 +10995,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9363,23 +11008,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDINCREMENT64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDINCREMENT64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedIncrement64_acq"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "1" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9395,7 +11039,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9408,23 +11052,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedExchangeAdd64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9440,7 +11083,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9453,23 +11096,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedExchangeAdd64_acq"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9485,7 +11127,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9498,23 +11140,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedAnd64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9530,7 +11171,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9543,23 +11184,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDAND64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDAND64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedOr64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9575,7 +11215,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9588,23 +11228,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDOR64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDOR64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedExchange64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "2" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9620,7 +11259,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9633,23 +11272,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDEXCHANGE64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDEXCHANGE64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
ilckd="_InterlockedCompareExchange64"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "3" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9665,7 +11303,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9678,24 +11316,23 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
ilckd="_InterlockedCompareExchange64_acq"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "3" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9711,7 +11348,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9724,24 +11361,23 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
ilckd="_InterlockedCompareExchange64_rel"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "3" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9757,7 +11393,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9770,25 +11406,24 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes
ilckd="_InterlockedCompareExchange128"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
-$as_echo_n "checking for ${ilckd}()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ilckd}()" >&5
+printf %s "checking for ${ilckd}()... " >&6; }
case "4" in
"1") ilckd_call="${ilckd}(var);";;
"2") ilckd_call="${ilckd}(var, (__int64) 0);";;
@@ -9804,7 +11439,7 @@ $as_echo_n "checking for ${ilckd}()... " >&6; }
#include <intrin.h>
int
-main ()
+main (void)
{
volatile __int64 *var;
@@ -9817,30 +11452,29 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_interlocked_op=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $have_interlocked_op = yes &&
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128 1
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
-$as_echo "$have_interlocked_op" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_interlocked_op" >&5
+printf "%s\n" "$have_interlocked_op" >&6; }
fi
if test "$ethr_have_native_atomics" = "yes"; then
ethr_native_atomic_implementation=windows
ethr_have_native_spinlock=yes
fi
- ;;
+ ;; #(
+ pthread) :
- pthread)
ETHR_THR_LIB_BASE_DIR=pthread
-$as_echo "#define ETHR_PTHREADS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_PTHREADS 1" >>confdefs.h
case $host_os in
openbsd*)
@@ -9877,27 +11511,27 @@ $as_echo "#define ETHR_PTHREADS 1" >>confdefs.h
esac
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SIGUSR1 and SIGUSR2 can be used" >&5
-$as_echo_n "checking if SIGUSR1 and SIGUSR2 can be used... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $usable_sigusrx" >&5
-$as_echo "$usable_sigusrx" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if SIGUSR1 and SIGUSR2 can be used" >&5
+printf %s "checking if SIGUSR1 and SIGUSR2 can be used... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $usable_sigusrx" >&5
+printf "%s\n" "$usable_sigusrx" >&6; }
if test $usable_sigusrx = cross; then
usable_sigusrx=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
if test $usable_sigusrx = no; then
ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX"
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sigaltstack can be used" >&5
-$as_echo_n "checking if sigaltstack can be used... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $usable_sigaltstack" >&5
-$as_echo "$usable_sigaltstack" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if sigaltstack can be used" >&5
+printf %s "checking if sigaltstack can be used... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $usable_sigaltstack" >&5
+printf "%s\n" "$usable_sigaltstack" >&6; }
if test $usable_sigaltstack = cross; then
usable_sigaltstack=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
if test $usable_sigaltstack = no; then
ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK"
@@ -9912,73 +11546,54 @@ $as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;
saved_libs="$LIBS"
LIBS="$LIBS $ETHR_X_LIBS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
\
-$as_echo "#define ETHR_HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define ETHR_HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
if test $NEED_NPTL_PTHREAD_H = yes; then
-$as_echo "#define ETHR_NEED_NPTL_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define ETHR_NEED_NPTL_PTHREAD_H 1" >>confdefs.h
fi
- ac_fn_c_check_header_mongrel "$LINENO" "sched.h" "ac_cv_header_sched_h" "$ac_includes_default"
-if test "x$ac_cv_header_sched_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "sched.h" "ac_cv_header_sched_h" "$ac_includes_default"
+if test "x$ac_cv_header_sched_h" = xyes
+then :
\
-$as_echo "#define ETHR_HAVE_SCHED_H 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_SCHED_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_time_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_time_h" = xyes
+then :
\
-$as_echo "#define ETHR_HAVE_SYS_TIME_H 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_SYS_TIME_H 1" >>confdefs.h
fi
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <time.h>
- #include <sys/time.h>
-int
-main ()
-{
-struct timeval *tv; return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-$as_echo "#define ETHR_TIME_WITH_SYS_TIME 1" >>confdefs.h
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usable PTHREAD_STACK_MIN" >&5
-$as_echo_n "checking for usable PTHREAD_STACK_MIN... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for usable PTHREAD_STACK_MIN" >&5
+printf %s "checking for usable PTHREAD_STACK_MIN... " >&6; }
pthread_stack_min=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -9993,32 +11608,34 @@ $as_echo_n "checking for usable PTHREAD_STACK_MIN... " >&6; }
#endif
int
-main ()
+main (void)
{
return PTHREAD_STACK_MIN;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
pthread_stack_min=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pthread_stack_min" >&5
-$as_echo "$pthread_stack_min" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pthread_stack_min" >&5
+printf "%s\n" "$pthread_stack_min" >&6; }
test $pthread_stack_min != yes || {
-$as_echo "#define ETHR_HAVE_USABLE_PTHREAD_STACK_MIN 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_USABLE_PTHREAD_STACK_MIN 1" >>confdefs.h
}
ac_fn_c_check_func "$LINENO" "pthread_spin_lock" "ac_cv_func_pthread_spin_lock"
-if test "x$ac_cv_func_pthread_spin_lock" = xyes; then :
+if test "x$ac_cv_func_pthread_spin_lock" = xyes
+then :
\
ethr_have_native_spinlock=yes \
-$as_echo "#define ETHR_HAVE_PTHREAD_SPIN_LOCK 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_SPIN_LOCK 1" >>confdefs.h
fi
@@ -10026,16 +11643,20 @@ fi
have_sched_yield=no
have_librt_sched_yield=no
ac_fn_c_check_func "$LINENO" "sched_yield" "ac_cv_func_sched_yield"
-if test "x$ac_cv_func_sched_yield" = xyes; then :
+if test "x$ac_cv_func_sched_yield" = xyes
+then :
have_sched_yield=yes
fi
- if test $have_sched_yield = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_yield in -lrt" >&5
-$as_echo_n "checking for sched_yield in -lrt... " >&6; }
-if ${ac_cv_lib_rt_sched_yield+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test $have_sched_yield = no
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sched_yield in -lrt" >&5
+printf %s "checking for sched_yield in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_sched_yield+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -10044,41 +11665,43 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sched_yield ();
int
-main ()
+main (void)
{
return sched_yield ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_sched_yield=yes
-else
+else $as_nop
ac_cv_lib_rt_sched_yield=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_sched_yield" >&5
-$as_echo "$ac_cv_lib_rt_sched_yield" >&6; }
-if test "x$ac_cv_lib_rt_sched_yield" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_sched_yield" >&5
+printf "%s\n" "$ac_cv_lib_rt_sched_yield" >&6; }
+if test "x$ac_cv_lib_rt_sched_yield" = xyes
+then :
have_librt_sched_yield=yes
ETHR_X_LIBS="$ETHR_X_LIBS -lrt"
fi
- fi
- if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then
-$as_echo "#define ETHR_HAVE_SCHED_YIELD 1" >>confdefs.h
+fi
+ if test $have_sched_yield = yes || test $have_librt_sched_yield = yes
+then :
+
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sched_yield() returns an int" >&5
-$as_echo_n "checking whether sched_yield() returns an int... " >&6; }
+printf "%s\n" "#define ETHR_HAVE_SCHED_YIELD 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sched_yield() returns an int" >&5
+printf %s "checking whether sched_yield() returns an int... " >&6; }
sched_yield_ret_int=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10088,39 +11711,44 @@ $as_echo_n "checking whether sched_yield() returns an int... " >&6; }
#endif
int
-main ()
+main (void)
{
int sched_yield();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
sched_yield_ret_int=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sched_yield_ret_int" >&5
-$as_echo "$sched_yield_ret_int" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sched_yield_ret_int" >&5
+printf "%s\n" "$sched_yield_ret_int" >&6; }
if test $sched_yield_ret_int = yes; then
-$as_echo "#define ETHR_SCHED_YIELD_RET_INT 1" >>confdefs.h
+printf "%s\n" "#define ETHR_SCHED_YIELD_RET_INT 1" >>confdefs.h
fi
- fi
+
+fi
have_pthread_yield=no
ac_fn_c_check_func "$LINENO" "pthread_yield" "ac_cv_func_pthread_yield"
-if test "x$ac_cv_func_pthread_yield" = xyes; then :
+if test "x$ac_cv_func_pthread_yield" = xyes
+then :
have_pthread_yield=yes
fi
- if test $have_pthread_yield = yes; then
+ if test $have_pthread_yield = yes
+then :
+
-$as_echo "#define ETHR_HAVE_PTHREAD_YIELD 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_YIELD 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_yield() returns an int" >&5
-$as_echo_n "checking whether pthread_yield() returns an int... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthread_yield() returns an int" >&5
+printf %s "checking whether pthread_yield() returns an int... " >&6; }
pthread_yield_ret_int=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10134,49 +11762,56 @@ $as_echo_n "checking whether pthread_yield() returns an int... " >&6; }
#endif
int
-main ()
+main (void)
{
int pthread_yield();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_yield_ret_int=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pthread_yield_ret_int" >&5
-$as_echo "$pthread_yield_ret_int" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pthread_yield_ret_int" >&5
+printf "%s\n" "$pthread_yield_ret_int" >&6; }
if test $pthread_yield_ret_int = yes; then
-$as_echo "#define ETHR_PTHREAD_YIELD_RET_INT 1" >>confdefs.h
+printf "%s\n" "#define ETHR_PTHREAD_YIELD_RET_INT 1" >>confdefs.h
fi
- fi
+
+fi
have_pthread_rwlock_init=no
ac_fn_c_check_func "$LINENO" "pthread_rwlock_init" "ac_cv_func_pthread_rwlock_init"
-if test "x$ac_cv_func_pthread_rwlock_init" = xyes; then :
+if test "x$ac_cv_func_pthread_rwlock_init" = xyes
+then :
have_pthread_rwlock_init=yes
fi
- if test $have_pthread_rwlock_init = yes; then
+ if test $have_pthread_rwlock_init = yes
+then :
ethr_have_pthread_rwlockattr_setkind_np=no
ac_fn_c_check_func "$LINENO" "pthread_rwlockattr_setkind_np" "ac_cv_func_pthread_rwlockattr_setkind_np"
-if test "x$ac_cv_func_pthread_rwlockattr_setkind_np" = xyes; then :
+if test "x$ac_cv_func_pthread_rwlockattr_setkind_np" = xyes
+then :
ethr_have_pthread_rwlockattr_setkind_np=yes
fi
- if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then
+ if test $ethr_have_pthread_rwlockattr_setkind_np = yes
+then :
-$as_echo "#define ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP" >&5
-$as_echo_n "checking for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP... " >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP" >&5
+printf %s "checking for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP... " >&6; }
ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10190,7 +11825,7 @@ $as_echo_n "checking for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP... " >&6;
#endif
int
-main ()
+main (void)
{
pthread_rwlockattr_t *attr;
@@ -10201,47 +11836,53 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_pthread_rwlock_writer_nonrecursive_initializer_np" >&5
-$as_echo "$ethr_pthread_rwlock_writer_nonrecursive_initializer_np" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_pthread_rwlock_writer_nonrecursive_initializer_np" >&5
+printf "%s\n" "$ethr_pthread_rwlock_writer_nonrecursive_initializer_np" >&6; }
if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then
-$as_echo "#define ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 1" >>confdefs.h
fi
- fi
- fi
+
+fi
+
+fi
if test "$force_pthread_rwlocks" = "yes"; then
-$as_echo "#define ETHR_FORCE_PTHREAD_RWLOCK 1" >>confdefs.h
+printf "%s\n" "#define ETHR_FORCE_PTHREAD_RWLOCK 1" >>confdefs.h
if test $have_pthread_rwlock_init = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues." >&5
-$as_echo "$as_me: WARNING: Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues." >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues." >&5
+printf "%s\n" "$as_me: WARNING: Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues." >&2;}
else
as_fn_error $? "User forced usage of pthread rwlock, but no such implementation was found" "$LINENO" 5
fi
fi
ac_fn_c_check_func "$LINENO" "pthread_attr_setguardsize" "ac_cv_func_pthread_attr_setguardsize"
-if test "x$ac_cv_func_pthread_attr_setguardsize" = xyes; then :
+if test "x$ac_cv_func_pthread_attr_setguardsize" = xyes
+then :
\
-$as_echo "#define ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE 1" >>confdefs.h
fi
- if test "x$erl_monotonic_clock_id" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout" >&5
-$as_echo_n "checking whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout... " >&6; }
+ if test "x$erl_monotonic_clock_id" != "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout" >&5
+printf %s "checking whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout... " >&6; }
pthread_cond_timedwait_monotonic=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10253,15 +11894,9 @@ $as_echo_n "checking whether pthread_cond_timedwait() can use the monotonic cloc
#elif defined(ETHR_HAVE_PTHREAD_H)
# include <pthread.h>
#endif
- #ifdef ETHR_TIME_WITH_SYS_TIME
- # include <time.h>
+ #include <time.h>
+ #ifdef ETHR_HAVE_SYS_TIME_H
# include <sys/time.h>
- #else
- # ifdef ETHR_HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
#endif
#if defined(ETHR_HAVE_MACH_CLOCK_GET_TIME)
# include <mach/clock.h>
@@ -10269,7 +11904,7 @@ $as_echo_n "checking whether pthread_cond_timedwait() can use the monotonic cloc
#endif
int
-main ()
+main (void)
{
int res;
@@ -10286,23 +11921,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_cond_timedwait_monotonic=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pthread_cond_timedwait_monotonic" >&5
-$as_echo "$pthread_cond_timedwait_monotonic" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pthread_cond_timedwait_monotonic" >&5
+printf "%s\n" "$pthread_cond_timedwait_monotonic" >&6; }
if test $pthread_cond_timedwait_monotonic = yes; then
-$as_echo "#define ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC 1" >>confdefs.h
fi
- fi
+
+fi
linux_futex=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux futexes" >&5
-$as_echo_n "checking for Linux futexes... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Linux futexes" >&5
+printf %s "checking for Linux futexes... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10312,7 +11949,7 @@ $as_echo_n "checking for Linux futexes... " >&6; }
#include <sys/time.h>
int
-main ()
+main (void)
{
int i = 1;
@@ -10326,20 +11963,21 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
linux_futex=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $linux_futex" >&5
-$as_echo "$linux_futex" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $linux_futex" >&5
+printf "%s\n" "$linux_futex" >&6; }
test $linux_futex = yes &&
-$as_echo "#define ETHR_HAVE_LINUX_FUTEX 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_LINUX_FUTEX 1" >>confdefs.h
pthread_setname=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np" >&5
-$as_echo_n "checking for pthread_setname_np... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np" >&5
+printf %s "checking for pthread_setname_np... " >&6; }
old_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -Werror"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -10347,87 +11985,91 @@ $as_echo_n "checking for pthread_setname_np... " >&6; }
#define __USE_GNU
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_setname_np(pthread_self(), "name");
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_setname=linux
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define __USE_GNU
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_set_name_np(pthread_self(), "name");
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_setname=bsd
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _DARWIN_C_SOURCE
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_setname_np("name");
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_setname=darwin
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pthread_setname" >&5
-$as_echo "$pthread_setname" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pthread_setname" >&5
+printf "%s\n" "$pthread_setname" >&6; }
case $with_threadnames-$pthread_setname in
yes-linux)
-$as_echo "#define ETHR_HAVE_PTHREAD_SETNAME_NP_2 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_SETNAME_NP_2 1" >>confdefs.h
;;
yes-bsd)
-$as_echo "#define ETHR_HAVE_PTHREAD_SET_NAME_NP_2 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_SET_NAME_NP_2 1" >>confdefs.h
;;
yes-darwin)
-$as_echo "#define ETHR_HAVE_PTHREAD_SETNAME_NP_1 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_SETNAME_NP_1 1" >>confdefs.h
;;
*) ;;
esac
pthread_getname=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_getname_np" >&5
-$as_echo_n "checking for pthread_getname_np... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_getname_np" >&5
+printf %s "checking for pthread_getname_np... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define __USE_GNU
#define _DARWIN_C_SOURCE
#include <pthread.h>
int
-main ()
+main (void)
{
char buff[256]; pthread_getname_np(pthread_self(), buff, 256);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_getname=linux
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -10435,51 +12077,57 @@ rm -f core conftest.err conftest.$ac_objext \
#define _DARWIN_C_SOURCE
#include <pthread.h>
int
-main ()
+main (void)
{
char buff[256]; pthread_getname_np(pthread_self(), buff);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pthread_getname=ibm
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pthread_getname" >&5
-$as_echo "$pthread_getname" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pthread_getname" >&5
+printf "%s\n" "$pthread_getname" >&6; }
case $pthread_getname in
linux)
-$as_echo "#define ETHR_HAVE_PTHREAD_GETNAME_NP_3 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_GETNAME_NP_3 1" >>confdefs.h
;;
ibm)
-$as_echo "#define ETHR_HAVE_PTHREAD_GETNAME_NP_2 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_PTHREAD_GETNAME_NP_2 1" >>confdefs.h
;;
*) ;;
esac
CFLAGS=$old_CFLAGS
- if test "X$disable_native_ethr_impls" = "Xyes"; then
+ if test "X$disable_native_ethr_impls" = "Xyes"
+then :
+
ethr_have_native_atomics=no
- else
+
+else $as_nop
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
-$as_echo_n "checking size of short... " >&6; }
-if ${ac_cv_sizeof_short+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+printf %s "checking size of short... " >&6; }
+if test ${ac_cv_sizeof_short+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_short" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (short)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -10488,31 +12136,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
-$as_echo "$ac_cv_sizeof_short" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+printf "%s\n" "$ac_cv_sizeof_short" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-_ACEOF
+printf "%s\n" "#define SIZEOF_SHORT $ac_cv_sizeof_short" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
-$as_echo_n "checking size of int... " >&6; }
-if ${ac_cv_sizeof_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+printf %s "checking size of int... " >&6; }
+if test ${ac_cv_sizeof_int+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_int" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (int)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -10521,31 +12169,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
-$as_echo "$ac_cv_sizeof_int" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+printf "%s\n" "$ac_cv_sizeof_int" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
+printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
-$as_echo_n "checking size of long... " >&6; }
-if ${ac_cv_sizeof_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+printf %s "checking size of long... " >&6; }
+if test ${ac_cv_sizeof_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -10554,31 +12202,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
-$as_echo "$ac_cv_sizeof_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
-$as_echo_n "checking size of long long... " >&6; }
-if ${ac_cv_sizeof_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+printf %s "checking size of long long... " >&6; }
+if test ${ac_cv_sizeof_long_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -10587,31 +12235,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
-$as_echo "$ac_cv_sizeof_long_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of __int128_t" >&5
-$as_echo_n "checking size of __int128_t... " >&6; }
-if ${ac_cv_sizeof___int128_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of __int128_t" >&5
+printf %s "checking size of __int128_t... " >&6; }
+if test ${ac_cv_sizeof___int128_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type___int128_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (__int128_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -10620,14 +12268,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int128_t" >&5
-$as_echo "$ac_cv_sizeof___int128_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int128_t" >&5
+printf "%s\n" "$ac_cv_sizeof___int128_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF___INT128_T $ac_cv_sizeof___int128_t
-_ACEOF
+printf "%s\n" "#define SIZEOF___INT128_T $ac_cv_sizeof___int128_t" >>confdefs.h
@@ -10656,28 +12302,30 @@ _ACEOF
else
gcc_atomic_type128="#error "
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working __sync_synchronize()" >&5
-$as_echo_n "checking for a working __sync_synchronize()... " >&6; }
-if ${ethr_cv___sync_synchronize+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working __sync_synchronize()" >&5
+printf %s "checking for a working __sync_synchronize()... " >&6; }
+if test ${ethr_cv___sync_synchronize+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv___sync_synchronize=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__sync_synchronize();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv___sync_synchronize=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $ethr_cv___sync_synchronize = yes; then
#
@@ -10722,8 +12370,8 @@ EOF
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv___sync_synchronize" >&5
-$as_echo "$ethr_cv___sync_synchronize" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv___sync_synchronize" >&5
+printf "%s\n" "$ethr_cv___sync_synchronize" >&6; }
if test "$ethr_cv___sync_synchronize" = "yes"; then
have_sync_synchronize_value="~0"
@@ -10731,9 +12379,7 @@ $as_echo "$ethr_cv___sync_synchronize" >&6; }
have_sync_synchronize_value="0"
fi
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_synchronize $have_sync_synchronize_value
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_synchronize $have_sync_synchronize_value" >>confdefs.h
@@ -10772,87 +12418,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_add_and_fetch()" >&5
-$as_echo_n "checking for 32-bit __sync_add_and_fetch()... " >&6; }
-if ${ethr_cv_32bit___sync_add_and_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_add_and_fetch()" >&5
+printf %s "checking for 32-bit __sync_add_and_fetch()... " >&6; }
+if test ${ethr_cv_32bit___sync_add_and_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_add_and_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_add_and_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_add_and_fetch" >&5
-$as_echo "$ethr_cv_32bit___sync_add_and_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_add_and_fetch()" >&5
-$as_echo_n "checking for 64-bit __sync_add_and_fetch()... " >&6; }
-if ${ethr_cv_64bit___sync_add_and_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_add_and_fetch" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_add_and_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_add_and_fetch()" >&5
+printf %s "checking for 64-bit __sync_add_and_fetch()... " >&6; }
+if test ${ethr_cv_64bit___sync_add_and_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_add_and_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_add_and_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_add_and_fetch" >&5
-$as_echo "$ethr_cv_64bit___sync_add_and_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_add_and_fetch()" >&5
-$as_echo_n "checking for 128-bit __sync_add_and_fetch()... " >&6; }
-if ${ethr_cv_128bit___sync_add_and_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_add_and_fetch" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_add_and_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_add_and_fetch()" >&5
+printf %s "checking for 128-bit __sync_add_and_fetch()... " >&6; }
+if test ${ethr_cv_128bit___sync_add_and_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_add_and_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_add_and_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_add_and_fetch" >&5
-$as_echo "$ethr_cv_128bit___sync_add_and_fetch" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_add_and_fetch" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_add_and_fetch" >&6; }
case $ethr_cv_128bit___sync_add_and_fetch-$ethr_cv_64bit___sync_add_and_fetch-$ethr_cv_32bit___sync_add_and_fetch in
no-no-no)
@@ -10873,9 +12525,7 @@ $as_echo "$ethr_cv_128bit___sync_add_and_fetch" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_add_and_fetch $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_add_and_fetch $have_atomic_ops" >>confdefs.h
@@ -10914,87 +12564,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_and()" >&5
-$as_echo_n "checking for 32-bit __sync_fetch_and_and()... " >&6; }
-if ${ethr_cv_32bit___sync_fetch_and_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_and()" >&5
+printf %s "checking for 32-bit __sync_fetch_and_and()... " >&6; }
+if test ${ethr_cv_32bit___sync_fetch_and_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_fetch_and_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_fetch_and_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_and" >&5
-$as_echo "$ethr_cv_32bit___sync_fetch_and_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_and()" >&5
-$as_echo_n "checking for 64-bit __sync_fetch_and_and()... " >&6; }
-if ${ethr_cv_64bit___sync_fetch_and_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_and" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_fetch_and_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_and()" >&5
+printf %s "checking for 64-bit __sync_fetch_and_and()... " >&6; }
+if test ${ethr_cv_64bit___sync_fetch_and_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_fetch_and_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_fetch_and_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_and" >&5
-$as_echo "$ethr_cv_64bit___sync_fetch_and_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_and()" >&5
-$as_echo_n "checking for 128-bit __sync_fetch_and_and()... " >&6; }
-if ${ethr_cv_128bit___sync_fetch_and_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_and" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_fetch_and_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_and()" >&5
+printf %s "checking for 128-bit __sync_fetch_and_and()... " >&6; }
+if test ${ethr_cv_128bit___sync_fetch_and_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_fetch_and_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_fetch_and_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_and" >&5
-$as_echo "$ethr_cv_128bit___sync_fetch_and_and" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_and" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_fetch_and_and" >&6; }
case $ethr_cv_128bit___sync_fetch_and_and-$ethr_cv_64bit___sync_fetch_and_and-$ethr_cv_32bit___sync_fetch_and_and in
no-no-no)
@@ -11015,9 +12671,7 @@ $as_echo "$ethr_cv_128bit___sync_fetch_and_and" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_fetch_and_and $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_fetch_and_and $have_atomic_ops" >>confdefs.h
@@ -11056,87 +12710,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_or()" >&5
-$as_echo_n "checking for 32-bit __sync_fetch_and_or()... " >&6; }
-if ${ethr_cv_32bit___sync_fetch_and_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_or()" >&5
+printf %s "checking for 32-bit __sync_fetch_and_or()... " >&6; }
+if test ${ethr_cv_32bit___sync_fetch_and_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_fetch_and_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_fetch_and_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_or" >&5
-$as_echo "$ethr_cv_32bit___sync_fetch_and_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_or()" >&5
-$as_echo_n "checking for 64-bit __sync_fetch_and_or()... " >&6; }
-if ${ethr_cv_64bit___sync_fetch_and_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_or" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_fetch_and_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_or()" >&5
+printf %s "checking for 64-bit __sync_fetch_and_or()... " >&6; }
+if test ${ethr_cv_64bit___sync_fetch_and_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_fetch_and_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_fetch_and_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_or" >&5
-$as_echo "$ethr_cv_64bit___sync_fetch_and_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_or()" >&5
-$as_echo_n "checking for 128-bit __sync_fetch_and_or()... " >&6; }
-if ${ethr_cv_128bit___sync_fetch_and_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_or" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_fetch_and_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_or()" >&5
+printf %s "checking for 128-bit __sync_fetch_and_or()... " >&6; }
+if test ${ethr_cv_128bit___sync_fetch_and_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_fetch_and_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_fetch_and_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_or" >&5
-$as_echo "$ethr_cv_128bit___sync_fetch_and_or" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_or" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_fetch_and_or" >&6; }
case $ethr_cv_128bit___sync_fetch_and_or-$ethr_cv_64bit___sync_fetch_and_or-$ethr_cv_32bit___sync_fetch_and_or in
no-no-no)
@@ -11157,9 +12817,7 @@ $as_echo "$ethr_cv_128bit___sync_fetch_and_or" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_fetch_and_or $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_fetch_and_or $have_atomic_ops" >>confdefs.h
@@ -11198,87 +12856,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_val_compare_and_swap()" >&5
-$as_echo_n "checking for 32-bit __sync_val_compare_and_swap()... " >&6; }
-if ${ethr_cv_32bit___sync_val_compare_and_swap+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_val_compare_and_swap()" >&5
+printf %s "checking for 32-bit __sync_val_compare_and_swap()... " >&6; }
+if test ${ethr_cv_32bit___sync_val_compare_and_swap+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_val_compare_and_swap=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_val_compare_and_swap=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_val_compare_and_swap" >&5
-$as_echo "$ethr_cv_32bit___sync_val_compare_and_swap" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_val_compare_and_swap()" >&5
-$as_echo_n "checking for 64-bit __sync_val_compare_and_swap()... " >&6; }
-if ${ethr_cv_64bit___sync_val_compare_and_swap+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_val_compare_and_swap" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_val_compare_and_swap" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_val_compare_and_swap()" >&5
+printf %s "checking for 64-bit __sync_val_compare_and_swap()... " >&6; }
+if test ${ethr_cv_64bit___sync_val_compare_and_swap+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_val_compare_and_swap=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_val_compare_and_swap=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_val_compare_and_swap" >&5
-$as_echo "$ethr_cv_64bit___sync_val_compare_and_swap" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_val_compare_and_swap()" >&5
-$as_echo_n "checking for 128-bit __sync_val_compare_and_swap()... " >&6; }
-if ${ethr_cv_128bit___sync_val_compare_and_swap+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_val_compare_and_swap" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_val_compare_and_swap" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_val_compare_and_swap()" >&5
+printf %s "checking for 128-bit __sync_val_compare_and_swap()... " >&6; }
+if test ${ethr_cv_128bit___sync_val_compare_and_swap+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_val_compare_and_swap=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_val_compare_and_swap=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_val_compare_and_swap" >&5
-$as_echo "$ethr_cv_128bit___sync_val_compare_and_swap" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_val_compare_and_swap" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_val_compare_and_swap" >&6; }
case $ethr_cv_128bit___sync_val_compare_and_swap-$ethr_cv_64bit___sync_val_compare_and_swap-$ethr_cv_32bit___sync_val_compare_and_swap in
no-no-no)
@@ -11299,9 +12963,7 @@ $as_echo "$ethr_cv_128bit___sync_val_compare_and_swap" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_val_compare_and_swap $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_val_compare_and_swap $have_atomic_ops" >>confdefs.h
@@ -11341,87 +13003,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_store_n()" >&5
-$as_echo_n "checking for 32-bit __atomic_store_n()... " >&6; }
-if ${ethr_cv_32bit___atomic_store_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_store_n()" >&5
+printf %s "checking for 32-bit __atomic_store_n()... " >&6; }
+if test ${ethr_cv_32bit___atomic_store_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_store_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_store_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_store_n" >&5
-$as_echo "$ethr_cv_32bit___atomic_store_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_store_n()" >&5
-$as_echo_n "checking for 64-bit __atomic_store_n()... " >&6; }
-if ${ethr_cv_64bit___atomic_store_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_store_n" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_store_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_store_n()" >&5
+printf %s "checking for 64-bit __atomic_store_n()... " >&6; }
+if test ${ethr_cv_64bit___atomic_store_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_store_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_store_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_store_n" >&5
-$as_echo "$ethr_cv_64bit___atomic_store_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_store_n()" >&5
-$as_echo_n "checking for 128-bit __atomic_store_n()... " >&6; }
-if ${ethr_cv_128bit___atomic_store_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_store_n" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_store_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_store_n()" >&5
+printf %s "checking for 128-bit __atomic_store_n()... " >&6; }
+if test ${ethr_cv_128bit___atomic_store_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_store_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_store_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_store_n" >&5
-$as_echo "$ethr_cv_128bit___atomic_store_n" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_store_n" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_store_n" >&6; }
case $ethr_cv_128bit___atomic_store_n-$ethr_cv_64bit___atomic_store_n-$ethr_cv_32bit___atomic_store_n in
no-no-no)
@@ -11442,9 +13110,7 @@ $as_echo "$ethr_cv_128bit___atomic_store_n" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_store_n $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_store_n $have_atomic_ops" >>confdefs.h
@@ -11483,87 +13149,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_load_n()" >&5
-$as_echo_n "checking for 32-bit __atomic_load_n()... " >&6; }
-if ${ethr_cv_32bit___atomic_load_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_load_n()" >&5
+printf %s "checking for 32-bit __atomic_load_n()... " >&6; }
+if test ${ethr_cv_32bit___atomic_load_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_load_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_load_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_load_n" >&5
-$as_echo "$ethr_cv_32bit___atomic_load_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_load_n()" >&5
-$as_echo_n "checking for 64-bit __atomic_load_n()... " >&6; }
-if ${ethr_cv_64bit___atomic_load_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_load_n" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_load_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_load_n()" >&5
+printf %s "checking for 64-bit __atomic_load_n()... " >&6; }
+if test ${ethr_cv_64bit___atomic_load_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_load_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_load_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_load_n" >&5
-$as_echo "$ethr_cv_64bit___atomic_load_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_load_n()" >&5
-$as_echo_n "checking for 128-bit __atomic_load_n()... " >&6; }
-if ${ethr_cv_128bit___atomic_load_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_load_n" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_load_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_load_n()" >&5
+printf %s "checking for 128-bit __atomic_load_n()... " >&6; }
+if test ${ethr_cv_128bit___atomic_load_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_load_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_load_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_load_n" >&5
-$as_echo "$ethr_cv_128bit___atomic_load_n" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_load_n" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_load_n" >&6; }
case $ethr_cv_128bit___atomic_load_n-$ethr_cv_64bit___atomic_load_n-$ethr_cv_32bit___atomic_load_n in
no-no-no)
@@ -11584,9 +13256,7 @@ $as_echo "$ethr_cv_128bit___atomic_load_n" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_load_n $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_load_n $have_atomic_ops" >>confdefs.h
@@ -11625,87 +13295,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_add_fetch()" >&5
-$as_echo_n "checking for 32-bit __atomic_add_fetch()... " >&6; }
-if ${ethr_cv_32bit___atomic_add_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_add_fetch()" >&5
+printf %s "checking for 32-bit __atomic_add_fetch()... " >&6; }
+if test ${ethr_cv_32bit___atomic_add_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_add_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_add_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_add_fetch" >&5
-$as_echo "$ethr_cv_32bit___atomic_add_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_add_fetch()" >&5
-$as_echo_n "checking for 64-bit __atomic_add_fetch()... " >&6; }
-if ${ethr_cv_64bit___atomic_add_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_add_fetch" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_add_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_add_fetch()" >&5
+printf %s "checking for 64-bit __atomic_add_fetch()... " >&6; }
+if test ${ethr_cv_64bit___atomic_add_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_add_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_add_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_add_fetch" >&5
-$as_echo "$ethr_cv_64bit___atomic_add_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_add_fetch()" >&5
-$as_echo_n "checking for 128-bit __atomic_add_fetch()... " >&6; }
-if ${ethr_cv_128bit___atomic_add_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_add_fetch" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_add_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_add_fetch()" >&5
+printf %s "checking for 128-bit __atomic_add_fetch()... " >&6; }
+if test ${ethr_cv_128bit___atomic_add_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_add_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_add_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_add_fetch" >&5
-$as_echo "$ethr_cv_128bit___atomic_add_fetch" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_add_fetch" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_add_fetch" >&6; }
case $ethr_cv_128bit___atomic_add_fetch-$ethr_cv_64bit___atomic_add_fetch-$ethr_cv_32bit___atomic_add_fetch in
no-no-no)
@@ -11726,9 +13402,7 @@ $as_echo "$ethr_cv_128bit___atomic_add_fetch" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_add_fetch $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_add_fetch $have_atomic_ops" >>confdefs.h
@@ -11767,87 +13441,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_and()" >&5
-$as_echo_n "checking for 32-bit __atomic_fetch_and()... " >&6; }
-if ${ethr_cv_32bit___atomic_fetch_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_and()" >&5
+printf %s "checking for 32-bit __atomic_fetch_and()... " >&6; }
+if test ${ethr_cv_32bit___atomic_fetch_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_fetch_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_fetch_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_and" >&5
-$as_echo "$ethr_cv_32bit___atomic_fetch_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_and()" >&5
-$as_echo_n "checking for 64-bit __atomic_fetch_and()... " >&6; }
-if ${ethr_cv_64bit___atomic_fetch_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_and" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_fetch_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_and()" >&5
+printf %s "checking for 64-bit __atomic_fetch_and()... " >&6; }
+if test ${ethr_cv_64bit___atomic_fetch_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_fetch_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_fetch_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_and" >&5
-$as_echo "$ethr_cv_64bit___atomic_fetch_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_and()" >&5
-$as_echo_n "checking for 128-bit __atomic_fetch_and()... " >&6; }
-if ${ethr_cv_128bit___atomic_fetch_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_and" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_fetch_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_and()" >&5
+printf %s "checking for 128-bit __atomic_fetch_and()... " >&6; }
+if test ${ethr_cv_128bit___atomic_fetch_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_fetch_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_fetch_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_and" >&5
-$as_echo "$ethr_cv_128bit___atomic_fetch_and" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_and" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_fetch_and" >&6; }
case $ethr_cv_128bit___atomic_fetch_and-$ethr_cv_64bit___atomic_fetch_and-$ethr_cv_32bit___atomic_fetch_and in
no-no-no)
@@ -11868,9 +13548,7 @@ $as_echo "$ethr_cv_128bit___atomic_fetch_and" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_fetch_and $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_fetch_and $have_atomic_ops" >>confdefs.h
@@ -11909,87 +13587,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_or()" >&5
-$as_echo_n "checking for 32-bit __atomic_fetch_or()... " >&6; }
-if ${ethr_cv_32bit___atomic_fetch_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_or()" >&5
+printf %s "checking for 32-bit __atomic_fetch_or()... " >&6; }
+if test ${ethr_cv_32bit___atomic_fetch_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_fetch_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_fetch_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_or" >&5
-$as_echo "$ethr_cv_32bit___atomic_fetch_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_or()" >&5
-$as_echo_n "checking for 64-bit __atomic_fetch_or()... " >&6; }
-if ${ethr_cv_64bit___atomic_fetch_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_or" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_fetch_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_or()" >&5
+printf %s "checking for 64-bit __atomic_fetch_or()... " >&6; }
+if test ${ethr_cv_64bit___atomic_fetch_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_fetch_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_fetch_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_or" >&5
-$as_echo "$ethr_cv_64bit___atomic_fetch_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_or()" >&5
-$as_echo_n "checking for 128-bit __atomic_fetch_or()... " >&6; }
-if ${ethr_cv_128bit___atomic_fetch_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_or" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_fetch_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_or()" >&5
+printf %s "checking for 128-bit __atomic_fetch_or()... " >&6; }
+if test ${ethr_cv_128bit___atomic_fetch_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_fetch_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_fetch_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_or" >&5
-$as_echo "$ethr_cv_128bit___atomic_fetch_or" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_or" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_fetch_or" >&6; }
case $ethr_cv_128bit___atomic_fetch_or-$ethr_cv_64bit___atomic_fetch_or-$ethr_cv_32bit___atomic_fetch_or in
no-no-no)
@@ -12010,9 +13694,7 @@ $as_echo "$ethr_cv_128bit___atomic_fetch_or" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_fetch_or $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_fetch_or $have_atomic_ops" >>confdefs.h
@@ -12051,87 +13733,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_compare_exchange_n()" >&5
-$as_echo_n "checking for 32-bit __atomic_compare_exchange_n()... " >&6; }
-if ${ethr_cv_32bit___atomic_compare_exchange_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_compare_exchange_n()" >&5
+printf %s "checking for 32-bit __atomic_compare_exchange_n()... " >&6; }
+if test ${ethr_cv_32bit___atomic_compare_exchange_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_compare_exchange_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_compare_exchange_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_compare_exchange_n" >&5
-$as_echo "$ethr_cv_32bit___atomic_compare_exchange_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_compare_exchange_n()" >&5
-$as_echo_n "checking for 64-bit __atomic_compare_exchange_n()... " >&6; }
-if ${ethr_cv_64bit___atomic_compare_exchange_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_compare_exchange_n" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_compare_exchange_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_compare_exchange_n()" >&5
+printf %s "checking for 64-bit __atomic_compare_exchange_n()... " >&6; }
+if test ${ethr_cv_64bit___atomic_compare_exchange_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_compare_exchange_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_compare_exchange_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_compare_exchange_n" >&5
-$as_echo "$ethr_cv_64bit___atomic_compare_exchange_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_compare_exchange_n()" >&5
-$as_echo_n "checking for 128-bit __atomic_compare_exchange_n()... " >&6; }
-if ${ethr_cv_128bit___atomic_compare_exchange_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_compare_exchange_n" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_compare_exchange_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_compare_exchange_n()" >&5
+printf %s "checking for 128-bit __atomic_compare_exchange_n()... " >&6; }
+if test ${ethr_cv_128bit___atomic_compare_exchange_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_compare_exchange_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_compare_exchange_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_compare_exchange_n" >&5
-$as_echo "$ethr_cv_128bit___atomic_compare_exchange_n" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_compare_exchange_n" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_compare_exchange_n" >&6; }
case $ethr_cv_128bit___atomic_compare_exchange_n-$ethr_cv_64bit___atomic_compare_exchange_n-$ethr_cv_32bit___atomic_compare_exchange_n in
no-no-no)
@@ -12152,9 +13840,7 @@ $as_echo "$ethr_cv_128bit___atomic_compare_exchange_n" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_compare_exchange_n $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_compare_exchange_n $have_atomic_ops" >>confdefs.h
@@ -12162,20 +13848,25 @@ _ACEOF
ethr_arm_dbm_sy_instr_val=0
ethr_arm_dbm_st_instr_val=0
ethr_arm_dbm_ld_instr_val=0
- case "$GCC-$host_cpu" in
- yes-arm*|yes-aarch*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb sy' instruction" >&5
-$as_echo_n "checking for ARM 'dmb sy' instruction... " >&6; }
-if ${ethr_cv_arm_dbm_sy_instr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ ethr_arm_isb_sy_instr_val=0
+ ethr_arm_dc_cvau_instr_val=0
+ ethr_arm_ic_ivau_instr_val=0
+ case "$GCC-$host_cpu" in #(
+ yes-arm*|yes-aarch*) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb sy' instruction" >&5
+printf %s "checking for ARM 'dmb sy' instruction... " >&6; }
+if test ${ethr_cv_arm_dbm_sy_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_arm_dbm_sy_instr=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__asm__ __volatile__("dmb sy" : : : "memory");
@@ -12184,32 +13875,34 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_arm_dbm_sy_instr=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_sy_instr" >&5
-$as_echo "$ethr_cv_arm_dbm_sy_instr" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_sy_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dbm_sy_instr" >&6; }
if test $ethr_cv_arm_dbm_sy_instr = yes; then
ethr_arm_dbm_sy_instr_val=1
test $ethr_cv_64bit___atomic_compare_exchange_n = yes &&
ethr_have_gcc_native_atomics=yes
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb st' instruction" >&5
-$as_echo_n "checking for ARM 'dmb st' instruction... " >&6; }
-if ${ethr_cv_arm_dbm_st_instr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb st' instruction" >&5
+printf %s "checking for ARM 'dmb st' instruction... " >&6; }
+if test ${ethr_cv_arm_dbm_st_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_arm_dbm_st_instr=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__asm__ __volatile__("dmb st" : : : "memory");
@@ -12218,30 +13911,32 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_arm_dbm_st_instr=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_st_instr" >&5
-$as_echo "$ethr_cv_arm_dbm_st_instr" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_st_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dbm_st_instr" >&6; }
if test $ethr_cv_arm_dbm_st_instr = yes; then
ethr_arm_dbm_st_instr_val=1
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb ld' instruction" >&5
-$as_echo_n "checking for ARM 'dmb ld' instruction... " >&6; }
-if ${ethr_cv_arm_dbm_ld_instr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb ld' instruction" >&5
+printf %s "checking for ARM 'dmb ld' instruction... " >&6; }
+if test ${ethr_cv_arm_dbm_ld_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_arm_dbm_ld_instr=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__asm__ __volatile__("dmb ld" : : : "memory");
@@ -12250,35 +13945,144 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_arm_dbm_ld_instr=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_ld_instr" >&5
-$as_echo "$ethr_cv_arm_dbm_ld_instr" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_ld_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dbm_ld_instr" >&6; }
if test $ethr_cv_arm_dbm_ld_instr = yes; then
ethr_arm_dbm_ld_instr_val=1
- fi;;
- *)
- ;;
- esac
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'isb sy' instruction" >&5
+printf %s "checking for ARM 'isb sy' instruction... " >&6; }
+if test ${ethr_cv_arm_isb_sy_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ethr_cv_arm_isb_sy_instr=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION $ethr_arm_dbm_sy_instr_val
+int
+main (void)
+{
+
+ __asm__ __volatile__("isb sy" : : : "memory");
+
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ethr_cv_arm_isb_sy_instr=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_isb_sy_instr" >&5
+printf "%s\n" "$ethr_cv_arm_isb_sy_instr" >&6; }
+ if test $ethr_cv_arm_isb_sy_instr = yes; then
+ ethr_arm_isb_sy_instr_val=1
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dc cvau' instruction" >&5
+printf %s "checking for ARM 'dc cvau' instruction... " >&6; }
+if test ${ethr_cv_arm_dc_cvau_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ethr_cv_arm_dc_cvau_instr=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+ char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION $ethr_arm_dbm_st_instr_val
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ethr_cv_arm_dc_cvau_instr=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dc_cvau_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dc_cvau_instr" >&6; }
+ if test $ethr_cv_arm_dc_cvau_instr = yes; then
+ ethr_arm_dc_cvau_instr_val=1
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'ic ivau' instruction" >&5
+printf %s "checking for ARM 'ic ivau' instruction... " >&6; }
+if test ${ethr_cv_arm_ic_ivau_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ethr_cv_arm_ic_ivau_instr=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+ char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC_ASM_ARM_DMB_LD_INSTRUCTION $ethr_arm_dbm_ld_instr_val
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ethr_cv_arm_ic_ivau_instr=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_ic_ivau_instr" >&5
+printf "%s\n" "$ethr_cv_arm_ic_ivau_instr" >&6; }
+ if test $ethr_cv_arm_ic_ivau_instr = yes; then
+ ethr_arm_ic_ivau_instr_val=1
+ fi
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION $ethr_arm_dbm_sy_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION $ethr_arm_dbm_st_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DMB_LD_INSTRUCTION $ethr_arm_dbm_ld_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION $ethr_arm_isb_sy_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION $ethr_arm_dc_cvau_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION $ethr_arm_ic_ivau_instr_val" >>confdefs.h
+
test $ethr_cv_32bit___sync_val_compare_and_swap = yes &&
ethr_have_gcc_native_atomics=yes
@@ -12298,15 +14102,13 @@ _ACEOF
test $ethr_have_gcc_atomic_builtins = 1 && ethr_native_atomic_implementation=gcc_atomic_sync
fi
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC___ATOMIC_BUILTINS $ethr_have_gcc_atomic_builtins
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE_GCC___ATOMIC_BUILTINS $ethr_have_gcc_atomic_builtins" >>confdefs.h
test $ethr_have_gcc_native_atomics = yes && ethr_have_native_atomics=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a usable libatomic_ops implementation" >&5
-$as_echo_n "checking for a usable libatomic_ops implementation... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a usable libatomic_ops implementation" >&5
+printf %s "checking for a usable libatomic_ops implementation... " >&6; }
case "x$with_libatomic_ops" in
xno | xyes | x)
libatomic_ops_include=
@@ -12324,7 +14126,7 @@ $as_echo_n "checking for a usable libatomic_ops implementation... " >&6; }
/* end confdefs.h. */
#include "atomic_ops.h"
int
-main ()
+main (void)
{
volatile AO_t x;
@@ -12362,35 +14164,40 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_have_native_atomics=yes
ethr_native_atomic_implementation=libatomic_ops
ethr_have_libatomic_ops=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_have_libatomic_ops" >&5
-$as_echo "$ethr_have_libatomic_ops" >&6; }
- if test $ethr_have_libatomic_ops = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_have_libatomic_ops" >&5
+printf "%s\n" "$ethr_have_libatomic_ops" >&6; }
+ if test $ethr_have_libatomic_ops = yes
+then :
+
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of AO_t" >&5
-$as_echo_n "checking size of AO_t... " >&6; }
-if ${ac_cv_sizeof_AO_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of AO_t" >&5
+printf %s "checking size of AO_t... " >&6; }
+if test ${ac_cv_sizeof_AO_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (AO_t))" "ac_cv_sizeof_AO_t" "
#include <stdio.h>
#include \"atomic_ops.h\"
-"; then :
+"
+then :
-else
+else $as_nop
if test "$ac_cv_type_AO_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (AO_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12399,49 +14206,49 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_AO_t" >&5
-$as_echo "$ac_cv_sizeof_AO_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_AO_t" >&5
+printf "%s\n" "$ac_cv_sizeof_AO_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_AO_T $ac_cv_sizeof_AO_t
-_ACEOF
+printf "%s\n" "#define SIZEOF_AO_T $ac_cv_sizeof_AO_t" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF_AO_T $ac_cv_sizeof_AO_t
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF_AO_T $ac_cv_sizeof_AO_t" >>confdefs.h
-$as_echo "#define ETHR_HAVE_LIBATOMIC_OPS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_LIBATOMIC_OPS 1" >>confdefs.h
if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
-$as_echo "#define ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS 1" >>confdefs.h
fi
ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include"
- elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then
+
+elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"
+then :
+
as_fn_error $? "No usable libatomic_ops implementation found" "$LINENO" 5
- fi
+
+fi
case "$host_cpu" in
sparc | sun4u | sparc64 | sun4v)
case "$with_sparc_memory_order" in
"TSO")
-$as_echo "#define ETHR_SPARC_TSO 1" >>confdefs.h
+printf "%s\n" "#define ETHR_SPARC_TSO 1" >>confdefs.h
;;
"PSO")
-$as_echo "#define ETHR_SPARC_PSO 1" >>confdefs.h
+printf "%s\n" "#define ETHR_SPARC_PSO 1" >>confdefs.h
;;
"RMO"|"")
-$as_echo "#define ETHR_SPARC_RMO 1" >>confdefs.h
+printf "%s\n" "#define ETHR_SPARC_RMO 1" >>confdefs.h
;;
*)
as_fn_error $? "Unsupported Sparc memory order: $with_sparc_memory_order" "$LINENO" 5;;
@@ -12451,7 +14258,7 @@ $as_echo "#define ETHR_SPARC_RMO 1" >>confdefs.h
i86pc | i*86 | x86_64 | amd64)
if test "$enable_x86_out_of_order" = "yes"; then
-$as_echo "#define ETHR_X86_OUT_OF_ORDER 1" >>confdefs.h
+printf "%s\n" "#define ETHR_X86_OUT_OF_ORDER 1" >>confdefs.h
fi
ethr_native_atomic_implementation=ethread
@@ -12466,31 +14273,30 @@ $as_echo "#define ETHR_X86_OUT_OF_ORDER 1" >>confdefs.h
;;
esac
- fi
+
+fi
test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
LIBS=$saved_libs
CPPFLAGS=$saved_cppflags
- ;;
- *)
- ;;
+ ;; #(
+ *) :
+ ;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether default stack size should be modified" >&5
-$as_echo_n "checking whether default stack size should be modified... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether default stack size should be modified" >&5
+printf %s "checking whether default stack size should be modified... " >&6; }
if test "x$ethr_modified_default_stack_size" != "x"; then
-cat >>confdefs.h <<_ACEOF
-#define ETHR_MODIFIED_DEFAULT_STACK_SIZE $ethr_modified_default_stack_size
-_ACEOF
+printf "%s\n" "#define ETHR_MODIFIED_DEFAULT_STACK_SIZE $ethr_modified_default_stack_size" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes; to $ethr_modified_default_stack_size kilo words" >&5
-$as_echo "yes; to $ethr_modified_default_stack_size kilo words" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes; to $ethr_modified_default_stack_size kilo words" >&5
+printf "%s\n" "yes; to $ethr_modified_default_stack_size kilo words" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ETHR_THR_LIB_BASE" != "x"; then
@@ -12503,17 +14309,19 @@ fi
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12522,37 +14330,35 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF_PTR $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF_PTR $ac_cv_sizeof_void_p" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
-$as_echo_n "checking size of int... " >&6; }
-if ${ac_cv_sizeof_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+printf %s "checking size of int... " >&6; }
+if test ${ac_cv_sizeof_int+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_int" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (int)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12561,36 +14367,34 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
-$as_echo "$ac_cv_sizeof_int" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+printf "%s\n" "$ac_cv_sizeof_int" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
+printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
-$as_echo_n "checking size of long... " >&6; }
-if ${ac_cv_sizeof_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+printf %s "checking size of long... " >&6; }
+if test ${ac_cv_sizeof_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12599,36 +14403,34 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
-$as_echo "$ac_cv_sizeof_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
-$as_echo_n "checking size of long long... " >&6; }
-if ${ac_cv_sizeof_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+printf %s "checking size of long long... " >&6; }
+if test ${ac_cv_sizeof_long_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12637,36 +14439,34 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
-$as_echo "$ac_cv_sizeof_long_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of __int64" >&5
-$as_echo_n "checking size of __int64... " >&6; }
-if ${ac_cv_sizeof___int64+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64))" "ac_cv_sizeof___int64" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of __int64" >&5
+printf %s "checking size of __int64... " >&6; }
+if test ${ac_cv_sizeof___int64+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int64))" "ac_cv_sizeof___int64" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type___int64" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (__int64)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12675,36 +14475,34 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int64" >&5
-$as_echo "$ac_cv_sizeof___int64" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int64" >&5
+printf "%s\n" "$ac_cv_sizeof___int64" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF___INT64 $ac_cv_sizeof___int64
-_ACEOF
+printf "%s\n" "#define SIZEOF___INT64 $ac_cv_sizeof___int64" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF___INT64 $ac_cv_sizeof___int64
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF___INT64 $ac_cv_sizeof___int64" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of __int128_t" >&5
-$as_echo_n "checking size of __int128_t... " >&6; }
-if ${ac_cv_sizeof___int128_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of __int128_t" >&5
+printf %s "checking size of __int128_t... " >&6; }
+if test ${ac_cv_sizeof___int128_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type___int128_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (__int128_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -12713,20 +14511,16 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int128_t" >&5
-$as_echo "$ac_cv_sizeof___int128_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int128_t" >&5
+printf "%s\n" "$ac_cv_sizeof___int128_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF___INT128_T $ac_cv_sizeof___int128_t
-_ACEOF
+printf "%s\n" "#define SIZEOF___INT128_T $ac_cv_sizeof___int128_t" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define ETHR_SIZEOF___INT128_T $ac_cv_sizeof___int128_t
-_ACEOF
+printf "%s\n" "#define ETHR_SIZEOF___INT128_T $ac_cv_sizeof___int128_t" >>confdefs.h
@@ -12736,11 +14530,12 @@ case X$erl_xcomp_bigendian in
*) as_fn_error $? "Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian" "$LINENO" 5;;
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
-$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
-if ${ac_cv_c_bigendian+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+printf %s "checking whether byte ordering is bigendian... " >&6; }
+if test ${ac_cv_c_bigendian+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_cv_c_bigendian=unknown
# See if we're dealing with a universal compiler.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -12751,7 +14546,8 @@ else
typedef int dummy;
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
# Check for potential -arch flags. It is not universal unless
# there are at least two -arch flags with different values.
@@ -12775,7 +14571,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
fi
done
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test $ac_cv_c_bigendian = unknown; then
# See if sys/param.h defines the BYTE_ORDER macro.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -12784,7 +14580,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
#include <sys/param.h>
int
-main ()
+main (void)
{
#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
&& defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
@@ -12796,7 +14592,8 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
# It does; now see whether it defined to BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -12804,7 +14601,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
#include <sys/param.h>
int
-main ()
+main (void)
{
#if BYTE_ORDER != BIG_ENDIAN
not big endian
@@ -12814,14 +14611,15 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_c_bigendian=yes
-else
+else $as_nop
ac_cv_c_bigendian=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
@@ -12830,7 +14628,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
#include <limits.h>
int
-main ()
+main (void)
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
bogus endian macros
@@ -12840,14 +14638,15 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
# It does; now see whether it defined to _BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
int
-main ()
+main (void)
{
#ifndef _BIG_ENDIAN
not big endian
@@ -12857,31 +14656,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_c_bigendian=yes
-else
+else $as_nop
ac_cv_c_bigendian=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# Compile a test program.
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
# Try to guess by grepping values from an object file.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-short int ascii_mm[] =
+unsigned short int ascii_mm[] =
{ 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
- short int ascii_ii[] =
+ unsigned short int ascii_ii[] =
{ 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
int use_ascii (int i) {
return ascii_mm[i] + ascii_ii[i];
}
- short int ebcdic_ii[] =
+ unsigned short int ebcdic_ii[] =
{ 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
- short int ebcdic_mm[] =
+ unsigned short int ebcdic_mm[] =
{ 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
int use_ebcdic (int i) {
return ebcdic_mm[i] + ebcdic_ii[i];
@@ -12889,14 +14690,15 @@ short int ascii_mm[] =
extern int foo;
int
-main ()
+main (void)
{
return use_ascii (foo) == use_ebcdic (foo);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
ac_cv_c_bigendian=yes
fi
@@ -12909,13 +14711,13 @@ if ac_fn_c_try_compile "$LINENO"; then :
fi
fi
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
-main ()
+main (void)
{
/* Are we little or big endian? From Harbison&Steele. */
@@ -12931,9 +14733,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_c_bigendian=no
-else
+else $as_nop
ac_cv_c_bigendian=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -12942,17 +14745,17 @@ fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
-$as_echo "$ac_cv_c_bigendian" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+printf "%s\n" "$ac_cv_c_bigendian" >&6; }
case $ac_cv_c_bigendian in #(
yes)
- $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+ printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h
;; #(
no)
;; #(
universal)
-$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
;; #(
*)
@@ -12963,7 +14766,7 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
if test "$ac_cv_c_bigendian" = "yes"; then
-$as_echo "#define ETHR_BIGENDIAN 1" >>confdefs.h
+printf "%s\n" "#define ETHR_BIGENDIAN 1" >>confdefs.h
fi
@@ -12973,15 +14776,17 @@ case X$erl_xcomp_double_middle_endian in
*) as_fn_error $? "Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian" "$LINENO" 5;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether double word ordering is middle-endian" >&5
-$as_echo_n "checking whether double word ordering is middle-endian... " >&6; }
-if ${ac_cv_c_double_middle_endian+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether double word ordering is middle-endian" >&5
+printf %s "checking whether double word ordering is middle-endian... " >&6; }
+if test ${ac_cv_c_double_middle_endian+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
# It does not; compile a test program.
-if test "$cross_compiling" = yes; then :
+if test "$cross_compiling" = yes
+then :
ac_cv_c_double_middle=unknown
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
@@ -13050,9 +14855,10 @@ main(void)
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_c_double_middle_endian=no
-else
+else $as_nop
ac_cv_c_double_middle_endian=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -13060,28 +14866,29 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_double_middle_endian" >&5
-$as_echo "$ac_cv_c_double_middle_endian" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_double_middle_endian" >&5
+printf "%s\n" "$ac_cv_c_double_middle_endian" >&6; }
case $ac_cv_c_double_middle_endian in
yes)
-$as_echo "#define DOUBLE_MIDDLE_ENDIAN 1" >>confdefs.h
+printf "%s\n" "#define DOUBLE_MIDDLE_ENDIAN 1" >>confdefs.h
;;
no)
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unknown double endianness
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unknown double endianness
presetting ac_cv_c_double_middle_endian=no (or yes) will help" >&5
-$as_echo "$as_me: WARNING: unknown double endianness
+printf "%s\n" "$as_me: WARNING: unknown double endianness
presetting ac_cv_c_double_middle_endian=no (or yes) will help" >&2;} ;;
esac
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)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc sse2 asm support" >&5
-$as_echo_n "checking for gcc sse2 asm support... " >&6; }
+case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in #(
+ yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc sse2 asm support" >&5
+printf %s "checking for gcc sse2 asm support... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -msse2"
gcc_sse2_asm=no
@@ -13089,7 +14896,7 @@ $as_echo_n "checking for gcc sse2 asm support... " >&6; }
/* end confdefs.h. */
int
-main ()
+main (void)
{
long long x, *y;
@@ -13099,26 +14906,27 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
gcc_sse2_asm=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS="$save_CFLAGS"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_sse2_asm" >&5
-$as_echo "$gcc_sse2_asm" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gcc_sse2_asm" >&5
+printf "%s\n" "$gcc_sse2_asm" >&6; }
if test "$gcc_sse2_asm" = "yes"; then
-$as_echo "#define ETHR_GCC_HAVE_SSE2_ASM_SUPPORT 1" >>confdefs.h
+printf "%s\n" "#define ETHR_GCC_HAVE_SSE2_ASM_SUPPORT 1" >>confdefs.h
ETHR_X86_SSE2_ASM=yes
fi
- ;;
- *)
- ;;
+ ;; #(
+ *) :
+ ;;
esac
-case "$GCC-$host_cpu" in
- yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64)
+case "$GCC-$host_cpu" in #(
+ yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64) :
if test $ac_cv_sizeof_void_p = 4; then
dw_cmpxchg="cmpxchg8b"
@@ -13145,15 +14953,15 @@ case "$GCC-$host_cpu" in
*) pic_text="";;
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc $pic_text$dw_cmpxchg plain asm support" >&5
-$as_echo_n "checking for gcc $pic_text$dw_cmpxchg plain asm support... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc $pic_text$dw_cmpxchg plain asm support" >&5
+printf %s "checking for gcc $pic_text$dw_cmpxchg plain asm support... " >&6; }
plain_cmpxchg=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
char xchgd;
@@ -13173,13 +14981,14 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
plain_cmpxchg=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $plain_cmpxchg" >&5
-$as_echo "$plain_cmpxchg" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $plain_cmpxchg" >&5
+printf "%s\n" "$plain_cmpxchg" >&6; }
if test $pic_cmpxchg = yes; then
gcc_pic_dw_cmpxchg_asm=$plain_cmpxchg
@@ -13200,7 +15009,7 @@ $as_echo "$plain_cmpxchg" >&6; }
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if !defined(__PIC__) || !__PIC__
@@ -13211,13 +15020,14 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
pic_cmpxchg=yes
gcc_cflags_pic=yes
-else
+else $as_nop
pic_cmpxchg=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test $pic_cmpxchg = yes; then
gcc_pic_dw_cmpxchg_asm=$gcc_dw_cmpxchg_asm
@@ -13229,10 +15039,12 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
- if test $gcc_pic_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ if test $gcc_pic_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4
+then :
+
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc pic cmpxchg8b asm support with EBX workaround" >&5
-$as_echo_n "checking for gcc pic cmpxchg8b asm support with EBX workaround... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc pic cmpxchg8b asm support with EBX workaround" >&5
+printf %s "checking for gcc pic cmpxchg8b asm support with EBX workaround... " >&6; }
# Check if we can work around it by managing the ebx
# register explicitly in the asm...
@@ -13241,7 +15053,7 @@ $as_echo_n "checking for gcc pic cmpxchg8b asm support with EBX workaround... "
/* end confdefs.h. */
int
-main ()
+main (void)
{
char xchgd;
@@ -13260,19 +15072,22 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
gcc_pic_dw_cmpxchg_asm=yes
gcc_cmpxchg8b_pic_no_clobber_ebx=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gcc_pic_dw_cmpxchg_asm" >&5
+printf "%s\n" "$gcc_pic_dw_cmpxchg_asm" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_pic_dw_cmpxchg_asm" >&5
-$as_echo "$gcc_pic_dw_cmpxchg_asm" >&6; }
+ if test $gcc_pic_dw_cmpxchg_asm = no
+then :
- if test $gcc_pic_dw_cmpxchg_asm = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds" >&5
-$as_echo_n "checking for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds" >&5
+printf %s "checking for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds... " >&6; }
# If no optimization is enabled we sometimes get a
# register shortage. Check if we can work around
# this...
@@ -13281,7 +15096,7 @@ $as_echo_n "checking for gcc pic cmpxchg8b asm support with EBX and register sho
/* end confdefs.h. */
int
-main ()
+main (void)
{
char xchgd;
@@ -13302,46 +15117,49 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
gcc_pic_dw_cmpxchg_asm=yes
gcc_cmpxchg8b_pic_no_clobber_ebx=yes
gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_pic_dw_cmpxchg_asm" >&5
-$as_echo "$gcc_pic_dw_cmpxchg_asm" >&6; }
- fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gcc_pic_dw_cmpxchg_asm" >&5
+printf "%s\n" "$gcc_pic_dw_cmpxchg_asm" >&6; }
+
+fi
if test $gcc_cflags_pic = yes; then
gcc_dw_cmpxchg_asm=$gcc_pic_dw_cmpxchg_asm
fi
- fi
+fi
CFLAGS="$save_CFLAGS"
if test "$gcc_cmpxchg8b_pic_no_clobber_ebx" = "yes"; then
-$as_echo "#define ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX 1" >>confdefs.h
+printf "%s\n" "#define ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX 1" >>confdefs.h
fi
if test "$gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage" = "yes"; then
-$as_echo "#define ETHR_CMPXCHG8B_REGISTER_SHORTAGE 1" >>confdefs.h
+printf "%s\n" "#define ETHR_CMPXCHG8B_REGISTER_SHORTAGE 1" >>confdefs.h
fi
if test "$gcc_dw_cmpxchg_asm" = "yes"; then
-$as_echo "#define ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT 1" >>confdefs.h
+printf "%s\n" "#define ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT 1" >>confdefs.h
- fi;;
- *)
- ;;
+ fi
+ ;; #(
+ *) :
+ ;;
esac
-$as_echo "#define ETHR_HAVE_ETHREAD_DEFINES 1" >>confdefs.h
+printf "%s\n" "#define ETHR_HAVE_ETHREAD_DEFINES 1" >>confdefs.h
@@ -13358,7 +15176,7 @@ if test "X$ETHR_LIB_NAME" = "X"; then
as_fn_error $? "cannot build emulator since no thread library was found" "$LINENO" 5
fi
-TYPES=opt
+DEFAULT_TYPES="opt"
DIRTY_SCHEDULER_TEST=$enable_dirty_schedulers_test
@@ -13377,7 +15195,7 @@ EOF
test "X$smp_require_native_atomics" = "Xyes" &&
-$as_echo "#define ETHR_SMP_REQUIRE_NATIVE_IMPLS 1" >>confdefs.h
+printf "%s\n" "#define ETHR_SMP_REQUIRE_NATIVE_IMPLS 1" >>confdefs.h
case "$ethr_have_native_atomics-$smp_require_native_atomics-$ethr_have_native_spinlock" in
@@ -13441,35 +15259,32 @@ EOF
esac
-for ac_func in posix_fadvise closefrom
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "posix_fadvise" "ac_cv_func_posix_fadvise"
+if test "x$ac_cv_func_posix_fadvise" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_FADVISE 1" >>confdefs.h
fi
-done
-
-for ac_header in linux/falloc.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "linux/falloc.h" "ac_cv_header_linux_falloc_h" "$ac_includes_default"
-if test "x$ac_cv_header_linux_falloc_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LINUX_FALLOC_H 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "closefrom" "ac_cv_func_closefrom"
+if test "x$ac_cv_func_closefrom" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOSEFROM 1" >>confdefs.h
fi
-done
+ac_fn_c_check_header_compile "$LINENO" "linux/falloc.h" "ac_cv_header_linux_falloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_falloc_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LINUX_FALLOC_H 1" >>confdefs.h
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether fallocate() works" >&5
-$as_echo_n "checking whether fallocate() works... " >&6; }
-if ${i_cv_fallocate_works+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether fallocate() works" >&5
+printf %s "checking whether fallocate() works... " >&6; }
+if test ${i_cv_fallocate_works+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -13482,7 +15297,7 @@ else
#include <linux/falloc.h>
int
-main ()
+main (void)
{
int fd = creat("conftest.temp", 0600);
@@ -13492,34 +15307,37 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
i_cv_fallocate_works=yes
-else
+else $as_nop
i_cv_fallocate_works=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $i_cv_fallocate_works" >&5
-$as_echo "$i_cv_fallocate_works" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $i_cv_fallocate_works" >&5
+printf "%s\n" "$i_cv_fallocate_works" >&6; }
if test $i_cv_fallocate_works = yes; then
-$as_echo "#define HAVE_FALLOCATE 1" >>confdefs.h
+printf "%s\n" "#define HAVE_FALLOCATE 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether posix_fallocate() works" >&5
-$as_echo_n "checking whether posix_fallocate() works... " >&6; }
-if ${i_cv_posix_fallocate_works+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether posix_fallocate() works" >&5
+printf %s "checking whether posix_fallocate() works... " >&6; }
+if test ${i_cv_posix_fallocate_works+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
i_cv_posix_fallocate_works=no
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -13546,11 +15364,12 @@ else
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
i_cv_posix_fallocate_works=yes
-else
+else $as_nop
i_cv_posix_fallocate_works=no
@@ -13561,11 +15380,11 @@ fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $i_cv_posix_fallocate_works" >&5
-$as_echo "$i_cv_posix_fallocate_works" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $i_cv_posix_fallocate_works" >&5
+printf "%s\n" "$i_cv_posix_fallocate_works" >&6; }
if test $i_cv_posix_fallocate_works = yes; then
-$as_echo "#define HAVE_POSIX_FALLOCATE /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_POSIX_FALLOCATE /**/" >>confdefs.h
fi
@@ -13588,35 +15407,35 @@ EMU_THR_X_LIBS=$ETHR_X_LIBS
EMU_THR_LIBS=$ETHR_LIBS
EMU_THR_DEFS=$ETHR_DEFS
ENABLE_ALLOC_TYPE_VARS="$ENABLE_ALLOC_TYPE_VARS threads"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lock checking should be enabled" >&5
-$as_echo_n "checking whether lock checking should be enabled... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_lock_check" >&5
-$as_echo "$enable_lock_check" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether lock checking should be enabled" >&5
+printf %s "checking whether lock checking should be enabled... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_lock_check" >&5
+printf "%s\n" "$enable_lock_check" >&6; }
if test "x$enable_lock_check" != "xno"; then
EMU_THR_DEFS="$EMU_THR_DEFS -DERTS_ENABLE_LOCK_CHECK"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lock counters should be enabled" >&5
-$as_echo_n "checking whether lock counters should be enabled... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_lock_count" >&5
-$as_echo "$enable_lock_count" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether lock counters should be enabled" >&5
+printf %s "checking whether lock counters should be enabled... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_lock_count" >&5
+printf "%s\n" "$enable_lock_count" >&6; }
if test "x$enable_lock_count" != "xno"; then
- TYPES="$TYPES lcnt"
+ DEFAULT_TYPES="$DEFAULT_TYPES lcnt"
fi
case $host_os in
linux*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether dlopen() needs to be called before first call to dlerror()" >&5
-$as_echo_n "checking whether dlopen() needs to be called before first call to dlerror()... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether dlopen() needs to be called before first call to dlerror()" >&5
+printf %s "checking whether dlopen() needs to be called before first call to dlerror()... " >&6; }
if test "x$ETHR_THR_LIB_BASE_TYPE" != "xposix_nptl"; then
-$as_echo "#define ERTS_NEED_DLOPEN_BEFORE_DLERROR 1" >>confdefs.h
+printf "%s\n" "#define ERTS_NEED_DLOPEN_BEFORE_DLERROR 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
;;
*)
@@ -13655,11 +15474,12 @@ fi
ERTS_INTERNAL_X_LIBS=
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
-$as_echo_n "checking for kstat_open in -lkstat... " >&6; }
-if ${ac_cv_lib_kstat_kstat_open+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
+printf %s "checking for kstat_open in -lkstat... " >&6; }
+if test ${ac_cv_lib_kstat_kstat_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lkstat $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -13668,32 +15488,31 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char kstat_open ();
int
-main ()
+main (void)
{
return kstat_open ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_kstat_kstat_open=yes
-else
+else $as_nop
ac_cv_lib_kstat_kstat_open=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
-$as_echo "$ac_cv_lib_kstat_kstat_open" >&6; }
-if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
+printf "%s\n" "$ac_cv_lib_kstat_kstat_open" >&6; }
+if test "x$ac_cv_lib_kstat_kstat_open" = xyes
+then :
-$as_echo "#define HAVE_KSTAT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_KSTAT 1" >>confdefs.h
ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"
fi
@@ -13712,18 +15531,20 @@ THR_DEFS=$ETHR_DEFS
TERMCAP_LIB=
-if test "x$with_termcap" != "xno" &&
- test "X$host" != "Xwin32"; then
+if test "x$with_termcap" != "xno" && test "X$host" != "Xwin32"
+then :
+
# try these libs
termcap_libs="tinfo ncurses curses termcap termlib"
for termcap_lib in $termcap_libs; do
- as_ac_Lib=`$as_echo "ac_cv_lib_$termcap_lib''_tgetent" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for tgetent in -l$termcap_lib" >&5
-$as_echo_n "checking for tgetent in -l$termcap_lib... " >&6; }
-if eval \${$as_ac_Lib+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$termcap_lib""_tgetent" | $as_tr_sh`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -l$termcap_lib" >&5
+printf %s "checking for tgetent in -l$termcap_lib... " >&6; }
+if eval test \${$as_ac_Lib+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-l$termcap_lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -13732,31 +15553,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char tgetent ();
int
-main ()
+main (void)
{
return tgetent ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$as_ac_Lib=yes"
-else
+else $as_nop
eval "$as_ac_Lib=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
eval ac_res=\$$as_ac_Lib
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+then :
TERMCAP_LIB="-l$termcap_lib"
fi
@@ -13768,6 +15588,7 @@ fi
if test "x$TERMCAP_LIB" = "x"; then
as_fn_error $? "No curses library functions found" "$LINENO" 5
fi
+
fi
@@ -13775,63 +15596,72 @@ fi
if test "x$TERMCAP_LIB" != "x"; then
-$as_echo "#define HAVE_TERMCAP 1" >>confdefs.h
+printf "%s\n" "#define HAVE_TERMCAP 1" >>confdefs.h
fi
-if test "X$host" != "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wcwidth" >&5
-$as_echo_n "checking for wcwidth... " >&6; }
+if test "X$host" != "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wcwidth" >&5
+printf %s "checking for wcwidth... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <wchar.h>
int
-main ()
+main (void)
{
wcwidth(0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_wcwidth=yes
-else
+else $as_nop
have_wcwidth=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $have_wcwidth = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_WCWIDTH 1" >>confdefs.h
+printf "%s\n" "#define HAVE_WCWIDTH 1" >>confdefs.h
fi
+
fi
# Check whether --enable-builtin-zlib was given.
-if test "${enable_builtin_zlib+set}" = set; then :
+if test ${enable_builtin_zlib+y}
+then :
enableval=$enable_builtin_zlib; case "$enableval" in
no) enable_builtin_zlib=no ;;
*) enable_builtin_zlib=yes ;;
esac
-else
+else $as_nop
enable_builtin_zlib=no
fi
Z_LIB=
-if test "x$enable_builtin_zlib" = "xyes"; then
+if test "x$enable_builtin_zlib" = "xyes"
+then :
-$as_echo "#define HAVE_ZLIB_INFLATEGETDICTIONARY 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: Using our own built-in zlib source" >&5
-$as_echo "$as_me: Using our own built-in zlib source" >&6;}
-else
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlib 1.2.5 or higher" >&5
-$as_echo_n "checking for zlib 1.2.5 or higher... " >&6; }
+printf "%s\n" "#define HAVE_ZLIB_INFLATEGETDICTIONARY 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using our own built-in zlib source" >&5
+printf "%s\n" "$as_me: Using our own built-in zlib source" >&6;}
+
+else $as_nop
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib 1.2.5 or higher" >&5
+printf %s "checking for zlib 1.2.5 or higher... " >&6; }
zlib_save_LIBS=$LIBS
LIBS="-lz $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -13840,7 +15670,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include "zlib.h"
int
-main ()
+main (void)
{
#if ZLIB_VERNUM >= 0x1250
@@ -13856,30 +15686,34 @@ error
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
Z_LIB="-lz"
-$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
+printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-if test "$Z_LIB" != ""; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inflateGetDictionary" >&5
-$as_echo_n "checking for library containing inflateGetDictionary... " >&6; }
-if ${ac_cv_search_inflateGetDictionary+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "$Z_LIB" != ""
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing inflateGetDictionary" >&5
+printf %s "checking for library containing inflateGetDictionary... " >&6; }
+if test ${ac_cv_search_inflateGetDictionary+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -13887,107 +15721,130 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char inflateGetDictionary ();
int
-main ()
+main (void)
{
return inflateGetDictionary ();
;
return 0;
}
_ACEOF
-for ac_lib in '' z; do
+for ac_lib in '' z
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_inflateGetDictionary=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_inflateGetDictionary+:} false; then :
+ if test ${ac_cv_search_inflateGetDictionary+y}
+then :
break
fi
done
-if ${ac_cv_search_inflateGetDictionary+:} false; then :
+if test ${ac_cv_search_inflateGetDictionary+y}
+then :
-else
+else $as_nop
ac_cv_search_inflateGetDictionary=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inflateGetDictionary" >&5
-$as_echo "$ac_cv_search_inflateGetDictionary" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inflateGetDictionary" >&5
+printf "%s\n" "$ac_cv_search_inflateGetDictionary" >&6; }
ac_res=$ac_cv_search_inflateGetDictionary
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-$as_echo "#define HAVE_ZLIB_INFLATEGETDICTIONARY 1" >>confdefs.h
+printf "%s\n" "#define HAVE_ZLIB_INFLATEGETDICTIONARY 1" >>confdefs.h
fi
+
fi
LIBS=$zlib_save_LIBS
+
fi
+
# Check whether --enable-esock was given.
-if test "${enable_esock+set}" = set; then :
- enableval=$enable_esock;
+if test ${enable_esock+y}
+then :
+ enableval=$enable_esock; case "$enableval" in
+ no) enable_esock=no ;;
+ *) enable_esock=yes ;;
+ esac
+
+else $as_nop
+ enable_esock=yes
fi
-USE_ESOCK=yes
+if test "x$enable_esock" = "xyes"
+then :
+
+
+printf "%s\n" "#define ESOCK_ENABLE 1" >>confdefs.h
+
+ ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r"
+if test "x$ac_cv_func_localtime_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h
-if test "x$enable_esock" = "xyes"; then
- USE_ESOCK=yes
-else
- if test "x$enable_esock" = "xno"; then
- USE_ESOCK=no
- fi
fi
+ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
+if test "x$ac_cv_func_strftime" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h
-if test "x$USE_ESOCK" = "xyes"; then
- if test "x$USE_ESOCK" = "xyes"; then
- for ac_func in localtime_r strftime getprotoent setprotoent endprotoent
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+ac_fn_c_check_func "$LINENO" "getprotoent" "ac_cv_func_getprotoent"
+if test "x$ac_cv_func_getprotoent" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETPROTOENT 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "setprotoent" "ac_cv_func_setprotoent"
+if test "x$ac_cv_func_setprotoent" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETPROTOENT 1" >>confdefs.h
- fi
fi
+ac_fn_c_check_func "$LINENO" "endprotoent" "ac_cv_func_endprotoent"
+if test "x$ac_cv_func_endprotoent" = xyes
+then :
+ printf "%s\n" "#define HAVE_ENDPROTOENT 1" >>confdefs.h
+fi
+fi
# Check whether --enable-esock_use_rcvsndtimeo was given.
-if test "${enable_esock_use_rcvsndtimeo+set}" = set; then :
+if test ${enable_esock_use_rcvsndtimeo+y}
+then :
enableval=$enable_esock_use_rcvsndtimeo;
fi
if test "x$enable_esock_rcvsndtimeo" = "xyes"; then
-$as_echo "#define ESOCK_USE_RCVSNDTIMEO 1" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_RCVSNDTIMEO 1" >>confdefs.h
fi
@@ -13995,9 +15852,10 @@ fi
# Check whether --with-esock-counter-size was given.
-if test "${with_esock_counter_size+set}" = set; then :
+if test ${with_esock_counter_size+y}
+then :
withval=$with_esock_counter_size;
-else
+else $as_nop
with_esock_counter_size=64
fi
@@ -14005,73 +15863,78 @@ fi
case "$with_esock_counter_size" in
16)
-$as_echo "#define ESOCK_COUNTER_SIZE 16" >>confdefs.h
+printf "%s\n" "#define ESOCK_COUNTER_SIZE 16" >>confdefs.h
;;
24)
-$as_echo "#define ESOCK_COUNTER_SIZE 24" >>confdefs.h
+printf "%s\n" "#define ESOCK_COUNTER_SIZE 24" >>confdefs.h
;;
32)
-$as_echo "#define ESOCK_COUNTER_SIZE 32" >>confdefs.h
+printf "%s\n" "#define ESOCK_COUNTER_SIZE 32" >>confdefs.h
;;
48)
-$as_echo "#define ESOCK_COUNTER_SIZE 48" >>confdefs.h
+printf "%s\n" "#define ESOCK_COUNTER_SIZE 48" >>confdefs.h
;;
64)
-$as_echo "#define ESOCK_COUNTER_SIZE 64" >>confdefs.h
+printf "%s\n" "#define ESOCK_COUNTER_SIZE 64" >>confdefs.h
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Invalid esock counter size ($with_esock_counter_size), using default (64)" >&5
-$as_echo "$as_me: WARNING: Invalid esock counter size ($with_esock_counter_size), using default (64)" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Invalid esock counter size ($with_esock_counter_size), using default (64)" >&5
+printf "%s\n" "$as_me: WARNING: Invalid esock counter size ($with_esock_counter_size), using default (64)" >&2;}
-$as_echo "#define ESOCK_COUNTER_SIZE 64" >>confdefs.h
+printf "%s\n" "#define ESOCK_COUNTER_SIZE 64" >>confdefs.h
;;
esac
ac_fn_c_check_func "$LINENO" "if_nametoindex" "ac_cv_func_if_nametoindex"
-if test "x$ac_cv_func_if_nametoindex" = xyes; then :
+if test "x$ac_cv_func_if_nametoindex" = xyes
+then :
-$as_echo "#define HAVE_IF_NAMETOINDEX 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IF_NAMETOINDEX 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "if_indextoname" "ac_cv_func_if_indextoname"
-if test "x$ac_cv_func_if_indextoname" = xyes; then :
+if test "x$ac_cv_func_if_indextoname" = xyes
+then :
-$as_echo "#define HAVE_IF_INDEXTONAME 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IF_INDEXTONAME 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "if_nameindex" "ac_cv_func_if_nameindex"
-if test "x$ac_cv_func_if_nameindex" = xyes; then :
+if test "x$ac_cv_func_if_nameindex" = xyes
+then :
-$as_echo "#define HAVE_IF_NAMEINDEX 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IF_NAMEINDEX 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "if_freenameindex" "ac_cv_func_if_freenameindex"
-if test "x$ac_cv_func_if_freenameindex" = xyes; then :
+if test "x$ac_cv_func_if_freenameindex" = xyes
+then :
-$as_echo "#define HAVE_IF_FREENAMEINDEX 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IF_FREENAMEINDEX 1" >>confdefs.h
fi
ac_fn_c_check_func "$LINENO" "gethostname" "ac_cv_func_gethostname"
-if test "x$ac_cv_func_gethostname" = xyes; then :
+if test "x$ac_cv_func_gethostname" = xyes
+then :
-$as_echo "#define HAVE_GETHOSTNAME 1" >>confdefs.h
+printf "%s\n" "#define HAVE_GETHOSTNAME 1" >>confdefs.h
fi
@@ -14080,20 +15943,22 @@ fi
# Check whether --enable-esock-socket-registry was given.
-if test "${enable_esock_socket_registry+set}" = set; then :
+if test ${enable_esock_socket_registry+y}
+then :
enableval=$enable_esock_socket_registry;
fi
-if test "x$enable_esock_socket_registry" = "xno"; then :
+if test "x$enable_esock_socket_registry" = "xno"
+then :
-$as_echo "#define ESOCK_USE_SOCKET_REGISTRY 0" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_SOCKET_REGISTRY 0" >>confdefs.h
-else
+else $as_nop
-$as_echo "#define ESOCK_USE_SOCKET_REGISTRY 1" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_SOCKET_REGISTRY 1" >>confdefs.h
fi
@@ -14104,14 +15969,13 @@ ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_map" "ac_cv_member_struct_ifr
#endif
"
-if test "x$ac_cv_member_struct_ifreq_ifr_map" = xyes; then :
+if test "x$ac_cv_member_struct_ifreq_ifr_map" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_IFREQ_IFR_MAP 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_IFREQ_IFR_MAP 1" >>confdefs.h
-$as_echo "#define ESOCK_USE_IFMAP /**/" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_IFMAP /**/" >>confdefs.h
fi
@@ -14122,14 +15986,13 @@ ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_hwaddr" "ac_cv_member_struct_
#endif
"
-if test "x$ac_cv_member_struct_ifreq_ifr_hwaddr" = xyes; then :
+if test "x$ac_cv_member_struct_ifreq_ifr_hwaddr" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_IFREQ_IFR_HWADDR 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_IFREQ_IFR_HWADDR 1" >>confdefs.h
-$as_echo "#define ESOCK_USE_HWADDR /**/" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_HWADDR /**/" >>confdefs.h
fi
@@ -14140,14 +16003,13 @@ ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_ifindex" "ac_cv_member_struct
#endif
"
-if test "x$ac_cv_member_struct_ifreq_ifr_ifindex" = xyes; then :
+if test "x$ac_cv_member_struct_ifreq_ifr_ifindex" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_IFREQ_IFR_IFINDEX 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_IFREQ_IFR_IFINDEX 1" >>confdefs.h
-$as_echo "#define ESOCK_USE_IFINDEX /**/" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_IFINDEX /**/" >>confdefs.h
fi
@@ -14158,19 +16020,35 @@ ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_index" "ac_cv_member_struct_i
#endif
"
-if test "x$ac_cv_member_struct_ifreq_ifr_index" = xyes; then :
+if test "x$ac_cv_member_struct_ifreq_ifr_index" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_IFREQ_IFR_INDEX 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_IFREQ_IFR_INDEX 1" >>confdefs.h
-$as_echo "#define ESOCK_USE_INDEX /**/" >>confdefs.h
+printf "%s\n" "#define ESOCK_USE_INDEX /**/" >>confdefs.h
fi
+ac_fn_c_check_member "$LINENO" "struct sockaddr_dl" "sdl_len" "ac_cv_member_struct_sockaddr_dl_sdl_len" "#ifdef __WIN32__
+ #else
+ #include <net/if_dl.h>
+ #endif
+
+"
+if test "x$ac_cv_member_struct_sockaddr_dl_sdl_len" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_DL_SDL_LEN 1" >>confdefs.h
+
+
+printf "%s\n" "#define ESOCK_SDL_LEN /**/" >>confdefs.h
+
+fi
+
+
#--------------------------------------------------------------------
# Check for the existence of the -lsocket and -lnsl libraries.
# The order here is important, so that they end up in the right
@@ -14193,18 +16071,22 @@ tk_oldLibs=$LIBS
erl_checkBoth=0
SOCKET_LIBS=""
ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
-if test "x$ac_cv_func_connect" = xyes; then :
+if test "x$ac_cv_func_connect" = xyes
+then :
erl_checkSocket=0
-else
+else $as_nop
erl_checkSocket=1
fi
-if test "$erl_checkSocket" = 1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
-$as_echo_n "checking for main in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "$erl_checkSocket" = 1
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
+printf %s "checking for main in -lsocket... " >&6; }
+if test ${ac_cv_lib_socket_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -14212,51 +16094,60 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_socket_main=yes
-else
+else $as_nop
ac_cv_lib_socket_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
-$as_echo "$ac_cv_lib_socket_main" >&6; }
-if test "x$ac_cv_lib_socket_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
+printf "%s\n" "$ac_cv_lib_socket_main" >&6; }
+if test "x$ac_cv_lib_socket_main" = xyes
+then :
SOCKET_LIBS="-lsocket"
-else
+else $as_nop
erl_checkBoth=1
fi
+
fi
-if test "$erl_checkBoth" = 1; then
+if test "$erl_checkBoth" = 1
+then :
+
LIBS="$LIBS -lsocket -lnsl"
ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
-if test "x$ac_cv_func_accept" = xyes; then :
+if test "x$ac_cv_func_accept" = xyes
+then :
SOCKET_LIBS="-lsocket -lnsl"
fi
+
fi
LIBS="$tk_oldLibs $SOCKET_LIBS"
ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
-if test "x$ac_cv_func_gethostbyname" = xyes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
-$as_echo_n "checking for main in -lnsl... " >&6; }
-if ${ac_cv_lib_nsl_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "x$ac_cv_func_gethostbyname" = xyes
+then :
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
+printf %s "checking for main in -lnsl... " >&6; }
+if test ${ac_cv_lib_nsl_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lnsl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -14264,32 +16155,35 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_nsl_main=yes
-else
+else $as_nop
ac_cv_lib_nsl_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
-$as_echo "$ac_cv_lib_nsl_main" >&6; }
-if test "x$ac_cv_lib_nsl_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
+printf "%s\n" "$ac_cv_lib_nsl_main" >&6; }
+if test "x$ac_cv_lib_nsl_main" = xyes
+then :
SOCKET_LIBS="$SOCKET_LIBS -lnsl"
fi
fi
ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
-if test "x$ac_cv_func_gethostbyname_r" = xyes; then :
+if test "x$ac_cv_func_gethostbyname_r" = xyes
+then :
have_gethostbyname_r=yes
fi
@@ -14299,36 +16193,43 @@ LIBS="$tk_oldLibs $SOCKET_LIBS"
-if test "$have_gethostbyname_r" = yes; then
+
+if test "$have_gethostbyname_r" = yes
+then :
+
# OK, so we have gethostbyname_r() - but do we know how to call it...?
# (if not, HAVE_GETHOSTBYNAME_R will not be defined at all)
- case $host_os in
- solaris2*)
+ case $host_os in #(
+ solaris2*) :
-$as_echo "#define HAVE_GETHOSTBYNAME_R GHBN_R_SOLARIS" >>confdefs.h
- ;;
- aix*|os400*)
+printf "%s\n" "#define HAVE_GETHOSTBYNAME_R GHBN_R_SOLARIS" >>confdefs.h
+
+ ;; #(
+ aix*|os400*) :
+
# AIX version also needs "struct hostent_data" defn
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netdb.h>
int
-main ()
+main (void)
{
struct hostent_data hd;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-$as_echo "#define HAVE_GETHOSTBYNAME_R GHBN_R_AIX" >>confdefs.h
+printf "%s\n" "#define HAVE_GETHOSTBYNAME_R GHBN_R_AIX" >>confdefs.h
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ;;
- *)
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;; #(
+ *) :
+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -14339,19 +16240,21 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes$" >/dev/null 2>&1; then :
+ $EGREP "^yes$" >/dev/null 2>&1
+then :
-$as_echo "#define HAVE_GETHOSTBYNAME_R GHBN_R_GLIBC" >>confdefs.h
+printf "%s\n" "#define HAVE_GETHOSTBYNAME_R GHBN_R_GLIBC" >>confdefs.h
fi
-rm -f conftest*
+rm -rf conftest*
+
+ ;;
+esac
- ;;
- esac
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working posix_openpt implementation" >&5
-$as_echo_n "checking for working posix_openpt implementation... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working posix_openpt implementation" >&5
+printf %s "checking for working posix_openpt implementation... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -14360,7 +16263,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include <fcntl.h>
int
-main ()
+main (void)
{
int mfd = posix_openpt(O_RDWR);
@@ -14373,128 +16276,134 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
working_posix_openpt=yes
-else
+else $as_nop
working_posix_openpt=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test "X$working_posix_openpt" = "Xyes"; then
-$as_echo "#define HAVE_WORKING_POSIX_OPENPT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_WORKING_POSIX_OPENPT 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if netdb.h requires netinet/in.h to be previously included" >&5
-$as_echo_n "checking if netdb.h requires netinet/in.h to be previously included... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if netdb.h requires netinet/in.h to be previously included" >&5
+printf %s "checking if netdb.h requires netinet/in.h to be previously included... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netdb.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "sockaddr_in" >/dev/null 2>&1; then :
+ $EGREP "sockaddr_in" >/dev/null 2>&1
+then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netinet/in.h>
#include <netdb.h>
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
need_in_h=yes
-else
+else $as_nop
need_in_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+else $as_nop
need_in_h=no
fi
-rm -f conftest*
+rm -rf conftest*
if test $need_in_h = yes; then
-$as_echo "#define NETDB_H_NEEDS_IN_H 1" >>confdefs.h
+printf "%s\n" "#define NETDB_H_NEEDS_IN_H 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
-$as_echo_n "checking for socklen_t... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
+printf %s "checking for socklen_t... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/socket.h>
int
-main ()
+main (void)
{
socklen_t test;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
have_socklen_t=yes
-else
+else $as_nop
have_socklen_t=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext,
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext,
if test $have_socklen_t = yes; then
-$as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SOCKLEN_T 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for h_errno declaration in netdb.h" >&5
-$as_echo_n "checking for h_errno declaration in netdb.h... " >&6; }
-if ${ac_cv_decl_h_errno+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for h_errno declaration in netdb.h" >&5
+printf %s "checking for h_errno declaration in netdb.h... " >&6; }
+if test ${ac_cv_decl_h_errno+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netdb.h>
int
-main ()
+main (void)
{
int err = h_errno;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_decl_h_errno=yes
-else
+else $as_nop
ac_cv_decl_h_errno=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_h_errno" >&5
-$as_echo "$ac_cv_decl_h_errno" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_h_errno" >&5
+printf "%s\n" "$ac_cv_decl_h_errno" >&6; }
if test $ac_cv_decl_h_errno = yes; then
-$as_echo "#define H_ERRNO_DECLARED 1" >>confdefs.h
+printf "%s\n" "#define H_ERRNO_DECLARED 1" >>confdefs.h
fi
@@ -14505,19 +16414,20 @@ CPPFLAGS="$CPPFLAGS $EMU_THR_DEFS"
ac_header_dirent=no
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
- as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
-$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; }
-if eval \${$as_ac_Header+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ as_ac_Header=`printf "%s\n" "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+printf %s "checking for $ac_hdr that defines DIR... " >&6; }
+if eval test \${$as_ac_Header+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <$ac_hdr>
int
-main ()
+main (void)
{
if ((DIR *) 0)
return 0;
@@ -14525,19 +16435,21 @@ return 0;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$as_ac_Header=yes"
-else
+else $as_nop
eval "$as_ac_Header=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$as_ac_Header
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+#define `printf "%s\n" "HAVE_$ac_hdr" | $as_tr_cpp` 1
_ACEOF
ac_header_dirent=$ac_hdr; break
@@ -14546,11 +16458,12 @@ fi
done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
-$as_echo_n "checking for library containing opendir... " >&6; }
-if ${ac_cv_search_opendir+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+printf %s "checking for library containing opendir... " >&6; }
+if test ${ac_cv_search_opendir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -14558,56 +16471,59 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char opendir ();
int
-main ()
+main (void)
{
return opendir ();
;
return 0;
}
_ACEOF
-for ac_lib in '' dir; do
+for ac_lib in '' dir
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_opendir=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_opendir+:} false; then :
+ if test ${ac_cv_search_opendir+y}
+then :
break
fi
done
-if ${ac_cv_search_opendir+:} false; then :
+if test ${ac_cv_search_opendir+y}
+then :
-else
+else $as_nop
ac_cv_search_opendir=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
-$as_echo "$ac_cv_search_opendir" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+printf "%s\n" "$ac_cv_search_opendir" >&6; }
ac_res=$ac_cv_search_opendir
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
-$as_echo_n "checking for library containing opendir... " >&6; }
-if ${ac_cv_search_opendir+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+printf %s "checking for library containing opendir... " >&6; }
+if test ${ac_cv_search_opendir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -14615,259 +16531,270 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char opendir ();
int
-main ()
+main (void)
{
return opendir ();
;
return 0;
}
_ACEOF
-for ac_lib in '' x; do
+for ac_lib in '' x
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_opendir=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_opendir+:} false; then :
+ if test ${ac_cv_search_opendir+y}
+then :
break
fi
done
-if ${ac_cv_search_opendir+:} false; then :
+if test ${ac_cv_search_opendir+y}
+then :
-else
+else $as_nop
ac_cv_search_opendir=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
-$as_echo "$ac_cv_search_opendir" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+printf "%s\n" "$ac_cv_search_opendir" >&6; }
ac_res=$ac_cv_search_opendir
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+printf %s "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+if test ${ac_cv_header_sys_wait_h+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
int
-main ()
+main (void)
{
-
+ int s;
+ wait (&s);
+ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_header_sys_wait_h=yes
+else $as_nop
+ ac_cv_header_sys_wait_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+printf "%s\n" "$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
+printf "%s\n" "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
+fi
+
+
+
+
+ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcntl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h
-else
- ac_cv_header_stdc=no
fi
-rm -f conftest*
+ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default"
+if test "x$ac_cv_header_limits_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default"
+if test "x$ac_cv_header_unistd_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
+fi
+ac_fn_c_check_header_compile "$LINENO" "syslog.h" "ac_cv_header_syslog_h" "$ac_includes_default"
+if test "x$ac_cv_header_syslog_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYSLOG_H 1" >>confdefs.h
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+fi
+ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
+if test "x$ac_cv_header_dlfcn_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
-else
- ac_cv_header_stdc=no
fi
-rm -f conftest*
+ac_fn_c_check_header_compile "$LINENO" "ieeefp.h" "ac_cv_header_ieeefp_h" "$ac_includes_default"
+if test "x$ac_cv_header_ieeefp_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_IEEEFP_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_types_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/stropts.h" "ac_cv_header_sys_stropts_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_stropts_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_STROPTS_H 1" >>confdefs.h
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sysctl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SYSCTL_H 1" >>confdefs.h
-else
- ac_cv_header_stdc=no
fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_ioctl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_IOCTL_H 1" >>confdefs.h
+
fi
+ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_time_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "sys/uio.h" "ac_cv_header_sys_uio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_uio_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_UIO_H 1" >>confdefs.h
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
+ac_fn_c_check_header_compile "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_MMAN_H 1" >>confdefs.h
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_socket_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "sys/sockio.h" "ac_cv_header_sys_sockio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sockio_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SOCKIO_H 1" >>confdefs.h
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
-$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
-if ${ac_cv_header_sys_wait_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/wait.h>
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/socketio.h" "ac_cv_header_sys_socketio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_socketio_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SOCKETIO_H 1" >>confdefs.h
-int
-main ()
-{
- int s;
- wait (&s);
- s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_sys_wait_h=yes
-else
- ac_cv_header_sys_wait_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_errno_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NET_ERRNO_H 1" >>confdefs.h
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
-$as_echo "$ac_cv_header_sys_wait_h" >&6; }
-if test $ac_cv_header_sys_wait_h = yes; then
+ac_fn_c_check_header_compile "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_malloc_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_MALLOC_H 1" >>confdefs.h
-$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+fi
+ac_fn_c_check_header_compile "$LINENO" "arpa/nameser.h" "ac_cv_header_arpa_nameser_h" "$ac_includes_default"
+if test "x$ac_cv_header_arpa_nameser_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_ARPA_NAMESER_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "libdlpi.h" "ac_cv_header_libdlpi_h" "$ac_includes_default"
+if test "x$ac_cv_header_libdlpi_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBDLPI_H 1" >>confdefs.h
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
-$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
-if ${ac_cv_header_time+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
+fi
+ac_fn_c_check_header_compile "$LINENO" "pty.h" "ac_cv_header_pty_h" "$ac_includes_default"
+if test "x$ac_cv_header_pty_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_PTY_H 1" >>confdefs.h
-int
-main ()
-{
-if ((struct tm *) 0)
-return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_time=yes
-else
- ac_cv_header_time=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "util.h" "ac_cv_header_util_h" "$ac_includes_default"
+if test "x$ac_cv_header_util_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_UTIL_H 1" >>confdefs.h
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
-$as_echo "$ac_cv_header_time" >&6; }
-if test $ac_cv_header_time = yes; then
+ac_fn_c_check_header_compile "$LINENO" "libutil.h" "ac_cv_header_libutil_h" "$ac_includes_default"
+if test "x$ac_cv_header_libutil_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBUTIL_H 1" >>confdefs.h
-$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+fi
+ac_fn_c_check_header_compile "$LINENO" "utmp.h" "ac_cv_header_utmp_h" "$ac_includes_default"
+if test "x$ac_cv_header_utmp_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_UTMP_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_langinfo_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LANGINFO_H 1" >>confdefs.h
+fi
+ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default"
+if test "x$ac_cv_header_poll_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h
-for ac_header in 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/mman.h \
- sys/socket.h sys/sockio.h sys/socketio.h \
- net/errno.h malloc.h arpa/nameser.h libdlpi.h \
- pty.h util.h libutil.h utmp.h langinfo.h poll.h sdkddkver.h \
- elf.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+fi
+ac_fn_c_check_header_compile "$LINENO" "sdkddkver.h" "ac_cv_header_sdkddkver_h" "$ac_includes_default"
+if test "x$ac_cv_header_sdkddkver_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SDKDDKVER_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "elf.h" "ac_cv_header_elf_h" "$ac_includes_default"
+if test "x$ac_cv_header_elf_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_ELF_H 1" >>confdefs.h
-done
+fi
ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_hwaddr" "ac_cv_member_struct_ifreq_ifr_hwaddr" "#ifdef __WIN32__
@@ -14876,11 +16803,10 @@ ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_hwaddr" "ac_cv_member_struct_
#endif
"
-if test "x$ac_cv_member_struct_ifreq_ifr_hwaddr" = xyes; then :
+if test "x$ac_cv_member_struct_ifreq_ifr_hwaddr" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_IFREQ_IFR_HWADDR 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_IFREQ_IFR_HWADDR 1" >>confdefs.h
fi
@@ -14892,25 +16818,42 @@ ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_enaddr" "ac_cv_member_struct_
#endif
"
-if test "x$ac_cv_member_struct_ifreq_ifr_enaddr" = xyes; then :
+if test "x$ac_cv_member_struct_ifreq_ifr_enaddr" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_IFREQ_IFR_ENADDR 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_IFREQ_IFR_ENADDR 1" >>confdefs.h
+
+
+fi
+
+
+
+ac_fn_c_check_type "$LINENO" "struct ip_mreqn" "ac_cv_type_struct_ip_mreqn" "
+ #include <netinet/in.h>
+
+"
+if test "x$ac_cv_type_struct_ip_mreqn" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_IP_MREQN 1" >>confdefs.h
fi
-if test x"$enable_systemd" != x"no"; then
+
+if test x"$enable_systemd" != x"no"
+then :
+
systemd_daemon_save_LIBS=$LIBS
LIBS=
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sd_listen_fds" >&5
-$as_echo_n "checking for library containing sd_listen_fds... " >&6; }
-if ${ac_cv_search_sd_listen_fds+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing sd_listen_fds" >&5
+printf %s "checking for library containing sd_listen_fds... " >&6; }
+if test ${ac_cv_search_sd_listen_fds+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -14918,57 +16861,60 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sd_listen_fds ();
int
-main ()
+main (void)
{
return sd_listen_fds ();
;
return 0;
}
_ACEOF
-for ac_lib in '' systemd systemd-daemon; do
+for ac_lib in '' systemd systemd-daemon
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $systemd_daemon_save_LIBS $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_sd_listen_fds=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_sd_listen_fds+:} false; then :
+ if test ${ac_cv_search_sd_listen_fds+y}
+then :
break
fi
done
-if ${ac_cv_search_sd_listen_fds+:} false; then :
+if test ${ac_cv_search_sd_listen_fds+y}
+then :
-else
+else $as_nop
ac_cv_search_sd_listen_fds=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sd_listen_fds" >&5
-$as_echo "$ac_cv_search_sd_listen_fds" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sd_listen_fds" >&5
+printf "%s\n" "$ac_cv_search_sd_listen_fds" >&6; }
ac_res=$ac_cv_search_sd_listen_fds
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
have_sd_listen_fds=yes
-else
+else $as_nop
have_sd_listen_fds=no
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sd_notify" >&5
-$as_echo_n "checking for library containing sd_notify... " >&6; }
-if ${ac_cv_search_sd_notify+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing sd_notify" >&5
+printf %s "checking for library containing sd_notify... " >&6; }
+if test ${ac_cv_search_sd_notify+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -14976,90 +16922,92 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sd_notify ();
int
-main ()
+main (void)
{
return sd_notify ();
;
return 0;
}
_ACEOF
-for ac_lib in '' systemd systemd-daemon; do
+for ac_lib in '' systemd systemd-daemon
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $systemd_daemon_save_LIBS $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_sd_notify=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_sd_notify+:} false; then :
+ if test ${ac_cv_search_sd_notify+y}
+then :
break
fi
done
-if ${ac_cv_search_sd_notify+:} false; then :
+if test ${ac_cv_search_sd_notify+y}
+then :
-else
+else $as_nop
ac_cv_search_sd_notify=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sd_notify" >&5
-$as_echo "$ac_cv_search_sd_notify" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sd_notify" >&5
+printf "%s\n" "$ac_cv_search_sd_notify" >&6; }
ac_res=$ac_cv_search_sd_notify
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
have_sd_notify=yes
-else
+else $as_nop
have_sd_notify=no
fi
-for ac_header in systemd/sd-daemon.h
+ for ac_header in systemd/sd-daemon.h
do :
- ac_fn_c_check_header_mongrel "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
-if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYSTEMD_SD_DAEMON_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
+if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYSTEMD_SD_DAEMON_H 1" >>confdefs.h
have_systemd_sd_daemon_h=yes
-else
+else $as_nop
have_systemd_sd_daemon_h=no
fi
done
-
if test x"$have_sd_listen_fds" = x"yes" && \
test x"$have_sd_notify" = x"yes" && \
test x"$have_systemd_sd_daemon_h" = x"yes"; then
-$as_echo "#define HAVE_SYSTEMD_DAEMON 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SYSTEMD_DAEMON 1" >>confdefs.h
SYSTEMD_DAEMON_LIBS=$LIBS
elif test x"$enable_systemd" = x"yes"; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "--enable-systemd was given, but test for systemd failed
See \`config.log' for more details" "$LINENO" 5; }
fi
LIBS=$systemd_daemon_save_LIBS
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_open in -ldlpi" >&5
-$as_echo_n "checking for dlpi_open in -ldlpi... " >&6; }
-if ${ac_cv_lib_dlpi_dlpi_open+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlpi_open in -ldlpi" >&5
+printf %s "checking for dlpi_open in -ldlpi... " >&6; }
+if test ${ac_cv_lib_dlpi_dlpi_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldlpi $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -15068,47 +17016,46 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char dlpi_open ();
int
-main ()
+main (void)
{
return dlpi_open ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_dlpi_dlpi_open=yes
-else
+else $as_nop
ac_cv_lib_dlpi_dlpi_open=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_open" >&5
-$as_echo "$ac_cv_lib_dlpi_dlpi_open" >&6; }
-if test "x$ac_cv_lib_dlpi_dlpi_open" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDLPI 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_open" >&5
+printf "%s\n" "$ac_cv_lib_dlpi_dlpi_open" >&6; }
+if test "x$ac_cv_lib_dlpi_dlpi_open" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBDLPI 1" >>confdefs.h
LIBS="-ldlpi $LIBS"
fi
-if test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"; then
+if test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"
+then :
+
unset -v ac_cv_lib_dlpi_dlpi_open
save_ldflags="$LDFLAGS"
- try_dlpi_lib=/lib
+ try_dlpi_lib=$erl_xcomp_sysroot/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
+ if test -d $erl_xcomp_sysroot/lib64; then
+ try_dlpi_lib= $erl_xcomp_sysroot/lib64
+ elif test -d $erl_xcomp_sysroot/lib/64; then
+ try_dlpi_lib= $erl_xcomp_sysroot/lib/64
fi
fi
if test ! -f "$try_dlpi_lib/libdlpi.so" && \
@@ -15122,13 +17069,14 @@ if test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"; then
fi
LDFLAGS="-L$try_dlpi_lib -R$try_dlpi_lib $LDFLAGS"
unset -v try_dlpi_lib
- { $as_echo "$as_me:${as_lineno-$LINENO}: Extending the search to include /lib" >&5
-$as_echo "$as_me: Extending the search to include /lib" >&6;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_open in -ldlpi" >&5
-$as_echo_n "checking for dlpi_open in -ldlpi... " >&6; }
-if ${ac_cv_lib_dlpi_dlpi_open+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Extending the search to include $erl_xcomp_sysroot/lib" >&5
+printf "%s\n" "$as_me: Extending the search to include $erl_xcomp_sysroot/lib" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlpi_open in -ldlpi" >&5
+printf %s "checking for dlpi_open in -ldlpi... " >&6; }
+if test ${ac_cv_lib_dlpi_dlpi_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldlpi $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -15137,33 +17085,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char dlpi_open ();
int
-main ()
+main (void)
{
return dlpi_open ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_dlpi_dlpi_open=yes
-else
+else $as_nop
ac_cv_lib_dlpi_dlpi_open=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_open" >&5
-$as_echo "$ac_cv_lib_dlpi_dlpi_open" >&6; }
-if test "x$ac_cv_lib_dlpi_dlpi_open" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDLPI 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_open" >&5
+printf "%s\n" "$ac_cv_lib_dlpi_dlpi_open" >&6; }
+if test "x$ac_cv_lib_dlpi_dlpi_open" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBDLPI 1" >>confdefs.h
LIBS="-ldlpi $LIBS"
@@ -15173,122 +17118,189 @@ fi
LDFLAGS="$save_ldflags"
fi
unset -v save_ldflags
+
fi
-ac_fn_c_check_header_mongrel "$LINENO" "sys/resource.h" "ac_cv_header_sys_resource_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_resource_h" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
+printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
+if test ${ac_cv_c_undeclared_builtin_options+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_CFLAGS=$CFLAGS
+ ac_cv_c_undeclared_builtin_options='cannot detect'
+ for ac_arg in '' -fno-builtin; do
+ CFLAGS="$ac_save_CFLAGS $ac_arg"
+ # This test program should *not* compile successfully.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+(void) strchr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ # This test program should compile successfully.
+ # No library function is consistently available on
+ # freestanding implementations, so test against a dummy
+ # declaration. Include always-available headers on the
+ # off chance that they somehow elicit warnings.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);
-$as_echo "#define HAVE_SYS_RESOURCE_H 1" >>confdefs.h
+int
+main (void)
+{
+(void) ac_decl (0, (char *) 0);
+ (void) ac_decl;
- ac_fn_c_check_decl "$LINENO" "getrlimit" "ac_cv_have_decl_getrlimit" "#include <sys/resource.h>
-"
-if test "x$ac_cv_have_decl_getrlimit" = xyes; then :
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ if test x"$ac_arg" = x
+then :
+ ac_cv_c_undeclared_builtin_options='none needed'
+else $as_nop
+ ac_cv_c_undeclared_builtin_options=$ac_arg
+fi
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+ CFLAGS=$ac_save_CFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
+printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
+ case $ac_cv_c_undeclared_builtin_options in #(
+ 'cannot detect') :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot make $CC report undeclared builtins
+See \`config.log' for more details" "$LINENO" 5; } ;; #(
+ 'none needed') :
+ ac_c_undeclared_builtin_options='' ;; #(
+ *) :
+ ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
+esac
+
+ac_fn_c_check_header_compile "$LINENO" "sys/resource.h" "ac_cv_header_sys_resource_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_resource_h" = xyes
+then :
+
+printf "%s\n" "#define HAVE_SYS_RESOURCE_H 1" >>confdefs.h
+
+ ac_fn_check_decl "$LINENO" "getrlimit" "ac_cv_have_decl_getrlimit" "#include <sys/resource.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_getrlimit" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_GETRLIMIT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "setrlimit" "ac_cv_have_decl_setrlimit" "#include <sys/resource.h>
-"
-if test "x$ac_cv_have_decl_setrlimit" = xyes; then :
+printf "%s\n" "#define HAVE_DECL_GETRLIMIT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "setrlimit" "ac_cv_have_decl_setrlimit" "#include <sys/resource.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_setrlimit" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SETRLIMIT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "RLIMIT_STACK" "ac_cv_have_decl_RLIMIT_STACK" "#include <sys/resource.h>
-"
-if test "x$ac_cv_have_decl_RLIMIT_STACK" = xyes; then :
+printf "%s\n" "#define HAVE_DECL_SETRLIMIT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "RLIMIT_STACK" "ac_cv_have_decl_RLIMIT_STACK" "#include <sys/resource.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_RLIMIT_STACK" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_RLIMIT_STACK $ac_have_decl
-_ACEOF
+printf "%s\n" "#define HAVE_DECL_RLIMIT_STACK $ac_have_decl" >>confdefs.h
fi
-
-for ac_func in getrusage
-do :
- ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage"
-if test "x$ac_cv_func_getrusage" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETRUSAGE 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage"
+if test "x$ac_cv_func_getrusage" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETRUSAGE 1" >>confdefs.h
fi
-done
have_kernel_poll=no
-ac_fn_c_check_header_mongrel "$LINENO" "sys/event.h" "ac_cv_header_sys_event_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_event_h" = xyes; then :
+ac_fn_c_check_header_compile "$LINENO" "sys/event.h" "ac_cv_header_sys_event_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_event_h" = xyes
+then :
have_kernel_poll=kqueue
fi
-
-ac_fn_c_check_header_mongrel "$LINENO" "sys/epoll.h" "ac_cv_header_sys_epoll_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_epoll_h" = xyes; then :
+ac_fn_c_check_header_compile "$LINENO" "sys/epoll.h" "ac_cv_header_sys_epoll_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_epoll_h" = xyes
+then :
have_kernel_poll=epoll
fi
-
-ac_fn_c_check_header_mongrel "$LINENO" "sys/devpoll.h" "ac_cv_header_sys_devpoll_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_devpoll_h" = xyes; then :
+ac_fn_c_check_header_compile "$LINENO" "sys/devpoll.h" "ac_cv_header_sys_devpoll_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_devpoll_h" = xyes
+then :
have_kernel_poll=/dev/poll
fi
-
-for ac_header in sys/timerfd.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "sys/timerfd.h" "ac_cv_header_sys_timerfd_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_timerfd_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_TIMERFD_H 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "sys/timerfd.h" "ac_cv_header_sys_timerfd_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_timerfd_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TIMERFD_H 1" >>confdefs.h
fi
-done
-
-for ac_header in netpacket/packet.h
+ for ac_header in netpacket/packet.h
do :
- ac_fn_c_check_header_mongrel "$LINENO" "netpacket/packet.h" "ac_cv_header_netpacket_packet_h" "$ac_includes_default"
-if test "x$ac_cv_header_netpacket_packet_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_NETPACKET_PACKET_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "netpacket/packet.h" "ac_cv_header_netpacket_packet_h" "$ac_includes_default"
+if test "x$ac_cv_header_netpacket_packet_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NETPACKET_PACKET_H 1" >>confdefs.h
have_netpacket_packet_h=yes
-else
+else $as_nop
have_netpacket_packet_h=no
fi
done
+if test "x$enable_sctp" != "xno"
+then :
-if test "x$enable_sctp" != "xno" ; then
ac_fn_c_check_header_compile "$LINENO" "netinet/sctp.h" "ac_cv_header_netinet_sctp_h" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
"
-if test "x$ac_cv_header_netinet_sctp_h" = xyes; then :
+if test "x$ac_cv_header_netinet_sctp_h" = xyes
+then :
LIBSCTP=libsctp.so.1
-$as_echo "#define HAVE_SCTP_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SCTP_H 1" >>confdefs.h
fi
@@ -15304,13 +17316,17 @@ case "x$enable_sctp" in
fi;;
esac
-if test x"$ac_cv_header_netinet_sctp_h" = x"yes"; then
- if test "x$enable_sctp" = "xlib"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sctp_bindx in -lsctp" >&5
-$as_echo_n "checking for sctp_bindx in -lsctp... " >&6; }
-if ${ac_cv_lib_sctp_sctp_bindx+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test x"$ac_cv_header_netinet_sctp_h" = x"yes"
+then :
+
+ if test "x$enable_sctp" = "xlib"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sctp_bindx in -lsctp" >&5
+printf %s "checking for sctp_bindx in -lsctp... " >&6; }
+if test ${ac_cv_lib_sctp_sctp_bindx+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsctp $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -15319,50 +17335,78 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sctp_bindx ();
int
-main ()
+main (void)
{
return sctp_bindx ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_sctp_sctp_bindx=yes
-else
+else $as_nop
ac_cv_lib_sctp_sctp_bindx=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sctp_sctp_bindx" >&5
-$as_echo "$ac_cv_lib_sctp_sctp_bindx" >&6; }
-if test "x$ac_cv_lib_sctp_sctp_bindx" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSCTP 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sctp_sctp_bindx" >&5
+printf "%s\n" "$ac_cv_lib_sctp_sctp_bindx" >&6; }
+if test "x$ac_cv_lib_sctp_sctp_bindx" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBSCTP 1" >>confdefs.h
LIBS="-lsctp $LIBS"
fi
fi
- for ac_func in sctp_bindx sctp_peeloff sctp_getladdrs sctp_freeladdrs sctp_getpaddrs sctp_freepaddrs
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "sctp_bindx" "ac_cv_func_sctp_bindx"
+if test "x$ac_cv_func_sctp_bindx" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_BINDX 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sctp_peeloff" "ac_cv_func_sctp_peeloff"
+if test "x$ac_cv_func_sctp_peeloff" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_PEELOFF 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sctp_getladdrs" "ac_cv_func_sctp_getladdrs"
+if test "x$ac_cv_func_sctp_getladdrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_GETLADDRS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sctp_freeladdrs" "ac_cv_func_sctp_freeladdrs"
+if test "x$ac_cv_func_sctp_freeladdrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_FREELADDRS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sctp_getpaddrs" "ac_cv_func_sctp_getpaddrs"
+if test "x$ac_cv_func_sctp_getpaddrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_GETPADDRS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sctp_freepaddrs" "ac_cv_func_sctp_freepaddrs"
+if test "x$ac_cv_func_sctp_freepaddrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_FREEPADDRS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sctp_connectx" "ac_cv_func_sctp_connectx"
+if test "x$ac_cv_func_sctp_connectx" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCTP_CONNECTX 1" >>confdefs.h
fi
-done
ac_fn_c_check_member "$LINENO" "struct sctp_accoc_value" "assoc_id" "ac_cv_member_struct_sctp_accoc_value_assoc_id" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -15370,450 +17414,391 @@ done
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_accoc_value_assoc_id" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_accoc_value_assoc_id" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_ACCOC_VALUE_ASSOC_ID 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_ACCOC_VALUE_ASSOC_ID 1" >>confdefs.h
fi
- ac_fn_c_check_decl "$LINENO" "SCTP_UNORDERED" "ac_cv_have_decl_SCTP_UNORDERED" "#if HAVE_SYS_SOCKET_H
+ ac_fn_check_decl "$LINENO" "SCTP_UNORDERED" "ac_cv_have_decl_SCTP_UNORDERED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_UNORDERED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_UNORDERED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_UNORDERED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_ADDR_OVER" "ac_cv_have_decl_SCTP_ADDR_OVER" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_UNORDERED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_ADDR_OVER" "ac_cv_have_decl_SCTP_ADDR_OVER" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_ADDR_OVER" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_ADDR_OVER" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_ADDR_OVER $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_ABORT" "ac_cv_have_decl_SCTP_ABORT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_ADDR_OVER $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_ABORT" "ac_cv_have_decl_SCTP_ABORT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_ABORT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_ABORT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_ABORT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_EOF" "ac_cv_have_decl_SCTP_EOF" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_ABORT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_EOF" "ac_cv_have_decl_SCTP_EOF" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_EOF" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_EOF" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_EOF $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_SENDALL" "ac_cv_have_decl_SCTP_SENDALL" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_EOF $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_SENDALL" "ac_cv_have_decl_SCTP_SENDALL" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_SENDALL" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_SENDALL" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_SENDALL $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_ADDR_CONFIRMED" "ac_cv_have_decl_SCTP_ADDR_CONFIRMED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_SENDALL $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_ADDR_CONFIRMED" "ac_cv_have_decl_SCTP_ADDR_CONFIRMED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_ADDR_CONFIRMED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_ADDR_CONFIRMED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_ADDR_CONFIRMED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_DELAYED_ACK_TIME" "ac_cv_have_decl_SCTP_DELAYED_ACK_TIME" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_ADDR_CONFIRMED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_DELAYED_ACK_TIME" "ac_cv_have_decl_SCTP_DELAYED_ACK_TIME" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_DELAYED_ACK_TIME" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_DELAYED_ACK_TIME" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_DELAYED_ACK_TIME $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_EMPTY" "ac_cv_have_decl_SCTP_EMPTY" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_DELAYED_ACK_TIME $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_EMPTY" "ac_cv_have_decl_SCTP_EMPTY" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_EMPTY" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_EMPTY" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_EMPTY $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_UNCONFIRMED" "ac_cv_have_decl_SCTP_UNCONFIRMED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_EMPTY $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_UNCONFIRMED" "ac_cv_have_decl_SCTP_UNCONFIRMED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_UNCONFIRMED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_UNCONFIRMED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_UNCONFIRMED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_CLOSED" "ac_cv_have_decl_SCTP_CLOSED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_UNCONFIRMED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_CLOSED" "ac_cv_have_decl_SCTP_CLOSED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_CLOSED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_CLOSED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_CLOSED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_IDLE" "ac_cv_have_decl_SCTPS_IDLE" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_CLOSED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_IDLE" "ac_cv_have_decl_SCTPS_IDLE" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_IDLE" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_IDLE" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_IDLE $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_BOUND" "ac_cv_have_decl_SCTP_BOUND" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_IDLE $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_BOUND" "ac_cv_have_decl_SCTP_BOUND" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_BOUND" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_BOUND" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_BOUND $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_BOUND" "ac_cv_have_decl_SCTPS_BOUND" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_BOUND $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_BOUND" "ac_cv_have_decl_SCTPS_BOUND" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_BOUND" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_BOUND" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_BOUND $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_LISTEN" "ac_cv_have_decl_SCTP_LISTEN" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_BOUND $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_LISTEN" "ac_cv_have_decl_SCTP_LISTEN" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_LISTEN" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_LISTEN" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_LISTEN $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_LISTEN" "ac_cv_have_decl_SCTPS_LISTEN" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_LISTEN $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_LISTEN" "ac_cv_have_decl_SCTPS_LISTEN" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_LISTEN" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_LISTEN" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_LISTEN $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_COOKIE_WAIT" "ac_cv_have_decl_SCTP_COOKIE_WAIT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_LISTEN $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_COOKIE_WAIT" "ac_cv_have_decl_SCTP_COOKIE_WAIT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_COOKIE_WAIT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_COOKIE_WAIT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_COOKIE_WAIT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_COOKIE_WAIT" "ac_cv_have_decl_SCTPS_COOKIE_WAIT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_COOKIE_WAIT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_COOKIE_WAIT" "ac_cv_have_decl_SCTPS_COOKIE_WAIT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_COOKIE_WAIT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_COOKIE_WAIT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_COOKIE_WAIT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_COOKIE_ECHOED" "ac_cv_have_decl_SCTP_COOKIE_ECHOED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_COOKIE_WAIT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_COOKIE_ECHOED" "ac_cv_have_decl_SCTP_COOKIE_ECHOED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_COOKIE_ECHOED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_COOKIE_ECHOED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_COOKIE_ECHOED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_COOKIE_ECHOED" "ac_cv_have_decl_SCTPS_COOKIE_ECHOED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_COOKIE_ECHOED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_COOKIE_ECHOED" "ac_cv_have_decl_SCTPS_COOKIE_ECHOED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_COOKIE_ECHOED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_COOKIE_ECHOED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_COOKIE_ECHOED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_ESTABLISHED" "ac_cv_have_decl_SCTP_ESTABLISHED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_COOKIE_ECHOED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_ESTABLISHED" "ac_cv_have_decl_SCTP_ESTABLISHED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_ESTABLISHED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_ESTABLISHED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_ESTABLISHED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_ESTABLISHED" "ac_cv_have_decl_SCTPS_ESTABLISHED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_ESTABLISHED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_ESTABLISHED" "ac_cv_have_decl_SCTPS_ESTABLISHED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_ESTABLISHED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_ESTABLISHED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_ESTABLISHED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_SHUTDOWN_PENDING" "ac_cv_have_decl_SCTP_SHUTDOWN_PENDING" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_ESTABLISHED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_SHUTDOWN_PENDING" "ac_cv_have_decl_SCTP_SHUTDOWN_PENDING" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_PENDING" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_PENDING" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_SHUTDOWN_PENDING $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_SHUTDOWN_PENDING" "ac_cv_have_decl_SCTPS_SHUTDOWN_PENDING" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_SHUTDOWN_PENDING $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_SHUTDOWN_PENDING" "ac_cv_have_decl_SCTPS_SHUTDOWN_PENDING" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_PENDING" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_PENDING" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_SHUTDOWN_PENDING $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_SHUTDOWN_SENT" "ac_cv_have_decl_SCTP_SHUTDOWN_SENT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_SHUTDOWN_PENDING $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_SHUTDOWN_SENT" "ac_cv_have_decl_SCTP_SHUTDOWN_SENT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_SENT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_SENT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_SHUTDOWN_SENT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_SHUTDOWN_SENT" "ac_cv_have_decl_SCTPS_SHUTDOWN_SENT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_SHUTDOWN_SENT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_SHUTDOWN_SENT" "ac_cv_have_decl_SCTPS_SHUTDOWN_SENT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_SENT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_SENT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_SHUTDOWN_SENT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_SHUTDOWN_RECEIVED" "ac_cv_have_decl_SCTP_SHUTDOWN_RECEIVED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_SHUTDOWN_SENT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_SHUTDOWN_RECEIVED" "ac_cv_have_decl_SCTP_SHUTDOWN_RECEIVED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_RECEIVED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_RECEIVED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_SHUTDOWN_RECEIVED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_SHUTDOWN_RECEIVED" "ac_cv_have_decl_SCTPS_SHUTDOWN_RECEIVED" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_SHUTDOWN_RECEIVED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_SHUTDOWN_RECEIVED" "ac_cv_have_decl_SCTPS_SHUTDOWN_RECEIVED" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_RECEIVED" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_RECEIVED" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_SHUTDOWN_RECEIVED $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTP_SHUTDOWN_ACK_SENT" "ac_cv_have_decl_SCTP_SHUTDOWN_ACK_SENT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTPS_SHUTDOWN_RECEIVED $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTP_SHUTDOWN_ACK_SENT" "ac_cv_have_decl_SCTP_SHUTDOWN_ACK_SENT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_ACK_SENT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTP_SHUTDOWN_ACK_SENT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "SCTPS_SHUTDOWN_ACK_SENT" "ac_cv_have_decl_SCTPS_SHUTDOWN_ACK_SENT" "#if HAVE_SYS_SOCKET_H
+printf "%s\n" "#define HAVE_DECL_SCTP_SHUTDOWN_ACK_SENT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SCTPS_SHUTDOWN_ACK_SENT" "ac_cv_have_decl_SCTPS_SHUTDOWN_ACK_SENT" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/sctp.h>
-"
-if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_ACK_SENT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SCTPS_SHUTDOWN_ACK_SENT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SCTPS_SHUTDOWN_ACK_SENT $ac_have_decl
-_ACEOF
+printf "%s\n" "#define HAVE_DECL_SCTPS_SHUTDOWN_ACK_SENT $ac_have_decl" >>confdefs.h
ac_fn_c_check_member "$LINENO" "struct sctp_paddrparams" "spp_pathmtu" "ac_cv_member_struct_sctp_paddrparams_spp_pathmtu" "#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -15821,11 +17806,10 @@ _ACEOF
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_paddrparams_spp_pathmtu" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_paddrparams_spp_pathmtu" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_PATHMTU 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_PATHMTU 1" >>confdefs.h
fi
@@ -15835,11 +17819,10 @@ ac_fn_c_check_member "$LINENO" "struct sctp_paddrparams" "spp_sackdelay" "ac_cv_
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_paddrparams_spp_sackdelay" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_paddrparams_spp_sackdelay" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_SACKDELAY 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_SACKDELAY 1" >>confdefs.h
fi
@@ -15849,11 +17832,10 @@ ac_fn_c_check_member "$LINENO" "struct sctp_paddrparams" "spp_flags" "ac_cv_memb
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_paddrparams_spp_flags" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_paddrparams_spp_flags" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_FLAGS 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_FLAGS 1" >>confdefs.h
fi
@@ -15863,11 +17845,10 @@ ac_fn_c_check_member "$LINENO" "struct sctp_remote_error" "sre_data" "ac_cv_memb
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_remote_error_sre_data" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_remote_error_sre_data" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_REMOTE_ERROR_SRE_DATA 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_REMOTE_ERROR_SRE_DATA 1" >>confdefs.h
fi
@@ -15877,11 +17858,10 @@ ac_fn_c_check_member "$LINENO" "struct sctp_send_failed" "ssf_data" "ac_cv_membe
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_send_failed_ssf_data" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_send_failed_ssf_data" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_SEND_FAILED_SSF_DATA 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_SEND_FAILED_SSF_DATA 1" >>confdefs.h
fi
@@ -15891,11 +17871,10 @@ ac_fn_c_check_member "$LINENO" "struct sctp_event_subscribe" "sctp_authenticatio
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_event_subscribe_sctp_authentication_event" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_event_subscribe_sctp_authentication_event" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_AUTHENTICATION_EVENT 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_AUTHENTICATION_EVENT 1" >>confdefs.h
fi
@@ -15905,46 +17884,39 @@ ac_fn_c_check_member "$LINENO" "struct sctp_event_subscribe" "sctp_sender_dry_ev
#include <netinet/sctp.h>
"
-if test "x$ac_cv_member_struct_sctp_event_subscribe_sctp_sender_dry_event" = xyes; then :
+if test "x$ac_cv_member_struct_sctp_event_subscribe_sctp_sender_dry_event" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SENDER_DRY_EVENT 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SENDER_DRY_EVENT 1" >>confdefs.h
fi
+
fi
-for ac_header in sched.h setns.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "sched.h" "ac_cv_header_sched_h" "$ac_includes_default"
+if test "x$ac_cv_header_sched_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SCHED_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "setns.h" "ac_cv_header_setns_h" "$ac_includes_default"
+if test "x$ac_cv_header_setns_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETNS_H 1" >>confdefs.h
-done
+fi
-for ac_func in setns
-do :
- ac_fn_c_check_func "$LINENO" "setns" "ac_cv_func_setns"
-if test "x$ac_cv_func_setns" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SETNS 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "setns" "ac_cv_func_setns"
+if test "x$ac_cv_func_setns" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETNS 1" >>confdefs.h
fi
-done
-for ac_header in linux/types.h linux/errqueue.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_SYS_TIME_H
+ac_fn_c_check_header_compile "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_LINUX_TYPES_H
@@ -15952,203 +17924,231 @@ ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE
#endif
"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+if test "x$ac_cv_header_linux_types_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LINUX_TYPES_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "linux/errqueue.h" "ac_cv_header_linux_errqueue_h" "#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_LINUX_TYPES_H
+# include <linux/types.h>
+#endif
-done
+"
+if test "x$ac_cv_header_linux_errqueue_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LINUX_ERRQUEUE_H 1" >>confdefs.h
+
+fi
HAVE_VALGRIND=no
-ac_fn_c_check_header_mongrel "$LINENO" "valgrind/valgrind.h" "ac_cv_header_valgrind_valgrind_h" "$ac_includes_default"
-if test "x$ac_cv_header_valgrind_valgrind_h" = xyes; then :
+ac_fn_c_check_header_compile "$LINENO" "valgrind/valgrind.h" "ac_cv_header_valgrind_valgrind_h" "$ac_includes_default"
+if test "x$ac_cv_header_valgrind_valgrind_h" = xyes
+then :
HAVE_VALGRIND=yes
fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SO_BSDCOMPAT declaration" >&5
-$as_echo_n "checking for SO_BSDCOMPAT declaration... " >&6; }
-if ${ac_cv_decl_so_bsdcompat+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SO_BSDCOMPAT declaration" >&5
+printf %s "checking for SO_BSDCOMPAT declaration... " >&6; }
+if test ${ac_cv_decl_so_bsdcompat+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/socket.h>
int
-main ()
+main (void)
{
int i = SO_BSDCOMPAT;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_decl_so_bsdcompat=yes
-else
+else $as_nop
ac_cv_decl_so_bsdcompat=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_so_bsdcompat" >&5
-$as_echo "$ac_cv_decl_so_bsdcompat" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_so_bsdcompat" >&5
+printf "%s\n" "$ac_cv_decl_so_bsdcompat" >&6; }
case "${ac_cv_decl_so_bsdcompat}" in
"yes" )
-$as_echo "#define HAVE_SO_BSDCOMPAT /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_SO_BSDCOMPAT /**/" >>confdefs.h
;;
* ) ;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for INADDR_LOOPBACK in netinet/in.h" >&5
-$as_echo_n "checking for INADDR_LOOPBACK in netinet/in.h... " >&6; }
-if ${ac_cv_decl_inaddr_loopback+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for INADDR_LOOPBACK in netinet/in.h" >&5
+printf %s "checking for INADDR_LOOPBACK in netinet/in.h... " >&6; }
+if test ${ac_cv_decl_inaddr_loopback+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <netinet/in.h>
int
-main ()
+main (void)
{
int i = INADDR_LOOPBACK;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_decl_inaddr_loopback=yes
-else
+else $as_nop
ac_cv_decl_inaddr_loopback=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_inaddr_loopback" >&5
-$as_echo "$ac_cv_decl_inaddr_loopback" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_inaddr_loopback" >&5
+printf "%s\n" "$ac_cv_decl_inaddr_loopback" >&6; }
-if test ${ac_cv_decl_inaddr_loopback} = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for INADDR_LOOPBACK in rpc/types.h" >&5
-$as_echo_n "checking for INADDR_LOOPBACK in rpc/types.h... " >&6; }
-if ${ac_cv_decl_inaddr_loopback_rpc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test ${ac_cv_decl_inaddr_loopback} = no
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for INADDR_LOOPBACK in rpc/types.h" >&5
+printf %s "checking for INADDR_LOOPBACK in rpc/types.h... " >&6; }
+if test ${ac_cv_decl_inaddr_loopback_rpc+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <rpc/types.h>
int
-main ()
+main (void)
{
int i = INADDR_LOOPBACK;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_decl_inaddr_loopback_rpc=yes
-else
+else $as_nop
ac_cv_decl_inaddr_loopback_rpc=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_inaddr_loopback_rpc" >&5
-$as_echo "$ac_cv_decl_inaddr_loopback_rpc" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_inaddr_loopback_rpc" >&5
+printf "%s\n" "$ac_cv_decl_inaddr_loopback_rpc" >&6; }
- case "${ac_cv_decl_inaddr_loopback_rpc}" in
- "yes" )
+ if test "${ac_cv_decl_inaddr_loopback_rpc}" = "yes"
+then :
-$as_echo "#define DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H /**/" >>confdefs.h
- ;;
- * )
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for INADDR_LOOPBACK in winsock2.h" >&5
-$as_echo_n "checking for INADDR_LOOPBACK in winsock2.h... " >&6; }
-if ${ac_cv_decl_inaddr_loopback_winsock2+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+printf "%s\n" "#define DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H /**/" >>confdefs.h
+
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for INADDR_LOOPBACK in winsock2.h" >&5
+printf %s "checking for INADDR_LOOPBACK in winsock2.h... " >&6; }
+if test ${ac_cv_decl_inaddr_loopback_winsock2+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
int
-main ()
+main (void)
{
int i = INADDR_LOOPBACK;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_decl_inaddr_loopback_winsock2=yes
-else
+else $as_nop
ac_cv_decl_inaddr_loopback_winsock2=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_inaddr_loopback_winsock2" >&5
-$as_echo "$ac_cv_decl_inaddr_loopback_winsock2" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_inaddr_loopback_winsock2" >&5
+printf "%s\n" "$ac_cv_decl_inaddr_loopback_winsock2" >&6; }
case "${ac_cv_decl_inaddr_loopback_winsock2}" in
"yes" )
-$as_echo "#define DEF_INADDR_LOOPBACK_IN_WINSOCK2_H /**/" >>confdefs.h
+printf "%s\n" "#define DEF_INADDR_LOOPBACK_IN_WINSOCK2_H /**/" >>confdefs.h
;;
* )
# couldn't find it anywhere
-$as_echo "#define HAVE_NO_INADDR_LOOPBACK /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_NO_INADDR_LOOPBACK /**/" >>confdefs.h
;;
- esac;;
- esac
+ esac
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys_errlist declaration in stdio.h or errno.h" >&5
-$as_echo_n "checking for sys_errlist declaration in stdio.h or errno.h... " >&6; }
-if ${ac_cv_decl_sys_errlist+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys_errlist declaration in stdio.h or errno.h" >&5
+printf %s "checking for sys_errlist declaration in stdio.h or errno.h... " >&6; }
+if test ${ac_cv_decl_sys_errlist+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <errno.h>
int
-main ()
+main (void)
{
char *msg = *(sys_errlist + 1);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_decl_sys_errlist=yes
-else
+else $as_nop
ac_cv_decl_sys_errlist=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_sys_errlist" >&5
-$as_echo "$ac_cv_decl_sys_errlist" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_decl_sys_errlist" >&5
+printf "%s\n" "$ac_cv_decl_sys_errlist" >&6; }
if test $ac_cv_decl_sys_errlist = yes; then
-$as_echo "#define SYS_ERRLIST_DECLARED /**/" >>confdefs.h
+printf "%s\n" "#define SYS_ERRLIST_DECLARED /**/" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if windows.h includes winsock2.h" >&5
-$as_echo_n "checking if windows.h includes winsock2.h... " >&6; }
-if ${erts_cv_windows_h_includes_winsock2_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if windows.h includes winsock2.h" >&5
+printf %s "checking if windows.h includes winsock2.h... " >&6; }
+if test ${erts_cv_windows_h_includes_winsock2_h+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <windows.h>
int
-main ()
+main (void)
{
#ifndef _WINSOCK2API_
#error winsock2.h not included
@@ -16159,34 +18159,36 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erts_cv_windows_h_includes_winsock2_h=yes
-else
+else $as_nop
erts_cv_windows_h_includes_winsock2_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_windows_h_includes_winsock2_h" >&5
-$as_echo "$erts_cv_windows_h_includes_winsock2_h" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_windows_h_includes_winsock2_h" >&5
+printf "%s\n" "$erts_cv_windows_h_includes_winsock2_h" >&6; }
if test $erts_cv_windows_h_includes_winsock2_h = yes; then
-$as_echo "#define WINDOWS_H_INCLUDES_WINSOCK2_H 1" >>confdefs.h
+printf "%s\n" "#define WINDOWS_H_INCLUDES_WINSOCK2_H 1" >>confdefs.h
fi
CPPFLAGS=$saved_cppflags
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
-$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
-if ${ac_cv_c_const+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+printf %s "checking for an ANSI C-conforming const... " >&6; }
+if test ${ac_cv_c_const+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __cplusplus
@@ -16199,7 +18201,7 @@ main ()
/* NEC SVR4.0.2 mips cc rejects this. */
struct point {int x, y;};
static struct point const zero = {0,0};
- /* AIX XL C 1.02.0.0 rejects this.
+ /* IBM XL C 1.02.0.0 rejects this.
It does not let you subtract one const X* pointer from another in
an arm of an if-expression whose if-part is not a constant
expression */
@@ -16227,7 +18229,7 @@ main ()
iptr p = 0;
++p;
}
- { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
+ { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
struct s { int j; const int *ap[3]; } bx;
struct s *b = &bx; b->j = 5;
@@ -16243,100 +18245,94 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_c_const=yes
-else
+else $as_nop
ac_cv_c_const=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
-$as_echo "$ac_cv_c_const" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+printf "%s\n" "$ac_cv_c_const" >&6; }
if test $ac_cv_c_const = no; then
-$as_echo "#define const /**/" >>confdefs.h
+printf "%s\n" "#define const /**/" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
-$as_echo_n "checking return type of signal handlers... " >&6; }
-if ${ac_cv_type_signal+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+
+ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
+if test "x$ac_cv_type_off_t" = xyes
+then :
+
+else $as_nop
+
+printf "%s\n" "#define off_t long int" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default
+"
+if test "x$ac_cv_type_pid_t" = xyes
+then :
+
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <sys/types.h>
-#include <signal.h>
+
+ #if defined _WIN64 && !defined __CYGWIN__
+ LLP64
+ #endif
int
-main ()
+main (void)
{
-return *(signal (0, 0)) (0) == 1;
+
;
return 0;
}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_type_signal=int
-else
- ac_cv_type_signal=void
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
-$as_echo "$ac_cv_type_signal" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define RETSIGTYPE $ac_cv_type_signal
-_ACEOF
-
-ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
-if test "x$ac_cv_type_off_t" = xyes; then :
-
-else
-
-cat >>confdefs.h <<_ACEOF
-#define off_t long int
_ACEOF
-
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_pid_type='int'
+else $as_nop
+ ac_pid_type='__int64'
fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
-if test "x$ac_cv_type_pid_t" = xyes; then :
+printf "%s\n" "#define pid_t $ac_pid_type" >>confdefs.h
-else
-
-cat >>confdefs.h <<_ACEOF
-#define pid_t int
-_ACEOF
fi
+
ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
-if test "x$ac_cv_type_size_t" = xyes; then :
+if test "x$ac_cv_type_size_t" = xyes
+then :
-else
+else $as_nop
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
-_ACEOF
+printf "%s\n" "#define size_t unsigned int" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
-$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
-if ${ac_cv_struct_tm+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
+printf %s "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if test ${ac_cv_struct_tm+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <time.h>
int
-main ()
+main (void)
{
struct tm tm;
int *p = &tm.tm_sec;
@@ -16345,51 +18341,54 @@ struct tm tm;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_struct_tm=time.h
-else
+else $as_nop
ac_cv_struct_tm=sys/time.h
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
-$as_echo "$ac_cv_struct_tm" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
+printf "%s\n" "$ac_cv_struct_tm" >&6; }
if test $ac_cv_struct_tm = sys/time.h; then
-$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h
+printf "%s\n" "#define TM_IN_SYS_TIME 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct sockaddr has sa_len field" >&5
-$as_echo_n "checking whether struct sockaddr has sa_len field... " >&6; }
-if ${ac_cv_struct_sockaddr_sa_len+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether struct sockaddr has sa_len field" >&5
+printf %s "checking whether struct sockaddr has sa_len field... " >&6; }
+if test ${ac_cv_struct_sockaddr_sa_len+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
-main ()
+main (void)
{
struct sockaddr s; s.sa_len = 10;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_struct_sockaddr_sa_len=yes
-else
+else $as_nop
ac_cv_struct_sockaddr_sa_len=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_sa_len" >&5
-$as_echo "$ac_cv_struct_sockaddr_sa_len" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_sa_len" >&5
+printf "%s\n" "$ac_cv_struct_sockaddr_sa_len" >&6; }
case ${ac_cv_struct_sockaddr_sa_len} in
"no" )
-$as_echo "#define NO_SA_LEN 1" >>confdefs.h
+printf "%s\n" "#define NO_SA_LEN 1" >>confdefs.h
;;
*) ;;
esac
@@ -16399,17 +18398,19 @@ esac
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5
-$as_echo_n "checking size of char... " >&6; }
-if ${ac_cv_sizeof_char+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of char" >&5
+printf %s "checking size of char... " >&6; }
+if test ${ac_cv_sizeof_char+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_char" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (char)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16418,31 +18419,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5
-$as_echo "$ac_cv_sizeof_char" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5
+printf "%s\n" "$ac_cv_sizeof_char" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_CHAR $ac_cv_sizeof_char
-_ACEOF
+printf "%s\n" "#define SIZEOF_CHAR $ac_cv_sizeof_char" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
-$as_echo_n "checking size of short... " >&6; }
-if ${ac_cv_sizeof_short+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+printf %s "checking size of short... " >&6; }
+if test ${ac_cv_sizeof_short+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_short" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (short)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16451,31 +18452,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
-$as_echo "$ac_cv_sizeof_short" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+printf "%s\n" "$ac_cv_sizeof_short" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-_ACEOF
+printf "%s\n" "#define SIZEOF_SHORT $ac_cv_sizeof_short" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
-$as_echo_n "checking size of int... " >&6; }
-if ${ac_cv_sizeof_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+printf %s "checking size of int... " >&6; }
+if test ${ac_cv_sizeof_int+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_int" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (int)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16484,31 +18485,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
-$as_echo "$ac_cv_sizeof_int" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+printf "%s\n" "$ac_cv_sizeof_int" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
+printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
-$as_echo_n "checking size of long... " >&6; }
-if ${ac_cv_sizeof_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+printf %s "checking size of long... " >&6; }
+if test ${ac_cv_sizeof_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16517,31 +18518,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
-$as_echo "$ac_cv_sizeof_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16550,31 +18551,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
-$as_echo_n "checking size of long long... " >&6; }
-if ${ac_cv_sizeof_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+printf %s "checking size of long long... " >&6; }
+if test ${ac_cv_sizeof_long_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16583,31 +18584,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
-$as_echo "$ac_cv_sizeof_long_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5
-$as_echo_n "checking size of size_t... " >&6; }
-if ${ac_cv_sizeof_size_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5
+printf %s "checking size of size_t... " >&6; }
+if test ${ac_cv_sizeof_size_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_size_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (size_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16616,31 +18617,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5
-$as_echo "$ac_cv_sizeof_size_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5
+printf "%s\n" "$ac_cv_sizeof_size_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t
-_ACEOF
+printf "%s\n" "#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5
-$as_echo_n "checking size of off_t... " >&6; }
-if ${ac_cv_sizeof_off_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5
+printf %s "checking size of off_t... " >&6; }
+if test ${ac_cv_sizeof_off_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_off_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (off_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16649,31 +18650,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5
-$as_echo "$ac_cv_sizeof_off_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5
+printf "%s\n" "$ac_cv_sizeof_off_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_OFF_T $ac_cv_sizeof_off_t
-_ACEOF
+printf "%s\n" "#define SIZEOF_OFF_T $ac_cv_sizeof_off_t" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5
-$as_echo_n "checking size of time_t... " >&6; }
-if ${ac_cv_sizeof_time_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5
+printf %s "checking size of time_t... " >&6; }
+if test ${ac_cv_sizeof_time_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_time_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (time_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16682,31 +18683,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5
-$as_echo "$ac_cv_sizeof_time_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5
+printf "%s\n" "$ac_cv_sizeof_time_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_TIME_T $ac_cv_sizeof_time_t
-_ACEOF
+printf "%s\n" "#define SIZEOF_TIME_T $ac_cv_sizeof_time_t" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of suseconds_t" >&5
-$as_echo_n "checking size of suseconds_t... " >&6; }
-if ${ac_cv_sizeof_suseconds_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (suseconds_t))" "ac_cv_sizeof_suseconds_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of suseconds_t" >&5
+printf %s "checking size of suseconds_t... " >&6; }
+if test ${ac_cv_sizeof_suseconds_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (suseconds_t))" "ac_cv_sizeof_suseconds_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_suseconds_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (suseconds_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16715,31 +18716,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_suseconds_t" >&5
-$as_echo "$ac_cv_sizeof_suseconds_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_suseconds_t" >&5
+printf "%s\n" "$ac_cv_sizeof_suseconds_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SUSECONDS_T $ac_cv_sizeof_suseconds_t
-_ACEOF
+printf "%s\n" "#define SIZEOF_SUSECONDS_T $ac_cv_sizeof_suseconds_t" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of _Float16" >&5
-$as_echo_n "checking size of _Float16... " >&6; }
-if ${ac_cv_sizeof__Float16+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (_Float16))" "ac_cv_sizeof__Float16" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of _Float16" >&5
+printf %s "checking size of _Float16... " >&6; }
+if test ${ac_cv_sizeof__Float16+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (_Float16))" "ac_cv_sizeof__Float16" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type__Float16" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (_Float16)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -16748,14 +18749,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof__Float16" >&5
-$as_echo "$ac_cv_sizeof__Float16" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof__Float16" >&5
+printf "%s\n" "$ac_cv_sizeof__Float16" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF__FLOAT16 $ac_cv_sizeof__Float16
-_ACEOF
+printf "%s\n" "#define SIZEOF__FLOAT16 $ac_cv_sizeof__Float16" >>confdefs.h
@@ -16766,8 +18765,8 @@ if test $ac_cv_sizeof_void_p = 8; then
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler 'restrict' support" >&5
-$as_echo_n "checking for C compiler 'restrict' support... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler 'restrict' support" >&5
+printf %s "checking for C compiler 'restrict' support... " >&6; }
restrict_keyword=""
for x in restrict __restrict; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -16777,43 +18776,42 @@ int * $x foo(int * $x arg);
{ int * $x var=arg; return var;}
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
restrict_keyword=$x
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test "x$restrict_keyword" != "x"; then
break
fi
done
-cat >>confdefs.h <<_ACEOF
-#define ERTS_RESTRICT $restrict_keyword
-_ACEOF
+printf "%s\n" "#define ERTS_RESTRICT $restrict_keyword" >>confdefs.h
if test "x$restrict_keyword" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_compiler_gnu" = "xyes"; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we should add -fno-tree-copyrename to CFLAGS for computed gotos to work properly" >&5
-$as_echo_n "checking if we should add -fno-tree-copyrename to CFLAGS for computed gotos to work properly... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we should add -fno-tree-copyrename to CFLAGS for computed gotos to work properly" >&5
+printf %s "checking if we should add -fno-tree-copyrename to CFLAGS for computed gotos to work properly... " >&6; }
## tree-copyrename was broken in gcc 4.3 and then removed in gcc 6
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if (__GNUC__ > 4 && __GNUC__ < 6) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
@@ -16826,27 +18824,29 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
no_tree_copyrename=yes
-else
+else $as_nop
no_tree_copyrename=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test "x$no_tree_copyrename" = "xyes"; then
CFLAGS="$CFLAGS -fno-tree-copyrename"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken gcc-4.3.0 compiler" >&5
-$as_echo_n "checking for broken gcc-4.3.0 compiler... " >&6; }
-if test "$cross_compiling" = yes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for broken gcc-4.3.0 compiler" >&5
+printf %s "checking for broken gcc-4.3.0 compiler... " >&6; }
+if test "$cross_compiling" = yes
+then :
gcc_4_3_0_bug=cross
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -16884,9 +18884,10 @@ int main(void)
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
gcc_4_3_0_bug=no
-else
+else $as_nop
gcc_4_3_0_bug=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -16906,8 +18907,8 @@ case $gcc_4_3_0_bug in
gcc_4_3_0_bug_result="$gcc_4_3_0_bug; could not run test since cross compiling, checked version number ($gcc_dumped_vsn) instead";;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_4_3_0_bug_result" >&5
-$as_echo "$gcc_4_3_0_bug_result" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gcc_4_3_0_bug_result" >&5
+printf "%s\n" "$gcc_4_3_0_bug_result" >&6; }
if test $gcc_4_3_0_bug = yes; then
as_fn_error $? "This gcc miscompiles the Erlang runtime system; please use a different version" "$LINENO" 5
fi
@@ -16920,11 +18921,12 @@ case X$erl_xcomp_bigendian in
*) as_fn_error $? "Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian" "$LINENO" 5;;
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
-$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
-if ${ac_cv_c_bigendian+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+printf %s "checking whether byte ordering is bigendian... " >&6; }
+if test ${ac_cv_c_bigendian+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_cv_c_bigendian=unknown
# See if we're dealing with a universal compiler.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -16935,7 +18937,8 @@ else
typedef int dummy;
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
# Check for potential -arch flags. It is not universal unless
# there are at least two -arch flags with different values.
@@ -16959,7 +18962,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
fi
done
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test $ac_cv_c_bigendian = unknown; then
# See if sys/param.h defines the BYTE_ORDER macro.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -16968,7 +18971,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
#include <sys/param.h>
int
-main ()
+main (void)
{
#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
&& defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
@@ -16980,7 +18983,8 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
# It does; now see whether it defined to BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -16988,7 +18992,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
#include <sys/param.h>
int
-main ()
+main (void)
{
#if BYTE_ORDER != BIG_ENDIAN
not big endian
@@ -16998,14 +19002,15 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_c_bigendian=yes
-else
+else $as_nop
ac_cv_c_bigendian=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
@@ -17014,7 +19019,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
#include <limits.h>
int
-main ()
+main (void)
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
bogus endian macros
@@ -17024,14 +19029,15 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
# It does; now see whether it defined to _BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
int
-main ()
+main (void)
{
#ifndef _BIG_ENDIAN
not big endian
@@ -17041,31 +19047,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_c_bigendian=yes
-else
+else $as_nop
ac_cv_c_bigendian=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# Compile a test program.
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
# Try to guess by grepping values from an object file.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-short int ascii_mm[] =
+unsigned short int ascii_mm[] =
{ 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
- short int ascii_ii[] =
+ unsigned short int ascii_ii[] =
{ 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
int use_ascii (int i) {
return ascii_mm[i] + ascii_ii[i];
}
- short int ebcdic_ii[] =
+ unsigned short int ebcdic_ii[] =
{ 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
- short int ebcdic_mm[] =
+ unsigned short int ebcdic_mm[] =
{ 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
int use_ebcdic (int i) {
return ebcdic_mm[i] + ebcdic_ii[i];
@@ -17073,14 +19081,15 @@ short int ascii_mm[] =
extern int foo;
int
-main ()
+main (void)
{
return use_ascii (foo) == use_ebcdic (foo);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
ac_cv_c_bigendian=yes
fi
@@ -17093,13 +19102,13 @@ if ac_fn_c_try_compile "$LINENO"; then :
fi
fi
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
-main ()
+main (void)
{
/* Are we little or big endian? From Harbison&Steele. */
@@ -17115,9 +19124,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_c_bigendian=no
-else
+else $as_nop
ac_cv_c_bigendian=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -17126,27 +19136,27 @@ fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
-$as_echo "$ac_cv_c_bigendian" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+printf "%s\n" "$ac_cv_c_bigendian" >&6; }
case $ac_cv_c_bigendian in #(
yes)
-$as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h
-$as_echo "#define ERTS_ENDIANNESS 1" >>confdefs.h
+printf "%s\n" "#define ERTS_ENDIANNESS 1" >>confdefs.h
;; #(
no)
-$as_echo "#define ERTS_ENDIANNESS -1" >>confdefs.h
+printf "%s\n" "#define ERTS_ENDIANNESS -1" >>confdefs.h
;; #(
universal)
-$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
;; #(
*)
@@ -17154,30 +19164,32 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
case "$erl_xcomp_bigendian" in
yes)
-$as_echo "#define ERTS_ENDIANNESS 1" >>confdefs.h
+printf "%s\n" "#define ERTS_ENDIANNESS 1" >>confdefs.h
;;
no)
-$as_echo "#define ERTS_ENDIANNESS -1" >>confdefs.h
+printf "%s\n" "#define ERTS_ENDIANNESS -1" >>confdefs.h
;;
*)
-$as_echo "#define ERTS_ENDIANNESS 0" >>confdefs.h
+printf "%s\n" "#define ERTS_ENDIANNESS 0" >>confdefs.h
;;
esac
;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether double word ordering is middle-endian" >&5
-$as_echo_n "checking whether double word ordering is middle-endian... " >&6; }
-if ${ac_cv_c_double_middle_endian+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether double word ordering is middle-endian" >&5
+printf %s "checking whether double word ordering is middle-endian... " >&6; }
+if test ${ac_cv_c_double_middle_endian+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
# It does not; compile a test program.
-if test "$cross_compiling" = yes; then :
+if test "$cross_compiling" = yes
+then :
ac_cv_c_double_middle=unknown
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
@@ -17246,9 +19258,10 @@ main(void)
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_c_double_middle_endian=no
-else
+else $as_nop
ac_cv_c_double_middle_endian=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -17256,40 +19269,37 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_double_middle_endian" >&5
-$as_echo "$ac_cv_c_double_middle_endian" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_double_middle_endian" >&5
+printf "%s\n" "$ac_cv_c_double_middle_endian" >&6; }
case $ac_cv_c_double_middle_endian in
yes)
-$as_echo "#define DOUBLE_MIDDLE_ENDIAN 1" >>confdefs.h
+printf "%s\n" "#define DOUBLE_MIDDLE_ENDIAN 1" >>confdefs.h
;;
no)
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unknown double endianness
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unknown double endianness
presetting ac_cv_c_double_middle_endian=no (or yes) will help" >&5
-$as_echo "$as_me: WARNING: unknown double endianness
+printf "%s\n" "$as_me: WARNING: unknown double endianness
presetting ac_cv_c_double_middle_endian=no (or yes) will help" >&2;} ;;
esac
-for ac_func in fdatasync
-do :
- ac_fn_c_check_func "$LINENO" "fdatasync" "ac_cv_func_fdatasync"
-if test "x$ac_cv_func_fdatasync" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_FDATASYNC 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "fdatasync" "ac_cv_func_fdatasync"
+if test "x$ac_cv_func_fdatasync" = xyes
+then :
+ printf "%s\n" "#define HAVE_FDATASYNC 1" >>confdefs.h
fi
-done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
-$as_echo_n "checking for library containing fdatasync... " >&6; }
-if ${ac_cv_search_fdatasync+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
+printf %s "checking for library containing fdatasync... " >&6; }
+if test ${ac_cv_search_fdatasync+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17297,72 +19307,73 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char fdatasync ();
int
-main ()
+main (void)
{
return fdatasync ();
;
return 0;
}
_ACEOF
-for ac_lib in '' rt; do
+for ac_lib in '' rt
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_fdatasync=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_fdatasync+:} false; then :
+ if test ${ac_cv_search_fdatasync+y}
+then :
break
fi
done
-if ${ac_cv_search_fdatasync+:} false; then :
+if test ${ac_cv_search_fdatasync+y}
+then :
-else
+else $as_nop
ac_cv_search_fdatasync=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5
-$as_echo "$ac_cv_search_fdatasync" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5
+printf "%s\n" "$ac_cv_search_fdatasync" >&6; }
ac_res=$ac_cv_search_fdatasync
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
-case $host_os in
- linux*|freebsd*|dragonfly*|darwin*)
- for ac_func in sendfile
-do :
- ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile"
-if test "x$ac_cv_func_sendfile" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SENDFILE 1
-_ACEOF
+case $host_os in #(
+ linux*|freebsd*|dragonfly*|darwin*) :
+
+ ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile"
+if test "x$ac_cv_func_sendfile" = xyes
+then :
+ printf "%s\n" "#define HAVE_SENDFILE 1" >>confdefs.h
fi
-done
- ;;
- solaris*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sendfilev" >&5
-$as_echo_n "checking for library containing sendfilev... " >&6; }
-if ${ac_cv_search_sendfilev+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ ;; #(
+ solaris*) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing sendfilev" >&5
+printf %s "checking for library containing sendfilev... " >&6; }
+if test ${ac_cv_search_sendfilev+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17370,58 +19381,61 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sendfilev ();
int
-main ()
+main (void)
{
return sendfilev ();
;
return 0;
}
_ACEOF
-for ac_lib in '' sendfile; do
+for ac_lib in '' sendfile
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_sendfilev=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_sendfilev+:} false; then :
+ if test ${ac_cv_search_sendfilev+y}
+then :
break
fi
done
-if ${ac_cv_search_sendfilev+:} false; then :
+if test ${ac_cv_search_sendfilev+y}
+then :
-else
+else $as_nop
ac_cv_search_sendfilev=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sendfilev" >&5
-$as_echo "$ac_cv_search_sendfilev" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sendfilev" >&5
+printf "%s\n" "$ac_cv_search_sendfilev" >&6; }
ac_res=$ac_cv_search_sendfilev
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-$as_echo "#define HAVE_SENDFILEV 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SENDFILEV 1" >>confdefs.h
fi
- ;;
- win32)
+ ;; #(
+ win32) :
+
LIBS="$LIBS -lmswsock"
- ;;
- *)
- ;;
+ ;; #(
+ *) :
+ ;;
esac
@@ -17430,33 +19444,21 @@ CPPFLAGS="$CPPFLAGS $EMU_THR_DEFS"
saved_libs=$LIBS
LIBS="$LIBS $EMU_THR_X_LIBS"
-for ac_header in windows.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default"
-if test "x$ac_cv_header_windows_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_WINDOWS_H 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default"
+if test "x$ac_cv_header_windows_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h
fi
-done
-
-for ac_header in winsock2.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default"
-if test "x$ac_cv_header_winsock2_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_WINSOCK2_H 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default"
+if test "x$ac_cv_header_winsock2_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_WINSOCK2_H 1" >>confdefs.h
fi
-done
-
-for ac_header in ws2tcpip.h
-do :
- ac_fn_c_check_header_compile "$LINENO" "ws2tcpip.h" "ac_cv_header_ws2tcpip_h" "
+ac_fn_c_check_header_compile "$LINENO" "ws2tcpip.h" "ac_cv_header_ws2tcpip_h" "
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
@@ -17465,17 +19467,14 @@ do :
#endif
"
-if test "x$ac_cv_header_ws2tcpip_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_WS2TCPIP_H 1
-_ACEOF
+if test "x$ac_cv_header_ws2tcpip_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_WS2TCPIP_H 1" >>confdefs.h
fi
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5
-$as_echo_n "checking for getaddrinfo... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5
+printf %s "checking for getaddrinfo... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17496,7 +19495,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#endif
int
-main ()
+main (void)
{
getaddrinfo("","",NULL,NULL);
@@ -17505,18 +19504,19 @@ getaddrinfo("","",NULL,NULL);
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_getaddrinfo=yes
-else
+else $as_nop
have_getaddrinfo=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $have_getaddrinfo = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getaddrinfo accepts enough flags" >&5
-$as_echo_n "checking whether getaddrinfo accepts enough flags... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether getaddrinfo accepts enough flags" >&5
+printf %s "checking whether getaddrinfo accepts enough flags... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17537,7 +19537,7 @@ $as_echo_n "checking whether getaddrinfo accepts enough flags... " >&6; }
#endif
int
-main ()
+main (void)
{
struct addrinfo hints, *ai;
@@ -17556,28 +19556,29 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
-else
+else $as_nop
have_getaddrinfo=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_getaddrinfo" >&5
-$as_echo "$have_getaddrinfo" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_getaddrinfo" >&5
+printf "%s\n" "$have_getaddrinfo" >&6; }
case $have_getaddrinfo in
yes)
-$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h
+printf "%s\n" "#define HAVE_GETADDRINFO 1" >>confdefs.h
;;
*) ;;
esac
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getnameinfo" >&5
-$as_echo_n "checking for getnameinfo... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getnameinfo" >&5
+printf %s "checking for getnameinfo... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17598,7 +19599,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#endif
int
-main ()
+main (void)
{
getnameinfo(NULL,0,NULL,0,NULL,0,0);
@@ -17607,60 +19608,310 @@ getnameinfo(NULL,0,NULL,0,NULL,0,0);
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_getnameinfo=yes
-else
+else $as_nop
have_getnameinfo=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $have_getnameinfo = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_GETNAMEINFO 1" >>confdefs.h
+printf "%s\n" "#define HAVE_GETNAMEINFO 1" >>confdefs.h
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-for ac_func in getipnodebyname getipnodebyaddr gethostbyname2
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "getipnodebyname" "ac_cv_func_getipnodebyname"
+if test "x$ac_cv_func_getipnodebyname" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETIPNODEBYNAME 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "getipnodebyaddr" "ac_cv_func_getipnodebyaddr"
+if test "x$ac_cv_func_getipnodebyaddr" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETIPNODEBYADDR 1" >>confdefs.h
+fi
+ac_fn_c_check_func "$LINENO" "gethostbyname2" "ac_cv_func_gethostbyname2"
+if test "x$ac_cv_func_gethostbyname2" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHOSTBYNAME2 1" >>confdefs.h
+
+fi
-for ac_func in ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlopen \
- pread pwrite memmove strerror strerror_r strncasecmp \
- gethrtime localtime_r gmtime_r mprotect madvise posix_madvise \
- mmap mremap memcpy mallopt sbrk _sbrk __sbrk brk _brk __brk \
- flockfile fstat strlcpy strlcat setsid posix2time time2posix \
- setlocale nl_langinfo poll mlockall ppoll vsyslog
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+
+ac_fn_c_check_func "$LINENO" "ieee_handler" "ac_cv_func_ieee_handler"
+if test "x$ac_cv_func_ieee_handler" = xyes
+then :
+ printf "%s\n" "#define HAVE_IEEE_HANDLER 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "fpsetmask" "ac_cv_func_fpsetmask"
+if test "x$ac_cv_func_fpsetmask" = xyes
+then :
+ printf "%s\n" "#define HAVE_FPSETMASK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "finite" "ac_cv_func_finite"
+if test "x$ac_cv_func_finite" = xyes
+then :
+ printf "%s\n" "#define HAVE_FINITE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "isnan" "ac_cv_func_isnan"
+if test "x$ac_cv_func_isnan" = xyes
+then :
+ printf "%s\n" "#define HAVE_ISNAN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "isinf" "ac_cv_func_isinf"
+if test "x$ac_cv_func_isinf" = xyes
+then :
+ printf "%s\n" "#define HAVE_ISINF 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "res_gethostbyname" "ac_cv_func_res_gethostbyname"
+if test "x$ac_cv_func_res_gethostbyname" = xyes
+then :
+ printf "%s\n" "#define HAVE_RES_GETHOSTBYNAME 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes
+then :
+ printf "%s\n" "#define HAVE_DLOPEN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "dlvsym" "ac_cv_func_dlvsym"
+if test "x$ac_cv_func_dlvsym" = xyes
+then :
+ printf "%s\n" "#define HAVE_DLVSYM 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
+if test "x$ac_cv_func_pread" = xyes
+then :
+ printf "%s\n" "#define HAVE_PREAD 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite"
+if test "x$ac_cv_func_pwrite" = xyes
+then :
+ printf "%s\n" "#define HAVE_PWRITE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove"
+if test "x$ac_cv_func_memmove" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMMOVE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRERROR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r"
+if test "x$ac_cv_func_strerror_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRERROR_R 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strncasecmp" "ac_cv_func_strncasecmp"
+if test "x$ac_cv_func_strncasecmp" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRNCASECMP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r"
+if test "x$ac_cv_func_localtime_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r"
+if test "x$ac_cv_func_gmtime_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_GMTIME_R 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "mprotect" "ac_cv_func_mprotect"
+if test "x$ac_cv_func_mprotect" = xyes
+then :
+ printf "%s\n" "#define HAVE_MPROTECT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "madvise" "ac_cv_func_madvise"
+if test "x$ac_cv_func_madvise" = xyes
+then :
+ printf "%s\n" "#define HAVE_MADVISE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix_madvise" "ac_cv_func_posix_madvise"
+if test "x$ac_cv_func_posix_madvise" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_MADVISE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = xyes
+then :
+ printf "%s\n" "#define HAVE_MMAP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "mremap" "ac_cv_func_mremap"
+if test "x$ac_cv_func_mremap" = xyes
+then :
+ printf "%s\n" "#define HAVE_MREMAP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "memcpy" "ac_cv_func_memcpy"
+if test "x$ac_cv_func_memcpy" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMCPY 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "mallopt" "ac_cv_func_mallopt"
+if test "x$ac_cv_func_mallopt" = xyes
+then :
+ printf "%s\n" "#define HAVE_MALLOPT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sbrk" "ac_cv_func_sbrk"
+if test "x$ac_cv_func_sbrk" = xyes
+then :
+ printf "%s\n" "#define HAVE_SBRK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "_sbrk" "ac_cv_func__sbrk"
+if test "x$ac_cv_func__sbrk" = xyes
+then :
+ printf "%s\n" "#define HAVE__SBRK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "__sbrk" "ac_cv_func___sbrk"
+if test "x$ac_cv_func___sbrk" = xyes
+then :
+ printf "%s\n" "#define HAVE___SBRK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "brk" "ac_cv_func_brk"
+if test "x$ac_cv_func_brk" = xyes
+then :
+ printf "%s\n" "#define HAVE_BRK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "_brk" "ac_cv_func__brk"
+if test "x$ac_cv_func__brk" = xyes
+then :
+ printf "%s\n" "#define HAVE__BRK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "__brk" "ac_cv_func___brk"
+if test "x$ac_cv_func___brk" = xyes
+then :
+ printf "%s\n" "#define HAVE___BRK 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "flockfile" "ac_cv_func_flockfile"
+if test "x$ac_cv_func_flockfile" = xyes
+then :
+ printf "%s\n" "#define HAVE_FLOCKFILE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "fstat" "ac_cv_func_fstat"
+if test "x$ac_cv_func_fstat" = xyes
+then :
+ printf "%s\n" "#define HAVE_FSTAT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
+if test "x$ac_cv_func_strlcpy" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
+if test "x$ac_cv_func_strlcat" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRLCAT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "setsid" "ac_cv_func_setsid"
+if test "x$ac_cv_func_setsid" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETSID 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix2time" "ac_cv_func_posix2time"
+if test "x$ac_cv_func_posix2time" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX2TIME 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "time2posix" "ac_cv_func_time2posix"
+if test "x$ac_cv_func_time2posix" = xyes
+then :
+ printf "%s\n" "#define HAVE_TIME2POSIX 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "setlocale" "ac_cv_func_setlocale"
+if test "x$ac_cv_func_setlocale" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETLOCALE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "nl_langinfo" "ac_cv_func_nl_langinfo"
+if test "x$ac_cv_func_nl_langinfo" = xyes
+then :
+ printf "%s\n" "#define HAVE_NL_LANGINFO 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll"
+if test "x$ac_cv_func_poll" = xyes
+then :
+ printf "%s\n" "#define HAVE_POLL 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "mlockall" "ac_cv_func_mlockall"
+if test "x$ac_cv_func_mlockall" = xyes
+then :
+ printf "%s\n" "#define HAVE_MLOCKALL 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll"
+if test "x$ac_cv_func_ppoll" = xyes
+then :
+ printf "%s\n" "#define HAVE_PPOLL 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "vsyslog" "ac_cv_func_vsyslog"
+if test "x$ac_cv_func_vsyslog" = xyes
+then :
+ printf "%s\n" "#define HAVE_VSYSLOG 1" >>confdefs.h
fi
-done
## We have a special check for inet_pton as AC_CHECK_FUCNS does not work
## on windows 32-bit as there a macro is used to rename the symbol...
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5
-$as_echo_n "checking for inet_pton... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5
+printf %s "checking for inet_pton... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17671,77 +19922,88 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#endif
int
-main ()
+main (void)
{
inet_pton(2,"",(void*)0)
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_inet_pton=yes
-else
+else $as_nop
have_inet_pton=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $have_inet_pton = yes; then
-$as_echo "#define HAVE_INET_PTON 1" >>confdefs.h
+printf "%s\n" "#define HAVE_INET_PTON 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for isfinite" >&5
-$as_echo_n "checking for isfinite... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for isfinite" >&5
+printf %s "checking for isfinite... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <math.h>
int
-main ()
+main (void)
{
isfinite(0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_isfinite=yes
-else
+else $as_nop
have_isfinite=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $have_isfinite = yes; then
-$as_echo "#define HAVE_ISFINITE 1" >>confdefs.h
+printf "%s\n" "#define HAVE_ISFINITE 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-case X$erl_xcomp_posix_memalign in
- Xno) ;;
- Xyes) have_posix_memalign=yes ;;
- *)
+case X$erl_xcomp_posix_memalign in #(
+ Xno) :
+ ;; #(
+ Xyes) :
+
+ have_posix_memalign=yes
+ ;; #(
+ *) :
+
ac_fn_c_check_func "$LINENO" "posix_memalign" "ac_cv_func_posix_memalign"
-if test "x$ac_cv_func_posix_memalign" = xyes; then :
- if test "$cross_compiling" != yes; then
-if test "$cross_compiling" = yes; then :
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+if test "x$ac_cv_func_posix_memalign" = xyes
+then :
+ if test "$cross_compiling" != yes
+then :
+
+if test "$cross_compiling" = yes
+then :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run test program while cross compiling
See \`config.log' for more details" "$LINENO" 5; }
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17756,7 +20018,8 @@ int main(void) {
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
have_posix_memalign=yes
fi
@@ -17764,95 +20027,98 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
- else
+
+else $as_nop
+
have_posix_memalign=yes
- fi
+
fi
-;;
+fi
+
+ ;;
esac
if test "$have_posix_memalign" = "yes"; then
-$as_echo "#define HAVE_POSIX_MEMALIGN 1" >>confdefs.h
+printf "%s\n" "#define HAVE_POSIX_MEMALIGN 1" >>confdefs.h
fi
case $host_os in
darwin10.8.0)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for writev" >&5
-$as_echo_n "checking for writev... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; } ;;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for writev" >&5
+printf %s "checking for writev... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; } ;;
*)
- for ac_func in writev
-do :
- ac_fn_c_check_func "$LINENO" "writev" "ac_cv_func_writev"
-if test "x$ac_cv_func_writev" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_WRITEV 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "writev" "ac_cv_func_writev"
+if test "x$ac_cv_func_writev" = xyes
+then :
+ printf "%s\n" "#define HAVE_WRITEV 1" >>confdefs.h
fi
-done
;;
esac
-ac_fn_c_check_decl "$LINENO" "posix2time" "ac_cv_have_decl_posix2time" "#include <time.h>
-"
-if test "x$ac_cv_have_decl_posix2time" = xyes; then :
+ac_fn_check_decl "$LINENO" "posix2time" "ac_cv_have_decl_posix2time" "#include <time.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_posix2time" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_POSIX2TIME $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "time2posix" "ac_cv_have_decl_time2posix" "#include <time.h>
-"
-if test "x$ac_cv_have_decl_time2posix" = xyes; then :
+printf "%s\n" "#define HAVE_DECL_POSIX2TIME $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "time2posix" "ac_cv_have_decl_time2posix" "#include <time.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_time2posix" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_TIME2POSIX $ac_have_decl
-_ACEOF
+printf "%s\n" "#define HAVE_DECL_TIME2POSIX $ac_have_decl" >>confdefs.h
-for ac_func in vprintf
-do :
- ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
-if test "x$ac_cv_func_vprintf" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_VPRINTF 1
-_ACEOF
+ac_func=
+for ac_item in $ac_func_c_list
+do
+ if test $ac_func; then
+ ac_fn_c_check_func "$LINENO" $ac_func ac_cv_func_$ac_func
+ if eval test \"x\$ac_cv_func_$ac_func\" = xyes; then
+ echo "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_func=
+ else
+ ac_func=$ac_item
+ fi
+done
-ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
-if test "x$ac_cv_func__doprnt" = xyes; then :
+if test "x$ac_cv_func_vprintf" = xno
+then :
+ ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
+if test "x$ac_cv_func__doprnt" = xyes
+then :
-$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_DOPRNT 1" >>confdefs.h
fi
fi
-done
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for conflicting declaration of fread" >&5
-$as_echo_n "checking for conflicting declaration of fread... " >&6; }
-if ${ac_cv_func_decl_fread+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for conflicting declaration of fread" >&5
+printf %s "checking for conflicting declaration of fread... " >&6; }
+if test ${ac_cv_func_decl_fread+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
extern int fread();
char *c = (char *)fread;
@@ -17861,143 +20127,152 @@ char *c = (char *)fread;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "ac_cv_func_decl_fread=no"
-else
+else $as_nop
eval "ac_cv_func_decl_fread=yes"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if eval "test \"`echo '$ac_cv_func_decl_'fread`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_CONFLICTING_FREAD_DECLARATION 1" >>confdefs.h
+printf "%s\n" "#define HAVE_CONFLICTING_FREAD_DECLARATION 1" >>confdefs.h
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for putc_unlocked" >&5
-$as_echo_n "checking for putc_unlocked... " >&6; }
-if ${erts_cv_putc_unlocked+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for putc_unlocked" >&5
+printf %s "checking for putc_unlocked... " >&6; }
+if test ${erts_cv_putc_unlocked+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
int res = putc_unlocked('x',stdout);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_putc_unlocked=yes
-else
+else $as_nop
erts_cv_putc_unlocked=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_putc_unlocked" >&5
-$as_echo "$erts_cv_putc_unlocked" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_putc_unlocked" >&5
+printf "%s\n" "$erts_cv_putc_unlocked" >&6; }
if test $erts_cv_putc_unlocked = yes; then
-$as_echo "#define HAVE_PUTC_UNLOCKED 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PUTC_UNLOCKED 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fwrite_unlocked" >&5
-$as_echo_n "checking for fwrite_unlocked... " >&6; }
-if ${erts_cv_fwrite_unlocked+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fwrite_unlocked" >&5
+printf %s "checking for fwrite_unlocked... " >&6; }
+if test ${erts_cv_fwrite_unlocked+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
size_t res = fwrite_unlocked(NULL,sizeof(char),0,stdout);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_fwrite_unlocked=yes
-else
+else $as_nop
erts_cv_fwrite_unlocked=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_fwrite_unlocked" >&5
-$as_echo "$erts_cv_fwrite_unlocked" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_fwrite_unlocked" >&5
+printf "%s\n" "$erts_cv_fwrite_unlocked" >&6; }
if test $erts_cv_fwrite_unlocked = yes; then
-$as_echo "#define HAVE_FWRITE_UNLOCKED 1" >>confdefs.h
+printf "%s\n" "#define HAVE_FWRITE_UNLOCKED 1" >>confdefs.h
fi
-for ac_func in openpty
-do :
- ac_fn_c_check_func "$LINENO" "openpty" "ac_cv_func_openpty"
-if test "x$ac_cv_func_openpty" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENPTY 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "openpty" "ac_cv_func_openpty"
+if test "x$ac_cv_func_openpty" = xyes
+then :
+ printf "%s\n" "#define HAVE_OPENPTY 1" >>confdefs.h
fi
-done
-for ac_header in net/if_dl.h ifaddrs.h netpacket/packet.h sys/un.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "net/if_dl.h" "ac_cv_header_net_if_dl_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_dl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NET_IF_DL_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ifaddrs_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_IFADDRS_H 1" >>confdefs.h
-done
+fi
+ac_fn_c_check_header_compile "$LINENO" "netpacket/packet.h" "ac_cv_header_netpacket_packet_h" "$ac_includes_default"
+if test "x$ac_cv_header_netpacket_packet_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NETPACKET_PACKET_H 1" >>confdefs.h
-for ac_func in getifaddrs
-do :
- ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
-if test "x$ac_cv_func_getifaddrs" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETIFADDRS 1
-_ACEOF
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_un_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_UN_H 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETIFADDRS 1" >>confdefs.h
fi
-done
ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_path" "ac_cv_member_struct_sockaddr_un_sun_path" "#include <sys/un.h>
"
-if test "x$ac_cv_member_struct_sockaddr_un_sun_path" = xyes; then :
+if test "x$ac_cv_member_struct_sockaddr_un_sun_path" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SOCKADDR_UN_SUN_PATH 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_UN_SUN_PATH 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether in6addr_any is declared" >&5
-$as_echo_n "checking whether in6addr_any is declared... " >&6; }
-if ${erts_cv_have_in6addr_any+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether in6addr_any is declared" >&5
+printf %s "checking whether in6addr_any is declared... " >&6; }
+if test ${erts_cv_have_in6addr_any+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18007,7 +20282,7 @@ else
#include <stdio.h>
int
-main ()
+main (void)
{
printf("%d", in6addr_any.s6_addr[16]);
@@ -18015,31 +20290,33 @@ printf("%d", in6addr_any.s6_addr[16]);
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_have_in6addr_any=yes
-else
+else $as_nop
erts_cv_have_in6addr_any=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have_in6addr_any" >&5
-$as_echo "$erts_cv_have_in6addr_any" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have_in6addr_any" >&5
+printf "%s\n" "$erts_cv_have_in6addr_any" >&6; }
case "$erts_cv_have_in6addr_any" in
yes)
-$as_echo "#define HAVE_IN6ADDR_ANY 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IN6ADDR_ANY 1" >>confdefs.h
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether in6addr_loopback is declared" >&5
-$as_echo_n "checking whether in6addr_loopback is declared... " >&6; }
-if ${erts_cv_have_in6addr_loopback+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether in6addr_loopback is declared" >&5
+printf %s "checking whether in6addr_loopback is declared... " >&6; }
+if test ${erts_cv_have_in6addr_loopback+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18049,7 +20326,7 @@ else
#include <stdio.h>
int
-main ()
+main (void)
{
printf("%d", in6addr_loopback.s6_addr[16]);
@@ -18057,81 +20334,76 @@ printf("%d", in6addr_loopback.s6_addr[16]);
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_have_in6addr_loopback=yes
-else
+else $as_nop
erts_cv_have_in6addr_loopback=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have_in6addr_loopback" >&5
-$as_echo "$erts_cv_have_in6addr_loopback" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have_in6addr_loopback" >&5
+printf "%s\n" "$erts_cv_have_in6addr_loopback" >&6; }
case "$erts_cv_have_in6addr_loopback" in
yes)
-$as_echo "#define HAVE_IN6ADDR_LOOPBACK 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IN6ADDR_LOOPBACK 1" >>confdefs.h
esac
-ac_fn_c_check_decl "$LINENO" "IN6ADDR_ANY_INIT" "ac_cv_have_decl_IN6ADDR_ANY_INIT" "
+ac_fn_check_decl "$LINENO" "IN6ADDR_ANY_INIT" "ac_cv_have_decl_IN6ADDR_ANY_INIT" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-"
-if test "x$ac_cv_have_decl_IN6ADDR_ANY_INIT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_IN6ADDR_ANY_INIT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_IN6ADDR_ANY_INIT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "IN6ADDR_LOOPBACK_INIT" "ac_cv_have_decl_IN6ADDR_LOOPBACK_INIT" "
+printf "%s\n" "#define HAVE_DECL_IN6ADDR_ANY_INIT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "IN6ADDR_LOOPBACK_INIT" "ac_cv_have_decl_IN6ADDR_LOOPBACK_INIT" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-"
-if test "x$ac_cv_have_decl_IN6ADDR_LOOPBACK_INIT" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_IN6ADDR_LOOPBACK_INIT" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_IN6ADDR_LOOPBACK_INIT $ac_have_decl
-_ACEOF
-ac_fn_c_check_decl "$LINENO" "IPV6_V6ONLY" "ac_cv_have_decl_IPV6_V6ONLY" "
+printf "%s\n" "#define HAVE_DECL_IN6ADDR_LOOPBACK_INIT $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "IPV6_V6ONLY" "ac_cv_have_decl_IPV6_V6ONLY" "
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-"
-if test "x$ac_cv_have_decl_IPV6_V6ONLY" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_IPV6_V6ONLY" = xyes
+then :
ac_have_decl=1
-else
+else $as_nop
ac_have_decl=0
fi
+printf "%s\n" "#define HAVE_DECL_IPV6_V6ONLY $ac_have_decl" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_IPV6_V6ONLY $ac_have_decl
-_ACEOF
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_getaffinity/sched_setaffinity" >&5
-$as_echo_n "checking for sched_getaffinity/sched_setaffinity... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sched_getaffinity/sched_setaffinity" >&5
+printf %s "checking for sched_getaffinity/sched_setaffinity... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sched.h>
int
-main ()
+main (void)
{
#ifndef CPU_SETSIZE
@@ -18150,29 +20422,30 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
sched_xetaffinity=yes
-else
+else $as_nop
sched_xetaffinity=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $sched_xetaffinity" >&5
-$as_echo "$sched_xetaffinity" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sched_xetaffinity" >&5
+printf "%s\n" "$sched_xetaffinity" >&6; }
if test $sched_xetaffinity = yes; then
-$as_echo "#define HAVE_SCHED_xETAFFINITY 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SCHED_xETAFFINITY 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pset functionality" >&5
-$as_echo_n "checking for pset functionality... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pset functionality" >&5
+printf %s "checking for pset functionality... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/pset.h>
int
-main ()
+main (void)
{
int res;
@@ -18187,23 +20460,24 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
pset_functionality=yes
-else
+else $as_nop
pset_functionality=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pset_functionality" >&5
-$as_echo "$pset_functionality" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pset_functionality" >&5
+printf "%s\n" "$pset_functionality" >&6; }
if test $pset_functionality = yes; then
-$as_echo "#define HAVE_PSET 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PSET 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for processor_bind functionality" >&5
-$as_echo_n "checking for processor_bind functionality... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for processor_bind functionality" >&5
+printf %s "checking for processor_bind functionality... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18212,7 +20486,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include <sys/procset.h>
int
-main ()
+main (void)
{
int res = processor_bind(P_LWPID, P_MYID, PBIND_NONE, NULL);
@@ -18221,23 +20495,24 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
processor_bind_functionality=yes
-else
+else $as_nop
processor_bind_functionality=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $processor_bind_functionality" >&5
-$as_echo "$processor_bind_functionality" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $processor_bind_functionality" >&5
+printf "%s\n" "$processor_bind_functionality" >&6; }
if test $processor_bind_functionality = yes; then
-$as_echo "#define HAVE_PROCESSOR_BIND 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PROCESSOR_BIND 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cpuset_getaffinity/cpuset_setaffinity" >&5
-$as_echo_n "checking for cpuset_getaffinity/cpuset_setaffinity... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cpuset_getaffinity/cpuset_setaffinity" >&5
+printf %s "checking for cpuset_getaffinity/cpuset_setaffinity... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18245,7 +20520,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include <sys/cpuset.h>
int
-main ()
+main (void)
{
int res;
@@ -18261,91 +20536,98 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
cpuset_xetaffinity=yes
-else
+else $as_nop
cpuset_xetaffinity=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cpuset_xetaffinity" >&5
-$as_echo "$cpuset_xetaffinity" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cpuset_xetaffinity" >&5
+printf "%s\n" "$cpuset_xetaffinity" >&6; }
if test $cpuset_xetaffinity = yes; then
-$as_echo "#define HAVE_CPUSET_xETAFFINITY 1" >>confdefs.h
+printf "%s\n" "#define HAVE_CPUSET_xETAFFINITY 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 'end' symbol" >&5
-$as_echo_n "checking for 'end' symbol... " >&6; }
-if ${erts_cv_have_end_symbol+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 'end' symbol" >&5
+printf %s "checking for 'end' symbol... " >&6; }
+if test ${erts_cv_have_end_symbol+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
extern char end; {char *x = &end; *x= 0;}
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_have_end_symbol=yes
-else
+else $as_nop
erts_cv_have_end_symbol=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have_end_symbol" >&5
-$as_echo "$erts_cv_have_end_symbol" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have_end_symbol" >&5
+printf "%s\n" "$erts_cv_have_end_symbol" >&6; }
if test $erts_cv_have_end_symbol = yes; then
-$as_echo "#define HAVE_END_SYMBOL 1" >>confdefs.h
+printf "%s\n" "#define HAVE_END_SYMBOL 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for '_end' symbol" >&5
-$as_echo_n "checking for '_end' symbol... " >&6; }
-if ${erts_cv_have__end_symbol+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for '_end' symbol" >&5
+printf %s "checking for '_end' symbol... " >&6; }
+if test ${erts_cv_have__end_symbol+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
extern char _end; {char *x = &_end; *x= 0;}
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_have__end_symbol=yes
-else
+else $as_nop
erts_cv_have__end_symbol=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have__end_symbol" >&5
-$as_echo "$erts_cv_have__end_symbol" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_have__end_symbol" >&5
+printf "%s\n" "$erts_cv_have__end_symbol" >&6; }
if test $erts_cv_have__end_symbol = yes; then
-$as_echo "#define HAVE__END_SYMBOL 1" >>confdefs.h
+printf "%s\n" "#define HAVE__END_SYMBOL 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if __after_morecore_hook can track malloc()s core memory use" >&5
-$as_echo_n "checking if __after_morecore_hook can track malloc()s core memory use... " >&6; }
-if ${erts_cv___after_morecore_hook_can_track_malloc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if __after_morecore_hook can track malloc()s core memory use" >&5
+printf %s "checking if __after_morecore_hook can track malloc()s core memory use... " >&6; }
+if test ${erts_cv___after_morecore_hook_can_track_malloc+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "$cross_compiling" = yes
+then :
case X$erl_xcomp_after_morecore_hook in
X) erts_cv___after_morecore_hook_can_track_malloc=cross;;
@@ -18354,7 +20636,7 @@ else
esac
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18481,9 +20763,10 @@ int main(void)
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
erts_cv___after_morecore_hook_can_track_malloc=yes
-else
+else $as_nop
erts_cv___after_morecore_hook_can_track_malloc=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -18491,24 +20774,27 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv___after_morecore_hook_can_track_malloc" >&5
-$as_echo "$erts_cv___after_morecore_hook_can_track_malloc" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv___after_morecore_hook_can_track_malloc" >&5
+printf "%s\n" "$erts_cv___after_morecore_hook_can_track_malloc" >&6; }
case $erts_cv___after_morecore_hook_can_track_malloc in
yes)
-$as_echo "#define ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC 1" >>confdefs.h
+printf "%s\n" "#define ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC 1" >>confdefs.h
;;
- cross) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result no guessed because of cross compilation" >&2;};;
+ cross) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result no guessed because of cross compilation" >&2;};;
*) ;;
esac
-if test "x$ac_cv_func_sbrk" = "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking types of sbrk()s return value and argument" >&5
-$as_echo_n "checking types of sbrk()s return value and argument... " >&6; }
-if ${erts_cv_sbrk_ret_arg_types+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "x$ac_cv_func_sbrk" = "xyes"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking types of sbrk()s return value and argument" >&5
+printf %s "checking types of sbrk()s return value and argument... " >&6; }
+if test ${erts_cv_sbrk_ret_arg_types+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
erts_cv_sbrk_ret_arg_types=unknown
@@ -18523,17 +20809,18 @@ else
#include <sys/types.h>
#include <unistd.h>
int
-main ()
+main (void)
{
$rtype sbrk($atype incr);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_sbrk_ret_arg_types="$rtype,$atype"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
IFS=","
if test "$erts_cv_sbrk_ret_arg_types" != "unknown"; then
@@ -18543,8 +20830,8 @@ rm -f core conftest.err conftest.$ac_objext \
done
IFS=$save_ifs
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_sbrk_ret_arg_types" >&5
-$as_echo "$erts_cv_sbrk_ret_arg_types" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_sbrk_ret_arg_types" >&5
+printf "%s\n" "$erts_cv_sbrk_ret_arg_types" >&6; }
if test "$erts_cv_sbrk_ret_arg_types" != "unknown"; then
save_ifs="$IFS"; IFS=","
@@ -18553,24 +20840,24 @@ $erts_cv_sbrk_ret_arg_types
EOF
IFS=$save_ifs
-cat >>confdefs.h <<_ACEOF
-#define SBRK_RET_TYPE $ret_type
-_ACEOF
+printf "%s\n" "#define SBRK_RET_TYPE $ret_type" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define SBRK_ARG_TYPE $arg_type
-_ACEOF
+printf "%s\n" "#define SBRK_ARG_TYPE $arg_type" >>confdefs.h
fi
+
fi
-if test $ac_cv_func_brk = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking types of brk()s return value and argument" >&5
-$as_echo_n "checking types of brk()s return value and argument... " >&6; }
-if ${erts_cv_brk_ret_arg_types+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test $ac_cv_func_brk = yes
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking types of brk()s return value and argument" >&5
+printf %s "checking types of brk()s return value and argument... " >&6; }
+if test ${erts_cv_brk_ret_arg_types+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
erts_cv_brk_ret_arg_types=unknown
@@ -18585,17 +20872,18 @@ else
#include <sys/types.h>
#include <unistd.h>
int
-main ()
+main (void)
{
$rtype brk($atype endds);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erts_cv_brk_ret_arg_types="$rtype,$atype"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
IFS=","
if test "$erts_cv_brk_ret_arg_types" != "unknown"; then
@@ -18605,8 +20893,8 @@ rm -f core conftest.err conftest.$ac_objext \
done
IFS=$save_ifs
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_brk_ret_arg_types" >&5
-$as_echo "$erts_cv_brk_ret_arg_types" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_brk_ret_arg_types" >&5
+printf "%s\n" "$erts_cv_brk_ret_arg_types" >&6; }
if test "$erts_cv_brk_ret_arg_types" != "unknown"; then
save_ifs="$IFS"; IFS=","
@@ -18615,27 +20903,27 @@ $erts_cv_brk_ret_arg_types
EOF
IFS=$save_ifs
-cat >>confdefs.h <<_ACEOF
-#define BRK_RET_TYPE $ret_type
-_ACEOF
+printf "%s\n" "#define BRK_RET_TYPE $ret_type" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define BRK_ARG_TYPE $arg_type
-_ACEOF
+printf "%s\n" "#define BRK_ARG_TYPE $arg_type" >>confdefs.h
fi
fi
-if test $ac_cv_func_sbrk = yes; then
+if test $ac_cv_func_sbrk = yes
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sbrk()/brk() wrappers can track malloc()s core memory use" >&5
-$as_echo_n "checking if sbrk()/brk() wrappers can track malloc()s core memory use... " >&6; }
-if ${erts_cv_brk_wrappers_can_track_malloc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if sbrk()/brk() wrappers can track malloc()s core memory use" >&5
+printf %s "checking if sbrk()/brk() wrappers can track malloc()s core memory use... " >&6; }
+if test ${erts_cv_brk_wrappers_can_track_malloc+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "$cross_compiling" = yes
+then :
case X$erl_xcomp_dlsym_brk_wrappers in
X) erts_cv_brk_wrappers_can_track_malloc=cross;;
@@ -18643,7 +20931,7 @@ else
*) as_fn_error $? "Bad erl_xcomp_dlsym_brk_wrappers value: $erl_xcomp_dlsym_brk_wrappers" "$LINENO" 5;;
esac
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18813,9 +21101,10 @@ int main(void)
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
erts_cv_brk_wrappers_can_track_malloc=yes
-else
+else $as_nop
erts_cv_brk_wrappers_can_track_malloc=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -18823,18 +21112,19 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erts_cv_brk_wrappers_can_track_malloc" >&5
-$as_echo "$erts_cv_brk_wrappers_can_track_malloc" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erts_cv_brk_wrappers_can_track_malloc" >&5
+printf "%s\n" "$erts_cv_brk_wrappers_can_track_malloc" >&6; }
case $erts_cv_brk_wrappers_can_track_malloc in
yes)
-$as_echo "#define ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC 1" >>confdefs.h
+printf "%s\n" "#define ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC 1" >>confdefs.h
;;
cross)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result no guessed because of cross compilation" >&2;};;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result no guessed because of cross compilation" >&2;};;
*) ;;
esac
+
fi
LIBS=$saved_libs
@@ -18843,17 +21133,18 @@ CPPFLAGS=$saved_cppflags
case $ARCH in
x86|amd64)
-$as_echo "#define ERTS_STRUCTURE_ALIGNED_ALLOC 1" >>confdefs.h
+printf "%s\n" "#define ERTS_STRUCTURE_ALIGNED_ALLOC 1" >>confdefs.h
;;
*)
;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for IP version 6 support" >&5
-$as_echo_n "checking for IP version 6 support... " >&6; }
-if ${ac_cv_sys_ipv6_support+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for IP version 6 support" >&5
+printf %s "checking for IP version 6 support... " >&6; }
+if test ${ac_cv_sys_ipv6_support+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ok_so_far=yes
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -18865,23 +21156,28 @@ else
#include <netinet/in.h>
#endif
int
-main ()
+main (void)
{
struct in6_addr a6; struct sockaddr_in6 s6;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ok_so_far=yes
-else
+else $as_nop
ok_so_far=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+if test $ok_so_far = yes
+then :
-if test $ok_so_far = yes; then
ac_cv_sys_ipv6_support=yes
-else
+
+else $as_nop
+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
@@ -18892,19 +21188,21 @@ else
#include <netinet/in.h>
#endif
int
-main ()
+main (void)
{
struct in_addr6 a6; struct sockaddr_in6 s6;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_sys_ipv6_support=in_addr6
-else
+else $as_nop
ac_cv_sys_ipv6_support=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
fi
fi
@@ -18912,34 +21210,36 @@ fi
case ${ac_cv_sys_ipv6_support} in
yes)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_IN6 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IN6 1" >>confdefs.h
;;
in_addr6)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (but I am redefining in_addr6 to in6_addr)" >&5
-$as_echo "yes (but I am redefining in_addr6 to in6_addr)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (but I am redefining in_addr6 to in6_addr)" >&5
+printf "%s\n" "yes (but I am redefining in_addr6 to in6_addr)" >&6; }
-$as_echo "#define HAVE_IN6 1" >>confdefs.h
+printf "%s\n" "#define HAVE_IN6 1" >>confdefs.h
-$as_echo "#define HAVE_IN_ADDR6_STRUCT /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_IN_ADDR6_STRUCT /**/" >>confdefs.h
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for multicast support" >&5
-$as_echo_n "checking for multicast support... " >&6; }
-if ${ac_cv_sys_multicast_support+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for multicast support" >&5
+printf %s "checking for multicast support... " >&6; }
+if test ${ac_cv_sys_multicast_support+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
@@ -18950,19 +21250,20 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes$" >/dev/null 2>&1; then :
+ $EGREP "^yes$" >/dev/null 2>&1
+then :
ac_cv_sys_multicast_support=yes
-else
+else $as_nop
ac_cv_sys_multicast_support=no
fi
-rm -f conftest*
+rm -rf conftest*
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_multicast_support" >&5
-$as_echo "$ac_cv_sys_multicast_support" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_multicast_support" >&5
+printf "%s\n" "$ac_cv_sys_multicast_support" >&6; }
if test $ac_cv_sys_multicast_support = yes; then
-$as_echo "#define HAVE_MULTICAST_SUPPORT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MULTICAST_SUPPORT 1" >>confdefs.h
fi
@@ -18970,43 +21271,48 @@ fi
# Check whether --with-clock-resolution was given.
-if test "${with_clock_resolution+set}" = set; then :
+if test ${with_clock_resolution+y}
+then :
withval=$with_clock_resolution;
fi
# Check whether --with-clock-gettime-realtime-id was given.
-if test "${with_clock_gettime_realtime_id+set}" = set; then :
+if test ${with_clock_gettime_realtime_id+y}
+then :
withval=$with_clock_gettime_realtime_id;
fi
# Check whether --with-clock-gettime-monotonic-id was given.
-if test "${with_clock_gettime_monotonic_id+set}" = set; then :
+if test ${with_clock_gettime_monotonic_id+y}
+then :
withval=$with_clock_gettime_monotonic_id;
fi
# Check whether --enable-prefer-elapsed-monotonic-time-during-suspend was given.
-if test "${enable_prefer_elapsed_monotonic_time_during_suspend+set}" = set; then :
+if test ${enable_prefer_elapsed_monotonic_time_during_suspend+y}
+then :
enableval=$enable_prefer_elapsed_monotonic_time_during_suspend; case "$enableval" in
yes) prefer_elapsed_monotonic_time_during_suspend=yes ;;
*) prefer_elapsed_monotonic_time_during_suspend=no ;;
esac
-else
+else $as_nop
prefer_elapsed_monotonic_time_during_suspend=no
fi
# Check whether --enable-gettimeofday-as-os-system-time was given.
-if test "${enable_gettimeofday_as_os_system_time+set}" = set; then :
+if test ${enable_gettimeofday_as_os_system_time+y}
+then :
enableval=$enable_gettimeofday_as_os_system_time; case "$enableval" in
yes) force_gettimeofday_os_system_time=yes ;;
*) force_gettimeofday_os_system_time=no ;;
esac
-else
+else $as_nop
force_gettimeofday_os_system_time=no
fi
@@ -19021,28 +21327,28 @@ case "$with_clock_resolution" in
;;
esac
-if test "$force_gettimeofday_os_system_time" = "yes"; then
+if test "$force_gettimeofday_os_system_time" = "yes"
+then :
+
- for ac_func in gettimeofday
-do :
ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
-if test "x$ac_cv_func_gettimeofday" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETTIMEOFDAY 1
-_ACEOF
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
fi
-done
if test "$ac_cv_func_gettimeofday" = "yes"; then
-$as_echo "#define OS_SYSTEM_TIME_GETTIMEOFDAY 1" >>confdefs.h
+printf "%s\n" "#define OS_SYSTEM_TIME_GETTIMEOFDAY 1" >>confdefs.h
else
as_fn_error $? "No gettimeofday() available" "$LINENO" 5
fi
-else # $force_gettimeofday_os_system_time != yes
+else $as_nop
+
+ # $force_gettimeofday_os_system_time != yes
case "$with_clock_gettime_realtime_id" in
""|no)
@@ -19061,8 +21367,9 @@ case "$with_clock_gettime_realtime_id" in
;;
esac
-case "$with_clock_resolution-$with_clock_gettime_realtime_id" in
- high-no)
+case "$with_clock_resolution-$with_clock_gettime_realtime_id" in #(
+ high-no) :
+
default_resolution_clock_gettime_wall="CLOCK_REALTIME"
low_resolution_clock_gettime_wall="CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST"
@@ -19088,11 +21395,12 @@ case "$with_clock_resolution-$with_clock_gettime_realtime_id" in
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19101,30 +21409,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -19138,11 +21445,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
-if ${erl_cv_clock_gettime_wall_high_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
+if test ${erl_cv_clock_gettime_wall_high_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19152,7 +21460,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -19165,46 +21473,56 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_wall_high_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_wall_high_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_wall_high_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_high_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_wall_high_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_high_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_wall_high_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- check_for_clock_getres=
- else
- check_for_clock_getres=clock_getres
- fi
+ if test "$LD_MAY_BE_WEAK" = "no"
+then :
- for ac_func in $check_for_clock_getres clock_get_attributes gettimeofday
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with wall clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_wall+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
+
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
+printf %s "checking for mach clock_get_time() with wall clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_wall+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19213,7 +21531,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -19228,16 +21546,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_wall=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_wall=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
-$as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_lib=
erl_wall_clock_low_resolution=no
@@ -19269,8 +21588,10 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_func=none
;;
esac
-;;
- low-no)
+
+ ;; #(
+ low-no) :
+
default_resolution_clock_gettime_wall="CLOCK_REALTIME"
low_resolution_clock_gettime_wall="CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST"
@@ -19296,11 +21617,12 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19309,30 +21631,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -19346,11 +21667,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
-if ${erl_cv_clock_gettime_wall_low_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
+if test ${erl_cv_clock_gettime_wall_low_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19360,7 +21682,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -19373,46 +21695,56 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_wall_low_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_wall_low_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_wall_low_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_low_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_wall_low_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_low_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_wall_low_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- check_for_clock_getres=
- else
- check_for_clock_getres=clock_getres
- fi
+ if test "$LD_MAY_BE_WEAK" = "no"
+then :
- for ac_func in $check_for_clock_getres clock_get_attributes gettimeofday
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with wall clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_wall+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
+
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
+printf %s "checking for mach clock_get_time() with wall clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_wall+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19421,7 +21753,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -19436,16 +21768,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_wall=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_wall=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
-$as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_lib=
erl_wall_clock_low_resolution=no
@@ -19477,8 +21810,10 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_func=none
;;
esac
-;;
- default-no)
+
+ ;; #(
+ default-no) :
+
default_resolution_clock_gettime_wall="CLOCK_REALTIME"
low_resolution_clock_gettime_wall="CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST"
@@ -19504,11 +21839,12 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19517,30 +21853,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -19554,11 +21889,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
-if ${erl_cv_clock_gettime_wall_default_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
+if test ${erl_cv_clock_gettime_wall_default_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19568,7 +21904,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -19581,46 +21917,56 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_wall_default_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_wall_default_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_wall_default_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_default_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_wall_default_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_default_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_wall_default_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- check_for_clock_getres=
- else
- check_for_clock_getres=clock_getres
- fi
+ if test "$LD_MAY_BE_WEAK" = "no"
+then :
- for ac_func in $check_for_clock_getres clock_get_attributes gettimeofday
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with wall clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_wall+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
+
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
+printf %s "checking for mach clock_get_time() with wall clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_wall+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19629,7 +21975,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -19644,16 +21990,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_wall=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_wall=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
-$as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_lib=
erl_wall_clock_low_resolution=no
@@ -19685,8 +22032,10 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_func=none
;;
esac
-;;
- *)
+
+ ;; #(
+ *) :
+
default_resolution_clock_gettime_wall="CLOCK_REALTIME"
low_resolution_clock_gettime_wall="CLOCK_REALTIME_COARSE CLOCK_REALTIME_FAST"
@@ -19712,11 +22061,12 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19725,30 +22075,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -19762,11 +22111,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
-if ${erl_cv_clock_gettime_wall_custom_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}wall clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}wall clock type... " >&6; }
+if test ${erl_cv_clock_gettime_wall_custom_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -19776,7 +22126,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -19789,46 +22139,56 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_wall_custom_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_wall_custom_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_wall_custom_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_custom_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_wall_custom_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_wall_custom_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_wall_custom_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- check_for_clock_getres=
- else
- check_for_clock_getres=clock_getres
- fi
+ if test "$LD_MAY_BE_WEAK" = "no"
+then :
- for ac_func in $check_for_clock_getres clock_get_attributes gettimeofday
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with wall clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_wall+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
+
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with wall clock type" >&5
+printf %s "checking for mach clock_get_time() with wall clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_wall+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19837,7 +22197,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -19852,16 +22212,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_wall=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_wall=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
-$as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_wall" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_lib=
erl_wall_clock_low_resolution=no
@@ -19893,7 +22254,8 @@ $as_echo "$erl_cv_mach_clock_get_time_wall" >&6; }
erl_wall_clock_func=none
;;
esac
-;;
+
+ ;;
esac
case "$erl_wall_clock_func-$erl_wall_clock_id-$with_clock_gettime_realtime_id" in
@@ -19912,17 +22274,17 @@ case $erl_wall_clock_func in
;;
mach_clock_get_time)
-$as_echo "#define OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME 1" >>confdefs.h
+printf "%s\n" "#define OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME 1" >>confdefs.h
;;
clock_gettime)
-$as_echo "#define OS_SYSTEM_TIME_USING_CLOCK_GETTIME 1" >>confdefs.h
+printf "%s\n" "#define OS_SYSTEM_TIME_USING_CLOCK_GETTIME 1" >>confdefs.h
;;
gettimeofday)
-$as_echo "#define OS_SYSTEM_TIME_GETTIMEOFDAY 1" >>confdefs.h
+printf "%s\n" "#define OS_SYSTEM_TIME_GETTIMEOFDAY 1" >>confdefs.h
;;
*)
@@ -19931,17 +22293,14 @@ esac
if test "x$erl_wall_clock_id" != "x"; then
-cat >>confdefs.h <<_ACEOF
-#define WALL_CLOCK_ID_STR "$erl_wall_clock_id"
-_ACEOF
+printf "%s\n" "#define WALL_CLOCK_ID_STR \"$erl_wall_clock_id\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define WALL_CLOCK_ID $erl_wall_clock_id
-_ACEOF
+printf "%s\n" "#define WALL_CLOCK_ID $erl_wall_clock_id" >>confdefs.h
fi
+
fi # $force_gettimeofday_os_system_time != yes
case "$with_clock_gettime_monotonic_id" in
@@ -19970,8 +22329,9 @@ case "$with_clock_gettime_monotonic_id" in
;;
esac
-case "$with_clock_resolution-$with_clock_gettime_monotonic_id" in
- high-no)
+case "$with_clock_resolution-$with_clock_gettime_monotonic_id" in #(
+ high-no) :
+
# CLOCK_MONOTONIC is buggy on MacOS (darwin), or at least on Big Sur
# and Monterey, since it may step backwards.
@@ -20019,11 +22379,12 @@ case "$with_clock_resolution-$with_clock_gettime_monotonic_id" in
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20032,30 +22393,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -20069,11 +22429,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
-$as_echo_n "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_raw+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
+printf %s "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_raw+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20082,7 +22443,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -20095,23 +22456,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_raw=yes
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_raw=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_raw" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_raw" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_high_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_high_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20121,7 +22484,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -20134,56 +22497,70 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_high_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_high_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_monotonic_high_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_high_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_high_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_high_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_high_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- for ac_func in clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ if test "$LD_MAY_BE_WEAK" != "no"
+then :
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
- else
- for ac_func in clock_getres clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+
+
+else $as_nop
+
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
- fi
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with monotonic clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_monotonic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
+printf %s "checking for mach clock_get_time() with monotonic clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_monotonic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20192,7 +22569,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -20207,16 +22584,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_monotonic=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_monotonic=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
-$as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_monotonic" >&6; }
erl_corrected_monotonic_clock=no
case $erl_cv_clock_gettime_monotonic_high_resolution-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
@@ -20278,8 +22656,10 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
;;
esac
-;;
- low-no)
+
+ ;; #(
+ low-no) :
+
# CLOCK_MONOTONIC is buggy on MacOS (darwin), or at least on Big Sur
# and Monterey, since it may step backwards.
@@ -20327,11 +22707,12 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20340,30 +22721,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -20377,11 +22757,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
-$as_echo_n "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_raw+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
+printf %s "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_raw+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20390,7 +22771,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -20403,23 +22784,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_raw=yes
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_raw=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_raw" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_raw" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_low_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_low_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20429,7 +22812,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -20442,56 +22825,70 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_low_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_low_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_monotonic_low_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_low_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_low_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_low_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_low_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- for ac_func in clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ if test "$LD_MAY_BE_WEAK" != "no"
+then :
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
- else
- for ac_func in clock_getres clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+
+
+else $as_nop
+
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
- fi
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with monotonic clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_monotonic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
+printf %s "checking for mach clock_get_time() with monotonic clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_monotonic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20500,7 +22897,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -20515,16 +22912,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_monotonic=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_monotonic=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
-$as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_monotonic" >&6; }
erl_corrected_monotonic_clock=no
case $erl_cv_clock_gettime_monotonic_low_resolution-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
@@ -20586,8 +22984,10 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
;;
esac
-;;
- default-no)
+
+ ;; #(
+ default-no) :
+
# CLOCK_MONOTONIC is buggy on MacOS (darwin), or at least on Big Sur
# and Monterey, since it may step backwards.
@@ -20635,11 +23035,12 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20648,30 +23049,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -20685,11 +23085,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
-$as_echo_n "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_raw+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
+printf %s "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_raw+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20698,7 +23099,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -20711,23 +23112,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_raw=yes
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_raw=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_raw" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_raw" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_default_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_default_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20737,7 +23140,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -20750,56 +23153,70 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_default_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_default_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_monotonic_default_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_default_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_default_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_default_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_default_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- for ac_func in clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ if test "$LD_MAY_BE_WEAK" != "no"
+then :
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
- else
- for ac_func in clock_getres clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+
+
+else $as_nop
+
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
- fi
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with monotonic clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_monotonic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
+printf %s "checking for mach clock_get_time() with monotonic clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_monotonic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -20808,7 +23225,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -20823,16 +23240,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_monotonic=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_monotonic=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
-$as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_monotonic" >&6; }
erl_corrected_monotonic_clock=no
case $erl_cv_clock_gettime_monotonic_default_resolution-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
@@ -20894,8 +23312,10 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
;;
esac
-;;
- *)
+
+ ;; #(
+ *) :
+
# CLOCK_MONOTONIC is buggy on MacOS (darwin), or at least on Big Sur
# and Monterey, since it may step backwards.
@@ -20943,11 +23363,12 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20956,30 +23377,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -20993,11 +23413,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
-$as_echo_n "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_raw+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
+printf %s "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_raw+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21006,7 +23427,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -21019,23 +23440,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_raw=yes
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_raw=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_raw" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_raw" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_custom_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_custom_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -21045,7 +23468,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -21058,56 +23481,70 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_custom_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_custom_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_monotonic_custom_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_custom_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_custom_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_custom_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_custom_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- for ac_func in clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ if test "$LD_MAY_BE_WEAK" != "no"
+then :
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
- else
- for ac_func in clock_getres clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+
+
+else $as_nop
+
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
- fi
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with monotonic clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_monotonic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
+printf %s "checking for mach clock_get_time() with monotonic clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_monotonic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21116,7 +23553,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -21131,16 +23568,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_monotonic=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_monotonic=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
-$as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_monotonic" >&6; }
erl_corrected_monotonic_clock=no
case $erl_cv_clock_gettime_monotonic_custom_resolution-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
@@ -21202,7 +23640,8 @@ $as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
;;
esac
-;;
+
+ ;;
esac
case "$erl_monotonic_clock_func-$erl_monotonic_clock_id-$with_clock_gettime_monotonic_id" in
@@ -21218,22 +23657,22 @@ esac
case $erl_monotonic_clock_func in
times)
-$as_echo "#define OS_MONOTONIC_TIME_USING_TIMES 1" >>confdefs.h
+printf "%s\n" "#define OS_MONOTONIC_TIME_USING_TIMES 1" >>confdefs.h
;;
mach_clock_get_time)
-$as_echo "#define OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME 1" >>confdefs.h
+printf "%s\n" "#define OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME 1" >>confdefs.h
;;
clock_gettime)
-$as_echo "#define OS_MONOTONIC_TIME_USING_CLOCK_GETTIME 1" >>confdefs.h
+printf "%s\n" "#define OS_MONOTONIC_TIME_USING_CLOCK_GETTIME 1" >>confdefs.h
;;
gethrtime)
-$as_echo "#define OS_MONOTONIC_TIME_USING_GETHRTIME 1" >>confdefs.h
+printf "%s\n" "#define OS_MONOTONIC_TIME_USING_GETHRTIME 1" >>confdefs.h
;;
*)
@@ -21242,13 +23681,13 @@ esac
if test $erl_corrected_monotonic_clock = yes; then
-$as_echo "#define ERTS_HAVE_CORRECTED_OS_MONOTONIC_TIME 1" >>confdefs.h
+printf "%s\n" "#define ERTS_HAVE_CORRECTED_OS_MONOTONIC_TIME 1" >>confdefs.h
fi
if test $erl_monotonic_clock_low_resolution = yes; then
-$as_echo "#define ERTS_HAVE_LOW_RESOLUTION_OS_MONOTONIC_LOW 1" >>confdefs.h
+printf "%s\n" "#define ERTS_HAVE_LOW_RESOLUTION_OS_MONOTONIC_LOW 1" >>confdefs.h
fi
@@ -21261,20 +23700,16 @@ if test "$erl_wall_clock_lib" != ""; then
fi
if test "x$erl_monotonic_clock_id" != "x"; then
-cat >>confdefs.h <<_ACEOF
-#define MONOTONIC_CLOCK_ID_STR "$erl_monotonic_clock_id"
-_ACEOF
+printf "%s\n" "#define MONOTONIC_CLOCK_ID_STR \"$erl_monotonic_clock_id\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define MONOTONIC_CLOCK_ID $erl_monotonic_clock_id
-_ACEOF
+printf "%s\n" "#define MONOTONIC_CLOCK_ID $erl_monotonic_clock_id" >>confdefs.h
fi
if test $erl_cv_clock_gettime_monotonic_raw = yes; then
-$as_echo "#define HAVE_CLOCK_GETTIME_MONOTONIC_RAW 1" >>confdefs.h
+printf "%s\n" "#define HAVE_CLOCK_GETTIME_MONOTONIC_RAW 1" >>confdefs.h
fi
@@ -21325,11 +23760,12 @@ fi
esac
clock_gettime_lib=""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -21338,30 +23774,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
clock_gettime_lib="-lrt"
fi
@@ -21375,11 +23810,12 @@ fi
trust_test=""
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
-$as_echo_n "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_raw+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)" >&5
+printf %s "checking for clock_gettime(CLOCK_MONOTONIC_RAW, _)... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_raw+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21388,7 +23824,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -21401,23 +23837,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_raw=yes
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_raw=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_raw" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_raw" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_raw" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
-$as_echo_n "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
-if ${erl_cv_clock_gettime_monotonic_high_resolution+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime() with ${check_msg}monotonic clock type" >&5
+printf %s "checking for clock_gettime() with ${check_msg}monotonic clock type... " >&6; }
+if test ${erl_cv_clock_gettime_monotonic_high_resolution+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -21427,7 +23865,7 @@ else
$trust_test
int
-main ()
+main (void)
{
struct timespec ts;
@@ -21440,56 +23878,70 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
erl_cv_clock_gettime_monotonic_high_resolution=$clock_type
-else
+else $as_nop
erl_cv_clock_gettime_monotonic_high_resolution=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
test $erl_cv_clock_gettime_monotonic_high_resolution = no || break
done
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_high_resolution" >&5
-$as_echo "$erl_cv_clock_gettime_monotonic_high_resolution" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_clock_gettime_monotonic_high_resolution" >&5
+printf "%s\n" "$erl_cv_clock_gettime_monotonic_high_resolution" >&6; }
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- for ac_func in clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ if test "$LD_MAY_BE_WEAK" != "no"
+then :
+
+ ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
fi
-done
- else
- for ac_func in clock_getres clock_get_attributes gethrtime
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+
+else $as_nop
+
+ ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
+if test "x$ac_cv_func_clock_getres" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETRES 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "clock_get_attributes" "ac_cv_func_clock_get_attributes"
+if test "x$ac_cv_func_clock_get_attributes" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GET_ATTRIBUTES 1" >>confdefs.h
- fi
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
-$as_echo_n "checking for mach clock_get_time() with monotonic clock type... " >&6; }
-if ${erl_cv_mach_clock_get_time_monotonic+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mach clock_get_time() with monotonic clock type" >&5
+printf %s "checking for mach clock_get_time() with monotonic clock type... " >&6; }
+if test ${erl_cv_mach_clock_get_time_monotonic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21498,7 +23950,7 @@ else
#include <mach/mach.h>
int
-main ()
+main (void)
{
kern_return_t res;
@@ -21513,16 +23965,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
erl_cv_mach_clock_get_time_monotonic=yes
-else
+else $as_nop
erl_cv_mach_clock_get_time_monotonic=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
-$as_echo "$erl_cv_mach_clock_get_time_monotonic" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_cv_mach_clock_get_time_monotonic" >&5
+printf "%s\n" "$erl_cv_mach_clock_get_time_monotonic" >&6; }
erl_corrected_monotonic_clock=no
case $erl_cv_clock_gettime_monotonic_high_resolution-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
@@ -21590,19 +24043,19 @@ case $erl_monotonic_clock_low_resolution-$erl_monotonic_clock_func in
no-mach_clock_get_time)
monotonic_hrtime=yes
-$as_echo "#define SYS_HRTIME_USING_MACH_CLOCK_GET_TIME 1" >>confdefs.h
+printf "%s\n" "#define SYS_HRTIME_USING_MACH_CLOCK_GET_TIME 1" >>confdefs.h
;;
no-clock_gettime)
monotonic_hrtime=yes
-$as_echo "#define SYS_HRTIME_USING_CLOCK_GETTIME 1" >>confdefs.h
+printf "%s\n" "#define SYS_HRTIME_USING_CLOCK_GETTIME 1" >>confdefs.h
;;
no-gethrtime)
monotonic_hrtime=yes
-$as_echo "#define SYS_HRTIME_USING_GETHRTIME 1" >>confdefs.h
+printf "%s\n" "#define SYS_HRTIME_USING_GETHRTIME 1" >>confdefs.h
;;
*)
@@ -21612,28 +24065,25 @@ esac
if test $monotonic_hrtime = yes; then
-$as_echo "#define HAVE_MONOTONIC_ERTS_SYS_HRTIME 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MONOTONIC_ERTS_SYS_HRTIME 1" >>confdefs.h
fi
if test "x$erl_monotonic_clock_id" != "x"; then
-cat >>confdefs.h <<_ACEOF
-#define HRTIME_CLOCK_ID_STR "$erl_monotonic_clock_id"
-_ACEOF
+printf "%s\n" "#define HRTIME_CLOCK_ID_STR \"$erl_monotonic_clock_id\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define HRTIME_CLOCK_ID $erl_monotonic_clock_id
-_ACEOF
+printf "%s\n" "#define HRTIME_CLOCK_ID $erl_monotonic_clock_id" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if gethrvtime works and how to use it" >&5
-$as_echo_n "checking if gethrvtime works and how to use it... " >&6; }
-if test "$cross_compiling" = yes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if gethrvtime works and how to use it" >&5
+printf %s "checking if gethrvtime works and how to use it... " >&6; }
+if test "$cross_compiling" = yes
+then :
case X$erl_xcomp_gethrvtime_procfs_ioctl in
X)
@@ -21648,7 +24098,7 @@ case X$erl_xcomp_gethrvtime_procfs_ioctl in
as_fn_error $? "Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl" "$LINENO" 5;;
esac
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21701,9 +24151,10 @@ int main() {
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
erl_gethrvtime=procfs_ioctl
-else
+else $as_nop
erl_gethrvtime=false
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -21712,32 +24163,35 @@ fi
LIBRT=$xrtlib
-case $erl_gethrvtime in
- procfs_ioctl)
+if test "$erl_gethrvtime" = "procfs_ioctl"
+then :
-$as_echo "#define HAVE_GETHRVTIME_PROCFS_IOCTL 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: uses ioctl to procfs" >&5
-$as_echo "uses ioctl to procfs" >&6; }
- ;;
- *)
+printf "%s\n" "#define HAVE_GETHRVTIME_PROCFS_IOCTL 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: uses ioctl to procfs" >&5
+printf "%s\n" "uses ioctl to procfs" >&6; }
+
+else $as_nop
+
if test $erl_gethrvtime = cross; then
erl_gethrvtime=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross" >&5
-$as_echo "cross" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result 'not working' guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result 'not working' guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross" >&5
+printf "%s\n" "cross" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result 'not working' guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result 'not working' guessed because of cross compilation" >&2;}
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not working" >&5
-$as_echo "not working" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not working" >&5
+printf "%s\n" "not working" >&6; }
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if clock_gettime can be used to get thread CPU time" >&5
-$as_echo_n "checking if clock_gettime can be used to get thread CPU time... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if clock_gettime can be used to get thread CPU time" >&5
+printf %s "checking if clock_gettime can be used to get thread CPU time... " >&6; }
save_libs=$LIBS
LIBS="-lrt"
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
case X$erl_xcomp_clock_gettime_cpu_time in
X) erl_clock_gettime_cpu_time=cross;;
@@ -21745,7 +24199,7 @@ $as_echo_n "checking if clock_gettime can be used to get thread CPU time... " >&
*) as_fn_error $? "Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time" "$LINENO" 5;;
esac
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21773,9 +24227,10 @@ else
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
erl_clock_gettime_cpu_time=yes
-else
+else $as_nop
erl_clock_gettime_cpu_time=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -21783,34 +24238,35 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
LIBS=$save_libs
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $erl_clock_gettime_cpu_time" >&5
-$as_echo "$erl_clock_gettime_cpu_time" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $erl_clock_gettime_cpu_time" >&5
+printf "%s\n" "$erl_clock_gettime_cpu_time" >&6; }
case $erl_clock_gettime_cpu_time in
yes)
-$as_echo "#define HAVE_CLOCK_GETTIME_CPU_TIME /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_CLOCK_GETTIME_CPU_TIME /**/" >>confdefs.h
LIBRT=-lrt
;;
cross)
erl_clock_gettime_cpu_time=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result no guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result no guessed because of cross compilation" >&2;}
;;
*)
;;
esac
- ;;
-esac
+
+fi
# Extract the first word of "m4", so it can be a program name with args.
set dummy m4; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_M4+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_M4+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$M4"; then
ac_cv_prog_M4="$M4" # Let the user override the test.
else
@@ -21818,11 +24274,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_M4="m4"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -21833,35 +24293,45 @@ fi
fi
M4=$ac_cv_prog_M4
if test -n "$M4"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
-$as_echo "$M4" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
+printf "%s\n" "$M4" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
JIT_ARCH=
-if test ${enable_jit} != no; then
+
+if test ${enable_jit} != no
+then :
+
case "$ARCH" in
amd64)
JIT_ARCH=x86
;;
+ arm64)
+ JIT_ARCH=arm
+ ;;
*)
if test ${enable_jit} = yes; then
- as_fn_error $? "JIT only works on x86 64-bit" "$LINENO" 5
+ as_fn_error $? "JIT only works on x86 64-bit and ARM 64-bit" "$LINENO" 5
else
enable_jit=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: JIT disabled due to lack to support on $ARCH-$OPSYS" >&5
-$as_echo "$as_me: WARNING: JIT disabled due to lack to support on $ARCH-$OPSYS" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: JIT disabled due to lack to support on $ARCH-$OPSYS" >&5
+printf "%s\n" "$as_me: WARNING: JIT disabled due to lack to support on $ARCH-$OPSYS" >&2;}
fi
;;
esac
- if test ${enable_jit} != no; then
- if test "$CXX" != false; then
+ if test ${enable_jit} != no
+then :
+
+ if test "$CXX" != false
+then :
+
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -21870,269 +24340,11 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
old_CXXFLAGS=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -std=c++17"
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-if test -z "$CXX"; then
- if test -n "$CCC"; then
- CXX=$CCC
- else
- if test -n "$ac_tool_prefix"; then
- for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CXX"; then
- ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CXX=$ac_cv_prog_CXX
-if test -n "$CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
-$as_echo "$CXX" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$CXX" && break
- done
-fi
-if test -z "$CXX"; then
- ac_ct_CXX=$CXX
- for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CXX"; then
- ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CXX="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
-if test -n "$ac_ct_CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
-$as_echo "$ac_ct_CXX" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$ac_ct_CXX" && break
-done
-
- if test "x$ac_ct_CXX" = x; then
- CXX="g++"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CXX=$ac_ct_CXX
- fi
-fi
-
- fi
-fi
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
- { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compiler $ac_option >&5") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- sed '10a\
-... rest of stderr output deleted ...
- 10q' conftest.err >conftest.er1
- cat conftest.er1 >&5
- fi
- rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
-$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if ${ac_cv_cxx_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
-{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- ac_compiler_gnu=yes
-else
- ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
-$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
- GXX=yes
-else
- GXX=
-fi
-ac_test_CXXFLAGS=${CXXFLAGS+set}
-ac_save_CXXFLAGS=$CXXFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
-$as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if ${ac_cv_prog_cxx_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_save_cxx_werror_flag=$ac_cxx_werror_flag
- ac_cxx_werror_flag=yes
- ac_cv_prog_cxx_g=no
- CXXFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- ac_cv_prog_cxx_g=yes
-else
- CXXFLAGS=""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-
-else
- ac_cxx_werror_flag=$ac_save_cxx_werror_flag
- CXXFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- ac_cv_prog_cxx_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_cxx_werror_flag=$ac_save_cxx_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
-$as_echo "$ac_cv_prog_cxx_g" >&6; }
-if test "$ac_test_CXXFLAGS" = set; then
- CXXFLAGS=$ac_save_CXXFLAGS
-elif test $ac_cv_prog_cxx_g = yes; then
- if test "$GXX" = yes; then
- CXXFLAGS="-g -O2"
- else
- CXXFLAGS="-g"
- fi
-else
- if test "$GXX" = yes; then
- CXXFLAGS="-O2"
- else
- CXXFLAGS=
- fi
-fi
-ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
+main (void)
{
#if __cplusplus < 201703L
#error "Needs C++17 compiler"
@@ -22141,27 +24353,29 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++17 support" >&5
-$as_echo_n "checking for C++17 support... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+if ac_fn_cxx_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++17 support" >&5
+printf %s "checking for C++17 support... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
HAVE_CXX17=true
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++17 support" >&5
-$as_echo_n "checking for C++17 support... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++17 support" >&5
+printf %s "checking for C++17 support... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
HAVE_CXX17=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- fi
+
+fi
if test "$CXX" = false -o "$HAVE_CXX17" = false; then
if test ${enable_jit} = yes; then
as_fn_error $? "JIT needs a C++ compiler with C++17 support" "$LINENO" 5
@@ -22171,39 +24385,48 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
JIT disabled due to lack of compiler with C++17 support
EOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: JIT disable due to lack of C++ compiler with C++17 support" >&5
-$as_echo "$as_me: WARNING: JIT disable due to lack of C++ compiler with C++17 support" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: JIT disable due to lack of C++ compiler with C++17 support" >&5
+printf "%s\n" "$as_me: WARNING: JIT disable due to lack of C++ compiler with C++17 support" >&2;}
fi
fi
- fi
+
+fi
if test ${enable_jit} != no; then
enable_jit=yes
fi
+
fi
-if test ${enable_jit} != no; then
- case $host_os in
- openbsd*)
+if test ${enable_jit} != no
+then :
+
+ case $host_os in #(
+ openbsd*) :
+
# Whenever the kernel is entered (page faults, system calls, etc),
# OpenBSD checks whether the stack pointer is in an area allocated with
# MAP_STACK, so we can't use the native stack for Erlang code.
#
# https://undeadly.org/cgi?action=article;sid=20180310000858
- enable_native_stack=no;;
- win32*)
+ enable_native_stack=no
+ ;; #(
+ win32*) :
+
# Windows never messes with the stack, so it's safe by default.
- enable_native_stack=yes;;
- *)
+ enable_native_stack=yes
+ ;; #(
+ *) :
+
# Use the native stack if we can safely redirect OS signals to a
# different stack.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for safe signal delivery" >&5
-$as_echo_n "checking for safe signal delivery... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for safe signal delivery" >&5
+printf %s "checking for safe signal delivery... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <signal.h>
int
-main ()
+main (void)
{
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
#define __DARWIN__ 1
@@ -22215,30 +24438,50 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
enable_native_stack=yes
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, disabling native stack in JIT" >&5
-$as_echo "no, disabling native stack in JIT" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, disabling native stack in JIT" >&5
+printf "%s\n" "no, disabling native stack in JIT" >&6; }
enable_native_stack=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext;;
- esac
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
- if test X${enable_native_stack} = Xyes; then
+ case "$JIT_ARCH" in
+ x86)
+ if test X${enable_native_stack} = Xyes; then
-$as_echo "#define NATIVE_ERLANG_STACK /**/" >>confdefs.h
+printf "%s\n" "#define NATIVE_ERLANG_STACK /**/" >>confdefs.h
+
+ fi
+ ;;
+ arm)
+ # ARM JIT doesn't support native stack due to its 16-byte alignment
+ # requirement.
+ enable_native_stack=no
+ ;;
+ *)
+ ;;
+ esac
- fi
fi
case $OPSYS in
linux*)
+ if test X${enable_native_stack} = Xyes; then
+
+printf "%s\n" "#define ERLANG_FRAME_POINTERS /**/" >>confdefs.h
+
+ fi
+
-$as_echo "#define HAVE_LINUX_PERF_SUPPORT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_LINUX_PERF_SUPPORT 1" >>confdefs.h
;;
*)
@@ -22246,19 +24489,19 @@ $as_echo "#define HAVE_LINUX_PERF_SUPPORT 1" >>confdefs.h
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to redefine FD_SETSIZE" >&5
-$as_echo_n "checking whether to redefine FD_SETSIZE... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to redefine FD_SETSIZE" >&5
+printf %s "checking whether to redefine FD_SETSIZE... " >&6; }
case $host_os in
bsdi*)
-$as_echo "#define REDEFINE_FD_SETSIZE /**/" >>confdefs.h
+printf "%s\n" "#define REDEFINE_FD_SETSIZE /**/" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
;;
esac
@@ -22283,15 +24526,20 @@ fi
#
# Check for working poll().
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working poll()" >&5
-$as_echo_n "checking for working poll()... " >&6; }
-if test "x$ac_cv_header_poll_h" != "xyes" -o "x$ac_cv_func_poll" != "xyes"; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working poll()" >&5
+printf %s "checking for working poll()... " >&6; }
+if test "x$ac_cv_header_poll_h" != "xyes" -o "x$ac_cv_func_poll" != "xyes"
+then :
+
poll_works=no
-else
-if test "$cross_compiling" = yes; then :
+else $as_nop
+
+
+if test "$cross_compiling" = yes
+then :
case X$erl_xcomp_poll in
X) poll_works=cross;;
@@ -22299,7 +24547,7 @@ case X$erl_xcomp_poll in
*) as_fn_error $? "Bad erl_xcomp_poll value: $erl_xcomp_poll" "$LINENO" 5;;
esac
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -22323,9 +24571,10 @@ main()
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
poll_works=yes
-else
+else $as_nop
poll_works=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -22333,6 +24582,7 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
+
fi
case $poll_works-$host_os in
@@ -22342,30 +24592,30 @@ case $poll_works-$host_os in
# be used by erts).
#
-$as_echo "#define USE_SELECT 1" >>confdefs.h
+printf "%s\n" "#define USE_SELECT 1" >>confdefs.h
if test $poll_works = cross; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross" >&5
-$as_echo "cross" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed based on OS ($host_os) because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result no guessed based on OS ($host_os) because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross" >&5
+printf "%s\n" "cross" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed based on OS ($host_os) because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result no guessed based on OS ($host_os) because of cross compilation" >&2;}
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no; non-existing, broken, or based on select()" >&5
-$as_echo "no; non-existing, broken, or based on select()" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no; non-existing, broken, or based on select()" >&5
+printf "%s\n" "no; non-existing, broken, or based on select()" >&6; }
fi
poll_works=no;;
yes-*|cross-*)
-$as_echo "#define ERTS_USE_POLL 1" >>confdefs.h
+printf "%s\n" "#define ERTS_USE_POLL 1" >>confdefs.h
if test $poll_works = cross; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross" >&5
-$as_echo "cross" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed based on OS ($host_os) because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed based on OS ($host_os) because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross" >&5
+printf "%s\n" "cross" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed based on OS ($host_os) because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed based on OS ($host_os) because of cross compilation" >&2;}
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
fi
poll_works=yes;;
esac
@@ -22376,33 +24626,35 @@ esac
if test $have_kernel_poll = kqueue; then
## Some OS X kernel version seems to have bugs in them with regards to kqueue
## Disable kernel poll on those versions
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether host os has known kqueue bugs" >&5
-$as_echo_n "checking whether host os has known kqueue bugs... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether host os has known kqueue bugs" >&5
+printf %s "checking whether host os has known kqueue bugs... " >&6; }
case $host_os in
# Any OS X version < 16 has known problems with using kqueue
# so we don't use it there. See erl_poll.c for details.
darwin[0-9].*|darwin1[0-5].*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, disabling kernel poll" >&5
-$as_echo "yes, disabling kernel poll" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, disabling kernel poll" >&5
+printf "%s\n" "yes, disabling kernel poll" >&6; }
have_kernel_poll=no
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
;;
esac
fi
#
# If epoll() found, check that it is level triggered.
#
-if test $have_kernel_poll = epoll; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether epoll is level triggered" >&5
-$as_echo_n "checking whether epoll is level triggered... " >&6; }
+if test $have_kernel_poll = epoll
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether epoll is level triggered" >&5
+printf %s "checking whether epoll is level triggered... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/epoll.h>
int
-main ()
+main (void)
{
#ifdef EPOLLET
@@ -22419,49 +24671,51 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
level_triggered_epoll=yes
-else
+else $as_nop
level_triggered_epoll=no
have_kernel_poll=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $level_triggered_epoll" >&5
-$as_echo "$level_triggered_epoll" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $level_triggered_epoll" >&5
+printf "%s\n" "$level_triggered_epoll" >&6; }
+
fi
#
# Check if we should enable kernel poll support
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether kernel poll support should be enabled" >&5
-$as_echo_n "checking whether kernel poll support should be enabled... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether kernel poll support should be enabled" >&5
+printf %s "checking whether kernel poll support should be enabled... " >&6; }
ERTS_ENABLE_KERNEL_POLL=no
ERTS_BUILD_FALLBACK_POLL=no
case $enable_kernel_poll-$have_kernel_poll in
no-*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no; disabled by user" >&5
-$as_echo "no; disabled by user" >&6; };;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no; disabled by user" >&5
+printf "%s\n" "no; disabled by user" >&6; };;
yes-no)
as_fn_error $? "no; kernel poll support requested but not found" "$LINENO" 5;;
*-no)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; };;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; };;
*)
case $have_kernel_poll in
epoll)
-$as_echo "#define HAVE_SYS_EPOLL_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SYS_EPOLL_H 1" >>confdefs.h
ERTS_BUILD_FALLBACK_POLL=yes
;;
/dev/poll)
-$as_echo "#define HAVE_SYS_DEVPOLL_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SYS_DEVPOLL_H 1" >>confdefs.h
;;
kqueue)
-$as_echo "#define HAVE_SYS_EVENT_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SYS_EVENT_H 1" >>confdefs.h
ERTS_BUILD_FALLBACK_POLL=yes
;;
@@ -22470,16 +24724,17 @@ $as_echo "#define HAVE_SYS_EVENT_H 1" >>confdefs.h
esac
ERTS_ENABLE_KERNEL_POLL=yes
-$as_echo "#define ERTS_ENABLE_KERNEL_POLL 1" >>confdefs.h
+printf "%s\n" "#define ERTS_ENABLE_KERNEL_POLL 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes; $have_kernel_poll" >&5
-$as_echo "yes; $have_kernel_poll" >&6; };;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes; $have_kernel_poll" >&5
+printf "%s\n" "yes; $have_kernel_poll" >&6; };;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether putenv() stores a copy of the key-value pair" >&5
-$as_echo_n "checking whether putenv() stores a copy of the key-value pair... " >&6; }
-if test "$cross_compiling" = yes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether putenv() stores a copy of the key-value pair" >&5
+printf %s "checking whether putenv() stores a copy of the key-value pair... " >&6; }
+if test "$cross_compiling" = yes
+then :
case X$erl_xcomp_putenv_copy in
X) copying_putenv=cross;;
@@ -22487,7 +24742,7 @@ case X$erl_xcomp_putenv_copy in
*) as_fn_error $? "Bad erl_xcomp_putenv_copy value: $erl_xcomp_putenv_copy" "$LINENO" 5;;
esac
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -22522,9 +24777,10 @@ int main(void) {
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
copying_putenv=yes
-else
+else $as_nop
copying_putenv=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -22532,32 +24788,33 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $copying_putenv" >&5
-$as_echo "$copying_putenv" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $copying_putenv" >&5
+printf "%s\n" "$copying_putenv" >&6; }
case $copying_putenv in
yes)
-$as_echo "#define HAVE_COPYING_PUTENV 1" >>confdefs.h
+printf "%s\n" "#define HAVE_COPYING_PUTENV 1" >>confdefs.h
;;
cross)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result no guessed because of cross compilation" >&2;};;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result no guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result no guessed because of cross compilation" >&2;};;
*) ;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a compiler that handles jumptables" >&5
-$as_echo_n "checking for a compiler that handles jumptables... " >&6; }
-if ${ac_cv_prog_emu_cc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a compiler that handles jumptables" >&5
+printf %s "checking for a compiler that handles jumptables... " >&6; }
+if test ${ac_cv_prog_emu_cc+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if defined(__clang_major__) && __clang_major__ >= 3
@@ -22583,12 +24840,13 @@ lbl2:
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_emu_cc="$CC"
-else
+else $as_nop
ac_cv_prog_emu_cc=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test "$ac_cv_prog_emu_cc" = no; then
for ac_progname in emu_cc.sh gcc-4.2 gcc; do
@@ -22608,7 +24866,9 @@ if test "$ac_cv_prog_emu_cc" = no; then
done
fi
-if test "$ac_cv_prog_emu_cc" != no; then
+if test "$ac_cv_prog_emu_cc" != no
+then :
+
save_CC="$CC"
save_CFLAGS=$CFLAGS
save_CPPFLAGS=$CPPFLAGS
@@ -22619,7 +24879,7 @@ if test "$ac_cv_prog_emu_cc" != no; then
/* end confdefs.h. */
int
-main ()
+main (void)
{
#if defined(__clang_major__) && __clang_major__ >= 3
@@ -22645,23 +24905,25 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_emu_cc="$CC"
-else
+else $as_nop
ac_cv_prog_emu_cc=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CC=$save_CC
CFLAGS=$save_CFLAGS
CPPFLAGS=$save_CPPFLAGS
+
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_emu_cc" >&5
-$as_echo "$ac_cv_prog_emu_cc" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_emu_cc" >&5
+printf "%s\n" "$ac_cv_prog_emu_cc" >&6; }
if test "$ac_cv_prog_emu_cc" = no; then
-$as_echo "#define NO_JUMP_TABLE /**/" >>confdefs.h
+printf "%s\n" "#define NO_JUMP_TABLE /**/" >>confdefs.h
EMU_CC="$CC"
else
@@ -22670,16 +24932,18 @@ fi
-case $DYNAMIC_TRACE_FRAMEWORK in
- dtrace|systemtap)
+case $DYNAMIC_TRACE_FRAMEWORK in #(
+ dtrace|systemtap) :
+
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}dtrace", so it can be a program name with args.
set dummy ${ac_tool_prefix}dtrace; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DTRACE+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DTRACE+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$DTRACE"; then
ac_cv_prog_DTRACE="$DTRACE" # Let the user override the test.
else
@@ -22687,11 +24951,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DTRACE="${ac_tool_prefix}dtrace"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -22702,11 +24970,11 @@ fi
fi
DTRACE=$ac_cv_prog_DTRACE
if test -n "$DTRACE"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
-$as_echo "$DTRACE" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
+printf "%s\n" "$DTRACE" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -22715,11 +24983,12 @@ if test -z "$ac_cv_prog_DTRACE"; then
ac_ct_DTRACE=$DTRACE
# Extract the first word of "dtrace", so it can be a program name with args.
set dummy dtrace; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DTRACE+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DTRACE+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_DTRACE"; then
ac_cv_prog_ac_ct_DTRACE="$ac_ct_DTRACE" # Let the user override the test.
else
@@ -22727,11 +24996,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DTRACE="dtrace"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -22742,11 +25015,11 @@ fi
fi
ac_ct_DTRACE=$ac_cv_prog_ac_ct_DTRACE
if test -n "$ac_ct_DTRACE"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DTRACE" >&5
-$as_echo "$ac_ct_DTRACE" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DTRACE" >&5
+printf "%s\n" "$ac_ct_DTRACE" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DTRACE" = x; then
@@ -22754,8 +25027,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DTRACE=$ac_ct_DTRACE
@@ -22766,13 +25039,18 @@ fi
test "$DTRACE" = "none" && as_fn_error $? "No dtrace utility found." "$LINENO" 5;
enable_lttng_test=no
- enable_dtrace_test=yes;;
- lttng)
+ enable_dtrace_test=yes
+ ;; #(
+ lttng) :
+
enable_lttng_test=yes
- enable_dtrace_test=no;;
- *)
+ enable_dtrace_test=no
+ ;; #(
+ *) :
+
enable_lttng_test=no
- enable_dtrace_test=no;;
+ enable_dtrace_test=no
+ ;;
esac
@@ -22797,43 +25075,43 @@ case $OPSYS in
: # Nothing to do
;;
esac
-if test "$enable_dtrace_test" = "yes" ; then
- if test "$DTRACE" = "dtrace" ; then
- for ac_header in sys/sdt.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_sdt_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_SDT_H 1
-_ACEOF
+if test "$enable_dtrace_test" = "yes"
+then :
-fi
+ if test "$DTRACE" = "dtrace"
+then :
-done
+ ac_fn_c_check_header_compile "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sdt_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SDT_H 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 1-stage DTrace precompilation" >&5
-$as_echo_n "checking for 1-stage DTrace precompilation... " >&6; }
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 1-stage DTrace precompilation" >&5
+printf %s "checking for 1-stage DTrace precompilation... " >&6; }
# 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
as_fn_error $? "Could not precompile erlang_dtrace.d: dtrace -h failed" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 2-stage DTrace precompilation" >&5
-$as_echo_n "checking for 2-stage DTrace precompilation... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 2-stage DTrace precompilation" >&5
+printf %s "checking for 2-stage DTrace precompilation... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include "foo-dtrace.h"
int
-main ()
+main (void)
{
ERLANG_DIST_PORT_BUSY_ENABLED();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
rm -f $DTRACE_2STEP_TEST
dtrace -G $DTRACE_CPP $DTRACE_BITS_FLAG -Iemulator/beam -o $DTRACE_2STEP_TEST -s emulator/beam/erlang_dtrace.d conftest.$OBJEXT 2>&5
if test -f $DTRACE_2STEP_TEST; then
@@ -22841,14 +25119,15 @@ if ac_fn_c_try_compile "$LINENO"; then :
DTRACE_ENABLED_2STEP=yes
fi
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
rm -f foo-dtrace.h
- if test "x$DTRACE_ENABLED_2STEP" = "xyes"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ if test "x$DTRACE_ENABLED_2STEP" = "xyes"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
DTRACE_ENABLED=yes
@@ -22863,38 +25142,34 @@ fi
LIBS="$LIBS -ldtrace"
;;
esac
- else
+
+else $as_nop
+
as_fn_error $? "Dtrace preprocessing test failed." "$LINENO" 5
- fi
-fi
-if test "$enable_lttng_test" = "yes" ; then
- for ac_header in lttng/tracepoint.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "lttng/tracepoint.h" "ac_cv_header_lttng_tracepoint_h" "$ac_includes_default"
-if test "x$ac_cv_header_lttng_tracepoint_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LTTNG_TRACEPOINT_H 1
-_ACEOF
+fi
fi
-done
+if test "$enable_lttng_test" = "yes"
+then :
- for ac_header in lttng/tracepoint-event.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "lttng/tracepoint-event.h" "ac_cv_header_lttng_tracepoint_event_h" "$ac_includes_default"
-if test "x$ac_cv_header_lttng_tracepoint_event_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LTTNG_TRACEPOINT_EVENT_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "lttng/tracepoint.h" "ac_cv_header_lttng_tracepoint_h" "$ac_includes_default"
+if test "x$ac_cv_header_lttng_tracepoint_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LTTNG_TRACEPOINT_H 1" >>confdefs.h
fi
-done
+ ac_fn_c_check_header_compile "$LINENO" "lttng/tracepoint-event.h" "ac_cv_header_lttng_tracepoint_event_h" "$ac_includes_default"
+if test "x$ac_cv_header_lttng_tracepoint_event_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LTTNG_TRACEPOINT_EVENT_H 1" >>confdefs.h
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tracepoint_enabled in lttng/tracepoint.h" >&5
-$as_echo_n "checking for tracepoint_enabled in lttng/tracepoint.h... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tracepoint_enabled in lttng/tracepoint.h" >&5
+printf %s "checking for tracepoint_enabled in lttng/tracepoint.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <lttng/tracepoint.h>
@@ -22907,20 +25182,21 @@ $as_echo_n "checking for tracepoint_enabled in lttng/tracepoint.h... " >&6; }
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
int
-main ()
+main (void)
{
if(tracepoint_enabled(org_erlang_otp,dummy)) do {} while(0)
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
as_fn_error $? "no (available in lttng-ust v2.7)" "$LINENO" 5
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test "x$ac_cv_header_lttng_tracepoint_h" = "xyes" \
-a "x$ac_cv_header_lttng_tracepoint_event_h" = "xyes"; then
# No straight forward way to test for liblttng-ust when no public symbol exists,
@@ -22929,6 +25205,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
as_fn_error $? "No LTTng support found." "$LINENO" 5
fi
+
fi
@@ -22938,11 +25215,12 @@ fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
-$as_echo_n "checking for kstat_open in -lkstat... " >&6; }
-if ${ac_cv_lib_kstat_kstat_open+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
+printf %s "checking for kstat_open in -lkstat... " >&6; }
+if test ${ac_cv_lib_kstat_kstat_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lkstat $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -22951,30 +25229,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char kstat_open ();
int
-main ()
+main (void)
{
return kstat_open ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_kstat_kstat_open=yes
-else
+else $as_nop
ac_cv_lib_kstat_kstat_open=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
-$as_echo "$ac_cv_lib_kstat_kstat_open" >&6; }
-if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
+printf "%s\n" "$ac_cv_lib_kstat_kstat_open" >&6; }
+if test "x$ac_cv_lib_kstat_kstat_open" = xyes
+then :
use_cpu_sup=yes
CPU_SUP_LIBS="$CPU_SUP_LIBS -lkstat"
@@ -22982,11 +25259,12 @@ if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then :
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_open in -lkvm" >&5
-$as_echo_n "checking for kvm_open in -lkvm... " >&6; }
-if ${ac_cv_lib_kvm_kvm_open+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for kvm_open in -lkvm" >&5
+printf %s "checking for kvm_open in -lkvm... " >&6; }
+if test ${ac_cv_lib_kvm_kvm_open+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lkvm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -22995,30 +25273,29 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char kvm_open ();
int
-main ()
+main (void)
{
return kvm_open ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_kvm_kvm_open=yes
-else
+else $as_nop
ac_cv_lib_kvm_kvm_open=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_open" >&5
-$as_echo "$ac_cv_lib_kvm_kvm_open" >&6; }
-if test "x$ac_cv_lib_kvm_kvm_open" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_open" >&5
+printf "%s\n" "$ac_cv_lib_kvm_kvm_open" >&6; }
+if test "x$ac_cv_lib_kvm_kvm_open" = xyes
+then :
use_cpu_sup=yes
CPU_SUP_LIBS="$CPU_SUP_LIBS -lkvm"
@@ -23045,7 +25322,8 @@ fi
# Check whether --with-javac was given.
-if test "${with_javac+set}" = set; then :
+if test ${with_javac+y}
+then :
withval=$with_javac;
fi
@@ -23078,11 +25356,12 @@ for ac_prog in $check_javac
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_JAVAC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_JAVAC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$JAVAC"; then
ac_cv_prog_JAVAC="$JAVAC" # Let the user override the test.
else
@@ -23090,11 +25369,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_JAVAC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -23105,23 +25388,26 @@ fi
fi
JAVAC=$ac_cv_prog_JAVAC
if test -n "$JAVAC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
-$as_echo "$JAVAC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+printf "%s\n" "$JAVAC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
test -n "$JAVAC" && break
done
-if test -n "$JAVAC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JDK version 1.6" >&5
-$as_echo_n "checking for JDK version 1.6... " >&6; }
-if ${ac_cv_prog_javac_ver_1_6+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test -n "$JAVAC"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for JDK version 1.6" >&5
+printf %s "checking for JDK version 1.6... " >&6; }
+if test ${ac_cv_prog_javac_ver_1_6+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
java_link='$JAVAC conftest.java 1>&5'
cat > conftest.java <<EOF
@@ -23132,24 +25418,32 @@ EOF
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$java_link\""; } >&5
(eval $java_link) 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && test -s conftest.class; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest.class
+then :
+
rm -rf conftest*
ac_cv_prog_javac_ver_1_6=yes
-else
+
+
+else $as_nop
+
echo "configure: failed program was:" 1>&5
cat conftest.java 1>&5
echo "configure: PATH was $PATH" 1>&5
rm -rf conftest*
ac_cv_prog_javac_ver_1_6=no
+
+
fi
rm -f conftest*
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_ver_1_6" >&5
-$as_echo "$ac_cv_prog_javac_ver_1_6" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_ver_1_6" >&5
+printf "%s\n" "$ac_cv_prog_javac_ver_1_6" >&6; }
if test $ac_cv_prog_javac_ver_1_6 = no; then
unset -v JAVAC
fi
+
fi
if test -z "$JAVAC"; then
@@ -23157,8 +25451,8 @@ if test -z "$JAVAC"; then
as_fn_error $? "No java compiler found in PATH (checked for $check_javac)" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find any usable java compiler, will skip: jinterface" >&5
-$as_echo "$as_me: WARNING: Could not find any usable java compiler, will skip: jinterface" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Could not find any usable java compiler, will skip: jinterface" >&5
+printf "%s\n" "$as_me: WARNING: Could not find any usable java compiler, will skip: jinterface" >&2;}
for a in $need_java ; do
echo "No Java compiler found" > $ERL_TOP/lib/$a/SKIP
@@ -23167,115 +25461,6 @@ fi
fi # end - try to find javac
-
-if test -n "$ac_tool_prefix"; then
- for ac_prog in $CCC c++ g++ CC cxx cc++ cl
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CXX"; then
- ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CXX=$ac_cv_prog_CXX
-if test -n "$CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
-$as_echo "$CXX" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$CXX" && break
- done
-fi
-if test -z "$CXX"; then
- ac_ct_CXX=$CXX
- for ac_prog in $CCC c++ g++ CC cxx cc++ cl
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CXX"; then
- ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CXX="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
-if test -n "$ac_ct_CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
-$as_echo "$ac_ct_CXX" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$ac_ct_CXX" && break
-done
-
- if test "x$ac_ct_CXX" = x; then
- CXX="false"
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CXX=$ac_ct_CXX
- fi
-fi
-
-
-# Remove SKIP file from previous run
-rm -f $ERL_TOP/lib/orber/SKIP
-
-if test "$CXX" = false; then
- echo "No C++ compiler found" > $ERL_TOP/lib/orber/SKIP
-fi
-
CFLAGS="$CFLAGS $CPPFLAGS"
#
@@ -23302,9 +25487,7 @@ fi
-cat >>confdefs.h <<_ACEOF
-#define ERTS_EMU_CMDLINE_FLAGS "$STATIC_CFLAGS $CFLAGS $DEBUG_CFLAGS $EMU_THR_DEFS $DEFS $WERRORFLAGS $WFLAGS"
-_ACEOF
+printf "%s\n" "#define ERTS_EMU_CMDLINE_FLAGS \"$STATIC_CFLAGS $CFLAGS $DEBUG_CFLAGS $EMU_THR_DEFS $DEFS $WERRORFLAGS $WFLAGS\"" >>confdefs.h
@@ -23330,16 +25513,12 @@ done
-for ac_func in log2
-do :
- ac_fn_c_check_func "$LINENO" "log2" "ac_cv_func_log2"
-if test "x$ac_cv_func_log2" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LOG2 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "log2" "ac_cv_func_log2"
+if test "x$ac_cv_func_log2" = xyes
+then :
+ printf "%s\n" "#define HAVE_LOG2 1" >>confdefs.h
fi
-done
@@ -23349,7 +25528,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"")
@@ -23359,12 +25538,13 @@ _Pragma("GCC diagnostic push")
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-$as_echo "#define HAVE_GCC_DIAG_IGNORE_WADDRESS_OF_PACKED_MEMBER 1" >>confdefs.h
+printf "%s\n" "#define HAVE_GCC_DIAG_IGNORE_WADDRESS_OF_PACKED_MEMBER 1" >>confdefs.h
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS="$saved_CFLAGS"
@@ -23376,7 +25556,8 @@ fi
# Check whether --enable-sanitizers was given.
-if test "${enable_sanitizers+set}" = set; then :
+if test ${enable_sanitizers+y}
+then :
enableval=$enable_sanitizers;
case "$enableval" in
no) sanitizers= ;;
@@ -23390,13 +25571,41 @@ fi
+# Check whether --enable-deterministic-build was given.
+if test ${enable_deterministic_build+y}
+then :
+ enableval=$enable_deterministic_build; case "$enableval" in
+ no) ERL_DETERMINISTIC=no ;;
+ *) ERL_DETERMINISTIC=yes ;;
+ esac
+else $as_nop
+ ERL_DETERMINISTIC=no
+fi
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking CFLAGS for -O switch" >&5
+printf %s "checking CFLAGS for -O switch... " >&6; }
+no_opt_CFLAGS=$(echo " $CFLAGS" | sed 's/ -O[^ ]*/ /g')
+if test "X $CFLAGS" = "X$no_opt_CFLAGS"; then
+ as_fn_error $? "
+ CFLAGS must contain a -O flag. If you need to edit the CFLAGS you probably
+ also want to add the default CFLAGS. The default CFLAGS are \"-O2 -g\".
+ If you want to build ERTS without any optimization, pass -O0 to CFLAGS." "$LINENO" 5
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+DEBUG_CFLAGS="-g -O0 $no_opt_CFLAGS"
+
+
+
ac_config_files="$ac_config_files emulator/$host/Makefile:emulator/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 include/internal/$host/erts_internal.mk:include/internal/erts_internal.mk.in lib_src/$host/Makefile:lib_src/Makefile.in ../make/$host/otp.mk:../make/otp.mk.in"
ac_config_files="$ac_config_files ../make/make_emakefile:../make/make_emakefile.in"
-ac_config_files="$ac_config_files ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in"
+ac_config_files="$ac_config_files ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in"
ac_config_files="$ac_config_files ../make/install_dir_data.sh:../make/install_dir_data.sh.in"
@@ -23429,8 +25638,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -23460,15 +25669,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -23482,8 +25691,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -23500,7 +25709,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -23518,8 +25727,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -23542,14 +25751,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -23559,46 +25770,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -23607,13 +25818,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -23622,8 +25826,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -23635,30 +25843,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -23671,13 +25859,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -23704,18 +25893,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -23727,12 +25918,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -23763,7 +25955,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -23785,6 +25977,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -23798,6 +25994,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -23839,7 +26041,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -23848,7 +26050,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -23911,7 +26113,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -23969,14 +26171,16 @@ $config_headers
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -24014,15 +26218,15 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
@@ -24030,7 +26234,7 @@ do
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
@@ -24039,7 +26243,7 @@ do
as_fn_error $? "ambiguous option: \`$1'
Try \`$0 --help' for more information.";;
--help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -24067,7 +26271,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -24081,7 +26285,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -24107,7 +26311,6 @@ do
"../make/make_emakefile") CONFIG_FILES="$CONFIG_FILES ../make/make_emakefile:../make/make_emakefile.in" ;;
"../lib/os_mon/c_src/$host/Makefile") CONFIG_FILES="$CONFIG_FILES ../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in" ;;
"../lib/runtime_tools/c_src/$host/Makefile") CONFIG_FILES="$CONFIG_FILES ../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in" ;;
- "../lib/tools/c_src/$host/Makefile") CONFIG_FILES="$CONFIG_FILES ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in" ;;
"../make/install_dir_data.sh") CONFIG_FILES="$CONFIG_FILES ../make/install_dir_data.sh:../make/install_dir_data.sh.in" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -24120,8 +26323,8 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -24457,7 +26660,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -24465,17 +26668,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -24492,7 +26695,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -24516,9 +26719,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -24575,8 +26778,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -24619,9 +26822,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -24637,20 +26840,20 @@ which seems to be undefined. Please make sure it is defined" >&2;}
#
if test x"$ac_file" != x-; then
{
- $as_echo "/* $configure_input */" \
+ printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
} >"$ac_tmp/config.h" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
-$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$ac_tmp/config.h" "$ac_file" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
- $as_echo "/* $configure_input */" \
+ printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
|| as_fn_error $? "could not create -" "$LINENO" 5
fi
@@ -24697,7 +26900,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/erts/configure.in b/erts/configure.ac
index beff4275f8..ab2ee78acd 100644
--- a/erts/configure.in
+++ b/erts/configure.ac
@@ -1,4 +1,4 @@
-dnl Process this file with autoconf to produce a configure script. -*-m4-*-
+dnl Process this file with autoconf to produce a configure script. -*-Autoconf-*-
dnl %CopyrightBegin%
dnl
@@ -21,16 +21,19 @@ dnl %CopyrightEnd%
dnl The string "FIXME convbreak" means that there is a break of
dnl autoconf convention that should be cleaned up.
-AC_INIT(vsn.mk)
-AC_PREREQ(2.59)
+AC_INIT
+AC_CONFIG_SRCDIR([emulator/beam/erl_process.c])
+AC_PREREQ([2.71])
+
+m4_include([otp.m4])
LM_PRECIOUS_VARS
dnl We check if -Werror was given on command line and if so
dnl we disable it for the configure and only use it when
dnl actually building erts
-no_werror_CFLAGS=$(echo "$CFLAGS" | sed 's/-Werror\([[^=]]\|$\)/ /g')
-if test "$CFLAGS" != "$no_werror_CFLAGS"; then
+no_werror_CFLAGS=$(echo " $CFLAGS " | sed 's/ -Werror / /g')
+if test "X $CFLAGS " != "X$no_werror_CFLAGS"; then
CFLAGS="$no_werror_CFLAGS"
WERRORFLAGS=-Werror
fi
@@ -73,24 +76,13 @@ erl_top=${ERL_TOP}
# echo X
# echo XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-AC_CONFIG_AUX_DIRS($srcdir/autoconf)
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
dnl ----------------------------------------------------------------------
dnl Figure out what system we are running on.
dnl ----------------------------------------------------------------------
-#
-# To configure for free source run ./configure --host=free_source
-#
-dnl
-dnl AC_CANONICAL_HOST does not like free_source as a host specification,
-dnl so we make a little special case.
-dnl
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=$host
-fi
+ERL_CANONICAL_SYSTEM_TYPE
if test "$cross_compiling" = "yes"; then
CROSS_COMPILING=yes
@@ -101,9 +93,9 @@ AC_SUBST(CROSS_COMPILING)
ERL_XCOMP_SYSROOT_INIT
-AC_ISC_POSIX
+AC_SEARCH_LIBS([strerror],[cposix])
-AC_CONFIG_HEADER($host/config.h:config.h.in include/internal/$host/ethread_header_config.h:include/internal/ethread_header_config.h.in include/$host/erl_int_sizes_config.h:include/erl_int_sizes_config.h.in)
+AC_CONFIG_HEADERS([$host/config.h:config.h.in include/internal/$host/ethread_header_config.h:include/internal/ethread_header_config.h.in include/$host/erl_int_sizes_config.h:include/erl_int_sizes_config.h.in])
dnl ----------------------------------------------------------------------
dnl Optional features.
dnl ----------------------------------------------------------------------
@@ -351,7 +343,7 @@ else
fi
AC_ARG_ENABLE(static-nifs,
-AS_HELP_STRING([--enable-static-nifs], [link nifs statically. If yes then all nifs in all Erlang/OTP applications will be statically linked into the main binary. It is also possible to give a list of nifs that should be linked statically. The list should be a comma separated and contain the absolute path to a .a archive for each nif that is to be statically linked. The name of the .a archive has to be the same as the name of the nif. Note that you have to link any external dependencies that the nifs have to the main binary, so for the crypto nif you want to pass LIBS=-lcrypto to configure.]),
+AS_HELP_STRING([--enable-static-nifs], [link nifs statically. If yes then all nifs in all Erlang/OTP applications will be statically linked into the main binary. It is also possible to give a list of nifs that should be linked statically. The list should be a comma separated and contain the absolute path to a .a archive for each nif that is to be statically linked. Note that you have to link any external dependencies, that the nifs have, to the main binary. So for the crypto nifs you want to pass LIBS=-lcrypto to configure.]),
STATIC_NIFS="$enableval",
STATIC_NIFS=no)
AC_SUBST(STATIC_NIFS)
@@ -390,16 +382,18 @@ esac
i_noretpoline_attr=""
-if test X"$with_spectre_mitigation" != X"no"; then
+AS_IF([test X"$with_spectre_mitigation" != X"no"],
+ [
CFLAGS="$CFLAGS -mindirect-branch=thunk"
AC_MSG_CHECKING([for spectre mitigation])
AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([],[return 0;])],
+ [AC_LANG_PROGRAM([[]],[[return 0;]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_ERROR([no])])
- if test X"$with_spectre_mitigation" = X"incomplete"; then
+ AS_IF([test X"$with_spectre_mitigation" = X"incomplete"],
+ [
# gcc and clang support this attribute if they're recent enough. Note
# that we must compile with -Werror to check for actual support as they
# warn rather than error out on unsupported attributes.
@@ -410,13 +404,13 @@ if test X"$with_spectre_mitigation" != X"no"; then
AC_MSG_CHECKING([whether spectre mitigation can be disabled on a per-function basis])
AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([$i_noretpoline_attr],[return 0;])],
+ [AC_LANG_PROGRAM([[$i_noretpoline_attr]],[[return 0;]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_ERROR([no])])
CFLAGS="$i_preserve_cflags"
- fi
-fi
+ ])
+ ])
AC_DEFINE_UNQUOTED(ERTS_NO_RETPOLINE, $i_noretpoline_attr,
[Per-function attribute for disabling retpoline. This is
@@ -427,9 +421,95 @@ dnl ----------------------------------------------------------------------
dnl Checks for programs.
dnl ----------------------------------------------------------------------
+AC_LANG([C])
+
AC_PROG_CC
AC_SUBST(GCC)
+AC_PROG_CXX
+AC_SUBST(CXXFLAGS)
+
+AC_PROG_EGREP
+AC_PROG_CPP
+AC_PROG_RANLIB
+AC_PROG_YACC
+LM_PROG_PERL5
+if test "$ac_cv_path_PERL" = false; then
+ AC_MSG_ERROR([Perl version 5 is required to build the emulator!])
+fi
+AC_PROG_LN_S
+AC_CHECK_TOOL([AR], [ar], [false])
+if test "$ac_cv_prog_AR" = false; then
+ AC_MSG_ERROR([No 'ar' command found in PATH])
+fi
+
+
+#
+# Get programs needed for building the documentation
+#
+
+## Delete previous failed configure results
+if test -f doc/CONF_INFO; then
+ rm -f doc/CONF_INFO
+fi
+
+AC_CHECK_PROGS(XSLTPROC, xsltproc)
+if test -z "$XSLTPROC"; then
+ echo "xsltproc" >> doc/CONF_INFO
+ AC_MSG_WARN([No 'xsltproc' command found: the documentation cannot be built])
+fi
+
+AC_CHECK_PROGS(FOP, fop)
+if test -z "$FOP"; then
+ FOP="$ERL_TOP/make/fakefop"
+ echo "fop" >> doc/CONF_INFO
+ AC_MSG_WARN([No 'fop' command found: going to generate placeholder PDF files])
+fi
+
+AC_CHECK_PROGS(XMLLINT, xmllint)
+if test -z "$XMLLINT"; then
+ echo "xmllint" >> doc/CONF_INFO
+ AC_MSG_WARN([No 'xmllint' command found: can't run the xmllint target for the documentation])
+fi
+
+dnl
+dnl We can live with Solaris /usr/ucb/install
+dnl
+case $host in
+ *-*-solaris*|free_source)
+ if test -x /usr/ucb/install; then
+ INSTALL="/usr/ucb/install -c"
+ fi
+ ;;
+ *)
+ ;;
+esac
+AC_PROG_INSTALL
+LM_PROG_INSTALL_DIR
+
+case $host_os in
+ darwin*)
+ dnl Need to preserve modification time on archives;
+ dnl otherwise, ranlib has to be run on archives
+ dnl again after installation.
+ INSTALL_DATA="$INSTALL_DATA -p";;
+ *)
+ ;;
+esac
+
+dnl
+dnl Fix for Tilera install permissions
+dnl
+
+case $build in
+ *tile*)
+ INSTALL_PROGRAM="$INSTALL_PROGRAM -m755"
+ INSTALL_SCRIPT="$INSTALL_SCRIPT -m755"
+ ;;
+ *)
+ ;;
+esac
+
dnl ---------------------------------------------------------------------
dnl Special stuff regarding CFLAGS and details in the environment...
dnl ---------------------------------------------------------------------
@@ -466,46 +546,19 @@ AC_SUBST(ERTS_CONFIG_H_IDIR)
extra_flags="$ERTS_CONFIG_H_IDIR $OTP_EXTRA_FLAGS"
CFLAGS="$CFLAGS $extra_flags"
-DEBUG_CFLAGS="-g $CPPFLAGS $extra_flags $DEBUG_CFLAGS"
DEBUG_FLAGS=-g
-dnl
-dnl Adjust DEBUG_CFLAGS to match CFLAGS in terms of -m
-dnl
-
-case $CFLAGS in
- *-m64*)
- case $DEBUG_CFLAGS in
- *-m64*)
- ;;
- *)
- DEBUG_CFLAGS="-m64 $DEBUG_CFLAGS"
- ;;
- esac
- ;;
- *-m32*)
- case $DEBUG_CFLAGS in
- *-m32*)
- ;;
- *)
- DEBUG_CFLAGS="-m32 $DEBUG_CFLAGS"
- ;;
- esac
- ;;
- *)
- ;;
-esac
lfs_conf=ok
lfs_source=none
-if test "${LFS_CFLAGS+set}" = "set" || \
- test "${LFS_LDFLAGS+set}" = "set" || \
- test "${LFS_LIBS+set}" = "set"; then
+AS_IF([test "${LFS_CFLAGS+set}" = "set" || test "${LFS_LDFLAGS+set}" = "set" || test "${LFS_LIBS+set}" = "set"],
+ [
lfs_source=user
-else
+ ],
+ [
LM_CHECK_GETCONF
test "$GETCONF" = "false" || lfs_source=getconf
-fi
+ ])
if test "$lfs_source" = "none"; then
AC_MSG_WARN([Do not know how to check for large file support flags; no getconf is available])
@@ -530,13 +583,13 @@ else
AC_MSG_WARN([Check for large file support flags failed; $GETCONF failed])
else
CFLAGS="$CFLAGS $LFS_CFLAGS"
- DEBUG_CFLAGS="$DEBUG_CFLAGS $LFS_CFLAGS"
LDFLAGS="$LDFLAGS $LFS_LDFLAGS"
LIBS="$LIBS $LFS_LIBS"
fi
fi
-if test "x$GCC" = xyes; then
+AS_IF([test "x$GCC" = xyes],
+ [
# Treat certain GCC warnings as errors
LM_TRY_ENABLE_CFLAG([-Werror=return-type], [WERRORFLAGS])
LM_TRY_ENABLE_CFLAG([-Werror=implicit], [WERRORFLAGS])
@@ -557,7 +610,7 @@ if test "x$GCC" = xyes; then
saved_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -Wdeclaration-after-statement"
- AC_TRY_COMPILE([],[;], warn_decl_after_st=true, warn_decl_after_st=false)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[;]])],[warn_decl_after_st=true],[warn_decl_after_st=false])
if test "X$warn_decl_after_st" = "Xtrue"; then
WFLAGS="$WFLAGS -Wdeclaration-after-statement"
fi
@@ -568,35 +621,26 @@ if test "x$GCC" = xyes; then
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
LM_TRY_ENABLE_CFLAG([-fno-common], [CFLAGS])
-else
+
+ LM_TRY_ENABLE_CFLAG([-fno-strict-aliasing], [CFLAGS])
+ ],
+ [
WFLAGS=""
WERRORFLAGS=${WERRORFLAGS:-""}
-fi
+ ])
AC_MSG_CHECKING([C99 support])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[
#if __STDC_VERSION__ < 199901L
#error "Not C99"
-#endif])],
+#endif]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
- CFLAGS="-std=gnu99 $CFLAGS"
- DEBUG_CFLAGS="-std=gnu99 $DEBUG_CFLAGS"])
-
-AC_MSG_CHECKING([CFLAGS for -O switch])
-case "$CFLAGS" in
- *-O*) AC_MSG_RESULT([yes]) ;;
- *)
- AC_MSG_ERROR([
- CFLAGS must contain a -O flag. If you need to edit the CFLAGS you probably
- also want to add the default CFLAGS. The default CFLAGS are "-O2 -g".
- If you want to build erts without any optimization, pass -O0 to CFLAGS.]) ;;
-esac
+ CFLAGS="-std=gnu99 $CFLAGS"])
dnl DEBUG_FLAGS is obsolete (I hope)
AC_SUBST(DEBUG_FLAGS)
-AC_SUBST(DEBUG_CFLAGS)
AC_SUBST(WFLAGS)
AC_SUBST(WERRORFLAGS)
@@ -605,57 +649,63 @@ LM_CHECK_RUN_CFLAG([-fprofile-generate -Werror],[PROFILE_GENERATE])
LM_CHECK_RUN_CFLAG([-fprofile-use -Werror],[PROFILE_USE])
LM_CHECK_RUN_CFLAG([-fprofile-use -fprofile-correction -Werror],[PROFILE_CORRECTION])
-if test "X$PROFILE_CORRECTION" = "Xtrue"; then
+AS_IF([test "X$PROFILE_CORRECTION" = "Xtrue"],
+ [
saved_CFLAGS=$CFLAGS
saved_LDFLAGS=$LDFLAGS
CFLAGS="-fprofile-generate $saved_CFLAGS"
LDFLAGS="-fprofile-generate $saved_LDFLAGS"
AC_MSG_CHECKING([whether $CC links with -fprofile-generate])
- AC_LINK_IFELSE([AC_LANG_PROGRAM([],[return 0;])],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[return 0;]])],
[AC_MSG_RESULT([yes])
PROFILE_GENERATE=true],
[AC_MSG_RESULT([no])
PROFILE_GENERATE=false])
CFLAGS=$saved_CFLAGS
LDFLAGS=$saved_LDFLAGS
-fi
+ ])
## Check if this is clang
LM_CHECK_ENABLE_CFLAG([-fprofile-instr-generate -Werror],[PROFILE_INSTR_GENERATE])
-if test "X$PROFILE_INSTR_GENERATE" = "Xtrue"; then
+AS_IF([test "X$PROFILE_INSTR_GENERATE" = "Xtrue"],
+ [
# It was clang, now we also have to check if we have llvm-profdata and that
# we can link programs with -fprofile-instr-use
saved_CFLAGS=$CFLAGS;
CFLAGS="-fprofile-instr-generate -Werror $saved_CFLAGS"
- AC_RUN_IFELSE([AC_LANG_PROGRAM([],[])],
+ AC_RUN_IFELSE([AC_LANG_PROGRAM([[]],[[]])],
[AC_PATH_PROG([LLVM_PROFDATA], [llvm-profdata],[],[$PATH:/Library/Developer/CommandLineTools/usr/bin])
AC_CHECK_PROGS([XCRUN], [xcrun])
- if test "X$XCRUN" != "X" -a "X$LLVM_PROFDATA" = "X"; then
+ AS_IF([test "X$XCRUN" != "X" -a "X$LLVM_PROFDATA" = "X"],
+ [
AC_MSG_CHECKING([for $XCRUN $LLVM_PROFDATA])
- if $XCRUN $LLVM_PROFDATA --help 2>& AS_MESSAGE_LOG_FD >& AS_MESSAGE_LOG_FD; then
+ AS_IF([$XCRUN $LLVM_PROFDATA --help 2>& AS_MESSAGE_LOG_FD >& AS_MESSAGE_LOG_FD],
+ [
LLVM_PROFDATA="$XCRUN $LLVM_PROFDATA"
AC_MSG_RESULT([yes])
- else
+ ],
+ [
AC_MSG_RESULT([no])
- fi
- fi
+ ])
+ ])
AC_SUBST(LLVM_PROFDATA)
- if test "X$LLVM_PROFDATA" != "X"; then
+ AS_IF([test "X$LLVM_PROFDATA" != "X"],
+ [
CFLAGS="-fprofile-instr-use=default.profdata $saved_CFLAGS";
$LLVM_PROFDATA merge -output=default.profdata *.profraw;
AC_MSG_CHECKING([whether $CC accepts -fprofile-instr-use=default.profdata -Werror])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[return 0;])],
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[return 0;]])],
[AC_MSG_RESULT([yes])
PROFILE_INSTR_USE=true],
[AC_MSG_RESULT([no])
PROFILE_INSTR_USE=false])
rm -f default.profdata
- fi],
+ ])],
[],
[AC_MSG_NOTICE([Disabling PGO when cross-compiling])])
rm -f *.profraw
CFLAGS=$saved_CFLAGS;
-fi
+ ])
AC_ARG_ENABLE(pgo,
AS_HELP_STRING([--enable-pgo],
@@ -830,92 +880,6 @@ else
AC_MSG_RESULT([no])
fi
-
-dnl some tests below will call this if we haven't already - and autoconf
-dnl can't handle those tests being done conditionally at runtime
-AC_PROG_CPP
-
-AC_PROG_RANLIB
-
-AC_PROG_YACC
-LM_PROG_PERL5
-if test "$ac_cv_path_PERL" = false; then
- AC_MSG_ERROR([Perl version 5 is required to build the emulator!])
-fi
-AC_PROG_LN_S
-
-
-AC_CHECK_TOOL([AR], [ar], [false])
-if test "$ac_cv_prog_AR" = false; then
- AC_MSG_ERROR([No 'ar' command found in PATH])
-fi
-
-#
-# Get programs needed for building the documentation
-#
-
-## Delete previous failed configure results
-if test -f doc/CONF_INFO; then
- rm -f doc/CONF_INFO
-fi
-
-AC_CHECK_PROGS(XSLTPROC, xsltproc)
-if test -z "$XSLTPROC"; then
- echo "xsltproc" >> doc/CONF_INFO
- AC_MSG_WARN([No 'xsltproc' command found: the documentation cannot be built])
-fi
-
-AC_CHECK_PROGS(FOP, fop)
-if test -z "$FOP"; then
- FOP="$ERL_TOP/make/fakefop"
- echo "fop" >> doc/CONF_INFO
- AC_MSG_WARN([No 'fop' command found: going to generate placeholder PDF files])
-fi
-
-AC_CHECK_PROGS(XMLLINT, xmllint)
-if test -z "$XMLLINT"; then
- echo "xmllint" >> doc/CONF_INFO
- AC_MSG_WARN([No 'xmllint' command found: can't run the xmllint target for the documentation])
-fi
-
-dnl
-dnl We can live with Solaris /usr/ucb/install
-dnl
-case $host in
- *-*-solaris*|free_source)
- if test -x /usr/ucb/install; then
- INSTALL="/usr/ucb/install -c"
- fi
- ;;
- *)
- ;;
-esac
-AC_PROG_INSTALL
-LM_PROG_INSTALL_DIR
-
-case $host_os in
- darwin*)
- dnl Need to preserve modification time on archives;
- dnl otherwise, ranlib has to be run on archives
- dnl again after installation.
- INSTALL_DATA="$INSTALL_DATA -p";;
- *)
- ;;
-esac
-
-dnl
-dnl Fix for Tilera install permissions
-dnl
-
-case $build in
- *tile*)
- INSTALL_PROGRAM="$INSTALL_PROGRAM -m755"
- INSTALL_SCRIPT="$INSTALL_SCRIPT -m755"
- ;;
- *)
- ;;
-esac
-
dnl ----------------------------------------------------------------------
dnl Misc. things (some of them should go away)
dnl ----------------------------------------------------------------------
@@ -937,7 +901,6 @@ LD_MAY_BE_WEAK=no
AC_SUBST(LD)
dnl Check for cygwin and object/exe files extension
-dnl AC_CYGWIN is deprecated
AC_EXEEXT
AC_OBJEXT
@@ -963,25 +926,32 @@ AC_SUBST(ERLANG_OSTYPE)
# Otherwise we assume that if the linker accepts the flag, it is needed.
AC_MSG_CHECKING(for extra flags needed to export symbols)
DEXPORT=""
-case $host_os in
- aix*|os400*)
+AS_CASE([$host_os],
+ [aix*|os400*],
+ [
DEXPORT=-Wl,-bexpall,-brtl
- ;;
- bsdi*)
+ ],
+ [bsdi*],
+ [
DEXPORT="-rdynamic "
- ;;
- win32)
+ ],
+ [win32],
+ [
DEXPORT=""
- ;;
- *)
+ ],
+ [
+ DEXPORT=
save_ldflags="$LDFLAGS"
LDFLAGS=-Wl,-export-dynamic
- AC_TRY_LINK(,,[DEXPORT=-Wl,-export-dynamic], [
- LDFLAGS=-Wl,-Bexport
- AC_TRY_LINK(,,[DEXPORT=-Wl,-Bexport],)])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[DEXPORT="$LDFLAGS"])
+ AS_IF([test "$DEXPORT" = ""],
+ [
+ LDFLAGS=-Wl,-Bexport
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[DEXPORT="$LDFLAGS"])
+ ])
LDFLAGS="$save_ldflags"
- ;;
-esac
+ ])
+
AC_SUBST(DEXPORT)
case "x$DEXPORT" in
"x")
@@ -1020,6 +990,7 @@ dnl ----------------------------------------------------------------------
AC_CHECK_LIB(m, sin)
AC_CHECK_LIB(dl, dlopen)
+AC_CHECK_LIB(dl, dlvsym)
AC_CHECK_LIB(inet, main)
AC_CHECK_LIB(util, openpty)
@@ -1033,7 +1004,7 @@ if test "X$ETHR_LIB_NAME" = "X"; then
AC_MSG_ERROR([cannot build emulator since no thread library was found])
fi
-TYPES=opt
+DEFAULT_TYPES="opt"
DIRTY_SCHEDULER_TEST=$enable_dirty_schedulers_test
AC_SUBST(DIRTY_SCHEDULER_TEST)
@@ -1112,24 +1083,23 @@ EOF
;;
esac
-AC_SUBST(TYPES)
+AC_SUBST(DEFAULT_TYPES)
AC_CHECK_FUNCS([posix_fadvise closefrom])
AC_CHECK_HEADERS([linux/falloc.h])
dnl * Old glibcs have broken fallocate64(). Make sure not to use it.
AC_CACHE_CHECK([whether fallocate() works],i_cv_fallocate_works,[
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/falloc.h>
- ],
- [
+ ]], [[
int fd = creat("conftest.temp", 0600);
fallocate(fd, FALLOC_FL_KEEP_SIZE,(off_t) 1024,(off_t) 1024);
- ], i_cv_fallocate_works=yes, i_cv_fallocate_works=no)
+ ]])],[i_cv_fallocate_works=yes],[i_cv_fallocate_works=no])
])
if test $i_cv_fallocate_works = yes; then
AC_DEFINE(HAVE_FALLOCATE, 1, Define if you have a working fallocate())
@@ -1138,7 +1108,7 @@ fi
dnl * Old glibcs have broken posix_fallocate(). Make sure not to use it.
dnl * It may also be broken in AIX.
AC_CACHE_CHECK([whether posix_fallocate() works],i_cv_posix_fallocate_works,[
- AC_TRY_RUN([
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
#if !defined(__sun) && !defined(__sun__)
#define _XOPEN_SOURCE 600
#endif
@@ -1160,11 +1130,11 @@ AC_CACHE_CHECK([whether posix_fallocate() works],i_cv_posix_fallocate_works,[
unlink("conftest.temp");
return ret;
}
- ], [
+ ]])],[
i_cv_posix_fallocate_works=yes
- ], [
+ ],[
i_cv_posix_fallocate_works=no
- ], [
+ ],[
i_cv_posix_fallocate_works=no
])
])
@@ -1200,7 +1170,7 @@ fi
AC_MSG_CHECKING(whether lock counters should be enabled)
AC_MSG_RESULT($enable_lock_count)
if test "x$enable_lock_count" != "xno"; then
- TYPES="$TYPES lcnt"
+ DEFAULT_TYPES="$DEFAULT_TYPES lcnt"
fi
case $host_os in
@@ -1262,8 +1232,8 @@ dnl ----------------------------------------------------------------------
TERMCAP_LIB=
-if test "x$with_termcap" != "xno" &&
- test "X$host" != "Xwin32"; then
+AS_IF([test "x$with_termcap" != "xno" && test "X$host" != "Xwin32"],
+ [
# try these libs
termcap_libs="tinfo ncurses curses termcap termlib"
@@ -1277,7 +1247,7 @@ if test "x$with_termcap" != "xno" &&
if test "x$TERMCAP_LIB" = "x"; then
AC_MSG_ERROR([No curses library functions found])
fi
-fi
+ ])
AC_SUBST(TERMCAP_LIB)
@@ -1286,16 +1256,16 @@ if test "x$TERMCAP_LIB" != "x"; then
AC_DEFINE(HAVE_TERMCAP, 1, [Define if termcap functions exists])
fi
-if test "X$host" != "Xwin32"; then
+AS_IF([test "X$host" != "Xwin32"],
+ [
AC_MSG_CHECKING(for wcwidth)
- AC_TRY_LINK([#include <wchar.h>], [wcwidth(0);],
- have_wcwidth=yes, have_wcwidth=no)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <wchar.h>]], [[wcwidth(0);]])],[have_wcwidth=yes],[have_wcwidth=no])
if test $have_wcwidth = yes; then
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_WCWIDTH, [1],
[Define to 1 if you have a `wcwidth' function.])
fi
-fi
+ ])
dnl -------------
dnl zlib
@@ -1311,11 +1281,13 @@ AC_ARG_ENABLE(builtin-zlib,
Z_LIB=
-if test "x$enable_builtin_zlib" = "xyes"; then
+AS_IF([test "x$enable_builtin_zlib" = "xyes"],
+ [
AC_DEFINE(HAVE_ZLIB_INFLATEGETDICTIONARY, 1,
[Define if your zlib version defines inflateGetDictionary.])
AC_MSG_NOTICE([Using our own built-in zlib source])
-else
+ ],
+ [
AC_MSG_CHECKING(for zlib 1.2.5 or higher)
zlib_save_LIBS=$LIBS
LIBS="-lz $LIBS"
@@ -1340,15 +1312,17 @@ error
AC_MSG_RESULT(no)
])
-if test "$Z_LIB" != ""; then
+AS_IF([test "$Z_LIB" != ""],
+ [
AC_SEARCH_LIBS(inflateGetDictionary, [z],
AC_DEFINE(HAVE_ZLIB_INFLATEGETDICTIONARY, 1,
[Define if your zlib version defines inflateGetDictionary.]))
-fi
+ ])
LIBS=$zlib_save_LIBS
-fi
+ ])
+
AC_SUBST(Z_LIB)
@@ -1358,27 +1332,18 @@ dnl -------------
AC_ARG_ENABLE(esock,
AS_HELP_STRING([--enable-esock], [enable builtin experimental socket (as a nif) support (default)])
-AS_HELP_STRING([--disable-esock], [disable builtin experimental socket (as a nif) support]))
-
-dnl Default value
-USE_ESOCK=yes
-
-if test "x$enable_esock" = "xyes"; then
- USE_ESOCK=yes
-else
- if test "x$enable_esock" = "xno"; then
- USE_ESOCK=no
- fi
-fi
+AS_HELP_STRING([--disable-esock], [disable builtin experimental socket (as a nif) support]),
+ [ case "$enableval" in
+ no) enable_esock=no ;;
+ *) enable_esock=yes ;;
+ esac
+],enable_esock=yes)
-if test "x$USE_ESOCK" = "xyes"; then
- if test "x$USE_ESOCK" = "xyes"; then
+AS_IF([test "x$enable_esock" = "xyes"],
+ [
+ AC_DEFINE(ESOCK_ENABLE, [1], [Enable esock])
AC_CHECK_FUNCS([localtime_r strftime getprotoent setprotoent endprotoent])
- fi
-fi
-
-AC_SUBST(USE_ESOCK)
-
+ ])
dnl *** ESOCK_USE_RCVSNDTIMEO ***
@@ -1503,6 +1468,15 @@ AC_CHECK_MEMBERS([struct ifreq.ifr_index],
])
+AC_CHECK_MEMBERS([struct sockaddr_dl.sdl_len],
+ [AC_DEFINE(ESOCK_SDL_LEN, [], [Socket address dl length])],
+ [],
+ [#ifdef __WIN32__
+ #else
+ #include <net/if_dl.h>
+ #endif
+ ])
+
dnl
dnl This test kindly borrowed from Tcl
dnl
@@ -1528,14 +1502,16 @@ tk_oldLibs=$LIBS
erl_checkBoth=0
SOCKET_LIBS=""
AC_CHECK_FUNC(connect, erl_checkSocket=0, erl_checkSocket=1)
-if test "$erl_checkSocket" = 1; then
+AS_IF([test "$erl_checkSocket" = 1],
+ [
AC_CHECK_LIB(socket, main, SOCKET_LIBS="-lsocket", erl_checkBoth=1)
-fi
+ ])
-if test "$erl_checkBoth" = 1; then
+AS_IF([test "$erl_checkBoth" = 1],
+ [
LIBS="$LIBS -lsocket -lnsl"
AC_CHECK_FUNC(accept, SOCKET_LIBS="-lsocket -lnsl")
-fi
+ ])
LIBS="$tk_oldLibs $SOCKET_LIBS"
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [SOCKET_LIBS="$SOCKET_LIBS -lnsl"]))
@@ -1550,22 +1526,23 @@ dnl These gethostbyname thingies use old style AC_DEFINE for BC with ancient
dnl autoconf...
dnl
-if test "$have_gethostbyname_r" = yes; then
+AS_IF([test "$have_gethostbyname_r" = yes],
+ [
# OK, so we have gethostbyname_r() - but do we know how to call it...?
# (if not, HAVE_GETHOSTBYNAME_R will not be defined at all)
- case $host_os in
- solaris2*)
+ AS_CASE([$host_os],
+ [solaris2*],
+ [
AC_DEFINE(HAVE_GETHOSTBYNAME_R, GHBN_R_SOLARIS,
[Define to flavour of gethostbyname_r])
- ;;
- aix*|os400*)
+ ],
+ [aix*|os400*],
+ [
# AIX version also needs "struct hostent_data" defn
- AC_TRY_COMPILE([#include <netdb.h>],
- [struct hostent_data hd;],
- AC_DEFINE(HAVE_GETHOSTBYNAME_R, GHBN_R_AIX,
- [Define to flavour of gethostbyname_r]))
- ;;
- *)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <netdb.h>]], [[struct hostent_data hd;]])],[AC_DEFINE(HAVE_GETHOSTBYNAME_R, GHBN_R_AIX,
+ Define to flavour of gethostbyname_r)],[])
+ ],
+ [
AC_EGREP_CPP(^yes$,[
#include <stdio.h>
#ifdef __GLIBC__
@@ -1573,23 +1550,21 @@ yes
#endif
], AC_DEFINE(HAVE_GETHOSTBYNAME_R, GHBN_R_GLIBC,
[Define to flavour of gethostbyname_r]))
- ;;
- esac
-fi
+ ])
+ ])
AC_MSG_CHECKING(for working posix_openpt implementation)
-AC_TRY_LINK([
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <fcntl.h>
-],
-[
+]], [[
int mfd = posix_openpt(O_RDWR);
ptsname(mfd);
grantpt(mfd);
unlockpt(mfd);
return mfd;
-], working_posix_openpt=yes, working_posix_openpt=no)
+]])],[working_posix_openpt=yes],[working_posix_openpt=no])
if test "X$working_posix_openpt" = "Xyes"; then
AC_DEFINE(HAVE_WORKING_POSIX_OPENPT, [1],
@@ -1607,11 +1582,8 @@ dnl netdb.h version 1.18.
AC_MSG_CHECKING([if netdb.h requires netinet/in.h to be previously included])
AC_EGREP_CPP(sockaddr_in,
[#include <netdb.h>],
- AC_TRY_COMPILE([#include <netinet/in.h>
- #include <netdb.h>],
- [return 0;],
- need_in_h=yes,
- need_in_h=no),
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <netinet/in.h>
+ #include <netdb.h>]], [[return 0;]])],[need_in_h=yes],[need_in_h=no]),
need_in_h=no)
if test $need_in_h = yes; then
@@ -1625,10 +1597,7 @@ fi
dnl Check for type socklen_t
dnl
AC_MSG_CHECKING([for socklen_t])
-AC_TRY_COMPILE( [#include <sys/socket.h>],
- [socklen_t test;],
- have_socklen_t=yes,
- have_socklen_t=no),
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[socklen_t test;]])],[have_socklen_t=yes],[have_socklen_t=no]),
if test $have_socklen_t = yes; then
AC_DEFINE(HAVE_SOCKLEN_T,[1],[Define if we have socklen_t])
@@ -1643,8 +1612,7 @@ dnl (e.g. function call for thread-safe) a simple 'extern int' may conflict
dnl (we do assume that h_errno exists at all...)
AC_CACHE_CHECK([for h_errno declaration in netdb.h],
ac_cv_decl_h_errno,
-[AC_TRY_COMPILE([#include <netdb.h>], [int err = h_errno;],
- ac_cv_decl_h_errno=yes, ac_cv_decl_h_errno=no)])
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <netdb.h>]], [[int err = h_errno;]])],[ac_cv_decl_h_errno=yes],[ac_cv_decl_h_errno=no])])
if test $ac_cv_decl_h_errno = yes; then
AC_DEFINE(H_ERRNO_DECLARED,[1],
[define if h_errno is declared (in some way) in a system header file])
@@ -1660,9 +1628,10 @@ saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $EMU_THR_DEFS"
AC_HEADER_DIRENT
-AC_HEADER_STDC
+AC_CHECK_INCLUDES_DEFAULT
+
AC_HEADER_SYS_WAIT
-AC_HEADER_TIME
+AC_CHECK_HEADERS_ONCE([sys/time.h])
dnl Interactive UX needs <net/errno.h> for socket related error codes.
dnl Some Linuxes needs <sys/socketio.h> instead of <sys/sockio.h>
@@ -1690,9 +1659,20 @@ AC_CHECK_MEMBERS([struct ifreq.ifr_enaddr], [], [],
])
dnl ----------------------------------------------------------------------
+dnl Checks for types.
+dnl ----------------------------------------------------------------------
+
+AC_CHECK_TYPES([struct ip_mreqn], [], [],
+ [
+ #include <netinet/in.h>
+ ])
+
+
+dnl ----------------------------------------------------------------------
dnl Check the availability of systemd
dnl ----------------------------------------------------------------------
-if test x"$enable_systemd" != x"no"; then
+AS_IF([test x"$enable_systemd" != x"no"],
+[
systemd_daemon_save_LIBS=$LIBS
LIBS=
@@ -1712,7 +1692,7 @@ elif test x"$enable_systemd" = x"yes"; then
AC_MSG_FAILURE([--enable-systemd was given, but test for systemd failed])
fi
LIBS=$systemd_daemon_save_LIBS
-fi
+])
AC_SUBST(SYSTEMD_DAEMON_LIBS)
@@ -1720,18 +1700,19 @@ 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
+AS_IF([test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"],
+ [
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
+ try_dlpi_lib=$erl_xcomp_sysroot/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
+ if test -d $erl_xcomp_sysroot/lib64; then
+ try_dlpi_lib= $erl_xcomp_sysroot/lib64
+ elif test -d $erl_xcomp_sysroot/lib/64; then
+ try_dlpi_lib= $erl_xcomp_sysroot/lib/64
fi
fi
if test ! -f "$try_dlpi_lib/libdlpi.so" && \
@@ -1750,13 +1731,13 @@ if test x"$ac_cv_lib_dlpi_dlpi_open" = x"no"; then
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_MSG_NOTICE([Extending the search to include $erl_xcomp_sysroot/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,
@@ -1786,7 +1767,8 @@ AC_CHECK_HEADERS([netpacket/packet.h],
dnl Check for kernel SCTP support
AC_SUBST(LIBSCTP)
-if test "x$enable_sctp" != "xno" ; then
+AS_IF([test "x$enable_sctp" != "xno"],
+ [
AC_CHECK_HEADER(netinet/sctp.h,
[LIBSCTP=libsctp.so.1
AC_DEFINE(HAVE_SCTP_H, [1],
@@ -1796,7 +1778,7 @@ if test "x$enable_sctp" != "xno" ; then
#include <sys/socket.h>
#endif
])
-fi
+ ])
case "x$enable_sctp" in
xno|x)
@@ -1807,10 +1789,12 @@ case "x$enable_sctp" in
fi;;
esac
-if test x"$ac_cv_header_netinet_sctp_h" = x"yes"; then
+AS_IF([test x"$ac_cv_header_netinet_sctp_h" = x"yes"],
+ [
AS_IF([test "x$enable_sctp" = "xlib"],
AC_CHECK_LIB(sctp, sctp_bindx))
- AC_CHECK_FUNCS([sctp_bindx sctp_peeloff sctp_getladdrs sctp_freeladdrs sctp_getpaddrs sctp_freepaddrs])
+ AC_CHECK_FUNCS([sctp_bindx sctp_peeloff sctp_getladdrs sctp_freeladdrs sctp_getpaddrs sctp_freepaddrs \
+ sctp_connectx])
AC_CHECK_MEMBERS([struct sctp_accoc_value.assoc_id], [], [],
[#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@@ -1848,7 +1832,7 @@ if test x"$ac_cv_header_netinet_sctp_h" = x"yes"; then
#endif
#include <netinet/sctp.h>
])
-fi
+ ])
dnl Check for setns
AC_CHECK_HEADERS(sched.h setns.h)
@@ -1874,15 +1858,12 @@ LM_DECL_SYS_ERRLIST
AC_CACHE_CHECK([if windows.h includes winsock2.h],
erts_cv_windows_h_includes_winsock2_h,
- AC_TRY_COMPILE([#include <windows.h>
- ],
- [#ifndef _WINSOCK2API_
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <windows.h>
+ ]], [[#ifndef _WINSOCK2API_
#error winsock2.h not included
#endif
int i = 1;
- ],
- erts_cv_windows_h_includes_winsock2_h=yes,
- erts_cv_windows_h_includes_winsock2_h=no))
+ ]])],[erts_cv_windows_h_includes_winsock2_h=yes],[erts_cv_windows_h_includes_winsock2_h=no]))
if test $erts_cv_windows_h_includes_winsock2_h = yes; then
AC_DEFINE(WINDOWS_H_INCLUDES_WINSOCK2_H, 1, \
[Define if windows.h includes winsock2.h])
@@ -1896,7 +1877,7 @@ dnl Checks for typedefs, structures, and compiler characteristics.
dnl ----------------------------------------------------------------------
AC_C_CONST
-AC_TYPE_SIGNAL
+
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
@@ -1926,11 +1907,10 @@ AC_SUBST(BITS64)
AC_MSG_CHECKING([for C compiler 'restrict' support])
restrict_keyword=""
for x in restrict __restrict; do
- AC_TRY_COMPILE([int * $x foo(int * $x arg);
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int * $x foo(int * $x arg);
int * $x foo(int * $x arg)
{ int * $x var=arg; return var;}
- ],[],
- [restrict_keyword=$x],[])
+ ]], [[]])],[restrict_keyword=$x],[])
if test "x$restrict_keyword" != "x"; then
break
fi
@@ -1945,15 +1925,13 @@ fi
if test "x$ac_compiler_gnu" = "xyes"; then
AC_MSG_CHECKING([if we should add -fno-tree-copyrename to CFLAGS for computed gotos to work properly])
## tree-copyrename was broken in gcc 4.3 and then removed in gcc 6
-AC_TRY_COMPILE([],[
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
#if (__GNUC__ > 4 && __GNUC__ < 6) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
;
#else
#error old and ok
#endif
- ],
- no_tree_copyrename=yes,
- no_tree_copyrename=no)
+ ]])],[no_tree_copyrename=yes],[no_tree_copyrename=no])
if test "x$no_tree_copyrename" = "xyes"; then
CFLAGS="$CFLAGS -fno-tree-copyrename"
@@ -1963,7 +1941,7 @@ else
fi
AC_MSG_CHECKING([for broken gcc-4.3.0 compiler])
-AC_TRY_RUN([
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
/* pr36339.c */
extern void abort (void);
@@ -1996,7 +1974,7 @@ int main(void)
abort ();
return 0;
}
-], gcc_4_3_0_bug=no, gcc_4_3_0_bug=yes, gcc_4_3_0_bug=cross)
+]])],[gcc_4_3_0_bug=no],[gcc_4_3_0_bug=yes],[gcc_4_3_0_bug=cross])
case $gcc_4_3_0_bug in
yes|no)
@@ -2055,21 +2033,21 @@ AC_SEARCH_LIBS(fdatasync, [rt])
dnl sendfile syscall
-case $host_os in
- linux*|freebsd*|dragonfly*|darwin*)
+AS_CASE([$host_os],
+ [linux*|freebsd*|dragonfly*|darwin*],
+ [
AC_CHECK_FUNCS([sendfile])
- ;;
- solaris*)
+ ],
+ [solaris*],
+ [
AC_SEARCH_LIBS(sendfilev, sendfile,
AC_DEFINE([HAVE_SENDFILEV],[1],
[Define to 1 if you have the `sendfilev' function.]))
- ;;
- win32)
+ ],
+ [win32],
+ [
LIBS="$LIBS -lmswsock"
- ;;
- *)
- ;;
-esac
+ ])
dnl ----------------------------------------------------------------------
dnl Checks for library functions.
@@ -2095,7 +2073,7 @@ AC_CHECK_HEADERS(ws2tcpip.h,[],[],[
])
dnl AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes, have_getaddrinfo=no)
AC_MSG_CHECKING(for getaddrinfo)
-AC_TRY_LINK([
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_WINSOCK2_H
@@ -2111,14 +2089,13 @@ AC_TRY_LINK([
#include <sys/socket.h>
#include <netdb.h>
#endif
-],
-[
+]], [[
getaddrinfo("","",NULL,NULL);
-],have_getaddrinfo=yes, have_getaddrinfo=no)
+]])],[have_getaddrinfo=yes],[have_getaddrinfo=no])
if test $have_getaddrinfo = yes; then
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([whether getaddrinfo accepts enough flags])
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_WINSOCK2_H
@@ -2134,8 +2111,7 @@ if test $have_getaddrinfo = yes; then
#include <sys/socket.h>
#include <netdb.h>
#endif
-],
-[
+]], [[
struct addrinfo hints, *ai;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
@@ -2147,7 +2123,7 @@ if test $have_getaddrinfo = yes; then
} else {
exit(1);
}
-],, have_getaddrinfo=no)
+]])],[],[have_getaddrinfo=no])
AC_MSG_RESULT($have_getaddrinfo)
case $have_getaddrinfo in
yes)
@@ -2159,7 +2135,7 @@ else
AC_MSG_RESULT([no])
fi
AC_MSG_CHECKING(for getnameinfo)
-AC_TRY_LINK([
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_WINSOCK2_H
@@ -2175,10 +2151,9 @@ AC_TRY_LINK([
#include <sys/socket.h>
#include <netdb.h>
#endif
-],
-[
+]], [[
getnameinfo(NULL,0,NULL,0,NULL,0,0);
-],have_getnameinfo=yes, have_getnameinfo=no)
+]])],[have_getnameinfo=yes],[have_getnameinfo=no])
if test $have_getnameinfo = yes; then
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_GETNAMEINFO, [1],
@@ -2191,7 +2166,7 @@ fi
AC_CHECK_FUNCS([getipnodebyname getipnodebyaddr gethostbyname2])
AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlopen \
- pread pwrite memmove strerror strerror_r strncasecmp \
+ dlvsym pread pwrite memmove strerror strerror_r strncasecmp \
gethrtime localtime_r gmtime_r mprotect madvise posix_madvise \
mmap mremap memcpy mallopt sbrk _sbrk __sbrk brk _brk __brk \
flockfile fstat strlcpy strlcat setsid posix2time time2posix \
@@ -2200,13 +2175,13 @@ AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlop
## We have a special check for inet_pton as AC_CHECK_FUCNS does not work
## on windows 32-bit as there a macro is used to rename the symbol...
AC_MSG_CHECKING([for inet_pton])
-AC_TRY_LINK([
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#ifdef WIN32
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif
-],[inet_pton(2,"",(void*)0)], have_inet_pton=yes, have_inet_pton=no)
+]], [[inet_pton(2,"",(void*)0)]])],[have_inet_pton=yes],[have_inet_pton=no])
if test $have_inet_pton = yes; then
AC_DEFINE(HAVE_INET_PTON,[1],
@@ -2217,8 +2192,7 @@ else
fi
AC_MSG_CHECKING([for isfinite])
-AC_TRY_LINK([#include <math.h>],
- [isfinite(0);], have_isfinite=yes, have_isfinite=no)
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]], [[isfinite(0);]])],[have_isfinite=yes],[have_isfinite=no])
if test $have_isfinite = yes; then
AC_DEFINE(HAVE_ISFINITE,[1],
@@ -2228,14 +2202,19 @@ else
AC_MSG_RESULT(no)
fi
-case X$erl_xcomp_posix_memalign in
- Xno) ;;
- Xyes) have_posix_memalign=yes ;;
- *)
+AS_CASE([X$erl_xcomp_posix_memalign],
+ [Xno],
+ [],
+ [Xyes],
+ [
+ have_posix_memalign=yes
+ ],
+ [
AC_CHECK_FUNC(
[posix_memalign],
- [if test "$cross_compiling" != yes; then
-AC_TRY_RUN([
+ [AS_IF([test "$cross_compiling" != yes],
+ [
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
int main(void) {
void *ptr = NULL;
@@ -2245,12 +2224,13 @@ int main(void) {
return error;
return 0;
}
-],have_posix_memalign=yes
-)
- else
+]])],[have_posix_memalign=yes
+],[],[])
+ ],
+ [
have_posix_memalign=yes
- fi]);;
-esac
+ ])])
+ ])
if test "$have_posix_memalign" = "yes"; then
AC_DEFINE(HAVE_POSIX_MEMALIGN,[1],
@@ -2279,10 +2259,7 @@ LM_CHECK_FUNC_DECL(fread, [extern int fread();],,
dnl Checking with TRY_LINK since putc_unlocked might be (probably is) a macro
AC_CACHE_CHECK([for putc_unlocked],
erts_cv_putc_unlocked,
- AC_TRY_LINK([#include <stdio.h>],
- [int res = putc_unlocked('x',stdout);],
- erts_cv_putc_unlocked=yes,
- erts_cv_putc_unlocked=no))
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[int res = putc_unlocked('x',stdout);]])],[erts_cv_putc_unlocked=yes],[erts_cv_putc_unlocked=no]))
if test $erts_cv_putc_unlocked = yes; then
AC_DEFINE(HAVE_PUTC_UNLOCKED, 1, [Define if you have putc_unlocked])
fi
@@ -2290,10 +2267,7 @@ fi
dnl Checking with TRY_LINK since fwrite_unlocked might be a macro
AC_CACHE_CHECK([for fwrite_unlocked],
erts_cv_fwrite_unlocked,
- AC_TRY_LINK([#include <stdio.h>],
- [size_t res = fwrite_unlocked(NULL,sizeof(char),0,stdout);],
- erts_cv_fwrite_unlocked=yes,
- erts_cv_fwrite_unlocked=no))
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[size_t res = fwrite_unlocked(NULL,sizeof(char),0,stdout);]])],[erts_cv_fwrite_unlocked=yes],[erts_cv_fwrite_unlocked=no]))
if test $erts_cv_fwrite_unlocked = yes; then
AC_DEFINE(HAVE_FWRITE_UNLOCKED, 1, [Define if you have fwrite_unlocked])
fi
@@ -2375,8 +2349,7 @@ dnl Checks for features/quirks in the system that affects Erlang.
dnl ----------------------------------------------------------------------
AC_MSG_CHECKING([for sched_getaffinity/sched_setaffinity])
-AC_TRY_LINK([#include <sched.h>],
-[
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sched.h>]], [[
#ifndef CPU_SETSIZE
#error no CPU_SETSIZE
#endif
@@ -2388,9 +2361,7 @@ AC_TRY_LINK([#include <sched.h>],
res = sched_getaffinity(0, sizeof(cpu_set_t), &cpuset);
res = CPU_ISSET(1, &cpuset);
CPU_CLR(1, &cpuset);
-],
- sched_xetaffinity=yes,
- sched_xetaffinity=no)
+]])],[sched_xetaffinity=yes],[sched_xetaffinity=no])
AC_MSG_RESULT([$sched_xetaffinity])
if test $sched_xetaffinity = yes; then
AC_DEFINE(HAVE_SCHED_xETAFFINITY, 1, [Define if you have sched_getaffinity/sched_setaffinity])
@@ -2398,8 +2369,7 @@ fi
AC_MSG_CHECKING([for pset functionality])
-AC_TRY_LINK([#include <sys/pset.h>],
-[
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/pset.h>]], [[
int res;
psetid_t id = PS_MYID;
int type = PS_PRIVATE;
@@ -2407,36 +2377,30 @@ AC_TRY_LINK([#include <sys/pset.h>],
processorid_t cpulist[1024];
res = pset_info(id, &type, &numcpus, &cpulist[0]);
-],
- pset_functionality=yes,
- pset_functionality=no)
+]])],[pset_functionality=yes],[pset_functionality=no])
AC_MSG_RESULT([$pset_functionality])
if test $pset_functionality = yes; then
AC_DEFINE(HAVE_PSET, 1, [Define if you have pset functionality])
fi
AC_MSG_CHECKING([for processor_bind functionality])
-AC_TRY_LINK([
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/processor.h>
#include <sys/procset.h>
-],
-[
+]], [[
int res = processor_bind(P_LWPID, P_MYID, PBIND_NONE, NULL);
-],
- processor_bind_functionality=yes,
- processor_bind_functionality=no)
+]])],[processor_bind_functionality=yes],[processor_bind_functionality=no])
AC_MSG_RESULT([$processor_bind_functionality])
if test $processor_bind_functionality = yes; then
AC_DEFINE(HAVE_PROCESSOR_BIND, 1, [Define if you have processor_bind functionality])
fi
AC_MSG_CHECKING([for cpuset_getaffinity/cpuset_setaffinity])
-AC_TRY_LINK([
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/param.h>
#include <sys/cpuset.h>
-],
-[
+]], [[
int res;
cpuset_t cpuset;
CPU_ZERO(&cpuset);
@@ -2445,9 +2409,7 @@ AC_TRY_LINK([
res = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset_t), &cpuset);
res = CPU_ISSET(1, &cpuset);
CPU_CLR(1, &cpuset);
-],
- cpuset_xetaffinity=yes,
- cpuset_xetaffinity=no)
+]])],[cpuset_xetaffinity=yes],[cpuset_xetaffinity=no])
AC_MSG_RESULT([$cpuset_xetaffinity])
if test $cpuset_xetaffinity = yes; then
AC_DEFINE(HAVE_CPUSET_xETAFFINITY, 1, [Define if you have cpuset_getaffinity/cpuset_setaffinity])
@@ -2455,27 +2417,21 @@ fi
AC_CACHE_CHECK([for 'end' symbol],
erts_cv_have_end_symbol,
- [AC_TRY_LINK([],
- [extern char end; {char *x = &end; *x= 0;}],
- erts_cv_have_end_symbol=yes,
- erts_cv_have_end_symbol=no)])
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern char end; {char *x = &end; *x= 0;}]])],[erts_cv_have_end_symbol=yes],[erts_cv_have_end_symbol=no])])
if test $erts_cv_have_end_symbol = yes; then
AC_DEFINE(HAVE_END_SYMBOL, 1, [Define if you have the 'end' symbol])
fi
AC_CACHE_CHECK([for '_end' symbol],
erts_cv_have__end_symbol,
- [AC_TRY_LINK([],
- [extern char _end; {char *x = &_end; *x= 0;}],
- erts_cv_have__end_symbol=yes,
- erts_cv_have__end_symbol=no)])
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern char _end; {char *x = &_end; *x= 0;}]])],[erts_cv_have__end_symbol=yes],[erts_cv_have__end_symbol=no])])
if test $erts_cv_have__end_symbol = yes; then
AC_DEFINE(HAVE__END_SYMBOL, 1, [Define if you have the '_end' symbol])
fi
AC_CACHE_CHECK([if __after_morecore_hook can track malloc()s core memory use],
erts_cv___after_morecore_hook_can_track_malloc,
- [AC_TRY_RUN([
+ [AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
@@ -2597,17 +2553,14 @@ int main(void)
return 1;
return 0;
}
- ],
- erts_cv___after_morecore_hook_can_track_malloc=yes,
- erts_cv___after_morecore_hook_can_track_malloc=no,
- [
+ ]])],[erts_cv___after_morecore_hook_can_track_malloc=yes],[erts_cv___after_morecore_hook_can_track_malloc=no],[
case X$erl_xcomp_after_morecore_hook in
X) erts_cv___after_morecore_hook_can_track_malloc=cross;;
Xyes|Xno) erts_cv___after_morecore_hook_can_track_malloc=$erl_xcomp_after_morecore_hook;;
*) AC_MSG_ERROR([Bad erl_xcomp_after_morecore_hook value: $erl_xcomp_after_morecore_hook]);;
esac
- ]
- )])
+
+ ])])
case $erts_cv___after_morecore_hook_can_track_malloc in
yes) AC_DEFINE(ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC, 1, \
@@ -2616,7 +2569,8 @@ case $erts_cv___after_morecore_hook_can_track_malloc in
*) ;;
esac
-if test "x$ac_cv_func_sbrk" = "xyes"; then
+AS_IF([test "x$ac_cv_func_sbrk" = "xyes"],
+ [
AC_CACHE_CHECK([types of sbrk()s return value and argument],
erts_cv_sbrk_ret_arg_types,
[
@@ -2628,10 +2582,8 @@ if test "x$ac_cv_func_sbrk" = "xyes"; then
for rtype in $ret_types; do
for atype in $arg_types; do
IFS=$save_ifs
- AC_TRY_LINK([#include <sys/types.h>
- #include <unistd.h>],
- [$rtype sbrk($atype incr);],
- [erts_cv_sbrk_ret_arg_types="$rtype,$atype"])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+ #include <unistd.h>]], [[$rtype sbrk($atype incr);]])],[erts_cv_sbrk_ret_arg_types="$rtype,$atype"],[])
IFS=","
if test "$erts_cv_sbrk_ret_arg_types" != "unknown"; then
break 2
@@ -2651,9 +2603,10 @@ EOF
AC_DEFINE_UNQUOTED(SBRK_ARG_TYPE, $arg_type, \
[Define the sbrk() argument type.])
fi
-fi
+ ])
-if test $ac_cv_func_brk = yes; then
+AS_IF([test $ac_cv_func_brk = yes],
+ [
AC_CACHE_CHECK([types of brk()s return value and argument],
erts_cv_brk_ret_arg_types,
[
@@ -2665,10 +2618,8 @@ if test $ac_cv_func_brk = yes; then
for rtype in $ret_types; do
for atype in $arg_types; do
IFS=$save_ifs
- AC_TRY_LINK([#include <sys/types.h>
- #include <unistd.h>],
- [$rtype brk($atype endds);],
- [erts_cv_brk_ret_arg_types="$rtype,$atype"])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+ #include <unistd.h>]], [[$rtype brk($atype endds);]])],[erts_cv_brk_ret_arg_types="$rtype,$atype"],[])
IFS=","
if test "$erts_cv_brk_ret_arg_types" != "unknown"; then
break 2
@@ -2688,14 +2639,14 @@ EOF
AC_DEFINE_UNQUOTED(BRK_ARG_TYPE, $arg_type, \
[Define the brk() argument type.])
fi
+ ])
-fi
-
-if test $ac_cv_func_sbrk = yes; then
+AS_IF([test $ac_cv_func_sbrk = yes],
+ [
AC_CACHE_CHECK([if sbrk()/brk() wrappers can track malloc()s core memory use],
erts_cv_brk_wrappers_can_track_malloc,
- [AC_TRY_RUN([
+ [AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
@@ -2860,10 +2811,7 @@ int main(void)
return 1;
return 0;
}
- ],
- erts_cv_brk_wrappers_can_track_malloc=yes,
- erts_cv_brk_wrappers_can_track_malloc=no,
- [
+ ]])],[erts_cv_brk_wrappers_can_track_malloc=yes],[erts_cv_brk_wrappers_can_track_malloc=no],[
case X$erl_xcomp_dlsym_brk_wrappers in
X) erts_cv_brk_wrappers_can_track_malloc=cross;;
Xyes|Xno) erts_cv_brk_wrappers_can_track_malloc=$erl_xcomp_dlsym_brk_wrappers;;
@@ -2878,7 +2826,7 @@ int main(void)
AC_MSG_WARN([result no guessed because of cross compilation]);;
*) ;;
esac
-fi
+ ])
dnl Restore LIBS
LIBS=$saved_libs
@@ -2900,14 +2848,18 @@ AC_CHECK_PROG(M4, m4, m4)
dnl Test if JIT can be enabled
JIT_ARCH=
-if test ${enable_jit} != no; then
+AS_IF([test ${enable_jit} != no],
+ [
case "$ARCH" in
amd64)
JIT_ARCH=x86
;;
+ arm64)
+ JIT_ARCH=arm
+ ;;
*)
if test ${enable_jit} = yes; then
- AC_MSG_ERROR([JIT only works on x86 64-bit])
+ AC_MSG_ERROR([JIT only works on x86 64-bit and ARM 64-bit])
else
enable_jit=no
AC_MSG_WARN([JIT disabled due to lack to support on $ARCH-$OPSYS])
@@ -2915,16 +2867,18 @@ if test ${enable_jit} != no; then
;;
esac
- if test ${enable_jit} != no; then
- if test "$CXX" != false; then
+ AS_IF([test ${enable_jit} != no],
+ [
+ AS_IF([test "$CXX" != false],
+ [
AC_LANG_PUSH(C++)
old_CXXFLAGS=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -std=c++17"
AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([],
- [#if __cplusplus < 201703L
+ [AC_LANG_PROGRAM([[]],
+ [[#if __cplusplus < 201703L
#error "Needs C++17 compiler"
- #endif])],
+ #endif]])],
[AC_MSG_CHECKING([for C++17 support])
AC_MSG_RESULT([yes])
HAVE_CXX17=true],
@@ -2932,7 +2886,7 @@ if test ${enable_jit} != no; then
AC_MSG_RESULT([no])
HAVE_CXX17=false])
AC_LANG_POP()
- fi
+ ])
if test "$CXX" = false -o "$HAVE_CXX17" = false; then
if test ${enable_jit} = yes; then
AC_MSG_ERROR([JIT needs a C++ compiler with C++17 support])
@@ -2945,58 +2899,75 @@ EOF
AC_MSG_WARN([JIT disable due to lack of C++ compiler with C++17 support])
fi
fi
- fi
+ ])
if test ${enable_jit} != no; then
enable_jit=yes
fi
-fi
+ ])
dnl Test if we can use the native stack for Erlang code
-if test ${enable_jit} != no; then
- case $host_os in
- openbsd*)
+AS_IF([test ${enable_jit} != no],
+ [
+ AS_CASE([$host_os],
+ [openbsd*],
+ [
# Whenever the kernel is entered (page faults, system calls, etc),
# OpenBSD checks whether the stack pointer is in an area allocated with
# MAP_STACK, so we can't use the native stack for Erlang code.
#
# https://undeadly.org/cgi?action=article;sid=20180310000858
- enable_native_stack=no;;
- win32*)
+ enable_native_stack=no
+ ],
+ [win32*],
+ [
# Windows never messes with the stack, so it's safe by default.
- enable_native_stack=yes;;
- *)
+ enable_native_stack=yes
+ ],
+ [
# Use the native stack if we can safely redirect OS signals to a
# different stack.
AC_MSG_CHECKING([for safe signal delivery])
- AC_TRY_COMPILE(
- [#include <signal.h>],
- [#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>]], [[#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
#define __DARWIN__ 1
#endif
#if !(defined(__GLIBC__) || defined(__DARWIN__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__sun__))
#error "Unknown libc. Assume musl, which does not allow safe signals"
- #endif],
- [AC_MSG_RESULT([yes])
- enable_native_stack=yes],
- [AC_MSG_RESULT([no, disabling native stack in JIT])
- enable_native_stack=no]
- );;
- esac
+ #endif]])],[AC_MSG_RESULT([yes])
+ enable_native_stack=yes],[AC_MSG_RESULT([no, disabling native stack in JIT])
+ enable_native_stack=no
+ ])
+ ])
- if test X${enable_native_stack} = Xyes; then
- AC_DEFINE(NATIVE_ERLANG_STACK, [],
- [Define if we can use the native stack for Erlang code])
- fi
-fi
+ case "$JIT_ARCH" in
+ x86)
+ if test X${enable_native_stack} = Xyes; then
+ AC_DEFINE(NATIVE_ERLANG_STACK, [],
+ [Define if we can use the native stack for Erlang code])
+ fi
+ ;;
+ arm)
+ # ARM JIT doesn't support native stack due to its 16-byte alignment
+ # requirement.
+ enable_native_stack=no
+ ;;
+ *)
+ ;;
+ esac
+ ])
dnl
dnl Check if the `perf` profiler is supported. At the moment it assumes it
dnl always works on Linux as we're not dependent on it; this is only used to
-dnl to control whether we generate `perf`-compatible memory maps.
+dnl to control whether we accept `perf`-related options.
dnl
case $OPSYS in
linux*)
+ if test X${enable_native_stack} = Xyes; then
+ AC_DEFINE(ERLANG_FRAME_POINTERS, [],
+ [Define if we need frame pointers on the Erlang stack])
+ fi
+
AC_DEFINE(HAVE_LINUX_PERF_SUPPORT, 1,
[Define if the targeted system supports the `perf` profiler])
;;
@@ -3052,13 +3023,15 @@ AC_SUBST(FLAVORS)
# Check for working poll().
#
AC_MSG_CHECKING([for working poll()])
-if test "x$ac_cv_header_poll_h" != "xyes" -o "x$ac_cv_func_poll" != "xyes"; then
+AS_IF([test "x$ac_cv_header_poll_h" != "xyes" -o "x$ac_cv_func_poll" != "xyes"],
+[
poll_works=no
-else
+],
+[
-AC_TRY_RUN([
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <poll.h>
main()
{
@@ -3077,10 +3050,7 @@ main()
exit(0);
#endif
}
-],
-poll_works=yes,
-poll_works=no,
-[
+]])],[poll_works=yes],[poll_works=no],[
case X$erl_xcomp_poll in
X) poll_works=cross;;
Xyes|Xno) poll_works=$erl_xcomp_poll;;
@@ -3088,7 +3058,7 @@ case X$erl_xcomp_poll in
esac
])
-fi
+])
case $poll_works-$host_os in
no-*|cross-darwin*)
@@ -3137,9 +3107,10 @@ fi
#
# If epoll() found, check that it is level triggered.
#
-if test $have_kernel_poll = epoll; then
+AS_IF([test $have_kernel_poll = epoll],
+ [
AC_MSG_CHECKING([whether epoll is level triggered])
- AC_TRY_LINK([#include <sys/epoll.h>],[
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/epoll.h>]], [[
#ifdef EPOLLET
/* Edge triggered option exist, assume level triggered
is default */
@@ -3149,12 +3120,10 @@ if test $have_kernel_poll = epoll; then
triggered only */
#error No EPOLLET
#endif
- ],
- level_triggered_epoll=yes,
- [level_triggered_epoll=no
+ ]])],[level_triggered_epoll=yes],[level_triggered_epoll=no
have_kernel_poll=no])
AC_MSG_RESULT([$level_triggered_epoll])
-fi
+ ])
#
# Check if we should enable kernel poll support
#
@@ -3191,7 +3160,7 @@ esac
AC_SUBST(ERTS_BUILD_FALLBACK_POLL)
AC_MSG_CHECKING([whether putenv() stores a copy of the key-value pair])
-AC_TRY_RUN([
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
int main(void) {
int i;
@@ -3221,10 +3190,7 @@ int main(void) {
return 5;
return 0;
}
-],
-copying_putenv=yes,
-copying_putenv=no,
-[
+]])],[copying_putenv=yes],[copying_putenv=no],[
case X$erl_xcomp_putenv_copy in
X) copying_putenv=cross;;
Xyes|Xno) copying_putenv=$erl_xcomp_putenv_copy;;
@@ -3256,19 +3222,23 @@ LM_FIND_EMU_CC
dnl
dnl DTrace & LTTNG
dnl
-case $DYNAMIC_TRACE_FRAMEWORK in
- dtrace|systemtap)
+AS_CASE([$DYNAMIC_TRACE_FRAMEWORK],
+ [dtrace|systemtap],
+ [
AC_CHECK_TOOL(DTRACE, dtrace, none)
test "$DTRACE" = "none" && AC_MSG_ERROR([No dtrace utility found.]);
enable_lttng_test=no
- enable_dtrace_test=yes;;
- lttng)
+ enable_dtrace_test=yes
+ ],
+ [lttng],
+ [
enable_lttng_test=yes
- enable_dtrace_test=no;;
- *)
+ enable_dtrace_test=no
+ ],
+ [
enable_lttng_test=no
- enable_dtrace_test=no;;
-esac
+ enable_dtrace_test=no
+ ])
AC_SUBST(DTRACE)
@@ -3292,8 +3262,10 @@ case $OPSYS in
: # Nothing to do
;;
esac
-if test "$enable_dtrace_test" = "yes" ; then
- if test "$DTRACE" = "dtrace" ; then
+AS_IF([test "$enable_dtrace_test" = "yes"],
+ [
+ AS_IF([test "$DTRACE" = "dtrace"],
+ [
AC_CHECK_HEADERS(sys/sdt.h)
AC_MSG_CHECKING([for 1-stage DTrace precompilation])
# The OS X version of dtrace prints a spurious line here.
@@ -3303,15 +3275,12 @@ if test "$enable_dtrace_test" = "yes" ; then
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for 2-stage DTrace precompilation])
- AC_TRY_COMPILE([ #include "foo-dtrace.h" ],
- [ERLANG_DIST_PORT_BUSY_ENABLED();],
- [rm -f $DTRACE_2STEP_TEST
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include "foo-dtrace.h" ]], [[ERLANG_DIST_PORT_BUSY_ENABLED();]])],[rm -f $DTRACE_2STEP_TEST
dtrace -G $DTRACE_CPP $DTRACE_BITS_FLAG -Iemulator/beam -o $DTRACE_2STEP_TEST -s emulator/beam/erlang_dtrace.d conftest.$OBJEXT 2>&AS_MESSAGE_LOG_FD
if test -f $DTRACE_2STEP_TEST; then
rm -f $DTRACE_2STEP_TEST
DTRACE_ENABLED_2STEP=yes
- fi],
- [])
+ fi],[])
rm -f foo-dtrace.h
AS_IF([test "x$DTRACE_ENABLED_2STEP" = "xyes"],
[AC_MSG_RESULT([yes])],
@@ -3329,12 +3298,14 @@ if test "$enable_dtrace_test" = "yes" ; then
LIBS="$LIBS -ldtrace"
;;
esac
- else
+ ],
+ [
AC_MSG_ERROR([Dtrace preprocessing test failed.])
- fi
-fi
+ ])
+ ])
-if test "$enable_lttng_test" = "yes" ; then
+AS_IF([test "$enable_lttng_test" = "yes"],
+ [
AC_CHECK_HEADERS(lttng/tracepoint.h)
AC_CHECK_HEADERS(lttng/tracepoint-event.h)
dnl The macro tracepoint_enabled is not present in older lttng versions
@@ -3342,7 +3313,7 @@ if test "$enable_lttng_test" = "yes" ; then
AC_MSG_CHECKING([for tracepoint_enabled in lttng/tracepoint.h])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
- [#include <lttng/tracepoint.h>
+ [[#include <lttng/tracepoint.h>
#define TRACEPOINT_PROVIDER org_erlang_otp
TRACEPOINT_EVENT(
org_erlang_otp,
@@ -3350,8 +3321,8 @@ if test "$enable_lttng_test" = "yes" ; then
TP_ARGS(int, my_int),
TP_FIELDS(ctf_integer(int, my_int, my_int)))
#define TRACEPOINT_CREATE_PROBES
- #define TRACEPOINT_DEFINE],
- [if(tracepoint_enabled(org_erlang_otp,dummy)) do {} while(0)])],
+ #define TRACEPOINT_DEFINE]],
+ [[if(tracepoint_enabled(org_erlang_otp,dummy)) do {} while(0)]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_ERROR([no (available in lttng-ust v2.7)])])
if test "x$ac_cv_header_lttng_tracepoint_h" = "xyes" \
@@ -3362,7 +3333,7 @@ if test "$enable_lttng_test" = "yes" ; then
else
AC_MSG_ERROR([No LTTng support found.])
fi
-fi
+ ])
#--------------------------------------------------------------------
@@ -3431,7 +3402,8 @@ else
fi
AC_CHECK_PROGS(JAVAC, $check_javac)
-if test -n "$JAVAC"; then
+AS_IF([test -n "$JAVAC"],
+ [
dnl Make sure it's at least JDK 1.6
AC_CACHE_CHECK(for JDK version 1.6,
ac_cv_prog_javac_ver_1_6,
@@ -3440,7 +3412,7 @@ if test -n "$JAVAC"; then
if test $ac_cv_prog_javac_ver_1_6 = no; then
unset -v JAVAC
fi
-fi
+ ])
if test -z "$JAVAC"; then
if test "X$with_javac" != "X"; then
@@ -3456,21 +3428,6 @@ fi
fi # end - try to find javac
-dnl
-dnl Orber has a c++ example, this isn't the right way to check for
-dnl it, but....
-dnl
-AC_SUBST(CXXFLAGS)
-dnl this deliberately does not believe that 'gcc' is a C++ compiler
-AC_CHECK_TOOLS(CXX, [$CCC c++ g++ CC cxx cc++ cl], false)
-
-# Remove SKIP file from previous run
-rm -f $ERL_TOP/lib/orber/SKIP
-
-if test "$CXX" = false; then
- echo "No C++ compiler found" > $ERL_TOP/lib/orber/SKIP
-fi
-
dnl ----------------------------------------------------------------------
dnl Include CPPFLAGS in CFLAGS
dnl ----------------------------------------------------------------------
@@ -3587,13 +3544,11 @@ dnl Check for GCC diagnostic ignored "-Waddress-of-packed-member"
dnl ----------------------------------------------------------------------
saved_CFLAGS="$CFLAGS"
CFLAGS="-Werror $CFLAGS"
-AC_TRY_COMPILE([],
- [_Pragma("GCC diagnostic push")
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"")
_Pragma("GCC diagnostic pop")
- ],
- AC_DEFINE(HAVE_GCC_DIAG_IGNORE_WADDRESS_OF_PACKED_MEMBER,[1],
- [define if compiler support _Pragma('GCC diagnostic ignored '-Waddress-of-packed-member'')]))
+ ]])],[AC_DEFINE(HAVE_GCC_DIAG_IGNORE_WADDRESS_OF_PACKED_MEMBER,1,
+ define if compiler support _Pragma('GCC diagnostic ignored '-Waddress-of-packed-member''))],[])
CFLAGS="$saved_CFLAGS"
@@ -3626,6 +3581,32 @@ LDFLAGS="$LDFLAGS $sanitizers"
])
dnl ----------------------------------------------------------------------
+dnl Enable build determinism flag
+dnl ----------------------------------------------------------------------
+
+AC_ARG_ENABLE(deterministic-build,
+AS_HELP_STRING([--enable-deterministic-build], [enable build determinism, stripping absolute paths from build output]),
+[ case "$enableval" in
+ no) ERL_DETERMINISTIC=no ;;
+ *) ERL_DETERMINISTIC=yes ;;
+ esac ],
+ERL_DETERMINISTIC=no)
+AC_SUBST(ERL_DETERMINISTIC)
+
+AC_MSG_CHECKING([CFLAGS for -O switch])
+dnl Remove all "-O*" options
+no_opt_CFLAGS=$(echo " $CFLAGS" | sed 's/ -O[[^ ]]*/ /g')
+if test "X $CFLAGS" = "X$no_opt_CFLAGS"; then
+ AC_MSG_ERROR([
+ CFLAGS must contain a -O flag. If you need to edit the CFLAGS you probably
+ also want to add the default CFLAGS. The default CFLAGS are "-O2 -g".
+ If you want to build ERTS without any optimization, pass -O0 to CFLAGS.])
+fi
+AC_MSG_RESULT([yes])
+DEBUG_CFLAGS="-g -O0 $no_opt_CFLAGS"
+AC_SUBST(DEBUG_CFLAGS)
+
+dnl ----------------------------------------------------------------------
dnl Output the result.
dnl ----------------------------------------------------------------------
@@ -3649,7 +3630,6 @@ dnl
AC_CONFIG_FILES([
../lib/os_mon/c_src/$host/Makefile:../lib/os_mon/c_src/Makefile.in
../lib/runtime_tools/c_src/$host/Makefile:../lib/runtime_tools/c_src/Makefile.in
- ../lib/tools/c_src/$host/Makefile:../lib/tools/c_src/Makefile.in
])
AC_CONFIG_FILES([../make/install_dir_data.sh:../make/install_dir_data.sh.in], [chmod +x ../make/install_dir_data.sh])
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index c70ea23aaa..afdb2e7b70 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -430,6 +430,21 @@
<c>{match,ANNO,Rep(P),Rep(E_0)}</c>.</p>
</item>
<item>
+ <p>If E is a conditional match operator expression <c>P ?= E_0</c>,
+ where <c>P</c> is a pattern, then Rep(E) =
+ <c>{maybe_match,ANNO,Rep(P),Rep(E_0)}</c>.</p>
+ </item>
+ <item>
+ <p>If E is a maybe expression <c>maybe B end</c>,
+ where <c>B</c> is a body then Rep(E) =
+ <c>{'maybe',ANNO,Rep(B)}</c>.</p>
+ </item>
+ <item>
+ <p>If E is a maybe expression <c>maybe B else Ec_1 ; ... ; Ec_k end</c>,
+ where <c>B</c> is a body and each <c>Ec_i</c> is an else clause then Rep(E) =
+ <c>{'maybe',ANNO,Rep(B),{'else',ANNO,[Rep(Ec_1), ..., Rep(Tc_k)]}}</c>.</p>
+ </item>
+ <item>
<p>If E is nil, <c>[]</c>, then Rep(E) = <c>{nil,ANNO}</c>.</p>
</item>
<item>
diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml
index d8d8765b91..f6b9327188 100644
--- a/erts/doc/src/alt_dist.xml
+++ b/erts/doc/src/alt_dist.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2020</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -314,8 +314,18 @@
<c>accept_connection/5</c> should spawn a process that will
perform the Erlang distribution handshake for the connection.
If the handshake successfully completes it should continue to
- function as a connection supervisor. This process
- should preferably execute on <c>max</c> priority.
+ function as a connection supervisor. This process should
+ preferably execute on <c>max</c> priority and should be linked
+ to the caller. The <c>dist_util:net_ticker_spawn_options()</c>
+ function can be called to get spawn options suitable for this process
+ which can be passed directly to
+ <seemfa marker="erts:erlang#spawn_opt/4"><c>erlang:spawn_opt/4</c></seemfa>.
+ <c>dist_util:net_ticker_spawn_options()</c> will by default return
+ <c>[link, {priority, max}]</c>, but allows the user to configure more
+ options using the
+ <seeapp marker="kernel:kernel_app#net_ticker_spawn_options"><c>net_ticker_spawn_options</c></seeapp>
+ kernel parameter. The process identifier of this process should be
+ returned.
</p>
<p>The arguments:</p>
<taglist>
@@ -380,8 +390,18 @@
<c>Node</c>. When connection has been established it should
perform the Erlang distribution handshake for the connection.
If the handshake successfully completes it should continue to
- function as a connection supervisor. This process
- should preferably execute on <c>max</c> priority.
+ function as a connection supervisor. This process should
+ preferably execute on <c>max</c> priority and should be linked
+ to the caller. The <c>dist_util:net_ticker_spawn_options()</c>
+ function can be called to get spawn options suitable for this process
+ which can be passed directly to
+ <seemfa marker="erts:erlang#spawn_opt/4"><c>erlang:spawn_opt/4</c></seemfa>.
+ <c>dist_util:net_ticker_spawn_options()</c> will by default return
+ <c>[link, {priority, max}]</c>, but allows the user to configure more
+ options using the
+ <seeapp marker="kernel:kernel_app#net_ticker_spawn_options"><c>net_ticker_spawn_options</c></seeapp>
+ kernel parameter. The process identifier of this process should be
+ returned.
</p>
<p>The arguments:</p>
<taglist>
@@ -1025,7 +1045,7 @@
header of four bytes containing the length of the package in a
big-endian 32-bit integer. As Unix domain sockets only can be used
between processes on the same machine, we do not need to
- code the integer in some special endianess, but we will do it anyway
+ code the integer in some special endianness, but we will do it anyway
because in most situation you need to do it. Unix domain
sockets are reliable and order maintaining, so we do not need to
implement resends and such in the driver.</p>
@@ -1410,7 +1430,7 @@
<section>
<title>Selected Parts of the Distribution Driver Implementation</title>
- <p>The implemenation of the distribution driver is not completely
+ <p>The implementation of the distribution driver is not completely
covered here, details about buffering and other things
unrelated to driver writing are not explained. Likewise are
some peculiarities of the UDS protocol not explained in
diff --git a/erts/doc/src/erl_cmd.xml b/erts/doc/src/erl_cmd.xml
index 5803647d29..ebfed75bf4 100644
--- a/erts/doc/src/erl_cmd.xml
+++ b/erts/doc/src/erl_cmd.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -283,10 +283,11 @@ $ <input>erl \
</item>
<tag><marker id="connect_all"/><c><![CDATA[-connect_all false]]></c></tag>
<item>
- <p>If this flag is present, <c><![CDATA[global]]></c> does not maintain
- a fully connected network of distributed Erlang nodes, and then
- global name registration cannot be used; see
- <seeerl marker="kernel:global"><c>global(3)</c></seeerl>.</p>
+ <p>
+ This flag is deprecated and has been replaced by the <c>kernel</c>
+ application parameter
+ <seeapp marker="kernel:kernel_app#connect_all"><c>connect_all</c></seeapp>.
+ </p>
</item>
<tag><c><![CDATA[-cookie Cookie]]></c></tag>
<item>
@@ -300,6 +301,25 @@ $ <input>erl \
console. Useful for running daemons and backgrounds processes. Implies
<c><![CDATA[-noinput]]></c>.</p>
</item>
+ <tag>
+ <marker id="disable-feature"></marker>
+ <c><![CDATA[-disable-feature feature]]></c>
+ </tag>
+ <item>
+ <p>Disables the
+ <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide> <c><![CDATA[feature]]></c>
+ in the runtime system. The special feature <c>all</c> can be
+ used to disable all non permanent features.
+ </p>
+ </item>
+ <tag><marker id="dist_listen"/><c>-dist_listen true|false</c></tag>
+ <item><p>
+ Specifies whether this node should be listening for incoming
+ distribution connections or not. By default a node will listen for
+ incoming connections. Setting this option to <c>false</c>
+ implies <seecom marker="#hidden"><c>-hidden</c></seecom>.
+ </p></item>
<tag><c><![CDATA[-emu_args]]></c></tag>
<item>
<p>Useful for debugging. Prints the arguments sent to the emulator.</p>
@@ -318,7 +338,10 @@ $ <input>erl \
build a specific flavor by doing <c>make FLAVOR=$FLAVOR</c> in the
Erlang/OTP source repository.)</p>
</item>
- <tag><c><![CDATA[-emu_type Type]]></c></tag>
+ <tag>
+ <marker id="emu_type"></marker>
+ <c><![CDATA[-emu_type Type]]></c>
+ </tag>
<item>
<p>Start an emulator of a different type. For example, to start
the lock-counter emulator, use <c>-emu_type lcnt</c>.
@@ -329,6 +352,18 @@ $ <input>erl \
Use the <c>configure</c> option <c>--enable-lock-counter</c> to
build the lock-counter emulator.)</p>
</item>
+ <tag>
+ <marker id="enable-feature"></marker>
+ <c><![CDATA[-enable-feature feature]]></c>
+ </tag>
+ <item>
+ <p>Enables the
+ <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide> <c><![CDATA[feature]]></c>
+ in the runtime system. The special feature <c>all</c> can be
+ used to enable all features.
+ </p>
+ </item>
<tag><c><![CDATA[-env Variable Value]]></c></tag>
<item>
<p>Sets the host OS environment variable <c><![CDATA[Variable]]></c> to
@@ -400,7 +435,7 @@ $ <input>erl \
the name supplied together with flag <c><![CDATA[-sname]]></c> or
<c><![CDATA[-name]]></c>.</p>
</item>
- <tag><c><![CDATA[-init_debug]]></c></tag>
+ <tag><marker id="init_debug"/><c><![CDATA[-init_debug]]></c></tag>
<item>
<p>Makes <c><![CDATA[init]]></c> write some debug information while
interpreting the boot script.</p>
@@ -461,10 +496,12 @@ $ <input>erl \
<p>Makes the Erlang runtime system into a distributed node.
This flag invokes all network servers necessary for a node to
become distributed; see <seeerl marker="kernel:net_kernel">
- <c>net_kernel(3)</c></seeerl>. It is also ensured that
+ <c>net_kernel(3)</c></seeerl>. It also ensures that
<c><![CDATA[epmd]]></c> runs on the current host before Erlang is
- started; see <seecom marker="epmd"><c>epmd(1)</c></seecom> and the
- <seecom marker="#start_epmd"><c>-start_epmd</c></seecom> option.</p>
+ started (see <seecom marker="epmd"><c>epmd(1)</c></seecom> and the
+ <seecom marker="#start_epmd"><c>-start_epmd</c></seecom> option) and
+ that a magic cookie has been set
+ (see <seecom marker="#setcookie">-setcookie</seecom>).</p>
<p>The node name will be <c><![CDATA[Name@Host]]></c>, where
<c><![CDATA[Host]]></c> is the fully qualified host name of the
current host. For short names, use flag <c><![CDATA[-sname]]></c>
@@ -580,6 +617,9 @@ $ <input>erl \
<note><p>Before OTP-23 the user <em>needed</em> to supply a valid <c>-sname</c> or
<c>-name</c> for <c>-remsh</c> to work. This is still the case if the target
node is not running OTP-23 or later.</p></note>
+ <note><p>The connecting node needs to have a proper shell with terminal emulation.
+ This means that UNIX users must use an Erlang compiled with terminal capabilities and
+ Windows users must use <seecom marker="werl"><c>werl(1)</c></seecom>.</p></note>
</item>
<tag><c><![CDATA[-rsh Program]]></c></tag>
<item>
@@ -608,11 +648,14 @@ $ <input>erl \
passed as atoms. See <seeerl marker="init">
<c>init(3)</c></seeerl>.</p>
</item>
- <tag><c><![CDATA[-setcookie Cookie]]></c></tag>
+ <tag><marker id="setcookie"/><c><![CDATA[-setcookie Cookie]]></c></tag>
<item>
<p>Sets the magic cookie of the node to <c><![CDATA[Cookie]]></c>; see
- <seemfa marker="erlang#set_cookie/2">
- <c>erlang:set_cookie/2</c></seemfa>.</p>
+ <seemfa marker="erlang#set_cookie/1"><c>erlang:set_cookie/1</c></seemfa>.
+ See see section
+ <seeguide marker="system/reference_manual:distributed">Distributed Erlang</seeguide>
+ in the Erlang Reference Manual for more details.
+ </p>
</item>
<tag><c><![CDATA[-setcookie Node Cookie]]></c></tag>
<item>
@@ -893,7 +936,7 @@ $ <input>erl \
<tag><marker id="+hmax"/><c><![CDATA[+hmax Size]]></c></tag>
<item>
<p>Sets the default maximum heap size of processes to the size
- <c><![CDATA[Size]]></c>. Defaults to <c>0</c>, which means that no
+ <c><![CDATA[Size]]></c> words. Defaults to <c>0</c>, which means that no
maximum heap size is used. For more information, see
<seeerl marker="erlang#process_flag_max_heap_size">
<c>process_flag(max_heap_size, MaxHeapSize)</c></seeerl>.</p>
@@ -961,10 +1004,45 @@ $ <input>erl \
<c>+IOt</c> are used, <c>+IOPt</c> is ignored.
</p>
</item>
- <tag><marker id="+JPperf"/><c>+JPperf true|false</c></tag>
+ <tag><marker id="+IOs"/><c>+IOs true|false</c></tag>
<item>
- <p>Enables or disables support for the `perf` profiler when running
- with the JIT on Linux. Defaults to false.</p>
+ <p>Enable or disable scheduler thread poll optimization. Default is
+ <c>true</c>.
+ </p>
+ <p>If enabled, file descriptors that are frequently read may be moved to
+ a special pollset used by scheduler threads. The objective is to
+ reduce the number of system calls and thereby CPU load, but it can
+ in some cases increase scheduling latency for individual file
+ descriptor input events.
+ </p>
+ </item>
+ <tag><marker id="+JPperf"/><c>+JPperf true|false|dump|map|fp|no_fp</c></tag>
+ <item>
+ <p>Enables or disables support for the <c>perf</c> profiler when
+ running with the JIT on Linux. Defaults to false.</p>
+ <p>This option can be combined multiple times to enable several
+ options:</p>
+ <taglist>
+ <tag><c>dump</c></tag>
+ <item>Gives <c>perf</c> detailed line information, so that the
+ <c>perf annotate</c> feature works.</item>
+ <tag><c>map</c></tag>
+ <item>Gives <c>perf</c> a map over all module code, letting it
+ translate machine code addresses to Erlang source code
+ locations. This also enables frame pointers for Erlang code so that
+ <c>perf</c> can walk the call stacks of Erlang processes, which
+ costs one extra word per stack frame.</item>
+ <tag><c>fp</c></tag>
+ <item>Enables frame pointers independently of the <c>map</c>
+ option.</item>
+ <tag><c>no_fp</c></tag>
+ <item>Disables the frame pointers added by the <c>map</c>
+ option.</item>
+ <tag><c>true</c></tag>
+ <item>Enables <c>map</c> and <c>dump</c>.</item>
+ <tag><c>false</c></tag>
+ <item>Disables all other options.</item>
+ </taglist>
<p>For more details about how to run perf see the
<seeguide marker="erts:BeamAsm#linux-perf-support">perf support</seeguide>
section in the BeamAsm internal documentation.
@@ -981,6 +1059,23 @@ $ <input>erl \
<p>Memory allocator-specific flags. For more information, see
<seecref marker="erts_alloc"><c>erts_alloc(3)</c></seecref>.</p>
</item>
+ <tag><marker id="+pad"/><c>+pad true|false</c></tag>
+ <item>
+ <p>Since: OTP 25.3</p>
+ <p>
+ The boolean value used with the <c>+pad</c> parameter determines
+ the default value of the
+ <seeerl marker="erlang#process_flag_async_dist">
+ <c>async_dist</c></seeerl> process flag of newly spawned processes.
+ By default, if no <c>+pad</c> command line option is passed,
+ the <c>async_dist</c> flag will be set to <c>false</c>.
+ </p>
+ <p>
+ The value used in runtime can be inspected by calling
+ <seeerl marker="erlang#system_info_async_dist">
+ <c>erlang:system_info(async_dist)</c></seeerl>.
+ </p>
+ </item>
<tag><marker id="+pc"/><marker id="printable_character_range"/>
<c><![CDATA[+pc Range]]></c></tag>
<item>
@@ -1501,6 +1596,16 @@ $ <input>erl \
<seeerl marker="erlang#system_info_cpu_topology">
<c>erlang:system_info(cpu_topology)</c></seeerl>.</p>
</item>
+ <tag><marker id="+ssrct"/><c>+ssrct</c></tag>
+ <item>
+ <p>Skips reading CPU topology.</p>
+ <note>
+ <p>Reading CPU topology slows down startup when starting many
+ parallel instances of ERTS on systems with large amount of
+ cores, using this flag might speed up execution in such
+ scenarios.</p>
+ </note>
+ </item>
<tag><marker id="+sfwi"/><c>+sfwi Interval</c></tag>
<item>
<p>Sets scheduler-forced wakeup interval. All run queues are
@@ -1716,6 +1821,11 @@ $ <input>erl \
limit is per distribution channel. A higher limit
gives lower latency and higher throughput at the expense
of higher memory use.</p>
+ <p>
+ This limit only affects processes that have disabled
+ <seeerl marker="erlang#process_flag_async_dist"><i>fully
+ asynchronous distributed signaling</i></seeerl>.
+ </p>
</item>
<tag><marker id="+zdntgc"/><c>+zdntgc time</c></tag>
<item>
@@ -1782,7 +1892,7 @@ $ <input>erl \
</item>
<tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag>
<item>A negative value causes the termination of the runtime system
- to wait indefinitely until the crash dump file has been completly
+ to wait indefinitely until the crash dump file has been completely
written. This is the default if option <c>-heart</c> is <em>not</em>
passed to <c>erl</c> and <c>ERL_CRASH_DUMP_SECONDS</c> is not set.
</item>
@@ -1871,14 +1981,17 @@ $ <input>erl \
<tag>The <c>.erlang</c> startup file</tag>
<item>
<p>When Erlang/OTP is started, the system searches for a file named
- <c>.erlang</c> in the user&apos;s home directory.</p>
+ <c>.erlang</c> in the <seeerl marker="erts:init#home">
+ user&apos;s home directory</seeerl> and then
+ <seeerl marker="stdlib:filename#user_config">
+ <c>filename:basedir(user_config, "erlang")</c></seeerl>.</p>
<p>If an <c>.erlang</c> file is found, it is assumed to contain valid
Erlang expressions. These expressions are evaluated as if they were
input to the shell.</p>
<p>A typical <c>.erlang</c> file contains a set of search paths, for
example:</p>
<code type="none"><![CDATA[
-io:format("executing user profile in HOME/.erlang\n",[]).
+io:format("executing user profile in $HOME/.erlang\n",[]).
code:add_path("/home/calvin/test/ebin").
code:add_path("/home/hobbes/bigappl-1.2/ebin").
io:format(".erlang rc finished\n",[]). ]]></code>
diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml
index de0b125c3a..400d3d896d 100644
--- a/erts/doc/src/erl_dist_protocol.xml
+++ b/erts/doc/src/erl_dist_protocol.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2007</year>
- <year>2021</year>
+ <year>2023</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -161,7 +161,8 @@
<tag><c>LowestVersion</c></tag>
<item>
<p>The lowest distribution version that this node can handle.
- Should be 5 to support connections to nodes older than OTP 23.</p>
+ The value in OTP 25 and later is 6 as support for connections to
+ nodes older than OTP 23 has been dropped.</p>
</item>
<tag><c>Nlen</c></tag>
<item>
@@ -549,12 +550,19 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
<p>
This section describes the distribution handshake protocol used between
nodes to establishing a connection. The protocol was introduced in
- Erlang/OTP R6 and has remained unchanged until OTP 23. The changes made in
- OTP 23 were designed to be compatible with the older protocol
- version. That is an old node can still connect toward a new node and vice
- versa.
+ Erlang/OTP R6 and amended in OTP 23. From OTP 25 support for the older
+ protocol was dropped. Therefore an OTP 25 node can not connect to nodes
+ older than OTP 23. This documentation only decribes the part of the
+ protocol used by OTP 25.
</p>
-
+ <note>
+ <p>
+ A bug introduced in OTP 25.0 may cause OTP 25 nodes to reject connection
+ attempts from OTP 23 and 24 nodes that are not using <c>epmd</c> to gain
+ version information about the remote node.
+ This is fixed in OTP 25.3.
+ </p>
+ </note>
<section>
<title>General</title>
<p>The TCP/IP distribution uses a handshake that expects a
@@ -658,19 +666,20 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
</table>
<p>
- The old <c>send_name</c> format is sent from nodes only supporting version 5
- or to nodes that might only support version 5. The <c>Version</c> is
- a 16-bit big endian integer and <em>must</em> always have the value 5, even
- if node <c>A</c> supports version 6. <c>Flags</c> are the
+ The old <c>send_name</c> format is only sent from OTP 23 and 24
+ nodes that are not using <c>epmd</c> and therefore do not know if
+ the remote node only supports protocol version 5. The <c>Version</c> is
+ a 16-bit big endian integer and <em>must</em> always have the value
+ 5 (even though node <c>A</c> supports version 6). <c>Flags</c> are the
<seeguide marker="#dflags">capability flags</seeguide>
of node <c>A</c> in 32-bit big endian. The flag bit
<seeguide marker="#DFLAG_HANDSHAKE_23"><c>DFLAG_HANDSHAKE_23</c></seeguide>
- should be set if node <c>A</c> supports version 6.
+ must be set (as node <c>A</c> must supports version 6).
<c>Name</c> is the full node name of <c>A</c>, as a string of bytes
(the packet length denotes how long it is).
</p>
<p>
- The new <c>send_name</c> is only sent from nodes supporting version 6 to
+ The new <c>send_name</c> is sent to
nodes known to support version 6. <c>Flags</c> are the
<seeguide marker="#dflags">capability flags</seeguide> of node
<c>A</c> in 64-bit big endian. The flag bit
@@ -682,6 +691,11 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
16-bit big endian. Any extra data after the node <c>Name</c> must be
accepted and ignored.
</p>
+ <p>
+ The <c>Name</c> must be just the host name (without @) when
+ <seeguide marker="#DFLAG_NAME_ME"><c>DFLAG_NAME_ME</c></seeguide>
+ is set.
+ </p>
</item>
<tag>3) <c>recv_status</c>/<c>send_status</c></tag>
<item>
@@ -737,34 +751,39 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
</item>
<tag><c>named:</c></tag>
<item><p>
- The handshake willl continue, but <c>A</c> requested a dynamic
+ The handshake will continue, but <c>A</c> requested a dynamic
node name by setting flag <seeguide marker="#DFLAG_NAME_ME">
<c>DFLAG_NAME_ME</c></seeguide>. The dynamic node name of
<c>A</c> is supplied at the end of the status message from
- <c>B</c>.</p>
- </item>
+ <c>B</c>. The host name of <c>A</c> which was sent as <c>Name</c>
+ in <c>send_name</c> will be used by node <c>B</c> to generate
+ the full dynamic node name.</p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">Slen=6</cell>
+ <cell align="center">2</cell>
+ <cell align="center">Nlen</cell>
+ <cell align="center">4</cell>
+ </row>
+ <row>
+ <cell align="center"><c>'s'</c></cell>
+ <cell align="center"><c>Status='named:'</c></cell>
+ <cell align="center"><c>Nlen</c></cell>
+ <cell align="center"><c>Name</c></cell>
+ <cell align="center"><c>Creation</c></cell>
+ </row>
+ <tcaption>The format of the 'named:' status message</tcaption>
+ </table>
+ <p>
+ <c>Name</c> is the full dynamic node name of <c>A</c>, as a
+ string of bytes. <c>Nlen</c> is the byte length of the node name in
+ 16-bit big endian. <c>Creation</c> is the incarnation identifier
+ of node <c>A</c> generated by node <c>B</c>.
+ Any extra data after the node <c>Creation</c> must be accepted and ignored.
+ </p>
+ </item>
</taglist>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- <cell align="center">Slen=6</cell>
- <cell align="center">2</cell>
- <cell align="center">Nlen</cell>
- </row>
- <row>
- <cell align="center"><c>'s'</c></cell>
- <cell align="center"><c>Status='named:'</c></cell>
- <cell align="center"><c>Nlen</c></cell>
- <cell align="center"><c>Name</c></cell>
- </row>
- <tcaption>The format of the 'named:' status message</tcaption>
- </table>
- <p>
- <c>Name</c> is the full dynamic node name of <c>A</c>, as a
- string of bytes. <c>Nlen</c> is the byte length of the node name in
- 16-bit big endian. Any extra data after the node <c>Name</c> must be
- accepted and ignored.
- </p>
</item>
<tag>3B) <c>send_status</c>/<c>recv_status</c></tag>
<item>
@@ -780,29 +799,11 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
handshake continues with <c>B</c> sending <c>A</c> another message,
the challenge. The challenge contains the same type of information
as the "name" message initially sent from <c>A</c> to <c>B</c>, plus
- a 32-bit challenge. The challenge message can have two different
- formats:
+ a 32-bit challenge:
</p>
<table align="left">
<row>
<cell align="center">1</cell>
- <cell align="center">2</cell>
- <cell align="center">4</cell>
- <cell align="center">4</cell>
- <cell align="center">Nlen</cell>
- </row>
- <row>
- <cell align="center"><c>'n'</c></cell>
- <cell align="center"><c>Version=5</c></cell>
- <cell align="center"><c>Flags</c></cell>
- <cell align="center"><c>Challenge</c></cell>
- <cell align="center"><c>Name</c></cell>
- </row>
- <tcaption>The old challenge message format (version 5)</tcaption>
- </table>
- <table align="left">
- <row>
- <cell align="center">1</cell>
<cell align="center">8</cell>
<cell align="center">4</cell>
<cell align="center">4</cell>
@@ -819,32 +820,18 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
</row>
<tcaption>The new challenge message format (version 6)</tcaption>
</table>
- <p>
- The old challenge message is sent from old <c>B</c> nodes
- (supporting only version 5) or if node <c>A</c> had not capability flag
- <seeguide marker="#DFLAG_HANDSHAKE_23"><c>DFLAG_HANDSHAKE_23</c></seeguide>
- set. The <c>Version</c> is a 16-bit big endian integer and
- <c>must</c> always have the value 5.
- </p>
- <p>
- The new challenge message is sent from new <c>B</c> nodes if node
- <c>A</c> had capability flag <seeguide marker="#DFLAG_HANDSHAKE_23">
- <c>DFLAG_HANDSHAKE_23</c></seeguide> set. Any extra data after the
- node <c>Name</c> must be accepted and ignored.
- </p>
<p>
<c>Challenge</c> is a 32-bit big-endian integer. The other fields
are node <c>B</c>'s flags, creation and full node name, similar to
- the <c>send_name</c> message.
+ the <c>send_name</c> message. Any extra data after the node
+ <c>Name</c> must be accepted and ignored.
</p>
- </item>
-
+ </item>
<tag>4B) <c>send_complement</c>/<c>recv_complement</c></tag>
<item>
<p>
The complement message, from <c>A</c> to <c>B</c>, is only sent if
- node <c>A</c> initially sent an old name message and received back a
- new challenge message from node <c>B</c>. It contains complementary
+ node <c>A</c> initially sent an old name message. It contains complementary
information missing in the initial old name message from node <c>A</c>.
</p>
<table align="left">
@@ -940,7 +927,7 @@ recv_status
&lt;---------------------------------------------- send_challenge
recv_challenge
-(if old send_name and new recv_challenge
+(if old send_name
send_complement - - - - - - - - - - - - - - - -&gt;
recv_complement)
@@ -996,9 +983,9 @@ DiB == gen_digest(ChA, ICA)?
</item>
<tag><c>-define(DFLAG_FUN_TAGS,16#10).</c></tag>
<item>
- <p>The node uses separate tag for funs (lambdas) in the distribution
- protocol.</p>
- <note><p>This flag will become mandatory in OTP 25.</p></note>
+ <p>The node uses separate tags for funs (lambdas) in the
+ distribution protocol. This flag is mandatory. If not
+ present, the connection is refused.</p>
</item>
<tag><c>-define(DFLAG_DIST_MONITOR_NAME,16#20).</c></tag>
<item>
@@ -1024,20 +1011,21 @@ DiB == gen_digest(ChA, ICA)?
<tag><c>-define(DFLAG_EXPORT_PTR_TAG,16#200).</c></tag>
<item>
<p>The node understands the <seeguide marker="erl_ext_dist#EXPORT_EXT">
- <c>EXPORT_EXT</c></seeguide> tag.</p>
- <note><p>This flag will become mandatory in OTP 25.</p></note>
+ <c>EXPORT_EXT</c></seeguide> tag.
+ This flag is mandatory. If not present, the connection is refused.
+ </p>
</item>
<tag><c>-define(DFLAG_BIT_BINARIES,16#400).</c></tag>
<item>
<p>The node understands the <seeguide marker="erl_ext_dist#BIT_BINARY_EXT">
- <c>BIT_BINARY_EXT</c></seeguide> tag.</p>
- <note><p>This flag will become mandatory in OTP 25.</p></note>
+ <c>BIT_BINARY_EXT</c></seeguide> tag.
+ This flag is mandatory. If not present, the connection is refused.</p>
</item>
<tag><c>-define(DFLAG_NEW_FLOATS,16#800).</c></tag>
<item>
<p>The node understands the <seeguide marker="erl_ext_dist#NEW_FLOAT_EXT">
- <c>NEW_FLOAT_EXT</c></seeguide> tag.</p>
- <note><p>This flag will become mandatory in OTP 25.</p></note>
+ <c>NEW_FLOAT_EXT</c></seeguide> tag. This flag is
+ mandatory. If not present, the connection is refused.</p>
</item>
<tag><c>-define(DFLAG_UNICODE_IO,16#1000).</c></tag>
<item>
@@ -1063,8 +1051,8 @@ DiB == gen_digest(ChA, ICA)?
<tag><c>-define(DFLAG_MAP_TAG, 16#20000).</c></tag>
<item>
<p>The node understands the map tag
- <seeguide marker="erl_ext_dist#MAP_EXT"><c>MAP_EXT</c></seeguide>.</p>
- <note><p>This flag will become mandatory in OTP 25.</p></note>
+ <seeguide marker="erl_ext_dist#MAP_EXT"><c>MAP_EXT</c></seeguide>. This flag is
+ mandatory. If not present, the connection is refused.</p>
</item>
<tag><marker id="DFLAG_BIG_CREATION"/><c>-define(DFLAG_BIG_CREATION, 16#40000).</c></tag>
<item>
@@ -1104,7 +1092,8 @@ DiB == gen_digest(ChA, ICA)?
<tag><marker id="DFLAG_HANDSHAKE_23"/><c>-define(DFLAG_HANDSHAKE_23, 16#1000000).</c></tag>
<item>
<p>The node supports the new connection setup handshake (version 6)
- introduced in OTP 23.</p>
+ introduced in OTP 23. This flag is mandatory (from OTP 25). If not
+ present, the connection is refused.</p>
</item>
<tag><marker id="DFLAG_UNLINK_ID"/><c>-define(DFLAG_UNLINK_ID, 16#2000000).</c></tag>
<item>
@@ -1114,6 +1103,12 @@ DiB == gen_digest(ChA, ICA)?
<seeguide marker="#old_link_protocol">old link protocol</seeguide>
will be used as a fallback.</p>
</item>
+ <tag><c>-define(DFLAG_MANDATORY_25_DIGEST, (1 bsl 36)).</c></tag>
+ <item>
+ <p>The node supports all capabilities that are mandatory in OTP 25.
+ Introduced in OTP 25.</p>
+ <note><p>This flag will become mandatory in OTP 27.</p></note>
+ </item>
<tag><marker id="DFLAG_SPAWN"/><c>-define(DFLAG_SPAWN, (1 bsl 32)).</c></tag>
<item>
<p>Set if the <seeguide marker="#SPAWN_REQUEST"><c>SPAWN_REQUEST</c></seeguide>,
@@ -1419,7 +1414,7 @@ DiB == gen_digest(ChA, ICA)?
</item>
<tag><c>PAYLOAD_EXIT_TT</c></tag>
<item>
- <p><c>{25, FromPid, ToPid}</c></p>
+ <p><c>{25, FromPid, ToPid, TraceToken}</c></p>
<p>Followed by <c>Reason</c>.</p>
<p>
This control message replaces the <c>EXIT_TT</c> control
@@ -1441,7 +1436,7 @@ DiB == gen_digest(ChA, ICA)?
</item>
<tag><c>PAYLOAD_EXIT2_TT</c></tag>
<item>
- <p><c>{27, FromPid, ToPid}</c></p>
+ <p><c>{27, FromPid, ToPid, TraceToken}</c></p>
<p>Followed by <c>Reason</c>.</p>
<p>
This control message replaces the <c>EXIT2_TT</c> control
@@ -1452,7 +1447,7 @@ DiB == gen_digest(ChA, ICA)?
</item>
<tag><c>PAYLOAD_MONITOR_P_EXIT</c></tag>
<item>
- <p><c>{28, FromPid, ToPid, Ref}</c></p>
+ <p><c>{28, FromProc, ToPid, Ref}</c></p>
<p>Followed by <c>Reason</c>.</p>
<p>
This control message replaces the <c>MONITOR_P_EXIT</c> control
diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml
index 5e2dd99945..b4b245187d 100644
--- a/erts/doc/src/erl_ext_dist.xml
+++ b/erts/doc/src/erl_ext_dist.xml
@@ -755,10 +755,8 @@
<item><p>A 32-bit big endian unsigned integer. All identifiers
originating from the same node incarnation must have identical <c>Creation</c>
values. This makes it possible to separate identifiers from old
- (crashed) nodes from a new one. The value zero should be avoided for
- normal operations as it is used as a wild card for debug purpose
- (like a pid returned by <seemfa marker="erts:erlang#list_to_pid/1">
- erlang:list_to_pid/1</seemfa>).</p>
+ (crashed) nodes from a new one. The value zero is reserved and
+ must be avoided for normal operations.</p>
</item>
</taglist>
<p><c>NEW_PID_EXT</c> was introduced in OTP 19, but only to be decoded
@@ -1110,7 +1108,7 @@
<section>
<marker id="FUN_EXT"/>
- <title>FUN_EXT</title>
+ <title>FUN_EXT (removed)</title>
<table align="left">
<row>
<cell align="center">1</cell>
@@ -1131,46 +1129,7 @@
<cell align="center"><c>Free vars ...</c></cell>
</row>
<tcaption>FUN_EXT</tcaption></table>
- <taglist>
- <tag><c>Pid</c></tag>
- <item>
- <p>A process identifier as in
- <seeguide marker="#PID_EXT"><c>PID_EXT</c></seeguide>.
- Represents the process in which the fun was created.
- </p>
- </item>
- <tag><c>Module</c></tag>
- <item>
- <p>
- The module that the fun is implemented in,
- <seeguide marker="#utf8_atoms">encoded as an atom</seeguide>.
- </p>
- </item>
- <tag><c>Index</c></tag>
- <item>
- <p>An integer encoded using
- <seeguide marker="#SMALL_INTEGER_EXT">
- <c>SMALL_INTEGER_EXT</c></seeguide>
- or <seeguide marker="#INTEGER_EXT"><c>INTEGER_EXT</c></seeguide>.
- It is typically a small index into the module's fun table.
- </p>
- </item>
- <tag><c>Uniq</c></tag>
- <item>
- <p>An integer encoded using
- <seeguide marker="#SMALL_INTEGER_EXT">
- <c>SMALL_INTEGER_EXT</c></seeguide> or
- <seeguide marker="#INTEGER_EXT"><c>INTEGER_EXT</c></seeguide>.
- <c>Uniq</c> is the hash value of the parse for the fun.
- </p>
- </item>
- <tag><c>Free vars</c></tag>
- <item>
- <p><c>NumFree</c> number of terms, each one encoded according
- to its type.
- </p>
- </item>
- </taglist>
+ <p>Not emitted since OTP R8, and not decoded since OTP 23.</p>
</section>
<section>
@@ -1205,7 +1164,7 @@
</row>
<tcaption>NEW_FUN_EXT</tcaption></table>
<p>
- This is the new encoding of internal funs: <c>fun F/A</c> and
+ This is the encoding of internal funs: <c>fun F/A</c> and
<c>fun(Arg1,..) -> ... end</c>.
</p>
<taglist>
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 7a3b766f4c..4208aa269a 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>2021</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -100,6 +100,8 @@ ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)</code>
-export([init/0, hello/0]).
+-nifs([hello/0]).
+
-on_load(init/0).
init() ->
@@ -127,7 +129,13 @@ $> erl
which loads the NIF library and replaces the <c>hello</c> function with its
native implementation in C. Once loaded, a NIF library is persistent. It
will not be unloaded until the module code version that it belongs to is
- purged.</p>
+ purged.
+ </p>
+ <p>
+ The <seeguide marker="system/reference_manual:modules#nifs_attribute">
+ <c>-nifs()</c></seeguide> attribute specifies which functions in the
+ module that are to be replaced by NIFs.
+ </p>
<p>
Each NIF must have an implementation in Erlang to be invoked if the
function is called before the NIF library is successfully loaded. A
@@ -140,21 +148,6 @@ $> erl
However, unused local stub functions will be optimized
away by the compiler, causing loading of the NIF library to fail.</p>
</note>
- <warning>
- <p>
- There is a known limitation for Erlang fallback functions of NIFs. Avoid
- functions involved in traversal of binaries by matching and
- recursion. If a NIF is loaded over such function, binary arguments to
- the NIF may get corrupted and cause VM crash or other misbehavior.
- </p>
- <p>Example of such bad fallback function:</p>
- <code type="none">
-skip_until(Byte, &lt;&lt;Byte, Rest/binary&gt;&gt;) ->
- Rest;
-skip_until(Byte, &lt;&lt;_, Rest/binary&gt;&gt;) ->
- skip_until(Byte, Rest).
-</code>
- </warning>
</section>
<section>
@@ -599,9 +592,15 @@ int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail,
<p>The fourth argument <c>NULL</c> is ignored. It
was earlier used for the deprecated <c>reload</c> callback
which is no longer supported since OTP 20.</p>
- <p>If compiling a NIF for static inclusion through
- <c>--enable-static-nifs</c>, you must define <c>STATIC_ERLANG_NIF</c>
- before the <c>ERL_NIF_INIT</c> declaration.</p>
+ <p>If compiling a NIF lib for static inclusion through
+ <c>--enable-static-nifs</c>, then the macro
+ <c>STATIC_ERLANG_NIF_LIBNAME</c> must be defined as the name of the
+ archive file (excluding file extension .a) without string
+ quotations. It must only contain characters allowed in a C
+ indentifier. The macro must be defined before <c>erl_nif.h</c> is
+ included. If the older macro <c>STATIC_ERLANG_NIF</c> is instead
+ used, then the name of the archive file must match the name of the
+ module.</p>
</item>
<tag><marker id="load"/><c>int (*load)(ErlNifEnv* caller_env, void** priv_data,
ERL_NIF_TERM load_info)</c></tag>
@@ -3242,7 +3241,7 @@ enif_map_iterator_destroy(env, &amp;iter);</code>
<c>ERL_NIF_SELECT_READ</c> and/or <c>ERL_NIF_SELECT_WRITE</c> to
indicate which type of event to cancel. Arguments <c>pid</c> and
<c>ref</c> are ignored when <c>ERL_NIF_SELECT_CANCEL</c> is specified.
- The return value will tell if the event was actualy cancelled or if a
+ The return value will tell if the event was actually cancelled or if a
notification may already have been sent.</p>
<p>Use <c>ERL_NIF_SELECT_STOP</c> as <c>mode</c> in order to safely
close an event object that has been passed to <c>enif_select</c>. The
@@ -3766,7 +3765,10 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
<section>
<title>See Also</title>
- <p><seemfa marker="erlang#load_nif/2">
- <c>erlang:load_nif/2</c></seemfa></p>
+ <p>
+ <seemfa marker="erlang#load_nif/2"><c>erlang:load_nif/2</c></seemfa><br/>
+ <seeguide marker="system/tutorial:nif">NIFs (tutorial)</seeguide><br/>
+ <seeguide marker="system/tutorial:debugging">Debugging NIFs and Port Drivers</seeguide>
+ </p>
</section>
</cref>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index a5e4a3b331..b6e34a9332 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -510,14 +510,14 @@
<datatype>
<name name="dist_handle" prefix="true"/>
<desc>
- <p>An opaque handle identifing a distribution channel.</p>
+ <p>An opaque handle identifying a distribution channel.</p>
</desc>
</datatype>
<datatype>
<name name="nif_resource" prefix="true"/>
<desc>
- <p>An opaque handle identifing a
+ <p>An opaque handle identifying a
<seecref marker="erl_nif#resource_objects">NIF resource object
</seecref>.</p>
</desc>
@@ -552,7 +552,6 @@
MQD)</c></seeerl> </p>
</desc>
</datatype>
-
<datatype>
<name name="stacktrace" prefix="true"/>
<name name="stacktrace_extrainfo" prefix="true"/>
@@ -561,7 +560,15 @@
section in the Erlang Reference Manual.
</p></desc>
</datatype>
-
+ <datatype>
+ <name name="send_destination" prefix="true"/>
+ <desc>
+ <p>The destination for a send operation, can be a remote or local process identifier,
+ a (local) port, a reference denoting a process alias, a locally registered name, or a tuple
+ <c>{<anno>RegName</anno>, <anno>Node</anno>}</c>
+ for a registered name at another node.</p>
+ </desc>
+ </datatype>
</datatypes>
<funcs>
@@ -1783,7 +1790,9 @@ end</code>
<p>Prints a text representation of <c><anno>Term</anno></c> on the
standard output.</p>
<warning>
- <p>This BIF is intended for debugging only.</p>
+ <p>This BIF is intended for debugging only. The printed representation
+ may contain internal details that do not match the high-level
+ representation of the term in Erlang.</p>
</warning>
</desc>
</func>
@@ -1818,7 +1827,7 @@ end</code>
<p>
This function is used when implementing an alternative
distribution carrier using processes as distribution
- controllers. <c><anno>DHandle</anno></c> is retrived
+ controllers. <c><anno>DHandle</anno></c> is retrieved
via the callback
<seeguide marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seeguide>.
More information can be found in the documentation of
@@ -1847,7 +1856,7 @@ end</code>
<p>
This function is used when implementing an alternative
distribution carrier using processes as distribution
- controllers. <c><anno>DHandle</anno></c> is retrived
+ controllers. <c><anno>DHandle</anno></c> is retrieved
via the callback
<seeguide marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seeguide>.
More information can be found in the documentation of
@@ -1883,7 +1892,7 @@ end</code>
<p>
This function is used when implementing an alternative
distribution carrier using processes as distribution
- controllers. <c><anno>DHandle</anno></c> is retrived
+ controllers. <c><anno>DHandle</anno></c> is retrieved
via the callback
<seeguide marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seeguide>.
More information can be found in the documentation of
@@ -1904,7 +1913,7 @@ end</code>
Once this function has been called, <c><anno>InputHandler</anno></c>
is the only process allowed to call
<seemfa marker="erlang#dist_ctrl_put_data/2"><c>erlang:dist_ctrl_put_data(DHandle, Data)</c></seemfa>
- with the <c><anno>DHandle</anno></c> identifing this distribution
+ with the <c><anno>DHandle</anno></c> identifying this distribution
channel.
</p>
<note><p>
@@ -1916,7 +1925,7 @@ end</code>
<p>
This function is used when implementing an alternative
distribution carrier using processes as distribution
- controllers. <c><anno>DHandle</anno></c> is retrived
+ controllers. <c><anno>DHandle</anno></c> is retrieved
via the callback
<seeguide marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seeguide>.
More information can be found in the documentation of
@@ -1949,7 +1958,7 @@ end</code>
<p>
This function is used when implementing an alternative
distribution carrier using processes as distribution
- controllers. <c><anno>DHandle</anno></c> is retrived
+ controllers. <c><anno>DHandle</anno></c> is retrieved
via the callback
<seeguide marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seeguide>.
More information can be found in the documentation of
@@ -1998,7 +2007,7 @@ end</code>
<p>
This function is used when implementing an alternative
distribution carrier using processes as distribution
- controllers. <c><anno>DHandle</anno></c> is retrived
+ controllers. <c><anno>DHandle</anno></c> is retrieved
via the callback
<seeguide marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seeguide>.
More information can be found in the documentation of
@@ -2364,7 +2373,14 @@ true</pre>
> <input>float_to_binary(7.12, [{decimals, 4}, compact]).</input>
&lt;&lt;"7.12">>
> <input>float_to_binary(7.12, [{scientific, 3}]).</input>
-&lt;&lt;"7.120e+00">></pre>
+&lt;&lt;"7.120e+00">>
+> <input>float_to_binary(7.12, [short]).</input>
+&lt;&lt;"7.12">>
+> <input>float_to_binary(0.1+0.2, [short]).</input>
+&lt;&lt;"0.30000000000000004">>
+> <input>float_to_binary(0.1+0.2)</input>
+&lt;&lt;"3.00000000000000044409e-01">>
+</pre>
</desc>
</func>
@@ -2399,6 +2415,16 @@ true</pre>
formatted using scientific notation with <c>Decimals</c>
digits of precision.</p>
</item>
+ <item><p>If option <c>short</c> is specified, the float is formatted
+ with the smallest number of digits that still guarantees that
+ <c>F =:= list_to_float(float_to_list(F, [short]))</c>. When the float
+ is inside the range (-2âµÂ³, 2âµÂ³), the notation
+ that yields the smallest number of characters is used (scientific
+ notation or normal decimal notation). Floats outside the range
+ (-2âµÂ³, 2âµÂ³) are always formatted using
+ scientific notation to avoid confusing results when doing arithmetic
+ operations.</p>
+ </item>
<item><p>If <c>Options</c> is <c>[]</c>, the function behaves as
<seemfa marker="#float_to_list/1">
<c>float_to_list/1</c></seemfa>.</p>
@@ -2412,6 +2438,10 @@ true</pre>
"7.12"
> <input>float_to_list(7.12, [{scientific, 3}]).</input>
"7.120e+00"
+> <input>float_to_list(7.12, [short]).</input>
+"7.12"
+> <input>float_to_list(0.1+0.2, [short]).</input>
+"0.30000000000000004"
> <input>float_to_list(0.1+0.2)</input>
"3.00000000000000044409e-01"
</pre>
@@ -2640,7 +2670,7 @@ account.</p>
{#Fun&lt;test.2.107738983>,#Fun&lt;test.3.107738983>}
</pre>
<p>Explanation: The string representations differ because the funs
-come from different fun experssions.</p>
+come from different fun expressions.</p>
<pre>
> <input>{fun() -> 1 end, fun() -> 1 end}.</input> > <input></input>
{#Fun&lt;erl_eval.45.97283095>,#Fun&lt;erl_eval.45.97283095>}
@@ -2796,7 +2826,9 @@ uncompiled code with the same arity are mapped to the same list by
<fsummary>Get the magic cookie of the local node.</fsummary>
<desc>
<p>Returns the magic cookie of the local node if the node is
- alive, otherwise the atom <c>nocookie</c>.</p>
+ alive, otherwise the atom <c>nocookie</c>. This value is set by
+ <seemfa marker="#set_cookie/1"><c>set_cookie/1</c></seemfa>.
+ </p>
</desc>
</func>
@@ -2806,7 +2838,8 @@ uncompiled code with the same arity are mapped to the same list by
<desc>
<p>Returns the magic cookie for node <c><anno>Node</anno></c>
if the local node is alive,
- otherwise the atom <c>nocookie</c>.</p>
+ otherwise the atom <c>nocookie</c>. This value is set by
+ <seemfa marker="#set_cookie/2"><c>set_cookie/2</c></seemfa>.</p>
</desc>
</func>
@@ -2875,7 +2908,7 @@ uncompiled code with the same arity are mapped to the same list by
applications with a supervision tree, because OTP
assumes the group leader of their processes is
their application master.</p>
- <p>Setting the group leader follows the signal ordering guarentees
+ <p>Setting the group leader follows the signal ordering guarantees
described in the
<seeguide marker="system/reference_manual:processes#signals">
Processes Chapter</seeguide> in the <i>Erlang Reference Manual</i>.</p>
@@ -3364,7 +3397,7 @@ is_process_alive(P2Pid),
<p>See the documentation about
<seeguide marker="system/reference_manual:processes#signals">signals</seeguide>
and <seemfa marker="#exit/2">erlang:exit/2</seemfa> for more
- information about signals and exit singnals.</p>
+ information about signals and exit signals.</p>
</desc>
</func>
@@ -3790,6 +3823,11 @@ is_process_alive(P2Pid),
previous current code for <c><anno>Module</anno></c> will remain
until the <c>on_load</c> call has finished.
</item>
+ <tag>not_allowed</tag>
+ <item>The code in <c><anno>Binary</anno></c> has been
+ compiled with features that are currently not enabled in the
+ runtime system.
+ </item>
</taglist>
<warning>
<p>This BIF is intended for the code server (see
@@ -3845,6 +3883,16 @@ is_process_alive(P2Pid),
allowed.
</item>
</taglist>
+ <p>
+ If the <seeguide marker="system/reference_manual:modules#nifs_attribute">
+ <c>-nifs()</c></seeguide> attribute is used (which is recommended),
+ all NIFs in the dynamic library much be declared as such for
+ <c>load_nif/2</c> to succeed. On the other hand, all functions declared
+ with the <c>-nifs()</c> attribute do not have to be implemented by the
+ dynamic library. This allows a target independent Erlang file to
+ contain fallback implementations for functions that may lack NIF
+ support depending on target OS/hardware platform.
+ </p>
</desc>
</func>
@@ -3950,7 +3998,7 @@ is_process_alive(P2Pid),
<func>
<name name="make_tuple" arity="3" since=""/>
- <fsummary>Create a new tuple with specifed arity and contents.</fsummary>
+ <fsummary>Create a new tuple with specified arity and contents.</fsummary>
<desc>
<p>Creates a tuple of size <c><anno>Arity</anno></c>, where each element
has value <c><anno>DefaultValue</anno></c>, and then fills in
@@ -4322,14 +4370,13 @@ RealSystem = system + MissedSystem</code>
<name name="module_loaded" arity="1" since=""/>
<fsummary>Check if a module is loaded.</fsummary>
<desc>
- <p>Returns <c>true</c> if the module <c><anno>Module</anno></c>
- is loaded, otherwise <c>false</c>. It does not attempt to load
- the module.</p>
- <warning>
- <p>This BIF is intended for the code server (see
- <seeerl marker="kernel:code"><c>code(3)</c></seeerl>)
- and is not to be used elsewhere.</p>
- </warning>
+ <p>
+ Returns <c>true</c> if the module <c><anno>Module</anno></c> is
+ loaded as
+ <seeguide marker="system/reference_manual:code_loading#code-replacement">
+ <i>current code</i></seeguide>; otherwise, <c>false</c>. It does
+ not attempt to load the module.
+ </p>
</desc>
</func>
@@ -4888,6 +4935,91 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
+ <name name="nodes" arity="2" since="OTP 25.1"/>
+ <fsummary>All nodes of a certain type in the system.</fsummary>
+ <desc>
+ <p>
+ Returns a list of <c><anno>NodeInfo</anno></c> tuples. The first
+ element is the node name. Nodes to be included in the list are
+ determined by the first argument <c><anno>Arg</anno></c> in the same
+ way as for
+ <seemfa marker="#nodes/1"><c>nodes(<anno>Arg</anno>)</c></seemfa>.
+ The second element of <c><anno>NodeInfo</anno></c> tuples is a map
+ containing further information about the node identified by the
+ first element. The information present in this map is determined by
+ the <c><anno>InfoOpts</anno></c> map passed as the second argument.
+ Currently the following associations are allowed in the
+ <c><anno>InfoOpts</anno></c> map:</p>
+ <taglist>
+ <tag><c>connection_id => boolean()</c></tag>
+ <item><p>
+ If the value of the association equals <c>true</c>, the <c>Info</c>
+ map in the returned result will contain the key <c>connection_id</c>
+ associated with the value <c><anno>ConnectionId</anno></c>. If
+ <c><anno>ConnectionId</anno></c> equals <c>undefined</c>, the node
+ is not connected to the node which the caller is executing on, or
+ is the node which the caller is executing on. If
+ <c><anno>ConnectionId</anno></c> is an integer, the node is
+ currently connected to the node which the caller is executing on.
+ </p>
+ <p>
+ <marker id="connection_id"/>
+ The integer connection identifier value together with a node name
+ identifies a specific connection instance to the node with that
+ node name. The connection identifier value is node local. That is,
+ on the other node the connection identifier will <i>not</i> be the
+ same value. If a connection is taken down and then taken up again,
+ the connection identifier value will change for the connection to
+ that node. The amount of values for connection identifiers are
+ limited, so it is possible to see the same value for different
+ instances, but quite unlikely. It is undefined how the value
+ change between two consecutive connection instances.
+ </p></item>
+ <tag><c>node_type => boolean()</c></tag>
+ <item><p>
+ If the value of the association equals <c>true</c>, the <c>Info</c>
+ map in the returned result will contain the key <c>node_type</c>
+ associated with the value <c><anno>NodeTypeInfo</anno></c>.
+ Currently the following node types exist:</p>
+ <taglist>
+ <tag><c>visible</c></tag>
+ <item><p>
+ The node is connected to the node of the calling process
+ through an ordinary visible connection. That is, the node
+ name would appear in the result returned by
+ <seemfa marker="#nodes/0"><c>nodes/0</c></seemfa>.
+ </p></item>
+ <tag><c>hidden</c></tag>
+ <item><p>
+ The node is connected to the node of the calling process
+ through a hidden connection. That is, the node
+ name would <i>not</i> appear in the result returned by
+ <seemfa marker="#nodes/0"><c>nodes/0</c></seemfa>.
+ </p></item>
+ <tag><c>this</c></tag>
+ <item><p>
+ This is the node of the calling process.
+ </p></item>
+ <tag><c>known</c></tag>
+ <item><p>
+ The node is not connected but known to the node of the
+ calling process.
+ </p></item>
+ </taglist>
+ </item>
+ </taglist>
+ <p>Example:</p>
+ <code type="erl">
+(a@localhost)1> nodes([this, connected], #{connection_id=>true, node_type=>true}).
+[{c@localhost,#{connection_id => 13892108,node_type => hidden}},
+ {b@localhost,#{connection_id => 3067553,node_type => visible}},
+ {a@localhost,#{connection_id => undefined,node_type => this}}]
+(a@localhost)2>
+ </code>
+ </desc>
+ </func>
+
+ <func>
<name name="now" arity="0" since=""/>
<fsummary>Elapsed time since 00:00 GMT.</fsummary>
<type name="timestamp"/>
@@ -4924,7 +5056,7 @@ receive_replies(ReqId, N, Acc) ->
new Erlang port. A port can be seen as an external Erlang
process.</p>
<p>The name of the executable as well as the arguments
- specifed in <c>cd</c>, <c>env</c>, <c>args</c>, and <c>arg0</c> are
+ specified in <c>cd</c>, <c>env</c>, <c>args</c>, and <c>arg0</c> are
subject to Unicode filename translation if the system is running
in Unicode filename mode. To avoid
translation or to force, for example UTF-8, supply the executable
@@ -6022,6 +6154,68 @@ receive_replies(ReqId, N, Acc) ->
<func>
<name name="process_flag" arity="2" clause_i="1"
+ anchor="process_flag_async_dist" since="OTP 25.3"/>
+ <fsummary>
+ Enable or disable fully asynchronous distributed signaling
+ for the calling process.
+ </fsummary>
+ <desc>
+ <p>
+ Enable or disable <i>fully asynchronous distributed signaling</i>
+ for the calling process. When disabled, which is the default, the
+ process sending a distributed signal will block in the send
+ operation if the buffer for the distribution channel reach the
+ <seecom marker="erts:erl#+zdbbl">distribution buffer busy
+ limit</seecom>. The process will remain blocked until the buffer
+ shrinks enough. This might in some cases take a substantial amount
+ of time. When <c>async_dist</c> is enabled, send operations of
+ distributed signals will always buffer the signal on the outgoing
+ distribution channel and then immediately return. That is, these
+ send operations will <em>never</em> block the sending process.
+ </p>
+ <note><p>
+ Since no flow control is enforced by the runtime system when
+ <c>async_dist</c> process flag is enabled, you need to make sure
+ that flow control for such data is implemented, or that the amount
+ of such data is known to always be limited. Unlimited signaling with
+ <c>async_dist</c> enabled in the absence of flow control will
+ typically cause the sending runtime system to crash on an out of
+ memory condition.
+ </p></note>
+ <p>
+ Blocking due to disabled <c>async_dist</c> can be monitored by
+ <seemfa marker="#system_monitor/2"><c>erlang:system_montor()</c></seemfa>
+ using the
+ <seeerl marker="#busy_dist_port"><c>busy_dist_port</c></seeerl>
+ option. Only data buffered by processes which (at the time of sending
+ a signal) have disabled <c>async_dist</c> will be counted when
+ determining whether or not an operation should block the caller.
+ </p>
+ <p>
+ The <c>async_dist</c> flag can also be set on a new process when
+ spawning it using the
+ <seemfa marker="#spawn_opt/4"><c>spawn_opt()</c></seemfa> BIF with the
+ option <seeerl marker="#spawn_opt_async_dist"><c>{async_dist,
+ Enable}</c></seeerl>. The default <c>async_dist</c> flag to use on
+ newly spawned processes can be set by passing the command line
+ argument <seecom marker="erl#+pad"><c>+pad
+ &lt;boolean&gt;</c></seecom> when starting the runtime system. If the
+ <c>+pad &lt;boolean&gt;</c> command line argument is not passed, the
+ default value of the <c>async_dist</c> flag will be <c>false</c>.
+ </p>
+ <p>
+ You can inspect the state of the <c>async_dist</c> process flag of a
+ process by calling <seeerl marker="#process_info_async_dist">
+ <c>process_info(Pid, async_dist)</c></seeerl>.
+ </p>
+ <p>
+ Returns the old value of the <c>async_dist</c> flag.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="process_flag" arity="2" clause_i="2"
anchor="process_flag_trap_exit" since=""/>
<fsummary>Set process flag trap_exit for the calling process.</fsummary>
<desc>
@@ -6039,7 +6233,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="2" since=""/>
+ <name name="process_flag" arity="2" clause_i="3" since=""/>
<fsummary>Set process flag error_handler for the calling process.
</fsummary>
<desc>
@@ -6053,7 +6247,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="3" since="OTP 24.0"/>
+ <name name="process_flag" arity="2" clause_i="4" since="OTP 24.0"/>
<fsummary>Set process flag fullsweep_after for the calling process.
</fsummary>
<desc>
@@ -6064,7 +6258,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="4"
+ <name name="process_flag" arity="2" clause_i="5"
anchor="process_flag_min_heap_size" since=""/>
<fsummary>Set process flag min_heap_size for the calling process.
</fsummary>
@@ -6075,7 +6269,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="5" since="OTP R13B04"/>
+ <name name="process_flag" arity="2" clause_i="6" since="OTP R13B04"/>
<fsummary>Set process flag min_bin_vheap_size for the calling process.
</fsummary>
<desc>
@@ -6086,7 +6280,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="6"
+ <name name="process_flag" arity="2" clause_i="7"
anchor="process_flag_max_heap_size" since="OTP 19.0"/>
<fsummary>Set process flag max_heap_size for the calling process.
</fsummary>
@@ -6096,6 +6290,11 @@ receive_replies(ReqId, N, Acc) ->
If <c><anno>MaxHeapSize</anno></c> is an integer, the system default
values for <c>kill</c> and <c>error_logger</c> are used.
</p>
+ <p>
+ For details on how the heap grows, see
+ <seeguide marker="erts:GarbageCollection#sizing-the-heap">Sizing
+ the heap</seeguide> in the ERTS internal documentation.
+ </p>
<taglist>
<tag><c>size</c></tag>
<item>
@@ -6160,7 +6359,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="7"
+ <name name="process_flag" arity="2" clause_i="8"
anchor="process_flag_message_queue_data" since="OTP 19.0"/>
<fsummary>Set process flag message_queue_data for the calling process.
</fsummary>
@@ -6202,7 +6401,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="8"
+ <name name="process_flag" arity="2" clause_i="9"
anchor="process_flag_priority" since=""/>
<fsummary>Set process flag priority for the calling process.</fsummary>
<type name="priority_level"/>
@@ -6275,7 +6474,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="9" since=""/>
+ <name name="process_flag" arity="2" clause_i="10" since=""/>
<fsummary>Set process flag save_calls for the calling process.</fsummary>
<desc>
<p><c><anno>N</anno></c> must be an integer in the interval 0..10000.
@@ -6306,7 +6505,7 @@ receive_replies(ReqId, N, Acc) ->
</func>
<func>
- <name name="process_flag" arity="2" clause_i="10" since=""/>
+ <name name="process_flag" arity="2" clause_i="11" since=""/>
<fsummary>Set process flag sensitive for the calling process.</fsummary>
<desc>
<p>Sets or clears flag <c>sensitive</c> for the current process.
@@ -6434,7 +6633,7 @@ receive_replies(ReqId, N, Acc) ->
<c><anno>Item</anno></c>s were included
in <c><anno>ItemList</anno></c>. Valid <c><anno>Item</anno></c>s can
be included multiple times in <c><anno>ItemList</anno></c>.</p>
- <p>Getting process informations follows the signal ordering guarantees
+ <p>Getting process information follows the signal ordering guarantees
described in the
<seeguide marker="system/reference_manual:processes#signals">
Processes Chapter</seeguide> in the <i>Erlang Reference Manual</i>.</p>
@@ -6451,6 +6650,18 @@ receive_replies(ReqId, N, Acc) ->
<p>Valid <c><anno>InfoTuple</anno></c>s with corresponding
<c><anno>Item</anno></c>s:</p>
<taglist>
+ <tag>
+ <marker id="process_info_async_dist"/>
+ <c>{async_dist, Enabled}</c>
+ </tag>
+ <item>
+ <p>Since: OTP 25.3</p>
+ <p>
+ Current value of the
+ <seeerl marker="erlang#process_flag_async_dist">
+ <c>async_dist</c></seeerl> process flag.
+ </p>
+ </item>
<tag><c>{backtrace, <anno>Bin</anno>}</c></tag>
<item>
<p>Binary <c><anno>Bin</anno></c> contains the same information
@@ -6632,6 +6843,14 @@ receive_replies(ReqId, N, Acc) ->
<seeerl marker="#process_flag_message_queue_data">
<c>process_flag(message_queue_data, MQD)</c></seeerl>.</p>
</item>
+ <tag><c>{parent, <anno>Pid</anno>}</c></tag>
+ <item>
+ <p><c><anno>Pid</anno></c> is the identifier
+ of the parent process, the one that spawned current
+ process. When the process does not have a parent
+ <c>undefined</c> is returned. Only the initial process
+ (<c>init</c>) on a node lacks a parent, though.</p>
+ </item>
<tag><c>{priority, <anno>Level</anno>}</c></tag>
<item>
<p><c><anno>Level</anno></c> is the current priority level for
@@ -7082,7 +7301,6 @@ true</pre>
<func>
<name name="send" arity="2" since=""/>
<fsummary>Send a message.</fsummary>
- <type name="dst"/>
<desc>
<p>Sends a message and returns <c><anno>Msg</anno></c>. This
is the same as using the <seeguide marker="system/reference_manual:expressions#send">
@@ -7090,8 +7308,7 @@ true</pre>
<c><anno>Dest</anno> ! <anno>Msg</anno></c>.</p>
<p><c><anno>Dest</anno></c> can be a remote or local process identifier,
an alias, a (local) port, a locally registered name, or a tuple
- <c>{<anno>RegName</anno>, <anno>Node</anno>}</c>
- for a registered name at another node.</p>
+ <c>{RegName, Node}</c> for a registered name at another node.</p>
<p>The function fails with a <c>badarg</c> run-time error if
<c><anno>Dest</anno></c> is an atom name, but this name is not
registered. This is the only case when <c>send</c> fails for an
@@ -7102,7 +7319,6 @@ true</pre>
<func>
<name name="send" arity="3" since=""/>
<fsummary>Send a message conditionally.</fsummary>
- <type name="dst"/>
<desc>
<p>Either sends a message and returns <c>ok</c>, or does not send
the message but returns something else (see below).
@@ -7158,7 +7374,6 @@ true</pre>
<func>
<name name="send_nosuspend" arity="2" since=""/>
<fsummary>Try to send a message without ever blocking.</fsummary>
- <type name="dst"/>
<desc>
<p>The same as
<seemfa marker="#send/3"><c>erlang:send(<anno>Dest</anno>,
@@ -7208,7 +7423,6 @@ true</pre>
<func>
<name name="send_nosuspend" arity="3" since=""/>
<fsummary>Try to send a message without ever blocking.</fsummary>
- <type name="dst"/>
<desc>
<p>The same as
<seemfa marker="#send/3"><c>erlang:send(<anno>Dest</anno>,
@@ -7250,6 +7464,8 @@ true</pre>
<seeguide marker="system/reference_manual:distributed">
Distributed Erlang</seeguide>
in the Erlang Reference Manual in System Documentation).</p>
+ <p>You can get this value using
+ <seemfa marker="#get_cookie/0"><c>get_cookie/0</c></seemfa>.</p>
<p>Failure: <c>function_clause</c> if the local node is not
alive.</p>
</desc>
@@ -7267,6 +7483,8 @@ true</pre>
<seeguide marker="system/reference_manual:distributed">
Distributed Erlang</seeguide>
in the Erlang Reference Manual in System Documentation).</p>
+ <p>You can get this value using
+ <seemfa marker="#get_cookie/1"><c>get_cookie/1</c></seemfa>.</p>
<p>Failure: <c>function_clause</c> if the local node is not
alive.</p>
</desc>
@@ -7687,6 +7905,21 @@ true</pre>
<c>process_flag(message_queue_data,
<anno>MQD</anno>)</c></seeerl>.</p>
</item>
+ <tag>
+ <marker id="spawn_opt_async_dist"/>
+ <c>{async_dist, Enabled}</c>
+ </tag>
+ <item>
+ <p>Since: OTP 25.3</p>
+ <p>
+ Set the
+ <seeerl marker="erlang#process_flag_async_dist">
+ <c>async_dist</c></seeerl> process flag of the spawned process.
+ This option will override the default value set by the command
+ line argument
+ <seecom marker="erl#+pad"><c>+pad &lt;boolean&gt;</c></seecom>.
+ </p>
+ </item>
</taglist>
</desc>
</func>
@@ -8037,6 +8270,11 @@ true</pre>
</p>
</item>
</taglist>
+ <p>
+ If a spawn reply message is delivered, it is guaranteed to be
+ delivered before any other signals from the newly spawned
+ process are delivered to the process issuing the spawn request.
+ </p>
<p>This function will fail with a <c>badarg</c> exception if:
</p>
<list>
@@ -8593,7 +8831,7 @@ lists:map(
and <seeerl marker="#system_info_dirty_cpu_schedulers">dirty CPU</seeerl>
schedulers in the system have been busy. This value is normally a
better indicator of how much load an Erlang node is under instead of
- looking at the CPU utilization privided by tools such as <c>top</c> or
+ looking at the CPU utilization provided by tools such as <c>top</c> or
<c>sysstat</c>. This is because <c>scheduler_wall_time</c> also includes
time where the scheduler is waiting for some other reasource (such as an internal
mutex) to be available but does not use the CPU. In order to better
@@ -8898,7 +9136,7 @@ ok
</item>
</taglist>
<p>
- Appart from the reply message, the <c>{asynchronous,
+ Apart from the reply message, the <c>{asynchronous,
ReplyTag}</c> option behaves exactly the same as the
<c>asynchronous</c> option without reply tag.
</p>
@@ -9158,6 +9396,11 @@ ok
<seeerl marker="#process_flag_max_heap_size">
<c>process_flag/2</c></seeerl>.</p>
<p>Returns the old value of the flag.</p>
+ <p>
+ For details on how the heap grows, see
+ <seeguide marker="erts:GarbageCollection#sizing-the-heap">Sizing
+ the heap</seeguide> in the ERTS internal documentation.
+ </p>
</desc>
</func>
@@ -10282,7 +10525,7 @@ Metadata = #{ pid => pid(),
introduced in the future:</p>
<taglist>
<tag><c>{function, Function}</c></tag>
- <item><p><c>Function</c> is the name of the funcion used.</p>
+ <item><p><c>Function</c> is the name of the function used.</p>
</item>
<tag><c>{clock_id, ClockId}</c></tag>
<item><p>Exists only if <c>Function</c>
@@ -10707,6 +10950,8 @@ Metadata = #{ pid => pid(),
</func>
<func>
+ <name name="system_info" arity="1" clause_i="79"
+ anchor="system_info_async_dist" since="OTP 25.3"/> <!-- async_dist -->
<name name="system_info" arity="1" clause_i="14"
anchor="system_info_dist" since=""/> <!-- creation -->
<name name="system_info" arity="1" clause_i="16" since="OTP 18.0"/> <!-- delayed_node_table_gc -->
@@ -10719,6 +10964,17 @@ Metadata = #{ pid => pid(),
<p>Returns information about Erlang Distribution in the
current system as specified by <c><anno>Item</anno></c>:</p>
<taglist>
+ <tag><marker id="system_info_async_dist"/><c>async_dist</c></tag>
+ <item>
+ <p>Since: OTP 25.3</p>
+ <p>
+ Returns the value of the command line argument
+ <seecom marker="erl#+pad">+pad &lt;boolean&gt;</seecom>
+ which the runtime system use. This value determines the default
+ <seeerl marker="erlang#process_flag_async_dist">
+ <c>async_dist</c></seeerl> value for newly spawned processes.
+ </p>
+ </item>
<tag><marker id="system_info_creation"/>
<c>creation</c></tag>
<item>
@@ -10857,7 +11113,7 @@ Metadata = #{ pid => pid(),
<!-- <name name="system_info" arity="1" clause_i="76"/> update_cpu_info -->
<name name="system_info" arity="1" clause_i="77" since=""/> <!-- version -->
<name name="system_info" arity="1" clause_i="78" since=""/> <!-- wordsize -->
- <!-- <name name="system_info" arity="1" clause_i="79"/> overview -->
+ <!-- <name name="system_info" arity="1" clause_i="80"/> overview -->
<!-- When adding any entry, make sure to update the overview clause_i -->
<fsummary>Information about the system.</fsummary>
<desc>
@@ -11225,7 +11481,7 @@ Metadata = #{ pid => pid(),
<c><anno>MonitorPid</anno></c>. <c>SusPid</c> is the pid
that got suspended when sending to <c>Port</c>.</p>
</item>
- <tag><c>busy_dist_port</c></tag>
+ <tag><c>busy_dist_port</c><marker id="busy_dist_port"/></tag>
<item>
<p>If a process in the system gets suspended because it
sends to a process on a remote node whose inter-node
@@ -12460,7 +12716,7 @@ improper_end</pre>
<item>
<p>Returns a list of atoms indicating what kind of traces is
enabled for the process. The list is empty if no
- traces are enabled, and one or more of the followings
+ traces are enabled, and one or more of the following
atoms if traces are enabled: <c>send</c>,
<c>'receive'</c>, <c>set_on_spawn</c>, <c>call</c>,
<c>return_to</c>, <c>procs</c>, <c>ports</c>,
diff --git a/erts/doc/src/erlc_cmd.xml b/erts/doc/src/erlc_cmd.xml
index 98042d49b7..5274e9b322 100644
--- a/erts/doc/src/erlc_cmd.xml
+++ b/erts/doc/src/erlc_cmd.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>1997</year><year>2020</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -142,6 +142,47 @@
<p>Use the
<seecom marker="#compile_server">compile server</seecom>.</p>
</item>
+ <tag>
+ <marker id="enable-feature"/>
+ <c>-enable-feature &lt;Feature&gt;</c>
+ </tag>
+ <item>
+ <p>Enables the
+ <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide> <c>feature</c>
+ during compilation. The special feature <c>all</c> can be
+ used to enable all features.
+ </p>
+ </item>
+ <tag>
+ <marker id="disable-feature"/>
+ <c>-disable-feature &lt;feature&gt;</c>
+ </tag>
+ <item>
+ <p>Disables the
+ <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide> <c>feature</c>
+ during compilation. The special feature <c>all</c> can be
+ used to disable all non permanent features.
+ </p>
+ </item>
+ <tag><c>-list-features</c></tag>
+ <item>
+ <p><marker id="list-features"/> List short descriptions of the
+ current configurable <seeguide
+ marker="system/reference_manual:features#features">features</seeguide>.
+ Non configurable features, i.e., those with a status of
+ <c>rejected</c> or <c>permanent</c> will not be shown.
+ </p>
+ </item>
+ <tag><c>-describe-feature &lt;feature&gt;</c></tag>
+ <item>
+ <p><marker id="describe-feature"/>
+ Show long description and history of
+ <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide> <c>feature</c>.
+ </p>
+ </item>
<tag><c>-M</c></tag>
<item>
<p>Produces a Makefile rule to track header dependencies. The
@@ -326,7 +367,7 @@ erlc +export_all file.erl</pre>
<p>Using the compile server does not always speed up the build, as
the compile server sometimes must be restarted to ensure correctness.
- Here are some examples of situtations that force a restart:</p>
+ Here are some examples of situations that force a restart:</p>
<list type="bulleted">
<item><c>erlc</c> wants to use a different version of Erlang
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index 1a1e583ab1..da293f9c45 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -4,7 +4,7 @@
<cref>
<header>
<copyright>
- <year>2002</year><year>2021</year>
+ <year>2002</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -514,6 +514,29 @@
<p>See also <seecref marker="#M_acul"><c>acul</c></seecref>.</p>
</item>
+ <tag><marker id="M_acful"/><c><![CDATA[+M<S>acful <utilization>|de]]></c>
+ </tag>
+ <item>
+ <p>Abandon carrier free utilization limit. When the utilization of
+ a carrier falls belows this limit erts_alloc instructs the OS that
+ unused memory in the carrier can be re-used for allocation by other OS
+ procesesses. On Unix this is done by calling <c>madvise(..., ..., MADV_FREE)</c>
+ on the unused memory region, on Windows it is done by calling
+ <c>VirtualAlloc(..., ..., MEM_RESET, PAGE_READWRITE)</c>. Defaults to 0
+ which means that no memory will be marked as re-usable by the OS.</p>
+ <p>A valid
+ <c><![CDATA[<utilization>]]></c> is an integer in the range
+ <c>[0, 100]</c> representing utilization in percent. If this value is
+ larger than the <c>acul</c> limit it will be lowered to the current
+ <c>acul</c> limit. If <c>de</c> (default
+ enabled) is passed instead of a <c><![CDATA[<utilization>]]></c>,
+ a recommended non-zero utilization value is used. The value
+ chosen depends on the allocator type and can be changed between
+ ERTS versions.
+ </p>
+ <p>See also <seecref marker="#M_acul"><c>acul</c></seecref>.</p>
+ </item>
+
<tag><marker id="M_as"/>
<c><![CDATA[+M<S>as bf|aobf|aoff|aoffcbf|aoffcaobf|ageffcaoff|ageffcbf|ageffcaobf|gf|af]]></c></tag>
<item>
@@ -638,7 +661,7 @@
good fit strategy is selected for allocator
<c><![CDATA[<S>]]></c>. When the good fit strategy is used, free
blocks are placed in segregated free-lists. Each free-list
- contains blocks of sizes in a specific range. The maxiumum block
+ contains blocks of sizes in a specific range. The maximum block
search depth sets a limit on the maximum number of blocks to
inspect in a free-list during a search for suitable block
satisfying the request.</p>
@@ -781,10 +804,6 @@
<seecref marker="#M_atags"><c>+M&lt;S&gt;atags</c></seecref> for a
more complete description.</p>
</item>
- <tag><marker id="Mit"/><c>+Mit X</c></tag>
- <item>
- <p>Reserved for future use. Do <em>not</em> use this flag.</p>
- </item>
</taglist>
<note>
diff --git a/erts/doc/src/inet_cfg.xml b/erts/doc/src/inet_cfg.xml
index 635156378e..76788f50b7 100644
--- a/erts/doc/src/inet_cfg.xml
+++ b/erts/doc/src/inet_cfg.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2020</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -79,7 +79,7 @@
<c><![CDATA['file']]></c> or <c><![CDATA['dns']]></c>, see below.</p>
<p>Native lookup (system calls) is always the default resolver method.
- This is true for all platforms, except VxWorks and OSE Delta where
+ This is true for all platforms, except OSE Delta where
<c><![CDATA['file']]></c> or <c><![CDATA['dns']]></c> is used (in that
priority order).</p>
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml
index 1b22cbe478..2d6b22a826 100644
--- a/erts/doc/src/init.xml
+++ b/erts/doc/src/init.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -108,7 +108,7 @@
3> <input>init:get_argument(progname).</input>
{ok,[["erl"]]}</pre>
</item>
- <tag><c>home</c></tag>
+ <tag><marker id="home"/><c>home</c></tag>
<item>
<p>The home directory (on Unix, the value of $HOME):</p>
<pre>
diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml
index 65a886fe96..988f895dde 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>2021</year>
+ <year>1999</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -113,8 +113,9 @@
<c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> |
<c><![CDATA[map_size]]></c> | <c><![CDATA[node]]></c> |
<c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> |
- <c><![CDATA[bit_size]]></c> |
+ <c><![CDATA[bit_size]]></c> | <c><![CDATA[byte_size]]></c> |
<c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> |
+ <c><![CDATA[binary_part]]></c> |
<c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> |
<c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> |
<c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> |
@@ -139,6 +140,7 @@
<c><![CDATA[process_dump]]></c> | <c><![CDATA[enable_trace]]></c> |
<c><![CDATA[disable_trace]]></c> | <c><![CDATA[trace]]></c> |
<c><![CDATA[display]]></c> | <c><![CDATA[caller]]></c> |
+ <c><![CDATA[caller_line]]></c> |
<c><![CDATA[set_tcw]]></c> | <c><![CDATA[silent]]></c>
</item>
</list>
@@ -195,8 +197,9 @@
<c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> |
<c><![CDATA[map_size]]></c> | <c><![CDATA[node]]></c> |
<c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> |
- <c><![CDATA[bit_size]]></c> |
+ <c><![CDATA[bit_size]]></c> | <c><![CDATA[byte_size]]></c> |
<c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> |
+ <c><![CDATA[binary_part]]></c> |
<c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> |
<c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> |
<c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> |
@@ -273,7 +276,8 @@
</item>
<tag><c>abs</c>, <c>element</c>, <c>hd</c>, <c>length</c>,
<c>map_get</c>, <c>map_size</c>, <c>node</c>, <c>round</c>,
- <c>size</c>, <c>bit_size</c>, <c>tl</c>, <c>trunc</c>, <c>'+'</c>,
+ <c>size</c>, <c>bit_size</c>, <c>byte_size</c>, <c>tl</c>,
+ <c>trunc</c>, <c>binary_part</c>, <c>'+'</c>,
<c>'-'</c>, <c>'*'</c>, <c>'div'</c>, <c>'rem'</c>, <c>'band'</c>,
<c>'bor'</c>, <c>'bxor'</c>, <c>'bnot'</c>, <c>'bsl'</c>,
<c>'bsr'</c>, <c>'>'</c>, <c>'>='</c>, <c>'&lt;'</c>, <c>'=&lt;'</c>,
@@ -435,6 +439,24 @@
<c><![CDATA[undefined]]></c>. The calling
Erlang function is not available during such calls.</p>
</item>
+ <tag><c>caller_line</c></tag>
+ <item>
+ <p>Similar to <c>caller</c> but returns additional information about
+ the source code location of the function call-site within the
+ caller function. Returns the calling function as a tuple
+ <c>{Module, Function, Arity, {File, Line}}</c>. <c>File</c> is the
+ <seeguide marker="system/reference_manual:data_types#string">string</seeguide>
+ file name while <c>Line</c> is source line number. If the <c>File</c>
+ and <c>Line</c> cannot be determined, <c>{Module, Function, Arity, undefined}</c>
+ is returned. If the calling function cannot be determined, the atom
+ <c><![CDATA[undefined]]></c> is returned. Can only be used in the
+ <c><![CDATA[MatchBody]]></c> part when tracing.</p>
+ <p>Notice that if a "technically built in function" (that is, a
+ function not written in Erlang) is traced, the
+ <c><![CDATA[caller_line]]></c> function sometimes returns the atom
+ <c><![CDATA[undefined]]></c>. The calling
+ Erlang function is not available during such calls.</p>
+ </item>
<tag><c>display</c></tag>
<item>
<p>For debugging purposes only. Displays the single argument as an
@@ -867,7 +889,7 @@
['$_']}]
]]></code>
- <p>Function <seemfa marker="stdlib:ets#test_ms/2"><c>ets:test_ms/2></c></seemfa>
+ <p>Function <seemfa marker="stdlib:ets#test_ms/2"><c>ets:test_ms/2</c></seemfa>
can be useful for testing complicated ETS matches.</p>
</section>
</chapter>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 8363f2b647..7f74df820d 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2022</year>
+ <year>2004</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,1692 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 13.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug on Windows where
+ <c>file:read_file_info/1</c> would fail for files with
+ corrupt metadata.</p>
+ <p>
+ Own Id: OTP-18348 Aux Id: GH-6356 </p>
+ </item>
+ <item>
+ <p>
+ Fix <c>process_info(_, binary)</c> to again include
+ "writable binaries" which were lost in OTP-25.0. Writable
+ binaries are an optimization used when binaries are
+ appended upon in a loop.</p>
+ <p>
+ Own Id: OTP-18373 Aux Id: PR-6574, GH-6573 </p>
+ </item>
+ <item>
+ <p>
+ Fix rare race when receiving fragmented messages on a
+ terminating connection. Could potentially cause memory
+ leaks as well as double free crashes. Bug exists since
+ OTP 22.0.</p>
+ <p>
+ Own Id: OTP-18382 Aux Id: PR-6585 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bug that could maybe cause problems when a file
+ descriptor number is closed by a linked in driver and
+ then opened (reused) and passed to <c>enif_select</c> by
+ a NIF. No actual symptoms seen, only failed internal
+ assertions in debug build.</p>
+ <p>
+ Own Id: OTP-18391</p>
+ </item>
+ <item>
+ <p>
+ The runtime system could crash when tracing a process
+ executing on a dirty scheduler.</p>
+ <p>
+ Own Id: OTP-18398 Aux Id: PR-6495, GH-6448, GH-5984 </p>
+ </item>
+ <item>
+ <p>In the binary syntax, attempting to match out integers
+ with size exceeding 2 GiB could crash the runtime
+ system.</p>
+ <p>
+ Own Id: OTP-18406 Aux Id: GH-6701 </p>
+ </item>
+ <item>
+ <p>Fixed edge case in floating-point negation where <c>A
+ = 0.0, B = -A</c> did not produce <c>B = -0.0</c> on
+ x86_64 JIT.</p>
+ <p>
+ Own Id: OTP-18411 Aux Id: GH-6717 </p>
+ </item>
+ <item>
+ <p>Fixed an issue in the JIT that could crash the
+ emulator on some platforms.</p>
+ <p>
+ Own Id: OTP-18418</p>
+ </item>
+ <item>
+ <p>
+ Added meta data to the windows installer.</p>
+ <p>
+ Own Id: OTP-18429 Aux Id: PR-6587 GH-4232 GH-6537 </p>
+ </item>
+ <item>
+ <p>Fixed ETS insertion order into <c>bag</c> and
+ <c>duplicate_bag</c> of tuples with identical keys when
+ passed in a list to <c>ets:insert/2</c>. The insert order
+ has been head-to-tail but was accidentally changed in OTP
+ 23.0. For <c>bag</c> it was reverted (tail-to-head),
+ while for <c>duplicate_bag</c> it was sometimes reverted
+ depending on the length of the list and number of
+ "reductions" left for the calling process.</p> <p>This
+ fix changes the insert order of <c>ets:insert/2</c> back
+ to always be head-to-tail of the list argument.</p>
+ <p>
+ Own Id: OTP-18434 Aux Id: PR-6752 </p>
+ </item>
+ <item>
+ <p>With the JIT for AArch64 (AMD64), calling <c>bxor</c>
+ in with non-integer arguments in a guard would crash the
+ runtime system.</p>
+ <p>
+ Own Id: OTP-18454 Aux Id: PR-6839 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug regarding process flag <c>max_heap_size</c>.
+ Could cause strange behavior when a process was killed
+ due to exceeding the limit.</p>
+ <p>
+ Own Id: OTP-18457 Aux Id: PR-6816 </p>
+ </item>
+ <item>
+ <p>
+ Fixed binary comprehensions to be similar to other
+ creation of binary data with respect to its contribution
+ of triggering garbage collection.</p>
+ <p>
+ Own Id: OTP-18458</p>
+ </item>
+ <item>
+ <p>In rare circumstances, when a process exceeded its
+ allowed heap size set by option <c>max_heap_size</c>, it
+ would not be killed as it should be, but instead enter a
+ kind of zombie state it would never get out of.</p>
+ <p>
+ Own Id: OTP-18463 Aux Id: PR-6858 </p>
+ </item>
+ <item>
+ <p>Instead of crashing, the <c>list_to_integer/1</c> and
+ <c>list_to_integer/2</c> BIFs now raise the
+ <c>system_limit</c> exception for overlong lists that
+ can't be converted to integers. Similarly, the
+ <c>string:to_integer/1</c> BIF now returns
+ <c>{error,system_limit}</c> for overlong lists.</p>
+ <p>
+ Own Id: OTP-18475 Aux Id: PR-6897 </p>
+ </item>
+ <item>
+ <p>
+ Active process aliases of a process at its termination
+ leaked memory.</p>
+ <p>
+ Own Id: OTP-18496 Aux Id: GH-6947, PR-6953 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support for fully asynchronous distributed signaling
+ where send operations <em>never</em> block. This
+ functionality is by default disabled and can be enabled
+ per process. For more information see the documentation
+ of <seeerl
+ marker="erts:erlang#process_flag_async_dist"><c>process_flag(async_dist,
+ Bool)</c></seeerl>.</p>
+ <p>
+ Own Id: OTP-18374 Aux Id: PR-6632 </p>
+ </item>
+ <item>
+ <p>Added the <c>+JPperf no_fp</c> option to explicitly
+ disable Erlang frame pointers otherwise added when using
+ the <c>+JPperf map</c> option.</p>
+ <p>
+ Own Id: OTP-18426</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Comparisons between small numbers and pids or ports
+ would in some edge cases say that the number was greater
+ than the pid or port, violating the term order.</p>
+ <p>
+ Own Id: OTP-18415</p>
+ </item>
+ <item>
+ <p>
+ <c>process_info(Pid, status)</c> when <c>Pid /=
+ self()</c> could return an erroneous result.</p>
+ <p>
+ Own Id: OTP-18421 Aux Id: PR-6806 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug in selective receive optimization that
+ could crash 32-bit emulators.</p>
+ <p>
+ Own Id: OTP-18383 Aux Id: ERIERL-905 </p>
+ </item>
+ <item>
+ <p>
+ A race condition which was very rarely triggered could
+ cause the signal queue of a process to become
+ inconsistent causing the runtime system to crash.</p>
+ <p>
+ Own Id: OTP-18388 Aux Id: OTP-17462, PR-6662 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix perf/gdb JIT symbols to not contain
+ <c>CodeInfoPrologue</c> for the JIT internal module
+ erts_beamasm.</p>
+ <p>
+ Own Id: OTP-18256 Aux Id: PR-6316 </p>
+ </item>
+ <item>
+ <p>
+ Fixed minor memory leaks.</p>
+ <p>
+ Own Id: OTP-18281 Aux Id: PR-4840 </p>
+ </item>
+ <item>
+ <p>Fix bugs in <c>ets:insert</c> and
+ <c>ets:insert_new</c> when called with a list of tuples
+ to insert while a concurrent process either deletes or
+ renames the table. The table deletion could be done with
+ <c>ets:delete/1</c> or be caused by termination of the
+ table owning process.</p> <p>Symptoms are either VM crash
+ or strange incorrect behavior from the insert operation.
+ The risk of triggering the bugs increases with the length
+ of the list of tuple to insert. Bugs exist since OTP
+ 23.0.</p>
+ <p>
+ Own Id: OTP-18284 Aux Id: PR-6305 </p>
+ </item>
+ <item>
+ <p>
+ Boost execution of scheduled thread progress jobs. This
+ to prevent memory exhaustion in extremely rapid
+ allocation/deallocation scenarios, such as repeated ETS
+ table creations/deletions.</p>
+ <p>
+ Own Id: OTP-18294 Aux Id: PR-6390 </p>
+ </item>
+ <item>
+ <p>
+ Fix segv crash during crash dumping an ETS table doing
+ <c>ets:delete_all_objects</c>.</p>
+ <p>
+ Own Id: OTP-18295</p>
+ </item>
+ <item>
+ <p>
+ Spec for function net:if_names/0 incorrect</p>
+ <p>
+ Own Id: OTP-18296 Aux Id: OTP-16464 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug in <c>binary_to_term</c> decoding a binary term
+ 2Gbyte or larger.</p>
+ <p>
+ Own Id: OTP-18306 Aux Id: GH-6393, PR-6401 </p>
+ </item>
+ <item>
+ <p>Documentation of <seemfa
+ marker="erts:erlang#module_loaded/1"><c>erlang:module_loaded/1</c></seemfa>
+ has been adjusted:</p> <list><item> It did not previously
+ say that the BIF only returns <c>true</c> for modules
+ loaded as <i>current code</i>. </item><item> The warning
+ claiming that the BIF should only be used by the code
+ server has been removed. </item></list>
+ <p>
+ Own Id: OTP-18313 Aux Id: PR-6456 </p>
+ </item>
+ <item>
+ <p>
+ Fix <c>list_to_atom/1</c> for negative code points. Could
+ either return with a positive code point or fail with an
+ incorrect exception.</p>
+ <p>
+ Own Id: OTP-18321</p>
+ </item>
+ <item>
+ <p>Fix rare bug causing VM crash when sending to a pid of
+ a spawning process returned from
+ <c>erlang:processes/0</c>.</p> <p>Only seen when provoked
+ by system process literal_area_collector, triggered by a
+ module purge operation, on a VM started with +Meamin (no
+ customized allocators).</p>
+ <p>
+ Own Id: OTP-18322 Aux Id: PR-6479 </p>
+ </item>
+ <item>
+ <p>
+ gen_udp:open/2 with option(s) add_membership or
+ drop_membership would drop earlier options.</p>
+ <p>
+ Own Id: OTP-18323 Aux Id: #6476 </p>
+ </item>
+ <item>
+ <p>
+ The <seemfa
+ marker="kernel:inet#setopts/2"><c>inet:setopts/2</c></seemfa>
+ <c>{reuseaddr, true}</c> option will now be ignored on
+ Windows unless the socket is an UDP socket. For more
+ information see the documentation of the <c>reuseaddr</c>
+ option part of the documentation of
+ <c>inet:setopts/2</c>.</p>
+ <p>
+ Prior to OTP 25 the <c>{reuseaddr, true}</c> option was
+ ignored for all sockets on Windows, but as of OTP 25.0
+ this was changed so that it was not ignored for any
+ sockets.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18324 Aux Id: GH-6461, PR-6481 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug in <c>binary_to_term</c> decoding a list of
+ length 1G or longer.</p>
+ <p>
+ Own Id: OTP-18328 Aux Id: GH-6439, PR-6440 </p>
+ </item>
+ <item>
+ <p>Fix bug in <c>binary_to_term</c> (and distributed
+ receive) when decoding a large map (&gt;32 keys) with
+ unsorted small maps (&lt;= 32) as keys of the large
+ map.</p>
+ <p>This was only a problem if the term was encoded by
+ <c>erl_interface</c>, <c>jinterface</c> or otherwise, as
+ the VM itself always encodes small maps with sorted
+ keys.</p>
+ <p>The "binary_to_term" would appear as successful but
+ the created large map was internally inconsistent. The
+ smaller key-maps could not be found with maps:get and
+ friends. Other operations such as map compare and merge
+ could probably also give incorrect results.</p>
+ <p>
+ Own Id: OTP-18343 Aux Id: GH-6496 </p>
+ </item>
+ <item>
+ <p>
+ Fix Windows bug in <c>open_port({spawn, Command}, ..)</c>
+ when <c>Command</c> is found via the OS search PATH and
+ that directory path contains white spaces. The port
+ program would start but the command line arguments to it
+ could be incorrect.</p>
+ <p>
+ Own Id: OTP-18345 Aux Id: GH-6387, PR-6396 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug in selective receive optimization that
+ could crash 32-bit emulators.</p>
+ <p>
+ Own Id: OTP-18383 Aux Id: ERIERL-905 </p>
+ </item>
+ <item>
+ <p>
+ A race condition which was very rarely triggered could
+ cause the signal queue of a process to become
+ inconsistent causing the runtime system to crash.</p>
+ <p>
+ Own Id: OTP-18388 Aux Id: OTP-17462, PR-6662 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Add abandon carrier free utilization limit
+ (<c>+Muacful</c>) option to erts_alloc. This option
+ allows the user to mark unused segments in a memory
+ carrier as re-useable by the OS if needed.</p>
+ <p>
+ This functionality was a non-configurable default before
+ Erlang/OTP 25, but removed due to performance issues.</p>
+ <p>
+ Own Id: OTP-18290 Aux Id: ERIERL-866 PR-6378 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Listen sockets created with the socket module, leaked
+ (erlang-) monitors.</p>
+ <p>
+ Own Id: OTP-18240 Aux Id: #6285 </p>
+ </item>
+ <item>
+ <p>
+ <seemfa
+ marker="erts:erlang#dist_ctrl_get_data_notification/1">Notifications
+ about available distribution data</seemfa> sent to
+ distribution controller processes could be lost.
+ Distribution controller processes can be used when
+ implementing an alternative distribution carrier. The
+ default distribution over tcp was not effected and the
+ bug was also not present on x86/x86_64 platforms.</p>
+ <p>
+ Own Id: OTP-18258 Aux Id: GH-6309, PR-6324 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed inconsistency bugs in <seeerl
+ marker="kernel:global"><c>global</c></seeerl> due to
+ <c>nodeup</c>/<c>nodedown</c> messages not being
+ delivered before/after traffic over connections. Also
+ fixed various other inconsistency bugs and deadlocks in
+ both <seeerl
+ marker="kernel:global_group"><c>global_group</c></seeerl>
+ and <c>global</c>.</p>
+ <p>
+ As building blocks for these fixes, a new BIF <seemfa
+ marker="erts:erlang#nodes/2"><c>erlang:nodes/2</c></seemfa>
+ has been introduced and <seemfa
+ marker="kernel:net_kernel#monitor_nodes/2"><c>net_kernel:monitor_nodes/2</c></seemfa>
+ has been extended.</p>
+ <p>
+ The <seecom
+ marker="erts:erl#hidden"><c>-hidden</c></seecom> and
+ <seecom
+ marker="erts:erl#connect_all"><c>-connect_all</c></seecom>
+ command line arguments did not work if multiple instances
+ were present on the command line which has been fixed.
+ The new kernel parameter <seeapp
+ marker="kernel:kernel_app#connect_all"><c>connect_all</c></seeapp>
+ has also been introduced in order to replace the
+ <c>-connect_all</c> command line argument.</p>
+ <p>
+ Own Id: OTP-17934 Aux Id: PR-6007 </p>
+ </item>
+ <item>
+ <p>
+ Fixed IPv6 multicast_if and membership socket options.</p>
+ <p>
+ Own Id: OTP-18091 Aux Id: #5789 </p>
+ </item>
+ <item>
+ <p>
+ Accept funs (NEW_FUN_EXT) with incorrectly encoded size
+ field. This is a workaround for a bug (OTP-18104)
+ existing in OTP 23 and 24 that could cause incorrect size
+ fields in certain cases. The emulator does not use the
+ decoded size field, but <c>erl_interface</c> still does
+ and is not helped by this workaround.</p>
+ <p>
+ Own Id: OTP-18093 Aux Id: OTP-18104, PR-5987 </p>
+ </item>
+ <item>
+ <p>
+ Fixed issue with inet:getifaddrs hanging on pure IPv6
+ Windows</p>
+ <p>
+ Own Id: OTP-18102 Aux Id: #5904 </p>
+ </item>
+ <item>
+ <p>Fix faulty distribution encoding of terms with
+ either</p> <list> <item>a fun with bit-string or
+ export-fun in its environment when encoded toward a not
+ yet established (pending) connection</item> <item>or a
+ fun with a binary/bitstring, in its environment,
+ referring to an off-heap binary (larger than 64
+ bytes).</item> </list> <p>The symptom could be failed
+ decoding on the receiving side leading to aborted
+ connection. Fix OTP-18093 is a workaround for theses bugs
+ that makes the VM accepts such faulty encoded funs.</p>
+ <p>The first encoding bug toward pending connection
+ exists only in OTP 23 and 24, but the second one exists
+ also on OTP 25.</p>
+ <p>
+ Own Id: OTP-18104 Aux Id: OTP-18093 </p>
+ </item>
+ <item>
+ <p>
+ Fixed emulator crash that could happen during crashdump
+ generation of ETS tables with options <c>ordered_set</c>
+ and <c>{write_concurrency,true}</c>.</p>
+ <p>
+ Own Id: OTP-18144 Aux Id: GH-5981 </p>
+ </item>
+ <item>
+ <p>
+ Retrieval of monotonic and system clock resolution on
+ MacOS could cause a crash and/or erroneous results.</p>
+ <p>
+ Own Id: OTP-18160 Aux Id: PR-6103 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where the max allowed size of <c>erl +hmax</c>
+ was lower than what was allowed by <c>process_flag</c>.</p>
+ <p>
+ Own Id: OTP-18161 Aux Id: PR-6081 </p>
+ </item>
+ <item>
+ <p>On computers with ARM64 (AArch64) processors, the JIT
+ could generate incorrect code when more than 4095 bits
+ were skipped at the tail end of a binary match.</p>
+ <p>
+ Own Id: OTP-18201</p>
+ </item>
+ <item>
+ <p>In rare circumstances, an <c>is_binary/1</c> guard
+ test could succeed when given a large integer.</p>
+ <p>
+ Own Id: OTP-18216 Aux Id: GH-6239, PR-6240 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug causing <c>ets:info</c> (and sometimes
+ <c>ets:whereis</c>) to return 'undefined' for an existing
+ table if a concurrent process were doing
+ <c>ets:insert</c> with a long list on the same table.</p>
+ <p>
+ Own Id: OTP-18218 Aux Id: ERIERL-855 </p>
+ </item>
+ <item>
+ <p>
+ Fix writing and reading of more than 2 GB in a single
+ read/write operation on macOS. Before this fix attempting
+ to read/write more than 2GB would result in
+ <c>{error,einval}</c>.</p>
+ <p>
+ Own Id: OTP-18222 Aux Id: PR-6248 GH-6242 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug sometimes causing emulator crash at node shutdown
+ when there are pending connections. Only seen when
+ running duel distribution protocols, inet_drv and
+ inet_tls_dist.</p>
+ <p>
+ Own Id: OTP-18243 Aux Id: GH-6247, PR-6258 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Yield when adjusting large process message queues due
+ to</p> <list> <item><p>copying terms from a literal area
+ prior to removing the literal area.</p></item>
+ <item><p>changing the <c>message_queue_data</c> state
+ from <c>on_heap</c> to <c>off_heap</c>.</p></item>
+ </list> <p>The message queue adjustment work will now be
+ interleaved with all other types of work that processes
+ have to do, even other message queue adjustment work.</p>
+ <p>
+ Own Id: OTP-17340 Aux Id: PR-6133 </p>
+ </item>
+ <item>
+ <p>
+ Add rudimentary debug feature (option) for the
+ inet-driver based sockets, such as gen_tcp and gen_udp.</p>
+ <p>
+ Own Id: OTP-18032</p>
+ </item>
+ <item>
+ <p>
+ Introduced the <c>hidden</c> and <c>dist_listen</c>
+ options to <seemfa
+ marker="kernel:net_kernel#start/2"><c>net_kernel:start/2</c></seemfa>.</p>
+ <p>
+ Also documented the <seecom
+ marker="erts:erl#dist_listen"><c>-dist_listen</c></seecom>
+ command line argument which was erroneously documented as
+ a <c>kernel</c> parameter and not as a command line
+ argument.</p>
+ <p>
+ Own Id: OTP-18107 Aux Id: PR-6009 </p>
+ </item>
+ <item>
+ <p>
+ New documentation chapter "Debugging NIFs and Port
+ Drivers" under Interoperability Tutorial.</p>
+ <p>
+ Own Id: OTP-18109</p>
+ </item>
+ <item>
+ <p>
+ Add new API function erl_features:configurable/0</p>
+ <p>
+ Own Id: OTP-18199 Aux Id: PR-5790 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The <seemfa
+ marker="erlang#monitor/3"><c>monitor/3</c></seemfa> BIF
+ did not apply options to the created monitor if the
+ target process or port did not exist. That is, the
+ corresponding down message would get a <c>`DOWN`</c> tag
+ even if a custom tag had been set, and the returned
+ reference was not an alias even if the <c>alias</c>
+ option had been passed.</p>
+ <p>
+ Own Id: OTP-18190 Aux Id: GH-6185, PR-6209 </p>
+ </item>
+ <item>
+ <p>
+ The <seemfa
+ marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time/1</c></seemfa>,
+ <seemfa
+ marker="erts:erlang#system_time/1"><c>erlang:system_time/1</c></seemfa>,
+ <seemfa
+ marker="erts:erlang#time_offset/1"><c>erlang:time_offset/1</c></seemfa>,
+ and <seemfa
+ marker="kernel:os#system_time/1"><c>os:system_time/1</c></seemfa>
+ BIFs erroneously failed when passed the argument
+ <c>native</c>.</p>
+ <p>
+ Own Id: OTP-18197 Aux Id: GH-6165, PR-6213 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Distributed exit signals could be lost under the
+ following conditions:</p> <list> <item><p> An exit signal
+ from a parent process to a child process was lost if:</p>
+ <list> <item><p> the parent process terminated before the
+ spawn request that created the child had completed,
+ </p></item> <item><p> the spawn request set up a link
+ between parent and child </p></item> <item><p> the spawn
+ request was distributed, and </p></item> <item><p> the
+ exit reason was larger than one machine word. </p></item>
+ </list> </item> <item><p> Loss of a connection over which
+ a not yet completed spawn request was ongoing could cause
+ loss of exit signals. Such loss of exit signals was very
+ rare. Besides the above described connection loss also
+ the following conditions had to be satisfied:</p> <list>
+ <item><p> The spawn request that was interrupted by the
+ connection loss also had to set up a link between the
+ parent process and the child process. </p></item>
+ <item><p> The parent process that issued the spawn
+ request also had to be terminating while the spawn
+ request was interrupted by the connection loss.
+ </p></item> <item><p> The same parent process also had to
+ have made other spawn requests to other nodes than to the
+ node to which the connection was lost. </p></item>
+ <item><p> These spawn requests to the other nodes also
+ had to set up links. </p></item> <item><p> These spawn
+ requests to the other nodes also had to be not yet
+ completed at the time of the connection loss. That is,
+ the spawn reply from the child process had not yet
+ reached the parent process. </p></item> </list> <p>If all
+ the conditions above were met, exit signals to the
+ children spawned due to the above described spawn
+ requests to other nodes <em>could</em> be lost.</p>
+ <p>The above bug also caused a significant memory leak
+ when it was triggered since the destruction of the parent
+ process never completed.</p> </item> </list>
+ <p>
+ Own Id: OTP-18164 Aux Id: PR-6114 </p>
+ </item>
+ <item>
+ <p>
+ A race could cause <c>process_info(Pid,
+ message_queue_len)</c> on other processes to return
+ invalid results.</p>
+ <p>
+ Own Id: OTP-18169 Aux Id: PR-6134 </p>
+ </item>
+ <item>
+ <p>
+ Fixed reduction counting for handling process system
+ tasks.</p>
+ <p>
+ Own Id: OTP-18170 Aux Id: PR-6135 </p>
+ </item>
+ <item>
+ <p>
+ Priority elevation of terminating processes did not work
+ which could cause execution of such processes to be
+ delayed.</p>
+ <p>
+ Own Id: OTP-18175 Aux Id: PR-6142 </p>
+ </item>
+ <item>
+ <p>
+ An unlink operation made by a process that terminated
+ before the unlink operation completed, i.e., before it
+ had received an unlink-ack signal from the linked
+ process, caused an exit signal to erroneously be sent
+ from the terminating process to the process being
+ unlinked. This exit signal would most often be ignored by
+ the receiver, but if the receiver of the exit signal
+ concurrently set up a new link, it could receive the exit
+ signal with the actual exit reason of the terminating
+ process instead of a <c>noproc</c> exit reason. It is
+ however very hard to detect that this has happened and
+ has no obvious negative consequences, so it should be
+ considered harmless.</p>
+ <p>
+ A distributed unlink-ack signal received by a terminating
+ process was also not properly removed which could cause a
+ minor memory leak.</p>
+ <p>
+ Own Id: OTP-18177 Aux Id: PR-6150 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>On computers with the ARM64 (AArch64) architecture
+ (such as Apple Silicon Macs) a <c>rem</c> expression
+ followed by a <c>div</c> expression with the same
+ operands could evaluate to the wrong result if the result
+ of the <c>rem</c> expression was unused.</p>
+ <p>
+ Own Id: OTP-18143</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A <c>spawn_reply</c> signal from a remote node could be
+ delayed and be delivered after other signals from the
+ newly spawned process.</p>
+ <p>
+ When this bug triggered, the connection to the node where
+ the process was spawned sometimes could be taken down due
+ to the bug. The following error message would then be
+ logged if this happened: <c>Missing 'spawn_reply' signal
+ from the node &lt;RemoteNode&gt; detected by &lt;Pid&gt;
+ on the node &lt;LocalNode&gt;. The node
+ &lt;RemoteNode&gt; probably suffers from the bug with
+ ticket id OTP-17737.</c></p>
+ <p>
+ This bug only affected processes which had enabled
+ <seeerl
+ marker="erts:erlang#process_flag_message_queue_data"><c>off_heap</c>
+ <c>message_queue_data</c></seeerl> and parallel reception
+ of signals had been automatically enabled.</p>
+ <p>
+ This bug was introduced in OTP 25.0, ERTS version 13.0.</p>
+ <p>
+ Own Id: OTP-18105 Aux Id: OTP-16982, PR-6003 </p>
+ </item>
+ <item>
+ <p>
+ Fixed type spec of <c>erlang:system_info(dist_ctrl)</c>.</p>
+ <p>
+ Own Id: OTP-18106 Aux Id: PR-5992 </p>
+ </item>
+ <item>
+ <p>
+ The zlib built in to the runtime system has been updated
+ to version 1.2.12. (Note that on most platforms, the
+ platform's own zlib is used.)</p>
+ <p>
+ Own Id: OTP-18123 Aux Id: GH-5994 </p>
+ </item>
+ <item>
+ <p>
+ The <c>erlang:is_alive()</c> BIF could return <c>true</c>
+ before configured distribution service was available.
+ This bug was introduced in OTP 25.0 ERTS version 13.0.</p>
+ <p>
+ The <c>erlang:monitor_node()</c> and
+ <c>erlang:monitor()</c> BIFs could erroneously fail even
+ though configured distribution service was available.
+ This occurred if these BIFs were called after the
+ distribution had been started using dynamic node name
+ assignment but before the name had been assigned.</p>
+ <p>
+ Own Id: OTP-18124 Aux Id: OTP-17558, PR-6032 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 13.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The socket option 'reuseaddr' is *no longer* ignored on
+ Windows.</p>
+ <p>
+ Own Id: OTP-17447 Aux Id: GH-4819 </p>
+ </item>
+ <item>
+ <p>
+ The growth rate of writable binaries has been adjusted to
+ only increase by 20% after 16MB in size. Before this
+ change the size would always double.</p>
+ <p>
+ This change may degrade write performance of large
+ binaries.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17569 Aux Id: PR-4793 </p>
+ </item>
+ <item>
+ <p>
+ Fix reduction counting bug in <c>re:run</c> that caused
+ the function to yield too frequently when doing
+ <c>global</c> matches.</p>
+ <p>
+ Own Id: OTP-17661 Aux Id: PR-5165 </p>
+ </item>
+ <item>
+ <p>
+ Fix spelling mistakes in epmd error messages.</p>
+ <p>
+ Own Id: OTP-17758 Aux Id: PR-5391 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where the "newshell" would trigger a newline at
+ the column width of the terminal, even if the next
+ character to be printed was a newline. This would cause
+ the terminal to render two newlines instead of one.</p>
+ <p>
+ Own Id: OTP-17779 Aux Id: GH-5403 PR-5599 </p>
+ </item>
+ <item>
+ <p>
+ Fix the memory value returned from
+ <c>ets:info(Tid,memory)</c> when the
+ <c>read_concurrency</c> option is used.</p>
+ <p>
+ Before this fix the memory used by the scheduler specific
+ lock cache lines was not counted towards the total. This
+ caused the returned memory usage to be very incorrect on
+ systems with many schedulers for tables with man locks.</p>
+ <p>
+ Own Id: OTP-17832 Aux Id: PR-5494 </p>
+ </item>
+ <item>
+ <p>
+ Fix the undocumented <c>--profile_boot</c> option to work
+ again.</p>
+ <p>
+ Own Id: OTP-17836 Aux Id: PR-5546 </p>
+ </item>
+ <item>
+ <p>
+ [socket] Encode of sockaddr has been improved.</p>
+ <p>
+ Own Id: OTP-18020</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>erl_child_setup</c> (the program used by
+ <c>open_port({spawn,...})</c> and <c>os:cmd/1</c>) to
+ better handle partial reads from the Erlang VM.</p>
+ <p>
+ Own Id: OTP-18047 Aux Id: PR-5861 </p>
+ </item>
+ <item>
+ <p>The runtime system would crash when attempting to
+ create more than 33554431 atoms.</p>
+ <p>
+ Own Id: OTP-18068 Aux Id: GH-5903 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Users can now configure ETS tables with the
+ <c>{write_concurrency, auto}</c> option. This option
+ forces tables to automatically change the number of locks
+ that are used at run-time depending on how much
+ concurrency is detected. The <c>{decentralized_counters,
+ true}</c> option is enabled by default when
+ <c>{write_concurrency, auto}</c> is active.</p>
+ <p>
+ Benchmark results comparing this option with the other
+ ETS optimization options are available here:</p>
+ <p>
+ https://erlang.org/bench/ets_bench_result_lock_config.html</p>
+ <p>
+ Own Id: OTP-15991 Aux Id: PR-5208 </p>
+ </item>
+ <item>
+ <p>
+ The net module now works on Windows.</p>
+ <p>
+ Own Id: OTP-16464</p>
+ </item>
+ <item>
+ <p>To enable more optimizations, BEAM files compiled with
+ OTP 21 and earlier cannot be loaded in OTP 25.</p>
+ <p>
+ Own Id: OTP-16702</p>
+ </item>
+ <item>
+ <p>
+ Optimize minor garbage collection for processes with
+ large number of binaries, funs and/or external
+ pids/ports/refs. This is a continuation of the
+ optimization (OTP-17602) released in OTP-24.1.</p>
+ <p>
+ Own Id: OTP-16852 Aux Id: ERL-1347, PR-5195 </p>
+ </item>
+ <item>
+ <p>
+ The signal queue of a process with
+ message_queue_data=off_heap* has been optimized to allow
+ parallel reception of signals from multiple processes. </p>
+ <p>
+ This is possible to do as Erlang only guarantees that
+ signals (i.e., message signals and non-message signals)
+ sent from a single process to another process are ordered
+ in send order. However, there are no ordering guarantees
+ for signals sent from different processes to a particular
+ process. Therefore, several processes can send signals in
+ parallel to a specific process without synchronizing with
+ each other. However, such signal sending was previously
+ always serialized as the senders had to acquire the lock
+ for the outer signal queue of the receiving process. This
+ parallel signal sending optimization yields much better
+ scalability for signal sending than what was previously
+ possible, see
+ https://erlang.org/bench/sigq_bench_result.html for
+ benchmark results.</p>
+ <p>
+ * Information about how to enable the
+ message_queue_data=off_heap setting can be found in the
+ documentation of the function erlang:process_flag/2.</p>
+ <p>
+ Own Id: OTP-16982 Aux Id: PR-5020 </p>
+ </item>
+ <item>
+ <p>The JIT now works for 64-bit ARM processors.</p>
+ <p>
+ Own Id: OTP-17119 Aux Id: PR-4869 </p>
+ </item>
+ <item>
+ <p>
+ Added support for the compile attribute <c>-nifs()</c> to
+ empower compiler and loader with information about which
+ functions may be overridden as NIFs by
+ <c>erlang:load_nif/2</c>. It is recommended to use this
+ attribute in all modules that load NIF libraries.</p>
+ <p>
+ Own Id: OTP-17151 Aux Id: ERIERL-590, PR-5479 </p>
+ </item>
+ <item>
+ <p>
+ A test case has been added to the otp_SUITE that test
+ that the dependency versions for OTP's applications are
+ correct. The test case uses xref to check if the used
+ functions are available in the specified dependency
+ versions. The test case depends on the Erlang/OTP team's
+ testing infrastructure and will be skipped if its
+ dependencies are not met.</p>
+ <p>
+ Own Id: OTP-17224</p>
+ </item>
+ <item>
+ <p>
+ An Erlang installation directory is now relocatable on
+ the file system given that the paths in the
+ installation's <c>RELEASES</c> file are paths that are
+ relative to the installations root directory. The
+ <c>`release_handler:create_RELEASES/4</c> function can
+ generate a <c>RELEASES</c> file with relative paths if
+ its <c>RootDir</c> parameter is set to the empty string.</p>
+ <p>
+ Own Id: OTP-17304</p>
+ </item>
+ <item>
+ <p>The following distribution flags are now mandatory:
+ <c>DFLAG_BIT_BINARIES</c>, <c>DFLAG_EXPORT_PTR_TAG</c>,
+ <c>DFLAG_MAP_TAGS</c>, <c>DFLAG_NEW_FLOATS</c>, and
+ <c>DFLAG_FUN_TAGS</c>. This mainly concerns libraries or
+ application that implement the distribution protocol
+ themselves.</p>
+ <p>
+ Own Id: OTP-17318 Aux Id: PR-4972 </p>
+ </item>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>When binary construction using the binary syntax
+ fails, the error message printed in the shell and by
+ <c>erl_error:format_exception/3,4</c> will contain more
+ detailed information about what went wrong.</p>
+ <p>
+ Own Id: OTP-17504 Aux Id: GH-4971, PR-5281, PR-5752 </p>
+ </item>
+ <item>
+ <p>
+ The configuration files <seecom
+ marker="erts:erl"><c>.erlang</c></seecom>, <seeguide
+ marker="system/reference_manual:distributed"><c>.erlang.cookie</c></seeguide>
+ and <seeerl
+ marker="stdlib:beam_lib#.erlang.crypt"><c>.erlang.crypt</c></seeerl>
+ can now be located in the XDG Config Home directory.</p>
+ <p>
+ See the documentation for each file and
+ <c>filename:basedir/2</c> for more details.</p>
+ <p>
+ Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821 </p>
+ </item>
+ <item>
+ <p>
+ Make <c>byte_size/1</c> and <c>binary_part/2/3</c>
+ callable from match specs (in ETS and tracing).</p>
+ <p>
+ Own Id: OTP-17555 Aux Id: PR-5027 </p>
+ </item>
+ <item>
+ <p>
+ Dynamic node name improvements: <c>erlang:is_alive/0</c>
+ changed to return true for pending dynamic node name and
+ new function <c>net_kernel:get_state/0</c>.</p>
+ <p>
+ Own Id: OTP-17558 Aux Id: OTP-17538, PR-5111, GH-5402 </p>
+ </item>
+ <item>
+ <p>
+ A new option called <c>short</c> has been added to the
+ functions <c>erlang:float_to_list</c> and
+ <c>erlang:float_to_binary</c>. This option creates the
+ shortest correctly rounded string representation of the
+ given float that can be converted back to the same float
+ again.</p>
+ <p>
+ Own Id: OTP-17562 Aux Id: GH-4492 </p>
+ </item>
+ <item>
+ <p>
+ The tagged tuple tests and fun-calls have been optimized
+ and are now a little bit cheaper than previously.</p>
+ <p>
+ These optimizations become possible after making sure
+ that all boxed terms have at least one word allocated
+ after the arity word. This has been accomplished by
+ letting all empty tuples refer to the same empty tuple
+ literal which also reduces memory usage for empty tuples.</p>
+ <p>
+ Own Id: OTP-17608</p>
+ </item>
+ <item>
+ <p>
+ The signal queue benchmark in parallel_messages_SUITE and
+ the ETS benchmark in ets_SUITE have benchmark result
+ visualization HTML pages with "fill-screen" buttons to
+ make the graphs bigger. This button did not work as
+ intended before. When pressing the button for a graph,
+ the last graph got replaced with a bigger version and not
+ the one over the button. This is now fixed.</p>
+ <p>
+ Own Id: OTP-17630</p>
+ </item>
+ <item>
+ <p>
+ The test case num_bif_SUITE:t_float_to_string previously
+ failed sometimes as it assumed a certain rounding of
+ floats printed with sprintf but the rounding type is
+ platform specific.</p>
+ <p>
+ Own Id: OTP-17636</p>
+ </item>
+ <item>
+ <p>
+ Optimize interpreter to create heap binaries of small
+ match contexts if possible.</p>
+ <p>
+ This optimization was already done in the JIT.</p>
+ <p>
+ Own Id: OTP-17660 Aux Id: PR-5164 </p>
+ </item>
+ <item>
+ <p>
+ Optimize integer multiplication for x86 JIT</p>
+ <p>
+ Own Id: OTP-17667 Aux Id: PR-5237 </p>
+ </item>
+ <item>
+ <p>
+ Removed use of node creation value zero as a wildcard.
+ Also prevent zero from being used as creation by
+ <c>erl_interface</c> and <c>jinterface</c> nodes.</p>
+ <p>
+ Own Id: OTP-17682 Aux Id: PR-5347 </p>
+ </item>
+ <item>
+ <p>
+ Distributed spawn operations now require <seeguide
+ marker="erts:erl_dist_protocol#DFLAG_SPAWN">distributed
+ <c>spawn_request()</c></seeguide> support. Distributed
+ <c>spawn_request()</c> was introduced in OTP 23. That is,
+ distributed spawn operations against Erlang nodes of
+ releases prior to OTP 23 will fail.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17683 Aux Id: PR-5306 </p>
+ </item>
+ <item>
+ <p>The Erlang compiler now includes type information in
+ BEAM files, and the JIT can now use that type information
+ to do optimizations such as eliminating or simplifying
+ type tests.</p>
+ <p>
+ Own Id: OTP-17684 Aux Id: PR-5316, PR-5664 </p>
+ </item>
+ <item>
+ <p>Improved the JIT's support for external tools like
+ <c>perf</c> and <c>gdb</c>, allowing them to show line
+ numbers and even the original Erlang source code when
+ that can be found.</p>
+ <p>To aid them in finding the source code, the
+ <c>absolute_path</c> compiler option has been added to
+ embed the absolute file path of a module.</p>
+ <p>
+ Own Id: OTP-17685</p>
+ </item>
+ <item>
+ <p>
+ Add [32-bit] to the Erlang shell title row for 32-bit
+ VMs.</p>
+ <p>
+ Own Id: OTP-17717 Aux Id: PR-5290 </p>
+ </item>
+ <item>
+ <p>Instructions for how to build the runtime system for
+ iOS/iPadOS can now be found in
+ <c>HOWTO/INSTALL.md</c>.</p>
+ <p>
+ Own Id: OTP-17728 Aux Id: PR-5284 </p>
+ </item>
+ <item>
+ <p>
+ Add support for static Elixir NIF modules with
+ non-alphanumeric characters by using new macro
+ <c>STATIC_ERLANG_NIF_LIBNAME</c>.</p>
+ <p>
+ Own Id: OTP-17729 Aux Id: PR-5477 </p>
+ </item>
+ <item>
+ <p>
+ Add new function <c>caller_line</c> to for trace match
+ specifications used by erlang:trace_pattern/3.</p>
+ <p>
+ This new option puts the line number of the caller into
+ the trace message sent to the trace receiver.</p>
+ <p>
+ Own Id: OTP-17753 Aux Id: PR-5305 GH-5297 </p>
+ </item>
+ <item>
+ <p>
+ A new <c>erl</c> command line argument <c>+ssrct</c> has
+ been introduced which will cause the runtime system to
+ skip reading CPU topology information. This reduce start
+ up time especially when the CPU topology is large.
+ Reading of CPU topology information is now also skipped
+ if a user defined CPU topology is set using the
+ <c>+sct</c> command line argument.</p>
+ <p>
+ Own Id: OTP-17762 Aux Id: GH-5204, PR-5219 </p>
+ </item>
+ <item>
+ <p>
+ The default time warp mode will change in Erlang/OTP 26.
+ Added a warning about this upcoming potential
+ incompatibility to the documentation.</p>
+ <p>
+ Own Id: OTP-17772 Aux Id: GH-4965 PR-5644 </p>
+ </item>
+ <item>
+ <p>The emulator will no longer mark unused memory as
+ discardable (e.g. through <c>madvise(2)</c>), as it
+ caused more problems than it solved.</p>
+ <p>
+ Own Id: OTP-17824</p>
+ </item>
+ <item>
+ <p>When a record matching or record update fails, a
+ <c>{badrecord,ExpectedRecordTag}</c> exception used to be
+ raised. In this release, the exception has been changed
+ to <c>{badrecord,ActualValue}</c>, where
+ <c>ActualValue</c> is the actual that was found instead
+ of the expected record.</p>
+ <p>
+ Own Id: OTP-17841 Aux Id: PR-5694 </p>
+ </item>
+ <item>
+ <p>
+ Removed the previously undocumented and unsupported
+ <c>emem</c> tool.</p>
+ <p>
+ Own Id: OTP-17892 Aux Id: PR-5591 </p>
+ </item>
+ <item>
+ <p>
+ Remove version number from the default install path on
+ Windows.</p>
+ <p>
+ Own Id: OTP-17899 Aux Id: PR-5524 </p>
+ </item>
+ <item>
+ <p>
+ On Windows apply the limit flag
+ JOB_OBJECT_LIMIT_BREAKAWAY_OK in the Erlang service to be
+ able to start a OS child process with a different session
+ number.</p>
+ <p>
+ Own Id: OTP-17927 Aux Id: PR-5283 </p>
+ </item>
+ <item>
+ <p>
+ New erl command line option <c>+IOs</c>. It can be used
+ to disable scheduler thread poll optimization, which has
+ been seen to cause degraded event latency in some use
+ cases.</p>
+ <p>
+ Own Id: OTP-17945 Aux Id: GH-4759, PR-5809 </p>
+ </item>
+ <item>
+ <p>
+ An API for multihomed SCTP connect has been added in the
+ guise of <c>gen_sctp:connectx_init/*</c></p>
+ <p>
+ Own Id: OTP-17951 Aux Id: PR-5656 </p>
+ </item>
+ <item>
+ <p>
+ [socket] Add encoding of the field hatype of the type
+ sockaddr_ll (family 'packet').</p>
+ <p>
+ Own Id: OTP-17968 Aux Id: OTP-16464 </p>
+ </item>
+ <item>
+ <p>
+ A cross compilation issue has been fixed about finding
+ libdlpi during the configure phase.</p>
+ <p>
+ Own Id: OTP-17985 Aux Id: GH-5728 </p>
+ </item>
+ <item>
+ <p>
+ <seemfa
+ marker="erts:erlang#process_info/2"><c>process_info/2</c></seemfa>
+ now also accepts <c>parent</c> as argument. When passed,
+ the process identifier of the parent process will be
+ returned.</p>
+ <p>
+ Own Id: OTP-17999 Aux Id: PR-5768 </p>
+ </item>
+ <item>
+ <p>
+ Add function attributes to <c>erl_nif</c> and
+ <c>erl_driver</c> APis to improve compiler detection of
+ interface misuse.</p>
+ <p>
+ Own Id: OTP-18006 Aux Id: PR-5932 </p>
+ </item>
+ <item>
+ <p>
+ The exported type <seetype
+ marker="erts:erlang#send_destination"><c>erlang:send_destination/0</c></seetype>
+ has been introduced.</p>
+ <p>
+ Own Id: OTP-18033 Aux Id: PR-2926, GH-5376 </p>
+ </item>
+ <item>
+ <p>
+ Building of the C/C++ make dependencies on Windows has
+ been optimized to be a lot faster.</p>
+ <p>
+ Own Id: OTP-18036 Aux Id: PR-5846 </p>
+ </item>
+ <item>
+ <p><c>file:sync/1</c> will now use the
+ <c>F_BARRIERFSYNC</c> flag when available on Mac OS.</p>
+ <p>
+ Own Id: OTP-18038</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>process_info(Pid, status)</c> when <c>Pid /=
+ self()</c> could return an erroneous result.</p>
+ <p>
+ Own Id: OTP-18421 Aux Id: PR-6806 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, when a process exceeded its
+ allowed heap size set by option <c>max_heap_size</c>, it
+ would not be killed as it should be, but instead enter a
+ kind of zombie state it would never get out of.</p>
+ <p>
+ Own Id: OTP-18463 Aux Id: PR-6858 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug in selective receive optimization that
+ could crash 32-bit emulators.</p>
+ <p>
+ Own Id: OTP-18383 Aux Id: ERIERL-905 </p>
+ </item>
+ <item>
+ <p>
+ A race condition which was very rarely triggered could
+ cause the signal queue of a process to become
+ inconsistent causing the runtime system to crash.</p>
+ <p>
+ Own Id: OTP-18388 Aux Id: OTP-17462, PR-6662 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Spec for function net:if_names/0 incorrect</p>
+ <p>
+ Own Id: OTP-18296 Aux Id: OTP-16464 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug in <c>binary_to_term</c> decoding a binary term
+ 2Gbyte or larger.</p>
+ <p>
+ Own Id: OTP-18306 Aux Id: GH-6393, PR-6401 </p>
+ </item>
+ <item>
+ <p>
+ Fix <c>list_to_atom/1</c> for negative code points. Could
+ either return with a positive code point or fail with an
+ incorrect exception.</p>
+ <p>
+ Own Id: OTP-18321</p>
+ </item>
+ <item>
+ <p>
+ Fix bug in <c>binary_to_term</c> decoding a list of
+ length 1G or longer.</p>
+ <p>
+ Own Id: OTP-18328 Aux Id: GH-6439, PR-6440 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <seemfa
+ marker="erts:erlang#dist_ctrl_get_data_notification/1">Notifications
+ about available distribution data</seemfa> sent to
+ distribution controller processes could be lost.
+ Distribution controller processes can be used when
+ implementing an alternative distribution carrier. The
+ default distribution over tcp was not effected and the
+ bug was also not present on x86/x86_64 platforms.</p>
+ <p>
+ Own Id: OTP-18258 Aux Id: GH-6309, PR-6324 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix writing and reading of more than 2 GB in a single
+ read/write operation on macOS. Before this fix attempting
+ to read/write more than 2GB would result in
+ <c>{error,einval}</c>.</p>
+ <p>
+ Own Id: OTP-18222 Aux Id: PR-6248 GH-6242 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug causing <c>ets:info</c> (and sometimes
+ <c>ets:whereis</c>) to return 'undefined' for an existing
+ table if a concurrent process were doing
+ <c>ets:insert</c> with a long list on the same table.</p>
+ <p>
+ Own Id: OTP-18218 Aux Id: ERIERL-855 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix faulty distribution encoding of terms with
+ either</p> <list> <item>a fun with bit-string or
+ export-fun in its environment when encoded toward a not
+ yet established (pending) connection</item> <item>or a
+ fun with a binary/bitstring, in its environment,
+ referring to an off-heap binary (larger than 64
+ bytes).</item> </list> <p>The symptom could be failed
+ decoding on the receiving side leading to aborted
+ connection. Fix OTP-18093 is a workaround for theses bugs
+ that makes the VM accepts such faulty encoded funs.</p>
+ <p>The first encoding bug toward pending connection
+ exists only in OTP 23 and 24, but the second one exists
+ also on OTP 25.</p>
+ <p>
+ Own Id: OTP-18104 Aux Id: OTP-18093 </p>
+ </item>
+ <item>
+ <p>Distributed exit signals could be lost under the
+ following conditions:</p> <list> <item><p> An exit signal
+ from a parent process to a child process was lost if:</p>
+ <list> <item><p> the parent process terminated before the
+ spawn request that created the child had completed,
+ </p></item> <item><p> the spawn request set up a link
+ between parent and child </p></item> <item><p> the spawn
+ request was distributed, and </p></item> <item><p> the
+ exit reason was larger than one machine word. </p></item>
+ </list> </item> <item><p> Loss of a connection over which
+ a not yet completed spawn request was ongoing could cause
+ loss of exit signals. Such loss of exit signals was very
+ rare. Besides the above described connection loss also
+ the following conditions had to be satisfied:</p> <list>
+ <item><p> The spawn request that was interrupted by the
+ connection loss also had to set up a link between the
+ parent process and the child process. </p></item>
+ <item><p> The parent process that issued the spawn
+ request also had to be terminating while the spawn
+ request was interrupted by the connection loss.
+ </p></item> <item><p> The same parent process also had to
+ have made other spawn requests to other nodes than to the
+ node to which the connection was lost. </p></item>
+ <item><p> These spawn requests to the other nodes also
+ had to set up links. </p></item> <item><p> These spawn
+ requests to the other nodes also had to be not yet
+ completed at the time of the connection loss. That is,
+ the spawn reply from the child process had not yet
+ reached the parent process. </p></item> </list> <p>If all
+ the conditions above were met, exit signals to the
+ children spawned due to the above described spawn
+ requests to other nodes <em>could</em> be lost.</p>
+ <p>The above bug also caused a significant memory leak
+ when it was triggered since the destruction of the parent
+ process never completed.</p> </item> </list>
+ <p>
+ Own Id: OTP-18164 Aux Id: PR-6114 </p>
+ </item>
+ <item>
+ <p>
+ A race could cause <c>process_info(Pid,
+ message_queue_len)</c> on other processes to return
+ invalid results.</p>
+ <p>
+ Own Id: OTP-18169 Aux Id: PR-6134 </p>
+ </item>
+ <item>
+ <p>
+ Fixed reduction counting for handling process system
+ tasks.</p>
+ <p>
+ Own Id: OTP-18170 Aux Id: PR-6135 </p>
+ </item>
+ <item>
+ <p>
+ Priority elevation of terminating processes did not work
+ which could cause execution of such processes to be
+ delayed.</p>
+ <p>
+ Own Id: OTP-18175 Aux Id: PR-6142 </p>
+ </item>
+ <item>
+ <p>
+ An unlink operation made by a process that terminated
+ before the unlink operation completed, i.e., before it
+ had received an unlink-ack signal from the linked
+ process, caused an exit signal to erroneously be sent
+ from the terminating process to the process being
+ unlinked. This exit signal would most often be ignored by
+ the receiver, but if the receiver of the exit signal
+ concurrently set up a new link, it could receive the exit
+ signal with the actual exit reason of the terminating
+ process instead of a <c>noproc</c> exit reason. It is
+ however very hard to detect that this has happened and
+ has no obvious negative consequences, so it should be
+ considered harmless.</p>
+ <p>
+ A distributed unlink-ack signal received by a terminating
+ process was also not properly removed which could cause a
+ minor memory leak.</p>
+ <p>
+ Own Id: OTP-18177 Aux Id: PR-6150 </p>
+ </item>
+ <item>
+ <p>
+ The <seemfa
+ marker="erlang#monitor/3"><c>monitor/3</c></seemfa> BIF
+ did not apply options to the created monitor if the
+ target process or port did not exist. That is, the
+ corresponding down message would get a <c>`DOWN`</c> tag
+ even if a custom tag had been set, and the returned
+ reference was not an alias even if the <c>alias</c>
+ option had been passed.</p>
+ <p>
+ Own Id: OTP-18190 Aux Id: GH-6185, PR-6209 </p>
+ </item>
+ <item>
+ <p>
+ The <seemfa
+ marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time/1</c></seemfa>,
+ <seemfa
+ marker="erts:erlang#system_time/1"><c>erlang:system_time/1</c></seemfa>,
+ <seemfa
+ marker="erts:erlang#time_offset/1"><c>erlang:time_offset/1</c></seemfa>,
+ and <seemfa
+ marker="kernel:os#system_time/1"><c>os:system_time/1</c></seemfa>
+ BIFs erroneously failed when passed the argument
+ <c>native</c>.</p>
+ <p>
+ Own Id: OTP-18197 Aux Id: GH-6165, PR-6213 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed emulator crash that could happen during crashdump
+ generation of ETS tables with options <c>ordered_set</c>
+ and <c>{write_concurrency,true}</c>.</p>
+ <p>
+ Own Id: OTP-18144 Aux Id: GH-5981 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 12.3.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Accept funs (NEW_FUN_EXT) with incorrectly encoded size
+ field. This is a workaround for a bug (OTP-18104)
+ existing in OTP 23 and 24 that could cause incorrect size
+ fields in certain cases. The emulator does not use the
+ decoded size field, but <c>erl_interface</c> still does
+ and is not helped by this workaround.</p>
+ <p>
+ Own Id: OTP-18093 Aux Id: OTP-18104, PR-5987 </p>
+ </item>
+ <item>
+ <p>
+ The zlib built in to the runtime system has been updated
+ to version 1.2.12. (Note that on most platforms, the
+ platform's own zlib is used.)</p>
+ <p>
+ Own Id: OTP-18123 Aux Id: GH-5994 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 12.3.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -619,7 +2305,7 @@
simultaneously received signals to that port could cause
a runtime system crash. The effected signals are
<c>link</c>, <c>monitor</c> and <c>demonitor</c>. On OTP
- 22 a similiar race could also cause a memory leak when
+ 22 a similar race could also cause a memory leak when
receiving an <c>unlink</c> signal.</p>
<p>
Own Id: OTP-17642 Aux Id: PR-5248 </p>
@@ -1326,7 +3012,7 @@
order to prevent late responses. The <c>gen_statem</c>
behavior still use a proxy process in the distributed
case, since it has always prevented late replies and
- aliases wont work against pre OTP 24 nodes. The proxy
+ aliases won't work against pre OTP 24 nodes. The proxy
process can be removed in OTP 26.</p>
<p>
The alias feature also made it possible to introduce new
@@ -1623,6 +3309,340 @@
</section>
+<section><title>Erts 11.2.2.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <seemfa
+ marker="erts:erlang#dist_ctrl_get_data_notification/1">Notifications
+ about available distribution data</seemfa> sent to
+ distribution controller processes could be lost.
+ Distribution controller processes can be used when
+ implementing an alternative distribution carrier. The
+ default distribution over tcp was not effected and the
+ bug was also not present on x86/x86_64 platforms.</p>
+ <p>
+ Own Id: OTP-18258 Aux Id: GH-6309, PR-6324 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 11.2.2.16</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Distributed exit signals could be lost under the
+ following conditions:</p> <list> <item><p> An exit signal
+ from a parent process to a child process was lost if:</p>
+ <list> <item><p> the parent process terminated before the
+ spawn request that created the child had completed,
+ </p></item> <item><p> the spawn request set up a link
+ between parent and child </p></item> <item><p> the spawn
+ request was distributed, and </p></item> <item><p> the
+ exit reason was larger than one machine word. </p></item>
+ </list> </item> <item><p> Loss of a connection over which
+ a not yet completed spawn request was ongoing could cause
+ loss of exit signals. Such loss of exit signals was very
+ rare. Besides the above described connection loss also
+ the following conditions had to be satisfied:</p> <list>
+ <item><p> The spawn request that was interrupted by the
+ connection loss also had to set up a link between the
+ parent process and the child process. </p></item>
+ <item><p> The parent process that issued the spawn
+ request also had to be terminating while the spawn
+ request was interrupted by the connection loss.
+ </p></item> <item><p> The same parent process also had to
+ have made other spawn requests to other nodes than to the
+ node to which the connection was lost. </p></item>
+ <item><p> These spawn requests to the other nodes also
+ had to set up links. </p></item> <item><p> These spawn
+ requests to the other nodes also had to be not yet
+ completed at the time of the connection loss. That is,
+ the spawn reply from the child process had not yet
+ reached the parent process. </p></item> </list> <p>If all
+ the conditions above were met, exit signals to the
+ children spawned due to the above described spawn
+ requests to other nodes <em>could</em> be lost.</p>
+ <p>The above bug also caused a significant memory leak
+ when it was triggered since the destruction of the parent
+ process never completed.</p> </item> </list>
+ <p>
+ Own Id: OTP-18164 Aux Id: PR-6114 </p>
+ </item>
+ <item>
+ <p>
+ A race could cause <c>process_info(Pid,
+ message_queue_len)</c> on other processes to return
+ invalid results.</p>
+ <p>
+ Own Id: OTP-18169 Aux Id: PR-6134 </p>
+ </item>
+ <item>
+ <p>
+ Fixed reduction counting for handling process system
+ tasks.</p>
+ <p>
+ Own Id: OTP-18170 Aux Id: PR-6135 </p>
+ </item>
+ <item>
+ <p>
+ Priority elevation of terminating processes did not work
+ which could cause execution of such processes to be
+ delayed.</p>
+ <p>
+ Own Id: OTP-18175 Aux Id: PR-6142 </p>
+ </item>
+ <item>
+ <p>
+ An unlink operation made by a process that terminated
+ before the unlink operation completed, i.e., before it
+ had received an unlink-ack signal from the linked
+ process, caused an exit signal to erroneously be sent
+ from the terminating process to the process being
+ unlinked. This exit signal would most often be ignored by
+ the receiver, but if the receiver of the exit signal
+ concurrently set up a new link, it could receive the exit
+ signal with the actual exit reason of the terminating
+ process instead of a <c>noproc</c> exit reason. It is
+ however very hard to detect that this has happened and
+ has no obvious negative consequences, so it should be
+ considered harmless.</p>
+ <p>
+ A distributed unlink-ack signal received by a terminating
+ process was also not properly removed which could cause a
+ minor memory leak.</p>
+ <p>
+ Own Id: OTP-18177 Aux Id: PR-6150 </p>
+ </item>
+ <item>
+ <p>
+ The <seemfa
+ marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time/1</c></seemfa>,
+ <seemfa
+ marker="erts:erlang#system_time/1"><c>erlang:system_time/1</c></seemfa>,
+ <seemfa
+ marker="erts:erlang#time_offset/1"><c>erlang:time_offset/1</c></seemfa>,
+ and <seemfa
+ marker="kernel:os#system_time/1"><c>os:system_time/1</c></seemfa>
+ BIFs erroneously failed when passed the argument
+ <c>native</c>.</p>
+ <p>
+ Own Id: OTP-18197 Aux Id: GH-6165, PR-6213 </p>
+ </item>
+ <item>
+ <p>
+ Fix writing and reading of more than 2 GB in a single
+ read/write operation on macOS. Before this fix attempting
+ to read/write more than 2GB would result in
+ <c>{error,einval}</c>.</p>
+ <p>
+ Own Id: OTP-18222 Aux Id: PR-6248 GH-6242 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 11.2.2.15</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix faulty distribution encoding of terms with
+ either</p> <list> <item>a fun with bit-string or
+ export-fun in its environment when encoded toward a not
+ yet established (pending) connection</item> <item>or a
+ fun with a binary/bitstring, in its environment,
+ referring to an off-heap binary (larger than 64
+ bytes).</item> </list> <p>The symptom could be failed
+ decoding on the receiving side leading to aborted
+ connection. Fix OTP-18093 is a workaround for theses bugs
+ that makes the VM accepts such faulty encoded funs.</p>
+ <p>The first encoding bug toward pending connection
+ exists only in OTP 23 and 24, but the second one exists
+ also on OTP 25.</p>
+ <p>
+ Own Id: OTP-18104 Aux Id: OTP-18093 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 11.2.2.14</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Accept funs (NEW_FUN_EXT) with incorrectly encoded size
+ field. This is a workaround for a bug (OTP-18104)
+ existing in OTP 23 and 24 that could cause incorrect size
+ fields in certain cases. The emulator does not use the
+ decoded size field, but <c>erl_interface</c> still does
+ and is not helped by this workaround.</p>
+ <p>
+ Own Id: OTP-18093 Aux Id: OTP-18104, PR-5987 </p>
+ </item>
+ <item>
+ <p>
+ The zlib built in to the runtime system has been updated
+ to version 1.2.12. (Note that on most platforms, the
+ platform's own zlib is used.)</p>
+ <p>
+ Own Id: OTP-18123 Aux Id: GH-5994 </p>
+ </item>
+ <item>
+ <p>
+ Fixed emulator crash that could happen during crashdump
+ generation of ETS tables with options <c>ordered_set</c>
+ and <c>{write_concurrency,true}</c>.</p>
+ <p>
+ Own Id: OTP-18144 Aux Id: GH-5981 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 11.2.2.13</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Let EPMD tolerate failure when binding to IPv4/IPv6
+ loopback intefaces in addition to user-supplied addresses
+ via <c>ERL_EPMD_ADDRESS</c> or the <c>-address</c>
+ option. This can happen, for example, if the host system
+ has ipv6 disabled via the disable_ipv6 sysctl.</p>
+ <p>
+ Own Id: OTP-17970 Aux Id: PR-5762 </p>
+ </item>
+ <item>
+ <p>Fixed a rare bug in <c>binary_to_term/1</c>,
+ <c>enif_make_map_from_arrays</c>,
+ <c>erl_drv_send_term</c>, and Erlang distribution that
+ could crash the emulator.</p>
+ <p>
+ Own Id: OTP-18027</p>
+ </item>
+ <item>
+ <p>Fixed a rare race in <c>persistent_term:get/1,2</c>
+ that could cause it to return the value of another
+ key.</p>
+ <p>
+ Own Id: OTP-18065 Aux Id: GH-5908 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where the process message queue was left in an
+ inconsistent state when changing from on_heap to off_heap
+ message queue data causing the GC to segfault.</p>
+ <p>
+ Own Id: OTP-18075 Aux Id: PR-5927 </p>
+ </item>
+ <item>
+ <p>
+ Fix functions that convert universal to localtime (such
+ as erlang:localtime/0 and
+ erlang:universaltime_to_localtime/1) to fetch the correct
+ localtime if it is changed after the start of the VM.</p>
+ <p>
+ Own Id: OTP-18076 Aux Id: ERIERL-802 PR-5905 </p>
+ </item>
+ <item>
+ <p>
+ Fix memory leak when a process doing a distributed
+ fragmented send is sent an exit signal. Before this fix
+ the receiving node would be left with an incomplete
+ message that would remain until the nodes were
+ disconnected. The bug has existed since Erlang/OTP 21.</p>
+ <p>
+ Own Id: OTP-18077 Aux Id: GH-5876 PR-5892 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 11.2.2.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix Erlang monotonic time on MacOS. Previously used OS
+ monotonic time primitive on MacOS is buggy and will not
+ be used anymore. It has been replaced with usage of
+ another OS monotonic time primitive that does not appear
+ to be buggy.</p>
+ <p>
+ Own Id: OTP-17998 Aux Id: PR-5825, GH-5554 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 11.2.2.11</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> By default <c>global</c> does <i>not</i> take any
+ actions to restore a fully connected network when
+ connections are lost due to network issues. This is
+ problematic for all applications expecting a fully
+ connected network to be provided, such as for example
+ <c>mnesia</c>, but also for <c>global</c> itself. A
+ network of overlapping partitions might cause the
+ internal state of <c>global</c> to become inconsistent.
+ Such an inconsistency can remain even after such
+ partitions have been brought together to form a fully
+ connected network again. The effect on other applications
+ that expects that a fully connected network is maintained
+ may vary, but they might misbehave in very subtle hard to
+ detect ways during such a partitioning. </p> <p> In order
+ to prevent such issues, we have introduced a <i>prevent
+ overlapping partitions</i> fix which can be enabled using
+ the <seeapp
+ marker="kernel:kernel_app#prevent_overlapping_partitions"><c>prevent_overlapping_partitions</c></seeapp>
+ <c>kernel(6)</c> parameter. When this fix has been
+ enabled, <c>global</c> will actively disconnect from
+ nodes that reports that they have lost connections to
+ other nodes. This will cause fully connected partitions
+ to form instead of leaving the network in a state with
+ overlapping partitions. Note that this fix <i>has</i> to
+ be enabled on <i>all</i> nodes in the network in order to
+ work properly. Since this quite substantially changes the
+ behavior, this fix is currently disabled by default.
+ Since you might get hard to detect issues without this
+ fix you are, however, <i>strongly</i> advised to enable
+ this fix in order to avoid issues such as the ones
+ described above. As of OTP 25 this fix will become
+ enabled by default. </p>
+ <p>
+ Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611 </p>
+ </item>
+ <item>
+ <p>
+ Fix memory leak when tracing on running on a process that
+ only handle system tasks or non-message signals (for
+ example process_info requests).</p>
+ <p>
+ Own Id: OTP-17904 Aux Id: ERIERL-757 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 11.2.2.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1740,7 +3760,7 @@
simultaneously received signals to that port could cause
a runtime system crash. The effected signals are
<c>link</c>, <c>monitor</c> and <c>demonitor</c>. On OTP
- 22 a similiar race could also cause a memory leak when
+ 22 a similar race could also cause a memory leak when
receiving an <c>unlink</c> signal.</p>
<p>
Own Id: OTP-17642 Aux Id: PR-5248 </p>
@@ -2984,7 +5004,7 @@
<item>
<p>Internally in BEAM, handling of continuation pointers
has been simplified. This change is not user-visible,
- except when examing a process stack in the crashdump
+ except when examining a process stack in the crashdump
viewer. The continuation pointer for a function will now
be stored below the y(0) for that function.</p>
<p>
@@ -3418,6 +5438,104 @@
</section>
+<section><title>Erts 10.7.2.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug where the process message queue was left in an
+ inconsistent state when changing from on_heap to off_heap
+ message queue data causing the GC to segfault.</p>
+ <p>
+ Own Id: OTP-18075 Aux Id: PR-5927 </p>
+ </item>
+ <item>
+ <p>
+ Fix functions that convert universal to localtime (such
+ as erlang:localtime/0 and
+ erlang:universaltime_to_localtime/1) to fetch the correct
+ localtime if it is changed after the start of the VM.</p>
+ <p>
+ Own Id: OTP-18076 Aux Id: ERIERL-802 PR-5905 </p>
+ </item>
+ <item>
+ <p>
+ Fix memory leak when a process doing a distributed
+ fragmented send is sent an exit signal. Before this fix
+ the receiving node would be left with an incomplete
+ message that would remain until the nodes were
+ disconnected. The bug has existed since Erlang/OTP 21.</p>
+ <p>
+ Own Id: OTP-18077 Aux Id: GH-5876 PR-5892 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 10.7.2.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> By default <c>global</c> does <i>not</i> take any
+ actions to restore a fully connected network when
+ connections are lost due to network issues. This is
+ problematic for all applications expecting a fully
+ connected network to be provided, such as for example
+ <c>mnesia</c>, but also for <c>global</c> itself. A
+ network of overlapping partitions might cause the
+ internal state of <c>global</c> to become inconsistent.
+ Such an inconsistency can remain even after such
+ partitions have been brought together to form a fully
+ connected network again. The effect on other applications
+ that expects that a fully connected network is maintained
+ may vary, but they might misbehave in very subtle hard to
+ detect ways during such a partitioning. </p> <p> In order
+ to prevent such issues, we have introduced a <i>prevent
+ overlapping partitions</i> fix which can be enabled using
+ the <c>prevent_overlapping_partitions</c>
+ <c>kernel(6)</c> parameter. When this fix has been
+ enabled, <c>global</c> will actively disconnect from
+ nodes that reports that they have lost connections to
+ other nodes. This will cause fully connected partitions
+ to form instead of leaving the network in a state with
+ overlapping partitions. Note that this fix <i>has</i> to
+ be enabled on <i>all</i> nodes in the network in order to
+ work properly. Since this quite substantially changes the
+ behavior, this fix is currently disabled by default.
+ Since you might get hard to detect issues without this
+ fix you are, however, <i>strongly</i> advised to enable
+ this fix in order to avoid issues such as the ones
+ described above. As of OTP 25 this fix will become
+ enabled by default. </p>
+ <p>
+ Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611 </p>
+ </item>
+ <item>
+ <p>
+ Fix memory leak when tracing on running on a process that
+ only handle system tasks or non-message signals (for
+ example process_info requests).</p>
+ <p>
+ Own Id: OTP-17904 Aux Id: ERIERL-757 </p>
+ </item>
+ <item>
+ <p>
+ Fix Erlang monotonic time on MacOS. Previously used OS
+ monotonic time primitive on MacOS is buggy and will not
+ be used anymore. It has been replaced with usage of
+ another OS monotonic time primitive that does not appear
+ to be buggy.</p>
+ <p>
+ Own Id: OTP-17998 Aux Id: PR-5825, GH-5554 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 10.7.2.16</title>
<section><title>Improvements and New Features</title>
@@ -3514,7 +5632,7 @@
simultaneously received signals to that port could cause
a runtime system crash. The effected signals are
<c>link</c>, <c>monitor</c> and <c>demonitor</c>. On OTP
- 22 a similiar race could also cause a memory leak when
+ 22 a similar race could also cause a memory leak when
receiving an <c>unlink</c> signal.</p>
<p>
Own Id: OTP-17642 Aux Id: PR-5248 </p>
@@ -7854,7 +9972,7 @@
<c>cpu_timestamp</c> in <seemfa
marker="erlang#trace/3">erlang:trace/3</seemfa> to use
it instead of per process CPU time. This makes this
- option useable on such OSs when running multiple
+ option usable on such OSs when running multiple
schedulers.</p>
<p>
Own Id: OTP-15090</p>
@@ -7898,7 +10016,7 @@
</item>
<item>
<p>
- Fix segfault when a process is interally re-scheduled
+ Fix segfault when a process is internally re-scheduled
while being traced for in out events. This bug was
introduced in erts-8.0 (OTP-19.0).</p>
<p>
@@ -8449,7 +10567,7 @@
request signal to the other process and waits for the
result instead of locking the other process and reading
the result directly. In some special cases where no
- conflicts occur, signal order wont be violated, and the
+ conflicts occur, signal order won't be violated, and the
amount of data requested is guaranteed to be small, the
inspected process may be inspected directly.</p>
<p>
@@ -10666,7 +12784,7 @@
<item>
<p>
Add option to make SIGTERM trigger the OS default
- behaviour instead of doing a gracefull shutdown. To
+ behaviour instead of doing a graceful shutdown. To
activate this bahviour the environment variable
ERL_ZZ_SIGTERM_KILL should be set to "true". This option
only works in OTP 19 as OTP 20 will have a different way
@@ -10995,9 +13113,9 @@
<p>
Fix a quite rare bug causing VM crash during code loading
and the use of export funs (fun M:F/A) of not yet loaded
- modules. Requires a very specfic timing of concurrent
+ modules. Requires a very specific timing of concurrent
scheduler threads. Has been seen on ARM but can probably
- also occure on other architectures. Bug has existed since
+ also occurred on other architectures. Bug has existed since
OTP R16.</p>
<p>
Own Id: OTP-14144 Aux Id: seq13242 </p>
@@ -11301,7 +13419,7 @@
</item>
<item>
<p>
- Update build scripts to not make assumtions about where
+ Update build scripts to not make assumptions about where
env, cp and perl are located.</p>
<p>
Own Id: OTP-13800</p>
@@ -13176,7 +15294,7 @@
<p>
Fix global call trace when hipe compiled code call beam
compiled functions. Tracing of beam functions should now
- alway work regardless who the caller is.</p>
+ always work regardless who the caller is.</p>
<p>
Own Id: OTP-11939</p>
</item>
@@ -13552,7 +15670,7 @@
<p>
Development of perfctr in the linux kernel ceased in
2010. The perfctr support code in the Erlang VM is thus
- effectively dead code and therefor removed.</p>
+ effectively dead code and therefore removed.</p>
<p>
Own Id: OTP-12508</p>
</item>
@@ -14197,7 +16315,7 @@
<item>
<p>
Fix two cases of unreachable code caused by false use of
- assigment operators.</p>
+ assignment operators.</p>
<p>
Own Id: OTP-12222</p>
</item>
@@ -15251,11 +17369,11 @@
Characteristics impact: A call to the
<c>garbage_collect/1</c> BIF or the
<c>check_process_code/2</c> BIF will normally take longer
- time to complete while the system as a whole wont be as
+ time to complete while the system as a whole won't be as
much negatively effected by the operation as before. A
call to <c>code:purge/1</c> and <c>code:soft_purge/1</c>
may complete faster or slower depending on the state of
- the system while the system as a whole wont be as much
+ the system while the system as a whole won't be as much
negatively effected by the operation as before.</p>
<p>
Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648 </p>
@@ -16249,7 +18367,7 @@
system:</p> <list> <item>Reduced memory footprint when
the memory load is unevenly distributed between scheduler
specific allocator instances.</item> <item>Depending on
- the default allocaton strategy used on a specific
+ the default allocation strategy used on a specific
allocator there might or might not be a slight
performance loss.</item> <item>When enabled on the
<c>fix_alloc</c> allocator, a different strategy for
@@ -16531,7 +18649,7 @@
<item>Memory leak when terminating ports</item>
<item>Memory leak when reaching the system limit of
maximum amount of concurrently existing ports</item>
- <item>Crashs due to missing, or late test of bad port
+ <item>Crashes due to missing, or late test of bad port
handle</item> <item>The newly introduced driver API
function <c>erl_drv_busy_msgq_limits()</c> could not be
used by dynamically linked in drivers on Windows</item>
@@ -16542,7 +18660,7 @@
<item>
<p>
Fix <c>{packet,httph}</c> header capitalization for
- unrecognized header fields longer than 20 charachters
+ unrecognized header fields longer than 20 characters
such as <c>Sec-Websocket-Version</c>. The limit is simply
raised from 20 to 50 characters with the hope that valid
headers longer than 50 are not used.</p>
@@ -16740,7 +18858,7 @@
For instance, prefer sbc segments over mbc segments,
caching policy is time-arrow aware, evicting older cached
segments to store newer segments. </p> <p>The default
- number of cachable segment has been increased from five
+ number of cacheable segment has been increased from five
to ten segments. This can be modified, same as before,
with the command line option <c>+MMmcs 5</c></p>
<p>Impact: Increased speed for processing on larger
@@ -16815,8 +18933,8 @@
<item>
<p>
The effect of the deprecated environment variable
- ERL_MAX_PORTS had been removed premeturely. It has now
- been readded. Note that this is still scheduled to be
+ ERL_MAX_PORTS had been removed prematurely. It has now
+ been re-added. Note that this is still scheduled to be
released in R17B.</p>
<p>
Own Id: OTP-10895</p>
@@ -17044,7 +19162,7 @@
port lock as well as truly asynchronous communication
with ports.</item> <item>Optimized lookup of port handles
from drivers.</item> <item>Optimized driver lookup when
- creating ports.</item> <item>Preemptable <seemfa
+ creating ports.</item> <item>Preemptible <seemfa
marker="erts:erlang#ports/0">erlang:ports/0</seemfa>
BIF.</item> <item>Improving responsiveness by bumping
reductions for a process calling a driver callback
@@ -17606,7 +19724,7 @@
</item>
<item>
<p>
- Correct formating in exit error messages</p>
+ Correct formatting in exit error messages</p>
<p>
Ensure displayed sizes are not negative. (Thanks to
Michael Santos)</p>
@@ -17963,7 +20081,7 @@
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
- <p><c>erlang:system_profile</c> errorneous profiled the
+ <p><c>erlang:system_profile</c> erroneous profiled the
profiler process when observing runnable processes. This
has been corrected. </p>
<p>
@@ -18044,7 +20162,7 @@
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
+ argument. Note that now is flushing not dependent of the
exit code, and you cannot only flush async threads
operations which we deemed as a strange behaviour anyway.
</p>
@@ -20355,7 +22473,7 @@
<p>
<c>epmd</c> used to generate a message to the syslog when
it started up, which could be annoying. This has been
- changed to only generate the message if the debug swith
+ changed to only generate the message if the debug switch
is given. (Thanks to Michael Santos.)</p>
<p>
Own Id: OTP-8775</p>
@@ -20531,7 +22649,7 @@
<item>
<p>
Extreme combinations of register/unregister in a highly
- parallell SMP application could crash the VM. The error
+ parallel SMP application could crash the VM. The error
is corrected.</p>
<p>
Own Id: OTP-8663</p>
@@ -20775,7 +22893,7 @@
<item>
<p>
Support for using gcc's built-in functions for atomic
- memory access has been added. This functionallity will be
+ memory access has been added. This functionality will be
used if available and no other native atomic
implementation in ERTS is available.</p>
<p>
@@ -21256,7 +23374,7 @@
GC. See the documentation for <c>spawn_opt/2-5</c>,
<c>erlang:system_info/1</c>, <c>erlang:system_flag/2</c>,
<c>process_flag/2-3</c>, <c>erlang:trace/3</c>, and the
- documenation for <c>erl</c> for the new command line
+ documentation for <c>erl</c> for the new command line
options <c>+hms</c> and <c>+hmbs</c>.</p>
<p>
Own Id: OTP-8370</p>
@@ -21286,7 +23404,7 @@
app-vsn/ebin/mod.beam file, the file info for the app-vsn
and app-vsn/ebin directories are faked using the file
info from the archive file as origin. The virtual
- direcories can also be listed. For short, the top
+ directories can also be listed. For short, the top
directories are virtual if they does not exist.</p>
<p>
Own Id: OTP-8387</p>
@@ -21709,7 +23827,7 @@
</item>
<item>
<p>
- The pthread rwlock implemention on Linux could cause
+ The pthread rwlock implementation on Linux could cause
starvation of writers. We, therefore, now use our own
rwlock implementation on Linux.</p>
<p>
@@ -22795,7 +24913,7 @@
</item>
<item>
<p>
- Floating point arithmetics in drivers could cause a
+ Floating point arithmetic in drivers could cause a
runtime system crash and/or unexpected results on runtime
systems with floating point exceptions enabled. Floating
point exceptions are disabled unless explicitly enabled
@@ -22807,7 +24925,7 @@
<p>
A bug when many sockets got signalled simultaneously
causing the emulator to panic with the message
- "Inconsistent, why isnt io reported?" is now corrected.</p>
+ "Inconsistent, why isn't io reported?" is now corrected.</p>
<p>
Own Id: OTP-7420</p>
</item>
@@ -23265,7 +25383,7 @@
<list>
<item>
<p>
- Floating point arithmetics in drivers can cause a runtime
+ Floating point arithmetic in drivers can cause a runtime
system crash and/or unexpected results on runtime systems
with floating point exceptions enabled. Floating point
exceptions are disabled unless explicitly enabled or if
@@ -23591,7 +25709,7 @@
<list>
<item>
<p>
- Floating point arithmetics in drivers can cause a runtime
+ Floating point arithmetic in drivers can cause a runtime
system crash on runtime systems with floating point
exceptions enabled. Floating point exceptions are
disabled unless explicitly enabled or if hipe is enabled.</p>
@@ -24643,7 +26761,7 @@
<p>Attempting to construct a binary longer than 536870911
bytes will now fail with a <c><![CDATA[system_limit]]></c> exception
(rather than fail in mysterious ways or construct an
- binary with incorrect contents). Similarily, attempting
+ binary with incorrect contents). Similarly, attempting
to match a binary longer than 536870911 bytes will now
fail (instead of producing an incorrect result). This
limitation has been documented in the Efficiency Guide.
diff --git a/erts/doc/src/persistent_term.xml b/erts/doc/src/persistent_term.xml
index 46cb313ff1..c2e967b694 100644
--- a/erts/doc/src/persistent_term.xml
+++ b/erts/doc/src/persistent_term.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2018</year><year>2020</year>
+ <year>2018</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -50,7 +50,7 @@
performance when updating or deleting persistent terms.</p></warning>
<p>Term lookup (using <seemfa
- marker="#get/1"><c>get/1</c></seemfa>), is done in constant time
+ marker="#get/1"><c>get/1</c></seemfa>) is done in constant time
and without taking any locks, and the term is <strong>not</strong>
copied to the heap (as is the case with terms stored in ETS
tables).</p>
@@ -71,7 +71,7 @@
scan of their heaps for the term that has been deleted. While
such scan is relatively light-weight, if there are many
processes, the system can become less responsive until all
- process have scanned their heaps.</p></item>
+ processes have scanned their heaps.</p></item>
<item><p>If the deleted term (or any part of it) is still used
by a process, that process will do a major (fullsweep) garbage
@@ -146,7 +146,7 @@
<p>Updating or deleting a persistent term will trigger a global GC
if the term does not fit in one machine word. Processes will be
scheduled as usual, but all processes will be made runnable at
- once, which will make the system less responsive until all process
+ once, which will make the system less responsive until all processes
have run and scanned their heaps for the deleted terms. One way to
minimize the effects on responsiveness could be to minimize the
number of processes on the node before updating or deleting a
@@ -157,7 +157,7 @@
persistent term could be deleted or updated in the future. If a
process holds a reference to a persistent term when the term is
deleted, the process will be garbage collected and the term copied
- to process.</p>
+ to the process.</p>
<p>Avoid updating or deleting more than one persistent term at a
time. Each deleted term will trigger its own global GC. That
diff --git a/erts/emulator/Makefile b/erts/emulator/Makefile
index 65fdbdb747..b1a363082c 100644
--- a/erts/emulator/Makefile
+++ b/erts/emulator/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -23,3 +23,5 @@
include $(ERL_TOP)/make/run_make.mk
+include $(ERL_TOP)/make/app_targets.mk
+
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 99da2b101e..979f76c4c6 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -33,6 +33,7 @@ LIBS = @LIBS@
Z_LIB=@Z_LIB@
CROSS_COMPILING = @CROSS_COMPILING@
NO_INLINE_FUNCTIONS=false
+USING_VC=@MIXED_VC@
OPCODE_TABLES = \
$(ERL_TOP)/lib/compiler/src/genop.tab \
@@ -56,7 +57,7 @@ JIT_ENABLED=no
endif
ifeq ($(FLAVOR),jit)
-OMIT_OMIT_FP=no
+OMIT_OMIT_FP=yes
OPCODE_TABLES += \
beam/jit/$(JIT_ARCH)/ops.tab \
beam/jit/$(JIT_ARCH)/predicates.tab \
@@ -202,8 +203,10 @@ space+=
STATIC_NIFS=@STATIC_NIFS@
ifneq ($(STATIC_NIFS),no)
ifeq ($(STATIC_NIFS),yes)
-STATIC_NIFS=$(ERL_TOP)/lib/asn1/priv/lib/$(TARGET)/asn1rt_nif.a \
- $(ERL_TOP)/lib/crypto/priv/lib/$(TARGET)/crypto$(TYPEMARKER).a
+STATIC_NIFS=$(ERL_TOP)/lib/asn1/priv/lib/$(TARGET)/asn1rt_nif.a
+ifeq ($(wildcard $(ERL_TOP)/lib/crypto/SKIP),)
+ STATIC_NIFS+=$(ERL_TOP)/lib/crypto/priv/lib/$(TARGET)/crypto$(TYPEMARKER).a
+endif
endif
STATIC_NIFS:=$(subst $(comma),$(space),$(STATIC_NIFS))
endif
@@ -218,7 +221,7 @@ endif
#
-# NOTE: When adding a new type update ERL_BUILD_TYPE_MARKER in sys/unix/sys.c
+# NOTE: When adding a new type update ERL_BUILD_TYPE_MARKER in sys/unix/sys_drivers.c
#
FLAVOR_MARKER=.$(FLAVOR)
@@ -371,6 +374,14 @@ endif
EPCRE_LIB = $(ERL_TOP)/erts/emulator/pcre/obj/$(TARGET)/$(TYPE)/$(LIB_PREFIX)epcre$(LIB_SUFFIX)
DEPLIBS += $(EPCRE_LIB)
+DEPLIBS += $(RYU_LIBRARY)
+ifeq ($(TARGET),win32)
+LIBS += -L$(RYU_OBJDIR) -lryu
+else
+# Build on darwin fails if -lryu is used
+LIBS += $(RYU_LIBRARY)
+endif
+
LIBSCTP = @LIBSCTP@
ORG_THR_LIBS=@EMU_THR_LIBS@
@@ -412,7 +423,8 @@ OBJDIR = obj/$(TTF_DIR)
CREATE_DIRS += $(OBJDIR) \
pcre/obj/$(TARGET)/$(TYPE) \
- $(ZLIB_OBJDIR)
+ $(ZLIB_OBJDIR) \
+ $(RYU_OBJDIR)
ifeq ($(FLAVOR),jit)
CREATE_DIRS+=$(OBJDIR)/asmjit/ $(OBJDIR)/asmjit/core $(OBJDIR)/asmjit/$(JIT_ARCH)
@@ -427,8 +439,10 @@ ENABLE_ALLOC_TYPE_VARS += @ERLANG_OSTYPE@
ifeq ($(TARGET), win32)
FLAVOR_EXECUTABLE = beam$(TF_MARKER).dll
+EMULATOR_LIB = libbeam.lib
else
FLAVOR_EXECUTABLE = beam$(TF_MARKER)
+EMULATOR_LIB = libbeam.a
PROFILE_EXECUTABLE = beam.prof$(TF_MARKER)
endif
CS_EXECUTABLE = erl_child_setup$(TYPEMARKER)
@@ -467,7 +481,7 @@ ifdef VOID_EMULATOR
all:
@echo $(VOID_EMULATOR)' - omitted target all'
else
-all: $(BINDIR)/$(EMULATOR_EXECUTABLE) $(UNIX_ONLY_BUILDS)
+all: $(BINDIR)/$(EMULATOR_EXECUTABLE) $(BINDIR)/$(EMULATOR_LIB) $(UNIX_ONLY_BUILDS)
endif
$(BINDIR)/$(PRIMARY_EXECUTABLE): $(BINDIR)/$(FLAVOR_EXECUTABLE)
@@ -478,6 +492,7 @@ endif
include zlib/zlib.mk
include pcre/pcre.mk
+include ryu/ryu.mk
$(ERTS_LIB):
$(V_at)cd $(ERTS_LIB_DIR) && $(MAKE) $(TYPE)
@@ -490,6 +505,7 @@ clean:
$(RM) -r obj/$(TARGET)
$(RM) -r pcre/obj/$(TARGET) $(PCRE_GENINC)
$(RM) -r zlib/obj/$(TARGET)
+ $(RM) -r ryu/obj/$(TARGET)
$(RM) -r bin/$(TARGET)
cd $(ERTS_LIB_DIR) && $(MAKE) clean
@@ -522,6 +538,10 @@ release_spec: all
$(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELEASE_PATH)/usr/include"
$(INSTALL_DATA) $(RELEASE_INCLUDES) "$(RELSYSDIR)/include"
$(INSTALL_PROGRAM) $(BINDIR)/$(EMULATOR_EXECUTABLE) "$(RELSYSDIR)/bin"
+ifeq ($(RELEASE_LIBBEAM),yes)
+ $(INSTALL_DIR) "$(RELSYSDIR)/lib"
+ $(INSTALL_PROGRAM) $(BINDIR)/$(EMULATOR_LIB) "$(RELSYSDIR)/lib"
+endif
ifeq ($(ERLANG_OSTYPE), unix)
$(INSTALL_PROGRAM) $(BINDIR)/$(CS_EXECUTABLE) "$(RELSYSDIR)/bin"
endif
@@ -575,6 +595,11 @@ $(TTF_DIR)/OPCODES-GENERATED: $(OPCODE_TABLES) utils/beam_makeops
-emulator $(OPCODE_TABLES) && echo $? >$(TTF_DIR)/OPCODES-GENERATED
GENERATE += $(TTF_DIR)/OPCODES-GENERATED
+ifeq ($(FLAVOR),jit)
+$(TTF_DIR)/beam_asm_global.hpp: beam/jit/$(JIT_ARCH)/beam_asm_global.hpp.pl
+ $(gen_verbose)LANG=C $(PERL) $< > $@
+GENERATE += $(TTF_DIR)/beam_asm_global.hpp
+endif
# bif and atom table
ATOMS= beam/atom.names
@@ -696,7 +721,7 @@ ASMJIT_H = $(wildcard asmjit/*.h) $(wildcard asmjit/core/*.h) $(wildcard asmjit/
ASMJIT_TTF_H = $(foreach HEADER,$(ASMJIT_H),$(TTF_DIR)/$(HEADER))
ifeq ($(FLAVOR),jit)
-GENERATE+=$(ASMJIT_TTF_H)
+GENERATE+=$(ASMJIT_TTF_H) $(TTF_DIR)/asmjit/asmjit.hpp
endif
# Preloaded code.
@@ -704,14 +729,10 @@ endif
# This list must be consistent with PRE_LOADED_MODULES in
# erts/preloaded/src/Makefile.
-ifeq ($(USE_ESOCK), yes)
ESOCK_PRELOAD_BEAM = \
$(ERL_TOP)/erts/preloaded/ebin/socket_registry.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_socket.beam \
$(ERL_TOP)/erts/preloaded/ebin/prim_net.beam
-else
-ESOCK_PRELOAD_BEAM =
-endif
PRELOAD_BEAM = $(ERL_TOP)/erts/preloaded/ebin/erts_code_purger.beam \
$(ERL_TOP)/erts/preloaded/ebin/erl_init.beam \
@@ -774,6 +795,7 @@ ifndef Z_LIB
COMMON_INCLUDES += -Izlib
endif
COMMON_INCLUDES += -Ipcre
+COMMON_INCLUDES += -Iryu
COMMON_INCLUDES += -I../include -I../include/$(TARGET)
COMMON_INCLUDES += -I../include/internal -I../include/internal/$(TARGET)
@@ -903,24 +925,30 @@ $(OBJDIR)/%.o: nifs/$(ERLANG_OSTYPE)/%.c
# included before any other directives, including other #includes.
#
ASMJIT_FLAGS=-DASMJIT_EMBED=1 -DASMJIT_NO_BUILDER=1 -DASMJIT_NO_DEPRECATED=1 -DASMJIT_STATIC=1 -DASMJIT_NO_FOREIGN=1
+
ASMJIT_PCH_OBJ=$(TTF_DIR)/asmjit/asmjit.hpp.gch
ASMJIT_PCH_SRC=$(TTF_DIR)/asmjit/asmjit.hpp
+$(OBJDIR)/%.o: beam/jit/%.cpp $(ASMJIT_PCH_OBJ)
+ $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
+ $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
+ -include $(ASMJIT_PCH_SRC) -c $< -o $@
+
$(OBJDIR)/%.o: beam/jit/$(JIT_ARCH)/%.cpp beam/jit/$(JIT_ARCH)/beam_asm.hpp $(ASMJIT_PCH_OBJ)
- $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
- $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
+ $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
+ $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
-include $(ASMJIT_PCH_SRC) -c $< -o $@
$(OBJDIR)/asmjit/%.o: asmjit/%.cpp $(ASMJIT_PCH_OBJ) $(dir $@)
- $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
- $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
+ $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
+ $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
-include $(ASMJIT_PCH_SRC) -c $< -o $@
## The dependency on erl_bif_info.c is in order to trigger a rebuild when
## the git sha define on the command line argument changes
$(ASMJIT_PCH_OBJ): $(ASMJIT_PCH_SRC) $(ASMJIT_TTF_H) beam/erl_bif_info.c
- $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
- $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
+ $(V_CXX) $(ASMJIT_FLAGS) $(INCLUDES) \
+ $(subst -O2, $(GEN_OPT_FLGS), $(CXXFLAGS)) \
-I$(TTF_DIR) -c $< -o $@
## We copy all asmjit headers into TTF_DIR in order for cross-compilation
@@ -992,21 +1020,37 @@ COMMON_OBJS = \
ASMJIT_OBJS = $(patsubst %.cpp,$(OBJDIR)/%.o,$(ASMJIT_CPP))
JIT_OBJS = \
- $(OBJDIR)/asm_load.o \
- $(OBJDIR)/beam_jit_common.o
+ $(OBJDIR)/asm_load.o \
+ $(OBJDIR)/beam_asm_global.o \
+ $(OBJDIR)/beam_asm_module.o \
+ $(OBJDIR)/beam_jit_common.o \
+ $(OBJDIR)/beam_jit_main.o \
+ $(OBJDIR)/beam_jit_metadata.o \
+ $(OBJDIR)/process_main.o
ifeq ($(JIT_ARCH), x86)
JIT_OBJS += \
- $(OBJDIR)/beam_asm.o \
- $(OBJDIR)/beam_asm_global.o \
- $(OBJDIR)/beam_asm_module.o \
- $(OBJDIR)/beam_asm_perf.o \
$(OBJDIR)/instr_arith.o \
$(OBJDIR)/instr_bs.o \
$(OBJDIR)/instr_bif.o \
$(OBJDIR)/instr_call.o \
$(OBJDIR)/instr_common.o \
$(OBJDIR)/instr_float.o \
+ $(OBJDIR)/instr_fun.o \
+ $(OBJDIR)/instr_guard_bifs.o \
+ $(OBJDIR)/instr_map.o \
+ $(OBJDIR)/instr_msg.o \
+ $(OBJDIR)/instr_select.o \
+ $(OBJDIR)/instr_trace.o
+else
+JIT_OBJS += \
+ $(OBJDIR)/instr_arith.o \
+ $(OBJDIR)/instr_bs.o \
+ $(OBJDIR)/instr_bif.o \
+ $(OBJDIR)/instr_call.o \
+ $(OBJDIR)/instr_common.o \
+ $(OBJDIR)/instr_float.o \
+ $(OBJDIR)/instr_fun.o \
$(OBJDIR)/instr_guard_bifs.o \
$(OBJDIR)/instr_map.o \
$(OBJDIR)/instr_msg.o \
@@ -1019,38 +1063,17 @@ JIT_OBJS += $(ASMJIT_OBJS)
EMU_OBJS = \
$(OBJDIR)/emu_load.o
-ifeq ($(USE_ESOCK), yes)
-
-# WE ARE USING ESOCK
-
ESOCK_NIF_OBJS = \
$(OBJDIR)/prim_socket_nif.o \
$(OBJDIR)/prim_net_nif.o
-ifneq ($(TARGET), win32)
-# These are *currently* only needed for non-win32,
-# since the nif-functions for socket and net are basically
-# stubbed with notsup in the win32 case.
ESOCK_RUN_OBJS = \
$(OBJDIR)/socket_dbg.o \
$(OBJDIR)/socket_tarray.o \
$(OBJDIR)/socket_util.o
-else
-ESOCK_RUN_OBJS =
-endif
-
-else
-
-# WE ARE *NOT* USING ESOCK
-
-ESOCK_NIF_OBJS =
-ESOCK_RUN_OBJS =
-
-endif
-
RUN_OBJS += \
- $(OBJDIR)/erl_alloc.o $(OBJDIR)/erl_mtrace.o \
+ $(OBJDIR)/erl_alloc.o \
$(OBJDIR)/erl_alloc_util.o $(OBJDIR)/erl_goodfit_alloc.o \
$(OBJDIR)/erl_bestfit_alloc.o $(OBJDIR)/erl_afit_alloc.o \
$(OBJDIR)/erl_init.o \
@@ -1099,7 +1122,8 @@ RUN_OBJS += \
$(ESOCK_RUN_OBJS) $(OBJDIR)/erl_flxctr.o \
$(OBJDIR)/erl_nfunc_sched.o \
$(OBJDIR)/erl_global_literals.o \
- $(OBJDIR)/beam_file.o
+ $(OBJDIR)/beam_file.o \
+ $(OBJDIR)/beam_types.o
LTTNG_OBJS = $(OBJDIR)/erlang_lttng.o
@@ -1175,7 +1199,6 @@ OS_OBJS += $(OBJDIR)/erl_poll.o \
$(OBJDIR)/erl_mmap.o \
$(OBJDIR)/erl_osenv.o \
$(OBJDIR)/erl_$(ERLANG_OSTYPE)_sys_ddll.o \
- $(OBJDIR)/erl_mtrace_sys_wrap.o \
$(OBJDIR)/erl_sys_common_misc.o \
$(OBJDIR)/erl_os_monotonic_time_extender.o
@@ -1235,6 +1258,26 @@ $(BINDIR)/$(FLAVOR_EXECUTABLE): $(INIT_OBJS) $(OBJS) $(DEPLIBS)
endif
# ----------------------------------------------------------------------
+# The emulator as a static lib ...
+#
+ifeq ($(USING_VC),yes)
+AR_OUT=-out:
+AR_FLAGS=
+else
+AR_OUT=
+ifeq ($(V),0)
+AR_FLAGS=rc
+else
+AR_FLAGS=rcv
+endif
+endif
+
+$(BINDIR)/${EMULATOR_LIB}: $(PRELOAD_OBJ) $(OBJS) $(DEPLIBS)
+ $(V_AR) $(AR_FLAGS) $(AR_OUT)$@ \
+ $(PRELOAD_OBJ) $(OBJS)
+ $(V_RANLIB) $@
+
+# ----------------------------------------------------------------------
# Dependencies
#
$(TARGET)/Makefile: Makefile.in
@@ -1297,11 +1340,14 @@ ifeq ($(TARGET),win32)
#DEP_CC=$(EMU_CC)
DEP_CC=$(CC)
-DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES) -I../etc/win32 \
+DEP_CXX=$(CXX)
+DEP_INCLUDES=$(INCLUDES) -I../etc/win32 \
-Idrivers/common -Idrivers/$(ERLANG_OSTYPE) \
-Inifs/common -Inifs/$(ERLANG_OSTYPE)
+DEP_FLAGS=-MM $(subst -O2,,$(CFLAGS)) $(INCLUDES)
+DEP_CXXFLAGS=-MM $(subst -O2,,$(CXXFLAGS)) $(DEP_INCLUDES) $(ASMJIT_FLAGS)
-# ifeq (@MIXED_VC@,yes)
+# ifeq ($(USING_VC),yes)
# VC++ used for compiling. If __GNUC__ is defined we will include
# other headers then when compiling which will result in faulty
# dependencies.
@@ -1339,34 +1385,57 @@ $(TARGET)/gen_git_version.mk:
# rebuild.
$(V_at)if utils/gen_git_version $@; then touch beam/erl_bif_info.c; fi
-.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)
+DEPEND_DEPS=jit src drv nif sys target zlib ryu
+
+$(TTF_DIR)/src.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
$(gen_verbose)
$(V_at)$(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \
- | $(SED_DEPEND) > $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) > $@
+$(TTF_DIR)/drv.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
$(V_at)$(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) > $@
$(V_at)$(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(DRV_OSTYPE_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) >> $@
+$(TTF_DIR)/nif.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
$(V_at)$(DEP_CC) $(DEP_FLAGS) $(NIF_COMMON_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) > $@
$(V_at)$(DEP_CC) $(DEP_FLAGS) -I../etc/$(ERLANG_OSTYPE) $(NIF_OSTYPE_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) >> $@
+$(TTF_DIR)/sys.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
$(V_at)$(DEP_CC) $(DEP_FLAGS) $(SYS_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) > $@
+$(TTF_DIR)/target.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
$(V_at)$(DEP_CC) $(DEP_FLAGS) $(TARGET_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) > $@
+$(TTF_DIR)/zlib.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
$(V_at)$(DEP_CC) $(DEP_FLAGS) $(ZLIB_SRC) \
- | $(SED_DEPEND_ZLIB) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND_ZLIB) > $@
+$(TTF_DIR)/ryu.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
+ $(V_at)$(DEP_CC) $(DEP_FLAGS) $(RYU_SRC) \
+ | $(SED_DEPEND_ZLIB) > $@
+$(TTF_DIR)/jit.depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC)
+ $(gen_verbose)
+ @touch $@
ifeq ($(JIT_ENABLED),yes)
$(V_at)$(DEP_CXX) $(DEP_CXXFLAGS) $(BEAM_CPP_SRC) \
- | $(SED_DEPEND) >> $(TTF_DIR)/depend.mk
+ | $(SED_DEPEND) > $@
endif
+
+.PHONY: depend
+ifdef VOID_EMULATOR
+depend:
+ @echo $(VOID_EMULATOR)' - omitted target depend'
+else
+depend: $(TTF_DIR)/depend.mk
+$(TTF_DIR)/depend.mk: $(foreach dep, $(DEPEND_DEPS), $(TTF_DIR)/$(dep).depend.mk)
+ -rm $@
+ for dep in $^; do cat $$dep >> $@; done
$(V_at)cd $(ERTS_LIB_DIR) && $(MAKE) depend
endif
@@ -1389,11 +1458,11 @@ compdb:
format-check:
clang-format --Werror --dry-run -i beam/jit/*.hpp beam/jit/*.c beam/jit/*.h \
- beam/jit/*/*.cpp beam/jit/*/*.hpp
+ beam/jit/*.cpp beam/jit/*/*.cpp beam/jit/*/*.hpp
format:
clang-format -i beam/jit/*.hpp beam/jit/*.c beam/jit/*.h \
- beam/jit/*/*.cpp beam/jit/*/*.hpp
+ beam/jit/*.cpp beam/jit/*/*.cpp beam/jit/*/*.hpp
ifneq ($(ERTS_SKIP_DEPEND),true)
ifneq ($(MAKECMDGOALS),clean)
diff --git a/erts/emulator/asan/asan_logs_to_html b/erts/emulator/asan/asan_logs_to_html
index b83bdb9d31..89030e426e 100755
--- a/erts/emulator/asan/asan_logs_to_html
+++ b/erts/emulator/asan/asan_logs_to_html
@@ -152,8 +152,8 @@ match_loop(Out, Bin, RegEx0, LogAcc0, PrevEnd, Unmatched0, LM0) ->
%% ErrorReport
"(?:(==ERROR: AddressSanitizer:.*\n"
"(?:.*\n)+?)" % any lines (non-greedy)
- "(?:^(?:==|--)|\\z))" % stop at line begining with == or --
- % or at end-of-string
+ "(?:^[=-]+$|\\z))" % stop at line consisting of only = or -
+ % or at end-of-string
"|"
%% Skipped
"(?:^[=-]+$)" % skip lines consisting only of = or -
@@ -188,7 +188,7 @@ match_loop(Out, Bin, RegEx0, LogAcc0, PrevEnd, Unmatched0, LM0) ->
Unmatched1 = [BP({PrevEnd, Start-PrevEnd})|Unmatched0],
TypeBin = BP(TypeIx),
- %% We indentify a leak by its type (direct or indirect)
+ %% We identify a leak by its type (direct or indirect)
%% and its full call stack.
Key = {TypeBin, BP(StackIx)},
{LogAcc2, LM2} =
@@ -262,10 +262,16 @@ log_error(_Out, #logacc{app_err=AppErr, tc_err=TcErr}=LogAcc, Txt0) ->
[_Exe, App, _Rest] ->
io_format("<h3>Before first test case of ~s</h3>\n",
[App]);
- [_Exe, _App, "tc", Num, Mod, Rest] ->
- [Func | _] = string:lexemes(Rest, "."),
- io_format("<h3>Test case #~s ~s:~s</h3>\n",
- [Num, Mod, Func]);
+ [_Exe, _App, "tc", Num, Mod, Rest0] ->
+ [Func | Rest1] = string:lexemes(Rest0, "."),
+ SubNode = case Rest1 of
+ ["subnode" | _] ->
+ " (subnode)";
+ _ ->
+ ""
+ end,
+ io_format("<h3>Test case #~s ~s:~s~s</h3>\n",
+ [Num, Mod, Func, SubNode]);
_ ->
io_format("<h3>Strange log file name '~s'</h3>\n",
[SrcFile])
@@ -360,7 +366,7 @@ try_delete_srcfile(LogAcc) ->
ignore;
#logacc{did_output=false} ->
%% This file did not contribute any output.
- %% Optimize future script invokations by removing it.
+ %% Optimize future script invocations by removing it.
delete_file(LogAcc#logacc.srcfile);
_ ->
keep
diff --git a/erts/emulator/asan/suppress b/erts/emulator/asan/suppress
index 26ba649522..71db30c040 100644
--- a/erts/emulator/asan/suppress
+++ b/erts/emulator/asan/suppress
@@ -1,8 +1,3 @@
-leak:erts_alloc_permanent_cache_aligned
-
-# Harmless leak of ErtsThrPrgrData from async threads in exiting emulator
-leak:erts_thr_progress_register_unmanaged_thread
-
# Block passed to sigaltstack()
leak:sys_thread_init_signal_stack
diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c
index bcbed7746b..ffeeb664ad 100644
--- a/erts/emulator/beam/atom.c
+++ b/erts/emulator/beam/atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -305,7 +305,7 @@ erts_atom_put_index(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc)
if (enc == ERTS_ATOM_ENC_UTF8) {
/* Need to verify encoding and length */
- byte *err_pos;
+ const byte *err_pos;
Uint no_chars;
switch (erts_analyze_utf8_x((byte *) text,
(Uint) tlen,
@@ -347,7 +347,7 @@ erts_atom_put_index(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc)
Eterm
erts_atom_put(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc)
{
- int aix = erts_atom_put_index(name, len, enc, trunc);
+ Sint aix = erts_atom_put_index(name, len, enc, trunc);
if (aix >= 0)
return make_atom(aix);
else
diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h
index 2bc1f653ec..681bd4586f 100644
--- a/erts/emulator/beam/atom.h
+++ b/erts/emulator/beam/atom.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,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 < (UWORD_CONSTANT(1) << 32)) ? MAX_ATOM_INDEX + 1 : ((UWORD_CONSTANT(1) << 31) - 1)) /* Here we use maximum signed interger value to avoid integer overflow */
+#define MAX_ATOM_TABLE_SIZE ((MAX_ATOM_INDEX + 1 < (UWORD_CONSTANT(1) << 32)) ? MAX_ATOM_INDEX + 1 : ((UWORD_CONSTANT(1) << 31) - 1)) /* Here we use maximum signed integer value to avoid integer overflow */
#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 839d52f578..5a5bcbceea 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -90,6 +90,7 @@ atom allocator
atom allocator_sizes
atom alloc_util_allocators
atom allow_passive_connect
+atom already_exists
atom already_loaded
atom amd64
atom anchored
@@ -104,6 +105,7 @@ atom arg0
atom arity
atom asn1
atom async
+atom async_dist
atom asynchronous
atom atom
atom atom_used
@@ -118,7 +120,8 @@ atom await_sched_wall_time_modifications
atom awaiting_load
atom awaiting_unload
atom backtrace backtrace_depth
-atom badarg badarith badarity badfile badfun badkey badmap badmatch badsig
+atom badarg badarith badarity badfile badfun badkey badmap badmatch
+atom badrecord badsig
atom badopt badtype
atom bad_map_iterator
atom bag
@@ -159,6 +162,7 @@ atom call_count
atom call_error_handler
atom call_time
atom caller
+atom caller_line
atom capture
atom case_clause
atom caseless
@@ -170,6 +174,7 @@ atom cflags
atom CHANGE='CHANGE'
atom characters_to_binary_int
atom characters_to_list_int
+atom check_gc
atom clear
atom clock_service
atom close
@@ -187,6 +192,7 @@ atom convert_time_unit
atom connect
atom connected
atom connection_closed
+atom connection_id
atom const
atom context_switches
atom continue_exit
@@ -243,6 +249,7 @@ atom dsend_continue_trap
atom duplicate_bag
atom duplicated
atom dupnames
+atom dynamic_node_name
atom einval
atom emu_flavor
atom emu_type
@@ -297,9 +304,11 @@ atom flags
atom flush
atom flush_monitor_messages
atom force
+atom format_bs_fail
atom format_cpu_topology
atom free
atom fullsweep_after
+atom function
atom functions
atom function_clause
atom garbage_collect
@@ -358,6 +367,7 @@ atom inherit
atom init
atom initial_call
atom input
+atom integer
atom internal
atom internal_error
atom instruction_counts
@@ -476,6 +486,7 @@ atom nodeup
atom noeol
atom noproc
atom normal
+atom normal_exit
atom nosuspend
atom no_fail
atom no_float
@@ -524,6 +535,7 @@ atom owner
atom packet
atom packet_size
atom parallelism
+atom parent
atom Plus='+'
atom PlusPlus='++'
atom pause
@@ -546,6 +558,7 @@ atom prepare_on_load
atom print
atom priority
atom private
+atom private_append
atom process
atom processes
atom processes_used
@@ -591,6 +604,7 @@ atom return_time_trace
atom return_to
atom return_to_trace
atom return_trace
+atom run_process
atom run_queue
atom run_queue_lengths
atom run_queue_lengths_all
@@ -629,6 +643,7 @@ atom set_on_spawn
atom set_seq_token
atom set_tcw
atom set_tcw_fake
+atom short
atom shutdown
atom sighup
atom sigterm
@@ -651,6 +666,7 @@ atom spawn_init
atom spawn_reply
atom spawn_request
atom spawn_request_yield
+atom spawn_service
atom spawned
atom ssl_tls
atom stack_size
@@ -710,14 +726,16 @@ atom unregister
atom urun
atom use_stdio
atom used
-atom utf8
+atom utf8 utf16 utf32
atom unblock
atom unblock_normal
atom uniq
+atom unit
atom unless_suspending
atom unloaded
atom unloaded_only
atom unload_cancelled
+atom unsafe
atom value
atom version
atom visible
@@ -732,4 +750,6 @@ atom xor
atom x86
atom yes
atom yield
-atom nifs \ No newline at end of file
+atom nifs
+atom auto
+atom debug_hash_fixed_number_of_locks
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index aa36e40a62..853ae05d3f 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -302,15 +302,35 @@ struct m {
Eterm exception;
};
-static Eterm staging_epilogue(Process* c_p, int, Eterm res, int, struct m*, int, int);
-static void smp_code_ix_commiter(void*);
-
static struct /* Protected by code_write_permission */
{
Process* stager;
- ErtsThrPrgrLaterOp lop;
+ ErtsCodeBarrier barrier;
} committer_state;
+static Eterm staging_epilogue(Process* c_p, int, Eterm res, int, struct m*, int, int);
+
+static void commit_code_ix(void *null)
+{
+ Process* p = committer_state.stager;
+
+ erts_commit_staging_code_ix();
+
+#ifdef DEBUG
+ committer_state.stager = NULL;
+#endif
+
+ erts_release_code_write_permission();
+
+ erts_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ if (!ERTS_PROC_IS_EXITING(p)) {
+ erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ }
+ erts_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+
+ erts_proc_dec_refc(p);
+}
+
static Eterm
exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions)
{
@@ -503,17 +523,19 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
{
if (is_blocking || !commit)
{
- if (commit) {
- int i;
- erts_end_staging_code_ix();
- erts_commit_staging_code_ix();
+ if (commit) {
+ int i;
+ erts_end_staging_code_ix();
+ erts_commit_staging_code_ix();
+
+ for (i=0; i < nmods; i++) {
+ if (mods[i].modp->curr.code_hdr
+ && mods[i].exception != am_on_load) {
+ set_default_trace_pattern(mods[i].module);
+ }
+ }
- for (i=0; i < nmods; i++) {
- if (mods[i].modp->curr.code_hdr
- && mods[i].exception != am_on_load) {
- set_default_trace_pattern(mods[i].module);
- }
- }
+ erts_blocking_code_barrier();
}
else {
erts_abort_staging_code_ix();
@@ -542,37 +564,19 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
*/
ASSERT(committer_state.stager == NULL);
committer_state.stager = c_p;
- erts_schedule_thr_prgr_later_op(smp_code_ix_commiter, NULL, &committer_state.lop);
- erts_proc_inc_refc(c_p);
- erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
- /*
- * smp_code_ix_commiter() will do the rest "later"
- * and resume this process to return 'res'.
- */
- ERTS_BIF_YIELD_RETURN(c_p, res);
- }
-}
+ erts_schedule_code_barrier(&committer_state.barrier,
+ commit_code_ix, NULL);
-static void smp_code_ix_commiter(void* null)
-{
- Process* p = committer_state.stager;
+ erts_proc_inc_refc(c_p);
+ erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL);
- erts_commit_staging_code_ix();
-#ifdef DEBUG
- committer_state.stager = NULL;
-#endif
- erts_release_code_write_permission();
- erts_proc_lock(p, ERTS_PROC_LOCK_STATUS);
- if (!ERTS_PROC_IS_EXITING(p)) {
- erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ /* commit_code_ix(NULL) will resume us when everything is finished, at
+ * which point we'll return `res`. */
+ ERTS_BIF_YIELD_RETURN(c_p, res);
}
- erts_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
- erts_proc_dec_refc(p);
}
-
-
BIF_RETTYPE
check_old_code_1(BIF_ALIST_1)
{
@@ -804,6 +808,12 @@ BIF_RETTYPE loaded_0(BIF_ALIST_0)
BIF_RETTYPE call_on_load_function_1(BIF_ALIST_1)
{
+#ifdef BEAMASM
+ /* This is implemented as an instruction. We've skipped providing a more
+ * helpful error message since it's undocumented and should never be called
+ * by the user. */
+ BIF_ERROR(BIF_P, BADARG);
+#else
Module* modp = erts_get_module(BIF_ARG_1, erts_active_code_ix());
const BeamCodeHeader *hdr;
@@ -819,6 +829,7 @@ BIF_RETTYPE call_on_load_function_1(BIF_ALIST_1)
}
BIF_ERROR(BIF_P, BADARG);
+#endif
}
BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
@@ -877,7 +888,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
modp->on_load = 0;
/*
- * The on_load function succeded. Fix up export entries.
+ * The on_load function succeeded. Fix up export entries.
*/
num_exps = export_list_size(code_ix);
for (i = 0; i < num_exps; i++) {
@@ -890,7 +901,8 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
DBG_CHECK_EXPORT(ep, code_ix);
if (ep->trampoline.not_loaded.deferred != 0) {
- ep->addresses[code_ix] = (void*)ep->trampoline.not_loaded.deferred;
+ ep->dispatch.addresses[code_ix] =
+ (void*)ep->trampoline.not_loaded.deferred;
ep->trampoline.not_loaded.deferred = 0;
} else {
if (ep->bif_number != -1) {
@@ -967,12 +979,39 @@ set_default_trace_pattern(Eterm module)
}
int
-erts_check_copy_literals_gc_need(Process *c_p, int *redsp,
- char *literals, Uint lit_bsize)
+erts_check_copy_literals_gc_need_max_reds(Process *c_p)
{
+ Uint64 words, reds;
+
/*
- * TODO: Implement yielding support!
+ * Calculate maximum amount of words that needs
+ * to be scanned...
*/
+ words = 1; /* fvalue */
+ words += c_p->hend - c_p->stop; /* stack */
+ words += c_p->htop - c_p->heap; /* new heap */
+ if (c_p->abandoned_heap)
+ words += c_p->heap_sz; /* abandoned heap */
+ words += c_p->old_htop - c_p->old_heap; /* old heap */
+ if (c_p->dictionary) {
+ Eterm* start = ERTS_PD_START(c_p->dictionary);
+ Eterm* end = start + ERTS_PD_SIZE(c_p->dictionary);
+
+ words += end - start; /* dictionary */
+ }
+ words += c_p->mbuf_sz; /* heap and message fragments */
+
+ /* Convert to reductions... */
+ reds = ((words - 1)/ERTS_CLA_SCAN_WORDS_PER_RED) + 1;
+ if (reds > CONTEXT_REDS)
+ return CONTEXT_REDS+1;
+ return (int) reds;
+}
+
+int
+erts_check_copy_literals_gc_need(Process *c_p, int *redsp,
+ char *literals, Uint lit_bsize)
+{
ErlHeapFragment *hfrag;
ErtsMessage *mfp;
Uint64 scanned = 0;
@@ -1255,7 +1294,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
* - erts_internal:release_literal_area_switch() changes the set of
* counters that blocks release of literal areas
* - The literal area collector process gets suspended waiting thread
- * progress in order to ensure that the change of counters is visable
+ * progress in order to ensure that the change of counters is visible
* by all schedulers.
* - When the literal area collector process is resumed after thread
* progress has completed, erts_internal:release_literal_area_switch()
@@ -1521,22 +1560,30 @@ erts_literal_area_collector_send_copy_request_3(BIF_ALIST_3)
req_id = TUPLE3(&tmp_heap[0], BIF_ARG_2, BIF_ARG_3, BIF_ARG_1);
- if (BIF_ARG_3 == am_false) {
+ switch (BIF_ARG_3) {
+
+ case am_init:
/*
- * Will handle signal queue and check if GC if needed. If
- * GC is needed operation will be continued by a GC (below).
+ * Will handle signal queue and if possible check if GC if needed.
+ * If GC is needed or needs to be checked the operation will be
+ * restarted later in the 'check_gc' or 'need_gc' case below...
*/
erts_proc_sig_send_cla_request(BIF_P, BIF_ARG_1, req_id);
- }
- else if (BIF_ARG_3 == am_true) {
+ break;
+
+ case am_check_gc:
+ case am_need_gc:
/*
- * Will perform a literal GC. Note that this assumes that
- * signal queue already has been handled...
+ * Will check and/or perform a literal GC. Note that this assumes that
+ * signal queue already has been handled by 'init' case above...
*/
- erts_schedule_cla_gc(BIF_P, BIF_ARG_1, req_id);
- }
- else
+ erts_schedule_cla_gc(BIF_P, BIF_ARG_1, req_id,
+ BIF_ARG_3 == am_check_gc);
+ break;
+
+ default:
BIF_ERROR(BIF_P, BADARG);
+ }
BIF_RET(am_ok);
}
@@ -2019,6 +2066,10 @@ BIF_RETTYPE erts_internal_purge_module_2(BIF_ALIST_2)
erts_remove_from_ranges(modp->old.code_hdr);
+ if (modp->old.code_hdr->are_nifs) {
+ erts_free(ERTS_ALC_T_PREPARED_CODE,
+ modp->old.code_hdr->are_nifs);
+ }
#ifndef BEAMASM
erts_free(ERTS_ALC_T_CODE, (void *) modp->old.code_hdr);
#else
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 2142830ae8..7f105ce7c4 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -123,7 +123,8 @@ static void bp_meta_unref(BpMetaTracer *bmt);
static void bp_count_unref(BpCount *bcp);
static void bp_time_unref(BpDataTime *bdt);
static void consolidate_bp_data(Module *modp, ErtsCodeInfo *ci, int local);
-static void uninstall_breakpoint(ErtsCodeInfo *ci);
+static void uninstall_breakpoint(ErtsCodeInfo *ci_rw,
+ const ErtsCodeInfo *ci_exec);
/* bp_hash */
#define BP_TIME_ADD(pi0, pi1) \
@@ -188,31 +189,33 @@ erts_bp_match_functions(BpFunctions* f, ErtsCodeMFA *mfa, int specified)
}
for (fi = 0; fi < num_functions; fi++) {
- ErtsCodeInfo* ci;
+ const ErtsCodeInfo* ci_exec;
+ ErtsCodeInfo* ci_rw;
void *w_ptr;
- w_ptr = erts_writable_code_ptr(&module[current]->curr,
- code_hdr->functions[fi]);
- ci = (ErtsCodeInfo*)w_ptr;
+ ci_exec = code_hdr->functions[fi];
+ w_ptr = erts_writable_code_ptr(&module[current]->curr, ci_exec);
+ ci_rw = (ErtsCodeInfo*)w_ptr;
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI));
+ ASSERT(BeamIsOpCode(ci_rw->u.op, op_i_func_info_IaaI));
#endif
switch (specified) {
case 3:
- if (ci->mfa.arity != mfa->arity)
+ if (ci_rw->mfa.arity != mfa->arity)
continue;
case 2:
- if (ci->mfa.function != mfa->function)
+ if (ci_rw->mfa.function != mfa->function)
continue;
case 1:
- if (ci->mfa.module != mfa->module)
+ if (ci_rw->mfa.module != mfa->module)
continue;
case 0:
break;
}
/* Store match */
- f->matching[i].ci = ci;
+ f->matching[i].ci_exec = ci_exec;
+ f->matching[i].ci_rw = ci_rw;
f->matching[i].mod = module[current];
i++;
}
@@ -260,12 +263,13 @@ erts_bp_match_export(BpFunctions* f, ErtsCodeMFA *mfa, int specified)
ASSERT(BeamIsOpCode(ep->trampoline.common.op, op_i_generic_breakpoint));
}
- f->matching[ne].ci = &ep->info;
- f->matching[ne].mod = erts_get_module(ep->info.mfa.module, code_ix);
-
- ne++;
+ f->matching[ne].ci_exec = &ep->info;
+ f->matching[ne].ci_rw = &ep->info;
+ f->matching[ne].mod = erts_get_module(ep->info.mfa.module, code_ix);
+ ne++;
}
+
f->matched = ne;
}
@@ -288,14 +292,14 @@ erts_consolidate_bp_data(BpFunctions* f, int local)
ERTS_LC_ASSERT(erts_has_code_write_permission());
for (i = 0; i < n; i++) {
- consolidate_bp_data(fs[i].mod, fs[i].ci, local);
+ consolidate_bp_data(fs[i].mod, fs[i].ci_rw, local);
}
}
static void
-consolidate_bp_data(Module* modp, ErtsCodeInfo *ci, int local)
+consolidate_bp_data(Module* modp, ErtsCodeInfo *ci_rw, int local)
{
- GenericBp* g = ci->u.gen_bp;
+ GenericBp* g = ci_rw->gen_bp;
GenericBpData* src;
GenericBpData* dst;
Uint flags;
@@ -343,14 +347,15 @@ consolidate_bp_data(Module* modp, ErtsCodeInfo *ci, int local)
ASSERT(modp->curr.num_traced_exports >= 0);
#if !defined(BEAMASM) && defined(DEBUG)
{
- BeamInstr instr = *(const BeamInstr*)erts_codeinfo_to_code(ci);
+ BeamInstr instr = *(const BeamInstr*)erts_codeinfo_to_code(ci_rw);
ASSERT(!BeamIsOpCode(instr, op_i_generic_breakpoint));
}
#endif
- }
- ci->u.gen_bp = NULL;
- Free(g);
- return;
+ }
+
+ ci_rw->gen_bp = NULL;
+ Free(g);
+ return;
}
/*
@@ -396,11 +401,12 @@ erts_install_breakpoints(BpFunctions* f)
Uint n = f->matched;
for (i = 0; i < n; i++) {
- ErtsCodeInfo* ci = f->matching[i].ci;
- GenericBp* g = ci->u.gen_bp;
- Module* modp = f->matching[i].mod;
+ const ErtsCodeInfo *ci_exec = f->matching[i].ci_exec;
+ ErtsCodeInfo *ci_rw = f->matching[i].ci_rw;
+ GenericBp *g = ci_rw->gen_bp;
+ Module *modp = f->matching[i].mod;
#ifdef BEAMASM
- if ((erts_asm_bp_get_flags(ci) & ERTS_ASM_BP_FLAG_BP) == 0 && g) {
+ if ((erts_asm_bp_get_flags(ci_exec) & ERTS_ASM_BP_FLAG_BP) == 0 && g) {
/*
* The breakpoint must be disabled in the active data
* (it will enabled later by switching bp indices),
@@ -409,12 +415,16 @@ erts_install_breakpoints(BpFunctions* f)
ASSERT(g->data[erts_active_bp_ix()].flags == 0);
ASSERT(g->data[erts_staging_bp_ix()].flags != 0);
- erts_asm_bp_set_flag(ci, ERTS_ASM_BP_FLAG_BP);
+ erts_asm_bp_set_flag(ci_rw, ci_exec, ERTS_ASM_BP_FLAG_BP);
modp->curr.num_breakpoints++;
}
#else
- BeamInstr volatile *pc = (BeamInstr*)erts_codeinfo_to_code(ci);
+ BeamInstr volatile *pc = (BeamInstr*)erts_codeinfo_to_code(ci_rw);
BeamInstr instr = *pc;
+
+ ASSERT(ci_exec == ci_rw);
+ (void)ci_exec;
+
if (!BeamIsOpCode(instr, op_i_generic_breakpoint) && g) {
BeamInstr br = BeamOpCodeAddr(op_i_generic_breakpoint);
@@ -452,30 +462,33 @@ erts_uninstall_breakpoints(BpFunctions* f)
Uint n = f->matched;
for (i = 0; i < n; i++) {
- uninstall_breakpoint(f->matching[i].ci);
+ uninstall_breakpoint(f->matching[i].ci_rw, f->matching[i].ci_exec);
}
}
#ifdef BEAMASM
static void
-uninstall_breakpoint(ErtsCodeInfo *ci)
+uninstall_breakpoint(ErtsCodeInfo *ci_rw, const ErtsCodeInfo *ci_exec)
{
- if (erts_asm_bp_get_flags(ci) & ERTS_ASM_BP_FLAG_BP) {
- GenericBp* g = ci->u.gen_bp;
+ if (erts_asm_bp_get_flags(ci_rw) & ERTS_ASM_BP_FLAG_BP) {
+ GenericBp* g = ci_rw->gen_bp;
if (g->data[erts_active_bp_ix()].flags == 0) {
- erts_asm_bp_unset_flag(ci, ERTS_ASM_BP_FLAG_BP);
+ erts_asm_bp_unset_flag(ci_rw, ci_exec, ERTS_ASM_BP_FLAG_BP);
}
}
}
#else
static void
-uninstall_breakpoint(ErtsCodeInfo *ci)
+uninstall_breakpoint(ErtsCodeInfo *ci_rw, const ErtsCodeInfo *ci_exec)
{
- BeamInstr *pc = (BeamInstr*)erts_codeinfo_to_code(ci);
+ BeamInstr *pc = (BeamInstr*)erts_codeinfo_to_code(ci_rw);
+
+ ASSERT(ci_rw == ci_exec);
+ (void)ci_exec;
if (BeamIsOpCode(*pc, op_i_generic_breakpoint)) {
- GenericBp* g = ci->u.gen_bp;
+ GenericBp* g = ci_rw->gen_bp;
if (g->data[erts_active_bp_ix()].flags == 0) {
/*
@@ -539,7 +552,7 @@ erts_clear_trace_break(BpFunctions* f)
void
erts_clear_export_trace(ErtsCodeInfo *ci, int local)
{
- GenericBp* g = ci->u.gen_bp;
+ GenericBp* g = ci->gen_bp;
if (g) {
Uint flags = local ? ERTS_BPF_LOCAL_TRACE : ERTS_BPF_GLOBAL_TRACE;
@@ -574,7 +587,7 @@ erts_clear_time_break(BpFunctions* f)
{
clear_break(f, ERTS_BPF_TIME_TRACE|ERTS_BPF_TIME_TRACE_ACTIVE);
}
-
+
void
erts_clear_all_breaks(BpFunctions* f)
{
@@ -605,16 +618,18 @@ erts_clear_module_break(Module *modp) {
erts_commit_staged_bp();
for (i = 0; i < n; ++i) {
- ErtsCodeInfo* ci;
+ const ErtsCodeInfo *ci_exec;
+ ErtsCodeInfo *ci_rw;
void *w_ptr;
- w_ptr = erts_writable_code_ptr(&modp->curr,
- code_hdr->functions[i]);
- ci = (ErtsCodeInfo*)w_ptr;
+ ci_exec = code_hdr->functions[i];
+ w_ptr = erts_writable_code_ptr(&modp->curr, ci_exec);
+ ci_rw = (ErtsCodeInfo*)w_ptr;
+
+ uninstall_breakpoint(ci_rw, ci_exec);
+ consolidate_bp_data(modp, ci_rw, 1);
- uninstall_breakpoint(ci);
- consolidate_bp_data(modp, ci, 1);
- ASSERT(ci->u.gen_bp == NULL);
+ ASSERT(ci_rw->gen_bp == NULL);
}
return n;
@@ -639,7 +654,7 @@ erts_clear_export_break(Module* modp, Export *ep)
erts_commit_staged_bp();
consolidate_bp_data(modp, ci, 0);
- ASSERT(ci->u.gen_bp == NULL);
+ ASSERT(ci->gen_bp == NULL);
}
/*
@@ -653,25 +668,53 @@ erts_clear_export_break(Module* modp, Export *ep)
* being the function which is the caller, but rather the function
* which we are about to return to.
*/
-static void fixup_cp_before_trace(Process *c_p, int *return_to_trace)
+static void fixup_cp_before_trace(Process *c_p,
+ Eterm cp_save[2],
+ int *return_to_trace)
{
+ const ErtsFrameLayout frame_layout = erts_frame_layout;
Eterm *cpp = c_p->stop;
+ if (frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ ASSERT(is_CP(cpp[1]));
+ cp_save[1] = cpp[1];
+ }
+
+ ASSERT(is_CP(cpp[0]));
+ cp_save[0] = cpp[0];
+
for (;;) {
- ErtsCodePtr w = cp_val(*cpp);
+ ErtsCodePtr w;
+
+ erts_inspect_frame(cpp, &w);
+
if (BeamIsReturnTrace(w)) {
- cpp += 3;
+ cpp += CP_SIZE + 2;
+ } else if (BeamIsReturnTimeTrace(w)) {
+ cpp += CP_SIZE + 1;
} else if (BeamIsReturnToTrace(w)) {
*return_to_trace = 1;
- cpp += 1;
- } else if (BeamIsReturnTimeTrace(w)) {
- cpp += 2;
+ cpp += CP_SIZE;
} else {
- break;
+ if (frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ ASSERT(is_CP(cpp[1]));
+ c_p->stop[1] = cpp[1];
+ }
+
+ ASSERT(is_CP(cpp[0]));
+ c_p->stop[0] = cpp[0];
+
+ return;
}
}
- c_p->stop[0] = (Eterm) cp_val(*cpp);
- ASSERT(is_CP(*cpp));
+}
+
+static void restore_cp_after_trace(Process *c_p, const Eterm cp_save[2]) {
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ c_p->stop[1] = cp_save[1];
+ }
+
+ c_p->stop[0] = cp_save[0];
}
BeamInstr
@@ -683,10 +726,10 @@ erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *info, Eterm* reg)
ErtsBpIndex ix = erts_active_bp_ix();
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(info->op, op_i_func_info_IaaI));
+ ASSERT(BeamIsOpCode(info->u.op, op_i_func_info_IaaI));
#endif
- g = info->u.gen_bp;
+ g = info->gen_bp;
bp = &g->data[ix];
bp_flags = bp->flags;
ASSERT((bp_flags & ~ERTS_BPF_ALL) == 0);
@@ -738,24 +781,41 @@ erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *info, Eterm* reg)
ErtsCodePtr w;
Eterm* E;
- prev_info= erts_trace_time_call(c_p, info, bp->time);
+ prev_info = erts_trace_time_call(c_p, info, bp->time);
+
E = c_p->stop;
- w = (ErtsCodePtr) E[0];
- if (!(BeamIsReturnTrace(w) || BeamIsReturnToTrace(w) || BeamIsReturnTimeTrace(w))) {
- ASSERT(c_p->htop <= E && E <= c_p->hend);
- if (HeapWordsLeft(c_p) < 2) {
- (void) erts_garbage_collect(c_p, 2, reg, info->mfa.arity);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- }
- E = c_p->stop;
- ASSERT(c_p->htop <= E && E <= c_p->hend);
+ erts_inspect_frame(E, &w);
- E -= 2;
- E[1] = prev_info ? make_cp(erts_codeinfo_to_code(prev_info)) : NIL;
- E[0] = (Eterm) beam_return_time_trace;
- c_p->stop = E;
- }
+ if (!(BeamIsReturnTrace(w) ||
+ BeamIsReturnToTrace(w) ||
+ BeamIsReturnTimeTrace(w))) {
+ int need = CP_SIZE + 1;
+
+ ASSERT(c_p->htop <= E && E <= c_p->hend);
+
+ if (HeapWordsLeft(c_p) < need) {
+ (void) erts_garbage_collect(c_p, need,
+ reg, info->mfa.arity);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ }
+
+ E = c_p->stop;
+
+ ASSERT(c_p->htop <= E && E <= c_p->hend);
+
+ E -= 2;
+ E[1] = prev_info ? make_cp(erts_codeinfo_to_code(prev_info)) : NIL;
+ E[0] = make_cp(beam_return_time_trace);
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ E -= 1;
+ E[0] = make_cp(FRAME_POINTER(c_p));
+ FRAME_POINTER(c_p) = E;
+ }
+
+ c_p->stop = E;
+ }
}
if (bp_flags & ERTS_BPF_DEBUG) {
@@ -769,56 +829,91 @@ static ErtsTracer
do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg,
int local, Binary* ms, ErtsTracer tracer)
{
+ Eterm cp_save[2] = {0, 0};
int return_to_trace = 0;
Uint32 flags;
Uint need = 0;
- Eterm cp_save;
- Eterm* E = c_p->stop;
+ Eterm* E;
- cp_save = E[0];
+ fixup_cp_before_trace(c_p, cp_save, &return_to_trace);
- fixup_cp_before_trace(c_p, &return_to_trace);
ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
flags = erts_call_trace(c_p, info, ms, reg, local, &tracer);
ERTS_REQ_PROC_MAIN_LOCK(c_p);
- E[0] = cp_save;
+ restore_cp_after_trace(c_p, cp_save);
+
+ E = c_p->stop;
ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+
if ((flags & MATCH_SET_RETURN_TO_TRACE) && !return_to_trace) {
- need += 1;
+ need += CP_SIZE;
}
+
if (flags & MATCH_SET_RX_TRACE) {
- need += 3 + size_object(tracer);
+ need += CP_SIZE + 2 + size_object(tracer);
}
+
if (need) {
- ASSERT(c_p->htop <= E && E <= c_p->hend);
- if (HeapWordsLeft(c_p) < need) {
- (void) erts_garbage_collect(c_p, need, reg, info->mfa.arity);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- E = c_p->stop;
- }
- }
- if (flags & MATCH_SET_RETURN_TO_TRACE && !return_to_trace) {
- E -= 1;
- ASSERT(c_p->htop <= E && E <= c_p->hend);
- E[0] = (Eterm) beam_return_to_trace;
- c_p->stop = E;
- }
- if (flags & MATCH_SET_RX_TRACE) {
- E -= 3;
- c_p->stop = E;
- ASSERT(c_p->htop <= E && E <= c_p->hend);
- ASSERT(is_CP((Eterm) (UWord) (&info->mfa.module)));
- ASSERT(IS_TRACER_VALID(tracer));
- E[2] = copy_object(tracer, c_p);
- E[1] = make_cp(&info->mfa.module);
- E[0] = (Eterm) ((flags & MATCH_SET_EXCEPTION_TRACE) ?
- beam_exception_trace : beam_return_trace);
- erts_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
- ERTS_TRACE_FLAGS(c_p) |= F_EXCEPTION_TRACE;
- erts_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
+ ASSERT(c_p->htop <= E && E <= c_p->hend);
+
+ if (HeapWordsLeft(c_p) < need) {
+ (void) erts_garbage_collect(c_p, need, reg, info->mfa.arity);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ E = c_p->stop;
+ }
+
+ if ((flags & MATCH_SET_RETURN_TO_TRACE) && !return_to_trace) {
+ E -= CP_SIZE;
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ E[0] = make_cp(beam_return_to_trace);
+ } else {
+ E[1] = make_cp(beam_return_to_trace);
+ E[0] = make_cp(FRAME_POINTER(c_p));
+ FRAME_POINTER(c_p) = E;
+ }
+
+ ASSERT(c_p->htop <= E && E <= c_p->hend);
+
+ c_p->stop = E;
+ }
+
+ if (flags & MATCH_SET_RX_TRACE) {
+ ErtsCodePtr trace_cp;
+
+ if (flags & MATCH_SET_EXCEPTION_TRACE) {
+ trace_cp = beam_exception_trace;
+ } else {
+ trace_cp = beam_return_trace;
+ }
+
+ E -= 2;
+ E[1] = copy_object(tracer, c_p);
+ E[0] = make_cp(&info->mfa.module);
+
+ E -= CP_SIZE;
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ E[0] = make_cp(trace_cp);
+ } else {
+ E[1] = make_cp(trace_cp);
+ E[0] = make_cp(FRAME_POINTER(c_p));
+ FRAME_POINTER(c_p) = E;
+ }
+
+ ASSERT(c_p->htop <= E && E <= c_p->hend);
+ ASSERT(is_CP((Eterm)(&info->mfa.module)));
+ ASSERT(IS_TRACER_VALID(tracer));
+
+ c_p->stop = E;
+
+ erts_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
+ ERTS_TRACE_FLAGS(c_p) |= F_EXCEPTION_TRACE;
+ erts_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
+ }
}
+
return tracer;
}
@@ -1097,7 +1192,7 @@ erts_find_local_func(const ErtsCodeMFA *mfa) {
for (i = 0; i < n; ++i) {
ci = code_hdr->functions[i];
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI));
+ ASSERT(BeamIsOpCode(ci->u.op, op_i_func_info_IaaI));
#endif
ASSERT(mfa->module == ci->mfa.module || is_nil(ci->mfa.module));
if (mfa->function == ci->mfa.function &&
@@ -1287,9 +1382,9 @@ set_break(BpFunctions* f, Binary *match_spec, Uint break_flags,
n = f->matched;
for (i = 0; i < n; i++) {
- set_function_break(f->matching[i].ci,
+ set_function_break(f->matching[i].ci_rw,
match_spec, break_flags,
- count_op, tracer);
+ count_op, tracer);
}
}
@@ -1303,7 +1398,7 @@ set_function_break(ErtsCodeInfo *ci, Binary *match_spec, Uint break_flags,
ErtsBpIndex ix = erts_staging_bp_ix();
ERTS_LC_ASSERT(erts_has_code_write_permission());
- g = ci->u.gen_bp;
+ g = ci->gen_bp;
if (g == 0) {
int i;
if (count_op == ERTS_BREAK_RESTART || count_op == ERTS_BREAK_PAUSE) {
@@ -1331,7 +1426,7 @@ set_function_break(ErtsCodeInfo *ci, Binary *match_spec, Uint break_flags,
for (i = 0; i < ERTS_NUM_BP_IX; i++) {
g->data[i].flags = 0;
}
- ci->u.gen_bp = g;
+ ci->gen_bp = g;
}
bp = &g->data[ix];
@@ -1423,7 +1518,7 @@ clear_break(BpFunctions* f, Uint break_flags)
n = f->matched;
for (i = 0; i < n; i++) {
- clear_function_break(f->matching[i].ci, break_flags);
+ clear_function_break(f->matching[i].ci_exec, break_flags);
}
}
@@ -1437,7 +1532,7 @@ clear_function_break(const ErtsCodeInfo *ci, Uint break_flags)
ERTS_LC_ASSERT(erts_has_code_write_permission());
- if ((g = ci->u.gen_bp) == NULL) {
+ if ((g = ci->gen_bp) == NULL) {
return 1;
}
@@ -1507,10 +1602,10 @@ get_time_break(const ErtsCodeInfo *ci)
static GenericBpData*
check_break(const ErtsCodeInfo *ci, Uint break_flags)
{
- GenericBp* g = ci->u.gen_bp;
+ GenericBp* g = ci->gen_bp;
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI));
+ ASSERT(BeamIsOpCode(ci->u.op, op_i_func_info_IaaI));
#endif
if (g) {
diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h
index 9941533e2d..3688f08332 100644
--- a/erts/emulator/beam/beam_bp.h
+++ b/erts/emulator/beam/beam_bp.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,8 @@ enum erts_break_op{
typedef Uint32 ErtsBpIndex;
typedef struct {
- ErtsCodeInfo *ci;
+ const ErtsCodeInfo *ci_exec;
+ ErtsCodeInfo *ci_rw;
Module* mod;
} BpFunction;
diff --git a/erts/emulator/beam/beam_code.h b/erts/emulator/beam/beam_code.h
index 07344628f0..7e8d2c744b 100644
--- a/erts/emulator/beam/beam_code.h
+++ b/erts/emulator/beam/beam_code.h
@@ -93,6 +93,13 @@ typedef struct beam_code_header {
const byte *md5_ptr;
/*
+ * Boolean array with functions declared as -nifs().
+ * Indexed same as functions[].
+ * NULL if no -nifs().
+ */
+ byte* are_nifs;
+
+ /*
* Start of function pointer table. This table contains pointers to
* all functions in the module plus an additional pointer just beyond
* the end of the last function.
diff --git a/erts/emulator/beam/beam_common.c b/erts/emulator/beam/beam_common.c
index 36f9d49629..2055f60e91 100644
--- a/erts/emulator/beam/beam_common.c
+++ b/erts/emulator/beam/beam_common.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
#include "dist.h"
#include "beam_catches.h"
#include "beam_common.h"
+#include "erl_global_literals.h"
#ifdef USE_VM_PROBES
#include "dtrace-wrapper.h"
@@ -233,7 +234,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp)
if (ERTS_PROC_IS_EXITING(c_p)) {
sys_strcpy(fun_buf, "<exiting>");
} else {
- ErtsCodeMFA *cmfa = erts_find_function_from_pc(c_p->i);
+ const ErtsCodeMFA *cmfa = erts_find_function_from_pc(c_p->i);
if (cmfa) {
dtrace_fun_decode(c_p, cmfa, NULL, fun_buf);
} else {
@@ -394,6 +395,7 @@ Eterm error_atom[NUMBER_EXIT_CODES] = {
am_notsup, /* 17 */
am_badmap, /* 18 */
am_badkey, /* 19 */
+ am_badrecord, /* 20 */
};
/* Returns the return address at E[0] in printable form, skipping tracing in
@@ -402,21 +404,24 @@ Eterm error_atom[NUMBER_EXIT_CODES] = {
* This is needed to generate correct stacktraces when throwing errors from
* instructions that return like an ordinary function, such as call_nif. */
ErtsCodePtr erts_printable_return_address(Process* p, Eterm *E) {
- Eterm *ptr = E;
+ Eterm *stack_bottom = STACK_START(p);
+ Eterm *scanner = E;
- ASSERT(is_CP(*ptr));
+ ASSERT(is_CP(scanner[0]));
- while (ptr < STACK_START(p)) {
- ErtsCodePtr cp = cp_val(*ptr);
+ while (scanner < stack_bottom) {
+ ErtsCodePtr return_address;
- if (BeamIsReturnTrace(cp)) {
- ptr += 3;
- } else if (BeamIsReturnTimeTrace(cp)) {
- ptr += 2;
- } else if (BeamIsReturnToTrace(cp)) {
- ptr += 1;
+ erts_inspect_frame(scanner, &return_address);
+
+ if (BeamIsReturnTrace(return_address)) {
+ scanner += CP_SIZE + 2;
+ } else if (BeamIsReturnTimeTrace(return_address)) {
+ scanner += CP_SIZE + 1;
+ } else if (BeamIsReturnToTrace(return_address)) {
+ scanner += CP_SIZE;
} else {
- return cp;
+ return return_address;
}
}
@@ -519,18 +524,20 @@ handle_error(Process* c_p, ErtsCodePtr pc, Eterm* reg,
&& !(c_p->freason & EXF_PANIC)) {
ErtsCodePtr new_pc;
/* The Beam handler code (catch_end or try_end) checks reg[0]
- for THE_NON_VALUE to see if the previous code finished
- abnormally. If so, reg[1], reg[2] and reg[3] should hold the
- exception class, term and trace, respectively. (If the
- handler is just a trap to native code, these registers will
- be ignored.) */
+ * for THE_NON_VALUE to see if the previous code finished
+ * abnormally. If so, reg[1], reg[2] and reg[3] should hold
+ * the term, trace, and exception class, respectively. Note
+ * that the handler code will only need to move the class
+ * to reg[0] to have all registers correctly set up for the
+ * code that follows.
+ */
reg[0] = THE_NON_VALUE;
- reg[1] = exception_tag[GET_EXC_CLASS(c_p->freason)];
- reg[2] = Value;
- reg[3] = c_p->ftrace;
+ reg[1] = Value;
+ reg[2] = c_p->ftrace;
+ reg[3] = exception_tag[GET_EXC_CLASS(c_p->freason)];
if ((new_pc = next_catch(c_p, reg))) {
-#if defined(BEAMASM) && defined(NATIVE_ERLANG_STACK)
+#if defined(BEAMASM) && (defined(NATIVE_ERLANG_STACK) || defined(__aarch64__))
/* In order to make use of native call and return
* instructions, when beamasm uses the native stack it
* doesn't include the CP in the current stack frame,
@@ -539,7 +546,11 @@ handle_error(Process* c_p, ErtsCodePtr pc, Eterm* reg,
*
* Therefore, we need to bump the stack pointer as if this were an
* ordinary return. */
- ASSERT(is_CP(c_p->stop[0]));
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ FRAME_POINTER(c_p) = (Eterm*)cp_val(c_p->stop[0]);
+ }
+
c_p->stop += CP_SIZE;
#else
/* To avoid keeping stale references. */
@@ -566,8 +577,10 @@ handle_error(Process* c_p, ErtsCodePtr pc, Eterm* reg,
static ErtsCodePtr
next_catch(Process* c_p, Eterm *reg) {
int active_catches = c_p->catches > 0;
+ ErtsCodePtr return_to_trace_address = NULL;
int have_return_to_trace = 0;
- Eterm *ptr, *prev, *return_to_trace_ptr = NULL;
+ Eterm *ptr, *prev;
+ ErtsCodePtr handler;
ptr = prev = c_p->stop;
ASSERT(ptr <= STACK_START(c_p));
@@ -583,53 +596,82 @@ next_catch(Process* c_p, Eterm *reg) {
}
while (ptr < STACK_START(c_p)) {
- if (is_catch(*ptr)) {
- if (active_catches) goto found_catch;
- ptr++;
- }
- else if (is_CP(*ptr)) {
- prev = ptr;
- if (BeamIsReturnTrace(cp_val(*prev))) {
- if (cp_val(*prev) == beam_exception_trace) {
- ErtsCodeMFA *mfa = (ErtsCodeMFA*)cp_val(ptr[1]);
- erts_trace_exception(c_p, mfa,
- reg[1], reg[2],
- ERTS_TRACER_FROM_ETERM(ptr+2));
- }
- /* Skip MFA, tracer, and CP. */
- ptr += 3;
- } else if (BeamIsReturnToTrace(cp_val(*prev))) {
- have_return_to_trace = !0; /* Record next cp */
- return_to_trace_ptr = NULL;
- /* Skip CP. */
- ptr += 1;
- } else if (BeamIsReturnTimeTrace(cp_val(*prev))) {
- /* Skip prev_info and CP. */
- ptr += 2;
- } else {
- if (have_return_to_trace) {
- /* Record this cp as possible return_to trace cp */
- have_return_to_trace = 0;
- return_to_trace_ptr = ptr;
- } else return_to_trace_ptr = NULL;
- ptr++;
- }
- } else ptr++;
+ Eterm val = ptr[0];
+
+ if (is_catch(val)) {
+ if (active_catches) {
+ goto found_catch;
+ }
+
+ ptr++;
+ } else if (is_CP(val)) {
+ ErtsCodePtr return_address;
+ const Eterm *frame;
+
+ prev = ptr;
+ frame = erts_inspect_frame(ptr, &return_address);
+
+ if (BeamIsReturnTrace(return_address)) {
+ if (return_address == beam_exception_trace) {
+ ErtsTracer *tracer;
+ ErtsCodeMFA *mfa;
+
+ mfa = (ErtsCodeMFA*)cp_val(frame[0]);
+ tracer = ERTS_TRACER_FROM_ETERM(&frame[1]);
+
+ ASSERT_MFA(mfa);
+ erts_trace_exception(c_p, mfa, reg[3], reg[1], tracer);
+ }
+
+ ptr += CP_SIZE + 2;
+ } else if (BeamIsReturnTimeTrace(return_address)) {
+ ptr += CP_SIZE + 1;
+ } else if (BeamIsReturnToTrace(return_address)) {
+ have_return_to_trace = 1; /* Record next cp */
+ return_to_trace_address = NULL;
+
+ ptr += CP_SIZE;
+ } else {
+ /* This is an ordinary call frame: if the previous frame was a
+ * return_to trace we should record this CP as a return_to
+ * candidate. */
+ if (have_return_to_trace) {
+ return_to_trace_address = return_address;
+ have_return_to_trace = 0;
+ } else {
+ return_to_trace_address = NULL;
+ }
+
+ ptr += CP_SIZE;
+ }
+ } else {
+ ptr++;
+ }
}
+
return NULL;
found_catch:
ASSERT(ptr < STACK_START(c_p));
c_p->stop = prev;
- if (IS_TRACED_FL(c_p, F_TRACE_RETURN_TO) && return_to_trace_ptr) {
- /* The stackframe closest to the catch contained an
- * return_to_trace entry, so since the execution now
- * continues after the catch, a return_to trace message
- * would be appropriate.
- */
- erts_trace_return_to(c_p, cp_val(*return_to_trace_ptr));
+
+ if (IS_TRACED_FL(c_p, F_TRACE_RETURN_TO) && return_to_trace_address) {
+ /* The stackframe closest to the catch contained an
+ * return_to_trace entry, so since the execution now
+ * continues after the catch, a return_to trace message
+ * would be appropriate.
+ */
+ erts_trace_return_to(c_p, return_to_trace_address);
}
- return catch_pc(*ptr);
+
+ /* Clear the try_tag or catch_tag in the stack frame so that we
+ * don't have to do it in the JITted code for the try_case
+ * instruction. (Unfortunately, a catch_end will still need to
+ * clear the catch_tag because it is executed even when no
+ * exception has occurred.) */
+ handler = catch_pc(*ptr);
+ *ptr = NIL;
+ return handler;
}
/*
@@ -712,6 +754,7 @@ expand_error_value(Process* c_p, Uint freason, Eterm Value) {
case (GET_EXC_INDEX(EXC_BADARITY)):
case (GET_EXC_INDEX(EXC_BADMAP)):
case (GET_EXC_INDEX(EXC_BADKEY)):
+ case (GET_EXC_INDEX(EXC_BADRECORD)):
/* Some common exceptions: value -> {atom, value} */
ASSERT(is_value(Value));
hp = HAlloc(c_p, 3);
@@ -753,35 +796,39 @@ gather_stacktrace(Process* p, struct StackTrace* s, int depth)
while (ptr < STACK_START(p) && depth > 0) {
if (is_CP(*ptr)) {
- ErtsCodePtr cp = cp_val(*ptr);
-
- if (BeamIsReturnTrace(cp)) {
- ptr += 3;
- } else if (BeamIsReturnTimeTrace(cp)) {
- ptr += 2;
- } else if (BeamIsReturnToTrace(cp)) {
- ptr += 1;
+ ErtsCodePtr return_address;
+
+ erts_inspect_frame(ptr, &return_address);
+
+ if (BeamIsReturnTrace(return_address)) {
+ ptr += CP_SIZE + 2;
+ } else if (BeamIsReturnTimeTrace(return_address)) {
+ ptr += CP_SIZE + 1;
+ } else if (BeamIsReturnToTrace(return_address)) {
+ ptr += CP_SIZE;
} else {
- if (cp != prev) {
- void *adjusted_cp;
+ if (return_address != prev) {
+ ErtsCodePtr adjusted_address;
/* Record non-duplicates only */
- prev = cp;
+ prev = return_address;
+
#ifdef BEAMASM
- /*
- * Some instructions (e.g. call) are shorter than one word,
- * so we will need to subtract one byte from the pointer
- * to avoid ending up before the start of the instruction.
- */
- adjusted_cp = ((char *) cp) - 1;
+ /* Some instructions (e.g. call) are shorter than one word,
+ * so we will need to subtract one byte from the pointer
+ * to avoid ending up before the start of the
+ * instruction. */
+ adjusted_address = ((char*)return_address) - 1;
#else
- /* Subtract one word from the pointer. */
- adjusted_cp = ((char *) cp) - sizeof(UWord);
+ /* Subtract one word from the pointer. */
+ adjusted_address = ((char*)return_address) - sizeof(UWord);
#endif
- s->trace[s->depth++] = adjusted_cp;
+
+ s->trace[s->depth++] = adjusted_address;
depth--;
}
- ptr++;
+
+ ptr += CP_SIZE;
}
} else {
ptr++;
@@ -796,7 +843,7 @@ gather_stacktrace(Process* p, struct StackTrace* s, int depth)
*
* There is an issue with line number information. Line number
* information is associated with the address *before* an operation
- * that may fail or be stored stored on the stack. But continuation
+ * that may fail or be stored on the stack. But continuation
* pointers point after its call instruction, not before. To avoid
* finding the wrong line number, we'll need to adjust them so that
* they point at the beginning of the call instruction or inside the
@@ -952,10 +999,13 @@ save_stacktrace(Process* c_p, ErtsCodePtr pc, Eterm* reg,
args = make_arglist(c_p, reg, bif_mfa->arity);
} else {
+ if (c_p->freason & EXF_HAS_EXT_INFO && is_map(c_p->fvalue)) {
+ error_info = c_p->fvalue;
+ }
non_bif_stacktrace:
-
s->current = c_p->current;
+
/*
* For a function_clause error, the arguments are in the beam
* registers and c_p->current is set.
@@ -1065,7 +1115,7 @@ static Eterm *get_freason_ptr_from_exc(Eterm exc) {
if (exc == NIL) {
/*
- * Is is not exactly clear when exc can be NIL. Probably only
+ * It is not exactly clear when exc can be NIL. Probably only
* when the exception has been generated from native code.
* Return a pointer to an Eterm that can be safely written and
* ignored.
@@ -1351,7 +1401,7 @@ apply_bif_error_adjustment(Process *p, Export *ep,
* error handling code.
*/
if (need == 0) {
- need = 1; /* i_apply_only */
+ need = CP_SIZE; /* i_apply_only */
}
if (HeapWordsLeft(p) < need) {
@@ -1365,7 +1415,17 @@ apply_bif_error_adjustment(Process *p, Export *ep,
* Push the continuation pointer for the current function to the stack.
*/
p->stop -= need;
- p->stop[0] = make_cp(I);
+
+ switch (erts_frame_layout) {
+ case ERTS_FRAME_LAYOUT_RA:
+ p->stop[0] = make_cp(I);
+ break;
+ case ERTS_FRAME_LAYOUT_FP_RA:
+ p->stop[0] = make_cp(FRAME_POINTER(p));
+ p->stop[1] = make_cp(I);
+ FRAME_POINTER(p) = &p->stop[0];
+ break;
+ }
} else {
/*
* Called from an i_apply_last_* instruction.
@@ -1377,7 +1437,17 @@ apply_bif_error_adjustment(Process *p, Export *ep,
* and then add a dummy stackframe for the i_apply_last* instruction
* to discard.
*/
- p->stop[0] = make_cp(I);
+ switch (erts_frame_layout) {
+ case ERTS_FRAME_LAYOUT_RA:
+ p->stop[0] = make_cp(I);
+ break;
+ case ERTS_FRAME_LAYOUT_FP_RA:
+ p->stop[0] = make_cp(FRAME_POINTER(p));
+ p->stop[1] = make_cp(I);
+ FRAME_POINTER(p) = &p->stop[0];
+ break;
+ }
+
p->stop -= need;
}
}
@@ -1596,10 +1666,21 @@ erts_hibernate(Process* c_p, Eterm* reg)
c_p->arg_reg[0] = module;
c_p->arg_reg[1] = function;
c_p->arg_reg[2] = args;
- c_p->stop = c_p->hend - CP_SIZE; /* Keep first continuation pointer */
- ASSERT(c_p->stop[0] == make_cp(beam_normal_exit));
+ c_p->stop = c_p->hend - CP_SIZE; /* Keep first continuation pointer */
+
+ switch(erts_frame_layout) {
+ case ERTS_FRAME_LAYOUT_RA:
+ ASSERT(c_p->stop[0] == make_cp(beam_normal_exit));
+ break;
+ case ERTS_FRAME_LAYOUT_FP_RA:
+ FRAME_POINTER(c_p) = &c_p->stop[0];
+ ASSERT(c_p->stop[0] == make_cp(NULL));
+ ASSERT(c_p->stop[1] == make_cp(beam_normal_exit));
+ break;
+ }
+
c_p->catches = 0;
- c_p->i = beam_apply;
+ c_p->i = beam_run_process;
/*
* If there are no waiting messages, garbage collect and
@@ -1628,171 +1709,133 @@ ErtsCodePtr
call_fun(Process* p, /* Current process. */
int arity, /* Number of arguments for Fun. */
Eterm* reg, /* Contents of registers. */
- Eterm args, /* THE_NON_VALUE or pre-built list of arguments. */
- Export **epp) /* Export entry, if any. */
+ Eterm args) /* THE_NON_VALUE or pre-built list of arguments. */
{
- Eterm fun = reg[arity];
- Eterm hdr;
- int i;
- Eterm* hp;
+ ErtsCodeIndex code_ix;
+ ErtsCodePtr code_ptr;
+ ErlFunThing *funp;
+ Eterm fun;
+
+ fun = reg[arity];
- if (!is_boxed(fun)) {
- goto badfun;
+ if (is_not_any_fun(fun)) {
+ p->current = NULL;
+ p->freason = EXC_BADFUN;
+ p->fvalue = fun;
+ return NULL;
}
- hdr = *boxed_val(fun);
- if (is_fun_header(hdr)) {
- ErlFunThing* funp = (ErlFunThing *) fun_val(fun);
- ErlFunEntry* fe = funp->fe;
- ErtsCodePtr code_ptr = fe->address;
- Eterm* var_ptr;
- unsigned num_free = funp->num_free;
- const ErtsCodeMFA *mfa = erts_code_to_codemfa(code_ptr);
- int actual_arity = mfa->arity;
+ funp = (ErlFunThing*)fun_val(fun);
- if (actual_arity == arity+num_free) {
- DTRACE_LOCAL_CALL(p, mfa);
- if (num_free == 0) {
- return code_ptr;
- } else {
- var_ptr = funp->env;
- reg += arity;
- i = 0;
- do {
- reg[i] = var_ptr[i];
- i++;
- } while (i < num_free);
- reg[i] = fun;
- return code_ptr;
- }
- return code_ptr;
- } else {
- /*
- * Something wrong here. First build a list of the arguments.
- */
+ code_ix = erts_active_code_ix();
+ code_ptr = (funp->entry.disp)->addresses[code_ix];
- if (is_non_value(args)) {
- Uint sz = 2 * arity;
- args = NIL;
- if (HeapWordsLeft(p) < sz) {
- erts_garbage_collect(p, sz, reg, arity+1);
- fun = reg[arity];
- }
- hp = HEAP_TOP(p);
- HEAP_TOP(p) += sz;
- for (i = arity-1; i >= 0; i--) {
- args = CONS(hp, reg[i], args);
- hp += 2;
- }
- }
+ if (ERTS_LIKELY(code_ptr != beam_unloaded_fun && funp->arity == arity)) {
+ for (int i = 0, num_free = funp->num_free; i < num_free; i++) {
+ reg[i + arity] = funp->env[i];
+ }
- if (actual_arity >= 0) {
- /*
- * There is a fun defined, but the call has the wrong arity.
- */
- hp = HAlloc(p, 3);
- p->freason = EXC_BADARITY;
- p->fvalue = TUPLE2(hp, fun, args);
- return NULL;
- } else {
- Export* ep;
- Module* modp;
- Eterm module;
- ErtsCodeIndex code_ix = erts_active_code_ix();
-
- /*
- * No arity. There is no module loaded that defines the fun,
- * either because the fun is newly created from the external
- * representation (the module has never been loaded),
- * or the module defining the fun has been unloaded.
- */
-
- module = fe->module;
-
- ERTS_THR_READ_MEMORY_BARRIER;
- if (fe->pend_purge_address) {
- /*
- * The system is currently trying to purge the
- * module containing this fun. Suspend the process
- * and let it try again when the purge operation is
- * done (may succeed or not).
- */
- ep = erts_suspend_process_on_pending_purge_lambda(p, fe);
- ASSERT(ep);
- }
- else {
- if ((modp = erts_get_module(module, code_ix)) != NULL
- && modp->curr.code_hdr != NULL) {
- /*
- * There is a module loaded, but obviously the fun is not
- * defined in it. We must not call the error_handler
- * (or we will get into an infinite loop).
- */
- goto badfun;
- }
+#ifdef USE_VM_CALL_PROBES
+ if (is_local_fun(funp)) {
+ DTRACE_LOCAL_CALL(p, erts_code_to_codemfa(code_ptr));
+ } else {
+ Export *ep = funp->entry.exp;
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ DTRACE_GLOBAL_CALL(p, &ep->info.mfa);
+ }
+#endif
- /*
- * No current code for this module. Call the error_handler module
- * to attempt loading the module.
- */
-
- ep = erts_find_function(erts_proc_get_error_handler(p),
- am_undefined_lambda, 3, code_ix);
- if (ep == NULL) { /* No error handler */
- p->current = NULL;
- p->freason = EXC_UNDEF;
- return NULL;
- }
- }
- reg[0] = module;
- reg[1] = fun;
- reg[2] = args;
- reg[3] = NIL;
- *epp = ep;
- return ep->addresses[code_ix];
- }
- }
- } else if (is_export_header(hdr)) {
- Export *ep;
- int actual_arity;
+ return code_ptr;
+ } else {
+ /* Something wrong here. First build a list of the arguments. */
+ if (is_non_value(args)) {
+ Uint sz = 2 * arity;
+ Eterm *hp;
- ep = *((Export **) (export_val(fun) + 1));
- actual_arity = ep->info.mfa.arity;
+ args = NIL;
- if (arity == actual_arity) {
- DTRACE_GLOBAL_CALL(p, &ep->info.mfa);
- *epp = ep;
- return ep->addresses[erts_active_code_ix()];
- } else {
- /*
- * Wrong arity. First build a list of the arguments.
- */
+ if (HeapWordsLeft(p) < sz) {
+ erts_garbage_collect(p, sz, reg, arity+1);
- if (is_non_value(args)) {
- args = NIL;
- hp = HAlloc(p, arity*2);
- for (i = arity-1; i >= 0; i--) {
- args = CONS(hp, reg[i], args);
- hp += 2;
- }
- }
+ fun = reg[arity];
+ funp = (ErlFunThing*)fun_val(fun);
+ }
- hp = HAlloc(p, 3);
- p->freason = EXC_BADARITY;
- p->fvalue = TUPLE2(hp, fun, args);
- return NULL;
- }
- } else {
- badfun:
- p->current = NULL;
- p->freason = EXC_BADFUN;
- p->fvalue = fun;
- return NULL;
+ hp = HEAP_TOP(p);
+ HEAP_TOP(p) += sz;
+
+ for (int i = arity - 1; i >= 0; i--) {
+ args = CONS(hp, reg[i], args);
+ hp += 2;
+ }
+ }
+
+ if (funp->arity != arity) {
+ /* There is a fun defined, but the call has the wrong arity. */
+ Eterm *hp = HAlloc(p, 3);
+ p->freason = EXC_BADARITY;
+ p->fvalue = TUPLE2(hp, fun, args);
+ return NULL;
+ } else {
+ ErlFunEntry *fe;
+ Eterm module;
+ Module *modp;
+ Export *ep;
+
+ /* There is no module loaded that defines the fun, either because
+ * the fun is newly created from the external representation (the
+ * module has never been loaded), or the module defining the fun
+ * has been unloaded. */
+ ASSERT(is_local_fun(funp) && code_ptr == beam_unloaded_fun);
+ fe = funp->entry.fun;
+ module = fe->module;
+
+ ERTS_THR_READ_MEMORY_BARRIER;
+ if (fe->pend_purge_address) {
+ /* The system is currently trying to purge the
+ * module containing this fun. Suspend the process
+ * and let it try again when the purge operation is
+ * done (may succeed or not). */
+ ep = erts_suspend_process_on_pending_purge_lambda(p, fe);
+ } else {
+ if ((modp = erts_get_module(module, code_ix)) != NULL
+ && modp->curr.code_hdr != NULL) {
+ /* There is a module loaded, but obviously the fun is
+ * not defined in it. We must not call the error_handler
+ * (or we will get into an infinite loop). */
+ p->current = NULL;
+ p->freason = EXC_BADFUN;
+ p->fvalue = fun;
+ return NULL;
+ }
+
+ /* No current code for this module. Call the error_handler
+ * module to attempt loading the module. */
+
+ ep = erts_find_function(erts_proc_get_error_handler(p),
+ am_undefined_lambda, 3, code_ix);
+ if (ep == NULL) {
+ /* No error handler */
+ p->current = NULL;
+ p->freason = EXC_UNDEF;
+ return NULL;
+ }
+ }
+
+ ASSERT(ep);
+
+ reg[0] = module;
+ reg[1] = fun;
+ reg[2] = args;
+ reg[3] = NIL;
+
+ return ep->dispatch.addresses[code_ix];
+ }
}
}
ErtsCodePtr
-apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg, Export **epp)
+apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg)
{
int arity;
Eterm tmp;
@@ -1819,41 +1862,17 @@ apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg, Export **epp)
return NULL;
}
reg[arity] = fun;
- return call_fun(p, arity, reg, args, epp);
-}
-
-ErlFunThing*
-new_fun_thing(Process* p, ErlFunEntry* fe, int num_free)
-{
- const ErtsCodeMFA *mfa;
- ErlFunThing* funp;
-
- mfa = erts_code_to_codemfa(fe->address);
- funp = (ErlFunThing*) p->htop;
- p->htop += ERL_FUN_SIZE + num_free;
- erts_refc_inc(&fe->refc, 2);
-
- funp->thing_word = HEADER_FUN;
- funp->next = MSO(p).first;
- MSO(p).first = (struct erl_off_heap_header*) funp;
- funp->fe = fe;
- funp->num_free = num_free;
- funp->creator = p->common.id;
- funp->arity = mfa->arity - num_free;
-
- return funp;
+ return call_fun(p, arity, reg, args);
}
int
is_function2(Eterm Term, Uint arity)
{
- if (is_fun(Term)) {
- ErlFunThing* funp = (ErlFunThing *) fun_val(Term);
- return funp->arity == arity;
- } else if (is_export(Term)) {
- Export* exp = (Export *) (export_val(Term)[1]);
- return exp->info.mfa.arity == arity;
+ if (is_any_fun(Term)) {
+ ErlFunThing *funp = (ErlFunThing*)fun_val(Term);
+ return funp->arity == arity;
}
+
return 0;
}
@@ -1985,11 +2004,14 @@ erts_gc_new_map(Process* p, Eterm* reg, Uint live,
}
thp = p->htop;
- mhp = thp + 1 + n/2;
+ mhp = thp + (n == 0 ? 0 : 1) + n/2;
E = p->stop;
- keys = make_tuple(thp);
- *thp++ = make_arityval(n/2);
-
+ if (n == 0) {
+ keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ keys = make_tuple(thp);
+ *thp++ = make_arityval(n/2);
+ }
mp = (flatmap_t *)mhp; mhp += MAP_HEADER_FLATMAP_SZ;
mp->thing_word = MAP_HEADER_FLATMAP;
mp->size = n/2;
@@ -2159,7 +2181,7 @@ erts_gc_update_map_assoc(Process* p, Eterm* reg, Uint live,
old_keys++, old_vals++, num_old--;
} else { /* Replace or insert new */
GET_TERM(new_p[1], *hp++);
- if (c > 0) { /* If new new key */
+ if (c > 0) { /* If new key */
*kp++ = new_key;
} else { /* If replacement */
*kp++ = key;
diff --git a/erts/emulator/beam/beam_common.h b/erts/emulator/beam/beam_common.h
index 52140c8a3e..f3725d0d2e 100644
--- a/erts/emulator/beam/beam_common.h
+++ b/erts/emulator/beam/beam_common.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -153,80 +153,81 @@ do { \
#ifdef USE_VM_CALL_PROBES
-#define DTRACE_LOCAL_CALL(p, mfa) \
- if (DTRACE_ENABLED(local_function_entry)) { \
- DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
- DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
- int depth = STACK_START(p) - STACK_TOP(p); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
- DTRACE3(local_function_entry, process_name, mfa_buf, depth); \
+#define DTRACE_LOCAL_CALL(p, cmfa) \
+ if (DTRACE_ENABLED(local_function_entry)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
+ int depth = STACK_START(p) - STACK_TOP(p); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
+ DTRACE3(local_function_entry, process_name, mfa_buf, depth); \
}
-#define DTRACE_GLOBAL_CALL(p, mfa) \
- if (DTRACE_ENABLED(global_function_entry)) { \
- DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
- DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
- int depth = STACK_START(p) - STACK_TOP(p); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
+#define DTRACE_GLOBAL_CALL(p, cmfa) \
+ if (DTRACE_ENABLED(global_function_entry)) { \
+ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
+ DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
+ int depth = STACK_START(p) - STACK_TOP(p); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
DTRACE3(global_function_entry, process_name, mfa_buf, depth); \
}
-#define DTRACE_RETURN(p, mfa) \
+#define DTRACE_RETURN(p, cmfa) \
if (DTRACE_ENABLED(function_return)) { \
DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
int depth = STACK_START(p) - STACK_TOP(p); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
DTRACE3(function_return, process_name, mfa_buf, depth); \
}
-#define DTRACE_BIF_ENTRY(p, mfa) \
+#define DTRACE_BIF_ENTRY(p, cmfa) \
if (DTRACE_ENABLED(bif_entry)) { \
DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
DTRACE2(bif_entry, process_name, mfa_buf); \
}
-#define DTRACE_BIF_RETURN(p, mfa) \
+#define DTRACE_BIF_RETURN(p, cmfa) \
if (DTRACE_ENABLED(bif_return)) { \
DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
DTRACE2(bif_return, process_name, mfa_buf); \
}
-#define DTRACE_NIF_ENTRY(p, mfa) \
+#define DTRACE_NIF_ENTRY(p, cmfa) \
if (DTRACE_ENABLED(nif_entry)) { \
DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
DTRACE2(nif_entry, process_name, mfa_buf); \
}
-#define DTRACE_NIF_RETURN(p, mfa) \
+#define DTRACE_NIF_RETURN(p, cmfa) \
if (DTRACE_ENABLED(nif_return)) { \
DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \
DTRACE_CHARBUF(mfa_buf, DTRACE_TERM_BUF_SIZE); \
- dtrace_fun_decode(p, mfa, process_name, mfa_buf); \
+ dtrace_fun_decode(p, cmfa, process_name, mfa_buf); \
DTRACE2(nif_return, process_name, mfa_buf); \
}
-#define DTRACE_GLOBAL_CALL_FROM_EXPORT(p,e) \
- do { \
- if (DTRACE_ENABLED(global_function_entry)) { \
- ErtsCodePtr fp__ = (((Export *) (e))->addresses[erts_active_code_ix()]); \
- DTRACE_GLOBAL_CALL((p), erts_code_to_codemfa(fp__)); \
- } \
+#define DTRACE_GLOBAL_CALL_FROM_EXPORT(p,e) \
+ do { \
+ if (DTRACE_ENABLED(global_function_entry)) { \
+ ErtsDispatchable *disp__ = &(e)->dispatch; \
+ ErtsCodePtr fp__ = disp__->addresses[erts_active_code_ix()]; \
+ DTRACE_GLOBAL_CALL((p), erts_code_to_codemfa(fp__)); \
+ } \
} while(0)
-#define DTRACE_RETURN_FROM_PC(p, i) \
- do { \
- const ErtsCodeMFA* cmfa; \
- if (DTRACE_ENABLED(function_return) && (cmfa = erts_find_function_from_pc(i))) { \
- DTRACE_RETURN((p), cmfa); \
- } \
- } while(0)
+#define DTRACE_RETURN_FROM_PC(p, i) \
+ if (DTRACE_ENABLED(function_return)) { \
+ const ErtsCodeMFA* cmfa = erts_find_function_from_pc(i); \
+ if (cmfa) { \
+ DTRACE_RETURN((p), cmfa); \
+ } \
+ }
#else /* USE_VM_PROBES */
#define DTRACE_LOCAL_CALL(p, mfa) do {} while (0)
@@ -255,13 +256,8 @@ Export* call_error_handler(Process* p, const ErtsCodeMFA* mfa,
Export* fixed_apply(Process* p, Eterm* reg, Uint arity,
ErtsCodePtr I, Uint offs);
Export* apply(Process* p, Eterm* reg, ErtsCodePtr I, Uint offs);
-ErtsCodePtr call_fun(Process* p, int arity, Eterm* reg,
- Eterm args, Export **epp);
-ErtsCodePtr apply_fun(Process* p, Eterm fun, Eterm args,
- Eterm* reg, Export **epp);
-Eterm new_fun(Process* p, Eterm* reg,
- ErlFunEntry* fe, int num_free);
-ErlFunThing* new_fun_thing(Process* p, ErlFunEntry* fe, int num_free);
+ErtsCodePtr call_fun(Process* p, int arity, Eterm* reg, Eterm args);
+ErtsCodePtr apply_fun(Process* p, Eterm fun, Eterm args, Eterm* reg);
int is_function2(Eterm Term, Uint arity);
Eterm erts_gc_new_map(Process* p, Eterm* reg, Uint live,
Uint n, const Eterm* data);
@@ -281,17 +277,41 @@ void copy_in_registers(Process *c_p, Eterm *reg);
void check_monitor_long_schedule(Process *c_p, Uint64 start_time,
ErtsCodePtr start_time_i);
-
-extern ErtsCodePtr beam_apply;
+extern ErtsCodePtr beam_run_process;
extern ErtsCodePtr beam_normal_exit;
extern ErtsCodePtr beam_exit;
extern ErtsCodePtr beam_save_calls;
extern ErtsCodePtr beam_bif_export_trap;
extern ErtsCodePtr beam_export_trampoline;
extern ErtsCodePtr beam_continue_exit;
+extern ErtsCodePtr beam_unloaded_fun;
+
extern ErtsCodePtr beam_return_to_trace; /* OpCode(i_return_to_trace) */
extern ErtsCodePtr beam_return_trace; /* OpCode(i_return_trace) */
extern ErtsCodePtr beam_exception_trace; /* OpCode(i_exception_trace) */
extern ErtsCodePtr beam_return_time_trace; /* OpCode(i_return_time_trace) */
+/** @brief Inspects an Erlang stack frame, returning the base of the data
+ * (first Y register).
+ * @param[in] frame The frame to inspect. Must point at a CP.
+ * @param[out] return_address The return address of \p frame */
+ERTS_GLB_INLINE
+const Eterm *erts_inspect_frame(Eterm *frame, ErtsCodePtr *return_address);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE
+const Eterm *erts_inspect_frame(Eterm *frame, ErtsCodePtr *return_address) {
+ ASSERT(is_CP(frame[0]));
+
+ if (ERTS_LIKELY(erts_frame_layout == ERTS_FRAME_LAYOUT_RA)) {
+ *return_address = (ErtsCodePtr)cp_val(frame[0]);
+ return &frame[1];
+ }
+
+ ASSERT(cp_val(frame[0]) == NULL || frame < (Eterm*)cp_val(frame[0]));
+ *return_address = (ErtsCodePtr)cp_val(frame[1]);
+ return &frame[2];
+}
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
#endif /* _BEAM_COMMON_H_ */
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index abf00ecaf8..5b7e2a9414 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -306,7 +306,7 @@ erts_debug_disassemble_1(BIF_ALIST_1)
* But this code_ptr will point to the start of the Export,
* not the function's func_info instruction. BOOM !?
*/
- cmfa = erts_code_to_codemfa(ep->addresses[code_ix]);
+ cmfa = erts_code_to_codemfa(ep->dispatch.addresses[code_ix]);
} else if (modp == NULL || (code_hdr = modp->curr.code_hdr) == NULL) {
BIF_RET(am_undef);
} else {
@@ -624,7 +624,11 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr)
}
break;
default:
+#ifdef ARCH_64
+ erts_print(to, to_arg, "%ld", *ap);
+#else
erts_print(to, to_arg, "%d", *ap);
+#endif
}
ap++;
break;
@@ -678,7 +682,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr)
case 'F': /* Function definition */
{
ErlFunEntry* fe = (ErlFunEntry *) *ap;
- const ErtsCodeMFA *cmfa = erts_find_function_from_pc(fe->address);
+ const ErtsCodeMFA *cmfa = erts_get_fun_mfa(fe);
erts_print(to, to_arg, "fun(`%T`:`%T`/%bpu)", cmfa->module,
cmfa->function, cmfa->arity);
ap++;
@@ -885,7 +889,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
- case op_i_make_fun3_Fdt:
+ case op_i_make_fun3_Fdtt:
{
int n = unpacked[-1];
@@ -905,6 +909,55 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
+ case op_i_bs_create_bin_jIWdW:
+ {
+ int n = unpacked[-1];
+ int i = 0;
+ Eterm type = 0;
+
+ while (n > 0) {
+ switch (i % 5) {
+ case 0: /* Type */
+ type = ap[i];
+ erts_print(to, to_arg, " `%d`", type);
+ break;
+ case 1: /* Unit */
+ case 2: /* Flags */
+ erts_print(to, to_arg, " `%d`", (Eterm) ap[i]);
+ break;
+ case 4: /* Size */
+ if (type == BSC_BINARY_FIXED_SIZE ||
+ type == BSC_FLOAT_FIXED_SIZE ||
+ type == BSC_INTEGER_FIXED_SIZE ||
+ type == BSC_STRING ||
+ type == BSC_UTF32) {
+ erts_print(to, to_arg, " `%d`", ap[i]);
+ break;
+ }
+
+ /*FALLTHROUGH*/
+ case 3: /* Src */
+ if (type == BSC_STRING) {
+ erts_print(to, to_arg, " ");
+ print_byte_string(to, to_arg, (byte *) ap[i], ap[i+1]);
+ break;
+ }
+ switch (loader_tag(ap[i])) {
+ case LOADER_X_REG:
+ erts_print(to, to_arg, " x(%d)", loader_x_reg_index(ap[i]));
+ break;
+ case LOADER_Y_REG:
+ erts_print(to, to_arg, " y(%d)", loader_y_reg_index(ap[i]) - CP_SIZE);
+ break;
+ default:
+ erts_print(to, to_arg, " `%T`", (Eterm) ap[i]);
+ break;
+ }
+ }
+ i++, size++, n--;
+ }
+ }
+ break;
}
erts_print(to, to_arg, "\n");
@@ -1085,7 +1138,7 @@ dirty_test(Process *c_p, Eterm type, Eterm arg1, Eterm arg2, ErtsCodePtr I)
Eterm *hp, sz;
Eterm cpy;
/* We do not want this to be optimized,
- but rather the oposite... */
+ but rather the opposite... */
sz = size_object(arg2);
hp = HAlloc(c_p, sz);
cpy = copy_struct(arg2, sz, &hp, &c_p->off_heap);
diff --git a/erts/emulator/beam/beam_file.c b/erts/emulator/beam/beam_file.c
index 4bae61ceb7..0c7bdfbec2 100644
--- a/erts/emulator/beam/beam_file.c
+++ b/erts/emulator/beam/beam_file.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,9 @@
#include "beam_load.h"
#include "erl_zlib.h"
#include "big.h"
+#include "erl_unicode.h"
+#include "erl_binary.h"
+#include "erl_global_literals.h"
#define LoadError(Expr) \
do { \
@@ -57,7 +60,10 @@ struct BeamCodeReader__ {
BeamFile *file;
BeamOp *pending;
- Uint first;
+
+ BeamOpArg current_func_label;
+ BeamOpArg current_entry_label;
+ int first;
};
typedef struct {
@@ -230,7 +236,6 @@ static int beamreader_read_tagged(BeamReader *reader, TaggedNumber *val) {
}
static int parse_atom_chunk(BeamFile *beam,
- ErtsAtomEncoding enc,
IFF_Chunk *chunk) {
BeamFile_AtomTable *atoms;
BeamReader reader;
@@ -255,7 +260,6 @@ static int parse_atom_chunk(BeamFile *beam,
atoms->entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
count * sizeof(atoms->entries[0]));
atoms->entries[0] = THE_NON_VALUE;
- atoms->encoding = enc;
atoms->count = count;
for (i = 1; i < count; i++) {
@@ -266,7 +270,7 @@ static int parse_atom_chunk(BeamFile *beam,
LoadAssert(beamreader_read_u8(&reader, &length));
LoadAssert(beamreader_read_bytes(&reader, length, &string));
- atom = erts_atom_put(string, length, enc, 1);
+ atom = erts_atom_put(string, length, ERTS_ATOM_ENC_UTF8, 1);
LoadAssert(atom != THE_NON_VALUE);
atoms->entries[i] = atom;
@@ -320,24 +324,23 @@ static int parse_import_chunk(BeamFile *beam, IFF_Chunk *chunk) {
return 1;
}
-static int parse_export_chunk(BeamFile *beam, IFF_Chunk *chunk) {
- BeamFile_ExportTable *exports;
+static int parse_export_table(BeamFile_ExportTable *dest,
+ BeamFile *beam, IFF_Chunk *chunk) {
BeamFile_AtomTable *atoms;
BeamReader reader;
Sint32 count;
int i;
- exports = &beam->exports;
- ASSERT(exports->entries == NULL);
+ ASSERT(dest->entries == NULL);
beamreader_init(chunk->data, chunk->size, &reader);
LoadAssert(beamreader_read_i32(&reader, &count));
- LoadAssert(CHECK_ITEM_COUNT(count, 0, sizeof(exports->entries[0])));
+ LoadAssert(CHECK_ITEM_COUNT(count, 0, sizeof(dest->entries[0])));
- exports->entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
- count * sizeof(exports->entries[0]));
- exports->count = count;
+ dest->entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
+ count * sizeof(dest->entries[0]));
+ dest->count = count;
atoms = &beam->atoms;
@@ -352,14 +355,24 @@ static int parse_export_chunk(BeamFile *beam, IFF_Chunk *chunk) {
LoadAssert(arity >= 0 && arity <= MAX_ARG);
LoadAssert(label >= 0);
- exports->entries[i].function = atoms->entries[atom_index];
- exports->entries[i].arity = arity;
- exports->entries[i].label = label;
+ dest->entries[i].function = atoms->entries[atom_index];
+ dest->entries[i].arity = arity;
+ dest->entries[i].label = label;
}
return 1;
}
+static int parse_export_chunk(BeamFile *beam, IFF_Chunk *chunk) {
+ return parse_export_table(&beam->exports, beam, chunk);
+}
+
+#ifdef BEAMASM
+static int parse_locals_chunk(BeamFile *beam, IFF_Chunk *chunk) {
+ return parse_export_table(&beam->locals, beam, chunk);
+}
+#endif
+
static int parse_lambda_chunk(BeamFile *beam, IFF_Chunk *chunk) {
BeamFile_LambdaTable *lambdas;
BeamFile_AtomTable *atoms;
@@ -436,6 +449,10 @@ static int parse_line_chunk(BeamFile *beam, IFF_Chunk *chunk) {
LoadAssert(CHECK_ITEM_COUNT(item_count, 0, sizeof(lines->items[0])));
LoadAssert(CHECK_ITEM_COUNT(name_count, 0, sizeof(lines->names[0])));
+ /* Include the implicit "module name with .erl suffix" entry so we don't
+ * have to special-case it anywhere else. */
+ name_count++;
+
/* Flags are unused at the moment. */
(void)flags;
@@ -448,17 +465,20 @@ static int parse_line_chunk(BeamFile *beam, IFF_Chunk *chunk) {
item_count * sizeof(lines->items[0]));
lines->item_count = item_count;
- lines->names = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
- name_count * sizeof(lines->names[0]));
- lines->name_count = name_count;
-
- lines->location_size = lines->name_count ? sizeof(Sint32) : sizeof(Sint16);
-
/* The zeroth entry in the line item table is always present and contains
* the "undefined location." */
lines->items[0].name_index = 0;
lines->items[0].location = 0;
+ lines->names = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
+ name_count * sizeof(lines->names[0]));
+ lines->name_count = name_count;
+
+ /* We have to use the 32-bit representation if there's any names other than
+ * the implicit "module_name.erl" in the table, as we can't fit LOC_FILE in
+ * 16 bits. */
+ lines->location_size = name_count > 1 ? sizeof(Sint32) : sizeof(Sint16);
+
name_index = 0;
i = 1;
@@ -494,20 +514,130 @@ static int parse_line_chunk(BeamFile *beam, IFF_Chunk *chunk) {
}
}
- for (i = 0; i < name_count; i++) {
- Sint16 name_length;
- const byte *name_data;
- Eterm name;
+ /* Add the implicit "module_name.erl" entry, followed by the rest of the
+ * name table. */
+ {
+ Eterm default_name_buf[MAX_ATOM_CHARACTERS * 2];
+ Eterm *name_heap = default_name_buf;
+ Eterm name, suffix;
+ Eterm *hp;
+
+ suffix = erts_get_global_literal(ERTS_LIT_ERL_FILE_SUFFIX);
+
+ hp = name_heap;
+ name = erts_atom_to_string(&hp, beam->module, suffix);
+
+ lines->names[0] = beamfile_add_literal(beam, name);
+
+ for (i = 1; i < name_count; i++) {
+ Uint num_chars, num_built, num_eaten;
+ const byte *name_data, *err_pos;
+ Sint16 name_length;
+ Eterm *hp;
+
+ LoadAssert(beamreader_read_i16(&reader, &name_length));
+ LoadAssert(name_length >= 0);
+
+ LoadAssert(beamreader_read_bytes(&reader, name_length, &name_data));
+
+ if (name_length > 0) {
+ LoadAssert(erts_analyze_utf8(name_data, name_length,
+ &err_pos, &num_chars,
+ NULL) == ERTS_UTF8_OK);
+
+ if (num_chars < MAX_ATOM_CHARACTERS) {
+ name_heap = default_name_buf;
+ } else {
+ name_heap = erts_alloc(ERTS_ALC_T_LOADER_TMP,
+ num_chars * sizeof(Eterm[2]));
+ }
+
+ hp = name_heap;
+ name = erts_make_list_from_utf8_buf(&hp, num_chars,
+ name_data,
+ name_length,
+ &num_built,
+ &num_eaten,
+ NIL);
+
+ ASSERT(num_built == num_chars);
+ ASSERT(num_eaten == name_length);
+
+ lines->names[i] = beamfile_add_literal(beam, name);
+
+ if (name_heap != default_name_buf) {
+ erts_free(ERTS_ALC_T_LOADER_TMP, name_heap);
+ }
+ } else {
+ /* Empty file names are rather unusual and annoying to deal
+ * with since NIL isn't a valid literal, so we'll fake it with
+ * our module name instead. */
+ lines->names[i] = lines->names[0];
+ }
+ }
+ }
+
+ return 1;
+}
+
+/* We assume the presence of a type table to simplify loading, so we'll need to
+ * create a dummy table (with single entry for the "any type") when we don't
+ * have one. */
+static void init_fallback_type_table(BeamFile *beam) {
+ BeamFile_TypeTable *types;
+
+ types = &beam->types;
+ ASSERT(types->entries == NULL);
+
+ types->entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
+ sizeof(types->entries[0]));
+ types->count = 1;
+ types->fallback = 1;
+
+ types->entries[0].type_union = BEAM_TYPE_ANY;
+ types->entries[0].min = 0;
+ types->entries[0].max = -1;
+}
+
+static int parse_type_chunk(BeamFile *beam, IFF_Chunk *chunk) {
+ BeamFile_TypeTable *types;
+ BeamReader reader;
+
+ Sint32 version, count;
+ int i;
+
+ beamreader_init(chunk->data, chunk->size, &reader);
+
+ LoadAssert(beamreader_read_i32(&reader, &version));
+ if (version != BEAM_TYPES_VERSION) {
+ /* Incompatible type format. */
+ init_fallback_type_table(beam);
+ return 1;
+ }
+
+ types = &beam->types;
+ ASSERT(types->entries == NULL);
+
+ LoadAssert(beamreader_read_i32(&reader, &count));
+ LoadAssert(CHECK_ITEM_COUNT(count, 0, sizeof(types->entries[0])));
+ LoadAssert(count >= 1);
- LoadAssert(beamreader_read_i16(&reader, &name_length));
- LoadAssert(beamreader_read_bytes(&reader, name_length, &name_data));
+ types->entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
+ count * sizeof(types->entries[0]));
+ types->count = count;
+ types->fallback = 0;
- name = erts_atom_put(name_data, name_length, ERTS_ATOM_ENC_UTF8, 1);
- LoadAssert(name != THE_NON_VALUE);
+ for (i = 0; i < count; i++) {
+ const byte *type_data;
- lines->names[i] = name;
+ LoadAssert(beamreader_read_bytes(&reader, 18, &type_data));
+ LoadAssert(beam_types_decode(type_data, 18, &types->entries[i]));
}
+ /* The first entry MUST be the "any type." */
+ LoadAssert(types->entries[0].type_union == BEAM_TYPE_ANY);
+ LoadAssert(types->entries[0].min > types->entries[0].max);
+
return 1;
}
@@ -726,7 +856,7 @@ static int read_beam_chunks(const IFF_File *file,
enum beamfile_read_result
beamfile_read(const byte *data, size_t size, BeamFile *beam) {
static const Uint chunk_iffs[] = {
- MakeIffId('A', 't', 'o', 'm'), /* 0 */
+ MakeIffId('A', 't', 'U', '8'), /* 0 */
MakeIffId('C', 'o', 'd', 'e'), /* 1 */
MakeIffId('S', 't', 'r', 'T'), /* 2 */
MakeIffId('I', 'm', 'p', 'T'), /* 3 */
@@ -736,10 +866,13 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
MakeIffId('A', 't', 't', 'r'), /* 7 */
MakeIffId('C', 'I', 'n', 'f'), /* 8 */
MakeIffId('L', 'i', 'n', 'e'), /* 9 */
- MakeIffId('A', 't', 'U', '8'), /* 10 */
+ MakeIffId('L', 'o', 'c', 'T'), /* 10 */
+ MakeIffId('A', 't', 'o', 'm'), /* 11 */
+ MakeIffId('T', 'y', 'p', 'e'), /* 12 */
+ MakeIffId('M', 'e', 't', 'a'), /* 13 */
};
- static const int ATOM_CHUNK = 0;
+ static const int UTF8_ATOM_CHUNK = 0;
static const int CODE_CHUNK = 1;
static const int STR_CHUNK = 2;
static const int IMP_CHUNK = 3;
@@ -749,7 +882,12 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
static const int ATTR_CHUNK = 7;
static const int COMPILE_CHUNK = 8;
static const int LINE_CHUNK = 9;
- static const int UTF8_ATOM_CHUNK = 10;
+#ifdef BEAMASM
+ static const int LOC_CHUNK = 10;
+#endif
+ static const int OBSOLETE_ATOM_CHUNK = 11;
+ static const int TYPE_CHUNK = 12;
+ static const int META_CHUNK = 13;
static const int NUM_CHUNKS = sizeof(chunk_iffs) / sizeof(chunk_iffs[0]);
@@ -757,8 +895,6 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
/* MSVC doesn't like the use of NUM_CHUNKS here */
IFF_Chunk chunks[sizeof(chunk_iffs) / sizeof(chunk_iffs[0])];
- IFF_Chunk *atom_chunk;
- ErtsAtomEncoding enc;
sys_memset(beam, 0, sizeof(*beam));
@@ -780,18 +916,16 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
goto error;
}
- if (chunks[UTF8_ATOM_CHUNK].size > 0) {
- atom_chunk = &chunks[UTF8_ATOM_CHUNK];
- enc = ERTS_ATOM_ENC_UTF8;
- } else if (chunks[ATOM_CHUNK].size > 0) {
- atom_chunk = &chunks[ATOM_CHUNK];
- enc = ERTS_ATOM_ENC_LATIN1;
- } else {
- error = BEAMFILE_READ_MISSING_ATOM_TABLE;
+ if (chunks[UTF8_ATOM_CHUNK].size == 0) {
+ if (chunks[OBSOLETE_ATOM_CHUNK].size == 0) {
+ /* Old atom table chunk is also missing. */
+ error = BEAMFILE_READ_MISSING_ATOM_TABLE;
+ } else {
+ /* Old atom table chunk table exists. (OTP 20 or earlier.) */
+ error = BEAMFILE_READ_OBSOLETE_ATOM_TABLE;
+ }
goto error;
- }
-
- if (!parse_atom_chunk(beam, enc, atom_chunk)) {
+ } else if (!parse_atom_chunk(beam, &chunks[UTF8_ATOM_CHUNK])) {
error = BEAMFILE_READ_CORRUPT_ATOM_TABLE;
goto error;
}
@@ -812,6 +946,15 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
goto error;
}
+#ifdef BEAMASM
+ if (erts_jit_asm_dump && chunks[LOC_CHUNK].size > 0) {
+ if (!parse_locals_chunk(beam, &chunks[LOC_CHUNK])) {
+ error = BEAMFILE_READ_CORRUPT_LOCALS_TABLE;
+ goto error;
+ }
+ }
+#endif
+
if (chunks[LAMBDA_CHUNK].size > 0) {
if (!parse_lambda_chunk(beam, &chunks[LAMBDA_CHUNK])) {
error = BEAMFILE_READ_CORRUPT_LAMBDA_TABLE;
@@ -833,6 +976,15 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
}
}
+ if (chunks[TYPE_CHUNK].size > 0) {
+ if (!parse_type_chunk(beam, &chunks[TYPE_CHUNK])) {
+ error = BEAMFILE_READ_CORRUPT_TYPE_TABLE;
+ goto error;
+ }
+ } else {
+ init_fallback_type_table(beam);
+ }
+
beam->strings.data = chunks[STR_CHUNK].data;
beam->strings.size = chunks[STR_CHUNK].size;
@@ -849,8 +1001,8 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
MD5Init(&md5);
MD5Update(&md5,
- (byte*)atom_chunk->data,
- atom_chunk->size);
+ (byte*)chunks[UTF8_ATOM_CHUNK].data,
+ chunks[UTF8_ATOM_CHUNK].size);
MD5Update(&md5,
(byte*)chunks[CODE_CHUNK].data,
chunks[CODE_CHUNK].size);
@@ -902,6 +1054,12 @@ beamfile_read(const byte *data, size_t size, BeamFile *beam) {
chunks[LITERAL_CHUNK].size);
}
+ if (chunks[META_CHUNK].size > 0) {
+ MD5Update(&md5,
+ (byte*)chunks[META_CHUNK].data,
+ chunks[META_CHUNK].size);
+ }
+
MD5Final(beam->checksum, &md5);
}
@@ -940,6 +1098,13 @@ void beamfile_free(BeamFile *beam) {
beam->exports.entries = NULL;
}
+#ifdef BEAMASM
+ if (beam->locals.entries) {
+ erts_free(ERTS_ALC_T_PREPARED_CODE, beam->locals.entries);
+ beam->locals.entries = NULL;
+ }
+#endif
+
if (beam->lambdas.entries) {
erts_free(ERTS_ALC_T_PREPARED_CODE, beam->lambdas.entries);
beam->lambdas.entries = NULL;
@@ -955,6 +1120,11 @@ void beamfile_free(BeamFile *beam) {
beam->lines.names = NULL;
}
+ if (beam->types.entries) {
+ erts_free(ERTS_ALC_T_PREPARED_CODE, beam->types.entries);
+ beam->types.entries = NULL;
+ }
+
if (beam->static_literals.entries) {
beamfile_literal_dtor(&beam->static_literals);
}
@@ -1101,6 +1271,16 @@ int iff_read_chunk(IFF_File *iff, Uint id, IFF_Chunk *chunk)
return read_beam_chunks(iff, 1, &id, chunk);
}
+void beamfile_init() {
+ Eterm suffix;
+ Eterm *hp;
+
+ hp = erts_alloc_global_literal(ERTS_LIT_ERL_FILE_SUFFIX, 8);
+ suffix = erts_bin_bytes_to_list(NIL, hp, (byte*)".erl", 4, 0);
+
+ erts_register_global_literal(ERTS_LIT_ERL_FILE_SUFFIX, suffix);
+}
+
/* * * * * * * */
void beamopallocator_init(BeamOpAllocator *allocator) {
@@ -1313,8 +1493,7 @@ static int beamcodereader_read_next(BeamCodeReader *code_reader, BeamOp **out) {
reader = &code_reader->reader;
LoadAssert(beamreader_read_u8(reader, &opcode));
- LoadAssert(opcode <= MAX_GENERIC_OPCODE);
- LoadAssert(gen_opc[opcode].name[0] != '\0');
+ LoadAssert(opcode > 0 && opcode <= MAX_GENERIC_OPCODE);
arity = gen_opc[opcode].arity;
ASSERT(arity <= ERTS_BEAM_MAX_OPARGS);
@@ -1354,12 +1533,6 @@ static int beamcodereader_read_next(BeamCodeReader *code_reader, BeamOp **out) {
case TAG_i:
LoadAssert(marshal_integer(code_reader, &raw_arg));
break;
- case TAG_h:
- /* Character, must be a valid unicode code point. */
- LoadAssert(raw_arg.word_value <= 0x10FFFF &&
- (raw_arg.word_value < 0xD800 ||
- raw_arg.word_value > 0xDFFFUL));
- break;
case TAG_x:
case TAG_y:
LoadAssert(raw_arg.word_value < MAX_REG);
@@ -1428,7 +1601,7 @@ static int beamcodereader_read_next(BeamCodeReader *code_reader, BeamOp **out) {
case 4:
/* Literal */
{
- BeamFile_LiteralTable *literals;
+ const BeamFile_LiteralTable *literals;
TaggedNumber index;
LoadAssert(beamreader_read_tagged(reader, &index));
@@ -1444,6 +1617,31 @@ static int beamcodereader_read_next(BeamCodeReader *code_reader, BeamOp **out) {
break;
}
+ case 5:
+ /* Register with type hint */
+ {
+ const BeamFile_TypeTable *types;
+ TaggedNumber index;
+
+ LoadAssert(beamreader_read_tagged(reader, &raw_arg));
+ LoadAssert(raw_arg.tag == TAG_x || raw_arg.tag == TAG_y);
+
+ LoadAssert(beamreader_read_tagged(reader, &index));
+ LoadAssert(index.tag == TAG_u);
+
+ types = &(code_reader->file)->types;
+
+ /* We may land here without a table if it was stripped
+ * after compilation, in which case we want to treat these
+ * as ordinary registers. */
+ if (!types->fallback) {
+ LoadAssert(index.word_value < types->count);
+
+ ERTS_CT_ASSERT(REG_MASK < (1 << 10));
+ raw_arg.word_value |= index.word_value << 10;
+ }
+ break;
+ }
default:
LoadError("Unrecognized extended tag");
}
@@ -1465,82 +1663,101 @@ static int beamcodereader_read_next(BeamCodeReader *code_reader, BeamOp **out) {
return 1;
}
+static void synthesize_func_end(BeamCodeReader *code_reader) {
+ BeamOp *func_end;
+
+ func_end = beamopallocator_new_op(code_reader->allocator);
+ func_end->op = genop_int_func_end_2;
+ func_end->arity = 2;
+
+ ASSERT(code_reader->current_func_label.type == TAG_u);
+ func_end->a[0].val = code_reader->current_func_label.val;
+ func_end->a[0].type = TAG_f;
+
+ ASSERT(code_reader->current_entry_label.type == TAG_u);
+ func_end->a[1].val = code_reader->current_entry_label.val;
+ func_end->a[1].type = TAG_f;
+
+ func_end->next = code_reader->pending;
+ code_reader->pending = func_end;
+}
int beamcodereader_next(BeamCodeReader *code_reader, BeamOp **out) {
BeamOp *op;
if (code_reader->pending) {
- *out = code_reader->pending;
- code_reader->pending = code_reader->pending->next;
+ op = code_reader->pending;
+ code_reader->pending = op->next;
+
+ *out = op;
return 1;
}
LoadAssert(beamcodereader_read_next(code_reader, &op));
- if (op->op != genop_label_1) {
- *out = op;
- return 1;
- } else {
- /*
- * To simplify the rest of the loading process, attempt
- * to synthesize int_func_start/5 and int_func_end/0
- * instructions.
+ switch (op->op) {
+ case genop_label_1:
+ /* To simplify the rest of the loading process, attempt to synthesize
+ * int_func_start/5 and int_func_end/2 instructions.
*
* We look for the following instruction sequence to
* find function boundaries: label Lbl | line Loc | func_info M F A.
* (Where the line instruction is optional.)
*
- * So far we have seen a label/0 instruction. Put this
- * instruction into the pending queue and decode the next
- * instruction.
- */
+ * So far we have seen a label/0 instruction. Put this instruction into
+ * the pending queue and decode the next instruction. */
code_reader->pending = op;
LoadAssert(beamcodereader_read_next(code_reader, &op->next));
op = op->next;
- /*
- * If the current instruction is a line instruction, append it to
- * the pending queue and decode the following instruction.
- */
+ /* If the current instruction is a line instruction, append it to
+ * the pending queue and decode the following instruction. */
if (op->op == genop_line_1) {
LoadAssert(beamcodereader_read_next(code_reader, &op->next));
op = op->next;
}
- /*
- * If the current instruction is a func_info instruction, we
- * have found a function boundary.
- */
- if (op->op == genop_func_info_3) {
+ /* The code must not end abruptly after a label. */
+ LoadAssert(op->op != genop_int_code_end_0);
+
+ /* If the current instruction is a func_info instruction, we
+ * have found a function boundary. */
+ if (ERTS_LIKELY(op->op != genop_func_info_3)) {
+ op->next = NULL;
+ } else {
+ BeamOpArg func_label, entry_label;
BeamOp *func_start;
+ BeamOp *entry_op;
BeamOp *next;
- /*
- * Prepare to walk through the queue of pending instructions.
- */
+ /* The func_info/3 instruction must be followed by its entry
+ * label. */
+ LoadAssert(beamcodereader_read_next(code_reader, &entry_op));
+ LoadAssert(entry_op->op == genop_label_1);
+ entry_label = entry_op->a[0];
+ LoadAssert(entry_label.type == TAG_u);
+ entry_op->next = NULL;
+
+ /* Prepare to walk through the queue of pending instructions. */
op = code_reader->pending;
- ASSERT(op->op == genop_label_1);
- /*
- * Allocate the int_func_start/0 function.
- */
- func_start = beamopallocator_new_op(code_reader->allocator);
- func_start->op = genop_int_func_start_5;
- func_start->arity = 5;
+ /* Pick up the label from the first label/1 instruction. */
+ ASSERT(op->op == genop_label_1);
+ func_label = op->a[0];
+ LoadAssert(func_label.type == TAG_u);
- /*
- * Pick up the label from the label/1 instruction.
- */
- func_start->a[0] = op->a[0];
next = op->next;
beamopallocator_free_op(code_reader->allocator, op);
op = next;
- /*
- * If the current instruction is a line/1 instruction,
- * pick up the location from that instruction.
- * Otherwise use NIL.
- */
+ /* Allocate the int_func_start/0 function. */
+ func_start = beamopallocator_new_op(code_reader->allocator);
+ func_start->op = genop_int_func_start_5;
+ func_start->arity = 5;
+ func_start->a[0] = func_label;
+
+ /* If the current instruction is a line/1 instruction, pick up the
+ * location from that instruction. Otherwise use NIL. */
func_start->a[1].type = TAG_n;
if (op->op == genop_line_1) {
func_start->a[1] = op->a[0];
@@ -1549,45 +1766,46 @@ int beamcodereader_next(BeamCodeReader *code_reader, BeamOp **out) {
op = next;
}
- /*
- * Pick up the MFA from the func_info/3 instruction.
- */
+ /* Pick up the MFA from the func_info/3 instruction. */
ASSERT(op->op == genop_func_info_3);
func_start->a[2] = op->a[0];
func_start->a[3] = op->a[1];
func_start->a[4] = op->a[2];
beamopallocator_free_op(code_reader->allocator, op);
- /*
- * Put the int_func_start/5 instruction into the pending
- * queue.
- */
+ /* Put the int_func_start/5 instruction into the pending queue,
+ * and link the entry label after it. */
code_reader->pending = func_start;
- op = func_start;
-
- /*
- * Unless this is the first function in the module,
- * synthesize an int_func_end/0 instruction and prepend
- * it to the pending queue.
- */
- if (code_reader->first) {
- code_reader->first = 0;
- } else {
- BeamOp *func_end;
- func_end = beamopallocator_new_op(code_reader->allocator);
- func_end->op = genop_int_func_end_0;
- func_end->arity = 0;
- func_end->next = code_reader->pending;
- code_reader->pending = func_end;
+ func_start->next = entry_op;
+
+ /* Unless this is the first function in the module, synthesize an
+ * int_func_end/2 instruction and prepend it to the pending
+ * queue. */
+ if (!code_reader->first) {
+ synthesize_func_end(code_reader);
}
+
+ code_reader->current_func_label = func_label;
+ code_reader->current_entry_label = entry_label;
+ code_reader->first = 0;
+ }
+
+ /* At this point, there is at least one instruction in the pending
+ * queue, and the op variable points to the last instruction in the
+ * queue. */
+ return beamcodereader_next(code_reader, out);
+ case genop_int_code_end_0:
+ code_reader->pending = op;
+
+ if (!code_reader->first) {
+ synthesize_func_end(code_reader);
}
- /*
- * At this point, there is at least one instruction in the pending
- * queue. The op variable points to the last instruction in the queue.
- */
op->next = NULL;
return beamcodereader_next(code_reader, out);
+ default:
+ *out = op;
+ return 1;
}
}
diff --git a/erts/emulator/beam/beam_file.h b/erts/emulator/beam/beam_file.h
index fe68447b8e..7c73ae1e37 100644
--- a/erts/emulator/beam/beam_file.h
+++ b/erts/emulator/beam/beam_file.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include "sys.h"
#include "atom.h"
+#include "beam_types.h"
#define CHECKSUM_SIZE 16
@@ -54,10 +55,6 @@ int iff_init(const byte *data, size_t size, IFF_File *iff);
int iff_read_chunk(IFF_File *iff, Uint id, IFF_Chunk *chunk);
typedef struct {
- /* The encoding that was used to create this table. This is only used for
- * version tests. */
- ErtsAtomEncoding encoding;
-
Sint32 count;
Eterm *entries;
} BeamFile_AtomTable;
@@ -120,7 +117,7 @@ typedef struct {
Sint32 flags;
Sint32 name_count;
- Eterm *names;
+ Sint *names;
Sint32 location_size;
Sint32 item_count;
@@ -141,6 +138,14 @@ typedef struct {
} BeamFile_LiteralTable;
typedef struct {
+ /* To simplify code that queries types, the first entry (which must be
+ * present) is always the "any type." */
+ Sint32 count;
+ char fallback; /* If this is a fallback type table */
+ BeamType *entries;
+} BeamFile_TypeTable;
+
+typedef struct {
IFF_File iff;
Eterm module;
@@ -150,8 +155,12 @@ typedef struct {
BeamFile_AtomTable atoms;
BeamFile_ImportTable imports;
BeamFile_ExportTable exports;
+#ifdef BEAMASM
+ BeamFile_ExportTable locals;
+#endif
BeamFile_LambdaTable lambdas;
BeamFile_LineTable lines;
+ BeamFile_TypeTable types;
/* Static literals are those defined in the file, and dynamic literals are
* those created when loading. The former is positively indexed starting
@@ -178,6 +187,7 @@ enum beamfile_read_result {
/* Mandatory chunks */
BEAMFILE_READ_MISSING_ATOM_TABLE,
+ BEAMFILE_READ_OBSOLETE_ATOM_TABLE,
BEAMFILE_READ_CORRUPT_ATOM_TABLE,
BEAMFILE_READ_MISSING_CODE_CHUNK,
BEAMFILE_READ_CORRUPT_CODE_CHUNK,
@@ -185,17 +195,19 @@ enum beamfile_read_result {
BEAMFILE_READ_CORRUPT_EXPORT_TABLE,
BEAMFILE_READ_MISSING_IMPORT_TABLE,
BEAMFILE_READ_CORRUPT_IMPORT_TABLE,
+ BEAMFILE_READ_CORRUPT_LOCALS_TABLE,
/* Optional chunks */
BEAMFILE_READ_CORRUPT_LAMBDA_TABLE,
BEAMFILE_READ_CORRUPT_LINE_TABLE,
- BEAMFILE_READ_CORRUPT_LITERAL_TABLE
+ BEAMFILE_READ_CORRUPT_LITERAL_TABLE,
+ BEAMFILE_READ_CORRUPT_TYPE_TABLE
};
typedef struct {
/* TAG_xyz */
- int type;
- BeamInstr val;
+ UWord type;
+ UWord val;
} BeamOpArg;
typedef struct beamop {
@@ -230,6 +242,8 @@ typedef struct {
#include "erl_process.h"
#include "erl_message.h"
+void beamfile_init(void);
+
/** @brief Reads the given module binary into \p beam and validates its
* structural integrity. */
enum beamfile_read_result
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 063b740c08..85beba57ee 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,8 @@ Uint erts_total_code_size;
static int load_code(LoaderState *stp);
+#define PLEASE_RECOMPILE "please re-compile this module with an Erlang/OTP " ERLANG_OTP_RELEASE " compiler"
+
/**********************************************************************/
void init_load(void)
@@ -54,6 +56,20 @@ void init_load(void)
erts_total_code_size = 0;
beam_catches_init();
erts_init_ranges();
+
+#ifdef DEBUG
+ {
+ int i;
+
+ for (i = 1; i < NUM_GENERIC_OPS; i++) {
+ const GenOpEntry *op = &gen_opc[i];
+
+ ASSERT(op->name && op->name[0] != '\0');
+ ASSERT(op->arity <= ERTS_BEAM_MAX_OPARGS);
+ ASSERT(op->num_specific <= 1 || op->arity <= 6);
+ }
+ }
+#endif
}
Binary *erts_alloc_loader_state(void) {
@@ -128,6 +144,8 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
BeamLoadError0(stp, "corrupt file header");
case BEAMFILE_READ_MISSING_ATOM_TABLE:
BeamLoadError0(stp, "missing atom table");
+ case BEAMFILE_READ_OBSOLETE_ATOM_TABLE:
+ BeamLoadError0(stp, PLEASE_RECOMPILE);
case BEAMFILE_READ_CORRUPT_ATOM_TABLE:
BeamLoadError0(stp, "corrupt atom table");
case BEAMFILE_READ_MISSING_CODE_CHUNK:
@@ -148,6 +166,10 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
BeamLoadError0(stp, "corrupt line table");
case BEAMFILE_READ_CORRUPT_LITERAL_TABLE:
BeamLoadError0(stp, "corrupt literal table");
+ case BEAMFILE_READ_CORRUPT_LOCALS_TABLE:
+ BeamLoadError0(stp, "corrupt locals table");
+ case BEAMFILE_READ_CORRUPT_TYPE_TABLE:
+ BeamLoadError0(stp, "corrupt type table");
case BEAMFILE_READ_SUCCESS:
break;
}
@@ -161,16 +183,13 @@ erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
if (stp->beam.code.max_opcode > MAX_GENERIC_OPCODE) {
BeamLoadError2(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"
+ " of the runtime system than the current (Erlang/OTP " ERLANG_OTP_RELEASE ").\n"
+ " To fix this, " PLEASE_RECOMPILE ".\n"
" (Use of opcode %d; this emulator supports "
"only up to %d.)",
stp->beam.code.max_opcode, MAX_GENERIC_OPCODE);
}
- stp->otp_20_or_higher = (stp->beam.atoms.encoding == ERTS_ATOM_ENC_UTF8);
-
if (!load_code(stp)) {
goto load_error;
}
@@ -233,7 +252,7 @@ erts_finish_loading(Binary* magic, Process* c_p,
erts_clear_export_break(mod_tab_p, ep);
- ep->addresses[code_ix] =
+ ep->dispatch.addresses[code_ix] =
(ErtsCodePtr)ep->trampoline.breakpoint.address;
ep->trampoline.breakpoint.address = 0;
@@ -369,10 +388,12 @@ static int load_code(LoaderState* stp)
int num_specific;
- beam_load_prepare_emit(stp);
-
op_reader = beamfile_get_code(&stp->beam, &stp->op_allocator);
+ if (!beam_load_prepare_emit(stp)) {
+ goto load_error;
+ }
+
for (;;) {
get_next_instr:
if (!beamcodereader_next(op_reader, &last_op)) {
@@ -452,14 +473,10 @@ static int load_code(LoaderState* stp)
* the possible specific instructions associated with this
* specific instruction.
*/
- Uint32 mask[3] = {0, 0, 0};
-
int specific, arity, arg, i;
+ Uint32 mask[3] = {0, 0, 0};
arity = gen_opc[tmp_op->op].arity;
- if (arity > 6) {
- BeamLoadError0(stp, "no specific operation found (arity > 6)");
- }
for (arg = 0; arg < arity; arg++) {
int type = tmp_op->a[arg].type;
@@ -523,25 +540,15 @@ static int load_code(LoaderState* stp)
/*
* No specific operation found.
*/
- if (i == num_specific) {
+ if (ERTS_UNLIKELY(i == num_specific)) {
stp->specific_op = -1;
- for (arg = 0; arg < tmp_op->arity; arg++) {
- /*
- * We'll give the error message here (instead of earlier)
- * to get a printout of the offending operation.
- */
- if (tmp_op->a[arg].type == TAG_h) {
- BeamLoadError0(stp, "the character data type is not supported");
- }
- }
/*
* No specific operations and no transformations means that
* the instruction is obsolete.
*/
if (num_specific == 0 && gen_opc[tmp_op->op].transform == -1) {
- BeamLoadError0(stp, "please re-compile this module with an "
- ERLANG_OTP_RELEASE " compiler ");
+ BeamLoadError0(stp, PLEASE_RECOMPILE);
}
/*
@@ -550,8 +557,7 @@ static int load_code(LoaderState* stp)
*/
switch (stp->genop->op) {
case genop_too_old_compiler_0:
- BeamLoadError0(stp, "please re-compile this module with an "
- ERLANG_OTP_RELEASE " compiler");
+ BeamLoadError0(stp, PLEASE_RECOMPILE);
case genop_unsupported_guard_bif_3:
{
Eterm Mod = (Eterm) stp->genop->a[0].val;
@@ -626,7 +632,12 @@ erts_release_literal_area(ErtsLiteralArea* literal_area)
}
case FUN_SUBTAG:
{
- ErlFunEntry* fe = ((ErlFunThing*)oh)->fe;
+ /* We _KNOW_ that this is a local fun, otherwise it would not
+ * be part of the off-heap list. */
+ ErlFunEntry* fe = ((ErlFunThing*)oh)->entry.fun;
+
+ ASSERT(is_local_fun((ErlFunThing*)oh));
+
if (erts_refc_dectest(&fe->refc, 0) == 0) {
erts_erase_fun_entry(fe);
}
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index fe3aeb44ad..0afdace2d3 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -56,7 +56,7 @@ typedef struct LoaderState_ LoaderState;
int beam_load_prepared_dtor(Binary *magic);
void beam_load_prepared_free(Binary *magic);
-void beam_load_prepare_emit(LoaderState *stp);
+int beam_load_prepare_emit(LoaderState *stp);
int beam_load_emit_op(LoaderState *stp, BeamOp *op);
int beam_load_finish_emit(LoaderState *stp);
diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c
index 22ae1ab817..56cc106c54 100644
--- a/erts/emulator/beam/beam_ranges.c
+++ b/erts/emulator/beam/beam_ranges.c
@@ -346,7 +346,6 @@ lookup_loc(FunctionInfo* fi, const void* pc,
if (pc < mid[0]) {
high = mid;
} else if (pc < mid[1]) {
- int file;
int index = mid - lt->func_tab[0];
if (lt->loc_size == 2) {
@@ -359,14 +358,6 @@ lookup_loc(FunctionInfo* fi, const void* pc,
return;
}
fi->needed += 3+2+3+2;
- file = LOC_FILE(fi->loc);
- if (file == 0) {
- /* Special case: Module name with ".erl" appended */
- Atom* mod_atom = atom_tab(atom_val(fi->mfa->module));
- fi->needed += 2*(mod_atom->len+4);
- } else {
- fi->needed += 2*erts_atom_to_string_length((fi->fname_ptr)[file-1]);
- }
return;
} else {
low = mid + 1;
diff --git a/erts/emulator/beam/beam_transform_engine.c b/erts/emulator/beam/beam_transform_engine.c
index 497d1e81b2..3ce934a48c 100644
--- a/erts/emulator/beam/beam_transform_engine.c
+++ b/erts/emulator/beam/beam_transform_engine.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -128,20 +128,6 @@ erts_transform_engine(LoaderState* st)
ap++;
break;
#endif
- case TOP_is_same_var:
- ASSERT(ap < instr->arity);
- i = *pc++;
- ASSERT(i < TE_MAX_VARS);
- if (var[i].type != instr->a[ap].type)
- goto restart;
- switch (var[i].type) {
- case TAG_n:
- break;
- default:
- if (var[i].val != instr->a[ap].val)
- goto restart;
- }
- break;
#if defined(TOP_is_bif)
case TOP_is_bif:
{
diff --git a/erts/emulator/beam/beam_types.c b/erts/emulator/beam/beam_types.c
new file mode 100644
index 0000000000..f0b8c8a6dc
--- /dev/null
+++ b/erts/emulator/beam/beam_types.c
@@ -0,0 +1,63 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "beam_types.h"
+
+#include "global.h"
+#include "erl_message.h"
+#include "external.h"
+
+static Sint64 get_sint64(const byte *data);
+
+int beam_types_decode(const byte *data, Uint size, BeamType *out) {
+ int types;
+
+ if (size != 18) {
+ return 0;
+ }
+
+ types = (Uint16)data[0] << 8 | (Uint16)data[1];
+ if (types == BEAM_TYPE_NONE) {
+ return 0;
+ }
+
+ out->type_union = types;
+
+ data += 2;
+ out->min = get_sint64(data);
+ data += 8;
+ out->max = get_sint64(data);
+
+ return 1;
+}
+
+static Sint64 get_sint64(const byte *data) {
+ Sint64 value = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ value = value << 8 | (Sint16)data[i];
+ }
+ return value;
+}
diff --git a/erts/emulator/beam/beam_types.h b/erts/emulator/beam/beam_types.h
new file mode 100644
index 0000000000..000a644edb
--- /dev/null
+++ b/erts/emulator/beam/beam_types.h
@@ -0,0 +1,101 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/**
+ * @description Basic type representation for BEAM instruction operands.
+ * @file beam_types.h
+ *
+ * While the compiler is good eliminating redundant type tests and simplifying
+ * instructions, we're limited by the available instructions and it's not
+ * always worthwhile to add new variants.
+ *
+ * The idea behind this module is to allow minor optimizations _inside_
+ * instructions based on what we know about their operand types. For example,
+ * when we know that the source passed to `is_tagged_tuple` is always boxed, we
+ * can skip the boxed check.
+ */
+
+#ifndef _BEAM_TYPES_H
+#define _BEAM_TYPES_H
+
+#include "sys.h"
+
+#define BEAM_TYPES_VERSION 1
+
+#define BEAM_TYPE_NONE (0)
+
+#define BEAM_TYPE_ATOM (1 << 0)
+#define BEAM_TYPE_BITSTRING (1 << 1)
+#define BEAM_TYPE_BS_MATCHSTATE (1 << 2)
+#define BEAM_TYPE_CONS (1 << 3)
+#define BEAM_TYPE_FLOAT (1 << 4)
+#define BEAM_TYPE_FUN (1 << 5)
+#define BEAM_TYPE_INTEGER (1 << 6)
+#define BEAM_TYPE_MAP (1 << 7)
+#define BEAM_TYPE_NIL (1 << 8)
+#define BEAM_TYPE_PID (1 << 9)
+#define BEAM_TYPE_PORT (1 << 10)
+#define BEAM_TYPE_REFERENCE (1 << 11)
+#define BEAM_TYPE_TUPLE (1 << 12)
+
+#define BEAM_TYPE_ANY ((1 << 13) - 1)
+
+#define BEAM_TYPE_MASK_BOXED \
+ (BEAM_TYPE_BITSTRING | \
+ BEAM_TYPE_BS_MATCHSTATE | \
+ BEAM_TYPE_FLOAT | \
+ BEAM_TYPE_FUN | \
+ BEAM_TYPE_INTEGER | \
+ BEAM_TYPE_MAP | \
+ BEAM_TYPE_PID | \
+ BEAM_TYPE_PORT | \
+ BEAM_TYPE_REFERENCE | \
+ BEAM_TYPE_TUPLE)
+
+#define BEAM_TYPE_MASK_IMMEDIATE \
+ (BEAM_TYPE_ATOM | \
+ BEAM_TYPE_INTEGER | \
+ BEAM_TYPE_NIL | \
+ BEAM_TYPE_PID | \
+ BEAM_TYPE_PORT)
+
+#define BEAM_TYPE_MASK_CELL \
+ (BEAM_TYPE_CONS)
+
+#define BEAM_TYPE_MASK_ALWAYS_IMMEDIATE \
+ (BEAM_TYPE_MASK_IMMEDIATE & ~(BEAM_TYPE_MASK_BOXED | BEAM_TYPE_MASK_CELL))
+#define BEAM_TYPE_MASK_ALWAYS_BOXED \
+ (BEAM_TYPE_MASK_BOXED & ~(BEAM_TYPE_MASK_CELL | BEAM_TYPE_MASK_IMMEDIATE))
+#define BEAM_TYPE_MASK_ALWAYS_CELL \
+ (BEAM_TYPE_MASK_CELL & ~(BEAM_TYPE_MASK_BOXED | BEAM_TYPE_MASK_IMMEDIATE))
+
+typedef struct {
+ /** @brief A set of the possible types (atom, tuple, etc) this term may
+ * be. When a single bit is set, the term will always be of that type. */
+ int type_union;
+
+ /** @brief Minimum and maximum values. Only valid if min <= max. */
+ Sint64 min;
+ Sint64 max;
+} BeamType;
+
+int beam_types_decode(const byte *data, Uint size, BeamType *out);
+
+#endif
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 34ace8c61b..c4687f04b8 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -45,7 +45,10 @@
#include "erl_map.h"
#include "erl_msacc.h"
#include "erl_proc_sig_queue.h"
+#include "erl_fun.h"
+#include "ryu.h"
#include "jit/beam_asm.h"
+#include "erl_global_literals.h"
#include "beam_load.h"
Export *erts_await_result;
@@ -129,8 +132,10 @@ BIF_RETTYPE link_1(BIF_ALIST_1)
rlnk = erts_link_internal_create(ERTS_LNK_TYPE_PROC, BIF_P->common.id);
- if (erts_proc_sig_send_link(BIF_P, BIF_ARG_1, rlnk))
+ if (erts_proc_sig_send_link(&BIF_P->common, BIF_P->common.id,
+ BIF_ARG_1, rlnk)) {
BIF_RET(am_true);
+ }
erts_link_tree_delete(&ERTS_P_LINKS(BIF_P), lnk);
erts_link_internal_release(lnk);
@@ -251,8 +256,7 @@ BIF_RETTYPE link_1(BIF_ALIST_1)
}
erts_link_set_dead_dist(&elnk->ld.dist, dep->sysname);
}
- erts_proc_sig_send_link_exit(NULL, THE_NON_VALUE, &elnk->ld.dist,
- am_noconnection, NIL);
+ erts_proc_sig_send_link_exit_noconnection(&elnk->ld.dist);
break;
case ERTS_DSIG_PREP_PENDING:
@@ -394,8 +398,16 @@ demonitor(Process *c_p, Eterm ref, Eterm *multip)
return am_true;
}
+ case ERTS_MON_TYPE_DIST_PORT: {
+ ASSERT(is_external_port(mon->other.item));
+ ASSERT(external_pid_dist_entry(mon->other.item)
+ == erts_this_dist_entry);
+ erts_monitor_release(mon);
+ return am_true;
+ }
+
case ERTS_MON_TYPE_PROC:
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(&c_p->common, c_p->common.id, 0, mon);
return am_true;
case ERTS_MON_TYPE_DIST_PROC: {
@@ -419,14 +431,12 @@ demonitor(Process *c_p, Eterm ref, Eterm *multip)
if (is_external_pid(to))
dep = external_pid_dist_entry(to);
- else {
- /* Monitoring a name at node to */
+ else /* Monitoring a name at node to */
dep = erts_sysname_to_connected_dist_entry(to);
- ASSERT(dep != erts_this_dist_entry);
- if (!dep) {
- erts_monitor_release(mon);
- return am_false;
- }
+
+ if (!dep || dep == erts_this_dist_entry) {
+ erts_monitor_release(mon);
+ return am_false;
}
code = erts_dsig_prepare(&ctx, dep, c_p, ERTS_PROC_LOCK_MAIN,
@@ -559,43 +569,6 @@ badarg:
BIF_ERROR(BIF_P, BADARG);
}
-/* Type must be atomic object! */
-void
-erts_queue_monitor_message(Process *p,
- ErtsProcLocks *p_locksp,
- Eterm ref,
- Eterm type,
- Eterm item,
- Eterm reason)
-{
- Eterm tup;
- Eterm* hp;
- Eterm reason_copy, ref_copy, item_copy;
- Uint reason_size, ref_size, item_size, heap_size;
- ErlOffHeap *ohp;
- ErtsMessage *msgp;
-
- reason_size = IS_CONST(reason) ? 0 : size_object(reason);
- item_size = IS_CONST(item) ? 0 : size_object(item);
- ref_size = size_object(ref);
-
- heap_size = 6+reason_size+ref_size+item_size;
-
- msgp = erts_alloc_message_heap(p, p_locksp, heap_size,
- &hp, &ohp);
-
- reason_copy = (IS_CONST(reason)
- ? reason
- : copy_struct(reason, reason_size, &hp, ohp));
- item_copy = (IS_CONST(item)
- ? item
- : copy_struct(item, item_size, &hp, ohp));
- 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, msgp, tup, am_system);
-}
-
Uint16
erts_monitor_opts(Eterm opts, Eterm *tag)
{
@@ -649,7 +622,6 @@ erts_monitor_opts(Eterm opts, Eterm *tag)
static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
Uint16 add_oflags, Eterm tag)
{
- Eterm tmp_heap[3];
Eterm ref, id, name;
ErtsMonitorData *mdp;
BIF_RETTYPE ret_val;
@@ -677,9 +649,13 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
mdp->origin.flags |= add_oflags;
erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p),
&mdp->origin);
- if (!erts_proc_sig_send_monitor(&mdp->u.target, id))
- erts_proc_sig_send_monitor_down(&mdp->u.target,
+ if (is_not_internal_pid(id)
+ || !erts_proc_sig_send_monitor(&c_p->common, c_p->common.id,
+ &mdp->u.target, id)) {
+ erts_proc_sig_send_monitor_down(NULL, id,
+ &mdp->u.target,
am_noproc);
+ }
}
goto done;
@@ -689,11 +665,7 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
local_named_process:
name = target;
id = erts_whereis_name_to_id(c_p, target);
- if (is_internal_pid(id))
- goto local_process;
- target = TUPLE2(&tmp_heap[0], name,
- erts_this_dist_entry->sysname);
- goto noproc;
+ goto local_process;
}
if (is_external_pid(target)) {
@@ -701,8 +673,16 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
int code;
dep = external_pid_dist_entry(target);
- if (dep == erts_this_dist_entry)
- goto noproc;
+ if (dep == erts_this_dist_entry) {
+ mdp = erts_monitor_create(ERTS_MON_TYPE_DIST_PROC, ref,
+ c_p->common.id, target,
+ NIL, tag);
+ mdp->origin.flags |= add_oflags;
+ erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p), &mdp->origin);
+ erts_proc_sig_send_monitor_down(NULL, target,
+ &mdp->u.target, am_noproc);
+ goto done;
+ }
id = target;
name = NIL;
@@ -722,7 +702,9 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
case ERTS_DSIG_PREP_NOT_ALIVE:
case ERTS_DSIG_PREP_NOT_CONNECTED:
erts_monitor_set_dead_dist(&mdp->u.target, dep->sysname);
- erts_proc_sig_send_monitor_down(&mdp->u.target, am_noconnection);
+ erts_proc_sig_send_monitor_down(NULL, id,
+ &mdp->u.target,
+ am_noconnection);
code = ERTS_DSIG_SEND_OK;
break;
@@ -756,7 +738,7 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
goto badarg;
if (is_not_atom(tpl[1]) || is_not_atom(tpl[2]))
goto badarg;
- if (!erts_is_alive && tpl[2] != am_Noname)
+ if (tpl[2] != am_Noname && !erts_is_this_node_alive())
goto badarg;
target = tpl[1];
dep = erts_find_or_insert_dist_entry(tpl[2]);
@@ -786,8 +768,10 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
mdp->origin.flags |= add_oflags;
erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p), &mdp->origin);
prt = erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
- if (!prt || erts_port_monitor(c_p, prt, &mdp->u.target) == ERTS_PORT_OP_DROPPED)
- erts_proc_sig_send_monitor_down(&mdp->u.target, am_noproc);
+ if (!prt || erts_port_monitor(c_p, prt, &mdp->u.target) == ERTS_PORT_OP_DROPPED) {
+ erts_proc_sig_send_monitor_down(prt ? &prt->common : NULL, id,
+ &mdp->u.target, am_noproc);
+ }
goto done;
}
@@ -795,16 +779,19 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
local_named_port:
name = target;
id = erts_whereis_name_to_id(c_p, target);
- if (is_internal_port(id))
- goto local_port;
- target = TUPLE2(&tmp_heap[0], name,
- erts_this_dist_entry->sysname);
- goto noproc;
+ goto local_port;
}
if (is_external_port(target)) {
- if (erts_this_dist_entry == external_port_dist_entry(target))
- goto noproc;
+ if (erts_this_dist_entry == external_port_dist_entry(target)) {
+ mdp = erts_monitor_create(ERTS_MON_TYPE_DIST_PORT, ref,
+ c_p->common.id, target,
+ NIL, tag);
+ mdp->origin.flags |= add_oflags;
+ erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p), &mdp->origin);
+ erts_proc_sig_send_monitor_down(NULL, target, &mdp->u.target, am_noproc);
+ goto done;
+ }
goto badarg;
}
@@ -843,23 +830,6 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
badarg:
ERTS_BIF_PREP_ERROR(ret_val, c_p, BADARG);
-
- if (0) {
- ErtsProcLocks locks;
-noproc:
- locks = ERTS_PROC_LOCK_MAIN;
-
- erts_queue_monitor_message(c_p,
- &locks,
- ref,
- type,
- target,
- am_noproc);
- if (locks != ERTS_PROC_LOCK_MAIN)
- erts_proc_unlock(c_p, locks & ~ERTS_PROC_LOCK_MAIN);
-
- ERTS_BIF_PREP_RET(ret_val, ref);
- }
done:
@@ -1102,7 +1072,7 @@ BIF_RETTYPE unlink_1(BIF_ALIST_1)
ilnk = (ErtsILink *) erts_link_tree_lookup(ERTS_P_LINKS(BIF_P),
BIF_ARG_1);
if (ilnk && !ilnk->unlinking) {
- Uint64 id = erts_proc_sig_send_unlink(BIF_P,
+ Uint64 id = erts_proc_sig_send_unlink(&BIF_P->common,
BIF_P->common.id,
&ilnk->link);
if (id)
@@ -1135,7 +1105,8 @@ BIF_RETTYPE unlink_1(BIF_ALIST_1)
else {
ErtsSigUnlinkOp *sulnk;
- sulnk = erts_proc_sig_make_unlink_op(BIF_P, BIF_P->common.id);
+ sulnk = erts_proc_sig_make_unlink_op(&BIF_P->common,
+ BIF_P->common.id);
ilnk->unlinking = sulnk->id;
#ifdef DEBUG
ref = NIL;
@@ -1173,7 +1144,7 @@ BIF_RETTYPE unlink_1(BIF_ALIST_1)
if (elnk->unlinking)
BIF_RET(am_true);
- unlink_id = erts_proc_sig_new_unlink_id(BIF_P);
+ unlink_id = erts_proc_sig_new_unlink_id(&BIF_P->common);
elnk->unlinking = unlink_id;
code = erts_dsig_prepare(&ctx, dep, BIF_P, ERTS_PROC_LOCK_MAIN,
@@ -1314,7 +1285,7 @@ BIF_RETTYPE error_3(BIF_ALIST_3)
/**********************************************************************/
/*
* This is like exactly like error/1. The only difference is
- * that Dialyzer thinks that it it will return an arbitrary term.
+ * that Dialyzer thinks that it will return an arbitrary term.
* It is useful in stub functions for NIFs.
*/
@@ -1327,7 +1298,7 @@ BIF_RETTYPE nif_error_1(BIF_ALIST_1)
/**********************************************************************/
/*
* This is like exactly like error/2. The only difference is
- * that Dialyzer thinks that it it will return an arbitrary term.
+ * that Dialyzer thinks that it will return an arbitrary term.
* It is useful in stub functions for NIFs.
*/
@@ -1397,7 +1368,7 @@ BIF_RETTYPE raise_3(BIF_ALIST_3)
switch (arityval(tp[0])) {
case 2:
/* {Fun,Args} */
- if (is_fun(tp[1])) {
+ if (is_any_fun(tp[1])) {
must_copy = 1;
} else {
goto error;
@@ -1409,7 +1380,7 @@ BIF_RETTYPE raise_3(BIF_ALIST_3)
* {Fun,Args,Location}
* {M,F,A}
*/
- if (is_fun(tp[1])) {
+ if (is_any_fun(tp[1])) {
location = tp[3];
} else if (is_atom(tp[1]) && is_atom(tp[2])) {
must_copy = 1;
@@ -1512,7 +1483,7 @@ erts_internal_await_exit_trap(BIF_ALIST_0)
* terminated in order to ensure that signal order
* is preserved. Yield if necessary.
*/
- erts_aint32_t state;
+ erts_aint32_t state = erts_atomic32_read_nob(&BIF_P->state);
int reds = ERTS_BIF_REDS_LEFT(BIF_P);
(void) erts_proc_sig_handle_incoming(BIF_P, &state, &reds,
reds, !0);
@@ -1547,7 +1518,7 @@ static BIF_RETTYPE send_exit_signal_bif(Process *c_p, Eterm id, Eterm reason, in
&& c_p->common.id == id
&& (reason == am_kill
|| !(c_p->flags & F_TRAP_EXIT)));
- erts_proc_sig_send_exit(c_p, c_p->common.id, id,
+ erts_proc_sig_send_exit(&c_p->common, c_p->common.id, id,
reason, NIL, exit2_suicide);
if (!exit2_suicide)
ERTS_BIF_PREP_RET(ret_val, am_true);
@@ -1806,7 +1777,21 @@ static Eterm process_flag_aux(Process *c_p, int *redsp, Eterm flag, Eterm val)
BIF_RETTYPE process_flag_2(BIF_ALIST_2)
{
Eterm old_value;
- if (BIF_ARG_1 == am_error_handler) {
+
+ if (BIF_ARG_1 == am_async_dist) {
+ old_value = (BIF_P->flags & F_ASYNC_DIST) ? am_true : am_false;
+ if (BIF_ARG_2 == am_false) {
+ BIF_P->flags &= ~F_ASYNC_DIST;
+ }
+ else if (BIF_ARG_2 == am_true) {
+ BIF_P->flags |= F_ASYNC_DIST;
+ }
+ else {
+ goto error;
+ }
+ BIF_RET(old_value);
+ }
+ else if (BIF_ARG_1 == am_error_handler) {
if (is_not_atom(BIF_ARG_2)) {
goto error;
}
@@ -2647,7 +2632,7 @@ done:
/**********************************************************************/
-/* returns the head of a list - this function is unecessary
+/* returns the head of a list - this function is unnecessary
and is only here to keep Robert happy (Even more, since it's OP as well) */
BIF_RETTYPE hd_1(BIF_ALIST_1)
{
@@ -2988,6 +2973,9 @@ BIF_RETTYPE make_tuple_2(BIF_ALIST_2)
if (is_not_small(BIF_ARG_1) || (n = signed_val(BIF_ARG_1)) < 0 || n > ERTS_MAX_TUPLE_SIZE) {
BIF_ERROR(BIF_P, BADARG);
}
+ if (n == 0) {
+ return ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ }
hp = HAlloc(BIF_P, n+1);
res = make_tuple(hp);
*hp++ = make_arityval(n);
@@ -3004,17 +2992,21 @@ BIF_RETTYPE make_tuple_3(BIF_ALIST_3)
Eterm* hp;
Eterm res;
Eterm list = BIF_ARG_3;
- Eterm* tup;
+ Eterm* tup = NULL;
if (is_not_small(BIF_ARG_1) || (n = signed_val(BIF_ARG_1)) < 0 || n > ERTS_MAX_TUPLE_SIZE) {
error:
BIF_ERROR(BIF_P, BADARG);
}
limit = (Uint) n;
- hp = HAlloc(BIF_P, n+1);
- res = make_tuple(hp);
- *hp++ = make_arityval(n);
- tup = hp;
+ if (n == 0) {
+ res = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ hp = HAlloc(BIF_P, n+1);
+ res = make_tuple(hp);
+ *hp++ = make_arityval(n);
+ tup = hp;
+ }
while (n--) {
*hp++ = BIF_ARG_2;
}
@@ -3131,6 +3123,10 @@ BIF_RETTYPE delete_element_2(BIF_ALIST_3)
BIF_ERROR(BIF_P, BADARG);
}
+ if (arity == 1) {
+ return ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ }
+
hp = HAlloc(BIF_P, arity + 1 - 1);
res = make_tuple(hp);
*hp = make_arityval(arity - 1);
@@ -3153,7 +3149,7 @@ BIF_RETTYPE atom_to_list_1(BIF_ALIST_1)
{
Atom* ap;
Uint num_chars, num_built, num_eaten;
- byte* err_pos;
+ const byte* err_pos;
Eterm res;
int ares;
@@ -3361,6 +3357,9 @@ BIF_RETTYPE string_list_to_integer_1(BIF_ALIST_1)
case LTI_NO_INTEGER:
hp = HAlloc(BIF_P,3);
BIF_RET(TUPLE2(hp, am_error, am_no_integer));
+ case LTI_SYSTEM_LIMIT:
+ hp = HAlloc(BIF_P,3);
+ BIF_RET(TUPLE2(hp, am_error, am_system_limit));
default:
hp = HAlloc(BIF_P,3);
BIF_RET(TUPLE2(hp, res, tail));
@@ -3369,25 +3368,27 @@ BIF_RETTYPE string_list_to_integer_1(BIF_ALIST_1)
BIF_RETTYPE list_to_integer_1(BIF_ALIST_1)
{
- /* Using erts_list_to_integer is about twice as fast as using
- erts_chars_to_integer because we do not have to copy the
- entire list */
+ /* Using erts_list_to_integer() is about twice as fast as using
+ * erts_chars_to_integer() because we do not have to copy the
+ * entire list. */
Eterm res;
Eterm dummy;
/* must be a list */
- if (erts_list_to_integer(BIF_P, BIF_ARG_1, 10,
- &res, &dummy) != LTI_ALL_INTEGER) {
- BIF_ERROR(BIF_P,BADARG);
+ switch (erts_list_to_integer(BIF_P, BIF_ARG_1, 10, &res, &dummy)) {
+ case LTI_ALL_INTEGER:
+ BIF_RET(res);
+ case LTI_SYSTEM_LIMIT:
+ BIF_ERROR(BIF_P, SYSTEM_LIMIT);
+ default:
+ BIF_ERROR(BIF_P, BADARG);
}
- BIF_RET(res);
}
BIF_RETTYPE list_to_integer_2(BIF_ALIST_2)
{
- /* Bif implementation is about 50% faster than pure erlang,
- and since we have erts_chars_to_integer now it is simpler
- as well. This could be optmized further if we did not have to
- copy the list to buf. */
+ /* The BIF implementation is about 50% faster than pure Erlang,
+ * and since we now have erts_list_to_integer() it is simpler as
+ * well. */
Sint i;
Eterm res, dummy;
int base;
@@ -3403,11 +3404,14 @@ BIF_RETTYPE list_to_integer_2(BIF_ALIST_2)
BIF_ERROR(BIF_P, BADARG);
}
- if (erts_list_to_integer(BIF_P, BIF_ARG_1, base,
- &res, &dummy) != LTI_ALL_INTEGER) {
- BIF_ERROR(BIF_P,BADARG);
+ switch (erts_list_to_integer(BIF_P, BIF_ARG_1, base, &res, &dummy)) {
+ case LTI_ALL_INTEGER:
+ BIF_RET(res);
+ case LTI_SYSTEM_LIMIT:
+ BIF_ERROR(BIF_P, SYSTEM_LIMIT);
+ default:
+ BIF_ERROR(BIF_P, BADARG);
}
- BIF_RET(res);
}
/**********************************************************************/
@@ -3420,6 +3424,7 @@ static int do_float_to_charbuf(Process *p, Eterm efloat, Eterm list,
int compact = 0;
enum fmt_type_ {
FMT_LEGACY,
+ FMT_SHORT,
FMT_FIXED,
FMT_SCIENTIFIC
} fmt_type = FMT_LEGACY;
@@ -3448,16 +3453,26 @@ static int do_float_to_charbuf(Process *p, Eterm efloat, Eterm list,
continue;
}
}
+ } else if (arg == am_short) {
+ fmt_type = FMT_SHORT;
+ continue;
}
goto badarg;
}
+
if (is_not_nil(list)) {
goto badarg;
}
GET_DOUBLE(efloat, f);
- if (fmt_type == FMT_FIXED) {
+ if (fmt_type == FMT_SHORT) {
+ const int index = d2s_buffered_n(f.fd, fbuf);
+
+ /* Terminate the string. */
+ fbuf[index] = '\0';
+ return index;
+ } else if (fmt_type == FMT_FIXED) {
return sys_double_to_chars_fast(f.fd, fbuf, sizeof_fbuf,
decimals, compact);
} else {
@@ -3836,7 +3851,9 @@ BIF_RETTYPE list_to_tuple_1(BIF_ALIST_1)
if ((len = erts_list_length(list)) < 0 || len > ERTS_MAX_TUPLE_SIZE) {
BIF_ERROR(BIF_P, BADARG);
}
-
+ if (len == 0) {
+ BIF_RET(ERTS_GLOBAL_LIT_EMPTY_TUPLE);
+ }
hp = HAlloc(BIF_P, len+1);
res = make_tuple(hp);
*hp++ = make_arityval(len);
@@ -4372,21 +4389,28 @@ BIF_RETTYPE ref_to_list_1(BIF_ALIST_1)
BIF_RETTYPE make_fun_3(BIF_ALIST_3)
{
- Eterm* hp;
+ ErlFunThing *funp;
+ Eterm *hp;
+ Export *ep;
Sint arity;
- if (is_not_atom(BIF_ARG_1) || is_not_atom(BIF_ARG_2) || is_not_small(BIF_ARG_3)) {
- error:
- BIF_ERROR(BIF_P, BADARG);
+ if (is_not_atom(BIF_ARG_1) ||
+ is_not_atom(BIF_ARG_2) ||
+ is_not_small(BIF_ARG_3)) {
+ BIF_ERROR(BIF_P, BADARG);
}
+
arity = signed_val(BIF_ARG_3);
- if (arity < 0) {
- goto error;
+ if (arity < 0 || arity > MAX_ARG) {
+ BIF_ERROR(BIF_P, BADARG);
}
- hp = HAlloc(BIF_P, 2);
- hp[0] = HEADER_EXPORT;
- hp[1] = (Eterm) erts_export_get_or_make_stub(BIF_ARG_1, BIF_ARG_2, (Uint) arity);
- BIF_RET(make_export(hp));
+
+ hp = HAlloc(BIF_P, ERL_FUN_SIZE);
+
+ ep = erts_export_get_or_make_stub(BIF_ARG_1, BIF_ARG_2, (Uint) arity);
+ funp = erts_new_export_fun_thing(&hp, ep, arity);
+
+ BIF_RET(make_fun(funp));
}
BIF_RETTYPE fun_to_list_1(BIF_ALIST_1)
@@ -4394,8 +4418,10 @@ 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);
+ if (is_not_any_fun(fun)) {
+ BIF_ERROR(p, BADARG);
+ }
+
BIF_RET(term2list_dsprintf(p, fun));
}
@@ -4421,7 +4447,7 @@ BIF_RETTYPE port_to_list_1(BIF_ALIST_1)
/**********************************************************************/
-/* convert a list of ascii characeters of the form
+/* convert a list of ascii characters of the form
<node.number.serial> to a PID
*/
@@ -5350,45 +5376,52 @@ static BIF_RETTYPE bif_return_trap(BIF_ALIST_2)
}
static BIF_RETTYPE
-bif_handle_signals_return(BIF_ALIST_1)
+bif_handle_signals_return(BIF_ALIST_2)
{
- int local_only = BIF_P->sig_qs.flags & FS_LOCAL_SIGS_ONLY;
- int sres, sreds, reds_left;
+ int reds_left;
erts_aint32_t state;
- reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
- sreds = reds_left;
-
- if (!local_only) {
- erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MSGQ);
- erts_proc_sig_fetch(BIF_P);
- erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MSGQ);
+ if (BIF_P->sig_qs.flags & FS_FLUSHED_SIGS) {
+ flushed:
+ ASSERT(BIF_P->sig_qs.flags & FS_FLUSHING_SIGS);
+ BIF_P->sig_qs.flags &= ~(FS_FLUSHED_SIGS|FS_FLUSHING_SIGS);
+ erts_set_gc_state(BIF_P, !0); /* Allow GC again... */
+ BIF_RET(BIF_ARG_2);
}
+
+ if (!(BIF_P->sig_qs.flags & FS_FLUSHING_SIGS)) {
+ int flags = ((is_internal_pid(BIF_ARG_1)
+ || is_internal_port(BIF_ARG_1))
+ ? ERTS_PROC_SIG_FLUSH_FLG_FROM_ID
+ : ERTS_PROC_SIG_FLUSH_FLG_FROM_ALL);
+ erts_proc_sig_init_flush_signals(BIF_P, flags, BIF_ARG_1);
+ if (BIF_P->sig_qs.flags & FS_FLUSHED_SIGS)
+ goto flushed;
+ }
+
+ ASSERT(BIF_P->sig_qs.flags & FS_FLUSHING_SIGS);
- state = erts_atomic32_read_nob(&BIF_P->state);
- sres = erts_proc_sig_handle_incoming(BIF_P, &state, &sreds,
- sreds, !0);
-
- BUMP_REDS(BIF_P, (int) sreds);
- reds_left -= sreds;
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
- if (state & ERTS_PSFLG_EXITING) {
- BIF_P->sig_qs.flags &= ~FS_LOCAL_SIGS_ONLY;
- ERTS_BIF_EXITED(BIF_P);
- }
- if (!sres | (reds_left <= 0)) {
- /*
- * More signals to handle or out of reds; need
- * to yield and continue. Prevent fetching of
- * more signals by setting local-sigs-only flag.
- */
- BIF_P->sig_qs.flags |= FS_LOCAL_SIGS_ONLY;
- ERTS_BIF_YIELD1(&erts_bif_handle_signals_return_export,
- BIF_P, BIF_ARG_1);
- }
+ state = erts_atomic32_read_nob(&BIF_P->state);
+ do {
+ int sreds = reds_left;
+ (void) erts_proc_sig_handle_incoming(BIF_P, &state, &sreds,
+ sreds, !0);
+ BUMP_REDS(BIF_P, (int) sreds);
+ if (state & ERTS_PSFLG_EXITING)
+ ERTS_BIF_EXITED(BIF_P);
+ if (BIF_P->sig_qs.flags & FS_FLUSHED_SIGS)
+ goto flushed;
+ reds_left -= sreds;
+ } while (reds_left > 0);
- BIF_P->sig_qs.flags &= ~FS_LOCAL_SIGS_ONLY;
- BIF_RET(BIF_ARG_1);
+ /*
+ * More signals to handle, but out of reductions. Yield
+ * and come back here and continue...
+ */
+ ERTS_BIF_YIELD2(&erts_bif_handle_signals_return_export,
+ BIF_P, BIF_ARG_1, BIF_ARG_2);
}
Export bif_return_trap_export;
@@ -5406,11 +5439,10 @@ void erts_init_trap_export(Export *ep, Eterm m, Eterm f, Uint a,
}
#ifdef BEAMASM
- ep->addresses[ERTS_SAVE_CALLS_CODE_IX] = beam_save_calls;
+ ep->dispatch.addresses[ERTS_SAVE_CALLS_CODE_IX] = beam_save_calls;
#endif
ep->bif_number = -1;
- ep->info.op = op_i_func_info_IaaI;
ep->info.mfa.module = m;
ep->info.mfa.function = f;
ep->info.mfa.arity = a;
@@ -5430,7 +5462,7 @@ void erts_init_bif(void)
&bif_return_trap);
erts_init_trap_export(&erts_bif_handle_signals_return_export,
- am_erlang, am_bif_handle_signals_return, 1,
+ am_erlang, am_bif_handle_signals_return, 2,
&bif_handle_signals_return);
erts_await_result = erts_export_put(am_erts_internal,
@@ -5489,11 +5521,7 @@ schedule(Process *c_p, Process *dirty_shadow_proc,
ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(c_p));
(void) erts_nfunc_schedule(c_p, dirty_shadow_proc,
mfa, pc,
-#ifdef BEAMASM
- op_call_bif_W,
-#else
BeamOpCodeAddr(op_call_bif_W),
-#endif
dfunc, ifunc,
module, function,
argc, argv);
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index 0bbe059887..59370c498b 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -327,7 +327,7 @@ extern ErtsCodePtr beam_bif_export_trap;
#define ERTS_BIF_PREP_TRAP(Export, Proc, Arity) \
do { \
- (Proc)->i = (Export)->addresses[erts_active_code_ix()]; \
+ (Proc)->i = (Export)->dispatch.addresses[erts_active_code_ix()]; \
(Proc)->arity = (Arity); \
(Proc)->freason = TRAP; \
} while(0);
@@ -522,23 +522,23 @@ do { \
extern Export erts_bif_handle_signals_return_export;
-#define ERTS_BIF_HANDLE_SIGNALS_RETURN(P, VAL) \
- BIF_TRAP1(&erts_bif_handle_signals_return_export, (P), (VAL))
+#define ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(P, FROM, VAL) \
+ BIF_TRAP2(&erts_bif_handle_signals_return_export, (P), (FROM), (VAL))
-#define ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(Ret, P, Val) \
- ERTS_BIF_PREP_TRAP1((Ret), &erts_bif_handle_signals_return_export, \
- (P), (Val))
+#define ERTS_BIF_PREP_HANDLE_SIGNALS_FROM_RETURN(Ret, P, From, Val) \
+ ERTS_BIF_PREP_TRAP2((Ret), &erts_bif_handle_signals_return_export, \
+ (P), (From), (Val))
#define ERTS_BIF_PREP_EXITED(RET, PROC) \
do { \
KILL_CATCHES((PROC)); \
- ERTS_BIF_PREP_ERROR((RET), (PROC), EXTAG_EXIT); \
+ ERTS_BIF_PREP_ERROR((RET), (PROC), EXTAG_EXIT | EXF_PANIC); \
} while (0)
-#define ERTS_BIF_EXITED(PROC) \
-do { \
- KILL_CATCHES((PROC)); \
- BIF_ERROR((PROC), EXTAG_EXIT); \
+#define ERTS_BIF_EXITED(PROC) \
+do { \
+ KILL_CATCHES((PROC)); \
+ BIF_ERROR((PROC), EXTAG_EXIT | EXF_PANIC); \
} while (0)
#define ERTS_BIF_CHK_EXITED(PROC) \
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index cb3fb560ff..ebf815570c 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -83,7 +83,6 @@ bif erlang:phash2/1
bif erlang:phash2/2
ubif erlang:hd/1
bif erlang:integer_to_list/1
-bif erlang:is_alive/0
ubif erlang:length/1
bif erlang:link/1
bif erlang:list_to_atom/1
@@ -110,7 +109,9 @@ bif erlang:monitor_node/2
bif erlang:monitor_node/3
ubif erlang:node/1
ubif erlang:node/0
+bif erlang:nodes/0
bif erlang:nodes/1
+bif erlang:nodes/2
bif erlang:now/0
bif erlang:monotonic_time/0
bif erlang:monotonic_time/1
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 70ef50f9a2..8439a8c08f 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -608,7 +608,7 @@ static dsize_t Z_sub(ErtsDigit* y, dsize_t yl, ErtsDigit* r)
/*
** Multiply digits in x with digits in y and store in r
-** Assumption: digits in r must be 0 (upto the size of x)
+** Assumption: digits in r must be 0 (up to the size of x)
*/
static dsize_t I_mul(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDigit* r)
{
@@ -984,7 +984,7 @@ static ErtsDigit D_rem(ErtsDigit* x, dsize_t xl, ErtsDigit d)
/*
** Remainder of x and y
**
-** Assumtions: xl >= yl, yl > 1
+** Assumptions: xl >= yl, yl > 1
** r must contain at least xl number of digits
*/
static dsize_t I_rem(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDigit* r)
@@ -1483,6 +1483,18 @@ erts_make_integer(Uint x, Process *p)
return uint_to_big(x,hp);
}
}
+
+Eterm
+erts_make_integer_fact(Uint x, ErtsHeapFactory *hf)
+{
+ Eterm* hp;
+ if (IS_USMALL(0,x))
+ return make_small(x);
+ else {
+ hp = erts_produce_heap(hf, BIG_UINT_HEAP_SIZE, 0);
+ return uint_to_big(x, hp);
+ }
+}
/*
* As erts_make_integer, but from a whole UWord.
*/
@@ -2618,7 +2630,7 @@ int term_equals_2pow32(Eterm x)
if (!is_big(x))
return 0;
bp = big_val(x);
-#if D_EXP == 16 /* 16 bit platfrom not really supported!!! */
+#if D_EXP == 16 /* 16 bit platform not really supported!!! */
return (BIG_SIZE(bp) == 3) && !BIG_DIGIT(bp,0) && !BIG_DIGIT(bp,1) &&
BIG_DIGIT(bp,2) == 1;
#elif D_EXP == 32
@@ -2996,6 +3008,11 @@ LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list,
m = (lg2+D_EXP-1)/D_EXP; /* number of digits */
m = BIG_NEED_SIZE(m); /* number of words + thing */
+ if (m > BIG_ARITY_MAX) {
+ error_res = LTI_SYSTEM_LIMIT;
+ goto error;
+ }
+
hp = HAlloc(BIF_P, m);
hp_end = hp + m;
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index b2320f59ac..73505569b3 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -156,6 +156,7 @@ 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_fact(Uint, ErtsHeapFactory *);
Eterm erts_make_integer_from_uword(UWord x, Process *p);
dsize_t big_bytes(Eterm);
@@ -187,7 +188,8 @@ typedef enum {
LTI_BAD_STRUCTURE = 0,
LTI_NO_INTEGER = 1,
LTI_SOME_INTEGER = 2,
- LTI_ALL_INTEGER = 3
+ LTI_ALL_INTEGER = 3,
+ LTI_SYSTEM_LIMIT = 4,
} LTI_result_t;
LTI_result_t erts_list_to_integer(Process *BIF_P, Eterm orig_list,
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 39ca0827ca..df220a4ce2 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -241,7 +241,7 @@ erts_get_aligned_binary_bytes_extra(Eterm bin, byte** base_ptr, ErtsAlcType_t al
}
Eterm
-erts_bin_bytes_to_list(Eterm previous, Eterm* hp, byte* bytes, Uint size, Uint bitoffs)
+erts_bin_bytes_to_list(Eterm previous, Eterm* hp, const byte* bytes, Uint size, Uint bitoffs)
{
if (bitoffs == 0) {
while (size) {
@@ -996,7 +996,7 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *c_p, Eterm arg, Export *bif)
break; /* done */
}
if (!ERTS_IOLIST_TO_BUF_FAILED(res))
- ERTS_INTERNAL_ERROR("iolist_size/iolist_to_buf missmatch");
+ ERTS_INTERNAL_ERROR("iolist_size/iolist_to_buf mismatch");
if (res == ERTS_IOLIST_TO_BUF_OVERFLOW)
goto overflow;
goto type_error;
@@ -1106,7 +1106,7 @@ BIF_RETTYPE list_to_bitstring_1(BIF_ALIST_1)
break; /* done */
}
if (!ERTS_IOLIST_TO_BUF_FAILED(res))
- ERTS_INTERNAL_ERROR("iolist_size/iolist_to_buf missmatch");
+ ERTS_INTERNAL_ERROR("iolist_size/iolist_to_buf mismatch");
if (res == ERTS_IOLIST_TO_BUF_OVERFLOW)
goto overflow;
goto type_error;
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index fa2f77dc7c..3b6de45587 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -134,12 +134,19 @@ process_killer(void)
if ((j = sys_get_key(0)) <= 0)
erts_exit(0, "");
switch(j) {
- case 'k':
+ case 'k':
+ {
+ Process *init_proc;
+
ASSERT(erts_init_process_id != ERTS_INVALID_PID);
+ init_proc = erts_proc_lookup_raw(erts_init_process_id);
+
/* Send a 'kill' exit signal from init process */
- erts_proc_sig_send_exit(NULL, erts_init_process_id,
- rp->common.id, am_kill, NIL,
- 0);
+ erts_proc_sig_send_exit(&init_proc->common,
+ erts_init_process_id,
+ rp->common.id,
+ am_kill, NIL, 0);
+ }
case 'n': br = 1; break;
case 'r': return;
default: return;
@@ -186,6 +193,7 @@ static int doit_print_monitor(ErtsMonitor *mon, void *vpcontext, Sint reds)
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_TIME_OFFSET:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_RESOURCE:
case ERTS_MON_TYPE_NODE:
@@ -300,7 +308,8 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p, ErtsProcLocks orig_lock
p->current->arity);
}
- erts_print(to, to_arg, "Spawned by: %T\n", p->parent);
+ erts_print(to, to_arg, "Spawned by: %T\n",
+ p->parent == am_undefined ? NIL : p->parent);
if (locks & ERTS_PROC_LOCK_MAIN) {
erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
@@ -705,25 +714,35 @@ bin_check(void)
{
Process *rp;
struct erl_off_heap_header* hdr;
+ struct erl_off_heap_header* oh_list;
int i, printed = 0, max = erts_ptab_max(&erts_proc);
+
for (i=0; i < max; i++) {
rp = erts_pix2proc(i);
if (!rp)
continue;
- for (hdr = rp->off_heap.first; hdr; hdr = hdr->next) {
- if (hdr->thing_word == HEADER_PROC_BIN) {
- ProcBin *bp = (ProcBin*) hdr;
- if (!printed) {
- erts_printf("Process %T holding binary data \n", rp->common.id);
- printed = 1;
- }
- erts_printf("%p orig_size: %bpd, norefs = %bpd\n",
- bp->val,
- bp->val->orig_size,
- erts_refc_read(&bp->val->intern.refc, 1));
- }
- }
+
+ oh_list = rp->off_heap.first;
+ for (;;) {
+ for (hdr = oh_list; hdr; hdr = hdr->next) {
+ if (hdr->thing_word == HEADER_PROC_BIN) {
+ ProcBin *bp = (ProcBin*) hdr;
+ if (!printed) {
+ erts_printf("Process %T holding binary data \n", rp->common.id);
+ printed = 1;
+ }
+ erts_printf("%p orig_size: %bpd, norefs = %bpd\n",
+ bp->val,
+ bp->val->orig_size,
+ erts_refc_read(&bp->val->intern.refc, 1));
+ }
+ }
+ if (oh_list == rp->wrt_bins)
+ break;
+ oh_list = rp->wrt_bins;
+ }
+
if (printed) {
erts_printf("--------------------------------------\n");
printed = 0;
diff --git a/erts/emulator/beam/code_ix.c b/erts/emulator/beam/code_ix.c
index d1159dd144..607f3c82c6 100644
--- a/erts/emulator/beam/code_ix.c
+++ b/erts/emulator/beam/code_ix.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,15 @@
# define CIX_TRACE(text)
#endif
+#if defined(BEAMASM) && defined(ERTS_THR_INSTRUCTION_BARRIER)
+# define CODE_IX_ISSUE_INSTRUCTION_BARRIERS
+#endif
+
+/* If we need to issue a code barrier when thread progress is blocked, we use
+ * this counter to signal all managed threads to execute an instruction barrier
+ * when thread progress is unblocked. */
+erts_atomic32_t outstanding_blocking_code_barriers;
+
erts_atomic32_t the_active_code_index;
erts_atomic32_t the_staging_code_index;
@@ -52,19 +61,28 @@ static erts_mtx_t code_write_permission_mtx;
static erts_tsd_key_t has_code_write_permission;
#endif
+#ifdef DEBUG
+static erts_tsd_key_t needs_code_barrier;
+#endif
+
void erts_code_ix_init(void)
{
/* We start emulator by initializing preloaded modules
* single threaded with active and staging set both to zero.
* Preloading is finished by a commit that will set things straight.
*/
+ erts_atomic32_init_nob(&outstanding_blocking_code_barriers, 0);
erts_atomic32_init_nob(&the_active_code_index, 0);
erts_atomic32_init_nob(&the_staging_code_index, 0);
erts_mtx_init(&code_write_permission_mtx, "code_write_permission", NIL,
ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_GENERIC);
#ifdef ERTS_ENABLE_LOCK_CHECK
erts_tsd_key_create(&has_code_write_permission,
- "erts_has_code_write_permission");
+ "erts_has_code_write_permission");
+#endif
+#ifdef DEBUG
+ erts_tsd_key_create(&needs_code_barrier,
+ "erts_needs_code_barrier");
#endif
CIX_TRACE("init");
}
@@ -223,3 +241,148 @@ int erts_has_code_write_permission(void)
return code_writing_seized && erts_tsd_get(has_code_write_permission);
}
#endif
+
+#ifdef DEBUG
+void erts_debug_require_code_barrier(void) {
+ erts_tsd_set(needs_code_barrier, (void*)(1));
+}
+
+void erts_debug_check_code_barrier(void) {
+ ASSERT(erts_tsd_get(needs_code_barrier) == (void*)0);
+}
+
+static void erts_debug_unrequire_code_barrier(void) {
+ erts_tsd_set(needs_code_barrier, (void*)(0));
+}
+#endif
+
+static void schedule_code_barrier_later_op(void *barrier_) {
+ ErtsCodeBarrier *barrier = (ErtsCodeBarrier*)barrier_;
+
+ if (barrier->size == 0) {
+ erts_schedule_thr_prgr_later_op(barrier->later_function,
+ barrier->later_data,
+ &barrier->later_op);
+ } else {
+ erts_schedule_thr_prgr_later_cleanup_op(barrier->later_function,
+ barrier->later_data,
+ &barrier->later_op,
+ barrier->size);
+ }
+}
+
+#ifdef CODE_IX_ISSUE_INSTRUCTION_BARRIERS
+static void issue_instruction_barrier(void *barrier_) {
+ ErtsCodeBarrier *barrier = (ErtsCodeBarrier*)barrier_;
+
+ ERTS_THR_INSTRUCTION_BARRIER;
+
+ if (erts_refc_dectest(&barrier->pending_schedulers, 0) == 0) {
+# ifdef ERTS_ENABLE_LOCK_CHECK
+ ErtsSchedulerData *initial_esdp = (ErtsSchedulerData*)barrier->esdp;
+
+ /* HACK: Dodges a broken lock-checking assertion, which requires that
+ * the _thread_ that takes a code permission is also the one that
+ * releases it.
+ *
+ * This has never held since processes can migrate between schedulers,
+ * but we have to roll with the punches. Commit the code on the
+ * scheduler that called `erts_schedule_code_barrier` in the hopes that
+ * it's the right one.
+ *
+ * This has been fixed in `master`. */
+ if (initial_esdp && initial_esdp != erts_get_scheduler_data()) {
+ erts_schedule_misc_aux_work(initial_esdp->no,
+ schedule_code_barrier_later_op,
+ barrier);
+ } else {
+ schedule_code_barrier_later_op(barrier);
+ }
+# else
+ schedule_code_barrier_later_op(barrier);
+# endif
+ }
+}
+#endif
+
+void erts_schedule_code_barrier(ErtsCodeBarrier *barrier,
+ void (*later_function)(void *),
+ void *later_data) {
+ erts_schedule_code_barrier_cleanup(barrier, later_function, later_data, 0);
+}
+
+void erts_schedule_code_barrier_cleanup(ErtsCodeBarrier *barrier,
+ void (*later_function)(void *),
+ void *later_data,
+ UWord size)
+{
+#ifdef DEBUG
+ erts_debug_unrequire_code_barrier();
+#endif
+
+ barrier->esdp = erts_get_scheduler_data();
+ barrier->later_function = later_function;
+ barrier->later_data = later_data;
+ barrier->size = size;
+
+#ifdef CODE_IX_ISSUE_INSTRUCTION_BARRIERS
+ /* Issue instruction barriers on all normal schedulers, ensuring that they
+ * won't execute old code.
+ *
+ * The last scheduler to run the barrier gets the honor of scheduling a
+ * thread progress op to run the `later_function`. */
+ erts_refc_init(&barrier->pending_schedulers,
+ (erts_aint_t)erts_no_schedulers);
+ erts_schedule_multi_misc_aux_work(1, 1, erts_no_schedulers,
+ issue_instruction_barrier,
+ barrier);
+ issue_instruction_barrier(barrier);
+#else
+ schedule_code_barrier_later_op(barrier);
+#endif
+}
+
+#ifdef CODE_IX_ISSUE_INSTRUCTION_BARRIERS
+static ErtsThrPrgrLaterOp global_code_barrier_lop;
+
+static void decrement_blocking_code_barriers(void *ignored) {
+ (void)ignored;
+ erts_atomic32_dec_nob(&outstanding_blocking_code_barriers);
+}
+
+static void schedule_blocking_code_barriers(void *ignored) {
+ ERTS_THR_INSTRUCTION_BARRIER;
+
+ /* Tell all managed threads to execute an instruction barrier as soon as we
+ * unblock thread progress, and schedule a thread progress job to clear the
+ * counter.
+ *
+ * Note that we increment and decrement instead of setting and clearing
+ * since we might execute several blocking barriers in the same tick. */
+ erts_atomic32_inc_nob(&outstanding_blocking_code_barriers);
+ erts_schedule_thr_prgr_later_op(decrement_blocking_code_barriers,
+ NULL,
+ &global_code_barrier_lop);
+}
+#endif
+
+void erts_blocking_code_barrier()
+{
+#ifdef DEBUG
+ erts_debug_unrequire_code_barrier();
+#endif
+
+ ERTS_LC_ASSERT(erts_thr_progress_is_blocking());
+
+#ifdef CODE_IX_ISSUE_INSTRUCTION_BARRIERS
+ schedule_blocking_code_barriers(NULL);
+#endif
+}
+
+void erts_code_ix_finalize_wait() {
+#ifdef CODE_IX_ISSUE_INSTRUCTION_BARRIERS
+ if (erts_atomic32_read_nob(&outstanding_blocking_code_barriers) != 0) {
+ ERTS_THR_INSTRUCTION_BARRIER;
+ }
+#endif
+}
diff --git a/erts/emulator/beam/code_ix.h b/erts/emulator/beam/code_ix.h
index 0345ccf1ef..f557ff2980 100644
--- a/erts/emulator/beam/code_ix.h
+++ b/erts/emulator/beam/code_ix.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
* The current 'active' code index is used to access the current running
* code. The 'staging' code index is used by the process that performs
* a code change operation. When a code change operation completes
- * succesfully, the staging code index becomes the new active code index.
+ * successfully, the staging code index becomes the new active code index.
*
* The third code index is not explicitly used. It can be thought of as
* the "previous active" or the "next staging" index. It is needed to make
@@ -59,10 +59,29 @@
#include "beam_opcodes.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
+
struct process;
#define ERTS_NUM_CODE_IX 3
+
+#ifdef BEAMASM
+#define ERTS_ADDRESSV_SIZE (ERTS_NUM_CODE_IX + 1)
+#define ERTS_SAVE_CALLS_CODE_IX (ERTS_ADDRESSV_SIZE - 1)
+#else
+#define ERTS_ADDRESSV_SIZE ERTS_NUM_CODE_IX
+#endif
+
+/* This structure lets `Export` entries and `ErlFunEntry` share dispatch code,
+ * which greatly improves the performance of fun calls. */
+typedef struct ErtsDispatchable_ {
+ ErtsCodePtr addresses[ERTS_ADDRESSV_SIZE];
+} ErtsDispatchable;
+
typedef unsigned ErtsCodeIndex;
typedef struct ErtsCodeMFA_ {
@@ -79,13 +98,36 @@ typedef struct ErtsCodeMFA_ {
/* If you change the size of this, you also have to update the code
in ops.tab to reflect the new func_info size */
typedef struct ErtsCodeInfo_ {
- BeamInstr op; /* OpCode(i_func_info) */
- union {
- struct generic_bp* gen_bp; /* Trace breakpoint */
+ /* In both the JIT and interpreter, we may jump here to raise a
+ * function_clause error.
+ *
+ * In addition, the JIT also stores the current breakpoint flags here. */
+ struct {
+#ifndef BEAMASM
+ BeamInstr op;
+#else
+ struct {
+ char raise_function_clause[sizeof(BeamInstr) - 1];
+ char breakpoint_flag;
+ } metadata;
+#endif
} u;
+
+ /* Trace breakpoint */
+ struct generic_bp *gen_bp;
ErtsCodeMFA mfa;
} ErtsCodeInfo;
+typedef struct {
+ erts_refc_t pending_schedulers;
+ ErtsThrPrgrLaterOp later_op;
+ void *esdp;
+ UWord size;
+
+ void (*later_function)(void *);
+ void *later_data;
+} ErtsCodeBarrier;
+
/* Get the code associated with a ErtsCodeInfo ptr. */
ERTS_GLB_INLINE
ErtsCodePtr erts_codeinfo_to_code(const ErtsCodeInfo *ci);
@@ -165,6 +207,32 @@ void erts_commit_staging_code_ix(void);
*/
void erts_abort_staging_code_ix(void);
+#ifdef DEBUG
+void erts_debug_require_code_barrier(void);
+void erts_debug_check_code_barrier(void);
+#endif
+
+/* Schedules an operation to run after thread progress _and_ all schedulers
+ * have issued an instruction barrier. */
+void erts_schedule_code_barrier(ErtsCodeBarrier *barrier,
+ void (*later_function)(void *),
+ void *later_data);
+
+void erts_schedule_code_barrier_cleanup(ErtsCodeBarrier *barrier,
+ void (*later_function)(void *),
+ void *later_data,
+ UWord size);
+
+/* Issues a code barrier on the current thread, as well as all managed threads
+ * when they wake up after thread progress is unblocked.
+ *
+ * Requires that thread progress is blocked. */
+void erts_blocking_code_barrier(void);
+
+/* Helper function for the above: all managed threads should call this as soon
+ * as thread progress is unblocked, _BEFORE_ updating thread progress. */
+void erts_code_ix_finalize_wait(void);
+
#ifdef ERTS_ENABLE_LOCK_CHECK
int erts_has_code_write_permission(void);
#endif
@@ -185,7 +253,7 @@ ERTS_GLB_INLINE
ErtsCodePtr erts_codeinfo_to_code(const ErtsCodeInfo *ci)
{
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI) || !ci->op);
+ ASSERT(BeamIsOpCode(ci->u.op, op_i_func_info_IaaI) || !ci->u.op);
#endif
ASSERT_MFA(&ci->mfa);
return (ErtsCodePtr)&ci[1];
@@ -197,7 +265,7 @@ const ErtsCodeInfo *erts_code_to_codeinfo(ErtsCodePtr I)
const ErtsCodeInfo *ci = &((const ErtsCodeInfo *)I)[-1];
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI) || !ci->op);
+ ASSERT(BeamIsOpCode(ci->u.op, op_i_func_info_IaaI) || !ci->u.op);
#endif
ASSERT_MFA(&ci->mfa);
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index 0d63433372..79f90fbcb0 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
#include "erl_binary.h"
#include "erl_bits.h"
#include "dtrace-wrapper.h"
+#include "erl_global_literals.h"
static void move_one_frag(Eterm** hpp, ErlHeapFragment*, ErlOffHeap*, int);
@@ -114,12 +115,20 @@ Uint size_object_x(Eterm obj, erts_literal_area_t *litopt)
ASSERT(is_header(hdr));
switch (hdr & _TAG_HEADER_MASK) {
case ARITYVAL_SUBTAG:
- ptr = tuple_val(obj);
arity = header_arity(hdr);
- sum += arity + 1;
if (arity == 0) { /* Empty tuple -- unusual. */
+ ASSERT(!litopt &&
+ erts_is_literal(obj,ptr) &&
+ obj == ERTS_GLOBAL_LIT_EMPTY_TUPLE);
+ /*
+ The empty tuple is always a global literal
+ constant so it does not take up any extra
+ space.
+ */
goto pop_next;
}
+ ptr = tuple_val(obj);
+ sum += arity + 1;
while (arity-- > 1) {
obj = *++ptr;
if (!IS_CONST(obj)) {
@@ -154,6 +163,7 @@ Uint size_object_x(Eterm obj, erts_literal_area_t *litopt)
mp = (flatmap_t*)flatmap_val(obj);
ptr = (Eterm *)mp;
n = flatmap_get_size(mp) + 1;
+ ASSERT(flatmap_get_size(mp) <= MAP_SMALL_MAP_LIMIT);
sum += n + 2;
ptr += 2; /* hdr + size words */
while (n--) {
@@ -365,7 +375,10 @@ Uint size_shared(Eterm obj)
int arity = header_arity(hdr);
sum += arity + 1;
if (arity == 0) { /* Empty tuple -- unusual. */
- goto pop_next;
+ ASSERT(COUNT_OFF_HEAP &&
+ erts_is_literal(obj,ptr) &&
+ obj == ERTS_GLOBAL_LIT_EMPTY_TUPLE);
+ goto pop_next;
}
while (arity-- > 0) {
obj = *++ptr;
@@ -418,6 +431,7 @@ Uint size_shared(Eterm obj)
case MAP_HEADER_TAG_FLATMAP_HEAD : {
flatmap_t *mp = (flatmap_t*)flatmap_val(obj);
Uint n = flatmap_get_size(mp) + 1;
+ ASSERT(flatmap_get_size(mp) <= MAP_SMALL_MAP_LIMIT);
ptr = (Eterm *)mp;
sum += n + 2;
ptr += 2; /* hdr + size words */
@@ -523,6 +537,9 @@ cleanup:
case ARITYVAL_SUBTAG: {
int arity = header_arity(hdr);
if (arity == 0) { /* Empty tuple -- unusual. */
+ ASSERT(COUNT_OFF_HEAP &&
+ erts_is_literal(obj,ptr) &&
+ obj == ERTS_GLOBAL_LIT_EMPTY_TUPLE);
goto cleanup_next;
}
while (arity-- > 0) {
@@ -551,6 +568,7 @@ cleanup:
case MAP_HEADER_TAG_FLATMAP_HEAD : {
flatmap_t *mp = (flatmap_t *) ptr;
Uint n = flatmap_get_size(mp) + 1;
+ ASSERT(flatmap_get_size(mp) <= MAP_SMALL_MAP_LIMIT);
ptr += 2; /* hdr + size words */
while (n--) {
obj = *ptr++;
@@ -736,6 +754,13 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
{
int const_flag = 1; /* assume constant tuple */
i = arityval(hdr);
+ if (i == 0) {
+ ASSERT(!litopt &&
+ erts_is_literal(obj,objp) &&
+ obj == ERTS_GLOBAL_LIT_EMPTY_TUPLE);
+ *argp = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ break;
+ }
*argp = make_tuple(htop);
tp = htop; /* tp is pointer to new arity value */
*htop++ = *objp++; /* copy arity value */
@@ -849,9 +874,15 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
*htop++ = *objp++;
}
funp = (ErlFunThing *) tp;
- funp->next = off_heap->first;
- off_heap->first = (struct erl_off_heap_header*) funp;
- erts_refc_inc(&funp->fe->refc, 2);
+
+ if (is_local_fun(funp)) {
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) funp;
+ erts_refc_inc(&funp->entry.fun->refc, 2);
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ }
+
*argp = make_fun(tp);
}
break;
@@ -888,6 +919,7 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
switch (MAP_HEADER_TYPE(hdr)) {
case MAP_HEADER_TAG_FLATMAP_HEAD :
i = flatmap_get_size(objp) + 3;
+ ASSERT(flatmap_get_size(objp) <= MAP_SMALL_MAP_LIMIT);
*argp = make_flatmap(htop);
while (i--) {
*htop++ = *objp++;
@@ -1094,7 +1126,9 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
#ifdef DEBUG
Eterm mypid = erts_get_current_pid();
#endif
-
+ const Eterm empty_tuple_literal =
+ ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+
DECLARE_EQUEUE_INIT_INFO(s, info);
DECLARE_BITSTORE_INIT_INFO(b, info);
DECLARE_SHTABLE_INIT_INFO(t, info);
@@ -1184,10 +1218,12 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
case TAG_PRIMARY_BOXED: {
Eterm hdr;
ptr = boxed_val(obj);
- /* off heap pointers to boxes are copied verbatim */
+ /* off heap pointers to boxes (except pointers to the
+ empty tuple) are copied verbatim */
if (erts_is_literal(obj,ptr)) {
VERBOSE(DEBUG_SHCOPY, ("[pid=%T] bypassed copying %p is %T\n", mypid, ptr, obj));
- if (copy_literals || in_literal_purge_area(ptr))
+ if (obj != empty_tuple_literal &&
+ (copy_literals || in_literal_purge_area(ptr)))
info->literal_size += size_object(obj);
goto pop_next;
}
@@ -1211,10 +1247,10 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
switch (hdr & _TAG_HEADER_MASK) {
case ARITYVAL_SUBTAG: {
int arity = header_arity(hdr);
+ /* arity cannot be 0 as the empty tuple is always a
+ global constant literal which is handled above */
+ ASSERT(arity != 0);
sum += arity + 1;
- if (arity == 0) { /* Empty tuple -- unusual. */
- goto pop_next;
- }
while (arity-- > 0) {
obj = *++ptr;
if (!IS_CONST(obj)) {
@@ -1286,6 +1322,7 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
case MAP_HEADER_TAG_FLATMAP_HEAD : {
flatmap_t *mp = (flatmap_t *) ptr;
Uint n = flatmap_get_size(mp) + 1;
+ ASSERT(flatmap_get_size(mp) <= MAP_SMALL_MAP_LIMIT);
sum += n + 2;
ptr += 2; /* hdr + size words */
while (n--) {
@@ -1382,7 +1419,8 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
Eterm mypid = erts_get_current_pid();
Eterm saved_obj = obj;
#endif
-
+ const Eterm empty_tuple_literal =
+ ERTS_GLOBAL_LIT_EMPTY_TUPLE;
DECLARE_EQUEUE_FROM_INFO(s, info);
DECLARE_BITSTORE_FROM_INFO(b, info);
DECLARE_SHTABLE_FROM_INFO(t, info);
@@ -1499,7 +1537,8 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
ptr = boxed_val(obj);
/* off heap pointers to boxes are copied verbatim */
if (erts_is_literal(obj,ptr)) {
- if (!(copy_literals || in_literal_purge_area(ptr))) {
+ if (obj == empty_tuple_literal ||
+ !(copy_literals || in_literal_purge_area(ptr))) {
*resp = obj;
} else {
Uint bsz = 0;
@@ -1577,9 +1616,15 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
*hp++ = HEAP_ELEM_TO_BE_FILLED;
}
}
- funp->next = off_heap->first;
- off_heap->first = (struct erl_off_heap_header*) funp;
- erts_refc_inc(&funp->fe->refc, 2);
+
+ if (is_local_fun(funp)) {
+ funp->next = off_heap->first;
+ off_heap->first = (struct erl_off_heap_header*) funp;
+ erts_refc_inc(&funp->entry.fun->refc, 2);
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ }
+
goto cleanup_next;
}
case MAP_SUBTAG:
@@ -1589,6 +1634,7 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
case MAP_HEADER_TAG_FLATMAP_HEAD : {
flatmap_t *mp = (flatmap_t *) ptr;
Uint n = flatmap_get_size(mp) + 1;
+ ASSERT(flatmap_get_size(mp) <= MAP_SMALL_MAP_LIMIT);
*hp++ = *++ptr; /* keys */
while (n--) {
obj = *++ptr;
@@ -1792,6 +1838,7 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
case MAP_HEADER_TAG_FLATMAP_HEAD : {
flatmap_t *mp = (flatmap_t *) hscan;
remaining = flatmap_get_size(mp) + 1;
+ ASSERT(flatmap_get_size(mp) <= MAP_SMALL_MAP_LIMIT);
hscan += 2;
break;
}
@@ -1899,7 +1946,8 @@ copy_shallow_x(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_h
Eterm* hp = *hpp;
const Eterm res = make_tuple(hp);
const Sint offs = (hp - tp) * sizeof(Eterm);
-
+ const Eterm empty_tuple_literal =
+ ERTS_GLOBAL_LIT_EMPTY_TUPLE;
while (sz--) {
Eterm val = *tp++;
@@ -1909,7 +1957,11 @@ copy_shallow_x(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_h
break;
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- *hp++ = byte_offset_ptr(val, offs);
+ if (val == empty_tuple_literal) {
+ *hp++ = empty_tuple_literal;
+ } else {
+ *hp++ = byte_offset_ptr(val, offs);
+ }
break;
case TAG_PRIMARY_HEADER:
*hp++ = val;
@@ -1924,12 +1976,18 @@ copy_shallow_x(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_h
}
goto off_heap_common;
- case FUN_SUBTAG:
- {
- ErlFunThing* funp = (ErlFunThing *) (tp-1);
- erts_refc_inc(&funp->fe->refc, 2);
- }
- goto off_heap_common;
+ case FUN_SUBTAG:
+ {
+ ErlFunThing* funp = (ErlFunThing *) (tp-1);
+
+ if (is_local_fun(funp)) {
+ erts_refc_inc(&funp->entry.fun->refc, 2);
+ goto off_heap_common;
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ goto default_copy;
+ }
+ }
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
case EXTERNAL_REF_SUBTAG:
@@ -1963,6 +2021,7 @@ copy_shallow_x(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_h
}
/* Fall through... */
}
+ default_copy:
default:
{
int tari = header_arity(val);
@@ -2054,34 +2113,49 @@ move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap, int lite
Eterm* hp = *hpp;
while (ptr != end) {
- Eterm val;
- ASSERT(ptr < end);
- val = *ptr;
- ASSERT(val != ERTS_HOLE_MARKER);
- if (is_header(val)) {
- struct erl_off_heap_header* hdr = (struct erl_off_heap_header*)hp;
- ASSERT(ptr + header_arity(val) < end);
- ptr = move_boxed(ptr, val, &hp, &dummy_ref);
- switch (val & _HEADER_SUBTAG_MASK) {
- case REF_SUBTAG:
- if (!is_magic_ref_thing(hdr))
- break;
- case REFC_BINARY_SUBTAG:
- case FUN_SUBTAG:
- case EXTERNAL_PID_SUBTAG:
- case EXTERNAL_PORT_SUBTAG:
- case EXTERNAL_REF_SUBTAG:
- hdr->next = off_heap->first;
- off_heap->first = hdr;
- break;
- }
- }
- else { /* must be a cons cell */
- ASSERT(ptr+1 < end);
- move_cons(ptr, val, &hp, &dummy_ref);
- ptr += 2;
- }
+ Eterm val;
+ ASSERT(ptr < end);
+ val = *ptr;
+ ASSERT(val != ERTS_HOLE_MARKER);
+
+ if (is_header(val)) {
+ struct erl_off_heap_header* hdr = (struct erl_off_heap_header*)hp;
+
+ ASSERT(ptr + header_arity(val) < end);
+ ptr = move_boxed(ptr, val, &hp, &dummy_ref);
+
+ switch (val & _HEADER_SUBTAG_MASK) {
+ case REF_SUBTAG:
+ if (!is_magic_ref_thing(hdr)) {
+ break;
+ }
+ case REFC_BINARY_SUBTAG:
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG:
+ hdr->next = off_heap->first;
+ off_heap->first = hdr;
+ break;
+ case FUN_SUBTAG:
+ {
+ ErlFunThing *funp = (ErlFunThing*)hdr;
+
+ if (is_local_fun(funp)) {
+ hdr->next = off_heap->first;
+ off_heap->first = hdr;
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ }
+ }
+ break;
+ }
+ } else { /* must be a cons cell */
+ ASSERT(ptr+1 < end);
+ move_cons(ptr, val, &hp, &dummy_ref);
+ ptr += 2;
+ }
}
+
*hpp = hp;
OH_OVERHEAD(off_heap, frag->off_heap.overhead);
frag->off_heap.first = NULL;
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 0967b94809..9a760fd97f 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2022. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@
#include "dtrace-wrapper.h"
#include "erl_proc_sig_queue.h"
#include "erl_global_literals.h"
+#include "erl_map.h"
#define DIST_CTL_DEFAULT_SIZE 64
@@ -177,7 +178,7 @@ static char *erts_dop_to_string(enum dop dop) {
int erts_is_alive; /* System must be blocked on change */
int erts_dist_buf_busy_limit;
-int erts_dflags_test_remove_hopefull_flags;
+Uint64 erts_dflags_test_remove_hopefull_flags;
Export spawn_request_yield_export;
@@ -192,7 +193,7 @@ static Export *dist_ctrl_put_data_trap;
static void erts_schedule_dist_command(Port *, DistEntry *);
static int dsig_send_exit(ErtsDSigSendContext *ctx, Eterm ctl, Eterm msg);
static int dsig_send_ctl(ErtsDSigSendContext *ctx, Eterm ctl);
-static void send_nodes_mon_msgs(Process *, Eterm, Eterm, Eterm, Eterm);
+static void send_nodes_mon_msgs(Process *, Eterm, Eterm, Uint32, Eterm, Eterm);
static void init_nodes_monitors(void);
static Sint abort_pending_connection(DistEntry* dep, Uint32 conn_id,
int *was_connected_p);
@@ -210,6 +211,37 @@ struct {
ErlHeapFragment *bp;
} nodedown;
+/*
+ * Dist entry queue flags are only modified while
+ * the dist entry queue lock is held...
+ */
+static ERTS_INLINE erts_aint32_t
+de_qflags_read(DistEntry *dep)
+{
+ return erts_atomic32_read_nob(&dep->qflgs);
+}
+
+static ERTS_INLINE erts_aint32_t
+de_qflags_read_set(DistEntry *dep, erts_aint32_t set)
+{
+ erts_aint32_t qflgs, new_qflgs;
+ ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&dep->qlock));
+ new_qflgs = qflgs = erts_atomic32_read_nob(&dep->qflgs);
+ new_qflgs |= set;
+ erts_atomic32_set_nob(&dep->qflgs, new_qflgs);
+ return qflgs;
+}
+
+static ERTS_INLINE erts_aint32_t
+de_qflags_read_unset(DistEntry *dep, erts_aint32_t unset)
+{
+ erts_aint32_t qflgs, new_qflgs;
+ ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&dep->qlock));
+ new_qflgs = qflgs = erts_atomic32_read_nob(&dep->qflgs);
+ new_qflgs &= ~unset;
+ erts_atomic32_set_nob(&dep->qflgs, new_qflgs);
+ return qflgs;
+}
static void
delete_cache(ErtsAtomCache *cache)
@@ -249,7 +281,7 @@ get_suspended_on_de(DistEntry *dep, erts_aint32_t unset_qflgs)
{
erts_aint32_t qflgs;
ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&dep->qlock));
- qflgs = erts_atomic32_read_band_acqb(&dep->qflgs, ~unset_qflgs);
+ qflgs = de_qflags_read_unset(dep, unset_qflgs);
qflgs &= ~unset_qflgs;
if (qflgs & ERTS_DE_QFLG_EXIT) {
/* No resume when exit has been scheduled */
@@ -267,23 +299,44 @@ get_suspended_on_de(DistEntry *dep, erts_aint32_t unset_qflgs)
static int monitor_connection_down(ErtsMonitor *mon, void *unused, Sint reds)
{
- if (erts_monitor_is_origin(mon))
- erts_proc_sig_send_demonitor(mon);
- else
- erts_proc_sig_send_monitor_down(mon, am_noconnection);
+ const ErtsMonitorData *data = erts_monitor_to_data(mon);
+ Eterm from;
+
+ if (erts_monitor_is_origin(mon)) {
+ from = data->u.target.other.item;
+ } else {
+ from = data->origin.other.item;
+ }
+
+ ASSERT(!is_internal_pid(from) && is_internal_pid(mon->other.item));
+
+ if (erts_monitor_is_origin(mon)) {
+ erts_proc_sig_send_demonitor(NULL, from, 0, mon);
+ } else {
+ erts_proc_sig_send_monitor_down(NULL, from, mon, am_noconnection);
+ }
+
return ERTS_MON_LNK_FIRE_REDS;
}
static int dist_pend_spawn_exit_connection_down(ErtsMonitor *mon, void *unused, Sint reds)
{
+ Process *proc = mon->other.ptr;
+ ASSERT(!erts_monitor_is_origin(mon));
+ if (proc) {
+ ErtsMonitorData *mdp = erts_monitor_to_data(mon);
+ if (mdp->origin.other.item == am_pending) {
+ /* Resume the parent process waiting for a result... */
+ erts_resume(proc, 0);
+ }
+ }
erts_monitor_release(mon);
return 1;
}
static int link_connection_down(ErtsLink *lnk, void *vdist, Sint reds)
{
- erts_proc_sig_send_link_exit(NULL, THE_NON_VALUE, lnk,
- am_noconnection, NIL);
+ erts_proc_sig_send_link_exit_noconnection(lnk);
return ERTS_MON_LNK_FIRE_REDS;
}
@@ -299,6 +352,7 @@ typedef enum {
typedef struct {
ErtsConMonLnkSeqCleanupState state;
DistEntry* dep;
+ Uint32 connection_id;
ErtsMonLnkDist *dist;
DistSeqNode *seq;
void *yield_state;
@@ -377,6 +431,7 @@ con_monitor_link_seq_cleanup(void *vcmlcp)
send_nodes_mon_msgs(NULL,
am_nodedown,
cmlcp->nodename,
+ cmlcp->connection_id,
cmlcp->visability,
cmlcp->reason);
erts_de_rwlock(cmlcp->dep);
@@ -442,10 +497,13 @@ schedule_con_monitor_link_seq_cleanup(DistEntry* dep,
cmlcp->yield_state = NULL;
cmlcp->dist = dist;
- if (!dist)
+ if (!dist) {
cmlcp->state = ERTS_CML_CLEANUP_STATE_NODE_MONITORS;
+ cmlcp->connection_id = 0;
+ }
else {
cmlcp->state = ERTS_CML_CLEANUP_STATE_LINKS;
+ cmlcp->connection_id = dist->connection_id;
erts_mtx_lock(&dist->mtx);
ASSERT(dist->alive);
dist->alive = 0;
@@ -794,7 +852,8 @@ set_node_not_alive(void *unused)
erts_thr_progress_block();
erts_set_this_node(am_Noname, 0);
erts_is_alive = 0;
- send_nodes_mon_msgs(NULL, am_nodedown, nodename, am_visible, nodedown.reason);
+ send_nodes_mon_msgs(NULL, am_nodedown, nodename, ~((Uint32) 0),
+ am_visible, nodedown.reason);
nodedown.reason = NIL;
bp = nodedown.bp;
nodedown.bp = NULL;
@@ -828,8 +887,10 @@ inc_no_nodes(void)
static void
kill_dist_ctrl_proc(void *vpid)
{
- erts_proc_sig_send_exit(NULL, (Eterm) vpid, (Eterm) vpid,
- am_kill, NIL, 0);
+ /* Send a 'kill' exit signal from init process */
+ Process *init_proc = erts_proc_lookup_raw(erts_init_process_id);
+ erts_proc_sig_send_exit(&init_proc->common, erts_init_process_id,
+ (Eterm)vpid, am_kill, NIL, 0);
}
static void
@@ -980,13 +1041,14 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
}
if (dep->state == ERTS_DE_STATE_EXITING) {
- ASSERT(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_EXIT);
+ ASSERT(de_qflags_read(dep) & ERTS_DE_QFLG_EXIT);
}
else {
+ ASSERT(dep->state == ERTS_DE_STATE_CONNECTED);
dep->state = ERTS_DE_STATE_EXITING;
erts_mtx_lock(&dep->qlock);
- ASSERT(!(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_EXIT));
- erts_atomic32_read_bor_relb(&dep->qflgs, ERTS_DE_QFLG_EXIT);
+ ASSERT(!(de_qflags_read(dep) & ERTS_DE_QFLG_EXIT));
+ de_qflags_read_set(dep, ERTS_DE_QFLG_EXIT);
erts_mtx_unlock(&dep->qlock);
}
@@ -1012,6 +1074,8 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
suspendees = get_suspended_on_de(dep, ERTS_DE_QFLGS_ALL);
erts_mtx_unlock(&dep->qlock);
+
+ erts_atomic32_set_relb(&dep->notify, 0);
erts_atomic_set_nob(&dep->dist_cmd_scheduled, 0);
dep->send = NULL;
@@ -1113,7 +1177,8 @@ void init_dist(void)
static ERTS_INLINE ErtsDistOutputBuf *
alloc_dist_obufs(byte **extp, TTBEncodeContext *ctx,
- Uint data_size, Uint fragments, Uint vlen)
+ Uint data_size, Uint fragments, Uint vlen,
+ int ignore_busy)
{
int ix;
ErtsDistOutputBuf *obuf;
@@ -1144,6 +1209,7 @@ alloc_dist_obufs(byte **extp, TTBEncodeContext *ctx,
erts_refc_add(&bin->intern.refc, fragments - 1, 1);
for (ix = 0; ix < fragments; ix++) {
+ obuf[ix].ignore_busy = ignore_busy;
obuf[ix].bin = bin;
obuf[ix].eiov = &ctx->fragment_eiovs[ix];
#ifdef DEBUG
@@ -1189,6 +1255,81 @@ size_obuf(ErtsDistOutputBuf *obuf)
return sz;
}
+static ERTS_INLINE void
+get_obuf_sizes(ErtsDistOutputBuf *obuf, Sint *size, Sint *ignore_size)
+{
+ Sint sz = size_obuf(obuf);
+ ASSERT(sz >= 0);
+ *size = sz;
+ *ignore_size = obuf->ignore_busy ? sz : 0;
+}
+
+static ERTS_INLINE void
+add_obuf_sizes(ErtsDistOutputBuf *obuf, Sint *size, Sint *ignore_size)
+{
+ Sint sz, isz;
+ get_obuf_sizes(obuf, &sz, &isz);
+ *size += sz;
+ *ignore_size += isz;
+}
+
+static ERTS_INLINE void
+subtract_obuf_sizes(ErtsDistOutputBuf *obuf, Sint *size, Sint *ignore_size)
+{
+ Sint sz, isz;
+ get_obuf_sizes(obuf, &sz, &isz);
+ *size -= sz;
+ *ignore_size -= isz;
+}
+
+static ERTS_INLINE void
+update_qsizes(DistEntry *dep, int *empty_fillp, Sint *qsizep,
+ Sint add_total_qsize, Sint ignore_qsize)
+{
+ /*
+ * All modifications of the 'total_qsize' and 'qsize' fields are
+ * made while holding the 'qlock', so read/modify/write of each
+ * field does not need to be atomic. Readers without the lock will
+ * still see consistent updates of each 'field'.
+ */
+ erts_aint_t qsize, add_qsize;
+
+ ERTS_LC_ASSERT(erts_lc_mtx_is_locked(&dep->qlock));
+
+ if (empty_fillp)
+ *empty_fillp = 0;
+
+ if (add_total_qsize) {
+ qsize = erts_atomic_read_nob(&dep->total_qsize);
+ qsize += (erts_aint_t) add_total_qsize;
+ if (empty_fillp && qsize == add_total_qsize)
+ *empty_fillp = !0;
+ erts_atomic_set_nob(&dep->total_qsize, (erts_aint_t) qsize);
+ }
+
+ add_qsize = (erts_aint_t) (add_total_qsize - ignore_qsize);
+ if (add_qsize) {
+ qsize = erts_atomic_read_nob(&dep->qsize);
+ qsize += add_qsize;
+ if (qsizep)
+ *qsizep = qsize;
+ erts_atomic_set_nob(&dep->qsize, (erts_aint_t) qsize);
+ }
+ else if (qsizep) {
+ *qsizep = erts_atomic_read_nob(&dep->qsize);
+ }
+
+#ifdef DEBUG
+ {
+ erts_aint_t tqsize = erts_atomic_read_nob(&dep->total_qsize);
+ qsize = erts_atomic_read_nob(&dep->qsize);
+ ASSERT(tqsize >= 0);
+ ASSERT(qsize >= 0);
+ ASSERT(tqsize >= qsize);
+ }
+#endif
+}
+
static ErtsDistOutputBuf* clear_de_out_queues(DistEntry* dep)
{
ErtsDistOutputBuf *obuf;
@@ -1219,21 +1360,19 @@ static ErtsDistOutputBuf* clear_de_out_queues(DistEntry* dep)
static void free_de_out_queues(DistEntry* dep, ErtsDistOutputBuf *obuf)
{
- Sint obufsize = 0;
+ Sint obufsize = 0, ignore_obufsize = 0;
while (obuf) {
ErtsDistOutputBuf *fobuf;
fobuf = obuf;
obuf = obuf->next;
- obufsize += size_obuf(fobuf);
+ add_obuf_sizes(fobuf, &obufsize, &ignore_obufsize);
free_dist_obuf(fobuf, !0);
}
if (obufsize) {
erts_mtx_lock(&dep->qlock);
- ASSERT(erts_atomic_read_nob(&dep->qsize) >= obufsize);
- erts_atomic_add_nob(&dep->qsize,
- (erts_aint_t) -obufsize);
+ update_qsizes(dep, NULL, NULL, -obufsize, -ignore_obufsize);
erts_mtx_unlock(&dep->qlock);
}
}
@@ -1328,7 +1467,7 @@ erts_dsig_send_unlink(ErtsDSigSendContext *ctx, Eterm local, Eterm remote, Uint6
* end up in an inconsistent state as we could before the new link
* protocol was introduced...
*/
- erts_proc_sig_send_dist_unlink_ack(ctx->c_p, ctx->dep, ctx->connection_id,
+ erts_proc_sig_send_dist_unlink_ack(ctx->dep, ctx->connection_id,
remote, local, id);
ctl = TUPLE3(&ctx->ctl_heap[0], make_small(DOP_UNLINK), local, remote);
}
@@ -1714,7 +1853,7 @@ dsig_send_spawn_request(ErtsDSigSendContext *ctx, Eterm ref, Eterm from,
* Present this as two messages for the sequence tracing.
* All data except the argument list in the first message
* and then the argument list as second message (which
- * willl become an actual message). For more info see
+ * will become an actual message). For more info see
* handling of seq-trace token in erl_create_process().
*/
@@ -1974,10 +2113,14 @@ int erts_net_message(Port *prt,
seq->ctl_len = ctl_len;
seq->seq_id = ede.data->seq_id;
seq->cnt = ede.data->frag_id;
- if (dist_seq_rbt_lookup_insert(&dep->sequences, seq) != NULL) {
+ erts_de_rlock(dep);
+ if (dep->state != ERTS_DE_STATE_CONNECTED
+ || dep->connection_id != ede.connection_id
+ || dist_seq_rbt_lookup_insert(&dep->sequences, seq) != NULL) {
free_message_buffer(&seq->hfrag);
- goto data_error;
+ goto data_error_runlock;
}
+ erts_de_runlock(dep);
erts_make_dist_ext_copy(&ede, erts_get_dist_ext(&seq->hfrag));
@@ -1989,10 +2132,17 @@ int erts_net_message(Port *prt,
/* fall through, the first fragment in the sequence was the last fragment */
case ERTS_PREP_DIST_EXT_FRAG_CONT: {
- DistSeqNode *seq = dist_seq_rbt_lookup(dep->sequences, ede.data->seq_id);
+ DistSeqNode *seq;
+ erts_de_rlock(dep);
+ if (dep->state != ERTS_DE_STATE_CONNECTED
+ || dep->connection_id != ede.connection_id) {
+ goto data_error_runlock;
+ }
+
+ seq = dist_seq_rbt_lookup(dep->sequences, ede.data->seq_id);
if (!seq)
- goto data_error;
+ goto data_error_runlock;
/* If we did a fall-though we already did this */
if (res == ERTS_PREP_DIST_EXT_FRAG_CONT)
@@ -2000,16 +2150,20 @@ int erts_net_message(Port *prt,
/* Verify that the fragments have arrived in the correct order */
if (seq->cnt != ede.data->frag_id)
- goto data_error;
+ goto data_error_runlock;
seq->cnt--;
/* Check if this was the last fragment */
- if (ede.data->frag_id > 1)
+ if (ede.data->frag_id > 1) {
+ erts_de_runlock(dep);
return 0;
+ }
/* Last fragment arrived, time to dispatch the signal */
+
dist_seq_rbt_delete(&dep->sequences, seq);
+ erts_de_runlock(dep);
ctl_len = seq->ctl_len;
/* Now that we no longer need the DistSeqNode we re-use the heapfragment
@@ -2090,11 +2244,10 @@ int erts_net_message(Port *prt,
ASSERT(eq(ldp->proc.other.item, from));
code = erts_link_dist_insert(&ldp->dist, ede.mld);
- if (erts_proc_sig_send_link(NULL, to, &ldp->proc)) {
+ if (erts_proc_sig_send_link(NULL, from, to, &ldp->proc)) {
if (!code) {
/* Race: connection already down => send link exit */
- erts_proc_sig_send_link_exit(NULL, THE_NON_VALUE, &ldp->dist,
- am_noconnection, NIL);
+ erts_proc_sig_send_link_exit_noconnection(&ldp->dist);
}
break; /* Done */
}
@@ -2177,8 +2330,7 @@ int erts_net_message(Port *prt,
if (is_not_internal_pid(to))
goto invalid_message;
- erts_proc_sig_send_dist_unlink_ack(NULL, dep, conn_id,
- from, to, id);
+ erts_proc_sig_send_dist_unlink_ack(dep, conn_id, from, to, id);
break;
}
@@ -2234,8 +2386,10 @@ int erts_net_message(Port *prt,
break;
}
- if (erts_proc_sig_send_monitor(&mdp->u.target, pid))
+ if (erts_proc_sig_send_monitor(NULL, watcher,
+ &mdp->u.target, pid)) {
break; /* done */
+ }
/* Failed to send to local proc; cleanup reply noproc... */
@@ -2256,8 +2410,7 @@ int erts_net_message(Port *prt,
case DOP_DEMONITOR_P:
/* A remote node informs us that a local pid in no longer monitored
- We get {DOP_DEMONITOR_P, Remote pid, Local pid or name, ref},
- We need only the ref of course */
+ We get {DOP_DEMONITOR_P, Remote pid, Local pid or name, ref}. */
if (tuple_arity != 4) {
goto invalid_message;
@@ -2274,9 +2427,9 @@ int erts_net_message(Port *prt,
if (is_not_external_pid(watcher) || external_pid_dist_entry(watcher) != dep)
goto invalid_message;
- if (is_internal_pid(watched))
- erts_proc_sig_send_dist_demonitor(watched, ref);
- else if (is_external_pid(watched)
+ if (is_internal_pid(watched)) {
+ erts_proc_sig_send_dist_demonitor(watcher, watched, ref);
+ } else if (is_external_pid(watched)
&& external_pid_dist_entry(watched) == erts_this_dist_entry) {
/* old incarnation; ignore it */
;
@@ -2289,13 +2442,14 @@ int erts_net_message(Port *prt,
mon = erts_monitor_tree_lookup(ede.mld->orig_name_monitors, ref);
if (mon)
erts_monitor_tree_delete(&ede.mld->orig_name_monitors, mon);
- }
- else
+ } else {
mon = NULL;
+ }
erts_mtx_unlock(&ede.mld->mtx);
- if (mon)
- erts_proc_sig_send_demonitor(mon);
+ if (mon) {
+ erts_proc_sig_send_demonitor(NULL, watcher, 0, mon);
+ }
}
else
goto invalid_message;
@@ -2374,19 +2528,20 @@ int erts_net_message(Port *prt,
* the atom '' (empty cookie).
*/
ASSERT((type == DOP_SEND_SENDER || type == DOP_SEND_SENDER_TT)
- ? (is_pid(tuple[2]) && (dep->dflags & DFLAG_SEND_SENDER))
+ ? is_pid(tuple[2])
: tuple[2] == am_Empty);
#ifdef ERTS_DIST_MSG_DBG
dist_msg_dbg(edep, "MSG", buf, orig_len);
#endif
- to = tuple[3];
- if (is_not_pid(to))
- goto invalid_message;
- rp = erts_proc_lookup(to);
+ from = tuple[2];
+ to = tuple[3];
+ if (is_not_pid(to))
+ goto invalid_message;
+ rp = erts_proc_lookup(to);
- if (rp) {
- erts_queue_dist_message(rp, 0, edep, ede_hfrag, token, am_Empty);
+ if (rp) {
+ erts_queue_dist_message(rp, 0, edep, ede_hfrag, token, from);
} else if (ede_hfrag != NULL) {
erts_free_dist_ext_copy(erts_get_dist_ext(ede_hfrag));
free_message_buffer(ede_hfrag);
@@ -2411,12 +2566,12 @@ int erts_net_message(Port *prt,
#ifdef ERTS_DIST_MSG_DBG
dist_msg_dbg(edep, "ALIAS MSG", buf, orig_len);
#endif
-
- to = tuple[3];
- if (is_not_ref(to))
- goto invalid_message;
-
- erts_proc_sig_send_dist_to_alias(to, edep, ede_hfrag, token);
+ from = tuple[2];
+ to = tuple[3];
+ if (is_not_ref(to)) {
+ goto invalid_message;
+ }
+ erts_proc_sig_send_dist_to_alias(from, to, edep, ede_hfrag, token);
break;
case DOP_PAYLOAD_MONITOR_P_EXIT:
@@ -2852,12 +3007,10 @@ int erts_net_message(Port *prt,
*/
dist_pend_spawn_exit_save_child_result(result,
ref,
- dep->mld);
+ ede.mld);
}
- }
- else if (lnk && !link_inserted) {
- erts_proc_sig_send_link_exit(NULL, THE_NON_VALUE, &ldp->dist,
- am_noconnection, NIL);
+ } else if (lnk && !link_inserted) {
+ erts_proc_sig_send_link_exit_noconnection(&ldp->dist);
}
break;
@@ -2898,6 +3051,9 @@ data_error:
erts_kill_dist_connection(dep, conn_id);
ERTS_CHK_NO_PROC_LOCKS;
return -1;
+data_error_runlock:
+ erts_de_runlock(dep);
+ goto data_error;
}
static int dsig_send_exit(ErtsDSigSendContext *ctx, Eterm ctl, Eterm msg)
@@ -3003,11 +3159,17 @@ retry:
goto fail;
}
- if (no_suspend && proc) {
- if (erts_atomic32_read_acqb(&dep->qflgs) & ERTS_DE_QFLG_BUSY) {
- res = ERTS_DSIG_PREP_WOULD_SUSPEND;
- goto fail;
- }
+ if (!proc || (proc->flags & F_ASYNC_DIST)) {
+ ctx->ignore_busy = !0;
+ }
+ else {
+ ctx->ignore_busy = 0;
+ if (no_suspend) {
+ if (de_qflags_read(dep) & ERTS_DE_QFLG_BUSY) {
+ res = ERTS_DSIG_PREP_WOULD_SUSPEND;
+ goto fail;
+ }
+ }
}
ctx->c_p = proc;
@@ -3181,7 +3343,8 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
+ ((ctx->fragments - 1)
* ERTS_DIST_FRAGMENT_HEADER_SIZE),
ctx->fragments,
- ctx->vlen);
+ ctx->vlen,
+ ctx->ignore_busy);
ctx->alloced_fragments = ctx->fragments;
/* Encode internal version of dist header */
ctx->dhdrp = ctx->extp;
@@ -3332,20 +3495,23 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
ctx->fragments = 0;
}
else {
- Sint qsize = erts_atomic_read_nob(&dep->qsize);
+ Sint qsize = (Sint) erts_atomic_read_nob(&dep->qsize);
erts_aint32_t qflgs;
ErtsProcList *plp = NULL;
Eterm notify_proc = NIL;
Sint obsz;
- int fragments;
+ int fragments, empty_fill;
/* Calculate how many fragments to send. This depends on
the available space in the distr queue and the amount
of remaining reductions. */
for (fragments = 0, obsz = 0;
- fragments < ctx->fragments &&
- ((ctx->reds > 0 && (qsize + obsz) < erts_dist_buf_busy_limit) ||
- ctx->no_trap || ctx->no_suspend);
+ (fragments < ctx->fragments
+ && ((ctx->reds > 0
+ && (ctx->ignore_busy
+ || (qsize + obsz < erts_dist_buf_busy_limit)))
+ || ctx->no_trap
+ || ctx->no_suspend));
fragments++) {
#ifdef DEBUG
int reds = 100;
@@ -3361,33 +3527,27 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
(!ctx->no_trap && !ctx->no_suspend));
erts_mtx_lock(&dep->qlock);
- qsize = erts_atomic_add_read_nob(&dep->qsize, (erts_aint_t) obsz);
- ASSERT(qsize >= obsz);
- qflgs = erts_atomic32_read_nob(&dep->qflgs);
- if (!(qflgs & ERTS_DE_QFLG_BUSY) && qsize >= erts_dist_buf_busy_limit) {
- erts_atomic32_read_bor_relb(&dep->qflgs, ERTS_DE_QFLG_BUSY);
+ update_qsizes(dep, &empty_fill, &qsize, obsz,
+ ctx->ignore_busy ? obsz : 0);
+ qflgs = de_qflags_read(dep);
+ if (!(qflgs & ERTS_DE_QFLG_BUSY)
+ && qsize >= erts_dist_buf_busy_limit) {
+ qflgs = de_qflags_read_set(dep, ERTS_DE_QFLG_BUSY);
qflgs |= ERTS_DE_QFLG_BUSY;
}
- if (qsize == obsz && (qflgs & ERTS_DE_QFLG_REQ_INFO)) {
- /* Previously empty queue and info requested... */
- qflgs = erts_atomic32_read_band_mb(&dep->qflgs,
- ~ERTS_DE_QFLG_REQ_INFO);
- if (qflgs & ERTS_DE_QFLG_REQ_INFO) {
+ if (empty_fill && is_internal_pid(dep->cid)) {
+ erts_aint32_t notify;
+ notify = erts_atomic32_xchg_mb(&dep->notify,
+ (erts_aint32_t) 0);
+ if (notify) {
+ /*
+ * Previously empty queue and notification
+ * requested...
+ */
notify_proc = dep->cid;
ASSERT(is_internal_pid(notify_proc));
}
- /* else: requester will send itself the message... */
- qflgs &= ~ERTS_DE_QFLG_REQ_INFO;
}
- if (!ctx->no_suspend && (qflgs & ERTS_DE_QFLG_BUSY)) {
- erts_mtx_unlock(&dep->qlock);
-
- plp = erts_proclist_create(ctx->c_p);
-
- erts_suspend(ctx->c_p, ERTS_PROC_LOCK_MAIN, NULL);
- suspended = 1;
- erts_mtx_lock(&dep->qlock);
- }
ASSERT(fragments < 2
|| (get_int64(&((char*)ctx->obuf->eiov->iov[1].iov_base)[10])
@@ -3405,30 +3565,41 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
ctx->obuf = &ctx->obuf[fragments];
}
- if (!ctx->no_suspend) {
- qflgs = erts_atomic32_read_nob(&dep->qflgs);
- if (!(qflgs & ERTS_DE_QFLG_BUSY)) {
- if (suspended)
- resume = 1; /* was busy when we started, but isn't now */
+ if ((qflgs & ERTS_DE_QFLG_BUSY)
+ && !ctx->ignore_busy
+ && !ctx->no_suspend) {
+
+ erts_mtx_unlock(&dep->qlock);
+
+ plp = erts_proclist_create(ctx->c_p);
+
+ erts_suspend(ctx->c_p, ERTS_PROC_LOCK_MAIN, NULL);
+ suspended = 1;
+
+ erts_mtx_lock(&dep->qlock);
+
+ qflgs = de_qflags_read(dep);
+ if (qflgs & ERTS_DE_QFLG_BUSY) {
+ /* Enqueue suspended process on dist entry */
+ ASSERT(plp);
+ erts_proclist_store_last(&dep->suspended, plp);
+ }
+ else {
+ resume = 1; /* was busy, 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(DTRACE_CHARBUF_NAME(port_str)),
- "%T", cid);
- erts_snprintf(remote_str, sizeof(DTRACE_CHARBUF_NAME(remote_str)),
- "%T", dep->sysname);
- DTRACE3(dist_port_not_busy, erts_this_node_sysname,
- port_str, remote_str);
- }
+ if (resume && DTRACE_ENABLED(dist_port_not_busy)) {
+ DTRACE_CHARBUF(port_str, 64);
+ DTRACE_CHARBUF(remote_str, 64);
+
+ erts_snprintf(port_str, sizeof(DTRACE_CHARBUF_NAME(port_str)),
+ "%T", cid);
+ erts_snprintf(remote_str, sizeof(DTRACE_CHARBUF_NAME(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 */
- ASSERT(plp);
- erts_proclist_store_last(&dep->suspended, plp);
- }
+ }
}
erts_mtx_unlock(&dep->qlock);
@@ -3646,13 +3817,64 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf)
? ((Sint) 1) \
: ((((Sint) (SZ)) >> 10) & ((Sint) ERTS_PORT_REDS_MASK__)))
+#ifndef DEBUG
+#define ERTS_DBG_CHK_DIST_QSIZE(DEP, PRT)
+#else
+#define ERTS_DBG_CHK_DIST_QSIZE(DEP, PRT) \
+ dbg_check_dist_qsize((DEP), (PRT))
+
+static void
+dbg_check_dist_qsize(DistEntry *dep, Port *prt)
+{
+ int ix;
+ Sint sz = 0, isz = 0, tqsz, qsz;
+ ErtsDistOutputBuf *qs[2];
+
+ ERTS_LC_ASSERT(dep && erts_lc_mtx_is_locked(&dep->qlock));
+ ASSERT(prt && erts_lc_is_port_locked(prt));
+ ERTS_LC_ASSERT((erts_atomic32_read_nob(&prt->sched.flags)
+ & ERTS_PTS_FLG_EXIT)
+ || prt->common.id == dep->cid);
+
+ tqsz = erts_atomic_read_nob(&dep->total_qsize);
+ qsz = erts_atomic_read_nob(&dep->qsize);
+
+ ASSERT(tqsz >= 0);
+ ASSERT(qsz >= 0);
+ ASSERT(tqsz >= qsz);
+
+ qs[0] = dep->out_queue.first;
+ qs[1] = dep->finalized_out_queue.first;
+
+ for (ix = 0; ix < sizeof(qs)/sizeof(qs[0]); ix++) {
+ ErtsDistOutputBuf *obuf = qs[ix];
+ while (obuf) {
+ add_obuf_sizes(obuf, &sz, &isz);
+ obuf = obuf->next;
+ }
+ }
+
+ ASSERT(tqsz == sz);
+ ASSERT(qsz == sz - isz);
+}
+
+#endif
+
int
erts_dist_command(Port *prt, int initial_reds)
{
Sint reds = initial_reds - ERTS_PORT_REDS_DIST_CMD_START;
enum dist_entry_state state;
Uint64 flags;
- Sint qsize, obufsize = 0;
+ /*
+ * 'obufsize' and 'ignore_obufsize' contains the number of bytes removed
+ * from the queue which will be updated (in dep->total_qsize and
+ * dep->qsize) before we return from this function. Note that
+ * 'obufsize' and 'ignore_obufsize' may be negative if we added to the
+ * queue size. This may occur since finalization of a buffer may increase
+ * buffer size.
+ */
+ Sint qsize, obufsize = 0, ignore_obufsize = 0;
ErtsDistOutputQueue oq, foq;
DistEntry *dep = (DistEntry*) erts_prtsd_get(prt, ERTS_PRTSD_DIST_ENTRY);
Uint (*send)(Port *prt, ErtsDistOutputBuf *obuf);
@@ -3688,6 +3910,7 @@ erts_dist_command(Port *prt, int initial_reds)
*/
erts_mtx_lock(&dep->qlock);
+ ERTS_DBG_CHK_DIST_QSIZE(dep, prt);
oq.first = dep->out_queue.first;
oq.last = dep->out_queue.last;
dep->out_queue.first = NULL;
@@ -3699,23 +3922,6 @@ erts_dist_command(Port *prt, int initial_reds)
dep->finalized_out_queue.first = NULL;
dep->finalized_out_queue.last = NULL;
-#ifdef DEBUG
- {
- Uint sz = 0;
- ErtsDistOutputBuf *curr = oq.first;
- while (curr) {
- sz += size_obuf(curr);
- curr = curr->next;
- }
- curr = foq.first;
- while (curr) {
- sz += size_obuf(curr);
- curr = curr->next;
- }
- ASSERT(sz <= erts_atomic_read_nob(&dep->qsize));
- }
-#endif
-
sched_flags = erts_atomic32_read_nob(&prt->sched.flags);
if (reds < 0)
@@ -3726,7 +3932,7 @@ erts_dist_command(Port *prt, int initial_reds)
do {
Uint size;
ErtsDistOutputBuf *fob;
- obufsize += size_obuf(foq.first);
+ add_obuf_sizes(foq.first, &obufsize, &ignore_obufsize);
size = (*send)(prt, foq.first);
erts_atomic64_inc_nob(&dep->out);
esdp->io.out += (Uint64) size;
@@ -3754,9 +3960,9 @@ erts_dist_command(Port *prt, int initial_reds)
ob = oq.first;
ASSERT(ob);
do {
- obufsize += size_obuf(ob);
+ add_obuf_sizes(ob, &obufsize, &ignore_obufsize);
reds = erts_encode_ext_dist_header_finalize(ob, dep, flags, reds);
- obufsize -= size_obuf(ob);
+ subtract_obuf_sizes(ob, &obufsize, &ignore_obufsize);
if (reds < 0)
break; /* finalize needs to be restarted... */
last_finalized = ob;
@@ -3794,12 +4000,11 @@ erts_dist_command(Port *prt, int initial_reds)
int preempt = 0;
while (oq.first && !preempt) {
ErtsDistOutputBuf *fob;
- Uint size, obsz;
- obufsize += size_obuf(oq.first);
+ Uint size;
+ add_obuf_sizes(oq.first, &obufsize, &ignore_obufsize);
reds = erts_encode_ext_dist_header_finalize(oq.first, dep, flags, reds);
- obsz = size_obuf(oq.first);
- obufsize -= obsz;
if (reds < 0) { /* finalize needs to be restarted... */
+ subtract_obuf_sizes(oq.first, &obufsize, &ignore_obufsize);
preempt = 1;
break;
}
@@ -3808,7 +4013,6 @@ erts_dist_command(Port *prt, int initial_reds)
esdp->io.out += (Uint64) size;
reds -= ERTS_PORT_REDS_DIST_CMD_DATA(size);
fob = oq.first;
- obufsize += obsz;
oq.first = oq.first->next;
free_dist_obuf(fob, !0);
sched_flags = erts_atomic32_read_nob(&prt->sched.flags);
@@ -3834,18 +4038,17 @@ erts_dist_command(Port *prt, int initial_reds)
/*
* Everything that was buffered when we started have now been
* written to the port. If port isn't busy but dist entry is
- * and we havn't got too muched queued on dist entry, set
+ * and we haven't got too muched queued on dist entry, set
* dist entry in a non-busy state and resume suspended
* processes.
*/
erts_mtx_lock(&dep->qlock);
- de_busy = !!(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_BUSY);
- qsize = (Sint) erts_atomic_add_read_nob(&dep->qsize,
- (erts_aint_t) -obufsize);
- ASSERT(qsize >= 0);
- obufsize = 0;
+ de_busy = !!(de_qflags_read(dep) & ERTS_DE_QFLG_BUSY);
+ update_qsizes(dep, NULL, &qsize, -obufsize, -ignore_obufsize);
+ obufsize = ignore_obufsize = 0;
if (!(sched_flags & ERTS_PTS_FLG_BUSY_PORT)
- && de_busy && qsize < erts_dist_buf_busy_limit) {
+ && de_busy
+ && qsize < erts_dist_buf_busy_limit) {
int resumed;
ErtsProcList *suspendees = get_suspended_on_de(dep, ERTS_DE_QFLG_BUSY);
erts_mtx_unlock(&dep->qlock);
@@ -3861,17 +4064,7 @@ erts_dist_command(Port *prt, int initial_reds)
done:
- if (obufsize != 0) {
- erts_mtx_lock(&dep->qlock);
-#ifdef DEBUG
- qsize = (Sint) erts_atomic_add_read_nob(&dep->qsize,
- (erts_aint_t) -obufsize);
- ASSERT(qsize >= 0);
-#else
- erts_atomic_add_nob(&dep->qsize, (erts_aint_t) -obufsize);
-#endif
- erts_mtx_unlock(&dep->qlock);
- }
+ ASSERT(!ignore_obufsize || obufsize);
ASSERT(!!foq.first == !!foq.last);
ASSERT(!dep->finalized_out_queue.first);
@@ -3882,7 +4075,21 @@ erts_dist_command(Port *prt, int initial_reds)
dep->finalized_out_queue.last = foq.last;
}
- /* Avoid wrapping reduction counter... */
+ if (obufsize != 0) {
+ erts_mtx_lock(&dep->qlock);
+ update_qsizes(dep, NULL, NULL, -obufsize, -ignore_obufsize);
+ ERTS_DBG_CHK_DIST_QSIZE(dep, prt);
+ erts_mtx_unlock(&dep->qlock);
+ }
+#ifdef DEBUG
+ else {
+ erts_mtx_lock(&dep->qlock);
+ ERTS_DBG_CHK_DIST_QSIZE(dep, prt);
+ erts_mtx_unlock(&dep->qlock);
+ }
+#endif
+
+ /* Avoid wrapping reduction counter... */
if (reds < INT_MIN/2)
reds = INT_MIN/2;
@@ -3912,7 +4119,7 @@ erts_dist_command(Port *prt, int initial_reds)
while (oq.first) {
ErtsDistOutputBuf *fob = oq.first;
oq.first = oq.first->next;
- obufsize += size_obuf(fob);
+ add_obuf_sizes(fob, &obufsize, &ignore_obufsize);
free_dist_obuf(fob, !0);
}
@@ -3921,14 +4128,15 @@ erts_dist_command(Port *prt, int initial_reds)
}
else {
if (oq.first) {
+ erts_mtx_lock(&dep->qlock);
+ update_qsizes(dep, NULL, NULL, -obufsize, -ignore_obufsize);
+ obufsize = ignore_obufsize = 0;
+
/*
- * Unhandle buffers need to be put back first
+ * Unhandled buffers need to be put back first
* in out_queue.
*/
- erts_mtx_lock(&dep->qlock);
- erts_atomic_add_nob(&dep->qsize, -obufsize);
- obufsize = 0;
- oq.last->next = dep->out_queue.first;
+ oq.last->next = dep->out_queue.first;
dep->out_queue.first = oq.first;
if (!dep->out_queue.last)
dep->out_queue.last = oq.last;
@@ -3944,7 +4152,7 @@ BIF_RETTYPE
dist_ctrl_get_data_notification_1(BIF_ALIST_1)
{
DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(BIF_P);
- erts_aint32_t qflgs;
+ erts_aint32_t notify;
erts_aint_t qsize;
Eterm receiver = NIL;
Uint32 conn_id;
@@ -3957,7 +4165,7 @@ dist_ctrl_get_data_notification_1(BIF_ALIST_1)
/*
* Caller is the only one that can consume from this queue
- * and the only one that can set the req-info flag...
+ * and the only one that can set the notify field...
*/
erts_de_rlock(dep);
@@ -3969,22 +4177,21 @@ dist_ctrl_get_data_notification_1(BIF_ALIST_1)
ASSERT(dep->cid == BIF_P->common.id);
- qflgs = erts_atomic32_read_acqb(&dep->qflgs);
+ notify = erts_atomic32_read_nob(&dep->notify);
- if (!(qflgs & ERTS_DE_QFLG_REQ_INFO)) {
- qsize = erts_atomic_read_acqb(&dep->qsize);
+ if (!notify) {
+ ERTS_THR_READ_MEMORY_BARRIER;
+ qsize = erts_atomic_read_nob(&dep->total_qsize);
ASSERT(qsize >= 0);
if (qsize > 0)
receiver = BIF_P->common.id; /* Notify ourselves... */
- else { /* Empty queue; set req-info flag... */
- qflgs = erts_atomic32_read_bor_mb(&dep->qflgs,
- ERTS_DE_QFLG_REQ_INFO);
- qsize = erts_atomic_read_acqb(&dep->qsize);
+ else { /* Empty queue; set the notify field... */
+ notify = erts_atomic32_xchg_mb(&dep->notify, (erts_aint32_t) !0);
+ qsize = erts_atomic_read_nob(&dep->total_qsize);
ASSERT(qsize >= 0);
if (qsize > 0) {
- qflgs = erts_atomic32_read_band_mb(&dep->qflgs,
- ~ERTS_DE_QFLG_REQ_INFO);
- if (qflgs & ERTS_DE_QFLG_REQ_INFO)
+ notify = erts_atomic32_xchg_mb(&dep->notify, (erts_aint32_t) 0);
+ if (notify)
receiver = BIF_P->common.id; /* Notify ourselves... */
/* else: someone else will notify us... */
}
@@ -4172,7 +4379,7 @@ dist_get_stat_1(BIF_ALIST_1)
}
read = (Sint64) erts_atomic64_read_nob(&dep->in);
write = (Sint64) erts_atomic64_read_nob(&dep->out);
- pend = (Sint64) erts_atomic_read_nob(&dep->qsize);
+ pend = (Sint64) erts_atomic_read_nob(&dep->total_qsize);
erts_de_runlock(dep);
@@ -4227,10 +4434,19 @@ dist_ctrl_get_data_1(BIF_ALIST_1)
{
DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(BIF_P);
const Sint initial_reds = ERTS_BIF_REDS_LEFT(BIF_P);
- Sint reds = initial_reds, obufsize = 0, ix, vlen;
+ Sint reds = initial_reds, ix, vlen;
+ /*
+ * 'obufsize' and 'ignore_obufsize' contains the number of bytes removed
+ * from the queue which will be updated (in dep->total_qsize and
+ * dep->qsize) before we return from this function. Note that
+ * 'obufsize' and 'ignore_obufsize' may be negative if we added to the
+ * queue size. This may occur since finalization of a buffer may increase
+ * buffer size.
+ */
+ Sint obufsize = 0, ignore_obufsize = 0;
ErtsDistOutputBuf *obuf;
Eterm *hp, res;
- erts_aint_t qsize;
+ Sint qsize;
Uint32 conn_id, get_size;
Uint hsz = 0, data_sz;
SysIOVec *iov;
@@ -4269,7 +4485,7 @@ dist_ctrl_get_data_1(BIF_ALIST_1)
{
if (!dep->tmp_out_queue.first) {
ASSERT(!dep->tmp_out_queue.last);
- qsize = erts_atomic_read_acqb(&dep->qsize);
+ qsize = (Sint) erts_atomic_read_acqb(&dep->total_qsize);
if (qsize > 0) {
erts_mtx_lock(&dep->qlock);
dep->tmp_out_queue.first = dep->out_queue.first;
@@ -4288,13 +4504,16 @@ dist_ctrl_get_data_1(BIF_ALIST_1)
}
obuf = dep->tmp_out_queue.first;
- obufsize += size_obuf(obuf);
+ add_obuf_sizes(obuf, &obufsize, &ignore_obufsize);
reds = erts_encode_ext_dist_header_finalize(obuf, dep, dep->dflags, reds);
- obufsize -= size_obuf(obuf);
+ subtract_obuf_sizes(obuf, &obufsize, &ignore_obufsize);
if (reds < 0) { /* finalize needs to be restarted... */
erts_de_runlock(dep);
- if (obufsize)
- erts_atomic_add_nob(&dep->qsize, (erts_aint_t) -obufsize);
+ if (obufsize) {
+ erts_mtx_lock(&dep->qlock);
+ update_qsizes(dep, NULL, NULL, -obufsize, -ignore_obufsize);
+ erts_mtx_unlock(&dep->qlock);
+ }
ERTS_BIF_YIELD1(BIF_TRAP_EXPORT(BIF_dist_ctrl_get_data_1),
BIF_P, BIF_ARG_1);
}
@@ -4375,16 +4594,18 @@ dist_ctrl_get_data_1(BIF_ALIST_1)
hp += 2;
}
- obufsize += size_obuf(obuf);
+ add_obuf_sizes(obuf, &obufsize, &ignore_obufsize);
- qsize = erts_atomic_add_read_nob(&dep->qsize, (erts_aint_t) -obufsize);
+ erts_mtx_lock(&dep->qlock);
- ASSERT(qsize >= 0);
+ update_qsizes(dep, NULL, &qsize, -obufsize, -ignore_obufsize);
- if (qsize < erts_dist_buf_busy_limit/2
- && (erts_atomic32_read_acqb(&dep->qflgs) & ERTS_DE_QFLG_BUSY)) {
+ if (qsize >= erts_dist_buf_busy_limit/2
+ || !(de_qflags_read(dep) & ERTS_DE_QFLG_BUSY)) {
+ erts_mtx_unlock(&dep->qlock);
+ }
+ else {
ErtsProcList *resume_procs = NULL;
- erts_mtx_lock(&dep->qlock);
resume_procs = get_suspended_on_de(dep, ERTS_DE_QFLG_BUSY);
erts_mtx_unlock(&dep->qlock);
if (resume_procs) {
@@ -4439,8 +4660,8 @@ static void kill_connection(DistEntry *dep)
dep->state = ERTS_DE_STATE_EXITING;
erts_mtx_lock(&dep->qlock);
- ASSERT(!(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_EXIT));
- erts_atomic32_read_bor_nob(&dep->qflgs, ERTS_DE_QFLG_EXIT);
+ ASSERT(!(de_qflags_read(dep) & ERTS_DE_QFLG_EXIT));
+ de_qflags_read_set(dep, ERTS_DE_QFLG_EXIT);
erts_mtx_unlock(&dep->qlock);
if (is_internal_port(dep->cid))
@@ -4654,13 +4875,13 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
if (!is_node_name_atom(BIF_ARG_1))
goto error;
- if (BIF_ARG_1 == am_Noname) /* cant use this name !! */
+ if (BIF_ARG_1 == am_Noname) /* can't use this name !! */
goto error;
if (erts_is_alive) /* must not be alive! */
goto error;
/* Check that all trap functions are defined !! */
- if (dmonitor_node_trap->addresses[0] == NULL) {
+ if (dmonitor_node_trap->dispatch.addresses[0] == NULL) {
goto error;
}
@@ -4689,7 +4910,8 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
erts_set_this_node(BIF_ARG_1, (Uint32) creation);
erts_this_dist_entry->creation = creation;
erts_is_alive = 1;
- send_nodes_mon_msgs(NULL, am_nodeup, BIF_ARG_1, am_visible, NIL);
+ send_nodes_mon_msgs(NULL, am_nodeup, BIF_ARG_1, ~((Uint32) 0),
+ am_visible, NIL);
erts_proc_lock(net_kernel, ERTS_PROC_LOCKS_ALL);
/* By setting F_DISTRIBUTION on net_kernel,
@@ -4722,6 +4944,36 @@ BIF_RETTYPE setnode_2(BIF_ALIST_2)
}
/*
+ * erts_is_this_node_alive() returns the same result as erlang:is_alive()
+ */
+int
+erts_is_this_node_alive(void)
+{
+ Eterm tmp_heap[3];
+ Eterm dyn_name_key, dyn_name_value;
+
+ /*
+ * erts_is_alive is only non zero if a node name has been set. Not if
+ * dynamic node name has been enabled.
+ */
+ if (erts_is_alive) {
+ return !0;
+ }
+
+ /*
+ * A persistent term with key '{erts_internal, dynamic_node_name}' has been
+ * set if dynamic node name has been enabled.
+ */
+ dyn_name_key = TUPLE2(&tmp_heap[0], am_erts_internal, am_dynamic_node_name);
+ dyn_name_value = erts_persistent_term_get(dyn_name_key);
+ if (is_value(dyn_name_value) && dyn_name_value != am_false) {
+ return !0;
+ }
+
+ return 0;
+}
+
+/*
* erts_internal:create_dist_channel/4 is used by
* erlang:setnode/3.
*/
@@ -4731,7 +4983,6 @@ typedef struct {
int de_locked;
Uint64 dflags;
Uint32 creation;
- Uint version;
Eterm setup_pid;
Process *net_kernel;
} ErtsSetupConnDistCtrl;
@@ -4750,7 +5001,6 @@ BIF_RETTYPE erts_internal_create_dist_channel_3(BIF_ALIST_3)
{
BIF_RETTYPE ret;
Uint64 flags;
- Uint version;
Uint32 creation;
Eterm *hp, res_tag = THE_NON_VALUE, res = THE_NON_VALUE;
DistEntry *dep = NULL;
@@ -4783,7 +5033,7 @@ BIF_RETTYPE erts_internal_create_dist_channel_3(BIF_ALIST_3)
if (!is_internal_port(BIF_ARG_2) && !is_internal_pid(BIF_ARG_2))
goto badarg;
- if (!is_tuple_arity(BIF_ARG_3, 3))
+ if (!is_tuple_arity(BIF_ARG_3, 2))
goto badarg;
tpl = tuple_val(BIF_ARG_3);
@@ -4792,16 +5042,8 @@ BIF_RETTYPE erts_internal_create_dist_channel_3(BIF_ALIST_3)
if (!term_to_Uint64(tpl[1], &flags))
goto badarg;
- /* Version... */
- if (!is_small(tpl[2]))
- goto badarg;
- version = unsigned_val(tpl[2]);
-
- if (version == 0)
- goto badarg;
-
/* Creation... */
- if (!term_to_Uint32(tpl[3], &creation))
+ if (!term_to_Uint32(tpl[2], &creation))
goto badarg;
if (~flags & DFLAG_DIST_MANDATORY) {
@@ -4846,7 +5088,6 @@ BIF_RETTYPE erts_internal_create_dist_channel_3(BIF_ALIST_3)
scdc.de_locked = 1;
scdc.dflags = flags;
scdc.creation = creation;
- scdc.version = version;
scdc.setup_pid = BIF_P->common.id;
scdc.net_kernel = net_kernel;
@@ -4876,7 +5117,6 @@ BIF_RETTYPE erts_internal_create_dist_channel_3(BIF_ALIST_3)
scdcp->de_locked = 0;
scdcp->dflags = flags;
scdcp->creation = creation;
- scdcp->version = version;
scdcp->setup_pid = BIF_P->common.id;
scdcp->net_kernel = net_kernel;
@@ -4939,25 +5179,29 @@ BIF_RETTYPE erts_internal_create_dist_channel_3(BIF_ALIST_3)
: dist_port_command);
ASSERT(dep->send);
- /*
- * Dist-ports do not use the "busy port message queue" functionality, but
- * instead use "busy dist entry" functionality.
- */
- {
- ErlDrvSizeT disable = ERL_DRV_BUSY_MSGQ_DISABLED;
- erl_drv_busy_msgq_limits(ERTS_Port2ErlDrvPort(pp), &disable, NULL);
- }
-
conn_id = dep->connection_id;
set_res = setup_connection_epiloge_rwunlock(BIF_P, dep, BIF_ARG_2, flags,
creation, BIF_P->common.id,
net_kernel);
/* Dec of refc on net_kernel by setup_connection_epiloge_rwunlock() */
net_kernel = NULL;
- if (set_res == 0)
+ if (set_res == 0) {
+ erts_atomic32_read_band_nob(&pp->state, ~ERTS_PORT_SFLG_DISTRIBUTION);
+ erts_prtsd_set(pp, ERTS_PRTSD_DIST_ENTRY, NULL);
+ erts_prtsd_set(pp, ERTS_PRTSD_CONN_ID, NULL);
goto badarg;
+ }
de_locked = 0;
+ /*
+ * Dist-ports do not use the "busy port message queue" functionality,
+ * but instead use "busy dist entry" functionality.
+ */
+ {
+ ErlDrvSizeT disable = ERL_DRV_BUSY_MSGQ_DISABLED;
+ erl_drv_busy_msgq_limits(ERTS_Port2ErlDrvPort(pp), &disable, NULL);
+ }
+
hp = HAlloc(BIF_P, 3 + ERTS_DHANDLE_SIZE);
res = erts_build_dhandle(&hp, &BIF_P->off_heap, dep, conn_id);
res_tag = am_ok; /* Connection up */
@@ -5017,7 +5261,6 @@ setup_connection_epiloge_rwunlock(Process *c_p, DistEntry *dep,
Process *net_kernel)
{
Eterm notify_proc = NIL;
- erts_aint32_t qflgs;
ErtsProcLocks nk_locks;
int success = 0;
@@ -5053,16 +5296,18 @@ setup_connection_epiloge_rwunlock(Process *c_p, DistEntry *dep,
erts_set_dist_entry_connected(dep, ctrlr, flags);
notify_proc = NIL;
- if (erts_atomic_read_nob(&dep->qsize)) {
+ if (erts_atomic_read_nob(&dep->total_qsize)) {
if (is_internal_port(dep->cid)) {
erts_schedule_dist_command(NULL, dep);
}
else {
- qflgs = erts_atomic32_read_nob(&dep->qflgs);
- if (qflgs & ERTS_DE_QFLG_REQ_INFO) {
- qflgs = erts_atomic32_read_band_mb(&dep->qflgs,
- ~ERTS_DE_QFLG_REQ_INFO);
- if (qflgs & ERTS_DE_QFLG_REQ_INFO) {
+ erts_aint32_t notify;
+ ERTS_THR_READ_MEMORY_BARRIER;
+ notify = erts_atomic32_read_nob(&dep->notify);
+ if (notify) {
+ notify = erts_atomic32_xchg_mb(&dep->notify,
+ (erts_aint32_t) 0);
+ if (notify) {
notify_proc = dep->cid;
ASSERT(is_internal_pid(notify_proc));
}
@@ -5080,6 +5325,7 @@ setup_connection_epiloge_rwunlock(Process *c_p, DistEntry *dep,
send_nodes_mon_msgs(c_p,
am_nodeup,
dep->sysname,
+ dep->connection_id,
flags & DFLAG_PUBLISHED ? am_visible : am_hidden,
NIL);
@@ -5171,17 +5417,18 @@ BIF_RETTYPE erts_internal_get_dflags_0(BIF_ALIST_0)
{
if (erts_dflags_test_remove_hopefull_flags) {
/* For internal emulator tests only! */
+ const Uint64 mask = ~erts_dflags_test_remove_hopefull_flags;
Eterm *hp, **hpp = NULL;
Uint sz = 0, *szp = &sz;
Eterm res;
while (1) {
res = erts_bld_tuple(hpp, szp, 6,
am_erts_dflags,
- erts_bld_uint64(hpp, szp, DFLAG_DIST_DEFAULT & ~DFLAG_DIST_HOPEFULLY),
- erts_bld_uint64(hpp, szp, DFLAG_DIST_MANDATORY & ~DFLAG_DIST_HOPEFULLY),
- erts_bld_uint64(hpp, szp, DFLAG_DIST_ADDABLE & ~DFLAG_DIST_HOPEFULLY),
- erts_bld_uint64(hpp, szp, DFLAG_DIST_REJECTABLE & ~DFLAG_DIST_HOPEFULLY),
- erts_bld_uint64(hpp, szp, DFLAG_DIST_STRICT_ORDER & ~DFLAG_DIST_HOPEFULLY));
+ erts_bld_uint64(hpp, szp, DFLAG_DIST_DEFAULT & mask),
+ erts_bld_uint64(hpp, szp, DFLAG_DIST_MANDATORY & mask),
+ erts_bld_uint64(hpp, szp, DFLAG_DIST_ADDABLE & mask),
+ erts_bld_uint64(hpp, szp, DFLAG_DIST_REJECTABLE & mask),
+ erts_bld_uint64(hpp, szp, DFLAG_DIST_STRICT_ORDER & mask));
if (hpp) {
ASSERT(is_value(res));
return res;
@@ -5280,6 +5527,7 @@ Sint erts_abort_pending_connection_rwunlock(DistEntry* dep,
ASSERT(!dep->finalized_out_queue.first);
resume_procs = get_suspended_on_de(dep, ERTS_DE_QFLGS_ALL);
erts_mtx_unlock(&dep->qlock);
+ erts_atomic32_set_relb(&dep->notify, 0);
erts_atomic_set_nob(&dep->dist_cmd_scheduled, 0);
dep->send = NULL;
@@ -5819,38 +6067,54 @@ BIF_RETTYPE node_0(BIF_ALIST_0)
BIF_RET(erts_this_dist_entry->sysname);
}
-
/**********************************************************************/
/* nodes() -> [ Node ] */
-#if 0 /* Done in erlang.erl instead. */
+static BIF_RETTYPE nodes(Process *c_p, Eterm node_types, Eterm options);
+
BIF_RETTYPE nodes_0(BIF_ALIST_0)
{
- return nodes_1(BIF_P, am_visible);
+ return nodes(BIF_P, am_visible, THE_NON_VALUE);
}
-#endif
-
BIF_RETTYPE nodes_1(BIF_ALIST_1)
{
+ return nodes(BIF_P, BIF_ARG_1, THE_NON_VALUE);
+}
+
+BIF_RETTYPE nodes_2(BIF_ALIST_2)
+{
+ return nodes(BIF_P, BIF_ARG_1, BIF_ARG_2);
+}
+
+typedef struct {
+ Eterm name;
+ Eterm type;
+ Uint32 cid;
+} ErtsNodeInfo;
+
+static BIF_RETTYPE
+nodes(Process *c_p, Eterm node_types, Eterm options)
+{
+ BIF_RETTYPE ret_val;
+ ErtsNodeInfo *eni, *eni_start = NULL, *eni_end;
Eterm result;
- int length;
- Eterm* hp;
+ Uint length;
int not_connected = 0;
int visible = 0;
int hidden = 0;
int this = 0;
- DeclareTmpHeap(buf,2,BIF_P); /* For one cons-cell */
+ int node_type = 0;
+ int connection_id = 0;
+ int xinfo = 0;
+ Eterm tmp_heap[2]; /* For one cons-cell */
DistEntry *dep;
- Eterm arg_list = BIF_ARG_1;
-#ifdef DEBUG
- Eterm* endp;
-#endif
+ Eterm arg_list;
- UseTmpHeap(2,BIF_P);
-
- if (is_atom(BIF_ARG_1))
- arg_list = CONS(buf, BIF_ARG_1, NIL);
+ if (is_atom(node_types))
+ arg_list = CONS(&tmp_heap[0], node_types, NIL);
+ else
+ arg_list = node_types;
while (is_list(arg_list)) {
switch(CAR(list_val(arg_list))) {
@@ -5859,13 +6123,43 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
case am_known: visible = hidden = not_connected = this = 1; break;
case am_this: this = 1; break;
case am_connected: visible = hidden = 1; break;
- default: goto error; break;
+ default: goto badarg; break;
}
arg_list = CDR(list_val(arg_list));
}
if (is_not_nil(arg_list)) {
- goto error;
+ goto badarg;
+ }
+
+ if (is_value(options)) {
+ if (is_not_map(options)) {
+ goto badarg;
+ }
+ else {
+ Sint no_opts = 0;
+ const Eterm *conn_idp = erts_maps_get(am_connection_id, options);
+ const Eterm *node_typep = erts_maps_get(am_node_type, options);
+ if (conn_idp) {
+ switch (*conn_idp) {
+ case am_true: connection_id = !0; break;
+ case am_false: connection_id = 0; break;
+ default: goto badarg;
+ }
+ no_opts++;
+ }
+ if (node_typep) {
+ switch (*node_typep) {
+ case am_true: node_type = !0; break;
+ case am_false: node_type = 0; break;
+ default: goto badarg;
+ }
+ no_opts++;
+ }
+ if (no_opts != erts_map_size(options))
+ goto badarg; /* got invalid options... */
+ xinfo = !0;
+ }
}
length = 0;
@@ -5890,59 +6184,130 @@ BIF_RETTYPE nodes_1(BIF_ALIST_1)
if (length == 0) {
erts_rwmtx_runlock(&erts_dist_table_rwmtx);
- goto done;
+ ERTS_BIF_PREP_RET(ret_val, NIL);
+ return ret_val;
}
- hp = HAlloc(BIF_P, 2*length);
+ eni_start = eni = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsNodeInfo)*length);
-#ifdef DEBUG
- endp = hp + length*2;
-#endif
- if(not_connected) {
- for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
- if (dep != erts_this_dist_entry) {
- result = CONS(hp, dep->sysname, result);
- hp += 2;
- }
+ if (this) {
+ eni->name = erts_this_dist_entry->sysname;
+ eni->type = am_this;
+ eni->cid = ~((Uint32) 0);
+ eni++;
+ }
+
+ if (visible) {
+ for (dep = erts_visible_dist_entries; dep; dep = dep->next) {
+ eni->name = dep->sysname;
+ eni->type = am_visible;
+ eni->cid = dep->connection_id;
+ ASSERT(eni->cid >= 0);
+ eni++;
}
- for(dep = erts_pending_dist_entries; dep; dep = dep->next) {
- result = CONS(hp, dep->sysname, result);
- hp += 2;
- }
}
- if(hidden)
- for(dep = erts_hidden_dist_entries; dep; dep = dep->next) {
- result = CONS(hp, dep->sysname, result);
- hp += 2;
- }
- if(visible)
- for(dep = erts_visible_dist_entries; dep; dep = dep->next) {
- result = CONS(hp, dep->sysname, result);
- hp += 2;
- }
- if(this) {
- result = CONS(hp, erts_this_dist_entry->sysname, result);
- hp += 2;
+
+ if (hidden) {
+ for (dep = erts_hidden_dist_entries; dep; dep = dep->next) {
+ eni->name = dep->sysname;
+ eni->type = am_hidden;
+ eni->cid = dep->connection_id;
+ eni++;
+ }
+ }
+
+ if (not_connected) {
+ for (dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
+ if (dep != erts_this_dist_entry) {
+ eni->name = dep->sysname;
+ eni->type = am_known;
+ eni->cid = ~((Uint32) 0);
+ eni++;
+ }
+ }
+ for (dep = erts_pending_dist_entries; dep; dep = dep->next) {
+ eni->name = dep->sysname;
+ eni->type = am_known;
+ eni->cid = ~((Uint32) 0);
+ eni++;
+ }
}
- ASSERT(endp == hp);
+
erts_rwmtx_runlock(&erts_dist_table_rwmtx);
-done:
- UnUseTmpHeap(2,BIF_P);
- BIF_RET(result);
+ eni_end = eni;
-error:
- UnUseTmpHeap(2,BIF_P);
- BIF_ERROR(BIF_P,BADARG);
-}
+ result = NIL;
+ if (!xinfo) {
+ Eterm *hp = HAlloc(c_p, 2*length);
+ for (eni = eni_start; eni < eni_end; eni++) {
+ result = CONS(hp, eni->name, result);
+ hp += 2;
+ }
+ }
+ else {
+ Eterm ks[2], *hp, keys_tuple = THE_NON_VALUE;
+ Uint map_size = 0, el_xtra, xtra;
+ ErtsHeapFactory hfact;
-/**********************************************************************/
-/* is_alive() -> Bool */
+ erts_factory_proc_init(&hfact, c_p);
-BIF_RETTYPE is_alive_0(BIF_ALIST_0)
-{
- Eterm res = erts_is_alive ? am_true : am_false;
- BIF_RET(res);
+ if (connection_id) {
+ ks[map_size++] = am_connection_id;
+ }
+ if (node_type) {
+ ks[map_size++] = am_node_type;
+ }
+
+ el_xtra = 3 + 2 + MAP_HEADER_FLATMAP_SZ + map_size;
+ xtra = length*el_xtra;
+
+ for (eni = eni_start; eni < eni_end; eni++) {
+ Eterm vs[2], info_map, tuple;
+ map_size = 0;
+ if (connection_id) {
+ Eterm cid;
+ if (eni->cid == ~((Uint32) 0))
+ cid = am_undefined;
+ else if (IS_USMALL(0, (Uint) eni->cid))
+ cid = make_small((Uint) eni->cid);
+ else {
+ hp = erts_produce_heap(&hfact, BIG_UINT_HEAP_SIZE, xtra);
+ cid = uint_to_big((Uint) eni->cid, hp);
+ }
+ vs[map_size++] = cid;
+ }
+ if (node_type) {
+ vs[map_size++] = eni->type;
+ }
+
+ info_map = erts_map_from_sorted_ks_and_vs(&hfact, ks, vs,
+ map_size, &keys_tuple);
+
+ hp = erts_produce_heap(&hfact, 3+2, xtra);
+
+ tuple = TUPLE2(hp, eni->name, info_map);
+ hp += 3;
+ result = CONS(hp, tuple, result);
+ xtra -= el_xtra;
+ }
+
+ erts_factory_close(&hfact);
+ }
+
+ erts_free(ERTS_ALC_T_TMP, (void *) eni_start);
+
+ if (length > 10) {
+ Uint reds = length / 10;
+ BUMP_REDS(c_p, reds);
+ }
+
+ ERTS_BIF_PREP_RET(ret_val, result);
+ return ret_val;
+
+badarg:
+ ERTS_BIF_PREP_ERROR(ret_val, c_p, BADARG);
+ return ret_val;
}
/**********************************************************************/
@@ -5978,7 +6343,7 @@ monitor_node(Process* p, Eterm Node, Eterm Bool, Eterm Options)
if (is_not_atom(Node))
goto badarg;
- if (erts_this_node->sysname == am_Noname && Node != am_Noname) {
+ if (Node != am_Noname && !erts_is_this_node_alive()) {
ERTS_BIF_PREP_ERROR(ret, p, EXC_NOTALIVE);
goto do_return;
}
@@ -6168,6 +6533,8 @@ BIF_RETTYPE net_kernel_dflag_unicode_io_1(BIF_ALIST_1)
#define ERTS_NODES_MON_OPT_TYPE_VISIBLE (((Uint16) 1) << 0)
#define ERTS_NODES_MON_OPT_TYPE_HIDDEN (((Uint16) 1) << 1)
#define ERTS_NODES_MON_OPT_DOWN_REASON (((Uint16) 1) << 2)
+#define ERTS_NODES_MON_OPT_INFO_MAP (((Uint16) 1) << 3)
+#define ERTS_NODES_MON_OPT_CONN_ID (((Uint16) 1) << 4)
#define ERTS_NODES_MON_OPT_TYPES \
(ERTS_NODES_MON_OPT_TYPE_VISIBLE|ERTS_NODES_MON_OPT_TYPE_HIDDEN)
@@ -6197,10 +6564,10 @@ init_nodes_monitors(void)
}
Eterm
-erts_monitor_nodes(Process *c_p, Eterm on, Eterm olist)
+erts_monitor_nodes(Process *c_p, Eterm on, Eterm options)
{
- Eterm key, old_value, opts_list = olist;
- Uint opts = (Uint) 0;
+ Eterm key, old_value;
+ Uint opts = (Uint) ERTS_NODES_MON_OPT_INFO_MAP;
ASSERT(c_p);
ERTS_LC_ASSERT(erts_proc_lc_my_proc_locks(c_p) == ERTS_PROC_LOCK_MAIN);
@@ -6208,55 +6575,63 @@ erts_monitor_nodes(Process *c_p, Eterm on, Eterm olist)
if (on != am_true && on != am_false)
return THE_NON_VALUE;
- if (is_not_nil(opts_list)) {
- int all = 0, visible = 0, hidden = 0;
-
- while (is_list(opts_list)) {
- Eterm *cp = list_val(opts_list);
- Eterm opt = CAR(cp);
- opts_list = CDR(cp);
- if (opt == am_nodedown_reason)
+ if (is_nil(options)) {
+ opts &= ~ERTS_NODES_MON_OPT_INFO_MAP;
+ }
+ else if (is_not_map(options)) {
+ return THE_NON_VALUE;
+ }
+ else {
+ Sint no_opts = 0;
+ const Eterm *l = erts_maps_get(am_list, options);
+ const Eterm *cid = erts_maps_get(am_connection_id, options);
+ const Eterm *nt = erts_maps_get(am_node_type, options);
+ const Eterm *nr = erts_maps_get(am_nodedown_reason, options);
+ if (l) {
+ if (*l == am_true) {
+ opts &= ~ERTS_NODES_MON_OPT_INFO_MAP;
+ }
+ else {
+ return THE_NON_VALUE;
+ }
+ no_opts++;
+ }
+ if (cid) {
+ if (*cid == am_true) {
+ opts |= ERTS_NODES_MON_OPT_CONN_ID;
+ }
+ else if (*cid != am_false) {
+ return THE_NON_VALUE;
+ }
+ no_opts++;
+ }
+ if (nt) {
+ switch (*nt) {
+ case am_visible:
+ opts |= ERTS_NODES_MON_OPT_TYPE_VISIBLE;
+ break;
+ case am_hidden:
+ opts |= ERTS_NODES_MON_OPT_TYPE_HIDDEN;
+ break;
+ case am_all:
+ opts |= ERTS_NODES_MON_OPT_TYPES;
+ break;
+ default:
+ return THE_NON_VALUE;
+ }
+ no_opts++;
+ }
+ if (nr) {
+ if (*nr == am_true) {
opts |= ERTS_NODES_MON_OPT_DOWN_REASON;
- else if (is_tuple(opt)) {
- Eterm* tp = tuple_val(opt);
- if (arityval(tp[0]) != 2)
- return THE_NON_VALUE;
- switch (tp[1]) {
- case am_node_type:
- switch (tp[2]) {
- case am_visible:
- if (hidden || all)
- return THE_NON_VALUE;
- opts |= ERTS_NODES_MON_OPT_TYPE_VISIBLE;
- visible = 1;
- break;
- case am_hidden:
- if (visible || all)
- return THE_NON_VALUE;
- opts |= ERTS_NODES_MON_OPT_TYPE_HIDDEN;
- hidden = 1;
- break;
- case am_all:
- if (visible || hidden)
- return THE_NON_VALUE;
- opts |= ERTS_NODES_MON_OPT_TYPES;
- all = 1;
- break;
- default:
- return THE_NON_VALUE;
- }
- break;
- default:
- return THE_NON_VALUE;
- }
- }
- else {
- return THE_NON_VALUE;
- }
- }
-
- if (is_not_nil(opts_list))
- return THE_NON_VALUE;
+ }
+ else if (*nr != am_false) {
+ return THE_NON_VALUE;
+ }
+ no_opts++;
+ }
+ if (no_opts != erts_map_size(options))
+ return THE_NON_VALUE; /* got invalid options... */
}
key = make_small(opts);
@@ -6349,8 +6724,24 @@ save_nodes_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
return 1;
}
+#define ERTS_MON_NODES_MAX_INFO_LIST_SZ__(MAX_ELEMS) \
+ ((MAX_ELEMS)*(3 /* key/value 2-tuple */ + 2/* cons cell */) \
+ + BIG_UINT_HEAP_SIZE /* connection id value */ \
+ + 4 /* top 3-tuple */)
+#define ERTS_MON_NODES_MAX_INFO_MAP_SZ__(MAX_ELEMS) \
+ ((MAX_ELEMS)*2 /* keys and values */ \
+ + 1 /* key tuple header */ + MAP_HEADER_FLATMAP_SZ /* 3 */ \
+ + BIG_UINT_HEAP_SIZE /* connection id value */ \
+ + 4 /* top 3-tuple */)
+#define ERTS_MON_NODES_MAX_INFO_SZ__(MAX_ELEMS) \
+ ((ERTS_MON_NODES_MAX_INFO_MAP_SZ__((MAX_ELEMS)) \
+ > ERTS_MON_NODES_MAX_INFO_LIST_SZ__((MAX_ELEMS))) \
+ ? ERTS_MON_NODES_MAX_INFO_MAP_SZ__((MAX_ELEMS)) \
+ : ERTS_MON_NODES_MAX_INFO_LIST_SZ__((MAX_ELEMS)))
+
static void
-send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reason)
+send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node,
+ Uint32 connection_id, Eterm type, Eterm reason)
{
Uint opts;
Uint i, no, reason_size;
@@ -6396,7 +6787,8 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas
erts_mtx_unlock(&nodes_monitors_mtx);
for (i = 0; i < no; i++) {
- Eterm tmp_heap[3+2+3+2+4 /* max need */];
+ ErtsHeapFactory hfact;
+ Eterm tmp_heap[ERTS_MON_NODES_MAX_INFO_SZ__(3/* max info elements */)];
Eterm *hp, msg;
Uint hsz;
@@ -6422,49 +6814,119 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas
}
}
+ /*
+ * tmp_heap[] is sized so there will be room for everything
+ * we need assuming no info, a two-tuple info list, or an info
+ * flat map is generated. In case there would be a greater heap
+ * need this will be taken care of by the heap factory...
+ */
+ erts_factory_tmp_init(&hfact,
+ &tmp_heap[0],
+ sizeof(tmp_heap)/sizeof(Uint),
+ ERTS_ALC_T_TMP);
hsz = 0;
- hp = &tmp_heap[0];
if (!opts) {
+ hp = erts_produce_heap(&hfact, 3, 0);
msg = TUPLE2(hp, what, node);
- hp += 3;
}
- else {
+ else { /* Info list or map... */
Eterm tup;
- Eterm info = NIL;
+ Eterm info;
- if (opts & (ERTS_NODES_MON_OPT_TYPE_VISIBLE
- | ERTS_NODES_MON_OPT_TYPE_HIDDEN)) {
+ if (opts & ERTS_NODES_MON_OPT_INFO_MAP) { /* Info map */
+ Uint map_size = 0;
+ Eterm ks[3], vs[3];
- tup = TUPLE2(hp, am_node_type, type);
- hp += 3;
- info = CONS(hp, tup, info);
- hp += 2;
- }
+ if (opts & ERTS_NODES_MON_OPT_CONN_ID) {
+ Eterm cid;
+ if (connection_id == ~((Uint32) 0)) {
+ cid = am_undefined;
+ }
+ else if (IS_USMALL(0, (Uint) connection_id)) {
+ cid = make_small(connection_id);
+ }
+ else {
+ hp = erts_produce_heap(&hfact, BIG_UINT_HEAP_SIZE, 0);
+ cid = uint_to_big(connection_id, hp);
+ }
+ ks[map_size] = am_connection_id;
+ vs[map_size] = cid;
+ map_size++;
+ }
+ if (opts & (ERTS_NODES_MON_OPT_TYPE_VISIBLE
+ | ERTS_NODES_MON_OPT_TYPE_HIDDEN)) {
+ ks[map_size] = am_node_type;
+ vs[map_size] = type;
+ map_size++;
+ }
+ if (what == am_nodedown
+ && (opts & ERTS_NODES_MON_OPT_DOWN_REASON)) {
+ hsz += reason_size;
+ ks[map_size] = am_nodedown_reason;
+ vs[map_size] = reason;
+ map_size++;
+ }
- if (what == am_nodedown
- && (opts & ERTS_NODES_MON_OPT_DOWN_REASON)) {
- hsz += reason_size;
- tup = TUPLE2(hp, am_nodedown_reason, reason);
- hp += 3;
- info = CONS(hp, tup, info);
- hp += 2;
+ info = erts_map_from_sorted_ks_and_vs(&hfact, ks, vs,
+ map_size, NULL);
+ ASSERT(is_value(info));
}
+ else { /* Info list */
+
+ info = NIL;
+ if (opts & (ERTS_NODES_MON_OPT_TYPE_VISIBLE
+ | ERTS_NODES_MON_OPT_TYPE_HIDDEN)) {
+ hp = erts_produce_heap(&hfact, 3 + 2, 0);
+ tup = TUPLE2(hp, am_node_type, type);
+ hp += 3;
+ info = CONS(hp, tup, info);
+ }
+ if (what == am_nodedown
+ && (opts & ERTS_NODES_MON_OPT_DOWN_REASON)) {
+ hp = erts_produce_heap(&hfact, 3 + 2, 0);
+ hsz += reason_size;
+ tup = TUPLE2(hp, am_nodedown_reason, reason);
+ hp += 3;
+ info = CONS(hp, tup, info);
+ }
+
+ if (opts & ERTS_NODES_MON_OPT_CONN_ID) {
+ Eterm cid;
+ if (connection_id == ~((Uint32) 0)) {
+ cid = am_undefined;
+ }
+ else if (IS_USMALL(0, (Uint) connection_id)) {
+ cid = make_small(connection_id);
+ }
+ else {
+ hp = erts_produce_heap(&hfact, BIG_UINT_HEAP_SIZE, 0);
+ cid = uint_to_big(connection_id, hp);
+ }
+ hp = erts_produce_heap(&hfact, 3 + 2, 0);
+ tup = TUPLE2(hp, am_connection_id, cid);
+ hp += 3;
+ info = CONS(hp, tup, info);
+ }
+ }
+
+ hp = erts_produce_heap(&hfact, 4, 0);
msg = TUPLE3(hp, what, node, info);
- hp += 4;
}
- ASSERT(hp - &tmp_heap[0] <= sizeof(tmp_heap)/sizeof(tmp_heap[0]));
- hsz += hp - &tmp_heap[0];
+ hsz += hfact.hp - hfact.hp_start;
+ if (hfact.heap_frags) {
+ ErlHeapFragment *bp;
+ for (bp = hfact.heap_frags; bp; bp = bp->next)
+ hsz += bp->used_size;
+ }
+
+ erts_proc_sig_send_monitor_nodes_msg(nmdp[i].options, nmdp[i].pid,
+ msg, hsz);
- erts_proc_sig_send_persistent_monitor_msg(ERTS_MON_TYPE_NODES,
- nmdp[i].options,
- am_system,
- nmdp[i].pid,
- msg,
- hsz);
+ erts_factory_close(&hfact);
}
if (nmdp != &def_buf[0])
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 6bb35fc8c9..7dabdd4961 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,33 +25,35 @@
#include "erl_node_tables.h"
#include "zlib.h"
-#define DFLAG_PUBLISHED ((Uint64)0x01)
-#define DFLAG_ATOM_CACHE ((Uint64)0x02)
-#define DFLAG_EXTENDED_REFERENCES ((Uint64)0x04)
-#define DFLAG_DIST_MONITOR ((Uint64)0x08)
-#define DFLAG_FUN_TAGS ((Uint64)0x10)
-#define DFLAG_DIST_MONITOR_NAME ((Uint64)0x20)
-#define DFLAG_HIDDEN_ATOM_CACHE ((Uint64)0x40)
-#define DFLAG_NEW_FUN_TAGS ((Uint64)0x80)
-#define DFLAG_EXTENDED_PIDS_PORTS ((Uint64)0x100)
-#define DFLAG_EXPORT_PTR_TAG ((Uint64)0x200)
-#define DFLAG_BIT_BINARIES ((Uint64)0x400)
-#define DFLAG_NEW_FLOATS ((Uint64)0x800)
-#define DFLAG_UNICODE_IO ((Uint64)0x1000)
-#define DFLAG_DIST_HDR_ATOM_CACHE ((Uint64)0x2000)
-#define DFLAG_SMALL_ATOM_TAGS ((Uint64)0x4000)
-#define DFLAG_ETS_COMPRESSED ((Uint64)0x8000) /* internal */
-#define DFLAG_UTF8_ATOMS ((Uint64)0x10000)
-#define DFLAG_MAP_TAG ((Uint64)0x20000)
-#define DFLAG_BIG_CREATION ((Uint64)0x40000)
-#define DFLAG_SEND_SENDER ((Uint64)0x80000)
-#define DFLAG_BIG_SEQTRACE_LABELS ((Uint64)0x100000)
-#define DFLAG_PENDING_CONNECT ((Uint64)0x200000) /* internal */
-#define DFLAG_EXIT_PAYLOAD ((Uint64)0x400000)
-#define DFLAG_FRAGMENTS ((Uint64)0x800000)
-#define DFLAG_HANDSHAKE_23 ((Uint64)0x1000000)
-#define DFLAG_UNLINK_ID ((Uint64)0x2000000)
-#define DFLAG_RESERVED ((Uint64)0xfc000000)
+#define DFLAG_PUBLISHED ((Uint64)0x01)
+#define DFLAG_ATOM_CACHE ((Uint64)0x02)
+#define DFLAG_EXTENDED_REFERENCES ((Uint64)0x04)
+#define DFLAG_DIST_MONITOR ((Uint64)0x08)
+#define DFLAG_FUN_TAGS ((Uint64)0x10)
+#define DFLAG_DIST_MONITOR_NAME ((Uint64)0x20)
+#define DFLAG_HIDDEN_ATOM_CACHE ((Uint64)0x40)
+#define DFLAG_NEW_FUN_TAGS ((Uint64)0x80)
+#define DFLAG_EXTENDED_PIDS_PORTS ((Uint64)0x100)
+#define DFLAG_EXPORT_PTR_TAG ((Uint64)0x200)
+#define DFLAG_BIT_BINARIES ((Uint64)0x400)
+#define DFLAG_NEW_FLOATS ((Uint64)0x800)
+#define DFLAG_UNICODE_IO ((Uint64)0x1000)
+#define DFLAG_DIST_HDR_ATOM_CACHE ((Uint64)0x2000)
+#define DFLAG_SMALL_ATOM_TAGS ((Uint64)0x4000)
+#define DFLAG_ETS_COMPRESSED ((Uint64)0x8000) /* internal */
+#define DFLAG_UTF8_ATOMS ((Uint64)0x10000)
+#define DFLAG_MAP_TAG ((Uint64)0x20000)
+#define DFLAG_BIG_CREATION ((Uint64)0x40000)
+#define DFLAG_SEND_SENDER ((Uint64)0x80000)
+#define DFLAG_BIG_SEQTRACE_LABELS ((Uint64)0x100000)
+#define DFLAG_PENDING_CONNECT ((Uint64)0x200000) /* internal */
+#define DFLAG_EXIT_PAYLOAD ((Uint64)0x400000)
+#define DFLAG_FRAGMENTS ((Uint64)0x800000)
+#define DFLAG_HANDSHAKE_23 ((Uint64)0x1000000)
+#define DFLAG_UNLINK_ID ((Uint64)0x2000000)
+#define DFLAG_MANDATORY_25_DIGEST ((Uint64)0x4000000)
+#define DFLAG_RESERVED ((Uint64)0xf8000000)
+
/*
* As the old handshake only support 32 flag bits, we reserve the remaining
* bits in the lower 32 for changes in the handshake protocol or potentially
@@ -69,21 +71,28 @@
#define DFLAG_DETERMINISTIC DFLAG_ATOM_CACHE
-/* Mandatory flags for distribution */
-#define DFLAG_DIST_MANDATORY (DFLAG_EXTENDED_REFERENCES \
- | DFLAG_EXTENDED_PIDS_PORTS \
- | DFLAG_UTF8_ATOMS \
- | DFLAG_NEW_FUN_TAGS \
- | DFLAG_BIG_CREATION)
+/* Mandatory flags for distribution in OTP 25. */
+#define DFLAG_DIST_MANDATORY_25 (DFLAG_EXTENDED_REFERENCES \
+ | DFLAG_FUN_TAGS \
+ | DFLAG_EXTENDED_PIDS_PORTS \
+ | DFLAG_UTF8_ATOMS \
+ | DFLAG_NEW_FUN_TAGS \
+ | DFLAG_BIG_CREATION \
+ | DFLAG_NEW_FLOATS \
+ | DFLAG_MAP_TAG \
+ | DFLAG_EXPORT_PTR_TAG \
+ | DFLAG_BIT_BINARIES \
+ | DFLAG_HANDSHAKE_23)
+
+/* Mandatory flags for distribution. */
+#define DFLAG_DIST_MANDATORY DFLAG_DIST_MANDATORY_25
/*
* Additional optimistic flags when encoding toward pending connection.
* If remote node (erl_interface) does not support these then we may need
* to transcode messages enqueued before connection setup was finished.
*/
-#define DFLAG_DIST_HOPEFULLY (DFLAG_EXPORT_PTR_TAG \
- | DFLAG_BIT_BINARIES \
- | DFLAG_DIST_MONITOR \
+#define DFLAG_DIST_HOPEFULLY (DFLAG_DIST_MONITOR \
| DFLAG_DIST_MONITOR_NAME \
| DFLAG_SPAWN \
| DFLAG_ALIAS \
@@ -91,22 +100,18 @@
/* Our preferred set of flags. Used for connection setup handshake */
#define DFLAG_DIST_DEFAULT (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY \
- | DFLAG_FUN_TAGS \
- | DFLAG_NEW_FLOATS \
| DFLAG_UNICODE_IO \
| DFLAG_DIST_HDR_ATOM_CACHE \
| DFLAG_SMALL_ATOM_TAGS \
- | DFLAG_UTF8_ATOMS \
- | DFLAG_MAP_TAG \
| DFLAG_SEND_SENDER \
| DFLAG_BIG_SEQTRACE_LABELS \
| DFLAG_EXIT_PAYLOAD \
| DFLAG_FRAGMENTS \
- | DFLAG_HANDSHAKE_23 \
| DFLAG_SPAWN \
| DFLAG_V4_NC \
| DFLAG_ALIAS \
- | DFLAG_UNLINK_ID)
+ | DFLAG_UNLINK_ID \
+ | DFLAG_MANDATORY_25_DIGEST)
/* Flags addable by local distr implementations */
#define DFLAG_DIST_ADDABLE DFLAG_DIST_DEFAULT
@@ -121,14 +126,7 @@
#define DFLAG_DIST_STRICT_ORDER DFLAG_DIST_HDR_ATOM_CACHE
/* All flags that should be enabled when term_to_binary/1 is used. */
-#define TERM_TO_BINARY_DFLAGS (DFLAG_EXTENDED_REFERENCES \
- | DFLAG_NEW_FUN_TAGS \
- | DFLAG_NEW_FLOATS \
- | DFLAG_EXTENDED_PIDS_PORTS \
- | DFLAG_EXPORT_PTR_TAG \
- | DFLAG_BIT_BINARIES \
- | DFLAG_MAP_TAG \
- | DFLAG_BIG_CREATION)
+#define TERM_TO_BINARY_DFLAGS DFLAG_NEW_FLOATS
/* opcodes used in distribution messages */
enum dop {
@@ -218,7 +216,7 @@ extern int erts_is_alive;
#define ERTS_DIST_CTRL_OPT_GET_SIZE ((Uint32) (1 << 0))
/* for emulator internal testing... */
-extern int erts_dflags_test_remove_hopefull_flags;
+extern Uint64 erts_dflags_test_remove_hopefull_flags;
#ifdef DEBUG
#define ERTS_DBG_CHK_NO_DIST_LNK(D, R, L) \
@@ -344,6 +342,7 @@ typedef struct erts_dsig_send_context {
int connect;
int no_suspend;
int no_trap;
+ int ignore_busy;
Eterm ctl;
Eterm msg;
@@ -442,4 +441,7 @@ int erts_auto_connect(DistEntry* dep, Process *proc, ErtsProcLocks proc_locks);
Uint erts_ttb_iov_size(int use_termv, Sint vlen, Uint fragments);
void erts_ttb_iov_init(TTBEncodeContext *ctx, int use_termv, char *ptr,
Sint vlen, Uint fragments, Uint fragments_size);
+
+int erts_is_this_node_alive(void);
+
#endif
diff --git a/erts/emulator/beam/emu/arith_instrs.tab b/erts/emulator/beam/emu/arith_instrs.tab
index 13c33b8f6b..42f71f68fe 100644
--- a/erts/emulator/beam/emu/arith_instrs.tab
+++ b/erts/emulator/beam/emu/arith_instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2020. All Rights Reserved.
+// Copyright Ericsson AB 2017-2021. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -474,7 +474,7 @@ shift.execute(Fail, Dst) {
HRelease(c_p, hp_end, hp);
if (ERTS_UNLIKELY(is_nil(Op1))) {
/*
- * This result must have been only slighty larger
+ * This result must have been only slightly larger
* than allowed since it wasn't caught by the
* previous test.
*/
diff --git a/erts/emulator/beam/emu/beam_emu.c b/erts/emulator/beam/emu/beam_emu.c
index 932e8a2108..258a61e480 100644
--- a/erts/emulator/beam/emu/beam_emu.c
+++ b/erts/emulator/beam/emu/beam_emu.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,9 +107,11 @@
* Special Beam instructions.
*/
-static BeamInstr beam_apply_[2];
-ErtsCodePtr beam_apply; /* beam_apply_[0]; */
-ErtsCodePtr beam_normal_exit; /* beam_apply_[1]; */
+static BeamInstr beam_run_process_[1];
+ErtsCodePtr beam_run_process;
+
+static BeamInstr beam_normal_exit_[1];
+ErtsCodePtr beam_normal_exit;
static BeamInstr beam_exit_[1];
ErtsCodePtr beam_exit;
@@ -120,7 +122,7 @@ ErtsCodePtr beam_continue_exit;
/* NOTE These should be the only variables containing trace instructions.
** Sometimes tests are for the instruction value, and sometimes
-** for the referring variable (one of these), and rouge references
+** for the referring variable (one of these), and rogue references
** will most likely cause chaos.
*/
@@ -140,6 +142,12 @@ ErtsCodePtr beam_exception_trace;
static BeamInstr beam_return_time_trace_[1];
ErtsCodePtr beam_return_time_trace;
+/* The address field of every fun that has no loaded code will point to
+ * beam_unloaded_fun[]. The -1 in beam_unloaded_fun[0] will be interpreted
+ * as an illegal arity when attempting to call a fun. */
+static BeamInstr unloaded_fun_code[4] = {NIL, NIL, -1, 0};
+ErtsCodePtr beam_unloaded_fun = &unloaded_fun_code[3];
+
/*
* All Beam instructions in numerical order.
*/
@@ -412,7 +420,7 @@ void process_main(ErtsSchedulerData *esdp)
if (ERTS_PROC_IS_EXITING(c_p)) {
sys_strcpy(fun_buf, "<exiting>");
} else {
- ErtsCodeMFA *cmfa = erts_find_function_from_pc(c_p->i);
+ const ErtsCodeMFA *cmfa = erts_find_function_from_pc(c_p->i);
if (cmfa) {
dtrace_fun_decode(c_p, cmfa,
NULL, fun_buf);
@@ -445,16 +453,12 @@ void process_main(ErtsSchedulerData *esdp)
* can get the module, function, and arity for the function being
* called from I[-3], I[-2], and I[-1] respectively.
*/
- context_switch_fun:
- /* Add one for the environment of the fun */
- c_p->arity = erts_code_to_codemfa(I)->arity + 1;
- goto context_switch2;
-
context_switch:
- c_p->arity = erts_code_to_codemfa(I)->arity;
-
- context_switch2: /* Entry for fun calls. */
- c_p->current = erts_code_to_codemfa(I);
+ {
+ const ErtsCodeMFA *mfa = erts_code_to_codemfa(I);
+ c_p->arity = mfa->arity;
+ c_p->current = mfa;
+ }
context_switch3:
@@ -533,7 +537,7 @@ void process_main(ErtsSchedulerData *esdp)
HEAVY_SWAPIN;
if (error_handler) {
- I = error_handler->addresses[erts_active_code_ix()];
+ I = error_handler->dispatch.addresses[erts_active_code_ix()];
Goto(*I);
}
}
@@ -575,7 +579,7 @@ void process_main(ErtsSchedulerData *esdp)
OpCase(label_L):
OpCase(on_load):
OpCase(line_I):
- OpCase(int_func_end):
+ OpCase(i_nif_padding):
erts_exit(ERTS_ERROR_EXIT, "meta op\n");
/*
@@ -627,7 +631,7 @@ static void install_bifs(void) {
ep = erts_export_put(entry->module, entry->name, entry->arity);
- ep->info.op = BeamOpCodeAddr(op_i_func_info_IaaI);
+ ep->info.u.op = BeamOpCodeAddr(op_i_func_info_IaaI);
ep->info.mfa.module = entry->module;
ep->info.mfa.function = entry->name;
ep->info.mfa.arity = entry->arity;
@@ -669,11 +673,11 @@ init_emulator_finish(void)
}
#endif
- beam_apply_[0] = BeamOpCodeAddr(op_i_apply);
- beam_apply_[1] = BeamOpCodeAddr(op_normal_exit);
+ beam_run_process_[0] = BeamOpCodeAddr(op_i_apply_only);
+ beam_run_process = (ErtsCodePtr)&beam_run_process_[0];
- beam_apply = (ErtsCodePtr)&beam_apply_[0];
- beam_normal_exit = (ErtsCodePtr)&beam_apply_[1];
+ beam_normal_exit_[0] = BeamOpCodeAddr(op_normal_exit);
+ beam_normal_exit = (ErtsCodePtr)&beam_normal_exit_[0];
beam_exit_[0] = BeamOpCodeAddr(op_error_action_code);
beam_exit = (ErtsCodePtr)&beam_exit_[0];
@@ -705,3 +709,58 @@ erts_beam_jump_table(void)
return 1;
#endif
}
+
+void
+erts_prepare_bs_construct_fail_info(Process* c_p, const BeamInstr* p, Eterm reason, Eterm Info, Eterm value)
+{
+ Eterm* hp;
+ Eterm cause_tuple;
+ Eterm op;
+ Eterm error_info;
+ Uint segment;
+
+ segment = p[2] >> 3;
+
+ switch (p[0]) {
+ case BSC_APPEND:
+ case BSC_PRIVATE_APPEND:
+ case BSC_BINARY:
+ case BSC_BINARY_FIXED_SIZE:
+ case BSC_BINARY_ALL:
+ op = am_binary;
+ break;
+ case BSC_FLOAT:
+ case BSC_FLOAT_FIXED_SIZE:
+ op = am_float;
+ break;
+ case BSC_INTEGER:
+ case BSC_INTEGER_FIXED_SIZE:
+ op = am_integer;
+ break;
+ case BSC_STRING:
+ op = am_string;
+ break;
+ case BSC_UTF8:
+ op = am_utf8;
+ break;
+ case BSC_UTF16:
+ op = am_utf16;
+ break;
+ case BSC_UTF32:
+ op = am_utf32;
+ break;
+ default:
+ op = am_none;
+ break;
+ }
+
+ hp = HeapFragOnlyAlloc(c_p, MAP3_SZ+4+1);
+ cause_tuple = TUPLE4(hp, make_small(segment), op, Info, value);
+ hp += 5;
+ error_info = MAP3(hp,
+ am_cause, cause_tuple,
+ am_function, am_format_bs_fail,
+ am_module, am_erl_erts_errors);
+ c_p->fvalue = error_info;
+ c_p->freason = reason | EXF_HAS_EXT_INFO;
+}
diff --git a/erts/emulator/beam/emu/bif_instrs.tab b/erts/emulator/beam/emu/bif_instrs.tab
index 1afb7ac6de..9f90bf6600 100644
--- a/erts/emulator/beam/emu/bif_instrs.tab
+++ b/erts/emulator/beam/emu/bif_instrs.tab
@@ -307,7 +307,7 @@ call_light_bif(Bif, Exp) {
//
// Call a BIF tail-recursively, storing the result in x(0) and doing
-// a return to the continuation poiner.
+// a return to the continuation pointer.
//
call_light_bif_only(Bif, Exp) {
ErlHeapFragment *live_hf_end;
@@ -445,6 +445,9 @@ send() {
}
}
+nif_start() {
+}
+
call_nif_early() {
HEAVY_SWAPOUT;
I = erts_call_nif_early(c_p, erts_code_to_codeinfo(I));
diff --git a/erts/emulator/beam/emu/bs_instrs.tab b/erts/emulator/beam/emu/bs_instrs.tab
index bfb364c26b..54ecc2648e 100644
--- a/erts/emulator/beam/emu/bs_instrs.tab
+++ b/erts/emulator/beam/emu/bs_instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2021. All Rights Reserved.
+// Copyright Ericsson AB 2017-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -132,6 +132,7 @@ TEST_BIN_VHEAP(VNh, Nh, Live) {
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
+ $MAYBE_EXIT_AFTER_GC();
}
HEAP_SPACE_VERIFIED(need);
}
@@ -333,13 +334,13 @@ i_new_bs_put_float(Fail, Sz, Flags, Src) {
Eterm flags = $Flags;
Sint _size;
$BS_GET_UNCHECKED_FIELD_SIZE(sz, (flags >> 3), $BADARG($Fail), _size);
- if (!erts_new_bs_put_float(c_p, ($Src), _size, flags)) {
+ if (is_value(erts_new_bs_put_float(c_p, ($Src), _size, flags))) {
$BADARG($Fail);
}
}
i_new_bs_put_float_imm(Fail, Sz, Flags, Src) {
- if (!erts_new_bs_put_float(c_p, ($Src), ($Sz), ($Flags))) {
+ if (is_value(erts_new_bs_put_float(c_p, ($Src), ($Sz), ($Flags)))) {
$BADARG($Fail);
}
}
@@ -426,13 +427,14 @@ bs_init.verify(Fail) {
}
bs_init.execute(Live, Dst) {
+ erts_bin_offset = 0;
+ erts_writable_bin = 0;
+
if (BsOp1 <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb;
Uint bin_need;
bin_need = heap_bin_size(BsOp1);
- erts_bin_offset = 0;
- erts_writable_bin = 0;
$GC_TEST(0, bin_need+BsOp2+ERL_SUB_BIN_SIZE, $Live);
hb = (ErlHeapBin *) HTOP;
HTOP += bin_need;
@@ -444,10 +446,7 @@ bs_init.execute(Live, Dst) {
Binary* bptr;
ProcBin* pb;
- erts_bin_offset = 0;
- erts_writable_bin = 0;
- $TEST_BIN_VHEAP(BsOp1 / sizeof(Eterm),
- BsOp2 + PROC_BIN_SIZE + ERL_SUB_BIN_SIZE, $Live);
+ $TEST_BIN_VHEAP(BsOp1 / sizeof(Eterm), BsOp2 + PROC_BIN_SIZE, $Live);
/*
* Allocate the binary struct itself.
@@ -539,7 +538,9 @@ bs_init_bits.execute(Live, Dst) {
} else {
alloc += PROC_BIN_SIZE;
}
- $test_heap(alloc, $Live);
+
+ erts_bin_offset = 0;
+ erts_writable_bin = 0;
/* num_bits = Number of bits to build
* num_bytes = Number of bytes to allocate in the binary
@@ -549,38 +550,18 @@ bs_init_bits.execute(Live, Dst) {
if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb;
- erts_bin_offset = 0;
- erts_writable_bin = 0;
+ $test_heap(alloc, $Live);
hb = (ErlHeapBin *) HTOP;
HTOP += heap_bin_size(num_bytes);
hb->thing_word = header_heap_bin(num_bytes);
hb->size = num_bytes;
erts_current_bin = (byte *) hb->data;
new_binary = make_binary(hb);
-
- do_bits_sub_bin:
- if (num_bits & 7) {
- ErlSubBin* sb;
-
- sb = (ErlSubBin *) HTOP;
- HTOP += ERL_SUB_BIN_SIZE;
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = num_bytes - 1;
- sb->bitsize = num_bits & 7;
- sb->offs = 0;
- sb->bitoffs = 0;
- sb->is_writable = 0;
- sb->orig = new_binary;
- new_binary = make_binary(sb);
- }
- HEAP_SPACE_VERIFIED(0);
- $Dst = new_binary;
} else {
Binary* bptr;
ProcBin* pb;
- erts_bin_offset = 0;
- erts_writable_bin = 0;
+ $TEST_BIN_VHEAP(num_bytes / sizeof(Eterm), alloc, $Live);
/*
* Allocate the binary struct itself.
@@ -602,8 +583,24 @@ bs_init_bits.execute(Live, Dst) {
pb->flags = 0;
OH_OVERHEAD(&(MSO(c_p)), pb->size / sizeof(Eterm));
new_binary = make_binary(pb);
- goto do_bits_sub_bin;
}
+
+ if (num_bits & 7) {
+ ErlSubBin* sb;
+
+ sb = (ErlSubBin *) HTOP;
+ HTOP += ERL_SUB_BIN_SIZE;
+ sb->thing_word = HEADER_SUB_BIN;
+ sb->size = num_bytes - 1;
+ sb->bitsize = num_bits & 7;
+ sb->offs = 0;
+ sb->bitoffs = 0;
+ sb->is_writable = 0;
+ sb->orig = new_binary;
+ new_binary = make_binary(sb);
+ }
+ HEAP_SPACE_VERIFIED(0);
+ $Dst = new_binary;
}
bs_add(Fail, Src1, Src2, Unit, Dst) {
@@ -839,75 +836,454 @@ i_bs_validate_unicode_retract(Fail, Src, Ms) {
}
}
+BS_GET_TERM(Term, Dst) {
+ $Dst = $Term;
+ switch (loader_tag($Dst)) {
+ case LOADER_X_REG:
+ $Dst = x(loader_x_reg_index($Dst));
+ break;
+ case LOADER_Y_REG:
+ $Dst = y(loader_y_reg_index($Dst));
+ break;
+ }
+}
-//
-// Matching of binaries.
-//
+BS_LOAD_UNIT(Ptr, Dst) {
+ $Dst = $Ptr[1];
+}
-i_bs_start_match2 := bs_start_match.fetch.execute;
+BS_LOAD_FLAGS(Ptr, Dst) {
+ $Dst = $Ptr[2];
+}
-bs_start_match.head() {
- Eterm context;
+BS_LOAD_SRC(Ptr, Dst) {
+ $BS_GET_TERM($Ptr[3], $Dst);
}
-bs_start_match.fetch(Src) {
- context = $Src;
+BS_LOAD_STRING_SRC(Ptr, Dst) {
+ $Dst = (byte *) $Ptr[3];
}
-bs_start_match.execute(Fail, Live, Slots, Dst) {
- Uint slots;
- Uint live;
- Eterm header;
- if (!is_boxed(context)) {
- $FAIL($Fail);
+BS_LOAD_SIZE(Ptr, Dst) {
+ $BS_GET_TERM($Ptr[4], $Dst);
+}
+
+BS_LOAD_FIXED_SIZE(Ptr, Dst) {
+ $Dst = $Ptr[4];
+}
+
+// Implicitly uses the c_p and p variables (for convenience).
+BS_FAIL_INFO(Fail, Reason, ErrorType, Value) {
+ erts_prepare_bs_construct_fail_info(c_p, p, $Reason, $ErrorType, $Value);
+ $FAIL_HEAD_OR_BODY($Fail);
+}
+
+// Implicitly uses the Size variable because of limitations of parsing in
+// beam_makeops of nested macro call; a nested macro call can only have one
+// argument.
+BS_FAIL_INFO_SYSTEM_LIMIT(Fail) {
+ $BS_FAIL_INFO($Fail, SYSTEM_LIMIT, am_size, Size);
+}
+
+i_bs_create_bin(Fail, Alloc, Live, Dst, N) {
+ //| -no_prefetch
+ int n = $N;
+ const BeamInstr* p_start = $NEXT_INSTRUCTION;
+ const BeamInstr* p_end = p_start + n;
+ const BeamInstr* p;
+ Uint num_bytes;
+ Uint alloc = $Alloc;
+ Eterm new_binary;
+
+ /* We count the total number of bits in an unsigned integer. To avoid
+ * having to check for overflow when adding to `num_bits`, we ensure that the
+ * signed size of each segment fits in a word. */
+ Uint num_bits = 0;
+
+ /* Calculate size of binary in bits. */
+ for (p = p_start; p < p_end; p += BSC_NUM_ARGS) {
+ Eterm Src;
+ Eterm Size;
+ Uint unit;
+ Uint fixed_size;
+
+ switch (p[0]) {
+ case BSC_APPEND:
+ case BSC_PRIVATE_APPEND:
+ break;
+ case BSC_BINARY_ALL:
+ {
+ Uint byte_size;
+ Uint bit_size;
+
+ $BS_LOAD_SRC(p, Src);
+ if (is_not_binary(Src)) {
+ $BS_FAIL_INFO($Fail, BADARG, am_type, Src);
+ }
+ byte_size = binary_size(Src);
+#ifndef ARCH_64
+ if ((byte_size >> 28) != 0) {
+ /* The size of the binary in bits will not fit in
+ * a 32-bit signed integer. */
+ $BS_FAIL_INFO($Fail, SYSTEM_LIMIT, am_binary, am_size);
+ }
+#endif
+ bit_size = (byte_size << 3) + binary_bitsize(Src);
+ num_bits += bit_size;
+ }
+ break;
+ case BSC_BINARY_FIXED_SIZE:
+ case BSC_FLOAT_FIXED_SIZE:
+ case BSC_INTEGER_FIXED_SIZE:
+ $BS_LOAD_FIXED_SIZE(p, fixed_size);
+ num_bits += fixed_size;
+ break;
+ case BSC_STRING:
+ $BS_LOAD_FIXED_SIZE(p, fixed_size);
+ num_bits += fixed_size * 8;
+ break;
+ case BSC_BINARY:
+ case BSC_FLOAT:
+ case BSC_INTEGER:
+ $BS_LOAD_UNIT(p, unit);
+ $BS_LOAD_SIZE(p, Size);
+ if (is_small(Size)) {
+ Sint signed_size = signed_val(Size);
+ Uint size;
+ if (signed_size >= 0) {
+ $BS_SAFE_MUL(signed_size, unit, $BS_FAIL_INFO_SYSTEM_LIMIT($Fail), size);
+ if (size >> (sizeof(Uint) * 8 - 1) != 0) {
+ /* The signed size does not fit in a word. */
+ $BS_FAIL_INFO($Fail, SYSTEM_LIMIT, am_size, Size);
+ }
+ num_bits += size;
+ } else {
+ $BS_FAIL_INFO($Fail, BADARG, am_size, Size);
+ }
+ } else {
+#ifdef ARCH_64
+ /* The size must fit in a small on 64-bit platforms. */
+ if (is_big(Size)) {
+ if (!big_sign(Size)) {
+ $BS_FAIL_INFO($Fail, SYSTEM_LIMIT, am_size, Size);
+ } else {
+ $BS_FAIL_INFO($Fail, BADARG, am_size, Size);
+ }
+ } else {
+ /* Not an integer. */
+ $BS_FAIL_INFO($Fail, BADARG, am_size, Size);
+ }
+#else
+ Uint size;
+
+ if (!term_to_Uint(Size, &size)) {
+ if (size == BADARG) {
+ /* Not an integer or a negative integer. Determine which. */
+ if (is_big(Size)) {
+ /* Negative integer. */
+ $BS_FAIL_INFO($Fail, BADARG, am_size, Size);
+ }
+ /* Not an integer. */
+ $BS_FAIL_INFO($Fail, BADARG, am_size, Size);
+ }
+ /* Huge positive integer. */
+ $BS_FAIL_INFO_SYSTEM_LIMIT($Fail);
+ }
+ $BS_SAFE_MUL(size, unit, $BS_FAIL_INFO_SYSTEM_LIMIT($Fail), size);
+ if ((size >> 31) != 0) {
+ $BS_FAIL_INFO_SYSTEM_LIMIT($Fail);
+ } else {
+ num_bits += size;
+ }
+#endif
+ }
+ break;
+ case BSC_UTF8:
+ {
+ int num_bytes;
+
+ /*
+ * Calculate the number of bits needed to encode the
+ * source operand to UTF-8. If the source operand is
+ * invalid (e.g. wrong type or range) we return a
+ * nonsense integer result (32). We can get away
+ * with that because we KNOW that full error checking
+ * will be done in the construction phase.
+ */
+
+ $BS_LOAD_SRC(p, Src);
+ if (Src < make_small(0x80UL)) {
+ num_bytes = 1;
+ } else if (Src < make_small(0x800UL)) {
+ num_bytes = 2;
+ } else if (Src < make_small(0x10000UL)) {
+ num_bytes = 3;
+ } else {
+ num_bytes = 4;
+ }
+ num_bits += num_bytes * 8;
+ }
+ break;
+ case BSC_UTF16:
+ {
+ int num_bytes = 2;
+
+ /*
+ * Calculate the number of bits needed to encode the
+ * source operarand to UTF-16. If the source operand
+ * is invalid (e.g. wrong type or range) we return a
+ * nonsense integer result (16 or 32). We can get away
+ * with that because we KNOW that full error checking
+ * will be done in the construction phase.
+ */
+
+ $BS_LOAD_SRC(p, Src);
+ if (Src >= make_small(0x10000UL)) {
+ num_bytes = 4;
+ }
+ num_bits += num_bytes * 8;
+ }
+ break;
+ case BSC_UTF32:
+ $BS_LOAD_SRC(p, Src);
+
+ /*
+ * There is no need to untag the integer, but it IS
+ * necessary to make sure it is small (if the term is a
+ * bignum, it could slip through the test, and there is no
+ * further test that would catch it, since bit syntax
+ * construction silently masks too big numbers).
+ */
+ if (is_not_small(Src) || Src > make_small(0x10FFFFUL) ||
+ (make_small(0xD800UL) <= Src && Src <= make_small(0xDFFFUL))) {
+ $BS_FAIL_INFO($Fail, BADARG, am_type, Src);
+ }
+ num_bits += 4 * 8;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
}
- header = *boxed_val(context);
- /* Reserve a slot for the start position. */
- slots = $Slots + 1;
- live = $Live;
+ /* Allocate binary. */
+ p = p_start;
+ if (p[0] == BSC_APPEND) {
+ Uint live = $Live;
+ Uint unit;
+ Eterm Src;
+
+ $BS_LOAD_UNIT(p, unit);
+ $BS_LOAD_SRC(p, Src);
+ HEAVY_SWAPOUT;
+ reg[live] = Src;
+ new_binary = erts_bs_append_checked(c_p, reg, live, num_bits, alloc, unit);
+ HEAVY_SWAPIN;
+ if (is_non_value(new_binary)) {
+ $BS_FAIL_INFO($Fail, c_p->freason, c_p->fvalue, reg[live]);
+ }
+ p_start += BSC_NUM_ARGS;
+ } else if (p[0] == BSC_PRIVATE_APPEND) {
+ Uint unit;
+ Eterm Src;
- if (header_is_bin_matchstate(header)) {
- ErlBinMatchState* ms = (ErlBinMatchState *) boxed_val(context);
- Uint actual_slots = HEADER_NUM_SLOTS(header);
-
- /* We're not compatible with contexts created by bs_start_match3. */
- ASSERT(actual_slots >= 1);
-
- ms->save_offset[0] = ms->mb.offset;
- if (ERTS_UNLIKELY(actual_slots < slots)) {
- ErlBinMatchState* expanded;
- Uint wordsneeded = ERL_BIN_MATCHSTATE_SIZE(slots);
- $GC_TEST_PRESERVE(wordsneeded, live, context);
- ms = (ErlBinMatchState *) boxed_val(context);
- expanded = (ErlBinMatchState *) HTOP;
- *expanded = *ms;
- *HTOP = HEADER_BIN_MATCHSTATE(slots);
- HTOP += wordsneeded;
- HEAP_SPACE_VERIFIED(0);
- context = make_matchstate(expanded);
- $REFRESH_GEN_DEST();
+ if (alloc) {
+ $test_heap(alloc, $Live);
}
- $Dst = context;
- } else if (is_binary_header(header)) {
- Eterm result;
- Uint wordsneeded = ERL_BIN_MATCHSTATE_SIZE(slots);
- $GC_TEST_PRESERVE(wordsneeded, live, context);
- HEAP_TOP(c_p) = HTOP;
-#ifdef DEBUG
- c_p->stop = E; /* Needed for checking in HeapOnlyAlloc(). */
-#endif
- result = erts_bs_start_match_2(c_p, context, slots);
- HTOP = HEAP_TOP(c_p);
- HEAP_SPACE_VERIFIED(0);
- $REFRESH_GEN_DEST();
- $Dst = result;
+ $BS_LOAD_UNIT(p, unit);
+ $BS_LOAD_SRC(p, Src);
+ new_binary = erts_bs_private_append_checked(c_p, Src, num_bits, unit);
+ if (is_non_value(new_binary)) {
+ $BS_FAIL_INFO($Fail, c_p->freason, c_p->fvalue, Src);
+ }
+ p_start += BSC_NUM_ARGS;
} else {
- $FAIL($Fail);
+ num_bytes = ((Uint64)num_bits+(Uint64)7) >> 3;
+ if (num_bits & 7) {
+ alloc += ERL_SUB_BIN_SIZE;
+ }
+ if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
+ alloc += heap_bin_size(num_bytes);
+ } else {
+ alloc += PROC_BIN_SIZE;
+ }
+
+ /* num_bits = Number of bits to build
+ * num_bytes = Number of bytes to allocate in the binary
+ * alloc = Total number of words to allocate on heap
+ */
+ erts_bin_offset = 0;
+ erts_writable_bin = 0;
+ if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
+ ErlHeapBin* hb;
+
+ $test_heap(alloc, $Live);
+ hb = (ErlHeapBin *) HTOP;
+ HTOP += heap_bin_size(num_bytes);
+ hb->thing_word = header_heap_bin(num_bytes);
+ hb->size = num_bytes;
+ erts_current_bin = (byte *) hb->data;
+ new_binary = make_binary(hb);
+ } else {
+ Binary* bptr;
+ ProcBin* pb;
+
+ $TEST_BIN_VHEAP(num_bytes / sizeof(Eterm), alloc, $Live);
+
+ /*
+ * Allocate the binary struct itself.
+ */
+ bptr = erts_bin_nrml_alloc(num_bytes);
+ erts_current_bin = (byte *) bptr->orig_bytes;
+
+ /*
+ * Now allocate the ProcBin on the heap.
+ */
+ pb = (ProcBin *) HTOP;
+ HTOP += PROC_BIN_SIZE;
+ pb->thing_word = HEADER_PROC_BIN;
+ pb->size = num_bytes;
+ pb->next = MSO(c_p).first;
+ MSO(c_p).first = (struct erl_off_heap_header*) pb;
+ pb->val = bptr;
+ pb->bytes = (byte*) bptr->orig_bytes;
+ pb->flags = 0;
+ OH_OVERHEAD(&(MSO(c_p)), pb->size / sizeof(Eterm));
+ new_binary = make_binary(pb);
+ }
+
+ if (num_bits & 7) {
+ ErlSubBin* sb;
+
+ sb = (ErlSubBin *) HTOP;
+ HTOP += ERL_SUB_BIN_SIZE;
+ sb->thing_word = HEADER_SUB_BIN;
+ sb->size = num_bytes - 1;
+ sb->bitsize = num_bits & 7;
+ sb->offs = 0;
+ sb->bitoffs = 0;
+ sb->is_writable = 0;
+ sb->orig = new_binary;
+ new_binary = make_binary(sb);
+ }
+ HEAP_SPACE_VERIFIED(0);
+ }
+
+ c_p->fcalls = FCALLS;
+
+ /* Construct the segments. */
+ for (p = p_start; p < p_end; p += BSC_NUM_ARGS) {
+ Eterm Src;
+ Eterm Size;
+ Eterm flags;
+ Eterm unit;
+ Sint _size;
+
+ if(p[0] == BSC_STRING) {
+ byte* string;
+ $BS_LOAD_STRING_SRC(p, string);
+ $BS_LOAD_FIXED_SIZE(p, Size);
+ erts_new_bs_put_string(ERL_BITS_ARGS_2(string, Size));
+ continue;
+ }
+
+ $BS_LOAD_SRC(p, Src);
+
+ switch (p[0]) {
+ case BSC_BINARY_ALL:
+ $BS_LOAD_UNIT(p, unit);
+ if (!erts_new_bs_put_binary_all(c_p, Src, unit)) {
+ $BS_FAIL_INFO($Fail, BADARG, am_unit, Src);
+ }
+ break;
+ case BSC_BINARY:
+ $BS_LOAD_UNIT(p, unit);
+ $BS_LOAD_FLAGS(p, flags);
+ $BS_LOAD_SIZE(p, Size);
+ $BS_GET_UNCHECKED_FIELD_SIZE(Size, unit, $BADARG($Fail), _size);
+ if (!erts_new_bs_put_binary(c_p, Src, _size)) {
+ Eterm reason = is_binary(Src) ? am_short : am_type;
+ $BS_FAIL_INFO($Fail, BADARG, reason, Src);
+ }
+ break;
+ case BSC_BINARY_FIXED_SIZE:
+ $BS_LOAD_FIXED_SIZE(p, Size);
+ if (!erts_new_bs_put_binary(c_p, Src, Size)) {
+ Eterm reason = is_binary(Src) ? am_short : am_type;
+ $BS_FAIL_INFO($Fail, BADARG, reason, Src);
+ }
+ break;
+ case BSC_FLOAT:
+ $BS_LOAD_UNIT(p, unit);
+ $BS_LOAD_FLAGS(p, flags);
+ $BS_LOAD_SIZE(p, Size);
+ $BS_GET_UNCHECKED_FIELD_SIZE(Size, unit, $BADARG($Fail), _size);
+ Src = erts_new_bs_put_float(c_p, Src, _size, flags);
+ if (is_value(Src)) {
+ $BS_FAIL_INFO($Fail, BADARG, c_p->fvalue, Src);
+ }
+ break;
+ case BSC_FLOAT_FIXED_SIZE:
+ $BS_LOAD_FLAGS(p, flags);
+ $BS_LOAD_FIXED_SIZE(p, Size);
+ Src = erts_new_bs_put_float(c_p, Src, Size, flags);
+ if (is_value(Src)) {
+ $BS_FAIL_INFO($Fail, BADARG, c_p->fvalue, Src);
+ }
+ break;
+ case BSC_INTEGER:
+ {
+ Sint _size;
+
+ $BS_LOAD_UNIT(p, unit);
+ $BS_LOAD_FLAGS(p, flags);
+ $BS_LOAD_SIZE(p, Size);
+ $BS_GET_UNCHECKED_FIELD_SIZE(Size, unit, $BADARG($Fail), _size);
+ if (!erts_new_bs_put_integer(ERL_BITS_ARGS_3(Src, _size, flags))) {
+ $BS_FAIL_INFO($Fail, BADARG, am_type, Src);
+ }
+ }
+ break;
+ case BSC_INTEGER_FIXED_SIZE:
+ case BSC_UTF32:
+ $BS_LOAD_FLAGS(p, flags);
+ $BS_LOAD_FIXED_SIZE(p, Size);
+ if (!erts_new_bs_put_integer(ERL_BITS_ARGS_3(Src, Size, flags))) {
+ $BS_FAIL_INFO($Fail, BADARG, am_type, Src);
+ }
+ break;
+ case BSC_UTF8:
+ if (!erts_bs_put_utf8(ERL_BITS_ARGS_1(Src))) {
+ $BS_FAIL_INFO($Fail, BADARG, am_type, Src);
+ }
+ break;
+ case BSC_UTF16:
+ $BS_LOAD_FLAGS(p, flags);
+ $BS_LOAD_SRC(p, Src);
+ if (!erts_bs_put_utf16(ERL_BITS_ARGS_2(Src, flags))) {
+ $BS_FAIL_INFO($Fail, BADARG, am_type, Src);
+ }
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
}
+
+ FCALLS = c_p->fcalls;
+
+ /* Return the resulting binary. */
+ $REFRESH_GEN_DEST();
+ $Dst = new_binary;
+ I += n;
}
+
+//
+// Matching of binaries.
+//
+
bs_test_zero_tail2(Fail, Ctx) {
ErlBinMatchBuffer *_mb;
_mb = (ErlBinMatchBuffer*) ms_matchbuffer($Ctx);
@@ -1029,10 +1405,19 @@ bs_get_integer.head() {
bs_get_integer.fetch(Ctx, Size, Live) {
Uint wordsneeded;
+ ErlBinMatchBuffer* mb;
Ms = $Ctx;
Sz = $Size;
wordsneeded = 1+WSIZE(NBYTES(Sz));
- $GC_TEST_PRESERVE(wordsneeded, $Live, Ms);
+
+ /* Check bits size before potential GC. We do not want a GC
+ * and then realize we don't need the allocated space (if the
+ * op fails).
+ */
+ mb = ms_matchbuffer(Ms);
+ if (mb->size - mb->offset >= Sz) {
+ $GC_TEST_PRESERVE(wordsneeded, $Live, Ms);
+ }
}
bs_get_integer.fetch_small(Ctx, Size) {
@@ -1157,49 +1542,6 @@ i_bs_get_utf16.execute(Fail, Flags, Dst) {
$Dst = result;
}
-bs_context_to_binary := ctx_to_bin.fetch.execute;
-
-ctx_to_bin.head() {
- Eterm context;
- ErlBinMatchBuffer* mb;
- Uint size;
- Uint offs;
-}
-
-ctx_to_bin.fetch(Src) {
- context = $Src;
- if (is_boxed(context) &&
- header_is_bin_matchstate(*boxed_val(context))) {
- ErlBinMatchState* ms;
- ms = (ErlBinMatchState *) boxed_val(context);
- mb = &ms->mb;
- offs = ms->save_offset[0];
- size = mb->size - offs;
- } else {
- $NEXT0();
- }
-}
-
-ctx_to_bin.execute() {
- Uint hole_size;
- Uint orig = mb->orig;
- ErlSubBin* sb = (ErlSubBin *) boxed_val(context);
- /* Since we're going to overwrite the match state with the result, an
- * ErlBinMatchState must be at least as large as an ErlSubBin. */
- ERTS_CT_ASSERT(sizeof(ErlSubBin) <= sizeof(ErlBinMatchState));
- hole_size = 1 + header_arity(sb->thing_word) - ERL_SUB_BIN_SIZE;
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = BYTE_OFFSET(size);
- sb->bitsize = BIT_OFFSET(size);
- sb->offs = BYTE_OFFSET(offs);
- sb->bitoffs = BIT_OFFSET(offs);
- sb->is_writable = 0;
- sb->orig = orig;
- if (hole_size) {
- sb[1].thing_word = make_pos_bignum_header(hole_size-1);
- }
-}
-
i_bs_match_string(Ctx, Fail, Bits, Ptr) {
byte* bytes = (byte *) $Ptr;
Uint bits = $Bits;
@@ -1221,18 +1563,6 @@ i_bs_match_string(Ctx, Fail, Bits, Ptr) {
mb->offset += bits;
}
-i_bs_save2(Src, Slot) {
- ErlBinMatchState* _ms = (ErlBinMatchState*) boxed_val((Eterm) $Src);
- ASSERT(HEADER_NUM_SLOTS(_ms->thing_word) > $Slot);
- _ms->save_offset[$Slot] = _ms->mb.offset;
-}
-
-i_bs_restore2(Src, Slot) {
- ErlBinMatchState* _ms = (ErlBinMatchState*) boxed_val((Eterm) $Src);
- ASSERT(HEADER_NUM_SLOTS(_ms->thing_word) > $Slot);
- _ms->mb.offset = _ms->save_offset[$Slot];
-}
-
bs_get_tail := bs_get_tail.fetch.execute;
bs_get_tail.head() {
@@ -1245,31 +1575,22 @@ bs_get_tail.fetch(Src) {
bs_get_tail.execute(Dst, Live) {
ErlBinMatchBuffer* mb;
- Uint size, offs;
- ErlSubBin* sb;
+ Eterm bin, *htop;
ASSERT(header_is_bin_matchstate(*boxed_val(context)));
- $GC_TEST_PRESERVE(ERL_SUB_BIN_SIZE, $Live, context);
-
- mb = ms_matchbuffer(context);
+ $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context);
- offs = mb->offset;
- size = mb->size - offs;
+ htop = HTOP;
- sb = (ErlSubBin *) HTOP;
- HTOP += ERL_SUB_BIN_SIZE;
+ mb = ms_matchbuffer(context);
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = BYTE_OFFSET(size);
- sb->bitsize = BIT_OFFSET(size);
- sb->offs = BYTE_OFFSET(offs);
- sb->bitoffs = BIT_OFFSET(offs);
- sb->is_writable = 0;
- sb->orig = mb->orig;
+ bin = erts_extract_sub_binary(&htop,mb->orig,mb->base,
+ mb->offset,mb->size - mb->offset);
+ HTOP = htop;
$REFRESH_GEN_DEST();
- $Dst = make_binary(sb);
+ $Dst = bin;
}
diff --git a/erts/emulator/beam/emu/emu_load.c b/erts/emulator/beam/emu/emu_load.c
index 35937754d9..3188325acc 100644
--- a/erts/emulator/beam/emu/emu_load.c
+++ b/erts/emulator/beam/emu/emu_load.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@ extern void check_allocated_block(Uint type, void *blk);
static void init_label(Label* lp);
-void beam_load_prepare_emit(LoaderState *stp) {
+int beam_load_prepare_emit(LoaderState *stp) {
BeamCodeHeader *hdr;
int i;
@@ -76,6 +76,7 @@ void beam_load_prepare_emit(LoaderState *stp) {
hdr->compile_size_on_heap = 0;
hdr->literal_area = NULL;
hdr->md5_ptr = NULL;
+ hdr->are_nifs = NULL;
stp->code_hdr = hdr;
@@ -136,6 +137,8 @@ void beam_load_prepare_emit(LoaderState *stp) {
stp->beam.code.function_count *
sizeof(unsigned int));
}
+
+ return 1;
}
void beam_load_prepared_free(Binary* magic)
@@ -155,11 +158,6 @@ int beam_load_prepared_dtor(Binary* magic)
beamfile_free(&stp->beam);
beamopallocator_dtor(&stp->op_allocator);
- if (stp->bin) {
- driver_free_binary(stp->bin);
- stp->bin = NULL;
- }
-
if (stp->code_hdr) {
BeamCodeHeader *hdr = stp->code_hdr;
@@ -167,6 +165,10 @@ int beam_load_prepared_dtor(Binary* magic)
erts_release_literal_area(hdr->literal_area);
hdr->literal_area = NULL;
}
+ if (hdr->are_nifs) {
+ erts_free(ERTS_ALC_T_PREPARED_CODE, hdr->are_nifs);
+ hdr->are_nifs = NULL;
+ }
erts_free(ERTS_ALC_T_CODE, hdr);
stp->code_hdr = NULL;
@@ -330,6 +332,7 @@ int beam_load_finish_emit(LoaderState *stp) {
BeamCodeLineTab* const line_tab = (BeamCodeLineTab *) (codev+stp->ci);
const unsigned int ftab_size = stp->beam.code.function_count;
const unsigned int num_instrs = stp->current_li;
+ const unsigned int num_names = stp->beam.lines.name_count;
const void** const line_items =
(const void**) &line_tab->func_tab[ftab_size + 1];
const void *locp_base;
@@ -346,10 +349,10 @@ int beam_load_finish_emit(LoaderState *stp) {
}
line_items[i] = codev + stp->ci - 1;
- line_tab->fname_ptr = (Eterm*) &line_items[i + 1];
- if (stp->beam.lines.name_count) {
- sys_memcpy((void*)line_tab->fname_ptr, stp->beam.lines.names,
- stp->beam.lines.name_count*sizeof(Eterm));
+ line_tab->fname_ptr = (Eterm*)&line_items[i + 1];
+ for (i = 0; i < num_names; i++) {
+ Eterm *fname = (Eterm*)&line_tab->fname_ptr[i];
+ *fname = beamfile_get_literal(&stp->beam, stp->beam.lines.names[i]);
}
locp_base = &line_tab->fname_ptr[stp->beam.lines.name_count];
@@ -527,7 +530,7 @@ int beam_load_finish_emit(LoaderState *stp) {
CHKBLK(ERTS_ALC_T_CODE,code_hdr);
/*
- * Save the updated code code size.
+ * Save the updated code size.
*/
stp->loaded_size = size;
@@ -630,7 +633,8 @@ void beam_load_finalize_code(LoaderState* stp, struct erl_module_instance* inst_
erts_refc_dectest(&fun_entry->refc, 1);
}
- fun_entry->address = stp->codev + stp->labels[lambda->label].value;
+ erts_set_fun_code(fun_entry,
+ stp->codev + stp->labels[lambda->label].value);
}
lp = stp->lambda_patches;
@@ -686,7 +690,7 @@ void beam_load_finalize_code(LoaderState* stp, struct erl_module_instance* inst_
*/
ep->trampoline.not_loaded.deferred = (BeamInstr) address;
} else {
- ep->addresses[erts_staging_code_ix()] = address;
+ ep->dispatch.addresses[erts_staging_code_ix()] = address;
}
}
@@ -699,7 +703,8 @@ void beam_load_finalize_code(LoaderState* stp, struct erl_module_instance* inst_
Export *ep = erts_export_put(entry->module,
entry->name,
entry->arity);
- const BeamInstr *addr = ep->addresses[erts_staging_code_ix()];
+ const BeamInstr *addr =
+ ep->dispatch.addresses[erts_staging_code_ix()];
if (!ErtsInArea(addr, stp->codev, stp->ci * sizeof(BeamInstr))) {
erts_exit(ERTS_ABORT_EXIT,
@@ -716,18 +721,6 @@ void beam_load_finalize_code(LoaderState* stp, struct erl_module_instance* inst_
stp->code_hdr = NULL;
}
-static int
-is_bif(Eterm mod, Eterm func, unsigned arity)
-{
- Export *e = erts_active_export_entry(mod, func, arity);
-
- if (e != NULL) {
- return e->bif_number != -1;
- }
-
- return 0;
-}
-
static void init_label(Label* lp)
{
lp->value = 0;
@@ -843,11 +836,11 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
break;
case 'x': /* x(N) */
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
- code[ci++] = tmp_op->a[arg].val * sizeof(Eterm);
+ code[ci++] = (tmp_op->a[arg].val & REG_MASK) * sizeof(Eterm);
break;
case 'y': /* y(N) */
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
- code[ci++] = (tmp_op->a[arg].val + CP_SIZE) * sizeof(Eterm);
+ code[ci++] = ((tmp_op->a[arg].val & REG_MASK) + CP_SIZE) * sizeof(Eterm);
break;
case 'a': /* Tagged atom */
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
@@ -877,10 +870,10 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
case 's': /* Any source (tagged constant or register) */
switch (tag) {
case TAG_x:
- code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val & REG_MASK);
break;
case TAG_y:
- code[ci++] = make_loader_y_reg(tmp_op->a[arg].val + CP_SIZE);
+ code[ci++] = make_loader_y_reg((tmp_op->a[arg].val & REG_MASK) + CP_SIZE);
break;
case TAG_i:
code[ci++] = (BeamInstr) make_small((Uint)tmp_op->a[arg].val);
@@ -915,10 +908,10 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
case 'S': /* Source (x(N), y(N)) */
switch (tag) {
case TAG_x:
- code[ci++] = tmp_op->a[arg].val * sizeof(Eterm);
+ code[ci++] = (tmp_op->a[arg].val & REG_MASK) * sizeof(Eterm);
break;
case TAG_y:
- code[ci++] = (tmp_op->a[arg].val + CP_SIZE) * sizeof(Eterm) + 1;
+ code[ci++] = ((tmp_op->a[arg].val & REG_MASK) + CP_SIZE) * sizeof(Eterm) + 1;
break;
default:
BeamLoadError1(stp, "bad tag %d for destination",
@@ -949,7 +942,7 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
break;
case 'A': /* Arity value. */
BeamLoadVerifyTag(stp, tag, TAG_u);
- code[ci++] = make_arityval(tmp_op->a[arg].val);
+ code[ci++] = make_arityval_unchecked(tmp_op->a[arg].val);
break;
case 'f': /* Destination label */
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
@@ -1233,10 +1226,10 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
ci++;
break;
case TAG_x:
- code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
+ code[ci++] = make_loader_x_reg(tmp_op->a[arg].val & REG_MASK);
break;
case TAG_y:
- code[ci++] = make_loader_y_reg(tmp_op->a[arg].val + CP_SIZE);
+ code[ci++] = make_loader_y_reg((tmp_op->a[arg].val & REG_MASK) + CP_SIZE);
break;
case TAG_n:
code[ci++] = NIL;
@@ -1356,38 +1349,43 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
#endif
}
break;
- case op_int_func_end:
- {
- /*
- * Native function calls may be larger than their stubs, so
- * we'll need to make sure any potentially-native function stub
- * is padded with enough room.
- */
- int padding_required;
-
- ci--; /* Get rid of the instruction */
-
- padding_required = stp->may_load_nif ||
- is_bif(stp->module, stp->function, stp->arity);
-
- ASSERT(stp->last_func_start);
- if (padding_required) {
- Sint pad = BEAM_NATIVE_MIN_FUNC_SZ - (ci - stp->last_func_start);
- if (pad > 0) {
- ASSERT(pad < BEAM_NATIVE_MIN_FUNC_SZ);
- CodeNeed(pad);
- while (pad-- > 0) {
- /*
- * Filling with actual instructions (instead
- * of zeroes) will look nicer in a disassembly
- * listing.
- */
- code[ci++] = BeamOpCodeAddr(op_padding);
- }
- }
- }
- }
- break;
+ case op_nif_start:
+ if (!stp->code_hdr->are_nifs) {
+ int bytes = stp->beam.code.function_count * sizeof(byte);
+ stp->code_hdr->are_nifs = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
+ bytes);
+ sys_memzero(stp->code_hdr->are_nifs, bytes);
+ }
+ ASSERT(stp->function_number > 0);
+ ASSERT(stp->function_number <= stp->beam.code.function_count);
+ stp->code_hdr->are_nifs[stp->function_number-1] = 1;
+
+ ci -= 1; /* Get rid of the instruction */
+ break;
+ case op_i_nif_padding:
+ {
+ /* Native function calls may be larger than their stubs, so we'll
+ * need to make sure any potentially-native function stub is padded
+ * with enough room. */
+ Sint pad;
+
+ ci -= 1; /* Get rid of the instruction */
+
+ ASSERT(stp->last_func_start);
+ pad = BEAM_NATIVE_MIN_FUNC_SZ - (ci - stp->last_func_start);
+
+ if (pad > 0) {
+ ASSERT(pad < BEAM_NATIVE_MIN_FUNC_SZ);
+ CodeNeed(pad);
+
+ while (pad-- > 0) {
+ /* Filling with actual instructions (instead of zeroes) will
+ * look nicer in a disassembly listing. */
+ code[ci++] = BeamOpCodeAddr(op_padding);
+ }
+ }
+ }
+ break;
case op_on_load:
ci--; /* Get rid of the instruction */
@@ -1399,6 +1397,21 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
case op_i_bs_match_string_yfWW:
new_string_patch(stp, ci-1);
break;
+ case op_i_bs_create_bin_jIWdW:
+ {
+ int n = tmp_op->arity;
+ BeamInstr* p = &code[ci-n];
+ BeamInstr* end_p = &code[ci];
+ while (p < end_p) {
+ switch (*p) {
+ case BSC_STRING:
+ new_string_patch(stp, p+3-code);
+ break;
+ }
+ p += 5;
+ }
+ }
+ break;
case op_catch_yf:
/* code[ci-3] &&lb_catch_yf
* code[ci-2] y-register offset in E
diff --git a/erts/emulator/beam/emu/float_instrs.tab b/erts/emulator/beam/emu/float_instrs.tab
index ce0101f98e..500a647d2b 100644
--- a/erts/emulator/beam/emu/float_instrs.tab
+++ b/erts/emulator/beam/emu/float_instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2021. All Rights Reserved.
+// Copyright Ericsson AB 2017-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -74,9 +74,9 @@ i_fdiv(Src1, Src2, Dst) {
}
i_fnegate(Src, Dst) {
+ /* Note that there is no need to check for errors since flipping the sign
+ * of a finite float is guaranteed to produce a finite float. */
+ ASSERT(erts_isfinite($Src));
$Dst = -$Src;
-
- if (!erts_isfinite($Dst)) {
- $BADARITH0();
- }
+ ASSERT(erts_isfinite($Dst));
}
diff --git a/erts/emulator/beam/emu/generators.tab b/erts/emulator/beam/emu/generators.tab
index f9988f2399..65d5c60175 100644
--- a/erts/emulator/beam/emu/generators.tab
+++ b/erts/emulator/beam/emu/generators.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2020. All Rights Reserved.
+// Copyright Ericsson AB 2020-2021. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,6 +19,36 @@
// %CopyrightEnd%
//
+// Rewrites call_fun2 as call_fun: we're not yet helped by the Tag parameter,
+// and can't do anything clever with Func either.
+gen.call_fun2(Tag, Arity, Func) {
+ BeamOp *call;
+
+ (void)Tag;
+
+ $NewBeamOp(S, call);
+ $BeamOpNameArity(call, call_fun, 1);
+ call->a[0] = Arity;
+ call->next = NULL;
+
+ /* Move the fun in place when needed. We don't generate this at the moment,
+ * but a future version of the compiler might keep Func in a Y register. */
+ if (Func.type != TAG_x || Arity.val != Func.val) {
+ BeamOp *move;
+
+ $NewBeamOp(S, move);
+ $BeamOpNameArity(move, move, 2);
+ move->a[0] = Func;
+ move->a[1].type = TAG_x;
+ move->a[1].val = Arity.val;
+ move->next = call;
+
+ return move;
+ }
+
+ return call;
+}
+
// Generate the fastest instruction to fetch an integer from a binary.
gen.get_integer2(Fail, Ms, Live, Size, Unit, Flags, Dst) {
BeamOp* op;
@@ -493,7 +523,7 @@ gen.select_tuple_arity(Src, Fail, Size, Rest) {
for (i = 3; i < arity - 2*align; i+=2) {
tmp[i-3].type = TAG_v;
- tmp[i-3].val = make_arityval(Rest[i-3].val);
+ tmp[i-3].val = make_arityval_unchecked(Rest[i-3].val);
tmp[i-2] = Rest[i-2];
}
@@ -531,9 +561,13 @@ gen.new_small_map_lit(Dst, Live, Size, Rest) {
$BeamOpArity(op, 3 + size/2);
op->next = NULL;
- tmp = thp = erts_alloc(ERTS_ALC_T_LOADER_TMP, (1 + size/2) * sizeof(*tmp));
- keys = make_tuple(thp);
- *thp++ = make_arityval(size/2);
+ tmp = thp = erts_alloc(ERTS_ALC_T_LOADER_TMP, ((size == 0 ? 0 : 1) + size/2) * sizeof(*tmp));
+ if (size == 0) {
+ keys = erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE);
+ } else {
+ keys = make_tuple(thp);
+ *thp++ = make_arityval(size/2);
+ }
dst = op->a+3;
@@ -831,3 +865,163 @@ gen.init_yregs(N, Yregs) {
$INIT_YREGS(S, N.val);
return first;
}
+
+gen.create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments) {
+ BeamOp* op;
+ int fixed_args;
+ BeamOpArg* src;
+ BeamOpArg* dst;
+ BeamOpArg* endp;
+
+ endp = Segments + N.val;
+ N.val = 5*N.val/6;
+
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, i_bs_create_bin, 5);
+ fixed_args = op->arity;
+ $BeamOpArity(op, (N.val + fixed_args));
+
+ op->a[0] = Fail;
+ op->a[1] = Alloc;
+ op->a[2] = Live;
+ op->a[3] = Dst;
+ op->a[4] = N;
+
+ for (src = Segments, dst = op->a+fixed_args; src < endp; src += 6, dst += 5) {
+ UWord unit;
+ BeamOpArg Flags;
+ Uint flags = 0;
+ BeamOpArg Size;
+ Uint type;
+ Uint segment;
+
+ ASSERT(src[0].type = TAG_a);
+ ASSERT(src[1].type == TAG_u);
+ ASSERT(src[2].type == TAG_u);
+ segment = src[1].val;
+
+ /* Get unit. */
+ dst[1] = src[2];
+ unit = dst[1].val;
+
+ /* Translate flags. */
+ Flags = src[3]; /* Flags */
+ if (Flags.type != TAG_n) {
+ if (Flags.type == TAG_q) {
+ Eterm term = beamfile_get_literal(&S->beam, Flags.val);
+ while (is_list(term)) {
+ Eterm* consp = list_val(term);
+ Eterm elem = CAR(consp);
+ switch (elem) {
+ case am_little:
+ flags |= BSF_LITTLE;
+ break;
+ case am_native:
+ flags |= BSF_NATIVE;
+ break;
+ }
+ term = CDR(consp);
+ }
+ ASSERT(is_nil(term));
+ }
+ }
+ Flags.type = TAG_u;
+ Flags.val = flags;
+ $NativeEndian(Flags);
+ Flags.val = (segment << 3) | Flags.val;
+ dst[2] = Flags;
+
+ /* Store source. */
+ dst[3] = src[4]; /* Src */
+
+ /* Get size */
+ Size = src[5]; /* Size */
+
+ /* Translate type. */
+ switch (src[0].val) {
+ case am_append:
+ type = BSC_APPEND;
+ break;
+ case am_private_append:
+ type = BSC_PRIVATE_APPEND;
+ break;
+ case am_binary:
+ {
+ UWord bits;
+ type = BSC_BINARY;
+ if (Size.type == TAG_a && Size.val == am_all) {
+ type = BSC_BINARY_ALL;
+ } else if (Size.type == TAG_i &&
+ (Sint) Size.val >= 0 &&
+ beam_load_safe_mul(Size.val, unit, &bits) &&
+ (bits >> (sizeof(Uint)-1)*8) == 0) {
+ type = BSC_BINARY_FIXED_SIZE;
+ Size.type = TAG_u;
+ Size.val = bits;
+ unit = 0;
+ }
+ }
+ break;
+ case am_float:
+ {
+ UWord bits;
+ type = BSC_FLOAT;
+ if (Size.type == TAG_i &&
+ (Sint) Size.val >= 0 &&
+ beam_load_safe_mul(Size.val, unit, &bits) &&
+ (bits >> (sizeof(Uint)-1)*8) == 0) {
+ type = BSC_FLOAT_FIXED_SIZE;
+ Size.type = TAG_u;
+ Size.val = bits;
+ unit = 0;
+ }
+ }
+ break;
+ case am_integer:
+ {
+ UWord bits;
+ type = BSC_INTEGER;
+ if (Size.type == TAG_i &&
+ (Sint) Size.val >= 0 &&
+ beam_load_safe_mul(Size.val, unit, &bits) &&
+ (bits >> (sizeof(Uint)-1)*8) == 0) {
+ type = BSC_INTEGER_FIXED_SIZE;
+ Size.type = TAG_u;
+ Size.val = bits;
+ unit = 0;
+ }
+ }
+ break;
+ case am_string:
+ type = BSC_STRING;
+ ASSERT(Size.type == TAG_i);
+ ASSERT(unit == 8);
+ Size.type = TAG_u;
+ Size.val = Size.val; /* Size of string in bytes. */
+ unit = 0;
+ break;
+ case am_utf8:
+ type = BSC_UTF8;
+ break;
+ case am_utf16:
+ type = BSC_UTF16;
+ break;
+ case am_utf32:
+ type = BSC_UTF32;
+ Size.type = TAG_u;
+ Size.val = 32;
+ break;
+ default:
+ abort();
+ }
+ dst[0].type = TAG_u;
+ dst[0].val = type;
+
+ /* Store value of unit. */
+ dst[1].val = unit;
+
+ /* Store size. */
+ dst[4] = Size;
+ }
+ return op;
+}
diff --git a/erts/emulator/beam/emu/instrs.tab b/erts/emulator/beam/emu/instrs.tab
index d86439e570..2c794aa4b0 100644
--- a/erts/emulator/beam/emu/instrs.tab
+++ b/erts/emulator/beam/emu/instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2021. All Rights Reserved.
+// Copyright Ericsson AB 2017-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -243,7 +243,7 @@ APPLY(I, Deallocate, Next) {
save_calls(c_p, ep);
}
- $Next = ep->addresses[erts_active_code_ix()];
+ $Next = ep->dispatch.addresses[erts_active_code_ix()];
}
HANDLE_APPLY_ERROR() {
@@ -290,7 +290,7 @@ FIXED_APPLY(Arity, I, Deallocate, Next) {
save_calls(c_p, ep);
}
- $Next = ep->addresses[erts_active_code_ix()];
+ $Next = ep->dispatch.addresses[erts_active_code_ix()];
}
apply(Arity) {
@@ -310,10 +310,8 @@ apply_last(Arity, Deallocate) {
}
APPLY_FUN(Next) {
- Export *ignored;
-
HEAVY_SWAPOUT;
- $Next = apply_fun(c_p, r(0), x(1), reg, &ignored);
+ $Next = apply_fun(c_p, r(0), x(1), reg);
HEAVY_SWAPIN;
if (ERTS_UNLIKELY(next == NULL)) {
@@ -350,10 +348,9 @@ i_apply_fun_only() {
CALL_FUN(Fun, Next) {
//| -no_next
- Export *ignored;
HEAVY_SWAPOUT;
- $Next = call_fun(c_p, $Fun, reg, THE_NON_VALUE, &ignored);
+ $Next = call_fun(c_p, $Fun, reg, THE_NON_VALUE);
HEAVY_SWAPIN;
if (ERTS_UNLIKELY(next == NULL)) {
@@ -543,12 +540,13 @@ init3(Y1, Y2, Y3) {
make_blank($Y3);
}
-i_make_fun3(FunP, Dst, NumFree) {
+i_make_fun3(FunP, Dst, Arity, NumFree) {
ErlFunThing* funp;
+ ErlFunEntry *fe = (ErlFunEntry *) $FunP;
int i, num_free = $NumFree;
//| -no_next
SWAPOUT;
- funp = new_fun_thing(c_p, (ErlFunEntry *) $FunP, num_free);
+ funp = erts_new_local_fun_thing(c_p, fe, $Arity, num_free);
SWAPIN;
I = $NEXT_INSTRUCTION;
for (i = 0; i < num_free; i++) {
@@ -1076,6 +1074,13 @@ if_end() {
//| -no_next;
}
+badrecord(Src) {
+ c_p->fvalue = $Src;
+ c_p->freason = EXC_BADRECORD;
+ goto find_func_info;
+ //| -no_next;
+}
+
system_limit_body() {
c_p->freason = SYSTEM_LIMIT;
$FAIL_BODY();
@@ -1088,28 +1093,40 @@ catch(Y, Fail) {
}
catch_end(Y) {
+ /*
+ * At entry:
+ *
+ * x0 = Result of expression or THE_NON_VALUE
+ *
+ * If x0 is THE_NON_VALUE, the following registers are also set:
+ *
+ * x1 = Error reason/thrown value
+ * x2 = Stacktrace
+ * x3 = Exception class
+ */
$try_end($Y);
if (is_non_value(r(0))) {
- c_p->fvalue = NIL;
- c_p->ftrace = NIL;
- if (x(1) == am_throw) {
- r(0) = x(2);
+ ASSERT(c_p->fvalue == NIL);
+ ASSERT(c_p->ftrace == NIL);
+ if (x(3) == am_throw) {
+ r(0) = x(1);
} else {
- if (x(1) == am_error) {
+ if (x(3) == am_error) {
SWAPOUT;
- x(2) = add_stacktrace(c_p, x(2), x(3));
+ x(1) = add_stacktrace(c_p, x(1), x(2));
SWAPIN;
}
- /* only x(2) is included in the rootset here */
+ /* only x(1) is included in the rootset here */
if ((E - HTOP) < (3 + S_RESERVED)) {
$GC_SWAPOUT();
PROCESS_MAIN_CHK_LOCKS(c_p);
- FCALLS -= erts_garbage_collect_nobump(c_p, 3, reg+2, 1, FCALLS);
+ FCALLS -= erts_garbage_collect_nobump(c_p, 3, reg+1, 1, FCALLS);
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
+ $MAYBE_EXIT_AFTER_GC();
}
- r(0) = TUPLE2(HTOP, am_EXIT, x(2));
+ r(0) = TUPLE2(HTOP, am_EXIT, x(1));
HTOP += 3;
}
}
@@ -1126,9 +1143,7 @@ try_case(Y) {
ASSERT(is_non_value(r(0)));
ASSERT(c_p->fvalue == NIL);
ASSERT(c_p->ftrace == NIL);
- r(0) = x(1);
- x(1) = x(2);
- x(2) = x(3);
+ r(0) = x(3);
}
try_case_end(Src) {
diff --git a/erts/emulator/beam/emu/load.h b/erts/emulator/beam/emu/load.h
index 83e8ace504..f78fee217d 100644
--- a/erts/emulator/beam/emu/load.h
+++ b/erts/emulator/beam/emu/load.h
@@ -2,7 +2,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,11 +94,6 @@ typedef struct {
*/
struct LoaderState_ {
/*
- * The current logical file within the binary.
- */
- ErlDrvBinary* bin; /* Binary holding BEAM file (or NULL) */
-
- /*
* The following are used mainly for diagnostics.
*/
diff --git a/erts/emulator/beam/emu/macros.tab b/erts/emulator/beam/emu/macros.tab
index f7aa49634a..c4353583ef 100644
--- a/erts/emulator/beam/emu/macros.tab
+++ b/erts/emulator/beam/emu/macros.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2020. All Rights Reserved.
+// Copyright Ericsson AB 2017-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -74,6 +74,12 @@ GC_SWAPOUT() {
c_p->i = I;
}
+MAYBE_EXIT_AFTER_GC() {
+ if (ERTS_PSFLG_EXITING & erts_atomic32_read_nob(&c_p->state)) {
+ goto context_switch3;
+ }
+}
+
GC_TEST(Ns, Nh, Live) {
Uint need = $Nh + $Ns;
if (ERTS_UNLIKELY((E - HTOP) < (need + S_RESERVED))) {
@@ -83,6 +89,7 @@ GC_TEST(Ns, Nh, Live) {
ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
PROCESS_MAIN_CHK_LOCKS(c_p);
SWAPIN;
+ $MAYBE_EXIT_AFTER_GC();
}
HEAP_SPACE_VERIFIED($Nh);
}
@@ -98,6 +105,7 @@ GC_TEST_PRESERVE(NeedHeap, Live, PreserveTerm) {
PROCESS_MAIN_CHK_LOCKS(c_p);
$PreserveTerm = reg[$Live];
SWAPIN;
+ $MAYBE_EXIT_AFTER_GC();
}
HEAP_SPACE_VERIFIED($NeedHeap);
}
@@ -170,7 +178,7 @@ DISPATCH_EXPORT(Export) {
DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, ep);
- SET_I(ep->addresses[erts_active_code_ix()]);
+ SET_I(ep->dispatch.addresses[erts_active_code_ix()]);
CHECK_ARGS(I);
dis_next = *I;
@@ -198,7 +206,7 @@ DISPATCH_FUN(I) {
FCALLS--;
Goto(dis_next);
} else {
- goto context_switch_fun;
+ goto context_switch;
}
}
diff --git a/erts/emulator/beam/emu/map_instrs.tab b/erts/emulator/beam/emu/map_instrs.tab
index efebd37fb3..9cd64662f8 100644
--- a/erts/emulator/beam/emu/map_instrs.tab
+++ b/erts/emulator/beam/emu/map_instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2020. All Rights Reserved.
+// Copyright Ericsson AB 2017-2021. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,14 +19,6 @@
// %CopyrightEnd%
//
-ensure_map(Map) {
- if (is_not_map($Map)) {
- c_p->freason = BADMAP;
- c_p->fvalue = $Map;
- $FAIL_BODY();
- }
-}
-
new_map(Dst, Live, N) {
Eterm res;
diff --git a/erts/emulator/beam/emu/msg_instrs.tab b/erts/emulator/beam/emu/msg_instrs.tab
index 8aa725fc3d..dce164cb95 100644
--- a/erts/emulator/beam/emu/msg_instrs.tab
+++ b/erts/emulator/beam/emu/msg_instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2022. All Rights Reserved.
+// Copyright Ericsson AB 2017-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -69,7 +69,11 @@ i_recv_set() {
}
recv_marker_reserve(Dst) {
+ SWAPOUT;
+
$Dst = erts_msgq_recv_marker_insert(c_p);
+
+ SWAPIN;
}
recv_marker_bind(Marker, Reference) {
diff --git a/erts/emulator/beam/emu/ops.tab b/erts/emulator/beam/emu/ops.tab
index 28cee5cd36..814fd23b1b 100644
--- a/erts/emulator/beam/emu/ops.tab
+++ b/erts/emulator/beam/emu/ops.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ FORBIDDEN_TYPES=h
# needs to be re-compiled with a modern compiler.
too_old_compiler/0
-too_old_compiler | never() =>
+too_old_compiler | never() => _
# In R9C and earlier, the loader used to insert special instructions inside
# the module_info/0,1 functions. (In R10B and later, the compiler inserts
@@ -45,8 +45,10 @@ too_old_compiler | never() =>
# necessary.) Since the instructions don't work correctly in R12B, simply
# refuse to load the module.
-func_info M=a a==am_module_info A=u==0 | label L | move n x==0 => too_old_compiler
-func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compiler
+func_info M=a a==am_module_info A=u==0 | label L | move n x==0 =>
+ too_old_compiler
+func_info M=a a==am_module_info A=u==1 | label L | move n x==0 =>
+ too_old_compiler
# The undocumented and unsupported guard BIF is_constant/1 was removed
# in R13. The is_constant/2 operation is marked as obsolete in genop.tab,
@@ -55,12 +57,6 @@ func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compil
bif1 Fail u$func:erlang:is_constant/1 Src Dst => too_old_compiler
-# Since the constant pool was introduced in R12B, empty tuples ({})
-# are literals. Therefore we no longer need to allow put_tuple/2
-# with a tuple size of zero.
-
-put_tuple u==0 d => too_old_compiler
-
#
# All the other instructions.
#
@@ -69,6 +65,7 @@ put_tuple u==0 d => too_old_compiler
label L
i_func_info I a a I
int_code_end
+nif_start
i_generic_breakpoint
i_debug_breakpoint
@@ -85,8 +82,11 @@ int_func_start/5
int_func_start Lbl Line M F A => label Lbl | i_func_info u M F A | line Line
# The end of a function.
-int_func_end/0
-int_func_end
+int_func_end/2
+int_func_end Func Entry | needs_nif_padding() => i_nif_padding
+int_func_end Func Entry => _
+
+i_nif_padding
# Instruction used for padding functions that use native code.
%cold
@@ -99,14 +99,14 @@ padding
# BIF, so we can omit the line instruction for non-BIFs.
#
-move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D => \
+move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D =>
move S X0 | call_ext_last Ar Func D
-move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif => \
+move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif =>
move S X0 | call_ext_only Ar Func
-move S X0=x==0 | line Loc | call_last Ar Func D => \
+move S X0=x==0 | line Loc | call_last Ar Func D =>
move S X0 | call_last Ar Func D
-move S X0=x==0 | line Loc | call_only Ar Func => \
+move S X0=x==0 | line Loc | call_only Ar Func =>
move S X0 | call_only Ar Func
# To ensure that a "move Src x(0)" instruction can be combined with
@@ -119,16 +119,19 @@ move S X0=x==0 | line Loc | call_only Ar Func => \
move S X0=x==0 | line Loc => line Loc | move S X0
# The line number in int_func_start/5 can be NIL.
-line n =>
+line n => _
line I
# For the JIT, the init_yregs/1 instruction allows generation of better code.
# For the BEAM interpreter, though, it will probably be more efficient to
# translate all uses of init_yregs/1 back to the instructions that the compiler
# would emit before OTP 24.
-allocate Ns Live | init_yregs N Yregs=* => allocate(Ns, Live, N, Yregs)
-allocate_heap Ns Nh Live | init_yregs N Yregs=* => allocate_heap(Ns, Nh, Live, N, Yregs)
-init_yregs N Yregs=* => init_yregs(N, Yregs)
+allocate Ns Live | init_yregs N Yregs=* =>
+ allocate(Ns, Live, N, Yregs)
+allocate_heap Ns Nh Live | init_yregs N Yregs=* =>
+ allocate_heap(Ns, Nh, Live, N, Yregs)
+init_yregs N Yregs=* =>
+ init_yregs(N, Yregs)
allocate t t?
allocate_heap t I t?
@@ -170,36 +173,44 @@ init3 y y y
select_val S=aiq Fail=f Size=u Rest=* => const_select_val(S, Fail, Size, Rest)
-select_val S=s Fail=f Size=u Rest=* | use_jump_tab(Size, Rest, 2) => \
- jump_tab(S, Fail, Size, Rest)
+select_val S=s Fail=f Size=u Rest=* | use_jump_tab(Size, Rest, 2) =>
+ jump_tab(S, Fail, Size, Rest)
-is_integer Fail=f S | select_val S=s Fail=f Size=u Rest=* | use_jump_tab(Size, Rest, 2) => \
- jump_tab(S, Fail, Size, Rest)
+is_integer Fail=f S | select_val S2=s Fail2=f Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) |
+ use_jump_tab(Size, Rest, 2) =>
+ jump_tab(S, Fail, Size, Rest)
-is_integer TypeFail=f S | select_val S=s Fail=f Size=u Rest=* | \
- mixed_types(Size, Rest) => \
- split_values(S, TypeFail, Fail, Size, Rest)
+is_integer TypeFail=f S | select_val S2=s Fail=f Size=u Rest=* |
+ equal(S, S2) |
+ mixed_types(Size, Rest) =>
+ split_values(S, TypeFail, Fail, Size, Rest)
-select_val S=s Fail=f Size=u Rest=* | mixed_types(Size, Rest) => \
- split_values(S, Fail, Fail, Size, Rest)
+select_val S=s Fail=f Size=u Rest=* | mixed_types(Size, Rest) =>
+ split_values(S, Fail, Fail, Size, Rest)
-is_integer Fail=f S | select_val S=d Fail=f Size=u Rest=* | \
- fixed_size_values(Size, Rest) => select_val(S, Fail, Size, Rest)
+is_integer Fail=f S | select_val S2=d Fail2=f Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) |
+ fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
-is_atom Fail=f S | select_val S=d Fail=f Size=u Rest=* | \
- fixed_size_values(Size, Rest) => select_val(S, Fail, Size, Rest)
+is_atom Fail=f S | select_val S2=d Fail2=f Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) |
+ fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
-select_val S=s Fail=f Size=u Rest=* | floats_or_bignums(Size, Rest) => \
- select_literals(S, Fail, Size, Rest)
+select_val S=s Fail=f Size=u Rest=* | floats_or_bignums(Size, Rest) =>
+ select_literals(S, Fail, Size, Rest)
-select_val S=d Fail=f Size=u Rest=* | fixed_size_values(Size, Rest) => \
- select_val(S, Fail, Size, Rest)
+select_val S=d Fail=f Size=u Rest=* | fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
-is_tuple Fail=f S | select_tuple_arity S=d Fail=f Size=u Rest=* => \
- select_tuple_arity(S, Fail, Size, Rest)
+is_tuple Fail=f S | select_tuple_arity S2=d Fail2=f Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) =>
+ select_tuple_arity(S, Fail, Size, Rest)
-select_tuple_arity S=d Fail=f Size=u Rest=* => \
- select_tuple_arity(S, Fail, Size, Rest)
+select_tuple_arity S=d Fail=f Size=u Rest=* =>
+ select_tuple_arity(S, Fail, Size, Rest)
i_select_val_bins xy f? I *
@@ -260,14 +271,15 @@ i_get_tuple_element3 x P x
is_number f? xy
%hot
-is_number Fail=f i =>
+is_number Fail=f i => _
+
is_number Fail=f na => jump Fail
is_number Fail Literal=q => move Literal x | is_number Fail x
jump f
#
-# Expection rasing instructions. Infrequently executed.
+# Exception raising instructions. Infrequently executed.
#
%cold
@@ -280,6 +292,8 @@ badmatch x
if_end
+badrecord s
+
# Operands for raise/2 are almost always in x(2) and x(1).
# Optimize for that case.
raise x==2 x==1 => i_raise
@@ -288,9 +302,10 @@ raise Trace Value => move Trace x | move Value x=1 | move x x=2 | i_raise
i_raise
-# Workaround the limitation that generators must always return at least one instruction.
+# Workaround the limitation that generators must always return at least one
+# instruction.
delete_me/0
-delete_me =>
+delete_me => _
system_limit/1
system_limit p => system_limit_body
@@ -315,16 +330,16 @@ move_jump f c r
# x -> y
-move X1=x Y1=y | move X2=x Y2=y | succ(Y1, Y2) => \
+move X1=x Y1=y | move X2=x Y2=y | succ(Y1, Y2) =>
move_window2 X1 X2 Y1
-move_window2 X1 X2 Y1 | move X3=x Y3=y | is_offset(Y1, Y3, 2) => \
+move_window2 X1 X2 Y1 | move X3=x Y3=y | is_offset(Y1, Y3, 2) =>
move_window3 X1 X2 X3 Y1
-move_window3 X1 X2 X3 Y1 | move X4=x Y4=y | is_offset(Y1, Y4, 3) => \
+move_window3 X1 X2 X3 Y1 | move X4=x Y4=y | is_offset(Y1, Y4, 3) =>
move_window4 X1 X2 X3 X4 Y1
-move_window4 X1 X2 X3 X4 Y1=y | move X5=x Y5=y | is_offset(Y1, Y5, 4) => \
+move_window4 X1 X2 X3 X4 Y1=y | move X5=x Y5=y | is_offset(Y1, Y5, 4) =>
move_window5 X1 X2 X3 X4 X5 Y1
move_window2 x x y
@@ -337,17 +352,17 @@ move_window5 x x x x x y
move_src_window/4
move_src_window/5
-move Y1=y X1=x | move Y2=y X2=x | succ(Y1, Y2) => \
+move Y1=y X1=x | move Y2=y X2=x | succ(Y1, Y2) =>
move_src_window Y1 Y2 X1 X2
-move_src_window Y1 Y2 X1 X2 | move Y3=y X3=x | succ(Y2, Y3) => \
+move_src_window Y1 Y2 X1 X2 | move Y3=y X3=x | succ(Y2, Y3) =>
move_src_window Y1 Y3 X1 X2 X3
-move_src_window Y1 Y2 X1 X2 | move Y3=y X3=x | move Y4=y X4=x | succ(Y3, Y4) => \
+move_src_window Y1 Y2 X1 X2 | move Y3=y X3=x | move Y4=y X4=x | succ(Y3, Y4) =>
move_src_window2 Y1 X1 X2 | move_src_window Y3 Y4 X3 X4
-move_src_window Y1 Y2 X1 X2 | move Y3=y X3=x => \
+move_src_window Y1 Y2 X1 X2 | move Y3=y X3=x =>
move3 Y1 X1 Y2 X2 Y3 X3
-move_src_window Y1 Y3 X1 X2 X3 | move Y4=y X4=x | succ(Y3, Y4) => \
+move_src_window Y1 Y3 X1 X2 X3 | move Y4=y X4=x | succ(Y3, Y4) =>
move_src_window4 Y1 X1 X2 X3 X4
move_src_window Y1 y X1 X2 => move_src_window2 Y1 X1 X2
@@ -362,17 +377,31 @@ swap R1=x R2=y => swap R2 R1
swap xy x
swap y y
-swap R1=x R2=x | swap R3=x R1 => swap2 R1 R2 R3
+swap R1=x R2=x | swap R3=x R1Other | equal(R1, R1Other) => swap2 R1 R2 R3
swap2 x x x
# move_shift
-move SD=x D=x | move Src=cxy SD=x | distinct(D, Src) => move_shift Src SD D
-move SD=y D=x | move Src=x SD=y | distinct(D, Src) => move_shift Src SD D
-move SD=y D=x | init SD | => move_shift n SD D
-move SD=x D=y | move Src=x SD=x | distinct(D, Src) => move_shift Src SD D
-move SD=x==0 D=y | move Src=y SD=x==0 | distinct(D, Src) => move_shift Src SD D
+move SD=x D=x | move Src=cxy SDOther=x |
+ equal(SD, SDOther) | distinct(D, Src) =>
+ move_shift Src SD D
+
+move SD=y D=x | move Src=x SDOther=y |
+ equal(SD, SDOther) | distinct(D, Src) =>
+ move_shift Src SD D
+
+move SD=y D=x | init SDOther |
+ equal(SD, SDOther) =>
+ move_shift n SD D
+
+move SD=x D=y | move Src=x SDOther=x |
+ equal(SD, SDOther) | distinct(D, Src) =>
+ move_shift Src SD D
+
+move SD=x==0 D=y | move Src=y SDOther |
+ equal(SD, SDOther) | distinct(D, Src) =>
+ move_shift Src SD D
move_shift cxy x x
move_shift nx y x
@@ -381,15 +410,15 @@ move_shift y r y
# move2_par x x x x
-move X1=x X2=x | move X3=x X4=x | independent_moves(X1, X2, X3, X4) => \
+move X1=x X2=x | move X3=x X4=x | independent_moves(X1, X2, X3, X4) =>
move2_par X1 X2 X3 X4
move2_par x x x x
# move2_par x x x y
-move X1=x X2=x | move X3=x Y1=y | independent_moves(X1, X2, X3, Y1) => \
+move X1=x X2=x | move X3=x Y1=y | independent_moves(X1, X2, X3, Y1) =>
move2_par X1 X2 X3 Y1
-move X3=x Y1=y | move X1=x X2=x | independent_moves(X3, Y1, X1, X2) => \
+move X3=x Y1=y | move X1=x X2=x | independent_moves(X3, Y1, X1, X2) =>
move2_par X1 X2 X3 Y1
move2_par x x x y
@@ -400,23 +429,23 @@ move2_par y x y x
# move2_par y x x y
-move S1=y S2=x | move X1=x Y1=y | independent_moves(S1, S2, X1, Y1) => \
+move S1=y S2=x | move X1=x Y1=y | independent_moves(S1, S2, X1, Y1) =>
move2_par S1 S2 X1 Y1
-move X1=x Y1=y | move S1=y S2=x | independent_moves(S1, S2, X1, Y1) => \
+move X1=x Y1=y | move S1=y S2=x | independent_moves(S1, S2, X1, Y1) =>
move2_par S1 S2 X1 Y1
move2_par y x x y
# move2_par y x x x
-move Y1=y X1=x | move S1=x D1=x | independent_moves(Y1, X1, S1, D1) => \
+move Y1=y X1=x | move S1=x D1=x | independent_moves(Y1, X1, S1, D1) =>
move2_par Y1 X1 S1 D1
-move S1=x D1=x | move Y1=y X1=x | independent_moves(Y1, X1, S1, D1) => \
+move S1=x D1=x | move Y1=y X1=x | independent_moves(Y1, X1, S1, D1) =>
move2_par Y1 X1 S1 D1
move2_par y x x x
# move2_par y y y y
-move Y1=y Y2=y | move Y3=y Y4=y | independent_moves(Y1, Y2, Y3, Y4) => \
+move Y1=y Y2=y | move Y3=y Y4=y | independent_moves(Y1, Y2, Y3, Y4) =>
move2_par Y1 Y2 Y3 Y4
move2_par y y y y
@@ -444,7 +473,7 @@ move r y
loop_rec Fail x==0 | smp_mark_target_label(Fail) => i_loop_rec Fail
-label L | wait_timeout Fail Src | smp_already_locked(L) => \
+label L | wait_timeout Fail Src | smp_already_locked(L) =>
label L | wait_timeout_locked Src Fail
wait_timeout Fail Src => wait_timeout_unlocked Src Fail
@@ -481,7 +510,8 @@ send
# Optimized comparisons with one immediate/literal operand.
#
-is_eq_exact Lbl S S =>
+is_eq_exact Lbl LHS RHS | equal(LHS, RHS) => _
+
is_eq_exact Lbl C1=c C2=c => move C1 x | is_eq_exact Lbl x C2
is_eq_exact Lbl C=c R=xy => is_eq_exact Lbl R C
@@ -489,7 +519,7 @@ is_eq_exact Lbl R=xy n => is_nil Lbl R
is_eq_exact Lbl R=xy C=ia => i_is_eq_exact_immed Lbl R C
is_eq_exact Lbl R=xy C=q => i_is_eq_exact_literal Lbl R C
-is_ne_exact Lbl S S => jump Lbl
+is_ne_exact Lbl LHS RHS | equal(LHS, RHS) => jump Lbl
is_ne_exact Lbl C1=c C2=c => move C1 x | is_ne_exact Lbl x C2
is_ne_exact Lbl C=c R=xy => is_ne_exact Lbl R C
@@ -549,21 +579,6 @@ is_ne f? S s
# Code compiled with OTP 22 and later uses put_tuple2 to
# to construct a tuple.
#
-# Code compiled before OTP 22 uses put_tuple + one put instruction
-# per element. Translate to put_tuple2.
-#
-
-i_put_tuple/2
-put_tuple Arity Dst => i_put_tuple Dst u
-
-i_put_tuple Dst Arity Puts=* | put S1 | put S2 | \
- put S3 | put S4 | put S5 => \
- tuple_append_put5(Arity, Dst, Puts, S1, S2, S3, S4, S5)
-
-i_put_tuple Dst Arity Puts=* | put S => \
- tuple_append_put(Arity, Dst, Puts, S)
-
-i_put_tuple Dst Arity Puts=* => put_tuple2 Dst Arity Puts
put_tuple2 xy I *
@@ -576,7 +591,7 @@ put_tuple2 xy I *
#
put_list Const=c n Dst => move Const x | put_list x n Dst
-put_list Src Dst=x Dst => update_list Src Dst
+put_list Head Tail=x Dst | equal(Tail, Dst) => update_list Head Dst
update_list xyc x
@@ -627,7 +642,8 @@ return_trace
#
# Note: There is no 'move_return y r', since there never are any y registers
-# when we do move_return (if we have y registers, we must do move_deallocate_return).
+# when we do move_return (if we have y registers, we must do
+# move_deallocate_return).
move S x==0 | return => move_return S
@@ -661,7 +677,7 @@ test_heap_1_put_list I y
# is_tagged_tuple Fail=f Src=rxy Arity Atom=a
#
-is_tagged_tuple Fail Literal=q Arity Atom => \
+is_tagged_tuple Fail Literal=q Arity Atom =>
move Literal x | is_tagged_tuple Fail x Arity Atom
is_tagged_tuple Fail=f c Arity Atom => jump Fail
@@ -671,7 +687,9 @@ is_tagged_tuple f? rxy A a
is_tuple Fail Literal=q => move Literal x | is_tuple Fail x
is_tuple Fail=f c => jump Fail
-is_tuple Fail=f S=xy | test_arity Fail=f S=xy Arity => is_tuple_of_arity Fail S Arity
+is_tuple Fail=f S=xy | test_arity Fail2=f S2=xy Arity |
+ equal(Fail, Fail2) | equal(S, S2) =>
+ is_tuple_of_arity Fail S Arity
is_tuple_of_arity f? rxy A
@@ -679,50 +697,58 @@ is_tuple f? rxy
test_arity Fail Literal=q Arity => move Literal x | test_arity Fail x Arity
test_arity Fail=f c Arity => jump Fail
-test_arity Fail Tuple=x Arity | get_tuple_element Tuple Pos Dst=x => \
- test_arity_get_tuple_element Fail Tuple Arity Pos Dst
+test_arity Fail Tuple=x Arity | get_tuple_element Tuple2 Pos Dst=x |
+ equal(Tuple, Tuple2) =>
+ test_arity_get_tuple_element Fail Tuple Arity Pos Dst
test_arity f? xy A
test_arity_get_tuple_element f? x A P x
-is_tuple NotTupleFail Tuple=x | is_tagged_tuple WrongRecordFail Tuple Arity Atom => \
- is_tagged_tuple_ff NotTupleFail WrongRecordFail Tuple Arity Atom
+is_tuple NotTupleFail Src=x |
+ is_tagged_tuple WrongRecordFail Tuple Arity Atom |
+ equal(Src, Tuple) =>
+ is_tagged_tuple_ff NotTupleFail WrongRecordFail Src Arity Atom
is_tagged_tuple_ff f? f? rx A a
-get_tuple_element Reg=x P1 D1=x | \
- get_tuple_element Reg=x P2 D2=x | \
- get_tuple_element Reg=x P3 D3=x | \
- succ(P1, P2) | succ(P2, P3) | succ(D1, D2) | succ(D2, D3) | \
- distinct(D1, Reg) | distinct(D2, Reg) => \
- i_get_tuple_element3 Reg P1 D1
-
-get_tuple_element Reg=x P1 D1=x | \
- get_tuple_element Reg=x P2 D2=x | \
- succ(P1, P2) | succ(D1, D2) | \
- distinct(D1, Reg) => \
- i_get_tuple_element2 Reg P1 D1
-
-get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \
- succ(P1, P2) | distinct(D1, Reg) => i_get_tuple_element2_dst Reg P1 D1 D2
-
-get_tuple_element Reg=x P1 D1=y | get_tuple_element Reg=x P2 D2=y | \
- succ(P1, P2) => i_get_tuple_element2_dst Reg P1 D1 D2
+get_tuple_element Reg=x P1 D1=x |
+ get_tuple_element Reg2 P2 D2=x |
+ get_tuple_element Reg3 P3 D3=x |
+ equal(Reg, Reg2) | equal(Reg, Reg3) |
+ succ(P1, P2) | succ(P2, P3) | succ(D1, D2) | succ(D2, D3) |
+ distinct(D1, Reg) | distinct(D2, Reg) =>
+ i_get_tuple_element3 Reg P1 D1
+
+get_tuple_element Reg=x P1 D1=x |
+ get_tuple_element Reg2 P2 D2=x |
+ equal(Reg, Reg2) |
+ succ(P1, P2) | succ(D1, D2) |
+ distinct(D1, Reg) =>
+ i_get_tuple_element2 Reg P1 D1
+
+get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg2=x P2 D2=x |
+ equal(Reg, Reg2) | succ(P1, P2) | distinct(D1, Reg) =>
+ i_get_tuple_element2_dst Reg P1 D1 D2
+
+get_tuple_element Reg=x P1 D1=y | get_tuple_element Reg2=x P2 D2=y |
+ equal(Reg, Reg2) | succ(P1, P2) =>
+ i_get_tuple_element2_dst Reg P1 D1 D2
get_tuple_element Reg P Dst => i_get_tuple_element Reg P Dst
-is_integer Fail=f i =>
+is_integer Fail=f i => _
is_integer Fail=f an => jump Fail
is_integer Fail Literal=q => move Literal x | is_integer Fail x
-is_integer Fail=f S=x | allocate Need Regs => is_integer_allocate Fail S Need Regs
+is_integer Fail=f S=x | allocate Need Regs =>
+ is_integer_allocate Fail S Need Regs
is_integer_allocate f? x t t
is_integer f? xy
-is_list Fail=f n =>
+is_list Fail=f n => _
is_list Fail Literal=q => move Literal x | is_list Fail x
is_list Fail=f c => jump Fail
is_list f? x
@@ -730,16 +756,20 @@ is_list f? x
is_list f? y
%hot
-is_nonempty_list Fail=f S=x | allocate Need Rs => is_nonempty_list_allocate Fail S Need Rs
+is_nonempty_list Fail=f S=x | allocate Need Rs =>
+ is_nonempty_list_allocate Fail S Need Rs
-is_nonempty_list Fail=f S=x | get_list S D1=x D2=x => \
- is_nonempty_list_get_list Fail S D1 D2
+is_nonempty_list Fail=f S=x | get_list S2 D1=x D2=x |
+ equal(S, S2) =>
+ is_nonempty_list_get_list Fail S D1 D2
-is_nonempty_list Fail=f S=x | get_hd S Dst=x => \
- is_nonempty_list_get_hd Fail S Dst
+is_nonempty_list Fail=f S=x | get_hd S2 Dst=x |
+ equal(S, S2) =>
+ is_nonempty_list_get_hd Fail S Dst
-is_nonempty_list Fail=f S=x | get_tl S Dst=x => \
- is_nonempty_list_get_tl Fail S Dst
+is_nonempty_list Fail=f S=x | get_tl S2 Dst=x |
+ equal(S, S2) =>
+ is_nonempty_list_get_tl Fail S Dst
is_nonempty_list_allocate f? rx t t
@@ -753,7 +783,7 @@ is_atom f? x
%cold
is_atom f? y
%hot
-is_atom Fail=f a =>
+is_atom Fail=f a => _
is_atom Fail=f niq => jump Fail
is_float f? x
@@ -763,7 +793,7 @@ is_float f? y
is_float Fail=f nai => jump Fail
is_float Fail Literal=q => move Literal x | is_float Fail x
-is_nil Fail=f n =>
+is_nil Fail=f n => _
is_nil Fail=f qia => jump Fail
is_nil f? xy
@@ -803,8 +833,8 @@ is_port f? x
is_port f? y
%hot
-is_boolean Fail=f a==am_true =>
-is_boolean Fail=f a==am_false =>
+is_boolean Fail=f a==am_true => _
+is_boolean Fail=f a==am_false => _
is_boolean Fail=f ac => jump Fail
%cold
@@ -837,9 +867,12 @@ call_light_bif_last/2
# The load_nif/2 BIF is an instruction.
#
-call_ext u==2 u$func:erlang:load_nif/2 => i_load_nif
-call_ext_last u==2 u$func:erlang:load_nif/2 D => i_load_nif | deallocate_return D
-call_ext_only u==2 u$func:erlang:load_nif/2 => i_load_nif | return
+call_ext u==2 u$func:erlang:load_nif/2 =>
+ i_load_nif
+call_ext_last u==2 u$func:erlang:load_nif/2 D =>
+ i_load_nif | deallocate_return D
+call_ext_only u==2 u$func:erlang:load_nif/2 =>
+ i_load_nif | return
%cold
i_load_nif
@@ -876,11 +909,11 @@ call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate
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
-call_ext u==0 u$func:os:perf_counter/0 => \
+call_ext u==0 u$func:os:perf_counter/0 =>
i_perf_counter
-call_ext_last u==0 u$func:os:perf_counter/0 D => \
+call_ext_last u==0 u$func:os:perf_counter/0 D =>
i_perf_counter | deallocate_return D
-call_ext_only u==0 u$func:os:perf_counter/0 => \
+call_ext_only u==0 u$func:os:perf_counter/0 =>
i_perf_counter | return
#
@@ -888,11 +921,11 @@ call_ext_only u==0 u$func:os:perf_counter/0 => \
# emulator state, which the ordinary call_light_bif instruction doesn't save.
#
-call_ext u Bif=u$is_bif | is_heavy_bif(Bif) => \
+call_ext u Bif=u$is_bif | is_heavy_bif(Bif) =>
i_call_ext Bif
-call_ext_last u Bif=u$is_bif D | is_heavy_bif(Bif) => \
+call_ext_last u Bif=u$is_bif D | is_heavy_bif(Bif) =>
i_call_ext Bif | deallocate_return D
-call_ext_only Ar=u Bif=u$is_bif | is_heavy_bif(Bif) => \
+call_ext_only Ar=u Bif=u$is_bif | is_heavy_bif(Bif) =>
allocate u Ar | i_call_ext Bif | deallocate_return u
#
@@ -910,9 +943,12 @@ call_ext_only Ar=u Bif=u$is_bif => call_light_bif_only Bif
# with call instructions.
#
-move S=c x==0 | call_ext Ar=u Func=u$is_not_bif => i_move_call_ext S Func
-move S=c x==0 | call_ext_last Ar=u Func=u$is_not_bif D => i_move_call_ext_last Func D S
-move S=c x==0 | call_ext_only Ar=u Func=u$is_not_bif => i_move_call_ext_only Func S
+move S=c x==0 | call_ext Ar=u Func=u$is_not_bif =>
+ i_move_call_ext S Func
+move S=c x==0 | call_ext_last Ar=u Func=u$is_not_bif D =>
+ i_move_call_ext_last Func D S
+move S=c x==0 | call_ext_only Ar=u Func=u$is_not_bif =>
+ i_move_call_ext_only Func S
call_ext Ar Func => i_call_ext Func
call_ext_last Ar Func D => i_call_ext_last Func D
@@ -934,13 +970,13 @@ i_apply_fun_only
# stack frame before returning.
#
-call_light_bif Bif=u$is_bif => \
+call_light_bif Bif=u$is_bif =>
call_light_bif Bif Bif
-call_light_bif_last Bif=u$is_bif D => \
+call_light_bif_last Bif=u$is_bif D =>
call_light_bif Bif Bif | deallocate_return D
-call_light_bif_only Bif=u$is_bif => \
+call_light_bif_only Bif=u$is_bif =>
call_light_bif_only Bif Bif | deallocate_return u
call_light_bif b e
@@ -960,12 +996,16 @@ i_perf_counter
bif0 u$bif:erlang:self/0 Dst=d => self Dst
bif0 u$bif:erlang:node/0 Dst=d => node Dst
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=x Dst=x => is_nonempty_list_get_hd Fail Src Dst
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=x Dst=x => is_nonempty_list_get_tl Fail Src Dst
+bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=x Dst=x =>
+ is_nonempty_list_get_hd Fail Src Dst
+bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=x Dst=x =>
+ is_nonempty_list_get_tl Fail Src Dst
-bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => get(Src, Dst)
+bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d =>
+ get(Src, Dst)
-bif2 Jump=j u$bif:erlang:element/2 S1=s S2=xy Dst=d => element(Jump, S1, S2, Dst)
+bif2 Jump=j u$bif:erlang:element/2 S1=s S2=xy Dst=d =>
+ element(Jump, S1, S2, Dst)
bif1 p Bif S1 Dst => i_bif1_body S1 Bif Dst
bif1 Fail=f Bif S1 Dst => i_bif1 S1 Fail Bif Dst
@@ -1039,17 +1079,21 @@ call_fun Arity => i_call_fun Arity
i_call_fun t
i_call_fun_last t Q
+call_fun2 Tag Arity Func => call_fun2(Tag, Arity, Func)
+
#
# A fun with an empty environment can be converted to a literal.
# As a further optimization, the we try to move the fun to its
# final destination directly.
-make_fun2 OldIndex=u => make_fun2(OldIndex)
-make_fun3 OldIndex=u Dst=d NumFree=u Env=* => make_fun3(OldIndex, Dst, NumFree, Env)
+make_fun2 OldIndex=u =>
+ make_fun2(OldIndex)
+make_fun3 OldIndex=u Dst=d NumFree=u Env=* =>
+ make_fun3(OldIndex, Dst, NumFree, Env)
%cold
-i_make_fun3 F d t *
+i_make_fun3 F d t t *
# Psuedo-instruction for signalling lambda load errors. Never actually runs.
i_lambda_error t
@@ -1062,29 +1106,6 @@ is_function Fail=f c => jump Fail
func_info M F A => i_func_info u M F A
# ================================================================
-# Bit syntax matching obsoleted in OTP 22.
-# ================================================================
-
-%cold
-bs_start_match2 Fail=f ica X Y D => jump Fail
-bs_start_match2 Fail Bin X Y D => i_bs_start_match2 Bin Fail X Y D
-i_bs_start_match2 xy f t t d
-
-bs_save2 Y=y Index => move Y x | bs_save2 x Index
-bs_save2 Reg Index => bs_save(Reg, Index)
-i_bs_save2 x t
-
-bs_restore2 Y=y Index => move Y x | bs_restore2 x Index
-bs_restore2 Reg Index => bs_restore(Reg, Index)
-i_bs_restore2 x t
-
-bs_context_to_binary Y=y | line L | badmatch Y => \
- move Y x | bs_context_to_binary x | line L | badmatch x
-bs_context_to_binary Y=y => move Y x | bs_context_to_binary x
-bs_context_to_binary x
-%warm
-
-# ================================================================
# New bit syntax matching (R11B).
# ================================================================
@@ -1096,14 +1117,14 @@ bs_match_string Fail Ms Bits Val => i_bs_match_string Ms Fail Bits Val
i_bs_match_string xy f W W
# Fetching integers from binaries.
-bs_get_integer2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d => \
- get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+bs_get_integer2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d =>
+ get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-i_bs_get_integer_small_imm Ms Bits Fail Flags Y=y => \
- i_bs_get_integer_small_imm Ms Bits Fail Flags x | move x Y
+i_bs_get_integer_small_imm Ms Bits Fail Flags Y=y =>
+ i_bs_get_integer_small_imm Ms Bits Fail Flags x | move x Y
-i_bs_get_integer_imm Ms Bits Live Fail Flags Y=y => \
- i_bs_get_integer_imm Ms Bits Live Fail Flags x | move x Y
+i_bs_get_integer_imm Ms Bits Live Fail Flags Y=y =>
+ i_bs_get_integer_imm Ms Bits Live Fail Flags x | move x Y
i_bs_get_integer_small_imm xy W f? t x
i_bs_get_integer_imm xy W t f? t x
@@ -1116,30 +1137,33 @@ i_bs_get_integer_32 xy f? d
%endif
# Fetching binaries from binaries.
-bs_get_binary2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d => \
- get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+bs_get_binary2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d =>
+ get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
i_bs_get_binary_imm2 xy f? t W t d
i_bs_get_binary2 xy f t? S t d
i_bs_get_binary_all2 xy f? t t d
# Fetching float from binaries.
-bs_get_float2 Fail=f Ms=xy Live=u Sz=s Unit=u Flags=u Dst=d => \
- get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+bs_get_float2 Fail=f Ms=xy Live=u Sz=s Unit=u Flags=u Dst=d =>
+ get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
bs_get_float2 Fail=f Ms=x Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
i_bs_get_float2 xy f? t s t d
-# Miscellanous
+# Miscellaneous
-bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u => skip_bits2(Fail, Ms, Sz, Unit, Flags)
+bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u =>
+ skip_bits2(Fail, Ms, Sz, Unit, Flags)
i_bs_skip_bits_imm2 f? xy W
i_bs_skip_bits2 xy xy f? t
+bs_test_tail2 Fail=f Ms=xy o => jump Fail
bs_test_tail2 Fail=f Ms=xy Bits=u==0 => bs_test_zero_tail2 Fail Ms
bs_test_tail2 Fail=f Ms=xy Bits=u => bs_test_tail_imm2 Fail Ms Bits
+
bs_test_zero_tail2 f? xy
bs_test_tail_imm2 f? xy W
@@ -1156,24 +1180,25 @@ bs_get_tail xy d t
# "slots" in the context itself, which lets us continue matching even after
# we've passed it off to another function.
-bs_start_match4 a==am_no_fail Live=u Src=xy Ctx=d => \
+bs_start_match4 a==am_no_fail Live=u Src=xy Ctx=d =>
bs_start_match3 p Src Live Ctx
-bs_start_match4 Fail=f Live=u Src=xy Ctx=d => \
+bs_start_match4 Fail=f Live=u Src=xy Ctx=d =>
bs_start_match3 Fail Src Live Ctx
%if ARCH_64
# This instruction nops on 64-bit platforms
-bs_start_match4 a==am_resume Live Same Same =>
+bs_start_match4 a==am_resume Live Ctx Dst | equal(Ctx, Dst) => _
bs_start_match4 a==am_resume Live Ctx Dst => move Ctx Dst
-bs_start_match3 Fail Bin Live Ctx | bs_get_position Ctx Pos=x Ignored => \
+bs_start_match3 Fail Bin Live Ctx | bs_get_position Ctx2 Pos=x Ignored |
+ equal(Ctx, Ctx2) =>
i_bs_start_match3_gp Bin Live Fail Ctx Pos
i_bs_start_match3_gp xy t j d x
%else
-bs_start_match4 a==am_resume Live Ctx Dst => \
+bs_start_match4 a==am_resume Live Ctx Dst =>
bs_start_match4 a=am_no_fail Live Ctx Dst
%endif
@@ -1208,35 +1233,46 @@ bs_skip_utf16 Fail=f Ms=xy Unit=u Flags=u => bs_get_utf16 Fail Ms Unit Flags x
i_bs_get_utf16 xy f? t d
-bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d => \
- bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst | \
- i_bs_validate_unicode_retract Fail Dst Ms
-bs_skip_utf32 Fail=f Ms=xy Live=u Flags=u => \
- bs_get_integer2 Fail Ms Live i=32 u=1 Flags x | \
- i_bs_validate_unicode_retract Fail x Ms
+bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst |
+ i_bs_validate_unicode_retract Fail Dst Ms
+
+bs_skip_utf32 Fail=f Ms=xy Live=u Flags=u =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags x |
+ i_bs_validate_unicode_retract Fail x Ms
i_bs_validate_unicode_retract j s S
%hot
-#
-# Constructing binaries
-#
+# ================================================================
+# New binary construction (OTP 25).
+# ================================================================
+
+bs_create_bin Fail Alloc=u Live=u Unit=u Dst=xy N=u Segments=* =>
+ create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments)
+
+i_bs_create_bin j I W d W *
+
+# ================================================================
+# Old instruction for constructing binaries (up to OTP 24).
+# ================================================================
+
%warm
bs_init2 Fail Sz Words Regs Flags Dst | binary_too_big(Sz) => system_limit Fail
-bs_init2 Fail Sz Words Regs Flags Dst=y => \
- bs_init2 Fail Sz Words Regs Flags x | move x Dst
+bs_init2 Fail Sz Words Regs Flags Dst=y =>
+ bs_init2 Fail Sz Words Regs Flags x | move x Dst
bs_init2 Fail Sz=u Words=u==0 Regs Flags Dst => i_bs_init Sz Regs Dst
-bs_init2 Fail Sz=u Words Regs Flags Dst => \
- i_bs_init_heap Sz Words Regs Dst
+bs_init2 Fail Sz=u Words Regs Flags Dst =>
+ i_bs_init_heap Sz Words Regs Dst
-bs_init2 Fail Sz Words=u==0 Regs Flags Dst => \
- i_bs_init_fail Sz Fail Regs Dst
-bs_init2 Fail Sz Words Regs Flags Dst => \
- i_bs_init_fail_heap Sz Words Fail Regs Dst
+bs_init2 Fail Sz Words=u==0 Regs Flags Dst =>
+ i_bs_init_fail Sz Fail Regs Dst
+bs_init2 Fail Sz Words Regs Flags Dst =>
+ i_bs_init_fail_heap Sz Words Fail Regs Dst
i_bs_init_fail xy j? t? x
@@ -1248,16 +1284,18 @@ i_bs_init_heap W I t? x
bs_init_bits Fail Sz=o Words Regs Flags Dst => system_limit Fail
-bs_init_bits Fail Sz Words Regs Flags Dst=y => \
- bs_init_bits Fail Sz Words Regs Flags x | move x Dst
+bs_init_bits Fail Sz Words Regs Flags Dst=y =>
+ bs_init_bits Fail Sz Words Regs Flags x | move x Dst
-bs_init_bits Fail Sz=u Words=u==0 Regs Flags Dst => i_bs_init_bits Sz Regs Dst
-bs_init_bits Fail Sz=u Words Regs Flags Dst => i_bs_init_bits_heap Sz Words Regs Dst
+bs_init_bits Fail Sz=u Words=u==0 Regs Flags Dst =>
+ i_bs_init_bits Sz Regs Dst
+bs_init_bits Fail Sz=u Words Regs Flags Dst =>
+ i_bs_init_bits_heap Sz Words Regs Dst
-bs_init_bits Fail Sz Words=u==0 Regs Flags Dst => \
- i_bs_init_bits_fail Sz Fail Regs Dst
-bs_init_bits Fail Sz Words Regs Flags Dst => \
- i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
+bs_init_bits Fail Sz Words=u==0 Regs Flags Dst =>
+ i_bs_init_bits_fail Sz Fail Regs Dst
+bs_init_bits Fail Sz Words Regs Flags Dst =>
+ i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
i_bs_init_bits_fail xy j? t? x
@@ -1270,14 +1308,14 @@ bs_add Fail S1=i==0 S2 Unit=u==1 D => move S2 D
bs_add j? s s t? x
-bs_append Fail Size Extra Live Unit Bin Flags Dst => \
- move Bin x | i_bs_append Fail Extra Live Unit Size Dst
+bs_append Fail Size Extra Live Unit Bin Flags Dst =>
+ move Bin x | i_bs_append Fail Extra Live Unit Size Dst
-bs_private_append Fail Size Unit Bin Flags Dst => \
- i_bs_private_append Fail Unit Size Bin Dst
+bs_private_append Fail Size Unit Bin Flags Dst =>
+ i_bs_private_append Fail Unit Size Bin Dst
-i_bs_private_append Fail Unit Size Bin Dst=y => \
- i_bs_private_append Fail Unit Size Bin x | move x Dst
+i_bs_private_append Fail Unit Size Bin Dst=y =>
+ i_bs_private_append Fail Unit Size Bin x | move x Dst
bs_init_writable
@@ -1288,8 +1326,8 @@ i_bs_private_append j? t s S x
# Storing integers into binaries.
#
-bs_put_integer Fail=j Sz=sq Unit=u Flags=u Src=s => \
- put_integer(Fail, Sz, Unit, Flags, Src)
+bs_put_integer Fail=j Sz=sq Unit=u Flags=u Src=s =>
+ put_integer(Fail, Sz, Unit, Flags, Src)
i_new_bs_put_integer j? S t s
i_new_bs_put_integer_imm xyc j? W t
@@ -1305,8 +1343,8 @@ bs_put_utf8 Fail u Src => i_bs_put_utf8 Fail Src
bs_put_utf16 Fail Flags Src => put_utf16(Fail, Flags, Src)
-bs_put_utf32 Fail=j Flags=u Src=s => \
- i_bs_validate_unicode Fail Src | bs_put_integer Fail i=32 u=1 Flags Src
+bs_put_utf32 Fail=j Flags=u Src=s =>
+ i_bs_validate_unicode Fail Src | bs_put_integer Fail i=32 u=1 Flags Src
i_bs_utf8_size S x
i_bs_utf16_size S x
@@ -1329,10 +1367,10 @@ i_bs_validate_unicode Fail Src=c => move Src x | i_bs_validate_unicode Fail x
# Will fail. No need to keep the instruction, because bs_add or
# bs_init* would already have raised an exception.
-bs_put_float Fail Sz=q Unit Flags Val =>
+bs_put_float Fail Sz=q Unit Flags Val => _
-bs_put_float Fail=j Sz=s Unit=u Flags=u Src=s => \
- put_float(Fail, Sz, Unit, Flags, Src)
+bs_put_float Fail=j Sz=s Unit=u Flags=u Src=s =>
+ put_float(Fail, Sz, Unit, Flags, Src)
i_new_bs_put_float j? S t s
i_new_bs_put_float_imm j? W t s
@@ -1341,17 +1379,17 @@ i_new_bs_put_float_imm j? W t s
# Storing binaries into binaries.
#
-bs_put_binary Fail=j Sz=s Unit=u Flags=u Src=s => \
- put_binary(Fail, Sz, Unit, Flags, Src)
+bs_put_binary Fail=j Sz=s Unit=u Flags=u Src=s =>
+ put_binary(Fail, Sz, Unit, Flags, Src)
-# In unoptimized code, the binary argument could be a literal. (In optimized code,
-# there would be a bs_put_string instruction.)
-i_new_bs_put_binary Fail Size Unit Lit=c => \
- move Lit x | i_new_bs_put_binary Fail Size Unit x
-i_new_bs_put_binary_imm Fail Size Lit=c => \
- move Lit x | i_new_bs_put_binary_imm Fail Size x
-i_new_bs_put_binary_all Lit=c Fail Unit => \
- move Lit x | i_new_bs_put_binary_all x Fail Unit
+# In unoptimized code, the binary argument could be a literal. (In optimized
+# code, there would be a bs_put_string instruction.)
+i_new_bs_put_binary Fail Size Unit Lit=c =>
+ move Lit x | i_new_bs_put_binary Fail Size Unit x
+i_new_bs_put_binary_imm Fail Size Lit=c =>
+ move Lit x | i_new_bs_put_binary_imm Fail Size x
+i_new_bs_put_binary_all Lit=c Fail Unit =>
+ move Lit x | i_new_bs_put_binary_all x Fail Unit
i_new_bs_put_binary j? S t S
i_new_bs_put_binary_imm j? W S
@@ -1395,8 +1433,8 @@ i_fnegate l l
# FPE signals were disabled in OTP 21 and we don't intend to ever
# enable them again.
#
-fclearerror =>
-fcheckerror p =>
+fclearerror => _
+fcheckerror p => _
%hot
@@ -1408,68 +1446,48 @@ apply t
apply_last t Q
#
-# Handle compatibility with OTP 17 here.
+# Map instructions. First introduced in R17.
#
-i_put_map_assoc/4
-
-# We KNOW that in OTP 20 (actually OTP 18 and higher), a put_map_assoc instruction
-# is always preceded by an is_map test. That means that put_map_assoc can never
-# fail and does not need any failure label.
-
-put_map_assoc Fail Map Dst Live Size Rest=* | compiled_with_otp_20_or_higher() => \
- i_put_map_assoc Map Dst Live Size Rest
-
-# Translate the put_map_assoc instruction if the module was compiled by a compiler
-# before 20. This is only necessary if the OTP 17 compiler was used, but we
-# have no safe and relatively easy way to know whether OTP 18/19 was used.
-
-put_map_assoc Fail=p Map Dst Live Size Rest=* => \
- ensure_map Map | i_put_map_assoc Map Dst Live Size Rest
-put_map_assoc Fail=f Map Dst Live Size Rest=* => \
- is_map Fail Map | i_put_map_assoc Map Dst Live Size Rest
+# We KNOW that in OTP 18 and higher, a put_map_assoc instruction is
+# always preceded by an is_map test. That means that put_map_assoc can
+# never fail and does not need any failure label.
-ensure_map Lit=q | literal_is_map(Lit) =>
-ensure_map Src=cqy => move Src x | ensure_map x
-
-%cold
-ensure_map x
-%hot
+put_map_assoc Fail Map Dst Live Size Rest=* =>
+ i_put_map_assoc Map Dst Live Size Rest
-#
-# Map instructions. First introduced in R17.
-#
+i_put_map_assoc/4
sorted_put_map_assoc/4
-i_put_map_assoc Map Dst Live Size Rest=* | map_key_sort(Size, Rest) => \
- sorted_put_map_assoc Map Dst Live Size Rest
+i_put_map_assoc Map Dst Live Size Rest=* | map_key_sort(Size, Rest) =>
+ sorted_put_map_assoc Map Dst Live Size Rest
sorted_put_map_exact/5
-put_map_exact F Map Dst Live Size Rest=* | map_key_sort(Size, Rest) => \
- sorted_put_map_exact F Map Dst Live Size Rest
+put_map_exact F Map Dst Live Size Rest=* | map_key_sort(Size, Rest) =>
+ sorted_put_map_exact F Map Dst Live Size Rest
+
+sorted_put_map_assoc Map Dst Live Size Rest=* | is_empty_map(Map) =>
+ new_map Dst Live Size Rest
+sorted_put_map_assoc Src=xyc Dst Live Size Rest=* =>
+ update_map_assoc Src Dst Live Size Rest
-sorted_put_map_assoc Map Dst Live Size Rest=* | is_empty_map(Map) => \
- new_map Dst Live Size Rest
-sorted_put_map_assoc Src=xyc Dst Live Size Rest=* => \
- update_map_assoc Src Dst Live Size Rest
+sorted_put_map_exact Fail Src=xy Dst Live Size Rest=* =>
+ update_map_exact Src Fail Dst Live Size Rest
-sorted_put_map_exact Fail Src=xy Dst Live Size Rest=* => \
- update_map_exact Src Fail Dst Live Size Rest
# Literal map arguments for an exact update operation are extremely rare.
-sorted_put_map_exact Fail Src Dst Live Size Rest=* => \
- move Src x | update_map_exact x Fail Dst Live Size Rest
+sorted_put_map_exact Fail Src Dst Live Size Rest=* =>
+ move Src x | update_map_exact x Fail Dst Live Size Rest
-new_map Dst Live Size Rest=* | is_small_map_literal_keys(Size, Rest) => \
- new_small_map_lit(Dst, Live, Size, Rest)
+new_map Dst Live Size Rest=* | is_small_map_literal_keys(Size, Rest) =>
+ new_small_map_lit(Dst, Live, Size, Rest)
new_map d t I *
i_new_small_map_lit d t q *
update_map_assoc xyc d t I *
update_map_exact xy j? d t I *
-is_map Fail Lit=q | literal_is_map(Lit) =>
+is_map Fail Lit=q | literal_is_map(Lit) => _
is_map Fail cq => jump Fail
-
is_map f? xy
## Transform has_map_fields #{ K1 := _, K2 := _ } to has_map_elements
@@ -1478,18 +1496,18 @@ has_map_fields Fail Src Size Rest=* => has_map_fields(Fail, Src, Size, Rest)
## Transform get_map_elements(s) #{ K1 := V1, K2 := V2 }
-get_map_elements Fail Src Size=u==2 Rest=* => \
+get_map_elements Fail Src Size=u==2 Rest=* =>
get_map_element(Fail, Src, Size, Rest)
-get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) => \
- get_map_elements(Fail, Src, Size, Rest)
+get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) =>
+ get_map_elements(Fail, Src, Size, Rest)
i_get_map_elements f? s I *
-i_get_map_element_hash Fail Src=c Key Hash Dst => \
+i_get_map_element_hash Fail Src=c Key Hash Dst =>
move Src x | i_get_map_element_hash Fail x Key Hash Dst
i_get_map_element_hash f? xy c I xy
-i_get_map_element Fail Src=c Key Dst => \
+i_get_map_element Fail Src=c Key Dst =>
move Src x | i_get_map_element Fail x Key Dst
i_get_map_element f? xy xy xy
@@ -1499,28 +1517,28 @@ i_get_map_element f? xy xy xy
gen_plus/5
gen_minus/5
-gc_bif1 Fail Live u$bif:erlang:splus/1 Src Dst => \
- gen_plus Fail Live Src i Dst
-gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst => \
- gen_plus Fail Live S1 S2 Dst
+gc_bif1 Fail Live u$bif:erlang:splus/1 Src Dst =>
+ gen_plus Fail Live Src i Dst
+gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst =>
+ gen_plus Fail Live S1 S2 Dst
-gc_bif1 Fail Live u$bif:erlang:sminus/1 Src Dst => \
- i_unary_minus Src Fail Dst
-gc_bif2 Fail Live u$bif:erlang:sminus/2 S1 S2 Dst => \
- gen_minus Fail Live S1 S2 Dst
+gc_bif1 Fail Live u$bif:erlang:sminus/1 Src Dst =>
+ i_unary_minus Src Fail Dst
+gc_bif2 Fail Live u$bif:erlang:sminus/2 S1 S2 Dst =>
+ gen_minus Fail Live S1 S2 Dst
#
# Optimize addition and subtraction of small literals using
# the i_increment/3 instruction (in bodies, not in guards).
#
-gen_plus p Live Int=i Reg=d Dst => \
- increment(Reg, Int, Dst)
-gen_plus p Live Reg=d Int=i Dst => \
- increment(Reg, Int, Dst)
+gen_plus p Live Int=i Reg=d Dst =>
+ increment(Reg, Int, Dst)
+gen_plus p Live Reg=d Int=i Dst =>
+ increment(Reg, Int, Dst)
-gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) => \
- increment_from_minus(Reg, Int, Dst)
+gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) =>
+ increment_from_minus(Reg, Int, Dst)
#
# Arithmetic instructions.
@@ -1529,39 +1547,40 @@ gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) => \
# It is OK to swap arguments for '+' in a guard. It is also
# OK to turn minus into plus in a guard.
gen_plus Fail=f Live S1=c S2 Dst => i_plus S2 S1 Fail Dst
-gen_minus Fail=f Live S1 S2=i Dst | negation_is_small(S2) => \
+gen_minus Fail=f Live S1 S2=i Dst | negation_is_small(S2) =>
plus_from_minus(Fail, Live, S1, S2, Dst)
gen_plus Fail Live S1 S2 Dst => i_plus S1 S2 Fail Dst
gen_minus Fail Live S1 S2 Dst => i_minus S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:stimes/2 S1 S2 Dst => \
- i_times Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:stimes/2 S1 S2 Dst =>
+ i_times Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:div/2 S1 S2 Dst => \
- i_m_div Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:intdiv/2 S1 S2 Dst => \
- i_int_div Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:div/2 S1 S2 Dst =>
+ i_m_div Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 S1 S2 Dst =>
+ i_int_div Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:rem/2 S1 S2 Dst => \
- i_rem S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:rem/2 S1 S2 Dst =>
+ i_rem S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:bsl/2 S1 S2 Dst => \
- i_bsl S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:bsr/2 S1 S2 Dst => \
- i_bsr S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:bsl/2 S1 S2 Dst =>
+ i_bsl S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:bsr/2 S1 S2 Dst =>
+ i_bsr S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:band/2 S1 S2 Dst => \
- i_band S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:band/2 S1 S2 Dst =>
+ i_band S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:bor/2 S1 S2 Dst => \
- i_bor Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:bor/2 S1 S2 Dst =>
+ i_bor Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst => \
- i_bxor Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst =>
+ i_bxor Fail S1 S2 Dst
-gc_bif1 Fail Live u$bif:erlang:bnot/1 Src Dst=d => i_int_bnot Fail Src Dst
+gc_bif1 Fail Live u$bif:erlang:bnot/1 Src Dst=d =>
+ i_int_bnot Fail Src Dst
i_increment rxy W d
@@ -1617,8 +1636,8 @@ bif1 Fail u$bif:erlang:trunc/1 s d => too_old_compiler
# Handle the length/1 guard BIF specially to make it trappable.
#
-gc_bif1 Fail=j Live u$bif:erlang:length/1 Src Dst => \
- i_length_setup Live Src | i_length Fail Live Dst
+gc_bif1 Fail=j Live u$bif:erlang:length/1 Src Dst =>
+ i_length_setup Live Src | i_length Fail Live Dst
i_length_setup Live Src=c => move Src x | i_length_setup Live x
@@ -1643,7 +1662,7 @@ gc_bif3 Fail=f Live Bif S1 S2 S3 Dst => i_bif3 S3 S2 S1 Fail Bif Dst
# encountered.
#
unsupported_guard_bif/3
-unsupported_guard_bif A B C | never() =>
+unsupported_guard_bif A B C | never() => _
#
# R13B03
@@ -1659,8 +1678,8 @@ on_load
recv_mark f => i_recv_mark
i_recv_mark
-recv_set Fail | label Lbl | loop_rec Lf Reg => \
- i_recv_set | label Lbl | loop_rec Lf Reg
+recv_set Fail | label Lbl | loop_rec Lf Reg =>
+ i_recv_set | label Lbl | loop_rec Lf Reg
i_recv_set
#
diff --git a/erts/emulator/beam/emu/predicates.tab b/erts/emulator/beam/emu/predicates.tab
index 4542d8bf0f..82f9501d39 100644
--- a/erts/emulator/beam/emu/predicates.tab
+++ b/erts/emulator/beam/emu/predicates.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2020. All Rights Reserved.
+// Copyright Ericsson AB 2020-2021. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -45,3 +45,28 @@ pred.independent_moves(Src1, Dst1, Src2, Dst2) {
(Src2.type != Dst1.type || Src2.val != Dst1.val) &&
(Dst1.type != Dst2.type ||Dst1.val != Dst2.val);
}
+
+pred.needs_nif_padding() {
+ Export *e = erts_active_export_entry(S->module, S->function, S->arity);
+
+ if (e != NULL && e->bif_number != -1) {
+ return 1;
+ }
+
+ /* If the module may load a NIF lib, all functions or functions declared as
+ * -nifs() must be able to hold a NIF stub. So we'll pad to that size at the
+ * end of every potential NIF function.
+ */
+ return S->may_load_nif &&
+ (S->code_hdr->are_nifs == NULL ||
+ S->code_hdr->are_nifs[S->function_number-1]);
+}
+
+// Test whether the given literal is a map.
+pred.literal_is_map(Lit) {
+ Eterm term;
+
+ ASSERT(Lit.type == TAG_q);
+ term = beamfile_get_literal(&S->beam, Lit.val);
+ return is_map(term);
+}
diff --git a/erts/emulator/beam/emu/trace_instrs.tab b/erts/emulator/beam/emu/trace_instrs.tab
index 630a9eb2d9..5241af9ca9 100644
--- a/erts/emulator/beam/emu/trace_instrs.tab
+++ b/erts/emulator/beam/emu/trace_instrs.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2017-2020. All Rights Reserved.
+// Copyright Ericsson AB 2017-2021. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -165,7 +165,7 @@ i_debug_breakpoint() {
HEAVY_SWAPIN;
if (breakpoint_handler) {
- I = breakpoint_handler->addresses[erts_active_code_ix()];
+ I = breakpoint_handler->dispatch.addresses[erts_active_code_ix()];
Goto(*I);
}
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index bbe0e90ae1..3ab9c9d1b6 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -38,7 +38,6 @@
#include "erl_db.h"
#include "erl_binary.h"
#include "erl_bits.h"
-#include "erl_mtrace.h"
#include "erl_mseg.h"
#include "erl_monitor_link.h"
#include "erl_hl_timer.h"
@@ -80,6 +79,9 @@
#define ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC
#define ERTS_ALC_DEFAULT_ACUL_LL_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC
+#define ERTS_ALC_DEFAULT_ENABLED_ACFUL ERTS_ALC_DEFAULT_ENABLED_ACUL - 20
+#define ERTS_ALC_DEFAULT_ENABLED_ACFUL_EHEAP_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC - 20
+#define ERTS_ALC_DEFAULT_ENABLED_ACFUL_LL_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC - 20
#ifdef DEBUG
static Uint install_debug_functions(void);
@@ -191,10 +193,6 @@ typedef struct {
int top_pad;
int dirty_alloc_insts;
AlcUInit_t alloc_util;
- struct {
- char *mtrace;
- char *nodename;
- } instr;
struct au_init sl_alloc;
struct au_init std_alloc;
struct au_init ll_alloc;
@@ -315,6 +313,7 @@ set_default_literal_alloc_opts(struct au_init *ip)
ip->init.util.rsbcmt = 0;
ip->init.util.rmbcmt = 0;
ip->init.util.acul = 0;
+ ip->init.util.acful = 0;
#if defined(ARCH_32)
# if HAVE_ERTS_MSEG
@@ -597,6 +596,9 @@ adjust_carrier_migration_support(struct au_init *auip)
auip->init.aoff.blk_order = FF_BF;
}
}
+ if (auip->init.util.acful > auip->init.util.acul) {
+ auip->init.util.acful = auip->init.util.acul;
+ }
}
void
@@ -644,6 +646,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
= ERTS_MAGIC_BIN_UNALIGNED_SIZE(sizeof(ErtsMagicIndirectionWord));
fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_RECV_MARK_BLK)]
= sizeof(ErtsRecvMarkerBlock);
+ fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_SIGQ_BUFFERS)]
+ = sizeof(ErtsSignalInQueueBufferArray);
#ifdef HARD_DEBUG
hdbg_init();
@@ -657,9 +661,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
if (ncpu < 1)
ncpu = 1;
- erts_tsd_key_create(&erts_allctr_prelock_tsd_key,
- "erts_allctr_prelock_tsd_key");
-
erts_sys_alloc_init();
erts_init_utils_mem();
@@ -697,6 +698,7 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
/* Make adjustments for carrier migration support */
init.temp_alloc.init.util.acul = 0;
+ init.temp_alloc.init.util.acful = 0;
adjust_carrier_migration_support(&init.sl_alloc);
adjust_carrier_migration_support(&init.std_alloc);
adjust_carrier_migration_support(&init.ll_alloc);
@@ -733,6 +735,16 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
init.driver_alloc.init.util.acul = 0;
init.fix_alloc.init.util.acul = 0;
init.literal_alloc.init.util.acul = 0;
+ init.temp_alloc.init.util.acful = 0;
+ init.sl_alloc.init.util.acful = 0;
+ init.std_alloc.init.util.acful = 0;
+ init.ll_alloc.init.util.acful = 0;
+ init.eheap_alloc.init.util.acful = 0;
+ init.binary_alloc.init.util.acful = 0;
+ init.ets_alloc.init.util.acful = 0;
+ init.driver_alloc.init.util.acful = 0;
+ init.fix_alloc.init.util.acful = 0;
+ init.literal_alloc.init.util.acful = 0;
}
/* Only temp_alloc can use thread specific interface */
@@ -770,7 +782,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
if (!init.temp_alloc.thr_spec)
refuse_af_strategy(&init.temp_alloc);
- erts_mtrace_pre_init();
#if HAVE_ERTS_MSEG
init.mseg.nos = erts_no_schedulers;
init.mseg.ndai = init.dirty_alloc_insts;
@@ -826,8 +837,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);
- erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
-
start_au_allocator(ERTS_ALC_A_TEMPORARY,
&init.temp_alloc,
&temp_alloc_state);
@@ -869,8 +878,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
&init.test_alloc,
&test_alloc_state);
- erts_mtrace_install_wrapper_functions();
-
init_aireq_alloc();
#ifdef DEBUG
@@ -1286,6 +1293,30 @@ get_acul_value(struct au_init *auip, char *param_end, char** argv, int* ip)
return (Uint) tmp;
}
+static Uint
+get_acful_value(struct au_init *auip, char *param_end, char** argv, int* ip)
+{
+ Sint tmp;
+ char *rest;
+ char *param = argv[*ip]+1;
+ char *value = get_value(param_end, argv, ip);
+ if (sys_strcmp(value, "de") == 0) {
+ switch (auip->init.util.alloc_no) {
+ case ERTS_ALC_A_LONG_LIVED:
+ return ERTS_ALC_DEFAULT_ENABLED_ACFUL_LL_ALLOC;
+ case ERTS_ALC_A_EHEAP:
+ return ERTS_ALC_DEFAULT_ENABLED_ACFUL_EHEAP_ALLOC;
+ default:
+ return ERTS_ALC_DEFAULT_ENABLED_ACFUL;
+ }
+ }
+ errno = 0;
+ tmp = (Sint) ErtsStrToSint(value, &rest, 10);
+ if (errno != 0 || rest == value || tmp < 0 || 100 < tmp)
+ bad_value(param, param_end, value);
+ return (Uint) tmp;
+}
+
static void
handle_au_arg(struct au_init *auip,
char* sub_param,
@@ -1315,6 +1346,10 @@ handle_au_arg(struct au_init *auip,
value = get_amount_value(sub_param + 5, argv, ip);
wp = &auip->init.util.acfml;
}
+ else if (has_prefix("acful", sub_param)) {
+ value = get_acful_value(auip, sub_param + 5, argv, ip);
+ wp = &auip->init.util.acful;
+ }
else
goto bad_switch;
@@ -1381,8 +1416,10 @@ handle_au_arg(struct au_init *auip,
bad_value(param, sub_param + 1, alg);
}
}
- if (!strategy_support_carrier_migration(auip))
+ if (!strategy_support_carrier_migration(auip)) {
auip->init.util.acul = 0;
+ auip->init.util.acful = 0;
+ }
} else if (has_prefix("atags", sub_param)) {
auip->init.util.atags = get_bool_value(sub_param + 5, argv, ip);
}
@@ -1514,6 +1551,7 @@ handle_au_arg(struct au_init *auip,
else if (res == 0) {
auip->thr_spec = 0;
auip->init.util.acul = 0;
+ auip->init.util.acful = 0;
break;
}
goto bad_switch;
@@ -1725,6 +1763,7 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
for (a = 0; a < aui_sz; a++) {
aui[a]->thr_spec = 0;
aui[a]->init.util.acul = 0;
+ aui[a]->init.util.acful = 0;
aui[a]->init.util.ramv = 0;
aui[a]->init.util.lmbcs = 5*1024*1024;
}
@@ -1738,15 +1777,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
bad_param(param, param+1);
}
break;
- case 'i':
- switch (argv[i][3]) {
- case 't':
- init->instr.mtrace = get_value(argv[i]+4, argv, &i);
- break;
- default:
- bad_param(param, param+2);
- }
- break;
case 'l':
if (has_prefix("pm", param+2)) {
arg = get_value(argv[i]+5, argv, &i);
@@ -1816,18 +1846,6 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
case '-':
if (argv[i][2] == '\0') {
/* End of system flags reached */
- if (init->instr.mtrace) {
- while (i < *argc) {
- if(sys_strcmp(argv[i], "-sname") == 0
- || sys_strcmp(argv[i], "-name") == 0) {
- if (i + 1 <*argc) {
- init->instr.nodename = argv[i+1];
- break;
- }
- }
- i++;
- }
- }
goto args_parsed;
}
break;
@@ -2202,7 +2220,7 @@ erts_memory(fmtfn_t *print_to_p, void *print_to_arg, void *proc, Eterm earg)
ERTS_LC_ASSERT(erts_thr_progress_is_blocking());
- /* Figure out whats wanted... */
+ /* Figure out what's wanted... */
length = 0;
if (is_non_value(earg)) { /* i.e. wants all */
@@ -2870,9 +2888,6 @@ erts_allocator_info(fmtfn_t to, void *arg)
erts_print(to, arg, "=allocator:instr\n");
- erts_print(to, arg, "option t: %s\n",
- erts_mtrace_enabled ? "true" : "false");
-
}
Eterm
@@ -2974,14 +2989,6 @@ erts_allocator_options(void *proc)
terms[length++] = erts_mmap_info_options(&erts_dflt_mmapper, NULL, NULL,
NULL, hpp, szp);
#endif
- {
- Eterm o[1], v[1];
- o[0] = ERTS_MAKE_AM("t");
- v[0] = erts_mtrace_enabled ? am_true : am_false;
-
- atoms[length] = ERTS_MAKE_AM("instr");
- terms[length++] = erts_bld_2tup_list(hpp, szp, 1, o, v);
- }
atoms[length] = ERTS_MAKE_AM("lock_physical_memory");
terms[length++] = (lock_all_physical_memory ? am_all : am_no);
@@ -3139,7 +3146,7 @@ reply_alloc_info(void *vair)
if (hpp)
sys_alloc_stat(&sas);
if (szp) {
- /* ensure ehough heap */
+ /* ensure enough heap */
sas.top_pad = INT_MAX;
sas.trim_threshold = INT_MAX;
}
@@ -3480,54 +3487,6 @@ badarg:
return res;
}
-/*
- * The allocator wrapper prelocking stuff below is about the locking order.
- * It only affects wrappers (erl_mtrace.c) that keep locks during
- * alloc/realloc/free.
- *
- * Some query functions in erl_alloc_util.c lock the allocator mutex and then
- * use erts_printf that in turn may call the sys allocator through the wrappers.
- * To avoid breaking locking order these query functions first "pre-locks" all
- * allocator wrappers.
- */
-ErtsAllocatorWrapper_t *erts_allctr_wrappers;
-int erts_allctr_wrapper_prelocked = 0;
-erts_tsd_key_t erts_allctr_prelock_tsd_key;
-
-void erts_allctr_wrapper_prelock_init(ErtsAllocatorWrapper_t* wrapper)
-{
- ASSERT(wrapper->lock && wrapper->unlock);
- wrapper->next = erts_allctr_wrappers;
- erts_allctr_wrappers = wrapper;
-}
-
-void erts_allctr_wrapper_pre_lock(void)
-{
- if (erts_allctr_wrappers) {
- ErtsAllocatorWrapper_t* wrapper = erts_allctr_wrappers;
- for ( ; wrapper; wrapper = wrapper->next) {
- wrapper->lock();
- }
- ASSERT(!erts_allctr_wrapper_prelocked);
- erts_allctr_wrapper_prelocked = 1;
- erts_tsd_set(erts_allctr_prelock_tsd_key, (void*)1);
- }
-}
-
-void erts_allctr_wrapper_pre_unlock(void)
-{
- if (erts_allctr_wrappers) {
- ErtsAllocatorWrapper_t* wrapper = erts_allctr_wrappers;
-
- erts_allctr_wrapper_prelocked = 0;
- erts_tsd_set(erts_allctr_prelock_tsd_key, (void*)0);
- for ( ; wrapper; wrapper = wrapper->next) {
- wrapper->unlock();
- }
- }
-}
-
-
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* NOTE: erts_alc_test() is only supposed to be used for testing. *
* *
diff --git a/erts/emulator/beam/erl_alloc.h b/erts/emulator/beam/erl_alloc.h
index c0c1890b0a..00ab6284d7 100644
--- a/erts/emulator/beam/erl_alloc.h
+++ b/erts/emulator/beam/erl_alloc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -164,18 +164,6 @@ typedef struct {
extern ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
-typedef struct ErtsAllocatorWrapper_t_ {
- void (*lock)(void);
- void (*unlock)(void);
- struct ErtsAllocatorWrapper_t_* next;
-}ErtsAllocatorWrapper_t;
-extern ErtsAllocatorWrapper_t *erts_allctr_wrappers;
-extern int erts_allctr_wrapper_prelocked;
-extern erts_tsd_key_t erts_allctr_prelock_tsd_key;
-void erts_allctr_wrapper_prelock_init(ErtsAllocatorWrapper_t* wrapper);
-void erts_allctr_wrapper_pre_lock(void);
-void erts_allctr_wrapper_pre_unlock(void);
-
void erts_alloc_register_scheduler(void *vesdp);
void erts_alloc_register_delayed_dealloc_handler_thread(ErtsThrAllocData *tadp,
int ix);
@@ -225,11 +213,11 @@ Eterm erts_alloc_set_dyn_param(struct process*, Eterm);
#if !ERTS_ALC_DO_INLINE
-void *erts_alloc(ErtsAlcType_t type, Uint size);
-void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size);
void erts_free(ErtsAlcType_t type, void *ptr);
-void *erts_alloc_fnf(ErtsAlcType_t type, Uint size);
-void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size);
+void *erts_alloc(ErtsAlcType_t type, Uint size) ERTS_ATTR_MALLOC_USD(2,erts_free,2);
+void *erts_realloc(ErtsAlcType_t type, void *ptr, Uint size) ERTS_ATTR_ALLOC_SIZE(3);
+void *erts_alloc_fnf(ErtsAlcType_t type, Uint size) ERTS_ATTR_MALLOC_USD(2,erts_free,2);
+void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size) ERTS_ATTR_ALLOC_SIZE(3);
int erts_is_allctr_wrapper_prelocked(void);
#ifdef ERTS_HAVE_IS_IN_LITERAL_RANGE
int erts_is_in_literal_range(void* ptr);
@@ -239,7 +227,7 @@ int erts_get_thr_alloc_ix(void);
#endif /* #if !ERTS_ALC_DO_INLINE */
-void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size);
+void *erts_alloc_permanent_cache_aligned(ErtsAlcType_t type, Uint size) ERTS_ATTR_MALLOC_US(2);
#ifndef ERTS_CACHE_LINE_SIZE
/* Assumed cache line size */
@@ -321,13 +309,6 @@ void *erts_realloc_fnf(ErtsAlcType_t type, void *ptr, Uint size)
}
ERTS_ALC_INLINE
-int erts_is_allctr_wrapper_prelocked(void)
-{
- return erts_allctr_wrapper_prelocked /* locked */
- && !!erts_tsd_get(erts_allctr_prelock_tsd_key); /* by me */
-}
-
-ERTS_ALC_INLINE
ErtsThrAllocData *erts_get_thr_alloc_data(void)
{
return (ErtsThrAllocData *) erts_tsd_get(erts_thr_alloc_data_key);
diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types
index f01d1a96d3..24ba019075 100644
--- a/erts/emulator/beam/erl_alloc.types
+++ b/erts/emulator/beam/erl_alloc.types
@@ -254,6 +254,7 @@ type BINARY_FIND SHORT_LIVED PROCESSES binary_find
type CRASH_DUMP STANDARD SYSTEM crash_dump
type DIST_TRANSCODE SHORT_LIVED SYSTEM dist_transcode_context
type RLA_BLOCK_CNTRS LONG_LIVED SYSTEM release_literal_area_block_counters
+type SIGQ_BUFFERS FIXED_SIZE PROCESSES process_signal_queue_buffers
type THR_Q_EL STANDARD SYSTEM thr_q_element
type THR_Q_EL_SL FIXED_SIZE SYSTEM sl_thr_q_element
@@ -273,6 +274,7 @@ type THR_PRGR_DATA LONG_LIVED SYSTEM thr_prgr_data
type T_THR_PRGR_DATA SHORT_LIVED SYSTEM temp_thr_prgr_data
type RELEASE_LAREA SHORT_LIVED SYSTEM release_literal_area
type SIG_DATA SHORT_LIVED PROCESSES signal_data
+type SIG_YIELD_DATA SHORT_LIVED PROCESSES signal_yield_data
type DIST_DEMONITOR SHORT_LIVED PROCESSES dist_demonitor
type CML_CLEANUP SHORT_LIVED SYSTEM connection_ml_cleanup
type ML_YIELD_STATE SHORT_LIVED SYSTEM monitor_link_yield_state
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index 5ae78c7153..be5705c637 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,6 @@
#include "global.h"
#include "big.h"
#include "erl_mmap.h"
-#include "erl_mtrace.h"
#define GET_ERL_ALLOC_UTIL_IMPL
#include "erl_alloc_util.h"
#include "erl_mseg.h"
@@ -51,6 +50,7 @@
#include "erl_thr_progress.h"
#include "erl_bif_unique.h"
#include "erl_nif.h"
+#include "erl_global_literals.h"
#ifdef ERTS_ENABLE_LOCK_COUNT
#include "erl_lock_count.h"
@@ -1090,8 +1090,6 @@ erts_alcu_sys_alloc(Allctr_t *allctr, Uint* size_p, int superalign)
#endif
res = erts_sys_alloc(0, NULL, size);
INC_CC(allctr->calls.sys_alloc);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_alloc(res, allctr->alloc_no, ERTS_ALC_A_SYSTEM, size);
return res;
}
@@ -1108,12 +1106,6 @@ erts_alcu_sys_realloc(Allctr_t *allctr, void *ptr, Uint *size_p, Uint old_size,
#endif
res = erts_sys_realloc(0, NULL, ptr, size);
INC_CC(allctr->calls.sys_realloc);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_realloc(res,
- allctr->alloc_no,
- ERTS_ALC_A_SYSTEM,
- ptr,
- size);
return res;
}
@@ -1127,8 +1119,6 @@ erts_alcu_sys_dealloc(Allctr_t *allctr, void *ptr, Uint size, int superalign)
#endif
erts_sys_free(0, NULL, ptr);
INC_CC(allctr->calls.sys_free);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_free(allctr->alloc_no, ERTS_ALC_A_SYSTEM, ptr);
}
#ifdef ARCH_32
@@ -1703,7 +1693,7 @@ dealloc_mbc(Allctr_t *allctr, Carrier_t *crr)
}
-static UWord allctr_abandon_limit(Allctr_t *allctr);
+static UWord allctr_abandon_limit(Allctr_t *allctr, UWord);
static void set_new_allctr_abandon_limit(Allctr_t*);
static void abandon_carrier(Allctr_t*, Carrier_t*);
static void poolify_my_carrier(Allctr_t*, Carrier_t*);
@@ -1780,7 +1770,7 @@ get_used_allctr(Allctr_t *pref_allctr, int pref_lock, void *p, UWord *sizep,
* This carrier has just been given back to us by writing
* to crr->allctr with a write barrier (see abandon_carrier).
*
- * We need a mathing read barrier to guarantee a correct view
+ * We need a matching read barrier to guarantee a correct view
* of the carrier for deallocation work.
*/
act = erts_atomic_cmpxchg_rb(&crr->allctr,
@@ -2261,7 +2251,7 @@ check_abandon_carrier(Allctr_t *allctr, Block_t *fblk, Carrier_t **busy_pcrr_pp)
if (!ERTS_ALC_IS_CPOOL_ENABLED(allctr))
return;
- ASSERT(allctr->cpool.abandon_limit == allctr_abandon_limit(allctr));
+ ASSERT(allctr->cpool.abandon_limit == allctr_abandon_limit(allctr, allctr->cpool.util_limit));
ASSERT(erts_thr_progress_is_managed_thread());
if (allctr->cpool.disable_abandon)
@@ -2665,6 +2655,9 @@ carrier_mem_discard_free_blocks(Allctr_t *allocator, Carrier_t *carrier)
Block_t *block;
int i;
+ if (carrier->cpool.total_blocks_size > carrier->cpool.discard_limit)
+ return;
+
block = allocator->first_fblk_in_mbc(allocator, carrier);
i = 0;
@@ -2733,7 +2726,7 @@ mbc_free(Allctr_t *allctr, ErtsAlcType_t type, void *p, Carrier_t **busy_pcrr_pp
blk = PREV_BLK(blk);
(*allctr->unlink_free_block)(allctr, blk);
- if (discard) {
+ if (discard && crr->cpool.total_blocks_size <= crr->cpool.discard_limit) {
mem_discard_coalesce(allctr, blk, &discard_region);
}
@@ -2753,7 +2746,7 @@ mbc_free(Allctr_t *allctr, ErtsAlcType_t type, void *p, Carrier_t **busy_pcrr_pp
/* Coalesce with next block... */
(*allctr->unlink_free_block)(allctr, nxt_blk);
- if (discard) {
+ if (discard && crr->cpool.total_blocks_size <= crr->cpool.discard_limit) {
mem_discard_coalesce(allctr, nxt_blk, &discard_region);
}
@@ -2793,7 +2786,7 @@ mbc_free(Allctr_t *allctr, ErtsAlcType_t type, void *p, Carrier_t **busy_pcrr_pp
(*allctr->link_free_block)(allctr, blk);
HARD_CHECK_BLK_CARRIER(allctr, blk);
- if (discard) {
+ if (discard && crr->cpool.total_blocks_size <= crr->cpool.discard_limit) {
mem_discard_finish(allctr, blk, &discard_region);
}
@@ -3079,7 +3072,7 @@ mbc_realloc(Allctr_t *allctr, ErtsAlcType_t type, void *p, Uint size,
}
if (cand_blk_sz < get_blk_sz) {
- /* We wont fit in cand_blk get a new one */
+ /* We won't fit in cand_blk get a new one */
#endif /* !MBC_REALLOC_ALWAYS_MOVES */
@@ -3153,7 +3146,7 @@ mbc_realloc(Allctr_t *allctr, ErtsAlcType_t type, void *p, Uint size,
/*
* Copy user-data then update new blocks in mbc_alloc_finalize().
* mbc_alloc_finalize() may write headers at old location of
- * user data; therfore, order is important.
+ * user data; therefore, order is important.
*/
new_p = BLK2UMEM(new_blk);
@@ -3821,7 +3814,7 @@ schedule_dealloc_carrier(Allctr_t *allctr, Carrier_t *crr)
Block_t* first_blk = MBC_TO_FIRST_BLK(allctr, crr);
ERTS_ALC_CPOOL_ASSERT(IS_FREE_LAST_MBC_BLK(first_blk));
- ERTS_ALC_CPOOL_ASSERT(IS_MBC_FIRST_ABLK(allctr, first_blk));
+ ERTS_ALC_CPOOL_ASSERT(IS_MBC_FIRST_FBLK(allctr, first_blk));
ERTS_ALC_CPOOL_ASSERT(crr == FBLK_TO_MBC(first_blk));
ERTS_ALC_CPOOL_ASSERT(crr == FIRST_BLK_TO_MBC(allctr, first_blk));
ERTS_ALC_CPOOL_ASSERT((erts_atomic_read_nob(&crr->allctr)
@@ -3876,6 +3869,17 @@ static void dealloc_my_carrier(Allctr_t *allctr, Carrier_t *crr)
erts_alloc_ensure_handle_delayed_dealloc_call(allctr->ix);
}
+static ERTS_INLINE UWord
+cpoll_init_carrier_limit(Carrier_t *crr, UWord percent_limit) {
+ UWord csz = CARRIER_SZ(crr);
+ UWord limit = percent_limit*csz;
+ if (limit > csz)
+ limit /= 100;
+ else
+ limit = (csz/100)*percent_limit;
+ return limit;
+}
+
static ERTS_INLINE void
cpool_init_carrier_data(Allctr_t *allctr, Carrier_t *crr)
{
@@ -3888,16 +3892,12 @@ cpool_init_carrier_data(Allctr_t *allctr, Carrier_t *crr)
sys_memset(&crr->cpool.blocks_size, 0, sizeof(crr->cpool.blocks_size));
sys_memset(&crr->cpool.blocks, 0, sizeof(crr->cpool.blocks));
crr->cpool.total_blocks_size = 0;
- if (!ERTS_ALC_IS_CPOOL_ENABLED(allctr))
+ if (!ERTS_ALC_IS_CPOOL_ENABLED(allctr)) {
crr->cpool.abandon_limit = 0;
- else {
- UWord csz = CARRIER_SZ(crr);
- UWord limit = csz*allctr->cpool.util_limit;
- if (limit > csz)
- limit /= 100;
- else
- limit = (csz/100)*allctr->cpool.util_limit;
- crr->cpool.abandon_limit = limit;
+ crr->cpool.discard_limit = 0;
+ } else {
+ crr->cpool.abandon_limit = cpoll_init_carrier_limit(crr, allctr->cpool.util_limit);
+ crr->cpool.discard_limit = cpoll_init_carrier_limit(crr, allctr->cpool.free_util_limit);
}
crr->cpool.state = ERTS_MBC_IS_HOME;
}
@@ -3905,7 +3905,7 @@ cpool_init_carrier_data(Allctr_t *allctr, Carrier_t *crr)
static UWord
-allctr_abandon_limit(Allctr_t *allctr)
+allctr_abandon_limit(Allctr_t *allctr, UWord percent_limit)
{
UWord limit;
UWord csz;
@@ -3916,11 +3916,11 @@ allctr_abandon_limit(Allctr_t *allctr)
csz += allctr->mbcs.carriers[i].size;
}
- limit = csz*allctr->cpool.util_limit;
+ limit = csz*percent_limit;
if (limit > csz)
limit /= 100;
else
- limit = (csz/100)*allctr->cpool.util_limit;
+ limit = (csz/100)*percent_limit;
return limit;
}
@@ -3928,7 +3928,7 @@ allctr_abandon_limit(Allctr_t *allctr)
static void ERTS_INLINE
set_new_allctr_abandon_limit(Allctr_t *allctr)
{
- allctr->cpool.abandon_limit = allctr_abandon_limit(allctr);
+ allctr->cpool.abandon_limit = allctr_abandon_limit(allctr, allctr->cpool.util_limit);
}
static void
@@ -4580,6 +4580,7 @@ static struct {
Eterm smbcs;
Eterm mbcgs;
Eterm acul;
+ Eterm acful;
Eterm acnl;
Eterm acfml;
Eterm cp;
@@ -4690,6 +4691,7 @@ init_atoms(Allctr_t *allctr)
AM_INIT(smbcs);
AM_INIT(mbcgs);
AM_INIT(acul);
+ AM_INIT(acful);
AM_INIT(acnl);
AM_INIT(acfml);
AM_INIT(cp);
@@ -5449,7 +5451,7 @@ info_options(Allctr_t *allctr,
Uint *szp)
{
Eterm res = THE_NON_VALUE;
- UWord acul, acnl, acfml;
+ UWord acul, acful, acnl, acfml;
char *cp_str;
Eterm cp_atom;
@@ -5464,6 +5466,7 @@ info_options(Allctr_t *allctr,
}
acul = allctr->cpool.util_limit;
+ acful = allctr->cpool.free_util_limit;
acnl = allctr->cpool.in_pool_limit;
acfml = allctr->cpool.fblk_min_limit;
ASSERT(allctr->cpool.carrier_pool <= ERTS_ALC_A_MAX);
@@ -5512,6 +5515,7 @@ info_options(Allctr_t *allctr,
"option smbcs: %beu\n"
"option mbcgs: %beu\n"
"option acul: %bpu\n"
+ "option acful: %bpu\n"
"option acnl: %bpu\n"
"option acfml: %bpu\n"
"option cp: %s\n",
@@ -5534,6 +5538,7 @@ info_options(Allctr_t *allctr,
allctr->smallest_mbc_size,
allctr->mbc_growth_stages,
acul,
+ acful,
acnl,
acfml,
cp_str);
@@ -5553,6 +5558,9 @@ info_options(Allctr_t *allctr,
add_2tup(hpp, szp, &res,
am.acul,
bld_uint(hpp, szp, acul));
+ add_2tup(hpp, szp, &res,
+ am.acful,
+ bld_uint(hpp, szp, acful));
add_2tup(hpp, szp, &res,
am.mbcgs,
bld_uint(hpp, szp, allctr->mbc_growth_stages));
@@ -5709,13 +5717,11 @@ erts_alcu_info_options(Allctr_t *allctr,
ensure_atoms_initialized(allctr);
if (allctr->thread_safe) {
- erts_allctr_wrapper_pre_lock();
erts_mtx_lock(&allctr->mutex);
}
res = info_options(allctr, print_to_p, print_to_arg, hpp, szp);
if (allctr->thread_safe) {
erts_mtx_unlock(&allctr->mutex);
- erts_allctr_wrapper_pre_unlock();
}
return res;
}
@@ -5748,7 +5754,6 @@ erts_alcu_sz_info(Allctr_t *allctr,
ensure_atoms_initialized(allctr);
if (allctr->thread_safe) {
- erts_allctr_wrapper_pre_lock();
erts_mtx_lock(&allctr->mutex);
}
@@ -5786,7 +5791,6 @@ erts_alcu_sz_info(Allctr_t *allctr,
if (allctr->thread_safe) {
erts_mtx_unlock(&allctr->mutex);
- erts_allctr_wrapper_pre_unlock();
}
return res;
@@ -5819,7 +5823,6 @@ erts_alcu_info(Allctr_t *allctr,
ensure_atoms_initialized(allctr);
if (allctr->thread_safe) {
- erts_allctr_wrapper_pre_lock();
erts_mtx_lock(&allctr->mutex);
}
@@ -5874,7 +5877,6 @@ erts_alcu_info(Allctr_t *allctr,
if (allctr->thread_safe) {
erts_mtx_unlock(&allctr->mutex);
- erts_allctr_wrapper_pre_unlock();
}
return res;
@@ -6811,6 +6813,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
ASSERT(allctr->next_fblk_in_mbc);
allctr->cpool.util_limit = init->acul;
+ allctr->cpool.free_util_limit = init->acful;
allctr->cpool.in_pool_limit = init->acnl;
allctr->cpool.fblk_min_limit = init->acfml;
allctr->cpool.carrier_pool = init->cp;
@@ -6824,6 +6827,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init)
}
else {
allctr->cpool.util_limit = 0;
+ allctr->cpool.free_util_limit = 0;
allctr->cpool.in_pool_limit = 0;
allctr->cpool.fblk_min_limit = 0;
allctr->cpool.carrier_pool = -1;
@@ -7682,17 +7686,23 @@ static int gather_ahist_append_result(hist_tree_t *node, void *arg, Sint reds)
ASSERT(state->building_result);
- hp = erts_produce_heap(&state->msg_factory, 7 + state->hist_slot_count, 0);
+ hp = erts_produce_heap(&state->msg_factory,
+ 7 + state->hist_slot_count +
+ (state->hist_slot_count == 0 ? -1 : 0),
+ 0);
+ if (state->hist_slot_count == 0) {
+ histogram_tuple = erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE);
+ } else {
+ hp[0] = make_arityval(state->hist_slot_count);
- hp[0] = make_arityval(state->hist_slot_count);
+ for (ix = 0; ix < state->hist_slot_count; ix++) {
+ hp[1 + ix] = make_small(node->histogram[ix]);
+ }
- for (ix = 0; ix < state->hist_slot_count; ix++) {
- hp[1 + ix] = make_small(node->histogram[ix]);
+ histogram_tuple = make_tuple(hp);
+ hp += 1 + state->hist_slot_count;
}
- histogram_tuple = make_tuple(hp);
- hp += 1 + state->hist_slot_count;
-
hp[0] = make_arityval(3);
hp[1] = ATAG_ID(node->tag);
hp[2] = alloc_type_atoms[ATAG_TYPE(node->tag)];
@@ -7959,7 +7969,7 @@ static void gather_cinfo_append_result(gather_cinfo_t *state,
term_size = 0;
/* Free block histogram. */
- term_size += 1 + state->hist_slot_count;
+ term_size += (state->hist_slot_count == 0 ? 0 : 1) + state->hist_slot_count;
/* Per-type block list. */
for (ix = ERTS_ALC_A_MIN; ix <= ERTS_ALC_A_MAX; ix++) {
@@ -8010,13 +8020,16 @@ static void gather_cinfo_append_result(gather_cinfo_t *state,
hp += 2;
}
}
-
- hp[0] = make_arityval(state->hist_slot_count);
- for (ix = 0; ix < state->hist_slot_count; ix++) {
- hp[1 + ix] = make_small(info->free_histogram[ix]);
+ if (state->hist_slot_count == 0) {
+ histogram_tuple = erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE);
+ } else {
+ hp[0] = make_arityval(state->hist_slot_count);
+ for (ix = 0; ix < state->hist_slot_count; ix++) {
+ hp[1 + ix] = make_small(info->free_histogram[ix]);
+ }
+ histogram_tuple = make_tuple(hp);
+ hp += 1 + state->hist_slot_count;
}
- histogram_tuple = make_tuple(hp);
- hp += 1 + state->hist_slot_count;
carrier_size = bld_unstable_uint(&hp, NULL, info->carrier_size);
unscanned_size = bld_unstable_uint(&hp, NULL, info->unscanned_size);
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index d4f695443a..84d215e0f0 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,6 +67,7 @@ typedef struct {
UWord smbcs;
UWord mbcgs;
UWord acul;
+ UWord acful;
UWord acnl;
UWord acfml;
@@ -127,6 +128,7 @@ typedef struct {
1024*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
0, /* (%) acul: abandon carrier utilization limit */\
+ 0, /* (%) acful: carrier free utilization limit */\
1000, /* (amount) acnl: abandoned carriers number limit */\
0, /* (bytes) acfml: abandoned carrier fblk min limit */\
/* --- Data not options -------------------------------------------- */\
@@ -167,6 +169,7 @@ typedef struct {
128*1024, /* (bytes) smbcs: smallest mbc size */\
10, /* (amount) mbcgs: mbc growth stages */\
0, /* (%) acul: abandon carrier utilization limit */\
+ 0, /* (%) acful: carrier free utilization limit */\
1000, /* (amount) acnl: abandoned carriers number limit */\
0, /* (bytes) acfml: abandoned carrier fblk min limit */\
/* --- Data not options -------------------------------------------- */\
@@ -476,6 +479,7 @@ typedef struct {
ErtsThrPrgrVal thr_prgr;
erts_atomic_t max_size;
UWord abandon_limit;
+ UWord discard_limit;
UWord blocks[ERTS_ALC_A_COUNT];
UWord blocks_size[ERTS_ALC_A_COUNT];
UWord total_blocks_size;
@@ -697,6 +701,7 @@ struct Allctr_t_ {
int disable_abandon;
int check_limit_count;
UWord util_limit; /* acul */
+ UWord free_util_limit; /* acful */
UWord in_pool_limit; /* acnl */
UWord fblk_min_limit; /* acmfl */
int carrier_pool; /* cp */
diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.c b/erts/emulator/beam/erl_ao_firstfit_alloc.c
index 46aacf7642..7970ed914b 100644
--- a/erts/emulator/beam/erl_ao_firstfit_alloc.c
+++ b/erts/emulator/beam/erl_ao_firstfit_alloc.c
@@ -1279,10 +1279,10 @@ static void print_tree(AOFF_RBTree_t*);
/*
* Checks that the order between parent and children are correct,
- * and that the Red-Black Tree properies are satisfied. if size > 0,
+ * and that the Red-Black Tree properties are satisfied. if size > 0,
* check_tree() returns the node that satisfies "address order first fit"
*
- * The Red-Black Tree properies are:
+ * The Red-Black Tree properties are:
* 1. Every node is either red or black.
* 2. Every leaf (NIL) is black.
* 3. If a node is red, then both its children are black.
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index 5d475ed061..813f79edaa 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -710,7 +710,7 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2)
return res;
} else {
/*
- * The result is a a big number.
+ * The result is a big number.
* Allocate a heap fragment and copy the result.
* Be careful to allocate exactly what we need
* to not leave any holes.
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index 51591557c1..3e3dc3a29d 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -115,17 +115,6 @@ typedef struct {
ErtsAlgndAsyncReadyQ *ready_queue;
} ErtsAsyncData;
-#if defined(USE_VM_PROBES)
-
-/*
- * 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;
-#endif
-
int erts_async_max_threads; /* Initialized by erl_init.c */
int erts_async_thread_suggested_stack_size; /* Initialized by erl_init.c */
@@ -238,10 +227,6 @@ erts_get_async_ready_queue(Uint sched_id)
static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q)
{
-#ifdef USE_VM_PROBES
- int len;
-#endif
-
if (is_internal_port(a->port)) {
ErtsAsyncReadyQ *arq = async_ready_q(a->sched_id);
a->q.prep_enq = erts_thr_q_prepare_enqueue(&arq->thr_q);
@@ -263,9 +248,6 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q,
{
int saved_fin_deq = 0;
ErtsThrQFinDeQ_t fin_deq;
-#ifdef USE_VM_PROBES
- int len;
-#endif
while (1) {
ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(q);
@@ -386,7 +368,12 @@ static ERTS_INLINE void async_reply(ErtsAsync *a, ErtsThrQPrepEnQ_t *prep_enq)
static void
async_wakeup(void *vtse)
{
- erts_tse_set((erts_tse_t *) vtse);
+ /*
+ * 'vtse' might be NULL if we are called after an async thread
+ * has unregistered from thread progress prior to termination.
+ */
+ if (vtse)
+ erts_tse_set((erts_tse_t *) vtse);
}
static erts_tse_t *async_thread_init(ErtsAsyncQ *aq)
@@ -448,6 +435,7 @@ static void *async_main(void* arg)
async_reply(a, prep_enq);
}
+ erts_thr_progress_unregister_unmanaged_thread();
return NULL;
}
@@ -546,7 +534,7 @@ unsigned int driver_async_port_key(ErlDrvPort port)
** key pointer to secedule queue (NULL means round robin)
** async_invoke function to run in thread
** async_data data to pass to invoke function
-** async_free function for relase async_data in case of failure
+** async_free function for release async_data in case of failure
*/
long driver_async(ErlDrvPort ix, unsigned int* key,
void (*async_invoke)(void*), void* async_data,
diff --git a/erts/emulator/beam/erl_bestfit_alloc.c b/erts/emulator/beam/erl_bestfit_alloc.c
index b3b3baf9a3..d171c5c3a2 100644
--- a/erts/emulator/beam/erl_bestfit_alloc.c
+++ b/erts/emulator/beam/erl_bestfit_alloc.c
@@ -735,7 +735,7 @@ bf_link_free_block(Allctr_t *allctr, Block_t *block)
BF_LIST_PREV(BF_LIST_NEXT(x)) = blk;
BF_LIST_NEXT(x) = blk;
- return; /* Finnished */
+ return; /* Finished */
}
else if (blk_sz < size) {
if (!x->left) {
@@ -1009,11 +1009,11 @@ static void print_tree(RBTree_t *, int);
/*
* Checks that the order between parent and children are correct,
- * and that the Red-Black Tree properies are satisfied. if size > 0,
+ * and that the Red-Black Tree properties are satisfied. if size > 0,
* check_tree() returns a node that satisfies "best fit" resp.
* "address order best fit".
*
- * The Red-Black Tree properies are:
+ * The Red-Black Tree properties are:
* 1. Every node is either red or black.
* 2. Every leaf (NIL) is black.
* 3. If a node is red, then both its children are black.
diff --git a/erts/emulator/beam/erl_bif_atomics.c b/erts/emulator/beam/erl_bif_atomics.c
index 3fd0fc8dcd..13b6b2aea9 100644
--- a/erts/emulator/beam/erl_bif_atomics.c
+++ b/erts/emulator/beam/erl_bif_atomics.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -227,16 +227,19 @@ BIF_RETTYPE atomics_compare_exchange_4(BIF_ALIST_4)
BIF_RETTYPE atomics_info_1(BIF_ALIST_1)
{
AtomicsRef* p;
- Uint hsz = MAP4_SZ;
+ Uint hsz = 0;
Eterm *hp;
Uint64 max;
Sint64 min;
UWord memory;
- Eterm max_val, min_val, sz_val, mem_val;
+ Eterm keys[4], values[4], res;
+ ErtsHeapFactory factory;
if (!get_ref(BIF_ARG_1, &p))
BIF_ERROR(BIF_P, BADARG);
+ erts_factory_proc_init(&factory, BIF_P);
+
max = p->is_signed ? ERTS_SINT64_MAX : ERTS_UINT64_MAX;
min = p->is_signed ? ERTS_SINT64_MIN : 0;
memory = erts_magic_ref2bin(BIF_ARG_1)->orig_size;
@@ -246,14 +249,17 @@ BIF_RETTYPE atomics_info_1(BIF_ALIST_1)
erts_bld_uword(NULL, &hsz, p->vlen);
erts_bld_uword(NULL, &hsz, memory);
- hp = HAlloc(BIF_P, hsz);
- max_val = erts_bld_uint64(&hp, NULL, max);
- min_val = erts_bld_sint64(&hp, NULL, min);
- sz_val = erts_bld_uword(&hp, NULL, p->vlen);
- mem_val = erts_bld_uword(&hp, NULL, memory);
-
- return MAP4(hp, am_max, max_val,
- am_memory, mem_val,
- am_min, min_val,
- am_size, sz_val);
+ hp = erts_produce_heap(&factory, hsz, MAP4_SZ);
+ keys[0] = am_max;
+ values[0] = erts_bld_uint64(&hp, NULL, max);
+ keys[1] = am_min;
+ values[1] = erts_bld_sint64(&hp, NULL, min);
+ keys[2] = am_size;
+ values[2] = erts_bld_uword(&hp, NULL, p->vlen);
+ keys[3] = am_memory;
+ values[3] = erts_bld_uword(&hp, NULL, memory);
+
+ res = erts_map_from_ks_and_vs(&factory, keys, values, 4);
+ erts_factory_close(&factory);
+ return res;
}
diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 13fac27ce8..884cf792db 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -1322,7 +1322,7 @@ static int parse_match_opts_list(Eterm l, Eterm bin, Uint *posp, Uint *endp)
return 0;
} else {
badarg:
- /* Ensure intialization. */
+ /* Ensure initialization. */
*posp = 0;
*endp = 0;
return 1;
diff --git a/erts/emulator/beam/erl_bif_chksum.c b/erts/emulator/beam/erl_bif_chksum.c
index 8671d36acb..0827321099 100644
--- a/erts/emulator/beam/erl_bif_chksum.c
+++ b/erts/emulator/beam/erl_bif_chksum.c
@@ -230,7 +230,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
if (!left) {
#ifdef ALLOW_BYTE_TAIL
if (is_byte(ioterm)) {
- /* inproper list with byte tail*/
+ /* improper list with byte tail*/
Eterm *hp;
hp = HAlloc(p, 2);
ioterm = CONS(hp, ioterm, NIL);
@@ -239,7 +239,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
;
#endif
} else if (!is_list(ioterm) && !is_nil(ioterm)) {
- /* inproper list end */
+ /* improper list end */
#ifdef ALLOW_BYTE_TAIL
if (is_byte(ioterm)) {
unsigned char b[1];
diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c
index 927211e736..2242570cad 100644
--- a/erts/emulator/beam/erl_bif_guard.c
+++ b/erts/emulator/beam/erl_bif_guard.c
@@ -289,7 +289,7 @@ Eterm erts_trapping_length_1(Process* p, Eterm* args)
if (is_list(list)) {
/*
- * We have exceeded the alloted number of iterations.
+ * We have exceeded the allotted number of iterations.
* Save the result so far and signal a trap.
*/
args[0] = list;
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index d5e598515c..f340015661 100644
--- 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,6 @@
#include "erl_message.h"
#include "erl_binary.h"
#include "erl_db.h"
-#include "erl_mtrace.h"
#include "dist.h"
#include "erl_gc.h"
#include "erl_cpu_topology.h"
@@ -93,8 +92,12 @@ static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
" [source]"
#endif
#endif
-#ifdef ARCH_64
+#if defined(ARCH_64)
" [64-bit]"
+#elif defined(ARCH_32)
+ " [32-bit]"
+#else
+# error "Unknown ARCH_?"
#endif
" [smp:%beu:%beu]"
" [ds:%beu:%beu:%beu]"
@@ -104,9 +107,9 @@ static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
" [async-threads:%d]"
#ifdef BEAMASM
#ifdef NATIVE_ERLANG_STACK
- " [jit]"
+ " [jit:ns%s]"
#else
- " [jit:no-native-stack]"
+ " [jit%s]"
#endif
#endif
#ifdef ET_DEBUG
@@ -291,6 +294,11 @@ static int do_make_one_mon_element(ErtsMonitor *mon, void * vpmlc, Sint reds)
t = AM_dist_process;
break;
}
+ case ERTS_MON_TYPE_DIST_PORT: {
+ ERTS_DECL_AM(dist_port);
+ t = AM_dist_port;
+ break;
+ }
case ERTS_MON_TYPE_RESOURCE: {
ERTS_DECL_AM(resource);
t = AM_resource;
@@ -428,7 +436,7 @@ static int make_one_lnk_element(ErtsLink *lnk, void * vpllc, Sint reds)
break;
}
default:
- ERTS_INTERNAL_ERROR("Unkown link type");
+ ERTS_INTERNAL_ERROR("Unknown link type");
t = am_undefined;
break;
}
@@ -494,6 +502,7 @@ erts_print_system_version(fmtfn_t to, void *arg, Process *c_p)
, total, online
, dirty_cpu, dirty_cpu_onln, dirty_io
, erts_async_max_threads
+ , (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA ? ":fp" : "")
);
}
@@ -578,6 +587,7 @@ static int collect_one_origin_monitor(ErtsMonitor *mon, void *vmicp, Sint reds)
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_TIME_OFFSET:
if (mon->flags & ERTS_ML_FLG_SPAWN_PENDING)
break; /* Not an active monitor... */
@@ -630,6 +640,7 @@ static int collect_one_target_monitor(ErtsMonitor *mon, void *vmicp, Sint reds)
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
micp->mi[micp->mi_i].entity.term = mon->other.item;
micp->mi[micp->mi_i].node = NIL;
@@ -765,6 +776,8 @@ collect_one_suspend_monitor(ErtsMonitor *mon, void *vsmicp, Sint reds)
#define ERTS_PI_IX_GARBAGE_COLLECTION_INFO 33
#define ERTS_PI_IX_MAGIC_REF 34
#define ERTS_PI_IX_FULLSWEEP_AFTER 35
+#define ERTS_PI_IX_PARENT 36
+#define ERTS_PI_IX_ASYNC_DIST 37
#define ERTS_PI_FLAG_SINGELTON (1 << 0)
#define ERTS_PI_FLAG_ALWAYS_WRAP (1 << 1)
@@ -820,7 +833,9 @@ static ErtsProcessInfoArgs pi_args[] = {
{am_message_queue_data, 0, 0, ERTS_PROC_LOCK_MAIN},
{am_garbage_collection_info, ERTS_PROCESS_GC_INFO_MAX_SIZE, 0, ERTS_PROC_LOCK_MAIN},
{am_magic_ref, 0, ERTS_PI_FLAG_FORCE_SIG_SEND, ERTS_PROC_LOCK_MAIN},
- {am_fullsweep_after, 0, 0, ERTS_PROC_LOCK_MAIN}
+ {am_fullsweep_after, 0, 0, ERTS_PROC_LOCK_MAIN},
+ {am_parent, 0, 0, ERTS_PROC_LOCK_MAIN},
+ {am_async_dist, 0, 0, ERTS_PROC_LOCK_MAIN}
};
#define ERTS_PI_ARGS ((int) (sizeof(pi_args)/sizeof(pi_args[0])))
@@ -939,6 +954,10 @@ pi_arg2ix(Eterm arg)
return ERTS_PI_IX_MAGIC_REF;
case am_fullsweep_after:
return ERTS_PI_IX_FULLSWEEP_AFTER;
+ case am_parent:
+ return ERTS_PI_IX_PARENT;
+ case am_async_dist:
+ return ERTS_PI_IX_ASYNC_DIST;
default:
return -1;
}
@@ -999,6 +1018,7 @@ process_info_aux(Process *c_p,
Process *rp,
ErtsProcLocks rp_locks,
int item_ix,
+ Sint *msgq_len_p,
int flags,
Uint *reserve_sizep,
Uint *reds);
@@ -1017,11 +1037,12 @@ erts_process_info(Process *c_p,
Eterm res;
Eterm part_res[ERTS_PI_ARGS];
int item_ix_ix, ix;
+ Sint msgq_len = -1;
if (ERTS_PI_FLAG_SINGELTON & flags) {
ASSERT(item_ix_len == 1);
res = process_info_aux(c_p, hfact, rp, rp_locks, item_ix[0],
- flags, &reserve_size, reds);
+ &msgq_len, flags, &reserve_size, reds);
return res;
}
@@ -1039,7 +1060,7 @@ erts_process_info(Process *c_p,
ix = pi_arg2ix(am_messages);
ASSERT(part_res[ix] == THE_NON_VALUE);
res = process_info_aux(c_p, hfact, rp, rp_locks, ix,
- flags, &reserve_size, reds);
+ &msgq_len, flags, &reserve_size, reds);
ASSERT(res != am_undefined);
ASSERT(res != THE_NON_VALUE);
part_res[ix] = res;
@@ -1049,7 +1070,7 @@ erts_process_info(Process *c_p,
ix = item_ix[item_ix_ix];
if (part_res[ix] == THE_NON_VALUE) {
res = process_info_aux(c_p, hfact, rp, rp_locks, ix,
- flags, &reserve_size, reds);
+ &msgq_len, flags, &reserve_size, reds);
ASSERT(res != am_undefined);
ASSERT(res != THE_NON_VALUE);
part_res[ix] = res;
@@ -1084,6 +1105,92 @@ erts_process_info(Process *c_p,
static void
pi_setup_grow(int **arr, int *def_arr, Uint *sz, int ix);
+static ERTS_INLINE int
+pi_maybe_flush_signals(Process *c_p, int pi_flags)
+{
+ int reds_left;
+ erts_aint32_t state;
+
+ /*
+ * pi_maybe_flush_signals() flush signals in callers
+ * signal queue for two different reasons:
+ *
+ * 1. If we need 'message_queue_len', but not 'messages', we need
+ * to handle all signals in the middle queue in order for
+ * 'c_p->sig_qs.len' to reflect the amount of messages in the
+ * message queue. We could count traverse the queues, but it
+ * is better to handle all signals in the queue instead since
+ * this is work we anyway need to do at some point.
+ *
+ * 2. Ensures that all signals that the caller might have sent to
+ * itself are handled before we gather information.
+ *
+ * This is, however, not strictly necessary. process_info() is
+ * not documented to send itself a signal when gathering
+ * information about itself. That is, the operation is not
+ * bound by the signal order guarantee when gathering
+ * information about itself. If we do not handle outstanding
+ * signals before gathering the information, outstanding signals
+ * from the caller to itself will not be part of the result.
+ * This would not be wrong, but perhaps surprising for the user.
+ * We continue doing it this way for now, since this is how it
+ * has been done for a very long time. We should, however,
+ * consider changing this in a future release, since this signal
+ * handling is not for free, although quite cheap since these
+ * signals anyway must be handled at some point.
+ */
+
+ if (c_p->sig_qs.flags & FS_FLUSHED_SIGS) {
+ flushed:
+
+ ASSERT(((pi_flags & (ERTS_PI_FLAG_WANT_MSGS
+ | ERTS_PI_FLAG_NEED_MSGQ_LEN))
+ != ERTS_PI_FLAG_NEED_MSGQ_LEN)
+ || !c_p->sig_qs.cont);
+ ASSERT(c_p->sig_qs.flags & FS_FLUSHING_SIGS);
+
+ c_p->sig_qs.flags &= ~(FS_FLUSHED_SIGS|FS_FLUSHING_SIGS);
+ erts_set_gc_state(c_p, !0); /* Allow GC again... */
+ return 0; /* done, all signals handled... */
+ }
+
+ state = erts_atomic32_read_nob(&c_p->state);
+
+ if (!(c_p->sig_qs.flags & FS_FLUSHING_SIGS)) {
+ int flush_flags = 0;
+ if (((pi_flags & (ERTS_PI_FLAG_WANT_MSGS
+ | ERTS_PI_FLAG_NEED_MSGQ_LEN))
+ == ERTS_PI_FLAG_NEED_MSGQ_LEN)
+ && c_p->sig_qs.cont) {
+ flush_flags |= ERTS_PROC_SIG_FLUSH_FLG_CLEAN_SIGQ;
+ }
+ if (state & ERTS_PSFLG_MAYBE_SELF_SIGS)
+ flush_flags |= ERTS_PROC_SIG_FLUSH_FLG_FROM_ID;
+ if (!flush_flags)
+ return 0; /* done; no need to flush... */
+ erts_proc_sig_init_flush_signals(c_p, flush_flags, c_p->common.id);
+ if (c_p->sig_qs.flags & FS_FLUSHED_SIGS)
+ goto flushed;
+ }
+
+ ASSERT(c_p->sig_qs.flags & FS_FLUSHING_SIGS);
+ reds_left = ERTS_BIF_REDS_LEFT(c_p);
+
+ do {
+ int sreds = reds_left;
+ (void) erts_proc_sig_handle_incoming(c_p, &state, &sreds,
+ sreds, !0);
+ BUMP_REDS(c_p, (int) sreds);
+ if (state & ERTS_PSFLG_EXITING)
+ return -1; /* process exiting... */
+ if (c_p->sig_qs.flags & FS_FLUSHED_SIGS)
+ goto flushed;
+ reds_left -= sreds;
+ } while (reds_left > 0);
+
+ return 1; /* yield and continue here later... */
+}
+
static BIF_RETTYPE
process_info_bif(Process *c_p, Eterm pid, Eterm opt, int always_wrap, int pi2)
{
@@ -1102,41 +1209,6 @@ process_info_bif(Process *c_p, Eterm pid, Eterm opt, int always_wrap, int pi2)
ERTS_CT_ASSERT(ERTS_PI_DEF_ARR_SZ > 0);
- if (c_p->common.id == pid) {
- int local_only = c_p->sig_qs.flags & FS_LOCAL_SIGS_ONLY;
- int sres, sreds, reds_left;
-
- reds_left = ERTS_BIF_REDS_LEFT(c_p);
- sreds = reds_left;
-
- if (!local_only) {
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
- erts_proc_sig_fetch(c_p);
- erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
- }
-
- sres = erts_proc_sig_handle_incoming(c_p, &state, &sreds, sreds, !0);
-
- BUMP_REDS(c_p, (int) sreds);
- reds_left -= sreds;
-
- if (state & ERTS_PSFLG_EXITING) {
- c_p->sig_qs.flags &= ~FS_LOCAL_SIGS_ONLY;
- goto exited;
- }
- if (!sres | (reds_left <= 0)) {
- /*
- * More signals to handle or out of reds; need
- * to yield and continue. Prevent fetching of
- * more signals by setting local-sigs-only flag.
- */
- c_p->sig_qs.flags |= FS_LOCAL_SIGS_ONLY;
- goto yield;
- }
-
- c_p->sig_qs.flags &= ~FS_LOCAL_SIGS_ONLY;
- }
-
if (is_atom(opt)) {
int ix = pi_arg2ix(opt);
item_ix[0] = ix;
@@ -1182,7 +1254,16 @@ process_info_bif(Process *c_p, Eterm pid, Eterm opt, int always_wrap, int pi2)
goto badarg;
}
- if (is_not_internal_pid(pid)) {
+ if (c_p->common.id == pid) {
+ int res = pi_maybe_flush_signals(c_p, flags);
+ if (res != 0) {
+ if (res > 0)
+ goto yield;
+ else
+ goto exited;
+ }
+ }
+ else if (is_not_internal_pid(pid)) {
if (is_external_pid(pid)
&& external_pid_dist_entry(pid) == erts_this_dist_entry)
goto undefined;
@@ -1218,9 +1299,13 @@ process_info_bif(Process *c_p, Eterm pid, Eterm opt, int always_wrap, int pi2)
}
if (flags & ERTS_PI_FLAG_NEED_MSGQ_LEN) {
ASSERT(locks & ERTS_PROC_LOCK_MAIN);
- erts_proc_lock(rp, ERTS_PROC_LOCK_MSGQ);
+ if (rp->sig_qs.flags & FS_FLUSHING_SIGS) {
+ erts_proc_unlock(rp, locks);
+ goto send_signal;
+ }
+ erts_proc_sig_queue_lock(rp);
erts_proc_sig_fetch(rp);
- if (c_p->sig_qs.cont) {
+ if (rp->sig_qs.cont) {
erts_proc_unlock(rp, locks|ERTS_PROC_LOCK_MSGQ);
locks = 0;
goto send_signal;
@@ -1256,7 +1341,8 @@ process_info_bif(Process *c_p, Eterm pid, Eterm opt, int always_wrap, int pi2)
if (c_p == rp || !ERTS_PROC_HAS_INCOMING_SIGNALS(c_p))
ERTS_BIF_PREP_RET(ret, res);
else
- ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(ret, c_p, res);
+ ERTS_BIF_PREP_HANDLE_SIGNALS_FROM_RETURN(ret, c_p,
+ pid, res);
done:
@@ -1296,7 +1382,7 @@ send_signal: {
flags |= ERTS_PI_FLAG_REQUEST_FOR_OTHER;
need_msgq_len = (flags & ERTS_PI_FLAG_NEED_MSGQ_LEN);
/*
- * Set save pointer to the end of the message queue so we wont
+ * Set save pointer to the end of the message queue so we won't
* have to scan the whole* message queue for the result. Note
* that caller unconditionally has to enter a receive only
* matching messages containing 'ref', or restore save pointer.
@@ -1347,6 +1433,7 @@ process_info_aux(Process *c_p,
Process *rp,
ErtsProcLocks rp_locks,
int item_ix,
+ Sint *msgq_len_p,
int flags,
Uint *reserve_sizep,
Uint *reds)
@@ -1432,10 +1519,15 @@ process_info_aux(Process *c_p,
break;
case ERTS_PI_IX_STATUS: {
- erts_aint32_t state = erts_atomic32_read_nob(&rp->state);
+ erts_aint32_t state;
+ if (!rp_locks)
+ state = erts_atomic32_read_mb(&rp->state);
+ else
+ state = erts_atomic32_read_nob(&rp->state);
res = erts_process_state2status(state);
- if (res == am_running && (state & ERTS_PSFLG_RUNNING_SYS)) {
- ASSERT(c_p == rp);
+ if (res == am_running
+ && c_p == rp
+ && (state & ERTS_PSFLG_RUNNING_SYS)) {
ASSERT(flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER);
if (!(state & (ERTS_PSFLG_ACTIVE
| ERTS_PSFLG_SIG_Q
@@ -1460,8 +1552,10 @@ process_info_aux(Process *c_p,
case ERTS_PI_IX_MESSAGES: {
ASSERT(flags & ERTS_PI_FLAG_NEED_MSGQ_LEN);
- if (rp->sig_qs.len == 0 || (ERTS_TRACE_FLAGS(rp) & F_SENSITIVE))
+ if (rp->sig_qs.len == 0 || (ERTS_TRACE_FLAGS(rp) & F_SENSITIVE)) {
+ *msgq_len_p = 0;
res = NIL;
+ }
else {
int info_on_self = !(flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER);
ErtsMessageInfo *mip;
@@ -1479,8 +1573,8 @@ process_info_aux(Process *c_p,
heap_need = erts_proc_sig_prep_msgq_for_inspection(c_p, rp,
rp_locks,
info_on_self,
- mip);
- len = rp->sig_qs.len;
+ mip, msgq_len_p);
+ len = *msgq_len_p;
heap_need += len*2; /* Cons cells */
@@ -1509,7 +1603,12 @@ process_info_aux(Process *c_p,
}
case ERTS_PI_IX_MESSAGE_QUEUE_LEN: {
- Sint len = rp->sig_qs.len;
+ Sint len = *msgq_len_p;
+ if (len < 0) {
+ ASSERT((flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER)
+ || !rp->sig_qs.cont);
+ len = rp->sig_qs.len;
+ }
ASSERT(flags & ERTS_PI_FLAG_NEED_MSGQ_LEN);
ASSERT(len >= 0);
if (len <= MAX_SMALL)
@@ -1908,12 +2007,15 @@ process_info_aux(Process *c_p,
case ERTS_PI_IX_BINARY: {
ErlHeapFragment *hfrag;
+ ErlOffHeap wrt_bins;
Uint sz;
res = NIL;
sz = 0;
+ wrt_bins.first = rp->wrt_bins;
(void)erts_bld_bin_list(NULL, &sz, &MSO(rp), NIL);
+ (void)erts_bld_bin_list(NULL, &sz, &wrt_bins, NIL);
for (hfrag = rp->mbuf; hfrag != NULL; hfrag = hfrag->next) {
(void)erts_bld_bin_list(NULL, &sz, &hfrag->off_heap, NIL);
}
@@ -1921,6 +2023,7 @@ process_info_aux(Process *c_p,
hp = erts_produce_heap(hfact, sz, reserve_size);
res = erts_bld_bin_list(&hp, NULL, &MSO(rp), NIL);
+ res = erts_bld_bin_list(&hp, NULL, &wrt_bins, res);
for (hfrag = rp->mbuf; hfrag != NULL; hfrag = hfrag->next) {
res = erts_bld_bin_list(&hp, NULL, &hfrag->off_heap, res);
}
@@ -2021,6 +2124,24 @@ process_info_aux(Process *c_p,
}
break;
+ case ERTS_PI_IX_PARENT:
+ if (is_immed(rp->parent)) {
+ ASSERT(is_internal_pid(rp->parent) || rp->parent == am_undefined);
+ res = rp->parent;
+ }
+ else {
+ Uint sz;
+ ASSERT(is_external_pid(rp->parent));
+ sz = size_object(rp->parent);
+ hp = erts_produce_heap(hfact, sz, reserve_size);
+ res = copy_struct(rp->parent, sz, &hp, hfact->off_heap);
+ }
+ break;
+
+ case ERTS_PI_IX_ASYNC_DIST:
+ res = (rp->flags & F_ASYNC_DIST) ? am_true : am_false;
+ break;
+
case ERTS_PI_IX_MAGIC_REF: {
Uint sz = 0;
(void) bld_magic_ref_bin_list(NULL, &sz, &MSO(rp));
@@ -2677,6 +2798,10 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
res = new_binary(BIF_P, (byte *) dsbufp->str, dsbufp->str_len);
erts_destroy_info_dsbuf(dsbufp);
BIF_RET(res);
+ } else if (am_async_dist == BIF_ARG_1) {
+ BIF_RET((erts_default_spo_flags & SPO_ASYNC_DIST)
+ ? am_true
+ : am_false);
} else if (ERTS_IS_ATOM_STR("dist_ctrl", BIF_ARG_1)) {
DistEntry *dep;
i = 0;
@@ -3055,9 +3180,6 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
if (sz)
hp = HAlloc(BIF_P, sz);
BIF_RET(c_compiler_used(&hp, NULL));
- } else if (ERTS_IS_ATOM_STR("stop_memory_trace", BIF_ARG_1)) {
- erts_mtrace_stop();
- BIF_RET(am_true);
} else if (ERTS_IS_ATOM_STR("context_reductions", BIF_ARG_1)) {
BIF_RET(make_small(CONTEXT_REDS));
} else if (ERTS_IS_ATOM_STR("kernel_poll", BIF_ARG_1)) {
@@ -3531,126 +3653,96 @@ fun_info_2(BIF_ALIST_2)
Process* p = BIF_P;
Eterm fun = BIF_ARG_1;
Eterm what = BIF_ARG_2;
+
+ const ErtsCodeMFA *mfa;
+ ErlFunThing *funp;
+ ErlFunEntry *fe;
Eterm* hp;
Eterm val;
- if (is_fun(fun)) {
- ErlFunThing* funp = (ErlFunThing *) fun_val(fun);
+ if (is_not_any_fun(fun)) {
+ BIF_ERROR(p, BADARG);
+ }
- switch (what) {
- case am_type:
- hp = HAlloc(p, 3);
- val = am_local;
- break;
- case am_pid:
- hp = HAlloc(p, 3);
- val = funp->creator;
- break;
- case am_module:
- hp = HAlloc(p, 3);
- val = funp->fe->module;
- break;
- case am_new_index:
- hp = HAlloc(p, 3);
- val = make_small(funp->fe->index);
- break;
- case am_new_uniq:
- val = new_binary(p, funp->fe->uniq, 16);
- hp = HAlloc(p, 3);
- break;
- case am_index:
- hp = HAlloc(p, 3);
- val = make_small(funp->fe->old_index);
- break;
- case am_uniq:
- hp = HAlloc(p, 3);
- val = make_small(funp->fe->old_uniq);
- break;
- case am_env:
- {
- Uint num_free = funp->num_free;
- int i;
-
- hp = HAlloc(p, 3 + 2*num_free);
- val = NIL;
- for (i = num_free-1; i >= 0; i--) {
- val = CONS(hp, funp->env[i], val);
- hp += 2;
- }
- }
- break;
- case am_refc:
- val = erts_make_integer(erts_atomic_read_nob(&funp->fe->refc), p);
- hp = HAlloc(p, 3);
- break;
- case am_arity:
- hp = HAlloc(p, 3);
- val = make_small(funp->arity);
- break;
- case am_name:
- {
- const ErtsCodeMFA *mfa = erts_code_to_codemfa((funp->fe)->address);
- hp = HAlloc(p, 3);
- val = mfa->function;
- }
- break;
- default:
- goto error;
- }
- } else if (is_export(fun)) {
- Export* exp = (Export *) ((UWord) (export_val(fun))[1]);
- switch (what) {
- case am_type:
- hp = HAlloc(p, 3);
- val = am_external;
- break;
- case am_pid:
- hp = HAlloc(p, 3);
- val = am_undefined;
- break;
- case am_module:
- hp = HAlloc(p, 3);
- val = exp->info.mfa.module;
- break;
- case am_new_index:
- hp = HAlloc(p, 3);
- val = am_undefined;
- break;
- case am_new_uniq:
- hp = HAlloc(p, 3);
- val = am_undefined;
- break;
- case am_index:
- hp = HAlloc(p, 3);
- val = am_undefined;
- break;
- case am_uniq:
- hp = HAlloc(p, 3);
- val = am_undefined;
- break;
- case am_env:
- hp = HAlloc(p, 3);
- val = NIL;
- break;
- case am_refc:
- hp = HAlloc(p, 3);
- val = am_undefined;
- break;
- case am_arity:
- hp = HAlloc(p, 3);
- val = make_small(exp->info.mfa.arity);
- break;
- case am_name:
- hp = HAlloc(p, 3);
- val = exp->info.mfa.function;
- break;
- default:
- goto error;
- }
+ funp = (ErlFunThing *) fun_val(fun);
+
+ if (is_local_fun(funp)) {
+ fe = funp->entry.fun;
+ mfa = erts_get_fun_mfa(fe);
} else {
- error:
- BIF_ERROR(p, BADARG);
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ mfa = &(funp->entry.exp)->info.mfa;
+ fe = NULL;
}
+
+ switch (what) {
+ case am_type:
+ val = is_local_fun(funp) ? am_local : am_external;
+ hp = HAlloc(p, 3);
+ break;
+ case am_pid:
+ val = is_local_fun(funp) ? funp->creator : am_undefined;
+ hp = HAlloc(p, 3);
+ break;
+ case am_module:
+ /* Unloaded funs must report their module even though we can't find
+ * their full MFA. */
+ val = (mfa != NULL) ? mfa->module : fe->module;
+ hp = HAlloc(p, 3);
+ break;
+ case am_new_index:
+ val = is_local_fun(funp) ? make_small(fe->index) : am_undefined;
+ hp = HAlloc(p, 3);
+ break;
+ case am_new_uniq:
+ val = is_local_fun(funp) ? new_binary(p, fe->uniq, 16) :
+ am_undefined;
+ hp = HAlloc(p, 3);
+ break;
+ case am_index:
+ val = is_local_fun(funp) ? make_small(fe->old_index) : am_undefined;
+ hp = HAlloc(p, 3);
+ break;
+ case am_uniq:
+ val = is_local_fun(funp) ? make_small(fe->old_uniq) : am_undefined;
+ hp = HAlloc(p, 3);
+ break;
+ case am_env:
+ {
+ Uint num_free = funp->num_free;
+ int i;
+
+ hp = HAlloc(p, 3 + 2 * num_free);
+ val = NIL;
+
+ for (i = num_free - 1; i >= 0; i--) {
+ val = CONS(hp, funp->env[i], val);
+ hp += 2;
+ }
+ }
+ break;
+ case am_refc:
+ if (is_local_fun(funp)) {
+ val = erts_make_integer(erts_atomic_read_nob(&fe->refc), p);
+ } else {
+ val = am_undefined;
+ }
+
+ hp = HAlloc(p, 3);
+ break;
+ case am_arity:
+ val = make_small(funp->arity);
+ hp = HAlloc(p, 3);
+ break;
+ case am_name:
+ /* Name must be `[]` for unloaded funs. */
+ val = (mfa != NULL) ? mfa->function : NIL;
+ hp = HAlloc(p, 3);
+ break;
+ default:
+ BIF_ERROR(p, BADARG);
+ }
+
return TUPLE2(hp, what, val);
}
@@ -3659,26 +3751,38 @@ fun_info_mfa_1(BIF_ALIST_1)
{
Process* p = BIF_P;
Eterm fun = BIF_ARG_1;
- Eterm* hp;
- if (is_fun(fun)) {
+ if (is_any_fun(fun)) {
const ErtsCodeMFA *mfa;
ErlFunThing* funp;
- funp = (ErlFunThing *) fun_val(fun);
- mfa = erts_code_to_codemfa((funp->fe)->address);
+ Eterm* hp;
+ funp = (ErlFunThing *) fun_val(fun);
hp = HAlloc(p, 4);
+
+ if (is_local_fun(funp)) {
+ mfa = erts_get_fun_mfa(funp->entry.fun);
+
+ if (mfa == NULL) {
+ /* Unloaded funs must report their module even though we can't
+ * find their full MFA, and their function name must be
+ * `[]`. */
+ BIF_RET(TUPLE3(hp,
+ funp->entry.fun->module,
+ NIL,
+ make_small(funp->arity)));
+ }
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ mfa = &(funp->entry.exp)->info.mfa;
+ }
+
BIF_RET(TUPLE3(hp,
- (funp->fe)->module,
+ mfa->module,
mfa->function,
make_small(funp->arity)));
- } else if (is_export(fun)) {
- Export* exp = (Export *) ((UWord) (export_val(fun))[1]);
- hp = HAlloc(p, 4);
- BIF_RET(TUPLE3(hp,exp->info.mfa.module,
- exp->info.mfa.function,
- make_small(exp->info.mfa.arity)));
}
+
BIF_ERROR(p, BADARG);
}
@@ -3688,42 +3792,54 @@ BIF_RETTYPE erts_internal_is_process_alive_2(BIF_ALIST_2)
BIF_ERROR(BIF_P, BADARG);
if (!erts_proc_sig_send_is_alive_request(BIF_P, BIF_ARG_1, BIF_ARG_2)) {
if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, am_ok);
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, BIF_ARG_1, am_ok);
}
BIF_RET(am_ok);
}
BIF_RETTYPE is_process_alive_1(BIF_ALIST_1)
{
+
if (is_internal_pid(BIF_ARG_1)) {
- erts_aint32_t state;
+ BIF_RETTYPE result;
Process *rp;
if (BIF_ARG_1 == BIF_P->common.id)
BIF_RET(am_true);
rp = erts_proc_lookup_raw(BIF_ARG_1);
- if (!rp)
- BIF_RET(am_false);
+ if (!rp) {
+ result = am_false;
+ }
+ else {
+ erts_aint32_t state = erts_atomic32_read_acqb(&rp->state);
+ if (state & (ERTS_PSFLG_EXITING
+ | ERTS_PSFLG_SIG_Q
+ | ERTS_PSFLG_SIG_IN_Q)) {
+ /*
+ * If in exiting state, trap out and send 'is alive'
+ * request and wait for it to complete termination.
+ *
+ * If process has signals enqueued, we need to
+ * send it an 'is alive' request via its signal
+ * queue in order to ensure that signal order is
+ * preserved (we may earlier have sent it an
+ * exit signal that has not been processed yet).
+ */
+ BIF_TRAP1(is_process_alive_trap, BIF_P, BIF_ARG_1);
+ }
+
+ result = am_true;
+ }
- state = erts_atomic32_read_acqb(&rp->state);
- if (state & (ERTS_PSFLG_EXITING
- | ERTS_PSFLG_SIG_Q
- | ERTS_PSFLG_SIG_IN_Q)) {
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P)) {
/*
- * If in exiting state, trap out and send 'is alive'
- * request and wait for it to complete termination.
- *
- * If process has signals enqueued, we need to
- * send it an 'is alive' request via its signal
- * queue in order to ensure that signal order is
- * preserved (we may earlier have sent it an
- * exit signal that has not been processed yet).
+ * Ensure that signal order of signals from inspected
+ * process to us is preserved...
*/
- BIF_TRAP1(is_process_alive_trap, BIF_P, BIF_ARG_1);
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, BIF_ARG_1, result);
}
-
- BIF_RET(am_true);
+ BIF_RET(result);
}
if (is_external_pid(BIF_ARG_1)) {
@@ -3732,6 +3848,8 @@ BIF_RETTYPE is_process_alive_1(BIF_ALIST_1)
}
BIF_ERROR(BIF_P, BADARG);
+
+
}
static Eterm
@@ -4149,6 +4267,31 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
else if (ERTS_IS_ATOM_STR("persistent_term", BIF_ARG_1)) {
BIF_RET(erts_debug_persistent_term_xtra_info(BIF_P));
}
+#ifdef DEBUG
+ else if (ERTS_IS_ATOM_STR("check_no_empty_boxed_non_literal_on_heap", BIF_ARG_1)) {
+ /*
+ There is an optimization that assumes that it is always
+ safe to read the word after the arity word of boxed
+ terms. This checks if there is a boxed term with nothing
+ after the arity word that is not a literal. Such
+ literals needs to be padded to make the above mentioned
+ optimization safe. Debug builds also do this check every
+ time the GC is run.
+ */
+ erts_dbg_check_no_empty_boxed_non_literal_on_heap(BIF_P, NULL);
+ BIF_RET(am_ok);
+ }
+#endif
+ else if (ERTS_IS_ATOM_STR("pid_ref_table_size", BIF_ARG_1)) {
+ Uint size = erts_pid_ref_table_size();
+ if (IS_SSMALL(size))
+ BIF_RET(make_small(size));
+ else {
+ Uint hsz = BIG_UWORD_HEAP_SIZE(size);
+ Eterm *hp = HAlloc(BIF_P, hsz);
+ BIF_RET(uword_to_big(size, hp));
+ }
+ }
}
else if (is_tuple(BIF_ARG_1)) {
Eterm* tp = tuple_val(BIF_ARG_1);
@@ -4201,10 +4344,10 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
ERTS_ASSERT_IS_NOT_EXITING(BIF_P);
BIF_RET(am_undefined);
}
-
erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
erts_proc_sig_fetch(p);
erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ state = erts_atomic32_read_nob(&BIF_P->state);
do {
int reds = CONTEXT_REDS;
sigs_done = erts_proc_sig_handle_incoming(p,
@@ -4267,10 +4410,11 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
ERTS_ASSERT_IS_NOT_EXITING(BIF_P);
BIF_RET(am_undefined);
}
-
+
erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
erts_proc_sig_fetch(p);
erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ state = erts_atomic32_read_nob(&BIF_P->state);
do {
int reds = CONTEXT_REDS;
sigs_done = erts_proc_sig_handle_incoming(p,
@@ -4360,15 +4504,6 @@ BIF_RETTYPE erts_debug_get_internal_state_1(BIF_ALIST_1)
BIF_RET(res);
}
}
- else if (ERTS_IS_ATOM_STR("term_to_binary_tuple_fallbacks", tp[1])) {
- Uint64 dflags = (TERM_TO_BINARY_DFLAGS
- & ~DFLAG_EXPORT_PTR_TAG
- & ~DFLAG_BIT_BINARIES);
- Eterm res = erts_term_to_binary(BIF_P, tp[2], 0, dflags);
- if (is_value(res))
- BIF_RET(res);
- BIF_ERROR(BIF_P, SYSTEM_LIMIT);
- }
else if (ERTS_IS_ATOM_STR("dist_ctrl", tp[1])) {
Eterm res = am_undefined;
DistEntry *dep = erts_sysname_to_connected_dist_entry(tp[2]);
@@ -4559,6 +4694,44 @@ test_multizero_timeout_in_timeout(void *vproc)
erts_start_timer_callback(0, test_multizero_timeout_in_timeout2, vproc);
}
+static Eterm
+proc_sig_block(Process *c_p, void *arg, int *redsp, ErlHeapFragment **bpp)
+{
+ ErtsMonotonicTime time, timeout_time, ms = (ErtsMonotonicTime) (Sint) arg;
+
+ if (redsp)
+ *redsp = 1;
+
+ time = erts_get_monotonic_time(NULL);
+
+ if (ms < 0)
+ timeout_time = time;
+ else
+ timeout_time = time + ERTS_MSEC_TO_MONOTONIC(ms);
+
+ while (time < timeout_time) {
+ ErtsMonotonicTime timeout = timeout_time - time;
+
+#ifdef __WIN32__
+ Sleep((DWORD) ERTS_MONOTONIC_TO_MSEC(timeout));
+#else
+ {
+ ErtsMonotonicTime to = ERTS_MONOTONIC_TO_USEC(timeout);
+ struct timeval tv;
+
+ tv.tv_sec = (long) to / (1000*1000);
+ tv.tv_usec = (long) to % (1000*1000);
+
+ select(0, NULL, NULL, NULL, &tv);
+ }
+#endif
+
+ time = erts_get_monotonic_time(NULL);
+ }
+
+ return am_ok;
+}
+
BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
{
/*
@@ -4880,24 +5053,21 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
BIF_RET(copy);
}
else if (ERTS_IS_ATOM_STR("remove_hopefull_dflags", BIF_ARG_1)) {
- int old_val, new_val;
+ Uint64 new_val;
- switch (BIF_ARG_2) {
- case am_true: new_val = !0; break;
- case am_false: new_val = 0; break;
- default: BIF_ERROR(BIF_P, BADARG); break;
- }
+ if (!term_to_Uint64(BIF_ARG_2, &new_val)
+ || (new_val & ~DFLAG_DIST_HOPEFULLY))
+ BIF_ERROR(BIF_P, BADARG);
erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
- old_val = erts_dflags_test_remove_hopefull_flags;
erts_dflags_test_remove_hopefull_flags = new_val;
erts_thr_progress_unblock();
erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
- BIF_RET(old_val ? am_true : am_false);
+ BIF_RET(am_ok);
}
else if (ERTS_IS_ATOM_STR("code_write_permission", BIF_ARG_1)) {
/*
@@ -4927,6 +5097,63 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
(void *) BIF_P);
BIF_RET(am_ok);
}
+ } else if (ERTS_IS_ATOM_STR("jit_asm_dump", BIF_ARG_1)) {
+#ifdef BEAMASM
+ /* Undocumented debug option for the JIT, changing the +JDdump
+ * setting at runtime. This saves us from dumping half of OTP every
+ * time we want to debug the loading of a single module. */
+ Eterm res = erts_jit_asm_dump ? am_true : am_false;
+ switch (BIF_ARG_2)
+ {
+ case am_false:
+ erts_jit_asm_dump = 0;
+ BIF_RET(res);
+ case am_true:
+ erts_jit_asm_dump = 1;
+ BIF_RET(res);
+ default:
+ break;
+ }
+#else
+ BIF_RET(am_notsup);
+#endif
+ } else if (ERTS_IS_ATOM_STR("proc_sig_buffers", BIF_ARG_1)) {
+ switch (BIF_ARG_2)
+ {
+ case am_true: {
+ int has_buffers = erts_proc_sig_queue_force_buffers(BIF_P);
+ BIF_RET(has_buffers ? am_true : am_false);
+ }
+ default:
+ break;
+ }
+ BIF_RET(am_notsup);
+ }
+ else if (ERTS_IS_ATOM_STR("process_uniq_counter", BIF_ARG_1)) {
+ Sint64 counter;
+ if (term_to_Sint64(BIF_ARG_2, &counter)) {
+ BIF_P->uniq = counter;
+ BIF_RET(am_ok);
+ }
+ }
+ else if (ERTS_IS_ATOM_STR("proc_sig_block", BIF_ARG_1)) {
+ if (is_tuple_arity(BIF_ARG_2, 2)) {
+ Eterm *tp = tuple_val(BIF_ARG_2);
+ Sint64 time;
+ if (is_internal_pid(tp[1]) && term_to_Sint64(tp[2], &time)) {
+ ErtsMonotonicTime wait_time = time;
+ Eterm res;
+
+ res = erts_proc_sig_send_rpc_request(BIF_P,
+ tp[1],
+ 0,
+ proc_sig_block,
+ (void *) (Sint) wait_time);
+ if (is_non_value(res))
+ BIF_RET(am_false);
+ BIF_RET(am_true);
+ }
+ }
}
}
diff --git a/erts/emulator/beam/erl_bif_op.c b/erts/emulator/beam/erl_bif_op.c
index a594ec1493..7113d9e890 100644
--- a/erts/emulator/beam/erl_bif_op.c
+++ b/erts/emulator/beam/erl_bif_op.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -251,19 +251,14 @@ Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2)
goto error;
}
- if (is_fun(arg1)) {
+ if (is_any_fun(arg1)) {
ErlFunThing* funp = (ErlFunThing *) fun_val(arg1);
if (funp->arity == (Uint) arity) {
BIF_RET(am_true);
}
- } else if (is_export(arg1)) {
- Export* exp = (Export *) (export_val(arg1)[1]);
-
- if (exp->info.mfa.arity == (Uint) arity) {
- BIF_RET(am_true);
- }
}
+
BIF_RET(am_false);
}
diff --git a/erts/emulator/beam/erl_bif_persistent.c b/erts/emulator/beam/erl_bif_persistent.c
index 9d9ac45266..08e15f55d6 100644
--- a/erts/emulator/beam/erl_bif_persistent.c
+++ b/erts/emulator/beam/erl_bif_persistent.c
@@ -474,9 +474,9 @@ BIF_RETTYPE persistent_term_get_0(BIF_ALIST_0)
}
}
-BIF_RETTYPE persistent_term_get_1(BIF_ALIST_1)
+static ERTS_INLINE Eterm
+persistent_term_get(Eterm key)
{
- Eterm key = BIF_ARG_1;
HashTable* hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table);
Eterm bucket;
@@ -484,24 +484,33 @@ BIF_RETTYPE persistent_term_get_1(BIF_ALIST_1)
if (is_boxed(bucket)) {
ASSERT(is_tuple_arity(bucket, 2));
- BIF_RET(tuple_val(bucket)[2]);
+ return tuple_val(bucket)[2];
}
- BIF_ERROR(BIF_P, BADARG);
+ return THE_NON_VALUE;
}
-BIF_RETTYPE persistent_term_get_2(BIF_ALIST_2)
+Eterm
+erts_persistent_term_get(Eterm key)
{
- Eterm key = BIF_ARG_1;
- Eterm result = BIF_ARG_2;
- HashTable* hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table);
- Eterm bucket;
+ return persistent_term_get(key);
+}
- (void)lookup(hash_table, key, &bucket);
+BIF_RETTYPE persistent_term_get_1(BIF_ALIST_1)
+{
+ Eterm result = persistent_term_get(BIF_ARG_1);
+ if (is_non_value(result)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
- if (is_boxed(bucket)) {
- ASSERT(is_tuple_arity(bucket, 2));
- result = tuple_val(bucket)[2];
+ BIF_RET(result);
+}
+
+BIF_RETTYPE persistent_term_get_2(BIF_ALIST_2)
+{
+ Eterm result = persistent_term_get(BIF_ARG_1);
+ if (is_non_value(result)) {
+ result = BIF_ARG_2;
}
BIF_RET(result);
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 0570d604eb..737a6be15f 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -104,7 +104,7 @@ BIF_RETTYPE erts_internal_open_port_2(BIF_ALIST_2)
port->async_open_port->to = BIF_P->common.id;
/*
- * We unconditionaly *must* do a receive on a message
+ * We unconditionally *must* do a receive on a message
* containing the reference after this...
*/
erts_msgq_set_save_end(BIF_P);
@@ -238,8 +238,17 @@ BIF_RETTYPE erts_internal_port_command_3(BIF_ALIST_3)
}
else {
/* Ensure signal order is preserved... */
- if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
- ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(res, BIF_P, res);
+ if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_PREP_HANDLE_SIGNALS_FROM_RETURN(res, BIF_P,
+ from, res);
+ }
}
return res;
@@ -287,8 +296,16 @@ BIF_RETTYPE erts_internal_port_call_3(BIF_ALIST_3)
ERTS_BIF_EXITED(BIF_P);
else {
/* Ensure signal order is preserved... */
- if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, from, retval);
+ }
}
BIF_RET(retval);
@@ -335,8 +352,16 @@ BIF_RETTYPE erts_internal_port_control_3(BIF_ALIST_3)
ERTS_BIF_EXITED(BIF_P);
else {
/* Ensure signal order is preserved... */
- if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, from, retval);
+ }
}
BIF_RET(retval);
@@ -382,8 +407,16 @@ BIF_RETTYPE erts_internal_port_close_1(BIF_ALIST_1)
}
/* Ensure signal order is preserved... */
- if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, from, retval);
+ }
BIF_RET(retval);
}
@@ -426,8 +459,16 @@ BIF_RETTYPE erts_internal_port_connect_2(BIF_ALIST_2)
}
/* Ensure signal order is preserved... */
- if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, from, retval);
+ }
BIF_RET(retval);
}
@@ -435,7 +476,7 @@ BIF_RETTYPE erts_internal_port_connect_2(BIF_ALIST_2)
BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
{
Eterm retval;
- Port* prt;
+ Port* prt = NULL;
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
@@ -474,8 +515,16 @@ BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
}
/* Ensure signal order is preserved... */
- if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, from, retval);
+ }
BIF_RET(retval);
}
@@ -484,7 +533,7 @@ BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
{
Eterm retval;
- Port* prt;
+ Port* prt = NULL;
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
@@ -523,8 +572,16 @@ BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
}
/* Ensure signal order is preserved... */
- if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
- ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P)) {
+ Eterm from;
+ if (is_internal_port(BIF_ARG_1))
+ from = BIF_ARG_1;
+ else if (prt)
+ from = prt->common.id;
+ else
+ from = NIL;
+ ERTS_BIF_HANDLE_SIGNALS_FROM_RETURN(BIF_P, from, retval);
+ }
BIF_RET(retval);
}
@@ -988,7 +1045,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
tp = tuple_val(name);
arity = *tp++;
- if (arity == make_arityval(0)) {
+ if (arity == make_arityval_zero()) {
goto badarg;
}
@@ -1000,7 +1057,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
name = tp[1];
encoding = erts_get_native_filename_encoding();
/* Do not convert the command to utf-16le yet, do that in win32 specific code */
- /* since the cmd is used for comparsion with drivers names and copied to port info */
+ /* since the cmd is used for comparison with drivers names and copied to port info */
if (encoding == ERL_FILENAME_WIN_WCHAR) {
encoding = ERL_FILENAME_UTF8;
}
@@ -1124,7 +1181,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
goto do_return;
}
-/* Merges the the global environment and the given {Key, Value} list into env,
+/* Merges the global environment and the given {Key, Value} list into env,
* unsetting all keys whose value is either 'false' or NIL. The behavior on
* NIL is undocumented and perhaps surprising, but the previous implementation
* worked in this manner. */
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 8e834e9c3c..e3008dfcef 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ static struct { /* Protected by code write permission */
BpFunctions f; /* Local functions */
BpFunctions e; /* Export entries */
Process* stager;
- ErtsThrPrgrLaterOp lop;
+ ErtsCodeBarrier barrier;
} finish_bp;
static Eterm
@@ -350,7 +350,7 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
ASSERT(matches >= 0);
ASSERT(finish_bp.stager == NULL);
finish_bp.stager = p;
- erts_schedule_thr_prgr_later_op(smp_bp_finisher, NULL, &finish_bp.lop);
+ erts_schedule_code_barrier(&finish_bp.barrier, smp_bp_finisher, NULL);
erts_proc_inc_refc(p);
erts_suspend(p, ERTS_PROC_LOCK_MAIN, NULL);
ERTS_BIF_YIELD_RETURN(p, make_small(matches));
@@ -369,8 +369,8 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
static void smp_bp_finisher(void* null)
{
if (erts_finish_breakpointing()) { /* Not done */
- /* Arrange for being called again */
- erts_schedule_thr_prgr_later_op(smp_bp_finisher, NULL, &finish_bp.lop);
+ /* Arrange for being called again */
+ erts_schedule_code_barrier(&finish_bp.barrier, smp_bp_finisher, NULL);
}
else { /* Done */
Process* p = finish_bp.stager;
@@ -1442,10 +1442,10 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified,
n = finish_bp.e.matched;
for (i = 0; i < n; i++) {
- ErtsCodeInfo *ci = fp[i].ci;
+ ErtsCodeInfo *ci_rw = fp[i].ci_rw;
Export* ep;
- ep = ErtsContainerStruct(ci, Export, info);
+ ep = ErtsContainerStruct(ci_rw, Export, info);
if (ep->bif_number != -1) {
ep->is_bif_traced = !!on;
@@ -1455,14 +1455,15 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified,
/* Turn on global call tracing */
if (!erts_is_export_trampoline_active(ep, code_ix)) {
fp[i].mod->curr.num_traced_exports++;
-#ifdef DEBUG
- ep->info.op = BeamOpCodeAddr(op_i_func_info_IaaI);
+#if defined(DEBUG) && !defined(BEAMASM)
+ ep->info.u.op = BeamOpCodeAddr(op_i_func_info_IaaI);
#endif
ep->trampoline.common.op = BeamOpCodeAddr(op_trace_jump_W);
- ep->trampoline.trace.address = (BeamInstr) ep->addresses[code_ix];
+ ep->trampoline.trace.address =
+ (BeamInstr) ep->dispatch.addresses[code_ix];
}
- erts_set_export_trace(ci, match_prog_set, 0);
+ erts_set_export_trace(ci_rw, match_prog_set, 0);
if (!erts_is_export_trampoline_active(ep, code_ix)) {
ep->trampoline.common.op = BeamOpCodeAddr(op_i_generic_breakpoint);
@@ -1474,7 +1475,7 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified,
* Turn off global tracing, either explicitly or implicitly
* before turning on breakpoint tracing.
*/
- erts_clear_export_trace(ci, 0);
+ erts_clear_export_trace(ci_rw, 0);
if (BeamIsOpCode(ep->trampoline.common.op, op_i_generic_breakpoint)) {
ep->trampoline.common.op = BeamOpCodeAddr(op_trace_jump_W);
}
@@ -1585,10 +1586,10 @@ erts_finish_breakpointing(void)
ERTS_LC_ASSERT(erts_has_code_write_permission());
/*
- * Memory barriers will be issued for all schedulers *before*
- * each of the stages below. (Unless the other schedulers
- * are blocked, in which case memory barriers will be issued
- * when they are awaken.)
+ * Memory and instruction barriers will be issued for all schedulers
+ * *before* each of the stages below. (Unless the other schedulers
+ * are blocked, in which case memory barriers will be issued when
+ * they are awakened.)
*/
switch (finish_bp.current++) {
case 0:
@@ -1669,7 +1670,7 @@ install_exp_breakpoints(BpFunctions* f)
Uint i;
for (i = 0; i < ne; i++) {
- Export* ep = ErtsContainerStruct(fp[i].ci, Export, info);
+ Export* ep = ErtsContainerStruct(fp[i].ci_rw, Export, info);
erts_activate_export_trampoline(ep, code_ix);
}
}
@@ -1683,11 +1684,12 @@ uninstall_exp_breakpoints(BpFunctions* f)
Uint i;
for (i = 0; i < ne; i++) {
- Export* ep = ErtsContainerStruct(fp[i].ci, Export, info);
+ Export* ep = ErtsContainerStruct(fp[i].ci_rw, Export, info);
if (erts_is_export_trampoline_active(ep, code_ix)) {
ASSERT(BeamIsOpCode(ep->trampoline.common.op, op_trace_jump_W));
- ep->addresses[code_ix] = (ErtsCodePtr)ep->trampoline.trace.address;
+ ep->dispatch.addresses[code_ix] =
+ (ErtsCodePtr)ep->trampoline.trace.address;
}
}
}
@@ -1701,7 +1703,7 @@ clean_export_entries(BpFunctions* f)
Uint i;
for (i = 0; i < ne; i++) {
- Export* ep = ErtsContainerStruct(fp[i].ci, Export, info);
+ Export* ep = ErtsContainerStruct(fp[i].ci_rw, Export, info);
if (erts_is_export_trampoline_active(ep, code_ix)) {
continue;
@@ -1857,8 +1859,7 @@ new_seq_trace_token(Process* p, int ensure_new_heap)
Uint mature_size = p->high_water - mature;
Eterm* tpl = tuple_val(SEQ_TRACE_TOKEN(p));
ASSERT(arityval(tpl[0]) == 5);
- if (ErtsInArea(tpl, OLD_HEAP(p),
- (OLD_HEND(p) - OLD_HEAP(p))*sizeof(Eterm)) ||
+ if (ErtsInBetween(tpl, OLD_HEAP(p), OLD_HEND(p)) ||
ErtsInArea(tpl, mature, mature_size*sizeof(Eterm))) {
hp = HAlloc(p, 6);
sys_memcpy(hp, tpl, 6*sizeof(Eterm));
diff --git a/erts/emulator/beam/erl_bif_unique.c b/erts/emulator/beam/erl_bif_unique.c
index 0deced34de..7b3b3746b1 100644
--- a/erts/emulator/beam/erl_bif_unique.c
+++ b/erts/emulator/beam/erl_bif_unique.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -701,6 +701,27 @@ init_pid_ref_tables(void)
}
}
+
+Uint
+erts_pid_ref_table_size(void)
+{
+ int i;
+ Uint sz = 0;
+
+ for (i = 0; i <= erts_no_schedulers; i++) {
+ HashInfo hi;
+ ErtsPidRefTable *tblp = &pid_ref_table[i].u.table;
+ erts_rwmtx_rlock(&tblp->rwmtx);
+ hash_get_info(&hi, &tblp->hash);
+ erts_rwmtx_runlock(&tblp->rwmtx);
+ sz += (Uint) hi.objs;
+ }
+
+ return sz;
+}
+
+
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Unique Integer *
\* */
diff --git a/erts/emulator/beam/erl_bif_unique.h b/erts/emulator/beam/erl_bif_unique.h
index 58426b0b55..bcbcfaee0d 100644
--- a/erts/emulator/beam/erl_bif_unique.h
+++ b/erts/emulator/beam/erl_bif_unique.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ void erts_magic_ref_save_bin__(Eterm ref);
ErtsMagicBinary *erts_magic_ref_lookup_bin__(Uint32 refn[ERTS_REF_NUMBERS]);
void erts_pid_ref_delete(Eterm ref);
Eterm erts_pid_ref_lookup__(Uint32 refn[ERTS_REF_NUMBERS]);
-
+Uint erts_pid_ref_table_size(void);
/* strict monotonic counter */
diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h
index df18e6d835..50affdf2b7 100644
--- a/erts/emulator/beam/erl_binary.h
+++ b/erts/emulator/beam/erl_binary.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -271,7 +271,7 @@ void erts_init_binary(void);
byte* erts_get_aligned_binary_bytes_extra(Eterm, byte**, ErtsAlcType_t, unsigned extra);
/* Used by unicode module */
-Eterm erts_bin_bytes_to_list(Eterm previous, Eterm* hp, byte* bytes, Uint size, Uint bitoffs);
+Eterm erts_bin_bytes_to_list(Eterm previous, Eterm* hp, const byte* bytes, Uint size, Uint bitoffs);
/*
* Common implementation for erlang:list_to_binary/1 and binary:list_to_bin/1
@@ -281,14 +281,7 @@ BIF_RETTYPE erts_list_to_binary_bif(Process *p, Eterm arg, Export *bif);
BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen);
-typedef union {
- /*
- * These two are almost always of
- * the same size, but when fallback
- * atomics are used they might
- * differ in size.
- */
- erts_atomic_t smp_atomic_word;
+typedef struct {
erts_atomic_t atomic_word;
} ErtsMagicIndirectionWord;
@@ -328,6 +321,16 @@ ERTS_GLB_INLINE Binary *erts_create_magic_indirection(int (*destructor)(Binary *
ERTS_GLB_INLINE erts_atomic_t *erts_binary_to_magic_indirection(Binary *bp);
ERTS_GLB_INLINE erts_atomic_t *erts_binary_to_magic_indirection(Binary *bp);
+/* A binary's size in bits must fit into a word for matching to work. We used
+ * to allow creating larger binaries than this, but they acted really strangely
+ * in Erlang code and were pretty much only usable in drivers and NIFs.
+ *
+ * This check also ensures, indirectly, that there won't be an overflow when
+ * the size is bumped by CHICKEN_PAD and the binary struct itself. */
+#define IS_BINARY_SIZE_OK(BYTE_SIZE) \
+ ERTS_LIKELY(BYTE_SIZE <= ERTS_UWORD_MAX / CHAR_BIT)
+
+
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
#include <stddef.h> /* offsetof */
@@ -352,15 +355,6 @@ erts_free_aligned_binary_bytes(byte* buf)
erts_free_aligned_binary_bytes_extra(buf,ERTS_ALC_T_TMP);
}
-/* A binary's size in bits must fit into a word for matching to work. We used
- * to allow creating larger binaries than this, but they acted really strangely
- * in Erlang code and were pretty much only usable in drivers and NIFs.
- *
- * This check also ensures, indirectly, that there won't be an overflow when
- * the size is bumped by CHICKEN_PAD and the binary struct itself. */
-#define IS_BINARY_SIZE_OK(BYTE_SIZE) \
- ERTS_LIKELY(BYTE_SIZE <= ERTS_UWORD_MAX / CHAR_BIT)
-
/* Explicit extra bytes allocated to counter buggy drivers.
** These extra bytes where earlier (< R13B04) added by an alignment-bug
** in this code. Do we dare remove this in some major release (R14?) maybe?
@@ -562,7 +556,7 @@ erts_binary_to_magic_indirection(Binary *bp)
ASSERT(bp->intern.flags & BIN_FLAG_MAGIC);
ASSERT(ERTS_MAGIC_BIN_ATYPE(bp) == ERTS_ALC_T_MINDIRECTION);
mip = (ErtsMagicIndirectionWord*)ERTS_MAGIC_BIN_UNALIGNED_DATA(bp);
- return &mip->smp_atomic_word;
+ return &mip->atomic_word;
}
#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index 9fa010bed0..8b6698b6ae 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,6 +78,11 @@ typedef Uint16 erlfp16;
static byte get_bit(byte b, size_t a_offs);
+/* If the proc bin is larger than 16 MB,
+ we only increase by 20% instead of doubling */
+#define GROW_PROC_BIN_SIZE(size) \
+ (((size) > (1ull << 24)) ? 1.2*(size) : 2*(size))
+
/* the state resides in the current process' scheduler data */
#define byte_buf (ErlBitsState.byte_buf_)
@@ -1016,10 +1021,12 @@ erts_new_bs_put_binary(Process *c_p, Eterm arg, Uint num_bits)
ERL_BITS_DEFINE_STATEP(c_p);
if (!is_binary(arg)) {
- return 0;
+ c_p->fvalue = arg;
+ return 0;
}
ERTS_GET_BINARY_BYTES(arg, bptr, bitoffs, bitsize);
if (num_bits > 8*binary_size(arg)+bitsize) {
+ c_p->fvalue = arg;
return 0;
}
copy_binary_to_buffer(erts_current_bin, erts_bin_offset, bptr, bitoffs, num_bits);
@@ -1038,24 +1045,20 @@ erts_new_bs_put_binary_all(Process *c_p, Eterm arg, Uint unit)
ERL_BITS_DEFINE_STATEP(c_p);
/*
- * This type test is not needed if the code was compiled with
- * an R12B or later compiler, since there would have been a
- * call to bit_size/1 or byte_size/1 that would have failed if
- * 'arg' was not a binary. However, in R11B and earlier releases,
- * size/1 was use for calculating the size of the binary, and
- * therefore 'arg' could be a tuple.
+ * This instruction is always preceded by a size calculation that
+ * will guarantee that 'arg' is a binary.
*/
- if (!is_binary(arg)) {
- return 0;
- }
+ ASSERT(is_binary(arg));
ERTS_GET_BINARY_BYTES(arg, bptr, bitoffs, bitsize);
num_bits = 8*binary_size(arg)+bitsize;
if (unit == 8) {
if (bitsize != 0) {
+ c_p->fvalue = arg;
return 0;
}
} else if (unit != 1 && num_bits % unit != 0) {
+ c_p->fvalue = arg;
return 0;
}
copy_binary_to_buffer(erts_current_bin, erts_bin_offset, bptr, bitoffs, num_bits);
@@ -1064,7 +1067,13 @@ erts_new_bs_put_binary_all(Process *c_p, Eterm arg, Uint unit)
return 1;
}
-int
+/*
+ * Returns THE_NON_VALUE on success.
+ *
+ * On failure, returns whichever was wrong of the value or the size,
+ * and sets c_p-fvalue to 'type', 'no_float', or 'invalid'.
+ */
+Eterm
erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
{
ERL_BITS_DEFINE_STATEP(c_p);
@@ -1099,7 +1108,8 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
#endif
} else if (is_big(arg)) {
if (big_to_double(arg, &u.f64) < 0) {
- return 0;
+ c_p->fvalue = am_no_float;
+ return arg;
}
#ifdef DOUBLE_MIDDLE_ENDIAN
a = u.i32[1];
@@ -1109,7 +1119,8 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
b = u.i32[1];
#endif
} else {
- return 0;
+ c_p->fvalue = am_type;
+ return arg;
}
} else if (num_bits == 32) {
union {
@@ -1131,14 +1142,16 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
} else if (is_big(arg)) {
double f64;
if (big_to_double(arg, &f64) < 0) {
- return 0;
+ c_p->fvalue = am_no_float;
+ return arg;
}
ERTS_FP_CHECK_INIT(c_p);
u.f32 = (float) f64;
ERTS_FP_ERROR(c_p,u.f32,;);
a = u.i32;
} else {
- return 0;
+ c_p->fvalue = am_type;
+ return arg;
}
} else if (num_bits == 16) {
union {
@@ -1160,17 +1173,20 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
} else if (is_big(arg)) {
double f64;
if (big_to_double(arg, &f64) < 0) {
- return 0;
+ c_p->fvalue = am_no_float;
+ return arg;
}
ERTS_FP_CHECK_INIT(c_p);
ERTS_FP_ERROR(c_p,f64,;);
u.f16 = FP16_FROM_FP64(f64);
a = u.i16;
} else {
- return 0;
+ c_p->fvalue = am_type;
+ return arg;
}
} else {
- return 0;
+ c_p->fvalue = am_invalid;
+ return make_small(num_bits);
}
if (BIT_IS_MACHINE_ENDIAN(flags)) {
@@ -1266,7 +1282,8 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
#endif
} else if (is_big(arg)) {
if (big_to_double(arg, &f64) < 0) {
- return 0;
+ c_p->fvalue = am_no_float;
+ return arg;
}
#ifdef DOUBLE_MIDDLE_ENDIAN
ftmp.fd = f64;
@@ -1274,7 +1291,8 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
bptr = (byte *) &f64;
#endif
} else {
- return 0;
+ c_p->fvalue = am_type;
+ return arg;
}
#ifdef DOUBLE_MIDDLE_ENDIAN
fbuf.fw[0] = ftmp.fw[1];
@@ -1294,14 +1312,16 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
bptr = (byte *) &f32;
} else if (is_big(arg)) {
if (big_to_double(arg, &f64) < 0) {
- return 0;
+ c_p->fvalue = am_no_float;
+ return arg;
}
ERTS_FP_CHECK_INIT(c_p);
f32 = (float) f64;
ERTS_FP_ERROR(c_p,f32,;);
bptr = (byte *) &f32;
} else {
- return 0;
+ c_p->fvalue = am_type;
+ return arg;
}
} else if (num_bits == 16) {
if (is_float(arg)) {
@@ -1316,17 +1336,20 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
bptr = (byte *) &f16;
} else if (is_big(arg)) {
if (big_to_double(arg, &f64) < 0) {
- return 0;
+ c_p->fvalue = am_no_float;
+ return arg;
}
ERTS_FP_CHECK_INIT(c_p);
ERTS_FP_ERROR(c_p,f64,;);
f16 = FP16_FROM_FP64(f64);
bptr = (byte *) &f16;
} else {
- return 0;
+ c_p->fvalue = am_type;
+ return arg;
}
} else {
- return 0;
+ c_p->fvalue = am_invalid;
+ return make_small(num_bits);
}
if (BIT_IS_MACHINE_ENDIAN(flags)) {
erts_copy_bits(bptr, 0, 1,
@@ -1339,7 +1362,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags)
}
}
erts_bin_offset += num_bits;
- return 1;
+ return THE_NON_VALUE;
}
void
@@ -1353,21 +1376,30 @@ erts_new_bs_put_string(ERL_BITS_PROTO_2(byte* iptr, Uint num_bytes))
erts_bin_offset += num_bytes*8;
}
+static ERTS_INLINE
+void increase_proc_bin_sz(Process* p, ProcBin* pb, Uint new_size)
+{
+ if (new_size > pb->size) {
+ const Uint incr = (new_size / sizeof(Eterm) -
+ pb->size / sizeof(Eterm));
+ if (ErtsInBetween(pb, OLD_HEAP(p), OLD_HTOP(p))) {
+ p->bin_old_vheap += incr;
+ }
+ else {
+ OH_OVERHEAD(&MSO(p), incr);
+ }
+ pb->size = new_size;
+ }
+ else
+ ASSERT(new_size == pb->size);
+}
+
Eterm
erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
- Uint extra_words, Uint unit)
+ Uint extra_words, Uint unit)
{
- Eterm bin; /* Given binary */
- Eterm* ptr;
- Eterm hdr;
- ErlSubBin* sb;
- ProcBin* pb;
- Binary* binp;
- Uint heap_need;
- Uint build_size_in_bits;
- Uint used_size_in_bits;
Uint unsigned_bits;
- ERL_BITS_DEFINE_STATEP(c_p);
+ Uint build_size_in_bits;
/*
* Check and untag the requested build size.
@@ -1375,7 +1407,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
if (is_small(build_size_term)) {
Sint signed_bits = signed_val(build_size_term);
if (signed_bits < 0) {
- goto badarg;
+ c_p->freason = BADARG;
+ return THE_NON_VALUE;
}
build_size_in_bits = (Uint) signed_bits;
} else if (term_to_Uint(build_size_term, &unsigned_bits)) {
@@ -1384,12 +1417,33 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
c_p->freason = unsigned_bits;
return THE_NON_VALUE;
}
+ return erts_bs_append_checked(c_p, reg, live, build_size_in_bits,
+ extra_words, unit);
+}
+
+Eterm
+erts_bs_append_checked(Process* c_p, Eterm* reg, Uint live,
+ Uint build_size_in_bits, Uint extra_words,
+ Uint unit)
+{
+ Eterm bin; /* Given binary */
+ Eterm* ptr;
+ Eterm hdr;
+ ErlSubBin* sb;
+ ProcBin* pb;
+ Binary* binp;
+ Uint heap_need;
+ Uint used_size_in_bits;
+ ERL_BITS_DEFINE_STATEP(c_p);
/*
* Check the binary argument.
*/
bin = reg[live];
if (!is_boxed(bin)) {
+ type_error:
+ c_p->fvalue = am_type;
+
badarg:
c_p->freason = BADARG;
return THE_NON_VALUE;
@@ -1397,7 +1451,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
ptr = boxed_val(bin);
hdr = *ptr;
if (!is_binary_header(hdr)) {
- goto badarg;
+ goto type_error;
}
if (hdr != HEADER_SUB_BIN) {
goto not_writable;
@@ -1420,6 +1474,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
if (unit > 1) {
if ((unit == 8 && (erts_bin_offset & 7) != 0) ||
(unit != 8 && (erts_bin_offset % unit) != 0)) {
+ c_p->fvalue = am_unit;
goto badarg;
}
}
@@ -1433,6 +1488,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
}
if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) {
+ c_p->fvalue = am_size;
c_p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
@@ -1440,7 +1496,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
used_size_in_bits = erts_bin_offset + build_size_in_bits;
sb->is_writable = 0; /* Make sure that no one else can write. */
- pb->size = NBYTES(used_size_in_bits);
+
+ increase_proc_bin_sz(c_p, pb, NBYTES(used_size_in_bits));
pb->flags |= PB_ACTIVE_WRITER;
/*
@@ -1448,7 +1505,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
*/
binp = pb->val;
if (binp->orig_size < pb->size) {
- Uint new_size = 2*pb->size;
+ Uint new_size = GROW_PROC_BIN_SIZE(pb->size);
+
binp = erts_bin_realloc(binp, new_size);
pb->val = binp;
pb->bytes = (byte *) binp->orig_bytes;
@@ -1509,7 +1567,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
erts_bin_offset = 8*binary_size(bin) + bitsize;
if (unit > 1) {
if ((unit == 8 && (erts_bin_offset & 7) != 0) ||
- (unit != 8 && (erts_bin_offset % unit) != 0)) {
+ (unit != 8 && (erts_bin_offset % unit) != 0)) {
+ c_p->fvalue = am_unit;
goto badarg;
}
}
@@ -1519,6 +1578,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
}
if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) {
+ c_p->fvalue = am_size;
c_p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
@@ -1527,7 +1587,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
used_size_in_bytes = NBYTES(used_size_in_bits);
if(used_size_in_bits < (ERTS_UINT_MAX / 2)) {
- bin_size = 2 * used_size_in_bytes;
+ bin_size = GROW_PROC_BIN_SIZE(used_size_in_bytes);
} else {
bin_size = NBYTES(ERTS_UINT_MAX);
}
@@ -1547,8 +1607,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
hp += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = used_size_in_bytes;
- pb->next = MSO(c_p).first;
- MSO(c_p).first = (struct erl_off_heap_header*)pb;
+ pb->next = c_p->wrt_bins;
+ c_p->wrt_bins = (struct erl_off_heap_header*)pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
@@ -1583,14 +1643,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
Eterm
erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit)
{
- Eterm* ptr;
- ErlSubBin* sb;
- ProcBin* pb;
- Binary* binp;
- Uint build_size_in_bits;
- Uint pos_in_bits_after_build;
Uint unsigned_bits;
- ERL_BITS_DEFINE_STATEP(p);
+ Uint build_size_in_bits;
/*
* Check and untag the requested build size.
@@ -1608,6 +1662,18 @@ erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit)
p->freason = unsigned_bits;
return THE_NON_VALUE;
}
+ return erts_bs_private_append_checked(p, bin, build_size_in_bits, unit);
+}
+
+Eterm
+erts_bs_private_append_checked(Process* p, Eterm bin, Uint build_size_in_bits, Uint unit)
+{
+ Eterm* ptr;
+ ErlSubBin* sb;
+ ProcBin* pb;
+ Binary* binp;
+ Uint pos_in_bits_after_build;
+ ERL_BITS_DEFINE_STATEP(p);
ptr = boxed_val(bin);
ASSERT(*ptr == HEADER_SUB_BIN);
@@ -1624,20 +1690,20 @@ erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit)
erts_bin_offset = 8*sb->size + sb->bitsize;
if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) {
+ p->fvalue = am_size;
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
pos_in_bits_after_build = erts_bin_offset + build_size_in_bits;
- pb->size = (pos_in_bits_after_build+7) >> 3;
- pb->flags |= PB_ACTIVE_WRITER;
+ increase_proc_bin_sz(p, pb, (pos_in_bits_after_build+7) >> 3);
/*
* Reallocate the binary if it is too small.
*/
binp = pb->val;
if (binp->orig_size < pb->size) {
- Uint new_size = 2*pb->size;
+ Uint new_size = GROW_PROC_BIN_SIZE(pb->size);
BUMP_REDS(p, pb->size / BITS_PER_REDUCTION);
if (pb->flags & PB_IS_WRITABLE) {
@@ -1656,16 +1722,45 @@ erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit)
* on. That means that a trace process now has (or have
* had) a reference to the binary, so we are not allowed
* to reallocate the binary. Instead, we must allocate a new
- * binary and copy the contents of the old binary into it.
+ * binary and copy the contents of the old binary into it.
+ *
+ * Also make a new ProcBin as the old one may have been moved
+ * from the 'wrt_bins' list to the regular 'off_heap' list by
+ * the GC. To move it back would mean traversing the off_heap list
+ * from the start. So instead create a new ProcBin for this
+ * (hopefully) rare case.
*/
Binary* bptr = erts_bin_nrml_alloc(new_size);
- sys_memcpy(bptr->orig_bytes, binp->orig_bytes, binp->orig_size);
- pb->flags |= PB_IS_WRITABLE | PB_ACTIVE_WRITER;
- pb->val = bptr;
- pb->bytes = (byte *) bptr->orig_bytes;
- erts_bin_release(binp);
+ ProcBin* new_pb;
+ Uint sz = PROC_BIN_SIZE;
+
+ sys_memcpy(bptr->orig_bytes, binp->orig_bytes, binp->orig_size);
+
+ /* If the subbinary is on the mature or old heap, we need to also move it */
+ if (ErtsInBetween(sb, OLD_HEAP(p), OLD_HTOP(p)) ||
+ ErtsInBetween(sb, HEAP_START(p), HIGH_WATER(p))) {
+ sz += ERL_SUB_BIN_SIZE;
+ }
+
+ new_pb = (ProcBin*) HeapFragOnlyAlloc(p, sz);
+ new_pb->thing_word = HEADER_PROC_BIN;
+ new_pb->size = pb->size;
+ new_pb->val = bptr;
+ new_pb->bytes = (byte *) bptr->orig_bytes;
+ new_pb->next = p->wrt_bins;
+ p->wrt_bins = (struct erl_off_heap_header*) new_pb;
+ pb = new_pb;
+ if (sz != PROC_BIN_SIZE) {
+ ErlSubBin *new_sb = (ErlSubBin*)(new_pb+1);
+ sys_memcpy(new_sb, sb, sizeof(*new_sb));
+ sb = new_sb;
+ bin = make_binary(sb);
+ }
+ sb->orig = make_binary(new_pb);
}
}
+ pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
+
erts_current_bin = pb->bytes;
sb->size = pos_in_bits_after_build >> 3;
@@ -1711,8 +1806,8 @@ erts_bs_init_writable(Process* p, Eterm sz)
hp += PROC_BIN_SIZE;
pb->thing_word = HEADER_PROC_BIN;
pb->size = 0;
- pb->next = MSO(p).first;
- MSO(p).first = (struct erl_off_heap_header*) pb;
+ pb->next = p->wrt_bins;
+ p->wrt_bins = (struct erl_off_heap_header*) pb;
pb->val = bptr;
pb->bytes = (byte*) bptr->orig_bytes;
pb->flags = PB_IS_WRITABLE | PB_ACTIVE_WRITER;
diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h
index 25aff39047..4596c65959 100644
--- a/erts/emulator/beam/erl_bits.h
+++ b/erts/emulator/beam/erl_bits.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -173,7 +173,7 @@ int erts_bs_put_utf8(ERL_BITS_PROTO_1(Eterm Integer));
int erts_bs_put_utf16(ERL_BITS_PROTO_2(Eterm Integer, Uint flags));
int erts_new_bs_put_binary(Process *c_p, Eterm Bin, Uint num_bits);
int erts_new_bs_put_binary_all(Process *c_p, Eterm Bin, Uint unit);
-int erts_new_bs_put_float(Process *c_p, Eterm Float, Uint num_bits, int flags);
+Eterm erts_new_bs_put_float(Process *c_p, Eterm Float, Uint num_bits, int flags);
void erts_new_bs_put_string(ERL_BITS_PROTO_2(byte* iptr, Uint num_bytes));
Uint erts_bits_bufs_size(void);
@@ -182,7 +182,10 @@ Eterm erts_bs_get_utf8(ErlBinMatchBuffer* mb);
Eterm erts_bs_get_utf16(ErlBinMatchBuffer* mb, Uint flags);
Eterm erts_bs_append(Process* p, Eterm* reg, Uint live, Eterm build_size_term,
Uint extra_words, Uint unit);
+Eterm erts_bs_append_checked(Process* p, Eterm* reg, Uint live, Uint size,
+ Uint extra_words, Uint unit);
Eterm erts_bs_private_append(Process* p, Eterm bin, Eterm sz, Uint unit);
+Eterm erts_bs_private_append_checked(Process* p, Eterm bin, Uint size, Uint unit);
Eterm erts_bs_init_writable(Process* p, Eterm sz);
/*
@@ -204,7 +207,7 @@ Eterm erts_extract_sub_binary(Eterm **hp, Eterm base_bin, byte *base_data,
#define EXTRACT_SUB_BIN_HEAP_NEED (heap_bin_size(ERL_ONHEAP_BIN_LIMIT))
/*
- * Flags for bs_get_* / bs_put_* / bs_init* instructions.
+ * Flags for bs_create_bin / bs_get_* / bs_put_* / bs_init* instructions.
*/
#define BSF_ALIGNED 1 /* Field is guaranteed to be byte-aligned. */
@@ -213,4 +216,24 @@ Eterm erts_extract_sub_binary(Eterm **hp, Eterm base_bin, byte *base_data,
#define BSF_EXACT 8 /* Size in bs_init is exact. */
#define BSF_NATIVE 16 /* Native endian. */
+/*
+ * Binary construction operations.
+ */
+
+#define BSC_APPEND 0
+#define BSC_PRIVATE_APPEND 1
+#define BSC_BINARY 2
+#define BSC_BINARY_FIXED_SIZE 3
+#define BSC_BINARY_ALL 4
+#define BSC_FLOAT 5
+#define BSC_FLOAT_FIXED_SIZE 6
+#define BSC_INTEGER 7
+#define BSC_INTEGER_FIXED_SIZE 8
+#define BSC_STRING 9
+#define BSC_UTF8 10
+#define BSC_UTF16 11
+#define BSC_UTF32 12
+
+#define BSC_NUM_ARGS 5
+
#endif /* __ERL_BITS_H__ */
diff --git a/erts/emulator/beam/erl_bits_f16.h b/erts/emulator/beam/erl_bits_f16.h
index 653239d64d..cda52ab719 100644
--- a/erts/emulator/beam/erl_bits_f16.h
+++ b/erts/emulator/beam/erl_bits_f16.h
@@ -33,7 +33,7 @@
* 1. uint16_t and uint32_t have been rewritten to Uint16 and Uint32
* 2. Mixed declarations were moved to the top to avoid warnings
* 3. inline was rewritten as ERTS_INLINE
- * 4. UINT16_C(x) and UINT32_C(x) were rewriten to xU as we don't support 16bits platform
+ * 4. UINT16_C(x) and UINT32_C(x) were rewritten to xU as we don't support 16bits platform
*/
static ERTS_INLINE float fp32_from_bits(Uint32 w) {
@@ -180,7 +180,7 @@ static ERTS_INLINE float fp16_ieee_to_fp32_value(Uint16 h) {
* A normalized single-precision floating-point number is represented as:
* FP32 = (1 + mantissa * 2**(-23)) * 2**(exponent - 127)
* Therefore, when the biased exponent is 126, a unit change in the mantissa of the input denormalized half-precision
- * number causes a change of the constructud single-precision number by 2**(-24), i.e. the same ammount.
+ * number causes a change of the constructud single-precision number by 2**(-24), i.e. the same amount.
*
* The last step is to adjust the bias of the constructed single-precision number. When the input half-precision number
* is zero, the constructed single-precision number has the value of
diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c
index 91a99077f8..ad07f989b6 100644
--- a/erts/emulator/beam/erl_cpu_topology.c
+++ b/erts/emulator/beam/erl_cpu_topology.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
#include "bif.h"
#include "erl_cpu_topology.h"
#include "erl_flxctr.h"
+#include "erl_global_literals.h"
#define ERTS_MAX_READER_GROUPS 64
@@ -907,12 +908,15 @@ erts_fake_scheduler_bindings(Process *p, Eterm how)
erts_fprintf(stderr, " %2d", cpudata[i].logical);
erts_fprintf(stderr, "\n");
#endif
-
- hp = HAlloc(p, cpudata_size+1);
- ERTS_BIF_PREP_RET(res, make_tuple(hp));
- *hp++ = make_arityval((Uint) cpudata_size);
- for (i = 0; i < cpudata_size; i++)
- *hp++ = make_small((Uint) cpudata[i].logical);
+ if (cpudata_size == 0) {
+ ERTS_BIF_PREP_RET(res, ERTS_GLOBAL_LIT_EMPTY_TUPLE);
+ } else {
+ hp = HAlloc(p, cpudata_size+1);
+ ERTS_BIF_PREP_RET(res, make_tuple(hp));
+ *hp++ = make_arityval((Uint) cpudata_size);
+ for (i = 0; i < cpudata_size; i++)
+ *hp++ = make_small((Uint) cpudata[i].logical);
+ }
}
destroy_tmp_cpu_topology_copy(cpudata);
@@ -1674,8 +1678,10 @@ erts_early_init_cpu_topology(int no_schedulers,
int max_reader_groups,
int *reader_groups_p,
int max_decentralized_counter_groups,
- int *decentralized_counter_groups_p)
+ int *decentralized_counter_groups_p,
+ int skip_read_topology)
{
+ erts_cpu_info_update(cpuinfo, skip_read_topology);
user_cpudata = NULL;
user_cpudata_size = 0;
@@ -1758,7 +1764,7 @@ erts_update_cpu_info(void)
{
int changed;
erts_rwmtx_rwlock(&cpuinfo_rwmtx);
- changed = erts_cpu_info_update(cpuinfo);
+ changed = erts_cpu_info_update(cpuinfo, 0);
if (changed) {
erts_cpu_topology_t *cpudata;
int cpudata_size;
diff --git a/erts/emulator/beam/erl_cpu_topology.h b/erts/emulator/beam/erl_cpu_topology.h
index 62bd0e73b6..9c9c8d2200 100644
--- a/erts/emulator/beam/erl_cpu_topology.h
+++ b/erts/emulator/beam/erl_cpu_topology.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,8 @@ erts_early_init_cpu_topology(int no_schedulers,
int max_reader_groups,
int *reader_groups_p,
int max_decentralized_counter_groups,
- int *decentralized_counter_groups_p);
+ int *decentralized_counter_groups_p,
+ int skip_read_topology);
void erts_init_cpu_topology(void);
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 05b21c53e2..514fd2b74d 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@
* Extended error information for ETS functions.
*/
-#define EXI_TYPE am_type /* The type is wrong. */
+#define EXI_TYPE am_type /* The type is wrong (or TRAP). */
#define EXI_ID am_id /* The table identifier is invalid. */
#define EXI_ACCESS am_access /* Insufficient access rights for ETS table. */
#define EXI_TAB_TYPE am_table_type /* Unsupported table type for this operation. */
@@ -57,6 +57,10 @@
#define EXI_POSITION am_position /* The position is out of range. */
#define EXI_OWNER am_owner /* The receiving process is already the owner. */
#define EXI_NOT_OWNER am_not_owner /* The current process is not the owner. */
+#define EXI_ALREADY_EXISTS am_already_exists /* The table identifier already exists. */
+
+#define DB_WRITE_CONCURRENCY_MIN_LOCKS 1
+#define DB_WRITE_CONCURRENCY_MAX_LOCKS 32768
erts_atomic_t erts_ets_misc_mem_size;
@@ -241,9 +245,16 @@ static void table_dec_refc(DbTable *tb, erts_aint_t min_val)
schedule_free_dbtable(tb);
}
+static ERTS_INLINE DbTable* btid2tab(Binary* btid)
+{
+ erts_atomic_t *tbref = erts_binary_to_magic_indirection(btid);
+ return (DbTable *) erts_atomic_read_nob(tbref);
+}
+
static int
-db_table_tid_destructor(Binary *unused)
+db_table_tid_destructor(Binary *btid)
{
+ ASSERT(btid2tab(btid) == NULL);
return 1;
}
@@ -255,19 +266,13 @@ make_btid(DbTable *tb)
erts_atomic_init_nob(tbref, (erts_aint_t) tb);
tb->common.btid = btid;
/*
- * Table and magic indirection refer eachother,
- * and table is refered once by being alive...
+ * Table and magic indirection refer each other,
+ * and table is referred once by being alive...
*/
erts_refc_init(&tb->common.refc, 2);
erts_refc_inc(&btid->intern.refc, 1);
}
-static ERTS_INLINE DbTable* btid2tab(Binary* btid)
-{
- erts_atomic_t *tbref = erts_binary_to_magic_indirection(btid);
- return (DbTable *) erts_atomic_read_nob(tbref);
-}
-
static DbTable *
tid2tab(Eterm tid, Eterm *error_info_p)
{
@@ -335,10 +340,23 @@ tid_clear(Process *c_p, DbTable *tb)
}
static ERTS_INLINE Eterm
+make_tid_heap(Eterm **hp, ErlOffHeap *oh, DbTable *tb)
+{
+ return erts_mk_magic_ref(hp, oh, tb->common.btid);
+}
+
+static ERTS_INLINE Eterm
make_tid(Process *c_p, DbTable *tb)
{
Eterm *hp = HAlloc(c_p, ERTS_MAGIC_REF_THING_SIZE);
- return erts_mk_magic_ref(&hp, &c_p->off_heap, tb->common.btid);
+ return make_tid_heap(&hp, &c_p->off_heap, tb);
+}
+
+static Eterm
+make_tid_fact(ErtsHeapFactory *hf, DbTable *tb)
+{
+ Eterm *hp = erts_produce_heap(hf, ERTS_MAGIC_REF_THING_SIZE, 0);
+ return make_tid_heap(&hp, hf->off_heap, tb);
}
Eterm
@@ -347,8 +365,6 @@ erts_db_make_tid(Process *c_p, DbTableCommon *tb)
return make_tid(c_p, (DbTable*)tb);
}
-
-
/*
** The meta hash table of all NAMED ets tables
*/
@@ -388,7 +404,7 @@ typedef enum {
LCK_READ=1, /* read only access */
LCK_WRITE=2, /* exclusive table write access */
LCK_WRITE_REC=3, /* record write access */
- NOLCK_ACCESS=4 /* Used to access the table structure
+ LCK_NOLOCK_ACCESS=4 /* Used to access the table structure
without acquiring the table lock */
} db_lock_kind_t;
@@ -419,12 +435,14 @@ static BIF_RETTYPE ets_select_count_1(BIF_ALIST_1);
static BIF_RETTYPE ets_select_replace_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 Eterm table_info(ErtsHeapFactory* hf, DbTable* tb, Eterm What);
static BIF_RETTYPE ets_select1(Process* p, int bif_ix, Eterm arg1);
static BIF_RETTYPE ets_select2(Process* p, DbTable*, Eterm tid, Eterm ms);
static BIF_RETTYPE ets_select3(Process* p, DbTable*, Eterm tid, Eterm ms, Sint chunk_size);
+static BIF_RETTYPE ets_insert_2_list_continuation(Process* p,
+ struct ets_insert_2_list_info* ctx);
/*
* Exported global
@@ -447,18 +465,20 @@ free_dbtable(void *vtb)
erts_flxctr_add(&tb->common.counters,
ERTS_DB_TABLE_MEM_COUNTER_ID,
-((Sint)erts_flxctr_nr_of_allocated_bytes(&tb->common.counters)));
- ASSERT(erts_flxctr_is_snapshot_ongoing(&tb->common.counters) ||
- sizeof(DbTable) == DB_GET_APPROX_MEM_CONSUMED(tb));
-
- ASSERT(is_immed(tb->common.heir_data));
if (!DB_LOCK_FREE(tb)) {
+ ERTS_DB_ALC_MEM_UPDATE_(tb, erts_rwmtx_size(&tb->common.rwlock), 0);
erts_rwmtx_destroy(&tb->common.rwlock);
erts_mtx_destroy(&tb->common.fixlock);
}
- if (tb->common.btid)
- erts_bin_release(tb->common.btid);
+ ASSERT(is_immed(tb->common.heir_data));
+
+ ASSERT(erts_flxctr_is_snapshot_ongoing(&tb->common.counters) ||
+ sizeof(DbTable) == DB_GET_APPROX_MEM_CONSUMED(tb));
+
+ ASSERT(tb->common.btid);
+ erts_bin_release(tb->common.btid);
erts_flxctr_destroy(&tb->common.counters, ERTS_ALC_T_ETS_CTRS);
erts_free(ERTS_ALC_T_DB_TABLE, tb);
@@ -466,10 +486,7 @@ free_dbtable(void *vtb)
static void schedule_free_dbtable(DbTable* tb)
{
- /*
- * NON-SMP case: Caller is *not* allowed to access the *tb
- * structure after this function has returned!
- * SMP case: Caller is allowed to access the *common* part of the *tb
+ /* SMP case: Caller is allowed to access the *common* part of the *tb
* structure until the bif has returned (we typically need to
* unlock the table lock after this function has returned).
* Caller is *not* allowed to access the specialized part
@@ -641,6 +658,7 @@ static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock)
if (!DB_LOCK_FREE(tb)) {
erts_rwmtx_init_opt(&tb->common.rwlock, &rwmtx_opt, "db_tab",
tb->common.the_name, ERTS_LOCK_FLAGS_CATEGORY_DB);
+ ERTS_DB_ALC_MEM_UPDATE_(tb, 0, erts_rwmtx_size(&tb->common.rwlock));
erts_mtx_init(&tb->common.fixlock, "db_tab_fix",
tb->common.the_name, ERTS_LOCK_FLAGS_CATEGORY_DB);
}
@@ -650,13 +668,15 @@ static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock)
static ERTS_INLINE void db_lock(DbTable* tb, db_lock_kind_t kind)
{
+ ASSERT(kind != LCK_NOLOCK_ACCESS);
if (DB_LOCK_FREE(tb))
return;
if (tb->common.type & DB_FINE_LOCKED) {
if (kind == LCK_WRITE) {
erts_rwmtx_rwlock(&tb->common.rwlock);
tb->common.is_thread_safe = 1;
- } else if (kind != NOLCK_ACCESS) {
+ }
+ else {
erts_rwmtx_rlock(&tb->common.rwlock);
ASSERT(!tb->common.is_thread_safe);
}
@@ -668,8 +688,6 @@ static ERTS_INLINE void db_lock(DbTable* tb, db_lock_kind_t kind)
case LCK_WRITE_REC:
erts_rwmtx_rwlock(&tb->common.rwlock);
break;
- case NOLCK_ACCESS:
- return;
default:
erts_rwmtx_rlock(&tb->common.rwlock);
}
@@ -679,7 +697,7 @@ static ERTS_INLINE void db_lock(DbTable* tb, db_lock_kind_t kind)
static ERTS_INLINE void db_unlock(DbTable* tb, db_lock_kind_t kind)
{
- if (DB_LOCK_FREE(tb) || kind == NOLCK_ACCESS)
+ if (DB_LOCK_FREE(tb) || kind == LCK_NOLOCK_ACCESS)
return;
if (tb->common.type & DB_FINE_LOCKED) {
if (kind == LCK_WRITE) {
@@ -712,7 +730,7 @@ static ERTS_INLINE int db_is_exclusive(DbTable* tb, db_lock_kind_t kind)
return
kind != LCK_READ &&
- kind != NOLCK_ACCESS &&
+ kind != LCK_NOLOCK_ACCESS &&
tb->common.is_thread_safe;
}
@@ -721,36 +739,26 @@ static DbTable* handle_lacking_permission(Process* p, DbTable* tb,
Uint* freason_p)
{
if (tb->common.status & DB_BUSY) {
- void* continuation_state;
if (!db_is_exclusive(tb, kind)) {
db_unlock(tb, kind);
db_lock(tb, LCK_WRITE);
}
- continuation_state = (void*)erts_atomic_read_nob(&tb->common.continuation_state);
- if (continuation_state != NULL) {
- const long iterations_per_red = 10;
- const long reds = iterations_per_red * ERTS_BIF_REDS_LEFT(p);
- long nr_of_reductions = DBG_RANDOM_REDS(reds, (Uint)freason_p);
- const long init_reds = nr_of_reductions;
- tb->common.continuation(&nr_of_reductions,
- &continuation_state,
- NULL);
- if (continuation_state == NULL) {
- erts_atomic_set_relb(&tb->common.continuation_state, (Sint)NULL);
- }
- BUMP_REDS(p, (init_reds - nr_of_reductions) / iterations_per_red);
+ if (tb->common.continuation_ctx) {
+ ets_insert_2_list_continuation(p, tb->common.continuation_ctx);
} else {
delete_all_objects_continue(p, tb);
}
db_unlock(tb, LCK_WRITE);
tb = NULL;
*freason_p = TRAP;
+ p->fvalue = EXI_TYPE;
}
else if (p->common.id != tb->common.owner
- && !(p->flags & F_ETS_SUPER_USER)) {
+ && (!(p->flags & F_ETS_SUPER_USER)
+ || (tb->common.status & DB_DELETE))) {
+ p->fvalue = (tb->common.status & DB_DELETE) ? EXI_ID : EXI_ACCESS;
db_unlock(tb, kind);
tb = NULL;
- p->fvalue = EXI_ACCESS;
*freason_p = BADARG | EXF_HAS_EXT_INFO;
}
return tb;
@@ -761,10 +769,11 @@ DbTable* db_get_table_aux(Process *p,
Eterm id,
int what,
db_lock_kind_t kind,
- int meta_already_locked,
+ int name_already_locked,
Uint* freason_p)
{
DbTable *tb;
+ erts_rwmtx_t *name_lck = NULL;
/*
* IMPORTANT: Only non-dirty scheduler threads are allowed
@@ -772,22 +781,22 @@ DbTable* db_get_table_aux(Process *p,
*/
ASSERT(erts_get_scheduler_data() && !ERTS_SCHEDULER_IS_DIRTY(erts_get_scheduler_data()));
- ASSERT((what == DB_READ_TBL_STRUCT) == (kind == NOLCK_ACCESS));
+ ASSERT((what == DB_READ_TBL_STRUCT) == (kind == LCK_NOLOCK_ACCESS));
if (META_DB_LOCK_FREE())
- meta_already_locked = 1;
+ name_already_locked = 1;
if (is_not_atom(id)) {
tb = tid2tab(id, &p->fvalue);
} else {
- erts_rwmtx_t *mtl;
- struct meta_name_tab_entry* bucket = meta_name_tab_bucket(id,&mtl);
- if (!meta_already_locked)
- erts_rwmtx_rlock(mtl);
+ struct meta_name_tab_entry* bucket = meta_name_tab_bucket(id,&name_lck);
+ if (!name_already_locked)
+ erts_rwmtx_rlock(name_lck);
else {
ERTS_LC_ASSERT(META_DB_LOCK_FREE()
- || erts_lc_rwmtx_is_rlocked(mtl)
- || erts_lc_rwmtx_is_rwlocked(mtl));
+ || erts_lc_rwmtx_is_rlocked(name_lck)
+ || erts_lc_rwmtx_is_rwlocked(name_lck));
+ name_lck = NULL;
}
tb = NULL;
if (bucket->pu.tb != NULL) {
@@ -806,22 +815,32 @@ DbTable* db_get_table_aux(Process *p,
}
}
}
- if (!meta_already_locked)
- erts_rwmtx_runlock(mtl);
if (tb == NULL) {
+ if (name_lck)
+ erts_rwmtx_runlock(name_lck);
p->fvalue = EXI_ID;
}
}
if (tb) {
+ if (what == DB_READ_TBL_STRUCT) {
+ if (name_lck)
+ erts_rwmtx_runlock(name_lck);
+ return tb;
+ }
+
+ DB_HASH_ADAPT_NUMBER_OF_LOCKS(tb);
db_lock(tb, kind);
+ if (name_lck)
+ erts_rwmtx_runlock(name_lck);
+
#ifdef ETS_DBG_FORCE_TRAP
/*
* The ets_SUITE uses this to verify that all table lookups calls
* can handle a failed TRAP return correctly.
*/
- if (what != DB_READ_TBL_STRUCT && tb->common.dbg_force_trap) {
+ if (tb->common.dbg_force_trap) {
if (!(p->flags & F_DBG_FORCED_TRAP)) {
db_unlock(tb, kind);
tb = NULL;
@@ -835,11 +854,7 @@ DbTable* db_get_table_aux(Process *p,
}
}
#endif
- if (what != DB_READ_TBL_STRUCT
- /* IMPORTANT: the above check is necessary as the status field
- might be in an intermediate state when
- kind==NOLCK_ACCESS */
- && ERTS_UNLIKELY(!(tb->common.status & what))) {
+ if (ERTS_UNLIKELY(!(tb->common.status & what))) {
tb = handle_lacking_permission(p, tb, kind, freason_p);
}
}
@@ -860,15 +875,31 @@ DbTable* db_get_table(Process *p,
return db_get_table_aux(p, id, what, kind, 0, freason_p);
}
-static BIF_RETTYPE db_get_table_or_fail_return(DbTable **tb, /* out */
- Eterm table_id,
- Uint32 what,
- db_lock_kind_t kind,
- Uint bif_ix,
- Process* p)
+static DbTable* db_get_table_or_fail_return(Binary* btid,
+ Uint32 what,
+ db_lock_kind_t kind,
+ Uint bif_ix,
+ Process* p)
{
- DB_GET_TABLE(*tb, table_id, what, kind, bif_ix, NULL, p);
- return THE_NON_VALUE;
+ DbTable* tb = btid2tab(btid);
+ if (!tb) {
+ p->freason = BADARG | EXF_HAS_EXT_INFO;
+ p->fvalue = EXI_ID;
+ }
+ else {
+ /* The lock has to be taken to complete the operation */
+ db_lock(tb, LCK_WRITE);
+ if (!(tb->common.status & what)) {
+ Uint freason;
+ tb = handle_lacking_permission(p, tb, kind, &freason);
+ if (!tb) {
+ BIF_RETTYPE ret = db_bif_fail(p, freason, bif_ix, NULL);
+ ASSERT(ret == THE_NON_VALUE); (void)ret;
+ }
+ }
+ }
+
+ return tb;
}
static int insert_named_tab(Eterm name_atom, DbTable* tb, int have_lock)
@@ -1260,9 +1291,9 @@ bail_out:
case DB_ERROR_UNSPEC:
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
default:
- BIF_ERROR(BIF_P, BADARG);
break;
}
+ BIF_ERROR(BIF_P, BADARG);
}
static BIF_RETTYPE
@@ -1457,9 +1488,9 @@ bail_out:
case DB_ERROR_BADPARAM:
BIF_ERROR(p, BADARG | EXF_HAS_EXT_INFO);
default:
- BIF_ERROR(p, BADARG);
break;
}
+ BIF_ERROR(p, BADARG);
}
/*
@@ -1500,20 +1531,38 @@ BIF_RETTYPE ets_update_counter_4(BIF_ALIST_4)
}
typedef enum {
+ /*
+ * Prepare phase. Done only by the process calling ets:insert/insert_new.
+ * All tuples to insert are allocated and copied without table lock.
+ */
ETS_INSERT_2_LIST_PROCESS_LOCAL,
- ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK,
- ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK_DESTROY,
+
+ /*
+ * Commit phase. May be assisted by other calling processes.
+ * Prepared tuples inserted with table lock.
+ */
ETS_INSERT_2_LIST_GLOBAL
} ets_insert_2_list_status;
-typedef struct {
+typedef struct ets_insert_2_list_info {
ets_insert_2_list_status status;
- BIF_RETTYPE destroy_return_value;
- DbTable* tb;
+ Binary* btid; /* identifies the table between traps */
+ Eterm tid; /* arg1, also used to detect table name change */
+ Eterm list; /* arg2 */
+ DbTable* tb; /* cached tb, does not keep table alive between traps */
void* continuation_state;
- Binary* continuation_res_bin;
+ erts_atomic_t return_value; /* Eterm: 'true', 'false' or THE_NON_VALUE */
} ets_insert_2_list_info;
+static void cancel_trap_continuation(DbTable* tb)
+{
+ ets_insert_2_list_info* ctx = tb->common.continuation_ctx;
+
+ if (ctx) {
+ tb->common.continuation_ctx = NULL;
+ erts_bin_release(&(ERTS_MAGIC_BIN_FROM_DATA(ctx)->binary));
+ }
+}
static ERTS_INLINE BIF_RETTYPE
ets_cret_to_return_value(Process* p, int cret)
@@ -1633,17 +1682,18 @@ static void* ets_insert_2_list_copy_term_list(DbTableMethod* meth,
{
void* db_term_list = NULL;
void *term;
+ void *last_term;
Eterm lst;
for (lst = list; is_list(lst); lst = CDR(list_val(lst))) {
term = meth->db_eterm_to_dbterm(compress,
keypos,
CAR(list_val(lst)));
if (db_term_list != NULL) {
- db_term_list =
- meth->db_dbterm_list_prepend(db_term_list,
- term);
+ last_term =
+ meth->db_dbterm_list_append(last_term, term);
} else {
db_term_list = term;
+ last_term = term;
}
}
@@ -1677,63 +1727,77 @@ static int ets_insert_new_2_dbterm_list_has_member(DbTable* tb, void* db_term_li
}
static void ets_insert_2_list_insert_db_term_list(DbTable* tb,
- void* list)
+ void* db_term_list)
{
- void* lst = list;
+ void* tail = db_term_list;
void* term = NULL;
DbTableMethod* meth = tb->common.meth;
+ int compress = tb->common.compress;
do {
LOCAL_VARIABLE(SWord, consumed_reds);
consumed_reds = 1;
- term = meth->db_dbterm_list_remove_first(&lst);
+ term = meth->db_dbterm_list_remove_first(&tail);
meth->db_put_dbterm(tb, term, 0, &consumed_reds);
YCF_CONSUME_REDS(consumed_reds);
- } while (lst != NULL);
+ } while (tail != NULL);
return;
+
+ YCF_SPECIAL_CODE_START(ON_DESTROY_STATE); {
+ ets_insert_2_list_destroy_copied_dbterms(meth,
+ compress,
+ tail);
+ } YCF_SPECIAL_CODE_END();
+
}
-static void ets_insert_2_list_lock_tbl(Eterm table_id,
- Process* p,
- Uint bif_ix,
- ets_insert_2_list_status on_success_status)
+static int ets_insert_2_list_lock_tbl(Binary *btid,
+ Process* p,
+ Uint bif_ix,
+ ets_insert_2_list_status on_success_status)
{
- BIF_RETTYPE fail_ret;
DbTable* tb;
+
do {
- fail_ret = db_get_table_or_fail_return(&tb,
- table_id,
- DB_WRITE,
- LCK_WRITE,
- bif_ix,
- p);
+ LOCAL_VARIABLE(ets_insert_2_list_info*,ctx);
+ ctx = YCF_GET_EXTRA_CONTEXT();
+ ASSERT(ctx->status != ETS_INSERT_2_LIST_GLOBAL);
+
+ tb = db_get_table_or_fail_return(btid,
+ DB_WRITE,
+ LCK_WRITE,
+ bif_ix,
+ p);
+ ASSERT(ctx->status != ETS_INSERT_2_LIST_GLOBAL);
+
if (tb == NULL) {
- ets_insert_2_list_info *ctx = YCF_GET_EXTRA_CONTEXT();
if (p->freason == TRAP) {
- ctx->status = ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK;
+ YCF_YIELD();
} else {
- ctx->status = ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK_DESTROY;
- ctx->destroy_return_value = fail_ret;
+ return 0;
}
-#ifdef DEBUG
+ }
+ else if (is_atom(ctx->tid) && tb->common.the_name != ctx->tid) {
/*
- * Setting ctx to NULL to avoid that YCF crashes with a
- * pointer to stack error when running a debug
- * build. YCF_GET_EXTRA_CONTEXT() may change between
- * yields as we use stack allocated data for the context
- * before the first yield so it is important that the
- * context is obtained again with YCF_GET_EXTRA_CONTEXT()
- * if a yield might have happened.
+ * The table has been renamed. We have to fail. This named
+ * insert op might otherwise be observable as if it happened
+ * AFTER the table was renamed.
+ *
+ * Note that we are allowed to fail here as long as there is no
+ * atomic name change op from one table to another.
*/
- ctx = NULL;
-#endif
- YCF_YIELD();
- } else {
- ets_insert_2_list_info *ctx = YCF_GET_EXTRA_CONTEXT();
+ p->freason = BADARG | EXF_HAS_EXT_INFO;
+ p->fvalue = EXI_ID;
+ db_unlock(tb, LCK_WRITE);
+ return 0;
+ }
+ else {
ctx->status = on_success_status;
- ASSERT(DB_LOCK_FREE(tb) || erts_lc_rwmtx_is_rwlocked(&tb->common.rwlock));
- ASSERT(!(tb->common.status & DB_DELETE));
}
} while (tb == NULL);
+
+ ERTS_LC_ASSERT(DB_LOCK_FREE(tb) || erts_lc_rwmtx_is_rwlocked(&tb->common.rwlock));
+ ASSERT(!(tb->common.status & (DB_DELETE|DB_BUSY)));
+ return 1;
}
#endif /* YCF_FUNCTIONS */
@@ -1754,13 +1818,14 @@ static ERTS_INLINE int can_insert_without_yield(Uint32 tb_type,
#ifdef YCF_FUNCTIONS
static BIF_RETTYPE ets_insert_2_list(Process* p,
Eterm table_id,
+ Binary* btid,
DbTable *tb,
Eterm list,
int is_insert_new)
{
int cret = DB_ERROR_NONE;
- void* db_term_list = NULL; /* OBS: memory managements depends on that
- db_term_list is initialized to NULL */
+ void* db_term_list = NULL;
+ void* destroy_list = NULL;
DbTableMethod* meth = tb->common.meth;
int compressed = tb->common.compress;
int keypos = tb->common.keypos;
@@ -1778,16 +1843,18 @@ static BIF_RETTYPE ets_insert_2_list(Process* p,
* table. This is necessary to ensure that the correct reason
* for the failure will be available in stack backtrace.
*/
- ets_insert_2_list_lock_tbl(table_id, p, bif_ix, ETS_INSERT_2_LIST_PROCESS_LOCAL);
- db_unlock(tb, LCK_WRITE);
- ERTS_BIF_PREP_ERROR_TRAPPED2(ret, p, BADARG, BIF_TRAP_EXPORT(bif_ix), table_id, list);
- return ret;
+ if (ets_insert_2_list_lock_tbl(btid, p, bif_ix, ETS_INSERT_2_LIST_PROCESS_LOCAL)) {
+ db_unlock(tb, LCK_WRITE);
+ p->freason = BADARG;
+ }
+ return THE_NON_VALUE;
}
if (can_insert_without_yield(tb_type, list_len, YCF_NR_OF_REDS_LEFT())) {
long reds_boost;
/* There is enough reductions left to do the inserts directly
from the heap without yielding */
- ets_insert_2_list_lock_tbl(table_id, p, bif_ix, ETS_INSERT_2_LIST_PROCESS_LOCAL);
+ if (!ets_insert_2_list_lock_tbl(btid, p, bif_ix, ETS_INSERT_2_LIST_PROCESS_LOCAL))
+ return THE_NON_VALUE;
/* Ensure that we will not yield while inserting from heap */
reds_boost = YCF_MAX_NR_OF_REDS - YCF_NR_OF_REDS_LEFT();
YCF_SET_NR_OF_REDS_LEFT(YCF_MAX_NR_OF_REDS);
@@ -1807,44 +1874,46 @@ static BIF_RETTYPE ets_insert_2_list(Process* p,
/* Copy term list from heap so that other processes can help */
db_term_list =
ets_insert_2_list_copy_term_list(meth, compressed, keypos, list);
+ destroy_list = db_term_list;
/* Lock table */
- ets_insert_2_list_lock_tbl(table_id, p, bif_ix, ETS_INSERT_2_LIST_GLOBAL);
- /* The operation must complete after this point */
+ if (!ets_insert_2_list_lock_tbl(btid, p, bif_ix, ETS_INSERT_2_LIST_GLOBAL)) {
+ const Eterm fvalue = p->fvalue;
+ ASSERT(p->freason == (BADARG | EXF_HAS_EXT_INFO));
+
+ destroy_list = NULL;
+ ets_insert_2_list_destroy_copied_dbterms(meth,
+ compressed,
+ db_term_list);
+ /* Restore failure reason as we may have trapped during destroy */
+ p->freason = BADARG | EXF_HAS_EXT_INFO;
+ p->fvalue = fvalue;
+ return THE_NON_VALUE;
+ }
+
if (is_insert_new) {
if (ets_insert_new_2_dbterm_list_has_member(tb, db_term_list)) {
+ destroy_list = NULL;
ets_insert_2_list_destroy_copied_dbterms(meth,
compressed,
db_term_list);
cret = DB_ERROR_NONE_FALSE;
- } else {
+ }
+ else {
+ destroy_list = NULL;
ets_insert_2_list_insert_db_term_list(tb, db_term_list);
}
- } else {
- ets_insert_2_list_insert_db_term_list(tb, db_term_list);
}
- if (tb->common.continuation != NULL) {
- /* Uninstall the continuation from the table struct */
- tb->common.continuation = NULL;
- if (is_insert_new) {
- int* result_ptr =
- ERTS_MAGIC_BIN_DATA(tb->common.continuation_res_bin);
- *result_ptr = cret;
- erts_bin_release(tb->common.continuation_res_bin);
- }
- tb->common.status |= tb->common.type & (DB_PRIVATE|DB_PROTECTED|DB_PUBLIC);
- tb->common.status &= ~DB_BUSY;
- erts_atomic_set_relb(&tb->common.continuation_state, (Sint)NULL);
+ else {
+ destroy_list = NULL;
+ ets_insert_2_list_insert_db_term_list(tb, db_term_list);
}
return ets_cret_to_return_value(NULL, cret);
- /* The following code will be executed if the initiating process
- is killed before an ets_insert_2_list_lock_tbl call has
- succeeded */
YCF_SPECIAL_CODE_START(ON_DESTROY_STATE); {
ets_insert_2_list_destroy_copied_dbterms(meth,
compressed,
- db_term_list);
+ destroy_list);
} YCF_SPECIAL_CODE_END();
}
#endif /* YCF_FUNCTIONS */
@@ -1879,48 +1948,76 @@ static void ets_insert_2_yield_free(void* data, void* ctx)
static int ets_insert_2_list_yield_dtor(Binary* bin)
{
ets_insert_2_list_info* ctx = ERTS_MAGIC_BIN_DATA(bin);
- if (ctx->status != ETS_INSERT_2_LIST_GLOBAL &&
- ctx->continuation_state != NULL) {
- /* The operation has not been committed to the table and has
- not completed*/
+ if (ctx->continuation_state) {
ets_insert_2_list_ycf_gen_destroy(ctx->continuation_state);
}
+ erts_bin_release(ctx->btid);
return 1;
}
-static void ets_insert_2_list_continuation(long *reds_ptr,
- void** state,
- void* extra_context)
+#define ITERATIONS_PER_RED 8
+
+static BIF_RETTYPE
+ets_insert_2_list_continuation(Process* p,
+ ets_insert_2_list_info* ctx)
{
+ long reds = ITERATIONS_PER_RED * ERTS_BIF_REDS_LEFT(p);
+ long init_reds;
+ BIF_RETTYPE ret;
+
+ reds = DBG_RANDOM_REDS(reds, (Uint)ctx);
+ init_reds = reds;
+
+ ERTS_LC_ASSERT(ctx->status != ETS_INSERT_2_LIST_GLOBAL
+ || DB_LOCK_FREE(tb)
+ || erts_lc_rwmtx_is_rwlocked(&ctx->tb->common.rwlock));
+ ASSERT(ctx->continuation_state);
+
#if defined(DEBUG) && defined(ARCH_64)
- ycf_debug_set_stack_start(reds_ptr);
+ ycf_debug_set_stack_start(&reds);
#endif
- ets_insert_2_list_ycf_gen_continue(reds_ptr, state, extra_context);
+ ret = ets_insert_2_list_ycf_gen_continue(&reds,
+ &ctx->continuation_state,
+ ctx);
#if defined(DEBUG) && defined(ARCH_64)
ycf_debug_reset_stack_start();
#endif
-}
-static int db_insert_new_2_res_bin_dtor(Binary *context_bin)
-{
- (void)context_bin;
- return 1;
+ if (ctx->continuation_state == NULL) {
+ if (is_value(ret)) {
+ ASSERT(ret == am_true || ret == am_false);
+ erts_atomic_set_nob(&ctx->return_value, ret);
+ }
+ if (ctx->status == ETS_INSERT_2_LIST_GLOBAL) {
+ DbTableCommon *tb = &ctx->tb->common;
+ if (tb->continuation_ctx) {
+ /* Uninstall the continuation from the table struct */
+ ASSERT(!(tb->status & DB_DELETE));
+ tb->status |= tb->type & (DB_PRIVATE|DB_PROTECTED|DB_PUBLIC);
+ tb->status &= ~DB_BUSY;
+ tb->continuation_ctx = NULL;
+ erts_bin_release(&(ERTS_MAGIC_BIN_FROM_DATA(ctx)->binary));
+ }
+ }
+ }
+ BUMP_REDS(p, (init_reds - reds) / ITERATIONS_PER_RED);
+ return ret;
}
-#define ITERATIONS_PER_RED 8
-
static BIF_RETTYPE ets_insert_2_list_driver(Process* p,
Eterm tid,
Eterm list,
int is_insert_new) {
- const long reds = ITERATIONS_PER_RED * ERTS_BIF_REDS_LEFT(p);
- long nr_of_reductions = DBG_RANDOM_REDS(reds, (Uint)&p);
- const long init_reds = nr_of_reductions;
+#if defined(DEBUG) && defined(ARCH_64)
+ int dbg_ycf_stack_start;
+#endif
ets_insert_2_list_info* ctx = NULL;
- ets_insert_2_list_info ictx;
BIF_RETTYPE ret = THE_NON_VALUE;
Eterm state_mref = list;
Uint bix = (is_insert_new ? BIF_ets_insert_new_2 : BIF_ets_insert_2);
+ ets_insert_2_list_info ictx;
+ int do_trap;
+
if (is_internal_magic_ref(state_mref)) {
Binary* state_bin = erts_magic_ref2bin(state_mref);
if (ERTS_MAGIC_BIN_DESTRUCTOR(state_bin) != ets_insert_2_list_yield_dtor) {
@@ -1930,57 +2027,60 @@ static BIF_RETTYPE ets_insert_2_list_driver(Process* p,
erts_set_gc_state(p, 1);
ctx = ERTS_MAGIC_BIN_DATA(state_bin);
if (ctx->status == ETS_INSERT_2_LIST_GLOBAL) {
- /* An operation that can be helped by other operations is
- handled here */
- Uint freason;
- int cret = DB_ERROR_NONE;
- DbTable* tb;
- /* First check if another process has completed the
- operation without acquiring the lock */
- tb = db_get_table(p, tid, DB_READ_TBL_STRUCT, NOLCK_ACCESS, &freason);
- ASSERT(tb || freason != TRAP);
- if (tb != NULL &&
- (void*)erts_atomic_read_acqb(&tb->common.continuation_state) ==
- ctx->continuation_state) {
- /* The lock has to be taken to complete the operation */
- if (NULL == (tb = db_get_table(p, tid, DB_WRITE, LCK_WRITE, &freason))) {
- if (freason == TRAP){
- erts_set_gc_state(p, 0);
- return db_bif_fail(p, freason, bix, NULL);
- }
- }
- /* Must be done since the db_get_table call did not trap */
- if (tb != NULL) {
+ DbTable* tb = btid2tab(ctx->btid);
+ if (tb) {
+ db_lock(tb, LCK_WRITE);
+ if (ctx != tb->common.continuation_ctx) {
db_unlock(tb, LCK_WRITE);
+ tb = NULL;
}
}
- if (is_insert_new) {
- int* res = ERTS_MAGIC_BIN_DATA(ctx->continuation_res_bin);
- cret = *res;
+ if (!tb) {
+ /*
+ * Operation completed/aborted by someone else.
+ * Note: If insert was successful but table has been deleted,
+ * we still return success. It would be wrong to fail the insert
+ * if someone have seen the result (before the table was deleted).
+ */
+ ret = erts_atomic_read_nob(&ctx->return_value);
+ if (is_value(ret)) {
+ ASSERT(ret == am_true ||
+ (ret == am_false && is_insert_new));
+ return ret;
+ }
+ else {
+ ASSERT(!tb || tb->common.status & DB_DELETE);
+ BIF_ERROR(p, BADARG | EXF_HAS_EXT_INFO);
+ }
}
- return ets_cret_to_return_value(NULL, cret);
- } else {
-#if defined(DEBUG) && defined(ARCH_64)
- ycf_debug_set_stack_start(&nr_of_reductions);
-#endif
- ret = ets_insert_2_list_ycf_gen_continue(&nr_of_reductions,
- &ctx->continuation_state,
- ctx);
-#if defined(DEBUG) && defined(ARCH_64)
- ycf_debug_reset_stack_start();
-#endif
+ ASSERT((tb->common.status & (DB_WRITE|DB_BUSY))
+ == DB_BUSY);
}
+ ret = ets_insert_2_list_continuation(p, ctx);
+ ASSERT(ctx->continuation_state
+ || ret == am_true || ret == am_false || ret == THE_NON_VALUE);
} else {
/* Start call */
+ long reds = ITERATIONS_PER_RED * ERTS_BIF_REDS_LEFT(p);
+ long init_reds;
+
+ reds = DBG_RANDOM_REDS(reds, (Uint)p);
+ init_reds = reds;
+
ictx.continuation_state = NULL;
ictx.status = ETS_INSERT_2_LIST_PROCESS_LOCAL;
+ erts_atomic_init_nob(&ictx.return_value, THE_NON_VALUE);
ictx.tb = NULL;
+ ictx.tid = tid;
+ ictx.list = list;
+ DB_GET_TABLE(ictx.tb, tid, DB_READ_TBL_STRUCT, LCK_NOLOCK_ACCESS, bix,
+ NULL, p);
+ ictx.btid = ictx.tb->common.btid;
ctx = &ictx;
- DB_GET_TABLE(ctx->tb, tid, DB_READ_TBL_STRUCT, NOLCK_ACCESS, bix, NULL, p);
#if defined(DEBUG) && defined(ARCH_64)
- ycf_debug_set_stack_start(&nr_of_reductions);
+ ycf_debug_set_stack_start(&dbg_ycf_stack_start);
#endif
- ret = ets_insert_2_list_ycf_gen_yielding(&nr_of_reductions,
+ ret = ets_insert_2_list_ycf_gen_yielding(&reds,
&ctx->continuation_state,
ctx,
ets_insert_2_yield_alloc,
@@ -1990,12 +2090,16 @@ static BIF_RETTYPE ets_insert_2_list_driver(Process* p,
NULL,
p,
tid,
+ ctx->btid,
ctx->tb,
list,
is_insert_new);
#if defined(DEBUG) && defined(ARCH_64)
ycf_debug_reset_stack_start();
#endif
+ ASSERT(ctx->continuation_state
+ || ret == am_true || ret == am_false || ret == THE_NON_VALUE);
+
if (ctx->continuation_state != NULL) {
Binary* state_bin = erts_create_magic_binary(sizeof(ets_insert_2_list_info),
ets_insert_2_list_yield_dtor);
@@ -2003,40 +2107,37 @@ static BIF_RETTYPE ets_insert_2_list_driver(Process* p,
state_mref = erts_mk_magic_ref(&hp, &MSO(p), state_bin);
ctx = ERTS_MAGIC_BIN_DATA(state_bin);
*ctx = ictx;
+ erts_refc_inc(&ctx->btid->intern.refc, 2);
}
- }
- BUMP_REDS(p, (init_reds - nr_of_reductions) / ITERATIONS_PER_RED);
- if (ctx->status == ETS_INSERT_2_LIST_GLOBAL &&
- ctx->continuation_state != NULL &&
- ctx->tb->common.continuation == NULL) {
- /* Install the continuation in the table structure so other
- threads can help */
- if (is_insert_new) {
- Binary* bin =
- erts_create_magic_binary(sizeof(int),
- db_insert_new_2_res_bin_dtor);
- Eterm* hp = HAlloc(p, ERTS_MAGIC_REF_THING_SIZE);
- erts_mk_magic_ref(&hp, &MSO(p), bin);
- erts_refc_inctest(&bin->intern.refc, 2);
- ctx->tb->common.continuation_res_bin = bin;
- ctx->continuation_res_bin = bin;
+ BUMP_REDS(p, (init_reds - reds) / ITERATIONS_PER_RED);
+ }
+ do_trap = (ctx->continuation_state != NULL);
+ if (do_trap) {
+ if (ctx->status == ETS_INSERT_2_LIST_GLOBAL &&
+ !ctx->tb->common.continuation_ctx) {
+ /* Install the continuation in the table structure so other
+ threads can help */
+ ctx->tb->common.status &= ~(DB_PRIVATE|DB_PROTECTED|DB_PUBLIC);
+ ctx->tb->common.status |= DB_BUSY;
+ ASSERT(ctx != &ictx);
+ erts_refc_inc(&(ERTS_MAGIC_BIN_FROM_DATA(ctx)->binary.intern.refc), 2);
+ ctx->tb->common.continuation_ctx = ctx;
}
- ctx->tb->common.continuation = ets_insert_2_list_continuation;
- ctx->tb->common.status &= ~(DB_PRIVATE|DB_PROTECTED|DB_PUBLIC);
- ctx->tb->common.status |= DB_BUSY;
- erts_atomic_set_relb(&ctx->tb->common.continuation_state,
- (Sint)ctx->continuation_state);
}
- if (ctx->status == ETS_INSERT_2_LIST_FAILED_TO_GET_LOCK_DESTROY) {
- return ctx->destroy_return_value;
+ else if (is_non_value(ret)) {
+ ASSERT(p->freason != TRAP);
+ ERTS_BIF_ERROR_TRAPPED2(p, p->freason, BIF_TRAP_EXPORT(bix),
+ ctx->tid, ctx->list);
}
if (ctx->status == ETS_INSERT_2_LIST_GLOBAL) {
db_unlock(ctx->tb, LCK_WRITE);
}
- if (ctx->continuation_state != NULL) {
+ if (do_trap) {
erts_set_gc_state(p, 0);
BIF_TRAP2(BIF_TRAP_EXPORT(bix), p, tid, state_mref);
}
+
+ ASSERT(ret == am_true || ret == am_false);
return ret;
}
@@ -2168,13 +2269,13 @@ BIF_RETTYPE ets_rename_2(BIF_ALIST_2)
db_unlock(tb, LCK_READ);
BIF_ERROR(BIF_P, BADARG);
}
-
+retry:
(void) meta_name_tab_bucket(BIF_ARG_2, &lck1);
if (is_atom(BIF_ARG_1)) {
old_name = BIF_ARG_1;
named_tab:
- (void) meta_name_tab_bucket(old_name, &lck2);
+ (void)meta_name_tab_bucket(old_name, &lck2);
if (lck1 == lck2)
lck2 = NULL;
else if (lck1 > lck2) {
@@ -2188,15 +2289,17 @@ BIF_RETTYPE ets_rename_2(BIF_ALIST_2)
if (!tb)
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
else {
+ old_name = tb->common.the_name;
if (is_table_named(tb)) {
- old_name = tb->common.the_name;
goto named_tab;
}
+ lck1 = NULL;
lck2 = NULL;
}
}
- erts_rwmtx_rwlock(lck1);
+ if (lck1)
+ erts_rwmtx_rwlock(lck1);
if (lck2)
erts_rwmtx_rwlock(lck2);
@@ -2205,6 +2308,16 @@ BIF_RETTYPE ets_rename_2(BIF_ALIST_2)
goto fail;
if (is_table_named(tb)) {
+ if (tb->common.the_name != old_name) {
+ /* Wow! Racing rename op. Unlock all and retry. */
+ ASSERT(is_not_atom(BIF_ARG_1));
+ if (lck1)
+ erts_rwmtx_rwunlock(lck1);
+ if (lck2)
+ erts_rwmtx_rwunlock(lck2);
+ db_unlock(tb, LCK_WRITE);
+ goto retry;
+ }
if (!insert_named_tab(BIF_ARG_2, tb, 1))
goto badarg;
@@ -2218,7 +2331,8 @@ BIF_RETTYPE ets_rename_2(BIF_ALIST_2)
tb->common.the_name = BIF_ARG_2;
db_unlock(tb, LCK_WRITE);
- erts_rwmtx_rwunlock(lck1);
+ if (lck1)
+ erts_rwmtx_rwunlock(lck1);
if (lck2)
erts_rwmtx_rwunlock(lck2);
BIF_RET(ret);
@@ -2229,7 +2343,8 @@ badarg:
fail:
if (tb)
db_unlock(tb, LCK_WRITE);
- erts_rwmtx_rwunlock(lck1);
+ if (lck1)
+ erts_rwmtx_rwunlock(lck1);
if (lck2)
erts_rwmtx_rwunlock(lck2);
@@ -2254,8 +2369,11 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
Sint keypos;
int is_named, is_compressed;
int is_fine_locked, frequent_read;
+ int number_of_locks;
int is_decentralized_counters;
int is_decentralized_counters_option;
+ int is_explicit_lock_granularity;
+ int is_write_concurrency_auto;
int cret;
DbTableMethod* meth;
@@ -2276,6 +2394,9 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
heir = am_none;
heir_data = (UWord) am_undefined;
is_compressed = erts_ets_always_compress;
+ number_of_locks = -1;
+ is_explicit_lock_granularity = 0;
+ is_write_concurrency_auto = 0;
list = BIF_ARG_2;
while(is_list(list)) {
@@ -2301,10 +2422,41 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
keypos = signed_val(tp[2]);
}
else if (tp[1] == am_write_concurrency) {
- if (tp[2] == am_true) {
+ if (tp[2] == am_auto) {
+ is_decentralized_counters = 1;
+ is_write_concurrency_auto = 1;
is_fine_locked = 1;
+ is_explicit_lock_granularity = 0;
+ number_of_locks = -1;
+ } else if (tp[2] == am_true) {
+ if (!(status & DB_ORDERED_SET)) {
+ is_decentralized_counters = 0;
+ }
+ is_fine_locked = 1;
+ is_explicit_lock_granularity = 0;
+ is_write_concurrency_auto = 0;
+ number_of_locks = -1;
} else if (tp[2] == am_false) {
is_fine_locked = 0;
+ is_explicit_lock_granularity = 0;
+ is_write_concurrency_auto = 0;
+ number_of_locks = -1;
+ } else if (is_tuple(tp[2])) {
+ Eterm *stp = tuple_val(tp[2]);
+ Sint number_of_locks_param;
+ if (arityval(stp[0]) == 2 &&
+ stp[1] == am_debug_hash_fixed_number_of_locks &&
+ term_to_Sint(stp[2], &number_of_locks_param) &&
+ number_of_locks_param >= DB_WRITE_CONCURRENCY_MIN_LOCKS &&
+ number_of_locks_param <= DB_WRITE_CONCURRENCY_MAX_LOCKS) {
+
+ is_decentralized_counters = 1;
+ is_fine_locked = 1;
+ is_explicit_lock_granularity = 1;
+ is_write_concurrency_auto = 0;
+ number_of_locks = number_of_locks_param;
+
+ } else break;
} else break;
if (DB_LOCK_FREE(NULL))
is_fine_locked = 0;
@@ -2368,15 +2520,43 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
status |= DB_CA_ORDERED_SET;
status &= ~(DB_SET | DB_BAG | DB_DUPLICATE_BAG | DB_ORDERED_SET);
status |= DB_FINE_LOCKED;
+ if (is_explicit_lock_granularity) {
+ /*
+ * The hidden debug option to explicitly set the number of locks,
+ * currently doesn't make sense for ordered_set.
+ */
+ BIF_ERROR(BIF_P, BADARG);
+ } else if (is_write_concurrency_auto) {
+ /*
+ * ordered_set tables that are configured with
+ * {write_concurrency, true} or {write_concurrency, auto}
+ * currently get the same implementation but we record
+ * that the auto option was used anyway so that
+ * ets:info(T, write_concurrency) can return auto when the
+ * table has been configured with {write_concurrency,
+ * auto}.
+ */
+ status |= DB_FINE_LOCKED_AUTO;
+ }
}
else if (IS_HASH_TABLE(status)) {
meth = &db_hash;
if (is_fine_locked && !(status & DB_PRIVATE)) {
status |= DB_FINE_LOCKED;
- }
+ if (is_explicit_lock_granularity) {
+ status |= DB_EXPLICIT_LOCK_GRANULARITY;
+ } else if (is_write_concurrency_auto) {
+ status |= DB_FINE_LOCKED_AUTO;
+ }
+ } else {
+ number_of_locks = -1;
+ }
}
else if (IS_TREE_TABLE(status)) {
meth = &db_tree;
+ if (is_explicit_lock_granularity) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
}
else {
BIF_ERROR(BIF_P, BADARG);
@@ -2386,7 +2566,7 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
status |= DB_FREQ_READ;
/* we create table outside any table lock
- * and take the unusal cost of destroy table if it
+ * and take the unusual cost of destroy table if it
* fails to find a slot
*/
{
@@ -2409,8 +2589,7 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
tb->common.status = status;
tb->common.type = status;
/* Note, 'type' is *read only* from now on... */
- tb->common.continuation = NULL;
- erts_atomic_set_nob(&tb->common.continuation_state, (Sint)NULL);
+ tb->common.continuation_ctx = NULL;
erts_refc_init(&tb->common.fix_count, 0);
db_init_lock(tb, status & (DB_FINE_LOCKED|DB_FREQ_READ));
tb->common.keypos = keypos;
@@ -2423,6 +2602,10 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
tb->common.dbg_force_trap = erts_ets_dbg_force_trap;
#endif
+ if (IS_HASH_TABLE(status)) {
+ DbTableHash* hash_db = (DbTableHash*) tb;
+ hash_db->nlocks = number_of_locks;
+ }
cret = meth->db_create(BIF_P, tb);
ASSERT(cret == DB_ERROR_NONE); (void)cret;
@@ -2445,7 +2628,8 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
tb->common.meth->db_free_empty_table(tb);
db_unlock(tb,LCK_WRITE);
table_dec_refc(tb, 0);
- BIF_ERROR(BIF_P, BADARG);
+ BIF_P->fvalue = EXI_ALREADY_EXISTS;
+ BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}
BIF_P->flags |= F_USING_DB; /* So we can remove tb if p dies */
@@ -2476,10 +2660,10 @@ BIF_RETTYPE ets_whereis_1(BIF_ALIST_1)
if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_INFO, LCK_READ, &freason)) == NULL) {
if (BIF_P->fvalue == EXI_ID) {
BIF_RET(am_undefined);
- } else {
- //ToDo: Could we avoid this
- return db_bif_fail(BIF_P, freason, BIF_ets_whereis_1, NULL);
}
+ ASSERT(BIF_P->fvalue == EXI_TYPE);
+ /* ToDo: Could we avoid this for freason==TRAP */
+ return db_bif_fail(BIF_P, freason, BIF_ets_whereis_1, NULL);
}
res = make_tid(BIF_P, tb);
@@ -2605,8 +2789,9 @@ BIF_RETTYPE ets_delete_1(BIF_ALIST_1)
* Clear all access bits to prevent any ets operation to access the
* table while it is being deleted.
*/
- tb->common.status &= ~(DB_PROTECTED|DB_PUBLIC|DB_PRIVATE);
+ tb->common.status &= ~(DB_PROTECTED | DB_PUBLIC | DB_PRIVATE | DB_BUSY);
tb->common.status |= DB_DELETE;
+ cancel_trap_continuation(tb);
if (tb->common.owner != BIF_P->common.id) {
@@ -2832,15 +3017,23 @@ BIF_RETTYPE ets_internal_delete_all_2(BIF_ALIST_2)
* the table and instead pitch in deleting objects
* (in delete_all_objects_continue) and then trap to self.
*/
+ Eterm tid;
ASSERT((tb->common.status & (DB_PRIVATE|DB_PROTECTED|DB_PUBLIC))
==
(tb->common.type & (DB_PRIVATE|DB_PROTECTED|DB_PUBLIC)));
tb->common.status &= ~(DB_PRIVATE|DB_PROTECTED|DB_PUBLIC);
tb->common.status |= DB_BUSY;
db_unlock(tb, LCK_WRITE);
+
+ if (is_atom(BIF_ARG_1)) {
+ ASSERT(is_table_named(tb));
+ tid = make_tid(BIF_P, tb);
+ } else {
+ tid = BIF_ARG_1;
+ }
BUMP_ALL_REDS(BIF_P);
BIF_TRAP2(BIF_TRAP_EXPORT(BIF_ets_internal_delete_all_2), BIF_P,
- BIF_ARG_1, nitems_holder);
+ tid, nitems_holder);
}
else {
/* Done, no trapping needed */
@@ -3104,7 +3297,7 @@ ets_all_reply(ErtsSchedulerData *esdp, ErtsEtsAllReq **reqpp,
* - save_sched_table() inserts at end of circular list.
*
* - This function scans from the end so we know that
- * the amount of tables to scan wont grow even if we
+ * the amount of tables to scan won't grow even if we
* yield.
*
* - remove_sched_table() updates the table we yielded
@@ -3999,13 +4192,13 @@ BIF_RETTYPE ets_info_1(BIF_ALIST_1)
table = BIF_ARG_1;
}
if ((tb = db_get_table(BIF_P, table, DB_INFO, LCK_READ, &freason)) == NULL) {
- if (BIF_P->fvalue == EXI_TYPE) {
- /* TRAP or invalid table identifier (not atom or magic reference). */
- return db_bif_fail(BIF_P, freason, BIF_ets_info_1, NULL);
- } else {
+ if (BIF_P->fvalue == EXI_ID) {
/* The table no longer exists. */
BIF_RET(am_undefined);
}
+ /* TRAP or invalid table identifier (not atom or magic reference). */
+ ASSERT(BIF_P->fvalue == EXI_TYPE);
+ return db_bif_fail(BIF_P, freason, BIF_ets_info_1, NULL);
}
/* If/when we implement lockless private tables:
@@ -4059,7 +4252,10 @@ BIF_RETTYPE ets_info_1(BIF_ALIST_1)
Sint words = (Sint) ((memory + sizeof(Sint) - 1) / sizeof(Sint));
results[i] = erts_make_integer(words, BIF_P);
} else {
- results[i] = table_info(BIF_P, tb, fields[i]);
+ ErtsHeapFactory hf;
+ erts_factory_proc_init(&hf, BIF_P);
+ results[i] = table_info(&hf, tb, fields[i]);
+ erts_factory_close(&hf);
ASSERT(is_value(results[i]));
}
}
@@ -4106,13 +4302,12 @@ BIF_RETTYPE ets_info_2(BIF_ALIST_2)
BIF_TRAP1(ets_info_binary_trap, BIF_P, BIF_ARG_1);
if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_INFO, LCK_READ, &freason)) == NULL) {
- if (BIF_P->fvalue == EXI_TYPE) {
- /* TRAP or invalid table identifier (not atom or magic reference). */
- return db_bif_fail(BIF_P, freason, BIF_ets_info_2, NULL);
- } else {
- /* The table no longer exists. */
+ if (BIF_P->fvalue == EXI_ID) {
BIF_RET(am_undefined);
}
+ /* TRAP or invalid table identifier (not atom or magic reference). */
+ ASSERT(BIF_P->fvalue == EXI_TYPE);
+ return db_bif_fail(BIF_P, freason, BIF_ets_info_2, NULL);
}
if (BIF_ARG_2 == am_size || BIF_ARG_2 == am_memory) {
ErtsFlxCtrSnapshotResult res =
@@ -4131,7 +4326,10 @@ BIF_RETTYPE ets_info_2(BIF_ALIST_2)
ret = erts_make_integer(r, BIF_P);
}
} else {
- ret = table_info(BIF_P, tb, BIF_ARG_2);
+ ErtsHeapFactory hf;
+ erts_factory_proc_init(&hf, BIF_P);
+ ret = table_info(&hf, tb, BIF_ARG_2);
+ erts_factory_close(&hf);
}
db_unlock(tb, LCK_READ);
if (is_non_value(ret)) {
@@ -4360,7 +4558,7 @@ void init_db(ErtsDbSpinCount db_spin_count)
}
/*
- * We don't have ony hard limit for number of tables anymore, .
+ * We don't have only hard limit for number of tables anymore, .
* but we use 'db_max_tabs' to determine size of name hash table.
*/
meta_name_tab_mask = (((Uint) 1)<<bits) - 1;
@@ -4637,8 +4835,10 @@ erts_db_process_exiting(Process *c_p, ErtsProcLocks c_p_locks, void **yield_stat
break;
}
/* Clear all access bits. */
- tb->common.status &= ~(DB_PROTECTED | DB_PUBLIC | DB_PRIVATE);
+ tb->common.status &= ~(DB_PROTECTED | DB_PUBLIC | DB_PRIVATE
+ | DB_BUSY);
tb->common.status |= DB_DELETE;
+ cancel_trap_continuation(tb);
if (is_table_named(tb))
remove_named_tab(tb, 0);
@@ -4978,7 +5178,7 @@ static SWord free_table_continue(Process *p, DbTable *tb, SWord reds)
struct fixing_procs_info_ctx
{
- Process* p;
+ ErtsHeapFactory* hf;
Eterm list;
};
@@ -4988,21 +5188,23 @@ static int fixing_procs_info_op(DbFixation* fix, void* vctx, Sint reds)
Eterm* hp;
Eterm tpl;
- hp = HAllocX(ctx->p, 5, 100);
+ hp = erts_produce_heap(ctx->hf, 5, 100);
tpl = TUPLE2(hp, fix->procs.p->common.id, make_small(fix->counter));
hp += 3;
ctx->list = CONS(hp, tpl, ctx->list);
return 1;
}
-static Eterm table_info(Process* p, DbTable* tb, Eterm What)
+static Eterm table_info(ErtsHeapFactory *hf, DbTable* tb, Eterm What)
{
Eterm ret = THE_NON_VALUE;
int use_monotonic;
+ ASSERT(hf != NULL);
+
if (What == am_size) {
Uint size = (Uint) (DB_GET_APPROX_NITEMS(tb));
- ret = erts_make_integer(size, p);
+ ret = erts_make_integer_fact(size, hf);
} else if (What == am_type) {
if (tb->common.status & DB_SET) {
ret = am_set;
@@ -5021,7 +5223,7 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
+ sizeof(Uint)
- 1)
/ sizeof(Uint));
- ret = erts_make_integer(words, p);
+ ret = erts_make_integer_fact(words, hf);
} else if (What == am_owner) {
ret = tb->common.owner;
} else if (What == am_heir) {
@@ -5034,7 +5236,20 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
else if (tb->common.status & DB_PUBLIC)
ret = am_public;
} else if (What == am_write_concurrency) {
- ret = tb->common.status & DB_FINE_LOCKED ? am_true : am_false;
+ if ((tb->common.status & DB_FINE_LOCKED) &&
+ (tb->common.status & (DB_SET | DB_BAG | DB_DUPLICATE_BAG)) &&
+ (tb->common.status & DB_EXPLICIT_LOCK_GRANULARITY)) {
+ Eterm* hp = erts_produce_heap(hf, 3, 0);
+ ret = make_tuple(hp);
+ *hp++ = make_arityval(2);
+ *hp++ = am_debug_hash_fixed_number_of_locks;
+ *hp++ = erts_make_integer_fact(tb->hash.nlocks, hf);
+ } else if ((tb->common.status & DB_FINE_LOCKED) &&
+ (tb->common.status & DB_FINE_LOCKED_AUTO)) {
+ ret = am_auto;
+ } else {
+ ret = tb->common.status & DB_FINE_LOCKED ? am_true : am_false;
+ }
} else if (What == am_read_concurrency) {
ret = tb->common.status & DB_FREQ_READ ? am_true : am_false;
} else if (What == am_name) {
@@ -5048,7 +5263,7 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
} else if (What == am_compressed) {
ret = tb->common.compress ? am_true : am_false;
} else if (What == am_id) {
- ret = make_tid(p, tb);
+ ret = make_tid_fact(hf, tb);
} else if (What == am_decentralized_counters) {
ret = tb->common.counters.is_decentralized ? am_true : am_false;
}
@@ -5088,13 +5303,13 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
mtime = 0;
need += 4;
}
- ctx.p = p;
+ ctx.hf = hf;
ctx.list = NIL;
fixing_procs_rbt_foreach(tb->common.fixing_procs,
fixing_procs_info_op,
&ctx);
- hp = HAlloc(p, need);
+ hp = erts_produce_heap(hf, need, 0);
if (use_monotonic)
time = (IS_SSMALL(mtime)
? make_small(mtime)
@@ -5121,7 +5336,7 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
Eterm* hp;
db_calc_stats_hash(&tb->hash, &stats);
- hp = HAlloc(p, 1 + 7 + FLOAT_SIZE_OBJECT*3);
+ hp = erts_produce_heap(hf, 1 + 8 + FLOAT_SIZE_OBJECT*3, 0);
f.fd = stats.avg_chain_len;
avg = make_float(hp);
PUT_DOUBLE(f, hp);
@@ -5136,18 +5351,19 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
std_dev_exp = make_float(hp);
PUT_DOUBLE(f, hp);
hp += FLOAT_SIZE_OBJECT;
- ret = TUPLE7(hp, make_small(erts_atomic_read_nob(&tb->hash.nactive)),
+ ret = TUPLE8(hp, make_small(erts_atomic_read_nob(&tb->hash.nactive)),
avg, std_dev_real, std_dev_exp,
make_small(stats.min_chain_len),
make_small(stats.max_chain_len),
- make_small(stats.kept_items));
+ make_small(stats.kept_items),
+ make_small(tb->hash.nlocks));
}
else if (IS_CATREE_TABLE(tb->common.status)) {
DbCATreeStats stats;
Eterm* hp;
db_calc_stats_catree(&tb->catree, &stats);
- hp = HAlloc(p, 4);
+ hp = erts_produce_heap(hf, 4, 0);
ret = TUPLE3(hp,
make_small(stats.route_nodes),
make_small(stats.base_nodes),
@@ -5163,12 +5379,14 @@ static Eterm table_info(Process* p, DbTable* tb, Eterm What)
static void print_table(fmtfn_t to, void *to_arg, int show, DbTable* tb)
{
Eterm tid;
- Eterm heap[ERTS_MAGIC_REF_THING_SIZE];
+ ErtsHeapFactory hf;
+ erts_factory_tmp_init(&hf, NULL, 0, ERTS_ALC_T_TMP);
if (is_table_named(tb)) {
tid = tb->common.the_name;
} else {
ErlOffHeap oh;
+ Eterm *heap = erts_produce_heap(&hf, ERTS_MAGIC_REF_THING_SIZE, 0);
ERTS_INIT_OFF_HEAP(&oh);
write_magic_ref_thing(heap, &oh, (ErtsMagicBinary *) tb->common.btid);
tid = make_internal_ref(heap);
@@ -5185,11 +5403,12 @@ static void print_table(fmtfn_t to, void *to_arg, int show, DbTable* tb)
+ sizeof(Uint)
- 1)
/ sizeof(Uint)));
- erts_print(to, to_arg, "Type: %T\n", table_info(NULL, tb, am_type));
- erts_print(to, to_arg, "Protection: %T\n", table_info(NULL, tb, am_protection));
- erts_print(to, to_arg, "Compressed: %T\n", table_info(NULL, tb, am_compressed));
- erts_print(to, to_arg, "Write Concurrency: %T\n", table_info(NULL, tb, am_write_concurrency));
- erts_print(to, to_arg, "Read Concurrency: %T\n", table_info(NULL, tb, am_read_concurrency));
+ erts_print(to, to_arg, "Type: %T\n", table_info(&hf, tb, am_type));
+ erts_print(to, to_arg, "Protection: %T\n", table_info(&hf, tb, am_protection));
+ erts_print(to, to_arg, "Compressed: %T\n", table_info(&hf, tb, am_compressed));
+ erts_print(to, to_arg, "Write Concurrency: %T\n", table_info(&hf, tb, am_write_concurrency));
+ erts_print(to, to_arg, "Read Concurrency: %T\n", table_info(&hf, tb, am_read_concurrency));
+ erts_factory_close(&hf);
}
typedef struct {
diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h
index 9f21728ca1..19379dcdbe 100644
--- a/erts/emulator/beam/erl_db.h
+++ b/erts/emulator/beam/erl_db.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@ union db_table {
/*TT*/
};
-#define DB_DEF_MAX_TABS 8192 /* Superseeded by environment variable
+#define DB_DEF_MAX_TABS 8192 /* Superseded by environment variable
"ERL_MAX_ETS_TABLES" */
#define ERL_MAX_ETS_TABLES_ENV "ERL_MAX_ETS_TABLES"
@@ -173,12 +173,15 @@ do { \
ERTS_GLB_INLINE void *erts_db_alloc(ErtsAlcType_t type,
DbTable *tab,
- Uint size);
+ Uint size) ERTS_ATTR_MALLOC_US(3);
ERTS_GLB_INLINE void *erts_db_alloc_fnf(ErtsAlcType_t type,
DbTable *tab,
- Uint size);
-ERTS_GLB_INLINE void *erts_db_alloc_nt(ErtsAlcType_t type, Uint size);
-ERTS_GLB_INLINE void *erts_db_alloc_fnf_nt(ErtsAlcType_t type, Uint size);
+ Uint size) ERTS_ATTR_MALLOC_US(3);
+ERTS_GLB_INLINE void*
+erts_db_alloc_nt(ErtsAlcType_t type, Uint size) ERTS_ATTR_MALLOC_US(2);
+
+ERTS_GLB_INLINE void*
+erts_db_alloc_fnf_nt(ErtsAlcType_t type, Uint size) ERTS_ATTR_MALLOC_US(2);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
diff --git a/erts/emulator/beam/erl_db_catree.c b/erts/emulator/beam/erl_db_catree.c
index b5033abc68..700003438c 100644
--- a/erts/emulator/beam/erl_db_catree.c
+++ b/erts/emulator/beam/erl_db_catree.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB and Kjell Winblad 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB and Kjell Winblad 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -79,6 +79,7 @@
#include "erl_db_catree.h"
#include "erl_db_tree.h"
#include "erl_db_tree_util.h"
+#include "erl_global_literals.h"
#ifdef DEBUG
# define IF_DEBUG(X) X
@@ -219,7 +220,7 @@ DbTableMethod db_catree =
db_lookup_dbterm_catree,
db_finalize_dbterm_catree,
db_eterm_to_dbterm_tree_common,
- db_dbterm_list_prepend_tree_common,
+ db_dbterm_list_append_tree_common,
db_dbterm_list_remove_first_tree_common,
db_put_dbterm_catree,
db_free_dbterm_tree_common,
@@ -873,7 +874,8 @@ Eterm copy_route_key(DbRouteKey* dst, Eterm key, Uint key_size)
dst->oh = tmp_offheap.first;
}
else {
- ASSERT(is_immed(key));
+ ASSERT(is_immed(key) ||
+ key == ERTS_GLOBAL_LIT_EMPTY_TUPLE);
dst->term = key;
dst->oh = NULL;
}
@@ -1032,6 +1034,7 @@ static DbTableCATreeNode *create_base_node(DbTableCATree *tb,
"erl_db_catree_base_node",
NIL,
ERTS_LOCK_FLAGS_CATEGORY_DB);
+ ERTS_DB_ALC_MEM_UPDATE_((DbTable *) tb, 0, erts_rwmtx_size(&p->u.base.lock));
BASE_NODE_STAT_SET(p, ((tb->common.status & DB_CATREE_FORCE_SPLIT)
? INT_MAX : 0));
p->u.base.is_valid = 1;
@@ -1090,7 +1093,7 @@ static void do_free_base_node(void* vptr)
static void free_catree_base_node(DbTableCATree* tb, DbTableCATreeNode* p)
{
ASSERT(p->is_base_node);
- ERTS_DB_ALC_MEM_UPDATE_(tb, sizeof_base_node(), 0);
+ ERTS_DB_ALC_MEM_UPDATE_(tb, sizeof_base_node() + erts_rwmtx_size(&p->u.base.lock), 0);
do_free_base_node(p);
}
@@ -1202,7 +1205,7 @@ static void join_catree(DbTableCATree *tb,
DbTableCATreeNode *neighbor_parent;
ASSERT(thiz->is_base_node);
- if (parent == NULL) {
+ if (parent == NULL || ERTS_IS_CRASH_DUMPING) {
BASE_NODE_STAT_SET(thiz, 0);
wunlock_base_node(thiz);
return;
@@ -1257,7 +1260,7 @@ static void join_catree(DbTableCATree *tb,
neighbor_parent = leftmost_route_node(GET_RIGHT(parent));
}
}
- } else { /* Symetric case */
+ } else { /* Symmetric case */
ASSERT(GET_RIGHT(parent) == thiz);
neighbor = rightmost_base_node(GET_LEFT_ACQB(parent));
if (try_wlock_base_node(&neighbor->u.base)) {
@@ -1332,11 +1335,13 @@ static void join_catree(DbTableCATree *tb,
thiz,
&thiz->u.base.free_item,
sizeof_base_node());
+ ERTS_DB_ALC_MEM_UPDATE_(tb, erts_rwmtx_size(&thiz->u.base.lock), 0);
erts_schedule_db_free(&tb->common,
do_free_base_node,
neighbor,
&neighbor->u.base.free_item,
sizeof_base_node());
+ ERTS_DB_ALC_MEM_UPDATE_(tb, erts_rwmtx_size(&neighbor->u.base.lock), 0);
}
static void split_catree(DbTableCATree *tb,
@@ -1348,7 +1353,7 @@ static void split_catree(DbTableCATree *tb,
DbTableCATreeNode* ERTS_RESTRICT new_right;
DbTableCATreeNode* ERTS_RESTRICT new_route;
- if (less_than_two_elements(base->u.base.root)) {
+ if (less_than_two_elements(base->u.base.root) || ERTS_IS_CRASH_DUMPING) {
if (!(tb->common.status & DB_CATREE_FORCE_SPLIT))
BASE_NODE_STAT_SET(base, 0);
wunlock_base_node(base);
@@ -1381,6 +1386,7 @@ static void split_catree(DbTableCATree *tb,
base,
&base->u.base.free_item,
sizeof_base_node());
+ ERTS_DB_ALC_MEM_UPDATE_(tb, erts_rwmtx_size(&base->u.base.lock), 0);
}
}
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 6eb7bde1b4..13aaf00c80 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,57 +87,71 @@
#define IS_DECENTRALIZED_CTRS(DB) ((DB)->common.counters.is_decentralized)
-#define NITEMS_ESTIMATE_FROM_LCK_CTR(LCK_CTR_P) \
- (LCK_CTR_P->nitems <= 0 ? 1: LCK_CTR_P->nitems)
-
-#define NITEMS_ESTIMATE(DB, LCK_CTR, HASH) \
- (IS_DECENTRALIZED_CTRS(DB) ? \
- (DB_HASH_LOCK_CNT * \
- (LCK_CTR != NULL ? \
- NITEMS_ESTIMATE_FROM_LCK_CTR(LCK_CTR) : \
- NITEMS_ESTIMATE_FROM_LCK_CTR(GET_LOCK_AND_CTR(DB, HASH)))) : \
- erts_flxctr_read_centralized(&(DB)->common.counters, \
- ERTS_DB_TABLE_NITEMS_COUNTER_ID))
-
-#define ADD_NITEMS(DB, LCK_CTR, HASH, TO_ADD) \
- do { \
- if (IS_DECENTRALIZED_CTRS(DB)) { \
- if (LCK_CTR != NULL) { \
- LCK_CTR->nitems += TO_ADD; \
- } else { \
- GET_LOCK_AND_CTR(DB,HASH)->nitems += TO_ADD; \
- } \
- } \
- erts_flxctr_add(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID, TO_ADD); \
- } while(0)
-#define INC_NITEMS(DB, LCK_CTR, HASH) \
- do { \
- if (IS_DECENTRALIZED_CTRS(DB)) { \
- if (LCK_CTR != NULL) { \
- LCK_CTR->nitems++; \
- } else { \
- GET_LOCK_AND_CTR(DB,HASH)->nitems++; \
- } \
- } \
- erts_flxctr_inc(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID); \
- } while(0)
-#define DEC_NITEMS(DB, LCK_CTR, HASH) \
- do { \
- if (IS_DECENTRALIZED_CTRS(DB)) { \
- if (LCK_CTR != NULL) { \
- LCK_CTR->nitems--; \
- } else { \
- GET_LOCK_AND_CTR(DB,HASH)->nitems--; \
- } \
- } \
- erts_flxctr_dec(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID); \
- } while(0)
+/*
+ * To get reasonable estimate of table load for grow/shrink decisions
+ * we limit the number of lock structs that hold (used) item counters.
+ * To simplify, this is also the minimum number of locks.
+ */
+#define NLOCKS_WITH_ITEM_COUNTERS 64
+
+#define LCK_AUTO_MAX_LOCKS 8192
+#define LCK_AUTO_MIN_LOCKS NLOCKS_WITH_ITEM_COUNTERS
+#define LCK_AUTO_DEFAULT_NUMBER_OF_LOCKS LCK_AUTO_MIN_LOCKS
+#define LCK_AUTO_MAX_LOCKS_FREQ_READ_RW_LOCKS 128
+
+
+static ERTS_INLINE int
+NITEMS_ESTIMATE(DbTableHash* DB, DbTableHashLockAndCounter* LCK_CTR, HashValue HASH)
+{
+ if (IS_DECENTRALIZED_CTRS(DB)) {
+ Sint nitems = erts_atomic_read_nob(&DB->locks[HASH % NLOCKS_WITH_ITEM_COUNTERS].u.lck_ctr.nitems);
+ return nitems * NLOCKS_WITH_ITEM_COUNTERS;
+ }
+ else {
+ return erts_flxctr_read_centralized(&(DB)->common.counters,
+ ERTS_DB_TABLE_NITEMS_COUNTER_ID);
+ }
+}
+
+static ERTS_INLINE void
+ADD_NITEMS(DbTableHash* DB, DbTableHashLockAndCounter* LCK_CTR, HashValue HASH,
+ Sint to_add)
+{
+ if (IS_DECENTRALIZED_CTRS(DB)) {
+ erts_atomic_add_nob(&DB->locks[HASH % NLOCKS_WITH_ITEM_COUNTERS].u.lck_ctr.nitems,
+ to_add);
+ }
+ erts_flxctr_add(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID,
+ to_add);
+}
+
+
+static ERTS_INLINE void
+INC_NITEMS(DbTableHash* DB, DbTableHashLockAndCounter* LCK_CTR, HashValue HASH)
+{
+ if (IS_DECENTRALIZED_CTRS(DB)) {
+ erts_atomic_inc_nob(&DB->locks[HASH % NLOCKS_WITH_ITEM_COUNTERS].u.lck_ctr.nitems);
+ }
+ erts_flxctr_inc(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID);
+}
+
+static ERTS_INLINE void
+DEC_NITEMS(DbTableHash* DB, DbTableHashLockAndCounter* LCK_CTR, HashValue HASH)
+{
+ if (IS_DECENTRALIZED_CTRS(DB)) {
+ erts_atomic_dec_nob(&DB->locks[HASH % NLOCKS_WITH_ITEM_COUNTERS].u.lck_ctr.nitems);
+ }
+ erts_flxctr_dec(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID);
+}
+
#define RESET_NITEMS(DB) \
erts_flxctr_reset(&(DB)->common.counters, ERTS_DB_TABLE_NITEMS_COUNTER_ID)
#define GROW_LIMIT(NACTIVE) ((NACTIVE)*1)
#define SHRINK_LIMIT(TB) erts_atomic_read_nob(&(TB)->shrink_limit)
+#define IS_POW2(x) ((x) && !((x) & ((x)-1)))
+
/*
** We want the first mandatory segment to be small (to reduce minimal footprint)
** and larger extra segments (to reduce number of alloc/free calls).
@@ -264,11 +278,125 @@ static ERTS_INLINE int is_pseudo_deleted(HashDbTerm* p)
((is_atom(term) ? (atom_tab(atom_val(term))->slot.bucket.hvalue) : \
make_internal_hash(term, 0)) & MAX_HASH_MASK)
-# define DB_HASH_LOCK_MASK (DB_HASH_LOCK_CNT-1)
-# define GET_LOCK(tb,hval) (&(tb)->locks->lck_vec[(hval) & DB_HASH_LOCK_MASK].lck_ctr.lck)
-# define GET_LOCK_AND_CTR(tb,hval) (&(tb)->locks->lck_vec[(hval) & DB_HASH_LOCK_MASK].lck_ctr)
+# define GET_LOCK_MASK(NUMBER_OF_LOCKS) ((NUMBER_OF_LOCKS)-1)
+
+# define GET_LOCK(tb,hval) (&(tb)->locks[(hval) & GET_LOCK_MASK(tb->nlocks)].u.lck_ctr.lck)
+# define GET_LOCK_AND_CTR(tb,hval) (&(tb)->locks[(hval) & GET_LOCK_MASK(tb->nlocks)].u.lck_ctr)
# define GET_LOCK_MAYBE(tb,hval) ((tb)->common.is_thread_safe ? NULL : GET_LOCK(tb,hval))
+# define LCK_AUTO_CONTENDED_STAT_CONTRIB 100
+# define LCK_AUTO_UNCONTENDED_STAT_CONTRIB -1
+# define LCK_AUTO_GROW_LIMIT 1000
+# define LCK_AUTO_SHRINK_LIMIT -10000000
+
+static void calc_shrink_limit(DbTableHash* tb);
+
+void db_hash_adapt_number_of_locks(DbTable* tb) {
+ db_hash_lock_array_resize_state current_state;
+ DbTableHash* tbl;
+ int new_number_of_locks;
+
+ ASSERT(IS_HASH_WITH_AUTO_TABLE(tb->common.type));
+
+ tbl = &tb->hash;
+ erts_rwmtx_rwlock(&tb->common.rwlock);
+ current_state = erts_atomic_read_nob(&tb->hash.lock_array_resize_state);
+ if (current_state == DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL) {
+ /* Another thread did the lock array resize job before us */
+ erts_rwmtx_rwunlock(&tb->common.rwlock);
+ return;
+ }
+ if (IS_FIXED(tb)) {
+ /*
+ Do not do any adaptation if the table is fixed as this can
+ lead to missed slots when traversing over the table.
+
+ The lock statistics is kept as it is likely that we want to
+ adapt when the table is not fixed any more.
+ */
+ erts_atomic_set_nob(&tbl->lock_array_resize_state,
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL);
+ erts_rwmtx_rwunlock(&tb->common.rwlock);
+ return;
+ }
+ if (current_state == DB_HASH_LOCK_ARRAY_RESIZE_STATUS_GROW &&
+ erts_atomic_read_nob(&tbl->nactive) >= (2*tbl->nlocks)) {
+ new_number_of_locks = 2*tbl->nlocks;
+ } else if (current_state == DB_HASH_LOCK_ARRAY_RESIZE_STATUS_SHRINK) {
+ new_number_of_locks = tbl->nlocks / 2;
+ } else {
+ /*
+ Do not do any adaptation if the number of active buckets is
+ smaller than the resulting number of locks.
+
+ We do not want to make the table unnecessary large just to
+ potentially reduce contention.
+ */
+ int i;
+ for (i = 0; i < tbl->nlocks; i++) {
+ tbl->locks[i].u.lck_ctr.lck_stat = 0;
+ }
+ erts_atomic_set_nob(&tbl->lock_array_resize_state,
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL);
+ erts_rwmtx_rwunlock(&tb->common.rwlock);
+ return;
+ }
+ {
+ erts_rwmtx_opt_t rwmtx_opt = ERTS_RWMTX_OPT_DEFAULT_INITER;
+ int i;
+ DbTableHashFineLockSlot* old_locks = tbl->locks;
+ Uint old_number_of_locks = tbl->nlocks;
+ ASSERT(new_number_of_locks != 0);
+ tbl->nlocks = new_number_of_locks;
+ if (tb->common.type & DB_FREQ_READ &&
+ new_number_of_locks <= LCK_AUTO_MAX_LOCKS_FREQ_READ_RW_LOCKS) {
+ rwmtx_opt.type = ERTS_RWMTX_TYPE_FREQUENT_READ;
+ }
+ if (erts_ets_rwmtx_spin_count >= 0) {
+ rwmtx_opt.main_spincount = erts_ets_rwmtx_spin_count;
+ }
+ tbl->locks = (DbTableHashFineLockSlot*) erts_db_alloc(ERTS_ALC_T_DB_SEG,
+ (DbTable *) tb,
+ sizeof(DbTableHashFineLockSlot) * tbl->nlocks);
+ for (i=0; i < tbl->nlocks; i++) {
+ erts_aint_t nitems;
+ erts_rwmtx_init_opt(GET_LOCK(tbl, i), &rwmtx_opt,
+ "db_hash_slot", tb->common.the_name, ERTS_LOCK_FLAGS_CATEGORY_DB);
+ ERTS_DB_ALC_MEM_UPDATE_(tb, 0, erts_rwmtx_size(GET_LOCK(tbl,i)));
+ nitems = (i >= NLOCKS_WITH_ITEM_COUNTERS ? 0 :
+ erts_atomic_read_nob(&old_locks[i].u.lck_ctr.nitems));
+ erts_atomic_init_nob(&tbl->locks[i].u.lck_ctr.nitems, nitems);
+ tbl->locks[i].u.lck_ctr.lck_stat = 0;
+ }
+/* #define HARD_DEBUG_ITEM_CNT_LOCK_CHANGE 1 */
+#ifdef HARD_DEBUG_ITEM_CNT_LOCK_CHANGE
+ {
+ Sint total_old = 0;
+ Sint total_new = 0;
+ int i;
+ for (i=0; i < old_number_of_locks; i++) {
+ total_old += old_locks[i].u.lck_ctr.nitems;
+ }
+ for (i=0; i < tbl->nlocks; i++) {
+ total_new += tbl->locks[i].u.lck_ctr.nitems;
+ }
+ /* erts_printf("%ld %ld %d\n", total_new, total_old, tbl->nlocks); */
+ ERTS_ASSERT(total_new == total_old);
+ }
+#endif
+
+ calc_shrink_limit(tbl);
+
+ erts_atomic_set_nob(&tbl->lock_array_resize_state, DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL);
+ erts_rwmtx_rwunlock(&tb->common.rwlock);
+ for (i = 0; i < old_number_of_locks; i++) {
+ ERTS_DB_ALC_MEM_UPDATE_(tb, erts_rwmtx_size(&old_locks[i].u.lck_ctr.lck), 0);
+ erts_rwmtx_destroy(&old_locks[i].u.lck_ctr.lck);
+ }
+ erts_db_free(ERTS_ALC_T_DB_SEG, tb, old_locks, sizeof(DbTableHashFineLockSlot) * old_number_of_locks);
+ }
+}
+
/* Fine grained read lock */
static ERTS_INLINE erts_rwmtx_t* RLOCK_HASH(DbTableHash* tb, HashValue hval)
{
@@ -281,16 +409,38 @@ static ERTS_INLINE erts_rwmtx_t* RLOCK_HASH(DbTableHash* tb, HashValue hval)
return lck;
}
}
-/* Fine grained write lock */
-static ERTS_INLINE erts_rwmtx_t* WLOCK_HASH(DbTableHash* tb, HashValue hval)
+
+static void
+wlock_after_failed_trylock(DbTableHash* tb, DbTableHashLockAndCounter* lock)
{
- if (tb->common.is_thread_safe) {
- return NULL;
- } else {
- erts_rwmtx_t* lck = GET_LOCK(tb,hval);
- ASSERT(tb->common.type & DB_FINE_LOCKED);
- erts_rwmtx_rwlock(lck);
- return lck;
+ erts_rwmtx_rwlock(&lock->lck);
+ lock->lck_stat += LCK_AUTO_CONTENDED_STAT_CONTRIB;
+ if (lock->lck_stat > LCK_AUTO_GROW_LIMIT) {
+ /*
+ * Do not do any adaptation if the table is
+ * fixed as this can lead to missed slots when
+ * traversing over the table.
+ */
+ if (!IS_FIXED(tb)) {
+ if (tb->nlocks < LCK_AUTO_MAX_LOCKS &&
+ (DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL ==
+ erts_atomic_read_nob(&tb->lock_array_resize_state))) {
+ /*
+ * Trigger lock array increase later when we
+ * can take the table lock
+ */
+ erts_atomic_set_nob(&tb->lock_array_resize_state,
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_GROW);
+ }
+ else {
+ /*
+ * The lock statistics is kept if the table is
+ * fixed as it is likely that we want to adapt
+ * when the table is not fixed any more.
+ */
+ lock->lck_stat = 0;
+ }
+ }
}
}
@@ -301,11 +451,48 @@ DbTableHashLockAndCounter* WLOCK_HASH_GET_LCK_AND_CTR(DbTableHash* tb, HashValue
if (tb->common.is_thread_safe) {
return NULL;
} else {
- DbTableHashLockAndCounter* lck_ctr = GET_LOCK_AND_CTR(tb,hval);
ASSERT(tb->common.type & DB_FINE_LOCKED);
- erts_rwmtx_rwlock(&lck_ctr->lck);
- return lck_ctr;
+ if (tb->common.type & DB_FINE_LOCKED_AUTO) {
+ DbTableHashLockAndCounter* lck_couter = GET_LOCK_AND_CTR(tb, hval);
+ if (EBUSY == erts_rwmtx_tryrwlock(&lck_couter->lck)) {
+ wlock_after_failed_trylock(tb, lck_couter);
+ } else {
+ lck_couter->lck_stat += LCK_AUTO_UNCONTENDED_STAT_CONTRIB;
+ if (lck_couter->lck_stat < LCK_AUTO_SHRINK_LIMIT
+ && !IS_FIXED(tb)) {
+ if(tb->nlocks > LCK_AUTO_MIN_LOCKS &&
+ (DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL ==
+ erts_atomic_read_nob(&tb->lock_array_resize_state))) {
+ /*
+ Trigger lock array increase later when we
+ can take the table lock
+ */
+ erts_atomic_set_nob(&tb->lock_array_resize_state,
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_SHRINK);
+ } else {
+ lck_couter->lck_stat = 0;
+ }
+ }
+ }
+ return lck_couter;
+ } else {
+ DbTableHashLockAndCounter* lck_ctr = GET_LOCK_AND_CTR(tb,hval);
+ ASSERT(tb->common.type & DB_FINE_LOCKED);
+ erts_rwmtx_rwlock(&lck_ctr->lck);
+ return lck_ctr;
+ }
+ }
+}
+
+/* Fine grained write lock */
+static ERTS_INLINE erts_rwmtx_t* WLOCK_HASH(DbTableHash* tb, HashValue hval)
+{
+ DbTableHashLockAndCounter* lck_cntr =
+ WLOCK_HASH_GET_LCK_AND_CTR(tb, hval);
+ if (lck_cntr == NULL) {
+ return NULL;
}
+ return &lck_cntr->lck;
}
static ERTS_INLINE void RUNLOCK_HASH(erts_rwmtx_t* lck)
@@ -349,10 +536,17 @@ static ERTS_INLINE void WUNLOCK_HASH_LCK_CTR(DbTableHashLockAndCounter* lck_ctr)
static ERTS_INLINE Sint next_slot(DbTableHash* tb, Uint ix,
erts_rwmtx_t** lck_ptr)
{
- ix += DB_HASH_LOCK_CNT;
+ /*
+ * To minimize locking ops, we jump to next bucket using same lock.
+ * In case of {write_concurrency,auto} this is safe as 'nlocks' does not
+ * change as long as table is fixed, which all single call select/match do.
+ * Unfixed next,prev and select/1 calls are also "safe" in the sence that
+ * we will seize correct locks as 'nlocks' will not change during the calls.
+ */
+ ix += tb->nlocks;
if (ix < NACTIVE(tb)) return ix;
RUNLOCK_HASH(*lck_ptr);
- ix = (ix + 1) & DB_HASH_LOCK_MASK;
+ ix = (ix + 1) & GET_LOCK_MASK(tb->nlocks);
if (ix != 0) *lck_ptr = RLOCK_HASH(tb,ix);
return ix;
}
@@ -360,10 +554,10 @@ static ERTS_INLINE Sint next_slot(DbTableHash* tb, Uint ix,
static ERTS_INLINE Sint next_slot_w(DbTableHash* tb, Uint ix,
erts_rwmtx_t** lck_ptr)
{
- ix += DB_HASH_LOCK_CNT;
+ ix += tb->nlocks;
if (ix < NACTIVE(tb)) return ix;
WUNLOCK_HASH(*lck_ptr);
- ix = (ix + 1) & DB_HASH_LOCK_MASK;
+ ix = (ix + 1) & GET_LOCK_MASK(tb->nlocks);
if (ix != 0) *lck_ptr = WLOCK_HASH(tb,ix);
return ix;
}
@@ -439,7 +633,7 @@ typedef int ExtraMatchValidatorF(int keypos, Eterm match, Eterm guard, Eterm bod
** Forward decl's (static functions)
*/
static struct ext_segtab* alloc_ext_segtab(DbTableHash* tb, unsigned seg_ix);
-static void alloc_seg(DbTableHash *tb);
+static void alloc_seg(DbTableHash *tb, int activate_new_seg);
static int free_seg(DbTableHash *tb);
static HashDbTerm* next_live(DbTableHash *tb, Uint *iptr, erts_rwmtx_t** lck_ptr,
HashDbTerm *list);
@@ -532,7 +726,7 @@ db_lookup_dbterm_hash(Process *p, DbTable *tbl, Eterm key, Eterm obj,
static void
db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle);
static void* db_eterm_to_dbterm_hash(int compress, int keypos, Eterm obj);
-static void* db_dbterm_list_prepend_hash(void* list, void* db_term);
+static void* db_dbterm_list_append_hash(void* last_term, void* db_term);
static void* db_dbterm_list_remove_first_hash(void** list);
static int db_put_dbterm_hash(DbTable* tb,
void* obj,
@@ -672,7 +866,7 @@ DbTableMethod db_hash =
db_lookup_dbterm_hash,
db_finalize_dbterm_hash,
db_eterm_to_dbterm_hash,
- db_dbterm_list_prepend_hash,
+ db_dbterm_list_append_hash,
db_dbterm_list_remove_first_hash,
db_put_dbterm_hash,
db_free_dbterm_hash,
@@ -807,28 +1001,72 @@ int db_create_hash(Process *p, DbTable *tbl)
sys_memset(tb->first_segtab[0], 0, SIZEOF_SEGMENT(FIRST_SEGSZ));
erts_atomic_init_nob(&tb->is_resizing, 0);
- if (tb->common.type & DB_FINE_LOCKED) {
- erts_rwmtx_opt_t rwmtx_opt = ERTS_RWMTX_OPT_DEFAULT_INITER;
- int i;
+ erts_atomic_init_nob(&tb->lock_array_resize_state,
+ (erts_aint_t)DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL);
+ if (!(tb->common.type & DB_FINE_LOCKED)) {
+ /*
+ The number of locks needs to be set even if fine grained
+ locking is not used as this variable is used as increment
+ when iterating over the table.
+ */
+ tb->nlocks = 1;
+ tb->locks = NULL;
+ }
+ else {
+ erts_rwmtx_opt_t rwmtx_opt = ERTS_RWMTX_OPT_DEFAULT_INITER;
+ int i;
+
+ if (tb->common.type & DB_FINE_LOCKED_AUTO) {
+ tb->nlocks = LCK_AUTO_DEFAULT_NUMBER_OF_LOCKS;
+ }
+ else {
+ if (tb->nlocks < 1) {
+ tb->nlocks = DB_HASH_LOCK_CNT;
+ }
+ /*
+ * nlocks needs to be a power of two so we round down to
+ * nearest power of two
+ */
+ tb->nlocks = 1 << (erts_fit_in_bits_int64(tb->nlocks)-1);
+ if (tb->nlocks < NLOCKS_WITH_ITEM_COUNTERS) {
+ tb->nlocks = NLOCKS_WITH_ITEM_COUNTERS;
+ }
+ }
+
+ /*
+ The table needs to be at least as big as the number of locks
+ so we expand until this properly is satisfied.
+ */
+ while (tb->nlocks > tb->nslots) {
+ alloc_seg(tb, 1);
+ }
+
if (tb->common.type & DB_FREQ_READ)
rwmtx_opt.type = ERTS_RWMTX_TYPE_FREQUENT_READ;
if (erts_ets_rwmtx_spin_count >= 0)
rwmtx_opt.main_spincount = erts_ets_rwmtx_spin_count;
- tb->locks = (DbTableHashFineLocks*) erts_db_alloc(ERTS_ALC_T_DB_SEG, /* Other type maybe? */
- (DbTable *) tb,
- sizeof(DbTableHashFineLocks));
- for (i=0; i<DB_HASH_LOCK_CNT; ++i) {
- erts_rwmtx_init_opt(&tb->locks->lck_vec[i].lck_ctr.lck, &rwmtx_opt,
+ tb->locks = (DbTableHashFineLockSlot*) erts_db_alloc(ERTS_ALC_T_DB_SEG, /* Other type maybe? */
+ (DbTable *) tb,
+ sizeof(DbTableHashFineLockSlot) * tb->nlocks);
+ for (i=0; i<tb->nlocks; ++i) {
+ erts_rwmtx_init_opt(
+ GET_LOCK(tb,i), &rwmtx_opt,
"db_hash_slot", tb->common.the_name, ERTS_LOCK_FLAGS_CATEGORY_DB);
- tb->locks->lck_vec[i].lck_ctr.nitems = 0;
+ ERTS_DB_ALC_MEM_UPDATE_(tb, 0, erts_rwmtx_size(GET_LOCK(tb,i)));
+ erts_atomic_init_nob(&tb->locks[i].u.lck_ctr.nitems, 0);
+ tb->locks[i].u.lck_ctr.lck_stat = 0;
}
- /* This important property is needed to guarantee the two buckets
- * involved in a grow/shrink operation it protected by the same lock:
- */
- ASSERT(erts_atomic_read_nob(&tb->nactive) % DB_HASH_LOCK_CNT == 0);
- }
- else { /* coarse locking */
- tb->locks = NULL;
+ /*
+ * These properties are needed to guarantee that the buckets
+ * involved in a grow/shrink operation it protected by the
+ * same lock:
+ */
+ ASSERT((erts_atomic_read_nob(&tb->szm) + 1) % tb->nlocks == 0);
+ ASSERT(tb->nlocks <= erts_atomic_read_nob(&tb->nactive));
+ ASSERT(erts_atomic_read_nob(&tb->nactive) <= tb->nslots);
+ ASSERT(tb->nslots <= (erts_atomic_read_nob(&tb->szm) + 1));
+ ASSERT(IS_POW2(tb->nlocks));
+ ASSERT(IS_POW2(erts_atomic_read_nob(&tb->szm) + 1));
}
ERTS_THR_MEMORY_BARRIER;
return DB_ERROR_NONE;
@@ -1697,7 +1935,8 @@ static int match_traverse_continue(traverse_context_t* ctx,
}
lck = ctx->on_lock_hash(tb, slot_ix);
- if (slot_ix >= NACTIVE(tb)) { /* Is this possible? */
+ if (slot_ix >= NACTIVE(tb)) {
+ /* Is this possible? Yes, for ets:select/1 without safe_fixtable */
ctx->on_unlock_hash(lck);
*ret = NIL;
ret_value = DB_ERROR_BADPARAM;
@@ -2354,9 +2593,14 @@ static Sint get_nitems_from_locks_or_counter(DbTableHash* tb)
if (IS_DECENTRALIZED_CTRS(tb)) {
int i;
Sint total = 0;
- for (i=0; i < DB_HASH_LOCK_CNT; ++i) {
- total += tb->locks->lck_vec[i].lck_ctr.nitems;
+ for (i=0; i < NLOCKS_WITH_ITEM_COUNTERS; ++i) {
+ total += erts_atomic_read_nob(&tb->locks[i].u.lck_ctr.nitems);
+ }
+#ifdef DEBUG
+ for ( ; i < tb->nlocks; ++i) {
+ ASSERT(erts_atomic_read_nob(&tb->locks[i].u.lck_ctr.nitems) == 0);
}
+#endif
return total;
} else {
return erts_flxctr_read_centralized(&tb->common.counters,
@@ -2728,7 +2972,7 @@ static SWord db_mark_all_deleted_hash(DbTable *tbl, SWord reds)
if (i < NACTIVE(tb)) {
/* Yield */
fixdel->slot = i;
- fixdel->all = 0;
+ fixdel->all = 1;
fixdel->trap = 1;
return -1;
}
@@ -2837,15 +3081,16 @@ static SWord db_free_table_continue_hash(DbTable *tbl, SWord reds)
}
if (tb->locks != NULL) {
int i;
- for (i=0; i<DB_HASH_LOCK_CNT; ++i) {
- erts_rwmtx_destroy(GET_LOCK(tb,i));
+ for (i=0; i<tb->nlocks; ++i) {
+ ERTS_DB_ALC_MEM_UPDATE_(tb, erts_rwmtx_size(GET_LOCK(tb,i)), 0);
+ erts_rwmtx_destroy(GET_LOCK(tb,i));
}
erts_db_free(ERTS_ALC_T_DB_SEG, (DbTable *)tb,
- (void*)tb->locks, sizeof(DbTableHashFineLocks));
+ (void*)tb->locks, tb->nlocks * sizeof(DbTableHashFineLockSlot));
tb->locks = NULL;
}
ASSERT(erts_flxctr_is_snapshot_ongoing(&tb->common.counters) ||
- ((sizeof(DbTable) +
+ ((sizeof(DbTable) + (!DB_LOCK_FREE(tb) ? erts_rwmtx_size(&tb->common.rwlock) : 0) +
erts_flxctr_nr_of_allocated_bytes(&tb->common.counters)) ==
erts_flxctr_read_approx(&tb->common.counters,
ERTS_DB_TABLE_MEM_COUNTER_ID)));
@@ -3046,7 +3291,7 @@ static void calc_shrink_limit(DbTableHash* tb)
*/
/* square of z-score 95% confidence */
/* const double z2 = 1.96*1.96; */
- /* Estimated propotion used buckets */
+ /* Estimated proportion used buckets */
/* const double p = 0.5; */
/* margin of error */
/* const double moe = 0.1; */
@@ -3058,13 +3303,13 @@ static void calc_shrink_limit(DbTableHash* tb)
/* const double d = n*x / (x + n - 1) + 1; */
/* printf("Cochran_formula=%f size=%d mod_with_size=%f\n", x, n, d); */
/* } */
- const int needed_slots = 100 * DB_HASH_LOCK_CNT;
+ const int needed_slots = 100 * NLOCKS_WITH_ITEM_COUNTERS;
if (tb->nslots < needed_slots) {
sample_size_is_enough = 0;
}
}
- if (sample_size_is_enough && tb->nslots >= (FIRST_SEGSZ + 2*EXT_SEGSZ)) {
+ if (sample_size_is_enough && tb->nslots >= MAX(tb->nlocks + EXT_SEGSZ, (FIRST_SEGSZ + 2*EXT_SEGSZ))) {
/*
* Start shrink when the sample size is big enough for
* decentralized counters if decentralized counters are used
@@ -3092,7 +3337,7 @@ static void calc_shrink_limit(DbTableHash* tb)
/* Extend table with one new segment
*/
-static void alloc_seg(DbTableHash *tb)
+static void alloc_seg(DbTableHash *tb, int activate_buckets)
{
int seg_ix = SLOT_IX_TO_SEG_IX(tb->nslots);
struct segment** segtab;
@@ -3117,6 +3362,18 @@ static void alloc_seg(DbTableHash *tb)
}
#endif
tb->nslots += EXT_SEGSZ;
+ if (activate_buckets) {
+ erts_aint_t nactive_before = erts_atomic_read_nob(&tb->nactive);
+ erts_aint_t nactive_now = nactive_before + EXT_SEGSZ;
+ erts_aint_t floor_2_mult = 1 << (erts_fit_in_bits_int64(nactive_now)-1);
+ if (floor_2_mult != nactive_now) {
+ erts_atomic_set_nob(&tb->szm, (floor_2_mult << 1) - 1);
+ } else {
+ erts_atomic_set_nob(&tb->szm, floor_2_mult - 1);
+ }
+ sys_memset(segtab[seg_ix], 0, SIZEOF_SEGMENT(EXT_SEGSZ));
+ erts_atomic_set_nob(&tb->nactive, nactive_now);
+ }
calc_shrink_limit(tb);
}
@@ -3341,7 +3598,7 @@ static void grow(DbTableHash* tb, int nitems)
if (nactive == tb->nslots) {
/* Time to get a new segment */
ASSERT(((nactive-FIRST_SEGSZ) & EXT_SEGSZ_MASK) == 0);
- alloc_seg(tb);
+ alloc_seg(tb, 0);
}
ASSERT(nactive < tb->nslots);
@@ -3751,6 +4008,12 @@ void db_calc_stats_hash(DbTableHash* tb, DbHashStats* stats)
int ix;
int len;
+ if (tb->nslots < NACTIVE(tb)) {
+ ASSERT(ERTS_IS_CRASH_DUMPING);
+ sys_memzero(stats, sizeof(*stats));
+ return;
+ }
+
stats->min_chain_len = INT_MAX;
stats->max_chain_len = 0;
ix = 0;
@@ -3771,7 +4034,7 @@ void db_calc_stats_hash(DbTableHash* tb, DbHashStats* stats)
stats->avg_chain_len = (float)sum / NACTIVE(tb);
stats->std_dev_chain_len = sqrt((sq_sum - stats->avg_chain_len*sum) / NACTIVE(tb));
/* Expected standard deviation from a good uniform hash function,
- ie binomial distribution (not taking the linear hashing into acount) */
+ ie binomial distribution (not taking the linear hashing into account) */
stats->std_dev_expected = sqrt(stats->avg_chain_len * (1 - 1.0/NACTIVE(tb)));
stats->kept_items = kept_items;
}
@@ -3907,11 +4170,11 @@ static void* db_eterm_to_dbterm_hash(int compress, int keypos, Eterm obj)
return term;
}
-static void* db_dbterm_list_prepend_hash(void* list, void* db_term)
+static void* db_dbterm_list_append_hash(void* last_term, void* db_term)
{
- HashDbTerm* l = list;
+ HashDbTerm* l = last_term;
HashDbTerm* t = db_term;
- t->next = l;
+ l->next = t;
return t;
}
@@ -3963,8 +4226,8 @@ void erts_lcnt_enable_db_hash_lock_count(DbTableHash *tb, int enable) {
return;
}
- for(i = 0; i < DB_HASH_LOCK_CNT; i++) {
- erts_lcnt_ref_t *ref = &tb->locks->lck_vec[i].lck_ctr.lck.lcnt;
+ for (i = 0; i < tb->nlocks; i++) {
+ erts_lcnt_ref_t *ref = &tb->locks[i].u.lck_ctr.lck.lcnt;
if(enable) {
erts_lcnt_install_new_lock_info(ref, "db_hash_slot", tb->common.the_name,
diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h
index 830dc77114..974715f5d2 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,8 +25,11 @@
typedef struct fixed_deletion {
UWord slot : sizeof(UWord)*8 - 2;
- UWord all : 1;
+
+ /* Used by delete_all_objects: */
+ UWord all : 1; /* marks [0 -> slot] */
UWord trap : 1;
+
struct fixed_deletion *next;
} FixedDeletion;
@@ -54,20 +57,21 @@ typedef struct hash_db_term {
#endif
typedef struct DbTableHashLockAndCounter {
- Sint nitems;
+ erts_atomic_t nitems;
+ Sint lck_stat;
erts_rwmtx_t lck;
} DbTableHashLockAndCounter;
-typedef struct db_table_hash_fine_locks {
+typedef struct db_table_hash_fine_lock_slot {
union {
DbTableHashLockAndCounter lck_ctr;
- byte _cache_line_alignment[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(erts_rwmtx_t))];
- }lck_vec[DB_HASH_LOCK_CNT];
-} DbTableHashFineLocks;
+ byte _cache_line_alignment[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(DbTableHashLockAndCounter))];
+ } u;
+} DbTableHashFineLockSlot;
typedef struct db_table_hash {
DbTableCommon common;
-
+ erts_atomic_t lock_array_resize_state;
/* szm, nactive, shrink_limit are write-protected by is_resizing or table write lock */
erts_atomic_t szm; /* current size mask. */
erts_atomic_t nactive; /* Number of "active" slots */
@@ -77,16 +81,32 @@ typedef struct db_table_hash {
struct segment* first_segtab[1];
/* SMP: nslots and nsegs are protected by is_resizing or table write lock */
+ int nlocks; /* Needs to be smaller or equal to nactive */
int nslots; /* Total number of slots */
int nsegs; /* Size of segment table */
/* List of slots where elements have been deleted while table was fixed */
erts_atomic_t fixdel; /* (FixedDeletion*) */
erts_atomic_t is_resizing; /* grow/shrink in progress */
- DbTableHashFineLocks* locks;
+ DbTableHashFineLockSlot* locks;
} DbTableHash;
-
+typedef enum {
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL = 0,
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_GROW = 1,
+ DB_HASH_LOCK_ARRAY_RESIZE_STATUS_SHRINK = 2
+} db_hash_lock_array_resize_state;
+
+/* To adapt number of locks if hash table with {write_concurrency, auto} */
+void db_hash_adapt_number_of_locks(DbTable* tb);
+#define DB_HASH_ADAPT_NUMBER_OF_LOCKS(TB) \
+ do { \
+ if (IS_HASH_WITH_AUTO_TABLE(TB->common.type) \
+ && (erts_atomic_read_nob(&tb->hash.lock_array_resize_state) \
+ != DB_HASH_LOCK_ARRAY_RESIZE_STATUS_NORMAL)) { \
+ db_hash_adapt_number_of_locks(tb); \
+ } \
+ }while(0)
/*
** Function prototypes, looks the same (except the suffix) for all
** table types. The process is always an [in out] parameter.
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index a439b974a7..61125b94b2 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -519,7 +519,7 @@ DbTableMethod db_tree =
db_lookup_dbterm_tree,
db_finalize_dbterm_tree,
db_eterm_to_dbterm_tree_common,
- db_dbterm_list_prepend_tree_common,
+ db_dbterm_list_append_tree_common,
db_dbterm_list_remove_first_tree_common,
db_put_dbterm_tree,
db_free_dbterm_tree_common,
@@ -2467,9 +2467,11 @@ static SWord db_free_table_continue_tree(DbTable *tbl, SWord reds)
ASSERT(erts_flxctr_is_snapshot_ongoing(&tb->common.counters) ||
((APPROX_MEM_CONSUMED(tb)
== (sizeof(DbTable) +
+ (!DB_LOCK_FREE(tb) ? erts_rwmtx_size(&tb->common.rwlock) : 0) +
erts_flxctr_nr_of_allocated_bytes(&tb->common.counters))) ||
(APPROX_MEM_CONSUMED(tb)
== (sizeof(DbTable) +
+ (!DB_LOCK_FREE(tb) ? erts_rwmtx_size(&tb->common.rwlock) : 0) +
sizeof(DbFixation) +
erts_flxctr_nr_of_allocated_bytes(&tb->common.counters)))));
}
@@ -3097,7 +3099,7 @@ static TreeDbTerm *find_next(DbTableCommon *tb, TreeDbTerm *root,
for (;;) {
PUSH_NODE(stack, this);
if (( c = cmp_key(tb,key,this) ) > 0) {
- if (this->right == NULL) /* We are at the previos
+ if (this->right == NULL) /* We are at the previous
and the element does
not exist */
break;
@@ -3531,11 +3533,11 @@ void* db_eterm_to_dbterm_tree_common(int compress, int keypos, Eterm obj)
return term;
}
-void* db_dbterm_list_prepend_tree_common(void *list, void *db_term)
+void* db_dbterm_list_append_tree_common(void *last_term, void *db_term)
{
- TreeDbTerm* l = list;
+ TreeDbTerm* l = last_term;
TreeDbTerm* t = db_term;
- t->left = l;
+ l->left = t;
return t;
}
@@ -4273,7 +4275,7 @@ static void check_slot_pos(DbTableTree *tb)
return;
t = traverse_until(tb->root, &pos, tb->stack.slot);
if (t != tb->stack.array[tb->stack.pos - 1]) {
- erts_fprintf(stderr, "Slot position does not correspont with stack, "
+ erts_fprintf(stderr, "Slot position does not correspond with stack, "
"element position %d is really 0x%08X, when stack says "
"it's 0x%08X\n", tb->stack.slot, t,
tb->stack.array[tb->stack.pos - 1]);
diff --git a/erts/emulator/beam/erl_db_tree_util.h b/erts/emulator/beam/erl_db_tree_util.h
index 75c82003b2..08d55e3373 100644
--- a/erts/emulator/beam/erl_db_tree_util.h
+++ b/erts/emulator/beam/erl_db_tree_util.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -172,7 +172,7 @@ void db_finalize_dbterm_tree_common(int cret,
TreeDbTerm **root,
DbTableTree *stack_container);
void* db_eterm_to_dbterm_tree_common(int compress, int keypos, Eterm obj);
-void* db_dbterm_list_prepend_tree_common(void* list, void* db_term);
+void* db_dbterm_list_append_tree_common(void* last_term, void* db_term);
void* db_dbterm_list_remove_first_tree_common(void **list);
int db_put_dbterm_tree_common(DbTableCommon *tb, TreeDbTerm **root, TreeDbTerm *value_to_insert,
int key_clash_fail, DbTableTree *stack_container);
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 8bace68d0f..8243ac1a73 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -39,6 +39,7 @@
#include "erl_map.h"
#include "erl_thr_progress.h"
#include "erl_proc_sig_queue.h"
+#include "erl_global_literals.h"
#include "erl_db_util.h"
@@ -292,7 +293,8 @@ typedef enum {
matchSilent,
matchSetSeqTokenFake,
matchTrace2,
- matchTrace3
+ matchTrace3,
+ matchCallerLine,
} MatchOps;
/*
@@ -676,6 +678,24 @@ static DMCGuardBif guard_tab[] =
DBIF_ALL
},
{
+ am_byte_size,
+ &byte_size_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_binary_part,
+ &binary_part_2,
+ 2,
+ DBIF_ALL
+ },
+ {
+ am_binary_part,
+ &binary_part_3,
+ 3,
+ DBIF_ALL
+ },
+ {
am_tl,
&tl_1,
1,
@@ -1143,14 +1163,18 @@ Binary *db_match_set_compile(Process *p, Eterm matchexpr,
if (l2 != NIL) {
goto error;
}
- hp = HAlloc(p, n + 1);
- t = make_tuple(hp);
- *hp++ = make_arityval((Uint) n);
- l2 = tp[1];
- while (n--) {
- *hp++ = CAR(list_val(l2));
- l2 = CDR(list_val(l2));
- }
+ if (n == 0) {
+ t = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ hp = HAlloc(p, n + 1);
+ t = make_tuple(hp);
+ *hp++ = make_arityval((Uint) n);
+ l2 = tp[1];
+ while (n--) {
+ *hp++ = CAR(list_val(l2));
+ l2 = CDR(list_val(l2));
+ }
+ }
}
matches[i] = t;
guards[i] = tp[2];
@@ -1430,14 +1454,18 @@ static Eterm db_match_set_lint(Process *p, Eterm matchexpr, Uint flags)
goto done;
}
- hp = HAlloc(p, n + 1);
- t = make_tuple(hp);
- *hp++ = make_arityval((Uint) n);
- l2 = tp[1];
- while (n--) {
- *hp++ = CAR(list_val(l2));
- l2 = CDR(list_val(l2));
- }
+ if (n == 0) {
+ t = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ hp = HAlloc(p, n + 1);
+ t = make_tuple(hp);
+ *hp++ = make_arityval((Uint) n);
+ l2 = tp[1];
+ while (n--) {
+ *hp++ = CAR(list_val(l2));
+ l2 = CDR(list_val(l2));
+ }
+ }
}
matches[i] = t;
guards[i] = tp[2];
@@ -1902,7 +1930,7 @@ restart:
** stack ---> + +
** ..........
** +-------------+
- ** The stack is expected to grow towards *higher* adresses.
+ ** The stack is expected to grow towards *higher* addresses.
** A special case is when the match expression is a single binding
** (i.e '$1').
*/
@@ -2014,6 +2042,7 @@ Eterm db_prog_match(Process *c_p,
Eterm *esp;
MatchVariable* variables;
const ErtsCodeMFA *cp;
+ FunctionInfo fi;
const UWord *pc = prog->text;
Eterm *ehp;
Eterm ret;
@@ -2295,13 +2324,18 @@ restart:
break;
case matchMkTuple:
n = *pc++;
- ehp = HAllocX(build_proc, n+1, HEAP_XTRA);
- t = make_tuple(ehp);
- *ehp++ = make_arityval(n);
- while (n--) {
- *ehp++ = *--esp;
- }
- *esp++ = t;
+ if (n == 0) {
+ t = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ *esp++ = t;
+ } else {
+ ehp = HAllocX(build_proc, n+1, HEAP_XTRA);
+ t = make_tuple(ehp);
+ *ehp++ = make_arityval(n);
+ while (n--) {
+ *ehp++ = *--esp;
+ }
+ *esp++ = t;
+ }
break;
case matchMkFlatMap:
n = *pc++;
@@ -2348,9 +2382,13 @@ restart:
erts_factory_proc_init(&factory, build_proc);
/* build flat structure */
- hp = erts_produce_heap(&factory, 3 + 1 + (2 * n), 0);
- keys = make_tuple(hp);
- *hp++ = make_arityval(n);
+ hp = erts_produce_heap(&factory, 3 + (n==0 ? 0 : 1) + (2 * n), 0);
+ if (n == 0) {
+ keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ keys = make_tuple(hp);
+ *hp++ = make_arityval(n);
+ }
ks = hp;
hp += n;
mp = (flatmap_t*)hp;
@@ -2364,6 +2402,7 @@ restart:
hashmap_iterator_init(&wstack, t, 0);
while ((kv=hashmap_iterator_next(&wstack)) != NULL) {
+ ASSERT(n != 0);
*ks++ = CAR(kv);
*vs++ = CDR(kv);
}
@@ -2689,7 +2728,16 @@ restart:
break;
case matchCaller:
ASSERT(c_p == self);
- t = c_p->stop[0];
+
+ /* Note that we can't use `erts_inspect_frame` here as the top of
+ * the stack could point at something other than a frame. */
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ t = c_p->stop[0];
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+ t = c_p->stop[1];
+ }
+
if (is_not_CP(t)) {
*esp++ = am_undefined;
} else if (!(cp = erts_find_function_from_pc(cp_val(t)))) {
@@ -2703,6 +2751,47 @@ restart:
ehp[3] = make_small((Uint) cp->arity);
}
break;
+ case matchCallerLine:
+ ASSERT(c_p == self);
+
+ /* Note that we can't use `erts_inspect_frame` here as the top of
+ * the stack could point at something other than a frame. */
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ t = c_p->stop[0];
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+ t = c_p->stop[1];
+ }
+
+ if (is_not_CP(t)) {
+ *esp++ = am_undefined;
+ break;
+ }
+
+ erts_lookup_function_info(&fi, cp_val(t), 1);
+ if (!fi.mfa) {
+ *esp++ = am_undefined;
+ } else {
+ if (fi.loc == LINE_INVALID_LOCATION) {
+ ehp = HAllocX(build_proc, 5, HEAP_XTRA);
+ } else {
+ ehp = HAllocX(build_proc, 8, HEAP_XTRA);
+ }
+ *esp++ = make_tuple(ehp);
+ ehp[0] = make_arityval(4);
+ ehp[1] = fi.mfa->module;
+ ehp[2] = fi.mfa->function;
+ ehp[3] = make_small((Uint) fi.mfa->arity);
+ if (fi.loc == LINE_INVALID_LOCATION) {
+ ehp[4] = am_undefined;
+ } else {
+ ehp[4] = make_tuple(&ehp[5]);
+ ehp[5] = make_arityval(2);
+ ehp[6] = fi.fname_ptr[LOC_FILE(fi.loc)];
+ ehp[7] = make_small(LOC_LINE(fi.loc));
+ }
+ }
+ break;
case matchSilent:
ASSERT(c_p == self);
--esp;
@@ -3398,29 +3487,33 @@ void db_cleanup_offheap_comp(DbTerm* obj)
for (u.hdr = obj->first_oh; u.hdr; u.hdr = u.hdr->next) {
erts_align_offheap(&u, &tmp);
- switch (thing_subtag(u.hdr->thing_word)) {
- case REFC_BINARY_SUBTAG:
+ switch (thing_subtag(u.hdr->thing_word)) {
+ case REFC_BINARY_SUBTAG:
erts_bin_release(u.pb->val);
- break;
- case FUN_SUBTAG:
- if (erts_refc_dectest(&u.fun->fe->refc, 0) == 0) {
- erts_erase_fun_entry(u.fun->fe);
- }
- break;
- case REF_SUBTAG:
- ASSERT(is_magic_ref_thing(u.hdr));
+ break;
+ case FUN_SUBTAG:
+ /* We _KNOW_ that this is a local fun, otherwise it would not
+ * be part of the off-heap list. */
+ ASSERT(is_local_fun(u.fun));
+ if (erts_refc_dectest(&u.fun->entry.fun->refc, 0) == 0) {
+ erts_erase_fun_entry(u.fun->entry.fun);
+ }
+ break;
+ case REF_SUBTAG:
+ ASSERT(is_magic_ref_thing(u.hdr));
erts_bin_release((Binary *)u.mref->mb);
- break;
- default:
- ASSERT(is_external_header(u.hdr->thing_word));
- erts_deref_node_entry(u.ext->node, make_boxed(u.ep));
- break;
- }
+ break;
+ default:
+ ASSERT(is_external_header(u.hdr->thing_word));
+ erts_deref_node_entry(u.ext->node, make_boxed(u.ep));
+ break;
+ }
}
+
#ifdef DEBUG_CLONE
if (obj->debug_clone != NULL) {
- erts_free(ERTS_ALC_T_DB_TERM, obj->debug_clone);
- obj->debug_clone = NULL;
+ erts_free(ERTS_ALC_T_DB_TERM, obj->debug_clone);
+ obj->debug_clone = NULL;
}
#endif
}
@@ -3795,9 +3888,9 @@ static void do_emit_constant(DMCContext *context, DMC_STACK_TYPE(UWord) *text,
context->save = emb;
}
else {
- /* must be {const, Immed} */
+ /* must be {const, Immed} or the empty tuple*/
ASSERT(is_tuple_arity(t,2) && tuple_val(t)[1] == am_const);
- ASSERT(is_immed(tuple_val(t)[2]));
+ ASSERT(is_tuple_arity(tuple_val(t)[2],0) || is_immed(tuple_val(t)[2]));
tmp = tuple_val(t)[2];
}
}
@@ -4841,8 +4934,30 @@ static DMCRet dmc_caller(DMCContext *context,
return retOk;
}
+static DMCRet dmc_caller_line(DMCContext *context,
+ DMCHeap *heap,
+ DMC_STACK_TYPE(UWord) *text,
+ Eterm t,
+ int *constant)
+{
+ Eterm *p = tuple_val(t);
+ DMCRet ret;
+
+ if (!check_trace("caller_line", context, constant,
+ (DCOMP_CALL_TRACE|DCOMP_ALLOW_TRACE_OPS), 0, &ret))
+ return ret;
+
+ if (p[0] != make_arityval(1)) {
+ RETURN_TERM_ERROR("Special form 'caller_line' called with "
+ "arguments in %T.", t, context, *constant);
+ }
+ *constant = 0;
+ DMC_PUSH(*text, matchCallerLine); /* Creates binary */
+ if (++context->stack_used > context->stack_need)
+ context->stack_need = context->stack_used;
+ return retOk;
+}
-
static DMCRet dmc_silent(DMCContext *context,
DMCHeap *heap,
DMC_STACK_TYPE(UWord) *text,
@@ -4928,7 +5043,9 @@ static DMCRet dmc_fun(DMCContext *context,
case am_trace:
return dmc_trace(context, heap, text, t, constant);
case am_caller:
- return dmc_caller(context, heap, text, t, constant);
+ return dmc_caller(context, heap, text, t, constant);
+ case am_caller_line:
+ return dmc_caller_line(context, heap, text, t, constant);
case am_silent:
return dmc_silent(context, heap, text, t, constant);
case am_set_tcw:
@@ -5339,14 +5456,18 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
if (tuple_val(t)[0] == make_arityval(1) &&
is_tuple(a = tuple_val(t)[1])) {
Uint i,n;
- Eterm *savep = *hp;
- ret = make_tuple(savep);
p = tuple_val(a);
n = arityval(p[0]);
- *hp += n + 1;
- *savep++ = make_arityval(n);
- for(i = 1; i <= n; ++i)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
+ if (n == 0) {
+ ret = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ Eterm *savep = *hp;
+ ret = make_tuple(savep);
+ *hp += n + 1;
+ *savep++ = make_arityval(n);
+ for(i = 1; i <= n; ++i)
+ *savep++ = my_copy_struct(p[i], hp, off_heap);
+ }
}
else if (tuple_val(t)[0] == make_arityval(2) &&
tuple_val(t)[1] == am_const) {
@@ -5368,15 +5489,18 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap)
mp = (flatmap_t*)flatmap_val(t);
/* Copy keys */
- savep = *hp;
- keys = make_tuple(savep);
- p = tuple_val(mp->keys);
+ p = tuple_val(mp->keys);
n = arityval(p[0]);
- *hp += n + 1;
- *savep++ = make_arityval(n);
- for(i = 1; i <= n; ++i)
- *savep++ = my_copy_struct(p[i], hp, off_heap);
-
+ if (n == 0) {
+ keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ savep = *hp;
+ keys = make_tuple(savep);
+ *hp += n + 1;
+ *savep++ = make_arityval(n);
+ for(i = 1; i <= n; ++i)
+ *savep++ = my_copy_struct(p[i], hp, off_heap);
+ }
savep = *hp;
ret = make_flatmap(savep);
n = flatmap_get_size(mp);
@@ -5986,6 +6110,10 @@ void db_match_dis(Binary *bp)
++t;
erts_printf("Caller\n");
break;
+ case matchCallerLine:
+ ++t;
+ erts_printf("CallerLine\n");
+ break;
default:
erts_printf("??? (0x%bpx)\n", *t);
++t;
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index 6ed1e15104..8b8851cad8 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -237,7 +237,7 @@ typedef struct db_table_method
** not DB_ERROR_NONE, the object is removed from the table. */
void (*db_finalize_dbterm)(int cret, DbUpdateHandle* handle);
void* (*db_eterm_to_dbterm)(int compress, int keypos, Eterm obj);
- void* (*db_dbterm_list_prepend)(void* list, void* db_term);
+ void* (*db_dbterm_list_append)(void* last_term, void* db_term);
void* (*db_dbterm_list_remove_first)(void** list);
int (*db_put_dbterm)(DbTable* tb, /* [in out] */
void* obj,
@@ -302,7 +302,7 @@ typedef struct db_table_common {
UWord heir_data; /* To send in ETS-TRANSFER (is_immed or (DbTerm*) */
Uint64 heir_started_interval; /* To further identify the heir */
Eterm the_name; /* an atom */
- Binary *btid;
+ Binary *btid; /* table magic ref, read only after creation */
DbTableMethod* meth; /* table methods */
/* The ErtsFlxCtr below contains:
* - Total number of items in table
@@ -321,11 +321,7 @@ typedef struct db_table_common {
int compress;
/* For unfinished operations that needs to be helped */
- void (*continuation)(long *reds_ptr,
- void** state,
- void* extra_context); /* To help yielded process */
- erts_atomic_t continuation_state;
- Binary* continuation_res_bin;
+ struct ets_insert_2_list_info* continuation_ctx;
#ifdef ETS_DBG_FORCE_TRAP
int dbg_force_trap; /* force trap on table lookup */
#endif
@@ -345,12 +341,17 @@ typedef struct db_table_common {
#define DB_FREQ_READ (1 << 10) /* read_concurrency */
#define DB_NAMED_TABLE (1 << 11)
#define DB_BUSY (1 << 12)
+#define DB_EXPLICIT_LOCK_GRANULARITY (1 << 13)
+#define DB_FINE_LOCKED_AUTO (1 << 14)
#define DB_CATREE_FORCE_SPLIT (1 << 31) /* erts_debug */
#define DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN (1 << 30) /* erts_debug */
-#define IS_HASH_TABLE(Status) (!!((Status) & \
- (DB_BAG | DB_SET | DB_DUPLICATE_BAG)))
+#define IS_HASH_TABLE(Status) (!!((Status) & \
+ (DB_BAG | DB_SET | DB_DUPLICATE_BAG)))
+#define IS_HASH_WITH_AUTO_TABLE(Status) \
+ (((Status) & \
+ (DB_ORDERED_SET | DB_CA_ORDERED_SET | DB_FINE_LOCKED_AUTO)) == DB_FINE_LOCKED_AUTO)
#define IS_TREE_TABLE(Status) (!!((Status) & \
DB_ORDERED_SET))
#define IS_CATREE_TABLE(Status) (!!((Status) & \
@@ -516,7 +517,7 @@ typedef struct dmc_err_info {
** Compilation flags
**
** The dialect is in the 3 least significant bits and are to be interspaced by
-** by at least 2 (decimal), thats why ((Uint) 2) isn't used. This is to be
+** by at least 2 (decimal), that's why ((Uint) 2) isn't used. This is to be
** able to add DBIF_GUARD or DBIF BODY to it to use in the match_spec bif
** table. The rest of the word is used like ordinary flags, one bit for each
** flag. Note that DCOMP_TABLE and DCOMP_TRACE are mutually exclusive.
diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c
index 0f48435612..487042932f 100644
--- a/erts/emulator/beam/erl_debug.c
+++ b/erts/emulator/beam/erl_debug.c
@@ -469,7 +469,7 @@ void print_untagged_memory(Eterm *pos, Eterm *end)
* is). This function knows about forwarding pointers to be able to
* print a heap during garbage collection. erts_printf("%T",val)
* do not know about forwarding pointers though, so it will still
- * crash if they are encoutered...
+ * crash if they are encountered...
*/
void print_tagged_memory(Eterm *pos, Eterm *end)
{
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index d5379a40d5..69f5862545 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2017. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -404,19 +404,23 @@ EXTERN int get_port_flags(ErlDrvPort port);
* since the binary is a shared object it MUST be written once.
*/
-EXTERN ErlDrvBinary* driver_alloc_binary(ErlDrvSizeT size);
-EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size);
EXTERN void driver_free_binary(ErlDrvBinary *bin);
+EXTERN ErlDrvBinary* driver_alloc_binary(ErlDrvSizeT size)
+ ERL_NAPI_ATTR_MALLOC_UD(driver_free_binary,1);
+EXTERN ErlDrvBinary* driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)
+ ERL_NAPI_ATTR_WUR;
-/* Referenc count on driver binaries */
+/* Reference count on driver binaries */
EXTERN ErlDrvSInt driver_binary_get_refc(ErlDrvBinary *dbp);
EXTERN ErlDrvSInt driver_binary_inc_refc(ErlDrvBinary *dbp);
EXTERN ErlDrvSInt driver_binary_dec_refc(ErlDrvBinary *dbp);
/* Allocation interface */
-EXTERN void *driver_alloc(ErlDrvSizeT size);
-EXTERN void *driver_realloc(void *ptr, ErlDrvSizeT size);
EXTERN void driver_free(void *ptr);
+EXTERN void *driver_alloc(ErlDrvSizeT size)
+ ERL_NAPI_ATTR_MALLOC_USD(1, driver_free, 1);
+EXTERN void *driver_realloc(void *ptr, ErlDrvSizeT size)
+ ERL_NAPI_ATTR_ALLOC_SIZE(2);
/* Queue interface */
EXTERN int driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len);
@@ -448,18 +452,18 @@ EXTERN void driver_system_info(ErlDrvSysInfo *sip, size_t si_size);
* erl driver thread functions.
*/
-EXTERN ErlDrvMutex *erl_drv_mutex_create(char *name);
EXTERN void erl_drv_mutex_destroy(ErlDrvMutex *mtx);
+EXTERN ErlDrvMutex *erl_drv_mutex_create(char *name) ERL_NAPI_ATTR_MALLOC_D(erl_drv_mutex_destroy,1);
EXTERN int erl_drv_mutex_trylock(ErlDrvMutex *mtx);
EXTERN void erl_drv_mutex_lock(ErlDrvMutex *mtx);
EXTERN void erl_drv_mutex_unlock(ErlDrvMutex *mtx);
-EXTERN ErlDrvCond *erl_drv_cond_create(char *name);
EXTERN void erl_drv_cond_destroy(ErlDrvCond *cnd);
+EXTERN ErlDrvCond *erl_drv_cond_create(char *name) ERL_NAPI_ATTR_MALLOC_D(erl_drv_cond_destroy,1);
EXTERN void erl_drv_cond_signal(ErlDrvCond *cnd);
EXTERN void erl_drv_cond_broadcast(ErlDrvCond *cnd);
EXTERN void erl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx);
-EXTERN ErlDrvRWLock *erl_drv_rwlock_create(char *name);
EXTERN void erl_drv_rwlock_destroy(ErlDrvRWLock *rwlck);
+EXTERN ErlDrvRWLock *erl_drv_rwlock_create(char *name) ERL_NAPI_ATTR_MALLOC_D(erl_drv_rwlock_destroy,1);
EXTERN int erl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck);
EXTERN void erl_drv_rwlock_rlock(ErlDrvRWLock *rwlck);
EXTERN void erl_drv_rwlock_runlock(ErlDrvRWLock *rwlck);
@@ -470,8 +474,8 @@ EXTERN int erl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key);
EXTERN void erl_drv_tsd_key_destroy(ErlDrvTSDKey key);
EXTERN void erl_drv_tsd_set(ErlDrvTSDKey key, void *data);
EXTERN void *erl_drv_tsd_get(ErlDrvTSDKey key);
-EXTERN ErlDrvThreadOpts *erl_drv_thread_opts_create(char *name);
EXTERN void erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts);
+EXTERN ErlDrvThreadOpts *erl_drv_thread_opts_create(char *name) ERL_NAPI_ATTR_MALLOC_D(erl_drv_thread_opts_destroy,1);
EXTERN int erl_drv_thread_create(char *name,
ErlDrvTid *tid,
void * (*func)(void *),
diff --git a/erts/emulator/beam/erl_drv_nif.h b/erts/emulator/beam/erl_drv_nif.h
index 53d1a3a531..735ffa380c 100644
--- a/erts/emulator/beam/erl_drv_nif.h
+++ b/erts/emulator/beam/erl_drv_nif.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -168,4 +168,58 @@ typedef struct {
# endif
#endif
+#define ERL_NAPI_ATTR_WUR
+#define ERL_NAPI_ATTR_ALLOC_SIZE(SZPOS)
+#define ERL_NAPI_ATTR_MALLOC_U
+#define ERL_NAPI_ATTR_MALLOC_US(SZPOS)
+#define ERL_NAPI_ATTR_MALLOC_UD(DTOR, PTRPOS)
+#define ERL_NAPI_ATTR_MALLOC_USD(SZPOS, DTOR, PTRPOS)
+#define ERL_NAPI_ATTR_MALLOC_D(DTOR, PTRPOS)
+
+/* ERL_NAPI_ATTR_MALLOC_xxx:
+ * U: Returns pointer to Undefined data. ((malloc))
+ * S: Has Size argument with nr of bytes of returned data. ((alloc_size(SZPOS)))
+ * D: Has 1-to-1 Deallocator function with ptr argument. ((malloc(DTOR,PTRPOS)))
+ */
+
+#ifdef __has_attribute
+# if __has_attribute(warn_unused_result)
+# undef ERL_NAPI_ATTR_WUR
+# define ERL_NAPI_ATTR_WUR __attribute__((warn_unused_result))
+# endif
+# if __has_attribute(alloc_size)
+# undef ERL_NAPI_ATTR_ALLOC_SIZE
+# define ERL_NAPI_ATTR_ALLOC_SIZE(SZPOS) \
+ __attribute__((alloc_size(SZPOS))) ERL_NAPI_ATTR_WUR
+# endif
+# if __has_attribute(malloc)
+# undef ERL_NAPI_ATTR_MALLOC_U
+# define ERL_NAPI_ATTR_MALLOC_U __attribute__((malloc)) ERL_NAPI_ATTR_WUR
+
+# undef ERL_NAPI_ATTR_MALLOC_US
+# define ERL_NAPI_ATTR_MALLOC_US(SZPOS) \
+ __attribute__((malloc)) ERL_NAPI_ATTR_ALLOC_SIZE(SZPOS)
+
+# undef ERL_NAPI_ATTR_MALLOC_D
+# if defined(__GNUC__) && __GNUC__ >= 11
+# define ERL_NAPI_ATTR_MALLOC_D(DTOR, PTRPOS) \
+ __attribute__((malloc(DTOR,PTRPOS))) \
+ ERL_NAPI_ATTR_WUR
+# else
+# define ERL_NAPI_ATTR_MALLOC_D(DTOR, PTRPOS) \
+ ERL_NAPI_ATTR_WUR
+# endif
+
+# undef ERL_NAPI_ATTR_MALLOC_UD
+# define ERL_NAPI_ATTR_MALLOC_UD(DTOR, PTRPOS) \
+ ERL_NAPI_ATTR_MALLOC_U \
+ ERL_NAPI_ATTR_MALLOC_D(DTOR, PTRPOS)
+
+# undef ERL_NAPI_ATTR_MALLOC_USD
+# define ERL_NAPI_ATTR_MALLOC_USD(SZPOS, DTOR, PTRPOS) \
+ ERL_NAPI_ATTR_MALLOC_US(SZPOS) \
+ ERL_NAPI_ATTR_MALLOC_D(DTOR, PTRPOS)
+# endif
+#endif
+
#endif /* __ERL_DRV_NIF_H__ */
diff --git a/erts/emulator/beam/erl_flxctr.h b/erts/emulator/beam/erl_flxctr.h
index df60f3651e..6109705b45 100644
--- a/erts/emulator/beam/erl_flxctr.h
+++ b/erts/emulator/beam/erl_flxctr.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2019. All Rights Reserved.
+ * Copyright Ericsson AB 2019-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -140,7 +140,7 @@ void erts_flxctr_dec(ErtsFlxCtr* c,
* @param c The ErtsFlxCtr instance to operate on
* @param counter_nr The number of the counter within c to operate on
*
- * @return A snapshot of the specifed counter if c is centralized or a
+ * @return A snapshot of the specified counter if c is centralized or a
* possibly incorrect estimate of the counter value if c is
* decentralized
*/
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index c9eb42a0bd..17b3e12dd8 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,16 @@
#include "global.h"
#include "erl_fun.h"
#include "hash.h"
+#include "beam_common.h"
+
+/* Container structure for fun entries, allowing us to start `ErlFunEntry` with
+ * a field other than its `HashBucket`. */
+typedef struct erl_fun_entry_container {
+ /* !! MUST BE THE FIRST FIELD !! */
+ HashBucket bucket;
+
+ ErlFunEntry entry;
+} ErlFunEntryContainer;
static Hash erts_fun_table;
@@ -37,18 +47,10 @@ static erts_rwmtx_t erts_fun_table_lock;
#define erts_fun_write_lock() erts_rwmtx_rwlock(&erts_fun_table_lock)
#define erts_fun_write_unlock() erts_rwmtx_rwunlock(&erts_fun_table_lock)
-static HashValue fun_hash(ErlFunEntry* obj);
-static int fun_cmp(ErlFunEntry* obj1, ErlFunEntry* obj2);
-static ErlFunEntry* fun_alloc(ErlFunEntry* template);
-static void fun_free(ErlFunEntry* obj);
-
-/*
- * The address field of every fun that has no loaded code will point
- * to unloaded_fun[]. The -1 in unloaded_fun[0] will be interpreted
- * as an illegal arity when attempting to call a fun.
- */
-static BeamInstr unloaded_fun_code[4] = {NIL, NIL, -1, 0};
-static ErtsCodePtr unloaded_fun = &unloaded_fun_code[3];
+static HashValue fun_hash(ErlFunEntryContainer* obj);
+static int fun_cmp(ErlFunEntryContainer* obj1, ErlFunEntryContainer* obj2);
+static ErlFunEntryContainer* fun_alloc(ErlFunEntryContainer* template);
+static void fun_free(ErlFunEntryContainer* obj);
void
erts_init_fun_table(void)
@@ -97,61 +99,66 @@ int erts_fun_table_sz(void)
ErlFunEntry*
erts_put_fun_entry2(Eterm mod, int old_uniq, int old_index,
- const byte* uniq, int index, int arity)
+ const byte* uniq, int index, int arity)
{
- ErlFunEntry template;
- ErlFunEntry* fe;
+ ErlFunEntryContainer template;
+ ErlFunEntryContainer *fc;
+ ErlFunEntry *tp;
erts_aint_t refc;
+ tp = &template.entry;
+
+ /* All fields are copied from the template when inserting a new entry. */
ASSERT(is_atom(mod));
- template.old_uniq = old_uniq;
- template.index = index;
- template.module = mod;
+ tp->old_index = old_index;
+ tp->old_uniq = old_uniq;
+ tp->index = index;
+ tp->module = mod;
+ tp->arity = arity;
+
+ sys_memcpy(tp->uniq, uniq, sizeof(tp->uniq));
+
erts_fun_write_lock();
- fe = (ErlFunEntry *) hash_put(&erts_fun_table, (void*) &template);
- sys_memcpy(fe->uniq, uniq, sizeof(fe->uniq));
- fe->old_index = old_index;
- fe->arity = arity;
- refc = erts_refc_inctest(&fe->refc, 0);
- if (refc < 2) /* New or pending delete */
- erts_refc_inc(&fe->refc, 1);
+ fc = (ErlFunEntryContainer*)hash_put(&erts_fun_table, (void*)&template);
+ refc = erts_refc_inctest(&fc->entry.refc, 0);
+ if (refc < 2) {
+ /* New or pending delete */
+ erts_refc_inc(&fc->entry.refc, 1);
+ }
erts_fun_write_unlock();
- return fe;
+
+ return &fc->entry;
}
-ErlFunEntry*
-erts_get_fun_entry(Eterm mod, int uniq, int index)
-{
- ErlFunEntry template;
- ErlFunEntry *ret;
+const ErtsCodeMFA *erts_get_fun_mfa(const ErlFunEntry *fe) {
+ ErtsCodePtr address = fe->dispatch.addresses[0];
- ASSERT(is_atom(mod));
- template.old_uniq = uniq;
- template.index = index;
- template.module = mod;
- erts_fun_read_lock();
- ret = (ErlFunEntry *) hash_get(&erts_fun_table, (void*) &template);
- if (ret) {
- erts_aint_t refc = erts_refc_inctest(&ret->refc, 1);
- if (refc < 2) /* Pending delete */
- erts_refc_inc(&ret->refc, 1);
+ if (address != beam_unloaded_fun) {
+ return erts_find_function_from_pc(address);
}
- erts_fun_read_unlock();
- return ret;
+
+ return NULL;
}
-int erts_is_fun_loaded(ErlFunEntry* fe) {
- int res = fe->address != unloaded_fun;
+void erts_set_fun_code(ErlFunEntry *fe, ErtsCodePtr address) {
+ int i;
- ASSERT(res == (0 != ((const BeamInstr*)fe->address)[0]));
+ for (i = 0; i < ERTS_ADDRESSV_SIZE; i++) {
+ fe->dispatch.addresses[i] = address;
+ }
+}
- return res;
+int erts_is_fun_loaded(const ErlFunEntry* fe) {
+ return fe->dispatch.addresses[0] != beam_unloaded_fun;
}
static void
erts_erase_fun_entry_unlocked(ErlFunEntry* fe)
{
- hash_erase(&erts_fun_table, (void *) fe);
+ ErlFunEntryContainer *fc = ErtsContainerStruct(fe, ErlFunEntryContainer,
+ entry);
+
+ hash_erase(&erts_fun_table, (void *) fc);
}
void
@@ -164,28 +171,33 @@ erts_erase_fun_entry(ErlFunEntry* fe)
*/
if (erts_refc_dectest(&fe->refc, -1) <= 0)
{
- if (fe->address != unloaded_fun)
- erts_exit(ERTS_ERROR_EXIT,
- "Internal error: "
- "Invalid reference count found on #Fun<%T.%d.%d>: "
- " About to erase fun still referred by code.\n",
- fe->module, fe->old_index, fe->old_uniq);
- erts_erase_fun_entry_unlocked(fe);
+ if (erts_is_fun_loaded(fe)) {
+ erts_exit(ERTS_ERROR_EXIT,
+ "Internal error: "
+ "Invalid reference count found on #Fun<%T.%d.%d>: "
+ " About to erase fun still referred by code.\n",
+ fe->module, fe->old_index, fe->old_uniq);
+ }
+ erts_erase_fun_entry_unlocked(fe);
}
erts_fun_write_unlock();
}
-static void fun_purge_foreach(ErlFunEntry *fe, struct erl_module_instance* modp)
+static void fun_purge_foreach(ErlFunEntryContainer *fc,
+ struct erl_module_instance* modp)
{
const char *fun_addr, *mod_start;
+ ErlFunEntry *fe = &fc->entry;
- fun_addr = (const char*)fe->address;
+ fun_addr = (const char*)fe->dispatch.addresses[0];
mod_start = (const char*)modp->code_hdr;
if (ErtsInArea(fun_addr, mod_start, modp->code_length)) {
- fe->pend_purge_address = fe->address;
+ fe->pend_purge_address = fe->dispatch.addresses[0];
ERTS_THR_WRITE_MEMORY_BARRIER;
- fe->address = unloaded_fun;
+
+ erts_set_fun_code(fe, beam_unloaded_fun);
+
erts_purge_state_add_fun(fe);
}
}
@@ -206,8 +218,8 @@ erts_fun_purge_abort_prepare(ErlFunEntry **funs, Uint no)
for (ix = 0; ix < no; ix++) {
ErlFunEntry *fe = funs[ix];
- if (fe->address == unloaded_fun) {
- fe->address = fe->pend_purge_address;
+ if (fe->dispatch.addresses[0] == beam_unloaded_fun) {
+ erts_set_fun_code(fe, fe->pend_purge_address);
}
}
}
@@ -236,19 +248,82 @@ erts_fun_purge_complete(ErlFunEntry **funs, Uint no)
ERTS_THR_WRITE_MEMORY_BARRIER;
}
+
+ErlFunThing *erts_new_export_fun_thing(Eterm **hpp, Export *exp, int arity)
+{
+ ErlFunThing *funp;
+
+ funp = (ErlFunThing*)(*hpp);
+ *hpp += ERL_FUN_SIZE;
+
+ funp->thing_word = HEADER_FUN;
+ funp->next = NULL;
+ funp->entry.exp = exp;
+ funp->num_free = 0;
+ funp->creator = am_external;
+ funp->arity = arity;
+
+#ifdef DEBUG
+ {
+ const ErtsCodeMFA *mfa = &exp->info.mfa;
+ ASSERT(arity == mfa->arity);
+ }
+#endif
+
+ return funp;
+}
+
+ErlFunThing *erts_new_local_fun_thing(Process *p, ErlFunEntry *fe,
+ int arity, int num_free)
+{
+ ErlFunThing *funp;
+
+ funp = (ErlFunThing*) p->htop;
+ p->htop += ERL_FUN_SIZE + num_free;
+ erts_refc_inc(&fe->refc, 2);
+
+ funp->thing_word = HEADER_FUN;
+ funp->next = MSO(p).first;
+ MSO(p).first = (struct erl_off_heap_header*) funp;
+ funp->entry.fun = fe;
+ funp->num_free = num_free;
+ funp->creator = p->common.id;
+ funp->arity = arity;
+
+#ifdef DEBUG
+ {
+ /* FIXME: This assertion can fail because it may point to new code that
+ * has not been committed yet. This is an actual bug but the fix is too
+ * too involved and risky to release in a patch.
+ *
+ * As this problem has existed since the introduction of funs and is
+ * very unlikely to cause actual issues in the wild, we've decided to
+ * postpone the fix until OTP 26. See OTP-18016 for details. */
+ const ErtsCodeMFA *mfa = erts_get_fun_mfa(fe);
+ ASSERT(!mfa || funp->arity == mfa->arity - num_free);
+ ASSERT(arity == fe->arity);
+ }
+#endif
+
+ return funp;
+}
+
+
struct dump_fun_foreach_args {
fmtfn_t to;
void *to_arg;
};
static void
-dump_fun_foreach(ErlFunEntry *fe, struct dump_fun_foreach_args *args)
+dump_fun_foreach(ErlFunEntryContainer *fc, struct dump_fun_foreach_args *args)
{
+ ErlFunEntry *fe = &fc->entry;
+
erts_print(args->to, args->to_arg, "=fun\n");
erts_print(args->to, args->to_arg, "Module: %T\n", fe->module);
erts_print(args->to, args->to_arg, "Uniq: %d\n", fe->old_uniq);
erts_print(args->to, args->to_arg, "Index: %d\n",fe->old_index);
- erts_print(args->to, args->to_arg, "Address: %p\n", fe->address);
+ erts_print(args->to, args->to_arg, "Address: %p\n", fe->dispatch.addresses[0]);
erts_print(args->to, args->to_arg, "Refc: %ld\n", erts_refc_read(&fe->refc, 1));
}
@@ -266,48 +341,48 @@ erts_dump_fun_entries(fmtfn_t to, void *to_arg)
}
static HashValue
-fun_hash(ErlFunEntry* obj)
+fun_hash(ErlFunEntryContainer* obj)
{
- return (HashValue) (obj->old_uniq ^ obj->index ^ atom_val(obj->module));
+ ErlFunEntry *fe = &obj->entry;
+
+ return (HashValue) (fe->old_uniq ^ fe->index ^ atom_val(fe->module));
}
static int
-fun_cmp(ErlFunEntry* obj1, ErlFunEntry* obj2)
+fun_cmp(ErlFunEntryContainer* obj1, ErlFunEntryContainer* obj2)
{
- /*
- * OTP 23: Use 'index' (instead of 'old_index') when comparing fun
- * entries. In OTP 23, multiple make_fun2 instructions may refer to the
- * the same 'index' (for the wrapper function generated for the
- * 'fun F/A' syntax).
- *
- * This is safe when loading code compiled with OTP R15 and later,
- * because since R15 (2011), the 'index' has been reliably equal
- * to 'old_index'. The loader refuses to load modules compiled before
- * OTP R15.
- */
-
- return !(obj1->module == obj2->module &&
- obj1->old_uniq == obj2->old_uniq &&
- obj1->index == obj2->index);
+ ErlFunEntry* fe1 = &obj1->entry;
+ ErlFunEntry* fe2 = &obj2->entry;
+
+ return !(fe1->old_index == fe2->old_index &&
+ fe1->old_uniq == fe2->old_uniq &&
+ fe1->module == fe2->module &&
+ fe1->index == fe2->index &&
+ fe1->arity == fe2->arity &&
+ !sys_memcmp(fe1->uniq, fe2->uniq, sizeof(fe1->uniq)));
}
-static ErlFunEntry*
-fun_alloc(ErlFunEntry* template)
+static ErlFunEntryContainer*
+fun_alloc(ErlFunEntryContainer* template)
{
- ErlFunEntry* obj = (ErlFunEntry *) erts_alloc(ERTS_ALC_T_FUN_ENTRY,
- sizeof(ErlFunEntry));
-
- obj->old_uniq = template->old_uniq;
- obj->index = template->index;
- obj->module = template->module;
- erts_refc_init(&obj->refc, -1);
- obj->address = unloaded_fun;
- obj->pend_purge_address = NULL;
+ ErlFunEntryContainer* obj;
+
+ obj = (ErlFunEntryContainer *) erts_alloc(ERTS_ALC_T_FUN_ENTRY,
+ sizeof(ErlFunEntryContainer));
+
+ sys_memcpy(obj, template, sizeof(ErlFunEntryContainer));
+
+ erts_refc_init(&obj->entry.refc, -1);
+
+ erts_set_fun_code(&obj->entry, beam_unloaded_fun);
+
+ obj->entry.pend_purge_address = NULL;
+
return obj;
}
static void
-fun_free(ErlFunEntry* obj)
+fun_free(ErlFunEntryContainer* obj)
{
erts_free(ERTS_ALC_T_FUN_ENTRY, (void *) obj);
}
diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h
index 995fb41de2..4276e9a999 100644
--- a/erts/emulator/beam/erl_fun.h
+++ b/erts/emulator/beam/erl_fun.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,53 +26,85 @@
/*
* Fun entry.
*/
-
typedef struct erl_fun_entry {
- HashBucket bucket; /* MUST BE LOCATED AT TOP OF STRUCT!!! */
-
- byte uniq[16]; /* MD5 for module. */
- int index; /* New style index. */
- int old_uniq; /* Unique number (old_style) */
- int old_index; /* Old style index */
- ErtsCodePtr address; /* Pointer to code for fun */
+ /* We start with an `ErtsDispatchable`, similar to export entries, so that
+ * we can mostly use the same code for both. This greatly reduces the
+ * complexity of instructions like `call_fun` and `is_function2`. */
+ ErtsDispatchable dispatch;
- Uint arity; /* The arity of the fun. */
+ /* These fields identify the function and must not be altered after fun
+ * creation. */
Eterm module; /* Tagged atom for module. */
+ Uint arity; /* The arity of the fun. */
+ int index; /* New style index. */
+ byte uniq[16]; /* MD5 for module. */
+ int old_uniq; /* Unique number (old_style) */
+ int old_index; /* Old style index */
+
erts_refc_t refc; /* Reference count: One for code + one for
* each fun object in each process. */
ErtsCodePtr pend_purge_address; /* Address during a pending purge */
} ErlFunEntry;
-/*
- * This structure represents a 'fun' (lambda). It is stored on
- * process heaps. It has variable size depending on the size
- * of the environment.
- */
+/* This structure represents a 'fun' (lambda), whether local or external. It is
+ * stored on process heaps, and has variable size depending on the size of the
+ * environment. */
typedef struct erl_fun_thing {
- Eterm thing_word; /* Subtag FUN_SUBTAG. */
- ErlFunEntry* fe; /* Pointer to fun entry. */
- struct erl_off_heap_header* next;
- Uint arity; /* The arity of the fun. */
- Uint num_free; /* Number of free variables (in env). */
- /* -- The following may be compound Erlang terms ---------------------- */
- Eterm creator; /* Pid of creator process (contains node). */
- Eterm env[1]; /* Environment (free variables). */
+ Eterm thing_word; /* Subtag FUN_SUBTAG. */
+
+ union {
+ /* Both `ErlFunEntry` and `Export` begin with an `ErtsDispatchable`, so
+ * code that doesn't really care which (e.g. calls) can use this
+ * pointer to improve performance. */
+ ErtsDispatchable *disp;
+
+ /* Pointer to function entry, valid iff `creator != am_external`.*/
+ ErlFunEntry *fun;
+
+ /* Pointer to export entry, valid iff `creator == am_external`.*/
+ Export *exp;
+ } entry;
+
+ /* Next off-heap object, must be NULL when this is an external fun. */
+ struct erl_off_heap_header *next;
+
+ byte arity; /* The _apparent_ arity of the fun. */
+ byte num_free; /* Number of free variables (in env). */
+
+ /* -- The following may be compound Erlang terms ---------------------- */
+ Eterm creator; /* Pid of creator process (contains node). */
+ Eterm env[1]; /* Environment (free variables). */
} ErlFunThing;
+#define is_local_fun(FunThing) ((FunThing)->creator != am_external)
+#define is_external_fun(FunThing) ((FunThing)->creator == am_external)
+
/* ERL_FUN_SIZE does _not_ include space for the environment */
#define ERL_FUN_SIZE ((sizeof(ErlFunThing)/sizeof(Eterm))-1)
+ErlFunThing *erts_new_export_fun_thing(Eterm **hpp, Export *exp, int arity);
+ErlFunThing *erts_new_local_fun_thing(Process *p,
+ ErlFunEntry *fe,
+ int arity,
+ int num_free);
+
void erts_init_fun_table(void);
void erts_fun_info(fmtfn_t, void *);
int erts_fun_table_sz(void);
-ErlFunEntry* erts_get_fun_entry(Eterm mod, int uniq, int index);
-
+/* Finds or inserts a fun entry that matches the given signature. */
ErlFunEntry* erts_put_fun_entry2(Eterm mod, int old_uniq, int old_index,
- const byte* uniq, int index, int arity);
+ const byte* uniq, int index, int arity);
+
+const ErtsCodeMFA *erts_get_fun_mfa(const ErlFunEntry *fe);
+
+void erts_set_fun_code(ErlFunEntry *fe, ErtsCodePtr address);
-int erts_is_fun_loaded(ErlFunEntry* fe);
+ERTS_GLB_INLINE
+ErtsCodePtr erts_get_fun_code(ErlFunEntry *fe, ErtsCodeIndex ix);
+
+int erts_is_fun_loaded(const ErlFunEntry* fe);
void erts_erase_fun_entry(ErlFunEntry* fe);
void erts_cleanup_funs(ErlFunThing* funp);
@@ -84,4 +116,13 @@ void erts_fun_purge_abort_finalize(ErlFunEntry **funs, Uint no);
void erts_fun_purge_complete(ErlFunEntry **funs, Uint no);
void erts_dump_fun_entries(fmtfn_t, void *);
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE
+ErtsCodePtr erts_get_fun_code(ErlFunEntry *fe, ErtsCodeIndex ix) {
+ return fe->dispatch.addresses[ix];
+}
+
+#endif
+
#endif
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 679d7f3a21..2bb41685bd 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,6 +113,7 @@ typedef struct {
int num_roots; /* Number of root arrays. */
} Rootset;
+static void copy_erlang_stack(Process *p, Eterm *new_heap, SWord new_sz);
static Uint setup_rootset(Process*, Eterm*, int, Rootset*);
static void cleanup_rootset(Rootset *rootset);
static Eterm *full_sweep_heaps(Process *p,
@@ -122,13 +123,13 @@ static Eterm *full_sweep_heaps(Process *p,
char *oh, Uint oh_size,
Eterm *objv, int nobj);
static int garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
- int need, Eterm* objv, int nobj, int fcalls,
+ Uint need, Eterm* objv, int nobj, int fcalls,
Uint max_young_gen_usage);
static int major_collection(Process* p, ErlHeapFragment *live_hf_end,
- int need, Eterm* objv, int nobj,
+ Uint need, Eterm* objv, int nobj,
Uint ygen_usage, Uint *recl);
static int minor_collection(Process* p, ErlHeapFragment *live_hf_end,
- int need, Eterm* objv, int nobj,
+ Uint need, Eterm* objv, int nobj,
Uint ygen_usage, Uint *recl);
static void do_minor(Process *p, ErlHeapFragment *live_hf_end,
char *mature, Uint mature_size,
@@ -148,12 +149,15 @@ static int adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj);
static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj);
static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj);
static void sweep_off_heap(Process *p, int fullsweep);
-static void offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size);
-static void offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size);
-static void offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
- Eterm* objv, int nobj);
-static void offset_off_heap(Process* p, Sint offs, char* area, Uint area_size);
-static void offset_mqueue(Process *p, Sint offs, char* area, Uint area_size);
+static void offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz);
+static void offset_stack(Eterm *stack, Uint sz,
+ Sint heap_offset, Sint stack_offset,
+ char* area, Uint area_sz);
+static void offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz);
+static void offset_rootset(Process *p, Sint heap_offs, Sint stack_offs,
+ char* area, Uint area_sz, Eterm* objv, int nobj);
+static void offset_off_heap(Process* p, Sint offs, char* area, Uint area_sz);
+static void offset_mqueue(Process *p, Sint offs, char* area, Uint area_sz);
static int reached_max_heap_size(Process *p, Uint total_heap_size,
Uint extra_heap_size, Uint extra_old_heap_size);
static void init_gc_info(ErtsGCInfo *gcip);
@@ -331,7 +335,7 @@ erts_next_heap_size(Uint size, Uint offset)
/*
* Return the next heap size to use. Make sure we never return
* a smaller heap size than the minimum heap size for the process.
- * (Use of the erlang:hibernate/3 BIF could have shrinked the
+ * (Use of the erlang:hibernate/3 BIF could have shrunk the
* heap below the minimum heap size.)
*/
static Uint
@@ -454,7 +458,13 @@ erts_gc_after_bif_call_lhf(Process* p, ErlHeapFragment *live_hf_end,
val[0] = result;
cost = garbage_collect(p, live_hf_end, 0, val, 1, p->fcalls, 0);
- result = val[0];
+ if (ERTS_PROC_IS_EXITING(p)) {
+ result = THE_NON_VALUE;
+ }
+ else {
+ result = val[0];
+ }
+
}
BUMP_REDS(p, cost);
@@ -471,14 +481,11 @@ erts_gc_after_bif_call(Process* p, Eterm result, Eterm* regs, Uint arity)
static ERTS_INLINE void assert_no_active_writers(Process *p)
{
#ifdef DEBUG
- struct erl_off_heap_header* ptr;
- ptr = MSO(p).first;
- while (ptr) {
- if (ptr->thing_word == HEADER_PROC_BIN) {
- ProcBin *pbp = (ProcBin*) ptr;
- ERTS_ASSERT(!(pbp->flags & PB_ACTIVE_WRITER));
- }
- ptr = ptr->next;
+ ProcBin *pb = (ProcBin*) p->wrt_bins;
+ while (pb) {
+ ASSERT(pb->thing_word == HEADER_PROC_BIN);
+ ERTS_ASSERT(!(pb->flags & PB_ACTIVE_WRITER));
+ pb = (ProcBin*) pb->next;
}
#endif
}
@@ -491,7 +498,7 @@ delay_garbage_collection(Process *p, ErlHeapFragment *live_hf_end, int need, int
{
ErlHeapFragment *hfrag;
Eterm *orig_heap, *orig_hend, *orig_htop, *orig_stop;
- Eterm *stop, *hend;
+ Eterm *hend;
Uint hsz, ssz;
int reds_left;
@@ -518,10 +525,11 @@ delay_garbage_collection(Process *p, ErlHeapFragment *live_hf_end, int need, int
hsz = ssz + need + ERTS_DELAY_GC_EXTRA_FREE + S_RESERVED;
hfrag = new_message_buffer(hsz);
+
+ copy_erlang_stack(p, &hfrag->mem[0], hsz);
+
p->heap = p->htop = &hfrag->mem[0];
p->hend = hend = &hfrag->mem[hsz];
- p->stop = stop = hend - ssz;
- sys_memcpy((void *) stop, (void *) orig_stop, ssz * sizeof(Eterm));
if (p->abandoned_heap) {
/*
@@ -672,7 +680,7 @@ check_for_possibly_long_gc(Process *p, Uint ygen_usage)
*/
static int
garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
- int need, Eterm* objv, int nobj, int fcalls,
+ Uint need, Eterm* objv, int nobj, int fcalls,
Uint max_young_gen_usage)
{
Uint reclaimed_now = 0;
@@ -722,7 +730,9 @@ garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
ERTS_CHK_OFFHEAP(p);
ErtsGcQuickSanityCheck(p);
-
+#ifdef DEBUG
+ erts_dbg_check_no_empty_boxed_non_literal_on_heap(p, NULL);
+#endif
#ifdef USE_VM_PROBES
*pidbuf = '\0';
if (DTRACE_ENABLED(gc_major_start)
@@ -775,16 +785,6 @@ do_major_collection:
ERTS_MSACC_SET_STATE_CACHED_X(ERTS_MSACC_STATE_GC);
}
- assert_no_active_writers(p);
-
- /*
- * Finish.
- */
-
- ERTS_CHK_OFFHEAP(p);
-
- ErtsGcQuickSanityCheck(p);
-
/* Max heap size has been reached and the process was configured
to be killed, so we kill it and set it in a delayed garbage
collecting state. There should be no gc_end trace or
@@ -806,6 +806,13 @@ do_major_collection:
return res;
}
+ /*
+ * Finish.
+ */
+ assert_no_active_writers(p);
+ ERTS_CHK_OFFHEAP(p);
+ ErtsGcQuickSanityCheck(p);
+
erts_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC);
if (IS_TRACED_FL(p, F_TRACE_GC)) {
@@ -875,7 +882,7 @@ do_major_collection:
}
int
-erts_garbage_collect_nobump(Process* p, int need, Eterm* objv, int nobj, int fcalls)
+erts_garbage_collect_nobump(Process* p, Uint need, Eterm* objv, int nobj, int fcalls)
{
int reds, reds_left;
if (p->sig_qs.flags & (FS_ON_HEAP_MSGQ|FS_OFF_HEAP_MSGQ_CHNG)) {
@@ -892,7 +899,7 @@ erts_garbage_collect_nobump(Process* p, int need, Eterm* objv, int nobj, int fca
}
void
-erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj)
+erts_garbage_collect(Process* p, Uint need, Eterm* objv, int nobj)
{
int reds;
if (p->sig_qs.flags & (FS_ON_HEAP_MSGQ|FS_OFF_HEAP_MSGQ_CHNG)) {
@@ -919,7 +926,7 @@ garbage_collect_hibernate(Process* p, int check_long_gc)
Eterm* htop;
Uint actual_size;
char* area;
- Uint area_size;
+ Uint area_sz;
Sint offs;
int reds;
@@ -958,7 +965,17 @@ garbage_collect_hibernate(Process* p, int check_long_gc)
/* Only allow one continuation pointer. */
ASSERT(p->stop == p->hend - CP_SIZE);
- ASSERT(p->stop[0] == make_cp(beam_normal_exit));
+
+ switch (erts_frame_layout) {
+ case ERTS_FRAME_LAYOUT_RA:
+ ASSERT(p->stop[0] == make_cp(beam_normal_exit));
+ break;
+ case ERTS_FRAME_LAYOUT_FP_RA:
+ ASSERT(p->stop[0] == make_cp(NULL));
+ ASSERT(p->stop[1] == make_cp(beam_normal_exit));
+ ASSERT(FRAME_POINTER(p) == &p->stop[0]);
+ break;
+ }
/*
* Do it.
@@ -1022,14 +1039,24 @@ garbage_collect_hibernate(Process* p, int check_long_gc)
p->hend = heap + heap_size;
p->stop = p->hend - CP_SIZE;
- p->stop[0] = make_cp(beam_normal_exit);
+
+ switch (erts_frame_layout) {
+ case ERTS_FRAME_LAYOUT_RA:
+ p->stop[0] = make_cp(beam_normal_exit);
+ break;
+ case ERTS_FRAME_LAYOUT_FP_RA:
+ p->stop[0] = make_cp(NULL);
+ p->stop[1] = make_cp(beam_normal_exit);
+ FRAME_POINTER(p) = &p->stop[0];
+ break;
+ }
offs = heap - p->heap;
area = (char *) p->heap;
- area_size = ((char *) p->htop) - area;
- offset_heap(heap, actual_size, offs, area, area_size);
+ area_sz = ((char *) p->htop) - area;
+ offset_heap(heap, actual_size, offs, area, area_sz);
p->high_water = heap + (p->high_water - p->heap);
- offset_rootset(p, offs, area, area_size, p->arg_reg, p->arity);
+ offset_rootset(p, offs, 0, area, area_sz, p->arg_reg, p->arity);
p->htop = heap + actual_size;
p->heap = heap;
p->heap_sz = heap_size;
@@ -1064,11 +1091,6 @@ erts_garbage_collect_hibernate(Process* p)
BUMP_REDS(p, reds);
}
-#define fullsweep_nstack(p,n_htop) (n_htop)
-#define GENSWEEP_NSTACK(p,old_htop,n_htop) do{}while(0)
-#define offset_nstack(p,offs,area,area_size) do{}while(0)
-#define sweep_literals_nstack(p,old_htop,area,area_size) (old_htop)
-
int
erts_garbage_collect_literals(Process* p, Eterm* literals,
Uint byte_lit_size,
@@ -1082,7 +1104,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */
Roots* roots;
char* area;
- Uint area_size;
+ Uint area_sz;
Eterm* old_htop;
Uint n;
Uint ygen_usage = 0;
@@ -1174,7 +1196,8 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
offs = temp_lit - literals;
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);
+ offset_rootset(p, offs, 0, (char *) literals, byte_lit_size,
+ p->arg_reg, p->arity);
if (oh) {
oh = (struct erl_off_heap_header *) ((Eterm *)(void *) oh + offs);
}
@@ -1186,10 +1209,10 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
*/
area = (char *) temp_lit;
- area_size = byte_lit_size;
+ area_sz = byte_lit_size;
n = setup_rootset(p, p->arg_reg, p->arity, &rootset);
roots = rootset.roots;
- old_htop = sweep_literals_nstack(p, p->old_htop, area, area_size);
+ old_htop = p->old_htop;
while (n--) {
Eterm* g_ptr = roots->v;
Uint g_sz = roots->sz;
@@ -1208,7 +1231,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
if (IS_MOVED_BOXED(val)) {
ASSERT(is_boxed(val));
*g_ptr = val;
- } else if (ErtsInArea(ptr, area, area_size)) {
+ } else if (ErtsInArea(ptr, area, area_sz)) {
move_boxed(ptr,val,&old_htop,g_ptr);
}
break;
@@ -1217,7 +1240,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
val = *ptr;
if (IS_MOVED_CONS(val)) { /* Moved */
*g_ptr = ptr[1];
- } else if (ErtsInArea(ptr, area, area_size)) {
+ } else if (ErtsInArea(ptr, area, area_sz)) {
move_cons(ptr,val,&old_htop,g_ptr);
}
break;
@@ -1234,10 +1257,10 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
* Now we'll have to go through all heaps updating all other references.
*/
- old_htop = sweep_literals_to_old_heap(p->heap, p->htop, old_htop, area, area_size);
+ old_htop = sweep_literals_to_old_heap(p->heap, p->htop, old_htop, area, area_sz);
old_htop = sweep_literal_area(p->old_heap, old_htop,
(char *) p->old_heap, sizeof(Eterm)*old_heap_size,
- area, area_size);
+ area, area_sz);
ASSERT(p->old_htop <= old_htop && old_htop <= p->old_hend);
p->old_htop = old_htop;
@@ -1259,16 +1282,14 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
*/
while (oh) {
- if (IS_MOVED_BOXED(oh->thing_word)) {
- struct erl_off_heap_header* ptr;
+ if (IS_MOVED_BOXED(oh->thing_word)) {
+ struct erl_off_heap_header* ptr;
- /*
- * This off-heap object has been copied to the heap.
- * We must increment its reference count and
- * link it into the MSO list for the process.
- */
+ /* This off-heap object has been copied to the heap.
+ * We must increment its reference count and
+ * link it into the MSO list for the process.*/
- ptr = (struct erl_off_heap_header*) boxed_val(oh->thing_word);
+ ptr = (struct erl_off_heap_header*) boxed_val(oh->thing_word);
switch (thing_subtag(ptr->thing_word)) {
case REFC_BINARY_SUBTAG:
{
@@ -1278,7 +1299,10 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
}
case FUN_SUBTAG:
{
- ErlFunEntry* fe = ((ErlFunThing*)ptr)->fe;
+ /* We _KNOW_ that this is a local fun, otherwise it would
+ * not be part of the off-heap list. */
+ ErlFunEntry* fe = ((ErlFunThing*)ptr)->entry.fun;
+ ASSERT(is_local_fun((ErlFunThing*)ptr));
erts_refc_inc(&fe->refc, 2);
break;
}
@@ -1300,10 +1324,12 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
break;
}
}
- *prev = ptr;
- prev = &ptr->next;
- }
- oh = oh->next;
+
+ *prev = ptr;
+ prev = &ptr->next;
+ }
+
+ oh = oh->next;
}
if (prev) {
@@ -1334,7 +1360,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
static int
minor_collection(Process* p, ErlHeapFragment *live_hf_end,
- int need, Eterm* objv, int nobj,
+ Uint need, Eterm* objv, int nobj,
Uint ygen_usage, Uint *recl)
{
Eterm *mature = p->abandoned_heap ? p->abandoned_heap : p->heap;
@@ -1344,6 +1370,8 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
Uint debug_tmp = 0;
#endif
+ need += S_RESERVED;
+
/*
* Check if we have gone past the max heap size limit
*/
@@ -1364,7 +1392,7 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
heap_size += OLD_HEND(p) - OLD_HEAP(p);
/* Add potential new young heap size */
- extra_heap_size = next_heap_size(p, stack_size + size_before, 0);
+ extra_heap_size = next_heap_size(p, stack_size + MAX(size_before,need), 0);
heap_size += extra_heap_size;
if (heap_size > MAX_HEAP_SIZE_GET(p))
@@ -1384,13 +1412,13 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
* This improved Estone by more than 1200 estones on my computer
* (Ultra Sparc 10).
*/
- Uint new_sz = erts_next_heap_size(size_before, 1);
+ Uint n_old_sz = erts_next_heap_size(size_before, 1);
/* Create new, empty old_heap */
n_old = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_OLD_HEAP,
- sizeof(Eterm)*new_sz);
+ sizeof(Eterm)*n_old_sz);
- OLD_HEND(p) = n_old + new_sz;
+ OLD_HEND(p) = n_old + n_old_sz;
OLD_HEAP(p) = OLD_HTOP(p) = n_old;
}
@@ -1406,7 +1434,7 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
Uint stack_size, size_after, adjust_size, need_after, new_sz, new_mature;
stack_size = STACK_START(p) - STACK_TOP(p);
- new_sz = stack_size + size_before;
+ new_sz = stack_size + MAX(size_before, need);
new_sz = next_heap_size(p, new_sz, 0);
prev_old_htop = p->old_htop;
@@ -1427,8 +1455,7 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
GEN_GCS(p)++;
need_after = ((HEAP_TOP(p) - HEAP_START(p))
+ need
- + stack_size
- + S_RESERVED);
+ + stack_size);
/*
* Excessively large heaps should be shrunk, but
@@ -1493,6 +1520,65 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
return -1;
}
+/* Copies the Erlang stack to the end of the new heap, adjusting continuation
+ * pointers as needed. */
+static ERTS_INLINE void copy_erlang_stack(Process *p,
+ Eterm *new_heap,
+ SWord new_sz) {
+ const ErtsFrameLayout frame_layout = erts_frame_layout;
+
+ Eterm *prev_stack_top, *prev_stack_end;
+ Eterm *new_stack_top;
+ SWord stack_size;
+
+ ASSERT(new_heap != HEAP_START(p));
+
+ prev_stack_top = STACK_TOP(p);
+ prev_stack_end = STACK_START(p);
+
+ stack_size = prev_stack_end - prev_stack_top;
+ new_stack_top = &new_heap[new_sz - stack_size];
+
+#if defined(DEBUG) && defined(ERLANG_FRAME_POINTERS)
+ erts_validate_stack(p, FRAME_POINTER(p), prev_stack_top);
+#endif
+
+ if (frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ sys_memcpy(new_stack_top, prev_stack_top, stack_size * sizeof(Eterm));
+ } else {
+ Eterm *new_p, *old_p;
+ SWord stack_offset;
+
+ ASSERT(frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+
+ old_p = prev_stack_top;
+ new_p = new_stack_top;
+
+ stack_offset = new_stack_top - prev_stack_top;
+
+ while (old_p < prev_stack_end) {
+ Eterm val = old_p[0];
+
+ if (is_CP(val)) {
+ Eterm *frame_ptr = (Eterm*)cp_val(val);
+
+ if (old_p < frame_ptr && frame_ptr < prev_stack_end) {
+ val = offset_ptr(val, stack_offset);
+ }
+ }
+
+ new_p[0] = val;
+
+ new_p++;
+ old_p++;
+ }
+
+ FRAME_POINTER(p) += stack_offset;
+ }
+
+ p->stop = new_stack_top;
+}
+
static void
do_minor(Process *p, ErlHeapFragment *live_hf_end,
char *mature, Uint mature_size,
@@ -1532,7 +1618,6 @@ do_minor(Process *p, ErlHeapFragment *live_hf_end,
n_htop = collect_live_heap_frags(p, live_hf_end, n_htop);
}
- GENSWEEP_NSTACK(p, old_htop, n_htop);
while (n--) {
Eterm* g_ptr = roots->v;
Uint g_sz = roots->sz;
@@ -1667,7 +1752,7 @@ do_minor(Process *p, ErlHeapFragment *live_hf_end,
OLD_HTOP(p) = old_htop;
HIGH_WATER(p) = n_htop;
- if (MSO(p).first) {
+ if (MSO(p).first || p->wrt_bins) {
sweep_off_heap(p, 0);
}
@@ -1680,10 +1765,7 @@ do_minor(Process *p, ErlHeapFragment *live_hf_end,
disallow_heap_frag_ref_in_old_heap(p);
#endif
- /* Copy stack to end of new heap */
- n = p->hend - p->stop;
- sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm));
- p->stop = n_heap + new_sz - n;
+ copy_erlang_stack(p, n_heap, new_sz);
#ifdef HARDDEBUG
disallow_heap_frag_ref_in_heap(p, n_heap, n_htop);
@@ -1714,7 +1796,7 @@ do_minor(Process *p, ErlHeapFragment *live_hf_end,
static int
major_collection(Process* p, ErlHeapFragment *live_hf_end,
- int need, Eterm* objv, int nobj,
+ Uint need, Eterm* objv, int nobj,
Uint ygen_usage, Uint *recl)
{
Uint size_before, size_after, stack_size;
@@ -1722,7 +1804,7 @@ major_collection(Process* p, ErlHeapFragment *live_hf_end,
Eterm* n_htop;
char* oh = (char *) OLD_HEAP(p);
Uint oh_size = (char *) OLD_HTOP(p) - oh;
- Uint new_sz, stk_sz;
+ Uint new_sz;
int adjusted;
VERBOSE(DEBUG_SHCOPY, ("[pid=%T] MAJOR GC: %p %p %p %p\n", p->common.id,
@@ -1773,10 +1855,7 @@ major_collection(Process* p, ErlHeapFragment *live_hf_end,
n_htop = full_sweep_heaps(p, live_hf_end, 0, n_heap, n_htop, oh, oh_size,
objv, nobj);
- /* Move the stack to the end of the heap */
- stk_sz = HEAP_END(p) - p->stop;
- sys_memcpy(n_heap + new_sz - stk_sz, p->stop, stk_sz * sizeof(Eterm));
- p->stop = n_heap + new_sz - stk_sz;
+ copy_erlang_stack(p, n_heap, new_sz);
#ifdef HARDDEBUG
disallow_heap_frag_ref_in_heap(p, n_heap, n_htop);
@@ -1908,7 +1987,7 @@ full_sweep_heaps(Process *p,
n_htop = sweep_heaps(n_heap, n_htop, oh, oh_size);
- if (MSO(p).first) {
+ if (MSO(p).first || p->wrt_bins) {
sweep_off_heap(p, 1);
}
@@ -1928,7 +2007,7 @@ adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
int adjusted = 0;
Uint wanted, sz, need_after;
Uint stack_size = STACK_SZ_ON_HEAP(p);
-
+
/*
* Resize the heap if needed.
*/
@@ -1938,7 +2017,7 @@ adjust_after_fullsweep(Process *p, int need, Eterm *objv, int nobj)
/* Too small - grow to match requested need */
sz = next_heap_size(p, need_after, 0);
grow_new_heap(p, sz, objv, nobj);
- adjusted = 1;
+ adjusted = 1;
} else if (3 * HEAP_SIZE(p) < 4 * need_after){
/* Need more than 75% of current, postpone to next GC.*/
FLAGS(p) |= F_HEAP_GROW;
@@ -2423,13 +2502,25 @@ erts_copy_one_frag(Eterm** hpp, ErlOffHeap* off_heap,
if (!is_magic_ref_thing(fhp - 1))
goto the_default;
case REFC_BINARY_SUBTAG:
- case FUN_SUBTAG:
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
case EXTERNAL_REF_SUBTAG:
oh = (struct erl_off_heap_header*) (hp-1);
cpy_sz = thing_arityval(val);
goto cpy_words;
+ case FUN_SUBTAG:
+ {
+ ErlFunThing *funp = (ErlFunThing*) (fhp - 1);
+
+ if (is_local_fun(funp)) {
+ oh = (struct erl_off_heap_header*) (hp - 1);
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ }
+
+ cpy_sz = thing_arityval(val);
+ goto cpy_words;
+ }
default:
the_default:
cpy_sz = header_arity(val);
@@ -2518,6 +2609,14 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
n++;
}
+ ASSERT(p->parent == am_undefined
+ || is_pid(follow_moved(p->parent, (Eterm) 0)));
+ if (is_not_immed(p->parent)) {
+ roots[n].v = &p->parent;
+ roots[n].sz = 1;
+ n++;
+ }
+
/*
* The process may be garbage-collected while it is terminating.
* fvalue contains the EXIT reason.
@@ -2542,7 +2641,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
roots[n].sz = ERTS_RECV_MARKER_BLOCK_SIZE;
n++;
}
-
+
/*
* If a NIF or BIF has saved arguments, they need to be added
*/
@@ -2651,100 +2750,116 @@ void cleanup_rootset(Rootset* rootset)
}
}
-static void
-grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj)
+static void resize_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj)
{
- Eterm* new_heap;
- Uint heap_size = HEAP_TOP(p) - HEAP_START(p);
- Uint stack_size = p->hend - p->stop;
- Sint offs;
+ Eterm *new_stack, *prev_stack;
+ Eterm *new_heap, *prev_heap;
+ Sint heap_offs, stack_offs;
+ Uint heap_used, stack_used;
+ Uint prev_sz;
+ Uint area_sz;
+ char* area;
- ASSERT(HEAP_SIZE(p) < new_sz);
- new_heap = (Eterm *) ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP,
- (void *) HEAP_START(p),
- sizeof(Eterm)*(HEAP_SIZE(p)),
- sizeof(Eterm)*new_sz);
-
- if ((offs = new_heap - HEAP_START(p)) == 0) { /* No move. */
- HEAP_END(p) = new_heap + new_sz;
- sys_memmove(p->hend - stack_size, p->stop, stack_size * sizeof(Eterm));
- p->stop = p->hend - stack_size;
- } else {
- char* area = (char *) HEAP_START(p);
- Uint area_size = (char *) HEAP_TOP(p) - area;
- Eterm* prev_stop = p->stop;
+ prev_heap = HEAP_START(p);
+ prev_sz = HEAP_SIZE(p);
- offset_heap(new_heap, heap_size, offs, area, area_size);
+ stack_used = STACK_START(p) - STACK_TOP(p);
+ prev_stack = &prev_heap[prev_sz - stack_used];
- HIGH_WATER(p) = new_heap + (HIGH_WATER(p) - HEAP_START(p));
+ if (new_sz <= prev_sz) {
+ /* When shrinking, we need to move the stack prior to reallocating as
+ * the upper part of the stack will disappear. */
+ sys_memmove(prev_stack - (prev_sz - new_sz),
+ prev_stack, stack_used * sizeof(Eterm));
+ }
- HEAP_END(p) = new_heap + new_sz;
- prev_stop = new_heap + (p->stop - p->heap);
- p->stop = p->hend - stack_size;
- sys_memmove(p->stop, prev_stop, stack_size * sizeof(Eterm));
+ new_heap = ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP, prev_heap,
+ prev_sz * sizeof(Eterm),
+ new_sz * sizeof(Eterm));
+ new_stack = &new_heap[new_sz - stack_used];
- offset_rootset(p, offs, area, area_size, objv, nobj);
- HEAP_TOP(p) = new_heap + heap_size;
- HEAP_START(p) = new_heap;
+ if (new_sz > prev_sz) {
+ /* We've grown and the previous stack has either remained in place or
+ * been copied over to its _previous position_ as part of reallocation,
+ * so we need to copy it to its new position at the end of the heap.
+ *
+ * Note that its pointers are still unchanged, so offset calculation
+ * should still use `prev_stack` as set above.*/
+ sys_memmove(new_stack,
+ &new_heap[prev_sz - stack_used],
+ stack_used * sizeof(Eterm));
}
+ heap_used = HEAP_TOP(p) - HEAP_START(p);
+
+ heap_offs = new_heap - prev_heap;
+ stack_offs = new_stack - prev_stack;
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ FRAME_POINTER(p) += stack_offs;
+ }
+
+ HEAP_TOP(p) = &new_heap[heap_used];
+ HEAP_START(p) = new_heap;
+
+ STACK_START(p) = &new_heap[new_sz];
+ STACK_TOP(p) = new_stack;
+
+ HIGH_WATER(p) = &new_heap[HIGH_WATER(p) - prev_heap];
+ HEAP_END(p) = &new_heap[new_sz];
+
+ HEAP_SIZE(p) = new_sz;
+
+ area = (char *) prev_heap;
+ area_sz = prev_sz * sizeof(Eterm);
+
+ if (new_heap == prev_heap) {
+ offset_stack(new_stack, stack_used, heap_offs, stack_offs,
+ area, area_sz);
+ } else {
+ offset_heap(new_heap, heap_used, heap_offs, area, area_sz);
+ offset_rootset(p, heap_offs, stack_offs, area, area_sz, objv, nobj);
+ }
+}
+
+static void
+grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj)
+{
+#ifdef USE_VM_PROBES
+ Uint prev_sz = HEAP_SIZE(p);
+#endif
+
+ ASSERT(HEAP_SIZE(p) < new_sz);
+ resize_new_heap(p, new_sz, objv, nobj);
+
#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);
+ DTRACE3(process_heap_grow, pidbuf, prev_sz, new_sz);
}
#endif
-
- HEAP_SIZE(p) = new_sz;
}
static void
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);
- sys_memmove(p->heap + new_sz - stack_size, p->stop, stack_size *
- sizeof(Eterm));
- new_heap = (Eterm *) ERTS_HEAP_REALLOC(ERTS_ALC_T_HEAP,
- (void*)p->heap,
- sizeof(Eterm)*(HEAP_SIZE(p)),
- sizeof(Eterm)*new_sz);
- p->hend = new_heap + new_sz;
- p->stop = p->hend - stack_size;
-
- if ((offs = new_heap - HEAP_START(p)) != 0) {
- char* area = (char *) HEAP_START(p);
- Uint area_size = (char *) HEAP_TOP(p) - area;
-
- /*
- * Normally, we don't expect a shrunk heap to move, but you never
- * know on some strange embedded systems...
- */
-
- offset_heap(new_heap, heap_size, offs, area, area_size);
+#ifdef USE_VM_PROBES
+ Uint prev_sz = HEAP_SIZE(p);
+#endif
- HIGH_WATER(p) = new_heap + (HIGH_WATER(p) - HEAP_START(p));
- offset_rootset(p, offs, area, area_size, objv, nobj);
- HEAP_TOP(p) = new_heap + heap_size;
- HEAP_START(p) = new_heap;
- }
+ ASSERT(HEAP_SIZE(p) > new_sz);
+ resize_new_heap(p, new_sz, objv, nobj);
#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);
+ DTRACE3(process_heap_shrink, pidbuf, prev_sz, new_sz);
}
#endif
-
- HEAP_SIZE(p) = new_sz;
}
static Uint64
@@ -2794,55 +2909,21 @@ next_vheap_size(Process* p, Uint64 vheap, Uint64 vheap_sz) {
return new_vheap_sz < p->min_vheap_size ? p->min_vheap_size : new_vheap_sz;
}
-struct shrink_cand_data {
- struct erl_off_heap_header* new_candidates;
- struct erl_off_heap_header* new_candidates_end;
- struct erl_off_heap_header* old_candidates;
- Uint no_of_candidates;
- Uint no_of_active;
-};
-
static ERTS_INLINE void
-link_live_proc_bin(struct shrink_cand_data *shrink,
- struct erl_off_heap_header*** prevppp,
- struct erl_off_heap_header** currpp,
- int new_heap)
+shrink_writable_bin(ProcBin *pb, Uint leave_unused)
{
- ProcBin *pbp = (ProcBin*) *currpp;
- ASSERT(**prevppp == *currpp);
-
- *currpp = pbp->next;
- if (pbp->flags & (PB_ACTIVE_WRITER|PB_IS_WRITABLE)) {
- ASSERT(pbp->flags & PB_IS_WRITABLE);
-
- if (pbp->flags & PB_ACTIVE_WRITER) {
- pbp->flags &= ~PB_ACTIVE_WRITER;
- shrink->no_of_active++;
- }
- else { /* inactive */
- Uint unused = pbp->val->orig_size - pbp->size;
- /* Our allocators are 8 byte aligned, i.e., shrinking with
- less than 8 bytes will have no real effect */
- if (unused >= 8) { /* A shrink candidate; save in candidate list */
- **prevppp = pbp->next;
- if (new_heap) {
- if (!shrink->new_candidates)
- shrink->new_candidates_end = (struct erl_off_heap_header*)pbp;
- pbp->next = shrink->new_candidates;
- shrink->new_candidates = (struct erl_off_heap_header*)pbp;
- }
- else {
- pbp->next = shrink->old_candidates;
- shrink->old_candidates = (struct erl_off_heap_header*)pbp;
- }
- shrink->no_of_candidates++;
- return;
- }
- }
+ Uint new_size = pb->size;
+
+ if (leave_unused) {
+ new_size += (new_size * 100) / leave_unused;
+ /* Our allocators are 8 byte aligned, i.e., shrinking with
+ less than 8 bytes will have no real effect */
+ if (new_size + 8 >= pb->val->orig_size)
+ return;
}
-
- /* Not a shrink candidate; keep in original mso list */
- *prevppp = &pbp->next;
+ ASSERT(erts_refc_read(&pb->val->intern.refc, 1) == 1);
+ pb->val = erts_bin_realloc(pb->val, new_size);
+ pb->bytes = (byte *) pb->val->orig_bytes;
}
#ifdef ERTS_MAGIC_REF_THING_HEADER
@@ -2859,23 +2940,26 @@ link_live_proc_bin(struct shrink_cand_data *shrink,
static void
sweep_off_heap(Process *p, int fullsweep)
{
- struct shrink_cand_data shrink = {0};
struct erl_off_heap_header* ptr;
struct erl_off_heap_header** prev;
+ struct erl_off_heap_header** insert_old_here;
char* oheap = NULL;
Uint oheap_sz = 0;
Uint64 bin_vheap = 0;
#ifdef DEBUG
+ Uint64 orig_bin_old_vheap = BIN_OLD_VHEAP(p);
int seen_mature = 0;
#endif
+ Uint shrink_ncandidates;
+ Uint shrink_nactive;
+ ProcBin* shrink_unresolved_end;
+ ProcBin* pb;
if (fullsweep == 0) {
oheap = (char *) OLD_HEAP(p);
oheap_sz = (char *) OLD_HEND(p) - oheap;
}
- BIN_OLD_VHEAP(p) = 0;
-
prev = &MSO(p).first;
ptr = MSO(p).first;
@@ -2899,9 +2983,9 @@ sweep_off_heap(Process *p, int fullsweep)
if (to_new_heap) {
bin_vheap += ptr->size / sizeof(Eterm);
} else {
- BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
- }
- link_live_proc_bin(&shrink, &prev, &ptr, to_new_heap);
+ BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm);
+ }
+ ASSERT(!(((ProcBin*)ptr)->flags & (PB_ACTIVE_WRITER|PB_IS_WRITABLE)));
break;
}
case ERTS_USED_MAGIC_REF_THING_HEADER__: {
@@ -2922,27 +3006,39 @@ sweep_off_heap(Process *p, int fullsweep)
make_boxed(&ptr->thing_word),
ERL_NODE_INC, __FILE__, __LINE__);
}
- prev = &ptr->next;
- ptr = ptr->next;
}
+ prev = &ptr->next;
+ ptr = ptr->next;
}
- else if (ErtsInArea(ptr, oheap, oheap_sz))
- break; /* and let old-heap loop continue */
+ else if (ErtsInArea(ptr, oheap, oheap_sz)) {
+ /*
+ * The rest of the list resides on the old heap and needs no
+ * attention during a minor gc.
+ */
+ ASSERT(!fullsweep);
+ break;
+ }
else {
/* garbage */
switch (thing_subtag(ptr->thing_word)) {
case REFC_BINARY_SUBTAG:
{
- Binary* bptr = ((ProcBin*)ptr)->val;
- erts_bin_release(bptr);
+ erts_bin_release(((ProcBin*)ptr)->val);
break;
}
case FUN_SUBTAG:
{
- ErlFunEntry* fe = ((ErlFunThing*)ptr)->fe;
- if (erts_refc_dectest(&fe->refc, 0) == 0) {
- erts_erase_fun_entry(fe);
- }
+ ErlFunThing* funp = ((ErlFunThing*)ptr);
+
+ if (is_local_fun(funp)) {
+ ErlFunEntry* fe = funp->entry.fun;
+
+ if (erts_refc_dectest(&fe->refc, 0) == 0) {
+ erts_erase_fun_entry(fe);
+ }
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ }
break;
}
case REF_SUBTAG:
@@ -2962,94 +3058,163 @@ sweep_off_heap(Process *p, int fullsweep)
}
}
- /* The rest of the list resides on old-heap, and we just did a
- * generational collection - keep objects in list.
- */
- while (ptr) {
- ASSERT(ErtsInArea(ptr, oheap, oheap_sz));
- ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
- switch (ptr->thing_word) {
- case HEADER_PROC_BIN:
- BIN_OLD_VHEAP(p) += ptr->size / sizeof(Eterm); /* for binary gc (words)*/
- link_live_proc_bin(&shrink, &prev, &ptr, 0);
- break;
- case ERTS_USED_MAGIC_REF_THING_HEADER__:
- ASSERT(is_magic_ref_thing(ptr));
- BIN_OLD_VHEAP(p) +=
- (((Uint) ((ErtsMRefThing *) ptr)->mb->orig_size)
- / sizeof(Eterm)); /* for binary gc (words)*/
- /* fall through... */
- default:
- ASSERT(is_fun_header(ptr->thing_word) ||
- is_external_header(ptr->thing_word)
- || is_magic_ref_thing(ptr));
- prev = &ptr->next;
- ptr = ptr->next;
- break;
- }
- }
+ insert_old_here = prev;
+#ifdef DEBUG
if (fullsweep) {
- BIN_OLD_VHEAP_SZ(p) = next_vheap_size(p, BIN_OLD_VHEAP(p) + MSO(p).overhead, BIN_OLD_VHEAP_SZ(p));
+ ASSERT(ptr == NULL);
+ ASSERT(BIN_OLD_VHEAP(p) == orig_bin_old_vheap);
}
- BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p));
- MSO(p).overhead = bin_vheap;
+ else {
+ /* The rest of the list resides on the old heap and needs no
+ * attention during a minor gc. In a DEBUG build, verify
+ * that the binaries in the list are not writable and that
+ * the other terms are of the allowed types.
+ */
+ while (ptr) {
+ ASSERT(ErtsInArea(ptr, oheap, oheap_sz));
+ ASSERT(!IS_MOVED_BOXED(ptr->thing_word));
+ switch (ptr->thing_word) {
+ case HEADER_PROC_BIN:
+ ASSERT(!(((ProcBin*)ptr)->flags & (PB_ACTIVE_WRITER|PB_IS_WRITABLE)));
+ break;
+ default:
+ ASSERT(is_fun_header(ptr->thing_word) ||
+ is_external_header(ptr->thing_word) ||
+ is_magic_ref_thing(ptr));
+ break;
+ }
+ ptr = ptr->next;
+ }
+ }
+#endif /* DEBUG */
/*
- * If we got any shrink candidates, check them out.
+ * Traverse writable binaries.
+ * As writable binaries may reside on the old heap we traverse
+ * the entire wrt_bins list even during minor gc.
*/
+ shrink_nactive = 0; /* number of active writable binaries */
+ shrink_ncandidates = 0; /* number of candidates for shrinking */
+ shrink_unresolved_end = NULL; /* end marker for second traversal */
+
+ pb = (ProcBin*) p->wrt_bins;
+ prev = &p->wrt_bins;
+ while (pb) {
+ int on_old_heap;
+ if (IS_MOVED_BOXED(pb->thing_word)) {
+ ASSERT(!ErtsInArea(pb, oheap, oheap_sz));
+ pb = (ProcBin*) boxed_val(pb->thing_word);
+ *prev = (struct erl_off_heap_header*) pb;
+ ASSERT(pb->thing_word == HEADER_PROC_BIN);
+ on_old_heap = ErtsInArea(pb, oheap, oheap_sz);
+ if (!on_old_heap) {
+ bin_vheap += pb->size / sizeof(Eterm);
+ } else {
+ BIN_OLD_VHEAP(p) += pb->size / sizeof(Eterm);
+ }
+ }
+ else {
+ ASSERT(pb->thing_word == HEADER_PROC_BIN);
+ on_old_heap = ErtsInArea(pb, oheap, oheap_sz);
+ if (!on_old_heap) {
+ /* garbage */
+ erts_bin_release(pb->val);
+ pb = (ProcBin*) pb->next;
+ *prev = (struct erl_off_heap_header*) pb;
+ continue;
+ }
+ }
+ if (pb->flags) {
+ ASSERT(pb->flags & PB_IS_WRITABLE);
+
+ /*
+ * How to shrink writable binaries. There are two distinct cases:
+ *
+ * + There are one or more active writers. We will shrink all
+ * writable binaries without active writers down to their
+ * original sizes.
+ *
+ * + There are no active writers. We will shrink all writable
+ * binaries, but not fully. How much margin we will leave
+ * depends on the number of writable binaries.
+ *
+ * That is, we don't know how to shrink the binaries before either
+ * + finding the first active writer, or
+ * + finding more than ERTS_INACT_WR_PB_LEAVE_LIMIT
+ * shrink candidates
+ */
+
+ if (pb->flags & PB_ACTIVE_WRITER) {
+ pb->flags &= ~PB_ACTIVE_WRITER;
+ shrink_nactive++;
+ if (!shrink_unresolved_end)
+ shrink_unresolved_end = pb;
+ }
+ else { /* inactive */
+ Uint unused = pb->val->orig_size - pb->size;
+ /* Our allocators are 8 byte aligned, i.e., shrinking with
+ less than 8 bytes will have no real effect */
+ if (unused >= 8) { /* A shrink candidate */
+ if (shrink_unresolved_end) {
+ shrink_writable_bin(pb, 0);
+ }
+ else if (++shrink_ncandidates > ERTS_INACT_WR_PB_LEAVE_LIMIT) {
+ shrink_unresolved_end = pb;
+ shrink_writable_bin(pb, 0);
+ }
+ /* else unresolved, handle in second traversal below */
+ }
+ }
+ prev = &pb->next;
+ pb = (ProcBin*) pb->next;
+ }
+ else { /* emasculated, move to regular off-heap list */
+ struct erl_off_heap_header* next = pb->next;
+ if (on_old_heap) {
+ pb->next = *insert_old_here;
+ *insert_old_here = (struct erl_off_heap_header*)pb;
+ }
+ else {
+ pb->next = p->off_heap.first;
+ p->off_heap.first = (struct erl_off_heap_header*)pb;
+ if (insert_old_here == &p->off_heap.first)
+ insert_old_here = &pb->next;
+ }
+ pb = (ProcBin*) next;
+ *prev = next;
+ }
+ }
- if (shrink.no_of_candidates) {
- ProcBin *candlist[] = { (ProcBin*)shrink.new_candidates,
- (ProcBin*)shrink.old_candidates };
+ /*
+ * Handle any unresolved shrink candidates left at the head of wrt_bins.
+ */
+ if (shrink_ncandidates) {
Uint leave_unused = 0;
- int i;
- if (shrink.no_of_active == 0) {
- if (shrink.no_of_candidates <= ERTS_INACT_WR_PB_LEAVE_MUCH_LIMIT)
+ if (shrink_nactive == 0) {
+ if (shrink_ncandidates <= ERTS_INACT_WR_PB_LEAVE_MUCH_LIMIT)
leave_unused = ERTS_INACT_WR_PB_LEAVE_MUCH_PERCENTAGE;
- else if (shrink.no_of_candidates <= ERTS_INACT_WR_PB_LEAVE_LIMIT)
- leave_unused = ERTS_INACT_WR_PB_LEAVE_PERCENTAGE;
+ else if (shrink_ncandidates <= ERTS_INACT_WR_PB_LEAVE_LIMIT)
+ leave_unused = ERTS_INACT_WR_PB_LEAVE_PERCENTAGE;
}
- for (i = 0; i < sizeof(candlist)/sizeof(candlist[0]); i++) {
- ProcBin* pb;
- for (pb = candlist[i]; pb; pb = (ProcBin*)pb->next) {
- Uint new_size = pb->size;
-
- if (leave_unused) {
- new_size += (new_size * 100) / leave_unused;
- /* Our allocators are 8 byte aligned, i.e., shrinking with
- less than 8 bytes will have no real effect */
- if (new_size + 8 >= pb->val->orig_size)
- continue;
- }
-
- pb->val = erts_bin_realloc(pb->val, new_size);
- pb->bytes = (byte *) pb->val->orig_bytes;
- }
+ for (pb = (ProcBin *)p->wrt_bins;
+ pb != shrink_unresolved_end;
+ pb = (ProcBin *)pb->next) {
+ ASSERT(pb);
+ ASSERT(pb->flags == PB_IS_WRITABLE);
+ shrink_writable_bin(pb, leave_unused);
}
+ }
-
- /*
- * We now potentially have the mso list divided into three lists:
- * - shrink candidates on new heap (inactive writable with unused data)
- * - shrink candidates on old heap (inactive writable with unused data)
- * - other binaries (read only + active writable ...) + funs and externals
- *
- * Put them back together: new candidates -> other -> old candidates
- * This order will ensure that the list only refers from new
- * generation to old and never from old to new *which is important*.
- */
- if (shrink.new_candidates) {
- if (prev == &MSO(p).first) /* empty other binaries list */
- prev = &shrink.new_candidates_end->next;
- else
- shrink.new_candidates_end->next = MSO(p).first;
- MSO(p).first = shrink.new_candidates;
- }
+ if (fullsweep) {
+ ASSERT(BIN_OLD_VHEAP(p) == orig_bin_old_vheap);
+ BIN_OLD_VHEAP(p) = 0;
+ BIN_OLD_VHEAP_SZ(p) = next_vheap_size(p, MSO(p).overhead, BIN_OLD_VHEAP_SZ(p));
}
- *prev = shrink.old_candidates;
+ BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p));
+ MSO(p).overhead = bin_vheap;
}
/*
@@ -3126,19 +3291,57 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
}
}
-/*
- * Offset pointers to heap from stack.
- */
+/* Offset on-stack pointers to stack and heap. */
+static void
+offset_stack(Eterm *stack, Uint sz,
+ Sint heap_offset, Sint stack_offset,
+ char* area, Uint area_sz) {
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA || stack_offset == 0) {
+ /* No need to update self-references, just update pointers to the
+ * heap. */
+ offset_heap_ptr(stack, sz, heap_offset, area, area_sz);
+ } else {
+ Sint i = 0;
-static void
-offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+
+ while (i < sz) {
+ Eterm val = stack[i];
+
+ switch (primary_tag(val)) {
+ case TAG_PRIMARY_HEADER:
+ if (ErtsInArea(val, area, area_sz)) {
+ stack[i] = offset_ptr(val, stack_offset);
+ }
+
+ i++;
+ break;
+ case TAG_PRIMARY_LIST:
+ case TAG_PRIMARY_BOXED:
+ if (ErtsInArea(ptr_val(val), area, area_sz)) {
+ stack[i] = offset_ptr(val, heap_offset);
+ }
+
+ i++;
+ break;
+ default:
+ i++;
+ break;
+ }
+ }
+ }
+}
+
+/* Offset pointers to heap from a root set. */
+static void
+offset_heap_ptr(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_sz)
{
while (sz--) {
Eterm val = *hp;
switch (primary_tag(val)) {
case TAG_PRIMARY_LIST:
case TAG_PRIMARY_BOXED:
- if (ErtsInArea(ptr_val(val), area, area_size)) {
+ if (ErtsInArea(ptr_val(val), area, area_sz)) {
*hp = offset_ptr(val, offs);
}
hp++;
@@ -3157,6 +3360,10 @@ offset_off_heap(Process* p, Sint offs, char* area, Uint area_size)
Eterm** uptr = (Eterm**) (void *) &MSO(p).first;
*uptr += offs;
}
+ if (p->wrt_bins && ErtsInArea(p->wrt_bins, area, area_size)) {
+ Eterm** uptr = (Eterm**) (void *) &p->wrt_bins;
+ *uptr += offs;
+ }
}
#ifndef USE_VM_PROBES
@@ -3214,43 +3421,47 @@ offset_mqueue(Process *p, Sint offs, char* area, Uint area_size)
}
static void ERTS_INLINE
-offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size,
- Eterm* objv, int nobj)
+offset_one_rootset(Process *p, Sint heap_offs, Sint stack_offs,
+ char* area, Uint area_sz, Eterm* objv, int nobj)
{
Eterm *v;
Uint sz;
if (p->dictionary) {
- offset_heap(ERTS_PD_START(p->dictionary),
- ERTS_PD_SIZE(p->dictionary),
- offs, area, area_size);
+ offset_heap(ERTS_PD_START(p->dictionary),
+ ERTS_PD_SIZE(p->dictionary),
+ heap_offs, area, area_sz);
}
- 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);
+ offset_heap_ptr(&p->fvalue, 1, heap_offs, area, area_sz);
+ offset_heap_ptr(&p->ftrace, 1, heap_offs, area, area_sz);
+ offset_heap_ptr(&p->seq_trace_token, 1, heap_offs, area, area_sz);
#ifdef USE_VM_PROBES
- offset_heap_ptr(&p->dt_utag, 1, offs, area, area_size);
+ offset_heap_ptr(&p->dt_utag, 1, heap_offs, area, area_sz);
#endif
- offset_heap_ptr(&p->group_leader, 1, offs, area, area_size);
- if (p->sig_qs.recv_mrk_blk)
- offset_heap_ptr(&p->sig_qs.recv_mrk_blk->ref[0],
- ERTS_RECV_MARKER_BLOCK_SIZE, 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);
- offset_nstack(p, offs, area, area_size);
+ offset_heap_ptr(&p->group_leader, 1, heap_offs, area, area_sz);
+ offset_heap_ptr(&p->parent, 1, heap_offs, area, area_sz);
+ if (p->sig_qs.recv_mrk_blk) {
+ offset_heap_ptr(&p->sig_qs.recv_mrk_blk->ref[0],
+ ERTS_RECV_MARKER_BLOCK_SIZE, heap_offs,
+ area, area_sz);
+ }
+ offset_mqueue(p, heap_offs, area, area_sz);
+ offset_stack(p->stop, (STACK_START(p) - p->stop), heap_offs, stack_offs,
+ area, area_sz);
if (nobj > 0) {
- offset_heap_ptr(objv, nobj, offs, area, area_size);
+ offset_heap_ptr(objv, nobj, heap_offs, area, area_sz);
+ }
+ offset_off_heap(p, heap_offs, area, area_sz);
+ if (erts_setup_nfunc_rootset(p, &v, &sz)) {
+ offset_heap_ptr(v, sz, heap_offs, area, area_sz);
}
- offset_off_heap(p, offs, area, area_size);
- if (erts_setup_nfunc_rootset(p, &v, &sz))
- offset_heap_ptr(v, sz, offs, area, area_size);
}
static void
-offset_rootset(Process *p, Sint offs, char* area, Uint area_size,
- Eterm* objv, int nobj)
+offset_rootset(Process *p, Sint heap_offs, Sint stack_offs,
+ char* area, Uint area_sz, Eterm* objv, int nobj)
{
- offset_one_rootset(p, offs, area, area_size, objv, nobj);
+ offset_one_rootset(p, heap_offs, stack_offs, area, area_sz, objv, nobj);
}
static void
@@ -3600,6 +3811,61 @@ erts_max_heap_size(Eterm arg, Uint *max_heap_size, Uint *max_heap_flags)
return 1;
}
+#ifdef DEBUG
+void erts_validate_stack(Process *p, Eterm *frame_ptr, Eterm *stack_top) {
+ Eterm *stack_bottom = HEAP_END(p);
+ Eterm *next_fp = frame_ptr;
+ Eterm *scanner = stack_top;
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ return;
+ }
+
+ /* We must have a frame pointer or an empty stack, but not both. */
+ ASSERT((next_fp != NULL) ^ (stack_top == stack_bottom));
+
+ /* If the GC happens when we are about to execute a trace we
+ need to skip the trace instructions */
+ if (BeamIsReturnTrace(p->i)) {
+ /* Skip MFA and tracer. */
+ ASSERT_MFA((ErtsCodeMFA*)cp_val(scanner[0]));
+ ASSERT(IS_TRACER_VALID(scanner[1]));
+ scanner += 2;
+ } else if (BeamIsReturnTimeTrace(p->i)) {
+ /* Skip prev_info. */
+ scanner += 1;
+ }
+
+ while (next_fp) {
+ ASSERT(next_fp >= stack_top && next_fp <= stack_bottom);
+
+ /* We may not skip any frames. */
+ while (scanner < next_fp) {
+ ASSERT(is_not_CP(scanner[0]));
+ scanner++;
+ }
+
+ /* {Next frame, Return address} or vice versa */
+ ASSERT(is_CP(scanner[0]) && is_CP(scanner[1]));
+ next_fp = (Eterm*)cp_val(scanner[0]);
+
+ /* Call tracing may store raw pointers on the stack. This is explicitly
+ * handled in all routines that deal with the stack. */
+ if (BeamIsReturnTrace((ErtsCodePtr)scanner[1])) {
+ /* Skip MFA and tracer. */
+ ASSERT_MFA((ErtsCodeMFA*)cp_val(scanner[2]));
+ ASSERT(IS_TRACER_VALID(scanner[3]));
+ scanner += 2;
+ } else if (BeamIsReturnTimeTrace((ErtsCodePtr)scanner[1])) {
+ /* Skip prev_info. */
+ scanner += 1;
+ }
+
+ scanner += CP_SIZE;
+ }
+}
+#endif
+
#if defined(DEBUG) || defined(ERTS_OFFHEAP_DEBUG)
int
@@ -3651,6 +3917,156 @@ erts_dbg_within_proc(Eterm *ptr, Process *p, Eterm *real_htop)
#endif
+#ifdef DEBUG
+
+#include "erl_global_literals.h"
+
+static int
+check_all_heap_terms_in_range(int (*check_eterm)(Eterm),
+ Eterm* region_start,
+ Eterm* region_end)
+{
+ Eterm* tp = region_start;
+ while (tp < region_end) {
+ Eterm val = *tp++;
+
+ switch (primary_tag(val)) {
+ case TAG_PRIMARY_IMMED1:
+ if (!check_eterm(val)) {
+ return 0;
+ }
+ break;
+ case TAG_PRIMARY_LIST:
+ case TAG_PRIMARY_BOXED:
+ if (!check_eterm(val)) {
+ return 0;
+ }
+ break;
+ case TAG_PRIMARY_HEADER:
+ switch (val & _HEADER_SUBTAG_MASK) {
+ case ARITYVAL_SUBTAG:
+ break;
+ case REFC_BINARY_SUBTAG:
+ goto off_heap_common;
+ case FUN_SUBTAG:
+ goto off_heap_common;
+ case EXTERNAL_PID_SUBTAG:
+ case EXTERNAL_PORT_SUBTAG:
+ case EXTERNAL_REF_SUBTAG:
+ off_heap_common:
+ {
+ int tari = thing_arityval(val);
+ tp += tari;
+ }
+ break;
+ case REF_SUBTAG: {
+ ErtsRefThing *rtp = (ErtsRefThing *) (tp - 1);
+ if (is_magic_ref_thing(rtp)) {
+ goto off_heap_common;
+ }
+ /* Fall through... */
+ }
+ default:
+ {
+ int tari = header_arity(val);
+ tp += tari;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+int
+erts_dbg_check_heap_terms(int (*check_eterm)(Eterm),
+ Process *p,
+ Eterm *real_htop)
+{
+ ErlHeapFragment* bp;
+ ErtsMessage* mp;
+ Eterm *htop, *heap;
+
+ if (p->abandoned_heap) {
+ ERTS_GET_ORIG_HEAP(p, heap, htop);
+ if (!check_all_heap_terms_in_range(check_eterm,
+ heap, htop))
+ return 0;
+ }
+
+ heap = p->heap;
+ htop = real_htop ? real_htop : HEAP_TOP(p);
+
+ if (OLD_HEAP(p) &&
+ !check_all_heap_terms_in_range(check_eterm,
+ OLD_HEAP(p), OLD_HTOP(p) /*OLD_HEND(p)*/)) {
+ return 0;
+ }
+
+ if (!check_all_heap_terms_in_range(check_eterm, heap, htop)) {
+ return 0;
+ }
+
+ mp = p->msg_frag;
+ bp = p->mbuf;
+
+ if (bp)
+ goto search_heap_frags;
+
+ while (mp) {
+
+ bp = erts_message_to_heap_frag(mp);
+ mp = mp->next;
+
+ search_heap_frags:
+
+ while (bp) {
+ if (!check_all_heap_terms_in_range(check_eterm,
+ bp->mem,
+ bp->mem + bp->used_size)) {
+ return 0;
+ }
+ bp = bp->next;
+ }
+ }
+
+ return 1;
+}
+
+static int check_no_empty_boxed_non_literal_term(Eterm term) {
+ if (is_boxed(term)) {
+ Uint arity = header_arity(*boxed_val(term));
+
+ /* Maps can have 0 arity even though they have something after the
+ * arity word. */
+ if (arity == 0 && !is_map(term)) {
+ if (term != ERTS_GLOBAL_LIT_EMPTY_TUPLE) {
+ /* Empty tuples are the only type of boxed value that can
+ * have an arity of 0. This can change in the feature and
+ * the condition above needs to be changed if it does. */
+ erts_exit(ERTS_ABORT_EXIT,
+ "Non-literal empty tuple found in heap.\n"
+ "This is not allowed due to an optimization\n"
+ "that assumes that the word after the arity\n"
+ "word is allocated.\n");
+ }
+ }
+ }
+ return 1;
+}
+
+void
+erts_dbg_check_no_empty_boxed_non_literal_on_heap(Process *p,
+ Eterm *real_htop)
+{
+ erts_dbg_check_heap_terms(check_no_empty_boxed_non_literal_term,
+ p,
+ real_htop);
+}
+
+#endif
+
#ifdef ERTS_OFFHEAP_DEBUG
#define ERTS_CHK_OFFHEAP_ASSERT(EXP) \
@@ -3671,18 +4087,26 @@ erts_check_off_heap2(Process *p, Eterm *htop)
{
Eterm *oheap = (Eterm *) OLD_HEAP(p);
Eterm *ohtop = (Eterm *) OLD_HTOP(p);
- int old;
+ enum { NEW_PART, OLD_PART, WRT_BIN_PART} part;
union erl_off_heap_ptr u;
- old = 0;
- for (u.hdr = MSO(p).first; u.hdr; u.hdr = u.hdr->next) {
+ part = NEW_PART;
+ u.hdr = MSO(p).first;
+repeat:
+ for (; u.hdr; u.hdr = u.hdr->next) {
erts_aint_t refc;
switch (thing_subtag(u.hdr->thing_word)) {
case REFC_BINARY_SUBTAG:
refc = erts_refc_read(&u.pb->val->intern.refc, 1);
break;
- case FUN_SUBTAG:
- refc = erts_refc_read(&u.fun->fe->refc, 1);
+ case FUN_SUBTAG:
+ if (is_local_fun(u.fun)) {
+ refc = erts_refc_read(&u.fun->entry.fun->refc, 1);
+ } else {
+ /* Export fun, fake a valid refc. */
+ ASSERT(is_external_fun(u.fun) && u.fun->next == NULL);
+ refc = 1;
+ }
break;
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
@@ -3701,19 +4125,26 @@ erts_check_off_heap2(Process *p, Eterm *htop)
ERTS_CHK_OFFHEAP_ASSERT(!(u.hdr->thing_word & ERTS_OFFHEAP_VISITED_BIT));
u.hdr->thing_word |= ERTS_OFFHEAP_VISITED_BIT;
#endif
- if (old) {
- ERTS_CHK_OFFHEAP_ASSERT(oheap <= u.ep && u.ep < ohtop);
- }
- else if (oheap <= u.ep && u.ep < ohtop)
- old = 1;
- else {
- ERTS_CHK_OFFHEAP_ASSERT(erts_dbg_within_proc(u.ep, p, htop));
- }
+ if (part == OLD_PART)
+ ERTS_CHK_OFFHEAP_ASSERT(oheap <= u.ep && u.ep < ohtop);
+ else if (part == NEW_PART && oheap <= u.ep && u.ep < ohtop)
+ part = OLD_PART;
+ else
+ ERTS_CHK_OFFHEAP_ASSERT(erts_dbg_within_proc(u.ep, p, htop));
}
+ if (part != WRT_BIN_PART) {
+ part = WRT_BIN_PART;
+ u.hdr = p->wrt_bins;
+ goto repeat;
+ }
+
+
#ifdef ERTS_OFFHEAP_DEBUG_CHK_CIRCULAR_LIST
for (u.hdr = MSO(p).first; u.hdr; u.hdr = u.hdr->next)
u.hdr->thing_word &= ~ERTS_OFFHEAP_VISITED_BIT;
+ for (u.hdr = p->wrt_bins; u.hdr; u.hdr = u.hdr->next)
+ u.hdr->thing_word &= ~ERTS_OFFHEAP_VISITED_BIT;
#endif
}
diff --git a/erts/emulator/beam/erl_gc.h b/erts/emulator/beam/erl_gc.h
index 347f099fa5..6b38379192 100644
--- a/erts/emulator/beam/erl_gc.h
+++ b/erts/emulator/beam/erl_gc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -169,8 +169,8 @@ Eterm erts_process_gc_info(struct process*, Uint *, Eterm **, Uint, Uint);
void erts_gc_info(ErtsGCInfo *gcip);
void erts_init_gc(void);
-int erts_garbage_collect_nobump(struct process*, int, Eterm*, int, int);
-void erts_garbage_collect(struct process*, int, Eterm*, int);
+int erts_garbage_collect_nobump(struct process*, Uint, Eterm*, int, int);
+void erts_garbage_collect(struct process*, Uint, Eterm*, int);
void erts_garbage_collect_hibernate(struct process* p);
Eterm erts_gc_after_bif_call_lhf(struct process* p, ErlHeapFragment *live_hf_end,
Eterm result, Eterm* regs, Uint arity);
@@ -195,4 +195,17 @@ void erts_copy_one_frag(Eterm** hpp, ErlOffHeap* off_heap,
int erts_dbg_within_proc(Eterm *ptr, Process *p, Eterm* real_htop);
#endif
+#ifdef DEBUG
+/* Validates the frame chain, ensuring that it always points within the stack
+ * and that no frames are skipped. */
+void erts_validate_stack(Process *p, Eterm *frame_ptr, Eterm *stack_top);
+int
+erts_dbg_check_heap_terms(int (*check_eterm)(Eterm),
+ Process *p,
+ Eterm *real_htop);
+void
+erts_dbg_check_no_empty_boxed_non_literal_on_heap(Process *p,
+ Eterm *real_htop);
+#endif
+
#endif /* __ERL_GC_H__ */
diff --git a/erts/emulator/beam/erl_global_literals.c b/erts/emulator/beam/erl_global_literals.c
index c3e7b8a70b..a05c103142 100644
--- a/erts/emulator/beam/erl_global_literals.c
+++ b/erts/emulator/beam/erl_global_literals.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,12 @@ struct literal {
static struct literal literals[ERTS_NUM_GLOBAL_LITERALS];
+/*
+ * Global Constant Literals
+ */
+Eterm ERTS_WRITE_UNLIKELY(ERTS_GLOBAL_LIT_EMPTY_TUPLE);
+
+
Eterm* erts_alloc_global_literal(Uint index, Uint sz)
{
ErtsLiteralArea* area;
diff --git a/erts/emulator/beam/erl_global_literals.h b/erts/emulator/beam/erl_global_literals.h
index 15e873479d..9d17c16e66 100644
--- a/erts/emulator/beam/erl_global_literals.h
+++ b/erts/emulator/beam/erl_global_literals.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,11 +24,16 @@
#define ERTS_LIT_OS_TYPE 0
#define ERTS_LIT_OS_VERSION 1
#define ERTS_LIT_DFLAGS_RECORD 2
+#define ERTS_LIT_EMPTY_TUPLE 3
+#define ERTS_LIT_ERL_FILE_SUFFIX 4
-#define ERTS_NUM_GLOBAL_LITERALS 3
+#define ERTS_NUM_GLOBAL_LITERALS 5
+
+extern Eterm ERTS_GLOBAL_LIT_EMPTY_TUPLE;
Eterm* erts_alloc_global_literal(Uint index, Uint sz);
void erts_register_global_literal(Uint index, Eterm term);
Eterm erts_get_global_literal(Uint index);
ErtsLiteralArea* erts_get_global_literal_area(Uint index);
+
#endif
diff --git a/erts/emulator/beam/erl_hl_timer.c b/erts/emulator/beam/erl_hl_timer.c
index c8c9e5e388..f77b6fd604 100644
--- a/erts/emulator/beam/erl_hl_timer.c
+++ b/erts/emulator/beam/erl_hl_timer.c
@@ -2182,7 +2182,7 @@ access_bif_timer(Process *c_p, Eterm tref, int cancel, int async, int info)
* callers message queue to the end of the queue.
*
* NOTE: It is of vital importance that the caller
- * immediately do a receive unconditionaly
+ * immediately do a receive unconditionally
* waiting for the message with the reference;
* otherwise, next receive will *not* work
* as expected!
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index ef822dbe8c..2f2e48d3c0 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2022. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,6 @@
#include "erl_mseg.h"
#include "erl_threads.h"
#include "erl_hl_timer.h"
-#include "erl_mtrace.h"
#include "erl_printf_term.h"
#include "erl_misc_utils.h"
#include "packet_parser.h"
@@ -53,6 +52,7 @@
#include "erl_osenv.h"
#include "erl_proc_sig_queue.h"
#include "beam_load.h"
+#include "erl_global_literals.h"
#include "jit/beam_asm.h"
@@ -132,12 +132,6 @@ static int modified_sched_thread_suggested_stack_size = 0;
Eterm erts_init_process_id = ERTS_INVALID_PID;
-/*
- * Note about VxWorks: All variables must be initialized by executable code,
- * not by an initializer. Otherwise a new instance of the emulator will
- * inherit previous values.
- */
-
extern void erl_crash_dump_v(char *, int, const char *, va_list);
#ifdef __WIN32__
extern void ConNormalExit(void);
@@ -168,7 +162,7 @@ int erts_initialized = 0;
int H_MIN_SIZE; /* The minimum heap grain */
int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/
-int H_MAX_SIZE; /* The maximum heap size */
+Uint H_MAX_SIZE; /* The maximum heap size */
int H_MAX_FLAGS; /* The maximum heap flags */
Uint32 erts_debug_flags; /* Debug flags. */
@@ -302,6 +296,17 @@ void erl_error(const char *fmt, va_list args)
static int early_init(int *argc, char **argv);
+static void init_constant_literals(void) {
+ Eterm* hp = erts_alloc_global_literal(ERTS_LIT_EMPTY_TUPLE, 2);
+ Eterm tuple;
+ hp[0] = make_arityval_zero();
+ hp[1] = make_arityval_zero();
+ tuple = make_tuple(hp);
+ erts_register_global_literal(ERTS_LIT_EMPTY_TUPLE, tuple);
+ ERTS_GLOBAL_LIT_EMPTY_TUPLE =
+ erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE);
+}
+
static void
erl_init(int ncpu,
int proc_tab_sz,
@@ -315,6 +320,7 @@ erl_init(int ncpu,
int node_tab_delete_delay,
ErtsDbSpinCount db_spin_count)
{
+ init_constant_literals();
erts_monitor_link_init();
erts_bif_unique_init();
erts_proc_sig_queue_init(); /* Must be after erts_bif_unique_init(); */
@@ -381,6 +387,7 @@ erl_init(int ncpu,
packet_parser_init();
erl_nif_init();
erts_msacc_init();
+ beamfile_init();
}
static Eterm
@@ -644,7 +651,7 @@ void erts_usage(void)
#ifdef BEAMASM
erts_fprintf(stderr, "-JDdump bool enable or disable dumping of generated assembly code for each module loaded\n");
- erts_fprintf(stderr, "-JPperf bool enable or disable support for perf on Linux\n");
+ erts_fprintf(stderr, "-JPperf true|false|dump|map|fp|no_fp enable or disable support for perf on Linux\n");
erts_fprintf(stderr, "\n");
#endif
@@ -656,6 +663,7 @@ void erts_usage(void)
erts_fprintf(stderr, "\n");
erts_fprintf(stderr, "-pc <set> control what characters are considered printable (default latin1)\n");
+ erts_fprintf(stderr, "-pad bool set default process async data (default false)\n");
erts_fprintf(stderr, "-P number set maximum number of processes on this node;\n");
erts_fprintf(stderr, " valid range is [%d-%d]\n",
ERTS_MIN_PROCESSES, ERTS_MAX_PROCESSES);
@@ -683,6 +691,7 @@ void erts_usage(void)
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, "-sct cput set cpu topology\n");
+ erts_fprintf(stderr, "-ssrct skip reading cpu topology\n");
erts_fprintf(stderr, "-secio bool enable or disable eager check I/O scheduling\n");
#if ERTS_HAVE_SCHED_UTIL_BALANCING_SUPPORT_OPT
erts_fprintf(stderr, "-sub bool enable or disable scheduler utilization balancing\n");
@@ -834,6 +843,7 @@ early_init(int *argc, char **argv) /*
int decentralized_counter_groups;
char envbuf[21]; /* enough for any 64-bit integer */
size_t envbufsz;
+ int skip_read_topology = 0;
erts_save_emu_args(*argc, argv);
@@ -973,7 +983,18 @@ early_init(int *argc, char **argv) /*
}
break;
}
-
+ case 's' : {
+ char *sub_param = argv[i]+2;
+ if (has_prefix("srct", sub_param)) {
+ /* skip reading cpu topology */
+ skip_read_topology = 1;
+ }
+ else if (has_prefix("ct", sub_param)) {
+ /* cpu topology */
+ skip_read_topology = 1;
+ }
+ break;
+ }
case 'S' :
if (argv[i][2] == 'P') {
int ptot, ponln;
@@ -1270,7 +1291,8 @@ early_init(int *argc, char **argv) /*
max_reader_groups,
&reader_groups,
max_decentralized_counter_groups,
- &decentralized_counter_groups);
+ &decentralized_counter_groups,
+ skip_read_topology);
erts_flxctr_setup(decentralized_counter_groups);
{
erts_thr_late_init_data_t elid = ERTS_THR_LATE_INIT_DATA_DEF_INITER;
@@ -1396,11 +1418,28 @@ erl_start(int argc, char **argv)
erts_usage();
}
erts_set_printable_characters(printable_chars);
- break;
- } else {
- erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
- erts_usage();
}
+ else {
+ char *sub_param = argv[i]+2;
+ if (has_prefix("ad", sub_param)) {
+ arg = get_arg(sub_param+2, argv[i+1], &i);
+ if (sys_strcmp("true", arg) == 0) {
+ erts_default_spo_flags |= SPO_ASYNC_DIST;
+ }
+ else if (sys_strcmp("false", arg) == 0) {
+ erts_default_spo_flags &= ~SPO_ASYNC_DIST;
+ }
+ else {
+ erts_fprintf(stderr, "bad async dist value %s\n", arg);
+ erts_usage();
+ }
+ }
+ else {
+ erts_fprintf(stderr, "%s unknown flag %s\n", argv[0], argv[i]);
+ erts_usage();
+ }
+ }
+ break;
case 'f':
if (!sys_strncmp(argv[i],"-fn",3)) {
int warning_type = ERL_FILENAME_WARNING_WARNING;
@@ -1603,8 +1642,11 @@ erl_start(int argc, char **argv)
}
VERBOSE(DEBUG_SYSTEM, ("using max heap log %d\n", H_MAX_FLAGS));
} else if (has_prefix("max", sub_param)) {
+ Sint hMaxSize;
+ char *rest;
arg = get_arg(sub_param+3, argv[i+1], &i);
- if ((H_MAX_SIZE = atoi(arg)) < 0) {
+ hMaxSize = ErtsStrToSint(arg, &rest, 10);
+ if (hMaxSize < 0 || hMaxSize > MAX_SMALL) {
erts_fprintf(stderr, "bad max heap size %s\n", arg);
erts_usage();
}
@@ -1614,6 +1656,7 @@ erl_start(int argc, char **argv)
arg, H_MIN_SIZE);
erts_usage();
}
+ H_MAX_SIZE = hMaxSize;
VERBOSE(DEBUG_SYSTEM, ("using max heap size %d\n", H_MAX_SIZE));
} else {
/* backward compatibility */
@@ -1688,13 +1731,18 @@ erl_start(int argc, char **argv)
#ifdef HAVE_LINUX_PERF_SUPPORT
if (sys_strcmp(arg, "true") == 0) {
- erts_jit_perf_support = BEAMASM_PERF_DUMP|BEAMASM_PERF_MAP;
+ erts_jit_perf_support |= BEAMASM_PERF_ENABLED;
} else if (sys_strcmp(arg, "false") == 0) {
- erts_jit_perf_support = 0;
+ erts_jit_perf_support &= ~BEAMASM_PERF_ENABLED;
} else if (sys_strcmp(arg, "dump") == 0) {
- erts_jit_perf_support = BEAMASM_PERF_DUMP;
+ erts_jit_perf_support |= BEAMASM_PERF_DUMP;
} else if (sys_strcmp(arg, "map") == 0) {
- erts_jit_perf_support = BEAMASM_PERF_MAP;
+ erts_jit_perf_support |= BEAMASM_PERF_MAP |
+ BEAMASM_PERF_FP;
+ } else if (sys_strcmp(arg, "fp") == 0) {
+ erts_jit_perf_support |= BEAMASM_PERF_FP;
+ } else if (sys_strcmp(arg, "no_fp") == 0) {
+ erts_jit_perf_support &= ~BEAMASM_PERF_FP;
} else {
erts_fprintf(stderr, "bad +JPperf support flag %s\n", arg);
erts_usage();
@@ -1789,8 +1837,8 @@ erl_start(int argc, char **argv)
errno = 0;
port_tab_sz = strtol(arg, NULL, 10);
if (errno != 0
- || port_tab_sz < ERTS_MIN_PROCESSES
- || ERTS_MAX_PROCESSES < port_tab_sz) {
+ || port_tab_sz < ERTS_MIN_PORTS
+ || ERTS_MAX_PORTS < port_tab_sz) {
erts_fprintf(stderr, "bad number of ports %s\n", arg);
erts_usage();
}
@@ -2099,6 +2147,9 @@ erl_start(int argc, char **argv)
}
erts_runq_supervision_interval = val;
}
+ else if (has_prefix("srct", sub_param)) {
+ /* skip reading cpu topology, already handled */
+ }
else {
erts_fprintf(stderr, "bad scheduling option %s\n", argv[i]);
erts_usage();
@@ -2491,13 +2542,21 @@ erl_start(int argc, char **argv)
__decl_noreturn void erts_thr_fatal_error(int err, const char *what)
{
const char *errstr = err ? strerror(err) : NULL;
- erts_fprintf(stderr,
- "Failed to %s: %s%s(%d)\n",
- what,
- errstr ? errstr : "",
- errstr ? " " : "",
- err);
- abort();
+ if (err == ENOMEM) {
+ erts_exit(ERTS_DUMP_EXIT, "Failed to %s: %s%s(%d)\n",
+ what,
+ errstr ? errstr : "",
+ errstr ? " " : "",
+ err);
+ } else {
+ erts_fprintf(stderr,
+ "Failed to %s: %s%s(%d)\n",
+ what,
+ errstr ? errstr : "",
+ errstr ? " " : "",
+ err);
+ abort();
+ }
}
@@ -2551,9 +2610,6 @@ erts_exit_vv(int n, int flush_async, const char *fmt, va_list args1, va_list arg
{
system_cleanup(flush_async);
- if (erts_mtrace_enabled)
- erts_mtrace_exit((Uint32) n);
-
if (fmt != NULL && *fmt != '\0')
erl_error(fmt, args2); /* Print error message. */
diff --git a/erts/emulator/beam/erl_io_queue.c b/erts/emulator/beam/erl_io_queue.c
index 8010b223e9..c931e5ffdb 100644
--- a/erts/emulator/beam/erl_io_queue.c
+++ b/erts/emulator/beam/erl_io_queue.c
@@ -413,7 +413,7 @@ SysIOVec* erts_ioq_peekq(ErtsIOQueue *q, int* vlenp) /* length of io-vector */
/* Fills a possibly deep list of chars and binaries into vec
** Small characters are first stored in the buffer buf of length ln
** binaries found are copied and linked into msoh
-** Return vector length on succsess,
+** Return vector length on success,
** -1 on overflow
** -2 on type error
*/
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c
index db1e6e0e66..c6f127e5a4 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,9 +33,6 @@
# include "config.h"
#endif
-/* Needed for VxWorks va_arg */
-#include "sys.h"
-
#ifdef ERTS_ENABLE_LOCK_CHECK
#include "erl_lock_check.h"
@@ -61,7 +58,7 @@ typedef struct {
* on initialization. Locks with small immediate Erlang terms should
* be locked before locks with large immediate Erlang terms, and
* locks with small addresses should be locked before locks with
- * large addresses. The immediate terms and adresses (boxed pointers)
+ * large addresses. The immediate terms and addresses (boxed pointers)
* are compared as unsigned integers not as Erlang terms.
*
* Once a spinlock or rw(spin)lock has been locked, the thread is not
@@ -144,7 +141,6 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "port_table", NULL },
{ "magic_ref_table", "address" },
{ "pid_ref_table", "address" },
- { "mtrace_op", NULL },
{ "instr_x", NULL },
{ "instr", NULL },
{ "dyn_lock_check", NULL },
@@ -162,13 +158,13 @@ static erts_lc_lock_order_t erts_lock_order[] = {
{ "save_ops_lock", NULL },
#endif
#endif
- { "mtrace_buf", NULL },
{ "os_monotonic_time", NULL },
{ "erts_alloc_hard_debug", NULL },
{ "hard_dbg_mseg", NULL },
{ "perf", NULL },
{ "jit_debug_descriptor", NULL },
- { "erts_mmap", NULL }
+ { "erts_mmap", NULL },
+ { "proc_sig_queue_buffer", "address" }
};
#define ERTS_LOCK_ORDER_SIZE \
@@ -532,7 +528,7 @@ unlock_of_not_locked(lc_thread_t *thr, erts_lc_lock_t *lck)
static void
lock_order_violation(lc_thread_t *thr, erts_lc_lock_t *lck)
{
- print_lock("Lock order violation occured when locking ", lck, "!\n");
+ print_lock("Lock order violation occurred when locking ", lck, "!\n");
print_curr_locks(thr);
print_lock_order();
lc_abort();
@@ -542,7 +538,7 @@ static void
type_order_violation(char *op, lc_thread_t *thr,
erts_lc_lock_t *lck)
{
- erts_fprintf(stderr, "Lock type order violation occured when ");
+ erts_fprintf(stderr, "Lock type order violation occurred when ");
print_lock(op, lck, "!\n");
ASSERT(thr);
print_curr_locks(thr);
diff --git a/erts/emulator/beam/erl_lock_count.h b/erts/emulator/beam/erl_lock_count.h
index 4c50bd11f0..02ab64ec95 100644
--- a/erts/emulator/beam/erl_lock_count.h
+++ b/erts/emulator/beam/erl_lock_count.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@ typedef struct {
} erts_lcnt_time_t;
typedef struct {
- /** @brief log2 array of nano seconds occurences */
+ /** @brief log2 array of nano seconds occurrences */
Uint32 ns[ERTS_LCNT_HISTOGRAM_SLOT_SIZE];
} erts_lcnt_hist_t;
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index c4ddee1436..e0b881db0a 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
#include "error.h"
#include "bif.h"
#include "erl_binary.h"
+#include "erl_global_literals.h"
#include "erl_map.h"
@@ -151,28 +152,35 @@ void erts_init_map(void) {
*/
BIF_RETTYPE map_size_1(BIF_ALIST_1) {
- if (is_flatmap(BIF_ARG_1)) {
- flatmap_t *mp = (flatmap_t*)flatmap_val(BIF_ARG_1);
- BIF_RET(make_small(flatmap_get_size(mp)));
- } else if (is_hashmap(BIF_ARG_1)) {
- Eterm *head;
- Uint size;
+ Sint size = erts_map_size(BIF_ARG_1);
+ if (size < 0) {
+ BIF_P->fvalue = BIF_ARG_1;
+ BIF_ERROR(BIF_P, BADMAP);
+ }
- head = hashmap_val(BIF_ARG_1);
- size = head[1];
+ /*
+ * As long as a small has 28 bits (on a 32-bit machine) for
+ * the integer itself, it is impossible to build a map whose
+ * size would not fit in a small. Add an assertion in case we
+ * ever decreases the number of bits in a small.
+ */
+ ASSERT(IS_USMALL(0, size));
+ BIF_RET(make_small(size));
+}
- /*
- * As long as a small has 28 bits (on a 32-bit machine) for
- * the integer itself, it is impossible to build a map whose
- * size would not fit in a small. Add an assertion in case we
- * ever decreases the number of bits in a small.
- */
- ASSERT(IS_USMALL(0, size));
- BIF_RET(make_small(size));
+Sint
+erts_map_size(Eterm map)
+{
+ if (is_flatmap(map)) {
+ flatmap_t *mp = (flatmap_t*)flatmap_val(map);
+ return (Sint) flatmap_get_size(mp);
+ }
+ else if (is_hashmap(map)) {
+ Eterm *head = hashmap_val(map);
+ return (Sint) head[1];
}
- BIF_P->fvalue = BIF_ARG_1;
- BIF_ERROR(BIF_P, BADMAP);
+ return -1;
}
/* maps:find/2
@@ -368,10 +376,14 @@ static Eterm flatmap_from_validated_list(Process *p, Eterm list, Eterm fill_valu
Sint idx = 0;
- hp = HAlloc(p, 3 + 1 + (2 * size));
+ hp = HAlloc(p, 3 + (size == 0 ? 0 : 1) + (2 * size));
thp = hp;
- keys = make_tuple(hp);
- *hp++ = make_arityval(size);
+ if (size == 0) {
+ keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ keys = make_tuple(hp);
+ *hp++ = make_arityval(size);
+ }
ks = hp;
hp += size;
mp = (flatmap_t*)hp;
@@ -486,14 +498,11 @@ static Eterm hashmap_from_validated_list(Process *p,
#ifdef NOT_YCF_YIELDING_VERSION
/* Macro to make YCF ignore declarations */
#define YCF_IGNORE(X) X
- YCF_IGNORE(Eterm tmp[2];)
YCF_IGNORE(ErtsHeapFactory factory_instance;)
#undef YCF_IGNORE
factory = &factory_instance;
#else
- Eterm *tmp;
factory = YCF_STACK_ALLOC(sizeof(ErtsHeapFactory));
- tmp = YCF_STACK_ALLOC(2 * sizeof(Eterm));
#endif
ASSERT(size > 0);
@@ -513,7 +522,7 @@ static Eterm hashmap_from_validated_list(Process *p,
key = kv[1];
value = kv[2];
}
- hx = hashmap_restore_hash(tmp,0,key);
+ hx = hashmap_restore_hash(0,key);
swizzle32(sw,hx);
hxns[ix].hx = sw;
hxns[ix].val = CONS(hp, key, value); hp += 2;
@@ -530,14 +539,14 @@ static Eterm hashmap_from_validated_list(Process *p,
YCF_SPECIAL_CODE_START(ON_DESTROY_STATE);
{
if (hxns != NULL) {
- /* Execution of this function got destoyed while yielding in
+ /* Execution of this function got destroyed while yielding in
the loop above */
erts_free(ERTS_ALC_T_MAP_TRAP, (void *) hxns);
}
}
YCF_SPECIAL_CODE_END();
erts_free(ERTS_ALC_T_MAP_TRAP, (void *) hxns);
- /* Memory managment depends on the line below */
+ /* Memory management depends on the line below */
hxns = NULL;
ERTS_VERIFY_UNUSED_TEMP_ALLOC(p);
@@ -552,7 +561,7 @@ static Eterm hashmap_from_validated_list(Process *p,
flatmap_t *mp;
Eterm keys;
Uint n = hashmap_size(res);
-
+ ASSERT(n > 0);
/* build flat structure */
hp = HAlloc(p, 3 + 1 + (2 * n));
keys = make_tuple(hp);
@@ -660,38 +669,93 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory* factory, Eterm *leafs, Uint n,
return res;
}
-Eterm erts_map_from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks0, Eterm *vs0, Uint n)
+static ERTS_INLINE Eterm
+from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs,
+ Uint n, Eterm *key_tuple, flatmap_t **fmpp)
{
if (n <= MAP_SMALL_MAP_LIMIT) {
- Eterm *ks, *vs, *hp;
- flatmap_t *mp;
+ Eterm *hp;
+ flatmap_t *fmp;
Eterm keys;
- hp = erts_produce_heap(factory, 3 + 1 + (2 * n), 0);
- keys = make_tuple(hp);
- *hp++ = make_arityval(n);
- ks = hp;
- hp += n;
- mp = (flatmap_t*)hp;
- hp += MAP_HEADER_FLATMAP_SZ;
- vs = hp;
+ if (key_tuple && is_value(*key_tuple)) {
+ keys = *key_tuple;
+ hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + n, 0);
+ ASSERT(is_tuple_arity(keys, n));
+ ASSERT(n == 0 || sys_memcmp((void *) (tuple_val(keys) + 1),
+ (void *) ks,
+ n * sizeof(Eterm)) == 0);
+ }
+ else if (n == 0) {
+ keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ if (key_tuple)
+ *key_tuple = keys;
+ hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + n, 0);
+ }
+ else {
+ hp = erts_produce_heap(factory, 1 + MAP_HEADER_FLATMAP_SZ + 2*n, 0);
+ keys = make_tuple(hp);
+ if (key_tuple) {
+ *key_tuple = keys;
+ }
+ *hp++ = make_arityval(n);
+ sys_memcpy((void *) hp,
+ (void *) ks,
+ n * sizeof(Eterm));
+ hp += n;
+ }
- mp->thing_word = MAP_HEADER_FLATMAP;
- mp->size = n;
- mp->keys = keys;
+ fmp = (flatmap_t*)hp;
+ hp += MAP_HEADER_FLATMAP_SZ;
- sys_memcpy(ks, ks0, n * sizeof(Eterm));
- sys_memcpy(vs, vs0, n * sizeof(Eterm));
+ fmp->thing_word = MAP_HEADER_FLATMAP;
+ fmp->size = n;
+ fmp->keys = keys;
- if (!erts_validate_and_sort_flatmap(mp)) {
+ sys_memcpy((void *) hp, (void *) vs, n * sizeof(Eterm));
+
+ if (fmpp) {
+ *fmpp = fmp;
return THE_NON_VALUE;
}
-
- return make_flatmap(mp);
+ return make_flatmap(fmp);
} else {
- return erts_hashmap_from_ks_and_vs(factory, ks0, vs0, n);
+ if (fmpp) {
+ *fmpp = NULL;
+ }
+ return erts_hashmap_from_ks_and_vs(factory, ks, vs, n);
}
- return THE_NON_VALUE;
+}
+
+Eterm erts_map_from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs, Uint n)
+{
+ Eterm res;
+ flatmap_t *fmp;
+
+ res = from_ks_and_vs(factory, ks, vs, n, NULL, &fmp);
+ if (fmp) {
+ if (erts_validate_and_sort_flatmap(fmp)) {
+ res = make_flatmap(fmp);
+ }
+ else {
+ res = THE_NON_VALUE;
+ }
+ }
+ return res;
+}
+
+Eterm erts_map_from_sorted_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs,
+ Uint n, Eterm *key_tuple)
+{
+#ifdef DEBUG
+ Uint i;
+ /* verify that key array contains unique and sorted keys... */
+ for (i = 1; i < n; i++) {
+ ASSERT(CMP_TERM(ks[i-1], ks[i]) < 0);
+ }
+#endif
+
+ return from_ks_and_vs(factory, ks, vs, n, key_tuple, NULL);
}
@@ -849,7 +913,6 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
Uint32 hx;
Eterm val;
hxnode_t *tmp = NULL;
- Eterm th[2];
ASSERT(lvl < 32);
ix = 0;
elems = 1;
@@ -861,7 +924,7 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
for(i = 0; i < jx - ix; i++) {
val = hxns[i + ix].val;
- hx = hashmap_restore_hash(th, lvl + 8, CAR(list_val(val)));
+ hx = hashmap_restore_hash(lvl + 8, CAR(list_val(val)));
swizzle32(sw,hx);
tmp[i].hx = sw;
tmp[i].val = val;
@@ -888,7 +951,7 @@ static Eterm hashmap_from_sorted_unique_array(ErtsHeapFactory* factory,
YCF_SPECIAL_CODE_START(ON_DESTROY_STATE);
{
if (tmp != NULL) {
- /* Execution of this function got destoyed while yielding in
+ /* Execution of this function got destroyed while yielding in
the loop above */
erts_free(temp_memory_allocator, (void *) tmp);
}
@@ -1497,8 +1560,6 @@ static BIF_RETTYPE hashmap_merge(Process *p, Eterm map_A, Eterm map_B,
Eterm trap_ret;
Sint initial_reds = (Sint) (ERTS_BIF_REDS_LEFT(p) * MAP_MERGE_LOOP_FACTOR);
Sint reds = initial_reds;
- DeclareTmpHeap(th,2,p);
- UseTmpHeap(2,p);
/*
* Strategy: Do depth-first traversal of both trees (at the same time)
@@ -1558,7 +1619,7 @@ recurse:
goto merge_nodes;
}
}
- hx = hashmap_restore_hash(th, ctx->lvl, keyA);
+ hx = hashmap_restore_hash(ctx->lvl, keyA);
sp->abm = 1 << hashmap_index(hx);
/* keep srcA pointing at the leaf */
}
@@ -1585,7 +1646,7 @@ recurse:
if (is_list(sp->nodeB)) { /* B is LEAF */
Eterm keyB = CAR(list_val(sp->nodeB));
- hx = hashmap_restore_hash(th, ctx->lvl, keyB);
+ hx = hashmap_restore_hash(ctx->lvl, keyB);
sp->bbm = 1 << hashmap_index(hx);
/* keep srcB pointing at the leaf */
}
@@ -1780,23 +1841,20 @@ static int hash_cmp(Uint32 ha, Uint32 hb)
int hashmap_key_hash_cmp(Eterm* ap, Eterm* bp)
{
unsigned int lvl = 0;
- DeclareTmpHeapNoproc(th,2);
- UseTmpHeapNoproc(2);
if (ap && bp) {
ASSERT(CMP_TERM(CAR(ap), CAR(bp)) != 0);
for (;;) {
- Uint32 ha = hashmap_restore_hash(th, lvl, CAR(ap));
- Uint32 hb = hashmap_restore_hash(th, lvl, CAR(bp));
+ Uint32 ha = hashmap_restore_hash(lvl, CAR(ap));
+ Uint32 hb = hashmap_restore_hash(lvl, CAR(bp));
int cmp = hash_cmp(ha, hb);
if (cmp) {
- UnUseTmpHeapNoproc(2);
return cmp;
}
lvl += 8;
}
}
- UnUseTmpHeapNoproc(2);
+
return ap ? -1 : 1;
}
@@ -1872,14 +1930,16 @@ int erts_maps_take(Process *p, Eterm key, Eterm map,
* Allocate key tuple first.
*/
- need = n + 1 - 1 + 3 + n - 1; /* tuple - 1 + map - 1 */
+ need = n + ((n-1) == 0 ? 0 : 1) - 1 + 3 + n - 1; /* tuple - 1 + map - 1 */
hp_start = HAlloc(p, need);
thp = hp_start;
- mhp = thp + n; /* offset with tuple heap size */
-
- tup = make_tuple(thp);
- *thp++ = make_arityval(n - 1);
-
+ mhp = thp + n + ((n-1) == 0 ? -1 : 0); /* offset with tuple heap size */
+ if ((n-1) == 0) {
+ tup = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ tup = make_tuple(thp);
+ *thp++ = make_arityval(n - 1);
+ }
*res = make_flatmap(mhp);
*mhp++ = MAP_HEADER_FLATMAP;
*mhp++ = n - 1;
@@ -2326,8 +2386,6 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
Eterm *ptr, hdr, *res;
Uint ix, lvl = 0;
Uint32 hval,bp;
- DeclareTmpHeapNoproc(th,2);
- UseTmpHeapNoproc(2);
ASSERT(is_boxed(node));
ptr = boxed_val(node);
@@ -2356,7 +2414,7 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
break;
}
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
ASSERT(is_boxed(node));
ptr = boxed_val(node);
@@ -2365,7 +2423,6 @@ erts_hashmap_get(Uint32 hx, Eterm key, Eterm node)
ASSERT(!is_hashmap_header_head(hdr));
}
- UnUseTmpHeapNoproc(2);
return res;
}
@@ -2403,7 +2460,6 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
Uint32 ix, cix, bp, hval, chx;
Uint slot, lvl = 0, clvl;
Uint size = 0, n = 0;
- Eterm th[2];
*update_size = 1;
@@ -2432,7 +2488,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
switch(hdr & _HEADER_MAP_SUBTAG_MASK) {
case HAMT_SUBTAG_HEAD_ARRAY:
ix = hashmap_index(hx);
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
size += HAMT_HEAD_ARRAY_SZ;
ESTACK_PUSH2(*sp, ix, node);
node = ptr[ix+2];
@@ -2459,7 +2515,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
goto unroll;
}
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
node = ptr[slot+1];
ASSERT(HAMT_NODE_BITMAP_SZ(n) <= 17);
size += HAMT_NODE_BITMAP_SZ(n);
@@ -2476,7 +2532,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
/* occupied */
if (bp & hval) {
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
node = ptr[slot+2];
ASSERT(HAMT_HEAD_BITMAP_SZ(n) <= 18);
size += HAMT_HEAD_BITMAP_SZ(n);
@@ -2500,7 +2556,7 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm value, Eterm node, Uint
}
insert_subnodes:
clvl = lvl;
- chx = hashmap_restore_hash(th,clvl,ckey);
+ chx = hashmap_restore_hash(clvl,ckey);
size += HAMT_NODE_BITMAP_SZ(2);
ix = hashmap_index(hx);
cix = hashmap_index(chx);
@@ -2508,8 +2564,8 @@ insert_subnodes:
while (cix == ix) {
ESTACK_PUSH4(*sp, 0, 1 << ix, 0, MAP_HEADER_HAMT_NODE_BITMAP(0));
size += HAMT_NODE_BITMAP_SZ(1);
- hx = hashmap_shift_hash(th,hx,lvl,key);
- chx = hashmap_shift_hash(th,chx,clvl,ckey);
+ hx = hashmap_shift_hash(hx,lvl,key);
+ chx = hashmap_shift_hash(chx,clvl,ckey);
ix = hashmap_index(hx);
cix = hashmap_index(chx);
}
@@ -2719,8 +2775,6 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key,
Uint slot, lvl = 0;
Uint size = 0, n = 0;
DECLARE_ESTACK(stack);
- DeclareTmpHeapNoproc(th,2);
- UseTmpHeapNoproc(2);
for (;;) {
switch(primary_tag(node)) {
@@ -2741,7 +2795,7 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key,
switch(hdr & _HEADER_MAP_SUBTAG_MASK) {
case HAMT_SUBTAG_HEAD_ARRAY:
ix = hashmap_index(hx);
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
size += HAMT_HEAD_ARRAY_SZ;
ESTACK_PUSH2(stack, ix, node);
node = ptr[ix+2];
@@ -2764,7 +2818,7 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key,
ESTACK_PUSH4(stack, n, bp, slot, node);
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
node = ptr[slot+1];
ASSERT(HAMT_NODE_BITMAP_SZ(n) <= 17);
size += HAMT_NODE_BITMAP_SZ(n);
@@ -2781,7 +2835,7 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key,
/* occupied */
if (bp & hval) {
- hx = hashmap_shift_hash(th,hx,lvl,key);
+ hx = hashmap_shift_hash(hx,lvl,key);
node = ptr[slot+2];
ASSERT(HAMT_HEAD_BITMAP_SZ(n) <= 18);
size += HAMT_HEAD_BITMAP_SZ(n);
@@ -2802,7 +2856,7 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key,
}
unroll:
- /* the size is bounded and atleast one less than the previous size */
+ /* the size is bounded and at least one less than the previous size */
size -= 1;
n = hashmap_size(map) - 1;
@@ -3147,10 +3201,17 @@ BIF_RETTYPE erts_internal_term_type_1(BIF_ALIST_1) {
switch (hdr & _TAG_HEADER_MASK) {
case ARITYVAL_SUBTAG:
BIF_RET(ERTS_MAKE_AM("tuple"));
- case EXPORT_SUBTAG:
- BIF_RET(ERTS_MAKE_AM("export"));
case FUN_SUBTAG:
- BIF_RET(ERTS_MAKE_AM("fun"));
+ {
+ ErlFunThing *funp = (ErlFunThing *)fun_val(obj);
+
+ if (is_local_fun(funp)) {
+ BIF_RET(ERTS_MAKE_AM("fun"));
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+ BIF_RET(ERTS_MAKE_AM("export"));
+ }
+ }
case MAP_SUBTAG:
switch (MAP_HEADER_TYPE(hdr)) {
case MAP_HEADER_TAG_FLATMAP_HEAD :
@@ -3383,7 +3444,7 @@ static Eterm hashmap_bld_tuple_uint(Uint **hpp, Uint *szp, Uint n, Uint nums[])
* continues down the 0:th slot until it finds a leaf.
*
* Once the leaf has been found, the return value is created
- * by traversing the tree using the the stack that was built
+ * by traversing the tree using the stack that was built
* when searching for the first leaf to return.
*
* The index can become a bignum, which complicates the code
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 9f070ea33e..3430ec6d7a 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
#include "sys.h"
-/* instrinsic wrappers */
+/* intrinsic wrappers */
#if ERTS_AT_LEAST_GCC_VSN__(3, 4, 0)
#define hashmap_clz(x) ((Uint32) __builtin_clz((unsigned int)(x)))
#define hashmap_bitcount(x) ((Uint32) __builtin_popcount((unsigned int) (x)))
@@ -55,14 +55,18 @@ typedef struct flatmap_s {
/* the head-node is a bitmap or array with an untagged size */
-
#define hashmap_size(x) (((hashmap_head_t*) hashmap_val(x))->size)
-#define hashmap_make_hash(Key) make_internal_hash(Key, 0)
+#define hashmap_make_hash(Key) make_map_hash(Key, 0)
+
+#define hashmap_restore_hash(Lvl, Key) \
+ (((Lvl) < 8) ? \
+ hashmap_make_hash(Key) >> (4*(Lvl)) : \
+ make_map_hash(Key, ((Lvl) >> 3)) >> (4 * ((Lvl) & 7)))
-#define hashmap_restore_hash(Heap,Lvl,Key) \
- (((Lvl) < 8) ? hashmap_make_hash(Key) >> (4*(Lvl)) : hashmap_make_hash(CONS(Heap, make_small((Lvl)>>3), (Key))) >> (4*((Lvl) & 7)))
-#define hashmap_shift_hash(Heap,Hx,Lvl,Key) \
- (((++(Lvl)) & 7) ? (Hx) >> 4 : hashmap_make_hash(CONS(Heap, make_small((Lvl)>>3), Key)))
+#define hashmap_shift_hash(Hx, Lvl, Key) \
+ (((++(Lvl)) & 7) ? \
+ (Hx) >> 4 : \
+ make_map_hash(Key, ((Lvl) >> 3)))
/* erl_term.h stuff */
#define flatmap_get_values(x) (((Eterm *)(x)) + sizeof(flatmap_t)/sizeof(Eterm))
@@ -102,6 +106,8 @@ Eterm erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n, int rejec
erts_hashmap_from_ks_and_vs_extra((F), (KS), (VS), (N), THE_NON_VALUE, THE_NON_VALUE);
Eterm erts_map_from_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks, Eterm *vs, Uint n);
+Eterm erts_map_from_sorted_ks_and_vs(ErtsHeapFactory *factory, Eterm *ks0, Eterm *vs0,
+ Uint n, Eterm *key_tuple);
Eterm erts_hashmap_from_ks_and_vs_extra(ErtsHeapFactory *factory,
Eterm *ks, Eterm *vs, Uint n,
Eterm k, Eterm v);
@@ -110,6 +116,8 @@ const Eterm *erts_maps_get(Eterm key, Eterm map);
const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm map);
+Sint erts_map_size(Eterm map);
+
/* hamt nodes v2.0
*
* node :: leaf | array | bitmap
diff --git a/erts/emulator/beam/erl_md5.c b/erts/emulator/beam/erl_md5.c
index 8d0352a367..f4b6301b5c 100644
--- a/erts/emulator/beam/erl_md5.c
+++ b/erts/emulator/beam/erl_md5.c
@@ -172,7 +172,7 @@ void MD5Update (context, input, inputLen)
}
/*
- * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * MD5 finalization. Ends an MD5 message-digest operation, writing
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 2e2cccf5ce..0026ecce99 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -161,19 +161,22 @@ erts_resize_message_buffer(ErlHeapFragment *bp, Uint size,
void
-erts_cleanup_offheap(ErlOffHeap *offheap)
+erts_cleanup_offheap_list(struct erl_off_heap_header* first)
{
union erl_off_heap_ptr u;
- for (u.hdr = offheap->first; u.hdr; u.hdr = u.hdr->next) {
+ for (u.hdr = first; u.hdr; u.hdr = u.hdr->next) {
switch (thing_subtag(u.hdr->thing_word)) {
case REFC_BINARY_SUBTAG:
erts_bin_release(u.pb->val);
break;
case FUN_SUBTAG:
- if (erts_refc_dectest(&u.fun->fe->refc, 0) == 0) {
- erts_erase_fun_entry(u.fun->fe);
- }
+ /* We _KNOW_ that this is a local fun, otherwise it would not
+ * be part of the off-heap list. */
+ ASSERT(is_local_fun(u.fun));
+ if (erts_refc_dectest(&u.fun->entry.fun->refc, 0) == 0) {
+ erts_erase_fun_entry(u.fun->entry.fun);
+ }
break;
case REF_SUBTAG:
ASSERT(is_magic_ref_thing(u.hdr));
@@ -188,6 +191,13 @@ erts_cleanup_offheap(ErlOffHeap *offheap)
}
void
+erts_cleanup_offheap(ErlOffHeap *offheap)
+{
+ erts_cleanup_offheap_list(offheap->first);
+}
+
+
+void
free_message_buffer(ErlHeapFragment* bp)
{
ASSERT(bp != NULL);
@@ -268,14 +278,14 @@ erts_realloc_shrink_message(ErtsMessage *mp, Uint sz, Eterm *brefs, Uint brefs_s
void
erts_queue_dist_message(Process *rcvr,
- ErtsProcLocks rcvr_locks,
- ErtsDistExternal *dist_ext,
+ ErtsProcLocks rcvr_locks,
+ ErtsDistExternal *dist_ext,
ErlHeapFragment *hfrag,
- Eterm token,
+ Eterm token,
Eterm from)
{
- ErtsMessage* mp;
erts_aint_t state;
+ ErtsMessage *mp;
ERTS_LC_ASSERT(rcvr_locks == erts_proc_lc_my_proc_locks(rcvr));
@@ -310,40 +320,63 @@ erts_queue_dist_message(Process *rcvr,
#endif
ERL_MESSAGE_TOKEN(mp) = token;
- if (!(rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
- if (erts_proc_trylock(rcvr, ERTS_PROC_LOCK_MSGQ) == EBUSY) {
- ErtsProcLocks need_locks = ERTS_PROC_LOCK_MSGQ;
- ErtsProcLocks unlocks =
- rcvr_locks & ERTS_PROC_LOCKS_HIGHER_THAN(ERTS_PROC_LOCK_MSGQ);
- if (unlocks) {
- erts_proc_unlock(rcvr, unlocks);
- need_locks |= unlocks;
- }
- erts_proc_lock(rcvr, need_locks);
- }
+ /* If the sender is known, try to enqueue to an outer message queue buffer
+ * instead of directly to the outer message queue.
+ *
+ * Otherwise, the code below flushes the buffer before adding the message
+ * to ensure the signal order is maintained. This should only happen for
+ * the relatively uncommon DOP_SEND/DOP_SEND_TT operations. */
+ if (is_external_pid(from) &&
+ erts_proc_sig_queue_try_enqueue_to_buffer(from, rcvr, rcvr_locks,
+ mp, &mp->next,
+ NULL, 1, 0)) {
+ return;
}
+ if (!(rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
+ ErtsProcLocks unlocks;
+
+ unlocks = rcvr_locks & ERTS_PROC_LOCKS_HIGHER_THAN(ERTS_PROC_LOCK_MSGQ);
+ erts_proc_unlock(rcvr, unlocks);
+
+ erts_proc_sig_queue_lock(rcvr);
+ }
state = erts_atomic32_read_acqb(&rcvr->state);
if (state & ERTS_PSFLG_EXITING) {
- if (!(rcvr_locks & ERTS_PROC_LOCK_MSGQ))
- erts_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
- /* Drop message if receiver is exiting or has a pending exit ... */
- erts_cleanup_messages(mp);
- }
- else {
- LINK_MESSAGE(rcvr, mp);
+ if (!(rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
+ erts_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
+ }
+
+ /* Drop message if receiver is exiting or has a pending exit ... */
+ erts_cleanup_messages(mp);
+ } else {
+ if (state & ERTS_PSFLG_OFF_HEAP_MSGQ) {
+ /* Install buffers for the outer message if the heuristic
+ * indicates that this is beneficial. It is best to do this as
+ * soon as possible to avoid as much contention as possible. */
+ erts_proc_sig_queue_maybe_install_buffers(rcvr, state);
+
+ /* Flush outer signal queue buffers, if such buffers are
+ * installed, to ensure that messages from the same
+ * process cannot be reordered. */
+ erts_proc_sig_queue_flush_buffers(rcvr);
+ }
+
+ LINK_MESSAGE(rcvr, mp);
- if (!(rcvr_locks & ERTS_PROC_LOCK_MSGQ))
- erts_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
+ if (!(rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
+ erts_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
+ }
- erts_proc_notify_new_message(rcvr, rcvr_locks);
+ erts_proc_notify_new_message(rcvr, rcvr_locks);
}
}
/* Add messages last in message queue */
static void
-queue_messages(Process* receiver,
+queue_messages(Eterm from,
+ Process* receiver,
ErtsProcLocks receiver_locks,
ErtsMessage* first,
ErtsMessage** last,
@@ -367,8 +400,17 @@ queue_messages(Process* receiver,
ERTS_LC_ASSERT((erts_proc_lc_my_proc_locks(receiver) & ERTS_PROC_LOCK_MSGQ)
== (receiver_locks & ERTS_PROC_LOCK_MSGQ));
+ /*
+ * Try to enqueue to an outer message queue buffer instead of
+ * directly to the outer message queue
+ */
+ if (erts_proc_sig_queue_try_enqueue_to_buffer(from, receiver, receiver_locks,
+ first, last, NULL, len, 0)) {
+ return;
+ }
+
if (!(receiver_locks & ERTS_PROC_LOCK_MSGQ)) {
- erts_proc_lock(receiver, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_lock(receiver);
locked_msgq = 1;
}
@@ -390,8 +432,23 @@ queue_messages(Process* receiver,
return;
}
+ /*
+ * Install buffers for the outer message if the heuristic
+ * indicates that this is beneficial. It is best to do this as
+ * soon as possible to avoid as much contention as possible.
+ */
+ erts_proc_sig_queue_maybe_install_buffers(receiver, state);
+
if (last == &first->next) {
ASSERT(len == 1);
+ if (state & ERTS_PSFLG_OFF_HEAP_MSGQ) {
+ /*
+ * Flush outer signal queue buffers, if such buffers are
+ * installed, to ensure that messages from the same
+ * process cannot be reordered.
+ */
+ erts_proc_sig_queue_flush_buffers(receiver);
+ }
LINK_MESSAGE(receiver, first);
}
else {
@@ -446,7 +503,7 @@ erts_queue_message(Process* receiver, ErtsProcLocks receiver_locks,
ERL_MESSAGE_TERM(mp) = msg;
ERL_MESSAGE_FROM(mp) = from;
ERL_MESSAGE_TOKEN(mp) = am_undefined;
- queue_messages(receiver, receiver_locks, mp, &mp->next, 1);
+ queue_messages(from, receiver, receiver_locks, mp, &mp->next, 1);
}
/**
@@ -463,7 +520,7 @@ erts_queue_message_token(Process* receiver, ErtsProcLocks receiver_locks,
ERL_MESSAGE_TERM(mp) = msg;
ERL_MESSAGE_FROM(mp) = from;
ERL_MESSAGE_TOKEN(mp) = token;
- queue_messages(receiver, receiver_locks, mp, &mp->next, 1);
+ queue_messages(from, receiver, receiver_locks, mp, &mp->next, 1);
}
@@ -482,9 +539,12 @@ erts_queue_proc_message(Process* sender,
Process* receiver, ErtsProcLocks receiver_locks,
ErtsMessage* mp, Eterm msg)
{
+ if (sender == receiver)
+ (void) erts_atomic32_read_bor_nob(&sender->state,
+ ERTS_PSFLG_MAYBE_SELF_SIGS);
ERL_MESSAGE_TERM(mp) = msg;
ERL_MESSAGE_FROM(mp) = sender->common.id;
- queue_messages(receiver, receiver_locks,
+ queue_messages(sender->common.id, receiver, receiver_locks,
prepend_pending_sig_maybe(sender, receiver, mp),
&mp->next, 1);
}
@@ -495,7 +555,10 @@ erts_queue_proc_messages(Process* sender,
Process* receiver, ErtsProcLocks receiver_locks,
ErtsMessage* first, ErtsMessage** last, Uint len)
{
- queue_messages(receiver, receiver_locks,
+ if (sender == receiver)
+ (void) erts_atomic32_read_bor_nob(&sender->state,
+ ERTS_PSFLG_MAYBE_SELF_SIGS);
+ queue_messages(sender->common.id, receiver, receiver_locks,
prepend_pending_sig_maybe(sender, receiver, first),
last, len);
}
@@ -953,7 +1016,7 @@ change_off_heap_msgq(void *vcohmq)
* process to complete this change itself.
*/
cohmq = (ErtsChangeOffHeapMessageQueue *) vcohmq;
- erts_proc_sig_send_move_msgq_off_heap(NULL, cohmq->pid);
+ erts_proc_sig_send_move_msgq_off_heap(cohmq->pid);
erts_free(ERTS_ALC_T_MSGQ_CHNG, vcohmq);
}
@@ -988,8 +1051,19 @@ erts_change_message_queue_management(Process *c_p, Eterm new_state)
case am_off_heap:
break;
case am_on_heap:
- c_p->sig_qs.flags |= FS_ON_HEAP_MSGQ;
+ erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ /*
+ * The flags are changed while holding the
+ * ERTS_PROC_LOCK_MSGQ lock so that it is guaranteed that
+ * there are no messages in buffers if (c_p->sig_qs.flags
+ * & FS_ON_HEAP_MSGQ) and the ERTS_PROC_LOCK_MSGQ is held.
+ */
+ erts_proc_sig_queue_flush_and_deinstall_buffers(c_p);
+
+ c_p->sig_qs.flags |= FS_ON_HEAP_MSGQ;
c_p->sig_qs.flags &= ~FS_OFF_HEAP_MSGQ;
+
+ erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
/*
* We are not allowed to clear ERTS_PSFLG_OFF_HEAP_MSGQ
* if a off heap change is ongoing. It will be adjusted
@@ -1099,8 +1173,8 @@ void erts_factory_proc_prealloc_init(ErtsHeapFactory* factory,
{
ErlHeapFragment *bp = p->mbuf;
- /* `bp->used_size` must be set _BEFORE_ we call `HAlloc`, as that will
- * update the used size and prevent us from undoing the changes later
+ /* `heap_frags_saved_used` must be set _BEFORE_ we call `HAlloc`, as that
+ * may update `bp->used_size` and prevent us from undoing the changes later
* on. */
factory->heap_frags_saved = bp;
factory->heap_frags_saved_used = bp ? bp->used_size : 0;
@@ -1518,7 +1592,6 @@ void erts_factory_undo(ErtsHeapFactory* factory)
ASSERT(factory->original_htop <= HEAP_LIMIT(factory->p));
HEAP_TOP(factory->p) = factory->original_htop;
-
/* Fix last heap frag */
if (factory->heap_frags_saved) {
ASSERT(factory->heap_frags_saved == factory->p->mbuf);
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index 0c06bab9c2..449aa92768 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,28 @@
#define ERTS_MSG_COPY_WORDS_PER_REDUCTION 64
#endif
+/* The number of buffers have to be 64 or less because we currently
+ use a single word to implement a bitset with information about
+ non-empty buffers */
+#ifdef DEBUG
+#define ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS 64
+#define ERTS_PROC_SIG_INQ_BUFFERED_CONTENTION_INSTALL_LIMIT 250
+#define ERTS_PROC_SIG_INQ_BUFFERED_ALWAYS_TURN_ON 1
+#define ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE 2
+#define ERTS_PROC_SIG_INQ_BUFFERED_MIN_NO_ENQUEUES_TO_KEEP \
+ (ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE + \
+ ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE / 2)
+#else
+#define ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS 64
+#define ERTS_PROC_SIG_INQ_BUFFERED_CONTENTION_INSTALL_LIMIT 50
+#define ERTS_PROC_SIG_INQ_BUFFERED_ALWAYS_TURN_ON 0
+#define ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE 8192
+/* At least 1.5 enqueues per flush all op */
+#define ERTS_PROC_SIG_INQ_BUFFERED_MIN_NO_ENQUEUES_TO_KEEP \
+ (ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE + \
+ ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE / 2)
+#endif
+
struct proc_bin;
struct external_thing_;
@@ -214,7 +236,7 @@ struct erl_mesg {
/*
* The ErtsMessage struct is only one special type
* of signal. All signal structs have a common
- * begining and can be differentiated by looking
+ * beginning and can be differentiated by looking
* at the ErtsSignal 'common.tag' field.
*
* - An ordinary message will have a value
@@ -262,6 +284,7 @@ typedef struct {
typedef struct {
ErtsSignal sig;
ErtsMessage **prev_next;
+ signed char is_yield_mark;
signed char pass;
signed char set_save;
signed char in_sigq;
@@ -360,6 +383,46 @@ typedef struct {
#endif
} ErtsSignalInQueue;
+typedef union {
+ struct ___ErtsSignalInQueueBufferFields {
+ erts_mtx_t lock;
+ /*
+ * Boolean value indicateing if the buffer is alive. An
+ * enqueue attempt to a dead buffer has to be canceled
+ */
+ int alive;
+ /*
+ * The number of enqueues that has been performed to this
+ * buffer. This value is used to decide if we should adapt
+ * back to an unbuffered state
+ */
+ Uint nr_of_enqueues;
+ ErtsSignalInQueue queue;
+ } b;
+ byte align__[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(struct ___ErtsSignalInQueueBufferFields))];
+} ErtsSignalInQueueBuffer;
+
+#if ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS > 64
+#error The data structure holding information about which slots that are non-empty (the nonempty_slots field in the struct below) needs to be changed (it currently only supports up to 64 slots)
+#endif
+
+typedef struct {
+ ErtsSignalInQueueBuffer slots[ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS];
+ ErtsThrPrgrLaterOp free_item;
+ erts_atomic64_t nonempty_slots;
+ erts_atomic64_t nonmsg_slots;
+ /*
+ * dirty_refc is incremented by dirty schedulers that access the
+ * buffer array to prevent deallocation while they are accessing
+ * the buffer array. This is needed since dirty schedulers are not
+ * part of the thread progress system.
+ */
+ erts_refc_t dirty_refc;
+ Uint nr_of_rounds_left;
+ Uint nr_of_enqueues;
+ int alive;
+} ErtsSignalInQueueBufferArray;
+
typedef struct erl_trace_message_queue__ {
struct erl_trace_message_queue__ *next; /* point to the next receiver */
Eterm receiver;
@@ -443,6 +506,7 @@ void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp);
Uint erts_msg_attached_data_size_aux(ErtsMessage *msg);
+void erts_cleanup_offheap_list(struct erl_off_heap_header* first);
void erts_cleanup_offheap(ErlOffHeap *offheap);
void erts_save_message_in_proc(Process *p, ErtsMessage *msg);
Sint erts_move_messages_off_heap(Process *c_p);
@@ -451,30 +515,8 @@ Eterm erts_change_message_queue_management(Process *c_p, Eterm new_state);
void erts_cleanup_messages(ErtsMessage *mp);
-void *erts_alloc_message_ref(void);
void erts_free_message_ref(void *);
-
-#define ERTS_SMALL_FIX_MSG_SZ 10
-#define ERTS_MEDIUM_FIX_MSG_SZ 20
-#define ERTS_LARGE_FIX_MSG_SZ 30
-
-void *erts_alloc_small_message(void);
-void erts_free_small_message(void *mp);
-
-typedef struct {
- ErtsMessage m;
- Eterm data[ERTS_SMALL_FIX_MSG_SZ-1];
-} ErtsSmallFixSzMessage;
-
-typedef struct {
- ErtsMessage m;
- Eterm data[ERTS_MEDIUM_FIX_MSG_SZ-1];
-} ErtsMediumFixSzMessage;
-
-typedef struct {
- ErtsMessage m;
- Eterm data[ERTS_LARGE_FIX_MSG_SZ-1];
-} ErtsLargeFixSzMessage;
+void *erts_alloc_message_ref(void) ERTS_ATTR_MALLOC_D(erts_free_message_ref,1);
ErtsMessage *erts_try_alloc_message_on_heap(Process *pp,
erts_aint32_t *psp,
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c
index 23fd3dd566..e103807940 100644
--- a/erts/emulator/beam/erl_monitor_link.c
+++ b/erts/emulator/beam/erl_monitor_link.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,6 +51,7 @@ ml_get_key(ErtsMonLnkNode *mln)
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_TIME_OFFSET:
case ERTS_MON_TYPE_RESOURCE: {
ErtsMonitorData *mdp = erts_monitor_to_data(mln);
@@ -197,8 +198,7 @@ ml_cmp_keys(Eterm key1, Eterm key2)
if (n1->sysname != n2->sysname)
return n1->sysname < n2->sysname ? -1 : 1;
ASSERT(n1->creation != n2->creation);
- if (n1->creation != 0 && n2->creation != 0)
- return n1->creation < n2->creation ? -1 : 1;
+ return n1->creation < n2->creation ? -1 : 1;
}
ndw1 = external_thing_data_words(et1);
@@ -891,6 +891,7 @@ erts_monitor_create(Uint16 type, Eterm ref, Eterm orgn, Eterm trgt, Eterm name,
break;
}
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_RESOURCE:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_NODES: {
@@ -914,7 +915,7 @@ erts_monitor_create(Uint16 type, Eterm ref, Eterm orgn, Eterm trgt, Eterm name,
else {
/* Pending spawn_request() */
pending_flag = ERTS_ML_FLG_SPAWN_PENDING;
- /* Prepare for storage of exteral pid */
+ /* Prepare for storage of external pid */
tsz = EXTERNAL_PID_HEAP_SIZE;
/* name contains tag */
@@ -1094,6 +1095,16 @@ erts_monitor_destroy__(ErtsMonitorData *mdp)
|| ((mdp->origin.flags & ERTS_ML_FLGS_SAME)
== (mdp->u.target.flags & ERTS_ML_FLGS_SAME)));
+ if (mdp->origin.flags & ERTS_ML_STATE_ALIAS_MASK) {
+ ASSERT(mdp->origin.type == ERTS_MON_TYPE_ALIAS
+ || mdp->origin.type == ERTS_MON_TYPE_PROC
+ || mdp->origin.type == ERTS_MON_TYPE_PORT
+ || mdp->origin.type == ERTS_MON_TYPE_TIME_OFFSET
+ || mdp->origin.type == ERTS_MON_TYPE_DIST_PROC
+ || mdp->origin.type == ERTS_MON_TYPE_DIST_PORT);
+ erts_pid_ref_delete(mdp->ref);
+ }
+
switch (mdp->origin.type) {
case ERTS_MON_TYPE_ALIAS:
ERTS_ML_ASSERT(!(mdp->origin.flags & ERTS_ML_FLG_TAG));
@@ -1203,7 +1214,8 @@ erts_monitor_size(ErtsMonitor *mon)
&& mon->type != ERTS_MON_TYPE_NODES) {
if (!is_immed(mdep->md.ref))
hsz += NC_HEAP_SIZE(mdep->md.ref);
- if (mon->type == ERTS_MON_TYPE_DIST_PROC) {
+ if (mon->type == ERTS_MON_TYPE_DIST_PROC
+ || mon->type == ERTS_MON_TYPE_DIST_PORT) {
if (!is_immed(mdep->md.origin.other.item))
hsz += NC_HEAP_SIZE(mdep->md.origin.other.item);
if (!is_immed(mdep->md.u.target.other.item))
diff --git a/erts/emulator/beam/erl_monitor_link.h b/erts/emulator/beam/erl_monitor_link.h
index 4c0a47963c..c61b0dd16f 100644
--- a/erts/emulator/beam/erl_monitor_link.h
+++ b/erts/emulator/beam/erl_monitor_link.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,7 +93,8 @@
* Key: Reference
* Name: Name (atom) if by name
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process and target part of the monitor is stored in
@@ -112,7 +113,8 @@
* Key: Reference
* Name: Name (atom) if by name
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process/port and target part of the monitor is stored
@@ -130,7 +132,8 @@
* Shared:
* Key: Reference
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process and target part of the monitor is stored in
@@ -153,7 +156,8 @@
* Name: Name (atom) if by name
* Dist: Pointer to dist structure
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process and target part of the monitor is stored in
@@ -182,6 +186,30 @@
* process.
*
*
+ * --- ERTS_MON_TYPE_DIST_PORT -----------------------------------
+ *
+ * A local process (origin) monitors a port (target) on an old
+ * incarnation of the local node. Note that it is currently only
+ * for this since operations against remote ports is not
+ * supported.
+ *
+ * Origin:
+ * Other Item: Monitored port identifier
+ * Target:
+ * Other Item: Local process identifier
+ * Shared:
+ * Key: Reference
+ * Dist: NULL
+ *
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
+ *
+ * Origin part of the monitor is stored in the monitor tree of
+ * origin process and target part is currently only used when
+ * passing monitor down signal (monitors against old incarnations
+ * will always immediately trigger monitor down noproc since the
+ * process wont be alive).
+ *
* --- ERTS_MON_TYPE_RESOURCE ------------------------------------
*
* A NIF resource (origin) monitors a process (target).
@@ -425,16 +453,17 @@
#define ERTS_ML_STATE_ALIAS_DEMONITOR (((Uint16) 2) << ERTS_ML_STATE_ALIAS_SHIFT)
#define ERTS_ML_STATE_ALIAS_ONCE (((Uint16) 3) << ERTS_ML_STATE_ALIAS_SHIFT)
-#define ERTS_MON_TYPE_MAX ((Uint16) 8)
+#define ERTS_MON_TYPE_MAX ((Uint16) 9)
#define ERTS_MON_TYPE_PROC ((Uint16) 0)
#define ERTS_MON_TYPE_PORT ((Uint16) 1)
#define ERTS_MON_TYPE_TIME_OFFSET ((Uint16) 2)
#define ERTS_MON_TYPE_DIST_PROC ((Uint16) 3)
-#define ERTS_MON_TYPE_RESOURCE ((Uint16) 4)
-#define ERTS_MON_TYPE_NODE ((Uint16) 5)
-#define ERTS_MON_TYPE_NODES ((Uint16) 6)
-#define ERTS_MON_TYPE_SUSPEND ((Uint16) 7)
+#define ERTS_MON_TYPE_DIST_PORT ((Uint16) 4)
+#define ERTS_MON_TYPE_RESOURCE ((Uint16) 5)
+#define ERTS_MON_TYPE_NODE ((Uint16) 6)
+#define ERTS_MON_TYPE_NODES ((Uint16) 7)
+#define ERTS_MON_TYPE_SUSPEND ((Uint16) 8)
#define ERTS_MON_TYPE_ALIAS ERTS_MON_TYPE_MAX
#define ERTS_MON_LNK_TYPE_MAX (ERTS_MON_TYPE_MAX + ((Uint16) 3))
@@ -1166,12 +1195,13 @@ int erts_monitor_list_foreach_delete_yielding(ErtsMonitor **list,
* Can create all types of monitors
*
* When the function is called it is assumed that:
- * - 'ref' is an internal ordinary reference if type is ERTS_MON_TYPE_PROC,
- * ERTS_MON_TYPE_PORT, ERTS_MON_TYPE_TIME_OFFSET, or ERTS_MON_TYPE_RESOURCE
+ * - 'ref' is an ordinary internal reference or internal pid-reference if type
+ * is ERTS_MON_TYPE_PROC, ERTS_MON_TYPE_PORT, ERTS_MON_TYPE_DIST_PORT,
+ * ERTS_MON_TYPE_TIME_OFFSET, or ERTS_MON_TYPE_RESOURCE
* - 'ref' is NIL if type is ERTS_MON_TYPE_NODE, ERTS_MON_TYPE_NODES, or
* ERTS_MON_TYPE_SUSPEND
- * - 'ref' is and ordinary internal reference or an external reference if
- * type is ERTS_MON_TYPE_DIST_PROC
+ * - 'ref' is and ordinary internal reference, internal pid-reference or an
+ * external reference if type is ERTS_MON_TYPE_DIST_PROC
* - 'name' is an atom or NIL if type is ERTS_MON_TYPE_PROC,
* ERTS_MON_TYPE_PORT, or ERTS_MON_TYPE_DIST_PROC
* - 'name is NIL if type is ERTS_MON_TYPE_TIME_OFFSET, ERTS_MON_TYPE_RESOURCE,
@@ -1180,8 +1210,9 @@ int erts_monitor_list_foreach_delete_yielding(ErtsMonitor **list,
*
* @param[in] type ERTS_MON_TYPE_PROC, ERTS_MON_TYPE_PORT,
* ERTS_MON_TYPE_TIME_OFFSET, ERTS_MON_TYPE_DIST_PROC,
- * ERTS_MON_TYPE_RESOURCE, ERTS_MON_TYPE_NODE,
- * ERTS_MON_TYPE_NODES, or ERTS_MON_TYPE_SUSPEND
+ * ERTS_MON_TYPE_DIST_PORT, ERTS_MON_TYPE_RESOURCE,
+ * ERTS_MON_TYPE_NODE, ERTS_MON_TYPE_NODES, or
+ * ERTS_MON_TYPE_SUSPEND
*
* @param[in] ref A reference or NIL depending on type
*
@@ -1310,7 +1341,7 @@ ERTS_GLB_INLINE int erts_monitor_dist_insert(ErtsMonitor *mon, ErtsMonLnkDist *d
* @brief Delete monitor from dist monitor tree or list
*
* When the function is called it is assumed that:
- * - 'mon' monitor earler has been inserted into 'dist'
+ * - 'mon' monitor earlier has been inserted into 'dist'
* If the above is not true, bad things will happen.
*
* @param[in] mon Pointer to monitor
@@ -1735,7 +1766,7 @@ void erts_link_tree_replace(ErtsLink **root, ErtsLink *old, ErtsLink *new_);
/**
*
- * @brief Replace a link in a link tree if key already exist based on adress
+ * @brief Replace a link in a link tree if key already exist based on address
*
* Inserts the link 'lnk' in the tree if no link with the same key
* already exists in tree. If a link with the same key exists in
@@ -2162,7 +2193,7 @@ ErtsLinkData *erts_link_external_create(Uint16 type, Eterm this_, Eterm other);
*
* @param[in] id Id of the entity linked.
*
- * @returns A pointer to the link stucture.
+ * @returns A pointer to the link structure.
*/
ErtsLink *erts_link_internal_create(Uint16 type, Eterm id);
@@ -2283,7 +2314,7 @@ ERTS_GLB_INLINE int erts_link_dist_insert(ErtsLink *lnk, ErtsMonLnkDist *dist);
* @brief Delete link from dist link list
*
* When the function is called it is assumed that:
- * - 'lnk' link earler has been inserted into 'dist'
+ * - 'lnk' link earlier has been inserted into 'dist'
* If the above is not true, bad things will happen.
*
* @param[in] lnk Pointer to link
diff --git a/erts/emulator/beam/erl_msacc.c b/erts/emulator/beam/erl_msacc.c
index 73edb7b7d2..6bb50e6088 100644
--- a/erts/emulator/beam/erl_msacc.c
+++ b/erts/emulator/beam/erl_msacc.c
@@ -130,11 +130,13 @@ void erts_msacc_update_cache(ErtsMsAcc **cache) {
#ifdef ERTS_MSACC_EXTENDED_STATES
-void erts_msacc_set_bif_state(ErtsMsAcc *__erts_msacc_cache, Eterm mod, void *fn) {
+const void *erts_msacc_set_bif_state(ErtsMsAcc *__erts_msacc_cache,
+ Eterm mod,
+ const void *bif) {
#ifdef ERTS_MSACC_EXTENDED_BIFS
-#define BIF_LIST(Mod,Func,Arity,BifFuncAddr,FuncAddr,Num) \
- if (fn == &BifFuncAddr) { \
+#define BIF_LIST(Mod,Func,Arity,BifFuncAddr,FuncAddr,Num) \
+ if (bif == &BifFuncAddr) { \
ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATIC_STATE_COUNT + Num); \
} else
#include "erl_bif_list.h"
@@ -150,6 +152,8 @@ void erts_msacc_set_bif_state(ErtsMsAcc *__erts_msacc_cache, Eterm mod, void *fn
ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_BIF);
}
#endif
+
+ return bif;
}
#endif
diff --git a/erts/emulator/beam/erl_msacc.h b/erts/emulator/beam/erl_msacc.h
index 409392aad6..1907f600f5 100644
--- a/erts/emulator/beam/erl_msacc.h
+++ b/erts/emulator/beam/erl_msacc.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -414,7 +414,11 @@ void erts_msacc_set_state_m__(ErtsMsAcc *msacc, Uint new_state, int increment) {
#else
-void erts_msacc_set_bif_state(ErtsMsAcc *msacc, Eterm mod, void *addr);
+/* Enters BIF state, returning the given `bif` so we don't have to spill it in
+ * jitted code. */
+const void *erts_msacc_set_bif_state(ErtsMsAcc *msacc,
+ Eterm mod,
+ const void *bif);
#define ERTS_MSACC_PUSH_STATE_X() ERTS_MSACC_PUSH_STATE()
#define ERTS_MSACC_POP_STATE_X() ERTS_MSACC_POP_STATE()
@@ -431,9 +435,10 @@ void erts_msacc_set_bif_state(ErtsMsAcc *msacc, Eterm mod, void *addr);
#define ERTS_MSACC_SET_STATE_CACHED_M_X(state) ERTS_MSACC_SET_STATE_CACHED_M(state)
#define ERTS_MSACC_POP_STATE_M_X() ERTS_MSACC_POP_STATE_M()
#define ERTS_MSACC_PUSH_AND_SET_STATE_M_X(state) ERTS_MSACC_PUSH_AND_SET_STATE_M(state)
-#define ERTS_MSACC_SET_BIF_STATE_CACHED_X(Mod,Addr) \
- if (ERTS_MSACC_IS_ENABLED_CACHED_X()) \
- erts_msacc_set_bif_state(__erts_msacc_cache, Mod, Addr)
+#define ERTS_MSACC_SET_BIF_STATE_CACHED_X(Mod,Addr) \
+ if (ERTS_MSACC_IS_ENABLED_CACHED_X()) { \
+ (void)erts_msacc_set_bif_state(__erts_msacc_cache, Mod, Addr); \
+ }
#endif /* !ERTS_MSACC_EXTENDED_STATES */
diff --git a/erts/emulator/beam/erl_mtrace.c b/erts/emulator/beam/erl_mtrace.c
deleted file mode 100644
index 6e0a0dcff7..0000000000
--- a/erts/emulator/beam/erl_mtrace.c
+++ /dev/null
@@ -1,1268 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2018. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-/*
- * Description: Memory allocation trace. The trace is sent over a
- * tcp/ip connection.
- *
- * The trace format is not intended to be documented.
- * Instead a library for parsing the trace will be
- * distributed. This in order to more easily be able
- * to make changes in the trace format. The library
- * for parsing the trace is currently not included in
- * the OTP distribution, but will be in the future.
- *
- * Author: Rickard Green
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "global.h"
-#include "erl_sock.h"
-#include "erl_threads.h"
-#include "erl_memory_trace_protocol.h"
-#include "erl_mtrace.h"
-
-#if defined(MAXHOSTNAMELEN) && MAXHOSTNAMELEN > 255
-# undef MAXHOSTNAMELEN
-#endif
-
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 255
-#endif
-
-#define TRACE_PRINTOUTS 0
-#ifdef TRACE_PRINTOUTS
-#define MSB2BITS(X) ((((unsigned)(X))+1)*8)
-#endif
-
-static erts_mtx_t mtrace_op_mutex;
-static erts_mtx_t mtrace_buf_mutex;
-
-#define TRACE_BUF_SZ (16*1024)
-
-
-#define UI8_MSB_EHF_SZ ERTS_MT_UI8_MSB_EHDR_FLD_SZ
-#define UI16_MSB_EHF_SZ ERTS_MT_UI16_MSB_EHDR_FLD_SZ
-#define UI32_MSB_EHF_SZ ERTS_MT_UI32_MSB_EHDR_FLD_SZ
-#define UI64_MSB_EHF_SZ ERTS_MT_UI64_MSB_EHDR_FLD_SZ
-#define UI_MSB_EHF_SZ ERTS_MT_UI64_MSB_EHDR_FLD_SZ
-#define TAG_EHF_SZ ERTS_MT_TAG_EHDR_FLD_SZ
-
-#define UI8_MSB_EHF_MSK ERTS_MT_UI8_MSB_EHDR_FLD_MSK
-#define UI16_MSB_EHF_MSK ERTS_MT_UI16_MSB_EHDR_FLD_MSK
-#define UI32_MSB_EHF_MSK ERTS_MT_UI32_MSB_EHDR_FLD_MSK
-#define UI_MSB_EHF_MSK ERTS_MT_UI64_MSB_EHDR_FLD_MSK
-#define UI64_MSB_EHF_MSK ERTS_MT_UI64_MSB_EHDR_FLD_MSK
-#define TAG_EHF_MSK ERTS_MT_TAG_EHDR_FLD_MSK
-
-#define UI8_SZ (1)
-#define UI16_SZ (2)
-#define UI32_SZ (4)
-#define UI64_SZ (8)
-#ifdef ARCH_64 /* XXX:PaN Halfword? (whole file...) */
-# define UI_SZ UI64_SZ
-#else
-# define UI_SZ UI32_SZ
-#endif
-
-#define WRITE_UI8(P, V) (*(P) = (byte) ((V) & 0xff))
-
-#define WRITE_UI16(P, V) \
- ((P)[0] = (byte) (((V) >> 8) & 0xff), \
- (P)[1] = (byte) ( (V) & 0xff))
-
-#define WRITE_UI32(P, V) \
- ((P)[0] = (byte) (((V) >> 24) & 0xff), \
- (P)[1] = (byte) (((V) >> 16) & 0xff), \
- (P)[2] = (byte) (((V) >> 8) & 0xff), \
- (P)[3] = (byte) ( (V) & 0xff))
-
-#define WRITE_UI64(P, V) \
- ((P)[0] = (byte) (((V) >> 56) & 0xff), \
- (P)[1] = (byte) (((V) >> 48) & 0xff), \
- (P)[2] = (byte) (((V) >> 40) & 0xff), \
- (P)[3] = (byte) (((V) >> 32) & 0xff), \
- (P)[4] = (byte) (((V) >> 24) & 0xff), \
- (P)[5] = (byte) (((V) >> 16) & 0xff), \
- (P)[6] = (byte) (((V) >> 8) & 0xff), \
- (P)[7] = (byte) ( (V) & 0xff))
-
-#define PUT_UI8(P, V) (WRITE_UI8((P), (V)), (P) += UI8_SZ)
-#define PUT_UI16(P, V) (WRITE_UI16((P), (V)), (P) += UI16_SZ)
-#define PUT_UI32(P, V) (WRITE_UI32((P), (V)), (P) += UI32_SZ)
-#define PUT_UI64(P, V) (WRITE_UI64((P), (V)), (P) += UI64_SZ)
-
-#define PUT_VSZ_UI16(P, M, V) \
-do { \
- Uint16 v__ = (Uint16) (V); \
- if (v__ >= (((Uint16) 1) << 8)) (M) = 1; else (M) = 0; \
- switch ((M)) { \
- case 1: *((P)++) = (byte) ((v__ >> 8) & 0xff); \
- case 0: *((P)++) = (byte) ( v__ & 0xff); \
- } \
-} while (0)
-
-#define PUT_VSZ_UI32(P, M, V) \
-do { \
- Uint32 v__ = (Uint32) (V); \
- if (v__ >= (((Uint32) 1) << 16)) { \
- if (v__ >= (((Uint32) 1) << 24)) (M) = 3; else (M) = 2; \
- } else { \
- if (v__ >= (((Uint32) 1) << 8)) (M) = 1; else (M) = 0; \
- } \
- switch ((M)) { \
- case 3: *((P)++) = (byte) ((v__ >> 24) & 0xff); \
- case 2: *((P)++) = (byte) ((v__ >> 16) & 0xff); \
- case 1: *((P)++) = (byte) ((v__ >> 8) & 0xff); \
- case 0: *((P)++) = (byte) ( v__ & 0xff); \
- } \
-} while (0)
-
-#ifdef ARCH_64
-
-#define PUT_VSZ_UI64(P, M, V) \
-do { \
- Uint64 v__ = (Uint64) (V); \
- if (v__ >= (((Uint64) 1) << 32)) { \
- if (v__ >= (((Uint64) 1) << 48)) { \
- if (v__ >= (((Uint64) 1) << 56)) (M) = 7; else (M) = 6; \
- } else { \
- if (v__ >= (((Uint64) 1) << 40)) (M) = 5; else (M) = 4; \
- } \
- } else { \
- if (v__ >= (((Uint64) 1) << 16)) { \
- if (v__ >= (((Uint64) 1) << 24)) (M) = 3; else (M) = 2; \
- } else { \
- if (v__ >= (((Uint64) 1) << 8)) (M) = 1; else (M) = 0; \
- } \
- } \
- switch ((M)) { \
- case 7: *((P)++) = (byte) ((v__ >> 56) & 0xff); \
- case 6: *((P)++) = (byte) ((v__ >> 48) & 0xff); \
- case 5: *((P)++) = (byte) ((v__ >> 40) & 0xff); \
- case 4: *((P)++) = (byte) ((v__ >> 32) & 0xff); \
- case 3: *((P)++) = (byte) ((v__ >> 24) & 0xff); \
- case 2: *((P)++) = (byte) ((v__ >> 16) & 0xff); \
- case 1: *((P)++) = (byte) ((v__ >> 8) & 0xff); \
- case 0: *((P)++) = (byte) ( v__ & 0xff); \
- } \
-} while (0)
-
-#define PUT_VSZ_UI PUT_VSZ_UI64
-#else /* #ifdef ARCH_64 */
-#define PUT_VSZ_UI PUT_VSZ_UI32
-#endif /* #ifdef ARCH_64 */
-
-#define MAKE_TBUF_SZ(SZ) \
- (TRACE_BUF_SZ < (SZ) \
- ? (disable_trace(1, "Internal buffer overflow", 0), 0) \
- : (endp - tracep < (SZ) ? send_trace_buffer() : 1))
-
-
-static void disable_trace(int error, char *reason, int eno);
-static int send_trace_buffer(void);
-
-#ifdef DEBUG
-void
-check_alloc_entry(byte *sp, byte *ep,
- byte tag,
- Uint16 ct_no, int ct_no_n,
- Uint16 type, int type_n,
- UWord res, int res_n,
- Uint size, int size_n,
- Uint32 ti,int ti_n);
-void
-check_realloc_entry(byte *sp, byte *ep,
- byte tag,
- Uint16 ct_no, int ct_no_n,
- Uint16 type, int type_n,
- UWord res, int res_n,
- UWord ptr, int ptr_n,
- Uint size, int size_n,
- Uint32 ti,int ti_n);
-void
-check_free_entry(byte *sp, byte *ep,
- byte tag,
- Uint16 ct_no, int ct_no_n,
- Uint16 t_no, int t_no_n,
- UWord ptr, int ptr_n,
- Uint32 ti,int ti_n);
-void
-check_time_inc_entry(byte *sp, byte *ep,
- Uint32 secs, int secs_n,
- Uint32 usecs, int usecs_n);
-#endif
-
-
-
-int erts_mtrace_enabled;
-static erts_sock_t socket_desc;
-static byte trace_buffer[TRACE_BUF_SZ];
-static byte *tracep;
-static byte *endp;
-static SysTimeval last_tv;
-
-static ErtsAllocatorWrapper_t mtrace_wrapper;
-
-#if ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0
-#error ERTS_MTRACE_SEGMENT_ID >= ERTS_ALC_A_MIN || ERTS_MTRACE_SEGMENT_ID < 0
-#endif
-
-char* erl_errno_id(int error);
-
-#define INVALID_TIME_INC (0xffffffff)
-
-static ERTS_INLINE Uint32
-get_time_inc(void)
-{
- Sint32 secs;
- Sint32 usecs;
- Uint32 res;
- SysTimeval tv;
- sys_gettimeofday(&tv);
-
- secs = tv.tv_sec - last_tv.tv_sec;
- if (tv.tv_usec >= last_tv.tv_usec)
- usecs = tv.tv_usec - last_tv.tv_usec;
- else {
- secs--;
- usecs = 1000000 + tv.tv_usec - last_tv.tv_usec;
- }
-
- ASSERT(0 <= usecs);
- ASSERT(usecs < 1000000);
-
- if (secs < 0) {
- /* Clock stepped backwards; we pretend that no time has past. */
- res = 0;
- }
- else if (secs < ERTS_MT_TIME_INC_SECS_MASK) {
- res = ((((Uint32) secs) << ERTS_MT_TIME_INC_SECS_SHIFT)
- | (((Uint32) usecs) << ERTS_MT_TIME_INC_USECS_SHIFT));
- }
- else {
- /* Increment too large to fit in a 32-bit integer;
- put a time inc entry in trace ... */
- if (MAKE_TBUF_SZ(UI8_SZ + UI16_SZ + 2*UI32_SZ)) {
- byte *hdrp;
- Uint16 hdr;
- int secs_n, usecs_n;
-
- *(tracep++) = ERTS_MT_TIME_INC_BDY_TAG;
-
- hdrp = tracep;
- tracep += 2;
-
- PUT_VSZ_UI32(tracep, secs_n, secs);
- PUT_VSZ_UI32(tracep, usecs_n, usecs);
-
- hdr = usecs_n;
-
- hdr <<= UI32_MSB_EHF_SZ;
- hdr |= secs_n;
-
- WRITE_UI16(hdrp, hdr);
-#ifdef DEBUG
- check_time_inc_entry(hdrp-1, tracep,
- (Uint32) secs, secs_n,
- (Uint32) usecs, usecs_n);
-#endif
- res = 0;
- }
- else {
- res = INVALID_TIME_INC;
- }
- }
-
- last_tv = tv;
- return res;
-}
-
-
-static void
-disable_trace(int error, char *reason, int eno)
-{
- char *mt_dis = "Memory trace disabled";
- char *eno_str;
-
- erts_mtrace_enabled = 0;
- erts_sock_close(socket_desc);
- socket_desc = ERTS_SOCK_INVALID_SOCKET;
-
- if (eno == 0)
- erts_fprintf(stderr, "%s: %s\n", mt_dis, reason);
- else {
- eno_str = erl_errno_id(eno);
- if (sys_strcmp(eno_str, "unknown") == 0)
- erts_fprintf(stderr, "%s: %s: %d\n", mt_dis, reason, eno);
- else
- erts_fprintf(stderr, "%s: %s: %s\n", mt_dis, reason, eno_str);
- }
-}
-
-static int
-send_trace_buffer(void)
-{
- ssize_t ssz;
- size_t sz;
-
- sz = tracep - trace_buffer;
- tracep = trace_buffer;
-
- do {
- ssz = erts_sock_send(socket_desc, (void *) tracep, sz);
- if (ssz < 0) {
- int socket_errno = erts_sock_errno();
-
-#ifdef EINTR
- if (socket_errno == EINTR)
- continue;
-#endif
- disable_trace(0, "Connection lost", socket_errno);
- return 0;
- }
- if (ssz > sz) {
- disable_trace(1, "Unexpected error", 0);
- return 0;
- }
- tracep += ssz;
- sz -= ssz;
- } while (sz);
-
- tracep = trace_buffer;
- return 1;
-}
-
-#if ERTS_ALC_N_MAX >= (1 << 16)
-#error "Excessively large type numbers"
-#endif
-
-
-static int
-write_trace_header(char *nodename, char *pid, char *hostname)
-{
-#ifdef DEBUG
- byte *startp;
-#endif
- Uint16 entry_sz;
- Uint32 flags, n_len, h_len, p_len, hdr_prolog_len;
- int i, no, str_len;
- const char *str;
- struct {
- Uint32 gsec;
- Uint32 sec;
- Uint32 usec;
- } start_time;
-
- sys_gettimeofday(&last_tv);
-
- start_time.gsec = (Uint32) (last_tv.tv_sec / 1000000000);
- start_time.sec = (Uint32) (last_tv.tv_sec % 1000000000);
- start_time.usec = (Uint32) last_tv.tv_usec;
-
- if (!MAKE_TBUF_SZ(3*UI32_SZ))
- return 0;
-
- flags = 0;
-#ifdef ARCH_64
- flags |= ERTS_MT_64_BIT_FLAG;
-#endif
- flags |= ERTS_MT_CRR_INFO;
-#ifdef ERTS_CAN_TRACK_MALLOC
- flags |= ERTS_MT_SEG_CRR_INFO;
-#endif
-
- /*
- * The following 3 ui32 words *always* have to come
- * first in the trace.
- */
- PUT_UI32(tracep, ERTS_MT_START_WORD);
- PUT_UI32(tracep, ERTS_MT_MAJOR_VSN);
- PUT_UI32(tracep, ERTS_MT_MINOR_VSN);
-
- n_len = sys_strlen(nodename);
- h_len = sys_strlen(hostname);
- p_len = sys_strlen(pid);
- hdr_prolog_len = (2*UI32_SZ
- + 3*UI16_SZ
- + 3*UI32_SZ
- + 3*UI8_SZ
- + n_len
- + h_len
- + p_len);
-
- if (!MAKE_TBUF_SZ(hdr_prolog_len))
- return 0;
-
- /*
- * New stuff can be added at the end the of header prolog
- * (EOHP). The reader should skip stuff at the end, that it
- * doesn't understand.
- */
-
-#ifdef DEBUG
- startp = tracep;
-#endif
-
- PUT_UI32(tracep, hdr_prolog_len);
- PUT_UI32(tracep, flags);
- PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
- PUT_UI16(tracep, ERTS_ALC_A_MAX);
- PUT_UI16(tracep, ERTS_ALC_N_MAX);
-
- PUT_UI32(tracep, start_time.gsec);
- PUT_UI32(tracep, start_time.sec);
- PUT_UI32(tracep, start_time.usec);
-
- PUT_UI8(tracep, (byte) n_len);
- sys_memcpy((void *) tracep, (void *) nodename, n_len);
- tracep += n_len;
-
- PUT_UI8(tracep, (byte) h_len);
- sys_memcpy((void *) tracep, (void *) hostname, h_len);
- tracep += h_len;
-
- PUT_UI8(tracep, (byte) p_len);
- sys_memcpy((void *) tracep, (void *) pid, p_len);
- tracep += p_len;
-
- ASSERT(startp + hdr_prolog_len == tracep);
-
- /*
- * EOHP
- */
-
- /*
- * All tags from here on should be followed by an Uint16 size
- * field containing the total size of the entry.
- *
- * New stuff can eigther be added at the end of an entry, or
- * as a new tagged entry. The reader should skip stuff at the
- * end, that it doesn't understand.
- */
-
- for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
- Uint16 aflags = 0;
-
-#ifndef ERTS_CAN_TRACK_MALLOC
- if (i != ERTS_ALC_A_SYSTEM)
-#endif
- aflags |= ERTS_MT_ALLCTR_USD_CRR_INFO;
-
- str = ERTS_ALC_A2AD(i);
- ASSERT(str);
- str_len = sys_strlen(str);
- if (str_len >= (1 << 8)) {
- disable_trace(1, "Excessively large allocator string", 0);
- return 0;
- }
-
- entry_sz = UI8_SZ + 3*UI16_SZ + UI8_SZ;
- entry_sz += (erts_allctrs_info[i].alloc_util ? 2 : 1)*UI16_SZ;
- entry_sz += UI8_SZ + str_len;
-
- if (!MAKE_TBUF_SZ(entry_sz))
- return 0;
-
-#ifdef DEBUG
- startp = tracep;
-#endif
- PUT_UI8(tracep, ERTS_MT_ALLOCATOR_HDR_TAG);
- PUT_UI16(tracep, entry_sz);
- PUT_UI16(tracep, aflags);
- PUT_UI16(tracep, (Uint16) i);
- PUT_UI8( tracep, (byte) str_len);
- sys_memcpy((void *) tracep, (void *) str, str_len);
- tracep += str_len;
- if (erts_allctrs_info[i].alloc_util) {
- PUT_UI8(tracep, 2);
- PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
- PUT_UI16(tracep, ERTS_ALC_A_SYSTEM);
- }
- else {
- PUT_UI8(tracep, 1);
- switch (i) {
- case ERTS_ALC_A_SYSTEM:
- PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
- break;
- default:
- PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
- break;
- }
- }
- ASSERT(startp + entry_sz == tracep);
- }
-
- for (i = ERTS_ALC_N_MIN; i <= ERTS_ALC_N_MAX; i++) {
- Uint16 nflags = 0;
- str = ERTS_ALC_N2TD(i);
- ASSERT(str);
-
- str_len = sys_strlen(str);
- if (str_len >= (1 << 8)) {
- disable_trace(1, "Excessively large type string", 0);
- return 0;
- }
-
- no = ERTS_ALC_T2A(ERTS_ALC_N2T(i));
- if (!erts_allctrs_info[no].enabled)
- no = ERTS_ALC_A_SYSTEM;
- ASSERT(ERTS_ALC_A_MIN <= no && no <= ERTS_ALC_A_MAX);
-
- entry_sz = UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI16_SZ;
-
- if (!MAKE_TBUF_SZ(entry_sz))
- return 0;
-
-#ifdef DEBUG
- startp = tracep;
-#endif
- PUT_UI8(tracep, ERTS_MT_BLOCK_TYPE_HDR_TAG);
- PUT_UI16(tracep, entry_sz);
- PUT_UI16(tracep, nflags);
- PUT_UI16(tracep, (Uint16) i);
- PUT_UI8(tracep, (byte) str_len);
- sys_memcpy((void *) tracep, (void *) str, str_len);
- tracep += str_len;
- PUT_UI16(tracep, no);
- ASSERT(startp + entry_sz == tracep);
- }
-
- entry_sz = UI8_SZ + UI16_SZ;
- if (!MAKE_TBUF_SZ(entry_sz))
- return 0;
- PUT_UI8(tracep, ERTS_MT_END_OF_HDR_TAG);
- PUT_UI16(tracep, entry_sz);
-
- return 1;
-}
-
-static void mtrace_pre_lock(void);
-static void mtrace_pre_unlock(void);
-static void *mtrace_alloc(ErtsAlcType_t, void *, Uint);
-static void *mtrace_realloc(ErtsAlcType_t, void *, void *, Uint);
-static void mtrace_free(ErtsAlcType_t, void *, void *);
-
-static ErtsAllocatorFunctions_t real_allctrs[ERTS_ALC_A_MAX+1];
-
-void erts_mtrace_pre_init(void)
-{
-}
-
-void erts_mtrace_init(char *receiver, char *nodename)
-{
- char hostname[MAXHOSTNAMELEN + 1];
- char pid[21]; /* enough for a 64 bit number */
-
- socket_desc = ERTS_SOCK_INVALID_SOCKET;
- erts_mtrace_enabled = receiver != NULL;
-
- if (erts_mtrace_enabled) {
- unsigned a, b, c, d, p;
- byte ip_addr[4];
- Uint16 port;
-
- erts_mtx_init(&mtrace_buf_mutex, "mtrace_buf", NIL,
- ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_DEBUG);
- erts_mtx_init(&mtrace_op_mutex, "mtrace_op", NIL,
- ERTS_LOCK_FLAGS_PROPERTY_STATIC | ERTS_LOCK_FLAGS_CATEGORY_DEBUG);
-
- socket_desc = erts_sock_open();
- if (socket_desc == ERTS_SOCK_INVALID_SOCKET) {
- disable_trace(1, "Failed to open socket", erts_sock_errno());
- return;
- }
-
- if (5 != sscanf(receiver, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &p)
- || a >= (1 << 8) || b >= (1 << 8)|| c >= (1 << 8) || d >= (1 << 8)
- || p >= (1 << 16)) {
- disable_trace(1, "Invalid receiver address", 0);
- return;
- }
-
- ip_addr[0] = (byte) a;
- ip_addr[1] = (byte) b;
- ip_addr[2] = (byte) c;
- ip_addr[3] = (byte) d;
-
- port = (Uint16) p;
-
- if (!erts_sock_connect(socket_desc, ip_addr, 4, port)) {
- disable_trace(1, "Failed to connect to receiver",
- erts_sock_errno());
- return;
- }
- tracep = trace_buffer;
- endp = trace_buffer + TRACE_BUF_SZ;
- /* gethostname requires that the len is max(hostname) + 1 */
- if (erts_sock_gethostname(hostname, MAXHOSTNAMELEN + 1) != 0)
- hostname[0] = '\0';
- hostname[MAXHOSTNAMELEN] = '\0';
- sys_get_pid(pid, sizeof(pid));
- write_trace_header(nodename ? nodename : "", pid, hostname);
- erts_mtrace_update_heap_size();
- }
-}
-
-void
-erts_mtrace_install_wrapper_functions(void)
-{
- if (erts_mtrace_enabled) {
- int i;
- /* Install trace functions */
- ERTS_CT_ASSERT(sizeof(erts_allctrs) == sizeof(real_allctrs));
-
- sys_memcpy((void *) real_allctrs,
- (void *) erts_allctrs,
- sizeof(erts_allctrs));
-
- for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
- erts_allctrs[i].alloc = mtrace_alloc;
- erts_allctrs[i].realloc = mtrace_realloc;
- erts_allctrs[i].free = mtrace_free;
- erts_allctrs[i].extra = (void *) &real_allctrs[i];
- }
- mtrace_wrapper.lock = mtrace_pre_lock;
- mtrace_wrapper.unlock = mtrace_pre_unlock;
- erts_allctr_wrapper_prelock_init(&mtrace_wrapper);
- }
-}
-
-void
-erts_mtrace_stop(void)
-{
- ASSERT(!erts_is_allctr_wrapper_prelocked());
- erts_mtx_lock(&mtrace_op_mutex);
- erts_mtx_lock(&mtrace_buf_mutex);
- if (erts_mtrace_enabled) {
- Uint32 ti = get_time_inc();
-
- if (ti != INVALID_TIME_INC
- && MAKE_TBUF_SZ(UI8_SZ + UI16_SZ + UI32_SZ)) {
- byte *hdrp;
- Uint16 hdr;
- int ti_n;
-
- *(tracep++) = ERTS_MT_STOP_BDY_TAG;
-
- hdrp = tracep;
- tracep += 2;
-
- PUT_VSZ_UI32(tracep, ti_n, ti);
-
- hdr = ti_n;
-
- WRITE_UI16(hdrp, hdr);
-
- if(send_trace_buffer()) {
- erts_mtrace_enabled = 0;
- erts_sock_close(socket_desc);
- socket_desc = ERTS_SOCK_INVALID_SOCKET;
- }
- }
- }
- erts_mtx_unlock(&mtrace_buf_mutex);
- erts_mtx_unlock(&mtrace_op_mutex);
-}
-
-void
-erts_mtrace_exit(Uint32 exit_value)
-{
- ASSERT(!erts_is_allctr_wrapper_prelocked());
- erts_mtx_lock(&mtrace_op_mutex);
- erts_mtx_lock(&mtrace_buf_mutex);
- if (erts_mtrace_enabled) {
- Uint32 ti = get_time_inc();
-
- if (ti != INVALID_TIME_INC
- && MAKE_TBUF_SZ(UI8_SZ + UI16_SZ + 2*UI32_SZ)) {
- byte *hdrp;
- Uint16 hdr;
- int ti_n, exit_value_n;
-
- *(tracep++) = ERTS_MT_EXIT_BDY_TAG;
-
- hdrp = tracep;
- tracep += 2;
-
- PUT_VSZ_UI32(tracep, exit_value_n, exit_value);
- PUT_VSZ_UI32(tracep, ti_n, ti);
-
- hdr = ti_n;
-
- hdr <<= UI32_MSB_EHF_SZ;
- hdr |= exit_value_n;
-
- WRITE_UI16(hdrp, hdr);
-
- if(send_trace_buffer()) {
- erts_mtrace_enabled = 0;
- erts_sock_close(socket_desc);
- socket_desc = ERTS_SOCK_INVALID_SOCKET;
- }
- }
- }
- erts_mtx_unlock(&mtrace_buf_mutex);
- erts_mtx_unlock(&mtrace_op_mutex);
-}
-
-static ERTS_INLINE void
-write_alloc_entry(byte tag,
- void *res,
- ErtsAlcType_t x,
- ErtsAlcType_t y,
- Uint size)
-{
- erts_mtx_lock(&mtrace_buf_mutex);
- if (erts_mtrace_enabled) {
- Uint32 ti = get_time_inc();
-
- if (ti != INVALID_TIME_INC
- && MAKE_TBUF_SZ(UI8_SZ + 2*UI16_SZ + 2*UI_SZ + UI32_SZ)) {
- Uint16 hdr, t_no = (Uint16) x, ct_no = (Uint16) y;
- byte *hdrp;
- int t_no_n, ct_no_n = 0, res_n, size_n, ti_n;
-
- *(tracep++) = tag;
-
- hdrp = tracep;
- tracep += 2;
-
- if (tag == ERTS_MT_CRR_ALLOC_BDY_TAG) {
- PUT_VSZ_UI16(tracep, ct_no_n, ct_no);
- }
- PUT_VSZ_UI16(tracep, t_no_n, t_no);
- PUT_VSZ_UI( tracep, res_n, res);
- PUT_VSZ_UI( tracep, size_n, size);
- PUT_VSZ_UI32(tracep, ti_n, ti);
-
- hdr = ti_n;
-
- hdr <<= UI_MSB_EHF_SZ;
- hdr |= size_n;
-
- hdr <<= UI_MSB_EHF_SZ;
- hdr |= res_n;
-
- hdr <<= UI16_MSB_EHF_SZ;
- hdr |= t_no_n;
-
- if (tag == ERTS_MT_CRR_ALLOC_BDY_TAG) {
- hdr <<= UI16_MSB_EHF_SZ;
- hdr |= ct_no_n;
- }
-
- WRITE_UI16(hdrp, hdr);
-
-#if TRACE_PRINTOUTS
- print_trace_entry(tag,
- ct_no, ct_no_n,
- t_no, t_no_n,
- (Uint) res, res_n,
- 0, 0,
- size, size_n,
- ti, ti_n);
-#endif
-
-#ifdef DEBUG
- check_alloc_entry(hdrp-1, tracep,
- tag,
- ct_no, ct_no_n,
- t_no, t_no_n,
- (UWord) res, res_n,
- size, size_n,
- ti, ti_n);
-#endif
-
- }
-
- }
- erts_mtx_unlock(&mtrace_buf_mutex);
-
-}
-
-static ERTS_INLINE void
-write_realloc_entry(byte tag,
- void *res,
- ErtsAlcType_t x,
- ErtsAlcType_t y,
- void *ptr,
- Uint size)
-{
- erts_mtx_lock(&mtrace_buf_mutex);
- if (erts_mtrace_enabled) {
- Uint32 ti = get_time_inc();
-
- if (ti != INVALID_TIME_INC
- && MAKE_TBUF_SZ(UI8_SZ + 2*UI16_SZ + 3*UI_SZ + UI32_SZ)) {
- Uint16 hdr, t_no = (Uint16) x, ct_no = (Uint16) y;
- byte *hdrp;
- int t_no_n, ct_no_n = 0, res_n, ptr_n, size_n, ti_n;
-
- *(tracep++) = tag;
-
- hdrp = tracep;
- tracep += 2;
-
- if (tag == ERTS_MT_CRR_REALLOC_BDY_TAG) {
- PUT_VSZ_UI16(tracep, ct_no_n, ct_no);
- }
- PUT_VSZ_UI16(tracep, t_no_n, t_no);
- PUT_VSZ_UI( tracep, res_n, res);
- PUT_VSZ_UI( tracep, ptr_n, ptr);
- PUT_VSZ_UI( tracep, size_n, size);
- PUT_VSZ_UI32(tracep, ti_n, ti);
-
- hdr = ti_n;
-
- hdr <<= UI_MSB_EHF_SZ;
- hdr |= size_n;
-
- hdr <<= UI_MSB_EHF_SZ;
- hdr |= ptr_n;
-
- hdr <<= UI_MSB_EHF_SZ;
- hdr |= res_n;
-
- hdr <<= UI16_MSB_EHF_SZ;
- hdr |= t_no_n;
-
- if (tag == ERTS_MT_CRR_REALLOC_BDY_TAG) {
- hdr <<= UI16_MSB_EHF_SZ;
- hdr |= ct_no_n;
- }
-
- WRITE_UI16(hdrp, hdr);
-
-#if TRACE_PRINTOUTS
- print_trace_entry(tag,
- ct_no, ct_no_n,
- t_no, t_no_n,
- (Uint) res, res_n,
- (Uint) ptr, ptr_n,
- size, size_n,
- ti, ti_n);
-#endif
-
-#ifdef DEBUG
- check_realloc_entry(hdrp-1, tracep,
- tag,
- ct_no, ct_no_n,
- t_no, t_no_n,
- (UWord) res, res_n,
- (UWord) ptr, ptr_n,
- size, size_n,
- ti, ti_n);
-#endif
-
- }
- }
- erts_mtx_unlock(&mtrace_buf_mutex);
-}
-
-static ERTS_INLINE void
-write_free_entry(byte tag,
- ErtsAlcType_t x,
- ErtsAlcType_t y,
- void *ptr)
-{
- erts_mtx_lock(&mtrace_buf_mutex);
- if (erts_mtrace_enabled) {
- Uint32 ti = get_time_inc();
-
- if (ti != INVALID_TIME_INC
- && MAKE_TBUF_SZ(UI8_SZ + 2*UI16_SZ + UI_SZ + UI32_SZ)) {
- Uint16 hdr, t_no = (Uint16) x, ct_no = (Uint16) y;
- byte *hdrp;
- int t_no_n, ct_no_n = 0, ptr_n, ti_n;
-
- *(tracep++) = tag;
-
- hdrp = tracep;
- tracep += 2;
-
- if (tag == ERTS_MT_CRR_FREE_BDY_TAG) {
- PUT_VSZ_UI16(tracep, ct_no_n, ct_no);
- }
- PUT_VSZ_UI16(tracep, t_no_n, t_no);
- PUT_VSZ_UI( tracep, ptr_n, ptr);
- PUT_VSZ_UI32(tracep, ti_n, ti);
-
- hdr = ti_n;
-
- hdr <<= UI_MSB_EHF_SZ;
- hdr |= ptr_n;
-
- hdr <<= UI16_MSB_EHF_SZ;
- hdr |= t_no_n;
-
- if (tag == ERTS_MT_CRR_FREE_BDY_TAG) {
- hdr <<= UI16_MSB_EHF_SZ;
- hdr |= ct_no_n;
- }
-
- WRITE_UI16(hdrp, hdr);
-
-#if TRACE_PRINTOUTS
- print_trace_entry(tag,
- ct_no, ct_no_n,
- t_no, t_no_n,
- (Uint) 0, 0,
- (Uint) ptr, ptr_n,
- 0, 0,
- ti, ti_n);
-#endif
-
-#ifdef DEBUG
- check_free_entry(hdrp-1, tracep,
- tag,
- ct_no, ct_no_n,
- t_no, t_no_n,
- (UWord) ptr, ptr_n,
- ti, ti_n);
-#endif
- }
-
- }
- erts_mtx_unlock(&mtrace_buf_mutex);
-}
-
-static void mtrace_pre_lock(void)
-{
- erts_mtx_lock(&mtrace_op_mutex);
-}
-
-static void mtrace_pre_unlock(void)
-{
- erts_mtx_unlock(&mtrace_op_mutex);
-}
-
-
-static void *
-mtrace_alloc(ErtsAlcType_t n, void *extra, Uint size)
-{
- ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
- void *res;
-
- if (!erts_is_allctr_wrapper_prelocked()) {
- erts_mtx_lock(&mtrace_op_mutex);
- }
-
- res = (*real_af->alloc)(n, real_af->extra, size);
- write_alloc_entry(ERTS_MT_ALLOC_BDY_TAG, res, n, 0, size);
-
- if (!erts_is_allctr_wrapper_prelocked()) {
- erts_mtx_unlock(&mtrace_op_mutex);
- }
-
- return res;
-}
-
-static void *
-mtrace_realloc(ErtsAlcType_t n, void *extra, void *ptr, Uint size)
-{
- ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
- void *res;
-
- if (!erts_is_allctr_wrapper_prelocked()) {
- erts_mtx_lock(&mtrace_op_mutex);
- }
-
- res = (*real_af->realloc)(n, real_af->extra, ptr, size);
- write_realloc_entry(ERTS_MT_REALLOC_BDY_TAG, res, n, 0, ptr, size);
-
- if (!erts_is_allctr_wrapper_prelocked()) {
- erts_mtx_unlock(&mtrace_op_mutex);
- }
-
- return res;
-
-}
-
-static void
-mtrace_free(ErtsAlcType_t n, void *extra, void *ptr)
-{
- ErtsAllocatorFunctions_t *real_af = (ErtsAllocatorFunctions_t *) extra;
-
- if (!erts_is_allctr_wrapper_prelocked()) {
- erts_mtx_lock(&mtrace_op_mutex);
- }
-
- (*real_af->free)(n, real_af->extra, ptr);
- if (!erts_is_allctr_wrapper_prelocked()) {
- write_free_entry(ERTS_MT_FREE_BDY_TAG, n, 0, ptr);
- }
-
- erts_mtx_unlock(&mtrace_op_mutex);
-}
-
-
-void
-erts_mtrace_crr_alloc(void *res, ErtsAlcType_t n, ErtsAlcType_t m, Uint size)
-{
- write_alloc_entry(ERTS_MT_CRR_ALLOC_BDY_TAG, res, n, m, size);
-}
-
-void
-erts_mtrace_crr_realloc(void *res, ErtsAlcType_t n, ErtsAlcType_t m, void *ptr,
- Uint size)
-{
- write_realloc_entry(ERTS_MT_CRR_REALLOC_BDY_TAG, res, n, m, ptr, size);
-}
-
-void
-erts_mtrace_crr_free(ErtsAlcType_t n, ErtsAlcType_t m, void *ptr)
-{
- write_free_entry(ERTS_MT_CRR_FREE_BDY_TAG, n, m, ptr);
-}
-
-
-#if TRACE_PRINTOUTS
-static void
-print_trace_entry(byte tag,
- Uint16 t_no, int t_no_n,
- Uint16 ct_no, int ct_no_n,
- Uint res, int res_n,
- Uint ptr, int ptr_n,
- Uint size, int size_n,
- Uint32 ti,int ti_n)
-{
- switch (tag) {
- case ERTS_MT_ALLOC_BDY_TAG:
- fprintf(stderr,
- "{alloc, {%lu, %lu, %lu}, {%u, %u, %u, %u}}\n\r",
-
- (unsigned long) t_no, (unsigned long) res,
- (unsigned long) size,
-
- MSB2BITS(t_no_n), MSB2BITS(res_n),
- MSB2BITS(size_n), MSB2BITS(ti_n));
- break;
- case ERTS_MT_REALLOC_BDY_TAG:
- fprintf(stderr,
- "{realloc, {%lu, %lu, %lu, %lu}, {%u, %u, %u, %u, %u}}\n\r",
-
- (unsigned long) t_no, (unsigned long) res,
- (unsigned long) ptr, (unsigned long) size,
-
- MSB2BITS(t_no_n), MSB2BITS(res_n),
- MSB2BITS(ptr_n), MSB2BITS(size_n), MSB2BITS(ti_n));
- break;
- case ERTS_MT_FREE_BDY_TAG:
- fprintf(stderr,
- "{free, {%lu, %lu}, {%u, %u, %u, %u, %u}}\n\r",
-
- (unsigned long) t_no, (unsigned long) ptr,
-
- MSB2BITS(t_no_n), MSB2BITS(ptr_n), MSB2BITS(ti_n));
- break;
- case ERTS_MT_CRR_ALLOC_BDY_TAG:
- fprintf(stderr,
- "{crr_alloc, {%lu, %lu, %lu, %lu}, {%u, %u, %u, %u, %u}}\n\r",
-
- (unsigned long) ct_no, (unsigned long) t_no,
- (unsigned long) res, (unsigned long) size,
-
- MSB2BITS(ct_no_n), MSB2BITS(t_no_n),
- MSB2BITS(res_n), MSB2BITS(size_n),
- MSB2BITS(ti_n));
- break;
- case ERTS_MT_CRR_REALLOC_BDY_TAG:
- fprintf(stderr,
- "{crr_realloc, {%lu, %lu, %lu, %lu, %lu}, "
- "{%u, %u, %u, %u, %u, %u}}\n\r",
-
- (unsigned long) ct_no, (unsigned long) t_no,
- (unsigned long) res, (unsigned long) ptr,
- (unsigned long) size,
-
- MSB2BITS(ct_no_n), MSB2BITS(t_no_n),
- MSB2BITS(res_n), MSB2BITS(ptr_n),
- MSB2BITS(size_n), MSB2BITS(ti_n));
- break;
- case ERTS_MT_CRR_FREE_BDY_TAG:
- fprintf(stderr,
- "{crr_free, {%lu, %lu, %lu}, {%u, %u, %u, %u}}\n\r",
-
- (unsigned long) ct_no, (unsigned long) t_no,
- (unsigned long) ptr,
-
- MSB2BITS(ct_no_n), MSB2BITS(t_no_n),
- MSB2BITS(ptr_n), MSB2BITS(ti_n));
- break;
- default:
- fprintf(stderr, "{'\?\?\?'}\n\r");
- break;
- }
-}
-
-#endif /* #if TRACE_PRINTOUTS */
-
-#ifdef DEBUG
-
-#define GET_UI16(P) ((P) += UI16_SZ, \
- (((Uint16) (*((P) - 2) << 8)) | ((Uint16) (*((P) - 1)))))
-
-static void
-check_ui(Uint16 *hdrp, byte **pp, Uint ui, int msb,
- Uint16 f_mask, Uint16 f_size)
-{
- Uint x;
- int n;
-
- ASSERT((msb & ~f_mask) == 0);
-
- n = (int) (*hdrp & f_mask);
-
- ASSERT(n == msb);
-
- *hdrp >>= f_size;
-
- x = 0;
- switch (n) {
-#ifdef ARCH_64
- case 7: x |= *((*pp)++); x <<= 8;
- case 6: x |= *((*pp)++); x <<= 8;
- case 5: x |= *((*pp)++); x <<= 8;
- case 4: x |= *((*pp)++); x <<= 8;
-#endif
- case 3: x |= *((*pp)++); x <<= 8;
- case 2: x |= *((*pp)++); x <<= 8;
- case 1: x |= *((*pp)++); x <<= 8;
- case 0: x |= *((*pp)++); break;
- default: ASSERT(0);
- }
-
- ASSERT(x == ui);
-}
-
-
-void
-check_alloc_entry(byte *sp, byte *ep,
- byte tag,
- Uint16 ct_no, int ct_no_n,
- Uint16 t_no, int t_no_n,
- UWord res, int res_n,
- Uint size, int size_n,
- Uint32 ti,int ti_n)
-{
- byte *p = sp;
- Uint16 hdr;
-
- ASSERT(*p == tag);
- p++;
-
- hdr = GET_UI16(p);
-
- if (tag == ERTS_MT_CRR_ALLOC_BDY_TAG)
- check_ui(&hdr, &p, ct_no, ct_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ);
- check_ui(&hdr, &p, t_no, t_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ);
- check_ui(&hdr, &p, res, res_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ);
- check_ui(&hdr, &p, size, size_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ);
- check_ui(&hdr, &p, ti, ti_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ);
-
- ASSERT(hdr == 0);
- ASSERT(p == ep);
-}
-
-void
-check_realloc_entry(byte *sp, byte *ep,
- byte tag,
- Uint16 ct_no, int ct_no_n,
- Uint16 t_no, int t_no_n,
- UWord res, int res_n,
- UWord ptr, int ptr_n,
- Uint size, int size_n,
- Uint32 ti,int ti_n)
-{
- byte *p = sp;
- Uint16 hdr;
-
- ASSERT(*p == tag);
- p++;
-
- hdr = GET_UI16(p);
-
- if (tag == ERTS_MT_CRR_REALLOC_BDY_TAG)
- check_ui(&hdr, &p, ct_no, ct_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ);
- check_ui(&hdr, &p, t_no, t_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ);
- check_ui(&hdr, &p, res, res_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ);
- check_ui(&hdr, &p, ptr, ptr_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ);
- check_ui(&hdr, &p, size, size_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ);
- check_ui(&hdr, &p, ti, ti_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ);
-
- ASSERT(hdr == 0);
- ASSERT(p == ep);
-}
-
-void
-check_free_entry(byte *sp, byte *ep,
- byte tag,
- Uint16 ct_no, int ct_no_n,
- Uint16 t_no, int t_no_n,
- UWord ptr, int ptr_n,
- Uint32 ti,int ti_n)
-{
- byte *p = sp;
- Uint16 hdr;
-
- ASSERT(*p == tag);
- p++;
-
- hdr = GET_UI16(p);
-
- if (tag == ERTS_MT_CRR_FREE_BDY_TAG)
- check_ui(&hdr, &p, ct_no, ct_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ);
- check_ui(&hdr, &p, t_no, t_no_n, UI16_MSB_EHF_MSK, UI16_MSB_EHF_SZ);
- check_ui(&hdr, &p, ptr, ptr_n, UI_MSB_EHF_MSK, UI_MSB_EHF_SZ);
- check_ui(&hdr, &p, ti, ti_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ);
-
- ASSERT(hdr == 0);
- ASSERT(p == ep);
-
-}
-
-void
-check_time_inc_entry(byte *sp, byte *ep,
- Uint32 secs, int secs_n,
- Uint32 usecs, int usecs_n)
-{
- byte *p = sp;
- Uint16 hdr;
-
- ASSERT(*p == ERTS_MT_TIME_INC_BDY_TAG);
- p++;
-
- hdr = GET_UI16(p);
-
- check_ui(&hdr, &p, secs, secs_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ);
- check_ui(&hdr, &p, usecs, usecs_n, UI32_MSB_EHF_MSK, UI32_MSB_EHF_SZ);
-
- ASSERT(hdr == 0);
- ASSERT(p == ep);
-
-}
-
-#endif /* #ifdef DEBUG */
-
diff --git a/erts/emulator/beam/erl_mtrace.h b/erts/emulator/beam/erl_mtrace.h
deleted file mode 100644
index 776c70a819..0000000000
--- a/erts/emulator/beam/erl_mtrace.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifndef ERL_MTRACE_H__
-#define ERL_MTRACE_H__
-
-#include "erl_alloc_types.h"
-
-#if (defined(ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC) \
- || defined(ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC))
-#undef ERTS_CAN_TRACK_MALLOC
-#define ERTS_CAN_TRACK_MALLOC
-#endif
-
-#define ERTS_MTRACE_SEGMENT_ID ERTS_ALC_A_INVALID
-
-extern int erts_mtrace_enabled;
-
-void erts_mtrace_pre_init(void);
-void erts_mtrace_init(char *receiver, char *nodename);
-void erts_mtrace_install_wrapper_functions(void);
-void erts_mtrace_stop(void);
-void erts_mtrace_exit(Uint32 exit_value);
-
-void erts_mtrace_crr_alloc(void*, ErtsAlcType_t, ErtsAlcType_t, Uint);
-void erts_mtrace_crr_realloc(void*, ErtsAlcType_t, ErtsAlcType_t, void*, Uint);
-void erts_mtrace_crr_free(ErtsAlcType_t, ErtsAlcType_t, void*);
-
-
-void erts_mtrace_update_heap_size(void); /* Implemented in
- * ../sys/common/erl_mtrace_sys_wrap.c
- */
-
-#endif /* #ifndef ERL_MTRACE_H__ */
-
diff --git a/erts/emulator/beam/erl_nfunc_sched.c b/erts/emulator/beam/erl_nfunc_sched.c
index 79ba08876a..a1732468d3 100644
--- a/erts/emulator/beam/erl_nfunc_sched.c
+++ b/erts/emulator/beam/erl_nfunc_sched.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2016-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2016-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -130,20 +130,17 @@ erts_nfunc_schedule(Process *c_p, Process *dirty_shadow_proc,
nep->trampoline.info.mfa.module = mod;
nep->trampoline.info.mfa.function = func;
nep->trampoline.info.mfa.arity = (Uint) argc;
-#ifdef BEAMASM
- nep->trampoline.trace[0] = (BeamInstr) instr; /* call_bif || call_nif */
-#endif
- nep->trampoline.call_op = (BeamInstr) instr; /* call_bif || call_nif */
nep->trampoline.dfunc = (BeamInstr) dfunc;
nep->func = ifunc;
used_proc->arity = argc;
used_proc->freason = TRAP;
-#ifndef BEAMASM
- used_proc->i = (ErtsCodePtr)&nep->trampoline.call_op;
-#else
- ERTS_CT_ASSERT(sizeof(nep->trampoline.trace) == BEAM_ASM_FUNC_PROLOGUE_SIZE);
- used_proc->i = (ErtsCodePtr)&nep->trampoline.trace;
+
+ /* call_bif || call_nif */
+ ERTS_CT_ASSERT(sizeof(nep->trampoline.call_bif_nif) >= sizeof(instr));
+ sys_memcpy(&nep->trampoline.call_bif_nif, &instr, sizeof(instr));
+
+ used_proc->i = (ErtsCodePtr)&nep->trampoline.call_bif_nif;
ASSERT_MFA(erts_code_to_codemfa(used_proc->i));
-#endif
+
return nep;
}
diff --git a/erts/emulator/beam/erl_nfunc_sched.h b/erts/emulator/beam/erl_nfunc_sched.h
index c016bc035a..c97525ad78 100644
--- a/erts/emulator/beam/erl_nfunc_sched.h
+++ b/erts/emulator/beam/erl_nfunc_sched.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2016-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2016-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
#include "erl_process.h"
#include "bif.h"
#include "error.h"
+#include "jit/beam_asm.h"
/*
* Native function wrappers are used to schedule native functions on both
@@ -40,10 +41,10 @@ typedef struct {
struct {
ErtsCodeInfo info;
#ifdef BEAMASM
- // Code used by tracing/nif load
- BeamInstr trace[1];
+ char call_bif_nif[BEAM_ASM_NFUNC_SIZE];
+#else
+ BeamInstr call_bif_nif; /* call_bif || call_nif */
#endif
- BeamInstr call_op; /* call_bif || call_nif */
BeamInstr dfunc;
} trampoline;
@@ -176,17 +177,11 @@ erts_proc_shadow2real(Process *c_p)
#if defined(ERTS_WANT_NFUNC_SCHED_INTERNALS__) && !defined(ERTS_NFUNC_SCHED_INTERNALS__)
#define ERTS_NFUNC_SCHED_INTERNALS__
-#ifdef BEAMASM
-#define NFUNC_FIELD__ trampoline.trace
-#else
-#define NFUNC_FIELD__ trampoline.call_op
-#endif
-
#define ERTS_I_BEAM_OP_TO_NFUNC(I) \
(ASSERT(BeamIsOpCode(*(const BeamInstr*)(I), op_call_bif_W) || \
BeamIsOpCode(*(const BeamInstr*)(I), op_call_nif_WWW)), \
((ErtsNativeFunc *) (((char *) (I)) - \
- offsetof(ErtsNativeFunc, NFUNC_FIELD__))))
+ offsetof(ErtsNativeFunc, trampoline.call_bif_nif))))
#include "erl_message.h"
#include <stddef.h>
@@ -244,6 +239,8 @@ erts_flush_dirty_shadow_proc(Process *sproc)
}
c_p->off_heap.overhead += sproc->off_heap.overhead;
+
+ ASSERT(sproc->wrt_bins == NULL);
}
ERTS_GLB_INLINE void
@@ -268,6 +265,7 @@ erts_cache_dirty_shadow_proc(Process *sproc)
sproc->mbuf = NULL;
sproc->mbuf_sz = 0;
ERTS_INIT_OFF_HEAP(&sproc->off_heap);
+ sproc->wrt_bins = NULL;
}
ERTS_GLB_INLINE Process *
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 1fdaa9c9ff..5a73a53f4e 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,6 +58,7 @@
#include "erl_utils.h"
#include "erl_io_queue.h"
#include "erl_proc_sig_queue.h"
+#include "beam_common.h"
#undef ERTS_WANT_NFUNC_SCHED_INTERNALS__
#define ERTS_WANT_NFUNC_SCHED_INTERNALS__
#include "erl_nfunc_sched.h"
@@ -65,6 +66,7 @@
#define HAVE_USE_DTRACE 1
#endif
#include "jit/beam_asm.h"
+#include "erl_global_literals.h"
#include <limits.h>
#include <stddef.h> /* offsetof */
@@ -83,10 +85,10 @@ struct erl_module_nif {
*/
erts_mtx_t load_mtx; /* protects load finish from unload */
struct ErtsNifFinish_* finish;
- ErtsThrPrgrLaterOp lop;
+ ErtsCodeBarrier barrier;
void* priv_data;
- void* handle; /* "dlopen" */
+ void* handle; /* "dlopen", NULL for static linked */
struct enif_entry_t entry;
erts_refc_t dynlib_refc; /* References to loaded native code
+1 erl_module_instance
@@ -335,6 +337,7 @@ schedule(ErlNifEnv* env, NativeFunPtr direct_fp, NativeFunPtr indirect_fp,
{
ErtsNativeFunc *ep;
Process *c_p, *dirty_shadow_proc;
+ ErtsCodePtr caller;
execution_state(env, &c_p, NULL);
ASSERT(c_p);
@@ -346,14 +349,12 @@ schedule(ErlNifEnv* env, NativeFunPtr direct_fp, NativeFunPtr indirect_fp,
ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(c_p));
+ erts_inspect_frame(c_p->stop, &caller);
+
ep = erts_nfunc_schedule(c_p, dirty_shadow_proc,
c_p->current,
- cp_val(c_p->stop[0]),
- #ifdef BEAMASM
- op_call_nif_WWW,
- #else
+ caller,
BeamOpCodeAddr(op_call_nif_WWW),
- #endif
direct_fp, indirect_fp,
mod, func_name,
argc, (const Eterm *) argv);
@@ -552,22 +553,15 @@ struct enif_msg_environment_t
Process phony_proc;
};
-#if S_REDZONE == 0
-/*
- * Arrays of size zero are not allowed (although some compilers do
- * allow it). Be sure to set the array size to 1 if there is no
- * redzone to ensure that the code can be compiled with any compiler.
- */
-static Eterm phony_heap[1];
-#else
-static Eterm phony_heap[S_REDZONE];
-#endif
+static Eterm phony_heap[32];
static ERTS_INLINE void
setup_nif_env(struct enif_msg_environment_t* msg_env,
struct erl_module_nif* mod,
Process* tracee)
{
+ ASSERT(sizeof(phony_heap) > (S_REDZONE * sizeof(Eterm)));
+
msg_env->env.hp = &phony_heap[0];
msg_env->env.hp_end = &phony_heap[0];
msg_env->env.heap_frag = NULL;
@@ -646,6 +640,7 @@ void enif_clear_env(ErlNifEnv* env)
menv->env.hp = menv->env.hp_end = HEAP_TOP(p);
ASSERT(!is_offheap(&MSO(p)));
+ ASSERT(!p->wrt_bins);
}
#ifdef DEBUG
@@ -1169,7 +1164,7 @@ int enif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term)
int enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)
{
- return is_fun(term);
+ return is_any_fun(term);
}
int enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)
@@ -1217,7 +1212,6 @@ ErlNifTermType enif_term_type(ErlNifEnv* env, ERL_NIF_TERM term) {
return ERL_NIF_TERM_TYPE_BITSTRING;
case FLOAT_DEF:
return ERL_NIF_TERM_TYPE_FLOAT;
- case EXPORT_DEF:
case FUN_DEF:
return ERL_NIF_TERM_TYPE_FUN;
case BIG_DEF:
@@ -1887,39 +1881,47 @@ int enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len,
ERL_NIF_TERM enif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)
{
+ if (cnt == 0) {
+ return ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
#ifdef ERTS_NIF_ASSERT_IN_ENV
- int nr = 0;
+ int nr = 0;
#endif
- Eterm* hp = alloc_heap(env,cnt+1);
- Eterm ret = make_tuple(hp);
- va_list ap;
-
- *hp++ = make_arityval(cnt);
- va_start(ap,cnt);
- while (cnt--) {
- Eterm elem = va_arg(ap,Eterm);
- ASSERT_IN_ENV(env, elem, ++nr, "tuple");
- *hp++ = elem;
+ Eterm* hp = alloc_heap(env,cnt+1);
+ Eterm ret = make_tuple(hp);
+ va_list ap;
+
+ *hp++ = make_arityval(cnt);
+ va_start(ap,cnt);
+ while (cnt--) {
+ Eterm elem = va_arg(ap,Eterm);
+ ASSERT_IN_ENV(env, elem, ++nr, "tuple");
+ *hp++ = elem;
+ }
+ va_end(ap);
+ return ret;
}
- va_end(ap);
- return ret;
}
ERL_NIF_TERM enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)
{
+ if (cnt == 0) {
+ return ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
#ifdef ERTS_NIF_ASSERT_IN_ENV
- int nr = 0;
+ int nr = 0;
#endif
- Eterm* hp = alloc_heap(env,cnt+1);
- Eterm ret = make_tuple(hp);
- const Eterm* src = arr;
-
- *hp++ = make_arityval(cnt);
- while (cnt--) {
- ASSERT_IN_ENV(env, *src, ++nr, "tuple");
- *hp++ = *src++;
+ Eterm* hp = alloc_heap(env,cnt+1);
+ Eterm ret = make_tuple(hp);
+ const Eterm* src = arr;
+
+ *hp++ = make_arityval(cnt);
+ while (cnt--) {
+ ASSERT_IN_ENV(env, *src, ++nr, "tuple");
+ *hp++ = *src++;
+ }
+ return ret;
}
- return ret;
}
ERL_NIF_TERM enif_make_list_cell(ErlNifEnv* env, Eterm car, Eterm cdr)
@@ -2262,6 +2264,8 @@ static void deref_nifmod(struct erl_module_nif* lib)
}
}
+static ErtsStaticNif* is_static_nif_module(Eterm mod_atom);
+
static void close_dynlib(struct erl_module_nif* lib)
{
ASSERT(lib != NULL);
@@ -2275,10 +2279,11 @@ static void close_dynlib(struct erl_module_nif* lib)
lib->entry.unload(&msg_env.env, lib->priv_data);
post_nif_noproc(&msg_env);
}
- if (!erts_is_static_nif(lib->handle))
+ if (lib->handle) {
erts_sys_ddll_close(lib->handle);
+ lib->handle = NULL;
+ }
- lib->handle = NULL;
deref_nifmod(lib);
}
@@ -2601,7 +2606,8 @@ static int dtor_demonitor(ErtsMonitor* mon, void* context, Sint reds)
ASSERT(erts_monitor_is_origin(mon));
ASSERT(is_internal_pid(mon->other.item));
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(NULL, am_system, 1, mon);
+
return 1;
}
@@ -3282,12 +3288,11 @@ int enif_get_map_size(ErlNifEnv* env, ERL_NIF_TERM term, size_t *size)
ERL_NIF_TERM enif_make_new_map(ErlNifEnv* env)
{
- Eterm* hp = alloc_heap(env,MAP_HEADER_FLATMAP_SZ+1);
+ Eterm* hp = alloc_heap(env,MAP_HEADER_FLATMAP_SZ);
Eterm tup;
flatmap_t *mp;
- tup = make_tuple(hp);
- *hp++ = make_arityval(0);
+ tup = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
mp = (flatmap_t*)hp;
mp->thing_word = MAP_HEADER_FLATMAP;
mp->size = 0;
@@ -3621,7 +3626,8 @@ int enif_monitor_process(ErlNifEnv* env, void* obj, const ErlNifPid* target_pid,
rmon_refc_inc(rm);
erts_mtx_unlock(&rm->lock);
- if (!erts_proc_sig_send_monitor(&mdp->u.target, target_pid->pid)) {
+ if (!erts_proc_sig_send_monitor(NULL, am_system, &mdp->u.target,
+ target_pid->pid)) {
/* Failed to send monitor signal; cleanup... */
#ifdef DEBUG
ErtsBinary* bin = ERTS_MAGIC_BIN_FROM_UNALIGNED_DATA(rsrc);
@@ -3680,7 +3686,7 @@ int enif_demonitor_process(ErlNifEnv* env, void* obj, const ErlNifMonitor* monit
ASSERT(erts_monitor_is_origin(mon));
ASSERT(is_internal_pid(mon->other.item));
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(NULL, am_system, 1, mon);
return 0;
}
@@ -3796,7 +3802,7 @@ static int examine_iovec_term(Eterm list, UWord max_length, iovec_slice_t *resul
result->referenced_size += byte_size;
}
- result->iovec_len += 1 + byte_size / MAX_SYSIOVEC_IOVLEN;
+ result->iovec_len += (MAX_SYSIOVEC_IOVLEN - 1 + byte_size) / MAX_SYSIOVEC_IOVLEN;
}
result->sublist_length += 1;
@@ -4119,8 +4125,8 @@ SysIOVec *enif_ioq_peek(ErlNifIOQueue *q, int *iovlen)
** load_nif/2 **
***************************************************************************/
-static const ErtsCodeInfo * const * get_func_pp(const BeamCodeHeader* mod_code,
- Eterm f_atom, unsigned arity)
+static int get_func_ix(const BeamCodeHeader* mod_code,
+ Eterm f_atom, unsigned arity)
{
int n = (int) mod_code->num_functions;
int j;
@@ -4129,16 +4135,15 @@ static const ErtsCodeInfo * const * get_func_pp(const BeamCodeHeader* mod_code,
const ErtsCodeInfo* ci = mod_code->functions[j];
#ifndef BEAMASM
- ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI));
+ ASSERT(BeamIsOpCode(ci->u.op, op_i_func_info_IaaI));
#endif
- if (f_atom == ci->mfa.function
- && arity == ci->mfa.arity) {
- return &mod_code->functions[j];
+ if (f_atom == ci->mfa.function && arity == ci->mfa.arity) {
+ return j;
}
}
- return NULL;
+ return -1;
}
static Eterm mkatom(const char *str)
@@ -4319,8 +4324,7 @@ typedef struct {
{
/* data */
#ifdef BEAMASM
- BeamInstr prologue[BEAM_ASM_FUNC_PROLOGUE_SIZE / sizeof(UWord)];
- BeamInstr call_nif[10];
+ char call_nif[64];
#else
BeamInstr call_nif[4];
#endif
@@ -4384,6 +4388,12 @@ static void nif_call_table_init(void)
hash_init(ERTS_ALC_T_NIF, &erts_nif_call_tab, "nif_call_tab", 100, f);
}
+static int check_is_nifable(const BeamCodeHeader* mod_code,
+ int func_ix)
+{
+ return !mod_code->are_nifs || mod_code->are_nifs[func_ix];
+}
+
static void patch_call_nif_early(ErlNifEntry*, struct erl_module_instance*);
Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
@@ -4398,13 +4408,12 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
int i, err, encoding;
Module* module_p;
Eterm mod_atom;
- const Atom* mod_atomp;
Eterm f_atom;
const ErtsCodeMFA* caller;
ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT;
Eterm ret = am_ok;
int veto;
- int taint = 1;
+ int is_static = 0;
struct erl_module_nif* lib = NULL;
struct erl_module_instance* this_mi;
struct erl_module_instance* prev_mi;
@@ -4430,14 +4439,11 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
module_p = erts_get_module(mod_atom, erts_active_code_ix());
ASSERT(module_p != NULL);
- mod_atomp = atom_tab(atom_val(mod_atom));
{
- ErtsStaticNifEntry* sne;
- sne = erts_static_nif_get_nif_init((char*)mod_atomp->name, mod_atomp->len);
+ ErtsStaticNif* sne = is_static_nif_module(mod_atom);
if (sne != NULL) {
- init_func = sne->nif_init;
- handle = init_func;
- taint = sne->taint;
+ entry = sne->entry;
+ is_static = 1;
}
}
this_mi = &module_p->curr;
@@ -4460,7 +4466,7 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
ret = load_nif_error(c_p,"reload","NIF library already loaded"
" (reload disallowed since OTP 20).");
}
- else if (init_func == NULL &&
+ else if (!is_static &&
(err=erts_sys_ddll_open(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
const char slogan[] = "Failed to load NIF library";
if (strstr(errdesc.str, lib_name) != NULL) {
@@ -4470,14 +4476,15 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
ret = load_nif_error(c_p, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str);
}
}
- else if (init_func == NULL &&
+ else if (!is_static &&
erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
ret = load_nif_error(c_p, bad_lib, "Failed to find library init"
" function: '%s'", errdesc.str);
}
- else if ((taint ? erts_add_taint(mod_atom) : 0,
- (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) {
+ else if (!is_static &&
+ (erts_add_taint(mod_atom),
+ (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) {
ret = load_nif_error(c_p, bad_lib, "Library init-call unsuccessful");
}
else if (entry->major > ERL_NIF_MAJOR_VERSION
@@ -4521,7 +4528,7 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
erts_rwmtx_rwlock(&erts_nif_call_tab_lock);
for (i=0; i < entry->num_of_funcs; i++) {
- const ErtsCodeInfo * const * ci_pp;
+ int func_ix;
const ErtsCodeInfo* ci;
ErlNifFunc* f = &entry->funcs[i];
ErtsNifBeamStub* stub = &lib->finish->beam_stubv[i];
@@ -4529,13 +4536,19 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
stub->code_info_exec = NULL; /* end marker in case we fail */
if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1)
- || (ci_pp = get_func_pp(this_mi->code_hdr, f_atom, f->arity))==NULL) {
+ || (func_ix = get_func_ix(this_mi->code_hdr, f_atom, f->arity)) < 0) {
ret = load_nif_error(c_p,bad_lib,"Function not found %T:%s/%u",
mod_atom, f->name, f->arity);
break;
}
- ci = *ci_pp;
+ ci = this_mi->code_hdr->functions[func_ix];
+
+ if (!check_is_nifable(this_mi->code_hdr, func_ix)) {
+ ret = load_nif_error(c_p,bad_lib,"Function not declared as nif %T:%s/%u",
+ mod_atom, f->name, f->arity);
+ break;
+ }
if (f->flags != 0 &&
f->flags != ERL_NIF_DIRTY_JOB_IO_BOUND &&
@@ -4550,8 +4563,8 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
{
ErtsCodePtr curr_func, next_func;
- curr_func = erts_codeinfo_to_code((ErtsCodeInfo*)ci_pp[0]);
- next_func = erts_codeinfo_to_code((ErtsCodeInfo*)ci_pp[1]);
+ curr_func = erts_codeinfo_to_code(this_mi->code_hdr->functions[func_ix]);
+ next_func = erts_codeinfo_to_code(this_mi->code_hdr->functions[func_ix+1]);
ASSERT(!ErtsInArea(next_func,
curr_func,
@@ -4613,16 +4626,16 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
#endif
}
erts_rwmtx_rwunlock(&erts_nif_call_tab_lock);
- ASSERT(lib->finish->nstubs_hashed == lib->entry.num_of_funcs);
}
if (ret != am_ok) {
goto error;
}
+ ASSERT(lib);
+ ASSERT(lib->finish->nstubs_hashed == lib->entry.num_of_funcs);
/* Call load or upgrade:
*/
- ASSERT(lib);
env.mod_nif = lib;
lib->priv_data = NULL;
@@ -4677,13 +4690,12 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
cleanup_opened_rt();
/*
- * Now we wait thread progress, to make sure no process is still
- * executing the beam code of the NIFs, before we can patch in the
- * final fast multi word call_nif_WWW instructions.
+ * Schedule a code barrier to make sure that no process is executing
+ * the to-be-patched functions, and that the `erts_call_nif_early`
+ * breakpoints are in effect before we try to patch module code.
*/
erts_refc_inc(&lib->refc, 2);
- erts_schedule_thr_prgr_later_op(load_nif_1st_finisher, lib,
- &lib->lop);
+ erts_schedule_code_barrier(&lib->barrier, load_nif_1st_finisher, lib);
}
else {
error:
@@ -4696,7 +4708,7 @@ Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args)
}
erts_free(ERTS_ALC_T_NIF, lib);
}
- if (handle != NULL && !erts_is_static_nif(handle)) {
+ if (handle != NULL) {
erts_sys_ddll_close(handle);
}
erts_sys_ddll_free_error(&errdesc);
@@ -4727,14 +4739,17 @@ static void patch_call_nif_early(ErlNifEntry* entry,
for (i=0; i < entry->num_of_funcs; i++)
{
ErlNifFunc* f = &entry->funcs[i];
- const ErtsCodeInfo * const * ci_pp;
- ErtsCodeInfo* ci;
+ int func_ix;
+ const ErtsCodeInfo *ci_exec;
+ ErtsCodeInfo *ci_rw;
Eterm f_atom;
erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1);
- ci_pp = get_func_pp(this_mi->code_hdr, f_atom, f->arity);
- ci = erts_writable_code_ptr(this_mi, *ci_pp);
+ func_ix = get_func_ix(this_mi->code_hdr, f_atom, f->arity);
+ ci_exec = this_mi->code_hdr->functions[func_ix];
+
+ ci_rw = erts_writable_code_ptr(this_mi, ci_exec);
#ifndef BEAMASM
{
@@ -4742,14 +4757,14 @@ static void patch_call_nif_early(ErlNifEntry* entry,
BeamInstr volatile *code_ptr;
/* `ci` is writable. */
- code_ptr = (BeamInstr*)erts_codeinfo_to_code(ci);
+ code_ptr = (BeamInstr*)erts_codeinfo_to_code(ci_rw);
- if (ci->u.gen_bp) {
+ if (ci_rw->gen_bp) {
/*
* Function traced, patch the original instruction word
* Code write permission protects against racing breakpoint writes.
*/
- GenericBp* g = ci->u.gen_bp;
+ GenericBp* g = ci_rw->gen_bp;
g->orig_instr = BeamSetCodeAddr(g->orig_instr, call_nif_early);
if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint))
continue;
@@ -4761,7 +4776,7 @@ static void patch_call_nif_early(ErlNifEntry* entry,
}
#else
/* See beam_asm.h for details on how the nif load trampoline works */
- erts_asm_bp_set_flag(ci, ERTS_ASM_BP_FLAG_CALL_NIF_EARLY);
+ erts_asm_bp_set_flag(ci_rw, ci_exec, ERTS_ASM_BP_FLAG_CALL_NIF_EARLY);
#endif
}
}
@@ -4792,15 +4807,27 @@ static void load_nif_1st_finisher(void* vlib)
if (fin) {
for (i=0; i < lib->entry.num_of_funcs; i++) {
- ErtsCodeInfo *ci = fin->beam_stubv[i].code_info_rw;
+ const ErtsCodeInfo *ci_exec = fin->beam_stubv[i].code_info_exec;
+ ErtsCodeInfo *ci_rw = fin->beam_stubv[i].code_info_rw;
#ifdef BEAMASM
- char *code_ptr = (char*)erts_codeinfo_to_code(ci);
- sys_memcpy(&code_ptr[BEAM_ASM_FUNC_PROLOGUE_SIZE],
- fin->beam_stubv[i].code.call_nif,
- sizeof(fin->beam_stubv[0].code.call_nif));
+ const char *code_exec = (char*)erts_codeinfo_to_code(ci_exec);
+ char *code_rw = (char*)erts_codeinfo_to_code(ci_rw);
+ const char *src = fin->beam_stubv[i].code.call_nif;
+
+ size_t cpy_sz = sizeof(fin->beam_stubv[0].code.call_nif) -
+ BEAM_ASM_FUNC_PROLOGUE_SIZE;
+
+ sys_memcpy(&code_rw[BEAM_ASM_FUNC_PROLOGUE_SIZE],
+ &src[BEAM_ASM_FUNC_PROLOGUE_SIZE],
+ cpy_sz);
+
+ beamasm_flush_icache(&code_exec[BEAM_ASM_FUNC_PROLOGUE_SIZE],
+ cpy_sz);
#else
- BeamInstr *code_ptr = (BeamInstr*)erts_codeinfo_to_code(ci);
+ BeamInstr *code_ptr = (BeamInstr*)erts_codeinfo_to_code(ci_rw);
+
+ (void)ci_exec;
/* called function */
code_ptr[1] = fin->beam_stubv[i].code.call_nif[1];
@@ -4818,13 +4845,9 @@ static void load_nif_1st_finisher(void* vlib)
erts_mtx_unlock(&lib->load_mtx);
if (fin) {
- /*
- * A second thread progress to get a memory barrier between the
- * arguments of call_nif_WWW (written above) and the instruction word
- * itself.
- */
- erts_schedule_thr_prgr_later_op(load_nif_2nd_finisher, lib,
- &lib->lop);
+ /* Schedule a code barrier to ensure that the `call_nif_WWW` sequence
+ * is visible before we start disabling the breakpoints. */
+ erts_schedule_code_barrier(&lib->barrier, load_nif_2nd_finisher, lib);
}
else { /* Unloaded */
deref_nifmod(lib);
@@ -4849,29 +4872,36 @@ static void load_nif_2nd_finisher(void* vlib)
fin = lib->finish;
if (fin) {
for (i=0; i < lib->entry.num_of_funcs; i++) {
- ErtsCodeInfo *ci = fin->beam_stubv[i].code_info_rw;
+ const ErtsCodeInfo *ci_exec = fin->beam_stubv[i].code_info_exec;
+ ErtsCodeInfo *ci_rw = fin->beam_stubv[i].code_info_rw;
#ifndef BEAMASM
BeamInstr volatile *code_ptr;
- code_ptr = (BeamInstr*)erts_codeinfo_to_code(ci);
+ ASSERT(ci_exec == ci_rw);
+ (void)ci_exec;
+
+ code_ptr = (BeamInstr*)erts_codeinfo_to_code(ci_rw);
- if (ci->u.gen_bp) {
+ if (ci_rw->gen_bp) {
/*
* Function traced, patch the original instruction word
*/
- GenericBp* g = ci->u.gen_bp;
+ GenericBp* g = ci_rw->gen_bp;
ASSERT(BeamIsOpCode(g->orig_instr, op_call_nif_early));
g->orig_instr = BeamOpCodeAddr(op_call_nif_WWW);
- if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint))
+
+ if (BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint)) {
continue;
+ }
}
ASSERT(BeamIsOpCode(code_ptr[0], op_call_nif_early));
code_ptr[0] = BeamOpCodeAddr(op_call_nif_WWW);
#else
/* See beam_asm.h for details on how the nif load trampoline works */
- erts_asm_bp_unset_flag(ci, ERTS_ASM_BP_FLAG_CALL_NIF_EARLY);
+ erts_asm_bp_unset_flag(ci_rw, ci_exec,
+ ERTS_ASM_BP_FLAG_CALL_NIF_EARLY);
#endif
}
}
@@ -4882,13 +4912,13 @@ static void load_nif_2nd_finisher(void* vlib)
if (fin) {
UWord bytes = sizeof_ErtsNifFinish(lib->entry.num_of_funcs);
/*
- * A third and final thread progress, to make sure no one is executing
- * the call_nif_early instructions anymore, before we can deallocate
- * the beam stubs.
+ * A third and final code barrier to make that the removal of the
+ * breakpoints is visible and that no one is executing them while we
+ * remove them.
*/
- erts_schedule_thr_prgr_later_cleanup_op(load_nif_3rd_finisher, lib,
- &lib->lop,
- bytes);
+ erts_schedule_code_barrier_cleanup(&lib->barrier,
+ load_nif_3rd_finisher, lib,
+ bytes);
}
else { /* Unloaded */
deref_nifmod(lib);
@@ -4930,6 +4960,29 @@ static void erase_hashed_stubs(ErtsNifFinish* fin)
erts_rwmtx_rwunlock(&erts_nif_call_tab_lock);
}
+static void static_nifs_init(void)
+{
+ ErtsStaticNif* p;
+
+ for (p = erts_static_nif_tab; p->nif_init != NULL; p++) {
+ ASSERT(p->entry == NULL && p->mod_atom == THE_NON_VALUE);
+ p->entry = erts_sys_ddll_call_nif_init(p->nif_init);
+ p->mod_atom = mkatom(p->entry->name);
+ if (p->taint)
+ erts_add_taint(p->mod_atom);
+ }
+}
+
+static ErtsStaticNif* is_static_nif_module(Eterm mod_atom)
+{
+ ErtsStaticNif* p;
+ for (p = erts_static_nif_tab; p->nif_init != NULL; p++)
+ if (mod_atom == p->mod_atom)
+ return p;
+ return NULL;
+}
+
+
void
erts_unload_nif(struct erl_module_nif* lib)
{
@@ -4984,6 +5037,7 @@ void erl_nif_init()
resource_type_list.name = THE_NON_VALUE;
nif_call_table_init();
+ static_nifs_init();
}
int erts_nif_get_funcs(struct erl_module_nif* mod,
@@ -5025,6 +5079,9 @@ Eterm erts_nif_call_function(Process *p, Process *tracee,
ErlHeapFragment *orig_hf = MBUF(p);
ErlOffHeap orig_oh = MSO(p);
Eterm *orig_htop = HEAP_TOP(p);
+#ifdef DEBUG
+ struct erl_off_heap_header* orig_wrt_bins = p->wrt_bins;
+#endif
ASSERT(is_internal_pid(p->common.id));
MBUF(p) = NULL;
clear_offheap(&MSO(p));
@@ -5050,6 +5107,7 @@ Eterm erts_nif_call_function(Process *p, Process *tracee,
MBUF(p) = orig_hf;
MSO(p) = orig_oh;
HEAP_TOP(p) = orig_htop;
+ ASSERT(p->wrt_bins == orig_wrt_bins);
} else {
/* Nif call was done without a process context,
so we create a phony one. */
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index e7858a5e3a..a9a81483f6 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -335,6 +335,10 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
#endif
+#ifdef STATIC_ERLANG_NIF_LIBNAME
+# define STATIC_ERLANG_NIF
+#endif
+
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) && !defined(STATIC_ERLANG_NIF)
# define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME)
# include "erl_nif_api_funcs.h"
@@ -342,6 +346,16 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
#else /* non windows or included from emulator itself */
+/* Redundant declaration of deallocator functions as they are referred to by
+ * __attribute__(malloc) of allocator functions and we cannot change
+ * the declaration order in erl_nif_api_funcs.h due to Windows. */
+extern void enif_free(void* ptr);
+extern void enif_mutex_destroy(ErlNifMutex *mtx);
+extern void enif_cond_destroy(ErlNifCond *cnd);
+extern void enif_rwlock_destroy(ErlNifRWLock *rwlck);
+extern void enif_thread_opts_destroy(ErlNifThreadOpts *opts);
+extern void enif_ioq_destroy(ErlNifIOQueue *q);
+
# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
# include "erl_nif_api_funcs.h"
# undef ERL_NIF_API_FUNC_DECL
@@ -365,12 +379,23 @@ extern TWinDynNifCallbacks WinDynNifCallbacks;
# endif
#endif
+
#ifdef STATIC_ERLANG_NIF
-# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(ERL_NIF_INIT_ARGS)
+# ifdef STATIC_ERLANG_NIF_LIBNAME
+# define ERL_NIF_INIT_NAME(MODNAME) ERL_NIF_INIT_NAME2(STATIC_ERLANG_NIF_LIBNAME)
+# define ERL_NIF_INIT_NAME2(LIB) ERL_NIF_INIT_NAME3(LIB)
+# define ERL_NIF_INIT_NAME3(LIB) LIB ## _nif_init
+# else
+# define ERL_NIF_INIT_NAME(MODNAME) MODNAME ## _nif_init
+# endif
+# define ERL_NIF_INIT_DECL(MODNAME) \
+ ErlNifEntry* ERL_NIF_INIT_NAME(MODNAME)(ERL_NIF_INIT_ARGS)
#else
-# define ERL_NIF_INIT_DECL(MODNAME) ERL_NIF_INIT_EXPORT ErlNifEntry* nif_init(ERL_NIF_INIT_ARGS)
+# define ERL_NIF_INIT_DECL(MODNAME) \
+ ERL_NIF_INIT_EXPORT ErlNifEntry* nif_init(ERL_NIF_INIT_ARGS)
#endif
+
#ifdef __cplusplus
}
# define ERL_NIF_INIT_PROLOGUE extern "C" {
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index 27fa953099..f9004eb64b 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2009-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2009-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
*/
#ifdef ERL_NIF_API_FUNC_DECL
ERL_NIF_API_FUNC_DECL(void*,enif_priv_data,(ErlNifEnv*));
-ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size));
+ERL_NIF_API_FUNC_DECL(void*,enif_alloc,(size_t size) ERL_NAPI_ATTR_MALLOC_USD(1,enif_free,1));
ERL_NIF_API_FUNC_DECL(void,enif_free,(void* ptr));
ERL_NIF_API_FUNC_DECL(int,enif_is_atom,(ErlNifEnv*, ERL_NIF_TERM term));
ERL_NIF_API_FUNC_DECL(int,enif_is_binary,(ErlNifEnv*, ERL_NIF_TERM term));
@@ -60,17 +60,17 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list_cell,(ErlNifEnv* env, ERL_NIF_
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string,(ErlNifEnv* env, const char* string, ErlNifCharEncoding));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_ref,(ErlNifEnv* env));
-ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name));
+ERL_NIF_API_FUNC_DECL(ErlNifMutex*,enif_mutex_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_mutex_destroy,1));
ERL_NIF_API_FUNC_DECL(void,enif_mutex_destroy,(ErlNifMutex *mtx));
ERL_NIF_API_FUNC_DECL(int,enif_mutex_trylock,(ErlNifMutex *mtx));
ERL_NIF_API_FUNC_DECL(void,enif_mutex_lock,(ErlNifMutex *mtx));
ERL_NIF_API_FUNC_DECL(void,enif_mutex_unlock,(ErlNifMutex *mtx));
-ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name));
+ERL_NIF_API_FUNC_DECL(ErlNifCond*,enif_cond_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_cond_destroy,1));
ERL_NIF_API_FUNC_DECL(void,enif_cond_destroy,(ErlNifCond *cnd));
ERL_NIF_API_FUNC_DECL(void,enif_cond_signal,(ErlNifCond *cnd));
ERL_NIF_API_FUNC_DECL(void,enif_cond_broadcast,(ErlNifCond *cnd));
ERL_NIF_API_FUNC_DECL(void,enif_cond_wait,(ErlNifCond *cnd, ErlNifMutex *mtx));
-ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name));
+ERL_NIF_API_FUNC_DECL(ErlNifRWLock*,enif_rwlock_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_rwlock_destroy,1));
ERL_NIF_API_FUNC_DECL(void,enif_rwlock_destroy,(ErlNifRWLock *rwlck));
ERL_NIF_API_FUNC_DECL(int,enif_rwlock_tryrlock,(ErlNifRWLock *rwlck));
ERL_NIF_API_FUNC_DECL(void,enif_rwlock_rlock,(ErlNifRWLock *rwlck));
@@ -82,7 +82,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_tsd_key_create,(char *name, ErlNifTSDKey *key));
ERL_NIF_API_FUNC_DECL(void,enif_tsd_key_destroy,(ErlNifTSDKey key));
ERL_NIF_API_FUNC_DECL(void,enif_tsd_set,(ErlNifTSDKey key, void *data));
ERL_NIF_API_FUNC_DECL(void*,enif_tsd_get,(ErlNifTSDKey key));
-ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name));
+ERL_NIF_API_FUNC_DECL(ErlNifThreadOpts*,enif_thread_opts_create,(char *name) ERL_NAPI_ATTR_MALLOC_D(enif_thread_opts_destroy,1));
ERL_NIF_API_FUNC_DECL(void,enif_thread_opts_destroy,(ErlNifThreadOpts *opts));
ERL_NIF_API_FUNC_DECL(int,enif_thread_create,(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts));
ERL_NIF_API_FUNC_DECL(ErlNifTid,enif_thread_self,(void));
@@ -90,7 +90,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_equal_tids,(ErlNifTid tid1, ErlNifTid tid2));
ERL_NIF_API_FUNC_DECL(void,enif_thread_exit,(void *resp));
ERL_NIF_API_FUNC_DECL(int,enif_thread_join,(ErlNifTid, void **respp));
-ERL_NIF_API_FUNC_DECL(void*,enif_realloc,(void* ptr, size_t size));
+ERL_NIF_API_FUNC_DECL(void*,enif_realloc,(void* ptr, size_t size) ERL_NAPI_ATTR_ALLOC_SIZE(2));
ERL_NIF_API_FUNC_DECL(void,enif_system_info,(ErlNifSysInfo *sip, size_t si_size));
ERL_NIF_API_FUNC_DECL(int,enif_fprintf,(FILE* filep, const char *format, ...));
ERL_NIF_API_FUNC_DECL(int,enif_inspect_iolist_as_binary,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifBinary* bin));
@@ -108,7 +108,7 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_tuple_from_array,(ErlNifEnv*, const
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_list_from_array,(ErlNifEnv*, const ERL_NIF_TERM arr[], unsigned cnt));
ERL_NIF_API_FUNC_DECL(int,enif_is_empty_list,(ErlNifEnv*, ERL_NIF_TERM term));
ERL_NIF_API_FUNC_DECL(ErlNifResourceType*,enif_open_resource_type,(ErlNifEnv*, const char* module_str, const char* name_str, void (*dtor)(ErlNifEnv*,void *), ErlNifResourceFlags flags, ErlNifResourceFlags* tried));
-ERL_NIF_API_FUNC_DECL(void*,enif_alloc_resource,(ErlNifResourceType* type, size_t size));
+ERL_NIF_API_FUNC_DECL(void *, enif_alloc_resource, (ErlNifResourceType *type, size_t size) ERL_NAPI_ATTR_MALLOC_US(2));
ERL_NIF_API_FUNC_DECL(void,enif_release_resource,(void* obj));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_resource,(ErlNifEnv*, void* obj));
ERL_NIF_API_FUNC_DECL(int,enif_get_resource,(ErlNifEnv*, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp));
@@ -121,7 +121,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_get_list_length,(ErlNifEnv* env, ERL_NIF_TERM ter
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM, enif_make_atom_len,(ErlNifEnv* env, const char* name, size_t len));
ERL_NIF_API_FUNC_DECL(int, enif_make_existing_atom_len,(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding));
ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_string_len,(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding));
-ERL_NIF_API_FUNC_DECL(ErlNifEnv*,enif_alloc_env,(void));
+ERL_NIF_API_FUNC_DECL(ErlNifEnv*,enif_alloc_env,(void) ERL_NAPI_ATTR_WUR);
ERL_NIF_API_FUNC_DECL(void,enif_free_env,(ErlNifEnv* env));
ERL_NIF_API_FUNC_DECL(void,enif_clear_env,(ErlNifEnv* env));
ERL_NIF_API_FUNC_DECL(int,enif_send,(ErlNifEnv* env, const ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg));
@@ -184,7 +184,7 @@ ERL_NIF_API_FUNC_DECL(ErlNifUInt64,enif_hash,(ErlNifHash type, ERL_NIF_TERM term
ERL_NIF_API_FUNC_DECL(int, enif_whereis_pid, (ErlNifEnv *env, ERL_NIF_TERM name, ErlNifPid *pid));
ERL_NIF_API_FUNC_DECL(int, enif_whereis_port, (ErlNifEnv *env, ERL_NIF_TERM name, ErlNifPort *port));
-ERL_NIF_API_FUNC_DECL(ErlNifIOQueue *,enif_ioq_create,(ErlNifIOQueueOpts opts));
+ERL_NIF_API_FUNC_DECL(ErlNifIOQueue *,enif_ioq_create,(ErlNifIOQueueOpts opts) ERL_NAPI_ATTR_MALLOC_D(enif_ioq_destroy,1));
ERL_NIF_API_FUNC_DECL(void,enif_ioq_destroy,(ErlNifIOQueue *q));
ERL_NIF_API_FUNC_DECL(int,enif_ioq_enq_binary,(ErlNifIOQueue *q, ErlNifBinary *bin, size_t skip));
diff --git a/erts/emulator/beam/erl_node_container_utils.h b/erts/emulator/beam/erl_node_container_utils.h
index 56ba8bbdb9..a92f031971 100644
--- a/erts/emulator/beam/erl_node_container_utils.h
+++ b/erts/emulator/beam/erl_node_container_utils.h
@@ -58,7 +58,7 @@
* are used as 'serial'. In the "emulator interface" (external format,
* list_to_pid, etc) the least significant 15 bits are presented as
* 'number' and the most significant 3 bits are presented as 'serial',
- * though. The makro internal_pid_index() can be used for retrieving
+ * though. The macro internal_pid_index() can be used for retrieving
* index into the process table. Do *not* use the result from
* pid_number() as an index into the process table. The pid_number() and
* pid_serial() (and friends) fetch the old fixed size 'number' and
@@ -106,7 +106,7 @@
*/
#define dist_entry_channel_no(x) \
((x) == erts_this_dist_entry \
- ? ((Uint) 0) \
+ ? ((Uint) ERST_INTERNAL_CHANNEL_NO) \
: (ASSERT(is_atom((x)->sysname)), \
(Uint) atom_val((x)->sysname)))
#define internal_channel_no(x) ((Uint) ERST_INTERNAL_CHANNEL_NO)
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 912caf5ace..2bec8ff20e 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -152,9 +152,13 @@ dist_table_alloc(void *dep_tmpl)
Eterm sysname;
Binary *bin;
DistEntry *dep;
+ Uint32 init_connection_id;
erts_rwmtx_opt_t rwmtx_opt = ERTS_RWMTX_OPT_DEFAULT_INITER;
rwmtx_opt.type = ERTS_RWMTX_TYPE_FREQUENT_READ;
+ init_connection_id = (Uint32) erts_get_monotonic_time(NULL);
+ init_connection_id &= ERTS_DIST_CON_ID_MASK;
+
sysname = ((DistEntry *) dep_tmpl)->sysname;
bin = erts_create_magic_binary_x(sizeof(DistEntry),
@@ -175,7 +179,7 @@ dist_table_alloc(void *dep_tmpl)
dep->creation = 0; /* undefined */
dep->cid = NIL;
erts_atomic_init_nob(&dep->input_handler, (erts_aint_t) NIL);
- dep->connection_id = 0;
+ dep->connection_id = init_connection_id;
dep->state = ERTS_DE_STATE_IDLE;
dep->pending_nodedown = 0;
dep->suspended_nodeup = NULL;
@@ -187,6 +191,8 @@ dist_table_alloc(void *dep_tmpl)
erts_mtx_init(&dep->qlock, "dist_entry_out_queue", sysname,
ERTS_LOCK_FLAGS_CATEGORY_DISTRIBUTION);
erts_atomic32_init_nob(&dep->qflgs, 0);
+ erts_atomic32_init_nob(&dep->notify, 0);
+ erts_atomic_init_nob(&dep->total_qsize, 0);
erts_atomic_init_nob(&dep->qsize, 0);
erts_atomic64_init_nob(&dep->in, 0);
erts_atomic64_init_nob(&dep->out, 0);
@@ -725,8 +731,6 @@ erts_set_dist_entry_pending(DistEntry *dep)
void
erts_set_dist_entry_connected(DistEntry *dep, Eterm cid, Uint64 flags)
{
- erts_aint32_t set_qflgs;
-
ASSERT(dep->mld);
ERTS_LC_ASSERT(erts_lc_is_de_rwlocked(dep));
@@ -763,9 +767,6 @@ erts_set_dist_entry_connected(DistEntry *dep, Eterm cid, Uint64 flags)
erts_atomic64_set_nob(&dep->in, 0);
erts_atomic64_set_nob(&dep->out, 0);
- set_qflgs = (is_internal_port(cid) ?
- ERTS_DE_QFLG_PORT_CTRL : ERTS_DE_QFLG_PROC_CTRL);
- erts_atomic32_read_bor_nob(&dep->qflgs, set_qflgs);
if(flags & DFLAG_PUBLISHED) {
dep->next = erts_visible_dist_entries;
@@ -1567,6 +1568,20 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id)
}
}
+static ERTS_INLINE ErlHeapFragment *
+get_hidden_heap_frag(Eterm val)
+{
+ ErlHeapFragment *hfp;
+ if (is_immed(val))
+ hfp = NULL;
+ else {
+ ASSERT(is_CP(val));
+ hfp = (ErlHeapFragment *) cp_val(val);
+ ASSERT(hfp->alloc_size == hfp->used_size + 1);
+ }
+ return hfp;
+}
+
static void insert_monitor_data(ErtsMonitor *mon, int type, Eterm id)
{
ErtsMonitorData *mdp = erts_monitor_to_data(mon);
@@ -1581,6 +1596,23 @@ static void insert_monitor_data(ErtsMonitor *mon, int type, Eterm id)
oh.first = mdep->uptr.ohhp;
insert_offheap(&oh, type, id);
}
+ if (mdp->origin.flags & ERTS_ML_FLG_TAG) {
+ ErlHeapFragment *hfp;
+ Eterm tag_storage;
+ if (mdp->origin.flags & ERTS_ML_FLG_EXTENDED)
+ tag_storage = ((ErtsMonitorDataExtended *) mdp)->heap[0];
+ else
+ tag_storage = ((ErtsMonitorDataTagHeap *) mdp)->heap[0];
+ hfp = get_hidden_heap_frag(tag_storage);
+ if (hfp)
+ insert_offheap(&hfp->off_heap, type, id);
+ }
+ if (mdp->origin.flags & ERTS_ML_FLG_SPAWN_PENDING) {
+ ErtsMonitorDataExtended *mdep = (ErtsMonitorDataExtended *) mdp;
+ ErlHeapFragment *hfp = get_hidden_heap_frag(mdep->u.name);
+ if (hfp)
+ insert_offheap(&hfp->off_heap, type, id);
+ }
}
}
mdp->origin.flags |= ERTS_ML_FLG_DBG_VISITED;
@@ -1610,6 +1642,9 @@ insert_dist_monitors(DistEntry *dep)
erts_monitor_tree_foreach(dep->mld->orig_name_monitors,
insert_monitor,
(void *) &dep->sysname);
+ erts_monitor_tree_foreach(dep->mld->dist_pend_spawn_exit,
+ insert_monitor,
+ (void *) &dep->sysname);
}
}
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index 937bfb1d9e..c12198a23c 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,15 +77,9 @@ enum dist_entry_state {
#define ERTS_DE_QFLG_BUSY (((erts_aint32_t) 1) << 0)
#define ERTS_DE_QFLG_EXIT (((erts_aint32_t) 1) << 1)
-#define ERTS_DE_QFLG_REQ_INFO (((erts_aint32_t) 1) << 2)
-#define ERTS_DE_QFLG_PORT_CTRL (((erts_aint32_t) 1) << 3)
-#define ERTS_DE_QFLG_PROC_CTRL (((erts_aint32_t) 1) << 4)
#define ERTS_DE_QFLGS_ALL (ERTS_DE_QFLG_BUSY \
- | ERTS_DE_QFLG_EXIT \
- | ERTS_DE_QFLG_REQ_INFO \
- | ERTS_DE_QFLG_PORT_CTRL \
- | ERTS_DE_QFLG_PROC_CTRL)
+ | ERTS_DE_QFLG_EXIT)
#if defined(ARCH_64)
#define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713f713f713UL)
@@ -105,6 +99,7 @@ struct ErtsDistOutputBuf_ {
* iov[2 ... vsize-1] data
*/
ErlIOVec *eiov;
+ int ignore_busy;
};
struct ErtsDistOutputBufsContainer_ {
@@ -153,7 +148,9 @@ struct dist_entry_ {
erts_mtx_t qlock; /* Protects qflgs and out_queue */
erts_atomic32_t qflgs;
- erts_atomic_t qsize;
+ erts_atomic32_t notify; /* User wants queue notification? */
+ erts_atomic_t qsize; /* Size of data in queue respecting busy dist */
+ erts_atomic_t total_qsize; /* Total size of data in queue */
erts_atomic64_t in;
erts_atomic64_t out;
ErtsDistOutputQueue out_queue;
@@ -200,7 +197,7 @@ Accs = lists:foldl(fun({V,<<"ERL_NODE_INC">>,_},M) -> Val = maps:get(V,M,0), M#{
lists:usort(lists:filter(fun({V,N}) -> N /= 0 end, maps:to_list(Accs))).
* There are bound to be bugs in the the instrumentation code, but
- * atleast this is a place to start when hunting refc bugs.
+ * at least this is a place to start when hunting refc bugs.
*
*/
#ifdef ERL_NODE_BOOKKEEP
diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c
index 27ecee8d09..26a2231749 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1326,22 +1326,22 @@ erts_port_task_abort(ErtsPortTaskHandle *pthp)
res = - 1; /* Task already aborted, executing, or executed */
else {
reset_port_task_handle(pthp);
-
#if ERTS_POLL_USE_SCHEDULER_POLLING
- switch (ptp->type) {
- case ERTS_PORT_TASK_INPUT:
- case ERTS_PORT_TASK_OUTPUT:
- if (ptp->u.alive.td.io.is_scheduler_event) {
- ASSERT(erts_atomic_read_nob(
- &erts_port_task_outstanding_io_tasks) > 0);
- erts_atomic_dec_relb(&erts_port_task_outstanding_io_tasks);
+ if (erts_sched_poll_enabled()) {
+ switch (ptp->type) {
+ case ERTS_PORT_TASK_INPUT:
+ case ERTS_PORT_TASK_OUTPUT:
+ if (ptp->u.alive.td.io.is_scheduler_event) {
+ ASSERT(erts_atomic_read_nob(
+ &erts_port_task_outstanding_io_tasks) > 0);
+ erts_atomic_dec_relb(&erts_port_task_outstanding_io_tasks);
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
- }
+ }
#endif
-
res = 0;
}
}
@@ -1844,16 +1844,14 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
}
ERTS_MSACC_POP_STATE_M();
-
#if ERTS_POLL_USE_SCHEDULER_POLLING
- if (io_tasks_executed) {
+ if (erts_sched_poll_enabled() && io_tasks_executed) {
ASSERT(erts_atomic_read_nob(&erts_port_task_outstanding_io_tasks)
>= io_tasks_executed);
erts_atomic_add_relb(&erts_port_task_outstanding_io_tasks,
-1*io_tasks_executed);
}
#endif
-
ASSERT(runq == erts_get_runq_port(pp));
active = finalize_exec(pp, &execq, processing_busy_q);
diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c
index 9f020559d0..24d6032012 100644
--- a/erts/emulator/beam/erl_printf_term.c
+++ b/erts/emulator/beam/erl_printf_term.c
@@ -644,58 +644,61 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) {
}
}
break;
- case EXPORT_DEF:
- {
- Export* ep = *((Export **) (export_val(wobj) + 1));
- long tdcount;
- int tres;
-
- PRINT_STRING(res, fn, arg, "fun ");
-
- /* We pass a temporary 'dcount' and adjust the real one later to ensure
- * that the fun doesn't get split up between the module and function
- * name. */
- tdcount = MAX_ATOM_SZ_LIMIT;
- tres = print_atom_name(fn, arg, ep->info.mfa.module, &tdcount);
- if (tres < 0) {
- res = tres;
- goto L_done;
- }
- *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount);
- res += tres;
+ case FUN_DEF:
+ {
+ ErlFunThing *funp = (ErlFunThing *) fun_val(wobj);
+
+ if (is_local_fun(funp)) {
+ ErlFunEntry *fe = funp->entry.fun;
+ Atom *ap = atom_tab(atom_val(fe->module));
+
+ PRINT_STRING(res, fn, arg, "#Fun<");
+ PRINT_BUF(res, fn, arg, ap->name, ap->len);
+ PRINT_CHAR(res, fn, arg, '.');
+ PRINT_SWORD(res, fn, arg, 'd', 0, 1,
+ (ErlPfSWord) fe->old_index);
+ PRINT_CHAR(res, fn, arg, '.');
+ PRINT_SWORD(res, fn, arg, 'd', 0, 1,
+ (ErlPfSWord) fe->old_uniq);
+ PRINT_CHAR(res, fn, arg, '>');
+ } else {
+ Export* ep = funp->entry.exp;
+ long tdcount;
+ int tres;
+
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+
+ PRINT_STRING(res, fn, arg, "fun ");
+
+ /* We pass a temporary 'dcount' and adjust the real one
+ * later to ensure that the fun doesn't get split up
+ * between the module and function name. */
+ tdcount = MAX_ATOM_SZ_LIMIT;
+ tres = print_atom_name(fn, arg, ep->info.mfa.module, &tdcount);
+ if (tres < 0) {
+ res = tres;
+ goto L_done;
+ }
+ *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount);
+ res += tres;
- PRINT_CHAR(res, fn, arg, ':');
+ PRINT_CHAR(res, fn, arg, ':');
- tdcount = MAX_ATOM_SZ_LIMIT;
- tres = print_atom_name(fn, arg, ep->info.mfa.function, &tdcount);
- if (tres < 0) {
- res = tres;
- goto L_done;
- }
- *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount);
- res += tres;
-
- PRINT_CHAR(res, fn, arg, '/');
- PRINT_SWORD(res, fn, arg, 'd', 0, 1,
- (ErlPfSWord) ep->info.mfa.arity);
- }
- break;
- case FUN_DEF:
- {
- ErlFunThing *funp = (ErlFunThing *) fun_val(wobj);
- Atom *ap = atom_tab(atom_val(funp->fe->module));
+ tdcount = MAX_ATOM_SZ_LIMIT;
+ tres = print_atom_name(fn, arg, ep->info.mfa.function, &tdcount);
+ if (tres < 0) {
+ res = tres;
+ goto L_done;
+ }
+ *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount);
+ res += tres;
- PRINT_STRING(res, fn, arg, "#Fun<");
- PRINT_BUF(res, fn, arg, ap->name, ap->len);
- PRINT_CHAR(res, fn, arg, '.');
- PRINT_SWORD(res, fn, arg, 'd', 0, 1,
- (ErlPfSWord) funp->fe->old_index);
- PRINT_CHAR(res, fn, arg, '.');
- PRINT_SWORD(res, fn, arg, 'd', 0, 1,
- (ErlPfSWord) funp->fe->old_uniq);
- PRINT_CHAR(res, fn, arg, '>');
- }
- break;
+ PRINT_CHAR(res, fn, arg, '/');
+ PRINT_SWORD(res, fn, arg, 'd', 0, 1,
+ (ErlPfSWord) ep->info.mfa.arity);
+ }
+ }
+ break;
case MAP_DEF: {
Eterm *head = boxed_val(wobj);
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index 83b6991809..d2799bdb91 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -216,11 +216,25 @@ typedef struct {
} ErtsProcSigRPC;
typedef struct {
+ ErtsRecvMarker next;
+ ErtsRecvMarker last;
+} ErtsYieldAdjMsgQ;
+
+typedef struct {
+ ErtsYieldAdjMsgQ *yield;
Eterm requester;
Eterm request_id;
} ErtsCLAData;
-static void wait_handle_signals(Process *c_p);
+typedef struct {
+ ErtsYieldAdjMsgQ *yield;
+} ErtsAdjOffHeapMsgQData;
+
+typedef struct {
+ ErtsMessage *first;
+ ErtsMessage **last;
+} ErtsSavedNMSignals;
+
static void wake_handle_signals(Process *proc);
static int handle_msg_tracing(Process *c_p,
@@ -243,17 +257,28 @@ static int
handle_cla(Process *c_p,
ErtsMessage *sig,
ErtsMessage ***next_nm_sig,
- int exiting);
+ int exiting,
+ int limit,
+ ErtsSavedNMSignals *saved_nm_sigs);
+
static int
handle_move_msgq_off_heap(Process *c_p,
ErtsMessage *sig,
ErtsMessage ***next_nm_sig,
- int exiting);
+ int exiting,
+ int limit,
+ ErtsSavedNMSignals *saved_nm_sigs);
static void
send_cla_reply(Process *c_p, ErtsMessage *sig, Eterm to,
Eterm req_id, Eterm result);
static void handle_missing_spawn_reply(Process *c_p, ErtsMonitor *omon);
+static Uint proc_sig_queue_flush_buffer(Process* proc,
+ Uint buffer_index,
+ ErtsSignalInQueueBufferArray* buffers);
+static void proc_sig_queue_lock_buffer(ErtsSignalInQueueBuffer* slot);
+static void proc_sig_queue_unlock_buffer(ErtsSignalInQueueBuffer* slot);
+
#ifdef ERTS_PROC_SIG_HARD_DEBUG
#define ERTS_PROC_SIG_HDBG_PRIV_CHKQ(P, T, NMN) \
do { \
@@ -287,6 +312,76 @@ proc_sig_hdbg_check_queue(Process *c_p,
#define ERTS_PROC_SIG_HDBG_PRIV_CHKQ(P, T, NMN)
#endif
+static void
+save_delayed_nm_signal(ErtsSavedNMSignals *saved_sigs, ErtsMessage *sig)
+{
+ ErtsSignal *nm_sig = (ErtsSignal *) sig;
+ nm_sig->common.next = NULL;
+ nm_sig->common.specific.next = NULL;
+ if (!saved_sigs->first) {
+ ASSERT(!saved_sigs->last);
+ saved_sigs->first = sig;
+ saved_sigs->last = &saved_sigs->first;
+ }
+ else {
+ ErtsSignal *last;
+ ASSERT(saved_sigs->last);
+ last = (ErtsSignal *) *saved_sigs->last;
+ last->common.next = sig;
+ last->common.specific.next = &last->common.next;
+ saved_sigs->last = &last->common.next;
+ }
+}
+
+static erts_aint32_t
+restore_delayed_nm_signals(Process *c_p, ErtsSavedNMSignals *saved_sigs)
+{
+ erts_aint32_t state;
+ ErtsSignal *lsig;
+
+ ASSERT(saved_sigs->first && saved_sigs->last);
+
+ lsig = (ErtsSignal *) *saved_sigs->last;
+ if (!c_p->sig_qs.cont) {
+ ASSERT(!c_p->sig_qs.nmsigs.next);
+ ASSERT(!c_p->sig_qs.nmsigs.last);
+ if (saved_sigs->last == &saved_sigs->first)
+ c_p->sig_qs.nmsigs.last = &c_p->sig_qs.cont;
+ else
+ c_p->sig_qs.nmsigs.last = saved_sigs->last;
+ c_p->sig_qs.cont_last = &lsig->common.next;
+ }
+ else {
+ lsig->common.next = c_p->sig_qs.cont;
+ if (c_p->sig_qs.nmsigs.next) {
+ ASSERT(c_p->sig_qs.nmsigs.last);
+ if (c_p->sig_qs.nmsigs.next == &c_p->sig_qs.cont)
+ lsig->common.specific.next = &lsig->common.next;
+ else
+ lsig->common.specific.next = c_p->sig_qs.nmsigs.next;
+ if (c_p->sig_qs.nmsigs.last == &c_p->sig_qs.cont)
+ c_p->sig_qs.nmsigs.last = &lsig->common.next;
+ }
+ else {
+ ASSERT(!c_p->sig_qs.nmsigs.last);
+ if (saved_sigs->last == &saved_sigs->first)
+ c_p->sig_qs.nmsigs.last = &c_p->sig_qs.cont;
+ else
+ c_p->sig_qs.nmsigs.last = saved_sigs->last;
+ if (c_p->sig_qs.cont_last == &c_p->sig_qs.cont)
+ c_p->sig_qs.cont_last = &lsig->common.next;
+ }
+ }
+
+ c_p->sig_qs.cont = saved_sigs->first;
+ c_p->sig_qs.nmsigs.next = &c_p->sig_qs.cont;
+
+ state = erts_atomic32_read_bor_nob(&c_p->state,
+ ERTS_PSFLG_SIG_Q);
+ state |= ERTS_PSFLG_SIG_Q;
+ return state;
+}
+
typedef struct {
ErtsSignalCommon common;
Eterm ref;
@@ -383,6 +478,18 @@ get_cla_data(ErtsMessage *sig)
+ sig->hfrag.used_size);
}
+static ERTS_INLINE ErtsAdjOffHeapMsgQData *
+get_move_msgq_off_heap_data(ErtsMessage *sig)
+{
+ ASSERT(ERTS_SIG_IS_NON_MSG(sig));
+ ASSERT(ERTS_PROC_SIG_OP(((ErtsSignal *) sig)->common.tag)
+ == ERTS_SIG_Q_OP_ADJ_MSGQ);
+ ASSERT(ERTS_PROC_SIG_TYPE(((ErtsSignal *) sig)->common.tag)
+ == ERTS_SIG_Q_TYPE_OFF_HEAP);
+ return (ErtsAdjOffHeapMsgQData *) (char *) (&sig->hfrag.mem[0]
+ + sig->hfrag.used_size);
+}
+
static ERTS_INLINE void
destroy_trace_info(ErtsSigTraceInfo *ti)
{
@@ -399,9 +506,18 @@ destroy_sig_group_leader(ErtsSigGroupLeader *sgl)
}
static ERTS_INLINE void
-sig_enqueue_trace(Process *c_p, ErtsMessage **sigp, int op,
- Process *rp, ErtsMessage ***last_next)
+sig_enqueue_trace(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsMessage **sigp, int op, Process *rp,
+ ErtsMessage ***last_next)
{
+ Process *c_p;
+
+ if (sender == NULL || !is_internal_pid(from)) {
+ return;
+ }
+
+ c_p = ErtsContainerStruct(sender, Process, common);
+
switch (op) {
case ERTS_SIG_Q_OP_LINK:
if (c_p
@@ -424,25 +540,27 @@ sig_enqueue_trace(Process *c_p, ErtsMessage **sigp, int op,
ti->common.specific.next = &ti->common.next;
ti->common.tag = tag;
ti->flags_on = ERTS_TRACE_FLAGS(c_p) & TRACEE_FLAGS;
- if (!(ti->flags_on & F_TRACE_SOL1))
+
+ if (!(ti->flags_on & F_TRACE_SOL1)) {
ti->flags_off = 0;
- else {
+ } else {
ti->flags_off = F_TRACE_SOL1|F_TRACE_SOL;
erts_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
ERTS_TRACE_FLAGS(c_p) &= ~(F_TRACE_SOL1|F_TRACE_SOL);
erts_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
}
+
erts_tracer_update(&ti->tracer, ERTS_TRACER(c_p));
*sigp = (ErtsMessage *) ti;
- if (!*last_next || *last_next == sigp)
+
+ if (!*last_next || *last_next == sigp) {
*last_next = &ti->common.next;
+ }
}
break;
-
#ifdef USE_VM_PROBES
case ERTS_SIG_Q_OP_EXIT:
case ERTS_SIG_Q_OP_EXIT_LINKED:
-
if (DTRACE_ENABLED(process_exit_signal)) {
ErtsMessage* sig = *sigp;
Uint16 type = ERTS_PROC_SIG_TYPE(((ErtsSignal *) sig)->common.tag);
@@ -450,6 +568,7 @@ sig_enqueue_trace(Process *c_p, ErtsMessage **sigp, int op,
ErtsExitSignalData *xsigd;
ASSERT(type == ERTS_SIG_Q_TYPE_GEN_EXIT);
+ (void)type;
xsigd = get_exit_signal_data(sig);
reason = xsigd->reason;
@@ -472,9 +591,7 @@ sig_enqueue_trace(Process *c_p, ErtsMessage **sigp, int op,
}
}
break;
-
#endif
-
default:
break;
}
@@ -527,46 +644,105 @@ static int dbg_count_nmsigs(ErtsMessage *first)
}
#endif
+#ifdef ERTS_PROC_SIG_HARD_DEBUG_SIGQ_BUFFERS
+static int dbg_count_all(ErtsMessage *first)
+{
+ ErtsMessage *sig;
+ int cnt = 0;
+
+ for (sig = first; sig; sig = sig->next) {
+ ++cnt;
+ }
+ return cnt;
+}
+
+static int dbg_check_non_msg(ErtsSignalInQueue* q)
+{
+ ErtsMessage** m = q->nmsigs.next;
+ int cnt = 0;
+ ErtsMessage** prev_m = NULL;
+ while (m != NULL) {
+ ERTS_ASSERT(ERTS_SIG_IS_NON_MSG(*m));
+ cnt++;
+ prev_m = m;
+ m = ((ErtsSignal *) (*m))->common.specific.next;
+ }
+ if (cnt > 0) {
+ ERTS_ASSERT(prev_m == q->nmsigs.last);
+ }
+ return cnt;
+}
+#endif /* ERTS_PROC_SIG_HARD_DEBUG_SIGQ_BUFFERS */
+
static ERTS_INLINE erts_aint32_t
enqueue_signals(Process *rp, ErtsMessage *first,
ErtsMessage **last, ErtsMessage **last_next,
Uint num_msgs,
- erts_aint32_t in_state)
+ erts_aint32_t state,
+ ErtsSignalInQueue* dest_queue)
{
- erts_aint32_t state = in_state;
- ErtsMessage **this = rp->sig_inq.last;
+ ErtsMessage **this;
+ int is_to_buffer = dest_queue != &rp->sig_inq;
+ int flush_buffers = (!is_to_buffer) && (state & ERTS_PSFLG_OFF_HEAP_MSGQ);
+
+ if (flush_buffers) {
+ erts_proc_sig_queue_flush_buffers(rp);
+#ifdef DEBUG
+ /*
+ * The following read is necessary to prevent
+ * ASSERT(is_to_buffer || state & ERTS_PSFLG_SIG_IN_Q) assert
+ * below from failing.
+ */
+ state = erts_atomic32_read_nob(&rp->state);
+#endif
+ }
- ERTS_HDBG_CHECK_SIGNAL_IN_QUEUE(rp);
+ this = dest_queue->last;
+
+ if (!is_to_buffer) {
+ ERTS_HDBG_CHECK_SIGNAL_IN_QUEUE(rp);
+ }
ASSERT(!*this);
*this = first;
- rp->sig_inq.last = last;
+ dest_queue->last = last;
- if (!rp->sig_inq.nmsigs.next) {
- ASSERT(!rp->sig_inq.nmsigs.last);
+ if (!dest_queue->nmsigs.next) {
+ ASSERT(!dest_queue->nmsigs.last);
if (ERTS_SIG_IS_NON_MSG(first)) {
- rp->sig_inq.nmsigs.next = this;
+ dest_queue->nmsigs.next = this;
}
else if (last_next) {
ASSERT(first->next && ERTS_SIG_IS_NON_MSG(first->next));
- rp->sig_inq.nmsigs.next = &first->next;
+ dest_queue->nmsigs.next = &first->next;
}
else
goto no_nmsig;
+ if (is_to_buffer) {
+ /*
+ * Check state first to avoid write overhead when it is
+ * unnecessary.
+ */
+ if ( ! (state & ERTS_PSFLG_SIG_IN_Q)) {
+ state = erts_atomic32_read_bor_relb(&rp->state,
+ ERTS_PSFLG_SIG_IN_Q);
+ }
+ } else {
+ state = erts_atomic32_read_bor_nob(&rp->state,
+ ERTS_PSFLG_SIG_IN_Q);
+ }
- state = erts_atomic32_read_bor_nob(&rp->state,
- ERTS_PSFLG_SIG_IN_Q);
no_nmsig:
- ASSERT(!(state & ERTS_PSFLG_SIG_IN_Q));
+ ;
}
else {
ErtsSignal *sig;
- ASSERT(rp->sig_inq.nmsigs.last);
+ ASSERT(dest_queue->nmsigs.last);
- sig = (ErtsSignal *) *rp->sig_inq.nmsigs.last;
+ sig = (ErtsSignal *) *dest_queue->nmsigs.last;
ASSERT(sig && !sig->common.specific.next);
- ASSERT(state & ERTS_PSFLG_SIG_IN_Q);
+ ASSERT(is_to_buffer || state & ERTS_PSFLG_SIG_IN_Q);
if (ERTS_SIG_IS_NON_MSG(first)) {
sig->common.specific.next = this;
}
@@ -578,18 +754,20 @@ enqueue_signals(Process *rp, ErtsMessage *first,
if (last_next) {
ASSERT(dbg_count_nmsigs(first) >= 2);
- rp->sig_inq.nmsigs.last = last_next;
+ dest_queue->nmsigs.last = last_next;
}
else if (ERTS_SIG_IS_NON_MSG(first)) {
ASSERT(dbg_count_nmsigs(first) == 1);
- rp->sig_inq.nmsigs.last = this;
+ dest_queue->nmsigs.last = this;
}
else
ASSERT(dbg_count_nmsigs(first) == 0);
- rp->sig_inq.len += num_msgs;
+ dest_queue->len += num_msgs;
- ERTS_HDBG_CHECK_SIGNAL_IN_QUEUE(rp);
+ if (!is_to_buffer) {
+ ERTS_HDBG_CHECK_SIGNAL_IN_QUEUE(rp);
+ }
return state;
}
@@ -599,7 +777,7 @@ erts_aint32_t erts_enqueue_signals(Process *rp, ErtsMessage *first,
Uint num_msgs,
erts_aint32_t in_state)
{
- return enqueue_signals(rp, first, last, last_next, num_msgs, in_state);
+ return enqueue_signals(rp, first, last, last_next, num_msgs, in_state, &rp->sig_inq);
}
void
@@ -638,7 +816,8 @@ check_push_msgq_len_offs_marker(Process *rp, ErtsSignal *sig);
static int
-proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
+proc_queue_signal(ErtsPTabElementCommon *sender, Eterm from, Eterm pid,
+ ErtsSignal *sig, int force_flush, int op)
{
int res;
Process *rp;
@@ -648,6 +827,20 @@ proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
erts_aint32_t state;
ErtsSignal *pend_sig;
+ ASSERT(sender == NULL || sender->id == from);
+
+ /* Tracing requires sender for local procs and ports. The assertions below
+ * will not catch errors after time-of-death, but ought to find most
+ * problems. */
+ ASSERT(sender != NULL || op == ERTS_SIG_Q_OP_FLUSH ||
+ (is_normal_sched && esdp->pending_signal.sig == sig) ||
+ (!(is_internal_pid(from) &&
+ erts_proc_lookup(from) != NULL) &&
+ !(is_internal_port(from) &&
+ erts_port_lookup(from, ERTS_PORT_SFLGS_INVALID_LOOKUP) != NULL)));
+
+ ASSERT(is_value(from) && is_internal_pid(pid));
+
if (is_normal_sched) {
pend_sig = esdp->pending_signal.sig;
if (op == ERTS_SIG_Q_OP_MONITOR
@@ -666,8 +859,10 @@ proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
if (pend_sig != sig) {
/* Switch them and send previously pending signal instead */
Eterm pend_to = esdp->pending_signal.to;
+
esdp->pending_signal.sig = sig;
esdp->pending_signal.to = pid;
+
sig = pend_sig;
pid = pend_to;
}
@@ -681,9 +876,12 @@ proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
#endif
pend_sig = NULL;
}
+
rp = erts_proc_lookup_raw(pid);
if (!rp) {
- erts_proc_sig_send_monitor_down((ErtsMonitor*)sig, am_noproc);
+ erts_proc_sig_send_monitor_down(sender, from,
+ (ErtsMonitor*)sig,
+ am_noproc);
return 1;
}
}
@@ -694,7 +892,9 @@ proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
rp = erts_proc_lookup_raw(pid);
if (!rp) {
- erts_proc_sig_send_monitor_down((ErtsMonitor*)pend_sig, am_noproc);
+ erts_proc_sig_send_monitor_down(sender, from,
+ (ErtsMonitor*)pend_sig,
+ am_noproc);
return 0;
}
@@ -709,14 +909,16 @@ proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
else {
pend_sig = NULL;
rp = erts_proc_lookup_raw(pid);
- if (!rp)
+ if (!rp) {
return 0;
+ }
}
}
else {
rp = erts_proc_lookup_raw_inc_refc(pid);
- if (!rp)
+ if (!rp) {
return 0;
+ }
pend_sig = NULL;
}
@@ -725,21 +927,45 @@ proc_queue_signal(Process *c_p, Eterm pid, ErtsSignal *sig, int op)
sigp = &first;
first_last_done:
+
+ if ((void *) sender == (void *) rp)
+ (void) erts_atomic32_read_bor_nob(&((Process *) sender)->state,
+ ERTS_PSFLG_MAYBE_SELF_SIGS);
+
sig->common.specific.next = NULL;
/* may add signals before sig */
- sig_enqueue_trace(c_p, sigp, op, rp, &last_next);
+ sig_enqueue_trace(sender, from, sigp, op, rp, &last_next);
last->next = NULL;
- erts_proc_lock(rp, ERTS_PROC_LOCK_MSGQ);
+ if (!force_flush && op != ERTS_SIG_Q_OP_PROCESS_INFO &&
+ erts_proc_sig_queue_try_enqueue_to_buffer(from, rp, 0, first,
+ &last->next, last_next,
+ 0, 1)) {
+ if (!is_normal_sched) {
+ erts_proc_dec_refc(rp);
+ }
+
+ return 1;
+ }
+
+ erts_proc_sig_queue_lock(rp);
state = erts_atomic32_read_nob(&rp->state);
- if (ERTS_PSFLG_FREE & state)
+ if (force_flush) {
+ erts_proc_sig_queue_flush_buffers(rp);
+ } else {
+ erts_proc_sig_queue_maybe_install_buffers(rp, state);
+ }
+
+ if (ERTS_PSFLG_FREE & state) {
res = 0;
- else {
- state = enqueue_signals(rp, first, &last->next, last_next, 0, state);
+ } else {
+ state = enqueue_signals(rp, first, &last->next,
+ last_next, 0, state,
+ &rp->sig_inq);
if (ERTS_UNLIKELY(op == ERTS_SIG_Q_OP_PROCESS_INFO))
check_push_msgq_len_offs_marker(rp, sig);
res = !0;
@@ -750,38 +976,42 @@ first_last_done:
if (res == 0) {
sig_enqueue_trace_cleanup(first, sig);
if (pend_sig) {
- erts_proc_sig_send_monitor_down((ErtsMonitor*)pend_sig, am_noproc);
+ erts_proc_sig_send_monitor_down(sender, from,
+ (ErtsMonitor*)pend_sig, am_noproc);
if (sig == pend_sig) {
/* We did a switch, callers signal is now pending (still ok) */
ASSERT(esdp->pending_signal.sig);
res = 1;
}
}
- }
- else
+ } else {
erts_proc_notify_new_sig(rp, state, 0);
+ }
- if (!is_normal_sched)
+ if (!is_normal_sched) {
erts_proc_dec_refc(rp);
+ }
return res;
}
-void erts_proc_sig_send_pending(ErtsSchedulerData* esdp)
+void erts_proc_sig_send_pending(Process *c_p, ErtsSchedulerData* esdp)
{
- ErtsSignal* sig = esdp->pending_signal.sig;
+ ErtsSignal *sig = esdp->pending_signal.sig;
+ Eterm to = esdp->pending_signal.to;
int op;
ASSERT(esdp && esdp->type == ERTS_SCHED_NORMAL);
+ ASSERT(c_p && c_p == esdp->pending_signal.dbg_from);
ASSERT(sig);
- ASSERT(is_internal_pid(esdp->pending_signal.to));
+ ASSERT(is_internal_pid(to));
op = ERTS_SIG_Q_OP_MONITOR;
ASSERT(op == ERTS_PROC_SIG_OP(sig->common.tag));
- if (!proc_queue_signal(NULL, esdp->pending_signal.to, sig, op)) {
+ if (!proc_queue_signal(&c_p->common, c_p->common.id, to, sig, 0, op)) {
ErtsMonitor* mon = (ErtsMonitor*)sig;
- erts_proc_sig_send_monitor_down(mon, am_noproc);
+ erts_proc_sig_send_monitor_down(NULL, to, mon, am_noproc);
}
}
@@ -841,8 +1071,6 @@ erts_proc_sig_fetch__(Process *proc)
ASSERT(proc->sig_inq.first);
if (!proc->sig_inq.nmsigs.next) {
- ASSERT(!(ERTS_PSFLG_SIG_IN_Q
- & erts_atomic32_read_nob(&proc->state)));
ASSERT(!proc->sig_inq.nmsigs.last);
if (proc->sig_qs.cont || ERTS_MSG_RECV_TRACED(proc)) {
@@ -864,13 +1092,10 @@ erts_proc_sig_fetch__(Process *proc)
else
proc->sig_qs.nmsigs.next = proc->sig_inq.nmsigs.next;
- s = erts_atomic32_read_bset_nob(&proc->state,
- (ERTS_PSFLG_SIG_Q
- | ERTS_PSFLG_SIG_IN_Q),
- ERTS_PSFLG_SIG_Q);
-
- ASSERT((s & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
- == ERTS_PSFLG_SIG_IN_Q); (void)s;
+ erts_atomic32_read_bset_nob(&proc->state,
+ (ERTS_PSFLG_SIG_Q
+ | ERTS_PSFLG_SIG_IN_Q),
+ ERTS_PSFLG_SIG_Q);
}
else {
ErtsSignal *sig;
@@ -932,7 +1157,7 @@ erts_proc_sig_fetch_msgq_len_offs__(Process *proc)
proc->sig_inq.len = 0;
/*
- * Temorarily remove marker during fetch...
+ * Temporarily remove marker during fetch...
*/
proc->sig_inq.first = marker->common.next;
@@ -1053,7 +1278,7 @@ erts_proc_sig_get_external(ErtsMessage *msgp)
static void do_seq_trace_output(Eterm to, Eterm token, Eterm msg);
static void
-send_gen_exit_signal(Process *c_p, Eterm from_tag,
+send_gen_exit_signal(ErtsPTabElementCommon *sender, Eterm from_tag,
Eterm from, Eterm to,
Sint16 op, Eterm reason, ErtsDistExternal *dist_ext,
ErlHeapFragment *dist_ext_hfrag,
@@ -1067,11 +1292,18 @@ send_gen_exit_signal(Process *c_p, Eterm from_tag,
ErlOffHeap *ohp;
Uint hsz, from_sz, reason_sz, ref_sz, token_sz, dist_ext_sz = 0;
int seq_trace;
+ Process *c_p;
#ifdef USE_VM_PROBES
Eterm s_utag, utag;
Uint utag_sz;
#endif
+ if (sender && is_internal_pid(from)) {
+ c_p = ErtsContainerStruct(sender, Process, common);
+ } else {
+ c_p = NULL;
+ }
+
ASSERT((is_value(reason) && dist_ext == NULL) ||
(is_non_value(reason) && dist_ext != NULL));
@@ -1080,8 +1312,9 @@ send_gen_exit_signal(Process *c_p, Eterm from_tag,
hsz = sizeof(ErtsExitSignalData)/sizeof(Eterm);
seq_trace = c_p && have_seqtrace(token);
- if (seq_trace)
+ if (seq_trace) {
seq_trace_update_serial(c_p);
+ }
#ifdef USE_VM_PROBES
utag_sz = 0;
@@ -1218,12 +1451,20 @@ send_gen_exit_signal(Process *c_p, Eterm from_tag,
ASSERT(hp == mp->hfrag.mem + mp->hfrag.alloc_size);
- if (seq_trace)
+ if (seq_trace) {
do_seq_trace_output(to, s_token, s_message);
+ }
- if (!proc_queue_signal(c_p, to, (ErtsSignal *) mp, op)) {
- mp->next = NULL;
- erts_cleanup_messages(mp);
+ {
+ /* Ensure that we're ordered relative to the sender process if one
+ * exists, and not `from` as it may be a name instead of a pid. */
+ Eterm order_by = sender ? sender->id : from;
+
+ if (!proc_queue_signal(sender, order_by, to, (ErtsSignal *)mp,
+ !(is_pid(order_by) || is_port(order_by)), op)) {
+ mp->next = NULL;
+ erts_cleanup_messages(mp);
+ }
}
}
@@ -1330,23 +1571,18 @@ erts_proc_sig_cleanup_non_msg_signal(ErtsMessage *sig)
Eterm tag = ((ErtsSignal *) sig)->common.tag;
/*
- * Heap alias message, heap frag alias message and
- * adjust message queue signals are the only non-message
- * signals, which are allocated as messages, which do not
- * use a combined message / heap fragment.
+ * Heap alias message and heap frag alias message are
+ * the only non-message signals, which are allocated as
+ * messages, which do not use a combined message / heap
+ * fragment.
*/
- if (ERTS_SIG_IS_HEAP_ALIAS_MSG_TAG(tag)
- || tag == ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_ADJ_MSGQ,
- ERTS_SIG_Q_TYPE_OFF_HEAP,
- 0)) {
+ if (ERTS_SIG_IS_HEAP_ALIAS_MSG_TAG(tag)) {
sig->data.heap_frag = NULL;
return;
}
-
-
- if(ERTS_SIG_IS_HEAP_FRAG_ALIAS_MSG_TAG(tag)) {
- /* Retreive pointer to heap fragment (may not be NULL). */
+ if (ERTS_SIG_IS_HEAP_FRAG_ALIAS_MSG_TAG(tag)) {
+ /* Retrieve pointer to heap fragment (may not be NULL). */
void *attached;
(void) get_alias_msg_data(sig, NULL, NULL, NULL, &attached);
sig->data.heap_frag = hfrag = (ErlHeapFragment *) attached;
@@ -1356,10 +1592,45 @@ erts_proc_sig_cleanup_non_msg_signal(ErtsMessage *sig)
/*
* Using a combined heap fragment...
*/
- ErtsDistExternal *edep = get_external_non_msg_signal(sig);
- if (edep)
- erts_free_dist_ext_copy(edep);
-
+ switch (ERTS_PROC_SIG_OP(tag)) {
+
+ case ERTS_SIG_Q_OP_ADJ_MSGQ: {
+ /* We need to deallocate yield markers if such has been used... */
+ ErtsYieldAdjMsgQ *yp;
+ switch (ERTS_PROC_SIG_TYPE(tag)) {
+ case ERTS_SIG_Q_TYPE_CLA: {
+ ErtsCLAData *cla = get_cla_data(sig);
+ yp = cla->yield;
+ cla->yield = NULL;
+ break;
+ }
+ case ERTS_SIG_Q_TYPE_OFF_HEAP: {
+ ErtsAdjOffHeapMsgQData *ohdp = get_move_msgq_off_heap_data(sig);
+ yp = ohdp->yield;
+ ohdp->yield = NULL;
+ break;
+ }
+ default:
+ ERTS_INTERNAL_ERROR("Invalid adjust-message-queue signal type");
+ yp = NULL;
+ break;
+ }
+ if (yp) {
+ ASSERT(!yp->next.in_msgq && !yp->next.in_sigq);
+ ASSERT(!yp->last.in_msgq && !yp->last.in_sigq);
+ erts_free(ERTS_ALC_T_SIG_YIELD_DATA, yp);
+ }
+ break;
+ }
+
+ default: {
+ ErtsDistExternal *edep = get_external_non_msg_signal(sig);
+ if (edep)
+ erts_free_dist_ext_copy(edep);
+ break;
+ }
+ }
+
sig->data.attached = ERTS_MSG_COMBINED_HFRAG;
hfrag = sig->hfrag.next;
erts_cleanup_offheap(&sig->hfrag.off_heap);
@@ -1536,7 +1807,7 @@ erts_proc_sig_send_to_alias(Process *c_p, Eterm from, Eterm to, Eterm msg, Eterm
hfrag_low, hfrag_high);
}
- if (!proc_queue_signal(c_p, pid, (ErtsSignal *) mp,
+ if (!proc_queue_signal(&c_p->common, from, pid, (ErtsSignal *) mp, 0,
ERTS_SIG_Q_OP_ALIAS_MSG)) {
mp->next = NULL;
erts_cleanup_messages(mp);
@@ -1555,7 +1826,8 @@ erts_proc_sig_send_to_alias(Process *c_p, Eterm from, Eterm to, Eterm msg, Eterm
}
void
-erts_proc_sig_send_dist_to_alias(Eterm alias, ErtsDistExternal *edep,
+erts_proc_sig_send_dist_to_alias(Eterm from, Eterm alias,
+ ErtsDistExternal *edep,
ErlHeapFragment *hfrag, Eterm token)
{
ErtsMessage* mp;
@@ -1618,20 +1890,24 @@ erts_proc_sig_send_dist_to_alias(Eterm alias, ErtsDistExternal *edep,
ERTS_SIG_Q_TYPE_DIST,
0);
- if (!proc_queue_signal(NULL, pid, (ErtsSignal *) mp,
+ if (!proc_queue_signal(NULL, from, pid, (ErtsSignal *) mp, 0,
ERTS_SIG_Q_OP_ALIAS_MSG)) {
mp->next = NULL;
erts_cleanup_messages(mp);
}
-
}
-
-void
+/**
+ * @brief Send a persistent monitor triggered signal to a process.
+ *
+ * Used by monitors that are not auto disabled such as for
+ * example 'time_offset' monitors.
+ */
+static void
erts_proc_sig_send_persistent_monitor_msg(Uint16 type, Eterm key,
Eterm from, Eterm to,
- Eterm msg, Uint msg_sz)
-{
+ Eterm msg, Uint msg_sz,
+ int force_flush) {
ErtsPersistMonMsg *prst_mon;
ErtsMessage *mp;
ErlHeapFragment *hfrag;
@@ -1683,13 +1959,30 @@ erts_proc_sig_send_persistent_monitor_msg(Uint16 type, Eterm key,
ERL_MESSAGE_FROM(mp) = from;
ERL_MESSAGE_TOKEN(mp) = am_undefined;
- if (!proc_queue_signal(NULL, to, (ErtsSignal *) mp,
+ if (!proc_queue_signal(NULL, from, to, (ErtsSignal *) mp, force_flush,
ERTS_SIG_Q_OP_PERSISTENT_MON_MSG)) {
mp->next = NULL;
erts_cleanup_messages(mp);
}
}
+void
+erts_proc_sig_send_monitor_nodes_msg(Eterm key, Eterm to,
+ Eterm msg, Uint msg_sz) {
+ erts_proc_sig_send_persistent_monitor_msg(ERTS_MON_TYPE_NODES,
+ key, am_system, to,
+ msg, msg_sz, 1);
+}
+
+void
+erts_proc_sig_send_monitor_time_offset_msg(Eterm key, Eterm to,
+ Eterm msg, Uint msg_sz) {
+ erts_proc_sig_send_persistent_monitor_msg(ERTS_MON_TYPE_TIME_OFFSET,
+ key, am_clock_service, to,
+ msg, msg_sz, 0);
+
+}
+
static ERTS_INLINE Eterm
get_persist_mon_msg(ErtsMessage *sig, Eterm *msg)
{
@@ -1702,12 +1995,14 @@ get_persist_mon_msg(ErtsMessage *sig, Eterm *msg)
}
void
-erts_proc_sig_send_exit(Process *c_p, Eterm from, Eterm to,
+erts_proc_sig_send_exit(ErtsPTabElementCommon *sender, Eterm from, Eterm to,
Eterm reason, Eterm token,
int normal_kills)
{
Eterm from_tag;
- ASSERT(!c_p || c_p->common.id == from);
+
+ ASSERT(sender == NULL || sender->id == from);
+
if (is_immed(from)) {
ASSERT(is_internal_pid(from) || is_internal_port(from));
from_tag = from;
@@ -1718,7 +2013,8 @@ erts_proc_sig_send_exit(Process *c_p, Eterm from, Eterm to,
dep = external_pid_dist_entry(from);
from_tag = dep->sysname;
}
- send_gen_exit_signal(c_p, from_tag, from, to, ERTS_SIG_Q_OP_EXIT,
+
+ send_gen_exit_signal(sender, from_tag, from, to, ERTS_SIG_Q_OP_EXIT,
reason, NULL, NULL, NIL, token, normal_kills, 0, 0);
}
@@ -1735,87 +2031,84 @@ erts_proc_sig_send_dist_exit(DistEntry *dep,
}
void
-erts_proc_sig_send_link_exit(Process *c_p, Eterm from, ErtsLink *lnk,
- Eterm reason, Eterm token)
+erts_proc_sig_send_link_exit_noconnection(ErtsLink *lnk)
{
Eterm to, from_tag, from_item;
- int conn_lost;
+ ErtsLink *olnk;
+ ErtsELink *elnk;
Uint32 conn_id;
- ASSERT(!c_p || c_p->common.id == from);
+
+ to = lnk->other.item;
+
+ ASSERT(lnk->flags & ERTS_ML_FLG_EXTENDED);
+ ASSERT(lnk->type == ERTS_LNK_TYPE_DIST_PROC);
+
+ olnk = erts_link_to_other(lnk, &elnk);
+
+ from_item = olnk->other.item;
+ from_tag = elnk->dist->nodename;
+ conn_id = elnk->dist->connection_id;
+
+ send_gen_exit_signal(NULL, from_tag, from_item, to, ERTS_SIG_Q_OP_EXIT_LINKED,
+ am_noconnection, NULL, NULL, NIL, NIL, 0, !0, conn_id);
+
+ erts_link_release(lnk);
+}
+
+void
+erts_proc_sig_send_link_exit(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsLink *lnk, Eterm reason, Eterm token)
+{
+ Eterm to;
+
+ ASSERT(sender == NULL || sender->id == from);
ASSERT(lnk);
+
to = lnk->other.item;
- if (is_value(from)) {
- ASSERT(is_internal_pid(from) || is_internal_port(from));
- from_tag = from_item = from;
- conn_id = 0;
- conn_lost = 0;
- }
- else {
- ErtsLink *olnk;
- ErtsELink *elnk;
- ASSERT(reason == am_noconnection);
- ASSERT(lnk->flags & ERTS_ML_FLG_EXTENDED);
- ASSERT(lnk->type == ERTS_LNK_TYPE_DIST_PROC);
+ ASSERT(is_internal_pid(from) || is_internal_port(from));
- olnk = erts_link_to_other(lnk, &elnk);
+ send_gen_exit_signal(sender, from, from, to, ERTS_SIG_Q_OP_EXIT_LINKED,
+ reason, NULL, NULL, NIL, token, 0, 0, 0);
- from_item = olnk->other.item;
- from_tag = elnk->dist->nodename;
- conn_id = elnk->dist->connection_id;
- conn_lost = !0;
- }
- send_gen_exit_signal(c_p, from_tag, from_item, to, ERTS_SIG_Q_OP_EXIT_LINKED,
- reason, NULL, NULL, NIL, token, 0, conn_lost, conn_id);
erts_link_release(lnk);
}
int
-erts_proc_sig_send_link(Process *c_p, Eterm to, ErtsLink *lnk)
+erts_proc_sig_send_link(ErtsPTabElementCommon *sender, Eterm from,
+ Eterm to, ErtsLink *lnk)
{
ErtsSignal *sig;
Uint16 type = lnk->type;
- ASSERT(!c_p || c_p->common.id == lnk->other.item);
- ASSERT(lnk);
+ ASSERT(!sender || sender->id == from);
+ ASSERT(lnk && eq(from, lnk->other.item));
ASSERT(is_internal_pid(to));
sig = (ErtsSignal *) lnk;
sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_LINK,
type, 0);
- return proc_queue_signal(c_p, to, sig, ERTS_SIG_Q_OP_LINK);
+ return proc_queue_signal(sender, from, to, sig, 0, ERTS_SIG_Q_OP_LINK);
}
ErtsSigUnlinkOp *
-erts_proc_sig_make_unlink_op(Process *c_p, Eterm from)
+erts_proc_sig_make_unlink_op(ErtsPTabElementCommon *sender, Eterm from)
{
- Uint64 id;
ErtsSigUnlinkOp *sulnk;
- if (c_p)
- id = erts_proc_sig_new_unlink_id(c_p);
- else {
- /*
- * *Only* ports are allowed to call without current
- * process pointer...
- */
- ASSERT(is_internal_port(from));
- id = (Uint64) erts_raw_get_unique_monotonic_integer();
- if (id == 0)
- id = (Uint64) erts_raw_get_unique_monotonic_integer();
- }
-
- ASSERT(id != 0);
+
+ ASSERT(sender->id == from);
sulnk = erts_alloc(ERTS_ALC_T_SIG_DATA, sizeof(ErtsSigUnlinkOp));
sulnk->from = from;
- sulnk->id = id;
+ sulnk->id = erts_proc_sig_new_unlink_id(sender);
return sulnk;
}
Uint64
-erts_proc_sig_send_unlink(Process *c_p, Eterm from, ErtsLink *lnk)
+erts_proc_sig_send_unlink(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsLink *lnk)
{
int res;
ErtsSignal *sig;
@@ -1827,7 +2120,7 @@ erts_proc_sig_send_unlink(Process *c_p, Eterm from, ErtsLink *lnk)
|| lnk->type != ERTS_LNK_TYPE_PORT);
ASSERT(lnk->flags & ERTS_ML_FLG_IN_TABLE);
- sulnk = erts_proc_sig_make_unlink_op(c_p, from);
+ sulnk = erts_proc_sig_make_unlink_op(sender, from);
id = sulnk->id;
sig = (ErtsSignal *) sulnk;
to = lnk->other.item;
@@ -1835,7 +2128,7 @@ erts_proc_sig_send_unlink(Process *c_p, Eterm from, ErtsLink *lnk)
lnk->type, 0);
ASSERT(is_internal_pid(to));
- res = proc_queue_signal(c_p, to, sig, ERTS_SIG_Q_OP_UNLINK);
+ res = proc_queue_signal(sender, from, to, sig, 0, ERTS_SIG_Q_OP_UNLINK);
if (res == 0) {
erts_proc_sig_destroy_unlink_op(sulnk);
return 0;
@@ -1844,7 +2137,8 @@ erts_proc_sig_send_unlink(Process *c_p, Eterm from, ErtsLink *lnk)
}
void
-erts_proc_sig_send_unlink_ack(Process *c_p, Eterm from, ErtsSigUnlinkOp *sulnk)
+erts_proc_sig_send_unlink_ack(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsSigUnlinkOp *sulnk)
{
ErtsSignal *sig = (ErtsSignal *) sulnk;
Eterm to = sulnk->from;
@@ -1857,8 +2151,10 @@ erts_proc_sig_send_unlink_ack(Process *c_p, Eterm from, ErtsSigUnlinkOp *sulnk)
type = is_internal_pid(from) ? ERTS_LNK_TYPE_PROC : ERTS_LNK_TYPE_PORT;
sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_UNLINK_ACK,
type, 0);
- if (!proc_queue_signal(c_p, to, sig, ERTS_SIG_Q_OP_UNLINK_ACK))
- erts_proc_sig_destroy_unlink_op(sulnk);
+
+ if (!proc_queue_signal(sender, from, to, sig, 0, ERTS_SIG_Q_OP_UNLINK_ACK)) {
+ erts_proc_sig_destroy_unlink_op(sulnk);
+ }
}
void
@@ -1891,12 +2187,14 @@ erts_proc_sig_send_dist_unlink(DistEntry *dep, Uint32 conn_id,
dep->sysname, conn_id,
to, from, id);
- if (!proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_UNLINK))
+ if (!proc_queue_signal(NULL, from, to, sig, 0,
+ ERTS_SIG_Q_OP_UNLINK)) {
reply_dist_unlink_ack(NULL, (ErtsSigDistUnlinkOp *) sig);
+ }
}
void
-erts_proc_sig_send_dist_unlink_ack(Process *c_p, DistEntry *dep,
+erts_proc_sig_send_dist_unlink_ack(DistEntry *dep,
Uint32 conn_id, Eterm from, Eterm to,
Uint64 id)
{
@@ -1911,8 +2209,10 @@ erts_proc_sig_send_dist_unlink_ack(Process *c_p, DistEntry *dep,
dep->sysname, conn_id,
to, from, id);
- if (!proc_queue_signal(c_p, to, sig, ERTS_SIG_Q_OP_UNLINK_ACK))
+ if (!proc_queue_signal(NULL, from, to, sig, 0,
+ ERTS_SIG_Q_OP_UNLINK_ACK)) {
destroy_sig_dist_unlink_op((ErtsSigDistUnlinkOp *) sig);
+ }
}
static void
@@ -1965,17 +2265,20 @@ erts_proc_sig_send_dist_monitor_down(DistEntry *dep, Eterm ref,
Eterm reason)
{
Eterm monitored, heap[3];
+
if (is_atom(from))
monitored = TUPLE2(&heap[0], from, dep->sysname);
else
monitored = from;
+
send_gen_exit_signal(NULL, dep->sysname, monitored,
to, ERTS_SIG_Q_OP_MONITOR_DOWN,
reason, dist_ext, hfrag, ref, NIL, 0, 0, 0);
}
void
-erts_proc_sig_send_monitor_down(ErtsMonitor *mon, Eterm reason)
+erts_proc_sig_send_monitor_down(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsMonitor *mon, Eterm reason)
{
Eterm to;
@@ -1995,8 +2298,11 @@ erts_proc_sig_send_monitor_down(ErtsMonitor *mon, Eterm reason)
sig = (ErtsSignal *) mon;
sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_MONITOR_DOWN,
mon->type, 0);
- if (proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_MONITOR_DOWN))
+ if (proc_queue_signal(sender, from, to, sig,
+ !(is_pid(from) || is_port(from)),
+ ERTS_SIG_Q_OP_MONITOR_DOWN)) {
return; /* receiver will destroy mon structure */
+ }
}
else {
ErtsMonitorData *mdp = erts_monitor_to_data(mon);
@@ -2040,16 +2346,18 @@ erts_proc_sig_send_monitor_down(ErtsMonitor *mon, Eterm reason)
|| is_atom(from_tag));
monitored = TUPLE2(&heap[0], name, node);
}
- send_gen_exit_signal(NULL, from_tag, monitored,
+
+ send_gen_exit_signal(sender, from_tag, monitored,
to, ERTS_SIG_Q_OP_MONITOR_DOWN,
reason, NULL, NULL, mdp->ref, NIL,
0, 0, 0);
}
+
erts_monitor_release(mon);
}
void
-erts_proc_sig_send_dist_demonitor(Eterm to, Eterm ref)
+erts_proc_sig_send_dist_demonitor(Eterm from, Eterm to, Eterm ref)
{
ErtsSigDistProcDemonitor *dmon;
ErtsSignal *sig;
@@ -2059,6 +2367,7 @@ erts_proc_sig_send_dist_demonitor(Eterm to, Eterm ref)
ERTS_INIT_OFF_HEAP(&oh);
+ ASSERT(is_external_pid(from));
ASSERT(is_internal_pid(to));
size = sizeof(ErtsSigDistProcDemonitor) - sizeof(Eterm);
@@ -2075,30 +2384,38 @@ erts_proc_sig_send_dist_demonitor(Eterm to, Eterm ref)
ERTS_SIG_Q_TYPE_DIST_PROC_DEMONITOR,
0);
- if (!proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_DEMONITOR))
+ if (!proc_queue_signal(NULL, from, to, sig, 0, ERTS_SIG_Q_OP_DEMONITOR)) {
destroy_dist_proc_demonitor(dmon);
+ }
}
void
-erts_proc_sig_send_demonitor(ErtsMonitor *mon)
+erts_proc_sig_send_demonitor(ErtsPTabElementCommon *sender, Eterm from,
+ int system, ErtsMonitor *mon)
{
ErtsSignal *sig = (ErtsSignal *) mon;
Uint16 type = mon->type;
Eterm to = mon->other.item;
- ASSERT(is_internal_pid(to));
+ ASSERT(is_internal_pid(to) || to == am_undefined);
ASSERT(erts_monitor_is_origin(mon));
ASSERT(!erts_monitor_is_in_table(mon));
+ ASSERT(!system || sender == NULL);
sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_DEMONITOR,
type, 0);
-
- if (!proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_DEMONITOR))
+
+ if (is_not_internal_pid(to)
+ || !proc_queue_signal(sender, from, to, sig,
+ !(system || (is_pid(from) || is_port(from))),
+ ERTS_SIG_Q_OP_DEMONITOR)) {
erts_monitor_release(mon);
+ }
}
int
-erts_proc_sig_send_monitor(ErtsMonitor *mon, Eterm to)
+erts_proc_sig_send_monitor(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsMonitor *mon, Eterm to)
{
ErtsSignal *sig = (ErtsSignal *) mon;
Uint16 type = mon->type;
@@ -2108,31 +2425,8 @@ erts_proc_sig_send_monitor(ErtsMonitor *mon, Eterm to)
sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_MONITOR,
type, 0);
-
- return proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_MONITOR);
-}
-void
-erts_proc_sig_send_trace_change(Eterm to, Uint on, Uint off, Eterm tracer)
-{
- ErtsSigTraceInfo *ti;
- Eterm tag;
-
- ti = erts_alloc(ERTS_ALC_T_SIG_DATA, sizeof(ErtsSigTraceInfo));
- tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_TRACE_CHANGE_STATE,
- ERTS_SIG_Q_TYPE_ADJUST_TRACE_INFO,
- 0);
-
- ti->common.tag = tag;
- ti->flags_off = off;
- ti->flags_on = on;
- ti->tracer = NIL;
- if (is_not_nil(tracer))
- erts_tracer_update(&ti->tracer, tracer);
-
- if (!proc_queue_signal(NULL, to, (ErtsSignal *) ti,
- ERTS_SIG_Q_OP_TRACE_CHANGE_STATE))
- destroy_trace_info(ti);
+ return proc_queue_signal(sender, from, to, sig, 0, ERTS_SIG_Q_OP_MONITOR);
}
void
@@ -2171,12 +2465,12 @@ erts_proc_sig_send_group_leader(Process *c_p, Eterm to, Eterm gl, Eterm ref)
ERTS_SIG_Q_TYPE_UNDEFINED,
0);
- res = proc_queue_signal(c_p, to, (ErtsSignal *) sgl,
- ERTS_SIG_Q_OP_GROUP_LEADER);
+ res = proc_queue_signal(c_p ? &c_p->common : NULL, sgl->reply_to, to,
+ (ErtsSignal *)sgl, 0, ERTS_SIG_Q_OP_GROUP_LEADER);
- if (!res)
+ if (!res) {
destroy_sig_group_leader(sgl);
- else if (c_p) {
+ } else if (c_p) {
erts_aint_t flags, rm_flags = ERTS_SIG_GL_FLG_SENDER;
int prio_res = maybe_elevate_sig_handling_prio(c_p, -1, to);
if (!prio_res)
@@ -2226,7 +2520,8 @@ erts_proc_sig_send_is_alive_request(Process *c_p, Eterm to, Eterm ref)
ERTS_SIG_Q_TYPE_UNDEFINED,
0);
- if (proc_queue_signal(c_p, to, (ErtsSignal *) mp, ERTS_SIG_Q_OP_IS_ALIVE)) {
+ if (proc_queue_signal(&c_p->common, c_p->common.id, to,
+ (ErtsSignal *)mp, 0, ERTS_SIG_Q_OP_IS_ALIVE)) {
(void) maybe_elevate_sig_handling_prio(c_p, -1, to);
return !0;
}
@@ -2283,12 +2578,15 @@ erts_proc_sig_send_process_info_request(Process *c_p,
sys_memcpy((void *) &pis->item_ix[0],
(void *) item_ix,
sizeof(int)*len);
- res = proc_queue_signal(c_p, to, (ErtsSignal *) pis,
- ERTS_SIG_Q_OP_PROCESS_INFO);
- if (res)
+
+ res = proc_queue_signal(&c_p->common, c_p->common.id, to,
+ (ErtsSignal *)pis, 0, ERTS_SIG_Q_OP_PROCESS_INFO);
+ if (res) {
(void) maybe_elevate_sig_handling_prio(c_p, -1, to);
- else
+ } else {
erts_free(ERTS_ALC_T_SIG_DATA, pis);
+ }
+
return res;
}
@@ -2332,9 +2630,10 @@ erts_proc_sig_send_sync_suspend(Process *c_p, Eterm to, Eterm tag, Eterm reply)
ERTS_SIG_Q_TYPE_UNDEFINED,
0);
- if (proc_queue_signal(c_p, to, (ErtsSignal *) mp, ERTS_SIG_Q_OP_SYNC_SUSPEND))
+ if (proc_queue_signal(&c_p->common, c_p->common.id, to,
+ (ErtsSignal *)mp, 0, ERTS_SIG_Q_OP_SYNC_SUSPEND)) {
(void) maybe_elevate_sig_handling_prio(c_p, -1, to);
- else {
+ } else {
Eterm *tp;
/* It wasn't alive; reply to ourselves... */
mp->next = NULL;
@@ -2361,11 +2660,13 @@ erts_proc_sig_send_dist_spawn_reply(Eterm node,
ErlHeapFragment *hfrag;
ErlOffHeap *ohp;
ErtsMessage *mp;
+ Eterm ordered_from;
+ int force_flush;
ASSERT(is_atom(node));
/*
- * A respons message to a spawn_request() operation
+ * A response message to a spawn_request() operation
* looks like this:
* {Tag, Ref, ok|error, Pid|ErrorAtom}
*
@@ -2432,8 +2733,23 @@ erts_proc_sig_send_dist_spawn_reply(Eterm node,
0);
ERL_MESSAGE_FROM(mp) = node;
ERL_MESSAGE_TOKEN(mp) = token_copy;
- if (!proc_queue_signal(NULL, to, (ErtsSignal *) mp,
- ERTS_SIG_Q_OP_DIST_SPAWN_REPLY)) {
+
+ /*
+ * Sent from spawn-service at node, but we need to order this
+ * signal against signals sent from the spawned process, so
+ * we need to pass the pid of the spawned process as from
+ * parameter or flush if connection was lost...
+ */
+ if (is_external_pid(result)) {
+ force_flush = 0;
+ ordered_from = result;
+ }
+ else {
+ force_flush = result == am_noconnection;
+ ordered_from = am_spawn_service;
+ }
+ if (!proc_queue_signal(NULL, ordered_from, to, (ErtsSignal *)mp,
+ force_flush, ERTS_SIG_Q_OP_DIST_SPAWN_REPLY)) {
mp->next = NULL;
mp->data.attached = ERTS_MSG_COMBINED_HFRAG;
ERL_MESSAGE_TERM(mp) = msg;
@@ -2488,9 +2804,10 @@ erts_proc_sig_send_rpc_request_prio(Process *c_p,
erts_msgq_set_save_end(c_p);
}
- if (proc_queue_signal(c_p, to, (ErtsSignal *) sig, ERTS_SIG_Q_OP_RPC))
+ if (proc_queue_signal(&c_p->common, c_p->common.id, to, (ErtsSignal *)sig,
+ 0, ERTS_SIG_Q_OP_RPC)) {
(void) maybe_elevate_sig_handling_prio(c_p, prio, to);
- else {
+ } else {
erts_free(ERTS_ALC_T_SIG_DATA, sig);
res = THE_NON_VALUE;
if (reply)
@@ -2534,6 +2851,7 @@ erts_proc_sig_send_cla_request(Process *c_p, Eterm to, Eterm req_id)
cla = (ErtsCLAData *) (char *) hp;
hfrag->used_size = hp - start_hp;
+ cla->yield = NULL;
cla->requester = c_p->common.id;
cla->request_id = req_id_cpy;
@@ -2546,15 +2864,29 @@ erts_proc_sig_send_cla_request(Process *c_p, Eterm to, Eterm req_id)
ERL_MESSAGE_DT_UTAG(sig) = NIL;
#endif
- if (!proc_queue_signal(c_p, to, (ErtsSignal *) sig, ERTS_SIG_Q_OP_ADJ_MSGQ))
+ if (!proc_queue_signal(&c_p->common, c_p->common.id, to, (ErtsSignal *)sig,
+ 0, ERTS_SIG_Q_OP_ADJ_MSGQ)) {
send_cla_reply(c_p, sig, c_p->common.id, req_id_cpy, am_ok);
+ }
}
void
-erts_proc_sig_send_move_msgq_off_heap(Process *c_p, Eterm to)
+erts_proc_sig_send_move_msgq_off_heap(Eterm to)
{
- ErtsMessage *sig = erts_alloc_message(0, NULL);
+ ErtsMessage *sig;
+ Eterm *hp;
+ Uint hsz;
+ ErtsAdjOffHeapMsgQData *ohdp;
ASSERT(is_internal_pid(to));
+
+ hsz = sizeof(ErtsAdjOffHeapMsgQData)/sizeof(Uint);
+ sig = erts_alloc_message(hsz, &hp);
+
+ ohdp = (ErtsAdjOffHeapMsgQData *) (char *) hp;
+ ohdp->yield = NULL;
+
+ sig->hfrag.used_size = 0;
+
ERL_MESSAGE_TERM(sig) = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_ADJ_MSGQ,
ERTS_SIG_Q_TYPE_OFF_HEAP,
0);
@@ -2563,12 +2895,91 @@ erts_proc_sig_send_move_msgq_off_heap(Process *c_p, Eterm to)
#ifdef USE_VM_PROBES
ERL_MESSAGE_DT_UTAG(sig) = NIL;
#endif
- if (!proc_queue_signal(c_p, to, (ErtsSignal *) sig, ERTS_SIG_Q_OP_ADJ_MSGQ)) {
- sig->next = NULL;
- erts_cleanup_messages(sig);
+
+ if (!proc_queue_signal(NULL, am_system, to, (ErtsSignal *)sig, 0,
+ ERTS_SIG_Q_OP_ADJ_MSGQ)) {
+ sig->next = NULL;
+ erts_cleanup_messages(sig);
}
}
+void
+erts_proc_sig_init_flush_signals(Process *c_p, int flags, Eterm id)
+{
+ int force_flush_buffers = 0, enqueue_mq, fetch_sigs;
+ ErtsSignal *sig;
+
+ ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
+
+ ASSERT(!(c_p->sig_qs.flags & (FS_FLUSHING_SIGS|FS_FLUSHED_SIGS)));
+ ASSERT(flags);
+ ASSERT((flags & ~ERTS_PROC_SIG_FLUSH_FLGS) == 0);
+ ASSERT(!(flags & ERTS_PROC_SIG_FLUSH_FLG_FROM_ID)
+ || is_internal_pid(id) || is_internal_port(id));
+
+ sig = erts_alloc(ERTS_ALC_T_SIG_DATA, sizeof(ErtsSignalCommon));
+ sig->common.next = NULL;
+ sig->common.specific.attachment = NULL;
+ sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_FLUSH,
+ ERTS_SIG_Q_TYPE_UNDEFINED,
+ 0);
+ switch (flags) {
+ case ERTS_PROC_SIG_FLUSH_FLG_FROM_ALL:
+ id = c_p->common.id;
+ force_flush_buffers = !0;
+ /* Fall through... */
+ case ERTS_PROC_SIG_FLUSH_FLG_FROM_ID:
+ if (!proc_queue_signal(NULL, id, c_p->common.id, sig,
+ force_flush_buffers, ERTS_SIG_Q_OP_FLUSH))
+ ERTS_INTERNAL_ERROR("Failed to send flush signal to ourselves");
+ enqueue_mq = 0;
+ fetch_sigs = !0;
+ break;
+ case ERTS_PROC_SIG_FLUSH_FLG_CLEAN_SIGQ:
+ enqueue_mq = !0;
+ fetch_sigs = 0;
+ break;
+ default:
+ enqueue_mq = !!(flags & ERTS_PROC_SIG_FLUSH_FLG_CLEAN_SIGQ);
+ fetch_sigs = !0;
+ break;
+ }
+
+ erts_set_gc_state(c_p, 0);
+
+ if (fetch_sigs) {
+ erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_fetch(c_p);
+ erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
+ }
+
+ c_p->sig_qs.flags |= FS_FLUSHING_SIGS;
+
+ if (enqueue_mq) {
+ if (!c_p->sig_qs.cont) {
+ c_p->sig_qs.flags |= FS_FLUSHED_SIGS;
+ erts_free(ERTS_ALC_T_SIG_DATA, sig);
+ }
+ else {
+ if (!c_p->sig_qs.nmsigs.last) {
+ ASSERT(!c_p->sig_qs.nmsigs.next);
+ c_p->sig_qs.nmsigs.next = c_p->sig_qs.cont_last;
+ }
+ else {
+ ErtsSignal *lsig = (ErtsSignal *) *c_p->sig_qs.nmsigs.last;
+ ASSERT(c_p->sig_qs.nmsigs.next);
+ ASSERT(lsig && !lsig->common.specific.next);
+ lsig->common.specific.next = c_p->sig_qs.cont_last;
+ }
+
+ c_p->sig_qs.nmsigs.last = c_p->sig_qs.cont_last;
+ *c_p->sig_qs.cont_last = (ErtsMessage *) sig;
+ c_p->sig_qs.cont_last = &sig->common.next;
+ }
+ }
+
+}
+
static int
handle_rpc(Process *c_p, ErtsProcSigRPC *rpc, int cnt, int limit, int *yieldp)
{
@@ -2755,7 +3166,7 @@ remove_iq_sig(Process *c_p, ErtsMessage *sig, ErtsMessage **next_sig)
static ERTS_INLINE void
remove_mq_sig(Process *c_p, ErtsMessage *sig,
- ErtsMessage **next_sig, ErtsMessage ***next_nm_sig)
+ ErtsMessage **next_sig, ErtsMessage ***next_nm_sig)
{
/*
* Remove signal from (middle) signal queue.
@@ -2983,6 +3394,8 @@ recv_marker_deallocate(Process *c_p, ErtsRecvMarker *markp)
ErtsRecvMarkerBlock *blkp = c_p->sig_qs.recv_mrk_blk;
int ix, nix;
+ ASSERT(!markp->is_yield_mark);
+
ASSERT(blkp);
ERTS_HDBG_CHK_RECV_MRKS(c_p);
@@ -3033,6 +3446,7 @@ recv_marker_dequeue(Process *c_p, ErtsRecvMarker *markp)
{
ErtsMessage *sigp;
+ ASSERT(!markp->is_yield_mark);
ASSERT(markp->proc == c_p);
if (markp->in_sigq <= 0) {
@@ -3098,6 +3512,7 @@ recv_marker_alloc_block(Process *c_p, ErtsRecvMarkerBlock **blkpp,
/* Allocate marker for 'uniqp' in index zero... */
*ixp = 0;
blkp->ref[0] = recv_marker_uniq(c_p, uniqp);
+ blkp->marker[0].is_yield_mark = 0;
markp = &blkp->marker[0];
markp->next_ix = markp->prev_ix = 0;
blkp->used_ix = 0;
@@ -3113,6 +3528,7 @@ recv_marker_alloc_block(Process *c_p, ErtsRecvMarkerBlock **blkpp,
blkp->free_ix = 1;
for (ix = 1; ix < ERTS_RECV_MARKER_BLOCK_SIZE; ix++) {
blkp->ref[ix] = am_free;
+ blkp->marker[ix].is_yield_mark = 0;
if (ix == ERTS_RECV_MARKER_BLOCK_SIZE - 1)
blkp->marker[ix].next_ix = -1; /* End of list */
else
@@ -3380,20 +3796,29 @@ erts_msgq_recv_marker_create_insert_set_save(Process *c_p, Eterm id)
}
void
-erts_msgq_remove_leading_recv_markers(Process *c_p)
+erts_msgq_remove_leading_recv_markers_set_save_first(Process *c_p)
{
+ ErtsMessage **save;
/*
* Receive markers in the front of the queue does not
- * add any value, so we just remove them...
+ * add any value, so we just remove them. We need to
+ * keep and pass yield markers though...
*/
ASSERT(c_p->sig_qs.first
&& ERTS_SIG_IS_RECV_MARKER(c_p->sig_qs.first));
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
+ save = &c_p->sig_qs.first;
do {
- ErtsRecvMarker *markp = (ErtsRecvMarker *) c_p->sig_qs.first;
- recv_marker_dequeue(c_p, markp);
- } while (c_p->sig_qs.first
- && ERTS_SIG_IS_RECV_MARKER(c_p->sig_qs.first));
+ ErtsRecvMarker *markp = (ErtsRecvMarker *) *save;
+ if (markp->is_yield_mark)
+ save = &markp->sig.common.next;
+ else
+ recv_marker_dequeue(c_p, markp);
+ } while (*save && ERTS_SIG_IS_RECV_MARKER(*save));
+
+ c_p->sig_qs.save = save;
+
+ ASSERT(!*save || ERTS_SIG_IS_MSG(*save));
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
}
@@ -3405,7 +3830,8 @@ erts_msgq_pass_recv_markers(Process *c_p, ErtsMessage **markpp)
ASSERT(ERTS_SIG_IS_RECV_MARKER(sigp));
do {
ErtsRecvMarker *markp = (ErtsRecvMarker *) sigp;
- if (++markp->pass > ERTS_RECV_MARKER_PASS_MAX) {
+ if (!markp->is_yield_mark
+ && ++markp->pass > ERTS_RECV_MARKER_PASS_MAX) {
recv_marker_dequeue(c_p, markp);
sigp = *sigpp;
}
@@ -3610,7 +4036,7 @@ convert_to_down_message(Process *c_p,
if (mdp->origin.flags & (ERTS_ML_FLG_SPAWN_ABANDONED
| ERTS_ML_FLG_SPAWN_NO_EMSG)) {
/*
- * Operation has been been abandoned or
+ * Operation has been abandoned or
* error message has been disabled...
*/
erts_monitor_tree_delete(&ERTS_P_MONITORS(c_p), *omon);
@@ -3660,7 +4086,7 @@ convert_to_down_message(Process *c_p,
hsz += 3; /* reg name 2-tuple */
else {
ASSERT(is_pid(mdp->origin.other.item)
- || is_internal_port(mdp->origin.other.item));
+ || is_port(mdp->origin.other.item));
hsz += NC_HEAP_SIZE(mdp->origin.other.item);
}
@@ -3705,6 +4131,22 @@ convert_to_down_message(Process *c_p,
ERL_MESSAGE_FROM(mp) = mdp->origin.other.item;
}
break;
+ case ERTS_MON_TYPE_DIST_PORT: {
+#ifdef DEBUG
+ ErtsMonitorDataExtended *mdep = (ErtsMonitorDataExtended *) mdp;
+#endif
+ ASSERT(mdp->origin.flags & ERTS_ML_FLG_EXTENDED);
+ type = am_port;
+ ASSERT(node == am_undefined);
+ ASSERT(!mdep->dist);
+ ASSERT(is_external_port(from)
+ && (external_port_dist_entry(from)
+ == erts_this_dist_entry));
+ node = erts_this_dist_entry->sysname;
+ ASSERT(is_atom(node) && node != am_undefined);
+ ERL_MESSAGE_FROM(mp) = node;
+ break;
+ }
case ERTS_MON_TYPE_PROC:
type = am_process;
if (mdp->origin.other.item == am_undefined) {
@@ -3722,8 +4164,14 @@ convert_to_down_message(Process *c_p,
ErtsMonitorDataExtended *mdep;
ASSERT(mdp->origin.flags & ERTS_ML_FLG_EXTENDED);
mdep = (ErtsMonitorDataExtended *) mdp;
- ASSERT(mdep->dist);
- node = mdep->dist->nodename;
+ if (mdep->dist)
+ node = mdep->dist->nodename;
+ else {
+ ASSERT(is_external_pid(from));
+ ASSERT(external_pid_dist_entry(from)
+ == erts_this_dist_entry);
+ node = erts_this_dist_entry->sysname;
+ }
}
ASSERT(is_atom(node) && node != am_undefined);
ERL_MESSAGE_FROM(mp) = node;
@@ -4171,6 +4619,7 @@ handle_process_info(Process *c_p, ErtsSigRecvTracing *tracing,
*c_p->sig_qs.last = c_p->sig_qs.cont;
c_p->sig_qs.last = *next_nm_sig;
+ ASSERT(*next_nm_sig);
c_p->sig_qs.cont = **next_nm_sig;
if (c_p->sig_qs.nmsigs.last == *next_nm_sig)
c_p->sig_qs.nmsigs.last = &c_p->sig_qs.cont;
@@ -4742,8 +5191,7 @@ handle_dist_spawn_reply(Process *c_p, ErtsSigRecvTracing *tracing,
static int
handle_dist_spawn_reply_exiting(Process *c_p,
ErtsMessage *sig,
- ErtsMonitor **pend_spawn_mon_pp,
- Eterm reason)
+ ErtsProcExitContext *pe_ctxt_p)
{
ErtsDistSpawnReplySigData *datap = get_dist_spawn_reply_data(sig);
Eterm result = datap->result;
@@ -4755,7 +5203,7 @@ handle_dist_spawn_reply_exiting(Process *c_p,
ASSERT(is_atom(result) || is_external_pid(result));
ASSERT(is_atom(result) || size_object(result) == EXTERNAL_PID_HEAP_SIZE);
- omon = erts_monitor_tree_lookup(*pend_spawn_mon_pp, datap->ref);
+ omon = erts_monitor_tree_lookup(pe_ctxt_p->pend_spawn_monitors, datap->ref);
if (!omon) {
/* May happen when connection concurrently close... */
ErtsLink *lnk = datap->link;
@@ -4773,7 +5221,7 @@ handle_dist_spawn_reply_exiting(Process *c_p,
ASSERT(omon->flags & ERTS_ML_FLG_SPAWN_PENDING);
ASSERT(!datap->link || is_external_pid(result));
- erts_monitor_tree_delete(pend_spawn_mon_pp, omon);
+ erts_monitor_tree_delete(&pe_ctxt_p->pend_spawn_monitors, omon);
mdp = erts_monitor_to_data(omon);
if (!erts_dist_pend_spawn_exit_delete(&mdp->u.target))
@@ -4794,12 +5242,17 @@ handle_dist_spawn_reply_exiting(Process *c_p,
ASSERT(!(omon->flags & ERTS_ML_FLG_SPAWN_LINK) || datap->link);
if (datap->link) {
- /* This link exit *should* have actual reason... */
- ErtsProcExitContext pectxt = {c_p, reason};
/* unless operation has been abandoned... */
- if (omon->flags & ERTS_ML_FLG_SPAWN_ABANDONED)
- pectxt.reason = am_abandoned;
- erts_proc_exit_handle_link(datap->link, (void *) &pectxt, -1);
+ if (omon->flags & ERTS_ML_FLG_SPAWN_ABANDONED) {
+ ErtsProcExitContext pectxt = {c_p, am_abandoned};
+ erts_proc_exit_handle_link(datap->link, (void *) &pectxt, -1);
+ }
+ else {
+ /* This link exit *should* have actual reason... */
+ erts_proc_exit_handle_link(datap->link,
+ (void *) pe_ctxt_p,
+ -1);
+ }
cnt++;
}
}
@@ -4861,11 +5314,12 @@ handle_alias_message(Process *c_p, ErtsMessage *sig, ErtsMessage ***next_nm_sig)
erts_pid_ref_delete(alias);
switch (mon->type) {
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_ALIAS:
erts_monitor_release(mon);
break;
case ERTS_MON_TYPE_PROC:
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(&c_p->common, c_p->common.id, 0, mon);
break;
case ERTS_MON_TYPE_DIST_PROC: {
ErtsMonitorData *mdp;
@@ -4963,29 +5417,27 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
int *redsp, int max_reds, int local_only)
{
Eterm tag;
- erts_aint32_t state;
+ erts_aint32_t state = *statep;
int yield, cnt, limit, abs_lim, msg_tracing, save_in_msgq;
ErtsMessage *sig, ***next_nm_sig;
ErtsSigRecvTracing tracing;
+ ErtsSavedNMSignals delayed_nm_signals = {0};
- ASSERT(!(c_p->sig_qs.flags & FS_WAIT_HANDLE_SIGS));
- if (c_p->sig_qs.flags & FS_HANDLING_SIGS)
- wait_handle_signals(c_p);
- else
- c_p->sig_qs.flags |= FS_HANDLING_SIGS;
+ ASSERT(!(c_p->sig_qs.flags & (FS_WAIT_HANDLE_SIGS|FS_HANDLING_SIGS)));
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
- state = erts_atomic32_read_nob(&c_p->state);
- if (!local_only) {
+ if (!local_only && !(c_p->sig_qs.flags & FS_FLUSHING_SIGS)) {
if (ERTS_PSFLG_SIG_IN_Q & state) {
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_lock(c_p);
erts_proc_sig_fetch(c_p);
erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
}
}
+ c_p->sig_qs.flags |= FS_HANDLING_SIGS;
+
limit = *redsp;
*redsp = 0;
yield = 0;
@@ -5071,6 +5523,7 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
switch (type) {
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
tmon = (ErtsMonitor *) sig;
@@ -5391,9 +5844,10 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
erts_link_release(llnk);
cnt += 4;
}
- if (is_internal_pid(sulnk->from))
- erts_proc_sig_send_unlink_ack(c_p, c_p->common.id, sulnk);
- else {
+ if (is_internal_pid(sulnk->from)) {
+ erts_proc_sig_send_unlink_ack(&c_p->common, c_p->common.id,
+ sulnk);
+ } else {
Port *prt;
ASSERT(is_internal_port(sulnk->from));
prt = erts_port_lookup(sulnk->from,
@@ -5491,21 +5945,57 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
ERTS_PROC_SIG_HDBG_PRIV_CHKQ(c_p, &tracing, next_nm_sig);
break;
- case ERTS_SIG_Q_OP_ADJ_MSGQ:
+ case ERTS_SIG_Q_OP_ADJ_MSGQ: {
+ int adj_limit, adj_cnt, min_adj_limit;
+ /*
+ * This may require a substantial amount of work and we
+ * want to get it over and done with in a reasonable
+ * amount of time, so we bump up the limit for it a bit...
+ */
+ min_adj_limit = ERTS_SIG_REDS_CNT_FACTOR*CONTEXT_REDS/6;
+ if (sig->next)
+ adj_limit = min_adj_limit;
+ else {
+ adj_limit = limit - cnt;
+ if (adj_limit < min_adj_limit)
+ adj_limit = min_adj_limit;
+ }
ERTS_PROC_SIG_HDBG_PRIV_CHKQ(c_p, &tracing, next_nm_sig);
switch (ERTS_PROC_SIG_TYPE(tag)) {
case ERTS_SIG_Q_TYPE_CLA:
- cnt += handle_cla(c_p, sig, next_nm_sig, 0);
+ adj_cnt = handle_cla(c_p, sig, next_nm_sig, 0, adj_limit,
+ &delayed_nm_signals);
break;
case ERTS_SIG_Q_TYPE_OFF_HEAP:
- cnt += handle_move_msgq_off_heap(c_p, sig, next_nm_sig, 0);
+ adj_cnt = handle_move_msgq_off_heap(c_p, sig, next_nm_sig,
+ 0, adj_limit,
+ &delayed_nm_signals);
break;
default:
- ERTS_INTERNAL_ERROR("Invalid 'adjust-message-queue' signal type");
+ ERTS_INTERNAL_ERROR("Invalid adjust-message-queue signal type");
break;
}
+ cnt += adj_cnt;
+ limit += adj_cnt;
+ if (limit > abs_lim)
+ abs_lim = limit;
ERTS_PROC_SIG_HDBG_PRIV_CHKQ(c_p, &tracing, next_nm_sig);
break;
+ }
+
+ case ERTS_SIG_Q_OP_FLUSH:
+ ERTS_PROC_SIG_HDBG_PRIV_CHKQ(c_p, &tracing, next_nm_sig);
+ ASSERT(c_p->sig_qs.flags & FS_FLUSHING_SIGS);
+ c_p->sig_qs.flags |= FS_FLUSHED_SIGS;
+ remove_nm_sig(c_p, sig, next_nm_sig);
+ erts_free(ERTS_ALC_T_SIG_DATA, sig);
+ ERTS_PROC_SIG_HDBG_PRIV_CHKQ(c_p, &tracing, next_nm_sig);
+ /*
+ * The caller has been exclusively handling signals until this
+ * point. Break out and let the process continue with other
+ * things as well...
+ */
+ goto stop;
case ERTS_SIG_Q_OP_TRACE_CHANGE_STATE: {
Uint16 type = ERTS_PROC_SIG_TYPE(tag);
@@ -5536,6 +6026,7 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
case ERTS_SIG_Q_OP_RECV_MARK: {
ErtsRecvMarker *markp = (ErtsRecvMarker *) sig;
ASSERT(markp->in_sigq);
+ ASSERT(!markp->is_yield_mark);
if (markp->in_sigq < 0) {
/* Marked for removal... */
@@ -5623,7 +6114,7 @@ stop: {
*next_nm_sig = &c_p->sig_qs.cont;
if (c_p->sig_qs.nmsigs.last == tracing.messages.next)
c_p->sig_qs.nmsigs.last = &c_p->sig_qs.cont;
- *statep = erts_atomic32_read_nob(&c_p->state);
+ state = erts_atomic32_read_nob(&c_p->state);
}
else {
ASSERT(!c_p->sig_qs.nmsigs.next);
@@ -5631,7 +6122,6 @@ stop: {
state = erts_atomic32_read_band_nob(&c_p->state,
~ERTS_PSFLG_SIG_Q);
state &= ~ERTS_PSFLG_SIG_Q;
- *statep = state;
}
if (tracing.messages.next != &c_p->sig_qs.cont) {
@@ -5677,7 +6167,7 @@ stop: {
ASSERT(c_p->sig_qs.cont);
- *statep = erts_atomic32_read_nob(&c_p->state);
+ state = erts_atomic32_read_nob(&c_p->state);
res = 0;
}
@@ -5710,10 +6200,36 @@ stop: {
state = erts_atomic32_read_band_nob(&c_p->state,
~ERTS_PSFLG_SIG_Q);
state &= ~ERTS_PSFLG_SIG_Q;
- *statep = state;
res = !0;
}
+ if (!!(state & ERTS_PSFLG_MAYBE_SELF_SIGS)
+ & !(state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))) {
+ /*
+ * We know we do not have any outstanding signals
+ * from ourselves...
+ */
+ state = erts_atomic32_read_band_nob(&c_p->state,
+ ~ERTS_PSFLG_MAYBE_SELF_SIGS);
+ state &= ~ERTS_PSFLG_MAYBE_SELF_SIGS;
+ }
+
+ if (delayed_nm_signals.first) {
+ /*
+ * We do this after clearing ERTS_PSFLG_MAYBE_SELF_SIGS
+ * since there currently are no signals that can be delayed
+ * that should be counted as originating from the process
+ * itself. If such signals appear in the future this has to
+ * be accounted for...
+ *
+ * The adjust message queue data "signal" does originate from
+ * the process itself, but it is not conseptually a signal.
+ */
+ state = restore_delayed_nm_signals(c_p, &delayed_nm_signals);
+ }
+
+ *statep = state;
+
/* Ensure that 'save' doesn't point to a receive marker... */
if (*c_p->sig_qs.save
&& ERTS_SIG_IS_RECV_MARKER(*c_p->sig_qs.save)) {
@@ -5723,7 +6239,7 @@ stop: {
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
- *redsp = cnt/4 + 1;
+ *redsp = cnt/ERTS_SIG_REDS_CNT_FACTOR + 1;
if (yield) {
int vreds = max_reds - *redsp;
@@ -5824,8 +6340,7 @@ stretch_limit(Process *c_p, ErtsSigRecvTracing *tp,
int
erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
- ErtsMonitor **pend_spawn_mon_pp,
- Eterm reason)
+ ErtsProcExitContext *pe_ctxt_p)
{
int cnt;
Sint limit;
@@ -5834,8 +6349,6 @@ erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
ERTS_LC_ASSERT(erts_proc_lc_my_proc_locks(c_p) == ERTS_PROC_LOCK_MAIN);
- ASSERT(!(ERTS_PSFLG_SIG_IN_Q & erts_atomic32_read_nob(&c_p->state)));
-
limit = *redsp;
limit *= ERTS_SIG_REDS_CNT_FACTOR;
@@ -5890,6 +6403,7 @@ erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_NODES:
case ERTS_MON_TYPE_SUSPEND:
@@ -5930,12 +6444,12 @@ erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
}
case ERTS_SIG_Q_OP_UNLINK:
- if (type == ERTS_SIG_Q_TYPE_DIST_LINK)
+ if (type == ERTS_SIG_Q_TYPE_DIST_LINK) {
reply_dist_unlink_ack(c_p, (ErtsSigDistUnlinkOp *) sig);
- else if (is_internal_pid(((ErtsSigUnlinkOp *) sig)->from))
- erts_proc_sig_send_unlink_ack(c_p, c_p->common.id,
+ } else if (is_internal_pid(((ErtsSigUnlinkOp *) sig)->from)) {
+ erts_proc_sig_send_unlink_ack(&c_p->common, c_p->common.id,
(ErtsSigUnlinkOp *) sig);
- else {
+ } else {
Port *prt;
ASSERT(is_internal_port(((ErtsSigUnlinkOp *) sig)->from));
prt = erts_port_lookup(((ErtsSigUnlinkOp *) sig)->from,
@@ -5948,7 +6462,10 @@ erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
break;
case ERTS_SIG_Q_OP_UNLINK_ACK:
- erts_proc_sig_destroy_unlink_op((ErtsSigUnlinkOp *) sig);
+ if (type == ERTS_SIG_Q_TYPE_DIST_LINK)
+ destroy_sig_dist_unlink_op((ErtsSigDistUnlinkOp *) sig);
+ else
+ erts_proc_sig_destroy_unlink_op((ErtsSigUnlinkOp *) sig);
break;
case ERTS_SIG_Q_OP_GROUP_LEADER: {
@@ -5977,32 +6494,39 @@ erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
}
case ERTS_SIG_Q_OP_DIST_SPAWN_REPLY: {
- cnt += handle_dist_spawn_reply_exiting(c_p, sig,
- pend_spawn_mon_pp,
- reason);
+ cnt += handle_dist_spawn_reply_exiting(c_p, sig, pe_ctxt_p);
+
break;
}
case ERTS_SIG_Q_OP_ADJ_MSGQ:
switch (ERTS_PROC_SIG_TYPE(tag)) {
case ERTS_SIG_Q_TYPE_CLA:
- handle_cla(c_p, sig, next_nm_sig, !0);
+ handle_cla(c_p, sig, next_nm_sig, !0, limit, NULL);
break;
case ERTS_SIG_Q_TYPE_OFF_HEAP:
- handle_move_msgq_off_heap(c_p, sig, next_nm_sig, !0);
+ handle_move_msgq_off_heap(c_p, sig, next_nm_sig, !0,
+ limit, NULL);
break;
default:
- ERTS_INTERNAL_ERROR("Invalid 'adjust-message-queue' signal type");
+ ERTS_INTERNAL_ERROR("Invalid adjust-message-queue signal type");
break;
}
break;
+ case ERTS_SIG_Q_OP_FLUSH:
+ ASSERT(c_p->sig_qs.flags & FS_FLUSHING_SIGS);
+ c_p->sig_qs.flags |= FS_FLUSHED_SIGS;
+ erts_free(ERTS_ALC_T_SIG_DATA, sig);
+ break;
+
case ERTS_SIG_Q_OP_TRACE_CHANGE_STATE:
destroy_trace_info((ErtsSigTraceInfo *) sig);
break;
case ERTS_SIG_Q_OP_RECV_MARK: {
ErtsRecvMarker *markp = (ErtsRecvMarker *) sig;
+ ASSERT(!markp->is_yield_mark);
markp->in_msgq = markp->in_sigq = markp->set_save = 0;
recv_marker_deallocate(c_p, markp);
break;
@@ -6064,6 +6588,7 @@ clear_seq_trace_token(ErtsMessage *sig)
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_NODES:
case ERTS_MON_TYPE_SUSPEND:
@@ -6094,6 +6619,7 @@ clear_seq_trace_token(ErtsMessage *sig)
case ERTS_SIG_Q_OP_RPC:
case ERTS_SIG_Q_OP_RECV_MARK:
case ERTS_SIG_Q_OP_ADJ_MSGQ:
+ case ERTS_SIG_Q_OP_FLUSH:
break;
default:
@@ -6106,8 +6632,33 @@ clear_seq_trace_token(ErtsMessage *sig)
void
erts_proc_sig_clear_seq_trace_tokens(Process *c_p)
{
- erts_proc_sig_fetch(c_p);
- ERTS_FOREACH_SIG_PRIVQS(c_p, sig, clear_seq_trace_token(sig));
+ int ix;
+ ErtsSignalInQueueBufferArray *bap;
+ int unget_info;
+ ErtsMessage *qs[] = {c_p->sig_qs.first,
+ c_p->sig_qs.cont,
+ c_p->sig_inq.first};
+
+ ERTS_LC_ASSERT(erts_thr_progress_is_blocking());
+
+ for (ix = 0; ix < sizeof(qs)/sizeof(qs[0]); ix++) {
+ ErtsMessage *sigp;
+ for (sigp = qs[ix]; sigp; sigp = sigp->next)
+ clear_seq_trace_token(sigp);
+ }
+
+ bap = erts_proc_sig_queue_get_buffers(c_p, &unget_info);
+ if (bap) {
+ for (ix = 0; ix < ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS; ix++) {
+ ErtsSignalInQueueBuffer* bp = &bap->slots[ix];
+ if (bp->b.alive) {
+ ErtsMessage *sigp;
+ for (sigp = bp->b.queue.first; sigp; sigp = sigp->next)
+ clear_seq_trace_token(sigp);
+ }
+ }
+ erts_proc_sig_queue_unget_buffers(bap, unget_info);
+ }
}
Uint
@@ -6143,6 +6694,7 @@ erts_proc_sig_signal_size(ErtsSignal *sig)
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_SUSPEND:
size = erts_monitor_size((ErtsMonitor *) sig);
@@ -6154,11 +6706,6 @@ erts_proc_sig_signal_size(ErtsSignal *sig)
break;
case ERTS_SIG_Q_OP_ADJ_MSGQ:
- if (type == ERTS_SIG_Q_TYPE_OFF_HEAP) {
- size = sizeof(ErtsMessageRef);
- break;
- }
- /* Fall through... */
case ERTS_SIG_Q_OP_SYNC_SUSPEND:
case ERTS_SIG_Q_OP_PERSISTENT_MON_MSG:
case ERTS_SIG_Q_OP_IS_ALIVE:
@@ -6233,6 +6780,10 @@ erts_proc_sig_signal_size(ErtsSignal *sig)
break;
}
+ case ERTS_SIG_Q_OP_FLUSH:
+ size = sizeof(ErtsSignalCommon);
+ break;
+
case ERTS_SIG_Q_OP_TRACE_CHANGE_STATE:
size = sizeof(ErtsSigTraceInfo);
break;
@@ -6306,7 +6857,7 @@ erts_proc_sig_receive_helper(Process *c_p,
consumed_reds += 4;
left_reds -= 4;
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_lock(c_p);
erts_proc_sig_fetch(c_p);
/*
* Messages may have been moved directly to
@@ -6351,6 +6902,7 @@ erts_proc_sig_receive_helper(Process *c_p,
if (max_reds < reds)
max_reds = reds;
#endif
+ state = erts_atomic32_read_nob(&c_p->state);
(void) erts_proc_sig_handle_incoming(c_p, &state, &reds,
max_reds, !0);
consumed_reds += reds;
@@ -6389,7 +6941,6 @@ erts_proc_sig_receive_helper(Process *c_p,
if (left_reds <= 0)
break; /* yield */
- ASSERT(!c_p->sig_qs.cont);
/* Go fetch again... */
}
@@ -6402,6 +6953,127 @@ erts_proc_sig_receive_helper(Process *c_p,
return consumed_reds;
}
+static void
+init_yield_marker(Process *c_p, ErtsRecvMarker *mrkp)
+{
+ mrkp->prev_next = NULL;
+ mrkp->is_yield_mark = (char) !0;
+ mrkp->pass = (char) 100;
+ mrkp->set_save = (char) 0;
+ mrkp->in_sigq = (char) 0;
+ mrkp->in_msgq = (char) 0;
+ mrkp->prev_ix = (char) -100;
+ mrkp->next_ix = (char) -100;
+#ifdef DEBUG
+ mrkp->used = (char) !0;
+ mrkp->proc = c_p;
+#endif
+ mrkp->sig.common.next = NULL;
+ mrkp->sig.common.specific.attachment = NULL;
+ mrkp->sig.common.tag = ERTS_RECV_MARKER_TAG;
+}
+
+static void
+remove_yield_marker(Process *c_p, ErtsRecvMarker *mrkp)
+{
+ ASSERT(mrkp);
+ ASSERT(mrkp->is_yield_mark);
+ ASSERT(mrkp->in_msgq);
+ remove_iq_sig(c_p, (ErtsMessage *) mrkp, mrkp->prev_next);
+ mrkp->in_msgq = 0;
+ mrkp->in_sigq = 0;
+ mrkp->prev_next = NULL;
+ mrkp->sig.common.next = NULL;
+}
+
+static ErtsYieldAdjMsgQ *
+create_yield_adj_msgq_data(Process *c_p)
+{
+ ErtsYieldAdjMsgQ *yp = erts_alloc(ERTS_ALC_T_SIG_YIELD_DATA,
+ sizeof(ErtsYieldAdjMsgQ));
+ init_yield_marker(c_p, &yp->next);
+ init_yield_marker(c_p, &yp->last);
+ return yp;
+}
+
+static ERTS_INLINE void
+insert_adj_msgq_yield_markers(Process *c_p,
+ ErtsYieldAdjMsgQ *yp,
+ ErtsMessage **nextpp,
+ ErtsMessage ***next_nm_sig,
+ ErtsSavedNMSignals *saved_sigs)
+{
+ ErtsMessage *sig, *nextp;
+
+ ASSERT(yp);
+ ASSERT(nextpp);
+ ASSERT(next_nm_sig && *next_nm_sig && **next_nm_sig);
+ ASSERT(!yp->next.in_msgq);
+
+ sig = **next_nm_sig;
+
+ ASSERT(ERTS_PROC_SIG_OP(ERL_MESSAGE_TERM(sig))
+ == ERTS_SIG_Q_OP_ADJ_MSGQ);
+
+ /*
+ * Insert 'next' yield marker. This is in the inner queue or
+ * in the beginning of the middle queue where we've already
+ * begun using 'prev_next' pointers for receive markers,
+ * so if a receive marker follow, we need to update it.
+ */
+ yp->next.in_msgq = !0;
+ yp->next.in_sigq = !0;
+ yp->next.prev_next = nextpp;
+ yp->next.sig.common.next = nextp = *nextpp;
+ *nextpp = (ErtsMessage *) &yp->next;
+
+ ERTS_SIG_DBG_RECV_MARK_SET_HANDLED(&yp->next);
+
+ if (nextp && ERTS_SIG_IS_RECV_MARKER(nextp)) {
+ ErtsRecvMarker *next_mrkp = (ErtsRecvMarker *) nextp;
+ next_mrkp->prev_next = &yp->next.sig.common.next;
+ }
+
+ if (yp->last.in_msgq) {
+ remove_nm_sig(c_p, sig, next_nm_sig);
+ }
+ else {
+ /*
+ * Replace adj-msgq signal with 'last' yield marker.
+ *
+ * This is in the middle queue after the point where
+ * we've begun using 'prev_next' pointers for receive
+ * markers, so if a receive marker follow, we do not
+ * need to adjust its 'prev_next'.
+ */
+ ErtsMessage **next_sig = *next_nm_sig;
+ yp->last.in_msgq = (char) !0;
+ yp->last.in_sigq = (char) !0;
+ yp->last.prev_next = next_sig;
+ *next_nm_sig = ((ErtsSignal *) sig)->common.specific.next;
+ *next_sig = (ErtsMessage *) &yp->last;
+ remove_mq_sig(c_p, sig, &yp->last.sig.common.next, next_nm_sig);
+
+ ERTS_SIG_DBG_RECV_MARK_SET_HANDLED(&yp->last);
+ }
+
+ save_delayed_nm_signal(saved_sigs, sig);
+}
+
+static ERTS_INLINE void
+destroy_adj_msgq_yield_markers(Process *c_p, ErtsYieldAdjMsgQ **ypp)
+{
+ ErtsYieldAdjMsgQ *yp = *ypp;
+ if (yp) {
+ if (yp->next.in_msgq)
+ remove_yield_marker(c_p, &yp->next);
+ if (yp->last.in_msgq)
+ remove_yield_marker(c_p, &yp->last);
+ erts_free(ERTS_ALC_T_SIG_YIELD_DATA, yp);
+ *ypp = NULL;
+ }
+}
+
static Uint
area_literal_size(Eterm* start, Eterm* end, char* lit_start, Uint lit_size)
{
@@ -6523,17 +7195,16 @@ static int
handle_cla(Process *c_p,
ErtsMessage *sig,
ErtsMessage ***next_nm_sig,
- int exiting)
+ int exiting,
+ int limit,
+ ErtsSavedNMSignals *saved_nm_sigs)
{
- /*
- * TODO: Implement yielding support!
- */
ErtsCLAData *cla;
- ErtsMessage *msg;
+ ErtsMessage *msg, *endp;
ErtsLiteralArea *la;
char *literals;
Uint lit_bsize;
- int nmsgs, reds;
+ int nmsgs, reds, stretch_yield_limit = 0;
Eterm result = am_ok;
Uint64 cnt = 0;
@@ -6554,6 +7225,30 @@ handle_cla(Process *c_p,
* can therefore occur behind this signal.
*/
+ msg = c_p->sig_qs.first;
+ if (!msg)
+ msg = c_p->sig_qs.cont;
+
+ if (!cla->yield) {
+ endp = sig;
+ }
+ else {
+ if (!cla->yield->next.in_msgq) {
+ /* All messages already handled... */
+ ASSERT(!cla->yield->last.in_msgq);
+ stretch_yield_limit = !0;
+ endp = msg = sig;
+ }
+ else {
+ ASSERT(!!cla->yield->last.in_msgq);
+ msg = cla->yield->next.sig.common.next;
+ endp = (ErtsMessage *) &cla->yield->last;
+ remove_yield_marker(c_p, &cla->yield->next);
+ }
+ }
+
+ ASSERT(!cla->yield || !cla->yield->next.in_msgq);
+
la = ERTS_COPY_LITERAL_AREA();
if (!la) {
ASSERT(0);
@@ -6566,12 +7261,8 @@ handle_cla(Process *c_p,
literals = (char *) &la->start[0];
lit_bsize = (char *) la->end - literals;
- msg = c_p->sig_qs.first;
- if (!msg)
- msg = c_p->sig_qs.cont;
-
nmsgs = 0;
- while (msg != sig) {
+ while (msg != endp) {
ASSERT(!!msg);
nmsgs++;
if (nmsgs >= ERTS_PROC_SIG_ADJ_MSGQ_MSGS_FACTOR) {
@@ -6586,7 +7277,7 @@ handle_cla(Process *c_p,
/*
* If a literal to copy is found in the message, we make
* an explicit copy of it in a heap fragment and attach
- * that heap fragment to the messag. Each message needs
+ * that heap fragment to the message. Each message needs
* to be self contained, we cannot save the literal at
* any other place than in the message itself.
*/
@@ -6666,6 +7357,18 @@ handle_cla(Process *c_p,
}
}
+ if (cnt > limit) { /* yield... */
+ ErtsMessage **nextpp = !msg->next ? &c_p->sig_qs.cont : &msg->next;
+ ASSERT(*nextpp);
+ if (*nextpp == endp)
+ break; /* we're at the end; no point yielding here... */
+ if (!cla->yield)
+ cla->yield = create_yield_adj_msgq_data(c_p);
+ insert_adj_msgq_yield_markers(c_p, cla->yield, nextpp,
+ next_nm_sig, saved_nm_sigs);
+ return cnt;
+ }
+
msg = msg->next;
if (!msg)
msg = c_p->sig_qs.cont;
@@ -6673,18 +7376,36 @@ handle_cla(Process *c_p,
remove_nm_sig(c_p, sig, next_nm_sig);
- reds = 0;
- if (erts_check_copy_literals_gc_need(c_p, &reds, literals, lit_bsize))
- result = am_need_gc;
-
- cnt += reds * ERTS_SIG_REDS_CNT_FACTOR;
+ reds = erts_check_copy_literals_gc_need_max_reds(c_p);
+ cnt++;
+ if (reds > CONTEXT_REDS)
+ result = am_check_gc;
+ else if (stretch_yield_limit
+ || cnt + reds*ERTS_SIG_REDS_CNT_FACTOR <= limit) {
+ reds = 0;
+ if (erts_check_copy_literals_gc_need(c_p, &reds, literals, lit_bsize))
+ result = am_need_gc;
+ cnt += reds * ERTS_SIG_REDS_CNT_FACTOR;
+ }
+ else {
+ /* yield... */
+ if (!cla->yield)
+ cla->yield = create_yield_adj_msgq_data(c_p);
+ else if (!!cla->yield->last.in_msgq)
+ remove_yield_marker(c_p, &cla->yield->last);
+ ASSERT(!cla->yield->next.in_msgq);
+ save_delayed_nm_signal(saved_nm_sigs, sig);
+ return cnt;
+ }
done:
+ destroy_adj_msgq_yield_markers(c_p, &cla->yield);
+
send_cla_reply(c_p, sig, cla->requester, cla->request_id, result);
- if (cnt > CONTEXT_REDS)
- return CONTEXT_REDS;
+ if (cnt > CONTEXT_REDS*ERTS_SIG_REDS_CNT_FACTOR)
+ return CONTEXT_REDS*ERTS_SIG_REDS_CNT_FACTOR;
return cnt;
}
@@ -6692,12 +7413,12 @@ static int
handle_move_msgq_off_heap(Process *c_p,
ErtsMessage *sig,
ErtsMessage ***next_nm_sig,
- int exiting)
+ int exiting,
+ int limit,
+ ErtsSavedNMSignals *saved_nm_sigs)
{
- /*
- * TODO: Implement yielding support!
- */
- ErtsMessage *msg;
+ ErtsAdjOffHeapMsgQData *ohdp;
+ ErtsMessage *msg, *endp;
int nmsgs;
Uint64 cnt = 0;
@@ -6717,6 +7438,8 @@ handle_move_msgq_off_heap(Process *c_p,
cnt++;
+ ohdp = get_move_msgq_off_heap_data(sig);
+
if (exiting) {
/* signal already removed from queue... */
goto cleanup;
@@ -6737,8 +7460,21 @@ handle_move_msgq_off_heap(Process *c_p,
if (!msg)
msg = c_p->sig_qs.cont;
+ if (!ohdp->yield) {
+ endp = sig;
+ }
+ else {
+ ASSERT(!!ohdp->yield->next.in_msgq);
+ ASSERT(!!ohdp->yield->last.in_msgq);
+ msg = ohdp->yield->next.sig.common.next;
+ endp = (ErtsMessage *) &ohdp->yield->last;
+ remove_yield_marker(c_p, &ohdp->yield->next);
+ }
+
+ ASSERT(!ohdp->yield || !ohdp->yield->next.in_msgq);
+
nmsgs = 0;
- while (msg != sig) {
+ while (msg != endp) {
ASSERT(!!msg);
nmsgs++;
if (nmsgs >= ERTS_PROC_SIG_ADJ_MSGQ_MSGS_FACTOR) {
@@ -6815,6 +7551,18 @@ handle_move_msgq_off_heap(Process *c_p,
cnt += h_sz/ERTS_PROC_SIG_ADJ_MSGQ_COPY_FACTOR;
}
+ if (cnt > limit) { /* yield... */
+ ErtsMessage **nextpp = !msg->next ? &c_p->sig_qs.cont : &msg->next;
+ ASSERT(*nextpp);
+ if (*nextpp == endp)
+ break; /* we're at the end; no point yielding... */
+ if (!ohdp->yield)
+ ohdp->yield = create_yield_adj_msgq_data(c_p);
+ insert_adj_msgq_yield_markers(c_p, ohdp->yield, nextpp,
+ next_nm_sig, saved_nm_sigs);
+ return cnt;
+ }
+
msg = msg->next;
if (!msg)
msg = c_p->sig_qs.cont;
@@ -6826,13 +7574,15 @@ done:
cleanup:
+ destroy_adj_msgq_yield_markers(c_p, &ohdp->yield);
sig->next = NULL;
+ sig->data.attached = ERTS_MSG_COMBINED_HFRAG;
erts_cleanup_messages(sig);
c_p->sig_qs.flags &= ~FS_OFF_HEAP_MSGQ_CHNG;
- if (cnt > CONTEXT_REDS)
- return CONTEXT_REDS;
+ if (cnt > CONTEXT_REDS*ERTS_SIG_REDS_CNT_FACTOR)
+ return CONTEXT_REDS*ERTS_SIG_REDS_CNT_FACTOR;
return cnt;
}
@@ -7060,7 +7810,8 @@ erts_proc_sig_prep_msgq_for_inspection(Process *c_p,
Process *rp,
ErtsProcLocks rp_locks,
int info_on_self,
- ErtsMessageInfo *mip)
+ ErtsMessageInfo *mip,
+ Sint *msgq_len_p)
{
Uint tot_heap_size;
ErtsMessage *mp, **mpp;
@@ -7134,7 +7885,11 @@ erts_proc_sig_prep_msgq_for_inspection(Process *c_p,
mp = mp->next;
}
- ASSERT(c_p->sig_qs.len == i);
+
+ ASSERT(info_on_self || c_p->sig_qs.len == i);
+ ASSERT(!info_on_self || c_p->sig_qs.len >= i);
+
+ *msgq_len_p = i;
return tot_heap_size;
}
@@ -7223,7 +7978,6 @@ erts_internal_dirty_process_handle_signals_1(BIF_ALIST_1)
BIF_RET(am_normal); /* will handle signals itself... */
}
else {
- erts_aint32_t state;
int done;
Eterm res = am_false;
int reds = 0;
@@ -7269,9 +8023,13 @@ erts_proc_sig_cleanup_queues(Process *c_p)
while (sig) {
ErtsMessage *free_sig = sig;
sig = sig->next;
- if (ERTS_SIG_IS_RECV_MARKER(free_sig))
- recv_marker_deallocate(c_p, (ErtsRecvMarker *) free_sig);
+ if (ERTS_SIG_IS_RECV_MARKER(free_sig)) {
+ ErtsRecvMarker *recv_mark = (ErtsRecvMarker *) free_sig;
+ ASSERT(!recv_mark->is_yield_mark);
+ recv_marker_deallocate(c_p, recv_mark);
+ }
else {
+ ASSERT(ERTS_SIG_IS_MSG(free_sig));
free_sig->next = NULL;
erts_cleanup_messages(free_sig);
}
@@ -7289,14 +8047,16 @@ erts_proc_sig_cleanup_queues(Process *c_p)
#endif
}
-/* Debug */
-
-static void
-wait_handle_signals(Process *c_p)
+void
+erts_proc_sig_do_wait_dirty_handle_signals__(Process *c_p)
{
/*
- * Process needs to wait on a dirty process signal
- * handler before it can handle signals by itself...
+ * A dirty process signal handler is currently handling
+ * signals for this process, so it is not safe for this
+ * process to continue to execute. This process needs to
+ * wait for the dirty signal handling to complete before
+ * it can continue executing. This since otherwise the
+ * signal queue can be seen in an inconsistent state.
*
* This should be a quite rare event. This only occurs
* when all of the following occurs:
@@ -7305,14 +8065,17 @@ wait_handle_signals(Process *c_p)
* * A dirty process signal handler starts handling
* signals for the process and unlocks the main
* lock while doing so. This can currently only
- * occur if handling an 'unlink' signal from a port.
+ * occur if handling an 'unlink' signal from a port, or
+ * when handling an alias message where the alias
+ * has been created when monitoring a port using
+ * '{alias, reply_demonitor}' option.
* * While the dirty process signal handler is handling
* signals for the process, the process stops executing
* dirty, gets scheduled on a normal scheduler, and
* then tries to handle signals itself.
*
- * If the above happens, the normal sceduler executing
- * the process will wait here until the dirty process
+ * If the above happens, the normal scheduler scheduling
+ * in the process will wait here until the dirty process
* signal handler is done with the process...
*/
erts_tse_t *event;
@@ -7340,18 +8103,17 @@ wait_handle_signals(Process *c_p)
erts_tse_return(event);
c_p->sig_qs.flags &= ~FS_WAIT_HANDLE_SIGS;
- c_p->sig_qs.flags |= FS_HANDLING_SIGS;
}
static void
wake_handle_signals(Process *proc)
{
/*
- * Wake scheduler sleeping in wait_handle_signals()
+ * Wake scheduler waiting in erts_proc_sig_check_wait_dirty_handle_signals()
* (above)...
*
- * This function should only be called by a dirty process
- * signal handler process...
+ * This function should only be called by a dirty process signal handler
+ * process...
*/
#ifdef DEBUG
Process *c_p = erts_get_current_process();
@@ -7369,6 +8131,8 @@ wake_handle_signals(Process *proc)
erts_tse_set(proc->scheduler_data->aux_work_data.ssi->event);
}
+/* Debug */
+
static void
debug_foreach_sig_heap_frags(ErlHeapFragment *hfrag,
void (*oh_func)(ErlOffHeap *, void *),
@@ -7457,6 +8221,7 @@ erts_proc_sig_debug_foreach_sig(Process *c_p,
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
mon_func((ErtsMonitor *) sig, arg, -1);
break;
@@ -7467,14 +8232,21 @@ erts_proc_sig_debug_foreach_sig(Process *c_p,
break;
case ERTS_SIG_Q_OP_ADJ_MSGQ:
- if (type == ERTS_SIG_Q_TYPE_OFF_HEAP)
- break;
- /* Fall through... */
case ERTS_SIG_Q_OP_PERSISTENT_MON_MSG:
- case ERTS_SIG_Q_OP_ALIAS_MSG:
debug_foreach_sig_heap_frags(&sig->hfrag, oh_func, arg);
break;
+ case ERTS_SIG_Q_OP_ALIAS_MSG: {
+ ErlHeapFragment *hfp;
+ if (type == ERTS_SIG_Q_TYPE_OFF_HEAP)
+ hfp = &sig->hfrag;
+ else if (type == ERTS_SIG_Q_TYPE_HEAP_FRAG)
+ hfp = sig->data.heap_frag;
+ else
+ break; /* on heap */
+ debug_foreach_sig_heap_frags(hfp, oh_func, arg);
+ }
+
case ERTS_SIG_Q_OP_DEMONITOR:
if (type == ERTS_SIG_Q_TYPE_DIST_PROC_DEMONITOR) {
debug_foreach_sig_fake_oh(((ErtsSigDistProcDemonitor *) sig)->ref,
@@ -7512,6 +8284,7 @@ erts_proc_sig_debug_foreach_sig(Process *c_p,
case ERTS_SIG_Q_OP_PROCESS_INFO:
case ERTS_SIG_Q_OP_RECV_MARK:
case ERTS_SIG_Q_OP_MSGQ_LEN_OFFS_MARK:
+ case ERTS_SIG_Q_OP_FLUSH:
break;
default:
@@ -7801,7 +8574,10 @@ proc_sig_hdbg_check_queue(Process *proc,
if (sig_psflg != ERTS_PSFLG_FREE) {
erts_aint32_t state = erts_atomic32_read_nob(&proc->state);
- ERTS_ASSERT(nm_sigs ? !!(state & sig_psflg) : !(state & sig_psflg));
+ ERTS_ASSERT(nm_sigs
+ ? !!(state & sig_psflg)
+ : (!(state & sig_psflg)
+ || !!erts_atomic_read_nob(&proc->sig_inq_buffers)));
}
return msg_len;
@@ -7865,3 +8641,494 @@ erts_proc_sig_hdbg_check_in_queue(Process *p, char *what, char *file, int line)
}
#endif /* ERTS_PROC_SIG_HARD_DEBUG */
+
+void erts_proc_sig_queue_lock(Process* proc)
+{
+ if (EBUSY == erts_proc_trylock(proc, ERTS_PROC_LOCK_MSGQ)) {
+ erts_proc_lock(proc, ERTS_PROC_LOCK_MSGQ);
+ proc->sig_inq_contention_counter += 1;
+ } else if(proc->sig_inq_contention_counter > 0) {
+ proc->sig_inq_contention_counter -= 1;
+ }
+}
+
+static void proc_sig_queue_lock_buffer(ErtsSignalInQueueBuffer* slot)
+{
+ erts_mtx_lock(&slot->b.lock);
+}
+
+static void proc_sig_queue_unlock_buffer(ErtsSignalInQueueBuffer* slot)
+{
+ erts_mtx_unlock(&slot->b.lock);
+}
+
+int
+erts_proc_sig_queue_try_enqueue_to_buffer(Eterm from,
+ Process* receiver,
+ ErtsProcLocks receiver_locks,
+ ErtsMessage* first,
+ ErtsMessage** last,
+ ErtsMessage** last_next,
+ Uint len,
+ int is_nonmsg_signal_enqueue)
+{
+ int need_unget_buffers;
+ ErtsSignalInQueueBufferArray* buffers;
+ if ((receiver_locks & ERTS_PROC_LOCK_MSGQ) ||
+ NULL == (buffers = erts_proc_sig_queue_get_buffers(receiver, &need_unget_buffers))) {
+ /* We never need to unget the buffers array if we do not get it */
+ return 0;
+ } else {
+ int is_nonmsg_signal_or_multi_sig;
+ ErtsSignalInQueueBuffer* buffer;
+ Uint64 nonempty_slots_before;
+ Uint32 slot, state;
+
+ ASSERT(is_value(from));
+
+ /* Use the sender id to hash to an outer signal queue buffer. This
+ * guarantees that all signals from the same process are ordered in
+ * send order. */
+ slot = make_internal_hash(from, 0) %
+ ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS;
+ buffer = &buffers->slots[slot];
+ nonempty_slots_before = 1;
+
+ /* Multiple signals or is_nonmsg_signal_enqueue means that we
+ * report that there is a non-msg signal in the queue. */
+ is_nonmsg_signal_or_multi_sig = is_nonmsg_signal_enqueue ||
+ !(last == &first->next);
+
+ proc_sig_queue_lock_buffer(buffer);
+
+ if ( ! buffer->b.alive ) {
+ /*
+ * The enqueue attempt fails if the buffer is dead. This
+ * means that the buffer array has got uninstalled.
+ */
+ proc_sig_queue_unlock_buffer(buffer);
+ erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);
+ return 0;
+ }
+ /*
+ * The buffer is alive and locked. This means that it is safe
+ * to insert signals to it
+ */
+
+ if (&buffer->b.queue.first == buffer->b.queue.last) {
+ /* The buffer is empty so we need to notify the receiver
+ * unless some other slot is nonempty (in that case
+ * another enqueuer has already (or will) notified the
+ * receiver).
+ */
+ nonempty_slots_before =
+ (Uint64)erts_atomic64_read_bor_nob(&buffers->nonempty_slots,
+ (erts_aint64_t)(((Uint64)1) << slot));
+ }
+
+ if (is_nonmsg_signal_or_multi_sig && !buffer->b.queue.nmsigs.next) {
+ /*
+ * Inserting nonmsg signal and no nonmsg signals in buffer
+ * before. This means that we have to update the nonmsg
+ * status of this buffer in the buffers structure.
+ *
+ * Acquire barrier is used since we do not want this
+ * operation to be reordered with setting the
+ * ERTS_PSFLG_SIG_IN_Q flag inside the enqueue_signals
+ * call below.
+ */
+ erts_atomic64_read_bor_mb(&buffers->nonmsg_slots,
+ (erts_aint64_t)(((Uint64)1) << slot));
+ }
+
+ state = erts_atomic32_read_nob(&receiver->state);
+
+ if (last == &first->next && !is_nonmsg_signal_or_multi_sig) {
+ /*
+ * Optimization for the common case of a single message
+ * signal.
+ */
+ ASSERT(len == 1);
+ ASSERT(ERTS_SIG_IS_MSG(first));
+ *buffer->b.queue.last = first;
+ buffer->b.queue.last = &first->next;
+ buffer->b.queue.len++;
+ } else {
+ state =
+ enqueue_signals(receiver,
+ first,
+ last,
+ last_next,
+ len,
+ state,
+ &buffer->b.queue);
+ }
+ buffer->b.nr_of_enqueues += 1;
+
+ proc_sig_queue_unlock_buffer(buffer);
+
+ /*
+ * The signal(s) are inserted into a buffer. However, we are
+ * not done because we need to notify the scheduler about that
+ * we have new signals.
+ */
+
+ if (!nonempty_slots_before) {
+
+ /*
+ * There is one situation in which we need to synchronize
+ * with the ERTS_PROC_LOCK_MSGQ lock:
+ *
+ * The buffer we inserted to was empty before we inserted
+ * to it, and no other buffer was marked as nonempty. In
+ * this case the process might hold the
+ * ERTS_PROC_LOCK_MSGQ to check if there are any more
+ * messages. If the process does not find any messages,
+ * it tells the scheduler to put the process to sleep
+ * while still holding the lock. Therefore, we wait until
+ * the ERTS_PROC_LOCK_MSGQ is released before we requests
+ * the scheduler to schedule the process (with a call to
+ * erts_proc_notify_new_message or
+ * erts_proc_notify_new_sig) so the request does not get
+ * overwritten by the sleep request.
+ *
+ */
+
+ erts_proc_lock_wait_until_released(receiver, ERTS_PROC_LOCK_MSGQ);
+ }
+
+ if (is_nonmsg_signal_or_multi_sig) {
+ if (is_nonmsg_signal_enqueue) {
+ erts_proc_notify_new_sig(receiver, state, 0);
+ } else {
+ erts_proc_notify_new_sig(receiver, state, ERTS_PSFLG_ACTIVE);
+ }
+ } else {
+ erts_proc_notify_new_message(receiver, receiver_locks);
+ }
+ erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);
+ return 1;
+ }
+}
+
+
+static void sig_inq_concat(ErtsSignalInQueue* q1, ErtsSignalInQueue* q2)
+{
+ ErtsMessage** first_queue_last = q1->last;
+ /* Second queue should not be empty */
+ ASSERT(q2->last != &q2->first);
+ if (NULL == q1->nmsigs.next) {
+ /* There is no non-message signals in q1 but maybe in q2 */
+ if (q2->nmsigs.next != NULL) {
+ /* There is non-message signals in q2 but not in q1 */
+ if (q2->nmsigs.next == &q2->first) {
+ /* The first message in q2 is a non-message signal
+ (The next pointer to the first non-message signal
+ comes from the first queue) */
+ q1->nmsigs.next = first_queue_last;
+ } else {
+ /* Internal message in q2 is the first non-message signal */
+ q1->nmsigs.next = q2->nmsigs.next;
+ }
+ if (q2->nmsigs.next == q2->nmsigs.last) {
+ /* Only one non-message signal in q2 (q1->nmsigs.last
+ should be the same as q1->nmsigs.next which is
+ already set up correctly) */
+ q1->nmsigs.last = q1->nmsigs.next;
+ } else {
+ /* More than one non-message signals in q2 */
+ q1->nmsigs.last = q2->nmsigs.last;
+ }
+ }
+ } else if (NULL != q2->nmsigs.next) {
+ ErtsMessage** first_nmsig_in_q2;
+ /* We have non-message signals in both queues */
+ if (q2->nmsigs.next == &q2->first) {
+ /* The first signal in q2 is a non-message signal */
+ ErtsSignal *sig;
+ sig = (ErtsSignal *) *q1->nmsigs.last;
+ sig->common.specific.next = first_queue_last;
+ first_nmsig_in_q2 = first_queue_last;
+ } else {
+ /* The first signal in q2 is a message signal */
+ ErtsSignal *sig;
+ sig = (ErtsSignal *) *q1->nmsigs.last;
+ sig->common.specific.next = q2->nmsigs.next;
+ first_nmsig_in_q2 = q2->nmsigs.next;
+ }
+ if (q2->nmsigs.last == &q2->first) {
+ /* Only one non-message signal in q2 */
+ q1->nmsigs.last = first_nmsig_in_q2;
+ } else {
+ q1->nmsigs.last = q2->nmsigs.last;
+ }
+ }
+ *q1->last = q2->first;
+ q1->last = q2->last;
+ q1->len += q2->len;
+ ASSERT((!q1->nmsigs.next && !q1->nmsigs.last) || (q1->nmsigs.next && q1->nmsigs.last));
+}
+
+static Uint proc_sig_queue_flush_buffer(Process* proc,
+ Uint buffer_index,
+ ErtsSignalInQueueBufferArray* buffers)
+{
+ Uint nr_of_enqueues;
+ ErtsSignalInQueueBuffer* buf = &buffers->slots[buffer_index];
+ proc_sig_queue_lock_buffer(buf);
+ /* This function should only be called when there is at least one
+ item in the buffer */
+ ASSERT(buf->b.queue.first != NULL);
+ nr_of_enqueues = buf->b.nr_of_enqueues;
+ buf->b.nr_of_enqueues = 0;
+ ASSERT(nr_of_enqueues > 0);
+ if (buf->b.alive) {
+ sig_inq_concat(&proc->sig_inq, &buf->b.queue);
+ buf->b.queue.first = NULL;
+ buf->b.queue.last = &buf->b.queue.first;
+ buf->b.queue.len = 0;
+ buf->b.queue.nmsigs.next = NULL;
+ buf->b.queue.nmsigs.last = NULL;
+ }
+ /*
+ * The appropriate bit in &buffers->nonempty_slots needs to be
+ * cleared because a thread might have inserted something after
+ * all bits got cleared in erts_proc_sig_queue_flush_all_buffers.
+ */
+ erts_atomic64_read_band_nob(&buffers->nonempty_slots,
+ (erts_aint64_t)(~(((Uint64)1) << buffer_index)));
+ /*
+ * The nonmsg_slots flag for this slot also needs to be cleared so
+ * that the erts_proc_sig_fetch function can detect if it has
+ * reset the ERTS_PSFLG_SIG_IN_Q when it should not do that.
+ */
+ erts_atomic64_read_band_nob(&buffers->nonmsg_slots,
+ (erts_aint64_t)(~(((Uint64)1) << buffer_index)));
+ proc_sig_queue_unlock_buffer(buf);
+ return nr_of_enqueues;
+}
+
+
+ErtsSignalInQueueBufferArray*
+erts_proc_sig_queue_flush_get_buffers(Process* proc, int *need_unget_buffers)
+{
+ Uint i;
+ ErtsSignalInQueueBufferArray* buffers;
+ Uint64 nonempty_slots;
+ buffers = erts_proc_sig_queue_get_buffers(proc, need_unget_buffers);
+ if (NULL == buffers) {
+ return NULL;
+ }
+ nonempty_slots = (Uint64)erts_atomic64_xchg_nob(&buffers->nonempty_slots,
+ (erts_aint64_t)((Uint64)0));
+ if (nonempty_slots != 0) {
+ for(i = 0; i < ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS; i++) {
+ Uint64 slot_mask = (((Uint64)1) << i);
+ if (nonempty_slots & slot_mask) {
+ buffers->nr_of_enqueues +=
+ proc_sig_queue_flush_buffer(proc, i, buffers);
+ }
+ }
+ }
+ if (--buffers->nr_of_rounds_left == 0) {
+ /* Take decision if we should adapt back to the normal state */
+ if(buffers->nr_of_enqueues <
+ ERTS_PROC_SIG_INQ_BUFFERED_MIN_NO_ENQUEUES_TO_KEEP) {
+ erts_proc_sig_queue_flush_and_deinstall_buffers(proc);
+ } else {
+ buffers->nr_of_rounds_left =
+ ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE;
+ buffers->nr_of_enqueues = 0;
+ }
+ }
+ return buffers;
+}
+
+
+void
+erts_proc_sig_queue_flush_buffers(Process* proc)
+{
+ ErtsSignalInQueueBufferArray* buffers;
+ int need_undread_buffers;
+
+ ERTS_LC_ASSERT(ERTS_PROC_IS_EXITING(proc) ||
+ (erts_proc_lc_my_proc_locks(proc) & ERTS_PROC_LOCK_MSGQ));
+
+ buffers =
+ erts_proc_sig_queue_flush_get_buffers(proc, &need_undread_buffers);
+ erts_proc_sig_queue_unget_buffers(buffers, need_undread_buffers);
+}
+
+static void sigq_buffer_array_refc_dec(void *buffers_p)
+{
+ ErtsSignalInQueueBufferArray* buffers = buffers_p;
+ erts_proc_sig_queue_unget_buffers(buffers, 1);
+}
+
+
+static void schedule_sigq_buffer_array_refc_dec(void *buffers_p)
+{
+ ErtsSignalInQueueBufferArray* buffers = buffers_p;
+ erts_schedule_thr_prgr_later_cleanup_op(sigq_buffer_array_refc_dec,
+ buffers,
+ &buffers->free_item,
+ sizeof(ErtsSignalInQueueBufferArray));
+}
+
+void erts_proc_sig_queue_flush_and_deinstall_buffers(Process* proc)
+{
+ Uint i;
+ ErtsSignalInQueueBufferArray* buffers;
+ int need_unget_buffers;
+ ErtsSchedulerData *esdp;
+
+ ERTS_LC_ASSERT(ERTS_PROC_IS_EXITING(proc) ||
+ (erts_proc_lc_my_proc_locks(proc) & ERTS_PROC_LOCK_MSGQ));
+ buffers = erts_proc_sig_queue_get_buffers(proc, &need_unget_buffers);
+
+ if (buffers == NULL) {
+ return;
+ }
+
+ if (!buffers->alive) {
+ erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);;
+ return;
+ }
+
+ buffers->alive = 0;
+ proc->sig_inq_contention_counter = 0;
+
+ for (i = 0; i < ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS; i++) {
+ proc_sig_queue_lock_buffer(&buffers->slots[i]);
+
+ if (buffers->slots[i].b.queue.first != NULL) {
+ sig_inq_concat(&proc->sig_inq, &buffers->slots[i].b.queue);
+ }
+
+ buffers->slots[i].b.alive = 0;
+
+ proc_sig_queue_unlock_buffer(&buffers->slots[i]);
+ }
+
+ /* Nothing can be enqueued to the buffer array beyond this point. */
+
+ erts_atomic64_set_nob(&buffers->nonempty_slots, (erts_aint64_t)0);
+ erts_atomic64_set_nob(&buffers->nonmsg_slots, (erts_aint64_t)0);
+ erts_atomic_set_mb(&proc->sig_inq_buffers, (erts_aint_t)NULL);
+
+ erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);
+
+ /* Release the buffer array through thread progress, as a managed thread
+ * may be holding a reference to it. */
+ esdp = erts_get_scheduler_data();
+ if (esdp != NULL && esdp->type == ERTS_SCHED_NORMAL) {
+ schedule_sigq_buffer_array_refc_dec((void*)buffers);
+ } else {
+ /* We can't issue cleanup jobs on anything other than normal
+ * schedulers, so we move to the first scheduler if required. */
+ erts_schedule_misc_aux_work(1,
+ schedule_sigq_buffer_array_refc_dec,
+ buffers);
+ }
+}
+
+void erts_proc_sig_queue_maybe_install_buffers(Process* p, erts_aint32_t state)
+{
+ int i;
+ ErtsSignalInQueueBufferArray* buffers;
+ if (!(state & ERTS_PSFLG_OFF_HEAP_MSGQ) ||
+ (((ErtsSignalInQueueBufferArray*)erts_atomic_read_nob(&p->sig_inq_buffers)) != NULL) ||
+ (!ERTS_PROC_SIG_INQ_BUFFERED_ALWAYS_TURN_ON &&
+ p->sig_inq_contention_counter <= ERTS_PROC_SIG_INQ_BUFFERED_CONTENTION_INSTALL_LIMIT)) {
+ return;
+ }
+ p->sig_inq_contention_counter = 0;
+ buffers = erts_alloc(ERTS_ALC_T_SIGQ_BUFFERS,
+ sizeof(ErtsSignalInQueueBufferArray));
+ erts_atomic64_init_nob(&buffers->nonempty_slots, (erts_aint64_t)(Uint64)0);
+ erts_atomic64_init_nob(&buffers->nonmsg_slots, (erts_aint64_t)(Uint64)0);
+ erts_refc_init(&buffers->dirty_refc, 1);
+ buffers->nr_of_enqueues = 0;
+ buffers->nr_of_rounds_left =
+ ERTS_PROC_SIG_INQ_BUFFERED_MIN_FLUSH_ALL_OPS_BEFORE_CHANGE;
+ buffers->alive = 1;
+ /* Initialize slots */
+ for(i = 0; i < ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS; i++) {
+ buffers->slots[i].b.alive = 1;
+ erts_mtx_init(&buffers->slots[i].b.lock,
+ "proc_sig_queue_buffer",
+ NIL,
+ ERTS_LOCK_FLAGS_CATEGORY_PROCESS);
+ buffers->slots[i].b.queue.first = NULL;
+ buffers->slots[i].b.queue.last = &buffers->slots[i].b.queue.first;
+ buffers->slots[i].b.queue.len = 0;
+ buffers->slots[i].b.queue.nmsigs.next = NULL;
+ buffers->slots[i].b.queue.nmsigs.last = NULL;
+ buffers->slots[i].b.nr_of_enqueues = 0;
+ }
+ erts_atomic_set_relb(&p->sig_inq_buffers, (erts_aint_t)buffers);
+}
+
+ErtsSignalInQueueBufferArray*
+erts_proc_sig_queue_get_buffers(Process* p, int *need_unread)
+{
+ ErtsThrPrgrDelayHandle dhndl =
+ erts_thr_progress_unmanaged_delay();
+ ErtsSignalInQueueBufferArray* buffers =
+ (ErtsSignalInQueueBufferArray*)erts_atomic_read_acqb(&p->sig_inq_buffers);
+ *need_unread = 0;
+ if (ERTS_THR_PRGR_DHANDLE_MANAGED == dhndl) {
+ erts_thr_progress_unmanaged_continue(dhndl);
+ return buffers;
+ }
+ if (buffers == NULL) {
+ erts_thr_progress_unmanaged_continue(dhndl);
+ return NULL;
+ }
+ erts_refc_inc(&buffers->dirty_refc, 2);
+ erts_thr_progress_unmanaged_continue(dhndl);
+ *need_unread = 1;
+ return buffers;
+}
+
+void erts_proc_sig_queue_unget_buffers(ErtsSignalInQueueBufferArray* buffers,
+ int need_unget)
+{
+ if (!need_unget) {
+ return;
+ } else {
+ int i;
+ erts_aint_t refc = erts_refc_dectest(&buffers->dirty_refc, 0);
+ if (refc != 0) {
+ return;
+ }
+ ASSERT(!buffers->alive);
+ for (i = 0; i < ERTS_PROC_SIG_INQ_BUFFERED_NR_OF_BUFFERS; i++) {
+ ASSERT(!buffers->slots[i].b.alive);
+ erts_mtx_destroy(&buffers->slots[i].b.lock);
+ }
+ erts_free(ERTS_ALC_T_SIGQ_BUFFERS, buffers);
+ }
+}
+
+/* Only for test purposes */
+int erts_proc_sig_queue_force_buffers(Process* p)
+{
+ erts_aint32_t state;
+ ErtsSignalInQueueBufferArray* buffers;
+
+ erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
+ state = erts_atomic32_read_nob(&p->state);
+ /* Fake contention */
+ p->sig_inq_contention_counter =
+ 1 + ERTS_PROC_SIG_INQ_BUFFERED_CONTENTION_INSTALL_LIMIT;
+ erts_proc_sig_queue_maybe_install_buffers(p, state);
+ buffers = ((ErtsSignalInQueueBufferArray*)
+ erts_atomic_read_nob(&p->sig_inq_buffers));
+ if (buffers) {
+ /* "Prevent" buffer deinstallation */
+ buffers->nr_of_rounds_left = ERTS_UINT_MAX;
+ }
+ erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ return buffers != NULL;
+}
diff --git a/erts/emulator/beam/erl_proc_sig_queue.h b/erts/emulator/beam/erl_proc_sig_queue.h
index 66ee35d1f7..60c7af5e66 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.h
+++ b/erts/emulator/beam/erl_proc_sig_queue.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,6 +91,9 @@
#if 0
# define ERTS_PROC_SIG_HARD_DEBUG_RECV_MARKER
#endif
+#if 0
+# define ERTS_PROC_SIG_HARD_DEBUG_SIGQ_BUFFERS
+#endif
struct erl_mesg;
struct erl_dist_external;
@@ -107,7 +110,7 @@ typedef struct {
* Note that not all signal are handled using this functionality!
*/
-#define ERTS_SIG_Q_OP_MAX 18
+#define ERTS_SIG_Q_OP_MAX 19
#define ERTS_SIG_Q_OP_EXIT 0 /* Exit signal due to bif call */
#define ERTS_SIG_Q_OP_EXIT_LINKED 1 /* Exit signal due to link break*/
@@ -127,7 +130,8 @@ typedef struct {
#define ERTS_SIG_Q_OP_ALIAS_MSG 15
#define ERTS_SIG_Q_OP_RECV_MARK 16
#define ERTS_SIG_Q_OP_UNLINK_ACK 17
-#define ERTS_SIG_Q_OP_ADJ_MSGQ ERTS_SIG_Q_OP_MAX
+#define ERTS_SIG_Q_OP_ADJ_MSGQ 18
+#define ERTS_SIG_Q_OP_FLUSH ERTS_SIG_Q_OP_MAX
#define ERTS_SIG_Q_TYPE_MAX (ERTS_MON_LNK_TYPE_MAX + 10)
@@ -238,6 +242,27 @@ void erl_proc_sig_hdbg_chk_recv_marker_block(struct process *c_p);
#include "erl_process.h"
#include "erl_bif_unique.h"
+
+void erts_proc_sig_queue_maybe_install_buffers(Process* p, erts_aint32_t state);
+void erts_proc_sig_queue_flush_and_deinstall_buffers(Process* proc);
+void erts_proc_sig_queue_flush_buffers(Process* proc);
+ErtsSignalInQueueBufferArray*
+erts_proc_sig_queue_flush_get_buffers(Process* proc, int *need_unget_buffers);
+void erts_proc_sig_queue_lock(Process* proc);
+ErtsSignalInQueueBufferArray*
+erts_proc_sig_queue_get_buffers(Process* p, int *need_unread);
+void erts_proc_sig_queue_unget_buffers(ErtsSignalInQueueBufferArray* buffers,
+ int need_unget);
+int erts_proc_sig_queue_try_enqueue_to_buffer(Eterm from,
+ Process* receiver,
+ ErtsProcLocks receiver_locks,
+ ErtsMessage* first,
+ ErtsMessage** last,
+ ErtsMessage** last_next,
+ Uint len,
+ int is_signal);
+int erts_proc_sig_queue_force_buffers(Process*);
+
#define ERTS_SIG_Q_OP_BITS 8
#define ERTS_SIG_Q_OP_SHIFT 0
#define ERTS_SIG_Q_OP_MASK ((1 << ERTS_SIG_Q_OP_BITS) - 1)
@@ -304,8 +329,10 @@ struct dist_entry_;
* @brief Send an exit signal to a process.
*
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
* @param[in] from Identifier of sender.
*
@@ -322,7 +349,7 @@ struct dist_entry_;
*
*/
void
-erts_proc_sig_send_exit(Process *c_p, Eterm from, Eterm to,
+erts_proc_sig_send_exit(ErtsPTabElementCommon *sender, Eterm from, Eterm to,
Eterm reason, Eterm token, int normal_kills);
/**
@@ -359,11 +386,26 @@ erts_proc_sig_send_dist_exit(DistEntry *dep,
/**
*
+ * @brief Send an exit signal due to a link to a process being
+ * broken by connection loss.
+ *
+ * @param[in] lnk Pointer to link structure
+ * from the sending side. It
+ * should contain information
+ * about receiver.
+ */
+void
+erts_proc_sig_send_link_exit_noconnection(ErtsLink *lnk);
+
+/**
+ *
* @brief Send an exit signal due to broken link to a process.
*
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
* @param[in] from Identifier of sender.
*
@@ -378,16 +420,18 @@ erts_proc_sig_send_dist_exit(DistEntry *dep,
*
*/
void
-erts_proc_sig_send_link_exit(Process *c_p, Eterm from, ErtsLink *lnk,
- Eterm reason, Eterm token);
+erts_proc_sig_send_link_exit(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsLink *lnk, Eterm reason, Eterm token);
/**
*
* @brief Send an link signal to a process.
*
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
* @param[in] to Identifier of receiver.
*
@@ -405,7 +449,8 @@ erts_proc_sig_send_link_exit(Process *c_p, Eterm from, ErtsLink *lnk,
*
*/
int
-erts_proc_sig_send_link(Process *c_p, Eterm to, ErtsLink *lnk);
+erts_proc_sig_send_link(ErtsPTabElementCommon *sender, Eterm from,
+ Eterm to, ErtsLink *lnk);
/**
*
@@ -414,15 +459,15 @@ erts_proc_sig_send_link(Process *c_p, Eterm to, ErtsLink *lnk);
* The newly created unlink identifier is to be used in an
* unlink operation.
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
+ * @param[in] sender Pointer to the sending process/port.
*
* @return A new 64-bit unlink identifier
* unique in context of the
* calling process. The identifier
* may be any value but zero.
*/
-ERTS_GLB_INLINE Uint64 erts_proc_sig_new_unlink_id(Process *c_p);
+ERTS_GLB_INLINE
+Uint64 erts_proc_sig_new_unlink_id(ErtsPTabElementCommon *sender);
/**
*
@@ -431,13 +476,10 @@ ERTS_GLB_INLINE Uint64 erts_proc_sig_new_unlink_id(Process *c_p);
* The structure will contain a newly created unlink
* identifier to be used in the operation.
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process
- * ('from' is a process
- * identifier), or NULL if not
- * called in the context of an
- * executing process ('from' is
- * a port identifier).
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
* @param[in] from Id (as an erlang term) of
* entity sending the unlink
@@ -447,7 +489,7 @@ ERTS_GLB_INLINE Uint64 erts_proc_sig_new_unlink_id(Process *c_p);
* structure.
*/
ErtsSigUnlinkOp *
-erts_proc_sig_make_unlink_op(Process *c_p, Eterm from);
+erts_proc_sig_make_unlink_op(ErtsPTabElementCommon *sender, Eterm from);
/**
*
@@ -464,8 +506,10 @@ erts_proc_sig_destroy_unlink_op(ErtsSigUnlinkOp *sulnk);
* @brief Send an unlink signal to a process.
*
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
* @param[in] from Id (as an erlang term) of
* entity sending the unlink
@@ -477,15 +521,18 @@ erts_proc_sig_destroy_unlink_op(ErtsSigUnlinkOp *sulnk);
* receiver.
*/
Uint64
-erts_proc_sig_send_unlink(Process *c_p, Eterm from, ErtsLink *lnk);
+erts_proc_sig_send_unlink(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsLink *lnk);
/**
*
* @brief Send an unlink acknowledgment signal to a process.
*
- *
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
+ *
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
* @param[in] from Id (as an erlang term) of
* entity sending the unlink
@@ -498,7 +545,7 @@ erts_proc_sig_send_unlink(Process *c_p, Eterm from, ErtsLink *lnk);
* signal.
*/
void
-erts_proc_sig_send_unlink_ack(Process *c_p, Eterm from,
+erts_proc_sig_send_unlink_ack(ErtsPTabElementCommon *sender, Eterm from,
ErtsSigUnlinkOp *sulnk);
/**
@@ -560,11 +607,6 @@ erts_proc_sig_send_dist_unlink(DistEntry *dep, Uint32 conn_id,
* This function is used instead of erts_proc_sig_send_unlink_ack()
* when the signal arrives via the distribution.
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process or
- * NULL if not called in the context
- * of an executing process.
- *
* @param[in] dep Distribution entry of channel
* that the signal arrived on.
*
@@ -575,7 +617,7 @@ erts_proc_sig_send_dist_unlink(DistEntry *dep, Uint32 conn_id,
* @param[in] id Identifier of unlink operation.
*/
void
-erts_proc_sig_send_dist_unlink_ack(Process *c_p, DistEntry *dep,
+erts_proc_sig_send_dist_unlink_ack(DistEntry *dep,
Uint32 conn_id, Eterm from, Eterm to,
Uint64 id);
@@ -583,6 +625,14 @@ erts_proc_sig_send_dist_unlink_ack(Process *c_p, DistEntry *dep,
*
* @brief Send a monitor down signal to a process.
*
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
+ *
+ * @param[in] from Sending entity, must be provided
+ * to maintain signal order.
+ *
* @param[in] mon Pointer to target monitor
* structure from the sending
* side. It should contain
@@ -592,27 +642,48 @@ erts_proc_sig_send_dist_unlink_ack(Process *c_p, DistEntry *dep,
*
*/
void
-erts_proc_sig_send_monitor_down(ErtsMonitor *mon, Eterm reason);
+erts_proc_sig_send_monitor_down(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsMonitor *mon, Eterm reason);
/**
*
* @brief Send a demonitor signal to a process.
*
- * @param[in] mon Pointer to origin monitor
- * structure from the sending
- * side. It should contain
- * information about receiver.
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
*
- * @param[in] reason Exit reason.
+ * @param[in] from Sending entity, must be provided
+ * to maintain signal order.
+ *
+ * @param[in] system Whether the sender is considered a
+ * system service, e.g. a NIF monitor,
+ * and it's okay to order by `from`
+ * even when it's not a pid or port.
+ *
+ * @param[in] mon Pointer to origin monitor
+ * structure from the sending
+ * side. It should contain
+ * information about receiver.
*
*/
void
-erts_proc_sig_send_demonitor(ErtsMonitor *mon);
+erts_proc_sig_send_demonitor(ErtsPTabElementCommon *sender, Eterm from,
+ int system, ErtsMonitor *mon);
/**
*
* @brief Send a monitor signal to a process.
*
+ * @param[in] sender Pointer to the sending process/port,
+ * if any, as it may not be possible to
+ * resolve the sender (e.g. after it's
+ * dead).
+ *
+ * @param[in] from Sending entity, must be provided
+ * to maintain signal order.
+ *
* @param[in] mon Pointer to target monitor
* structure to insert on
* receiver side.
@@ -630,7 +701,8 @@ erts_proc_sig_send_demonitor(ErtsMonitor *mon);
*
*/
int
-erts_proc_sig_send_monitor(ErtsMonitor *mon, Eterm to);
+erts_proc_sig_send_monitor(ErtsPTabElementCommon *sender, Eterm from,
+ ErtsMonitor *mon, Eterm to);
/**
*
@@ -673,27 +745,22 @@ erts_proc_sig_send_dist_monitor_down(DistEntry *dep, Eterm ref,
* when the signal arrives via the distribution and
* no monitor structure is available.
*
+ * @param[in] from Identifier of sender.
+ *
* @param[in] to Identifier of receiver.
*
* @param[in] ref Reference identifying the monitor.
*
*/
void
-erts_proc_sig_send_dist_demonitor(Eterm to, Eterm ref);
+erts_proc_sig_send_dist_demonitor(Eterm from, Eterm to, Eterm ref);
/**
*
- * @brief Send a persistent monitor triggered signal to a process.
- *
- * Used by monitors that are not auto disabled such as for
- * example 'time_offset' monitors.
- *
- * @param[in] type Monitor type.
+ * @brief Send a persistent "node down" monitor signal to a process
*
* @param[in] key Monitor key.
*
- * @param[in] from Identifier of sender.
- *
* @param[in] to Identifier of receiver.
*
* @param[in] msg Message template.
@@ -702,27 +769,25 @@ erts_proc_sig_send_dist_demonitor(Eterm to, Eterm ref);
*
*/
void
-erts_proc_sig_send_persistent_monitor_msg(Uint16 type, Eterm key,
- Eterm from, Eterm to,
- Eterm msg, Uint msg_sz);
+erts_proc_sig_send_monitor_nodes_msg(Eterm key, Eterm to,
+ Eterm msg, Uint msg_sz);
/**
*
- * @brief Send a trace change signal to a process.
+ * @brief Send a persistent "time offset changed" monitor signal to a process
*
- * @param[in] to Identifier of receiver.
+ * @param[in] key Monitor key.
*
- * @param[in] on Trace flags to enable.
+ * @param[in] to Identifier of receiver.
*
- * @param[in] off Trace flags to disable.
+ * @param[in] msg Message template.
*
- * @param[in] tracer Tracer to set. If the non-value,
- * tracer will not be changed.
+ * @param[in] msg_sz Heap size of message template.
*
*/
void
-erts_proc_sig_send_trace_change(Eterm to, Uint on, Uint off,
- Eterm tracer);
+erts_proc_sig_send_monitor_time_offset_msg(Eterm key, Eterm to,
+ Eterm msg, Uint msg_sz);
/**
*
@@ -799,7 +864,7 @@ erts_proc_sig_send_is_alive_request(Process *c_p, Eterm to,
* @param[in] item_ix Info index array to pass to
* erts_process_info()
*
- * @param[in] len Lenght of info index array
+ * @param[in] len Length of info index array
*
* @param[in] need_msgq_len Non-zero if message queue
* length is needed; otherwise,
@@ -1043,14 +1108,11 @@ erts_proc_sig_send_cla_request(Process *c_p, Eterm to, Eterm req_id);
*
* When received, all on heap messages will be moved off heap.
*
- * @param[in] c_p Pointer to process struct of
- * currently executing process.
- *
* @param[in] to Identifier of receiver.
*
*/
void
-erts_proc_sig_send_move_msgq_off_heap(Process *c_p, Eterm to);
+erts_proc_sig_send_move_msgq_off_heap(Eterm to);
/*
* End of send operations of currently supported process signals.
@@ -1072,6 +1134,9 @@ erts_proc_sig_send_move_msgq_off_heap(Process *c_p, Eterm to);
*
* @param[out] statep Pointer to process state after
* signal handling. May not be NULL.
+ * The state should recently have
+ * been updated before calling
+ * this function.
*
* @param[in,out] redsp Pointer to an integer containing
* reductions. On input, the amount
@@ -1125,6 +1190,8 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
* used by the call. On output, the
* amount of reductions consumed.
*
+ * @param[in,out] pe_ctxtp Process exit context pointer.
+ *
* @return Returns a non-zero value, when
* no more signals to handle in the
* middle queue remain. A zero
@@ -1134,8 +1201,7 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
*/
int
erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
- ErtsMonitor **pend_spawn_mon_pp,
- Eterm reason);
+ ErtsProcExitContext *pe_ctxt_p);
/**
*
@@ -1191,6 +1257,58 @@ erts_proc_sig_receive_helper(Process *c_p, int fcalls,
int neg_o_reds, ErtsMessage **msgpp,
int *get_outp);
+/*
+ * CLEAN_SIGQ - Flush until middle queue is empty, i.e.
+ * the content of inner+middle queue equals
+ * the message queue.
+ */
+#define ERTS_PROC_SIG_FLUSH_FLG_CLEAN_SIGQ (1 << 0)
+/*
+ * FROM_ALL - Flush signals from all local senders (processes
+ * and ports).
+ */
+#define ERTS_PROC_SIG_FLUSH_FLG_FROM_ALL (1 << 1)
+/*
+ * FROM_ID - Flush signals from process or port identified
+ * by 'id'.
+ */
+#define ERTS_PROC_SIG_FLUSH_FLG_FROM_ID (1 << 2)
+
+/*
+ * All erts_proc_sig_init_flush_signals() flags.
+ */
+#define ERTS_PROC_SIG_FLUSH_FLGS \
+ (ERTS_PROC_SIG_FLUSH_FLG_CLEAN_SIGQ \
+ | ERTS_PROC_SIG_FLUSH_FLG_FROM_ALL \
+ | ERTS_PROC_SIG_FLUSH_FLG_FROM_ID)
+
+/**
+ *
+ * @brief Initialize flush of signals from another process or port
+ *
+ * Inserts a flush signal in the outer signal queue of
+ * current process and sets the FS_FLUSHING_SIGS flag in
+ * 'c_p->sig_qs.flags'. When the flush signal has been
+ * handled the FS_FLUSHED_SIGS flag is set as well.
+ *
+ * While the flushing is ongoing the process *should* only
+ * handle incoming signals and not execute Erlang code. When
+ * the functionality that initiated the flush detects that
+ * the flush is done by the FS_FLUSHED_SIGS flag being set,
+ * it should clear both the FS_FLUSHED_SIGS flag and the
+ * FS_FLUSHING_SIGS flag.
+ *
+ * @param[in] c_p Pointer to process struct of
+ * currently executing process.
+ * flags Flags indicating how to flush.
+ * (see above).
+ * from Identifier of sender to flush
+ * signals from in case the
+ * FROM_ID flag is set.
+ */
+void
+erts_proc_sig_init_flush_signals(Process *c_p, int flags, Eterm from);
+
/**
*
* @brief Fetch signals from the outer queue
@@ -1256,7 +1374,7 @@ erts_enqueue_signals(Process *rp, ErtsMessage *first,
*
*/
void
-erts_proc_sig_send_pending(ErtsSchedulerData* esdp);
+erts_proc_sig_send_pending(Process *c_p, ErtsSchedulerData* esdp);
void
@@ -1264,7 +1382,8 @@ erts_proc_sig_send_to_alias(Process *c_p, Eterm from, Eterm to,
Eterm msg, Eterm token);
void
-erts_proc_sig_send_dist_to_alias(Eterm alias, ErtsDistExternal *edep,
+erts_proc_sig_send_dist_to_alias(Eterm from, Eterm alias,
+ ErtsDistExternal *edep,
ErlHeapFragment *hfrag, Eterm token);
/**
@@ -1307,12 +1426,16 @@ typedef struct {
*
* @param[in] mip Pointer to array of
* ErtsMessageInfo structures.
+ *
+ * @param[out] msgq_lenp Pointer to integer containing
+ * amount of messages.
*/
Uint erts_proc_sig_prep_msgq_for_inspection(Process *c_p,
Process *rp,
ErtsProcLocks rp_locks,
int info_on_self,
- ErtsMessageInfo *mip);
+ ErtsMessageInfo *mip,
+ Sint *msgq_lenp);
/**
*
@@ -1390,6 +1513,26 @@ int
erts_proc_sig_decode_dist(Process *proc, ErtsProcLocks proc_locks,
ErtsMessage *msgp, int force_off_heap);
+/**
+ *
+ * @brief Check if a newly scheduled process needs to wait for
+ * ongoing dirty handling of signals to complete.
+ *
+ * @param[in] c_p Pointer to executing process.
+ *
+ * @param[in] state_in State of process.
+ *
+ * @return Updated state of process if
+ * we had to wait; otherwise,
+ * state_in.
+ */
+ERTS_GLB_INLINE erts_aint32_t
+erts_proc_sig_check_wait_dirty_handle_signals(Process *c_p,
+ erts_aint32_t state_in);
+
+void erts_proc_sig_do_wait_dirty_handle_signals__(Process *c_p);
+
+
ErtsDistExternal *
erts_proc_sig_get_external(ErtsMessage *msgp);
@@ -1613,7 +1756,7 @@ Eterm erts_msgq_recv_marker_create_insert(Process *c_p, Eterm id);
void erts_msgq_recv_marker_create_insert_set_save(Process *c_p, Eterm id);
ErtsMessage **erts_msgq_pass_recv_markers(Process *c_p,
ErtsMessage **markpp);
-void erts_msgq_remove_leading_recv_markers(Process *c_p);
+void erts_msgq_remove_leading_recv_markers_set_save_first(Process *c_p);
#define ERTS_RECV_MARKER_IX__(BLKP, MRKP) \
((int) ((MRKP) - &(BLKP)->marker[0]))
@@ -1621,14 +1764,30 @@ void erts_msgq_remove_leading_recv_markers(Process *c_p);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE Uint64
-erts_proc_sig_new_unlink_id(Process *c_p)
+erts_proc_sig_new_unlink_id(ErtsPTabElementCommon *sender)
{
Uint64 id;
- ASSERT(c_p);
- id = (Uint64) c_p->uniq++;
- if (id == 0)
+ ASSERT(sender);
+
+ if (is_internal_pid(sender->id)) {
+ Process *c_p = ErtsContainerStruct(sender, Process, common);
id = (Uint64) c_p->uniq++;
+
+ if (id == 0) {
+ id = (Uint64) c_p->uniq++;
+ }
+ } else {
+ ASSERT(is_internal_port(sender->id));
+
+ id = (Uint64) erts_raw_get_unique_monotonic_integer();
+ if (id == 0) {
+ id = (Uint64) erts_raw_get_unique_monotonic_integer();
+ }
+ }
+
+ ASSERT(id != 0);
+
return id;
}
@@ -1637,7 +1796,8 @@ erts_proc_sig_fetch(Process *proc)
{
Sint res = 0;
ErtsSignal *sig;
-
+ ErtsSignalInQueueBufferArray* buffers;
+ int need_unget_buffers;
ERTS_LC_ASSERT(ERTS_PROC_IS_EXITING(proc)
|| ((erts_proc_lc_my_proc_locks(proc)
& (ERTS_PROC_LOCK_MAIN
@@ -1645,9 +1805,18 @@ erts_proc_sig_fetch(Process *proc)
== (ERTS_PROC_LOCK_MAIN
| ERTS_PROC_LOCK_MSGQ)));
+ ASSERT(!(proc->sig_qs.flags & FS_FLUSHING_SIGS)
+ || ERTS_PROC_IS_EXITING(proc)
+ || ERTS_IS_CRASH_DUMPING);
+
+ ASSERT(!(proc->sig_qs.flags & FS_HANDLING_SIGS));
+
ERTS_HDBG_CHECK_SIGNAL_IN_QUEUE(proc);
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(proc, !0);
+ buffers = erts_proc_sig_queue_flush_get_buffers(proc,
+ &need_unget_buffers);
+
sig = (ErtsSignal *) proc->sig_inq.first;
if (sig) {
if (ERTS_LIKELY(sig->common.tag != ERTS_PROC_SIG_MSGQ_LEN_OFFS_MARK))
@@ -1655,7 +1824,20 @@ erts_proc_sig_fetch(Process *proc)
else
res = erts_proc_sig_fetch_msgq_len_offs__(proc);
}
-
+ if (buffers) {
+ Uint32 state = erts_atomic32_read_acqb(&proc->state);
+ if (!(ERTS_PSFLG_SIG_IN_Q & state) &&
+ erts_atomic64_read_nob(&buffers->nonmsg_slots)) {
+ /* We may have raced with a thread inserting into a buffer
+ * when resetting the flag ERTS_PSFLG_SIG_IN_Q in one of
+ * the fetch functions above so we have to make sure that
+ * it is set when there is a nonmsg signal in the buffers. */
+ erts_atomic32_read_bor_nob(&proc->state,
+ ERTS_PSFLG_SIG_IN_Q |
+ ERTS_PSFLG_ACTIVE);
+ }
+ erts_proc_sig_queue_unget_buffers(buffers, need_unget_buffers);
+ }
res += proc->sig_qs.len;
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(proc, !0);
@@ -1805,6 +1987,7 @@ erts_msgq_recv_marker_clear(Process *c_p, Eterm id)
{
ErtsRecvMarkerBlock *blkp = c_p->sig_qs.recv_mrk_blk;
int ix;
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
if (!is_small(id) && !is_big(id) && !is_internal_ref(id))
return;
@@ -1832,7 +2015,8 @@ erts_msgq_recv_marker_clear(Process *c_p, Eterm id)
ERTS_GLB_INLINE Eterm
erts_msgq_recv_marker_insert(Process *c_p)
{
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
+ erts_proc_sig_queue_lock(c_p);
erts_proc_sig_fetch(c_p);
erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
@@ -1845,6 +2029,7 @@ ERTS_GLB_INLINE void erts_msgq_recv_marker_bind(Process *c_p,
Eterm insert_id,
Eterm bind_id)
{
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
#ifdef ERTS_SUPPORT_OLD_RECV_MARK_INSTRS
ASSERT(bind_id != erts_old_recv_marker_id);
#endif
@@ -1874,6 +2059,7 @@ ERTS_GLB_INLINE void erts_msgq_recv_marker_bind(Process *c_p,
ERTS_GLB_INLINE void
erts_msgq_recv_marker_insert_bind(Process *c_p, Eterm id)
{
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
if (is_internal_ref(id)) {
#ifdef ERTS_SUPPORT_OLD_RECV_MARK_INSTRS
ErtsRecvMarkerBlock *blkp = c_p->sig_qs.recv_mrk_blk;
@@ -1881,7 +2067,7 @@ erts_msgq_recv_marker_insert_bind(Process *c_p, Eterm id)
ERTS_PROC_SIG_RECV_MARK_CLEAR_OLD_MARK__(blkp);
#endif
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_lock(c_p);
erts_proc_sig_fetch(c_p);
erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
@@ -1893,6 +2079,7 @@ erts_msgq_recv_marker_insert_bind(Process *c_p, Eterm id)
ERTS_GLB_INLINE void
erts_msgq_recv_marker_set_save(Process *c_p, Eterm id)
{
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
if (is_internal_ref(id)) {
ErtsRecvMarkerBlock *blkp = c_p->sig_qs.recv_mrk_blk;
@@ -1913,6 +2100,7 @@ erts_msgq_recv_marker_set_save(Process *c_p, Eterm id)
ERTS_GLB_INLINE ErtsMessage *
erts_msgq_peek_msg(Process *c_p)
{
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
ASSERT(!(*c_p->sig_qs.save) || ERTS_SIG_IS_MSG(*c_p->sig_qs.save));
return *c_p->sig_qs.save;
}
@@ -1921,6 +2109,7 @@ ERTS_GLB_INLINE void
erts_msgq_unlink_msg(Process *c_p, ErtsMessage *msgp)
{
ErtsMessage *sigp = msgp->next;
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE__(c_p, 0, "before");
*c_p->sig_qs.save = sigp;
c_p->sig_qs.len--;
@@ -1939,6 +2128,7 @@ ERTS_GLB_INLINE void
erts_msgq_set_save_first(Process *c_p)
{
ErtsRecvMarkerBlock *blkp = c_p->sig_qs.recv_mrk_blk;
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
if (blkp) {
ERTS_PROC_SIG_RECV_MARK_CLEAR_PENDING_SET_SAVE__(blkp);
#ifdef ERTS_SUPPORT_OLD_RECV_MARK_INSTRS
@@ -1952,14 +2142,16 @@ erts_msgq_set_save_first(Process *c_p)
* anymore...
*/
if (c_p->sig_qs.first && ERTS_SIG_IS_RECV_MARKER(c_p->sig_qs.first))
- erts_msgq_remove_leading_recv_markers(c_p);
- c_p->sig_qs.save = &c_p->sig_qs.first;
+ erts_msgq_remove_leading_recv_markers_set_save_first(c_p);
+ else
+ c_p->sig_qs.save = &c_p->sig_qs.first;
}
ERTS_GLB_INLINE void
erts_msgq_unlink_msg_set_save_first(Process *c_p, ErtsMessage *msgp)
{
ErtsMessage *sigp = msgp->next;
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE__(c_p, 0, "before");
*c_p->sig_qs.save = sigp;
c_p->sig_qs.len--;
@@ -1976,6 +2168,7 @@ erts_msgq_set_save_next(Process *c_p)
{
ErtsMessage *sigp = (*c_p->sig_qs.save)->next;
ErtsMessage **sigpp = &(*c_p->sig_qs.save)->next;
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
ERTS_HDBG_CHECK_SIGNAL_PRIV_QUEUE(c_p, 0);
if (sigp && ERTS_SIG_IS_RECV_MARKER(sigp))
sigpp = erts_msgq_pass_recv_markers(c_p, sigpp);
@@ -1987,8 +2180,9 @@ ERTS_GLB_INLINE void
erts_msgq_set_save_end(Process *c_p)
{
/* Set save pointer to end of message queue... */
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_lock(c_p);
erts_proc_sig_fetch(c_p);
erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
@@ -2006,6 +2200,23 @@ erts_msgq_set_save_end(Process *c_p)
#undef ERTS_PROC_SIG_RECV_MARK_CLEAR_PENDING_SET_SAVE__
#undef ERTS_PROC_SIG_RECV_MARK_CLEAR_OLD_MARK__
+ERTS_GLB_INLINE erts_aint32_t
+erts_proc_sig_check_wait_dirty_handle_signals(Process *c_p,
+ erts_aint32_t state_in)
+{
+ erts_aint32_t state = state_in;
+ ASSERT(erts_get_scheduler_data()->type == ERTS_SCHED_NORMAL);
+ ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
+
+ if (c_p->sig_qs.flags & FS_HANDLING_SIGS) {
+ erts_proc_sig_do_wait_dirty_handle_signals__(c_p);
+ state = erts_atomic32_read_mb(&c_p->state);
+ }
+ ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p));
+ ASSERT(!(c_p->sig_qs.flags & FS_HANDLING_SIGS));
+ return state;
+}
+
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
#endif /* ERTS_PROC_SIG_QUEUE_H__ */
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 776094dfbf..c2ca5a03f3 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2022. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1715,8 +1715,8 @@ haw_thr_prgr_current_check_progress(ErtsAuxWorkData *awdp)
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
+ * We have used a previously read current value that isn't the
+ * latest; need to poke ourselves in order to guarantee no loss
* of wakeups.
*/
erts_sched_poke(awdp->ssi);
@@ -2258,17 +2258,24 @@ handle_canceled_timers_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, i
/*
* Handle scheduled thread progress later operations.
*/
-#define ERTS_MAX_THR_PRGR_LATER_OPS 50
+#define ERTS_MIN_THR_PRGR_LATER_OPS 50
static ERTS_INLINE erts_aint32_t
handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting)
{
- int lops;
+ int lops, limit;
ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
ASSERT(!awdp->esdp || !ERTS_SCHEDULER_IS_DIRTY(awdp->esdp));
- for (lops = 0; lops < ERTS_MAX_THR_PRGR_LATER_OPS; lops++) {
+ /*
+ * Boost loop limit proportional to number of queued later ops
+ * in order to always keep up.
+ */
+ limit = (awdp->later_op.list_len / 8
+ + ERTS_MIN_THR_PRGR_LATER_OPS);
+
+ for (lops = 0; lops < limit; lops++) {
ErtsThrPrgrLaterOp *lop = awdp->later_op.first;
if (!erts_thr_progress_has_reached_this(current, lop->later))
@@ -2277,6 +2284,7 @@ handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int wait
if (!awdp->later_op.first) {
awdp->later_op.last = NULL;
}
+ awdp->later_op.list_len--;
lop->func(lop->data);
if (!awdp->later_op.first) {
awdp->later_op.size = thr_prgr_later_cleanup_op_threshold;
@@ -2297,17 +2305,19 @@ enqueue_later_op(ErtsSchedulerData *esdp,
ErtsThrPrgrLaterOp *lop)
{
ErtsThrPrgrVal later = erts_thr_progress_later(esdp);
+ ErtsAuxWorkData* awdp = &esdp->aux_work_data;
ASSERT(esdp && !ERTS_SCHEDULER_IS_DIRTY(esdp));
lop->func = later_func;
lop->data = later_data;
lop->later = later;
lop->next = NULL;
- if (!esdp->aux_work_data.later_op.last)
- esdp->aux_work_data.later_op.first = lop;
+ if (!awdp->later_op.last)
+ awdp->later_op.first = lop;
else
- esdp->aux_work_data.later_op.last->next = lop;
- esdp->aux_work_data.later_op.last = lop;
+ awdp->later_op.last->next = lop;
+ awdp->later_op.last = lop;
+ awdp->later_op.list_len++;
set_aux_work_flags_wakeup_nob(esdp->ssi,
ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP);
return later;
@@ -2657,7 +2667,7 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
/*
* Handlers are *only* allowed to modify flags in return value
- * and ssi flags that are explicity handled by the handler.
+ * and ssi flags that are explicitly handled by the handler.
* Handlers are, e.g., not allowed to read the ssi flag field and
* then unconditionally return that value.
*
@@ -2667,7 +2677,7 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
/*
* Keep ERTS_SSI_AUX_WORK flags in expected frequency order relative
- * eachother. Most frequent first.
+ * each other. Most frequent first.
*/
HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_DELAYED_AW_WAKEUP,
handle_delayed_aux_work_wakeup);
@@ -3194,11 +3204,11 @@ aux_thread(void *vix)
#if ERTS_POLL_USE_FALLBACK
if (ix == 0) {
-#if ERTS_POLL_USE_SCHEDULER_POLLING
- ssi->psi = erts_create_pollset_thread(-2, tpd);
-#else
- ssi->psi = erts_create_pollset_thread(-1, tpd);
-#endif
+ if (erts_sched_poll_enabled()) {
+ ssi->psi = erts_create_pollset_thread(-2, tpd);
+ } else {
+ ssi->psi = erts_create_pollset_thread(-1, tpd);
+ }
}
#endif
@@ -3365,11 +3375,13 @@ try_set_sys_scheduling(void)
static ERTS_INLINE int
prepare_for_sys_schedule(void)
{
- while (!erts_port_task_have_outstanding_io_tasks()
- && try_set_sys_scheduling()) {
- if (!erts_port_task_have_outstanding_io_tasks())
- return 1;
- clear_sys_scheduling();
+ if (erts_sched_poll_enabled()) {
+ while (!erts_port_task_have_outstanding_io_tasks()
+ && try_set_sys_scheduling()) {
+ if (!erts_port_task_have_outstanding_io_tasks())
+ return 1;
+ clear_sys_scheduling();
+ }
}
return 0;
}
@@ -3698,7 +3710,7 @@ wake_scheduler(ErtsRunQueue *rq)
* The unlocked run queue is not strictly necessary
* from a thread safety or deadlock prevention
* perspective. It will, however, cost us performance
- * if it is locked during wakup of another scheduler,
+ * if it is locked during wakeup of another scheduler,
* so all code *should* handle this without having
* the lock on the run queue.
*/
@@ -5834,6 +5846,8 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp,
awdp->later_op.size = 0;
awdp->later_op.first = NULL;
awdp->later_op.last = NULL;
+ awdp->later_op.list_len = 0;
+
awdp->async_ready.need_thr_prgr = 0;
awdp->async_ready.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
awdp->async_ready.queue = NULL;
@@ -5963,6 +5977,7 @@ init_scheduler_data(ErtsSchedulerData* esdp, int num,
}
esdp->reductions = 0;
+ esdp->rand_state = (Uint64)(UWord)esdp + ((Uint64)(UWord)esdp << 32);
init_sched_wall_time(esdp, time_stamp);
erts_port_task_handle_init(&esdp->nosuspend_port_task_handle);
@@ -6020,7 +6035,7 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online, int no_poll_th
rq->ix = ix;
- /* make sure that the "extra" id correponds to the schedulers
+ /* make sure that the "extra" id corresponds to the schedulers
* id if the esdp->no <-> ix+1 mapping change.
*/
@@ -6287,9 +6302,6 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online, int no_poll_th
erts_atomic32_set_nob(&schdlr_sspnd.changing,
set_schdlr_sspnd_change_flags);
- init_misc_aux_work();
-
-
/* init port tasks */
erts_port_task_init();
@@ -6628,10 +6640,12 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p,
*/
/*
- * No normal execution until dirty CLA or hibernat has
+ * No normal execution until dirty CLA or hibernate has
* been handled...
*/
- ASSERT(!(p->flags & (F_DIRTY_CLA | F_DIRTY_GC_HIBERNATE)));
+ ASSERT(!(p->flags & (F_DIRTY_CHECK_CLA
+ | F_DIRTY_CLA
+ | F_DIRTY_GC_HIBERNATE)));
a = erts_atomic32_read_band_nob(&p->state,
~ERTS_PSFLG_DIRTY_ACTIVE_SYS);
@@ -6853,7 +6867,7 @@ change_proc_schedule_state(Process *p,
| ERTS_PSFLG_RUNNING_SYS
| ERTS_PSFLG_DIRTY_RUNNING
| ERTS_PSFLG_DIRTY_RUNNING_SYS))) {
- /* We activated a prevously inactive process */
+ /* We activated a previously inactive process */
profile_runnable_proc(p, am_active);
}
@@ -6965,7 +6979,7 @@ active_sys_enqueue(Process *p, ErtsProcSysTask *sys_task,
| ERTS_PSFLG_DIRTY_RUNNING
| ERTS_PSFLG_DIRTY_RUNNING_SYS))
&& (!(a & ERTS_PSFLG_ACTIVE) || (a & ERTS_PSFLG_SUSPENDED))) {
- /* We activated a prevously inactive process */
+ /* We activated a previously inactive process */
profile_runnable_proc(p, am_active);
}
}
@@ -7501,7 +7515,7 @@ msb_scheduler_type_switch(ErtsSchedType sched_type,
/*
* Make sure to alternate between dirty types
- * inbetween normal execution if highest
+ * between normal execution if highest
* priorities are equal.
*/
@@ -8620,9 +8634,9 @@ sched_thread_func(void *vesdp)
erts_thr_progress_register_managed_thread(esdp, &callbacks, 0, 0);
-#if ERTS_POLL_USE_SCHEDULER_POLLING
- esdp->ssi->psi = erts_create_pollset_thread(-1, NULL);
-#endif
+ if (erts_sched_poll_enabled()) {
+ esdp->ssi->psi = erts_create_pollset_thread(-1, NULL);
+ }
#ifdef ERTS_ENABLE_LOCK_CHECK
{
@@ -8989,8 +9003,10 @@ erts_internal_suspend_process_2(BIF_ALIST_2)
erts_proc_unlock(rp, ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_STATUS);
}
if (send_sig) {
- if (erts_proc_sig_send_monitor(&mdp->u.target, BIF_ARG_1))
+ if (erts_proc_sig_send_monitor(&BIF_P->common, BIF_P->common.id,
+ &mdp->u.target, BIF_ARG_1)) {
sync = !async;
+ }
else {
noproc:
erts_monitor_tree_delete(&ERTS_P_MONITORS(BIF_P), &mdp->origin);
@@ -9047,7 +9063,7 @@ resume_process_1(BIF_ALIST_1)
if ((mstate & ERTS_MSUSPEND_STATE_COUNTER_MASK) == 0) {
erts_monitor_tree_delete(&ERTS_P_MONITORS(BIF_P), mon);
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(&BIF_P->common, BIF_P->common.id, 0, mon);
}
BIF_RET(am_true);
@@ -9448,8 +9464,11 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
int actual_reds;
int reds;
Uint32 flags;
- erts_aint32_t state = 0; /* Supress warning... */
+ erts_aint32_t state = 0; /* Suppress warning... */
int is_normal_sched;
+#ifdef DEBUG
+ int aborted_execution = 0;
+#endif
ERTS_MSACC_DECLARE_CACHE();
@@ -9497,8 +9516,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp));
if (esdp->pending_signal.sig) {
- ASSERT(esdp->pending_signal.dbg_from == p);
- erts_proc_sig_send_pending(esdp);
+ erts_proc_sig_send_pending(p, esdp);
}
}
else {
@@ -9521,7 +9539,9 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
esdp->virtual_reds = 0;
#if ERTS_POLL_USE_SCHEDULER_POLLING
- fcalls = (int) erts_atomic32_add_read_acqb(&function_calls, reds);
+ if (erts_sched_poll_enabled()) {
+ fcalls = (int)erts_atomic32_add_read_acqb(&function_calls, reds);
+ }
#endif
ASSERT(esdp && esdp == erts_get_scheduler_data());
@@ -9573,7 +9593,8 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
if (state & ERTS_PSFLG_FREE) {
if (!is_normal_sched) {
- ASSERT(p->flags & F_DELAYED_DEL_PROC);
+ ASSERT((p->flags & F_DELAYED_DEL_PROC)
+ || aborted_execution);
}
else {
ASSERT(esdp->free_process == p);
@@ -9601,6 +9622,10 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
ErtsMigrationPaths *mps;
ErtsMigrationPath *mp;
+#ifdef DEBUG
+ aborted_execution = 0;
+#endif
+
if (is_normal_sched) {
if (esdp->check_time_reds >= ERTS_CHECK_TIME_REDS)
@@ -10000,6 +10025,9 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
erts_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
if (IS_TRACED(p))
trace_schedule_in(p, state);
+#ifdef DEBUG
+ aborted_execution = !0;
+#endif
goto sched_out_proc;
}
}
@@ -10055,29 +10083,44 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
}
else {
/* On normal scheduler */
+
+ /*
+ * Check if a dirty signal handler is handling signals for
+ * us and if so, wait for it to complete before continuing...
+ */
+ state = erts_proc_sig_check_wait_dirty_handle_signals(p, state);
+
if (state & ERTS_PSFLG_RUNNING_SYS) {
if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q)) {
- int local_only = (!!(p->sig_qs.flags & FS_LOCAL_SIGS_ONLY)
- & !(state & (ERTS_PSFLG_SUSPENDED|ERTS_PSFLGS_DIRTY_WORK)));
- if (!local_only | !!(state & ERTS_PSFLG_SIG_Q)) {
- int sig_reds;
+ int sig_reds;
+ /*
+ * If we have dirty work scheduled we allow
+ * usage of all reductions since we need to
+ * handle all signals before doing dirty
+ * work...
+ *
+ * If a BIF is flushing signals, we also allow
+ * usage of all reductions since the BIF cannot
+ * continue exectution until the flush
+ * completes...
+ */
+ sig_reds = reds;
+ if (((state & (ERTS_PSFLGS_DIRTY_WORK
+ | ERTS_PSFLG_ACTIVE)) == ERTS_PSFLG_ACTIVE)
+ && !(p->sig_qs.flags & FS_FLUSHING_SIGS)) {
/*
- * If we have dirty work scheduled we allow
- * usage of all reductions since we need to
- * handle all signals before doing dirty
- * work...
+ * We are active, i.e., have erlang work to do,
+ * and have no dirty work and are not flushing
+ * limit amount of signal handling work...
*/
- if (state & ERTS_PSFLGS_DIRTY_WORK)
- sig_reds = reds;
- else
- sig_reds = ERTS_SIG_HANDLE_REDS_MAX_PREFERED;
- (void) erts_proc_sig_handle_incoming(p,
- &state,
- &sig_reds,
- sig_reds,
- local_only);
- reds -= sig_reds;
+ sig_reds = ERTS_SIG_HANDLE_REDS_MAX_PREFERED;
}
+ (void) erts_proc_sig_handle_incoming(p,
+ &state,
+ &sig_reds,
+ sig_reds,
+ 0);
+ reds -= sig_reds;
}
if ((state & (ERTS_PSFLG_SYS_TASKS
| ERTS_PSFLG_EXITING)) == ERTS_PSFLG_SYS_TASKS) {
@@ -10087,8 +10130,14 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
* hand written beam assembly in
* prim_eval:'receive'. If GC is delayed we are
* not allowed to execute system tasks.
+ *
+ * We also don't allow execution of system tasks
+ * if a BIF is flushing signals, since there are
+ * system tasks that might need to fetch from the
+ * outer signal queue...
*/
- if (!(p->flags & F_DELAY_GC)) {
+ if (!(p->flags & F_DELAY_GC)
+ && !(p->sig_qs.flags & FS_FLUSHING_SIGS)) {
int cost = execute_sys_tasks(p, &state, reds);
calls += cost;
reds -= cost;
@@ -10140,6 +10189,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
if (!(state & ERTS_PSFLG_EXITING)
&& !(p->flags & (F_DELAY_GC|F_DISABLE_GC))) {
int cost = scheduler_gc_proc(p, reds);
+ state = erts_atomic32_read_nob(&p->state);
calls += cost;
reds -= cost;
if (reds <= 0)
@@ -10501,7 +10551,9 @@ done:
}
-static void exit_permanent_prio_elevation(Process *c_p, erts_aint32_t state);
+static void exit_permanent_prio_elevation(Process *c_p,
+ erts_aint32_t state,
+ int prio);
static void save_gc_task(Process *c_p, ErtsProcSysTask *st, int prio);
static void save_dirty_task(Process *c_p, ErtsProcSysTask *st);
@@ -10583,25 +10635,49 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
int fcalls;
int cla_reds = 0;
- if (!ERTS_PROC_GET_SAVED_CALLS_BUF(c_p))
- fcalls = reds;
- else
- fcalls = reds - CONTEXT_REDS;
- st_res = erts_copy_literals_gc(c_p, &cla_reds, fcalls);
- reds -= cla_reds;
- if (is_non_value(st_res)) {
- if (c_p->flags & F_DIRTY_CLA) {
- save_dirty_task(c_p, st);
- st = NULL;
- break;
- }
- /* Needed gc, but gc was disabled */
- save_gc_task(c_p, st, st_prio);
- st = NULL;
- break;
- }
- /* We did a major gc */
- minor_gc = major_gc = 1;
+ if (st->arg[0] == am_true) {
+ /*
+ * Check if copy literal area GC is needed and only
+ * do GC if needed. This check is never requested unless
+ * we know that this is to much work to do on a normal
+ * scheduler, so we do not even try to check it here
+ * but instead unconditionally schedule this as dirty
+ * work...
+ */
+ if (c_p->flags & F_DISABLE_GC) {
+ /* We might need to GC, but GC was disabled */
+ save_gc_task(c_p, st, st_prio);
+ st = NULL;
+ }
+ else {
+ c_p->flags |= F_DIRTY_CHECK_CLA;
+ save_dirty_task(c_p, st);
+ st = NULL;
+ erts_schedule_dirty_sys_execution(c_p);
+ }
+ }
+ else {
+ /* Copy literal area GC needed... */
+ if (!ERTS_PROC_GET_SAVED_CALLS_BUF(c_p))
+ fcalls = reds;
+ else
+ fcalls = reds - CONTEXT_REDS;
+ st_res = erts_copy_literals_gc(c_p, &cla_reds, fcalls);
+ reds -= cla_reds;
+ if (is_non_value(st_res)) {
+ if (c_p->flags & F_DIRTY_CLA) {
+ save_dirty_task(c_p, st);
+ st = NULL;
+ break;
+ }
+ /* Needed gc, but gc was disabled */
+ save_gc_task(c_p, st, st_prio);
+ st = NULL;
+ break;
+ }
+ /* We did a major gc */
+ minor_gc = major_gc = 1;
+ }
break;
}
case ERTS_PSTT_FTMQ:
@@ -10614,30 +10690,32 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
break;
case ERTS_PSTT_PRIO_SIG: {
erts_aint32_t fail_state, state;
- int sig_res, sig_reds = reds;
+ int sig_res, sig_reds;
st_res = am_false;
+ ASSERT(!(c_p->sig_qs.flags & FS_FLUSHING_SIGS));
+
if (st->arg[0] == am_false) {
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_lock(c_p);
erts_proc_sig_fetch(c_p);
erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ);
+ st->arg[0] = am_true;
}
+ state = erts_atomic32_read_nob(&c_p->state);
sig_reds = reds;
sig_res = erts_proc_sig_handle_incoming(c_p, &state, &sig_reds,
reds, !0);
reds -= sig_reds;
if (state & ERTS_PSFLG_EXITING) {
- exit_permanent_prio_elevation(c_p, state);
+ exit_permanent_prio_elevation(c_p, state, st_prio);
break;
}
if (sig_res)
break;
- st->arg[0] = am_true;
-
fail_state = ERTS_PSFLG_EXITING;
if (schedule_process_sys_task(c_p, st_prio, st, &fail_state)) {
@@ -10645,9 +10723,10 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
st = NULL;
}
else {
- state = erts_atomic32_read_nob(&c_p->state);
- exit_permanent_prio_elevation(c_p, state);
+ state = erts_atomic32_read_nob(&c_p->state);
+ exit_permanent_prio_elevation(c_p, state, st_prio);
}
+
break;
}
case ERTS_PSTT_TEST:
@@ -10659,7 +10738,7 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
}
if (st)
- reds += notify_sys_task_executed(c_p, st, st_res, 1);
+ reds -= notify_sys_task_executed(c_p, st, st_res, 1);
state = erts_atomic32_read_acqb(&c_p->state);
} while (qmask && reds > 0);
@@ -10676,8 +10755,7 @@ static int
cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
{
erts_aint32_t state = in_state;
- int max_reds = in_reds;
- int reds = 0;
+ int reds = in_reds;
int qmask = 1; /* Set to 1 to force looping as long as there
* are dirty tasks.
*/
@@ -10690,6 +10768,7 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
int st_prio;
if (c_p->dirty_sys_tasks) {
+ st_prio = PRIORITY_MAX; /* Silence warning... */
st = c_p->dirty_sys_tasks;
c_p->dirty_sys_tasks = st->next;
}
@@ -10703,7 +10782,7 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
switch (st->type) {
case ERTS_PSTT_PRIO_SIG:
state = erts_atomic32_read_nob(&c_p->state);
- exit_permanent_prio_elevation(c_p, state);
+ exit_permanent_prio_elevation(c_p, state, st_prio);
/* fall through... */
case ERTS_PSTT_GC_MAJOR:
case ERTS_PSTT_GC_MINOR:
@@ -10725,38 +10804,41 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
break;
}
- reds += notify_sys_task_executed(c_p, st, st_res, 1);
+ reds -= notify_sys_task_executed(c_p, st, st_res, 1);
state = erts_atomic32_read_acqb(&c_p->state);
- } while (qmask && reds < max_reds);
+ } while (qmask && reds > 0);
return reds;
}
static void
-exit_permanent_prio_elevation(Process *c_p, erts_aint32_t state)
+exit_permanent_prio_elevation(Process *c_p, erts_aint32_t state, int elev_prio)
{
- erts_aint32_t a;
+ erts_aint32_t a, nprio = (erts_aint32_t) elev_prio;
/*
* we are about to terminate; permanently elevate
* prio in order to ensure high prio signal
* handling...
*/
+ ASSERT(PRIORITY_MAX <= elev_prio && elev_prio <= PRIORITY_LOW);
+
a = state;
while (1) {
- erts_aint32_t aprio, uprio, n, e;
+ erts_aint32_t uprio, n, e;
ASSERT(a & ERTS_PSFLG_EXITING);
- aprio = ERTS_PSFLGS_GET_ACT_PRIO(a);
uprio = ERTS_PSFLGS_GET_USR_PRIO(a);
- if (aprio >= uprio)
- break; /* user prio >= actual prio */
+ if (nprio >= uprio)
+ break; /* user prio is higher than or equal to elevation prio */
/*
* actual prio is higher than user prio; raise
* user prio to actual prio...
*/
n = e = a;
- n &= ~ERTS_PSFLGS_USR_PRIO_MASK;
- n |= aprio << ERTS_PSFLGS_USR_PRIO_OFFSET;
+ n &= ~(ERTS_PSFLGS_USR_PRIO_MASK
+ | ERTS_PSFLGS_ACT_PRIO_MASK);
+ n |= ((nprio << ERTS_PSFLGS_USR_PRIO_OFFSET)
+ | (nprio << ERTS_PSFLGS_ACT_PRIO_OFFSET));
a = erts_atomic32_cmpxchg_mb(&c_p->state, n, e);
if (a == e)
break;
@@ -10800,10 +10882,12 @@ erts_execute_dirty_system_task(Process *c_p)
/*
* If multiple operations, perform them in the following
* order (in order to avoid unnecessary GC):
- * 1. Copy Literal Area (implies major GC).
- * 2. GC Hibernate (implies major GC if not woken).
- * 3. Major GC (implies minor GC).
- * 4. Minor GC.
+ * 1. Check for Copy Literals Area GC need. This may
+ * trigger a Copy Literals Area GC.
+ * 2. Copy Literal Area GC (implies major GC).
+ * 3. GC Hibernate (implies major GC if not woken).
+ * 4. Major GC (implies minor GC).
+ * 5. Minor GC.
*
* System task requests are handled after the actual
* operations have been performed...
@@ -10811,6 +10895,37 @@ erts_execute_dirty_system_task(Process *c_p)
ASSERT(!(c_p->flags & (F_DELAY_GC|F_DISABLE_GC)));
+ if (c_p->flags & F_DIRTY_CHECK_CLA) {
+ ErtsLiteralArea *la = ERTS_COPY_LITERAL_AREA();
+
+ ASSERT(!(c_p->flags & F_DIRTY_CLA));
+ c_p->flags &= ~F_DIRTY_CHECK_CLA;
+ if (!la)
+ cla_res = am_ok;
+ else {
+ int check_cla_reds = 0;
+ char *literals = (char *) &la->start[0];
+ Uint lit_bsize = (char *) la->end - literals;
+ if (erts_check_copy_literals_gc_need(c_p,
+ &check_cla_reds,
+ literals,
+ lit_bsize)) {
+ /*
+ * We had references to this literal area on the heap;
+ * need a copy literals GC...
+ */
+ c_p->flags |= F_DIRTY_CLA;
+ }
+ else {
+ /*
+ * We have no references to this literal area on the
+ * heap; no copy literals GC needed...
+ */
+ cla_res = am_ok;
+ }
+ }
+ }
+
if (c_p->flags & F_DIRTY_CLA) {
int cla_reds = 0;
cla_res = erts_copy_literals_gc(c_p, &cla_reds, c_p->fcalls);
@@ -10839,7 +10954,8 @@ erts_execute_dirty_system_task(Process *c_p)
c_p->arity, c_p->fcalls);
}
- ASSERT(!(c_p->flags & (F_DIRTY_CLA
+ ASSERT(!(c_p->flags & (F_DIRTY_CHECK_CLA
+ | F_DIRTY_CLA
| F_DIRTY_GC_HIBERNATE
| F_DIRTY_MAJOR_GC
| F_DIRTY_MINOR_GC)));
@@ -11115,7 +11231,7 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
return ret; /* signal sent... */
}
/*
- * schedule system task directly since we wont violate
+ * schedule system task directly since we won't violate
* signal order...
*/
}
@@ -11223,7 +11339,7 @@ erts_internal_request_system_task_4(BIF_ALIST_4)
}
void
-erts_schedule_cla_gc(Process *c_p, Eterm to, Eterm req_id)
+erts_schedule_cla_gc(Process *c_p, Eterm to, Eterm req_id, int check)
{
Process *rp;
ErtsProcSysTask *st;
@@ -11249,7 +11365,8 @@ erts_schedule_cla_gc(Process *c_p, Eterm to, Eterm req_id)
req_id_sz,
&hp,
&st->off_heap);
- for (i = 0; i < ERTS_MAX_PROC_SYS_TASK_ARGS; i++)
+ st->arg[0] = check ? am_true : am_false;
+ for (i = 1; i < ERTS_MAX_PROC_SYS_TASK_ARGS; i++)
st->arg[i] = THE_NON_VALUE;
rp = erts_proc_lookup_raw(to);
@@ -11800,6 +11917,8 @@ static void early_init_process_struct(void *varg, Eterm data)
erts_atomic32_init_nob(&proc->dirty_state, 0);
proc->dirty_sys_tasks = NULL;
erts_init_runq_proc(proc, arg->run_queue, arg->bound);
+ erts_atomic_init_nob(&proc->sig_inq_buffers, (erts_aint_t)NULL);
+
erts_atomic32_init_relb(&proc->state, arg->state);
erts_proc_lock_init(proc); /* All locks locked */
@@ -11919,6 +12038,22 @@ erts_parse_spawn_opts(ErlSpawnOpts *sop, Eterm opts_list, Eterm *tag,
sop->priority = PRIORITY_LOW;
else
result = -1;
+ } else if (arg == am_async_dist) {
+ if (val == am_true) {
+ if (sop->flags & SPO_ASYNC_DIST)
+ sop->multi_set = !0;
+ else
+ sop->flags |= SPO_ASYNC_DIST;
+ }
+ else if (val == am_false) {
+ if (!(sop->flags & SPO_ASYNC_DIST))
+ sop->multi_set = !0;
+ else
+ sop->flags &= ~SPO_ASYNC_DIST;
+ }
+ else {
+ result = -1;
+ }
} else if (arg == am_message_queue_data) {
if (sop->flags & (SPO_OFF_HEAP_MSGQ|SPO_ON_HEAP_MSGQ))
sop->multi_set = !0;
@@ -12156,6 +12291,9 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
/* Reserve place for continuation pointer, redzone, etc */
heap_need = arg_size + S_RESERVED;
+ if (so->flags & SPO_ASYNC_DIST)
+ flags |= F_ASYNC_DIST;
+
p->flags = flags;
p->sig_qs.flags = qs_flags;
@@ -12183,6 +12321,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
*/
p->off_heap.first = NULL;
p->off_heap.overhead = 0;
+ p->wrt_bins = NULL;
if (is_not_immed(group_leader))
heap_need += NC_HEAP_SIZE(group_leader);
@@ -12198,7 +12337,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->high_water = p->heap;
p->gen_gcs = 0;
p->hend = p->heap + sz;
- p->stop = p->hend - 1; /* Reserve place for continuation pointer */
+ p->stop = p->hend - CP_SIZE; /* Reserve place for continuation pointer. */
p->htop = p->heap;
p->heap_sz = sz;
p->abandoned_heap = NULL;
@@ -12215,8 +12354,19 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->current = &p->u.initial;
- p->i = beam_apply;
- p->stop[0] = make_cp(beam_normal_exit);
+ p->i = beam_run_process;
+
+ switch (erts_frame_layout) {
+ case ERTS_FRAME_LAYOUT_RA:
+ p->stop[0] = make_cp(beam_normal_exit);
+ break;
+ case ERTS_FRAME_LAYOUT_FP_RA:
+ p->stop[0] = make_cp(NULL);
+ p->stop[1] = make_cp(beam_normal_exit);
+
+ FRAME_POINTER(p) = &p->stop[0];
+ break;
+ }
p->arg_reg = p->def_arg_reg;
p->max_arg_reg = sizeof(p->def_arg_reg)/sizeof(p->def_arg_reg[0]);
@@ -12266,11 +12416,13 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->sig_qs.len = 0;
p->sig_qs.nmsigs.next = NULL;
p->sig_qs.nmsigs.last = NULL;
+ p->sig_inq_contention_counter = 0;
p->sig_inq.first = NULL;
p->sig_inq.last = &p->sig_inq.first;
p->sig_inq.len = 0;
p->sig_inq.nmsigs.next = NULL;
p->sig_inq.nmsigs.last = NULL;
+ ASSERT(erts_atomic_read_nob(&p->sig_inq_buffers) == (erts_aint_t)NULL);
#ifdef ERTS_PROC_SIG_HARD_DEBUG
p->sig_inq.may_contain_heap_terms = 0;
#endif
@@ -12284,9 +12436,20 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
DT_UTAG(p) = NIL;
DT_UTAG_FLAGS(p) = 0;
#endif
- p->parent = (!parent || parent->common.id == ERTS_INVALID_PID
- ? NIL
- : parent->common.id);
+
+ if (parent_id == ERTS_INVALID_PID) {
+ p->parent = am_undefined;
+ }
+ else if (is_internal_pid(parent_id)) {
+ p->parent = parent_id;
+ }
+ else {
+ Eterm sz, *hp;
+ ASSERT(is_external_pid(parent_id));
+ sz = size_object(parent_id);
+ hp = HAlloc(p, sz);
+ p->parent = copy_struct(parent_id, sz, &hp, &MSO(p));
+ }
INIT_HOLE_CHECK(p);
#ifdef DEBUG
@@ -12578,8 +12741,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->common.id, parent_id);
erts_link_tree_insert(&ERTS_P_LINKS(p), &ldp->proc);
if (!erts_link_dist_insert(&ldp->dist, so->mld)) {
- erts_proc_sig_send_link_exit(NULL, THE_NON_VALUE, &ldp->dist,
- am_noconnection, NIL);
+ erts_proc_sig_send_link_exit_noconnection(&ldp->dist);
}
}
@@ -12747,6 +12909,7 @@ void erts_init_empty_process(Process *p)
p->next = NULL;
p->off_heap.first = NULL;
p->off_heap.overhead = 0;
+ p->wrt_bins = NULL;
p->common.u.alive.reg = NULL;
p->heap_sz = 0;
p->high_water = NULL;
@@ -12770,11 +12933,13 @@ void erts_init_empty_process(Process *p)
p->sig_qs.len = 0;
p->sig_qs.nmsigs.next = NULL;
p->sig_qs.nmsigs.last = NULL;
+ p->sig_inq_contention_counter = 0;
p->sig_inq.first = NULL;
p->sig_inq.last = &p->sig_inq.first;
p->sig_inq.len = 0;
p->sig_inq.nmsigs.next = NULL;
p->sig_inq.nmsigs.last = NULL;
+ erts_atomic_init_nob(&p->sig_inq_buffers, (erts_aint_t)NULL);
#ifdef ERTS_PROC_SIG_HARD_DEBUG
p->sig_inq.may_contain_heap_terms = 0;
#endif
@@ -12803,7 +12968,7 @@ void erts_init_empty_process(Process *p)
p->def_arg_reg[4] = 0;
p->def_arg_reg[5] = 0;
- p->parent = NIL;
+ p->parent = am_undefined;
p->static_flags = 0;
p->common.u.alive.started_interval = 0;
@@ -12858,7 +13023,7 @@ erts_debug_verify_clean_empty_process(Process* p)
ASSERT(p->i == NULL);
ASSERT(p->current == NULL);
- ASSERT(p->parent == NIL);
+ ASSERT(p->parent == am_undefined);
ASSERT(p->sig_inq.first == NULL);
ASSERT(p->sig_inq.len == 0);
@@ -12867,6 +13032,7 @@ erts_debug_verify_clean_empty_process(Process* p)
ASSERT(p->off_heap.first == NULL);
ASSERT(p->off_heap.overhead == 0);
+ ASSERT(p->wrt_bins == NULL);
ASSERT(p->mbuf == NULL);
}
@@ -12878,9 +13044,11 @@ erts_cleanup_empty_process(Process* p)
{
/* We only check fields that are known to be used... */
- erts_cleanup_offheap(&p->off_heap);
+ erts_cleanup_offheap_list(p->off_heap.first);
p->off_heap.first = NULL;
p->off_heap.overhead = 0;
+ erts_cleanup_offheap_list(p->wrt_bins);
+ p->wrt_bins = NULL;
if (p->mbuf != NULL) {
free_message_buffer(p->mbuf);
@@ -12934,6 +13102,7 @@ delete_process(Process* p)
/* Clean binaries and funs */
erts_cleanup_offheap(&p->off_heap);
+ erts_cleanup_offheap_list(p->wrt_bins);
/*
* The mso list should not be used anymore, but if it is, make sure that
@@ -13014,7 +13183,7 @@ erts_set_self_exiting(Process *c_p, Eterm reason)
erts_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR);
set_self_exiting(c_p, reason, &enqueue, &enq_prio, &state);
- c_p->freason = EXTAG_EXIT;
+ c_p->freason = EXTAG_EXIT | EXF_PANIC;
KILL_CATCHES(c_p);
c_p->i = beam_exit;
@@ -13295,7 +13464,9 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
switch (mon->type) {
case ERTS_MON_TYPE_SUSPEND:
case ERTS_MON_TYPE_PROC:
- erts_proc_sig_send_monitor_down(mon, reason);
+ erts_proc_sig_send_monitor_down(&c_p->common,
+ c_p->common.id,
+ mon, reason);
mon = NULL;
break;
case ERTS_MON_TYPE_PORT: {
@@ -13315,6 +13486,10 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
erts_fire_nif_monitor(mon);
mon = NULL;
break;
+ case ERTS_MON_TYPE_DIST_PORT:
+ /* Target of a dist port monitor is never inserted... */
+ ERTS_INTERNAL_ERROR("Unexpected dist port monitor");
+ break;
case ERTS_MON_TYPE_DIST_PROC: {
ErtsMonLnkDist *dist;
DistEntry *dep;
@@ -13372,7 +13547,7 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
switch (mon->type) {
case ERTS_MON_TYPE_SUSPEND:
case ERTS_MON_TYPE_PROC:
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(&c_p->common, c_p->common.id, 0, mon);
mon = NULL;
break;
case ERTS_MON_TYPE_TIME_OFFSET:
@@ -13390,7 +13565,8 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
break;
case ERTS_MON_TYPE_PORT: {
Port *prt;
- ASSERT(is_internal_port(mon->other.item));
+ ASSERT(is_internal_port(mon->other.item)
+ || mon->other.item == am_undefined);
prt = erts_port_lookup_raw(mon->other.item);
if (prt) {
if (erts_port_demonitor(c_p, prt, mon) != ERTS_PORT_OP_DROPPED)
@@ -13398,6 +13574,9 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
}
break;
}
+ case ERTS_MON_TYPE_DIST_PORT:
+ /* just release it... */
+ break;
case ERTS_MON_TYPE_DIST_PROC: {
ErtsMonLnkDist *dist;
DistEntry *dep;
@@ -13412,7 +13591,14 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
mdp = erts_monitor_to_data(mon);
dist = ((ErtsMonitorDataExtended *) mdp)->dist;
- ASSERT(dist);
+ if (!dist) {
+ ASSERT(is_external_pid(mon->other.item));
+ ASSERT(external_pid_dist_entry(mon->other.item)
+ == erts_this_dist_entry);
+ /* Target part is in our signal queue... */
+ mdp = NULL;
+ break;
+ }
if (mon->flags & ERTS_ML_FLG_NAME) {
watched = ((ErtsMonitorDataExtended *) mdp)->u.name;
ASSERT(is_atom(watched));
@@ -13543,13 +13729,17 @@ erts_proc_exit_handle_link(ErtsLink *lnk, void *vctxt, Sint reds)
switch (lnk->type) {
case ERTS_LNK_TYPE_PROC:
ASSERT(is_internal_pid(lnk->other.item));
- erts_proc_sig_send_link_exit(c_p, c_p->common.id, lnk,
+ if (((ErtsILink *) lnk)->unlinking)
+ break;
+ erts_proc_sig_send_link_exit(&c_p->common, c_p->common.id, lnk,
reason, SEQ_TRACE_TOKEN(c_p));
lnk = NULL;
break;
case ERTS_LNK_TYPE_PORT: {
Port *prt;
ASSERT(is_internal_port(lnk->other.item));
+ if (((ErtsILink *) lnk)->unlinking)
+ break;
prt = erts_port_lookup(lnk->other.item,
ERTS_PORT_SFLGS_INVALID_LOOKUP);
if (prt)
@@ -13569,8 +13759,14 @@ erts_proc_exit_handle_link(ErtsLink *lnk, void *vctxt, Sint reds)
ErtsDSigSendContext ctx;
int code;
+ dlnk = erts_link_to_other(lnk, &elnk);
+ if (elnk->unlinking) {
+ if (!erts_link_dist_delete(dlnk))
+ elnk = NULL;
+ break;
+ }
+
if (is_immed(reason)) {
- dlnk = erts_link_to_other(lnk, &elnk);
dist = elnk->dist;
ASSERT(is_external_pid(lnk->other.item));
@@ -13820,7 +14016,7 @@ restart:
*
* - A non-immediate exit reason may refer to literals.
* - A process executing dirty while terminated, might access
- * any term on the heap, and therfore literals, until it has
+ * any term on the heap, and therefore literals, until it has
* stopped executing dirty.
*/
if (!trap_state->block_rla_ref
@@ -13966,6 +14162,7 @@ restart:
erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_queue_flush_and_deinstall_buffers(p);
erts_proc_sig_fetch(p);
erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
@@ -14017,9 +14214,7 @@ restart:
case ERTS_CONTINUE_EXIT_HANDLE_PROC_SIG: {
Sint r = reds;
- if (!erts_proc_sig_handle_exit(p, &r,
- &trap_state->pectxt.pend_spawn_monitors,
- trap_state->reason)) {
+ if (!erts_proc_sig_handle_exit(p, &r, &trap_state->pectxt)) {
goto yield;
}
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index 4b2e32db46..ac70260d0d 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -283,7 +283,7 @@ typedef enum {
/*
* Keep ERTS_SSI_AUX_WORK flags ordered in expected frequency
- * order relative eachother. Most frequent at lowest at lowest
+ * order relative each other. Most frequent at lowest at lowest
* index.
*
* ERTS_SSI_AUX_WORK_DEBUG_WAIT_COMPLETED_IX *need* to be
@@ -581,6 +581,7 @@ typedef struct ErtsAuxWorkData_ {
UWord size;
ErtsThrPrgrLaterOp *first;
ErtsThrPrgrLaterOp *last;
+ Uint list_len;
} later_op;
struct {
int need_thr_prgr;
@@ -664,11 +665,11 @@ typedef struct ErtsSchedulerRegisters_ {
ErtsCodePtr start_time_i;
UWord start_time;
-#if !defined(NATIVE_ERLANG_STACK) && defined(JIT_HARD_DEBUG)
+#if (!defined(NATIVE_ERLANG_STACK) || defined(__aarch64__)) && defined(JIT_HARD_DEBUG)
/* Holds the initial thread stack pointer. Used to ensure that everything
* that is pushed to the stack is also popped. */
UWord *initial_sp;
-#elif defined(NATIVE_ERLANG_STACK) && defined(DEBUG)
+#elif defined(NATIVE_ERLANG_STACK) && defined(DEBUG) && !defined(__aarch64__)
/* Raw pointers to the start and end of the stack. Used to test bounds
* without clobbering any registers. */
UWord *runtime_stack_start;
@@ -723,6 +724,7 @@ struct ErtsSchedulerData_ {
} pending_signal;
Uint64 reductions;
+ Uint64 rand_state;
ErtsSchedWallTime sched_wall_time;
ErtsGCInfo gc_info;
ErtsPortTaskHandle nosuspend_port_task_handle;
@@ -956,6 +958,21 @@ typedef struct ErtsProcSysTaskQs_ ErtsProcSysTaskQs;
(ASSERT((p)->htop <= (p)->stop), \
MAX((p)->htop, (p)->stop - S_REDZONE))
+#ifdef ERLANG_FRAME_POINTERS
+/* The current frame pointer on the Erlang stack. */
+# define FRAME_POINTER(p) (p)->frame_pointer
+#else
+/* We define this to a trapping lvalue when frame pointers are unsupported to
+ * provoke crashes when used without checking `erts_frame_layout`. The checks
+ * will always be optimized out because the variable is hardcoded to
+ * `ERTS_FRAME_LAYOUT_RA`. */
+# define FRAME_POINTER(p) (((Eterm ** volatile)0xbadf00d)[0])
+
+# ifndef erts_frame_layout
+# error "erts_frame_layout has not been hardcoded to ERTS_FRAME_LAYOUT_RA"
+# endif
+#endif
+
# define HEAP_END(p) (p)->hend
# define HEAP_SIZE(p) (p)->heap_sz
# define STACK_START(p) (p)->hend
@@ -995,8 +1012,13 @@ struct process {
* shorter instruction can be used to access them.
*/
- Eterm* htop; /* Heap top */
- Eterm* stop; /* Stack top */
+ Eterm *htop; /* Heap top */
+ Eterm *stop; /* Stack top */
+
+#ifdef ERLANG_FRAME_POINTERS
+ Eterm *frame_pointer; /* Frame pointer */
+#endif
+
Sint fcalls; /* Number of reductions left to execute.
* Only valid for the current process.
*/
@@ -1045,7 +1067,7 @@ struct process {
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 */
+ Eterm dt_utag; /* Place to store the dynamic trace user tag */
Uint dt_utag_flags; /* flag field for the dt_utag */
#endif
union {
@@ -1082,6 +1104,7 @@ struct process {
Uint16 gen_gcs; /* Number of (minor) generational GCs. */
Uint16 max_gen_gcs; /* Max minor gen GCs before fullsweep. */
ErlOffHeap off_heap; /* Off-heap data updated by copy_struct(). */
+ struct erl_off_heap_header* wrt_bins; /* Writable binaries */
ErlHeapFragment* mbuf; /* Pointer to heap fragment list */
ErlHeapFragment* live_hf_end;
ErtsMessage *msg_frag; /* Pointer to message fragment list */
@@ -1097,8 +1120,9 @@ struct process {
erts_atomic32_t state; /* Process state flags (see ERTS_PSFLG_*) */
erts_atomic32_t dirty_state; /* Process dirty state flags (see ERTS_PDSFLG_*) */
-
+ Uint sig_inq_contention_counter;
ErtsSignalInQueue sig_inq;
+ erts_atomic_t sig_inq_buffers;
ErlTraceMessageQueue *trace_msg_q;
erts_proc_lock_t lock;
ErtsSchedulerData *scheduler_data;
@@ -1223,8 +1247,9 @@ void erts_check_for_holes(Process* p);
process table. Always ACTIVE while EXITING. Never
SUSPENDED unless also FREE. */
#define ERTS_PSFLG_EXITING ERTS_PSFLG_BIT(5)
-/* UNUSED */
-#define ERTS_PSFLG_UNUSED ERTS_PSFLG_BIT(6)
+/* MAYBE_SELF_SIGS - We might have outstanding signals
+ from ourselves to ourselvs. */
+#define ERTS_PSFLG_MAYBE_SELF_SIGS ERTS_PSFLG_BIT(6)
/* ACTIVE - Process "wants" to execute */
#define ERTS_PSFLG_ACTIVE ERTS_PSFLG_BIT(7)
/* IN_RUNQ - Real process (not proxy) struct used in a
@@ -1232,7 +1257,7 @@ void erts_check_for_holes(Process* p);
#define ERTS_PSFLG_IN_RUNQ ERTS_PSFLG_BIT(8)
/* RUNNING - Executing in process_main() */
#define ERTS_PSFLG_RUNNING ERTS_PSFLG_BIT(9)
-/* SUSPENDED - Process suspended; supress active but
+/* SUSPENDED - Process suspended; suppress active but
not active-sys nor dirty-active-sys */
#define ERTS_PSFLG_SUSPENDED ERTS_PSFLG_BIT(10)
/* GC - gc */
@@ -1385,8 +1410,9 @@ void erts_check_for_holes(Process* p);
#define SPO_IX_ASYNC 11
#define SPO_IX_NO_SMSG 12
#define SPO_IX_NO_EMSG 13
+#define SPO_IX_ASYNC_DIST 14
-#define SPO_NO_INDICES (SPO_IX_ASYNC+1)
+#define SPO_NO_INDICES (SPO_IX_ASYNC_DIST+1)
#define SPO_LINK (1 << SPO_IX_LINK)
#define SPO_MONITOR (1 << SPO_IX_MONITOR)
@@ -1402,8 +1428,9 @@ void erts_check_for_holes(Process* p);
#define SPO_ASYNC (1 << SPO_IX_ASYNC)
#define SPO_NO_SMSG (1 << SPO_IX_NO_SMSG)
#define SPO_NO_EMSG (1 << SPO_IX_NO_EMSG)
+#define SPO_ASYNC_DIST (1 << SPO_IX_ASYNC_DIST)
-#define SPO_MAX_FLAG SPO_NO_EMSG
+#define SPO_MAX_FLAG SPO_ASYNC_DIST
#define SPO_USE_ARGS \
(SPO_MIN_HEAP_SIZE \
@@ -1544,15 +1571,19 @@ extern int erts_system_profile_ts_type;
#define F_TRAP_EXIT (1 << 22) /* Trapping exit */
#define F_FRAGMENTED_SEND (1 << 23) /* Process is doing a distributed fragmented send */
#define F_DBG_FORCED_TRAP (1 << 24) /* DEBUG: Last BIF call was a forced trap */
+#define F_DIRTY_CHECK_CLA (1 << 25) /* Check if copy literal area GC scheduled */
+#define F_ASYNC_DIST (1 << 26) /* Truly asynchronous distribution */
/* Signal queue flags */
#define FS_OFF_HEAP_MSGQ (1 << 0) /* Off heap msg queue */
#define FS_ON_HEAP_MSGQ (1 << 1) /* On heap msg queue */
#define FS_OFF_HEAP_MSGQ_CHNG (1 << 2) /* Off heap msg queue changing */
-#define FS_LOCAL_SIGS_ONLY (1 << 3) /* Handle privq sigs only */
+#define FS_UNUSED (1 << 3) /* Unused */
#define FS_HANDLING_SIGS (1 << 4) /* Process is handling signals */
#define FS_WAIT_HANDLE_SIGS (1 << 5) /* Process is waiting to handle signals */
#define FS_DELAYED_PSIGQS_LEN (1 << 6) /* Delayed update of sig_qs.len */
+#define FS_FLUSHING_SIGS (1 << 7) /* Currently flushing signals */
+#define FS_FLUSHED_SIGS (1 << 8) /* Flushing of signals completed */
/*
* F_DISABLE_GC and F_DELAY_GC are similar. Both will prevent
@@ -1724,9 +1755,9 @@ Uint64 erts_get_proc_interval(void);
Uint64 erts_ensure_later_proc_interval(Uint64);
Uint64 erts_step_proc_interval(void);
-ErtsProcList *erts_proclist_create(Process *);
-ErtsProcList *erts_proclist_copy(ErtsProcList *);
void erts_proclist_destroy(ErtsProcList *);
+ErtsProcList *erts_proclist_create(Process *) ERTS_ATTR_MALLOC_D(erts_proclist_destroy,1);
+ErtsProcList *erts_proclist_copy(ErtsProcList *);
void erts_proclist_dump(fmtfn_t to, void *to_arg, ErtsProcList*);
ERTS_GLB_INLINE int erts_proclist_same(ErtsProcList *, Process *);
@@ -1908,7 +1939,7 @@ void erts_schedule_thr_prgr_later_cleanup_op(void (*)(void *),
ErtsThrPrgrLaterOp *,
UWord);
void erts_schedule_complete_off_heap_message_queue_change(Eterm pid);
-void erts_schedule_cla_gc(Process *c_p, Eterm to, Eterm req_id);
+void erts_schedule_cla_gc(Process *c_p, Eterm to, Eterm req_id, int check);
struct db_fixation;
void erts_schedule_ets_free_fixation(Eterm pid, struct db_fixation*);
void erts_schedule_flush_trace_messages(Process *proc, int force_on_proc);
@@ -2494,7 +2525,7 @@ erts_init_runq_proc(Process *p, ErtsRunQueue *rq, int bnd)
* @param bndp[in,out] Pointer to integer. On input non-zero
* value causes the process to be bound to
* the run-queue. On output, indicating
- * wether process previously was bound or
+ * whether process previously was bound or
* not.
* @return Previous run-queue.
*/
@@ -2573,7 +2604,7 @@ erts_bind_runq_proc(Process *p, int bind)
}
/**
- * Determine wether a process is bound to a run-queue or not.
+ * Determine whether a process is bound to a run-queue or not.
*
* @return Returns a non-zero value if bound,
* and zero of not bound.
@@ -2595,7 +2626,7 @@ erts_proc_runq_is_bound(Process *p)
* value if the process is bound to the
* run-queue.
* @return Pointer to the normal run-queue that
- * the process currently is assigend to.
+ * the process currently is assigned to.
* A process is always assigned to a
* normal run-queue.
*/
@@ -2862,19 +2893,15 @@ Uint32 erts_sched_local_random_hash_64_to_32_shift(Uint64 key)
/*
* This function attempts to return a random number based on the state
- * of the scheduler, the current process and the additional_seed
- * parameter.
+ * of the scheduler and the additional_seed parameter.
*/
ERTS_GLB_INLINE
Uint32 erts_sched_local_random(Uint additional_seed)
{
ErtsSchedulerData *esdp = erts_get_scheduler_data();
- Uint64 seed =
- additional_seed +
- esdp->reductions +
- esdp->current_process->fcalls +
- (((Uint64)esdp->no) << 32);
- return erts_sched_local_random_hash_64_to_32_shift(seed);
+ esdp->rand_state++;
+ return erts_sched_local_random_hash_64_to_32_shift(esdp->rand_state
+ + additional_seed);
}
#ifdef DEBUG
diff --git a/erts/emulator/beam/erl_process_dump.c b/erts/emulator/beam/erl_process_dump.c
index ce46af8fba..9fa5969b5e 100644
--- a/erts/emulator/beam/erl_process_dump.c
+++ b/erts/emulator/beam/erl_process_dump.c
@@ -159,9 +159,12 @@ Uint erts_process_memory(Process *p, int include_sigs_in_transit)
* Size of message queue plus size of all signals
* in transit to the process!
*/
- erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
- erts_proc_sig_fetch(p);
- erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ if (!(p->sig_qs.flags & FS_FLUSHING_SIGS)
+ || ERTS_IS_CRASH_DUMPING) {
+ erts_proc_sig_queue_lock(p);
+ erts_proc_sig_fetch(p);
+ erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ }
ERTS_FOREACH_SIG_PRIVQS(
p, mp,
@@ -228,7 +231,9 @@ dump_process_info(fmtfn_t to, void *to_arg, Process *p)
if (ERTS_TRACE_FLAGS(p) & F_SENSITIVE)
return;
- erts_proc_sig_fetch(p);
+ if (!(p->sig_qs.flags & FS_FLUSHING_SIGS) || ERTS_IS_CRASH_DUMPING) {
+ erts_proc_sig_fetch(p);
+ }
if (p->sig_qs.first || p->sig_qs.cont) {
erts_print(to, to_arg, "=proc_messages:%T\n", p->common.id);
@@ -708,7 +713,7 @@ dump_externally(fmtfn_t to, void *to_arg, Eterm term)
byte* s;
byte* p;
- if (is_fun(term)) {
+ if (is_any_fun(term)) {
/*
* The fun's environment used to cause trouble. There were
* two kind of problems:
@@ -1123,8 +1128,8 @@ erts_dump_extended_process_state(fmtfn_t to, void *to_arg, erts_aint32_t psflg)
erts_print(to, to_arg, "FREE"); break;
case ERTS_PSFLG_EXITING:
erts_print(to, to_arg, "EXITING"); break;
- case ERTS_PSFLG_UNUSED:
- erts_print(to, to_arg, "UNUSED"); break;
+ case ERTS_PSFLG_MAYBE_SELF_SIGS:
+ erts_print(to, to_arg, "MAYBE_SELF_SIGS"); break;
case ERTS_PSFLG_ACTIVE:
erts_print(to, to_arg, "ACTIVE"); break;
case ERTS_PSFLG_IN_RUNQ:
diff --git a/erts/emulator/beam/erl_process_lock.c b/erts/emulator/beam/erl_process_lock.c
index 5cd7c14b91..ae7a25e2fb 100644
--- a/erts/emulator/beam/erl_process_lock.c
+++ b/erts/emulator/beam/erl_process_lock.c
@@ -31,7 +31,7 @@
* queues.
* The bit field contains of a number of lock flags (L1, L2, ...)
* and a number of wait flags (W1, W2, ...). Each lock flag has a
- * corresponding wait flag. The bit field isn't guarranteed to be
+ * corresponding wait flag. The bit field isn't guaranteed to be
* larger than 32-bits which sets a maximum of 16 different locks
* per process. Currently, only 4 locks per process are used. The
* bit field is operated on by use of atomic operations (custom
@@ -221,9 +221,9 @@ dequeue_waiter(erts_proc_lock_t *lck, int ix)
}
/*
- * Tries to aquire as many locks as possible in lock order,
+ * Tries to acquire as many locks as possible in lock order,
* and sets the wait flag on the first lock not possible to
- * aquire.
+ * acquire.
*
* Note: We need the pix lock during this operation. Wait
* flags are only allowed to be manipulated under pix
@@ -274,7 +274,7 @@ try_aquire(erts_proc_lock_t *lck, erts_tse_t *wtr)
/*
* Transfer 'trnsfr_lcks' held by this executing thread to other
* threads waiting for the locks. When a lock has been transferred
- * we also have to try to aquire as many lock as possible for the
+ * we also have to try to acquire as many lock as possible for the
* other thread.
*/
static int
@@ -416,7 +416,7 @@ wait_for_locks(Process *p,
check_queue(&p->lock);
#endif
- /* Try to aquire locks one at a time in lock order and set wait flag */
+ /* Try to acquire locks one at a time in lock order and set wait flag */
try_aquire(&p->lock, wtr);
ASSERT((wtr->uflgs & ~ERTS_PROC_LOCKS_ALL) == 0);
@@ -444,7 +444,7 @@ wait_for_locks(Process *p,
/*
* Wait for needed locks. When we are woken all needed locks have
- * have been acquired by other threads and transfered to us.
+ * have been acquired by other threads and transferred to us.
* However, we need to be prepared for spurious wakeups.
*/
do {
diff --git a/erts/emulator/beam/erl_process_lock.h b/erts/emulator/beam/erl_process_lock.h
index 70ff3baf49..3c8428c5b9 100644
--- a/erts/emulator/beam/erl_process_lock.h
+++ b/erts/emulator/beam/erl_process_lock.h
@@ -229,7 +229,7 @@ typedef struct erts_proc_lock_t_ {
#ifndef ERTS_PROC_LOCK_LOCK_CHECK__
#define ERTS_PROC_LOCK_LOCK_CHECK__
-/* Lock counter implemetation */
+/* Lock counter implementation */
#ifdef ERTS_ENABLE_LOCK_POSITION
#define erts_proc_lock__(P,I,L) erts_proc_lock_x__(P,I,L,__FILE__,__LINE__)
@@ -462,6 +462,9 @@ typedef struct {
#define ERTS_PROC_LOCK_FLGS_READ_(L) \
((ErtsProcLocks) erts_atomic32_read_nob(&(L)->flags))
+#define ERTS_PROC_LOCK_FLGS_READ_ACQB_(L) \
+ ((ErtsProcLocks) erts_atomic32_read_acqb(&(L)->flags))
+
#else /* no opt atomic ops */
ERTS_GLB_INLINE ErtsProcLocks erts_proc_lock_flags_band(erts_proc_lock_t *,
@@ -509,6 +512,7 @@ erts_proc_lock_flags_cmpxchg(erts_proc_lock_t *lck, ErtsProcLocks new,
#define ERTS_PROC_LOCK_FLGS_CMPXCHG_RELB_(L, NEW, EXPECTED) \
erts_proc_lock_flags_cmpxchg((L), (NEW), (EXPECTED))
#define ERTS_PROC_LOCK_FLGS_READ_(L) ((L)->flags)
+#define ERTS_PROC_LOCK_FLGS_READ_ACQB_(L) ((L)->flags)
#endif /* end no opt atomic ops */
#endif /* ERTS_PROC_LOCK_OWN_IMPL */
@@ -918,6 +922,8 @@ ERTS_GLB_INLINE void erts_proc_lock(Process *, ErtsProcLocks);
#endif
ERTS_GLB_INLINE void erts_proc_unlock(Process *, ErtsProcLocks);
ERTS_GLB_INLINE int erts_proc_trylock(Process *, ErtsProcLocks);
+ERTS_GLB_INLINE void
+erts_proc_lock_wait_until_released(Process *p, ErtsProcLocks locks);
ERTS_GLB_INLINE void erts_proc_inc_refc(Process *);
ERTS_GLB_INLINE void erts_proc_dec_refc(Process *);
@@ -979,6 +985,50 @@ erts_proc_trylock(Process *p, ErtsProcLocks locks)
locks);
}
+ERTS_GLB_INLINE void
+erts_proc_lock_wait_until_released(Process *p, ErtsProcLocks locks)
+{
+#if ERTS_PROC_LOCK_OWN_IMPL
+#if !ERTS_PROC_LOCK_ATOMIC_IMPL
+ Uint32 was_locked;
+ erts_pix_lock(pix_lck);
+ was_locked = (ERTS_PROC_LOCK_FLGS_READ_(&p->lock) & locks);
+ erts_pix_unlock(pix_lck);
+ if (was_locked) {
+ erts_proc_lock(p, locks);
+ erts_proc_unlock(p, locks);
+ }
+#else
+ ETHR_MEMBAR(ETHR_StoreLoad | ETHR_LoadLoad);
+ if (ERTS_PROC_LOCK_FLGS_READ_ACQB_(&p->lock) & locks) {
+ erts_proc_lock(p, locks);
+ erts_proc_unlock(p, locks);
+ }
+#endif
+#elif ERTS_PROC_LOCK_RAW_MUTEX_IMPL
+ if (locks & ERTS_PROC_LOCK_MAIN) {
+ erts_mtx_lock(&p->lock.main);
+ erts_mtx_unlock(&p->lock.main);
+ }
+ if (locks & ERTS_PROC_LOCK_MSGQ) {
+ erts_mtx_lock(&p->lock.msgq);
+ erts_mtx_unlock(&p->lock.msgq);
+ }
+ if (locks & ERTS_PROC_LOCK_BTM) {
+ erts_mtx_lock(&p->lock.btm);
+ erts_mtx_unlock(&p->lock.btm);
+ }
+ if (locks & ERTS_PROC_LOCK_STATUS) {
+ erts_mtx_lock(&p->lock.status);
+ erts_mtx_unlock(&p->lock.status);
+ }
+ if (locks & ERTS_PROC_LOCK_TRACE) {
+ erts_mtx_lock(&p->lock.trace);
+ erts_mtx_unlock(&p->lock.trace);
+ }
+#endif
+}
+
ERTS_GLB_INLINE void erts_proc_inc_refc(Process *p)
{
ASSERT(!(erts_atomic32_read_nob(&p->state) & ERTS_PSFLG_PROXY));
diff --git a/erts/emulator/beam/erl_ptab.c b/erts/emulator/beam/erl_ptab.c
index cc91bdbf0a..8f28ed7f20 100644
--- a/erts/emulator/beam/erl_ptab.c
+++ b/erts/emulator/beam/erl_ptab.c
@@ -828,8 +828,8 @@ cleanup_ptab_list_bif_data(Binary *bp)
if (ptdep->prev) {
/*
- * Only remove this bif invokation when we
- * have preceding invokations.
+ * Only remove this bif invocation when we
+ * have preceding invocations.
*/
ptdep->prev->next = ptdep->next;
if (ptdep->next)
@@ -851,7 +851,7 @@ cleanup_ptab_list_bif_data(Binary *bp)
}
else {
/*
- * Free all elements until next bif invokation
+ * Free all elements until next bif invocation
* is found.
*/
ERTS_PTAB_LIST_ASSERT(ptab->list.data.deleted.start == ptdep);
@@ -1477,7 +1477,7 @@ erts_debug_ptab_list(Process *c_p, ErtsPTab *ptab)
hp = HAlloc(c_p, need); /* we need two heap words for each id */
hp_end = hp + need;
- /* make the list by scanning bakward */
+ /* make the list by scanning backward */
for (i = ptab->r.o.max-1; i >= 0; i--) {
diff --git a/erts/emulator/beam/erl_rbtree.h b/erts/emulator/beam/erl_rbtree.h
index ce401fa7e7..3767239da2 100644
--- a/erts/emulator/beam/erl_rbtree.h
+++ b/erts/emulator/beam/erl_rbtree.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2015-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2015-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -359,7 +359,7 @@
* int indent,
* (void)(*print_node)(ERTS_RBT_T *));
* Prints the tree. Note that this function is recursive.
- * Should only be used for debuging.
+ * Should only be used for debugging.
*/
#ifdef ERTS_RBT_CMP_KEYS
diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c
index bf2e0b8010..65f7d0f280 100644
--- a/erts/emulator/beam/erl_term.c
+++ b/erts/emulator/beam/erl_term.c
@@ -121,7 +121,7 @@ ET_DEFINE_CHECKED(Uint,arityval,Eterm,is_sane_arity_value);
ET_DEFINE_CHECKED(Uint,thing_arityval,Eterm,is_thing);
ET_DEFINE_CHECKED(Uint,thing_subtag,Eterm,is_thing);
ET_DEFINE_CHECKED(Eterm*,binary_val,Wterm,is_binary);
-ET_DEFINE_CHECKED(Eterm*,fun_val,Wterm,is_fun);
+ET_DEFINE_CHECKED(Eterm*,fun_val,Wterm,is_any_fun);
ET_DEFINE_CHECKED(int,bignum_header_is_neg,Eterm,_is_bignum_header);
ET_DEFINE_CHECKED(Eterm,bignum_header_neg,Eterm,_is_bignum_header);
ET_DEFINE_CHECKED(Uint,bignum_header_arity,Eterm,_is_bignum_header);
@@ -144,7 +144,6 @@ ET_DEFINE_CHECKED(struct erl_node_*,external_port_node,Wterm,is_external_port);
ET_DEFINE_CHECKED(Uint,external_ref_data_words,Wterm,is_external_ref);
ET_DEFINE_CHECKED(Uint32*,external_ref_data,Wterm,is_external_ref);
ET_DEFINE_CHECKED(struct erl_node_*,external_ref_node,Eterm,is_external_ref);
-ET_DEFINE_CHECKED(Eterm*,export_val,Wterm,is_export);
ET_DEFINE_CHECKED(Uint,external_thing_data_words,ExternalThing*,is_thing_ptr);
ET_DEFINE_CHECKED(Eterm,make_cp,ErtsCodePtr,_is_legal_cp);
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 490fe1f1d1..5ec1d885e1 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -129,7 +129,6 @@ struct erl_node_; /* Declared in erl_node_tables.h */
#define REF_SUBTAG (0x4 << _TAG_PRIMARY_SIZE) /* REF */
#define FUN_SUBTAG (0x5 << _TAG_PRIMARY_SIZE) /* FUN */
#define FLOAT_SUBTAG (0x6 << _TAG_PRIMARY_SIZE) /* FLOAT */
-#define EXPORT_SUBTAG (0x7 << _TAG_PRIMARY_SIZE) /* FLOAT */
#define _BINARY_XXX_MASK (0x3 << _TAG_PRIMARY_SIZE)
#define REFC_BINARY_SUBTAG (0x8 << _TAG_PRIMARY_SIZE) /* BINARY */
#define HEAP_BINARY_SUBTAG (0x9 << _TAG_PRIMARY_SIZE) /* BINARY */
@@ -146,7 +145,6 @@ struct erl_node_; /* Declared in erl_node_tables.h */
#define _TAG_HEADER_POS_BIG (TAG_PRIMARY_HEADER|POS_BIG_SUBTAG)
#define _TAG_HEADER_NEG_BIG (TAG_PRIMARY_HEADER|NEG_BIG_SUBTAG)
#define _TAG_HEADER_FLOAT (TAG_PRIMARY_HEADER|FLOAT_SUBTAG)
-#define _TAG_HEADER_EXPORT (TAG_PRIMARY_HEADER|EXPORT_SUBTAG)
#define _TAG_HEADER_REF (TAG_PRIMARY_HEADER|REF_SUBTAG)
#define _TAG_HEADER_REFC_BIN (TAG_PRIMARY_HEADER|REFC_BINARY_SUBTAG)
#define _TAG_HEADER_HEAP_BIN (TAG_PRIMARY_HEADER|HEAP_BINARY_SUBTAG)
@@ -313,8 +311,21 @@ _ET_DECLARE_CHECKED(Uint,header_arity,Eterm)
#define MAX_ARITYVAL ((((Uint)1) << 24) - 1)
#define ERTS_MAX_TUPLE_SIZE MAX_ARITYVAL
+/*
+ Due to an optimization that assumes that the word after the arity
+ word is allocated, one should generally not create tuples of arity
+ zero. One should instead use the literal that can be obtained by
+ calling erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE).
+
+ If one really wants to create a zero arityval one should use
+ make_arityval_zero() or make_arityval_unchecked(sz)
+ */
+#define make_arityval_zero() (_make_header(0,_TAG_HEADER_ARITYVAL))
#define make_arityval(sz) (ASSERT((sz) <= MAX_ARITYVAL), \
+ ASSERT((sz) > 0), \
_make_header((sz),_TAG_HEADER_ARITYVAL))
+#define make_arityval_unchecked(sz) (ASSERT((sz) <= MAX_ARITYVAL), \
+ _make_header((sz),_TAG_HEADER_ARITYVAL))
#define is_arity_value(x) (((x) & _TAG_HEADER_MASK) == _TAG_HEADER_ARITYVAL)
#define is_sane_arity_value(x) ((((x) & _TAG_HEADER_MASK) == _TAG_HEADER_ARITYVAL) && \
(((x) >> _HEADER_ARITY_OFFS) <= MAX_ARITYVAL))
@@ -374,30 +385,16 @@ _ET_DECLARE_CHECKED(Eterm*,binary_val,Wterm)
/* process binaries stuff (special case of binaries) */
#define HEADER_PROC_BIN _make_header(PROC_BIN_SIZE-1,_TAG_HEADER_REFC_BIN)
-/* fun & export objects */
-#define is_any_fun(x) (is_fun((x)) || is_export((x)))
-#define is_not_any_fun(x) (!is_any_fun((x)))
-
/* fun objects */
-#define HEADER_FUN _make_header(ERL_FUN_SIZE-2,_TAG_HEADER_FUN)
-#define is_fun_header(x) ((x) == HEADER_FUN)
-#define make_fun(x) make_boxed((Eterm*)(x))
-#define is_fun(x) (is_boxed((x)) && is_fun_header(*boxed_val((x))))
-#define is_not_fun(x) (!is_fun((x)))
+#define HEADER_FUN _make_header(ERL_FUN_SIZE-2,_TAG_HEADER_FUN)
+#define is_fun_header(x) ((x) == HEADER_FUN)
+#define make_fun(x) make_boxed((Eterm*)(x))
+#define is_any_fun(x) (is_boxed((x)) && is_fun_header(*boxed_val((x))))
+#define is_not_any_fun(x) (!is_any_fun((x)))
#define _unchecked_fun_val(x) _unchecked_boxed_val((x))
_ET_DECLARE_CHECKED(Eterm*,fun_val,Wterm)
#define fun_val(x) _ET_APPLY(fun_val,(x))
-/* export access methods */
-#define make_export(x) make_boxed((x))
-#define is_export(x) (is_boxed((x)) && is_export_header(*boxed_val((x))))
-#define is_not_export(x) (!is_export((x)))
-#define _unchecked_export_val(x) _unchecked_boxed_val(x)
-_ET_DECLARE_CHECKED(Eterm*,export_val,Wterm)
-#define export_val(x) _ET_APPLY(export_val,(x))
-#define is_export_header(x) ((x) == HEADER_EXPORT)
-#define HEADER_EXPORT _make_header(1,_TAG_HEADER_EXPORT)
-
/* bignum access methods */
#define make_pos_bignum_header(sz) _make_header((sz),_TAG_HEADER_POS_BIG)
#define make_neg_bignum_header(sz) _make_header((sz),_TAG_HEADER_NEG_BIG)
@@ -477,15 +474,18 @@ typedef union float_def
#define is_tuple(x) (is_boxed((x)) && is_arity_value(*boxed_val((x))))
#define is_not_tuple(x) (!is_tuple((x)))
#define is_tuple_arity(x, a) \
- (is_boxed((x)) && *boxed_val((x)) == make_arityval((a)))
+ (is_boxed((x)) && *boxed_val((x)) == make_arityval_unchecked((a)))
#define is_not_tuple_arity(x, a) (!is_tuple_arity((x),(a)))
#define _unchecked_tuple_val(x) _unchecked_boxed_val(x)
_ET_DECLARE_CHECKED(Eterm*,tuple_val,Wterm)
#define tuple_val(x) _ET_APPLY(tuple_val,(x))
-#define TUPLE0(t) \
- ((t)[0] = make_arityval(0), \
- make_tuple(t))
+/*
+ Due to an optimization that assumes that the word after the arity
+ word is allocated, one should generally not create tuples of arity
+ zero on heaps. One should instead use the literal that can be
+ obtained by calling erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE).
+ */
#define TUPLE1(t,e1) \
((t)[0] = make_arityval(1), \
(t)[1] = (e1), \
@@ -1291,22 +1291,8 @@ _ET_DECLARE_CHECKED(struct erl_node_*,external_ref_node,Eterm)
(hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
(hp)[MAP_HEADER_FLATMAP_SZ+2] = v3, \
make_flatmap(hp))
-#define MAP4(hp, k1, v1, k2, v2, k3, v3, k4, v4) \
- (MAP_HEADER(hp, 4, TUPLE4(hp+4+MAP_HEADER_FLATMAP_SZ, k1, k2, k3, k4)), \
- (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
- (hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
- (hp)[MAP_HEADER_FLATMAP_SZ+2] = v3, \
- (hp)[MAP_HEADER_FLATMAP_SZ+3] = v4, \
- make_flatmap(hp))
-#define MAP5(hp, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5) \
- (MAP_HEADER(hp, 5, TUPLE5(hp+5+MAP_HEADER_FLATMAP_SZ, k1, k2, k3, k4, k5)), \
- (hp)[MAP_HEADER_FLATMAP_SZ+0] = v1, \
- (hp)[MAP_HEADER_FLATMAP_SZ+1] = v2, \
- (hp)[MAP_HEADER_FLATMAP_SZ+2] = v3, \
- (hp)[MAP_HEADER_FLATMAP_SZ+3] = v4, \
- (hp)[MAP_HEADER_FLATMAP_SZ+4] = v5, \
- make_flatmap(hp))
-
+/* MAP4 and greater have to be created with erts_map_from_ks_and_vs as in the
+ debug emulator maps > 3 are hashmaps. */
/* number tests */
@@ -1402,7 +1388,6 @@ _ET_DECLARE_CHECKED(Uint,loader_y_reg_index,Uint)
#define EXTERNAL_PID_DEF 0x6
#define PORT_DEF 0x7
#define EXTERNAL_PORT_DEF 0x8
-#define EXPORT_DEF 0x9
#define FUN_DEF 0xa
#define REF_DEF 0xb
#define EXTERNAL_REF_DEF 0xc
@@ -1472,7 +1457,6 @@ ERTS_GLB_INLINE unsigned tag_val_def(Wterm x)
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE): return BIG_DEF;
case (_TAG_HEADER_REF >> _TAG_PRIMARY_SIZE): return REF_DEF;
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE): return FLOAT_DEF;
- case (_TAG_HEADER_EXPORT >> _TAG_PRIMARY_SIZE): return EXPORT_DEF;
case (_TAG_HEADER_FUN >> _TAG_PRIMARY_SIZE): return FUN_DEF;
case (_TAG_HEADER_EXTERNAL_PID >> _TAG_PRIMARY_SIZE): return EXTERNAL_PID_DEF;
case (_TAG_HEADER_EXTERNAL_PORT >> _TAG_PRIMARY_SIZE): return EXTERNAL_PORT_DEF;
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
index b7f0069eb0..ccd0b3aea1 100644
--- a/erts/emulator/beam/erl_thr_progress.c
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -554,6 +554,22 @@ erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *callbacks)
intrnl->unmanaged.callbacks[tpd->id] = *callbacks;
}
+void
+erts_thr_progress_unregister_unmanaged_thread(void)
+{
+ /*
+ * If used, the previously registered wakeup callback
+ * must be prepared for NULL passed as argument. This since
+ * the callback might be called after this unregistration
+ * in case of an outstanding wakeup request when unregistration
+ * is made.
+ */
+ ErtsThrPrgrData* tpd = erts_thr_progress_data();
+ ASSERT(tpd->id >= 0);
+ intrnl->unmanaged.callbacks[tpd->id].arg = NULL;
+ erts_free(ERTS_ALC_T_THR_PRGR_DATA, tpd);
+}
+
ErtsThrPrgrData *
erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp,
@@ -847,6 +863,12 @@ update(ErtsThrPrgrData *tpd)
int
erts_thr_progress_update(ErtsThrPrgrData *tpd)
{
+#ifdef DEBUG
+ /* If we've run any code that requires a code barrier, it must have been
+ * scheduled prior to this point. */
+ erts_debug_check_code_barrier();
+#endif
+
return update(tpd);
}
@@ -911,10 +933,18 @@ erts_thr_progress_finalize_wait(ErtsThrPrgrData *tpd)
break;
current = val;
}
- if (block_count_inc())
- block_thread(tpd);
- if (update(tpd))
- leader_update(tpd);
+
+ if (block_count_inc()) {
+ block_thread(tpd);
+ } else {
+ /* Issue a code barrier if one was requested while thread progress was
+ * blocked. */
+ erts_code_ix_finalize_wait();
+ }
+
+ if (update(tpd)) {
+ leader_update(tpd);
+ }
}
void
@@ -1124,7 +1154,7 @@ request_wakeup_managed(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value)
ASSERT(!erts_thr_progress_has_reached(value));
/*
- * This thread is guarranteed to issue a full memory barrier:
+ * This thread is guaranteed 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.
@@ -1293,6 +1323,10 @@ block_thread(ErtsThrPrgrData *tpd)
} while (block_count_inc());
+ /* Issue a code barrier if one was requested while thread progress was
+ * blocked. */
+ erts_code_ix_finalize_wait();
+
cbp->finalize_wait(cbp->arg);
return lflgs;
@@ -1383,7 +1417,7 @@ erts_thr_progress_fatal_error_wait(SWord timeout) {
/*
* Counting poll intervals may give us a too long timeout
* if cpu is busy. We use timeout time to try to prevent
- * this. In case we havn't got time correction this may
+ * this. In case we haven't got time correction this may
* however fail too...
*/
timeout_time = erts_get_monotonic_time(esdp);
diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h
index 82a5f1811d..3adc8e32c6 100644
--- a/erts/emulator/beam/erl_thr_progress.h
+++ b/erts/emulator/beam/erl_thr_progress.h
@@ -127,6 +127,7 @@ void erts_thr_progress_init(int no_schedulers, int managed, int unmanaged);
ErtsThrPrgrData *erts_thr_progress_register_managed_thread(
ErtsSchedulerData *esdp, ErtsThrPrgrCallbacks *, int, int);
void erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *);
+void erts_thr_progress_unregister_unmanaged_thread(void);
void erts_thr_progress_active(ErtsThrPrgrData *, int on);
void erts_thr_progress_wakeup(ErtsThrPrgrData *,
ErtsThrPrgrVal value);
diff --git a/erts/emulator/beam/erl_thr_queue.c b/erts/emulator/beam/erl_thr_queue.c
index aab7c199d2..0813c5530e 100644
--- a/erts/emulator/beam/erl_thr_queue.c
+++ b/erts/emulator/beam/erl_thr_queue.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@
* 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
+ * Memory deallocation 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.
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index e6f0300e7c..d3639e1135 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,10 @@
* - ERTS_THR_DATA_DEPENDENCY_READ_MEMORY_BARRIER
* Data dependency read barrier. Orders *only* loads
* according to data dependency across the barrier.
+ * - ERTS_THR_INSTRUCTION_BARRIER
+ * Instruction synchronization barrier. Orders *only*
+ * instruction fetches. These are not allowed to be
+ * reordered over the barrier.
*
* --- Atomic operations ---
*
@@ -266,6 +270,23 @@
#define ERTS_THR_READ_MEMORY_BARRIER ETHR_READ_MEMORY_BARRIER
#define ERTS_THR_DATA_DEPENDENCY_READ_MEMORY_BARRIER ETHR_READ_DEPEND_MEMORY_BARRIER
+#ifdef ETHR_INSTRUCTION_BARRIER
+# define ERTS_THR_INSTRUCTION_BARRIER ETHR_INSTRUCTION_BARRIER
+#else
+/* !! Note that we DO NOT define a fallback !!
+ *
+ * If we cannot issue an instruction barrier ourselves, we are most likely
+ * running on an operating system that disallows this operation from user-space
+ * (e.g. MacOS). In that case, we either:
+ *
+ * 1. Rely on a system call to do everything for us, including core
+ * synchronization.
+ * 2. Lack a way to control instruction cache, and therefore can't use the JIT
+ * begin with.
+ *
+ * In either case we want a compile-time error when this barrier is used. */
+#endif
+
#ifdef ERTS_ENABLE_LOCK_POSITION
#define erts_mtx_lock(L) erts_mtx_lock_x(L, __FILE__, __LINE__)
#define erts_mtx_trylock(L) erts_mtx_trylock_x(L, __FILE__, __LINE__)
@@ -445,6 +466,7 @@ ERTS_GLB_INLINE void erts_rwmtx_init(erts_rwmtx_t *rwmtx,
char *name,
Eterm extra,
erts_lock_flags_t flags);
+ERTS_GLB_INLINE size_t erts_rwmtx_size(erts_rwmtx_t *rwmtx);
ERTS_GLB_INLINE void erts_rwmtx_destroy(erts_rwmtx_t *rwmtx);
#ifdef ERTS_ENABLE_LOCK_POSITION
ERTS_GLB_INLINE int erts_rwmtx_tryrlock_x(erts_rwmtx_t *rwmtx, const char *file, unsigned int line);
@@ -1883,6 +1905,11 @@ erts_rwmtx_init(erts_rwmtx_t *rwmtx, char *name, Eterm extra,
erts_rwmtx_init_opt(rwmtx, NULL, name, extra, flags);
}
+ERTS_GLB_INLINE size_t
+erts_rwmtx_size(erts_rwmtx_t *rwmtx) {
+ return ethr_rwmutex_size(&rwmtx->rwmtx);
+}
+
ERTS_GLB_INLINE void
erts_rwmtx_destroy(erts_rwmtx_t *rwmtx)
{
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 0e1d4b087f..7af829e738 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -216,6 +216,15 @@ update_last_mtime(ErtsSchedulerData *esdp, ErtsMonotonicTime mtime)
if (!esdp)
esdp = erts_get_scheduler_data();
if (esdp) {
+#if 1
+ if (mtime < esdp->last_monotonic_time)
+ erts_exit(ERTS_ABORT_EXIT,
+ "Monotonic time stepped backwards!\n"
+ "Previous time: %b64d\n"
+ "Current time: %b64d\n",
+ esdp->last_monotonic_time,
+ mtime);
+#endif
ASSERT(mtime >= esdp->last_monotonic_time);
esdp->last_monotonic_time = mtime;
esdp->check_time_reds = 0;
@@ -1982,12 +1991,10 @@ send_time_offset_changed_notifications(void *new_offsetp)
for (mix = 0; mix < no_monitors; mix++) {
*patch_refp = to_mon_info[mix].ref;
- erts_proc_sig_send_persistent_monitor_msg(ERTS_MON_TYPE_TIME_OFFSET,
- *patch_refp,
- am_clock_service,
- to_mon_info[mix].pid,
- message_template,
- hsz);
+ erts_proc_sig_send_monitor_time_offset_msg(*patch_refp,
+ to_mon_info[mix].pid,
+ message_template,
+ hsz);
}
erts_free(ERTS_ALC_T_TMP, tmp);
@@ -2151,6 +2158,10 @@ time_unit_conversion(Process *c_p, Eterm term, ErtsMonotonicTime val, ErtsMonoto
/* Convert to common user specified time units */
switch (term) {
+ case am_native:
+ result = val + muloff*ERTS_MONOTONIC_OFFSET_NATIVE;
+ ERTS_BIF_PREP_RET(ret, make_time_val(c_p, result));
+ break;
case am_second:
case am_seconds:
case make_small(1):
@@ -2334,7 +2345,7 @@ erts_napi_convert_time_unit(ErtsMonotonicTime val, int from, int to)
{
ErtsMonotonicTime ffreq, tfreq, denom;
/*
- * Convertion between time units using floor function.
+ * Conversion between time units using floor function.
*
* Note that this needs to work also for negative
* values. Ordinary integer division on a negative
@@ -2434,7 +2445,7 @@ BIF_RETTYPE timestamp_0(BIF_ALIST_0)
/*
* Mega seconds is the only value that potentially
- * ever could be a bignum. However, that wont happen
+ * ever could be a bignum. However, that won't happen
* during at least the next 4 million years...
*
* (System time will also have wrapped in the
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 3ea796e0e3..82d4cf728c 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,6 +53,7 @@
#include "erl_thr_progress.h"
#include "erl_bif_unique.h"
#include "erl_map.h"
+#include "erl_global_literals.h"
#if 0
#define DEBUG_PRINTOUTS
@@ -1121,7 +1122,7 @@ erts_call_trace(Process* p, ErtsCodeInfo *info, Binary *match_spec,
* use process flags
*/
tracee_flags = &ERTS_TRACE_FLAGS(p);
- /* Is is not ideal at all to call this check twice,
+ /* It is not ideal at all to call this check twice,
it should be optimized so that only one call is made. */
if (!is_tracer_enabled(p, ERTS_PROC_LOCK_MAIN, &p->common, &tnif,
TRACE_FUN_ENABLED, am_trace_status)
@@ -1245,7 +1246,7 @@ erts_call_trace(Process* p, ErtsCodeInfo *info, Binary *match_spec,
ASSERT(!ERTS_TRACER_IS_NIL(*tracer));
/*
- * Build the the {M,F,A} tuple in the local heap.
+ * Build the {M,F,A} tuple in the local heap.
* (A is arguments or arity.)
*/
@@ -2632,6 +2633,9 @@ lookup_tracer_nif(const ErtsTracer tracer)
{
ErtsTracerNif tnif_tmpl;
ErtsTracerNif *tnif;
+ if (tracer == erts_tracer_nil) {
+ return NULL;
+ }
tnif_tmpl.module = ERTS_TRACER_MODULE(tracer);
ERTS_LC_ASSERT(erts_thr_progress_lc_is_delaying() || erts_get_scheduler_id() > 0);
erts_rwmtx_rlock(&tracer_mtx);
@@ -2793,8 +2797,12 @@ send_to_tracer_nif_raw(Process *c_p, Process *tracee,
map_values[map_elem_count++] = am_monotonic;
map->size = map_elem_count;
- map->keys = make_tuple(local_heap);
- local_heap[0] = make_arityval(map_elem_count);
+ if (map_elem_count == 0) {
+ map->keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ map->keys = make_tuple(local_heap);
+ local_heap[0] = make_arityval(map_elem_count);
+ }
#undef MAP_SIZE
erts_nif_call_function(c_p, tracee ? tracee : c_p,
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index 1fcc0f1a13..1c0fed9658 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
/*
* The bits used effects trace flags (of processes and ports)
* as well as sequential trace flags. If changed make sure
- * these arn't messed up...
+ * these aren't messed up...
*/
#define ERTS_TRACE_TS_TYPE_BITS 3
#define ERTS_TRACE_TS_TYPE_MASK \
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index 992ef9e3e4..945a22a632 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -478,7 +478,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
} /* is_list(ioterm) */
if (!is_list(ioterm) && !is_nil(ioterm)) {
- /* inproper list end */
+ /* improper list end */
if (is_binary(ioterm)) {
Sint x;
if (latin1) {
@@ -764,7 +764,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
} /* is_list(ioterm) */
if ((*left) && !is_list(ioterm) && !is_nil(ioterm)) {
- /* inproper list end */
+ /* improper list end */
if (is_binary(ioterm)) {
ioterm = do_build_utf8(p,ioterm,left,latin1,target,pos,characters,err,leftover,num_leftovers);
if ((*err) != 0) {
@@ -939,7 +939,7 @@ static int is_valid_utf8(Eterm orig_bin)
Uint bitsize;
Uint size;
byte *temp_alloc = NULL;
- byte *endpos;
+ const byte *endpos;
Uint numchar;
byte *bytes;
int ret;
@@ -1188,7 +1188,7 @@ BIF_RETTYPE unicode_characters_to_list_2(BIF_ALIST_2)
* a faster analyze and size count with this function.
*/
static ERTS_INLINE int
-analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left,
+analyze_utf8(const byte *source, Uint size, const byte **err_pos, Uint *num_chars, int *left,
Sint *num_latin1_chars, Uint max_chars)
{
int res = ERTS_UTF8_OK;
@@ -1288,29 +1288,29 @@ analyze_utf8(byte *source, Uint size, byte **err_pos, Uint *num_chars, int *left
return res;
}
-int erts_analyze_utf8(byte *source, Uint size,
- byte **err_pos, Uint *num_chars, int *left)
+int erts_analyze_utf8(const byte *source, Uint size,
+ const byte **err_pos, Uint *num_chars, int *left)
{
return analyze_utf8(source, size, err_pos, num_chars, left, NULL, 0);
}
-int erts_analyze_utf8_x(byte *source, Uint size,
- byte **err_pos, Uint *num_chars, int *left,
+int erts_analyze_utf8_x(const byte *source, Uint size,
+ const byte **err_pos, Uint *num_chars, int *left,
Sint *num_latin1_chars, Uint max_chars)
{
return analyze_utf8(source, size, err_pos, num_chars, left, num_latin1_chars, max_chars);
}
-static ERTS_INLINE Eterm
-make_list_from_utf8_buf(Eterm **hpp, Uint num,
- byte *bytes, Uint sz,
- Uint *num_built, Uint *num_eaten,
- Eterm tail)
+Eterm
+erts_make_list_from_utf8_buf(Eterm **hpp, Uint num,
+ const byte *bytes, Uint sz,
+ Uint *num_built, Uint *num_eaten,
+ Eterm tail)
{
Eterm *hp;
Eterm ret;
Uint left = num;
- byte *source, *ssource;
+ const byte *source, *ssource;
Uint unipoint;
hp = *hpp;
ret = tail;
@@ -1369,9 +1369,9 @@ static Eterm do_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz,
hp = HAlloc(p,num * 2);
- return make_list_from_utf8_buf(&hp, num, bytes, sz,
- num_built, num_eaten,
- tail);
+ return erts_make_list_from_utf8_buf(&hp, num, bytes, sz,
+ num_built, num_eaten,
+ tail);
}
Eterm erts_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz, Uint left,
Uint *num_built, Uint *num_eaten, Eterm tail)
@@ -1389,7 +1389,7 @@ Uint erts_atom_to_string_length(Eterm atom)
if (ap->latin1_chars >= 0)
return (Uint) ap->len;
else {
- byte* err_pos;
+ const byte* err_pos;
Uint num_chars;
int ares =
erts_analyze_utf8(ap->name, ap->len, &err_pos, &num_chars, NULL);
@@ -1399,17 +1399,17 @@ Uint erts_atom_to_string_length(Eterm atom)
}
}
-Eterm erts_atom_to_string(Eterm **hpp, Eterm atom)
+Eterm erts_atom_to_string(Eterm **hpp, Eterm atom, Eterm tail)
{
Atom *ap;
ASSERT(is_atom(atom));
ap = atom_tab(atom_val(atom));
if (ap->latin1_chars >= 0)
- return buf_to_intlist(hpp, (char*)ap->name, ap->len, NIL);
+ return buf_to_intlist(hpp, (char*)ap->name, ap->len, tail);
else {
Eterm res;
- byte* err_pos;
+ const byte* err_pos;
Uint num_chars, num_built, num_eaten;
#ifdef DEBUG
Eterm *hp_start = *hpp;
@@ -1418,8 +1418,8 @@ Eterm erts_atom_to_string(Eterm **hpp, Eterm atom)
erts_analyze_utf8(ap->name, ap->len, &err_pos, &num_chars, NULL);
ASSERT(ares == ERTS_UTF8_OK);
- res = make_list_from_utf8_buf(hpp, num_chars, ap->name, ap->len,
- &num_built, &num_eaten, NIL);
+ res = erts_make_list_from_utf8_buf(hpp, num_chars, ap->name, ap->len,
+ &num_built, &num_eaten, tail);
ASSERT(num_built == num_chars);
ASSERT(num_eaten == ap->len);
@@ -1756,7 +1756,7 @@ static BIF_RETTYPE do_bif_utf8_to_list(Process *p,
Eterm *hp;
Eterm ret;
byte *temp_alloc = NULL;
- byte *endpos;
+ const byte *endpos;
Uint numchar;
Uint b_sz; /* size of the non analyzed tail */
@@ -2158,7 +2158,7 @@ char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
ErtsAlcType_t alloc_type, Sint* used,
Uint extra_wchars)
{
- byte *err_pos;
+ const byte *err_pos;
Uint num_chars;
char* name_buf = NULL;
Sint need;
@@ -2200,7 +2200,7 @@ Eterm erts_convert_native_to_filename(Process *p, size_t size, byte *bytes)
{
Uint num_chars;
Eterm *hp;
- byte *err_pos;
+ const byte *err_pos;
Uint num_built; /* characters */
Uint num_eaten; /* bytes */
Eterm ret;
@@ -2379,7 +2379,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
if (x <= 0xffff) {
need += 2;
break;
- } /* else fall throug to error */
+ } /* else fall through to error */
default:
DESTROY_ESTACK(stack);
return ((Sint) -1);
@@ -2420,7 +2420,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
} /* is_list(ioterm) */
if (!is_list(ioterm) && !is_nil(ioterm)) {
- /* inproper list end */
+ /* improper list end */
DESTROY_ESTACK(stack);
return ((Sint) -1);
}
@@ -2678,7 +2678,7 @@ BIF_RETTYPE prim_file_internal_name2native_1(BIF_ALIST_1)
if (is_binary(BIF_ARG_1)) {
byte *temp_alloc = NULL;
byte *bytes;
- byte *err_pos;
+ const byte *err_pos;
Uint size,num_chars;
/* Uninterpreted encoding except if windows widechar, in case we convert from
utf8 to win_wchar */
@@ -2763,7 +2763,7 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1)
Eterm *hp;
byte *temp_alloc = NULL;
byte *bytes;
- byte *err_pos;
+ const byte *err_pos;
Uint num_built; /* characters */
Uint num_eaten; /* bytes */
Eterm ret;
@@ -2857,7 +2857,7 @@ BIF_RETTYPE prim_file_internal_normalize_utf8_1(BIF_ALIST_1)
Eterm ret;
byte *temp_alloc = NULL;
byte *bytes;
- byte *err_pos;
+ const byte *err_pos;
if (is_not_binary(BIF_ARG_1)) {
BIF_ERROR(BIF_P,BADARG);
@@ -2890,7 +2890,7 @@ BIF_RETTYPE prim_file_is_translatable_1(BIF_ALIST_1)
ERTS_DECLARE_DUMMY(Uint bitoffs);
byte *temp_alloc = NULL;
byte *bytes;
- byte *err_pos;
+ const byte *err_pos;
int status;
if (is_not_binary(BIF_ARG_1)) {
diff --git a/erts/emulator/beam/erl_unicode.h b/erts/emulator/beam/erl_unicode.h
index 31369fc8f9..930fc1f600 100644
--- a/erts/emulator/beam/erl_unicode.h
+++ b/erts/emulator/beam/erl_unicode.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,6 @@
#define _ERL_UNICODE_H
Uint erts_atom_to_string_length(Eterm atom);
-Eterm erts_atom_to_string(Eterm **hpp, Eterm atom);
+Eterm erts_atom_to_string(Eterm **hpp, Eterm atom, Eterm tail);
#endif /* _ERL_UNICODE_H */
diff --git a/erts/emulator/beam/erl_utils.h b/erts/emulator/beam/erl_utils.h
index f87773ddca..e83881f52f 100644
--- a/erts/emulator/beam/erl_utils.h
+++ b/erts/emulator/beam/erl_utils.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,6 +73,7 @@ Uint32 make_hash2(Eterm);
Uint32 trapping_make_hash2(Eterm, Eterm*, struct process*);
Uint32 make_hash(Eterm);
Uint32 make_internal_hash(Eterm, Uint32 salt);
+Uint32 make_map_hash(Eterm key, int level);
void erts_save_emu_args(int argc, char **argv);
Eterm erts_get_emu_args(struct process *c_p);
@@ -107,8 +108,8 @@ void erts_init_utils(void);
void erts_init_utils_mem(void);
void erts_utils_sched_spec_data_init(void);
-erts_dsprintf_buf_t *erts_create_tmp_dsbuf(Uint);
void erts_destroy_tmp_dsbuf(erts_dsprintf_buf_t *);
+erts_dsprintf_buf_t *erts_create_tmp_dsbuf(Uint) ERTS_ATTR_MALLOC_D(erts_destroy_tmp_dsbuf,1);
int eq(Eterm, Eterm);
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index 50e3fdc9f2..54df471cda 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,9 +27,17 @@
*/
/* #define FORCE_HEAP_FRAGS */
-/* valgrind can't handle stack switching, so we will turn off native stack. */
+/* `valgrind` can't handle stack switching, so we will turn off native
+ * stack. */
#ifdef VALGRIND
#undef NATIVE_ERLANG_STACK
+#undef ERLANG_FRAME_POINTERS
+#endif
+
+/* Frame pointer support costs an extra word per process even when unused, so
+ * it's worth disabling for compact builds. */
+#ifdef CODE_MODEL_SMALL
+#undef ERLANG_FRAME_POINTERS
#endif
#if defined(DEBUG) && !defined(CHECK_FOR_HOLES) && !defined(__WIN32__)
@@ -40,9 +48,10 @@
#define EMULATOR "BEAM"
#define SEQ_TRACE 1
-#define CONTEXT_REDS 4000 /* Swap process out after this number */
-#define MAX_ARG 255 /* Max number of arguments allowed */
-#define MAX_REG 1024 /* Max number of x(N) registers used */
+#define CONTEXT_REDS 4000 /* Swap process out after this number */
+#define MAX_ARG 255 /* Max number of arguments allowed */
+#define MAX_REG 1024 /* Max number of x(N) registers used */
+#define REG_MASK (MAX_REG - 1)
/*
* Guard BIFs and the new trapping length/1 implementation need 3 extra
@@ -54,7 +63,23 @@
#define VH_DEFAULT_SIZE 32768 /* default virtual (bin) heap min size (words) */
#define H_DEFAULT_MAX_SIZE 0 /* default max heap size is off */
-#define CP_SIZE 1
+typedef enum {
+ /* Return address only */
+ ERTS_FRAME_LAYOUT_RA,
+ /* Frame pointer, return address */
+ ERTS_FRAME_LAYOUT_FP_RA
+} ErtsFrameLayout;
+
+ERTS_GLB_INLINE
+int erts_cp_size(void);
+
+#if defined(BEAMASM) && defined(ERLANG_FRAME_POINTERS)
+extern ErtsFrameLayout ERTS_WRITE_UNLIKELY(erts_frame_layout);
+# define CP_SIZE erts_cp_size()
+#else
+# define erts_frame_layout ERTS_FRAME_LAYOUT_RA
+# define CP_SIZE 1
+#endif
/* In the JIT we're not guaranteed to have allocated a word for the CP when
* allocating a stack frame (it's still reserved however), as the `call` and
@@ -76,6 +101,8 @@
#if defined(BEAMASM) && defined(NATIVE_ERLANG_STACK)
#define S_REDZONE (CP_SIZE * 3)
+#elif defined(BEAMASM) && defined(__aarch64__)
+#define S_REDZONE (CP_SIZE * 3)
#elif defined(DEBUG)
/* Ensure that a redzone won't cause problems in the interpreter. */
#define S_REDZONE CP_SIZE
@@ -227,14 +254,12 @@ extern Uint erts_instr_count[];
extern int H_MIN_SIZE; /* minimum (heap + stack) */
extern int BIN_VH_MIN_SIZE; /* minimum virtual (bin) heap */
-extern int H_MAX_SIZE; /* maximum (heap + stack) */
+extern Uint H_MAX_SIZE; /* maximum (heap + stack) */
extern int H_MAX_FLAGS; /* maximum heap flags */
extern int erts_atom_table_size;/* Atom table size */
extern int erts_pd_initial_size;/* Initial Process dictionary table size */
-#define ORIG_CREATION 0
-
/* macros for extracting bytes from uint16's */
#define hi_byte(a) ((a) >> 8)
@@ -291,4 +316,17 @@ extern void** beam_ops;
#endif /* BEAMASM */
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+ERTS_GLB_INLINE
+int erts_cp_size()
+{
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ return 1;
+ }
+
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+ return 2;
+}
+#endif
+
#endif /* __ERL_VM_H__ */
diff --git a/erts/emulator/beam/erlang_dtrace.d b/erts/emulator/beam/erlang_dtrace.d
index 4f0b61fb61..bc73432f10 100644
--- a/erts/emulator/beam/erlang_dtrace.d
+++ b/erts/emulator/beam/erlang_dtrace.d
@@ -23,7 +23,7 @@
* 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.
+ * 1. The "__" will turn into a hyphen, "-", 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.
diff --git a/erts/emulator/beam/error.h b/erts/emulator/beam/error.h
index 2067505eda..e307f3ed6d 100644
--- a/erts/emulator/beam/error.h
+++ b/erts/emulator/beam/error.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -165,8 +165,10 @@
/* Bad map */
#define EXC_BADKEY ((19 << EXC_OFFSET) | EXC_ERROR)
/* Bad key in map */
+#define EXC_BADRECORD ((20 << EXC_OFFSET) | EXC_ERROR)
+ /* Bad key in map */
-#define NUMBER_EXIT_CODES 20 /* The number of exit code indices */
+#define NUMBER_EXIT_CODES 21 /* The number of exit code indices */
/*
* Internal pseudo-error codes.
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 8ed54ea1c2..fdaf1a15a5 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -123,15 +123,15 @@ export_alloc(struct export_entry* tmpl_e)
blob = (struct export_blob*) erts_alloc(ERTS_ALC_T_EXPORT, sizeof(*blob));
erts_atomic_add_nob(&total_entries_bytes, sizeof(*blob));
obj = &blob->exp;
- obj->info.op = 0;
- obj->info.u.gen_bp = NULL;
+ sys_memset(&obj->info.u, 0, sizeof(obj->info.u));
+ obj->info.gen_bp = NULL;
obj->info.mfa.module = tmpl->info.mfa.module;
obj->info.mfa.function = tmpl->info.mfa.function;
obj->info.mfa.arity = tmpl->info.mfa.arity;
obj->bif_number = -1;
obj->is_bif_traced = 0;
- memset(&obj->trampoline, 0, sizeof(obj->trampoline));
+ sys_memset(&obj->trampoline, 0, sizeof(obj->trampoline));
if (BeamOpsAreInitialized()) {
obj->trampoline.common.op = BeamOpCodeAddr(op_call_error_handler);
@@ -293,7 +293,7 @@ erts_export_put(Eterm mod, Eterm func, unsigned int arity)
res = ee->ep;
#ifdef BEAMASM
- res->addresses[ERTS_SAVE_CALLS_CODE_IX] = beam_save_calls;
+ res->dispatch.addresses[ERTS_SAVE_CALLS_CODE_IX] = beam_save_calls;
#endif
return res;
@@ -336,7 +336,8 @@ erts_export_get_or_make_stub(Eterm mod, Eterm func, unsigned int arity)
ep = entry->ep;
#ifdef BEAMASM
- ep->addresses[ERTS_SAVE_CALLS_CODE_IX] = beam_save_calls;
+ ep->dispatch.addresses[ERTS_SAVE_CALLS_CODE_IX] =
+ beam_save_calls;
#endif
ASSERT(ep);
@@ -395,10 +396,6 @@ void export_start_staging(void)
ErtsCodeIndex src_ix = erts_active_code_ix();
IndexTable* dst = &export_tables[dst_ix];
IndexTable* src = &export_tables[src_ix];
- struct export_entry* src_entry;
-#ifdef DEBUG
- struct export_entry* dst_entry;
-#endif
int i;
ASSERT(dst_ix != src_ix);
@@ -409,13 +406,23 @@ void export_start_staging(void)
* Insert all entries in src into dst table
*/
for (i = 0; i < src->entries; i++) {
- src_entry = (struct export_entry*) erts_index_lookup(src, i);
- src_entry->ep->addresses[dst_ix] = src_entry->ep->addresses[src_ix];
-#ifdef DEBUG
- dst_entry = (struct export_entry*)
+ struct export_entry* src_entry;
+ ErtsDispatchable *disp;
+
+ src_entry = (struct export_entry*) erts_index_lookup(src, i);
+ disp = &src_entry->ep->dispatch;
+
+ disp->addresses[dst_ix] = disp->addresses[src_ix];
+
+#ifndef DEBUG
+ index_put_entry(dst, src_entry);
+#else /* DEBUG */
+ {
+ struct export_entry* dst_entry =
+ (struct export_entry*)index_put_entry(dst, src_entry);
+ ASSERT(entry_to_blob(src_entry) == entry_to_blob(dst_entry));
+ }
#endif
- index_put_entry(dst, src_entry);
- ASSERT(entry_to_blob(src_entry) == entry_to_blob(dst_entry));
}
export_staging_unlock();
diff --git a/erts/emulator/beam/export.h b/erts/emulator/beam/export.h
index 699f67da95..93b2b7a673 100644
--- a/erts/emulator/beam/export.h
+++ b/erts/emulator/beam/export.h
@@ -32,30 +32,25 @@
#ifdef BEAMASM
#define OP_PAD BeamInstr __pad[1];
#define DISPATCH_SIZE 1
-#define ERTS_ADDRESSV_SIZE (ERTS_NUM_CODE_IX + 1)
-#define ERTS_SAVE_CALLS_CODE_IX (ERTS_ADDRESSV_SIZE - 1)
#else
#define OP_PAD
#define DISPATCH_SIZE 0
-#define ERTS_ADDRESSV_SIZE ERTS_NUM_CODE_IX
#endif
typedef struct export_
{
- /* Pointer to code for function.
- *
- * !! THIS WAS DELIBERATELY RENAMED TO CAUSE ERRORS WHEN MERGING !!
+ /* !! WARNING !!
*
* The JIT has a special calling convention for export entries, assuming
* the entry itself is in a certain register. Blindly setting `c_p->i` to
- * one of these addresses will crash the emulator when the entry is traced,
- * which is unlikely to be caught in our tests.
+ * one of the addresses in `dispatch` will crash the emulator when the
+ * entry is traced, which is unlikely to be caught in our tests.
*
* Use the `BIF_TRAP` macros if at all possible, and be _very_ careful when
- * accessing these directly.
+ * accessing this field directly.
*
- * See `BeamAssembler::emit_setup_export_call` for details. */
- ErtsCodePtr addresses[ERTS_ADDRESSV_SIZE];
+ * See `BeamAssembler::emit_setup_dispatchable_call` for details. */
+ ErtsDispatchable dispatch;
/* Index into bif_table[], or -1 if not a BIF. */
int bif_number;
@@ -167,7 +162,7 @@ ERTS_GLB_INLINE void erts_activate_export_trampoline(Export *ep, int code_ix) {
trampoline_address = (ErtsCodePtr)&ep->trampoline.raw[0];
#endif
- ep->addresses[code_ix] = trampoline_address;
+ ep->dispatch.addresses[code_ix] = trampoline_address;
}
ERTS_GLB_INLINE int erts_is_export_trampoline_active(Export *ep, int code_ix) {
@@ -180,7 +175,7 @@ ERTS_GLB_INLINE int erts_is_export_trampoline_active(Export *ep, int code_ix) {
trampoline_address = (ErtsCodePtr)&ep->trampoline.raw[0];
#endif
- return ep->addresses[code_ix] == trampoline_address;
+ return ep->dispatch.addresses[code_ix] == trampoline_address;
}
ERTS_GLB_INLINE Export*
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 67584e38ec..a95e098c59 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@
#include "erl_map.h"
#include "erl_proc_sig_queue.h"
#include "erl_trace.h"
+#include "erl_global_literals.h"
#define PASS_THROUGH 'p'
@@ -65,19 +66,6 @@
#define ERTS_MAX_TINY_CREATION (3)
#define is_tiny_creation(Cre) ((unsigned)(Cre) <= ERTS_MAX_TINY_CREATION)
-/*
- * When 0 is used as creation, the real creation
- * is unknown. Creation 0 on data will be changed to current
- * creation of the node which it belongs to when it enters
- * that node.
- * This typically happens when a remote pid is created with
- * list_to_pid/1 and then sent to the remote node. This behavior
- * has the undesirable effect that a pid can be passed between nodes,
- * and as a result of that not being equal to itself (the pid that
- * comes back isn't equal to the original pid).
- *
- */
-
#undef ERTS_DEBUG_USE_DIST_SEP
#ifdef DEBUG
# if 0
@@ -123,12 +111,9 @@ static ErtsExtSzRes encode_size_struct_int(TTBSizeContext*, ErtsAtomCacheMap *ac
static Export binary_to_term_trap_export;
static BIF_RETTYPE binary_to_term_trap_1(BIF_ALIST_1);
static Sint transcode_dist_obuf(ErtsDistOutputBuf*, DistEntry*, Uint64 dflags, Sint reds);
-static byte *hopefull_bit_binary(TTBEncodeContext* ctx, byte **epp, Binary *pb_val, Eterm pb_term,
- byte *bytes, byte bitoffs, byte bitsize, Uint sz);
-static void hopefull_export(TTBEncodeContext* ctx, byte **epp, Export* exp, Uint32 dflags,
- struct erl_off_heap_header** off_heap);
static void store_in_vec(TTBEncodeContext *ctx, byte *ep, Binary *ohbin, Eterm ohpb,
byte *ohp, Uint ohsz);
+static Uint32 calc_iovec_fun_size(SysIOVec* iov, Uint32 fun_high_ix, byte* size_p);
void erts_init_external(void) {
erts_init_trap_export(&term_to_binary_trap_export,
@@ -230,7 +215,6 @@ insert_acache_map(ErtsAtomCacheMap *acmp, Eterm atom, Uint64 dflags)
if (acmp && acmp->sz < ERTS_MAX_INTERNAL_ATOM_CACHE_ENTRIES) {
int ix;
ASSERT(acmp->hdr_sz < 0);
- ASSERT(dflags & DFLAG_UTF8_ATOMS);
ix = atom2cix(atom);
if (acmp->cache[ix].iix < 0) {
acmp->cache[ix].iix = acmp->sz;
@@ -268,7 +252,6 @@ erts_finalize_atom_cache_map(ErtsAtomCacheMap *acmp, Uint64 dflags)
int i;
int sz = 0;
int min_sz;
- ASSERT(dflags & DFLAG_UTF8_ATOMS);
ASSERT(acmp->hdr_sz < 0);
/* Make sure cache update instructions fit */
min_sz = (2+4)*acmp->sz;
@@ -438,7 +421,6 @@ Sint erts_encode_ext_dist_header_finalize(ErtsDistOutputBuf* ob,
int long_atoms;
Uint64 seq_id = 0, frag_id = 0;
register byte *ep = ob->eiov->iov[1].iov_base;
- ASSERT(dflags & DFLAG_UTF8_ATOMS);
/*
* The buffer can have different layouts at this point depending on
@@ -852,9 +834,6 @@ erts_prepare_dist_ext(ErtsDistExternal *edep,
ASSERT(dep);
erts_de_rlock(dep);
- ASSERT(dep->dflags & DFLAG_UTF8_ATOMS);
-
-
if ((dep->state != ERTS_DE_STATE_CONNECTED &&
dep->state != ERTS_DE_STATE_PENDING)
|| dep->connection_id != conn_id) {
@@ -1612,8 +1591,7 @@ typedef struct {
ErtsHeapFactory factory;
int remaining_n;
char* remaining_bytes;
- ErtsWStack flat_maps;
- ErtsPStack hamt_array;
+ ErtsPStack map_array;
} B2TDecodeContext;
typedef struct {
@@ -1812,9 +1790,9 @@ static void b2t_destroy_context(B2TContext* context)
case B2TDecodeTuple:
case B2TDecodeString:
case B2TDecodeBinary:
- if (context->u.dc.hamt_array.pstart) {
- erts_free(context->u.dc.hamt_array.alloc_type,
- context->u.dc.hamt_array.pstart);
+ if (context->u.dc.map_array.pstart) {
+ erts_free(context->u.dc.map_array.alloc_type,
+ context->u.dc.map_array.pstart);
}
break;
default:;
@@ -1969,8 +1947,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Eterm bin, B2TContext *ctx)
ctx->u.dc.res = (Eterm) (UWord) NULL;
ctx->u.dc.next = &ctx->u.dc.res;
erts_factory_proc_prealloc_init(&ctx->u.dc.factory, p, ctx->heap_size);
- ctx->u.dc.flat_maps.wstart = NULL;
- ctx->u.dc.hamt_array.pstart = NULL;
+ ctx->u.dc.map_array.pstart = NULL;
ctx->state = B2TDecode;
/*fall through*/
case B2TDecode:
@@ -2955,9 +2932,8 @@ static ERTS_INLINE int dec_is_this_node(Eterm sysname, Uint32 creation)
{
return (sysname == INTERNAL_LOCAL_SYSNAME
||
- (sysname == erts_this_node->sysname
- && (creation == erts_this_node->creation
- || creation == ORIG_CREATION)));
+ (sysname == erts_this_node->sysname &&
+ creation == erts_this_node->creation));
}
@@ -3152,9 +3128,20 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
break;
case ENC_PATCH_FUN_SIZE:
{
- byte* size_p = (byte *) obj;
- Sint32 sz = ep - size_p;
- put_int32(sz, size_p);
+ byte* size_p = (byte *) obj;
+ Sint32 fun_sz;
+
+ if (use_iov && !ErtsInArea(size_p, ctx->cptr, ep - ctx->cptr)) {
+ ASSERT(ctx->vlen > 0);
+ fun_sz = (ep - ctx->cptr)
+ + calc_iovec_fun_size(ctx->iov, ctx->vlen-1, size_p);
+ }
+ else {
+ /* No iovec encoding or still in same iovec buffer as start
+ * of fun. Easy to calculate fun size. */
+ fun_sz = ep - size_p;
+ }
+ put_int32(fun_sz, size_p);
}
goto outer_loop;
case ENC_BIN_COPY: {
@@ -3387,8 +3374,6 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
? INTERNAL_LOCAL_SYSNAME : ref_node_name(obj));
Uint32 creation = ref_creation(obj);
- ASSERT(dflags & DFLAG_EXTENDED_REFERENCES);
-
erts_magic_ref_save_bin(obj);
*ep++ = NEWER_REFERENCE_EXT;
@@ -3662,72 +3647,23 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
data_dst = ep;
ep += j;
}
- } else if (dflags & DFLAG_BIT_BINARIES) {
- /* Bit-level binary. */
- if (dflags & DFLAG_PENDING_CONNECT) {
- ASSERT(ctx);
- j = off_heap_bytesize;
- if (!j) {
- pb_val = NULL;
- pb_term = THE_NON_VALUE;
- j = binary_size(obj);
- }
- data_dst = hopefull_bit_binary(ctx, &ep, pb_val, pb_term,
- bytes, bitoffs, bitsize, j);
- if (!data_dst)
- break; /* off heap binary referred... */
- ASSERT(!off_heap_bytesize);
- off_heap_tail = 0;
- /*
- * Trailing bits already written by hopefull_bit_binary();
- * now go copy all whole octets...
- */
- bitsize = 0;
- }
- else {
- *ep++ = BIT_BINARY_EXT;
- j = binary_size(obj);
- put_int32((j+1), ep);
- ep += 4;
- *ep++ = bitsize;
- if (off_heap_bytesize) {
- /* trailing bits */
- ep[0] = 0;
- copy_binary_to_buffer(ep, 0, bytes + j, 0, bitsize);
- off_heap_tail = 1;
- }
- else {
- ep[j] = 0; /* Zero unused bits at end of binary */
- data_dst = ep;
- ep += j + 1;
- }
- }
} else {
- /*
- * Bit-level binary, but the receiver doesn't support it.
- * Build a tuple instead.
- */
- *ep++ = SMALL_TUPLE_EXT;
- *ep++ = 2;
- *ep++ = BINARY_EXT;
- j = binary_size(obj);
- put_int32((j+1), ep);
- ep += 4;
-
+ /* Bit-level binary. */
+ *ep++ = BIT_BINARY_EXT;
+ j = binary_size(obj);
+ put_int32((j+1), ep);
+ ep += 4;
+ *ep++ = bitsize;
if (off_heap_bytesize) {
/* trailing bits */
ep[0] = 0;
copy_binary_to_buffer(ep, 0, bytes + j, 0, bitsize);
- ep[1] = SMALL_INTEGER_EXT;
- ep[2] = bitsize;
- off_heap_tail = 3;
+ off_heap_tail = 1;
}
else {
- ep[j] = 0; /* Zero unused bits at end of binary */
+ ep[j] = 0; /* Zero unused bits at end of binary */
data_dst = ep;
- ep += j+1;
- *ep++ = SMALL_INTEGER_EXT;
- *ep++ = bitsize;
+ ep += j + 1;
}
}
if (off_heap_bytesize) {
@@ -3745,63 +3681,49 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
}
}
break;
- case EXPORT_DEF:
- {
- Export* exp = *((Export **) (export_val(obj) + 1));
- if (dflags & DFLAG_PENDING_CONNECT) {
- ASSERT(ctx);
- hopefull_export(ctx, &ep, exp, dflags, off_heap);
- }
- else if ((dflags & DFLAG_EXPORT_PTR_TAG) != 0) {
- *ep++ = EXPORT_EXT;
- ep = enc_atom(acmp, exp->info.mfa.module, ep, dflags);
- ep = enc_atom(acmp, exp->info.mfa.function, ep, dflags);
- ep = enc_term(acmp, make_small(exp->info.mfa.arity),
- ep, dflags, off_heap);
- } else {
- /* Tag, arity */
- *ep++ = SMALL_TUPLE_EXT;
- put_int8(2, ep);
- ep += 1;
+ case FUN_DEF:
+ {
+ ErlFunThing* funp = (ErlFunThing *) fun_val(obj);
- /* Module name */
- ep = enc_atom(acmp, exp->info.mfa.module, ep, dflags);
+ if (is_local_fun(funp)) {
+ ErlFunEntry* fe = funp->entry.fun;
+ int ei;
- /* Function name */
- ep = enc_atom(acmp, exp->info.mfa.function, ep, dflags);
- }
- break;
- }
- break;
- case FUN_DEF:
- {
- ErlFunThing* funp = (ErlFunThing *) fun_val(obj);
- int ei;
-
- ASSERT(dflags & DFLAG_NEW_FUN_TAGS);
- *ep++ = NEW_FUN_EXT;
- WSTACK_PUSH2(s, ENC_PATCH_FUN_SIZE,
- (UWord) ep); /* Position for patching in size */
- ep += 4;
- *ep = funp->arity;
- ep += 1;
- sys_memcpy(ep, funp->fe->uniq, 16);
- ep += 16;
- put_int32(funp->fe->index, ep);
- ep += 4;
- put_int32(funp->num_free, ep);
- ep += 4;
- ep = enc_atom(acmp, funp->fe->module, ep, dflags);
- ep = enc_term(acmp, make_small(funp->fe->old_index), ep, dflags, off_heap);
- ep = enc_term(acmp, make_small(funp->fe->old_uniq), ep, dflags, off_heap);
- ep = enc_pid(acmp, funp->creator, ep, dflags);
-
- for (ei = funp->num_free-1; ei >= 0; ei--) {
- WSTACK_PUSH2(s, ENC_TERM, (UWord) funp->env[ei]);
- }
- }
- break;
- }
+ *ep++ = NEW_FUN_EXT;
+ WSTACK_PUSH2(s, ENC_PATCH_FUN_SIZE,
+ (UWord) ep); /* Position for patching in size */
+ ep += 4;
+ *ep = funp->arity;
+ ep += 1;
+ sys_memcpy(ep, fe->uniq, 16);
+ ep += 16;
+ put_int32(fe->index, ep);
+ ep += 4;
+ put_int32((Uint32)funp->num_free, ep);
+ ep += 4;
+ ep = enc_atom(acmp, fe->module, ep, dflags);
+ ep = enc_term(acmp, make_small(fe->old_index), ep, dflags, off_heap);
+ ep = enc_term(acmp, make_small(fe->old_uniq), ep, dflags, off_heap);
+ ep = enc_pid(acmp, funp->creator, ep, dflags);
+
+ for (ei = funp->num_free-1; ei >= 0; ei--) {
+ WSTACK_PUSH2(s, ENC_TERM, (UWord) funp->env[ei]);
+ }
+ } else {
+ Export *exp = funp->entry.exp;
+
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+
+ *ep++ = EXPORT_EXT;
+ ep = enc_atom(acmp, exp->info.mfa.module, ep, dflags);
+ ep = enc_atom(acmp, exp->info.mfa.function, ep, dflags);
+ ep = enc_term(acmp, make_small(exp->info.mfa.arity),
+ ep, dflags, off_heap);
+
+ }
+ }
+ break;
+ }
}
DESTROY_WSTACK(s);
if (ctx) {
@@ -3939,123 +3861,6 @@ store_in_vec(TTBEncodeContext *ctx,
}
}
-static byte *
-begin_hopefull_data(TTBEncodeContext *ctx, byte *ep)
-{
- store_in_vec(ctx, ep, NULL, THE_NON_VALUE, NULL, 0);
- ASSERT(ERTS_NO_HIX == get_uint32(ctx->hopefull_ixp));
- put_int32(ctx->vlen, ctx->hopefull_ixp);
- ctx->hopefull_ixp = ep;
- put_int32(ERTS_NO_HIX, ep);
- ep += 4;
- ctx->cptr = ep;
- return ep;
-}
-
-static byte *
-end_hopefull_data(TTBEncodeContext *ctx, byte *ep, Uint fallback_size)
-{
- Uint sz;
- store_in_vec(ctx, ep, NULL, THE_NON_VALUE, NULL, 0);
- /*
- * Reserve extra room for fallback if needed. The four
- * bytes used for hopefull index can be used for
- * fallback encoding...
- */
- sz = ep - ctx->hopefull_ixp;
- if (fallback_size > sz) {
- ep += fallback_size - sz;
- ctx->cptr = ep;
- }
- return ep;
-}
-
-static byte *
-hopefull_bit_binary(TTBEncodeContext* ctx, byte **epp, Binary *pb_val, Eterm pb_term,
- byte *bytes, byte bitoffs, byte bitsize, Uint sz)
-{
- byte *octets, *ep = *epp;
-
- ctx->hopefull_flags |= DFLAG_BIT_BINARIES;
-
- /*
- * The fallback:
- *
- * SMALL_TUPLE_EXT - 1 byte
- * 2 - 1 byte
- * BINARY_EXT - 1 byte
- * whole octet size ('sz') - 4 byte
- * whole octets - 'sz' bytes
- * trailing bits - 1 byte
- * SMALL_INTEGER_EXT - 1 byte
- * bitsize - 1 byte
- */
-
- /* bit binary prelude in one hopefull data element */
- ep = begin_hopefull_data(ctx, ep);
- *ep++ = BIT_BINARY_EXT;
- put_int32((sz+1), ep);
- ep += 4;
- *ep++ = bitsize;
- ep = end_hopefull_data(ctx, ep, 1+1+1+4);
-
- /* All whole octets... */
- if (pb_val) {
- octets = NULL;
- store_in_vec(ctx, ep, pb_val, pb_term, bytes, sz);
- }
- else {
- /* ... will be copied here afterwards */
- octets = ep;
- ep += sz;
- }
-
- /* copy trailing bits into new hopefull data element */
- ep = begin_hopefull_data(ctx, ep);
- *ep = 0; /* Clear the bit in the byte */
-
- copy_binary_to_buffer(ep, 0, bytes + sz, bitoffs, bitsize);
- ep++;
-
- ep = end_hopefull_data(ctx, ep, 1+1+1);
- *epp = ep;
-
- return octets;
-}
-
-static void
-hopefull_export(TTBEncodeContext* ctx, byte **epp, Export* exp, Uint32 dflags,
- struct erl_off_heap_header** off_heap)
-{
- Uint fallback_sz;
- byte *ep = *epp, *mod_start;
-
- /*
- * The fallback:
- *
- * SMALL_TUPLE_EXT - 1 byte
- * 2 - 1 byte
- * module atom... - M bytes
- * function atom... - F bytes
- */
-
- ctx->hopefull_flags |= DFLAG_EXPORT_PTR_TAG;
-
- ep = begin_hopefull_data(ctx, ep);
-
- *ep++ = EXPORT_EXT;
- mod_start = ep;
- ep = enc_atom(NULL, exp->info.mfa.module, ep, dflags);
- ep = enc_atom(NULL, exp->info.mfa.function, ep, dflags);
- fallback_sz = 2 + (ep - mod_start);
- ep = enc_term(NULL, make_small(exp->info.mfa.arity),
- ep, dflags, off_heap);
-
- ep = end_hopefull_data(ctx, ep, fallback_sz);
-
- *epp = ep;
-}
-
/** @brief Is it a list of bytes not longer than MAX_STRING_LEN?
* @param lenp out: string length or number of list cells traversed
* @return true/false
@@ -4086,11 +3891,14 @@ is_external_string(Eterm list, Uint* lenp)
}
-struct dec_term_hamt
+struct dec_term_map
{
- Eterm* objp; /* write result here */
- Uint size; /* nr of leafs */
- Eterm* leaf_array;
+ Eterm* objp; /* hashmap: write result here, flatmap: NULL */
+ Uint size; /* hashmap: nr of leafs, flatmap: unused */
+ union {
+ Eterm* leaf_array; /* hashmap */
+ flatmap_t* flatmap;
+ } u;
};
@@ -4105,12 +3913,11 @@ dec_term(ErtsDistExternal *edep,
B2TContext* ctx,
int ets_decode)
{
-#define PSTACK_TYPE struct dec_term_hamt
- PSTACK_DECLARE(hamt_array, 5);
+#define PSTACK_TYPE struct dec_term_map
+ PSTACK_DECLARE(map_array, 10);
int n;
ErtsAtomEncoding char_enc;
register Eterm* hp; /* Please don't take the address of hp */
- DECLARE_WSTACK(flat_maps); /* for preprocessing of small maps */
Eterm* next;
SWord reds;
#ifdef DEBUG
@@ -4196,13 +4003,9 @@ dec_term(ErtsDistExternal *edep,
return NULL;
}
}
- PSTACK_CHANGE_ALLOCATOR(hamt_array, ERTS_ALC_T_SAVED_ESTACK);
- WSTACK_CHANGE_ALLOCATOR(flat_maps, ERTS_ALC_T_SAVED_ESTACK);
- if (ctx->u.dc.hamt_array.pstart) {
- PSTACK_RESTORE(hamt_array, &ctx->u.dc.hamt_array);
- }
- if (ctx->u.dc.flat_maps.wstart) {
- WSTACK_RESTORE(flat_maps, &ctx->u.dc.flat_maps);
+ PSTACK_CHANGE_ALLOCATOR(map_array, ERTS_ALC_T_SAVED_ESTACK);
+ if (ctx->u.dc.map_array.pstart) {
+ PSTACK_RESTORE(map_array, &ctx->u.dc.map_array);
}
}
else {
@@ -4327,10 +4130,18 @@ dec_term_atom_common:
case LARGE_TUPLE_EXT:
n = get_int32(ep);
ep += 4;
+ if (n == 0) {
+ *objp = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ break;
+ }
goto tuple_loop;
case SMALL_TUPLE_EXT:
n = get_int8(ep);
ep++;
+ if (n == 0) {
+ *objp = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ break;
+ }
tuple_loop:
*objp = make_tuple(hp);
*hp++ = make_arityval(n);
@@ -4355,37 +4166,39 @@ dec_term_atom_common:
*objp = NIL;
break;
case LIST_EXT:
- n = get_int32(ep);
+ {
+ Uint32 nu = get_uint32(ep);
ep += 4;
- if (n == 0) {
+ if (nu == 0) {
next = objp;
break;
}
*objp = make_list(hp);
- hp += 2 * n;
+ hp += 2 * (Uint) nu;
objp = hp - 2;
objp[0] = (Eterm) (objp+1);
objp[1] = (Eterm) next;
next = objp;
objp -= 2;
- n--;
+ nu--;
if (ctx) {
- if (reds < n) {
+ if ((Uint) reds < nu) {
ASSERT(reds > 0);
ctx->state = B2TDecodeList;
- ctx->u.dc.remaining_n = n - reds;
- n = reds;
+ ctx->u.dc.remaining_n = nu - reds;
+ nu = reds;
}
- reds -= n;
+ reds -= nu;
}
- while (n > 0) {
+ while (nu > 0) {
objp[0] = (Eterm) next;
objp[1] = make_list(next);
next = objp;
objp -= 2;
- n--;
+ nu--;
}
break;
+ }
case STRING_EXT:
n = get_int16(ep);
ep += 2;
@@ -4665,19 +4478,21 @@ dec_term_atom_common:
}
case BINARY_EXT:
{
- n = get_int32(ep);
+ Uint32 nu = get_uint32(ep);
ep += 4;
- if ((unsigned)n <= ERL_ONHEAP_BIN_LIMIT) {
+ ASSERT(IS_BINARY_SIZE_OK(nu));
+
+ if (nu <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
- hb->thing_word = header_heap_bin(n);
- hb->size = n;
- hp += heap_bin_size(n);
- sys_memcpy(hb->data, ep, n);
+ hb->thing_word = header_heap_bin(nu);
+ hb->size = nu;
+ hp += heap_bin_size(nu);
+ sys_memcpy(hb->data, ep, nu);
*objp = make_binary(hb);
} else if (edep && edep->data && edep->data->binp &&
- n > (edep->data->binp->orig_size / 4)) {
+ nu > (edep->data->binp->orig_size / 4)) {
/* If we decode a refc binary from a distribution data
entry we know that it is a refc binary to begin with
so we just increment it and use the reference. This
@@ -4689,37 +4504,39 @@ dec_term_atom_common:
Binary* bptr = edep->data->binp;
erts_refc_inc(&bptr->intern.refc, 1);
pb->thing_word = HEADER_PROC_BIN;
- pb->size = n;
+ pb->size = nu;
pb->next = factory->off_heap->first;
factory->off_heap->first = (struct erl_off_heap_header*)pb;
pb->val = bptr;
pb->bytes = (byte*) ep;
ERTS_ASSERT((byte*)(bptr->orig_bytes) < ep &&
- ep+n <= (byte*)(bptr->orig_bytes+bptr->orig_size));
+ ep+nu <= (byte*)(bptr->orig_bytes+bptr->orig_size));
pb->flags = 0;
OH_OVERHEAD(factory->off_heap, pb->size / sizeof(Eterm));
hp += PROC_BIN_SIZE;
*objp = make_binary(pb);
} else {
- Binary* dbin = erts_bin_nrml_alloc(n);
+ Binary* dbin;
+
+ dbin = erts_bin_nrml_alloc(nu);
*objp = erts_build_proc_bin(factory->off_heap, hp, dbin);
hp += PROC_BIN_SIZE;
if (ctx) {
- int n_limit = reds * B2T_MEMCPY_FACTOR;
- if (n > n_limit) {
+ unsigned int n_limit = reds * B2T_MEMCPY_FACTOR;
+ if (nu > n_limit) {
ctx->state = B2TDecodeBinary;
- ctx->u.dc.remaining_n = n - n_limit;
+ ctx->u.dc.remaining_n = nu - n_limit;
ctx->u.dc.remaining_bytes = dbin->orig_bytes + n_limit;
- n = n_limit;
+ nu = n_limit;
reds = 0;
}
else
- reds -= n / B2T_MEMCPY_FACTOR;
+ reds -= nu / B2T_MEMCPY_FACTOR;
}
- sys_memcpy(dbin->orig_bytes, ep, n);
+ sys_memcpy(dbin->orig_bytes, ep, nu);
}
- ep += n;
+ ep += nu;
break;
}
case BIT_BINARY_EXT:
@@ -4727,51 +4544,53 @@ dec_term_atom_common:
Eterm bin;
ErlSubBin* sb;
Uint bitsize;
+ Uint32 nu = get_uint32(ep);
+
+ ASSERT(IS_BINARY_SIZE_OK(nu));
- n = get_int32(ep);
bitsize = ep[4];
- if (((bitsize==0) != (n==0)) || bitsize > 8)
+ if (((bitsize==0) != (nu==0)) || bitsize > 8)
goto error;
ep += 5;
- if ((unsigned)n <= ERL_ONHEAP_BIN_LIMIT) {
+ if (nu <= ERL_ONHEAP_BIN_LIMIT) {
ErlHeapBin* hb = (ErlHeapBin *) hp;
- hb->thing_word = header_heap_bin(n);
- hb->size = n;
- sys_memcpy(hb->data, ep, n);
+ hb->thing_word = header_heap_bin(nu);
+ hb->size = nu;
+ sys_memcpy(hb->data, ep, nu);
bin = make_binary(hb);
- hp += heap_bin_size(n);
- ep += n;
+ hp += heap_bin_size(nu);
+ ep += nu;
} else {
- Binary* dbin = erts_bin_nrml_alloc(n);
- Uint n_copy = n;
+ Binary* dbin = erts_bin_nrml_alloc(nu);
+ Uint n_copy = nu;
bin = erts_build_proc_bin(factory->off_heap, hp, dbin);
hp += PROC_BIN_SIZE;
if (ctx) {
int n_limit = reds * B2T_MEMCPY_FACTOR;
- if (n > n_limit) {
+ if (nu > n_limit) {
ctx->state = B2TDecodeBinary;
- ctx->u.dc.remaining_n = n - n_limit;
+ ctx->u.dc.remaining_n = nu - n_limit;
ctx->u.dc.remaining_bytes = dbin->orig_bytes + n_limit;
n_copy = n_limit;
reds = 0;
}
else {
- reds -= n / B2T_MEMCPY_FACTOR;
+ reds -= nu / B2T_MEMCPY_FACTOR;
}
}
sys_memcpy(dbin->orig_bytes, ep, n_copy);
ep += n_copy;
}
- if (bitsize == 8 || n == 0) {
+ if (bitsize == 8 || nu == 0) {
*objp = bin;
} else {
sb = (ErlSubBin *)hp;
sb->thing_word = HEADER_SUB_BIN;
sb->orig = bin;
- sb->size = n - 1;
+ sb->size = nu - 1;
sb->bitsize = bitsize;
sb->bitoffs = 0;
sb->offs = 0;
@@ -4781,56 +4600,63 @@ dec_term_atom_common:
}
break;
}
- case EXPORT_EXT:
- {
- Eterm mod;
- Eterm name;
- Eterm temp;
- Sint arity;
-
- if ((ep = dec_atom(edep, ep, &mod)) == NULL) {
- goto error;
- }
- if ((ep = dec_atom(edep, ep, &name)) == NULL) {
- goto error;
- }
- factory->hp = hp;
- ep = dec_term(edep, factory, ep, &temp, NULL, 0);
- hp = factory->hp;
- if (ep == NULL) {
- goto error;
- }
- if (!is_small(temp)) {
- goto error;
- }
- arity = signed_val(temp);
- if (arity < 0) {
- goto error;
- }
- if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
- if (!erts_active_export_entry(mod, name, arity))
- goto error;
+ case EXPORT_EXT:
+ {
+ ErlFunThing *funp;
+ Export *export;
+ Eterm mod;
+ Eterm name;
+ Eterm temp;
+ Sint arity;
+
+ if ((ep = dec_atom(edep, ep, &mod)) == NULL) {
+ goto error;
}
- *objp = make_export(hp);
- *hp++ = HEADER_EXPORT;
- *hp++ = (Eterm) erts_export_get_or_make_stub(mod, name, arity);
- break;
- }
- break;
+ if ((ep = dec_atom(edep, ep, &name)) == NULL) {
+ goto error;
+ }
+ factory->hp = hp;
+ ep = dec_term(edep, factory, ep, &temp, NULL, 0);
+ if (ep == NULL) {
+ goto error;
+ }
+ if (!is_small(temp)) {
+ goto error;
+ }
+ arity = signed_val(temp);
+ if (arity < 0) {
+ goto error;
+ }
+ if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
+ if (!erts_active_export_entry(mod, name, arity)) {
+ goto error;
+ }
+ }
+
+ export = erts_export_get_or_make_stub(mod, name, arity);
+ funp = erts_new_export_fun_thing(&factory->hp, export, arity);
+ hp = factory->hp;
+ *objp = make_fun(funp);
+ }
+ break;
case MAP_EXT:
{
Uint32 size,n;
Eterm *kptr,*vptr;
Eterm keys;
+ struct dec_term_map* map = PSTACK_PUSH(map_array);
size = get_int32(ep); ep += 4;
if (size <= MAP_SMALL_MAP_LIMIT) {
flatmap_t *mp;
-
- keys = make_tuple(hp);
- *hp++ = make_arityval(size);
- hp += size;
+ if (size == 0) {
+ keys = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ } else {
+ keys = make_tuple(hp);
+ *hp++ = make_arityval(size);
+ hp += size;
+ }
kptr = hp - 1;
mp = (flatmap_t*)hp;
@@ -4842,7 +4668,9 @@ dec_term_atom_common:
* vptr, last word for values
*/
- WSTACK_PUSH(flat_maps, (UWord)mp);
+ map->objp = NULL;
+ map->u.flatmap = mp;
+
mp->thing_word = MAP_HEADER_FLATMAP;
mp->size = size;
mp->keys = keys;
@@ -4857,11 +4685,10 @@ dec_term_atom_common:
}
}
else { /* Make hamt */
- struct dec_term_hamt* hamt = PSTACK_PUSH(hamt_array);
-
- hamt->objp = objp;
- hamt->size = size;
- hamt->leaf_array = hp;
+ ASSERT(objp != NULL);
+ map->objp = objp;
+ map->size = size;
+ map->u.leaf_array = hp;
for (n = size; n; n--) {
CDR(hp) = (Eterm) next;
@@ -4929,8 +4756,9 @@ dec_term_atom_common:
funp->next = factory->off_heap->first;
factory->off_heap->first = (struct erl_off_heap_header*)funp;
- funp->fe = erts_put_fun_entry2(module, old_uniq, old_index,
- uniq, index, arity);
+ funp->entry.fun = erts_put_fun_entry2(module, old_uniq,
+ old_index, uniq,
+ index, arity);
funp->arity = arity;
hp = factory->hp;
@@ -5022,11 +4850,8 @@ dec_term_atom_common:
ctx->u.dc.ep = ep;
ctx->u.dc.next = next;
ctx->u.dc.factory.hp = hp;
- if (!WSTACK_ISEMPTY(flat_maps)) {
- WSTACK_SAVE(flat_maps, &ctx->u.dc.flat_maps);
- }
- if (!PSTACK_IS_EMPTY(hamt_array)) {
- PSTACK_SAVE(hamt_array, &ctx->u.dc.hamt_array);
+ if (!PSTACK_IS_EMPTY(map_array)) {
+ PSTACK_SAVE(map_array, &ctx->u.dc.map_array);
}
ctx->reds = 0;
return NULL;
@@ -5043,36 +4868,45 @@ dec_term_atom_common:
factory->hp = hp;
/*
* From here on factory may produce (more) heap fragments
+ * and we don't use local variable 'hp' anymore.
*/
- if (!PSTACK_IS_EMPTY(hamt_array)) {
- do {
- struct dec_term_hamt* hamt = PSTACK_TOP(hamt_array);
-
- *hamt->objp = erts_hashmap_from_array(factory,
- hamt->leaf_array,
- hamt->size,
- 1);
- if (is_non_value(*hamt->objp))
- goto error_hamt;
-
- (void) PSTACK_POP(hamt_array);
- } while (!PSTACK_IS_EMPTY(hamt_array));
- }
-
- /* Iterate through all the (flat)maps and check for validity and sort keys
- * - done here for when we know it is complete.
+ /*
+ * Iterate through all the maps and for
+ * + hashmaps: hash keys and generate all inner hamt nodes
+ * + flatmaps: check for duplicate keys and sort keys if needed
+ *
+ * We do this at the end because the size of the preallocated heap is only
+ * guaranteed to include everything except hamt nodes. If unlucky with hash
+ * collisions the factory may need to create new heap fragments.
+ *
+ * As maps may include each other as keys, it's important the iteration
+ * below is done bottom-up. Sub maps are completed before potential
+ * container maps.
*/
+ if (!PSTACK_IS_EMPTY(map_array)) {
+ do {
+ struct dec_term_map* map = PSTACK_TOP(map_array);
+
+ if (map->objp) {
+ *map->objp = erts_hashmap_from_array(factory,
+ map->u.leaf_array,
+ map->size,
+ 1);
+ if (is_non_value(*map->objp))
+ goto error_map_fixup;
+ }
+ else {
+ if (!erts_validate_and_sort_flatmap(map->u.flatmap))
+ goto error_map_fixup;
+ }
- while(!WSTACK_ISEMPTY(flat_maps)) {
- next = (Eterm *)WSTACK_POP(flat_maps);
- if (!erts_validate_and_sort_flatmap((flatmap_t*)next))
- goto error;
+ (void) PSTACK_POP(map_array);
+ } while (!PSTACK_IS_EMPTY(map_array));
}
- /* Now that no more errors can occur, the stacks can be destroyed safely. */
- PSTACK_DESTROY(hamt_array);
- WSTACK_DESTROY(flat_maps);
+ /* Now that no more errors can occur, the stack can be destroyed safely. */
+ PSTACK_DESTROY(map_array);
ASSERT((Eterm*)*dbg_resultp != NULL);
@@ -5096,15 +4930,13 @@ error:
}
else ASSERT(!factory->hp || factory->hp == hp);
-error_hamt:
+error_map_fixup:
erts_factory_undo(factory);
- PSTACK_DESTROY(hamt_array);
+ PSTACK_DESTROY(map_array);
if (ctx) {
ctx->state = B2TDecodeFail;
ctx->reds = reds;
}
- WSTACK_DESTROY(flat_maps);
-
return NULL;
}
@@ -5233,7 +5065,6 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
break;
case EXTERNAL_REF_DEF:
case REF_DEF:
- ASSERT(dflags & DFLAG_EXTENDED_REFERENCES);
i = ref_no_numbers(obj);
result += (1 + 2 + encode_size_struct2(acmp, ref_node_name(obj), dflags) +
4 + 4*i);
@@ -5389,21 +5220,12 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
+ 4 /* size */);
trailing_result = 0;
}
- else if (dflags & DFLAG_BIT_BINARIES) {
+ else {
result += (1 /* BIT_BINARY_EXT */
+ 4 /* size */
+ 1 /* trailing bitsize */);
trailing_result = 1 /* trailing bits */;
}
- else {
- /* sigh... */
- result += (1 /* SMALL_TUPLE_EXT */
- + 1 /* 2 tuple size */
- + 1 /* BINARY_EXT */
- + 4 /* binary size */);
- trailing_result = (1 /* SMALL_INTEGER_EXT */
- + 1 /* bitsize */);
- }
csz = result - ctx->last_result;
ctx->last_result = result;
result += trailing_result;
@@ -5414,110 +5236,54 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
/* potentially multiple elements for binary */
vlen += bin_size/MAX_SYSIOVEC_IOVLEN;
ctx->extra_size += bin_size;
-
- if (dflags & DFLAG_PENDING_CONNECT) {
- ASSERT(dflags & DFLAG_BIT_BINARIES);
- ASSERT(ctx);
- vlen += 2; /* for hopefull prolog and epilog */
- result += (4 /* for hopefull prolog (see below) */
- + 4); /* for hopefull epilog (see below) */
- ctx->last_result = result;
- }
break;
}
}
}
if (bitsize == 0) {
- result += (1 /* BIT_BINARY_EXT */
- + 4 /* size */
- + bin_size);
- }
- else if (dflags & DFLAG_PENDING_CONNECT) {
- /* This is the odd case when we have an un-aligned bit-string
- during a pending connect. */
- Uint csz;
- ASSERT(dflags & DFLAG_BIT_BINARIES);
- ASSERT(ctx);
- csz = result - ctx->last_result;
- /* potentially multiple elements leading up to binary */
- vlen += (csz + MAX_SYSIOVEC_IOVLEN - 1)/MAX_SYSIOVEC_IOVLEN;
-
- vlen++; /* hopefull prolog */
- /*
- * Size for hopefull prolog is max of
- * - fallback: 1 + 1 + 1 + 4
- * - hopfull index + bit binary prolog: 4 + 1 + 4 + 1
- */
- result += 4 + 1 + 4 + 1;
- /* potentially multiple elements for binary */
- vlen += bin_size/MAX_SYSIOVEC_IOVLEN + 1;
- result += bin_size;
- vlen++; /* hopefull epiolog */
- /*
- * Size for hopefull epiolog is max of
- * - fallback: 1 + 1 + 1
- * - hopfull index + bit binary epilog: 4 + 1
- */
- result += 4 + 1;
- ctx->last_result = result;
- }
- else if (dflags & DFLAG_BIT_BINARIES) {
- result += 1 + 4 + 1 + bin_size + 1;
+ result += (1 /* BINARY_EXT */
+ + 4); /* size */
}
else {
- /* Sigh... */
- result += 1 + 1 + 1 + 4 + bin_size + 1 + 1 + 1;
+ result += (1 /* BIT_BINARY_EXT */
+ + 4 /* size */
+ + 1 /* bits */
+ + 1); /* trailing bits */
}
+ result += bin_size;
break;
}
- case FUN_DEF:
- {
- ErlFunThing* funp = (ErlFunThing *) fun_val(obj);
-
- ASSERT(dflags & DFLAG_NEW_FUN_TAGS);
- result += 20+1+1+4; /* New ID + Tag */
- result += 4; /* Length field (number of free variables */
- result += encode_size_struct2(acmp, funp->creator, dflags);
- result += encode_size_struct2(acmp, funp->fe->module, dflags);
- result += 2 * (1+4); /* Index, Uniq */
- if (funp->num_free > 1) {
- WSTACK_PUSH2(s, (UWord) (funp->env + 1),
- (UWord) TERM_ARRAY_OP(funp->num_free-1));
- }
- if (funp->num_free != 0) {
- obj = funp->env[0];
- continue; /* big loop */
- }
- break;
- }
+ case FUN_DEF:
+ {
+ ErlFunThing *funp = (ErlFunThing *) fun_val(obj);
+
+ if (is_local_fun(funp)) {
+ result += 20+1+1+4; /* New ID + Tag */
+ result += 4; /* Length field (number of free variables */
+ result += encode_size_struct2(acmp, funp->creator, dflags);
+ result += encode_size_struct2(acmp, funp->entry.fun->module, dflags);
+ result += 2 * (1+4); /* Index, Uniq */
+ if (funp->num_free > 1) {
+ WSTACK_PUSH2(s, (UWord) (funp->env + 1),
+ (UWord) TERM_ARRAY_OP(funp->num_free-1));
+ }
+ if (funp->num_free != 0) {
+ obj = funp->env[0];
+ continue; /* big loop */
+ }
+ } else {
+ Export* ep = funp->entry.exp;
- case EXPORT_DEF:
- {
- Export* ep = *((Export **) (export_val(obj) + 1));
- Uint tmp_result = result;
- result += 1;
- result += encode_size_struct2(acmp, ep->info.mfa.module, dflags);
- result += encode_size_struct2(acmp, ep->info.mfa.function, dflags);
- result += encode_size_struct2(acmp, make_small(ep->info.mfa.arity), dflags);
- if (dflags & DFLAG_PENDING_CONNECT) {
- Uint csz;
- ASSERT(ctx);
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
- /*
- * Fallback is 1 + 1 + Module size + Function size, that is,
- * the hopefull index + hopefull encoding is larger...
- */
- ASSERT(dflags & DFLAG_EXPORT_PTR_TAG);
- csz = tmp_result - ctx->last_result;
- /* potentially multiple elements leading up to hopefull entry */
- vlen += (csz/MAX_SYSIOVEC_IOVLEN + 1
- + 1); /* hopefull entry */
- result += 4; /* hopefull index */
- ctx->last_result = result;
+ result += 1;
+ result += encode_size_struct2(acmp, ep->info.mfa.module, dflags);
+ result += encode_size_struct2(acmp, ep->info.mfa.function, dflags);
+ result += encode_size_struct2(acmp, make_small(ep->info.mfa.arity), dflags);
}
- }
- break;
+ break;
+ }
default:
erts_exit(ERTS_ERROR_EXIT,"Internal data structure error (in encode_size_struct_int) %x\n",
@@ -5540,7 +5306,6 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
obj = CAR(cons);
}
break;
-
case TERM_ARRAY_OP(1):
obj = *(Eterm*)WSTACK_POP(s);
break;
@@ -5577,11 +5342,21 @@ static Sint
decoded_size(const byte *ep, const byte* endp, int internal_tags, B2TContext* ctx)
{
Sint heap_size;
- int terms;
int atom_extra_skip;
Uint n;
SWord reds;
+ /* Keep track of the current number of sub terms remaining to be decoded.
+ *
+ * We limit the number of sub terms to 2^32-1, even on 64-bit
+ * machines, because a term that has many sub-terms must be truly
+ * ginormous and is proably a mistake.
+ *
+ * This means that a map with 2^31 or more elements cannot be decoded,
+ * even on a 64-bit machine.
+ */
+ Uint32 terms;
+
if (ctx) {
reds = ctx->reds;
if (ctx->u.sc.ep) {
@@ -5620,9 +5395,11 @@ init_done:
if ((sz) > endp-ep) { goto error; } \
} while (0)
+/* Increment the number of terms that remain to decode
+ * and check for the term counter wrapping around. */
#define ADDTERMS(n) \
do { \
- int before = terms; \
+ Uint32 before = terms; \
terms += (n); \
if (terms < before) goto error; \
} while (0)
@@ -5707,7 +5484,7 @@ init_done:
case_PID:
/* In case it is an external pid */
heap_size += EXTERNAL_PID_HEAP_SIZE;
- terms++;
+ ADDTERMS(1);
break;
case V4_PORT_EXT:
atom_extra_skip = 12;
@@ -5720,7 +5497,7 @@ init_done:
case_PORT:
/* In case it is an external port */
heap_size += EXTERNAL_PORT_HEAP_SIZE;
- terms++;
+ ADDTERMS(1);
break;
case NEWER_REFERENCE_EXT:
atom_extra_skip = 4;
@@ -5745,7 +5522,7 @@ init_done:
#else
heap_size += EXTERNAL_THING_HEAD_SIZE + id_words;
#endif
- terms++;
+ ADDTERMS(1);
break;
}
case REFERENCE_EXT:
@@ -5760,20 +5537,23 @@ init_done:
CHKSIZE(4);
n = get_uint32(ep);
ep += 4;
- ADDTERMS(n);
- terms++;
+ CHKSIZE(n); /* Fail faster if the binary is too short. */
+ /* Count terms in two operations to avoid overflow. */
+ ADDTERMS(n);
+ ADDTERMS(1);
heap_size += 2 * n;
break;
case SMALL_TUPLE_EXT:
CHKSIZE(1);
n = *ep++;
- terms += n;
+ ADDTERMS(n);
heap_size += n + 1;
break;
case LARGE_TUPLE_EXT:
CHKSIZE(4);
n = get_uint32(ep);
ep += 4;
+ CHKSIZE(n); /* Fail faster if the binary is too short. */
ADDTERMS(n);
heap_size += n + 1;
break;
@@ -5781,19 +5561,25 @@ init_done:
CHKSIZE(4);
n = get_uint32(ep);
ep += 4;
- ADDTERMS(2*n);
if (n <= MAP_SMALL_MAP_LIMIT) {
heap_size += 3 + n + 1 + n;
- } else {
-#if !defined(ARCH_64)
- if ((n >> 30) != 0) {
- /* Can't possibly fit in memory. */
- goto error;
- }
+#if defined(ARCH_64)
+ } else if ((n >> 31) != 0) {
+ /* Avoid overflow by limiting the number of elements in
+ * a map to 2^31-1 (about 2 billions). */
+ goto error;
+#else
+ } else if ((n >> 30) != 0) {
+ /* Can't possibly fit in memory on 32-bit machine. */
+ goto error;
#endif
- CHKSIZE(2*n); /* Conservative size check */
+ } else {
+ CHKSIZE(2*(Uint)n); /* Fail faster if the binary is too short. */
heap_size += HASHMAP_ESTIMATED_HEAP_SIZE(n);
}
+ /* Count terms in two operations to avoid overflow. */
+ ADDTERMS(n);
+ ADDTERMS(n);
break;
case STRING_EXT:
CHKSIZE(2);
@@ -5812,6 +5598,10 @@ init_done:
case BINARY_EXT:
CHKSIZE(4);
n = get_uint32(ep);
+#if defined(ARCH_32)
+ if (!IS_BINARY_SIZE_OK(n))
+ goto error;
+#endif
SKIP2(n, 4);
if (n <= ERL_ONHEAP_BIN_LIMIT) {
heap_size += heap_bin_size(n);
@@ -5823,6 +5613,10 @@ init_done:
{
CHKSIZE(5);
n = get_uint32(ep);
+#if defined(ARCH_32)
+ if (!IS_BINARY_SIZE_OK(n))
+ goto error;
+#endif
SKIP2(n, 5);
if (n <= ERL_ONHEAP_BIN_LIMIT) {
heap_size += heap_bin_size(n) + ERL_SUB_BIN_SIZE;
@@ -5832,17 +5626,18 @@ init_done:
}
break;
case EXPORT_EXT:
- terms += 3;
- heap_size += 2;
+ ADDTERMS(3);
+ heap_size += ERL_FUN_SIZE;
break;
case NEW_FUN_EXT:
{
unsigned num_free;
- Uint total_size;
CHKSIZE(1+16+4+4);
- total_size = get_uint32(ep);
- CHKSIZE(total_size);
+ /* Ignore faulty Size field as we have bugs since OTP 23.0
+ * that can encode it too large if fun contains EXPORT_EXT or
+ * BIT_BINARY_EXT hopefully encoded for pending connection.
+ */
ep += 1+16+4+4;
CHKSIZE(4);
num_free = get_uint32(ep);
@@ -5850,7 +5645,7 @@ init_done:
if (num_free > MAX_ARG) {
goto error;
}
- terms += 4 + num_free;
+ ADDTERMS(4 + num_free);
heap_size += ERL_FUN_SIZE + num_free;
break;
}
@@ -5888,7 +5683,7 @@ init_done:
}
terms--;
- if (ctx && --reds <= 0 && terms > 0) {
+ if (ctx && --reds <= 0 && terms != 0) {
ctx->u.sc.heap_size = heap_size;
ctx->u.sc.terms = terms;
ctx->u.sc.ep = ep;
@@ -5896,9 +5691,8 @@ init_done:
ctx->reds = 0;
return 0;
}
- }while (terms > 0);
+ } while (terms != 0);
- /* 'terms' may be non-zero if it has wrapped around */
if (terms == 0) {
if (ctx) {
ctx->state = B2TDecodeInit;
@@ -5977,6 +5771,29 @@ transcode_decode_state_destroy(ErtsTranscodeDecodeState *state)
erts_free(ERTS_ALC_T_TMP, state->hp);
}
+static Uint32
+calc_iovec_fun_size(SysIOVec* iov, Uint32 fun_high_ix, byte* size_p)
+{
+ Sint32 ix;
+ Uint32 fun_size = 0;
+
+ ASSERT(size_p[-1] == NEW_FUN_EXT);
+
+ /*
+ * Search backwards for start of fun while adding up its total byte size.
+ */
+ for (ix = fun_high_ix; ix >= 0; ix--) {
+ fun_size += iov[ix].iov_len;
+
+ if (ErtsInArea(size_p, iov[ix].iov_base, iov[ix].iov_len)) {
+ fun_size -= (size_p - (byte*)iov[ix].iov_base);
+ break;
+ }
+ }
+ ERTS_ASSERT(ix >= 0);
+ return fun_size;
+}
+
static
Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
DistEntry* dep,
@@ -5986,10 +5803,8 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
ErlIOVec* eiov = ob->eiov;
SysIOVec* iov = eiov->iov;
byte *hdr;
- Uint64 hopefull_flags;
- Uint32 hopefull_ix, payload_ix;
+ Uint32 payload_ix;
Sint start_r, r;
- Uint new_len;
byte *ep;
if (reds < 0)
@@ -6055,11 +5870,9 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
return reds;
}
+ /* Currently, the hopefull flags and IX are not used. */
hdr++;
- hopefull_flags = get_int64(hdr);
-
hdr += 8;
- hopefull_ix = get_int32(hdr);
if ((~dflags & DFLAG_SPAWN)
&& ep[0] == SMALL_TUPLE_EXT
@@ -6222,8 +6035,7 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
#endif
/* Send unlink ack to local sender... */
- erts_proc_sig_send_dist_unlink_ack(NULL, dep,
- dep->connection_id,
+ erts_proc_sig_send_dist_unlink_ack(dep, dep->connection_id,
remote, local, id);
transcode_decode_state_destroy(&tds);
@@ -6237,167 +6049,6 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
start_r = r = reds*ERTS_TRANSCODE_REDS_FACT;
- if (~dflags & hopefull_flags) {
-
- while (hopefull_ix != ERTS_NO_HIX) {
- Uint32 new_hopefull_ix;
-
- if (r <= 0) { /* yield... */
- /* save current hopefull_ix... */
- ep = (byte *) iov[1].iov_base;
- ep += 5;
- put_int32(hopefull_ix, ep);
- return -1;
- }
-
- /* Read next hopefull index */
- ep = (byte *) iov[hopefull_ix].iov_base;
- ep -= 4;
- new_hopefull_ix = get_int32(ep);
- ASSERT(new_hopefull_ix == ERTS_NO_HIX
- || (hopefull_ix < new_hopefull_ix
- && new_hopefull_ix < eiov->vsize));
-
- ep = (byte *) iov[hopefull_ix].iov_base;
- switch (*ep) {
-
- case EXPORT_EXT: {
- byte *start_ep, *end_ep;
- Eterm module, function;
- if (!(hopefull_flags & DFLAG_EXPORT_PTR_TAG))
- break;
- /* Read original encoding... */
- ep++;
- start_ep = ep;
- ep = (byte*)dec_atom(NULL, ep, &module);
- ASSERT(ep && is_atom(module));
- ep = (byte*)dec_atom(NULL, ep, &function);
- ASSERT(ep && is_atom(function));
- end_ep = ep;
- ASSERT(*ep == SMALL_INTEGER_EXT
- || *ep == INTEGER_EXT
- || *ep == SMALL_BIG_EXT
- || *ep == LARGE_BIG_EXT);
-
- /*
- * module and function atoms are encoded
- * between start_ep and end_ep. Prepend a
- * 2-tuple tag before the atoms and
- * remove arity at end.
- */
-
- /* write fallback */
-
- ep = start_ep;
- ep--;
- put_int8(2, ep);
- ep--;
- *ep = SMALL_TUPLE_EXT;
-
- iov[hopefull_ix].iov_base = ep;
-
- /* Update iov sizes... */
- new_len = end_ep - ep;
- eiov->size -= iov[hopefull_ix].iov_len;
- eiov->size += new_len;
- iov[hopefull_ix].iov_len = new_len;
- r--;
- break;
- }
-
- case BIT_BINARY_EXT: {
- Uint bin_sz;
- byte bitsize, epilog_byte;
- ASSERT(hopefull_ix != ERTS_NO_HIX);
- if (!(hopefull_flags & DFLAG_BIT_BINARIES)) {
- /* skip to epilog... */
- hopefull_ix = new_hopefull_ix;
- ep = (byte *) iov[hopefull_ix].iov_base;
- ep -= 4;
- new_hopefull_ix = get_int32(ep);
- ASSERT(new_hopefull_ix == ERTS_NO_HIX
- || (hopefull_ix < new_hopefull_ix
- && new_hopefull_ix < eiov->vsize));
- break;
- }
-
- /* read original encoded prolog... */
- ep++;
- bin_sz = get_uint32(ep);
- ep += 4;
- bitsize = *ep++;
-
- /* write fallback prolog... */
- iov[hopefull_ix].iov_base = &((byte*)iov[hopefull_ix].iov_base)[-4];
- ep = (byte *) iov[hopefull_ix].iov_base;
-
- *ep++ = SMALL_TUPLE_EXT;
- *ep++ = 2;
- *ep++ = BINARY_EXT;
- put_int32(bin_sz, ep);
- ep += 4;
-
- /* Update iov sizes... */
- new_len = ep - (byte *) iov[hopefull_ix].iov_base;
- eiov->size -= iov[hopefull_ix].iov_len;
- eiov->size += new_len;
- iov[hopefull_ix].iov_len = new_len;
- r--;
-#ifdef DEBUG
- /*
- * The binary data between the prolog and the
- * epilog should be of size 'bin_sz - 1' and
- * exists in the iov elements between prolog
- * and epilog...
- */
- {
- Uint ix, debug_bin_sz = 0;
- for (ix = hopefull_ix+1; ix < new_hopefull_ix; ix++)
- debug_bin_sz += iov[ix].iov_len;
- ASSERT(debug_bin_sz == bin_sz - 1);
- }
-#endif
- /* jump to epilog... */
- hopefull_ix = new_hopefull_ix;
- ep = (byte *) iov[hopefull_ix].iov_base;
-
- /* read original encoded epilog... */
- epilog_byte = *ep;
-
- ASSERT(1 == iov[hopefull_ix].iov_len);
-
- iov[hopefull_ix].iov_base = &((byte*)iov[hopefull_ix].iov_base)[-4];
- ep = (byte *) iov[hopefull_ix].iov_base;
- new_hopefull_ix = get_int32(ep);
- ASSERT(new_hopefull_ix == ERTS_NO_HIX
- || (hopefull_ix < new_hopefull_ix
- && new_hopefull_ix < eiov->vsize));
-
- /* write fallback epilog... */
-
- *ep++ = epilog_byte;
- *ep++ = SMALL_INTEGER_EXT;
- *ep++ = bitsize;
-
- /* Update iov sizes... */
- new_len = ep - (byte *) iov[hopefull_ix].iov_base;
- eiov->size -= iov[hopefull_ix].iov_len;
- eiov->size += new_len;
- iov[hopefull_ix].iov_len = new_len;
- r--;
- break;
- }
-
- default:
- ERTS_INTERNAL_ERROR("Unexpected external tag");
- break;
- }
-
- hopefull_ix = new_hopefull_ix;
- r--;
- }
- }
-
/*
* Replace hopefull data header with actual header...
*/
diff --git a/erts/emulator/beam/generators.tab b/erts/emulator/beam/generators.tab
index 546b3b18b2..eec78315a2 100644
--- a/erts/emulator/beam/generators.tab
+++ b/erts/emulator/beam/generators.tab
@@ -51,31 +51,6 @@ NativeEndian(flags) {
#endif
}
-gen_bs_save_restore(reg, index, instr) {
- BeamOp* op;
-
- $NewBeamOp(S, op);
- $BeamOpNameArity(op, $instr, 2);
- op->a[0] = $reg;
- op->a[1] = $index;
- if (Index.type == TAG_u) {
- op->a[1].val = $index.val+1;
- } else if ($index.type == TAG_a && $index.val == am_start) {
- op->a[1].type = TAG_u;
- op->a[1].val = 0;
- }
- return op;
-}
-
-gen.bs_save(Reg, Index) {
- $gen_bs_save_restore(Reg, Index, i_bs_save2);
-}
-
-gen.bs_restore(Reg, Index) {
- $gen_bs_save_restore(Reg, Index, i_bs_restore2);
-}
-
-
// Generate an instruction to fetch a float from a binary.
gen.get_float2(Fail, Ms, Live, Size, Unit, Flags, Dst) {
BeamOp* op;
@@ -376,6 +351,7 @@ gen.make_fun2(idx) {
int i;
BeamFile_LambdaEntry *entry = &S->beam.lambdas.entries[idx.val];
unsigned num_free = entry->num_free;
+ unsigned arity = entry->arity;
$NewBeamOp(S, th);
@@ -386,17 +362,19 @@ gen.make_fun2(idx) {
th->a[1].val = num_free;
th->next = op;
- $BeamOpNameArity(op, i_make_fun3, 3);
- $BeamOpArity(op, 3 + num_free);
+ $BeamOpNameArity(op, i_make_fun3, 4);
+ $BeamOpArity(op, 4 + num_free);
op->a[0].type = TAG_u;
op->a[0].val = idx.val;
op->a[1].type = TAG_x;
op->a[1].val = 0;
op->a[2].type = TAG_u;
- op->a[2].val = num_free;
+ op->a[2].val = arity - num_free;
+ op->a[3].type = TAG_u;
+ op->a[3].val = num_free;
for (i = 0; i < num_free; i++) {
- op->a[i+3].type = TAG_x;
- op->a[i+3].val = i;
+ op->a[i+4].type = TAG_x;
+ op->a[i+4].val = i;
}
return th;
}
@@ -412,15 +390,17 @@ gen.make_fun3(idx, Dst, NumFree, Env) {
if (NumFree.val == entry->num_free) {
int i;
- $BeamOpNameArity(op, i_make_fun3, 3);
- $BeamOpArity(op, 3 + NumFree.val);
+ $BeamOpNameArity(op, i_make_fun3, 4);
+ $BeamOpArity(op, 4 + NumFree.val);
op->a[0].type = TAG_u;
op->a[0].val = idx.val;
op->a[1] = Dst;
op->a[2].type = TAG_u;
- op->a[2].val = entry->num_free;
+ op->a[2].val = entry->arity - entry->num_free;
+ op->a[3].type = TAG_u;
+ op->a[3].val = entry->num_free;
for (i = 0; i < NumFree.val; i++) {
- op->a[i+3] = Env[i];
+ op->a[i+4] = Env[i];
}
return op;
}
@@ -431,46 +411,6 @@ gen.make_fun3(idx, Dst, NumFree, Env) {
return op;
}
-gen.tuple_append_put5(Arity, Dst, Puts, S1, S2, S3, S4, S5) {
- BeamOp* op;
- int arity = Arity.val; /* Arity of tuple, not the instruction */
- int i;
-
- $NewBeamOp(S, op);
- $BeamOpNameArity(op, i_put_tuple, 2);
- $BeamOpArity(op, arity+2+5);
- op->a[0] = Dst;
- op->a[1].type = TAG_u;
- op->a[1].val = arity + 5;
- for (i = 0; i < arity; i++) {
- op->a[i+2] = Puts[i];
- }
- op->a[arity+2] = S1;
- op->a[arity+3] = S2;
- op->a[arity+4] = S3;
- op->a[arity+5] = S4;
- op->a[arity+6] = S5;
- return op;
-}
-
-gen.tuple_append_put(Arity, Dst, Puts, Src) {
- BeamOp* op;
- int arity = Arity.val; /* Arity of tuple, not the instruction */
- int i;
-
- $NewBeamOp(S, op);
- $BeamOpNameArity(op, i_put_tuple, 2);
- $BeamOpArity(op, arity+2+1);
- op->a[0] = Dst;
- op->a[1].type = TAG_u;
- op->a[1].val = arity + 1;
- for (i = 0; i < arity; i++) {
- op->a[i+2] = Puts[i];
- }
- op->a[arity+2] = Src;
- return op;
-}
-
// Generate an instruction for get/1.
gen.get(Src, Dst) {
BeamOp* op;
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index feab1ba53e..8c4dd90966 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -931,13 +931,6 @@ Eterm erts_bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail);
void erts_bif_info_init(void);
/* bif.c */
-
-void erts_queue_monitor_message(Process *,
- ErtsProcLocks*,
- Eterm,
- Eterm,
- Eterm,
- Eterm);
void erts_init_trap_export(Export* ep, Eterm m, Eterm f, Uint a,
Eterm (*bif)(Process*, Eterm*, ErtsCodePtr));
void erts_init_bif(void);
@@ -957,6 +950,7 @@ Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
Eterm erts_check_process_code(Process *c_p, Eterm module, int *redsp, int fcalls);
#define ERTS_CLA_SCAN_WORDS_PER_RED 512
+int erts_check_copy_literals_gc_need_max_reds(Process *c_p);
int erts_check_copy_literals_gc_need(Process *c_p, int *redsp,
char *literals, Uint lit_bsize);
Eterm erts_copy_literals_gc(Process *c_p, int *redsp, int fcalls);
@@ -976,7 +970,7 @@ typedef struct ErtsLiteralArea_ {
void erts_queue_release_literals(Process *c_p, ErtsLiteralArea* literals);
#define ERTS_LITERAL_AREA_ALLOC_SIZE(N) \
- (sizeof(ErtsLiteralArea) + sizeof(Eterm)*((N) - 1))
+ (sizeof(ErtsLiteralArea) + sizeof(Eterm)*(N - 1))
#define ERTS_LITERAL_AREA_SIZE(AP) \
(ERTS_LITERAL_AREA_ALLOC_SIZE((AP)->end - (AP)->start))
@@ -1216,6 +1210,7 @@ void print_pass_through(int, byte*, int);
int catchlevel(Process*);
void init_emulator(void);
void process_main(ErtsSchedulerData *);
+void erts_prepare_bs_construct_fail_info(Process* c_p, const BeamInstr* p, Eterm reason, Eterm Info, Eterm value);
void erts_dirty_process_main(ErtsSchedulerData *);
Eterm build_stacktrace(Process* c_p, Eterm exc);
Eterm expand_error_value(Process* c_p, Uint freason, Eterm Value);
@@ -1307,14 +1302,15 @@ typedef struct {
ErlDrvEntry* de;
int taint;
} ErtsStaticDriver;
-typedef void *(*ErtsStaticNifInitFPtr)(void);
-typedef struct ErtsStaticNifEntry_ {
- const char *nif_name;
- ErtsStaticNifInitFPtr nif_init;
- int taint;
-} ErtsStaticNifEntry;
-ErtsStaticNifEntry* erts_static_nif_get_nif_init(const char *name, int len);
-int erts_is_static_nif(void *handle);
+typedef void* ErtsStaticNifInitF(void);
+typedef struct {
+ ErtsStaticNifInitF* const nif_init;
+ const int taint;
+
+ Eterm mod_atom;
+ ErlNifEntry* entry;
+} ErtsStaticNif;
+extern ErtsStaticNif erts_static_nif_tab[];
void erts_init_static_drivers(void);
/* erl_drv_thread.c */
@@ -1443,6 +1439,7 @@ void erts_init_bif_binary(void);
Sint erts_binary_set_loop_limit(Sint limit);
/* erl_bif_persistent.c */
+Eterm erts_persistent_term_get(Eterm key);
void erts_init_bif_persistent_term(void);
void erts_init_persistent_dumping(void);
extern ErtsLiteralArea** erts_persistent_areas;
@@ -1471,10 +1468,10 @@ Sint erts_unicode_set_loop_limit(Sint limit);
void erts_native_filename_put(Eterm ioterm, int encoding, byte *p) ;
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);
-int erts_analyze_utf8_x(byte *source, Uint size,
- byte **err_pos, Uint *num_chars, int *left,
+int erts_analyze_utf8(const byte *source, Uint size,
+ const byte **err_pos, Uint *num_chars, int *left);
+int erts_analyze_utf8_x(const byte *source, Uint size,
+ const byte **err_pos, Uint *num_chars, int *left,
Sint *num_latin1_chars, Uint max_chars);
char *erts_convert_filename_to_native(Eterm name, char *statbuf,
size_t statbuf_size,
@@ -1495,6 +1492,11 @@ char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
Eterm erts_convert_native_to_filename(Process *p, size_t size, byte *bytes);
Eterm erts_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz, Uint left,
Uint *num_built, Uint *num_eaten, Eterm tail);
+Eterm
+erts_make_list_from_utf8_buf(Eterm **hpp, Uint num,
+ const byte *bytes, Uint sz,
+ Uint *num_built, Uint *num_eaten,
+ Eterm tail);
int erts_utf8_to_latin1(byte* dest, const byte* source, int slen);
#define ERTS_UTF8_OK 0
#define ERTS_UTF8_INCOMPLETE 1
@@ -1712,8 +1714,10 @@ int erts_beam_jump_table(void);
ERTS_GLB_INLINE void dtrace_pid_str(Eterm pid, char *process_buf);
ERTS_GLB_INLINE void dtrace_proc_str(Process *process, char *process_buf);
ERTS_GLB_INLINE void dtrace_port_str(Port *port, char *port_buf);
-ERTS_GLB_INLINE void dtrace_fun_decode(Process *process, ErtsCodeMFA *mfa,
- char *process_buf, char *mfa_buf);
+ERTS_GLB_INLINE void dtrace_fun_decode(Process *process,
+ const ErtsCodeMFA *mfa,
+ char *process_buf,
+ char *mfa_buf);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -1746,7 +1750,7 @@ dtrace_port_str(Port *port, char *port_buf)
}
ERTS_GLB_INLINE void
-dtrace_fun_decode(Process *process, ErtsCodeMFA *mfa,
+dtrace_fun_decode(Process *process, const ErtsCodeMFA *mfa,
char *process_buf, char *mfa_buf)
{
if (process_buf) {
diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c
index 777a2cda5d..434ba25098 100644
--- a/erts/emulator/beam/hash.c
+++ b/erts/emulator/beam/hash.c
@@ -110,7 +110,7 @@ static ERTS_INLINE void set_thresholds(Hash* h)
if (h->shift < h->max_shift)
h->shrink_threshold = hash_get_slots(h) / 5; /* shrink at 20% load */
else
- h->shrink_threshold = -1; /* never shrink below inital size */
+ h->shrink_threshold = -1; /* never shrink below initial size */
}
/*
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 09235158c1..2ef5bc4d01 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@
#include "erl_time.h"
#include "erl_io_queue.h"
#include "erl_proc_sig_queue.h"
+#include "erl_global_literals.h"
extern ErlDrvEntry fd_driver_entry;
extern ErlDrvEntry vanilla_driver_entry;
@@ -569,7 +570,12 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */
if (!(opts->spawn_type & ERTS_SPAWN_EXECUTABLE)) {
/* No spawn driver default */
driver = NULL;
- }
+ } else {
+#ifdef __IOS__
+ erts_rwmtx_runlock(&erts_driver_list_lock);
+ ERTS_OPEN_DRIVER_RET(NULL, -3, BADARG);
+#endif
+ }
if (opts->spawn_type != ERTS_SPAWN_EXECUTABLE) {
@@ -813,7 +819,8 @@ driver_create_port(ErlDrvPort creator_port_ix, /* Creating port */
port_lnk = erts_link_internal_create(ERTS_LNK_TYPE_PORT, pid);
erts_link_tree_insert(&ERTS_P_LINKS(port), port_lnk);
proc_lnk = erts_link_internal_create(ERTS_LNK_TYPE_PORT, port->common.id);
- if (!erts_proc_sig_send_link(NULL, pid, proc_lnk)) {
+ if (!erts_proc_sig_send_link(&port->common, port->common.id,
+ pid, proc_lnk)) {
erts_link_tree_delete(&ERTS_P_LINKS(port), port_lnk);
erts_link_internal_release(proc_lnk);
erts_link_internal_release(port_lnk);
@@ -1170,7 +1177,7 @@ erts_schedule_proc2port_signal(Process *c_p,
* callers message queue to the end of the queue.
*
* NOTE: It is of vital importance that the caller
- * immediately do a receive unconditionaly
+ * immediately do a receive unconditionally
* waiting for the message with the reference;
* otherwise, next receive will *not* work
* as expected!
@@ -1224,7 +1231,7 @@ send_badsig(Port *prt) {
ERTS_CHK_NO_PROC_LOCKS;
ERTS_LC_ASSERT(erts_get_scheduler_id());
ASSERT(is_internal_pid(connected));
- erts_proc_sig_send_exit(NULL, prt->common.id, connected,
+ erts_proc_sig_send_exit(&prt->common, prt->common.id, connected,
am_badsig, NIL, 0);
} /* send_badsig */
@@ -1637,7 +1644,7 @@ erts_port_output_async(Port *prt, Eterm from, Eterm list)
ErlDrvSizeT ERTS_DECLARE_DUMMY(r);
/*
- * Apperently there exist code that write 1 byte to
+ * Apparently there exist code that write 1 byte to
* much in buffer. Where it resides I don't know, but
* we can live with one byte extra allocated...
*/
@@ -1971,7 +1978,7 @@ erts_port_output(Process *c_p,
ErlDrvSizeT r;
/*
- * Apperently there exist code that write 1 byte to
+ * Apparently there exist code that write 1 byte to
* much in buffer. Where it resides I don't know, but
* we can live with one byte extra allocated...
*/
@@ -2344,7 +2351,8 @@ set_port_connected(int bang_op,
if (created) {
ErtsLink *olnk = erts_link_internal_create(ERTS_LNK_TYPE_PORT,
prt->common.id);
- if (!erts_proc_sig_send_link(NULL, connect, olnk)) {
+ if (!erts_proc_sig_send_link(&prt->common, prt->common.id,
+ connect, olnk)) {
erts_link_tree_delete(&ERTS_P_LINKS(prt), lnk);
erts_link_internal_release(lnk);
erts_link_internal_release(olnk);
@@ -2465,39 +2473,47 @@ erts_port_connect(Process *c_p,
}
static void
-port_unlink_failure(Eterm port_id, ErtsSigUnlinkOp *sulnk)
+port_unlink_failure(Port *prt, Eterm port_id, ErtsSigUnlinkOp *sulnk)
{
- erts_proc_sig_send_unlink_ack(NULL, port_id, sulnk);
+ erts_proc_sig_send_unlink_ack(prt ? &prt->common : NULL, port_id, sulnk);
}
static void
port_unlink(Port *prt, erts_aint32_t state, ErtsSigUnlinkOp *sulnk)
{
- if (state & ERTS_PORT_SFLGS_INVALID_LOOKUP)
- port_unlink_failure(prt->common.id, sulnk);
- else {
+ if (state & ERTS_PORT_SFLGS_INVALID_LOOKUP) {
+ port_unlink_failure(prt, prt->common.id, sulnk);
+ } else {
ErtsILink *ilnk;
+
ilnk = (ErtsILink *) erts_link_tree_lookup(ERTS_P_LINKS(prt),
sulnk->from);
+
if (ilnk && !ilnk->unlinking) {
if (IS_TRACED_FL(prt, F_TRACE_PORTS))
trace_port(prt, am_getting_unlinked, sulnk->from);
erts_link_tree_delete(&ERTS_P_LINKS(prt), &ilnk->link);
erts_link_internal_release(&ilnk->link);
}
- erts_proc_sig_send_unlink_ack(NULL, prt->common.id, sulnk);
+
+ erts_proc_sig_send_unlink_ack(&prt->common, prt->common.id, sulnk);
}
}
static int
port_sig_unlink(Port *prt, erts_aint32_t state, int op, ErtsProc2PortSigData *sigdp)
{
- if (op == ERTS_PROC2PORT_SIG_EXEC)
- port_unlink(prt, state, sigdp->u.unlink.sulnk);
- else
- port_unlink_failure(sigdp->u.unlink.port_id, sigdp->u.unlink.sulnk);
- if (sigdp->flags & ERTS_P2P_SIG_DATA_FLG_REPLY)
- port_sched_op_reply(sigdp->caller, sigdp->ref, am_true, prt);
+ if (op == ERTS_PROC2PORT_SIG_EXEC) {
+ port_unlink(prt, state, sigdp->u.unlink.sulnk);
+ } else {
+ port_unlink_failure(prt, sigdp->u.unlink.port_id,
+ sigdp->u.unlink.sulnk);
+ }
+
+ if (sigdp->flags & ERTS_P2P_SIG_DATA_FLG_REPLY) {
+ port_sched_op_reply(sigdp->caller, sigdp->ref, am_true, prt);
+ }
+
return ERTS_PORT_REDS_UNLINK;
}
@@ -2522,7 +2538,7 @@ erts_port_unlink(Process *c_p, Port *prt, ErtsSigUnlinkOp *sulnk, Eterm *refp)
BUMP_REDS(c_p, ERTS_PORT_REDS_UNLINK);
return ERTS_PORT_OP_DONE;
case ERTS_TRY_IMM_DRV_CALL_INVALID_PORT:
- port_unlink_failure(prt->common.id, sulnk);
+ port_unlink_failure(prt, prt->common.id, sulnk);
return ERTS_PORT_OP_DROPPED;
default:
/* Schedule call instead... */
@@ -2622,17 +2638,17 @@ erts_port_unlink_ack(Process *c_p, Port *prt, ErtsSigUnlinkOp *sulnk)
}
static void
-port_link_failure(Eterm port_id, ErtsLink *lnk)
+port_link_failure(Port *port, Eterm port_id, ErtsLink *lnk)
{
- erts_proc_sig_send_link_exit(NULL, port_id, lnk, am_noproc, NIL);
+ erts_proc_sig_send_link_exit(&port->common, port_id, lnk, am_noproc, NIL);
}
static void
port_link(Port *prt, erts_aint32_t state, ErtsLink *nlnk)
{
- if (state & ERTS_PORT_SFLGS_INVALID_LOOKUP)
- port_link_failure(prt->common.id, nlnk);
- else {
+ if (state & ERTS_PORT_SFLGS_INVALID_LOOKUP) {
+ port_link_failure(prt, prt->common.id, nlnk);
+ } else {
ErtsLink *lnk;
lnk = erts_link_tree_lookup_insert(&ERTS_P_LINKS(prt), nlnk);
if (lnk)
@@ -2645,12 +2661,16 @@ port_link(Port *prt, erts_aint32_t state, ErtsLink *nlnk)
static int
port_sig_link(Port *prt, erts_aint32_t state, int op, ErtsProc2PortSigData *sigdp)
{
- if (op == ERTS_PROC2PORT_SIG_EXEC)
- port_link(prt, state, sigdp->u.link.lnk);
- else
- port_link_failure(sigdp->u.link.port_id, sigdp->u.link.lnk);
- if (sigdp->flags & ERTS_P2P_SIG_DATA_FLG_REPLY)
- port_sched_op_reply(sigdp->caller, sigdp->ref, am_true, prt);
+ if (op == ERTS_PROC2PORT_SIG_EXEC) {
+ port_link(prt, state, sigdp->u.link.lnk);
+ } else {
+ port_link_failure(prt, sigdp->u.link.port_id, sigdp->u.link.lnk);
+ }
+
+ if (sigdp->flags & ERTS_P2P_SIG_DATA_FLG_REPLY) {
+ port_sched_op_reply(sigdp->caller, sigdp->ref, am_true, prt);
+ }
+
return ERTS_PORT_REDS_LINK;
}
@@ -2695,9 +2715,11 @@ erts_port_link(Process *c_p, Port *prt, ErtsLink *lnk, Eterm *refp)
}
static void
-port_monitor_failure(Eterm port_id, ErtsMonitor *mon)
+port_monitor_failure(Port *prt, Eterm port_id, ErtsMonitor *mon)
{
- erts_proc_sig_send_monitor_down(mon, am_noproc);
+ ASSERT(prt == NULL || prt->common.id == port_id);
+ erts_proc_sig_send_monitor_down(prt ? &prt->common : NULL, port_id,
+ mon, am_noproc);
}
/* Origin wants to monitor port Prt. State contains possible error, which has
@@ -2707,9 +2729,10 @@ static void
port_monitor(Port *prt, erts_aint32_t state, ErtsMonitor *mon)
{
ASSERT(prt);
- if (state & ERTS_PORT_SFLGS_INVALID_LOOKUP)
- port_monitor_failure(prt->common.id, mon);
- else {
+
+ if (state & ERTS_PORT_SFLGS_INVALID_LOOKUP) {
+ port_monitor_failure(prt, prt->common.id, mon);
+ } else {
ASSERT(erts_monitor_is_target(mon));
erts_monitor_list_insert(&ERTS_P_LT_MONITORS(prt), mon);
}
@@ -2719,11 +2742,12 @@ static int
port_sig_monitor(Port *prt, erts_aint32_t state, int op,
ErtsProc2PortSigData *sigdp)
{
- if (op == ERTS_PROC2PORT_SIG_EXEC)
+ if (op == ERTS_PROC2PORT_SIG_EXEC) {
port_monitor(prt, state, sigdp->u.monitor.mon);
- else
- port_monitor_failure(sigdp->u.monitor.port_id,
- sigdp->u.monitor.mon);
+ } else {
+ port_monitor_failure(prt, sigdp->u.monitor.port_id, sigdp->u.monitor.mon);
+ }
+
return ERTS_PORT_REDS_MONITOR;
}
@@ -2852,7 +2876,7 @@ unlink_proc(Port *prt, Eterm pid)
ilnk = (ErtsILink *) erts_link_tree_lookup(ERTS_P_LINKS(prt),
pid);
if (ilnk && !ilnk->unlinking) {
- Uint64 id = erts_proc_sig_send_unlink(NULL,
+ Uint64 id = erts_proc_sig_send_unlink(&prt->common,
prt->common.id,
&ilnk->link);
if (id != 0)
@@ -3190,7 +3214,7 @@ static int flush_linebuf(LineBufContext *bp)
* Returns: LINEBUF_EMPTY if there is no more data that can be
* determined as a line (only part of a line left), LINEBUF_EOL if a whole
* line could be delivered and LINEBUF_NOEOL if the buffer size has been
- * exceeded. The data and the data length can be accesed through the
+ * exceeded. The data and the data length can be accessed through the
* LINEBUF_DATA and the LINEBUF_DATALEN macros applied to the LineBufContext.
* Parameters:
* bp - A LineBufContext that is initialized with
@@ -3304,7 +3328,7 @@ deliver_result(Port *prt, Eterm sender, Eterm pid, Eterm res)
/*
* Deliver a "read" message.
- * hbuf -- byte that are always formated as a list
+ * hbuf -- byte that are always formatted as a list
* hlen -- number of byte in header
* buf -- data
* len -- length of data
@@ -3761,25 +3785,35 @@ erts_terminate_port(Port *pp)
}
typedef struct {
- Eterm port_id;
+ Port *port;
Eterm reason;
} ErtsPortExitContext;
static int link_port_exit(ErtsLink *lnk, void *vpectxt, Sint reds)
{
ErtsPortExitContext *pectxt = vpectxt;
- erts_proc_sig_send_link_exit(NULL, pectxt->port_id,
- lnk, pectxt->reason, NIL);
+ Port *port = pectxt->port;
+
+ if (((ErtsILink *) lnk)->unlinking)
+ erts_link_release(lnk);
+ else
+ erts_proc_sig_send_link_exit(&port->common, port->common.id,
+ lnk, pectxt->reason, NIL);
return 1;
}
static int monitor_port_exit(ErtsMonitor *mon, void *vpectxt, Sint reds)
{
ErtsPortExitContext *pectxt = vpectxt;
- if (erts_monitor_is_target(mon))
- erts_proc_sig_send_monitor_down(mon, pectxt->reason);
- else
- erts_proc_sig_send_demonitor(mon);
+ Port *port = pectxt->port;
+
+ if (erts_monitor_is_target(mon)) {
+ erts_proc_sig_send_monitor_down(&port->common, port->common.id, mon,
+ pectxt->reason);
+ } else {
+ erts_proc_sig_send_demonitor(&port->common, port->common.id, 0, mon);
+ }
+
return 1;
}
@@ -3860,8 +3894,8 @@ erts_deliver_port_exit(Port *prt, Eterm from, Eterm reason, int send_closed,
if (prt->common.u.alive.reg != NULL)
(void) erts_unregister_name(NULL, 0, prt, prt->common.u.alive.reg->name);
- pectxt.port_id = prt->common.id;
pectxt.reason = modified_reason;
+ pectxt.port = prt;
if (state & ERTS_PORT_SFLG_DISTRIBUTION) {
DistEntry *dep = (DistEntry*) erts_prtsd_get(prt, ERTS_PRTSD_DIST_ENTRY);
@@ -6009,18 +6043,24 @@ driver_deliver_term(Port *prt, Eterm to, ErlDrvTermData* data, int len)
case ERL_DRV_TUPLE: { /* int */
int size = (int)ptr[0];
- Eterm* tp = erts_produce_heap(&factory, size+1, HEAP_EXTRA);
+ if (size == 0) {
+ mess = ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ ptr++;
+ break;
+ } else {
+ Eterm* tp = erts_produce_heap(&factory, size+1, HEAP_EXTRA);
- *tp = make_arityval(size);
- mess = make_tuple(tp);
+ *tp = make_arityval(size);
+ mess = make_tuple(tp);
- tp += size; /* point at last element */
+ tp += size; /* point at last element */
- while(size--) {
- *tp-- = ESTACK_POP(stack);
- }
- ptr++;
- break;
+ while(size--) {
+ *tp-- = ESTACK_POP(stack);
+ }
+ ptr++;
+ break;
+ }
}
case ERL_DRV_PID: /* pid argument */
@@ -6068,15 +6108,15 @@ driver_deliver_term(Port *prt, Eterm to, ErlDrvTermData* data, int len)
Eterm* vp;
flatmap_t *mp;
Eterm* tp = erts_produce_heap(&factory,
- 2*size + 1 + MAP_HEADER_FLATMAP_SZ,
+ 2*size + (size==0 ? 0 : 1) + MAP_HEADER_FLATMAP_SZ,
HEAP_EXTRA);
-
- *tp = make_arityval(size);
-
- mp = (flatmap_t*) (tp + 1 + size);
+ if (size != 0) {
+ *tp = make_arityval(size);
+ }
+ mp = (flatmap_t*) (tp + (size==0 ? 0 : 1) + size);
mp->thing_word = MAP_HEADER_FLATMAP;
mp->size = size;
- mp->keys = make_tuple(tp);
+ mp->keys = (size!= 0 ? make_tuple(tp) : ERTS_GLOBAL_LIT_EMPTY_TUPLE);
mess = make_flatmap(mp);
tp += size; /* point at last key */
@@ -6952,7 +6992,8 @@ static int do_driver_monitor_process(Port *prt,
prt->common.id, process, NIL,
THE_NON_VALUE);
- if (!erts_proc_sig_send_monitor(&mdp->u.target, process)) {
+ if (!erts_proc_sig_send_monitor(&prt->common, prt->common.id,
+ &mdp->u.target, process)) {
erts_monitor_release_both(mdp);
return 1;
}
@@ -7001,7 +7042,8 @@ static int do_driver_demonitor_process(Port *prt, const ErlDrvMonitor *monitor)
return 1;
erts_monitor_tree_delete(&ERTS_P_MONITORS(prt), mon);
- erts_proc_sig_send_demonitor(mon);
+ erts_proc_sig_send_demonitor(&prt->common, prt->common.id, 0, mon);
+
return 0;
}
diff --git a/erts/emulator/beam/jit/arm/beam_asm.hpp b/erts/emulator/beam/jit/arm/beam_asm.hpp
new file mode 100644
index 0000000000..a2d28c27b5
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/beam_asm.hpp
@@ -0,0 +1,1700 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <queue>
+#include <map>
+#include <functional>
+#include <algorithm>
+#include <cmath>
+
+#ifndef ASMJIT_ASMJIT_H_INCLUDED
+# include <asmjit/asmjit.hpp>
+#endif
+
+#include <asmjit/a64.h>
+
+extern "C"
+{
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "sys.h"
+#include "erl_vm.h"
+#include "global.h"
+#include "beam_catches.h"
+#include "big.h"
+
+#include "beam_asm.h"
+}
+
+#include "beam_jit_common.hpp"
+
+/* Is it safe to STP or LDP `Struct->Field1` and `Struct->Field2`? */
+#define ERTS_CT_ASSERT_FIELD_PAIR(Struct, Field1, Field2) \
+ static_assert(std::is_standard_layout<Struct>::value && \
+ (offsetof(Struct, Field2) - offsetof(Struct, Field1) == \
+ sizeof(((Struct *)nullptr)->Field1)) && \
+ (sizeof(((Struct *)nullptr)->Field1) == \
+ sizeof(((Struct *)nullptr)->Field2)))
+
+using namespace asmjit;
+
+class BeamAssembler : public ErrorHandler {
+protected:
+ /* Holds code and relocation information. */
+ CodeHolder code;
+
+ a64::Assembler a;
+
+ FileLogger logger;
+
+ Section *rodata = nullptr;
+
+ /* * * * * * * * * */
+
+ /* Points at x_reg_array inside an ErtsSchedulerRegisters struct, allowing
+ * the aux_regs field to be addressed with an 8-bit displacement. */
+ const arm::Gp scheduler_registers = a64::x19;
+
+ const arm::Gp E = a64::x20;
+ const arm::Gp c_p = a64::x21;
+ const arm::Gp FCALLS = a64::x22;
+ const arm::Gp HTOP = a64::x23;
+
+ /* Local copy of the active code index.
+ *
+ * This is set to ERTS_SAVE_CALLS_CODE_IX when save_calls is active, which
+ * routes us to a common handler routine that calls save_calls before
+ * jumping to the actual code. */
+ const arm::Gp active_code_ix = a64::x24;
+
+ /* X registers */
+#if defined(DEBUG)
+ /*
+ * To ensure that we thoroughly test flushing of caller-save X
+ * registers, define more caller-save X registers in a DEBUG
+ * build.
+ */
+# define ERTS_HIGHEST_CALLEE_SAVE_XREG 2
+# define ERTS_HIGHEST_CALLER_SAVE_XREG 5
+ const arm::Gp XREG0 = a64::x25;
+ const arm::Gp XREG1 = a64::x26;
+ const arm::Gp XREG2 = a64::x27;
+
+ /*
+ * Caller-save X registers. Must be flushed before calling C
+ * code.
+ */
+ const arm::Gp XREG3 = a64::x15;
+ const arm::Gp XREG4 = a64::x16;
+ const arm::Gp XREG5 = a64::x17;
+#else
+# define ERTS_HIGHEST_CALLEE_SAVE_XREG 3
+# define ERTS_HIGHEST_CALLER_SAVE_XREG 5
+ const arm::Gp XREG0 = a64::x25;
+ const arm::Gp XREG1 = a64::x26;
+ const arm::Gp XREG2 = a64::x27;
+ const arm::Gp XREG3 = a64::x28;
+
+ /*
+ * Caller-save X registers. Must be flushed before calling C
+ * code.
+ */
+ const arm::Gp XREG4 = a64::x15;
+ const arm::Gp XREG5 = a64::x16;
+#endif
+
+#define ERTS_LOWEST_CALLEE_SAVE_XREG (0)
+#define ERTS_LOWEST_CALLER_SAVE_XREG (ERTS_HIGHEST_CALLEE_SAVE_XREG + 1)
+
+ static const int num_register_backed_xregs = 6;
+ const arm::Gp register_backed_xregs[num_register_backed_xregs] =
+ {XREG0, XREG1, XREG2, XREG3, XREG4, XREG5};
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ const arm::Mem erts_msacc_cache = getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.erts_msacc_cache));
+#endif
+
+ /* * * * * * * * * */
+ const arm::Gp ZERO = a64::xzr;
+
+ /*
+ * All of the following registers are caller-save.
+ *
+ * Note that ARG1 is also the register for the return value.
+ */
+ const arm::Gp ARG1 = a64::x0;
+ const arm::Gp ARG2 = a64::x1;
+ const arm::Gp ARG3 = a64::x2;
+ const arm::Gp ARG4 = a64::x3;
+ const arm::Gp ARG5 = a64::x4;
+ const arm::Gp ARG6 = a64::x5;
+ const arm::Gp ARG7 = a64::x6;
+ const arm::Gp ARG8 = a64::x7;
+
+ const arm::Gp TMP1 = a64::x8;
+ const arm::Gp TMP2 = a64::x9;
+ const arm::Gp TMP3 = a64::x10;
+ const arm::Gp TMP4 = a64::x11;
+ const arm::Gp TMP5 = a64::x12;
+ const arm::Gp TMP6 = a64::x13;
+
+ /*
+ * Assume that SUPER_TMP will be destroyed by any helper function.
+ */
+ const arm::Gp SUPER_TMP = a64::x14;
+
+ /*
+ * Note that x18 is reserved on Apple platforms and must not be used.
+ */
+
+ /* Callee-saved floating-point registers.
+ *
+ * Note that only the bottom 64 bits of these (128-bit) registers are
+ * callee-save, so we cannot pack two floats into each register. */
+ const arm::VecD FREG0 = a64::d8;
+ const arm::VecD FREG1 = a64::d9;
+ const arm::VecD FREG2 = a64::d10;
+ const arm::VecD FREG3 = a64::d11;
+ const arm::VecD FREG4 = a64::d12;
+ const arm::VecD FREG5 = a64::d13;
+ const arm::VecD FREG6 = a64::d14;
+ const arm::VecD FREG7 = a64::d15;
+ static const int num_register_backed_fregs = 8;
+ const arm::VecD register_backed_fregs[num_register_backed_fregs] =
+ {FREG0, FREG1, FREG2, FREG3, FREG4, FREG5, FREG6, FREG7};
+
+ const arm::Mem TMP_MEM1q = getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.TMP_MEM[0]));
+ const arm::Mem TMP_MEM2q = getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.TMP_MEM[1]));
+ const arm::Mem TMP_MEM3q = getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.TMP_MEM[2]));
+ const arm::Mem TMP_MEM4q = getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.TMP_MEM[3]));
+ const arm::Mem TMP_MEM5q = getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.TMP_MEM[4]));
+
+ /* Fill registers with undefined contents to find bugs faster.
+ * A boxed value is most likely to cause noticeable trouble. */
+ static const Uint64 bad_boxed_ptr = 0xcafebad0000002UL;
+
+ /* Number of highest element displacement for L/SDP and L/STR. */
+ static const size_t MAX_LDP_STP_DISPLACEMENT = 0x3F;
+ static const size_t MAX_LDR_STR_DISPLACEMENT = 0xFFF;
+
+ /* Constants for "alternate flag state" operands, which are distinct from
+ * `arm::CondCode::xyz`. Mainly used in `CCMP` instructions. */
+ enum NZCV : int {
+ kNF = 8,
+ kSigned = kNF,
+
+ kZF = 4,
+ kEqual = kZF,
+
+ kCF = 2,
+ kCarry = kCF,
+
+ kVF = 1,
+ kOverflow = kVF,
+
+ kNone = 0
+ };
+
+public:
+ static bool hasCpuFeature(uint32_t featureId);
+
+ BeamAssembler();
+ BeamAssembler(const std::string &log);
+
+ ~BeamAssembler();
+
+ void *getBaseAddress();
+ size_t getOffset();
+
+protected:
+ void _codegen(JitAllocator *allocator,
+ const void **executable_ptr,
+ void **writable_ptr);
+
+ void *getCode(Label label);
+ byte *getCode(char *labelName);
+
+ void handleError(Error err, const char *message, BaseEmitter *origin);
+
+#ifdef JIT_HARD_DEBUG
+ constexpr arm::Mem getInitialSPRef() const {
+ int base = offsetof(ErtsSchedulerRegisters, initial_sp);
+
+ return getSchedulerRegRef(base);
+ }
+#endif
+
+ constexpr arm::Mem getSchedulerRegRef(int offset) const {
+ ASSERT((offset & (sizeof(Eterm) - 1)) == 0);
+ return arm::Mem(scheduler_registers, offset);
+ }
+
+ constexpr arm::Mem getFRef(int index, size_t size = sizeof(UWord)) const {
+ int base = offsetof(ErtsSchedulerRegisters, f_reg_array.d);
+ int offset = index * sizeof(FloatDef);
+
+ ASSERT(0 <= index && index <= 1023);
+ return getSchedulerRegRef(base + offset);
+ }
+
+ constexpr arm::Mem getXRef(int index) const {
+ int base = offsetof(ErtsSchedulerRegisters, x_reg_array.d);
+ int offset = index * sizeof(Eterm);
+
+ ASSERT(0 <= index && index < ERTS_X_REGS_ALLOCATED);
+ return getSchedulerRegRef(base + offset);
+ }
+
+ constexpr arm::Mem getYRef(int index) const {
+ ASSERT(0 <= index && index <= 1023);
+
+ return arm::Mem(E, index * sizeof(Eterm));
+ }
+
+ constexpr arm::Mem getCARRef(arm::Gp Src) const {
+ return arm::Mem(Src, -TAG_PRIMARY_LIST);
+ }
+
+ constexpr arm::Mem getCDRRef(arm::Gp Src,
+ size_t size = sizeof(UWord)) const {
+ return arm::Mem(Src, -TAG_PRIMARY_LIST + sizeof(Eterm));
+ }
+
+ /* Loads the X register array into `to`. Remember to sync the registers in
+ * `emit_enter_runtime`. */
+ void load_x_reg_array(arm::Gp to) {
+ int offset = offsetof(ErtsSchedulerRegisters, x_reg_array.d);
+
+ lea(to, getSchedulerRegRef(offset));
+ }
+
+ void load_erl_bits_state(arm::Gp to) {
+ int offset =
+ offsetof(ErtsSchedulerRegisters, aux_regs.d.erl_bits_state);
+
+ lea(to, getSchedulerRegRef(offset));
+ }
+
+ void emit_assert_redzone_unused() {
+#ifdef JIT_HARD_DEBUG
+ const int REDZONE_BYTES = S_REDZONE * sizeof(Eterm);
+ Label next = a.newLabel();
+
+ a.sub(SUPER_TMP, E, imm(REDZONE_BYTES));
+ a.cmp(HTOP, SUPER_TMP);
+
+ a.b_ls(next);
+ a.udf(0xbeef);
+
+ a.bind(next);
+#endif
+ }
+
+ /*
+ * Calls an Erlang function.
+ */
+ template<typename Any>
+ void erlang_call(Any Target) {
+ emit_assert_redzone_unused();
+ aligned_call(Target);
+ }
+
+ void branch(arm::Mem target) {
+ a.ldr(SUPER_TMP, target);
+ a.br(SUPER_TMP);
+ }
+
+ template<typename FuncPtr>
+ void aligned_call(FuncPtr(*target)) {
+ mov_imm(SUPER_TMP, target);
+ a.blr(SUPER_TMP);
+ }
+
+ void aligned_call(Label target) {
+ a.bl(target);
+ }
+
+ void aligned_call(arm::Gp target) {
+ a.blr(target);
+ }
+
+ /* Calls the given address. In DEBUG builds, make
+ * sure that the CP is aligned. */
+ template<typename OperandType>
+ void aligned_call(OperandType target) {
+ ERTS_CT_ASSERT(_CPMASK == 3);
+ ASSERT(is_CP(a.offset()));
+ a.ldr(TMP1, target);
+ a.blr(TMP1);
+ }
+
+ void runtime_call(arm::Gp func, unsigned args) {
+ ASSERT(args < 5);
+ a.blr(func);
+ }
+
+ template<typename T>
+ struct function_arity;
+ template<typename T, typename... Args>
+ struct function_arity<T(Args...)>
+ : std::integral_constant<int, sizeof...(Args)> {};
+
+ template<int expected_arity, typename T>
+ void runtime_call(T(*func)) {
+ static_assert(expected_arity == function_arity<T>());
+
+ a.mov(TMP1, func);
+ a.blr(TMP1);
+ }
+
+ /* Explicitly position-independent absolute jump, for use in fragments that
+ * need to be memcpy'd for performance reasons (e.g. NIF stubs) */
+ template<typename T>
+ void pic_jmp(T(*addr)) {
+ a.mov(SUPER_TMP, addr);
+ a.br(SUPER_TMP);
+ }
+
+ constexpr arm::Mem getArgRef(const ArgRegister &arg) const {
+ if (arg.isXRegister()) {
+ return getXRef(arg.as<ArgXRegister>().get());
+ } else if (arg.isYRegister()) {
+ return getYRef(arg.as<ArgYRegister>().get());
+ }
+
+ return getFRef(arg.as<ArgFRegister>().get());
+ }
+
+ /* Returns the current code address for the `Export` or `ErlFunEntry` in
+ * `Src`.
+ *
+ * Export tracing, save_calls, etc are implemented by shared fragments that
+ * assume that the respective entry is in ARG1, so we have to copy it over
+ * if it isn't already. */
+ arm::Mem emit_setup_dispatchable_call(const arm::Gp &Src) {
+ return emit_setup_dispatchable_call(Src, active_code_ix);
+ }
+
+ arm::Mem emit_setup_dispatchable_call(const arm::Gp &Src,
+ const arm::Gp &CodeIndex) {
+ if (ARG1 != Src) {
+ a.mov(ARG1, Src);
+ }
+
+ ERTS_CT_ASSERT(offsetof(ErlFunEntry, dispatch) == 0);
+ ERTS_CT_ASSERT(offsetof(Export, dispatch) == 0);
+ ERTS_CT_ASSERT(offsetof(ErtsDispatchable, addresses) == 0);
+
+ return arm::Mem(ARG1, CodeIndex, arm::lsl(3));
+ }
+
+ enum Update : int {
+ eStack = (1 << 0),
+ eHeap = (1 << 1),
+ eReductions = (1 << 2),
+ eCodeIndex = (1 << 3),
+ eXRegs = (1 << 4)
+ };
+
+ void emit_enter_erlang_frame() {
+ a.str(a64::x30, arm::Mem(E, -8).pre());
+ }
+
+ void emit_leave_erlang_frame() {
+ a.ldr(a64::x30, arm::Mem(E).post(8));
+ }
+
+ void emit_enter_runtime_frame() {
+ a.stp(a64::x29, a64::x30, arm::Mem(a64::sp, -16).pre());
+ a.mov(a64::x29, a64::sp);
+ }
+
+ void emit_leave_runtime_frame() {
+ a.mov(a64::sp, a64::x29);
+ a.ldp(a64::x29, a64::x30, arm::Mem(a64::sp).post(16));
+ }
+
+ /* We keep the first six X registers in machine registers. Some of those
+ * registers are callee-saved and some are caller-saved.
+ *
+ * We ignore the ones above `live` to reduce the save/restore traffic on
+ * these registers. It's enough for this figure to be at least as high as
+ * the number of actually live registers, and we default to all six
+ * registers when we don't know the exact number.
+ *
+ * Furthermore, we only save the callee-save registers when told to sync
+ * all registers with the `Update::eXRegs` flag, as this is very rarely
+ * needed. */
+
+ template<int Spec = 0>
+ void emit_enter_runtime(int live = num_register_backed_xregs) {
+ ERTS_CT_ASSERT((Spec & (Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs)) == Spec);
+
+ if ((Spec & Update::eStack) && (Spec & Update::eHeap)) {
+ /* Store HTOP and E in one go. */
+ ERTS_CT_ASSERT_FIELD_PAIR(Process, htop, stop);
+ a.stp(HTOP, E, arm::Mem(c_p, offsetof(Process, htop)));
+ } else if (Spec & Update::eStack) {
+ a.str(E, arm::Mem(c_p, offsetof(Process, stop)));
+ } else if (Spec & Update::eHeap) {
+ a.str(HTOP, arm::Mem(c_p, offsetof(Process, htop)));
+ }
+
+ if (Spec & Update::eReductions) {
+ a.str(FCALLS, arm::Mem(c_p, offsetof(Process, fcalls)));
+ }
+
+ /* Save register-backed X registers to the X register array when
+ * needed. The backing registers must NOT be used afterwards.
+ *
+ * In a DEBUG build, the backing X registers will be overwritten with
+ * garbage values. */
+ if (live > 0) {
+ int num_to_save = MIN(live, ERTS_HIGHEST_CALLER_SAVE_XREG + 1);
+ int i;
+
+ if (Spec & Update::eXRegs) {
+ i = ERTS_LOWEST_CALLEE_SAVE_XREG;
+ } else {
+ /* If we don't need to sync the X register array, then we can
+ * get away with saving only the fragile X registers. */
+ i = ERTS_LOWEST_CALLER_SAVE_XREG;
+ }
+
+#ifdef DEBUG
+ /* Destroy the saved X registers to find bugs sooner.*/
+ if (i < num_to_save) {
+ mov_imm(SUPER_TMP, bad_boxed_ptr + 0x20 + (Spec << 8));
+ }
+#endif
+
+ while (i < num_to_save - 1) {
+ a.stp(register_backed_xregs[i + 0],
+ register_backed_xregs[i + 1],
+ getXRef(i));
+
+#ifdef DEBUG
+ a.mov(register_backed_xregs[i + 0], SUPER_TMP);
+ a.mov(register_backed_xregs[i + 1], SUPER_TMP);
+#endif
+
+ i += 2;
+ }
+
+ if (i < num_to_save) {
+ a.str(register_backed_xregs[i], getXRef(i));
+
+#ifdef DEBUG
+ a.mov(register_backed_xregs[i], SUPER_TMP);
+#endif
+ }
+ }
+ }
+
+ template<int Spec = 0>
+ void emit_leave_runtime(int live = num_register_backed_xregs) {
+ ERTS_CT_ASSERT(
+ (Spec & (Update::eReductions | Update::eStack | Update::eHeap |
+ Update::eXRegs | Update::eCodeIndex)) == Spec);
+
+ if ((Spec & Update::eStack) && (Spec & Update::eHeap)) {
+ /* Load HTOP and E in one go. */
+ ERTS_CT_ASSERT_FIELD_PAIR(Process, htop, stop);
+ a.ldp(HTOP, E, arm::Mem(c_p, offsetof(Process, htop)));
+ } else if (Spec & Update::eHeap) {
+ a.ldr(HTOP, arm::Mem(c_p, offsetof(Process, htop)));
+ } else if (Spec & Update::eStack) {
+ a.ldr(E, arm::Mem(c_p, offsetof(Process, stop)));
+ }
+
+ if (Spec & Update::eReductions) {
+ a.ldr(FCALLS, arm::Mem(c_p, offsetof(Process, fcalls)));
+ }
+
+ if (Spec & Update::eCodeIndex) {
+ /* Updates the local copy of the active code index, retaining
+ * save_calls if active. */
+ mov_imm(SUPER_TMP, &the_active_code_index);
+ a.ldr(SUPER_TMP.w(), arm::Mem(SUPER_TMP));
+ a.cmp(active_code_ix, imm(ERTS_SAVE_CALLS_CODE_IX));
+ a.csel(active_code_ix,
+ active_code_ix,
+ SUPER_TMP,
+ arm::CondCode::kEQ);
+ }
+
+ /* Restore register-backed X registers from the X register array when
+ * needed. The register array must NOT be used afterwards.
+ *
+ * In a DEBUG build, the register array will be overwritten with
+ * garbage values. */
+ if (live > 0) {
+ int num_to_restore = MIN(live, ERTS_HIGHEST_CALLER_SAVE_XREG + 1);
+ int i;
+
+ if (Spec & Update::eXRegs) {
+ i = ERTS_LOWEST_CALLEE_SAVE_XREG;
+ } else {
+ /* If we don't need to sync the X register array, then we can
+ * get away with loading only the fragile X registers. */
+ i = ERTS_LOWEST_CALLER_SAVE_XREG;
+ }
+
+#ifdef DEBUG
+ /* Destroy the restored X registers to find bugs sooner.*/
+ if (i < num_to_restore) {
+ mov_imm(SUPER_TMP, bad_boxed_ptr + 0x80 + (Spec << 8));
+ }
+#endif
+
+ while (i < num_to_restore - 1) {
+ a.ldp(register_backed_xregs[i],
+ register_backed_xregs[i + 1],
+ getXRef(i));
+
+#ifdef DEBUG
+ a.stp(SUPER_TMP, SUPER_TMP, getXRef(i));
+#endif
+
+ i += 2;
+ }
+
+ if (i < num_to_restore) {
+ a.ldr(register_backed_xregs[i], getXRef(i));
+
+#ifdef DEBUG
+ a.str(SUPER_TMP, getXRef(i));
+#endif
+ }
+ }
+ }
+
+ void emit_is_boxed(Label Fail, arm::Gp Src) {
+ const int bitNumber = 0;
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED ==
+ (1 << bitNumber));
+ a.tbnz(Src, imm(bitNumber), Fail);
+ }
+
+ void emit_is_not_boxed(Label Fail, arm::Gp Src) {
+ const int bitNumber = 0;
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED ==
+ (1 << bitNumber));
+ a.tbz(Src, imm(bitNumber), Fail);
+ }
+
+ arm::Gp emit_ptr_val(arm::Gp Dst, arm::Gp Src) {
+#if !defined(TAG_LITERAL_PTR)
+ return Src;
+#else
+ /* We intentionally skip TAG_PTR_MASK__ here, as we want to use
+ * plain `emit_boxed_val` when we know the argument can't be a literal,
+ * such as in bit-syntax matching.
+ *
+ * This comes at very little cost as `emit_boxed_val` nearly always has
+ * a displacement. */
+ a.and_(Dst, Src, imm(~TAG_LITERAL_PTR));
+ return Dst;
+#endif
+ }
+
+ void emit_untag_ptr(arm::Gp Dst, arm::Gp Src) {
+ a.and_(Dst, Src, imm(~TAG_PTR_MASK__));
+ }
+
+ constexpr arm::Mem emit_boxed_val(arm::Gp Src, int32_t bytes = 0) const {
+ ASSERT(bytes % sizeof(Eterm) == 0);
+ return arm::Mem(Src, bytes - TAG_PRIMARY_BOXED);
+ }
+
+ void emit_branch_if_not_value(arm::Gp reg, Label lbl) {
+ emit_branch_if_eq(reg, THE_NON_VALUE, lbl);
+ }
+
+ void emit_branch_if_value(arm::Gp reg, Label lbl) {
+ emit_branch_if_ne(reg, THE_NON_VALUE, lbl);
+ }
+
+ void emit_branch_if_eq(arm::Gp reg, Uint value, Label lbl) {
+ if (value == 0) {
+ a.cbz(reg, lbl);
+ } else {
+ a.cmp(reg, imm(value));
+ a.b_eq(lbl);
+ }
+ }
+
+ void emit_branch_if_ne(arm::Gp reg, Uint value, Label lbl) {
+ if (value == 0) {
+ a.cbnz(reg, lbl);
+ } else {
+ a.cmp(reg, imm(value));
+ a.b_ne(lbl);
+ }
+ }
+
+ /* Set the Z flag if Reg1 and Reg2 are both immediates. */
+ void emit_are_both_immediate(arm::Gp Reg1, arm::Gp Reg2) {
+ ERTS_CT_ASSERT(TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK);
+ a.and_(SUPER_TMP, Reg1, Reg2);
+ a.and_(SUPER_TMP, SUPER_TMP, imm(_TAG_PRIMARY_MASK));
+ a.cmp(SUPER_TMP, imm(TAG_PRIMARY_IMMED1));
+ }
+
+ /* Set the Z flag if Reg1 and Reg2 are definitely not equal based
+ * on their tags alone. (They may still be equal if both are
+ * immediates and all other bits are equal too.) */
+ void emit_is_unequal_based_on_tags(arm::Gp Reg1, arm::Gp Reg2) {
+ ERTS_CT_ASSERT(TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK);
+ ERTS_CT_ASSERT((TAG_PRIMARY_LIST | TAG_PRIMARY_BOXED) ==
+ TAG_PRIMARY_IMMED1);
+ a.orr(SUPER_TMP, Reg1, Reg2);
+ a.and_(SUPER_TMP, SUPER_TMP, imm(_TAG_PRIMARY_MASK));
+
+ /*
+ * SUPER_TMP will be now be TAG_PRIMARY_IMMED1 if either
+ * one or both registers are immediates, or if one register
+ * is a list and the other a boxed.
+ */
+ a.cmp(SUPER_TMP, imm(TAG_PRIMARY_IMMED1));
+ }
+
+ template<typename T>
+ void mov_imm(arm::Gp to, T value) {
+ static_assert(std::is_integral<T>::value || std::is_pointer<T>::value);
+ if (value) {
+ a.mov(to, imm(value));
+ } else {
+ a.mov(to, ZERO);
+ }
+ }
+
+ void mov_imm(arm::Gp to, std::nullptr_t value) {
+ (void)value;
+ mov_imm(to, 0);
+ }
+
+ void sub(arm::Gp to, arm::Gp src, int64_t val) {
+ if (val < 0) {
+ add(to, src, -val);
+ } else if (val == 0 && to != src) {
+ a.mov(to, src);
+ } else if (val < (1 << 24)) {
+ if (val & 0xFFF) {
+ a.sub(to, src, imm(val & 0xFFF));
+ src = to;
+ }
+
+ if (val & 0xFFF000) {
+ a.sub(to, src, imm(val & 0xFFF000));
+ }
+ } else {
+ mov_imm(SUPER_TMP, val);
+ a.sub(to, src, SUPER_TMP);
+ }
+ }
+
+ void add(arm::Gp to, arm::Gp src, int64_t val) {
+ if (val < 0) {
+ sub(to, src, -val);
+ } else if (val == 0 && to != src) {
+ a.mov(to, src);
+ } else if (val < (1 << 24)) {
+ if (val & 0xFFF) {
+ a.add(to, src, imm(val & 0xFFF));
+ src = to;
+ }
+
+ if (val & 0xFFF000) {
+ a.add(to, src, imm(val & 0xFFF000));
+ }
+ } else {
+ mov_imm(SUPER_TMP, val);
+ a.add(to, src, SUPER_TMP);
+ }
+ }
+
+ void cmp(arm::Gp src, int64_t val) {
+ if (Support::isUInt12(val)) {
+ a.cmp(src, imm(val));
+ } else if (Support::isUInt12(-val)) {
+ a.cmn(src, imm(-val));
+ } else {
+ mov_imm(SUPER_TMP, val);
+ a.cmp(src, SUPER_TMP);
+ }
+ }
+
+ void ldur(arm::Gp reg, arm::Mem mem) {
+ safe_9bit_imm(a64::Inst::kIdLdur, reg, mem);
+ }
+
+ void stur(arm::Gp reg, arm::Mem mem) {
+ safe_9bit_imm(a64::Inst::kIdStur, reg, mem);
+ }
+
+ void safe_9bit_imm(uint32_t instId, arm::Gp reg, arm::Mem mem) {
+ int64_t offset = mem.offset();
+
+ ASSERT(mem.hasBaseReg() && !mem.hasIndex());
+
+ if (Support::isInt9(offset)) {
+ a.emit(instId, reg, mem);
+ } else {
+ lea(SUPER_TMP, mem);
+ a.emit(instId, reg, arm::Mem(SUPER_TMP));
+ }
+ }
+
+ /*
+ * ARM has no LEA instruction. Implement our own to enable us
+ * to use helpers based on getSchedulerRegRef() that return an
+ * arm::Mem class.
+ */
+ void lea(arm::Gp to, arm::Mem mem) {
+ int64_t offset = mem.offset();
+
+ ASSERT(mem.hasBaseReg() && !mem.hasIndex());
+
+ if (offset == 0) {
+ a.mov(to, arm::GpX(mem.baseId()));
+ } else {
+ add(to, arm::GpX(mem.baseId()), offset);
+ }
+ }
+
+public:
+ void embed_rodata(const char *labelName, const char *buff, size_t size);
+ void embed_bss(const char *labelName, size_t size);
+ void embed_zeros(size_t size);
+
+ void setLogger(std::string log);
+ void setLogger(FILE *log);
+
+ void comment(const char *format) {
+ if (logger.file()) {
+ a.commentf("# %s", format);
+ }
+ }
+
+ template<typename... Ts>
+ void comment(const char *format, Ts... args) {
+ if (logger.file()) {
+ char buff[1024];
+ erts_snprintf(buff, sizeof(buff), format, args...);
+ a.commentf("# %s", buff);
+ }
+ }
+
+ struct AsmRange {
+ ErtsCodePtr start;
+ ErtsCodePtr stop;
+ const std::string name;
+
+ struct LineData {
+ ErtsCodePtr start;
+ const std::string file;
+ unsigned line;
+ };
+
+ const std::vector<LineData> lines;
+ };
+
+ void embed(void *data, uint32_t size) {
+ a.embed((char *)data, size);
+ }
+};
+
+#include "beam_asm_global.hpp"
+
+class BeamModuleAssembler : public BeamAssembler {
+ typedef unsigned BeamLabel;
+
+ /* Map of BEAM label number to asmjit Label. These should not be used
+ * directly by most instructions because of displacement limits, use
+ * `resolve_beam_label` instead. */
+ typedef std::unordered_map<BeamLabel, const Label> LabelMap;
+ LabelMap rawLabels;
+
+ /* Sequence number used to create unique named labels by
+ * resolve_label(). Only used when assembly output has been
+ * requested. */
+ long labelSeq = 0;
+
+ struct patch {
+ Label where;
+ uint64_t val_offs;
+ };
+
+ struct patch_catch {
+ struct patch patch;
+ Label handler;
+ };
+ std::vector<struct patch_catch> catches;
+
+ /* Map of import entry to patch labels and mfa */
+ struct patch_import {
+ std::vector<struct patch> patches;
+ ErtsCodeMFA mfa;
+ };
+ typedef std::unordered_map<unsigned, struct patch_import> ImportMap;
+ ImportMap imports;
+
+ /* Map of fun entry to patch labels */
+ struct patch_lambda {
+ std::vector<struct patch> patches;
+ Label trampoline;
+ };
+ typedef std::unordered_map<unsigned, struct patch_lambda> LambdaMap;
+ LambdaMap lambdas;
+
+ /* Map of literals to patch labels */
+ struct patch_literal {
+ std::vector<struct patch> patches;
+ };
+ typedef std::unordered_map<unsigned, struct patch_literal> LiteralMap;
+ LiteralMap literals;
+
+ /* All string patches */
+ std::vector<struct patch> strings;
+
+ /* All functions that have been seen so far */
+ std::vector<BeamLabel> functions;
+
+ /* The BEAM file we've been loaded from, if any. */
+ const BeamFile *beam;
+
+ BeamGlobalAssembler *ga;
+
+ /* Used by emit to populate the labelToMFA map */
+ Label current_label;
+
+ /* The offset of our BeamCodeHeader, if any. */
+ Label code_header;
+
+ /* The module's on_load function, if any. */
+ Label on_load;
+
+ /* The end of the last function. Note that the dispatch table, constants,
+ * and veneers may follow. */
+ Label code_end;
+
+ Eterm mod;
+
+ /* Save the last PC for an error. */
+ size_t last_error_offset = 0;
+
+ static constexpr ptrdiff_t STUB_CHECK_INTERVAL = 4 << 10;
+ size_t last_stub_check_offset = 0;
+
+ enum Displacement : size_t {
+ /* Pessimistic estimate for helper functions, where we don't know the
+ * branch displacement or whether it will be used near label
+ * resolution.
+ *
+ * Note that we subtract the size of one instruction to handle
+ * backward displacements. */
+ dispUnknown = (32 << 10) - sizeof(Uint32) - STUB_CHECK_INTERVAL,
+
+ /* +- 32KB: `tbz`, `tbnz`, `ldr` of 8-byte literal. */
+ disp32K = (32 << 10) - sizeof(Uint32),
+
+ /* +- 1MB: `adr`, `b.cond`, `cb.cond` */
+ disp1MB = (1 << 20) - sizeof(Uint32),
+
+ /* +- 128MB: `b`, `blr` */
+ disp128MB = (128 << 20) - sizeof(Uint32),
+
+ dispMin = dispUnknown,
+ dispMax = disp128MB
+ };
+
+ static_assert(dispMin <= dispUnknown && dispMax >= disp128MB);
+ static_assert(STUB_CHECK_INTERVAL < dispMin / 2);
+
+ struct Veneer {
+ ssize_t latestOffset;
+ Label anchor;
+
+ Label target;
+
+ constexpr bool operator>(const Veneer &other) const {
+ return latestOffset > other.latestOffset;
+ }
+ };
+
+ struct Constant {
+ ssize_t latestOffset;
+ Label anchor;
+
+ ArgVal value;
+
+ constexpr bool operator>(const Constant &other) const {
+ return latestOffset > other.latestOffset;
+ }
+ };
+
+ /* ArgVal -> Constant
+ *
+ * `_pending_constants` points directly into this container, which is
+ * documented to be safe as long as we only insert elements. */
+ std::unordered_multimap<ArgVal, const Constant, ArgVal::Hash> _constants;
+
+ /* Label::id() -> Veneer
+ *
+ * `_pending_veneers` points directly into this container. */
+ std::unordered_multimap<uint32_t, const Veneer> _veneers;
+
+ template<typename T>
+ using PendingStubs =
+ std::priority_queue<std::reference_wrapper<const T>,
+ std::deque<std::reference_wrapper<const T>>,
+ std::greater<const T &>>;
+
+ /* All pending stubs, segregated by type and sorted by `latestOffset` in
+ * ascending order.
+ *
+ * We use separate queues to avoid interleaving them, as they have
+ * different sizes and alignment requirements. */
+ PendingStubs<Constant> _pending_constants;
+ PendingStubs<Veneer> _pending_veneers;
+
+ /* Maps code pointers to thunks that jump to them, letting us treat global
+ * fragments as if they were local. */
+ std::unordered_map<void (*)(), Label> _dispatchTable;
+
+public:
+ BeamModuleAssembler(BeamGlobalAssembler *ga,
+ Eterm mod,
+ int num_labels,
+ const BeamFile *file = NULL);
+ BeamModuleAssembler(BeamGlobalAssembler *ga,
+ Eterm mod,
+ int num_labels,
+ int num_functions,
+ const BeamFile *file = NULL);
+
+ bool emit(unsigned op, const Span<ArgVal> &args);
+
+ void codegen(JitAllocator *allocator,
+ const void **executable_ptr,
+ void **writable_ptr,
+ const BeamCodeHeader *in_hdr,
+ const BeamCodeHeader **out_exec_hdr,
+ BeamCodeHeader **out_rw_hdr);
+
+ void codegen(JitAllocator *allocator,
+ const void **executable_ptr,
+ void **writable_ptr);
+
+ void codegen(char *buff, size_t len);
+
+ void register_metadata(const BeamCodeHeader *header);
+
+ ErtsCodePtr getCode(unsigned label);
+ ErtsCodePtr getLambda(unsigned index);
+
+ void *getCode(Label label) {
+ return BeamAssembler::getCode(label);
+ }
+
+ byte *getCode(char *labelName) {
+ return BeamAssembler::getCode(labelName);
+ }
+
+ void embed_vararg_rodata(const Span<ArgVal> &args, a64::Gp reg);
+
+ unsigned getCodeSize() {
+ ASSERT(code.hasBaseAddress());
+ return code.codeSize();
+ }
+
+ void copyCodeHeader(BeamCodeHeader *hdr);
+ BeamCodeHeader *getCodeHeader(void);
+ const ErtsCodeInfo *getOnLoad(void);
+
+ unsigned patchCatches(char *rw_base);
+ void patchLambda(char *rw_base, unsigned index, BeamInstr I);
+ void patchLiteral(char *rw_base, unsigned index, Eterm lit);
+ void patchImport(char *rw_base, unsigned index, BeamInstr I);
+ void patchStrings(char *rw_base, const byte *string);
+
+protected:
+ int getTypeUnion(const ArgSource &arg) const {
+ auto typeIndex =
+ arg.isRegister() ? arg.as<ArgRegister>().typeIndex() : 0;
+
+ ASSERT(typeIndex < beam->types.count);
+ return beam->types.entries[typeIndex].type_union;
+ }
+
+ auto getIntRange(const ArgSource &arg) const {
+ if (arg.isSmall()) {
+ Sint value = arg.as<ArgSmall>().getSigned();
+ return std::make_pair(value, value);
+ } else {
+ auto typeIndex =
+ arg.isRegister() ? arg.as<ArgRegister>().typeIndex() : 0;
+
+ ASSERT(typeIndex < beam->types.count);
+ const auto &entry = beam->types.entries[typeIndex];
+ ASSERT(entry.type_union & BEAM_TYPE_INTEGER);
+ return std::make_pair(entry.min, entry.max);
+ }
+ }
+
+ bool always_small(const ArgSource &arg) const {
+ if (arg.isSmall()) {
+ return true;
+ }
+
+ int type_union = getTypeUnion(arg);
+ if (type_union == BEAM_TYPE_INTEGER) {
+ auto [min, max] = getIntRange(arg);
+ return min <= max;
+ } else {
+ return false;
+ }
+ }
+
+ bool always_immediate(const ArgSource &arg) const {
+ if (arg.isImmed() || always_small(arg)) {
+ return true;
+ }
+
+ int type_union = getTypeUnion(arg);
+ return (type_union & BEAM_TYPE_MASK_ALWAYS_IMMEDIATE) == type_union;
+ }
+
+ bool always_same_types(const ArgSource &lhs, const ArgSource &rhs) const {
+ int lhs_types = getTypeUnion(lhs);
+ int rhs_types = getTypeUnion(rhs);
+
+ /* We can only be certain that the types are the same when there's
+ * one possible type. For example, if one is a number and the other
+ * is an integer, they could differ if the former is a float. */
+ if ((lhs_types & (lhs_types - 1)) == 0) {
+ return lhs_types == rhs_types;
+ }
+
+ return false;
+ }
+
+ bool always_one_of(const ArgSource &arg, int types) const {
+ if (arg.isImmed()) {
+ if (arg.isSmall()) {
+ return !!(types & BEAM_TYPE_INTEGER);
+ } else if (arg.isAtom()) {
+ return !!(types & BEAM_TYPE_ATOM);
+ } else if (arg.isNil()) {
+ return !!(types & BEAM_TYPE_NIL);
+ }
+
+ return false;
+ } else {
+ int type_union = getTypeUnion(arg);
+ return type_union == (type_union & types);
+ }
+ }
+
+ int masked_types(const ArgSource &arg, int mask) const {
+ if (arg.isImmed()) {
+ if (arg.isSmall()) {
+ return mask & BEAM_TYPE_INTEGER;
+ } else if (arg.isAtom()) {
+ return mask & BEAM_TYPE_ATOM;
+ } else if (arg.isNil()) {
+ return mask & BEAM_TYPE_NIL;
+ }
+
+ return BEAM_TYPE_NONE;
+ } else {
+ return getTypeUnion(arg) & mask;
+ }
+ }
+
+ bool exact_type(const ArgSource &arg, int type_id) const {
+ return always_one_of(arg, type_id);
+ }
+
+ bool is_sum_small(const ArgSource &LHS, const ArgSource &RHS) {
+ if (!(always_small(LHS) && always_small(RHS))) {
+ return false;
+ } else {
+ Sint min, max;
+ auto [min1, max1] = getIntRange(LHS);
+ auto [min2, max2] = getIntRange(RHS);
+ min = min1 + min2;
+ max = max1 + max2;
+ return IS_SSMALL(min) && IS_SSMALL(max);
+ }
+ }
+
+ bool is_difference_small(const ArgSource &LHS, const ArgSource &RHS) {
+ if (!(always_small(LHS) && always_small(RHS))) {
+ return false;
+ } else {
+ Sint min, max;
+ auto [min1, max1] = getIntRange(LHS);
+ auto [min2, max2] = getIntRange(RHS);
+ min = min1 - max2;
+ max = max1 - min2;
+ return IS_SSMALL(min) && IS_SSMALL(max);
+ }
+ }
+
+ bool is_product_small(const ArgSource &LHS, const ArgSource &RHS) {
+ if (!(always_small(LHS) && always_small(RHS))) {
+ return false;
+ } else {
+ auto [min1, max1] = getIntRange(LHS);
+ auto [min2, max2] = getIntRange(RHS);
+ auto mag1 = std::max(std::abs(min1), std::abs(max1));
+ auto mag2 = std::max(std::abs(min2), std::abs(max2));
+
+ /*
+ * mag1 * mag2 <= MAX_SMALL
+ * mag1 <= MAX_SMALL / mag2 (when mag2 != 0)
+ */
+ ERTS_CT_ASSERT(MAX_SMALL < -MIN_SMALL);
+ return mag2 == 0 || mag1 <= MAX_SMALL / mag2;
+ }
+ }
+
+ bool is_bsl_small(const ArgSource &LHS, const ArgSource &RHS) {
+ /*
+ * In the code compiled by scripts/diffable, there never
+ * seems to be any range information for the RHS. Therefore,
+ * don't bother unless RHS is an immediate small.
+ */
+ if (!(always_small(LHS) && RHS.isSmall())) {
+ return false;
+ } else {
+ auto [min1, max1] = getIntRange(LHS);
+ auto rhs_val = RHS.as<ArgSmall>().getSigned();
+
+ if (min1 < 0 || max1 == 0 || rhs_val < 0) {
+ return false;
+ }
+
+ return rhs_val < Support::clz(max1) - _TAG_IMMED1_SIZE;
+ }
+ }
+
+ /* Helpers */
+ void emit_gc_test(const ArgWord &Stack,
+ const ArgWord &Heap,
+ const ArgWord &Live);
+ void emit_gc_test_preserve(const ArgWord &Need,
+ const ArgWord &Live,
+ arm::Gp term);
+
+ arm::Mem emit_variable_apply(bool includeI);
+ arm::Mem emit_fixed_apply(const ArgWord &arity, bool includeI);
+
+ arm::Gp emit_call_fun(bool skip_box_test = false,
+ bool skip_fun_test = false,
+ bool skip_arity_test = false);
+
+ arm::Gp emit_is_binary(const ArgLabel &Fail,
+ const ArgSource &Src,
+ Label next,
+ Label subbin);
+
+ void emit_is_boxed(Label Fail, arm::Gp Src) {
+ BeamAssembler::emit_is_boxed(Fail, Src);
+ }
+
+ void emit_is_boxed(Label Fail, const ArgVal &Arg, arm::Gp Src) {
+ if (always_one_of(Arg, BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("skipped box test since argument is always boxed");
+ return;
+ }
+
+ BeamAssembler::emit_is_boxed(Fail, Src);
+ }
+
+ void emit_get_list(const arm::Gp boxed_ptr,
+ const ArgRegister &Hd,
+ const ArgRegister &Tl);
+
+ void emit_div_rem(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ErtsCodeMFA *error_mfa,
+ const ArgRegister &Quotient,
+ const ArgRegister &Remainder,
+ bool need_div,
+ bool need_rem);
+
+ void emit_i_bif(const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst);
+
+ void emit_error(int code);
+
+ int emit_bs_get_field_size(const ArgSource &Size,
+ int unit,
+ Label Fail,
+ const arm::Gp &out);
+
+ void emit_bs_get_utf8(const ArgRegister &Ctx, const ArgLabel &Fail);
+ void emit_bs_get_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags);
+
+ void emit_raise_exception();
+ void emit_raise_exception(const ErtsCodeMFA *exp);
+ void emit_raise_exception(Label I, const ErtsCodeMFA *exp);
+
+ void emit_validate(const ArgWord &Arity);
+ void emit_bs_skip_bits(const ArgLabel &Fail, const ArgRegister &Ctx);
+
+ void emit_linear_search(arm::Gp val, Label fail, const Span<ArgVal> &args);
+
+ void emit_float_instr(uint32_t instId,
+ const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst);
+
+ void emit_validate_unicode(Label next, Label fail, arm::Gp value);
+
+ void emit_bif_is_eq_ne_exact_immed(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst,
+ Eterm fail_value,
+ Eterm succ_value);
+
+ void emit_proc_lc_unrequire(void);
+ void emit_proc_lc_require(void);
+
+ void emit_nyi(const char *msg);
+ void emit_nyi(void);
+
+ /* Returns a vector of the untagged and rebased `args`. The adjusted
+ * `comparand` is stored in ARG1. */
+ const std::vector<ArgVal> emit_select_untag(const Span<ArgVal> &args,
+ a64::Gp comparand,
+ Label fail,
+ UWord base,
+ int shift);
+
+ void emit_binsearch_nodes(arm::Gp reg,
+ size_t Left,
+ size_t Right,
+ Label fail,
+ const Span<ArgVal> &args);
+
+ bool emit_optimized_three_way_select(arm::Gp reg,
+ Label fail,
+ const Span<ArgVal> &args);
+
+#ifdef DEBUG
+ void emit_tuple_assertion(const ArgSource &Src, arm::Gp tuple_reg);
+#endif
+
+#include "beamasm_protos.h"
+
+ /* Resolves a BEAM label.
+ *
+ * When the branch type is not `dispUnknown`, this must be used
+ * _IMMEDIATELY BEFORE_ the instruction that the label is used in. */
+ const Label &resolve_beam_label(const ArgLabel &Label,
+ enum Displacement disp);
+ const Label &resolve_label(const Label &target,
+ enum Displacement disp,
+ const char *name = nullptr);
+
+ /* Resolves a shared fragment, creating a trampoline that loads the
+ * appropriate address before jumping there.
+ *
+ * When the branch type is not `dispUnknown`, this must be used
+ * _IMMEDIATELY BEFORE_ the instruction that the label is used in. */
+ const Label &resolve_fragment(void (*fragment)(), enum Displacement disp);
+
+ /* Embeds a constant argument and returns its address. All kinds of
+ * constants are accepted, including labels and export entries.
+ *
+ * When the branch type is not `dispUnknown`, this must be used
+ * _IMMEDIATELY BEFORE_ the instruction that the label is used in. */
+ arm::Mem embed_constant(const ArgVal &value, enum Displacement disp);
+
+ /* Convenience wrapper for embedding raw pointers or immediates. */
+ template<typename T,
+ std::enable_if_t<std::is_integral<T>::value ||
+ std::is_pointer<T>::value,
+ bool> = true>
+ arm::Mem embed_constant(T data, enum Displacement disp) {
+ return embed_constant(ArgWord((UWord)data), disp);
+ }
+
+ /* Binds a label and all related veneers that are within reach of it. */
+ void bind_veneer_target(const Label &target);
+
+ void emit_constant(const Constant &constant);
+ void emit_veneer(const Veneer &veneer);
+
+ /* Unconditionally emits all veneers and constants that are due within
+ * `range` bytes. */
+ void flush_pending_stubs(size_t range);
+
+ /* Emits pending veneers when appropriate. Must be called at least once
+ * every `STUB_CHECK_INTERVAL` bytes for veneers and constants to work. */
+ void check_pending_stubs();
+
+ /* Calls the given shared fragment, ensuring that the redzone is unused and
+ * that the return address forms a valid CP. */
+ template<typename Any>
+ void fragment_call(Any target) {
+ emit_assert_redzone_unused();
+
+#if defined(JIT_HARD_DEBUG)
+ /* Verify that the stack has not grown. */
+ Label next = a.newLabel();
+ a.ldr(SUPER_TMP, getInitialSPRef());
+ a.cmp(a64::sp, SUPER_TMP);
+ a.b_eq(next);
+ a.udf(0xdead);
+ a.bind(next);
+#endif
+
+ a.bl(resolve_fragment((void (*)())target, disp128MB));
+ }
+
+ template<typename T>
+ struct function_arity;
+ template<typename T, typename... Args>
+ struct function_arity<T(Args...)>
+ : std::integral_constant<int, sizeof...(Args)> {};
+
+ template<int expected_arity, typename T>
+ void runtime_call(T(*func)) {
+ static_assert(expected_arity == function_arity<T>());
+
+ a.bl(resolve_fragment((void (*)())func, disp128MB));
+ }
+
+ bool isRegisterBacked(const ArgVal &arg) {
+ if (arg.isXRegister()) {
+ return arg.as<ArgXRegister>().get() < num_register_backed_xregs;
+ } else if (arg.isFRegister()) {
+ return arg.as<ArgFRegister>().get() < num_register_backed_fregs;
+ }
+
+ return false;
+ }
+
+ template<typename RegType = arm::Gp>
+ struct Variable {
+ RegType reg;
+ arm::Mem mem;
+
+ Variable(RegType _r) : Variable(_r, arm::Mem()) {
+ }
+ Variable(RegType _r, arm::Mem _mem) : reg(_r), mem(_mem) {
+ }
+ };
+
+ Variable<arm::Gp> init_destination(const ArgVal &arg, arm::Gp tmp) {
+ /* We don't support storing into GpW since their maximum displacement
+ * is 16K, which means we have to check stubs far more often. */
+ ASSERT(tmp.isGpX());
+
+ if (isRegisterBacked(arg)) {
+ auto index = arg.as<ArgXRegister>().get();
+ return Variable(register_backed_xregs[index]);
+ } else {
+ return Variable(tmp, getArgRef(arg));
+ }
+ }
+
+ Variable<arm::VecD> init_destination(const ArgVal &arg, arm::VecD tmp) {
+ if (isRegisterBacked(arg)) {
+ auto index = arg.as<ArgFRegister>().get();
+ return Variable(register_backed_fregs[index]);
+ } else {
+ return Variable(tmp, getArgRef(arg));
+ }
+ }
+
+ Variable<arm::Gp> load_source(const ArgVal &arg, arm::Gp tmp) {
+ /* We don't support loading into GpW since their maximum displacement
+ * is 16K, which means we have to check stubs far more often. */
+ ASSERT(tmp.isGpX());
+
+ if (arg.isLiteral()) {
+ a.ldr(tmp, embed_constant(arg, disp32K));
+ return Variable(tmp);
+ } else if (arg.isRegister()) {
+ if (isRegisterBacked(arg)) {
+ auto index = arg.as<ArgXRegister>().get();
+ return Variable(register_backed_xregs[index]);
+ }
+
+ auto ref = getArgRef(arg);
+ a.ldr(tmp, ref);
+ return Variable(tmp, ref);
+ } else {
+ if (arg.isImmed() || arg.isWord()) {
+ auto val = arg.isImmed() ? arg.as<ArgImmed>().get()
+ : arg.as<ArgWord>().get();
+
+ if (Support::isIntOrUInt32(val)) {
+ mov_imm(tmp, val);
+ return Variable(tmp);
+ }
+ }
+
+ a.ldr(tmp, embed_constant(arg, disp32K));
+ return Variable(tmp);
+ }
+ }
+
+ auto load_sources(const ArgVal &Src1,
+ arm::Gp tmp1,
+ const ArgVal &Src2,
+ arm::Gp tmp2) {
+ if (Src1.isRegister() && Src2.isRegister() && !isRegisterBacked(Src1) &&
+ !isRegisterBacked(Src2)) {
+ switch (ArgVal::memory_relation(Src1, Src2)) {
+ case ArgVal::Relation::consecutive:
+ safe_ldp(tmp1, tmp2, Src1, Src2);
+ return std::make_pair(Variable(tmp1, getArgRef(Src1)),
+ Variable(tmp2, getArgRef(Src2)));
+ case ArgVal::Relation::reverse_consecutive:
+ safe_ldp(tmp2, tmp1, Src2, Src1);
+ return std::make_pair(Variable(tmp1, getArgRef(Src1)),
+ Variable(tmp2, getArgRef(Src2)));
+ case ArgVal::Relation::none:
+ break;
+ }
+ }
+
+ return std::make_pair(load_source(Src1, tmp1), load_source(Src2, tmp2));
+ }
+
+ Variable<arm::VecD> load_source(const ArgVal &arg, arm::VecD tmp) {
+ if (isRegisterBacked(arg)) {
+ auto index = arg.as<ArgFRegister>().get();
+ return Variable<arm::VecD>(register_backed_fregs[index]);
+ }
+
+ a.ldr(tmp, getArgRef(arg));
+ return Variable<arm::VecD>(tmp);
+ }
+
+ template<typename Reg>
+ void mov_var(const Variable<Reg> &to, const Variable<Reg> &from) {
+ mov_var(to.reg, from);
+ }
+
+ template<typename Reg>
+ void mov_var(const Variable<Reg> &to, Reg from) {
+ if (to.reg != from) {
+ a.mov(to.reg, from);
+ }
+ }
+
+ template<typename Reg>
+ void mov_var(Reg to, const Variable<Reg> &from) {
+ if (to != from.reg) {
+ a.mov(to, from.reg);
+ }
+ }
+
+ template<typename Reg>
+ void flush_var(const Variable<Reg> &to) {
+ if (to.mem.hasBase()) {
+ a.str(to.reg, to.mem);
+ }
+ }
+
+ void flush_vars(const Variable<arm::Gp> &to1,
+ const Variable<arm::Gp> &to2) {
+ const arm::Mem &mem1 = to1.mem;
+ const arm::Mem &mem2 = to2.mem;
+
+ if (mem1.hasBaseReg() && mem2.hasBaseReg() &&
+ mem1.baseId() == mem2.baseId()) {
+ if (mem1.offset() + 8 == mem2.offset()) {
+ safe_stp(to1.reg, to2.reg, mem1);
+ return;
+ } else if (mem1.offset() == mem2.offset() + 8) {
+ safe_stp(to2.reg, to1.reg, mem2);
+ return;
+ }
+ }
+
+ /* Not possible to optimize with stp. */
+ flush_var(to1);
+ flush_var(to2);
+ }
+
+ void mov_arg(const ArgVal &To, const ArgVal &From) {
+ if (isRegisterBacked(To)) {
+ auto to = init_destination(To, SUPER_TMP);
+ auto from = load_source(From, to.reg);
+ mov_var(to, from);
+ flush_var(to);
+ } else {
+ auto from = load_source(From, SUPER_TMP);
+ auto to = init_destination(To, from.reg);
+ mov_var(to, from);
+ flush_var(to);
+ }
+ }
+
+ void mov_arg(const ArgVal &To, arm::Mem From) {
+ auto to = init_destination(To, SUPER_TMP);
+ a.ldr(to.reg, From);
+ flush_var(to);
+ }
+
+ void mov_arg(arm::Mem To, const ArgVal &From) {
+ auto from = load_source(From, SUPER_TMP);
+ auto to = Variable(from.reg, To);
+ flush_var(to);
+ }
+
+ void mov_arg(arm::Gp to, const ArgVal &from) {
+ auto r = load_source(from, to);
+ if (r.reg != to) {
+ a.mov(to, r.reg);
+ }
+ }
+
+ void mov_arg(const ArgVal &to, arm::Gp from) {
+ auto r = init_destination(to, from);
+ if (r.reg != from) {
+ a.mov(r.reg, from);
+ }
+ flush_var(r);
+ }
+
+ void cmp_arg(arm::Gp gp, const ArgVal &arg) {
+ if (arg.isImmed() || arg.isWord()) {
+ Sint val = arg.isImmed() ? arg.as<ArgImmed>().get()
+ : arg.as<ArgWord>().get();
+
+ if (Support::isUInt12(val)) {
+ a.cmp(gp, imm(val));
+ return;
+ } else if (Support::isUInt12(-val)) {
+ a.cmn(gp, imm(-val));
+ return;
+ }
+ }
+
+ mov_arg(SUPER_TMP, arg);
+ a.cmp(gp, SUPER_TMP);
+ }
+
+ void safe_stp(arm::Gp gp1,
+ arm::Gp gp2,
+ const ArgVal &Dst1,
+ const ArgVal &Dst2) {
+ ASSERT(ArgVal::memory_relation(Dst1, Dst2) ==
+ ArgVal::Relation::consecutive);
+ safe_stp(gp1, gp2, getArgRef(Dst1));
+ }
+
+ void safe_stp(arm::Gp gp1, arm::Gp gp2, arm::Mem mem) {
+ auto offset = mem.offset();
+
+ ASSERT(gp1.isGpX() && gp2.isGpX());
+
+ if (std::abs(offset) <= sizeof(Eterm) * MAX_LDP_STP_DISPLACEMENT) {
+ a.stp(gp1, gp2, mem);
+ } else if (std::abs(offset) <
+ sizeof(Eterm) * MAX_LDR_STR_DISPLACEMENT) {
+ /* Note that we used `<` instead of `<=`, as we're loading two
+ * elements rather than one. */
+ a.str(gp1, mem);
+ a.str(gp2, mem.cloneAdjusted(sizeof(Eterm)));
+ } else {
+ add(SUPER_TMP, arm::GpX(mem.baseId()), offset);
+ a.stp(gp1, gp2, arm::Mem(SUPER_TMP));
+ }
+ }
+
+ void safe_ldr(arm::Gp gp, arm::Mem mem) {
+ auto offset = mem.offset();
+
+ ASSERT(mem.hasBaseReg() && !mem.hasIndex());
+ ASSERT(gp.isGpX());
+
+ if (std::abs(offset) <= sizeof(Eterm) * MAX_LDR_STR_DISPLACEMENT) {
+ a.ldr(gp, mem);
+ } else {
+ add(SUPER_TMP, arm::GpX(mem.baseId()), offset);
+ a.ldr(gp, arm::Mem(SUPER_TMP));
+ }
+ }
+
+ void safe_ldp(arm::Gp gp1,
+ arm::Gp gp2,
+ const ArgVal &Src1,
+ const ArgVal &Src2) {
+ ASSERT(ArgVal::memory_relation(Src1, Src2) ==
+ ArgVal::Relation::consecutive);
+
+ safe_ldp(gp1, gp2, getArgRef(Src1));
+ }
+
+ void safe_ldp(arm::Gp gp1, arm::Gp gp2, arm::Mem mem) {
+ auto offset = mem.offset();
+
+ ASSERT(gp1.isGpX() && gp2.isGpX());
+ ASSERT(gp1 != gp2);
+
+ if (std::abs(offset) <= sizeof(Eterm) * MAX_LDP_STP_DISPLACEMENT) {
+ a.ldp(gp1, gp2, mem);
+ } else if (std::abs(offset) <
+ sizeof(Eterm) * MAX_LDR_STR_DISPLACEMENT) {
+ /* Note that we used `<` instead of `<=`, as we're loading two
+ * elements rather than one. */
+ a.ldr(gp1, mem);
+ a.ldr(gp2, mem.cloneAdjusted(sizeof(Eterm)));
+ } else {
+ add(SUPER_TMP, arm::GpX(mem.baseId()), offset);
+ a.ldp(gp1, gp2, arm::Mem(SUPER_TMP));
+ }
+ }
+};
+
+void beamasm_metadata_update(
+ std::string module_name,
+ ErtsCodePtr base_address,
+ size_t code_size,
+ const std::vector<BeamAssembler::AsmRange> &ranges);
+void beamasm_metadata_early_init();
+void beamasm_metadata_late_init();
diff --git a/erts/emulator/beam/jit/arm/beam_asm_global.cpp b/erts/emulator/beam/jit/arm/beam_asm_global.cpp
new file mode 100644
index 0000000000..5e4360a770
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/beam_asm_global.cpp
@@ -0,0 +1,349 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#define ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS
+#include "beam_asm.hpp"
+#undef ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS
+
+using namespace asmjit;
+
+extern "C"
+{
+#include "bif.h"
+#include "beam_common.h"
+}
+
+BeamGlobalAssembler::BeamGlobalAssembler(JitAllocator *allocator)
+ : BeamAssembler("beam_asm_global") {
+ labels.reserve(emitPtrs.size());
+
+ /* These labels are defined up-front so global functions can refer to each
+ * other freely without any order dependencies. */
+ for (auto val : labelNames) {
+ std::string name = "global::" + val.second;
+ labels[val.first] = a.newNamedLabel(name.c_str());
+ }
+
+ /* Emit all of the code and bind all of the labels */
+ for (auto val : emitPtrs) {
+ a.align(AlignMode::kCode, 8);
+ a.bind(labels[val.first]);
+ /* This funky syntax calls the function pointer within this instance
+ * of BeamGlobalAssembler */
+ (this->*val.second)();
+ }
+
+ {
+ /* We have no need of the module pointers as we use `getCode(...)` for
+ * everything. */
+ const void *_ignored_exec;
+ void *_ignored_rw;
+ _codegen(allocator, &_ignored_exec, &_ignored_rw);
+ }
+
+ std::vector<AsmRange> ranges;
+
+ ranges.reserve(emitPtrs.size());
+
+ for (auto val : emitPtrs) {
+ ErtsCodePtr start = (ErtsCodePtr)getCode(labels[val.first]);
+ ErtsCodePtr stop;
+
+ if (val.first + 1 < emitPtrs.size()) {
+ stop = (ErtsCodePtr)getCode(labels[(GlobalLabels)(val.first + 1)]);
+ } else {
+ stop = (ErtsCodePtr)((char *)getBaseAddress() + code.codeSize());
+ }
+
+ ranges.push_back({.start = start,
+ .stop = stop,
+ .name = code.labelEntry(labels[val.first])->name()});
+ }
+
+ beamasm_metadata_update("global",
+ (ErtsCodePtr)getBaseAddress(),
+ code.codeSize(),
+ ranges);
+
+ /* `this->get_xxx` are populated last to ensure that we crash if we use
+ * them instead of labels in global code. */
+ for (auto val : labelNames) {
+ ptrs[val.first] = (fptr)getCode(labels[val.first]);
+ }
+}
+
+/* ARG3 = (HTOP + S_RESERVED + bytes needed) !!
+ * ARG4 = Live registers */
+void BeamGlobalAssembler::emit_garbage_collect() {
+ emit_enter_runtime_frame();
+
+ /* Convert ARG3 to words needed and move it to the correct argument slot.
+ *
+ * Note that we cancel out the S_RESERVED that we added in the GC check, as
+ * the GC routines handle that separately and we don't want it to be added
+ * twice. */
+ a.sub(ARG2, ARG3, HTOP);
+ a.lsr(ARG2, ARG2, imm(3));
+ a.sub(ARG2, ARG2, imm(S_RESERVED));
+
+ /* Save our return address in c_p->i so we can tell where we crashed if we
+ * did so during GC. */
+ a.str(a64::x30, arm::Mem(c_p, offsetof(Process, i)));
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ a.mov(ARG1, c_p);
+ /* ARG2 is already loaded. */
+ load_x_reg_array(ARG3);
+ /* ARG4 (live registers) is already loaded. */
+ a.mov(ARG5, FCALLS);
+ runtime_call<5>(erts_garbage_collect_nobump);
+ a.sub(FCALLS, FCALLS, ARG1);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, state.value)));
+ a.tst(TMP1, imm(ERTS_PSFLG_EXITING));
+ a.b_ne(labels[do_schedule]);
+
+ a.ret(a64::x30);
+}
+
+/* Handles trapping to exports from C code, setting registers up in the same
+ * manner a normal call_ext instruction would so that save_calls, tracing, and
+ * so on will work.
+ *
+ * Our return address is on the stack as we always come here from a BIF, so we
+ * must pop it into LR (x30) to convert this into an ordinary call. The
+ * callee will then push LR to the stack in its prologue, cancelling this out.
+ *
+ * Assumes that c_p->current points into the MFA of an export entry. */
+void BeamGlobalAssembler::emit_bif_export_trap() {
+ int export_offset = offsetof(Export, info.mfa);
+
+ a.ldr(ARG1, arm::Mem(c_p, offsetof(Process, current)));
+ a.sub(ARG1, ARG1, export_offset);
+
+ emit_leave_erlang_frame();
+
+ branch(emit_setup_dispatchable_call(ARG1));
+}
+
+/* Handles export breakpoints, error handler, jump tracing, and so on.
+ *
+ * We must be careful with LR (x30) and the stack as this runs between the
+ * caller and callee, and the latter pushes LR to the stack as part of its
+ * prologue.
+ *
+ * ARG1 = export entry
+ */
+void BeamGlobalAssembler::emit_export_trampoline() {
+ Label call_bif = a.newLabel(), error_handler = a.newLabel(),
+ jump_trace = a.newLabel();
+
+ /* What are we supposed to do? */
+ a.ldr(TMP1, arm::Mem(ARG1, offsetof(Export, trampoline.common.op)));
+
+ /* We test the generic bp first as it is most likely to be triggered in a
+ * loop. */
+ a.cmp(TMP1, imm(op_i_generic_breakpoint));
+ a.b_eq(labels[generic_bp_global]);
+
+ a.cmp(TMP1, imm(op_call_bif_W));
+ a.b_eq(call_bif);
+
+ a.cmp(TMP1, imm(op_call_error_handler));
+ a.b_eq(error_handler);
+
+ a.cmp(TMP1, imm(op_trace_jump_W));
+ a.b_eq(jump_trace);
+
+ /* Must never happen. */
+ a.udf(0xffff);
+
+ a.bind(call_bif);
+ {
+ /* Emulate a `call_bif` instruction.
+ *
+ * Note that we don't check reductions: yielding here is very tricky
+ * and error-prone, and there's little point in doing so as we can only
+ * land here directly after being scheduled in. */
+ ssize_t func_offset = offsetof(Export, trampoline.bif.address);
+
+ lea(ARG2, arm::Mem(ARG1, offsetof(Export, info.mfa)));
+ a.ldr(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+ a.ldr(ARG4, arm::Mem(ARG1, func_offset));
+
+ /* `call_bif_shared` assumes that the return address has been pushed to
+ * the stack as part of the prologue, so we have to do that manually
+ * now. */
+ emit_enter_erlang_frame();
+ a.b(labels[call_bif_shared]);
+ }
+
+ a.bind(jump_trace);
+ {
+ a.ldr(TMP1, arm::Mem(ARG1, offsetof(Export, trampoline.trace.address)));
+ a.br(TMP1);
+ }
+
+ a.bind(error_handler);
+ {
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>();
+
+ lea(ARG2, arm::Mem(ARG1, offsetof(Export, info.mfa)));
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG3);
+ mov_imm(ARG4, am_undefined_function);
+ runtime_call<4>(call_error_handler);
+
+ /* If there is no error_handler, any number of X registers
+ * can be live. */
+ emit_leave_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ a.cbz(ARG1, labels[process_exit]);
+
+ branch(emit_setup_dispatchable_call(ARG1));
+ }
+}
+
+/*
+ * Get the error address implicitly by calling the shared fragment and using
+ * the return address as the error address.
+ */
+void BeamModuleAssembler::emit_raise_exception() {
+ emit_raise_exception(nullptr);
+}
+
+void BeamModuleAssembler::emit_raise_exception(const ErtsCodeMFA *exp) {
+ if (exp) {
+ a.ldr(ARG4, embed_constant(exp, disp32K));
+ } else {
+ a.mov(ARG4, ZERO);
+ }
+
+ fragment_call(ga->get_raise_exception());
+
+ /* `line` instructions need to know the latest offset that may throw an
+ * exception. See the `line` instruction for details. */
+ last_error_offset = a.offset();
+}
+
+void BeamModuleAssembler::emit_raise_exception(Label I,
+ const ErtsCodeMFA *exp) {
+ a.adr(ARG2, I);
+
+ if (exp) {
+ a.ldr(ARG4, embed_constant(exp, disp32K));
+ } else {
+ a.mov(ARG4, ZERO);
+ }
+
+ a.b(resolve_fragment(ga->get_raise_exception_shared(), disp128MB));
+}
+
+void BeamGlobalAssembler::emit_process_exit() {
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ mov_imm(ARG2, 0);
+ mov_imm(ARG4, 0);
+ load_x_reg_array(ARG3);
+ runtime_call<4>(handle_error);
+
+ emit_leave_runtime();
+
+ a.cbz(ARG1, labels[do_schedule]);
+ a.udf(0xdead);
+}
+
+/* You must have already done emit_leave_runtime_frame()! */
+void BeamGlobalAssembler::emit_raise_exception() {
+ a.mov(ARG2, a64::x30);
+ a.b(labels[raise_exception_shared]);
+}
+
+void BeamGlobalAssembler::emit_raise_exception_shared() {
+ Label crash = a.newLabel();
+
+ /* Push a fake CP to ensure that we can handle a topmost frame
+ * with `catch` and an instruction raising and exception.
+ *
+ * The fake CP is discarded by handle_error() before jumping to
+ * a catch handler, and is ignored as a duplicate in stack
+ * traces because it's equal to the error address. */
+ a.str(ARG2, arm::Mem(E, -8).pre());
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ /* The error address must be a valid CP or NULL. */
+ a.tst(ARG2, imm(_CPMASK));
+ a.b_ne(crash);
+
+ /* ARG2 and ARG4 must be set prior to jumping here! */
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG3);
+ runtime_call<4>(handle_error);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ a.cbz(ARG1, labels[do_schedule]);
+
+ /* XREG0 = THE_NON_VALUE
+ * XREG1 = class
+ * XREG2 = error reason/thrown value
+ * XREG3 = raw stacktrace. */
+ a.br(ARG1);
+
+ a.bind(crash);
+ a.udf(0xbad);
+}
+
+void BeamModuleAssembler::emit_proc_lc_unrequire(void) {
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ a.mov(ARG1, c_p);
+ mov_imm(ARG2, ERTS_PROC_LOCK_MAIN);
+ runtime_call<2>(erts_proc_lc_unrequire_lock);
+#endif
+}
+
+void BeamModuleAssembler::emit_proc_lc_require(void) {
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ a.mov(ARG1, c_p);
+ mov_imm(ARG2, ERTS_PROC_LOCK_MAIN);
+ runtime_call<4>(erts_proc_lc_require_lock);
+#endif
+}
+
+extern "C"
+{
+ /* GDB puts a breakpoint in this function.
+ *
+ * Has to be on another file than the caller as otherwise gcc may
+ * optimize away the call. */
+ void ERTS_NOINLINE __jit_debug_register_code(void);
+ void ERTS_NOINLINE __jit_debug_register_code(void) {
+ }
+}
diff --git a/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl b/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl
new file mode 100644
index 0000000000..f42d16e853
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl
@@ -0,0 +1,216 @@
+#!/usr/bin/env perl -W
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2022. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+use strict;
+
+# Please keep the names in the list in alphabetical order.
+my @beam_global_funcs = qw(
+ apply_fun_shared
+ arith_compare_shared
+ bif_nif_epilogue
+ bif_export_trap
+ bif_bit_size_body
+ bif_bit_size_guard
+ bif_byte_size_body
+ bif_byte_size_guard
+ bif_element_body_shared
+ bif_element_guard_shared
+ bif_is_eq_exact_shared
+ bif_is_ne_exact_shared
+ bif_tuple_size_body
+ bif_tuple_size_guard
+ bs_add_guard_shared
+ bs_add_body_shared
+ bs_bit_size_shared
+ bs_create_bin_error_shared
+ bs_get_tail_shared
+ bs_size_check_shared
+ call_bif_shared
+ call_light_bif_shared
+ call_nif_yield_helper
+ catch_end_shared
+ call_nif_early
+ call_nif_shared
+ check_float_error
+ debug_bp
+ dispatch_bif
+ dispatch_nif
+ dispatch_return
+ dispatch_save_calls
+ export_trampoline
+ fconv_shared
+ handle_and_error
+ handle_call_fun_error
+ handle_element_error_shared
+ handle_hd_error
+ handle_map_size_error
+ handle_not_error
+ handle_or_error
+ handle_tl_error
+ garbage_collect
+ generic_bp_global
+ generic_bp_local
+ i_band_body_shared
+ i_bnot_body_shared
+ i_bnot_guard_shared
+ i_bor_body_shared
+ i_bif_body_shared
+ i_bif_guard_shared
+ i_breakpoint_trampoline_shared
+ i_bsr_body_shared
+ i_bsl_body_shared
+ i_func_info_shared
+ i_get_map_element_shared
+ i_get_map_element_hash_shared
+ i_length_guard_shared
+ i_length_body_shared
+ i_loop_rec_shared
+ i_new_small_map_lit_shared
+ i_test_yield_shared
+ i_bxor_body_shared
+ int_div_rem_body_shared
+ int_div_rem_guard_shared
+ internal_hash_helper
+ minus_body_shared
+ new_map_shared
+ update_map_assoc_shared
+ unloaded_fun
+ plus_body_shared
+ process_exit
+ process_main
+ raise_exception
+ raise_exception_shared
+ times_body_shared
+ times_guard_shared
+ unary_minus_body_shared
+ update_map_exact_guard_shared
+ update_map_exact_body_shared
+ );
+
+
+# Labels exported from within process_main
+my @process_main_labels = qw(
+ context_switch
+ context_switch_simplified
+ do_schedule
+ );
+
+my $decl_enums =
+ gen_list(' %s,', @beam_global_funcs, '', @process_main_labels);
+
+my $decl_emit_funcs =
+ gen_list(' void emit_%s(void);', @beam_global_funcs);
+
+my $decl_get_funcs =
+ gen_list(' void (*get_%s(void))() { return get(%s); }',
+ @beam_global_funcs, '', @process_main_labels);
+
+my $decl_emitPtrs =
+ gen_list(' {%s, &BeamGlobalAssembler::emit_%s},', @beam_global_funcs);
+
+my $decl_label_names =
+ gen_list(' {%s, "%s"},', @beam_global_funcs, '', @process_main_labels);
+
+sub gen_list {
+ my ($format, @strings) = @_;
+ my $out = '';
+ foreach my $str (@strings) {
+ if ($str eq '') {
+ $out .= "\n";
+ }
+ else {
+ my $subst = $format;
+ $subst =~ s/%s/$str/g;
+ $out .= "$subst\n";
+ }
+ }
+ $out;
+}
+
+
+my $this_source_file = __FILE__;
+
+print <<END_OF_FILE;
+/*
+ * Warning: Do not edit this file.
+ * Auto-generated by $this_source_file.
+ */
+
+#ifndef _BEAM_ASM_GLOBAL_HPP
+#define _BEAM_ASM_GLOBAL_HPP
+
+
+class BeamGlobalAssembler : public BeamAssembler {
+ typedef void (BeamGlobalAssembler::*emitFptr)(void);
+ typedef void (*fptr)(void);
+
+ enum GlobalLabels : uint32_t {
+$decl_enums
+ };
+
+ static const std::map<GlobalLabels, const std::string> labelNames;
+ static const std::map<GlobalLabels, emitFptr> emitPtrs;
+ std::unordered_map<GlobalLabels, Label> labels;
+ std::unordered_map<GlobalLabels, fptr> ptrs;
+
+$decl_emit_funcs
+
+ template<typename T>
+ void emit_bitwise_fallback_body(T(*func_ptr), const ErtsCodeMFA *mfa);
+
+ void emit_i_length_common(Label fail, int state_size);
+
+ void emit_raise_badarg(const ErtsCodeMFA *mfa);
+
+ void emit_bif_bit_size_helper(Label fail);
+ void emit_bif_byte_size_helper(Label fail);
+ void emit_bif_element_helper(Label fail);
+ void emit_bif_tuple_size_helper(Label fail);
+
+ void emit_flatmap_get_element();
+ void emit_hashmap_get_element();
+
+public:
+ BeamGlobalAssembler(JitAllocator *allocator);
+
+ void (*get(GlobalLabels lbl))(void) {
+ ASSERT(ptrs[lbl]);
+ return ptrs[lbl];
+ }
+
+$decl_get_funcs
+};
+
+#ifdef ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS
+
+const std::map<BeamGlobalAssembler::GlobalLabels, BeamGlobalAssembler::emitFptr>
+BeamGlobalAssembler::emitPtrs = {
+$decl_emitPtrs
+};
+
+const std::map<BeamGlobalAssembler::GlobalLabels, const std::string>
+BeamGlobalAssembler::labelNames = {
+$decl_label_names
+};
+
+#endif /* ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS */
+
+#endif /* !_BEAM_ASM_GLOBAL_HPP */
+END_OF_FILE
diff --git a/erts/emulator/beam/jit/arm/beam_asm_module.cpp b/erts/emulator/beam/jit/arm/beam_asm_module.cpp
new file mode 100644
index 0000000000..3f2aa86a02
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/beam_asm_module.cpp
@@ -0,0 +1,837 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <algorithm>
+#include <sstream>
+#include <float.h>
+
+#include "beam_asm.hpp"
+using namespace asmjit;
+
+#ifdef BEAMASM_DUMP_SIZES
+# include <mutex>
+
+typedef std::pair<Uint64, Uint64> op_stats;
+
+static std::unordered_map<char *, op_stats> sizes;
+static std::mutex size_lock;
+
+extern "C" void beamasm_dump_sizes() {
+ std::lock_guard<std::mutex> lock(size_lock);
+
+ std::vector<std::pair<char *, op_stats>> flat(sizes.cbegin(), sizes.cend());
+ double total_size = 0.0;
+
+ for (const auto &op : flat) {
+ total_size += op.second.second;
+ }
+
+ /* Sort instructions by total size, in descending order. */
+ std::sort(
+ flat.begin(),
+ flat.end(),
+ [](std::pair<char *, op_stats> &a, std::pair<char *, op_stats> &b) {
+ return a.second.second > b.second.second;
+ });
+
+ for (const auto &op : flat) {
+ fprintf(stderr,
+ "%34s:\t%zu\t%f\t%zu\t%zu\r\n",
+ op.first,
+ op.second.second,
+ op.second.second / total_size,
+ op.second.first,
+ op.second.first ? (op.second.second / op.second.first) : 0);
+ }
+}
+#endif
+
+ErtsCodePtr BeamModuleAssembler::getCode(BeamLabel label) {
+ ASSERT(label < rawLabels.size() + 1);
+ return (ErtsCodePtr)getCode(rawLabels[label]);
+}
+
+ErtsCodePtr BeamModuleAssembler::getLambda(unsigned index) {
+ const auto &lambda = lambdas[index];
+ return (ErtsCodePtr)getCode(lambda.trampoline);
+}
+
+BeamModuleAssembler::BeamModuleAssembler(BeamGlobalAssembler *ga,
+ Eterm mod,
+ int num_labels,
+ int num_functions,
+ const BeamFile *file)
+ : BeamModuleAssembler(ga, mod, num_labels, file) {
+ _veneers.reserve(num_labels + 1);
+
+ code_header = a.newLabel();
+ a.align(AlignMode::kCode, 8);
+ a.bind(code_header);
+
+ embed_zeros(sizeof(BeamCodeHeader) +
+ sizeof(ErtsCodeInfo *) * num_functions);
+
+#ifdef DEBUG
+ last_stub_check_offset = a.offset();
+#endif
+}
+
+void BeamModuleAssembler::embed_vararg_rodata(const Span<ArgVal> &args,
+ a64::Gp reg) {
+ /* Short sequences are inlined in the .text section for slightly better
+ * speed. */
+ bool inlineData = args.size() <= 6;
+
+ Label data = a.newLabel(), next = a.newLabel();
+
+ if (inlineData) {
+ a.adr(reg, data);
+ a.b(next);
+ } else {
+ Label pointer = a.newLabel();
+
+ a.ldr(reg, arm::Mem(pointer));
+ a.b(next);
+
+ a.align(AlignMode::kCode, 8);
+ a.bind(pointer);
+ a.embedLabel(data, 8);
+
+ a.section(rodata);
+ }
+
+ a.align(AlignMode::kData, 8);
+ a.bind(data);
+
+ for (const ArgVal &arg : args) {
+ union {
+ BeamInstr as_beam;
+ char as_char[1];
+ } data;
+
+ a.align(AlignMode::kData, 8);
+ switch (arg.getType()) {
+ case ArgVal::Literal: {
+ auto &patches = literals[arg.as<ArgLiteral>().get()].patches;
+ Label patch = a.newLabel();
+
+ a.bind(patch);
+ a.embedUInt64(LLONG_MAX);
+ patches.push_back({patch, 0});
+ break;
+ }
+ case ArgVal::XReg:
+ data.as_beam = make_loader_x_reg(arg.as<ArgXRegister>().get());
+ a.embed(&data.as_char, sizeof(data.as_beam));
+ break;
+ case ArgVal::YReg:
+ data.as_beam = make_loader_y_reg(arg.as<ArgYRegister>().get());
+ a.embed(&data.as_char, sizeof(data.as_beam));
+ break;
+ case ArgVal::Label:
+ a.embedLabel(rawLabels[arg.as<ArgLabel>().get()]);
+ break;
+ case ArgVal::Immediate:
+ data.as_beam = arg.as<ArgImmed>().get();
+ a.embed(&data.as_char, sizeof(data.as_beam));
+ break;
+ case ArgVal::Word:
+ data.as_beam = arg.as<ArgWord>().get();
+ a.embed(&data.as_char, sizeof(data.as_beam));
+ break;
+ default:
+ ERTS_ASSERT(!"error");
+ }
+ }
+
+ if (!inlineData) {
+ a.section(code.textSection());
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_i_nif_padding() {
+ const size_t minimum_size = sizeof(UWord[BEAM_NATIVE_MIN_FUNC_SZ]);
+ size_t prev_func_start, diff;
+
+ prev_func_start = code.labelOffsetFromBase(rawLabels[functions.back() + 1]);
+ diff = a.offset() - prev_func_start;
+
+ if (diff < minimum_size) {
+ embed_zeros(minimum_size - diff);
+ }
+}
+
+void BeamGlobalAssembler::emit_i_breakpoint_trampoline_shared() {
+ constexpr ssize_t flag_offset =
+ sizeof(ErtsCodeInfo) + BEAM_ASM_FUNC_PROLOGUE_SIZE -
+ offsetof(ErtsCodeInfo, u.metadata.breakpoint_flag);
+
+ Label bp_and_nif = a.newLabel(), bp_only = a.newLabel(),
+ nif_only = a.newLabel();
+
+ a.ldrb(ARG1.w(), arm::Mem(a64::x30, -flag_offset));
+
+ a.cmp(ARG1, imm(ERTS_ASM_BP_FLAG_BP_NIF_CALL_NIF_EARLY));
+ a.b_eq(bp_and_nif);
+ ERTS_CT_ASSERT((1 << 0) == ERTS_ASM_BP_FLAG_CALL_NIF_EARLY);
+ a.tbnz(ARG1, imm(0), nif_only);
+ ERTS_CT_ASSERT((1 << 1) == ERTS_ASM_BP_FLAG_BP);
+ a.tbnz(ARG1, imm(1), bp_only);
+
+#ifndef DEBUG
+ a.ret(a64::x30);
+#else
+ Label error = a.newLabel();
+
+ /* ARG1 must be a valid breakpoint flag. */
+ a.cbnz(ARG1, error);
+ a.ret(a64::x30);
+
+ a.bind(error);
+ a.udf(0xBC0D);
+#endif
+
+ a.bind(bp_and_nif);
+ {
+ emit_enter_runtime_frame();
+ a.bl(labels[generic_bp_local]);
+ emit_leave_runtime_frame();
+
+ /* !! FALL THROUGH !! */
+ }
+
+ a.bind(nif_only);
+ {
+ /* call_nif_early returns on its own, unlike generic_bp_local. */
+ a.b(labels[call_nif_early]);
+ }
+
+ a.bind(bp_only);
+ {
+ emit_enter_runtime_frame();
+ a.bl(labels[generic_bp_local]);
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_i_breakpoint_trampoline() {
+ /* This little prologue is used by nif loading and tracing to insert
+ * alternative instructions. */
+ Label next = a.newLabel();
+
+ emit_enter_erlang_frame();
+
+ /* This branch is modified to jump to the BL instruction when the
+ * breakpoint is enabled. */
+ a.b(next);
+
+ if (code_header.isValid()) {
+ a.bl(resolve_fragment(ga->get_i_breakpoint_trampoline_shared(),
+ disp128MB));
+ } else {
+ /* NIF or BIF stub; we're not going to use this trampoline as-is, but
+ * we need to reserve space for it. */
+ a.udf(0xB1F);
+ }
+
+ a.bind(next);
+
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ BEAM_ASM_FUNC_PROLOGUE_SIZE);
+}
+
+static void i_emit_nyi(char *msg) {
+ erts_exit(ERTS_ERROR_EXIT, "NYI: %s\n", msg);
+}
+
+void BeamModuleAssembler::emit_nyi(const char *msg) {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, imm(msg));
+ runtime_call<1>(i_emit_nyi);
+
+ /* Never returns */
+}
+
+void BeamModuleAssembler::emit_nyi() {
+ emit_nyi("<unspecified>");
+}
+
+bool BeamModuleAssembler::emit(unsigned specific_op, const Span<ArgVal> &args) {
+ check_pending_stubs();
+
+#ifdef BEAMASM_DUMP_SIZES
+ size_t before = a.offset();
+#endif
+
+ comment(opc[specific_op].name);
+
+#define InstrCnt()
+ switch (specific_op) {
+#include "beamasm_emit.h"
+ default:
+ ERTS_ASSERT(0 && "Invalid instruction");
+ break;
+ }
+
+#ifdef BEAMASM_DUMP_SIZES
+ {
+ std::lock_guard<std::mutex> lock(size_lock);
+
+ sizes[opc[specific_op].name].first++;
+ sizes[opc[specific_op].name].second += a.offset() - before;
+ }
+#endif
+
+ return true;
+}
+
+/*
+ * Here follows meta instructions.
+ */
+
+void BeamGlobalAssembler::emit_i_func_info_shared() {
+ /* a64::x30 now points 4 bytes into the ErtsCodeInfo struct for the
+ * function. Put the address of the MFA into ARG1. */
+ a.add(ARG1, a64::x30, offsetof(ErtsCodeInfo, mfa) - 4);
+ mov_imm(TMP1, EXC_FUNCTION_CLAUSE);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.str(ARG1, arm::Mem(c_p, offsetof(Process, current)));
+
+ mov_imm(ARG2, 0);
+ mov_imm(ARG4, 0);
+
+ a.b(labels[raise_exception_shared]);
+}
+
+void BeamModuleAssembler::emit_i_func_info(const ArgWord &Label,
+ const ArgAtom &Module,
+ const ArgAtom &Function,
+ const ArgWord &Arity) {
+ ErtsCodeInfo info;
+
+ /* `op_i_func_info_IaaI` is used in various places in the emulator, so this
+ * label is always encoded as a word, even though the signature ought to
+ * be `op_i_func_info_LaaI`. */
+ functions.push_back(Label.get());
+
+ info.mfa.module = Module.get();
+ info.mfa.function = Function.get();
+ info.mfa.arity = Arity.get();
+ info.gen_bp = NULL;
+
+ comment("%T:%T/%d", info.mfa.module, info.mfa.function, info.mfa.arity);
+
+ /* This is an ErtsCodeInfo structure that has a valid ARM opcode as its `op`
+ * field, which *calls* the `raise_function_clause` fragment so we can trace
+ * it back to this particular function.
+ *
+ * We also use this field to store the current breakpoint flag, as ARM is a
+ * bit more strict about modifying code than x86: only branch instructions
+ * can be safely modified without issuing an ISB. By storing the flag here
+ * and reading it in the fragment, we don't have to change any code other
+ * than the branch instruction. */
+ if (code_header.isValid()) {
+ /* We avoid using the `fragment_call` helper to ensure a constant
+ * layout, as it adds code in certain debug configurations. */
+ a.bl(resolve_fragment(ga->get_i_func_info_shared(), disp128MB));
+ } else {
+ a.udf(0xF1F0);
+ }
+
+ ERTS_CT_ASSERT(ERTS_ASM_BP_FLAG_NONE == 0);
+ a.embedUInt32(0);
+
+ ASSERT(a.offset() % sizeof(UWord) == 0);
+ a.embed(&info.gen_bp, sizeof(info.gen_bp));
+ a.embed(&info.mfa, sizeof(info.mfa));
+}
+
+void BeamModuleAssembler::emit_label(const ArgLabel &Label) {
+ ASSERT(Label.isLabel());
+
+ current_label = rawLabels[Label.get()];
+ bind_veneer_target(current_label);
+}
+
+void BeamModuleAssembler::emit_aligned_label(const ArgLabel &Label,
+ const ArgWord &Alignment) {
+ a.align(AlignMode::kCode, Alignment.get());
+ emit_label(Label);
+}
+
+void BeamModuleAssembler::emit_on_load() {
+ on_load = current_label;
+}
+
+void BeamModuleAssembler::bind_veneer_target(const Label &target) {
+ auto veneer_range = _veneers.equal_range(target.id());
+ for (auto it = veneer_range.first; it != veneer_range.second; it++) {
+ const Veneer &veneer = it->second;
+
+ ASSERT(veneer.target == target);
+
+ if (!code.isLabelBound(veneer.anchor)) {
+ ASSERT(a.offset() <= veneer.latestOffset);
+ a.bind(veneer.anchor);
+
+ /* TODO: remove from pending stubs? */
+ }
+ }
+
+ a.bind(target);
+}
+
+void BeamModuleAssembler::emit_int_code_end() {
+ /* This label is used to figure out the end of the last function */
+ code_end = a.newLabel();
+ a.bind(code_end);
+
+ emit_nyi("int_code_end");
+
+ /* We emit the dispatch table before all remaining stubs to bind veneers
+ * directly in the table itself, avoiding a painful extra jump.
+ *
+ * Since the table is potentially very large, we'll emit all stubs that are
+ * due within it so we won't have to check on every iteration. */
+ flush_pending_stubs(_dispatchTable.size() * sizeof(Uint32[8]) +
+ dispUnknown);
+
+ for (auto pair : _dispatchTable) {
+ bind_veneer_target(pair.second);
+
+ a.mov(SUPER_TMP, imm(pair.first));
+ a.br(SUPER_TMP);
+ }
+
+ /* Emit all remaining stubs. */
+ flush_pending_stubs(dispMax);
+}
+
+void BeamModuleAssembler::emit_line(const ArgWord &Loc) {
+ /* There is no need to align the line instruction. In the loaded code, the
+ * type of the pointer will be void* and that pointer will only be used in
+ * comparisons.
+ *
+ * We only need to do something when there's a possibility of raising an
+ * exception at the very end of the preceding instruction (and thus
+ * pointing at the start of this one). If we were to do nothing, the error
+ * would erroneously refer to this instead of the preceding line.
+ *
+ * Since line addresses are taken _after_ line instructions we can avoid
+ * this by adding a nop when we detect this condition. */
+ if (a.offset() == last_error_offset) {
+ a.nop();
+ }
+}
+
+void BeamModuleAssembler::emit_func_line(const ArgWord &Loc) {
+ emit_line(Loc);
+}
+
+void BeamModuleAssembler::emit_empty_func_line() {
+}
+
+/*
+ * Here follows stubs for instructions that should never be called.
+ */
+
+void BeamModuleAssembler::emit_i_debug_breakpoint() {
+ emit_nyi("i_debug_breakpoint should never be called");
+}
+
+void BeamModuleAssembler::emit_i_generic_breakpoint() {
+ emit_nyi("i_generic_breakpoint should never be called");
+}
+
+void BeamModuleAssembler::emit_trace_jump(const ArgWord &) {
+ emit_nyi("trace_jump should never be called");
+}
+
+void BeamModuleAssembler::emit_call_error_handler() {
+ emit_nyi("call_error_handler should never be called");
+}
+
+unsigned BeamModuleAssembler::patchCatches(char *rw_base) {
+ unsigned catch_no = BEAM_CATCHES_NIL;
+
+ for (const auto &c : catches) {
+ const auto &patch = c.patch;
+ ErtsCodePtr handler;
+
+ handler = (ErtsCodePtr)getCode(c.handler);
+ catch_no = beam_catches_cons(handler, catch_no, nullptr);
+
+ /* Patch the `mov` instruction with the catch tag */
+ auto offset = code.labelOffsetFromBase(patch.where);
+ auto where = (Eterm *)&rw_base[offset];
+
+ ASSERT(LLONG_MAX == *where);
+ Eterm catch_term = make_catch(catch_no);
+
+ /* With the current tag scheme, more than 33 million
+ * catches can exist at once. */
+ ERTS_ASSERT(catch_term >> 31 == 0);
+
+ *where = catch_term;
+ }
+
+ return catch_no;
+}
+
+void BeamModuleAssembler::patchImport(char *rw_base,
+ unsigned index,
+ BeamInstr I) {
+ for (const auto &patch : imports[index].patches) {
+ auto offset = code.labelOffsetFromBase(patch.where);
+ auto where = (Eterm *)&rw_base[offset];
+
+ ASSERT(LLONG_MAX == *where);
+ *where = I + patch.val_offs;
+ }
+}
+
+void BeamModuleAssembler::patchLambda(char *rw_base,
+ unsigned index,
+ BeamInstr I) {
+ for (const auto &patch : lambdas[index].patches) {
+ auto offset = code.labelOffsetFromBase(patch.where);
+ auto where = (Eterm *)&rw_base[offset];
+
+ ASSERT(LLONG_MAX == *where);
+ *where = I + patch.val_offs;
+ }
+}
+
+void BeamModuleAssembler::patchLiteral(char *rw_base,
+ unsigned index,
+ Eterm lit) {
+ for (const auto &patch : literals[index].patches) {
+ auto offset = code.labelOffsetFromBase(patch.where);
+ auto where = (Eterm *)&rw_base[offset];
+
+ ASSERT(LLONG_MAX == *where);
+ *where = lit + patch.val_offs;
+ }
+}
+
+void BeamModuleAssembler::patchStrings(char *rw_base,
+ const byte *string_table) {
+ for (const auto &patch : strings) {
+ auto offset = code.labelOffsetFromBase(patch.where);
+ auto where = (const byte **)&rw_base[offset];
+
+ ASSERT(LLONG_MAX == (Eterm)*where);
+ *where = string_table + patch.val_offs;
+ }
+}
+
+const Label &BeamModuleAssembler::resolve_beam_label(const ArgLabel &Lbl,
+ enum Displacement disp) {
+ ASSERT(Lbl.isLabel());
+
+ const Label &beamLabel = rawLabels.at(Lbl.get());
+ const auto &labelEntry = code.labelEntry(beamLabel);
+
+ if (labelEntry->hasName()) {
+ return resolve_label(rawLabels.at(Lbl.get()), disp, labelEntry->name());
+ } else {
+ return resolve_label(rawLabels.at(Lbl.get()), disp);
+ }
+}
+
+const Label &BeamModuleAssembler::resolve_label(const Label &target,
+ enum Displacement disp,
+ const char *labelName) {
+ ssize_t currOffset = a.offset();
+
+ ssize_t minOffset = currOffset - disp;
+ ssize_t maxOffset = currOffset + disp;
+
+ ASSERT(disp >= dispMin && disp <= dispMax);
+ ASSERT(target.isValid());
+
+ if (code.isLabelBound(target)) {
+ ssize_t targetOffset = code.labelOffsetFromBase(target);
+
+ /* Backward reference: skip veneers if it's already in range. */
+ if (targetOffset >= minOffset) {
+ return target;
+ }
+ }
+
+ /* If a previously created veneer is reachable from this point, we can use
+ * it instead of creating a new one. */
+ auto range = _veneers.equal_range(target.id());
+ for (auto it = range.first; it != range.second; it++) {
+ const Veneer &veneer = it->second;
+
+ if (code.isLabelBound(veneer.anchor)) {
+ ssize_t veneerOffset = code.labelOffsetFromBase(veneer.anchor);
+
+ if (veneerOffset >= minOffset && veneerOffset <= maxOffset) {
+ return veneer.anchor;
+ }
+ } else if (veneer.latestOffset <= maxOffset) {
+ return veneer.anchor;
+ }
+ }
+
+ Label anchor;
+
+ if (!labelName) {
+ anchor = a.newLabel();
+ } else {
+ /* This is the entry label for a function. Create an unique
+ * name for the anchor label. It is necessary to include a
+ * sequence number in the label name because if the module is
+ * huge more than one veneer can be created for each entry
+ * label. */
+ std::stringstream name;
+ name << '@' << labelName << '-' << labelSeq++;
+ anchor = a.newNamedLabel(name.str().c_str());
+ }
+
+ auto it = _veneers.emplace(target.id(),
+ Veneer{.latestOffset = maxOffset,
+ .anchor = anchor,
+ .target = target});
+
+ const Veneer &veneer = it->second;
+ _pending_veneers.emplace(veneer);
+
+ return veneer.anchor;
+}
+
+const Label &BeamModuleAssembler::resolve_fragment(void (*fragment)(),
+ enum Displacement disp) {
+ auto it = _dispatchTable.find(fragment);
+
+ if (it == _dispatchTable.end()) {
+ it = _dispatchTable.emplace(fragment, a.newLabel()).first;
+ }
+
+ return resolve_label(it->second, disp);
+}
+
+arm::Mem BeamModuleAssembler::embed_constant(const ArgVal &value,
+ enum Displacement disp) {
+ ssize_t currOffset = a.offset();
+
+ ssize_t minOffset = currOffset - disp;
+ ssize_t maxOffset = currOffset + disp;
+
+ ASSERT(disp >= dispMin && disp <= dispMax);
+ ASSERT(!value.isRegister());
+
+ /* If a previously embedded constant is reachable from this point, we
+ * can use it instead of creating a new one. */
+ auto range = _constants.equal_range(value);
+ for (auto it = range.first; it != range.second; it++) {
+ const Constant &constant = it->second;
+
+ if (code.isLabelBound(constant.anchor)) {
+ ssize_t constOffset = code.labelOffsetFromBase(constant.anchor);
+
+ if (constOffset >= minOffset && constOffset <= maxOffset) {
+ return arm::Mem(constant.anchor);
+ }
+ } else if (constant.latestOffset <= maxOffset) {
+ return arm::Mem(constant.anchor);
+ }
+ }
+
+ auto it = _constants.emplace(value,
+ Constant{.latestOffset = maxOffset,
+ .anchor = a.newLabel(),
+ .value = value});
+
+ const Constant &constant = it->second;
+ _pending_constants.emplace(constant);
+
+ return arm::Mem(constant.anchor);
+}
+
+void BeamModuleAssembler::emit_i_flush_stubs() {
+ /* Flush all stubs that are due within the next two check intervals
+ * to prevent them from being emitted inside function prologues or
+ * NIF padding. */
+ flush_pending_stubs(STUB_CHECK_INTERVAL * 2);
+ last_stub_check_offset = a.offset();
+}
+
+void BeamModuleAssembler::check_pending_stubs() {
+ size_t currOffset = a.offset();
+
+ /* We shouldn't let too much space pass between checks. */
+ ASSERT((last_stub_check_offset + dispMin) >= currOffset);
+
+ if ((last_stub_check_offset + STUB_CHECK_INTERVAL) < currOffset) {
+ last_stub_check_offset = currOffset;
+
+ flush_pending_stubs(STUB_CHECK_INTERVAL * 2);
+ }
+}
+
+void BeamModuleAssembler::flush_pending_stubs(size_t range) {
+ size_t effective_offset;
+ Label next;
+
+ effective_offset = a.offset() + range;
+
+ while (!_pending_veneers.empty()) {
+ const Veneer &veneer = _pending_veneers.top();
+
+ if (veneer.latestOffset > effective_offset) {
+ break;
+ }
+
+ if (!code.isLabelBound(veneer.anchor)) {
+ if (!next.isValid()) {
+ next = a.newLabel();
+
+ comment("Begin stub section");
+ a.b(next);
+ }
+
+ emit_veneer(veneer);
+
+ effective_offset = a.offset() + range;
+ }
+
+ _pending_veneers.pop();
+ }
+
+ while (!_pending_constants.empty()) {
+ const Constant &constant = _pending_constants.top();
+
+ if (constant.latestOffset > effective_offset) {
+ break;
+ }
+
+ /* Unlike veneers, we never bind constants ahead of time. */
+ ASSERT(!code.isLabelBound(constant.anchor));
+
+ if (!next.isValid()) {
+ next = a.newLabel();
+
+ comment("Begin stub section");
+ a.b(next);
+ }
+
+ emit_constant(constant);
+
+ effective_offset = a.offset() + range;
+
+ _pending_constants.pop();
+ }
+
+ if (next.isValid()) {
+ comment("End stub section");
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_veneer(const Veneer &veneer) {
+ const Label &anchor = veneer.anchor;
+ const Label &target = veneer.target;
+ bool directBranch;
+
+ ASSERT(!code.isLabelBound(anchor));
+ a.bind(anchor);
+
+ /* Prefer direct branches when possible. */
+ if (code.isLabelBound(target)) {
+ auto targetOffset = code.labelOffsetFromBase(target);
+ directBranch = (a.offset() - targetOffset) <= disp128MB;
+ } else {
+ directBranch = false;
+ }
+
+#ifdef DEBUG
+ directBranch &= (a.offset() % 512) >= 256;
+#endif
+
+ if (ERTS_LIKELY(directBranch)) {
+ a.b(target);
+ } else {
+ Label pointer = a.newLabel();
+
+ a.ldr(SUPER_TMP, arm::Mem(pointer));
+ a.br(SUPER_TMP);
+
+ a.align(AlignMode::kCode, 8);
+ a.bind(pointer);
+ a.embedLabel(veneer.target);
+ }
+}
+
+void BeamModuleAssembler::emit_constant(const Constant &constant) {
+ const Label &anchor = constant.anchor;
+ const ArgVal &value = constant.value;
+
+ ASSERT(!code.isLabelBound(anchor));
+ a.align(AlignMode::kData, 8);
+ a.bind(anchor);
+
+ ASSERT(!value.isRegister());
+
+ if (value.isImmed()) {
+ a.embedUInt64(value.as<ArgImmed>().get());
+ } else if (value.isWord()) {
+ a.embedUInt64(value.as<ArgWord>().get());
+ } else if (value.isLabel()) {
+ a.embedLabel(rawLabels.at(value.as<ArgLabel>().get()));
+ } else {
+ a.embedUInt64(LLONG_MAX);
+
+ switch (value.getType()) {
+ case ArgVal::BytePtr:
+ strings.push_back({anchor, value.as<ArgBytePtr>().get()});
+ break;
+ case ArgVal::Catch: {
+ auto handler = rawLabels[value.as<ArgCatch>().get()];
+ catches.push_back({{anchor, 0}, handler});
+ break;
+ }
+ case ArgVal::Export: {
+ auto index = value.as<ArgExport>().get();
+ imports[index].patches.push_back({anchor, 0});
+ break;
+ }
+ case ArgVal::FunEntry: {
+ auto index = value.as<ArgLambda>().get();
+ lambdas[index].patches.push_back({anchor, 0});
+ break;
+ }
+ case ArgVal::Literal: {
+ auto index = value.as<ArgLiteral>().get();
+ literals[index].patches.push_back({anchor, 0});
+ break;
+ }
+ default:
+ ASSERT(!"error");
+ }
+ }
+}
diff --git a/erts/emulator/beam/jit/arm/generators.tab b/erts/emulator/beam/jit/arm/generators.tab
new file mode 100644
index 0000000000..b6ec48c678
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/generators.tab
@@ -0,0 +1,586 @@
+// -*- c -*-
+//
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2020-2022. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// %CopyrightEnd%
+//
+
+// Generate the fastest instruction to fetch an integer from a binary.
+gen.get_integer2(Fail, Ms, Live, Size, Unit, Flags, Dst) {
+ BeamOp* op;
+ UWord bits;
+
+ $NewBeamOp(S, op);
+ $NativeEndian(Flags);
+
+ if (Size.type == TAG_i) {
+ if (!beam_load_safe_mul(Size.val, Unit.val, &bits)) {
+ $BeamOpNameArity(op, jump, 1);
+ op->a[0] = Fail;
+
+ return op;
+ } else if (bits <= 1023) {
+ $BeamOpNameArity(op, i_bs_get_fixed_integer, 6);
+ op->a[0] = Ms;
+ op->a[1] = Fail;
+ op->a[2] = Live;
+ op->a[3].type = TAG_u;
+ op->a[3].val = Flags.val;
+ op->a[4].type = TAG_u;
+ op->a[4].val = bits;
+ op->a[5] = Dst;
+
+ return op;
+ }
+ }
+
+ $BeamOpNameArity(op, i_bs_get_integer, 6);
+ op->a[0] = Ms;
+ op->a[1] = Fail;
+ op->a[2] = Live;
+ op->a[3].type = TAG_u;
+ op->a[3].val = (Unit.val << 3) | Flags.val;
+ op->a[4] = Size;
+ op->a[5] = Dst;
+
+ return op;
+}
+
+gen.select_tuple_arity(Src, Fail, Size, Rest) {
+ BeamOp* op;
+ BeamOpArg *tmp;
+ int size = Size.val / 2;
+ int arity = Size.val + 3;
+ int i, j;
+
+ /* Verify the validity of the list. */
+ if (Size.val % 2 != 0) {
+ return NULL;
+ }
+
+ for (i = 0; i < Size.val; i += 2) {
+ if (Rest[i].type != TAG_u || Rest[i+1].type != TAG_f) {
+ return NULL;
+ }
+ }
+
+ /*
+ * Generate the generic instruction.
+ * Assumption:
+ * Few different tuple arities to select on (fewer than 20).
+ * Use linear scan approach.
+ */
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, i_select_tuple_arity, 3);
+ $BeamOpArity(op, arity);
+ op->next = NULL;
+ op->a[0] = Src;
+ op->a[1] = Fail;
+
+ /* Variable argument count */
+ op->a[2].type = TAG_u;
+ op->a[2].val = Size.val;
+
+ tmp = (BeamOpArg*)erts_alloc(ERTS_ALC_T_LOADER_TMP,
+ sizeof(BeamOpArg) * arity);
+
+ for (i = 3; i < arity; i += 2) {
+ tmp[i - 2] = Rest[i - 2];
+ tmp[i - 3].type = TAG_v;
+ tmp[i - 3].val = make_arityval_unchecked(Rest[i - 3].val);
+ }
+
+ /* Sort the values to make them useful for a binary or sentinel search. */
+ beam_load_sort_select_vals(tmp, size);
+
+ j = 3;
+ for (i = 3; i < arity; i += 2) {
+ op->a[j + size] = tmp[i - 2];
+ op->a[j] = tmp[i - 3];
+ j++;
+ }
+
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) tmp);
+
+ return op;
+}
+
+gen.split_values(Src, TypeFail, Fail, Size, Rest) {
+ BeamOp* op1;
+ BeamOp* op2;
+ BeamOp* is_integer;
+ int i;
+
+ ASSERT(Size.val >= 2 && Size.val % 2 == 0);
+
+ $NewBeamOp(S, is_integer);
+ $BeamOpNameArity(is_integer, is_integer, 2);
+ is_integer->a[0] = TypeFail;
+ is_integer->a[1] = Src;
+
+ $NewBeamOp(S, op1);
+ $BeamOpNameArity(op1, select_val, 3);
+ $BeamOpArity(op1, 3 + Size.val);
+ op1->a[0] = Src;
+ /* We use [] instead of a failure label to indicate a fallthrough
+ * to next instruction if none of the values match. That way, we
+ * don't have to create a new label dynamically, which would be
+ * tricky in BeamAsm. */
+ op1->a[1].type = TAG_n;
+ op1->a[1].val = 0;
+ op1->a[2].type = TAG_u;
+ op1->a[2].val = 0;
+
+ $NewBeamOp(S, op2);
+ $BeamOpNameArity(op2, select_val, 3);
+ $BeamOpArity(op2, 3 + Size.val);
+ op2->a[0] = Src;
+ op2->a[1] = Fail;
+ op2->a[2].type = TAG_u;
+ op2->a[2].val = 0;
+
+ /*
+ * Split the list.
+ */
+
+ ASSERT(Size.type == TAG_u);
+ for (i = 0; i < Size.val; i += 2) {
+ BeamOp* op = (Rest[i].type == TAG_q) ? op2 : op1;
+ int dst = 3 + op->a[2].val;
+
+ ASSERT(Rest[i+1].type == TAG_f);
+ op->a[dst] = Rest[i];
+ op->a[dst+1] = Rest[i+1];
+ op->arity += 2;
+ op->a[2].val += 2;
+ }
+ ASSERT(op1->a[2].val > 0);
+ ASSERT(op2->a[2].val > 0);
+
+ /*
+ * Order the instruction sequence appropriately.
+ */
+
+ if (TypeFail.val == Fail.val) {
+ /*
+ * select_val Src [] S ... (small numbers)
+ * is_integer Fail S
+ * select_val Src Fail S ... (bignums)
+ */
+ op1->next = is_integer;
+ is_integer->next = op2;
+ } else {
+ /*
+ * is_integer TypeFail S
+ * select_val Src [] S ... (small numbers)
+ * select_val Src Fail S ... (bignums)
+ */
+ is_integer->next = op1;
+ op1->next = op2;
+ op1 = is_integer;
+ }
+ op2->next = NULL;
+
+ return op1;
+}
+
+//
+// Generate a select_val instruction. We know that a jump table
+// is not suitable, and that all values are of the same type
+// (integer or atoms).
+//
+gen.select_val(Src, Fail, Size, Rest) {
+ BeamOp* op;
+ BeamOpArg *tmp;
+ int arity = Size.val + 3;
+ int size = Size.val / 2;
+ int i, j;
+
+ $NewBeamOp(S, op);
+ op->next = NULL;
+
+ /* Use linear search for small search spaces */
+ if (size <= 10) {
+ $BeamOpNameArity(op, i_select_val_lins, 3);
+ } else {
+ $BeamOpNameArity(op, i_select_val_bins, 3);
+ }
+
+ $BeamOpArity(op, arity);
+ op->a[0] = Src;
+ op->a[1] = Fail;
+
+ /* Variable argument count */
+ op->a[2].type = TAG_u;
+ op->a[2].val = Size.val;
+
+ tmp = (BeamOpArg *) erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(BeamOpArg)*(arity));
+
+ for (i = 3; i < arity; i++) {
+ tmp[i-3] = Rest[i-3];
+ }
+
+ /* Sort the values to make them useful for a binary or sentinel search. */
+ beam_load_sort_select_vals(tmp, size);
+
+ j = 3;
+ for (i = 3; i < arity; i += 2) {
+ op->a[j] = tmp[i-3];
+ op->a[j+size] = tmp[i-2];
+ j++;
+ }
+
+ erts_free(ERTS_ALC_T_LOADER_TMP, (void *) tmp);
+
+#ifdef DEBUG
+ for (i = 0; i < size - 1; i++) {
+ ASSERT(op->a[i+3].val <= op->a[i+4].val);
+ }
+#endif
+
+ return op;
+}
+
+//
+// Generate a select_val instruction for big numbers.
+//
+gen.select_literals(Src, Fail, Size, Rest) {
+ BeamOp* op;
+ BeamOp* jump;
+ BeamOp** prev_next = &op;
+
+ int i;
+
+ for (i = 0; i < Size.val; i += 2) {
+ BeamOp* op;
+ ASSERT(Rest[i].type == TAG_q);
+
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, is_ne_exact, 3);
+ op->a[0] = Rest[i+1];
+ op->a[1] = Src;
+ op->a[2] = Rest[i];
+ *prev_next = op;
+ prev_next = &op->next;
+ }
+
+ $NewBeamOp(S, jump);
+ $BeamOpNameArity(jump, jump, 1);
+ jump->next = NULL;
+ jump->a[0] = Fail;
+ *prev_next = jump;
+ return op;
+}
+
+gen.new_small_map_lit(Dst, Live, Size, Rest) {
+ unsigned size = Size.val;
+ Uint lit;
+ unsigned i;
+ BeamOp* op;
+ BeamOpArg* dst;
+ Eterm* tmp;
+ Eterm* thp;
+ Eterm keys;
+
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, i_new_small_map_lit, 4);
+ $BeamOpArity(op, 4 + size/2);
+ op->next = NULL;
+
+ tmp = thp = erts_alloc(ERTS_ALC_T_LOADER_TMP, ((size == 0 ? 0 : 1) + size/2) * sizeof(*tmp));
+ if (size == 0) {
+ keys = erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE);
+ } else {
+ keys = make_tuple(thp);
+ *thp++ = make_arityval(size/2);
+ }
+
+ dst = op->a+4;
+
+ for (i = 0; i < size; i += 2) {
+ switch (Rest[i].type) {
+ case TAG_a:
+ *thp++ = Rest[i].val;
+ ASSERT(is_atom(Rest[i].val));
+ break;
+ case TAG_i:
+ *thp++ = make_small(Rest[i].val);
+ break;
+ case TAG_n:
+ *thp++ = NIL;
+ break;
+ case TAG_q:
+ *thp++ = beamfile_get_literal(&S->beam, Rest[i].val);
+ break;
+ }
+ *dst++ = Rest[i + 1];
+ }
+
+ lit = beamfile_add_literal(&S->beam, keys);
+ erts_free(ERTS_ALC_T_LOADER_TMP, tmp);
+
+ op->a[0] = Dst;
+ op->a[1] = Live;
+ op->a[2].type = TAG_q;
+ op->a[2].val = lit;
+ op->a[3].type = TAG_u;
+ op->a[3].val = size / 2;
+
+ return op;
+}
+
+// Generate the fastest instruction to fetch a binary from a binary.
+gen.get_binary2(Fail, Ms, Live, Size, Unit, Flags, Dst) {
+ BeamOp* op;
+
+ $NewBeamOp(S, op);
+ $NativeEndian(Flags);
+
+ if (Size.type == TAG_a && Size.val == am_all) {
+ $BeamOpNameArity(op, i_bs_get_binary_all2, 5);
+ op->a[0] = Ms;
+ op->a[1] = Fail;
+ op->a[2] = Live;
+ op->a[3] = Unit;
+ op->a[4] = Dst;
+ } else {
+ $BeamOpNameArity(op, i_bs_get_binary2, 6);
+ op->a[0] = Ms;
+ op->a[1] = Fail;
+ op->a[2] = Live;
+ op->a[3] = Size;
+ op->a[4].type = TAG_u;
+ op->a[4].val = (Unit.val << 3) | Flags.val;
+ op->a[5] = Dst;
+ }
+
+ op->next = NULL;
+ return op;
+}
+
+gen.skip_utf16(Fail, Ms, Flags) {
+ BeamOp* op;
+ $NewBeamOp(S, op);
+
+ $NativeEndian(Flags);
+ $BeamOpNameArity(op, i_bs_skip_utf16, 3);
+ op->a[0] = Ms;
+ op->a[1] = Fail;
+ op->a[2] = Flags;
+ return op;
+}
+
+gen.allocate_heap_zero(Ns, Nh, Live) {
+ BeamOp* alloc;
+ BeamOp* init;
+ int i;
+
+ $NewBeamOp(S, alloc);
+ $NewBeamOp(S, init);
+
+ $BeamOpNameArity(alloc, allocate_heap, 3);
+ alloc->a[0] = Ns;
+ alloc->a[1] = Nh;
+ alloc->a[2] = Live;
+ alloc->next = init;
+
+ $BeamOpNameArity(init, init_yregs, 1);
+ $BeamOpArity(init, Ns.val+1);
+ init->a[0] = Ns;
+ for (i = 0; i < Ns.val; i++) {
+ init->a[i+1].type = TAG_y;
+ init->a[i+1].val = i;
+ }
+
+ return alloc;
+}
+
+gen.jump_tab(Src, Fail, Size, Rest) {
+ Sint min, max;
+ Sint i;
+ Sint size;
+ Sint arity;
+ int fixed_args;
+ BeamOp* op;
+
+ /*
+ * The rule in ops.tab must ensure that there are more than
+ * two values.
+ */
+ ASSERT(Size.val > 2);
+ ASSERT(Size.val % 2 == 0);
+
+ /* Calculate the minimum and maximum values and size of jump table. */
+ ASSERT(Rest[0].type == TAG_i);
+ min = max = Rest[0].val;
+ for (i = 2; i < Size.val; i += 2) {
+ ASSERT(Rest[i].type == TAG_i && Rest[i+1].type == TAG_f);
+ if (Rest[i].val < min) {
+ min = Rest[i].val;
+ } else if (max < Rest[i].val) {
+ max = Rest[i].val;
+ }
+ }
+ size = max - min + 1;
+
+ /* Allocate structure and fill in the fixed fields. */
+ $NewBeamOp(S, op);
+ op->next = NULL;
+ $BeamOpNameArity(op, i_jump_on_val, 4);
+ fixed_args = op->arity;
+ arity = fixed_args + size;
+ $BeamOpArity(op, arity);
+ op->a[0] = Src;
+ op->a[1] = Fail;
+ op->a[2].type = TAG_u;
+ op->a[2].val = min;
+ op->a[3].type = TAG_u;
+ op->a[3].val = size;
+
+ /* Fill in the jump table. */
+ for (i = fixed_args; i < arity; i++) {
+ op->a[i] = Fail;
+ }
+
+ for (i = 0; i < Size.val; i += 2) {
+ Sint index = fixed_args + Rest[i].val - min;
+ ASSERT(fixed_args <= index && index < arity);
+ op->a[index] = Rest[i+1];
+ }
+
+ return op;
+}
+
+gen.func_end(Func_Label, Entry_Label) {
+ BeamOp *op = NULL;
+
+ if (S->labels[Entry_Label.val].lambda_index != -1) {
+ int index = S->labels[Entry_Label.val].lambda_index;
+ BeamFile_LambdaEntry *lambda_entry;
+
+ lambda_entry = &S->beam.lambdas.entries[index];
+
+ if (lambda_entry->num_free > 0) {
+ BeamOp *lambda;
+
+ $NewBeamOp(S, lambda);
+ $BeamOpNameArity(lambda, i_lambda_trampoline, 4);
+
+ lambda->a[0].type = TAG_u;
+ lambda->a[0].val = index;
+ lambda->a[1] = Entry_Label;
+ lambda->a[2].type = TAG_u;
+ lambda->a[2].val = lambda_entry->arity;
+ lambda->a[3].type = TAG_u;
+ lambda->a[3].val = lambda_entry->num_free;
+
+ lambda->next = op;
+ op = lambda;
+ }
+ }
+
+ if (S->may_load_nif && (S->load_hdr->are_nifs == NULL ||
+ S->load_hdr->are_nifs[S->function_number-1])) {
+ BeamOp *padding;
+
+ $NewBeamOp(S, padding);
+ $BeamOpNameArity(padding, i_nif_padding, 0);
+
+ padding->next = op;
+ op = padding;
+ }
+
+ if (op == NULL) {
+ /* Workaround for the fact that we have to return an instruction from
+ * generators. The loader will remove this dummy instruction. */
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, delete_me, 0);
+
+ op->next = NULL;
+ }
+
+ return op;
+}
+
+gen.create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments) {
+ BeamOp* op;
+ int fixed_args;
+ int i;
+
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, i_bs_create_bin, 4);
+ fixed_args = op->arity;
+ $BeamOpArity(op, (N.val + fixed_args));
+
+ op->a[0] = Fail;
+ op->a[1] = Alloc;
+ op->a[2] = Live;
+ op->a[3] = Dst;
+
+ for (i = 0; i < N.val; i += 6) {
+ BeamOpArg Flags;
+ Uint flags = 0;
+
+ /* Copy all but flags. */
+ op->a[i+fixed_args+0] = Segments[i+0];
+ op->a[i+fixed_args+1] = Segments[i+1];
+ op->a[i+fixed_args+2] = Segments[i+2];
+ op->a[i+fixed_args+4] = Segments[i+4];
+ op->a[i+fixed_args+5] = Segments[i+5];
+
+ /* Translate flags. */
+ Flags = Segments[i+3]; /* Flags */
+ if (Flags.type != TAG_n) {
+ if (Flags.type == TAG_q) {
+ Eterm term = beamfile_get_literal(&S->beam, Flags.val);
+ while (is_list(term)) {
+ Eterm* consp = list_val(term);
+ Eterm elem = CAR(consp);
+ switch (elem) {
+ case am_little:
+ flags |= BSF_LITTLE;
+ break;
+ case am_native:
+ flags |= BSF_NATIVE;
+ break;
+ }
+ term = CDR(consp);
+ }
+ ASSERT(is_nil(term));
+ }
+ }
+ Flags.type = TAG_u;
+ Flags.val = flags;
+ $NativeEndian(Flags);
+ op->a[i+fixed_args+3] = Flags;
+ }
+
+ if (op->a[4].val == am_private_append && Alloc.val != 0) {
+ BeamOp* th;
+ $NewBeamOp(S, th);
+ $BeamOpNameArity(th, test_heap, 2);
+ th->a[0] = Alloc;
+ th->a[1] = Live;
+ th->next = op;
+
+ op->a[1].val = 0;
+
+ op = th;
+ }
+
+ return op;
+}
diff --git a/erts/emulator/beam/jit/arm/instr_arith.cpp b/erts/emulator/beam/jit/arm/instr_arith.cpp
new file mode 100644
index 0000000000..59c90b712a
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_arith.cpp
@@ -0,0 +1,1356 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "erl_bif_table.h"
+#include "big.h"
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_plus_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_Plus, 2};
+
+ Label error = a.newLabel();
+
+ /* Save original arguments for the error path. */
+ a.stp(ARG2, ARG3, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_plus);
+
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ /* emit_enter_runtime() was done in the module code. */
+ emit_leave_runtime(0);
+
+ /* Place the original arguments in X registers. */
+ a.ldp(XREG0, XREG1, TMP_MEM1q);
+ mov_imm(ARG4, &bif_mfa);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_i_plus(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ bool rhs_is_arm_literal =
+ RHS.isSmall() && Support::isUInt12(RHS.as<ArgSmall>().get());
+
+ if (is_sum_small(LHS, RHS)) {
+ auto dst = init_destination(Dst, ARG1);
+ if (rhs_is_arm_literal) {
+ auto lhs = load_source(LHS, ARG2);
+ Uint cleared_tag = RHS.as<ArgSmall>().get() & ~_TAG_IMMED1_MASK;
+ comment("add small constant without overflow check");
+ a.add(dst.reg, lhs.reg, imm(cleared_tag));
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ comment("addition without overflow check");
+ a.and_(TMP1, rhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.add(dst.reg, lhs.reg, TMP1);
+ }
+ flush_var(dst);
+ return;
+ }
+
+ Label next = a.newLabel();
+
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+
+ if (rhs_is_arm_literal) {
+ comment("add small constant with overflow check");
+ Uint cleared_tag = RHS.as<ArgSmall>().get() & ~_TAG_IMMED1_MASK;
+ a.adds(ARG1, lhs.reg, imm(cleared_tag));
+ } else {
+ comment("addition with overflow check");
+ a.and_(TMP1, rhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.adds(ARG1, lhs.reg, TMP1);
+ }
+
+ if (always_small(RHS)) {
+ a.and_(TMP1, lhs.reg, imm(_TAG_IMMED1_MASK));
+ } else if (always_small(LHS)) {
+ a.and_(TMP1, rhs.reg, imm(_TAG_IMMED1_MASK));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, lhs.reg, rhs.reg);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ }
+
+ /* Test for not overflow AND small operands. */
+ a.ccmp(TMP1,
+ imm(_TAG_IMMED1_SMALL),
+ imm(NZCV::kNone),
+ imm(arm::CondCode::kVC));
+ a.b_eq(next);
+
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_plus);
+ emit_leave_runtime(Live.get());
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_plus_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ a.bind(next);
+ mov_arg(Dst, ARG1);
+}
+
+/*
+ * ARG2 = Src
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_unary_minus_body_shared() {
+ Label error = a.newLabel();
+
+ /* Save original argument for the error path. */
+ a.str(ARG2, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_unary_minus);
+
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_Minus, 1};
+
+ /* emit_enter_runtime() was done in the module code. */
+ emit_leave_runtime(0);
+
+ /* Place the original argument in an X registers. */
+ a.ldr(XREG0, TMP_MEM1q);
+ mov_imm(ARG4, &bif_mfa);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_i_unary_minus(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Src,
+ const ArgRegister &Dst) {
+ auto src = load_source(Src, ARG2);
+
+ a.mov(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.and_(TMP2, src.reg, imm(~_TAG_IMMED1_MASK));
+
+ if (is_difference_small(ArgImmed(make_small(0)), Src)) {
+ auto dst = init_destination(Dst, ARG1);
+ comment("no overflow test because result is always small");
+ a.sub(dst.reg, TMP1, TMP2);
+ flush_var(dst);
+ return;
+ }
+
+ Label next = a.newLabel();
+
+ a.subs(ARG1, TMP1, TMP2);
+
+ /* Test for not overflow AND small operands. */
+ a.ccmp(TMP2,
+ imm(_TAG_IMMED1_SMALL),
+ imm(NZCV::kNone),
+ imm(arm::CondCode::kVC));
+ a.b_eq(next);
+
+ mov_var(ARG2, src);
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_unary_minus);
+ emit_leave_runtime(Live.get());
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_unary_minus_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ a.bind(next);
+ mov_arg(Dst, ARG1);
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_minus_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_Minus, 2};
+
+ Label error = a.newLabel();
+
+ /* Save original arguments for the error path. */
+ a.stp(ARG2, ARG3, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_minus);
+
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ /* emit_enter_runtime() was done in the module code. */
+ emit_leave_runtime(0);
+
+ /* Place the original arguments in X registers. */
+ a.ldp(XREG0, XREG1, TMP_MEM1q);
+ mov_imm(ARG4, &bif_mfa);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_i_minus(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ bool rhs_is_arm_literal =
+ RHS.isSmall() && Support::isUInt12(RHS.as<ArgSmall>().get());
+
+ if (is_difference_small(LHS, RHS)) {
+ auto dst = init_destination(Dst, ARG1);
+ if (rhs_is_arm_literal) {
+ auto lhs = load_source(LHS, ARG2);
+ Uint cleared_tag = RHS.as<ArgSmall>().get() & ~_TAG_IMMED1_MASK;
+ comment("subtract small constant without overflow check");
+ a.sub(dst.reg, lhs.reg, imm(cleared_tag));
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ comment("subtraction without overflow check");
+ a.and_(TMP1, rhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.sub(dst.reg, lhs.reg, TMP1);
+ }
+ flush_var(dst);
+ return;
+ }
+
+ Label next = a.newLabel();
+
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+
+ if (rhs_is_arm_literal) {
+ comment("subtract small constant with overflow check");
+ Uint cleared_tag = RHS.as<ArgSmall>().get() & ~_TAG_IMMED1_MASK;
+ a.subs(ARG1, lhs.reg, imm(cleared_tag));
+ } else {
+ comment("subtraction with overflow check");
+ a.and_(TMP1, rhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.subs(ARG1, lhs.reg, TMP1);
+ }
+
+ if (always_small(RHS)) {
+ a.and_(TMP1, lhs.reg, imm(_TAG_IMMED1_MASK));
+ } else if (always_small(LHS)) {
+ a.and_(TMP1, rhs.reg, imm(_TAG_IMMED1_MASK));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, lhs.reg, rhs.reg);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ }
+
+ /* Test for not overflow AND small operands. */
+ a.ccmp(TMP1,
+ imm(_TAG_IMMED1_SMALL),
+ imm(NZCV::kNone),
+ imm(arm::CondCode::kVC));
+ a.b_eq(next);
+
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_minus);
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_minus_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ a.bind(next);
+ mov_arg(Dst, ARG1);
+}
+
+/* ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The result is returned in ARG1 (set to THE_NON_VALUE if
+ * the call failed).
+ */
+void BeamGlobalAssembler::emit_times_guard_shared() {
+ Label generic = a.newLabel();
+
+ /* Speculatively untag and multiply. */
+ a.and_(TMP1, ARG2, imm(~_TAG_IMMED1_MASK));
+ a.asr(TMP2, ARG3, imm(_TAG_IMMED1_SIZE));
+ a.mul(TMP3, TMP1, TMP2);
+ a.smulh(TMP4, TMP1, TMP2);
+
+ /* Check that both operands are small integers. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG2, ARG3);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+
+ /* The high 65 bits of result will all be the same if no overflow
+ * occurred. Another way to say that is that the sign bit of the
+ * low 64 bits repeated 64 times must be equal to the high 64 bits
+ * of the product. */
+ a.cmp(TMP4, TMP3, arm::asr(63));
+ a.b_ne(generic);
+
+ a.orr(ARG1, TMP3, imm(_TAG_IMMED1_SMALL));
+ a.ret(a64::x30);
+
+ a.bind(generic);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_times);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+/* ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_times_body_shared() {
+ Label generic = a.newLabel(), error = a.newLabel();
+
+ /* Speculatively untag and multiply. */
+ a.and_(TMP1, ARG2, imm(~_TAG_IMMED1_MASK));
+ a.asr(TMP2, ARG3, imm(_TAG_IMMED1_SIZE));
+ a.mul(TMP3, TMP1, TMP2);
+ a.smulh(TMP4, TMP1, TMP2);
+
+ /* Check that both operands are integers. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG2, ARG3);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+
+ /* The high 65 bits of result will all be the same if no overflow
+ * occurred. Another way to say that is that the sign bit of the
+ * low 64 bits repeated 64 times must be equal to the high 64 bits
+ * of the product. */
+ a.cmp(TMP4, TMP3, arm::asr(63));
+ a.b_ne(generic);
+
+ a.orr(ARG1, TMP3, imm(_TAG_IMMED1_SMALL));
+ a.ret(a64::x30);
+
+ a.bind(generic);
+
+ /* Save original arguments for the error path. */
+ a.stp(ARG2, ARG3, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_times);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_Times, 2};
+
+ /* Place the original arguments in x-registers. */
+ a.ldp(XREG0, XREG1, TMP_MEM1q);
+ mov_imm(ARG4, &bif_mfa);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_i_times(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ if (is_product_small(LHS, RHS)) {
+ auto dst = init_destination(Dst, ARG1);
+ comment("multiplication without overflow check");
+ if (RHS.isSmall()) {
+ auto lhs = load_source(LHS, ARG2);
+ a.and_(TMP1, lhs.reg, imm(~_TAG_IMMED1_MASK));
+ mov_imm(TMP2, RHS.as<ArgSmall>().getSigned());
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ a.and_(TMP1, lhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.asr(TMP2, rhs.reg, imm(_TAG_IMMED1_SIZE));
+ }
+ a.mul(dst.reg, TMP1, TMP2);
+ a.orr(dst.reg, dst.reg, imm(_TAG_IMMED1_SMALL));
+ flush_var(dst);
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ fragment_call(ga->get_times_guard_shared());
+ emit_branch_if_not_value(ARG1,
+ resolve_beam_label(Fail, dispUnknown));
+ } else {
+ fragment_call(ga->get_times_body_shared());
+ }
+
+ mov_arg(Dst, ARG1);
+ }
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * Quotient is returned in ARG1, remainder in ARG2.
+ * Error is indicated by the Z flag.
+ */
+void BeamGlobalAssembler::emit_int_div_rem_guard_shared() {
+ Label exit = a.newLabel(), generic = a.newLabel();
+
+ /* Speculatively go ahead with the division. */
+ a.asr(TMP1, ARG2, imm(_TAG_IMMED1_SIZE));
+ a.asr(TMP2, ARG3, imm(_TAG_IMMED1_SIZE));
+ a.sdiv(TMP3, TMP1, TMP2);
+ a.msub(TMP4, TMP3, TMP2, TMP1);
+
+ a.cmp(ARG3, imm(make_small(0)));
+ a.b_eq(exit);
+
+ /* Check whether both operands are small integers. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG2, ARG3);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+
+ /* MIN_SMALL divided by -1 will overflow, and we'll need to fall
+ * back to the generic handler in that case. */
+ a.asr(TMP1, TMP3, imm(SMALL_BITS - 1));
+ a.cmp(TMP1, imm(1));
+ a.b_ge(generic);
+
+ /* The Z flag is now clear (meaning no error). */
+
+ mov_imm(TMP1, _TAG_IMMED1_SMALL);
+ arm::Shift tagShift = arm::lsl(_TAG_IMMED1_SIZE);
+ a.orr(ARG1, TMP1, TMP3, tagShift);
+ a.orr(ARG2, TMP1, TMP4, tagShift);
+
+ a.bind(exit);
+ { a.ret(a64::x30); }
+
+ a.bind(generic);
+ {
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ lea(ARG4, TMP_MEM4q);
+ lea(ARG5, TMP_MEM5q);
+ runtime_call<5>(erts_int_div_rem);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.tst(ARG1, ARG1);
+ a.ldp(ARG1, ARG2, TMP_MEM4q);
+
+ a.ret(a64::x30);
+ }
+}
+
+/* ARG2 = LHS
+ * ARG3 = RHS
+ * ARG4 = error MFA
+ *
+ * Quotient is returned in ARG1, remainder in ARG2.
+ */
+void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
+ Label div_zero = a.newLabel(), generic_div = a.newLabel(),
+ generic_error = a.newLabel();
+
+ /* Speculatively go ahead with the division. */
+ a.asr(TMP1, ARG2, imm(_TAG_IMMED1_SIZE));
+ a.asr(TMP2, ARG3, imm(_TAG_IMMED1_SIZE));
+ a.sdiv(TMP3, TMP1, TMP2);
+ a.msub(TMP4, TMP3, TMP2, TMP1);
+
+ a.cmp(ARG3, imm(make_small(0)));
+ a.b_eq(div_zero);
+
+ /* Check whether both operands are small integers. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG2, ARG3);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic_div);
+
+ /* MIN_SMALL divided by -1 will overflow, and we'll need to fall
+ * back to the generic handler in that case. */
+ a.asr(TMP1, TMP3, imm(SMALL_BITS - 1));
+ a.cmp(TMP1, imm(1));
+ a.b_ge(generic_div);
+
+ mov_imm(TMP1, _TAG_IMMED1_SMALL);
+ arm::Shift tagShift = arm::lsl(_TAG_IMMED1_SIZE);
+ a.orr(ARG1, TMP1, TMP3, tagShift);
+ a.orr(ARG2, TMP1, TMP4, tagShift);
+
+ a.ret(a64::x30);
+
+ a.bind(generic_div);
+ {
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ /* Save MFA and original arguments for the error path. */
+ a.stp(ARG2, ARG3, TMP_MEM1q);
+ a.str(ARG4, TMP_MEM3q);
+
+ a.mov(ARG1, c_p);
+ lea(ARG4, TMP_MEM4q);
+ lea(ARG5, TMP_MEM5q);
+ runtime_call<5>(erts_int_div_rem);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.tst(ARG1, ARG1);
+ a.ldp(ARG1, ARG2, TMP_MEM4q);
+ a.b_eq(generic_error);
+
+ a.ret(a64::x30);
+ }
+
+ a.bind(div_zero);
+ {
+ mov_imm(TMP1, EXC_BADARITH);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.mov(XREG0, ARG2);
+ a.mov(XREG1, ARG3);
+ a.b(labels[raise_exception]);
+ }
+
+ a.bind(generic_error);
+ {
+ a.ldp(XREG0, XREG1, TMP_MEM1q);
+ a.ldr(ARG4, TMP_MEM3q); // MFA
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_div_rem(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ErtsCodeMFA *error_mfa,
+ const ArgRegister &Quotient,
+ const ArgRegister &Remainder,
+ bool need_div,
+ bool need_rem) {
+ Sint divisor = 0;
+
+ if (RHS.isSmall()) {
+ divisor = RHS.as<ArgSmall>().getSigned();
+ }
+
+ if (always_small(LHS) && divisor != (Sint)0 && divisor != (Sint)-1) {
+ auto lhs = load_source(LHS, ARG3);
+ auto quotient = init_destination(Quotient, ARG1);
+ auto remainder = init_destination(Remainder, ARG2);
+
+ comment("skipped test for smalls operands and overflow");
+ a.asr(TMP1, lhs.reg, imm(_TAG_IMMED1_SIZE));
+ mov_imm(TMP2, divisor);
+ a.sdiv(quotient.reg, TMP1, TMP2);
+ if (need_rem) {
+ a.msub(remainder.reg, quotient.reg, TMP2, TMP1);
+ }
+ mov_imm(TMP3, _TAG_IMMED1_SMALL);
+ arm::Shift tagShift = arm::lsl(_TAG_IMMED1_SIZE);
+
+ if (need_div) {
+ a.orr(quotient.reg, TMP3, quotient.reg, tagShift);
+ }
+ if (need_rem) {
+ a.orr(remainder.reg, TMP3, remainder.reg, tagShift);
+ }
+ if (need_div) {
+ flush_var(quotient);
+ }
+ if (need_rem) {
+ flush_var(remainder);
+ }
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ fragment_call(ga->get_int_div_rem_guard_shared());
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.mov(ARG4, imm(error_mfa));
+ fragment_call(ga->get_int_div_rem_body_shared());
+ }
+
+ if (need_div) {
+ mov_arg(Quotient, ARG1);
+ }
+ if (need_rem) {
+ mov_arg(Remainder, ARG2);
+ }
+ }
+}
+
+void BeamModuleAssembler::emit_i_rem_div(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Remainder,
+ const ArgRegister &Quotient) {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_rem, 2};
+ bool need_rem = Quotient != Remainder;
+
+ emit_div_rem(Fail, LHS, RHS, &bif_mfa, Quotient, Remainder, true, need_rem);
+}
+
+void BeamModuleAssembler::emit_i_div_rem(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Quotient,
+ const ArgRegister &Remainder) {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_div, 2};
+ bool need_div = Quotient != Remainder;
+
+ emit_div_rem(Fail, LHS, RHS, &bif_mfa, Quotient, Remainder, need_div, true);
+}
+
+void BeamModuleAssembler::emit_i_int_div(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Quotient) {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_div, 2};
+ ArgYRegister Dummy(0);
+
+ emit_div_rem(Fail, LHS, RHS, &bif_mfa, Quotient, Dummy, true, false);
+}
+
+void BeamModuleAssembler::emit_i_rem(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Remainder) {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_rem, 2};
+ ArgYRegister Dummy(0);
+
+ emit_div_rem(Fail, LHS, RHS, &bif_mfa, Dummy, Remainder, false, true);
+}
+
+void BeamModuleAssembler::emit_i_m_div(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_Div, 2};
+
+ Label next = a.newLabel();
+
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ emit_enter_runtime(Live.get());
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_div);
+
+ emit_leave_runtime(Live.get());
+
+ a.cmp(ARG1, imm(THE_NON_VALUE));
+
+ if (Fail.get() != 0) {
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.b_ne(next);
+
+ mov_arg(XREG0, LHS);
+ mov_arg(XREG1, RHS);
+
+ emit_raise_exception(&bif_mfa);
+ }
+
+ a.bind(next);
+ mov_arg(Dst, ARG1);
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+template<typename T>
+void BeamGlobalAssembler::emit_bitwise_fallback_body(T(*func_ptr),
+ const ErtsCodeMFA *mfa) {
+ Label error = a.newLabel();
+
+ emit_enter_runtime_frame();
+
+ /* Save original arguments for the error path. */
+ a.stp(ARG2, ARG3, TMP_MEM1q);
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(func_ptr);
+
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ /* emit_enter_runtime() was done in the module code. */
+ emit_leave_runtime(0);
+
+ /* Place the original arguments in X registers. */
+ a.ldp(XREG0, XREG1, TMP_MEM1q);
+ a.mov(ARG4, imm(mfa));
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamGlobalAssembler::emit_i_band_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_band, 2};
+ emit_bitwise_fallback_body(erts_band, &bif_mfa);
+}
+
+void BeamModuleAssembler::emit_i_band(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ auto dst = init_destination(Dst, ARG1);
+
+ /* TAG & TAG = TAG, so we don't need to tag it again. */
+ a.and_(ARG1, lhs.reg, rhs.reg);
+
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ } else {
+ Label next = a.newLabel();
+
+ /* All other term types has at least one zero in the low 4
+ * bits. Therefore, the result will be a small iff both operands
+ * are small. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG1, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_eq(next);
+
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_band);
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1,
+ resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_band_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ a.bind(next);
+ }
+
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * Result is returned in RET.
+ */
+void BeamGlobalAssembler::emit_i_bor_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_bor, 2};
+ emit_bitwise_fallback_body(erts_bor, &bif_mfa);
+}
+
+void BeamModuleAssembler::emit_i_bor(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ auto dst = init_destination(Dst, ARG1);
+
+ /* TAG | TAG = TAG, so we don't need to tag it again. */
+ a.orr(ARG1, lhs.reg, rhs.reg);
+
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ } else {
+ Label generic = a.newLabel(), next = a.newLabel();
+ if (always_small(RHS)) {
+ a.and_(TMP1, lhs.reg, imm(_TAG_IMMED1_MASK));
+ } else if (always_small(LHS)) {
+ a.and_(TMP1, rhs.reg, imm(_TAG_IMMED1_MASK));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, lhs.reg, rhs.reg);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ }
+
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_eq(next);
+
+ a.bind(generic);
+ {
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_bor);
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1,
+ resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_bor_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+ }
+
+ a.bind(next);
+ }
+
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_i_bxor_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_bxor, 2};
+ emit_bitwise_fallback_body(erts_bxor, &bif_mfa);
+}
+
+void BeamModuleAssembler::emit_i_bxor(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+
+ if (always_small(LHS) && always_small(RHS)) {
+ auto dst = init_destination(Dst, ARG1);
+ comment("skipped test for small operands because they are always "
+ "small");
+
+ /* TAG ^ TAG = 0, so we'll need to tag it again. */
+ a.eor(dst.reg, lhs.reg, rhs.reg);
+ a.orr(dst.reg, dst.reg, imm(_TAG_IMMED1_SMALL));
+ flush_var(dst);
+ return;
+ }
+
+ Label next = a.newLabel();
+ auto dst = init_destination(Dst, ARG1);
+
+ /* TAG ^ TAG = 0, so we'll need to tag it again. */
+ a.eor(ARG1, lhs.reg, rhs.reg);
+ a.orr(ARG1, ARG1, imm(_TAG_IMMED1_SMALL));
+
+ if (always_small(RHS)) {
+ a.and_(TMP1, lhs.reg, imm(_TAG_IMMED1_MASK));
+ } else if (always_small(LHS)) {
+ a.and_(TMP1, rhs.reg, imm(_TAG_IMMED1_MASK));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, lhs.reg, rhs.reg);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ }
+
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_eq(next);
+
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_bxor);
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_bxor_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ a.bind(next);
+ {
+ mov_var(dst, ARG1);
+ flush_var(dst);
+ }
+}
+
+/*
+ * ARG1 = Src
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1. Error is indicated by
+ * THE_NON_VALUE.
+ */
+void BeamGlobalAssembler::emit_i_bnot_guard_shared() {
+ emit_enter_runtime_frame();
+
+ /* Undo the speculative inversion in module code. */
+ a.eor(ARG2, ARG1, imm(~_TAG_IMMED1_MASK));
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_bnot);
+
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+/*
+ * ARG1 = Src
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_i_bnot_body_shared() {
+ Label error = a.newLabel();
+
+ emit_enter_runtime_frame();
+
+ /* Undo the speculative inversion in module code. */
+ a.eor(ARG2, ARG1, imm(~_TAG_IMMED1_MASK));
+
+ /* Save original arguments for the error path. */
+ a.str(ARG2, TMP_MEM1q);
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_bnot);
+
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_bnot, 1};
+
+ /* emit_enter_runtime() was done in the module code. */
+ emit_leave_runtime(0);
+
+ /* Place the original arguments in X registers. */
+ a.ldr(XREG0, TMP_MEM1q);
+ mov_imm(ARG4, &bif_mfa);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bnot(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Src,
+ const ArgRegister &Dst) {
+ Label next = a.newLabel();
+ auto src = load_source(Src, TMP2);
+ auto dst = init_destination(Dst, ARG1);
+
+ /* Invert everything except the tag so we don't have to tag it again. */
+ a.eor(ARG1, src.reg, imm(~_TAG_IMMED1_MASK));
+
+ if (always_one_of(Src, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operand since it is a number");
+ emit_is_boxed(next, Src, ARG1);
+ } else {
+ a.and_(TMP1, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_eq(next);
+ }
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_bnot_guard_shared());
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_bnot_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ a.bind(next);
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_i_bsr_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_bsr, 2};
+ emit_bitwise_fallback_body(erts_bsr, &bif_mfa);
+}
+
+void BeamModuleAssembler::emit_i_bsr(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ Label generic = a.newLabel(), next = a.newLabel();
+ auto lhs = load_source(LHS, ARG2);
+ auto dst = init_destination(Dst, ARG1);
+ bool need_generic = true;
+
+ if (RHS.isSmall()) {
+ Sint shift = RHS.as<ArgSmall>().getSigned();
+
+ if (shift >= 0 && shift < SMALL_BITS - 1) {
+ if (always_small(LHS)) {
+ comment("skipped test for small left operand because it is "
+ "always small");
+ need_generic = false;
+ } else if (always_one_of(LHS,
+ BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operand since it is a "
+ "number");
+ emit_is_not_boxed(generic, lhs.reg);
+ } else {
+ a.and_(TMP1, lhs.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+ }
+
+ /* We don't need to clear the mask after shifting because
+ * _TAG_IMMED1_SMALL will set all the bits anyway. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_MASK == _TAG_IMMED1_SMALL);
+ a.asr(TMP1, lhs.reg, imm(shift));
+ a.orr(dst.reg, TMP1, imm(_TAG_IMMED1_SMALL));
+
+ if (need_generic) {
+ a.b(next);
+ }
+ } else {
+ /* Constant shift is negative or too big to fit the `asr`
+ * instruction; fall back to the generic path. */
+ }
+ }
+
+ a.bind(generic);
+ if (need_generic) {
+ mov_var(ARG2, lhs);
+ mov_arg(ARG3, RHS);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_bsr);
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1,
+ resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_bsr_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ mov_var(dst, ARG1);
+ }
+
+ a.bind(next);
+ flush_var(dst);
+}
+
+/*
+ * ARG2 = LHS
+ * ARG3 = RHS
+ *
+ * The module code must have executed emit_enter_runtime()
+ * before calling this function.
+ *
+ * The result is returned in ARG1.
+ */
+void BeamGlobalAssembler::emit_i_bsl_body_shared() {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_bsl, 2};
+ emit_bitwise_fallback_body(erts_bsl, &bif_mfa);
+}
+
+static int count_leading_zeroes(UWord value) {
+ const int word_bits = sizeof(value) * CHAR_BIT;
+
+ if (value == 0) {
+ return word_bits;
+ }
+
+ return Support::clz(value);
+}
+
+void BeamModuleAssembler::emit_i_bsl(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ auto [lhs, rhs] = load_sources(LHS, ARG2, RHS, ARG3);
+ auto dst = init_destination(Dst, ARG1);
+
+ if (is_bsl_small(LHS, RHS)) {
+ comment("skipped tests because operands and result are always small");
+ a.and_(TMP1, lhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.lsl(TMP1, TMP1, imm(RHS.as<ArgSmall>().getSigned()));
+ a.orr(dst.reg, TMP1, imm(_TAG_IMMED1_SMALL));
+ flush_var(dst);
+ return;
+ }
+
+ Label generic = a.newLabel(), next = a.newLabel();
+ bool inline_shift = true;
+
+ if (LHS.isImmed() && RHS.isImmed()) {
+ /* The compiler should've optimized this away, so we'll fall
+ * back to the generic path to simplify the inline
+ * implementation. */
+ inline_shift = false;
+ } else if (LHS.isLiteral() || RHS.isLiteral()) {
+ /* At least one argument is not a small. */
+ inline_shift = false;
+ } else if (LHS.isImmed() && !LHS.isSmall()) {
+ /* Invalid constant. */
+ inline_shift = false;
+ } else if (RHS.isImmed() &&
+ (!RHS.isSmall() || RHS.as<ArgSmall>().getSigned() < 0 ||
+ RHS.as<ArgSmall>().getSigned() >= SMALL_BITS - 1)) {
+ /* Constant shift is invalid or always produces a bignum. */
+ inline_shift = false;
+ }
+
+ if (inline_shift) {
+ /* shiftLimit will be calculated as the number of leading sign
+ * bits not counting the sign bit. Note that this value is one
+ * lower than the number of leading zeros as used by the
+ * x86_64 JIT. */
+ Operand shiftLimit, shiftCount;
+
+ ASSERT(!(LHS.isImmed() && RHS.isImmed()));
+ if (LHS.isRegister()) {
+ /* Count the number of leading sign bits so we can test
+ * whether the shift will overflow. (The count does not
+ * include the sign bit.) To ensure that the tag bits are
+ * not counted, we must make sure that the topmost tag bit
+ * is equal to the inverted value of the sign bit. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.eor(TMP1, lhs.reg, lhs.reg, arm::lsr(64 - _TAG_IMMED1_SIZE));
+ a.cls(ARG4, TMP1);
+ shiftLimit = ARG4;
+
+ if (always_small(LHS)) {
+ comment("skipped test for small operand since it is always "
+ "small");
+ } else if (always_one_of(LHS,
+ BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operand since it is a "
+ "number");
+ emit_is_not_boxed(generic, TMP1);
+ } else {
+ a.and_(TMP1, lhs.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+ }
+ } else {
+ UWord value = LHS.as<ArgSmall>().get();
+
+ if (signed_val(value) < 0) {
+ value ^= ~(UWord)_TAG_IMMED1_MASK;
+ }
+
+ shiftLimit = imm(count_leading_zeroes(value) - 1);
+ }
+
+ if (RHS.isRegister()) {
+ /* Negate the tag bits and then rotate them out, forcing the
+ * comparison below to fail for non-smalls. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.eor(ARG5, rhs.reg, imm(_TAG_IMMED1_SMALL));
+ a.ror(ARG5, ARG5, imm(_TAG_IMMED1_SIZE));
+ shiftCount = ARG5;
+
+ /* Fall back to generic path when the shift magnitude is negative or
+ * greater than the leading zero count.
+ *
+ * The raw emit form is used since `shiftLimit` may be a register
+ * or immediate, and the `cmp` helper doesn't accept untyped
+ * `Operand`s. */
+ a.emit(a64::Inst::kIdCmp, ARG5, shiftLimit);
+ a.b_hi(generic);
+ } else {
+ ASSERT(!shiftLimit.isImm());
+
+ shiftCount = imm(RHS.as<ArgSmall>().getSigned());
+
+ a.emit(a64::Inst::kIdCmp, shiftLimit, shiftCount);
+ a.b_lo(generic);
+ }
+
+ a.and_(TMP1, lhs.reg, imm(~_TAG_IMMED1_MASK));
+ a.emit(a64::Inst::kIdLsl, TMP1, TMP1, shiftCount);
+ a.orr(dst.reg, TMP1, imm(_TAG_IMMED1_SMALL));
+
+ flush_var(dst);
+ a.b(next);
+ }
+
+ a.bind(generic);
+ {
+ mov_var(ARG2, lhs);
+ mov_var(ARG3, rhs);
+
+ if (Fail.get() != 0) {
+ emit_enter_runtime(Live.get());
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_bsl);
+ emit_leave_runtime(Live.get());
+ emit_branch_if_not_value(ARG1,
+ resolve_beam_label(Fail, dispUnknown));
+ } else {
+ emit_enter_runtime(Live.get());
+ fragment_call(ga->get_i_bsl_body_shared());
+ emit_leave_runtime(Live.get());
+ }
+
+ mov_var(dst, ARG1);
+ flush_var(dst);
+ }
+
+ a.bind(next);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_bif.cpp b/erts/emulator/beam/jit/arm/instr_bif.cpp
new file mode 100644
index 0000000000..43890fc9a5
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_bif.cpp
@@ -0,0 +1,995 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "beam_common.h"
+#include "code_ix.h"
+#include "erl_bif_table.h"
+#include "erl_nfunc_sched.h"
+#include "bif.h"
+#include "erl_msacc.h"
+}
+
+/* ARG2 = argument vector, ARG4 (!) = bif function pointer
+ *
+ * Result is returned in ARG1 (will be THE_NON_VALUE if the BIF call failed). */
+void BeamGlobalAssembler::emit_i_bif_guard_shared() {
+ /* We use the X register array for the arguments for the BIF. The
+ * actual contents of the first three X registers are kept safe in
+ * callee-saved machine registers (XREG0 through XREG2).
+ */
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 2);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ lea(ARG2, getXRef(0));
+ mov_imm(ARG3, 0);
+ runtime_call(ARG4, 3); /* ARG3 is never used by guard BIFs. */
+
+ emit_leave_runtime<Update::eReductions>();
+ emit_leave_runtime_frame();
+ a.ret(a64::x30);
+}
+
+/* ARG2 = argument vector, ARG4 (!) = bif function pointer
+ *
+ * Result is returned in RET. */
+void BeamGlobalAssembler::emit_i_bif_body_shared() {
+ Label error = a.newLabel();
+
+ /* See comment in emit_i_bif_guard_shared. */
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 2);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eReductions>();
+
+ /* Save current BIF for the error path. */
+ a.mov(ARG1, c_p);
+ lea(ARG2, getXRef(0));
+ a.str(ARG4, TMP_MEM1q);
+ mov_imm(ARG3, 0); /* ARG3 is never used by guard BIFs. */
+
+ runtime_call(ARG4, 3);
+ emit_branch_if_not_value(ARG1, error);
+
+ emit_leave_runtime<Update::eReductions>();
+
+ emit_leave_runtime_frame();
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ /* Find the correct MFA from the BIF's function address. */
+ a.ldr(ARG1, TMP_MEM1q);
+ runtime_call<1>(ubif2mfa);
+
+ /* The argument registers must be reloaded on error, as the machine
+ * registers may contain garbage, which will later be swapped into the
+ * register array in the `raise_exception` fragment. */
+ emit_leave_runtime<Update::eReductions | Update::eXRegs>(3);
+ emit_leave_runtime_frame();
+
+ a.mov(ARG4, ARG1);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bif1(const ArgSource &Src1,
+ const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
+ auto src1 = load_source(Src1, TMP1);
+
+ a.str(src1.reg, getXRef(0));
+
+ emit_i_bif(Fail, Bif, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bif2(const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
+ auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2);
+
+ a.stp(src1.reg, src2.reg, getXRef(0));
+
+ emit_i_bif(Fail, Bif, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bif3(const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgSource &Src3,
+ const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
+ auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2);
+ auto src3 = load_source(Src3, TMP3);
+
+ a.stp(src1.reg, src2.reg, getXRef(0));
+ a.str(src3.reg, getXRef(2));
+
+ emit_i_bif(Fail, Bif, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bif(const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
+ mov_arg(ARG4, Bif);
+
+ if (Fail.get() != 0) {
+ fragment_call(ga->get_i_bif_guard_shared());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ fragment_call(ga->get_i_bif_body_shared());
+ }
+
+ mov_arg(Dst, ARG1);
+}
+
+/*
+ * Emit code for guard BIFs that can't fail (e.g. is_list/1). We
+ * don't need to test for failure.
+ */
+
+void BeamModuleAssembler::emit_nofail_bif1(const ArgSource &Src1,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
+ auto src1 = load_source(Src1, TMP1);
+
+ a.str(src1.reg, getXRef(0));
+
+ mov_arg(ARG4, Bif);
+ fragment_call(ga->get_i_bif_guard_shared());
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_nofail_bif2(const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
+ auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2);
+
+ a.stp(src1.reg, src2.reg, getXRef(0));
+
+ mov_arg(ARG4, Bif);
+ fragment_call(ga->get_i_bif_guard_shared());
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_length_setup(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Src) {
+ mov_arg(TMP1, Src);
+ mov_imm(TMP2, make_small(0));
+
+ /* Store trap state after the currently live registers. There are
+ * 3 extra registers beyond the ordinary ones that we're free to
+ * use for whatever purpose. */
+ ERTS_CT_ASSERT(ERTS_X_REGS_ALLOCATED - MAX_REG >= 3);
+ mov_arg(ArgXRegister(Live.get() + 0), TMP1);
+ mov_arg(ArgXRegister(Live.get() + 1), TMP2);
+
+ /* Store original argument. This is only needed for exceptions and can be
+ * safely skipped in guards. */
+ if (Fail.get() == 0) {
+ mov_arg(ArgXRegister(Live.get() + 2), TMP1);
+ }
+}
+
+/* ARG2 = live registers, ARG3 = entry address
+ *
+ * Result is returned in RET. */
+void BeamGlobalAssembler::emit_i_length_common(Label fail, int state_size) {
+ Label trap_or_error = a.newLabel();
+
+ ASSERT(state_size >= 2 && state_size <= ERTS_X_REGS_ALLOCATED - MAX_REG);
+
+ /* Save arguments for error/trapping path. */
+ a.stp(ARG2, ARG3, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eReductions | Update::eXRegs>();
+
+ a.mov(ARG1, c_p);
+ lea(TMP1, getXRef(0));
+ a.add(ARG2, TMP1, ARG2, arm::lsl(3));
+ runtime_call<2>(erts_trapping_length_1);
+
+ emit_branch_if_not_value(ARG1, trap_or_error);
+
+ emit_leave_runtime<Update::eReductions | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+
+ a.bind(trap_or_error);
+ {
+ a.ldp(ARG2, ARG3, TMP_MEM1q);
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.cmp(TMP1, imm(TRAP));
+ a.b_ne(fail);
+
+ emit_leave_runtime<Update::eReductions | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ /* The trap state is stored in the registers above the current live
+ * ones, so we add the state size (in words) to keep it alive. */
+ a.add(ARG2, ARG2, imm(state_size));
+
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, current)));
+ a.str(ARG2, arm::Mem(c_p, offsetof(Process, arity)));
+
+ /* We'll find our way back through the entry address (ARG3). */
+ a.b(labels[context_switch_simplified]);
+ }
+}
+
+/* ARG2 = live registers, ARG3 = entry address
+ *
+ * Result is returned in RET. */
+void BeamGlobalAssembler::emit_i_length_body_shared() {
+ Label error = a.newLabel();
+ /* `state_size = 3` to include the original argument. */
+ emit_i_length_common(error, 3);
+
+ a.bind(error);
+ {
+ static const ErtsCodeMFA bif_mfa = {am_erlang, am_length, 1};
+
+ /* Move the original argument to x0. It's stored in the third word of
+ * the trap state. */
+ lea(TMP1, getXRef(0));
+ a.add(ARG2, TMP1, ARG2, arm::lsl(3));
+ a.ldr(TMP1, arm::Mem(ARG2, sizeof(Eterm[2])));
+
+ emit_leave_runtime<Update::eReductions | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ a.mov(XREG0, TMP1);
+
+ mov_imm(ARG4, &bif_mfa);
+ emit_raise_exception();
+ }
+}
+
+/* ARG2 = live registers, ARG3 = entry address
+ *
+ * Result is returned in ARG. Error is indicated by THE_NON_VALUE. */
+void BeamGlobalAssembler::emit_i_length_guard_shared() {
+ Label error = a.newLabel();
+
+ emit_i_length_common(error, 2);
+
+ a.bind(error);
+ {
+ emit_leave_runtime<Update::eReductions | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_i_length(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ Label entry = a.newLabel();
+
+ a.bind(entry);
+
+ mov_arg(ARG2, Live);
+ a.adr(ARG3, entry);
+ if (Fail.get() != 0) {
+ fragment_call(ga->get_i_length_guard_shared());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ fragment_call(ga->get_i_length_body_shared());
+ }
+
+ mov_arg(Dst, ARG1);
+}
+
+#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
+
+static Eterm debug_call_light_bif(Process *c_p,
+ Eterm *reg,
+ ErtsCodePtr I,
+ ErtsBifFunc vbf) {
+ Eterm result;
+
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ {
+ ERTS_CHK_MBUF_SZ(c_p);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ result = vbf(c_p, reg, I);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
+ ERTS_CHK_MBUF_SZ(c_p);
+
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ERTS_HOLE_CHECK(c_p);
+ }
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+
+ return result;
+}
+#endif
+
+/* It is important that the below code is as optimized as possible.
+ * When doing any changes, make sure to look at the estone bif_dispatch
+ * benchmark to make sure you don't introduce any regressions.
+ *
+ * ARG3 = entry
+ * ARG4 = export entry
+ * ARG8 = BIF pointer
+ */
+void BeamGlobalAssembler::emit_call_light_bif_shared() {
+ /* We use the HTOP, FCALLS, and XREG1 registers as they are not
+ * used on the runtime-stack and are caller save. */
+
+ arm::Mem entry_mem = TMP_MEM1q, export_mem = TMP_MEM2q,
+ mbuf_mem = TMP_MEM3q;
+
+ Label trace = a.newLabel(), yield = a.newLabel();
+
+ /* Spill everything we may need on the error and GC paths. */
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, mbuf)));
+ a.stp(ARG3, ARG4, TMP_MEM1q);
+ a.str(TMP1, mbuf_mem);
+
+ /* Check if we should trace this bif call or handle save_calls. Both
+ * variants dispatch through the export entry. */
+ a.ldr(TMP1.w(), arm::Mem(ARG4, offsetof(Export, is_bif_traced)));
+ a.cmp(TMP1, imm(0));
+ a.ccmp(active_code_ix,
+ imm(ERTS_SAVE_CALLS_CODE_IX),
+ imm(NZCV::kZF),
+ imm(arm::CondCode::kEQ));
+ a.b_eq(trace);
+
+ a.subs(FCALLS, FCALLS, imm(1));
+ a.b_le(yield);
+ {
+ Label check_bif_return = a.newLabel(), gc_after_bif_call = a.newLabel();
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>();
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ {
+ Label skip_msacc = a.newLabel();
+
+ a.ldr(TMP1, erts_msacc_cache);
+ a.cbz(TMP1, skip_msacc);
+
+ /* The values of the X registers are in the X register array, so we
+ * use XREG0 to save the entry pointer (ARG3) over this call. */
+ a.mov(XREG0, ARG3);
+
+ a.ldr(ARG1, erts_msacc_cache);
+ a.ldr(ARG2, arm::Mem(ARG4, offsetof(Export, info.mfa.module)));
+ a.mov(ARG3, ARG8);
+ runtime_call<3>(erts_msacc_set_bif_state);
+
+ a.mov(ARG8, ARG1);
+ a.mov(ARG3, XREG0);
+
+ a.bind(skip_msacc);
+ }
+#endif
+
+ {
+ /* Call the BIF proper. ARG3 and ARG8 have been set earlier. */
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+
+#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
+ a.mov(ARG4, ARG8);
+ runtime_call<4>(debug_call_light_bif);
+#else
+ runtime_call(ARG8, 3);
+#endif
+ }
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ {
+ Label skip_msacc = a.newLabel();
+
+ a.mov(XREG0, ARG1);
+
+ a.ldr(TMP1, erts_msacc_cache);
+ a.cbz(TMP1, skip_msacc);
+
+ lea(ARG1, erts_msacc_cache);
+ runtime_call<1>(erts_msacc_update_cache);
+
+ /* Set state to emulator if msacc has been enabled */
+ a.ldr(ARG1, erts_msacc_cache);
+ a.cbz(ARG1, skip_msacc);
+
+ mov_imm(ARG2, ERTS_MSACC_STATE_EMULATOR);
+ mov_imm(ARG3, 1);
+ runtime_call<3>(erts_msacc_set_state_m__);
+
+ a.bind(skip_msacc);
+ a.mov(ARG1, XREG0);
+ }
+#endif
+
+ /* We must update the active code index in case another process has
+ * loaded new code, as the result of this BIF may be observable on both
+ * ends.
+ *
+ * It doesn't matter whether the BIF modifies anything; if process A
+ * loads new code and calls erlang:monotonic_time/0 soon after, we'd
+ * break the illusion of atomic upgrades if process B still ran old code
+ * after seeing a later timestamp from its own call to
+ * erlang:monotonic_time/0. */
+ emit_leave_runtime<Update::eReductions | Update::eCodeIndex |
+ Update::eHeap | Update::eStack | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ /* ERTS_IS_GC_DESIRED_INTERNAL */
+ {
+ a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags)));
+ a.tst(TMP1, imm(F_FORCE_GC | F_DISABLE_GC));
+
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, bin_vheap_sz)));
+ a.ldr(TMP2, arm::Mem(c_p, offsetof(Process, off_heap.overhead)));
+
+ /* If neither F_FORCE_GC nor F_DISABLE_GC were set,
+ * test whether binary heap size should trigger GC.
+ *
+ * Otherwise, set the flags as if `off_heap.overhead > bin_vheap_sz`
+ * to force a GC. */
+ a.ccmp(TMP2, TMP1, imm(NZCV::kCF), imm(arm::CondCode::kEQ));
+
+ a.sub(TMP1, E, HTOP);
+ a.asr(TMP1, TMP1, imm(3));
+ a.ldr(TMP2, arm::Mem(c_p, offsetof(Process, mbuf_sz)));
+
+ /* If our binary heap size was small enough not to need a GC, check
+ * whether the heap fragment size is larger than the remaining heap
+ * size.
+ *
+ * Otherwise, set the flags as if it is to force a GC. */
+ a.ccmp(TMP1, TMP2, imm(NZCV::kVF), imm(arm::CondCode::kLS));
+ a.b_lt(gc_after_bif_call);
+ }
+
+ a.bind(check_bif_return);
+ {
+ Label error = a.newLabel(), trap = a.newLabel();
+
+ emit_branch_if_not_value(ARG1, trap);
+
+ a.mov(XREG0, ARG1);
+ a.ret(a64::x30);
+
+ a.bind(trap);
+ {
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ emit_branch_if_ne(TMP1, TRAP, error);
+
+ /* Push our return address to the Erlang stack and trap out.
+ *
+ * The BIF_TRAP macros all set up c_p->arity and c_p->current,
+ * so we can use a simplified context switch. */
+ emit_enter_erlang_frame();
+ a.ldr(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+ a.b(labels[context_switch_simplified]);
+ }
+
+ a.bind(error);
+ {
+ /* raise_exception_shared expects current PC in ARG2 and MFA in
+ * ARG4. */
+ a.ldp(ARG2, ARG4, entry_mem);
+ add(ARG4, ARG4, offsetof(Export, info.mfa));
+ a.b(labels[raise_exception_shared]);
+ }
+ }
+
+ a.bind(gc_after_bif_call);
+ {
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>();
+
+ a.mov(ARG3, ARG1);
+
+ a.mov(ARG1, c_p);
+ a.ldr(ARG2, mbuf_mem);
+ load_x_reg_array(ARG4);
+ a.ldr(ARG5, export_mem);
+ a.ldr(ARG5, arm::Mem(ARG5, offsetof(Export, info.mfa.arity)));
+ runtime_call<5>(erts_gc_after_bif_call_lhf);
+
+ emit_leave_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>();
+ emit_leave_runtime_frame();
+
+ a.b(check_bif_return);
+ }
+ }
+
+ a.bind(trace);
+ {
+ /* Call the export entry instead of the BIF. */
+ branch(emit_setup_dispatchable_call(ARG4));
+ }
+
+ a.bind(yield);
+ {
+ a.ldr(ARG2, arm::Mem(ARG4, offsetof(Export, info.mfa.arity)));
+ lea(ARG4, arm::Mem(ARG4, offsetof(Export, info.mfa)));
+ a.str(ARG2, arm::Mem(c_p, offsetof(Process, arity)));
+ a.str(ARG4, arm::Mem(c_p, offsetof(Process, current)));
+
+ /* We'll find our way back through ARG3 (entry address). */
+ a.b(labels[context_switch_simplified]);
+ }
+}
+
+void BeamModuleAssembler::emit_call_light_bif(const ArgWord &Bif,
+ const ArgExport &Exp) {
+ Label entry = a.newLabel();
+
+ a.bind(entry);
+
+ mov_arg(ARG4, Exp);
+ mov_arg(ARG8, Bif);
+ a.adr(ARG3, entry);
+
+ fragment_call(ga->get_call_light_bif_shared());
+}
+
+void BeamModuleAssembler::emit_send() {
+ Label entry = a.newLabel();
+
+ /* This is essentially a mirror of call_light_bif, there's no point to
+ * specializing send/2 anymore. We do it here because it's far more work to
+ * do it in the loader. */
+ a.bind(entry);
+
+ a.ldr(ARG4, embed_constant(BIF_TRAP_EXPORT(BIF_send_2), disp32K));
+ a.ldr(ARG8, embed_constant(send_2, disp32K));
+ a.adr(ARG3, entry);
+
+ fragment_call(ga->get_call_light_bif_shared());
+}
+
+void BeamModuleAssembler::emit_nif_start() {
+ /* load time only instruction */
+}
+
+void BeamGlobalAssembler::emit_bif_nif_epilogue(void) {
+ Label check_trap = a.newLabel(), trap = a.newLabel(), error = a.newLabel();
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ {
+ Label skip_msacc = a.newLabel();
+
+ a.ldr(TMP1, erts_msacc_cache);
+ a.cbz(TMP1, skip_msacc);
+
+ /* The values of the X registers are in the X register array,
+ * so we can use XREG0 to save the contents of ARG1 during the
+ * call. */
+ a.mov(XREG0, ARG1);
+ a.ldr(ARG1, erts_msacc_cache);
+ mov_imm(ARG2, ERTS_MSACC_STATE_EMULATOR);
+ mov_imm(ARG3, 1);
+ runtime_call<3>(erts_msacc_set_state_m__);
+ a.mov(ARG1, XREG0);
+
+ a.bind(skip_msacc);
+ }
+#endif
+
+ /* Another process may have loaded new code and somehow notified us through
+ * this call, so we must update the active code index. */
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions | Update::eCodeIndex>();
+
+ emit_branch_if_not_value(ARG1, check_trap);
+
+ comment("Do return and dispatch to it");
+ a.mov(XREG0, ARG1);
+
+ emit_leave_erlang_frame();
+ a.ret(a64::x30);
+
+ a.bind(check_trap);
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.cmp(TMP1, imm(TRAP));
+ a.b_ne(error);
+ {
+ comment("yield");
+
+ comment("test trap to hibernate");
+ a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags)));
+ a.tbz(TMP1, imm(Support::ctz(F_HIBERNATE_SCHED)), trap);
+
+ comment("do hibernate trap");
+ a.and_(TMP1, TMP1, imm(~F_HIBERNATE_SCHED));
+ a.str(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags)));
+ a.b(labels[do_schedule]);
+ }
+
+ a.bind(trap);
+ {
+ comment("do normal trap");
+
+ /* The BIF_TRAP macros all set up c_p->arity and c_p->current, so we
+ * can use a simplified context switch. */
+ a.ldr(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+ a.b(labels[context_switch_simplified]);
+ }
+
+ a.bind(error);
+ {
+ a.mov(ARG2, E);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_printable_return_address);
+
+ emit_leave_runtime();
+
+ a.mov(ARG2, ARG1);
+ a.ldr(ARG4, arm::Mem(c_p, offsetof(Process, current)));
+ a.b(labels[raise_exception_shared]);
+ }
+}
+
+/* Used by call_bif, dispatch_bif, and export_trampoline.
+ *
+ * Note that we don't check reductions here as we may have jumped here through
+ * interpreted code (e.g. an ErtsNativeFunc or export entry) and it's very
+ * tricky to yield back. Reductions are checked in module code instead.
+ *
+ * ARG2 = BIF MFA
+ * ARG3 = I (rip), doesn't need to point past an MFA
+ * ARG4 = function to be called */
+void BeamGlobalAssembler::emit_call_bif_shared(void) {
+ /* "Heavy" BIFs need up-to-date values for `c_p->i`, `c_p->current`, and
+ * `c_p->arity`. */
+
+ emit_enter_runtime_frame();
+ a.str(ARG2, arm::Mem(c_p, offsetof(Process, current)));
+ /* `call_bif` wants arity in ARG5. */
+ a.ldr(ARG5, arm::Mem(ARG2, offsetof(ErtsCodeMFA, arity)));
+ a.str(ARG5, arm::Mem(c_p, offsetof(Process, arity)));
+ a.str(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+
+ /* The corresponding leave can be found in the epilogue. */
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ {
+ Label skip_msacc = a.newLabel();
+
+ a.ldr(TMP1, erts_msacc_cache);
+ a.cbz(TMP1, skip_msacc);
+
+ /* The values of the X registers are in the X register array, so we can
+ * use XREG0 and XREG1 to save the contents of the ARG* registers
+ * during the call. */
+ a.mov(XREG0, ARG3);
+ a.mov(XREG1, ARG5);
+
+ a.ldr(ARG1, erts_msacc_cache);
+ a.ldr(ARG2, arm::Mem(ARG2, offsetof(ErtsCodeMFA, module)));
+ a.mov(ARG3, ARG4);
+ runtime_call<3>(erts_msacc_set_bif_state);
+ a.mov(ARG4, ARG1);
+
+ a.mov(ARG3, XREG0);
+ a.mov(ARG5, XREG1);
+
+ a.bind(skip_msacc);
+ }
+#endif
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ /* ARG3 (I), ARG4 (func), and ARG5 (arity) have already been provided. */
+ runtime_call<5>(beam_jit_call_bif);
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ /* The values of the X registers are in the X register array, so we can use
+ * XREG0 to save the contents of ARG1 during the call. */
+ a.mov(XREG0, ARG1);
+ lea(ARG1, erts_msacc_cache);
+ runtime_call<1>(erts_msacc_update_cache);
+ a.mov(ARG1, XREG0);
+#endif
+
+ emit_leave_runtime_frame();
+ emit_bif_nif_epilogue();
+}
+
+void BeamGlobalAssembler::emit_dispatch_bif(void) {
+ /* c_p->i points into the trampoline of a ErtsNativeFunc, right after the
+ * `info` structure. */
+ a.ldr(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+
+ ERTS_CT_ASSERT(offsetof(ErtsNativeFunc, trampoline.call_bif_nif) ==
+ sizeof(ErtsCodeInfo));
+
+ ssize_t mfa_offset = offsetof(ErtsNativeFunc, trampoline.call_bif_nif) -
+ offsetof(ErtsNativeFunc, trampoline.info.mfa);
+
+ a.sub(ARG2, ARG3, imm(mfa_offset));
+
+ ssize_t dfunc_offset = offsetof(ErtsNativeFunc, trampoline.dfunc) -
+ offsetof(ErtsNativeFunc, trampoline.call_bif_nif);
+ a.ldr(ARG4, arm::Mem(ARG3, dfunc_offset));
+
+ a.b(labels[call_bif_shared]);
+}
+
+/* This is only used for opcode compatibility with the interpreter, it's never
+ * actually called. */
+void BeamModuleAssembler::emit_call_bif(const ArgWord &Func) {
+ (void)Func;
+
+ emit_nyi("emit_call_bif");
+}
+
+void BeamModuleAssembler::emit_call_bif_mfa(const ArgAtom &M,
+ const ArgAtom &F,
+ const ArgWord &A) {
+ BeamInstr func;
+ Export *e;
+
+ e = erts_active_export_entry(M.get(), F.get(), A.get());
+ ASSERT(e != NULL && e->bif_number != -1);
+
+ func = (BeamInstr)bif_table[e->bif_number].f;
+
+ a.adr(ARG3, current_label);
+ a.sub(ARG2, ARG3, imm(sizeof(ErtsCodeMFA)));
+ a.mov(ARG4, imm(func));
+
+ a.b(resolve_fragment(ga->get_call_bif_shared(), disp128MB));
+}
+
+void BeamGlobalAssembler::emit_call_nif_early() {
+ a.mov(ARG2, a64::x30);
+ a.sub(ARG2, ARG2, imm(BEAM_ASM_FUNC_PROLOGUE_SIZE + sizeof(ErtsCodeInfo)));
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_call_nif_early);
+
+ emit_leave_runtime();
+
+ /* Emulate `emit_call_nif`, loading the current (phony) instruction
+ * pointer into ARG3.
+ *
+ * Note that we "inherit" the frame that was pushed to the stack prior to
+ * running the breakpoint instruction, discarding the current content of
+ * LR (x30). */
+ a.mov(ARG3, ARG1);
+ a.b(labels[call_nif_shared]);
+}
+
+/* Used by call_nif, call_nif_early, and dispatch_nif.
+ *
+ * Note that we don't check reductions here as we may have jumped here through
+ * interpreted code (e.g. an ErtsNativeFunc or export entry) and it's very
+ * tricky to yield back. Reductions are checked in module code instead.
+ *
+ * ARG3 = current I, just past the end of an ErtsCodeInfo. */
+void BeamGlobalAssembler::emit_call_nif_shared(void) {
+ /* The corresponding leave can be found in the epilogue. */
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ {
+ Label skip_msacc = a.newLabel();
+
+ a.ldr(TMP1, erts_msacc_cache);
+ a.cbz(TMP1, skip_msacc);
+
+ /* The values of the X registers are in the X register array,
+ * so we can use XREG0 to save the contents of ARG3 during the
+ * call. */
+ a.mov(XREG0, ARG3);
+ a.ldr(ARG1, erts_msacc_cache);
+ mov_imm(ARG2, ERTS_MSACC_STATE_NIF);
+ mov_imm(ARG3, 1);
+ runtime_call<3>(erts_msacc_set_state_m__);
+ a.mov(ARG3, XREG0);
+
+ a.bind(skip_msacc);
+ }
+#endif
+
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, ARG3);
+ load_x_reg_array(ARG3);
+ ERTS_CT_ASSERT((4 + BEAM_ASM_FUNC_PROLOGUE_SIZE) % sizeof(UWord) == 0);
+ a.ldr(ARG4, arm::Mem(ARG2, 4 + BEAM_ASM_FUNC_PROLOGUE_SIZE));
+ a.ldr(ARG5, arm::Mem(ARG2, 12 + BEAM_ASM_FUNC_PROLOGUE_SIZE));
+ a.ldr(ARG6, arm::Mem(ARG2, 16 + BEAM_ASM_FUNC_PROLOGUE_SIZE));
+ runtime_call<5>(beam_jit_call_nif);
+
+ emit_bif_nif_epilogue();
+}
+
+void BeamGlobalAssembler::emit_dispatch_nif(void) {
+ /* c_p->i points into the trampoline of a ErtsNativeFunc, right after the
+ * `info` structure.
+ *
+ * ErtsNativeFunc already follows the NIF call layout, so we don't need to
+ * do anything beyond loading the address. */
+ a.ldr(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+ a.b(labels[call_nif_shared]);
+}
+
+void BeamGlobalAssembler::emit_call_nif_yield_helper() {
+ Label yield = a.newLabel();
+
+ a.subs(FCALLS, FCALLS, imm(1));
+ a.b_le(yield);
+ a.b(labels[call_nif_shared]);
+
+ a.bind(yield);
+ {
+ int mfa_offset = sizeof(ErtsCodeMFA);
+ int arity_offset = offsetof(ErtsCodeMFA, arity) - mfa_offset;
+
+ a.ldur(TMP1, arm::Mem(ARG3, arity_offset));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, arity)));
+
+ a.sub(TMP1, ARG3, imm(mfa_offset));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, current)));
+
+ /* Yield to `dispatch` rather than `entry` to avoid pushing too many
+ * frames to the stack. See `emit_call_nif` for details. */
+ a.add(ARG3, ARG3, imm(BEAM_ASM_NFUNC_SIZE + sizeof(UWord[3])));
+ a.b(labels[context_switch_simplified]);
+ }
+}
+
+/* WARNING: This stub is memcpy'd, so all code herein must be explicitly
+ * position-independent. */
+void BeamModuleAssembler::emit_call_nif(const ArgWord &Func,
+ const ArgWord &NifMod,
+ const ArgWord &DirtyFunc) {
+ Label entry = a.newLabel(), dispatch = a.newLabel();
+
+ /* The start of this function must mimic the layout of ErtsNativeFunc.
+ *
+ * We jump here on the very first entry. */
+ a.bind(entry);
+ {
+ a.b(dispatch);
+
+ /* Everything prior to this, including the breakpoint, is part of the
+ * `call_bif_nif` field. */
+ ASSERT(a.offset() % sizeof(UWord) == 0);
+
+ /* ErtsNativeFunc.func */
+ a.embedUInt64(Func.get());
+
+ /* ErtsNativeFunc.m */
+ a.embedUInt64(NifMod.get());
+
+ /* ErtsNativeFunc.dfunc */
+ a.embedUInt64(DirtyFunc.get());
+ }
+
+ /* `emit_call_nif_yield_helper` relies on this to compute the address of
+ * `dispatch` */
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ BEAM_ASM_NFUNC_SIZE + sizeof(UWord[3]));
+
+ a.bind(dispatch);
+ {
+ a.adr(ARG3, current_label);
+ pic_jmp(ga->get_call_nif_yield_helper());
+ }
+}
+
+static ErtsCodePtr get_on_load_address(Process *c_p, Eterm module) {
+ const Module *modp = erts_get_module(module, erts_active_code_ix());
+
+ if (modp && modp->on_load) {
+ const BeamCodeHeader *hdr = (modp->on_load)->code_hdr;
+
+ if (hdr) {
+ return erts_codeinfo_to_code(hdr->on_load);
+ }
+ }
+
+ c_p->freason = BADARG;
+
+ return NULL;
+}
+
+/* Implements the internal and undocumented erlang:call_on_load_function/1,
+ * which is very tricky to implement as a BIF. */
+void BeamModuleAssembler::emit_i_call_on_load_function() {
+ static ErtsCodeMFA mfa = {am_erlang, am_call_on_load_function, 1};
+ Label next = a.newLabel();
+
+ a.mov(ARG2, XREG0);
+
+ /* The first X register must be preserved for the error path. */
+ emit_enter_runtime(1);
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(get_on_load_address);
+
+ emit_leave_runtime(1);
+
+ a.cbnz(ARG1, next);
+ emit_raise_exception(&mfa);
+
+ a.bind(next);
+ erlang_call(ARG1);
+}
+
+void BeamModuleAssembler::emit_i_load_nif() {
+ static ErtsCodeMFA mfa = {am_erlang, am_load_nif, 2};
+
+ Label entry = a.newLabel(), next = a.newLabel(), schedule = a.newLabel();
+
+ a.bind(entry);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs>(2);
+
+ a.mov(ARG1, c_p);
+ a.adr(ARG2, current_label);
+ load_x_reg_array(ARG3);
+ runtime_call<3>(beam_jit_load_nif);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs>(2);
+
+ a.cmp(ARG1, imm(RET_NIF_yield));
+ a.b_eq(schedule);
+
+ a.cmp(ARG1, imm(RET_NIF_success));
+ a.b_eq(next);
+
+ emit_raise_exception(current_label, &mfa);
+
+ a.bind(schedule);
+ {
+ a.adr(ARG3, entry);
+ a.b(resolve_fragment(ga->get_context_switch_simplified(), disp128MB));
+ }
+
+ a.bind(next);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_bs.cpp b/erts/emulator/beam/jit/arm/instr_bs.cpp
new file mode 100644
index 0000000000..06873cd709
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_bs.cpp
@@ -0,0 +1,2023 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "erl_binary.h"
+#include "erl_bits.h"
+#include "beam_common.h"
+}
+
+/* Clobbers TMP1+TMP2
+ *
+ * If max_size > 0, we jump to the fail label when Size > max_size
+ *
+ * Returns -1 when the field check always fails, 1 if it may fail, and 0 if it
+ * never fails. */
+int BeamModuleAssembler::emit_bs_get_field_size(const ArgSource &Size,
+ int unit,
+ Label fail,
+ const arm::Gp &out) {
+ if (Size.isImmed()) {
+ if (Size.isSmall()) {
+ Sint sval = Size.as<ArgSmall>().getSigned();
+
+ if (sval < 0) {
+ /* badarg */
+ } else if (sval > (MAX_SMALL / unit)) {
+ /* system_limit */
+ } else {
+ mov_imm(out, sval * unit);
+ return 0;
+ }
+ }
+
+ a.b(fail);
+ return -1;
+ } else {
+ auto size_reg = load_source(Size, TMP2);
+
+ /* Negating the tag bits lets us guard against non-smalls, negative
+ * numbers, and overflow with a single `tst` instruction. */
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ ASSERT(unit <= 1024);
+
+ a.eor(out, size_reg.reg, imm(_TAG_IMMED1_SMALL));
+ a.tst(out, imm(0xFFF0000000000000UL | _TAG_IMMED1_MASK));
+
+ if (unit == 0) {
+ /* Silly but legal.*/
+ mov_imm(out, 0);
+ } else if (Support::isPowerOf2(unit)) {
+ int trailing_bits = Support::ctz<Eterm>(unit);
+
+ /* The tag bits were cleared out by the argument check, so all we
+ * need to do is shift the result into place. */
+ if (trailing_bits < _TAG_IMMED1_SIZE) {
+ a.lsr(out, out, imm(_TAG_IMMED1_SIZE - trailing_bits));
+ } else if (trailing_bits > _TAG_IMMED1_SIZE) {
+ a.lsl(out, out, imm(trailing_bits - _TAG_IMMED1_SIZE));
+ }
+ } else {
+ if (unit >= (1 << _TAG_IMMED1_SIZE)) {
+ mov_imm(TMP1, unit >> _TAG_IMMED1_SIZE);
+ } else {
+ a.lsr(out, out, imm(_TAG_IMMED1_SIZE));
+ mov_imm(TMP1, unit);
+ }
+
+ a.mul(out, out, TMP1);
+ }
+
+ a.b_ne(fail);
+
+ return 1;
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_init_heap(const ArgWord &Size,
+ const ArgWord &Heap,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ mov_arg(ARG4, Size);
+ mov_arg(ARG5, Heap);
+ mov_arg(ARG6, Live);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ load_erl_bits_state(ARG3);
+ runtime_call<6>(beam_jit_bs_init);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ mov_arg(Dst, ARG1);
+}
+
+/* Set the error reason when a size check has failed. */
+void BeamGlobalAssembler::emit_bs_size_check_shared() {
+ emit_enter_runtime_frame();
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(beam_jit_bs_field_size_argument_error);
+
+ emit_leave_runtime(0);
+ emit_leave_runtime_frame();
+
+ mov_imm(ARG4, 0);
+ a.b(labels[raise_exception]);
+}
+
+void BeamModuleAssembler::emit_i_bs_init_fail_heap(const ArgSource &Size,
+ const ArgWord &Heap,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ Label fail;
+
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ fail = a.newLabel();
+ }
+
+ if (emit_bs_get_field_size(Size, 1, fail, ARG4) >= 0) {
+ mov_arg(ARG5, Heap);
+ mov_arg(ARG6, Live);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ load_erl_bits_state(ARG3);
+ runtime_call<6>(beam_jit_bs_init);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ mov_arg(Dst, ARG1);
+ }
+
+ if (Fail.get() == 0) {
+ Label next = a.newLabel();
+
+ a.b(next);
+
+ a.bind(fail);
+ {
+ mov_arg(ARG2, Size);
+ fragment_call(ga->get_bs_size_check_shared());
+ }
+
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_init(const ArgWord &Size,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal Heap(ArgVal::Word, 0);
+ emit_i_bs_init_heap(Size, Heap, Live, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bs_init_fail(const ArgRegister &Size,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal Heap(ArgVal::Word, 0);
+ emit_i_bs_init_fail_heap(Size, Heap, Fail, Live, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bs_init_bits(const ArgWord &NumBits,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal heap(ArgVal::Word, 0);
+ emit_i_bs_init_bits_heap(NumBits, heap, Live, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bs_init_bits_heap(const ArgWord &NumBits,
+ const ArgWord &Alloc,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ mov_arg(ARG4, NumBits);
+ mov_arg(ARG5, Alloc);
+ mov_arg(ARG6, Live);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ load_erl_bits_state(ARG3);
+ runtime_call<6>(beam_jit_bs_init_bits);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_bs_init_bits_fail(const ArgRegister &NumBits,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal Heap(ArgVal::Word, 0);
+
+ emit_i_bs_init_bits_fail_heap(NumBits, Heap, Fail, Live, Dst);
+}
+
+void BeamModuleAssembler::emit_i_bs_init_bits_fail_heap(
+ const ArgSource &NumBits,
+ const ArgWord &Alloc,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ Label fail;
+
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ fail = a.newLabel();
+ }
+
+ if (emit_bs_get_field_size(NumBits, 1, fail, ARG4) >= 0) {
+ mov_arg(ARG5, Alloc);
+ mov_arg(ARG6, Live);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ load_erl_bits_state(ARG3);
+ runtime_call<6>(beam_jit_bs_init_bits);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ mov_arg(Dst, ARG1);
+ }
+
+ if (Fail.get() == 0) {
+ Label next = a.newLabel();
+
+ a.b(next);
+ a.bind(fail);
+ {
+ mov_arg(ARG2, NumBits);
+ fragment_call(ga->get_bs_size_check_shared());
+ }
+
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_bs_put_string(const ArgWord &Size,
+ const ArgBytePtr &Ptr) {
+ mov_arg(ARG2, Ptr);
+ mov_arg(ARG3, Size);
+
+ emit_enter_runtime();
+
+ load_erl_bits_state(ARG1);
+ runtime_call<3>(erts_new_bs_put_string);
+
+ emit_leave_runtime();
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_integer_imm(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgWord &Sz,
+ const ArgWord &Flags) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Sz);
+ mov_arg(ARG4, Flags);
+
+ emit_enter_runtime();
+
+ load_erl_bits_state(ARG1);
+ runtime_call<4>(erts_new_bs_put_integer);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+ } else {
+ Label next = a.newLabel();
+
+ a.cbnz(ARG1, next);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_integer(const ArgLabel &Fail,
+ const ArgRegister &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ int unit = Flags.get() >> 3;
+ Label next, fail;
+
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ fail = a.newLabel();
+ next = a.newLabel();
+ }
+
+ /* Clobbers RET + ARG3 */
+ if (emit_bs_get_field_size(Sz, unit, fail, ARG3) >= 0) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG4, Flags);
+
+ emit_enter_runtime();
+
+ load_erl_bits_state(ARG1);
+ runtime_call<4>(erts_new_bs_put_integer);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ a.cbz(ARG1, fail);
+ } else {
+ a.cbnz(ARG1, next);
+ }
+ }
+
+ if (Fail.get() == 0) {
+ a.bind(fail);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_binary(const ArgLabel &Fail,
+ const ArgSource &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ int unit = Flags.get() >> 3;
+ Label next, fail;
+
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ fail = a.newLabel();
+ next = a.newLabel();
+ }
+
+ if (emit_bs_get_field_size(Sz, unit, fail, ARG3) >= 0) {
+ mov_arg(ARG2, Src);
+
+ emit_enter_runtime<Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_new_bs_put_binary);
+
+ emit_leave_runtime<Update::eReductions>();
+
+ if (Fail.get() != 0) {
+ a.cbz(ARG1, fail);
+ } else {
+ a.cbnz(ARG1, next);
+ }
+ }
+
+ if (Fail.get() == 0) {
+ a.bind(fail);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_binary_all(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgWord &Unit) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Unit);
+
+ emit_enter_runtime<Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_new_bs_put_binary_all);
+
+ emit_leave_runtime<Update::eReductions>();
+
+ if (Fail.get() == 0) {
+ Label next = a.newLabel();
+
+ a.cbnz(ARG1, next);
+ emit_error(BADARG);
+ a.bind(next);
+ } else {
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_binary_imm(const ArgLabel &Fail,
+ const ArgWord &Sz,
+ const ArgSource &Src) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Sz);
+
+ emit_enter_runtime<Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_new_bs_put_binary);
+
+ emit_leave_runtime<Update::eReductions>();
+
+ if (Fail.get() == 0) {
+ Label next = a.newLabel();
+
+ a.cbnz(ARG1, next);
+ emit_error(BADARG);
+ a.bind(next);
+ } else {
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_float(const ArgLabel &Fail,
+ const ArgRegister &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ int unit = Flags.get() >> 3;
+ Label next, fail;
+
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ fail = a.newLabel();
+ next = a.newLabel();
+ }
+
+ if (emit_bs_get_field_size(Sz, unit, fail, ARG3) >= 0) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG4, Flags);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<4>(erts_new_bs_put_float);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ emit_branch_if_value(ARG1, fail);
+ } else {
+ emit_branch_if_not_value(ARG1, next);
+ }
+ }
+
+ if (Fail.get() == 0) {
+ a.bind(fail);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_new_bs_put_float_imm(const ArgLabel &Fail,
+ const ArgWord &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Sz);
+ mov_arg(ARG4, Flags);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<4>(erts_new_bs_put_float);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ emit_branch_if_value(ARG1, resolve_beam_label(Fail, disp1MB));
+ } else {
+ Label next = a.newLabel();
+
+ emit_branch_if_not_value(ARG1, next);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_start_match3(const ArgRegister &Src,
+ const ArgWord &Live,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ Label is_binary = a.newLabel(), next = a.newLabel();
+
+ mov_arg(ARG2, Src);
+
+ if (Fail.get() != 0) {
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, ARG2);
+ } else {
+ /* bs_start_match3 may not throw, and the compiler will only emit {f,0}
+ * when it knows that the source is a match state or binary, so we're
+ * free to skip the binary tests. */
+ }
+
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, ARG2);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, 0));
+
+ a.and_(TMP1, TMP1, imm(_HEADER_SUBTAG_MASK));
+ a.cmp(TMP1, imm(BIN_MATCHSTATE_SUBTAG));
+ a.b_eq(next);
+
+ if (Fail.get() != 0) {
+ comment("is_binary_header");
+ a.cmp(TMP1, _TAG_HEADER_SUB_BIN);
+ a.b_eq(is_binary);
+ ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
+ a.and_(TMP1, TMP1, imm(~4));
+ a.cmp(TMP1, imm(_TAG_HEADER_REFC_BIN));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(is_binary);
+ {
+ /* Src is not guaranteed to be inside the live range, so we need to
+ * stash it during GC. */
+ emit_gc_test_preserve(ArgVal(ArgVal::Word, ERL_BIN_MATCHSTATE_SIZE(0)),
+ Live,
+ ARG2);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap>(Live.get());
+
+ a.mov(ARG1, c_p);
+ /* ARG2 was set above */
+ runtime_call<2>(erts_bs_start_match_3);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(Live.get());
+
+ a.add(ARG2, ARG1, imm(TAG_PRIMARY_BOXED));
+ }
+
+ a.bind(next);
+ mov_arg(Dst, ARG2);
+}
+
+void BeamModuleAssembler::emit_i_bs_match_string(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Bits,
+ const ArgBytePtr &Ptr) {
+ const int position_offset = offsetof(ErlBinMatchState, mb.offset);
+ const int size_offset = offsetof(ErlBinMatchState, mb.size);
+ const int base_offset = offsetof(ErlBinMatchState, mb.base);
+
+ const auto size = Bits.get();
+
+ {
+ auto ctx_reg = load_source(Ctx, TMP1);
+
+ a.ldur(TMP2, emit_boxed_val(ctx_reg.reg, position_offset));
+ a.ldur(TMP3, emit_boxed_val(ctx_reg.reg, size_offset));
+ add(TMP4, TMP2, size);
+ a.cmp(TMP4, TMP3);
+ a.b_hi(resolve_beam_label(Fail, disp1MB));
+
+ /* ARG4 = mb->offset & 7 */
+ a.and_(ARG4, TMP2, imm(7));
+
+ /* ARG3 = mb->base + (mb->offset >> 3) */
+ a.lsr(TMP2, TMP2, imm(3));
+ a.ldur(TMP1, emit_boxed_val(ctx_reg.reg, base_offset));
+ a.add(ARG3, TMP1, TMP2);
+ }
+
+ emit_enter_runtime();
+
+ mov_arg(ARG1, Ptr);
+ mov_imm(ARG2, 0);
+ mov_imm(ARG5, size);
+ runtime_call<5>(erts_cmp_bits);
+
+ emit_leave_runtime();
+ a.cbnz(ARG1, resolve_beam_label(Fail, disp1MB));
+
+ {
+ auto ctx_reg = load_source(Ctx, TMP1);
+
+ a.ldur(TMP2, emit_boxed_val(ctx_reg.reg, position_offset));
+ add(TMP2, TMP2, size);
+ a.stur(TMP2, emit_boxed_val(ctx_reg.reg, position_offset));
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_get_position(const ArgRegister &Ctx,
+ const ArgRegister &Dst) {
+ const int position_offset = offsetof(ErlBinMatchState, mb.offset);
+ auto ctx_reg = load_source(Ctx, TMP1);
+ auto dst_reg = init_destination(Dst, TMP2);
+
+ /* Match contexts can never be literals, so we can skip clearing literal
+ * tags. */
+ a.ldur(dst_reg.reg, emit_boxed_val(ctx_reg.reg, position_offset));
+ a.lsl(dst_reg.reg, dst_reg.reg, imm(_TAG_IMMED1_SIZE));
+ a.orr(dst_reg.reg, dst_reg.reg, imm(_TAG_IMMED1_SMALL));
+
+ flush_var(dst_reg);
+}
+
+void BeamModuleAssembler::emit_i_bs_get_fixed_integer(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgWord &Flags,
+ const ArgWord &Bits,
+ const ArgRegister &Dst) {
+ auto ctx = load_source(Ctx, TMP1);
+ int flags, bits;
+
+ flags = Flags.get();
+ bits = Bits.get();
+
+ if (bits >= SMALL_BITS) {
+ emit_gc_test_preserve(ArgVal(ArgVal::Word, BIG_NEED_FOR_BITS(bits)),
+ Live,
+ ctx.reg);
+ }
+
+ lea(ARG4, emit_boxed_val(ctx.reg, offsetof(ErlBinMatchState, mb)));
+
+ if (bits >= SMALL_BITS) {
+ emit_enter_runtime<Update::eHeap>(Live.get());
+ } else {
+ emit_enter_runtime(Live.get());
+ }
+
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, bits);
+ a.mov(ARG3, flags);
+ /* ARG4 set above. */
+ runtime_call<4>(erts_bs_get_integer_2);
+
+ if (bits >= SMALL_BITS) {
+ emit_leave_runtime<Update::eHeap>(Live.get());
+ } else {
+ emit_leave_runtime(Live.get());
+ }
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_bs_get_integer(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgWord &FlagsAndUnit,
+ const ArgSource &Sz,
+ const ArgRegister &Dst) {
+ Label fail;
+ int unit;
+
+ fail = resolve_beam_label(Fail, dispUnknown);
+ unit = FlagsAndUnit.get() >> 3;
+
+ if (emit_bs_get_field_size(Sz, unit, fail, ARG5) >= 0) {
+ mov_arg(ARG3, Ctx);
+ mov_arg(ARG4, FlagsAndUnit);
+ mov_arg(ARG6, Live);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<6>(beam_jit_bs_get_integer);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get());
+
+ emit_branch_if_not_value(ARG1, fail);
+ mov_arg(Dst, ARG1);
+ }
+}
+
+void BeamModuleAssembler::emit_bs_test_tail2(const ArgLabel &Fail,
+ const ArgRegister &Ctx,
+ const ArgWord &Offset) {
+ const int position_offset = offsetof(ErlBinMatchState, mb.offset);
+ const int size_offset = offsetof(ErlBinMatchState, mb.size);
+
+ auto ctx_reg = load_source(Ctx, TMP1);
+
+ ASSERT(Offset.isWord());
+
+ a.ldur(TMP2, emit_boxed_val(ctx_reg.reg, size_offset));
+ a.ldur(TMP3, emit_boxed_val(ctx_reg.reg, position_offset));
+ a.sub(TMP2, TMP2, TMP3);
+
+ if (Offset.get() != 0) {
+ cmp(TMP2, Offset.get());
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.cbnz(TMP2, resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_bs_set_position(const ArgRegister &Ctx,
+ const ArgRegister &Pos) {
+ const int position_offset = offsetof(ErlBinMatchState, mb.offset);
+ auto [ctx, pos] = load_sources(Ctx, TMP1, Pos, TMP2);
+
+ a.lsr(TMP2, pos.reg, imm(_TAG_IMMED1_SIZE));
+ a.stur(TMP2, emit_boxed_val(ctx.reg, position_offset));
+}
+
+void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgWord &Unit,
+ const ArgRegister &Dst) {
+ unsigned unit = Unit.get();
+
+ mov_arg(ARG1, Ctx);
+
+ /* Ctx is not guaranteed to be inside the live range, so we need to stash
+ * it during GC. */
+ emit_gc_test_preserve(ArgVal(ArgVal::Word, EXTRACT_SUB_BIN_HEAP_NEED),
+ Live,
+ ARG1);
+
+ /* Make field fetching slightly more compact by pre-loading the match
+ * buffer into the right argument slot for `erts_bs_get_binary_all_2`. */
+ lea(ARG2, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb)));
+
+ ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, offset, size);
+ a.ldp(TMP2, TMP3, arm::Mem(ARG2, offsetof(ErlBinMatchBuffer, offset)));
+
+ /* Remainder = Size - Offset */
+ a.sub(TMP1, TMP3, TMP2);
+
+ /* Unit may be 1 if compiling with +no_bsm3, which lacks the
+ * bs_get_tail instruction. */
+ if (unit > 1) {
+ if ((unit & (unit - 1))) {
+ mov_imm(TMP2, unit);
+
+ a.udiv(TMP3, TMP1, TMP2);
+ a.msub(TMP1, TMP3, TMP2, TMP1);
+
+ a.cbnz(TMP1, resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.tst(TMP1, imm(unit - 1));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+ }
+
+ emit_enter_runtime<Update::eHeap>(Live.get());
+
+ a.mov(ARG1, c_p);
+ /* ARG2 was set above. */
+ runtime_call<2>(erts_bs_get_binary_all_2);
+
+ emit_leave_runtime<Update::eHeap>(Live.get());
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamGlobalAssembler::emit_bs_get_tail_shared() {
+ lea(TMP1, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb)));
+
+ ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, orig, base);
+ a.ldp(ARG2, ARG3, arm::Mem(TMP1, offsetof(ErlBinMatchBuffer, orig)));
+
+ ERTS_CT_ASSERT_FIELD_PAIR(ErlBinMatchBuffer, offset, size);
+ a.ldp(ARG4, TMP1, arm::Mem(TMP1, offsetof(ErlBinMatchBuffer, offset)));
+
+ lea(ARG1, arm::Mem(c_p, offsetof(Process, htop)));
+
+ /* Extracted size = mb->size - mb->offset */
+ a.sub(ARG5, TMP1, ARG4);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eHeap>();
+
+ runtime_call<5>(erts_extract_sub_binary);
+
+ emit_leave_runtime<Update::eHeap>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+void BeamModuleAssembler::emit_bs_get_tail(const ArgRegister &Ctx,
+ const ArgRegister &Dst,
+ const ArgWord &Live) {
+ mov_arg(ARG1, Ctx);
+
+ /* Ctx is not guaranteed to be inside the live range, so we need to stash
+ * it during GC. */
+ emit_gc_test_preserve(ArgVal(ArgVal::Word, EXTRACT_SUB_BIN_HEAP_NEED),
+ Live,
+ ARG1);
+
+ fragment_call(ga->get_bs_get_tail_shared());
+
+ mov_arg(Dst, ARG1);
+}
+
+/* Bits to skip are passed in ARG1 */
+void BeamModuleAssembler::emit_bs_skip_bits(const ArgLabel &Fail,
+ const ArgRegister &Ctx) {
+ const int position_offset = offsetof(ErlBinMatchState, mb.offset);
+ const int size_offset = offsetof(ErlBinMatchState, mb.size);
+
+ auto ctx_reg = load_source(Ctx, TMP1);
+
+ a.ldur(TMP2, emit_boxed_val(ctx_reg.reg, position_offset));
+ a.ldur(TMP3, emit_boxed_val(ctx_reg.reg, size_offset));
+
+ a.add(TMP2, TMP2, ARG1);
+ a.cmp(TMP2, TMP3);
+ a.b_hi(resolve_beam_label(Fail, disp1MB));
+
+ a.stur(TMP2, emit_boxed_val(ctx_reg.reg, position_offset));
+}
+
+void BeamModuleAssembler::emit_i_bs_skip_bits2(const ArgRegister &Ctx,
+ const ArgRegister &Bits,
+ const ArgLabel &Fail,
+ const ArgWord &Unit) {
+ Label fail = resolve_beam_label(Fail, dispUnknown);
+
+ if (emit_bs_get_field_size(Bits, Unit.get(), fail, ARG1) >= 0) {
+ emit_bs_skip_bits(Fail, Ctx);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_skip_bits_imm2(const ArgLabel &Fail,
+ const ArgRegister &Ctx,
+ const ArgWord &Bits) {
+ mov_arg(ARG1, Bits);
+ emit_bs_skip_bits(Fail, Ctx);
+}
+
+void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Size,
+ const ArgWord &Flags,
+ const ArgRegister &Dst) {
+ Label fail;
+ int unit;
+
+ fail = resolve_beam_label(Fail, dispUnknown);
+ unit = Flags.get() >> 3;
+
+ if (emit_bs_get_field_size(Size, unit, fail, ARG2) >= 0) {
+ a.str(ARG2, TMP_MEM1q);
+
+ mov_arg(ARG4, Ctx);
+
+ /* Ctx is not guaranteed to be inside the live range, so we need to
+ * stash it during GC. */
+ emit_gc_test_preserve(ArgVal(ArgVal::Word, EXTRACT_SUB_BIN_HEAP_NEED),
+ Live,
+ ARG4);
+
+ lea(ARG4, emit_boxed_val(ARG4, offsetof(ErlBinMatchState, mb)));
+
+ emit_enter_runtime<Update::eHeap>(Live.get());
+
+ a.mov(ARG1, c_p);
+ a.ldr(ARG2, TMP_MEM1q);
+ mov_imm(ARG3, Flags.get());
+ runtime_call<4>(erts_bs_get_binary_2);
+
+ emit_leave_runtime<Update::eHeap>(Live.get());
+
+ emit_branch_if_not_value(ARG1, fail);
+
+ mov_arg(Dst, ARG1);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_get_float2(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Sz,
+ const ArgWord &Flags,
+ const ArgRegister &Dst) {
+ Label fail;
+ Sint unit;
+
+ fail = resolve_beam_label(Fail, dispUnknown);
+ unit = Flags.get() >> 3;
+
+ mov_arg(ARG4, Ctx);
+
+ /* Ctx is not guaranteed to be inside the live range, so we need to stash
+ * it during GC. */
+ emit_gc_test_preserve(ArgWord(FLOAT_SIZE_OBJECT), Live, ARG4);
+
+ if (emit_bs_get_field_size(Sz, unit, fail, ARG2) >= 0) {
+ lea(ARG4, emit_boxed_val(ARG4, offsetof(ErlBinMatchState, mb)));
+
+ emit_enter_runtime<Update::eHeap>(Live.get());
+
+ a.mov(ARG1, c_p);
+ mov_imm(ARG3, Flags.get());
+ runtime_call<4>(erts_bs_get_float_2);
+
+ emit_leave_runtime<Update::eHeap>(Live.get());
+
+ emit_branch_if_not_value(ARG1, fail);
+
+ mov_arg(Dst, ARG1);
+ }
+}
+
+void BeamModuleAssembler::emit_i_bs_utf8_size(const ArgSource &Src,
+ const ArgXRegister &Dst) {
+ auto src_reg = load_source(Src, TMP1);
+ auto dst_reg = init_destination(Dst, TMP2);
+
+ Label next = a.newLabel();
+
+ /* Note that the source and destination registers could be the
+ * same register. Therefore, we must copy the source register
+ * before writing to the destination register. */
+ a.lsr(TMP1, src_reg.reg, imm(_TAG_IMMED1_SIZE));
+ mov_imm(dst_reg.reg, make_small(1));
+ a.cmp(TMP1, imm(0x7F));
+ a.b_ls(next);
+
+ mov_imm(dst_reg.reg, make_small(2));
+ a.cmp(TMP1, imm(0x7FFUL));
+ a.b_ls(next);
+
+ a.cmp(TMP1, imm(0x10000UL));
+ mov_imm(TMP2, make_small(3));
+ mov_imm(TMP3, make_small(4));
+ a.csel(dst_reg.reg, TMP2, TMP3, arm::CondCode::kLO);
+
+ a.bind(next);
+ flush_var(dst_reg);
+}
+
+void BeamModuleAssembler::emit_i_bs_put_utf8(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ mov_arg(ARG2, Src);
+
+ emit_enter_runtime();
+
+ load_erl_bits_state(ARG1);
+ runtime_call<2>(erts_bs_put_utf8);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+ } else {
+ Label next = a.newLabel();
+
+ a.cbnz(ARG1, next);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_bs_get_utf8(const ArgRegister &Ctx,
+ const ArgLabel &Fail) {
+ mov_arg(ARG1, Ctx);
+ lea(ARG1, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb)));
+
+ emit_enter_runtime();
+
+ runtime_call<1>(erts_bs_get_utf8);
+
+ emit_leave_runtime();
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+}
+
+void BeamModuleAssembler::emit_i_bs_get_utf8(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ emit_bs_get_utf8(Ctx, Fail);
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_bs_skip_utf8(const ArgRegister &Ctx,
+ const ArgLabel &Fail) {
+ emit_bs_get_utf8(Ctx, Fail);
+}
+
+void BeamModuleAssembler::emit_i_bs_utf16_size(const ArgSource &Src,
+ const ArgXRegister &Dst) {
+ auto src_reg = load_source(Src, TMP1);
+ auto dst_reg = init_destination(Dst, TMP2);
+
+ /* erts_bs_put_utf16 errors out whenever something's fishy, so we can
+ * return garbage (2 or 4) if our input is not a small. */
+ a.asr(TMP1, src_reg.reg, imm(_TAG_IMMED1_SIZE));
+ a.cmp(TMP1, imm(0x10000UL));
+ mov_imm(TMP1, make_small(2));
+ mov_imm(TMP2, make_small(4));
+ a.csel(dst_reg.reg, TMP1, TMP2, arm::CondCode::kLO);
+
+ flush_var(dst_reg);
+}
+
+void BeamModuleAssembler::emit_i_bs_put_utf16(const ArgLabel &Fail,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Flags);
+
+ emit_enter_runtime();
+
+ load_erl_bits_state(ARG1);
+ runtime_call<3>(erts_bs_put_utf16);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+ } else {
+ Label next = a.newLabel();
+
+ a.cbnz(ARG1, next);
+ emit_error(BADARG);
+ a.bind(next);
+ }
+}
+
+void BeamModuleAssembler::emit_bs_get_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags) {
+ auto ctx_reg = load_source(Ctx, TMP1);
+
+ lea(ARG1, emit_boxed_val(ctx_reg.reg, offsetof(ErlBinMatchState, mb)));
+
+ emit_enter_runtime();
+
+ mov_imm(ARG2, Flags.get());
+ runtime_call<2>(erts_bs_get_utf16);
+
+ emit_leave_runtime();
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+}
+
+void BeamModuleAssembler::emit_i_bs_get_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags,
+ const ArgRegister &Dst) {
+ emit_bs_get_utf16(Ctx, Fail, Flags);
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_bs_skip_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags) {
+ emit_bs_get_utf16(Ctx, Fail, Flags);
+}
+
+void BeamModuleAssembler::emit_validate_unicode(Label next,
+ Label fail,
+ arm::Gp value) {
+ ASSERT(value != TMP2);
+
+ a.and_(TMP2, value, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(fail);
+
+ mov_imm(TMP2, make_small(0xD800UL));
+ a.cmp(value, TMP2);
+ a.b_lo(next);
+
+ mov_imm(TMP2, make_small(0xDFFFUL));
+ a.cmp(value, TMP2);
+ a.b_ls(fail);
+
+ mov_imm(TMP2, make_small(0x10FFFFUL));
+ a.cmp(value, TMP2);
+ a.b_hi(fail);
+
+ a.b(next);
+}
+
+void BeamModuleAssembler::emit_i_bs_validate_unicode(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src_reg = load_source(Src, TMP1);
+ Label fail, next = a.newLabel();
+
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ fail = a.newLabel();
+ }
+
+ emit_validate_unicode(next, fail, src_reg.reg);
+
+ if (Fail.get() == 0) {
+ a.bind(fail);
+ emit_error(BADARG);
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_i_bs_validate_unicode_retract(
+ const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgRegister &Ms) {
+ Label fail = a.newLabel(), next = a.newLabel();
+ auto src_reg = load_source(Src, TMP1);
+
+ emit_validate_unicode(next, fail, src_reg.reg);
+
+ a.bind(fail);
+ {
+ const int position_offset = offsetof(ErlBinMatchState, mb.offset);
+ auto ctx_reg = load_source(Ms, TMP2);
+
+ a.ldur(TMP1, emit_boxed_val(ctx_reg.reg, position_offset));
+ a.sub(TMP1, TMP1, imm(32));
+ a.stur(TMP1, emit_boxed_val(ctx_reg.reg, position_offset));
+
+ if (Fail.get() != 0) {
+ a.b(resolve_beam_label(Fail, disp128MB));
+ } else {
+ emit_error(BADARG);
+ }
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_bs_test_unit(const ArgLabel &Fail,
+ const ArgRegister &Ctx,
+ const ArgWord &Unit) {
+ auto ctx_reg = load_source(Ctx, TMP1);
+ unsigned int unit = Unit.get();
+
+ a.ldur(TMP2,
+ emit_boxed_val(ctx_reg.reg, offsetof(ErlBinMatchState, mb.size)));
+ a.ldur(TMP3,
+ emit_boxed_val(ctx_reg.reg, offsetof(ErlBinMatchState, mb.offset)));
+
+ a.sub(TMP1, TMP2, TMP3);
+
+ if ((unit & (unit - 1))) {
+ mov_imm(TMP2, unit);
+
+ a.udiv(TMP3, TMP1, TMP2);
+ a.msub(TMP1, TMP3, TMP2, TMP1);
+
+ a.cbnz(TMP1, resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.tst(TMP1, imm(unit - 1));
+ a.b_ne(resolve_beam_label(Fail, dispUnknown));
+ }
+}
+
+/* ARG2 = current `Size`,
+ * ARG3 = elements to `Add`,
+ * ARG4 = element `Unit`
+ *
+ * Error is indicated through cond_ne() */
+void BeamGlobalAssembler::emit_bs_add_guard_shared() {
+ Label error = a.newLabel();
+
+ /* Since `Unit` is guaranteed to be less than 1024, we can check overflow
+ * and negative numbers by testing whether any of the highest 12 value bits
+ * are set on either argument. */
+ a.orr(TMP1, ARG2, ARG3);
+ a.tst(TMP1, imm(0xFFF0000000000000UL));
+
+ a.and_(TMP1, ARG2, ARG3);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ a.ccmp(TMP1,
+ imm(_TAG_IMMED1_SMALL),
+ imm(NZCV::kNone),
+ imm(arm::CondCode::kEQ));
+ a.b_ne(error);
+
+ /* Return `Size` + `Add` * `Unit`
+ *
+ * Note that the result takes the tag bits from `Size` */
+ a.and_(TMP2, ARG3, imm(~_TAG_IMMED1_SMALL));
+ a.mul(TMP2, TMP2, ARG4);
+ a.add(ARG1, TMP2, ARG2);
+
+ a.bind(error);
+ a.ret(a64::x30);
+}
+
+/* ARG2 = current `Size`,
+ * ARG3 = elements to `Add`,
+ * ARG4 = element `Unit` */
+void BeamGlobalAssembler::emit_bs_add_body_shared() {
+ Label error = a.newLabel();
+
+ /* Since `Unit` is guaranteed to be less than 1024, we can check overflow
+ * and negative numbers by testing whether any of the highest 12 value bits
+ * are set on either argument. */
+ a.orr(TMP1, ARG2, ARG3);
+ a.tst(TMP1, imm(0xFFF0000000000000UL));
+
+ a.and_(TMP1, ARG2, ARG3);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ a.ccmp(TMP1,
+ imm(_TAG_IMMED1_SMALL),
+ imm(NZCV::kNone),
+ imm(arm::CondCode::kEQ));
+ a.b_ne(error);
+
+ /* Return `Size` + `Add` * `Unit`
+ *
+ * Note that the result takes the tag bits from `Size` */
+ a.and_(TMP2, ARG3, imm(~_TAG_IMMED1_SMALL));
+ a.mul(TMP2, TMP2, ARG4);
+ a.add(ARG1, TMP2, ARG2);
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ emit_enter_runtime_frame();
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(beam_jit_bs_add_argument_error);
+
+ emit_leave_runtime(0);
+ emit_leave_runtime_frame();
+
+ mov_imm(ARG4, 0);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_bs_add(const ArgLabel &Fail,
+ const ArgSource &Size,
+ const ArgSource &Add,
+ const ArgWord &Unit,
+ const ArgXRegister &Dst) {
+ ASSERT(Unit.get() < 1024);
+
+ mov_arg(ARG2, Size);
+ mov_arg(ARG3, Add);
+ mov_arg(ARG4, Unit);
+
+ if (Fail.get() == 0) {
+ fragment_call(ga->get_bs_add_body_shared());
+ } else {
+ fragment_call(ga->get_bs_add_guard_shared());
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_bs_append(const ArgLabel &Fail,
+ const ArgWord &ExtraHeap,
+ const ArgWord &Live,
+ const ArgWord &Unit,
+ const ArgSource &Size,
+ const ArgSource &Bin,
+ const ArgRegister &Dst) {
+ mov_arg(ARG3, Live);
+ mov_arg(ARG4, Size);
+ mov_arg(ARG5, ExtraHeap);
+ mov_arg(ARG6, Unit);
+
+ mov_arg(ArgXRegister(Live.get()), Bin);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get() + 1);
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<6>(erts_bs_append);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get() + 1);
+
+ if (Fail.get() != 0) {
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ Label next = a.newLabel();
+
+ emit_branch_if_value(ARG1, next);
+ /* The error has been prepared in `erts_bs_append` */
+ emit_raise_exception();
+
+ a.bind(next);
+ }
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_bs_private_append(const ArgLabel &Fail,
+ const ArgWord &Unit,
+ const ArgSource &Size,
+ const ArgRegister &Src,
+ const ArgXRegister &Dst) {
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Size);
+ mov_arg(ARG4, Unit);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<4>(erts_bs_private_append);
+
+ emit_leave_runtime();
+
+ if (Fail.get() != 0) {
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ Label next = a.newLabel();
+
+ emit_branch_if_value(ARG1, next);
+ /* The error has been prepared in `erts_bs_private_append` */
+ emit_raise_exception();
+
+ a.bind(next);
+ }
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_bs_init_writable() {
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 0);
+
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, XREG0);
+
+ /* We have an implicit liveness of 0, so we don't need to stash X
+ * registers. */
+ emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>(0);
+
+ runtime_call<2>(erts_bs_init_writable);
+
+ emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>(0);
+
+ a.mov(XREG0, ARG1);
+}
+
+void BeamGlobalAssembler::emit_bs_create_bin_error_shared() {
+ a.mov(XREG0, a64::x30);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap>(0);
+
+ /* ARG3 is already set by the caller */
+ a.mov(ARG2, ARG4);
+ a.mov(ARG4, ARG1);
+ a.mov(ARG1, c_p);
+ runtime_call<4>(beam_jit_bs_construct_fail_info);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(0);
+
+ a.mov(ARG4, ZERO);
+ a.mov(ARG2, XREG0);
+ a.b(labels[raise_exception_shared]);
+}
+
+/*
+ * ARG1 = term
+ *
+ * If the term in ARG1 is a binary on entry, on return
+ * ARG1 will contain the size of the binary in bits and
+ * sign flag will be cleared.
+ *
+ * If the term is not a binary, the sign flag will be set.
+ */
+void BeamGlobalAssembler::emit_bs_bit_size_shared() {
+ Label not_sub_bin = a.newLabel();
+ Label fail = a.newLabel();
+
+ arm::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+
+ emit_is_boxed(fail, boxed_ptr);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.and_(TMP1, TMP1, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP1, imm(_TAG_HEADER_SUB_BIN));
+ a.b_ne(not_sub_bin);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ a.ldurb(TMP2.w(), emit_boxed_val(boxed_ptr, offsetof(ErlSubBin, bitsize)));
+
+ a.adds(ARG1, TMP2, TMP1, arm::lsl(3));
+ a.ret(a64::x30);
+
+ a.bind(not_sub_bin);
+ ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
+ a.and_(TMP1, TMP1, imm(~4));
+ a.cmp(TMP1, imm(_TAG_HEADER_REFC_BIN));
+ a.b_ne(fail);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ a.lsl(ARG1, TMP1, imm(3));
+ a.tst(ARG1, ARG1);
+
+ a.ret(a64::x30);
+
+ a.bind(fail);
+ mov_imm(ARG1, -1);
+ a.tst(ARG1, ARG1);
+
+ a.ret(a64::x30);
+}
+
+struct BscSegment {
+ BscSegment()
+ : type(am_false), unit(1), flags(0), src(ArgNil()), size(ArgNil()),
+ error_info(0), effectiveSize(-1) {
+ }
+
+ Eterm type;
+ Uint unit;
+ Uint flags;
+ ArgVal src;
+ ArgVal size;
+
+ Uint error_info;
+ Sint effectiveSize;
+};
+
+void BeamModuleAssembler::emit_i_bs_create_bin(const ArgLabel &Fail,
+ const ArgWord &Alloc,
+ const ArgWord &Live0,
+ const ArgRegister &Dst,
+ const Span<ArgVal> &args) {
+ Uint num_bits = 0;
+ std::size_t n = args.size();
+ std::vector<BscSegment> segments;
+ Label error;
+ ArgWord Live = Live0;
+ arm::Gp sizeReg;
+
+ /*
+ * Collect information about each segment and calculate sizes of
+ * fixed segments.
+ */
+ for (std::size_t i = 0; i < n; i += 6) {
+ BscSegment seg;
+ JitBSCOp bsc_op;
+ Uint bsc_segment;
+
+ seg.type = args[i].as<ArgImmed>().get();
+ bsc_segment = args[i + 1].as<ArgWord>().get();
+ seg.unit = args[i + 2].as<ArgWord>().get();
+ seg.flags = args[i + 3].as<ArgWord>().get();
+ seg.src = args[i + 4];
+ seg.size = args[i + 5];
+
+ switch (seg.type) {
+ case am_float:
+ bsc_op = BSC_OP_FLOAT;
+ break;
+ case am_integer:
+ bsc_op = BSC_OP_INTEGER;
+ break;
+ case am_utf8:
+ bsc_op = BSC_OP_UTF8;
+ break;
+ case am_utf16:
+ bsc_op = BSC_OP_UTF16;
+ break;
+ case am_utf32:
+ bsc_op = BSC_OP_UTF32;
+ break;
+ default:
+ bsc_op = BSC_OP_BINARY;
+ break;
+ }
+
+ /*
+ * Save segment number and operation for use in extended
+ * error information.
+ */
+ seg.error_info = beam_jit_set_bsc_segment_op(bsc_segment, bsc_op);
+
+ /*
+ * Attempt to calculate the effective size of this segment.
+ * Give up is variable or invalid.
+ */
+ if (seg.size.isSmall() && seg.unit != 0) {
+ Uint unsigned_size = seg.size.as<ArgSmall>().getUnsigned();
+
+ if ((unsigned_size >> (sizeof(Eterm) - 1) * 8) == 0) {
+ /* This multiplication cannot overflow. */
+ Uint seg_size = seg.unit * unsigned_size;
+ seg.effectiveSize = seg_size;
+ num_bits += seg_size;
+ }
+ }
+
+ if (seg.effectiveSize < 0 && seg.type != am_append &&
+ seg.type != am_private_append) {
+ /* At least one segment will need a dynamic size
+ * calculation. */
+ sizeReg = ARG8;
+ }
+
+ segments.insert(segments.end(), seg);
+ }
+
+ if (Fail.get() != 0) {
+ error = resolve_beam_label(Fail, dispUnknown);
+ } else {
+ Label past_error = a.newLabel();
+
+ a.b(past_error);
+
+ error = a.newLabel();
+ a.bind(error);
+ {
+ /*
+ * ARG1 = optional bad size value; valid if BSC_VALUE_ARG1 is set in
+ * ARG4
+ *
+ * ARG3 = optional bad size value; valid if BSC_VALUE_ARG3 is
+ * set in ARG4
+ *
+ * ARG4 = packed error information
+ */
+ comment("handle error");
+ fragment_call(ga->get_bs_create_bin_error_shared());
+ last_error_offset = a.offset();
+ }
+
+ a.bind(past_error);
+ }
+
+ /* We count the total number of bits in an unsigned integer. To
+ * avoid having to check for overflow when adding to the counter,
+ * we ensure that the signed size of each segment fits in a
+ * word. */
+ if (sizeReg.isValid()) {
+ comment("calculate sizes");
+ mov_imm(sizeReg, num_bits);
+ }
+
+ /* Generate code for calculating the size of the binary to be
+ * created. */
+ for (auto seg : segments) {
+ if (seg.effectiveSize >= 0) {
+ continue;
+ }
+
+ if (seg.type == am_append || seg.type == am_private_append) {
+ continue;
+ }
+
+ if (seg.size.isAtom() && seg.size.as<ArgAtom>().get() == am_all &&
+ seg.type == am_binary) {
+ comment("size of an entire binary");
+ mov_arg(ARG1, seg.src);
+ a.mov(ARG3, ARG1);
+ fragment_call(ga->get_bs_bit_size_shared());
+ if (exact_type(seg.src, BEAM_TYPE_BITSTRING)) {
+ comment("skipped check for success since the source "
+ "is always a bit string");
+ } else {
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG3));
+ }
+ a.b_mi(resolve_label(error, disp1MB));
+ }
+ a.add(sizeReg, sizeReg, ARG1);
+ } else if (seg.unit != 0) {
+ bool can_fail = true;
+ comment("size binary/integer/float/string");
+
+ if (always_small(seg.size)) {
+ auto [min, _] = getIntRange(seg.size);
+ if (min >= 0) {
+ can_fail = false;
+ }
+ }
+
+ mov_arg(ARG3, seg.size);
+
+ if (can_fail && Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_DEPENDS,
+ BSC_INFO_SIZE,
+ BSC_VALUE_ARG3));
+ }
+
+ if (always_small(seg.size)) {
+ comment("skipped test for small size since it is always small");
+ } else if (always_one_of(seg.size,
+ BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small size since it is a number");
+ emit_is_not_boxed(error, ARG3);
+ } else {
+ a.and_(TMP2, ARG3, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(resolve_label(error, disp1MB));
+ }
+ if (can_fail) {
+ a.tbnz(ARG3, 63, resolve_label(error, disp32K));
+ }
+ a.asr(TMP1, ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit == 1) {
+ a.add(sizeReg, sizeReg, TMP1);
+ } else {
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(
+ seg.error_info,
+ BSC_REASON_SYSTEM_LIMIT,
+ BSC_INFO_SIZE,
+ BSC_VALUE_ARG3));
+ }
+ a.tst(TMP1, imm(0xffful << 52));
+ a.b_ne(resolve_label(error, disp1MB));
+ mov_imm(TMP2, seg.unit);
+ a.madd(sizeReg, TMP1, TMP2, sizeReg);
+ }
+ } else {
+ switch (seg.type) {
+ case am_utf8: {
+ comment("size utf8");
+ Label next = a.newLabel();
+ auto src_reg = load_source(seg.src, TMP1);
+
+ a.lsr(TMP1, src_reg.reg, imm(_TAG_IMMED1_SIZE));
+ mov_imm(TMP2, 1 * 8);
+ a.cmp(TMP1, imm(0x7F));
+ a.b_ls(next);
+
+ mov_imm(TMP2, 2 * 8);
+ a.cmp(TMP1, imm(0x7FFUL));
+ a.b_ls(next);
+
+ a.cmp(TMP1, imm(0x10000UL));
+ mov_imm(TMP2, 3 * 8);
+ mov_imm(TMP3, 4 * 8);
+ a.csel(TMP2, TMP2, TMP3, arm::CondCode::kLO);
+
+ a.bind(next);
+ a.add(sizeReg, sizeReg, TMP2);
+ break;
+ }
+ case am_utf16: {
+ /* erts_bs_put_utf16 errors out whenever something's
+ * fishy, so we can return garbage (16 or 32) if our
+ * input is not a small. */
+ comment("size utf16");
+ auto src_reg = load_source(seg.src, TMP1);
+
+ a.asr(TMP1, src_reg.reg, imm(_TAG_IMMED1_SIZE));
+ a.cmp(TMP1, imm(0x10000UL));
+ mov_imm(TMP1, 2 * 8);
+ mov_imm(TMP2, 4 * 8);
+ a.csel(TMP1, TMP1, TMP2, arm::CondCode::kLO);
+ a.add(sizeReg, sizeReg, TMP1);
+ break;
+ }
+ case am_utf32: {
+ Label next = a.newLabel();
+
+ comment("size utf32");
+ mov_arg(ARG3, seg.src);
+
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG3));
+ }
+
+ a.add(sizeReg, sizeReg, imm(4 * 8));
+
+ a.and_(TMP2, ARG3, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(error);
+
+ mov_imm(TMP2, make_small(0xD800UL));
+ a.cmp(ARG3, TMP2);
+ a.b_lo(next);
+
+ mov_imm(TMP2, make_small(0xDFFFUL));
+ a.cmp(ARG3, TMP2);
+ a.b_ls(error);
+
+ mov_imm(TMP2, make_small(0x10FFFFUL));
+ a.cmp(ARG3, TMP2);
+ a.b_hi(error);
+
+ a.bind(next);
+ break;
+ }
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+ }
+
+ /* Allocate the binary. */
+ if (segments[0].type == am_append) {
+ BscSegment seg = segments[0];
+ comment("append to binary");
+ mov_arg(ARG3, Live);
+ if (sizeReg.isValid()) {
+ a.mov(ARG4, sizeReg);
+ } else {
+ mov_imm(ARG4, num_bits);
+ }
+ mov_arg(ARG5, Alloc);
+ mov_imm(ARG6, seg.unit);
+ mov_arg(ArgXRegister(Live.get()), seg.src);
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get() + 1);
+ runtime_call<6>(erts_bs_append_checked);
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(Live.get() + 1);
+
+ if (Fail.get() == 0) {
+ mov_arg(ARG3, ArgXRegister(Live.get()));
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_FVALUE,
+ BSC_VALUE_ARG3));
+ }
+ emit_branch_if_not_value(ARG1, resolve_label(error, dispUnknown));
+ } else if (segments[0].type == am_private_append) {
+ BscSegment seg = segments[0];
+ comment("private append to binary");
+ ASSERT(Alloc.get() == 0);
+ mov_arg(ARG2, seg.src);
+ if (sizeReg.isValid()) {
+ a.mov(ARG3, sizeReg);
+ } else {
+ mov_imm(ARG3, num_bits);
+ }
+ a.mov(ARG4, seg.unit);
+ a.mov(ARG1, c_p);
+ emit_enter_runtime(Live.get());
+ runtime_call<4>(erts_bs_private_append_checked);
+ emit_leave_runtime(Live.get());
+ /* There is no way the call can fail on a 64-bit architecture. */
+ } else {
+ comment("allocate binary");
+ mov_arg(ARG5, Alloc);
+ mov_arg(ARG6, Live);
+ load_erl_bits_state(ARG3);
+ load_x_reg_array(ARG2);
+ a.mov(ARG1, c_p);
+ emit_enter_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>(Live.get());
+ if (sizeReg.isValid()) {
+ comment("(size in bits)");
+ a.mov(ARG4, sizeReg);
+ runtime_call<6>(beam_jit_bs_init_bits);
+ } else if (num_bits % 8 == 0) {
+ comment("(size in bytes)");
+ mov_imm(ARG4, num_bits / 8);
+ runtime_call<6>(beam_jit_bs_init);
+ } else {
+ mov_imm(ARG4, num_bits);
+ runtime_call<6>(beam_jit_bs_init_bits);
+ }
+ emit_leave_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eXRegs>(Live.get());
+ }
+ a.str(ARG1, TMP_MEM1q);
+
+ /* Build each segment of the binary. */
+ for (auto seg : segments) {
+ switch (seg.type) {
+ case am_append:
+ case am_private_append:
+ break;
+ case am_binary: {
+ Uint error_info;
+ bool can_fail = true;
+
+ comment("construct a binary segment");
+ if (seg.effectiveSize >= 0) {
+ /* The segment has a literal size. */
+ mov_imm(ARG3, seg.effectiveSize);
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG1, c_p);
+ emit_enter_runtime<Update::eReductions>(Live.get());
+ runtime_call<3>(erts_new_bs_put_binary);
+ emit_leave_runtime<Update::eReductions>(Live.get());
+ error_info = beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_DEPENDS,
+ BSC_VALUE_FVALUE);
+ } else if (seg.size.isAtom() &&
+ seg.size.as<ArgAtom>().get() == am_all) {
+ /* Include the entire binary/bitstring in the
+ * resulting binary. */
+ a.mov(ARG3, seg.unit);
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG1, c_p);
+
+ emit_enter_runtime<Update::eReductions>(Live.get());
+ runtime_call<3>(erts_new_bs_put_binary_all);
+ emit_leave_runtime<Update::eReductions>(Live.get());
+
+ error_info = beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_UNIT,
+ BSC_VALUE_FVALUE);
+ if (seg.unit == 1) {
+ comment("skipped test for success because unit =:= 1");
+ can_fail = false;
+ }
+ } else {
+ /* The size is a variable. We have verified that
+ * the value is a non-negative small in the
+ * appropriate range. Multiply the size with the
+ * unit. */
+ mov_arg(ARG3, seg.size);
+ a.asr(ARG3, ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit != 1) {
+ mov_imm(TMP1, seg.unit);
+ a.mul(ARG3, ARG3, TMP1);
+ }
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG1, c_p);
+
+ emit_enter_runtime<Update::eReductions>(Live.get());
+ runtime_call<3>(erts_new_bs_put_binary);
+ emit_leave_runtime<Update::eReductions>(Live.get());
+
+ error_info = beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_DEPENDS,
+ BSC_VALUE_FVALUE);
+ }
+
+ if (can_fail) {
+ if (Fail.get() == 0) {
+ mov_imm(ARG4, error_info);
+ }
+ a.cbz(ARG1, resolve_label(error, disp1MB));
+ }
+ break;
+ }
+ case am_float:
+ comment("construct float segment");
+ if (seg.effectiveSize >= 0) {
+ mov_imm(ARG3, seg.effectiveSize);
+ } else {
+ mov_arg(ARG3, seg.size);
+ a.asr(ARG3, ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit != 1) {
+ mov_imm(TMP1, seg.unit);
+ a.mul(ARG3, ARG3, TMP1);
+ }
+ }
+ mov_arg(ARG2, seg.src);
+ mov_imm(ARG4, seg.flags);
+ a.mov(ARG1, c_p);
+
+ emit_enter_runtime(Live.get());
+ runtime_call<4>(erts_new_bs_put_float);
+ emit_leave_runtime(Live.get());
+
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_FVALUE,
+ BSC_VALUE_ARG1));
+ }
+ emit_branch_if_value(ARG1, resolve_label(error, dispUnknown));
+ break;
+ case am_integer:
+ comment("construct integer segment");
+ if (seg.effectiveSize >= 0) {
+ mov_imm(ARG3, seg.effectiveSize);
+ } else {
+ mov_arg(ARG3, seg.size);
+ a.asr(ARG3, ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit != 1) {
+ mov_imm(TMP1, seg.unit);
+ a.mul(ARG3, ARG3, TMP1);
+ }
+ }
+ mov_arg(ARG2, seg.src);
+ mov_imm(ARG4, seg.flags);
+ load_erl_bits_state(ARG1);
+
+ emit_enter_runtime(Live.get());
+ runtime_call<4>(erts_new_bs_put_integer);
+ emit_leave_runtime(Live.get());
+
+ if (exact_type(seg.src, BEAM_TYPE_INTEGER)) {
+ comment("skipped test for success because construction can't "
+ "fail");
+ } else {
+ if (Fail.get() == 0) {
+ mov_arg(ARG3, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG3));
+ }
+ a.cbz(ARG1, resolve_label(error, disp1MB));
+ }
+ break;
+ case am_string: {
+ ArgBytePtr string_ptr(
+ ArgVal(ArgVal::BytePtr, seg.src.as<ArgWord>().get()));
+
+ comment("insert string");
+ ASSERT(seg.effectiveSize >= 0);
+ mov_imm(ARG3, seg.effectiveSize / 8);
+ mov_arg(ARG2, string_ptr);
+ load_erl_bits_state(ARG1);
+
+ emit_enter_runtime(Live.get());
+ runtime_call<3>(erts_new_bs_put_string);
+ emit_leave_runtime(Live.get());
+ break;
+ }
+ case am_utf8:
+ comment("construct utf8 segment");
+ mov_arg(ARG2, seg.src);
+ load_erl_bits_state(ARG1);
+
+ emit_enter_runtime(Live.get());
+ runtime_call<2>(erts_bs_put_utf8);
+
+ emit_leave_runtime(Live.get());
+ if (Fail.get() == 0) {
+ mov_arg(ARG3, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG3));
+ }
+ a.cbz(ARG1, resolve_label(error, disp1MB));
+ break;
+ case am_utf16:
+ comment("construct utf8 segment");
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG3, seg.flags);
+ load_erl_bits_state(ARG1);
+
+ emit_enter_runtime(Live.get());
+ runtime_call<3>(erts_bs_put_utf16);
+ emit_leave_runtime(Live.get());
+
+ if (Fail.get() == 0) {
+ mov_arg(ARG3, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG3));
+ }
+ a.cbz(ARG1, resolve_label(error, disp1MB));
+ break;
+ case am_utf32:
+ mov_arg(ARG2, seg.src);
+ mov_imm(ARG3, 4 * 8);
+ a.mov(ARG4, seg.flags);
+ load_erl_bits_state(ARG1);
+
+ emit_enter_runtime(Live.get());
+ runtime_call<4>(erts_new_bs_put_integer);
+ emit_leave_runtime(Live.get());
+
+ if (Fail.get() == 0) {
+ mov_arg(ARG3, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG3));
+ }
+ a.cbz(ARG1, resolve_label(error, disp1MB));
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ comment("done");
+ mov_arg(Dst, TMP_MEM1q);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_call.cpp b/erts/emulator/beam/jit/arm/instr_call.cpp
new file mode 100644
index 0000000000..58bbd45a42
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_call.cpp
@@ -0,0 +1,217 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "beam_common.h"
+}
+
+void BeamGlobalAssembler::emit_dispatch_return() {
+ a.mov(ARG3, a64::x30);
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, current)));
+ mov_imm(TMP1, 1);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, arity)));
+ a.b(labels[context_switch_simplified]);
+}
+
+void BeamModuleAssembler::emit_return() {
+ emit_leave_erlang_frame();
+
+#ifdef JIT_HARD_DEBUG
+ /* Validate return address and {x,0} */
+ emit_validate(ArgVal(ArgVal::Word, 1));
+#endif
+
+ /* The reduction test is kept in module code because moving it to a shared
+ * fragment caused major performance regressions in dialyzer. */
+ a.subs(FCALLS, FCALLS, imm(1));
+ a.b_mi(resolve_fragment(ga->get_dispatch_return(), disp1MB));
+
+ a.ret(a64::x30);
+}
+
+void BeamModuleAssembler::emit_i_call(const ArgLabel &CallTarget) {
+ erlang_call(resolve_beam_label(CallTarget, disp128MB));
+}
+
+void BeamModuleAssembler::emit_i_call_last(const ArgLabel &CallTarget,
+ const ArgWord &Deallocate) {
+ emit_deallocate(Deallocate);
+ emit_i_call_only(CallTarget);
+}
+
+void BeamModuleAssembler::emit_i_call_only(const ArgLabel &CallTarget) {
+ emit_leave_erlang_frame();
+ a.b(resolve_beam_label(CallTarget, disp128MB));
+}
+
+/* Handles save_calls. When the active code index is ERTS_SAVE_CALLS_CODE_IX,
+ * all remote calls will land here.
+ *
+ * Export entry is in ARG1, return address is in LR (x30). Both of these must
+ * be preserved since this runs between caller and callee. */
+void BeamGlobalAssembler::emit_dispatch_save_calls() {
+ a.str(ARG1, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ a.mov(ARG2, ARG1);
+ a.mov(ARG1, c_p);
+ runtime_call<2>(save_calls);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.ldr(ARG1, TMP_MEM1q);
+
+ /* Keep going with the actual code index. */
+ a.mov(TMP1, imm(&the_active_code_index));
+ a.ldr(TMP1.w(), arm::Mem(TMP1));
+
+ branch(emit_setup_dispatchable_call(ARG1, TMP1));
+}
+
+void BeamModuleAssembler::emit_i_call_ext(const ArgExport &Exp) {
+ mov_arg(ARG1, Exp);
+
+ arm::Mem target = emit_setup_dispatchable_call(ARG1);
+ erlang_call(target);
+}
+
+void BeamModuleAssembler::emit_i_call_ext_only(const ArgExport &Exp) {
+ mov_arg(ARG1, Exp);
+
+ arm::Mem target = emit_setup_dispatchable_call(ARG1);
+ emit_leave_erlang_frame();
+ branch(target);
+}
+
+void BeamModuleAssembler::emit_i_call_ext_last(const ArgExport &Exp,
+ const ArgWord &Deallocate) {
+ emit_deallocate(Deallocate);
+ emit_i_call_ext_only(Exp);
+}
+
+static ErtsCodeMFA apply3_mfa = {am_erlang, am_apply, 3};
+
+arm::Mem BeamModuleAssembler::emit_variable_apply(bool includeI) {
+ Label dispatch = a.newLabel(), entry = a.newLabel();
+
+ a.bind(entry);
+
+ emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap |
+ Update::eXRegs>(3);
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+
+ if (includeI) {
+ a.adr(ARG3, entry);
+ } else {
+ mov_imm(ARG3, 0);
+ }
+
+ mov_imm(ARG4, 0);
+
+ comment("apply()");
+ runtime_call<4>(apply);
+
+ /* Any number of X registers can be live at this point. */
+ emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap |
+ Update::eXRegs>();
+
+ a.cbnz(ARG1, dispatch);
+ emit_raise_exception(entry, &apply3_mfa);
+
+ a.bind(dispatch);
+ return emit_setup_dispatchable_call(ARG1);
+}
+
+void BeamModuleAssembler::emit_i_apply() {
+ arm::Mem target = emit_variable_apply(false);
+ erlang_call(target);
+}
+
+void BeamModuleAssembler::emit_i_apply_last(const ArgWord &Deallocate) {
+ emit_deallocate(Deallocate);
+ emit_i_apply_only();
+}
+
+void BeamModuleAssembler::emit_i_apply_only() {
+ arm::Mem target = emit_variable_apply(true);
+
+ emit_leave_erlang_frame();
+ branch(target);
+}
+
+arm::Mem BeamModuleAssembler::emit_fixed_apply(const ArgWord &Arity,
+ bool includeI) {
+ Label dispatch = a.newLabel(), entry = a.newLabel();
+
+ a.bind(entry);
+
+ mov_arg(ARG3, Arity);
+
+ emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap |
+ Update::eXRegs>(Arity.get() + 2);
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+
+ if (includeI) {
+ a.adr(ARG4, entry);
+ } else {
+ mov_imm(ARG4, 0);
+ }
+
+ mov_imm(ARG5, 0);
+
+ runtime_call<5>(fixed_apply);
+
+ /* We will need to reload all X registers in case there has been
+ * an error. */
+ emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap |
+ Update::eXRegs>();
+
+ a.cbnz(ARG1, dispatch);
+ emit_raise_exception(entry, &apply3_mfa);
+
+ a.bind(dispatch);
+
+ return emit_setup_dispatchable_call(ARG1);
+}
+
+void BeamModuleAssembler::emit_apply(const ArgWord &Arity) {
+ arm::Mem target = emit_fixed_apply(Arity, false);
+ erlang_call(target);
+}
+
+void BeamModuleAssembler::emit_apply_last(const ArgWord &Arity,
+ const ArgWord &Deallocate) {
+ emit_deallocate(Deallocate);
+
+ arm::Mem target = emit_fixed_apply(Arity, true);
+
+ emit_leave_erlang_frame();
+ branch(target);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_common.cpp b/erts/emulator/beam/jit/arm/instr_common.cpp
new file mode 100644
index 0000000000..39a64f263f
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_common.cpp
@@ -0,0 +1,1757 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Notes.
+ *
+ * The immediate operand for the and, orr, eor, and tst instructions
+ * follow special rules.
+ *
+ * For our purposes, only bit patterns consisting of 1 through 63 ones
+ * at any position in a word are possible to encode as an
+ * immediate. Other patterns must be loaded into a tempoary register.
+ *
+ * Here are some examples of possible immediate values:
+ *
+ * 0b00000011
+ * 0b00001111
+ * 0b00111100
+ *
+ * 0xFFFFFFFFFFFFFFF0
+ * 0x100000000000000F
+ *
+ * The last one is possible because it is the pattern 0x1F
+ * (0b00011111) rotated right one position.
+ *
+ * Here is an example of mask that is not a possible to encode as an
+ * immediate:
+ *
+ * 0b111011
+ *
+ * For more about the encoding rules, see:
+ *
+ * https://stackoverflow.com/questions/30904718/range-of-immediate-values-in-armv8-a64-assembly
+ *
+ */
+
+#include <algorithm>
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "erl_bif_table.h"
+#include "big.h"
+#include "beam_catches.h"
+#include "beam_common.h"
+#include "code_ix.h"
+}
+
+using namespace asmjit;
+
+/* Helpers */
+
+void BeamModuleAssembler::emit_error(int reason) {
+ mov_imm(TMP1, reason);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ emit_raise_exception();
+}
+
+void BeamModuleAssembler::emit_gc_test_preserve(const ArgWord &Need,
+ const ArgWord &Live,
+ arm::Gp term) {
+ const int32_t bytes_needed = (Need.get() + S_RESERVED) * sizeof(Eterm);
+ Label after_gc_check = a.newLabel();
+
+ add(ARG3, HTOP, bytes_needed);
+ a.cmp(ARG3, E);
+ a.b_ls(after_gc_check);
+
+ ASSERT(Live.get() < ERTS_X_REGS_ALLOCATED);
+ mov_arg(ArgVal(ArgVal::XReg, Live.get()), term);
+
+ mov_imm(ARG4, Live.get() + 1);
+ fragment_call(ga->get_garbage_collect());
+
+ mov_arg(term, ArgVal(ArgVal::XReg, Live.get()));
+
+ a.bind(after_gc_check);
+}
+
+void BeamModuleAssembler::emit_gc_test(const ArgWord &Ns,
+ const ArgWord &Nh,
+ const ArgWord &Live) {
+ int32_t bytes_needed = (Ns.get() + Nh.get() + S_RESERVED) * sizeof(Eterm);
+ Label after_gc_check = a.newLabel();
+
+ add(ARG3, HTOP, bytes_needed);
+ a.cmp(ARG3, E);
+ a.b_ls(after_gc_check);
+
+ mov_imm(ARG4, Live.get());
+ fragment_call(ga->get_garbage_collect());
+
+ a.bind(after_gc_check);
+}
+
+void BeamModuleAssembler::emit_validate(const ArgWord &Arity) {
+#ifdef DEBUG
+ Label next = a.newLabel(), crash = a.newLabel();
+
+ /* Crash if the Erlang heap is not word-aligned */
+ a.tst(HTOP, imm(sizeof(Eterm) - 1));
+ a.b_ne(crash);
+
+ /* Crash if the Erlang stack is not word-aligned */
+ a.tst(E, imm(sizeof(Eterm) - 1));
+ a.b_ne(crash);
+
+ /* Crash if we've overrun the stack */
+ lea(TMP1, arm::Mem(E, -(int32_t)(S_REDZONE * sizeof(Eterm))));
+ a.cmp(HTOP, TMP1);
+ a.b_hi(crash);
+
+ a.b(next);
+
+ a.bind(crash);
+ a.udf(0xbad);
+ a.bind(next);
+
+# ifdef JIT_HARD_DEBUG
+ emit_enter_runtime_frame();
+
+ for (unsigned i = 0; i < arity.get(); i++) {
+ mov_arg(ARG1, ArgVal(ArgVal::XReg, i));
+
+ emit_enter_runtime();
+ runtime_call<1>(beam_jit_validate_term);
+ emit_leave_runtime();
+ }
+
+ emit_leave_runtime_frame();
+# endif
+
+#endif
+}
+
+/* Instrs */
+
+void BeamModuleAssembler::emit_i_validate(const ArgWord &Arity) {
+ emit_validate(Arity);
+}
+
+void BeamModuleAssembler::emit_allocate_heap(const ArgWord &NeedStack,
+ const ArgWord &NeedHeap,
+ const ArgWord &Live) {
+ ASSERT(NeedStack.get() <= MAX_REG);
+
+ emit_gc_test(NeedStack, NeedHeap, Live);
+
+ if (NeedStack.get() > 0) {
+ sub(E, E, NeedStack.get() * sizeof(Eterm));
+ }
+}
+
+void BeamModuleAssembler::emit_allocate(const ArgWord &NeedStack,
+ const ArgWord &Live) {
+ emit_allocate_heap(NeedStack, ArgWord(0), Live);
+}
+
+void BeamModuleAssembler::emit_deallocate(const ArgWord &Deallocate) {
+ ASSERT(Deallocate.get() <= 1023);
+
+ if (Deallocate.get() > 0) {
+ add(E, E, Deallocate.get() * sizeof(Eterm));
+ }
+}
+
+void BeamModuleAssembler::emit_test_heap(const ArgWord &Nh,
+ const ArgWord &Live) {
+ emit_gc_test(ArgWord(0), Nh, Live);
+}
+
+void BeamModuleAssembler::emit_normal_exit() {
+ /* This is implicitly global; it does not normally appear in modules and
+ * doesn't require size optimization. */
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+ emit_proc_lc_unrequire();
+
+ mov_imm(TMP1, EXC_NORMAL);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, arity)));
+ a.mov(ARG1, c_p);
+ mov_imm(ARG2, am_normal);
+ runtime_call<2>(erts_do_exit_process);
+
+ emit_proc_lc_require();
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.b(resolve_fragment(ga->get_do_schedule(), disp128MB));
+}
+
+void BeamModuleAssembler::emit_continue_exit() {
+ /* This is implicitly global; it does not normally appear in modules and
+ * doesn't require size optimization. */
+
+ emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>(0);
+ emit_proc_lc_unrequire();
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(erts_continue_exit_process);
+
+ emit_proc_lc_require();
+ emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>(0);
+
+ a.b(resolve_fragment(ga->get_do_schedule(), disp128MB));
+}
+
+void BeamModuleAssembler::emit_get_list(const ArgRegister &Src,
+ const ArgRegister &Hd,
+ const ArgRegister &Tl) {
+ auto src = load_source(Src, TMP1);
+ auto hd = init_destination(Hd, TMP2);
+ auto tl = init_destination(Tl, TMP3);
+ arm::Gp cons_ptr = emit_ptr_val(TMP1, src.reg);
+
+ /* The `ldp` instruction does not accept a negative offset, so we
+ * will need subtract the LIST tag beforehand. (This also nicely
+ * take care of the potential overwriting issue when Src == Hd.) */
+ a.sub(TMP1, cons_ptr, imm(TAG_PRIMARY_LIST));
+ if (hd.reg == tl.reg) {
+ /* ldp with two identical registers is an illegal
+ * instruction. Produce the same result at the interpreter. */
+ a.ldr(tl.reg, arm::Mem(TMP1, sizeof(Eterm)));
+ flush_var(tl);
+ } else {
+ a.ldp(hd.reg, tl.reg, arm::Mem(TMP1));
+ flush_vars(hd, tl);
+ }
+}
+
+void BeamModuleAssembler::emit_get_hd(const ArgRegister &Src,
+ const ArgRegister &Hd) {
+ auto src = load_source(Src, TMP1);
+ auto hd = init_destination(Hd, TMP2);
+ arm::Gp cons_ptr = emit_ptr_val(TMP1, src.reg);
+
+ a.ldur(hd.reg, getCARRef(cons_ptr));
+ flush_var(hd);
+}
+
+void BeamModuleAssembler::emit_get_tl(const ArgRegister &Src,
+ const ArgRegister &Tl) {
+ auto src = load_source(Src, TMP1);
+ auto tl = init_destination(Tl, TMP2);
+ arm::Gp cons_ptr = emit_ptr_val(TMP1, src.reg);
+
+ a.ldur(tl.reg, getCDRRef(cons_ptr));
+ flush_var(tl);
+}
+
+void BeamModuleAssembler::emit_i_get(const ArgSource &Src,
+ const ArgRegister &Dst) {
+ mov_arg(ARG2, Src);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_pd_hash_get);
+
+ emit_leave_runtime();
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_i_get_hash(const ArgConstant &Src,
+ const ArgWord &Hash,
+ const ArgRegister &Dst) {
+ mov_arg(ARG2, Hash);
+ mov_arg(ARG3, Src);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_pd_hash_get_with_hx);
+
+ emit_leave_runtime();
+
+ mov_arg(Dst, ARG1);
+}
+
+/* Store the untagged pointer to a tuple in ARG1. */
+void BeamModuleAssembler::emit_load_tuple_ptr(const ArgSource &Src) {
+ auto src = load_source(Src, ARG1);
+ emit_untag_ptr(ARG1, src.reg);
+}
+
+#ifdef DEBUG
+/* Emit an assertion to ensure that tuple_reg points into the same
+ * tuple as Src. */
+void BeamModuleAssembler::emit_tuple_assertion(const ArgSource &Src,
+ arm::Gp tuple_reg) {
+ Label ok = a.newLabel(), fatal = a.newLabel();
+ ASSERT(tuple_reg != TMP1);
+ mov_arg(TMP1, Src);
+ emit_is_boxed(fatal, TMP1);
+ emit_untag_ptr(TMP1, TMP1);
+ a.cmp(TMP1, tuple_reg);
+ a.b_eq(ok);
+
+ a.bind(fatal);
+ a.udf(0xaaaa);
+ a.bind(ok);
+}
+#endif
+
+/* Fetch an element from the tuple pointed to by the untagged pointer
+ * in ARG1. */
+void BeamModuleAssembler::emit_i_get_tuple_element(const ArgSource &Src,
+ const ArgWord &Element,
+ const ArgRegister &Dst) {
+#ifdef DEBUG
+ emit_tuple_assertion(Src, ARG1);
+#endif
+
+ auto dst = init_destination(Dst, TMP1);
+ safe_ldr(dst.reg, arm::Mem(ARG1, Element.get()));
+ flush_var(dst);
+}
+
+/* Fetch two consecutive tuple elements from the tuple pointed to by
+ * the boxed pointer in ARG1. */
+void BeamModuleAssembler::emit_get_two_tuple_elements(const ArgSource &Src,
+ const ArgWord &Element,
+ const ArgRegister &Dst1,
+ const ArgRegister &Dst2) {
+#ifdef DEBUG
+ emit_tuple_assertion(Src, ARG1);
+#endif
+
+ auto dst1 = init_destination(Dst1, TMP1);
+ auto dst2 = init_destination(Dst2, TMP2);
+
+ arm::Mem element_ptr = arm::Mem(ARG1, Element.get());
+ safe_ldp(dst1.reg, dst2.reg, element_ptr);
+ flush_vars(dst1, dst2);
+}
+
+void BeamModuleAssembler::emit_init(const ArgYRegister &Y) {
+ mov_imm(TMP1, NIL);
+ a.str(TMP1, getArgRef(Y));
+}
+
+void BeamModuleAssembler::emit_init_yregs(const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ unsigned count = Size.get();
+ ASSERT(count == args.size());
+
+ unsigned i = 0;
+
+ mov_imm(TMP1, NIL);
+
+ while (i < count) {
+ unsigned first_y = args[i].as<ArgYRegister>().get();
+ unsigned slots = 1;
+
+ while (i + slots < count) {
+ unsigned current_y = args[i + slots].as<ArgYRegister>().get();
+
+ if (first_y + slots != current_y) {
+ break;
+ }
+ slots++;
+ }
+
+ i += slots;
+
+ /* Now first_y is the number of the first y register to be initialized
+ * and slots is the number of y registers to be initialized. */
+ while (slots >= 2) {
+ /* `stp` can only address the first 64 Y registers. */
+ if (first_y <= MAX_LDP_STP_DISPLACEMENT) {
+ a.stp(TMP1, TMP1, getYRef(first_y));
+ first_y += 2;
+ slots -= 2;
+ } else {
+ a.str(TMP1, getYRef(first_y));
+ first_y += 1;
+ slots -= 1;
+ }
+ }
+
+ if (slots == 1) {
+ a.str(TMP1, getYRef(first_y));
+ }
+ }
+}
+
+void BeamModuleAssembler::emit_trim(const ArgWord &Words,
+ const ArgWord &Remaining) {
+ ASSERT(Words.get() <= 1023);
+
+ if (Words.get() > 0) {
+ add(E, E, Words.get() * sizeof(Eterm));
+ }
+}
+
+void BeamModuleAssembler::emit_i_move(const ArgSource &Src,
+ const ArgRegister &Dst) {
+ mov_arg(Dst, Src);
+}
+
+void BeamModuleAssembler::emit_store_two_xregs(const ArgXRegister &Src1,
+ const ArgYRegister &Dst1,
+ const ArgXRegister &Src2,
+ const ArgYRegister &Dst2) {
+ auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2);
+ safe_stp(src1.reg, src2.reg, Dst1, Dst2);
+}
+
+void BeamModuleAssembler::emit_load_two_xregs(const ArgYRegister &Src1,
+ const ArgXRegister &Dst1,
+ const ArgYRegister &Src2,
+ const ArgXRegister &Dst2) {
+ ASSERT(ArgVal::memory_relation(Src1, Src2) ==
+ ArgVal::Relation::consecutive);
+ auto dst1 = init_destination(Dst1, TMP1);
+ auto dst2 = init_destination(Dst2, TMP2);
+
+ safe_ldp(dst1.reg, dst2.reg, Src1, Src2);
+ flush_vars(dst1, dst2);
+}
+
+void BeamModuleAssembler::emit_move_two_yregs(const ArgYRegister &Src1,
+ const ArgYRegister &Dst1,
+ const ArgYRegister &Src2,
+ const ArgYRegister &Dst2) {
+ /* Optimize fetching of source Y registers. */
+ switch (ArgVal::memory_relation(Src1, Src2)) {
+ case ArgVal::Relation::consecutive:
+ safe_ldp(TMP1, TMP2, Src1, Src2);
+ break;
+ case ArgVal::Relation::reverse_consecutive:
+ safe_ldp(TMP2, TMP1, Src2, Src1);
+ break;
+ case ArgVal::Relation::none:
+ a.ldr(TMP1, getArgRef(Src1));
+ a.ldr(TMP2, getArgRef(Src2));
+ break;
+ }
+
+ /* Destination registers are always in consecutive order. */
+ safe_stp(TMP1, TMP2, Dst1, Dst2);
+}
+
+void BeamModuleAssembler::emit_swap(const ArgRegister &R1,
+ const ArgRegister &R2) {
+ if (isRegisterBacked(R1)) {
+ auto r1 = load_source(R1, ZERO);
+ mov_arg(TMP1, R2);
+ mov_arg(R2, R1);
+ a.mov(r1.reg, TMP1);
+ } else if (isRegisterBacked(R2)) {
+ return emit_swap(R2, R1);
+ } else {
+ switch (ArgVal::memory_relation(R1, R2)) {
+ case ArgVal::Relation::consecutive:
+ safe_ldp(TMP1, TMP2, R1, R2);
+ safe_stp(TMP2, TMP1, R1, R2);
+ break;
+ case ArgVal::Relation::reverse_consecutive:
+ safe_ldp(TMP1, TMP2, R2, R1);
+ safe_stp(TMP2, TMP1, R2, R1);
+ break;
+ case ArgVal::Relation::none:
+ a.ldr(TMP1, getArgRef(R1));
+ a.ldr(TMP2, getArgRef(R2));
+ a.str(TMP1, getArgRef(R2));
+ a.str(TMP2, getArgRef(R1));
+ break;
+ }
+ }
+}
+
+void BeamModuleAssembler::emit_swap2(const ArgRegister &R1,
+ const ArgRegister &R2,
+ const ArgRegister &R3) {
+ auto [arg1, arg2] = load_sources(R1, TMP1, R2, TMP2);
+ auto arg3 = load_source(R3, TMP3);
+
+ mov_var(TMP4, arg1);
+ mov_var(arg1, arg2);
+ mov_var(arg2, arg3);
+ mov_var(arg3, TMP4);
+
+ flush_vars(arg1, arg2);
+ flush_var(arg3);
+}
+
+void BeamModuleAssembler::emit_swap3(const ArgRegister &R1,
+ const ArgRegister &R2,
+ const ArgRegister &R3,
+ const ArgRegister &R4) {
+ auto [arg1, arg2] = load_sources(R1, TMP1, R2, TMP2);
+ auto [arg3, arg4] = load_sources(R3, TMP3, R4, TMP4);
+
+ mov_var(TMP5, arg1);
+ mov_var(arg1, arg2);
+ mov_var(arg2, arg3);
+ mov_var(arg3, arg4);
+ mov_var(arg4, TMP5);
+
+ flush_vars(arg1, arg2);
+ flush_vars(arg3, arg4);
+}
+
+void BeamModuleAssembler::emit_swap4(const ArgRegister &R1,
+ const ArgRegister &R2,
+ const ArgRegister &R3,
+ const ArgRegister &R4,
+ const ArgRegister &R5) {
+ auto [arg1, arg2] = load_sources(R1, TMP1, R2, TMP2);
+ auto [arg3, arg4] = load_sources(R3, TMP3, R4, TMP4);
+ auto arg5 = load_source(R5, TMP5);
+
+ mov_var(TMP6, arg1);
+ mov_var(arg1, arg2);
+ mov_var(arg2, arg3);
+ mov_var(arg3, arg4);
+ mov_var(arg4, arg5);
+ mov_var(arg5, TMP6);
+
+ flush_vars(arg1, arg2);
+ flush_vars(arg3, arg4);
+ flush_var(arg5);
+}
+
+void BeamModuleAssembler::emit_node(const ArgRegister &Dst) {
+ a.ldr(TMP1, embed_constant(&erts_this_node, disp32K));
+ a.ldr(TMP1, arm::Mem(TMP1));
+ mov_arg(Dst, arm::Mem(TMP1, offsetof(ErlNode, sysname)));
+}
+
+void BeamModuleAssembler::emit_put_list(const ArgSource &Hd,
+ const ArgSource &Tl,
+ const ArgRegister &Dst) {
+ auto [hd, tl] = load_sources(Hd, TMP1, Tl, TMP2);
+ auto dst = init_destination(Dst, TMP3);
+
+ a.stp(hd.reg, tl.reg, arm::Mem(HTOP).post(sizeof(Eterm[2])));
+ a.sub(dst.reg, HTOP, imm(sizeof(Eterm[2]) - TAG_PRIMARY_LIST));
+
+ flush_var(dst);
+}
+
+void BeamModuleAssembler::emit_put_list2(const ArgSource &Hd1,
+ const ArgSource &Hd2,
+ const ArgSource &Tl,
+ const ArgRegister &Dst) {
+ const arm::Mem put_cons = arm::Mem(HTOP).post(sizeof(Eterm[2]));
+
+ auto [hd1, hd2] = load_sources(Hd1, TMP1, Hd2, TMP2);
+ auto tl = load_source(Tl, TMP3);
+ auto dst = init_destination(Dst, TMP4);
+
+ a.stp(hd1.reg, tl.reg, put_cons);
+ a.sub(dst.reg, HTOP, imm(sizeof(Eterm[2]) - TAG_PRIMARY_LIST));
+
+ a.stp(hd2.reg, dst.reg, put_cons);
+ a.sub(dst.reg, HTOP, imm(sizeof(Eterm[2]) - TAG_PRIMARY_LIST));
+
+ flush_var(dst);
+}
+
+void BeamModuleAssembler::emit_put_tuple2(const ArgRegister &Dst,
+ const ArgWord &Arity,
+ const Span<ArgVal> &args) {
+ ASSERT(arityval(Arity.get()) == args.size());
+
+ std::vector<ArgVal> data;
+ data.reserve(args.size() + 1);
+ data.push_back(Arity);
+
+ bool dst_is_src = false;
+ for (auto arg : args) {
+ data.push_back(arg);
+ dst_is_src |= (arg == Dst);
+ }
+
+ if (dst_is_src) {
+ a.add(TMP1, HTOP, TAG_PRIMARY_BOXED);
+ } else {
+ auto ptr = init_destination(Dst, TMP1);
+ a.add(ptr.reg, HTOP, TAG_PRIMARY_BOXED);
+ flush_var(ptr);
+ }
+
+ size_t size = data.size();
+ unsigned i;
+ for (i = 0; i < size - 1; i += 2) {
+ if ((i % 128) == 0) {
+ check_pending_stubs();
+ }
+
+ auto [first, second] = load_sources(data[i], TMP2, data[i + 1], TMP3);
+ a.stp(first.reg, second.reg, arm::Mem(HTOP).post(sizeof(Eterm[2])));
+ }
+
+ if (i < size) {
+ mov_arg(arm::Mem(HTOP).post(sizeof(Eterm)), data[i]);
+ }
+
+ if (dst_is_src) {
+ auto ptr = init_destination(Dst, TMP1);
+ mov_var(ptr, TMP1);
+ flush_var(ptr);
+ }
+}
+
+void BeamModuleAssembler::emit_self(const ArgRegister &Dst) {
+ mov_arg(Dst, arm::Mem(c_p, offsetof(Process, common.id)));
+}
+
+void BeamModuleAssembler::emit_set_tuple_element(const ArgSource &Element,
+ const ArgRegister &Tuple,
+ const ArgWord &Offset) {
+ auto tuple = load_source(Tuple, TMP1);
+ auto element = load_source(Element, TMP2);
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, tuple.reg);
+ arm::Mem boxed_val = emit_boxed_val(boxed_ptr, Offset.get());
+
+ stur(element.reg, boxed_val);
+}
+
+void BeamModuleAssembler::emit_is_nonempty_list(const ArgLabel &Fail,
+ const ArgRegister &Src) {
+ auto list_ptr = load_source(Src, TMP1);
+ const int bitNumber = 1;
+
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST == (1 << bitNumber));
+ a.tbnz(list_ptr.reg, imm(bitNumber), resolve_beam_label(Fail, disp32K));
+}
+
+void BeamModuleAssembler::emit_jump(const ArgLabel &Fail) {
+ a.b(resolve_beam_label(Fail, disp128MB));
+}
+
+void BeamModuleAssembler::emit_is_atom(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+
+ a.and_(TMP1, src.reg, imm(_TAG_IMMED2_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED2_ATOM));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+void BeamModuleAssembler::emit_is_boolean(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ /* Since am_true and am_false differ by a single bit, we can simplify the
+ * check by clearing said bit and comparing against the lesser one. */
+ ERTS_CT_ASSERT(am_false == make_atom(0));
+ ERTS_CT_ASSERT(am_true == make_atom(1));
+
+ auto src = load_source(Src, TMP1);
+ a.and_(TMP1, src.reg, imm(~(am_true & ~_TAG_IMMED1_MASK)));
+ a.cmp(TMP1, imm(am_false));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+arm::Gp BeamModuleAssembler::emit_is_binary(const ArgLabel &Fail,
+ const ArgSource &Src,
+ Label next,
+ Label subbin) {
+ auto src = load_source(Src, ARG1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ arm::Gp boxed_ptr = emit_ptr_val(ARG1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.and_(TMP1, TMP1, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP1, imm(_TAG_HEADER_SUB_BIN));
+ a.b_eq(subbin);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_BITSTRING) {
+ comment("simplified binary test since source is always a bitstring "
+ "when boxed");
+ } else {
+ ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
+ a.and_(TMP1, TMP1, imm(~4));
+ a.cmp(TMP1, imm(_TAG_HEADER_REFC_BIN));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.b(next);
+
+ return boxed_ptr;
+}
+
+void BeamModuleAssembler::emit_is_binary(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ Label next = a.newLabel(), subbin = a.newLabel();
+
+ arm::Gp boxed_ptr = emit_is_binary(Fail, Src, next, subbin);
+
+ a.bind(subbin);
+ {
+ /* emit_is_binary() has already removed the literal tag (if
+ * applicable) from the copy of Src. */
+ a.ldrb(TMP1.w(),
+ emit_boxed_val(boxed_ptr, offsetof(ErlSubBin, bitsize)));
+ a.cbnz(TMP1, resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_bitstring(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ Label next = a.newLabel();
+
+ (void)emit_is_binary(Fail, Src, next, next);
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_float(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FLOAT) {
+ comment("skipped header test since we know it's a float when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+
+ a.cmp(TMP1, imm(HEADER_FLONUM));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_is_function(const ArgLabel &Fail,
+ const ArgRegister &Src) {
+ auto src = load_source(Src, TMP1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN) {
+ comment("skipped header test since we know it's a fun when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.cmp(TMP1, imm(HEADER_FUN));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_is_function2(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgSource &Arity) {
+ if (!Arity.isSmall()) {
+ /*
+ * Non-literal arity - extremely uncommon. Generate simple code.
+ */
+ mov_arg(ARG2, Src);
+ mov_arg(ARG3, Arity);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erl_is_function);
+
+ emit_leave_runtime();
+
+ a.cmp(ARG1, imm(am_true));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+
+ return;
+ }
+
+ unsigned arity = Arity.as<ArgSmall>().getUnsigned();
+ if (arity > MAX_ARG) {
+ /* Arity is negative or too large. */
+ a.b(resolve_beam_label(Fail, disp128MB));
+
+ return;
+ }
+
+ auto src = load_source(Src, TMP1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN) {
+ comment("skipped header test since we know it's a fun when boxed");
+ } else {
+ a.ldur(TMP2, emit_boxed_val(boxed_ptr));
+ a.cmp(TMP2, imm(HEADER_FUN));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.ldurb(TMP2.w(), emit_boxed_val(boxed_ptr, offsetof(ErlFunThing, arity)));
+ emit_branch_if_ne(TMP2, arity, resolve_beam_label(Fail, dispUnknown));
+}
+
+void BeamModuleAssembler::emit_is_integer(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+
+ if (always_immediate(Src)) {
+ comment("skipped test for boxed since the value is always immediate");
+ a.and_(TMP2, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+
+ return;
+ }
+
+ Label next = a.newLabel();
+
+ if (always_one_of(Src, BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified small test since all other types are boxed");
+ emit_is_boxed(next, Src, src.reg);
+ } else {
+ a.and_(TMP2, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_SMALL));
+ a.b_eq(next);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, TMP2);
+ }
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_INTEGER) {
+ comment("skipped header test since we know it's a bignum when "
+ "boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+
+ /* The following value (0b111011) is not possible to use as
+ * an immediate operand for 'and'. See the note at the beginning
+ * of the file.
+ */
+ mov_imm(TMP2, _TAG_HEADER_MASK - _BIG_SIGN_BIT);
+ a.and_(TMP1, TMP1, TMP2);
+ a.cmp(TMP1, imm(_TAG_HEADER_POS_BIG));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_list(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+
+ a.tst(src.reg, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
+ a.mov(TMP2, NIL);
+ a.ccmp(src.reg, TMP2, imm(NZCV::kEqual), imm(arm::CondCode::kNE));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+void BeamModuleAssembler::emit_is_map(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ /* As an optimization for the `error | #{}` case, skip checking the header
+ * word when we know that the only possible boxed type is a map. */
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_MAP) {
+ comment("skipped header test since we know it's a map when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.and_(TMP1, TMP1, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP1, imm(_TAG_HEADER_MAP));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_is_nil(const ArgLabel &Fail,
+ const ArgRegister &Src) {
+ auto src = load_source(Src, TMP1);
+ a.cmp(src.reg, imm(NIL));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+void BeamModuleAssembler::emit_is_number(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+ Label next = a.newLabel();
+
+ if (always_one_of(Src, BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified small test since all other types are boxed");
+ emit_is_boxed(next, Src, src.reg);
+ } else {
+ a.and_(TMP2, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_SMALL));
+ a.b_eq(next);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+ }
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) ==
+ (BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("skipped header test since we know it's a number when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+
+ /* The following value (0b111011) is not possible to use as
+ * an immediate operand for 'and'. See the note at the beginning
+ * of the file.
+ */
+ mov_imm(TMP2, _TAG_HEADER_MASK - _BIG_SIGN_BIT);
+ a.and_(TMP2, TMP1, TMP2);
+ a.cmp(TMP2, imm(_TAG_HEADER_POS_BIG));
+
+ a.mov(TMP3, imm(HEADER_FLONUM));
+ a.ccmp(TMP1, TMP3, imm(NZCV::kEqual), imm(arm::CondCode::kNE));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_pid(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+ Label next = a.newLabel();
+
+ if (always_one_of(Src, BEAM_TYPE_PID | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified local pid test since all other types are boxed");
+ emit_is_boxed(next, Src, src.reg);
+ } else {
+ a.and_(TMP2, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_PID));
+ a.b_eq(next);
+
+ /* Reuse TMP2 as the important bits are still available. */
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, TMP2);
+ }
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_PID) {
+ comment("skipped header test since we know it's a pid when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP2, emit_boxed_val(boxed_ptr));
+ a.and_(TMP2, TMP2, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP2, imm(_TAG_HEADER_EXTERNAL_PID));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_port(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+ Label next = a.newLabel();
+
+ if (always_one_of(Src, BEAM_TYPE_PORT | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified local port test since all other types are boxed");
+ emit_is_boxed(next, Src, src.reg);
+ } else {
+ a.and_(TMP2, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP2, imm(_TAG_IMMED1_PORT));
+ a.b_eq(next);
+
+ /* Reuse TMP2 as the important bits are still available. */
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, TMP2);
+ }
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_PORT) {
+ comment("skipped header test since we know it's a port when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP2, emit_boxed_val(boxed_ptr));
+ a.and_(TMP2, TMP2, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP2, imm(_TAG_HEADER_EXTERNAL_PORT));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_reference(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, TMP1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_REFERENCE) {
+ comment("skipped header test since we know it's a ref when boxed");
+ } else {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.and_(TMP1, TMP1, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP1, imm(_TAG_HEADER_EXTERNAL_REF));
+ a.ccmp(TMP1,
+ imm(_TAG_HEADER_REF),
+ imm(NZCV::kEqual),
+ imm(arm::CondCode::kNE));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+/* Note: This instruction leaves the untagged pointer to the tuple in
+ * ARG1. */
+void BeamModuleAssembler::emit_i_is_tagged_tuple(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Arity,
+ const ArgAtom &Tag) {
+ auto src = load_source(Src, ARG1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ emit_untag_ptr(ARG1, src.reg);
+
+ /* It is safe to fetch the both the header word and the first
+ * element of the tuple with ldp because the empty tuple is always
+ * a literal that is padded so that the word after arity is
+ * allocated. */
+ a.ldp(TMP1, TMP2, arm::Mem(ARG1));
+
+ if (Arity.get() < 32) {
+ cmp_arg(TMP2, Tag);
+ a.ccmp(TMP1,
+ imm(Arity.get()),
+ imm(NZCV::kNone),
+ imm(arm::CondCode::kEQ));
+ } else {
+ cmp_arg(TMP1, Arity);
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ cmp_arg(TMP2, Tag);
+ }
+
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+/* Note: This instruction leaves the untagged pointer to the tuple in
+ * ARG2. */
+void BeamModuleAssembler::emit_i_is_tagged_tuple_ff(const ArgLabel &NotTuple,
+ const ArgLabel &NotRecord,
+ const ArgSource &Src,
+ const ArgWord &Arity,
+ const ArgAtom &Tag) {
+ Label correct_arity = a.newLabel();
+ auto src = load_source(Src, ARG1);
+
+ emit_is_boxed(resolve_beam_label(NotTuple, dispUnknown), Src, src.reg);
+
+ emit_untag_ptr(ARG1, src.reg);
+
+ /* It is safe to fetch the both the header word and the first
+ * element of the tuple with ldp because the empty tuple is always
+ * a literal that is padded so that the word after arity is
+ * allocated. */
+ a.ldp(TMP1, TMP2, arm::Mem(ARG1));
+
+ cmp_arg(TMP1, Arity);
+ a.b_eq(correct_arity);
+
+ /* Not a tuple or the wrong arity. Decide which. */
+ ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
+ a.tst(TMP1, imm(_TAG_HEADER_MASK));
+ a.b_eq(resolve_beam_label(NotRecord, disp1MB));
+ a.b(resolve_beam_label(NotTuple, disp128MB));
+
+ a.bind(correct_arity);
+ {
+ cmp_arg(TMP2, Tag);
+ a.b_ne(resolve_beam_label(NotRecord, disp1MB));
+ }
+}
+
+/* Note: This instruction leaves the untagged pointer to the tuple in
+ * ARG1. */
+void BeamModuleAssembler::emit_i_is_tuple(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ auto src = load_source(Src, ARG1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+ emit_untag_ptr(ARG1, src.reg);
+
+ /* As an optimization for the `error | {ok, Value}` case, skip checking the
+ * header word when we know that the only possible boxed type is a tuple. */
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_TUPLE) {
+ comment("skipped header test since we know it's a tuple when boxed");
+ } else {
+ a.ldr(TMP1, arm::Mem(ARG1));
+ ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
+ a.tst(TMP1, imm(_TAG_HEADER_MASK));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+/* Note: This instruction leaves the untagged pointer to the tuple in
+ * ARG1. */
+void BeamModuleAssembler::emit_i_is_tuple_of_arity(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Arity) {
+ auto src = load_source(Src, ARG1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ emit_untag_ptr(ARG1, src.reg);
+
+ a.ldr(TMP1, arm::Mem(ARG1));
+ cmp_arg(TMP1, Arity);
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+/* Note: This instruction leaves the untagged pointer to the tuple in
+ * ARG1. */
+void BeamModuleAssembler::emit_i_test_arity(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Arity) {
+ auto src = load_source(Src, ARG1);
+ emit_untag_ptr(ARG1, src.reg);
+
+ a.ldr(TMP1, arm::Mem(ARG1));
+ cmp_arg(TMP1, Arity);
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+}
+
+void BeamModuleAssembler::emit_is_eq_exact(const ArgLabel &Fail,
+ const ArgSource &X,
+ const ArgSource &Y) {
+ auto x = load_source(X, ARG1);
+
+ /* If either argument is known to be an immediate, we can fail immediately
+ * if they're not equal. */
+ if (always_immediate(X) || always_immediate(Y)) {
+ if (!X.isImmed() && !Y.isImmed()) {
+ comment("simplified check since one argument is an immediate");
+ }
+
+ cmp_arg(x.reg, Y);
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+
+ return;
+ }
+
+ /* Both operands are registers. */
+ Label next = a.newLabel();
+ auto y = load_source(Y, ARG2);
+
+ a.cmp(x.reg, y.reg);
+ a.b_eq(next);
+
+ if (always_same_types(X, Y)) {
+ comment("skipped tag test since they are always equal");
+ } else {
+ /* The terms could still be equal if both operands are pointers
+ * having the same tag. */
+ emit_is_unequal_based_on_tags(x.reg, y.reg);
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+ }
+
+ /* Both operands are pointers having the same tag. Must do a
+ * deeper comparison. */
+ mov_var(ARG1, x);
+ mov_var(ARG2, y);
+
+ emit_enter_runtime();
+
+ runtime_call<2>(eq);
+
+ emit_leave_runtime();
+
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_ne_exact(const ArgLabel &Fail,
+ const ArgSource &X,
+ const ArgSource &Y) {
+ auto x = load_source(X, ARG1);
+
+ /* If either argument is known to be an immediate, we can fail immediately
+ * if they're equal. */
+ if (always_immediate(X) || always_immediate(Y)) {
+ if (!X.isImmed() && !Y.isImmed()) {
+ comment("simplified check since one argument is an immediate");
+ }
+
+ cmp_arg(x.reg, Y);
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+
+ return;
+ }
+
+ /* Both operands are registers. */
+ Label next = a.newLabel();
+ auto y = load_source(Y, ARG2);
+
+ a.cmp(x.reg, y.reg);
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+
+ if (always_same_types(X, Y)) {
+ comment("skipped tag test since they are always equal");
+ } else {
+ /* Test whether the terms are definitely unequal based on the tags
+ * alone. */
+ emit_is_unequal_based_on_tags(x.reg, y.reg);
+ a.b_eq(next);
+ }
+
+ /* Both operands are pointers having the same tag. Must do a
+ * deeper comparison. */
+ mov_var(ARG1, x);
+ mov_var(ARG2, y);
+
+ emit_enter_runtime();
+
+ runtime_call<2>(eq);
+
+ emit_leave_runtime();
+
+ a.cbnz(ARG1, resolve_beam_label(Fail, disp1MB));
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_eq(const ArgLabel &Fail,
+ const ArgSource &X,
+ const ArgSource &Y) {
+ Label next = a.newLabel();
+
+ auto x = load_source(X, ARG1);
+ auto y = load_source(Y, ARG2);
+
+ a.cmp(x.reg, y.reg);
+ a.b_eq(next);
+
+ /* We can skip deep comparisons when both args are immediates. */
+ emit_are_both_immediate(x.reg, y.reg);
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+
+ mov_var(ARG1, x);
+ mov_var(ARG2, y);
+ fragment_call(ga->get_arith_compare_shared());
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_is_ne(const ArgLabel &Fail,
+ const ArgSource &X,
+ const ArgSource &Y) {
+ Label next = a.newLabel();
+
+ auto x = load_source(X, ARG1);
+ auto y = load_source(Y, ARG2);
+
+ a.cmp(x.reg, y.reg);
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+
+ /* We can skip deep comparisons when both args are immediates. */
+ emit_are_both_immediate(x.reg, y.reg);
+ a.b_eq(next);
+
+ mov_var(ARG1, x);
+ mov_var(ARG2, y);
+ fragment_call(ga->get_arith_compare_shared());
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+
+ a.bind(next);
+}
+
+/*
+ * ARG1 = LHS
+ * ARG2 = RHS
+ *
+ * Result is returned in the flags.
+ */
+void BeamGlobalAssembler::emit_arith_compare_shared() {
+ Label atom_compare = a.newLabel(), generic_compare = a.newLabel();
+
+ /* Are both floats?
+ *
+ * This is done first as relative comparisons on atoms doesn't make much
+ * sense. */
+ a.orr(TMP1, ARG1, ARG2);
+ emit_is_boxed(atom_compare, TMP1);
+
+ arm::Gp boxed_ptr1 = emit_ptr_val(TMP1, ARG1);
+ a.ldur(TMP3, emit_boxed_val(boxed_ptr1));
+ arm::Gp boxed_ptr2 = emit_ptr_val(TMP2, ARG2);
+ a.ldur(TMP4, emit_boxed_val(boxed_ptr2));
+
+ mov_imm(TMP5, HEADER_FLONUM);
+ a.cmp(TMP3, TMP5);
+ a.ccmp(TMP4, TMP5, imm(NZCV::kNone), imm(arm::CondCode::kEQ));
+ a.b_ne(generic_compare);
+
+ a.ldur(a64::d0, emit_boxed_val(boxed_ptr1, sizeof(Eterm)));
+ a.ldur(a64::d1, emit_boxed_val(boxed_ptr2, sizeof(Eterm)));
+ a.fcmpe(a64::d0, a64::d1);
+ a.ret(a64::x30);
+
+ a.bind(atom_compare);
+ {
+ a.and_(TMP1, ARG1, imm(_TAG_IMMED2_MASK));
+ a.and_(TMP2, ARG2, imm(_TAG_IMMED2_MASK));
+ a.sub(TMP1, TMP1, imm(_TAG_IMMED2_ATOM));
+ a.sub(TMP2, TMP2, imm(_TAG_IMMED2_ATOM));
+ a.orr(TMP1, TMP1, TMP2);
+ a.cbnz(TMP1, generic_compare);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ runtime_call<2>(erts_cmp_atoms);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ /* Note: erts_cmp_atoms() returns int, not Sint. */
+ a.tst(ARG1.w(), ARG1.w());
+ a.ret(a64::x30);
+ }
+
+ a.bind(generic_compare);
+ {
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ comment("erts_cmp_compound(X, Y, 0, 0);");
+ mov_imm(ARG3, 0);
+ mov_imm(ARG4, 0);
+ runtime_call<4>(erts_cmp_compound);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.tst(ARG1, ARG1);
+
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_is_lt(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS) {
+ mov_arg(ARG1, LHS);
+ mov_arg(ARG2, RHS);
+
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ a.cmp(ARG1, ARG2);
+ a.b_ge(resolve_beam_label(Fail, disp1MB));
+ } else if (always_one_of(LHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED) &&
+ always_one_of(RHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ Label branch_compare = a.newLabel();
+
+ a.cmp(ARG1, ARG2);
+
+ /* The only possible kind of immediate is a small and all other values
+ * are boxed, so we can test for smalls by testing boxed. */
+ comment("simplified small test since all other types are boxed");
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED == (1 << 0));
+ a.and_(TMP1, ARG1, ARG2);
+ a.tbnz(TMP1, imm(0), branch_compare);
+ fragment_call(ga->get_arith_compare_shared());
+
+ /* The flags will either be from the initial comparison, or from the
+ * shared fragment. */
+ a.bind(branch_compare);
+ a.b_ge(resolve_beam_label(Fail, disp1MB));
+ } else {
+ Label generic = a.newLabel(), next = a.newLabel();
+
+ /* Relative comparisons are overwhelmingly likely to be used on smalls,
+ * so we'll specialize those and keep the rest in a shared fragment. */
+ if (RHS.isSmall()) {
+ a.and_(TMP1, ARG1, imm(_TAG_IMMED1_MASK));
+ } else if (LHS.isSmall()) {
+ a.and_(TMP1, ARG2, imm(_TAG_IMMED1_MASK));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG1, ARG2);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ }
+
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+
+ a.cmp(ARG1, ARG2);
+ a.b(next);
+
+ a.bind(generic);
+ fragment_call(ga->get_arith_compare_shared());
+
+ a.bind(next);
+ a.b_ge(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_is_ge(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS) {
+ mov_arg(ARG1, LHS);
+ mov_arg(ARG2, RHS);
+
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ a.cmp(ARG1, ARG2);
+ a.b_lt(resolve_beam_label(Fail, disp1MB));
+ } else if (always_one_of(LHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED) &&
+ always_one_of(RHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ Label branch_compare = a.newLabel();
+
+ a.cmp(ARG1, ARG2);
+
+ /* The only possible kind of immediate is a small and all other values
+ * are boxed, so we can test for smalls by testing boxed. */
+ comment("simplified small test since all other types are boxed");
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED == (1 << 0));
+ a.and_(TMP1, ARG1, ARG2);
+ a.tbnz(TMP1, imm(0), branch_compare);
+
+ fragment_call(ga->get_arith_compare_shared());
+
+ /* The flags will either be from the initial comparison, or from the
+ * shared fragment. */
+ a.bind(branch_compare);
+ a.b_lt(resolve_beam_label(Fail, disp1MB));
+ } else {
+ Label generic = a.newLabel(), next = a.newLabel();
+
+ /* Relative comparisons are overwhelmingly likely to be used on smalls,
+ * so we'll specialize those and keep the rest in a shared fragment. */
+ if (RHS.isSmall()) {
+ a.and_(TMP1, ARG1, imm(_TAG_IMMED1_MASK));
+ } else if (LHS.isSmall()) {
+ a.and_(TMP1, ARG2, imm(_TAG_IMMED1_MASK));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.and_(TMP1, ARG1, ARG2);
+ a.and_(TMP1, TMP1, imm(_TAG_IMMED1_MASK));
+ }
+
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(generic);
+
+ a.cmp(ARG1, ARG2);
+ a.b(next);
+
+ a.bind(generic);
+ fragment_call(ga->get_arith_compare_shared());
+
+ a.bind(next);
+ a.b_lt(resolve_beam_label(Fail, disp1MB));
+ }
+}
+
+void BeamModuleAssembler::emit_badmatch(const ArgSource &Src) {
+ mov_arg(arm::Mem(c_p, offsetof(Process, fvalue)), Src);
+ emit_error(BADMATCH);
+}
+
+void BeamModuleAssembler::emit_case_end(const ArgSource &Src) {
+ mov_arg(arm::Mem(c_p, offsetof(Process, fvalue)), Src);
+ emit_error(EXC_CASE_CLAUSE);
+}
+
+void BeamModuleAssembler::emit_system_limit_body() {
+ emit_error(SYSTEM_LIMIT);
+}
+
+void BeamModuleAssembler::emit_if_end() {
+ emit_error(EXC_IF_CLAUSE);
+}
+
+void BeamModuleAssembler::emit_badrecord(const ArgSource &Src) {
+ mov_arg(arm::Mem(c_p, offsetof(Process, fvalue)), Src);
+ emit_error(EXC_BADRECORD);
+}
+
+void BeamModuleAssembler::emit_catch(const ArgYRegister &Y,
+ const ArgCatch &Handler) {
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, catches)));
+ a.add(TMP1, TMP1, imm(1));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, catches)));
+
+ mov_arg(Y, Handler);
+}
+
+void BeamGlobalAssembler::emit_catch_end_shared() {
+ Label not_throw = a.newLabel(), not_error = a.newLabel(),
+ after_gc = a.newLabel();
+
+ /* XREG0 = THE_NON_VALUE
+ * XREG1 = error reason/thrown value
+ * XREG2 = raw stacktrace.
+ * XREG3 = class
+ */
+
+ a.mov(XREG0, XREG1);
+ a.cmp(XREG3, imm(am_throw));
+
+ a.b_ne(not_throw);
+
+ /* Return thrown value. */
+ a.ret(a64::x30);
+
+ a.bind(not_throw);
+ {
+ emit_enter_runtime_frame();
+
+ a.mov(ARG1, XREG0);
+
+ a.cmp(XREG3, imm(am_error));
+ a.b_ne(not_error);
+
+ a.mov(ARG2, XREG0);
+ a.mov(ARG3, XREG2);
+
+ /* This is an error, attach a stacktrace to the reason. */
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 2);
+ emit_enter_runtime<Update::eStack | Update::eHeap>(2);
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(add_stacktrace);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(2);
+
+ /* Fall through! */
+ }
+
+ /* Error term from exit/1 or stack backtrace from error/{1,2,3} is
+ * now in ARG1. */
+ a.bind(not_error);
+ {
+ const int32_t bytes_needed = (3 + S_RESERVED) * sizeof(Eterm);
+ add(ARG3, HTOP, bytes_needed);
+ a.cmp(ARG3, E);
+
+ a.b_ls(after_gc);
+ {
+ /* Preserve stacktrace / reason. */
+ a.mov(XREG0, ARG1);
+
+ mov_imm(ARG4, 1);
+ a.bl(labels[garbage_collect]);
+
+ a.mov(ARG1, XREG0);
+ }
+ a.bind(after_gc);
+
+ a.add(XREG0, HTOP, imm(TAG_PRIMARY_BOXED));
+ mov_imm(TMP1, make_arityval(2));
+ mov_imm(TMP2, am_EXIT);
+ a.stp(TMP1, TMP2, arm::Mem(HTOP).post(2 * sizeof(Eterm)));
+ a.str(ARG1, arm::Mem(HTOP).post(sizeof(Eterm)));
+ }
+
+ emit_leave_runtime_frame();
+ a.ret(a64::x30);
+}
+
+void BeamModuleAssembler::emit_catch_end(const ArgYRegister &CatchTag) {
+ Label next = a.newLabel();
+
+ /* XREG0 = THE_NON_VALUE
+ * XREG1 = class
+ * XREG2 = error reason/thrown value
+ * XREG3 = raw stacktrace. */
+
+ emit_try_end(CatchTag);
+ emit_branch_if_value(XREG0, next);
+ fragment_call(ga->get_catch_end_shared());
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_try_end(const ArgYRegister &CatchTag) {
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, catches)));
+ a.sub(TMP1, TMP1, imm(1));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, catches)));
+
+ emit_init(CatchTag);
+}
+
+void BeamModuleAssembler::emit_try_case(const ArgYRegister &CatchTag) {
+ /* XREG0 = THE_NON_VALUE
+ * XREG1 = error reason/thrown value
+ * XREG2 = raw stacktrace.
+ * XREG3 = class */
+
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, catches)));
+ a.mov(XREG0, XREG3);
+ a.sub(TMP1, TMP1, imm(1));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, catches)));
+
+ /* The try_tag in the Y slot in the stack frame has already been
+ * cleared. */
+
+#ifdef DEBUG
+ Label ok = a.newLabel();
+ comment("Start of assertion code");
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, fvalue)));
+ a.ldr(TMP2, arm::Mem(c_p, offsetof(Process, ftrace)));
+ mov_imm(TMP3, NIL);
+ a.cmp(TMP1, TMP3);
+ a.ccmp(TMP2, TMP3, imm(NZCV::kNone), imm(arm::CondCode::kEQ));
+ a.b_eq(ok);
+
+ comment("Assertion c_p->fvalue == NIL && c_p->ftrace == NIL failed");
+ a.udf(0x42);
+
+ a.bind(ok);
+#endif
+}
+
+void BeamModuleAssembler::emit_try_case_end(const ArgSource &Src) {
+ mov_arg(arm::Mem(c_p, offsetof(Process, fvalue)), Src);
+ emit_error(EXC_TRY_CLAUSE);
+}
+
+void BeamModuleAssembler::emit_raise(const ArgSource &Trace,
+ const ArgSource &Value) {
+ mov_arg(TMP1, Value);
+ mov_arg(ARG2, Trace);
+
+ /* This is an error, attach a stacktrace to the reason. */
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, fvalue)));
+ a.str(ARG2, arm::Mem(c_p, offsetof(Process, ftrace)));
+
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_sanitize_freason);
+
+ emit_leave_runtime(0);
+
+ emit_raise_exception();
+}
+
+void BeamModuleAssembler::emit_build_stacktrace() {
+ a.mov(ARG2, XREG0);
+
+ emit_enter_runtime<Update::eStack | Update::eHeap>(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(build_stacktrace);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(0);
+
+ a.mov(XREG0, ARG1);
+}
+
+/* This instruction has the same semantics as the erlang:raise/3 BIF,
+ * except that it can rethrow a raw stack backtrace. */
+void BeamModuleAssembler::emit_raw_raise() {
+ Label next = a.newLabel();
+
+ a.mov(ARG1, XREG2);
+ a.mov(ARG2, XREG0);
+ a.mov(ARG3, XREG1);
+ a.mov(ARG4, c_p);
+
+ emit_enter_runtime(0);
+ runtime_call<4>(raw_raise);
+ emit_leave_runtime(0);
+
+ a.cbnz(ARG1, next);
+
+ emit_raise_exception();
+
+ a.bind(next);
+ mov_imm(XREG0, am_badarg);
+}
+
+#define TEST_YIELD_RETURN_OFFSET \
+ (BEAM_ASM_FUNC_PROLOGUE_SIZE + sizeof(Uint32[3]))
+
+/* ARG3 = current_label */
+void BeamGlobalAssembler::emit_i_test_yield_shared() {
+ a.sub(ARG2, ARG3, imm(sizeof(ErtsCodeMFA)));
+ a.add(ARG3, ARG3, imm(TEST_YIELD_RETURN_OFFSET));
+
+ a.str(ARG2, arm::Mem(c_p, offsetof(Process, current)));
+ a.ldr(ARG2, arm::Mem(ARG2, offsetof(ErtsCodeMFA, arity)));
+ a.str(ARG2, arm::Mem(c_p, offsetof(Process, arity)));
+
+ a.b(labels[context_switch_simplified]);
+}
+
+void BeamModuleAssembler::emit_i_test_yield() {
+ /* When present, this is guaranteed to be the first instruction after the
+ * breakpoint trampoline. */
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ BEAM_ASM_FUNC_PROLOGUE_SIZE);
+
+ a.adr(ARG3, current_label);
+ a.subs(FCALLS, FCALLS, imm(1));
+ a.b_le(resolve_fragment(ga->get_i_test_yield_shared(), disp1MB));
+
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ TEST_YIELD_RETURN_OFFSET);
+}
+
+void BeamModuleAssembler::emit_i_yield() {
+ mov_imm(XREG0, am_true);
+ fragment_call(ga->get_dispatch_return());
+}
+
+void BeamModuleAssembler::emit_i_perf_counter() {
+ Label next = a.newLabel(), small = a.newLabel();
+
+ emit_enter_runtime_frame();
+ runtime_call<0>(erts_sys_time_data__.r.o.perf_counter);
+ emit_leave_runtime_frame();
+
+ a.asr(TMP1, ARG1, imm(SMALL_BITS - 1));
+ a.add(TMP1, TMP1, imm(1));
+ a.cmp(TMP1, imm(1));
+ a.b_ls(small);
+
+ {
+ a.mov(XREG0, ARG1);
+
+ emit_gc_test(ArgWord(0),
+ ArgWord(ERTS_MAX_UINT64_HEAP_SIZE),
+ ArgWord(0));
+
+ mov_imm(TMP1, make_pos_bignum_header(1));
+ a.stp(TMP1, XREG0, arm::Mem(HTOP).post(sizeof(Eterm[2])));
+ a.sub(XREG0, HTOP, imm(sizeof(Eterm[2]) - TAG_PRIMARY_BOXED));
+ a.b(next);
+ }
+
+ a.bind(small);
+ {
+ a.lsl(ARG1, ARG1, imm(_TAG_IMMED1_SIZE));
+ a.orr(XREG0, ARG1, imm(_TAG_IMMED1_SMALL));
+ }
+
+ a.bind(next);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_float.cpp b/erts/emulator/beam/jit/arm/instr_float.cpp
new file mode 100644
index 0000000000..25fe82df90
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_float.cpp
@@ -0,0 +1,230 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "big.h"
+}
+
+/* Checks whether d0 contains a finite value.
+ *
+ * Clobbers d30 and d31. */
+void BeamGlobalAssembler::emit_check_float_error() {
+ Label double_max = a.newLabel(), error = a.newLabel();
+
+ a.fabs(a64::d30, a64::d0);
+ a.ldr(a64::d31, arm::Mem(double_max));
+ a.fcmp(a64::d30, a64::d31);
+ a.b_hi(error);
+ a.ret(a64::x30);
+
+ a.align(AlignMode::kCode, 8);
+ a.bind(double_max);
+ a.embedUInt64(0x7FEFFFFFFFFFFFFFul);
+
+ a.bind(error);
+ {
+ mov_imm(ARG4, 0);
+ mov_imm(TMP1, EXC_BADARITH);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_float_instr(uint32_t instId,
+ const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ auto lhs = load_source(LHS, a64::d0);
+ auto rhs = load_source(RHS, a64::d1);
+ auto dst = init_destination(Dst, a64::d2);
+
+ a.emit(instId, a64::d0, lhs.reg, rhs.reg);
+ fragment_call(ga->get_check_float_error());
+ a.mov(dst.reg, a64::d0);
+ flush_var(dst);
+}
+
+/* * * * */
+
+void BeamModuleAssembler::emit_fload(const ArgSource &Src,
+ const ArgFRegister &Dst) {
+ auto src = load_source(Src, TMP1);
+ auto dst = init_destination(Dst, a64::d0);
+ arm::Gp float_ptr = emit_ptr_val(TMP1, src.reg);
+
+ a.ldur(dst.reg, emit_boxed_val(float_ptr, sizeof(Eterm)));
+ flush_var(dst);
+}
+
+void BeamModuleAssembler::emit_fstore(const ArgFRegister &Src,
+ const ArgRegister &Dst) {
+ auto src = load_source(Src, a64::d0);
+ auto dst = init_destination(Dst, TMP1);
+
+ a.add(dst.reg, HTOP, imm(TAG_PRIMARY_BOXED));
+
+ mov_imm(TMP2, HEADER_FLONUM);
+ a.str(TMP2, arm::Mem(HTOP).post(sizeof(Eterm)));
+ a.str(src.reg, arm::Mem(HTOP).post(sizeof(Eterm)));
+
+ flush_var(dst);
+}
+
+/* ARG1 = source term */
+void BeamGlobalAssembler::emit_fconv_shared() {
+ Label error = a.newLabel();
+
+ /* Is the source a bignum? */
+ {
+ emit_is_boxed(error, ARG1);
+
+ emit_untag_ptr(TMP1, ARG1);
+ a.ldr(TMP1, arm::Mem(TMP1));
+
+ /* The mask (0b111011) cannot be encoded as an immediate operand for
+ * 'and'. */
+ mov_imm(TMP2, _TAG_HEADER_MASK - _BIG_SIGN_BIT);
+ a.and_(TMP2, TMP1, TMP2);
+ a.cmp(TMP2, imm(_TAG_HEADER_POS_BIG));
+ a.b_ne(error);
+ }
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ /* ARG1 already contains the source term. */
+ lea(ARG2, TMP_MEM1q);
+ runtime_call<2>(big_to_double);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.tbnz(ARG1.w(), imm(31), error);
+
+ a.ldr(a64::d0, TMP_MEM1q);
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ mov_imm(ARG4, 0);
+ mov_imm(TMP1, EXC_BADARITH);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_fconv(const ArgSource &Src,
+ const ArgFRegister &Dst) {
+ auto dst = init_destination(Dst, a64::d0);
+ auto src = load_source(Src, ARG1);
+
+ if (always_small(Src)) {
+ comment("skipped test for small operand since it is always small");
+ a.asr(TMP1, src.reg, imm(_TAG_IMMED1_SIZE));
+ a.scvtf(dst.reg, TMP1);
+ flush_var(dst);
+ return;
+ }
+
+ Label next = a.newLabel(), not_small = a.newLabel(),
+ fallback = a.newLabel();
+
+ a.and_(TMP1, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_MASK));
+ a.b_ne(not_small);
+
+ a.asr(TMP1, src.reg, imm(_TAG_IMMED1_SIZE));
+ a.scvtf(dst.reg, TMP1);
+ a.b(next);
+
+ a.bind(not_small);
+ {
+ if (masked_types(Src, BEAM_TYPE_FLOAT) == BEAM_TYPE_NONE) {
+ comment("skipped float path since source cannot be a float");
+ } else {
+ /* If the source is always a number, we can skip the box test when
+ * it's not a small. */
+ if (always_one_of(Src, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("skipped box test since source is always a number");
+ } else {
+ emit_is_boxed(fallback, Src, src.reg);
+ }
+
+ emit_untag_ptr(TMP1, src.reg);
+
+ /* Speculatively load the float value, this is safe since all boxed
+ * terms are at least two words long. */
+ a.ldr(dst.reg, arm::Mem(TMP1, sizeof(Eterm)));
+
+ a.ldr(TMP1, arm::Mem(TMP1));
+ a.cmp(TMP1, imm(HEADER_FLONUM));
+ a.b_eq(next);
+ }
+
+ a.bind(fallback);
+ {
+ mov_var(ARG1, src);
+ fragment_call(ga->get_fconv_shared());
+ mov_var(dst, a64::d0);
+ }
+ }
+
+ a.bind(next);
+ flush_var(dst);
+}
+
+void BeamModuleAssembler::emit_i_fadd(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(a64::Inst::kIdFadd_v, LHS, RHS, Dst);
+}
+
+void BeamModuleAssembler::emit_i_fsub(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(a64::Inst::kIdFsub_v, LHS, RHS, Dst);
+}
+
+void BeamModuleAssembler::emit_i_fmul(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(a64::Inst::kIdFmul_v, LHS, RHS, Dst);
+}
+
+void BeamModuleAssembler::emit_i_fdiv(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(a64::Inst::kIdFdiv_v, LHS, RHS, Dst);
+}
+
+void BeamModuleAssembler::emit_i_fnegate(const ArgFRegister &Src,
+ const ArgFRegister &Dst) {
+ auto src = load_source(Src, a64::d0);
+ auto dst = init_destination(Dst, a64::d1);
+
+ /* Note that there is no need to check for errors since flipping the sign
+ * of a finite float is guaranteed to produce a finite float. */
+ a.fneg(a64::d0, src.reg);
+ a.mov(dst.reg, a64::d0);
+ flush_var(dst);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_fun.cpp b/erts/emulator/beam/jit/arm/instr_fun.cpp
new file mode 100644
index 0000000000..c236281ace
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_fun.cpp
@@ -0,0 +1,453 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+/* Calls to functions that are being purged (but haven't finished) land here.
+ *
+ * Keep in mind that this runs in the limbo between caller and callee. It must
+ * not clobber LR (x30).
+ *
+ * ARG3 = arity
+ * ARG4 = fun thing
+ * ARG5 = address of the call_fun instruction that got us here. Note that we
+ * can't use LR (x30) for this because tail calls point elsewhere. */
+void BeamGlobalAssembler::emit_unloaded_fun() {
+ Label error = a.newLabel();
+
+ a.str(ARG5, TMP_MEM1q);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eHeap | Update::eStack | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ /* ARG3 and ARG4 have already been set. */
+ runtime_call<4>(beam_jit_handle_unloaded_fun);
+
+ emit_leave_runtime<Update::eHeap | Update::eStack | Update::eXRegs |
+ Update::eReductions | Update::eCodeIndex>();
+ emit_leave_runtime_frame();
+
+ a.cbz(ARG1, error);
+
+ a.ldr(TMP1, emit_setup_dispatchable_call(ARG1));
+ a.br(TMP1);
+
+ a.bind(error);
+ {
+ a.ldr(ARG2, TMP_MEM1q);
+ mov_imm(ARG4, nullptr);
+ a.b(labels[raise_exception_shared]);
+ }
+}
+
+/* Handles errors for `call_fun`. Assumes that we're running on the Erlang
+ * stack with a valid stack frame.
+ *
+ * ARG3 = arity
+ * ARG4 = fun thing
+ * ARG5 = address of the call_fun instruction that got us here. Note that we
+ * can't use LR (x30) for this because tail calls point elsewhere. */
+void BeamGlobalAssembler::emit_handle_call_fun_error() {
+ Label bad_arity = a.newLabel(), bad_fun = a.newLabel();
+
+ emit_is_boxed(bad_fun, ARG4);
+
+ arm::Gp fun_thing = emit_ptr_val(TMP1, ARG4);
+ a.ldur(TMP1, emit_boxed_val(fun_thing));
+ a.cmp(TMP1, imm(HEADER_FUN));
+ a.b_eq(bad_arity);
+
+ a.bind(bad_fun);
+ {
+ mov_imm(TMP1, EXC_BADFUN);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.str(ARG4, arm::Mem(c_p, offsetof(Process, fvalue)));
+
+ a.mov(ARG2, ARG5);
+ mov_imm(ARG4, nullptr);
+ a.b(labels[raise_exception_shared]);
+ }
+
+ a.bind(bad_arity);
+ {
+ a.stp(ARG4, ARG5, TMP_MEM1q);
+
+ emit_enter_runtime<Update::eHeap | Update::eStack | Update::eXRegs>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ /* ARG3 is already set */
+ runtime_call<3>(beam_jit_build_argument_list);
+
+ emit_leave_runtime<Update::eHeap | Update::eStack | Update::eXRegs>();
+
+ a.ldr(XREG0, TMP_MEM1q);
+ a.mov(XREG1, ARG1);
+
+ /* Create the {Fun, Args} tuple. */
+ {
+ const int32_t bytes_needed = (3 + S_RESERVED) * sizeof(Eterm);
+ Label after_gc = a.newLabel();
+
+ add(ARG3, HTOP, bytes_needed);
+ a.cmp(ARG3, E);
+ a.b_ls(after_gc);
+ {
+ mov_imm(ARG4, 2);
+ a.bl(labels[garbage_collect]);
+ }
+ a.bind(after_gc);
+
+ a.add(ARG1, HTOP, imm(TAG_PRIMARY_BOXED));
+
+ mov_imm(TMP1, make_arityval(2));
+ a.str(TMP1, arm::Mem(HTOP).post(sizeof(Eterm)));
+ a.stp(XREG0, XREG1, arm::Mem(HTOP).post(sizeof(Eterm[2])));
+ }
+
+ a.mov(TMP1, imm(EXC_BADARITY));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.str(ARG1, arm::Mem(c_p, offsetof(Process, fvalue)));
+
+ a.ldr(ARG2, TMP_MEM2q);
+ mov_imm(ARG4, nullptr);
+ a.b(labels[raise_exception_shared]);
+ }
+}
+
+/* `call_fun` instructions land here to set up their environment before jumping
+ * to the actual implementation.
+ *
+ * Keep in mind that this runs in the limbo between caller and callee. It must
+ * not clobber LR (x30).
+ *
+ * ARG4 = fun thing */
+void BeamModuleAssembler::emit_i_lambda_trampoline(const ArgLambda &Lambda,
+ const ArgLabel &Lbl,
+ const ArgWord &Arity,
+ const ArgWord &NumFree) {
+ const ssize_t env_offset = offsetof(ErlFunThing, env) - TAG_PRIMARY_BOXED;
+ const ssize_t fun_arity = Arity.get() - NumFree.get();
+ const ssize_t total_arity = Arity.get();
+
+ const auto &lambda = lambdas[Lambda.get()];
+ a.bind(lambda.trampoline);
+
+ if (NumFree.get() == 1) {
+ auto first = init_destination(ArgXRegister(fun_arity), TMP1);
+
+ /* Don't bother untagging when there's only a single element, it's
+ * guaranteed to be within range of LDUR. */
+ emit_ptr_val(ARG4, ARG4);
+ a.ldur(first.reg, arm::Mem(ARG4, env_offset));
+ flush_var(first);
+ } else if (NumFree.get() >= 2) {
+ ssize_t i;
+
+ emit_ptr_val(ARG4, ARG4);
+ a.add(ARG4, ARG4, imm(env_offset));
+
+ for (i = fun_arity; i < total_arity - 1; i += 2) {
+ auto first = init_destination(ArgXRegister(i), TMP1);
+ auto second = init_destination(ArgXRegister(i + 1), TMP2);
+
+ a.ldp(first.reg, second.reg, arm::Mem(ARG4).post(sizeof(Eterm[2])));
+ flush_vars(first, second);
+ }
+
+ if (i < total_arity) {
+ auto last = init_destination(ArgXRegister(i), TMP1);
+ a.ldr(last.reg, arm::Mem(ARG4));
+ flush_var(last);
+ }
+ }
+
+ a.b(resolve_beam_label(Lbl, disp128MB));
+}
+
+void BeamModuleAssembler::emit_i_make_fun3(const ArgLambda &Lambda,
+ const ArgRegister &Dst,
+ const ArgWord &Arity,
+ const ArgWord &NumFree,
+ const Span<ArgVal> &env) {
+ const ssize_t num_free = NumFree.get();
+ ssize_t i;
+
+ ASSERT(num_free == env.size());
+
+ a.mov(ARG1, c_p);
+ mov_arg(ARG2, Lambda);
+ mov_arg(ARG3, Arity);
+ mov_arg(ARG4, NumFree);
+
+ emit_enter_runtime<Update::eHeap>();
+
+ runtime_call<4>(erts_new_local_fun_thing);
+
+ emit_leave_runtime<Update::eHeap>();
+
+ if (num_free) {
+ comment("Move fun environment");
+ }
+
+ for (i = 0; i < num_free - 1; i += 2) {
+ ssize_t offset = offsetof(ErlFunThing, env) + i * sizeof(Eterm);
+
+ if ((i % 128) == 0) {
+ check_pending_stubs();
+ }
+
+ auto [first, second] = load_sources(env[i], TMP1, env[i + 1], TMP2);
+ safe_stp(first.reg, second.reg, arm::Mem(ARG1, offset));
+ }
+
+ if (i < num_free) {
+ ssize_t offset = offsetof(ErlFunThing, env) + i * sizeof(Eterm);
+ mov_arg(arm::Mem(ARG1, offset), env[i]);
+ }
+
+ comment("Create boxed ptr");
+ auto dst = init_destination(Dst, TMP1);
+ a.orr(dst.reg, ARG1, imm(TAG_PRIMARY_BOXED));
+ flush_var(dst);
+}
+
+void BeamGlobalAssembler::emit_apply_fun_shared() {
+ Label finished = a.newLabel();
+
+ /* Put the arity and fun into the right registers for `call_fun`, and stash
+ * the argument list in ARG5 for the error path. We'll bump the arity as
+ * we go through the argument list. */
+ mov_imm(ARG3, 0);
+ a.mov(ARG4, XREG0);
+ a.mov(ARG5, XREG1);
+
+ {
+ Label unpack_next = a.newLabel(), malformed_list = a.newLabel(),
+ raise_error = a.newLabel();
+
+ /* apply/2 is rarely used on a hot code path, so we'll simplify things
+ * by switching to the runtime environment where we can operate
+ * entirely on the X register array.
+ *
+ * Note that we don't have any live registers at this point. */
+ emit_enter_runtime<Update::eXRegs>(0);
+
+ a.mov(TMP1, ARG5);
+ lea(TMP2, getXRef(0));
+
+ a.bind(unpack_next);
+ {
+ a.cmp(TMP1, imm(NIL));
+ a.b_eq(finished);
+
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST == (1 << 1));
+ a.tbnz(TMP1, imm(1), malformed_list);
+
+ emit_ptr_val(TMP1, TMP1);
+ a.sub(TMP1, TMP1, imm(TAG_PRIMARY_LIST));
+ a.ldp(TMP3, TMP1, arm::Mem(TMP1));
+ a.str(TMP3, arm::Mem(TMP2).post(sizeof(Eterm)));
+
+ /* We bail at MAX_REG-1 rather than MAX_REG as the highest register
+ * is reserved for the loader. */
+ a.add(ARG3, ARG3, imm(1));
+ a.cmp(ARG3, imm(MAX_REG - 1));
+ a.b_lo(unpack_next);
+ }
+
+ a.mov(TMP1, imm(SYSTEM_LIMIT));
+ a.b(raise_error);
+
+ a.bind(malformed_list);
+ a.mov(TMP1, imm(BADARG));
+
+ a.bind(raise_error);
+ {
+ static const ErtsCodeMFA apply_mfa = {am_erlang, am_apply, 2};
+
+ emit_leave_runtime<Update::eXRegs>(0);
+
+ a.mov(XREG0, ARG4);
+ a.mov(XREG1, ARG5);
+
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ mov_imm(ARG4, &apply_mfa);
+ a.b(labels[raise_exception]);
+ }
+ }
+
+ a.bind(finished);
+ {
+ emit_leave_runtime<Update::eXRegs>();
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_i_apply_fun() {
+ fragment_call(ga->get_apply_fun_shared());
+ erlang_call(emit_call_fun());
+}
+
+void BeamModuleAssembler::emit_i_apply_fun_last(const ArgWord &Deallocate) {
+ emit_deallocate(Deallocate);
+ emit_i_apply_fun_only();
+}
+
+void BeamModuleAssembler::emit_i_apply_fun_only() {
+ fragment_call(ga->get_apply_fun_shared());
+ emit_leave_erlang_frame();
+ a.br(emit_call_fun());
+}
+
+/* Assumes that:
+ * ARG3 = arity
+ * ARG4 = fun thing */
+arm::Gp BeamModuleAssembler::emit_call_fun(bool skip_box_test,
+ bool skip_fun_test,
+ bool skip_arity_test) {
+ const bool never_fails = skip_box_test && skip_fun_test && skip_arity_test;
+ Label next = a.newLabel();
+
+ /* Speculatively untag the ErlFunThing. */
+ emit_untag_ptr(TMP2, ARG4);
+
+ if (!never_fails) {
+ /* Load the error fragment into TMP3 so we can CSEL ourselves there on
+ * error. */
+ a.adr(TMP3, resolve_fragment(ga->get_handle_call_fun_error(), disp1MB));
+ }
+
+ /* The `handle_call_fun_error` and `unloaded_fun` fragments expect current
+ * PC in ARG5. */
+ a.adr(ARG5, next);
+
+ if (!skip_box_test) {
+ /* As emit_is_boxed(), but explicitly sets ZF so we can rely on that
+ * for error checking in `next`. */
+ a.tst(ARG4, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED));
+ a.b_ne(next);
+ } else {
+ comment("skipped box test since source is always boxed");
+ }
+
+ if (!skip_fun_test) {
+ /* Load header word and `ErlFunThing->entry`. We can safely do this
+ * before testing the header because boxed terms are guaranteed to be
+ * at least two words long. */
+ ERTS_CT_ASSERT_FIELD_PAIR(ErlFunThing, thing_word, entry);
+ a.ldp(TMP1, ARG1, arm::Mem(TMP2));
+
+ a.cmp(TMP1, imm(HEADER_FUN));
+ a.b_ne(next);
+ } else {
+ comment("skipped fun test since source is always a fun when boxed");
+ a.ldr(ARG1, arm::Mem(TMP2, offsetof(ErlFunThing, entry)));
+ }
+
+ if (!skip_arity_test) {
+ a.ldrb(TMP2.w(), arm::Mem(TMP2, offsetof(ErlFunThing, arity)));
+ a.cmp(TMP2, ARG3);
+ } else {
+ comment("skipped arity test since source always has right arity");
+ }
+
+ a.ldr(TMP1, emit_setup_dispatchable_call(ARG1));
+
+ /* Assumes that ZF is set on success and clear on error, overwriting our
+ * destination with the error fragment's address. */
+ a.bind(next);
+
+ if (!never_fails) {
+ a.csel(TMP1, TMP1, TMP3, imm(arm::CondCode::kEQ));
+ }
+
+ return TMP1;
+}
+
+void BeamModuleAssembler::emit_i_call_fun2(const ArgVal &Tag,
+ const ArgWord &Arity,
+ const ArgRegister &Func) {
+ mov_arg(ARG4, Func);
+
+ if (Tag.isAtom()) {
+ mov_imm(ARG3, Arity.get());
+
+ auto target = emit_call_fun(
+ always_one_of(Func, BEAM_TYPE_MASK_ALWAYS_BOXED),
+ masked_types(Func, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN,
+ Tag.as<ArgAtom>().get() == am_safe);
+
+ erlang_call(target);
+ } else {
+ const auto &trampoline = lambdas[Tag.as<ArgLambda>().get()].trampoline;
+ erlang_call(resolve_label(trampoline, disp128MB));
+ }
+}
+
+void BeamModuleAssembler::emit_i_call_fun2_last(const ArgVal &Tag,
+ const ArgWord &Arity,
+ const ArgRegister &Func,
+ const ArgWord &Deallocate) {
+ mov_arg(ARG4, Func);
+
+ if (Tag.isAtom()) {
+ mov_imm(ARG3, Arity.get());
+
+ auto target = emit_call_fun(
+ always_one_of(Func, BEAM_TYPE_MASK_ALWAYS_BOXED),
+ masked_types(Func, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN,
+ Tag.as<ArgAtom>().get() == am_safe);
+
+ emit_deallocate(Deallocate);
+ emit_leave_erlang_frame();
+
+ a.br(target);
+ } else {
+ emit_deallocate(Deallocate);
+ emit_leave_erlang_frame();
+
+ const auto &trampoline = lambdas[Tag.as<ArgLambda>().get()].trampoline;
+ a.b(resolve_label(trampoline, disp128MB));
+ }
+}
+
+void BeamModuleAssembler::emit_i_call_fun(const ArgWord &Arity) {
+ const ArgXRegister Func(Arity.get());
+ const ArgAtom Tag(am_unsafe);
+
+ emit_i_call_fun2(Tag, Arity, Func);
+}
+
+void BeamModuleAssembler::emit_i_call_fun_last(const ArgWord &Arity,
+ const ArgWord &Deallocate) {
+ const ArgXRegister Func(Arity.get());
+ const ArgAtom Tag(am_unsafe);
+
+ emit_i_call_fun2_last(Tag, Arity, Func, Deallocate);
+}
+
+/* Psuedo-instruction for signalling lambda load errors. Never actually runs. */
+void BeamModuleAssembler::emit_i_lambda_error(const ArgWord &Dummy) {
+ emit_nyi("emit_i_lambda_error");
+}
diff --git a/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp b/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
new file mode 100644
index 0000000000..1c7df4e6f6
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
@@ -0,0 +1,819 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Guard BIF calls using the generic bif1, bif2, and bif3 instructions
+ * are expensive. Not only are there two indirect calls (one to the
+ * fragment, one to the BIF itself), but the caller-saved X registers
+ * must also be saved and restored, and the BIF operands that are
+ * usually in CPU registers must be written out to memory.
+ *
+ * Therefore, guard BIFs that are used fairly frequently and can
+ * be implemented entirely in assembly language without any calls to
+ * C function are implemented in this source file.
+ */
+
+#include <algorithm>
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "erl_bif_table.h"
+#include "big.h"
+#include "beam_catches.h"
+#include "beam_common.h"
+#include "code_ix.h"
+#include "erl_map.h"
+}
+
+using namespace asmjit;
+
+/* Raise a badarg exception for the given MFA. */
+void BeamGlobalAssembler::emit_raise_badarg(const ErtsCodeMFA *mfa) {
+ mov_imm(TMP1, BADARG);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ mov_imm(ARG4, mfa);
+ a.b(labels[raise_exception]);
+}
+
+/* ================================================================
+ * '=:='/2
+ * '=/='/2
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_bif_is_eq_exact_shared() {
+ Label succ = a.newLabel(), fail = a.newLabel();
+
+ a.cmp(ARG1, ARG2);
+ a.b_eq(succ);
+
+ /* The terms could still be equal if both operands are pointers
+ * having the same tag. */
+ emit_is_unequal_based_on_tags(ARG1, ARG2);
+ a.b_eq(fail);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ runtime_call<2>(eq);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.cbz(ARG1, fail);
+
+ a.bind(succ);
+ {
+ mov_imm(ARG1, am_true);
+ a.ret(a64::x30);
+ }
+
+ a.bind(fail);
+ {
+ mov_imm(ARG1, am_false);
+ a.ret(a64::x30);
+ }
+}
+
+void BeamGlobalAssembler::emit_bif_is_ne_exact_shared() {
+ Label succ = a.newLabel(), fail = a.newLabel();
+
+ a.cmp(ARG1, ARG2);
+ a.b_eq(fail);
+
+ emit_is_unequal_based_on_tags(ARG1, ARG2);
+ a.b_eq(succ);
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime();
+
+ runtime_call<2>(eq);
+
+ emit_leave_runtime();
+ emit_leave_runtime_frame();
+
+ a.cbnz(ARG1, fail);
+
+ a.bind(succ);
+ {
+ mov_imm(ARG1, am_true);
+ a.ret(a64::x30);
+ }
+
+ a.bind(fail);
+ {
+ mov_imm(ARG1, am_false);
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_bif_is_eq_ne_exact_immed(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst,
+ Eterm fail_value,
+ Eterm succ_value) {
+ auto dst = init_destination(Dst, TMP2);
+
+ if (RHS.isImmed()) {
+ auto lhs = load_source(LHS, TMP1);
+ cmp_arg(lhs.reg, RHS);
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, TMP1, RHS, TMP2);
+ a.cmp(lhs.reg, rhs.reg);
+ }
+
+ mov_imm(TMP3, succ_value);
+ mov_imm(TMP4, fail_value);
+ a.csel(dst.reg, TMP3, TMP4, arm::CondCode::kEQ);
+ flush_var(dst);
+}
+
+void BeamModuleAssembler::emit_bif_is_eq_exact(const ArgRegister &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ if (always_immediate(LHS) || always_immediate(RHS)) {
+ if (!LHS.isImmed() && !RHS.isImmed()) {
+ comment("simplified check since one argument is an immediate");
+ }
+ emit_bif_is_eq_ne_exact_immed(LHS, RHS, Dst, am_false, am_true);
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG1, RHS, ARG2);
+ auto dst = init_destination(Dst, ARG1);
+
+ mov_var(ARG1, lhs);
+ mov_var(ARG2, rhs);
+ fragment_call(ga->get_bif_is_eq_exact_shared());
+ mov_var(dst, ARG1);
+ flush_var(dst);
+ }
+}
+
+void BeamModuleAssembler::emit_bif_is_ne_exact(const ArgRegister &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ if (always_immediate(LHS) || always_immediate(RHS)) {
+ if (!LHS.isImmed() && !RHS.isImmed()) {
+ comment("simplified check since one argument is an immediate");
+ }
+ emit_bif_is_eq_ne_exact_immed(LHS, RHS, Dst, am_true, am_false);
+ } else {
+ auto [lhs, rhs] = load_sources(LHS, ARG1, RHS, ARG2);
+ auto dst = init_destination(Dst, ARG1);
+
+ mov_var(ARG1, lhs);
+ mov_var(ARG2, rhs);
+ fragment_call(ga->get_bif_is_ne_exact_shared());
+ mov_var(dst, ARG1);
+ flush_var(dst);
+ }
+}
+
+/* ================================================================
+ * and/2
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_handle_and_error() {
+ static ErtsCodeMFA mfa = {am_erlang, am_and, 2};
+ emit_raise_badarg(&mfa);
+}
+
+void BeamModuleAssembler::emit_bif_and(const ArgLabel &Fail,
+ const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgRegister &Dst) {
+ static const Uint diff_bit = am_true - am_false;
+ Label next = a.newLabel();
+
+ auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2);
+ auto dst = init_destination(Dst, TMP3);
+
+ ERTS_CT_ASSERT(am_false == make_atom(0));
+ ERTS_CT_ASSERT(am_true == make_atom(1));
+
+ a.and_(TMP3, src1.reg, imm(_TAG_IMMED2_MASK | ~diff_bit));
+ a.and_(TMP4, src2.reg, imm(_TAG_IMMED2_MASK | ~diff_bit));
+ a.cmp(TMP3, imm(_TAG_IMMED2_ATOM));
+ a.ccmp(TMP3, TMP4, imm(NZCV::kNone), imm(arm::CondCode::kEQ));
+
+ if (Fail.get()) {
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.b_eq(next);
+ mov_var(XREG0, src1);
+ mov_var(XREG1, src2);
+ fragment_call(ga->get_handle_or_error());
+ }
+
+ a.bind(next);
+ {
+ a.and_(dst.reg, src1.reg, src2.reg);
+ flush_var(dst);
+ }
+}
+
+/* ================================================================
+ * bit_size/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_bif_bit_size_helper(Label fail) {
+ Label not_sub_bin = a.newLabel();
+ arm::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+
+ emit_is_boxed(fail, boxed_ptr);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.and_(TMP1, TMP1, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP1, imm(_TAG_HEADER_SUB_BIN));
+ a.b_ne(not_sub_bin);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ a.ldurb(TMP2.w(), emit_boxed_val(boxed_ptr, offsetof(ErlSubBin, bitsize)));
+
+ mov_imm(ARG1, _TAG_IMMED1_SMALL);
+ a.add(TMP1, TMP2, TMP1, arm::lsl(3));
+ a.bfi(ARG1, TMP1, imm(_TAG_IMMED1_SIZE), imm(SMALL_BITS));
+ a.ret(a64::x30);
+
+ a.bind(not_sub_bin);
+ ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
+ a.and_(TMP1, TMP1, imm(~4));
+ a.cmp(TMP1, imm(_TAG_HEADER_REFC_BIN));
+ a.b_ne(fail);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ mov_imm(ARG1, _TAG_IMMED1_SMALL);
+ a.bfi(ARG1, TMP1, imm(_TAG_IMMED1_SIZE + 3), imm(SMALL_BITS - 3));
+
+ a.ret(a64::x30);
+}
+
+void BeamGlobalAssembler::emit_bif_bit_size_body() {
+ Label error = a.newLabel();
+
+ emit_bif_bit_size_helper(error);
+
+ a.bind(error);
+ {
+ static ErtsCodeMFA mfa = {am_erlang, am_bit_size, 1};
+ a.mov(XREG0, ARG1);
+ emit_raise_badarg(&mfa);
+ }
+}
+
+void BeamGlobalAssembler::emit_bif_bit_size_guard() {
+ Label error = a.newLabel();
+
+ emit_bif_bit_size_helper(error);
+
+ a.bind(error);
+ {
+ mov_imm(ARG1, THE_NON_VALUE);
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_bif_bit_size(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgRegister &Dst) {
+ auto src = load_source(Src, ARG1);
+ auto dst = init_destination(Dst, ARG1);
+
+ mov_var(ARG1, src);
+
+ if (Fail.get() == 0) {
+ fragment_call(ga->get_bif_bit_size_body());
+ } else {
+ fragment_call(ga->get_bif_bit_size_guard());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ }
+
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
+
+/* ================================================================
+ * byte_size/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_bif_byte_size_helper(Label fail) {
+ Label not_sub_bin = a.newLabel();
+ arm::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+
+ emit_is_boxed(fail, boxed_ptr);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.and_(TMP1, TMP1, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP1, imm(_TAG_HEADER_SUB_BIN));
+ a.b_ne(not_sub_bin);
+
+ a.ldurb(TMP2.w(), emit_boxed_val(boxed_ptr, offsetof(ErlSubBin, bitsize)));
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ a.cmp(TMP2, imm(0));
+ a.cinc(TMP1, TMP1, arm::CondCode::kNE);
+
+ mov_imm(ARG1, _TAG_IMMED1_SMALL);
+ a.bfi(ARG1, TMP1, imm(_TAG_IMMED1_SIZE), imm(SMALL_BITS));
+ a.ret(a64::x30);
+
+ a.bind(not_sub_bin);
+ ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
+ a.and_(TMP1, TMP1, imm(~4));
+ a.cmp(TMP1, imm(_TAG_HEADER_REFC_BIN));
+ a.b_ne(fail);
+
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ mov_imm(ARG1, _TAG_IMMED1_SMALL);
+ a.bfi(ARG1, TMP1, imm(_TAG_IMMED1_SIZE), imm(SMALL_BITS));
+
+ a.ret(a64::x30);
+}
+
+void BeamGlobalAssembler::emit_bif_byte_size_body() {
+ Label error = a.newLabel();
+
+ emit_bif_byte_size_helper(error);
+
+ a.bind(error);
+ {
+ static ErtsCodeMFA mfa = {am_erlang, am_byte_size, 1};
+ a.mov(XREG0, ARG1);
+ emit_raise_badarg(&mfa);
+ }
+}
+
+void BeamGlobalAssembler::emit_bif_byte_size_guard() {
+ Label error = a.newLabel();
+
+ emit_bif_byte_size_helper(error);
+
+ a.bind(error);
+ {
+ mov_imm(ARG1, THE_NON_VALUE);
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_bif_byte_size(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgRegister &Dst) {
+ auto src = load_source(Src, ARG1);
+ auto dst = init_destination(Dst, ARG1);
+
+ mov_var(ARG1, src);
+
+ if (Fail.get() == 0) {
+ fragment_call(ga->get_bif_byte_size_body());
+ } else {
+ fragment_call(ga->get_bif_byte_size_guard());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ }
+
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
+
+/* ================================================================
+ * element/2
+ * ================================================================
+ */
+
+/* ARG1 = Position (1-based)
+ * ARG2 = Tuple
+ *
+ * Will return the result in ARG1, or jump to the label `fail` if
+ * the operation fails.
+ */
+void BeamGlobalAssembler::emit_bif_element_helper(Label fail) {
+ a.and_(TMP1, ARG1, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ a.b_ne(fail);
+
+ /* Ensure that ARG2 contains a tuple. */
+ emit_is_boxed(fail, ARG2);
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, ARG2);
+ lea(TMP1, emit_boxed_val(boxed_ptr));
+ a.ldr(TMP2, arm::Mem(TMP1));
+ ERTS_CT_ASSERT(make_arityval_zero() == 0);
+ a.tst(TMP2, imm(_TAG_HEADER_MASK));
+ a.b_ne(fail);
+
+ /* Ensure that the position points within the tuple. */
+ a.lsr(TMP2, TMP2, imm(_HEADER_ARITY_OFFS));
+ a.asr(TMP3, ARG1, imm(_TAG_IMMED1_SIZE));
+ a.cmp(TMP3, imm(1));
+ a.b_mi(fail);
+ a.cmp(TMP2, TMP3);
+ a.b_lo(fail);
+
+ a.ldr(ARG1, arm::Mem(TMP1, TMP3, arm::lsl(3)));
+ a.ret(a64::x30);
+}
+
+void BeamGlobalAssembler::emit_bif_element_body_shared() {
+ Label error = a.newLabel();
+
+ emit_bif_element_helper(error);
+
+ a.bind(error);
+ {
+ static ErtsCodeMFA mfa = {am_erlang, am_element, 2};
+ a.mov(XREG0, ARG1);
+ a.mov(XREG1, ARG2);
+ emit_raise_badarg(&mfa);
+ }
+}
+
+void BeamGlobalAssembler::emit_bif_element_guard_shared() {
+ Label error = a.newLabel();
+
+ emit_bif_element_helper(error);
+
+ a.bind(error);
+ {
+ mov_imm(ARG1, THE_NON_VALUE);
+ a.ret(a64::x30);
+ }
+}
+
+void BeamGlobalAssembler::emit_handle_element_error_shared() {
+ static ErtsCodeMFA mfa = {am_erlang, am_element, 2};
+ a.mov(XREG0, ARG1);
+ a.mov(XREG1, ARG2);
+ emit_raise_badarg(&mfa);
+}
+
+void BeamModuleAssembler::emit_bif_element(const ArgLabel &Fail,
+ const ArgSource &Pos,
+ const ArgSource &Tuple,
+ const ArgRegister &Dst) {
+ /*
+ * Try to optimize the use of a tuple as a lookup table.
+ */
+ if (exact_type(Pos, BEAM_TYPE_INTEGER) && Tuple.isLiteral()) {
+ Eterm tuple_literal =
+ beamfile_get_literal(beam, Tuple.as<ArgLiteral>().get());
+
+ if (is_tuple(tuple_literal)) {
+ Label next = a.newLabel(), fail = a.newLabel();
+ Sint size = Sint(arityval(*tuple_val(tuple_literal)));
+ auto [min, max] = getIntRange(Pos);
+ bool is_bounded = min <= max;
+ bool can_fail = !is_bounded || min < 1 || size < max;
+ auto [pos, tuple] = load_sources(Pos, ARG3, Tuple, ARG4);
+ auto dst = init_destination(Dst, ARG1);
+
+ if (always_small(Pos)) {
+ comment("skipped test for small position since it is always "
+ "small");
+ } else {
+ comment("simplified test for small position since it is an "
+ "integer");
+ emit_is_not_boxed(fail, pos.reg);
+ }
+
+ comment("skipped tuple test since source is always a literal "
+ "tuple");
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, tuple.reg);
+ lea(TMP1, emit_boxed_val(boxed_ptr));
+
+ a.asr(TMP3, pos.reg, imm(_TAG_IMMED1_SIZE));
+
+ if (is_bounded && min >= 1) {
+ comment("skipped check for position >= 1");
+ } else {
+ a.cmp(TMP3, imm(1));
+ a.b_mi(fail);
+ }
+
+ if (is_bounded && size >= max) {
+ comment("skipped check for position beyond tuple");
+ } else {
+ mov_imm(TMP2, size);
+ a.cmp(TMP2, TMP3);
+ a.b_lo(fail);
+ }
+
+ a.ldr(dst.reg, arm::Mem(TMP1, TMP3, arm::lsl(3)));
+
+ if (can_fail) {
+ a.b(next);
+ }
+
+ a.bind(fail);
+ if (can_fail) {
+ if (Fail.get() != 0) {
+ a.b(resolve_beam_label(Fail, disp128MB));
+ } else {
+ a.mov(ARG1, pos.reg);
+ a.mov(ARG2, tuple.reg);
+ fragment_call(ga->get_handle_element_error_shared());
+ }
+ }
+
+ a.bind(next);
+ flush_var(dst);
+
+ return;
+ }
+ }
+
+ mov_arg(ARG1, Pos);
+ mov_arg(ARG2, Tuple);
+
+ if (Fail.get() != 0) {
+ fragment_call(ga->get_bif_element_guard_shared());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ fragment_call(ga->get_bif_element_body_shared());
+ }
+
+ auto dst = init_destination(Dst, ARG1);
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
+
+/* ================================================================
+ * hd/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_handle_hd_error() {
+ static ErtsCodeMFA mfa = {am_erlang, am_hd, 1};
+ emit_raise_badarg(&mfa);
+}
+
+void BeamModuleAssembler::emit_bif_hd(const ArgSource &Src,
+ const ArgRegister &Hd) {
+ Label good_cons = a.newLabel();
+ auto src = load_source(Src, TMP1);
+ auto hd = init_destination(Hd, TMP2);
+ const int bitNumber = 1;
+
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST == (1 << bitNumber));
+
+ a.tbz(src.reg, imm(bitNumber), good_cons);
+ mov_var(XREG0, src);
+ fragment_call(ga->get_handle_hd_error());
+
+ a.bind(good_cons);
+ {
+ arm::Gp cons_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(hd.reg, getCARRef(cons_ptr));
+ flush_var(hd);
+ }
+}
+
+/* ================================================================
+ * map_size/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_handle_map_size_error() {
+ static ErtsCodeMFA mfa = {am_erlang, am_map_size, 1};
+ mov_imm(TMP1, BADMAP);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, freason)));
+ a.str(XREG0, arm::Mem(c_p, offsetof(Process, fvalue)));
+ mov_imm(ARG4, &mfa);
+ a.b(labels[raise_exception]);
+}
+
+void BeamModuleAssembler::emit_bif_map_size(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgRegister &Dst) {
+ Label error = a.newLabel(), good_map = a.newLabel();
+ auto src = load_source(Src, TMP1);
+ auto dst = init_destination(Dst, TMP2);
+
+ if (Fail.get() == 0) {
+ emit_is_boxed(error, Src, src.reg);
+ } else {
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+ }
+
+ arm::Gp boxed_ptr = emit_ptr_val(TMP3, src.reg);
+ a.ldur(TMP4, emit_boxed_val(boxed_ptr));
+ a.and_(TMP4, TMP4, imm(_TAG_HEADER_MASK));
+ a.cmp(TMP4, imm(_TAG_HEADER_MAP));
+
+ if (Fail.get() == 0) {
+ a.b_eq(good_map);
+ a.bind(error);
+ {
+ mov_var(XREG0, src);
+ fragment_call(ga->get_handle_map_size_error());
+ }
+ } else {
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ a.bind(error); /* Never referenced. */
+ }
+
+ a.bind(good_map);
+ {
+ ERTS_CT_ASSERT(offsetof(flatmap_t, size) == sizeof(Eterm));
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ mov_imm(dst.reg, _TAG_IMMED1_SMALL);
+ a.bfi(dst.reg, TMP1, imm(_TAG_IMMED1_SIZE), imm(SMALL_BITS));
+ flush_var(dst);
+ }
+}
+
+/* ================================================================
+ * not/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_handle_not_error() {
+ static ErtsCodeMFA mfa = {am_erlang, am_not, 1};
+ emit_raise_badarg(&mfa);
+}
+
+void BeamModuleAssembler::emit_bif_not(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Dst) {
+ Label next = a.newLabel();
+ auto src = load_source(Src, TMP1);
+ auto dst = init_destination(Dst, TMP2);
+ ERTS_CT_ASSERT(am_false == make_atom(0));
+ ERTS_CT_ASSERT(am_true == make_atom(1));
+ Uint diff_bit = am_true - am_false;
+
+ a.and_(TMP3, src.reg, imm(_TAG_IMMED2_MASK | ~diff_bit));
+ a.cmp(TMP3, imm(_TAG_IMMED2_ATOM));
+
+ if (Fail.get() == 0) {
+ a.b_eq(next);
+ mov_var(XREG0, src);
+ fragment_call(ga->get_handle_not_error());
+ } else {
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+ {
+ a.eor(dst.reg, src.reg, imm(diff_bit));
+ flush_var(dst);
+ }
+}
+
+/* ================================================================
+ * or/2
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_handle_or_error() {
+ static ErtsCodeMFA mfa = {am_erlang, am_or, 2};
+ emit_raise_badarg(&mfa);
+}
+
+void BeamModuleAssembler::emit_bif_or(const ArgLabel &Fail,
+ const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgRegister &Dst) {
+ static const Uint diff_bit = am_true - am_false;
+ Label next = a.newLabel();
+
+ auto [src1, src2] = load_sources(Src1, TMP1, Src2, TMP2);
+ auto dst = init_destination(Dst, TMP3);
+
+ ERTS_CT_ASSERT(am_false == make_atom(0));
+ ERTS_CT_ASSERT(am_true == make_atom(1));
+
+ a.and_(TMP3, src1.reg, imm(_TAG_IMMED2_MASK | ~diff_bit));
+ a.and_(TMP4, src2.reg, imm(_TAG_IMMED2_MASK | ~diff_bit));
+ a.cmp(TMP3, imm(_TAG_IMMED2_ATOM));
+ a.ccmp(TMP3, TMP4, imm(NZCV::kNone), imm(arm::CondCode::kEQ));
+
+ if (Fail.get()) {
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.b_eq(next);
+ mov_var(XREG0, src1);
+ mov_var(XREG1, src2);
+ fragment_call(ga->get_handle_or_error());
+ }
+
+ a.bind(next);
+ {
+ a.orr(dst.reg, src1.reg, src2.reg);
+ flush_var(dst);
+ }
+}
+
+/* ================================================================
+ * tl/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_handle_tl_error() {
+ static ErtsCodeMFA mfa = {am_erlang, am_tl, 1};
+ emit_raise_badarg(&mfa);
+}
+
+void BeamModuleAssembler::emit_bif_tl(const ArgSource &Src,
+ const ArgRegister &Tl) {
+ Label good_cons = a.newLabel();
+ auto src = load_source(Src, TMP1);
+ auto tl = init_destination(Tl, TMP2);
+ const int bitNumber = 1;
+
+ ERTS_CT_ASSERT(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST == (1 << bitNumber));
+
+ a.tbz(src.reg, imm(bitNumber), good_cons);
+ mov_var(XREG0, src);
+ fragment_call(ga->get_handle_tl_error());
+
+ a.bind(good_cons);
+ {
+ arm::Gp cons_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(tl.reg, getCDRRef(cons_ptr));
+ flush_var(tl);
+ }
+}
+
+/* ================================================================
+ * tuple_size/1
+ * ================================================================
+ */
+
+void BeamGlobalAssembler::emit_bif_tuple_size_helper(Label fail) {
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, ARG1);
+
+ emit_is_boxed(fail, boxed_ptr);
+
+ ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr));
+ a.tst(TMP1, imm(_TAG_HEADER_MASK));
+ a.b_ne(fail);
+
+ ERTS_CT_ASSERT(_HEADER_ARITY_OFFS - _TAG_IMMED1_SIZE > 0);
+ ERTS_CT_ASSERT(_TAG_IMMED1_SMALL == _TAG_IMMED1_MASK);
+ a.lsr(TMP1, TMP1, _HEADER_ARITY_OFFS - _TAG_IMMED1_SIZE);
+ a.orr(ARG1, TMP1, imm(_TAG_IMMED1_SMALL));
+
+ a.ret(a64::x30);
+}
+
+void BeamGlobalAssembler::emit_bif_tuple_size_body() {
+ Label error = a.newLabel();
+
+ emit_bif_tuple_size_helper(error);
+
+ a.bind(error);
+ {
+ static ErtsCodeMFA mfa = {am_erlang, am_tuple_size, 1};
+ a.mov(XREG0, ARG1);
+ emit_raise_badarg(&mfa);
+ }
+}
+
+void BeamGlobalAssembler::emit_bif_tuple_size_guard() {
+ Label error = a.newLabel();
+
+ emit_bif_tuple_size_helper(error);
+
+ a.bind(error);
+ {
+ mov_imm(ARG1, THE_NON_VALUE);
+ a.ret(a64::x30);
+ }
+}
+
+void BeamModuleAssembler::emit_bif_tuple_size(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Dst) {
+ auto src = load_source(Src, ARG1);
+ auto dst = init_destination(Dst, ARG1);
+
+ mov_var(ARG1, src);
+
+ if (Fail.get() == 0) {
+ fragment_call(ga->get_bif_tuple_size_body());
+ } else {
+ fragment_call(ga->get_bif_tuple_size_guard());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ }
+
+ mov_var(dst, ARG1);
+ flush_var(dst);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_map.cpp b/erts/emulator/beam/jit/arm/instr_map.cpp
new file mode 100644
index 0000000000..36d0d95433
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_map.cpp
@@ -0,0 +1,636 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+#include <algorithm>
+#include "beam_asm.hpp"
+
+using namespace asmjit;
+
+extern "C"
+{
+#include "erl_map.h"
+#include "beam_common.h"
+}
+
+static const Uint32 INTERNAL_HASH_SALT = 3432918353;
+static const Uint32 HCONST_22 = 0x98C475E6UL;
+static const Uint32 HCONST = 0x9E3779B9;
+
+/* ARG3 = incoming hash
+ * ARG6 = lower 32
+ * ARG7 = upper 32
+ * ARG8 = type constant
+ *
+ * Helper function for calculating the internal hash of keys before looking
+ * them up in a map.
+ *
+ * This is essentially just a manual expansion of the `UINT32_HASH_2` macro.
+ * Whenever the internal hash algorithm is updated, this and all of its users
+ * must follow suit.
+ *
+ * Result is returned in ARG3. All arguments are clobbered. */
+void BeamGlobalAssembler::emit_internal_hash_helper() {
+ a64::Gp hash = ARG3.w(), lower = ARG6.w(), upper = ARG7.w(),
+ constant = ARG8.w();
+
+ a.add(lower, lower, constant);
+ a.add(upper, upper, constant);
+
+ using rounds =
+ std::initializer_list<std::tuple<a64::Gp, a64::Gp, a64::Gp, int>>;
+ for (const auto &round : rounds{{lower, upper, hash, 13},
+ {upper, hash, lower, -8},
+ {hash, lower, upper, 13},
+ {lower, upper, hash, 12},
+ {upper, hash, lower, -16},
+ {hash, lower, upper, 5},
+ {lower, upper, hash, 3},
+ {upper, hash, lower, -10},
+ {hash, lower, upper, 15}}) {
+ const auto &[r_a, r_b, r_c, shift] = round;
+
+ a.sub(r_a, r_a, r_b);
+ a.sub(r_a, r_a, r_c);
+
+ if (shift > 0) {
+ a.eor(r_a, r_a, r_c, arm::lsr(shift));
+ } else {
+ a.eor(r_a, r_a, r_c, arm::lsl(-shift));
+ }
+ }
+
+ a.ret(a64::x30);
+}
+
+/* ARG1 = untagged hash map root
+ * ARG2 = key
+ * ARG3 = key hash
+ * ARG4 = node header
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_hashmap_get_element() {
+ Label node_loop = a.newLabel();
+
+ arm::Gp node = ARG1, key = ARG2, key_hash = ARG3, header_val = ARG4,
+ depth = TMP4, index = TMP5, one = TMP6;
+
+ const int header_shift =
+ (_HEADER_ARITY_OFFS + MAP_HEADER_TAG_SZ + MAP_HEADER_ARITY_SZ);
+
+ /* Skip the root header, which is two words long (child headers are one
+ * word). */
+ a.add(node, node, imm(sizeof(Eterm[2])));
+ mov_imm(depth, 0);
+
+ a.bind(node_loop);
+ {
+ Label fail = a.newLabel(), leaf_node = a.newLabel(),
+ skip_index_adjustment = a.newLabel(), update_hash = a.newLabel();
+
+ /* Find out which child we should follow, and shift the hash for the
+ * next round. */
+ a.and_(index, key_hash, imm(0xF));
+ a.lsr(key_hash, key_hash, imm(4));
+ a.add(depth, depth, imm(1));
+
+ /* The entry offset is always equal to the index on fully populated
+ * nodes, so we'll skip adjusting them. */
+ ERTS_CT_ASSERT(header_shift == 16);
+ a.asr(header_val.w(), header_val.w(), imm(header_shift));
+ a.cmn(header_val.w(), imm(1));
+ a.b_eq(skip_index_adjustment);
+ {
+ /* If our bit isn't set on this node, the key can't be found.
+ *
+ * Note that we jump directly to the return sequence as ZF is clear
+ * at this point. */
+ a.lsr(TMP1, header_val, index);
+ a.tbz(TMP1, imm(0), fail);
+
+ /* The actual offset of our entry is the number of bits set (in
+ * essence "entries present") before our index in the bitmap. Clear
+ * the upper bits and count the remainder. */
+ a.lsl(TMP2, TMP1, index);
+ a.eor(TMP1, TMP2, header_val);
+ a.fmov(a64::d0, TMP1);
+ a.cnt(a64::v0.b8(), a64::v0.b8());
+ a.addv(a64::b0, a64::v0.b8());
+ a.fmov(index, a64::d0);
+ }
+ a.bind(skip_index_adjustment);
+
+ a.ldr(TMP1, arm::Mem(node, index, arm::lsl(3)));
+ emit_untag_ptr(node, TMP1);
+
+ /* Have we found our leaf? */
+ emit_is_boxed(leaf_node, TMP1);
+
+ /* Nope, we have to search another node. Read and skip past the header
+ * word. */
+ a.ldr(header_val, arm::Mem(node).post(sizeof(Eterm)));
+
+ /* After 8 nodes we've run out of the 32 bits we started with, so we
+ * need to update the hash to keep going. */
+ a.tst(depth, imm(0x7));
+ a.b_eq(update_hash);
+ a.b(node_loop);
+
+ a.bind(leaf_node);
+ {
+ /* We've arrived at a leaf, set ZF according to whether its key
+ * matches ours and speculatively place the element in ARG1. */
+ a.ldp(TMP1, ARG1, arm::Mem(node));
+ a.cmp(TMP1, key);
+
+ /* See comment at the jump. */
+ a.bind(fail);
+ a.ret(a64::x30);
+ }
+
+ /* After 8 nodes we've run out of the 32 bits we started with, so we
+ * must calculate a new hash to continue.
+ *
+ * This is a manual expansion `make_map_hash` from utils.c, and all
+ * changes to that function must be mirrored here. */
+ a.bind(update_hash);
+ {
+ emit_enter_runtime_frame();
+
+ /* NOTE: ARG3 (key_hash) is always 0 at this point. */
+ a.lsr(ARG6, depth, imm(3));
+ mov_imm(ARG7, 1);
+ mov_imm(ARG8, HCONST_22);
+ a.bl(labels[internal_hash_helper]);
+
+ mov_imm(TMP1, INTERNAL_HASH_SALT);
+ a.eor(ARG3, ARG3, TMP1);
+
+ a.mov(ARG6.w(), key.w());
+ a.lsr(ARG7, key, imm(32));
+ mov_imm(ARG8, HCONST);
+ a.bl(labels[internal_hash_helper]);
+
+ emit_leave_runtime_frame();
+
+ a.b(node_loop);
+ }
+ }
+}
+
+/* ARG1 = untagged flat map
+ * ARG2 = key
+ * ARG5 = size
+ *
+ * Result is returned in ARG1. ZF is set on success. */
+void BeamGlobalAssembler::emit_flatmap_get_element() {
+ Label fail = a.newLabel(), loop = a.newLabel();
+
+ /* Bump size by 1 to slide past the `keys` field in the map, and the header
+ * word in the key array. Also set flags to ensure ZF == 0 when entering
+ * the loop. */
+ a.adds(ARG5, ARG5, imm(1));
+
+ /* Adjust our map pointer to the `keys` field before loading it. This
+ * saves us from having to bump it to point at the values later on. */
+ a.ldr(TMP1, arm::Mem(ARG1).pre(offsetof(flatmap_t, keys)));
+ emit_untag_ptr(TMP1, TMP1);
+
+ a.bind(loop);
+ {
+ a.sub(ARG5, ARG5, imm(1));
+ a.cbz(ARG5, fail);
+
+ a.ldr(TMP4, arm::Mem(TMP1, ARG5, arm::lsl(3)));
+ a.cmp(ARG2, TMP4);
+ a.b_ne(loop);
+ }
+
+ a.ldr(ARG1, arm::Mem(ARG1, ARG5, arm::lsl(3)));
+
+ a.bind(fail);
+ a.ret(a64::x30);
+}
+
+void BeamGlobalAssembler::emit_new_map_shared() {
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(erts_gc_new_map);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+void BeamModuleAssembler::emit_new_map(const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ embed_vararg_rodata(args, ARG5);
+
+ mov_arg(ARG3, Live);
+ mov_imm(ARG4, args.size());
+ fragment_call(ga->get_new_map_shared());
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamGlobalAssembler::emit_i_new_small_map_lit_shared() {
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(erts_gc_new_small_map_lit);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+void BeamModuleAssembler::emit_i_new_small_map_lit(const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgLiteral &Keys,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ ASSERT(Size.get() == args.size());
+
+ embed_vararg_rodata(args, ARG5);
+
+ ASSERT(Keys.isLiteral());
+ mov_arg(ARG3, Keys);
+ mov_arg(ARG4, Live);
+
+ fragment_call(ga->get_i_new_small_map_lit_shared());
+
+ mov_arg(Dst, ARG1);
+}
+
+/* ARG1 = map
+ * ARG2 = key
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_i_get_map_element_shared() {
+ Label generic = a.newLabel(), hashmap = a.newLabel();
+
+ a.and_(TMP1, ARG2, imm(_TAG_PRIMARY_MASK));
+ a.cmp(TMP1, imm(TAG_PRIMARY_IMMED1));
+ a.b_ne(generic);
+
+ emit_untag_ptr(ARG1, ARG1);
+
+ /* hashmap_get_element expects node header in ARG4, flatmap_get_element
+ * expects size in ARG5 */
+ ERTS_CT_ASSERT_FIELD_PAIR(flatmap_t, thing_word, size);
+ a.ldp(ARG4, ARG5, arm::Mem(ARG1));
+ a.and_(TMP1, ARG4, imm(_HEADER_MAP_SUBTAG_MASK));
+ a.cmp(TMP1, imm(HAMT_SUBTAG_HEAD_FLATMAP));
+ a.b_ne(hashmap);
+
+ emit_flatmap_get_element();
+
+ a.bind(generic);
+ {
+ emit_enter_runtime_frame();
+
+ emit_enter_runtime();
+ runtime_call<2>(get_map_element);
+ emit_leave_runtime();
+
+ a.cmp(ARG1, imm(THE_NON_VALUE));
+
+ /* Invert ZF, we want it to be set when RET is a value. */
+ a.cset(TMP1, arm::CondCode::kEQ);
+ a.tst(TMP1, TMP1);
+
+ emit_leave_runtime_frame();
+ a.ret(a64::x30);
+ }
+
+ a.bind(hashmap);
+ {
+ emit_enter_runtime_frame();
+
+ /* Calculate the internal hash of ARG2 before diving into the HAMT. */
+ mov_imm(ARG3, INTERNAL_HASH_SALT);
+ a.mov(ARG6.w(), ARG2.w());
+ a.lsr(ARG7, ARG2, imm(32));
+ mov_imm(ARG8, HCONST);
+ a.bl(labels[internal_hash_helper]);
+
+ emit_leave_runtime_frame();
+
+ emit_hashmap_get_element();
+ }
+}
+
+void BeamModuleAssembler::emit_i_get_map_element(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Key,
+ const ArgRegister &Dst) {
+ mov_arg(ARG1, Src);
+ mov_arg(ARG2, Key);
+
+ if (masked_types(Key, BEAM_TYPE_MASK_IMMEDIATE) != BEAM_TYPE_NONE) {
+ fragment_call(ga->get_i_get_map_element_shared());
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ } else {
+ emit_enter_runtime();
+ runtime_call<2>(get_map_element);
+ emit_leave_runtime();
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ }
+
+ /*
+ * Don't store the result if the destination is the scratch X register.
+ * (This instruction was originally a has_map_fields instruction.)
+ */
+ if (!(Dst.isXRegister() && Dst.as<ArgXRegister>().get() == SCRATCH_X_REG)) {
+ mov_arg(Dst, ARG1);
+ }
+}
+
+void BeamModuleAssembler::emit_i_get_map_elements(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ Label generic = a.newLabel(), next = a.newLabel();
+
+ /* We're not likely to gain much from inlining huge extractions, and the
+ * resulting code is quite large, so we'll cut it off after a handful
+ * elements.
+ *
+ * Note that the arguments come in flattened triplets of
+ * `{Key, Dst, KeyHash}` */
+ bool can_inline = args.size() < (8 * 3);
+
+ ASSERT(Size.get() == args.size());
+ ASSERT((Size.get() % 3) == 0);
+
+ for (size_t i = 0; i < args.size(); i += 3) {
+ can_inline &= args[i].isImmed();
+ }
+
+ mov_arg(ARG1, Src);
+
+ if (can_inline) {
+ comment("simplified multi-element lookup");
+
+ emit_untag_ptr(TMP1, ARG1);
+
+ ERTS_CT_ASSERT_FIELD_PAIR(flatmap_t, thing_word, size);
+ a.ldp(TMP2, TMP3, arm::Mem(TMP1, offsetof(flatmap_t, thing_word)));
+ a.and_(TMP2, TMP2, imm(_HEADER_MAP_SUBTAG_MASK));
+ a.cmp(TMP2, imm(HAMT_SUBTAG_HEAD_FLATMAP));
+ a.b_ne(generic);
+
+ check_pending_stubs();
+
+ /* Bump size by 1 to slide past the `keys` field in the map, and the
+ * header word in the key array. */
+ a.add(TMP3, TMP3, imm(1));
+
+ /* Adjust our map pointer to the `keys` field before loading it. This
+ * saves us from having to bump it to point at the values later on. */
+ ERTS_CT_ASSERT(sizeof(flatmap_t) ==
+ offsetof(flatmap_t, keys) + sizeof(Eterm));
+ a.ldr(TMP2, arm::Mem(TMP1).pre(offsetof(flatmap_t, keys)));
+ emit_untag_ptr(TMP2, TMP2);
+
+ for (ssize_t i = args.size() - 3; i >= 0; i -= 3) {
+ Label loop = a.newLabel();
+
+ a.bind(loop);
+ {
+ a.subs(TMP3, TMP3, imm(1));
+ a.b_eq(resolve_beam_label(Fail, disp1MB));
+
+ a.ldr(TMP4, arm::Mem(TMP2, TMP3, arm::lsl(3)));
+
+ const auto &Comparand = args[i];
+ cmp_arg(TMP4, Comparand);
+ a.b_ne(loop);
+ }
+
+ /* Don't store the result if the destination is the scratch X
+ * register. (This instruction was originally a has_map_fields
+ * instruction.) */
+ const auto &Dst = args[i + 1];
+ if (!(Dst.isXRegister() &&
+ Dst.as<ArgXRegister>().get() == SCRATCH_X_REG)) {
+ mov_arg(Dst, arm::Mem(TMP1, TMP3, arm::lsl(3)));
+ }
+ }
+
+ a.b(next);
+ }
+
+ a.bind(generic);
+ {
+ embed_vararg_rodata(args, ARG5);
+
+ a.mov(ARG3, E);
+
+ emit_enter_runtime<Update::eXRegs>();
+
+ mov_imm(ARG4, args.size() / 3);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(beam_jit_get_map_elements);
+
+ emit_leave_runtime<Update::eXRegs>();
+
+ a.cbz(ARG1, resolve_beam_label(Fail, disp1MB));
+ }
+
+ a.bind(next);
+}
+
+/* ARG1 = map
+ * ARG2 = key
+ * ARG3 = key hash
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_i_get_map_element_hash_shared() {
+ Label hashmap = a.newLabel();
+
+ emit_untag_ptr(ARG1, ARG1);
+
+ /* hashmap_get_element expects node header in ARG4, flatmap_get_element
+ * expects size in ARG5 */
+ ERTS_CT_ASSERT_FIELD_PAIR(flatmap_t, thing_word, size);
+ a.ldp(ARG4, ARG5, arm::Mem(ARG1));
+ a.and_(TMP1, ARG4, imm(_HEADER_MAP_SUBTAG_MASK));
+ a.cmp(TMP1, imm(HAMT_SUBTAG_HEAD_FLATMAP));
+ a.b_ne(hashmap);
+
+ emit_flatmap_get_element();
+
+ a.bind(hashmap);
+ emit_hashmap_get_element();
+}
+
+void BeamModuleAssembler::emit_i_get_map_element_hash(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgConstant &Key,
+ const ArgWord &Hx,
+ const ArgRegister &Dst) {
+ mov_arg(ARG1, Src);
+ mov_arg(ARG2, Key);
+ mov_arg(ARG3, Hx);
+
+ if (Key.isImmed()) {
+ fragment_call(ga->get_i_get_map_element_hash_shared());
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ } else {
+ emit_enter_runtime();
+ runtime_call<3>(get_map_element_hash);
+ emit_leave_runtime();
+
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ }
+
+ /*
+ * Don't store the result if the destination is the scratch X register.
+ * (This instruction was originally a has_map_fields instruction.)
+ */
+ if (!(Dst.isXRegister() && Dst.as<ArgXRegister>().get() == SCRATCH_X_REG)) {
+ mov_arg(Dst, ARG1);
+ }
+}
+
+/* ARG3 = live registers, ARG4 = update vector size, ARG5 = update vector. */
+void BeamGlobalAssembler::emit_update_map_assoc_shared() {
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(erts_gc_update_map_assoc);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+void BeamModuleAssembler::emit_update_map_assoc(const ArgSource &Src,
+ const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ auto src_reg = load_source(Src, TMP1);
+
+ ASSERT(Size.get() == args.size());
+
+ embed_vararg_rodata(args, ARG5);
+
+ mov_arg(ArgXRegister(Live.get()), src_reg.reg);
+ mov_arg(ARG3, Live);
+ mov_imm(ARG4, args.size());
+
+ fragment_call(ga->get_update_map_assoc_shared());
+
+ mov_arg(Dst, ARG1);
+}
+
+/* ARG3 = live registers, ARG4 = update vector size, ARG5 = update vector.
+ *
+ * Result is returned in RET, error is indicated by ZF. */
+void BeamGlobalAssembler::emit_update_map_exact_guard_shared() {
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(erts_gc_update_map_exact);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+ emit_leave_runtime_frame();
+
+ a.ret(a64::x30);
+}
+
+/* ARG3 = live registers, ARG4 = update vector size, ARG5 = update vector.
+ *
+ * Does not return on error. */
+void BeamGlobalAssembler::emit_update_map_exact_body_shared() {
+ Label error = a.newLabel();
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(erts_gc_update_map_exact);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+ emit_leave_runtime_frame();
+
+ emit_branch_if_not_value(ARG1, error);
+ a.ret(a64::x30);
+
+ a.bind(error);
+ {
+ mov_imm(ARG4, 0);
+ a.b(labels[raise_exception]);
+ }
+}
+
+void BeamModuleAssembler::emit_update_map_exact(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ auto src_reg = load_source(Src, TMP1);
+
+ ASSERT(Size.get() == args.size());
+
+ embed_vararg_rodata(args, ARG5);
+
+ /* We _KNOW_ Src is a map */
+
+ mov_arg(ArgXRegister(Live.get()), src_reg.reg);
+ mov_arg(ARG3, Live);
+ mov_imm(ARG4, args.size());
+
+ if (Fail.get() != 0) {
+ fragment_call(ga->get_update_map_exact_guard_shared());
+ emit_branch_if_not_value(ARG1, resolve_beam_label(Fail, dispUnknown));
+ } else {
+ fragment_call(ga->get_update_map_exact_body_shared());
+ }
+
+ mov_arg(Dst, ARG1);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_msg.cpp b/erts/emulator/beam/jit/arm/instr_msg.cpp
new file mode 100644
index 0000000000..e512261d96
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_msg.cpp
@@ -0,0 +1,385 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "bif.h"
+#include "code_ix.h"
+#include "erl_proc_sig_queue.h"
+#ifdef USE_VM_PROBES
+# include "dtrace-wrapper.h"
+#endif
+}
+
+#ifdef ERTS_SUPPORT_OLD_RECV_MARK_INSTRS
+
+static void recv_mark(Process *p) {
+ /* inlined here... */
+ erts_msgq_recv_marker_insert_bind(p, erts_old_recv_marker_id);
+}
+
+static void recv_mark_set(Process *p) {
+ /* inlined here... */
+ erts_msgq_recv_marker_set_save(p, erts_old_recv_marker_id);
+}
+
+void BeamModuleAssembler::emit_i_recv_mark() {
+ /*
+ * OLD INSTRUCTION: This instruction is to be removed
+ * in OTP 26.
+ *
+ * Save the current end of message queue
+ */
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(recv_mark);
+
+ emit_leave_runtime();
+}
+
+void BeamModuleAssembler::emit_i_recv_set() {
+ /*
+ * OLD INSTRUCTION: This instruction is to be removed
+ * in OTP 26.
+ *
+ * If previously saved recv mark, set save pointer to it
+ */
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(recv_mark_set);
+
+ emit_leave_runtime();
+}
+
+#endif /* ERTS_SUPPORT_OLD_RECV_MARK_INSTRS */
+
+void BeamModuleAssembler::emit_recv_marker_reserve(const ArgRegister &Dst) {
+ emit_enter_runtime<Update::eStack | Update::eHeap>();
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(erts_msgq_recv_marker_insert);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>();
+
+ mov_arg(Dst, ARG1);
+}
+
+void BeamModuleAssembler::emit_recv_marker_bind(const ArgRegister &Marker,
+ const ArgRegister &Reference) {
+ mov_arg(ARG2, Marker);
+ mov_arg(ARG3, Reference);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_msgq_recv_marker_bind);
+
+ emit_leave_runtime();
+}
+
+void BeamModuleAssembler::emit_recv_marker_clear(const ArgRegister &Reference) {
+ mov_arg(ARG2, Reference);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_msgq_recv_marker_clear);
+
+ emit_leave_runtime();
+}
+
+void BeamModuleAssembler::emit_recv_marker_use(const ArgRegister &Reference) {
+ mov_arg(ARG2, Reference);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_msgq_recv_marker_set_save);
+
+ emit_leave_runtime();
+}
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+int erts_lc_proc_sig_receive_helper(Process *c_p,
+ int fcalls,
+ int neg_o_reds,
+ ErtsMessage **msgpp,
+ int *get_outp) {
+ int res;
+ /*
+ * erts_proc_sig_receive_helper() may temporarliy release
+ * its own main lock...
+ */
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ res = erts_proc_sig_receive_helper(c_p,
+ fcalls,
+ neg_o_reds,
+ msgpp,
+ get_outp);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+ return res;
+}
+#endif
+
+void BeamGlobalAssembler::emit_i_loop_rec_shared() {
+ Label restart = a.newLabel(), peek_message = a.newLabel(),
+ schedule_out = a.newLabel(), check_is_distributed = a.newLabel(),
+ done = a.newLabel();
+
+ arm::Mem await_addr = TMP_MEM1q, message_ptr = TMP_MEM2q,
+ get_out = TMP_MEM3q;
+ arm::Mem flags = arm::Mem(c_p, offsetof(Process, flags));
+
+ a.mov(XREG1, a64::x30);
+
+ a.ldr(TMP1.w(), flags);
+ a.orr(TMP1, TMP1, imm(F_DELAY_GC));
+ a.str(TMP1.w(), flags);
+ a.str(ARG1, arm::Mem(c_p, offsetof(Process, i)));
+ a.str(ARG2, await_addr);
+
+ a.bind(restart);
+ {
+ a.tst(FCALLS, FCALLS);
+ a.b_le(schedule_out);
+
+ /* !! FALL THROUGH !! */
+ }
+
+ comment("Peek next message");
+ a.bind(peek_message);
+ {
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, sig_qs.save)));
+ a.ldr(ARG1, arm::Mem(TMP1));
+ a.cbnz(ARG1, check_is_distributed);
+ comment("Inner queue empty, fetch more from outer/middle queues");
+
+ emit_enter_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap>(0);
+
+ a.str(ZERO, message_ptr);
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, FCALLS);
+ mov_imm(ARG3, 0);
+ lea(ARG4, message_ptr);
+ lea(ARG5, get_out);
+#ifdef ERTS_ENABLE_LOCK_CHECK
+ runtime_call<5>(erts_lc_proc_sig_receive_helper);
+#else
+ runtime_call<5>(erts_proc_sig_receive_helper);
+#endif
+
+ /* erts_proc_sig_receive_helper merely inspects FCALLS, so we don't
+ * need to update it here.
+ *
+ * Also note that another process may have loaded new code and sent us
+ * a message to notify us about it, so we must update the active code
+ * index. */
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eCodeIndex>(
+ 0);
+
+ a.sub(FCALLS, FCALLS, ARG1);
+
+ /* Need to spill message_ptr to ARG1 as check_is_distributed uses it. */
+ a.ldr(ARG1, message_ptr);
+ a.cbnz(ARG1, check_is_distributed);
+
+ /* Did we receive a signal or run out of reds? */
+ a.ldr(TMP1.w(), get_out);
+ a.cbnz(TMP1, schedule_out);
+
+ /* The queue is empty and we're not yielding or exiting, so we'll jump
+ * to our wait/timeout instruction.
+ *
+ * Note that the message queue lock is still held in this case. */
+ a.ldr(TMP1.w(), flags);
+ a.and_(TMP1, TMP1, imm(~F_DELAY_GC));
+ a.str(TMP1.w(), flags);
+
+ a.ldr(TMP1, await_addr);
+ a.br(TMP1);
+ }
+
+ a.bind(schedule_out);
+ {
+ /* We either ran out of reductions or received an exit signal; schedule
+ * ourselves out. The yield address (`c_p->i`) was set on ingress. */
+ a.ldr(TMP1.w(), flags);
+ a.and_(TMP1, TMP1, imm(~F_DELAY_GC));
+ a.str(TMP1.w(), flags);
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, arity)));
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, current)));
+
+ a.b(labels[do_schedule]);
+ }
+
+ /*
+ * ARG1 now contains the pointer to a message.
+ */
+ comment("Check if message is distributed");
+ a.bind(check_is_distributed);
+ {
+ a.ldr(TMP1, arm::Mem(ARG1, offsetof(ErtsSignal, common.tag)));
+ emit_branch_if_value(TMP1, done);
+
+ sub(FCALLS, FCALLS, 10);
+
+ emit_enter_runtime(0);
+
+ a.mov(ARG2, ARG1);
+ a.mov(ARG1, c_p);
+ runtime_call<2>(beam_jit_decode_dist);
+
+ emit_leave_runtime(0);
+
+ a.cbz(ARG1, restart);
+
+ /* !! FALL THROUGH !! */
+ }
+
+ a.bind(done);
+ {
+ a.ldr(XREG0, arm::Mem(ARG1, offsetof(ErtsMessage, m[0])));
+ a.ret(XREG1);
+ }
+}
+
+void BeamModuleAssembler::emit_i_loop_rec(const ArgLabel &Wait) {
+ Label entry = a.newLabel();
+
+ a.bind(entry);
+ a.adr(ARG1, entry);
+ a.ldr(ARG2, embed_constant(Wait, disp32K));
+ fragment_call(ga->get_i_loop_rec_shared());
+}
+
+void BeamModuleAssembler::emit_remove_message() {
+ /* HTOP and E are passed explicitly and only read from, so we don't need to
+ * swap them out. */
+ a.mov(ARG3, HTOP);
+ a.mov(ARG4, E);
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, FCALLS);
+ a.mov(ARG5, active_code_ix);
+ runtime_call<5>(beam_jit_remove_message);
+ a.mov(FCALLS, ARG1);
+
+ emit_leave_runtime();
+}
+
+void BeamModuleAssembler::emit_loop_rec_end(const ArgLabel &Dest) {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(erts_msgq_set_save_next);
+
+ emit_leave_runtime(0);
+
+ a.sub(FCALLS, FCALLS, imm(1));
+ a.b(resolve_beam_label(Dest, disp128MB));
+}
+
+void BeamModuleAssembler::emit_wait_unlocked(const ArgLabel &Dest) {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ a.ldr(ARG2, embed_constant(Dest, disp32K));
+ runtime_call<2>(beam_jit_wait_unlocked);
+
+ emit_leave_runtime(0);
+
+ a.b(resolve_fragment(ga->get_do_schedule(), disp128MB));
+}
+
+void BeamModuleAssembler::emit_wait_locked(const ArgLabel &Dest) {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ a.ldr(ARG2, embed_constant(Dest, disp32K));
+ runtime_call<2>(beam_jit_wait_locked);
+
+ emit_leave_runtime(0);
+
+ a.b(resolve_fragment(ga->get_do_schedule(), disp128MB));
+}
+
+void BeamModuleAssembler::emit_wait_timeout_unlocked(const ArgSource &Src,
+ const ArgLabel &Dest) {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(beam_jit_take_receive_lock);
+
+ emit_leave_runtime(0);
+
+ emit_wait_timeout_locked(Src, Dest);
+}
+
+void BeamModuleAssembler::emit_wait_timeout_locked(const ArgSource &Src,
+ const ArgLabel &Dest) {
+ Label wait = a.newLabel(), next = a.newLabel();
+
+ mov_arg(ARG2, Src);
+
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ a.adr(ARG3, next);
+ runtime_call<3>(beam_jit_wait_timeout);
+
+ emit_leave_runtime(0);
+
+ ERTS_CT_ASSERT(RET_next < RET_wait && RET_wait < RET_badarg);
+ a.cmp(ARG1, imm(RET_wait));
+ a.b_eq(wait);
+ a.b_lt(next);
+
+ emit_raise_exception(current_label, (ErtsCodeMFA *)nullptr);
+
+ a.bind(wait);
+ emit_wait_locked(Dest);
+
+ a.bind(next);
+}
+
+void BeamModuleAssembler::emit_timeout_locked() {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(beam_jit_timeout_locked);
+
+ emit_leave_runtime(0);
+}
+
+void BeamModuleAssembler::emit_timeout() {
+ emit_enter_runtime(0);
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(beam_jit_timeout);
+
+ emit_leave_runtime(0);
+}
diff --git a/erts/emulator/beam/jit/arm/instr_select.cpp b/erts/emulator/beam/jit/arm/instr_select.cpp
new file mode 100644
index 0000000000..41c9b0a95c
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_select.cpp
@@ -0,0 +1,498 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <algorithm>
+#include <numeric>
+
+#include "beam_asm.hpp"
+
+using namespace asmjit;
+
+template<typename T>
+static constexpr bool isInt13(T value) {
+ typedef typename std::make_unsigned<T>::type U;
+ typedef typename std::make_signed<T>::type S;
+
+ return Support::isUInt12(U(value)) || Support::isUInt12(-S(value));
+}
+
+/* The `cmp`/`cmn` instructions in AArch64 only accept 12-bit unsigned immediate
+ * values (`cmn` negating said immediate, giving us an effective range of 13
+ * bit signed). That means that to compare most atoms, the atom number to be
+ * compared must be loaded into a temporary register.
+ *
+ * We can use the immediate form of `cmp`/`cmn` for more values if we untag
+ * both the source value and the values to be compared.
+ *
+ * This function finds the `base` and `shift` that result in the most number
+ * of elements fitting in a 13-bit immediate. */
+static std::pair<UWord, int> plan_untag(const Span<ArgVal> &args) {
+ auto left = args.begin(), right = args.begin();
+ auto best_left = left, best_right = right;
+ int count, shift;
+
+ count = args.size() / 2;
+
+ ASSERT(left->isImmed() && (args.begin() + count)->isLabel());
+ ASSERT(left->isSmall() || right->isAtom());
+
+ shift = left->isSmall() ? _TAG_IMMED1_SIZE : _TAG_IMMED2_SIZE;
+
+ while (right < (args.begin() + count)) {
+ auto distance = std::distance(left, right);
+ UWord left_value, mid_value, right_value;
+
+ left_value = left->as<ArgImmed>().get() >> shift;
+ mid_value = (left + distance / 2)->as<ArgImmed>().get() >> shift;
+ right_value = right->as<ArgImmed>().get() >> shift;
+
+ if (isInt13(left_value - mid_value) &&
+ isInt13(right_value - mid_value)) {
+ if (distance > std::distance(best_left, best_right)) {
+ best_right = right;
+ best_left = left;
+ }
+
+ right++;
+ } else {
+ left++;
+ }
+ }
+
+ auto distance = std::distance(best_left, best_right);
+
+ /* Skip everything if the best run is too short, untagging has its costs
+ * too. */
+ if (distance <= 6) {
+ return std::make_pair(0, 0);
+ }
+
+ /* Apply neither shift nor base if the best run doesn't need it: we're more
+ * likely to lose by rebasing/shifting. */
+ if (isInt13(best_left->as<ArgImmed>().get()) &&
+ isInt13(best_right->as<ArgImmed>().get())) {
+ return std::make_pair(0, 0);
+ }
+
+ /* Skip rebasing if the best run doesn't need it after shifting. */
+ if (isInt13(best_left->as<ArgImmed>().get() >> shift) &&
+ isInt13(best_right->as<ArgImmed>().get() >> shift)) {
+ return std::make_pair(0, shift);
+ }
+
+ auto mid_value = (best_left + distance / 2)->as<ArgImmed>().get();
+ return std::make_pair(mid_value, shift);
+}
+
+const std::vector<ArgVal> BeamModuleAssembler::emit_select_untag(
+ const Span<ArgVal> &args,
+ a64::Gp comparand,
+ Label fail,
+ UWord base,
+ int shift) {
+ ASSERT(base != 0 || shift > 0);
+
+ /* Emit code to test that the source value has the correct type and
+ * untag it. */
+ comment("(comparing untagged+rebased values)");
+ if (args.front().isSmall()) {
+ a.and_(TMP1, comparand, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED1_SMALL));
+ } else {
+ ASSERT(args.front().isAtom());
+ a.and_(TMP1, comparand, imm(_TAG_IMMED2_MASK));
+ a.cmp(TMP1, imm(_TAG_IMMED2_ATOM));
+ }
+
+ a.b_ne(resolve_label(fail, disp1MB));
+
+ if (shift != 0) {
+ a.lsr(ARG1, comparand, imm(shift));
+ base >>= shift;
+
+ comparand = ARG1;
+ }
+
+ std::vector<ArgVal> result(args.begin(), args.end());
+ int count = args.size() / 2;
+
+ if (base != 0) {
+ sub(ARG1, comparand, base);
+
+ /* The values will always be ordered differently after adjusting the
+ * base, so we have to sort them again.
+ *
+ * This is rather annoying because the labels and values can't be
+ * sorted together. Perhaps we should diverge from the other platforms,
+ * keeping them together just on ARM? */
+ std::vector<int> sorted_indexes(count);
+ std::iota(sorted_indexes.begin(), sorted_indexes.end(), 0);
+ std::sort(sorted_indexes.begin(),
+ sorted_indexes.end(),
+ [&](int lhs, int rhs) {
+ auto lhs_value =
+ (args[lhs].as<ArgImmed>().get() >> shift) - base;
+ auto rhs_value =
+ (args[rhs].as<ArgImmed>().get() >> shift) - base;
+ return lhs_value < rhs_value;
+ });
+
+ for (auto i = 0; i < count; i++) {
+ const auto &src_value = args[sorted_indexes[i]];
+ const auto &src_label = args[sorted_indexes[i] + count];
+ auto &dst_value = result[i];
+ auto &dst_label = result[i + count];
+
+ /* The value won't be a valid immediate after shifting, so we
+ * change it to a word. */
+ dst_value =
+ ArgWord((src_value.as<ArgImmed>().get() >> shift) - base);
+ dst_label = src_label;
+ }
+ } else {
+ /* Fast-path for when a shift alone is enough, it won't affect the
+ * order. */
+ for (auto i = 0; i < count; i++) {
+ auto &dst_value = result[i];
+ auto &dst_label = result[i + count];
+
+ dst_value = ArgWord(args[i].as<ArgImmed>().get() >> shift);
+ dst_label = args[i + count];
+ }
+ }
+
+ ASSERT(std::is_sorted(result.begin(),
+ result.begin() + count,
+ [](const ArgWord &lhs, const ArgWord &rhs) {
+ return lhs.get() < rhs.get();
+ }));
+
+ return result;
+}
+
+void BeamModuleAssembler::emit_linear_search(arm::Gp comparand,
+ Label fail,
+ const Span<ArgVal> &args) {
+ int count = args.size() / 2;
+
+ for (int i = 0; i < count; i++) {
+ const ArgVal &value = args[i];
+ const ArgVal &label = args[i + count];
+
+ if ((i % 128) == 0) {
+ /* Checking veneers on the first element is intentional. */
+ check_pending_stubs();
+ }
+
+ cmp_arg(comparand, value);
+ a.b_eq(resolve_beam_label(label, disp1MB));
+ }
+
+ /* An invalid label means fallthrough to the next instruction. */
+ if (fail.isValid()) {
+ a.b(resolve_label(fail, disp128MB));
+ }
+}
+
+void BeamModuleAssembler::emit_i_select_tuple_arity(const ArgRegister &Src,
+ const ArgLabel &Fail,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ auto src = load_source(Src, TMP1);
+
+ emit_is_boxed(resolve_beam_label(Fail, dispUnknown), Src, src.reg);
+
+ arm::Gp boxed_ptr = emit_ptr_val(TMP1, src.reg);
+ a.ldur(TMP1, emit_boxed_val(boxed_ptr, 0));
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_TUPLE) {
+ comment("simplified tuple test since the source is always a tuple "
+ "when boxed");
+ } else {
+ ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
+ a.tst(TMP1, imm(_TAG_HEADER_MASK));
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ }
+
+ Label fail = rawLabels[Fail.get()];
+ emit_linear_search(TMP1, fail, args);
+}
+
+void BeamModuleAssembler::emit_i_select_val_lins(const ArgSource &Src,
+ const ArgVal &Fail,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ ASSERT(Size.get() == args.size());
+ Label fail, next;
+
+ /*
+ * To keep the code simpler, we will drop down a level and
+ * use rawLabels. That will allow us to use Label to represent
+ * a label present in the BEAM file or a label created here.
+ */
+
+ if (Fail.isLabel()) {
+ next = fail = rawLabels[Fail.as<ArgLabel>().get()];
+ } else {
+ ASSERT(Fail.isNil());
+
+ /* Fail is [], meaning that if none of the values match,
+ * we should fall through to the next instruction.
+ *
+ * We set `next` to a label that will be located after the
+ * instructions for the linear search. That label is needed if
+ * values are untagged and a type test is emitted to skip the
+ * comparisons of the untagged values in case the type is
+ * wrong.
+ *
+ * We intentionally do not initialize the Label `fail`
+ * as an indication for emit_optimized_three_way_select() and
+ * emit_linear_search() that not branch is needed at the end
+ * of the linear search.
+ */
+ next = a.newLabel();
+ }
+
+ auto src = load_source(Src, ARG1);
+
+ auto plan = plan_untag(args);
+ auto base = plan.first;
+ auto shift = plan.second;
+
+ if (base == 0 && shift == 0) {
+ if (!emit_optimized_three_way_select(src.reg, fail, args)) {
+ emit_linear_search(src.reg, fail, args);
+ }
+ } else {
+ auto untagged = emit_select_untag(args, src.reg, next, base, shift);
+
+ if (!emit_optimized_three_way_select(ARG1, fail, untagged)) {
+ emit_linear_search(ARG1, fail, untagged);
+ }
+ }
+
+ if (!Fail.isLabel()) {
+ bind_veneer_target(next);
+ }
+}
+
+void BeamModuleAssembler::emit_i_select_val_bins(const ArgSource &Src,
+ const ArgVal &Fail,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ ASSERT(Size.get() == args.size());
+
+ int count = args.size() / 2;
+ Label fail;
+
+ /* See the comment in emit_i_select_val_lins() for an explanation
+ * why we use raw labels. */
+ if (Fail.isLabel()) {
+ fail = rawLabels[Fail.as<ArgLabel>().get()];
+ } else {
+ ASSERT(Fail.isNil());
+ fail = a.newLabel();
+ }
+
+ comment("Binary search in table of %lu elements", count);
+
+ auto src = load_source(Src, ARG1);
+
+ auto plan = plan_untag(args);
+ auto base = plan.first;
+ auto shift = plan.second;
+
+ if (base == 0 && shift == 0) {
+ emit_binsearch_nodes(src.reg, 0, count - 1, fail, args);
+ } else {
+ auto untagged = emit_select_untag(args, src.reg, fail, base, shift);
+ emit_binsearch_nodes(ARG1, 0, count - 1, fail, untagged);
+ }
+
+ if (!Fail.isLabel()) {
+ bind_veneer_target(fail);
+ }
+}
+
+/*
+ * Emit code for a binary search through an interval Left <= Right of
+ * the i_select_val argument vector `args`.
+ */
+void BeamModuleAssembler::emit_binsearch_nodes(arm::Gp reg,
+ size_t Left,
+ size_t Right,
+ Label fail,
+ const Span<ArgVal> &args) {
+ ASSERT(Left <= Right);
+ ASSERT(Right < args.size() / 2);
+
+ const size_t remaining = (Right - Left + 1);
+ const size_t mid = (Left + Right) >> 1;
+ const size_t count = args.size() / 2;
+
+ if (remaining <= 10) {
+ /* Measurements on randomly generated select_val instructions
+ have shown that linear search is faster than binary search
+ when there are ten or less elements.
+ */
+ std::vector<ArgVal> shrunk;
+
+ comment("Linear search in [%lu..%lu], %lu elements",
+ Left,
+ Right,
+ remaining);
+
+ shrunk.reserve(remaining * 2);
+ shrunk.insert(shrunk.end(),
+ args.begin() + Left,
+ args.begin() + Left + remaining);
+ shrunk.insert(shrunk.end(),
+ args.begin() + Left + count,
+ args.begin() + count + Left + remaining);
+
+ emit_linear_search(reg, fail, shrunk);
+
+ return;
+ }
+
+ comment("Subtree [%lu..%lu], pivot %lu", Left, Right, mid);
+
+ check_pending_stubs();
+
+ cmp_arg(reg, args[mid]);
+
+ auto &lbl = args[mid + count];
+
+ /* The search has failed if Left == Right, but that should never
+ * happen since we revert to a linear search when there are
+ * ten or less elements. */
+ ASSERT(Left != Right);
+ ASSERT(Left != mid);
+
+ a.b_eq(resolve_beam_label(lbl, disp1MB));
+
+ Label right_tree = a.newLabel();
+ a.b_hs(resolve_label(right_tree, disp1MB));
+
+ emit_binsearch_nodes(reg, Left, mid - 1, fail, args);
+
+ bind_veneer_target(right_tree);
+ emit_binsearch_nodes(reg, mid + 1, Right, fail, args);
+}
+
+void BeamModuleAssembler::emit_i_jump_on_val(const ArgSource &Src,
+ const ArgVal &Fail,
+ const ArgWord &Base,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ Label fail;
+ auto src = load_source(Src, TMP1);
+
+ ASSERT(Size.get() == args.size());
+
+ a.and_(TMP3, src.reg, imm(_TAG_IMMED1_MASK));
+ a.cmp(TMP3, imm(_TAG_IMMED1_SMALL));
+
+ if (Fail.isLabel()) {
+ a.b_ne(resolve_beam_label(Fail, disp1MB));
+ } else {
+ /* NIL means fallthrough to the next instruction. */
+ ASSERT(Fail.isNil());
+
+ fail = a.newLabel();
+ a.b_ne(fail);
+ }
+
+ a.asr(TMP1, src.reg, imm(_TAG_IMMED1_SIZE));
+
+ if (Base.get() != 0) {
+ if (Support::isUInt12((Sint)Base.get())) {
+ a.sub(TMP1, TMP1, imm(Base.get()));
+ } else {
+ mov_imm(TMP3, Base.get());
+ a.sub(TMP1, TMP1, TMP3);
+ }
+ }
+
+ a.cmp(TMP1, imm(args.size()));
+ if (Fail.isLabel()) {
+ a.b_hs(resolve_beam_label(Fail, disp1MB));
+ } else {
+ a.b_hs(fail);
+ }
+
+ embed_vararg_rodata(args, TMP2);
+ a.ldr(TMP3, arm::Mem(TMP2, TMP1, arm::lsl(3)));
+ a.br(TMP3);
+
+ if (Fail.getType() == ArgVal::Immediate) {
+ a.bind(fail);
+ }
+}
+
+/*
+ * Attempt to optimize the case when a select_val has exactly two
+ * values which only differ by one bit and they both branch to the
+ * same label.
+ *
+ * The optimization makes use of the observation that (V == X || V ==
+ * Y) is equivalent to (V | (X ^ Y)) == (X | Y) when (X ^ Y) has only
+ * one bit set.
+ *
+ * Return true if the optimization was possible.
+ */
+bool BeamModuleAssembler::emit_optimized_three_way_select(
+ arm::Gp reg,
+ Label fail,
+ const Span<ArgVal> &args) {
+ if (args.size() != 4 || (args[2] != args[3])) {
+ return false;
+ }
+
+ uint64_t x = args[0].isImmed() ? args[0].as<ArgImmed>().get()
+ : args[0].as<ArgWord>().get();
+ uint64_t y = args[1].isImmed() ? args[1].as<ArgImmed>().get()
+ : args[1].as<ArgWord>().get();
+ uint64_t combined = x | y;
+ uint64_t diff = x ^ y;
+
+ ArgWord val(combined);
+
+ if ((diff & (diff - 1)) != 0) {
+ return false;
+ }
+
+ comment("(Src == 0x%x || Src == 0x%x) <=> (Src | 0x%x) == 0x%x",
+ x,
+ y,
+ diff,
+ combined);
+
+ a.orr(TMP1, reg, imm(diff));
+ cmp_arg(TMP1, val);
+ a.b_eq(resolve_beam_label(args[2], disp1MB));
+
+ /* An invalid label means fallthrough to the next instruction. */
+ if (fail.isValid()) {
+ a.b(resolve_label(fail, disp128MB));
+ }
+
+ return true;
+}
diff --git a/erts/emulator/beam/jit/arm/instr_trace.cpp b/erts/emulator/beam/jit/arm/instr_trace.cpp
new file mode 100644
index 0000000000..b8a64d2628
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/instr_trace.cpp
@@ -0,0 +1,217 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "beam_common.h"
+#include "erl_bif_table.h"
+#include "beam_bp.h"
+};
+
+/* This function is jumped to from the export entry of a function.
+ *
+ * ARG1 = export entry */
+void BeamGlobalAssembler::emit_generic_bp_global() {
+ /* Enter an Erlang frame to make the stack consistent with local
+ * breakpoints. */
+ emit_enter_erlang_frame();
+
+ lea(ARG2, arm::Mem(ARG1, offsetof(Export, info)));
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ /* ARG2 is already set above */
+ load_x_reg_array(ARG3);
+ runtime_call<3>(erts_generic_breakpoint);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ /* This is technically a tail call so we must leave the current frame
+ * before jumping. Note that we might not leave the frame we entered
+ * earlier in this function, but one added by erts_generic_breakpoint. */
+ emit_leave_erlang_frame();
+ a.br(ARG1);
+}
+
+/* This function is called from the module header, which is in turn called from
+ * the prologue of the traced function. As such, the real return address is at
+ * SP+8 rather than LR (x30).
+ *
+ * See beam_asm.h for more details */
+void BeamGlobalAssembler::emit_generic_bp_local() {
+ a.ldr(ARG2, arm::Mem(a64::sp, 8));
+
+ /* Stash return address for later use in `debug_bp` */
+ a.str(ARG2, TMP_MEM1q);
+
+ /* Our actual return address is valid (and word-aligned), but it points
+ * just after the trampoline word so we'll need to skip that to find our
+ * ErtsCodeInfo. */
+ a.sub(ARG2, ARG2, imm(BEAM_ASM_FUNC_PROLOGUE_SIZE + sizeof(ErtsCodeInfo)));
+
+ emit_enter_runtime_frame();
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ /* ARG2 is already set above */
+ load_x_reg_array(ARG3);
+ runtime_call<3>(erts_generic_breakpoint);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.cmp(ARG1, imm(BeamOpCodeAddr(op_i_debug_breakpoint)));
+ a.b_eq(labels[debug_bp]);
+
+ emit_leave_runtime_frame();
+ a.ret(a64::x30);
+}
+
+/* This function is called from the module header which is called from the
+ * prologue of the function to trace. See beam_asm.h for more details
+ *
+ * The only place that we can come to here is from generic_bp_local */
+void BeamGlobalAssembler::emit_debug_bp() {
+ Label error = a.newLabel();
+
+ /* Read and adjust the return address we saved in generic_bp_local. */
+ a.ldr(ARG2, TMP_MEM1q);
+ a.sub(ARG2, ARG2, imm(BEAM_ASM_FUNC_PROLOGUE_SIZE + sizeof(ErtsCodeMFA)));
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG3);
+ a.mov(ARG4, imm(am_breakpoint));
+ runtime_call<4>(call_error_handler);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>();
+
+ /* We skip two runtime frames (ours and the one entered in the module
+ * header) so that we can call the error handler's code instead of
+ * `call_nif_early`, if necessary. */
+ emit_leave_runtime_frame();
+ emit_leave_runtime_frame();
+
+ a.cbz(ARG1, error);
+
+ emit_leave_erlang_frame();
+ branch(emit_setup_dispatchable_call(ARG1));
+
+ a.bind(error);
+ {
+ a.ldr(ARG2, TMP_MEM1q);
+ mov_imm(ARG4, 0);
+
+ a.b(labels[raise_exception_shared]);
+ }
+}
+
+static void return_trace(Process *c_p,
+ ErtsCodeMFA *mfa,
+ Eterm val,
+ ErtsTracer *tracer) {
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ erts_trace_return(c_p, mfa, val, tracer);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+}
+
+void BeamModuleAssembler::emit_return_trace() {
+ a.ldr(ARG2, getYRef(0));
+ a.mov(ARG3, XREG0);
+ lea(ARG4, getYRef(1));
+
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 1);
+ emit_enter_runtime<Update::eStack | Update::eHeap>(1);
+
+ a.mov(ARG1, c_p);
+ runtime_call<4>(return_trace);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(1);
+
+ emit_deallocate(ArgVal(ArgVal::Word, 2));
+ emit_return();
+}
+
+void BeamModuleAssembler::emit_i_return_time_trace() {
+ /* Pass prev_info if present (is a CP), otherwise null. */
+ a.ldr(ARG2, getYRef(0));
+ mov_imm(ARG3, 0);
+
+ a.tst(ARG2, imm(_CPMASK));
+ a.sub(ARG2, ARG2, imm(sizeof(ErtsCodeInfo)));
+ a.csel(ARG2, ARG2, ARG3, arm::CondCode::kEQ);
+
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 1);
+ emit_enter_runtime<Update::eStack | Update::eHeap>(1);
+
+ a.mov(ARG1, c_p);
+ runtime_call<2>(erts_trace_time_return);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(1);
+
+ emit_deallocate(ArgVal(ArgVal::Word, 1));
+ emit_return();
+}
+
+void BeamModuleAssembler::emit_i_return_to_trace() {
+ ERTS_CT_ASSERT(ERTS_HIGHEST_CALLEE_SAVE_XREG >= 1);
+ emit_enter_runtime<Update::eStack | Update::eHeap>(1);
+
+ a.mov(ARG1, c_p);
+ runtime_call<1>(beam_jit_return_to_trace);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap>(1);
+
+ emit_deallocate(ArgVal(ArgVal::Word, 0));
+ emit_return();
+}
+
+void BeamModuleAssembler::emit_i_hibernate() {
+ Label error = a.newLabel();
+
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(3);
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<2>(erts_hibernate);
+
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs |
+ Update::eReductions>(3);
+
+ a.cbz(ARG1, error);
+
+ a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags)));
+ a.and_(TMP1, TMP1, imm(~F_HIBERNATE_SCHED));
+ a.str(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags)));
+ a.b(resolve_fragment(ga->get_do_schedule(), disp128MB));
+
+ a.bind(error);
+ emit_raise_exception(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa);
+}
diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab
new file mode 100644
index 0000000000..9cfce18e58
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/ops.tab
@@ -0,0 +1,1391 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+
+#
+# Types that should never be used in specific operations.
+#
+
+FORBIDDEN_TYPES=hQ
+
+#
+# The instructions that follows are only known by the loader and the emulator.
+# They can be changed without recompiling old Beam files.
+#
+# Instructions starting with a "i_" prefix are instructions produced by
+# instruction transformations; thus, they never occur in BEAM files.
+#
+
+# The too_old_compiler/0 instruction is specially handled in beam_load.c
+# to produce a user-friendly message informing the user that the module
+# needs to be re-compiled with a modern compiler.
+
+too_old_compiler/0
+too_old_compiler | never() => _
+
+# In R9C and earlier, the loader used to insert special instructions inside
+# the module_info/0,1 functions. (In R10B and later, the compiler inserts
+# an explicit call to an undocumented BIF, so that no loader trickery is
+# necessary.) Since the instructions don't work correctly in R12B, simply
+# refuse to load the module.
+
+func_info M=a a==am_module_info A=u==0 | label L | move n x==0 => too_old_compiler
+func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compiler
+
+# The undocumented and unsupported guard BIF is_constant/1 was removed
+# in R13. The is_constant/2 operation is marked as obsolete in genop.tab,
+# so the loader will automatically generate a too_old_compiler message
+# it is used, but we need to handle the is_constant/1 BIF specially here.
+
+bif1 Fail u$func:erlang:is_constant/1 Src Dst => too_old_compiler
+
+#
+# All the other instructions.
+#
+
+%cold
+# An unaligned label. The address of an unaligned label must never be saved
+# on the stack or used in a context where it can be confused with an Erlang term.
+
+label L
+
+# An label aligned to a certain boundary. This is used in two cases:
+#
+# * When the label points to the start of a function, as the ErtsCodeInfo
+# struct must be word-aligned.
+# * When the address is stored on the stack or otherwise needs to be properly
+# tagged as a continuation pointer.
+aligned_label L t
+
+i_func_info I a a I
+int_code_end
+nif_start
+
+i_generic_breakpoint
+i_debug_breakpoint
+i_return_time_trace
+i_return_to_trace
+trace_jump W
+i_yield
+%hot
+
+return
+
+#
+# A tail call will not refer to the current function on error unless it's a
+# BIF, so we can omit the line instruction for non-BIFs.
+#
+
+move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D =>
+ move S X0 | call_ext_last Ar Func D
+move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif =>
+ move S X0 | call_ext_only Ar Func
+
+move S X0=x==0 | line Loc | call_last Ar Func D =>
+ move S X0 | call_last Ar Func D
+move S X0=x==0 | line Loc | call_only Ar Func =>
+ move S X0 | call_only Ar Func
+
+# The line number in int_func_start/5 can be NIL.
+func_line n => empty_func_line
+
+empty_func_line
+func_line I
+
+line n => _
+line I
+
+allocate t t
+allocate_heap t I t
+
+deallocate t
+
+init y
+
+trim t t
+
+test_heap I t
+
+# Translate instructions generated by a compiler before OTP 24.
+allocate_zero Ns Live => allocate_heap_zero Ns u Live
+allocate_heap_zero Ns Nh Live => allocate_heap_zero(Ns, Nh, Live)
+
+init_yregs I *
+
+# Selecting values.
+
+# The size of the dispatch code for a jump table is at least 40 bytes
+# (8 instructions + one 64-bit word for the pointer to the
+# table). Therefore we shouldn't use a jump table if there are too few
+# values.
+
+select_val S Fail=fn Size=u Rest=* | use_jump_tab(Size, Rest, 6) =>
+ jump_tab(S, Fail, Size, Rest)
+
+is_integer Fail=f S=s | select_val S2 Fail2 Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) |
+ use_jump_tab(Size, Rest, 6) =>
+ jump_tab(S, Fail, Size, Rest)
+
+is_integer TypeFail=f S=s | select_val S2 Fail=fn Size=u Rest=* |
+ equal(S, S2) |
+ mixed_types(Size, Rest) =>
+ split_values(S, TypeFail, Fail, Size, Rest)
+
+select_val S Fail=fn Size=u Rest=* | mixed_types(Size, Rest) =>
+ split_values(S, Fail, Fail, Size, Rest)
+
+is_integer Fail=f S=d | select_val S2 Fail2 Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) |
+ fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
+
+is_atom Fail=f S=d | select_val S2 Fail2 Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) |
+ fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
+
+select_val S Fail=fn Size=u Rest=* | floats_or_bignums(Size, Rest) =>
+ select_literals(S, Fail, Size, Rest)
+
+select_val S Fail=fn Size=u Rest=* | fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
+
+is_tuple Fail=f S=d | select_tuple_arity S2 Fail2 Size=u Rest=* |
+ equal(Fail, Fail2) | equal(S, S2) =>
+ select_tuple_arity(S, Fail, Size, Rest)
+
+select_tuple_arity S=d Fail=f Size=u Rest=* =>
+ select_tuple_arity(S, Fail, Size, Rest)
+
+i_select_val_bins s fn I *
+
+i_select_val_lins s fn I *
+
+i_select_tuple_arity S f I *
+
+i_jump_on_val s fn W I *
+
+is_number f s
+
+jump f
+
+#
+# List matching instructions. The combination of test for a nonempty list
+# followed by get_{list/hd/tl} are common, so we will optimize that.
+#
+is_nonempty_list Fail nqia => jump Fail
+
+is_nonempty_list f S
+
+get_list S d d
+get_hd S d
+get_tl S d
+
+# Old-style catch.
+catch y H
+catch_end y
+
+# Try/catch.
+try Y F => catch Y F
+
+try_case y
+try_end y
+
+try_case_end s
+
+# Destructive set tuple element
+
+set_tuple_element s S P
+
+#
+# Get tuple element. Since this instruction is frequently used, we will try
+# to only fetch the pointer to the tuple once for a sequence of BEAM
+# instructions that fetch multiple elements from the same tuple.
+#
+
+current_tuple/1
+current_tuple/2
+
+is_tuple Fail=f Src | test_arity Fail2 Src2 Arity |
+ equal(Fail, Fail2) | equal(Src, Src) =>
+ i_is_tuple_of_arity Fail Src Arity | current_tuple Src
+
+test_arity Fail Src Arity => i_test_arity Fail Src Arity | current_tuple Src
+
+is_tuple NotTupleFail Src |
+ is_tagged_tuple WrongRecordFail Tuple Arity Atom |
+ equal(Src, Tuple) =>
+ i_is_tagged_tuple_ff NotTupleFail WrongRecordFail Src Arity Atom |
+ current_tuple Src
+
+is_tagged_tuple Fail Tuple Arity Atom =>
+ i_is_tagged_tuple Fail Tuple Arity Atom | current_tuple Tuple
+
+is_tuple Fail=f Src => i_is_tuple Fail Src | current_tuple Src
+
+i_is_tuple_of_arity f s A
+i_test_arity f s A
+
+i_is_tagged_tuple f s A a
+i_is_tagged_tuple_ff f f s A a
+
+i_is_tuple f s
+
+# Generate instruction sequence for fetching the tuple element and remember
+# that we have a current tuple pointer.
+
+get_tuple_element Tuple Pos Dst =>
+ load_tuple_ptr Tuple |
+ i_get_tuple_element Tuple Pos Dst |
+ current_tuple Tuple
+
+current_tuple Tuple | get_tuple_element Tuple2 Pos Dst |
+ equal(Tuple, Tuple2) =>
+ i_get_tuple_element Tuple Pos Dst |
+ current_tuple Tuple
+
+# Drop the current_tuple instruction if the tuple is overwritten.
+i_get_tuple_element Tuple Pos Tuple2 | current_tuple Tuple3 |
+ equal(Tuple, Tuple2) | equal(Tuple, Tuple3) =>
+ i_get_tuple_element Tuple Pos Tuple
+
+# This is a current_tuple instruction instruction not followed by
+# get_tuple_element. Invalidate the current tuple pointer.
+
+current_tuple Tuple => _
+
+load_tuple_ptr s
+
+# If positions are in consecutive memory, fetch and store two words at
+# once.
+i_get_tuple_element Tuple Pos1 Dst1 |
+ current_tuple Tuple2 |
+ get_tuple_element Tuple3 Pos2 Dst2 |
+ equal(Tuple, Tuple2) | equal(Tuple, Tuple3) |
+ consecutive_words(Pos1, Pos2) =>
+ get_two_tuple_elements Tuple Pos1 Dst1 Dst2 |
+ current_tuple Tuple Dst2
+
+# Drop the current_tuple instruction if the tuple is overwritten.
+current_tuple Tuple Tuple2 | equal(Tuple, Tuple2) => _
+current_tuple Tuple Dst => current_tuple Tuple
+
+# The first operand will only be used in the debug-compiled runtime
+# system to verify that the register holding the tuple pointer agrees
+# with the source tuple operand.
+i_get_tuple_element s P S
+get_two_tuple_elements s P S S
+
+#
+# Exception raising instructions. Infrequently executed.
+#
+
+%cold
+case_end s
+
+badmatch s
+
+if_end
+
+badrecord s
+
+raise s s
+
+# Workaround the limitation that generators must always return at least one
+# instruction.
+delete_me/0
+delete_me => _
+
+system_limit/1
+system_limit p => system_limit_body
+system_limit Fail=f => jump Fail
+
+system_limit_body
+
+%hot
+
+#
+# Optimize moves of consecutive memory addresses.
+#
+move Src=c Dst => i_move Src Dst
+move Src SrcDst | move SrcDst2 Dst |
+ equal(SrcDst, SrcDst2) =>
+ i_move Src SrcDst | move SrcDst Dst
+
+# Optimize two moves from X registers to Y registers when destination
+# Y registers are consecutive.
+
+move S1=x D1=y | move S2=x D2=y | consecutive_words(D1, D2) =>
+ store_two_xregs S1 D1 S2 D2
+move S1=x D1=y | move S2=x D2=y | consecutive_words(D2, D1) =>
+ store_two_xregs S2 D2 S1 D1
+
+# Optimize two moves from Y registers to X registers when source Y
+# registers are consecutive.
+
+move S1=y D1=x | move S2=y D2=x |
+ consecutive_words(S1, S2) |
+ distinct(D1, D2) =>
+ load_two_xregs S1 D1 S2 D2
+
+move S1=y D1=x | move S2=y D2=x |
+ consecutive_words(S2, S1) |
+ distinct(D1, D2) =>
+ load_two_xregs S2 D2 S1 D1
+
+# Optimize two moves of Y registers when destinations are consecutive.
+move S1=y D1=y | move S2=y D2=y |
+ consecutive_words(D1, D2) =>
+ move_two_yregs S1 D1 S2 D2
+
+move S1=y D1=y | move S2=y D2=y |
+ consecutive_words(D2, D1) =>
+ move_two_yregs S2 D2 S1 D1
+
+move Src Dst => i_move Src Dst
+
+i_move s d
+store_two_xregs x y x y
+load_two_xregs y x y x
+move_two_yregs y y y y
+
+#
+# Swap instructions.
+#
+
+swap R1 R2 | swap R2Other R3 | equal(R2, R2Other) => swap2 R1 R2 R3
+swap R1 R2 | swap R1Other R3 | equal(R1, R1Other) => swap2 R2 R1 R3
+swap R1 R2 | swap R3 R1Other | equal(R1, R1Other) => swap2 R2 R1 R3
+swap R1 R2 | swap R3 R2Other | equal(R2, R2Other) => swap2 R1 R2 R3
+
+swap2 R1 R2 R3 | swap R3Other R4 |
+ equal(R3, R3Other) =>
+ swap3 R1 R2 R3 R4
+swap2 R1 R2 R3 | swap R4 R3Other |
+ equal(R3, R3Other) =>
+ swap3 R1 R2 R3 R4
+
+swap3 R1 R2 R3 R4 | swap R4Other R5 |
+ equal(R4, R4Other) =>
+ swap4 R1 R2 R3 R4 R5
+swap3 R1 R2 R3 R4 | swap R5 R4Other |
+ equal(R4, R4Other) =>
+ swap4 R1 R2 R3 R4 R5
+
+swap d d
+swap2 d d d
+swap3 d d d d
+swap4 d d d d d
+
+#
+# Receive operations. We conservatively align all labels before any
+# of the receive instructions.
+#
+# As the labels may be stored in the process structure, we must align them to
+# the nearest 4-byte boundary to ensure they're properly tagged as continuation
+# pointers.
+#
+
+label L | loop_rec Fail Reg =>
+ aligned_label L u=4 | loop_rec Fail Reg
+label L | wait_timeout Fail Src =>
+ aligned_label L u=4 | wait_timeout Fail Src
+label L | wait Fail =>
+ aligned_label L u=4 | wait Fail
+label L | timeout =>
+ aligned_label L u=4 | timeout
+
+loop_rec Fail x==0 | smp_mark_target_label(Fail) => i_loop_rec Fail
+
+aligned_label L A | wait_timeout Fail Src | smp_already_locked(L) =>
+ aligned_label L A | wait_timeout_locked Src Fail
+wait_timeout Fail Src => wait_timeout_unlocked Src Fail
+
+aligned_label L A | wait Fail | smp_already_locked(L) =>
+ aligned_label L A | wait_locked Fail
+wait Fail => wait_unlocked Fail
+
+aligned_label L A | timeout | smp_already_locked(L) =>
+ aligned_label L A | timeout_locked
+
+remove_message
+timeout
+timeout_locked
+i_loop_rec f
+loop_rec_end f
+wait_locked f
+wait_unlocked f
+
+# Note that a timeout value must fit in 32 bits.
+wait_timeout_unlocked s f
+wait_timeout_locked s f
+
+send
+
+#
+# Optimized comparisons with one immediate/literal operand.
+#
+
+is_eq_exact Lbl LHS RHS | equal(LHS, RHS) => _
+is_eq_exact Lbl C=c R=xy => is_eq_exact Lbl R C
+
+is_eq_exact Lbl R=xy n => is_nil Lbl R
+
+is_ne_exact Lbl LHS RHS | equal(LHS, RHS) => jump Lbl
+is_ne_exact Lbl C=c R=xy => is_ne_exact Lbl R C
+
+is_eq_exact f s s
+
+is_ne_exact f s s
+
+is_lt f s s
+is_ge f s s
+
+is_eq Fail=f Const=c Reg=xy => is_eq Fail Reg Const
+is_eq f s s
+
+is_ne Fail=f Const=c Reg=xy => is_ne Fail Reg Const
+is_ne f s s
+
+#
+# Putting tuples.
+#
+# Code compiled with OTP 22 and later uses put_tuple2 to
+# to construct a tuple.
+#
+
+put_tuple2 S A *
+
+#
+# Putting lists.
+#
+
+put_list Hd1=y Tl Dst | put_list Hd2=y Dst2 Dst3 |
+ equal(Dst, Dst2) | equal(Dst, Dst3) |
+ consecutive_words(Hd1, Hd2) =>
+ put_list2 Hd1 Hd2 Tl Dst
+
+put_list s s d
+put_list2 s s s d
+
+#
+# Some more only used by the emulator
+#
+
+%cold
+normal_exit
+continue_exit
+call_bif W
+call_bif_mfa a a I
+call_nif W W W
+call_error_handler
+return_trace
+%hot
+
+#
+# Type tests. Note that the operands for most type tests are `s` to
+# ensure that literal operands will work. The BEAM compiler starting
+# from OTP 22 will never emit type tests with literal operands even if
+# all optimizations are turned off, but loading unoptimized code from
+# older releases and code generated by alternative code generators.
+#
+
+is_integer f s
+is_list f s
+is_atom f s
+is_float f s
+
+is_nil Fail=f n => _
+is_nil Fail=f qia => jump Fail
+is_nil f S
+
+# XXX Deprecated.
+is_bitstr Fail Term => is_bitstring Fail Term
+
+is_binary f s
+is_bitstring f s
+
+is_reference f s
+is_pid f s
+is_port f s
+
+is_boolean f s
+
+is_function2 f s s
+
+#################################################################
+# External function and bif calls.
+#################################################################
+
+# Expands into call_light_bif/2
+call_light_bif/1
+
+#
+# The load_nif/2 BIF is an instruction.
+#
+
+call_ext u==2 u$func:erlang:load_nif/2 =>
+ i_load_nif
+call_ext_last u==2 u$func:erlang:load_nif/2 D =>
+ i_load_nif | deallocate D | return
+call_ext_only u==2 u$func:erlang:load_nif/2 =>
+ i_load_nif | return
+
+%cold
+i_load_nif
+%hot
+
+#
+# The call_on_load_function/1 BIF is an instruction.
+#
+
+call_ext u==1 u$func:erlang:call_on_load_function/1 =>
+ i_call_on_load_function
+call_ext_last u==1 u$func:erlang:call_on_load_function/1 D =>
+ i_call_on_load_function | deallocate D | return
+call_ext_only u==1 u$func:erlang:call_on_load_function/1 =>
+ i_call_on_load_function | return
+
+%cold
+i_call_on_load_function
+%hot
+
+#
+# apply/2 is an instruction, not a BIF.
+#
+
+call_ext u==2 u$func:erlang:apply/2 => i_apply_fun
+call_ext_last u==2 u$func:erlang:apply/2 D => i_apply_fun_last D
+call_ext_only u==2 u$func:erlang:apply/2 => i_apply_fun_only
+
+#
+# The apply/3 BIF is an instruction.
+#
+
+call_ext u==3 u$func:erlang:apply/3 => i_apply
+call_ext_last u==3 u$func:erlang:apply/3 D => i_apply_last D
+call_ext_only u==3 u$func:erlang:apply/3 => i_apply_only
+
+#
+# The yield/0 BIF is an instruction
+#
+
+call_ext u==0 u$func:erlang:yield/0 => i_yield
+call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate D | return
+call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return
+
+#
+# The hibernate/3 BIF is an instruction.
+#
+call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate
+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
+
+call_ext u==0 u$func:os:perf_counter/0 =>
+ i_perf_counter
+call_ext_last u==0 u$func:os:perf_counter/0 D =>
+ i_perf_counter | deallocate D | return
+call_ext_only u==0 u$func:os:perf_counter/0 =>
+ i_perf_counter | return
+
+#
+# BIFs like process_info/1,2 require up-to-date information about the current
+# emulator state, which the ordinary call_light_bif instruction doesn't save.
+#
+
+call_ext u Bif=u$is_bif | is_heavy_bif(Bif) =>
+ i_call_ext Bif
+call_ext_last u Bif=u$is_bif D | is_heavy_bif(Bif) =>
+ i_call_ext Bif | deallocate D | return
+call_ext_only Ar=u Bif=u$is_bif | is_heavy_bif(Bif) =>
+ allocate u Ar | i_call_ext Bif | deallocate u | return
+
+#
+# The general case for BIFs that have no special requirements.
+#
+
+call_ext u Bif=u$is_bif =>
+ call_light_bif Bif
+call_ext_last u Bif=u$is_bif D =>
+ call_light_bif Bif | deallocate D | return
+call_ext_only Ar=u Bif=u$is_bif =>
+ allocate u Ar | call_light_bif Bif | deallocate u | return
+
+#
+# Any remaining calls are calls to Erlang functions, not BIFs.
+# We rename the instructions to internal names. This is necessary,
+# to avoid an end-less loop, because we want to call a few BIFs
+# with call instructions.
+#
+
+call_ext Ar Func => i_call_ext Func
+call_ext_last Ar Func D => i_call_ext_last Func D
+call_ext_only Ar Func => i_call_ext_only Func
+
+i_validate t
+
+i_apply
+i_apply_last t
+i_apply_only
+
+i_apply_fun
+i_apply_fun_last t
+i_apply_fun_only
+
+call_light_bif Bif => call_light_bif Bif Bif
+call_light_bif b e
+
+%cold
+
+i_hibernate
+i_perf_counter
+
+%hot
+
+#
+# Calls to non-building and guard BIFs.
+#
+
+bif0 u$bif:erlang:self/0 Dst=d => self Dst
+bif0 u$bif:erlang:node/0 Dst=d => node Dst
+
+bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=xy Dst =>
+ is_nonempty_list Fail Src | get_hd Src Dst
+bif1 Fail=p Bif=u$bif:erlang:hd/1 Src Dst =>
+ bif_hd Src Dst
+
+bif_hd s d
+
+bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=xy Dst =>
+ is_nonempty_list Fail Src | get_tl Src Dst
+bif1 Fail=p Bif=u$bif:erlang:tl/1 Src Dst =>
+ bif_tl Src Dst
+
+bif_tl s d
+
+bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => get(Src, Dst)
+
+bif2 Fail u$bif:erlang:element/2 S1 S2 Dst => bif_element Fail S1 S2 Dst
+bif_element j s s d
+
+bif2 Fail Bif=u$bif:erlang:and/2 Src1 Src2 Dst=d => bif_and Fail Src1 Src2 Dst
+bif_and j s s d
+
+bif2 Fail Bif=u$bif:erlang:or/2 Src1 Src2 Dst=d => bif_or Fail Src1 Src2 Dst
+bif_or j s s d
+
+bif1 Fail Bif=u$bif:erlang:not/1 Src=d Dst=d => bif_not Fail Src Dst
+bif_not j S d
+
+gc_bif1 Fail Live Bif=u$bif:erlang:bit_size/1 Src Dst=d =>
+ bif_bit_size Fail Src Dst
+bif_bit_size j s d
+
+gc_bif1 Fail Live Bif=u$bif:erlang:byte_size/1 Src Dst=d =>
+ bif_byte_size Fail Src Dst
+bif_byte_size j s d
+
+bif1 Fail Bif=u$bif:erlang:tuple_size/1 Src=d Dst=d =>
+ bif_tuple_size Fail Src Dst
+bif_tuple_size j S d
+
+bif1 Fail Bif S1 Dst | never_fails(Bif) => nofail_bif1 S1 Bif Dst
+bif2 Fail Bif S1 S2 Dst | never_fails(Bif) => nofail_bif2 S1 S2 Bif Dst
+
+bif1 Fail Bif S1 Dst => i_bif1 S1 Fail Bif Dst
+bif2 Fail Bif S1 S2 Dst => i_bif2 S1 S2 Fail Bif Dst
+
+nofail_bif2 S1=d S2 Bif Dst | is_eq_exact_bif(Bif) => bif_is_eq_exact S1 S2 Dst
+nofail_bif2 S1=d S2 Bif Dst | is_ne_exact_bif(Bif) => bif_is_ne_exact S1 S2 Dst
+
+i_get_hash c I d
+i_get s d
+
+self d
+
+node d
+
+nofail_bif1 s b d
+nofail_bif2 s s b d
+
+i_bif1 s j b d
+i_bif2 s s j b d
+i_bif3 s s s j b d
+
+bif_is_eq_exact S s d
+bif_is_ne_exact S s d
+
+#
+# Internal calls.
+#
+
+call Ar Func => i_call Func
+call_last Ar Func D => i_call_last Func D
+call_only Ar Func => i_call_only Func
+
+i_call f
+i_call_last f t
+i_call_only f
+
+i_call_ext e
+i_call_ext_last e t
+i_call_ext_only e
+
+# Fun calls.
+
+call_fun Arity | deallocate D | return => i_call_fun_last Arity D
+call_fun Arity => i_call_fun Arity
+
+i_call_fun t
+i_call_fun_last t t
+
+call_fun2 Safe Arity Func | deallocate D | return =>
+ i_call_fun2_last Safe Arity Func D
+call_fun2 Safe Arity Func =>
+ i_call_fun2 Safe Arity Func
+
+i_call_fun2 aF t S
+i_call_fun2_last aF t S t
+
+#
+# A fun with an empty environment can be converted to a literal.
+# As a further optimization, the we try to move the fun to its
+# final destination directly.
+
+make_fun2 OldIndex=u =>
+ make_fun2(OldIndex)
+make_fun3 OldIndex=u Dst=d NumFree=u Env=* =>
+ make_fun3(OldIndex, Dst, NumFree, Env)
+
+%cold
+
+i_make_fun3 F S t t *
+
+# Psuedo-instruction for signalling lambda load errors. Never actually runs.
+i_lambda_error t
+
+%hot
+
+is_function f S
+is_function Fail=f c => jump Fail
+
+# The start and end of a function.
+int_func_start/5
+int_func_end/2
+
+func_prologue/2
+
+int_func_start Func_Label Func_Line M F A |
+ label Entry_Label | line Entry_Line =>
+ int_func_start Func_Label Func_Line M F A |
+ func_prologue Entry_Label Entry_Line
+
+int_func_start Func_Label Func_Line M F A |
+ label Entry_Label =>
+ int_func_start Func_Label Func_Line M F A |
+ func_prologue Entry_Label n
+
+int_func_start Func_Label Func_Line M F A |
+ func_prologue Entry_Label Entry_Line |
+ is_mfa_bif(M, F, A) =>
+ i_flush_stubs |
+ func_line Func_Line |
+ aligned_label Func_Label u=8 |
+ i_func_info Func_Label M F A |
+ aligned_label Entry_Label u=8 |
+ i_breakpoint_trampoline |
+ line Entry_Line |
+ call_bif_mfa M F A
+
+int_func_start Func_Label Func_Line M F A |
+ func_prologue Entry_Label Entry_Line =>
+ i_flush_stubs |
+ func_line Func_Line |
+ aligned_label Func_Label u=8 |
+ i_func_info Func_Label M F A |
+ aligned_label Entry_Label u=8 |
+ i_breakpoint_trampoline |
+ line Entry_Line |
+ i_test_yield
+
+int_func_end Func_Label Entry_Label =>
+ func_end(Func_Label, Entry_Label)
+
+# Handles yielding on function ingress (rather than on each call).
+i_test_yield
+
+# Ensures that the prior function is large enough to allow NIF patching.
+i_nif_padding
+
+# Flushes veneers prior to entering a new function so we don't have to worry
+# about them being emitted in the prologue or NIF padding.
+i_flush_stubs
+
+# Handles tracing, early NIF calls, and so on.
+i_breakpoint_trampoline
+
+# ================================================================
+# New bit syntax matching (R11B).
+# ================================================================
+
+%warm
+
+# Matching integers
+bs_match_string Fail Ms Bits Val => i_bs_match_string Ms Fail Bits Val
+
+i_bs_match_string S f W M
+
+# Fetching integers from binaries.
+bs_get_integer2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d =>
+ get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+
+i_bs_get_integer S f t t s d
+i_bs_get_fixed_integer S f t t t d
+
+# Fetching binaries from binaries.
+bs_get_binary2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d =>
+ get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+
+i_bs_get_binary2 S f t s t d
+i_bs_get_binary_all2 S f t t d
+
+# Fetching float from binaries.
+bs_get_float2 Fail=f Ms=xy Live=u Sz=s Unit=u Flags=u Dst=d =>
+ get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+
+bs_get_float2 Fail=f Ms=x Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
+
+i_bs_get_float2 S f t s t d
+
+# Miscellaneous
+
+bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u =>
+ skip_bits2(Fail, Ms, Sz, Unit, Flags)
+
+i_bs_skip_bits_imm2 f S W
+i_bs_skip_bits2 S S f t
+
+bs_test_tail2 Fail=f Ms=xy o => jump Fail
+
+bs_test_tail2 f S W
+
+bs_test_unit f S t
+
+# Gets a bitstring from the tail of a context.
+bs_get_tail S d t
+
+# New bs_start_match variant for contexts with external position storage.
+#
+# bs_get/set_position is used to save positions into registers instead of
+# "slots" in the context itself, which lets us continue matching even after
+# we've passed it off to another function.
+
+bs_start_match4 a==am_no_fail Live=u Src=xy Ctx=d =>
+ bs_start_match3 p Src Live Ctx
+bs_start_match4 Fail=f Live=u Src=xy Ctx=d =>
+ bs_start_match3 Fail Src Live Ctx
+
+%if ARCH_64
+
+# This instruction nops on 64-bit platforms
+bs_start_match4 a==am_resume Live Ctx Dst | equal(Ctx, Dst) => _
+bs_start_match4 a==am_resume Live Ctx Dst => move Ctx Dst
+
+%else
+
+bs_start_match4 a==am_resume Live Ctx Dst =>
+ bs_start_match4 a=am_no_fail Live Ctx Dst
+
+%endif
+
+bs_start_match3 Fail=j ica Live Dst => jump Fail
+bs_start_match3 Fail Bin Live Dst => i_bs_start_match3 Bin Live Fail Dst
+
+i_bs_start_match3 S t j d
+
+# Match context position instructions. 64-bit assumes that all positions can
+# fit into an unsigned small.
+
+%if ARCH_64
+ bs_get_position Src Dst Live => i_bs_get_position Src Dst
+ i_bs_get_position S S
+ bs_set_position S S
+%else
+ bs_get_position S d t
+ bs_set_position S S
+%endif
+
+#
+# Utf8/utf16/utf32 support. (R12B-5)
+#
+bs_get_utf8 Fail=f Ms=xy u u Dst=d => i_bs_get_utf8 Ms Fail Dst
+i_bs_get_utf8 S f d
+
+bs_skip_utf8 Fail=f Ms=xy u u => i_bs_skip_utf8 Ms Fail
+i_bs_skip_utf8 S f
+
+bs_get_utf16 Fail=f Ms=xy u Flags=u Dst=d => get_utf16(Fail, Ms, Flags, Dst)
+bs_skip_utf16 Fail=f Ms=xy u Flags=u => skip_utf16(Fail, Ms, Flags)
+
+i_bs_get_utf16 S f t d
+i_bs_skip_utf16 S f t
+
+bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst |
+ i_bs_validate_unicode_retract Fail Dst Ms
+bs_skip_utf32 Fail=f Ms=xy Live=u Flags=u =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags x |
+ i_bs_validate_unicode_retract Fail x Ms
+
+i_bs_validate_unicode_retract j s S
+%hot
+
+# ================================================================
+# New binary construction (OTP 25).
+# ================================================================
+
+bs_create_bin Fail=j Alloc=u Live=u Unit=u Dst=xy N=u Segments=* =>
+ create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments)
+
+i_bs_create_bin j I t d *
+
+# ================================================================
+# Old instruction for constructing binaries (up to OTP 24).
+# ================================================================
+
+%warm
+
+bs_init2 Fail Sz Words Regs Flags Dst | binary_too_big(Sz) => system_limit Fail
+
+bs_init2 Fail Sz=u Words=u==0 Regs Flags Dst => i_bs_init Sz Regs Dst
+
+bs_init2 Fail Sz=u Words Regs Flags Dst =>
+ i_bs_init_heap Sz Words Regs Dst
+
+bs_init2 Fail Sz Words=u==0 Regs Flags Dst =>
+ i_bs_init_fail Sz Fail Regs Dst
+bs_init2 Fail Sz Words Regs Flags Dst =>
+ i_bs_init_fail_heap Sz Words Fail Regs Dst
+
+i_bs_init_fail S j t S
+
+i_bs_init_fail_heap s I j t S
+
+i_bs_init W t S
+
+i_bs_init_heap W I t S
+
+
+bs_init_bits Fail Sz=o Words Regs Flags Dst => system_limit Fail
+
+bs_init_bits Fail Sz=u Words=u==0 Regs Flags Dst =>
+ i_bs_init_bits Sz Regs Dst
+bs_init_bits Fail Sz=u Words Regs Flags Dst =>
+ i_bs_init_bits_heap Sz Words Regs Dst
+
+bs_init_bits Fail Sz Words=u==0 Regs Flags Dst =>
+ i_bs_init_bits_fail Sz Fail Regs Dst
+bs_init_bits Fail Sz Words Regs Flags Dst =>
+ i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
+
+i_bs_init_bits_fail S j t S
+
+i_bs_init_bits_fail_heap s I j t S
+
+i_bs_init_bits W t S
+i_bs_init_bits_heap W I t S
+
+bs_add Fail S1=i==0 S2 Unit=u==1 D => move S2 D
+
+bs_add j s s t x
+
+bs_append Fail Size Extra Live Unit Bin Flags Dst =>
+ i_bs_append Fail Extra Live Unit Size Bin Dst
+
+bs_private_append Fail Size Unit Bin Flags Dst =>
+ i_bs_private_append Fail Unit Size Bin Dst
+
+i_bs_private_append Fail Unit Size Bin Dst=y =>
+ i_bs_private_append Fail Unit Size Bin x | move x Dst
+
+bs_init_writable
+
+i_bs_append j I t t s s S
+i_bs_private_append j t s S x
+
+#
+# Storing integers into binaries.
+#
+
+bs_put_integer Fail=j Sz=sq Unit=u Flags=u Src=s =>
+ put_integer(Fail, Sz, Unit, Flags, Src)
+
+i_new_bs_put_integer j S t s
+i_new_bs_put_integer_imm s j W t
+
+#
+# Utf8/utf16/utf32 support. (R12B-5)
+#
+
+bs_utf8_size j Src Dst=d => i_bs_utf8_size Src Dst
+bs_utf16_size j Src Dst=d => i_bs_utf16_size Src Dst
+
+bs_put_utf8 Fail u Src => i_bs_put_utf8 Fail Src
+bs_put_utf16 Fail Flags Src => put_utf16(Fail, Flags, Src)
+
+bs_put_utf32 Fail=j Flags=u Src=s =>
+ i_bs_validate_unicode Fail Src | bs_put_integer Fail i=32 u=1 Flags Src
+
+i_bs_utf8_size s x
+i_bs_utf16_size s x
+
+i_bs_put_utf8 j s
+i_bs_put_utf16 j t s
+
+i_bs_validate_unicode j s
+
+#
+# Storing floats into binaries.
+#
+
+# Will fail. No need to keep the instruction, because bs_add or
+# bs_init* would already have raised an exception.
+bs_put_float Fail Sz=q Unit Flags Val => _
+
+bs_put_float Fail=j Sz=s Unit=u Flags=u Src=s =>
+ put_float(Fail, Sz, Unit, Flags, Src)
+
+i_new_bs_put_float j S t s
+i_new_bs_put_float_imm j W t s
+
+#
+# Storing binaries into binaries.
+#
+
+bs_put_binary Fail=j Sz=s Unit=u Flags=u Src=s =>
+ put_binary(Fail, Sz, Unit, Flags, Src)
+
+i_new_bs_put_binary j s t s
+i_new_bs_put_binary_imm j W s
+i_new_bs_put_binary_all s j t
+
+#
+# Warning: The i_bs_put_string and i_new_bs_put_string instructions
+# are specially treated in the loader.
+# Don't change the instruction format unless you change the loader too.
+#
+
+bs_put_string W M
+
+#
+# New floating point instructions (R8).
+#
+
+fadd p FR1 FR2 FR3 => i_fadd FR1 FR2 FR3
+fsub p FR1 FR2 FR3 => i_fsub FR1 FR2 FR3
+fmul p FR1 FR2 FR3 => i_fmul FR1 FR2 FR3
+fdiv p FR1 FR2 FR3 => i_fdiv FR1 FR2 FR3
+fnegate p FR1 FR2 => i_fnegate FR1 FR2
+
+fmove Arg=l Dst=d => fstore Arg Dst
+fmove Arg=dq Dst=l => fload Arg Dst
+
+fstore l d
+fload Sq l
+
+fconv s l
+
+i_fadd l l l
+i_fsub l l l
+i_fmul l l l
+i_fdiv l l l
+i_fnegate l l
+
+fclearerror => _
+fcheckerror p => _
+
+%hot
+
+#
+# New apply instructions in R10B.
+#
+
+apply t
+apply_last t t
+
+#
+# Map instructions. First introduced in R17.
+#
+
+# We KNOW that in OTP 18 and higher, a put_map_assoc instruction is
+# always preceded by an is_map test. That means that put_map_assoc can
+# never fail and does not need any failure label.
+
+put_map_assoc Fail Map Dst Live Size Rest=* =>
+ i_put_map_assoc Map Dst Live Size Rest
+i_put_map_assoc/4
+
+sorted_put_map_assoc/4
+i_put_map_assoc Map Dst Live Size Rest=* | map_key_sort(Size, Rest) =>
+ sorted_put_map_assoc Map Dst Live Size Rest
+
+sorted_put_map_exact/5
+put_map_exact F Map Dst Live Size Rest=* | map_key_sort(Size, Rest) =>
+ sorted_put_map_exact F Map Dst Live Size Rest
+
+sorted_put_map_assoc Map Dst Live Size Rest=* | is_empty_map(Map) =>
+ new_map Dst Live Size Rest
+sorted_put_map_assoc Src=s Dst Live Size Rest=* =>
+ update_map_assoc Src Dst Live Size Rest
+
+sorted_put_map_exact Fail Src Dst Live Size Rest=* =>
+ update_map_exact Src Fail Dst Live Size Rest
+
+new_map Dst Live Size Rest=* | is_small_map_literal_keys(Size, Rest) =>
+ new_small_map_lit(Dst, Live, Size, Rest)
+
+new_map d t I *
+i_new_small_map_lit d t q I *
+update_map_assoc s d t I *
+update_map_exact s j d t I *
+
+is_map f s
+
+## Transform has_map_fields #{ K1 := _, K2 := _ } to has_map_elements
+
+has_map_fields Fail Src Size Rest=* =>
+ has_map_fields(Fail, Src, Size, Rest)
+
+## Transform get_map_elements(s) #{ K1 := V1, K2 := V2 }
+
+get_map_elements Fail Src Size=u==2 Rest=* =>
+ get_map_element(Fail, Src, Size, Rest)
+get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) =>
+ get_map_elements(Fail, Src, Size, Rest)
+
+i_get_map_elements f s I *
+
+i_get_map_element_hash Fail Src=c Key Hash Dst =>
+ move Src x | i_get_map_element_hash Fail x Key Hash Dst
+i_get_map_element_hash f S c I S
+
+i_get_map_element Fail Src=c Key Dst =>
+ move Src x | i_get_map_element Fail x Key Dst
+i_get_map_element f S S S
+
+#
+# Arithmetic instructions.
+#
+
+gc_bif2 Fail Live u$bif:erlang:splus/2 Src1 Src2 Dst =>
+ i_plus Fail Live Src1 Src2 Dst
+
+gc_bif1 Fail Live u$bif:erlang:sminus/1 Src Dst =>
+ i_unary_minus Fail Live Src Dst
+
+gc_bif2 Fail Live u$bif:erlang:sminus/2 Src1 Src2 Dst =>
+ i_minus Fail Live Src1 Src2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:stimes/2 S1 S2 Dst =>
+ i_times Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:div/2 S1 S2 Dst =>
+ i_m_div Fail Live S1 S2 Dst
+
+# Fused 'rem'/'div' pair.
+gc_bif2 Fail Live u$bif:erlang:rem/2 LHS1 RHS1 Remainder |
+ gc_bif2 A B u$bif:erlang:intdiv/2 LHS2 RHS2 Quotient |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Remainder) |
+ distinct(RHS1, Remainder) =>
+ i_rem_div Fail Live LHS1 RHS1 Remainder Quotient
+
+# As above but with a `line` in between
+gc_bif2 Fail Live u$bif:erlang:rem/2 LHS1 RHS1 Remainder |
+ line Loc |
+ gc_bif2 A B u$bif:erlang:intdiv/2 LHS2 RHS2 Quotient |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Remainder) |
+ distinct(RHS1, Remainder) =>
+ i_rem_div Fail Live LHS1 RHS1 Remainder Quotient
+
+# Fused 'div'/'rem' pair
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 LHS1 RHS1 Quotient |
+ gc_bif2 A B u$bif:erlang:rem/2 LHS2 RHS2 Remainder |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Quotient) |
+ distinct(RHS1, Quotient) =>
+ i_div_rem Fail Live LHS1 RHS1 Quotient Remainder
+
+# As above but with a `line` in between
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 LHS1 RHS1 Quotient |
+ line Loc |
+ gc_bif2 A B u$bif:erlang:rem/2 LHS2 RHS2 Remainder |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Quotient) |
+ distinct(RHS1, Quotient) =>
+ i_div_rem Fail Live LHS1 RHS1 Quotient Remainder
+
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 S1 S2 Dst =>
+ i_int_div Fail Live S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:rem/2 S1 S2 Dst =>
+ i_rem Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:band/2 S1 S2 Dst =>
+ i_band Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:bor/2 S1 S2 Dst =>
+ i_bor Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst =>
+ i_bxor Fail Live S1 S2 Dst
+
+gc_bif1 Fail Live u$bif:erlang:bnot/1 Src Dst =>
+ i_bnot Fail Live Src Dst
+
+gc_bif2 Fail Live u$bif:erlang:bsr/2 S1 S2 Dst =>
+ i_bsr Fail Live S1 S2 Dst
+
+gc_bif2 Fail Live u$bif:erlang:bsl/2 S1 S2 Dst =>
+ i_bsl Fail Live S1 S2 Dst
+
+i_plus j I s s d
+i_unary_minus j I s d
+i_minus j I s s d
+i_times j I s s d
+
+i_m_div j I s s d
+
+i_rem_div j I s s d d
+i_div_rem j I s s d d
+i_int_div j I s s d
+i_rem j I s s d
+
+i_band j I s s d
+i_bor j I s s d
+i_bxor j I s s d
+
+i_bnot j I s d
+
+i_bsr j I s s d
+i_bsl j I s s d
+
+#
+# Old guard BIFs that creates heap fragments are no longer allowed.
+#
+bif1 Fail u$bif:erlang:length/1 s d => too_old_compiler
+bif1 Fail u$bif:erlang:size/1 s d => too_old_compiler
+bif1 Fail u$bif:erlang:abs/1 s d => too_old_compiler
+bif1 Fail u$bif:erlang:float/1 s d => too_old_compiler
+bif1 Fail u$bif:erlang:round/1 s d => too_old_compiler
+bif1 Fail u$bif:erlang:trunc/1 s d => too_old_compiler
+
+#
+# Handle the length/1 guard BIF specially to make it trappable.
+#
+
+gc_bif1 Fail=j Live u$bif:erlang:length/1 Src Dst =>
+ i_length_setup Fail Live Src | i_length Fail Live Dst
+
+i_length_setup j t s
+i_length j t d
+
+#
+# Specialized guard BIFs.
+#
+
+gc_bif1 Fail Live Bif=u$bif:erlang:map_size/1 Src Dst=d => bif_map_size Fail Src Dst
+bif_map_size j s d
+
+#
+# Guard BIFs.
+#
+gc_bif1 Fail Live Bif Src Dst => i_bif1 Src Fail Bif Dst
+gc_bif2 Fail Live Bif S1 S2 Dst => i_bif2 S1 S2 Fail Bif Dst
+gc_bif3 Fail Live Bif S1 S2 S3 Dst => i_bif3 S1 S2 S3 Fail Bif Dst
+
+#
+# The following instruction is specially handled in beam_load.c
+# to produce a user-friendly message if an unsupported guard BIF is
+# encountered.
+#
+unsupported_guard_bif/3
+unsupported_guard_bif A B C | never() => _
+
+#
+# R13B03
+#
+on_load
+
+#
+# R14A.
+#
+# Superseded in OTP 24 by 'recv_marker_reserve' and friends.
+#
+
+recv_mark f => i_recv_mark
+i_recv_mark
+
+recv_set Fail | label Lbl | loop_rec Lf Reg =>
+ i_recv_set | label Lbl | loop_rec Lf Reg
+i_recv_set
+
+#
+# OTP 21.
+#
+
+build_stacktrace
+raw_raise
+
+#
+# Specialized move instructions. Since they don't require a second
+# instruction, we have intentionally placed them after any other
+# transformation rules that starts with a move instruction in order to
+# produce better code for the transformation engine.
+#
+
+move n D=y => init D
+
+#
+# OTP 24
+#
+
+recv_marker_reserve S
+recv_marker_bind S S
+recv_marker_clear S
+recv_marker_use S
+
+#
+# Mark all intentionally unused macros, predicates, and generators.
+#
+
+%unused pred.negation_is_small
+
+%unused gen_increment
+%unused gen.increment
+%unused gen.increment_from_minus
+%unused gen.plus_from_minus
+
+# Landing pad for fun calls/apply where we set up arguments and check errors
+i_lambda_trampoline F f W W
diff --git a/erts/emulator/beam/jit/arm/predicates.tab b/erts/emulator/beam/jit/arm/predicates.tab
new file mode 100644
index 0000000000..fc55441c28
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/predicates.tab
@@ -0,0 +1,107 @@
+// -*- c -*-
+//
+// %CopyrightBegin%
+//
+// Copyright Ericsson AB 2020-2021. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// %CopyrightEnd%
+//
+
+pred.is_mfa_bif(M, F, A) {
+ Export *e;
+
+ ASSERT(M.type == TAG_a && F.type == TAG_a && A.type == TAG_u);
+ e = erts_active_export_entry(M.val, F.val, A.val);
+
+ if (e != NULL) {
+ return e->bif_number != -1;
+ }
+
+ return 0;
+}
+
+pred.never_fails(Bif) {
+ static Eterm nofail_bifs[] =
+ {am_Neqeq,
+ am_Le,
+ am_Neq,
+ am_Eq,
+ am_Le,
+ am_Eqeq,
+ am_Gt,
+ am_Ge,
+ am_is_atom,
+ am_is_boolean,
+ am_is_binary,
+ am_is_bitstring,
+ am_is_float,
+ am_is_integer,
+ am_is_list,
+ am_is_map,
+ am_is_number,
+ am_is_pid,
+ am_is_port,
+ am_is_reference,
+ am_is_tuple,
+ };
+
+ Uint index = Bif.val;
+
+ if (Bif.type == TAG_u && index < S->beam.imports.count) {
+ BeamFile_ImportEntry *entry = &S->beam.imports.entries[index];
+ int i;
+
+ if (entry->module != am_erlang) {
+ return 0;
+ }
+
+ if (entry->function == am_is_function) {
+ /* Note that is_function/2 may fail. */
+ return entry->arity == 1;
+ }
+
+ for (i = 0; i < sizeof(nofail_bifs) / sizeof(nofail_bifs[0]); i++) {
+ if (entry->function == nofail_bifs[i]) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+pred.consecutive_words(A1, A2) {
+ return A1.type == A2.type && A1.val + 1 == A2.val;
+}
+pred.is_eq_exact_bif(Bif) {
+ Uint index = Bif.val;
+
+ if (Bif.type == TAG_u && index < S->beam.imports.count) {
+ BeamFile_ImportEntry *entry = &S->beam.imports.entries[index];
+
+ return entry->module == am_erlang && entry->function == am_Eq && entry->arity == 2;
+ }
+ return 0;
+}
+
+pred.is_ne_exact_bif(Bif) {
+ Uint index = Bif.val;
+
+ if (Bif.type == TAG_u && index < S->beam.imports.count) {
+ BeamFile_ImportEntry *entry = &S->beam.imports.entries[index];
+
+ return entry->module == am_erlang && entry->function == am_Neq && entry->arity == 2;
+ }
+ return 0;
+}
diff --git a/erts/emulator/beam/jit/arm/process_main.cpp b/erts/emulator/beam/jit/arm/process_main.cpp
new file mode 100644
index 0000000000..8b7ddfa17d
--- /dev/null
+++ b/erts/emulator/beam/jit/arm/process_main.cpp
@@ -0,0 +1,314 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "bif.h"
+#include "beam_common.h"
+#include "code_ix.h"
+#include "export.h"
+}
+
+#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
+static Process *erts_debug_schedule(ErtsSchedulerData *esdp,
+ Process *c_p,
+ int calls) {
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ c_p = erts_schedule(esdp, c_p, calls);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ return c_p;
+}
+#endif
+
+/* void process_main(ErtsSchedulerData *esdp); */
+void BeamGlobalAssembler::emit_process_main() {
+ Label context_switch_local = a.newLabel(),
+ context_switch_simplified_local = a.newLabel(),
+ do_schedule_local = a.newLabel(), schedule_next = a.newLabel();
+
+ const arm::Mem start_time_i =
+ getSchedulerRegRef(offsetof(ErtsSchedulerRegisters, start_time_i));
+ const arm::Mem start_time =
+ getSchedulerRegRef(offsetof(ErtsSchedulerRegisters, start_time));
+
+ /* Be kind to debuggers and `perf` by setting up a proper stack frame. */
+ a.stp(a64::x29, a64::x30, arm::Mem(a64::sp, -16).pre());
+
+ /* Allocate the register structure on the stack to allow computing the
+ * runtime stack address from it, greatly reducing the cost of stack
+ * swapping. */
+ a.mov(TMP1, a64::sp);
+ sub(TMP1, TMP1, sizeof(ErtsSchedulerRegisters) + ERTS_CACHE_LINE_SIZE);
+ a.and_(TMP1, TMP1, imm(~ERTS_CACHE_LINE_MASK));
+ a.mov(a64::sp, TMP1);
+ a.mov(a64::x29, a64::sp);
+
+ a.str(TMP1, arm::Mem(ARG1, offsetof(ErtsSchedulerData, registers)));
+
+ a.mov(scheduler_registers, a64::sp);
+
+ load_erl_bits_state(ARG1);
+ runtime_call<1>(erts_bits_init_state);
+
+ /* Save the initial SP of the thread so that we can verify that it
+ * doesn't grow. */
+#ifdef JIT_HARD_DEBUG
+ a.mov(TMP1, a64::sp);
+ a.str(TMP1, getInitialSPRef());
+#endif
+
+ a.str(a64::xzr, start_time_i);
+ a.str(a64::xzr, start_time);
+
+ mov_imm(c_p, 0);
+ mov_imm(FCALLS, 0);
+ mov_imm(ARG3, 0); /* Set reds_used for erts_schedule call */
+
+ a.b(schedule_next);
+
+ a.bind(do_schedule_local);
+ {
+ /* Figure out reds_used. def_arg_reg[5] = REDS_IN */
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, def_arg_reg[5])));
+ a.sub(ARG3, TMP1, FCALLS);
+ a.b(schedule_next);
+ }
+
+ /*
+ * The *next* instruction pointer is provided in ARG3, and must be preceded
+ * by an ErtsCodeMFA.
+ */
+ a.bind(context_switch_local);
+ comment("Context switch, unknown arity/MFA");
+ {
+ Sint arity_offset = offsetof(ErtsCodeMFA, arity) - sizeof(ErtsCodeMFA);
+
+ a.ldur(TMP1, arm::Mem(ARG3, arity_offset));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, arity)));
+
+ a.sub(TMP1, ARG3, imm((Uint)sizeof(ErtsCodeMFA)));
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, current)));
+
+ /* !! Fall through !! */
+ }
+
+ a.bind(context_switch_simplified_local);
+ comment("Context switch, known arity and MFA");
+ {
+ Label not_exiting = a.newLabel();
+
+#ifdef DEBUG
+ Label check_i = a.newLabel();
+ /* Check that ARG3 is set to a valid CP. */
+ a.tst(ARG3, imm(_CPMASK));
+ a.b_eq(check_i);
+ a.udf(1);
+ a.bind(check_i);
+#endif
+
+ a.str(ARG3, arm::Mem(c_p, offsetof(Process, i)));
+ a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, state.value)));
+
+ a.tst(TMP1, imm(ERTS_PSFLG_EXITING));
+ a.b_eq(not_exiting);
+ {
+ comment("Process exiting");
+
+ a.adr(TMP1, labels[process_exit]);
+ a.str(TMP1, arm::Mem(c_p, offsetof(Process, i)));
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, arity)));
+ a.str(ZERO, arm::Mem(c_p, offsetof(Process, current)));
+ a.b(do_schedule_local);
+ }
+
+ a.bind(not_exiting);
+
+ /* Figure out reds_used. def_arg_reg[5] = REDS_IN */
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, def_arg_reg[5])));
+ a.sub(FCALLS, TMP1, FCALLS);
+
+ comment("Copy out X registers");
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<2>(copy_out_registers);
+
+ /* Restore reds_used from FCALLS */
+ a.mov(ARG3, FCALLS);
+
+ /* !! Fall through !! */
+ }
+
+ a.bind(schedule_next);
+ comment("schedule_next");
+
+ {
+ Label schedule = a.newLabel(), skip_long_schedule = a.newLabel();
+
+ /* ARG3 contains reds_used at this point */
+
+ a.ldr(TMP1, start_time);
+ a.cbz(TMP1, schedule);
+ {
+ a.mov(ARG1, c_p);
+ a.ldr(ARG2, start_time);
+
+ /* Spill reds_used in start_time slot */
+ a.str(ARG3, start_time);
+
+ a.ldr(ARG3, start_time_i);
+ runtime_call<3>(check_monitor_long_schedule);
+
+ /* Restore reds_used */
+ a.ldr(ARG3, start_time);
+ }
+
+ a.bind(schedule);
+ mov_imm(ARG1, 0);
+ a.mov(ARG2, c_p);
+#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
+ runtime_call<3>(erts_debug_schedule);
+#else
+ runtime_call<3>(erts_schedule);
+#endif
+ a.mov(c_p, ARG1);
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ lea(ARG1, erts_msacc_cache);
+ runtime_call<1>(erts_msacc_update_cache);
+#endif
+
+ a.str(ZERO, start_time);
+ mov_imm(ARG1, &erts_system_monitor_long_schedule);
+ a.ldr(TMP1, arm::Mem(ARG1));
+ a.cbz(TMP1, skip_long_schedule);
+
+ {
+ /* Enable long schedule test */
+ runtime_call<0>(erts_timestamp_millis);
+ a.str(ARG1, start_time);
+ a.ldr(TMP1, arm::Mem(c_p, offsetof(Process, i)));
+ a.str(TMP1, start_time_i);
+ }
+
+ a.bind(skip_long_schedule);
+ comment("skip_long_schedule");
+
+ /* Copy arguments */
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<2>(copy_in_registers);
+
+ /* Setup reduction counting */
+ a.ldr(FCALLS, arm::Mem(c_p, offsetof(Process, fcalls)));
+ a.str(FCALLS, arm::Mem(c_p, offsetof(Process, def_arg_reg[5])));
+
+#ifdef DEBUG
+ a.str(FCALLS, a64::Mem(c_p, offsetof(Process, debug_reds_in)));
+#endif
+
+ comment("check whether save calls is on");
+ a.mov(ARG1, c_p);
+ mov_imm(ARG2, ERTS_PSD_SAVED_CALLS_BUF);
+ runtime_call<2>(erts_psd_get);
+
+ /* Read the active code index, overriding it with
+ * ERTS_SAVE_CALLS_CODE_IX when save_calls is enabled (ARG1 != 0). */
+ mov_imm(TMP1, &the_active_code_index);
+ a.ldr(TMP1.w(), arm::Mem(TMP1));
+ a.mov(TMP2, imm(ERTS_SAVE_CALLS_CODE_IX));
+ a.cmp(ARG1, ZERO);
+ a.csel(active_code_ix, TMP1, TMP2, arm::CondCode::kEQ);
+
+ /* Start executing the Erlang process. Note that reductions have
+ * already been set up above. */
+ emit_leave_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ /* Check if we are just returning from a dirty nif/bif call and if so we
+ * need to do a bit of cleaning up before continuing.
+ *
+ * This relies on `op_call_nif_WWW` / `op_call_bif_W` being encoded as
+ * UDF(opcode) followed by UDF(0), which we will never emit. */
+ a.ldr(ARG1, arm::Mem(c_p, offsetof(Process, i)));
+ a.ldr(TMP1, arm::Mem(ARG1));
+
+ ERTS_CT_ASSERT((op_call_nif_WWW & 0xFFFF0000) == 0);
+ a.cmp(TMP1, imm(op_call_nif_WWW));
+ a.b_eq(labels[dispatch_nif]);
+
+ ERTS_CT_ASSERT((op_call_bif_W & 0xFFFF0000) == 0);
+ a.cmp(TMP1, imm(op_call_bif_W));
+ a.b_eq(labels[dispatch_bif]);
+
+ a.br(ARG1);
+ }
+
+ /* Processes may jump to the exported entry points below, executing on the
+ * Erlang stack when entering. These are separate from the `_local` labels
+ * above as we don't want to worry about which stack we're on when the
+ * cases overlap. */
+
+ /* `ga->get_context_switch()`
+ *
+ * The *next* instruction pointer is provided in ARG3, and must be preceded
+ * by an ErtsCodeMFA.
+ *
+ * The X registers are expected to be in CPU registers.
+ */
+ a.bind(labels[context_switch]);
+ {
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ a.b(context_switch_local);
+ }
+
+ /* `ga->get_context_switch_simplified()`
+ *
+ * The next instruction pointer is provided in ARG3, which does not need to
+ * point past an ErtsCodeMFA as the process structure has already been
+ * updated.
+ *
+ * The X registers are expected to be in CPU registers.
+ */
+ a.bind(labels[context_switch_simplified]);
+ {
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ a.b(context_switch_simplified_local);
+ }
+
+ /* `ga->get_do_schedule()`
+ *
+ * `c_p->i` must be set prior to jumping here.
+ *
+ * The X registers are expected to be in CPU registers.
+ */
+ a.bind(labels[do_schedule]);
+ {
+ emit_enter_runtime<Update::eStack | Update::eHeap | Update::eXRegs>();
+
+ a.b(do_schedule_local);
+ }
+}
diff --git a/erts/emulator/beam/jit/asm_load.c b/erts/emulator/beam/jit/asm_load.c
index 24fae1896c..a3594a4800 100644
--- a/erts/emulator/beam/jit/asm_load.c
+++ b/erts/emulator/beam/jit/asm_load.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,15 +36,18 @@
# include <sanitizer/lsan_interface.h>
#endif
+#define INVALID_LAMBDA_INDEX -1
+
static void init_label(Label *lp);
-void beam_load_prepare_emit(LoaderState *stp) {
+int beam_load_prepare_emit(LoaderState *stp) {
BeamCodeHeader *hdr;
int i;
stp->ba = beamasm_new_assembler(stp->module,
stp->beam.code.label_count,
- stp->beam.code.function_count);
+ stp->beam.code.function_count,
+ &stp->beam);
/* Initialize code header */
stp->codev_size = stp->beam.code.function_count + 1;
@@ -64,6 +67,7 @@ void beam_load_prepare_emit(LoaderState *stp) {
hdr->compile_size_on_heap = 0;
hdr->literal_area = NULL;
hdr->md5_ptr = NULL;
+ hdr->are_nifs = NULL;
stp->load_hdr = hdr;
@@ -73,6 +77,23 @@ void beam_load_prepare_emit(LoaderState *stp) {
init_label(&stp->labels[i]);
}
+ for (i = 0; i < stp->beam.lambdas.count; i++) {
+ BeamFile_LambdaEntry *lambda = &stp->beam.lambdas.entries[i];
+
+ if (stp->labels[lambda->label].lambda_index == INVALID_LAMBDA_INDEX) {
+ stp->labels[lambda->label].lambda_index = i;
+ } else {
+ beam_load_report_error(__LINE__,
+ stp,
+ "lambda already defined for label %i. To "
+ "fix this, please recompile this module "
+ "with an OTP " ERLANG_OTP_RELEASE
+ " compiler.",
+ lambda->label);
+ return 0;
+ }
+ }
+
stp->bif_imports =
erts_alloc(ERTS_ALC_T_PREPARED_CODE,
stp->beam.imports.count * sizeof(BifEntry **));
@@ -111,10 +132,13 @@ void beam_load_prepare_emit(LoaderState *stp) {
stp->beam.code.function_count *
sizeof(unsigned int));
}
+
+ return 1;
}
static void init_label(Label *lp) {
sys_memset(lp, 0, sizeof(*lp));
+ lp->lambda_index = INVALID_LAMBDA_INDEX;
}
void beam_load_prepared_free(Binary *magic) {
@@ -132,11 +156,6 @@ int beam_load_prepared_dtor(Binary *magic) {
beamfile_free(&stp->beam);
beamopallocator_dtor(&stp->op_allocator);
- if (stp->bin) {
- driver_free_binary(stp->bin);
- stp->bin = NULL;
- }
-
if (stp->load_hdr) {
BeamCodeHeader *hdr = stp->load_hdr;
@@ -144,6 +163,10 @@ int beam_load_prepared_dtor(Binary *magic) {
erts_release_literal_area(hdr->literal_area);
hdr->literal_area = NULL;
}
+ if (hdr->are_nifs) {
+ erts_free(ERTS_ALC_T_PREPARED_CODE, hdr->are_nifs);
+ hdr->are_nifs = NULL;
+ }
erts_free(ERTS_ALC_T_PREPARED_CODE, hdr);
stp->load_hdr = NULL;
@@ -252,7 +275,7 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
switch (*sign) {
case 'n': /* Nil */
ASSERT(tag != TAG_r);
- curr->type = TAG_i;
+ curr->type = 'I';
curr->val = NIL;
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
break;
@@ -262,19 +285,20 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
break;
case 'a': /* Tagged atom */
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
- curr->type = TAG_i;
+ curr->type = 'I';
break;
case 'c': /* Tagged constant */
switch (tag) {
case TAG_i:
curr->val = make_small((Uint)curr->val);
+ curr->type = 'I';
break;
case TAG_a:
- curr->type = TAG_i;
+ curr->type = 'I';
break;
case TAG_n:
curr->val = NIL;
- curr->type = TAG_i;
+ curr->type = 'I';
break;
case TAG_q:
break;
@@ -294,12 +318,13 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
break;
case TAG_i:
curr->val = (BeamInstr)make_small(curr->val);
+ curr->type = 'I';
break;
case TAG_a:
- curr->type = TAG_i;
+ curr->type = 'I';
break;
case TAG_n:
- curr->type = TAG_i;
+ curr->type = 'I';
curr->val = NIL;
break;
case TAG_q: {
@@ -354,7 +379,8 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
break;
case 'A': /* Arity value. */
BeamLoadVerifyTag(stp, tag, TAG_u);
- curr->val = make_arityval(curr->val);
+ curr->val = curr->val == 0 ? make_arityval_zero()
+ : make_arityval(curr->val);
break;
case 'f': /* Destination label */
BeamLoadVerifyTag(stp, tag_to_letter[tag], *sign);
@@ -394,13 +420,14 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
stp->last_label);
}
stp->labels[stp->last_label].value = 1;
+ curr->type = TAG_f;
break;
case 'e': /* Export entry */
BeamLoadVerifyTag(stp, tag, TAG_u);
if (curr->val >= stp->beam.imports.count) {
BeamLoadError1(stp, "invalid import table index %d", curr->val);
}
- curr->type = TAG_r;
+ curr->type = 'E';
break;
case 'b': {
int i = tmp_op->a[arg].val;
@@ -426,10 +453,26 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
break;
case 'F': /* Fun entry */
BeamLoadVerifyTag(stp, tag, TAG_u);
+ curr->type = 'F';
+ break;
+ case 'H': /* Exception handler */
+ BeamLoadVerifyTag(stp, tag, TAG_f);
+ curr->type = 'H';
+ break;
+ case 'M':
+ curr->type = 'M';
+ break;
+ case 'i':
+ curr->type = 'I';
break;
default:
BeamLoadError1(stp, "bad argument tag: %d", *sign);
}
+
+ /* These types must have been translated to 'I' */
+ ASSERT(curr->type != TAG_i && curr->type != TAG_n &&
+ curr->type != TAG_a && curr->type != TAG_v);
+
sign++;
arg++;
}
@@ -437,7 +480,7 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
/*
* Verify and massage any list arguments according to the primitive tags.
*
- * TAG_i will denote a tagged immediate value (NIL, small integer,
+ * 'I' will denote a tagged immediate value (NIL, small integer,
* atom, or tuple arity). TAG_n, TAG_a, and TAG_v will no longer be used.
*/
for (; arg < tmp_op->arity; arg++) {
@@ -446,14 +489,15 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
switch (tmp_op->a[arg].type) {
case TAG_i:
curr->val = make_small(tmp_op->a[arg].val);
+ curr->type = 'I';
break;
case TAG_n:
curr->val = NIL;
- curr->type = TAG_i;
+ curr->type = 'I';
break;
case TAG_a:
case TAG_v:
- curr->type = TAG_i;
+ curr->type = 'I';
break;
case TAG_u:
case TAG_f:
@@ -497,6 +541,17 @@ int beam_load_emit_op(LoaderState *stp, BeamOp *tmp_op) {
}
break;
+ case op_nif_start:
+ if (!stp->load_hdr->are_nifs) {
+ int bytes = stp->beam.code.function_count * sizeof(byte);
+ stp->load_hdr->are_nifs =
+ erts_alloc(ERTS_ALC_T_PREPARED_CODE, bytes);
+ sys_memzero(stp->load_hdr->are_nifs, bytes);
+ }
+ ASSERT(stp->function_number > 0);
+ ASSERT(stp->function_number <= stp->beam.code.function_count);
+ stp->load_hdr->are_nifs[stp->function_number - 1] = 1;
+ break;
}
/* Generate assembly code for the specific instruction. */
@@ -567,6 +622,7 @@ static const BeamCodeLineTab *finish_line_table(LoaderState *stp,
const void **line_items_ro;
void **line_items_rw;
+ const unsigned int num_names = stp->beam.lines.name_count;
const Eterm *fname_base_ro;
Eterm *fname_base_rw;
@@ -611,10 +667,9 @@ static const BeamCodeLineTab *finish_line_table(LoaderState *stp,
line_items_rw[i] = (void *)&module_base[module_size];
- if (stp->beam.lines.name_count) {
- sys_memcpy(fname_base_rw,
- stp->beam.lines.names,
- stp->beam.lines.name_count * sizeof(Eterm));
+ for (i = 0; i < num_names; i++) {
+ fname_base_rw[i] =
+ beamfile_get_literal(&stp->beam, stp->beam.lines.names[i]);
}
if (stp->beam.lines.location_size == sizeof(Uint16)) {
@@ -713,15 +768,6 @@ int beam_load_finish_emit(LoaderState *stp) {
stp->on_load = beamasm_get_on_load(stp->ba);
- /* If there is line information, place it here. This must be done after
- * code generation to make sure the addresses are correct.
- *
- * Ideally we'd want this to be embedded in the module itself just like the
- * string table is and use offsets rather than absolute addresses, but this
- * will do for now. */
-
- code_hdr_rw->line_table = finish_line_table(stp, module_base, module_size);
-
/*
* Place the literals in their own allocated heap (for fast range check)
* and fix up all instructions that refer to it.
@@ -765,6 +811,10 @@ int beam_load_finish_emit(LoaderState *stp) {
(stp->load_hdr)->literal_area = literal_area;
}
+ /* Line information must be added after moving literals, since source file
+ * names are literal lists. */
+ code_hdr_rw->line_table = finish_line_table(stp, module_base, module_size);
+
if (stp->beam.attributes.size) {
const byte *attr = beamasm_get_rodata(stp->ba, "attr");
@@ -864,7 +914,7 @@ void beam_load_finalize_code(LoaderState *stp,
* code callable. */
ep->trampoline.not_loaded.deferred = (BeamInstr)address;
} else {
- ep->addresses[staging_ix] = address;
+ ep->dispatch.addresses[staging_ix] = address;
}
}
@@ -905,7 +955,7 @@ void beam_load_finalize_code(LoaderState *stp,
erts_refc_dectest(&fun_entry->refc, 1);
}
- fun_entry->address = beamasm_get_code(stp->ba, lambda->label);
+ erts_set_fun_code(fun_entry, beamasm_get_lambda(stp->ba, i));
beamasm_patch_lambda(stp->ba,
stp->native_module_rw,
@@ -914,8 +964,14 @@ void beam_load_finalize_code(LoaderState *stp,
}
}
+ /* Register debug / profiling info with external tools. */
+ beamasm_register_metadata(stp->ba, stp->code_hdr);
+
+ beamasm_flush_icache(inst_p->code_hdr, inst_p->code_length);
+
/* Prevent literals and code from being freed. */
(stp->load_hdr)->literal_area = NULL;
+ stp->load_hdr->are_nifs = NULL;
stp->native_module_exec = NULL;
stp->native_module_rw = NULL;
stp->code_hdr = NULL;
diff --git a/erts/emulator/beam/jit/beam_asm.h b/erts/emulator/beam/jit/beam_asm.h
index 4a61c87fe0..1a4dff270a 100644
--- a/erts/emulator/beam/jit/beam_asm.h
+++ b/erts/emulator/beam/jit/beam_asm.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,8 @@
* %CopyrightEnd%
*/
-#ifdef BEAMASM
+#if defined(BEAMASM) && !defined(__BEAM_ASM_H__)
+# define __BEAM_ASM_H__
# include "sys.h"
# include "bif.h"
@@ -27,27 +28,42 @@
# include "beam_file.h"
# include "beam_common.h"
+# if defined(__APPLE__)
+# include <libkern/OSCacheControl.h>
+# endif
+
/* Global configuration variables */
# ifdef HAVE_LINUX_PERF_SUPPORT
-# define BEAMASM_PERF_DUMP (1 << 0)
-# define BEAMASM_PERF_MAP (1 << 1)
-extern int erts_jit_perf_support;
+enum beamasm_perf_flags {
+ BEAMASM_PERF_DUMP = (1 << 0),
+ BEAMASM_PERF_MAP = (1 << 1),
+ BEAMASM_PERF_FP = (1 << 2),
+
+ BEAMASM_PERF_ENABLED =
+ BEAMASM_PERF_DUMP | BEAMASM_PERF_MAP | BEAMASM_PERF_FP,
+ BEAMASM_PERF_DISABLED = 0,
+};
+extern enum beamasm_perf_flags erts_jit_perf_support;
# endif
void beamasm_init(void);
-void beamasm_init_perf(void);
-void *beamasm_new_assembler(Eterm mod, int num_labels, int num_functions);
+void *beamasm_new_assembler(Eterm mod,
+ int num_labels,
+ int num_functions,
+ BeamFile *beam);
void beamasm_codegen(void *ba,
const void **native_module_exec,
void **native_module_rw,
const BeamCodeHeader *in_hdr,
const BeamCodeHeader **out_exec_hdr,
BeamCodeHeader **out_rw_hdr);
+void beamasm_register_metadata(void *ba, const BeamCodeHeader *hdr);
void beamasm_purge_module(const void *native_module_exec,
void *native_module_rw);
void beamasm_delete_assembler(void *ba);
int beamasm_emit(void *ba, unsigned specific_op, BeamOp *op);
ErtsCodePtr beamasm_get_code(void *ba, int label);
+ErtsCodePtr beamasm_get_lambda(void *ba, int index);
const byte *beamasm_get_rodata(void *ba, char *label);
void beamasm_embed_rodata(void *ba,
const char *labelName,
@@ -61,10 +77,6 @@ void beamasm_patch_literal(void *ba, char *rw_base, int index, Eterm lit);
void beamasm_patch_lambda(void *ba, char *rw_base, int index, BeamInstr fe);
void beamasm_patch_strings(void *ba, char *rw_base, const byte *strtab);
-void beamasm_emit_call_bif(const ErtsCodeInfo *info,
- Eterm (*bif)(BIF_ALIST),
- char *buff,
- unsigned buff_len);
void beamasm_emit_call_nif(const ErtsCodeInfo *info,
void *normal_fptr,
void *lib,
@@ -80,47 +92,55 @@ char *beamasm_get_base(void *instance);
/* Return current instruction offset, for line information. */
size_t beamasm_get_offset(void *ba);
-// Number of bytes emitted at first label in order to support trace and nif load
-# define BEAM_ASM_FUNC_PROLOGUE_SIZE 8
+void beamasm_flush_icache(const void *address, size_t size);
+
+/* Number of bytes emitted at first label in order to support trace and nif
+ * load. */
+# if defined(__aarch64__)
+# define BEAM_ASM_FUNC_PROLOGUE_SIZE 12
+# else
+# define BEAM_ASM_FUNC_PROLOGUE_SIZE 8
+# endif
+
+/* Size (in bytes) of a ErtsNativeFunc/call_nif prologue. */
+# if defined(__aarch64__)
+# define BEAM_ASM_NFUNC_SIZE (BEAM_ASM_FUNC_PROLOGUE_SIZE + 4)
+# else
+# define BEAM_ASM_NFUNC_SIZE (BEAM_ASM_FUNC_PROLOGUE_SIZE + 8)
+# endif
/*
- * The code below is used to deal with intercepting the execution of
- * a process at the start of a function. It is used by tracing and nif loading.
+ * The code below is used to deal with intercepting the execution of a process
+ * at the start of a function. It is used by tracing and nif loading.
*
* In the interpreter this is solved by simply writing a new instruction as
* the first instruction in a function. In asm mode it is not as simple as
* our code changes have to be to executing native code.
*
- * The solution is as follows:
+ * On x86, the solution is as follows:
*
* When emitting a function the first word (or function prologue) is:
- * 0x0: jmp 6
- * 0x2: ERTS_ASM_BP_FLAG_NONE
- * 0x3: relative near call
- * 0x4: &genericBPTramp
+ * 0x0: short jmp 6
+ * 0x2: nop
+ * 0x3: relative near call to shared breakpoint fragment
* 0x8: actual code for function
*
- * When code starts to execute it will simply see the "jmp 6" instruction
- * which skips the prologue and starts to execute the code directly.
+ * When code starts to execute it will simply see the `short jmp 6`
+ * instruction which skips the prologue and starts to execute the code
+ * directly.
*
- * When we want to enable a certain breakpoint we set the jmp target to
- * be 1 (which means it will land on the call instruction) and will call
- * genericBPTramp. genericBPTramp is a label at the top of each module
- * that contains trampolines for all flag combinations.
+ * When we want to enable a certain breakpoint we set the jmp target to be 1,
+ * which means it will land on the call to the shared breakpoint fragment.
+ * This fragment checks the current `breakpoint_flag` stored in the
+ * ErtsCodeInfo of this function, and then calls `erts_call_nif_early` and
+ * `erts_generic_breakpoint` accordingly.
*
- * genericBPTramp:
- * 0x0: ret
- * 0x10: jmp call_nif_early
- * 0x20: call generic_bp_local
- * 0x30: call generic_bp_local
- * 0x35: jmp call_nif_early
+ * Note that the update of the branch and `breakpoint_flag` does not need to
+ * be atomic: it's fine if a process only sees one of these being updated, as
+ * the code that sets breakpoints/loads NIFs doesn't rely on the trampoline
+ * being active until thread progress has been made.
*
- * Note that each target is 16 byte aligned. This is because the call target
- * in the function prologue is updated to target the correct place when a flag
- * is updated. So if CALL_NIF_EARLY is set, then it is updated to be
- * genericBPTramp + 0x10. If BP is set, it is updated to genericBPTramp + 0x20
- * and the combination makes it be genericBPTramp + 0x30.
- */
+ * The solution for AArch64 is similar. */
enum erts_asm_bp_flag {
ERTS_ASM_BP_FLAG_NONE = 0,
@@ -130,39 +150,81 @@ enum erts_asm_bp_flag {
ERTS_ASM_BP_FLAG_CALL_NIF_EARLY | ERTS_ASM_BP_FLAG_BP
};
-static inline void erts_asm_bp_set_flag(ErtsCodeInfo *ci,
- enum erts_asm_bp_flag flag) {
- BeamInstr volatile *code_ptr = (BeamInstr *)erts_codeinfo_to_code(ci);
- BeamInstr code = *code_ptr;
- byte *codebytes = (byte *)&code;
- Uint32 *code32 = (Uint32 *)(codebytes + 4);
- /* 0xEB = relative jmp, 0xE8 = relative call */
- ASSERT(codebytes[0] == 0xEB && codebytes[3] == 0xE8);
- codebytes[1] = 1;
- codebytes[2] |= flag;
- *code32 += flag * 16;
- code_ptr[0] = code;
+static inline enum erts_asm_bp_flag erts_asm_bp_get_flags(
+ const ErtsCodeInfo *ci_exec) {
+ return (enum erts_asm_bp_flag)ci_exec->u.metadata.breakpoint_flag;
}
-static inline enum erts_asm_bp_flag erts_asm_bp_get_flags(ErtsCodeInfo *ci) {
- byte *codebytes = (byte *)erts_codeinfo_to_code(ci);
- return (enum erts_asm_bp_flag)codebytes[2];
+static inline void erts_asm_bp_set_flag(ErtsCodeInfo *ci_rw,
+ const ErtsCodeInfo *ci_exec,
+ enum erts_asm_bp_flag flag) {
+ ASSERT(flag != ERTS_ASM_BP_FLAG_NONE);
+
+ if (ci_rw->u.metadata.breakpoint_flag == ERTS_ASM_BP_FLAG_NONE) {
+# if defined(__aarch64__)
+ const Uint32 *exec_code = (Uint32 *)erts_codeinfo_to_code(ci_exec);
+ Uint32 volatile *rw_code = (Uint32 *)erts_codeinfo_to_code(ci_rw);
+
+ /* B .next, .enabled: BL breakpoint_handler, .next: */
+ ASSERT(rw_code[1] == 0x14000002);
+
+ /* Reroute the initial jump instruction to `.enabled`. */
+ rw_code[1] = 0x14000001;
+
+ beamasm_flush_icache(&exec_code[1], sizeof(Uint32));
+# else /* x86_64 */
+ byte volatile *rw_code = (byte *)erts_codeinfo_to_code(ci_rw);
+
+ /* SHORT JMP .next, NOP, .enabled: CALL breakpoint_handler, .next: */
+ ASSERT(rw_code[0] == 0xEB && rw_code[1] == 0x06 && rw_code[2] == 0x90 &&
+ rw_code[3] == 0xE8);
+
+ /* Reroute the initial jump instruction to `.enabled`. */
+ rw_code[1] = 1;
+
+ (void)ci_exec;
+# endif
+ }
+
+ ci_rw->u.metadata.breakpoint_flag |= flag;
}
-static inline void erts_asm_bp_unset_flag(ErtsCodeInfo *ci,
+static inline void erts_asm_bp_unset_flag(ErtsCodeInfo *ci_rw,
+ const ErtsCodeInfo *ci_exec,
enum erts_asm_bp_flag flag) {
- BeamInstr volatile *code_ptr = (BeamInstr *)erts_codeinfo_to_code(ci);
- BeamInstr code = *code_ptr;
- byte *codebytes = (byte *)&code;
- Uint32 *code32 = (Uint32 *)(codebytes + 4);
- /* 0xEB = relative jmp, 0xE8 = relative call */
- ASSERT(codebytes[0] == 0xEB && codebytes[3] == 0xE8);
- codebytes[2] &= ~flag;
- *code32 -= flag * 16;
- if (codebytes[2] == ERTS_ASM_BP_FLAG_NONE) {
- codebytes[1] = 6;
+ ASSERT(flag != ERTS_ASM_BP_FLAG_NONE);
+
+ ci_rw->u.metadata.breakpoint_flag &= ~flag;
+
+ if (ci_rw->u.metadata.breakpoint_flag == ERTS_ASM_BP_FLAG_NONE) {
+ /* We've removed the last flag, route the branch instruction back
+ * past the prologue. */
+
+# if defined(__aarch64__)
+ const Uint32 *exec_code = (Uint32 *)erts_codeinfo_to_code(ci_exec);
+ Uint32 volatile *rw_code = (Uint32 *)erts_codeinfo_to_code(ci_rw);
+
+ /* B .enabled, .enabled: BL breakpoint_handler, .next: */
+ ASSERT(rw_code[1] == 0x14000001);
+
+ /* Reroute the initial jump instruction back to `.next`. */
+ ERTS_CT_ASSERT(BEAM_ASM_FUNC_PROLOGUE_SIZE == sizeof(Uint32[3]));
+ rw_code[1] = 0x14000002;
+
+ beamasm_flush_icache(&exec_code[1], sizeof(Uint32));
+# else /* x86_64 */
+ byte volatile *rw_code = (byte *)erts_codeinfo_to_code(ci_rw);
+
+ /* SHORT JMP .enabled, NOP, .enabled: CALL breakpoint_handler, .next: */
+ ASSERT(rw_code[0] == 0xEB && rw_code[1] == 0x01 && rw_code[2] == 0x90 &&
+ rw_code[3] == 0xE8);
+
+ /* Reroute the initial jump instruction back to `.next`. */
+ rw_code[1] = BEAM_ASM_FUNC_PROLOGUE_SIZE - 2;
+
+ (void)ci_exec;
+# endif
}
- code_ptr[0] = code;
}
#endif
diff --git a/erts/emulator/beam/jit/beam_jit_args.hpp b/erts/emulator/beam/jit/beam_jit_args.hpp
new file mode 100644
index 0000000000..8e1e0359ee
--- /dev/null
+++ b/erts/emulator/beam/jit/beam_jit_args.hpp
@@ -0,0 +1,380 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef __BEAM_JIT_ARGS_HPP__
+#define __BEAM_JIT_ARGS_HPP__
+
+struct ArgVal : public BeamOpArg {
+ enum TYPE : UWord {
+ Word = TAG_u,
+ XReg = TAG_x,
+ YReg = TAG_y,
+ FReg = TAG_l,
+ Label = TAG_f,
+ Literal = TAG_q,
+
+ BytePtr = 'M',
+ Catch = 'H',
+ Export = 'E',
+ FunEntry = 'F',
+ Immediate = 'I'
+ };
+
+ constexpr ArgVal(UWord t, UWord value) : BeamOpArg{t, value} {
+ ASSERT(t == TYPE::Word || t == TYPE::XReg || t == TYPE::YReg ||
+ t == TYPE::FReg || t == TYPE::Label || t == TYPE::Literal ||
+ t == TYPE::BytePtr || t == TYPE::Catch || t == TYPE::Export ||
+ t == TYPE::FunEntry || t == TYPE::Immediate);
+ }
+
+ constexpr enum TYPE getType() const {
+ return (enum TYPE)type;
+ }
+
+ /* */
+
+ constexpr bool isAtom() const {
+ return isImmed() && is_atom(val);
+ }
+
+ constexpr bool isBytePtr() const {
+ return getType() == TYPE::BytePtr;
+ }
+
+ constexpr bool isCatch() const {
+ return getType() == TYPE::Catch;
+ }
+
+ constexpr bool isConstant() const {
+ return isImmed() || isLiteral();
+ }
+
+ constexpr bool isExport() const {
+ return getType() == TYPE::Export;
+ }
+
+ constexpr bool isImmed() const {
+ return getType() == TYPE::Immediate;
+ }
+
+ constexpr bool isLabel() const {
+ return getType() == TYPE::Label;
+ }
+
+ constexpr bool isLambda() const {
+ return getType() == TYPE::FunEntry;
+ }
+
+ constexpr bool isLiteral() const {
+ return getType() == TYPE::Literal;
+ }
+
+ constexpr bool isNil() const {
+ return isImmed() && val == NIL;
+ }
+
+ constexpr bool isSmall() const {
+ return isImmed() && is_small(val);
+ }
+
+ constexpr bool isSource() const {
+ return isConstant() || isRegister();
+ }
+
+ constexpr bool isRegister() const {
+ return isXRegister() || isYRegister() || isFRegister();
+ }
+
+ constexpr bool isXRegister() const {
+ return getType() == TYPE::XReg;
+ }
+
+ constexpr bool isYRegister() const {
+ return getType() == TYPE::YReg;
+ }
+
+ constexpr bool isFRegister() const {
+ return getType() == TYPE::FReg;
+ }
+
+ constexpr bool isWord() const {
+ return getType() == TYPE::Word;
+ }
+
+ struct Hash {
+ constexpr size_t operator()(const ArgVal &key) const {
+ return ((size_t)key.getType() << 48) ^ (size_t)key.val;
+ }
+ };
+
+ constexpr bool operator==(const ArgVal &other) const {
+ return getType() == other.getType() && val == other.val;
+ }
+
+ constexpr bool operator!=(const ArgVal &other) const {
+ return !(*this == other);
+ }
+
+ enum Relation { none, consecutive, reverse_consecutive };
+
+ static Relation memory_relation(const ArgVal &lhs, const ArgVal &rhs) {
+ if (lhs.isRegister() && lhs.getType() == rhs.getType()) {
+ if ((lhs.val & REG_MASK) + 1 == (rhs.val & REG_MASK)) {
+ return consecutive;
+ } else if ((lhs.val & REG_MASK) == (rhs.val & REG_MASK) + 1) {
+ return reverse_consecutive;
+ }
+ }
+
+ return none;
+ };
+
+ template<typename T>
+ constexpr T as() const {
+ return static_cast<T>(*this);
+ }
+};
+
+struct ArgBytePtr : public ArgVal {
+ template<typename T>
+ constexpr ArgBytePtr(const T &other) : ArgVal(other) {
+ ASSERT(isBytePtr());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgCatch : public ArgVal {
+ template<typename T>
+ constexpr ArgCatch(const T &other) : ArgVal(other) {
+ ASSERT(isCatch());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgExport : public ArgVal {
+ template<typename T>
+ constexpr ArgExport(const T &other) : ArgVal(other) {
+ ASSERT(isExport());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgLabel : public ArgVal {
+ template<typename T>
+ constexpr ArgLabel(const T &other) : ArgVal(other) {
+ ASSERT(isLabel());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgLambda : public ArgVal {
+ template<typename T>
+ constexpr ArgLambda(const T &other) : ArgVal(other) {
+ ASSERT(isLambda());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgWord : public ArgVal {
+ /* Allows explicit construction from any integral type. */
+ template<typename T,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+ constexpr explicit ArgWord(T value) : ArgVal(ArgVal::Word, value) {
+ }
+
+ template<typename T,
+ std::enable_if_t<!std::is_integral<T>::value, bool> = true>
+ constexpr ArgWord(const T &other) : ArgVal(other) {
+ ASSERT(isWord());
+ }
+
+ template<typename T>
+ constexpr ArgWord operator+(T value) const {
+ return ArgWord(val + value);
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgSource : public ArgVal {
+ template<typename T>
+ constexpr ArgSource(const T &other) : ArgVal(other) {
+ ASSERT(isSource());
+ }
+};
+
+struct ArgRegister : public ArgSource {
+ template<typename T>
+ constexpr ArgRegister(const T &other) : ArgSource(other) {
+ ASSERT(isRegister());
+ }
+
+ constexpr int typeIndex() const {
+ return (int)(val >> 10);
+ }
+};
+
+struct ArgXRegister : public ArgRegister {
+ /* Allows explicit construction from any integral type. */
+ template<typename T,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+ constexpr explicit ArgXRegister(T reg)
+ : ArgRegister(ArgVal(ArgVal::XReg, reg)) {
+ }
+
+ template<typename T,
+ std::enable_if_t<!std::is_integral<T>::value, bool> = true>
+ constexpr ArgXRegister(const T &other) : ArgRegister(other) {
+ ASSERT(isXRegister());
+ }
+
+ constexpr auto get() const {
+ return val & REG_MASK;
+ }
+};
+
+struct ArgYRegister : public ArgRegister {
+ /* Allows explicit construction from any integral type. */
+ template<typename T,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+ constexpr explicit ArgYRegister(T reg)
+ : ArgRegister(ArgVal(ArgVal::YReg, reg)) {
+ }
+
+ template<typename T,
+ std::enable_if_t<!std::is_integral<T>::value, bool> = true>
+ constexpr ArgYRegister(const T &other) : ArgRegister(other) {
+ ASSERT(isYRegister());
+ }
+
+ constexpr auto get() const {
+ return val & REG_MASK;
+ }
+};
+
+struct ArgFRegister : public ArgRegister {
+ template<typename T>
+ constexpr ArgFRegister(const T &other) : ArgRegister(other) {
+ ASSERT(isFRegister());
+ }
+
+ constexpr auto get() const {
+ return val & REG_MASK;
+ }
+};
+
+struct ArgConstant : public ArgSource {
+ template<typename T>
+ constexpr ArgConstant(const T &other) : ArgSource(other) {
+ ASSERT(isConstant());
+ }
+};
+
+struct ArgImmed : public ArgConstant {
+ constexpr explicit ArgImmed(Eterm term)
+ : ArgConstant(ArgVal(ArgVal::Immediate, term)) {
+ ASSERT(isImmed());
+ }
+
+ template<typename T>
+ constexpr ArgImmed(const T &other) : ArgConstant(other) {
+ ASSERT(isImmed());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgLiteral : public ArgConstant {
+ template<typename T>
+ constexpr ArgLiteral(const T &other) : ArgConstant(other) {
+ ASSERT(isLiteral());
+ }
+
+ constexpr auto get() const {
+ return val;
+ }
+};
+
+struct ArgAtom : public ArgImmed {
+ template<typename T>
+ constexpr ArgAtom(const T &other) : ArgImmed(other) {
+ ASSERT(isAtom());
+ }
+
+ constexpr Eterm get() const {
+ return val;
+ }
+};
+
+struct ArgNil : public ArgImmed {
+ constexpr explicit ArgNil() : ArgImmed(ArgVal(ArgVal::Immediate, NIL)) {
+ }
+
+ template<typename T>
+ constexpr ArgNil(const T &other) : ArgImmed(other) {
+ ASSERT(isNil());
+ }
+
+ constexpr Eterm get() const {
+ return val;
+ }
+};
+
+struct ArgSmall : public ArgImmed {
+ template<typename T>
+ constexpr ArgSmall(const T &other) : ArgImmed(other) {
+ ASSERT(isSmall());
+ }
+
+ constexpr Sint getSigned() const {
+ /* `signed_val` is not constexpr in debug builds, so we'll do it
+ * manually as we already know for certain that this is a small. */
+ return ((Sint)val) >> _TAG_IMMED1_SIZE;
+ }
+
+ constexpr Uint getUnsigned() const {
+ return ((Uint)val) >> _TAG_IMMED1_SIZE;
+ }
+
+ constexpr Eterm get() const {
+ return val;
+ }
+};
+
+#endif
diff --git a/erts/emulator/beam/jit/beam_jit_common.c b/erts/emulator/beam/jit/beam_jit_common.c
deleted file mode 100644
index 98b27e16f4..0000000000
--- a/erts/emulator/beam/jit/beam_jit_common.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2021-2022. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
-#include "bif.h"
-#include "code_ix.h"
-#include "erl_proc_sig_queue.h"
-#include "erl_binary.h"
-#include "erl_bits.h"
-#include "erl_map.h"
-#include "beam_common.h"
-#ifdef USE_VM_PROBES
-# include "dtrace-wrapper.h"
-#endif
-
-#include "beam_jit_common.h"
-
-#if defined(DEBUG) && defined(JIT_HARD_DEBUG)
-void beam_jit_validate_term(Eterm term) {
- if (is_boxed(term)) {
- Eterm header = *boxed_val(term);
-
- if (header_is_bin_matchstate(header)) {
- return;
- }
- }
-
- size_object_x(term, NULL);
-}
-#endif
-
-Eterm beam_jit_call_bif(Process *c_p,
- Eterm *reg,
- ErtsCodePtr I,
- ErtsBifFunc vbf,
- Uint arity) {
- ErlHeapFragment *live_hf_end;
- Eterm result;
-
- ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
- {
- live_hf_end = c_p->mbuf;
-
- ERTS_CHK_MBUF_SZ(c_p);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- result = vbf(c_p, reg, I);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
- ERTS_CHK_MBUF_SZ(c_p);
-
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- ERTS_HOLE_CHECK(c_p);
- }
- PROCESS_MAIN_CHK_LOCKS(c_p);
- ERTS_REQ_PROC_MAIN_LOCK(c_p);
-
- if (ERTS_IS_GC_AFTER_BIF_DESIRED(c_p)) {
- result = erts_gc_after_bif_call_lhf(c_p,
- live_hf_end,
- result,
- reg,
- arity);
- }
-
- return result;
-}
-
-Eterm beam_jit_call_nif(Process *c_p,
- ErtsCodePtr I,
- Eterm *reg,
- BeamJitNifF *fp,
- struct erl_module_nif *NifMod) {
- Eterm nif_bif_result;
- Eterm bif_nif_arity;
- ErlHeapFragment *live_hf_end;
- const ErtsCodeMFA *codemfa;
-
- codemfa = erts_code_to_codemfa(I);
-
- c_p->current = codemfa; /* current and vbf set to please handle_error */
-
- bif_nif_arity = codemfa->arity;
- ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
-
- {
- struct enif_environment_t env;
- ASSERT(c_p->scheduler_data);
- live_hf_end = c_p->mbuf;
- ERTS_CHK_MBUF_SZ(c_p);
- erts_pre_nif(&env, c_p, NifMod, NULL);
-
- ASSERT((c_p->scheduler_data)->current_nif == NULL);
- (c_p->scheduler_data)->current_nif = &env;
-
- nif_bif_result = (*fp)(&env, bif_nif_arity, reg);
- if (env.exception_thrown)
- nif_bif_result = THE_NON_VALUE;
-
- ASSERT((c_p->scheduler_data)->current_nif == &env);
- (c_p->scheduler_data)->current_nif = NULL;
-
- erts_post_nif(&env);
- ERTS_CHK_MBUF_SZ(c_p);
-
- PROCESS_MAIN_CHK_LOCKS(c_p);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- ASSERT(!env.exiting);
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- }
- ERTS_REQ_PROC_MAIN_LOCK(c_p);
- ERTS_HOLE_CHECK(c_p);
-
- if (ERTS_IS_GC_AFTER_BIF_DESIRED(c_p)) {
- nif_bif_result = erts_gc_after_bif_call_lhf(c_p,
- live_hf_end,
- nif_bif_result,
- reg,
- bif_nif_arity);
- }
-
- return nif_bif_result;
-}
-
-enum beam_jit_nif_load_ret beam_jit_load_nif(Process *c_p,
- ErtsCodePtr I,
- Eterm *reg) {
- if (erts_try_seize_code_write_permission(c_p)) {
- Eterm result;
-
- PROCESS_MAIN_CHK_LOCKS((c_p));
- ERTS_UNREQ_PROC_MAIN_LOCK((c_p));
- result = erts_load_nif(c_p, I, reg[0], reg[1]);
- erts_release_code_write_permission();
- ERTS_REQ_PROC_MAIN_LOCK(c_p);
-
- if (ERTS_LIKELY(is_value(result))) {
- reg[0] = result;
- return RET_NIF_success;
- } else {
- c_p->freason = BADARG;
- return RET_NIF_error;
- }
- } else {
- /* Yield and try again. */
- c_p->current = NULL;
- c_p->arity = 2;
- return RET_NIF_yield;
- }
-}
-
-Uint beam_jit_get_map_elements(Eterm map,
- Eterm *reg,
- Eterm *E,
- Uint n,
- Eterm *fs) {
- Uint sz;
-
- /* This instruction assumes Arg1 is a map, i.e. that it follows a test
- * is_map if needed. */
-
- if (is_flatmap(map)) {
- flatmap_t *mp;
- Eterm *ks;
- Eterm *vs;
-
- mp = (flatmap_t *)flatmap_val(map);
- sz = flatmap_get_size(mp);
-
- if (sz == 0) {
- return 0;
- }
-
- ks = flatmap_get_keys(mp);
- vs = flatmap_get_values(mp);
-
- while (sz) {
- if (EQ(fs[0], *ks)) {
- PUT_TERM_REG(*vs, fs[1]);
-
- n--;
- fs += 3;
-
- /* no more values to fetch, we are done */
- if (n == 0) {
- return 1;
- }
- }
-
- ks++, sz--, vs++;
- }
- return 0;
- } else {
- ASSERT(is_hashmap(map));
-
- while (n--) {
- const Eterm *v;
- Uint32 hx;
-
- hx = fs[2];
- ASSERT(hx == hashmap_make_hash(fs[0]));
-
- if ((v = erts_hashmap_get(hx, fs[0], map)) == NULL) {
- return 0;
- }
-
- PUT_TERM_REG(*v, fs[1]);
- fs += 3;
- }
-
- return 1;
- }
-}
-
-static void test_bin_vheap(Process *c_p,
- Eterm *reg,
- Uint VNh,
- Uint Nh,
- Uint Live) {
- int need = Nh;
-
- if (c_p->stop - c_p->htop < (need + S_RESERVED) ||
- MSO(c_p).overhead + VNh >= BIN_VHEAP_SZ(c_p)) {
- c_p->fcalls -=
- erts_garbage_collect_nobump(c_p, need, reg, Live, c_p->fcalls);
- }
-}
-
-static void gc_test(Process *c_p, Eterm *reg, Uint Ns, Uint Nh, Uint Live) {
- int need = Nh + Ns;
-
- if (ERTS_UNLIKELY(c_p->stop - c_p->htop < (need + S_RESERVED))) {
- c_p->fcalls -=
- erts_garbage_collect_nobump(c_p, need, reg, Live, c_p->fcalls);
- }
-}
-
-void beam_jit_bs_field_size_argument_error(Process *c_p, Eterm size) {
- if (((is_small(size) && signed_val(size) >= 0) ||
- (is_big(size) && !big_sign(size)))) {
- /* If the argument is a positive integer, we must've had a system_limit
- * error. */
- c_p->freason = SYSTEM_LIMIT;
- } else {
- c_p->freason = BADARG;
- }
-}
-
-/* Set the exception code for bs_add argument errors after the fact, which is
- * much easier and more compact than discriminating within module code. */
-void beam_jit_bs_add_argument_error(Process *c_p, Eterm A, Eterm B) {
- if (((is_small(A) && signed_val(A) >= 0) || (is_big(A) && !big_sign(A))) &&
- ((is_small(B) && signed_val(B) >= 0) || (is_big(B) && !big_sign(B)))) {
- /* If all arguments are positive integers, we must've had a system_limit
- * error. */
- c_p->freason = SYSTEM_LIMIT;
- } else {
- c_p->freason = BADARG;
- }
-}
-
-static Eterm i_bs_start_match2_gc_test_preserve(Process *c_p,
- Eterm *reg,
- Uint need,
- Uint live,
- Eterm preserve) {
- Uint words_left = (Uint)(STACK_TOP(c_p) - HEAP_TOP(c_p));
-
- if (ERTS_UNLIKELY(words_left < need + S_RESERVED)) {
- reg[live] = preserve;
- PROCESS_MAIN_CHK_LOCKS(c_p);
- c_p->fcalls -= erts_garbage_collect_nobump(c_p,
- need,
- reg,
- live + 1,
- c_p->fcalls);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- preserve = reg[live];
- }
-
- return preserve;
-}
-
-Eterm beam_jit_bs_start_match2(Eterm context,
- Uint live,
- Uint slots,
- Process *c_p,
- Eterm *reg) {
- Eterm header;
- if (!is_boxed(context)) {
- return THE_NON_VALUE;
- }
- header = *boxed_val(context);
-
- slots++;
-
- if (header_is_bin_matchstate(header)) {
- ErlBinMatchState *ms = (ErlBinMatchState *)boxed_val(context);
- Uint actual_slots = HEADER_NUM_SLOTS(header);
-
- /* We're not compatible with contexts created by bs_start_match3. */
- ASSERT(actual_slots >= 1);
-
- ms->save_offset[0] = ms->mb.offset;
- if (ERTS_UNLIKELY(actual_slots < slots)) {
- ErlBinMatchState *expanded;
- Uint wordsneeded = ERL_BIN_MATCHSTATE_SIZE(slots);
- context = i_bs_start_match2_gc_test_preserve(c_p,
- reg,
- wordsneeded,
- live,
- context);
- ms = (ErlBinMatchState *)boxed_val(context);
- expanded = (ErlBinMatchState *)HEAP_TOP(c_p);
- *expanded = *ms;
- *HEAP_TOP(c_p) = HEADER_BIN_MATCHSTATE(slots);
- HEAP_TOP(c_p) += wordsneeded;
- context = make_matchstate(expanded);
- }
- return context;
- } else if (is_binary_header(header)) {
- Uint wordsneeded = ERL_BIN_MATCHSTATE_SIZE(slots);
- context = i_bs_start_match2_gc_test_preserve(c_p,
- reg,
- wordsneeded,
- live,
- context);
- return erts_bs_start_match_2(c_p, context, slots);
- } else {
- return THE_NON_VALUE;
- }
-}
-
-Eterm beam_jit_bs_init(Process *c_p,
- Eterm *reg,
- ERL_BITS_DECLARE_STATEP,
- Eterm BsOp1,
- Eterm BsOp2,
- unsigned Live) {
- if (BsOp1 <= ERL_ONHEAP_BIN_LIMIT) {
- ErlHeapBin *hb;
- Uint bin_need;
-
- bin_need = heap_bin_size(BsOp1);
- erts_bin_offset = 0;
- erts_writable_bin = 0;
- gc_test(c_p, reg, 0, bin_need + BsOp2 + ERL_SUB_BIN_SIZE, Live);
- hb = (ErlHeapBin *)c_p->htop;
- c_p->htop += bin_need;
- hb->thing_word = header_heap_bin(BsOp1);
- hb->size = BsOp1;
- erts_current_bin = (byte *)hb->data;
- return make_binary(hb);
- } else {
- Binary *bptr;
- ProcBin *pb;
-
- erts_bin_offset = 0;
- erts_writable_bin = 0;
- test_bin_vheap(c_p,
- reg,
- BsOp1 / sizeof(Eterm),
- BsOp2 + PROC_BIN_SIZE + ERL_SUB_BIN_SIZE,
- Live);
-
- /*
- * Allocate the binary struct itself.
- */
- bptr = erts_bin_nrml_alloc(BsOp1);
- erts_current_bin = (byte *)bptr->orig_bytes;
-
- /*
- * Now allocate the ProcBin on the heap.
- */
- pb = (ProcBin *)c_p->htop;
- c_p->htop += PROC_BIN_SIZE;
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = BsOp1;
- pb->next = MSO(c_p).first;
- MSO(c_p).first = (struct erl_off_heap_header *)pb;
- pb->val = bptr;
- pb->bytes = (byte *)bptr->orig_bytes;
- pb->flags = 0;
-
- OH_OVERHEAD(&(MSO(c_p)), BsOp1 / sizeof(Eterm));
-
- return make_binary(pb);
- }
-}
-
-Eterm beam_jit_bs_init_bits(Process *c_p,
- Eterm *reg,
- ERL_BITS_DECLARE_STATEP,
- Uint num_bits,
- Uint alloc,
- unsigned Live) {
- Eterm new_binary;
- Uint num_bytes = ((Uint64)num_bits + (Uint64)7) >> 3;
-
- if (num_bits & 7) {
- alloc += ERL_SUB_BIN_SIZE;
- }
- if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
- alloc += heap_bin_size(num_bytes);
- } else {
- alloc += PROC_BIN_SIZE;
- }
- gc_test(c_p, reg, 0, alloc, Live);
-
- /* num_bits = Number of bits to build
- * num_bytes = Number of bytes to allocate in the binary
- * alloc = Total number of words to allocate on heap
- * Operands: NotUsed NotUsed Dst
- */
- if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
- ErlHeapBin *hb;
-
- erts_bin_offset = 0;
- erts_writable_bin = 0;
- hb = (ErlHeapBin *)c_p->htop;
- c_p->htop += heap_bin_size(num_bytes);
- hb->thing_word = header_heap_bin(num_bytes);
- hb->size = num_bytes;
- erts_current_bin = (byte *)hb->data;
- new_binary = make_binary(hb);
-
- do_bits_sub_bin:
- if (num_bits & 7) {
- ErlSubBin *sb;
-
- sb = (ErlSubBin *)c_p->htop;
- c_p->htop += ERL_SUB_BIN_SIZE;
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = num_bytes - 1;
- sb->bitsize = num_bits & 7;
- sb->offs = 0;
- sb->bitoffs = 0;
- sb->is_writable = 0;
- sb->orig = new_binary;
- new_binary = make_binary(sb);
- }
- /* HEAP_SPACE_VERIFIED(0); */
- return new_binary;
- } else {
- Binary *bptr;
- ProcBin *pb;
-
- erts_bin_offset = 0;
- erts_writable_bin = 0;
-
- /*
- * Allocate the binary struct itself.
- */
- bptr = erts_bin_nrml_alloc(num_bytes);
- erts_current_bin = (byte *)bptr->orig_bytes;
-
- /*
- * Now allocate the ProcBin on the heap.
- */
- pb = (ProcBin *)c_p->htop;
- c_p->htop += PROC_BIN_SIZE;
- pb->thing_word = HEADER_PROC_BIN;
- pb->size = num_bytes;
- pb->next = MSO(c_p).first;
- MSO(c_p).first = (struct erl_off_heap_header *)pb;
- pb->val = bptr;
- pb->bytes = (byte *)bptr->orig_bytes;
- pb->flags = 0;
- OH_OVERHEAD(&(MSO(c_p)), pb->size / sizeof(Eterm));
- new_binary = make_binary(pb);
- goto do_bits_sub_bin;
- }
-}
-
-Eterm beam_jit_bs_get_integer(Process *c_p,
- Eterm *reg,
- Eterm context,
- Uint flags,
- Uint size,
- Uint Live) {
- ErlBinMatchBuffer *mb;
-
- if (size >= SMALL_BITS) {
- Uint wordsneeded;
-
- /* Check bits size before potential gc.
- * We do not want a gc and then realize we don't need
- * the allocated space (i.e. if the op fails).
- *
- * Remember to re-acquire the matchbuffer after gc.
- */
- mb = ms_matchbuffer(context);
- if (mb->size - mb->offset < size) {
- return THE_NON_VALUE;
- }
-
- wordsneeded = 1 + WSIZE(NBYTES((Uint)size));
- reg[Live] = context;
- gc_test(c_p, reg, 0, wordsneeded, Live + 1);
- context = reg[Live];
- }
-
- mb = ms_matchbuffer(context);
- return erts_bs_get_integer_2(c_p, size, flags, mb);
-}
-
-void beam_jit_bs_context_to_binary(Eterm context) {
- if (is_boxed(context) && header_is_bin_matchstate(*boxed_val(context))) {
- Uint orig, size, offs, hole_size;
- ErlBinMatchBuffer *mb;
- ErlBinMatchState *ms;
- ErlSubBin *sb;
- ms = (ErlBinMatchState *)boxed_val(context);
- mb = &ms->mb;
- offs = ms->save_offset[0];
- size = mb->size - offs;
- orig = mb->orig;
- sb = (ErlSubBin *)boxed_val(context);
- /* Since we're going to overwrite the match state with the result, an
- * ErlBinMatchState must be at least as large as an ErlSubBin. */
- ERTS_CT_ASSERT(sizeof(ErlSubBin) <= sizeof(ErlBinMatchState));
- hole_size = 1 + header_arity(sb->thing_word) - ERL_SUB_BIN_SIZE;
- sb->thing_word = HEADER_SUB_BIN;
- sb->size = BYTE_OFFSET(size);
- sb->bitsize = BIT_OFFSET(size);
- sb->offs = BYTE_OFFSET(offs);
- sb->bitoffs = BIT_OFFSET(offs);
- sb->is_writable = 0;
- sb->orig = orig;
- if (hole_size) {
- sb[1].thing_word = make_pos_bignum_header(hole_size - 1);
- }
- }
-}
-
-ErtsMessage *beam_jit_decode_dist(Process *c_p, ErtsMessage *msgp) {
- if (!erts_proc_sig_decode_dist(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
- /*
- * A corrupt distribution message that we weren't able to decode;
- * remove it...
- */
-
- /* TODO: Add DTrace probe for this bad message situation? */
- erts_msgq_unlink_msg(c_p, msgp);
- msgp->next = NULL;
- erts_cleanup_messages(msgp);
-
- return NULL;
- }
-
- return msgp;
-}
-
-/* Remove a (matched) message from the message queue. */
-Sint beam_jit_remove_message(Process *c_p,
- Sint FCALLS,
- Eterm *HTOP,
- Eterm *E,
- Uint32 active_code_ix) {
- ErtsMessage *msgp;
-
- ERTS_CHK_MBUF_SZ(c_p);
-
- if (active_code_ix == ERTS_SAVE_CALLS_CODE_IX) {
- save_calls(c_p, &exp_receive);
- }
-
- msgp = erts_msgq_peek_msg(c_p);
-
- if (ERL_MESSAGE_TOKEN(msgp) == 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;
- } else {
- 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);
-#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;
- } 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)) ||
- is_atom(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->common.id,
- c_p);
-#ifdef USE_VM_PROBES
- }
-#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;
- Sint len = erts_proc_sig_privqs_len(c_p);
-
- dtrace_proc_str(c_p, receiver_name);
- token2 = SEQ_TRACE_TOKEN(c_p);
- if (have_seqtrace(token2)) {
- tok_label = SEQ_TRACE_T_DTRACE_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)),
- len, /* This is NOT message queue len, but its something... */
- tok_label,
- tok_lastcnt,
- tok_serial);
- }
-#endif
- erts_msgq_unlink_msg_set_save_first(c_p, msgp);
- CANCEL_TIMER(c_p);
-
- erts_save_message_in_proc(c_p, msgp);
- c_p->flags &= ~F_DELAY_GC;
-
- if (ERTS_IS_GC_DESIRED_INTERNAL(c_p, HTOP, E, 0)) {
- /*
- * We want to GC soon but we leave a few
- * reductions giving the message some time
- * to turn into garbage.
- */
- ERTS_VBUMP_LEAVE_REDS_INTERNAL(c_p, 5, FCALLS);
- }
-
- ERTS_CHK_MBUF_SZ(c_p);
-
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- return FCALLS;
-}
-
-void beam_jit_take_receive_lock(Process *c_p) {
- erts_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
-}
-
-void beam_jit_wait_locked(Process *c_p, ErtsCodePtr cp) {
- c_p->arity = 0;
- if (!ERTS_PTMR_IS_TIMED_OUT(c_p)) {
- erts_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE);
- }
- ASSERT(!ERTS_PROC_IS_EXITING(c_p));
- erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
- c_p->current = NULL;
- c_p->i = cp;
-}
-
-void beam_jit_wait_unlocked(Process *c_p, ErtsCodePtr cp) {
- beam_jit_take_receive_lock(c_p);
- beam_jit_wait_locked(c_p, cp);
-}
-
-enum beam_jit_tmo_ret beam_jit_wait_timeout(Process *c_p,
- Eterm timeout_value,
- ErtsCodePtr next) {
- /*
- * If we have already set the timer, we must NOT set it again. Therefore,
- * we must test the F_INSLPQUEUE flag as well as the F_TIMO flag.
- */
- if ((c_p->flags & (F_INSLPQUEUE | F_TIMO)) == 0) {
- if (timeout_value == make_small(0)) {
- erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
- return RET_next;
- } else if (timeout_value == am_infinity) {
- c_p->flags |= F_TIMO;
- } else {
- int tres = erts_set_proc_timer_term(c_p, timeout_value);
- if (tres == 0) {
- /*
- * The timer routiner will set c_p->i to the value in
- * c_p->def_arg_reg[0]. Note that it is safe to use this
- * location because there are no living x registers in
- * a receive statement.
- */
- c_p->def_arg_reg[0] = (Eterm)next;
- } else { /* Wrong time */
- erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
- c_p->freason = EXC_TIMEOUT_VALUE;
- erts_msgq_set_save_first(c_p);
- return RET_badarg;
- }
- }
- }
- return RET_wait;
-}
-
-void beam_jit_timeout(Process *c_p) {
- if (IS_TRACED_FL(c_p, F_TRACE_RECEIVE)) {
- trace_receive(c_p, am_clock_service, am_timeout, NULL);
- }
- if (ERTS_PROC_GET_SAVED_CALLS_BUF(c_p)) {
- save_calls(c_p, &exp_timeout);
- }
- c_p->flags &= ~F_TIMO;
- erts_msgq_set_save_first(c_p);
-}
-
-void beam_jit_timeout_locked(Process *c_p) {
- erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
- beam_jit_timeout(c_p);
-}
diff --git a/erts/emulator/beam/jit/beam_jit_common.cpp b/erts/emulator/beam/jit/beam_jit_common.cpp
new file mode 100644
index 0000000000..04fdf209d4
--- /dev/null
+++ b/erts/emulator/beam/jit/beam_jit_common.cpp
@@ -0,0 +1,1310 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_jit_common.hpp"
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "sys.h"
+#include "erl_vm.h"
+#include "global.h"
+#include "code_ix.h"
+#include "erl_proc_sig_queue.h"
+#include "erl_binary.h"
+#include "erl_bits.h"
+#include "erl_map.h"
+#include "beam_common.h"
+#ifdef USE_VM_PROBES
+# include "dtrace-wrapper.h"
+#endif
+}
+
+static std::string getAtom(Eterm atom) {
+ Atom *ap = atom_tab(atom_val(atom));
+ return std::string((char *)ap->name, ap->len);
+}
+
+BeamAssembler::BeamAssembler() : code() {
+ /* Setup with default code info */
+ Error err = code.init(Environment::host());
+ ERTS_ASSERT(!err && "Failed to init codeHolder");
+
+ err = code.newSection(&rodata,
+ ".rodata",
+ SIZE_MAX,
+ SectionFlags::kReadOnly,
+ 8);
+ ERTS_ASSERT(!err && "Failed to create .rodata section");
+
+ err = code.attach(&a);
+
+ ERTS_ASSERT(!err && "Failed to attach codeHolder");
+#ifdef DEBUG
+ a.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
+#endif
+ a.addEncodingOptions(EncodingOptions::kOptimizeForSize |
+ EncodingOptions::kOptimizedAlign);
+ code.setErrorHandler(this);
+}
+
+BeamAssembler::BeamAssembler(const std::string &log) : BeamAssembler() {
+ if (erts_jit_asm_dump) {
+ setLogger(log + ".asm");
+ }
+}
+
+BeamAssembler::~BeamAssembler() {
+ if (logger.file()) {
+ fclose(logger.file());
+ }
+}
+
+void *BeamAssembler::getBaseAddress() {
+ ASSERT(code.hasBaseAddress());
+ return (void *)code.baseAddress();
+}
+
+size_t BeamAssembler::getOffset() {
+ return a.offset();
+}
+
+void BeamAssembler::_codegen(JitAllocator *allocator,
+ const void **executable_ptr,
+ void **writable_ptr) {
+ Error err = code.flatten();
+ ERTS_ASSERT(!err && "Could not flatten code");
+ err = code.resolveUnresolvedLinks();
+ ERTS_ASSERT(!err && "Could not resolve all links");
+
+ /* Verify that all labels are bound */
+#ifdef DEBUG
+ for (auto e : code.labelEntries()) {
+ if (!e->isBound()) {
+ if (e->hasName()) {
+ erts_exit(ERTS_ABORT_EXIT,
+ "Label %d with name %s is not bound\n",
+ e->id(),
+ e->name());
+ } else {
+ erts_exit(ERTS_ABORT_EXIT, "Label %d is not bound\n", e->id());
+ }
+ }
+ }
+#endif
+
+ err = allocator->alloc(const_cast<void **>(executable_ptr),
+ writable_ptr,
+ code.codeSize() + 16);
+
+ if (err == ErrorCode::kErrorTooManyHandles) {
+ ERTS_ASSERT(!"Failed to allocate module code: "
+ "out of file descriptors");
+ } else if (err) {
+ ERTS_ASSERT("Failed to allocate module code");
+ }
+
+ code.relocateToBase((uint64_t)*executable_ptr);
+ code.copyFlattenedData(*writable_ptr,
+ code.codeSize(),
+ CopySectionFlags::kPadSectionBuffer);
+
+#ifdef DEBUG
+ if (FileLogger *l = dynamic_cast<FileLogger *>(code.logger()))
+ if (FILE *f = l->file())
+ fprintf(f, "; CODE_SIZE: %zd\n", code.codeSize());
+#endif
+}
+
+void *BeamAssembler::getCode(Label label) {
+ ASSERT(label.isValid());
+ return (char *)getBaseAddress() + code.labelOffsetFromBase(label);
+}
+
+byte *BeamAssembler::getCode(char *labelName) {
+ return (byte *)getCode(code.labelByName(labelName, strlen(labelName)));
+}
+
+void BeamAssembler::handleError(Error err,
+ const char *message,
+ BaseEmitter *origin) {
+ comment(message);
+ fflush(logger.file());
+ ASSERT(0 && "Failed to encode instruction");
+}
+
+void BeamAssembler::embed_rodata(const char *labelName,
+ const char *buff,
+ size_t size) {
+ Label label = a.newNamedLabel(labelName);
+
+ a.section(rodata);
+ a.bind(label);
+ a.embed(buff, size);
+ a.section(code.textSection());
+}
+
+void BeamAssembler::embed_bss(const char *labelName, size_t size) {
+ Label label = a.newNamedLabel(labelName);
+
+ /* Reuse rodata section for now */
+ a.section(rodata);
+ a.bind(label);
+ embed_zeros(size);
+ a.section(code.textSection());
+}
+
+void BeamAssembler::embed_zeros(size_t size) {
+ static constexpr size_t buf_size = 16384;
+ static const char zeros[buf_size] = {};
+
+ while (size >= buf_size) {
+ a.embed(zeros, buf_size);
+ size -= buf_size;
+ }
+
+ if (size > 0) {
+ a.embed(zeros, size);
+ }
+}
+
+void BeamAssembler::setLogger(std::string log) {
+ FILE *f = fopen(log.data(), "w+");
+
+ /* FIXME: Don't crash when loading multiple modules with the same name.
+ *
+ * setLogger(nullptr) disables logging. */
+ if (f) {
+ setvbuf(f, NULL, _IONBF, 0);
+ }
+
+ setLogger(f);
+}
+
+void BeamAssembler::setLogger(FILE *log) {
+ logger.setFile(log);
+ logger.setIndentation(FormatIndentationGroup::kCode, 4);
+ code.setLogger(&logger);
+}
+
+void BeamModuleAssembler::codegen(JitAllocator *allocator,
+ const void **executable_ptr,
+ void **writable_ptr,
+ const BeamCodeHeader *in_hdr,
+ const BeamCodeHeader **out_exec_hdr,
+ BeamCodeHeader **out_rw_hdr) {
+ const BeamCodeHeader *code_hdr_exec;
+ BeamCodeHeader *code_hdr_rw;
+
+ codegen(allocator, executable_ptr, writable_ptr);
+
+ {
+ auto offset = code.labelOffsetFromBase(code_header);
+
+ auto base_exec = (const char *)(*executable_ptr);
+ code_hdr_exec = (const BeamCodeHeader *)&base_exec[offset];
+
+ auto base_rw = (const char *)(*writable_ptr);
+ code_hdr_rw = (BeamCodeHeader *)&base_rw[offset];
+ }
+
+ sys_memcpy(code_hdr_rw, in_hdr, sizeof(BeamCodeHeader));
+ code_hdr_rw->on_load = getOnLoad();
+
+ for (unsigned i = 0; i < functions.size(); i++) {
+ ErtsCodeInfo *ci = (ErtsCodeInfo *)getCode(functions[i]);
+ code_hdr_rw->functions[i] = ci;
+ }
+
+ char *module_end = (char *)code.baseAddress() + a.offset();
+ code_hdr_rw->functions[functions.size()] = (ErtsCodeInfo *)module_end;
+
+ *out_exec_hdr = code_hdr_exec;
+ *out_rw_hdr = code_hdr_rw;
+}
+
+void BeamModuleAssembler::codegen(JitAllocator *allocator,
+ const void **executable_ptr,
+ void **writable_ptr) {
+ _codegen(allocator, executable_ptr, writable_ptr);
+}
+
+void BeamModuleAssembler::codegen(char *buff, size_t len) {
+ code.flatten();
+ code.resolveUnresolvedLinks();
+ ERTS_ASSERT(code.codeSize() <= len);
+ code.relocateToBase((uint64_t)buff);
+ code.copyFlattenedData(buff,
+ code.codeSize(),
+ CopySectionFlags::kPadSectionBuffer);
+}
+
+BeamModuleAssembler::BeamModuleAssembler(BeamGlobalAssembler *_ga,
+ Eterm _mod,
+ int num_labels,
+ const BeamFile *file)
+ : BeamAssembler(getAtom(_mod)), beam(file), ga(_ga), mod(_mod) {
+ rawLabels.reserve(num_labels + 1);
+
+ if (logger.file() && beam) {
+ /* Dig out all named labels from the BEAM-file and sort them on the
+ * label id. */
+ const int named_count = beam->exports.count + beam->locals.count;
+ BeamFile_ExportEntry *entries;
+
+ entries = (BeamFile_ExportEntry *)erts_alloc(
+ ERTS_ALC_T_PREPARED_CODE,
+ (named_count + 1) * sizeof(entries[0]));
+
+ for (int i = 0; i < beam->exports.count; i++) {
+ entries[i] = beam->exports.entries[i];
+ }
+
+ for (int i = 0; i < beam->locals.count; i++) {
+ entries[i + beam->exports.count] = beam->locals.entries[i];
+ }
+
+ /* Place a sentinel entry with an invalid label number. */
+ entries[named_count].label = 0;
+
+ std::qsort(entries,
+ named_count,
+ sizeof(entries[0]),
+ [](const void *lhs__, const void *rhs__) {
+ auto lhs = (const BeamFile_ExportEntry *)lhs__;
+ auto rhs = (const BeamFile_ExportEntry *)rhs__;
+
+ if (lhs->label < rhs->label) {
+ return -1;
+ } else if (lhs->label == rhs->label) {
+ return 0;
+ } else {
+ return 1;
+ }
+ });
+
+ BeamFile_ExportEntry *e = &entries[0];
+
+ for (int i = 1; i < num_labels; i++) {
+ /* Large enough to hold most realistic function names. We will
+ * truncate too long names, but as the label name is not important
+ * for the functioning of the JIT and this functionality is
+ * probably only used by developers, we don't bother with dynamic
+ * allocation. */
+ char tmp[MAX_ATOM_SZ_LIMIT];
+
+ /* The named_labels are sorted, so no need for a search. */
+ if (e->label == i) {
+ erts_snprintf(tmp, sizeof(tmp), "%T/%d", e->function, e->arity);
+ rawLabels.emplace(i, a.newNamedLabel(tmp));
+ e++;
+ } else {
+ std::string lblName = "label_" + std::to_string(i);
+ rawLabels.emplace(i, a.newNamedLabel(lblName.data()));
+ }
+ }
+
+ erts_free(ERTS_ALC_T_PREPARED_CODE, entries);
+ } else if (logger.file()) {
+ /* There is no naming info, but dumping of the assembly code
+ * has been requested, so do the best we can and number the
+ * labels. */
+ for (int i = 1; i < num_labels; i++) {
+ std::string lblName = "label_" + std::to_string(i);
+ rawLabels.emplace(i, a.newNamedLabel(lblName.data()));
+ }
+ } else {
+ /* No output is requested, go with unnamed labels */
+ for (int i = 1; i < num_labels; i++) {
+ rawLabels.emplace(i, a.newLabel());
+ }
+ }
+
+ if (beam) {
+ /* Create labels for the trampolines that unpack fun environments.
+ *
+ * Note that `num_free == 0` short-circuits directly to the target. */
+ for (int i = 0; i < beam->lambdas.count; i++) {
+ const auto &lambda = beam->lambdas.entries[i];
+ lambdas[i].trampoline = (lambda.num_free > 0)
+ ? a.newLabel()
+ : rawLabels.at(lambda.label);
+ }
+ }
+}
+
+void BeamModuleAssembler::register_metadata(const BeamCodeHeader *header) {
+#ifndef WIN32
+ const BeamCodeLineTab *line_table = header->line_table;
+
+ char name_buffer[MAX_ATOM_SZ_LIMIT];
+ std::string module_name = getAtom(mod);
+ std::vector<AsmRange> ranges;
+ ERTS_DECL_AM(erts_beamasm);
+
+ ranges.reserve(functions.size() + 2);
+
+ ASSERT((ErtsCodePtr)getBaseAddress() == (ErtsCodePtr)header);
+
+ /* Push info about the header */
+ ranges.push_back({.start = (ErtsCodePtr)getBaseAddress(),
+ .stop = getCode(functions[0]),
+ .name = module_name + "::codeHeader"});
+
+ for (unsigned i = 0; i < functions.size(); i++) {
+ std::vector<AsmRange::LineData> lines;
+ ErtsCodePtr start, stop;
+ const ErtsCodeInfo *ci;
+ Sint n;
+
+ start = getCode(functions[i]);
+ ci = (const ErtsCodeInfo *)start;
+
+ stop = ((const char *)erts_codeinfo_to_code(ci));
+
+ if (ci->mfa.module != AM_erts_beamasm) {
+ /* All modules (except erts_beamasm, which is a JIT internal module)
+ have a prologue that should be counted as part of the CodeInfo */
+ stop = ((const char *)stop) + BEAM_ASM_FUNC_PROLOGUE_SIZE;
+ }
+
+ n = erts_snprintf(name_buffer,
+ 1024,
+ "%T:%T/%d",
+ ci->mfa.module,
+ ci->mfa.function,
+ ci->mfa.arity);
+
+ /* We use a different symbol for CodeInfo and the Prologue
+ * in order for the perf disassembly to be better. */
+ std::string function_name(name_buffer, n);
+ ranges.push_back({.start = start,
+ .stop = stop,
+ .name = function_name + "-CodeInfoPrologue"});
+
+ /* The actual code */
+ start = stop;
+ if (i + 1 < functions.size()) {
+ stop = getCode(functions[i + 1]);
+ } else {
+ stop = getCode(code_end);
+ }
+
+ if (line_table) {
+ const void **line_cursor = line_table->func_tab[i];
+ const int loc_size = line_table->loc_size;
+
+ /* Register all lines belonging to this function. */
+ while ((intptr_t)line_cursor[0] < (intptr_t)stop) {
+ ptrdiff_t line_index;
+ Uint32 loc;
+
+ line_index = line_cursor - line_table->func_tab[0];
+
+ if (loc_size == 2) {
+ loc = line_table->loc_tab.p2[line_index];
+ } else {
+ ASSERT(loc_size == 4);
+ loc = line_table->loc_tab.p4[line_index];
+ }
+
+ if (loc != LINE_INVALID_LOCATION) {
+ Uint32 file;
+ Eterm fname;
+ int res;
+
+ file = LOC_FILE(loc);
+ fname = line_table->fname_ptr[file];
+
+ ERTS_ASSERT(is_nil(fname) || is_list(fname));
+
+ res = erts_unicode_list_to_buf(fname,
+ (byte *)name_buffer,
+ sizeof(name_buffer) / 4,
+ &n);
+
+ ERTS_ASSERT(res != -1);
+
+ lines.push_back({.start = line_cursor[0],
+ .file = std::string(name_buffer, n),
+ .line = LOC_LINE(loc)});
+ }
+
+ line_cursor++;
+ }
+ }
+
+ ranges.push_back({.start = start,
+ .stop = stop,
+ .name = function_name,
+ .lines = lines});
+ }
+
+ /* Push info about the footer */
+ ranges.push_back(
+ {.start = ranges.back().stop,
+ .stop = (ErtsCodePtr)(code.baseAddress() + code.codeSize()),
+ .name = module_name + "::codeFooter"});
+
+ beamasm_metadata_update(module_name,
+ (ErtsCodePtr)code.baseAddress(),
+ code.codeSize(),
+ ranges);
+#endif
+}
+
+BeamCodeHeader *BeamModuleAssembler::getCodeHeader() {
+ return (BeamCodeHeader *)getCode(code_header);
+}
+
+const ErtsCodeInfo *BeamModuleAssembler::getOnLoad() {
+ if (on_load.isValid()) {
+ return erts_code_to_codeinfo((ErtsCodePtr)getCode(on_load));
+ } else {
+ return 0;
+ }
+}
+
+/* ** */
+
+#if defined(DEBUG) && defined(JIT_HARD_DEBUG)
+void beam_jit_validate_term(Eterm term) {
+ if (is_boxed(term)) {
+ Eterm header = *boxed_val(term);
+
+ if (header_is_bin_matchstate(header)) {
+ return;
+ }
+ }
+
+ size_object_x(term, NULL);
+}
+#endif
+
+Eterm beam_jit_call_bif(Process *c_p,
+ Eterm *reg,
+ ErtsCodePtr I,
+ ErtsBifFunc vbf,
+ Uint arity) {
+ ErlHeapFragment *live_hf_end;
+ Eterm result;
+
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ {
+ live_hf_end = c_p->mbuf;
+
+ ERTS_CHK_MBUF_SZ(c_p);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ result = vbf(c_p, reg, I);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result));
+ ERTS_CHK_MBUF_SZ(c_p);
+
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ERTS_HOLE_CHECK(c_p);
+ }
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+
+ if (ERTS_IS_GC_AFTER_BIF_DESIRED(c_p)) {
+ result = erts_gc_after_bif_call_lhf(c_p,
+ live_hf_end,
+ result,
+ reg,
+ arity);
+ }
+
+ return result;
+}
+
+Eterm beam_jit_call_nif(Process *c_p,
+ ErtsCodePtr I,
+ Eterm *reg,
+ BeamJitNifF *fp,
+ struct erl_module_nif *NifMod) {
+ Eterm nif_bif_result;
+ Eterm bif_nif_arity;
+ ErlHeapFragment *live_hf_end;
+ const ErtsCodeMFA *codemfa;
+
+ codemfa = erts_code_to_codemfa(I);
+
+ c_p->current = codemfa; /* current and vbf set to please handle_error */
+
+ bif_nif_arity = codemfa->arity;
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+
+ {
+ struct enif_environment_t env;
+ ASSERT(c_p->scheduler_data);
+ live_hf_end = c_p->mbuf;
+ ERTS_CHK_MBUF_SZ(c_p);
+ erts_pre_nif(&env, c_p, NifMod, NULL);
+
+ ASSERT((c_p->scheduler_data)->current_nif == NULL);
+ (c_p->scheduler_data)->current_nif = &env;
+
+ nif_bif_result = (*fp)(&env, bif_nif_arity, reg);
+ if (env.exception_thrown)
+ nif_bif_result = THE_NON_VALUE;
+
+ ASSERT((c_p->scheduler_data)->current_nif == &env);
+ (c_p->scheduler_data)->current_nif = NULL;
+
+ erts_post_nif(&env);
+ ERTS_CHK_MBUF_SZ(c_p);
+
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ASSERT(!env.exiting);
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ }
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+ ERTS_HOLE_CHECK(c_p);
+
+ if (ERTS_IS_GC_AFTER_BIF_DESIRED(c_p)) {
+ nif_bif_result = erts_gc_after_bif_call_lhf(c_p,
+ live_hf_end,
+ nif_bif_result,
+ reg,
+ bif_nif_arity);
+ }
+
+ return nif_bif_result;
+}
+
+enum beam_jit_nif_load_ret beam_jit_load_nif(Process *c_p,
+ ErtsCodePtr I,
+ Eterm *reg) {
+ if (erts_try_seize_code_write_permission(c_p)) {
+ Eterm result;
+
+ PROCESS_MAIN_CHK_LOCKS((c_p));
+ ERTS_UNREQ_PROC_MAIN_LOCK((c_p));
+ result = erts_load_nif(c_p, I, reg[0], reg[1]);
+ erts_release_code_write_permission();
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+
+ if (ERTS_LIKELY(is_value(result))) {
+ reg[0] = result;
+ return RET_NIF_success;
+ } else {
+ c_p->freason = BADARG;
+ return RET_NIF_error;
+ }
+ } else {
+ /* Yield and try again. */
+ c_p->current = NULL;
+ c_p->arity = 2;
+ return RET_NIF_yield;
+ }
+}
+
+Uint beam_jit_get_map_elements(Eterm map,
+ Eterm *reg,
+ Eterm *E,
+ Uint n,
+ Eterm *fs) {
+ Uint sz;
+
+ /* This instruction assumes Arg1 is a map, i.e. that it follows a test
+ * is_map if needed. */
+
+ if (is_flatmap(map)) {
+ flatmap_t *mp;
+ Eterm *ks;
+ Eterm *vs;
+
+ mp = (flatmap_t *)flatmap_val(map);
+ sz = flatmap_get_size(mp);
+
+ if (sz == 0) {
+ return 0;
+ }
+
+ ks = flatmap_get_keys(mp);
+ vs = flatmap_get_values(mp);
+
+ while (sz) {
+ if (EQ(fs[0], *ks)) {
+ PUT_TERM_REG(*vs, fs[1]);
+
+ n--;
+ fs += 3;
+
+ /* no more values to fetch, we are done */
+ if (n == 0) {
+ return 1;
+ }
+ }
+
+ ks++, sz--, vs++;
+ }
+ return 0;
+ } else {
+ ASSERT(is_hashmap(map));
+
+ while (n--) {
+ const Eterm *v;
+ Uint32 hx;
+
+ hx = fs[2];
+ ASSERT(hx == hashmap_make_hash(fs[0]));
+
+ if ((v = erts_hashmap_get(hx, fs[0], map)) == NULL) {
+ return 0;
+ }
+
+ PUT_TERM_REG(*v, fs[1]);
+ fs += 3;
+ }
+
+ return 1;
+ }
+}
+
+static void test_bin_vheap(Process *c_p,
+ Eterm *reg,
+ Uint VNh,
+ Uint Nh,
+ Uint Live) {
+ int need = Nh;
+
+ if (c_p->stop - c_p->htop < (need + S_RESERVED) ||
+ MSO(c_p).overhead + VNh >= BIN_VHEAP_SZ(c_p)) {
+ c_p->fcalls -=
+ erts_garbage_collect_nobump(c_p, need, reg, Live, c_p->fcalls);
+ }
+}
+
+static void gc_test(Process *c_p, Eterm *reg, Uint Ns, Uint Nh, Uint Live) {
+ int need = Nh + Ns;
+
+ if (ERTS_UNLIKELY(c_p->stop - c_p->htop < (need + S_RESERVED))) {
+ c_p->fcalls -=
+ erts_garbage_collect_nobump(c_p, need, reg, Live, c_p->fcalls);
+ }
+}
+
+void beam_jit_bs_field_size_argument_error(Process *c_p, Eterm size) {
+ if (((is_small(size) && signed_val(size) >= 0) ||
+ (is_big(size) && !big_sign(size)))) {
+ /* If the argument is a positive integer, we must've had a system_limit
+ * error. */
+ c_p->freason = SYSTEM_LIMIT;
+ } else {
+ c_p->freason = BADARG;
+ }
+}
+
+/* Set the exception code for bs_add argument errors after the fact, which is
+ * much easier and more compact than discriminating within module code. */
+void beam_jit_bs_add_argument_error(Process *c_p, Eterm A, Eterm B) {
+ if (((is_small(A) && signed_val(A) >= 0) || (is_big(A) && !big_sign(A))) &&
+ ((is_small(B) && signed_val(B) >= 0) || (is_big(B) && !big_sign(B)))) {
+ /* If all arguments are positive integers, we must've had a system_limit
+ * error. */
+ c_p->freason = SYSTEM_LIMIT;
+ } else {
+ c_p->freason = BADARG;
+ }
+}
+
+Eterm beam_jit_bs_init(Process *c_p,
+ Eterm *reg,
+ ERL_BITS_DECLARE_STATEP,
+ Eterm num_bytes,
+ Uint alloc,
+ unsigned Live) {
+ erts_bin_offset = 0;
+ erts_writable_bin = 0;
+ if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
+ ErlHeapBin *hb;
+ Uint bin_need;
+
+ bin_need = heap_bin_size(num_bytes);
+ gc_test(c_p, reg, 0, bin_need + alloc + ERL_SUB_BIN_SIZE, Live);
+ hb = (ErlHeapBin *)c_p->htop;
+ c_p->htop += bin_need;
+ hb->thing_word = header_heap_bin(num_bytes);
+ hb->size = num_bytes;
+ erts_current_bin = (byte *)hb->data;
+ return make_binary(hb);
+ } else {
+ Binary *bptr;
+ ProcBin *pb;
+
+ test_bin_vheap(c_p,
+ reg,
+ num_bytes / sizeof(Eterm),
+ alloc + PROC_BIN_SIZE,
+ Live);
+
+ /*
+ * Allocate the binary struct itself.
+ */
+ bptr = erts_bin_nrml_alloc(num_bytes);
+ erts_current_bin = (byte *)bptr->orig_bytes;
+
+ /*
+ * Now allocate the ProcBin on the heap.
+ */
+ pb = (ProcBin *)c_p->htop;
+ c_p->htop += PROC_BIN_SIZE;
+ pb->thing_word = HEADER_PROC_BIN;
+ pb->size = num_bytes;
+ pb->next = MSO(c_p).first;
+ MSO(c_p).first = (struct erl_off_heap_header *)pb;
+ pb->val = bptr;
+ pb->bytes = (byte *)bptr->orig_bytes;
+ pb->flags = 0;
+
+ OH_OVERHEAD(&(MSO(c_p)), num_bytes / sizeof(Eterm));
+
+ return make_binary(pb);
+ }
+}
+
+Eterm beam_jit_bs_init_bits(Process *c_p,
+ Eterm *reg,
+ ERL_BITS_DECLARE_STATEP,
+ Uint num_bits,
+ Uint alloc,
+ unsigned Live) {
+ Eterm new_binary;
+ Uint num_bytes = ((Uint64)num_bits + (Uint64)7) >> 3;
+
+ if (num_bits & 7) {
+ alloc += ERL_SUB_BIN_SIZE;
+ }
+ if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
+ alloc += heap_bin_size(num_bytes);
+ } else {
+ alloc += PROC_BIN_SIZE;
+ }
+
+ erts_bin_offset = 0;
+ erts_writable_bin = 0;
+
+ /* num_bits = Number of bits to build
+ * num_bytes = Number of bytes to allocate in the binary
+ * alloc = Total number of words to allocate on heap
+ * Operands: NotUsed NotUsed Dst
+ */
+ if (num_bytes <= ERL_ONHEAP_BIN_LIMIT) {
+ ErlHeapBin *hb;
+
+ gc_test(c_p, reg, 0, alloc, Live);
+ hb = (ErlHeapBin *)c_p->htop;
+ c_p->htop += heap_bin_size(num_bytes);
+ hb->thing_word = header_heap_bin(num_bytes);
+ hb->size = num_bytes;
+ erts_current_bin = (byte *)hb->data;
+ new_binary = make_binary(hb);
+ } else {
+ Binary *bptr;
+ ProcBin *pb;
+
+ test_bin_vheap(c_p, reg, num_bytes / sizeof(Eterm), alloc, Live);
+
+ /*
+ * Allocate the binary struct itself.
+ */
+ bptr = erts_bin_nrml_alloc(num_bytes);
+ erts_current_bin = (byte *)bptr->orig_bytes;
+
+ /*
+ * Now allocate the ProcBin on the heap.
+ */
+ pb = (ProcBin *)c_p->htop;
+ c_p->htop += PROC_BIN_SIZE;
+ pb->thing_word = HEADER_PROC_BIN;
+ pb->size = num_bytes;
+ pb->next = MSO(c_p).first;
+ MSO(c_p).first = (struct erl_off_heap_header *)pb;
+ pb->val = bptr;
+ pb->bytes = (byte *)bptr->orig_bytes;
+ pb->flags = 0;
+ OH_OVERHEAD(&(MSO(c_p)), pb->size / sizeof(Eterm));
+ new_binary = make_binary(pb);
+ }
+
+ if (num_bits & 7) {
+ ErlSubBin *sb;
+
+ sb = (ErlSubBin *)c_p->htop;
+ c_p->htop += ERL_SUB_BIN_SIZE;
+ sb->thing_word = HEADER_SUB_BIN;
+ sb->size = num_bytes - 1;
+ sb->bitsize = num_bits & 7;
+ sb->offs = 0;
+ sb->bitoffs = 0;
+ sb->is_writable = 0;
+ sb->orig = new_binary;
+ new_binary = make_binary(sb);
+ }
+
+ return new_binary;
+}
+
+Eterm beam_jit_bs_get_integer(Process *c_p,
+ Eterm *reg,
+ Eterm context,
+ Uint flags,
+ Uint size,
+ Uint Live) {
+ ErlBinMatchBuffer *mb;
+
+ if (size >= SMALL_BITS) {
+ Uint wordsneeded;
+
+ /* Check bits size before potential gc.
+ * We do not want a gc and then realize we don't need
+ * the allocated space (i.e. if the op fails).
+ *
+ * Remember to re-acquire the matchbuffer after gc.
+ */
+ mb = ms_matchbuffer(context);
+ if (mb->size - mb->offset < size) {
+ return THE_NON_VALUE;
+ }
+
+ wordsneeded = 1 + WSIZE(NBYTES((Uint)size));
+ reg[Live] = context;
+ gc_test(c_p, reg, 0, wordsneeded, Live + 1);
+ context = reg[Live];
+ }
+
+ mb = ms_matchbuffer(context);
+ return erts_bs_get_integer_2(c_p, size, flags, mb);
+}
+
+void beam_jit_bs_construct_fail_info(Process *c_p,
+ Uint packed_error_info,
+ Eterm arg3,
+ Eterm arg1) {
+ Eterm *hp;
+ Eterm cause_tuple;
+ Eterm error_info;
+ Uint segment = beam_jit_get_bsc_segment(packed_error_info);
+ JitBSCOp op = beam_jit_get_bsc_op(packed_error_info);
+ JitBSCInfo info = beam_jit_get_bsc_info(packed_error_info);
+ JitBSCReason reason = beam_jit_get_bsc_reason(packed_error_info);
+ JitBSCValue value_location = beam_jit_get_bsc_value(packed_error_info);
+ Eterm Op = am_none;
+ Uint Reason = BADARG;
+ Eterm Info = am_none;
+ Eterm value = am_undefined;
+
+ switch (op) {
+ case BSC_OP_BINARY:
+ Op = am_binary;
+ break;
+ case BSC_OP_FLOAT:
+ Op = am_float;
+ break;
+ case BSC_OP_INTEGER:
+ Op = am_integer;
+ break;
+ case BSC_OP_UTF8:
+ Op = am_utf8;
+ break;
+ case BSC_OP_UTF16:
+ Op = am_utf16;
+ break;
+ case BSC_OP_UTF32:
+ Op = am_utf32;
+ break;
+ }
+
+ switch (value_location) {
+ case BSC_VALUE_ARG1:
+ value = arg1;
+ break;
+ case BSC_VALUE_ARG3:
+ value = arg3;
+ break;
+ case BSC_VALUE_FVALUE:
+ value = c_p->fvalue;
+ break;
+ }
+
+ switch (reason) {
+ case BSC_REASON_BADARG:
+ Reason = BADARG;
+ break;
+ case BSC_REASON_SYSTEM_LIMIT:
+ Reason = SYSTEM_LIMIT;
+ break;
+ case BSC_REASON_DEPENDS:
+ if ((is_small(value) && signed_val(value) >= 0) ||
+ (is_big(value) && !big_sign(value))) {
+ Reason = SYSTEM_LIMIT;
+ } else {
+ Reason = BADARG;
+ }
+ break;
+ }
+
+ switch (info) {
+ case BSC_INFO_FVALUE:
+ Info = c_p->fvalue;
+ break;
+ case BSC_INFO_TYPE:
+ Info = am_type;
+ break;
+ case BSC_INFO_SIZE:
+ Info = am_size;
+ break;
+ case BSC_INFO_UNIT:
+ Info = am_unit;
+ break;
+ case BSC_INFO_DEPENDS:
+ ASSERT(op == BSC_OP_BINARY);
+ Info = is_binary(value) ? am_short : am_type;
+ break;
+ }
+
+ hp = HAlloc(c_p, Sint(MAP3_SZ + 5));
+ cause_tuple = TUPLE4(hp, make_small(segment), Op, Info, value);
+ hp += 5;
+ error_info = MAP3(hp,
+ am_cause,
+ cause_tuple,
+ am_function,
+ am_format_bs_fail,
+ am_module,
+ am_erl_erts_errors);
+ c_p->fvalue = error_info;
+ c_p->freason = Reason | EXF_HAS_EXT_INFO;
+}
+
+Sint beam_jit_bs_bit_size(Eterm term) {
+ if (is_binary(term)) {
+ ASSERT(sizeof(Uint) == 8); /* Only support 64-bit machines. */
+ Uint byte_size = binary_size(term);
+ return (Sint)((byte_size << 3) + binary_bitsize(term));
+ }
+
+ /* Signal error */
+ return (Sint)-1;
+}
+
+ErtsMessage *beam_jit_decode_dist(Process *c_p, ErtsMessage *msgp) {
+ if (!erts_proc_sig_decode_dist(c_p, ERTS_PROC_LOCK_MAIN, msgp, 0)) {
+ /*
+ * A corrupt distribution message that we weren't able to decode;
+ * remove it...
+ */
+
+ /* TODO: Add DTrace probe for this bad message situation? */
+ erts_msgq_unlink_msg(c_p, msgp);
+ msgp->next = NULL;
+ erts_cleanup_messages(msgp);
+
+ return NULL;
+ }
+
+ return msgp;
+}
+
+/* Remove a (matched) message from the message queue. */
+Sint beam_jit_remove_message(Process *c_p,
+ Sint FCALLS,
+ Eterm *HTOP,
+ Eterm *E,
+ Uint32 active_code_ix) {
+ ErtsMessage *msgp;
+
+ ERTS_CHK_MBUF_SZ(c_p);
+
+ if (active_code_ix == ERTS_SAVE_CALLS_CODE_IX) {
+ save_calls(c_p, &exp_receive);
+ }
+
+ msgp = erts_msgq_peek_msg(c_p);
+
+ if (ERL_MESSAGE_TOKEN(msgp) == 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;
+ } else {
+ 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);
+#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;
+ } 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)) ||
+ is_atom(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->common.id,
+ c_p);
+#ifdef USE_VM_PROBES
+ }
+#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;
+ Sint len = erts_proc_sig_privqs_len(c_p);
+
+ dtrace_proc_str(c_p, receiver_name);
+ token2 = SEQ_TRACE_TOKEN(c_p);
+ if (have_seqtrace(token2)) {
+ tok_label = SEQ_TRACE_T_DTRACE_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)),
+ len, /* This is NOT message queue len, but its something... */
+ tok_label,
+ tok_lastcnt,
+ tok_serial);
+ }
+#endif
+ erts_msgq_unlink_msg_set_save_first(c_p, msgp);
+ CANCEL_TIMER(c_p);
+
+ erts_save_message_in_proc(c_p, msgp);
+ c_p->flags &= ~F_DELAY_GC;
+
+ if (ERTS_IS_GC_DESIRED_INTERNAL(c_p, HTOP, E, 0)) {
+ /*
+ * We want to GC soon but we leave a few
+ * reductions giving the message some time
+ * to turn into garbage.
+ */
+ ERTS_VBUMP_LEAVE_REDS_INTERNAL(c_p, 5, FCALLS);
+ }
+
+ ERTS_CHK_MBUF_SZ(c_p);
+
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ return FCALLS;
+}
+
+void beam_jit_take_receive_lock(Process *c_p) {
+ erts_proc_lock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
+}
+
+void beam_jit_wait_locked(Process *c_p, ErtsCodePtr cp) {
+ c_p->arity = 0;
+ if (!ERTS_PTMR_IS_TIMED_OUT(c_p)) {
+ erts_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE);
+ }
+ ASSERT(!ERTS_PROC_IS_EXITING(c_p));
+ erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
+ c_p->current = NULL;
+ c_p->i = cp;
+}
+
+void beam_jit_wait_unlocked(Process *c_p, ErtsCodePtr cp) {
+ beam_jit_take_receive_lock(c_p);
+ beam_jit_wait_locked(c_p, cp);
+}
+
+enum beam_jit_tmo_ret beam_jit_wait_timeout(Process *c_p,
+ Eterm timeout_value,
+ ErtsCodePtr next) {
+ /*
+ * If we have already set the timer, we must NOT set it again. Therefore,
+ * we must test the F_INSLPQUEUE flag as well as the F_TIMO flag.
+ */
+ if ((c_p->flags & (F_INSLPQUEUE | F_TIMO)) == 0) {
+ if (timeout_value == make_small(0)) {
+ erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
+ return RET_next;
+ } else if (timeout_value == am_infinity) {
+ c_p->flags |= F_TIMO;
+ } else {
+ int tres = erts_set_proc_timer_term(c_p, timeout_value);
+ if (tres == 0) {
+ /*
+ * The timer routiner will set c_p->i to the value in
+ * c_p->def_arg_reg[0]. Note that it is safe to use this
+ * location because there are no living x registers in
+ * a receive statement.
+ */
+ c_p->def_arg_reg[0] = (Eterm)next;
+ } else { /* Wrong time */
+ erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
+ c_p->freason = EXC_TIMEOUT_VALUE;
+ erts_msgq_set_save_first(c_p);
+ return RET_badarg;
+ }
+ }
+ }
+ return RET_wait;
+}
+
+void beam_jit_timeout(Process *c_p) {
+ if (IS_TRACED_FL(c_p, F_TRACE_RECEIVE)) {
+ trace_receive(c_p, am_clock_service, am_timeout, NULL);
+ }
+ if (ERTS_PROC_GET_SAVED_CALLS_BUF(c_p)) {
+ save_calls(c_p, &exp_timeout);
+ }
+ c_p->flags &= ~F_TIMO;
+ erts_msgq_set_save_first(c_p);
+}
+
+void beam_jit_timeout_locked(Process *c_p) {
+ erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE);
+ beam_jit_timeout(c_p);
+}
+
+void beam_jit_return_to_trace(Process *c_p) {
+ if (IS_TRACED_FL(c_p, F_TRACE_RETURN_TO)) {
+ ErtsCodePtr return_to_address;
+ Uint *cpp;
+
+ cpp = (Uint *)c_p->stop;
+ ASSERT(is_CP(cpp[0]));
+
+ for (;;) {
+ erts_inspect_frame(cpp, &return_to_address);
+
+ if (BeamIsReturnTrace(return_to_address)) {
+ cpp += CP_SIZE + 2;
+ } else if (BeamIsReturnTimeTrace(return_to_address)) {
+ cpp += CP_SIZE + 1;
+ } else if (BeamIsReturnToTrace(return_to_address)) {
+ cpp += CP_SIZE;
+ } else {
+ break;
+ }
+ }
+
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ erts_trace_return_to(c_p, return_to_address);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+ }
+}
+
+Eterm beam_jit_build_argument_list(Process *c_p, const Eterm *regs, int arity) {
+ Eterm *hp;
+ Eterm res;
+
+ hp = HAlloc(c_p, arity * 2);
+ res = NIL;
+
+ for (int i = arity - 1; i >= 0; i--) {
+ res = CONS(hp, regs[i], res);
+ hp += 2;
+ }
+
+ return res;
+}
+
+Export *beam_jit_handle_unloaded_fun(Process *c_p,
+ Eterm *reg,
+ int arity,
+ Eterm fun_thing) {
+ ErtsCodeIndex code_ix = erts_active_code_ix();
+ Eterm module, args;
+ ErlFunThing *funp;
+ ErlFunEntry *fe;
+ Module *modp;
+ Export *ep;
+
+ funp = (ErlFunThing *)fun_val(fun_thing);
+ ASSERT(is_local_fun(funp));
+
+ fe = funp->entry.fun;
+ module = fe->module;
+
+ ERTS_THR_READ_MEMORY_BARRIER;
+
+ if (fe->pend_purge_address) {
+ /* The system is currently trying to purge the module containing this
+ * fun. Suspend the process and let it try again when the purge
+ * operation is done (may succeed or not). */
+ ep = erts_suspend_process_on_pending_purge_lambda(c_p, fe);
+ } else {
+ if ((modp = erts_get_module(module, code_ix)) != NULL &&
+ modp->curr.code_hdr != NULL) {
+ /* There is a module loaded, but obviously the fun is not defined
+ * in it. We must not call the error_handler (or we will get into
+ * an infinite loop). */
+ c_p->current = NULL;
+ c_p->freason = EXC_BADFUN;
+ c_p->fvalue = fun_thing;
+ return NULL;
+ }
+
+ /* No current code for this module. Call the error_handler module to
+ * attempt loading the module. */
+ ep = erts_find_function(erts_proc_get_error_handler(c_p),
+ am_undefined_lambda,
+ 3,
+ code_ix);
+ if (ERTS_UNLIKELY(ep == NULL)) {
+ /* No error handler, crash out. */
+ c_p->current = NULL;
+ c_p->freason = EXC_UNDEF;
+ return NULL;
+ }
+ }
+
+ args = beam_jit_build_argument_list(c_p, reg, arity);
+
+ reg[0] = module;
+ reg[1] = fun_thing;
+ reg[2] = args;
+ reg[3] = NIL;
+
+ return ep;
+}
diff --git a/erts/emulator/beam/jit/beam_jit_common.h b/erts/emulator/beam/jit/beam_jit_common.h
deleted file mode 100644
index b2da85d0b8..0000000000
--- a/erts/emulator/beam/jit/beam_jit_common.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2021. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "sys.h"
-#include "erl_vm.h"
-#include "global.h"
-
-#if defined(DEBUG) && defined(JIT_HARD_DEBUG)
-void beam_jit_validate_term(Eterm term);
-#endif
-
-typedef Eterm BeamJitNifF(struct enif_environment_t *, int argc, Eterm argv[]);
-enum beam_jit_nif_load_ret { RET_NIF_success, RET_NIF_error, RET_NIF_yield };
-
-Eterm beam_jit_call_bif(Process *c_p,
- Eterm *reg,
- ErtsCodePtr I,
- ErtsBifFunc vbf,
- Uint arity);
-Eterm beam_jit_call_nif(Process *c_p,
- ErtsCodePtr I,
- Eterm *reg,
- BeamJitNifF *fp,
- struct erl_module_nif *NifMod);
-enum beam_jit_nif_load_ret beam_jit_load_nif(Process *c_p,
- ErtsCodePtr I,
- Eterm *reg);
-
-Uint beam_jit_get_map_elements(Eterm map,
- Eterm *reg,
- Eterm *E,
- Uint n,
- Eterm *fs);
-
-void beam_jit_bs_field_size_argument_error(Process *c_p, Eterm size);
-void beam_jit_bs_add_argument_error(Process *c_p, Eterm A, Eterm B);
-Eterm beam_jit_bs_start_match2(Eterm context,
- Uint live,
- Uint slots,
- Process *c_p,
- Eterm *reg);
-Eterm beam_jit_bs_init(Process *c_p,
- Eterm *reg,
- ERL_BITS_DECLARE_STATEP,
- Eterm BsOp1,
- Eterm BsOp2,
- unsigned Live);
-Eterm beam_jit_bs_init_bits(Process *c_p,
- Eterm *reg,
- ERL_BITS_DECLARE_STATEP,
- Uint num_bits,
- Uint alloc,
- unsigned Live);
-Eterm beam_jit_bs_get_integer(Process *c_p,
- Eterm *reg,
- Eterm context,
- Uint flags,
- Uint size,
- Uint Live);
-
-ErtsMessage *beam_jit_decode_dist(Process *c_p, ErtsMessage *msgp);
-Sint beam_jit_remove_message(Process *c_p,
- Sint FCALLS,
- Eterm *HTOP,
- Eterm *E,
- Uint32 active_code_ix);
-void beam_jit_bs_context_to_binary(Eterm context);
-
-void beam_jit_take_receive_lock(Process *c_p);
-void beam_jit_wait_locked(Process *c_p, ErtsCodePtr cp);
-void beam_jit_wait_unlocked(Process *c_p, ErtsCodePtr cp);
-
-enum beam_jit_tmo_ret { RET_next = 0, RET_wait = 1, RET_badarg = 2 };
-
-enum beam_jit_tmo_ret beam_jit_wait_timeout(Process *c_p,
- Eterm timeout_value,
- ErtsCodePtr next);
-
-void beam_jit_timeout(Process *c_p);
-void beam_jit_timeout_locked(Process *c_p);
diff --git a/erts/emulator/beam/jit/beam_jit_common.hpp b/erts/emulator/beam/jit/beam_jit_common.hpp
index f8f894c676..41cf957daa 100644
--- a/erts/emulator/beam/jit/beam_jit_common.hpp
+++ b/erts/emulator/beam/jit/beam_jit_common.hpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2021. All Rights Reserved.
+ * Copyright Ericsson AB 2021-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,9 @@
* %CopyrightEnd%
*/
+#ifndef __BEAM_JIT_COMMON_HPP__
+#define __BEAM_JIT_COMMON_HPP__
+
#include <string>
#include <vector>
#include <unordered_map>
@@ -30,108 +33,237 @@ extern "C"
#endif
#include "sys.h"
+#include "bif.h"
#include "erl_vm.h"
#include "global.h"
-
-#include "beam_jit_common.h"
+#include "beam_file.h"
}
-class ArgVal {
- BeamOpArg gen_op;
+#include "beam_jit_args.hpp"
+
+/* This is a view into a contiguous container (like an array or `std::vector`),
+ * letting us reuse the existing argument array in `beamasm_emit` while keeping
+ * our interfaces convenient.
+ *
+ * Needless to say, spans must not live longer than the container they wrap, so
+ * you must be careful not to return a span of an rvalue or stack-allocated
+ * container.
+ *
+ * We can replace this with std::span once we require C++20. */
+template<typename T>
+class Span {
+ const T *_data;
+ size_t _size;
public:
- enum TYPE {
- u = TAG_u,
- i = TAG_i,
- x = TAG_x,
- y = TAG_y,
- f = TAG_f,
- q = TAG_q,
- e = TAG_r,
- l = TAG_l /* float register */
- };
-
- ArgVal(const BeamOpArg &arg) {
- gen_op = arg;
+ template<typename Container>
+ Span(const Container &other) : Span(other.data(), other.size()) {
}
- ArgVal(enum TYPE t, BeamInstr val) {
- gen_op.type = t;
- gen_op.val = val;
+ template<typename Container>
+ Span(Container &other) : Span(other.data(), other.size()) {
}
- ArgVal(unsigned t, BeamInstr val) {
-#ifdef DEBUG
- switch (t) {
- case TAG_u:
- break;
- case TAG_i:
- break;
- case TAG_x:
- break;
- case TAG_y:
- break;
- case TAG_f:
- break;
- case TAG_q:
- break;
- case TAG_r:
- break;
- case TAG_l:
- break;
- default:
- ASSERT(0);
- }
-#endif
-
- gen_op.type = t;
- gen_op.val = val;
+ Span(const T *begin, const T *end) : Span(begin, end - begin) {
}
- constexpr enum TYPE getType() const {
- return (enum TYPE)gen_op.type;
+ Span(const T *data, size_t size) : _data(data), _size(size) {
}
- constexpr uint64_t getValue() const {
- return gen_op.val;
+ Span<T> subspan(size_t index, size_t count) const {
+ ASSERT(index <= size() && count <= (size() - index));
+ return Span<T>(begin() + index, count);
}
- constexpr bool isMem() const {
- return gen_op.type == x || gen_op.type == y;
+ const auto size() const {
+ return _size;
}
- constexpr bool isLiteral() const {
- return gen_op.type == q;
+ const auto begin() const {
+ return &_data[0];
}
- constexpr bool isImmed() const {
- return gen_op.type == i;
+ const auto end() const {
+ return &_data[size()];
}
- template<typename T>
- ArgVal operator+(T val) const {
- return ArgVal(gen_op.type, val + gen_op.val);
+ const T &operator[](size_t index) const {
+#ifdef DEBUG
+ ASSERT(index < _size);
+#endif
+ return _data[index];
}
- template<typename T>
- ArgVal operator*(T val) const {
- return ArgVal(gen_op.type, val * gen_op.val);
+ const T &front() const {
+ return operator[](0);
}
- enum Relation { none, consecutive, reverse_consecutive };
-
- static Relation register_relation(const ArgVal &arg1, const ArgVal &arg2) {
- TYPE type = arg1.getType();
- bool same_reg_types =
- type == arg2.getType() && (type == TYPE::x || type == TYPE::y);
- if (!same_reg_types) {
- return none;
- } else if (arg1.getValue() + 1 == arg2.getValue()) {
- return consecutive;
- } else if (arg1.getValue() == arg2.getValue() + 1) {
- return reverse_consecutive;
- } else {
- return none;
- }
- };
+ const T &back() const {
+ return operator[](size() - 1);
+ }
};
+
+static const Uint BSC_SEGMENT_OFFSET = 10;
+
+typedef enum : Uint {
+ BSC_OP_BINARY = 0,
+ BSC_OP_FLOAT = 1,
+ BSC_OP_INTEGER = 2,
+ BSC_OP_UTF8 = 3,
+ BSC_OP_UTF16 = 4,
+ BSC_OP_UTF32 = 5,
+ BSC_OP_LAST = 5
+} JitBSCOp;
+static const Uint BSC_OP_MASK = 0x07;
+static const Uint BSC_OP_OFFSET = 7;
+
+typedef enum : Uint {
+ BSC_INFO_FVALUE = 0,
+ BSC_INFO_TYPE = 1,
+ BSC_INFO_SIZE = 2,
+ BSC_INFO_UNIT = 3,
+ BSC_INFO_DEPENDS = 4,
+ BSC_INFO_LAST = 4,
+} JitBSCInfo;
+static const Uint BSC_INFO_MASK = 0x07;
+static const Uint BSC_INFO_OFFSET = 4;
+
+typedef enum : Uint {
+ BSC_REASON_BADARG = 0,
+ BSC_REASON_SYSTEM_LIMIT = 1,
+ BSC_REASON_DEPENDS = 2,
+ BSC_REASON_LAST = 2,
+} JitBSCReason;
+static const Uint BSC_REASON_MASK = 0x03;
+
+typedef enum : Uint {
+ BSC_VALUE_ARG1 = 0,
+ BSC_VALUE_ARG3 = 1,
+ BSC_VALUE_FVALUE = 2,
+ BSC_VALUE_LAST = 2
+} JitBSCValue;
+static const Uint BSC_VALUE_MASK = 0x03;
+static const Uint BSC_VALUE_OFFSET = 2;
+
+static constexpr Uint beam_jit_set_bsc_segment_op(Uint segment, JitBSCOp op) {
+ return (segment << BSC_SEGMENT_OFFSET) | (op << BSC_OP_OFFSET);
+}
+
+static constexpr Uint beam_jit_update_bsc_reason_info(Uint packed_info,
+ JitBSCReason reason,
+ JitBSCInfo info,
+ JitBSCValue value) {
+ return packed_info | (value << BSC_VALUE_OFFSET) |
+ (info << BSC_INFO_OFFSET) | reason;
+}
+
+static constexpr Uint beam_jit_get_bsc_segment(Uint packed_info) {
+ return packed_info >> BSC_SEGMENT_OFFSET;
+}
+
+static constexpr JitBSCOp beam_jit_get_bsc_op(Uint packed_info) {
+ ERTS_CT_ASSERT((BSC_OP_LAST & ~BSC_OP_MASK) == 0);
+ return (JitBSCOp)((packed_info >> BSC_OP_OFFSET) & BSC_OP_MASK);
+}
+
+static constexpr JitBSCInfo beam_jit_get_bsc_info(Uint packed_info) {
+ ERTS_CT_ASSERT((BSC_INFO_LAST & ~BSC_INFO_MASK) == 0);
+ return (JitBSCInfo)((packed_info >> BSC_INFO_OFFSET) & BSC_INFO_MASK);
+}
+
+static constexpr JitBSCReason beam_jit_get_bsc_reason(Uint packed_info) {
+ ERTS_CT_ASSERT((BSC_REASON_LAST & ~BSC_REASON_MASK) == 0);
+ return (JitBSCReason)(packed_info & BSC_REASON_MASK);
+}
+
+static constexpr JitBSCValue beam_jit_get_bsc_value(Uint packed_info) {
+ ERTS_CT_ASSERT((BSC_VALUE_LAST & ~BSC_VALUE_MASK) == 0);
+ return (JitBSCValue)((packed_info >> BSC_VALUE_OFFSET) & BSC_VALUE_MASK);
+}
+
+/* ** */
+
+#if defined(DEBUG) && defined(JIT_HARD_DEBUG)
+void beam_jit_validate_term(Eterm term);
+#endif
+
+typedef Eterm BeamJitNifF(struct enif_environment_t *, int argc, Eterm argv[]);
+enum beam_jit_nif_load_ret { RET_NIF_success, RET_NIF_error, RET_NIF_yield };
+
+Eterm beam_jit_call_bif(Process *c_p,
+ Eterm *reg,
+ ErtsCodePtr I,
+ ErtsBifFunc vbf,
+ Uint arity);
+Eterm beam_jit_call_nif(Process *c_p,
+ ErtsCodePtr I,
+ Eterm *reg,
+ BeamJitNifF *fp,
+ struct erl_module_nif *NifMod);
+enum beam_jit_nif_load_ret beam_jit_load_nif(Process *c_p,
+ ErtsCodePtr I,
+ Eterm *reg);
+
+Uint beam_jit_get_map_elements(Eterm map,
+ Eterm *reg,
+ Eterm *E,
+ Uint n,
+ Eterm *fs);
+
+void beam_jit_bs_field_size_argument_error(Process *c_p, Eterm size);
+void beam_jit_bs_add_argument_error(Process *c_p, Eterm A, Eterm B);
+Eterm beam_jit_bs_init(Process *c_p,
+ Eterm *reg,
+ ERL_BITS_DECLARE_STATEP,
+ Eterm num_bytes,
+ Uint alloc,
+ unsigned Live);
+Eterm beam_jit_bs_init_bits(Process *c_p,
+ Eterm *reg,
+ ERL_BITS_DECLARE_STATEP,
+ Uint num_bits,
+ Uint alloc,
+ unsigned Live);
+Eterm beam_jit_bs_get_integer(Process *c_p,
+ Eterm *reg,
+ Eterm context,
+ Uint flags,
+ Uint size,
+ Uint Live);
+
+ErtsMessage *beam_jit_decode_dist(Process *c_p, ErtsMessage *msgp);
+Sint beam_jit_remove_message(Process *c_p,
+ Sint FCALLS,
+ Eterm *HTOP,
+ Eterm *E,
+ Uint32 active_code_ix);
+
+void beam_jit_bs_construct_fail_info(Process *c_p,
+ Uint packed_error_info,
+ Eterm arg3,
+ Eterm arg1);
+Sint beam_jit_bs_bit_size(Eterm term);
+
+void beam_jit_take_receive_lock(Process *c_p);
+void beam_jit_wait_locked(Process *c_p, ErtsCodePtr cp);
+void beam_jit_wait_unlocked(Process *c_p, ErtsCodePtr cp);
+
+enum beam_jit_tmo_ret { RET_next = 0, RET_wait = 1, RET_badarg = 2 };
+
+enum beam_jit_tmo_ret beam_jit_wait_timeout(Process *c_p,
+ Eterm timeout_value,
+ ErtsCodePtr next);
+
+void beam_jit_timeout(Process *c_p);
+void beam_jit_timeout_locked(Process *c_p);
+
+void beam_jit_return_to_trace(Process *c_p);
+
+Eterm beam_jit_build_argument_list(Process *c_p, const Eterm *regs, int arity);
+
+Export *beam_jit_handle_unloaded_fun(Process *c_p,
+ Eterm *reg,
+ int arity,
+ Eterm fun_thing);
+
+#endif
diff --git a/erts/emulator/beam/jit/beam_jit_main.cpp b/erts/emulator/beam/jit/beam_jit_main.cpp
new file mode 100644
index 0000000000..2ddde35511
--- /dev/null
+++ b/erts/emulator/beam/jit/beam_jit_main.cpp
@@ -0,0 +1,592 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "bif.h"
+#include "beam_common.h"
+#include "code_ix.h"
+#include "export.h"
+#include "erl_threads.h"
+
+#if defined(__APPLE__)
+# include <libkern/OSCacheControl.h>
+#elif defined(WIN32)
+# include <windows.h>
+#endif
+}
+
+#ifdef ERLANG_FRAME_POINTERS
+ErtsFrameLayout ERTS_WRITE_UNLIKELY(erts_frame_layout);
+#endif
+
+/* Global configuration variables (under the `+J` prefix) */
+#ifdef HAVE_LINUX_PERF_SUPPORT
+enum beamasm_perf_flags erts_jit_perf_support;
+#endif
+
+/*
+ * Special Beam instructions.
+ */
+
+ErtsCodePtr beam_run_process;
+ErtsCodePtr beam_normal_exit;
+ErtsCodePtr beam_exit;
+ErtsCodePtr beam_export_trampoline;
+ErtsCodePtr beam_bif_export_trap;
+ErtsCodePtr beam_continue_exit;
+ErtsCodePtr beam_save_calls;
+ErtsCodePtr beam_unloaded_fun;
+
+/* NOTE These should be the only variables containing trace instructions.
+** Sometimes tests are for the instruction value, and sometimes
+** for the variable reference (one of these), and rogue references
+** will most likely cause chaos.
+*/
+ErtsCodePtr beam_return_to_trace; /* OpCode(i_return_to_trace) */
+ErtsCodePtr beam_return_trace; /* OpCode(i_return_trace) */
+ErtsCodePtr beam_exception_trace; /* UGLY also OpCode(i_return_trace) */
+ErtsCodePtr beam_return_time_trace; /* OpCode(i_return_time_trace) */
+
+static JitAllocator *jit_allocator;
+
+static BeamGlobalAssembler *bga;
+static BeamModuleAssembler *bma;
+static CpuInfo cpuinfo;
+
+/*
+ * Enter all BIFs into the export table.
+ *
+ * Note that they will all call the error_handler until their modules have been
+ * loaded, which may prevent the system from booting if BIFs from non-preloaded
+ * modules are apply/3'd while loading code. Ordinary BIF calls will work fine
+ * however since they won't go through export entries.
+ */
+static void install_bifs(void) {
+ typedef Eterm (*bif_func_type)(Process *, Eterm *, ErtsCodePtr);
+ int i;
+
+ ASSERT(beam_export_trampoline != NULL);
+ ASSERT(beam_save_calls != NULL);
+
+ for (i = 0; i < BIF_SIZE; i++) {
+ BifEntry *entry;
+ Export *ep;
+ int j;
+
+ entry = &bif_table[i];
+
+ ep = erts_export_put(entry->module, entry->name, entry->arity);
+
+ sys_memset(&ep->info.u, 0, sizeof(ep->info.u));
+ ep->info.mfa.module = entry->module;
+ ep->info.mfa.function = entry->name;
+ ep->info.mfa.arity = entry->arity;
+ ep->bif_number = i;
+
+ for (j = 0; j < ERTS_NUM_CODE_IX; j++) {
+ erts_activate_export_trampoline(ep, j);
+ }
+
+ /* Set up a hidden export entry so we can trap to this BIF without
+ * it being seen when tracing. */
+ erts_init_trap_export(BIF_TRAP_EXPORT(i),
+ entry->module,
+ entry->name,
+ entry->arity,
+ (bif_func_type)entry->f);
+ }
+}
+
+static JitAllocator *create_allocator(JitAllocator::CreateParams *params) {
+ void *test_ro, *test_rw;
+ Error err;
+
+ auto *allocator = new JitAllocator(params);
+
+ err = allocator->alloc(&test_ro, &test_rw, 1);
+ allocator->release(test_ro);
+
+ if (err == ErrorCode::kErrorOk) {
+ return allocator;
+ }
+
+ delete allocator;
+ return nullptr;
+}
+
+static JitAllocator *pick_allocator() {
+ JitAllocator::CreateParams single_params;
+ single_params.reset();
+
+#if defined(HAVE_LINUX_PERF_SUPPORT)
+ /* `perf` has a hard time showing symbols for dual-mapped memory, so we'll
+ * use single-mapped memory when enabled. */
+ if (erts_jit_perf_support & BEAMASM_PERF_ENABLED) {
+ if (auto *alloc = create_allocator(&single_params)) {
+ return alloc;
+ }
+
+ ERTS_INTERNAL_ERROR("jit: Failed to allocate executable+writable "
+ "memory. Either allow this or disable the "
+ "'+JPperf' option.");
+ }
+#endif
+
+#if !defined(VALGRIND)
+ /* Default to dual-mapped memory with separate executable and writable
+ * regions of the same code. This is required for platforms that enforce
+ * W^X, and we prefer it when available to catch errors sooner.
+ *
+ * `blockSize` is analogous to "carrier size," and we pick something
+ * much larger than the default since dual-mapping implies having one
+ * file descriptor per block on most platforms. The block sizes do grow
+ * over time, but we don't want to waste half a dozen fds just to get to
+ * the shell on platforms that are very fd-constrained. */
+ JitAllocator::CreateParams dual_params;
+
+ dual_params.reset();
+ dual_params.options = JitAllocatorOptions::kUseDualMapping,
+ dual_params.blockSize = 4 << 20;
+
+ if (auto *alloc = create_allocator(&dual_params)) {
+ return alloc;
+ } else if (auto *alloc = create_allocator(&single_params)) {
+ return alloc;
+ }
+
+ ERTS_INTERNAL_ERROR("jit: Cannot allocate executable memory. Use the "
+ "interpreter instead.");
+#elif defined(VALGRIND)
+ if (auto *alloc = create_allocator(&single_params)) {
+ return alloc;
+ }
+
+ ERTS_INTERNAL_ERROR("jit: the valgrind emulator requires the ability to "
+ "allocate executable+writable memory.");
+#endif
+}
+
+void beamasm_init() {
+ unsigned label = 1;
+
+ ASSERT(bga == nullptr && bma == nullptr);
+
+ struct operands {
+ Eterm name;
+ int arity;
+ BeamInstr operand;
+ ErtsCodePtr *target;
+ };
+
+ std::vector<struct operands> operands = {
+ {am_run_process, 3, op_i_apply_only, &beam_run_process},
+ {am_normal_exit, 0, op_normal_exit, &beam_normal_exit},
+ {am_continue_exit, 0, op_continue_exit, &beam_continue_exit},
+ {am_exception_trace, 0, op_return_trace, &beam_exception_trace},
+ {am_return_trace, 0, op_return_trace, &beam_return_trace},
+ {am_return_to_trace,
+ 0,
+ op_i_return_to_trace,
+ &beam_return_to_trace},
+ {am_return_time_trace,
+ 0,
+ op_i_return_time_trace,
+ &beam_return_time_trace}};
+
+ Eterm mod_name;
+ ERTS_DECL_AM(erts_beamasm);
+ mod_name = AM_erts_beamasm;
+
+ /* erts_frame_layout is hardcoded to ERTS_FRAME_LAYOUT_RA when Erlang
+ * frame pointers are disabled or unsupported. */
+#if defined(ERLANG_FRAME_POINTERS)
+# ifdef HAVE_LINUX_PERF_SUPPORT
+ if (erts_jit_perf_support & BEAMASM_PERF_FP) {
+ erts_frame_layout = ERTS_FRAME_LAYOUT_FP_RA;
+ } else {
+ erts_frame_layout = ERTS_FRAME_LAYOUT_RA;
+ }
+# else
+ erts_frame_layout = ERTS_FRAME_LAYOUT_RA;
+# endif
+#else
+ ERTS_CT_ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_RA);
+#endif
+
+ beamasm_metadata_early_init();
+
+ /*
+ * Ensure that commonly used fields in the PCB can be accessed with
+ * short instructions. Before removing any of these assertions, please
+ * consider the effect it will have on code size and/or performance.
+ */
+ ERTS_CT_ASSERT(offsetof(Process, htop) < 128);
+ ERTS_CT_ASSERT(offsetof(Process, stop) < 128);
+ ERTS_CT_ASSERT(offsetof(Process, fcalls) < 128);
+ ERTS_CT_ASSERT(offsetof(Process, freason) < 128);
+ ERTS_CT_ASSERT(offsetof(Process, fvalue) < 128);
+
+#ifdef ERLANG_FRAME_POINTERS
+ ERTS_CT_ASSERT(offsetof(Process, frame_pointer) < 128);
+#endif
+
+ cpuinfo = CpuInfo::host();
+
+ jit_allocator = pick_allocator();
+
+ bga = new BeamGlobalAssembler(jit_allocator);
+
+ bma = new BeamModuleAssembler(bga,
+ mod_name,
+ 1 + operands.size() * 2,
+ operands.size());
+
+ std::vector<ArgVal> args;
+
+ for (auto &op : operands) {
+ unsigned func_label, entry_label;
+
+ func_label = label++;
+ entry_label = label++;
+
+ args = {ArgVal(ArgVal::Label, func_label),
+ ArgVal(ArgVal::Word, sizeof(UWord))};
+ bma->emit(op_aligned_label_Lt, args);
+
+ args = {ArgVal(ArgVal::Word, func_label),
+ ArgVal(ArgVal::Immediate, mod_name),
+ ArgVal(ArgVal::Immediate, op.name),
+ ArgVal(ArgVal::Word, op.arity)};
+ bma->emit(op_i_func_info_IaaI, args);
+
+ args = {ArgVal(ArgVal::Label, entry_label),
+ ArgVal(ArgVal::Word, sizeof(UWord))};
+ bma->emit(op_aligned_label_Lt, args);
+
+ args = {};
+ bma->emit(op.operand, args);
+
+ op.operand = entry_label;
+ }
+
+ args = {};
+ bma->emit(op_int_code_end, args);
+
+ {
+ /* We have no need of the module pointers as we use `getCode(...)`
+ * for everything, and the code will live as long as the emulator
+ * itself. */
+ const void *_ignored_exec;
+ void *_ignored_rw;
+
+ /* Register our global code with gdb/perf so it shows up nicely in
+ * stack traces. */
+ BeamCodeHeader *_ignored_code_hdr_rw = NULL;
+ const BeamCodeHeader *code_hdr_ro = NULL;
+ BeamCodeHeader load_header = {};
+
+ load_header.num_functions = operands.size();
+
+ bma->codegen(jit_allocator,
+ &_ignored_exec,
+ &_ignored_rw,
+ &load_header,
+ &code_hdr_ro,
+ &_ignored_code_hdr_rw);
+ bma->register_metadata(code_hdr_ro);
+ }
+
+ for (auto op : operands) {
+ if (op.target) {
+ *op.target = bma->getCode(op.operand);
+ }
+ }
+
+ /* These instructions rely on register contents, and can only be reached
+ * from a `call_ext_*`-instruction or trapping from the emulator, hence the
+ * lack of wrapper functions. */
+ beam_save_calls = (ErtsCodePtr)bga->get_dispatch_save_calls();
+ beam_export_trampoline = (ErtsCodePtr)bga->get_export_trampoline();
+
+ /* Used when trappping to Erlang code from the emulator, setting up
+ * registers in the same way as call_ext so that save_calls and tracing
+ * works when trapping. */
+ beam_bif_export_trap = (ErtsCodePtr)bga->get_bif_export_trap();
+
+ beam_exit = (ErtsCodePtr)bga->get_process_exit();
+
+ beam_unloaded_fun = (ErtsCodePtr)bga->get_unloaded_fun();
+
+ beamasm_metadata_late_init();
+}
+
+bool BeamAssembler::hasCpuFeature(uint32_t featureId) {
+ return cpuinfo.hasFeature(featureId);
+}
+
+void init_emulator(void) {
+ install_bifs();
+}
+
+void process_main(ErtsSchedulerData *esdp) {
+ typedef void (*pmain_type)(ErtsSchedulerData *);
+
+ pmain_type pmain = (pmain_type)bga->get_process_main();
+ pmain(esdp);
+}
+
+extern "C"
+{
+ int erts_beam_jump_table(void) {
+#if defined(NO_JUMP_TABLE)
+ return 0;
+#else
+ return 1;
+#endif
+ }
+
+ void beamasm_flush_icache(const void *address, size_t size) {
+#ifdef DEBUG
+ erts_debug_require_code_barrier();
+#endif
+
+#if defined(__aarch64__) && defined(WIN32)
+ /* Issues full memory/instruction barriers on all threads for us. */
+ FlushInstructionCache(GetCurrentProcess(), address, size);
+#elif defined(__aarch64__) && defined(__APPLE__)
+ /* Issues full memory/instruction barriers on all threads for us. */
+ sys_icache_invalidate((char *)address, size);
+#elif defined(__aarch64__) && defined(__GNUC__) && \
+ defined(ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION) && \
+ defined(ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION) && \
+ defined(ERTS_THR_INSTRUCTION_BARRIER)
+ /* Note that we do not issue any barriers here, whether instruction or
+ * memory. This is on purpose as we must issue those on all schedulers
+ * and not just the calling thread, and the chances of us forgetting to
+ * do that is much higher if we issue them here. */
+ UWord start = reinterpret_cast<UWord>(address);
+ UWord end = start + size;
+
+ ETHR_COMPILER_BARRIER;
+
+ for (size_t i = start & ~ERTS_CACHE_LINE_MASK; i < end;
+ i += ERTS_CACHE_LINE_SIZE) {
+ __asm__ __volatile__("dc cvau, %0\n"
+ "ic ivau, %0\n" ::"r"(i)
+ :);
+ }
+#elif (defined(__x86_64__) || defined(_M_X64)) && \
+ defined(ERTS_THR_INSTRUCTION_BARRIER)
+ /* We don't need to invalidate cache on this platform, but since we
+ * might be modifying code with a different linear address than the one
+ * we execute from (dual-mapped memory), we still need to issue an
+ * instruction barrier on all schedulers to ensure that the change is
+ * visible. */
+ (void)address;
+ (void)size;
+#else
+# error "Platform lacks implementation for clearing instruction cache." \
+ "Please report this bug."
+#endif
+ }
+
+ void *beamasm_new_assembler(Eterm mod,
+ int num_labels,
+ int num_functions,
+ BeamFile *file) {
+ return new BeamModuleAssembler(bga,
+ mod,
+ num_labels,
+ num_functions,
+ file);
+ }
+
+ int beamasm_emit(void *instance, unsigned specific_op, BeamOp *op) {
+ /* The argument array must be safely convertible from `BeamOpArg*` to
+ * `ArgVal*` for us to reuse it directly.
+ *
+ * The exact traits we need weren't introduced until C++20, but the
+ * assertions below will catch just about everything that would break
+ * this conversion. */
+ static_assert(std::is_base_of<BeamOpArg, ArgVal>::value);
+ static_assert(std::is_standard_layout<ArgVal>::value);
+
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ const Span<ArgVal> args(static_cast<ArgVal *>(op->a), op->arity);
+ return ba->emit(specific_op, args);
+ }
+
+ void beamasm_emit_call_nif(const ErtsCodeInfo *info,
+ void *normal_fptr,
+ void *lib,
+ void *dirty_fptr,
+ char *buff,
+ unsigned buff_len) {
+ BeamModuleAssembler ba(bga, info->mfa.module, 3);
+ std::vector<ArgVal> args;
+
+ args = {ArgVal(ArgVal::Label, 1), ArgVal(ArgVal::Word, sizeof(UWord))};
+ ba.emit(op_aligned_label_Lt, args);
+
+ args = {ArgVal(ArgVal::Word, 1),
+ ArgVal(ArgVal::Immediate, info->mfa.module),
+ ArgVal(ArgVal::Immediate, info->mfa.function),
+ ArgVal(ArgVal::Word, info->mfa.arity)};
+ ba.emit(op_i_func_info_IaaI, args);
+
+ args = {ArgVal(ArgVal::Label, 2), ArgVal(ArgVal::Word, sizeof(UWord))};
+ ba.emit(op_aligned_label_Lt, args);
+
+ args = {};
+ ba.emit(op_i_breakpoint_trampoline, args);
+
+ args = {ArgVal(ArgVal::Word, (BeamInstr)normal_fptr),
+ ArgVal(ArgVal::Word, (BeamInstr)lib),
+ ArgVal(ArgVal::Word, (BeamInstr)dirty_fptr)};
+ ba.emit(op_call_nif_WWW, args);
+
+ ba.codegen(buff, buff_len);
+ }
+
+ void beamasm_delete_assembler(void *instance) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ delete ba;
+ }
+
+ void beamasm_purge_module(const void *native_module_exec,
+ void *native_module_rw) {
+ jit_allocator->release(const_cast<void *>(native_module_exec));
+ }
+
+ ErtsCodePtr beamasm_get_code(void *instance, int label) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return reinterpret_cast<ErtsCodePtr>(ba->getCode(label));
+ }
+
+ ErtsCodePtr beamasm_get_lambda(void *instance, int index) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return reinterpret_cast<ErtsCodePtr>(ba->getLambda(index));
+ }
+
+ const byte *beamasm_get_rodata(void *instance, char *label) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return reinterpret_cast<const byte *>(ba->getCode(label));
+ }
+
+ void beamasm_embed_rodata(void *instance,
+ const char *labelName,
+ const char *buff,
+ size_t size) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ if (size) {
+ ba->embed_rodata(labelName, buff, size);
+ }
+ }
+
+ void beamasm_embed_bss(void *instance, char *labelName, size_t size) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ if (size) {
+ ba->embed_bss(labelName, size);
+ }
+ }
+
+ void beamasm_codegen(void *instance,
+ const void **native_module_exec,
+ void **native_module_rw,
+ const BeamCodeHeader *in_hdr,
+ const BeamCodeHeader **out_exec_hdr,
+ BeamCodeHeader **out_rw_hdr) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+
+ ba->codegen(jit_allocator,
+ native_module_exec,
+ native_module_rw,
+ in_hdr,
+ out_exec_hdr,
+ out_rw_hdr);
+ }
+
+ void beamasm_register_metadata(void *instance, const BeamCodeHeader *hdr) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ ba->register_metadata(hdr);
+ }
+
+ Uint beamasm_get_header(void *instance, const BeamCodeHeader **hdr) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+
+ *hdr = ba->getCodeHeader();
+
+ return ba->getCodeSize();
+ }
+
+ char *beamasm_get_base(void *instance) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return (char *)ba->getBaseAddress();
+ }
+
+ size_t beamasm_get_offset(void *instance) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return ba->getOffset();
+ }
+
+ const ErtsCodeInfo *beamasm_get_on_load(void *instance) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return ba->getOnLoad();
+ }
+
+ unsigned int beamasm_patch_catches(void *instance, char *rw_base) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ return ba->patchCatches(rw_base);
+ }
+
+ void beamasm_patch_import(void *instance,
+ char *rw_base,
+ int index,
+ BeamInstr import) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ ba->patchImport(rw_base, index, import);
+ }
+
+ void beamasm_patch_literal(void *instance,
+ char *rw_base,
+ int index,
+ Eterm lit) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ ba->patchLiteral(rw_base, index, lit);
+ }
+
+ void beamasm_patch_lambda(void *instance,
+ char *rw_base,
+ int index,
+ BeamInstr fe) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ ba->patchLambda(rw_base, index, fe);
+ }
+
+ void beamasm_patch_strings(void *instance,
+ char *rw_base,
+ const byte *string_table) {
+ BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
+ ba->patchStrings(rw_base, string_table);
+ }
+}
diff --git a/erts/emulator/beam/jit/beam_jit_metadata.cpp b/erts/emulator/beam/jit/beam_jit_metadata.cpp
new file mode 100644
index 0000000000..68b59babd4
--- /dev/null
+++ b/erts/emulator/beam/jit/beam_jit_metadata.cpp
@@ -0,0 +1,541 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "beam_common.h"
+}
+
+#if !(defined(WIN32) || defined(__APPLE__) || defined(__MACH__) || \
+ defined(__DARWIN__))
+# define HAVE_GDB_SUPPORT
+#endif
+
+#ifdef HAVE_GDB_SUPPORT
+
+enum jit_actions : uint32_t {
+ JIT_NOACTION = 0,
+ JIT_REGISTER_FN,
+ JIT_UNREGISTER_FN,
+};
+
+struct jit_code_entry {
+ struct jit_code_entry *next_entry;
+ struct jit_code_entry *prev_entry;
+ const char *symfile_addr;
+ uint64_t symfile_size;
+};
+
+struct jit_descriptor {
+ uint32_t version;
+ jit_actions action_flag;
+ struct jit_code_entry *relevant_entry;
+ struct jit_code_entry *first_entry;
+ erts_mtx_t mutex;
+};
+
+extern "C"
+{
+ extern void ERTS_NOINLINE __jit_debug_register_code(void);
+
+ /* Make sure to specify the version statically, because the
+ * debugger may check the version before we can set it. */
+ struct jit_descriptor __jit_debug_descriptor = {1,
+ JIT_NOACTION,
+ NULL,
+ NULL};
+} /* extern "C" */
+
+struct emulator_info {
+ /* 0 = regular, 1 = frame pointers */
+ int frame_layout;
+ const void *normal_exit;
+};
+
+struct module_info {
+ uint64_t base_address;
+ uint32_t range_count;
+ uint32_t code_size;
+ /* Module name, including null terminator. */
+ uint16_t name_length;
+ char name[];
+};
+
+struct range_info {
+ uint32_t start_offset;
+ uint32_t end_offset;
+ uint32_t line_count;
+ /* Range name, including null terminator. */
+ uint16_t name_length;
+ char name[];
+};
+
+struct line_info {
+ uint32_t start_offset;
+ uint32_t line_number;
+ /* File name, including null terminator. */
+ uint16_t file_length;
+ char file[];
+};
+
+enum debug_info_header {
+ DEBUG_INFO_HEADER_EMULATOR = 0,
+ DEBUG_INFO_HEADER_MODULE = 1,
+};
+
+struct debug_info {
+ enum debug_info_header header;
+ union {
+ struct emulator_info emu;
+ struct module_info mod;
+ } payload;
+};
+
+static void beamasm_init_early_gdb() {
+ erts_mtx_init(&__jit_debug_descriptor.mutex,
+ "jit_debug_descriptor",
+ NIL,
+ (ERTS_LOCK_FLAGS_PROPERTY_STATIC |
+ ERTS_LOCK_FLAGS_CATEGORY_GENERIC));
+}
+
+static void beamasm_init_late_gdb() {
+ auto debug_info = (struct debug_info *)malloc(sizeof(struct debug_info));
+ jit_code_entry *entry;
+
+ debug_info->header = DEBUG_INFO_HEADER_EMULATOR;
+ debug_info->payload.emu.frame_layout = erts_frame_layout;
+ debug_info->payload.emu.normal_exit = beam_normal_exit;
+
+ entry = (jit_code_entry *)malloc(sizeof(jit_code_entry));
+ entry->symfile_addr = (char *)debug_info;
+ entry->symfile_size = sizeof(struct debug_info);
+
+ /* Insert into linked list */
+ entry->next_entry = __jit_debug_descriptor.first_entry;
+ if (entry->next_entry) {
+ entry->next_entry->prev_entry = entry;
+ } else {
+ entry->prev_entry = nullptr;
+ }
+
+ /* Insert into linked list */
+ erts_mtx_lock(&__jit_debug_descriptor.mutex);
+ entry->next_entry = __jit_debug_descriptor.first_entry;
+ if (entry->next_entry) {
+ entry->next_entry->prev_entry = entry;
+ } else {
+ entry->prev_entry = nullptr;
+ }
+
+ /* Register with gdb */
+ __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+ __jit_debug_descriptor.first_entry = entry;
+ __jit_debug_descriptor.relevant_entry = entry;
+ __jit_debug_register_code();
+ erts_mtx_unlock(&__jit_debug_descriptor.mutex);
+}
+
+static void beamasm_update_gdb_info(
+ std::string module_name,
+ ErtsCodePtr base_address,
+ size_t code_size,
+ const std::vector<BeamAssembler::AsmRange> &ranges) {
+ Sint symfile_size = sizeof(struct debug_info) + module_name.size() + 1;
+
+ for (const auto &range : ranges) {
+ symfile_size += sizeof(struct range_info) + range.name.size() + 1;
+
+ for (const auto &line : range.lines) {
+ symfile_size += sizeof(struct line_info) + line.file.size() + 1;
+ }
+ }
+
+ char *symfile = (char *)malloc(symfile_size);
+ jit_code_entry *entry;
+
+ entry = (jit_code_entry *)malloc(sizeof(jit_code_entry));
+ entry->symfile_addr = symfile;
+ entry->symfile_size = symfile_size;
+
+ auto debug_info = (struct debug_info *)symfile;
+ debug_info->header = DEBUG_INFO_HEADER_MODULE;
+
+ auto module_info = &debug_info->payload.mod;
+ module_info->base_address = (uint64_t)base_address;
+ module_info->code_size = (uint32_t)code_size;
+ module_info->range_count = ranges.size();
+ module_info->name_length = module_name.size() + 1;
+ sys_memcpy(module_info->name,
+ module_name.c_str(),
+ module_info->name_length);
+
+ symfile += sizeof(*debug_info) + module_info->name_length;
+
+ for (const auto &range : ranges) {
+ ASSERT(range.start >= base_address && range.start <= range.stop);
+
+ auto range_info = (struct range_info *)symfile;
+ range_info->start_offset = (char *)range.start - (char *)base_address;
+ range_info->end_offset = (char *)range.stop - (char *)base_address;
+ range_info->line_count = (uint32_t)range.lines.size();
+ range_info->name_length = (uint16_t)range.name.size() + 1;
+ sys_memcpy(range_info->name,
+ range.name.c_str(),
+ range_info->name_length);
+
+ symfile += sizeof(*range_info) + range_info->name_length;
+
+ for (const auto &line : range.lines) {
+ auto line_info = (struct line_info *)symfile;
+ line_info->start_offset = (char *)line.start - (char *)base_address;
+ line_info->line_number = (uint32_t)line.line;
+ line_info->file_length = (uint16_t)line.file.size() + 1;
+ sys_memcpy(line_info->file,
+ line.file.c_str(),
+ line_info->file_length);
+
+ symfile += sizeof(*line_info) + line_info->file_length;
+ }
+ }
+
+ ASSERT(symfile_size == (symfile - entry->symfile_addr));
+
+ /* Insert into linked list */
+ erts_mtx_lock(&__jit_debug_descriptor.mutex);
+ entry->next_entry = __jit_debug_descriptor.first_entry;
+ if (entry->next_entry) {
+ entry->next_entry->prev_entry = entry;
+ } else {
+ entry->prev_entry = nullptr;
+ }
+
+ /* register with gdb */
+ __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+ __jit_debug_descriptor.first_entry = entry;
+ __jit_debug_descriptor.relevant_entry = entry;
+ __jit_debug_register_code();
+ erts_mtx_unlock(&__jit_debug_descriptor.mutex);
+}
+
+#endif /* HAVE_GDB_SUPPORT */
+
+#ifdef HAVE_LINUX_PERF_SUPPORT
+
+# ifdef HAVE_ELF_H
+# include <elf.h>
+# define HAVE_LINUX_PERF_DUMP_SUPPORT 1
+
+class JitPerfDump {
+ FILE *file = nullptr;
+ Uint64 code_index = 0;
+
+ enum PerfDumpId {
+ JIT_CODE_LOAD = 0, /* record describing a jitted function */
+ JIT_CODE_MOVE = 1, /* record describing an already jitted function which
+ is moved */
+ JIT_CODE_DEBUG_INFO = 2, /* record describing the debug information for
+ a jitted function */
+ JIT_CODE_CLOSE =
+ 3, /* record marking the end of the jit runtime (optional) */
+ JIT_CODE_UNWINDING_INFO =
+ 4 /* record describing a function unwinding information */
+ };
+
+ struct FileHeader {
+ Uint32 magic;
+ Uint32 version;
+ Uint32 total_size;
+ Uint32 elf_mach;
+ Uint32 pad1;
+ Uint32 pid;
+ Uint64 timestamp;
+ Uint64 flags;
+
+ FileHeader() {
+ magic = 0x4A695444; /* "JiTD" as numbers */
+ version = 1;
+ total_size = sizeof(FileHeader);
+ elf_mach = EM_X86_64;
+ pad1 = 0;
+ pid = getpid();
+ timestamp = erts_os_monotonic_time();
+ flags = 0;
+ ERTS_CT_ASSERT(sizeof(FileHeader) == 4 * 10);
+ }
+ };
+
+ struct RecordHeader {
+ Uint32 id;
+ Uint32 total_size;
+ Uint64 timestamp;
+ };
+
+public:
+ bool init() {
+ char name[MAXPATHLEN];
+ FileHeader header;
+
+ /* LLVM places this file in ~/.debug/jit/ maybe we should do that to? */
+
+ erts_snprintf(name, sizeof(name), "/tmp/jit-%d.dump", getpid());
+
+ file = fopen(name, "w+");
+
+ if (file) {
+ fwrite(&header, sizeof(header), 1, file);
+ /* inform perf of the location of the dump file */
+ void *addr = mmap(NULL,
+ sizeof(header),
+ PROT_READ | PROT_EXEC,
+ MAP_PRIVATE,
+ fileno(file),
+ 0);
+ if (addr == MAP_FAILED) {
+ int saved_errno = errno;
+ erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbuf,
+ "perf: mmap of %s(%d) failed: %d\r\n",
+ name,
+ fileno(file),
+ saved_errno);
+ erts_send_error_to_logger_nogl(dsbuf);
+ fclose(file);
+ file = nullptr;
+ return false;
+ }
+ } else {
+ int saved_errno = errno;
+ erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbuf,
+ "perf: Failed to open %s (%d)",
+ name,
+ saved_errno);
+ erts_send_error_to_logger_nogl(dsbuf);
+ return false;
+ }
+ return true;
+ }
+
+ void update(const std::vector<BeamAssembler::AsmRange> &ranges) {
+ struct JitCodeLoadRecord {
+ RecordHeader header;
+ Uint32 pid;
+ Uint32 tid;
+ Uint64 vma;
+ Uint64 code_addr;
+ Uint64 code_size;
+ Uint64 code_index;
+ /* Null terminated M:F/A */
+ /* Native code */
+ } record;
+
+ record.header.id = JIT_CODE_LOAD;
+ record.pid = getpid();
+ record.tid = erts_thr_self();
+
+ for (const BeamAssembler::AsmRange &range : ranges) {
+ /* Line entries must be written first, if present. */
+ if (!range.lines.empty()) {
+ struct JitCodeDebugEntry {
+ Uint64 line_addr;
+ Uint32 line;
+ Uint32 column;
+ char name[];
+ } debug_entry;
+
+ struct JitCodeDebugInfoRecord {
+ RecordHeader header;
+ Uint64 code_addr;
+ Uint64 nr_entry;
+ struct JitCodeDebugEntry entries[];
+ } debug_info;
+
+ debug_info.header.id = JIT_CODE_DEBUG_INFO;
+ debug_info.header.total_size = sizeof(debug_info);
+ debug_info.header.timestamp = erts_os_monotonic_time();
+ debug_info.code_addr = (Uint64)range.start;
+ debug_info.nr_entry = range.lines.size() + 1;
+
+ for (const auto &line : range.lines) {
+ debug_info.header.total_size += sizeof(debug_entry);
+ debug_info.header.total_size += line.file.size() + 1;
+ }
+
+ /* Add a dummy line to terminate the function. Otherwise, the
+ * line section will stop right before the final line. */
+ debug_info.header.total_size += sizeof(debug_entry);
+ debug_info.header.total_size += 1;
+
+ fwrite(&debug_info, sizeof(debug_info), 1, file);
+
+ for (const auto &line : range.lines) {
+ debug_entry.line_addr = (Uint64)line.start;
+ debug_entry.line = line.line;
+ debug_entry.column = 0;
+
+ fwrite(&debug_entry, sizeof(debug_entry), 1, file);
+ fwrite(line.file.c_str(), line.file.size() + 1, 1, file);
+ }
+
+ debug_entry.line_addr = (Uint64)range.stop;
+ debug_entry.line = 0;
+ debug_entry.column = 0;
+
+ fwrite(&debug_entry, sizeof(debug_entry), 1, file);
+ fwrite("", 1, 1, file);
+ }
+
+ ptrdiff_t codeSize = (byte *)range.stop - (byte *)range.start;
+ size_t nameLen = range.name.size();
+
+ ASSERT(codeSize >= 0);
+
+ record.header.total_size = sizeof(record) + nameLen + 1 + codeSize;
+ record.vma = (Uint64)range.start;
+ record.code_addr = (Uint64)range.start;
+ record.code_size = (Uint64)codeSize;
+ record.code_index = ++code_index;
+ record.header.timestamp = erts_os_monotonic_time();
+
+ fwrite(&record, sizeof(record), 1, file);
+ fwrite(range.name.c_str(), nameLen + 1, 1, file);
+ fwrite(range.start, codeSize, 1, file);
+ }
+
+ fflush(file);
+ }
+};
+
+# endif /* HAVE_LINUX_PERF_SUPPORT */
+
+class JitPerfMap {
+ FILE *file = nullptr;
+
+public:
+ bool init() {
+ char name[MAXPATHLEN];
+ snprintf(name, sizeof(name), "/tmp/perf-%i.map", getpid());
+ file = fopen(name, "w");
+ if (!file) {
+ int saved_errno = errno;
+ erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
+ erts_dsprintf(dsbuf,
+ "perf: Failed to open %s (%d)",
+ name,
+ saved_errno);
+ erts_send_error_to_logger_nogl(dsbuf);
+ return false;
+ }
+ return true;
+ }
+
+ void update(const std::vector<BeamAssembler::AsmRange> &ranges) {
+ for (const auto &range : ranges) {
+ char *start = (char *)range.start, *stop = (char *)range.stop;
+ ptrdiff_t size = stop - start;
+ fprintf(file, "%p %tx $%s\n", start, size, range.name.c_str());
+ }
+ fflush(file);
+ }
+};
+
+class JitPerfSupport {
+ enum PerfModes { NONE = 0, MAP = (1 << 0), DUMP = (1 << 1) };
+
+ int modes;
+
+ erts_mtx_t mutex;
+# ifdef HAVE_LINUX_PERF_DUMP_SUPPORT
+ JitPerfDump perf_dump;
+# endif
+ JitPerfMap perf_map;
+
+public:
+ JitPerfSupport() : modes(NONE) {
+ }
+ void init() {
+ modes = JitPerfSupport::NONE;
+# ifdef HAVE_LINUX_PERF_DUMP_SUPPORT
+ if ((erts_jit_perf_support & BEAMASM_PERF_DUMP) && perf_dump.init()) {
+ modes |= JitPerfSupport::DUMP;
+ }
+# endif
+ if ((erts_jit_perf_support & BEAMASM_PERF_MAP) && perf_map.init()) {
+ modes |= JitPerfSupport::MAP;
+ }
+
+ erts_mtx_init(&mutex,
+ "perf",
+ NIL,
+ ERTS_LOCK_FLAGS_PROPERTY_STATIC |
+ ERTS_LOCK_FLAGS_CATEGORY_GENERIC);
+ }
+
+ void update(const std::vector<BeamAssembler::AsmRange> &ranges) {
+ if (modes) {
+ erts_mtx_lock(&mutex);
+# ifdef HAVE_LINUX_PERF_DUMP_SUPPORT
+ if (modes & DUMP) {
+ perf_dump.update(ranges);
+ }
+# endif
+ if (modes & MAP) {
+ perf_map.update(ranges);
+ }
+ erts_mtx_unlock(&mutex);
+ }
+ }
+};
+
+static JitPerfSupport perf;
+#endif /* HAVE_LINUX_PERF_SUPPORT */
+
+void beamasm_metadata_early_init() {
+#ifdef HAVE_GDB_SUPPORT
+ beamasm_init_early_gdb();
+#endif
+
+#ifdef HAVE_LINUX_PERF_SUPPORT
+ perf.init();
+#endif
+}
+
+void beamasm_metadata_late_init() {
+#ifdef HAVE_GDB_SUPPORT
+ beamasm_init_late_gdb();
+#endif
+}
+
+void beamasm_metadata_update(
+ std::string module_name,
+ ErtsCodePtr base_address,
+ size_t code_size,
+ const std::vector<BeamAssembler::AsmRange> &ranges) {
+#ifdef HAVE_LINUX_PERF_SUPPORT
+ perf.update(ranges);
+#endif
+
+#ifdef HAVE_GDB_SUPPORT
+ beamasm_update_gdb_info(module_name, base_address, code_size, ranges);
+#endif
+}
diff --git a/erts/emulator/beam/jit/load.h b/erts/emulator/beam/jit/load.h
index a3d099bb04..819553ca54 100644
--- a/erts/emulator/beam/jit/load.h
+++ b/erts/emulator/beam/jit/load.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,9 +25,11 @@
* Type for a label.
*/
typedef struct {
- Uint value; /* Value of label (0 if not known yet). */
- Uint looprec_targeted; /* Non-zero if this label is the target of a
- * loop_rec instruction. */
+ Uint value; /* Value of label (0 if not known yet). */
+ int looprec_targeted; /* Non-zero if this label is the target of a
+ * loop_rec instruction. */
+ int lambda_index; /* The lambda index of this label, or -1 if not
+ * a target of a lambda. */
} Label;
/*
@@ -41,8 +43,6 @@ typedef struct {
/* This structure contains all information about the module being loaded. */
struct LoaderState_ {
- ErlDrvBinary *bin; /* Binary holding BEAM file (or NULL) */
-
/*
* The following are used mainly for diagnostics.
*/
@@ -90,8 +90,6 @@ struct LoaderState_ {
int function_number;
int last_label;
- int otp_20_or_higher;
-
BeamOpAllocator op_allocator;
BeamFile beam;
};
diff --git a/erts/emulator/beam/jit/x86/beam_asm.cpp b/erts/emulator/beam/jit/x86/beam_asm.cpp
deleted file mode 100644
index 51d3a7db07..0000000000
--- a/erts/emulator/beam/jit/x86/beam_asm.cpp
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2020-2022. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-#include "beam_asm.hpp"
-
-extern "C"
-{
-#include "bif.h"
-#include "beam_common.h"
-#include "code_ix.h"
-#include "export.h"
-}
-
-/* Global configuration variables (under the `+J` prefix) */
-#ifdef HAVE_LINUX_PERF_SUPPORT
-int erts_jit_perf_support;
-#endif
-
-/*
- * Special Beam instructions.
- */
-
-ErtsCodePtr beam_apply;
-ErtsCodePtr beam_normal_exit;
-ErtsCodePtr beam_exit;
-ErtsCodePtr beam_export_trampoline;
-ErtsCodePtr beam_bif_export_trap;
-ErtsCodePtr beam_continue_exit;
-ErtsCodePtr beam_save_calls;
-
-/* NOTE These should be the only variables containing trace instructions.
-** Sometimes tests are for the instruction value, and sometimes
-** for the variable reference (one of these), and rogue references
-** will most likely cause chaos.
-*/
-ErtsCodePtr beam_return_to_trace; /* OpCode(i_return_to_trace) */
-ErtsCodePtr beam_return_trace; /* OpCode(i_return_trace) */
-ErtsCodePtr beam_exception_trace; /* UGLY also OpCode(i_return_trace) */
-ErtsCodePtr beam_return_time_trace; /* OpCode(i_return_time_trace) */
-
-static JitAllocator *jit_allocator;
-
-static BeamGlobalAssembler *bga;
-static BeamModuleAssembler *bma;
-static CpuInfo cpuinfo;
-
-static void beamasm_init_gdb_jit_info(void);
-
-/*
- * Enter all BIFs into the export table.
- *
- * Note that they will all call the error_handler until their modules have been
- * loaded, which may prevent the system from booting if BIFs from non-preloaded
- * modules are apply/3'd while loading code. Ordinary BIF calls will work fine
- * however since they won't go through export entries.
- */
-static void install_bifs(void) {
- typedef Eterm (*bif_func_type)(Process *, Eterm *, ErtsCodePtr);
- int i;
-
- ASSERT(beam_export_trampoline != NULL);
- ASSERT(beam_save_calls != NULL);
-
- for (i = 0; i < BIF_SIZE; i++) {
- BifEntry *entry;
- Export *ep;
- int j;
-
- entry = &bif_table[i];
-
- ep = erts_export_put(entry->module, entry->name, entry->arity);
-
- ep->info.op = op_i_func_info_IaaI;
- ep->info.mfa.module = entry->module;
- ep->info.mfa.function = entry->name;
- ep->info.mfa.arity = entry->arity;
- ep->bif_number = i;
-
- for (j = 0; j < ERTS_NUM_CODE_IX; j++) {
- erts_activate_export_trampoline(ep, j);
- }
-
- /* Set up a hidden export entry so we can trap to this BIF without
- * it being seen when tracing. */
- erts_init_trap_export(BIF_TRAP_EXPORT(i),
- entry->module,
- entry->name,
- entry->arity,
- (bif_func_type)entry->f);
- }
-}
-
-static JitAllocator *create_allocator(JitAllocator::CreateParams *params) {
- void *test_ro, *test_rw;
- Error err;
-
- auto *allocator = new JitAllocator(params);
-
- err = allocator->alloc(&test_ro, &test_rw, 1);
- allocator->release(test_ro);
-
- if (err == ErrorCode::kErrorOk) {
- return allocator;
- }
-
- delete allocator;
- return nullptr;
-}
-
-static JitAllocator *pick_allocator() {
- JitAllocator::CreateParams single_params;
- single_params.reset();
-
-#if defined(HAVE_LINUX_PERF_SUPPORT)
- /* `perf` has a hard time showing symbols for dual-mapped memory, so we'll
- * use single-mapped memory when enabled. */
- if (erts_jit_perf_support & (BEAMASM_PERF_DUMP | BEAMASM_PERF_MAP)) {
- if (auto *alloc = create_allocator(&single_params)) {
- return alloc;
- }
-
- ERTS_INTERNAL_ERROR("jit: Failed to allocate executable+writable "
- "memory. Either allow this or disable the "
- "'+JPperf' option.");
- }
-#endif
-
-#if !defined(VALGRIND)
- /* Default to dual-mapped memory with separate executable and writable
- * regions of the same code. This is required for platforms that enforce
- * W^X, and we prefer it when available to catch errors sooner.
- *
- * `blockSize` is analogous to "carrier size," and we pick something
- * much larger than the default since dual-mapping implies having one
- * file descriptor per block on most platforms. The block sizes do grow
- * over time, but we don't want to waste half a dozen fds just to get to
- * the shell on platforms that are very fd-constrained. */
- JitAllocator::CreateParams dual_params;
-
- dual_params.reset();
- dual_params.options = JitAllocatorOptions::kUseDualMapping,
- dual_params.blockSize = 4 << 20;
-
- if (auto *alloc = create_allocator(&dual_params)) {
- return alloc;
- } else if (auto *alloc = create_allocator(&single_params)) {
- return alloc;
- }
-
- ERTS_INTERNAL_ERROR("jit: Cannot allocate executable memory. Use the "
- "interpreter instead.");
-#elif defined(VALGRIND)
- if (auto *alloc = create_allocator(&single_params)) {
- return alloc;
- }
-
- ERTS_INTERNAL_ERROR("jit: the valgrind emulator requires the ability to "
- "allocate executable+writable memory.");
-#endif
-}
-
-void beamasm_init() {
- unsigned label = 1;
-
- ASSERT(bga == nullptr && bma == nullptr);
-
- struct operands {
- Eterm name;
- BeamInstr operand;
- ErtsCodePtr *target;
- };
-
- std::vector<struct operands> operands = {
- {am_exit, op_error_action_code, &beam_exit},
- {am_continue_exit, op_continue_exit, &beam_continue_exit},
- {am_return_trace, op_return_trace, &beam_return_trace},
- {am_return_to_trace, op_i_return_to_trace, &beam_return_to_trace},
- {am_return_time_trace,
- op_i_return_time_trace,
- &beam_return_time_trace},
- {am_exception_trace, op_return_trace, &beam_exception_trace}};
-
- Eterm mod_name;
- ERTS_DECL_AM(erts_beamasm);
- mod_name = AM_erts_beamasm;
-
- beamasm_init_perf();
- beamasm_init_gdb_jit_info();
-
- /*
- * Ensure that commonly used fields in the PCB can be accessed with
- * short instructions. Before removing any of these assertions, please
- * consider the effect it will have on code size and/or performance.
- */
-
- ERTS_CT_ASSERT(offsetof(Process, htop) < 128);
- ERTS_CT_ASSERT(offsetof(Process, stop) < 128);
- ERTS_CT_ASSERT(offsetof(Process, fcalls) < 128);
- ERTS_CT_ASSERT(offsetof(Process, freason) < 128);
- ERTS_CT_ASSERT(offsetof(Process, fvalue) < 128);
-
- cpuinfo = CpuInfo::host();
-
- jit_allocator = pick_allocator();
-
- bga = new BeamGlobalAssembler(jit_allocator);
-
- bma = new BeamModuleAssembler(bga, mod_name, 4 + operands.size() * 2);
-
- for (auto &op : operands) {
- unsigned func_label, entry_label;
-
- func_label = label++;
- entry_label = label++;
-
- bma->emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, func_label),
- ArgVal(ArgVal::u, sizeof(UWord))});
- bma->emit(op_i_func_info_IaaI,
- {ArgVal(ArgVal::i, func_label),
- ArgVal(ArgVal::i, am_erts_internal),
- ArgVal(ArgVal::i, op.name),
- ArgVal(ArgVal::i, 0)});
- bma->emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, entry_label),
- ArgVal(ArgVal::u, sizeof(UWord))});
- bma->emit(op.operand, {});
-
- op.operand = entry_label;
- }
-
- {
- unsigned func_label, apply_label, normal_exit_label;
-
- func_label = label++;
- apply_label = label++;
- normal_exit_label = label++;
-
- bma->emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, func_label),
- ArgVal(ArgVal::u, sizeof(UWord))});
- bma->emit(op_i_func_info_IaaI,
- {ArgVal(ArgVal::i, func_label),
- ArgVal(ArgVal::i, am_erts_internal),
- ArgVal(ArgVal::i, am_apply),
- ArgVal(ArgVal::i, 3)});
- bma->emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, apply_label),
- ArgVal(ArgVal::u, sizeof(UWord))});
- bma->emit(op_i_apply, {});
- bma->emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, normal_exit_label),
- ArgVal(ArgVal::u, sizeof(UWord))});
- bma->emit(op_normal_exit, {});
-
- bma->emit(op_int_code_end, {});
-
- {
- /* We have no need of the module pointers as we use `getCode(...)`
- * for everything, and the code will live as long as the emulator
- * itself. */
- const void *_ignored_exec;
- void *_ignored_rw;
- bma->codegen(jit_allocator, &_ignored_exec, &_ignored_rw);
- }
-
- beam_apply = bma->getCode(apply_label);
- beam_normal_exit = bma->getCode(normal_exit_label);
- }
-
- for (auto op : operands) {
- if (op.target) {
- *op.target = bma->getCode(op.operand);
- }
- }
-
- /* This instruction relies on register contents, and can only be reached
- * from a `call_ext_*`-instruction, hence the lack of a wrapper function. */
- beam_save_calls = (ErtsCodePtr)bga->get_dispatch_save_calls();
- beam_export_trampoline = (ErtsCodePtr)bga->get_export_trampoline();
- beam_bif_export_trap = (ErtsCodePtr)bga->get_bif_export_trap();
-}
-
-bool BeamAssembler::hasCpuFeature(uint32_t featureId) {
- return cpuinfo.hasFeature(featureId);
-}
-
-void init_emulator(void) {
- install_bifs();
-}
-
-void process_main(ErtsSchedulerData *esdp) {
- typedef void (*pmain_type)(ErtsSchedulerData *);
-
- pmain_type pmain = (pmain_type)bga->get_process_main();
- pmain(esdp);
-}
-
-#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
-static Process *erts_debug_schedule(ErtsSchedulerData *esdp,
- Process *c_p,
- int calls) {
- PROCESS_MAIN_CHK_LOCKS(c_p);
- ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- c_p = erts_schedule(esdp, c_p, calls);
- ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
- ERTS_REQ_PROC_MAIN_LOCK(c_p);
- PROCESS_MAIN_CHK_LOCKS(c_p);
- return c_p;
-}
-#endif
-
-/* void process_main(ErtsSchedulerData *esdp); */
-void BeamGlobalAssembler::emit_process_main() {
- Label context_switch_local = a.newLabel(),
- context_switch_simplified_local = a.newLabel(),
- do_schedule_local = a.newLabel(), schedule_next = a.newLabel();
-
- const x86::Mem start_time_i =
- getSchedulerRegRef(offsetof(ErtsSchedulerRegisters, start_time_i));
- const x86::Mem start_time =
- getSchedulerRegRef(offsetof(ErtsSchedulerRegisters, start_time));
-
- /* Allocate the register structure on the stack to allow computing the
- * runtime stack address from it, greatly reducing the cost of stack
- * swapping. */
- a.sub(x86::rsp, imm(sizeof(ErtsSchedulerRegisters) + ERTS_CACHE_LINE_SIZE));
- a.and_(x86::rsp, imm(~ERTS_CACHE_LINE_MASK));
-
- a.mov(x86::qword_ptr(ARG1, offsetof(ErtsSchedulerData, registers)),
- x86::rsp);
-
- /* Center `registers` at the base of x_reg_array so we can use negative
- * 8-bit displacement to address the commonly used aux_regs, located at the
- * start of the ErtsSchedulerRegisters struct. */
- a.lea(registers,
- x86::qword_ptr(x86::rsp,
- offsetof(ErtsSchedulerRegisters, x_reg_array.d)));
-
-#if defined(DEBUG) && defined(NATIVE_ERLANG_STACK)
- /* Save stack bounds so they can be tested without clobbering anything. */
- a.call(erts_get_stacklimit);
-
- a.mov(getSchedulerRegRef(
- offsetof(ErtsSchedulerRegisters, runtime_stack_end)),
- RET);
- a.mov(getSchedulerRegRef(
- offsetof(ErtsSchedulerRegisters, runtime_stack_start)),
- x86::rsp);
-#elif !defined(NATIVE_ERLANG_STACK)
- /* Save the initial SP of the thread so that we can verify that it
- * doesn't grow. */
-# ifdef JIT_HARD_DEBUG
- a.mov(getInitialSPRef(), x86::rsp);
-# endif
-
- /* Manually do an `emit_enter_runtime` to match the `emit_leave_runtime`
- * below. We avoid `emit_enter_runtime` because it may do additional
- * assertions that may currently fail.
- *
- * IMPORTANT: We must ensure that this sequence leaves the stack
- * aligned on a 16-byte boundary. */
- a.mov(getRuntimeStackRef(), x86::rsp);
- a.sub(x86::rsp, imm(15));
- a.and_(x86::rsp, imm(-16));
-#endif
-
- load_erl_bits_state(ARG1);
- runtime_call<1>(erts_bits_init_state);
-
- a.mov(start_time_i, imm(0));
- a.mov(start_time, imm(0));
-
- mov_imm(c_p, 0);
- mov_imm(FCALLS, 0);
- mov_imm(ARG3, 0); /* Set reds_used for erts_schedule call */
-
- a.jmp(schedule_next);
-
- a.bind(do_schedule_local);
- {
- /* Figure out reds_used. def_arg_reg[5] = REDS_IN */
- a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, def_arg_reg[5])));
- a.sub(ARG3, FCALLS);
-
- a.jmp(schedule_next);
- }
-
- a.bind(context_switch_local);
- comment("Context switch, unknown arity/MFA");
- {
- Sint arity_offset = offsetof(ErtsCodeMFA, arity) - sizeof(ErtsCodeMFA);
-
- a.mov(ARG1, x86::qword_ptr(ARG3, arity_offset));
- a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), ARG1);
-
- a.lea(ARG1, x86::qword_ptr(ARG3, -(Sint)sizeof(ErtsCodeMFA)));
- a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), ARG1);
-
- /* !! Fall through !! */
- }
-
- a.bind(context_switch_simplified_local);
- comment("Context switch, known arity and MFA");
- {
- Label not_exiting = a.newLabel();
-
-#ifdef DEBUG
- Label check_i = a.newLabel();
- /* Check that ARG3 is set to a valid CP. */
- a.test(ARG3, imm(_CPMASK));
- a.je(check_i);
- a.ud2();
- a.bind(check_i);
-#endif
-
- a.mov(x86::qword_ptr(c_p, offsetof(Process, i)), ARG3);
-
-#ifdef WIN32
- a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.value)));
-#else
- a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.counter)));
-#endif
-
- a.test(ARG1d, imm(ERTS_PSFLG_EXITING));
- a.short_().je(not_exiting);
- {
- comment("Process exiting");
-
- /* We load the beam_exit from memory because it has not yet been set
- * when the global assembler is created. */
- a.mov(ARG1, imm(&beam_exit));
- a.mov(ARG1, x86::qword_ptr(ARG1));
- a.mov(x86::qword_ptr(c_p, offsetof(Process, i)), ARG1);
- a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), imm(0));
- a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), imm(0));
- a.jmp(do_schedule_local);
- }
- a.bind(not_exiting);
-
- /* Figure out reds_used. def_arg_reg[5] = REDS_IN */
- a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, def_arg_reg[5])));
- a.sub(ARG3, FCALLS);
-
- /* Spill reds_used to FCALLS as we no longer need that value */
- a.mov(FCALLS, ARG3);
-
- a.mov(ARG1, c_p);
- load_x_reg_array(ARG2);
- runtime_call<2>(copy_out_registers);
-
- /* Restore reds_used from FCALLS */
- a.mov(ARG3, FCALLS);
-
- /* !! Fall through !! */
- }
-
- a.bind(schedule_next);
- comment("schedule_next");
- {
- Label schedule = a.newLabel(), skip_long_schedule = a.newLabel();
-
- /* ARG3 contains reds_used at this point */
-
- a.cmp(start_time, imm(0));
- a.short_().je(schedule);
- {
- a.mov(ARG1, c_p);
- a.mov(ARG2, start_time);
-
- /* Spill reds_used in start_time slot */
- a.mov(start_time, ARG3);
-
- a.mov(ARG3, start_time_i);
- runtime_call<3>(check_monitor_long_schedule);
-
- /* Restore reds_used */
- a.mov(ARG3, start_time);
- }
- a.bind(schedule);
-
- mov_imm(ARG1, 0);
- a.mov(ARG2, c_p);
-#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
- runtime_call<3>(erts_debug_schedule);
-#else
- runtime_call<3>(erts_schedule);
-#endif
- a.mov(c_p, RET);
-
-#ifdef ERTS_MSACC_EXTENDED_STATES
- a.lea(ARG1,
- x86::qword_ptr(registers,
- offsetof(ErtsSchedulerRegisters,
- aux_regs.d.erts_msacc_cache)));
- runtime_call<1>(erts_msacc_update_cache);
-#endif
-
- a.mov(ARG1, imm((UWord)&erts_system_monitor_long_schedule));
- a.cmp(x86::qword_ptr(ARG1), imm(0));
- a.mov(start_time, imm(0));
- a.short_().je(skip_long_schedule);
- {
- /* Enable long schedule test */
- runtime_call<0>(erts_timestamp_millis);
- a.mov(start_time, RET);
- a.mov(RET, x86::qword_ptr(c_p, offsetof(Process, i)));
- a.mov(start_time_i, RET);
- }
- a.bind(skip_long_schedule);
-
- /* Copy arguments */
- a.mov(ARG1, c_p);
- load_x_reg_array(ARG2);
- runtime_call<2>(copy_in_registers);
-
- /* Setup reduction counting */
- a.mov(FCALLS, x86::qword_ptr(c_p, offsetof(Process, fcalls)));
- a.mov(x86::qword_ptr(c_p, offsetof(Process, def_arg_reg[5])), FCALLS);
-
-#ifdef DEBUG
- a.mov(x86::qword_ptr(c_p, offsetof(Process, debug_reds_in)), FCALLS);
-#endif
-
- /* Check whether save calls is on */
- a.mov(ARG1, c_p);
- a.mov(ARG2, imm(ERTS_PSD_SAVED_CALLS_BUF));
- runtime_call<2>(erts_psd_get);
-
- /* Read the active code index, overriding it with
- * ERTS_SAVE_CALLS_CODE_IX when save_calls is enabled (RET != 0). */
- a.test(RET, RET);
- a.mov(ARG1, imm(&the_active_code_index));
- a.mov(ARG2, imm(ERTS_SAVE_CALLS_CODE_IX));
- a.mov(active_code_ix.r32(), x86::dword_ptr(ARG1));
- a.cmovnz(active_code_ix, ARG2);
-
- /* Start executing the Erlang process. Note that reductions have
- * already been set up above. */
- emit_leave_runtime<Update::eStack | Update::eHeap>();
-
- /* Check if we are just returning from a dirty nif/bif call and if so we
- * need to do a bit of cleaning up before continuing. */
- a.mov(RET, x86::qword_ptr(c_p, offsetof(Process, i)));
- a.cmp(x86::qword_ptr(RET), imm(op_call_nif_WWW));
- a.je(labels[dispatch_nif]);
- a.cmp(x86::qword_ptr(RET), imm(op_call_bif_W));
- a.je(labels[dispatch_bif]);
- a.jmp(RET);
- }
-
- /* Processes may jump to the exported entry points below, executing on the
- * Erlang stack when entering. These are separate from the `_local` labels
- * above as we don't want to worry about which stack we're on when the
- * cases overlap. */
-
- /* `ga->get_context_switch()`
- *
- * The *next* instruction pointer is provided in ARG3, and must be preceded
- * by an ErtsCodeMFA. */
- a.bind(labels[context_switch]);
- {
- emit_enter_runtime<Update::eStack | Update::eHeap>();
-
- a.jmp(context_switch_local);
- }
-
- /* `ga->get_context_switch_simplified()`
- *
- * The next instruction pointer is provided in ARG3, which does not need to
- * point past an ErtsCodeMFA as the process structure has already been
- * updated. */
- a.bind(labels[context_switch_simplified]);
- {
- emit_enter_runtime<Update::eStack | Update::eHeap>();
-
- a.jmp(context_switch_simplified_local);
- }
-
- /* `ga->get_do_schedule()`
- *
- * `c_p->i` must be set prior to jumping here. */
- a.bind(labels[do_schedule]);
- {
- emit_enter_runtime<Update::eStack | Update::eHeap>();
-
- a.jmp(do_schedule_local);
- }
-}
-
-enum jit_actions : uint32_t {
- JIT_NOACTION = 0,
- JIT_REGISTER_FN,
- JIT_UNREGISTER_FN,
-};
-
-struct jit_code_entry {
- struct jit_code_entry *next_entry;
- struct jit_code_entry *prev_entry;
- const char *symfile_addr;
- uint64_t symfile_size;
-};
-
-struct jit_descriptor {
- uint32_t version;
- jit_actions action_flag;
- struct jit_code_entry *relevant_entry;
- struct jit_code_entry *first_entry;
- erts_mtx_t mutex;
-};
-
-extern "C"
-{
- extern void ERTS_NOINLINE __jit_debug_register_code(void);
-
- /* Make sure to specify the version statically, because the
- * debugger may check the version before we can set it. */
- struct jit_descriptor __jit_debug_descriptor = {1,
- JIT_NOACTION,
- NULL,
- NULL};
-} /* extern "C" */
-
-static void beamasm_init_gdb_jit_info(void) {
- Sint symfile_size = sizeof(uint64_t) * 2;
- uint64_t *symfile = (uint64_t *)malloc(symfile_size);
- jit_code_entry *entry;
-
- symfile[0] = 0;
- symfile[1] = (uint64_t)beam_normal_exit;
-
- entry = (jit_code_entry *)malloc(sizeof(jit_code_entry));
-
- /* Add address description */
- entry->symfile_addr = (char *)symfile;
- entry->symfile_size = symfile_size;
-
- /* Insert into linked list */
- entry->next_entry = __jit_debug_descriptor.first_entry;
- if (entry->next_entry) {
- entry->next_entry->prev_entry = entry;
- } else {
- entry->prev_entry = nullptr;
- }
-
- /* register with dbg */
- __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
- __jit_debug_descriptor.first_entry = entry;
- __jit_debug_descriptor.relevant_entry = entry;
- __jit_debug_register_code();
-
- erts_mtx_init(&__jit_debug_descriptor.mutex,
- "jit_debug_descriptor",
- NIL,
- (ERTS_LOCK_FLAGS_PROPERTY_STATIC |
- ERTS_LOCK_FLAGS_CATEGORY_GENERIC));
-}
-
-void BeamAssembler::update_gdb_jit_info(std::string modulename,
- std::vector<AsmRange> &functions) {
- Sint symfile_size = sizeof(uint64_t) * 3 + modulename.size() + 1;
-
- for (auto fun : functions) {
- symfile_size += sizeof(uint64_t) * 2;
- symfile_size += fun.name.size() + 1;
- }
-
- char *symfile = (char *)malloc(symfile_size);
- jit_code_entry *entry;
-
- entry = (jit_code_entry *)malloc(sizeof(jit_code_entry));
-
- /* Add address description */
- entry->symfile_addr = symfile;
- entry->symfile_size = symfile_size;
-
- ((uint64_t *)symfile)[0] = functions.size();
- ((uint64_t *)symfile)[1] = code.baseAddress();
- ((uint64_t *)symfile)[2] = (uint64_t)code.codeSize();
-
- symfile += sizeof(uint64_t) * 3;
-
- sys_memcpy(symfile, modulename.c_str(), modulename.size() + 1);
- symfile += modulename.size() + 1;
-
- for (unsigned i = 0; i < functions.size(); i++) {
- ((uint64_t *)symfile)[0] = (uint64_t)functions[i].start;
- ((uint64_t *)symfile)[1] = (uint64_t)functions[i].stop;
-
- ASSERT(functions[i].start <= functions[i].stop);
-
- symfile += sizeof(uint64_t) * 2;
-
- sys_memcpy(symfile,
- functions[i].name.c_str(),
- functions[i].name.size() + 1);
- symfile += functions[i].name.size() + 1;
- }
-
- ASSERT(symfile_size == (symfile - entry->symfile_addr));
-
- /* Insert into linked list */
- erts_mtx_lock(&__jit_debug_descriptor.mutex);
- entry->next_entry = __jit_debug_descriptor.first_entry;
- if (entry->next_entry) {
- entry->next_entry->prev_entry = entry;
- } else {
- entry->prev_entry = nullptr;
- }
-
- /* register with dbg */
- __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
- __jit_debug_descriptor.first_entry = entry;
- __jit_debug_descriptor.relevant_entry = entry;
- __jit_debug_register_code();
- erts_mtx_unlock(&__jit_debug_descriptor.mutex);
-}
-
-extern "C"
-{
- int erts_beam_jump_table(void) {
-#if defined(NO_JUMP_TABLE)
- return 0;
-#else
- return 1;
-#endif
- }
-
- void *beamasm_new_assembler(Eterm mod, int num_labels, int num_functions) {
- return new BeamModuleAssembler(bga, mod, num_labels, num_functions);
- }
-
- int beamasm_emit(void *instance, unsigned specific_op, BeamOp *op) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- const std::vector<ArgVal> args(&op->a[0], &op->a[op->arity]);
-
- return ba->emit(specific_op, args);
- }
-
- void beamasm_emit_call_nif(const ErtsCodeInfo *info,
- void *normal_fptr,
- void *lib,
- void *dirty_fptr,
- char *buff,
- unsigned buff_len) {
- BeamModuleAssembler ba(bga, info->mfa.module, 3);
-
- ba.emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, 1), ArgVal(ArgVal::u, sizeof(UWord))});
- ba.emit(op_i_func_info_IaaI,
- {ArgVal(ArgVal::i, 1),
- ArgVal(ArgVal::i, info->mfa.module),
- ArgVal(ArgVal::i, info->mfa.function),
- ArgVal(ArgVal::i, info->mfa.arity)});
- ba.emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, 2), ArgVal(ArgVal::u, sizeof(UWord))});
- ba.emit(op_i_breakpoint_trampoline, {});
- ba.emit(op_call_nif_WWW,
- {ArgVal(ArgVal::i, (BeamInstr)normal_fptr),
- ArgVal(ArgVal::i, (BeamInstr)lib),
- ArgVal(ArgVal::i, (BeamInstr)dirty_fptr)});
-
- ba.codegen(buff, buff_len);
- }
-
- void beamasm_emit_call_bif(const ErtsCodeInfo *info,
- Eterm (*bif)(BIF_ALIST),
- char *buff,
- unsigned buff_len) {
- BeamModuleAssembler ba(bga, info->mfa.module, 3);
-
- ba.emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, 1), ArgVal(ArgVal::u, sizeof(UWord))});
- ba.emit(op_i_func_info_IaaI,
- {ArgVal(ArgVal::i, 1),
- ArgVal(ArgVal::i, info->mfa.module),
- ArgVal(ArgVal::i, info->mfa.function),
- ArgVal(ArgVal::i, info->mfa.arity)});
- ba.emit(op_aligned_label_Lt,
- {ArgVal(ArgVal::i, 2), ArgVal(ArgVal::u, sizeof(UWord))});
- ba.emit(op_i_breakpoint_trampoline, {});
- ba.emit(op_call_bif_W, {ArgVal(ArgVal::i, (BeamInstr)bif)});
-
- ba.codegen(buff, buff_len);
- }
-
- void beamasm_delete_assembler(void *instance) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- delete ba;
- }
-
- void beamasm_purge_module(const void *native_module_exec,
- void *native_module_rw) {
- jit_allocator->release(const_cast<void *>(native_module_exec));
- }
-
- ErtsCodePtr beamasm_get_code(void *instance, int label) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- return reinterpret_cast<ErtsCodePtr>(ba->getCode(label));
- }
-
- const byte *beamasm_get_rodata(void *instance, char *label) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- return reinterpret_cast<const byte *>(ba->getCode(label));
- }
-
- void beamasm_embed_rodata(void *instance,
- const char *labelName,
- const char *buff,
- size_t size) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- if (size) {
- ba->embed_rodata(labelName, buff, size);
- }
- }
-
- void beamasm_embed_bss(void *instance, char *labelName, size_t size) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- if (size) {
- ba->embed_bss(labelName, size);
- }
- }
-
- void beamasm_codegen(void *instance,
- const void **native_module_exec,
- void **native_module_rw,
- const BeamCodeHeader *in_hdr,
- const BeamCodeHeader **out_exec_hdr,
- BeamCodeHeader **out_rw_hdr) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
-
- ba->codegen(jit_allocator,
- native_module_exec,
- native_module_rw,
- in_hdr,
- out_exec_hdr,
- out_rw_hdr);
- }
-
- Uint beamasm_get_header(void *instance, const BeamCodeHeader **hdr) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
-
- *hdr = ba->getCodeHeader();
-
- return ba->getCodeSize();
- }
-
- char *beamasm_get_base(void *instance) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- return (char *)ba->getBaseAddress();
- }
-
- size_t beamasm_get_offset(void *instance) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- return ba->getOffset();
- }
-
- const ErtsCodeInfo *beamasm_get_on_load(void *instance) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- return ba->getOnLoad();
- }
-
- unsigned int beamasm_patch_catches(void *instance, char *rw_base) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- return ba->patchCatches(rw_base);
- }
-
- void beamasm_patch_import(void *instance,
- char *rw_base,
- int index,
- BeamInstr import) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- ba->patchImport(rw_base, index, import);
- }
-
- void beamasm_patch_literal(void *instance,
- char *rw_base,
- int index,
- Eterm lit) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- ba->patchLiteral(rw_base, index, lit);
- }
-
- void beamasm_patch_lambda(void *instance,
- char *rw_base,
- int index,
- BeamInstr fe) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- ba->patchLambda(rw_base, index, fe);
- }
-
- void beamasm_patch_strings(void *instance,
- char *rw_base,
- const byte *string_table) {
- BeamModuleAssembler *ba = static_cast<BeamModuleAssembler *>(instance);
- ba->patchStrings(rw_base, string_table);
- }
-}
-
-const uint8_t *BeamAssembler::nops[3] = {nop1, nop2, nop3};
-const uint8_t BeamAssembler::nop1[1] = {0x90};
-const uint8_t BeamAssembler::nop2[2] = {0x66, 0x90};
-const uint8_t BeamAssembler::nop3[3] = {0x0F, 0x1F, 0x00};
diff --git a/erts/emulator/beam/jit/x86/beam_asm.hpp b/erts/emulator/beam/jit/x86/beam_asm.hpp
index 813305c969..66891730ef 100644
--- a/erts/emulator/beam/jit/x86/beam_asm.hpp
+++ b/erts/emulator/beam/jit/x86/beam_asm.hpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,8 @@
#include <vector>
#include <unordered_map>
#include <map>
+#include <algorithm>
+#include <cmath>
#ifndef ASMJIT_ASMJIT_H_INCLUDED
# include <asmjit/asmjit.hpp>
@@ -37,12 +39,17 @@ extern "C"
#include "erl_vm.h"
#include "global.h"
#include "beam_catches.h"
+#include "big.h"
#include "beam_asm.h"
}
#include "beam_jit_common.hpp"
+/* On Windows, the min and max macros may be defined. */
+#undef min
+#undef max
+
using namespace asmjit;
class BeamAssembler : public ErrorHandler {
@@ -69,16 +76,18 @@ protected:
* when running on the runtime stack. */
const x86::Gp E = x86::rsp;
- /* Cached copy of Erlang stack pointer used to speed up stack switches when
- * we know that the runtime doesn't read or modify the Erlang stack.
- *
- * If we find ourselves pressed for registers in the future, we could save
- * this in the same slot as `registers` as that can be trivially recomputed
- * from the top of the runtime stack. */
- const x86::Gp E_saved = x86::r12;
+# ifdef ERLANG_FRAME_POINTERS
+ /* Current frame pointer, used when we emit native stack frames (e.g. to
+ * better support `perf`). */
+ const x86::Gp frame_pointer = x86::rbp;
+# endif
+ /* When we're not using frame pointers, we can keep the Erlang stack in
+ * RBP when running on the runtime stack, which is slightly faster than
+ * reading and writing from c_p->stop. */
+ const x86::Gp E_saved = x86::rbp;
#else
- const x86::Gp E = x86::r12;
+ const x86::Gp E = x86::rbp;
#endif
const x86::Gp c_p = x86::r13;
@@ -90,7 +99,7 @@ protected:
* This is set to ERTS_SAVE_CALLS_CODE_IX when save_calls is active, which
* routes us to a common handler routine that calls save_calls before
* jumping to the actual code. */
- const x86::Gp active_code_ix = x86::rbp;
+ const x86::Gp active_code_ix = x86::r12;
#ifdef ERTS_MSACC_EXTENDED_STATES
const x86::Mem erts_msacc_cache = getSchedulerRegRef(
@@ -164,102 +173,23 @@ protected:
public:
static bool hasCpuFeature(uint32_t featureId);
- BeamAssembler() : code() {
- /* Setup with default code info */
- Error err = code.init(Environment::host());
- ERTS_ASSERT(!err && "Failed to init codeHolder");
-
- err = code.newSection(&rodata,
- ".rodata",
- SIZE_MAX,
- SectionFlags::kReadOnly,
- 8);
- ERTS_ASSERT(!err && "Failed to create .rodata section");
-
- err = code.attach(&a);
-
- ERTS_ASSERT(!err && "Failed to attach codeHolder");
-#ifdef DEBUG
- a.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
-#endif
- a.addEncodingOptions(EncodingOptions::kOptimizeForSize);
- code.setErrorHandler(this);
- }
+ BeamAssembler();
+ BeamAssembler(const std::string &log);
- BeamAssembler(const std::string &log) : BeamAssembler() {
- if (erts_jit_asm_dump) {
- setLogger(log + ".asm");
- }
- }
+ ~BeamAssembler();
- ~BeamAssembler() {
- if (logger.file())
- fclose(logger.file());
- }
-
- void *getBaseAddress() {
- ASSERT(code.hasBaseAddress());
- return (void *)code.baseAddress();
- }
-
- size_t getOffset() {
- return a.offset();
- }
+ void *getBaseAddress();
+ size_t getOffset();
protected:
void _codegen(JitAllocator *allocator,
const void **executable_ptr,
- void **writable_ptr) {
- Error err = code.flatten();
- ERTS_ASSERT(!err && "Could not flatten code");
- err = code.resolveUnresolvedLinks();
- ERTS_ASSERT(!err && "Could not resolve all links");
-
- /* Verify that all labels are bound */
-#ifdef DEBUG
- for (auto e : code.labelEntries()) {
- if (!e->isBound()) {
- erts_exit(ERTS_ABORT_EXIT, "Label %s is not bound", e->name());
- }
- }
-#endif
-
- err = allocator->alloc(const_cast<void **>(executable_ptr),
- writable_ptr,
- code.codeSize() + 16);
-
- if (err == ErrorCode::kErrorTooManyHandles) {
- ERTS_ASSERT(!"Failed to allocate module code: "
- "out of file descriptors");
- } else if (err) {
- ERTS_ASSERT("Failed to allocate module code");
- }
-
- code.relocateToBase((uint64_t)*executable_ptr);
- code.copyFlattenedData(*writable_ptr,
- code.codeSize(),
- CopySectionFlags::kPadSectionBuffer);
-#ifdef DEBUG
- if (FileLogger *l = dynamic_cast<FileLogger *>(code.logger()))
- if (FILE *f = l->file())
- fprintf(f, "; CODE_SIZE: %zd\n", code.codeSize());
-#endif
- }
+ void **writable_ptr);
- void *getCode(Label label) {
- ASSERT(label.isValid());
- return (char *)getBaseAddress() + code.labelOffsetFromBase(label);
- }
-
- byte *getCode(char *labelName) {
- return (byte *)getCode(code.labelByName(labelName, strlen(labelName)));
- }
+ void *getCode(Label label);
+ byte *getCode(char *labelName);
- void handleError(Error err, const char *message, BaseEmitter *origin) {
- comment(message);
- fflush(logger.file());
- ASSERT(0 && "Fault instruction encode");
- }
+ void handleError(Error err, const char *message, BaseEmitter *origin);
constexpr x86::Mem getRuntimeStackRef() const {
int base = offsetof(ErtsSchedulerRegisters, aux_regs.d.runtime_stack);
@@ -365,6 +295,7 @@ protected:
a.short_().jle(ok);
a.bind(crash);
+ comment("Redzone touched");
a.ud2();
a.bind(ok);
@@ -412,6 +343,7 @@ protected:
Label next = a.newLabel();
a.cmp(x86::rsp, getInitialSPRef());
a.short_().je(next);
+ comment("The stack has grown");
a.ud2();
a.bind(next);
#endif
@@ -553,52 +485,47 @@ protected:
}
/* Explicitly position-independent absolute jump, for use in fragments that
- * need to be memcpy'd for performance reasons (e.g. export entries) */
+ * need to be memcpy'd for performance reasons (e.g. NIF stubs) */
template<typename T>
void pic_jmp(T(*addr)) {
a.mov(ARG6, imm(addr));
a.jmp(ARG6);
}
- constexpr x86::Mem getArgRef(const ArgVal &val,
+ constexpr x86::Mem getArgRef(const ArgRegister &arg,
size_t size = sizeof(UWord)) const {
- switch (val.getType()) {
- case ArgVal::TYPE::l:
- return getFRef(val.getValue(), size);
- case ArgVal::TYPE::x:
- return getXRef(val.getValue(), size);
- case ArgVal::TYPE::y:
- return getYRef(val.getValue(), size);
- default:
- ERTS_ASSERT(!"NYI");
- return x86::Mem();
+ if (arg.isXRegister()) {
+ return getXRef(arg.as<ArgXRegister>().get(), size);
+ } else if (arg.isYRegister()) {
+ return getYRef(arg.as<ArgYRegister>().get(), size);
}
+
+ return getFRef(arg.as<ArgFRegister>().get(), size);
}
- /* Returns the current code address for the export entry in `Src`
+ /* Returns the current code address for the `Export` or `ErlFunEntry` in
+ * `Src`.
*
- * Export tracing, save_calls, etc is implemented by shared fragments that
- * assume that the export entry is in RET, so we have to copy it over if it
- * isn't already. */
- x86::Mem emit_setup_export_call(const x86::Gp &Src) {
- return emit_setup_export_call(Src, active_code_ix);
+ * Export tracing, save_calls, etc are implemented by shared fragments that
+ * assume that the respective entry is in RET, so we have to copy it over
+ * if it isn't already. */
+ x86::Mem emit_setup_dispatchable_call(const x86::Gp &Src) {
+ return emit_setup_dispatchable_call(Src, active_code_ix);
}
- x86::Mem emit_setup_export_call(const x86::Gp &Src,
- const x86::Gp &CodeIndex) {
+ x86::Mem emit_setup_dispatchable_call(const x86::Gp &Src,
+ const x86::Gp &CodeIndex) {
if (RET != Src) {
a.mov(RET, Src);
}
- return x86::qword_ptr(RET, CodeIndex, 3, offsetof(Export, addresses));
- }
+ ERTS_CT_ASSERT(offsetof(ErlFunEntry, dispatch) == 0);
+ ERTS_CT_ASSERT(offsetof(Export, dispatch) == 0);
- /* Discards a continuation pointer, including the frame pointer if
- * applicable. */
- void emit_discard_cp() {
- emit_assert_erlang_stack();
-
- a.add(x86::rsp, imm(CP_SIZE * sizeof(Eterm)));
+ return x86::qword_ptr(RET,
+ CodeIndex,
+ 3,
+ offsetof(ErtsDispatchable, addresses));
}
void emit_assert_runtime_stack() {
@@ -623,6 +550,7 @@ protected:
a.short_().je(next);
a.bind(crash);
+ comment("Runtime stack is corrupt");
a.ud2();
a.bind(next);
@@ -643,6 +571,7 @@ protected:
a.short_().jle(next);
a.bind(crash);
+ comment("Erlang stack is corrupt");
a.ud2();
a.bind(next);
#endif
@@ -655,6 +584,36 @@ protected:
eCodeIndex = (1 << 3)
};
+ void emit_enter_frame() {
+#ifdef NATIVE_ERLANG_STACK
+ if (ERTS_UNLIKELY(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA)) {
+# ifdef ERLANG_FRAME_POINTERS
+ a.push(frame_pointer);
+ a.mov(frame_pointer, E);
+# endif
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_RA);
+ }
+#endif
+ }
+
+ void emit_leave_frame() {
+#ifdef NATIVE_ERLANG_STACK
+ if (ERTS_UNLIKELY(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA)) {
+ a.leave();
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_RA);
+ }
+#endif
+ }
+
+ void emit_unwind_frame() {
+ emit_assert_erlang_stack();
+
+ emit_leave_frame();
+ a.add(x86::rsp, imm(sizeof(UWord)));
+ }
+
template<int Spec = 0>
void emit_enter_runtime() {
emit_assert_erlang_stack();
@@ -662,46 +621,65 @@ protected:
ERTS_CT_ASSERT((Spec & (Update::eReductions | Update::eStack |
Update::eHeap)) == Spec);
-#ifdef NATIVE_ERLANG_STACK
- if (!(Spec & Update::eStack)) {
- a.mov(E_saved, E);
- }
-#endif
+ if (ERTS_LIKELY(erts_frame_layout == ERTS_FRAME_LAYOUT_RA)) {
+ if ((Spec & (Update::eHeap | Update::eStack)) ==
+ (Update::eHeap | Update::eStack)) {
+ /* To update both heap and stack we use sse instructions like
+ * gcc -O3 does. Basically it is this function run through
+ * gcc -O3:
+ *
+ * struct a { long a; long b; long c; };
+ * void test(long a, long b, long c, struct a *s) {
+ * s->a = a;
+ * s->b = b;
+ * s->c = c;
+ * } */
+ ERTS_CT_ASSERT((offsetof(Process, stop) -
+ offsetof(Process, htop)) == sizeof(Eterm *));
+ a.movq(x86::xmm0, HTOP);
+ a.movq(x86::xmm1, E);
+ a.punpcklqdq(x86::xmm0, x86::xmm1);
+ a.movups(x86::xmmword_ptr(c_p, offsetof(Process, htop)),
+ x86::xmm0);
+ } else if (Spec & Update::eHeap) {
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, htop)), HTOP);
+ } else if (Spec & Update::eStack) {
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, stop)), E);
+ }
- if ((Spec & (Update::eHeap | Update::eStack)) ==
- (Update::eHeap | Update::eStack)) {
- /* To update both heap and stack we use sse instructions like gcc
- -O3 does. Basically it is this function run through gcc -O3:
-
- struct a { long a; long b; long c; };
-
- void test(long a, long b, long c, struct a *s) {
- s->a = a;
- s->b = b;
- s->c = c;
- }
- */
- ERTS_CT_ASSERT(offsetof(Process, stop) - offsetof(Process, htop) ==
- 8);
- a.movq(x86::xmm0, HTOP);
- a.movq(x86::xmm1, E);
- if (Spec & Update::eReductions) {
- a.mov(x86::qword_ptr(c_p, offsetof(Process, fcalls)), FCALLS);
+#ifdef NATIVE_ERLANG_STACK
+ if (!(Spec & Update::eStack)) {
+ a.mov(E_saved, E);
}
- a.punpcklqdq(x86::xmm0, x86::xmm1);
- a.movups(x86::xmmword_ptr(c_p, offsetof(Process, htop)), x86::xmm0);
+#endif
} else {
- if ((Spec & Update::eStack)) {
+#ifdef ERLANG_FRAME_POINTERS
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+
+ if (Spec & Update::eStack) {
+ ERTS_CT_ASSERT((offsetof(Process, frame_pointer) -
+ offsetof(Process, stop)) == sizeof(Eterm *));
+ a.movq(x86::xmm0, E);
+ a.movq(x86::xmm1, frame_pointer);
+ a.punpcklqdq(x86::xmm0, x86::xmm1);
+ a.movups(x86::xmmword_ptr(c_p, offsetof(Process, stop)),
+ x86::xmm0);
+ } else {
+ /* We can skip updating the frame pointer whenever the process
+ * doesn't have to inspect the stack. We still need to update
+ * the stack pointer to switch stacks, though, since we don't
+ * have enough spare callee-save registers. */
a.mov(x86::qword_ptr(c_p, offsetof(Process, stop)), E);
}
if (Spec & Update::eHeap) {
a.mov(x86::qword_ptr(c_p, offsetof(Process, htop)), HTOP);
}
+#endif
+ }
- if (Spec & Update::eReductions) {
- a.mov(x86::qword_ptr(c_p, offsetof(Process, fcalls)), FCALLS);
- }
+ if (Spec & Update::eReductions) {
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, fcalls)), FCALLS);
}
#ifdef NATIVE_ERLANG_STACK
@@ -724,13 +702,25 @@ protected:
ERTS_CT_ASSERT((Spec & (Update::eReductions | Update::eStack |
Update::eHeap | Update::eCodeIndex)) == Spec);
+ if (ERTS_LIKELY(erts_frame_layout == ERTS_FRAME_LAYOUT_RA)) {
+ if (Spec & Update::eStack) {
+ a.mov(E, x86::qword_ptr(c_p, offsetof(Process, stop)));
+ } else {
#ifdef NATIVE_ERLANG_STACK
- if (!(Spec & Update::eStack)) {
- a.mov(E, E_saved);
- }
+ a.mov(E, E_saved);
#endif
- if ((Spec & Update::eStack)) {
+ }
+ } else {
+#ifdef ERLANG_FRAME_POINTERS
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+
a.mov(E, x86::qword_ptr(c_p, offsetof(Process, stop)));
+
+ if (Spec & Update::eStack) {
+ a.mov(frame_pointer,
+ x86::qword_ptr(c_p, offsetof(Process, frame_pointer)));
+ }
+#endif
}
if (Spec & Update::eHeap) {
@@ -807,12 +797,53 @@ protected:
}
}
+ /* Set the Z flag if Reg1 and Reg2 are definitely not equal based on their
+ * tags alone. (They may still be equal if both are immediates and all other
+ * bits are equal too.) */
+ void emit_is_unequal_based_on_tags(x86::Gp Reg1, x86::Gp Reg2) {
+ ASSERT(Reg1 != RET && Reg2 != RET);
+ emit_is_unequal_based_on_tags(Reg1, Reg2, RET);
+ }
+
+ void emit_is_unequal_based_on_tags(x86::Gp Reg1,
+ x86::Gp Reg2,
+ const x86::Gp &spill) {
+ ERTS_CT_ASSERT(TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK);
+ ERTS_CT_ASSERT((TAG_PRIMARY_LIST | TAG_PRIMARY_BOXED) ==
+ TAG_PRIMARY_IMMED1);
+ a.mov(RETd, Reg1.r32());
+ a.or_(RETd, Reg2.r32());
+ a.and_(RETb, imm(_TAG_PRIMARY_MASK));
+
+ /* RET will be now be TAG_PRIMARY_IMMED1 if either one or both
+ * registers are immediates, or if one register is a list and the other
+ * a boxed. */
+ a.cmp(RETb, imm(TAG_PRIMARY_IMMED1));
+ }
+
/*
* Generate the shortest instruction for setting a register to an immediate
* value. May clear flags.
*/
- void mov_imm(x86::Gp to, Uint value) {
- if (value == 0) {
+ template<typename T>
+ void mov_imm(x86::Gp to, T value) {
+ static_assert(std::is_integral<T>::value || std::is_pointer<T>::value);
+ if (value) {
+ /* Generate the shortest instruction to set the register to an
+ * immediate.
+ *
+ * 48 c7 c0 2a 00 00 00 mov rax, 42
+ * b8 2a 00 00 00 mov eax, 42
+ *
+ * 49 c7 c0 2a 00 00 00 mov r8, 42
+ * 41 b8 2a 00 00 00 mov r8d, 42
+ */
+ if (Support::isUInt32((Uint)value)) {
+ a.mov(to.r32(), imm(value));
+ } else {
+ a.mov(to, imm(value));
+ }
+ } else {
/*
* Generate the shortest instruction to set the register to zero.
*
@@ -825,34 +856,26 @@ protected:
* Note: xor clears ZF and CF; mov does not change any flags.
*/
a.xor_(to.r32(), to.r32());
- } else {
- a.mov(to, imm(value));
}
}
+ void mov_imm(x86::Gp to, std::nullptr_t value) {
+ (void)value;
+ mov_imm(to, 0);
+ }
+
public:
void embed_rodata(const char *labelName, const char *buff, size_t size);
void embed_bss(const char *labelName, size_t size);
-
void embed_zeros(size_t size);
- void setLogger(std::string log) {
- FILE *f = fopen(log.data(), "w+");
+ void setLogger(std::string log);
+ void setLogger(FILE *log);
- /* FIXME: Don't crash when loading multiple modules with the same name.
- *
- * setLogger(nullptr) disables logging. */
- if (f) {
- setvbuf(f, NULL, _IONBF, 0);
+ void comment(const char *format) {
+ if (logger.file()) {
+ a.commentf("# %s", format);
}
-
- setLogger(f);
- }
-
- void setLogger(FILE *log) {
- logger.setFile(log);
- logger.setIndentation(FormatIndentationGroup::kCode, 4);
- code.setLogger(&logger);
}
template<typename... Ts>
@@ -867,150 +890,26 @@ public:
struct AsmRange {
ErtsCodePtr start;
ErtsCodePtr stop;
- std::string name;
-
- /* Not used yet */
- std::string file;
- unsigned line;
- };
+ const std::string name;
- void update_gdb_jit_info(std::string modulename,
- std::vector<AsmRange> &functions);
+ struct LineData {
+ ErtsCodePtr start;
+ const std::string file;
+ unsigned line;
+ };
- void embed(void *data, uint32_t size) {
- a.embed((char *)data, size);
- }
-};
-
-class BeamGlobalAssembler : public BeamAssembler {
- typedef void (BeamGlobalAssembler::*emitFptr)(void);
- typedef void (*fptr)(void);
-
- /* Please keep this in alphabetical order. */
-#define BEAM_GLOBAL_FUNCS(_) \
- _(arith_compare_shared) \
- _(arith_eq_shared) \
- _(bif_nif_epilogue) \
- _(bif_element_shared) \
- _(bif_export_trap) \
- _(bs_add_shared) \
- _(bs_size_check_shared) \
- _(bs_fixed_integer_shared) \
- _(bs_get_tail_shared) \
- _(call_bif_shared) \
- _(call_light_bif_shared) \
- _(call_nif_early) \
- _(call_nif_shared) \
- _(catch_end_shared) \
- _(dispatch_bif) \
- _(dispatch_nif) \
- _(dispatch_return) \
- _(dispatch_save_calls) \
- _(error_action_code) \
- _(export_trampoline) \
- _(garbage_collect) \
- _(generic_bp_global) \
- _(generic_bp_local) \
- _(debug_bp) \
- _(handle_error_shared_prologue) \
- _(handle_error_shared) \
- _(handle_element_error) \
- _(handle_hd_error) \
- _(i_band_body_shared) \
- _(i_band_guard_shared) \
- _(i_bif_body_shared) \
- _(i_bif_guard_shared) \
- _(i_bor_body_shared) \
- _(i_bor_guard_shared) \
- _(i_bnot_body_shared) \
- _(i_bnot_guard_shared) \
- _(i_bsl_guard_shared) \
- _(i_bsl_body_shared) \
- _(i_bsr_guard_shared) \
- _(i_bsr_body_shared) \
- _(i_bxor_body_shared) \
- _(i_bxor_guard_shared) \
- _(i_func_info_shared) \
- _(i_load_nif_shared) \
- _(i_length_guard_shared) \
- _(i_length_body_shared) \
- _(i_loop_rec_shared) \
- _(i_new_small_map_lit_shared) \
- _(i_test_yield_shared) \
- _(increment_body_shared) \
- _(int_div_rem_body_shared) \
- _(int_div_rem_guard_shared) \
- _(minus_body_shared) \
- _(minus_guard_shared) \
- _(new_map_shared) \
- _(plus_body_shared) \
- _(plus_guard_shared) \
- _(process_main) \
- _(times_body_shared) \
- _(times_guard_shared) \
- _(unary_minus_body_shared) \
- _(unary_minus_guard_shared) \
- _(update_map_assoc_shared) \
- _(update_map_exact_guard_shared) \
- _(update_map_exact_body_shared)
-
-/* Labels exported from within process_main */
-#define PROCESS_MAIN_LABELS(_) \
- _(context_switch) \
- _(context_switch_simplified) \
- _(do_schedule)
-
-#define DECL_ENUM(NAME) NAME,
-
- enum GlobalLabels : uint32_t {
- BEAM_GLOBAL_FUNCS(DECL_ENUM) PROCESS_MAIN_LABELS(DECL_ENUM)
+ const std::vector<LineData> lines;
};
-#undef DECL_ENUM
-
- static const std::map<GlobalLabels, emitFptr> emitPtrs;
- static const std::map<GlobalLabels, std::string> labelNames;
- std::unordered_map<GlobalLabels, Label> labels;
- std::unordered_map<GlobalLabels, fptr> ptrs;
-
-#define DECL_FUNC(NAME) void emit_##NAME(void);
-
- BEAM_GLOBAL_FUNCS(DECL_FUNC);
-#undef DECL_FUNC
-
- template<typename T>
- void emit_bitwise_fallback_body(T(*func_ptr), const ErtsCodeMFA *mfa);
-
- template<typename T>
- void emit_bitwise_fallback_guard(T(*func_ptr));
-
- x86::Mem emit_i_length_common(Label fail, int state_size);
-
- void emit_handle_error();
-
-public:
- BeamGlobalAssembler(JitAllocator *allocator);
-
- void (*get(GlobalLabels lbl))(void) {
- ASSERT(ptrs[lbl]);
- return ptrs[lbl];
- }
-
-#define GET_CODE(NAME) \
- void (*get_##NAME(void))() { \
- return get(NAME); \
- }
-
- BEAM_GLOBAL_FUNCS(GET_CODE)
- PROCESS_MAIN_LABELS(GET_CODE)
-#undef GET_CODE
};
+#include "beam_asm_global.hpp"
+
class BeamModuleAssembler : public BeamAssembler {
typedef unsigned BeamLabel;
/* Map of label number to asmjit Label */
- typedef std::unordered_map<BeamLabel, Label> LabelMap;
- LabelMap labels;
+ typedef std::unordered_map<BeamLabel, const Label> LabelMap;
+ LabelMap rawLabels;
struct patch {
Label where;
@@ -1032,10 +931,10 @@ class BeamModuleAssembler : public BeamAssembler {
typedef std::unordered_map<unsigned, struct patch_import> ImportMap;
ImportMap imports;
- /* Map of fun entry to patch labels */
+ /* Map of fun entry to trampoline labels and patches */
struct patch_lambda {
std::vector<struct patch> patches;
- ErlFunEntry fe;
+ Label trampoline;
};
typedef std::unordered_map<unsigned, struct patch_lambda> LambdaMap;
LambdaMap lambdas;
@@ -1053,35 +952,43 @@ class BeamModuleAssembler : public BeamAssembler {
/* All functions that have been seen so far */
std::vector<BeamLabel> functions;
+ /* The BEAM file we've been loaded from, if any. */
+ const BeamFile *beam;
+
BeamGlobalAssembler *ga;
+ Label code_header;
+
/* Used by emit to populate the labelToMFA map */
- Label currLabel;
- unsigned prev_op = 0;
- Label codeHeader;
- Label funcInfo;
- Label funcYield;
- Label genericBPTramp;
+ Label current_label;
+
+ /* The module's on_load function, if any. */
Label on_load;
- Label floatMax;
- Label floatSignMask;
+ /* The end of the last function. */
+ Label code_end;
Eterm mod;
/* Save the last PC for an error. */
size_t last_error_offset = 0;
+ /* Maps code pointers to thunks that jump to them, letting us treat global
+ * fragments as if they were local. */
+ std::unordered_map<void (*)(), Label> _dispatchTable;
+
public:
BeamModuleAssembler(BeamGlobalAssembler *ga,
Eterm mod,
- unsigned num_labels);
+ int num_labels,
+ const BeamFile *file = NULL);
BeamModuleAssembler(BeamGlobalAssembler *ga,
Eterm mod,
- unsigned num_labels,
- unsigned num_functions);
+ int num_labels,
+ int num_functions,
+ const BeamFile *file = NULL);
- bool emit(unsigned op, const std::vector<ArgVal> &args);
+ bool emit(unsigned op, const Span<ArgVal> &args);
void codegen(JitAllocator *allocator,
const void **executable_ptr,
@@ -1096,7 +1003,11 @@ public:
void codegen(char *buff, size_t len);
+ void register_metadata(const BeamCodeHeader *header);
+
ErtsCodePtr getCode(unsigned label);
+ ErtsCodePtr getLambda(unsigned index);
+
void *getCode(Label label) {
return BeamAssembler::getCode(label);
}
@@ -1104,7 +1015,7 @@ public:
return BeamAssembler::getCode(labelName);
}
- Label embed_vararg_rodata(const std::vector<ArgVal> &args, int y_offset);
+ Label embed_vararg_rodata(const Span<ArgVal> &args, int y_offset);
unsigned getCodeSize() {
ASSERT(code.hasBaseAddress());
@@ -1122,35 +1033,217 @@ public:
void patchStrings(char *rw_base, const byte *string);
protected:
+ int getTypeUnion(const ArgSource &arg) const {
+ auto typeIndex =
+ arg.isRegister() ? arg.as<ArgRegister>().typeIndex() : 0;
+
+ ASSERT(typeIndex < beam->types.count);
+ return beam->types.entries[typeIndex].type_union;
+ }
+
+ auto getIntRange(const ArgSource &arg) const {
+ if (arg.isSmall()) {
+ Sint value = arg.as<ArgSmall>().getSigned();
+ return std::make_pair(value, value);
+ } else {
+ auto typeIndex =
+ arg.isRegister() ? arg.as<ArgRegister>().typeIndex() : 0;
+
+ ASSERT(typeIndex < beam->types.count);
+ const auto &entry = beam->types.entries[typeIndex];
+ ASSERT(entry.type_union & BEAM_TYPE_INTEGER);
+ return std::make_pair(entry.min, entry.max);
+ }
+ }
+
+ bool always_small(const ArgSource &arg) const {
+ if (arg.isSmall()) {
+ return true;
+ }
+
+ int type_union = getTypeUnion(arg);
+ if (type_union == BEAM_TYPE_INTEGER) {
+ auto [min, max] = getIntRange(arg);
+ return min <= max;
+ } else {
+ return false;
+ }
+ }
+
+ bool always_immediate(const ArgSource &arg) const {
+ if (arg.isImmed() || always_small(arg)) {
+ return true;
+ }
+
+ int type_union = getTypeUnion(arg);
+ return (type_union & BEAM_TYPE_MASK_ALWAYS_IMMEDIATE) == type_union;
+ }
+
+ bool always_same_types(const ArgSource &lhs, const ArgSource &rhs) const {
+ int lhs_types = getTypeUnion(lhs);
+ int rhs_types = getTypeUnion(rhs);
+
+ /* We can only be certain that the types are the same when there's
+ * one possible type. For example, if one is a number and the other
+ * is an integer, they could differ if the former is a float. */
+ if ((lhs_types & (lhs_types - 1)) == 0) {
+ return lhs_types == rhs_types;
+ }
+
+ return false;
+ }
+
+ bool always_one_of(const ArgSource &arg, int types) const {
+ if (arg.isImmed()) {
+ if (arg.isSmall()) {
+ return !!(types & BEAM_TYPE_INTEGER);
+ } else if (arg.isAtom()) {
+ return !!(types & BEAM_TYPE_ATOM);
+ } else if (arg.isNil()) {
+ return !!(types & BEAM_TYPE_NIL);
+ }
+
+ return false;
+ } else {
+ int type_union = getTypeUnion(arg);
+ return type_union == (type_union & types);
+ }
+ }
+
+ int masked_types(const ArgSource &arg, int mask) const {
+ if (arg.isImmed()) {
+ if (arg.isSmall()) {
+ return mask & BEAM_TYPE_INTEGER;
+ } else if (arg.isAtom()) {
+ return mask & BEAM_TYPE_ATOM;
+ } else if (arg.isNil()) {
+ return mask & BEAM_TYPE_NIL;
+ }
+
+ return BEAM_TYPE_NONE;
+ } else {
+ return getTypeUnion(arg) & mask;
+ }
+ }
+
+ bool exact_type(const ArgSource &arg, int type_id) const {
+ return always_one_of(arg, type_id);
+ }
+
+ bool is_sum_small(const ArgSource &LHS, const ArgSource &RHS) {
+ if (!(always_small(LHS) && always_small(RHS))) {
+ return false;
+ } else {
+ Sint min, max;
+ auto [min1, max1] = getIntRange(LHS);
+ auto [min2, max2] = getIntRange(RHS);
+ min = min1 + min2;
+ max = max1 + max2;
+ return IS_SSMALL(min) && IS_SSMALL(max);
+ }
+ }
+
+ bool is_difference_small(const ArgSource &LHS, const ArgSource &RHS) {
+ if (!(always_small(LHS) && always_small(RHS))) {
+ return false;
+ } else {
+ Sint min, max;
+ auto [min1, max1] = getIntRange(LHS);
+ auto [min2, max2] = getIntRange(RHS);
+ min = min1 - max2;
+ max = max1 - min2;
+ return IS_SSMALL(min) && IS_SSMALL(max);
+ }
+ }
+
+ bool is_product_small(const ArgSource &LHS, const ArgSource &RHS) {
+ if (!(always_small(LHS) && always_small(RHS))) {
+ return false;
+ } else {
+ auto [min1, max1] = getIntRange(LHS);
+ auto [min2, max2] = getIntRange(RHS);
+ auto mag1 = std::max(std::abs(min1), std::abs(max1));
+ auto mag2 = std::max(std::abs(min2), std::abs(max2));
+
+ /*
+ * mag1 * mag2 <= MAX_SMALL
+ * mag1 <= MAX_SMALL / mag2 (when mag2 != 0)
+ */
+ ERTS_CT_ASSERT(MAX_SMALL < -MIN_SMALL);
+ return mag2 == 0 || mag1 <= MAX_SMALL / mag2;
+ }
+ }
+
+ bool is_bsl_small(const ArgSource &LHS, const ArgSource &RHS) {
+ /*
+ * In the code compiled by scripts/diffable, there never
+ * seems to be any range information for the RHS. Therefore,
+ * don't bother unless RHS is an immediate small.
+ */
+ if (!(always_small(LHS) && RHS.isSmall())) {
+ return false;
+ } else {
+ auto [min1, max1] = getIntRange(LHS);
+ auto rhs_val = RHS.as<ArgSmall>().getSigned();
+
+ if (min1 < 0 || max1 == 0 || rhs_val < 0) {
+ return false;
+ }
+
+ return rhs_val < Support::clz(max1) - _TAG_IMMED1_SIZE;
+ }
+ }
+
/* Helpers */
- void emit_gc_test(const ArgVal &Stack,
- const ArgVal &Heap,
- const ArgVal &Live);
- void emit_gc_test_preserve(const ArgVal &Need,
- const ArgVal &Live,
+ void emit_gc_test(const ArgWord &Stack,
+ const ArgWord &Heap,
+ const ArgWord &Live);
+ void emit_gc_test_preserve(const ArgWord &Need,
+ const ArgWord &Live,
x86::Gp term);
x86::Mem emit_variable_apply(bool includeI);
- x86::Mem emit_fixed_apply(const ArgVal &arity, bool includeI);
+ x86::Mem emit_fixed_apply(const ArgWord &arity, bool includeI);
- x86::Gp emit_call_fun(const ArgVal &Fun);
- x86::Gp emit_apply_fun(void);
+ x86::Gp emit_call_fun(bool skip_box_test = false,
+ bool skip_fun_test = false,
+ bool skip_arity_test = false);
- void emit_is_binary(Label Fail, x86::Gp Src, Label next, Label subbin);
+ x86::Gp emit_is_binary(const ArgLabel &Fail,
+ const ArgSource &Src,
+ Label next,
+ Label subbin);
+
+ void emit_is_boxed(Label Fail, x86::Gp Src, Distance dist = dLong) {
+ BeamAssembler::emit_is_boxed(Fail, Src, dist);
+ }
+
+ void emit_is_boxed(Label Fail,
+ const ArgVal &Arg,
+ x86::Gp Src,
+ Distance dist = dLong) {
+ if (always_one_of(Arg, BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("skipped box test since argument is always boxed");
+ return;
+ }
+
+ BeamAssembler::emit_is_boxed(Fail, Src, dist);
+ }
void emit_get_list(const x86::Gp boxed_ptr,
- const ArgVal &Hd,
- const ArgVal &Tl);
+ const ArgRegister &Hd,
+ const ArgRegister &Tl);
- void emit_div_rem(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ErtsCodeMFA *error_mfa);
+ void emit_div_rem(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ErtsCodeMFA *error_mfa,
+ bool need_div = true,
+ bool need_rem = true);
void emit_setup_guard_bif(const std::vector<ArgVal> &args,
- const ArgVal &bif);
+ const ArgWord &bif);
- void emit_bif_arg_error(std::vector<ArgVal> args, const ErtsCodeMFA *mfa);
void emit_error(int code);
x86::Mem emit_bs_get_integer_prologue(Label next,
@@ -1158,39 +1251,48 @@ protected:
int flags,
int size);
- int emit_bs_get_field_size(const ArgVal &Size,
+ int emit_bs_get_field_size(const ArgSource &Size,
int unit,
Label Fail,
const x86::Gp &out,
unsigned max_size = 0);
- void emit_bs_get_utf8(const ArgVal &Ctx, const ArgVal &Fail);
- void emit_bs_get_utf16(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Flags);
+ void emit_bs_get_utf8(const ArgRegister &Ctx, const ArgLabel &Fail);
+ void emit_bs_get_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags);
+
+ void emit_raise_exception();
+ void emit_raise_exception(const ErtsCodeMFA *exp);
+ void emit_raise_exception(Label I, const ErtsCodeMFA *exp);
+ void emit_raise_exception(x86::Gp I, const ErtsCodeMFA *exp);
- void emit_handle_error();
- void emit_handle_error(const ErtsCodeMFA *exp);
- void emit_handle_error(Label I, const ErtsCodeMFA *exp);
- void emit_validate(const ArgVal &arity);
- void emit_bs_skip_bits(const ArgVal &Fail, const ArgVal &Ctx);
+ void emit_validate(const ArgWord &arity);
+ void emit_bs_skip_bits(const ArgLabel &Fail, const ArgRegister &Ctx);
void emit_linear_search(x86::Gp val,
const ArgVal &Fail,
- const std::vector<ArgVal> &args);
+ const Span<ArgVal> &args);
- void emit_check_float(Label next, x86::Xmm value);
+ void emit_float_instr(uint32_t instId,
+ const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst);
- void emit_is_small(Label fail, x86::Gp Reg);
- void emit_is_both_small(Label fail, x86::Gp A, x86::Gp B);
+ void emit_is_small(Label fail, const ArgSource &Arg, x86::Gp Reg);
+ void emit_are_both_small(Label fail,
+ const ArgSource &LHS,
+ x86::Gp A,
+ const ArgSource &RHS,
+ x86::Gp B);
void emit_validate_unicode(Label next, Label fail, x86::Gp value);
- void emit_bif_is_eq_ne_exact_immed(const ArgVal &Src,
- const ArgVal &Immed,
- const ArgVal &Dst,
- Eterm fail_value,
- Eterm succ_value);
+ void emit_bif_is_eq_ne_exact(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst,
+ Eterm fail_value,
+ Eterm succ_value);
void emit_proc_lc_unrequire(void);
void emit_proc_lc_require(void);
@@ -1201,17 +1303,39 @@ protected:
void emit_binsearch_nodes(size_t Left,
size_t Right,
const ArgVal &Fail,
- const std::vector<ArgVal> &args);
+ const Span<ArgVal> &args);
bool emit_optimized_three_way_select(const ArgVal &Fail,
- const std::vector<ArgVal> &args);
+ const Span<ArgVal> &args);
#ifdef DEBUG
- void emit_tuple_assertion(const ArgVal &Src, x86::Gp tuple_reg);
+ void emit_tuple_assertion(const ArgSource &Src, x86::Gp tuple_reg);
#endif
#include "beamasm_protos.h"
+ const Label &resolve_beam_label(const ArgLabel &Lbl) const {
+ return rawLabels.at(Lbl.get());
+ }
+
+ /* Resolves a shared fragment, creating a trampoline that loads the
+ * appropriate address before jumping there. */
+ const Label &resolve_fragment(void (*fragment)());
+
+ void safe_fragment_call(void (*fragment)()) {
+ emit_assert_redzone_unused();
+ a.call(resolve_fragment(fragment));
+ }
+
+ template<typename FuncPtr>
+ void aligned_call(FuncPtr(*target)) {
+ BeamAssembler::aligned_call(resolve_fragment(target));
+ }
+
+ void aligned_call(Label target) {
+ BeamAssembler::aligned_call(target);
+ }
+
void make_move_patch(x86::Gp to,
std::vector<struct patch> &patches,
int64_t offset = 0) {
@@ -1252,8 +1376,8 @@ protected:
void cmp_arg(x86::Mem mem, const ArgVal &val, const x86::Gp &spill) {
/* Note that the cast to Sint is necessary to handle negative numbers
* such as NIL. */
- if (val.isImmed() && Support::isInt32((Sint)val.getValue())) {
- a.cmp(mem, imm(val.getValue()));
+ if (val.isImmed() && Support::isInt32((Sint)val.as<ArgImmed>().get())) {
+ a.cmp(mem, imm(val.as<ArgImmed>().get()));
} else {
mov_arg(spill, val);
a.cmp(mem, spill);
@@ -1261,8 +1385,8 @@ protected:
}
void cmp_arg(x86::Gp gp, const ArgVal &val, const x86::Gp &spill) {
- if (val.isImmed() && Support::isInt32((Sint)val.getValue())) {
- a.cmp(gp, imm(val.getValue()));
+ if (val.isImmed() && Support::isInt32((Sint)val.as<ArgImmed>().get())) {
+ a.cmp(gp, imm(val.as<ArgImmed>().get()));
} else {
mov_arg(spill, val);
a.cmp(gp, spill);
@@ -1271,21 +1395,40 @@ protected:
/* Note: May clear flags. */
void mov_arg(x86::Gp to, const ArgVal &from, const x86::Gp &spill) {
- if (from.isMem()) {
- a.mov(to, getArgRef(from));
+ if (from.isBytePtr()) {
+ make_move_patch(to, strings, from.as<ArgBytePtr>().get());
+ } else if (from.isExport()) {
+ make_move_patch(to, imports[from.as<ArgExport>().get()].patches);
+ } else if (from.isImmed()) {
+ mov_imm(to, from.as<ArgImmed>().get());
+ } else if (from.isLambda()) {
+ make_move_patch(to, lambdas[from.as<ArgLambda>().get()].patches);
} else if (from.isLiteral()) {
- make_move_patch(to, literals[from.getValue()].patches);
+ make_move_patch(to, literals[from.as<ArgLiteral>().get()].patches);
+ } else if (from.isRegister()) {
+ a.mov(to, getArgRef(from.as<ArgRegister>()));
+ } else if (from.isWord()) {
+ mov_imm(to, from.as<ArgWord>().get());
} else {
- mov_imm(to, from.getValue());
+ ASSERT(!"mov_arg with incompatible type");
}
+
+#ifdef DEBUG
+ /* Explicitly clear flags to catch bugs quicker, it may be very rare
+ * for a certain instruction to load values that would otherwise cause
+ * flags to be cleared. */
+ a.test(to, to);
+#endif
}
void mov_arg(x86::Mem to, const ArgVal &from, const x86::Gp &spill) {
if (from.isImmed()) {
- if (Support::isInt32((Sint)from.getValue())) {
- a.mov(to, imm(from.getValue()));
+ auto val = from.as<ArgImmed>().get();
+
+ if (Support::isInt32((Sint)val)) {
+ a.mov(to, imm(val));
} else {
- a.mov(spill, imm(from.getValue()));
+ a.mov(spill, imm(val));
a.mov(to, spill);
}
} else {
@@ -1300,6 +1443,11 @@ protected:
a.mov(getArgRef(to), from);
}
+ void mov_arg(const ArgVal &to, x86::Mem from, const x86::Gp &spill) {
+ a.mov(spill, from);
+ a.mov(getArgRef(to), spill);
+ }
+
void mov_arg(const ArgVal &to, BeamInstr from, const x86::Gp &spill) {
if (Support::isInt32((Sint)from)) {
a.mov(getArgRef(to), imm(from));
@@ -1310,7 +1458,7 @@ protected:
}
void mov_arg(const ArgVal &to, const ArgVal &from, const x86::Gp &spill) {
- if (from.isMem()) {
+ if (from.isRegister()) {
mov_arg(spill, from);
mov_arg(to, spill);
} else {
@@ -1319,5 +1467,10 @@ protected:
}
};
-void beamasm_update_perf_info(std::string modulename,
- std::vector<BeamAssembler::AsmRange> &ranges);
+void beamasm_metadata_update(
+ std::string module_name,
+ ErtsCodePtr base_address,
+ size_t code_size,
+ const std::vector<BeamAssembler::AsmRange> &ranges);
+void beamasm_metadata_early_init();
+void beamasm_metadata_late_init();
diff --git a/erts/emulator/beam/jit/x86/beam_asm_global.cpp b/erts/emulator/beam/jit/x86/beam_asm_global.cpp
index a65b254bea..ec38e05323 100644
--- a/erts/emulator/beam/jit/x86/beam_asm_global.cpp
+++ b/erts/emulator/beam/jit/x86/beam_asm_global.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,9 @@
* %CopyrightEnd%
*/
+#define ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS
#include "beam_asm.hpp"
+#undef ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS
using namespace asmjit;
@@ -28,21 +30,6 @@ extern "C"
#include "beam_common.h"
}
-#define STRINGIFY_(X) #X
-#define STRINGIFY(X) STRINGIFY_(X)
-
-#define DECL_EMIT(NAME) {NAME, &BeamGlobalAssembler::emit_##NAME},
-const std::map<BeamGlobalAssembler::GlobalLabels, BeamGlobalAssembler::emitFptr>
- BeamGlobalAssembler::emitPtrs = {BEAM_GLOBAL_FUNCS(DECL_EMIT)};
-#undef DECL_EMIT
-
-#define DECL_LABEL_NAME(NAME) {NAME, STRINGIFY(NAME)},
-
-const std::map<BeamGlobalAssembler::GlobalLabels, std::string>
- BeamGlobalAssembler::labelNames = {BEAM_GLOBAL_FUNCS(
- DECL_LABEL_NAME) PROCESS_MAIN_LABELS(DECL_LABEL_NAME)};
-#undef DECL_LABEL_NAME
-
BeamGlobalAssembler::BeamGlobalAssembler(JitAllocator *allocator)
: BeamAssembler("beam_asm_global") {
labels.reserve(emitPtrs.size());
@@ -91,8 +78,10 @@ BeamGlobalAssembler::BeamGlobalAssembler(JitAllocator *allocator)
.name = code.labelEntry(labels[val.first])->name()});
}
- update_gdb_jit_info("global", ranges);
- beamasm_update_perf_info("global", ranges);
+ beamasm_metadata_update("global",
+ (ErtsCodePtr)getBaseAddress(),
+ code.codeSize(),
+ ranges);
#endif
/* `this->get_xxx` are populated last to ensure that we crash if we use them
@@ -103,31 +92,31 @@ BeamGlobalAssembler::BeamGlobalAssembler(JitAllocator *allocator)
}
}
-void BeamGlobalAssembler::emit_handle_error() {
- /* Move return address into ARG2 so we know where we crashed.
- *
- * This bluntly assumes that we haven't pushed anything to the (Erlang)
- * stack in the fragments that jump here. */
-
-#ifdef NATIVE_ERLANG_STACK
- a.mov(ARG2, x86::qword_ptr(E));
-#else
- a.pop(ARG2);
-#endif
- a.jmp(labels[handle_error_shared]);
-}
-
-/* ARG3 = (HTOP + bytes needed) !!
+/* ARG3 = (HTOP + S_RESERVED + bytes needed) !!
* ARG4 = Live registers */
void BeamGlobalAssembler::emit_garbage_collect() {
- /* Convert ARG3 to words needed and move it to the correct argument slot */
+ Label exiting = a.newLabel();
+
+ emit_enter_frame();
+
+ /* Convert ARG3 to words needed and move it to the correct argument slot.
+ *
+ * Note that we cancel out the S_RESERVED that we added in the GC check, as
+ * the GC routines handle that separately and we don't want it to be added
+ * twice. */
a.sub(ARG3, HTOP);
a.shr(ARG3, imm(3));
- a.mov(ARG2, ARG3);
+ a.lea(ARG2, x86::qword_ptr(ARG3, -S_RESERVED));
/* Save our return address in c_p->i so we can tell where we crashed if we
* do so during GC. */
- a.mov(RET, x86::qword_ptr(x86::rsp));
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ a.mov(RET, x86::qword_ptr(x86::rsp));
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+ a.mov(RET, x86::qword_ptr(x86::rsp, 8));
+ }
+
a.mov(x86::qword_ptr(c_p, offsetof(Process, i)), RET);
emit_enter_runtime<Update::eStack | Update::eHeap>();
@@ -140,7 +129,20 @@ void BeamGlobalAssembler::emit_garbage_collect() {
emit_leave_runtime<Update::eStack | Update::eHeap>();
+#ifdef WIN32
+ a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.value)));
+#else
+ a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.counter)));
+#endif
+ a.test(ARG1d, imm(ERTS_PSFLG_EXITING));
+ a.short_().jne(exiting);
+
+ emit_leave_frame();
a.ret();
+
+ a.bind(exiting);
+ emit_unwind_frame();
+ a.jmp(labels[do_schedule]);
}
/* Handles trapping to exports from C code, setting registers up in the same
@@ -149,12 +151,11 @@ void BeamGlobalAssembler::emit_garbage_collect() {
*
* Assumes that c_p->current points into the MFA of an export entry. */
void BeamGlobalAssembler::emit_bif_export_trap() {
- int export_offset = offsetof(Export, info.mfa);
-
a.mov(RET, x86::qword_ptr(c_p, offsetof(Process, current)));
- a.sub(RET, export_offset);
+ a.sub(RET, imm(offsetof(Export, info.mfa)));
- a.jmp(emit_setup_export_call(RET));
+ emit_leave_frame();
+ a.jmp(emit_setup_dispatchable_call(RET));
}
/* Handles export breakpoints, error handler, jump tracing, and so on.
@@ -182,6 +183,7 @@ void BeamGlobalAssembler::emit_export_trampoline() {
a.je(jump_trace);
/* Must never happen. */
+ comment("Unexpected export trampoline op");
a.ud2();
a.bind(call_bif);
@@ -197,6 +199,7 @@ void BeamGlobalAssembler::emit_export_trampoline() {
a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, i)));
a.mov(ARG4, x86::qword_ptr(RET, func_offset));
+ emit_enter_frame();
a.jmp(labels[call_bif_shared]);
}
@@ -205,6 +208,7 @@ void BeamGlobalAssembler::emit_export_trampoline() {
a.bind(error_handler);
{
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack |
Update::eHeap>();
@@ -218,8 +222,10 @@ void BeamGlobalAssembler::emit_export_trampoline() {
Update::eHeap>();
a.test(RET, RET);
- a.je(labels[error_action_code]);
- a.jmp(emit_setup_export_call(RET));
+ a.je(labels[process_exit]);
+
+ emit_leave_frame();
+ a.jmp(emit_setup_dispatchable_call(RET));
}
}
@@ -227,61 +233,94 @@ void BeamGlobalAssembler::emit_export_trampoline() {
* Get the error address implicitly by calling the shared fragment and using
* the return address as the error address.
*/
-void BeamModuleAssembler::emit_handle_error() {
- emit_handle_error(nullptr);
+void BeamModuleAssembler::emit_raise_exception() {
+ emit_raise_exception(nullptr);
}
-void BeamModuleAssembler::emit_handle_error(const ErtsCodeMFA *exp) {
- mov_imm(ARG4, (Uint)exp);
- safe_fragment_call(ga->get_handle_error_shared_prologue());
-
- /*
- * It is important that error address is not equal to a line
- * instruction that may follow this BEAM instruction. To avoid
- * that, BeamModuleAssembler::emit() will emit a nop instruction
- * if necessary.
- */
- last_error_offset = getOffset() & -8;
+void BeamModuleAssembler::emit_raise_exception(const ErtsCodeMFA *exp) {
+ mov_imm(ARG4, exp);
+ safe_fragment_call(ga->get_raise_exception());
+
+ /* `line` instructions need to know the latest offset that may throw an
+ * exception. See the `line` instruction for details. */
+ last_error_offset = a.offset();
}
-void BeamModuleAssembler::emit_handle_error(Label I, const ErtsCodeMFA *exp) {
+void BeamModuleAssembler::emit_raise_exception(Label I,
+ const ErtsCodeMFA *exp) {
a.lea(ARG2, x86::qword_ptr(I));
- mov_imm(ARG4, (Uint)exp);
+ emit_raise_exception(ARG2, exp);
+}
+
+void BeamModuleAssembler::emit_raise_exception(x86::Gp I,
+ const ErtsCodeMFA *exp) {
+ if (I != ARG2) {
+ a.mov(ARG2, I);
+ }
+
+ mov_imm(ARG4, exp);
#ifdef NATIVE_ERLANG_STACK
/* The CP must be reserved for try/catch to work, so we'll fake a call with
* the return address set to the error address. */
a.push(ARG2);
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+# ifdef ERLANG_FRAME_POINTERS
+ a.push(frame_pointer);
+# endif
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_RA);
+ }
#endif
- abs_jmp(ga->get_handle_error_shared());
+ a.jmp(resolve_fragment(ga->get_raise_exception_shared()));
}
-/* This is an alias for handle_error */
-void BeamGlobalAssembler::emit_error_action_code() {
+void BeamGlobalAssembler::emit_process_exit() {
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
mov_imm(ARG2, 0);
mov_imm(ARG4, 0);
+ load_x_reg_array(ARG3);
+ runtime_call<4>(handle_error);
- a.jmp(labels[handle_error_shared]);
+ emit_leave_runtime();
+
+ a.test(RET, RET);
+ a.je(labels[do_schedule]);
+ comment("End of process");
+ a.ud2();
}
-void BeamGlobalAssembler::emit_handle_error_shared_prologue() {
- /*
- * We must align the return address to make it a proper tagged CP.
- * This is safe because we will never actually return to the
- * return address.
- */
+/* Helper function for throwing exceptions from global fragments.
+ *
+ * Assumes that the next item on the _machine stack_ is a return address: we
+ * must not jump here while in a frame. */
+void BeamGlobalAssembler::emit_raise_exception() {
+ /* We must align the return address to make it a proper tagged CP, in case
+ * we were called with `safe_fragment_call`. This is safe because we will
+ * never actually return to the return address. */
a.pop(ARG2);
- a.and_(ARG2, imm(-8));
+ a.and_(ARG2, imm(~_CPMASK));
#ifdef NATIVE_ERLANG_STACK
a.push(ARG2);
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+# ifdef ERLANG_FRAME_POINTERS
+ a.push(frame_pointer);
+# endif
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_RA);
+ }
#endif
- a.jmp(labels[handle_error_shared]);
+ a.jmp(labels[raise_exception_shared]);
}
-void BeamGlobalAssembler::emit_handle_error_shared() {
+void BeamGlobalAssembler::emit_raise_exception_shared() {
Label crash = a.newLabel();
emit_enter_runtime<Update::eStack | Update::eHeap>();
@@ -303,6 +342,7 @@ void BeamGlobalAssembler::emit_handle_error_shared() {
a.jmp(RET);
a.bind(crash);
+ comment("Error address is not a CP or NULL or ARG2 and ARG4 are unset");
a.ud2();
}
diff --git a/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl b/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl
new file mode 100755
index 0000000000..898a1f6065
--- /dev/null
+++ b/erts/emulator/beam/jit/x86/beam_asm_global.hpp.pl
@@ -0,0 +1,207 @@
+#!/usr/bin/env perl -W
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2022-2023. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+use strict;
+
+# Please keep the names in the list in alphabetical order.
+my @beam_global_funcs = qw(
+ apply_fun_shared
+ arith_compare_shared
+ arith_eq_shared
+ bif_nif_epilogue
+ bif_element_shared
+ bif_export_trap
+ bs_add_shared
+ bs_create_bin_error_shared
+ bs_size_check_shared
+ bs_fixed_integer_shared
+ bs_get_tail_shared
+ call_bif_shared
+ call_light_bif_shared
+ call_nif_early
+ call_nif_shared
+ call_nif_yield_helper
+ catch_end_shared
+ check_float_error
+ dispatch_bif
+ dispatch_nif
+ dispatch_return
+ dispatch_save_calls
+ export_trampoline
+ garbage_collect
+ generic_bp_global
+ generic_bp_local
+ debug_bp
+ fconv_shared
+ handle_call_fun_error
+ handle_element_error
+ handle_hd_error
+ i_band_body_shared
+ i_band_guard_shared
+ i_bif_body_shared
+ i_bif_guard_shared
+ i_bor_body_shared
+ i_bor_guard_shared
+ i_bnot_body_shared
+ i_bnot_guard_shared
+ i_breakpoint_trampoline_shared
+ i_bsl_guard_shared
+ i_bsl_body_shared
+ i_bsr_guard_shared
+ i_bsr_body_shared
+ i_bxor_body_shared
+ i_bxor_guard_shared
+ i_func_info_shared
+ i_get_map_element_shared
+ i_get_map_element_hash_shared
+ i_load_nif_shared
+ i_length_guard_shared
+ i_length_body_shared
+ i_loop_rec_shared
+ i_new_small_map_lit_shared
+ i_test_yield_shared
+ increment_body_shared
+ int_div_rem_body_shared
+ int_div_rem_guard_shared
+ internal_hash_helper
+ minus_body_shared
+ minus_guard_shared
+ new_map_shared
+ plus_body_shared
+ plus_guard_shared
+ process_exit
+ process_main
+ raise_exception
+ raise_exception_shared
+ times_body_shared
+ times_guard_shared
+ unary_minus_body_shared
+ unary_minus_guard_shared
+ unloaded_fun
+ update_map_assoc_shared
+ update_map_exact_guard_shared
+ update_map_exact_body_shared
+ );
+
+# Labels exported from within process_main
+my @process_main_labels = qw(
+ context_switch
+ context_switch_simplified
+ do_schedule
+ );
+
+my $decl_enums =
+ gen_list(' %s,', @beam_global_funcs, '', @process_main_labels);
+
+my $decl_emit_funcs =
+ gen_list(' void emit_%s(void);', @beam_global_funcs);
+
+my $decl_get_funcs =
+ gen_list(' void (*get_%s(void))() { return get(%s); }',
+ @beam_global_funcs, '', @process_main_labels);
+
+my $decl_emitPtrs =
+ gen_list(' {%s, &BeamGlobalAssembler::emit_%s},', @beam_global_funcs);
+
+my $decl_label_names =
+ gen_list(' {%s, "%s"},', @beam_global_funcs, '', @process_main_labels);
+
+sub gen_list {
+ my ($format, @strings) = @_;
+ my $out = '';
+ foreach my $str (@strings) {
+ if ($str eq '') {
+ $out .= "\n";
+ }
+ else {
+ my $subst = $format;
+ $subst =~ s/%s/$str/g;
+ $out .= "$subst\n";
+ }
+ }
+ $out;
+}
+
+
+my $this_source_file = __FILE__;
+
+print <<END_OF_FILE;
+/*
+ * Warning: Do not edit this file.
+ * Auto-generated by $this_source_file.
+ */
+
+#ifndef _BEAM_ASM_GLOBAL_HPP
+#define _BEAM_ASM_GLOBAL_HPP
+
+
+class BeamGlobalAssembler : public BeamAssembler {
+ typedef void (BeamGlobalAssembler::*emitFptr)(void);
+ typedef void (*fptr)(void);
+
+ enum GlobalLabels : uint32_t {
+$decl_enums
+ };
+
+ static const std::map<GlobalLabels, const std::string> labelNames;
+ static const std::map<GlobalLabels, emitFptr> emitPtrs;
+ std::unordered_map<GlobalLabels, Label> labels;
+ std::unordered_map<GlobalLabels, fptr> ptrs;
+
+$decl_emit_funcs
+
+ template<typename T>
+ void emit_bitwise_fallback_body(T(*func_ptr), const ErtsCodeMFA *mfa);
+
+ template<typename T>
+ void emit_bitwise_fallback_guard(T(*func_ptr));
+
+ x86::Mem emit_i_length_common(Label fail, int state_size);
+
+ void emit_flatmap_get_element();
+ void emit_hashmap_get_element();
+
+public:
+ BeamGlobalAssembler(JitAllocator *allocator);
+
+ void (*get(GlobalLabels lbl))(void) {
+ ASSERT(ptrs[lbl]);
+ return ptrs[lbl];
+ }
+
+$decl_get_funcs
+};
+
+#ifdef ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS
+
+const std::map<BeamGlobalAssembler::GlobalLabels, BeamGlobalAssembler::emitFptr>
+BeamGlobalAssembler::emitPtrs = {
+$decl_emitPtrs
+};
+
+const std::map<BeamGlobalAssembler::GlobalLabels, const std::string>
+BeamGlobalAssembler::labelNames = {
+$decl_label_names
+};
+
+#endif /* ERTS_BEAM_ASM_GLOBAL_WANT_STATIC_DEFS */
+
+#endif /* !_BEAM_ASM_GLOBAL_HPP */
+END_OF_FILE
diff --git a/erts/emulator/beam/jit/x86/beam_asm_module.cpp b/erts/emulator/beam/jit/x86/beam_asm_module.cpp
index bada1c8395..be01db5ac3 100644
--- a/erts/emulator/beam/jit/x86/beam_asm_module.cpp
+++ b/erts/emulator/beam/jit/x86/beam_asm_module.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,11 +24,6 @@
#include "beam_asm.hpp"
using namespace asmjit;
-static std::string getAtom(Eterm atom) {
- Atom *ap = atom_tab(atom_val(atom));
- return std::string((char *)ap->name, ap->len);
-}
-
#ifdef BEAMASM_DUMP_SIZES
# include <mutex>
@@ -67,127 +62,31 @@ extern "C" void beamasm_dump_sizes() {
}
#endif
-BeamModuleAssembler::BeamModuleAssembler(BeamGlobalAssembler *ga,
- Eterm mod,
- unsigned num_labels)
- : BeamAssembler(getAtom(mod)) {
- this->ga = ga;
- this->mod = mod;
-
- labels.reserve(num_labels + 1);
- for (unsigned i = 1; i < num_labels; i++) {
- Label lbl;
-
-#ifdef DEBUG
- std::string lblName = "label_" + std::to_string(i);
- lbl = a.newNamedLabel(lblName.data());
-#else
- lbl = a.newLabel();
-#endif
+ErtsCodePtr BeamModuleAssembler::getCode(BeamLabel label) {
+ ASSERT(label < rawLabels.size() + 1);
+ return (ErtsCodePtr)getCode(rawLabels[label]);
+}
- labels[i] = lbl;
- }
+ErtsCodePtr BeamModuleAssembler::getLambda(unsigned index) {
+ const auto &lambda = lambdas[index];
+ return (ErtsCodePtr)getCode(lambda.trampoline);
}
BeamModuleAssembler::BeamModuleAssembler(BeamGlobalAssembler *ga,
Eterm mod,
- unsigned num_labels,
- unsigned num_functions)
- : BeamModuleAssembler(ga, mod, num_labels) {
- codeHeader = a.newLabel();
+ int num_labels,
+ int num_functions,
+ const BeamFile *file)
+ : BeamModuleAssembler(ga, mod, num_labels, file) {
+ code_header = a.newLabel();
a.align(AlignMode::kCode, 8);
- a.bind(codeHeader);
+ a.bind(code_header);
embed_zeros(sizeof(BeamCodeHeader) +
sizeof(ErtsCodeInfo *) * num_functions);
-
- floatMax = a.newLabel();
- a.align(AlignMode::kCode, 8);
- a.bind(floatMax);
- double max = DBL_MAX;
- a.embed((char *)&max, sizeof(double));
-
- floatSignMask = a.newLabel();
- a.align(AlignMode::kCode, 16); /* 128-bit aligned */
- a.bind(floatSignMask);
- uint64_t signMask = 0x7FFFFFFFFFFFFFFFul;
- a.embed((char *)&signMask, sizeof(double));
-
- /* Shared trampoline for function_clause errors, which can't jump straight
- * to `i_func_info_shared` due to size restrictions. */
- funcInfo = a.newLabel();
- a.align(AlignMode::kCode, 8);
- a.bind(funcInfo);
- abs_jmp(ga->get_i_func_info_shared());
-
- /* Shared trampoline for yielding on function ingress. */
- funcYield = a.newLabel();
- a.align(AlignMode::kCode, 8);
- a.bind(funcYield);
- abs_jmp(ga->get_i_test_yield_shared());
-
- /* Setup the early_nif/breakpoint trampoline. */
- genericBPTramp = a.newLabel();
- a.align(AlignMode::kCode, 16);
- a.bind(genericBPTramp);
- {
- a.ret();
-
- a.align(AlignMode::kCode, 16);
- abs_jmp(ga->get_call_nif_early());
-
- a.align(AlignMode::kCode, 16);
- aligned_call(ga->get_generic_bp_local());
- a.ret();
-
- a.align(AlignMode::kCode, 16);
- ASSERT(a.offset() - code.labelOffsetFromBase(genericBPTramp) == 16 * 3);
- aligned_call(ga->get_generic_bp_local());
- abs_jmp(ga->get_call_nif_early());
- }
-}
-
-ErtsCodePtr BeamModuleAssembler::getCode(unsigned label) {
- ASSERT(label < labels.size() + 1);
- return (ErtsCodePtr)getCode(labels[label]);
}
-void BeamAssembler::embed_rodata(const char *labelName,
- const char *buff,
- size_t size) {
- Label label = a.newNamedLabel(labelName);
-
- a.section(rodata);
- a.bind(label);
- a.embed(buff, size);
- a.section(code.textSection());
-}
-
-void BeamAssembler::embed_bss(const char *labelName, size_t size) {
- Label label = a.newNamedLabel(labelName);
-
- /* Reuse rodata section for now */
- a.section(rodata);
- a.bind(label);
- embed_zeros(size);
- a.section(code.textSection());
-}
-
-void BeamAssembler::embed_zeros(size_t size) {
- static constexpr size_t buf_size = 16384;
- static const char zeros[buf_size] = {};
-
- while (size >= buf_size) {
- a.embed(zeros, buf_size);
- size -= buf_size;
- }
-
- if (size > 0) {
- a.embed(zeros, size);
- }
-}
-
-Label BeamModuleAssembler::embed_vararg_rodata(const std::vector<ArgVal> &args,
+Label BeamModuleAssembler::embed_vararg_rodata(const Span<ArgVal> &args,
int y_offset) {
Label label = a.newLabel();
@@ -206,27 +105,33 @@ Label BeamModuleAssembler::embed_vararg_rodata(const std::vector<ArgVal> &args,
a.align(AlignMode::kData, 8);
switch (arg.getType()) {
- case TAG_x:
- data.as_beam = make_loader_x_reg(arg.getValue());
+ case ArgVal::XReg: {
+ auto index = arg.as<ArgXRegister>().get();
+ data.as_beam = make_loader_x_reg(index);
a.embed(&data.as_char, sizeof(data.as_beam));
- break;
- case TAG_y:
- data.as_beam = make_loader_y_reg(arg.getValue() + y_offset);
+ } break;
+ case ArgVal::YReg: {
+ auto index = arg.as<ArgYRegister>().get();
+ data.as_beam = make_loader_y_reg(index + y_offset);
a.embed(&data.as_char, sizeof(data.as_beam));
+ } break;
+ case ArgVal::Literal: {
+ auto index = arg.as<ArgLiteral>().get();
+ make_word_patch(literals[index].patches);
+ } break;
+ case ArgVal::Label:
+ a.embedLabel(resolve_beam_label(arg));
break;
- case TAG_q:
- make_word_patch(literals[arg.getValue()].patches);
- break;
- case TAG_f:
- a.embedLabel(labels[arg.getValue()]);
+ case ArgVal::Immediate:
+ data.as_beam = arg.as<ArgImmed>().get();
+ a.embed(&data.as_char, sizeof(data.as_beam));
break;
- case TAG_i:
- case TAG_u:
- /* Tagged immediate or untagged word. */
- data.as_beam = arg.getValue();
+ case ArgVal::Word:
+ data.as_beam = arg.as<ArgWord>().get();
a.embed(&data.as_char, sizeof(data.as_beam));
break;
default:
+ erts_fprintf(stderr, "tag: %li\n", arg.getType());
ERTS_ASSERT(!"error");
}
}
@@ -236,15 +141,11 @@ Label BeamModuleAssembler::embed_vararg_rodata(const std::vector<ArgVal> &args,
return label;
}
-static void i_emit_nyi(char *msg) {
- erts_exit(ERTS_ERROR_EXIT, "NYI: %s\n", msg);
-}
-
void BeamModuleAssembler::emit_i_nif_padding() {
const size_t minimum_size = sizeof(UWord[BEAM_NATIVE_MIN_FUNC_SZ]);
size_t prev_func_start, diff;
- prev_func_start = code.labelOffsetFromBase(labels[functions.back() + 1]);
+ prev_func_start = code.labelOffsetFromBase(rawLabels[functions.back() + 1]);
diff = a.offset() - prev_func_start;
if (diff < minimum_size) {
@@ -252,34 +153,86 @@ void BeamModuleAssembler::emit_i_nif_padding() {
}
}
+void BeamGlobalAssembler::emit_i_breakpoint_trampoline_shared() {
+ constexpr ssize_t flag_offset =
+ sizeof(ErtsCodeInfo) + BEAM_ASM_FUNC_PROLOGUE_SIZE -
+ offsetof(ErtsCodeInfo, u.metadata.breakpoint_flag);
+
+ Label bp_and_nif = a.newLabel(), bp_only = a.newLabel(),
+ nif_only = a.newLabel();
+
+ a.mov(RET, x86::qword_ptr(x86::rsp));
+ a.movzx(RETd, x86::byte_ptr(RET, -flag_offset));
+
+ a.cmp(RETd, imm(ERTS_ASM_BP_FLAG_BP_NIF_CALL_NIF_EARLY));
+ a.short_().je(bp_and_nif);
+ a.cmp(RETd, imm(ERTS_ASM_BP_FLAG_CALL_NIF_EARLY));
+ a.short_().je(nif_only);
+ a.cmp(RETd, imm(ERTS_ASM_BP_FLAG_BP));
+ a.short_().je(bp_only);
+
+#ifndef DEBUG
+ a.ret();
+#else
+ Label error = a.newLabel();
+
+ /* RET must be a valid breakpoint flag. */
+ a.test(RETd, RETd);
+ a.short_().jnz(error);
+ a.ret();
+
+ a.bind(error);
+ a.ud2();
+#endif
+
+ a.bind(bp_and_nif);
+ {
+ aligned_call(labels[generic_bp_local]);
+ /* FALL THROUGH */
+ }
+
+ a.bind(nif_only);
+ {
+ /* call_nif_early returns on its own, unlike generic_bp_local. */
+ a.jmp(labels[call_nif_early]);
+ }
+
+ a.bind(bp_only);
+ {
+ aligned_call(labels[generic_bp_local]);
+ a.ret();
+ }
+}
+
void BeamModuleAssembler::emit_i_breakpoint_trampoline() {
/* This little prologue is used by nif loading and tracing to insert
* alternative instructions. The call is filled with a relative call to a
* trampoline in the module header and then the jmp target is zeroed so that
* it effectively becomes a nop */
- byte flag = ERTS_ASM_BP_FLAG_NONE;
Label next = a.newLabel();
a.short_().jmp(next);
- /* We embed a zero byte here, which is used to flag whether to make an early
- * nif call, call a breakpoint handler, or both. */
- a.embed(&flag, sizeof(flag));
-
- if (genericBPTramp.isValid()) {
- a.call(genericBPTramp);
+ if (code_header.isValid()) {
+ auto fragment = ga->get_i_breakpoint_trampoline_shared();
+ aligned_call(resolve_fragment(fragment));
} else {
/* NIF or BIF stub; we're not going to use this trampoline as-is, but
* we need to reserve space for it. */
a.ud2();
+ a.align(AlignMode::kCode, sizeof(UWord));
}
- a.align(AlignMode::kCode, 8);
+ ASSERT(a.offset() % sizeof(UWord) == 0);
a.bind(next);
- ASSERT((a.offset() - code.labelOffsetFromBase(currLabel)) ==
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
BEAM_ASM_FUNC_PROLOGUE_SIZE);
}
+static void i_emit_nyi(char *msg) {
+ erts_exit(ERTS_ERROR_EXIT, "NYI: %s\n", msg);
+}
+
void BeamModuleAssembler::emit_nyi(const char *msg) {
emit_enter_runtime();
@@ -293,8 +246,7 @@ void BeamModuleAssembler::emit_nyi() {
emit_nyi("<unspecified>");
}
-bool BeamModuleAssembler::emit(unsigned specific_op,
- const std::vector<ArgVal> &args) {
+bool BeamModuleAssembler::emit(unsigned specific_op, const Span<ArgVal> &args) {
comment(opc[specific_op].name);
#ifdef BEAMASM_DUMP_SIZES
@@ -309,18 +261,6 @@ bool BeamModuleAssembler::emit(unsigned specific_op,
break;
}
- if (getOffset() == last_error_offset) {
- /*
- * The previous PC where an exception may occur is equal to the
- * current offset, which is also the offset of the next
- * instruction. If the next instruction happens to be a
- * line instruction, the location for the exception will
- * be that line instruction, which is probably wrong.
- * To avoid that, bump the instruction offset.
- */
- a.nop();
- }
-
#ifdef BEAMASM_DUMP_SIZES
{
std::lock_guard<std::mutex> lock(size_lock);
@@ -341,81 +281,100 @@ void BeamGlobalAssembler::emit_i_func_info_shared() {
/* Pop the ErtsCodeInfo address into ARG1 and mask out the offset added by
* the call instruction. */
a.pop(ARG1);
- a.and_(ARG1, ~0x7);
+ a.and_(ARG1, imm(~0x7));
- a.lea(ARG1, x86::qword_ptr(ARG1, offsetof(ErtsCodeInfo, mfa)));
+ a.add(ARG1, imm(offsetof(ErtsCodeInfo, mfa)));
a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), EXC_FUNCTION_CLAUSE);
a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), ARG1);
- a.jmp(labels[error_action_code]);
+
+ mov_imm(ARG2, 0);
+ mov_imm(ARG4, 0);
+ a.jmp(labels[raise_exception_shared]);
}
-void BeamModuleAssembler::emit_i_func_info(const ArgVal &Label,
- const ArgVal &Module,
- const ArgVal &Function,
- const ArgVal &Arity) {
+void BeamModuleAssembler::emit_i_func_info(const ArgWord &Label,
+ const ArgAtom &Module,
+ const ArgAtom &Function,
+ const ArgWord &Arity) {
ErtsCodeInfo info;
- functions.push_back(Label.getValue());
+ /* `op_i_func_info_IaaI` is used in various places in the emulator, so this
+ * label is always encoded as a word, even though the signature ought to
+ * be `op_i_func_info_LaaI`. */
+ functions.push_back(Label.get());
- info.mfa.module = Module.getValue();
- info.mfa.function = Function.getValue();
- info.mfa.arity = Arity.getValue();
- info.u.gen_bp = NULL;
+ info.mfa.module = Module.get();
+ info.mfa.function = Function.get();
+ info.mfa.arity = Arity.get();
+ info.gen_bp = NULL;
comment("%T:%T/%d", info.mfa.module, info.mfa.function, info.mfa.arity);
/* This is an ErtsCodeInfo structure that has a valid x86 opcode as its `op`
- * field, which *calls* the funcInfo trampoline so we can trace it back to
- * this particular function.
+ * field, which *calls* the `_i_func_info_shared` fragment so we can trace
+ * it back to this particular function.
*
- * We make a relative call to a trampoline in the module header because this
- * needs to fit into a word, and an directy call to `i_func_info_shared`
- * would be too large. */
- if (funcInfo.isValid()) {
- a.call(funcInfo);
- } else {
- a.nop();
- }
-
- a.align(AlignMode::kCode, sizeof(UWord));
- a.embed(&info.u.gen_bp, sizeof(info.u.gen_bp));
+ * We also use this field to store the current breakpoint flag so that we
+ * only have to modify a single branch target when changing breakpoints. */
+ a.call(resolve_fragment(ga->get_i_func_info_shared()));
+ a.nop();
+ a.nop();
+ a.embedUInt8(ERTS_ASM_BP_FLAG_NONE);
+
+ ASSERT(a.offset() % sizeof(UWord) == 0);
+ a.embed(&info.gen_bp, sizeof(info.gen_bp));
a.embed(&info.mfa, sizeof(info.mfa));
}
-void BeamModuleAssembler::emit_label(const ArgVal &Label) {
- currLabel = labels[Label.getValue()];
- a.bind(currLabel);
+void BeamModuleAssembler::emit_label(const ArgLabel &Label) {
+ ASSERT(Label.isLabel());
+
+ current_label = rawLabels[Label.get()];
+ a.bind(current_label);
}
-void BeamModuleAssembler::emit_aligned_label(const ArgVal &Label,
- const ArgVal &Alignment) {
- ASSERT(Alignment.getType() == ArgVal::u);
- a.align(AlignMode::kCode, Alignment.getValue());
+void BeamModuleAssembler::emit_aligned_label(const ArgLabel &Label,
+ const ArgWord &Alignment) {
+ a.align(AlignMode::kCode, Alignment.get());
emit_label(Label);
}
void BeamModuleAssembler::emit_on_load() {
- on_load = currLabel;
+ on_load = current_label;
}
void BeamModuleAssembler::emit_int_code_end() {
/* This label is used to figure out the end of the last function */
- labels[labels.size() + 1] = a.newLabel();
- a.bind(labels[labels.size()]);
+ code_end = a.newLabel();
+ a.bind(code_end);
emit_nyi("int_code_end");
+
+ for (auto pair : _dispatchTable) {
+ a.bind(pair.second);
+ a.jmp(imm(pair.first));
+ }
}
-void BeamModuleAssembler::emit_line(const ArgVal &) {
- /*
- * There is no need to align the line instruction. In the loaded
- * code, the type of the pointer will be void* and that pointer
- * will only be used in comparisons.
- */
+void BeamModuleAssembler::emit_line(const ArgWord &Loc) {
+ /* There is no need to align the line instruction. In the loaded code, the
+ * type of the pointer will be void* and that pointer will only be used in
+ * comparisons.
+ *
+ * We only need to do something when there's a possibility of raising an
+ * exception at the very end of the preceding instruction (and thus
+ * pointing at the start of this one). If we were to do nothing, the error
+ * would erroneously refer to this instead of the preceding line.
+ *
+ * Since line addresses are taken _after_ line instructions we can avoid
+ * this by adding a nop when we detect this condition. */
+ if (a.offset() == last_error_offset) {
+ a.nop();
+ }
}
-void BeamModuleAssembler::emit_func_line(const ArgVal &Loc) {
+void BeamModuleAssembler::emit_func_line(const ArgWord &Loc) {
emit_line(Loc);
}
@@ -434,7 +393,7 @@ void BeamModuleAssembler::emit_i_generic_breakpoint() {
emit_nyi("i_generic_breakpoint should never be called");
}
-void BeamModuleAssembler::emit_trace_jump(const ArgVal &) {
+void BeamModuleAssembler::emit_trace_jump(const ArgWord &) {
emit_nyi("trace_jump should never be called");
}
@@ -442,129 +401,6 @@ void BeamModuleAssembler::emit_call_error_handler() {
emit_nyi("call_error_handler should never be called");
}
-void BeamModuleAssembler::codegen(JitAllocator *allocator,
- const void **executable_ptr,
- void **writable_ptr,
- const BeamCodeHeader *in_hdr,
- const BeamCodeHeader **out_exec_hdr,
- BeamCodeHeader **out_rw_hdr) {
- const BeamCodeHeader *code_hdr_exec;
- BeamCodeHeader *code_hdr_rw;
-
- codegen(allocator, executable_ptr, writable_ptr);
-
- {
- auto offset = code.labelOffsetFromBase(codeHeader);
-
- auto base_exec = (const char *)(*executable_ptr);
- code_hdr_exec = (const BeamCodeHeader *)&base_exec[offset];
-
- auto base_rw = (const char *)(*writable_ptr);
- code_hdr_rw = (BeamCodeHeader *)&base_rw[offset];
- }
-
- sys_memcpy(code_hdr_rw, in_hdr, sizeof(BeamCodeHeader));
- code_hdr_rw->on_load = getOnLoad();
-
- for (unsigned i = 0; i < functions.size(); i++) {
- ErtsCodeInfo *ci = (ErtsCodeInfo *)getCode(functions[i]);
- code_hdr_rw->functions[i] = ci;
- }
-
- char *module_end = (char *)code.baseAddress() + a.offset();
- code_hdr_rw->functions[functions.size()] = (ErtsCodeInfo *)module_end;
-
- *out_exec_hdr = code_hdr_exec;
- *out_rw_hdr = code_hdr_rw;
-}
-
-void BeamModuleAssembler::codegen(JitAllocator *allocator,
- const void **executable_ptr,
- void **writable_ptr) {
- _codegen(allocator, executable_ptr, writable_ptr);
-
-#ifndef WIN32
- if (functions.size()) {
- char *buff = (char *)erts_alloc(ERTS_ALC_T_TMP, 1024);
- std::vector<AsmRange> ranges;
- std::string name = getAtom(mod);
- ranges.reserve(functions.size() + 2);
-
- /* Push info about the header */
- ranges.push_back({.start = (ErtsCodePtr)getBaseAddress(),
- .stop = getCode(functions[0]),
- .name = name + "::codeHeader"});
-
- for (unsigned i = 0; i < functions.size(); i++) {
- ErtsCodePtr start, stop;
- const ErtsCodeInfo *ci;
- int n;
-
- start = getCode(functions[i]);
- ci = (const ErtsCodeInfo *)start;
-
- n = erts_snprintf(buff,
- 1024,
- "%T:%T/%d",
- ci->mfa.module,
- ci->mfa.function,
- ci->mfa.arity);
- stop = ((const char *)erts_codeinfo_to_code(ci)) +
- BEAM_ASM_FUNC_PROLOGUE_SIZE;
-
- /* We use a different symbol for CodeInfo and the Prologue
- in order for the perf disassembly to be better. */
- std::string name(buff, n);
- ranges.push_back({.start = start,
- .stop = stop,
- .name = name + "-CodeInfoPrologue"});
-
- /* The actual code */
- start = stop;
- if (i + 1 < functions.size()) {
- stop = getCode(functions[i + 1]);
- } else {
- stop = getCode(labels.size());
- }
-
- ranges.push_back({.start = start, .stop = stop, .name = name});
- }
-
- /* Push info about the footer */
- ranges.push_back(
- {.start = ranges.back().stop,
- .stop = (ErtsCodePtr)(code.baseAddress() + code.codeSize()),
- .name = name + "::codeFooter"});
-
- update_gdb_jit_info(name, ranges);
- beamasm_update_perf_info(name, ranges);
- erts_free(ERTS_ALC_T_TMP, buff);
- }
-#endif
-}
-
-void BeamModuleAssembler::codegen(char *buff, size_t len) {
- code.flatten();
- code.resolveUnresolvedLinks();
- ERTS_ASSERT(code.codeSize() <= len);
- code.relocateToBase((uint64_t)buff);
- code.copyFlattenedData(buff,
- code.codeSize(),
- CopySectionFlags::kPadSectionBuffer);
-}
-
-BeamCodeHeader *BeamModuleAssembler::getCodeHeader() {
- return (BeamCodeHeader *)getCode(codeHeader);
-}
-
-const ErtsCodeInfo *BeamModuleAssembler::getOnLoad() {
- if (on_load.isValid()) {
- return erts_code_to_codeinfo((ErtsCodePtr)getCode(on_load));
- } else {
- return 0;
- }
-}
-
unsigned BeamModuleAssembler::patchCatches(char *rw_base) {
unsigned catch_no = BEAM_CATCHES_NIL;
@@ -637,3 +473,13 @@ void BeamModuleAssembler::patchStrings(char *rw_base,
*where = string_table + patch.val_offs;
}
}
+
+const Label &BeamModuleAssembler::resolve_fragment(void (*fragment)()) {
+ auto it = _dispatchTable.find(fragment);
+
+ if (it == _dispatchTable.end()) {
+ it = _dispatchTable.emplace(fragment, a.newLabel()).first;
+ }
+
+ return it->second;
+}
diff --git a/erts/emulator/beam/jit/x86/beam_asm_perf.cpp b/erts/emulator/beam/jit/x86/beam_asm_perf.cpp
deleted file mode 100644
index cbc61f4059..0000000000
--- a/erts/emulator/beam/jit/x86/beam_asm_perf.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-#include "beam_asm.hpp"
-
-#ifdef HAVE_LINUX_PERF_SUPPORT
-
-# ifdef HAVE_ELF_H
-# include <elf.h>
-# define HAVE_LINUX_PERF_DUMP_SUPPORT 1
-
-class JitPerfDump {
- FILE *file = nullptr;
- Uint64 code_index = 0;
-
- enum PerfDumpId {
- JIT_CODE_LOAD = 0, /* record describing a jitted function */
- JIT_CODE_MOVE = 1, /* record describing an already jitted function which
- is moved */
- JIT_CODE_DEBUG_INFO = 2, /* record describing the debug information for
- a jitted function */
- JIT_CODE_CLOSE =
- 3, /* record marking the end of the jit runtime (optional) */
- JIT_CODE_UNWINDING_INFO =
- 4 /* record describing a function unwinding information */
- };
-
- struct FileHeader {
- Uint32 magic;
- Uint32 version;
- Uint32 total_size;
- Uint32 elf_mach;
- Uint32 pad1;
- Uint32 pid;
- Uint64 timestamp;
- Uint64 flags;
-
- FileHeader() {
- magic = 0x4A695444; /* "JiTD" as numbers */
- version = 1;
- total_size = sizeof(FileHeader);
- elf_mach = EM_X86_64;
- pad1 = 0;
- pid = getpid();
- timestamp = erts_os_monotonic_time();
- flags = 0;
- ERTS_CT_ASSERT(sizeof(FileHeader) == 4 * 10);
- }
- };
-
- struct RecordHeader {
- Uint32 id;
- Uint32 total_size;
- Uint64 timestamp;
- };
-
-public:
- bool init() {
- char name[MAXPATHLEN];
- FileHeader header;
-
- /* LLVM places this file in ~/.debug/jit/ maybe we should do that to? */
-
- erts_snprintf(name, sizeof(name), "/tmp/jit-%d.dump", getpid());
-
- file = fopen(name, "w+");
-
- if (file) {
- fwrite(&header, sizeof(header), 1, file);
- /* inform perf of the location of the dump file */
- void *addr = mmap(NULL,
- sizeof(header),
- PROT_READ | PROT_EXEC,
- MAP_PRIVATE,
- fileno(file),
- 0);
- if (addr == MAP_FAILED) {
- int saved_errno = errno;
- erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
- erts_dsprintf(dsbuf,
- "perf: mmap of %s(%d) failed: %d\r\n",
- name,
- fileno(file),
- saved_errno);
- erts_send_error_to_logger_nogl(dsbuf);
- fclose(file);
- file = nullptr;
- return false;
- }
- } else {
- int saved_errno = errno;
- erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
- erts_dsprintf(dsbuf,
- "perf: Failed to open %s (%d)",
- name,
- saved_errno);
- erts_send_error_to_logger_nogl(dsbuf);
- return false;
- }
- return true;
- }
-
- void update_perf_info(std::string modulename,
- std::vector<BeamAssembler::AsmRange> &ranges) {
- struct JitCodeLoadRecord {
- RecordHeader header;
- Uint32 pid;
- Uint32 tid;
- Uint64 vma;
- Uint64 code_addr;
- Uint64 code_size;
- Uint64 code_index;
- /* Null terminated M:F/A */
- /* Native code */
- };
- JitCodeLoadRecord record;
- record.header.id = JIT_CODE_LOAD;
- record.pid = getpid();
- record.tid = erts_thr_self();
- for (BeamAssembler::AsmRange &r : ranges) {
- size_t nameLen = r.name.size();
- ptrdiff_t codeSize = (char *)r.stop - (char *)r.start;
- ASSERT(codeSize >= 0);
- record.header.total_size = sizeof(record) + nameLen + 1 + codeSize;
- record.vma = (Uint64)r.start;
- record.code_addr = (Uint64)r.start;
- record.code_size = (Uint64)codeSize;
- record.code_index = ++code_index;
- record.header.timestamp = erts_os_monotonic_time();
-
- fwrite(&record, sizeof(record), 1, file);
- fwrite(r.name.c_str(), nameLen + 1, 1, file);
- fwrite(r.start, codeSize, 1, file);
- }
- }
-};
-
-# endif
-
-class JitPerfMap {
- FILE *file = nullptr;
-
-public:
- bool init() {
- char name[MAXPATHLEN];
- snprintf(name, sizeof(name), "/tmp/perf-%i.map", getpid());
- file = fopen(name, "w");
- if (!file) {
- int saved_errno = errno;
- erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
- erts_dsprintf(dsbuf,
- "perf: Failed to open %s (%d)",
- name,
- saved_errno);
- erts_send_error_to_logger_nogl(dsbuf);
- return false;
- }
- return true;
- }
- void update_perf_info(std::string modulename,
- std::vector<BeamAssembler::AsmRange> &ranges) {
- for (BeamAssembler::AsmRange &r : ranges) {
- char *start = (char *)r.start, *stop = (char *)r.stop;
- ptrdiff_t size = stop - start;
- fprintf(file, "%p %tx $%s\n", start, size, r.name.c_str());
- }
- fflush(file);
- }
-};
-
-class JitPerfSupport {
- enum PerfModes { NONE = 0, MAP = (1 << 0), DUMP = (1 << 1) };
-
- int modes;
-
- erts_mtx_t mutex;
-# ifdef HAVE_LINUX_PERF_DUMP_SUPPORT
- JitPerfDump perf_dump;
-# endif
- JitPerfMap perf_map;
-
-public:
- JitPerfSupport() : modes(NONE) {
- }
- void init() {
- modes = JitPerfSupport::NONE;
-# ifdef HAVE_LINUX_PERF_DUMP_SUPPORT
- if ((erts_jit_perf_support & BEAMASM_PERF_DUMP) && perf_dump.init()) {
- modes |= JitPerfSupport::DUMP;
- }
-# endif
- if ((erts_jit_perf_support & BEAMASM_PERF_MAP) && perf_map.init()) {
- modes |= JitPerfSupport::MAP;
- }
-
- erts_mtx_init(&mutex,
- "perf",
- NIL,
- ERTS_LOCK_FLAGS_PROPERTY_STATIC |
- ERTS_LOCK_FLAGS_CATEGORY_GENERIC);
- }
-
- void update_perf_info(std::string modulename,
- std::vector<BeamAssembler::AsmRange> &ranges) {
- if (modes) {
- erts_mtx_lock(&mutex);
-# ifdef HAVE_LINUX_PERF_DUMP_SUPPORT
- if (modes & DUMP) {
- perf_dump.update_perf_info(modulename, ranges);
- }
-# endif
- if (modes & MAP) {
- perf_map.update_perf_info(modulename, ranges);
- }
- erts_mtx_unlock(&mutex);
- }
- }
-};
-
-static JitPerfSupport perf;
-
-void beamasm_init_perf() {
- perf.init();
-}
-
-void beamasm_update_perf_info(std::string modulename,
- std::vector<BeamAssembler::AsmRange> &ranges) {
- perf.update_perf_info(modulename, ranges);
-}
-#else
-void beamasm_init_perf() {
-}
-
-void beamasm_update_perf_info(std::string modulename,
- std::vector<BeamAssembler::AsmRange> &ranges) {
-}
-#endif
diff --git a/erts/emulator/beam/jit/x86/generators.tab b/erts/emulator/beam/jit/x86/generators.tab
index 5742414960..4b0b2ad043 100644
--- a/erts/emulator/beam/jit/x86/generators.tab
+++ b/erts/emulator/beam/jit/x86/generators.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2020-2021. All Rights Reserved.
+// Copyright Ericsson AB 2020-2022. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@ gen.select_tuple_arity(Src, Fail, Size, Rest) {
for (i = 3; i < arity; i += 2) {
tmp[i - 2] = Rest[i - 2];
tmp[i - 3].type = TAG_v;
- tmp[i - 3].val = make_arityval(Rest[i - 3].val);
+ tmp[i - 3].val = make_arityval_unchecked(Rest[i - 3].val);
}
/* Sort the values to make them useful for a binary or sentinel search. */
@@ -384,9 +384,13 @@ gen.new_small_map_lit(Dst, Live, Size, Rest) {
$BeamOpArity(op, 4 + size/2);
op->next = NULL;
- tmp = thp = erts_alloc(ERTS_ALC_T_LOADER_TMP, (1 + size/2) * sizeof(*tmp));
- keys = make_tuple(thp);
- *thp++ = make_arityval(size/2);
+ tmp = thp = erts_alloc(ERTS_ALC_T_LOADER_TMP, ((size == 0 ? 0 : 1) + size/2) * sizeof(*tmp));
+ if (size == 0) {
+ keys = erts_get_global_literal(ERTS_LIT_EMPTY_TUPLE);
+ } else {
+ keys = make_tuple(thp);
+ *thp++ = make_arityval(size/2);
+ }
dst = op->a+4;
@@ -528,3 +532,123 @@ gen.allocate_heap_zero(Ns, Nh, Live) {
return alloc;
}
+
+gen.func_end(Func_Label, Entry_Label) {
+ BeamOp *op = NULL;
+
+ if (S->labels[Entry_Label.val].lambda_index != -1) {
+ int index = S->labels[Entry_Label.val].lambda_index;
+ BeamFile_LambdaEntry *lambda_entry;
+
+ lambda_entry = &S->beam.lambdas.entries[index];
+
+ if (lambda_entry->num_free > 0) {
+ BeamOp *lambda;
+
+ $NewBeamOp(S, lambda);
+ $BeamOpNameArity(lambda, i_lambda_trampoline, 4);
+
+ lambda->a[0].type = TAG_u;
+ lambda->a[0].val = index;
+ lambda->a[1] = Entry_Label;
+ lambda->a[2].type = TAG_u;
+ lambda->a[2].val = lambda_entry->arity;
+ lambda->a[3].type = TAG_u;
+ lambda->a[3].val = lambda_entry->num_free;
+
+ lambda->next = op;
+ op = lambda;
+ }
+ }
+
+ if (S->may_load_nif && (S->load_hdr->are_nifs == NULL ||
+ S->load_hdr->are_nifs[S->function_number-1])) {
+ BeamOp *padding;
+
+ $NewBeamOp(S, padding);
+ $BeamOpNameArity(padding, i_nif_padding, 0);
+
+ padding->next = op;
+ op = padding;
+ }
+
+ if (op == NULL) {
+ /* Workaround for the fact that we have to return an instruction from
+ * generators. The loader will remove this dummy instruction. */
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, delete_me, 0);
+
+ op->next = NULL;
+ }
+
+ return op;
+}
+
+gen.create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments) {
+ BeamOp* op;
+ int fixed_args;
+ int i;
+
+ $NewBeamOp(S, op);
+ $BeamOpNameArity(op, i_bs_create_bin, 4);
+ fixed_args = op->arity;
+ $BeamOpArity(op, (N.val + fixed_args));
+
+ op->a[0] = Fail;
+ op->a[1] = Alloc;
+ op->a[2] = Live;
+ op->a[3] = Dst;
+
+ for (i = 0; i < N.val; i += 6) {
+ BeamOpArg Flags;
+ Uint flags = 0;
+
+ /* Copy all but flags. */
+ op->a[i+fixed_args+0] = Segments[i+0];
+ op->a[i+fixed_args+1] = Segments[i+1];
+ op->a[i+fixed_args+2] = Segments[i+2];
+ op->a[i+fixed_args+4] = Segments[i+4];
+ op->a[i+fixed_args+5] = Segments[i+5];
+
+ /* Translate flags. */
+ Flags = Segments[i+3]; /* Flags */
+ if (Flags.type != TAG_n) {
+ if (Flags.type == TAG_q) {
+ Eterm term = beamfile_get_literal(&S->beam, Flags.val);
+ while (is_list(term)) {
+ Eterm* consp = list_val(term);
+ Eterm elem = CAR(consp);
+ switch (elem) {
+ case am_little:
+ flags |= BSF_LITTLE;
+ break;
+ case am_native:
+ flags |= BSF_NATIVE;
+ break;
+ }
+ term = CDR(consp);
+ }
+ ASSERT(is_nil(term));
+ }
+ }
+ Flags.type = TAG_u;
+ Flags.val = flags;
+ $NativeEndian(Flags);
+ op->a[i+fixed_args+3] = Flags;
+ }
+
+ if (op->a[4].val == am_private_append && Alloc.val != 0) {
+ BeamOp* th;
+ $NewBeamOp(S, th);
+ $BeamOpNameArity(th, test_heap, 2);
+ th->a[0] = Alloc;
+ th->a[1] = Live;
+ th->next = op;
+
+ op->a[1].val = 0;
+
+ op = th;
+ }
+
+ return op;
+}
diff --git a/erts/emulator/beam/jit/x86/instr_arith.cpp b/erts/emulator/beam/jit/x86/instr_arith.cpp
index 43cb6137c1..31d6ff2631 100644
--- a/erts/emulator/beam/jit/x86/instr_arith.cpp
+++ b/erts/emulator/beam/jit/x86/instr_arith.cpp
@@ -27,48 +27,76 @@
extern "C"
{
+#include "big.h"
#include "erl_bif_table.h"
}
-void BeamModuleAssembler::emit_bif_arg_error(std::vector<ArgVal> args,
- const ErtsCodeMFA *mfa) {
- comment("handle_error");
- for (unsigned i = 0; i < args.size(); i++)
- mov_arg(ArgVal(ArgVal::x, i), args[i]);
- emit_handle_error(mfa);
-}
-
-void BeamModuleAssembler::emit_is_small(Label fail, x86::Gp Reg) {
+void BeamModuleAssembler::emit_is_small(Label fail,
+ const ArgSource &Arg,
+ x86::Gp Reg) {
ASSERT(ARG1 != Reg);
- comment("is_small(X)");
- a.mov(ARG1d, Reg.r32());
- a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
- a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(fail);
+ if (always_small(Arg)) {
+ comment("skipped test for small operand since it is always small");
+ } else if (always_one_of(Arg, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operand since it is a number");
+ a.test(Reg.r32(), imm(TAG_PRIMARY_LIST));
+ a.short_().je(fail);
+ } else {
+ comment("is the operand small?");
+ a.mov(ARG1d, Reg.r32());
+ a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
+ a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
+ a.short_().jne(fail);
+ }
}
-void BeamModuleAssembler::emit_is_both_small(Label fail, x86::Gp A, x86::Gp B) {
+void BeamModuleAssembler::emit_are_both_small(Label fail,
+ const ArgSource &LHS,
+ x86::Gp A,
+ const ArgSource &RHS,
+ x86::Gp B) {
ASSERT(ARG1 != A && ARG1 != B);
-
- comment("is_both_small(X, Y)");
- if (A != RET && B != RET) {
- a.mov(RETd, A.r32());
- a.and_(RETd, B.r32());
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ } else if (always_one_of(LHS, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER) &&
+ always_one_of(RHS, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operands since both are numbers");
+ if (always_small(RHS)) {
+ a.test(A.r32(), imm(TAG_PRIMARY_LIST));
+ } else if (always_small(LHS)) {
+ a.test(B.r32(), imm(TAG_PRIMARY_LIST));
+ } else if (A != RET && B != RET) {
+ a.mov(RETd, A.r32());
+ a.and_(RETd, B.r32());
+ a.test(RETb, imm(TAG_PRIMARY_LIST));
+ } else {
+ a.mov(ARG1d, A.r32());
+ a.and_(ARG1d, B.r32());
+ a.test(ARG1d, imm(TAG_PRIMARY_LIST));
+ }
+ a.short_().je(fail);
} else {
- a.mov(ARG1d, A.r32());
- a.and_(ARG1d, B.r32());
- a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
- a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
+ comment("are both operands small?");
+ if (A != RET && B != RET) {
+ a.mov(RETd, A.r32());
+ a.and_(RETd, B.r32());
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ } else {
+ a.mov(ARG1d, A.r32());
+ a.and_(ARG1d, B.r32());
+ a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
+ a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
+ }
+ a.short_().jne(fail);
}
- a.short_().jne(fail);
}
void BeamGlobalAssembler::emit_increment_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -76,36 +104,63 @@ void BeamGlobalAssembler::emit_increment_body_shared() {
runtime_call<3>(erts_mixed_plus);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
-
a.ret();
a.bind(error);
{
mov_imm(ARG4, 0);
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
-void BeamModuleAssembler::emit_i_increment(const ArgVal &Src,
- const ArgVal &Val,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_increment(const ArgRegister &Src,
+ const ArgWord &Val,
+ const ArgRegister &Dst) {
+ ArgVal tagged_val = ArgVal(ArgVal::Immediate, make_small(Val.get()));
+
+ if (is_sum_small(Src, tagged_val)) {
+ Uint shifted_val = Val.get() << _TAG_IMMED1_SIZE;
+
+ comment("skipped operand and overflow checks");
+ mov_arg(RET, Src);
+ if (Support::isInt32(shifted_val)) {
+ a.add(RET, imm(shifted_val));
+ } else {
+ mov_imm(ARG1, shifted_val);
+ a.add(RET, ARG1);
+ }
+ mov_arg(Dst, RET);
+
+ return;
+ }
+
Label mixed = a.newLabel(), next = a.newLabel();
/* Place the values in ARG2 and ARG3 to prepare for the mixed call. Note
* that ARG3 is untagged at this point */
mov_arg(ARG2, Src);
- mov_imm(ARG3, Val.getValue() << _TAG_IMMED1_SIZE);
- a.mov(RETd, ARG2d);
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(mixed);
-
- a.mov(RET, ARG2);
- a.add(RET, ARG3);
- a.short_().jno(next);
+ mov_imm(ARG3, Val.get() << _TAG_IMMED1_SIZE);
+
+ if (always_one_of(Src, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operand since it is a number");
+ a.mov(RET, ARG2);
+ a.test(RETb, imm(TAG_PRIMARY_LIST));
+ a.short_().je(mixed);
+ a.add(RET, ARG3);
+ a.short_().jno(next);
+ } else {
+ a.mov(RETd, ARG2d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.short_().jne(mixed);
+ a.mov(RET, ARG2);
+ a.add(RET, ARG3);
+ a.short_().jno(next);
+ }
a.bind(mixed);
safe_fragment_call(ga->get_increment_body_shared());
@@ -120,6 +175,7 @@ void BeamGlobalAssembler::emit_plus_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime();
/* Save original arguments for the error path. */
@@ -130,10 +186,10 @@ void BeamGlobalAssembler::emit_plus_body_shared() {
runtime_call<3>(erts_mixed_plus);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
-
a.ret();
a.bind(error);
@@ -145,11 +201,12 @@ void BeamGlobalAssembler::emit_plus_body_shared() {
a.mov(getXRef(1), ARG2);
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
void BeamGlobalAssembler::emit_plus_guard_shared() {
+ emit_enter_frame();
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -157,21 +214,33 @@ void BeamGlobalAssembler::emit_plus_guard_shared() {
runtime_call<3>(erts_mixed_plus);
emit_leave_runtime();
+ emit_leave_frame();
/* Set ZF if the addition failed. */
emit_test_the_non_value(RET);
a.ret();
}
-void BeamModuleAssembler::emit_i_plus(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_plus(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ if (is_sum_small(LHS, RHS)) {
+ comment("add without overflow check");
+ mov_arg(RET, LHS);
+ mov_arg(ARG2, RHS);
+ a.and_(RET, imm(~_TAG_IMMED1_MASK));
+ a.add(RET, ARG2);
+ mov_arg(Dst, RET);
+
+ return;
+ }
+
Label next = a.newLabel(), mixed = a.newLabel();
mov_arg(ARG2, LHS); /* Used by erts_mixed_plus in this slot */
mov_arg(ARG3, RHS); /* Used by erts_mixed_plus in this slot */
- emit_is_both_small(mixed, ARG2, ARG3);
+ emit_are_both_small(mixed, LHS, ARG2, RHS, ARG3);
comment("add with overflow check");
a.mov(RET, ARG2);
@@ -183,9 +252,9 @@ void BeamModuleAssembler::emit_i_plus(const ArgVal &LHS,
/* Call mixed addition. */
a.bind(mixed);
{
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_plus_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_plus_body_shared());
}
@@ -200,6 +269,7 @@ void BeamGlobalAssembler::emit_minus_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime();
/* Save original arguments for the error path. */
@@ -210,10 +280,10 @@ void BeamGlobalAssembler::emit_minus_body_shared() {
runtime_call<3>(erts_mixed_minus);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
-
a.ret();
a.bind(error);
@@ -225,11 +295,12 @@ void BeamGlobalAssembler::emit_minus_body_shared() {
a.mov(getXRef(1), ARG2);
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
void BeamGlobalAssembler::emit_minus_guard_shared() {
+ emit_enter_frame();
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -237,32 +308,34 @@ void BeamGlobalAssembler::emit_minus_guard_shared() {
runtime_call<3>(erts_mixed_minus);
emit_leave_runtime();
+ emit_leave_frame();
/* Set ZF if the addition failed. */
emit_test_the_non_value(RET);
a.ret();
}
-void BeamModuleAssembler::emit_i_minus(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_minus(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ if (is_difference_small(LHS, RHS)) {
+ comment("subtract without overflow check");
+ mov_arg(RET, LHS);
+ mov_arg(ARG2, RHS);
+ a.and_(ARG2, imm(~_TAG_IMMED1_MASK));
+ a.sub(RET, ARG2);
+ mov_arg(Dst, RET);
+
+ return;
+ }
+
Label next = a.newLabel(), mixed = a.newLabel();
mov_arg(ARG2, LHS); /* Used by erts_mixed_plus in this slot */
mov_arg(ARG3, RHS); /* Used by erts_mixed_plus in this slot */
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- a.mov(RETd, ARG2d);
- } else if (LHS.isImmed() && is_small(LHS.getValue())) {
- a.mov(RETd, ARG3d);
- } else {
- a.mov(RETd, ARG2d);
- a.and_(RETd, ARG3d);
- }
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(mixed);
+ emit_are_both_small(mixed, LHS, ARG2, RHS, ARG3);
comment("sub with overflow check");
a.mov(RET, ARG2);
@@ -272,9 +345,9 @@ void BeamModuleAssembler::emit_i_minus(const ArgVal &LHS,
a.short_().jno(next);
a.bind(mixed);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_minus_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_minus_body_shared());
}
@@ -288,6 +361,7 @@ void BeamGlobalAssembler::emit_unary_minus_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime();
/* Save original arguments for the error path. */
@@ -297,10 +371,10 @@ void BeamGlobalAssembler::emit_unary_minus_body_shared() {
runtime_call<2>(erts_unary_minus);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
-
a.ret();
a.bind(error);
@@ -310,11 +384,12 @@ void BeamGlobalAssembler::emit_unary_minus_body_shared() {
a.mov(getXRef(0), ARG1);
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
void BeamGlobalAssembler::emit_unary_minus_guard_shared() {
+ emit_enter_frame();
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -322,15 +397,29 @@ void BeamGlobalAssembler::emit_unary_minus_guard_shared() {
runtime_call<2>(erts_unary_minus);
emit_leave_runtime();
+ emit_leave_frame();
/* Set ZF if the negation failed. */
emit_test_the_non_value(RET);
a.ret();
}
-void BeamModuleAssembler::emit_i_unary_minus(const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_unary_minus(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ ArgVal zero = ArgVal(ArgVal::Immediate, make_small(0));
+
+ if (is_difference_small(zero, Src)) {
+ comment("negation without overflow test");
+ mov_arg(ARG2, Src);
+ a.mov(RETd, imm(_TAG_IMMED1_SMALL));
+ a.and_(ARG2, imm(~_TAG_IMMED1_MASK));
+ a.sub(RET, ARG2);
+ mov_arg(Dst, RET);
+
+ return;
+ }
+
Label next = a.newLabel(), mixed = a.newLabel();
mov_arg(ARG2, Src);
@@ -348,9 +437,9 @@ void BeamModuleAssembler::emit_i_unary_minus(const ArgVal &Src,
a.short_().jno(next);
a.bind(mixed);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_unary_minus_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_unary_minus_body_shared());
}
@@ -368,6 +457,8 @@ void BeamModuleAssembler::emit_i_unary_minus(const ArgVal &Src,
void BeamGlobalAssembler::emit_int_div_rem_guard_shared() {
Label exit = a.newLabel(), generic = a.newLabel();
+ emit_enter_frame();
+
a.cmp(ARG4, imm(SMALL_ZERO));
a.je(exit);
@@ -430,7 +521,10 @@ void BeamGlobalAssembler::emit_int_div_rem_guard_shared() {
/* Return with a potential error in ZF. It will be set if we came here from
* the guard against SMALL_ZERO or if we're returning THE_NON_VALUE. */
a.bind(exit);
- a.ret();
+ {
+ emit_leave_frame();
+ a.ret();
+ }
}
/* ARG1 = LHS, ARG4 (!) = RHS, ARG5 = error MFA
@@ -441,7 +535,9 @@ void BeamGlobalAssembler::emit_int_div_rem_guard_shared() {
* Quotient is returned in RAX, remainder in RDX. */
void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
Label div_zero = a.newLabel(), generic_div = a.newLabel(),
- generic_error = a.newLabel(), error = a.newLabel();
+ generic_error = a.newLabel();
+
+ emit_enter_frame();
a.cmp(ARG4, imm(SMALL_ZERO));
a.je(div_zero);
@@ -477,6 +573,7 @@ void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
a.cmp(ARG6, imm(1));
a.short_().jge(generic_div);
+ emit_leave_frame();
a.ret();
a.bind(generic_div);
@@ -496,6 +593,7 @@ void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
runtime_call<5>(erts_int_div_rem);
emit_leave_runtime();
+ emit_leave_frame();
/* erts_int_div returns 0 on failure and 1 on success. */
a.test(RETd, RETd);
@@ -510,6 +608,8 @@ void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
a.bind(div_zero);
{
+ emit_leave_frame();
+
/* Set up a badarith exception and place the original arguments in
* x-registers. */
a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)),
@@ -519,7 +619,7 @@ void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
a.mov(getXRef(1), ARG4);
a.mov(ARG4, ARG5);
- a.short_().jmp(error);
+ a.jmp(labels[raise_exception]);
}
a.bind(generic_error);
@@ -532,37 +632,95 @@ void BeamGlobalAssembler::emit_int_div_rem_body_shared() {
/* Read saved MFA. */
a.mov(ARG4, TMP_MEM3q);
+ a.jmp(labels[raise_exception]);
+ }
+}
- /* Fall through to `error` */
+void BeamModuleAssembler::emit_div_rem(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ErtsCodeMFA *error_mfa,
+ bool need_div,
+ bool need_rem) {
+ Label generic_div = a.newLabel(), next = a.newLabel();
+ bool need_generic = true;
+ Sint divisor = 0;
+
+ if (RHS.isSmall()) {
+ divisor = RHS.as<ArgSmall>().getSigned();
}
- a.bind(error);
- emit_handle_error_shared_prologue();
-}
+ if (divisor != (Sint)0 && divisor != (Sint)-1) {
+ /* There is no possibility of overflow. */
+ a.mov(ARG6, imm(divisor));
+ mov_arg(x86::rax, LHS);
+ if (always_small(LHS)) {
+ comment("skipped test for small dividend since it is always small");
+ need_generic = false;
+ } else if (always_one_of(LHS, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small dividend since it is an "
+ "integer");
+ a.mov(ARG2d, x86::eax);
+ a.test(ARG2d, imm(TAG_PRIMARY_LIST));
+ a.short_().je(generic_div);
+ } else {
+ comment("testing for a small dividend");
+ a.mov(ARG2d, x86::eax);
+ a.and_(ARG2d, imm(_TAG_IMMED1_MASK));
+ a.cmp(ARG2d, imm(_TAG_IMMED1_SMALL));
+ a.short_().jne(generic_div);
+ }
-void BeamModuleAssembler::emit_div_rem(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ErtsCodeMFA *error_mfa) {
- mov_arg(ARG4, RHS); /* Done first as mov_arg may clobber ARG1 */
- mov_arg(ARG1, LHS);
-
- /* TODO: Specialize division with immediates, either here or in the
- * compiler. */
- if (Fail.getValue() != 0) {
- safe_fragment_call(ga->get_int_div_rem_guard_shared());
- a.je(labels[Fail.getValue()]);
- } else {
- a.mov(ARG5, imm(error_mfa));
- safe_fragment_call(ga->get_int_div_rem_body_shared());
+ /* Sign-extend and divide. The result is implicitly placed in
+ * RAX and the remainder in RDX (ARG3). */
+ comment("divide with inlined code");
+ a.sar(x86::rax, imm(_TAG_IMMED1_SIZE));
+ a.cqo();
+ a.idiv(ARG6);
+
+ if (need_div) {
+ a.sal(x86::rax, imm(_TAG_IMMED1_SIZE));
+ }
+
+ if (need_rem) {
+ a.sal(x86::rdx, imm(_TAG_IMMED1_SIZE));
+ }
+
+ if (need_div) {
+ a.or_(x86::rax, imm(_TAG_IMMED1_SMALL));
+ }
+
+ if (need_rem) {
+ a.or_(x86::rdx, imm(_TAG_IMMED1_SMALL));
+ }
+
+ if (need_generic) {
+ a.short_().jmp(next);
+ }
}
+
+ a.bind(generic_div);
+ if (need_generic) {
+ mov_arg(ARG4, RHS); /* Done first as mov_arg may clobber ARG1 */
+ mov_arg(ARG1, LHS);
+
+ if (Fail.get() != 0) {
+ safe_fragment_call(ga->get_int_div_rem_guard_shared());
+ a.je(resolve_beam_label(Fail));
+ } else {
+ a.mov(ARG5, imm(error_mfa));
+ safe_fragment_call(ga->get_int_div_rem_body_shared());
+ }
+ }
+
+ a.bind(next);
}
-void BeamModuleAssembler::emit_i_rem_div(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Remainder,
- const ArgVal &Quotient) {
+void BeamModuleAssembler::emit_i_rem_div(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Remainder,
+ const ArgRegister &Quotient) {
static const ErtsCodeMFA bif_mfa = {am_erlang, am_rem, 2};
emit_div_rem(Fail, LHS, RHS, &bif_mfa);
@@ -571,11 +729,11 @@ void BeamModuleAssembler::emit_i_rem_div(const ArgVal &LHS,
mov_arg(Quotient, x86::rax);
}
-void BeamModuleAssembler::emit_i_div_rem(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Quotient,
- const ArgVal &Remainder) {
+void BeamModuleAssembler::emit_i_div_rem(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Quotient,
+ const ArgRegister &Remainder) {
static const ErtsCodeMFA bif_mfa = {am_erlang, am_div, 2};
emit_div_rem(Fail, LHS, RHS, &bif_mfa);
@@ -584,32 +742,32 @@ void BeamModuleAssembler::emit_i_div_rem(const ArgVal &LHS,
mov_arg(Remainder, x86::rdx);
}
-void BeamModuleAssembler::emit_i_int_div(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Quotient) {
+void BeamModuleAssembler::emit_i_int_div(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Quotient) {
static const ErtsCodeMFA bif_mfa = {am_erlang, am_div, 2};
- emit_div_rem(Fail, LHS, RHS, &bif_mfa);
+ emit_div_rem(Fail, LHS, RHS, &bif_mfa, true, false);
mov_arg(Quotient, x86::rax);
}
-void BeamModuleAssembler::emit_i_rem(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Remainder) {
+void BeamModuleAssembler::emit_i_rem(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Remainder) {
static const ErtsCodeMFA bif_mfa = {am_erlang, am_rem, 2};
- emit_div_rem(Fail, LHS, RHS, &bif_mfa);
+ emit_div_rem(Fail, LHS, RHS, &bif_mfa, false, true);
mov_arg(Remainder, x86::rdx);
}
-void BeamModuleAssembler::emit_i_m_div(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_m_div(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
static const ErtsCodeMFA bif_mfa = {am_erlang, am_Div, 2};
Label next = a.newLabel();
@@ -627,110 +785,65 @@ void BeamModuleAssembler::emit_i_m_div(const ArgVal &Fail,
emit_test_the_non_value(RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.je(resolve_beam_label(Fail));
} else {
a.short_().jne(next);
- emit_bif_arg_error({LHS, RHS}, &bif_mfa);
+
+ mov_arg(ARG2, LHS);
+ mov_arg(ARG3, RHS);
+ mov_arg(ArgXRegister(0), ARG2);
+ mov_arg(ArgXRegister(1), ARG3);
+
+ emit_raise_exception(&bif_mfa);
}
a.bind(next);
mov_arg(Dst, RET);
}
-/* ARG1 = LHS, ARG4 (!) = RHS
- *
- * We avoid using ARG2 and ARG3 because multiplication clobbers RDX, which is
- * ARG2 on Windows and ARG3 on SystemV.
+/* ARG2 = LHS, ARG3 (!) = RHS
*
* Result is returned in RET, error is indicated by ZF. */
void BeamGlobalAssembler::emit_times_guard_shared() {
- Label generic = a.newLabel();
+ emit_enter_frame();
+ emit_enter_runtime();
- /* Are both smalls? */
- a.mov(ARG2d, ARG1d);
- a.and_(ARG2d, ARG4d);
- a.and_(ARG2d, imm(_TAG_IMMED1_MASK));
- a.cmp(ARG2d, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(generic);
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_times);
- a.mov(RET, ARG1);
- a.mov(ARG2, ARG4);
- a.and_(RET, imm(~_TAG_IMMED1_MASK));
- a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
- a.imul(RET, ARG2); /* Clobbers RDX */
- a.short_().jo(generic);
+ emit_leave_runtime();
+ emit_leave_frame();
- a.or_(RET, imm(_TAG_IMMED1_SMALL)); /* Always sets ZF to false */
+ emit_test_the_non_value(RET); /* Sets ZF for use in caller */
a.ret();
-
- a.bind(generic);
- {
- emit_enter_runtime();
-
- a.mov(ARG2, ARG1);
- a.mov(ARG3, ARG4);
- a.mov(ARG1, c_p);
- runtime_call<3>(erts_mixed_times);
-
- emit_leave_runtime();
-
- emit_test_the_non_value(RET); /* Sets ZF for use in caller */
-
- a.ret();
- }
}
-/* ARG1 = LHS, ARG4 (!) = RHS
- *
- * We avoid using ARG2 and ARG3 because multiplication clobbers RDX, which is
- * ARG2 on Windows and ARG3 on SystemV.
+/* ARG2 = LHS, ARG3 (!) = RHS
*
* Result is returned in RET. */
void BeamGlobalAssembler::emit_times_body_shared() {
static const ErtsCodeMFA bif_mfa = {am_erlang, am_Times, 2};
- Label generic = a.newLabel(), error = a.newLabel();
-
- /* Are both smalls? */
- a.mov(ARG2d, ARG1d);
- a.and_(ARG2d, ARG4d);
- a.and_(ARG2d, imm(_TAG_IMMED1_MASK));
- a.cmp(ARG2, imm(_TAG_IMMED1_SMALL));
- a.jne(generic);
-
- a.mov(RET, ARG1);
- a.mov(ARG2, ARG4);
- a.and_(RET, imm(~_TAG_IMMED1_MASK));
- a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
- a.imul(RET, ARG2); /* Clobbers RDX */
- a.short_().jo(generic);
-
- a.or_(RET, imm(_TAG_IMMED1_SMALL));
-
- a.ret();
-
- a.bind(generic);
- {
- emit_enter_runtime();
+ Label error = a.newLabel();
- /* Save original arguments for the error path. */
- a.mov(TMP_MEM1q, ARG1);
- a.mov(TMP_MEM2q, ARG4);
+ emit_enter_frame();
+ emit_enter_runtime();
- a.mov(ARG2, ARG1);
- a.mov(ARG3, ARG4);
- a.mov(ARG1, c_p);
- runtime_call<3>(erts_mixed_times);
+ /* Save original arguments for the error path. */
+ a.mov(TMP_MEM1q, ARG2);
+ a.mov(TMP_MEM2q, ARG3);
- emit_leave_runtime();
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_mixed_times);
- emit_test_the_non_value(RET);
- a.short_().je(error);
+ emit_leave_runtime();
+ emit_leave_frame();
- a.ret();
- }
+ emit_test_the_non_value(RET);
+ a.short_().je(error);
+ a.ret();
a.bind(error);
{
@@ -741,26 +854,69 @@ void BeamGlobalAssembler::emit_times_body_shared() {
a.mov(getXRef(1), ARG2);
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
-void BeamModuleAssembler::emit_i_times(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- mov_arg(ARG4, RHS); /* Done first as mov_arg may clobber ARG1 */
- mov_arg(ARG1, LHS);
-
- /* TODO: Specialize multiplication with immediates, either here or in the
- * compiler. */
- if (Fail.getValue() != 0) {
- safe_fragment_call(ga->get_times_guard_shared());
- a.je(labels[Fail.getValue()]);
+void BeamModuleAssembler::emit_i_times(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ if (is_product_small(LHS, RHS)) {
+ comment("multiplication without overflow check");
+ mov_arg(RET, LHS);
+ mov_arg(ARG2, RHS);
+ a.and_(RET, imm(~_TAG_IMMED1_MASK));
+ a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
+ a.imul(RET, ARG2);
+ a.or_(RET, imm(_TAG_IMMED1_SMALL));
+ mov_arg(Dst, RET);
+ return;
+ }
+
+ Label next = a.newLabel(), mixed = a.newLabel();
+
+ mov_arg(ARG2, LHS); /* Used by erts_mixed_times in this slot */
+ mov_arg(ARG3, RHS); /* Used by erts_mixed_times in this slot */
+
+ if (RHS.isSmall()) {
+ Sint val = RHS.as<ArgSmall>().getSigned();
+ emit_is_small(mixed, LHS, ARG2);
+ comment("mul with overflow check, imm RHS");
+ a.mov(RET, ARG2);
+ a.mov(ARG4, imm(val));
+ } else if (LHS.isSmall()) {
+ Sint val = LHS.as<ArgSmall>().getSigned();
+ emit_is_small(mixed, RHS, ARG3);
+ comment("mul with overflow check, imm LHS");
+ a.mov(RET, ARG3);
+ a.mov(ARG4, imm(val));
} else {
- safe_fragment_call(ga->get_times_body_shared());
+ emit_are_both_small(mixed, LHS, ARG2, RHS, ARG3);
+ comment("mul with overflow check");
+ a.mov(RET, ARG2);
+ a.mov(ARG4, ARG3);
+ a.sar(ARG4, imm(_TAG_IMMED1_SIZE));
}
+ a.and_(RET, imm(~_TAG_IMMED1_MASK));
+ a.imul(RET, ARG4);
+ a.short_().jo(mixed);
+ a.or_(RET, imm(_TAG_IMMED1_SMALL));
+ a.short_().jmp(next);
+
+ /* Call mixed multiplication. */
+ a.bind(mixed);
+ {
+ if (Fail.get() != 0) {
+ safe_fragment_call(ga->get_times_guard_shared());
+ a.je(resolve_beam_label(Fail));
+ } else {
+ safe_fragment_call(ga->get_times_body_shared());
+ }
+ }
+
+ a.bind(next);
mov_arg(Dst, RET);
}
@@ -769,6 +925,7 @@ void BeamModuleAssembler::emit_i_times(const ArgVal &Fail,
* Result is returned in RET. Error is indicated by ZF. */
template<typename T>
void BeamGlobalAssembler::emit_bitwise_fallback_guard(T(*func_ptr)) {
+ emit_enter_frame();
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -777,6 +934,7 @@ void BeamGlobalAssembler::emit_bitwise_fallback_guard(T(*func_ptr)) {
runtime_call<3>(func_ptr);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.ret();
@@ -790,6 +948,7 @@ void BeamGlobalAssembler::emit_bitwise_fallback_body(T(*func_ptr),
const ErtsCodeMFA *mfa) {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime();
/* Save original arguments for the error path. */
@@ -802,10 +961,10 @@ void BeamGlobalAssembler::emit_bitwise_fallback_body(T(*func_ptr),
runtime_call<3>(func_ptr);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
-
a.ret();
a.bind(error);
@@ -817,7 +976,7 @@ void BeamGlobalAssembler::emit_bitwise_fallback_body(T(*func_ptr),
a.mov(getXRef(1), ARG2);
a.mov(ARG4, imm(mfa));
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
@@ -830,19 +989,26 @@ void BeamGlobalAssembler::emit_i_band_body_shared() {
emit_bitwise_fallback_body(erts_band, &bif_mfa);
}
-void BeamModuleAssembler::emit_i_band(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Dst) {
- Label generic = a.newLabel(), next = a.newLabel();
-
+void BeamModuleAssembler::emit_i_band(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
mov_arg(ARG2, LHS);
mov_arg(RET, RHS);
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- emit_is_small(generic, ARG2);
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ a.and_(RET, ARG2);
+ mov_arg(Dst, RET);
+ return;
+ }
+
+ Label generic = a.newLabel(), next = a.newLabel();
+
+ if (always_small(RHS)) {
+ emit_is_small(generic, LHS, ARG2);
} else {
- emit_is_both_small(generic, RET, ARG2);
+ emit_are_both_small(generic, LHS, ARG2, RHS, RET);
}
/* TAG & TAG = TAG, so we don't need to tag it again. */
@@ -851,9 +1017,9 @@ void BeamModuleAssembler::emit_i_band(const ArgVal &LHS,
a.bind(generic);
{
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_band_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_band_body_shared());
}
@@ -878,19 +1044,26 @@ void BeamGlobalAssembler::emit_i_bor_body_shared() {
emit_bitwise_fallback_body(erts_bor, &bif_mfa);
}
-void BeamModuleAssembler::emit_i_bor(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- Label generic = a.newLabel(), next = a.newLabel();
-
+void BeamModuleAssembler::emit_i_bor(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
mov_arg(ARG2, LHS);
mov_arg(RET, RHS);
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- emit_is_small(generic, ARG2);
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ a.or_(RET, ARG2);
+ mov_arg(Dst, RET);
+ return;
+ }
+
+ Label generic = a.newLabel(), next = a.newLabel();
+
+ if (always_small(RHS)) {
+ emit_is_small(generic, LHS, ARG2);
} else {
- emit_is_both_small(generic, RET, ARG2);
+ emit_are_both_small(generic, LHS, ARG2, RHS, RET);
}
/* TAG | TAG = TAG, so we don't need to tag it again. */
@@ -899,9 +1072,9 @@ void BeamModuleAssembler::emit_i_bor(const ArgVal &Fail,
a.bind(generic);
{
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bor_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bor_body_shared());
}
@@ -926,19 +1099,28 @@ void BeamGlobalAssembler::emit_i_bxor_body_shared() {
emit_bitwise_fallback_body(erts_bxor, &bif_mfa);
}
-void BeamModuleAssembler::emit_i_bxor(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- Label generic = a.newLabel(), next = a.newLabel();
-
+void BeamModuleAssembler::emit_i_bxor(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
mov_arg(ARG2, LHS);
mov_arg(RET, RHS);
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- emit_is_small(generic, ARG2);
+ if (always_small(LHS) && always_small(RHS)) {
+ comment("skipped test for small operands since they are always small");
+ /* TAG ^ TAG = 0, so we need to tag it again. */
+ a.xor_(RET, ARG2);
+ a.or_(RET, imm(_TAG_IMMED1_SMALL));
+ mov_arg(Dst, RET);
+ return;
+ }
+
+ Label generic = a.newLabel(), next = a.newLabel();
+
+ if (always_small(RHS)) {
+ emit_is_small(generic, LHS, ARG2);
} else {
- emit_is_both_small(generic, RET, ARG2);
+ emit_are_both_small(generic, LHS, ARG2, RHS, RET);
}
/* TAG ^ TAG = 0, so we need to tag it again. */
@@ -948,9 +1130,9 @@ void BeamModuleAssembler::emit_i_bxor(const ArgVal &Fail,
a.bind(generic);
{
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bxor_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bxor_body_shared());
}
@@ -964,6 +1146,8 @@ void BeamModuleAssembler::emit_i_bxor(const ArgVal &Fail,
*
* Result is returned in RET. Error is indicated by ZF. */
void BeamGlobalAssembler::emit_i_bnot_guard_shared() {
+ emit_enter_frame();
+
/* Undo the speculative inversion in module code */
a.xor_(RET, imm(~_TAG_IMMED1_MASK));
@@ -974,6 +1158,7 @@ void BeamGlobalAssembler::emit_i_bnot_guard_shared() {
runtime_call<2>(erts_bnot);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.ret();
@@ -987,6 +1172,8 @@ void BeamGlobalAssembler::emit_i_bnot_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
+
/* Undo the speculative inversion in module code */
a.xor_(RET, imm(~_TAG_IMMED1_MASK));
@@ -1000,10 +1187,10 @@ void BeamGlobalAssembler::emit_i_bnot_body_shared() {
runtime_call<2>(erts_bnot);
emit_leave_runtime();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
-
a.ret();
a.bind(error);
@@ -1013,13 +1200,13 @@ void BeamGlobalAssembler::emit_i_bnot_body_shared() {
a.mov(getXRef(0), ARG1);
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error_shared_prologue();
+ a.jmp(labels[raise_exception]);
}
}
-void BeamModuleAssembler::emit_i_bnot(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bnot(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgRegister &Dst) {
Label next = a.newLabel();
mov_arg(RET, Src);
@@ -1029,14 +1216,20 @@ void BeamModuleAssembler::emit_i_bnot(const ArgVal &Fail,
/* Fall through to the generic path if the result is not a small, where the
* above operation will be reverted. */
- a.mov(ARG1d, RETd);
- a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
- a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
- a.short_().je(next);
+ if (always_one_of(Src, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small operand since it is a number");
+ a.test(RETb, imm(TAG_PRIMARY_LIST));
+ a.short_().jne(next);
+ } else {
+ a.mov(ARG1d, RETd);
+ a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
+ a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
+ a.short_().je(next);
+ }
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bnot_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bnot_body_shared());
}
@@ -1060,19 +1253,26 @@ void BeamGlobalAssembler::emit_i_bsr_body_shared() {
emit_bitwise_fallback_body(erts_bsr, &bif_mfa);
}
-void BeamModuleAssembler::emit_i_bsr(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bsr(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
Label generic = a.newLabel(), next = a.newLabel();
+ bool need_generic = true;
mov_arg(ARG2, LHS);
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- Sint shift = signed_val(RHS.getValue());
+ if (RHS.isSmall()) {
+ Sint shift = RHS.as<ArgSmall>().getSigned();
if (shift >= 0 && shift < SMALL_BITS - 1) {
- emit_is_small(generic, ARG2);
+ if (always_small(LHS)) {
+ comment("skipped test for small left operand because it is "
+ "always small");
+ need_generic = false;
+ } else {
+ emit_is_small(generic, LHS, ARG2);
+ }
a.mov(RET, ARG2);
@@ -1082,7 +1282,9 @@ void BeamModuleAssembler::emit_i_bsr(const ArgVal &LHS,
a.sar(RET, imm(shift));
a.or_(RET, imm(_TAG_IMMED1_SMALL));
- a.short_().jmp(next);
+ if (need_generic) {
+ a.short_().jmp(next);
+ }
} else {
/* Constant shift is negative or too big to fit the `sar`
* instruction, fall back to the generic path. */
@@ -1090,12 +1292,12 @@ void BeamModuleAssembler::emit_i_bsr(const ArgVal &LHS,
}
a.bind(generic);
- {
+ if (need_generic) {
mov_arg(RET, RHS);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bsr_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bsr_body_shared());
}
@@ -1127,21 +1329,24 @@ static int count_leading_zeroes(UWord value) {
return word_bits;
}
- UWord mask = UWORD_CONSTANT(1) << (word_bits - 1);
- int count = 0;
+ return Support::clz(value);
+}
- while ((value & mask) == 0) {
- mask >>= 1;
- count++;
+void BeamModuleAssembler::emit_i_bsl(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ if (is_bsl_small(LHS, RHS)) {
+ comment("skipped tests because operands and result are always small");
+ mov_arg(RET, LHS);
+ ERTS_CT_ASSERT(_TAG_IMMED1_MASK == _TAG_IMMED1_SMALL);
+ a.xor_(RET, imm(_TAG_IMMED1_MASK));
+ a.sal(RET, imm(RHS.as<ArgSmall>().getSigned()));
+ a.or_(RET, imm(_TAG_IMMED1_SMALL));
+ mov_arg(Dst, RET);
+ return;
}
- return count;
-}
-
-void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Fail,
- const ArgVal &Dst) {
bool inline_shift = hasCpuFeature(CpuFeatures::X86::kLZCNT);
Label generic = a.newLabel(), next = a.newLabel();
@@ -1155,12 +1360,12 @@ void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
} else if (LHS.isLiteral() || RHS.isLiteral()) {
/* At least one argument is not a small. */
inline_shift = false;
- } else if (LHS.isImmed() && !is_small(LHS.getValue())) {
+ } else if (LHS.isImmed() && !LHS.isSmall()) {
/* Invalid constant. */
inline_shift = false;
} else if (RHS.isImmed() &&
- (!is_small(RHS.getValue()) || signed_val(RHS.getValue()) < 0 ||
- signed_val(RHS.getValue()) >= SMALL_BITS - 1)) {
+ (!RHS.isSmall() || RHS.as<ArgSmall>().getSigned() < 0 ||
+ RHS.as<ArgSmall>().getSigned() >= SMALL_BITS - 1)) {
/* Constant shift is invalid or always produces a bignum. */
inline_shift = false;
}
@@ -1170,7 +1375,7 @@ void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
ASSERT(!(LHS.isImmed() && RHS.isImmed()));
- if (LHS.isMem()) {
+ if (LHS.isRegister()) {
a.mov(ARG1, ARG2);
a.mov(ARG3, ARG2);
@@ -1184,13 +1389,18 @@ void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
* flag on shifts greater than 1. */
a.lzcnt(ARG3, ARG1);
- a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
- a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(generic);
+ if (always_small(LHS)) {
+ comment("skipped test for small operand since it is always "
+ "small");
+ } else {
+ a.and_(ARG1d, imm(_TAG_IMMED1_MASK));
+ a.cmp(ARG1d, imm(_TAG_IMMED1_SMALL));
+ a.short_().jne(generic);
+ }
shiftLimit = ARG3;
} else {
- UWord value = LHS.getValue();
+ UWord value = LHS.as<ArgSmall>().get();
if (signed_val(value) < 0) {
value ^= ~(UWord)_TAG_IMMED1_MASK;
@@ -1199,7 +1409,7 @@ void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
shiftLimit = imm(count_leading_zeroes(value));
}
- if (RHS.isMem()) {
+ if (RHS.isRegister()) {
/* Move RHS to the counter register, as it's the only one that can
* be used for variable shifts. */
a.mov(x86::rcx, RET);
@@ -1223,7 +1433,7 @@ void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
} else {
ASSERT(!shiftLimit.isImm());
- shiftCount = imm(signed_val(RHS.getValue()));
+ shiftCount = imm(RHS.as<ArgSmall>().getSigned());
a.emit(x86::Inst::kIdCmp, shiftLimit, shiftCount);
a.short_().jbe(generic);
@@ -1238,9 +1448,9 @@ void BeamModuleAssembler::emit_i_bsl(const ArgVal &LHS,
a.bind(generic);
{
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bsl_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bsl_body_shared());
}
diff --git a/erts/emulator/beam/jit/x86/instr_bif.cpp b/erts/emulator/beam/jit/x86/instr_bif.cpp
index bc390b0fa8..4c2d4f007e 100644
--- a/erts/emulator/beam/jit/x86/instr_bif.cpp
+++ b/erts/emulator/beam/jit/x86/instr_bif.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ extern "C"
*
* Result is returned in RET, error is indicated by ZF. */
void BeamGlobalAssembler::emit_i_bif_guard_shared() {
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions>();
a.mov(ARG1, c_p);
@@ -42,6 +43,7 @@ void BeamGlobalAssembler::emit_i_bif_guard_shared() {
runtime_call(ARG4, 3);
emit_leave_runtime<Update::eReductions>();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.ret();
@@ -53,6 +55,7 @@ void BeamGlobalAssembler::emit_i_bif_guard_shared() {
void BeamGlobalAssembler::emit_i_bif_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions>();
/* Save current BIF and argument vector for the error path. */
@@ -68,6 +71,7 @@ void BeamGlobalAssembler::emit_i_bif_body_shared() {
a.short_().je(error);
emit_leave_runtime<Update::eReductions>();
+ emit_leave_frame();
a.ret();
@@ -87,14 +91,15 @@ void BeamGlobalAssembler::emit_i_bif_body_shared() {
runtime_call<1>(ubif2mfa);
emit_leave_runtime<Update::eReductions>();
+ emit_leave_frame();
a.mov(ARG4, RET);
- a.jmp(labels[handle_error_shared_prologue]);
+ a.jmp(labels[raise_exception]);
}
}
void BeamModuleAssembler::emit_setup_guard_bif(const std::vector<ArgVal> &args,
- const ArgVal &bif) {
+ const ArgWord &bif) {
bool is_contiguous_mem = false;
ASSERT(args.size() > 0 && args.size() <= 3);
@@ -102,12 +107,12 @@ void BeamModuleAssembler::emit_setup_guard_bif(const std::vector<ArgVal> &args,
/* If the guard BIF's arguments are in memory and continuous, for example
* `map_get(x0, x1)`, then we can pass the address of the first argument
* instead of filling in the argument vector. */
- is_contiguous_mem = args.size() && args[0].isMem();
+ is_contiguous_mem = args.size() && args[0].isRegister();
for (size_t i = 1; i < args.size() && is_contiguous_mem; i++) {
- const ArgVal &curr = args[i], &prev = args[i - 1];
+ const ArgSource &curr = args[i], &prev = args[i - 1];
- is_contiguous_mem = curr.getType() == prev.getType() &&
- curr.getValue() == prev.getValue() + 1;
+ is_contiguous_mem =
+ ArgVal::memory_relation(prev, curr) == ArgVal::consecutive;
}
if (is_contiguous_mem) {
@@ -123,15 +128,15 @@ void BeamModuleAssembler::emit_setup_guard_bif(const std::vector<ArgVal> &args,
mov_arg(ARG4, bif);
}
-void BeamModuleAssembler::emit_i_bif1(const ArgVal &Src1,
- const ArgVal &Fail,
- const ArgVal &Bif,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bif1(const ArgSource &Src1,
+ const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
emit_setup_guard_bif({Src1}, Bif);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bif_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bif_body_shared());
}
@@ -139,16 +144,16 @@ void BeamModuleAssembler::emit_i_bif1(const ArgVal &Src1,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bif2(const ArgVal &Src1,
- const ArgVal &Src2,
- const ArgVal &Fail,
- const ArgVal &Bif,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bif2(const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
emit_setup_guard_bif({Src1, Src2}, Bif);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bif_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bif_body_shared());
}
@@ -156,17 +161,17 @@ void BeamModuleAssembler::emit_i_bif2(const ArgVal &Src1,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bif3(const ArgVal &Src1,
- const ArgVal &Src2,
- const ArgVal &Src3,
- const ArgVal &Fail,
- const ArgVal &Bif,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bif3(const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgSource &Src3,
+ const ArgLabel &Fail,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
emit_setup_guard_bif({Src1, Src2, Src3}, Bif);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
safe_fragment_call(ga->get_i_bif_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
safe_fragment_call(ga->get_i_bif_body_shared());
}
@@ -180,34 +185,34 @@ void BeamModuleAssembler::emit_i_bif3(const ArgVal &Src1,
* to align the call targeting the shared fragment.
*/
-void BeamModuleAssembler::emit_nofail_bif1(const ArgVal &Src1,
- const ArgVal &Bif,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_nofail_bif1(const ArgSource &Src1,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
emit_setup_guard_bif({Src1}, Bif);
safe_fragment_call(ga->get_i_bif_guard_shared());
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_nofail_bif2(const ArgVal &Src1,
- const ArgVal &Src2,
- const ArgVal &Bif,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_nofail_bif2(const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgWord &Bif,
+ const ArgRegister &Dst) {
emit_setup_guard_bif({Src1, Src2}, Bif);
safe_fragment_call(ga->get_i_bif_guard_shared());
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_length_setup(const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_length_setup(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Src) {
x86::Mem trap_state;
/* Store trap state after the currently live registers. There's an extra 3
* registers beyond the ordinary ones that we're free to use for whatever
* purpose. */
ERTS_CT_ASSERT(ERTS_X_REGS_ALLOCATED - MAX_REG >= 3);
- ASSERT(Live.getValue() <= MAX_REG);
- trap_state = getXRef(Live.getValue());
+ ASSERT(Live.get() <= MAX_REG);
+ trap_state = getXRef(Live.get());
/* Remainder of the list. */
mov_arg(trap_state, Src);
@@ -217,7 +222,7 @@ void BeamModuleAssembler::emit_i_length_setup(const ArgVal &Fail,
/* Original argument. This is only needed for exceptions and can be safely
* skipped in guards. */
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
x86::Mem original_argument;
original_argument = trap_state.cloneAdjusted(2 * sizeof(Eterm));
@@ -238,6 +243,8 @@ x86::Mem BeamGlobalAssembler::emit_i_length_common(Label fail, int state_size) {
trap_state = getXRef(0);
trap_state.setIndex(ARG2, 3);
+ emit_enter_frame();
+
/* Save arguments for error/trapping path. */
a.mov(TMP_MEM1q, ARG2);
a.mov(TMP_MEM2q, ARG3);
@@ -249,6 +256,7 @@ x86::Mem BeamGlobalAssembler::emit_i_length_common(Label fail, int state_size) {
runtime_call<2>(erts_trapping_length_1);
emit_leave_runtime<Update::eReductions>();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(trap);
@@ -268,7 +276,7 @@ x86::Mem BeamGlobalAssembler::emit_i_length_common(Label fail, int state_size) {
a.add(ARG2, imm(state_size));
/* We'll find our way back through the entry address (ARG3). */
- emit_discard_cp();
+ a.add(x86::rsp, imm(sizeof(UWord)));
a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), imm(0));
a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), ARG2);
@@ -298,7 +306,7 @@ void BeamGlobalAssembler::emit_i_length_body_shared() {
a.mov(getXRef(0), ARG1);
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error();
+ a.jmp(labels[raise_exception]);
}
}
@@ -312,14 +320,14 @@ void BeamGlobalAssembler::emit_i_length_guard_shared() {
a.bind(error);
{
- mov_imm(RET, 0);
+ a.sub(RET, RET);
a.ret();
}
}
-void BeamModuleAssembler::emit_i_length(const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_length(const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
Label entry = a.newLabel();
align_erlang_cp();
@@ -328,13 +336,13 @@ void BeamModuleAssembler::emit_i_length(const ArgVal &Fail,
mov_arg(ARG2, Live);
a.lea(ARG3, x86::qword_ptr(entry));
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
/* The return address is discarded when yielding, so it doesn't need to
* be aligned. */
safe_fragment_call(ga->get_i_length_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
- fragment_call(ga->get_i_length_body_shared());
+ safe_fragment_call(ga->get_i_length_body_shared());
}
mov_arg(Dst, RET);
@@ -375,31 +383,35 @@ static Eterm debug_call_light_bif(Process *c_p,
* RET = BIF pointer
*/
void BeamGlobalAssembler::emit_call_light_bif_shared() {
- /* We use the HTOP and FCALLS registers as they are
- not used on the runtime-stack and are caller save. */
+ x86::Mem entry_mem = TMP_MEM1q, export_mem = TMP_MEM2q,
+ mbuf_mem = TMP_MEM3q;
+
+ Label trace = a.newLabel(), yield = a.newLabel();
- x86::Gp I = HTOP, exp = FCALLS;
+ emit_enter_frame();
- Label error = a.newLabel(), trace = a.newLabel(), trap = a.newLabel(),
- yield = a.newLabel(), call_save_calls = a.newLabel(),
- call_bif = a.newLabel(), gc_after_bif_call = a.newLabel(),
- check_bif_return = a.newLabel();
+ /* Spill everything we may need on the error and GC paths. */
+ a.mov(ARG1, x86::qword_ptr(c_p, offsetof(Process, mbuf)));
+ a.mov(entry_mem, ARG3);
+ a.mov(export_mem, ARG4);
+ a.mov(mbuf_mem, ARG1);
- /* Check if we should trace this bif call */
+ /* Check if we should trace this bif call or handle save_calls. Both
+ * variants dispatch through the export entry. */
a.cmp(x86::dword_ptr(ARG4, offsetof(Export, is_bif_traced)), imm(0));
a.jne(trace);
+ a.cmp(active_code_ix, imm(ERTS_SAVE_CALLS_CODE_IX));
+ a.je(trace);
a.dec(FCALLS);
a.jle(yield);
{
+ Label check_bif_return = a.newLabel(), gc_after_bif_call = a.newLabel();
+
emit_enter_runtime<Update::eReductions | Update::eStack |
Update::eHeap>();
- /* Spill the arguments we may need on the error path. */
- a.mov(I, ARG3);
- a.mov(exp, ARG4);
-
#ifdef ERTS_MSACC_EXTENDED_STATES
{
Label skip_msacc = a.newLabel();
@@ -407,7 +419,7 @@ void BeamGlobalAssembler::emit_call_light_bif_shared() {
a.cmp(erts_msacc_cache, imm(0));
a.short_().je(skip_msacc);
- a.mov(TMP_MEM1q, RET);
+ a.mov(TMP_MEM4q, ARG3);
a.mov(ARG1, erts_msacc_cache);
a.mov(ARG2,
@@ -415,29 +427,23 @@ void BeamGlobalAssembler::emit_call_light_bif_shared() {
a.mov(ARG3, RET);
runtime_call<3>(erts_msacc_set_bif_state);
- a.mov(ARG3, I);
- a.mov(RET, TMP_MEM1q);
+ a.mov(ARG3, TMP_MEM4q);
a.bind(skip_msacc);
}
#endif
- /* Check if we need to call save_calls */
- a.cmp(active_code_ix, imm(ERTS_SAVE_CALLS_CODE_IX));
- a.je(call_save_calls);
- a.bind(call_bif);
- a.mov(ARG1, x86::qword_ptr(c_p, offsetof(Process, mbuf)));
- a.mov(TMP_MEM1q, ARG1);
-
- /* ARG3 and RET have been set earlier. */
- a.mov(ARG1, c_p);
- load_x_reg_array(ARG2);
+ {
+ /* Call the BIF proper. ARG3 and RET have been set earlier. */
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
- a.mov(ARG4, RET);
- runtime_call<4>(debug_call_light_bif);
+ a.mov(ARG4, RET);
+ runtime_call<4>(debug_call_light_bif);
#else
- runtime_call(RET, 3);
+ runtime_call(RET, 3);
#endif
+ }
#ifdef ERTS_MSACC_EXTENDED_STATES
{
@@ -445,180 +451,153 @@ void BeamGlobalAssembler::emit_call_light_bif_shared() {
a.cmp(erts_msacc_cache, imm(0));
a.short_().je(skip_msacc);
-
- /* update cache if it was changed in the bif.
- TMP_MEM1q is already taken to save ARG1 above */
- a.mov(TMP_MEM2q, RET);
- a.lea(ARG1, erts_msacc_cache);
- runtime_call<1>(erts_msacc_update_cache);
- a.mov(RET, TMP_MEM2q);
-
- /* set state to emulator if msacc has been enabled */
- a.cmp(erts_msacc_cache, imm(0));
- a.short_().je(skip_msacc);
- a.mov(ARG1, erts_msacc_cache);
- a.mov(ARG2, imm(ERTS_MSACC_STATE_EMULATOR));
- a.mov(ARG3, imm(1));
- runtime_call<3>(erts_msacc_set_state_m__);
- a.mov(RET, TMP_MEM2q);
-
+ {
+ /* Update cache if it was changed in the BIF, stashing the
+ * return value in TMP_MEM4q. */
+ a.mov(TMP_MEM4q, RET);
+ a.lea(ARG1, erts_msacc_cache);
+ runtime_call<1>(erts_msacc_update_cache);
+ a.mov(RET, TMP_MEM4q);
+
+ /* set state to emulator if msacc has been enabled */
+ a.cmp(erts_msacc_cache, imm(0));
+ a.short_().je(skip_msacc);
+
+ a.mov(ARG1, erts_msacc_cache);
+ a.mov(ARG2, imm(ERTS_MSACC_STATE_EMULATOR));
+ a.mov(ARG3, imm(1));
+ runtime_call<3>(erts_msacc_set_state_m__);
+ a.mov(RET, TMP_MEM4q);
+ }
a.bind(skip_msacc);
}
#endif
+ /* We must update the active code index in case another process has
+ * loaded new code, as the result of this BIF may be observable on
+ * both ends.
+ *
+ * It doesn't matter whether the BIF modifies anything; if process
+ * A loads new code and calls erlang:monotonic_time/0 soon after,
+ * we'd break the illusion of atomic upgrades if process B still
+ * ran old code after seeing a later timestamp from its own call to
+ * erlang:monotonic_time/0. */
+ emit_leave_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap | Update::eCodeIndex>();
+
/* ERTS_IS_GC_DESIRED_INTERNAL */
{
- a.mov(ARG2, x86::qword_ptr(c_p, offsetof(Process, stop)));
- a.mov(ARG3, RET);
- a.mov(ARG5, x86::qword_ptr(c_p, offsetof(Process, htop)));
+ /* Test whether GC is forced. */
+ a.test(x86::dword_ptr(c_p, offsetof(Process, flags)),
+ imm(F_FORCE_GC | F_DISABLE_GC));
+ a.jne(gc_after_bif_call);
- /* Test if binary heap size should trigger gc */
- a.mov(RET, x86::qword_ptr(c_p, offsetof(Process, bin_vheap_sz)));
+ /* Test if binary heap size should trigger GC. */
+ a.mov(ARG1, x86::qword_ptr(c_p, offsetof(Process, bin_vheap_sz)));
a.cmp(x86::qword_ptr(c_p, offsetof(Process, off_heap.overhead)),
- RET);
- a.mov(RETd, x86::dword_ptr(c_p, offsetof(Process, flags)));
- a.seta(x86::cl); /* Clobber ARG1 on windows and ARG4 on Linux */
- a.and_(RETd, imm(F_FORCE_GC | F_DISABLE_GC));
- a.or_(x86::cl, RETb);
- a.jne(gc_after_bif_call);
+ ARG1);
+ a.ja(gc_after_bif_call);
/* Test if heap fragment size is larger than remaining heap size. */
- a.mov(RET, ARG2);
- a.sub(RET, ARG5);
- a.sar(RET, imm(3));
- a.cmp(RET, x86::qword_ptr(c_p, offsetof(Process, mbuf_sz)));
+ a.mov(ARG2, x86::qword_ptr(c_p, offsetof(Process, mbuf_sz)));
+ a.lea(ARG1, x86::qword_ptr(HTOP, ARG2, 0, 3));
+ a.cmp(E, ARG1);
a.jl(gc_after_bif_call);
}
- /*
- ARG2 is set to E
- ARG3 is set to bif return
- ARG5 is set to HTOP
-
- HTOP is exp
- E_saved|E is I
- */
+ /* ! FALL THROUGH ! */
a.bind(check_bif_return);
- emit_test_the_non_value(ARG3);
-
- /* NOTE: Short won't reach if JIT_HARD_DEBUG is defined. */
- a.je(trap);
-
- a.mov(HTOP, ARG5);
-#ifdef NATIVE_ERLANG_STACK
- a.mov(E_saved, ARG2);
-#else
- a.mov(E, ARG2);
-#endif
-
- /* We must update the active code index in case another process has
- * loaded new code, as the result of this BIF may be observable on both
- * ends.
- *
- * It doesn't matter whether the BIF modifies anything; if process A
- * loads new code and calls erlang:monotonic_time/0 soon after, we'd
- * break the illusion of atomic upgrades if process B still ran old code
- * after seeing a later timestamp from its own call to
- * erlang:monotonic_time/0. */
-
- emit_leave_runtime<Update::eReductions | Update::eCodeIndex>();
-
- a.mov(getXRef(0), ARG3);
- a.ret();
-
- a.bind(call_save_calls);
{
- /* Stash the bif function pointer */
- a.mov(TMP_MEM1q, RET);
+ Label trap = a.newLabel(), error = a.newLabel();
- /* Setup the arguments to call */
- a.mov(ARG1, c_p);
- a.mov(ARG2, exp);
- runtime_call<2>(save_calls);
-
- /* Restore RET and ARG3 to the values expected
- by the bif call */
- a.mov(RET, TMP_MEM1q);
- a.mov(ARG3, I);
- a.jmp(call_bif);
- }
+ emit_test_the_non_value(RET);
+ a.short_().je(trap);
- a.bind(trap);
- {
- a.cmp(x86::qword_ptr(c_p, offsetof(Process, freason)), imm(TRAP));
- a.short_().jne(error);
+ a.mov(getXRef(0), RET);
- emit_leave_runtime<Update::eHeap | Update::eStack |
- Update::eReductions | Update::eCodeIndex>();
+ emit_leave_frame();
+ a.ret();
+
+ a.bind(trap);
+ {
+ a.cmp(x86::qword_ptr(c_p, offsetof(Process, freason)),
+ imm(TRAP));
+ a.short_().jne(error);
#if !defined(NATIVE_ERLANG_STACK)
- a.pop(getCPRef());
+ a.pop(getCPRef());
#endif
- /* Trap out, our return address is on the Erlang stack.
- *
- * The BIF_TRAP macros all set up c_p->arity and c_p->current, so
- * we can use a simplified context switch. */
- a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, i)));
- a.jmp(labels[context_switch_simplified]);
- }
-
- a.bind(error);
- {
- a.mov(ARG4, exp);
- a.mov(RET, I);
-
- /* Update::eCodeIndex clobbers ARG1 + ARG2 */
- emit_leave_runtime<Update::eHeap | Update::eStack |
- Update::eReductions | Update::eCodeIndex>();
+ /* Trap out, our return address is on the Erlang stack.
+ *
+ * The BIF_TRAP macros all set up c_p->arity and c_p->current,
+ * so we can use a simplified context switch. */
+ a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, i)));
+ a.jmp(labels[context_switch_simplified]);
+ }
- /* handle_error_shared needs the entry address in ARG2 */
- a.mov(ARG2, RET);
+ a.bind(error);
+ {
+ a.mov(ARG2, entry_mem);
+ a.mov(ARG4, export_mem);
+ a.add(ARG4, imm(offsetof(Export, info.mfa)));
#if !defined(NATIVE_ERLANG_STACK)
- /* Discard the continuation pointer as it will never be used. */
- emit_discard_cp();
+ /* Discard the continuation pointer as it will never be
+ * used. */
+ emit_unwind_frame();
#endif
- /* get_handle_error expects current PC in ARG2 and MFA in ARG4. */
- a.lea(ARG4, x86::qword_ptr(ARG4, offsetof(Export, info.mfa)));
-
- /* Overwrite the return address with the entry address to ensure
- * that only the entry address ends up in the stack trace. */
- a.mov(x86::qword_ptr(E), ARG2);
-
- a.jmp(labels[handle_error_shared]);
+ /* Overwrite the return address with the entry address to
+ * ensure that only the entry address ends up in the stack
+ * trace. */
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_RA) {
+ a.mov(x86::qword_ptr(E), ARG2);
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
+ a.mov(x86::qword_ptr(E, 8), ARG2);
+ }
+
+ a.jmp(labels[raise_exception_shared]);
+ }
}
a.bind(gc_after_bif_call);
{
+ a.mov(ARG2, mbuf_mem);
+ a.mov(ARG5, export_mem);
+ a.mov(ARG5, x86::qword_ptr(ARG5, offsetof(Export, info.mfa.arity)));
+
+ emit_enter_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap>();
+
a.mov(ARG1, c_p);
- a.mov(ARG2, TMP_MEM1q);
- /* ARG3 already contains result */
+ a.mov(ARG3, RET);
load_x_reg_array(ARG4);
- a.mov(ARG5, x86::qword_ptr(exp, offsetof(Export, info.mfa.arity)));
runtime_call<5>(erts_gc_after_bif_call_lhf);
- a.mov(ARG3, RET);
- a.mov(ARG5, x86::qword_ptr(c_p, offsetof(Process, htop)));
- a.mov(ARG2, x86::qword_ptr(c_p, offsetof(Process, stop)));
+
+ emit_leave_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap>();
+
a.jmp(check_bif_return);
}
}
a.bind(trace);
{
- /* Call the export entry instead of the BIF. If we use the
- * native stack as the Erlang stack our return address is
- * already on the Erlang stack. Otherwise we will have to move
- * the return address from the native stack to the Erlang
- * stack. */
+ /* Tail call the export entry instead of the BIF. If we use the native
+ * stack as the Erlang stack our return address is already on the
+ * Erlang stack. Otherwise we will have to move the return address from
+ * the native stack to the Erlang stack. */
+
+ emit_leave_frame();
#if !defined(NATIVE_ERLANG_STACK)
/* The return address must be on the Erlang stack. */
a.pop(getCPRef());
#endif
- x86::Mem destination = emit_setup_export_call(ARG4);
+ x86::Mem destination = emit_setup_dispatchable_call(ARG4);
a.jmp(destination);
}
@@ -630,21 +609,21 @@ void BeamGlobalAssembler::emit_call_light_bif_shared() {
a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), ARG4);
/* We'll find our way back through ARG3 (entry address). */
- emit_discard_cp();
+ emit_unwind_frame();
a.jmp(labels[context_switch_simplified]);
}
}
-void BeamModuleAssembler::emit_call_light_bif(const ArgVal &Bif,
- const ArgVal &Exp) {
+void BeamModuleAssembler::emit_call_light_bif(const ArgWord &Bif,
+ const ArgExport &Exp) {
Label entry = a.newLabel();
align_erlang_cp();
a.bind(entry);
- make_move_patch(ARG4, imports[Exp.getValue()].patches);
- a.mov(RET, imm(Bif.getValue()));
+ mov_arg(ARG4, Exp);
+ a.mov(RET, imm(Bif.get()));
a.lea(ARG3, x86::qword_ptr(entry));
fragment_call(ga->get_call_light_bif_shared());
@@ -654,9 +633,8 @@ void BeamModuleAssembler::emit_send() {
Label entry = a.newLabel();
/* This is essentially a mirror of call_light_bif, there's no point to
- * specializing send/2 anymore.
- *
- * FIXME: Rewrite this to an ordinary BIF in the loader instead. */
+ * specializing send/2 anymore. We do it here because it's far more work to
+ * do it in the loader. */
align_erlang_cp();
a.bind(entry);
@@ -667,6 +645,10 @@ void BeamModuleAssembler::emit_send() {
fragment_call(ga->get_call_light_bif_shared());
}
+void BeamModuleAssembler::emit_nif_start() {
+ /* load time only instruction */
+}
+
void BeamGlobalAssembler::emit_bif_nif_epilogue(void) {
Label check_trap = a.newLabel(), trap = a.newLabel(), error = a.newLabel();
@@ -696,6 +678,9 @@ void BeamGlobalAssembler::emit_bif_nif_epilogue(void) {
comment("Do return and dispatch to it");
a.mov(getXRef(0), RET);
+
+ emit_leave_frame();
+
#ifdef NATIVE_ERLANG_STACK
a.ret();
#else
@@ -745,7 +730,7 @@ void BeamGlobalAssembler::emit_bif_nif_epilogue(void) {
a.mov(ARG2, RET);
a.mov(ARG4, x86::qword_ptr(c_p, offsetof(Process, current)));
- a.jmp(labels[handle_error_shared]);
+ a.jmp(labels[raise_exception_shared]);
}
}
@@ -779,17 +764,16 @@ void BeamGlobalAssembler::emit_call_bif_shared(void) {
a.short_().je(skip_msacc);
a.mov(TMP_MEM1q, ARG3);
- a.mov(TMP_MEM2q, ARG4);
- a.mov(TMP_MEM3q, ARG5);
+ a.mov(TMP_MEM2q, ARG5);
a.mov(ARG1, erts_msacc_cache);
a.mov(ARG2, x86::qword_ptr(ARG2, offsetof(ErtsCodeMFA, module)));
a.mov(ARG3, ARG4);
runtime_call<3>(erts_msacc_set_bif_state);
+ a.mov(ARG4, RET);
a.mov(ARG3, TMP_MEM1q);
- a.mov(ARG4, TMP_MEM2q);
- a.mov(ARG5, TMP_MEM3q);
+ a.mov(ARG5, TMP_MEM2q);
a.bind(skip_msacc);
}
#endif
@@ -814,41 +798,52 @@ void BeamGlobalAssembler::emit_dispatch_bif(void) {
* `info` structure. */
a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, i)));
- ERTS_CT_ASSERT(offsetof(ErtsNativeFunc, trampoline.trace) ==
+ ERTS_CT_ASSERT(offsetof(ErtsNativeFunc, trampoline.call_bif_nif) ==
sizeof(ErtsCodeInfo));
ssize_t mfa_offset = offsetof(ErtsNativeFunc, trampoline.info.mfa) -
- offsetof(ErtsNativeFunc, trampoline.trace);
+ offsetof(ErtsNativeFunc, trampoline.call_bif_nif);
a.lea(ARG2, x86::qword_ptr(ARG3, mfa_offset));
ssize_t dfunc_offset = offsetof(ErtsNativeFunc, trampoline.dfunc) -
- offsetof(ErtsNativeFunc, trampoline.trace);
+ offsetof(ErtsNativeFunc, trampoline.call_bif_nif);
a.mov(ARG4, x86::qword_ptr(ARG3, dfunc_offset));
a.jmp(labels[call_bif_shared]);
}
-void BeamModuleAssembler::emit_call_bif(const ArgVal &Func) {
+void BeamModuleAssembler::emit_call_bif(const ArgWord &Func) {
int mfa_offset = -(int)sizeof(ErtsCodeMFA);
- a.lea(ARG2, x86::qword_ptr(currLabel, mfa_offset));
- a.lea(ARG3, x86::qword_ptr(currLabel));
- mov_arg(ARG4, Func);
+ Label entry = a.newLabel();
+
+ /* This is _always_ the first instruction in a function and replaces the
+ * yield test that would otherwise add a frame, so we must add a frame
+ * here. */
+ emit_enter_frame();
+
+ /* Yield entry point; must be after entering frame. */
+ a.bind(entry);
+ {
+ a.lea(ARG2, x86::qword_ptr(current_label, mfa_offset));
+ a.lea(ARG3, x86::qword_ptr(entry));
+ mov_arg(ARG4, Func);
- abs_jmp(ga->get_call_bif_shared());
+ a.jmp(resolve_fragment(ga->get_call_bif_shared()));
+ }
}
-void BeamModuleAssembler::emit_call_bif_mfa(const ArgVal &M,
- const ArgVal &F,
- const ArgVal &A) {
+void BeamModuleAssembler::emit_call_bif_mfa(const ArgAtom &M,
+ const ArgAtom &F,
+ const ArgWord &A) {
BeamInstr func;
Export *e;
- e = erts_active_export_entry(M.getValue(), F.getValue(), A.getValue());
+ e = erts_active_export_entry(M.get(), F.get(), A.get());
ASSERT(e != NULL && e->bif_number != -1);
func = (BeamInstr)bif_table[e->bif_number].f;
- emit_call_bif(ArgVal(ArgVal::i, func));
+ emit_call_bif(ArgWord(func));
}
void BeamGlobalAssembler::emit_call_nif_early() {
@@ -866,6 +861,7 @@ void BeamGlobalAssembler::emit_call_nif_early() {
a.test(ARG2, imm(sizeof(UWord) - 1));
a.short_().je(next);
+ comment("# Return address isn't word-aligned");
a.ud2();
a.bind(next);
@@ -879,11 +875,14 @@ void BeamGlobalAssembler::emit_call_nif_early() {
emit_leave_runtime();
- /* We won't return to the original code. */
- emit_discard_cp();
+ /* We won't return to the original code. We KNOW that the stack points at
+ * a return address. */
+ a.add(x86::rsp, imm(8));
/* Emulate `emit_call_nif`, loading the current (phony) instruction
- * pointer into ARG2. */
+ * pointer into ARG2. We push a (redundant) frame pointer to match the
+ * corresponding `emit_leave_frame` in `call_nif_shared`. */
+ emit_enter_frame();
a.mov(ARG3, RET);
a.jmp(labels[call_nif_shared]);
}
@@ -932,48 +931,71 @@ void BeamGlobalAssembler::emit_dispatch_nif(void) {
*
* ErtsNativeFunc already follows the NIF call layout, so we don't need to
* do anything beyond loading the address. */
- ERTS_CT_ASSERT(offsetof(ErtsNativeFunc, trampoline.trace) ==
+ ERTS_CT_ASSERT(offsetof(ErtsNativeFunc, trampoline.call_bif_nif) ==
sizeof(ErtsCodeInfo));
a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, i)));
a.jmp(labels[call_nif_shared]);
}
-/* WARNING: This stub is memcpy'd, so all code herein must be explicitly
- * position-independent. */
-void BeamModuleAssembler::emit_call_nif(const ArgVal &Func,
- const ArgVal &NifMod,
- const ArgVal &DirtyFunc) {
- Label dispatch = a.newLabel();
- uint64_t val;
-
- /* The start of this function has to mimic the layout of ErtsNativeFunc. */
- a.jmp(dispatch); /* call_op */
-
- a.align(AlignMode::kCode, 8);
- /* ErtsNativeFunc.dfunc */
- val = Func.getValue();
- a.embed(&val, sizeof(val));
- /* ErtsNativeFunc.m */
- val = NifMod.getValue();
- a.embed(&val, sizeof(val));
- /* ErtsNativeFunc.func */
- val = DirtyFunc.getValue();
- a.embed(&val, sizeof(val));
-
- /* The real code starts here */
- a.bind(dispatch);
+void BeamGlobalAssembler::emit_call_nif_yield_helper() {
+ Label yield = a.newLabel();
+
+ a.dec(FCALLS);
+ a.short_().jl(yield);
+ a.jmp(labels[call_nif_shared]);
+
+ a.bind(yield);
{
- Label yield = a.newLabel();
+ int mfa_offset = -(int)sizeof(ErtsCodeMFA);
+ int arity_offset = mfa_offset + (int)offsetof(ErtsCodeMFA, arity);
- a.lea(ARG3, x86::qword_ptr(currLabel));
+ a.mov(ARG1, x86::qword_ptr(ARG3, arity_offset));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), ARG1);
- a.dec(FCALLS);
- a.jl(yield);
+ a.lea(ARG1, x86::qword_ptr(ARG3, mfa_offset));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), ARG1);
- pic_jmp(ga->get_call_nif_shared());
+ /* Yield to `dispatch` rather than `entry` to avoid pushing too many
+ * frames to the stack. See `emit_call_nif` for details. */
+ a.add(ARG3, imm(BEAM_ASM_NFUNC_SIZE + sizeof(UWord[3])));
+ a.jmp(labels[context_switch_simplified]);
+ }
+}
- a.bind(yield);
- pic_jmp(ga->get_context_switch());
+/* WARNING: This stub is memcpy'd, so all code herein must be explicitly
+ * position-independent. */
+void BeamModuleAssembler::emit_call_nif(const ArgWord &Func,
+ const ArgWord &NifMod,
+ const ArgWord &DirtyFunc) {
+ Label entry = a.newLabel(), dispatch = a.newLabel();
+
+ /* The start of this function must mimic the layout of ErtsNativeFunc.
+ *
+ * We jump here on the very first entry, pushing a stack frame if
+ * applicable. */
+ a.bind(entry);
+ {
+ emit_enter_frame();
+ a.short_().jmp(dispatch); /* call_op */
+
+ a.align(AlignMode::kCode, 8);
+ /* ErtsNativeFunc.dfunc */
+ a.embedUInt64(Func.get());
+ /* ErtsNativeFunc.m */
+ a.embedUInt64(NifMod.get());
+ /* ErtsNativeFunc.func */
+ a.embedUInt64(DirtyFunc.get());
+ }
+
+ /* `emit_call_nif_yield_helper` relies on this to compute the address of
+ * `dispatch` */
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ BEAM_ASM_NFUNC_SIZE + sizeof(UWord[3]));
+
+ a.bind(dispatch);
+ {
+ a.lea(ARG3, x86::qword_ptr(current_label));
+ pic_jmp(ga->get_call_nif_yield_helper());
}
}
@@ -996,15 +1018,18 @@ void BeamGlobalAssembler::emit_i_load_nif_shared() {
a.cmp(RET, RET_NIF_yield);
a.short_().je(yield);
+
+ /* We entered the frame in module code. */
+ emit_leave_frame();
+
a.cmp(RET, RET_NIF_success);
a.short_().jne(error);
-
a.ret();
a.bind(error);
{
a.mov(ARG4, imm(&bif_mfa));
- emit_handle_error();
+ a.jmp(labels[raise_exception]);
}
a.bind(yield);
@@ -1014,10 +1039,49 @@ void BeamGlobalAssembler::emit_i_load_nif_shared() {
}
}
+static ErtsCodePtr get_on_load_address(Process *c_p, Eterm module) {
+ const Module *modp = erts_get_module(module, erts_active_code_ix());
+
+ if (modp && modp->on_load) {
+ const BeamCodeHeader *hdr = (modp->on_load)->code_hdr;
+
+ if (hdr) {
+ return erts_codeinfo_to_code(hdr->on_load);
+ }
+ }
+
+ c_p->freason = BADARG;
+
+ return NULL;
+}
+
+/* Implements the internal and undocumented erlang:call_on_load_function/1,
+ * which is tricky to implement in the face of frame pointers. */
+void BeamModuleAssembler::emit_i_call_on_load_function() {
+ static ErtsCodeMFA mfa = {am_erlang, am_call_on_load_function, 1};
+ Label next = a.newLabel();
+
+ emit_enter_runtime();
+
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, getXRef(0));
+ runtime_call<2>(get_on_load_address);
+
+ emit_leave_runtime();
+
+ a.test(RET, RET);
+ a.jne(next);
+
+ emit_raise_exception(&mfa);
+
+ a.bind(next);
+ erlang_call(RET, ARG1);
+}
+
#ifdef NATIVE_ERLANG_STACK
void BeamModuleAssembler::emit_i_load_nif() {
- Label entry = a.newLabel(), next = a.newLabel();
+ Label entry = a.newLabel(), yield = a.newLabel(), next = a.newLabel();
/* i_load_nif is a rewrite of a call_ext instruction, so we'll body-call
* ourselves to ensure the stack is consistent with that. This greatly
@@ -1028,8 +1092,13 @@ void BeamModuleAssembler::emit_i_load_nif() {
align_erlang_cp();
a.bind(entry);
{
- a.lea(ARG2, x86::qword_ptr(entry));
- abs_jmp(ga->get_i_load_nif_shared());
+ emit_enter_frame();
+
+ a.bind(yield);
+ {
+ a.lea(ARG2, x86::qword_ptr(yield));
+ a.jmp(resolve_fragment(ga->get_i_load_nif_shared()));
+ }
}
a.bind(next);
@@ -1048,7 +1117,7 @@ void BeamModuleAssembler::emit_i_load_nif() {
emit_enter_runtime<Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
- a.lea(ARG2, x86::qword_ptr(currLabel));
+ a.lea(ARG2, x86::qword_ptr(current_label));
load_x_reg_array(ARG3);
runtime_call<3>(beam_jit_load_nif);
@@ -1059,12 +1128,12 @@ void BeamModuleAssembler::emit_i_load_nif() {
a.cmp(RET, imm(RET_NIF_success));
a.je(next);
- emit_handle_error(currLabel, &mfa);
+ emit_raise_exception(current_label, &mfa);
a.bind(schedule);
{
a.lea(ARG3, x86::qword_ptr(entry));
- abs_jmp(ga->get_context_switch_simplified());
+ a.jmp(resolve_fragment(ga->get_context_switch_simplified()));
}
a.bind(next);
diff --git a/erts/emulator/beam/jit/x86/instr_bs.cpp b/erts/emulator/beam/jit/x86/instr_bs.cpp
index e21ee18ba7..ab6abff6cc 100644
--- a/erts/emulator/beam/jit/x86/instr_bs.cpp
+++ b/erts/emulator/beam/jit/x86/instr_bs.cpp
@@ -33,14 +33,14 @@ extern "C"
*
* Returns -1 when the field check always fails, 1 if it may fail, and 0 if it
* never fails. */
-int BeamModuleAssembler::emit_bs_get_field_size(const ArgVal &Size,
+int BeamModuleAssembler::emit_bs_get_field_size(const ArgSource &Size,
int unit,
Label fail,
const x86::Gp &out,
unsigned max_size) {
if (Size.isImmed()) {
- if (is_small(Size.getValue())) {
- Sint sval = signed_val(Size.getValue());
+ if (Size.isSmall()) {
+ Sint sval = Size.as<ArgSmall>().getSigned();
if (sval < 0) {
/* badarg */
@@ -95,10 +95,10 @@ int BeamModuleAssembler::emit_bs_get_field_size(const ArgVal &Size,
}
}
-void BeamModuleAssembler::emit_i_bs_init_heap(const ArgVal &Size,
- const ArgVal &Heap,
- const ArgVal &Live,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_init_heap(const ArgWord &Size,
+ const ArgWord &Heap,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
mov_arg(ARG4, Size);
mov_arg(ARG5, Heap);
mov_arg(ARG6, Live);
@@ -125,15 +125,15 @@ void BeamGlobalAssembler::emit_bs_size_check_shared() {
a.ret();
}
-void BeamModuleAssembler::emit_i_bs_init_fail_heap(const ArgVal &Size,
- const ArgVal &Heap,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_init_fail_heap(const ArgSource &Size,
+ const ArgWord &Heap,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
Label fail;
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
}
@@ -157,7 +157,7 @@ void BeamModuleAssembler::emit_i_bs_init_fail_heap(const ArgVal &Size,
mov_arg(Dst, RET);
}
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
Label next = a.newLabel();
a.short_().jmp(next);
@@ -165,41 +165,41 @@ void BeamModuleAssembler::emit_i_bs_init_fail_heap(const ArgVal &Size,
{
mov_arg(ARG2, Size);
safe_fragment_call(ga->get_bs_size_check_shared());
- emit_handle_error();
+ emit_raise_exception();
}
a.bind(next);
}
}
-void BeamModuleAssembler::emit_i_bs_init(const ArgVal &Size,
- const ArgVal &Live,
- const ArgVal &Dst) {
- const ArgVal Heap(ArgVal::TYPE::u, 0);
+void BeamModuleAssembler::emit_i_bs_init(const ArgWord &Size,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal Heap(ArgVal::Word, 0);
emit_i_bs_init_heap(Size, Heap, Live, Dst);
}
-void BeamModuleAssembler::emit_i_bs_init_fail(const ArgVal &Size,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Dst) {
- const ArgVal Heap(ArgVal::TYPE::u, 0);
+void BeamModuleAssembler::emit_i_bs_init_fail(const ArgRegister &Size,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal Heap(ArgVal::Word, 0);
emit_i_bs_init_fail_heap(Size, Heap, Fail, Live, Dst);
}
-void BeamModuleAssembler::emit_i_bs_init_bits(const ArgVal &NumBits,
- const ArgVal &Live,
- const ArgVal &Dst) {
- const ArgVal heap(ArgVal::TYPE::u, 0);
+void BeamModuleAssembler::emit_i_bs_init_bits(const ArgWord &NumBits,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal heap(ArgVal::Word, 0);
emit_i_bs_init_bits_heap(NumBits, heap, Live, Dst);
}
-void BeamModuleAssembler::emit_i_bs_init_bits_heap(const ArgVal &NumBits,
- const ArgVal &Alloc,
- const ArgVal &Live,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_init_bits_heap(const ArgWord &NumBits,
+ const ArgWord &Alloc,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
mov_arg(ARG4, NumBits);
mov_arg(ARG5, Alloc);
mov_arg(ARG6, Live);
@@ -217,24 +217,25 @@ void BeamModuleAssembler::emit_i_bs_init_bits_heap(const ArgVal &NumBits,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_init_bits_fail(const ArgVal &NumBits,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Dst) {
- const ArgVal Heap(ArgVal::TYPE::u, 0);
+void BeamModuleAssembler::emit_i_bs_init_bits_fail(const ArgRegister &NumBits,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ const ArgVal Heap(ArgVal::Word, 0);
emit_i_bs_init_bits_fail_heap(NumBits, Heap, Fail, Live, Dst);
}
-void BeamModuleAssembler::emit_i_bs_init_bits_fail_heap(const ArgVal &NumBits,
- const ArgVal &Alloc,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_init_bits_fail_heap(
+ const ArgSource &NumBits,
+ const ArgWord &Alloc,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
Label fail;
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
}
@@ -259,7 +260,7 @@ void BeamModuleAssembler::emit_i_bs_init_bits_fail_heap(const ArgVal &NumBits,
mov_arg(Dst, RET);
}
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
Label next = a.newLabel();
a.short_().jmp(next);
@@ -267,33 +268,33 @@ void BeamModuleAssembler::emit_i_bs_init_bits_fail_heap(const ArgVal &NumBits,
{
mov_arg(ARG2, NumBits);
safe_fragment_call(ga->get_bs_size_check_shared());
- emit_handle_error();
+ emit_raise_exception();
}
a.bind(next);
}
}
-void BeamModuleAssembler::emit_bs_put_string(const ArgVal &Size,
- const ArgVal &Ptr) {
+void BeamModuleAssembler::emit_bs_put_string(const ArgWord &Size,
+ const ArgBytePtr &Ptr) {
mov_arg(ARG3, Size);
emit_enter_runtime();
- make_move_patch(ARG2, strings, Ptr.getValue());
+ mov_arg(ARG2, Ptr);
load_erl_bits_state(ARG1);
runtime_call<3>(erts_new_bs_put_string);
emit_leave_runtime();
}
-void BeamModuleAssembler::emit_i_new_bs_put_integer_imm(const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Sz,
- const ArgVal &Flags) {
+void BeamModuleAssembler::emit_i_new_bs_put_integer_imm(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgWord &Sz,
+ const ArgWord &Flags) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -310,8 +311,8 @@ void BeamModuleAssembler::emit_i_new_bs_put_integer_imm(const ArgVal &Src,
a.test(RET, RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.je(resolve_beam_label(Fail));
} else {
a.short_().jne(next);
emit_error(BADARG);
@@ -319,15 +320,15 @@ void BeamModuleAssembler::emit_i_new_bs_put_integer_imm(const ArgVal &Src,
}
}
-void BeamModuleAssembler::emit_i_new_bs_put_integer(const ArgVal &Fail,
- const ArgVal &Sz,
- const ArgVal &Flags,
- const ArgVal &Src) {
- int unit = Flags.getValue() >> 3;
+void BeamModuleAssembler::emit_i_new_bs_put_integer(const ArgLabel &Fail,
+ const ArgRegister &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ int unit = Flags.get() >> 3;
Label next, fail;
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
next = a.newLabel();
@@ -347,29 +348,29 @@ void BeamModuleAssembler::emit_i_new_bs_put_integer(const ArgVal &Fail,
a.test(RET, RET);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
a.je(fail);
} else {
a.short_().jne(next);
}
}
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
a.bind(fail);
emit_error(BADARG);
a.bind(next);
}
}
-void BeamModuleAssembler::emit_i_new_bs_put_binary(const ArgVal &Fail,
- const ArgVal &Sz,
- const ArgVal &Flags,
- const ArgVal &Src) {
- int unit = Flags.getValue() >> 3;
+void BeamModuleAssembler::emit_i_new_bs_put_binary(const ArgLabel &Fail,
+ const ArgSource &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ int unit = Flags.get() >> 3;
Label next, fail;
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
next = a.newLabel();
@@ -388,26 +389,26 @@ void BeamModuleAssembler::emit_i_new_bs_put_binary(const ArgVal &Fail,
a.test(RET, RET);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
a.je(fail);
} else {
a.short_().jne(next);
}
}
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
a.bind(fail);
emit_error(BADARG);
a.bind(next);
}
}
-void BeamModuleAssembler::emit_i_new_bs_put_binary_all(const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Unit) {
+void BeamModuleAssembler::emit_i_new_bs_put_binary_all(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgWord &Unit) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -423,21 +424,21 @@ void BeamModuleAssembler::emit_i_new_bs_put_binary_all(const ArgVal &Src,
a.test(RET, RET);
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
a.jne(next);
emit_error(BADARG);
a.bind(next);
} else {
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
}
}
-void BeamModuleAssembler::emit_i_new_bs_put_binary_imm(const ArgVal &Fail,
- const ArgVal &Sz,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_new_bs_put_binary_imm(const ArgLabel &Fail,
+ const ArgWord &Sz,
+ const ArgSource &Src) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -453,24 +454,24 @@ void BeamModuleAssembler::emit_i_new_bs_put_binary_imm(const ArgVal &Fail,
a.test(RET, RET);
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
a.short_().jne(next);
emit_error(BADARG);
a.bind(next);
} else {
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
}
}
-void BeamModuleAssembler::emit_i_new_bs_put_float(const ArgVal &Fail,
- const ArgVal &Sz,
- const ArgVal &Flags,
- const ArgVal &Src) {
- int unit = Flags.getValue() >> 3;
+void BeamModuleAssembler::emit_i_new_bs_put_float(const ArgLabel &Fail,
+ const ArgRegister &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
+ int unit = Flags.get() >> 3;
Label next, fail;
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
next = a.newLabel();
@@ -488,29 +489,29 @@ void BeamModuleAssembler::emit_i_new_bs_put_float(const ArgVal &Fail,
emit_leave_runtime();
- a.test(RET, RET);
+ emit_test_the_non_value(RET);
- if (Fail.getValue() != 0) {
- a.je(fail);
+ if (Fail.get() != 0) {
+ a.jne(fail);
} else {
- a.short_().jne(next);
+ a.short_().je(next);
}
}
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
a.bind(fail);
emit_error(BADARG);
a.bind(next);
}
}
-void BeamModuleAssembler::emit_i_new_bs_put_float_imm(const ArgVal &Fail,
- const ArgVal &Sz,
- const ArgVal &Flags,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_new_bs_put_float_imm(const ArgLabel &Fail,
+ const ArgWord &Sz,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -525,27 +526,27 @@ void BeamModuleAssembler::emit_i_new_bs_put_float_imm(const ArgVal &Fail,
emit_leave_runtime();
- a.test(RET, RET);
+ emit_test_the_non_value(RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.jne(resolve_beam_label(Fail));
} else {
- a.short_().jne(next);
+ a.short_().je(next);
emit_error(BADARG);
a.bind(next);
}
}
-void BeamModuleAssembler::emit_i_bs_start_match3(const ArgVal &Src,
- const ArgVal &Live,
- const ArgVal &Fail,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_start_match3(const ArgRegister &Src,
+ const ArgWord &Live,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
Label is_binary = a.newLabel(), next = a.newLabel();
mov_arg(ARG2, Src);
- if (Fail.getValue() != 0) {
- emit_is_boxed(labels[Fail.getValue()], ARG2);
+ if (Fail.get() != 0) {
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG2);
} else {
/* bs_start_match3 may not throw, and the compiler will only emit {f,0}
* when it knows that the source is a match state or binary, so we're
@@ -563,23 +564,21 @@ void BeamModuleAssembler::emit_i_bs_start_match3(const ArgVal &Src,
a.short_().je(next);
#endif
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
comment("is_binary_header");
a.cmp(RETb, _TAG_HEADER_SUB_BIN);
a.short_().je(is_binary);
ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
a.and_(RETb, imm(~4));
a.cmp(RETb, imm(_TAG_HEADER_REFC_BIN));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
a.bind(is_binary);
{
/* Src is not guaranteed to be inside the live range, so we need to
* stash it during GC. */
- emit_gc_test_preserve(ArgVal(ArgVal::i, ERL_BIN_MATCHSTATE_SIZE(0)),
- Live,
- ARG2);
+ emit_gc_test_preserve(ArgWord(ERL_BIN_MATCHSTATE_SIZE(0)), Live, ARG2);
emit_enter_runtime<Update::eStack | Update::eHeap>();
@@ -596,12 +595,12 @@ void BeamModuleAssembler::emit_i_bs_start_match3(const ArgVal &Src,
mov_arg(Dst, ARG2);
}
-void BeamModuleAssembler::emit_i_bs_match_string(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Bits,
- const ArgVal &Ptr) {
- const UWord size = Bits.getValue();
- Label fail = labels[Fail.getValue()];
+void BeamModuleAssembler::emit_i_bs_match_string(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Bits,
+ const ArgBytePtr &Ptr) {
+ const UWord size = Bits.get();
+ Label fail = resolve_beam_label(Fail);
mov_arg(ARG1, Ctx);
@@ -623,7 +622,7 @@ void BeamModuleAssembler::emit_i_bs_match_string(const ArgVal &Ctx,
emit_enter_runtime();
- make_move_patch(ARG1, strings, Ptr.getValue());
+ mov_arg(ARG1, Ptr);
mov_imm(ARG2, 0);
mov_imm(ARG5, size);
runtime_call<5>(erts_cmp_bits);
@@ -638,8 +637,8 @@ void BeamModuleAssembler::emit_i_bs_match_string(const ArgVal &Ctx,
imm(size));
}
-void BeamModuleAssembler::emit_i_bs_get_position(const ArgVal &Ctx,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_get_position(const ArgRegister &Ctx,
+ const ArgRegister &Dst) {
mov_arg(ARG1, Ctx);
/* Match contexts can never be literals, so we can skip clearing literal
@@ -711,18 +710,18 @@ x86::Mem BeamModuleAssembler::emit_bs_get_integer_prologue(Label next,
}
}
-void BeamModuleAssembler::emit_i_bs_get_integer_8(const ArgVal &Ctx,
- const ArgVal &Flags,
- const ArgVal &Fail,
- const ArgVal &Dst) {
- int flags = Flags.getValue();
+void BeamModuleAssembler::emit_i_bs_get_integer_8(const ArgRegister &Ctx,
+ const ArgWord &Flags,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ int flags = Flags.get();
Label next = a.newLabel();
x86::Mem address;
mov_arg(ARG4, Ctx);
address = emit_bs_get_integer_prologue(next,
- labels[Fail.getValue()],
+ resolve_beam_label(Fail),
flags,
8);
@@ -739,18 +738,18 @@ void BeamModuleAssembler::emit_i_bs_get_integer_8(const ArgVal &Ctx,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_get_integer_16(const ArgVal &Ctx,
- const ArgVal &Flags,
- const ArgVal &Fail,
- const ArgVal &Dst) {
- int flags = Flags.getValue();
+void BeamModuleAssembler::emit_i_bs_get_integer_16(const ArgRegister &Ctx,
+ const ArgWord &Flags,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ int flags = Flags.get();
Label next = a.newLabel();
x86::Mem address;
mov_arg(ARG4, Ctx);
address = emit_bs_get_integer_prologue(next,
- labels[Fail.getValue()],
+ resolve_beam_label(Fail),
flags,
16);
@@ -782,18 +781,18 @@ void BeamModuleAssembler::emit_i_bs_get_integer_16(const ArgVal &Ctx,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_get_integer_32(const ArgVal &Ctx,
- const ArgVal &Flags,
- const ArgVal &Fail,
- const ArgVal &Dst) {
- int flags = Flags.getValue();
+void BeamModuleAssembler::emit_i_bs_get_integer_32(const ArgRegister &Ctx,
+ const ArgWord &Flags,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
+ int flags = Flags.get();
Label next = a.newLabel();
x86::Mem address;
mov_arg(ARG4, Ctx);
address = emit_bs_get_integer_prologue(next,
- labels[Fail.getValue()],
+ resolve_beam_label(Fail),
flags,
32);
@@ -824,12 +823,12 @@ void BeamModuleAssembler::emit_i_bs_get_integer_32(const ArgVal &Ctx,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_get_integer_64(const ArgVal &Ctx,
- const ArgVal &Flags,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Dst) {
- int flags = Flags.getValue();
+void BeamModuleAssembler::emit_i_bs_get_integer_64(const ArgRegister &Ctx,
+ const ArgWord &Flags,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgRegister &Dst) {
+ int flags = Flags.get();
Label next = a.newLabel();
x86::Mem address;
@@ -837,10 +836,10 @@ void BeamModuleAssembler::emit_i_bs_get_integer_64(const ArgVal &Ctx,
/* Ctx is not guaranteed to be inside the live range, so we need to stash
* it during GC. */
- emit_gc_test_preserve(ArgVal(ArgVal::i, BIG_UINT_HEAP_SIZE), Live, ARG4);
+ emit_gc_test_preserve(ArgWord(BIG_UINT_HEAP_SIZE), Live, ARG4);
address = emit_bs_get_integer_prologue(next,
- labels[Fail.getValue()],
+ resolve_beam_label(Fail),
flags,
64);
@@ -889,17 +888,17 @@ void BeamModuleAssembler::emit_i_bs_get_integer_64(const ArgVal &Ctx,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_get_integer(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &FlagsAndUnit,
- const ArgVal &Sz,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_get_integer(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgWord &FlagsAndUnit,
+ const ArgSource &Sz,
+ const ArgRegister &Dst) {
Label fail;
int unit;
- fail = labels[Fail.getValue()];
- unit = FlagsAndUnit.getValue() >> 3;
+ fail = resolve_beam_label(Fail);
+ unit = FlagsAndUnit.get() >> 3;
/* Clobbers RET + ARG3, returns a negative result if we always fail and
* further work is redundant. */
@@ -925,25 +924,28 @@ void BeamModuleAssembler::emit_i_bs_get_integer(const ArgVal &Ctx,
}
}
-void BeamModuleAssembler::emit_bs_test_tail2(const ArgVal &Fail,
- const ArgVal &Ctx,
- const ArgVal &Offset) {
- ASSERT(Offset.getType() == ArgVal::TYPE::u);
-
+void BeamModuleAssembler::emit_bs_test_tail2(const ArgLabel &Fail,
+ const ArgRegister &Ctx,
+ const ArgWord &Offset) {
mov_arg(ARG1, Ctx);
a.mov(ARG2, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.size)));
a.sub(ARG2, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)));
- if (Offset.getValue() != 0) {
- a.cmp(ARG2, imm(Offset.getValue()));
+ if (Offset.get() != 0) {
+ if (Support::isInt32(Offset.get())) {
+ a.cmp(ARG2, imm(Offset.get()));
+ } else {
+ mov_imm(RET, Offset.get());
+ a.cmp(ARG2, RET);
+ }
}
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_bs_set_position(const ArgVal &Ctx,
- const ArgVal &Pos) {
+void BeamModuleAssembler::emit_bs_set_position(const ArgRegister &Ctx,
+ const ArgRegister &Pos) {
mov_arg(ARG1, Ctx);
mov_arg(ARG2, Pos);
@@ -951,20 +953,18 @@ void BeamModuleAssembler::emit_bs_set_position(const ArgVal &Ctx,
a.mov(emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)), ARG2);
}
-void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Unit,
- const ArgVal &Dst) {
- unsigned unit = Unit.getValue();
+void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgWord &Unit,
+ const ArgRegister &Dst) {
+ unsigned unit = Unit.get();
mov_arg(ARG1, Ctx);
/* Ctx is not guaranteed to be inside the live range, so we need to stash
* it during GC. */
- emit_gc_test_preserve(ArgVal(ArgVal::i, EXTRACT_SUB_BIN_HEAP_NEED),
- Live,
- ARG1);
+ emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, ARG1);
a.mov(RET, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.size)));
a.sub(RET, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)));
@@ -979,7 +979,7 @@ void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgVal &Ctx,
a.test(RETb, imm(unit - 1));
}
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
emit_enter_runtime<Update::eHeap>();
@@ -1011,16 +1011,14 @@ void BeamGlobalAssembler::emit_bs_get_tail_shared() {
a.ret();
}
-void BeamModuleAssembler::emit_bs_get_tail(const ArgVal &Ctx,
- const ArgVal &Dst,
- const ArgVal &Live) {
+void BeamModuleAssembler::emit_bs_get_tail(const ArgRegister &Ctx,
+ const ArgRegister &Dst,
+ const ArgWord &Live) {
mov_arg(ARG1, Ctx);
/* Ctx is not guaranteed to be inside the live range, so we need to stash
* it during GC. */
- emit_gc_test_preserve(ArgVal(ArgVal::i, EXTRACT_SUB_BIN_HEAP_NEED),
- Live,
- ARG1);
+ emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, ARG1);
safe_fragment_call(ga->get_bs_get_tail_shared());
@@ -1028,49 +1026,49 @@ void BeamModuleAssembler::emit_bs_get_tail(const ArgVal &Ctx,
}
/* Bits to skip are passed in RET */
-void BeamModuleAssembler::emit_bs_skip_bits(const ArgVal &Fail,
- const ArgVal &Ctx) {
+void BeamModuleAssembler::emit_bs_skip_bits(const ArgLabel &Fail,
+ const ArgRegister &Ctx) {
mov_arg(ARG1, Ctx);
a.add(RET, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)));
a.cmp(RET, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.size)));
- a.ja(labels[Fail.getValue()]);
+ a.ja(resolve_beam_label(Fail));
a.mov(emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)), RET);
}
-void BeamModuleAssembler::emit_i_bs_skip_bits2(const ArgVal &Ctx,
- const ArgVal &Bits,
- const ArgVal &Fail,
- const ArgVal &Unit) {
+void BeamModuleAssembler::emit_i_bs_skip_bits2(const ArgRegister &Ctx,
+ const ArgRegister &Bits,
+ const ArgLabel &Fail,
+ const ArgWord &Unit) {
Label fail;
- fail = labels[Fail.getValue()];
+ fail = resolve_beam_label(Fail);
- if (emit_bs_get_field_size(Bits, Unit.getValue(), fail, RET) >= 0) {
+ if (emit_bs_get_field_size(Bits, Unit.get(), fail, RET) >= 0) {
emit_bs_skip_bits(Fail, Ctx);
}
}
-void BeamModuleAssembler::emit_i_bs_skip_bits_imm2(const ArgVal &Fail,
- const ArgVal &Ctx,
- const ArgVal &Bits) {
+void BeamModuleAssembler::emit_i_bs_skip_bits_imm2(const ArgLabel &Fail,
+ const ArgRegister &Ctx,
+ const ArgWord &Bits) {
mov_arg(RET, Bits);
emit_bs_skip_bits(Fail, Ctx);
}
-void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Size,
- const ArgVal &Flags,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Size,
+ const ArgWord &Flags,
+ const ArgRegister &Dst) {
Label fail;
int unit;
- fail = labels[Fail.getValue()];
- unit = Flags.getValue() >> 3;
+ fail = resolve_beam_label(Fail);
+ unit = Flags.get() >> 3;
/* Clobbers RET + ARG3 */
if (emit_bs_get_field_size(Size, unit, fail, ARG2) >= 0) {
@@ -1080,15 +1078,13 @@ void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgVal &Ctx,
/* Ctx is not guaranteed to be inside the live range, so we need to
* stash it during GC. */
- emit_gc_test_preserve(ArgVal(ArgVal::i, EXTRACT_SUB_BIN_HEAP_NEED),
- Live,
- ARG4);
+ emit_gc_test_preserve(ArgWord(EXTRACT_SUB_BIN_HEAP_NEED), Live, ARG4);
emit_enter_runtime<Update::eHeap>();
a.mov(ARG1, c_p);
a.mov(ARG2, TMP_MEM1q);
- mov_imm(ARG3, Flags.getValue());
+ mov_imm(ARG3, Flags.get());
a.lea(ARG4, emit_boxed_val(ARG4, offsetof(ErlBinMatchState, mb)));
runtime_call<4>(erts_bs_get_binary_2);
@@ -1101,29 +1097,29 @@ void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgVal &Ctx,
}
}
-void BeamModuleAssembler::emit_i_bs_get_float2(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Sz,
- const ArgVal &Flags,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_get_float2(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Live,
+ const ArgSource &Sz,
+ const ArgWord &Flags,
+ const ArgRegister &Dst) {
Label fail;
Sint unit;
- fail = labels[Fail.getValue()];
- unit = Flags.getValue() >> 3;
+ fail = resolve_beam_label(Fail);
+ unit = Flags.get() >> 3;
mov_arg(ARG4, Ctx);
/* Ctx is not guaranteed to be inside the live range, so we need to stash
* it during GC. */
- emit_gc_test_preserve(ArgVal(ArgVal::i, FLOAT_SIZE_OBJECT), Live, ARG4);
+ emit_gc_test_preserve(ArgWord(FLOAT_SIZE_OBJECT), Live, ARG4);
if (emit_bs_get_field_size(Sz, unit, fail, ARG2, 64) >= 0) {
emit_enter_runtime<Update::eHeap>();
a.mov(ARG1, c_p);
- mov_imm(ARG3, Flags.getValue());
+ mov_imm(ARG3, Flags.get());
a.lea(ARG4, emit_boxed_val(ARG4, offsetof(ErlBinMatchState, mb)));
runtime_call<4>(erts_bs_get_float_2);
@@ -1136,8 +1132,8 @@ void BeamModuleAssembler::emit_i_bs_get_float2(const ArgVal &Ctx,
}
}
-void BeamModuleAssembler::emit_i_bs_utf8_size(const ArgVal &Src,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_utf8_size(const ArgSource &Src,
+ const ArgXRegister &Dst) {
Label next = a.newLabel();
mov_arg(ARG1, Src);
@@ -1157,11 +1153,11 @@ void BeamModuleAssembler::emit_i_bs_utf8_size(const ArgVal &Src,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_put_utf8(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_bs_put_utf8(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -1176,8 +1172,8 @@ void BeamModuleAssembler::emit_i_bs_put_utf8(const ArgVal &Fail,
a.test(RET, RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.je(resolve_beam_label(Fail));
} else {
a.short_().jne(next);
emit_error(BADARG);
@@ -1185,8 +1181,8 @@ void BeamModuleAssembler::emit_i_bs_put_utf8(const ArgVal &Fail,
}
}
-void BeamModuleAssembler::emit_bs_get_utf8(const ArgVal &Ctx,
- const ArgVal &Fail) {
+void BeamModuleAssembler::emit_bs_get_utf8(const ArgRegister &Ctx,
+ const ArgLabel &Fail) {
mov_arg(ARG1, Ctx);
emit_enter_runtime();
@@ -1197,23 +1193,23 @@ void BeamModuleAssembler::emit_bs_get_utf8(const ArgVal &Ctx,
emit_leave_runtime();
emit_test_the_non_value(RET);
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_i_bs_get_utf8(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_get_utf8(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst) {
emit_bs_get_utf8(Ctx, Fail);
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_skip_utf8(const ArgVal &Ctx,
- const ArgVal &Fail) {
+void BeamModuleAssembler::emit_i_bs_skip_utf8(const ArgRegister &Ctx,
+ const ArgLabel &Fail) {
emit_bs_get_utf8(Ctx, Fail);
}
-void BeamModuleAssembler::emit_i_bs_utf16_size(const ArgVal &Src,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_utf16_size(const ArgSource &Src,
+ const ArgXRegister &Dst) {
mov_arg(ARG1, Src);
mov_imm(RET, make_small(2));
@@ -1224,12 +1220,12 @@ void BeamModuleAssembler::emit_i_bs_utf16_size(const ArgVal &Src,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_put_utf16(const ArgVal &Fail,
- const ArgVal &Flags,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_bs_put_utf16(const ArgLabel &Fail,
+ const ArgWord &Flags,
+ const ArgSource &Src) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -1246,8 +1242,8 @@ void BeamModuleAssembler::emit_i_bs_put_utf16(const ArgVal &Fail,
a.test(RET, RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.je(resolve_beam_label(Fail));
} else {
a.short_().jne(next);
emit_error(BADARG);
@@ -1255,34 +1251,34 @@ void BeamModuleAssembler::emit_i_bs_put_utf16(const ArgVal &Fail,
}
}
-void BeamModuleAssembler::emit_bs_get_utf16(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Flags) {
+void BeamModuleAssembler::emit_bs_get_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags) {
mov_arg(ARG1, Ctx);
emit_enter_runtime();
a.lea(ARG1, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb)));
- mov_imm(ARG2, Flags.getValue());
+ mov_imm(ARG2, Flags.get());
runtime_call<2>(erts_bs_get_utf16);
emit_leave_runtime();
emit_test_the_non_value(RET);
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_i_bs_get_utf16(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Flags,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_get_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags,
+ const ArgRegister &Dst) {
emit_bs_get_utf16(Ctx, Fail, Flags);
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_skip_utf16(const ArgVal &Ctx,
- const ArgVal &Fail,
- const ArgVal &Flags) {
+void BeamModuleAssembler::emit_i_bs_skip_utf16(const ArgRegister &Ctx,
+ const ArgLabel &Fail,
+ const ArgWord &Flags) {
emit_bs_get_utf16(Ctx, Fail, Flags);
}
@@ -1304,12 +1300,12 @@ void BeamModuleAssembler::emit_validate_unicode(Label next,
a.jmp(next);
}
-void BeamModuleAssembler::emit_i_bs_validate_unicode(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_bs_validate_unicode(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label fail, next = a.newLabel();
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
}
@@ -1317,7 +1313,7 @@ void BeamModuleAssembler::emit_i_bs_validate_unicode(const ArgVal &Fail,
mov_arg(ARG1, Src);
emit_validate_unicode(next, fail, ARG1);
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
a.bind(fail);
emit_error(BADARG);
}
@@ -1325,9 +1321,10 @@ void BeamModuleAssembler::emit_i_bs_validate_unicode(const ArgVal &Fail,
a.bind(next);
}
-void BeamModuleAssembler::emit_i_bs_validate_unicode_retract(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Ms) {
+void BeamModuleAssembler::emit_i_bs_validate_unicode_retract(
+ const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgRegister &Ms) {
Label fail = a.newLabel(), next = a.newLabel();
mov_arg(ARG1, Src);
@@ -1341,8 +1338,8 @@ void BeamModuleAssembler::emit_i_bs_validate_unicode_retract(const ArgVal &Fail,
a.sub(emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)),
imm(32));
- if (Fail.getValue() != 0) {
- a.jmp(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.jmp(resolve_beam_label(Fail));
} else {
emit_error(BADARG);
}
@@ -1351,10 +1348,10 @@ void BeamModuleAssembler::emit_i_bs_validate_unicode_retract(const ArgVal &Fail,
a.bind(next);
}
-void BeamModuleAssembler::emit_bs_test_unit(const ArgVal &Fail,
- const ArgVal &Ctx,
- const ArgVal &Unit) {
- unsigned int unit = Unit.getValue();
+void BeamModuleAssembler::emit_bs_test_unit(const ArgLabel &Fail,
+ const ArgRegister &Ctx,
+ const ArgWord &Unit) {
+ unsigned int unit = Unit.get();
mov_arg(ARG1, Ctx);
@@ -1371,7 +1368,7 @@ void BeamModuleAssembler::emit_bs_test_unit(const ArgVal &Fail,
a.test(RETb, imm(unit - 1));
}
- a.jnz(labels[Fail.getValue()]);
+ a.jnz(resolve_beam_label(Fail));
}
/* Set the error reason when bs_add has failed. */
@@ -1383,54 +1380,57 @@ void BeamGlobalAssembler::emit_bs_add_shared() {
a.ret();
}
-void BeamModuleAssembler::emit_bs_add(const ArgVal &Fail,
- const ArgVal &Src1,
- const ArgVal &Src2,
- const ArgVal &Unit,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_bs_add(const ArgLabel &Fail,
+ const ArgSource &Src1,
+ const ArgSource &Src2,
+ const ArgWord &Unit,
+ const ArgXRegister &Dst) {
Label fail;
- if (Fail.getValue() != 0) {
- fail = labels[Fail.getValue()];
+ if (Fail.get() != 0) {
+ fail = resolve_beam_label(Fail);
} else {
fail = a.newLabel();
}
/* Both arguments must be immediates on x64. */
mov_arg(ARG1, Src1);
- if (Src2.getType() == ArgVal::i) {
+
+ if (Src2.isImmed()) {
a.mov(RETd, ARG1d);
} else {
mov_arg(ARG2, Src2);
a.mov(RETd, ARG2d);
- if (Src1.getType() != ArgVal::i) {
+ if (Src1.isImmed()) {
a.and_(RETd, ARG1d);
}
}
+
a.and_(RETb, imm(_TAG_IMMED1_MASK));
a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
a.jne(fail);
/* Verify that ARG2 >= 0 and multiply ARG2 by the unit. The
* result will be untagged but not shifted and stored in RET. */
- if (Src2.getType() == ArgVal::i) {
- Uint val = unsigned_val(Src2.getValue());
+ if (Src2.isSmall()) {
+ Uint val = Src2.as<ArgSmall>().getUnsigned();
+
if ((val >> (sizeof(Eterm) - 1) * 8) != 0) {
/* Protect against negative or huge literal size. */
a.jmp(fail);
return;
} else {
- val = (Unit.getValue() * val) << _TAG_IMMED1_SIZE;
+ val = (Unit.get() * val) << _TAG_IMMED1_SIZE;
mov_imm(RET, val);
}
} else {
a.and_(ARG2, imm(~_TAG_IMMED1_MASK));
a.js(fail);
/* Multiply ARG2 by unit. */
- if (Unit.getValue() == 1) {
+ if (Unit.get() == 1) {
a.mov(RET, ARG2);
} else {
- mov_imm(RET, Unit.getValue());
+ mov_imm(RET, Unit.get());
a.mul(ARG2); /* CLOBBERS RDX = ARG3! */
a.jo(fail);
}
@@ -1444,7 +1444,7 @@ void BeamModuleAssembler::emit_bs_add(const ArgVal &Fail,
* flag when the result won't fit an immediate. */
a.add(RET, ARG1);
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
a.jo(fail);
} else {
Label next = a.newLabel();
@@ -1456,7 +1456,7 @@ void BeamModuleAssembler::emit_bs_add(const ArgVal &Fail,
mov_arg(ARG2, Src1);
mov_arg(ARG3, Src2);
safe_fragment_call(ga->get_bs_add_shared());
- emit_handle_error();
+ emit_raise_exception();
}
a.bind(next);
@@ -1465,16 +1465,16 @@ void BeamModuleAssembler::emit_bs_add(const ArgVal &Fail,
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_append(const ArgVal &Fail,
- const ArgVal &ExtraHeap,
- const ArgVal &Live,
- const ArgVal &Unit,
- const ArgVal &Size,
- const ArgVal &Bin,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_append(const ArgLabel &Fail,
+ const ArgWord &ExtraHeap,
+ const ArgWord &Live,
+ const ArgWord &Unit,
+ const ArgSource &Size,
+ const ArgSource &Bin,
+ const ArgRegister &Dst) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -1483,7 +1483,7 @@ void BeamModuleAssembler::emit_i_bs_append(const ArgVal &Fail,
mov_arg(ARG5, ExtraHeap);
mov_arg(ARG6, Unit);
- mov_arg(ArgVal(ArgVal::TYPE::x, Live.getValue()), Bin);
+ mov_arg(ArgXRegister(Live.get()), Bin);
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
@@ -1495,26 +1495,26 @@ void BeamModuleAssembler::emit_i_bs_append(const ArgVal &Fail,
emit_test_the_non_value(RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.je(resolve_beam_label(Fail));
} else {
a.short_().jne(next);
/* The error has been prepared in `erts_bs_append` */
- emit_handle_error();
+ emit_raise_exception();
a.bind(next);
}
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_bs_private_append(const ArgVal &Fail,
- const ArgVal &Unit,
- const ArgVal &Size,
- const ArgVal &Src,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_bs_private_append(const ArgLabel &Fail,
+ const ArgWord &Unit,
+ const ArgSource &Size,
+ const ArgRegister &Src,
+ const ArgXRegister &Dst) {
Label next;
- if (Fail.getValue() == 0) {
+ if (Fail.get() == 0) {
next = a.newLabel();
}
@@ -1531,12 +1531,12 @@ void BeamModuleAssembler::emit_i_bs_private_append(const ArgVal &Fail,
emit_test_the_non_value(RET);
- if (Fail.getValue() != 0) {
- a.je(labels[Fail.getValue()]);
+ if (Fail.get() != 0) {
+ a.je(resolve_beam_label(Fail));
} else {
a.short_().jne(next);
/* The error has been prepared in `erts_bs_private_append` */
- emit_handle_error();
+ emit_raise_exception();
a.bind(next);
}
@@ -1554,60 +1554,600 @@ void BeamModuleAssembler::emit_bs_init_writable() {
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
}
-/* Old compatibility instructions for <= OTP-21. Kept in order to be able to
- * load old code. While technically we could remove these in OTP-24, we've
- * decided to keep them until at least OTP-25 to make things easier for
- * users. */
-void BeamModuleAssembler::emit_i_bs_start_match2(const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Live,
- const ArgVal &Slots,
- const ArgVal &Dst) {
- mov_arg(ARG1, Src);
- mov_arg(ARG2, Live);
- mov_arg(ARG3, Slots);
+void BeamGlobalAssembler::emit_bs_create_bin_error_shared() {
+ emit_enter_runtime<Update::eStack | Update::eHeap>();
- emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ /* ARG3 is already set by the caller */
+ a.mov(ARG2, ARG4);
+ a.mov(ARG4, ARG1);
+ a.mov(ARG1, c_p);
+ runtime_call<4>(beam_jit_bs_construct_fail_info);
- a.mov(ARG4, c_p);
- load_x_reg_array(ARG5);
- runtime_call<5>(beam_jit_bs_start_match2);
+ emit_leave_runtime<Update::eStack | Update::eHeap>();
- emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ /* We must align the return address to make it a proper tagged CP, in case
+ * we were called with `safe_fragment_call`. This is safe because we will
+ * never actually return to the return address. */
+ a.pop(ARG2);
+ a.and_(ARG2, imm(-8));
- emit_test_the_non_value(RET);
- a.je(labels[Fail.getValue()]);
- mov_arg(Dst, RET);
+#ifdef NATIVE_ERLANG_STACK
+ a.push(ARG2);
+
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+# ifdef ERLANG_FRAME_POINTERS
+ a.push(frame_pointer);
+# endif
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_RA);
+ }
+#endif
+
+ mov_imm(ARG4, nullptr);
+ a.jmp(labels[raise_exception_shared]);
}
-void BeamModuleAssembler::emit_i_bs_save2(const ArgVal &Ctx,
- const ArgVal &Slot) {
- int slot_offset = offsetof(ErlBinMatchState, save_offset) +
- (sizeof(Eterm) * Slot.getValue());
+struct BscSegment {
+ BscSegment()
+ : type(am_false), unit(1), flags(0), src(ArgNil()), size(ArgNil()),
+ error_info(0), effectiveSize(-1) {
+ }
- mov_arg(ARG1, Ctx);
+ Eterm type;
+ Uint unit;
+ Uint flags;
+ ArgVal src;
+ ArgVal size;
+
+ Uint error_info;
+ Sint effectiveSize;
+};
+
+void BeamModuleAssembler::emit_i_bs_create_bin(const ArgLabel &Fail,
+ const ArgWord &Alloc,
+ const ArgWord &Live0,
+ const ArgRegister &Dst,
+ const Span<ArgVal> &args) {
+ Uint num_bits = 0;
+ std::size_t n = args.size();
+ std::vector<BscSegment> segments;
+ Label error = a.newLabel();
+ Label past_error = a.newLabel();
+ ArgWord Live = Live0;
+ x86::Gp sizeReg;
+
+ /*
+ * Collect information about each segment and calculate sizes of
+ * fixed segments.
+ */
+ for (std::size_t i = 0; i < n; i += 6) {
+ BscSegment seg;
+ JitBSCOp bsc_op;
+ Uint bsc_segment;
+
+ seg.type = args[i].as<ArgImmed>().get();
+ bsc_segment = args[i + 1].as<ArgWord>().get();
+ seg.unit = args[i + 2].as<ArgWord>().get();
+ seg.flags = args[i + 3].as<ArgWord>().get();
+ seg.src = args[i + 4];
+ seg.size = args[i + 5];
+
+ switch (seg.type) {
+ case am_float:
+ bsc_op = BSC_OP_FLOAT;
+ break;
+ case am_integer:
+ bsc_op = BSC_OP_INTEGER;
+ break;
+ case am_utf8:
+ bsc_op = BSC_OP_UTF8;
+ break;
+ case am_utf16:
+ bsc_op = BSC_OP_UTF16;
+ break;
+ case am_utf32:
+ bsc_op = BSC_OP_UTF32;
+ break;
+ default:
+ bsc_op = BSC_OP_BINARY;
+ break;
+ }
- a.mov(ARG2, emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)));
- a.mov(emit_boxed_val(ARG1, slot_offset), ARG2);
-}
+ /*
+ * Save segment number and operation for use in extended
+ * error information.
+ */
+ seg.error_info = beam_jit_set_bsc_segment_op(bsc_segment, bsc_op);
+
+ /*
+ * As soon as we have entered runtime mode, Y registers can no
+ * longer be accessed in the usual way. Therefore, if the source
+ * and/or size are in Y register, copy them to X registers.
+ */
+ if (seg.src.isYRegister()) {
+ ArgVal reg = ArgXRegister(Live.get());
+ mov_arg(reg, seg.src);
+
+ Live = Live + 1;
+ seg.src = reg;
+ }
-void BeamModuleAssembler::emit_i_bs_restore2(const ArgVal &Ctx,
- const ArgVal &Slot) {
- int slot_offset = offsetof(ErlBinMatchState, save_offset) +
- (sizeof(Eterm) * Slot.getValue());
+ if (seg.size.isYRegister()) {
+ ArgVal reg = ArgXRegister(Live.get());
+ mov_arg(reg, seg.size);
- mov_arg(ARG1, Ctx);
+ Live = Live + 1;
+ seg.size = reg;
+ }
- a.mov(ARG2, emit_boxed_val(ARG1, slot_offset));
- a.mov(emit_boxed_val(ARG1, offsetof(ErlBinMatchState, mb.offset)), ARG2);
-}
+ if (seg.size.isSmall() && seg.unit != 0) {
+ Uint unsigned_size = seg.size.as<ArgSmall>().getUnsigned();
-void BeamModuleAssembler::emit_bs_context_to_binary(const ArgVal &Src) {
- mov_arg(ARG1, Src);
+ if ((unsigned_size >> (sizeof(Eterm) - 1) * 8) == 0) {
+ /* This multiplication cannot overflow. */
+ Uint seg_size = seg.unit * unsigned_size;
+ seg.effectiveSize = seg_size;
+ num_bits += seg_size;
+ }
+ }
- emit_enter_runtime();
+ if (seg.effectiveSize < 0 && seg.type != am_append &&
+ seg.type != am_private_append) {
+ sizeReg = FCALLS;
+ }
- runtime_call<1>(beam_jit_bs_context_to_binary);
+ segments.insert(segments.end(), seg);
+ }
- emit_leave_runtime();
+ emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+
+ a.short_().jmp(past_error);
+ a.bind(error);
+ {
+ /*
+ * ARG1 = optional bad size value; valid if BSC_VALUE_ARG1 is set in
+ * ARG4
+ *
+ * ARG3 = optional bad size value; valid if BSC_VALUE_ARG3 is set
+ * in ARG4
+ *
+ * ARG4 = packed error information
+ */
+ comment("handle error");
+ emit_leave_runtime<Update::eReductions | Update::eStack |
+ Update::eHeap>();
+ if (Fail.get() != 0) {
+ a.jmp(resolve_beam_label(Fail));
+ } else {
+ safe_fragment_call(ga->get_bs_create_bin_error_shared());
+ }
+ }
+
+ a.bind(past_error);
+
+ /* We count the total number of bits in an unsigned integer. To
+ * avoid having to check for overflow when adding to the counter,
+ * we ensure that the signed size of each segment fits in a
+ * word. */
+ if (sizeReg.isValid()) {
+ comment("calculate sizes");
+ mov_imm(sizeReg, num_bits);
+ }
+
+ /* Generate code for calculating the size of the binary to be
+ * created. */
+ for (auto seg : segments) {
+ if (seg.effectiveSize >= 0) {
+ continue;
+ }
+
+ if (seg.type == am_append || seg.type == am_private_append) {
+ continue;
+ }
+
+ if (seg.size.isAtom() && seg.size.as<ArgAtom>().get() == am_all &&
+ seg.type == am_binary) {
+ comment("size of an entire binary");
+ mov_arg(ARG1, seg.src);
+ runtime_call<1>(beam_jit_bs_bit_size);
+ if (exact_type(seg.src, BEAM_TYPE_BITSTRING)) {
+ comment("skipped check for success since the source "
+ "is always a bit string");
+ } else {
+ if (Fail.get() == 0) {
+ mov_arg(ARG1, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG1));
+ }
+ a.test(RET, RET);
+ a.js(error);
+ }
+ a.add(sizeReg, RET);
+ } else if (seg.unit != 0) {
+ bool can_fail = true;
+ comment("size binary/integer/float/string");
+
+ if (always_small(seg.size)) {
+ auto min = std::get<0>(getIntRange(seg.size));
+ if (min >= 0) {
+ can_fail = false;
+ }
+ }
+
+ if (can_fail && Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_DEPENDS,
+ BSC_INFO_SIZE,
+ BSC_VALUE_ARG1));
+ }
+
+ mov_arg(ARG1, seg.size);
+
+ if (always_small(seg.size)) {
+ comment("skipped test for small size since it is always small");
+ } else if (always_one_of(seg.size,
+ BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("simplified test for small size since it is a number");
+ a.test(ARG1d, imm(TAG_PRIMARY_LIST));
+ a.je(error);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.jne(error);
+ }
+
+ a.mov(RET, ARG1);
+ a.sar(RET, imm(_TAG_IMMED1_SIZE));
+ if (can_fail) {
+ a.js(error);
+ }
+ if (seg.unit != 1) {
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(
+ seg.error_info,
+ BSC_REASON_SYSTEM_LIMIT,
+ BSC_INFO_SIZE,
+ BSC_VALUE_ARG1));
+ }
+ a.imul(RET, RET, imm(seg.unit));
+ a.jo(error);
+ }
+ a.add(sizeReg, RET);
+ } else {
+ switch (seg.type) {
+ case am_utf8: {
+ Label next = a.newLabel();
+
+ comment("size utf8");
+ mov_arg(ARG1, seg.src);
+
+ mov_imm(RET, 0);
+ a.mov(RETb, imm(1 * 8));
+ a.cmp(ARG1, imm(make_small(0x80UL)));
+ a.short_().jl(next);
+
+ a.mov(RETb, imm(2 * 8));
+ a.cmp(ARG1, imm(make_small(0x800UL)));
+ a.short_().jl(next);
+
+ a.mov(RETb, imm(3 * 8));
+ a.cmp(ARG1, imm(make_small(0x10000UL)));
+ a.short_().jl(next);
+
+ a.mov(RETb, imm(4 * 8));
+
+ a.bind(next);
+ a.add(sizeReg, RET);
+ break;
+ }
+ case am_utf16: {
+ mov_arg(ARG1, seg.src);
+ mov_imm(RET, 2 * 8);
+ mov_imm(ARG2, 4 * 8);
+ a.cmp(ARG1, imm(make_small(0x10000UL)));
+ a.cmovae(RET, ARG2);
+ a.add(sizeReg, RET);
+ break;
+ }
+ case am_utf32: {
+ Label next = a.newLabel();
+
+ mov_arg(ARG1, seg.src);
+
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG1));
+ }
+
+ a.add(sizeReg, imm(4 * 8));
+
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.jne(error);
+
+ a.cmp(ARG1, imm(make_small(0xD800UL)));
+ a.short_().jb(next);
+ a.cmp(ARG1, imm(make_small(0xDFFFUL)));
+ a.jbe(error);
+ a.cmp(ARG1, imm(make_small(0x10FFFFUL)));
+ a.ja(error);
+
+ a.bind(next);
+ break;
+ }
+ default:
+ ASSERT(0);
+ }
+ }
+ }
+
+ /* Allocate the binary. */
+ if (segments[0].type == am_append) {
+ BscSegment seg = segments[0];
+ comment("append to binary");
+ mov_arg(ARG3, Live);
+ if (sizeReg.isValid()) {
+ a.mov(ARG4, sizeReg);
+ } else {
+ mov_imm(ARG4, num_bits);
+ }
+ mov_arg(ARG5, Alloc);
+ mov_imm(ARG6, seg.unit);
+ mov_arg(ArgXRegister(Live.get()), seg.src);
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<6>(erts_bs_append_checked);
+ if (Fail.get() == 0) {
+ mov_arg(ARG1, ArgXRegister(Live.get()));
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_FVALUE,
+ BSC_VALUE_ARG1));
+ }
+ emit_test_the_non_value(RET);
+ a.je(error);
+ } else if (segments[0].type == am_private_append) {
+ BscSegment seg = segments[0];
+ comment("private append to binary");
+ ASSERT(Alloc.get() == 0);
+ mov_arg(ARG2, seg.src);
+ if (sizeReg.isValid()) {
+ a.mov(ARG3, sizeReg);
+ } else {
+ mov_imm(ARG3, num_bits);
+ }
+ a.mov(ARG4, seg.unit);
+ a.mov(ARG1, c_p);
+ runtime_call<4>(erts_bs_private_append_checked);
+ /* There is no way the call can fail on a 64-bit architecture. */
+ } else {
+ comment("allocate binary");
+ mov_arg(ARG5, Alloc);
+ mov_arg(ARG6, Live);
+ load_erl_bits_state(ARG3);
+ load_x_reg_array(ARG2);
+ a.mov(ARG1, c_p);
+ if (sizeReg.isValid()) {
+ comment("(size in bits)");
+ a.mov(ARG4, sizeReg);
+ runtime_call<6>(beam_jit_bs_init_bits);
+ } else if (num_bits % 8 == 0) {
+ comment("(size in bytes)");
+ mov_imm(ARG4, num_bits / 8);
+ runtime_call<6>(beam_jit_bs_init);
+ } else {
+ mov_imm(ARG4, num_bits);
+ runtime_call<6>(beam_jit_bs_init_bits);
+ }
+ }
+ a.mov(TMP_MEM1q, RET);
+
+ /* Build each segment of the binary. */
+ for (auto seg : segments) {
+ switch (seg.type) {
+ case am_append:
+ case am_private_append:
+ break;
+ case am_binary: {
+ Uint error_info;
+ bool can_fail = true;
+
+ comment("construct a binary segment");
+ if (seg.effectiveSize >= 0) {
+ /* The segment has a literal size. */
+ mov_imm(ARG3, seg.effectiveSize);
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_new_bs_put_binary);
+ error_info = beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_DEPENDS,
+ BSC_VALUE_FVALUE);
+ } else if (seg.size.isAtom() &&
+ seg.size.as<ArgAtom>().get() == am_all) {
+ /* Include the entire binary/bitstring in the
+ * resulting binary. */
+ a.mov(ARG3, seg.unit);
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_new_bs_put_binary_all);
+ error_info = beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_UNIT,
+ BSC_VALUE_FVALUE);
+ if (seg.unit == 1) {
+ comment("skipped test for success because unit =:= 1");
+ can_fail = false;
+ }
+ } else {
+ /* The size is a variable. We have verified that
+ * the value is a non-negative small in the
+ * appropriate range. Multiply the size with the
+ * unit. */
+ mov_arg(ARG3, seg.size);
+ a.sar(ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit != 1) {
+ mov_imm(RET, seg.unit);
+ a.mul(ARG3); /* CLOBBERS RDX = ARG3! */
+ a.mov(ARG3, RET);
+ }
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG1, c_p);
+ runtime_call<3>(erts_new_bs_put_binary);
+ error_info = beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_DEPENDS,
+ BSC_VALUE_FVALUE);
+ }
+
+ if (can_fail) {
+ if (Fail.get() == 0) {
+ mov_imm(ARG4, error_info);
+ }
+ a.test(RETd, RETd);
+ a.je(error);
+ }
+ break;
+ }
+ case am_float:
+ comment("construct float segment");
+ if (seg.effectiveSize >= 0) {
+ mov_imm(ARG3, seg.effectiveSize);
+ } else {
+ mov_arg(ARG3, seg.size);
+ a.sar(ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit != 1) {
+ mov_imm(RET, seg.unit);
+ a.mul(ARG3); /* CLOBBERS RDX = ARG3! */
+ a.mov(ARG3, RET);
+ }
+ }
+ mov_arg(ARG2, seg.src);
+ mov_imm(ARG4, seg.flags);
+ a.mov(ARG1, c_p);
+ runtime_call<4>(erts_new_bs_put_float);
+ if (Fail.get() == 0) {
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_FVALUE,
+ BSC_VALUE_ARG1));
+ }
+ a.mov(ARG1, RET);
+ emit_test_the_non_value(RET);
+ a.jne(error);
+ break;
+ case am_integer:
+ comment("construct integer segment");
+ if (seg.effectiveSize >= 0) {
+ mov_imm(ARG3, seg.effectiveSize);
+ } else {
+ mov_arg(ARG3, seg.size);
+ a.sar(ARG3, imm(_TAG_IMMED1_SIZE));
+ if (seg.unit != 1) {
+ mov_imm(RET, seg.unit);
+ a.mul(ARG3); /* CLOBBERS RDX = ARG3! */
+ a.mov(ARG3, RET);
+ }
+ }
+ mov_arg(ARG2, seg.src);
+ mov_imm(ARG4, seg.flags);
+ load_erl_bits_state(ARG1);
+ runtime_call<4>(erts_new_bs_put_integer);
+ if (exact_type(seg.src, BEAM_TYPE_INTEGER)) {
+ comment("skipped test for success because construction can't "
+ "fail");
+ } else {
+ if (Fail.get() == 0) {
+ mov_arg(ARG1, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG1));
+ }
+ a.test(RETd, RETd);
+ a.je(error);
+ }
+ break;
+ case am_string: {
+ ArgBytePtr string_ptr(
+ ArgVal(ArgVal::BytePtr, seg.src.as<ArgWord>().get()));
+
+ comment("insert string");
+ ASSERT(seg.effectiveSize >= 0);
+ mov_imm(ARG3, seg.effectiveSize / 8);
+ mov_arg(ARG2, string_ptr);
+ load_erl_bits_state(ARG1);
+ runtime_call<3>(erts_new_bs_put_string);
+ } break;
+ case am_utf8:
+ mov_arg(ARG2, seg.src);
+ load_erl_bits_state(ARG1);
+ runtime_call<2>(erts_bs_put_utf8);
+ if (Fail.get() == 0) {
+ mov_arg(ARG1, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG1));
+ }
+ a.test(RETd, RETd);
+ a.je(error);
+ break;
+ case am_utf16:
+ mov_arg(ARG2, seg.src);
+ a.mov(ARG3, seg.flags);
+ load_erl_bits_state(ARG1);
+ runtime_call<3>(erts_bs_put_utf16);
+ if (Fail.get() == 0) {
+ mov_arg(ARG1, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG1));
+ }
+ a.test(RETd, RETd);
+ a.je(error);
+ break;
+ case am_utf32:
+ mov_arg(ARG2, seg.src);
+ mov_imm(ARG3, 4 * 8);
+ a.mov(ARG4, seg.flags);
+ load_erl_bits_state(ARG1);
+ runtime_call<4>(erts_new_bs_put_integer);
+ if (Fail.get() == 0) {
+ mov_arg(ARG1, seg.src);
+ mov_imm(ARG4,
+ beam_jit_update_bsc_reason_info(seg.error_info,
+ BSC_REASON_BADARG,
+ BSC_INFO_TYPE,
+ BSC_VALUE_ARG1));
+ }
+ a.test(RETd, RETd);
+ a.je(error);
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ comment("done");
+ emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ a.mov(RET, TMP_MEM1q);
+ mov_arg(Dst, RET);
}
diff --git a/erts/emulator/beam/jit/x86/instr_call.cpp b/erts/emulator/beam/jit/x86/instr_call.cpp
index de6b537393..8cf676737f 100644
--- a/erts/emulator/beam/jit/x86/instr_call.cpp
+++ b/erts/emulator/beam/jit/x86/instr_call.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,13 +39,13 @@ void BeamGlobalAssembler::emit_dispatch_return() {
}
void BeamModuleAssembler::emit_return() {
- Label dispatch_return = a.newLabel();
-
#ifdef JIT_HARD_DEBUG
/* Validate return address and {x,0} */
- emit_validate(ArgVal(ArgVal::u, 1));
+ emit_validate(ArgWord(1));
#endif
+ emit_leave_frame();
+
#if !defined(NATIVE_ERLANG_STACK)
a.mov(ARG3, getCPRef());
a.mov(getCPRef(), imm(NIL));
@@ -54,33 +54,29 @@ void BeamModuleAssembler::emit_return() {
/* The reduction test is kept in module code because moving it to a shared
* fragment caused major performance regressions in dialyzer. */
a.dec(FCALLS);
- a.short_().jl(dispatch_return);
+ a.jl(resolve_fragment(ga->get_dispatch_return()));
#ifdef NATIVE_ERLANG_STACK
a.ret();
#else
a.jmp(ARG3);
#endif
-
- a.bind(dispatch_return);
- abs_jmp(ga->get_dispatch_return());
}
-void BeamModuleAssembler::emit_i_call(const ArgVal &CallDest) {
- Label dest = labels[CallDest.getValue()];
-
- erlang_call(dest, RET);
+void BeamModuleAssembler::emit_i_call(const ArgLabel &CallDest) {
+ erlang_call(resolve_beam_label(CallDest), RET);
}
-void BeamModuleAssembler::emit_i_call_last(const ArgVal &CallDest,
- const ArgVal &Deallocate) {
+void BeamModuleAssembler::emit_i_call_last(const ArgLabel &CallDest,
+ const ArgWord &Deallocate) {
emit_deallocate(Deallocate);
-
- a.jmp(labels[CallDest.getValue()]);
+ emit_i_call_only(CallDest);
}
-void BeamModuleAssembler::emit_i_call_only(const ArgVal &CallDest) {
- a.jmp(labels[CallDest.getValue()]);
+void BeamModuleAssembler::emit_i_call_only(const ArgLabel &CallDest) {
+ emit_leave_frame();
+
+ a.jmp(resolve_beam_label(CallDest));
}
/* Handles save_calls. Export entry is in RET.
@@ -104,27 +100,31 @@ void BeamGlobalAssembler::emit_dispatch_save_calls() {
a.mov(ARG1, imm(&the_active_code_index));
a.mov(ARG1d, x86::dword_ptr(ARG1));
- a.jmp(emit_setup_export_call(RET, ARG1));
+ a.jmp(emit_setup_dispatchable_call(RET, ARG1));
}
-void BeamModuleAssembler::emit_i_call_ext(const ArgVal &Exp) {
- make_move_patch(RET, imports[Exp.getValue()].patches);
- x86::Mem destination = emit_setup_export_call(RET);
+void BeamModuleAssembler::emit_i_call_ext(const ArgExport &Exp) {
+ mov_arg(RET, Exp);
+ x86::Mem destination = emit_setup_dispatchable_call(RET);
erlang_call(destination, ARG1);
}
-void BeamModuleAssembler::emit_i_call_ext_only(const ArgVal &Exp) {
- make_move_patch(RET, imports[Exp.getValue()].patches);
- x86::Mem destination = emit_setup_export_call(RET);
+void BeamModuleAssembler::emit_i_call_ext_only(const ArgExport &Exp) {
+ mov_arg(RET, Exp);
+ x86::Mem destination = emit_setup_dispatchable_call(RET);
+
+ emit_leave_frame();
a.jmp(destination);
}
-void BeamModuleAssembler::emit_i_call_ext_last(const ArgVal &Exp,
- const ArgVal &Deallocate) {
+void BeamModuleAssembler::emit_i_call_ext_last(const ArgExport &Exp,
+ const ArgWord &Deallocate) {
emit_deallocate(Deallocate);
- make_move_patch(RET, imports[Exp.getValue()].patches);
- x86::Mem destination = emit_setup_export_call(RET);
+ mov_arg(RET, Exp);
+ x86::Mem destination = emit_setup_dispatchable_call(RET);
+
+ emit_leave_frame();
a.jmp(destination);
}
@@ -155,10 +155,10 @@ x86::Mem BeamModuleAssembler::emit_variable_apply(bool includeI) {
a.test(RET, RET);
a.short_().jne(dispatch);
- emit_handle_error(entry, &apply3_mfa);
+ emit_raise_exception(entry, &apply3_mfa);
a.bind(dispatch);
- return emit_setup_export_call(RET);
+ return emit_setup_dispatchable_call(RET);
}
void BeamModuleAssembler::emit_i_apply() {
@@ -166,17 +166,19 @@ void BeamModuleAssembler::emit_i_apply() {
erlang_call(dest, ARG1);
}
-void BeamModuleAssembler::emit_i_apply_last(const ArgVal &Deallocate) {
+void BeamModuleAssembler::emit_i_apply_last(const ArgWord &Deallocate) {
emit_deallocate(Deallocate);
emit_i_apply_only();
}
void BeamModuleAssembler::emit_i_apply_only() {
x86::Mem dest = emit_variable_apply(true);
+
+ emit_leave_frame();
a.jmp(dest);
}
-x86::Mem BeamModuleAssembler::emit_fixed_apply(const ArgVal &Arity,
+x86::Mem BeamModuleAssembler::emit_fixed_apply(const ArgWord &Arity,
bool includeI) {
Label dispatch = a.newLabel(), entry = a.newLabel();
@@ -205,113 +207,23 @@ x86::Mem BeamModuleAssembler::emit_fixed_apply(const ArgVal &Arity,
a.test(RET, RET);
a.short_().jne(dispatch);
- emit_handle_error(entry, &apply3_mfa);
+ emit_raise_exception(entry, &apply3_mfa);
a.bind(dispatch);
- return emit_setup_export_call(RET);
+ return emit_setup_dispatchable_call(RET);
}
-void BeamModuleAssembler::emit_apply(const ArgVal &Arity) {
+void BeamModuleAssembler::emit_apply(const ArgWord &Arity) {
x86::Mem dest = emit_fixed_apply(Arity, false);
erlang_call(dest, ARG1);
}
-void BeamModuleAssembler::emit_apply_last(const ArgVal &Arity,
- const ArgVal &Deallocate) {
+void BeamModuleAssembler::emit_apply_last(const ArgWord &Arity,
+ const ArgWord &Deallocate) {
emit_deallocate(Deallocate);
x86::Mem dest = emit_fixed_apply(Arity, true);
- a.jmp(dest);
-}
-
-x86::Gp BeamModuleAssembler::emit_apply_fun() {
- Label dispatch = a.newLabel();
-
- emit_enter_runtime<Update::eStack | Update::eHeap>();
-
- a.mov(ARG1, c_p);
- a.mov(ARG2, getXRef(0));
- a.mov(ARG3, getXRef(1));
- load_x_reg_array(ARG4);
- a.lea(ARG5, TMP_MEM1q);
- runtime_call<5>(apply_fun);
-
- emit_leave_runtime<Update::eStack | Update::eHeap>();
-
- a.mov(ARG2, RET);
- a.test(RET, RET);
-
- /* Put the export entry, if any, into RET to follow the export calling
- * convention in case we applied an external fun. See
- * `emit_setup_export_call` for details. */
- a.mov(RET, TMP_MEM1q);
-
- a.short_().jne(dispatch);
- emit_handle_error();
- a.bind(dispatch);
-
- return ARG2;
-}
-
-void BeamModuleAssembler::emit_i_apply_fun() {
- x86::Gp dest = emit_apply_fun();
-
- ASSERT(dest != ARG1);
- erlang_call(dest, ARG1);
-}
-
-void BeamModuleAssembler::emit_i_apply_fun_last(const ArgVal &Deallocate) {
- emit_deallocate(Deallocate);
- emit_i_apply_fun_only();
-}
-
-void BeamModuleAssembler::emit_i_apply_fun_only() {
- x86::Gp dest = emit_apply_fun();
-
- a.jmp(dest);
-}
-
-x86::Gp BeamModuleAssembler::emit_call_fun(const ArgVal &Fun) {
- Label dispatch = a.newLabel();
-
- mov_arg(ARG2, Fun);
-
- emit_enter_runtime<Update::eStack | Update::eHeap>();
-
- a.mov(ARG1, c_p);
- load_x_reg_array(ARG3);
- mov_imm(ARG4, THE_NON_VALUE);
- a.lea(ARG5, TMP_MEM1q);
- runtime_call<5>(call_fun);
-
- emit_leave_runtime<Update::eStack | Update::eHeap>();
-
- a.mov(ARG2, RET);
- a.test(RET, RET);
-
- /* Put the export entry, if any, into RET to follow the export calling
- * convention in case we called an external fun. See
- * `emit_setup_export_call` for details. */
- a.mov(RET, TMP_MEM1q);
-
- a.short_().jne(dispatch);
- emit_handle_error();
- a.bind(dispatch);
-
- return ARG2;
-}
-
-void BeamModuleAssembler::emit_i_call_fun(const ArgVal &Fun) {
- x86::Gp dest = emit_call_fun(Fun);
-
- ASSERT(dest != ARG1);
- erlang_call(dest, ARG1);
-}
-
-void BeamModuleAssembler::emit_i_call_fun_last(const ArgVal &Fun,
- const ArgVal &Deallocate) {
- emit_deallocate(Deallocate);
- x86::Gp dest = emit_call_fun(Fun);
+ emit_leave_frame();
a.jmp(dest);
}
diff --git a/erts/emulator/beam/jit/x86/instr_common.cpp b/erts/emulator/beam/jit/x86/instr_common.cpp
index 09135aa25f..6a64db52b2 100644
--- a/erts/emulator/beam/jit/x86/instr_common.cpp
+++ b/erts/emulator/beam/jit/x86/instr_common.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2022. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,12 +23,17 @@
*
* Instructions that use 32-bit registers (e.g. eax) are generally
* one byte shorter than instructions that use 64-bits registers
- * (e.g. rax). This does not apply to registers r8-r15 beacuse they'll
+ * (e.g. rax). This does not apply to registers r8-r15 because they'll
* always need a rex prefix. The `and`, `or`, and `cmp` instructions
- * are even shorter than operating on the RETb (al) register. The
+ * are even shorter when operating on the RETb (al) register. The
* `test` instruction with an immediate second operand is shorter
* when operating on an 8-bit register.
*
+ * When loading an immediate value to a register, storing to the
+ * 32-bit register in one or two bytes shorter than storing to
+ * the corresponding 64-bit register. The mov_imm() helper
+ * will automatically choose the shortest instruction.
+ *
* On both Unix and Windows, instructions can be shortened by using
* RETd, ARG1d, or ARG2d instead of RET, ARG1, or ARG2, respectively.
* On Unix, but not on Windows, ARG3d and ARG4d will also result in
@@ -93,13 +98,13 @@ using namespace asmjit;
void BeamModuleAssembler::emit_error(int reason) {
a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), imm(reason));
- emit_handle_error();
+ emit_raise_exception();
}
-void BeamModuleAssembler::emit_gc_test_preserve(const ArgVal &Need,
- const ArgVal &Live,
+void BeamModuleAssembler::emit_gc_test_preserve(const ArgWord &Need,
+ const ArgWord &Live,
x86::Gp term) {
- const int32_t bytes_needed = (Need.getValue() + S_RESERVED) * sizeof(Eterm);
+ const int32_t bytes_needed = (Need.get() + S_RESERVED) * sizeof(Eterm);
Label after_gc_check = a.newLabel();
ASSERT(term != ARG3);
@@ -108,32 +113,32 @@ void BeamModuleAssembler::emit_gc_test_preserve(const ArgVal &Need,
a.cmp(ARG3, E);
a.short_().jbe(after_gc_check);
- a.mov(getXRef(Live.getValue()), term);
- mov_imm(ARG4, Live.getValue() + 1);
+ a.mov(getXRef(Live.get()), term);
+ mov_imm(ARG4, Live.get() + 1);
fragment_call(ga->get_garbage_collect());
- a.mov(term, getXRef(Live.getValue()));
+ a.mov(term, getXRef(Live.get()));
a.bind(after_gc_check);
}
-void BeamModuleAssembler::emit_gc_test(const ArgVal &Ns,
- const ArgVal &Nh,
- const ArgVal &Live) {
+void BeamModuleAssembler::emit_gc_test(const ArgWord &Ns,
+ const ArgWord &Nh,
+ const ArgWord &Live) {
const int32_t bytes_needed =
- (Ns.getValue() + Nh.getValue() + S_RESERVED) * sizeof(Eterm);
+ (Ns.get() + Nh.get() + S_RESERVED) * sizeof(Eterm);
Label after_gc_check = a.newLabel();
a.lea(ARG3, x86::qword_ptr(HTOP, bytes_needed));
a.cmp(ARG3, E);
a.short_().jbe(after_gc_check);
- mov_imm(ARG4, Live.getValue());
+ mov_imm(ARG4, Live.get());
fragment_call(ga->get_garbage_collect());
a.bind(after_gc_check);
}
-void BeamModuleAssembler::emit_validate(const ArgVal &arity) {
+void BeamModuleAssembler::emit_validate(const ArgWord &Arity) {
#ifdef DEBUG
Label next = a.newLabel(), crash = a.newLabel();
@@ -158,7 +163,7 @@ void BeamModuleAssembler::emit_validate(const ArgVal &arity) {
# ifdef JIT_HARD_DEBUG
emit_enter_runtime();
- for (unsigned i = 0; i < arity.getValue(); i++) {
+ for (unsigned i = 0; i < Arity.get(); i++) {
a.mov(ARG1, getXRef(i));
runtime_call<1>(beam_jit_validate_term);
}
@@ -171,16 +176,15 @@ void BeamModuleAssembler::emit_validate(const ArgVal &arity) {
/* Instrs */
-void BeamModuleAssembler::emit_i_validate(const ArgVal &Arity) {
+void BeamModuleAssembler::emit_i_validate(const ArgWord &Arity) {
emit_validate(Arity);
}
-void BeamModuleAssembler::emit_allocate_heap(const ArgVal &NeedStack,
- const ArgVal &NeedHeap,
- const ArgVal &Live) {
- ASSERT(NeedStack.getType() == ArgVal::TYPE::u);
- ASSERT(NeedStack.getValue() <= MAX_REG);
- ArgVal needed = NeedStack;
+void BeamModuleAssembler::emit_allocate_heap(const ArgWord &NeedStack,
+ const ArgWord &NeedHeap,
+ const ArgWord &Live) {
+ ASSERT(NeedStack.get() <= MAX_REG);
+ ArgWord needed = NeedStack;
#if !defined(NATIVE_ERLANG_STACK)
needed = needed + CP_SIZE;
@@ -188,39 +192,45 @@ void BeamModuleAssembler::emit_allocate_heap(const ArgVal &NeedStack,
emit_gc_test(needed, NeedHeap, Live);
- if (needed.getValue() > 0) {
- a.sub(E, imm(needed.getValue() * sizeof(Eterm)));
+ if (needed.get() > 0) {
+ a.sub(E, imm(needed.get() * sizeof(Eterm)));
}
+
#if !defined(NATIVE_ERLANG_STACK)
a.mov(getCPRef(), imm(NIL));
#endif
}
-void BeamModuleAssembler::emit_allocate(const ArgVal &NeedStack,
- const ArgVal &Live) {
- emit_allocate_heap(NeedStack, ArgVal(ArgVal::TYPE::u, 0), Live);
+void BeamModuleAssembler::emit_allocate(const ArgWord &NeedStack,
+ const ArgWord &Live) {
+ emit_allocate_heap(NeedStack, ArgWord(0), Live);
}
-void BeamModuleAssembler::emit_deallocate(const ArgVal &Deallocate) {
- ASSERT(Deallocate.getType() == ArgVal::TYPE::u);
- ASSERT(Deallocate.getValue() <= 1023);
- ArgVal dealloc = Deallocate;
+void BeamModuleAssembler::emit_deallocate(const ArgWord &Deallocate) {
+ ASSERT(Deallocate.get() <= 1023);
+
+ if (ERTS_LIKELY(erts_frame_layout == ERTS_FRAME_LAYOUT_RA)) {
+ ArgWord dealloc = Deallocate;
#if !defined(NATIVE_ERLANG_STACK)
- dealloc = dealloc + CP_SIZE;
+ dealloc = dealloc + CP_SIZE;
#endif
- if (dealloc.getValue() > 0) {
- a.add(E, imm(dealloc.getValue() * sizeof(Eterm)));
+ if (dealloc.get() > 0) {
+ a.add(E, imm(dealloc.get() * sizeof(Eterm)));
+ }
+ } else {
+ ASSERT(erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA);
}
}
-void BeamModuleAssembler::emit_test_heap(const ArgVal &Nh, const ArgVal &Live) {
- emit_gc_test(ArgVal(ArgVal::u, 0), Nh, Live);
+void BeamModuleAssembler::emit_test_heap(const ArgWord &Nh,
+ const ArgWord &Live) {
+ emit_gc_test(ArgWord(0), Nh, Live);
}
void BeamModuleAssembler::emit_normal_exit() {
- /* This is implictly global; it does not normally appear in modules and
+ /* This is implicitly global; it does not normally appear in modules and
* doesn't require size optimization. */
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
@@ -235,11 +245,11 @@ void BeamModuleAssembler::emit_normal_exit() {
emit_proc_lc_require();
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
- abs_jmp(ga->get_do_schedule());
+ a.jmp(resolve_fragment(ga->get_do_schedule()));
}
void BeamModuleAssembler::emit_continue_exit() {
- /* This is implictly global; it does not normally appear in modules and
+ /* This is implicitly global; it does not normally appear in modules and
* doesn't require size optimization. */
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
@@ -251,54 +261,15 @@ void BeamModuleAssembler::emit_continue_exit() {
emit_proc_lc_require();
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
- abs_jmp(ga->get_do_schedule());
-}
-
-/* This is an alias for handle_error */
-void BeamModuleAssembler::emit_error_action_code() {
- abs_jmp(ga->get_error_action_code());
-}
-
-/* Psuedo-instruction for signalling lambda load errors. Never actually runs. */
-void BeamModuleAssembler::emit_i_lambda_error(const ArgVal &Dummy) {
- a.hlt();
-}
-
-void BeamModuleAssembler::emit_i_make_fun3(const ArgVal &Fun,
- const ArgVal &Dst,
- const ArgVal &NumFree,
- const std::vector<ArgVal> &env) {
- size_t num_free = env.size();
- ASSERT(NumFree.getValue() == num_free);
-
- mov_arg(ARG3, NumFree);
-
- emit_enter_runtime<Update::eHeap>();
-
- a.mov(ARG1, c_p);
- make_move_patch(ARG2, lambdas[Fun.getValue()].patches);
- runtime_call<3>(new_fun_thing);
-
- emit_leave_runtime<Update::eHeap>();
-
- comment("Move fun environment");
- for (unsigned i = 0; i < num_free; i++) {
- mov_arg(x86::qword_ptr(RET,
- offsetof(ErlFunThing, env) + i * sizeof(Eterm)),
- env[i]);
- }
-
- comment("Create boxed ptr");
- a.or_(RETb, TAG_PRIMARY_BOXED);
- mov_arg(Dst, RET);
+ a.jmp(resolve_fragment(ga->get_do_schedule()));
}
void BeamModuleAssembler::emit_get_list(const x86::Gp src,
- const ArgVal &Hd,
- const ArgVal &Tl) {
+ const ArgRegister &Hd,
+ const ArgRegister &Tl) {
x86::Gp boxed_ptr = emit_ptr_val(src, src);
- switch (ArgVal::register_relation(Hd, Tl)) {
+ switch (ArgVal::memory_relation(Hd, Tl)) {
case ArgVal::Relation::consecutive: {
comment("(moving head and tail together)");
x86::Mem dst_ptr = getArgRef(Hd, 16);
@@ -329,14 +300,15 @@ void BeamModuleAssembler::emit_get_list(const x86::Gp src,
}
}
-void BeamModuleAssembler::emit_get_list(const ArgVal &Src,
- const ArgVal &Hd,
- const ArgVal &Tl) {
+void BeamModuleAssembler::emit_get_list(const ArgRegister &Src,
+ const ArgRegister &Hd,
+ const ArgRegister &Tl) {
mov_arg(ARG1, Src);
emit_get_list(ARG1, Hd, Tl);
}
-void BeamModuleAssembler::emit_get_hd(const ArgVal &Src, const ArgVal &Hd) {
+void BeamModuleAssembler::emit_get_hd(const ArgRegister &Src,
+ const ArgRegister &Hd) {
mov_arg(ARG1, Src);
x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
@@ -346,7 +318,8 @@ void BeamModuleAssembler::emit_get_hd(const ArgVal &Src, const ArgVal &Hd) {
mov_arg(Hd, ARG2);
}
-void BeamModuleAssembler::emit_get_tl(const ArgVal &Src, const ArgVal &Tl) {
+void BeamModuleAssembler::emit_get_tl(const ArgRegister &Src,
+ const ArgRegister &Tl) {
mov_arg(ARG1, Src);
x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
@@ -356,22 +329,23 @@ void BeamModuleAssembler::emit_get_tl(const ArgVal &Src, const ArgVal &Tl) {
mov_arg(Tl, ARG2);
}
-void BeamModuleAssembler::emit_is_nonempty_list_get_list(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Hd,
- const ArgVal &Tl) {
+void BeamModuleAssembler::emit_is_nonempty_list_get_list(
+ const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Hd,
+ const ArgRegister &Tl) {
mov_arg(RET, Src);
a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
emit_get_list(RET, Hd, Tl);
}
-void BeamModuleAssembler::emit_is_nonempty_list_get_hd(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Hd) {
+void BeamModuleAssembler::emit_is_nonempty_list_get_hd(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Hd) {
mov_arg(RET, Src);
a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
@@ -380,12 +354,12 @@ void BeamModuleAssembler::emit_is_nonempty_list_get_hd(const ArgVal &Fail,
mov_arg(Hd, ARG2);
}
-void BeamModuleAssembler::emit_is_nonempty_list_get_tl(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Tl) {
+void BeamModuleAssembler::emit_is_nonempty_list_get_tl(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Tl) {
mov_arg(RET, Src);
a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
@@ -394,7 +368,8 @@ void BeamModuleAssembler::emit_is_nonempty_list_get_tl(const ArgVal &Fail,
mov_arg(Tl, ARG2);
}
-void BeamModuleAssembler::emit_i_get(const ArgVal &Src, const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_get(const ArgSource &Src,
+ const ArgRegister &Dst) {
mov_arg(ARG2, Src);
emit_enter_runtime();
@@ -407,9 +382,9 @@ void BeamModuleAssembler::emit_i_get(const ArgVal &Src, const ArgVal &Dst) {
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_get_hash(const ArgVal &Src,
- const ArgVal &Hash,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_get_hash(const ArgConstant &Src,
+ const ArgWord &Hash,
+ const ArgRegister &Dst) {
mov_arg(ARG2, Hash);
mov_arg(ARG3, Src);
@@ -424,7 +399,7 @@ void BeamModuleAssembler::emit_i_get_hash(const ArgVal &Src,
}
/* Store the pointer to a tuple in ARG2. Remove any LITERAL_PTR tag. */
-void BeamModuleAssembler::emit_load_tuple_ptr(const ArgVal &Term) {
+void BeamModuleAssembler::emit_load_tuple_ptr(const ArgSource &Term) {
mov_arg(ARG2, Term);
(void)emit_ptr_val(ARG2, ARG2);
}
@@ -432,7 +407,7 @@ void BeamModuleAssembler::emit_load_tuple_ptr(const ArgVal &Term) {
#ifdef DEBUG
/* Emit an assertion to ensure that tuple_reg points into the same
* tuple as Src. */
-void BeamModuleAssembler::emit_tuple_assertion(const ArgVal &Src,
+void BeamModuleAssembler::emit_tuple_assertion(const ArgSource &Src,
x86::Gp tuple_reg) {
Label ok = a.newLabel(), fatal = a.newLabel();
ASSERT(tuple_reg != RET);
@@ -443,38 +418,41 @@ void BeamModuleAssembler::emit_tuple_assertion(const ArgVal &Src,
a.short_().je(ok);
a.bind(fatal);
- { a.ud2(); }
+ {
+ comment("tuple assertion failure");
+ a.ud2();
+ }
a.bind(ok);
}
#endif
/* Fetch an element from the tuple pointed to by the boxed pointer
* in ARG2. */
-void BeamModuleAssembler::emit_i_get_tuple_element(const ArgVal &Src,
- const ArgVal &Element,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_get_tuple_element(const ArgSource &Src,
+ const ArgWord &Element,
+ const ArgRegister &Dst) {
#ifdef DEBUG
emit_tuple_assertion(Src, ARG2);
#endif
- a.mov(ARG1, emit_boxed_val(ARG2, Element.getValue()));
+ a.mov(ARG1, emit_boxed_val(ARG2, Element.get()));
mov_arg(Dst, ARG1);
}
/* Fetch two consecutive tuple elements from the tuple pointed to by
* the boxed pointer in ARG2. */
-void BeamModuleAssembler::emit_get_two_tuple_elements(const ArgVal &Src,
- const ArgVal &Element,
- const ArgVal &Dst1,
- const ArgVal &Dst2) {
+void BeamModuleAssembler::emit_get_two_tuple_elements(const ArgSource &Src,
+ const ArgWord &Element,
+ const ArgRegister &Dst1,
+ const ArgRegister &Dst2) {
#ifdef DEBUG
emit_tuple_assertion(Src, ARG2);
#endif
x86::Mem element_ptr =
- emit_boxed_val(ARG2, Element.getValue(), 2 * sizeof(Eterm));
+ emit_boxed_val(ARG2, Element.get(), 2 * sizeof(Eterm));
- switch (ArgVal::register_relation(Dst1, Dst2)) {
+ switch (ArgVal::memory_relation(Dst1, Dst2)) {
case ArgVal::Relation::consecutive: {
x86::Mem dst_ptr = getArgRef(Dst1, 16);
a.movups(x86::xmm0, element_ptr);
@@ -493,21 +471,21 @@ void BeamModuleAssembler::emit_get_two_tuple_elements(const ArgVal &Src,
}
case ArgVal::Relation::none:
fallback:
- a.mov(ARG1, emit_boxed_val(ARG2, Element.getValue()));
- a.mov(ARG3, emit_boxed_val(ARG2, (Element + sizeof(Eterm)).getValue()));
+ a.mov(ARG1, emit_boxed_val(ARG2, Element.get()));
+ a.mov(ARG3, emit_boxed_val(ARG2, Element.get() + sizeof(Eterm)));
mov_arg(Dst1, ARG1);
mov_arg(Dst2, ARG3);
break;
}
}
-void BeamModuleAssembler::emit_init(const ArgVal &Y) {
- mov_arg(Y, NIL);
+void BeamModuleAssembler::emit_init(const ArgYRegister &Dst) {
+ mov_arg(Dst, NIL);
}
-void BeamModuleAssembler::emit_init_yregs(const ArgVal &Size,
- const std::vector<ArgVal> &args) {
- unsigned count = Size.getValue();
+void BeamModuleAssembler::emit_init_yregs(const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ unsigned count = Size.get();
ASSERT(count == args.size());
if (count == 1) {
@@ -522,14 +500,16 @@ void BeamModuleAssembler::emit_init_yregs(const ArgVal &Size,
mov_imm(x86::rax, NIL);
while (i < count) {
+ unsigned first_y = args[i].as<ArgYRegister>().get();
unsigned slots = 1;
- unsigned first_y = args.at(i).getValue();
while (i + slots < count) {
- ArgVal current_y = args.at(i + slots);
- if (first_y + slots != current_y.getValue()) {
+ const ArgYRegister &current_y = args[i + slots];
+
+ if (first_y + slots != current_y.get()) {
break;
}
+
slots++;
}
@@ -584,31 +564,30 @@ void BeamModuleAssembler::emit_init_yregs(const ArgVal &Size,
}
}
-void BeamModuleAssembler::emit_i_trim(const ArgVal &Words) {
- ASSERT(Words.getType() == ArgVal::TYPE::u);
- ASSERT(Words.getValue() <= 1023);
-
- if (Words.getValue() > 0) {
- a.add(E, imm(Words.getValue() * sizeof(Eterm)));
+void BeamModuleAssembler::emit_i_trim(const ArgWord &Words) {
+ if (Words.get() > 0) {
+ ASSERT(Words.get() <= 1023);
+ a.add(E, imm(Words.get() * sizeof(Eterm)));
}
}
-void BeamModuleAssembler::emit_i_move(const ArgVal &Src, const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_move(const ArgSource &Src,
+ const ArgRegister &Dst) {
mov_arg(Dst, Src);
}
/* Move two words at consecutive addresses to consecutive or reverse
* consecutive destinations. */
-void BeamModuleAssembler::emit_move_two_words(const ArgVal &Src1,
- const ArgVal &Dst1,
- const ArgVal &Src2,
- const ArgVal &Dst2) {
+void BeamModuleAssembler::emit_move_two_words(const ArgSource &Src1,
+ const ArgRegister &Dst1,
+ const ArgSource &Src2,
+ const ArgRegister &Dst2) {
x86::Mem src_ptr = getArgRef(Src1, 16);
- ASSERT(ArgVal::register_relation(Src1, Src2) ==
+ ASSERT(ArgVal::memory_relation(Src1, Src2) ==
ArgVal::Relation::consecutive);
- switch (ArgVal::register_relation(Dst1, Dst2)) {
+ switch (ArgVal::memory_relation(Dst1, Dst2)) {
case ArgVal::Relation::consecutive: {
x86::Mem dst_ptr = getArgRef(Dst1, 16);
a.movups(x86::xmm0, src_ptr);
@@ -635,12 +614,13 @@ void BeamModuleAssembler::emit_move_two_words(const ArgVal &Src1,
}
}
-void BeamModuleAssembler::emit_swap(const ArgVal &R1, const ArgVal &R2) {
+void BeamModuleAssembler::emit_swap(const ArgRegister &R1,
+ const ArgRegister &R2) {
if (!hasCpuFeature(CpuFeatures::X86::kAVX)) {
goto fallback;
}
- switch (ArgVal::register_relation(R1, R2)) {
+ switch (ArgVal::memory_relation(R1, R2)) {
case ArgVal::Relation::consecutive: {
x86::Mem ptr = getArgRef(R1, 16);
comment("(swapping using AVX)");
@@ -665,15 +645,16 @@ void BeamModuleAssembler::emit_swap(const ArgVal &R1, const ArgVal &R2) {
}
}
-void BeamModuleAssembler::emit_node(const ArgVal &Dst) {
+void BeamModuleAssembler::emit_node(const ArgRegister &Dst) {
a.mov(ARG1, imm(&erts_this_node));
a.mov(ARG1, x86::qword_ptr(ARG1));
a.mov(ARG1, x86::qword_ptr(ARG1, offsetof(ErlNode, sysname)));
mov_arg(Dst, ARG1);
}
-void BeamModuleAssembler::emit_put_cons(const ArgVal &Hd, const ArgVal &Tl) {
- switch (ArgVal::register_relation(Hd, Tl)) {
+void BeamModuleAssembler::emit_put_cons(const ArgSource &Hd,
+ const ArgSource &Tl) {
+ switch (ArgVal::memory_relation(Hd, Tl)) {
case ArgVal::Relation::consecutive: {
x86::Mem src_ptr = getArgRef(Hd, 16);
x86::Mem dst_ptr = x86::xmmword_ptr(HTOP, 0);
@@ -703,25 +684,26 @@ void BeamModuleAssembler::emit_put_cons(const ArgVal &Hd, const ArgVal &Tl) {
a.lea(ARG2, x86::qword_ptr(HTOP, TAG_PRIMARY_LIST));
}
-void BeamModuleAssembler::emit_append_cons(const ArgVal &index,
- const ArgVal &Hd) {
- size_t offset = 2 * index.getValue() * sizeof(Eterm);
+void BeamModuleAssembler::emit_append_cons(const ArgWord &Index,
+ const ArgSource &Hd) {
+ size_t offset = Index.get() * sizeof(Eterm[2]);
mov_arg(x86::qword_ptr(HTOP, offset), Hd);
a.mov(x86::qword_ptr(HTOP, offset + sizeof(Eterm)), ARG2);
a.lea(ARG2, x86::qword_ptr(HTOP, offset + TAG_PRIMARY_LIST));
}
-void BeamModuleAssembler::emit_store_cons(const ArgVal &len,
- const ArgVal &Dst) {
- a.add(HTOP, imm(len.getValue() * 2 * sizeof(Eterm)));
+void BeamModuleAssembler::emit_store_cons(const ArgWord &Len,
+ const ArgRegister &Dst) {
+ a.add(HTOP, imm(Len.get() * sizeof(Eterm[2])));
mov_arg(Dst, ARG2);
}
-void BeamModuleAssembler::emit_put_tuple2(const ArgVal &Dst,
- const ArgVal &Arity,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_put_tuple2(const ArgRegister &Dst,
+ const ArgWord &Arity,
+ const Span<ArgVal> &args) {
size_t size = args.size();
- ASSERT(arityval(Arity.getValue()) == size);
+
+ ASSERT(arityval(Arity.get()) == size);
comment("Move arity word");
mov_arg(x86::qword_ptr(HTOP, 0), Arity);
@@ -733,7 +715,7 @@ void BeamModuleAssembler::emit_put_tuple2(const ArgVal &Dst,
if (i + 1 == size) {
mov_arg(dst_ptr, args[i]);
} else {
- switch (ArgVal::register_relation(args[i], args[i + 1])) {
+ switch (ArgVal::memory_relation(args[i], args[i + 1])) {
case ArgVal::consecutive: {
x86::Mem src_ptr = getArgRef(args[i], 16);
@@ -772,43 +754,51 @@ void BeamModuleAssembler::emit_put_tuple2(const ArgVal &Dst,
mov_arg(Dst, ARG1);
}
-void BeamModuleAssembler::emit_self(const ArgVal &Dst) {
+void BeamModuleAssembler::emit_self(const ArgRegister &Dst) {
a.mov(ARG1, x86::qword_ptr(c_p, offsetof(Process, common.id)));
mov_arg(Dst, ARG1);
}
-void BeamModuleAssembler::emit_set_tuple_element(const ArgVal &Element,
- const ArgVal &Tuple,
- const ArgVal &Offset) {
+void BeamModuleAssembler::emit_set_tuple_element(const ArgSource &Element,
+ const ArgRegister &Tuple,
+ const ArgWord &Offset) {
mov_arg(ARG1, Tuple);
x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- mov_arg(emit_boxed_val(boxed_ptr, Offset.getValue()), Element, ARG2);
+ mov_arg(emit_boxed_val(boxed_ptr, Offset.get()), Element, ARG2);
}
-void BeamModuleAssembler::emit_is_nonempty_list(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_nonempty_list(const ArgLabel &Fail,
+ const ArgRegister &Src) {
x86::Mem list_ptr = getArgRef(Src, 1);
a.test(list_ptr, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_jump(const ArgVal &Fail) {
- a.jmp(labels[Fail.getValue()]);
+void BeamModuleAssembler::emit_jump(const ArgLabel &Fail) {
+ a.jmp(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_is_atom(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_atom(const ArgLabel &Fail,
+ const ArgSource &Src) {
mov_arg(RET, Src);
- ERTS_CT_ASSERT(_TAG_IMMED2_MASK < 256);
- a.and_(RETb, imm(_TAG_IMMED2_MASK));
- a.cmp(RETb, imm(_TAG_IMMED2_ATOM));
- a.jne(labels[Fail.getValue()]);
+
+ if (always_one_of(Src, BEAM_TYPE_ATOM | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified atom test since all other types are boxed");
+ a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED));
+ a.je(resolve_beam_label(Fail));
+ } else {
+ ERTS_CT_ASSERT(_TAG_IMMED2_MASK < 256);
+ a.and_(RETb, imm(_TAG_IMMED2_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED2_ATOM));
+ a.jne(resolve_beam_label(Fail));
+ }
}
-void BeamModuleAssembler::emit_is_boolean(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_boolean(const ArgLabel &Fail,
+ const ArgSource &Src) {
/* Since am_true and am_false differ by a single bit, we can simplify the
* check by clearing said bit and comparing against the lesser one. */
ERTS_CT_ASSERT(am_false == make_atom(0));
@@ -818,97 +808,104 @@ void BeamModuleAssembler::emit_is_boolean(const ArgVal &Fail,
a.and_(ARG1, imm(~(am_true & ~_TAG_IMMED1_MASK)));
a.cmp(ARG1, imm(am_false));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_is_binary(Label fail,
- x86::Gp src,
- Label next,
- Label subbin) {
- ASSERT(src != RET && src != ARG2);
+x86::Gp BeamModuleAssembler::emit_is_binary(const ArgLabel &Fail,
+ const ArgSource &Src,
+ Label next,
+ Label subbin) {
+ mov_arg(ARG1, Src);
- emit_is_boxed(fail, src);
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG1);
- x86::Gp boxed_ptr = emit_ptr_val(src, src);
+ x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
-
a.and_(RETb, imm(_TAG_HEADER_MASK));
a.cmp(RETb, imm(_TAG_HEADER_SUB_BIN));
a.short_().je(subbin);
- ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
- a.and_(RETb, imm(~4));
- a.cmp(RETb, imm(_TAG_HEADER_REFC_BIN));
- a.short_().je(next);
- a.jmp(fail);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_BITSTRING) {
+ comment("simplified binary test since source is always a bitstring "
+ "when boxed");
+ } else {
+ ERTS_CT_ASSERT(_TAG_HEADER_REFC_BIN + 4 == _TAG_HEADER_HEAP_BIN);
+ a.and_(RETb, imm(~4));
+ a.cmp(RETb, imm(_TAG_HEADER_REFC_BIN));
+ a.jne(resolve_beam_label(Fail));
+ }
+
+ a.short_().jmp(next);
+
+ return boxed_ptr;
}
-void BeamModuleAssembler::emit_is_binary(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_binary(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label next = a.newLabel(), subbin = a.newLabel();
+ x86::Gp boxed_ptr;
- mov_arg(ARG1, Src);
-
- emit_is_binary(labels[Fail.getValue()], ARG1, next, subbin);
+ boxed_ptr = emit_is_binary(Fail, Src, next, subbin);
a.bind(subbin);
{
/* emit_is_binary has already removed the literal tag from Src, if
* applicable. */
- a.cmp(emit_boxed_val(ARG1, offsetof(ErlSubBin, bitsize), sizeof(byte)),
+ a.cmp(emit_boxed_val(boxed_ptr,
+ offsetof(ErlSubBin, bitsize),
+ sizeof(byte)),
imm(0));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
a.bind(next);
}
-void BeamModuleAssembler::emit_is_bitstring(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_bitstring(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label next = a.newLabel();
- mov_arg(ARG1, Src);
-
- emit_is_binary(labels[Fail.getValue()], ARG1, next, next);
+ emit_is_binary(Fail, Src, next, next);
a.bind(next);
}
-void BeamModuleAssembler::emit_is_float(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_float(const ArgLabel &Fail,
+ const ArgSource &Src) {
mov_arg(ARG1, Src);
- emit_is_boxed(labels[Fail.getValue()], ARG1);
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG1);
- x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.cmp(emit_boxed_val(boxed_ptr), imm(HEADER_FLONUM));
- a.jne(labels[Fail.getValue()]);
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FLOAT) {
+ comment("skipped header test since we know it's a float when boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+ a.cmp(emit_boxed_val(boxed_ptr), imm(HEADER_FLONUM));
+ a.jne(resolve_beam_label(Fail));
+ }
}
-void BeamModuleAssembler::emit_is_function(const ArgVal &Fail,
- const ArgVal &Src) {
- Label next = a.newLabel();
-
+void BeamModuleAssembler::emit_is_function(const ArgLabel &Fail,
+ const ArgRegister &Src) {
mov_arg(RET, Src);
- emit_is_boxed(labels[Fail.getValue()], RET);
-
- x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.cmp(RET, imm(HEADER_FUN));
- a.short_().je(next);
- ERTS_CT_ASSERT(HEADER_EXPORT < 256);
- a.cmp(RETb, imm(HEADER_EXPORT));
- a.jne(labels[Fail.getValue()]);
+ emit_is_boxed(resolve_beam_label(Fail), Src, RET);
- a.bind(next);
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN) {
+ comment("skipped header test since we know it's a fun when boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.cmp(RET, imm(HEADER_FUN));
+ a.jne(resolve_beam_label(Fail));
+ }
}
-void BeamModuleAssembler::emit_is_function2(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Arity) {
- if (Arity.getType() != ArgVal::i) {
- /*
- * Non-literal arity - extremely uncommon. Generate simple code.
- */
+void BeamModuleAssembler::emit_is_function2(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgSource &Arity) {
+ if (!Arity.isSmall()) {
+ /* Non-small arity - extremely uncommon. Generate simple code. */
mov_arg(ARG2, Src);
mov_arg(ARG3, Arity);
@@ -920,73 +917,81 @@ void BeamModuleAssembler::emit_is_function2(const ArgVal &Fail,
emit_leave_runtime();
a.cmp(RET, imm(am_true));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
return;
}
- unsigned arity = unsigned_val(Arity.getValue());
+ unsigned arity = Arity.as<ArgSmall>().getUnsigned();
if (arity > MAX_ARG) {
/* Arity is negative or too large. */
- a.jmp(labels[Fail.getValue()]);
+ a.jmp(resolve_beam_label(Fail));
return;
}
- Label next = a.newLabel(), fun = a.newLabel();
-
mov_arg(ARG1, Src);
- emit_is_boxed(labels[Fail.getValue()], ARG1);
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG1);
x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.cmp(RETd, imm(HEADER_FUN));
- a.short_().je(fun);
- ERTS_CT_ASSERT(HEADER_EXPORT < 256);
- a.cmp(RETb, imm(HEADER_EXPORT));
- a.jne(labels[Fail.getValue()]);
-
- comment("Check arity of export fun");
- a.mov(ARG2, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
- a.cmp(x86::qword_ptr(ARG2, offsetof(Export, info.mfa.arity)), imm(arity));
- a.jne(labels[Fail.getValue()]);
- a.short_().jmp(next);
- comment("Check arity of fun");
- a.bind(fun);
- {
- a.cmp(emit_boxed_val(boxed_ptr, offsetof(ErlFunThing, arity)),
- imm(arity));
- a.jne(labels[Fail.getValue()]);
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN) {
+ comment("skipped header test since we know it's a fun when boxed");
+ } else {
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.cmp(RETd, imm(HEADER_FUN));
+ a.jne(resolve_beam_label(Fail));
}
- a.bind(next);
+ a.cmp(emit_boxed_val(boxed_ptr, offsetof(ErlFunThing, arity), sizeof(byte)),
+ imm(arity));
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_is_integer(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_integer(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ if (always_immediate(Src)) {
+ comment("skipped test for boxed since the value is always immediate");
+ mov_arg(RET, Src);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.jne(resolve_beam_label(Fail));
+
+ return;
+ }
+
Label next = a.newLabel();
- Label fail = labels[Fail.getValue()];
mov_arg(ARG1, Src);
- a.mov(RETd, ARG1d);
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- a.short_().je(next);
+ if (always_one_of(Src, BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified small test since all other types are boxed");
+ emit_is_boxed(next, Src, ARG1);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.short_().je(next);
- emit_is_boxed(fail, RET);
+ emit_is_boxed(resolve_beam_label(Fail), Src, RET);
+ }
- x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_INTEGER) {
+ comment("skipped header test since we know it's a bignum when "
+ "boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.and_(RETb, imm(_TAG_HEADER_MASK - _BIG_SIGN_BIT));
- a.cmp(RETb, imm(_TAG_HEADER_POS_BIG));
- a.jne(fail);
+ a.and_(RETb, imm(_TAG_HEADER_MASK - _BIG_SIGN_BIT));
+ a.cmp(RETb, imm(_TAG_HEADER_POS_BIG));
+ a.jne(resolve_beam_label(Fail));
+ }
a.bind(next);
}
-void BeamModuleAssembler::emit_is_list(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_list(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label next = a.newLabel();
mov_arg(RET, Src);
@@ -994,213 +999,267 @@ void BeamModuleAssembler::emit_is_list(const ArgVal &Fail, const ArgVal &Src) {
a.cmp(RET, imm(NIL));
a.short_().je(next);
a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
a.bind(next);
}
-void BeamModuleAssembler::emit_is_map(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_map(const ArgLabel &Fail,
+ const ArgSource &Src) {
mov_arg(RET, Src);
- emit_is_boxed(labels[Fail.getValue()], RET);
+ emit_is_boxed(resolve_beam_label(Fail), Src, RET);
- x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.and_(RETb, imm(_TAG_HEADER_MASK));
- a.cmp(RETb, imm(_TAG_HEADER_MAP));
- a.jne(labels[Fail.getValue()]);
+ /* As an optimization for the `error | #{}` case, skip checking the header
+ * word when we know that the only possible boxed type is a map. */
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_MAP) {
+ comment("skipped header test since we know it's a map when boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.and_(RETb, imm(_TAG_HEADER_MASK));
+ a.cmp(RETb, imm(_TAG_HEADER_MAP));
+ a.jne(resolve_beam_label(Fail));
+ }
}
-void BeamModuleAssembler::emit_is_nil(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_nil(const ArgLabel &Fail,
+ const ArgRegister &Src) {
a.cmp(getArgRef(Src), imm(NIL));
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_is_number(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_number(const ArgLabel &Fail,
+ const ArgSource &Src) {
+ Label fail = resolve_beam_label(Fail);
Label next = a.newLabel();
- Label fail = labels[Fail.getValue()];
mov_arg(ARG1, Src);
- a.mov(RETd, ARG1d);
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- a.short_().je(next);
+ if (always_one_of(Src, BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified small test test since all other types are boxed");
+ emit_is_boxed(next, Src, ARG1);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.short_().je(next);
- emit_is_boxed(fail, RET);
+ /* Reuse RET as the important bits are still available. */
+ emit_is_boxed(fail, Src, RET);
+ }
- x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.mov(ARG1, emit_boxed_val(boxed_ptr));
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) ==
+ (BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("skipped header test since we know it's a number when boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+ a.mov(ARG1, emit_boxed_val(boxed_ptr));
- a.mov(RETd, ARG1d);
- a.and_(RETb, imm(_TAG_HEADER_MASK - _BIG_SIGN_BIT));
- a.cmp(RETb, imm(_TAG_HEADER_POS_BIG));
- a.short_().je(next);
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_HEADER_MASK - _BIG_SIGN_BIT));
+ a.cmp(RETb, imm(_TAG_HEADER_POS_BIG));
+ a.short_().je(next);
- a.cmp(ARG1d, imm(HEADER_FLONUM));
- a.jne(fail);
+ a.cmp(ARG1d, imm(HEADER_FLONUM));
+ a.jne(fail);
+ }
a.bind(next);
}
-void BeamModuleAssembler::emit_is_pid(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_pid(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label next = a.newLabel();
mov_arg(ARG1, Src);
- a.mov(RETd, ARG1d);
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_PID));
- a.short_().je(next);
+ if (always_one_of(Src, BEAM_TYPE_PID | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified local pid test since all other types are boxed");
+ emit_is_boxed(next, Src, ARG1);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_PID));
+ a.short_().je(next);
- /* Reuse RET as the important bits are still available. */
- emit_is_boxed(labels[Fail.getValue()], RET);
+ /* Reuse RET as the important bits are still available. */
+ emit_is_boxed(resolve_beam_label(Fail), Src, RET);
+ }
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_PID) {
+ comment("skipped header test since we know it's a pid when boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.and_(RETb, imm(_TAG_HEADER_MASK));
+ a.cmp(RETb, imm(_TAG_HEADER_EXTERNAL_PID));
+ a.jne(resolve_beam_label(Fail));
+ }
- x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.and_(RETb, _TAG_HEADER_MASK);
- a.cmp(RETb, _TAG_HEADER_EXTERNAL_PID);
- a.jne(labels[Fail.getValue()]);
a.bind(next);
}
-void BeamModuleAssembler::emit_is_port(const ArgVal &Fail, const ArgVal &Src) {
+void BeamModuleAssembler::emit_is_port(const ArgLabel &Fail,
+ const ArgSource &Src) {
Label next = a.newLabel();
+
mov_arg(ARG1, Src);
- a.mov(RETd, ARG1d);
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_PORT));
- a.short_().je(next);
+ if (always_one_of(Src, BEAM_TYPE_PORT | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ comment("simplified local port test since all other types are boxed");
+ emit_is_boxed(next, Src, ARG1);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_PORT));
+ a.short_().je(next);
- /* Reuse RET as the important bits are still available. */
- emit_is_boxed(labels[Fail.getValue()], RET);
+ /* Reuse RET as the important bits are still available. */
+ emit_is_boxed(resolve_beam_label(Fail), Src, RET);
+ }
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_PORT) {
+ comment("skipped header test since we know it's a port when boxed");
+ } else {
+ x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.and_(RETb, imm(_TAG_HEADER_MASK));
+ a.cmp(RETb, imm(_TAG_HEADER_EXTERNAL_PORT));
+ a.jne(resolve_beam_label(Fail));
+ }
- x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.and_(RETb, imm(_TAG_HEADER_MASK));
- a.cmp(RETb, imm(_TAG_HEADER_EXTERNAL_PORT));
- a.jne(labels[Fail.getValue()]);
a.bind(next);
}
-void BeamModuleAssembler::emit_is_reference(const ArgVal &Fail,
- const ArgVal &Src) {
- Label next = a.newLabel();
-
+void BeamModuleAssembler::emit_is_reference(const ArgLabel &Fail,
+ const ArgSource &Src) {
mov_arg(RET, Src);
- emit_is_boxed(labels[Fail.getValue()], RET);
+ emit_is_boxed(resolve_beam_label(Fail), Src, RET);
- x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- a.and_(RETb, imm(_TAG_HEADER_MASK));
- a.cmp(RETb, imm(_TAG_HEADER_REF));
- a.short_().je(next);
- a.cmp(RETb, imm(_TAG_HEADER_EXTERNAL_REF));
- a.jne(labels[Fail.getValue()]);
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_REFERENCE) {
+ comment("skipped header test since we know it's a ref when boxed");
+ } else {
+ Label next = a.newLabel();
- a.bind(next);
+ x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.and_(RETb, imm(_TAG_HEADER_MASK));
+ a.cmp(RETb, imm(_TAG_HEADER_REF));
+ a.short_().je(next);
+ a.cmp(RETb, imm(_TAG_HEADER_EXTERNAL_REF));
+ a.jne(resolve_beam_label(Fail));
+
+ a.bind(next);
+ }
}
/* Note: This instruction leaves the pointer to the tuple in ARG2. */
-void BeamModuleAssembler::emit_i_is_tagged_tuple(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Arity,
- const ArgVal &Tag) {
+void BeamModuleAssembler::emit_i_is_tagged_tuple(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Arity,
+ const ArgAtom &Tag) {
mov_arg(ARG2, Src);
- emit_is_boxed(labels[Fail.getValue()], ARG2);
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG2);
x86::Gp boxed_ptr = emit_ptr_val(ARG2, ARG2);
ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
- a.cmp(emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)), imm(Arity.getValue()));
- a.jne(labels[Fail.getValue()]);
+ a.cmp(emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)), imm(Arity.get()));
+ a.jne(resolve_beam_label(Fail));
- a.cmp(emit_boxed_val(boxed_ptr, sizeof(Eterm)), imm(Tag.getValue()));
- a.jne(labels[Fail.getValue()]);
+ a.cmp(emit_boxed_val(boxed_ptr, sizeof(Eterm)), imm(Tag.get()));
+ a.jne(resolve_beam_label(Fail));
}
/* Note: This instruction leaves the pointer to the tuple in ARG2. */
-void BeamModuleAssembler::emit_i_is_tagged_tuple_ff(const ArgVal &NotTuple,
- const ArgVal &NotRecord,
- const ArgVal &Src,
- const ArgVal &Arity,
- const ArgVal &Tag) {
+void BeamModuleAssembler::emit_i_is_tagged_tuple_ff(const ArgLabel &NotTuple,
+ const ArgLabel &NotRecord,
+ const ArgSource &Src,
+ const ArgWord &Arity,
+ const ArgAtom &Tag) {
mov_arg(ARG2, Src);
- emit_is_boxed(labels[NotTuple.getValue()], ARG2);
+
+ emit_is_boxed(resolve_beam_label(NotTuple), Src, ARG2);
+
(void)emit_ptr_val(ARG2, ARG2);
a.mov(ARG1, emit_boxed_val(ARG2));
ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
a.test(ARG1.r8(), imm(_TAG_HEADER_MASK));
- a.jne(labels[NotTuple.getValue()]);
+ a.jne(resolve_beam_label(NotTuple));
ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
- a.cmp(ARG1d, imm(Arity.getValue()));
- a.jne(labels[NotRecord.getValue()]);
+ a.cmp(ARG1d, imm(Arity.get()));
+ a.jne(resolve_beam_label(NotRecord));
- a.cmp(emit_boxed_val(ARG2, sizeof(Eterm)), imm(Tag.getValue()));
- a.jne(labels[NotRecord.getValue()]);
+ a.cmp(emit_boxed_val(ARG2, sizeof(Eterm)), imm(Tag.get()));
+ a.jne(resolve_beam_label(NotRecord));
}
/* Note: This instruction leaves the pointer to the tuple in ARG2. */
-void BeamModuleAssembler::emit_i_is_tuple(const ArgVal &Fail,
- const ArgVal &Src) {
+void BeamModuleAssembler::emit_i_is_tuple(const ArgLabel &Fail,
+ const ArgSource &Src) {
mov_arg(ARG2, Src);
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_TUPLE) {
+ /* Fast path for the `error | {ok, Value}` case. */
+ comment("simplified tuple test since the source is always a tuple "
+ "when boxed");
+ /* We must be careful to still leave the pointer to the tuple
+ * in ARG2. */
+ (void)emit_ptr_val(ARG2, ARG2);
+ a.test(ARG2.r8(), imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED));
+ } else {
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG2);
- emit_is_boxed(labels[Fail.getValue()], ARG2);
-
- (void)emit_ptr_val(ARG2, ARG2);
- ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
- a.test(emit_boxed_val(ARG2, 0, sizeof(byte)), imm(_TAG_HEADER_MASK));
+ (void)emit_ptr_val(ARG2, ARG2);
+ ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
+ a.test(emit_boxed_val(ARG2, 0, sizeof(byte)), imm(_TAG_HEADER_MASK));
+ }
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
/* Note: This instruction leaves the pointer to the tuple in ARG2. */
-void BeamModuleAssembler::emit_i_is_tuple_of_arity(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Arity) {
+void BeamModuleAssembler::emit_i_is_tuple_of_arity(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Arity) {
mov_arg(ARG2, Src);
- emit_is_boxed(labels[Fail.getValue()], ARG2);
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG2);
(void)emit_ptr_val(ARG2, ARG2);
ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
- a.cmp(emit_boxed_val(ARG2, 0, sizeof(Uint32)), imm(Arity.getValue()));
- a.jne(labels[Fail.getValue()]);
+ a.cmp(emit_boxed_val(ARG2, 0, sizeof(Uint32)), imm(Arity.get()));
+ a.jne(resolve_beam_label(Fail));
}
/* Note: This instruction leaves the pointer to the tuple in ARG2. */
-void BeamModuleAssembler::emit_i_test_arity(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Arity) {
+void BeamModuleAssembler::emit_i_test_arity(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Arity) {
mov_arg(ARG2, Src);
(void)emit_ptr_val(ARG2, ARG2);
ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
- a.cmp(emit_boxed_val(ARG2, 0, sizeof(Uint32)), imm(Arity.getValue()));
- a.jne(labels[Fail.getValue()]);
+ a.cmp(emit_boxed_val(ARG2, 0, sizeof(Uint32)), imm(Arity.get()));
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_i_is_eq_exact_immed(const ArgVal &Fail,
- const ArgVal &X,
- const ArgVal &Y) {
- cmp_arg(getArgRef(X), Y);
- a.jne(labels[Fail.getValue()]);
-}
+void BeamModuleAssembler::emit_is_eq_exact(const ArgLabel &Fail,
+ const ArgSource &X,
+ const ArgSource &Y) {
+ /* If one argument is known to be an immediate, we can fail
+ * immediately if they're not equal. */
+ if (X.isRegister() && always_immediate(Y)) {
+ comment("simplified check since one argument is an immediate");
-void BeamModuleAssembler::emit_i_is_ne_exact_immed(const ArgVal &Fail,
- const ArgVal &X,
- const ArgVal &Y) {
- cmp_arg(getArgRef(X), Y);
- a.je(labels[Fail.getValue()]);
-}
+ cmp_arg(getArgRef(X), Y);
+ a.jne(resolve_beam_label(Fail));
+
+ return;
+ }
-void BeamModuleAssembler::emit_is_eq_exact(const ArgVal &Fail,
- const ArgVal &X,
- const ArgVal &Y) {
Label next = a.newLabel();
mov_arg(ARG2, Y); /* May clobber ARG1 */
@@ -1213,12 +1272,14 @@ void BeamModuleAssembler::emit_is_eq_exact(const ArgVal &Fail,
a.short_().je(next);
#endif
- /* Fancy way of checking if both are immediates. */
- a.mov(RETd, ARG1d);
- a.and_(RETd, ARG2d);
- a.and_(RETb, imm(_TAG_PRIMARY_MASK));
- a.cmp(RETb, imm(TAG_PRIMARY_IMMED1));
- a.je(labels[Fail.getValue()]);
+ if (always_same_types(X, Y)) {
+ comment("skipped test of tags since they are always equal");
+ } else {
+ /* The terms could still be equal if both operands are pointers
+ * having the same tag. */
+ emit_is_unequal_based_on_tags(ARG1, ARG2);
+ a.je(resolve_beam_label(Fail));
+ }
emit_enter_runtime();
@@ -1226,23 +1287,23 @@ void BeamModuleAssembler::emit_is_eq_exact(const ArgVal &Fail,
emit_leave_runtime();
- a.test(RET, RET);
- a.je(labels[Fail.getValue()]);
+ a.test(RETd, RETd);
+ a.je(resolve_beam_label(Fail));
a.bind(next);
}
-void BeamModuleAssembler::emit_i_is_eq_exact_literal(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Literal,
- const ArgVal &tag_test) {
+void BeamModuleAssembler::emit_i_is_eq_exact_literal(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgConstant &Literal,
+ const ArgWord &tag_test) {
mov_arg(ARG2, Literal); /* May clobber ARG1 */
mov_arg(ARG1, Src);
/* Fail immediately unless Src is the same type of pointer as the literal.
*/
- a.test(ARG1.r8(), imm(tag_test.getValue()));
- a.jne(labels[Fail.getValue()]);
+ a.test(ARG1.r8(), imm(tag_test.get()));
+ a.jne(resolve_beam_label(Fail));
emit_enter_runtime();
@@ -1250,31 +1311,45 @@ void BeamModuleAssembler::emit_i_is_eq_exact_literal(const ArgVal &Fail,
emit_leave_runtime();
- a.test(RET, RET);
- a.jz(labels[Fail.getValue()]);
+ a.test(RETd, RETd);
+ a.jz(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_is_ne_exact(const ArgVal &Fail,
- const ArgVal &X,
- const ArgVal &Y) {
+void BeamModuleAssembler::emit_is_ne_exact(const ArgLabel &Fail,
+ const ArgSource &X,
+ const ArgSource &Y) {
+ /* If one argument is known to be an immediate, we can fail
+ * immediately if they're equal. */
+ if (X.isRegister() && always_immediate(Y)) {
+ comment("simplified check since one argument is an immediate");
+
+ cmp_arg(getArgRef(X), Y);
+ a.je(resolve_beam_label(Fail));
+
+ return;
+ }
+
Label next = a.newLabel();
mov_arg(ARG2, Y); /* May clobber ARG1 */
mov_arg(ARG1, X);
a.cmp(ARG1, ARG2);
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
+
+ if (always_same_types(X, Y)) {
+ comment("skipped tag test since they are always equal");
+ } else {
+ /* Test whether the terms are definitely unequal based on the tags
+ * alone. */
+ emit_is_unequal_based_on_tags(ARG1, ARG2);
- /* Fancy way of checking if both are immediates. */
- a.mov(RETd, ARG1d);
- a.and_(RETd, ARG2d);
- a.and_(RETb, imm(_TAG_PRIMARY_MASK));
- a.cmp(RETb, imm(TAG_PRIMARY_IMMED1));
#ifdef JIT_HARD_DEBUG
- a.je(next);
+ a.je(next);
#else
- a.short_().je(next);
+ a.short_().je(next);
#endif
+ }
emit_enter_runtime();
@@ -1282,15 +1357,16 @@ void BeamModuleAssembler::emit_is_ne_exact(const ArgVal &Fail,
emit_leave_runtime();
- a.test(RET, RET);
- a.jnz(labels[Fail.getValue()]);
+ a.test(RETd, RETd);
+ a.jnz(resolve_beam_label(Fail));
a.bind(next);
}
-void BeamModuleAssembler::emit_i_is_ne_exact_literal(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Literal) {
+void BeamModuleAssembler::emit_i_is_ne_exact_literal(
+ const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgConstant &Literal) {
Label next = a.newLabel();
mov_arg(ARG2, Literal); /* May clobber ARG1 */
@@ -1307,8 +1383,8 @@ void BeamModuleAssembler::emit_i_is_ne_exact_literal(const ArgVal &Fail,
emit_leave_runtime();
- a.test(RET, RET);
- a.jnz(labels[Fail.getValue()]);
+ a.test(RETd, RETd);
+ a.jnz(resolve_beam_label(Fail));
a.bind(next);
}
@@ -1362,10 +1438,10 @@ void BeamGlobalAssembler::emit_arith_eq_shared() {
}
}
-void BeamModuleAssembler::emit_is_eq(const ArgVal &Fail,
- const ArgVal &A,
- const ArgVal &B) {
- Label fail = labels[Fail.getValue()], next = a.newLabel();
+void BeamModuleAssembler::emit_is_eq(const ArgLabel &Fail,
+ const ArgSource &A,
+ const ArgSource &B) {
+ Label fail = resolve_beam_label(Fail), next = a.newLabel();
mov_arg(ARG2, B); /* May clobber ARG1 */
mov_arg(ARG1, A);
@@ -1385,10 +1461,10 @@ void BeamModuleAssembler::emit_is_eq(const ArgVal &Fail,
a.bind(next);
}
-void BeamModuleAssembler::emit_is_ne(const ArgVal &Fail,
- const ArgVal &A,
- const ArgVal &B) {
- Label fail = labels[Fail.getValue()], next = a.newLabel();
+void BeamModuleAssembler::emit_is_ne(const ArgLabel &Fail,
+ const ArgSource &A,
+ const ArgSource &B) {
+ Label fail = resolve_beam_label(Fail), next = a.newLabel();
mov_arg(ARG2, B); /* May clobber ARG1 */
mov_arg(ARG1, A);
@@ -1414,6 +1490,8 @@ void BeamGlobalAssembler::emit_arith_compare_shared() {
atom_compare = a.newLabel();
generic_compare = a.newLabel();
+ emit_enter_frame();
+
/* Are both floats?
*
* This is done first as relative comparisons on atoms doesn't make much
@@ -1447,6 +1525,7 @@ void BeamGlobalAssembler::emit_arith_compare_shared() {
a.setae(x86::al);
a.dec(x86::al);
+ emit_leave_frame();
a.ret();
a.bind(atom_compare);
@@ -1470,6 +1549,7 @@ void BeamGlobalAssembler::emit_arith_compare_shared() {
/* !! erts_cmp_atoms returns int, not Sint !! */
a.test(RETd, RETd);
+ emit_leave_frame();
a.ret();
}
@@ -1486,122 +1566,184 @@ void BeamGlobalAssembler::emit_arith_compare_shared() {
a.test(RET, RET);
+ emit_leave_frame();
a.ret();
}
}
-void BeamModuleAssembler::emit_is_lt(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS) {
- Label fail = labels[Fail.getValue()];
+void BeamModuleAssembler::emit_is_lt(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS) {
Label generic = a.newLabel(), next = a.newLabel();
+ bool both_small = always_small(LHS) && always_small(RHS);
mov_arg(ARG2, RHS); /* May clobber ARG1 */
mov_arg(ARG1, LHS);
- a.cmp(ARG1, ARG2);
- a.je(fail);
-
- /* Relative comparisons are overwhelmingly likely to be used on smalls, so
- * we'll specialize those and keep the rest in a shared fragment. */
-
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- a.mov(RETd, ARG1d);
- } else if (LHS.isImmed() && is_small(LHS.getValue())) {
- a.mov(RETd, ARG2d);
- } else {
+ if (both_small) {
+ comment("skipped test for small operands since they are always small");
+ } else if (always_one_of(LHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED) &&
+ always_one_of(RHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ /* The only possible kind of immediate is a small and all other
+ * values are boxed, so we can test for smalls by testing boxed. */
+ comment("simplified small test since all other types are boxed");
a.mov(RETd, ARG1d);
a.and_(RETd, ARG2d);
- }
+ a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED));
+ a.short_().je(generic);
+ } else {
+ /* Relative comparisons are overwhelmingly likely to be used on
+ * smalls, so we'll specialize those and keep the rest in a shared
+ * fragment. */
+ if (RHS.isSmall()) {
+ a.mov(RETd, ARG1d);
+ } else if (LHS.isSmall()) {
+ a.mov(RETd, ARG2d);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETd, ARG2d);
+ }
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(generic);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.short_().jne(generic);
+ }
+ /* Both arguments are smalls. */
a.cmp(ARG1, ARG2);
- a.short_().jl(next);
- a.jmp(fail);
+ if (!both_small) {
+ a.short_().jmp(next);
+ }
a.bind(generic);
{
- safe_fragment_call(ga->get_arith_compare_shared());
- a.jge(fail);
+ if (!both_small) {
+ safe_fragment_call(ga->get_arith_compare_shared());
+ }
}
a.bind(next);
+ a.jge(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_is_ge(const ArgVal &Fail,
- const ArgVal &LHS,
- const ArgVal &RHS) {
- Label fail = labels[Fail.getValue()];
+void BeamModuleAssembler::emit_is_ge(const ArgLabel &Fail,
+ const ArgSource &LHS,
+ const ArgSource &RHS) {
Label generic = a.newLabel(), next = a.newLabel();
+ bool both_small = always_small(LHS) && always_small(RHS);
mov_arg(ARG2, RHS); /* May clobber ARG1 */
mov_arg(ARG1, LHS);
- a.cmp(ARG1, ARG2);
- a.short_().je(next);
-
- /* Relative comparisons are overwhelmingly likely to be used on smalls, so
- * we'll specialize those and keep the rest in a shared fragment. */
-
- if (RHS.isImmed() && is_small(RHS.getValue())) {
- a.mov(RETd, ARG1d);
- } else if (LHS.isImmed() && is_small(LHS.getValue())) {
- a.mov(RETd, ARG2d);
- } else {
+ if (both_small) {
+ comment("skipped test for small operands since they are always small");
+ } else if (always_one_of(LHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED) &&
+ always_one_of(RHS,
+ BEAM_TYPE_INTEGER | BEAM_TYPE_MASK_ALWAYS_BOXED)) {
+ /* The only possible kind of immediate is a small and all other
+ * values are boxed, so we can test for smalls by testing boxed. */
+ comment("simplified small test since all other types are boxed");
a.mov(RETd, ARG1d);
a.and_(RETd, ARG2d);
- }
+ a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED));
+ a.short_().je(generic);
+ } else {
+ /* Relative comparisons are overwhelmingly likely to be used on
+ * smalls, so we'll specialize those and keep the rest in a shared
+ * fragment. */
+ if (RHS.isSmall()) {
+ a.mov(RETd, ARG1d);
+ } else if (LHS.isSmall()) {
+ a.mov(RETd, ARG2d);
+ } else {
+ a.mov(RETd, ARG1d);
+ a.and_(RETd, ARG2d);
+ }
- a.and_(RETb, imm(_TAG_IMMED1_MASK));
- a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- a.short_().jne(generic);
+ a.and_(RETb, imm(_TAG_IMMED1_MASK));
+ a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
+ a.short_().jne(generic);
+ }
+ /* Both arguments are smalls. */
a.cmp(ARG1, ARG2);
- a.short_().jge(next);
- a.jmp(fail);
+ if (!both_small) {
+ a.short_().jmp(next);
+ }
a.bind(generic);
{
- safe_fragment_call(ga->get_arith_compare_shared());
- a.jl(fail);
+ if (!both_small) {
+ safe_fragment_call(ga->get_arith_compare_shared());
+ }
}
a.bind(next);
+ a.jl(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_bif_is_eq_ne_exact_immed(const ArgVal &Src,
- const ArgVal &Immed,
- const ArgVal &Dst,
- Eterm fail_value,
- Eterm succ_value) {
- cmp_arg(getArgRef(Src), Immed);
- mov_imm(RET, fail_value);
- mov_imm(ARG1, succ_value);
- a.cmove(RET, ARG1);
+void BeamModuleAssembler::emit_bif_is_eq_ne_exact(const ArgSource &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst,
+ Eterm fail_value,
+ Eterm succ_value) {
+ /* `mov_imm` may clobber the flags if either value is zero. */
+ ASSERT(fail_value && succ_value);
+
+ mov_imm(RET, succ_value);
+ cmp_arg(getArgRef(LHS), RHS);
+
+ if (always_immediate(LHS) || always_immediate(RHS)) {
+ if (!LHS.isImmed() && !RHS.isImmed()) {
+ comment("simplified check since one argument is an immediate");
+ }
+ mov_imm(ARG1, fail_value);
+ a.cmovne(RET, ARG1);
+ } else {
+ Label next = a.newLabel();
+
+ a.je(next);
+
+ mov_arg(ARG1, LHS);
+ mov_arg(ARG2, RHS);
+
+ emit_enter_runtime();
+ runtime_call<2>(eq);
+ emit_leave_runtime();
+
+ a.test(RET, RET);
+
+ mov_imm(RET, succ_value);
+ mov_imm(ARG1, fail_value);
+ a.cmove(RET, ARG1);
+
+ a.bind(next);
+ }
+
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_bif_is_eq_exact_immed(const ArgVal &Src,
- const ArgVal &Immed,
- const ArgVal &Dst) {
- emit_bif_is_eq_ne_exact_immed(Src, Immed, Dst, am_false, am_true);
+void BeamModuleAssembler::emit_bif_is_eq_exact(const ArgRegister &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ emit_bif_is_eq_ne_exact(LHS, RHS, Dst, am_false, am_true);
}
-void BeamModuleAssembler::emit_bif_is_ne_exact_immed(const ArgVal &Src,
- const ArgVal &Immed,
- const ArgVal &Dst) {
- emit_bif_is_eq_ne_exact_immed(Src, Immed, Dst, am_true, am_false);
+void BeamModuleAssembler::emit_bif_is_ne_exact(const ArgRegister &LHS,
+ const ArgSource &RHS,
+ const ArgRegister &Dst) {
+ emit_bif_is_eq_ne_exact(LHS, RHS, Dst, am_true, am_false);
}
-void BeamModuleAssembler::emit_badmatch(const ArgVal &Src) {
+void BeamModuleAssembler::emit_badmatch(const ArgSource &Src) {
mov_arg(x86::qword_ptr(c_p, offsetof(Process, fvalue)), Src);
emit_error(BADMATCH);
}
-void BeamModuleAssembler::emit_case_end(const ArgVal &Src) {
+void BeamModuleAssembler::emit_case_end(const ArgSource &Src) {
mov_arg(x86::qword_ptr(c_p, offsetof(Process, fvalue)), Src);
emit_error(EXC_CASE_CLAUSE);
}
@@ -1614,7 +1756,13 @@ void BeamModuleAssembler::emit_if_end() {
emit_error(EXC_IF_CLAUSE);
}
-void BeamModuleAssembler::emit_catch(const ArgVal &Y, const ArgVal &Fail) {
+void BeamModuleAssembler::emit_badrecord(const ArgSource &Src) {
+ mov_arg(x86::qword_ptr(c_p, offsetof(Process, fvalue)), Src);
+ emit_error(EXC_BADRECORD);
+}
+
+void BeamModuleAssembler::emit_catch(const ArgYRegister &CatchTag,
+ const ArgLabel &Handler) {
a.inc(x86::qword_ptr(c_p, offsetof(Process, catches)));
Label patch_addr = a.newLabel();
@@ -1632,30 +1780,41 @@ void BeamModuleAssembler::emit_catch(const ArgVal &Y, const ArgVal &Fail) {
a.bind(patch_addr);
a.mov(RETd, imm(0x7fffffff));
- mov_arg(Y, RET);
+ mov_arg(CatchTag, RET);
/* Offset = 1 for `mov` payload */
- catches.push_back({{patch_addr, 0x1, 0}, labels[Fail.getValue()]});
+ catches.push_back({{patch_addr, 0x1, 0}, resolve_beam_label(Handler)});
}
+/*
+ * At entry:
+ *
+ * x0 = THE_NON_VALUE
+ * x1 = Term
+ * x2 = Stacktrace
+ * x3 = Exception class
+ */
void BeamGlobalAssembler::emit_catch_end_shared() {
Label not_throw = a.newLabel(), not_error = a.newLabel(),
after_gc = a.newLabel();
+ emit_enter_frame();
+
/* Load thrown value / reason into ARG2 for add_stacktrace */
- a.mov(ARG2, getXRef(2));
+ a.mov(ARG2, getXRef(1));
- a.cmp(getXRef(1), imm(am_throw));
+ a.cmp(getXRef(3), imm(am_throw));
a.short_().jne(not_throw);
/* Thrown value, return it in x0 */
a.mov(getXRef(0), ARG2);
+ emit_leave_frame();
a.ret();
a.bind(not_throw);
{
- a.cmp(getXRef(1), imm(am_error));
+ a.cmp(getXRef(3), imm(am_error));
/* NOTE: Short won't reach if JIT_HARD_DEBUG is defined. */
a.jne(not_error);
@@ -1664,7 +1823,7 @@ void BeamGlobalAssembler::emit_catch_end_shared() {
a.mov(ARG1, c_p);
/* ARG2 set above. */
- a.mov(ARG3, getXRef(3));
+ a.mov(ARG3, getXRef(2));
runtime_call<3>(add_stacktrace);
emit_leave_runtime<Update::eStack | Update::eHeap>();
@@ -1699,13 +1858,14 @@ void BeamGlobalAssembler::emit_catch_end_shared() {
a.mov(getXRef(0), RET);
}
+ emit_leave_frame();
a.ret();
}
-void BeamModuleAssembler::emit_catch_end(const ArgVal &Y) {
+void BeamModuleAssembler::emit_catch_end(const ArgYRegister &CatchTag) {
Label next = a.newLabel();
- emit_try_end(Y);
+ emit_try_end(CatchTag);
a.cmp(getXRef(0), imm(THE_NON_VALUE));
a.short_().jne(next);
@@ -1713,18 +1873,17 @@ void BeamModuleAssembler::emit_catch_end(const ArgVal &Y) {
a.bind(next);
}
-void BeamModuleAssembler::emit_try_end(const ArgVal &Y) {
+void BeamModuleAssembler::emit_try_end(const ArgYRegister &CatchTag) {
a.dec(x86::qword_ptr(c_p, offsetof(Process, catches)));
- emit_init(Y);
+ emit_init(CatchTag);
}
-void BeamModuleAssembler::emit_try_case(const ArgVal &Y) {
+void BeamModuleAssembler::emit_try_case(const ArgYRegister &CatchTag) {
+ /* The try_tag in the Y slot in the stack frame has already been
+ * cleared. */
a.dec(x86::qword_ptr(c_p, offsetof(Process, catches)));
- mov_arg(Y, NIL);
- a.movups(x86::xmm0, x86::xmmword_ptr(registers, 1 * sizeof(Eterm)));
a.mov(RET, getXRef(3));
- a.movups(x86::xmmword_ptr(registers, 0 * sizeof(Eterm)), x86::xmm0);
- a.mov(getXRef(2), RET);
+ a.mov(getXRef(0), RET);
#ifdef DEBUG
Label fvalue_ok = a.newLabel(), assertion_failed = a.newLabel();
@@ -1742,12 +1901,13 @@ void BeamModuleAssembler::emit_try_case(const ArgVal &Y) {
#endif
}
-void BeamModuleAssembler::emit_try_case_end(const ArgVal &Src) {
+void BeamModuleAssembler::emit_try_case_end(const ArgSource &Src) {
mov_arg(x86::qword_ptr(c_p, offsetof(Process, fvalue)), Src);
emit_error(EXC_TRY_CLAUSE);
}
-void BeamModuleAssembler::emit_raise(const ArgVal &Trace, const ArgVal &Value) {
+void BeamModuleAssembler::emit_raise(const ArgSource &Trace,
+ const ArgSource &Value) {
mov_arg(ARG3, Value);
mov_arg(ARG2, Trace);
@@ -1762,7 +1922,7 @@ void BeamModuleAssembler::emit_raise(const ArgVal &Trace, const ArgVal &Value) {
emit_leave_runtime();
- emit_handle_error();
+ emit_raise_exception();
}
void BeamModuleAssembler::emit_build_stacktrace() {
@@ -1792,49 +1952,62 @@ void BeamModuleAssembler::emit_raw_raise() {
a.test(RET, RET);
a.short_().jne(next);
- emit_handle_error();
+ emit_raise_exception();
a.bind(next);
a.mov(getXRef(0), imm(am_badarg));
}
+#define TEST_YIELD_RETURN_OFFSET \
+ (BEAM_ASM_FUNC_PROLOGUE_SIZE + 16 + \
+ (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA ? 4 : 0))
+
+/* ARG3 = return address, current_label + TEST_YIELD_RETURN_OFFSET */
void BeamGlobalAssembler::emit_i_test_yield_shared() {
- int mfa_offset = -(int)sizeof(ErtsCodeMFA) - BEAM_ASM_FUNC_PROLOGUE_SIZE;
+ int mfa_offset = -TEST_YIELD_RETURN_OFFSET - (int)sizeof(ErtsCodeMFA);
- /* Yield address is in ARG3. */
a.lea(ARG2, x86::qword_ptr(ARG3, mfa_offset));
a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), ARG2);
a.mov(ARG2, x86::qword_ptr(ARG2, offsetof(ErtsCodeMFA, arity)));
a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), ARG2);
- emit_discard_cp();
-
a.jmp(labels[context_switch_simplified]);
}
void BeamModuleAssembler::emit_i_test_yield() {
- Label next = a.newLabel(), entry = a.newLabel();
-
/* When present, this is guaranteed to be the first instruction after the
* breakpoint trampoline. */
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ BEAM_ASM_FUNC_PROLOGUE_SIZE);
- ASSERT(a.offset() % 8 == 0);
- a.bind(entry);
+ emit_enter_frame();
+
+ a.lea(ARG3, x86::qword_ptr(current_label, TEST_YIELD_RETURN_OFFSET));
a.dec(FCALLS);
- a.short_().jg(next);
- a.lea(ARG3, x86::qword_ptr(entry));
- a.call(funcYield);
- a.bind(next);
+ a.long_().jle(resolve_fragment(ga->get_i_test_yield_shared()));
+
+ ASSERT((a.offset() - code.labelOffsetFromBase(current_label)) ==
+ TEST_YIELD_RETURN_OFFSET);
+
+#if defined(JIT_HARD_DEBUG) && defined(ERLANG_FRAME_POINTERS)
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, x86::rbp);
+ a.mov(ARG3, x86::rsp);
+
+ emit_enter_runtime<Update::eStack>();
+ runtime_call<3>(erts_validate_stack);
+ emit_leave_runtime<Update::eStack>();
+#endif
}
void BeamModuleAssembler::emit_i_yield() {
a.mov(getXRef(0), imm(am_true));
#ifdef NATIVE_ERLANG_STACK
- fragment_call(ga->get_dispatch_return());
+ fragment_call(resolve_fragment(ga->get_dispatch_return()));
#else
Label next = a.newLabel();
a.lea(ARG3, x86::qword_ptr(next));
- abs_jmp(ga->get_dispatch_return());
+ a.jmp(resolve_fragment(ga->get_dispatch_return()));
a.align(AlignMode::kCode, 8);
a.bind(next);
@@ -1864,9 +2037,9 @@ void BeamModuleAssembler::emit_i_perf_counter() {
{
a.mov(TMP_MEM1q, RET);
- emit_gc_test(ArgVal(ArgVal::i, 0),
- ArgVal(ArgVal::i, ERTS_MAX_UINT64_HEAP_SIZE),
- ArgVal(ArgVal::i, 0));
+ emit_gc_test(ArgWord(0),
+ ArgWord(ERTS_MAX_UINT64_HEAP_SIZE),
+ ArgWord(0));
a.mov(ARG1, TMP_MEM1q);
diff --git a/erts/emulator/beam/jit/x86/instr_float.cpp b/erts/emulator/beam/jit/x86/instr_float.cpp
index 24b5d3908e..d3e47d49dc 100644
--- a/erts/emulator/beam/jit/x86/instr_float.cpp
+++ b/erts/emulator/beam/jit/x86/instr_float.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,21 +25,68 @@ extern "C"
#include "big.h"
}
-void BeamModuleAssembler::emit_fload(const ArgVal &Src, const ArgVal &Dst) {
+/* Fixes a silly compilation error on Windows, where the following macro
+ * prevents us from using `std::numeric_limits<T>::max()` */
+#ifdef max
+# undef max
+#endif
+
+void BeamGlobalAssembler::emit_check_float_error() {
+ Label error = a.newLabel(), floatMax = a.newLabel(),
+ floatSignMask = a.newLabel();
+
+ a.movsd(x86::xmm2, x86::xmm0);
+ a.movsd(x86::xmm1, x86::qword_ptr(floatMax));
+ a.andpd(x86::xmm2, x86::xmmword_ptr(floatSignMask));
+ a.ucomisd(x86::xmm1, x86::xmm2);
+ a.short_().jb(error);
+ a.ret();
+
+ a.bind(error);
+ {
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)),
+ imm(EXC_BADARITH));
+ a.sub(ARG4, ARG4);
+ a.jmp(labels[raise_exception]);
+ }
+
+ a.align(AlignMode::kCode, 16);
+ a.bind(floatSignMask);
+ a.embedUInt64(0x7FFFFFFFFFFFFFFFul);
+ a.bind(floatMax);
+ a.embedDouble(std::numeric_limits<double>::max());
+}
+
+void BeamModuleAssembler::emit_float_instr(uint32_t instId,
+ const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ a.movsd(x86::xmm0, getArgRef(LHS));
+ a.movsd(x86::xmm1, getArgRef(RHS));
+
+ a.emit(instId, x86::xmm0, x86::xmm1);
+ safe_fragment_call(ga->get_check_float_error());
+ a.movsd(getArgRef(Dst), x86::xmm0);
+}
+
+void BeamModuleAssembler::emit_fload(const ArgSource &Src,
+ const ArgFRegister &Dst) {
/* {thing_word,double} */
mov_arg(ARG1, Src);
x86::Gp boxed_ptr = emit_ptr_val(ARG1, ARG1);
- a.mov(ARG1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
- a.mov(getArgRef(Dst), ARG1);
+
+ a.movsd(x86::xmm0, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+ a.movsd(getArgRef(Dst), x86::xmm0);
}
-void BeamModuleAssembler::emit_fstore(const ArgVal &Src, const ArgVal &Dst) {
- a.mov(ARG1, getArgRef(Src));
+void BeamModuleAssembler::emit_fstore(const ArgFRegister &Src,
+ const ArgRegister &Dst) {
+ a.movsd(x86::xmm0, getArgRef(Src));
/* {thing_word,double} */
a.mov(x86::qword_ptr(HTOP), imm(HEADER_FLONUM));
- a.mov(x86::qword_ptr(HTOP, sizeof(Eterm)), ARG1);
+ a.movsd(x86::qword_ptr(HTOP, sizeof(Eterm)), x86::xmm0);
a.lea(ARG1, x86::qword_ptr(HTOP, make_float(0)));
mov_arg(Dst, ARG1);
@@ -47,122 +94,132 @@ void BeamModuleAssembler::emit_fstore(const ArgVal &Src, const ArgVal &Dst) {
a.add(HTOP, imm(FLOAT_SIZE_OBJECT * sizeof(Eterm)));
}
-static int handle_fconv(Eterm src, double *dst) {
- if (is_small(src)) {
- *dst = (double)signed_val(src);
- } else if (is_float(src)) {
- GET_DOUBLE(src, *(FloatDef *)dst);
- } else if (is_big(src)) {
- if (big_to_double(src, dst) < 0) {
- return 1;
- }
- } else {
- return 1;
- }
+/* ARG2 = source term */
+void BeamGlobalAssembler::emit_fconv_shared() {
+ Label error = a.newLabel();
- return 0;
-}
+ /* big_to_double expects source in ARG1 */
+ a.mov(ARG1, ARG2);
-void BeamModuleAssembler::emit_fconv(const ArgVal &Src, const ArgVal &Dst) {
- Label next = a.newLabel();
+ emit_is_boxed(error, ARG2, dShort);
- mov_arg(ARG1, Src);
- a.lea(ARG2, getArgRef(Dst));
+ auto boxed_ptr = emit_ptr_val(ARG2, ARG2);
+ a.mov(ARG2, emit_boxed_val(boxed_ptr));
+ a.and_(ARG2, imm(_TAG_HEADER_MASK - _BIG_SIGN_BIT));
+ a.cmp(ARG2, imm(_TAG_HEADER_POS_BIG));
+ a.short_().jne(error);
+ emit_enter_frame();
emit_enter_runtime();
- runtime_call<2>(handle_fconv);
+ /* ARG1 already contains the source term. */
+ a.lea(ARG2, TMP_MEM1q);
+ runtime_call<2>(big_to_double);
emit_leave_runtime();
+ emit_leave_frame();
- a.test(RET, RET);
- a.short_().je(next);
-
- emit_error(EXC_BADARITH);
-
- a.bind(next);
-}
+ a.test(RETd, RETd);
+ a.short_().js(error);
-void BeamModuleAssembler::emit_check_float(Label next, x86::Xmm value) {
- a.movsd(x86::xmm2, value);
- a.movsd(x86::xmm1, x86::qword_ptr(floatMax));
- a.andpd(x86::xmm2, x86::xmmword_ptr(floatSignMask));
- a.ucomisd(x86::xmm1, x86::xmm2);
- a.short_().jnb(next);
+ a.movsd(x86::xmm0, TMP_MEM1q);
+ a.ret();
- emit_error(EXC_BADARITH);
+ a.bind(error);
+ {
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)),
+ imm(EXC_BADARITH));
+ a.sub(ARG4, ARG4);
+ a.jmp(labels[raise_exception]);
+ }
}
-void BeamModuleAssembler::emit_i_fadd(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- Label next = a.newLabel();
+void BeamModuleAssembler::emit_fconv(const ArgSource &Src,
+ const ArgFRegister &Dst) {
+ if (always_small(Src)) {
+ comment("simplified fconv since source is always small");
+ mov_arg(ARG2, Src);
+ a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
+ a.cvtsi2sd(x86::xmm0, ARG2);
+ a.movsd(getArgRef(Dst), x86::xmm0);
+ return;
+ }
- a.movsd(x86::xmm0, getArgRef(LHS));
- a.movsd(x86::xmm1, getArgRef(RHS));
- a.addpd(x86::xmm0, x86::xmm1);
+ Label next = a.newLabel(), not_small = a.newLabel(),
+ fallback = a.newLabel();
+
+ mov_arg(ARG2, Src);
+
+ emit_is_small(not_small, Src, ARG2);
+
+ a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
+ a.cvtsi2sd(x86::xmm0, ARG2);
+ a.short_().jmp(next);
+
+ a.bind(not_small);
+ {
+ if (masked_types(Src, BEAM_TYPE_FLOAT) == BEAM_TYPE_NONE) {
+ comment("skipped float path since source cannot be a float");
+ } else {
+ /* If the source is always a number, we can skip the box test when
+ * it's not a small. */
+ if (always_one_of(Src, BEAM_TYPE_FLOAT | BEAM_TYPE_INTEGER)) {
+ comment("skipped box test since source is always a number");
+ } else {
+ emit_is_boxed(fallback, Src, ARG2, dShort);
+ }
+
+ /* Speculatively load the float value, this is safe since all boxed
+ * terms are at least two words long. */
+ auto boxed_ptr = emit_ptr_val(ARG1, ARG2);
+ a.movsd(x86::xmm0, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
+
+ a.cmp(emit_boxed_val(boxed_ptr), imm(HEADER_FLONUM));
+ a.short_().je(next);
+ }
- emit_check_float(next, x86::xmm0);
+ /* Bignum or invalid input, handle it in a shared fragment. */
+ a.bind(fallback);
+ safe_fragment_call(ga->get_fconv_shared());
+ }
a.bind(next);
a.movsd(getArgRef(Dst), x86::xmm0);
}
-void BeamModuleAssembler::emit_i_fsub(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- Label next = a.newLabel();
-
- a.movsd(x86::xmm0, getArgRef(LHS));
- a.movsd(x86::xmm1, getArgRef(RHS));
- a.subpd(x86::xmm0, x86::xmm1);
-
- emit_check_float(next, x86::xmm0);
-
- a.bind(next);
- a.movsd(getArgRef(Dst), x86::xmm0);
+void BeamModuleAssembler::emit_i_fadd(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(x86::Inst::kIdAddpd, LHS, RHS, Dst);
}
-void BeamModuleAssembler::emit_i_fmul(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- Label next = a.newLabel();
-
- a.movsd(x86::xmm0, getArgRef(LHS));
- a.movsd(x86::xmm1, getArgRef(RHS));
- a.mulpd(x86::xmm0, x86::xmm1);
-
- emit_check_float(next, x86::xmm0);
-
- a.bind(next);
- a.movsd(getArgRef(Dst), x86::xmm0);
+void BeamModuleAssembler::emit_i_fsub(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(x86::Inst::kIdSubpd, LHS, RHS, Dst);
}
-void BeamModuleAssembler::emit_i_fdiv(const ArgVal &LHS,
- const ArgVal &RHS,
- const ArgVal &Dst) {
- Label next = a.newLabel();
-
- a.movsd(x86::xmm0, getArgRef(LHS));
- a.movsd(x86::xmm1, getArgRef(RHS));
- a.divpd(x86::xmm0, x86::xmm1);
-
- emit_check_float(next, x86::xmm0);
-
- a.bind(next);
- a.movsd(getArgRef(Dst), x86::xmm0);
+void BeamModuleAssembler::emit_i_fmul(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(x86::Inst::kIdMulpd, LHS, RHS, Dst);
}
-void BeamModuleAssembler::emit_i_fnegate(const ArgVal &Src, const ArgVal &Dst) {
- Label next = a.newLabel();
-
- /* xmm0 = 0.0 */
- a.pxor(x86::xmm0, x86::xmm0);
- a.movsd(x86::xmm1, getArgRef(Src));
- a.subpd(x86::xmm0, x86::xmm1);
-
- emit_check_float(next, x86::xmm0);
+void BeamModuleAssembler::emit_i_fdiv(const ArgFRegister &LHS,
+ const ArgFRegister &RHS,
+ const ArgFRegister &Dst) {
+ emit_float_instr(x86::Inst::kIdDivpd, LHS, RHS, Dst);
+}
- a.bind(next);
- a.movsd(getArgRef(Dst), x86::xmm0);
+void BeamModuleAssembler::emit_i_fnegate(const ArgFRegister &Src,
+ const ArgFRegister &Dst) {
+ /* Note that there is no need to check for errors since flipping the sign
+ * of a finite float is guaranteed to produce a finite float. */
+ if (Src != Dst) {
+ mov_arg(RET, Src);
+ a.btc(RET, imm(63));
+ mov_arg(Dst, RET);
+ } else {
+ a.btc(getArgRef(Dst), 63);
+ }
}
diff --git a/erts/emulator/beam/jit/x86/instr_fun.cpp b/erts/emulator/beam/jit/x86/instr_fun.cpp
new file mode 100644
index 0000000000..1ae19aaaba
--- /dev/null
+++ b/erts/emulator/beam/jit/x86/instr_fun.cpp
@@ -0,0 +1,437 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021-2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+/* Calls to functions that are being purged (but haven't finished) land here.
+ *
+ * ARG3 = arity
+ * ARG4 = fun thing
+ * ARG5 = current PC */
+void BeamGlobalAssembler::emit_unloaded_fun() {
+ Label error = a.newLabel();
+
+ emit_enter_frame();
+
+ a.mov(TMP_MEM1q, ARG5);
+
+ emit_enter_runtime<Update::eHeap | Update::eStack | Update::eReductions>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ /* ARG3 and ARG4 have already been set. */
+ runtime_call<4>(beam_jit_handle_unloaded_fun);
+
+ emit_leave_runtime<Update::eHeap | Update::eStack | Update::eReductions |
+ Update::eCodeIndex>();
+
+ a.test(RET, RET);
+ a.jz(error);
+
+ emit_leave_frame();
+ a.jmp(emit_setup_dispatchable_call(RET));
+
+ a.bind(error);
+ {
+ /* The `raise_exception` fragment expects that the PC is on the
+ * stack. */
+ a.push(TMP_MEM1q);
+ mov_imm(ARG4, nullptr);
+ a.jmp(labels[raise_exception]);
+ }
+}
+
+/* Handles errors for `call_fun`.
+ *
+ * ARG3 = arity
+ * ARG4 = fun thing
+ * ARG5 = current PC */
+void BeamGlobalAssembler::emit_handle_call_fun_error() {
+ Label bad_arity = a.newLabel(), bad_fun = a.newLabel();
+
+ emit_enter_frame();
+
+ emit_is_boxed(bad_fun, ARG4);
+
+ x86::Gp fun_thing = emit_ptr_val(RET, ARG4);
+ a.cmp(emit_boxed_val(fun_thing), imm(HEADER_FUN));
+ a.short_().je(bad_arity);
+
+ a.bind(bad_fun);
+ {
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), imm(EXC_BADFUN));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, fvalue)), ARG4);
+
+ /* The `raise_exception` fragment expects that the PC is on the
+ * stack. */
+ a.push(ARG5);
+ mov_imm(ARG4, nullptr);
+ a.jmp(labels[raise_exception]);
+ }
+
+ a.bind(bad_arity);
+ {
+ /* Stash our fun and current PC. Note that we don't move the fun to
+ * {x,0} straight away as that would clobber the first argument. */
+ a.mov(TMP_MEM1q, ARG4);
+ a.mov(TMP_MEM2q, ARG5);
+
+ emit_enter_runtime<Update::eHeap | Update::eStack>();
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ /* ARG3 is already set. */
+ runtime_call<3>(beam_jit_build_argument_list);
+
+ emit_leave_runtime<Update::eHeap | Update::eStack>();
+
+ a.mov(ARG1, TMP_MEM1q);
+ a.mov(getXRef(0), ARG1);
+ a.mov(getXRef(1), RET);
+
+ /* Create the {Fun, Args} tuple. */
+ {
+ const int32_t bytes_needed = (3 + S_RESERVED) * sizeof(Eterm);
+ Label after_gc = a.newLabel();
+
+ a.lea(ARG3, x86::qword_ptr(HTOP, bytes_needed));
+ a.cmp(ARG3, E);
+ a.short_().jbe(after_gc);
+ {
+ mov_imm(ARG4, 2);
+ aligned_call(labels[garbage_collect]);
+ }
+ a.bind(after_gc);
+
+ a.mov(ARG1, getXRef(0));
+ a.mov(ARG2, getXRef(1));
+
+ a.mov(x86::qword_ptr(HTOP), imm(make_arityval(2)));
+ a.mov(x86::qword_ptr(HTOP, sizeof(Eterm[1])), ARG1);
+ a.mov(x86::qword_ptr(HTOP, sizeof(Eterm[2])), ARG2);
+
+ a.lea(ARG1, x86::qword_ptr(HTOP, TAG_PRIMARY_BOXED));
+ a.add(HTOP, imm(sizeof(Eterm[3])));
+ }
+
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)),
+ imm(EXC_BADARITY));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, fvalue)), ARG1);
+
+ /* The `raise_exception` fragment expects that the PC is on the
+ * stack. */
+ a.push(TMP_MEM2q);
+ mov_imm(ARG4, nullptr);
+ a.jmp(labels[raise_exception]);
+ }
+}
+
+/* `call_fun` instructions land here to set up their environment before jumping
+ * to the actual implementation.
+ *
+ * Keep in mind that this runs in the limbo between caller and callee, so we
+ * must not enter a frame here.
+ *
+ * ARG4 = fun thing */
+void BeamModuleAssembler::emit_i_lambda_trampoline(const ArgLambda &Lambda,
+ const ArgLabel &Lbl,
+ const ArgWord &Arity,
+ const ArgWord &NumFree) {
+ const ssize_t effective_arity = Arity.get() - NumFree.get();
+ const ssize_t num_free = NumFree.get();
+ ssize_t i;
+
+ const auto &lambda = lambdas[Lambda.get()];
+ a.bind(lambda.trampoline);
+
+ emit_ptr_val(ARG4, ARG4);
+
+ for (i = 0; i < num_free - 1; i += 2) {
+ size_t offset = offsetof(ErlFunThing, env) + i * sizeof(Eterm);
+
+ a.movups(x86::xmm0, emit_boxed_val(ARG4, offset, sizeof(Eterm[2])));
+ a.movups(getXRef(i + effective_arity, sizeof(Eterm[2])), x86::xmm0);
+ }
+
+ if (i < num_free) {
+ size_t offset = offsetof(ErlFunThing, env) + i * sizeof(Eterm);
+
+ a.mov(RET, emit_boxed_val(ARG4, offset));
+ a.mov(getXRef(i + effective_arity), RET);
+ }
+
+ a.jmp(resolve_beam_label(Lbl));
+}
+
+void BeamModuleAssembler::emit_i_make_fun3(const ArgLambda &Lambda,
+ const ArgRegister &Dst,
+ const ArgWord &Arity,
+ const ArgWord &NumFree,
+ const Span<ArgVal> &env) {
+ size_t num_free = env.size();
+
+ ASSERT(NumFree.get() == num_free);
+
+ mov_arg(ARG2, Lambda);
+ mov_arg(ARG3, Arity);
+ mov_arg(ARG4, NumFree);
+
+ emit_enter_runtime<Update::eHeap>();
+
+ a.mov(ARG1, c_p);
+ runtime_call<4>(erts_new_local_fun_thing);
+
+ emit_leave_runtime<Update::eHeap>();
+
+ comment("Move fun environment");
+ for (unsigned i = 0; i < num_free; i++) {
+ mov_arg(x86::qword_ptr(RET,
+ offsetof(ErlFunThing, env) + i * sizeof(Eterm)),
+ env[i]);
+ }
+
+ comment("Create boxed ptr");
+ a.or_(RETb, TAG_PRIMARY_BOXED);
+ mov_arg(Dst, RET);
+}
+
+/* Unwraps `apply_fun` so we can share the rest of the implementation with
+ * `call_fun`. */
+void BeamGlobalAssembler::emit_apply_fun_shared() {
+ Label finished = a.newLabel();
+
+ emit_enter_frame();
+
+ /* Put the arity and fun into the right registers for `call_fun`, and stash
+ * the argument list in ARG5 for the error path. We'll bump the arity as
+ * we go through the argument list. */
+ mov_imm(ARG3, 0);
+ a.mov(ARG4, getXRef(0));
+ a.mov(ARG5, getXRef(1));
+
+ {
+ Label unpack_next = a.newLabel(), malformed_list = a.newLabel(),
+ raise_error = a.newLabel();
+
+ auto x_register = getXRef(0);
+
+ ASSERT(x_register.shift() == 0);
+ x_register.setIndex(ARG3);
+ x_register.setShift(3);
+
+ a.mov(ARG1, ARG5);
+ a.bind(unpack_next);
+ {
+ a.cmp(ARG1d, imm(NIL));
+ a.short_().je(finished);
+
+ a.test(ARG1d, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
+ a.short_().jne(malformed_list);
+
+ emit_ptr_val(ARG1, ARG1);
+ a.mov(RET, getCARRef(ARG1));
+ a.mov(ARG1, getCDRRef(ARG1));
+ a.mov(x_register, RET);
+
+ a.inc(ARG3);
+
+ /* We bail at MAX_REG-1 rather than MAX_REG as the highest register
+ * is reserved for the loader. */
+ a.cmp(ARG3, imm(MAX_REG - 1));
+ a.jb(unpack_next);
+ }
+
+ a.mov(RET, imm(SYSTEM_LIMIT));
+ a.jmp(raise_error);
+
+ a.bind(malformed_list);
+ a.mov(RET, imm(BADARG));
+
+ a.bind(raise_error);
+ {
+ static const ErtsCodeMFA apply_mfa = {am_erlang, am_apply, 2};
+
+ a.mov(getXRef(0), ARG4);
+ a.mov(getXRef(1), ARG5);
+
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), RET);
+ mov_imm(ARG4, &apply_mfa);
+
+ emit_leave_frame();
+ a.jmp(labels[raise_exception]);
+ }
+ }
+
+ a.bind(finished);
+
+ emit_leave_frame();
+ a.ret();
+}
+
+void BeamModuleAssembler::emit_i_apply_fun() {
+ safe_fragment_call(ga->get_apply_fun_shared());
+
+ x86::Gp target = emit_call_fun();
+ ASSERT(target != ARG6);
+ erlang_call(target, ARG6);
+}
+
+void BeamModuleAssembler::emit_i_apply_fun_last(const ArgWord &Deallocate) {
+ emit_deallocate(Deallocate);
+ emit_i_apply_fun_only();
+}
+
+void BeamModuleAssembler::emit_i_apply_fun_only() {
+ safe_fragment_call(ga->get_apply_fun_shared());
+
+ x86::Gp target = emit_call_fun();
+ emit_leave_frame();
+ a.jmp(target);
+}
+
+/* Assumes that:
+ * ARG3 = arity
+ * ARG4 = fun thing */
+x86::Gp BeamModuleAssembler::emit_call_fun(bool skip_box_test,
+ bool skip_fun_test,
+ bool skip_arity_test) {
+ const bool never_fails = skip_box_test && skip_fun_test && skip_arity_test;
+ Label next = a.newLabel();
+
+ /* Speculatively strip the literal tag when needed. */
+ x86::Gp fun_thing = emit_ptr_val(RET, ARG4);
+
+ if (!never_fails) {
+ /* Load the error fragment into ARG2 so we can CMOV ourselves there on
+ * error. */
+ a.mov(ARG2, ga->get_handle_call_fun_error());
+ }
+
+ /* The `handle_call_fun_error` and `unloaded_fun` fragments expect current
+ * PC in ARG5. */
+ a.lea(ARG5, x86::qword_ptr(next));
+
+ if (!skip_box_test) {
+ /* As emit_is_boxed(), but explicitly sets ZF so we can rely on that
+ * for error checking in `next`. */
+ a.test(ARG4d, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_BOXED));
+ a.short_().jne(next);
+ } else {
+ comment("skipped box test since source is always boxed");
+ }
+
+ if (skip_fun_test) {
+ comment("skipped fun test since source is always a fun when boxed");
+ } else {
+ a.cmp(emit_boxed_val(fun_thing), imm(HEADER_FUN));
+ a.short_().jne(next);
+ }
+
+ if (skip_arity_test) {
+ comment("skipped arity test since source always has right arity");
+ } else {
+ a.cmp(emit_boxed_val(fun_thing,
+ offsetof(ErlFunThing, arity),
+ sizeof(byte)),
+ ARG3.r8());
+ }
+
+ a.mov(RET, emit_boxed_val(fun_thing, offsetof(ErlFunThing, entry)));
+ a.mov(ARG1, emit_setup_dispatchable_call(RET));
+
+ a.bind(next);
+
+ if (!never_fails) {
+ /* Assumes that ZF is set on success and clear on error, overwriting
+ * our destination with the error fragment's address. */
+ a.cmovne(ARG1, ARG2);
+ }
+
+ return ARG1;
+}
+
+void BeamModuleAssembler::emit_i_call_fun2(const ArgVal &Tag,
+ const ArgWord &Arity,
+ const ArgRegister &Func) {
+ mov_arg(ARG4, Func);
+
+ if (Tag.isImmed()) {
+ mov_imm(ARG3, Arity.get());
+
+ auto target = emit_call_fun(
+ always_one_of(Func, BEAM_TYPE_MASK_ALWAYS_BOXED),
+ masked_types(Func, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN,
+ Tag.as<ArgImmed>().get() == am_safe);
+
+ erlang_call(target, ARG6);
+ } else {
+ const auto &trampoline = lambdas[Tag.as<ArgLambda>().get()].trampoline;
+ erlang_call(trampoline, RET);
+ }
+}
+
+void BeamModuleAssembler::emit_i_call_fun2_last(const ArgVal &Tag,
+ const ArgWord &Arity,
+ const ArgRegister &Func,
+ const ArgWord &Deallocate) {
+ mov_arg(ARG4, Func);
+
+ if (Tag.isImmed()) {
+ mov_imm(ARG3, Arity.get());
+
+ auto target = emit_call_fun(
+ always_one_of(Func, BEAM_TYPE_MASK_ALWAYS_BOXED),
+ masked_types(Func, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_FUN,
+ Tag.as<ArgImmed>().get() == am_safe);
+
+ emit_deallocate(Deallocate);
+ emit_leave_frame();
+
+ a.jmp(target);
+ } else {
+ const auto &trampoline = lambdas[Tag.as<ArgLambda>().get()].trampoline;
+
+ emit_deallocate(Deallocate);
+ emit_leave_frame();
+
+ a.jmp(trampoline);
+ }
+}
+
+void BeamModuleAssembler::emit_i_call_fun(const ArgWord &Arity) {
+ const ArgXRegister Func(Arity.get());
+ const ArgAtom Tag(am_unsafe);
+
+ emit_i_call_fun2(Tag, Arity, Func);
+}
+
+void BeamModuleAssembler::emit_i_call_fun_last(const ArgWord &Arity,
+ const ArgWord &Deallocate) {
+ const ArgXRegister Func(Arity.get());
+ const ArgAtom Tag(am_unsafe);
+
+ emit_i_call_fun2_last(Tag, Arity, Func, Deallocate);
+}
+
+/* Psuedo-instruction for signalling lambda load errors. Never actually runs. */
+void BeamModuleAssembler::emit_i_lambda_error(const ArgWord &Dummy) {
+ comment("lambda error");
+ a.ud2();
+}
diff --git a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
index f952898c0e..26133d5ac0 100644
--- a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
+++ b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ void BeamGlobalAssembler::emit_handle_hd_error() {
a.mov(getXRef(0), RET);
a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), imm(BADARG));
a.mov(ARG4, imm(&mfa));
- a.jmp(labels[handle_error_shared_prologue]);
+ a.jmp(labels[raise_exception]);
}
/*
@@ -60,25 +60,22 @@ void BeamGlobalAssembler::emit_handle_hd_error() {
* The code size for this specialization of hd/1 is 21 bytes,
* while the code size for the bif1 instruction is 24 bytes.
*/
-void BeamModuleAssembler::emit_bif_hd(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Hd) {
+void BeamModuleAssembler::emit_bif_hd(const ArgSource &Src,
+ const ArgRegister &Hd) {
+ Label good_cons = a.newLabel();
+
mov_arg(RET, Src);
a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- Uint fail = Fail.getValue();
- if (fail) {
- a.jne(labels[fail]);
- } else {
- Label next = a.newLabel();
- a.short_().je(next);
- safe_fragment_call(ga->get_handle_hd_error());
- a.bind(next);
- }
+ a.short_().je(good_cons);
+ safe_fragment_call(ga->get_handle_hd_error());
- x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
- a.mov(ARG2, getCARRef(boxed_ptr));
- mov_arg(Hd, ARG2);
+ a.bind(good_cons);
+ {
+ x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
+ a.mov(ARG2, getCARRef(boxed_ptr));
+ mov_arg(Hd, ARG2);
+ }
}
void BeamGlobalAssembler::emit_handle_element_error() {
@@ -88,19 +85,20 @@ void BeamGlobalAssembler::emit_handle_element_error() {
a.mov(getXRef(1), ARG2);
a.mov(x86::qword_ptr(c_p, offsetof(Process, freason)), imm(BADARG));
a.mov(ARG4, imm(&mfa));
- a.jmp(labels[handle_error_shared_prologue]);
+
+ a.jmp(labels[raise_exception]);
}
-/*
- * ARG1 = Position (1-based)
+/* ARG1 = Position (1-based)
* ARG2 = Tuple
* ARG3 = 0 if if in body, otherwise address of failure label.
*
- * Will return with a value in RET only if the element operation succeeds.
- */
+ * Will return with a value in RET only if the element operation succeeds. */
void BeamGlobalAssembler::emit_bif_element_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
+
a.mov(RETd, ARG1d);
a.and_(RETb, imm(_TAG_IMMED1_MASK));
a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
@@ -116,7 +114,7 @@ void BeamGlobalAssembler::emit_bif_element_shared() {
a.lea(ARG5, emit_boxed_val(ARG5));
a.mov(ARG6, x86::qword_ptr(ARG5));
a.mov(RETd, ARG6d);
- ERTS_CT_ASSERT(make_arityval(0) == 0);
+ ERTS_CT_ASSERT(make_arityval_zero() == 0);
a.and_(RETb, imm(_TAG_HEADER_MASK));
a.short_().jne(error);
@@ -127,87 +125,176 @@ void BeamGlobalAssembler::emit_bif_element_shared() {
a.inc(ARG4);
a.mov(RET, x86::qword_ptr(ARG5, ARG4, 3));
- a.test(RETd, RETd);
+
+ emit_leave_frame();
a.ret();
a.bind(error);
{
- Label exception = a.newLabel();
+ emit_leave_frame();
a.test(ARG3, ARG3);
- a.short_().je(exception);
- emit_discard_cp();
- a.jmp(ARG3);
+ a.je(labels[handle_element_error]);
- a.bind(exception);
- a.jmp(labels[handle_element_error]);
+ /* Discard return address and jump to fail label. */
+ a.add(x86::rsp, imm(8));
+ a.jmp(ARG3);
}
}
/*
* At the time of implementation, there were 3678 uses of element/2 in
* the OTP source code. 3137 of those uses had a literal first argument
- * (the position in the tuple), while 540 uses had a varible first
+ * (the position in the tuple), while 540 uses had a variable first
* argument. Calls to element/2 (with a literal first argument) is
* especially common in code generated by yecc.
*/
-void BeamModuleAssembler::emit_bif_element(const ArgVal &Fail,
- const ArgVal &Pos,
- const ArgVal &Tuple,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_bif_element(const ArgLabel &Fail,
+ const ArgSource &Pos,
+ const ArgSource &Tuple,
+ const ArgRegister &Dst) {
bool const_position;
- const_position = Pos.getType() == ArgVal::i && is_small(Pos.getValue()) &&
- signed_val(Pos.getValue()) > 0 &&
- signed_val(Pos.getValue()) <= (Sint)MAX_ARITYVAL;
+ const_position = Pos.isSmall() && Pos.as<ArgSmall>().getSigned() > 0 &&
+ Pos.as<ArgSmall>().getSigned() <= (Sint)MAX_ARITYVAL;
+
+ /*
+ * Try to optimize the use of a tuple as a lookup table.
+ */
+ if (exact_type(Pos, BEAM_TYPE_INTEGER) && Tuple.isLiteral()) {
+ Eterm tuple = beamfile_get_literal(beam, Tuple.as<ArgLiteral>().get());
+
+ if (is_tuple(tuple)) {
+ Label error = a.newLabel(), next = a.newLabel();
+ Sint size = Sint(arityval(*tuple_val(tuple)));
+ auto [min, max] = getIntRange(Pos);
+ bool is_bounded = min <= max;
+ bool can_fail = !is_bounded || min < 1 || size < max;
+
+ comment("skipped tuple test since source is always a literal "
+ "tuple");
+ mov_arg(ARG2, Tuple);
+ mov_arg(ARG1, Pos);
+ x86::Gp boxed_ptr = emit_ptr_val(ARG3, ARG2);
+ a.lea(ARG4, emit_boxed_val(boxed_ptr));
+ if (always_small(Pos)) {
+ comment("skipped test for small position since it is always "
+ "small");
+ } else {
+ comment("simplified test for small position since it is an "
+ "integer");
+ a.test(ARG1.r8(), imm(TAG_PRIMARY_LIST));
+ a.short_().je(error);
+ }
+
+ a.mov(RET, ARG1);
+ a.sar(RET, imm(_TAG_IMMED1_SIZE));
+ if (is_bounded && min >= 1) {
+ comment("skipped check for position =:= 0 since it is always "
+ ">= 1");
+ } else {
+ a.short_().jz(error);
+ }
+ if (is_bounded && min >= 0 && size >= max) {
+ comment("skipped check for negative position and position "
+ "beyond tuple");
+ } else {
+ /* Note: Also checks for negative size. */
+ a.cmp(RET, imm(size));
+ a.short_().ja(error);
+ }
+
+ a.mov(RET, x86::qword_ptr(ARG4, RET, 3));
+ if (can_fail) {
+ a.short_().jmp(next);
+ }
+
+ a.bind(error);
+ if (can_fail) {
+ if (Fail.get() == 0) {
+ safe_fragment_call(ga->get_handle_element_error());
+ } else {
+ a.jmp(resolve_beam_label(Fail));
+ }
+ }
+
+ a.bind(next);
+ mov_arg(Dst, RET);
+
+ return;
+ }
+ }
if (const_position) {
/* The position is a valid small integer. Inline the code.
*
* The size of the code is 40 bytes, while the size of the bif2
* instruction is 36 bytes. */
- Uint position = signed_val(Pos.getValue());
- Label error;
+ Uint position = Pos.as<ArgSmall>().getSigned();
mov_arg(ARG2, Tuple);
- if (Fail.getValue() == 0) {
- error = a.newLabel();
+ x86::Gp boxed_ptr = emit_ptr_val(ARG3, ARG2);
- emit_is_boxed(error, ARG2, dShort);
- } else {
- emit_is_boxed(labels[Fail.getValue()], ARG2);
- }
+ if (exact_type(Tuple, BEAM_TYPE_TUPLE)) {
+ comment("skipped tuple test since source is always a tuple");
+ ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
+ a.cmp(emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)),
+ imm(make_arityval_unchecked(position)));
- x86::Gp boxed_ptr = emit_ptr_val(ARG3, ARG2);
- a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ if (Fail.get() == 0) {
+ Label next = a.newLabel();
- ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
- a.cmp(RETd, imm(make_arityval(position)));
+ a.short_().jae(next);
- if (Fail.getValue() == 0) {
- a.short_().jb(error);
- } else {
- a.jb(labels[Fail.getValue()]);
- }
+ mov_imm(ARG1, make_small(position));
+ safe_fragment_call(ga->get_handle_element_error());
- ERTS_CT_ASSERT(make_arityval(0) == 0);
- a.and_(RETb, imm(_TAG_HEADER_MASK));
+ a.bind(next);
+ } else {
+ a.jb(resolve_beam_label(Fail));
+ }
+ } else {
+ Distance dist;
+ Label error;
+
+ if (Fail.get() == 0) {
+ error = a.newLabel();
+ dist = dShort;
+ } else {
+ error = resolve_beam_label(Fail);
+ dist = dLong;
+ }
- if (Fail.getValue() == 0) {
- Label next = a.newLabel();
+ emit_is_boxed(error, Tuple, ARG2, dist);
- a.short_().je(next);
+ a.mov(RETd, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
+ a.cmp(RETd, imm(make_arityval_unchecked(position)));
- a.bind(error);
- {
- mov_imm(ARG1, make_small(position));
- safe_fragment_call(ga->get_handle_element_error());
+ if (Fail.get() == 0) {
+ a.short_().jb(error);
+ } else {
+ a.jb(error);
}
- a.bind(next);
- } else {
- a.jne(labels[Fail.getValue()]);
+ ERTS_CT_ASSERT(make_arityval_zero() == 0);
+ a.and_(RETb, imm(_TAG_HEADER_MASK));
+
+ if (Fail.get() == 0) {
+ Label next = a.newLabel();
+
+ a.short_().je(next);
+
+ a.bind(error);
+ {
+ mov_imm(ARG1, make_small(position));
+ safe_fragment_call(ga->get_handle_element_error());
+ }
+
+ a.bind(next);
+ } else {
+ a.jne(error);
+ }
}
a.mov(RET, emit_boxed_val(boxed_ptr, position * sizeof(Eterm)));
@@ -219,8 +306,8 @@ void BeamModuleAssembler::emit_bif_element(const ArgVal &Fail,
mov_arg(ARG2, Tuple);
mov_arg(ARG1, Pos);
- if (Fail.getValue() != 0) {
- a.lea(ARG3, x86::qword_ptr(labels[Fail.getValue()]));
+ if (Fail.get() != 0) {
+ a.lea(ARG3, x86::qword_ptr(resolve_beam_label(Fail)));
} else {
mov_imm(ARG3, 0);
}
diff --git a/erts/emulator/beam/jit/x86/instr_map.cpp b/erts/emulator/beam/jit/x86/instr_map.cpp
index b3e5287db6..cf0063e967 100644
--- a/erts/emulator/beam/jit/x86/instr_map.cpp
+++ b/erts/emulator/beam/jit/x86/instr_map.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,28 +28,202 @@ extern "C"
#include "beam_common.h"
}
-void BeamModuleAssembler::emit_ensure_map(const ArgVal &map) {
- Label next = a.newLabel(), badmap = a.newLabel();
+static const Uint32 INTERNAL_HASH_SALT = 3432918353;
+static const Uint32 HCONST_22 = 0x98C475E6UL;
+static const Uint32 HCONST = 0x9E3779B9;
- mov_arg(ARG1, map);
- emit_is_boxed(badmap, ARG1, dShort);
- /* We use ARG1 in the badmap branch, so use ARG2 below */
- x86::Gp boxed_ptr = emit_ptr_val(ARG2, ARG1);
- a.mov(ARG2, emit_boxed_val(boxed_ptr));
- a.and_(ARG2d, imm(_TAG_HEADER_MASK));
- a.cmp(ARG2d, imm(_TAG_HEADER_MAP));
- a.short_().je(next);
+/* ARG3 = incoming hash
+ * ARG4 = lower 32
+ * ARG5 = upper 32
+ * ARG6 = type constant
+ *
+ * Helper function for calculating the internal hash of keys before looking
+ * them up in a map.
+ *
+ * This is essentially just a manual expansion of the `UINT32_HASH_2` macro.
+ * Whenever the internal hash algorithm is updated, this and all of its users
+ * must follow suit.
+ *
+ * Result is returned in ARG3. */
+void BeamGlobalAssembler::emit_internal_hash_helper() {
+ x86::Gp hash = ARG3d, lower = ARG4d, upper = ARG5d;
+
+ a.add(lower, ARG6d);
+ a.add(upper, ARG6d);
+
+ using rounds =
+ std::initializer_list<std::tuple<x86::Gp, x86::Gp, x86::Gp, int>>;
+ for (const auto &round : rounds{{lower, upper, hash, 13},
+ {upper, hash, lower, -8},
+ {hash, lower, upper, 13},
+ {lower, upper, hash, 12},
+ {upper, hash, lower, -16},
+ {hash, lower, upper, 5},
+ {lower, upper, hash, 3},
+ {upper, hash, lower, -10},
+ {hash, lower, upper, 15}}) {
+ const auto &[r_a, r_b, r_c, shift] = round;
+
+ a.sub(r_a, r_b);
+ a.sub(r_a, r_c);
+
+ /* We have no use for the type constant anymore, reuse its register for
+ * the `a ^= r_c << shift` expression. */
+ a.mov(ARG6d, r_c);
+
+ if (shift > 0) {
+ a.shr(ARG6d, imm(shift));
+ } else {
+ a.shl(ARG6d, imm(-shift));
+ }
+
+ a.xor_(r_a, ARG6d);
+ }
+
+ a.ret();
+}
+
+/* ARG1 = hash map root, ARG2 = key, ARG3 = key hash, RETd = node header
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_hashmap_get_element() {
+ Label node_loop = a.newLabel();
+
+ x86::Gp node = ARG1, key = ARG2, key_hash = ARG3d, header_val = RETd,
+ index = ARG4d, depth = ARG5d;
- a.bind(badmap);
+ const int header_shift =
+ (_HEADER_ARITY_OFFS + MAP_HEADER_TAG_SZ + MAP_HEADER_ARITY_SZ);
+
+ /* Skip the root header. This is not required for child nodes. */
+ a.add(node, imm(sizeof(Eterm)));
+ mov_imm(depth, 0);
+
+ a.bind(node_loop);
{
- a.mov(x86::qword_ptr(c_p, offsetof(Process, fvalue)), ARG1);
- emit_error(BADMAP);
+ Label fail = a.newLabel(), leaf_node = a.newLabel(),
+ skip_index_adjustment = a.newLabel(), update_hash = a.newLabel();
+
+ /* Find out which child we should follow, and shift the hash for the
+ * next round. */
+ a.mov(index, key_hash);
+ a.and_(index, imm(0xF));
+ a.shr(key_hash, imm(4));
+ a.inc(depth);
+
+ /* The entry offset is always equal to the index on fully populated
+ * nodes, so we'll skip adjusting them. */
+ ERTS_CT_ASSERT(header_shift == 16);
+ a.sar(header_val, imm(header_shift));
+ a.cmp(header_val, imm(-1));
+ a.short_().je(skip_index_adjustment);
+ {
+ /* If our bit isn't set on this node, the key can't be found.
+ *
+ * Note that we jump directly to a `RET` instruction, as `BT` only
+ * affects CF, and ZF ("not found") is clear at this point. */
+ a.bt(header_val, index);
+ a.short_().jnc(fail);
+
+ /* The actual offset of our entry is the number of bits set (in
+ * essence "entries present") before our index in the bitmap. */
+ a.bzhi(header_val, header_val, index);
+ a.popcnt(index, header_val);
+ }
+ a.bind(skip_index_adjustment);
+
+ a.mov(node,
+ x86::qword_ptr(node,
+ index.r64(),
+ 3,
+ sizeof(Eterm) - TAG_PRIMARY_BOXED));
+ emit_ptr_val(node, node);
+
+ /* Have we found our leaf? */
+ a.test(node.r32(), imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
+ a.short_().je(leaf_node);
+
+ /* Nope, we have to search another node. */
+ a.mov(header_val, emit_boxed_val(node, 0, sizeof(Uint32)));
+
+ /* After 8 nodes we've run out of the 32 bits we started with, so we
+ * need to update the hash to keep going. */
+ a.test(depth, imm(0x7));
+ a.short_().jz(update_hash);
+ a.short_().jmp(node_loop);
+
+ a.bind(leaf_node);
+ {
+ /* We've arrived at a leaf, set ZF according to whether its key
+ * matches ours and speculatively place the element in RET. */
+ a.cmp(getCARRef(node), key);
+ a.mov(RET, getCDRRef(node));
+
+ /* See comment at the jump. */
+ a.bind(fail);
+ a.ret();
+ }
+
+ /* After 8 nodes we've run out of the 32 bits we started with, so we
+ * must calculate a new hash to continue.
+ *
+ * This is a manual expansion `make_map_hash` from utils.c, and all
+ * changes to that function must be mirrored here. */
+ a.bind(update_hash);
+ {
+ a.mov(TMP_MEM1d, depth);
+
+ /* NOTE: ARG3d is always 0 at this point. */
+ a.mov(ARG4d, depth);
+ a.shr(ARG4d, imm(3));
+ mov_imm(ARG5d, 1);
+ a.mov(ARG6d, imm(HCONST_22));
+ a.call(labels[internal_hash_helper]);
+
+ a.xor_(ARG3d, imm(INTERNAL_HASH_SALT));
+ a.mov(ARG4d, key.r32());
+ a.mov(ARG5, key);
+ a.shr(ARG5, imm(32));
+ a.mov(ARG6d, imm(HCONST));
+ a.call(labels[internal_hash_helper]);
+
+ a.mov(depth, TMP_MEM1d);
+
+ a.jmp(node_loop);
+ }
}
+}
- a.bind(next);
+/* ARG1 = flat map, ARG2 = key
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_flatmap_get_element() {
+ Label fail = a.newLabel(), loop = a.newLabel();
+
+ a.mov(RETd, emit_boxed_val(ARG1, offsetof(flatmap_t, size), 4));
+ a.mov(ARG4, emit_boxed_val(ARG1, offsetof(flatmap_t, keys)));
+
+ emit_ptr_val(ARG4, ARG4);
+
+ a.bind(loop);
+ {
+ a.dec(RETd);
+ a.short_().jl(fail);
+
+ a.cmp(ARG2,
+ x86::qword_ptr(ARG4, RET, 3, sizeof(Eterm) - TAG_PRIMARY_BOXED));
+ a.short_().jne(loop);
+ }
+
+ int value_offset = sizeof(flatmap_t) - TAG_PRIMARY_BOXED;
+ a.mov(RET, x86::qword_ptr(ARG1, RET, 3, value_offset));
+
+ a.bind(fail);
+ a.ret();
}
void BeamGlobalAssembler::emit_new_map_shared() {
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -57,19 +231,20 @@ void BeamGlobalAssembler::emit_new_map_shared() {
runtime_call<5>(erts_gc_new_map);
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ emit_leave_frame();
a.ret();
}
-void BeamModuleAssembler::emit_new_map(const ArgVal &Dst,
- const ArgVal &Live,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_new_map(const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
Label data = embed_vararg_rodata(args, CP_SIZE);
- ASSERT(Size.getValue() == args.size());
+ ASSERT(Size.get() == args.size());
- mov_imm(ARG3, Live.getValue());
+ mov_imm(ARG3, Live.get());
mov_imm(ARG4, args.size());
a.lea(ARG5, x86::qword_ptr(data));
fragment_call(ga->get_new_map_shared());
@@ -78,6 +253,7 @@ void BeamModuleAssembler::emit_new_map(const ArgVal &Dst,
}
void BeamGlobalAssembler::emit_i_new_small_map_lit_shared() {
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -85,23 +261,23 @@ void BeamGlobalAssembler::emit_i_new_small_map_lit_shared() {
runtime_call<5>(erts_gc_new_small_map_lit);
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ emit_leave_frame();
a.ret();
}
-void BeamModuleAssembler::emit_i_new_small_map_lit(
- const ArgVal &Dst,
- const ArgVal &Live,
- const ArgVal &Keys,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_i_new_small_map_lit(const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgLiteral &Keys,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
Label data = embed_vararg_rodata(args, CP_SIZE);
- ASSERT(Size.getValue() == args.size());
+ ASSERT(Size.get() == args.size());
ASSERT(Keys.isLiteral());
mov_arg(ARG3, Keys);
- mov_imm(ARG4, Live.getValue());
+ mov_imm(ARG4, Live.get());
a.lea(ARG5, x86::qword_ptr(data));
fragment_call(ga->get_i_new_small_map_lit_shared());
@@ -109,85 +285,232 @@ void BeamModuleAssembler::emit_i_new_small_map_lit(
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_i_get_map_element(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Key,
- const ArgVal &Dst) {
- mov_arg(ARG1, Src);
- mov_arg(ARG2, Key);
+/* ARG1 = map, ARG2 = key
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_i_get_map_element_shared() {
+ Label generic = a.newLabel(), hashmap = a.newLabel();
- emit_enter_runtime();
+ a.mov(RETd, ARG2d);
- runtime_call<2>(get_map_element);
+ a.and_(RETb, imm(_TAG_PRIMARY_MASK));
+ a.cmp(RETb, imm(TAG_PRIMARY_IMMED1));
+ a.short_().jne(generic);
- emit_leave_runtime();
+ emit_ptr_val(ARG1, ARG1);
- emit_test_the_non_value(RET);
- a.je(labels[Fail.getValue()]);
+ a.mov(RETd, emit_boxed_val(ARG1, 0, sizeof(Uint32)));
+ a.mov(ARG4d, RETd);
+
+ a.and_(ARG4d, imm(_HEADER_MAP_SUBTAG_MASK));
+ a.cmp(ARG4d, imm(HAMT_SUBTAG_HEAD_FLATMAP));
+ a.short_().jne(hashmap);
+
+ emit_flatmap_get_element();
+
+ a.bind(generic);
+ {
+ emit_enter_runtime();
+ runtime_call<2>(get_map_element);
+ emit_leave_runtime();
+
+ emit_test_the_non_value(RET);
+
+ /* Invert ZF, we want it to be set when RET is a value. */
+ a.setnz(ARG1.r8());
+ a.dec(ARG1.r8());
+
+ a.ret();
+ }
+
+ a.bind(hashmap);
+ {
+ /* Calculate the internal hash of ARG2 before diving into the HAMT. */
+ a.mov(ARG5, ARG2);
+ a.shr(ARG5, imm(32));
+ a.mov(ARG4d, ARG2d);
+
+ a.mov(ARG3d, imm(INTERNAL_HASH_SALT));
+ a.mov(ARG6d, imm(HCONST));
+ a.call(labels[internal_hash_helper]);
+
+ emit_hashmap_get_element();
+ }
+}
+
+void BeamModuleAssembler::emit_i_get_map_element(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgRegister &Key,
+ const ArgRegister &Dst) {
+ mov_arg(ARG1, Src);
+ mov_arg(ARG2, Key);
+
+ if (masked_types(Key, BEAM_TYPE_MASK_IMMEDIATE) != BEAM_TYPE_NONE &&
+ hasCpuFeature(CpuFeatures::X86::kBMI2)) {
+ safe_fragment_call(ga->get_i_get_map_element_shared());
+ a.jne(resolve_beam_label(Fail));
+ } else {
+ emit_enter_runtime();
+ runtime_call<2>(get_map_element);
+ emit_leave_runtime();
- /*
- * Don't store the result if the destination is the scratch X register.
- * (This instruction was originally a has_map_fields instruction.)
- */
- if (!(Dst.getType() == ArgVal::x && Dst.getValue() == SCRATCH_X_REG)) {
+ emit_test_the_non_value(RET);
+ a.je(resolve_beam_label(Fail));
+ }
+
+ /* Don't store the result if the destination is the scratch X register.
+ * (This instruction was originally a has_map_fields instruction.) */
+ if (!(Dst.isXRegister() && Dst.as<ArgXRegister>().get() == SCRATCH_X_REG)) {
mov_arg(Dst, RET);
}
}
-void BeamModuleAssembler::emit_i_get_map_elements(
- const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_i_get_map_elements(const ArgLabel &Fail,
+ const ArgSource &Src,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ Label generic = a.newLabel(), next = a.newLabel();
Label data = embed_vararg_rodata(args, 0);
- ASSERT(Size.getValue() == args.size());
+ /* We're not likely to gain much from inlining huge extractions, and the
+ * resulting code is quite large, so we'll cut it off after a handful
+ * elements.
+ *
+ * Note that the arguments come in flattened triplets of
+ * `{Key, Dst, KeyHash}` */
+ bool can_inline = args.size() < (8 * 3);
+
+ ASSERT(Size.get() == args.size());
+ ASSERT((Size.get() % 3) == 0);
+
+ for (size_t i = 0; i < args.size(); i += 3) {
+ can_inline &= args[i].isImmed();
+ }
mov_arg(ARG1, Src);
- a.mov(ARG3, E);
- emit_enter_runtime();
+ if (can_inline) {
+ comment("simplified multi-element lookup");
+
+ emit_ptr_val(ARG1, ARG1);
+
+ a.mov(RETd, emit_boxed_val(ARG1, 0, sizeof(Uint32)));
+ a.and_(RETb, imm(_HEADER_MAP_SUBTAG_MASK));
+ a.cmp(RETb, imm(HAMT_SUBTAG_HEAD_FLATMAP));
+ a.jne(generic);
+
+ ERTS_CT_ASSERT(MAP_SMALL_MAP_LIMIT <= ERTS_UINT32_MAX);
+ a.mov(RETd,
+ emit_boxed_val(ARG1, offsetof(flatmap_t, size), sizeof(Uint32)));
+ a.mov(ARG2, emit_boxed_val(ARG1, offsetof(flatmap_t, keys)));
+
+ emit_ptr_val(ARG2, ARG2);
+
+ for (ssize_t i = args.size() - 3; i >= 0; i -= 3) {
+ Label loop = a.newLabel();
+
+ a.bind(loop);
+ {
+ x86::Mem candidate =
+ x86::qword_ptr(ARG2,
+ RET,
+ 3,
+ sizeof(Eterm) - TAG_PRIMARY_BOXED);
+
+ a.dec(RETd);
+ a.jl(resolve_beam_label(Fail));
+
+ const auto &Comparand = args[i];
+ cmp_arg(candidate, Comparand, ARG3);
+ a.short_().jne(loop);
+ }
+
+ /* Don't store the result if the destination is the scratch X
+ * register. (This instruction was originally a has_map_fields
+ * instruction.) */
+ const auto &Dst = args[i + 1];
+ if (!(Dst.isXRegister() &&
+ Dst.as<ArgXRegister>().get() == SCRATCH_X_REG)) {
+ const int value_offset = sizeof(flatmap_t) - TAG_PRIMARY_BOXED;
+ mov_arg(Dst, x86::qword_ptr(ARG1, RET, 3, value_offset), ARG3);
+ }
+ }
+
+ a.short_().jmp(next);
+ }
- mov_imm(ARG4, args.size() / 3);
- a.lea(ARG5, x86::qword_ptr(data));
- load_x_reg_array(ARG2);
- runtime_call<5>(beam_jit_get_map_elements);
+ a.bind(generic);
+ {
+ mov_imm(ARG4, args.size() / 3);
+ a.lea(ARG5, x86::qword_ptr(data));
+ a.mov(ARG3, E);
- emit_leave_runtime();
+ emit_enter_runtime();
- a.test(RET, RET);
- a.je(labels[Fail.getValue()]);
+ load_x_reg_array(ARG2);
+ runtime_call<5>(beam_jit_get_map_elements);
+
+ emit_leave_runtime();
+
+ a.test(RET, RET);
+ a.je(resolve_beam_label(Fail));
+ }
+
+ a.bind(next);
+}
+
+/* ARG1 = map, ARG2 = key, ARG3 = key hash
+ *
+ * Result is returned in RET. ZF is set on success. */
+void BeamGlobalAssembler::emit_i_get_map_element_hash_shared() {
+ Label hashmap = a.newLabel();
+
+ emit_ptr_val(ARG1, ARG1);
+
+ a.mov(RETd, emit_boxed_val(ARG1, 0, sizeof(Uint32)));
+ a.mov(ARG4d, RETd);
+
+ a.and_(ARG4d, imm(_HEADER_MAP_SUBTAG_MASK));
+ a.cmp(ARG4d, imm(HAMT_SUBTAG_HEAD_FLATMAP));
+ a.short_().jne(hashmap);
+
+ emit_flatmap_get_element();
+
+ a.bind(hashmap);
+ emit_hashmap_get_element();
}
-void BeamModuleAssembler::emit_i_get_map_element_hash(const ArgVal &Fail,
- const ArgVal &Src,
- const ArgVal &Key,
- const ArgVal &Hx,
- const ArgVal &Dst) {
+void BeamModuleAssembler::emit_i_get_map_element_hash(const ArgLabel &Fail,
+ const ArgRegister &Src,
+ const ArgConstant &Key,
+ const ArgWord &Hx,
+ const ArgRegister &Dst) {
mov_arg(ARG1, Src);
mov_arg(ARG2, Key);
mov_arg(ARG3, Hx);
- emit_enter_runtime();
-
- runtime_call<3>(get_map_element_hash);
-
- emit_leave_runtime();
+ if (Key.isImmed() && hasCpuFeature(CpuFeatures::X86::kBMI2)) {
+ safe_fragment_call(ga->get_i_get_map_element_hash_shared());
+ a.jne(resolve_beam_label(Fail));
+ } else {
+ emit_enter_runtime();
+ runtime_call<3>(get_map_element_hash);
+ emit_leave_runtime();
- emit_test_the_non_value(RET);
- a.je(labels[Fail.getValue()]);
+ emit_test_the_non_value(RET);
+ a.je(resolve_beam_label(Fail));
+ }
- /*
- * Don't store the result if the destination is the scratch X register.
- * (This instruction was originally a has_map_fields instruction.)
- */
- if (!(Dst.getType() == ArgVal::x && Dst.getValue() == SCRATCH_X_REG)) {
+ /* Don't store the result if the destination is the scratch X register.
+ * (This instruction was originally a has_map_fields instruction.) */
+ if (!(Dst.isXRegister() && Dst.as<ArgXRegister>().get() == SCRATCH_X_REG)) {
mov_arg(Dst, RET);
}
}
/* ARG3 = live registers, ARG4 = update vector size, ARG5 = update vector. */
void BeamGlobalAssembler::emit_update_map_assoc_shared() {
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -195,23 +518,23 @@ void BeamGlobalAssembler::emit_update_map_assoc_shared() {
runtime_call<5>(erts_gc_update_map_assoc);
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ emit_leave_frame();
a.ret();
}
-void BeamModuleAssembler::emit_update_map_assoc(
- const ArgVal &Src,
- const ArgVal &Dst,
- const ArgVal &Live,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_update_map_assoc(const ArgSource &Src,
+ const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
Label data = embed_vararg_rodata(args, CP_SIZE);
- ASSERT(Size.getValue() == args.size());
+ ASSERT(Size.get() == args.size());
- mov_arg(getXRef(Live.getValue()), Src);
+ mov_arg(getXRef(Live.get()), Src);
- mov_imm(ARG3, Live.getValue());
+ mov_imm(ARG3, Live.get());
mov_imm(ARG4, args.size());
a.lea(ARG5, x86::qword_ptr(data));
fragment_call(ga->get_update_map_assoc_shared());
@@ -223,6 +546,7 @@ void BeamModuleAssembler::emit_update_map_assoc(
*
* Result is returned in RET, error is indicated by ZF. */
void BeamGlobalAssembler::emit_update_map_exact_guard_shared() {
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -230,6 +554,7 @@ void BeamGlobalAssembler::emit_update_map_exact_guard_shared() {
runtime_call<5>(erts_gc_update_map_exact);
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.ret();
@@ -241,6 +566,7 @@ void BeamGlobalAssembler::emit_update_map_exact_guard_shared() {
void BeamGlobalAssembler::emit_update_map_exact_body_shared() {
Label error = a.newLabel();
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -248,6 +574,7 @@ void BeamGlobalAssembler::emit_update_map_exact_body_shared() {
runtime_call<5>(erts_gc_update_map_exact);
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ emit_leave_frame();
emit_test_the_non_value(RET);
a.short_().je(error);
@@ -257,31 +584,30 @@ void BeamGlobalAssembler::emit_update_map_exact_body_shared() {
a.bind(error);
{
mov_imm(ARG4, 0);
- emit_handle_error();
+ a.jmp(labels[raise_exception]);
}
}
-void BeamModuleAssembler::emit_update_map_exact(
- const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Dst,
- const ArgVal &Live,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_update_map_exact(const ArgSource &Src,
+ const ArgLabel &Fail,
+ const ArgRegister &Dst,
+ const ArgWord &Live,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
Label data = embed_vararg_rodata(args, CP_SIZE);
- ASSERT(Size.getValue() == args.size());
+ ASSERT(Size.get() == args.size());
/* We _KNOW_ Src is a map */
- mov_arg(getXRef(Live.getValue()), Src);
+ mov_arg(getXRef(Live.get()), Src);
- mov_imm(ARG3, Live.getValue());
+ mov_imm(ARG3, Live.get());
mov_imm(ARG4, args.size());
a.lea(ARG5, x86::qword_ptr(data));
- if (Fail.getValue() != 0) {
+ if (Fail.get() != 0) {
fragment_call(ga->get_update_map_exact_guard_shared());
- a.je(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(Fail));
} else {
fragment_call(ga->get_update_map_exact_body_shared());
}
diff --git a/erts/emulator/beam/jit/x86/instr_msg.cpp b/erts/emulator/beam/jit/x86/instr_msg.cpp
index a0e4293525..025e834d59 100644
--- a/erts/emulator/beam/jit/x86/instr_msg.cpp
+++ b/erts/emulator/beam/jit/x86/instr_msg.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,19 +74,19 @@ void BeamModuleAssembler::emit_i_recv_set() {
#endif /* ERTS_SUPPORT_OLD_RECV_MARK_INSTRS */
-void BeamModuleAssembler::emit_recv_marker_reserve(const ArgVal &Dst) {
- emit_enter_runtime();
+void BeamModuleAssembler::emit_recv_marker_reserve(const ArgRegister &Dst) {
+ emit_enter_runtime<Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
runtime_call<1>(erts_msgq_recv_marker_insert);
- emit_leave_runtime();
+ emit_leave_runtime<Update::eStack | Update::eHeap>();
mov_arg(Dst, RET);
}
-void BeamModuleAssembler::emit_recv_marker_bind(const ArgVal &Marker,
- const ArgVal &Reference) {
+void BeamModuleAssembler::emit_recv_marker_bind(const ArgRegister &Marker,
+ const ArgRegister &Reference) {
mov_arg(ARG2, Marker);
mov_arg(ARG3, Reference);
@@ -98,7 +98,7 @@ void BeamModuleAssembler::emit_recv_marker_bind(const ArgVal &Marker,
emit_leave_runtime();
}
-void BeamModuleAssembler::emit_recv_marker_clear(const ArgVal &Reference) {
+void BeamModuleAssembler::emit_recv_marker_clear(const ArgRegister &Reference) {
mov_arg(ARG2, Reference);
emit_enter_runtime();
@@ -109,7 +109,7 @@ void BeamModuleAssembler::emit_recv_marker_clear(const ArgVal &Reference) {
emit_leave_runtime();
}
-void BeamModuleAssembler::emit_recv_marker_use(const ArgVal &Reference) {
+void BeamModuleAssembler::emit_recv_marker_use(const ArgRegister &Reference) {
mov_arg(ARG2, Reference);
emit_enter_runtime();
@@ -150,6 +150,8 @@ void BeamGlobalAssembler::emit_i_loop_rec_shared() {
x86::Mem await_addr = TMP_MEM1q, message_ptr = TMP_MEM2q,
get_out = TMP_MEM3d;
+ emit_enter_frame();
+
a.or_(x86::dword_ptr(c_p, offsetof(Process, flags)), imm(F_DELAY_GC));
a.mov(x86::qword_ptr(c_p, offsetof(Process, i)), ARG1);
a.mov(await_addr, ARG2);
@@ -223,7 +225,7 @@ void BeamGlobalAssembler::emit_i_loop_rec_shared() {
* Note that the message queue lock is still held in this case. */
a.and_(x86::dword_ptr(c_p, offsetof(Process, flags)), imm(~F_DELAY_GC));
- emit_discard_cp();
+ emit_unwind_frame();
a.jmp(await_addr);
}
@@ -235,7 +237,7 @@ void BeamGlobalAssembler::emit_i_loop_rec_shared() {
a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), imm(0));
a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), imm(0));
- emit_discard_cp();
+ emit_unwind_frame();
a.jmp(labels[do_schedule]);
}
@@ -269,18 +271,19 @@ void BeamGlobalAssembler::emit_i_loop_rec_shared() {
a.mov(ARG1, x86::qword_ptr(ARG1, offsetof(ErtsMessage, m[0])));
a.mov(getXRef(0), ARG1);
+ emit_leave_frame();
a.ret();
}
}
-void BeamModuleAssembler::emit_i_loop_rec(const ArgVal &Wait) {
+void BeamModuleAssembler::emit_i_loop_rec(const ArgLabel &Wait) {
Label entry = a.newLabel();
align_erlang_cp();
a.bind(entry);
a.lea(ARG1, x86::qword_ptr(entry));
- a.lea(ARG2, x86::qword_ptr(labels[Wait.getValue()]));
+ a.lea(ARG2, x86::qword_ptr(resolve_beam_label(Wait)));
fragment_call(ga->get_i_loop_rec_shared());
}
@@ -301,7 +304,7 @@ void BeamModuleAssembler::emit_remove_message() {
emit_leave_runtime();
}
-void BeamModuleAssembler::emit_loop_rec_end(const ArgVal &Dest) {
+void BeamModuleAssembler::emit_loop_rec_end(const ArgLabel &Dest) {
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -310,35 +313,35 @@ void BeamModuleAssembler::emit_loop_rec_end(const ArgVal &Dest) {
emit_leave_runtime();
a.dec(FCALLS);
- a.jmp(labels[Dest.getValue()]);
+ a.jmp(resolve_beam_label(Dest));
}
-void BeamModuleAssembler::emit_wait_unlocked(const ArgVal &Dest) {
+void BeamModuleAssembler::emit_wait_unlocked(const ArgLabel &Dest) {
emit_enter_runtime();
a.mov(ARG1, c_p);
- a.lea(ARG2, x86::qword_ptr(labels[Dest.getValue()]));
+ a.lea(ARG2, x86::qword_ptr(resolve_beam_label(Dest)));
runtime_call<2>(beam_jit_wait_unlocked);
emit_leave_runtime();
- abs_jmp(ga->get_do_schedule());
+ a.jmp(resolve_fragment(ga->get_do_schedule()));
}
-void BeamModuleAssembler::emit_wait_locked(const ArgVal &Dest) {
+void BeamModuleAssembler::emit_wait_locked(const ArgLabel &Dest) {
emit_enter_runtime();
a.mov(ARG1, c_p);
- a.lea(ARG2, x86::qword_ptr(labels[Dest.getValue()]));
+ a.lea(ARG2, x86::qword_ptr(resolve_beam_label(Dest)));
runtime_call<2>(beam_jit_wait_locked);
emit_leave_runtime();
- abs_jmp(ga->get_do_schedule());
+ a.jmp(resolve_fragment(ga->get_do_schedule()));
}
-void BeamModuleAssembler::emit_wait_timeout_unlocked(const ArgVal &Src,
- const ArgVal &Dest) {
+void BeamModuleAssembler::emit_wait_timeout_unlocked(const ArgSource &Src,
+ const ArgLabel &Dest) {
emit_enter_runtime();
a.mov(ARG1, c_p);
@@ -349,8 +352,8 @@ void BeamModuleAssembler::emit_wait_timeout_unlocked(const ArgVal &Src,
emit_wait_timeout_locked(Src, Dest);
}
-void BeamModuleAssembler::emit_wait_timeout_locked(const ArgVal &Src,
- const ArgVal &Dest) {
+void BeamModuleAssembler::emit_wait_timeout_locked(const ArgSource &Src,
+ const ArgLabel &Dest) {
Label wait = a.newLabel(), next = a.newLabel();
mov_arg(ARG2, Src);
@@ -372,7 +375,7 @@ void BeamModuleAssembler::emit_wait_timeout_locked(const ArgVal &Src,
a.short_().jl(next);
#endif
- emit_handle_error(currLabel, (ErtsCodeMFA *)nullptr);
+ emit_raise_exception(current_label, (ErtsCodeMFA *)nullptr);
a.bind(wait);
emit_wait_locked(Dest);
diff --git a/erts/emulator/beam/jit/x86/instr_select.cpp b/erts/emulator/beam/jit/x86/instr_select.cpp
index 0784eb5bd2..39199d2027 100644
--- a/erts/emulator/beam/jit/x86/instr_select.cpp
+++ b/erts/emulator/beam/jit/x86/instr_select.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,79 +24,89 @@ using namespace asmjit;
void BeamModuleAssembler::emit_linear_search(x86::Gp comparand,
const ArgVal &Fail,
- const std::vector<ArgVal> &args) {
+ const Span<ArgVal> &args) {
int count = args.size() / 2;
for (int i = 0; i < count; i++) {
- const ArgVal &value = args[i];
- const ArgVal &label = args[i + count];
+ const ArgImmed &value = args[i];
+ const ArgLabel &label = args[i + count];
cmp_arg(comparand, value, ARG1);
- a.je(labels[label.getValue()]);
+ a.je(resolve_beam_label(label));
}
- if (Fail.getType() == ArgVal::f) {
- a.jmp(labels[Fail.getValue()]);
+ if (Fail.isLabel()) {
+ a.jmp(resolve_beam_label(Fail));
} else {
/* NIL means fallthrough to the next instruction. */
- ASSERT(Fail.getType() == ArgVal::i && Fail.getValue() == NIL);
+ ASSERT(Fail.isNil());
}
}
-void BeamModuleAssembler::emit_i_select_tuple_arity(
- const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_i_select_tuple_arity(const ArgRegister &Src,
+ const ArgLabel &Fail,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
mov_arg(ARG2, Src);
- emit_is_boxed(labels[Fail.getValue()], ARG2);
+
+ emit_is_boxed(resolve_beam_label(Fail), Src, ARG2);
+
x86::Gp boxed_ptr = emit_ptr_val(ARG2, ARG2);
ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
a.mov(ARG2d, emit_boxed_val(boxed_ptr, 0, sizeof(Uint32)));
- ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
- a.test(ARG2.r8(), imm(_TAG_HEADER_MASK));
- a.jne(labels[Fail.getValue()]);
+
+ if (masked_types(Src, BEAM_TYPE_MASK_BOXED) == BEAM_TYPE_TUPLE) {
+ comment("simplified tuple test since the source is always a tuple "
+ "when boxed");
+ } else {
+ ERTS_CT_ASSERT(_TAG_HEADER_ARITYVAL == 0);
+ a.test(ARG2.r8(), imm(_TAG_HEADER_MASK));
+ a.jne(resolve_beam_label(Fail));
+ }
ERTS_CT_ASSERT(Support::isInt32(make_arityval(MAX_ARITYVAL)));
int count = args.size() / 2;
for (int i = 0; i < count; i++) {
- const ArgVal &value = args[i];
- const ArgVal &label = args[i + count];
+ const ArgImmed &value = args[i];
+ const ArgLabel &label = args[i + count];
- a.cmp(ARG2d, imm(value.getValue()));
- a.je(labels[label.getValue()]);
+ a.cmp(ARG2d, imm(value.get()));
+ a.je(resolve_beam_label(label));
}
- a.jne(labels[Fail.getValue()]);
+ a.jne(resolve_beam_label(Fail));
}
-void BeamModuleAssembler::emit_i_select_val_lins(
- const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
- ASSERT(Size.getValue() == args.size());
+void BeamModuleAssembler::emit_i_select_val_lins(const ArgSource &Src,
+ const ArgVal &Fail,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ ASSERT(Size.get() == args.size());
+
mov_arg(ARG2, Src);
- if (emit_optimized_three_way_select(Fail, args))
+
+ if (emit_optimized_three_way_select(Fail, args)) {
return;
+ }
+
emit_linear_search(ARG2, Fail, args);
}
-void BeamModuleAssembler::emit_i_select_val_bins(
- const ArgVal &Src,
- const ArgVal &Fail,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
- ASSERT(Size.getValue() == args.size());
+void BeamModuleAssembler::emit_i_select_val_bins(const ArgSource &Src,
+ const ArgVal &Fail,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
+ ASSERT(Size.get() == args.size());
+
int count = args.size() / 2;
Label fail;
- if (Fail.getType() == ArgVal::f) {
- fail = labels[Fail.getValue()];
+ if (Fail.isLabel()) {
+ fail = resolve_beam_label(Fail);
} else {
/* NIL means fallthrough to the next instruction. */
- ASSERT(Fail.getType() == ArgVal::i && Fail.getValue() == NIL);
+ ASSERT(Fail.isNil());
fail = a.newLabel();
}
@@ -104,7 +114,7 @@ void BeamModuleAssembler::emit_i_select_val_bins(
comment("Binary search in table of %lu elements", count);
emit_binsearch_nodes(0, count - 1, Fail, args);
- if (Fail.getType() == ArgVal::i) {
+ if (Fail.isNil()) {
a.bind(fail);
}
}
@@ -115,15 +125,15 @@ void BeamModuleAssembler::emit_i_select_val_bins(
*
* ARG2 is the value being looked up.
*/
-void BeamModuleAssembler::emit_binsearch_nodes(
- size_t Left,
- size_t Right,
- const ArgVal &Fail,
- const std::vector<ArgVal> &args) {
+void BeamModuleAssembler::emit_binsearch_nodes(size_t Left,
+ size_t Right,
+ const ArgVal &Fail,
+ const Span<ArgVal> &args) {
ASSERT(Left <= Right);
ASSERT(Right < args.size() / 2);
size_t mid = (Left + Right) >> 1;
- ArgVal midval(ArgVal::i, args[mid].getValue());
+ const ArgImmed midval = args[mid];
+
int count = args.size() / 2;
size_t remaining = (Right - Left + 1);
@@ -147,8 +157,10 @@ void BeamModuleAssembler::emit_binsearch_nodes(
args.begin() + Left + count,
args.begin() + count + Left + remaining);
- if (!emit_optimized_three_way_select(Fail, shrunk))
+ if (!emit_optimized_three_way_select(Fail, shrunk)) {
emit_linear_search(ARG2, Fail, shrunk);
+ }
+
return;
}
@@ -156,15 +168,15 @@ void BeamModuleAssembler::emit_binsearch_nodes(
cmp_arg(ARG2, midval, ARG1);
if (Left == Right) {
- a.je(labels[args[mid + count].getValue()]);
- a.jmp(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(args[mid + count]));
+ a.jmp(resolve_beam_label(Fail));
return;
}
- a.je(labels[args[mid + count].getValue()]);
+ a.je(resolve_beam_label(args[mid + count]));
if (Left == mid) {
- a.jb(labels[Fail.getValue()]);
+ a.jb(resolve_beam_label(Fail));
} else {
Label right_tree = a.newLabel();
a.ja(right_tree);
@@ -175,15 +187,15 @@ void BeamModuleAssembler::emit_binsearch_nodes(
emit_binsearch_nodes(mid + 1, Right, Fail, args);
}
-void BeamModuleAssembler::emit_i_jump_on_val(const ArgVal &Src,
+void BeamModuleAssembler::emit_i_jump_on_val(const ArgSource &Src,
const ArgVal &Fail,
- const ArgVal &Base,
- const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+ const ArgWord &Base,
+ const ArgWord &Size,
+ const Span<ArgVal> &args) {
Label data = embed_vararg_rodata(args, 0);
Label fail;
- ASSERT(Size.getValue() == args.size());
+ ASSERT(Size.get() == args.size());
mov_arg(ARG1, Src);
@@ -191,29 +203,30 @@ void BeamModuleAssembler::emit_i_jump_on_val(const ArgVal &Src,
a.and_(RETb, imm(_TAG_IMMED1_MASK));
a.cmp(RETb, imm(_TAG_IMMED1_SMALL));
- if (Fail.getType() == ArgVal::f) {
- a.jne(labels[Fail.getValue()]);
+ if (Fail.isLabel()) {
+ a.jne(resolve_beam_label(Fail));
} else {
/* NIL means fallthrough to the next instruction. */
- ASSERT(Fail.getType() == ArgVal::i && Fail.getValue() == NIL);
+ ASSERT(Fail.isNil());
+
fail = a.newLabel();
a.short_().jne(fail);
}
a.sar(ARG1, imm(_TAG_IMMED1_SIZE));
- if (Base.getValue() != 0) {
- if (Support::isInt32((Sint)Base.getValue())) {
- a.sub(ARG1, imm(Base.getValue()));
+ if (Base.get() != 0) {
+ if (Support::isInt32((Sint)Base.get())) {
+ a.sub(ARG1, imm(Base.get()));
} else {
- a.mov(ARG2, imm(Base.getValue()));
+ a.mov(ARG2, imm(Base.get()));
a.sub(ARG1, ARG2);
}
}
a.cmp(ARG1, imm(args.size()));
- if (Fail.getType() == ArgVal::f) {
- a.jae(labels[Fail.getValue()]);
+ if (Fail.isLabel()) {
+ a.jae(resolve_beam_label(Fail));
} else {
a.short_().jae(fail);
}
@@ -221,7 +234,7 @@ void BeamModuleAssembler::emit_i_jump_on_val(const ArgVal &Src,
a.lea(RET, x86::qword_ptr(data));
a.jmp(x86::qword_ptr(RET, ARG1, 3));
- if (Fail.getType() == ArgVal::i) {
+ if (Fail.isNil()) {
a.bind(fail);
}
}
@@ -241,15 +254,16 @@ void BeamModuleAssembler::emit_i_jump_on_val(const ArgVal &Src,
*/
bool BeamModuleAssembler::emit_optimized_three_way_select(
const ArgVal &Fail,
- const std::vector<ArgVal> &args) {
- if (args.size() != 4 || (args[2].getValue() != args[3].getValue()))
+ const Span<ArgVal> &args) {
+ if (args.size() != 4 || (args[2] != args[3])) {
return false;
+ }
- uint64_t x = args[0].getValue();
- uint64_t y = args[1].getValue();
+ uint64_t x = args[0].as<ArgImmed>().get();
+ uint64_t y = args[1].as<ArgImmed>().get();
uint64_t combined = x | y;
uint64_t diff = x ^ y;
- ArgVal val(ArgVal::i, combined);
+ ArgVal val(ArgVal::Immediate, combined);
if ((diff & (diff - 1)) != 0)
return false;
@@ -265,13 +279,16 @@ bool BeamModuleAssembler::emit_optimized_three_way_select(
a.mov(ARG1, imm(diff));
a.or_(ARG2, ARG1);
}
+
cmp_arg(ARG2, val, ARG1);
- a.je(labels[args[2].getValue()]);
- if (Fail.getType() == ArgVal::f) {
- a.jmp(labels[Fail.getValue()]);
+ a.je(resolve_beam_label(args[2]));
+
+ if (Fail.isLabel()) {
+ a.jmp(resolve_beam_label(Fail));
} else {
/* NIL means fallthrough to the next instruction. */
- ASSERT(Fail.getType() == ArgVal::i && Fail.getValue() == NIL);
+ ASSERT(Fail.isNil());
}
+
return true;
}
diff --git a/erts/emulator/beam/jit/x86/instr_trace.cpp b/erts/emulator/beam/jit/x86/instr_trace.cpp
index 02f76300f0..f3a825775d 100644
--- a/erts/emulator/beam/jit/x86/instr_trace.cpp
+++ b/erts/emulator/beam/jit/x86/instr_trace.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2020-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ extern "C"
*
* RET = export entry */
void BeamGlobalAssembler::emit_generic_bp_global() {
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -40,6 +41,10 @@ void BeamGlobalAssembler::emit_generic_bp_global() {
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ /* This is technically a tail call so we must leave the current frame
+ * before jumping. Note that we might not leave the frame we entered
+ * earlier this function, but one added by `erts_generic_breakpoint`. */
+ emit_leave_frame();
a.jmp(RET);
}
@@ -52,8 +57,14 @@ void BeamGlobalAssembler::emit_generic_bp_local() {
emit_assert_erlang_stack();
#ifdef NATIVE_ERLANG_STACK
- /* Since we've entered here on the Erlang stack, we need to stash our return
- * addresses in case `erts_generic_breakpoint` pushes any trace frames. */
+ /* Since we've entered here on the Erlang stack, we need to stash our
+ * return addresses in case `erts_generic_breakpoint` pushes any trace
+ * frames.
+ *
+ * Note that both of these are return addresses even when frame pointers
+ * are enabled due to the way the breakpoint trampoline works. They must
+ * not be restored until we're ready to return to module code, lest we
+ * leave the stack in an inconsistent state. */
a.pop(TMP_MEM2q);
a.pop(ARG2);
#else
@@ -81,6 +92,7 @@ void BeamGlobalAssembler::emit_generic_bp_local() {
}
#endif
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
@@ -90,14 +102,21 @@ void BeamGlobalAssembler::emit_generic_bp_local() {
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
+ /* This doesn't necessarily leave the frame entered above: see the
+ * corresponding comment in `generic_bp_global` */
+ emit_leave_frame();
+
+ a.cmp(RET, imm(BeamOpCodeAddr(op_i_debug_breakpoint)));
+ a.je(labels[debug_bp]);
+
+ /* Note that we don't restore our return addresses in the `debug_bp` case
+ * above, since it tail calls the error handler and thus never returns to
+ * module code or `call_nif_early`. */
#ifdef NATIVE_ERLANG_STACK
a.push(TMP_MEM1q);
a.push(TMP_MEM2q);
#endif
- a.cmp(RET, imm(BeamOpCodeAddr(op_i_debug_breakpoint)));
- a.je(labels[debug_bp]);
-
a.ret();
}
@@ -110,6 +129,7 @@ void BeamGlobalAssembler::emit_debug_bp() {
emit_assert_erlang_stack();
+ emit_enter_frame();
emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
/* Read and adjust the return address we saved in generic_bp_local. */
@@ -123,23 +143,17 @@ void BeamGlobalAssembler::emit_debug_bp() {
runtime_call<4>(call_error_handler);
emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>();
-
- /* Skip two frames so we can make a direct jump to the error handler. This
- * makes it so that if we are to do a call_nif_early, we skip that and call
- * the error handler's code instead, mirroring the way the interpreter
- * works. */
- emit_discard_cp();
- emit_discard_cp();
+ emit_leave_frame();
a.test(RET, RET);
a.je(error);
- a.jmp(emit_setup_export_call(RET));
+ a.jmp(emit_setup_dispatchable_call(RET));
a.bind(error);
{
a.mov(ARG2, TMP_MEM1q);
- a.jmp(labels[handle_error_shared]);
+ a.jmp(labels[raise_exception]);
}
}
@@ -164,7 +178,7 @@ void BeamModuleAssembler::emit_return_trace() {
emit_leave_runtime<Update::eStack | Update::eHeap>();
- emit_deallocate(ArgVal(ArgVal::u, 2));
+ emit_deallocate(ArgWord(2));
emit_return();
}
@@ -184,49 +198,21 @@ void BeamModuleAssembler::emit_i_return_time_trace() {
emit_leave_runtime<Update::eStack | Update::eHeap>();
- emit_deallocate(ArgVal(ArgVal::u, 1));
+ emit_deallocate(ArgWord(1));
emit_return();
}
-static void i_return_to_trace(Process *c_p) {
- if (IS_TRACED_FL(c_p, F_TRACE_RETURN_TO)) {
- Uint *cpp = (Uint *)c_p->stop;
- while (is_not_CP(*cpp)) {
- cpp++;
- }
- for (;;) {
- ErtsCodePtr w = cp_val(*cpp);
- if (BeamIsReturnTrace(w)) {
- do
- ++cpp;
- while (is_not_CP(*cpp));
- cpp += 2;
- } else if (BeamIsReturnToTrace(w)) {
- do
- ++cpp;
- while (is_not_CP(*cpp));
- } else {
- break;
- }
- }
- ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
- erts_trace_return_to(c_p, cp_val(*cpp));
- ERTS_REQ_PROC_MAIN_LOCK(c_p);
- }
-}
-
void BeamModuleAssembler::emit_i_return_to_trace() {
emit_enter_runtime<Update::eStack | Update::eHeap>();
a.mov(ARG1, c_p);
- runtime_call<1>(i_return_to_trace);
+ runtime_call<1>(beam_jit_return_to_trace);
emit_leave_runtime<Update::eStack | Update::eHeap>();
/* Remove the zero-sized stack frame. (Will actually do nothing if
* the native stack is used.) */
- emit_deallocate(ArgVal(ArgVal::u, 0));
-
+ emit_deallocate(ArgWord(0));
emit_return();
}
@@ -247,8 +233,8 @@ void BeamModuleAssembler::emit_i_hibernate() {
a.mov(ARG1, x86::qword_ptr(c_p, offsetof(Process, flags)));
a.and_(ARG1, imm(~F_HIBERNATE_SCHED));
a.mov(x86::qword_ptr(c_p, offsetof(Process, flags)), ARG1);
- abs_jmp(ga->get_do_schedule());
+ a.jmp(resolve_fragment(ga->get_do_schedule()));
a.bind(error);
- emit_handle_error(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa);
+ emit_raise_exception(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa);
}
diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab
index d917d6b87b..5481fff2d8 100644
--- a/erts/emulator/beam/jit/x86/ops.tab
+++ b/erts/emulator/beam/jit/x86/ops.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ FORBIDDEN_TYPES=hQ
# needs to be re-compiled with a modern compiler.
too_old_compiler/0
-too_old_compiler | never() =>
+too_old_compiler | never() => _
# In R9C and earlier, the loader used to insert special instructions inside
# the module_info/0,1 functions. (In R10B and later, the compiler inserts
@@ -45,8 +45,10 @@ too_old_compiler | never() =>
# necessary.) Since the instructions don't work correctly in R12B, simply
# refuse to load the module.
-func_info M=a a==am_module_info A=u==0 | label L | move n x==0 => too_old_compiler
-func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compiler
+func_info M=a a==am_module_info A=u==0 | label L | move n x==0 =>
+ too_old_compiler
+func_info M=a a==am_module_info A=u==1 | label L | move n x==0 =>
+ too_old_compiler
# The undocumented and unsupported guard BIF is_constant/1 was removed
# in R13. The is_constant/2 operation is marked as obsolete in genop.tab,
@@ -55,12 +57,6 @@ func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compil
bif1 Fail u$func:erlang:is_constant/1 Src Dst => too_old_compiler
-# Since the constant pool was introduced in R12B, empty tuples ({})
-# are literals. Therefore we no longer need to allow put_tuple/2
-# with a tuple size of zero.
-
-put_tuple u==0 d => too_old_compiler
-
#
# All the other instructions.
#
@@ -81,6 +77,7 @@ aligned_label L t
i_func_info I a a I
int_code_end
+nif_start
i_generic_breakpoint
i_debug_breakpoint
@@ -97,14 +94,14 @@ return
# BIF, so we can omit the line instruction for non-BIFs.
#
-move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D => \
+move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D =>
move S X0 | call_ext_last Ar Func D
-move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif => \
+move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif =>
move S X0 | call_ext_only Ar Func
-move S X0=x==0 | line Loc | call_last Ar Func D => \
+move S X0=x==0 | line Loc | call_last Ar Func D =>
move S X0 | call_last Ar Func D
-move S X0=x==0 | line Loc | call_only Ar Func => \
+move S X0=x==0 | line Loc | call_only Ar Func =>
move S X0 | call_only Ar Func
# The line number in int_func_start/5 can be NIL.
@@ -113,11 +110,11 @@ func_line n => empty_func_line
empty_func_line
func_line I
-line n =>
+line n => _
line I
-allocate t t?
-allocate_heap t I t?
+allocate t t
+allocate_heap t I t
deallocate t
@@ -127,7 +124,7 @@ trim N Remaining => i_trim N
i_trim t
-test_heap I t?
+test_heap I t
# Translate instructions generated by a compiler before OTP 24.
allocate_zero Ns Live => allocate_heap_zero Ns u Live
@@ -141,59 +138,74 @@ init_yregs I *
# bytes. Therefore we shouldn't use a jump table if there are too few
# values.
-select_val S Fail=fn Size=u Rest=* | use_jump_tab(Size, Rest, 6) => \
- jump_tab(S, Fail, Size, Rest)
-is_integer Fail=f S | select_val S=s Fail=fn Size=u Rest=* | use_jump_tab(Size, Rest, 6) => \
- jump_tab(S, Fail, Size, Rest)
+select_val S Fail=fn Size=u Rest=* | use_jump_tab(Size, Rest, 6) =>
+ jump_tab(S, Fail, Size, Rest)
+
+is_integer Fail=f S | select_val S2=s Fail2=fn Size=u Rest=* |
+ equal(S, S2) | equal(Fail, Fail2) |
+ use_jump_tab(Size, Rest, 6) =>
+ jump_tab(S, Fail, Size, Rest)
-is_integer TypeFail=f S | select_val S=s Fail=fn Size=u Rest=* | \
- mixed_types(Size, Rest) => \
- split_values(S, TypeFail, Fail, Size, Rest)
+is_integer TypeFail=f S | select_val S2=s Fail=fn Size=u Rest=* |
+ equal(S, S2) |
+ mixed_types(Size, Rest) =>
+ split_values(S, TypeFail, Fail, Size, Rest)
-select_val S Fail=fn Size=u Rest=* | mixed_types(Size, Rest) => \
- split_values(S, Fail, Fail, Size, Rest)
+select_val S Fail=fn Size=u Rest=* | mixed_types(Size, Rest) =>
+ split_values(S, Fail, Fail, Size, Rest)
-is_integer Fail=f S | select_val S=d Fail=fn Size=u Rest=* | \
- fixed_size_values(Size, Rest) => select_val(S, Fail, Size, Rest)
+is_integer Fail=f S | select_val S2=d Fail2=fn Size=u Rest=* |
+ equal(S, S2) | equal(Fail, Fail2) |
+ fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
-is_atom Fail=f S | select_val S=d Fail=fn Size=u Rest=* | \
- fixed_size_values(Size, Rest) => select_val(S, Fail, Size, Rest)
+is_atom Fail=f S | select_val S2=d Fail2=fn Size=u Rest=* |
+ equal(S, S2) | equal(Fail, Fail2) |
+ fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
-select_val S Fail=fn Size=u Rest=* | floats_or_bignums(Size, Rest) => \
- select_literals(S, Fail, Size, Rest)
+select_val S Fail=fn Size=u Rest=* | floats_or_bignums(Size, Rest) =>
+ select_literals(S, Fail, Size, Rest)
-select_val S Fail=fn Size=u Rest=* | fixed_size_values(Size, Rest) => \
- select_val(S, Fail, Size, Rest)
+select_val S Fail=fn Size=u Rest=* | fixed_size_values(Size, Rest) =>
+ select_val(S, Fail, Size, Rest)
-is_tuple Fail=f S | select_tuple_arity S=d Fail=f Size=u Rest=* => \
- select_tuple_arity(S, Fail, Size, Rest)
+is_tuple Fail=f S | select_tuple_arity S2=d Fail2=f Size=u Rest=* |
+ equal(S, S2) | equal(Fail, Fail2) =>
+ select_tuple_arity(S, Fail, Size, Rest)
-select_tuple_arity S=d Fail=f Size=u Rest=* => \
- select_tuple_arity(S, Fail, Size, Rest)
+select_tuple_arity S=d Fail=f Size=u Rest=* =>
+ select_tuple_arity(S, Fail, Size, Rest)
i_select_val_bins s fn I *
i_select_val_lins s fn I *
-i_select_tuple_arity S f? I *
+i_select_tuple_arity S f I *
i_jump_on_val s fn W I *
-is_number f? s
+is_number f s
jump f
#
-# List matching instructions. The combination of test for a nonempty list followed
-# by get_{list/hd/tl} are common, so we will optimize that.
+# List matching instructions. The combination of test for a nonempty list
+# followed by get_{list/hd/tl} are common, so we will optimize that.
#
is_nonempty_list Fail nqia => jump Fail
-is_nonempty_list Fail Src | get_list Src Hd Tl => is_nonempty_list_get_list Fail Src Hd Tl
-is_nonempty_list Fail Src | get_hd Src Hd => is_nonempty_list_get_hd Fail Src Hd
-is_nonempty_list Fail Src | get_tl Src Tl => is_nonempty_list_get_tl Fail Src Tl
-is_nonempty_list f? S
+is_nonempty_list Fail Src | get_list Src2 Hd Tl | equal(Src, Src2) =>
+ is_nonempty_list_get_list Fail Src Hd Tl
+
+is_nonempty_list Fail Src | get_hd Src2 Hd | equal(Src, Src2) =>
+ is_nonempty_list_get_hd Fail Src Hd
+
+is_nonempty_list Fail Src | get_tl Src2 Tl | equal(Src, Src2) =>
+ is_nonempty_list_get_tl Fail Src Tl
+
+is_nonempty_list f S
get_list S d d
get_hd S d
@@ -221,63 +233,79 @@ set_tuple_element s S P
#
# Get tuple element. Since this instruction is frequently used, we will try
-# to only fetch the pointer to the tuple once for a sequence of BEAM instructions
-# that fetch multiple elements from the same tuple.
+# to only fetch the pointer to the tuple once for a sequence of BEAM
+# instructions that fetch multiple elements from the same tuple.
#
current_tuple/1
current_tuple/2
-is_tuple Fail=f Src | test_arity Fail Src Arity => \
- i_is_tuple_of_arity Fail Src Arity | current_tuple Src
+is_tuple Fail=f Src | test_arity Fail2 Src2 Arity |
+ equal(Fail, Fail2) | equal(Src, Src2) =>
+ i_is_tuple_of_arity Fail Src Arity | current_tuple Src
test_arity Fail Src Arity => i_test_arity Fail Src Arity | current_tuple Src
-is_tuple NotTupleFail Tuple | is_tagged_tuple WrongRecordFail Tuple Arity Atom => \
- i_is_tagged_tuple_ff NotTupleFail WrongRecordFail Tuple Arity Atom | current_tuple Tuple
+is_tuple NotTupleFail Src |
+ is_tagged_tuple WrongRecordFail Tuple Arity Atom |
+ equal(Src, Tuple) =>
+ i_is_tagged_tuple_ff NotTupleFail WrongRecordFail Src Arity Atom |
+ current_tuple Src
-is_tagged_tuple Fail Tuple Arity Atom => \
- i_is_tagged_tuple Fail Tuple Arity Atom | current_tuple Tuple
+is_tagged_tuple Fail Tuple Arity Atom =>
+ i_is_tagged_tuple Fail Tuple Arity Atom | current_tuple Tuple
is_tuple Fail=f Src => i_is_tuple Fail Src | current_tuple Src
-i_is_tuple_of_arity f? s A
-i_test_arity f? s A
+i_is_tuple_of_arity f s A
+i_test_arity f s A
-i_is_tagged_tuple f? s A a
-i_is_tagged_tuple_ff f? f? s A a
+i_is_tagged_tuple f s A a
+i_is_tagged_tuple_ff f f s A a
-i_is_tuple f? s
+i_is_tuple f s
# Generate instruction sequence for fetching the tuple element and remember
# that we have a current tuple pointer.
-get_tuple_element Tuple Pos Dst => \
- load_tuple_ptr Tuple | i_get_tuple_element Tuple Pos Dst | current_tuple Tuple
-current_tuple Tuple | get_tuple_element Tuple Pos Dst => \
- i_get_tuple_element Tuple Pos Dst | current_tuple Tuple
+get_tuple_element Tuple Pos Dst =>
+ load_tuple_ptr Tuple |
+ i_get_tuple_element Tuple Pos Dst |
+ current_tuple Tuple
+
+current_tuple Tuple | get_tuple_element Tuple2 Pos Dst |
+ equal(Tuple, Tuple2) =>
+ i_get_tuple_element Tuple Pos Dst | current_tuple Tuple
# Drop the current_tuple instruction if the tuple is overwritten.
-i_get_tuple_element Tuple Pos Tuple | current_tuple Tuple => i_get_tuple_element Tuple Pos Tuple
+i_get_tuple_element Tuple Pos Tuple2 | current_tuple Tuple3 |
+ equal(Tuple, Tuple2) | equal(Tuple, Tuple3) =>
+ i_get_tuple_element Tuple Pos Tuple
-# This is a current_tuple instruction instruction not followed by get_tuple_element.
-# Invalidate the current tuple pointer.
+# This is a current_tuple instruction instruction not followed by
+# get_tuple_element. Invalidate the current tuple pointer.
-current_tuple Tuple =>
+current_tuple Tuple => _
load_tuple_ptr s
# If both positions and destinations are in consecutive memory, fetch and store
# two words at once.
-i_get_tuple_element Tuple Pos1 Dst1 | current_tuple Tuple | \
- get_tuple_element Tuple Pos2 Dst2 | consecutive_words(Pos1, Dst1, Pos2, Dst2) => \
- get_two_tuple_elements Tuple Pos1 Dst1 Dst2 | current_tuple Tuple Dst2
-i_get_tuple_element Tuple Pos1 Dst1 | current_tuple Tuple | \
- get_tuple_element Tuple Pos2 Dst2 | consecutive_words(Pos1, Dst2, Pos2, Dst1) => \
- get_two_tuple_elements Tuple Pos1 Dst1 Dst2 | current_tuple Tuple Dst2
+i_get_tuple_element Tuple Pos1 Dst1 |
+ current_tuple Tuple2 |
+ get_tuple_element Tuple3 Pos2 Dst2 |
+ equal(Tuple, Tuple2) | equal(Tuple, Tuple3) |
+ consecutive_words(Pos1, Dst1, Pos2, Dst2) =>
+ get_two_tuple_elements Tuple Pos1 Dst1 Dst2 | current_tuple Tuple Dst2
+
+i_get_tuple_element Tuple Pos1 Dst1 | current_tuple Tuple2 |
+ get_tuple_element Tuple3 Pos2 Dst2 |
+ equal(Tuple, Tuple2) | equal(Tuple, Tuple3) |
+ consecutive_words(Pos1, Dst2, Pos2, Dst1) =>
+ get_two_tuple_elements Tuple Pos1 Dst1 Dst2 | current_tuple Tuple Dst2
# Drop the current_tuple instruction if the tuple is overwritten.
-current_tuple Tuple Tuple =>
+current_tuple Tuple Tuple2 | equal(Tuple, Tuple2) => _
current_tuple Tuple Dst => current_tuple Tuple
# The first operand will only be used in the debug-compiled runtime
@@ -287,7 +315,7 @@ i_get_tuple_element s P S
get_two_tuple_elements s P S S
#
-# Expection rasing instructions. Infrequently executed.
+# Exception raising instructions. Infrequently executed.
#
%cold
@@ -297,11 +325,14 @@ badmatch s
if_end
+badrecord s
+
raise s s
-# Workaround the limitation that generators must always return at least one instruction.
+# Workaround the limitation that generators must always return at least one
+# instruction.
delete_me/0
-delete_me =>
+delete_me => _
system_limit/1
system_limit p => system_limit_body
@@ -317,16 +348,21 @@ system_limit_body
move Src=c Dst => i_move Src Dst
-move Src SrcDst | move SrcDst Dst => i_move Src SrcDst | move SrcDst Dst
+move Src SrcDst | move SrcDst2 Dst | equal(SrcDst, SrcDst2) =>
+ i_move Src SrcDst | move SrcDst Dst
# Try to move two words at once. Always arrange the source operands in
# consecutive order; the destination operands may be in consecutive or
# reverse consecutive order.
-move S1=d D1=d | move S2=d D2=d | consecutive_words(S1, D1, S2, D2) => move_two_words S1 D1 S2 D2
-move S1=d D1=d | move S2=d D2=d | consecutive_words(S1, D2, S2, D1) => move_two_words S1 D1 S2 D2
-move S1=d D1=d | move S2=d D2=d | consecutive_words(S2, D1, S1, D2) => move_two_words S2 D2 S1 D1
-move S1=d D1=d | move S2=d D2=d | consecutive_words(S2, D2, S1, D1) => move_two_words S2 D2 S1 D1
+move S1=d D1=d | move S2=d D2=d | consecutive_words(S1, D1, S2, D2) =>
+ move_two_words S1 D1 S2 D2
+move S1=d D1=d | move S2=d D2=d | consecutive_words(S1, D2, S2, D1) =>
+ move_two_words S1 D1 S2 D2
+move S1=d D1=d | move S2=d D2=d | consecutive_words(S2, D1, S1, D2) =>
+ move_two_words S2 D2 S1 D1
+move S1=d D1=d | move S2=d D2=d | consecutive_words(S2, D2, S1, D1) =>
+ move_two_words S2 D2 S1 D1
move Src Dst => i_move Src Dst
@@ -347,26 +383,26 @@ move_two_words s d s d
# pointers.
#
-label L | loop_rec Fail Reg => \
+label L | loop_rec Fail Reg =>
aligned_label L u=4 | loop_rec Fail Reg
-label L | wait_timeout Fail Src => \
+label L | wait_timeout Fail Src =>
aligned_label L u=4 | wait_timeout Fail Src
-label L | wait Fail => \
+label L | wait Fail =>
aligned_label L u=4 | wait Fail
-label L | timeout => \
+label L | timeout =>
aligned_label L u=4 | timeout
loop_rec Fail x==0 | smp_mark_target_label(Fail) => i_loop_rec Fail
-aligned_label L A | wait_timeout Fail Src | smp_already_locked(L) => \
+aligned_label L A | wait_timeout Fail Src | smp_already_locked(L) =>
aligned_label L A | wait_timeout_locked Src Fail
wait_timeout Fail Src => wait_timeout_unlocked Src Fail
-aligned_label L A | wait Fail | smp_already_locked(L) => \
+aligned_label L A | wait Fail | smp_already_locked(L) =>
aligned_label L A | wait_locked Fail
wait Fail => wait_unlocked Fail
-aligned_label L A | timeout | smp_already_locked(L) => \
+aligned_label L A | timeout | smp_already_locked(L) =>
aligned_label L A | timeout_locked
remove_message
@@ -387,40 +423,34 @@ send
# Optimized comparisons with one immediate/literal operand.
#
-is_eq_exact Lbl S S =>
+is_eq_exact Lbl LHS RHS | equal(LHS, RHS) => _
is_eq_exact Lbl C=c R=xy => is_eq_exact Lbl R C
is_eq_exact Lbl R=xy n => is_nil Lbl R
-is_eq_exact Lbl R=xy C=ia => i_is_eq_exact_immed Lbl R C
is_eq_exact Lbl R=xy C=q => is_eq_exact_literal(Lbl, R, C)
-is_ne_exact Lbl S S => jump Lbl
+is_ne_exact Lbl LHS RHS | equal(LHS, RHS) => jump Lbl
is_ne_exact Lbl C=c R=xy => is_ne_exact Lbl R C
-is_ne_exact Lbl R=xy C=ian => i_is_ne_exact_immed Lbl R C
is_ne_exact Lbl R=xy C=q => i_is_ne_exact_literal Lbl R C
-i_is_eq_exact_immed f? s c
-
i_is_eq_exact_literal/4
-i_is_eq_exact_literal f? s c I
+i_is_eq_exact_literal f s c I
-i_is_ne_exact_immed f? s c
+i_is_ne_exact_literal f s c
-i_is_ne_exact_literal f? s c
+is_eq_exact f s s
-is_eq_exact f? s s
+is_ne_exact f s s
-is_ne_exact f? s s
-
-is_lt f? s s
-is_ge f? s s
+is_lt f s s
+is_ge f s s
is_eq Fail=f Const=c Reg=xy => is_eq Fail Reg Const
-is_eq f? s s
+is_eq f s s
is_ne Fail=f Const=c Reg=xy => is_ne Fail Reg Const
-is_ne f? s s
+is_ne f s s
#
# Putting tuples.
@@ -428,21 +458,6 @@ is_ne f? s s
# Code compiled with OTP 22 and later uses put_tuple2 to
# to construct a tuple.
#
-# Code compiled before OTP 22 uses put_tuple + one put instruction
-# per element. Translate to put_tuple2.
-#
-
-i_put_tuple/2
-put_tuple Arity Dst => i_put_tuple Dst u
-
-i_put_tuple Dst Arity Puts=* | put S1 | put S2 | \
- put S3 | put S4 | put S5 => \
- tuple_append_put5(Arity, Dst, Puts, S1, S2, S3, S4, S5)
-
-i_put_tuple Dst Arity Puts=* | put S => \
- tuple_append_put(Arity, Dst, Puts, S)
-
-i_put_tuple Dst Arity Puts=* => put_tuple2 Dst Arity Puts
put_tuple2 S A *
@@ -452,8 +467,13 @@ put_tuple2 S A *
store_cons/2
put_list Hd Tl Dst => put_cons Hd Tl | store_cons u=1 Dst
-store_cons Len Dst | put_list Hd Dst Dst | distinct(Dst, Hd) => combine_conses(Len, Dst, Hd)
-store_cons Len Dst | put_list Hd Dst OtherDst => store_cons Len Dst | append_cons u Hd | store_cons u=1 OtherDst
+
+store_cons Len Dst | put_list Hd Tl Dst2 |
+ equal(Dst, Tl) | equal(Dst, Dst2) | distinct(Dst, Hd) =>
+ combine_conses(Len, Dst, Hd)
+
+store_cons Len Dst | put_list Hd Tl OtherDst | equal(Dst, Tl) =>
+ store_cons Len Dst | append_cons u Hd | store_cons u=1 OtherDst
put_cons s s
append_cons I s
@@ -470,7 +490,6 @@ call_bif W
call_bif_mfa a a I
call_nif W W W
call_error_handler
-error_action_code
return_trace
%hot
@@ -482,28 +501,28 @@ return_trace
# older releases and code generated by alternative code generators.
#
-is_integer f? s
-is_list f? s
-is_atom f? s
-is_float f? s
+is_integer f s
+is_list f s
+is_atom f s
+is_float f s
-is_nil Fail=f n =>
+is_nil Fail=f n => _
is_nil Fail=f qia => jump Fail
-is_nil f? S
+is_nil f S
# XXX Deprecated.
is_bitstr Fail Term => is_bitstring Fail Term
-is_binary f? s
-is_bitstring f? s
+is_binary f s
+is_bitstring f s
-is_reference f? s
-is_pid f? s
-is_port f? s
+is_reference f s
+is_pid f s
+is_port f s
-is_boolean f? s
+is_boolean f s
-is_function2 f? s s
+is_function2 f s s
#################################################################
# External function and bif calls.
@@ -516,11 +535,11 @@ call_light_bif/1
# The load_nif/2 BIF is an instruction.
#
-call_ext u==2 u$func:erlang:load_nif/2 => \
+call_ext u==2 u$func:erlang:load_nif/2 =>
i_load_nif
-call_ext_last u==2 u$func:erlang:load_nif/2 D => \
+call_ext_last u==2 u$func:erlang:load_nif/2 D =>
i_load_nif | deallocate D | return
-call_ext_only u==2 u$func:erlang:load_nif/2 => \
+call_ext_only u==2 u$func:erlang:load_nif/2 =>
i_load_nif | return
%cold
@@ -528,6 +547,21 @@ i_load_nif
%hot
#
+# The call_on_load_function/1 BIF is an instruction.
+#
+
+call_ext u==1 u$func:erlang:call_on_load_function/1 =>
+ i_call_on_load_function
+call_ext_last u==1 u$func:erlang:call_on_load_function/1 D =>
+ i_call_on_load_function | deallocate D | return
+call_ext_only u==1 u$func:erlang:call_on_load_function/1 =>
+ i_call_on_load_function | return
+
+%cold
+i_call_on_load_function
+%hot
+
+#
# apply/2 is an instruction, not a BIF.
#
@@ -558,11 +592,11 @@ call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate
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
-call_ext u==0 u$func:os:perf_counter/0 => \
+call_ext u==0 u$func:os:perf_counter/0 =>
i_perf_counter
-call_ext_last u==0 u$func:os:perf_counter/0 D => \
+call_ext_last u==0 u$func:os:perf_counter/0 D =>
i_perf_counter | deallocate D | return
-call_ext_only u==0 u$func:os:perf_counter/0 => \
+call_ext_only u==0 u$func:os:perf_counter/0 =>
i_perf_counter | return
#
@@ -570,22 +604,22 @@ call_ext_only u==0 u$func:os:perf_counter/0 => \
# emulator state, which the ordinary call_light_bif instruction doesn't save.
#
-call_ext u Bif=u$is_bif | is_heavy_bif(Bif) => \
+call_ext u Bif=u$is_bif | is_heavy_bif(Bif) =>
i_call_ext Bif
-call_ext_last u Bif=u$is_bif D | is_heavy_bif(Bif) => \
+call_ext_last u Bif=u$is_bif D | is_heavy_bif(Bif) =>
i_call_ext Bif | deallocate D | return
-call_ext_only Ar=u Bif=u$is_bif | is_heavy_bif(Bif) => \
+call_ext_only Ar=u Bif=u$is_bif | is_heavy_bif(Bif) =>
allocate u Ar | i_call_ext Bif | deallocate u | return
#
# The general case for BIFs that have no special requirements.
#
-call_ext u Bif=u$is_bif => \
+call_ext u Bif=u$is_bif =>
call_light_bif Bif
-call_ext_last u Bif=u$is_bif D => \
+call_ext_last u Bif=u$is_bif D =>
call_light_bif Bif | deallocate D | return
-call_ext_only Ar=u Bif=u$is_bif => \
+call_ext_only Ar=u Bif=u$is_bif =>
allocate u Ar | call_light_bif Bif | deallocate u | return
#
@@ -626,25 +660,20 @@ i_perf_counter
bif0 u$bif:erlang:self/0 Dst=d => self Dst
bif0 u$bif:erlang:node/0 Dst=d => node Dst
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=n Dst => \
- jump Fail
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src Dst => \
+bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=xy Dst =>
is_nonempty_list Fail Src | get_hd Src Dst
-bif1 Fail Bif=u$bif:erlang:hd/1 Src Dst => \
- bif_hd Fail Src Dst
+bif1 Fail=p Bif=u$bif:erlang:hd/1 Src Dst =>
+ bif_hd Src Dst
-bif_hd j? s d
+bif_hd s d
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=n Dst => \
- jump Fail
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src Dst => \
+bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=xy Dst =>
is_nonempty_list Fail Src | get_tl Src Dst
bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => get(Src, Dst)
bif2 Fail u$bif:erlang:element/2 S1=ixy S2 Dst => bif_element Fail S1 S2 Dst
-
-bif_element j? s s d
+bif_element j s s d
bif1 Fail Bif S1 Dst | never_fails(Bif) => nofail_bif1 S1 Bif Dst
bif2 Fail Bif S1 S2 Dst | never_fails(Bif) => nofail_bif2 S1 S2 Bif Dst
@@ -652,8 +681,8 @@ bif2 Fail Bif S1 S2 Dst | never_fails(Bif) => nofail_bif2 S1 S2 Bif Dst
bif1 Fail Bif S1 Dst => i_bif1 S1 Fail Bif Dst
bif2 Fail Bif S1 S2 Dst => i_bif2 S1 S2 Fail Bif Dst
-nofail_bif2 S1=d S2=ian Bif Dst | is_eq_exact_bif(Bif) => bif_is_eq_exact_immed S1 S2 Dst
-nofail_bif2 S1=d S2=ian Bif Dst | is_ne_exact_bif(Bif) => bif_is_ne_exact_immed S1 S2 Dst
+nofail_bif2 S1=d S2 Bif Dst | is_eq_exact_bif(Bif) => bif_is_eq_exact S1 S2 Dst
+nofail_bif2 S1=d S2 Bif Dst | is_ne_exact_bif(Bif) => bif_is_ne_exact S1 S2 Dst
i_get_hash c I d
i_get s d
@@ -665,12 +694,12 @@ node d
nofail_bif1 s b d
nofail_bif2 s s b d
-i_bif1 s j? b d
-i_bif2 s s j? b d
-i_bif3 s s s j? b d
+i_bif1 s j b d
+i_bif2 s s j b d
+i_bif3 s s s j b d
-bif_is_eq_exact_immed S c d
-bif_is_ne_exact_immed S c d
+bif_is_eq_exact S s d
+bif_is_ne_exact S s d
#
# Internal calls.
@@ -696,66 +725,77 @@ call_fun Arity => i_call_fun Arity
i_call_fun t
i_call_fun_last t t
+call_fun2 Tag Arity Func | deallocate D | return =>
+ i_call_fun2_last Tag Arity Func D
+call_fun2 Tag Arity Func =>
+ i_call_fun2 Tag Arity Func
+
+i_call_fun2 aF t S
+i_call_fun2_last aF t S t
+
#
# A fun with an empty environment can be converted to a literal.
# As a further optimization, the we try to move the fun to its
# final destination directly.
+#
+
+make_fun2 OldIndex=u =>
+ make_fun2(OldIndex)
-make_fun2 OldIndex=u => make_fun2(OldIndex)
-make_fun3 OldIndex=u Dst=d NumFree=u Env=* => make_fun3(OldIndex, Dst, NumFree, Env)
+make_fun3 OldIndex=u Dst=d NumFree=u Env=* =>
+ make_fun3(OldIndex, Dst, NumFree, Env)
%cold
-i_make_fun3 F S t *
+i_make_fun3 F S t t *
# Psuedo-instruction for signalling lambda load errors. Never actually runs.
i_lambda_error t
%hot
-is_function f? S
+is_function f S
is_function Fail=f c => jump Fail
# The start and end of a function.
int_func_start/5
-int_func_end/0
+int_func_end/2
func_prologue/2
-int_func_start Func_Label Func_Line M F A | \
- label Entry_Label | line Entry_Line => \
- int_func_start Func_Label Func_Line M F A | \
+int_func_start Func_Label Func_Line M F A |
+ label Entry_Label | line Entry_Line =>
+ int_func_start Func_Label Func_Line M F A |
func_prologue Entry_Label Entry_Line
-int_func_start Func_Label Func_Line M F A | \
- label Entry_Label => \
- int_func_start Func_Label Func_Line M F A | \
+int_func_start Func_Label Func_Line M F A |
+ label Entry_Label =>
+ int_func_start Func_Label Func_Line M F A |
func_prologue Entry_Label n
-int_func_start Func_Label Func_Line M F A | \
- func_prologue Entry_Label Entry_Line | \
- is_mfa_bif(M, F, A) => \
- aligned_label Func_Label u=8 | \
- func_line Func_Line | \
- i_func_info Func_Label M F A | \
- aligned_label Entry_Label u=8 | \
- line Entry_Line | \
- i_breakpoint_trampoline | \
+int_func_start Func_Label Func_Line M F A |
+ func_prologue Entry_Label Entry_Line |
+ is_mfa_bif(M, F, A) =>
+ func_line Func_Line |
+ aligned_label Func_Label u=8 |
+ i_func_info Func_Label M F A |
+ aligned_label Entry_Label u=8 |
+ i_breakpoint_trampoline |
+ line Entry_Line |
call_bif_mfa M F A
-int_func_start Func_Label Func_Line M F A | \
- func_prologue Entry_Label Entry_Line => \
- aligned_label Func_Label u=8 | \
- func_line Func_Line | \
- i_func_info Func_Label M F A | \
- aligned_label Entry_Label u=8 | \
- line Entry_Line | \
- i_breakpoint_trampoline | \
+int_func_start Func_Label Func_Line M F A |
+ func_prologue Entry_Label Entry_Line =>
+ func_line Func_Line |
+ aligned_label Func_Label u=8 |
+ i_func_info Func_Label M F A |
+ aligned_label Entry_Label u=8 |
+ i_breakpoint_trampoline |
+ line Entry_Line |
i_test_yield
-
-int_func_end | needs_nif_padding() => i_nif_padding
-int_func_end =>
+int_func_end Func_Label Entry_Label =>
+ func_end(Func_Label, Entry_Label)
# Handles yielding on function ingress (rather than on each call).
i_test_yield
@@ -763,28 +803,13 @@ i_test_yield
# Ensures that the prior function is large enough to allow NIF patching.
i_nif_padding
+# Landing pad for fun calls/apply where we set up arguments and check errors
+i_lambda_trampoline F f W W
+
# Handles tracing, early NIF calls, and so on.
i_breakpoint_trampoline
# ================================================================
-# Bit syntax matching obsoleted in OTP 22.
-# ================================================================
-
-%cold
-bs_start_match2 Fail=f ica X Y D => jump Fail
-bs_start_match2 Fail Bin X Y D => i_bs_start_match2 Bin Fail X Y D
-i_bs_start_match2 S f t t d
-
-bs_save2 Reg Index => bs_save(Reg, Index)
-i_bs_save2 x t
-
-bs_restore2 Reg Index => bs_restore(Reg, Index)
-i_bs_restore2 S t
-
-bs_context_to_binary S
-%warm
-
-# ================================================================
# New bit syntax matching (R11B).
# ================================================================
@@ -793,45 +818,47 @@ bs_context_to_binary S
# Matching integers
bs_match_string Fail Ms Bits Val => i_bs_match_string Ms Fail Bits Val
-i_bs_match_string S f W W
+i_bs_match_string S f W M
# Fetching integers from binaries.
-bs_get_integer2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d => \
+bs_get_integer2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d =>
get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-i_bs_get_integer S f? t t s d
+i_bs_get_integer S f t t s d
-i_bs_get_integer_8 S t f? d
-i_bs_get_integer_16 S t f? d
-i_bs_get_integer_32 S t f? d
-i_bs_get_integer_64 S t f? t d
+i_bs_get_integer_8 S t f d
+i_bs_get_integer_16 S t f d
+i_bs_get_integer_32 S t f d
+i_bs_get_integer_64 S t f t d
# Fetching binaries from binaries.
-bs_get_binary2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d => \
- get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+bs_get_binary2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d =>
+ get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
-i_bs_get_binary2 S f t? s t d
-i_bs_get_binary_all2 S f? t t d
+i_bs_get_binary2 S f t s t d
+i_bs_get_binary_all2 S f t t d
# Fetching float from binaries.
-bs_get_float2 Fail=f Ms=xy Live=u Sz=s Unit=u Flags=u Dst=d => \
- get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
+bs_get_float2 Fail=f Ms=xy Live=u Sz=s Unit=u Flags=u Dst=d =>
+ get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
bs_get_float2 Fail=f Ms=x Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
-i_bs_get_float2 S f? t s t d
+i_bs_get_float2 S f t s t d
+
+# Miscellaneous
-# Miscellanous
+bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u =>
+ skip_bits2(Fail, Ms, Sz, Unit, Flags)
-bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u => \
- skip_bits2(Fail, Ms, Sz, Unit, Flags)
+i_bs_skip_bits_imm2 f S W
+i_bs_skip_bits2 S S f t
-i_bs_skip_bits_imm2 f? S W
-i_bs_skip_bits2 S S f? t
+bs_test_tail2 Fail=f Ms=xy o => jump Fail
-bs_test_tail2 f? S t
+bs_test_tail2 f S W
-bs_test_unit f? S t
+bs_test_unit f S t
# Gets a bitstring from the tail of a context.
bs_get_tail S d t
@@ -842,20 +869,20 @@ bs_get_tail S d t
# "slots" in the context itself, which lets us continue matching even after
# we've passed it off to another function.
-bs_start_match4 a==am_no_fail Live=u Src=xy Ctx=d => \
+bs_start_match4 a==am_no_fail Live=u Src=xy Ctx=d =>
bs_start_match3 p Src Live Ctx
-bs_start_match4 Fail=f Live=u Src=xy Ctx=d => \
+bs_start_match4 Fail=f Live=u Src=xy Ctx=d =>
bs_start_match3 Fail Src Live Ctx
%if ARCH_64
# This instruction nops on 64-bit platforms
-bs_start_match4 a==am_resume Live Same Same =>
+bs_start_match4 a==am_resume Live Ctx Dst | equal(Ctx, Dst) => _
bs_start_match4 a==am_resume Live Ctx Dst => move Ctx Dst
%else
-bs_start_match4 a==am_resume Live Ctx Dst => \
+bs_start_match4 a==am_resume Live Ctx Dst =>
bs_start_match4 a=am_no_fail Live Ctx Dst
%endif
@@ -873,7 +900,7 @@ i_bs_start_match3 S t j d
i_bs_get_position S S
bs_set_position S S
%else
- bs_get_position S d t?
+ bs_get_position S d t
bs_set_position S S
%endif
@@ -881,99 +908,110 @@ i_bs_start_match3 S t j d
# Utf8/utf16/utf32 support. (R12B-5)
#
bs_get_utf8 Fail=f Ms=xy u u Dst=d => i_bs_get_utf8 Ms Fail Dst
-i_bs_get_utf8 S f? d
+i_bs_get_utf8 S f d
bs_skip_utf8 Fail=f Ms=xy u u => i_bs_skip_utf8 Ms Fail
-i_bs_skip_utf8 S f?
+i_bs_skip_utf8 S f
bs_get_utf16 Fail=f Ms=xy u Flags=u Dst=d => get_utf16(Fail, Ms, Flags, Dst)
bs_skip_utf16 Fail=f Ms=xy u Flags=u => skip_utf16(Fail, Ms, Flags)
-i_bs_get_utf16 S f? t d
-i_bs_skip_utf16 S f? t
+i_bs_get_utf16 S f t d
+i_bs_skip_utf16 S f t
-bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d => \
- bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst | \
- i_bs_validate_unicode_retract Fail Dst Ms
-bs_skip_utf32 Fail=f Ms=xy Live=u Flags=u => \
- bs_get_integer2 Fail Ms Live i=32 u=1 Flags x | \
- i_bs_validate_unicode_retract Fail x Ms
+bs_get_utf32 Fail=f Ms=xy Live=u Flags=u Dst=d =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst |
+ i_bs_validate_unicode_retract Fail Dst Ms
+
+bs_skip_utf32 Fail=f Ms=xy Live=u Flags=u =>
+ bs_get_integer2 Fail Ms Live i=32 u=1 Flags x |
+ i_bs_validate_unicode_retract Fail x Ms
i_bs_validate_unicode_retract j s S
%hot
-#
-# Constructing binaries
-#
+# ================================================================
+# New binary construction (OTP 25).
+# ================================================================
+
+bs_create_bin Fail=j Alloc=u Live=u Unit=u Dst=xy N=u Segments=* =>
+ create_bin(Fail, Alloc, Live, Unit, Dst, N, Segments)
+
+i_bs_create_bin j I t d *
+
+# ================================================================
+# Old instruction for constructing binaries (up to OTP 24).
+# ================================================================
+
%warm
bs_init2 Fail Sz Words Regs Flags Dst | binary_too_big(Sz) => system_limit Fail
bs_init2 Fail Sz=u Words=u==0 Regs Flags Dst => i_bs_init Sz Regs Dst
-bs_init2 Fail Sz=u Words Regs Flags Dst => \
- i_bs_init_heap Sz Words Regs Dst
+bs_init2 Fail Sz=u Words Regs Flags Dst =>
+ i_bs_init_heap Sz Words Regs Dst
-bs_init2 Fail Sz Words=u==0 Regs Flags Dst => \
- i_bs_init_fail Sz Fail Regs Dst
-bs_init2 Fail Sz Words Regs Flags Dst => \
- i_bs_init_fail_heap Sz Words Fail Regs Dst
+bs_init2 Fail Sz Words=u==0 Regs Flags Dst =>
+ i_bs_init_fail Sz Fail Regs Dst
+bs_init2 Fail Sz Words Regs Flags Dst =>
+ i_bs_init_fail_heap Sz Words Fail Regs Dst
-i_bs_init_fail S j? t? S
+i_bs_init_fail S j t S
-i_bs_init_fail_heap s I j? t? S
+i_bs_init_fail_heap s I j t S
-i_bs_init W t? S
+i_bs_init W t S
-i_bs_init_heap W I t? S
+i_bs_init_heap W I t S
bs_init_bits Fail Sz=o Words Regs Flags Dst => system_limit Fail
-bs_init_bits Fail Sz=u Words=u==0 Regs Flags Dst => \
+bs_init_bits Fail Sz=u Words=u==0 Regs Flags Dst =>
i_bs_init_bits Sz Regs Dst
-bs_init_bits Fail Sz=u Words Regs Flags Dst => \
+bs_init_bits Fail Sz=u Words Regs Flags Dst =>
i_bs_init_bits_heap Sz Words Regs Dst
-bs_init_bits Fail Sz Words=u==0 Regs Flags Dst => \
- i_bs_init_bits_fail Sz Fail Regs Dst
-bs_init_bits Fail Sz Words Regs Flags Dst => \
- i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
+bs_init_bits Fail Sz Words=u==0 Regs Flags Dst =>
+ i_bs_init_bits_fail Sz Fail Regs Dst
+bs_init_bits Fail Sz Words Regs Flags Dst =>
+ i_bs_init_bits_fail_heap Sz Words Fail Regs Dst
-i_bs_init_bits_fail S j? t? S
+i_bs_init_bits_fail S j t S
-i_bs_init_bits_fail_heap s I j? t? S
+i_bs_init_bits_fail_heap s I j t S
-i_bs_init_bits W t? S
-i_bs_init_bits_heap W I t? S
+i_bs_init_bits W t S
+i_bs_init_bits_heap W I t S
bs_add Fail S1=i==0 S2 Unit=u==1 D => move S2 D
-bs_add j? s s t? x
+bs_add j s s t x
-bs_append Fail Size Extra Live Unit Bin Flags Dst => \
- i_bs_append Fail Extra Live Unit Size Bin Dst
+bs_append Fail Size Extra Live Unit Bin Flags Dst =>
+ i_bs_append Fail Extra Live Unit Size Bin Dst
-bs_private_append Fail Size Unit Bin Flags Dst => \
- i_bs_private_append Fail Unit Size Bin Dst
+bs_private_append Fail Size Unit Bin Flags Dst =>
+ i_bs_private_append Fail Unit Size Bin Dst
-i_bs_private_append Fail Unit Size Bin Dst=y => \
- i_bs_private_append Fail Unit Size Bin x | move x Dst
+i_bs_private_append Fail Unit Size Bin Dst=y =>
+ i_bs_private_append Fail Unit Size Bin x | move x Dst
bs_init_writable
-i_bs_append j? I t? t s s S
-i_bs_private_append j? t s S x
+i_bs_append j I t t s s S
+i_bs_private_append j t s S x
#
# Storing integers into binaries.
#
-bs_put_integer Fail=j Sz=sq Unit=u Flags=u Src=s => \
- put_integer(Fail, Sz, Unit, Flags, Src)
+bs_put_integer Fail=j Sz=sq Unit=u Flags=u Src=s =>
+ put_integer(Fail, Sz, Unit, Flags, Src)
-i_new_bs_put_integer j? S t s
-i_new_bs_put_integer_imm s j? W t
+i_new_bs_put_integer j S t s
+i_new_bs_put_integer_imm s j W t
#
# Utf8/utf16/utf32 support. (R12B-5)
@@ -985,16 +1023,16 @@ bs_utf16_size j Src Dst=d => i_bs_utf16_size Src Dst
bs_put_utf8 Fail u Src => i_bs_put_utf8 Fail Src
bs_put_utf16 Fail Flags Src => put_utf16(Fail, Flags, Src)
-bs_put_utf32 Fail=j Flags=u Src=s => \
- i_bs_validate_unicode Fail Src | bs_put_integer Fail i=32 u=1 Flags Src
+bs_put_utf32 Fail=j Flags=u Src=s =>
+ i_bs_validate_unicode Fail Src | bs_put_integer Fail i=32 u=1 Flags Src
i_bs_utf8_size s x
i_bs_utf16_size s x
-i_bs_put_utf8 j? s
-i_bs_put_utf16 j? t s
+i_bs_put_utf8 j s
+i_bs_put_utf16 j t s
-i_bs_validate_unicode j? s
+i_bs_validate_unicode j s
#
# Storing floats into binaries.
@@ -1002,24 +1040,24 @@ i_bs_validate_unicode j? s
# Will fail. No need to keep the instruction, because bs_add or
# bs_init* would already have raised an exception.
-bs_put_float Fail Sz=q Unit Flags Val =>
+bs_put_float Fail Sz=q Unit Flags Val => _
-bs_put_float Fail=j Sz=s Unit=u Flags=u Src=s => \
- put_float(Fail, Sz, Unit, Flags, Src)
+bs_put_float Fail=j Sz=s Unit=u Flags=u Src=s =>
+ put_float(Fail, Sz, Unit, Flags, Src)
-i_new_bs_put_float j? S t s
-i_new_bs_put_float_imm j? W t s
+i_new_bs_put_float j S t s
+i_new_bs_put_float_imm j W t s
#
# Storing binaries into binaries.
#
-bs_put_binary Fail=j Sz=s Unit=u Flags=u Src=s => \
- put_binary(Fail, Sz, Unit, Flags, Src)
+bs_put_binary Fail=j Sz=s Unit=u Flags=u Src=s =>
+ put_binary(Fail, Sz, Unit, Flags, Src)
-i_new_bs_put_binary j? s t s
-i_new_bs_put_binary_imm j? W s
-i_new_bs_put_binary_all s j? t
+i_new_bs_put_binary j s t s
+i_new_bs_put_binary_imm j W s
+i_new_bs_put_binary_all s j t
#
# Warning: The i_bs_put_string and i_new_bs_put_string instructions
@@ -1027,7 +1065,7 @@ i_new_bs_put_binary_all s j? t
# Don't change the instruction format unless you change the loader too.
#
-bs_put_string W W
+bs_put_string W M
#
# New floating point instructions (R8).
@@ -1053,8 +1091,8 @@ i_fmul l l l
i_fdiv l l l
i_fnegate l l
-fclearerror =>
-fcheckerror p =>
+fclearerror => _
+fcheckerror p => _
%hot
@@ -1066,84 +1104,65 @@ apply t
apply_last t t
#
-# Handle compatibility with OTP 17 here.
+# Map instructions. First introduced in R17.
#
-i_put_map_assoc/4
-
-# We KNOW that in OTP 20 (actually OTP 18 and higher), a put_map_assoc instruction
-# is always preceded by an is_map test. That means that put_map_assoc can never
-# fail and does not need any failure label.
-
-put_map_assoc Fail Map Dst Live Size Rest=* | compiled_with_otp_20_or_higher() => \
- i_put_map_assoc Map Dst Live Size Rest
-
-# Translate the put_map_assoc instruction if the module was compiled by a compiler
-# before 20. This is only necessary if the OTP 17 compiler was used, but we
-# have no safe and relatively easy way to know whether OTP 18/19 was used.
+# We KNOW that in OTP 18 and higher, a put_map_assoc instruction is
+# always preceded by an is_map test. That means that put_map_assoc can
+# never fail and does not need any failure label.
-put_map_assoc Fail=p Map Dst Live Size Rest=* => \
- ensure_map Map | i_put_map_assoc Map Dst Live Size Rest
-put_map_assoc Fail=f Map Dst Live Size Rest=* => \
- is_map Fail Map | i_put_map_assoc Map Dst Live Size Rest
+put_map_assoc Fail Map Dst Live Size Rest=* =>
+ i_put_map_assoc Map Dst Live Size Rest
-ensure_map Lit=q | literal_is_map(Lit) =>
-
-%cold
-ensure_map s
-%hot
-
-#
-# Map instructions. First introduced in R17.
-#
+i_put_map_assoc/4
sorted_put_map_assoc/4
-i_put_map_assoc Map Dst Live Size Rest=* | map_key_sort(Size, Rest) => \
- sorted_put_map_assoc Map Dst Live Size Rest
+i_put_map_assoc Map Dst Live Size Rest=* | map_key_sort(Size, Rest) =>
+ sorted_put_map_assoc Map Dst Live Size Rest
sorted_put_map_exact/5
-put_map_exact F Map Dst Live Size Rest=* | map_key_sort(Size, Rest) => \
- sorted_put_map_exact F Map Dst Live Size Rest
+put_map_exact F Map Dst Live Size Rest=* | map_key_sort(Size, Rest) =>
+ sorted_put_map_exact F Map Dst Live Size Rest
-sorted_put_map_assoc Map Dst Live Size Rest=* | is_empty_map(Map) => \
- new_map Dst Live Size Rest
-sorted_put_map_assoc Src=s Dst Live Size Rest=* => \
- update_map_assoc Src Dst Live Size Rest
+sorted_put_map_assoc Map Dst Live Size Rest=* | is_empty_map(Map) =>
+ new_map Dst Live Size Rest
+sorted_put_map_assoc Src=s Dst Live Size Rest=* =>
+ update_map_assoc Src Dst Live Size Rest
-sorted_put_map_exact Fail Src Dst Live Size Rest=* => \
- update_map_exact Src Fail Dst Live Size Rest
+sorted_put_map_exact Fail Src Dst Live Size Rest=* =>
+ update_map_exact Src Fail Dst Live Size Rest
-new_map Dst Live Size Rest=* | is_small_map_literal_keys(Size, Rest) => \
- new_small_map_lit(Dst, Live, Size, Rest)
+new_map Dst Live Size Rest=* | is_small_map_literal_keys(Size, Rest) =>
+ new_small_map_lit(Dst, Live, Size, Rest)
new_map d t I *
i_new_small_map_lit d t q I *
update_map_assoc s d t I *
-update_map_exact s j? d t I *
+update_map_exact s j d t I *
-is_map f? s
+is_map f s
## Transform has_map_fields #{ K1 := _, K2 := _ } to has_map_elements
-has_map_fields Fail Src Size Rest=* => \
- has_map_fields(Fail, Src, Size, Rest)
+has_map_fields Fail Src Size Rest=* =>
+ has_map_fields(Fail, Src, Size, Rest)
## Transform get_map_elements(s) #{ K1 := V1, K2 := V2 }
-get_map_elements Fail Src Size=u==2 Rest=* => \
+get_map_elements Fail Src Size=u==2 Rest=* =>
get_map_element(Fail, Src, Size, Rest)
-get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) => \
- get_map_elements(Fail, Src, Size, Rest)
+get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) =>
+ get_map_elements(Fail, Src, Size, Rest)
-i_get_map_elements f? s I *
+i_get_map_elements f s I *
-i_get_map_element_hash Fail Src=c Key Hash Dst => \
+i_get_map_element_hash Fail Src=c Key Hash Dst =>
move Src x | i_get_map_element_hash Fail x Key Hash Dst
-i_get_map_element_hash f? S c I S
+i_get_map_element_hash f S c I S
-i_get_map_element Fail Src=c Key Dst => \
+i_get_map_element Fail Src=c Key Dst =>
move Src x | i_get_map_element Fail x Key Dst
-i_get_map_element f? S S S
+i_get_map_element f S S S
#
# Convert the plus operations to a generic plus instruction.
@@ -1151,28 +1170,28 @@ i_get_map_element f? S S S
gen_plus/5
gen_minus/5
-gc_bif1 Fail Live u$bif:erlang:splus/1 Src Dst => \
- gen_plus Fail Live Src i Dst
-gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst => \
- gen_plus Fail Live S1 S2 Dst
+gc_bif1 Fail Live u$bif:erlang:splus/1 Src Dst =>
+ gen_plus Fail Live Src i Dst
+gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst =>
+ gen_plus Fail Live S1 S2 Dst
-gc_bif1 Fail Live u$bif:erlang:sminus/1 Src Dst => \
- i_unary_minus Src Fail Dst
-gc_bif2 Fail Live u$bif:erlang:sminus/2 S1 S2 Dst => \
- gen_minus Fail Live S1 S2 Dst
+gc_bif1 Fail Live u$bif:erlang:sminus/1 Src Dst =>
+ i_unary_minus Src Fail Dst
+gc_bif2 Fail Live u$bif:erlang:sminus/2 S1 S2 Dst =>
+ gen_minus Fail Live S1 S2 Dst
#
# Optimize addition and subtraction of small literals using
# the i_increment/3 instruction (in bodies, not in guards).
#
-gen_plus p Live Int=i Reg=d Dst => \
- increment(Reg, Int, Dst)
-gen_plus p Live Reg=d Int=i Dst => \
- increment(Reg, Int, Dst)
+gen_plus p Live Int=i Reg=d Dst =>
+ increment(Reg, Int, Dst)
+gen_plus p Live Reg=d Int=i Dst =>
+ increment(Reg, Int, Dst)
-gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) => \
- increment_from_minus(Reg, Int, Dst)
+gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) =>
+ increment_from_minus(Reg, Int, Dst)
#
# Arithmetic instructions.
@@ -1181,95 +1200,103 @@ gen_minus p Live Reg=d Int=i Dst | negation_is_small(Int) => \
# It is OK to swap arguments for '+' in a guard. It is also
# OK to turn minus into plus in a guard.
gen_plus Fail=f Live S1=c S2 Dst => i_plus S2 S1 Fail Dst
-gen_minus Fail=f Live S1 S2=i Dst | negation_is_small(S2) => \
+gen_minus Fail=f Live S1 S2=i Dst | negation_is_small(S2) =>
plus_from_minus(Fail, Live, S1, S2, Dst)
gen_plus Fail Live S1 S2 Dst => i_plus S1 S2 Fail Dst
gen_minus Fail Live S1 S2 Dst => i_minus S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:stimes/2 S1 S2 Dst => \
- i_times Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:stimes/2 S1 S2 Dst =>
+ i_times Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:div/2 S1 S2 Dst => \
- i_m_div Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:div/2 S1 S2 Dst =>
+ i_m_div Fail S1 S2 Dst
# Fused 'rem'/'div' pair.
-gc_bif2 Fail Live u$bif:erlang:rem/2 LHS RHS Remainder | \
- gc_bif2 A B u$bif:erlang:intdiv/2 LHS RHS Quotient | \
- distinct(LHS, Remainder) | \
- distinct(RHS, Remainder) => \
- i_rem_div LHS RHS Fail Remainder Quotient
+gc_bif2 Fail Live u$bif:erlang:rem/2 LHS1 RHS1 Remainder |
+ gc_bif2 A B u$bif:erlang:intdiv/2 LHS2 RHS2 Quotient |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Remainder) |
+ distinct(RHS1, Remainder) =>
+ i_rem_div LHS1 RHS1 Fail Remainder Quotient
# As above but with a `line` in between
-gc_bif2 Fail Live u$bif:erlang:rem/2 LHS RHS Remainder | \
- line Loc | \
- gc_bif2 A B u$bif:erlang:intdiv/2 LHS RHS Quotient | \
- distinct(LHS, Remainder) | \
- distinct(RHS, Remainder) => \
- i_rem_div LHS RHS Fail Remainder Quotient
+gc_bif2 Fail Live u$bif:erlang:rem/2 LHS1 RHS1 Remainder |
+ line Loc |
+ gc_bif2 A B u$bif:erlang:intdiv/2 LHS2 RHS2 Quotient |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Remainder) |
+ distinct(RHS1, Remainder) =>
+ i_rem_div LHS1 RHS1 Fail Remainder Quotient
# Fused 'div'/'rem' pair
-gc_bif2 Fail Live u$bif:erlang:intdiv/2 LHS RHS Quotient | \
- gc_bif2 A B u$bif:erlang:rem/2 LHS RHS Remainder | \
- distinct(LHS, Quotient) | \
- distinct(RHS, Quotient) => \
- i_div_rem LHS RHS Fail Quotient Remainder
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 LHS1 RHS1 Quotient |
+ gc_bif2 A B u$bif:erlang:rem/2 LHS2 RHS2 Remainder |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Quotient) |
+ distinct(RHS1, Quotient) =>
+ i_div_rem LHS1 RHS1 Fail Quotient Remainder
# As above but with a `line` in between
-gc_bif2 Fail Live u$bif:erlang:intdiv/2 LHS RHS Quotient | \
- line Loc | \
- gc_bif2 A B u$bif:erlang:rem/2 LHS RHS Remainder | \
- distinct(LHS, Quotient) | \
- distinct(RHS, Quotient) => \
- i_div_rem LHS RHS Fail Quotient Remainder
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 LHS1 RHS1 Quotient |
+ line Loc |
+ gc_bif2 A B u$bif:erlang:rem/2 LHS2 RHS2 Remainder |
+ equal(LHS1, LHS2) |
+ equal(RHS1, RHS2) |
+ distinct(LHS1, Quotient) |
+ distinct(RHS1, Quotient) =>
+ i_div_rem LHS1 RHS1 Fail Quotient Remainder
-gc_bif2 Fail Live u$bif:erlang:intdiv/2 S1 S2 Dst => \
- i_int_div Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:rem/2 S1 S2 Dst => \
- i_rem S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:intdiv/2 S1 S2 Dst =>
+ i_int_div Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:rem/2 S1 S2 Dst =>
+ i_rem S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:bsl/2 S1 S2 Dst => \
- i_bsl S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:bsr/2 S1 S2 Dst => \
- i_bsr S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:bsl/2 S1 S2 Dst =>
+ i_bsl S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:bsr/2 S1 S2 Dst =>
+ i_bsr S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:band/2 S1 S2 Dst => \
- i_band S1 S2 Fail Dst
+gc_bif2 Fail Live u$bif:erlang:band/2 S1 S2 Dst =>
+ i_band S1 S2 Fail Dst
-gc_bif2 Fail Live u$bif:erlang:bor/2 S1 S2 Dst => \
- i_bor Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:bor/2 S1 S2 Dst =>
+ i_bor Fail S1 S2 Dst
-gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst => \
- i_bxor Fail S1 S2 Dst
+gc_bif2 Fail Live u$bif:erlang:bxor/2 S1 S2 Dst =>
+ i_bxor Fail S1 S2 Dst
-gc_bif1 Fail Live u$bif:erlang:bnot/1 Src Dst => \
- i_bnot Fail Src Dst
+gc_bif1 Fail Live u$bif:erlang:bnot/1 Src Dst =>
+ i_bnot Fail Src Dst
i_increment S W d
-i_plus s s j? d
-i_minus s s j? d
+i_plus s s j d
+i_minus s s j d
-i_unary_minus s j? d
+i_unary_minus s j d
-i_times j? s s d
+i_times j s s d
-i_m_div j? s s d
+i_m_div j s s d
-i_rem_div s s j? d d
-i_div_rem s s j? d d
-i_int_div j? s s d
-i_rem s s j? d
+i_rem_div s s j d d
+i_div_rem s s j d d
+i_int_div j s s d
+i_rem s s j d
-i_bsl s s j? d
-i_bsr s s j? d
+i_bsl s s j d
+i_bsr s s j d
-i_band s s j? d
-i_bor j? s s d
-i_bxor j? s s d
+i_band s s j d
+i_bor j s s d
+i_bxor j s s d
-i_bnot j? s d
+i_bnot j s d
#
# Old guard BIFs that creates heap fragments are no longer allowed.
@@ -1285,11 +1312,11 @@ bif1 Fail u$bif:erlang:trunc/1 s d => too_old_compiler
# Handle the length/1 guard BIF specially to make it trappable.
#
-gc_bif1 Fail=j Live u$bif:erlang:length/1 Src Dst => \
- i_length_setup Fail Live Src | i_length Fail Live Dst
+gc_bif1 Fail=j Live u$bif:erlang:length/1 Src Dst =>
+ i_length_setup Fail Live Src | i_length Fail Live Dst
-i_length_setup j? t s
-i_length j? t d
+i_length_setup j t s
+i_length j t d
#
# Guard BIFs.
@@ -1304,7 +1331,7 @@ gc_bif3 Fail Live Bif S1 S2 S3 Dst => i_bif3 S1 S2 S3 Fail Bif Dst
# encountered.
#
unsupported_guard_bif/3
-unsupported_guard_bif A B C | never() =>
+unsupported_guard_bif A B C | never() => _
#
# R13B03
@@ -1320,8 +1347,8 @@ on_load
recv_mark f => i_recv_mark
i_recv_mark
-recv_set Fail | label Lbl | loop_rec Lf Reg => \
- i_recv_set | label Lbl | loop_rec Lf Reg
+recv_set Fail | label Lbl | loop_rec Lf Reg =>
+ i_recv_set | label Lbl | loop_rec Lf Reg
i_recv_set
#
diff --git a/erts/emulator/beam/jit/x86/predicates.tab b/erts/emulator/beam/jit/x86/predicates.tab
index d9d3801c8f..cd1230cd1a 100644
--- a/erts/emulator/beam/jit/x86/predicates.tab
+++ b/erts/emulator/beam/jit/x86/predicates.tab
@@ -32,12 +32,6 @@ pred.is_mfa_bif(M, F, A) {
return 0;
}
-pred.needs_nif_padding() {
- /* If the module may load a NIF all functions must be able to hold a NIF
- * stub, so we'll pad to that size at the end of every function. */
- return S->may_load_nif;
-}
-
pred.never_fails(Bif) {
static Eterm nofail_bifs[] =
{am_Neqeq,
diff --git a/erts/emulator/beam/jit/x86/process_main.cpp b/erts/emulator/beam/jit/x86/process_main.cpp
new file mode 100644
index 0000000000..210aecb0c2
--- /dev/null
+++ b/erts/emulator/beam/jit/x86/process_main.cpp
@@ -0,0 +1,348 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2020-2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include "beam_asm.hpp"
+
+extern "C"
+{
+#include "bif.h"
+#include "beam_common.h"
+#include "code_ix.h"
+#include "export.h"
+}
+
+const uint8_t *BeamAssembler::nops[3] = {nop1, nop2, nop3};
+const uint8_t BeamAssembler::nop1[1] = {0x90};
+const uint8_t BeamAssembler::nop2[2] = {0x66, 0x90};
+const uint8_t BeamAssembler::nop3[3] = {0x0F, 0x1F, 0x00};
+
+#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
+static Process *erts_debug_schedule(ErtsSchedulerData *esdp,
+ Process *c_p,
+ int calls) {
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ ERTS_UNREQ_PROC_MAIN_LOCK(c_p);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ c_p = erts_schedule(esdp, c_p, calls);
+ ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ ERTS_REQ_PROC_MAIN_LOCK(c_p);
+ PROCESS_MAIN_CHK_LOCKS(c_p);
+ return c_p;
+}
+#endif
+
+/* void process_main(ErtsSchedulerData *esdp); */
+void BeamGlobalAssembler::emit_process_main() {
+ Label context_switch_local = a.newLabel(),
+ context_switch_simplified_local = a.newLabel(),
+ do_schedule_local = a.newLabel(), schedule_next = a.newLabel();
+
+ const x86::Mem start_time_i =
+ getSchedulerRegRef(offsetof(ErtsSchedulerRegisters, start_time_i));
+ const x86::Mem start_time =
+ getSchedulerRegRef(offsetof(ErtsSchedulerRegisters, start_time));
+
+ /* Allocate the register structure on the stack to allow computing the
+ * runtime stack address from it, greatly reducing the cost of stack
+ * swapping. */
+ a.sub(x86::rsp, imm(sizeof(ErtsSchedulerRegisters) + ERTS_CACHE_LINE_SIZE));
+ a.and_(x86::rsp, imm(~ERTS_CACHE_LINE_MASK));
+
+ a.mov(x86::qword_ptr(ARG1, offsetof(ErtsSchedulerData, registers)),
+ x86::rsp);
+
+ /* Center `registers` at the base of x_reg_array so we can use negative
+ * 8-bit displacement to address the commonly used aux_regs, located at the
+ * start of the ErtsSchedulerRegisters struct. */
+ a.lea(registers,
+ x86::qword_ptr(x86::rsp,
+ offsetof(ErtsSchedulerRegisters, x_reg_array.d)));
+
+ load_erl_bits_state(ARG1);
+ runtime_call<1>(erts_bits_init_state);
+
+#if defined(DEBUG) && defined(NATIVE_ERLANG_STACK)
+ /* Save stack bounds so they can be tested without clobbering anything. */
+ runtime_call<0>(erts_get_stacklimit);
+
+ a.mov(getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, runtime_stack_end)),
+ RET);
+ a.mov(getSchedulerRegRef(
+ offsetof(ErtsSchedulerRegisters, runtime_stack_start)),
+ x86::rsp);
+#elif !defined(NATIVE_ERLANG_STACK)
+ /* Save the initial SP of the thread so that we can verify that it
+ * doesn't grow. */
+# ifdef JIT_HARD_DEBUG
+ a.mov(getInitialSPRef(), x86::rsp);
+# endif
+
+ /* Manually do an `emit_enter_runtime` to match the `emit_leave_runtime`
+ * below. We avoid `emit_enter_runtime` because it may do additional
+ * assertions that may currently fail.
+ *
+ * IMPORTANT: We must ensure that this sequence leaves the stack
+ * aligned on a 16-byte boundary. */
+ a.mov(getRuntimeStackRef(), x86::rsp);
+ a.sub(x86::rsp, imm(15));
+ a.and_(x86::rsp, imm(-16));
+#endif
+
+ a.mov(start_time_i, imm(0));
+ a.mov(start_time, imm(0));
+
+ mov_imm(c_p, 0);
+ mov_imm(FCALLS, 0);
+ mov_imm(ARG3, 0); /* Set reds_used for erts_schedule call */
+
+ a.jmp(schedule_next);
+
+ a.bind(do_schedule_local);
+ {
+ /* Figure out reds_used. def_arg_reg[5] = REDS_IN */
+ a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, def_arg_reg[5])));
+ a.sub(ARG3, FCALLS);
+
+ a.jmp(schedule_next);
+ }
+
+ a.bind(context_switch_local);
+ comment("Context switch, unknown arity/MFA");
+ {
+ Sint arity_offset = offsetof(ErtsCodeMFA, arity) - sizeof(ErtsCodeMFA);
+
+ a.mov(ARG1, x86::qword_ptr(ARG3, arity_offset));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), ARG1);
+
+ a.lea(ARG1, x86::qword_ptr(ARG3, -(Sint)sizeof(ErtsCodeMFA)));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), ARG1);
+
+ /* !! Fall through !! */
+ }
+
+ a.bind(context_switch_simplified_local);
+ comment("Context switch, known arity and MFA");
+ {
+ Label not_exiting = a.newLabel();
+
+#ifdef ERLANG_FRAME_POINTERS
+ /* Kill the current frame pointer to avoid confusing `perf` and similar
+ * tools. */
+ a.sub(frame_pointer, frame_pointer);
+#endif
+
+#ifdef DEBUG
+ Label check_i = a.newLabel();
+ /* Check that ARG3 is set to a valid CP. */
+ a.test(ARG3, imm(_CPMASK));
+ a.je(check_i);
+ comment("# ARG3 is not a valid CP");
+ a.ud2();
+ a.bind(check_i);
+#endif
+
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, i)), ARG3);
+
+#if defined(JIT_HARD_DEBUG) && defined(ERLANG_FRAME_POINTERS)
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, x86::qword_ptr(c_p, offsetof(Process, frame_pointer)));
+ a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, stop)));
+
+ runtime_call<3>(erts_validate_stack);
+#endif
+
+#ifdef WIN32
+ a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.value)));
+#else
+ a.mov(ARG1d, x86::dword_ptr(c_p, offsetof(Process, state.counter)));
+#endif
+
+ a.test(ARG1d, imm(ERTS_PSFLG_EXITING));
+ a.short_().je(not_exiting);
+ {
+ comment("Process exiting");
+
+ a.lea(ARG1, x86::qword_ptr(labels[process_exit]));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, i)), ARG1);
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, arity)), imm(0));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, current)), imm(0));
+ a.jmp(do_schedule_local);
+ }
+ a.bind(not_exiting);
+
+ /* Figure out reds_used. def_arg_reg[5] = REDS_IN */
+ a.mov(ARG3, x86::qword_ptr(c_p, offsetof(Process, def_arg_reg[5])));
+ a.sub(ARG3, FCALLS);
+
+ /* Spill reds_used to FCALLS as we no longer need that value */
+ a.mov(FCALLS, ARG3);
+
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<2>(copy_out_registers);
+
+ /* Restore reds_used from FCALLS */
+ a.mov(ARG3, FCALLS);
+
+ /* !! Fall through !! */
+ }
+
+ a.bind(schedule_next);
+ comment("schedule_next");
+ {
+ Label schedule = a.newLabel(), skip_long_schedule = a.newLabel();
+
+ /* ARG3 contains reds_used at this point */
+
+ a.cmp(start_time, imm(0));
+ a.short_().je(schedule);
+ {
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, start_time);
+
+ /* Spill reds_used in start_time slot */
+ a.mov(start_time, ARG3);
+
+ a.mov(ARG3, start_time_i);
+ runtime_call<3>(check_monitor_long_schedule);
+
+ /* Restore reds_used */
+ a.mov(ARG3, start_time);
+ }
+ a.bind(schedule);
+
+#ifdef ERLANG_FRAME_POINTERS
+ if (erts_frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ /* Kill the current frame pointer so that misc jobs that execute
+ * during `erts_schedule` aren't attributed to the function we
+ * were scheduled out of. */
+ a.sub(frame_pointer, frame_pointer);
+ }
+#endif
+
+ mov_imm(ARG1, 0);
+ a.mov(ARG2, c_p);
+#if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
+ runtime_call<3>(erts_debug_schedule);
+#else
+ runtime_call<3>(erts_schedule);
+#endif
+ a.mov(c_p, RET);
+
+#ifdef ERTS_MSACC_EXTENDED_STATES
+ a.lea(ARG1,
+ x86::qword_ptr(registers,
+ offsetof(ErtsSchedulerRegisters,
+ aux_regs.d.erts_msacc_cache)));
+ runtime_call<1>(erts_msacc_update_cache);
+#endif
+
+ a.mov(ARG1, imm((UWord)&erts_system_monitor_long_schedule));
+ a.cmp(x86::qword_ptr(ARG1), imm(0));
+ a.mov(start_time, imm(0));
+ a.short_().je(skip_long_schedule);
+ {
+ /* Enable long schedule test */
+ runtime_call<0>(erts_timestamp_millis);
+ a.mov(start_time, RET);
+ a.mov(RET, x86::qword_ptr(c_p, offsetof(Process, i)));
+ a.mov(start_time_i, RET);
+ }
+ a.bind(skip_long_schedule);
+
+ /* Copy arguments */
+ a.mov(ARG1, c_p);
+ load_x_reg_array(ARG2);
+ runtime_call<2>(copy_in_registers);
+
+ /* Setup reduction counting */
+ a.mov(FCALLS, x86::qword_ptr(c_p, offsetof(Process, fcalls)));
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, def_arg_reg[5])), FCALLS);
+
+#ifdef DEBUG
+ a.mov(x86::qword_ptr(c_p, offsetof(Process, debug_reds_in)), FCALLS);
+#endif
+
+ /* Check whether save calls is on */
+ a.mov(ARG1, c_p);
+ a.mov(ARG2, imm(ERTS_PSD_SAVED_CALLS_BUF));
+ runtime_call<2>(erts_psd_get);
+
+ /* Read the active code index, overriding it with
+ * ERTS_SAVE_CALLS_CODE_IX when save_calls is enabled (RET != 0). */
+ a.test(RET, RET);
+ a.mov(ARG1, imm(&the_active_code_index));
+ a.mov(ARG2, imm(ERTS_SAVE_CALLS_CODE_IX));
+ a.mov(active_code_ix.r32(), x86::dword_ptr(ARG1));
+ a.cmovnz(active_code_ix, ARG2);
+
+ /* Start executing the Erlang process. Note that reductions have
+ * already been set up above. */
+ emit_leave_runtime<Update::eStack | Update::eHeap>();
+
+ /* Check if we are just returning from a dirty nif/bif call and if so we
+ * need to do a bit of cleaning up before continuing. */
+ a.mov(RET, x86::qword_ptr(c_p, offsetof(Process, i)));
+ a.cmp(x86::qword_ptr(RET), imm(op_call_nif_WWW));
+ a.je(labels[dispatch_nif]);
+ a.cmp(x86::qword_ptr(RET), imm(op_call_bif_W));
+ a.je(labels[dispatch_bif]);
+ a.jmp(RET);
+ }
+
+ /* Processes may jump to the exported entry points below, executing on the
+ * Erlang stack when entering. These are separate from the `_local` labels
+ * above as we don't want to worry about which stack we're on when the
+ * cases overlap. */
+
+ /* `ga->get_context_switch()`
+ *
+ * The *next* instruction pointer is provided in ARG3, and must be preceded
+ * by an ErtsCodeMFA. */
+ a.bind(labels[context_switch]);
+ {
+ emit_enter_runtime<Update::eStack | Update::eHeap>();
+
+ a.jmp(context_switch_local);
+ }
+
+ /* `ga->get_context_switch_simplified()`
+ *
+ * The next instruction pointer is provided in ARG3, which does not need to
+ * point past an ErtsCodeMFA as the process structure has already been
+ * updated. */
+ a.bind(labels[context_switch_simplified]);
+ {
+ emit_enter_runtime<Update::eStack | Update::eHeap>();
+
+ a.jmp(context_switch_simplified_local);
+ }
+
+ /* `ga->get_do_schedule()`
+ *
+ * `c_p->i` must be set prior to jumping here. */
+ a.bind(labels[do_schedule]);
+ {
+ emit_enter_runtime<Update::eStack | Update::eHeap>();
+
+ a.jmp(do_schedule_local);
+ }
+}
diff --git a/erts/emulator/beam/predicates.tab b/erts/emulator/beam/predicates.tab
index 833542112b..7ebd5bcb2b 100644
--- a/erts/emulator/beam/predicates.tab
+++ b/erts/emulator/beam/predicates.tab
@@ -2,7 +2,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 2020. All Rights Reserved.
+// Copyright Ericsson AB 2020-2022. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -23,10 +23,6 @@ pred.never() {
return 0;
}
-pred.compiled_with_otp_20_or_higher() {
- return S->otp_20_or_higher;
-}
-
// Test whether a jump table can be used.
pred.use_jump_tab(Size, Rest, MinSize) {
Sint min, max;
@@ -144,25 +140,18 @@ pred.is_heavy_bif(Bif) {
return 0;
}
-// Test whether the given literal is a map.
-pred.literal_is_map(Lit) {
- Eterm term;
-
- ASSERT(Lit.type == TAG_q);
- term = beamfile_get_literal(&S->beam, Lit.val);
- return is_map(term);
-}
-
// Predicate to test whether all of the given new small map keys are literals
pred.is_small_map_literal_keys(Size, Rest) {
- if (Size.val > MAP_SMALL_MAP_LIMIT) {
+ Uint pair_count = Size.val / 2;
+
+ if (pair_count > MAP_SMALL_MAP_LIMIT) {
return 0;
}
/*
* Operations with non-literals have always only one key.
*/
- if (Size.val != 2) {
+ if (pair_count != 1) {
return 1;
}
@@ -226,7 +215,33 @@ pred.map_key_sort(Size, Rest) {
return beam_load_map_key_sort(S, Size, Rest);
}
-// Test that the two registers are distinct.
-pred.distinct(Reg1, Reg2) {
- return Reg1.type != Reg2.type || Reg1.val != Reg2.val;
+// Test that two operands are distinct.
+pred.distinct(Val1, Val2) {
+ if (Val1.type != Val2.type) {
+ return 1;
+ } else if (Val1.type == TAG_x || Val1.type == TAG_y) {
+ /* We must not compare the type indices (if any). */
+ return (Val1.val & REG_MASK) != (Val2.val & REG_MASK);
+ } else if (Val1.type == TAG_n) {
+ /* NIL has no associated value. */
+ return 0;
+ } else {
+ return Val1.val != Val2.val;
+ }
+}
+
+// Test that two operands are equal when disregarding types. Opposite of the
+// `distinct` predicate.
+pred.equal(Val1, Val2) {
+ if (Val1.type != Val2.type) {
+ return 0;
+ } else if (Val1.type == TAG_x || Val1.type == TAG_y) {
+ /* We must not compare the type indices (if any). */
+ return (Val1.val & REG_MASK) == (Val2.val & REG_MASK);
+ } else if (Val1.type == TAG_n) {
+ /* NIL has no associated value. */
+ return 1;
+ } else {
+ return Val1.val == Val2.val;
+ }
}
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 1ffc7f5028..20b0571e43 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -105,6 +105,9 @@
#define ErtsInArea(ptr,start,nbytes) \
((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
+#define ErtsInBetween(ptr,start,end) \
+ ErtsInArea(ptr, start, (char*)(end) - (char*)(start))
+
#define ErtsContainerStruct(ptr, type, member) \
((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - offsetof(type, member)))
@@ -267,7 +270,7 @@ __decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *f
* static int test(){ return 0;}
* GCC_DIAG_ON(unused-function)
*
- * These macros were orginally authored by Jonathan Wakely and has
+ * These macros were originally authored by Jonathan Wakely and has
* been modified by Patrick Horgan.
*
* Source: http://dbp-consulting.com/tutorials/SuppressingGCCWarnings.html
@@ -346,7 +349,7 @@ __decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *f
** Eterm: A tagged erlang term (possibly 64 bits)
** BeamInstr: A beam code instruction unit, possibly larger than Eterm, not smaller.
** Uint: An unsigned integer exactly as large as an Eterm.
-** Sint: A signed integer exactly as large as an eterm and therefor large
+** Sint: A signed integer exactly as large as an eterm and therefore large
** enough to hold the return value of the signed_val() macro.
** UWord: An unsigned integer at least as large as a void * and also as large
** or larger than an Eterm
@@ -767,6 +770,8 @@ extern void *erts_sys_ddll_call_init(void *function);
extern void *erts_sys_ddll_call_nif_init(void *function);
extern int erts_sys_ddll_sym2(void *handle, const char *name, void **function, ErtsSysDdllError*);
#define erts_sys_ddll_sym(H,N,F) erts_sys_ddll_sym2(H,N,F,NULL)
+extern int erts_sys_ddll_vsym2(void *handle, const char *name, const char *vers, void **function, ErtsSysDdllError*);
+#define erts_sys_ddll_vsym(H,N,V,F) erts_sys_ddll_vsym2(H,N,V,F,NULL)
extern char *erts_sys_ddll_error(int code);
@@ -1368,4 +1373,60 @@ erts_raw_env_next_char(byte *p, int encoding)
#define ERTS_SPAWN_DRV_CONTROL_MAGIC_NUMBER 0x04c76a00U
#define ERTS_FORKER_DRV_CONTROL_MAGIC_NUMBER 0x050a7800U
+#define ERTS_ATTR_WUR
+#define ERTS_ATTR_ALLOC_SIZE(SZPOS)
+#define ERTS_ATTR_MALLOC_U
+#define ERTS_ATTR_MALLOC_US(SZPOS)
+#define ERTS_ATTR_MALLOC_UD(DTOR, PTRPOS)
+#define ERTS_ATTR_MALLOC_USD(SZPOS, DTOR, PTRPOS)
+#define ERTS_ATTR_MALLOC_D(DTOR, PTRPOS)
+
+/* ERTS_ATTR_MALLOC_xxx:
+ * U: Returns pointer to Undefined data. ((malloc))
+ * S: Has Size argument with nr of bytes of returned data. ((alloc_size(SZPOS)))
+ * D: Has 1-to-1 Deallocator function with ptr argument. ((malloc(DTOR,PTRPOS)))
+ * (D does not work on INLINE functions)
+ */
+
+#ifdef __has_attribute
+# if __has_attribute(warn_unused_result)
+# undef ERTS_ATTR_WUR
+# define ERTS_ATTR_WUR __attribute__((warn_unused_result))
+# endif
+# if __has_attribute(alloc_size)
+# undef ERTS_ATTR_ALLOC_SIZE
+# define ERTS_ATTR_ALLOC_SIZE(SZPOS) __attribute__((alloc_size(SZPOS)))
+# endif
+# if __has_attribute(malloc)
+# undef ERTS_ATTR_MALLOC_U
+# define ERTS_ATTR_MALLOC_U __attribute__((malloc)) ERTS_ATTR_WUR
+
+# undef ERTS_ATTR_MALLOC_US
+# define ERTS_ATTR_MALLOC_US(SZPOS) \
+ __attribute__((malloc)) \
+ ERTS_ATTR_ALLOC_SIZE(SZPOS) \
+ ERTS_ATTR_WUR
+
+# undef ERTS_ATTR_MALLOC_D
+# if defined(__GNUC__) && __GNUC__ >= 11
+# define ERTS_ATTR_MALLOC_D(DTOR, PTRPOS) \
+ __attribute__((malloc(DTOR,PTRPOS))) \
+ ERTS_ATTR_WUR
+# else
+# define ERTS_ATTR_MALLOC_D(DTOR, PTRPOS) \
+ ERTS_ATTR_WUR
+# endif
+
+# undef ERTS_ATTR_MALLOC_UD
+# define ERTS_ATTR_MALLOC_UD(DTOR, PTRPOS) \
+ ERTS_ATTR_MALLOC_U \
+ ERTS_ATTR_MALLOC_D(DTOR, PTRPOS)
+
+# undef ERTS_ATTR_MALLOC_USD
+# define ERTS_ATTR_MALLOC_USD(SZPOS, DTOR, PTRPOS) \
+ ERTS_ATTR_MALLOC_US(SZPOS) \
+ ERTS_ATTR_MALLOC_D(DTOR, PTRPOS)
+# endif
#endif
+
+#endif /* __SYS_H__ */
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index ce57b041d6..851b3d6109 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -134,7 +134,7 @@
* will be triggered at once. The circular list of the slot will
* be moved to the 'sentinel' field while bumping these timers
* as when bumping an ordinary wheel slot. A yielding bump
- * operation and cancelation of timers is handled the same way
+ * operation and cancellation of timers is handled the same way
* as if the timer was in a wheel slot.
*
* -- Searching for Next Timeout --
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 80d92c5602..9feb3aab0e 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,6 +60,8 @@
#include "erl_nfunc_sched.h"
#include "erl_proc_sig_queue.h"
#include "erl_unicode.h"
+#include "beam_common.h"
+#include "erl_global_literals.h"
/* *******************************
* ** Yielding C Fun (YCF) Note **
@@ -566,8 +568,16 @@ erts_bld_tuple(Uint **hpp, Uint *szp, Uint arity, ...)
ASSERT(arity < (((Uint)1) << (sizeof(Uint)*8 - _HEADER_ARITY_OFFS)));
- if (szp)
- *szp += arity + 1;
+ if (szp) {
+ if (arity == 0) {
+ *szp = 0;
+ } else {
+ *szp += arity + 1;
+ }
+ }
+ if (arity == 0) {
+ return ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ }
if (hpp) {
res = make_tuple(*hpp);
*((*hpp)++) = make_arityval(arity);
@@ -596,8 +606,16 @@ Eterm erts_bld_tuplev(Uint **hpp, Uint *szp, Uint arity, Eterm terms[])
ASSERT(arity < (((Uint)1) << (sizeof(Uint)*8 - _HEADER_ARITY_OFFS)));
- if (szp)
- *szp += arity + 1;
+ if (szp) {
+ if (arity == 0) {
+ *szp = 0;
+ } else {
+ *szp += arity + 1;
+ }
+ }
+ if (arity == 0) {
+ return ERTS_GLOBAL_LIT_EMPTY_TUPLE;
+ }
if (hpp) {
res = make_tuple(*hpp);
@@ -791,7 +809,7 @@ erts_bld_atom_2uint_3tup_list(Uint **hpp, Uint *szp, Sint length,
** h(0) = <initial hash>
** h(i) = h(i-1)*X + B(i-1)
** The above should hold regardless of internal representation.
-** Pids are hashed like small numbers but with differrent constants, as are
+** Pids are hashed like small numbers but with different constants, as are
** ports.
** References are hashed like ports but only on the least significant byte.
** Binaries are hashed on all bytes (not on the 15 first as in
@@ -938,37 +956,43 @@ tail_recur:
hash = hash*FUNNY_NUMBER4 + sz;
break;
}
- case EXPORT_DEF:
- {
- Export* ep = *((Export **) (export_val(term) + 1));
+ case FUN_DEF:
+ {
+ ErlFunThing* funp = (ErlFunThing *) fun_val(term);
- hash = hash * FUNNY_NUMBER11 + ep->info.mfa.arity;
- hash = hash*FUNNY_NUMBER1 +
- (atom_tab(atom_val(ep->info.mfa.module))->slot.bucket.hvalue);
- hash = hash*FUNNY_NUMBER1 +
- (atom_tab(atom_val(ep->info.mfa.function))->slot.bucket.hvalue);
- break;
- }
+ if (is_local_fun(funp)) {
- case FUN_DEF:
- {
- ErlFunThing* funp = (ErlFunThing *) fun_val(term);
- Uint num_free = funp->num_free;
-
- hash = hash * FUNNY_NUMBER10 + num_free;
- hash = hash*FUNNY_NUMBER1 +
- (atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue);
- hash = hash*FUNNY_NUMBER2 + funp->fe->index;
- hash = hash*FUNNY_NUMBER2 + funp->fe->old_uniq;
- if (num_free > 0) {
- if (num_free > 1) {
- WSTACK_PUSH3(stack, (UWord) &funp->env[1], (num_free-1), MAKE_HASH_TERM_ARRAY_OP);
- }
- term = funp->env[0];
- goto tail_recur;
- }
- break;
- }
+ ErlFunEntry* fe = funp->entry.fun;
+ Uint num_free = funp->num_free;
+
+ hash = hash * FUNNY_NUMBER10 + num_free;
+ hash = hash*FUNNY_NUMBER1 +
+ (atom_tab(atom_val(fe->module))->slot.bucket.hvalue);
+ hash = hash*FUNNY_NUMBER2 + fe->index;
+ hash = hash*FUNNY_NUMBER2 + fe->old_uniq;
+
+ if (num_free > 0) {
+ if (num_free > 1) {
+ WSTACK_PUSH3(stack, (UWord) &funp->env[1],
+ (num_free-1), MAKE_HASH_TERM_ARRAY_OP);
+ }
+
+ term = funp->env[0];
+ goto tail_recur;
+ }
+ } else {
+ const ErtsCodeMFA *mfa = &funp->entry.exp->info.mfa;
+
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+
+ hash = hash * FUNNY_NUMBER11 + mfa->arity;
+ hash = hash*FUNNY_NUMBER1 +
+ (atom_tab(atom_val(mfa->module))->slot.bucket.hvalue);
+ hash = hash*FUNNY_NUMBER1 +
+ (atom_tab(atom_val(mfa->function))->slot.bucket.hvalue);
+ }
+ break;
+ }
case PID_DEF:
/* only 15 bits... */
UINT32_HASH_RET(internal_pid_number(term),FUNNY_NUMBER5,FUNNY_NUMBER6);
@@ -1670,43 +1694,50 @@ make_hash2_helper(Eterm term_param, const int can_trap, Eterm* state_mref_write_
goto hash2_common;
}
break;
- case EXPORT_SUBTAG:
- {
- Export* ep = *((Export **) (export_val(term) + 1));
- UINT32_HASH_2
- (ep->info.mfa.arity,
- atom_tab(atom_val(ep->info.mfa.module))->slot.bucket.hvalue,
- HCONST);
- UINT32_HASH
- (atom_tab(atom_val(ep->info.mfa.function))->slot.bucket.hvalue,
- HCONST_14);
- goto hash2_common;
- }
- case FUN_SUBTAG:
- {
- ErlFunThing* funp = (ErlFunThing *) fun_val(term);
- ErtsMakeHash2Context_FUN_SUBTAG ctx = {
- .num_free = funp->num_free,
- .bptr = NULL};
- UINT32_HASH_2
- (ctx.num_free,
- atom_tab(atom_val(funp->fe->module))->slot.bucket.hvalue,
- HCONST);
- UINT32_HASH_2
- (funp->fe->index, funp->fe->old_uniq, HCONST);
- if (ctx.num_free == 0) {
- goto hash2_common;
- } else {
- ctx.bptr = funp->env + ctx.num_free - 1;
- while (ctx.num_free-- > 1) {
- term = *ctx.bptr--;
- ESTACK_PUSH(s, term);
+ case FUN_SUBTAG:
+ {
+ ErlFunThing* funp = (ErlFunThing *) fun_val(term);
+
+ if (is_local_fun(funp)) {
+ ErlFunEntry* fe = funp->entry.fun;
+ ErtsMakeHash2Context_FUN_SUBTAG ctx = {
+ .num_free = funp->num_free,
+ .bptr = NULL};
+
+ UINT32_HASH_2
+ (ctx.num_free,
+ atom_tab(atom_val(fe->module))->slot.bucket.hvalue,
+ HCONST);
+ UINT32_HASH_2
+ (fe->index, fe->old_uniq, HCONST);
+ if (ctx.num_free == 0) {
+ goto hash2_common;
+ } else {
+ ctx.bptr = funp->env + ctx.num_free - 1;
+ while (ctx.num_free-- > 1) {
+ term = *ctx.bptr--;
+ ESTACK_PUSH(s, term);
TRAP_LOCATION(fun_subtag);
- }
- term = *ctx.bptr;
- }
- }
+ }
+ term = *ctx.bptr;
+ }
+ } else {
+ Export *ep = funp->entry.exp;
+
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
+
+ UINT32_HASH_2
+ (ep->info.mfa.arity,
+ atom_tab(atom_val(ep->info.mfa.module))->slot.bucket.hvalue,
+ HCONST);
+ UINT32_HASH
+ (atom_tab(atom_val(ep->info.mfa.function))->slot.bucket.hvalue,
+ HCONST_14);
+
+ goto hash2_common;
+ }
+ }
break;
case REFC_BINARY_SUBTAG:
case HEAP_BINARY_SUBTAG:
@@ -2047,6 +2078,17 @@ trapping_make_hash2(Eterm term, Eterm* state_mref_write_back, Process* p)
return make_hash2_helper(term, 1, state_mref_write_back, p);
}
+/* Term hash function for maps, with a separate depth parameter */
+Uint32 make_map_hash(Eterm key, int depth) {
+ Uint32 hash = 0;
+
+ if (depth > 0) {
+ UINT32_HASH_2(depth, 1, HCONST_22);
+ }
+
+ return make_internal_hash(key, hash);
+}
+
/* Term hash function for internal use.
*
* Limitation #1: Is not "portable" in any way between different VM instances.
@@ -2215,32 +2257,34 @@ make_internal_hash(Eterm term, Uint32 salt)
goto pop_next;
}
break;
- case EXPORT_SUBTAG:
- {
- Export* ep = *((Export **) (export_val(term) + 1));
- /* Assumes Export entries never move */
- POINTER_HASH(ep, HCONST_14);
- goto pop_next;
- }
+ case FUN_SUBTAG:
+ {
+ ErlFunThing* funp = (ErlFunThing *) fun_val(term);
+
+ if (is_local_fun(funp)) {
+ ErlFunEntry* fe = funp->entry.fun;
+ Uint num_free = funp->num_free;
+ UINT32_HASH_2(num_free, fe->module, HCONST_20);
+ UINT32_HASH_2(fe->index, fe->old_uniq, HCONST_21);
+ if (num_free == 0) {
+ goto pop_next;
+ } else {
+ Eterm* bptr = funp->env + num_free - 1;
+ while (num_free-- > 1) {
+ term = *bptr--;
+ ESTACK_PUSH(s, term);
+ }
+ term = *bptr;
+ }
+ } else {
+ ASSERT(is_external_fun(funp) && funp->next == NULL);
- case FUN_SUBTAG:
- {
- ErlFunThing* funp = (ErlFunThing *) fun_val(term);
- Uint num_free = funp->num_free;
- UINT32_HASH_2(num_free, funp->fe->module, HCONST_20);
- UINT32_HASH_2(funp->fe->index, funp->fe->old_uniq, HCONST_21);
- if (num_free == 0) {
- goto pop_next;
- } else {
- Eterm* bptr = funp->env + num_free - 1;
- while (num_free-- > 1) {
- term = *bptr--;
- ESTACK_PUSH(s, term);
- }
- term = *bptr;
- }
- }
- break;
+ /* Assumes Export entries never move */
+ POINTER_HASH(funp->entry.exp, HCONST_14);
+ goto pop_next;
+ }
+ }
+ break;
case REFC_BINARY_SUBTAG:
case HEAP_BINARY_SUBTAG:
case SUB_BINARY_SUBTAG:
@@ -2417,9 +2461,9 @@ make_internal_hash(Eterm term, Uint32 salt)
{log, Level, format, [args], #{ gl, pid, time, error_logger => #{tag, emulator => true} }}
*/
static Eterm
-do_allocate_logger_message(Eterm gleader, ErtsMonotonicTime *ts, Eterm *pid,
- Eterm **hp, ErlOffHeap **ohp,
- ErlHeapFragment **bp, Uint sz)
+do_allocate_logger_message(ErtsHeapFactory *factory,
+ Eterm gleader, ErtsMonotonicTime *ts,
+ Eterm *pid, Uint sz)
{
Uint gl_sz;
gl_sz = IS_CONST(gleader) ? 0 : size_object(gleader);
@@ -2438,19 +2482,25 @@ do_allocate_logger_message(Eterm gleader, ErtsMonotonicTime *ts, Eterm *pid,
*ts = ERTS_MONOTONIC_TO_USEC(erts_os_system_time());
erts_bld_sint64(NULL, &sz, *ts);
- *bp = new_message_buffer(sz);
- *ohp = &(*bp)->off_heap;
- *hp = (*bp)->mem;
-
- return copy_struct(gleader,gl_sz,hp,*ohp);
+ erts_factory_heap_frag_init(factory, new_message_buffer(sz));
+ {
+ Eterm *hp = erts_produce_heap(factory, gl_sz, 0);
+ return copy_struct(gleader,gl_sz,&hp,factory->off_heap);
+ }
}
-static void do_send_logger_message(Eterm gl, Eterm tag, Eterm format, Eterm args,
- ErtsMonotonicTime ts, Eterm pid,
- Eterm *hp, ErlHeapFragment *bp)
+static void do_send_logger_message(ErtsHeapFactory *factory,
+ Eterm gl, Eterm tag, Eterm format, Eterm args,
+ ErtsMonotonicTime ts, Eterm pid)
{
+ Eterm *hp;
Eterm message, md, el_tag = tag;
- Eterm time = erts_bld_sint64(&hp, NULL, ts);
+ Uint sz = 0;
+ Eterm time;
+
+ erts_bld_sint64(NULL, &sz, ts);
+ hp = erts_produce_heap(factory, sz, 0);
+ time = erts_bld_sint64(&hp, NULL, ts);
/* This mapping is needed for the backwards compatible error_logger */
switch (tag) {
@@ -2461,42 +2511,40 @@ static void do_send_logger_message(Eterm gl, Eterm tag, Eterm format, Eterm args
break;
}
+ hp = erts_produce_heap(factory, MAP2_SZ, 0);
md = MAP2(hp, am_emulator, am_true, ERTS_MAKE_AM("tag"), el_tag);
- hp += MAP2_SZ;
if (is_nil(gl) && is_non_value(pid)) {
/* no gl and no pid, probably from a port */
+ hp = erts_produce_heap(factory, MAP2_SZ, 0);
md = MAP2(hp,
am_error_logger, md,
am_time, time);
- hp += MAP2_SZ;
pid = NIL;
} else if (is_nil(gl)) {
/* no gl */
+ hp = erts_produce_heap(factory, MAP3_SZ, 0);
md = MAP3(hp,
am_error_logger, md,
am_pid, pid,
am_time, time);
- hp += MAP3_SZ;
} else if (is_non_value(pid)) {
/* no gl */
+ hp = erts_produce_heap(factory, MAP3_SZ, 0);
md = MAP3(hp,
am_error_logger, md,
ERTS_MAKE_AM("gl"), gl,
am_time, time);
- hp += MAP3_SZ;
pid = NIL;
} else {
- md = MAP4(hp,
- am_error_logger, md,
- ERTS_MAKE_AM("gl"), gl,
- am_pid, pid,
- am_time, time);
- hp += MAP4_SZ;
+ Eterm keys[] = { am_error_logger, ERTS_MAKE_AM("gl"), am_pid, am_time };
+ Eterm values[] = { md, gl, pid, time };
+ md = erts_map_from_ks_and_vs(factory, keys, values, 4);
}
-
+ hp = erts_produce_heap(factory, 6, 0);
message = TUPLE5(hp, am_log, tag, format, args, md);
- erts_queue_error_logger_message(pid, message, bp);
+ erts_factory_close(factory);
+ erts_queue_error_logger_message(pid, message, factory->heap_frags);
}
static int do_send_to_logger(Eterm tag, Eterm gl, char *buf, size_t len)
@@ -2504,23 +2552,23 @@ static int do_send_to_logger(Eterm tag, Eterm gl, char *buf, size_t len)
Uint sz;
Eterm list, args, format, pid;
ErtsMonotonicTime ts;
+ ErtsHeapFactory factory;
Eterm *hp = NULL;
- ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
sz = len * 2 /* message list */ + 2 /* cons surrounding message list */
+ 8 /* "~s~n" */;
/* gleader size is accounted and allocated next */
- gl = do_allocate_logger_message(gl, &ts, &pid, &hp, &ohp, &bp, sz);
+ gl = do_allocate_logger_message(&factory, gl, &ts, &pid, sz);
+ hp = erts_produce_heap(&factory, sz, 0);
list = buf_to_intlist(&hp, buf, len, NIL);
args = CONS(hp,list,NIL);
hp += 2;
format = buf_to_intlist(&hp, "~s~n", 4, NIL);
- do_send_logger_message(gl, tag, format, args, ts, pid, hp, bp);
+ do_send_logger_message(&factory, gl, tag, format, args, ts, pid);
return 0;
}
@@ -2533,8 +2581,7 @@ static int do_send_term_to_logger(Eterm tag, Eterm gl,
ErtsMonotonicTime ts;
Eterm *hp = NULL;
- ErlOffHeap *ohp = NULL;
- ErlHeapFragment *bp = NULL;
+ ErtsHeapFactory factory;
ASSERT(len > 0);
@@ -2542,12 +2589,13 @@ static int do_send_term_to_logger(Eterm tag, Eterm gl,
sz = len * 2 /* format */ + args_sz;
/* gleader size is accounted and allocated next */
- gl = do_allocate_logger_message(gl, &ts, &pid, &hp, &ohp, &bp, sz);
+ gl = do_allocate_logger_message(&factory, gl, &ts, &pid, sz);
+ hp = erts_produce_heap(&factory, sz, 0);
format = buf_to_intlist(&hp, buf, len, NIL);
- args = copy_struct(args, args_sz, &hp, ohp);
+ args = copy_struct(args, args_sz, &hp, factory.off_heap);
- do_send_logger_message(gl, tag, format, args, ts, pid, hp, bp);
+ do_send_logger_message(&factory, gl, tag, format, args, ts, pid);
return 0;
}
@@ -2851,35 +2899,46 @@ tailrecur_ne:
}
break; /* not equal */
}
- case EXPORT_SUBTAG:
- {
- if (is_export(b)) {
- Export* a_exp = *((Export **) (export_val(a) + 1));
- Export* b_exp = *((Export **) (export_val(b) + 1));
- if (a_exp == b_exp) goto pop_next;
- }
- break; /* not equal */
- }
- case FUN_SUBTAG:
- {
- ErlFunThing* f1;
- ErlFunThing* f2;
+ case FUN_SUBTAG:
+ {
+ ErlFunThing* f1;
+ ErlFunThing* f2;
- if (!is_fun(b))
- goto not_equal;
- f1 = (ErlFunThing *) fun_val(a);
- f2 = (ErlFunThing *) fun_val(b);
- if (f1->fe->module != f2->fe->module ||
- f1->fe->index != f2->fe->index ||
- f1->fe->old_uniq != f2->fe->old_uniq ||
- f1->num_free != f2->num_free) {
- goto not_equal;
- }
- if ((sz = f1->num_free) == 0) goto pop_next;
- aa = f1->env;
- bb = f2->env;
- goto term_array;
- }
+ if (is_not_any_fun(b)) {
+ goto not_equal;
+ }
+
+ f1 = (ErlFunThing *) fun_val(a);
+ f2 = (ErlFunThing *) fun_val(b);
+
+ if (is_local_fun(f1) && is_local_fun(f2)) {
+ ErlFunEntry *fe1, *fe2;
+
+ fe1 = f1->entry.fun;
+ fe2 = f2->entry.fun;
+
+ if (fe1->module != fe2->module ||
+ fe1->index != fe2->index ||
+ fe1->old_uniq != fe2->old_uniq ||
+ f1->num_free != f2->num_free) {
+ goto not_equal;
+ }
+
+ if ((sz = f1->num_free) == 0) {
+ goto pop_next;
+ }
+
+ aa = f1->env;
+ bb = f2->env;
+ goto term_array;
+ } else if (is_external_fun(f1) && is_external_fun(f2)) {
+ if (f1->entry.exp == f2->entry.exp) {
+ goto pop_next;
+ }
+ }
+
+ goto not_equal;
+ }
case EXTERNAL_PID_SUBTAG: {
ExternalThing *ap;
@@ -3474,58 +3533,69 @@ tailrecur_ne:
goto mixed_types;
}
ON_CMP_GOTO(big_comp(a, b));
- case (_TAG_HEADER_EXPORT >> _TAG_PRIMARY_SIZE):
- if (!is_export(b)) {
- a_tag = EXPORT_DEF;
- goto mixed_types;
- } else {
- Export* a_exp = *((Export **) (export_val(a) + 1));
- Export* b_exp = *((Export **) (export_val(b) + 1));
- if ((j = erts_cmp_atoms(a_exp->info.mfa.module,
- b_exp->info.mfa.module)) != 0) {
- RETURN_NEQ(j);
- }
- if ((j = erts_cmp_atoms(a_exp->info.mfa.function,
- b_exp->info.mfa.function)) != 0) {
- RETURN_NEQ(j);
- }
- ON_CMP_GOTO((Sint) a_exp->info.mfa.arity - (Sint) b_exp->info.mfa.arity);
- }
- break;
- case (_TAG_HEADER_FUN >> _TAG_PRIMARY_SIZE):
- if (!is_fun(b)) {
- a_tag = FUN_DEF;
- goto mixed_types;
- } else {
- ErlFunThing* f1 = (ErlFunThing *) fun_val(a);
- ErlFunThing* f2 = (ErlFunThing *) fun_val(b);
- Sint diff;
+ case (_TAG_HEADER_FUN >> _TAG_PRIMARY_SIZE):
+ if (is_not_any_fun(b)) {
+ a_tag = FUN_DEF;
+ goto mixed_types;
+ } else {
+ ErlFunThing* f1 = (ErlFunThing *) fun_val(a);
+ ErlFunThing* f2 = (ErlFunThing *) fun_val(b);
- diff = erts_cmp_atoms((f1->fe)->module, (f2->fe)->module);
- if (diff != 0) {
- RETURN_NEQ(diff);
- }
- diff = f1->fe->index - f2->fe->index;
- if (diff != 0) {
- RETURN_NEQ(diff);
- }
- diff = f1->fe->old_uniq - f2->fe->old_uniq;
- if (diff != 0) {
- RETURN_NEQ(diff);
- }
- diff = f1->num_free - f2->num_free;
- if (diff != 0) {
- RETURN_NEQ(diff);
- }
- i = f1->num_free;
- if (i == 0) goto pop_next;
- aa = f1->env;
- bb = f2->env;
- goto term_array;
- }
- case (_TAG_HEADER_EXTERNAL_PID >> _TAG_PRIMARY_SIZE):
- if (!is_pid(b)) {
+ if (is_local_fun(f1) && is_local_fun(f2)) {
+ ErlFunEntry* fe1 = f1->entry.fun;
+ ErlFunEntry* fe2 = f2->entry.fun;
+
+ Sint diff;
+
+ diff = erts_cmp_atoms(fe1->module, (fe2)->module);
+
+ if (diff != 0) {
+ RETURN_NEQ(diff);
+ }
+
+ diff = fe1->index - fe2->index;
+ if (diff != 0) {
+ RETURN_NEQ(diff);
+ }
+
+ diff = fe1->old_uniq - fe2->old_uniq;
+ if (diff != 0) {
+ RETURN_NEQ(diff);
+ }
+
+ diff = f1->num_free - f2->num_free;
+ if (diff != 0) {
+ RETURN_NEQ(diff);
+ }
+
+ i = f1->num_free;
+ if (i == 0) goto pop_next;
+ aa = f1->env;
+ bb = f2->env;
+ goto term_array;
+ } else if (is_external_fun(f1) && is_external_fun(f2)) {
+ Export* a_exp = f1->entry.exp;
+ Export* b_exp = f2->entry.exp;
+
+ if ((j = erts_cmp_atoms(a_exp->info.mfa.module,
+ b_exp->info.mfa.module)) != 0) {
+ RETURN_NEQ(j);
+ }
+ if ((j = erts_cmp_atoms(a_exp->info.mfa.function,
+ b_exp->info.mfa.function)) != 0) {
+ RETURN_NEQ(j);
+ }
+
+ ON_CMP_GOTO((Sint) a_exp->info.mfa.arity -
+ (Sint) b_exp->info.mfa.arity);
+ } else {
+ /* External funs compare greater than local ones. */
+ RETURN_NEQ(is_external_fun(f1) - is_external_fun(f2));
+ }
+ }
+ case (_TAG_HEADER_EXTERNAL_PID >> _TAG_PRIMARY_SIZE):
+ if (!is_pid(b)) {
a_tag = EXTERNAL_PID_DEF;
goto mixed_types;
}
@@ -4107,7 +4177,7 @@ erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written)
{
Eterm* listptr;
Sint sz = 0;
- Sint val;
+ Uint val;
int res;
while (1) {
@@ -4130,8 +4200,8 @@ erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written)
res = -1;
break;
}
- val = signed_val(CAR(listptr));
- if (0 <= val && val < 0x80) {
+ val = (Uint) signed_val(CAR(listptr));
+ if (val < 0x80) {
buf[sz] = val;
sz++;
} else if (val < 0x800) {
@@ -4180,13 +4250,13 @@ erts_unicode_list_to_buf_len(Eterm list)
listptr = list_val(list);
while (1) {
- Sint val;
+ Uint val;
if (is_not_small(CAR(listptr))) {
return -1;
}
- val = signed_val(CAR(listptr));
- if (0 <= val && val < 0x80) {
+ val = (Uint) signed_val(CAR(listptr));
+ if (val < 0x80) {
sz++;
} else if (val < 0x800) {
sz += 2;
@@ -5135,15 +5205,7 @@ erts_build_mfa_item(FunctionInfo* fi, Eterm* hp, Eterm args, Eterm* mfa_p, Eterm
Eterm tuple;
int line = LOC_LINE(fi->loc);
int file = LOC_FILE(fi->loc);
- Eterm file_term = NIL;
-
- if (file == 0) {
- Atom* ap = atom_tab(atom_val(fi->mfa->module));
- file_term = buf_to_intlist(&hp, ".erl", 4, NIL);
- file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, file_term);
- } else {
- file_term = erts_atom_to_string(&hp, (fi->fname_ptr)[file-1]);
- }
+ Eterm file_term = fi->fname_ptr[file];
tuple = TUPLE2(hp, am_line, make_small(line));
hp += 3;
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index cf3c5fa3f6..ec5f9a655c 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -111,6 +111,50 @@
#include "erl_driver.h"
+
+#if !defined(TRUE)
+#define TRUE 1
+#endif
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+
+/* Descriptor debug */
+#ifdef INET_DRV_DEBUG
+#define DDBG_DEFAULT TRUE
+#else
+#define DDBG_DEFAULT FALSE
+#endif
+#define DDBG(__D__, __ARG__) if ( (__D__)->debug ) erts_printf __ARG__
+
+#define B2S(__B__) ((__B__) ? "true" : "false")
+#define SH2S(__H__) (((__H__) == TCP_SHUT_WR) ? "write" : \
+ (((__H__) == TCP_SHUT_RD) ? "read" : \
+ (((__H__) == TCP_SHUT_RDWR) ? "read-write" : \
+ "undefined")))
+#define A2S(__A__) (((__A__) == INET_PASSIVE) ? "passive" : \
+ (((__A__) == INET_ACTIVE) ? "active" : \
+ (((__A__) == INET_ONCE) ? "once" : \
+ (((__A__) == INET_MULTI) ? "multi" : \
+ "undefined"))))
+#define M2S(__M__) (((__M__) == INET_MODE_LIST) ? "list" : \
+ (((__M__) == INET_MODE_BINARY) ? "binary" : \
+ "undefined"))
+#define D2S(__D__) (((__D__) == INET_DELIVER_PORT) ? "port" : \
+ (((__D__) == INET_DELIVER_TERM) ? "term" : \
+ "undefined"))
+#define DOM2S(__D__) (((__D__) == INET_AF_INET) ? "inet" : \
+ (((__D__) == INET_AF_INET6) ? "inet6" : \
+ (((__D__) == INET_AF_LOCAL) ? "local" : \
+ "undefined")))
+
+#if defined(__WIN32__) && defined(ARCH_64)
+#define SOCKET_FSTR "%lld"
+#else
+#define SOCKET_FSTR "%d"
+#endif
+
+
/* The IS_SOCKET_ERROR macro below is used for portability reasons. While
POSIX specifies that errors from socket-related system calls should be
indicated with a -1 return value, some users have experienced non-Windows
@@ -517,6 +561,13 @@ static typeof(sctp_freepaddrs) *p_sctp_freepaddrs = NULL;
static void (*p_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
#endif
+#if defined(__GNUC__) && defined(HAVE_SCTP_CONNECTX)
+static typeof(sctp_connectx) *p_sctp_connectx = NULL;
+#else
+static int (*p_sctp_connectx)
+ (int sd, struct sockaddr * addrs, int addrcnt, sctp_assoc_t * assoc_id) = NULL;
+#endif
+
#endif /* #if defined(HAVE_SCTP_H) */
#ifndef WANT_NONBLOCKING
@@ -527,10 +578,11 @@ static void (*p_sctp_freepaddrs)(struct sockaddr *addrs) = NULL;
/* #define INET_DRV_DEBUG 1 */
#ifdef INET_DRV_DEBUG
#define DEBUG 1
-#undef DEBUGF
-#define DEBUGF(X) printf X
+#undef DEBUGF
+#define DEBUGF(__X__) erts_printf __X__
#endif
+
#if !defined(HAVE_STRNCASECMP)
#define STRNCASECMP my_strncasecmp
@@ -690,6 +742,7 @@ static size_t my_strnlen(const char *s, size_t maxlen)
#define INET_AF_LOOPBACK 4 /* INADDR_LOOPBACK or IN6ADDR_LOOPBACK_INIT */
#define INET_AF_LOCAL 5
#define INET_AF_UNDEFINED 6 /* Unknown */
+#define INET_AF_LIST 7 /* List of addresses for sctp connectx */
/* open and INET_REQ_GETTYPE enumeration */
#define INET_TYPE_STREAM 1
@@ -839,6 +892,8 @@ static size_t my_strnlen(const char *s, size_t maxlen)
#define INET_OPT_TTL 46 /* IP_TTL */
#define INET_OPT_RECVTTL 47 /* IP_RECVTTL ancillary data */
#define TCP_OPT_NOPUSH 48 /* super-Nagle, aka TCP_CORK */
+#define INET_LOPT_DEBUG 99 /* Enable/disable DEBUG for a socket */
+
/* SCTP options: a separate range, from 100: */
#define SCTP_OPT_RTOINFO 100
#define SCTP_OPT_ASSOCINFO 101
@@ -1014,6 +1069,26 @@ typedef union {
} inet_address;
+/* On some platforms, for instance FreeBSD, this option is instead
+ * called IPV6_JOIN_GROUP and IPV6_JOIN_GROUP. */
+
+#if defined(HAVE_IN6)
+
+#if defined(IPV6_ADD_MEMBERSHIP)
+#define INET_ADD_MEMBERSHIP IPV6_ADD_MEMBERSHIP
+#elif defined(IPV6_JOIN_GROUP)
+#define INET_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#endif
+
+#if defined(IPV6_DROP_MEMBERSHIP)
+#define INET_DROP_MEMBERSHIP IPV6_DROP_MEMBERSHIP
+#elif defined(IPV6_LEAVE_GROUP)
+#define INET_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
+#endif
+
+#endif
+
+
#define inet_address_port(x) \
((((x)->sai.sin_family == AF_INET) || \
((x)->sai.sin_family == AF_INET6)) ? \
@@ -1148,7 +1223,7 @@ typedef struct {
unsigned long recv_cnt; /* number of packets received */
unsigned long recv_max; /* maximum packet size received */
double recv_avg; /* average packet size received */
- double recv_dvi; /* avarage deviation from avg_size */
+ double recv_dvi; /* average deviation from avg_size */
#ifdef ARCH_64
Uint64 send_oct; /* number of octets sent, 64 bits */
#else
@@ -1166,6 +1241,7 @@ typedef struct {
as full file path */
#endif
int recv_cmsgflags; /* Which ancillary data to expect */
+ int debug; /* debug enabled or not */
} inet_descriptor;
@@ -1558,12 +1634,12 @@ static void *realloc_wrapper(void *current, ErlDrvSizeT size){
return ret;
}
#define REALLOC(X,Y) realloc_wrapper(X,Y)
-#define FREE(P) driver_free((P))
+#define FREE(P) driver_free((P))
#else /* FATAL_MALLOC */
-#define ALLOC(X) driver_alloc((X))
+#define ALLOC(X) driver_alloc((X))
#define REALLOC(X,Y) driver_realloc((X), (Y))
-#define FREE(P) driver_free((P))
+#define FREE(P) driver_free((P))
#endif /* FATAL_MALLOC */
@@ -1775,7 +1851,7 @@ static int load_inet_get_address
#define INET_DRV_CACHE_LINE_MASK (INET_DRV_CACHE_LINE_SIZE - 1)
/*
-** Binary Buffer Managment
+** Binary Buffer Management
** We keep a stack of usable buffers
*/
#define BUFFER_STACK_SIZE 14
@@ -2302,6 +2378,43 @@ static int async_ok(inet_descriptor* desc)
return send_async_ok(desc->dport, aid, caller);
}
+#ifdef HAVE_SCTP
+static int async_ok_assoc_id(inet_descriptor* desc, sctp_assoc_t assoc_id)
+{
+ int req;
+ int aid;
+ int i = 0;
+ ErlDrvTermData caller;
+ ErlDrvTermData spec[2*LOAD_ATOM_CNT + LOAD_PORT_CNT + LOAD_INT_CNT +
+ LOAD_ASSOC_ID_CNT + 2*LOAD_TUPLE_CNT];
+
+ if (deq_async(desc, &aid, &caller, &req) < 0)
+ return -1;
+
+ i = LOAD_ATOM(spec, i, am_inet_async);
+ i = LOAD_PORT(spec, i, desc->dport);
+ i = LOAD_INT(spec, i, aid);
+ {
+ i = LOAD_ATOM(spec, i, am_ok);
+ i = LOAD_ASSOC_ID(spec, i, assoc_id);
+ i = LOAD_TUPLE(spec, i, 2);
+ }
+ i = LOAD_TUPLE(spec, i, 4);
+
+ ASSERT(i == sizeof(spec)/sizeof(*spec));
+
+ return erl_drv_send_term(desc->dport, caller, spec, i);
+}
+
+static int async_ok_maybe_assoc_id(inet_descriptor* desc, sctp_assoc_t *p_assoc_id)
+{
+ if (p_assoc_id)
+ return async_ok_assoc_id(desc, *p_assoc_id);
+ else
+ return async_ok(desc);
+}
+#endif
+
static int async_ok_port(inet_descriptor* desc, ErlDrvTermData Port2)
{
int req;
@@ -3491,7 +3604,7 @@ static int compile_ancillary_data(struct msghdr *mhdr,
break;
}
default:
- /* Unknow socket option */
+ /* Unknown socket option */
return 1;
}
#undef COMPILE_ANCILLARY_DATA_ITEM
@@ -4270,6 +4383,11 @@ static int inet_init()
p_sctp_getpaddrs = NULL;
p_sctp_freepaddrs = NULL;
# endif
+# if defined(HAVE_SCTP_CONNECTX)
+ p_sctp_connectx = sctp_connectx;
+# else
+ p_sctp_connectx = NULL;
+# endif
inet_init_sctp();
add_driver_entry(&sctp_inet_driver_entry);
# else
@@ -4310,6 +4428,10 @@ static int inet_init()
p_sctp_freepaddrs = NULL;
p_sctp_getpaddrs = NULL;
}
+ if (erts_sys_ddll_vsym(h_libsctp, "sctp_connectx", "VERS_3", &ptr) == 0) {
+ p_sctp_connectx = ptr;
+ }
+ else p_sctp_connectx = NULL;
inet_init_sctp();
add_driver_entry(&sctp_inet_driver_entry);
}
@@ -4343,10 +4465,6 @@ static char* inet_set_address(int family, inet_address* dst,
{
short port;
- // printf("inet_set_address -> entry with"
- // "\r\n family: %d"
- // "\r\n", family);
-
switch (family) {
case AF_INET: {
if (*len < 2+4) return str_einval;
@@ -4376,12 +4494,8 @@ static char* inet_set_address(int family, inet_address* dst,
sys_memcpy(&dst->sai6.sin6_addr, *src, 16);
*src += 16;
dst->sai6.sin6_flowinfo = get_int32(*src);
- // printf("inet_set_address -> flowinfo: %u"
- // "\r\n", dst->sai6.sin6_flowinfo);
*src += 4;
dst->sai6.sin6_scope_id = get_int32(*src);
- // printf("inet_set_address -> scope_id: %u"
- // "\r\n", dst->sai6.sin6_scope_id);
*src += 4;
*len = sizeof(struct sockaddr_in6);
return NULL;
@@ -4857,6 +4971,7 @@ static ErlDrvSSizeT inet_ctl_open(inet_descriptor* desc, int domain, int type,
desc->state = INET_STATE_OPEN;
desc->stype = type;
desc->sfamily = domain;
+
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -4869,6 +4984,18 @@ static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
inet_address name;
SOCKLEN_T sz;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_ctl_fdopen -> entry with"
+ "\r\n socket: %d"
+ "\r\n bound: %s"
+ "\r\n domain: %d"
+ "\r\n type: %d"
+ "\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port),
+ s, B2S(bound), domain, type) );
+
if (bound) {
/* check that it is a socket and that the socket is bound */
sz = sizeof(name);
@@ -4902,6 +5029,12 @@ static ErlDrvSSizeT inet_ctl_fdopen(inet_descriptor* desc, int domain, int type,
* not certain that we can open it again */
desc->stype = type;
desc->sfamily = domain;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_ctl_fdopen -> done\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
@@ -5586,7 +5719,7 @@ static ErlDrvSSizeT inet_ctl_ifget(inet_descriptor* desc,
else {
struct sockadd_in* ap;
/* emulate netmask,
- * (wasted stuff since noone uses classes)
+ * (wasted stuff since no one uses classes)
*/
buf_check(sptr, s_end, 1);
*sptr++ = INET_IFOPT_NETMASK;
@@ -5840,9 +5973,10 @@ static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
{
int i;
DWORD ret, n;
- IP_INTERFACE_INFO *info_p;
- MIB_IPADDRTABLE *ip_addrs_p;
- IP_ADAPTER_ADDRESSES *ip_adaddrs_p, *ia_p;
+ IP_INTERFACE_INFO *info_p = NULL;
+ MIB_IPADDRTABLE *ip_addrs_p = NULL;
+ IP_ADAPTER_ADDRESSES *ip_adaddrs_p = NULL;
+ IP_ADAPTER_ADDRESSES *ia_p = NULL;
char *buf_p;
char *buf_alloc_p;
@@ -5901,10 +6035,11 @@ static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
if (ret == NO_ERROR) break;
if (ret == ERROR_BUFFER_OVERFLOW) continue;
i = 0;
+ break;
}
if (! i) {
FREE(ip_adaddrs_p);
- ip_adaddrs_p = NULL;
+ ip_adaddrs_p = NULL;
}
} else ip_adaddrs_p = NULL;
}
@@ -5921,11 +6056,12 @@ static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
if (ret == NO_ERROR) break;
if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
i = 0;
+ break;
}
if (! i) {
- FREE(info_p);
- info_p = NULL;
- }
+ FREE(info_p);
+ info_p = NULL;
+ }
}
if (! ip_adaddrs_p) {
@@ -5940,6 +6076,7 @@ static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
if (ret == NO_ERROR) break;
if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
i = 0;
+ break;
}
if (! i) {
if (info_p) FREE(info_p);
@@ -5982,13 +6119,15 @@ index:
} else {
/* Then try IP_ADAPTER_INDEX_MAP.Name (only IPv4 adapters) */
int j;
- for (j = 0; j < info_p->NumAdapters; j++) {
- if (info_p->Adapter[j].Index == (ULONG) ifrow.dwIndex) {
- if (info_p->Adapter[j].Name[0] != 0) {
- wname_p = info_p->Adapter[j].Name;
+ if (info_p) {
+ for (j = 0; j < info_p->NumAdapters; j++) {
+ if (info_p->Adapter[j].Index == (ULONG) ifrow.dwIndex) {
+ if (info_p->Adapter[j].Name[0] != 0) {
+ wname_p = info_p->Adapter[j].Name;
+ }
+ break;
}
- break;
- }
+ }
}
}
if (wname_p) {
@@ -6345,6 +6484,7 @@ static ErlDrvSSizeT inet_ctl_getifaddrs(inet_descriptor* desc_p,
#endif
+
/* Per H @ Tail-f: The original code here had problems that possibly
only occur if you abuse it for non-INET sockets, but anyway:
a) If the getsockopt for SO_PRIORITY or IP_TOS failed, the actual
@@ -6412,6 +6552,40 @@ static int setopt_prio_tos_trick
}
#endif
+
+static
+int inet_setopt(int fd,
+ int proto, int type,
+ char* arg_ptr, int arg_sz,
+ int propagate)
+{
+ int res;
+
+#if defined(IP_TOS) && defined(IPPROTO_IP) \
+ && defined(SO_PRIORITY) && !defined(__WIN32__)
+ DEBUGF(("inet_setopt -> try trick setopt with"
+ "\r\n fd: %d"
+ "\r\n proto: %d"
+ "\r\n type: %d"
+ "\r\n sz: %d"
+ "\r\n propagate: %d"
+ "\r\n", fd, proto, type, arg_sz, propagate));
+ res = setopt_prio_tos_trick (fd, proto, type, arg_ptr, arg_sz, propagate);
+#else
+ DEBUGF(("inet_setopt -> try std setopt with"
+ "\r\n fd: %d"
+ "\r\n proto: %d"
+ "\r\n type: %d"
+ "\r\n sz: %d"
+ "\r\n", fd, proto, type, arg_sz));
+ res = sock_setopt (fd, proto, type, arg_ptr, arg_sz);
+#endif
+
+ return res;
+}
+
+
+
/* set socket options:
** return -1 on error
** 0 if ok
@@ -6427,12 +6601,22 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
int proto;
int opt;
struct linger li_val;
-#if defined(HAVE_MULTICAST_SUPPORT) && defined(IPPROTO_IP)
- struct ip_mreq mreq_val;
+#if defined(HAVE_MULTICAST_SUPPORT)
+#if defined(IPPROTO_IP)
+#if defined(HAVE_STRUCT_IP_MREQN)
+ struct ip_mreqn mreq4;
+#else
+ struct ip_mreq mreq4;
#endif
- int ival;
+#endif
+#if defined(HAVE_IN6) && defined(AF_INET6) && defined(IPPROTO_IPV6)
+ struct ipv6_mreq mreq6;
+#endif
+ unsigned int mreqSz = 0;
+#endif
+ int ival;
char* arg_ptr;
- int arg_sz;
+ int arg_sz;
#ifdef SO_BINDTODEVICE
char ifname[IFNAMSIZ];
#endif
@@ -6447,7 +6631,6 @@ 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) {
int recv_cmsgflags;
@@ -6462,47 +6645,74 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
propagate = 0;
recv_cmsgflags = desc->recv_cmsgflags;
- switch(opt) {
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts -> opt: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), opt) );
+
+ switch(opt) {
case INET_LOPT_HEADER:
- DEBUGF(("inet_set_opts(%p): s=%d, HEADER=%d\r\n",
- desc->port, desc->s,ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(header) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
desc->hsz = ival;
continue;
case INET_LOPT_MODE:
/* List or Binary: */
- DEBUGF(("inet_set_opts(%p): s=%d, MODE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(mode) -> %s (%d)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ M2S(ival), ival) );
desc->mode = ival;
continue;
case INET_LOPT_DELIVER:
- DEBUGF(("inet_set_opts(%p): s=%d, DELIVER=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(deliver) -> %s (%d)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ D2S(ival), ival) );
desc->deliver = ival;
continue;
case INET_LOPT_BUFFER:
- DEBUGF(("inet_set_opts(%p): s=%d, BUFFER=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(buffer) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (ival < INET_MIN_BUFFER) ival = INET_MIN_BUFFER;
desc->bufsz = ival;
desc->flags |= INET_FLG_BUFFER_SET;
continue;
case INET_LOPT_ACTIVE:
- DEBUGF(("inet_set_opts(%p): s=%d, ACTIVE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(active) -> active (ival): %s (%d)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ A2S(ival), ival) );
desc->active = ival;
if (desc->active == INET_MULTI) {
- long ac = desc->active_count;
+ long ac = desc->active_count;
Sint16 nval = get_int16(ptr);
ptr += 2;
len -= 2;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(active) -> nval: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), nval) );
ac += nval;
if (ac > INT16_MAX || ac < INT16_MIN)
return -1;
desc->active_count += nval;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(active) -> count => %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ desc->active_count) );
if (desc->active_count < 0)
desc->active_count = 0;
if (desc->active_count == 0) {
@@ -6529,24 +6739,35 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
continue;
case INET_LOPT_PACKET:
- DEBUGF(("inet_set_opts(%p): s=%d, PACKET=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(packet) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
desc->htype = ival;
continue;
case INET_LOPT_PACKET_SIZE:
- DEBUGF(("inet_set_opts(%p): s=%d, PACKET_SIZE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(packet-size) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
desc->psize = (unsigned int)ival;
continue;
case INET_LOPT_EXITONCLOSE:
- DEBUGF(("inet_set_opts(%p): s=%d, EXITONCLOSE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(exit-on-close) -> %d (%s)\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port), ival, B2S(ival)) );
desc->exitf = ival;
continue;
case INET_LOPT_TCP_HIWTRMRK:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(hiwtrmrk) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (desc->stype == SOCK_STREAM) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
if (ival < 0) ival = 0;
@@ -6557,6 +6778,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
continue;
case INET_LOPT_TCP_LOWTRMRK:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(lowtrmrk) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (desc->stype == SOCK_STREAM) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
if (ival < 0) ival = 0;
@@ -6568,6 +6793,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
case INET_LOPT_MSGQ_HIWTRMRK: {
ErlDrvSizeT high;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(msgq-hiwtrmrk) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
|| ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
return -1;
@@ -6578,6 +6807,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
case INET_LOPT_MSGQ_LOWTRMRK: {
ErlDrvSizeT low;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(msgq-lowtrmrk) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (ival < ERL_DRV_BUSY_MSGQ_LIM_MIN
|| ERL_DRV_BUSY_MSGQ_LIM_MAX < ival)
return -1;
@@ -6587,6 +6820,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
}
case INET_LOPT_TCP_SEND_TIMEOUT:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(send-timeout) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (desc->stype == SOCK_STREAM) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
tdesc->send_timeout = ival;
@@ -6594,6 +6831,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
continue;
case INET_LOPT_TCP_SEND_TIMEOUT_CLOSE:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(send-timeout-close) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (desc->stype == SOCK_STREAM) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
tdesc->send_timeout_close = ival;
@@ -6602,6 +6843,11 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
case INET_LOPT_TCP_DELAY_SEND:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(delay-send) -> %d (%s)\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port), ival, B2S(ival)) );
if (desc->stype == SOCK_STREAM) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
if (ival)
@@ -6613,6 +6859,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
#ifdef HAVE_UDP
case INET_LOPT_UDP_READ_PACKETS:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(read-packets) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (desc->stype == SOCK_DGRAM) {
udp_descriptor* udesc = (udp_descriptor*) desc;
if (ival <= 0) return -1;
@@ -6623,6 +6873,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
#ifdef HAVE_SETNS
case INET_LOPT_NETNS:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(netns) -> %d, %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival, len) );
/* It is annoying that ival and len are both (signed) int */
if (ival < 0) return -1;
if (len < ival) return -1;
@@ -6636,6 +6890,11 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
#endif
case INET_LOPT_TCP_SHOW_ECONNRESET:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(show-econnreset) -> %d (%s)\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port), ival, B2S(ival)) );
if (desc->sprotocol == IPPROTO_TCP) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
if (ival)
@@ -6646,43 +6905,90 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
continue;
case INET_LOPT_LINE_DELIM:
- DEBUGF(("inet_set_opts(%p): s=%d, LINE_DELIM=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(line-delimiter) -> %c (%d)\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port), (char) ival, ival) );
desc->delimiter = (char)ival;
continue;
- case INET_OPT_REUSEADDR:
+ case INET_OPT_REUSEADDR:
#ifdef __WIN32__
- continue; /* Bjorn says */
-#else
- type = SO_REUSEADDR;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_REUSEADDR=%d\r\n",
- desc->port, desc->s,ival));
- break;
+ /* The behaviour changed in Windows Server 2003.
+ * Now it works as the combo of `SO_REUSEADDR` and
+ * `SO_REUSEPORT` does on *BSD.
+ */
+ if (desc->stype != SOCK_DGRAM) {
+ /*
+ * We refuse usage of SO_REUSEADDR on non-UDP sockets since it
+ * mostly (perhaps only) opens up for socket collisions and
+ * probably hasn't got any useful use-cases. There are useful
+ * use-cases for multicast sockets, though. For more
+ * information see:
+ * https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
+ *
+ * Prior to OTP 25 we also refused to use SO_REUSEADDR on any
+ * sockets on Windows. See
+ * 2a6ac6f3f027fcab6d607599e82714e930d9fde2
+ *
+ * We certainly do not want to use it for the Erlang
+ * distribution TCP sockets since we can end up reusing our
+ * own active sockets as demonstrated in the issue:
+ * https://github.com/erlang/otp/issues/6461
+ *
+ * We probably want to expose the Windows specific
+ * SO_EXCLUSIVEADDRUSE in the API as well...
+ */
+ continue;
+ }
#endif
+ type = SO_REUSEADDR;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(reuseaddr) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+ break;
+
case INET_OPT_KEEPALIVE: type = SO_KEEPALIVE;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_KEEPALIVE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(keepalive) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
break;
+
case INET_OPT_DONTROUTE: type = SO_DONTROUTE;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_DONTROUTE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(dontroute) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
break;
+
case INET_OPT_BROADCAST: type = SO_BROADCAST;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_BROADCAST=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(broadcast) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
break;
+
case INET_OPT_OOBINLINE: type = SO_OOBINLINE;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_OOBINLINE=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(oobinline) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
break;
- case INET_OPT_SNDBUF: type = SO_SNDBUF;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_SNDBUF=%d\r\n",
- desc->port, desc->s, ival));
+
+ case INET_OPT_SNDBUF: type = SO_SNDBUF; DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(sndbuf) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
break;
+
case INET_OPT_RCVBUF: type = SO_RCVBUF;
- DEBUGF(("inet_set_opts(%p): s=%d, SO_RCVBUF=%d\r\n",
- desc->port, desc->s, ival));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(rcvbuf) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (!(desc->flags & INET_FLG_BUFFER_SET)) {
/* make sure we have desc->bufsz >= SO_RCVBUF */
if (ival > (1 << 16) && desc->stype == SOCK_DGRAM && !IS_SCTP(desc))
@@ -6694,6 +7000,7 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
desc->bufsz = ival;
}
break;
+
case INET_OPT_LINGER: type = SO_LINGER;
if (len < 4)
return -1;
@@ -6703,9 +7010,14 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
len -= 4;
arg_ptr = (char*) &li_val;
arg_sz = sizeof(li_val);
- DEBUGF(("inet_set_opts(%p): s=%d, SO_LINGER=%d,%d",
- desc->port, desc->s,
- li_val.l_onoff,li_val.l_linger));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(linger) -> %d, %d\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port),
+ li_val.l_onoff, li_val.l_linger) );
+
if (desc->sprotocol == IPPROTO_TCP) {
tcp_descriptor* tdesc = (tcp_descriptor*) desc;
if (li_val.l_onoff && li_val.l_linger == 0)
@@ -6717,49 +7029,72 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
case INET_OPT_PRIORITY:
#ifdef SO_PRIORITY
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(prio) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
type = SO_PRIORITY;
propagate = 1; /* We do want to know if this fails */
- DEBUGF(("inet_set_opts(%p): s=%d, SO_PRIORITY=%d\r\n",
- desc->port, desc->s, ival));
break;
#else
/* inet_fill_opts always returns a value for this option,
* so we need to ignore it if not implemented */
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(prio) -> SKIP\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
continue;
#endif
+
case INET_OPT_TOS:
#if defined(IP_TOS) && defined(IPPROTO_IP)
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(tos) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IP;
type = IP_TOS;
propagate = 1;
- DEBUGF(("inet_set_opts(%p): s=%d, IP_TOS=%d\r\n",
- desc->port, desc->s, ival));
break;
#else
/* inet_fill_opts always returns a value for this option,
* so we need to ignore it if not implemented. */
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(tos) -> SKIP\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
continue;
#endif
+
#if defined(IPV6_TCLASS) && defined(IPPROTO_IPV6)
case INET_OPT_TCLASS:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(tclass) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IPV6;
type = IPV6_TCLASS;
propagate = 1;
- DEBUGF(("inet_set_opts(%p): s=%d, IPV6_TCLASS=%d\r\n",
- desc->port, desc->s, ival));
break;
#endif
+
#if defined(IP_TTL) && defined(IPPROTO_IP)
case INET_OPT_TTL:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(ttl) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IP;
type = IP_TTL;
propagate = 1;
- DEBUGF(("inet_set_opts(%p): s=%d, IP_TTL=%d\r\n",
- desc->port, desc->s, ival));
break;
#endif
#if defined(IP_RECVTOS) && defined(IPPROTO_IP)
case INET_OPT_RECVTOS:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(recvtos) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IP;
type = IP_RECVTOS;
propagate = 1;
@@ -6767,12 +7102,14 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
ival ?
(desc->recv_cmsgflags | INET_CMSG_RECVTOS) :
(desc->recv_cmsgflags & ~INET_CMSG_RECVTOS);
- DEBUGF(("inet_set_opts(%p): s=%d, IP_RECVTOS=%d\r\n",
- desc->port, desc->s, ival));
break;
#endif
#if defined(IPV6_RECVTCLASS) && defined(IPPROTO_IPV6)
case INET_OPT_RECVTCLASS:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(recvtclass) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IPV6;
type = IPV6_RECVTCLASS;
propagate = 1;
@@ -6780,12 +7117,14 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
ival ?
(desc->recv_cmsgflags | INET_CMSG_RECVTCLASS) :
(desc->recv_cmsgflags & ~INET_CMSG_RECVTCLASS);
- DEBUGF(("inet_set_opts(%p): s=%d, IPV6_RECVTCLASS=%d\r\n",
- desc->port, desc->s, ival));
break;
#endif
#if defined(IP_RECVTTL) && defined(IPPROTO_IP)
case INET_OPT_RECVTTL:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(recvttl) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IP;
type = IP_RECVTTL;
propagate = 1;
@@ -6793,87 +7132,283 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
ival ?
(desc->recv_cmsgflags | INET_CMSG_RECVTTL) :
(desc->recv_cmsgflags & ~INET_CMSG_RECVTTL);
- DEBUGF(("inet_set_opts(%p): s=%d, IP_RECVTTL=%d\r\n",
- desc->port, desc->s, ival));
break;
#endif
case TCP_OPT_NODELAY:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(nodelay) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
proto = IPPROTO_TCP;
type = TCP_NODELAY;
- DEBUGF(("inet_set_opts(%p): s=%d, TCP_NODELAY=%d\r\n",
- desc->port, desc->s, ival));
break;
case TCP_OPT_NOPUSH:
#if defined(INET_TCP_NOPUSH)
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(nopush) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_TCP;
type = INET_TCP_NOPUSH;
- DEBUGF(("inet_set_opts(%p): s=%d, t=%d TCP_NOPUSH=%d\r\n",
- desc->port, desc->s, type, ival));
break;
#else
/* inet_fill_opts always returns a value for this option,
* so we need to ignore it if not implemented, just in case */
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(nopush) -> SKIP\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
continue;
#endif
#if defined(HAVE_MULTICAST_SUPPORT) && defined(IPPROTO_IP)
case UDP_OPT_MULTICAST_TTL:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(multicast-ttl) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
proto = IPPROTO_IP;
type = IP_MULTICAST_TTL;
- DEBUGF(("inet_set_opts(%p): s=%d, IP_MULTICAST_TTL=%d\r\n",
- desc->port, desc->s,ival));
break;
case UDP_OPT_MULTICAST_LOOP:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(multicast-loop) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
proto = IPPROTO_IP;
type = IP_MULTICAST_LOOP;
- DEBUGF(("inet_set_opts(%p): s=%d, IP_MULTICAST_LOOP=%d\r\n",
- desc->port, desc->s,ival));
break;
case UDP_OPT_MULTICAST_IF:
- proto = IPPROTO_IP;
- type = IP_MULTICAST_IF;
- DEBUGF(("inet_set_opts(%p): s=%d, IP_MULTICAST_IF=%x\r\n",
- desc->port, desc->s, ival));
- ival = sock_htonl(ival);
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(multicast-if) -> %d (%d)\r\n",
+ __LINE__,
+ desc->s, driver_caller(desc->port), ival, sock_htonl(ival)) );
+ if (desc->sfamily == AF_INET) {
+ proto = IPPROTO_IP;
+ type = IP_MULTICAST_IF;
+ DEBUGF(("inet_set_opts(%p): s=%d, IP_MULTICAST_IF = %x\r\n",
+ desc->port, desc->s, ival));
+ ival = sock_htonl(ival);
+ }
+#if defined(HAVE_IN6) && defined(AF_INET6) && defined(IPPROTO_IPV6)
+ else if (desc->sfamily == AF_INET6) {
+ proto = IPPROTO_IPV6;
+ type = IPV6_MULTICAST_IF;
+ DEBUGF(("inet_set_opts(%p): s=%d, IPV6_MULTICAST_IF = %x\r\n",
+ desc->port, desc->s, ival));
+ ival = sock_htonl(ival);
+ } else {
+ return -1;
+ }
+#else
+ else {
+ return -1;
+ }
+#endif
break;
case UDP_OPT_ADD_MEMBERSHIP:
- proto = IPPROTO_IP;
- type = IP_ADD_MEMBERSHIP;
- DEBUGF(("inet_set_opts(%p): s=%d, IP_ADD_MEMBERSHIP=%d\r\n",
- desc->port, desc->s,ival));
- goto L_set_mreq;
-
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(add-membership) -> domain: %d (%s)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ ival, DOM2S(ival)) );
+ if (ival == INET_AF_INET) {
+ proto = IPPROTO_IP;
+ type = IP_ADD_MEMBERSHIP;
+ }
+#if defined(HAVE_IN6) && defined(AF_INET6) && defined(IPPROTO_IPV6)
+ else if (ival == INET_AF_INET6) {
+ proto = IPPROTO_IPV6;
+#if defined(INET_ADD_MEMBERSHIP)
+ type = INET_DROP_MEMBERSHIP;
+#else
+ return -1;
+#endif
+ }
+#endif
+ else {
+ return -1;
+ }
+ goto L_init_mreq;
+
case UDP_OPT_DROP_MEMBERSHIP:
- proto = IPPROTO_IP;
- type = IP_DROP_MEMBERSHIP;
- DEBUGF(("inet_set_opts(%p): s=%d, "
- "IP_DROP_MEMBERSHIP=%x\r\n",
- desc->port, desc->s, ival));
- L_set_mreq:
- mreq_val.imr_multiaddr.s_addr = sock_htonl(ival);
- ival = get_int32(ptr);
- mreq_val.imr_interface.s_addr = sock_htonl(ival);
- ptr += 4;
- len -= 4;
- arg_ptr = (char*)&mreq_val;
- arg_sz = sizeof(mreq_val);
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(drop-membership) -> %d (%s)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ ival, DOM2S(ival)) );
+ if (ival == INET_AF_INET) {
+ proto = IPPROTO_IP;
+ type = IP_DROP_MEMBERSHIP;
+ }
+#if defined(HAVE_IN6) && defined(AF_INET6) && defined(IPPROTO_IPV6)
+ else if (ival == INET_AF_INET6) {
+ proto = IPPROTO_IPV6;
+#if defined(INET_DROP_MEMBERSHIP)
+ type = INET_DROP_MEMBERSHIP;
+#else
+ return -1;
+#endif
+ }
+#endif
+ else {
+ return -1;
+ }
+
+ L_init_mreq:
+ {
+ int domain = ival;
+
+ ival = get_int32(ptr); // Interface | Ifindex
+ ptr += 4;
+ len -= 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq) -> "
+ "\r\n proto: %d"
+ "\r\n type: %d"
+ "\r\n domain: %d (%s)"
+ "\r\n if: %d"
+ "\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ proto, type, domain, DOM2S(domain), ival));
+
+ if ((domain == INET_AF_INET) && (desc->sfamily == AF_INET)) {
+
+ mreqSz = sizeof(mreq4);
+
+ /* 0) Read out the ifindex (see above)
+ * 1) Read out the multiaddr
+ * 2) Read out the local address
+ */
+
+#if defined(HAVE_STRUCT_IP_MREQN)
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq,inet) -> mreqn\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)));
+
+ mreq4.imr_ifindex = sock_htonl(ival);
+ ival = get_int32(ptr);
+ ptr += 4;
+ len -= 4;
+ mreq4.imr_multiaddr.s_addr = sock_htonl(ival);
+ ival = get_int32(ptr);
+ ptr += 4;
+ len -= 4;
+ mreq4.imr_address.s_addr = sock_htonl(ival);
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq,inet) -> "
+ "try setopt: "
+ "\r\n maddr: %x"
+ "\r\n addr: %x"
+ "\r\n if: %d"
+ "\r\n sz: %d"
+ "\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ mreq4.imr_multiaddr.s_addr,
+ mreq4.imr_address.s_addr,
+ mreq4.imr_ifindex,
+ mreqSz));
+
+#else
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq,inet) -> mreq\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)));
+
+ ival = get_int32(ptr);
+ ptr += 4;
+ len -= 4;
+ mreq4.imr_multiaddr.s_addr = sock_htonl(ival);
+ ival = get_int32(ptr);
+ ptr += 4;
+ len -= 4;
+ mreq4.imr_interface.s_addr = sock_htonl(ival);
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq,inet) -> "
+ "try setopt: "
+ "\r\n maddr: %x"
+ "\r\n if: %x"
+ "\r\n sz: %d"
+ "\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ mreq4.imr_multiaddr.s_addr,
+ mreq4.imr_interface.s_addr,
+ mreqSz));
+
+#endif
+
+ arg_ptr = (char*)&mreq4;
+ arg_sz = mreqSz;
+
+ }
+#if defined(HAVE_IN6) && defined(AF_INET6) && defined(IPPROTO_IPV6)
+ else if ((domain == INET_AF_INET6) &&
+ (desc->sfamily == AF_INET6)) {
+
+ mreqSz = sizeof(mreq6);
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq,inet6) -> mreq\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)));
+
+ /* 0) Read out the ifindex
+ * 1) Read out the multiaddr
+ */
+
+ sys_memcpy(&mreq6.ipv6mr_multiaddr, ptr, 16);
+ ptr += 16;
+ len -= len;
+ mreq6.ipv6mr_interface = ival;
+
+ arg_ptr = (char*)&mreq6;
+ arg_sz = mreqSz;
+
+ }
+#endif
+ else {
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(L_init_mreq) -> "
+ "invalid domain: "
+ "\r\n domain: %d (%d, %d)"
+ "\r\n sfmaily: %d (%d, %d)"
+ "\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ domain, INET_AF_INET, INET_AF_INET6,
+ desc->sfamily, AF_INET, AF_INET6));
+ return -1;
+ }
+ }
break;
#endif /* defined(HAVE_MULTICAST_SUPPORT) && defined(IPPROTO_IP) */
case INET_OPT_IPV6_V6ONLY:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(ipv6-v6only) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
#if HAVE_DECL_IPV6_V6ONLY && defined(IPPROTO_IPV6)
proto = IPPROTO_IPV6;
type = IPV6_V6ONLY;
propagate = 1;
- DEBUGF(("inet_set_opts(%p): s=%d, IPV6_V6ONLY=%d\r\n",
- desc->port, desc->s, ival));
break;
#elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6)
/* Fake a'la OpenBSD; set to 'true' is fine but 'false' invalid. */
@@ -6885,6 +7420,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
#endif
case INET_OPT_RAW:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(raw) -> %d, %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival, len) );
if (len < 8) {
return -1;
}
@@ -6904,6 +7443,10 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
#ifdef SO_BINDTODEVICE
case INET_OPT_BIND_TO_DEVICE:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(bindtodevice) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
if (ival < 0) return -1;
if (len < ival) return -1;
if (ival > sizeof(ifname)) {
@@ -6919,27 +7462,41 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_ptr = (char*)&ifname;
arg_sz = sizeof(ifname);
propagate = 1; /* We do want to know if this fails */
-
- DEBUGF(("inet_set_opts(%p): s=%d, SO_BINDTODEVICE=%s\r\n",
- desc->port, desc->s, ifname));
break;
#endif
- default:
+ case INET_LOPT_DEBUG:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts(debug) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+ if (ival) {
+ desc->debug = TRUE;
+ } else {
+ desc->debug = FALSE;
+ }
+ continue; /* take care of next option */
+
+ default:
return -1;
}
-#if defined(IP_TOS) && defined(IPPROTO_IP) \
- && defined(SO_PRIORITY) && !defined(__WIN32__)
- res = setopt_prio_tos_trick (desc->s, proto, type, arg_ptr, arg_sz, propagate);
-#else
- res = sock_setopt (desc->s, proto, type, arg_ptr, arg_sz);
-#endif
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts -> try set opt (%d) %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), proto, type) );
+
+ res = inet_setopt(desc->s, proto, type, arg_ptr, arg_sz, propagate);
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_set_opts -> set opt result: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), res) );
+
if (res == 0) desc->recv_cmsgflags = recv_cmsgflags;
if (propagate && res != 0) {
return -1;
}
- DEBUGF(("inet_set_opts(%p): s=%d returned %d\r\n",
- desc->port, desc->s, res));
}
if ( ((desc->stype == SOCK_STREAM) && IS_CONNECTED(desc)) ||
@@ -6958,7 +7515,8 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
}
if (desc->active != old_active) {
- /* Need to cancel the read_packet timer if we go from active to passive. */
+ /* Need to cancel the read_packet timer *
+ * if we go from active to passive. */
if (desc->active == INET_PASSIVE && desc->stype == SOCK_DGRAM)
driver_cancel_timer(desc->port);
@@ -6995,7 +7553,7 @@ static char* sctp_get_initmsg(struct sctp_initmsg* ini, char* curr)
}
/* "sctp_get_sendparams":
-** Parses (from the command buffer) the 6 user-sprcified parms of
+** Parses (from the command buffer) the 6 user-specified params of
** "sctp_sndrcvinfo":
** stream(u16), flags(u16), ppid(u32), context(u32),
** timetoleave(u32), assoc_id
@@ -7085,6 +7643,11 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
eopt = *curr;
curr++;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> eopt: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), eopt) );
+
recv_cmsgflags = desc->recv_cmsgflags;
/* Get the option value. XXX: The condition (curr < ptr + len)
does not preclude us from reading from beyond the buffer end,
@@ -7096,43 +7659,82 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
/* Local INET options: */
case INET_LOPT_BUFFER:
- desc->bufsz = get_int32(curr); curr += 4;
+ {
+ int ival = get_int32(curr); curr += 4;
- if (desc->bufsz < INET_MIN_BUFFER)
- desc->bufsz = INET_MIN_BUFFER;
- desc->flags |= INET_FLG_BUFFER_SET;
- res = 0; /* This does not affect the kernel buffer size */
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(buffer) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ desc->bufsz = ival;
+
+ if (desc->bufsz < INET_MIN_BUFFER)
+ desc->bufsz = INET_MIN_BUFFER;
+ desc->flags |= INET_FLG_BUFFER_SET;
+ res = 0; /* This does not affect the kernel buffer size */
+ }
continue;
case INET_LOPT_MODE:
- desc->mode = get_int32(curr); curr += 4;
- res = 0;
+ {
+ int ival = get_int32(curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(mode) -> %s (%d)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ M2S(ival), ival) );
+
+ desc->mode = ival;
+ res = 0;
+ }
continue;
case INET_LOPT_ACTIVE:
- desc->active = get_int32(curr); curr += 4;
- if (desc->active == INET_MULTI) {
- long ac = desc->active_count;
- Sint16 nval = get_int16(curr); curr += 2;
- ac += nval;
- if (ac > INT16_MAX || ac < INT16_MIN)
- return -1;
- desc->active_count += nval;
- if (desc->active_count < 0)
+ {
+ int ival = get_int32(curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(active) -> %s (%d)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ A2S(ival), ival) );
+
+ desc->active = ival;
+ if (desc->active == INET_MULTI) {
+ long ac = desc->active_count;
+ Sint16 nval = get_int16(curr); curr += 2;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(active) -> nval: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), nval) );
+ ac += nval;
+ if (ac > INT16_MAX || ac < INT16_MIN)
+ return -1;
+ desc->active_count += nval;
+ if (desc->active_count < 0)
+ desc->active_count = 0;
+ if (desc->active_count == 0) {
+ desc->active = INET_PASSIVE;
+ packet_passive_message(desc);
+ }
+ } else
desc->active_count = 0;
- if (desc->active_count == 0) {
- desc->active = INET_PASSIVE;
- packet_passive_message(desc);
- }
- } else
- desc->active_count = 0;
- res = 0;
+ res = 0;
+ }
continue;
#ifdef HAVE_SETNS
case INET_LOPT_NETNS:
{
size_t ns_len;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> NETNS\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
ns_len = get_int32(curr); curr += 4;
CHKLEN(curr, ns_len);
if (desc->netns != NULL) FREE(desc->netns);
@@ -7148,6 +7750,11 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
case SCTP_OPT_RTOINFO:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> RTOINFO\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, ASSOC_ID_LEN + 3*4);
arg.rtoi.srto_assoc_id = GET_ASSOC_ID(curr); curr += ASSOC_ID_LEN;
arg.rtoi.srto_initial = get_int32 (curr); curr += 4;
@@ -7160,8 +7767,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.rtoi);
break;
}
+
case SCTP_OPT_ASSOCINFO:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> ASSOCINFO\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, ASSOC_ID_LEN + 2*2 + 3*4);
arg.ap.sasoc_assoc_id = GET_ASSOC_ID(curr); curr += ASSOC_ID_LEN;
@@ -7178,8 +7791,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.ap);
break;
}
+
case SCTP_OPT_INITMSG:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> INITMSG\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, SCTP_GET_INITMSG_LEN);
curr = sctp_get_initmsg (&arg.im, curr);
@@ -7189,8 +7808,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.im);
break;
}
+
case INET_OPT_LINGER:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> LINGER\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, 2*4);
arg.lin.l_onoff = get_int32 (curr); curr += 4;
arg.lin.l_linger = get_int32 (curr); curr += 4;
@@ -7201,8 +7826,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.lin);
break;
}
+
case SCTP_OPT_NODELAY:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> NODELAY\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
arg.ival= get_int32 (curr); curr += 4;
proto = IPPROTO_SCTP;
type = SCTP_NODELAY;
@@ -7210,9 +7841,17 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.ival);
break;
}
+
case INET_OPT_RCVBUF:
{
- arg.ival= get_int32 (curr); curr += 4;
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(rcvbuf) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival= ival;
proto = SOL_SOCKET;
type = SO_RCVBUF;
arg_ptr = (char*) (&arg.ival);
@@ -7225,9 +7864,17 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
desc->flags |= INET_FLG_BUFFER_SET;
break;
}
+
case INET_OPT_SNDBUF:
{
- arg.ival= get_int32 (curr); curr += 4;
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(sndbuf) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival= ival;
proto = SOL_SOCKET;
type = SO_SNDBUF;
arg_ptr = (char*) (&arg.ival);
@@ -7237,6 +7884,11 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
}
case INET_OPT_REUSEADDR:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> REUSEADDR\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
arg.ival= get_int32 (curr); curr += 4;
proto = SOL_SOCKET;
type = SO_REUSEADDR;
@@ -7246,21 +7898,36 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
}
case INET_OPT_DONTROUTE:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = SOL_SOCKET;
- type = SO_DONTROUTE;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(dontroute) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = SOL_SOCKET;
+ type = SO_DONTROUTE;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
+
case INET_OPT_PRIORITY:
# ifdef SO_PRIORITY
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = SOL_SOCKET;
- type = SO_PRIORITY;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(prio) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival = ival;
+ proto = SOL_SOCKET;
+ type = SO_PRIORITY;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
# else
@@ -7272,11 +7939,17 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
case INET_OPT_TOS:
# if defined(IP_TOS) && defined(IPPROTO_IP)
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IP;
- type = IP_TOS;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(tos) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IP;
+ type = IP_TOS;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
# else
@@ -7288,11 +7961,18 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
# if defined(IPV6_TCLASS) && defined(IPPROTO_IPV6)
case INET_OPT_TCLASS:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IPV6;
- type = IPV6_TCLASS;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(tclass) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IPV6;
+ type = IPV6_TCLASS;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
# endif
@@ -7300,11 +7980,18 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
# if defined(IP_TTL) && defined(IPPROTO_IP)
case INET_OPT_TTL:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IP;
- type = IP_TTL;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(ttl) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IP;
+ type = IP_TTL;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
# endif
@@ -7312,11 +7999,18 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
# if defined(IP_RECVTOS) && defined(IPPROTO_IP)
case INET_OPT_RECVTOS:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IP;
- type = IP_RECVTOS;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(recvtos) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IP;
+ type = IP_RECVTOS;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
recv_cmsgflags =
arg.ival ?
(desc->recv_cmsgflags | INET_CMSG_RECVTOS) :
@@ -7328,11 +8022,18 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
# if defined(IPV6_RECVTCLASS) && defined(IPPROTO_IPV6)
case INET_OPT_RECVTCLASS:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IPV6;
- type = IPV6_RECVTCLASS;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(recvtclass) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IPV6;
+ type = IPV6_RECVTCLASS;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
recv_cmsgflags =
arg.ival ?
(desc->recv_cmsgflags | INET_CMSG_RECVTCLASS) :
@@ -7344,11 +8045,18 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
# if defined(IP_RECVTTL) && defined(IPPROTO_IP)
case INET_OPT_RECVTTL:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IP;
- type = IP_RECVTTL;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(recvttl) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IP;
+ type = IP_RECVTTL;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
recv_cmsgflags =
arg.ival ?
(desc->recv_cmsgflags | INET_CMSG_RECVTTL) :
@@ -7361,11 +8069,18 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
case INET_OPT_IPV6_V6ONLY:
# if HAVE_DECL_IPV6_V6ONLY && defined(IPPROTO_IPV6)
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_IPV6;
- type = IPV6_V6ONLY;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(ipv6_v6only) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = IPPROTO_IPV6;
+ type = IPV6_V6ONLY;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
# elif defined(__WIN32__) && defined(HAVE_IN6) && defined(AF_INET6)
@@ -7376,6 +8091,11 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
#ifdef SO_BINDTODEVICE
case INET_OPT_BIND_TO_DEVICE:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> BIND_TO_DEVICE\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
arg_sz = get_int32(curr); curr += 4;
CHKLEN(curr, arg_sz);
if (arg_sz >= sizeof(arg.ifname))
@@ -7393,45 +8113,82 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
case SCTP_OPT_AUTOCLOSE:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_SCTP;
- type = SCTP_AUTOCLOSE;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(autoclose) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival = ival;
+ proto = IPPROTO_SCTP;
+ type = SCTP_AUTOCLOSE;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
+
case SCTP_OPT_DISABLE_FRAGMENTS:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_SCTP;
- type = SCTP_DISABLE_FRAGMENTS;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(disable_fragments) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = IPPROTO_SCTP;
+ type = SCTP_DISABLE_FRAGMENTS;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
+
case SCTP_OPT_I_WANT_MAPPED_V4_ADDR:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_SCTP;
- type = SCTP_I_WANT_MAPPED_V4_ADDR;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(i_want_mapped_v4_addr) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(ival)) );
+
+ arg.ival = ival;
+ proto = IPPROTO_SCTP;
+ type = SCTP_I_WANT_MAPPED_V4_ADDR;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
+
case SCTP_OPT_MAXSEG:
{
- arg.ival= get_int32 (curr); curr += 4;
- proto = IPPROTO_SCTP;
- type = SCTP_MAXSEG;
- arg_ptr = (char*) (&arg.ival);
- arg_sz = sizeof ( arg.ival);
+ int ival = get_int32 (curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(maxseg) -> %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), ival) );
+
+ arg.ival = ival;
+ proto = IPPROTO_SCTP;
+ type = SCTP_MAXSEG;
+ arg_ptr = (char*) (&arg.ival);
+ arg_sz = sizeof ( arg.ival);
break;
}
+
case SCTP_OPT_PRIMARY_ADDR:
case SCTP_OPT_SET_PEER_PRIMARY_ADDR:
{
ErlDrvSizeT alen;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> PRIMARY_ADDR | SET_PEER_PRIMARY_ADDR\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, ASSOC_ID_LEN);
/* XXX: These 2 opts have isomorphic value data structures,
"sctp_setpeerprim" and "sctp_prim" (in Solaris 10, the latter
@@ -7455,8 +8212,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.prim);
break;
}
+
case SCTP_OPT_ADAPTATION_LAYER:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> ADAPTATION_LAYER\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
/* XXX: do we need to convert the Ind into network byte order??? */
arg.ad.ssb_adaptation_ind = sock_htonl (get_int32(curr)); curr += 4;
@@ -7466,6 +8229,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.ad);
break;
}
+
case SCTP_OPT_PEER_ADDR_PARAMS:
{
ErlDrvSizeT alen;
@@ -7478,6 +8242,11 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
# endif
# endif
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> PEER_ADDR_PARAMS\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, ASSOC_ID_LEN);
arg.pap.spp_assoc_id = GET_ASSOC_ID(curr); curr += ASSOC_ID_LEN;
@@ -7523,7 +8292,7 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
if (pmtud_disable) cflags |= SPP_PMTUD_DISABLE;
# ifdef HAVE_STRUCT_SCTP_PADDRPARAMS_SPP_SACKDELAY
- /* The followings are missing in FreeBSD 7.1 */
+ /* The following are missing in FreeBSD 7.1 */
sackdelay_enable =eflags& SCTP_FLAG_SACDELAY_ENABLE;
sackdelay_disable=eflags& SCTP_FLAG_SACDELAY_DISABLE;
if (sackdelay_enable && sackdelay_disable)
@@ -7542,8 +8311,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
arg_sz = sizeof ( arg.pap);
break;
}
+
case SCTP_OPT_DEFAULT_SEND_PARAM:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> DEFAULT_SEND_PARAM\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, SCTP_GET_SENDPARAMS_LEN);
curr = sctp_get_sendparams (&arg.sri, curr);
@@ -7554,8 +8329,14 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
VALGRIND_MAKE_MEM_DEFINED(arg_ptr, arg_sz); /*suppress "uninitialised bytes"*/
break;
}
+
case SCTP_OPT_EVENTS:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> EVENTS\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, 9);
/* We do not support "sctp_authentication_event" -- it is not
implemented in Linux Kernel SCTP anyway. Just in case if
@@ -7589,6 +8370,11 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
#if defined(HAVE_DECL_SCTP_DELAYED_ACK_TIME) && defined(SCTP_ASSOC_VALUE_ASSOC_ID)
case SCTP_OPT_DELAYED_ACK_TIME:
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts -> DELAYED_ACK_TIME\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
CHKLEN(curr, ASSOC_ID_LEN + 4);
arg.av.assoc_id = GET_ASSOC_ID(curr); curr += ASSOC_ID_LEN;
arg.av.assoc_value = get_int32(curr); curr += 4;
@@ -7600,6 +8386,26 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
break;
}
#endif
+
+ case INET_LOPT_DEBUG:
+ {
+ int ival = get_int32(curr); curr += 4;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "sctp_set_opts(debug) -> %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ B2S(ival)) );
+ if (ival) {
+ desc->debug = TRUE;
+ } else {
+ desc->debug = FALSE;
+ }
+
+ res = 0;
+ }
+ continue; /* take care of next option */
+
default:
/* XXX: No more supported SCTP options. In particular, authentica-
tion options (SCTP_AUTH_CHUNK, SCTP_AUTH_KEY, SCTP_PEER_AUTH_
@@ -7610,12 +8416,9 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len)
*/
return -1;
}
-#if defined(IP_TOS) && defined(IPPROTO_IP) \
- && defined(SO_PRIORITY) && !defined(__WIN32__)
- res = setopt_prio_tos_trick (desc->s, proto, type, arg_ptr, arg_sz, 1);
-#else
- res = sock_setopt (desc->s, proto, type, arg_ptr, arg_sz);
-#endif
+
+ res = inet_setopt(desc->s, proto, type, arg_ptr, arg_sz, 1);
+
/* The return values of "sock_setopt" can only be 0 or -1: */
ASSERT(res == 0 || res == -1);
if (res == 0) desc->recv_cmsgflags = recv_cmsgflags;
@@ -7733,7 +8536,13 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
dest_used = new_need; \
} while(0)
-
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_fill_opts -> entry\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
+
PLACE_FOR(1,ptr);
*ptr = INET_REP_OK;
@@ -7746,6 +8555,11 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
PLACE_FOR(5,ptr);
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_fill_opts -> opt %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), opt) );
+
switch(opt) {
case INET_LOPT_BUFFER:
*ptr++ = opt;
@@ -7997,14 +8811,44 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
proto = IPPROTO_IP;
type = IP_MULTICAST_TTL;
break;
+
case UDP_OPT_MULTICAST_LOOP:
proto = IPPROTO_IP;
type = IP_MULTICAST_LOOP;
break;
+
case UDP_OPT_MULTICAST_IF:
- proto = IPPROTO_IP;
- type = IP_MULTICAST_IF;
- break;
+ {
+ int mif = 0;
+ unsigned int mifSz = sizeof(mif);
+
+ *ptr++ = opt;
+ /* We use up the 4 (value) places for the domain/family
+ * So we need to allocate 4 more */
+ PLACE_FOR(4,ptr);
+ if (desc->sfamily == AF_INET) {
+ put_int32(INET_AF_INET, ptr);
+ ptr += 4;
+ proto = IPPROTO_IP;
+ type = IP_MULTICAST_IF;
+ } else if (desc->sfamily == AF_INET6) {
+ put_int32(INET_AF_INET6, ptr);
+ ptr += 4;
+ proto = IPPROTO_IPV6;
+ type = IPV6_MULTICAST_IF;
+ } else {
+ RETURN_ERROR();
+ }
+ if (IS_SOCKET_ERROR(sock_getopt(desc->s,
+ proto, type,
+ &mif, &mifSz))) {
+ TRUNCATE_TO(0,ptr);
+ continue;
+ }
+ put_int32(mif, ptr);
+ }
+ continue;
+
case INET_OPT_LINGER:
arg_sz = sizeof(li_val);
sys_memzero((void *) &li_val, sizeof(li_val));
@@ -8179,14 +9023,36 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc,
}
#endif /* #ifdef __WIN32__ */
+ case INET_LOPT_DEBUG:
+ *ptr++ = opt;
+ ival = desc->debug;
+ put_int32(ival, ptr);
+ continue;
+
default:
RETURN_ERROR();
}
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_fill_opts -> try get opt (proto %d, type %d)\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), proto, type) );
+
/* We have 5 bytes allocated to ptr */
if (IS_SOCKET_ERROR(sock_getopt(desc->s,proto,type,arg_ptr,&arg_sz))) {
+ int save_errno = sock_errno();
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_fill_opts -> failed get option (%d) %d: "
+ "\r\n errno: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port),
+ proto, type, save_errno) );
+
TRUNCATE_TO(0,ptr);
continue;
}
+
*ptr++ = opt;
if (arg_ptr == (char*)&ival) {
put_int32(ival, ptr);
@@ -8264,7 +9130,7 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc,
return (Errno); \
} while(0)
- /* Spec is a name parmeter */
+ /* Spec is a name parameter */
# define PLACE_FOR(Spec, Index, N) \
do { \
int need; \
@@ -8802,7 +9668,7 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc,
i = LOAD_INT (spec, i, ap.spp_hbinterval);
i = LOAD_INT (spec, i, ap.spp_pathmaxrxt);
- /* The following fields are not suported in SOLARIS10,
+ /* The following fields are not supported in SOLARIS10,
** so put 0s for "spp_pathmtu", "spp_sackdelay",
** and empty list for "spp_flags":
*/
@@ -9199,6 +10065,11 @@ static ErlDrvSSizeT inet_subscribe(inet_descriptor* desc,
/* Terminate socket */
static void inet_stop(inet_descriptor* desc)
{
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR "] "
+ "inet_stop -> entry\r\n",
+ __LINE__, desc->s) );
+
erl_inet_close(desc);
#ifdef HAVE_SETNS
if (desc->netns != NULL)
@@ -9306,6 +10177,8 @@ static ErlDrvData inet_start(ErlDrvPort port, int size, int protocol)
desc->recv_cmsgflags = 0;
+ desc->debug = DDBG_DEFAULT;
+
return (ErlDrvData)desc;
}
@@ -9327,6 +10200,11 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
ErlDrvSizeT i;
int dstlen = 1; /* Reply code */
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_ctl -> GETSTAT\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
for (i = 0; i < len; i++) {
switch(buf[i]) {
case INET_STAT_SEND_OCT: dstlen += 9; break;
@@ -9334,7 +10212,7 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
default: dstlen += 5; break;
}
}
- DEBUGF(("inet_ctl(%p): GETSTAT\r\n", (long) desc->port));
+
if (dstlen > INET_MAX_OPT_BUFFER) /* sanity check */
return 0;
if (dstlen > rsize) {
@@ -9350,8 +10228,12 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
case INET_REQ_SUBSCRIBE: {
char* dst;
int dstlen = 1 /* Reply code */ + len*5;
- DEBUGF(("inet_ctl(%p): INET_REQ_SUBSCRIBE\r\n",
- desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_ctl -> SUBSCRIBE\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
if (dstlen > INET_MAX_OPT_BUFFER) /* sanity check */
return 0;
if (dstlen > rsize) {
@@ -9366,7 +10248,12 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
case INET_REQ_GETOPTS: { /* get options */
ErlDrvSSizeT replen;
- DEBUGF(("inet_ctl(%p): GETOPTS\r\n", desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "inet_ctl -> GETOPTS\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
#ifdef HAVE_SCTP
if (IS_SCTP(desc))
{
@@ -9374,44 +10261,73 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
return ctl_error(-replen, rbuf, rsize);
} else
#endif
- if ((replen = inet_fill_opts(desc, buf, len, rbuf, rsize)) < 0) {
- return ctl_error(EINVAL, rbuf, rsize);
- }
+ if ((replen = inet_fill_opts(desc, buf, len, rbuf, rsize)) < 0) {
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
return replen;
}
case INET_REQ_GETIFLIST: {
- DEBUGF(("inet_ctl(%p): GETIFLIST\r\n", desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETIFLIST\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (!IS_OPEN(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
return inet_ctl_getiflist(desc, rbuf, rsize);
}
case INET_REQ_GETIFADDRS: {
- DEBUGF(("inet_ctl(%p): GETIFADDRS\r\n", desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETIFADDRS\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (!IS_OPEN(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
return inet_ctl_getifaddrs(desc, rbuf, rsize);
}
case INET_REQ_IFGET: {
- DEBUGF(("inet_ctl(%p): IFGET\r\n", desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> IFGET\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (!IS_OPEN(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
return inet_ctl_ifget(desc, buf, len, rbuf, rsize);
}
case INET_REQ_IFSET: {
- DEBUGF(("inet_ctl(%p): IFSET\r\n", desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> IFSET\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (!IS_OPEN(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
return inet_ctl_ifset(desc, buf, len, rbuf, rsize);
}
case INET_REQ_SETOPTS: { /* set options */
- DEBUGF(("inet_ctl(%p): SETOPTS\r\n", desc->port));
- /* XXX fprintf(stderr,"inet_ctl(%p): SETOPTS (len = %d)\r\n", desc->port,(int) len); */
- switch(inet_set_opts(desc, buf, len)) {
+ int sres;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%d,%T] inet_ctl -> SETOPTS\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
+ sres = inet_set_opts(desc, buf, len);
+
+ /* We cannot debug-print if sres == 0 since we have then actually *
+ * completed a driver_exit => we have no longer a descriptor! */
+ if (sres != 0)
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%d,%T] inet_ctl(setopts) -> sres: %d\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), sres) );
+
+ switch(sres) {
case -1:
return ctl_error(EINVAL, rbuf, rsize);
case 0:
@@ -9436,18 +10352,26 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
}
}
+
case INET_REQ_GETSTATUS: {
char tbuf[4];
- DEBUGF(("inet_ctl(%p): GETSTATUS\r\n", desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETSTATUS\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
put_int32(desc->state, tbuf);
return ctl_reply(INET_REP_OK, tbuf, 4, rbuf, rsize);
}
+
case INET_REQ_GETTYPE: {
char tbuf[8];
- DEBUGF(("inet_ctl(%p): GETTYPE\r\n", desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETTYPE\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (desc->sfamily == AF_INET) {
put_int32(INET_AF_INET, &tbuf[0]);
}
@@ -9484,18 +10408,24 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
case INET_REQ_GETFD: {
char tbuf[4];
- DEBUGF(("inet_ctl(%p): GETFD\r\n", desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%d,%T] inet_ctl -> GETFD\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
if (!IS_OPEN(desc))
return ctl_error(EINVAL, rbuf, rsize);
put_int32((long)desc->s, tbuf);
return ctl_reply(INET_REP_OK, tbuf, 4, rbuf, rsize);
}
+
case INET_REQ_GETHOSTNAME: { /* get host name */
char tbuf[INET_MAXHOSTNAMELEN + 1];
- DEBUGF(("inet_ctl(%p): GETHOSTNAME\r\n",
- desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETHOSTNAME\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (len != 0)
return ctl_error(EINVAL, rbuf, rsize);
@@ -9505,9 +10435,12 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
return ctl_reply(INET_REP_OK, tbuf, strlen(tbuf), rbuf, rsize);
}
+
case INET_REQ_GETPADDRS: {
- DEBUGF(("inet_ctl(%p): INET_GETPADDRS\r\n",
- desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETPADDRS\r\n",
+ __LINE__, driver_caller(desc->port)) );
if (len != 4) return ctl_error(EINVAL, rbuf, rsize);
@@ -9538,13 +10471,16 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
}
}
+
case INET_REQ_PEER: { /* get peername */
char tbuf[sizeof(inet_address)];
inet_address peer;
inet_address* ptr;
unsigned int sz;
- DEBUGF(("inet_ctl(%p): PEER\r\n", desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> PEER\r\n",
+ __LINE__, driver_caller(desc->port)) );
if (!(desc->state & INET_F_ACTIVE))
return ctl_error(ENOTCONN, rbuf, rsize);
@@ -9567,6 +10503,11 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
case INET_REQ_SETPEER: { /* set fake peername Port Address */
char *xerror;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> SETPEER\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (len == 0) {
desc->peer_ptr = NULL;
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
@@ -9584,8 +10525,10 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
}
case INET_REQ_GETLADDRS: {
- DEBUGF(("inet_ctl(%p): INET_GETLADDRS\r\n",
- desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETLADDRS\r\n",
+ __LINE__, driver_caller(desc->port)) );
if (len != 4) return ctl_error(EINVAL, rbuf, rsize);
@@ -9623,7 +10566,9 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
inet_address* ptr;
unsigned int sz;
- DEBUGF(("inet_ctl(%p): NAME\r\n", desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%d,%T] inet_ctl -> NAME\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
if ((ptr = desc->name_ptr) != NULL) {
sz = desc->name_addr_len;
@@ -9643,6 +10588,11 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
case INET_REQ_SETNAME: { /* set fake sockname Port Address */
char *xerror;
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> SETNAME\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (len == 0) {
desc->name_ptr = NULL;
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
@@ -9664,7 +10614,9 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
inet_address local;
int port;
- DEBUGF(("inet_ctl(%p): BIND\r\n", desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%d,%T] inet_ctl -> BIND\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
if (len < 2)
return ctl_error(EINVAL, rbuf, rsize);
@@ -9675,12 +10627,9 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
(desc->sfamily, &local, &buf, &len)) != NULL)
return ctl_xerror(xerror, rbuf, rsize);
- // printf("inet_ctl(INET_REQ_BIND) -> try bind\r\n");
if (IS_SOCKET_ERROR(sock_bind(desc->s,(struct sockaddr*) &local, len))) {
- // printf("inet_ctl(INET_REQ_BIND) -> bind failed\r\n");
return ctl_error(sock_errno(), rbuf, rsize);
}
- // printf("inet_ctl(INET_REQ_BIND) -> bound\r\n");
desc->state = INET_STATE_OPEN;
@@ -9697,8 +10646,10 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
}
case INET_REQ_IGNOREFD: {
- DEBUGF(("inet_ctl(%p): IGNOREFD, IGNORED = %d\r\n",
- desc->port,(int)*buf));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%d,%T] inet_ctl -> IGNOREFD: %s\r\n",
+ __LINE__, desc->s, driver_caller(desc->port), B2S(*buf)) );
/*
* FD can only be ignored for connected TCP connections for now,
@@ -9739,6 +10690,10 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
short port;
int n;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETSERVBYNAME\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (len < 2)
return ctl_error(EINVAL, rbuf, rsize);
n = get_int8(buf); buf++; len--;
@@ -9765,6 +10720,10 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
int n;
struct servent* srv;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> GETSERVBYPORT\r\n",
+ __LINE__, driver_caller(desc->port)) );
+
if (len < 3)
return ctl_error(EINVAL, rbuf, rsize);
port = get_int16(buf);
@@ -9782,6 +10741,9 @@ static ErlDrvSSizeT inet_ctl(inet_descriptor* desc, int cmd, char* buf,
}
default:
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] inet_ctl -> unknown command\r\n",
+ __LINE__, driver_caller(desc->port)) );
return ctl_xerror(EXBADPORT, rbuf, rsize);
}
}
@@ -10111,8 +11073,10 @@ static void tcp_close_check(tcp_descriptor* desc)
static void tcp_inet_stop(ErlDrvData e)
{
tcp_descriptor* desc = (tcp_descriptor*)e;
- DEBUGF(("tcp_inet_stop(%p) {s=%d\r\n",
- desc->inet.port, desc->inet.s));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR "] tcp_inet_stop -> entry\r\n",
+ __LINE__, desc->inet.s) );
tcp_close_check(desc);
tcp_clear_input(desc);
@@ -10121,12 +11085,15 @@ static void tcp_inet_stop(ErlDrvData e)
if(desc->tcp_add_flags & TCP_ADDF_SENDFILE) {
desc->tcp_add_flags &= ~TCP_ADDF_SENDFILE;
close(desc->sendfile.dup_file_fd);
- DEBUGF(("tcp_inet_stop(%p): SENDFILE dup closed %d\r\n",
- desc->inet.port, desc->sendfile.dup_file_fd));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR "] "
+ "tcp_inet_stop -> SENDFILE dup closed %d\r\n",
+ __LINE__, desc->inet.s, desc->sendfile.dup_file_fd) );
+
}
#endif
- DEBUGF(("tcp_inet_stop(%p) }\r\n", desc->inet.port));
inet_stop(INETP(desc));
}
@@ -10167,10 +11134,14 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
cmd -= ERTS_INET_DRV_CONTROL_MAGIC_NUMBER;
switch(cmd) {
+
case INET_REQ_OPEN: { /* open socket and return internal index */
int domain;
- DEBUGF(("tcp_inet_ctl(%p): OPEN\r\n",
- desc->inet.port));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][%T] tcp_inet_ctl -> OPEN\r\n",
+ __LINE__, driver_caller(desc->inet.port)) );
+
if (len != 2) return ctl_error(EINVAL, rbuf, rsize);
switch(buf[0]) {
case INET_AF_INET:
@@ -10194,11 +11165,16 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
break;
}
+
case INET_REQ_FDOPEN: { /* pass in an open (and optionally bound) socket */
int domain;
int bound;
- DEBUGF(("tcp_inet_ctl(%p): FDOPEN\r\n",
- desc->inet.port));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> FDOPEN\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
+
if (len != 6 && len != 10) return ctl_error(EINVAL, rbuf, rsize);
switch(buf[0]) {
case INET_AF_INET:
@@ -10228,11 +11204,15 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
break;
}
- case INET_REQ_LISTEN: { /* argument backlog */
+ case INET_REQ_LISTEN: { /* argument backlog */
int backlog;
- DEBUGF(("tcp_inet_ctl(%p): LISTEN\r\n",
- desc->inet.port));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> LISTEN\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
+
if (desc->inet.state == INET_STATE_CLOSED)
return ctl_xerror(EXBADPORT, rbuf, rsize);
if (!IS_OPEN(INETP(desc)))
@@ -10252,8 +11232,11 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
char tbuf[2], *xerror;
unsigned timeout;
- DEBUGF(("tcp_inet_ctl(%p): CONNECT\r\n",
- desc->inet.port));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> CONNECT\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
+
/* INPUT: Timeout(4), Port(2), Address(N) */
if (!IS_OPEN(INETP(desc)))
@@ -10273,16 +11256,35 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
code = sock_connect(desc->inet.s,
(struct sockaddr*) &desc->inet.remote, len);
+
+ /* We *cannot* have debug printouts here since it resets the
+ * 'errno' value (printf).
+ */
+
if (IS_SOCKET_ERROR(code) &&
((sock_errno() == ERRNO_BLOCK) || /* Winsock2 */
(sock_errno() == EINPROGRESS))) { /* Unix & OSE!! */
- sock_select(INETP(desc), FD_CONNECT, 1);
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl(connect) -> would block => select\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port)) );
+
+ sock_select(INETP(desc), FD_CONNECT, 1);
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 */
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl(connect) -> connected\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port)) );
+
desc->inet.state = INET_STATE_CONNECTED;
if (desc->inet.active)
sock_select(INETP(desc), (FD_READ|FD_CLOSE), 1);
@@ -10290,11 +11292,21 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
async_ok(INETP(desc));
}
else {
- return ctl_error(sock_errno(), rbuf, rsize);
+ int save_errno = sock_errno();
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl(connect) -> error: %s (%d)\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port),
+ errno_str(save_errno), save_errno) );
+
+ return ctl_error(save_errno, rbuf, rsize);
}
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
}
+
case INET_REQ_ACCEPT: { /* do async accept */
char tbuf[2];
unsigned timeout;
@@ -10302,8 +11314,11 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
unsigned int n;
SOCKET s;
- DEBUGF(("tcp_inet_ctl(%p): ACCEPT\r\n",
- desc->inet.port));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> ACCEPT\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
+
/* INPUT: Timeout(4) */
if ((desc->inet.state != INET_STATE_LISTENING && desc->inet.state != INET_STATE_ACCEPTING &&
@@ -10405,9 +11420,12 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
}
}
+
+
case INET_REQ_CLOSE:
- DEBUGF(("tcp_inet_ctl(%p): CLOSE\r\n",
- desc->inet.port));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] tcp_inet_ctl -> CLOSE\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
tcp_close_check(desc);
tcp_desc_close(desc);
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
@@ -10418,8 +11436,10 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
char tbuf[2];
int n;
- DEBUGF(("tcp_inet_ctl(%p): RECV (s=%d)\r\n",
- desc->inet.port, desc->inet.s));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] tcp_inet_ctl -> RECV\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
+
/* INPUT: Timeout(4), Length(4) */
if (!IS_CONNECTED(INETP(desc))) {
if (desc->tcp_add_flags & TCP_ADDF_DELAYED_CLOSE_RECV) {
@@ -10438,8 +11458,13 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
timeout = get_int32(buf);
buf += 4;
n = get_int32(buf);
- DEBUGF(("tcp_inet_ctl(%p) timeout = %d, n = %d\r\n",
- desc->inet.port,timeout,n));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl(recv) -> timeout: %d, n: %d\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port), timeout, n) );
+
if ((desc->inet.htype != TCP_PB_RAW) && (n != 0))
return ctl_error(EINVAL, rbuf, rsize);
if (n > TCP_MAX_PACKET_SIZE)
@@ -10463,9 +11488,11 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
}
+
case TCP_REQ_UNRECV: {
- DEBUGF(("tcp_inet_ctl(%p): UNRECV\r\n",
- desc->inet.port));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] tcp_inet_ctl -> UNRECV\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
if (!IS_CONNECTED(INETP(desc)))
return ctl_error(ENOTCONN, rbuf, rsize);
tcp_push_buffer(desc, buf, len);
@@ -10473,17 +11500,31 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
tcp_deliver(desc, 0);
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
}
+
+
case TCP_REQ_SHUTDOWN: {
int how;
- DEBUGF(("tcp_inet_ctl(%p): FDOPEN\r\n",
- desc->inet.port));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> SHUTDOWN\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
+
if (!IS_CONNECTED(INETP(desc))) {
return ctl_error(ENOTCONN, rbuf, rsize);
}
if (len != 1) {
return ctl_error(EINVAL, rbuf, rsize);
}
+
how = buf[0];
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl(shutdown) -> how: %s (%d)\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port), SH2S(how), how) );
+
if (how != TCP_SHUT_RD && driver_sizeq(desc->inet.port) > 0) {
if (how == TCP_SHUT_WR) {
desc->tcp_add_flags |= TCP_ADDF_PENDING_SHUT_WR;
@@ -10501,6 +11542,7 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
}
}
+
case TCP_REQ_SENDFILE: {
#ifdef HAVE_SENDFILE
const ErlDrvSizeT required_len =
@@ -10509,8 +11551,10 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
int raw_file_fd;
- DEBUGF(("tcp_inet_ctl(%p): SENDFILE\r\n",
- desc->inet.port));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> SENDFILE\r\n",
+ __LINE__, desc->inet.s, driver_caller(desc->inet.port)) );
if (len != required_len) {
return ctl_error(EINVAL, rbuf, rsize);
@@ -10530,8 +11574,12 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
desc->sendfile.dup_file_fd = dup(raw_file_fd);
- DEBUGF(("tcp_inet_ctl(%p): SENDFILE dup %d\r\n",
- desc->inet.port, desc->sendfile.dup_file_fd));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl(sendfile) -> dup: %d\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port),
+ desc->sendfile.dup_file_fd) );
if(desc->sendfile.dup_file_fd == -1) {
return ctl_error(errno, rbuf, rsize);
@@ -10565,8 +11613,11 @@ static ErlDrvSSizeT tcp_inet_ctl(ErlDrvData e, unsigned int cmd,
}
default:
- DEBUGF(("tcp_inet_ctl(%p): %u\r\n",
- desc->inet.port, cmd));
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_ctl -> (maybe) general command %u\r\n",
+ __LINE__,
+ desc->inet.s, driver_caller(desc->inet.port), cmd) );
return inet_ctl(INETP(desc), cmd, buf, len, rbuf, rsize);
}
@@ -10660,31 +11711,50 @@ static int tcp_inet_multi_timeout(ErlDrvData e, ErlDrvTermData caller)
** output on a socket only !
** a reply code will be sent to connected (caller later)
** {inet_reply, S, Status}
-** NOTE! normal sockets use the the tcp_inet_commandv
+** NOTE! normal sockets use the tcp_inet_commandv
** but distribution still uses the tcp_inet_command!!
*/
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);
+ tcp_descriptor* desc = (tcp_descriptor*)e;
+ ErlDrvTermData caller = driver_caller(desc->inet.port);
+
+ desc->inet.caller = caller;
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_command -> entry\r\n",
+ __LINE__, desc->inet.s, caller) );
- DEBUGF(("tcp_inet_command(%p) {s=%d\r\n",
- desc->inet.port, desc->inet.s));
if (!IS_CONNECTED(INETP(desc)))
inet_reply_error(INETP(desc), ENOTCONN);
else if (tcp_send(desc, buf, len) == 0)
inet_reply_ok(INETP(desc));
- DEBUGF(("tcp_inet_command(%p) }\r\n", desc->inet.port));
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_command -> done\r\n",
+ __LINE__, desc->inet.s, caller) );
+
}
static void tcp_inet_commandv(ErlDrvData e, ErlIOVec* ev)
{
- tcp_descriptor* desc = (tcp_descriptor*)e;
- desc->inet.caller = driver_caller(desc->inet.port);
+ tcp_descriptor* desc = (tcp_descriptor*)e;
+ ErlDrvTermData caller = driver_caller(desc->inet.port);
+
+ desc->inet.caller = caller;
+
+#ifdef INET_DRV_DEBUG
+ /* This function is just called to much to be part of this *
+ * by default. Atleast as long as there are no 'debug levels'. */
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "tcp_inet_commandv -> entry\r\n",
+ __LINE__, desc->inet.s, caller) );
+#endif
- DEBUGF(("tcp_inet_commandv(%p) {s=%d\r\n",
- desc->inet.port, desc->inet.s));
if (!IS_CONNECTED(INETP(desc))) {
if (desc->tcp_add_flags & TCP_ADDF_DELAYED_CLOSE_SEND) {
desc->tcp_add_flags &= ~TCP_ADDF_DELAYED_CLOSE_SEND;
@@ -10703,7 +11773,13 @@ static void tcp_inet_commandv(ErlDrvData e, ErlIOVec* ev)
tcp_shutdown_error(desc, EPIPE);
else if (tcp_sendv(desc, ev) == 0)
inet_reply_ok(INETP(desc));
- DEBUGF(("tcp_inet_commandv(%p) }\r\n", desc->inet.port));
+
+#ifdef INET_DRV_DEBUG
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] tcp_inet_commandv -> done\r\n",
+ __LINE__, desc->inet.s, caller) );
+#endif
+
}
static void tcp_inet_flush(ErlDrvData e)
@@ -10734,7 +11810,13 @@ static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp)
{
tcp_descriptor* desc = (tcp_descriptor*)e;
ErlDrvTermData who = driver_get_monitored_process(desc->inet.port,monitorp);
- int state = desc->inet.state;
+ int state = desc->inet.state;
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%p] "
+ "tcp_inet_process_exit -> entry with"
+ "\r\n who: %T\r\n",
+ __LINE__, desc->inet.s, desc->inet.port, who) );
if ((state & INET_STATE_MULTI_ACCEPTING) == INET_STATE_MULTI_ACCEPTING) {
int id,req;
@@ -10757,6 +11839,12 @@ static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp)
sock_select(INETP(desc),FD_ACCEPT,0);
desc->inet.state = INET_STATE_LISTENING; /* restore state */
}
+
+ DDBG(INETP(desc),
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%p] "
+ "tcp_inet_process_exit -> done\r\n",
+ __LINE__, desc->inet.s, desc->inet.port) );
+
}
static void inet_stop_select(ErlDrvEvent event, void* _)
@@ -10776,7 +11864,7 @@ static int tcp_recv_closed(tcp_descriptor* desc)
#endif
int blocking_send = 0;
DEBUGF(("tcp_recv_closed(%p): s=%d, in %s, line %d\r\n",
- port, desc->inet.s, __FILE__, __LINE__));
+ port, desc->inet.s, __LINE__));
if (IS_BUSY(INETP(desc))) {
/* A send is blocked */
desc->inet.caller = desc->inet.busy_caller;
@@ -11182,7 +12270,7 @@ static int winsock_event_select(inet_descriptor *desc, int flags, int on)
return -1;
}
- /* Now, WSAEventSelect() is trigged only when the queue goes from
+ /* Now, WSAEventSelect() is triggered only when the queue goes from
full to empty or from empty to full; therefore we need an extra test
to see whether it is writeable, readable or closed... */
if ((desc->event_mask & FD_WRITE)) {
@@ -11324,7 +12412,7 @@ static void tcp_inet_event(ErlDrvData e, ErlDrvEvent event)
}
if (netEv.lNetworkEvents & FD_CLOSE) {
/* error in err = netEv.iErrorCode[FD_CLOSE_BIT] */
- DEBUGF(("Detected close in %s, line %d\r\n", __FILE__, __LINE__));
+ DEBUGF(("Detected close in %s, line %d\r\n", __LINE__));
if (desc->tcp_add_flags & TCP_ADDF_SHOW_ECONNRESET) {
err = netEv.iErrorCode[FD_CLOSE_BIT];
if (err == ECONNRESET)
@@ -11533,7 +12621,7 @@ static int tcp_send_or_shutdown_error(tcp_descriptor* desc, int err)
* and active sockets.
*/
DEBUGF(("driver_failure_eof(%p) in %s, line %d\r\n",
- desc->inet.port, __FILE__, __LINE__));
+ desc->inet.port, __LINE__));
if (desc->inet.active) {
ErlDrvTermData err_atom;
if (show_econnreset) {
@@ -12129,7 +13217,7 @@ done:
}
#endif /* HAVE_SENDFILE */
-/* socket ready for ouput:
+/* socket ready for output:
** 1. INET_STATE_CONNECTING => non block connect ?
** 2. INET_STATE_CONNECTED => write output
*/
@@ -12471,13 +13559,16 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
int af = AF_INET;
cmd -= ERTS_INET_DRV_CONTROL_MAGIC_NUMBER;
+
switch(cmd) {
case INET_REQ_OPEN: /* open socket and return internal index */
- DEBUGF(("packet_inet_ctl(%p): OPEN\r\n",
- desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][%T] packet_inet_ctl -> OPEN\r\n",
+ __LINE__, driver_caller(desc->port)) );
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)
@@ -12489,6 +13580,7 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
default:
return ctl_xerror(str_eafnosupport, rbuf, rsize);
}
+
switch (buf[1]) {
case INET_TYPE_STREAM: type = SOCK_STREAM; break;
case INET_TYPE_DGRAM: type = SOCK_DGRAM; break;
@@ -12498,6 +13590,7 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
default:
return ctl_error(EINVAL, rbuf, rsize);
}
+
replen = inet_ctl_open(desc, af, type, rbuf, rsize);
if ((*rbuf)[0] != INET_REP_ERROR) {
@@ -12523,11 +13616,16 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
case INET_REQ_FDOPEN: { /* pass in an open (and optionally bound) socket */
SOCKET s;
int bound;
- DEBUGF(("packet inet_ctl(%p): FDOPEN\r\n",
- desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> FDOPEN\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
if (len != 6 && len != 10) {
return ctl_error(EINVAL, rbuf, rsize);
}
+
switch (buf[0]) {
case INET_AF_INET: af = AF_INET; break;
#if defined(HAVE_IN6) && defined(AF_INET6)
@@ -12539,6 +13637,7 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
default:
return ctl_xerror(str_eafnosupport, rbuf, rsize);
}
+
switch (buf[1]) {
case INET_TYPE_STREAM: type = SOCK_STREAM; break;
case INET_TYPE_DGRAM: type = SOCK_DGRAM; break;
@@ -12577,8 +13676,10 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
case INET_REQ_CLOSE:
- DEBUGF(("packet_inet_ctl(%p): CLOSE\r\n",
- desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> CLOSE\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
erl_inet_close(desc);
return ctl_reply(INET_REP_OK, NULL, 0, rbuf, rsize);
@@ -12595,9 +13696,15 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
char tbuf[2];
#ifdef HAVE_SCTP
unsigned timeout;
+ sctp_assoc_t assoc_id = 0;
+ sctp_assoc_t *p_assoc_id = NULL;
#endif
- DEBUGF(("packet_inet_ctl(%p): CONNECT\r\n",
- desc->port));
+
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> CONNECT\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
/* INPUT: [ Timeout(4), Port(2), Address(N) ] */
@@ -12619,22 +13726,55 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
/* For SCTP, we do not set the peer's addr in desc->remote, as
multiple peers are possible: */
- if ((xerror = inet_set_faddress
- (desc->sfamily, &remote, &buf, &len)) != NULL)
+ if ((*buf) == INET_AF_LIST) {
+ /* called as gen_sctp:connectx... */
+ int addrcnt = 0;
+ buf++; len--;
+ addrcnt = get_int8(buf),
+ buf++; len--;
+ if (! p_sctp_connectx)
+ return ctl_error(ENOTSUP, rbuf, rsize);
+ if (addrcnt > 0) {
+ char *rabuf = ALLOC(sizeof(inet_address) * addrcnt);
+ struct sockaddr *addrs = (struct sockaddr *) rabuf;
+ ErlDrvSizeT remote_size;
+ char *ep = buf + len;
+
+ for(int ai=0; ai < addrcnt; ai++) {
+ remote_size = ep - buf;
+ if ((xerror = inet_set_faddress
+ (desc->sfamily, &remote, &buf, &remote_size)) != NULL) {
+ FREE((char *)addrs);
+ return ctl_xerror(xerror, rbuf, rsize);
+ }
+ memcpy(rabuf, &remote, remote_size);
+ rabuf += remote_size;
+ }
+ p_assoc_id = &assoc_id;
+ code = p_sctp_connectx(desc->s, addrs, addrcnt, p_assoc_id);
+ FREE((char *)addrs);
+ } else {
+ return ctl_error(EINVAL, rbuf, rsize);
+ }
+ } else {
+ /* called as gen_sctp:connect... */
+ if ((xerror = inet_set_faddress
+ (desc->sfamily, &remote, &buf, &len)) != NULL)
return ctl_xerror(xerror, rbuf, rsize);
-
- code = sock_connect(desc->s, &remote.sa, len);
+
+ code = sock_connect(desc->s, &remote.sa, len);
+ }
if (IS_SOCKET_ERROR(code) && (sock_errno() == EINPROGRESS)) {
/* XXX: Unix only -- WinSock would have a different cond! */
if (timeout != INET_INFINITY)
driver_set_timer(desc->port, timeout);
enq_async(desc, tbuf, INET_REQ_CONNECT);
- async_ok(desc);
+ async_ok_maybe_assoc_id(desc, p_assoc_id);
}
else if (code == 0) { /* OK we are connected */
enq_async(desc, tbuf, INET_REQ_CONNECT);
- async_ok(desc);
+ async_ok_maybe_assoc_id(desc, p_assoc_id);
}
else {
return ctl_error(sock_errno(), rbuf, rsize);
@@ -12694,9 +13834,12 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
from the TCP section. Returns: {ok,[]} on success.
*/
int backlog;
-
- DEBUGF(("packet_inet_ctl(%p): LISTEN\r\n",
- desc->port));
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> LISTEN\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
if (!IS_SCTP(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
if (!IS_OPEN(desc))
@@ -12723,6 +13866,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
char* curr;
int add_flag, rflag;
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> BINDX\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
if (!IS_SCTP(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
@@ -12761,8 +13909,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
int err;
SOCKET new_socket;
- DEBUGF(("packet_inet_ctl(%p): PEELOFF\r\n",
- desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> PEELOFF\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
if (!IS_SCTP(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
if (!IS_OPEN(desc))
@@ -12803,8 +13954,11 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
unsigned timeout;
char tbuf[2];
- DEBUGF(("packet_inet_ctl(%p): RECV\r\n",
- desc->port));
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%T] "
+ "packet_inet_ctl -> RECV\r\n",
+ __LINE__, desc->s, driver_caller(desc->port)) );
+
/* INPUT: Timeout(4), Length(4) */
if (!IS_OPEN(desc))
return ctl_xerror(EXBADPORT, rbuf, rsize);
@@ -12829,6 +13983,7 @@ static ErlDrvSSizeT packet_inet_ctl(ErlDrvData e, unsigned int cmd, char* buf,
INET_REQ_BIND goes here. If the req is not recognised
there either, an error is returned:
*/
+
return inet_ctl(desc, cmd, buf, len, rbuf, rsize);
}
}
@@ -12837,6 +13992,12 @@ static void packet_inet_timeout(ErlDrvData e)
{
udp_descriptor * udesc = (udp_descriptor*) e;
inet_descriptor * desc = INETP(udesc);
+
+ DDBG(desc,
+ ("INET-DRV-DBG[%d][" SOCKET_FSTR ",%p] "
+ "packet_inet_timeout -> entry\r\n",
+ __LINE__, desc->s, desc->port) );
+
if (!(desc->active)) {
sock_select(desc, FD_READ, 0);
async_error_am (desc, am_timeout);
@@ -12850,7 +14011,7 @@ static void packet_inet_timeout(ErlDrvData e)
** input should be: Family Address buffer .
** For UDP, buffer (after Address) is just data to be sent.
** For SCTP, buffer contains a list representing 2 items:
-** (1) 6 parms for sctp_sndrcvinfo, as in sctp_get_sendparams();
+** (1) 6 params for sctp_sndrcvinfo, as in sctp_get_sendparams();
** (2) 0+ real data bytes.
** There is no destination address -- SCTP send is performed over
** an existing association, using "sctp_sndrcvinfo" specified.
@@ -13516,7 +14677,7 @@ subs_list *subs;
this = subs->next;
while(this) {
next = this->next;
- FREE((void *) this);
+ FREE(this);
this = next;
}
@@ -13547,7 +14708,7 @@ static void send_to_subscribers
if(free_subs && !first) {
next = this->next;
- FREE((void *) this);
+ FREE(this);
this = next;
}
else
@@ -13561,76 +14722,3 @@ static void send_to_subscribers
}
}
-
-/*
- * A *very* limited socket interface. Used by the memory tracer
- * (erl_mtrace.c).
- */
-#include "erl_sock.h"
-
-erts_sock_t erts_sock_open(void)
-{
- SOCKET s;
-
- if(!sock_init())
- return ERTS_SOCK_INVALID_SOCKET;
-
- s = sock_open(AF_INET, SOCK_STREAM, 0);
-
- if (s == INVALID_SOCKET)
- return ERTS_SOCK_INVALID_SOCKET;
-
- return (erts_sock_t) s;
-}
-
-void erts_sock_close(erts_sock_t socket)
-{
- if (socket != ERTS_SOCK_INVALID_SOCKET)
- sock_close((SOCKET) socket);
-}
-
-
-int erts_sock_connect(erts_sock_t socket, byte *ip_addr, int len, Uint16 port)
-{
- SOCKET s = (SOCKET) socket;
- char buf[2 + 4], *p;
- ErlDrvSizeT blen = 6;
- inet_address addr;
-
- if (socket == ERTS_SOCK_INVALID_SOCKET || len != 4)
- return 0;
-
- put_int16(port, buf);
- memcpy((void *) (buf + 2), (void *) ip_addr, 4);
-
- p = buf;
- if (inet_set_address(AF_INET, &addr, &p, &blen) != NULL)
- return 0;
-
- if (IS_SOCKET_ERROR
- (sock_connect(s, (struct sockaddr *) &addr, blen)))
- return 0;
- return 1;
-}
-
-Sint erts_sock_send(erts_sock_t socket, const void *buf, Sint len)
-{
- Sint result = (Sint) sock_send((SOCKET) socket, buf, (size_t) len, 0);
- if (IS_SOCKET_ERROR(result))
- return SOCKET_ERROR;
- return result;
-}
-
-
-int erts_sock_gethostname(char *buf, int bufsz)
-{
- if (IS_SOCKET_ERROR(sock_hostname(buf, bufsz)))
- return SOCKET_ERROR;
- return 0;
-}
-
-
-int erts_sock_errno()
-{
- return sock_errno();
-}
diff --git a/erts/emulator/drivers/common/ram_file_drv.c b/erts/emulator/drivers/common/ram_file_drv.c
index 8112f82476..fb2ac31ca7 100644
--- a/erts/emulator/drivers/common/ram_file_drv.c
+++ b/erts/emulator/drivers/common/ram_file_drv.c
@@ -129,11 +129,11 @@ struct erl_drv_entry ram_file_driver_entry = {
/* A File is represented as a array of bytes, this array is
reallocated when needed. A possibly better implementation
- whould be to have a vector of blocks. This may be implemented
+ would be to have a vector of blocks. This may be implemented
when we have the commandv/driver_outputv
*/
typedef struct ram_file {
- ErlDrvPort port; /* the associcated port */
+ ErlDrvPort port; /* the associated port */
int flags; /* flags read/write */
ErlDrvBinary* bin; /* binary to hold binary file */
char* buf; /* buffer start (in binary) */
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index 58a56e8cf0..08ab714153 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,7 +82,7 @@ char *tgetstr(char* cap, char** buf);
char *tgoto(char* cm, int col, int line);
int tputs(char* cp, int affcnt, int (*outc)(int c));
-/* Terminal capabilites in which we are interested. */
+/* Terminal capabilities in which we are interested. */
static char *capbuf;
static char *up, *down, *left, *right;
static int cols, xn;
@@ -152,7 +152,7 @@ static int ins_chars(byte *,int);
static int del_chars(int);
static int step_over_chars(int);
static int insert_buf(byte*,int);
-static int write_buf(Uint32 *,int);
+static int write_buf(Uint32 *,int,int);
static int outc(int c);
static int move_cursor(int,int);
static int cp_pos_to_col(int cp_pos);
@@ -942,12 +942,12 @@ static int put_chars(byte *s, int l)
if (lpos > llen)
llen = lpos;
if (n > 0)
- write_buf(lbuf + lpos - n, n);
+ write_buf(lbuf + lpos - n, n, 0);
return TRUE;
}
/*
- * Move the current postition forwards or backwards within the current
+ * Move the current position forwards or backwards within the current
* line. We know about padding.
*/
static int move_rel(int n)
@@ -981,7 +981,7 @@ static int ins_chars(byte *s, int l)
driver_free(tbuf);
}
llen += n;
- write_buf(lbuf + (lpos - n), llen - (lpos - n));
+ write_buf(lbuf + (lpos - n), llen - (lpos - n), 0);
move_cursor(llen, lpos);
return TRUE;
}
@@ -1011,7 +1011,7 @@ static int del_chars(int n)
memmove(lbuf + lpos, lbuf + pos, r * sizeof(Uint32));
llen -= l;
/* Write out characters after, blank the tail and jump back to lpos. */
- write_buf(lbuf + lpos, r);
+ write_buf(lbuf + lpos, r, 0);
for (i = gcs ; i > 0; --i)
outc(' ');
if (xn && COL(cp_pos_to_col(llen)+gcs) == 0)
@@ -1031,7 +1031,7 @@ static int del_chars(int n)
lpos -= l;
llen -= l;
/* Write out characters after, blank the tail and jump back to lpos. */
- write_buf(lbuf + lpos, r);
+ write_buf(lbuf + lpos, r, 0);
for (i = gcs ; i > 0; --i)
outc(' ');
if (xn && COL(cp_pos_to_col(llen)+gcs) == 0)
@@ -1101,7 +1101,7 @@ static int insert_buf(byte *s, int n)
DEBUGLOG(("insert_buf: ANSI Escape: \\e"));
lbuf[lpos++] = (CONTROL_TAG | ((Uint32) ch));
} else if (ch == '\n' || ch == '\r') {
- write_buf(lbuf + buffpos, lpos - buffpos);
+ write_buf(lbuf + buffpos, lpos - buffpos, 1);
outc('\r');
if (ch == '\n')
outc('\n');
@@ -1128,7 +1128,7 @@ static int insert_buf(byte *s, int n)
* occur normally.
*/
-static int write_buf(Uint32 *s, int n)
+static int write_buf(Uint32 *s, int n, int next_char_is_crnl)
{
byte ubuf[4];
int ubytes = 0, i;
@@ -1136,6 +1136,8 @@ static int write_buf(Uint32 *s, int n)
update_cols();
+ DEBUGLOG(("write_buf(%d, %d)",n,next_char_is_crnl));
+
while (n > 0) {
if (!(*s & TAG_MASK) ) {
if (utf8_mode) {
@@ -1199,9 +1201,22 @@ static int write_buf(Uint32 *s, int n)
--s;
}
}
- /* Check landed in first column of new line and have 'xn' bug. */
+ /* Check landed in first column of new line and have 'xn' bug.
+ * https://www.gnu.org/software/termutils/manual/termcap-1.3/html_node/termcap_27.html
+ *
+ * The 'xn' bugs (from what I understand) is that the terminal cursor does
+ * not wrap to the next line when the current line is full. For example:
+ *
+ * If the terminal column size is 20 and we output 20 'a' the cursor will be
+ * on row 1, column 21. While we actually want it at row 2 column 0. So to
+ * achieve this the code below emits " \b", which will move the cursor to the
+ * correct place.
+ *
+ * We should not apply this 'xn' workaround if we know that the next character
+ * to be emitted is a cr|nl as that will wrap by itself.
+ */
n = s - lbuf;
- if (xn && n != 0 && COL(cp_pos_to_col(n)) == 0) {
+ if (!next_char_is_crnl && xn && n != 0 && COL(cp_pos_to_col(n)) == 0) {
if (n >= llen) {
outc(' ');
} else if (lastput == 0) { /* A multibyte UTF8 character */
@@ -1546,7 +1561,7 @@ static int tty_reset(int fd) /* of terminal device */
/*
* Signal handler to cope with signals so that we can reset the tty
- * to the orignal settings
+ * to the original settings
*/
#ifdef ERTS_NOT_USED
diff --git a/erts/emulator/drivers/win32/ttsl_drv.c b/erts/emulator/drivers/win32/ttsl_drv.c
index 8d59682766..8917e48919 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -489,7 +489,7 @@ static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT coun
if (buf[0] == OP_PUTC_SYNC) {
/* On windows we do a blocking write to the tty so we just
- send the ack immidiately. If at some point in the future
+ send the ack immediately. If at some point in the future
someone has a problem with tty output being blocking
this has to be changed. */
ErlDrvTermData spec[] = {
@@ -568,7 +568,7 @@ static int put_chars(byte *s, int l)
}
/*
- * Move the current postition forwards or backwards within the current
+ * Move the current position forwards or backwards within the current
* line. We know about padding.
*/
static int move_rel(int n)
diff --git a/erts/emulator/drivers/win32/win_con.c b/erts/emulator/drivers/win32/win_con.c
index e0bc1fde05..2e3c12dc58 100644
--- a/erts/emulator/drivers/win32/win_con.c
+++ b/erts/emulator/drivers/win32/win_con.c
@@ -1903,7 +1903,7 @@ void LogFileWrite(TCHAR *buf, int num_chars)
to = *((int *)buf);
buf += (sizeof(int)/sizeof(TCHAR))-1;
num_chars -= 2 * (sizeof(int)/sizeof(TCHAR));
- // Wont seek in Unicode file, sorry...
+ // Won't seek in Unicode file, sorry...
// fseek(logfile,to-from *sizeof(TCHAR),SEEK_CUR);
break;
default:
diff --git a/erts/emulator/internal_doc/AutomaticYieldingOfCCode.md b/erts/emulator/internal_doc/AutomaticYieldingOfCCode.md
index 1497c95642..9ee24595d8 100644
--- a/erts/emulator/internal_doc/AutomaticYieldingOfCCode.md
+++ b/erts/emulator/internal_doc/AutomaticYieldingOfCCode.md
@@ -50,7 +50,7 @@ The source code of YCF is included in the folder
the Erlang/OTP system. The documentation of YCF can be found in
`"$ERL_TOP"/erts/lib_src/yielding_c_fun/README.md`. A rendered version
of YCF documentation can be found
-[here](https://github.com/erlang/otp/erts/lib_src/yielding_c_fun/README.md).
+[here](https://github.com/erlang/otp/blob/master/erts/lib_src/yielding_c_fun/README.md).
Yielding C Fun in the Erlang Run-time System
-------------------------------------------
@@ -69,7 +69,7 @@ Best Practices for YCF in the ERTS
First of all, before starting to use YCF it is recommended to read
through its documentation in
-[erts/lib_src/yielding_c_fun/README.md](https://github.com/erlang/otp/erts/lib_src/yielding_c_fun/README.md)
+[erts/lib_src/yielding_c_fun/README.md](https://github.com/erlang/otp/blob/master/erts/lib_src/yielding_c_fun/README.md)
to understand what limitations and functionalities YCF has.
### Mark YCF Transformed Functions
@@ -114,7 +114,7 @@ If a function `F1` that is transformed by one YCF invocation depends
on a function `F2` that is transformed by another YCF invocation, one
needs to tell YCF that `F2` is an YCF transformed function so that
`F1` can call the transformed version (see the documentation of
-`-fexternal` in [YCF's documentation](https://github.com/erlang/otp/erts/lib_src/yielding_c_fun/README.md)
+`-fexternal` in [YCF's documentation](https://github.com/erlang/otp/blob/master/erts/lib_src/yielding_c_fun/README.md)
for more information about how to do that).
diff --git a/erts/emulator/internal_doc/BeamAsm.md b/erts/emulator/internal_doc/BeamAsm.md
index 3b4ac619ce..351b908296 100644
--- a/erts/emulator/internal_doc/BeamAsm.md
+++ b/erts/emulator/internal_doc/BeamAsm.md
@@ -1,10 +1,11 @@
# BeamAsm, the Erlang JIT
BeamAsm provides load-time conversion of Erlang BEAM instructions into
-native code on x86-64. This allows the loader to eliminate any instruction
-dispatching overhead and also specialize each instruction on their argument types.
+native code on x86-64 and aarch64. This allows the loader to eliminate any
+instruction dispatching overhead and also specialize each instruction on their
+argument types.
-BeamAsm does hardly any cross instruction optimizations and the x and y
+BeamAsm does hardly any cross instruction optimizations and the `x` and `y`
register arrays work the same as when interpreting BEAM instructions.
This allows the Erlang run-time system to be largely unchanged except for
places that need to work with loaded BEAM instructions like code loading,
@@ -14,7 +15,8 @@ BeamAsm uses [asmjit](https://github.com/asmjit/asmjit) to generate native code
in run-time. Only small parts of the
[Assembler API](https://asmjit.com/doc/group__asmjit__assembler.html) of
[asmjit](https://github.com/asmjit/asmjit) is used. At the moment
-[asmjit](https://github.com/asmjit/asmjit) only supports x86 32/64 bit assembler.
+[asmjit](https://github.com/asmjit/asmjit) only supports x86 32/64 bit and
+aarch64 assembler.
## Loading Code
@@ -25,12 +27,12 @@ used in BeamAsm are much simpler than the interpreter's, as most of the
transformations for the interpreter are done only to eliminate the instruction
dispatch overhead.
-Then each instruction is encoded using the C++ functions in the jit/instr_*.cpp files.
-Example:
+Then each instruction is encoded using the C++ functions in the
+`jit/$ARCH/instr_*.cpp` files. For example:
void BeamModuleAssembler::emit_is_nonempty_list(const ArgVal &Fail, const ArgVal &Src) {
a.test(getArgRef(Src), imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- a.jne(labels[Fail.getValue()]);
+ a.jne(labels[Fail.getLabel()]);
}
[asmjit](https://github.com/asmjit/asmjit) provides a fairly straightforward
@@ -44,11 +46,14 @@ common patterns.
The original register allocation done by the Erlang compiler is used to manage the
liveness of values and the physical registers are statically allocated to keep
-the necessary process state. At the moment this is the static register allocation:
+the necessary process state. At the moment this is the static register
+allocation on x86-64:
rbx: ErtsSchedulerRegisters struct (contains x/float registers and some metadata)
- rbp: Active code index
- r12: Optional Save slot for the Erlang stack pointer when executing C code
+ rbp: Current frame pointer when `perf` support is enabled, otherwise this
+ is an optional save slot for the Erlang stack pointer when executing C
+ code.
+ r12: Active code index
r13: Current running process
r14: Remaining reductions
r15: Erlang heap pointer
@@ -82,13 +87,12 @@ For instance, the return instruction looks something like this:
Label yield = a.newLabel();
- a.dec(FCALLS); /* Decrement reduction counter */
- a.jl(dispatch_return); /* Check if we should yield */
+ /* Decrement reduction counter */
+ a.dec(FCALLS);
+ /* If FCALLS < 0, jump to the yield-on-return fragment */
+ a.jl(resolve_fragment(ga->get_dispatch_return()));
a.ret();
- a.bind(yield);
- abs_jmp(ga->get_dispatch_return());
-
The code above is not exactly what is emitted, but close enough. The thing to note
is that the code for doing the context switch is never emitted. Instead, we jump
to a global fragment that all return instructions share. This greatly reduces
@@ -132,6 +136,23 @@ handlers even when we lack a stack frame. This is merely a reservation and has
no effect on how the stack works, and all values stored there must be valid
Erlang terms in case of a garbage collection.
+## Frame pointers
+
+To aid debuggers and sampling profilers, we support running Erlang code with
+native frame pointers. At the time of writing, this is only enabled together
+with `perf` support (`+JPperf true`) to save stack space, but we may add a flag
+to explicitly enable it in the future.
+
+When enabled, continuation pointers (CP) have both a return address _and_ a
+frame pointer that points at the previous CP. CPs must form a valid chain at
+all times, and it's illegal to have "half" a CP when the stack is inspected.
+
+Frame pointers are pushed when entering an Erlang function and popped before
+leaving it, including on tail calls as the callee will immediately push the
+frame pointer on entry. This has a slight overhead but saves us the headache of
+having multiple entry points for each function depending on whether it's tail-
+or body-called, which would get very tricky once breakpoints enter the picture.
+
## Running C code
As Erlang stacks can be very small, we have to switch over to a different stack
@@ -163,39 +184,31 @@ All combinations of the `Update` constants are legal, but the ones given to
## Tracing and NIF Loading
To make tracing and NIF loading work there needs to be a way to intercept
-any function call. In the interpreter, this is done by rewriting the loaded BEAM code,
-but this is more complicated in BeamAsm as we want to have a fast and compact way to
-do this. This is solved by emitting the code below at the start of each function:
+any function call. In the interpreter, this is done by rewriting the loaded
+BEAM code, but this is more complicated in BeamAsm as we want to have a fast
+and compact way to do this. This is solved by emitting the code below at the
+start of each function (x86 variant below):
- 0x0: jmp 6
- 0x2: ERTS_ASM_BP_FLAG_NONE
- 0x3: relative near call
- 0x4: &genericBPTramp
- 0x8: actual code for the function
+ 0x0: short jmp 6 (address 0x8)
+ 0x2: nop
+ 0x3: relative near call to shared breakpoint fragment
+ 0x8: actual code for function
-When code starts to execute it will simply see the `jmp 6` instruction
+When code starts to execute it will simply see the `short jmp 6` instruction
which skips the prologue and starts to execute the code directly.
-When we want to enable a certain break point we set the `jmp` target to
-be 1 (which means it will land on the call instruction) and will call
-genericBPTramp. genericBPTramp is a label at the top of each module
-that contains [trampolines][1] for all flag combinations.
+When we want to enable a certain breakpoint we set the jmp target to be 1,
+which means it will land on the call to the shared breakpoint fragment. This
+fragment checks the current `breakpoint_flag` stored in the ErtsCodeInfo of
+this function, and then calls `erts_call_nif_early` and
+`erts_generic_breakpoint` accordingly.
-[1]: https://en.wikipedia.org/wiki/Trampoline_(computing)
+Note that the update of the branch and `breakpoint_flag` does not need to be
+atomic: it's fine if a process only sees one of these being updated, as the
+code that sets breakpoints/loads NIFs doesn't rely on the trampoline being
+active until thread progress has been made.
- genericBPTramp:
-
- 0x0: ret
- 0x10: jmp call_nif_early
- 0x20: call generic_bp_local
- 0x30: call generic_bp_local
- 0x35: jmp call_nif_early
-
-Note that each target is 16 byte aligned. This is because the call target
-in the function prologue is updated to target the correct place when a flag
-is updated. So if CALL\_NIF\_EARLY is set, then it is updated to be
-genericBPTramp + 0x10. If BP is set, it is updated to genericBPTramp + 0x20
-and the combination makes it to be genericBPTramp + 0x30.
+The solution for AArch64 is similar.
### Updating code
@@ -209,16 +222,17 @@ The `erts_writable_code_ptr` function can be used to get writable pointers,
given a module instance:
for (i = 0; i < n; ++i) {
- ErtsCodeInfo* ci;
+ const ErtsCodeInfo* ci_exec;
+ ErtsCodeInfo* ci_rw;
void *w_ptr;
- w_ptr = erts_writable_code_ptr(&modp->curr,
- code_hdr->functions[i]);
- ci = (ErtsCodeInfo*)w_ptr;
+ ci_exec = code_hdr->functions[i];
+ w_ptr = erts_writable_code_ptr(&modp->curr, ci_exec);
+ ci_rw = (ErtsCodeInfo*)w_ptr;
- uninstall_breakpoint(ci);
- consolidate_bp_data(modp, ci, 1);
- ASSERT(ci->u.gen_bp == NULL);
+ uninstall_breakpoint(ci_rw, ci_exec);
+ consolidate_bp_data(modp, ci_rw, 1);
+ ASSERT(ci_rw->gen_bp == NULL);
}
Without the module instance there's no reliable way to figure out the writable
@@ -238,11 +252,11 @@ means that all remote calls _must_ place the export entry in said register,
even when we don't know beforehand that the call is remote, such as when
calling a fun.
-This is pretty easy to do in assembler and the `emit_setup_export_call` helper
-handles it nicely for us, but we can't set registers when trapping out from C
-code. When trapping to an export entry from C code one must set `c_p->current`
-to the `ErtsCodeMFA` inside the export entry in question, and then set `c_p->i`
-to `beam_bif_export_trap`.
+This is pretty easy to do in assembler and the `emit_setup_dispatchable_call`
+helper handles it nicely for us, but we can't set registers when trapping out
+from C code. When trapping to an export entry from C code one must set
+`c_p->current` to the `ErtsCodeMFA` inside the export entry in question, and
+then set `c_p->i` to `beam_bif_export_trap`.
The `BIF_TRAP` macros handle this for you, so you generally don't need to
think about it.
@@ -254,29 +268,31 @@ think about it.
The BeamAsm implementation resides in the `$ERL_TOP/erts/emulator/beam/jit` folder.
The files are:
-* `load.h`
- * BeamAsm specific header for loading code
* `asm_load.c`
* BeamAsm specific functions for loading code
-* `generators.tab`, `predicates.tab`, `ops.tab`
- * BeamAsm specific transformations for instructions. See [beam_makeops](beam_makeops) for
- more details.
* `beam_asm.h`
* Header file describing the C -> C++ api
-* `beam_asm.hpp`
+* `beam_jit_metadata.cpp`
+ * `gdb` and Linux `perf` support for BeamAsm
+* `load.h`
+ * BeamAsm specific header for loading code
+* `$ARCH/beam_asm.hpp`
* Header file describing the structs and classes used by BeamAsm.
-* `beam_asm.cpp`
- * Implementation of the main process loop
+* `$ARCH/beam_asm.cpp`
* The BeamAsm initialization code
* The C -> C++ interface functions.
-* `beam_asm_module.cpp`
+* `$ARCH/generators.tab`, `$ARCH/predicates.tab`, `$ARCH/ops.tab`
+ * BeamAsm specific transformations for instructions. See
+ [beam_makeops](beam_makeops) for more details.
+* `$ARCH/beam_asm_module.cpp`
* The code for the BeamAsm module code generator logic
-* `beam_asm_global.cpp`
- * Global code fragments that are used by multiple instructions, e.g. error handling code.
-* `instr_*.cpp`
+* `$ARCH/beam_asm_global.cpp`
+ * Global code fragments that are used by multiple instructions, e.g. error
+ handling code.
+* `$ARCH/instr_*.cpp`
* Implementation of individual instructions grouped into files by area
-* `beam_asm_perf.cpp`
- * The linux perf support for BeamAsm
+* `$ARCH/process_main.cpp`
+ * Implementation of the main process loop
## Linux perf support
@@ -288,14 +304,18 @@ You can run perf on BeamAsm like this:
perf record erl +JPperf true
-and then look at the results using `perf report` as you normally would with perf.
+and then look at the results using `perf report` as you normally would with
+perf.
+
+Frame pointers are enabled when the `+JPperf true` option is passed, so you can
+use `perf record --call-graph=fp` to get more context. This will give you
+accurate call graphs for pure Erlang code, but in rare cases it fails to track
+transitions from Erlang to C code and back. [`perf record --call-graph=lbr`](https://lwn.net/Articles/680985/)
+may work better in those cases, but it's worse at tracking in general.
-If you want to get some context to you calls you cann use the [lbr](https://lwn.net/Articles/680985/)
-call-graph option to `perf record`. Using `lbr` is not perfect (for instance you
-do not get any syscalls in the context), but it work well enough.
For example, you can run perf to analyze dialyzer building a PLT like this:
- ERL_FLAGS="+JPperf true +S 1" perf record --call-graph lbr \
+ ERL_FLAGS="+JPperf true +S 1" perf record --call-graph=fp \
dialyzer --build_plt -Wunknown --apps compiler crypto erts kernel stdlib \
syntax_tools asn1 edoc et ftp inets mnesia observer public_key \
sasl runtime_tools snmp ssl tftp wx xmerl tools
@@ -315,10 +335,10 @@ By expanding it and looking at its parents we can see that it is the function
at it in the source code to see if you can figure out why so much time is spent there.
After `eq` we see the function `erl_types:t_has_var/1` where we spend almost
-6% of the entire execution in. A while further down you can see `copy_struct` which
-is the function used to copy terms. If we expand it to view the parents we find that
-it is mostly `ets:lookup_element/3` that contributes to this time via the Erlang
-function `dialyzer_plt:ets_table_lookup/2`.
+5% of the entire execution in. A while further down you can see `copy_struct_x`
+which is the function used to copy terms. If we expand it to view the parents
+we find that it is mostly `ets:lookup_element/3` that contributes to this time
+via the Erlang function `dialyzer_plt:ets_table_lookup/2`.
### Flame Graph
@@ -328,12 +348,12 @@ be more easily shared with others and manipulated to give a graph tailor-made fo
your needs. For instance, if we run dialyzer with all schedulers:
## Run dialyzer with multiple schedulers
- ERL_FLAGS="+JPperf true" perf record --call-graph lbr \
+ ERL_FLAGS="+JPperf true" perf record --call-graph=fp \
dialyzer --build_plt -Wunknown --apps compiler crypto erts kernel stdlib \
syntax_tools asn1 edoc et ftp inets mnesia observer public_key \
sasl runtime_tools snmp ssl tftp wx xmerl tools --statistics
-And then use the scripts found at Brendan Gregg's [CPU Flame Graphs](http://www.brendangregg.com/FlameGraphs/cpuflamegraphs)
+And then use the scripts found at Brendan Gregg's [CPU Flame Graphs](https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html)
web page as follows:
## Collect the results
@@ -367,12 +387,12 @@ you what you want.
### Annotate perf functions
-If you want to be able to use the `perf annotate` functionality (and in extention
+If you want to be able to use the `perf annotate` functionality (and in extension
the annotate functionality in the `perf report` gui) you need to use a monotonic
clock when calling `perf record`, i.e. `perf record -k mono`. So for a dialyzer
run you would do this:
- ERL_FLAGS="+JPperf true +S 1" perf record -k mono --call-graph lbr \
+ ERL_FLAGS="+JPperf true +S 1" perf record -k mono --call-graph=fp \
dialyzer --build_plt -Wunknown --apps compiler crypto erts kernel stdlib \
syntax_tools asn1 edoc et ftp inets mnesia observer public_key \
sasl runtime_tools snmp ssl tftp wx xmerl tools
@@ -390,6 +410,10 @@ or by pressing `a` in the `perf report` ui. Then you get something like this:
![Linux Perf FlameGraph: dialyzer PLT build](figures/beamasm-perf-annotate.png)
+`perf annotate` will interleave the listing with the original source code
+whenever possible. You can use the `+{source,Filename}` or `+absolute_paths`
+compiler options to tell `perf` where to find the source code.
+
> *WARNING*: Calling `perf inject --jit` will create a lot of files in `/tmp/`
> and in `~/.debug/tmp/`. So make sure to cleanup in those directories from time to
> time or you may run out of inodes.
@@ -420,11 +444,11 @@ we have found useful:
You will see a banner containing `[jit]` shell when you start. You can also use
`erlang:system_info(emu_flavor)` to check the flavor and it should be `jit`.
-There are three major reasons why when building Erlang/OTP you would not get the JIT.
+There are two major reasons why when building Erlang/OTP you would not get the
+JIT.
-* You are not building x86 64-bit
+* You are not building a 64-bit emulator for x86 or ARM
* You do not have a C++ compiler that supports C++-17
-* You do not have an OS that supports executable *and* writable memory
If you run `./configure --enable-jit` configure will abort when it discovers that
your system cannot build the JIT.
@@ -448,29 +472,24 @@ when that happens. One such could be very short-lived small scripts. If you come
any scenarios when this happens, please open a bug report at
[the Erlang/OTP bug tracker](https://github.com/erlang/otp/issues).
-### Would it be possible to add support for BeamAsm on ARM?
+### Would it be possible to add support for BeamAsm on other CPU architectures?
Any new architecture needs support in the assembler as well. Since we use
[asmjit](https://github.com/asmjit/asmjit) for this, that means we need support
in [asmjit](https://github.com/asmjit/asmjit). BeamAsm uses relatively few
-instructions (mostly, `mov`, `jmp`, `cmp`, `sub`, `add`), so it would not need to have
-full support of all ARM instructions.
+instructions (mostly, `mov`, `jmp`, `cmp`, `sub`, `add`), so it would not need
+to have full support of all instructions.
Another approach would be to not use [asmjit](https://github.com/asmjit/asmjit)
-for ARM, but instead, use something different to assemble code during load-time.
+for the new architecture, but instead use something different to assemble code
+during load-time.
### Would it be possible to add support for BeamAsm on another OS?
-Adding a new OS that runs x86-64 should not need any large changes if
-the OS supports mapping of memory as executable. If the ABI used by the
+Adding a new OS that runs x86-64 or aarch64 should not need any large changes
+if the OS supports mapping of memory as executable. If the ABI used by the
OS is not supported changes related to calling C-functions also have to
be made.
-As a reference, it took us about 2-3 weeks to implement support for Windows.
-
-### Would it be possible to add support in perf to better crawl the Erlang stack?
-
-Yes, though not easily.
-
-Using `perf --call-graph lbr` works for Erlang, but it does not give a
-perfect record as the buffer has a limited size.
+As a reference, it took us about 2-3 weeks to implement support for Windows,
+and about three months to finish the aarch64 port.
diff --git a/erts/emulator/internal_doc/CodeLoading.md b/erts/emulator/internal_doc/CodeLoading.md
index cfdc1bf30a..fa5bba0643 100644
--- a/erts/emulator/internal_doc/CodeLoading.md
+++ b/erts/emulator/internal_doc/CodeLoading.md
@@ -56,7 +56,7 @@ different modules and returns a "magic binary" containing the internal
state of each prepared module. Function `finish_loading` could take a
list of such states and do the finishing of all of them in one go.
-Currenlty we use the legacy BIF `erlang:load_module` which is now
+Currently we use the legacy BIF `erlang:load_module` which is now
implemented in Erlang by calling the above two functions in
sequence. Function `finish_loading` is limited to only accepts a list
with one module state as we do not yet use the multi module loading
diff --git a/erts/emulator/internal_doc/DelayedDealloc.md b/erts/emulator/internal_doc/DelayedDealloc.md
index 4b7c774141..8a86a70b10 100644
--- a/erts/emulator/internal_doc/DelayedDealloc.md
+++ b/erts/emulator/internal_doc/DelayedDealloc.md
@@ -89,7 +89,7 @@ same location in memory.
The head contains pointers to beginning of the list (`head.first`), and
to the first block which other threads may refer to
-(`head.unref_end`). Blocks between these pointers are only refered to
+(`head.unref_end`). Blocks between these pointers are only referred to
by the head part of the data structure which is only used by the
thread owning the allocator instance. When these two pointers are not
equal the thread owning the allocator instance deallocate block after
@@ -137,7 +137,7 @@ If no new memory blocks are inserted into the list, it should
eventually be emptied. All pointers to the list however expect to
always point to something. This is solved by inserting an empty
"marker" element, which only has to purpose of being there in the
-absense of other elements. That is when the list is empty it only
+absence of other elements. That is when the list is empty it only
contains this "marker" element.
### Contention ###
diff --git a/erts/emulator/internal_doc/GarbageCollection.md b/erts/emulator/internal_doc/GarbageCollection.md
index a1627b3233..ae8602bd68 100644
--- a/erts/emulator/internal_doc/GarbageCollection.md
+++ b/erts/emulator/internal_doc/GarbageCollection.md
@@ -35,7 +35,7 @@ Compiling this code to beam assembly (`erlc -S`) shows exactly what is happening
Looking at the assembler code we can see three things: The heap requirement in this function turns out to be only six words, as seen by the `{test_heap,6,1}` instruction. All the allocations are combined to a single instruction. The bulk of the data `{text, "hello world!"}` is a *literal*. Literals, sometimes referred to as constants, are not allocated in the function since they are a part of the module and allocated at load time.
-If there is not enough space available on the heap to satisfy the `test_heap` instructions request for memory, then a garbage collection is initiated. It may happen immediately in the `test_heap` instruction, or it can be delayed until a later time depending on what state the process is in. If the garbage collection is delayed, any memory needed will be allocated in heap fragments. Heap fragments are extra memory blocks that are a part of the young heap, but are not allocated in the contigious area where terms normally reside. See [The young heap](#the-young-heap) for more details.
+If there is not enough space available on the heap to satisfy the `test_heap` instructions request for memory, then a garbage collection is initiated. It may happen immediately in the `test_heap` instruction, or it can be delayed until a later time depending on what state the process is in. If the garbage collection is delayed, any memory needed will be allocated in heap fragments. Heap fragments are extra memory blocks that are a part of the young heap, but are not allocated in the contiguous area where terms normally reside. See [The young heap](#the-young-heap) for more details.
### The collector
@@ -171,7 +171,7 @@ There are a bunch of different tradeoffs that come into play when trying to figu
Using `off_heap` may seem like a nice way to get a more scalable system as you get very little contention on the main locks, however, allocating a heap fragment is more expensive than allocating on the heap of the receiving process. So if it is very unlikely that contention will occur, it is more efficient to try to allocate the message directly on the receiving process' heap.
-Using `on_heap` will force all messages to be part of on the young heap which will increase the amount of data that the garbage collector has to move. So if a garbage collection is triggered while processing a large amount of messages, they will be copied to the young heap. This in turn will lead to that the messages will quickly be promoted to the old heap and thus increase its size. This may be good or bad depending on exactly what the process does. A large old heap means that the young heap will also be larger, which in turn means that less garbage collections will be triggered while processing the message queue. This will temporarly increase the throughput of the process at the cost of more memory usage. However, if after all the messages have been consumed the process enters a state where a lot less messages are being received. Then it may be a long time before the next fullsweep garbage collection happens and the messages that are on the old heap will be there until that happens. So while `on_heap` is potentially faster than the other modes, it uses more memory for a longer time. This mode is the legacy mode which is almost how the message queue was handled before Erlang/OTP 19.0.
+Using `on_heap` will force all messages to be part of on the young heap which will increase the amount of data that the garbage collector has to move. So if a garbage collection is triggered while processing a large amount of messages, they will be copied to the young heap. This in turn will lead to that the messages will quickly be promoted to the old heap and thus increase its size. This may be good or bad depending on exactly what the process does. A large old heap means that the young heap will also be larger, which in turn means that less garbage collections will be triggered while processing the message queue. This will temporarily increase the throughput of the process at the cost of more memory usage. However, if after all the messages have been consumed the process enters a state where a lot less messages are being received. Then it may be a long time before the next fullsweep garbage collection happens and the messages that are on the old heap will be there until that happens. So while `on_heap` is potentially faster than the other modes, it uses more memory for a longer time. This mode is the legacy mode which is almost how the message queue was handled before Erlang/OTP 19.0.
Which one of these strategies is best depends a lot on what the process is doing and how it interacts with other processes. So, as always, profile the application and see how it behaves with the different options.
diff --git a/erts/emulator/internal_doc/PTables.md b/erts/emulator/internal_doc/PTables.md
index ef61963a40..6b316eaa7e 100644
--- a/erts/emulator/internal_doc/PTables.md
+++ b/erts/emulator/internal_doc/PTables.md
@@ -113,7 +113,7 @@ the "thread progress" functionality in order to determine when it is
safe to deallocate the process structure. We'll get back to this when
describing deletion in the table.
-Using this new lookup approach we wont modify any memory at all which
+Using this new lookup approach we won't modify any memory at all which
is important. A lookup conceptually only read memory, now this is true
in the implementation also which is important from a scalability
perspective. The previous implementation modified the cache line
@@ -282,7 +282,7 @@ single cache line containing the state of the rwlock even in the case
we are only read locking. Instead of using such an rwlock, we have our
own implementation of reader optimized rwlocks which keeps track of
reader threads in separate thread specific cache lines. This in order
-to avoid contention on a singe cache line. As long as we only do read
+to avoid contention on a single cache line. As long as we only do read
lock operations, threads only need to read a global cache line and
modify its own cache line, and by this minimize communication between
involved processors. The iterating BIFs are normally very infrequently
@@ -299,7 +299,7 @@ threads modify the table at the same time as we are trying to find the
slot. The easy fix is to abort the operation if an empty slot could
not be found in a finite number operation, and then restart the
operation under a write lock. This will be implemented in next
-release, but furter work should be made trying to find a better
+release, but further work should be made trying to find a better
solution.
This and also previous implementation do not work well when the table
@@ -320,7 +320,7 @@ not require exclusive access to the table while reading a sequence of
slots. In principle this should be rather easy, the code can handle
sequences of variable sizes, so shrinking the sequence size of slots
to one would solv the problem. This will, however, need some tweeks
-and modifications of not trival code, but is something that should be
+and modifications of not trivial code, but is something that should be
looked at in the future.
By increasing the size of identifiers, at least on 64-bit machines
diff --git a/erts/emulator/internal_doc/PortSignals.md b/erts/emulator/internal_doc/PortSignals.md
index 8782ae4e17..f2490152ca 100644
--- a/erts/emulator/internal_doc/PortSignals.md
+++ b/erts/emulator/internal_doc/PortSignals.md
@@ -108,7 +108,7 @@ and a private, lock free, queue like, task data structure. This "semi
locked" approach is similar to how the message boxes of processes are
managed. The lock is port specific and only used for protection of
port tasks, so the run queue lock is now needed in more or less the
-same way for ports as for processes. This ensures that we wont see an
+same way for ports as for processes. This ensures that we won't see an
increased lock contention on run queue locks due to this rewrite of
the port functionality.
@@ -211,7 +211,7 @@ consuming, and did not really depend on the port. That is we would
like to do this without having the port lock locked.
In order to improve this, state information was re-organized in the
-port structer, so that we can access it using atomic memory
+port structure, so that we can access it using atomic memory
operations. This together with the new port table implementation,
enabled us to lookup the port and inspect the state before acquiring
the port lock, which in turn made it possible to perform preparations
diff --git a/erts/emulator/internal_doc/SuperCarrier.md b/erts/emulator/internal_doc/SuperCarrier.md
index f52c6613d5..55ac5a67af 100644
--- a/erts/emulator/internal_doc/SuperCarrier.md
+++ b/erts/emulator/internal_doc/SuperCarrier.md
@@ -12,7 +12,7 @@ Problem
-------
The initial motivation for this feature was customers asking for a way
-to pre-allocate physcial memory at VM start for it to use.
+to pre-allocate physical memory at VM start for it to use.
Other problems were different experienced limitations of the OS
implementation of mmap:
@@ -29,7 +29,7 @@ fragmentation increased.
Solution
--------
-Allocate one large continious area of address space at VM start and
+Allocate one large continuous area of address space at VM start and
then use that area to satisfy our dynamic memory need during
runtime. In other words: implement our own mmap.
@@ -70,7 +70,7 @@ name suggest that it can be viewed as our own mmap implementation.
A super carrier needs to satisfy two slightly different kinds of
allocation requests; multi block carriers (MBC) and single block
-carriers (SBC). They are both rather large blocks of continious
+carriers (SBC). They are both rather large blocks of continuous
memory, but MBCs and SBCs have different demands on alignment and
size.
@@ -79,13 +79,13 @@ alignment.
MBCs are more restricted. They can only have a number of fixed
sizes that are powers of 2. The start address need to have a very
-large aligment (currently 256 kb, called "super alignment"). This is a
+large alignment (currently 256 kb, called "super alignment"). This is a
design choice that allows very low overhead per allocated block in the
MBC.
To reduce fragmentation within the super carrier, it is good to keep SBCs
and MBCs apart. MBCs with their uniform alignment and sizes can be
-packed very efficiently together. SBCs without demand for aligment can
+packed very efficiently together. SBCs without demand for alignment can
also be allocated quite efficiently together. But mixing them can lead
to a lot of memory wasted when we need to create large holes of
padding to the next alignment limit.
@@ -102,9 +102,9 @@ The MBC area is called *sa* as in super aligned and the SBC area is
called *sua* as in super un-aligned.
Note that the "super" in super alignment and the "super" in super
-carrier has nothing to do with each other. We could have choosen
+carrier has nothing to do with each other. We could have chosen
another naming to avoid confusion, such as "meta" carrier or "giant"
-aligment.
+alignment.
+-------+ <---- sua.top
| sua |
diff --git a/erts/emulator/internal_doc/ThreadProgress.md b/erts/emulator/internal_doc/ThreadProgress.md
index 03a802f904..a48b250104 100644
--- a/erts/emulator/internal_doc/ThreadProgress.md
+++ b/erts/emulator/internal_doc/ThreadProgress.md
@@ -78,7 +78,7 @@ thread progress operation has been initiated, and at least once
ordered using communication via memory which makes it possible to draw
conclusion about the memory state after the thread progress operation
has completed. Lets call the progress made from initiation to
-comletion for "thread progress".
+completion for "thread progress".
Assuming that the thread progress functionality is efficient, a lot of
algorithms can both be simplified and made more efficient than using
@@ -120,7 +120,7 @@ communication.
We also want threads to be able to determine when thread progress has
been made relatively fast. That is we need to have some balance
-between comunication overhead and time to complete the operation.
+between communication overhead and time to complete the operation.
### API ###
@@ -222,7 +222,7 @@ current global value plus one at the time when we call
confirmed global value plus two at this time.
The above described implementation more or less minimizes the
-comunication needed before we can increment the global counter. The
+communication needed before we can increment the global counter. The
amount of communication in the system due to the thread progress
functionality however also depend on the frequency with which managed
threads call `erts_thr_progress_update()`. Today each scheduler thread
diff --git a/erts/emulator/internal_doc/Tracing.md b/erts/emulator/internal_doc/Tracing.md
index 196ae0dd4e..f0182daad8 100644
--- a/erts/emulator/internal_doc/Tracing.md
+++ b/erts/emulator/internal_doc/Tracing.md
@@ -1,8 +1,64 @@
-Non-blocking trace setting
-==========================
-
-Introduction
-------------
+# Tracing
+
+## Implementation
+### Call, return, and exception tracing
+
+Tracing is implemented by setting breakpoints in the traced functions,
+and sending the appropriate trace messages when they're hit.
+
+* Call trace messages are sent immediately.
+* Return tracing pushes a frame to the stack which _returns to_ an
+ instruction that sends a trace message when encountered.
+* Exception tracing also pushes a frame to the stack, but will only send
+ a trace message if we encounter it in stack scanning while throwing an
+ exception.
+
+This means that one must be careful not to use return or exception tracing
+on functions that never return, as each call pushes a frame that will
+never be removed.
+
+Another limitation is that since the breakpoint is in the _callee_ and not
+the _caller_, we're limited to the information we have on function ingress.
+This means that we can't actually tell who called us: since we're limited
+to inspecting the stack we can only say where we're _going to return to_,
+which is not quite the same thing.
+
+As an illustration, when the `caller` option is enabled all trace messages
+from `bar/1` will say that they were called from `foo/0`, even though it
+went through a bunch of other functions on the way:
+
+ foo() ->
+ lots(),
+ ok.
+
+ lots() ->
+ 'of'().
+
+ 'of'() ->
+ indirections().
+
+ indirections() ->
+ bar(10).
+
+ bar(0) ->
+ done;
+ bar(N) ->
+ bar(N - 1).
+
+### Export tracing
+
+In the interpreter, breakpoints are set inside the code trampoline for
+export entries, and their address vector is updated to point to them.
+This way, only remote calls will hit the breakpoint while local calls to
+the same function are left alone, but it otherwise acts the same way as
+local breakpoints.
+
+Things get a bit more involved in the JIT. See `BeamAsm.md` for more
+details.
+
+## Setting breakpoints
+
+### Introduction
Before OTP R16 when trace settings were changed by `erlang:trace_pattern`,
all other execution in the VM were halted while the trace operation
@@ -10,15 +66,13 @@ was carried out in single threaded mode. Similar to code loading, this
can impose a severe problem for availability that grows with the
number of cores.
-In OTP R16, trace breakpoints are set in the code without blocking the
-VM. Erlang processes may continue executing undisturbed in parallel
-during the entire operation. The same base technique is used as for
-code loading. A staging area of breakpoints is prepared and then made
-active with a single atomic operation.
-
+In OTP R16, breakpoints are set in the code without blocking the VM.
+Erlang processes may continue executing undisturbed in parallel during the
+entire operation. The same base technique is used as for code loading. A
+staging area of breakpoints is prepared and then made active with a single
+atomic operation.
-Redesign of Breakpoint Wheel
-----------------------------
+### Redesign of Breakpoint Wheel
To make it easier to manage breakpoints without single threaded mode a
redesign of the breakpoint mechanism has been made. The old
@@ -34,9 +88,7 @@ one struct (`GenericBp`) to hold the data for all types of breakpoints
for each instrumented function. A bit-flag field is used to indicate
what different type of break actions that are enabled.
-
-Same Same but Different
------------------------
+### Same Same but Different
Even though `trace_pattern` use the same technique as the non-blocking
code loading with replicated generations of data structures and an
@@ -54,8 +106,8 @@ instantaneously without the need of external function calls.
The chosen solution is instead for tracing to use the technique of
replication applied on the data structures for breakpoints. Two
-generations of breakpoints are kept and indentified by index of 0 and
-1. The global atomic variables `erts_active_bp_index` will determine
+generations of breakpoints are kept and identified by index of 0 and
+1\. The global atomic variables `erts_active_bp_index` will determine
which generation of breakpoints running code will use.
### Atomicity Without Atomic Operations
@@ -70,9 +122,7 @@ guarantee we need is that the written instruction word is seen as
atomic. Either fully written or not at all. This is true for word
aligned write operation on all hardware architectures we use.
-
-Adding a new Breakpoint
------------------------
+### Adding a new Breakpoint
This is a simplified sequence describing what `trace_pattern` goes
through when adding a new breakpoint.
@@ -83,8 +133,8 @@ through when adding a new breakpoint.
Set the active part as disabled with a zeroed flagfield. Save the original
instruction word in the breakpoint.
-3. Write a pointer to the breakpoint at offset -4 from the first
- instruction "func\_info" header.
+3. Write a pointer to the breakpoint at offset `-sizeof(UWord)` from the first
+ instruction `ErtsFuncInfo` header.
4. Set the staging part of the breakpoint as enabled with specified
breakpoint data.
@@ -92,7 +142,8 @@ through when adding a new breakpoint.
5. Wait for thread progress.
6. Write a `op_i_generic_breakpoint` as the first instruction for the function.
- This instruction will execute the breakpoint that it finds at offset -4.
+ This instruction will execute the breakpoint that it finds at offset
+ `-sizeof(UWord)`.
7. Wait for thread progress.
@@ -120,9 +171,7 @@ becomes visible they will however execute the disabled part of the
breakpoint structure and do nothing other than executing the saved
original instruction.
-
-To Updating and Remove Breakpoints
-----------------------------------
+### To Update and Remove Breakpoints
The above sequence did only describe adding a new breakpoint. We do
basically the same sequence to update the settings of an existing
@@ -141,7 +190,7 @@ and removing breakpoints.
2. Allocate new breakpoint structures with a disabled active part and
the original beam instruction. Write a pointer to the breakpoint in
- "func\_info" header at offset -4.
+ `ErtsFuncInfo` header at offset `-sizeof(UWord)`.
3. Update the staging part of all affected breakpoints. Disable
breakpoints that are to be removed.
@@ -169,7 +218,6 @@ and removing breakpoints.
13. Release code write permission and return from `trace_pattern`.
-
### All that Waiting for Thread Progress
There are four rounds of waiting for thread progress in the above
@@ -188,7 +236,7 @@ value of `erts_active_bp_index` at different times as it is read
without any memory barrier. But this is the best we can do without
more expensive thread synchronization.
-The waiting in step 8 is to make sure we dont't restore the original
+The waiting in step 8 is to make sure we don't restore the original
bream instructions for disabled breakpoints until we know that no
thread is still accessing the old enabled part of a disabled
breakpoint.
@@ -197,9 +245,7 @@ The waiting in step 10 is to make sure no lingering thread is still
accessing disabled breakpoint structures to be deallocated in step
12.
-
-Global Tracing
---------------
+### Global Tracing
Call tracing with `global` option only affects external function
calls. This was earlier handled by inserting a special trace
@@ -212,9 +258,7 @@ tracing is that we insert the `op_i_generic_breakpoint` instruction
(with its pointer at offset -4) in the export entry rather than in the
code.
-
-Future work
------------
+### Future work
We still go to single threaded mode when new code is loaded for a
module that is traced, or when loading code when there is a default
diff --git a/erts/emulator/internal_doc/beam_makeops.md b/erts/emulator/internal_doc/beam_makeops.md
index e93aeac52d..563ad200f7 100644
--- a/erts/emulator/internal_doc/beam_makeops.md
+++ b/erts/emulator/internal_doc/beam_makeops.md
@@ -77,13 +77,13 @@ following line:
64: move/2
This is a definition of an external generic BEAM instruction. Most
-importantly it specifices that the opcode is 64. It also defines that
+importantly it specifies that the opcode is 64. It also defines that
it has two operands. The BEAM assembler will use the opcode when
creating `.beam` files. The compiler does not really need the arity,
but it will use it as an internal sanity check when assembling the
BEAM code.
-Let's have a look at `ops.tab` in `erts/emulator/beam`, where the
+Let's have a look at `ops.tab` in `erts/emulator/beam/emu`, where the
specific `move` instructions are defined. Here are a few of them:
move x x
@@ -98,8 +98,8 @@ an integer, an atom, or a literal).
Now let's look at the implementation of the `move` instruction. There
are multiple files containing implementations of instructions in the
-`erts/emulator/beam` directory. The `move` instruction is defined in
-`instrs.tab`. It looks like this:
+`erts/emulator/beam/emu` directory. The `move` instruction is defined
+in `instrs.tab`. It looks like this:
move(Src, Dst) {
$Dst = $Src;
@@ -122,7 +122,7 @@ layout for the instruction `{move,{atom,id},{x,5}}`:
+--------------------+--------------------+
This example and all other examples in the document assumes a 64-bit
-archictecture, and furthermore that pointers to C code fit in 32 bits.
+architecture, and furthermore that pointers to C code fit in 32 bits.
`I` in the BEAM virtual machine is the instruction pointer. When BEAM
executes an instruction, `I` points to the first word of the
@@ -163,7 +163,7 @@ word.
the instruction word. In this example, it will return 40 which is the
byte offset for X register 5. The `xb()` macro will cast a byte
pointer to an `Eterm` pointer and dereference it. The `I[1]` on
-the right side of the `=` fetches an Erlang term (the atom `id` in
+the right-hand side of the `=` fetches an Erlang term (the atom `id` in
this case).
* `I += 2` advances the instruction pointer to the next
@@ -231,13 +231,13 @@ to a `move2` instruction:
move X1=x Y1=y | move X2=x Y2=y => move2 X1 Y1 X2 Y2
-The left side of the arrow (`=>`) is a pattern. If the pattern
+The left-hand side of the arrow (`=>`) is a pattern. If the pattern
matches, the matching instructions will be replaced by the
-instructions on the right side. Variables in a pattern must start
+instructions on the right-hand side. Variables in a pattern must start
with an uppercase letter just as in Erlang. A pattern variable may be
followed `=` and one or more type letters to constrain the match to
-one of those types. The variables that are bound on the left side can
-be used on the right side.
+one of those types. The variables that are bound on the left-hand side can
+be used on the right-hand side.
We will also need to define a specific instruction and an implementation:
@@ -258,14 +258,15 @@ it will match the new instructions against the transformation rules.
Because of that, we can define the rule for a `move3/6` instruction
as follows:
- move2 X1=x Y1=y X2=x Y2=y | move X3=x Y3=y => \
+ move2 X1=x Y1=y X2=x Y2=y | move X3=x Y3=y =>
move3 X1 Y1 X2 Y2 X3 Y3
-(A `\` before a newline can be used to break a long line for readability.)
+(For readability, a long transformation line can be broken after `|`
+and `=>` operators.)
It would also be possible to define it like this:
- move X1=x Y1=y | move X2=x Y2=y | move X3=x Y3=y => \
+ move X1=x Y1=y | move X2=x Y2=y | move X3=x Y3=y =>
move3 X1 Y1 X2 Y2 X3 Y3
but in that case it must be defined before the rule for `move2/4`
@@ -298,7 +299,7 @@ keep multiple generic instructions in a linked list.
* The loader tries to apply transformation rules against the
generic instructions in the linked list. If a rule matches, the
matched instructions will be removed and replaced with new
-generic instructions constructed from the right side of the
+generic instructions constructed from the right-hand side of the
transformation.
* If a transformation rule matched, the loader applies the
@@ -322,7 +323,7 @@ in the code area for the module being loaded.
* The loader translates each operand to a machine word and stores it
in the code area. The operand type for the selected specific
instruction guides the translation. For example, if the type is `e`,
-the value of the operand is an index into an arry of external
+the value of the operand is an index into an array of external
functions and will be translated to a pointer to the export entry for
the function to call. If the type is `x`, the number of the X
register will be multiplied by the word size to produce a byte offset.
@@ -369,7 +370,7 @@ The following files will be written to the output directory:
* `beam_opcode.hrl` - Used by `beam_asm`. It contains tag definitions
used for encoding instruction operands.
-The input file should only contain the definition of BEAM_FORMAT_NUMBER
+The input file should only contain the definition of BEAM\_FORMAT\_NUMBER
and external generic instructions. (Everything else would be ignored.)
### Running beam_makeops for the emulator ###
@@ -382,7 +383,7 @@ The following output files will be generated in the output directory.
instructions (including how to pack their operands), and
transformation rules are all part of this file.
-* `beam_opcodes.h` - Miscellanous preprocessor definitions, mainly
+* `beam_opcodes.h` - Miscellaneous preprocessor definitions, mainly
used by `beam_load.c` but also by `beam_{hot,warm,cold}.h`.
* `beam_transform.c` - Implementation of guard constraints and generators
@@ -424,8 +425,10 @@ A line with `//` is also a comment. It is recommended to only
use this style of comments in files that define implementations of
instructions.
-A long line can be broken into shorter lines by a placing a `\` before
-the newline.
+A long transformation line can be broken after the `=>` operator and
+after `|` operators. Since OTP 25, this is the only way to break transformation
+lines. When reading older source you may see that `\` was used for this
+purpose, but we removed it since it was only seen together with `=>` and `|`.
### Variable definitions ###
@@ -538,13 +541,14 @@ It is also possible to add an `%else` clause:
The following symbols are always defined.
* `ARCH_64` - is 1 for a 64-bit machine, and 0 otherwise.
-* `ARCH_32` - is 1 for 32-bit machine, and 1 otherwise.
+* `ARCH_32` - is 1 for 32-bit machine, and 0 otherwise.
The `Makefile` for building the emulator currently defines the
following symbols by using the `-D` option on the command line for
**beam\_makeops**.
-* `USE_VM_PROBES` - 1 if the runtime system is compiled to use VM probes (support for dtrace or systemtap), 0 otherwise.
+* `USE_VM_PROBES` - 1 if the runtime system is compiled to use VM
+ probes (support for dtrace or systemtap), 0 otherwise.
### Defining external generic instructions ###
@@ -586,8 +590,9 @@ the most common way. Whenever a specific instruction is created,
**beam\_makeops** automatically creates an internal generic instruction
if it does not previously exist.
-* Explicitly. This is necessary only when a generic instruction does
-not have any corresponding specific instruction.
+* Explicitly. This is necessary only when a generic instruction is
+used in transformations, but does not have any corresponding specific
+instruction.
The syntax for an internal generic instruction is as follows:
@@ -726,18 +731,18 @@ register as a port. Therefore the literal term must not contain a
port or pid.)
* `S` - Tagged source register (X or Y). The tag will be tested at
-runtime to retrieve the value from an X register or a Y register. Slighly
+runtime to retrieve the value from an X register or a Y register. Slightly
cheaper than `s`.
* `d` - Tagged destination register (X or Y). The tag will be tested
at runtime to set up a pointer to the destination register. If the
-instruction performs a garbarge collection, it must use the
+instruction performs a garbage collection, it must use the
`$REFRESH_GEN_DEST()` macro to refresh the pointer before storing to
it (there are more details about that in a later section).
* `j` - A failure label (combination of `f` and `p`). If the branch target 0,
an exception will be raised if instruction fails, otherwise control will be
-transfered to the target address.
+transferred to the target address.
The types that follows are all applied to an operand that has the `u`
type.
@@ -874,31 +879,24 @@ A rule is recognized by its right-pointer arrow: `=>`. To the left of
the arrow is one or more instruction patterns, separated by `|`. To
the right of the arrow is zero or more instructions, separated by `|`.
If the instructions from the BEAM code matches the instruction
-patterns on the left side, they will be replaced with instructions on
-the right side (or removed if there are no instructions on the right).
+patterns on the left-hand side, they will be replaced with
+instructions on the right-hand side (or removed if there are no
+instructions on the right).
#### Defining instruction patterns ####
-We will start looking at the patterns on the left side of the arrow.
+We will start looking at the patterns on the left-hand side of the arrow.
A pattern for an instruction consists of its name, followed by a pattern
for each of its operands. The operand patterns are separated by spaces.
The simplest possible pattern is a variable. Just like in Erlang,
-a variable must begin with an uppercase letter. If the same variable is
-used in multiple operands, the pattern will only match if the operands
-are equal. For example:
-
- move Same Same =>
+a variable must begin with an uppercase letter. In constrast to Erlang,
+variables must **not** be repeated.
-This pattern will match if the operands for `move` are the same. If
-the pattern match, the instruction will be removed. (That used to be an
-actual rule a long time ago when the compiler would occasionally produce
-instructions such as `{move,{x,2},{x,2}}`.)
-
-Variables that have been bound on the left side can be used on the
-right side. For example, this rule will rewrite all `move` instructions
-to `assign` instructions with the operands swapped:
+Variables that have been bound on the left-hand side can be used on
+the right-hand side. For example, this rule will rewrite all `move`
+instructions to `assign` instructions with the operands swapped:
move Src Dst => assign Dst Src
@@ -923,6 +921,18 @@ Here the `is_eq_exact` instruction is replaced with a specialized instruction
that only compares literals, but only if the first operand is a register and
the second operand is a literal.
+#### Removing instructions ####
+
+The instructions of the left-hand side of the pattern can be removed
+by using the `_` symbol on the right-hand side of the
+transformation. For example, a `line` instruction without any actual
+line-number information can be removed like this:
+
+ line n => _
+
+(Before OTP 25, this was instead achieved by leaving the right-hand side
+blank.)
+
#### Further constraining patterns ####
In addition to specifying a type letter, the actual value for the type can
@@ -934,10 +944,11 @@ Here the second operand of `move` is constrained to be X register 1.
When specifying an atom constraint, the atom is written as it would be
in the C source code. That is, it needs an `am_` prefix, and it must
-be listed in `atom.names`. For example:
+be listed in `atom.names`. For example, redundant `is_boolean` instructions
+can be removed like this:
- is_boolean Fail=f a==am_true =>
- is_boolean Fail=f a==am_false =>
+ is_boolean Fail=f a==am_true => _
+ is_boolean Fail=f a==am_false => _
There are several constraints available for testing whether a call is to a BIF
or a function.
@@ -961,7 +972,7 @@ result.
The `u$is_not_bif` constraint matches if the operand does not refer to
a BIF (not listed in `bif.tab`). For example:
- move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D => \
+ move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D =>
move S X0 | call_ext_last Ar Func D
The `u$bif:Module:Name/Arity` constraint tests whether the given
@@ -970,7 +981,7 @@ operand refers to a specific BIF. Note that `Module:Name/Arity`
be a compilation error. It is useful when a call to a specific BIF
should be replaced with an instruction as in this example:
- gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst => \
+ gc_bif2 Fail Live u$bif:erlang:splus/2 S1 S2 Dst =>
gen_plus Fail Live S1 S2 Dst
Here the call to the GC BIF `'+'/2` will be replaced with the instruction
@@ -986,13 +997,14 @@ a specific function. Here is an example:
bif1 Fail u$func:erlang:is_constant/1 Src Dst => too_old_compiler
`is_constant/1` used to be a BIF a long time ago. The transformation
-replaces the call with the `too_old_compiler` instruction which will produce
-a nicer error message than the default error would be for a missing guard BIF.
+replaces the call with the `too_old_compiler` instruction, which is
+specially handled in the loader to produce a nicer error message than
+the default error would be for a missing guard BIF.
#### Type constraints allowed in patterns ####
-Here are all type letters that are allowed on the left side of a transformation
-rule.
+Here are all type letters that are allowed on the left-hand side of a
+transformation rule.
* `u` - An untagged integer that fits in a machine word.
@@ -1026,26 +1038,47 @@ instruction, it must only be used for a destination register.)
* `o` - Overflow. An untagged integer that does not fit in a machine word.
-#### Guard constraints (predicates) ####
+#### Predicates ####
If the constraints described so far is not enough, additional
constraints can be implemented in C and be called as a guard function
-on the left side of the transformation. If the guard function returns
+on the left-hand side of the transformation. If the guard function returns
a non-zero value, the matching of the rule will continue, otherwise
-the match will fail. For example:
+the match will fail. Such guard functions are hereafter called
+*predicates*.
- ensure_map Lit=q | literal_is_map(Lit) =>
+The most commonly used guard constraints is `equal()`. It can be used
+to remove a redundant `move` instructio like this:
-The guard test `literal_is_map/1` tests whether the given literal is a map.
-If the literal is a map, the instruction is unnecessary and can be removed.
+ move R1 R2 | equal(R1, R2) => _
-Such guard tests are also called predicates. At the time of writing, all
-predicates are defined in the file `predicates.tab`.
+or remove a redundant `is_eq_exact` instruction like this:
+
+ is_eq_exact Lbl Src1 Src2 | equal(Src1, Src2) => _
+
+At the time of writing, all predicates are defined in files named
+`predicates.tab` in several directories. In `predicates.tab` directly
+in `$ERL_TOP/erts/emulator/beam`, predicates that are used by both the
+traditinal emulator and the JIT implementations are contained.
+Predicates only used by the emulator can be found in
+`emu/predicates.tab`.
+
+### A very brief note on implementation of predicates ####
It is outside the scope for this document to describe in detail how
predicates are implemented because it requires knowledge of the
-internal loader data structures, but here is the implementation of
-`literal_is_map()`:
+internal loader data structures, but here is quick look at the
+implementation of a simple predicate called `literal_is_map()`.
+
+Here is first an example how it is used:
+
+ is_map Fail Lit=q | literal_is_map(Lit) => _
+
+If the `Lit` operand is a literal, then the `literal_is_map()`
+predicate is called to determine wheter is is a map literal.
+It it is, the instruction is not needed and can be removed.
+
+`literal_is_map()` is implemented like this (in `emu/predicates.tab`):
pred.literal_is_map(Lit) {
Eterm term;
@@ -1096,23 +1129,24 @@ generic instruction:
To match a variable number of arguments we need to use the special
operand type `*` like this:
- select_val Src=aiq Fail=f Size=u List=* => \
+ select_val Src=aiq Fail=f Size=u List=* =>
i_const_select_val Src Fail Size List
This transformation renames a `select_val/3` instruction
with a constant source operand to `i_const_select_val/3`.
-#### Constructing new instructions on the right side ####
+#### Constructing new instructions on the right-hand side ####
-The most common operand on the right side is a variable that was bound while
-matching the left side. For example:
+The most common operand on the right-hand side is a variable that was
+bound while matching the pattern on the left-hand side. For example:
trim N Remaining => i_trim N
-An operand can also be a type letter to construct an operand of that type.
-Each type has a default value. For example, the type `x` has the default
-value 1023, which is the highest X register. That makes `x` on the right
-side a convenient shortcut for a temporary X register. For example:
+An operand can also be a type letter to construct an operand of that
+type. Each type has a default value. For example, the type `x` has
+the default value 1023, which is the highest X register. That makes
+`x` on the right-hand side a convenient shortcut for a temporary X
+register. For example:
is_number Fail Literal=q => move Literal x | is_number Fail x
@@ -1133,15 +1167,15 @@ the atom `false` is written as `am_false`. The atom must be listed in
Here is an example showing how values can be specified:
- bs_put_utf32 Fail=j Flags=u Src=s => \
- i_bs_validate_unicode Fail Src | \
+ bs_put_utf32 Fail=j Flags=u Src=s =>
+ i_bs_validate_unicode Fail Src |
bs_put_integer Fail i=32 u=1 Flags Src
-#### Type letters on the right side ####
+#### Type letters on the right-hand side ####
Here follows all types that are allowed to be used in operands for
-instructions being constructed on the right side of a transformation
-rule.
+instructions being constructed on the right-hand side of a
+transformation rule.
* `u` - Construct an untagged integer. The default value is 0.
@@ -1160,16 +1194,16 @@ use as a temporary X register.
* `n` - NIL (`[]`, the empty list).
-#### Function call on the right side ####
+#### Function call on the right-hand side ####
Transformations that are not possible to describe with the rule
language as described here can be implemented as a generator function
-in C and called from the right side of a transformation. The left
+in C and called from the right-hand side of a transformation. The left-hand
side of the transformation will perform the match and bind operands to
variables. The variables can then be passed to a generator function
-on the right side. For example:
+on the right-hand side. For example:
- bif2 Fail=j u$bif:erlang:element/2 Index=s Tuple=xy Dst=d => \
+ bif2 Fail=j u$bif:erlang:element/2 Index=s Tuple=xy Dst=d =>
element(Jump, Index, Tuple, Dst)
This transformation rule matches a call to the BIF `element/2`.
@@ -1191,12 +1225,13 @@ already an untagged integer. It also knows that the index is at least
instruction will have to fetch the index from a register, test that it
is an integer, and untag the integer.
-At the time of writing, all generators functions were defined in the
-file `generators.tab`.
+At the time of writing, all generators functions were defined in files
+named `generators.tab` in several directories (in the same directories
+as the `predicates.tab` files).
It is outside the scope of this document to describe in detail how
-generator functions are written, but here is the
-implementation of `element()`:
+generator functions are written, but here is the implementation of
+`element()`:
gen.element(Fail, Index, Tuple, Dst) {
BeamOp* op;
@@ -1616,7 +1651,7 @@ of the instruction, a pointer will be initialized to point to the X or
Y register in question.
If there is a garbage collection before the result is stored,
-the stack will move and if the `d` operand refered to a Y
+the stack will move and if the `d` operand referred to a Y
register, the pointer will no longer be valid. (Y registers are
stored on the stack.)
@@ -2047,13 +2082,13 @@ like this:
select_val s f I *
The `*` as the last operand will make sure that the variable operands
-are passed in as a C++ vector of `ArgVal`. Here is the emitter
-function:
+are passed in as a `Span` of `ArgVal` (will be `std::span` in C++20 onwards).
+Here is the emitter function:
void BeamModuleAssembler::emit_select_val(const ArgVal &Src,
const ArgVal &Fail,
const ArgVal &Size,
- const std::vector<ArgVal> &args) {
+ const Span<ArgVal> &args) {
ASSERT(Size.getValue() == args.size());
.
.
diff --git a/erts/emulator/internal_doc/dec.erl b/erts/emulator/internal_doc/dec.erl
index 8ce83fa402..4d3a4d980b 100644
--- a/erts/emulator/internal_doc/dec.erl
+++ b/erts/emulator/internal_doc/dec.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
%% The C header is generated from a text file containing tuples in the
%% following format:
%% {RevList,Translation}
-%% Where 'RevList' is a reversed list of the denormalized repressentation of
+%% Where 'RevList' is a reversed list of the denormalized representation of
%% the character 'Translation'. An example would be the swedish character
%% 'ö', which would be represented in the file as:
%% {[776,111],246}, as the denormalized representation of codepoint 246
diff --git a/erts/emulator/internal_doc/figures/beamasm-perf-annotate.png b/erts/emulator/internal_doc/figures/beamasm-perf-annotate.png
index 6961341bdd..0d5ed0f0f7 100644
--- a/erts/emulator/internal_doc/figures/beamasm-perf-annotate.png
+++ b/erts/emulator/internal_doc/figures/beamasm-perf-annotate.png
Binary files differ
diff --git a/erts/emulator/internal_doc/figures/perf-beamasm.png b/erts/emulator/internal_doc/figures/perf-beamasm.png
index 8524709a68..7012861459 100644
--- a/erts/emulator/internal_doc/figures/perf-beamasm.png
+++ b/erts/emulator/internal_doc/figures/perf-beamasm.png
Binary files differ
diff --git a/erts/emulator/nifs/common/prim_file_nif.c b/erts/emulator/nifs/common/prim_file_nif.c
index 48b5329773..4acedf1692 100644
--- a/erts/emulator/nifs/common/prim_file_nif.c
+++ b/erts/emulator/nifs/common/prim_file_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson 2017-2021. All Rights Reserved.
+ * Copyright Ericsson 2017-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -997,9 +997,12 @@ static ERL_NIF_TERM build_file_info(ErlNifEnv *env, efile_fileinfo_t *info) {
enif_make_uint64(env, info->size),
efile_filetype_to_atom(info->type),
efile_access_to_atom(info->access),
- enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info->a_time)),
- enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info->m_time)),
- enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info->c_time)),
+ enif_make_int64(env,
+ MIN(EFILE_MAX_FILETIME, MAX(EFILE_MIN_FILETIME, info->a_time))),
+ enif_make_int64(env,
+ MIN(EFILE_MAX_FILETIME, MAX(EFILE_MIN_FILETIME, info->m_time))),
+ enif_make_int64(env,
+ MIN(EFILE_MAX_FILETIME, MAX(EFILE_MIN_FILETIME, info->c_time))),
enif_make_uint(env, info->mode),
enif_make_uint(env, info->links),
enif_make_uint(env, info->major_device),
diff --git a/erts/emulator/nifs/common/prim_file_nif.h b/erts/emulator/nifs/common/prim_file_nif.h
index a375021224..a9cb74ab0b 100644
--- a/erts/emulator/nifs/common/prim_file_nif.h
+++ b/erts/emulator/nifs/common/prim_file_nif.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson 2017-2021. All Rights Reserved.
+ * Copyright Ericsson 2017-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ enum efile_modes_t {
EFILE_MODE_SYNC = (1 << 4),
EFILE_MODE_SKIP_TYPE_CHECK = (1 << 5), /* Special for device files on Unix. */
- EFILE_MODE_NO_TRUNCATE = (1 << 6), /* Special for reopening on VxWorks. */
+ /* EFILE_MODE_RESERVED = (1 << 6), - Reserved, previously used for reopening on VxWorks. */
EFILE_MODE_DIRECTORY = (1 << 7),
@@ -94,7 +94,12 @@ typedef struct {
/* The smallest value that can be converted freely between universal, local,
* and POSIX time, as required by read_file_info/2. Corresponds to
* {{1902,1,1},{0,0,0}} */
-#define EFILE_MIN_FILETIME -2145916800
+#define EFILE_MIN_FILETIME (-2145916800LL)
+
+/* The largest value that can be converted freely between universal, local,
+ * and POSIX time, as required by read_file_info/2. Corresponds to
+ * {{9999,12,31},{23,59,59}} */
+#define EFILE_MAX_FILETIME (253402300799LL)
/* Initializes an efile_data_t; must be used in efile_open on success. */
#define EFILE_INIT_RESOURCE(__d, __modes) do { \
diff --git a/erts/emulator/nifs/common/prim_net_nif.c b/erts/emulator/nifs/common/prim_net_nif.c
index f9cd62f4e2..b023a8e481 100644
--- a/erts/emulator/nifs/common/prim_net_nif.c
+++ b/erts/emulator/nifs/common/prim_net_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,9 +31,29 @@
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
+#ifndef ESOCK_ENABLE
+# include <erl_nif.h>
+
+static
+ErlNifFunc net_funcs[] = {};
+
+static
+int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ (void)env;
+ (void)priv_data;
+ (void)load_info;
+
+ return 1;
+}
+
+ERL_NIF_INIT(prim_net, net_funcs, on_load, NULL, NULL, NULL)
+
+#else
+
/* If we HAVE_SCTP_H and Solaris, we need to define the following in
* order to get SCTP working:
*/
@@ -91,7 +111,7 @@
#ifdef __WIN32__
-#define STRNCASECMP strncasecmp
+// #define STRNCASECMP strncasecmp
#define INCL_WINSOCK_API_TYPEDEFS 1
#ifndef WINDOWS_H_INCLUDES_WINSOCK2_H
@@ -218,9 +238,10 @@
/* Debug stuff... */
#define NET_NIF_DEBUG_DEFAULT FALSE
-#define NDBG( proto ) ESOCK_DBG_PRINTF( data.debug , proto )
-
+#define NDBG( proto ) ESOCK_DBG_PRINTF( data.debug , proto )
+#define NDBG2( dbg, proto ) ESOCK_DBG_PRINTF( (dbg || data.debug) , proto )
+/* Global 'stuff' */
typedef struct {
BOOLEAN_T debug;
} NetData;
@@ -253,20 +274,24 @@ extern char* erl_errno_id(int error);
* int argc,
* const ERL_NIF_TERM argv[]);
*
- * So, to simplify, use some macro magic to define those.
+ * So, to simplify, we use some macro magic to define those.
*
* These are the functions making up the "official" API.
*/
-#define ENET_NIF_FUNCS \
- ENET_NIF_FUNC_DEF(info); \
- ENET_NIF_FUNC_DEF(command); \
- ENET_NIF_FUNC_DEF(gethostname); \
- ENET_NIF_FUNC_DEF(getnameinfo); \
- ENET_NIF_FUNC_DEF(getaddrinfo); \
- ENET_NIF_FUNC_DEF(getifaddrs); \
- ENET_NIF_FUNC_DEF(if_name2index); \
- ENET_NIF_FUNC_DEF(if_index2name); \
+#define ENET_NIF_FUNCS \
+ ENET_NIF_FUNC_DEF(info); \
+ ENET_NIF_FUNC_DEF(command); \
+ ENET_NIF_FUNC_DEF(gethostname); \
+ ENET_NIF_FUNC_DEF(getnameinfo); \
+ ENET_NIF_FUNC_DEF(getaddrinfo); \
+ ENET_NIF_FUNC_DEF(getifaddrs); \
+ ENET_NIF_FUNC_DEF(get_adapters_addresses); \
+ ENET_NIF_FUNC_DEF(get_if_entry); \
+ ENET_NIF_FUNC_DEF(get_interface_info); \
+ ENET_NIF_FUNC_DEF(get_ip_address_table); \
+ ENET_NIF_FUNC_DEF(if_name2index); \
+ ENET_NIF_FUNC_DEF(if_index2name); \
ENET_NIF_FUNC_DEF(if_names);
#define ENET_NIF_FUNC_DEF(F) \
@@ -280,9 +305,8 @@ ENET_NIF_FUNCS
/* And here comes the functions that does the actual work (for the most part) */
static ERL_NIF_TERM enet_command(ErlNifEnv* env,
ERL_NIF_TERM cmd);
-#if defined(HAVE_GETHOSTNAME)
+
static ERL_NIF_TERM enet_gethostname(ErlNifEnv* env);
-#endif
#if defined(HAVE_GETNAMEINFO)
static ERL_NIF_TERM enet_getnameinfo(ErlNifEnv* env,
@@ -302,6 +326,147 @@ static ERL_NIF_TERM enet_getifaddrs(ErlNifEnv* env,
char* netns);
#endif
+#if defined(__WIN32__)
+
+/* *** Get Adapters Addresses functions *** */
+static BOOLEAN_T enet_get_adapters_addresses_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs);
+static BOOLEAN_T enet_get_adapters_addresses_args_family(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs,
+ ULONG* fam);
+static BOOLEAN_T enet_get_adapters_addresses_args_flags(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs,
+ ULONG* flags);
+static ERL_NIF_TERM enet_get_adapters_addresses(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ ULONG fam,
+ ULONG flags);
+static ERL_NIF_TERM enet_adapters_addresses_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP);
+static ERL_NIF_TERM enet_adapter_addresses_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP);
+static ERL_NIF_TERM enet_adapter_encode_name(ErlNifEnv* env,
+ WCHAR* name);
+static ERL_NIF_TERM enet_adapter_encode_friendly_name(ErlNifEnv* env,
+ WCHAR* fname);
+static ERL_NIF_TERM encode_if_oper_status(ErlNifEnv* env,
+ DWORD status);
+static ERL_NIF_TERM encode_adapter_flags(ErlNifEnv* env,
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP);
+static ERL_NIF_TERM encode_adapter_unicast_addrs(ErlNifEnv* env,
+ IP_ADAPTER_UNICAST_ADDRESS* firstP);
+static ERL_NIF_TERM encode_adapter_unicast_addr(ErlNifEnv* env,
+ IP_ADAPTER_UNICAST_ADDRESS* addrP);
+static ERL_NIF_TERM encode_adapter_unicast_addr_flags(ErlNifEnv* env,
+ DWORD flags);
+static ERL_NIF_TERM encode_adapter_unicast_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP);
+static ERL_NIF_TERM encode_adapter_unicast_addr_porig(ErlNifEnv* env,
+ IP_PREFIX_ORIGIN porig);
+static ERL_NIF_TERM encode_adapter_unicast_addr_sorig(ErlNifEnv* env,
+ IP_SUFFIX_ORIGIN sorig);
+static ERL_NIF_TERM encode_adapter_unicast_addr_dad_state(ErlNifEnv* env,
+ IP_DAD_STATE dstate);
+static ERL_NIF_TERM encode_adapter_anycast_addrs(ErlNifEnv* env,
+ IP_ADAPTER_ANYCAST_ADDRESS* firstP);
+static ERL_NIF_TERM encode_adapter_anycast_addr(ErlNifEnv* env,
+ IP_ADAPTER_ANYCAST_ADDRESS* addrP);
+static ERL_NIF_TERM encode_adapter_anycast_addr_flags(ErlNifEnv* env,
+ DWORD flags);
+static ERL_NIF_TERM encode_adapter_anycast_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP);
+static ERL_NIF_TERM encode_adapter_multicast_addrs(ErlNifEnv* env,
+ IP_ADAPTER_MULTICAST_ADDRESS* firstP);
+static ERL_NIF_TERM encode_adapter_multicast_addr(ErlNifEnv* env,
+ IP_ADAPTER_MULTICAST_ADDRESS* addrP);
+static ERL_NIF_TERM encode_adapter_multicast_addr_flags(ErlNifEnv* env,
+ DWORD flags);
+static ERL_NIF_TERM encode_adapter_multicast_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP);
+static ERL_NIF_TERM encode_adapter_dns_server_addrs(ErlNifEnv* env,
+ IP_ADAPTER_DNS_SERVER_ADDRESS* firstP);
+static ERL_NIF_TERM encode_adapter_dns_server_addr(ErlNifEnv* env,
+ IP_ADAPTER_DNS_SERVER_ADDRESS* addrP);
+static ERL_NIF_TERM encode_adapter_dns_server_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP);
+static ERL_NIF_TERM encode_adapter_zone_indices(ErlNifEnv* env,
+ DWORD* zoneIndices,
+ DWORD len);
+static ERL_NIF_TERM encode_adapter_prefixes(ErlNifEnv* env,
+ IP_ADAPTER_PREFIX* firstP);
+static ERL_NIF_TERM encode_adapter_prefix(ErlNifEnv* env,
+ IP_ADAPTER_PREFIX* prefP);
+static ERL_NIF_TERM encode_adapter_prefix_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP);
+
+
+/* *** Get If Entry (MIB_IFROW) functions *** */
+static ERL_NIF_TERM enet_get_if_entry(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ DWORD index);
+static BOOLEAN_T enet_get_if_entry_args_index(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs,
+ DWORD* index);
+static BOOLEAN_T enet_get_if_entry_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs);
+static ERL_NIF_TERM enet_if_row_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ MIB_IFROW* rowP);
+static ERL_NIF_TERM encode_if_type(ErlNifEnv* env,
+ DWORD type);
+static ERL_NIF_TERM encode_if_row_description(ErlNifEnv* env,
+ DWORD len,
+ UCHAR* buf);
+static ERL_NIF_TERM encode_if_admin_status(ErlNifEnv* env,
+ DWORD status);
+static ERL_NIF_TERM encode_internal_if_oper_status(ErlNifEnv* env,
+ DWORD status);
+static ERL_NIF_TERM encode_if_row_phys_address(ErlNifEnv* env,
+ DWORD len,
+ UCHAR* buf);
+
+/* *** Get Interface Info functions *** */
+static ERL_NIF_TERM enet_get_interface_info(ErlNifEnv* env,
+ BOOLEAN_T dbg);
+static BOOLEAN_T enet_get_interface_info_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eextra);
+static ERL_NIF_TERM enet_interface_info_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_INTERFACE_INFO* infoP);
+static void encode_adapter_index_map(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_ADAPTER_INDEX_MAP* adapterP,
+ ERL_NIF_TERM* eadapter);
+static ERL_NIF_TERM encode_adapter_index_map_name(ErlNifEnv* env, WCHAR* name);
+static void make_adapter_index_map(ErlNifEnv* env,
+ ERL_NIF_TERM eindex,
+ ERL_NIF_TERM ename,
+ ERL_NIF_TERM* emap);
+/* *** Get IP Address Table functions *** */
+static ERL_NIF_TERM enet_get_ip_address_table(ErlNifEnv* env,
+ BOOLEAN_T dbg);
+static ERL_NIF_TERM enet_get_ip_address_table_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ MIB_IPADDRTABLE* tabP);
+static ERL_NIF_TERM encode_ip_address_row(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ MIB_IPADDRROW* rowP);
+static ERL_NIF_TERM encode_ip_address_row_addr(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ const char* descr,
+ DWORD addr);
+static void make_ip_address_row(ErlNifEnv* env,
+ ERL_NIF_TERM eaddr,
+ ERL_NIF_TERM eindex,
+ ERL_NIF_TERM emask,
+ ERL_NIF_TERM eBCastAddr,
+ ERL_NIF_TERM eReasmSize,
+ ERL_NIF_TERM* iar);
+
+#endif
+
#if defined(HAVE_IF_NAMETOINDEX)
static ERL_NIF_TERM enet_if_name2index(ErlNifEnv* env,
char* ifn);
@@ -359,6 +524,7 @@ static BOOLEAN_T enet_getifaddrs_netns(ErlNifEnv* env,
static BOOLEAN_T change_network_namespace(char* netns, int* cns, int* err);
static BOOLEAN_T restore_network_namespace(int ns, int* err);
#endif
+static ERL_NIF_TERM encode_sockaddr(ErlNifEnv* env, struct sockaddr* sa);
static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env,
const ERL_NIF_TERM eflags,
int* flags);
@@ -379,9 +545,9 @@ static ERL_NIF_TERM encode_address_info(ErlNifEnv* env,
static unsigned int address_info_length(struct addrinfo* addrInfoP);
static ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env,
- int family);
+ int family);
static ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env,
- int socktype);
+ int socktype);
static void make_address_info(ErlNifEnv* env,
ERL_NIF_TERM fam,
@@ -390,9 +556,18 @@ static void make_address_info(ErlNifEnv* env,
ERL_NIF_TERM addr,
ERL_NIF_TERM* ai);
+#if defined(__WIN32__)
+static ERL_NIF_TERM encode_uchar(ErlNifEnv* env,
+ DWORD len,
+ UCHAR* buf);
+static ERL_NIF_TERM encode_wchar(ErlNifEnv* env,
+ WCHAR* name);
+#endif
static BOOLEAN_T get_debug(ErlNifEnv* env,
ERL_NIF_TERM map);
-static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
+static int on_load(ErlNifEnv* env,
+ void** priv_data,
+ ERL_NIF_TERM load_info);
#if HAVE_IN6
@@ -428,33 +603,132 @@ static const struct in6_addr in6addr_loopback =
#define LOCAL_ATOMS \
LOCAL_ATOM_DECL(address_info); \
+ LOCAL_ATOM_DECL(admin_status); \
+ LOCAL_ATOM_DECL(anycast_addrs); \
+ LOCAL_ATOM_DECL(atm); \
LOCAL_ATOM_DECL(automedia); \
+ LOCAL_ATOM_DECL(bcast_addr); \
LOCAL_ATOM_DECL(broadaddr); \
LOCAL_ATOM_DECL(broadcast); \
+ LOCAL_ATOM_DECL(dad_state); \
LOCAL_ATOM_DECL(debug); \
+ LOCAL_ATOM_DECL(deprecated); \
+ LOCAL_ATOM_DECL(description); \
+ LOCAL_ATOM_DECL(dhcp); \
+ LOCAL_ATOM_DECL(dhcp_v4_enabled); \
+ LOCAL_ATOM_DECL(ddns_enabled); \
+ LOCAL_ATOM_DECL(disconnected); \
+ LOCAL_ATOM_DECL(dns_eligible); \
+ LOCAL_ATOM_DECL(dns_server_addrs); \
+ LOCAL_ATOM_DECL(dns_suffix); \
+ LOCAL_ATOM_DECL(down); \
LOCAL_ATOM_DECL(dstaddr); \
+ LOCAL_ATOM_DECL(duplicate); \
LOCAL_ATOM_DECL(dynamic); \
+ LOCAL_ATOM_DECL(ethernet_csmacd); \
+ LOCAL_ATOM_DECL(fddi); \
+ LOCAL_ATOM_DECL(friendly_name); \
LOCAL_ATOM_DECL(host); \
LOCAL_ATOM_DECL(idn); \
+ LOCAL_ATOM_DECL(ieee1394); \
+ LOCAL_ATOM_DECL(ieee80211); \
+ LOCAL_ATOM_DECL(ieee80216_wman); \
+ LOCAL_ATOM_DECL(include_prefix); \
+ LOCAL_ATOM_DECL(include_wins_info); \
+ LOCAL_ATOM_DECL(include_gateways); \
+ LOCAL_ATOM_DECL(include_all_interfaces); \
+ LOCAL_ATOM_DECL(include_all_compartments); \
+ LOCAL_ATOM_DECL(include_tunnel_bindingorder); \
+ LOCAL_ATOM_DECL(index); \
+ LOCAL_ATOM_DECL(internal_oper_status); \
+ LOCAL_ATOM_DECL(invalid); \
+ LOCAL_ATOM_DECL(in_octets); \
+ LOCAL_ATOM_DECL(in_ucast_pkts); \
+ LOCAL_ATOM_DECL(in_nucast_pkts); \
+ LOCAL_ATOM_DECL(in_discards); \
+ LOCAL_ATOM_DECL(in_errors); \
+ LOCAL_ATOM_DECL(in_unknown_protos); \
+ LOCAL_ATOM_DECL(ipv4_enabled); \
+ LOCAL_ATOM_DECL(ipv6_enabled); \
+ LOCAL_ATOM_DECL(ipv6_index); \
+ LOCAL_ATOM_DECL(ipv6_managed_address_config_supported); \
+ LOCAL_ATOM_DECL(ipv6_other_stateful_config); \
+ LOCAL_ATOM_DECL(iso88025_tokenring); \
+ LOCAL_ATOM_DECL(last_change); \
+ LOCAL_ATOM_DECL(lease_lifetime); \
+ LOCAL_ATOM_DECL(length); \
+ LOCAL_ATOM_DECL(link_layer_address); \
+ LOCAL_ATOM_DECL(lower_layer_down); \
+ LOCAL_ATOM_DECL(manual); \
+ LOCAL_ATOM_DECL(mask); \
LOCAL_ATOM_DECL(master); \
LOCAL_ATOM_DECL(multicast); \
+ LOCAL_ATOM_DECL(multicast_addrs); \
LOCAL_ATOM_DECL(namereqd); \
LOCAL_ATOM_DECL(name_info); \
+ LOCAL_ATOM_DECL(netbios_over_tcpip_enabled); \
LOCAL_ATOM_DECL(netmask); \
LOCAL_ATOM_DECL(noarp); \
LOCAL_ATOM_DECL(nofqdn); \
+ LOCAL_ATOM_DECL(non_operational); \
LOCAL_ATOM_DECL(notrailers); \
+ LOCAL_ATOM_DECL(not_present); \
+ LOCAL_ATOM_DECL(no_multicast); \
LOCAL_ATOM_DECL(numerichost); \
LOCAL_ATOM_DECL(numericserv); \
+ LOCAL_ATOM_DECL(on_link_prefix_length); \
+ LOCAL_ATOM_DECL(operational); \
+ LOCAL_ATOM_DECL(oper_status); \
+ LOCAL_ATOM_DECL(other); \
+ LOCAL_ATOM_DECL(out_octets); \
+ LOCAL_ATOM_DECL(out_ucast_pkts); \
+ LOCAL_ATOM_DECL(out_nucast_pkts); \
+ LOCAL_ATOM_DECL(out_discards); \
+ LOCAL_ATOM_DECL(out_errors); \
+ LOCAL_ATOM_DECL(out_qlen); \
+ LOCAL_ATOM_DECL(phys_addr); \
LOCAL_ATOM_DECL(pointopoint); \
LOCAL_ATOM_DECL(portsel); \
+ LOCAL_ATOM_DECL(ppp); \
+ LOCAL_ATOM_DECL(preferred); \
+ LOCAL_ATOM_DECL(preferred_lifetime); \
+ LOCAL_ATOM_DECL(prefixes); \
+ LOCAL_ATOM_DECL(prefix_origin); \
LOCAL_ATOM_DECL(promisc); \
+ LOCAL_ATOM_DECL(random); \
+ LOCAL_ATOM_DECL(reasm_size); \
+ LOCAL_ATOM_DECL(receive_only); \
+ LOCAL_ATOM_DECL(register_adapter_suffix); \
+ LOCAL_ATOM_DECL(router_advertisement); \
LOCAL_ATOM_DECL(running); \
LOCAL_ATOM_DECL(service); \
LOCAL_ATOM_DECL(slave); \
- LOCAL_ATOM_DECL(up);
+ LOCAL_ATOM_DECL(skip_unicast); \
+ LOCAL_ATOM_DECL(skip_anycast); \
+ LOCAL_ATOM_DECL(skip_multicast); \
+ LOCAL_ATOM_DECL(skip_dns_server); \
+ LOCAL_ATOM_DECL(skip_friendly_name); \
+ LOCAL_ATOM_DECL(software_loopback); \
+ LOCAL_ATOM_DECL(speed); \
+ LOCAL_ATOM_DECL(suffix_origin); \
+ LOCAL_ATOM_DECL(tentative); \
+ LOCAL_ATOM_DECL(testing); \
+ LOCAL_ATOM_DECL(transient); \
+ LOCAL_ATOM_DECL(tunnel); \
+ LOCAL_ATOM_DECL(unchanged); \
+ LOCAL_ATOM_DECL(unknown); \
+ LOCAL_ATOM_DECL(unicast_addrs); \
+ LOCAL_ATOM_DECL(unreachable); \
+ LOCAL_ATOM_DECL(up); \
+ LOCAL_ATOM_DECL(valid_lifetime); \
+ LOCAL_ATOM_DECL(well_known); \
+ LOCAL_ATOM_DECL(wwanpp); \
+ LOCAL_ATOM_DECL(wwanpp2); \
+ LOCAL_ATOM_DECL(zone_indices);
#define LOCAL_ERROR_REASON_ATOMS \
+ LOCAL_ATOM_DECL(address_not_associated); \
+ LOCAL_ATOM_DECL(can_not_complete); \
LOCAL_ATOM_DECL(eaddrfamily); \
LOCAL_ATOM_DECL(ebadflags); \
LOCAL_ATOM_DECL(efail); \
@@ -468,7 +742,17 @@ static const struct in6_addr in6addr_loopback =
LOCAL_ATOM_DECL(eoverflow); \
LOCAL_ATOM_DECL(eservice); \
LOCAL_ATOM_DECL(esocktype); \
- LOCAL_ATOM_DECL(esystem);
+ LOCAL_ATOM_DECL(esystem); \
+ LOCAL_ATOM_DECL(insufficient_buffer); \
+ LOCAL_ATOM_DECL(invalid_data); \
+ LOCAL_ATOM_DECL(invalid_flags); \
+ LOCAL_ATOM_DECL(invalid_parameter); \
+ LOCAL_ATOM_DECL(not_found); \
+ LOCAL_ATOM_DECL(not_enough_memory); \
+ LOCAL_ATOM_DECL(not_supported); \
+ LOCAL_ATOM_DECL(no_data); \
+ LOCAL_ATOM_DECL(no_function); \
+ LOCAL_ATOM_DECL(no_uniconde_traslation);
#define LOCAL_ATOM_DECL(A) static ERL_NIF_TERM atom_##A
LOCAL_ATOMS
@@ -501,6 +785,10 @@ static ErlNifResourceTypeInit netInit = {
* nif_getnameinfo/2
* nif_getaddrinfo/3
* nif_getifaddrs/1
+ * nif_get_adapters_addresses/1
+ * nif_get_if_entry/1
+ * nif_get_interface_info/1
+ * nif_get_ip_address_table/1
* nif_if_name2index/1
* nif_if_index2name/1
* nif_if_names/0
@@ -519,9 +807,6 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env,
int argc,
const ERL_NIF_TERM argv[])
{
-#if defined(__WIN32__)
- return enif_raise_exception(env, MKA(env, "notsup"));
-#else
ERL_NIF_TERM info, tmp;
NDBG( ("NET", "info -> entry\r\n") );
@@ -533,7 +818,6 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env,
NDBG( ("NET", "info -> done: %T\r\n", info) );
return info;
-#endif
}
@@ -555,9 +839,6 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env,
int argc,
const ERL_NIF_TERM argv[])
{
-#if defined(__WIN32__)
- return enif_raise_exception(env, MKA(env, "notsup"));
-#else
ERL_NIF_TERM ecmd, result;
NDBG( ("NET", "command -> entry (%d)\r\n", argc) );
@@ -574,7 +855,6 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env,
NDBG( ("NET", "command -> result: %T\r\n", result) );
return result;
-#endif
}
@@ -583,7 +863,6 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env,
* The command can, in principle, be anything, though currently we only
* support a debug command.
*/
-#if !defined(__WIN32__)
static
ERL_NIF_TERM enet_command(ErlNifEnv* env,
ERL_NIF_TERM cmd)
@@ -610,7 +889,6 @@ ERL_NIF_TERM enet_command(ErlNifEnv* env,
}
}
-#endif
@@ -626,9 +904,6 @@ ERL_NIF_TERM nif_gethostname(ErlNifEnv* env,
int argc,
const ERL_NIF_TERM argv[])
{
-#if defined(__WIN32__)
- return enif_raise_exception(env, MKA(env, "notsup"));
-#elif defined(HAVE_GETHOSTNAME)
ERL_NIF_TERM result;
NDBG( ("NET", "nif_gethostname -> entry (%d)\r\n", argc) );
@@ -641,13 +916,9 @@ ERL_NIF_TERM nif_gethostname(ErlNifEnv* env,
NDBG( ("NET", "nif_gethostname -> done when result: %T\r\n", result) );
return result;
-#else
- return esock_make_error(env, esock_atom_enotsup);
-#endif
}
-#if !defined(__WIN32__) && defined(HAVE_GETHOSTNAME)
static
ERL_NIF_TERM enet_gethostname(ErlNifEnv* env)
{
@@ -683,8 +954,6 @@ ERL_NIF_TERM enet_gethostname(ErlNifEnv* env)
return result;
}
-#endif
-
@@ -704,9 +973,7 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env,
int argc,
const ERL_NIF_TERM argv[])
{
-#if defined(__WIN32__)
- return enif_raise_exception(env, MKA(env, "notsup"));
-#elif defined(HAVE_GETNAMEINFO)
+#if defined(HAVE_GETNAMEINFO)
ERL_NIF_TERM result;
ERL_NIF_TERM eSockAddr, eFlags;
int flags = 0; // Just in case...
@@ -750,10 +1017,10 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env,
-/* Given the provided sock(et) address (and flags), retreive the host and
+/* Given the provided sock(et) address (and flags), retrieve the host and
* service info.
*/
-#if !defined(__WIN32__) && defined(HAVE_GETNAMEINFO)
+#if defined(HAVE_GETNAMEINFO)
static
ERL_NIF_TERM enet_getnameinfo(ErlNifEnv* env,
const ESockAddress* saP,
@@ -818,7 +1085,7 @@ ERL_NIF_TERM enet_getnameinfo(ErlNifEnv* env,
break;
#endif
-#if defined(EAI_NONAME)
+#if !defined(__WIN32__) && defined(EAI_NONAME)
case EAI_NONAME:
result = esock_make_error(env, atom_enoname);
break;
@@ -864,9 +1131,7 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env,
int argc,
const ERL_NIF_TERM argv[])
{
-#if defined(__WIN32__)
- return enif_raise_exception(env, MKA(env, "notsup"));
-#elif defined(HAVE_GETADDRINFO)
+#if defined(HAVE_GETADDRINFO)
ERL_NIF_TERM result, eHostName, eServName; //, eHints;
char* hostName;
char* servName;
@@ -926,7 +1191,7 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env,
}
-#if !defined(__WIN32__) && defined(HAVE_GETADDRINFO)
+#if defined(HAVE_GETADDRINFO)
static
ERL_NIF_TERM enet_getaddrinfo(ErlNifEnv* env,
char* host,
@@ -998,7 +1263,8 @@ ERL_NIF_TERM enet_getaddrinfo(ErlNifEnv* env,
break;
#endif
-#if defined(EAI_NONAME)
+ /* This value conflict with "some" other value on windows... */
+#if !defined(__WIN32__) && defined(EAI_NONAME)
case EAI_NONAME:
result = esock_make_error(env, atom_enoname);
break;
@@ -1251,7 +1517,7 @@ ERL_NIF_TERM enet_getifaddrs_process(ErlNifEnv* env, struct ifaddrs* ifap)
-/* Calculate the length of the interface adress linked list
+/* Calculate the length of the interface address linked list
* The list is NULL-terminated, so the only way is to
* iterate through the list until we find next = NULL.
*/
@@ -1422,19 +1688,7 @@ ERL_NIF_TERM encode_ifaddrs_flags(ErlNifEnv* env, unsigned int flags)
static
ERL_NIF_TERM encode_ifaddrs_addr(ErlNifEnv* env, struct sockaddr* sa)
{
- ERL_NIF_TERM esa;
-
- if (sa != NULL) {
-
- unsigned int sz = sizeof(ESockAddress);
-
- esock_encode_sockaddr(env, (ESockAddress*) sa, sz, &esa);
-
- } else {
- esa = esock_atom_undefined;
- }
-
- return esa;
+ return encode_sockaddr(env, sa);
}
@@ -1522,6 +1776,2162 @@ void make_ifaddrs(ErlNifEnv* env,
/* ----------------------------------------------------------------------
+ * nif_get_adapters_addresses
+ *
+ * Description:
+ * Get adapters addresses.
+ * This is a windows only function!
+ *
+ * Arguments:
+ * Args - A way to pass 'extra' arguments.
+ * #{family := unspec (default) | inet | inet6,
+ * flags := flags(),
+ * debug := boolean() (optional)}
+ *
+ * flags() :: #{skip_unicast :: boolean() (default false),
+ * skip_anycast :: boolean() (default true),
+ * skip_multicast :: boolean() (default true),
+ * skip_dns_server :: boolean() (default true),
+ * skip_friendly_name :: boolean() (default true),
+ * include_prefix :: boolean() (default true),
+ * include_wins_info :: boolean() (default false),
+ * include_gateways :: boolean() (default false),
+ * include_all_interfaces :: boolean() (default false),
+ * include_all_compartments :: boolean() (default false),
+ * include_tunnel_bindingorder :: boolean() (default false)}
+ * Suggested Help atoms:
+ * no_skips_all_includes
+ * all_skips_no_includes
+ * no_skips_no_includes
+ * all_skips_all_includes
+ */
+
+static
+ERL_NIF_TERM nif_get_adapters_addresses(ErlNifEnv* env,
+ int argc,
+ const ERL_NIF_TERM argv[])
+{
+#if !defined(__WIN32__)
+ return enif_raise_exception(env, MKA(env, "notsup"));
+#else
+ ERL_NIF_TERM result, eargs;
+ ULONG fam, flags;
+ BOOLEAN_T dbg;
+
+ NDBG( ("NET", "nif_get_adapters_addresses -> entry (%d)\r\n", argc) );
+
+ if ((argc != 1) ||
+ !IS_MAP(env, argv[0])) {
+ return enif_make_badarg(env);
+ }
+ eargs = argv[0];
+
+ if (!enet_get_adapters_addresses_args_family(env, eargs, &fam))
+ return enif_make_badarg(env);
+
+ if (!enet_get_adapters_addresses_args_flags(env, eargs, &flags))
+ return enif_make_badarg(env);
+
+ dbg = enet_get_adapters_addresses_args_debug(env, eargs);
+
+ result = enet_get_adapters_addresses(env, dbg, fam, flags);
+
+ NDBG2( dbg,
+ ("NET",
+ "nif_get_adapters_addresses -> done when result: "
+ "\r\n %T\r\n", result) );
+
+ return result;
+#endif
+}
+
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_adapters_addresses_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs)
+{
+ return get_debug(env, eargs);
+}
+#endif
+
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_adapters_addresses_args_family(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs,
+ ULONG* fam)
+{
+ ERL_NIF_TERM key = esock_atom_family;
+ ERL_NIF_TERM eval;
+ DWORD val;
+
+ if (!GET_MAP_VAL(env, eargs, key, &eval)) {
+ *fam = AF_UNSPEC; // Default
+ return TRUE;
+ } else {
+ if (!IS_ATOM(env, eval))
+ return FALSE;
+
+ if (COMPARE(eval, esock_atom_unspec))
+ val = AF_UNSPEC;
+ else if (COMPARE(eval, esock_atom_inet))
+ val = AF_INET;
+ else if (COMPARE(eval, esock_atom_inet6))
+ val = AF_INET6;
+ else
+ return FALSE;
+
+ *fam = val;
+ return TRUE;
+ }
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_adapters_addresses_args_flags(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs,
+ ULONG* flags)
+{
+ ERL_NIF_TERM eflags;
+ ULONG val = 0;
+
+ if (!GET_MAP_VAL(env, eargs, esock_atom_flags, &eflags)) {
+ // Default
+ *flags =
+ GAA_FLAG_INCLUDE_PREFIX |
+ GAA_FLAG_SKIP_ANYCAST |
+ GAA_FLAG_SKIP_DNS_SERVER |
+ GAA_FLAG_SKIP_FRIENDLY_NAME |
+ GAA_FLAG_SKIP_MULTICAST;
+ return TRUE;
+ } else {
+ if (!IS_MAP(env, eflags))
+ return FALSE;
+
+ /* skip unicast */
+ if (esock_get_bool_from_map(env, eflags, atom_skip_unicast, FALSE))
+ val |= GAA_FLAG_SKIP_UNICAST;
+
+ /* skip anycast */
+ if (esock_get_bool_from_map(env, eflags, atom_skip_anycast, TRUE))
+ val |= GAA_FLAG_SKIP_ANYCAST;
+
+ /* skip multicast */
+ if (esock_get_bool_from_map(env, eflags, atom_skip_multicast, TRUE))
+ val |= GAA_FLAG_SKIP_MULTICAST;
+
+ /* skip dns-server */
+ if (esock_get_bool_from_map(env, eflags, atom_skip_dns_server, TRUE))
+ val |= GAA_FLAG_SKIP_DNS_SERVER;
+
+ /* skip fiendly-name */
+ if (esock_get_bool_from_map(env, eflags, atom_skip_friendly_name, TRUE))
+ val |= GAA_FLAG_SKIP_FRIENDLY_NAME;
+
+ /* include prefix */
+ if (esock_get_bool_from_map(env, eflags, atom_include_prefix, TRUE))
+ val |= GAA_FLAG_INCLUDE_PREFIX;
+
+ /* include wins-info */
+ if (esock_get_bool_from_map(env, eflags, atom_include_wins_info, FALSE))
+ val |= GAA_FLAG_INCLUDE_WINS_INFO;
+
+ /* include gateways */
+ if (esock_get_bool_from_map(env, eflags, atom_include_gateways, FALSE))
+ val |= GAA_FLAG_INCLUDE_GATEWAYS;
+
+ /* include all-interfaces */
+ if (esock_get_bool_from_map(env, eflags,
+ atom_include_all_interfaces, FALSE))
+ val |= GAA_FLAG_INCLUDE_ALL_INTERFACES;
+
+ /* include all-compartments */
+ if (esock_get_bool_from_map(env, eflags,
+ atom_include_all_compartments, FALSE))
+ val |= GAA_FLAG_INCLUDE_ALL_COMPARTMENTS;
+
+ /* include tunnel-bindingorder */
+ if (esock_get_bool_from_map(env, eflags,
+ atom_include_tunnel_bindingorder, FALSE))
+ val |= GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER;
+
+ *flags = val;
+ return TRUE;
+ }
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_get_adapters_addresses(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ ULONG family,
+ ULONG flags)
+{
+ int i;
+ DWORD ret;
+ unsigned long ipAdAddrsSz = 16 * 1024;
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP;
+ ERL_NIF_TERM eret, addrs, result;
+
+ ipAdAddrsP = (IP_ADAPTER_ADDRESSES*) MALLOC(ipAdAddrsSz);
+ for (i = 17; i; i--) {
+ ret = GetAdaptersAddresses(family, flags, NULL,
+ ipAdAddrsP, &ipAdAddrsSz);
+ if (ret == NO_ERROR) {
+ /* We are done! */
+ break;
+ } else if (ret == ERROR_BUFFER_OVERFLOW) {
+ /* Not large enough */
+ ipAdAddrsP = REALLOC(ipAdAddrsP, ipAdAddrsSz);
+ continue;
+ } else {
+ /* Failure */
+ i = 0;
+ }
+ if (ret == NO_ERROR) break;
+ if (ret == ERROR_BUFFER_OVERFLOW) continue;
+ i = 0;
+ }
+
+ if (! i) {
+
+ NDBG2( dbg,
+ ("NET", "enet_get_adapters_addresses -> "
+ "try encode error (%d)\r\n", ret) );
+
+ FREE(ipAdAddrsP);
+
+ switch (ret) {
+ case ERROR_ADDRESS_NOT_ASSOCIATED:
+ eret = atom_address_not_associated;
+ break;
+ case ERROR_BUFFER_OVERFLOW:
+ eret = atom_insufficient_buffer;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ eret = atom_invalid_parameter;
+ break;
+ case ERROR_NO_DATA:
+ eret = atom_no_data;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ eret = atom_not_enough_memory;
+ break;
+ default:
+ eret = MKI(env, ret);
+ break;
+ }
+
+ result = esock_make_error(env, eret);
+
+ } else {
+
+ NDBG2( dbg,
+ ("NET", "enet_get_adapters_addresses -> "
+ "try encode addresses\r\n") );
+
+ addrs = enet_adapters_addresses_encode(env, dbg, ipAdAddrsP);
+ result = esock_make_ok2(env, addrs);
+
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_adapters_addresses -> done with:"
+ "\r\n result: %T"
+ "\r\n", result) );
+
+ return result;
+}
+#endif
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_adapters_addresses_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP)
+{
+ /* No idea how many we actually need, so just get some */
+ SocketTArray adapterArray = TARRAY_CREATE(16);
+ IP_ADAPTER_ADDRESSES* addrsP = ipAdAddrsP;
+ ERL_NIF_TERM entry, result;
+
+ NDBG2( dbg, ("NET", "enet_get_adapters_addresses -> entry\r\n") );
+
+ while (addrsP != NULL) {
+ /* Process current adapter */
+ entry = enet_adapter_addresses_encode(env, dbg, addrsP);
+
+ NDBG2( dbg, ("NET", "enet_get_adapters_addresses -> entry encoded:"
+ "\r\n Adapter Entry: %T"
+ "\r\n", entry) );
+
+ TARRAY_ADD(adapterArray, entry);
+
+ addrsP = addrsP->Next;
+ }
+
+ TARRAY_TOLIST(adapterArray, env, &result);
+
+ NDBG2( dbg, ("NET", "enet_get_adapters_addresses -> done:"
+ "\r\n %T"
+ "\r\n", result) );
+
+ return result;
+
+ }
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_adapter_addresses_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP)
+{
+ ERL_NIF_TERM ifIdx, name;
+ ERL_NIF_TERM unicastAddrs, anycastAddrs, multicastAddrs, dnsServerAddrs;
+ ERL_NIF_TERM dnsSuffix, description, flags, physAddr, fName, mtu, ifType;
+ ERL_NIF_TERM operStatus, zoneIndices, ipv6IfIdx, prefixes;
+ ERL_NIF_TERM map;
+
+ ifIdx = MKI(env, ipAdAddrsP->IfIndex);
+ name = MKS(env, ipAdAddrsP->AdapterName);
+ unicastAddrs = encode_adapter_unicast_addrs(env, ipAdAddrsP->FirstUnicastAddress);
+ anycastAddrs = encode_adapter_anycast_addrs(env, ipAdAddrsP->FirstAnycastAddress);
+ multicastAddrs = encode_adapter_multicast_addrs(env, ipAdAddrsP->FirstMulticastAddress);
+ dnsServerAddrs = encode_adapter_dns_server_addrs(env, ipAdAddrsP->FirstDnsServerAddress);
+ dnsSuffix = encode_wchar(env, ipAdAddrsP->DnsSuffix);
+ description = encode_wchar(env, ipAdAddrsP->Description);
+ fName = encode_wchar(env, ipAdAddrsP->FriendlyName);
+ physAddr = encode_uchar(env,
+ ipAdAddrsP->PhysicalAddressLength,
+ ipAdAddrsP->PhysicalAddress);
+ flags = encode_adapter_flags(env, ipAdAddrsP);
+ mtu = MKUI(env, ipAdAddrsP->Mtu);
+ ifType = encode_if_type(env, ipAdAddrsP->IfType);
+ operStatus = encode_if_oper_status(env, ipAdAddrsP->OperStatus);
+ zoneIndices = encode_adapter_zone_indices(env,
+ ipAdAddrsP->ZoneIndices,
+ NUM(ipAdAddrsP->ZoneIndices));
+ ipv6IfIdx = MKI(env, ipAdAddrsP->Ipv6IfIndex);
+ prefixes = encode_adapter_prefixes(env, ipAdAddrsP->FirstPrefix);
+
+ /* *** _LH *** */
+ // tLinkSpeed = MKUI64(env, ipAdAddrsP->TransmitLinkSpeed);
+ // rLinkSpeed = MKUI64(env, ipAdAddrsP->ReceiveLinkSpeed);
+ // winsServerAddr = ...
+ // gatewayAddr = ...
+ // ipv4Metric = ...
+ // ipv6Metric = ...
+ // luid = ...
+ // dhcpv4Server = ...
+ // compartmentId = ...
+ // networkDuid = ...
+ // connectionType = ...
+ // tunnelType = ...
+ // dhcpv6Server = ...
+ // dhcpv6ClientDuid = ...
+ // dhcpv6Iaid = ...
+ // dnsSuffix = ...
+
+ {
+ ERL_NIF_TERM keys[] = {atom_index,
+ esock_atom_name,
+ atom_unicast_addrs,
+ atom_anycast_addrs,
+ atom_multicast_addrs,
+ atom_dns_server_addrs,
+ atom_dns_suffix,
+ atom_description,
+ atom_friendly_name,
+ atom_phys_addr,
+ esock_atom_flags,
+ esock_atom_mtu,
+ esock_atom_type,
+ atom_oper_status,
+ atom_zone_indices,
+ atom_ipv6_index,
+ atom_prefixes/* , */
+ /* atom_transmit_link_speed, */
+ /* atom_receive_link_speed */
+ };
+ ERL_NIF_TERM vals[] = {ifIdx,
+ name,
+ unicastAddrs,
+ anycastAddrs,
+ multicastAddrs,
+ dnsServerAddrs,
+ dnsSuffix,
+ description,
+ fName,
+ physAddr,
+ flags,
+ mtu,
+ ifType,
+ operStatus,
+ zoneIndices,
+ ipv6IfIdx,
+ prefixes
+ /* , */
+ /* tLinkSpeed, */
+ /* rLinkSpeed */
+ };
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &map) );
+ }
+
+ return map;
+}
+#endif // __WIN32__
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_flags(ErlNifEnv* env,
+ IP_ADAPTER_ADDRESSES* ipAdAddrsP)
+{
+ ERL_NIF_TERM ddnsEnabled, regAdSuffix, dhcpv4Enabled, recvOnly;
+ ERL_NIF_TERM noMulticast, ipv6OtherStatefulCfg, netbiosOverTcpipEnabled;
+ ERL_NIF_TERM ipv4Enabled, ipv6Enabled, ipv6ManagedAddrCfgSup;
+ ERL_NIF_TERM eflags;
+
+#if defined(ESOCK_WIN_XP)
+ /* This is just a dummy-ifdef ... there is no such flag (ESOCK_WIN_XP).
+ * But this is a way to keep the code...
+ */
+ ddnsEnabled = BOOL2ATOM(ipAdAddrsP->DdnsEnabled);
+ regAdSuffix = BOOL2ATOM(ipAdAddrsP->RegisterAdapterSuffix);
+ dhcpv4Enabled = BOOL2ATOM(ipAdAddrsP->Dhcpv4Enabled);
+ recvOnly = BOOL2ATOM(ipAdAddrsP->ReceiveOnly);
+ noMulticast = BOOL2ATOM(ipAdAddrsP->NoMulticast);
+ ipv6OtherStatefulCfg = BOOL2ATOM(ipAdAddrsP->Ipv6OtherStatefulConfig);
+ netbiosOverTcpipEnabled = BOOL2ATOM(ipAdAddrsP->NetbiosOverTcpipEnabled);
+ ipv4Enabled = BOOL2ATOM(ipAdAddrsP->Ipv4Enabled);
+ ipv6Enabled = BOOL2ATOM(ipAdAddrsP->Ipv6Enabled);
+ ipv6ManagedAddrCfgSup = BOOL2ATOM(ipAdAddrsP->Ipv6ManagedAddressConfigurationSupported);
+#else
+ ddnsEnabled = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_DDNS_ENABLED);
+ regAdSuffix = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_REGISTER_ADAPTER_SUFFIX);
+ dhcpv4Enabled = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_DHCP_ENABLED);
+ recvOnly = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_RECEIVE_ONLY);
+ noMulticast = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_NO_MULTICAST);
+ ipv6OtherStatefulCfg = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG);
+ netbiosOverTcpipEnabled = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_NETBIOS_OVER_TCPIP_ENABLED);
+ ipv4Enabled = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_IPV4_ENABLED);
+ ipv6Enabled = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_IPV6_ENABLED);
+ ipv6ManagedAddrCfgSup = BOOL2ATOM(ipAdAddrsP->Flags & IP_ADAPTER_IPV6_MANAGE_ADDRESS_CONFIG);
+#endif
+
+ {
+ ERL_NIF_TERM keys[] = {atom_ddns_enabled,
+ atom_register_adapter_suffix,
+ atom_dhcp_v4_enabled,
+ atom_receive_only,
+ atom_no_multicast,
+ atom_ipv6_other_stateful_config,
+ atom_netbios_over_tcpip_enabled,
+ atom_ipv4_enabled,
+ atom_ipv6_enabled,
+ atom_ipv6_managed_address_config_supported};
+ ERL_NIF_TERM vals[] = {ddnsEnabled,
+ regAdSuffix,
+ dhcpv4Enabled,
+ recvOnly,
+ noMulticast,
+ ipv6OtherStatefulCfg,
+ netbiosOverTcpipEnabled,
+ ipv4Enabled,
+ ipv6Enabled,
+ ipv6ManagedAddrCfgSup};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &eflags) );
+ }
+
+ return eflags;
+}
+#endif // __WIN32__
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_unicast_addrs(ErlNifEnv* env,
+ IP_ADAPTER_UNICAST_ADDRESS* firstP)
+{
+ IP_ADAPTER_UNICAST_ADDRESS* tmp = firstP;
+ SocketTArray ta = TARRAY_CREATE(16);
+ ERL_NIF_TERM eaddrs;
+
+
+ while (tmp != NULL) {
+ TARRAY_ADD(ta, encode_adapter_unicast_addr(env, tmp));
+ tmp = tmp->Next;
+ }
+
+ TARRAY_TOLIST(ta, env, &eaddrs);
+
+ return eaddrs;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * unicast_address() ::
+ * #{flags := #{dns_eligible := boolean(),
+ * transient := boolean()},
+ * addr := socket:address(),
+ * prefix_origin := ip_prefix_origin(),
+ * suffix_origin := ip_suffix_origin(),
+ * dad_state := ip_dad_state(),
+ * valid_lifetime := ulong(),
+ * preferred_lifetime := ulong(),
+ * lease_lifetime := ulong(),
+ * on_link_prefix_length := uint8()}
+ */
+static
+ERL_NIF_TERM encode_adapter_unicast_addr(ErlNifEnv* env,
+ IP_ADAPTER_UNICAST_ADDRESS* addrP)
+{
+ ERL_NIF_TERM eflags, esa, eporig, esorig, edstate, evlt, eplt, ellt;
+ /* ERL_NIF_TERM eplen; - Not on XP */
+ ERL_NIF_TERM eua;
+
+ eflags = encode_adapter_unicast_addr_flags(env, addrP->Flags);
+ esa = encode_adapter_unicast_addr_sockaddr(env,
+ addrP->Address.lpSockaddr);
+ eporig = encode_adapter_unicast_addr_porig(env, addrP->PrefixOrigin);
+ esorig = encode_adapter_unicast_addr_sorig(env, addrP->SuffixOrigin);
+ edstate = encode_adapter_unicast_addr_dad_state(env, addrP->DadState);
+ evlt = MKUL(env, addrP->ValidLifetime);
+ eplt = MKUL(env, addrP->PreferredLifetime);
+ ellt = MKUL(env, addrP->LeaseLifetime);
+ /* eplen = MKUI(env, addrP->OnLinkPrefixLength); - Not on XP */
+
+ /*
+ if (addrP->Address.lpSockaddr->sa_family == AF_INET)
+ {
+ struct sockaddr* sinP = addrP->Address.lpSockaddr;
+ ERL_NIF_TERM keys[] = {esock_atom_flags,
+ esock_atom_addr,
+ MKA(env, "raw_addr"),
+ MKA(env, "raw_addr_ntohl"),
+ atom_prefix_origin,
+ atom_suffix_origin,
+ atom_dad_state,
+ atom_valid_lifetime,
+ atom_preferred_lifetime,
+ atom_lease_lifetime
+ };
+ ERL_NIF_TERM vals[] = {eflags,
+ esa,
+ MKUI(env, (DWORD) (((struct sockaddr_in *)sinP)->sin_addr.s_addr)),
+ MKUI(env, ntohl((DWORD) (((struct sockaddr_in *)sinP)->sin_addr.s_addr))),
+ eporig,
+ esorig,
+ edstate,
+ evlt,
+ eplt,
+ ellt
+ };
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &eua) );
+
+ } else
+ */
+ {
+ ERL_NIF_TERM keys[] = {esock_atom_flags,
+ esock_atom_addr,
+ atom_prefix_origin,
+ atom_suffix_origin,
+ atom_dad_state,
+ atom_valid_lifetime,
+ atom_preferred_lifetime,
+ atom_lease_lifetime/* ,
+ on_link_prefix_length
+ Not on XP */
+ };
+ ERL_NIF_TERM vals[] = {eflags,
+ esa,
+ eporig,
+ esorig,
+ edstate,
+ evlt,
+ eplt,
+ ellt/*,
+ eplen
+ Not pn XP */
+ };
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &eua) );
+
+ }
+
+ return eua;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_unicast_addr_flags(ErlNifEnv* env,
+ DWORD flags)
+{
+ ERL_NIF_TERM map;
+ ERL_NIF_TERM dnsEl = BOOL2ATOM(flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE);
+ ERL_NIF_TERM trans = BOOL2ATOM(flags & IP_ADAPTER_ADDRESS_TRANSIENT);
+ ERL_NIF_TERM keys[] = {atom_dns_eligible, atom_transient};
+ ERL_NIF_TERM vals[] = {dnsEl, trans};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &map) );
+
+ return map;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_unicast_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP)
+{
+ return encode_sockaddr(env, addrP);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_unicast_addr_porig(ErlNifEnv* env,
+ IP_PREFIX_ORIGIN porig)
+{
+ ERL_NIF_TERM eporig;
+
+ switch (porig) {
+ case IpPrefixOriginOther:
+ eporig = atom_other;
+ break;
+
+ case IpPrefixOriginManual:
+ eporig = atom_manual;
+ break;
+
+ case IpPrefixOriginWellKnown:
+ eporig = atom_well_known;
+ break;
+
+ case IpPrefixOriginDhcp:
+ eporig = atom_dhcp;
+ break;
+
+ case IpPrefixOriginRouterAdvertisement:
+ eporig = atom_router_advertisement;
+ break;
+
+ case IpPrefixOriginUnchanged:
+ eporig = atom_unchanged;
+ break;
+
+ default:
+ eporig = MKI(env, (int) porig);
+ break;
+ }
+
+ return eporig;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_unicast_addr_sorig(ErlNifEnv* env,
+ IP_SUFFIX_ORIGIN sorig)
+{
+ ERL_NIF_TERM esorig;
+
+ switch (sorig) {
+ case IpSuffixOriginOther:
+ esorig = atom_other;
+ break;
+
+ case IpSuffixOriginManual:
+ esorig = atom_manual;
+ break;
+
+ case IpSuffixOriginWellKnown:
+ esorig = atom_well_known;
+ break;
+
+ case IpSuffixOriginDhcp:
+ esorig = atom_dhcp;
+ break;
+
+ case IpSuffixOriginLinkLayerAddress:
+ esorig = atom_link_layer_address;
+ break;
+
+ case IpSuffixOriginRandom:
+ esorig = atom_random;
+ break;
+
+ case IpSuffixOriginUnchanged:
+ esorig = atom_unchanged;
+ break;
+
+ default:
+ esorig = MKI(env, (int) sorig);
+ break;
+ }
+
+ return esorig;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_unicast_addr_dad_state(ErlNifEnv* env,
+ IP_DAD_STATE dstate)
+{
+ ERL_NIF_TERM edstate;
+
+ switch (dstate) {
+ case IpDadStateInvalid:
+ edstate = atom_invalid;
+ break;
+
+ case IpDadStateTentative:
+ edstate = atom_tentative;
+ break;
+
+ case IpDadStateDuplicate:
+ edstate = atom_duplicate;
+ break;
+
+ case IpDadStateDeprecated:
+ edstate = atom_deprecated;
+ break;
+
+ case IpDadStatePreferred:
+ edstate = atom_preferred;
+ break;
+
+ default:
+ edstate = MKI(env, (int) dstate);
+ break;
+ }
+
+ return edstate;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_anycast_addrs(ErlNifEnv* env,
+ IP_ADAPTER_ANYCAST_ADDRESS* firstP)
+{
+ IP_ADAPTER_ANYCAST_ADDRESS* tmp = firstP;
+ SocketTArray ta = TARRAY_CREATE(16);
+ ERL_NIF_TERM eaddrs;
+
+
+ while (tmp != NULL) {
+ TARRAY_ADD(ta, encode_adapter_anycast_addr(env, tmp));
+ tmp = tmp->Next;
+ }
+
+ TARRAY_TOLIST(ta, env, &eaddrs);
+
+ return eaddrs;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * anycast_address() ::
+ * #{flags := #{dns_eligible := boolean(),
+ * transient := boolean()},
+ * addr := socket:address()}
+ */
+static
+ERL_NIF_TERM encode_adapter_anycast_addr(ErlNifEnv* env,
+ IP_ADAPTER_ANYCAST_ADDRESS* addrP)
+{
+ ERL_NIF_TERM eflags, esa;
+ ERL_NIF_TERM eaa;
+
+ eflags = encode_adapter_anycast_addr_flags(env, addrP->Flags);
+ esa = encode_adapter_anycast_addr_sockaddr(env,
+ addrP->Address.lpSockaddr);
+ {
+ ERL_NIF_TERM keys[] = {esock_atom_flags,
+ esock_atom_addr};
+ ERL_NIF_TERM vals[] = {eflags,
+ esa};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &eaa) );
+
+ }
+
+ return eaa;
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_anycast_addr_flags(ErlNifEnv* env,
+ DWORD flags)
+{
+ return encode_adapter_unicast_addr_flags(env, flags);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_anycast_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP)
+{
+ return encode_sockaddr(env, addrP);
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_multicast_addrs(ErlNifEnv* env,
+ IP_ADAPTER_MULTICAST_ADDRESS* firstP)
+{
+ IP_ADAPTER_MULTICAST_ADDRESS* tmp = firstP;
+ SocketTArray ta = TARRAY_CREATE(16);
+ ERL_NIF_TERM eaddrs;
+
+ while (tmp != NULL) {
+ TARRAY_ADD(ta, encode_adapter_multicast_addr(env, tmp));
+ tmp = tmp->Next;
+ }
+
+ TARRAY_TOLIST(ta, env, &eaddrs);
+
+ return eaddrs;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * multicast_address() ::
+ * #{flags := #{dns_eligible := boolean(),
+ * transient := boolean()},
+ * addr := socket:address()}
+ */
+static
+ERL_NIF_TERM encode_adapter_multicast_addr(ErlNifEnv* env,
+ IP_ADAPTER_MULTICAST_ADDRESS* addrP)
+{
+ ERL_NIF_TERM eflags, esa;
+ ERL_NIF_TERM ema;
+
+ eflags = encode_adapter_multicast_addr_flags(env, addrP->Flags);
+ esa = encode_adapter_multicast_addr_sockaddr(env,
+ addrP->Address.lpSockaddr);
+ {
+ ERL_NIF_TERM keys[] = {esock_atom_flags,
+ esock_atom_addr};
+ ERL_NIF_TERM vals[] = {eflags,
+ esa};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &ema) );
+
+ }
+
+ return ema;
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_multicast_addr_flags(ErlNifEnv* env,
+ DWORD flags)
+{
+ return encode_adapter_unicast_addr_flags(env, flags);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_multicast_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP)
+{
+ return encode_sockaddr(env, addrP);
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_dns_server_addrs(ErlNifEnv* env,
+ IP_ADAPTER_DNS_SERVER_ADDRESS* firstP)
+{
+ IP_ADAPTER_DNS_SERVER_ADDRESS* tmp = firstP;
+ SocketTArray ta = TARRAY_CREATE(16);
+ ERL_NIF_TERM eaddrs;
+
+ while (tmp != NULL) {
+ TARRAY_ADD(ta, encode_adapter_dns_server_addr(env, tmp));
+ tmp = tmp->Next;
+ }
+
+ TARRAY_TOLIST(ta, env, &eaddrs);
+
+ return eaddrs;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * dns_server_address() ::
+ * #{addr := socket:address()}
+ */
+static
+ERL_NIF_TERM encode_adapter_dns_server_addr(ErlNifEnv* env,
+ IP_ADAPTER_DNS_SERVER_ADDRESS* addrP)
+{
+ ERL_NIF_TERM esa;
+ ERL_NIF_TERM edsa;
+
+ esa = encode_adapter_dns_server_addr_sockaddr(env,
+ addrP->Address.lpSockaddr);
+ {
+ ERL_NIF_TERM keys[] = {esock_atom_addr};
+ ERL_NIF_TERM vals[] = {esa};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &edsa) );
+
+ }
+
+ return edsa;
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_dns_server_addr_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP)
+{
+ return encode_sockaddr(env, addrP);
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_if_oper_status(ErlNifEnv* env,
+ DWORD status)
+{
+ ERL_NIF_TERM estatus;
+
+ switch (status) {
+ case IfOperStatusUp:
+ estatus = esock_atom_up;
+ break;
+ case IfOperStatusDown:
+ estatus = atom_down;
+ break;
+ case IfOperStatusTesting:
+ estatus = atom_testing;
+ break;
+ case IfOperStatusUnknown:
+ estatus = atom_unknown;
+ break;
+ case IfOperStatusDormant:
+ estatus = esock_atom_dormant;
+ break;
+ case IfOperStatusNotPresent:
+ estatus = atom_not_present;
+ break;
+ case IfOperStatusLowerLayerDown:
+ estatus = atom_lower_layer_down;
+ break;
+ default:
+ estatus = MKUI(env, status);
+ break;
+ }
+
+ return estatus;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_zone_indices(ErlNifEnv* env,
+ DWORD* zoneIndices,
+ DWORD len)
+{
+ SocketTArray ta = TARRAY_CREATE(len);
+ DWORD i;
+ ERL_NIF_TERM ezi;
+
+ for (i = 0; i < len; i++) {
+ TARRAY_ADD(ta, MKUI(env, zoneIndices[i]));
+ }
+
+ TARRAY_TOLIST(ta, env, &ezi);
+
+ return ezi;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_prefixes(ErlNifEnv* env,
+ IP_ADAPTER_PREFIX* firstP)
+{
+ IP_ADAPTER_PREFIX* tmp = firstP;
+ SocketTArray ta = TARRAY_CREATE(16);
+ ERL_NIF_TERM eprefs;
+
+ while (tmp != NULL) {
+ TARRAY_ADD(ta, encode_adapter_prefix(env, tmp));
+ tmp = tmp->Next;
+ }
+
+ TARRAY_TOLIST(ta, env, &eprefs);
+
+ return eprefs;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * prerix() ::
+ * #{addr := socket:address(),
+ * length := non_neg_integer()}
+ */
+static
+ERL_NIF_TERM encode_adapter_prefix(ErlNifEnv* env,
+ IP_ADAPTER_PREFIX* prefP)
+{
+ ERL_NIF_TERM esa, eplen;
+ ERL_NIF_TERM epref;
+
+ esa = encode_adapter_prefix_sockaddr(env, prefP->Address.lpSockaddr);
+ eplen = MKUI(env, prefP->PrefixLength);
+ /*
+ if (prefP->Address.lpSockaddr->sa_family == AF_INET)
+ {
+ struct sockaddr* sinP = prefP->Address.lpSockaddr;
+ ERL_NIF_TERM keys[] = {esock_atom_addr,
+ atom_length,
+ MKA(env, "raw_addr"),
+ MKA(env, "raw_addr_ntohl")};
+ ERL_NIF_TERM vals[] =
+ {esa, eplen,
+ MKUI(env, (DWORD) (((struct sockaddr_in *)sinP)->sin_addr.s_addr)),
+ MKUI(env, ntohl((DWORD) (((struct sockaddr_in *)sinP)->sin_addr.s_addr)))};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &epref) );
+ } else
+ */
+ {
+ ERL_NIF_TERM keys[] = {esock_atom_addr, atom_length};
+ ERL_NIF_TERM vals[] = {esa, eplen};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &epref) );
+
+ }
+
+ return epref;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_prefix_sockaddr(ErlNifEnv* env,
+ struct sockaddr* addrP)
+{
+ return encode_sockaddr(env, addrP);
+}
+#endif // __WIN32__
+
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_adapter_encode_name(ErlNifEnv* env, WCHAR* name)
+{
+ return encode_wchar(env, name);
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_adapter_encode_friendly_name(ErlNifEnv* env, WCHAR* fname)
+{
+ return encode_wchar(env, fname);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_adapter_index_map_name(ErlNifEnv* env, WCHAR* name)
+{
+ return encode_wchar(env, name);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+void make_adapter_index_map(ErlNifEnv* env,
+ ERL_NIF_TERM eindex,
+ ERL_NIF_TERM ename,
+ ERL_NIF_TERM* emap)
+{
+ ERL_NIF_TERM keys[2];
+ ERL_NIF_TERM vals[2];
+ size_t len = NUM(keys); // Just in case...
+
+ /* Index */
+ NDBG( ("NET", "make_adapter_index_map -> index: %T\r\n", eindex) );
+ keys[0] = atom_index;
+ vals[0] = eindex;
+
+ /* Name */
+ NDBG( ("NET", "make_adapter_index_map -> name: %T\r\n", ename) );
+ keys[1] = esock_atom_name;
+ vals[1] = ename;
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, len, emap) );
+}
+#endif // __WIN32__
+
+
+
+/* ----------------------------------------------------------------------
+ * nif_get_if_entry
+ *
+ * Description:
+ * Get If Entry
+ * This is a windows only function!
+ *
+ * Arguments:
+ * Args - A way to pass arguments.
+ * Currently only used for: index and debug:
+ * #{index := non_neg_integer(),
+ * debug := boolean() (optional)}
+ *
+ * Results:
+ * {ok, mib_if_row()} | {error, Reason :: term()}
+ */
+static
+ERL_NIF_TERM nif_get_if_entry(ErlNifEnv* env,
+ int argc,
+ const ERL_NIF_TERM argv[])
+{
+#if !defined(__WIN32__)
+ return enif_raise_exception(env, MKA(env, "notsup"));
+#else
+ ERL_NIF_TERM result, eargs;
+ DWORD index;
+ BOOLEAN_T dbg;
+
+ NDBG( ("NET", "nif_get_if_entry -> entry (%d)\r\n", argc) );
+
+ if ((argc != 1) ||
+ !IS_MAP(env, argv[0])) {
+ return enif_make_badarg(env);
+ }
+ eargs = argv[0];
+
+ if (!enet_get_if_entry_args_index(env, eargs, &index))
+ return enif_make_badarg(env);
+
+ dbg = enet_get_if_entry_args_debug(env, eargs);
+
+ result = enet_get_if_entry(env, dbg, index);
+
+ NDBG2( dbg,
+ ("NET",
+ "nif_get_if_entry -> done when result: "
+ "\r\n %T\r\n", result) );
+
+ return result;
+#endif
+}
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_if_entry_args_index(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs,
+ DWORD* index)
+{
+ ERL_NIF_TERM key = atom_index;
+ ERL_NIF_TERM eval;
+ DWORD val;
+
+ if (!GET_MAP_VAL(env, eargs, key, &eval)) {
+ return FALSE;
+ } else {
+ if (!IS_NUM(env, eval))
+ return FALSE;
+
+ if (!GET_UINT(env, eval, &val))
+ return FALSE;
+
+ *index = val;
+ return TRUE;
+ }
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_if_entry_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs)
+{
+ return get_debug(env, eargs);
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_get_if_entry(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ DWORD index)
+{
+ DWORD ret;
+ MIB_IFROW ifRow;
+ ERL_NIF_TERM eifRow, result;
+
+ NDBG2( dbg,
+ ("NET", "nif_get_if_entry -> entry with"
+ "\r\n index: %d\r\n", index) );
+
+ sys_memzero(&ifRow, sizeof(ifRow));
+ ifRow.dwIndex = index;
+ ret = GetIfEntry(&ifRow);
+
+ NDBG2( dbg,
+ ("NET", "nif_get_if_entry -> get-if-entru result:"
+ "\r\n %d\r\n", ret) );
+
+ switch (ret) {
+ /* Success */
+ case NO_ERROR:
+ eifRow = enet_if_row_encode(env, dbg, &ifRow);
+ result = esock_make_ok2(env, eifRow);
+ break;
+
+ /* Known errors */
+ case ERROR_CAN_NOT_COMPLETE:
+ result = esock_make_error(env, atom_can_not_complete);
+ break;
+ case ERROR_INVALID_DATA:
+ result = esock_make_error(env, atom_invalid_data);
+ break;
+ case ERROR_INVALID_PARAMETER:
+ result = esock_make_error(env, atom_invalid_parameter);
+ break;
+ case ERROR_NOT_FOUND:
+ result = esock_make_error(env, esock_atom_not_found);
+ break;
+ case ERROR_NOT_SUPPORTED:
+ result = esock_make_error(env, atom_not_supported);
+ break;
+
+ /* Other errors */
+ default:
+ result = esock_make_error(env, MKI(env, ret));
+ break;
+ }
+
+ NDBG2( dbg,
+ ("NET", "nif_get_if_entry -> done when:"
+ "\r\n result: %T\r\n", result) );
+
+ return result;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+// Returns: mib_if_row()
+static
+ERL_NIF_TERM enet_if_row_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ MIB_IFROW* rowP)
+{
+ ERL_NIF_TERM eName, eIndex, eType, eMtu, eSpeed, ePhuysAddr, eAdminStatus;
+ ERL_NIF_TERM eOperStatus, eLastChange, eInOctets, eInUcastPkts;
+ ERL_NIF_TERM eInNUcastPkts, eInDiscards, eInError, eInUnknownProtos;
+ ERL_NIF_TERM eOutOcts, eOutUcastPkts, eOutNUcastPkts, eOutDiscards;
+ ERL_NIF_TERM eOutErrors, eOutQLen, eDescr;
+ ERL_NIF_TERM erow;
+
+ NDBG2( dbg, ("NET", "enet_if_row_encode -> entry\r\n") );
+
+ eName = encode_wchar(env, rowP->wszName);
+ eIndex = MKUI(env, rowP->dwIndex);
+ eType = encode_if_type(env, rowP->dwType);
+ eMtu = MKUI(env, rowP->dwMtu);
+ eSpeed = MKUI(env, rowP->dwSpeed);
+ ePhuysAddr = encode_if_row_phys_address(env,
+ rowP->dwPhysAddrLen,
+ rowP->bPhysAddr);
+ eAdminStatus = encode_if_admin_status(env, rowP->dwAdminStatus);
+ eOperStatus = encode_internal_if_oper_status(env, rowP->dwOperStatus);
+ eLastChange = MKUI(env, rowP->dwLastChange);
+ eInOctets = MKUI(env, rowP->dwInOctets);
+ eInUcastPkts = MKUI(env, rowP->dwInUcastPkts);
+ eInNUcastPkts = MKUI(env, rowP->dwInNUcastPkts);
+ eInDiscards = MKUI(env, rowP->dwInDiscards);
+ eInError = MKUI(env, rowP->dwInErrors);
+ eInUnknownProtos = MKUI(env, rowP->dwInUnknownProtos);
+ eOutOcts = MKUI(env, rowP->dwOutOctets);
+ eOutUcastPkts = MKUI(env, rowP->dwOutUcastPkts);
+ eOutNUcastPkts = MKUI(env, rowP->dwOutNUcastPkts);
+ eOutDiscards = MKUI(env, rowP->dwOutDiscards);
+ eOutErrors = MKUI(env, rowP->dwOutErrors);
+ eOutQLen = MKUI(env, rowP->dwOutQLen);
+ eDescr = encode_if_row_description(env,
+ rowP->dwDescrLen,
+ rowP->bDescr);
+ {
+ ERL_NIF_TERM keys[] = {esock_atom_name,
+ atom_index,
+ esock_atom_type,
+ esock_atom_mtu,
+ atom_speed,
+ atom_phys_addr,
+ atom_admin_status,
+ atom_internal_oper_status,
+ atom_last_change,
+ atom_in_octets,
+ atom_in_ucast_pkts,
+ atom_in_nucast_pkts,
+ atom_in_discards,
+ atom_in_errors,
+ atom_in_unknown_protos,
+ atom_out_octets,
+ atom_out_ucast_pkts,
+ atom_out_nucast_pkts,
+ atom_out_discards,
+ atom_out_errors,
+ atom_out_qlen,
+ atom_description};
+ ERL_NIF_TERM vals[] = {eName,
+ eIndex,
+ eType,
+ eMtu,
+ eSpeed,
+ ePhuysAddr,
+ eAdminStatus,
+ eOperStatus,
+ eLastChange,
+ eInOctets,
+ eInUcastPkts,
+ eInNUcastPkts,
+ eInDiscards,
+ eInError,
+ eInUnknownProtos,
+ eOutOcts,
+ eOutUcastPkts,
+ eOutNUcastPkts,
+ eOutDiscards,
+ eOutErrors,
+ eOutQLen,
+ eDescr};
+ size_t numKeys = NUM(keys);
+ size_t numVals = NUM(vals);
+
+ ESOCK_ASSERT( numKeys == numVals );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, &erow) );
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_if_row_encode -> done with:"
+ "\r\n result: %T"
+ "\r\n", erow) );
+
+ return erow;
+
+}
+#endif
+
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_if_type(ErlNifEnv* env,
+ DWORD type)
+{
+ ERL_NIF_TERM etype;
+
+ switch (type) {
+ case IF_TYPE_OTHER:
+ etype = atom_other;
+ break;
+ case IF_TYPE_ETHERNET_CSMACD:
+ etype = atom_ethernet_csmacd;
+ break;
+ case IF_TYPE_ISO88025_TOKENRING:
+ etype = atom_iso88025_tokenring;
+ break;
+ case IF_TYPE_FDDI:
+ etype = atom_fddi;
+ break;
+ case IF_TYPE_PPP:
+ etype = atom_ppp;
+ break;
+ case IF_TYPE_SOFTWARE_LOOPBACK:
+ etype = atom_software_loopback;
+ break;
+ case IF_TYPE_ATM:
+ etype = atom_atm;
+ break;
+ case IF_TYPE_IEEE80211:
+ etype = atom_ieee80211;
+ break;
+ case IF_TYPE_TUNNEL:
+ etype = atom_tunnel;
+ break;
+ case IF_TYPE_IEEE1394:
+ etype = atom_ieee1394;
+ break;
+ case IF_TYPE_IEEE80216_WMAN:
+ etype = atom_ieee80216_wman;
+ break;
+ case IF_TYPE_WWANPP:
+ etype = atom_wwanpp;
+ break;
+ case IF_TYPE_WWANPP2:
+ etype = atom_wwanpp2;
+ break;
+ default:
+ etype = MKUI(env, type);
+ break;
+ }
+
+ return etype;
+
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * The description is defined as a UCHAR array with a *max* length
+ * of MAXLEN_IFDESCR. But the actual length is defined by the
+ * dwDescrLen field.
+ * The documentation does not specify that its a NULL terminated
+ * string, but in practice that is what it is. But, if the string
+ * *is* MAXLEN_IFDESCR there is no room for a NULL terminator...
+ * So, just to be on the safe side we copy the text into a buffer
+ * of length = len + 1 and add an extra NULL character at the last
+ * position. Then we can handle the it as any NULL terminated string.
+ */
+static
+ERL_NIF_TERM encode_if_row_description(ErlNifEnv* env,
+ DWORD len,
+ UCHAR* buf)
+{
+ ERL_NIF_TERM edesc;
+ UCHAR* tmp = MALLOC(len + 1);
+
+ ESOCK_ASSERT( tmp != NULL );
+
+ sys_memcpy(tmp, buf, len);
+ tmp[len] = 0;
+
+ edesc = MKS(env, tmp);
+
+ FREE(tmp);
+
+ return edesc;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_if_admin_status(ErlNifEnv* env,
+ DWORD status)
+{
+ ERL_NIF_TERM estatus;
+
+ switch (status) {
+ case IF_OPER_STATUS_NON_OPERATIONAL:
+ estatus = atom_non_operational;
+ break;
+ case IF_OPER_STATUS_UNREACHABLE:
+ estatus = atom_unreachable;
+ break;
+ case IF_OPER_STATUS_DISCONNECTED:
+ estatus = atom_disconnected;
+ break;
+ case IF_OPER_STATUS_CONNECTING:
+ estatus = esock_atom_connecting;
+ break;
+ case IF_OPER_STATUS_CONNECTED:
+ estatus = esock_atom_connected;
+ break;
+ case IF_OPER_STATUS_OPERATIONAL:
+ estatus = atom_operational;
+ break;
+ default:
+ estatus = MKUI(env, status);
+ break;
+ }
+
+ return estatus;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_internal_if_oper_status(ErlNifEnv* env,
+ DWORD status)
+{
+ ERL_NIF_TERM estatus;
+
+ switch (status) {
+ case IF_OPER_STATUS_NON_OPERATIONAL:
+ estatus = atom_non_operational;
+ break;
+ case IF_OPER_STATUS_UNREACHABLE:
+ estatus = atom_unreachable;
+ break;
+ case IF_OPER_STATUS_DISCONNECTED:
+ estatus = atom_disconnected;
+ break;
+ case IF_OPER_STATUS_CONNECTING:
+ estatus = esock_atom_connecting;
+ break;
+ case IF_OPER_STATUS_CONNECTED:
+ estatus = esock_atom_connected;
+ break;
+ case IF_OPER_STATUS_OPERATIONAL:
+ estatus = atom_operational;
+ break;
+ default:
+ estatus = MKUI(env, status);
+ break;
+ }
+
+ return estatus;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_if_row_phys_address(ErlNifEnv* env,
+ DWORD len,
+ UCHAR* buf)
+{
+ return encode_uchar(env, len, buf);
+}
+#endif // __WIN32__
+
+
+
+/* ----------------------------------------------------------------------
+ * nif_get_interface_info
+ *
+ * Description:
+ * Get interface info table (only IPv4 interfaces)
+ * This is a windows only function!
+ *
+ * Physical Interfaces?
+ *
+ * Arguments:
+ * Args - A way to pass arguments.
+ * Currently only used for debug.
+ *
+ * Results:
+ * {ok, [ip_adapter_index_map()]} | {error, Reason :: term()}
+ */
+
+static
+ERL_NIF_TERM nif_get_interface_info(ErlNifEnv* env,
+ int argc,
+ const ERL_NIF_TERM argv[])
+{
+#if !defined(__WIN32__)
+ return enif_raise_exception(env, MKA(env, "notsup"));
+#else
+ ERL_NIF_TERM result, eargs;
+ BOOLEAN_T dbg;
+
+ NDBG( ("NET", "nif_get_interface_info -> entry (%d)\r\n", argc) );
+
+ if ((argc != 1) ||
+ !IS_MAP(env, argv[0])) {
+ return enif_make_badarg(env);
+ }
+ eargs = argv[0];
+
+ dbg = enet_get_interface_info_args_debug(env, eargs);
+
+ result = enet_get_interface_info(env, dbg);
+
+ NDBG2( dbg,
+ ("NET",
+ "nif_get_interface_info -> done when result: "
+ "\r\n %T\r\n", result) );
+
+ return result;
+#endif
+}
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_interface_info_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs)
+{
+ return get_debug(env, eargs);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_get_interface_info(ErlNifEnv* env,
+ BOOLEAN_T dbg)
+{
+ int i;
+ DWORD ret;
+ unsigned long infoSize = 4 * 1024;
+ IP_INTERFACE_INFO* infoP = (IP_INTERFACE_INFO*) MALLOC(infoSize);
+ ERL_NIF_TERM eret, einfo, result;
+
+ for (i = 17; i; i--) {
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> try get info with: "
+ "\r\n infoSize: %d"
+ "\r\n", infoSize) );
+
+ ret = GetInterfaceInfo(infoP, &infoSize);
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> "
+ "get-info result: %d (%d)\r\n", ret, infoSize) );
+
+ if (ret == NO_ERROR) {
+ /* We are done! */
+ break;
+ } else if (ret == ERROR_INSUFFICIENT_BUFFER) {
+ /* Not large enough */
+ infoP = REALLOC(infoP, infoSize);
+ continue;
+ } else {
+ /* Failure */
+ i = 0;
+ }
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> "
+ "done when get info counter: %d\r\n", i) );
+
+ if (! i) {
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> "
+ "try encode error (%d)\r\n", ret) );
+
+ FREE(infoP);
+
+ switch (ret) {
+ case ERROR_INSUFFICIENT_BUFFER:
+ eret = atom_insufficient_buffer;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ eret = atom_invalid_parameter;
+ break;
+ case ERROR_NO_DATA:
+ eret = atom_no_data;
+ break;
+ case ERROR_NOT_SUPPORTED:
+ eret = atom_not_supported;
+ break;
+ default:
+ eret = MKI(env, ret);
+ break;
+ }
+
+ result = esock_make_error(env, eret);
+
+ } else {
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> try encode info\r\n") );
+
+ einfo = enet_interface_info_encode(env, dbg, infoP);
+ result = esock_make_ok2(env, einfo);
+
+ FREE(infoP);
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> done with:"
+ "\r\n result: %T"
+ "\r\n", result) );
+
+ return result;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+// Returns: [#{index := integer(), name := string()}]
+static
+ERL_NIF_TERM enet_interface_info_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_INTERFACE_INFO* infoP)
+{
+ ERL_NIF_TERM result;
+ LONG num = infoP->NumAdapters;
+
+ NDBG2( dbg,
+ ("NET", "enet_interface_info_encode -> entry with"
+ "\r\n num: %d"
+ "\r\n", num) );
+
+ if (num > 0) {
+ ERL_NIF_TERM* array = MALLOC(num * sizeof(ERL_NIF_TERM));
+ LONG i = 0;
+
+ while (i < num) {
+ ERL_NIF_TERM entry;
+
+ NDBG2( dbg,
+ ("NET", "enet_interface_info_encode -> "
+ "try encode adapter %d"
+ "\r\n", i) );
+
+ encode_adapter_index_map(env, dbg, &infoP->Adapter[i], &entry);
+
+ array[i] = entry;
+ i++;
+ }
+
+ result = MKLA(env, array, num);
+ FREE(array);
+
+ } else {
+ result = MKEL(env);
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_interface_info -> done with:"
+ "\r\n result: %T"
+ "\r\n", result) );
+
+ return result;
+
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * ip_adapter_index_map() :: #{name :: string(),
+ * index :: non_neg_integer()}
+ */
+static
+void encode_adapter_index_map(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ IP_ADAPTER_INDEX_MAP* adapterP,
+ ERL_NIF_TERM* eadapter)
+{
+ ERL_NIF_TERM eindex = MKI(env, adapterP->Index);
+ ERL_NIF_TERM ename = encode_adapter_index_map_name(env, adapterP->Name);
+ ERL_NIF_TERM map;
+
+ NDBG2( dbg,
+ ("NET", "encode_adapter_index_map -> map fields: "
+ "\r\n index: %T"
+ "\r\n name: %T"
+ "\r\n", eindex, ename) );
+
+ make_adapter_index_map(env, eindex, ename, &map);
+
+ NDBG2( dbg,
+ ("NET", "encode_adapter_index_map -> encoded map: %T\r\n", map) );
+
+ *eadapter = map;
+}
+#endif // __WIN32__
+
+
+
+/* ----------------------------------------------------------------------
+ * nif_get_ip_address_table
+ *
+ * Description:
+ * Get ip address table table.
+ * This is a windows only function!
+ *
+ * Active Interfaces?
+ *
+ * Arguments:
+ * Args - A way to pass arguments.
+ * Currently only used for debug.
+ *
+ * Returns:
+ * {ok, [mib_ip_address_row()]} | {error, Reason :: term()}
+ */
+
+static
+ERL_NIF_TERM nif_get_ip_address_table(ErlNifEnv* env,
+ int argc,
+ const ERL_NIF_TERM argv[])
+{
+#if !defined(__WIN32__)
+ return enif_raise_exception(env, MKA(env, "notsup"));
+#else
+ ERL_NIF_TERM result, eargs;
+ BOOLEAN_T dbg;
+
+ NDBG( ("NET", "nif_get_ip_address_table -> entry (%d)\r\n", argc) );
+
+ if ((argc != 1) ||
+ !IS_MAP(env, argv[0])) {
+ return enif_make_badarg(env);
+ }
+ eargs = argv[0];
+
+ dbg = enet_get_ip_address_table_args_debug(env, eargs);
+
+ result = enet_get_ip_address_table(env, dbg);
+
+ NDBG2( dbg,
+ ("NET",
+ "nif_get_ip_address_table -> done when result: "
+ "\r\n %T\r\n", result) );
+
+ return result;
+#endif
+}
+
+
+
+#if defined(__WIN32__)
+static
+BOOLEAN_T enet_get_ip_address_table_args_debug(ErlNifEnv* env,
+ const ERL_NIF_TERM eargs)
+{
+ return get_debug(env, eargs);
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM enet_get_ip_address_table(ErlNifEnv* env,
+ BOOLEAN_T dbg)
+{
+ int i;
+ DWORD ret;
+ /* The table is *not* just an array of 'row',
+ * but that is the significant part, so...
+ */
+ unsigned long tabSize = 16*sizeof(MIB_IPADDRROW);
+ MIB_IPADDRTABLE* ipAddrTabP = (MIB_IPADDRTABLE*) MALLOC(tabSize);
+ ERL_NIF_TERM eret, etable, result;
+
+ for (i = 17; i; i--) {
+
+ NDBG2( dbg,
+ ("NET", "enet_get_ip_address_table -> try get table with: "
+ "\r\n tabSize: %d"
+ "\r\n", tabSize) );
+
+ ret = GetIpAddrTable(ipAddrTabP, &tabSize, FALSE);
+
+ NDBG2( dbg,
+ ("NET", "enet_get_ip_address_table -> "
+ "get-tab result: %d (%d)\r\n", ret, tabSize) );
+
+ ipAddrTabP = REALLOC(ipAddrTabP, tabSize);
+ if (ret == NO_ERROR) break;
+ if (ret == ERROR_INSUFFICIENT_BUFFER) continue;
+ i = 0;
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_ip_address_table -> "
+ "done when get-tab counter: %d\r\n", i) );
+
+ if (! i) {
+
+ NDBG2( dbg,
+ ("NET",
+ "enet_get_ip_address_table -> try transform error\r\n") );
+
+ FREE(ipAddrTabP);
+
+ switch (ret) {
+ case ERROR_INSUFFICIENT_BUFFER:
+ eret = atom_insufficient_buffer;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ eret = atom_invalid_parameter;
+ break;
+ case ERROR_NOT_SUPPORTED:
+ eret = atom_not_supported;
+ break;
+ default:
+ eret = MKI(env, ret);
+ break;
+ }
+
+ result = esock_make_error(env, eret);
+
+ } else {
+
+ NDBG2( dbg,
+ ("NET",
+ "enet_get_ip_address_table -> try transform table\r\n") );
+
+ etable = enet_get_ip_address_table_encode(env, dbg, ipAddrTabP);
+ result = esock_make_ok2(env, etable);
+
+ FREE(ipAddrTabP);
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_ip_address_table -> done with:"
+ "\r\n result: %T"
+ "\r\n", result) );
+
+ return result;
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+// Returns: [row()]
+static
+ERL_NIF_TERM enet_get_ip_address_table_encode(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ MIB_IPADDRTABLE* tabP)
+{
+ ERL_NIF_TERM result;
+ LONG num = tabP->dwNumEntries;
+
+ NDBG2( dbg,
+ ("NET", "enet_get_ip_address_table_encode -> entry with"
+ "\r\n num: %d"
+ "\r\n", num) );
+
+ if (num > 0) {
+ ERL_NIF_TERM* array = MALLOC(num * sizeof(ERL_NIF_TERM));
+ LONG i = 0;
+
+ while (i < num) {
+ ERL_NIF_TERM entry;
+
+ NDBG2( dbg,
+ ("NET", "enet_interface_info_encode -> "
+ "try encode ip-address-row %d"
+ "\r\n", i) );
+
+ entry = encode_ip_address_row(env, dbg, &tabP->table[i]);
+
+ array[i] = entry;
+ i++;
+ }
+
+ result = MKLA(env, array, num);
+ FREE(array);
+
+ } else {
+ result = MKEL(env);
+ }
+
+ NDBG2( dbg,
+ ("NET", "enet_get_ip_address_table -> done with:"
+ "\r\n result: %T"
+ "\r\n", result) );
+
+ return result;
+
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+ERL_NIF_TERM encode_ip_address_row(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ MIB_IPADDRROW* rowP)
+{
+ ERL_NIF_TERM eaddr = encode_ip_address_row_addr(env,
+ dbg, "Addr",
+ rowP->dwAddr);
+ ERL_NIF_TERM eindex = MKUL(env, rowP->dwIndex);
+ ERL_NIF_TERM emask = encode_ip_address_row_addr(env,
+ dbg, "Mask",
+ rowP->dwMask);
+ ERL_NIF_TERM eBCastAddr = encode_ip_address_row_addr(env,
+ dbg, "BCaseAddr",
+ rowP->dwBCastAddr);
+ ERL_NIF_TERM eReasmSize = MKUL(env, rowP->dwReasmSize);
+ ERL_NIF_TERM map;
+
+ NDBG2( dbg,
+ ("NET", "encode_ipAddress_row_map -> map fields: "
+ "\r\n address: %T"
+ "\r\n index: %T"
+ "\r\n mask: %T"
+ "\r\n bcas-addr: %T"
+ "\r\n reasm-size: %T"
+ "\r\n", eaddr, eindex, emask, eBCastAddr, eReasmSize) );
+
+ make_ip_address_row(env, eaddr, eindex, emask, eBCastAddr, eReasmSize, &map);
+
+ NDBG2( dbg,
+ ("NET", "encode_ip_address_row -> encoded map: %T\r\n", map) );
+
+ return map;
+}
+#endif // __WIN32__
+
+
+
+#if defined(__WIN32__)
+/* Converts an *IPv4* address to an erlang term (4-tuple) */
+static
+ERL_NIF_TERM encode_ip_address_row_addr(ErlNifEnv* env,
+ BOOLEAN_T dbg,
+ const char* descr,
+ DWORD addr)
+{
+ struct in_addr a;
+ ERL_NIF_TERM ea;
+
+ NDBG2( dbg,
+ ("NET",
+ "encode_ip_address_row_addr -> entry with: "
+ "\r\n %s: %lu\r\n", descr, addr) );
+
+ a.s_addr = addr;
+
+ esock_encode_in_addr(env, &a, &ea);
+
+ return ea;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+static
+void make_ip_address_row(ErlNifEnv* env,
+ ERL_NIF_TERM eaddr,
+ ERL_NIF_TERM eindex,
+ ERL_NIF_TERM emask,
+ ERL_NIF_TERM eBCastAddr,
+ ERL_NIF_TERM eReasmSize,
+ ERL_NIF_TERM* iar)
+{
+ ERL_NIF_TERM keys[] = {esock_atom_addr,
+ atom_index,
+ atom_mask,
+ atom_bcast_addr,
+ atom_reasm_size};
+ ERL_NIF_TERM vals[] = {eaddr, eindex, emask, eBCastAddr, eReasmSize};
+ size_t numKeys = NUM(keys);
+
+ ESOCK_ASSERT( numKeys == NUM(vals) );
+
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, iar) );
+
+}
+#endif // __WIN32__
+
+
+
+
+/* ----------------------------------------------------------------------
* nif_if_name2index
*
* Description:
@@ -1792,7 +4202,23 @@ unsigned int enet_if_names_length(struct if_nameindex* p)
* A special case is when there is no flags, which is
* represented by the atom undefined.
*/
-#if !defined(__WIN32__)
+
+static
+ERL_NIF_TERM encode_sockaddr(ErlNifEnv* env, struct sockaddr* sa)
+{
+ ERL_NIF_TERM esa;
+
+ if (sa != NULL) {
+ esock_encode_sockaddr(env, (ESockAddress*) sa, -1, &esa);
+ } else {
+ esa = esock_atom_undefined;
+ }
+
+ return esa;
+}
+
+
+
static
BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env,
const ERL_NIF_TERM eflags,
@@ -1938,24 +4364,6 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env,
-static
-ERL_NIF_TERM decode_bool(ErlNifEnv* env,
- ERL_NIF_TERM ebool,
- BOOLEAN_T* ibool)
-{
- if (COMPARE(ebool, esock_atom_true) == 0) {
- *ibool = TRUE;
- return esock_atom_ok;
- } else if (COMPARE(ebool, esock_atom_false) == 0) {
- *ibool = FALSE;
- return esock_atom_ok;
- } else {
- return esock_make_error(env, esock_atom_einval);
- }
-}
-
-
-
/* Encode the address info
* The address info is a linked list och address info, which
* will result in the result being a list of zero or more length.
@@ -1994,7 +4402,7 @@ ERL_NIF_TERM encode_address_infos(ErlNifEnv* env,
-/* Calculate the length of the adress info linked list
+/* Calculate the length of the address info linked list
* The list is NULL-terminated, so the only way is to
* iterate through the list until we find next = NULL.
*/
@@ -2097,7 +4505,6 @@ void make_address_info(ErlNifEnv* env,
ESOCK_ASSERT( numKeys == NUM(vals) );
ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, ai) );
}
-#endif // if !defined(__WIN32__)
@@ -2107,8 +4514,8 @@ void make_address_info(ErlNifEnv* env,
/* We should really have another API, so that we can return errno... */
/* *** change network namespace ***
- * Retreive the current namespace and set the new.
- * Return result and previous namespace if successfull.
+ * Retrieve the current namespace and set the new.
+ * Return result and previous namespace if successful.
*/
#if !defined(__WIN32__)
static
@@ -2199,6 +4606,22 @@ BOOLEAN_T restore_network_namespace(int ns, int* err)
#endif // ifdef HAVE_SETNS
+static
+ERL_NIF_TERM decode_bool(ErlNifEnv* env,
+ ERL_NIF_TERM ebool,
+ BOOLEAN_T* ibool)
+{
+ if (COMPARE(ebool, esock_atom_true) == 0) {
+ *ibool = TRUE;
+ return esock_atom_ok;
+ } else if (COMPARE(ebool, esock_atom_false) == 0) {
+ *ibool = FALSE;
+ return esock_atom_ok;
+ } else {
+ return esock_make_error(env, esock_atom_einval);
+ }
+}
+
/* ----------------------------------------------------------------------
@@ -2261,22 +4684,97 @@ ErlNifFunc net_funcs[] =
{"nif_command", 1, nif_command, 0}, // Shall we let this be dirty?
/* get/set hostname */
- {"nif_gethostname", 0, nif_gethostname, 0},
+ {"nif_gethostname", 0, nif_gethostname, 0},
/* address and name translation in protocol-independent manner */
- {"nif_getnameinfo", 2, nif_getnameinfo, 0},
- {"nif_getaddrinfo", 3, nif_getaddrinfo, 0},
+ {"nif_getnameinfo", 2, nif_getnameinfo, 0},
+ {"nif_getaddrinfo", 3, nif_getaddrinfo, 0},
- {"nif_getifaddrs", 1, nif_getifaddrs, ERL_NIF_DIRTY_JOB_IO_BOUND},
+ {"nif_getifaddrs", 1, nif_getifaddrs, ERL_NIF_DIRTY_JOB_IO_BOUND},
+ {"nif_get_adapters_addresses", 1, nif_get_adapters_addresses, ERL_NIF_DIRTY_JOB_IO_BOUND},
+ {"nif_get_if_entry", 1, nif_get_if_entry, ERL_NIF_DIRTY_JOB_IO_BOUND},
+ {"nif_get_interface_info", 1, nif_get_interface_info, ERL_NIF_DIRTY_JOB_IO_BOUND},
+ {"nif_get_ip_address_table", 1, nif_get_ip_address_table, ERL_NIF_DIRTY_JOB_IO_BOUND},
/* Network interface (name and/or index) functions */
- {"nif_if_name2index", 1, nif_if_name2index, 0},
- {"nif_if_index2name", 1, nif_if_index2name, 0},
- {"nif_if_names", 0, nif_if_names, 0}
+ {"nif_if_name2index", 1, nif_if_name2index, 0},
+ {"nif_if_index2name", 1, nif_if_index2name, 0},
+ {"nif_if_names", 0, nif_if_names, 0}
};
-#if !defined(__WIN32__)
+#if defined(__WIN32__)
+/*
+ * The assumption is that the 'name' string is NULL terminated
+ */
+static
+ERL_NIF_TERM encode_wchar(ErlNifEnv* env, WCHAR* name)
+{
+ ERL_NIF_TERM result;
+ int len = WideCharToMultiByte(CP_UTF8, 0,
+ name, -1,
+ NULL, 0, NULL, NULL);
+
+ if (!len) {
+ result = esock_atom_undefined;
+ } else {
+ char* buf = (char*) MALLOC(len+1);
+
+ if (0 == WideCharToMultiByte(CP_UTF8, 0,
+ name, -1,
+ buf, len, NULL, NULL)) {
+ DWORD error = GetLastError();
+
+ switch (error) {
+ case ERROR_INSUFFICIENT_BUFFER:
+ result = atom_insufficient_buffer;
+ break;
+ case ERROR_INVALID_FLAGS:
+ result = atom_invalid_flags;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ result = atom_invalid_parameter;
+ break;
+ case ERROR_NO_UNICODE_TRANSLATION:
+ result = atom_no_uniconde_traslation;
+ break;
+ default:
+ result = MKI(env, error);
+ break;
+ }
+ } else {
+ result = MKS(env, buf);
+ }
+
+ FREE(buf);
+ }
+
+ return result;
+}
+#endif // __WIN32__
+
+
+#if defined(__WIN32__)
+/*
+ * This builds a binary term from an array of uchar
+ */
+static
+ERL_NIF_TERM encode_uchar(ErlNifEnv* env,
+ DWORD len,
+ UCHAR* buf)
+{
+ ERL_NIF_TERM ebuf;
+ unsigned char* p;
+
+ p = enif_make_new_binary(env, len, &ebuf);
+ ESOCK_ASSERT( p != NULL );
+ sys_memcpy(p, buf, len);
+
+ return ebuf;
+}
+#endif // __WIN32__
+
+
static
BOOLEAN_T get_debug(ErlNifEnv* env,
ERL_NIF_TERM map)
@@ -2289,7 +4787,6 @@ BOOLEAN_T get_debug(ErlNifEnv* env,
return esock_get_bool_from_map(env, map, debug, NET_NIF_DEBUG_DEFAULT);
}
-#endif
/* =======================================================================
@@ -2330,3 +4827,4 @@ LOCAL_ERROR_REASON_ATOMS
}
ERL_NIF_INIT(prim_net, net_funcs, on_load, NULL, NULL, NULL)
+#endif
diff --git a/erts/emulator/nifs/common/prim_socket_nif.c b/erts/emulator/nifs/common/prim_socket_nif.c
index 438387b9c4..4ac0fc0966 100644
--- a/erts/emulator/nifs/common/prim_socket_nif.c
+++ b/erts/emulator/nifs/common/prim_socket_nif.c
@@ -24,7 +24,8 @@
* The first function is called 'nif_<something>', e.g. nif_open.
* This does the initial validation and argument processing and then
* calls the function that does the actual work. This is called
- * 'esock_<something>'.
+ * 'esock_<something>', e.g. esock_open (actually esock_open2 or
+ * esock_open4).
* ----------------------------------------------------------------------
*
*
@@ -38,11 +39,30 @@
#define STATIC_ERLANG_NIF 1
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
+#ifndef ESOCK_ENABLE
+# include <erl_nif.h>
+
+static
+ErlNifFunc esock_funcs[] = {};
+
+static
+int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ (void)env;
+ (void)priv_data;
+ (void)load_info;
+
+ return 1;
+}
+
+ERL_NIF_INIT(prim_socket, esock_funcs, on_load, NULL, NULL, NULL)
+
+#else
+
/* If we HAVE_SCTP_H and Solaris, we need to define the following in
* order to get SCTP working:
*/
@@ -491,6 +511,9 @@ typedef int SOCKET; /* A subset of HANDLE */
#define ESOCK_GET_RESOURCE(ENV, REF, RES) \
enif_get_resource((ENV), (REF), esocks, (RES))
+#define ESOCK_MON2TERM(E, M) \
+ esock_make_monitor_term((E), (M))
+
#define ESOCK_RECV_BUFFER_COUNT_DEFAULT 0
#define ESOCK_RECV_BUFFER_SIZE_DEFAULT 8192
#define ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT 1024
@@ -3976,17 +3999,13 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(addrform); \
GLOBAL_ATOM_DECL(add_membership); \
GLOBAL_ATOM_DECL(add_source_membership); \
+ GLOBAL_ATOM_DECL(alen); \
GLOBAL_ATOM_DECL(allmulti); \
GLOBAL_ATOM_DECL(any); \
- GLOBAL_ATOM_DECL(arphrd_dlci); \
- GLOBAL_ATOM_DECL(arphrd_ether); \
- GLOBAL_ATOM_DECL(arphrd_frelay); \
- GLOBAL_ATOM_DECL(arphrd_ieee802); \
- GLOBAL_ATOM_DECL(arphrd_ieee1394); \
- GLOBAL_ATOM_DECL(arphrd_loopback); \
- GLOBAL_ATOM_DECL(arphrd_netrom); \
- GLOBAL_ATOM_DECL(arphrd_none); \
+ GLOBAL_ATOM_DECL(appletlk); \
+ GLOBAL_ATOM_DECL(arcnet); \
GLOBAL_ATOM_DECL(associnfo); \
+ GLOBAL_ATOM_DECL(atm); \
GLOBAL_ATOM_DECL(authhdr); \
GLOBAL_ATOM_DECL(auth_active_key); \
GLOBAL_ATOM_DECL(auth_asconf); \
@@ -3996,6 +4015,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(auth_level); \
GLOBAL_ATOM_DECL(autoclose); \
GLOBAL_ATOM_DECL(automedia); \
+ GLOBAL_ATOM_DECL(ax25); \
GLOBAL_ATOM_DECL(bad_data); \
GLOBAL_ATOM_DECL(bindtodevice); \
GLOBAL_ATOM_DECL(block_source); \
@@ -4010,6 +4030,8 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(confirm); \
GLOBAL_ATOM_DECL(congestion); \
GLOBAL_ATOM_DECL(connect); \
+ GLOBAL_ATOM_DECL(connected); \
+ GLOBAL_ATOM_DECL(connecting); \
GLOBAL_ATOM_DECL(context); \
GLOBAL_ATOM_DECL(cork); \
GLOBAL_ATOM_DECL(credentials); \
@@ -4022,6 +4044,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(delayed_ack_time); \
GLOBAL_ATOM_DECL(dgram); \
GLOBAL_ATOM_DECL(disable_fragments); \
+ GLOBAL_ATOM_DECL(dlci); \
GLOBAL_ATOM_DECL(domain); \
GLOBAL_ATOM_DECL(dontfrag); \
GLOBAL_ATOM_DECL(dontroute); \
@@ -4032,6 +4055,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(dying); \
GLOBAL_ATOM_DECL(dynamic); \
GLOBAL_ATOM_DECL(echo); \
+ GLOBAL_ATOM_DECL(eether); \
GLOBAL_ATOM_DECL(egp); \
GLOBAL_ATOM_DECL(enotsup); \
GLOBAL_ATOM_DECL(eor); \
@@ -4039,6 +4063,8 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(errqueue); \
GLOBAL_ATOM_DECL(esp_network_level); \
GLOBAL_ATOM_DECL(esp_trans_level); \
+ GLOBAL_ATOM_DECL(ether); \
+ GLOBAL_ATOM_DECL(eui64); \
GLOBAL_ATOM_DECL(events); \
GLOBAL_ATOM_DECL(explicit_eor); \
GLOBAL_ATOM_DECL(faith); \
@@ -4049,6 +4075,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(flowinfo); \
GLOBAL_ATOM_DECL(fragment_interleave); \
GLOBAL_ATOM_DECL(freebind); \
+ GLOBAL_ATOM_DECL(frelay); \
GLOBAL_ATOM_DECL(get_peer_addr_info); \
GLOBAL_ATOM_DECL(hatype); \
GLOBAL_ATOM_DECL(hdrincl); \
@@ -4058,11 +4085,15 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(host); \
GLOBAL_ATOM_DECL(icmp); \
GLOBAL_ATOM_DECL(icmp6); \
+ GLOBAL_ATOM_DECL(ieee802); \
+ GLOBAL_ATOM_DECL(ieee1394); \
GLOBAL_ATOM_DECL(ifindex); \
GLOBAL_ATOM_DECL(igmp); \
GLOBAL_ATOM_DECL(implink); \
+ GLOBAL_ATOM_DECL(index); \
GLOBAL_ATOM_DECL(inet); \
GLOBAL_ATOM_DECL(inet6); \
+ GLOBAL_ATOM_DECL(infiniband); \
GLOBAL_ATOM_DECL(info); \
GLOBAL_ATOM_DECL(initmsg); \
GLOBAL_ATOM_DECL(invalid); \
@@ -4088,6 +4119,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(link1); \
GLOBAL_ATOM_DECL(link2); \
GLOBAL_ATOM_DECL(local); \
+ GLOBAL_ATOM_DECL(localtlk); \
GLOBAL_ATOM_DECL(local_auth_chunks); \
GLOBAL_ATOM_DECL(loopback); \
GLOBAL_ATOM_DECL(lowdelay); \
@@ -4097,6 +4129,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(maxburst); \
GLOBAL_ATOM_DECL(maxseg); \
GLOBAL_ATOM_DECL(md5sig); \
+ GLOBAL_ATOM_DECL(metricom); \
GLOBAL_ATOM_DECL(mincost); \
GLOBAL_ATOM_DECL(minttl); \
GLOBAL_ATOM_DECL(monitor); \
@@ -4111,6 +4144,8 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(multicast_loop); \
GLOBAL_ATOM_DECL(multicast_ttl); \
GLOBAL_ATOM_DECL(name); \
+ GLOBAL_ATOM_DECL(netrom); \
+ GLOBAL_ATOM_DECL(nlen); \
GLOBAL_ATOM_DECL(noarp); \
GLOBAL_ATOM_DECL(nodelay); \
GLOBAL_ATOM_DECL(nodefrag); \
@@ -4150,6 +4185,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(primary_addr); \
GLOBAL_ATOM_DECL(priority); \
GLOBAL_ATOM_DECL(promisc); \
+ GLOBAL_ATOM_DECL(pronet); \
GLOBAL_ATOM_DECL(protocol); \
GLOBAL_ATOM_DECL(pup); \
GLOBAL_ATOM_DECL(raw); \
@@ -4197,6 +4233,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(set_peer_primary_addr); \
GLOBAL_ATOM_DECL(simplex); \
GLOBAL_ATOM_DECL(slave); \
+ GLOBAL_ATOM_DECL(slen); \
GLOBAL_ATOM_DECL(sndbuf); \
GLOBAL_ATOM_DECL(sndbufforce); \
GLOBAL_ATOM_DECL(sndlowat); \
@@ -4216,6 +4253,8 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(true); \
GLOBAL_ATOM_DECL(trunc); \
GLOBAL_ATOM_DECL(ttl); \
+ GLOBAL_ATOM_DECL(tunnel); \
+ GLOBAL_ATOM_DECL(tunnel6); \
GLOBAL_ATOM_DECL(type); \
GLOBAL_ATOM_DECL(udp); \
GLOBAL_ATOM_DECL(unblock_source); \
@@ -4228,6 +4267,7 @@ static const struct in6_addr in6addr_loopback =
GLOBAL_ATOM_DECL(user_timeout); \
GLOBAL_ATOM_DECL(use_ext_recvinfo); \
GLOBAL_ATOM_DECL(use_min_mtu); \
+ GLOBAL_ATOM_DECL(void); \
GLOBAL_ATOM_DECL(v6only)
@@ -4267,8 +4307,6 @@ ERL_NIF_TERM esock_atom_socket_tag; // This has a "special" name ('$socket')
LOCAL_ATOM_DECL(closed); \
LOCAL_ATOM_DECL(closing); \
LOCAL_ATOM_DECL(code); \
- LOCAL_ATOM_DECL(connected); \
- LOCAL_ATOM_DECL(connecting); \
LOCAL_ATOM_DECL(cookie_life); \
LOCAL_ATOM_DECL(counter_wrap); \
LOCAL_ATOM_DECL(counters); \
@@ -4859,7 +4897,7 @@ ERL_NIF_TERM esock_socket_info_state(ErlNifEnv* env,
SSDBG( descP, ("SOCKET", "esock_socket_info_state {%d} -> connecting"
"\r\n", descP->sock) );
*/
- TARRAY_ADD(estate, atom_connecting);
+ TARRAY_ADD(estate, esock_atom_connecting);
}
if ((state & ESOCK_STATE_CONNECTED) != 0) {
@@ -4867,7 +4905,7 @@ ERL_NIF_TERM esock_socket_info_state(ErlNifEnv* env,
SSDBG( descP, ("SOCKET", "esock_socket_info_state {%d} -> connected"
"\r\n", descP->sock) );
*/
- TARRAY_ADD(estate, atom_connected);
+ TARRAY_ADD(estate, esock_atom_connected);
}
if ((state & ESOCK_STATE_SELECTED) != 0) {
@@ -5791,7 +5829,7 @@ ERL_NIF_TERM esock_open2(ErlNifEnv* env,
* Before we do anything else, we try to retrieve domain, type and protocol
* This information is either present in the eopts map or if not we need
* to "get" it from the system (getsockopt).
- * Note that its not possible to get all of these on all platoforms,
+ * Note that its not possible to get all of these on all platforms,
* and in those cases the user *must* provide us with them (eopts).
*
* We try the system first (since its more reliable) and if that fails
@@ -6160,8 +6198,8 @@ BOOLEAN_T esock_open_which_protocol(SOCKET sock, int* proto)
/* We should really have another API, so that we can return errno... */
/* *** change network namespace ***
- * Retreive the current namespace and set the new.
- * Return result and previous namespace if successfull.
+ * Retrieve the current namespace and set the new.
+ * Return result and previous namespace if successful.
*/
#ifndef __WIN32__
static
@@ -6729,7 +6767,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env,
ref,
descP->currentAcceptorP,
descP->currentAcceptor.pid,
- esock_make_monitor_term(env, &descP->currentAcceptor.mon),
+ ESOCK_MON2TERM(env, &descP->currentAcceptor.mon),
descP->currentAcceptor.env,
descP->currentAcceptor.ref) );
@@ -6789,9 +6827,8 @@ ERL_NIF_TERM esock_accept(ErlNifEnv* env,
accRef, caller, save_errno);
} else {
/* We got an incoming connection */
- return
- esock_accept_listening_accept(env, descP, sockRef,
- accSock, caller);
+ return esock_accept_listening_accept(env, descP, sockRef,
+ accSock, caller);
}
} else {
@@ -6802,16 +6839,20 @@ ERL_NIF_TERM esock_accept(ErlNifEnv* env,
SSDBG( descP, ("SOCKET", "esock_accept_accepting -> check: "
"is caller current acceptor:"
- "\r\n Caller: %T"
- "\r\n Current: %T"
- "\r\n", caller, descP->currentAcceptor.pid) );
+ "\r\n Caller: %T"
+ "\r\n Current: %T"
+ "\r\n Current Mon: %T"
+ "\r\n",
+ caller,
+ descP->currentAcceptor.pid,
+ ESOCK_MON2TERM(env, &descP->currentAcceptor.mon)) );
if (COMPARE_PIDS(&descP->currentAcceptor.pid, &caller) == 0) {
SSDBG( descP,
("SOCKET",
- "esock_accept_accepting {%d} -> current acceptor\r\n",
- descP->sock) );
+ "esock_accept_accepting {%d} -> current acceptor"
+ "\r\n", descP->sock) );
return esock_accept_accepting_current(env, descP, sockRef, accRef);
@@ -6855,7 +6896,7 @@ ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env,
SSDBG( descP,
("SOCKET",
- "esock_accept_listening_error {%d} -> would block\r\n",
+ "esock_accept_listening_error {%d} -> would block - retry\r\n",
descP->sock) );
descP->currentAcceptor.pid = caller;
@@ -6868,8 +6909,20 @@ ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env,
descP->currentAcceptor.ref =
CP_TERM(descP->currentAcceptor.env, accRef);
descP->currentAcceptorP = &descP->currentAcceptor;
+
+ SSDBG( descP,
+ ("SOCKET",
+ "esock_accept_listening_error {%d} -> retry for: "
+ "\r\n Current Pid: %T"
+ "\r\n Current Mon: %T"
+ "\r\n",
+ descP->sock,
+ descP->currentAcceptor.pid,
+ ESOCK_MON2TERM(env, &descP->currentAcceptor.mon)) );
+
res = esock_accept_busy_retry(env, descP, sockRef, accRef, NULL);
} else {
+
SSDBG( descP,
("SOCKET",
"esock_accept_listening {%d} -> errno: %d\r\n",
@@ -6947,6 +7000,7 @@ ERL_NIF_TERM esock_accept_accepting_current(ErlNifEnv* env,
/* *** esock_accept_accepting_current_accept ***
+ *
* Handles when the current acceptor succeeded in its accept call -
* handle the new connection.
*/
@@ -6967,6 +7021,12 @@ ERL_NIF_TERM esock_accept_accepting_current_accept(ErlNifEnv* env,
if (esock_accept_accepted(env, descP, sockRef, accSock,
descP->currentAcceptor.pid, &res)) {
+ ESOCK_ASSERT( DEMONP("esock_accept_accepting_current_accept -> "
+ "current acceptor",
+ env, descP, &descP->currentAcceptor.mon) == 0);
+
+ MON_INIT(&descP->currentAcceptor.mon);
+
if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
@@ -7059,7 +7119,7 @@ ERL_NIF_TERM esock_accept_accepting_current_error(ErlNifEnv* env,
/* *** esock_accept_accepting_other ***
* Handles when the another acceptor makes an attempt, which
- * results (maybe) in the request beeing pushed onto the
+ * results (maybe) in the request being pushed onto the
* acceptor queue.
*/
#ifndef __WIN32__
@@ -7100,9 +7160,13 @@ ERL_NIF_TERM esock_accept_busy_retry(ErlNifEnv* env,
ESOCK_ASSERT( DEMONP("esock_accept_busy_retry - select failed",
env, descP, &descP->currentAcceptor.mon) == 0);
+
+ MON_INIT(&descP->currentAcceptor.mon);
+
/* It is very unlikely that a next acceptor will be able
- * to do anything succesful, but we will clean the queue
+ * to do anything successful, but we will clean the queue
*/
+
if (!activate_next_acceptor(env, descP, sockRef)) {
SSDBG( descP,
("SOCKET",
@@ -8353,7 +8417,7 @@ esock_sendfile(ErlNifEnv *env,
if ((res < 0) && (error == EINVAL)) {
/* On e.b SunOS 5.10 using sfv_len > file size
- * lands here - we regard this as a succesful send.
+ * lands here - we regard this as a successful send.
* All other causes for EINVAL are avoided,
* except for .sfv_fd not seekable, which would
* give bytes_sent == 0 that we would interpret
@@ -9066,7 +9130,7 @@ ERL_NIF_TERM esock_recvmsg(ErlNifEnv* env,
size_t bufSz = (bufLen != 0 ? bufLen : descP->rBufSz);
size_t ctrlSz = (ctrlLen != 0 ? ctrlLen : descP->rCtrlSz);
struct msghdr msgHdr;
- struct iovec iov[1]; // Shall we always use 1?
+ SysIOVec iov[1]; // Shall we always use 1?
ErlNifBinary data[1]; // Shall we always use 1?
ErlNifBinary ctrl;
ERL_NIF_TERM readerCheck;
@@ -9535,7 +9599,7 @@ ERL_NIF_TERM esock_finalize_close(ErlNifEnv* env,
#endif
/* This nif is executed in a dirty scheduler just so that
- * it can "hang" (whith minumum effect on the VM) while the
+ * it can "hang" (with minimum effect on the VM) while the
* kernel writes our buffers. IF we have set the linger option
* for this ({true, integer() > 0}). For this to work we must
* be blocking...
@@ -12903,7 +12967,7 @@ ERL_NIF_TERM esock_getopt_pktoptions(ErlNifEnv* env,
"\r\n", descP->sock, keys[3], vals[3]) );
}
- /* Guard agains cut-and-paste errors */
+ /* Guard against cut-and-paste errors */
ESOCK_ASSERT( numKeys == NUM(vals) );
/* Make control message header map */
@@ -13050,13 +13114,28 @@ ERL_NIF_TERM esock_sockname(ErlNifEnv* env,
if (! IS_OPEN(descP->readState))
return esock_make_error(env, atom_closed);
+ SSDBG( descP,
+ ("SOCKET", "esock_sockname {%d} -> open - try get sockname\r\n",
+ descP->sock) );
+
sys_memzero((char*) saP, sz);
if (sock_name(descP->sock, (struct sockaddr*) saP, &sz) < 0) {
return esock_make_error_errno(env, sock_errno());
} else {
ERL_NIF_TERM esa;
+ SSDBG( descP,
+ ("SOCKET", "esock_sockname {%d} -> "
+ "got sockname - try decode\r\n",
+ descP->sock) );
+
esock_encode_sockaddr(env, saP, sz, &esa);
+
+ SSDBG( descP,
+ ("SOCKET", "esock_sockname {%d} -> decoded: "
+ "\r\n %T\r\n",
+ descP->sock, esa) );
+
return esock_make_ok2(env, esa);
}
}
@@ -13128,14 +13207,29 @@ ERL_NIF_TERM esock_peername(ErlNifEnv* env,
if (! IS_OPEN(descP->readState))
return esock_make_error(env, atom_closed);
+ SSDBG( descP,
+ ("SOCKET", "esock_peername {%d} -> open - try get peername\r\n",
+ descP->sock) );
+
sys_memzero((char*) saP, sz);
if (sock_peer(descP->sock, (struct sockaddr*) saP, &sz) < 0) {
- return esock_make_error_errno(env, sock_errno());
+ return esock_make_error_errno(env, sock_errno());
} else {
- ERL_NIF_TERM esa;
+ ERL_NIF_TERM esa;
+
+ SSDBG( descP,
+ ("SOCKET", "esock_peername {%d} -> "
+ "got peername - try decode\r\n",
+ descP->sock) );
+
+ esock_encode_sockaddr(env, saP, sz, &esa);
+
+ SSDBG( descP,
+ ("SOCKET", "esock_peername {%d} -> decoded: "
+ "\r\n %T\r\n",
+ descP->sock, esa) );
- esock_encode_sockaddr(env, saP, sz, &esa);
- return esock_make_ok2(env, esa);
+ return esock_make_ok2(env, esa);
}
}
#endif // #ifndef __WIN32__
@@ -14085,9 +14179,8 @@ ERL_NIF_TERM encode_ioctl_ifraddr(ErlNifEnv* env,
struct sockaddr* addrP)
{
ERL_NIF_TERM eaddr;
- unsigned int sz = sizeof(ESockAddress);
- esock_encode_sockaddr(env, (ESockAddress*) addrP, sz, &eaddr);
+ esock_encode_sockaddr(env, (ESockAddress*) addrP, -1, &eaddr);
SSDBG( descP, ("SOCKET", "encode_ioctl_ifraddr -> done with"
"\r\n Sock Addr: %T"
@@ -14331,17 +14424,19 @@ ERL_NIF_TERM encode_ioctl_ifreq_sockaddr(ErlNifEnv* env, struct sockaddr* sa)
ERL_NIF_TERM esa;
if (sa != NULL) {
- unsigned int sz = sizeof(ESockAddress);
- esock_encode_sockaddr(env, (ESockAddress*) sa, sz, &esa);
-
+ esock_encode_sockaddr(env, (ESockAddress*) sa, -1, &esa);
+
} else {
- esa = esock_atom_undefined;
+
+ esa = esock_atom_undefined;
+
}
return esa;
}
+
/* The ifreq structure *always* contain a name
* and *one* other element. The second element
* depend on the ioctl request.
@@ -14628,6 +14723,7 @@ ERL_NIF_TERM esock_cancel_accept_current(ErlNifEnv* env,
ESOCK_ASSERT( DEMONP("esock_cancel_accept_current -> current acceptor",
env, descP, &descP->currentAcceptor.mon) == 0);
+ MON_INIT(&descP->currentAcceptor.mon);
res = esock_cancel_read_select(env, descP, descP->currentAcceptor.ref);
SSDBG( descP,
@@ -15219,7 +15315,7 @@ ERL_NIF_TERM send_check_fail(ErlNifEnv* env,
/* *** send_error_waiting_writers ***
*
- * Process all waiting writers when a fatal error has occured.
+ * Process all waiting writers when a fatal error has occurred.
* All waiting writers will be "aborted", that is a
* nif_abort message will be sent (with ref and reason).
*/
@@ -15253,7 +15349,7 @@ void send_error_waiting_writers(ErlNifEnv* env,
/* *** send_check_retry ***
*
- * Processing done upon uncomplete or blocked send.
+ * Processing done upon incomplete or blocked send.
*
* We failed to write the *entire* packet (anything less
* then size of the packet, which is 0 <= written < sizeof
@@ -15517,7 +15613,7 @@ recv_update_current_reader(ErlNifEnv* env,
/* *** recv_error_current_reader ***
*
* Process the current reader and any waiting readers
- * when a read (fatal) error has occured.
+ * when a read (fatal) error has occurred.
* All waiting readers will be "aborted", that is a
* nif_abort message will be sent (with ref and reason).
*/
@@ -15688,7 +15784,7 @@ ERL_NIF_TERM recv_check_full(ErlNifEnv* env,
/* Send up each chunk of data for each of the read
* and let the erlang code assemble it: {more, Bin}
* (when complete it should return {ok, Bin}).
- * We need to read atleast one more time to be sure if its
+ * We need to read at least one more time to be sure if its
* done...
*
* Also, we need to check if the rNumCnt has reached its max (rNum),
@@ -15895,7 +15991,7 @@ ERL_NIF_TERM recv_check_fail(ErlNifEnv* env,
/* *** recv_check_fail_econnreset ***
*
- * We detected that the socket was closed wile reading.
+ * We detected that the socket was closed while reading.
* Inform current and waiting readers.
*/
#ifndef __WIN32__
@@ -15996,7 +16092,7 @@ ERL_NIF_TERM recv_check_fail_gen(ErlNifEnv* env,
/* *** recv_check_partial ***
*
- * Handle a sucessful recv which only partly filled the specified buffer.
+ * Handle a successful recv which only partly filled the specified buffer.
*/
#ifndef __WIN32__
static
@@ -16209,7 +16305,7 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
} else {
- /* +++ We sucessfully got a message - time to encode the address +++ */
+ /* +++ We successfully got a message - time to encode the address +++ */
ERL_NIF_TERM eSockAddr;
@@ -16316,7 +16412,7 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env,
} else {
- /* +++ We sucessfully got a message - time to encode it +++ */
+ /* +++ We successfully got a message - time to encode it +++ */
res = recvmsg_check_msg(env, descP, read, msgHdrP,
dataBufP, ctrlBufP, sockRef);
@@ -16603,7 +16699,7 @@ void encode_cmsgs(ErlNifEnv* env,
"\r\n %T: %T"
"\r\n", descP->sock, keys[3], vals[3]) );
- /* Guard agains cut-and-paste errors */
+ /* Guard against cut-and-paste errors */
ESOCK_ASSERT( numKeys == NUM(vals) );
ESOCK_ASSERT( MKMA(env, keys, vals,
numKeys - (have_value ? 0 : 1), &cmsgHdr) );
@@ -17066,7 +17162,7 @@ BOOLEAN_T esock_cmsg_encode_recverr(ErlNifEnv *env,
if (have_offender) {
esock_encode_sockaddr(env,
(ESockAddress *)offender,
- (CHARP(sock_err) + dataLen ) - CHARP(offender),
+ (CHARP(sock_err) + dataLen) - CHARP(offender),
&eSockAddr);
} else {
eSockAddr = esock_atom_undefined;
@@ -17417,7 +17513,7 @@ BOOLEAN_T decode_cmsghdr_value(ErlNifEnv* env,
return FALSE;
}
- // Succesful decode
+ // Successful decode
type = cmsgSpecP->type;
@@ -17517,7 +17613,7 @@ BOOLEAN_T decode_cmsghdr_data(ErlNifEnv* env,
return FALSE;
}
- // Succesful decode
+ // Successful decode
SSDBG( descP,
("SOCKET",
@@ -19206,7 +19302,7 @@ ESockRequestQueueElement* qpop(ESockRequestQueue* q)
ESockRequestQueueElement* e = q->first;
if (e != NULL) {
- /* Atleast one element in the queue */
+ /* At least one element in the queue */
if (e == q->last) {
/* Only one element in the queue */
q->first = q->last = NULL;
@@ -19359,7 +19455,7 @@ int esock_monitor(const char* slogan,
("SOCKET",
"esock_monitor {%d} [%T] %s: monitor ok: %T\r\n",
descP->sock, esock_self(env), slogan,
- esock_make_monitor_term(env, monP)) );
+ ESOCK_MON2TERM(env, monP)) );
}
return res;
@@ -19379,7 +19475,7 @@ int esock_demonitor(const char* slogan,
SSDBG( descP, ("SOCKET",
"esock_demonitor {%d} [%T] %s: try demonitor %T\r\n",
descP->sock, esock_self(env), slogan,
- esock_make_monitor_term(env, monP)) );
+ ESOCK_MON2TERM(env, monP)) );
res = enif_demonitor_process(env, descP, &monP->mon);
esock_monitor_init(monP);
@@ -20333,3 +20429,5 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
* unload: NULL (not used)
*/
ERL_NIF_INIT(prim_socket, esock_funcs, on_load, NULL, NULL, NULL)
+
+#endif
diff --git a/erts/emulator/nifs/common/socket_dbg.c b/erts/emulator/nifs/common/socket_dbg.c
index deb531415f..3be1b21cf0 100644
--- a/erts/emulator/nifs/common/socket_dbg.c
+++ b/erts/emulator/nifs/common/socket_dbg.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,12 @@
*
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef ESOCK_ENABLE
+
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
@@ -39,6 +45,9 @@
FILE* esock_dbgout = NULL;
+/* Leave at least 14 for the filename */
+#define PATH_LEN (MAX_PATH - 14)
+
extern
BOOLEAN_T esock_dbg_init(char* filename)
{
@@ -58,6 +67,48 @@ BOOLEAN_T esock_dbg_init(char* filename)
fp = NULL;
+#if defined(__WIN32__)
+ {
+ /* char path[PATH_LEN]; */
+ /* char tf[MAX_PATH]; */
+ /* DWORD wres; */
+
+ /* wres = GetTempPathA(PATH_LEN, &path); */
+
+ /* if ((wres > PATH_LEN) || (wres == 0)) { */
+ /* /\* */
+ /* * We don't really care what is wrong. */
+ /* * Just make the simplest possible solution (= use stdout) */
+ /* *\/ */
+ /* esock_dbgout = stdout; */
+ /* return TRUE; // Successful file open */
+ /* }; */
+
+ /* /\* If 'filename' has been constructed in the unix */
+ /* * way, this may result in an odd tf... */
+ /* *\/ */
+ /* wres = GetTempFileNameA(path, filename, 0, &tf); */
+
+ /* if (wres == 0) { */
+ /* /\* */
+ /* * Again, we don't really care *what* is wrong. */
+ /* * Just make the simplest possible solution (= use stdout) */
+ /* *\/ */
+ /* esock_dbgout = stdout; */
+ /* return TRUE; // Successful file open */
+ /* } */
+
+ // Should we use CreateFile instead?
+ // fp = fopen(tf, mode);
+
+
+ /* For simplicity, we do not (*currently*) support generating
+ * a 'temporary' (debug) file name, we simply use the file name
+ * 'as is'.
+ */
+ fp = fopen(filename, mode);
+ }
+#else
/* If there is trailing ?????? replace it with XXXXXX
* and use mkstemp() to create an unique file name
*/
@@ -82,10 +133,11 @@ BOOLEAN_T esock_dbg_init(char* filename)
} else {
fp = fopen(filename, mode);
}
+#endif
if (fp != NULL) {
esock_dbgout = fp;
- return TRUE; // Succesful file open
+ return TRUE; // Successful file open
}
esock_dbgout = stdout;
@@ -129,3 +181,4 @@ void esock_dbg_printf( const char* prefix, const char* format, ... )
}
}
+#endif
diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h
index cc8584ee7e..95b2c6c22f 100644
--- a/erts/emulator/nifs/common/socket_int.h
+++ b/erts/emulator/nifs/common/socket_int.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,6 +60,10 @@
#include <sys/un.h>
#endif
+#ifdef HAVE_NET_IF_DL_H
+#include <net/if_dl.h>
+#endif
+
#ifdef HAVE_NETPACKET_PACKET_H
#include <netpacket/packet.h>
#endif
@@ -129,6 +133,10 @@ typedef union {
struct sockaddr_ll ll;
#endif
+#if defined(AF_LINK)
+ struct sockaddr_dl dl;
+#endif
+
/* Max size sockaddr on system */
struct sockaddr_storage ss;
@@ -163,6 +171,13 @@ typedef int BOOLEAN_T;
#define SOCKOPTLEN_T SOCKLEN_T
#endif
+/*
+ * Seems to be missing.
+ */
+#ifndef __GNUC__
+typedef long ssize_t;
+#endif
+
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* "Global" atoms (esock_atom_...)
@@ -181,17 +196,14 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(addrform); \
GLOBAL_ATOM_DEF(add_membership); \
GLOBAL_ATOM_DEF(add_source_membership); \
+ GLOBAL_ATOM_DEF(alen); \
GLOBAL_ATOM_DEF(allmulti); \
GLOBAL_ATOM_DEF(any); \
- GLOBAL_ATOM_DEF(arphrd_dlci); \
- GLOBAL_ATOM_DEF(arphrd_ether); \
- GLOBAL_ATOM_DEF(arphrd_frelay); \
- GLOBAL_ATOM_DEF(arphrd_ieee802); \
- GLOBAL_ATOM_DEF(arphrd_ieee1394); \
- GLOBAL_ATOM_DEF(arphrd_loopback); \
- GLOBAL_ATOM_DEF(arphrd_netrom); \
- GLOBAL_ATOM_DEF(arphrd_none); \
+ GLOBAL_ATOM_DEF(appletlk); \
+ GLOBAL_ATOM_DEF(arcnet); \
+ GLOBAL_ATOM_DEF(ax25); \
GLOBAL_ATOM_DEF(associnfo); \
+ GLOBAL_ATOM_DEF(atm); \
GLOBAL_ATOM_DEF(authhdr); \
GLOBAL_ATOM_DEF(auth_active_key); \
GLOBAL_ATOM_DEF(auth_asconf); \
@@ -215,6 +227,8 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(confirm); \
GLOBAL_ATOM_DEF(congestion); \
GLOBAL_ATOM_DEF(connect); \
+ GLOBAL_ATOM_DEF(connected); \
+ GLOBAL_ATOM_DEF(connecting); \
GLOBAL_ATOM_DEF(context); \
GLOBAL_ATOM_DEF(cork); \
GLOBAL_ATOM_DEF(credentials); \
@@ -227,6 +241,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(delayed_ack_time); \
GLOBAL_ATOM_DEF(dgram); \
GLOBAL_ATOM_DEF(disable_fragments); \
+ GLOBAL_ATOM_DEF(dlci); \
GLOBAL_ATOM_DEF(domain); \
GLOBAL_ATOM_DEF(dontfrag); \
GLOBAL_ATOM_DEF(dontroute); \
@@ -237,6 +252,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(dying); \
GLOBAL_ATOM_DEF(dynamic); \
GLOBAL_ATOM_DEF(echo); \
+ GLOBAL_ATOM_DEF(eether); \
GLOBAL_ATOM_DEF(egp); \
GLOBAL_ATOM_DEF(enotsup); \
GLOBAL_ATOM_DEF(eor); \
@@ -244,6 +260,8 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(errqueue); \
GLOBAL_ATOM_DEF(esp_network_level); \
GLOBAL_ATOM_DEF(esp_trans_level); \
+ GLOBAL_ATOM_DEF(ether); \
+ GLOBAL_ATOM_DEF(eui64); \
GLOBAL_ATOM_DEF(events); \
GLOBAL_ATOM_DEF(explicit_eor); \
GLOBAL_ATOM_DEF(faith); \
@@ -254,6 +272,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(flowinfo); \
GLOBAL_ATOM_DEF(fragment_interleave); \
GLOBAL_ATOM_DEF(freebind); \
+ GLOBAL_ATOM_DEF(frelay); \
GLOBAL_ATOM_DEF(get_peer_addr_info); \
GLOBAL_ATOM_DEF(hatype); \
GLOBAL_ATOM_DEF(hdrincl); \
@@ -263,11 +282,15 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(host); \
GLOBAL_ATOM_DEF(icmp); \
GLOBAL_ATOM_DEF(icmp6); \
+ GLOBAL_ATOM_DEF(ieee802); \
+ GLOBAL_ATOM_DEF(ieee1394); \
GLOBAL_ATOM_DEF(ifindex); \
GLOBAL_ATOM_DEF(igmp); \
GLOBAL_ATOM_DEF(implink); \
+ GLOBAL_ATOM_DEF(index); \
GLOBAL_ATOM_DEF(inet); \
GLOBAL_ATOM_DEF(inet6); \
+ GLOBAL_ATOM_DEF(infiniband); \
GLOBAL_ATOM_DEF(info); \
GLOBAL_ATOM_DEF(initmsg); \
GLOBAL_ATOM_DEF(invalid); \
@@ -293,6 +316,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(link1); \
GLOBAL_ATOM_DEF(link2); \
GLOBAL_ATOM_DEF(local); \
+ GLOBAL_ATOM_DEF(localtlk); \
GLOBAL_ATOM_DEF(local_auth_chunks); \
GLOBAL_ATOM_DEF(loopback); \
GLOBAL_ATOM_DEF(lowdelay); \
@@ -302,6 +326,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(maxburst); \
GLOBAL_ATOM_DEF(maxseg); \
GLOBAL_ATOM_DEF(md5sig); \
+ GLOBAL_ATOM_DEF(metricom); \
GLOBAL_ATOM_DEF(mincost); \
GLOBAL_ATOM_DEF(minttl); \
GLOBAL_ATOM_DEF(monitor); \
@@ -316,6 +341,8 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(multicast_loop); \
GLOBAL_ATOM_DEF(multicast_ttl); \
GLOBAL_ATOM_DEF(name); \
+ GLOBAL_ATOM_DEF(netrom); \
+ GLOBAL_ATOM_DEF(nlen); \
GLOBAL_ATOM_DEF(noarp); \
GLOBAL_ATOM_DEF(nodelay); \
GLOBAL_ATOM_DEF(nodefrag); \
@@ -355,6 +382,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(primary_addr); \
GLOBAL_ATOM_DEF(priority); \
GLOBAL_ATOM_DEF(promisc); \
+ GLOBAL_ATOM_DEF(pronet); \
GLOBAL_ATOM_DEF(protocol); \
GLOBAL_ATOM_DEF(pup); \
GLOBAL_ATOM_DEF(raw); \
@@ -402,6 +430,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(set_peer_primary_addr); \
GLOBAL_ATOM_DEF(simplex); \
GLOBAL_ATOM_DEF(slave); \
+ GLOBAL_ATOM_DEF(slen); \
GLOBAL_ATOM_DEF(sndbuf); \
GLOBAL_ATOM_DEF(sndbufforce); \
GLOBAL_ATOM_DEF(sndlowat); \
@@ -422,6 +451,8 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(true); \
GLOBAL_ATOM_DEF(trunc); \
GLOBAL_ATOM_DEF(ttl); \
+ GLOBAL_ATOM_DEF(tunnel); \
+ GLOBAL_ATOM_DEF(tunnel6); \
GLOBAL_ATOM_DEF(type); \
GLOBAL_ATOM_DEF(udp); \
GLOBAL_ATOM_DEF(unblock_source); \
@@ -434,6 +465,7 @@ typedef int BOOLEAN_T;
GLOBAL_ATOM_DEF(user_timeout); \
GLOBAL_ATOM_DEF(use_ext_recvinfo); \
GLOBAL_ATOM_DEF(use_min_mtu); \
+ GLOBAL_ATOM_DEF(void); \
GLOBAL_ATOM_DEF(v6only);
diff --git a/erts/emulator/nifs/common/socket_tarray.c b/erts/emulator/nifs/common/socket_tarray.c
index def22c4919..c35089f878 100644
--- a/erts/emulator/nifs/common/socket_tarray.c
+++ b/erts/emulator/nifs/common/socket_tarray.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2019. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,9 +24,11 @@
*
*/
-/* #ifdef HAVE_CONFIG_H */
-/* #include "config.h" */
-/* #endif */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef ESOCK_ENABLE
#include <stdio.h>
@@ -141,3 +143,5 @@ void esock_tarray_ensure_fits(SocketTArrayInt* taP, Uint32 needs)
taP->array = (ERL_NIF_TERM*) mem;
}
}
+
+#endif
diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c
index 94a5e3e3dc..3747723ede 100644
--- a/erts/emulator/nifs/common/socket_util.c
+++ b/erts/emulator/nifs/common/socket_util.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,9 +24,11 @@
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
+#ifdef ESOCK_ENABLE
+
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
@@ -34,8 +36,13 @@
#include <time.h>
#include <stddef.h>
#include <sys/types.h>
+#if !defined(__WIN32__)
#include <sys/socket.h>
+#endif
+
+#if !defined(__IOS__) && !defined(__WIN32__)
#include <net/if_arp.h>
+#endif
#include "socket_int.h"
#include "sys.h"
@@ -62,6 +69,10 @@
#define UDBG( proto ) ESOCK_DBG_PRINTF( UTIL_DEBUG , proto )
+#if defined(__WIN32__)
+typedef u_short sa_family_t;
+#endif
+
extern char* erl_errno_id(int error); /* THIS IS JUST TEMPORARY??? */
@@ -82,6 +93,12 @@ static void esock_encode_packet_addr_tuple(ErlNifEnv* env,
unsigned char* addr,
ERL_NIF_TERM* eAddr);
+#if defined(HAVE_NET_IF_DL_H) && defined(AF_LINK)
+static void esock_encode_sockaddr_dl(ErlNifEnv* env,
+ struct sockaddr_dl* sockAddrP,
+ SOCKLEN_T addrLen,
+ ERL_NIF_TERM* eSockAddr);
+#endif
static void esock_encode_sockaddr_native(ErlNifEnv* env,
struct sockaddr* sa,
SOCKLEN_T len,
@@ -90,7 +107,7 @@ static void esock_encode_sockaddr_native(ErlNifEnv* env,
static void esock_encode_sockaddr_broken(ErlNifEnv* env,
struct sockaddr* sa,
- socklen_t len,
+ SOCKLEN_T len,
ERL_NIF_TERM* eSockAddr);
static void make_sockaddr_in(ErlNifEnv* env,
@@ -115,7 +132,19 @@ static void make_sockaddr_ll(ErlNifEnv* env,
ERL_NIF_TERM addr,
ERL_NIF_TERM* sa);
#endif
-
+#if defined(HAVE_NET_IF_DL_H) && defined(AF_LINK)
+static void make_sockaddr_dl(ErlNifEnv* env,
+ ERL_NIF_TERM index,
+ ERL_NIF_TERM type,
+ ERL_NIF_TERM nlen,
+ ERL_NIF_TERM alen,
+ ERL_NIF_TERM slen,
+ ERL_NIF_TERM data,
+ ERL_NIF_TERM* sa);
+#endif
+#ifdef HAS_AF_LOCAL
+static SOCKLEN_T sa_local_length(int l, struct sockaddr_un* sa);
+#endif
/* *** esock_get_bool_from_map ***
@@ -160,14 +189,14 @@ BOOLEAN_T esock_get_bool_from_map(ErlNifEnv* env,
extern
void esock_encode_iov(ErlNifEnv* env,
ssize_t read,
- struct iovec* iov,
+ SysIOVec* iov,
size_t len,
ErlNifBinary* data,
ERL_NIF_TERM* eIOV)
{
- ssize_t rem = read;
- size_t i;
- ERL_NIF_TERM a[len]; // At most this length
+ ssize_t rem = read;
+ size_t i;
+ ERL_NIF_TERM* a;
UDBG( ("SUTIL", "esock_encode_iov -> entry with"
"\r\n read: %ld"
@@ -175,8 +204,11 @@ void esock_encode_iov(ErlNifEnv* env,
"\r\n", (long) read, (unsigned long) len) );
if (len == 0) {
+ UDBG( ("SUTIL", "esock_encode_iov -> done when empty\r\n") );
*eIOV = MKEL(env);
return;
+ } else {
+ a = MALLOC(len * sizeof(ERL_NIF_TERM)); // At most this length
}
for (i = 0; i < len; i++) {
@@ -212,6 +244,8 @@ void esock_encode_iov(ErlNifEnv* env,
*eIOV = MKLA(env, a, i);
+ FREE(a);
+
UDBG( ("SUTIL", "esock_encode_msghdr -> done\r\n") );
}
@@ -222,7 +256,7 @@ void esock_encode_iov(ErlNifEnv* env,
* Decode an IO Vector. In erlang we represented this as a list of binaries.
*
* We assume that we have already figured out how long the iov (actually
- * eIOV) is (len), and therefor allocated an array of bins and iov to be
+ * eIOV) is (len), and therefore allocated an array of bins and iov to be
* used.
*/
@@ -230,7 +264,7 @@ extern
BOOLEAN_T esock_decode_iov(ErlNifEnv* env,
ERL_NIF_TERM eIOV,
ErlNifBinary* bufs,
- struct iovec* iov,
+ SysIOVec* iov,
size_t len,
ssize_t* totSize)
{
@@ -255,7 +289,7 @@ BOOLEAN_T esock_decode_iov(ErlNifEnv* env,
if (IS_BIN(env, elem) && GET_BIN(env, elem, &bufs[i])) {
ssize_t z;
- iov[i].iov_base = (caddr_t) bufs[i].data;
+ iov[i].iov_base = (void*) bufs[i].data;
iov[i].iov_len = bufs[i].size;
z = sz;
@@ -366,21 +400,32 @@ BOOLEAN_T esock_decode_sockaddr(ErlNifEnv* env,
* packet - sockaddr_ll: protocol, ifindex, hatype, pkttype, addr
* unspec - sockaddr: addr
* (int) - sockaddr: addr
+ *
+ * An address length > 0 means the caller knows the length, and we use it.
+ * An address length of '-1' means the caller don't know, which
+ * in turn mean that "we" has to calculate.
+ *
+ * sys/socket.h:
+ * __SOCKADDR_ALLTYPES
*/
+#define SALEN(L, SZ) (((L) > 0) ? (L) : (SZ))
+
extern
void esock_encode_sockaddr(ErlNifEnv* env,
ESockAddress* sockAddrP,
- SOCKLEN_T addrLen,
+ int addrLen,
ERL_NIF_TERM* eSockAddr)
{
- int family;
+ int family;
+ SOCKLEN_T len;
// Sanity check
- if (addrLen < (char *)&sockAddrP->sa.sa_data - (char *)sockAddrP) {
- // We got crap, cannot even know the address family
- esock_encode_sockaddr_broken(env, &sockAddrP->sa, addrLen, eSockAddr);
- return;
+ if ((addrLen > 0) &&
+ (addrLen < (char *)&sockAddrP->sa.sa_data - (char *)sockAddrP)) {
+ // We got crap, cannot even know the address family
+ esock_encode_sockaddr_broken(env, &sockAddrP->sa, addrLen, eSockAddr);
+ return;
}
family = sockAddrP->ss.ss_family;
@@ -391,70 +436,160 @@ void esock_encode_sockaddr(ErlNifEnv* env,
switch (family) {
case AF_INET:
- esock_encode_sockaddr_in(env, &sockAddrP->in4, addrLen, eSockAddr);
- break;
+ len = SALEN(addrLen, sizeof(struct sockaddr_in));
+ esock_encode_sockaddr_in(env, &sockAddrP->in4, len, eSockAddr);
+ break;
#if defined(HAVE_IN6) && defined(AF_INET6)
case AF_INET6:
- esock_encode_sockaddr_in6(env, &sockAddrP->in6, addrLen, eSockAddr);
- break;
+ len = SALEN(addrLen, sizeof(struct sockaddr_in6));
+ esock_encode_sockaddr_in6(env, &sockAddrP->in6, len, eSockAddr);
+ break;
#endif
#ifdef HAS_AF_LOCAL
case AF_LOCAL:
- esock_encode_sockaddr_un(env, &sockAddrP->un, addrLen, eSockAddr);
- break;
+ len = sa_local_length(addrLen, &sockAddrP->un);
+ esock_encode_sockaddr_un(env, &sockAddrP->un, len, eSockAddr);
+ break;
#endif
#ifdef AF_UNSPEC
case AF_UNSPEC:
- esock_encode_sockaddr_native(env, &sockAddrP->sa,
- addrLen, esock_atom_unspec, eSockAddr);
- break;
+ len = SALEN(addrLen, 0);
+ esock_encode_sockaddr_native(env,
+ &sockAddrP->sa, len,
+ esock_atom_unspec,
+ eSockAddr);
+ break;
#endif
#if defined(HAVE_NETPACKET_PACKET_H)
case AF_PACKET:
- esock_encode_sockaddr_ll(env, &sockAddrP->ll, addrLen, eSockAddr);
- break;
+ len = SALEN(addrLen, sizeof(struct sockaddr_ll));
+ esock_encode_sockaddr_ll(env, &sockAddrP->ll, len, eSockAddr);
+ break;
#endif
#if defined(AF_IMPLINK)
case AF_IMPLINK:
- esock_encode_sockaddr_native(env, &sockAddrP->sa,
- addrLen, esock_atom_implink, eSockAddr);
+ len = SALEN(addrLen, 0);
+ esock_encode_sockaddr_native(env,
+ &sockAddrP->sa, len,
+ esock_atom_implink,
+ eSockAddr);
break;
#endif
#if defined(AF_PUP)
case AF_PUP:
- esock_encode_sockaddr_native(env, &sockAddrP->sa,
- addrLen, esock_atom_pup, eSockAddr);
- break;
+ len = SALEN(addrLen, 0);
+ esock_encode_sockaddr_native(env,
+ &sockAddrP->sa, len,
+ esock_atom_pup,
+ eSockAddr);
+ break;
#endif
#if defined(AF_CHAOS)
case AF_CHAOS:
- esock_encode_sockaddr_native(env, &sockAddrP->sa,
- addrLen, esock_atom_chaos, eSockAddr);
- break;
+ len = SALEN(addrLen, 0);
+ esock_encode_sockaddr_native(env,
+ &sockAddrP->sa, len,
+ esock_atom_chaos,
+ eSockAddr);
+ break;
#endif
-#if defined(AF_LINK)
+#if defined(HAVE_NET_IF_DL_H) && defined(AF_LINK)
case AF_LINK:
- esock_encode_sockaddr_native(env, &sockAddrP->sa,
- addrLen, esock_atom_link, eSockAddr);
+ /*
+ * macOS (Darwin Kernel Version 21.4.0):
+ * -------------------------------------
+ * struct sockaddr_dl {
+ * u_char sdl_len; // Total length of sockaddr
+ * u_char sdl_family; // AF_LINK
+ * u_short sdl_index; // if != 0, system given index for interface
+ * u_char sdl_type; // interface type
+ * u_char sdl_nlen; // interface name length, no trailing 0 reqd.
+ * u_char sdl_alen; // link level address length
+ * u_char sdl_slen; // link layer selector length
+ * char sdl_data[12]; // minimum work area, can be larger;
+ * // contains both if name and ll address
+ * #ifndef __APPLE__
+ * // For TokenRing
+ * u_short sdl_rcf; // source routing control
+ * u_short sdl_route[16]; // source routing information
+ * #endif
+ * };
+ *
+ * FreeBSD (12.2-RELEASE-p14):
+ * ---------------------------
+ * struct sockaddr_dl {
+ * u_char sdl_len; // Total length of sockaddr
+ * u_char sdl_family; // AF_LINK
+ * u_short sdl_index; // if != 0,
+ * // system given index for interface
+ * u_char sdl_type; // interface type
+ * u_char sdl_nlen; // interface name length, no trailing 0 reqd
+ * u_char sdl_alen; // link level address length
+ * u_char sdl_slen; // link layer selector length
+ * char sdl_data[46]; // minimum work area, can be larger;
+ * // contains both if name and ll address
+ * };
+ *
+ * OpenIndiana 2021.10
+ * struct sockaddr_dl {
+ * ushort_t sdl_family; // AF_LINK
+ * ushort_t sdl_index; // if != 0,
+ * // system given index for interface
+ * uchar_t sdl_type; // interface type
+ * uchar_t sdl_nlen; // interface name length, no trailing 0 reqd
+ * uchar_t sdl_alen; // link level address length
+ * uchar_t sdl_slen; // link layer selector length
+ * char sdl_data[244]; // contains both if name and ll address
+ * };
+ *
+ */
+#if defined(ESOCK_SDL_LEN)
+ len = SALEN(addrLen, sockAddrP->dl.sdl_len);
+#else
+ // The data area is dlen = nlen + alen
+ len = SALEN(addrLen,
+ (CHARP(sockAddrP->dl.sdl_data) - CHARP(sockAddrP)) +
+ sockAddrP->dl.sdl_nlen + sockAddrP->dl.sdl_alen);
+#endif
+ esock_encode_sockaddr_dl(env, &sockAddrP->dl, len, eSockAddr);
break;
#endif
default:
- esock_encode_sockaddr_native(env, &sockAddrP->sa,
- addrLen, MKI(env, family), eSockAddr);
- break;
+ len = SALEN(addrLen, 0);
+ esock_encode_sockaddr_native(env,
+ &sockAddrP->sa, len,
+ MKI(env, family),
+ eSockAddr);
+ break;
}
}
+#ifdef HAS_AF_LOCAL
+static
+SOCKLEN_T sa_local_length(int l, struct sockaddr_un* sa)
+{
+ if (l > 0) {
+ return ((SOCKLEN_T) l);
+ } else {
+#if defined(SUN_LEN)
+ return SUN_LEN(sa);
+#else
+ return (offsetof(struct sockaddr_un, sun_path) + strlen(sa->sun_path) + 1);
+#endif
+ }
+}
+#endif
+
extern
void esock_encode_hwsockaddr(ErlNifEnv* env,
@@ -481,49 +616,49 @@ void esock_encode_hwsockaddr(ErlNifEnv* env,
switch (family) {
#if defined(ARPHRD_NETROM)
case ARPHRD_NETROM:
- efamily = esock_atom_arphrd_netrom;
+ efamily = esock_atom_netrom;
break;
#endif
#if defined(ARPHRD_ETHER)
case ARPHRD_ETHER:
- efamily = esock_atom_arphrd_ether;
+ efamily = esock_atom_ether;
break;
#endif
#if defined(ARPHRD_IEEE802)
case ARPHRD_IEEE802:
- efamily = esock_atom_arphrd_ieee802;
+ efamily = esock_atom_ieee802;
break;
#endif
#if defined(ARPHRD_DLCI)
case ARPHRD_DLCI:
- efamily = esock_atom_arphrd_dlci;
+ efamily = esock_atom_dlci;
break;
#endif
#if defined(ARPHRD_FRELAY)
case ARPHRD_FRELAY:
- efamily = esock_atom_arphrd_frelay;
+ efamily = esock_atom_frelay;
break;
#endif
#if defined(ARPHRD_IEEE1394)
case ARPHRD_IEEE1394:
- efamily = esock_atom_arphrd_ieee1394;
+ efamily = esock_atom_ieee1394;
break;
#endif
#if defined(ARPHRD_LOOPBACK)
case ARPHRD_LOOPBACK:
- efamily = esock_atom_arphrd_loopback;
+ efamily = esock_atom_loopback;
break;
#endif
#if defined(ARPHRD_NONE)
case ARPHRD_NONE:
- efamily = esock_atom_arphrd_none;
+ efamily = esock_atom_none;
break;
#endif
@@ -643,7 +778,7 @@ void esock_encode_sockaddr_in(ErlNifEnv* env,
"\r\n addr size: %d"
"\r\n", addrLen, sizeof(struct sockaddr_in)) );
esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP,
- addrLen, MKI(env, AF_INET), eSockAddr);
+ addrLen, esock_atom_inet, eSockAddr);
}
}
@@ -783,7 +918,7 @@ void esock_encode_sockaddr_in6(ErlNifEnv* env,
} else {
esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP,
- addrLen, MKI(env, AF_INET6), eSockAddr);
+ addrLen, esock_atom_inet6, eSockAddr);
}
}
#endif
@@ -877,6 +1012,10 @@ void esock_encode_sockaddr_un(ErlNifEnv* env,
ERL_NIF_TERM ePath;
size_t n, m;
+ UDBG( ("SUTIL", "esock_encode_sockaddr_un -> entry with"
+ "\r\n. addrLen: %d"
+ "\r\n", addrLen) );
+
n = sockAddrP->sun_path - (char *)sockAddrP; // offsetof
if (addrLen >= n) {
n = addrLen - n; // sun_path length
@@ -911,7 +1050,7 @@ void esock_encode_sockaddr_un(ErlNifEnv* env,
}
} else {
esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP,
- addrLen, MKI(env, AF_LOCAL), eSockAddr);
+ addrLen, esock_atom_local, eSockAddr);
}
}
#endif
@@ -929,7 +1068,7 @@ void esock_encode_sockaddr_un(ErlNifEnv* env,
* ifindex: integer()
* hatype: integer() (should be an atom really)
* pkttype: integer() (should be an atom really)
- * addr: list() (should be something usefull...)
+ * addr: list() (should be something useful...)
*
*/
@@ -942,6 +1081,10 @@ void esock_encode_sockaddr_ll(ErlNifEnv* env,
{
ERL_NIF_TERM eProto, eIfIdx, eHaType, ePktType, eAddr;
+ UDBG( ("SUTIL", "esock_encode_sockaddr_ll -> entry with"
+ "\r\n. addrLen: %d"
+ "\r\n", addrLen) );
+
if (addrLen >= sizeof(struct sockaddr_ll)) {
/* protocol - the standard ethernet protocol type */
@@ -968,7 +1111,75 @@ void esock_encode_sockaddr_ll(ErlNifEnv* env,
} else {
esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP,
- addrLen, MKI(env, AF_PACKET), eSockAddr);
+ addrLen, esock_atom_packet, eSockAddr);
+ }
+}
+#endif
+
+
+
+/* +++ esock_encode_sockaddr_dl +++
+ *
+ * Encode a LINK address - sockaddr_dl (link-level layer). In erlang it's
+ * represented as a map, which has a specific set of attributes
+ * (beside the mandatory family attribute, which is "inherited" from
+ * the "sockaddr" type):
+ *
+ * The length field (sdl_len) has already been used, so we don't use it
+ * in *this* function.
+ *
+ * index: non_neg_integer()
+ * type: non_neg_integer()
+ * nlen: non_neg_integer() (name length)
+ * alen: non_neg_integer() (address length)
+ * slen: non_neg_integer() (sector length)
+ * data: binary()
+ */
+
+#if defined(HAVE_NET_IF_DL_H) && defined(AF_LINK)
+extern
+void esock_encode_sockaddr_dl(ErlNifEnv* env,
+ struct sockaddr_dl* sockAddrP,
+ SOCKLEN_T addrLen,
+ ERL_NIF_TERM* eSockAddr)
+{
+ ERL_NIF_TERM eindex, etype, enlen, ealen, eslen, edata;
+ SOCKLEN_T dlen;
+
+ UDBG( ("SUTIL", "esock_encode_sockaddr_dl -> entry with"
+ "\r\n. addrLen: %d"
+ "\r\n", addrLen) );
+
+ /* There is a minumum length (defined by the size of the data field) */
+ if (addrLen >= sizeof(struct sockaddr_dl)) {
+
+ /* index - if != 0, system given index for interface */
+ eindex = MKUI(env, sockAddrP->sdl_index);
+
+ /* type - interface type */
+ etype = MKUI(env, sockAddrP->sdl_type);
+
+ /* nlen - interface name length, no trailing 0 reqd. */
+ enlen = MKUI(env, sockAddrP->sdl_nlen);
+
+ /* alen - link level address length */
+ ealen = MKUI(env, sockAddrP->sdl_alen);
+
+ /* slen - ink layer selector length */
+ eslen = MKUI(env, sockAddrP->sdl_slen);
+
+ /* data - minimum work area, can be larger; *
+ * contains both if name and ll address */
+ dlen = addrLen - (CHARP(sockAddrP->sdl_data) - CHARP(sockAddrP));
+ edata = esock_make_new_binary(env, &sockAddrP->sdl_data, dlen);
+
+ make_sockaddr_dl(env,
+ eindex, etype, enlen, ealen, eslen, edata,
+ eSockAddr);
+
+ } else {
+ esock_encode_sockaddr_native(env, (struct sockaddr *)sockAddrP,
+ addrLen, esock_atom_link, eSockAddr);
}
}
#endif
@@ -1496,7 +1707,157 @@ void esock_encode_packet_hatype(ErlNifEnv* env,
unsigned short hatype,
ERL_NIF_TERM* eHaType)
{
- *eHaType = MKUI(env, hatype);
+ ERL_NIF_TERM tmp;
+
+ switch (hatype) {
+
+ /*
+ * ARP protocol HARDWARE identifiers.
+ */
+
+#if defined(ARPHRD_NETROM)
+ case ARPHRD_NETROM:
+ tmp = esock_atom_netrom;
+ break;
+#endif
+
+#if defined(ARPHRD_ETHER)
+ case ARPHRD_ETHER:
+ tmp = esock_atom_ether;
+ break;
+#endif
+
+#if defined(ARPHRD_EETHER)
+ case ARPHRD_EETHER:
+ tmp = esock_atom_eether;
+ break;
+#endif
+
+#if defined(ARPHRD_AX25)
+ case ARPHRD_AX25:
+ tmp = esock_atom_ax25;
+ break;
+#endif
+
+#if defined(ARPHRD_PRONET)
+ case ARPHRD_PRONET:
+ tmp = esock_atom_pronet;
+ break;
+#endif
+
+#if defined(ARPHRD_CHAOS)
+ case ARPHRD_CHAOS:
+ tmp = esock_atom_chaos;
+ break;
+#endif
+
+#if defined(ARPHRD_IEEE802)
+ case ARPHRD_IEEE802:
+ tmp = esock_atom_ieee802;
+ break;
+#endif
+
+#if defined(ARPHRD_ARCNET)
+ case ARPHRD_ARCNET:
+ tmp = esock_atom_arcnet;
+ break;
+#endif
+
+#if defined(ARPHRD_APPLETLK)
+ case ARPHRD_APPLETLK:
+ tmp = esock_atom_appletlk;
+ break;
+#endif
+
+#if defined(ARPHRD_DLCI)
+ case ARPHRD_DLCI:
+ tmp = esock_atom_dlci;
+ break;
+#endif
+
+#if defined(ARPHRD_ATM)
+ case ARPHRD_ATM:
+ tmp = esock_atom_atm;
+ break;
+#endif
+
+#if defined(ARPHRD_METRICOM)
+ case ARPHRD_METRICOM:
+ tmp = esock_atom_metricom;
+ break;
+#endif
+
+#if defined(ARPHRD_IEEE1394)
+ case ARPHRD_IEEE1394:
+ tmp = esock_atom_ieee1394;
+ break;
+#endif
+
+#if defined(ARPHRD_EUI64)
+ case ARPHRD_EUI64:
+ tmp = esock_atom_eui64;
+ break;
+#endif
+
+#if defined(ARPHRD_INFINIBAND)
+ case ARPHRD_INFINIBAND:
+ tmp = esock_atom_infiniband;
+ break;
+#endif
+
+
+ /*
+ * Dummy types for non ARP hardware
+ */
+
+#if defined(ARPHRD_TUNNEL)
+ case ARPHRD_TUNNEL:
+ tmp = esock_atom_tunnel;
+ break;
+#endif
+
+#if defined(ARPHRD_TUNNEL6)
+ case ARPHRD_TUNNEL6:
+ tmp = esock_atom_tunnel6;
+ break;
+#endif
+
+#if defined(ARPHRD_LOOPBACK)
+ case ARPHRD_LOOPBACK:
+ tmp = esock_atom_loopback;
+ break;
+#endif
+
+#if defined(ARPHRD_LOCALTLK)
+ case ARPHRD_LOCALTLK:
+ tmp = esock_atom_localtlk;
+ break;
+#endif
+
+
+#if defined(ARPHRD_NONE)
+ case ARPHRD_NONE:
+ tmp = esock_atom_none;
+ break;
+#endif
+
+#if defined(ARPHRD_VOID)
+ case ARPHRD_VOID:
+ tmp = esock_atom_void;
+ break;
+#endif
+
+
+ /*
+ * And the rest will be just integer
+ */
+
+ default:
+ tmp = MKUI(env, hatype);
+ break;
+ }
+
+ *eHaType = tmp;
}
@@ -1623,7 +1984,7 @@ void esock_encode_packet_addr_tuple(ErlNifEnv* env,
unsigned char* addr,
ERL_NIF_TERM* eAddr)
{
- ERL_NIF_TERM array[len];
+ ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM));
unsigned char i;
for (i = 0; i < len; i++) {
@@ -1631,6 +1992,9 @@ void esock_encode_packet_addr_tuple(ErlNifEnv* env,
}
*eAddr = MKTA(env, array, len);
+
+ FREE(array);
+
}
@@ -1686,7 +2050,7 @@ BOOLEAN_T esock_decode_sockaddr_native(ErlNifEnv* env,
-/* Encode as #{family := integer(), addr := binary()}
+/* Encode as #{family := atom() | integer(), addr := binary()}
* assuming at least the ->family field can be accessed
* and hence at least 0 bytes of address
*/
@@ -1700,8 +2064,17 @@ void esock_encode_sockaddr_native(ErlNifEnv* env,
size_t size;
ERL_NIF_TERM eData;
- size = ((char*)addr + len) - (char*)&addr->sa_data;
- eData = esock_make_new_binary(env, &addr->sa_data, size);
+ UDBG( ("SUTIL", "esock_encode_sockaddr_native -> entry with"
+ "\r\n. len: %d"
+ "\r\n. eFamily: %T"
+ "\r\n", len, eFamily) );
+
+ if (len > 0) {
+ size = ((char*)addr + len) - (char*)&addr->sa_data;
+ eData = esock_make_new_binary(env, &addr->sa_data, size);
+ } else {
+ eData = esock_make_new_binary(env, &addr->sa_data, 0);
+ }
{
ERL_NIF_TERM keys[] = {esock_atom_family, esock_atom_addr};
@@ -1713,6 +2086,7 @@ void esock_encode_sockaddr_native(ErlNifEnv* env,
}
}
+
/* Encode as a raw binary() regarding the whole address
* structure as a blob
*/
@@ -1720,6 +2094,10 @@ static void esock_encode_sockaddr_broken(ErlNifEnv* env,
struct sockaddr* addr,
SOCKLEN_T len,
ERL_NIF_TERM* eSockAddr) {
+ UDBG( ("SUTIL", "esock_encode_sockaddr_broken -> entry with"
+ "\r\n. len: %d"
+ "\r\n", len) );
+
*eSockAddr = esock_make_new_binary(env, addr, len);
}
@@ -2282,17 +2660,51 @@ void make_sockaddr_ll(ErlNifEnv* env,
ERL_NIF_TERM* sa)
{
ERL_NIF_TERM keys[] = {esock_atom_family,
- esock_atom_protocol,
- esock_atom_ifindex,
- esock_atom_hatype,
- esock_atom_pkttype,
- esock_atom_addr};
+ esock_atom_protocol,
+ esock_atom_ifindex,
+ esock_atom_hatype,
+ esock_atom_pkttype,
+ esock_atom_addr};
ERL_NIF_TERM vals[] = {esock_atom_packet,
- proto,
- ifindex,
- hatype,
- pkttype,
- addr};
+ proto,
+ ifindex,
+ hatype,
+ pkttype,
+ addr};
+ size_t numKeys = NUM(keys);
+
+ ESOCK_ASSERT( numKeys == NUM(vals) );
+ ESOCK_ASSERT( MKMA(env, keys, vals, numKeys, sa) );
+}
+#endif
+
+
+/* Construct the Link-Level socket address */
+#if defined(HAVE_NET_IF_DL_H) && defined(AF_LINK)
+static
+void make_sockaddr_dl(ErlNifEnv* env,
+ ERL_NIF_TERM index,
+ ERL_NIF_TERM type,
+ ERL_NIF_TERM nlen,
+ ERL_NIF_TERM alen,
+ ERL_NIF_TERM slen,
+ ERL_NIF_TERM data,
+ ERL_NIF_TERM* sa)
+{
+ ERL_NIF_TERM keys[] = {esock_atom_family,
+ esock_atom_index,
+ esock_atom_type,
+ esock_atom_nlen,
+ esock_atom_alen,
+ esock_atom_slen,
+ esock_atom_data};
+ ERL_NIF_TERM vals[] = {esock_atom_link,
+ index,
+ type,
+ nlen,
+ alen,
+ slen,
+ data};
size_t numKeys = NUM(keys);
ESOCK_ASSERT( numKeys == NUM(vals) );
@@ -2338,3 +2750,5 @@ BOOLEAN_T esock_is_integer(ErlNifEnv *env, ERL_NIF_TERM term)
else
return FALSE;
}
+
+#endif
diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h
index af58c15377..2533ee145a 100644
--- a/erts/emulator/nifs/common/socket_util.h
+++ b/erts/emulator/nifs/common/socket_util.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2018-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2018-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,9 @@
#define LONG(L) ((long) (L))
#define ULONG(L) ((unsigned long) (L))
#define SZT(I) ((size_t) (I))
+#ifndef VOID
#define VOID(D) ((void) (D))
+#endif
#define VOIDP(P) ((void*) (P))
#define CHARP(P) ((char*) (P))
#define UCHARP(P) ((unsigned char*) (P))
@@ -54,13 +56,13 @@ extern
BOOLEAN_T esock_decode_iov(ErlNifEnv* env,
ERL_NIF_TERM eIOV,
ErlNifBinary* bufs,
- struct iovec* iov,
+ SysIOVec* iov,
size_t len,
ssize_t* totSize);
extern
void esock_encode_iov(ErlNifEnv* env,
ssize_t read,
- struct iovec* iov,
+ SysIOVec* iov,
size_t len,
ErlNifBinary* data,
ERL_NIF_TERM* eIOV);
@@ -73,7 +75,7 @@ BOOLEAN_T esock_decode_sockaddr(ErlNifEnv* env,
extern
void esock_encode_sockaddr(ErlNifEnv* env,
ESockAddress* sockAddrP,
- SOCKLEN_T addrLen,
+ int addrLen,
ERL_NIF_TERM* eSockAddr);
extern
void esock_encode_hwsockaddr(ErlNifEnv* env,
diff --git a/erts/emulator/nifs/unix/unix_prim_file.c b/erts/emulator/nifs/unix/unix_prim_file.c
index 6d51ccd83b..2bb51651ef 100644
--- a/erts/emulator/nifs/unix/unix_prim_file.c
+++ b/erts/emulator/nifs/unix/unix_prim_file.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson 2017-2021. All Rights Reserved.
+ * Copyright Ericsson 2017-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,8 @@
#include <utime.h>
+#define FALLBACK_RW_LENGTH ((1ull << 31) - 1)
+
/* Macros for testing file types. */
#ifdef NO_UMASK
#define FILE_MODE 0644
@@ -139,11 +141,7 @@ static int get_flags(enum efile_modes_t modes) {
if(modes & EFILE_MODE_READ && !(modes & EFILE_MODE_WRITE)) {
flags |= O_RDONLY;
} else if(modes & EFILE_MODE_WRITE && !(modes & EFILE_MODE_READ)) {
- if(!(modes & EFILE_MODE_NO_TRUNCATE)) {
- flags |= O_TRUNC;
- }
-
- flags |= O_WRONLY | O_CREAT;
+ flags |= O_TRUNC | O_WRONLY | O_CREAT;
} else if(modes & EFILE_MODE_READ_WRITE) {
flags |= O_RDWR | O_CREAT;
} else {
@@ -317,6 +315,11 @@ Sint64 efile_readv(efile_data_t *d, SysIOVec *iov, int iovlen) {
if(use_fallback) {
result = read(u->fd, iov->iov_base, iov->iov_len);
+
+ /* Some OSs (e.g. macOS) does not allow reads greater than 2 GB,
+ so if we get EINVAL in the fallback, we try with a smaller length */
+ if (result < 0 && errno == EINVAL && iov->iov_len > FALLBACK_RW_LENGTH)
+ result = read(u->fd, iov->iov_base, FALLBACK_RW_LENGTH);
}
if(result > 0) {
@@ -362,6 +365,11 @@ Sint64 efile_writev(efile_data_t *d, SysIOVec *iov, int iovlen) {
if(use_fallback) {
result = write(u->fd, iov->iov_base, iov->iov_len);
+
+ /* Some OSs (e.g. macOS) does not allow writes greater than 2 GB,
+ so if we get EINVAL in the fallback, we try with a smaller length */
+ if (result < 0 && errno == EINVAL && iov->iov_len > FALLBACK_RW_LENGTH)
+ result = write(u->fd, iov->iov_base, FALLBACK_RW_LENGTH);
}
if(result > 0) {
@@ -542,7 +550,9 @@ int efile_sync(efile_data_t *d, int data_only) {
}
#endif
-#if defined(__DARWIN__) && defined(F_FULLFSYNC)
+#if defined(__DARWIN__) && defined(F_BARRIERFSYNC)
+ if(fcntl(u->fd, F_BARRIERFSYNC) < 0) {
+#elif defined(__DARWIN__) && defined(F_FULLFSYNC)
if(fcntl(u->fd, F_FULLFSYNC) < 0) {
#else
if(fsync(u->fd) < 0) {
diff --git a/erts/emulator/nifs/win32/win_prim_file.c b/erts/emulator/nifs/win32/win_prim_file.c
index 57797fad39..bdbf7a19d2 100644
--- a/erts/emulator/nifs/win32/win_prim_file.c
+++ b/erts/emulator/nifs/win32/win_prim_file.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson 2017-2021. All Rights Reserved.
+ * Copyright Ericsson 2017-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,11 +65,16 @@
#define TICKS_PER_SECOND (10000000ULL)
#define EPOCH_DIFFERENCE (11644473600LL)
+/* Note: some functions return a file time of -1 when the time is unavailable,
+ * rather than the documented 0, so we'll silently convert it to 0. */ \
#define FILETIME_TO_EPOCH(epoch, ft) \
do { \
ULARGE_INTEGER ull; \
ull.LowPart = (ft).dwLowDateTime; \
ull.HighPart = (ft).dwHighDateTime; \
+ if (ull.QuadPart == ~0ULL) { \
+ ull.QuadPart = 0; \
+ } \
(epoch) = ((ull.QuadPart / TICKS_PER_SECOND) - EPOCH_DIFFERENCE); \
} while(0)
@@ -85,7 +90,7 @@ typedef struct {
efile_data_t common;
HANDLE handle;
/* The following field is only used when the handle has been
- obtained from an already exisiting file descriptor (i.e.,
+ obtained from an already existing file descriptor (i.e.,
prim_file:file_desc_to_ref/2). common.modes is set to
EFILE_MODE_FROM_ALREADY_OPEN_FD when that is the case. It is
needed because we can't close using handle in that case. */
@@ -428,7 +433,7 @@ static int is_path_root(const efile_path_t *path) {
path_iterator++;
} while(path_iterator < path_end && !IS_SLASH(*path_iterator));
- /* If we're past the end of the string and it didnt't end with a slash,
+ /* If we're past the end of the string and it didn't end with a slash,
* then we're a root path. */
return path_iterator >= path_end && !IS_SLASH(path_start[length - 1]);
}
diff --git a/erts/emulator/pcre/local_config.h b/erts/emulator/pcre/local_config.h
index 178c4d4281..6f4f3a1868 100644
--- a/erts/emulator/pcre/local_config.h
+++ b/erts/emulator/pcre/local_config.h
@@ -73,9 +73,6 @@
"configure" can be used to override this default. */
#define POSIX_MALLOC_THRESHOLD 10
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
/* Define to enable support for Unicode properties */
#define SUPPORT_UCP
diff --git a/erts/emulator/pcre/pcre_compile.c b/erts/emulator/pcre/pcre_compile.c
index 80b966869a..94a7222e4d 100644
--- a/erts/emulator/pcre/pcre_compile.c
+++ b/erts/emulator/pcre/pcre_compile.c
@@ -4834,7 +4834,7 @@ for (;; ptr++)
If the class contains characters outside the 0-255 range, a different
opcode is compiled. It may optionally have a bit map for characters < 256,
- but those above are are explicitly listed afterwards. A flag byte tells
+ but those above are explicitly listed afterwards. A flag byte tells
whether the bitmap is present, and whether this is a negated class or not.
In JavaScript compatibility mode, an isolated ']' causes an error. In
@@ -5855,7 +5855,7 @@ for (;; ptr++)
/* If previous was a character type match (\d or similar), abolish it and
create a suitable repeat item. The code is shared with single-character
repeats by setting op_type to add a suitable offset into repeat_type. Note
- the the Unicode property types will be present only when SUPPORT_UCP is
+ the Unicode property types will be present only when SUPPORT_UCP is
defined, but we don't wrap the little bits of code here because it just
makes it horribly messy. */
@@ -7070,7 +7070,7 @@ for (;; ptr++)
/* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird
thing to do, but Perl allows all assertions to be quantified, and when
they contain capturing parentheses there may be a potential use for
- this feature. Not that that applies to a quantified (?!) but we allow
+ this feature. Not that applies to a quantified (?!) but we allow
it for uniformity. */
/* ------------------------------------------------------------ */
diff --git a/erts/emulator/pcre/pcre_exec.c b/erts/emulator/pcre/pcre_exec.c
index 99c37f0657..bf7a9044ee 100644
--- a/erts/emulator/pcre/pcre_exec.c
+++ b/erts/emulator/pcre/pcre_exec.c
@@ -301,7 +301,7 @@ been known for decades.) So....
There is a fudge, triggered by defining NO_RECURSE, which avoids recursive
calls by keeping local variables that need to be preserved in blocks of memory
-obtained from malloc() instead instead of on the stack. Macros are used to
+obtained from malloc() instead of on the stack. Macros are used to
achieve this so that the actual code doesn't look very different to what it
always used to.
@@ -626,7 +626,7 @@ frame->Xoffset_top = offset_top;
frame->Xeptrb = eptrb;
frame->Xrdepth = rdepth;
-/* This is where control jumps back to to effect "recursion" */
+/* This is where control jumps back to effect "recursion" */
HEAP_RECURSE:
@@ -3213,7 +3213,7 @@ for (;;)
/* Match an extended character class. In the 8-bit library, this opcode is
- encountered only when UTF-8 mode mode is supported. In the 16-bit and
+ encountered only when UTF-8 mode is supported. In the 16-bit and
32-bit libraries, codepoints greater than 255 may be encountered even when
UTF is not supported. */
@@ -7023,7 +7023,7 @@ if (extra_data != NULL)
{
md->loop_limit = extra_data->loop_limit;
if (extra_data->restart_data)
- md->loop_limit -= extra_data->loop_limit - exec_context->valid_utf_ystate.cnt;
+ md->loop_limit -= exec_context->valid_utf_ystate.cnt;
if (md->loop_limit < 10)
md->loop_limit = 10; /* At least do something if we've come this far... */
}
@@ -7371,7 +7371,7 @@ for(;;)
break;
}
- /* If req_char is set, we know that that character must appear in the
+ /* If req_char is set, we know that character must appear in the
subject for the match to succeed. If the first character is set, req_char
must be later in the subject; otherwise the test starts at the match point.
This optimization can save a huge amount of backtracking in patterns with
diff --git a/erts/emulator/pcre/pcre_maketables.c b/erts/emulator/pcre/pcre_maketables.c
index 89204d1152..7877a577e9 100644
--- a/erts/emulator/pcre/pcre_maketables.c
+++ b/erts/emulator/pcre/pcre_maketables.c
@@ -108,7 +108,7 @@ exclusive ones - in some locales things may be different.
Note that the table for "space" includes everything "isspace" gives, including
VT in the default locale. This makes it work for the POSIX class [:space:].
-From release 8.34 is is also correct for Perl space, because Perl added VT at
+From release 8.34 is also correct for Perl space, because Perl added VT at
release 5.18.
Note also that it is possible for a character to be alnum or alpha without
diff --git a/erts/emulator/pcre/pcre_valid_utf8.c b/erts/emulator/pcre/pcre_valid_utf8.c
index 1dc1f9ba0c..95a60c3fdb 100644
--- a/erts/emulator/pcre/pcre_valid_utf8.c
+++ b/erts/emulator/pcre/pcre_valid_utf8.c
@@ -219,7 +219,7 @@ for (p = string; length-- > 0; p++)
switch (ab)
{
/* 2-byte character. No further bytes to check for 0x80. Check first byte
- for for xx00 000x (overlong sequence). */
+ for xx00 000x (overlong sequence). */
case 1: if ((c & 0x3e) == 0)
{
@@ -251,7 +251,7 @@ for (p = string; length-- > 0; p++)
break;
/* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2
- bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a
+ bytes for 1111 0000, xx00 xxxx (overlong sequence), then check for a
character greater than 0x0010ffff (f4 8f bf bf) */
case 3:
diff --git a/erts/emulator/ryu/README.ryu_update.md b/erts/emulator/ryu/README.ryu_update.md
new file mode 100644
index 0000000000..cc60ea1690
--- /dev/null
+++ b/erts/emulator/ryu/README.ryu_update.md
@@ -0,0 +1,20 @@
+# How to update the Ryu version used by Erlang
+
+Last commit taken : 844864ac213bdbf1fb57e6f51c653b3d90af0937
+
+## The basic changes to the Ryu library
+
+To work with the Erlang VM, Ryu has been changed in three important ways. These
+changes have been marked with a `//CHANGE_FOR_ERLANG` comment explaining them in
+the code.
+
+1. We only kept the bare minimum files needed to generate a double to string with the shortest algorithm, with the widest lookup table
+2. We deleted the code producing the final string, this is handled using a modified version of to_chars from the MS STL. <https://github.com/microsoft/STL/blob/8f4c8163775d665d80642044ce27c4bc696127ce/stl/inc/xcharconv_ryu.h#L1302>
+3. All other unneeded code has been deleted
+
+This is build with our own makefile.
+
+Some of the more minor difference:
+
+- the Zero case in common.h is changed to correspond to erlang fixed point version
+- the MS STL pointer check are not here. Erlang generate a 256 bytes buffer, we only need 30 maximum. Beware what this mean when refactoring.
diff --git a/erts/emulator/ryu/common.h b/erts/emulator/ryu/common.h
new file mode 100644
index 0000000000..7048e90974
--- /dev/null
+++ b/erts/emulator/ryu/common.h
@@ -0,0 +1,115 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_COMMON_H
+#define RYU_COMMON_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_M_IX86) || defined(_M_ARM)
+#define RYU_32_BIT_PLATFORM
+#endif
+
+// Returns the number of decimal digits in v, which must not contain more than 9 digits.
+static inline uint32_t decimalLength9(const uint32_t v) {
+ // Function precondition: v is not a 10-digit number.
+ // (f2s: 9 digits are sufficient for round-tripping.)
+ // (d2fixed: We print 9-digit blocks.)
+ assert(v < 1000000000);
+ if (v >= 100000000) { return 9; }
+ if (v >= 10000000) { return 8; }
+ if (v >= 1000000) { return 7; }
+ if (v >= 100000) { return 6; }
+ if (v >= 10000) { return 5; }
+ if (v >= 1000) { return 4; }
+ if (v >= 100) { return 3; }
+ if (v >= 10) { return 2; }
+ return 1;
+}
+
+// Returns e == 0 ? 1 : [log_2(5^e)]; requires 0 <= e <= 3528.
+static inline int32_t log2pow5(const int32_t e) {
+ // This approximation works up to the point that the multiplication overflows at e = 3529.
+ // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
+ // than 2^9297.
+ assert(e >= 0);
+ assert(e <= 3528);
+ return (int32_t) ((((uint32_t) e) * 1217359) >> 19);
+}
+
+// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 3528.
+static inline int32_t pow5bits(const int32_t e) {
+ // This approximation works up to the point that the multiplication overflows at e = 3529.
+ // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
+ // than 2^9297.
+ assert(e >= 0);
+ assert(e <= 3528);
+ return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1);
+}
+
+// Returns e == 0 ? 1 : ceil(log_2(5^e)); requires 0 <= e <= 3528.
+static inline int32_t ceil_log2pow5(const int32_t e) {
+ return log2pow5(e) + 1;
+}
+
+// Returns floor(log_10(2^e)); requires 0 <= e <= 1650.
+static inline uint32_t log10Pow2(const int32_t e) {
+ // The first value this approximation fails for is 2^1651 which is just greater than 10^297.
+ assert(e >= 0);
+ assert(e <= 1650);
+ return (((uint32_t) e) * 78913) >> 18;
+}
+
+// Returns floor(log_10(5^e)); requires 0 <= e <= 2620.
+static inline uint32_t log10Pow5(const int32_t e) {
+ // The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
+ assert(e >= 0);
+ assert(e <= 2620);
+ return (((uint32_t) e) * 732923) >> 20;
+}
+
+static inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) {
+ if (mantissa) {
+ memcpy(result, "NaN", 3);
+ return 3;
+ }
+ if (sign) {
+ result[0] = '-';
+ }
+ if (exponent) {
+ memcpy(result + sign, "Infinity", 8);
+ return sign + 8;
+ }
+ // CHANGE_FOR_ERLANG we use "0.0" as the 0 and not "0E0"
+ memcpy(result + sign, "0.0", 3);
+ return sign + 3;
+}
+
+static inline uint32_t float_to_bits(const float f) {
+ uint32_t bits = 0;
+ memcpy(&bits, &f, sizeof(float));
+ return bits;
+}
+
+static inline uint64_t double_to_bits(const double d) {
+ uint64_t bits = 0;
+ memcpy(&bits, &d, sizeof(double));
+ return bits;
+}
+
+#endif // RYU_COMMON_H
diff --git a/erts/emulator/ryu/d2s.c b/erts/emulator/ryu/d2s.c
new file mode 100644
index 0000000000..643e41ce02
--- /dev/null
+++ b/erts/emulator/ryu/d2s.c
@@ -0,0 +1,712 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+
+// Runtime compiler options:
+// -DRYU_DEBUG Generate verbose debugging output to stdout.
+//
+// -DRYU_ONLY_64_BIT_OPS Avoid using uint128_t or 64-bit intrinsics. Slower,
+// depending on your compiler.
+//
+
+// CHANGE_FOR_ERLANG: "ryu/ryu.h" -> "ryu.h"
+#include "ryu.h"
+// END CHANGE_FOR_ERLANG
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef RYU_DEBUG
+#include <inttypes.h>
+#include <stdio.h>
+#endif
+
+// CHANGE_FOR_ERLANG: "ryu/*.h" -> "*.h"
+#include "common.h"
+#include "digit_table.h"
+#include "d2s_intrinsics.h"
+// END CHANGE_FOR_ERLANG
+
+// CHANGE_FOR_ERLANG we got rid of the small_table. Also namespace as above
+#include "d2s_full_table.h"
+// END CHANGE_FOR_ERLANG
+
+#define DOUBLE_MANTISSA_BITS 52
+#define DOUBLE_EXPONENT_BITS 11
+#define DOUBLE_BIAS 1023
+
+static inline uint32_t decimalLength17(const uint64_t v) {
+ // This is slightly faster than a loop.
+ // The average output length is 16.38 digits, so we check high-to-low.
+ // Function precondition: v is not an 18, 19, or 20-digit number.
+ // (17 digits are sufficient for round-tripping.)
+ assert(v < 100000000000000000L);
+ if (v >= 10000000000000000L) { return 17; }
+ if (v >= 1000000000000000L) { return 16; }
+ if (v >= 100000000000000L) { return 15; }
+ if (v >= 10000000000000L) { return 14; }
+ if (v >= 1000000000000L) { return 13; }
+ if (v >= 100000000000L) { return 12; }
+ if (v >= 10000000000L) { return 11; }
+ if (v >= 1000000000L) { return 10; }
+ if (v >= 100000000L) { return 9; }
+ if (v >= 10000000L) { return 8; }
+ if (v >= 1000000L) { return 7; }
+ if (v >= 100000L) { return 6; }
+ if (v >= 10000L) { return 5; }
+ if (v >= 1000L) { return 4; }
+ if (v >= 100L) { return 3; }
+ if (v >= 10L) { return 2; }
+ return 1;
+}
+
+// A floating decimal representing m * 10^e.
+typedef struct floating_decimal_64 {
+ uint64_t mantissa;
+ // Decimal exponent's range is -324 to 308
+ // inclusive, and can fit in a short if needed.
+ int32_t exponent;
+} floating_decimal_64;
+
+static inline floating_decimal_64 d2d(const uint64_t ieeeMantissa, const uint32_t ieeeExponent) {
+ int32_t e2;
+ uint64_t m2;
+ if (ieeeExponent == 0) {
+ // We subtract 2 so that the bounds computation has 2 additional bits.
+ e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+ m2 = ieeeMantissa;
+ } else {
+ e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
+ m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+ }
+ const bool even = (m2 & 1) == 0;
+ const bool acceptBounds = even;
+
+#ifdef RYU_DEBUG
+ printf("-> %" PRIu64 " * 2^%d\n", m2, e2 + 2);
+#endif
+
+ // Step 2: Determine the interval of valid decimal representations.
+ const uint64_t mv = 4 * m2;
+ // Implicit bool -> int conversion. True is 1, false is 0.
+ const uint32_t mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
+ // We would compute mp and mm like this:
+ // uint64_t mp = 4 * m2 + 2;
+ // uint64_t mm = mv - 1 - mmShift;
+
+ // Step 3: Convert to a decimal power base using 128-bit arithmetic.
+ uint64_t vr, vp, vm;
+ int32_t e10;
+ bool vmIsTrailingZeros = false;
+ bool vrIsTrailingZeros = false;
+ if (e2 >= 0) {
+ // I tried special-casing q == 0, but there was no effect on performance.
+ // This expression is slightly faster than max(0, log10Pow2(e2) - 1).
+ const uint32_t q = log10Pow2(e2) - (e2 > 3);
+ e10 = (int32_t) q;
+ const int32_t k = DOUBLE_POW5_INV_BITCOUNT + pow5bits((int32_t) q) - 1;
+ const int32_t i = -e2 + (int32_t) q + k;
+ vr = mulShiftAll64(m2, DOUBLE_POW5_INV_SPLIT[q], i, &vp, &vm, mmShift);
+#ifdef RYU_DEBUG
+ printf("%" PRIu64 " * 2^%d / 10^%u\n", mv, e2, q);
+ printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+#endif
+ if (q <= 21) {
+ // This should use q <= 22, but I think 21 is also safe. Smaller values
+ // may still be safe, but it's more difficult to reason about them.
+ // Only one of mp, mv, and mm can be a multiple of 5, if any.
+ const uint32_t mvMod5 = ((uint32_t) mv) - 5 * ((uint32_t) div5(mv));
+ if (mvMod5 == 0) {
+ vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
+ } else if (acceptBounds) {
+ // Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
+ // <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
+ // <=> true && pow5Factor(mm) >= q, since e2 >= q.
+ vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
+ } else {
+ // Same as min(e2 + 1, pow5Factor(mp)) >= q.
+ vp -= multipleOfPowerOf5(mv + 2, q);
+ }
+ }
+ } else {
+ // This expression is slightly faster than max(0, log10Pow5(-e2) - 1).
+ const uint32_t q = log10Pow5(-e2) - (-e2 > 1);
+ e10 = (int32_t) q + e2;
+ const int32_t i = -e2 - (int32_t) q;
+ const int32_t k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
+ const int32_t j = (int32_t) q - k;
+ vr = mulShiftAll64(m2, DOUBLE_POW5_SPLIT[i], j, &vp, &vm, mmShift);
+#ifdef RYU_DEBUG
+ printf("%" PRIu64 " * 5^%d / 10^%u\n", mv, -e2, q);
+ printf("%u %d %d %d\n", q, i, k, j);
+ printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+#endif
+ if (q <= 1) {
+ // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
+ // mv = 4 * m2, so it always has at least two trailing 0 bits.
+ vrIsTrailingZeros = true;
+ if (acceptBounds) {
+ // mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff mmShift == 1.
+ vmIsTrailingZeros = mmShift == 1;
+ } else {
+ // mp = mv + 2, so it always has at least one trailing 0 bit.
+ --vp;
+ }
+ } else if (q < 63) { // TODO(ulfjack): Use a tighter bound here.
+ // We want to know if the full product has at least q trailing zeros.
+ // We need to compute min(p2(mv), p5(mv) - e2) >= q
+ // <=> p2(mv) >= q && p5(mv) - e2 >= q
+ // <=> p2(mv) >= q (because -e2 >= q)
+ vrIsTrailingZeros = multipleOfPowerOf2(mv, q);
+#ifdef RYU_DEBUG
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+ }
+ }
+#ifdef RYU_DEBUG
+ printf("e10=%d\n", e10);
+ printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+ printf("vm is trailing zeros=%s\n", vmIsTrailingZeros ? "true" : "false");
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+
+ // Step 4: Find the shortest decimal representation in the interval of valid representations.
+ int32_t removed = 0;
+ uint8_t lastRemovedDigit = 0;
+ uint64_t output;
+ // On average, we remove ~2 digits.
+ if (vmIsTrailingZeros || vrIsTrailingZeros) {
+ // General case, which happens rarely (~0.7%).
+ for (;;) {
+ const uint64_t vpDiv10 = div10(vp);
+ const uint64_t vmDiv10 = div10(vm);
+ if (vpDiv10 <= vmDiv10) {
+ break;
+ }
+ const uint32_t vmMod10 = ((uint32_t) vm) - 10 * ((uint32_t) vmDiv10);
+ const uint64_t vrDiv10 = div10(vr);
+ const uint32_t vrMod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrDiv10);
+ vmIsTrailingZeros &= vmMod10 == 0;
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = (uint8_t) vrMod10;
+ vr = vrDiv10;
+ vp = vpDiv10;
+ vm = vmDiv10;
+ ++removed;
+ }
+#ifdef RYU_DEBUG
+ printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+ printf("d-10=%s\n", vmIsTrailingZeros ? "true" : "false");
+#endif
+ if (vmIsTrailingZeros) {
+ for (;;) {
+ const uint64_t vmDiv10 = div10(vm);
+ const uint32_t vmMod10 = ((uint32_t) vm) - 10 * ((uint32_t) vmDiv10);
+ if (vmMod10 != 0) {
+ break;
+ }
+ const uint64_t vpDiv10 = div10(vp);
+ const uint64_t vrDiv10 = div10(vr);
+ const uint32_t vrMod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrDiv10);
+ vrIsTrailingZeros &= lastRemovedDigit == 0;
+ lastRemovedDigit = (uint8_t) vrMod10;
+ vr = vrDiv10;
+ vp = vpDiv10;
+ vm = vmDiv10;
+ ++removed;
+ }
+ }
+#ifdef RYU_DEBUG
+ printf("%" PRIu64 " %d\n", vr, lastRemovedDigit);
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+ if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0) {
+ // Round even if the exact number is .....50..0.
+ lastRemovedDigit = 4;
+ }
+ // We need to take vr + 1 if vr is outside bounds or we need to round up.
+ output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
+ } else {
+ // Specialized for the common case (~99.3%). Percentages below are relative to this.
+ bool roundUp = false;
+ const uint64_t vpDiv100 = div100(vp);
+ const uint64_t vmDiv100 = div100(vm);
+ if (vpDiv100 > vmDiv100) { // Optimization: remove two digits at a time (~86.2%).
+ const uint64_t vrDiv100 = div100(vr);
+ const uint32_t vrMod100 = ((uint32_t) vr) - 100 * ((uint32_t) vrDiv100);
+ roundUp = vrMod100 >= 50;
+ vr = vrDiv100;
+ vp = vpDiv100;
+ vm = vmDiv100;
+ removed += 2;
+ }
+ // Loop iterations below (approximately), without optimization above:
+ // 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
+ // Loop iterations below (approximately), with optimization above:
+ // 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
+ for (;;) {
+ const uint64_t vpDiv10 = div10(vp);
+ const uint64_t vmDiv10 = div10(vm);
+ if (vpDiv10 <= vmDiv10) {
+ break;
+ }
+ const uint64_t vrDiv10 = div10(vr);
+ const uint32_t vrMod10 = ((uint32_t) vr) - 10 * ((uint32_t) vrDiv10);
+ roundUp = vrMod10 >= 5;
+ vr = vrDiv10;
+ vp = vpDiv10;
+ vm = vmDiv10;
+ ++removed;
+ }
+#ifdef RYU_DEBUG
+ printf("%" PRIu64 " roundUp=%s\n", vr, roundUp ? "true" : "false");
+ printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
+#endif
+ // We need to take vr + 1 if vr is outside bounds or we need to round up.
+ output = vr + (vr == vm || roundUp);
+ }
+ const int32_t exp = e10 + removed;
+
+#ifdef RYU_DEBUG
+ printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
+ printf("O=%" PRIu64 "\n", output);
+ printf("EXP=%d\n", exp);
+#endif
+
+ floating_decimal_64 fd;
+ fd.exponent = exp;
+ fd.mantissa = output;
+ return fd;
+}
+
+//CHANGE_FOR_ERLANG: This format is new, it is here to handle the different format switch used in the STL code
+enum chars_format {
+ FMT_SCIENTIFIC,
+ FMT_FIXED,
+ FMT_GENERAL
+};
+
+// This is inspired from the MS STL Charconv, under Apache with LLVM exception licence
+// see https://github.com/microsoft/STL/blob/main/LICENSE.txt
+// The inspiration is at https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/inc/xcharconv_ryu.h#L1926
+// CHANGE_FOR_ERLANG all the types and typecast have been adapted to C types from Cpp.
+// I have also kept the Ryu original function head as it allows to not impact the rest of the code
+// __v and __mantissa and __exponent have lost their double underscore over the whole function
+// all the test on the lenght of the buffer have been dropped too. This could need change, but
+// we always pass a 256 bytes buffer when we only need 26 bytes maximum.
+static inline int to_chars(const floating_decimal_64 v, const bool sign, char* const result) {
+ // Step 5: Print the decimal representation.
+ uint64_t __output = v.mantissa;
+ int32_t _Ryu_exponent = v.exponent;
+ const uint32_t __olength = decimalLength17(__output);
+ int32_t _Scientific_exponent = _Ryu_exponent + ((int32_t) __olength) - 1;
+
+ // CHANGE_FOR_ERLANG: we use our chars_format instead of the STL one
+ enum chars_format _Fmt;
+
+ int32_t _Lower;
+ int32_t _Upper;
+
+ if (__olength == 1) {
+ // CHANGE_FOR_ERLANG the format and examples have been adapted to the erlang format
+ // as the original would have not shown a change in format
+ // (erlang always add ".0" to scientific format) and omit the + in the exponent
+ // Value | Fixed | Scientific
+ // 1e-4 | "0.0001" | "1.0e-4"
+ // 1e2 | "100.0" | "1.0e2"
+ // CHANGE_FOR_ERLANG the values for a switch, as seen in the example above, for erlang
+ // are different than for STL format.
+ _Lower = -4;
+ _Upper = 2;
+ } else if (_Scientific_exponent >= 10) {
+ // CHANGE_FOR_ERLANG This case does not exist for the STL and is due to the
+ // negative sign in the exponent.
+ // Value | Fixed | Scientific
+ // 123456789e1 | "1234567890.0" | "1.23456789e9"
+ // 123456789e2 | "12345678900.0" | "1.23456789e10"
+
+ _Lower = - (int32_t) (__olength + 2);
+ _Upper = 2;
+ } else {
+ // CHANGE_FOR_ERLANG the format and examples have been adapted to the erlang format
+ // as the original would have not shown a change in format
+ // (erlang always add ".0" to scientific format) and omit the + in the exponent
+ // Value | Fixed | Scientific
+ // 1234e-6 | "0.001234" | "1.234e-4"
+ // 1234e1 | "12340.0" | "1.234e4"
+ // CHANGE_FOR_ERLANG the values for a switch, as seen in the example above, for erlang
+ // are different than for STL format.
+ _Lower = - (int32_t) (__olength + 2);
+ _Upper = 1;
+ }
+
+ if (_Lower <= _Ryu_exponent && _Ryu_exponent <= _Upper) {
+ // CHANGE_FOR_ERLANG this is added to handle the -2**53, 2**53 range special case
+ // These are edge cases not captured above, all the other are naturally handled
+ // by _Lower nad _Upper
+ if ((__output >= (1ull << 53) && _Ryu_exponent == 0)
+ || (__output > ((1ull << 52) / 5) && _Ryu_exponent == 1)
+ || (__output > ((1ull << 51) / 25) && _Ryu_exponent == 2)) {
+ _Fmt = FMT_SCIENTIFIC;
+ } else {
+ _Fmt = FMT_FIXED;
+ }
+ } else {
+ // CHANGE_FOR_ERLANG we do not need to handle the %g case here.
+ _Fmt = FMT_SCIENTIFIC;
+ }
+
+ // CHANGE_FOR_ERLANG we handle the sign here as it is handled outside of this in the STL case
+ // and we need it to compute the start of the buffer for the characters after
+ if (sign) {
+ result[0] = '-';
+ }
+
+ // CHANGE_FOR_ERLANG we compute the start of the usable buffer. It is done here
+ // in order to be fixed for both branches of formatting.
+ char* const __result = result + sign;
+
+ if (_Fmt == FMT_FIXED) {
+ // CHANGE_FOR_ERLANG this whole table has been adapted to erlang examples to help
+ // debug and evolve the edge cases
+ // Example: __output == 1729, __olength == 4
+
+ // _Ryu_exponent | Printed | _Whole_digits | _Total_fixed_length | Notes
+ // --------------|----------|---------------|----------------------|---------------------------------------
+ // 1 | 17290.0 | 5 | _Whole_digits + 2 | Unified length cases.
+ // 0 | 1729.0 | 4 | |
+ // --------------|----------|---------------|----------------------|---------------------------------------
+ // -1 | 172.9 | 3 | __olength + 1 | This case can't happen for
+ // -2 | 17.29 | 2 | | __olength == 1, but no additional
+ // -3 | 1.729 | 1 | | code is needed to avoid it.
+ // --------------|----------|---------------|----------------------|---------------------------------------
+ // -4 | 0.1729 | 0 | 2 - _Ryu_exponent | If the decimal point appears, we need
+ // -5 | 0.01729 | -1 | | to put the "0" in front
+ // -6 | 0.001729 | -2 | |
+
+ const int32_t _Whole_digits = (int32_t) (__olength) + _Ryu_exponent;
+
+ uint32_t _Total_fixed_length;
+ if (_Ryu_exponent >= 0) {
+ // CHANGE_FOR_ERLANG the examples and values have been adapted to erlang format one
+ // CHANGE_FOR_ERLANG we also dropped the whole adjustement, as it is only of value
+ // for %f which we do not handle
+ // cases "17290.0" and "1729.0"
+ _Total_fixed_length = (uint32_t) (_Whole_digits) + 2;
+ } else if (_Whole_digits > 0) { // case "17.29"
+ _Total_fixed_length = __olength + 1;
+ } else { // case "0.001729"
+ _Total_fixed_length = (uint32_t) (2 - _Ryu_exponent);
+ }
+
+ char* _Mid;
+ if (_Ryu_exponent >= 0) { // case "172900.0"
+ // CHANGE_FOR_ERLANG we do not need the can_use_ryu, as we are not doing %f
+ // but always shortest round_trip. The whole complexity here is dropped
+ // Print the decimal digits, left-aligned within [result, result + _Total_fixed_length).
+ _Mid = __result + __olength;
+ } else { // cases "1729.0", "17.29", and "0.001729"
+ // Print the decimal digits, right-aligned within [result, result + _Total_fixed_length).
+ _Mid = __result + _Total_fixed_length;
+ }
+
+ // We prefer 32-bit operations, even on 64-bit platforms.
+ // We have at most 17 digits, and uint32_t can store 9 digits.
+ // If __output doesn't fit into uint32_t, we cut off 8 digits,
+ // so the rest will fit into uint32_t.
+ // CHANGE_FOR_ERLANG we consider in this whole thing that memcopy use the same
+ // char has defined in the DIGIT_TABLE
+ // CHANGE_FOR_ERLANG __DIGIT_TABLE became DIGIT_TABLE
+ if ((__output >> 32) != 0) {
+ // Expensive 64-bit division.
+ const uint64_t __q = div1e8(__output);
+ uint32_t __output2 = (uint32_t) (__output - 100000000 * __q);
+ __output = __q;
+
+ const uint32_t __c = __output2 % 10000;
+ __output2 /= 10000;
+ const uint32_t __d = __output2 % 10000;
+ const uint32_t __c0 = (__c % 100) << 1;
+ const uint32_t __c1 = (__c / 100) << 1;
+ const uint32_t __d0 = (__d % 100) << 1;
+ const uint32_t __d1 = (__d / 100) << 1;
+
+ memcpy(_Mid -= 2, DIGIT_TABLE + __c0, 2);
+ memcpy(_Mid -= 2, DIGIT_TABLE + __c1, 2);
+ memcpy(_Mid -= 2, DIGIT_TABLE + __d0, 2);
+ memcpy(_Mid -= 2, DIGIT_TABLE + __d1, 2);
+ }
+ uint32_t __output2 = (uint32_t) __output;
+ while (__output2 >= 10000) {
+#ifdef __clang__ // TRANSITION, LLVM-38217
+ const uint32_t __c = __output2 - 10000 * (__output2 / 10000);
+#else
+ const uint32_t __c = __output2 % 10000;
+#endif
+ __output2 /= 10000;
+ const uint32_t __c0 = (__c % 100) << 1;
+ const uint32_t __c1 = (__c / 100) << 1;
+ memcpy(_Mid -= 2, DIGIT_TABLE + __c0, 2);
+ memcpy(_Mid -= 2, DIGIT_TABLE + __c1, 2);
+ }
+ if (__output2 >= 100) {
+ const uint32_t __c = (__output2 % 100) << 1;
+ __output2 /= 100;
+ memcpy(_Mid -= 2, DIGIT_TABLE + __c, 2);
+ }
+ if (__output2 >= 10) {
+ const uint32_t __c = __output2 << 1;
+ memcpy(_Mid -= 2, DIGIT_TABLE + __c, 2);
+ } else {
+ *--_Mid = (char) ('0' + __output2);
+ }
+
+ if (_Ryu_exponent > 0) { // case "172900.0"
+ // Performance note: it might be more efficient to do this immediately after setting _Mid.
+ // CHANGE_FOR_ERLANG we have different case here, so we have to add the ".0" here
+ // we use memset as we do not have access to fill_n
+ memset(__result + __olength, '0', (size_t) _Ryu_exponent);
+ __result[__olength + (size_t) _Ryu_exponent] = '.';
+ __result[__olength + (size_t) _Ryu_exponent + 1] = '0';
+ } else if (_Ryu_exponent == 0) { // case "1729.0"
+ // CHANGE_FOR_ERLANG we have different case here, so we have to add the ".0" here
+ __result[__olength] = '.';
+ __result[__olength + 1] = '0';
+ } else if (_Whole_digits > 0) { // case "17.29"
+ // Performance note: moving digits might not be optimal.
+ memmove(__result, __result + 1, (size_t) _Whole_digits);
+ __result[_Whole_digits] = '.';
+ } else { // case "0.001729"
+ // CHANGE_FOR_ERLANG we use the memset here as we do not have access to fill_n
+ // Performance note: a larger memset() followed by overwriting '.' might be more efficient.
+ __result[0] = '0';
+ __result[1] = '.';
+ memset(__result + 2, '0', (size_t) (-_Whole_digits));
+ }
+
+ // CHANGE_FOR_ERLANG we do not need the errc and we are only interested in
+ // returning the length, as it is what Ryu and erlang expect. We do add the
+ // sign as we did it here instead of adding it by default as in the STL
+ return _Total_fixed_length + sign;
+ }
+
+ uint32_t _Scientific_exponent_length;
+ // CHANGE_FOR_ERLANG we have to do a little bit more complex logic here because we do not always
+ // print the exponent sign, only if it is negative
+ if (_Scientific_exponent <= -100) { // "e-100"
+ _Scientific_exponent_length = 5;
+ } else if (_Scientific_exponent <= -10 || _Scientific_exponent >= 100) { // "e-10" or "e100"
+ _Scientific_exponent_length = 4;
+ } else if ((_Scientific_exponent > -10 && _Scientific_exponent < 0) || _Scientific_exponent >= 10) { // "e-9" or "e10"
+ _Scientific_exponent_length = 3;
+ } else { // "e1"
+ _Scientific_exponent_length = 2;
+ }
+
+ // CHANGE_FOR_ERLANG we do not need the ternary as we did all the logic above
+ const uint32_t _Total_scientific_length = __olength + 1 +(__olength == 1) // digits + decimal point + possible 0 after decimal point
+ + _Scientific_exponent_length; // + scientific exponent
+
+ // Print the decimal digits.
+ uint32_t __i = 0;
+ // We prefer 32-bit operations, even on 64-bit platforms.
+ // We have at most 17 digits, and uint32_t can store 9 digits.
+ // If __output doesn't fit into uint32_t, we cut off 8 digits,
+ // so the rest will fit into uint32_t.
+ // CHANGE_FOR_ERLANG we consider in this whole thing that memcopy use the same
+ // char has defined in the DIGIT_TABLE
+ // CHANGE_FOR_ERLANG __DIGIT_TABLE became DIGIT_TABLE
+ if ((__output >> 32) != 0) {
+ // Expensive 64-bit division.
+ const uint64_t __q = div1e8(__output);
+ uint32_t __output2 = (uint32_t) (__output) - 100000000 * (uint32_t) (__q);
+ __output = __q;
+
+ const uint32_t __c = __output2 % 10000;
+ __output2 /= 10000;
+ const uint32_t __d = __output2 % 10000;
+ const uint32_t __c0 = (__c % 100) << 1;
+ const uint32_t __c1 = (__c / 100) << 1;
+ const uint32_t __d0 = (__d % 100) << 1;
+ const uint32_t __d1 = (__d / 100) << 1;
+ memcpy(__result + __olength - __i - 1, DIGIT_TABLE + __c0, 2);
+ memcpy(__result + __olength - __i - 3, DIGIT_TABLE + __c1, 2);
+ memcpy(__result + __olength - __i - 5, DIGIT_TABLE + __d0, 2);
+ memcpy(__result + __olength - __i - 7, DIGIT_TABLE + __d1, 2);
+ __i += 8;
+ }
+ uint32_t __output2 = (uint32_t) (__output);
+ while (__output2 >= 10000) {
+#ifdef __clang__ // TRANSITION, LLVM-38217
+ const uint32_t __c = __output2 - 10000 * (__output2 / 10000);
+#else
+ const uint32_t __c = __output2 % 10000;
+#endif
+ __output2 /= 10000;
+ const uint32_t __c0 = (__c % 100) << 1;
+ const uint32_t __c1 = (__c / 100) << 1;
+ memcpy(__result + __olength - __i - 1, DIGIT_TABLE + __c0, 2);
+ memcpy(__result + __olength - __i - 3, DIGIT_TABLE + __c1, 2);
+ __i += 4;
+ }
+ if (__output2 >= 100) {
+ const uint32_t __c = (__output2 % 100) << 1;
+ __output2 /= 100;
+ memcpy(__result + __olength - __i - 1, DIGIT_TABLE + __c, 2);
+ __i += 2;
+ }
+ if (__output2 >= 10) {
+ const uint32_t __c = __output2 << 1;
+ // We can't use memcpy here: the decimal dot goes between these two digits.
+ __result[2] = DIGIT_TABLE[__c + 1];
+ __result[0] = DIGIT_TABLE[__c];
+ } else {
+ __result[0] = (char) ('0' + __output2);
+ }
+
+ // Print decimal point if needed.
+ uint32_t __index;
+ if (__olength > 1) {
+ __result[1] = '.';
+ __index = __olength + 1;
+ } else {
+ // In erlang we _have_ to print the ".0" in the case this is an integer
+ __result[1] = '.';
+ __result[2] = '0';
+ __index = __olength + 2;
+ }
+
+ // Print the exponent.
+ __result[__index++] = 'e';
+ if (_Scientific_exponent < 0) {
+ __result[__index++] = '-';
+ _Scientific_exponent = -_Scientific_exponent;
+ }
+ // CHANGE_FOR_ERLANG no else, as we do not print the positive sign on the exponent
+
+ if (_Scientific_exponent >= 100) {
+ const int32_t __c = _Scientific_exponent % 10;
+ memcpy(__result + __index, DIGIT_TABLE + 2 * (_Scientific_exponent / 10), 2);
+ __result[__index + 2] = (char) ('0' + __c);
+ __index += 3;
+ } else if (_Scientific_exponent >= 10) {
+ // CHANGE_FOR_ERLANG we have to do this only if the exponent is larger than 10
+ memcpy(__result + __index, DIGIT_TABLE + 2 * _Scientific_exponent, 2);
+ __index += 2;
+ } else {
+ // CHANGE_FOR_ERLANG we can have an exponent under 10, which is not handled by the table
+ // so we handle it here
+ __result[__index++] = (char) ('0' + _Scientific_exponent);
+ }
+
+ // CHANGE_FOR_ERLANG we do not need the errc and we are only interested in
+ // returning the length, as it is what Ryu and erlang expect. We do add the
+ // sign as we did it here instead of adding it by default as in the STL
+ return _Total_scientific_length + sign;
+}
+// end of STL code, back to ryu
+
+static inline bool d2d_small_int(const uint64_t ieeeMantissa, const uint32_t ieeeExponent,
+ floating_decimal_64* const v) {
+ const uint64_t m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
+ const int32_t e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;
+
+ if (e2 > 0) {
+ // f = m2 * 2^e2 >= 2^53 is an integer.
+ // Ignore this case for now.
+ return false;
+ }
+
+ if (e2 < -52) {
+ // f < 1.
+ return false;
+ }
+
+ // Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52: 1 <= f = m2 / 2^-e2 < 2^53.
+ // Test if the lower -e2 bits of the significand are 0, i.e. whether the fraction is 0.
+ const uint64_t mask = (1ull << -e2) - 1;
+ const uint64_t fraction = m2 & mask;
+ if (fraction != 0) {
+ return false;
+ }
+
+ // f is an integer in the range [1, 2^53).
+ // Note: mantissa might contain trailing (decimal) 0's.
+ // Note: since 2^53 < 10^16, there is no need to adjust decimalLength17().
+ v->mantissa = m2 >> -e2;
+ v->exponent = 0;
+ return true;
+}
+
+int d2s_buffered_n(double f, char* result) {
+ // Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
+ const uint64_t bits = double_to_bits(f);
+
+#ifdef RYU_DEBUG
+ printf("IN=");
+ for (int32_t bit = 63; bit >= 0; --bit) {
+ printf("%d", (int) ((bits >> bit) & 1));
+ }
+ printf("\n");
+#endif
+
+ // Decode bits into sign, mantissa, and exponent.
+ const bool ieeeSign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
+ const uint64_t ieeeMantissa = bits & ((1ull << DOUBLE_MANTISSA_BITS) - 1);
+ const uint32_t ieeeExponent = (uint32_t) ((bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));
+ // Case distinction; exit early for the easy cases.
+ if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0)) {
+ return copy_special_str(result, ieeeSign, ieeeExponent, ieeeMantissa);
+ }
+
+ floating_decimal_64 v;
+ const bool isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, &v);
+ if (isSmallInt) {
+ // For small integers in the range [1, 2^53), v.mantissa might contain trailing (decimal) zeros.
+ // For scientific notation we need to move these zeros into the exponent.
+ // (This is not needed for fixed-point notation, so it might be beneficial to trim
+ // trailing zeros in to_chars only if needed - once fixed-point notation output is implemented.)
+ for (;;) {
+ const uint64_t q = div10(v.mantissa);
+ const uint32_t r = ((uint32_t) v.mantissa) - 10 * ((uint32_t) q);
+ if (r != 0) {
+ break;
+ }
+ v.mantissa = q;
+ ++v.exponent;
+ }
+ } else {
+ v = d2d(ieeeMantissa, ieeeExponent);
+ }
+
+ return to_chars(v, ieeeSign, result);
+}
+
+void d2s_buffered(double f, char* result) {
+ const int index = d2s_buffered_n(f, result);
+
+ // Terminate the string.
+ result[index] = '\0';
+}
+
+char* d2s(double f) {
+ char* const result = (char*) malloc(25);
+ d2s_buffered(f, result);
+ return result;
+}
diff --git a/erts/emulator/ryu/d2s_full_table.h b/erts/emulator/ryu/d2s_full_table.h
new file mode 100644
index 0000000000..c8629eef1b
--- /dev/null
+++ b/erts/emulator/ryu/d2s_full_table.h
@@ -0,0 +1,367 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_D2S_FULL_TABLE_H
+#define RYU_D2S_FULL_TABLE_H
+
+// These tables are generated by PrintDoubleLookupTable.
+#define DOUBLE_POW5_INV_BITCOUNT 125
+#define DOUBLE_POW5_BITCOUNT 125
+
+#define DOUBLE_POW5_INV_TABLE_SIZE 342
+#define DOUBLE_POW5_TABLE_SIZE 326
+
+static const uint64_t DOUBLE_POW5_INV_SPLIT[DOUBLE_POW5_INV_TABLE_SIZE][2] = {
+ { 1u, 2305843009213693952u }, { 11068046444225730970u, 1844674407370955161u },
+ { 5165088340638674453u, 1475739525896764129u }, { 7821419487252849886u, 1180591620717411303u },
+ { 8824922364862649494u, 1888946593147858085u }, { 7059937891890119595u, 1511157274518286468u },
+ { 13026647942995916322u, 1208925819614629174u }, { 9774590264567735146u, 1934281311383406679u },
+ { 11509021026396098440u, 1547425049106725343u }, { 16585914450600699399u, 1237940039285380274u },
+ { 15469416676735388068u, 1980704062856608439u }, { 16064882156130220778u, 1584563250285286751u },
+ { 9162556910162266299u, 1267650600228229401u }, { 7281393426775805432u, 2028240960365167042u },
+ { 16893161185646375315u, 1622592768292133633u }, { 2446482504291369283u, 1298074214633706907u },
+ { 7603720821608101175u, 2076918743413931051u }, { 2393627842544570617u, 1661534994731144841u },
+ { 16672297533003297786u, 1329227995784915872u }, { 11918280793837635165u, 2126764793255865396u },
+ { 5845275820328197809u, 1701411834604692317u }, { 15744267100488289217u, 1361129467683753853u },
+ { 3054734472329800808u, 2177807148294006166u }, { 17201182836831481939u, 1742245718635204932u },
+ { 6382248639981364905u, 1393796574908163946u }, { 2832900194486363201u, 2230074519853062314u },
+ { 5955668970331000884u, 1784059615882449851u }, { 1075186361522890384u, 1427247692705959881u },
+ { 12788344622662355584u, 2283596308329535809u }, { 13920024512871794791u, 1826877046663628647u },
+ { 3757321980813615186u, 1461501637330902918u }, { 10384555214134712795u, 1169201309864722334u },
+ { 5547241898389809503u, 1870722095783555735u }, { 4437793518711847602u, 1496577676626844588u },
+ { 10928932444453298728u, 1197262141301475670u }, { 17486291911125277965u, 1915619426082361072u },
+ { 6610335899416401726u, 1532495540865888858u }, { 12666966349016942027u, 1225996432692711086u },
+ { 12888448528943286597u, 1961594292308337738u }, { 17689456452638449924u, 1569275433846670190u },
+ { 14151565162110759939u, 1255420347077336152u }, { 7885109000409574610u, 2008672555323737844u },
+ { 9997436015069570011u, 1606938044258990275u }, { 7997948812055656009u, 1285550435407192220u },
+ { 12796718099289049614u, 2056880696651507552u }, { 2858676849947419045u, 1645504557321206042u },
+ { 13354987924183666206u, 1316403645856964833u }, { 17678631863951955605u, 2106245833371143733u },
+ { 3074859046935833515u, 1684996666696914987u }, { 13527933681774397782u, 1347997333357531989u },
+ { 10576647446613305481u, 2156795733372051183u }, { 15840015586774465031u, 1725436586697640946u },
+ { 8982663654677661702u, 1380349269358112757u }, { 18061610662226169046u, 2208558830972980411u },
+ { 10759939715039024913u, 1766847064778384329u }, { 12297300586773130254u, 1413477651822707463u },
+ { 15986332124095098083u, 2261564242916331941u }, { 9099716884534168143u, 1809251394333065553u },
+ { 14658471137111155161u, 1447401115466452442u }, { 4348079280205103483u, 1157920892373161954u },
+ { 14335624477811986218u, 1852673427797059126u }, { 7779150767507678651u, 1482138742237647301u },
+ { 2533971799264232598u, 1185710993790117841u }, { 15122401323048503126u, 1897137590064188545u },
+ { 12097921058438802501u, 1517710072051350836u }, { 5988988032009131678u, 1214168057641080669u },
+ { 16961078480698431330u, 1942668892225729070u }, { 13568862784558745064u, 1554135113780583256u },
+ { 7165741412905085728u, 1243308091024466605u }, { 11465186260648137165u, 1989292945639146568u },
+ { 16550846638002330379u, 1591434356511317254u }, { 16930026125143774626u, 1273147485209053803u },
+ { 4951948911778577463u, 2037035976334486086u }, { 272210314680951647u, 1629628781067588869u },
+ { 3907117066486671641u, 1303703024854071095u }, { 6251387306378674625u, 2085924839766513752u },
+ { 16069156289328670670u, 1668739871813211001u }, { 9165976216721026213u, 1334991897450568801u },
+ { 7286864317269821294u, 2135987035920910082u }, { 16897537898041588005u, 1708789628736728065u },
+ { 13518030318433270404u, 1367031702989382452u }, { 6871453250525591353u, 2187250724783011924u },
+ { 9186511415162383406u, 1749800579826409539u }, { 11038557946871817048u, 1399840463861127631u },
+ { 10282995085511086630u, 2239744742177804210u }, { 8226396068408869304u, 1791795793742243368u },
+ { 13959814484210916090u, 1433436634993794694u }, { 11267656730511734774u, 2293498615990071511u },
+ { 5324776569667477496u, 1834798892792057209u }, { 7949170070475892320u, 1467839114233645767u },
+ { 17427382500606444826u, 1174271291386916613u }, { 5747719112518849781u, 1878834066219066582u },
+ { 15666221734240810795u, 1503067252975253265u }, { 12532977387392648636u, 1202453802380202612u },
+ { 5295368560860596524u, 1923926083808324180u }, { 4236294848688477220u, 1539140867046659344u },
+ { 7078384693692692099u, 1231312693637327475u }, { 11325415509908307358u, 1970100309819723960u },
+ { 9060332407926645887u, 1576080247855779168u }, { 14626963555825137356u, 1260864198284623334u },
+ { 12335095245094488799u, 2017382717255397335u }, { 9868076196075591040u, 1613906173804317868u },
+ { 15273158586344293478u, 1291124939043454294u }, { 13369007293925138595u, 2065799902469526871u },
+ { 7005857020398200553u, 1652639921975621497u }, { 16672732060544291412u, 1322111937580497197u },
+ { 11918976037903224966u, 2115379100128795516u }, { 5845832015580669650u, 1692303280103036413u },
+ { 12055363241948356366u, 1353842624082429130u }, { 841837113407818570u, 2166148198531886609u },
+ { 4362818505468165179u, 1732918558825509287u }, { 14558301248600263113u, 1386334847060407429u },
+ { 12225235553534690011u, 2218135755296651887u }, { 2401490813343931363u, 1774508604237321510u },
+ { 1921192650675145090u, 1419606883389857208u }, { 17831303500047873437u, 2271371013423771532u },
+ { 6886345170554478103u, 1817096810739017226u }, { 1819727321701672159u, 1453677448591213781u },
+ { 16213177116328979020u, 1162941958872971024u }, { 14873036941900635463u, 1860707134196753639u },
+ { 15587778368262418694u, 1488565707357402911u }, { 8780873879868024632u, 1190852565885922329u },
+ { 2981351763563108441u, 1905364105417475727u }, { 13453127855076217722u, 1524291284333980581u },
+ { 7073153469319063855u, 1219433027467184465u }, { 11317045550910502167u, 1951092843947495144u },
+ { 12742985255470312057u, 1560874275157996115u }, { 10194388204376249646u, 1248699420126396892u },
+ { 1553625868034358140u, 1997919072202235028u }, { 8621598323911307159u, 1598335257761788022u },
+ { 17965325103354776697u, 1278668206209430417u }, { 13987124906400001422u, 2045869129935088668u },
+ { 121653480894270168u, 1636695303948070935u }, { 97322784715416134u, 1309356243158456748u },
+ { 14913111714512307107u, 2094969989053530796u }, { 8241140556867935363u, 1675975991242824637u },
+ { 17660958889720079260u, 1340780792994259709u }, { 17189487779326395846u, 2145249268790815535u },
+ { 13751590223461116677u, 1716199415032652428u }, { 18379969808252713988u, 1372959532026121942u },
+ { 14650556434236701088u, 2196735251241795108u }, { 652398703163629901u, 1757388200993436087u },
+ { 11589965406756634890u, 1405910560794748869u }, { 7475898206584884855u, 2249456897271598191u },
+ { 2291369750525997561u, 1799565517817278553u }, { 9211793429904618695u, 1439652414253822842u },
+ { 18428218302589300235u, 2303443862806116547u }, { 7363877012587619542u, 1842755090244893238u },
+ { 13269799239553916280u, 1474204072195914590u }, { 10615839391643133024u, 1179363257756731672u },
+ { 2227947767661371545u, 1886981212410770676u }, { 16539753473096738529u, 1509584969928616540u },
+ { 13231802778477390823u, 1207667975942893232u }, { 6413489186596184024u, 1932268761508629172u },
+ { 16198837793502678189u, 1545815009206903337u }, { 5580372605318321905u, 1236652007365522670u },
+ { 8928596168509315048u, 1978643211784836272u }, { 18210923379033183008u, 1582914569427869017u },
+ { 7190041073742725760u, 1266331655542295214u }, { 436019273762630246u, 2026130648867672343u },
+ { 7727513048493924843u, 1620904519094137874u }, { 9871359253537050198u, 1296723615275310299u },
+ { 4726128361433549347u, 2074757784440496479u }, { 7470251503888749801u, 1659806227552397183u },
+ { 13354898832594820487u, 1327844982041917746u }, { 13989140502667892133u, 2124551971267068394u },
+ { 14880661216876224029u, 1699641577013654715u }, { 11904528973500979224u, 1359713261610923772u },
+ { 4289851098633925465u, 2175541218577478036u }, { 18189276137874781665u, 1740432974861982428u },
+ { 3483374466074094362u, 1392346379889585943u }, { 1884050330976640656u, 2227754207823337509u },
+ { 5196589079523222848u, 1782203366258670007u }, { 15225317707844309248u, 1425762693006936005u },
+ { 5913764258841343181u, 2281220308811097609u }, { 8420360221814984868u, 1824976247048878087u },
+ { 17804334621677718864u, 1459980997639102469u }, { 17932816512084085415u, 1167984798111281975u },
+ { 10245762345624985047u, 1868775676978051161u }, { 4507261061758077715u, 1495020541582440929u },
+ { 7295157664148372495u, 1196016433265952743u }, { 7982903447895485668u, 1913626293225524389u },
+ { 10075671573058298858u, 1530901034580419511u }, { 4371188443704728763u, 1224720827664335609u },
+ { 14372599139411386667u, 1959553324262936974u }, { 15187428126271019657u, 1567642659410349579u },
+ { 15839291315758726049u, 1254114127528279663u }, { 3206773216762499739u, 2006582604045247462u },
+ { 13633465017635730761u, 1605266083236197969u }, { 14596120828850494932u, 1284212866588958375u },
+ { 4907049252451240275u, 2054740586542333401u }, { 236290587219081897u, 1643792469233866721u },
+ { 14946427728742906810u, 1315033975387093376u }, { 16535586736504830250u, 2104054360619349402u },
+ { 5849771759720043554u, 1683243488495479522u }, { 15747863852001765813u, 1346594790796383617u },
+ { 10439186904235184007u, 2154551665274213788u }, { 15730047152871967852u, 1723641332219371030u },
+ { 12584037722297574282u, 1378913065775496824u }, { 9066413911450387881u, 2206260905240794919u },
+ { 10942479943902220628u, 1765008724192635935u }, { 8753983955121776503u, 1412006979354108748u },
+ { 10317025513452932081u, 2259211166966573997u }, { 874922781278525018u, 1807368933573259198u },
+ { 8078635854506640661u, 1445895146858607358u }, { 13841606313089133175u, 1156716117486885886u },
+ { 14767872471458792434u, 1850745787979017418u }, { 746251532941302978u, 1480596630383213935u },
+ { 597001226353042382u, 1184477304306571148u }, { 15712597221132509104u, 1895163686890513836u },
+ { 8880728962164096960u, 1516130949512411069u }, { 10793931984473187891u, 1212904759609928855u },
+ { 17270291175157100626u, 1940647615375886168u }, { 2748186495899949531u, 1552518092300708935u },
+ { 2198549196719959625u, 1242014473840567148u }, { 18275073973719576693u, 1987223158144907436u },
+ { 10930710364233751031u, 1589778526515925949u }, { 12433917106128911148u, 1271822821212740759u },
+ { 8826220925580526867u, 2034916513940385215u }, { 7060976740464421494u, 1627933211152308172u },
+ { 16716827836597268165u, 1302346568921846537u }, { 11989529279587987770u, 2083754510274954460u },
+ { 9591623423670390216u, 1667003608219963568u }, { 15051996368420132820u, 1333602886575970854u },
+ { 13015147745246481542u, 2133764618521553367u }, { 3033420566713364587u, 1707011694817242694u },
+ { 6116085268112601993u, 1365609355853794155u }, { 9785736428980163188u, 2184974969366070648u },
+ { 15207286772667951197u, 1747979975492856518u }, { 1097782973908629988u, 1398383980394285215u },
+ { 1756452758253807981u, 2237414368630856344u }, { 5094511021344956708u, 1789931494904685075u },
+ { 4075608817075965366u, 1431945195923748060u }, { 6520974107321544586u, 2291112313477996896u },
+ { 1527430471115325346u, 1832889850782397517u }, { 12289990821117991246u, 1466311880625918013u },
+ { 17210690286378213644u, 1173049504500734410u }, { 9090360384495590213u, 1876879207201175057u },
+ { 18340334751822203140u, 1501503365760940045u }, { 14672267801457762512u, 1201202692608752036u },
+ { 16096930852848599373u, 1921924308174003258u }, { 1809498238053148529u, 1537539446539202607u },
+ { 12515645034668249793u, 1230031557231362085u }, { 1578287981759648052u, 1968050491570179337u },
+ { 12330676829633449412u, 1574440393256143469u }, { 13553890278448669853u, 1259552314604914775u },
+ { 3239480371808320148u, 2015283703367863641u }, { 17348979556414297411u, 1612226962694290912u },
+ { 6500486015647617283u, 1289781570155432730u }, { 10400777625036187652u, 2063650512248692368u },
+ { 15699319729512770768u, 1650920409798953894u }, { 16248804598352126938u, 1320736327839163115u },
+ { 7551343283653851484u, 2113178124542660985u }, { 6041074626923081187u, 1690542499634128788u },
+ { 12211557331022285596u, 1352433999707303030u }, { 1091747655926105338u, 2163894399531684849u },
+ { 4562746939482794594u, 1731115519625347879u }, { 7339546366328145998u, 1384892415700278303u },
+ { 8053925371383123274u, 2215827865120445285u }, { 6443140297106498619u, 1772662292096356228u },
+ { 12533209867169019542u, 1418129833677084982u }, { 5295740528502789974u, 2269007733883335972u },
+ { 15304638867027962949u, 1815206187106668777u }, { 4865013464138549713u, 1452164949685335022u },
+ { 14960057215536570740u, 1161731959748268017u }, { 9178696285890871890u, 1858771135597228828u },
+ { 14721654658196518159u, 1487016908477783062u }, { 4398626097073393881u, 1189613526782226450u },
+ { 7037801755317430209u, 1903381642851562320u }, { 5630241404253944167u, 1522705314281249856u },
+ { 814844308661245011u, 1218164251424999885u }, { 1303750893857992017u, 1949062802279999816u },
+ { 15800395974054034906u, 1559250241823999852u }, { 5261619149759407279u, 1247400193459199882u },
+ { 12107939454356961969u, 1995840309534719811u }, { 5997002748743659252u, 1596672247627775849u },
+ { 8486951013736837725u, 1277337798102220679u }, { 2511075177753209390u, 2043740476963553087u },
+ { 13076906586428298482u, 1634992381570842469u }, { 14150874083884549109u, 1307993905256673975u },
+ { 4194654460505726958u, 2092790248410678361u }, { 18113118827372222859u, 1674232198728542688u },
+ { 3422448617672047318u, 1339385758982834151u }, { 16543964232501006678u, 2143017214372534641u },
+ { 9545822571258895019u, 1714413771498027713u }, { 15015355686490936662u, 1371531017198422170u },
+ { 5577825024675947042u, 2194449627517475473u }, { 11840957649224578280u, 1755559702013980378u },
+ { 16851463748863483271u, 1404447761611184302u }, { 12204946739213931940u, 2247116418577894884u },
+ { 13453306206113055875u, 1797693134862315907u }, { 3383947335406624054u, 1438154507889852726u },
+ { 16482362180876329456u, 2301047212623764361u }, { 9496540929959153242u, 1840837770099011489u },
+ { 11286581558709232917u, 1472670216079209191u }, { 5339916432225476010u, 1178136172863367353u },
+ { 4854517476818851293u, 1885017876581387765u }, { 3883613981455081034u, 1508014301265110212u },
+ { 14174937629389795797u, 1206411441012088169u }, { 11611853762797942306u, 1930258305619341071u },
+ { 5600134195496443521u, 1544206644495472857u }, { 15548153800622885787u, 1235365315596378285u },
+ { 6430302007287065643u, 1976584504954205257u }, { 16212288050055383484u, 1581267603963364205u },
+ { 12969830440044306787u, 1265014083170691364u }, { 9683682259845159889u, 2024022533073106183u },
+ { 15125643437359948558u, 1619218026458484946u }, { 8411165935146048523u, 1295374421166787957u },
+ { 17147214310975587960u, 2072599073866860731u }, { 10028422634038560045u, 1658079259093488585u },
+ { 8022738107230848036u, 1326463407274790868u }, { 9147032156827446534u, 2122341451639665389u },
+ { 11006974540203867551u, 1697873161311732311u }, { 5116230817421183718u, 1358298529049385849u },
+ { 15564666937357714594u, 2173277646479017358u }, { 1383687105660440706u, 1738622117183213887u },
+ { 12174996128754083534u, 1390897693746571109u }, { 8411947361780802685u, 2225436309994513775u },
+ { 6729557889424642148u, 1780349047995611020u }, { 5383646311539713719u, 1424279238396488816u },
+ { 1235136468979721303u, 2278846781434382106u }, { 15745504434151418335u, 1823077425147505684u },
+ { 16285752362063044992u, 1458461940118004547u }, { 5649904260166615347u, 1166769552094403638u },
+ { 5350498001524674232u, 1866831283351045821u }, { 591049586477829062u, 1493465026680836657u },
+ { 11540886113407994219u, 1194772021344669325u }, { 18673707743239135u, 1911635234151470921u },
+ { 14772334225162232601u, 1529308187321176736u }, { 8128518565387875758u, 1223446549856941389u },
+ { 1937583260394870242u, 1957514479771106223u }, { 8928764237799716840u, 1566011583816884978u },
+ { 14521709019723594119u, 1252809267053507982u }, { 8477339172590109297u, 2004494827285612772u },
+ { 17849917782297818407u, 1603595861828490217u }, { 6901236596354434079u, 1282876689462792174u },
+ { 18420676183650915173u, 2052602703140467478u }, { 3668494502695001169u, 1642082162512373983u },
+ { 10313493231639821582u, 1313665730009899186u }, { 9122891541139893884u, 2101865168015838698u },
+ { 14677010862395735754u, 1681492134412670958u }, { 673562245690857633u, 1345193707530136767u }
+};
+
+static const uint64_t DOUBLE_POW5_SPLIT[DOUBLE_POW5_TABLE_SIZE][2] = {
+ { 0u, 1152921504606846976u }, { 0u, 1441151880758558720u },
+ { 0u, 1801439850948198400u }, { 0u, 2251799813685248000u },
+ { 0u, 1407374883553280000u }, { 0u, 1759218604441600000u },
+ { 0u, 2199023255552000000u }, { 0u, 1374389534720000000u },
+ { 0u, 1717986918400000000u }, { 0u, 2147483648000000000u },
+ { 0u, 1342177280000000000u }, { 0u, 1677721600000000000u },
+ { 0u, 2097152000000000000u }, { 0u, 1310720000000000000u },
+ { 0u, 1638400000000000000u }, { 0u, 2048000000000000000u },
+ { 0u, 1280000000000000000u }, { 0u, 1600000000000000000u },
+ { 0u, 2000000000000000000u }, { 0u, 1250000000000000000u },
+ { 0u, 1562500000000000000u }, { 0u, 1953125000000000000u },
+ { 0u, 1220703125000000000u }, { 0u, 1525878906250000000u },
+ { 0u, 1907348632812500000u }, { 0u, 1192092895507812500u },
+ { 0u, 1490116119384765625u }, { 4611686018427387904u, 1862645149230957031u },
+ { 9799832789158199296u, 1164153218269348144u }, { 12249790986447749120u, 1455191522836685180u },
+ { 15312238733059686400u, 1818989403545856475u }, { 14528612397897220096u, 2273736754432320594u },
+ { 13692068767113150464u, 1421085471520200371u }, { 12503399940464050176u, 1776356839400250464u },
+ { 15629249925580062720u, 2220446049250313080u }, { 9768281203487539200u, 1387778780781445675u },
+ { 7598665485932036096u, 1734723475976807094u }, { 274959820560269312u, 2168404344971008868u },
+ { 9395221924704944128u, 1355252715606880542u }, { 2520655369026404352u, 1694065894508600678u },
+ { 12374191248137781248u, 2117582368135750847u }, { 14651398557727195136u, 1323488980084844279u },
+ { 13702562178731606016u, 1654361225106055349u }, { 3293144668132343808u, 2067951531382569187u },
+ { 18199116482078572544u, 1292469707114105741u }, { 8913837547316051968u, 1615587133892632177u },
+ { 15753982952572452864u, 2019483917365790221u }, { 12152082354571476992u, 1262177448353618888u },
+ { 15190102943214346240u, 1577721810442023610u }, { 9764256642163156992u, 1972152263052529513u },
+ { 17631875447420442880u, 1232595164407830945u }, { 8204786253993389888u, 1540743955509788682u },
+ { 1032610780636961552u, 1925929944387235853u }, { 2951224747111794922u, 1203706215242022408u },
+ { 3689030933889743652u, 1504632769052528010u }, { 13834660704216955373u, 1880790961315660012u },
+ { 17870034976990372916u, 1175494350822287507u }, { 17725857702810578241u, 1469367938527859384u },
+ { 3710578054803671186u, 1836709923159824231u }, { 26536550077201078u, 2295887403949780289u },
+ { 11545800389866720434u, 1434929627468612680u }, { 14432250487333400542u, 1793662034335765850u },
+ { 8816941072311974870u, 2242077542919707313u }, { 17039803216263454053u, 1401298464324817070u },
+ { 12076381983474541759u, 1751623080406021338u }, { 5872105442488401391u, 2189528850507526673u },
+ { 15199280947623720629u, 1368455531567204170u }, { 9775729147674874978u, 1710569414459005213u },
+ { 16831347453020981627u, 2138211768073756516u }, { 1296220121283337709u, 1336382355046097823u },
+ { 15455333206886335848u, 1670477943807622278u }, { 10095794471753144002u, 2088097429759527848u },
+ { 6309871544845715001u, 1305060893599704905u }, { 12499025449484531656u, 1631326116999631131u },
+ { 11012095793428276666u, 2039157646249538914u }, { 11494245889320060820u, 1274473528905961821u },
+ { 532749306367912313u, 1593091911132452277u }, { 5277622651387278295u, 1991364888915565346u },
+ { 7910200175544436838u, 1244603055572228341u }, { 14499436237857933952u, 1555753819465285426u },
+ { 8900923260467641632u, 1944692274331606783u }, { 12480606065433357876u, 1215432671457254239u },
+ { 10989071563364309441u, 1519290839321567799u }, { 9124653435777998898u, 1899113549151959749u },
+ { 8008751406574943263u, 1186945968219974843u }, { 5399253239791291175u, 1483682460274968554u },
+ { 15972438586593889776u, 1854603075343710692u }, { 759402079766405302u, 1159126922089819183u },
+ { 14784310654990170340u, 1448908652612273978u }, { 9257016281882937117u, 1811135815765342473u },
+ { 16182956370781059300u, 2263919769706678091u }, { 7808504722524468110u, 1414949856066673807u },
+ { 5148944884728197234u, 1768687320083342259u }, { 1824495087482858639u, 2210859150104177824u },
+ { 1140309429676786649u, 1381786968815111140u }, { 1425386787095983311u, 1727233711018888925u },
+ { 6393419502297367043u, 2159042138773611156u }, { 13219259225790630210u, 1349401336733506972u },
+ { 16524074032238287762u, 1686751670916883715u }, { 16043406521870471799u, 2108439588646104644u },
+ { 803757039314269066u, 1317774742903815403u }, { 14839754354425000045u, 1647218428629769253u },
+ { 4714634887749086344u, 2059023035787211567u }, { 9864175832484260821u, 1286889397367007229u },
+ { 16941905809032713930u, 1608611746708759036u }, { 2730638187581340797u, 2010764683385948796u },
+ { 10930020904093113806u, 1256727927116217997u }, { 18274212148543780162u, 1570909908895272496u },
+ { 4396021111970173586u, 1963637386119090621u }, { 5053356204195052443u, 1227273366324431638u },
+ { 15540067292098591362u, 1534091707905539547u }, { 14813398096695851299u, 1917614634881924434u },
+ { 13870059828862294966u, 1198509146801202771u }, { 12725888767650480803u, 1498136433501503464u },
+ { 15907360959563101004u, 1872670541876879330u }, { 14553786618154326031u, 1170419088673049581u },
+ { 4357175217410743827u, 1463023860841311977u }, { 10058155040190817688u, 1828779826051639971u },
+ { 7961007781811134206u, 2285974782564549964u }, { 14199001900486734687u, 1428734239102843727u },
+ { 13137066357181030455u, 1785917798878554659u }, { 11809646928048900164u, 2232397248598193324u },
+ { 16604401366885338411u, 1395248280373870827u }, { 16143815690179285109u, 1744060350467338534u },
+ { 10956397575869330579u, 2180075438084173168u }, { 6847748484918331612u, 1362547148802608230u },
+ { 17783057643002690323u, 1703183936003260287u }, { 17617136035325974999u, 2128979920004075359u },
+ { 17928239049719816230u, 1330612450002547099u }, { 17798612793722382384u, 1663265562503183874u },
+ { 13024893955298202172u, 2079081953128979843u }, { 5834715712847682405u, 1299426220705612402u },
+ { 16516766677914378815u, 1624282775882015502u }, { 11422586310538197711u, 2030353469852519378u },
+ { 11750802462513761473u, 1268970918657824611u }, { 10076817059714813937u, 1586213648322280764u },
+ { 12596021324643517422u, 1982767060402850955u }, { 5566670318688504437u, 1239229412751781847u },
+ { 2346651879933242642u, 1549036765939727309u }, { 7545000868343941206u, 1936295957424659136u },
+ { 4715625542714963254u, 1210184973390411960u }, { 5894531928393704067u, 1512731216738014950u },
+ { 16591536947346905892u, 1890914020922518687u }, { 17287239619732898039u, 1181821263076574179u },
+ { 16997363506238734644u, 1477276578845717724u }, { 2799960309088866689u, 1846595723557147156u },
+ { 10973347230035317489u, 1154122327223216972u }, { 13716684037544146861u, 1442652909029021215u },
+ { 12534169028502795672u, 1803316136286276519u }, { 11056025267201106687u, 2254145170357845649u },
+ { 18439230838069161439u, 1408840731473653530u }, { 13825666510731675991u, 1761050914342066913u },
+ { 3447025083132431277u, 2201313642927583642u }, { 6766076695385157452u, 1375821026829739776u },
+ { 8457595869231446815u, 1719776283537174720u }, { 10571994836539308519u, 2149720354421468400u },
+ { 6607496772837067824u, 1343575221513417750u }, { 17482743002901110588u, 1679469026891772187u },
+ { 17241742735199000331u, 2099336283614715234u }, { 15387775227926763111u, 1312085177259197021u },
+ { 5399660979626290177u, 1640106471573996277u }, { 11361262242960250625u, 2050133089467495346u },
+ { 11712474920277544544u, 1281333180917184591u }, { 10028907631919542777u, 1601666476146480739u },
+ { 7924448521472040567u, 2002083095183100924u }, { 14176152362774801162u, 1251301934489438077u },
+ { 3885132398186337741u, 1564127418111797597u }, { 9468101516160310080u, 1955159272639746996u },
+ { 15140935484454969608u, 1221974545399841872u }, { 479425281859160394u, 1527468181749802341u },
+ { 5210967620751338397u, 1909335227187252926u }, { 17091912818251750210u, 1193334516992033078u },
+ { 12141518985959911954u, 1491668146240041348u }, { 15176898732449889943u, 1864585182800051685u },
+ { 11791404716994875166u, 1165365739250032303u }, { 10127569877816206054u, 1456707174062540379u },
+ { 8047776328842869663u, 1820883967578175474u }, { 836348374198811271u, 2276104959472719343u },
+ { 7440246761515338900u, 1422565599670449589u }, { 13911994470321561530u, 1778206999588061986u },
+ { 8166621051047176104u, 2222758749485077483u }, { 2798295147690791113u, 1389224218428173427u },
+ { 17332926989895652603u, 1736530273035216783u }, { 17054472718942177850u, 2170662841294020979u },
+ { 8353202440125167204u, 1356664275808763112u }, { 10441503050156459005u, 1695830344760953890u },
+ { 3828506775840797949u, 2119787930951192363u }, { 86973725686804766u, 1324867456844495227u },
+ { 13943775212390669669u, 1656084321055619033u }, { 3594660960206173375u, 2070105401319523792u },
+ { 2246663100128858359u, 1293815875824702370u }, { 12031700912015848757u, 1617269844780877962u },
+ { 5816254103165035138u, 2021587305976097453u }, { 5941001823691840913u, 1263492066235060908u },
+ { 7426252279614801142u, 1579365082793826135u }, { 4671129331091113523u, 1974206353492282669u },
+ { 5225298841145639904u, 1233878970932676668u }, { 6531623551432049880u, 1542348713665845835u },
+ { 3552843420862674446u, 1927935892082307294u }, { 16055585193321335241u, 1204959932551442058u },
+ { 10846109454796893243u, 1506199915689302573u }, { 18169322836923504458u, 1882749894611628216u },
+ { 11355826773077190286u, 1176718684132267635u }, { 9583097447919099954u, 1470898355165334544u },
+ { 11978871809898874942u, 1838622943956668180u }, { 14973589762373593678u, 2298278679945835225u },
+ { 2440964573842414192u, 1436424174966147016u }, { 3051205717303017741u, 1795530218707683770u },
+ { 13037379183483547984u, 2244412773384604712u }, { 8148361989677217490u, 1402757983365377945u },
+ { 14797138505523909766u, 1753447479206722431u }, { 13884737113477499304u, 2191809349008403039u },
+ { 15595489723564518921u, 1369880843130251899u }, { 14882676136028260747u, 1712351053912814874u },
+ { 9379973133180550126u, 2140438817391018593u }, { 17391698254306313589u, 1337774260869386620u },
+ { 3292878744173340370u, 1672217826086733276u }, { 4116098430216675462u, 2090272282608416595u },
+ { 266718509671728212u, 1306420176630260372u }, { 333398137089660265u, 1633025220787825465u },
+ { 5028433689789463235u, 2041281525984781831u }, { 10060300083759496378u, 1275800953740488644u },
+ { 12575375104699370472u, 1594751192175610805u }, { 1884160825592049379u, 1993438990219513507u },
+ { 17318501580490888525u, 1245899368887195941u }, { 7813068920331446945u, 1557374211108994927u },
+ { 5154650131986920777u, 1946717763886243659u }, { 915813323278131534u, 1216698602428902287u },
+ { 14979824709379828129u, 1520873253036127858u }, { 9501408849870009354u, 1901091566295159823u },
+ { 12855909558809837702u, 1188182228934474889u }, { 2234828893230133415u, 1485227786168093612u },
+ { 2793536116537666769u, 1856534732710117015u }, { 8663489100477123587u, 1160334207943823134u },
+ { 1605989338741628675u, 1450417759929778918u }, { 11230858710281811652u, 1813022199912223647u },
+ { 9426887369424876662u, 2266277749890279559u }, { 12809333633531629769u, 1416423593681424724u },
+ { 16011667041914537212u, 1770529492101780905u }, { 6179525747111007803u, 2213161865127226132u },
+ { 13085575628799155685u, 1383226165704516332u }, { 16356969535998944606u, 1729032707130645415u },
+ { 15834525901571292854u, 2161290883913306769u }, { 2979049660840976177u, 1350806802445816731u },
+ { 17558870131333383934u, 1688508503057270913u }, { 8113529608884566205u, 2110635628821588642u },
+ { 9682642023980241782u, 1319147268013492901u }, { 16714988548402690132u, 1648934085016866126u },
+ { 11670363648648586857u, 2061167606271082658u }, { 11905663298832754689u, 1288229753919426661u },
+ { 1047021068258779650u, 1610287192399283327u }, { 15143834390605638274u, 2012858990499104158u },
+ { 4853210475701136017u, 1258036869061940099u }, { 1454827076199032118u, 1572546086327425124u },
+ { 1818533845248790147u, 1965682607909281405u }, { 3442426662494187794u, 1228551629943300878u },
+ { 13526405364972510550u, 1535689537429126097u }, { 3072948650933474476u, 1919611921786407622u },
+ { 15755650962115585259u, 1199757451116504763u }, { 15082877684217093670u, 1499696813895630954u },
+ { 9630225068416591280u, 1874621017369538693u }, { 8324733676974063502u, 1171638135855961683u },
+ { 5794231077790191473u, 1464547669819952104u }, { 7242788847237739342u, 1830684587274940130u },
+ { 18276858095901949986u, 2288355734093675162u }, { 16034722328366106645u, 1430222333808546976u },
+ { 1596658836748081690u, 1787777917260683721u }, { 6607509564362490017u, 2234722396575854651u },
+ { 1823850468512862308u, 1396701497859909157u }, { 6891499104068465790u, 1745876872324886446u },
+ { 17837745916940358045u, 2182346090406108057u }, { 4231062170446641922u, 1363966306503817536u },
+ { 5288827713058302403u, 1704957883129771920u }, { 6611034641322878003u, 2131197353912214900u },
+ { 13355268687681574560u, 1331998346195134312u }, { 16694085859601968200u, 1664997932743917890u },
+ { 11644235287647684442u, 2081247415929897363u }, { 4971804045566108824u, 1300779634956185852u },
+ { 6214755056957636030u, 1625974543695232315u }, { 3156757802769657134u, 2032468179619040394u },
+ { 6584659645158423613u, 1270292612261900246u }, { 17454196593302805324u, 1587865765327375307u },
+ { 17206059723201118751u, 1984832206659219134u }, { 6142101308573311315u, 1240520129162011959u },
+ { 3065940617289251240u, 1550650161452514949u }, { 8444111790038951954u, 1938312701815643686u },
+ { 665883850346957067u, 1211445438634777304u }, { 832354812933696334u, 1514306798293471630u },
+ { 10263815553021896226u, 1892883497866839537u }, { 17944099766707154901u, 1183052186166774710u },
+ { 13206752671529167818u, 1478815232708468388u }, { 16508440839411459773u, 1848519040885585485u },
+ { 12623618533845856310u, 1155324400553490928u }, { 15779523167307320387u, 1444155500691863660u },
+ { 1277659885424598868u, 1805194375864829576u }, { 1597074856780748586u, 2256492969831036970u },
+ { 5609857803915355770u, 1410308106144398106u }, { 16235694291748970521u, 1762885132680497632u },
+ { 1847873790976661535u, 2203606415850622041u }, { 12684136165428883219u, 1377254009906638775u },
+ { 11243484188358716120u, 1721567512383298469u }, { 219297180166231438u, 2151959390479123087u },
+ { 7054589765244976505u, 1344974619049451929u }, { 13429923224983608535u, 1681218273811814911u },
+ { 12175718012802122765u, 2101522842264768639u }, { 14527352785642408584u, 1313451776415480399u },
+ { 13547504963625622826u, 1641814720519350499u }, { 12322695186104640628u, 2052268400649188124u },
+ { 16925056528170176201u, 1282667750405742577u }, { 7321262604930556539u, 1603334688007178222u },
+ { 18374950293017971482u, 2004168360008972777u }, { 4566814905495150320u, 1252605225005607986u },
+ { 14931890668723713708u, 1565756531257009982u }, { 9441491299049866327u, 1957195664071262478u },
+ { 1289246043478778550u, 1223247290044539049u }, { 6223243572775861092u, 1529059112555673811u },
+ { 3167368447542438461u, 1911323890694592264u }, { 1979605279714024038u, 1194577431684120165u },
+ { 7086192618069917952u, 1493221789605150206u }, { 18081112809442173248u, 1866527237006437757u },
+ { 13606538515115052232u, 1166579523129023598u }, { 7784801107039039482u, 1458224403911279498u },
+ { 507629346944023544u, 1822780504889099373u }, { 5246222702107417334u, 2278475631111374216u },
+ { 3278889188817135834u, 1424047269444608885u }, { 8710297504448807696u, 1780059086805761106u }
+};
+
+#endif // RYU_D2S_FULL_TABLE_H
diff --git a/erts/emulator/ryu/d2s_intrinsics.h b/erts/emulator/ryu/d2s_intrinsics.h
new file mode 100644
index 0000000000..77388b3088
--- /dev/null
+++ b/erts/emulator/ryu/d2s_intrinsics.h
@@ -0,0 +1,358 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_D2S_INTRINSICS_H
+#define RYU_D2S_INTRINSICS_H
+
+#include <assert.h>
+#include <stdint.h>
+
+// Defines RYU_32_BIT_PLATFORM if applicable.
+#include "common.h"
+
+// ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined.
+// Let's do the same for now.
+#if defined(__SIZEOF_INT128__) && !defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS)
+#define HAS_UINT128
+#elif defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
+#define HAS_64_BIT_INTRINSICS
+#endif
+
+#if defined(HAS_UINT128)
+typedef __uint128_t uint128_t;
+#endif
+
+#if defined(HAS_64_BIT_INTRINSICS)
+
+#include <intrin.h>
+
+static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
+ return _umul128(a, b, productHi);
+}
+
+// Returns the lower 64 bits of (hi*2^64 + lo) >> dist, with 0 < dist < 64.
+static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
+ // For the __shiftright128 intrinsic, the shift value is always
+ // modulo 64.
+ // In the current implementation of the double-precision version
+ // of Ryu, the shift value is always < 64. (In the case
+ // RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [49, 58].
+ // Otherwise in the range [2, 59].)
+ // However, this function is now also called by s2d, which requires supporting
+ // the larger shift range (TODO: what is the actual range?).
+ // Check this here in case a future change requires larger shift
+ // values. In this case this function needs to be adjusted.
+ assert(dist < 64);
+ return __shiftright128(lo, hi, (unsigned char) dist);
+}
+
+#else // defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
+ // The casts here help MSVC to avoid calls to the __allmul library function.
+ const uint32_t aLo = (uint32_t)a;
+ const uint32_t aHi = (uint32_t)(a >> 32);
+ const uint32_t bLo = (uint32_t)b;
+ const uint32_t bHi = (uint32_t)(b >> 32);
+
+ const uint64_t b00 = (uint64_t)aLo * bLo;
+ const uint64_t b01 = (uint64_t)aLo * bHi;
+ const uint64_t b10 = (uint64_t)aHi * bLo;
+ const uint64_t b11 = (uint64_t)aHi * bHi;
+
+ const uint32_t b00Lo = (uint32_t)b00;
+ const uint32_t b00Hi = (uint32_t)(b00 >> 32);
+
+ const uint64_t mid1 = b10 + b00Hi;
+ const uint32_t mid1Lo = (uint32_t)(mid1);
+ const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
+
+ const uint64_t mid2 = b01 + mid1Lo;
+ const uint32_t mid2Lo = (uint32_t)(mid2);
+ const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
+
+ const uint64_t pHi = b11 + mid1Hi + mid2Hi;
+ const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
+
+ *productHi = pHi;
+ return pLo;
+}
+
+static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
+ // We don't need to handle the case dist >= 64 here (see above).
+ assert(dist < 64);
+ assert(dist > 0);
+ return (hi << (64 - dist)) | (lo >> dist);
+}
+
+#endif // defined(HAS_64_BIT_INTRINSICS)
+
+#if defined(RYU_32_BIT_PLATFORM)
+
+// Returns the high 64 bits of the 128-bit product of a and b.
+static inline uint64_t umulh(const uint64_t a, const uint64_t b) {
+ // Reuse the umul128 implementation.
+ // Optimizers will likely eliminate the instructions used to compute the
+ // low part of the product.
+ uint64_t hi;
+ umul128(a, b, &hi);
+ return hi;
+}
+
+// On 32-bit platforms, compilers typically generate calls to library
+// functions for 64-bit divisions, even if the divisor is a constant.
+//
+// E.g.:
+// https://bugs.llvm.org/show_bug.cgi?id=37932
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443
+//
+// The functions here perform division-by-constant using multiplications
+// in the same way as 64-bit compilers would do.
+//
+// NB:
+// The multipliers and shift values are the ones generated by clang x64
+// for expressions like x/5, x/10, etc.
+
+static inline uint64_t div5(const uint64_t x) {
+ return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2;
+}
+
+static inline uint64_t div10(const uint64_t x) {
+ return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3;
+}
+
+static inline uint64_t div100(const uint64_t x) {
+ return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
+}
+
+static inline uint64_t div1e8(const uint64_t x) {
+ return umulh(x, 0xABCC77118461CEFDu) >> 26;
+}
+
+static inline uint64_t div1e9(const uint64_t x) {
+ return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11;
+}
+
+static inline uint32_t mod1e9(const uint64_t x) {
+ // Avoid 64-bit math as much as possible.
+ // Returning (uint32_t) (x - 1000000000 * div1e9(x)) would
+ // perform 32x64-bit multiplication and 64-bit subtraction.
+ // x and 1000000000 * div1e9(x) are guaranteed to differ by
+ // less than 10^9, so their highest 32 bits must be identical,
+ // so we can truncate both sides to uint32_t before subtracting.
+ // We can also simplify (uint32_t) (1000000000 * div1e9(x)).
+ // We can truncate before multiplying instead of after, as multiplying
+ // the highest 32 bits of div1e9(x) can't affect the lowest 32 bits.
+ return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x));
+}
+
+#else // defined(RYU_32_BIT_PLATFORM)
+
+static inline uint64_t div5(const uint64_t x) {
+ return x / 5;
+}
+
+static inline uint64_t div10(const uint64_t x) {
+ return x / 10;
+}
+
+static inline uint64_t div100(const uint64_t x) {
+ return x / 100;
+}
+
+static inline uint64_t div1e8(const uint64_t x) {
+ return x / 100000000;
+}
+
+static inline uint64_t div1e9(const uint64_t x) {
+ return x / 1000000000;
+}
+
+static inline uint32_t mod1e9(const uint64_t x) {
+ return (uint32_t) (x - 1000000000 * div1e9(x));
+}
+
+#endif // defined(RYU_32_BIT_PLATFORM)
+
+static inline uint32_t pow5Factor(uint64_t value) {
+ uint32_t count = 0;
+ for (;;) {
+ assert(value != 0);
+ const uint64_t q = div5(value);
+ const uint32_t r = ((uint32_t) value) - 5 * ((uint32_t) q);
+ if (r != 0) {
+ break;
+ }
+ value = q;
+ ++count;
+ }
+ return count;
+}
+
+// Returns true if value is divisible by 5^p.
+static inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) {
+ // I tried a case distinction on p, but there was no performance difference.
+ return pow5Factor(value) >= p;
+}
+
+// Returns true if value is divisible by 2^p.
+static inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) {
+ assert(value != 0);
+ assert(p < 64);
+ // __builtin_ctzll doesn't appear to be faster here.
+ return (value & ((1ull << p) - 1)) == 0;
+}
+
+// We need a 64x128-bit multiplication and a subsequent 128-bit shift.
+// Multiplication:
+// The 64-bit factor is variable and passed in, the 128-bit factor comes
+// from a lookup table. We know that the 64-bit factor only has 55
+// significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
+// factor only has 124 significant bits (i.e., the 4 topmost bits are
+// zeros).
+// Shift:
+// In principle, the multiplication result requires 55 + 124 = 179 bits to
+// represent. However, we then shift this value to the right by j, which is
+// at least j >= 115, so the result is guaranteed to fit into 179 - 115 = 64
+// bits. This means that we only need the topmost 64 significant bits of
+// the 64x128-bit multiplication.
+//
+// There are several ways to do this:
+// 1. Best case: the compiler exposes a 128-bit type.
+// We perform two 64x64-bit multiplications, add the higher 64 bits of the
+// lower result to the higher result, and shift by j - 64 bits.
+//
+// We explicitly cast from 64-bit to 128-bit, so the compiler can tell
+// that these are only 64-bit inputs, and can map these to the best
+// possible sequence of assembly instructions.
+// x64 machines happen to have matching assembly instructions for
+// 64x64-bit multiplications and 128-bit shifts.
+//
+// 2. Second best case: the compiler exposes intrinsics for the x64 assembly
+// instructions mentioned in 1.
+//
+// 3. We only have 64x64 bit instructions that return the lower 64 bits of
+// the result, i.e., we have to use plain C.
+// Our inputs are less than the full width, so we have three options:
+// a. Ignore this fact and just implement the intrinsics manually.
+// b. Split both into 31-bit pieces, which guarantees no internal overflow,
+// but requires extra work upfront (unless we change the lookup table).
+// c. Split only the first factor into 31-bit pieces, which also guarantees
+// no internal overflow, but requires extra work since the intermediate
+// results are not perfectly aligned.
+#if defined(HAS_UINT128)
+
+// Best case: use 128-bit type.
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ const uint128_t b0 = ((uint128_t) m) * mul[0];
+ const uint128_t b2 = ((uint128_t) m) * mul[1];
+ return (uint64_t) (((b0 >> 64) + b2) >> (j - 64));
+}
+
+static inline uint64_t mulShiftAll64(const uint64_t m, const uint64_t* const mul, const int32_t j,
+ uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
+// m <<= 2;
+// uint128_t b0 = ((uint128_t) m) * mul[0]; // 0
+// uint128_t b2 = ((uint128_t) m) * mul[1]; // 64
+//
+// uint128_t hi = (b0 >> 64) + b2;
+// uint128_t lo = b0 & 0xffffffffffffffffull;
+// uint128_t factor = (((uint128_t) mul[1]) << 64) + mul[0];
+// uint128_t vpLo = lo + (factor << 1);
+// *vp = (uint64_t) ((hi + (vpLo >> 64)) >> (j - 64));
+// uint128_t vmLo = lo - (factor << mmShift);
+// *vm = (uint64_t) ((hi + (vmLo >> 64) - (((uint128_t) 1ull) << 64)) >> (j - 64));
+// return (uint64_t) (hi >> (j - 64));
+ *vp = mulShift64(4 * m + 2, mul, j);
+ *vm = mulShift64(4 * m - 1 - mmShift, mul, j);
+ return mulShift64(4 * m, mul, j);
+}
+
+#elif defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ // m is maximum 55 bits
+ uint64_t high1; // 128
+ const uint64_t low1 = umul128(m, mul[1], &high1); // 64
+ uint64_t high0; // 64
+ umul128(m, mul[0], &high0); // 0
+ const uint64_t sum = high0 + low1;
+ if (sum < high0) {
+ ++high1; // overflow into high1
+ }
+ return shiftright128(sum, high1, j - 64);
+}
+
+static inline uint64_t mulShiftAll64(const uint64_t m, const uint64_t* const mul, const int32_t j,
+ uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
+ *vp = mulShift64(4 * m + 2, mul, j);
+ *vm = mulShift64(4 * m - 1 - mmShift, mul, j);
+ return mulShift64(4 * m, mul, j);
+}
+
+#else // !defined(HAS_UINT128) && !defined(HAS_64_BIT_INTRINSICS)
+
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ // m is maximum 55 bits
+ uint64_t high1; // 128
+ const uint64_t low1 = umul128(m, mul[1], &high1); // 64
+ uint64_t high0; // 64
+ umul128(m, mul[0], &high0); // 0
+ const uint64_t sum = high0 + low1;
+ if (sum < high0) {
+ ++high1; // overflow into high1
+ }
+ return shiftright128(sum, high1, j - 64);
+}
+
+// This is faster if we don't have a 64x64->128-bit multiplication.
+static inline uint64_t mulShiftAll64(uint64_t m, const uint64_t* const mul, const int32_t j,
+ uint64_t* const vp, uint64_t* const vm, const uint32_t mmShift) {
+ m <<= 1;
+ // m is maximum 55 bits
+ uint64_t tmp;
+ const uint64_t lo = umul128(m, mul[0], &tmp);
+ uint64_t hi;
+ const uint64_t mid = tmp + umul128(m, mul[1], &hi);
+ hi += mid < tmp; // overflow into hi
+
+ const uint64_t lo2 = lo + mul[0];
+ const uint64_t mid2 = mid + mul[1] + (lo2 < lo);
+ const uint64_t hi2 = hi + (mid2 < mid);
+ *vp = shiftright128(mid2, hi2, (uint32_t) (j - 64 - 1));
+
+ if (mmShift == 1) {
+ const uint64_t lo3 = lo - mul[0];
+ const uint64_t mid3 = mid - mul[1] - (lo3 > lo);
+ const uint64_t hi3 = hi - (mid3 > mid);
+ *vm = shiftright128(mid3, hi3, (uint32_t) (j - 64 - 1));
+ } else {
+ const uint64_t lo3 = lo + lo;
+ const uint64_t mid3 = mid + mid + (lo3 < lo);
+ const uint64_t hi3 = hi + hi + (mid3 < mid);
+ const uint64_t lo4 = lo3 - mul[0];
+ const uint64_t mid4 = mid3 - mul[1] - (lo4 > lo3);
+ const uint64_t hi4 = hi3 - (mid4 > mid3);
+ *vm = shiftright128(mid4, hi4, (uint32_t) (j - 64));
+ }
+
+ return shiftright128(mid, hi, (uint32_t) (j - 64 - 1));
+}
+
+#endif // HAS_64_BIT_INTRINSICS
+
+#endif // RYU_D2S_INTRINSICS_H
diff --git a/erts/emulator/ryu/digit_table.h b/erts/emulator/ryu/digit_table.h
new file mode 100644
index 0000000000..02219bc6d5
--- /dev/null
+++ b/erts/emulator/ryu/digit_table.h
@@ -0,0 +1,35 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_DIGIT_TABLE_H
+#define RYU_DIGIT_TABLE_H
+
+// A table of all two-digit numbers. This is used to speed up decimal digit
+// generation by copying pairs of digits into the final output.
+static const char DIGIT_TABLE[200] = {
+ '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
+ '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
+ '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
+ '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
+ '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
+ '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
+ '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
+ '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
+ '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
+ '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
+};
+
+#endif // RYU_DIGIT_TABLE_H
diff --git a/erts/emulator/ryu/ryu.h b/erts/emulator/ryu/ryu.h
new file mode 100644
index 0000000000..9439ada7cc
--- /dev/null
+++ b/erts/emulator/ryu/ryu.h
@@ -0,0 +1,36 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// (See accompanying file LICENSE-Apache or copy at
+// http://www.apache.org/licenses/LICENSE-2.0)
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE-Boost or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+#ifndef RYU_H
+#define RYU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+
+int d2s_buffered_n(double f, char* result);
+void d2s_buffered(double f, char* result);
+char* d2s(double f);
+
+//CHANGE_FOR_ERLANG we dropped all the other functions as not used by us
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RYU_H
diff --git a/erts/emulator/ryu/ryu.mk b/erts/emulator/ryu/ryu.mk
new file mode 100644
index 0000000000..524618f446
--- /dev/null
+++ b/erts/emulator/ryu/ryu.mk
@@ -0,0 +1,57 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+# ----------------------------------------------------
+# Make include file for Ryu
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2011-2021. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+# ----------------------------------------------------
+
+RYU_FILES = d2s
+
+RYU_OBJDIR = $(ERL_TOP)/erts/emulator/ryu/obj/$(TARGET)/$(TYPE)
+RYU_OBJS = $(RYU_FILES:%=$(RYU_OBJDIR)/%.o)
+RYU_DIR = $(ERL_TOP)/erts/emulator/ryu
+
+RYU_SRC = $(RYU_FILES:%=ryu/%.c)
+
+ifeq ($(TARGET), win32)
+RYU_LIBRARY = $(RYU_OBJDIR)/ryu.lib
+else
+RYU_LIBRARY = $(RYU_OBJDIR)/libryu.a
+endif
+
+ifeq ($(TARGET), win32)
+RYU_CFLAGS = $(CFLAGS)
+else
+RYU_CFLAGS = $(filter-out -Wdeclaration-after-statement,$(CFLAGS))
+endif
+
+ifeq ($(TARGET), win32)
+$(RYU_LIBRARY): $(RYU_OBJS)
+ $(V_AR) -out:$@ $(RYU_OBJS)
+else
+$(RYU_LIBRARY): $(RYU_OBJS)
+ $(V_AR) $(ARFLAGS) $@ $(RYU_OBJS)
+ -@ ($(RANLIB) $@ || true) 2>/dev/null
+endif
+
+
+
+$(RYU_OBJDIR)/%.o: ryu/%.c
+ $(V_CC) -c $(RYU_CFLAGS) -o $@ $<
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 5c1f755c45..39b6517bcf 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,7 +93,7 @@ typedef enum {
#endif
ERTS_EV_FLAG_WANT_ERROR = 0x10, /* ERL_NIF_SELECT_ERROR turned on */
- /* Combinations */
+ /* Combinations, defined only to be displayed by debugger (gdb) */
ERTS_EV_FLAG_USED_FALLBACK = ERTS_EV_FLAG_USED | ERTS_EV_FLAG_FALLBACK,
ERTS_EV_FLAG_USED_SCHEDULER = ERTS_EV_FLAG_USED | ERTS_EV_FLAG_SCHEDULER,
ERTS_EV_FLAG_USED_IN_SCHEDULER = ERTS_EV_FLAG_USED | ERTS_EV_FLAG_SCHEDULER | ERTS_EV_FLAG_IN_SCHEDULER,
@@ -101,16 +101,25 @@ typedef enum {
ERTS_EV_FLAG_UNUSED_IN_SCHEDULER = ERTS_EV_FLAG_SCHEDULER | ERTS_EV_FLAG_IN_SCHEDULER
} EventStateFlags;
-#define flag2str(flags) \
- ((flags) == ERTS_EV_FLAG_CLEAR ? "CLEAR" : \
- ((flags) == ERTS_EV_FLAG_USED ? "USED" : \
- ((flags) == ERTS_EV_FLAG_FALLBACK ? "FLBK" : \
- ((flags) == ERTS_EV_FLAG_USED_FALLBACK ? "USED|FLBK" : \
- ((flags) == ERTS_EV_FLAG_USED_SCHEDULER ? "USED|SCHD" : \
- ((flags) == ERTS_EV_FLAG_UNUSED_SCHEDULER ? "SCHD" : \
- ((flags) == ERTS_EV_FLAG_USED_IN_SCHEDULER ? "USED|IN_SCHD" : \
- ((flags) == ERTS_EV_FLAG_UNUSED_IN_SCHEDULER ? "IN_SCHD" : \
- "ERROR"))))))))
+
+static const char* event_state_flag_to_str(EventStateFlags f)
+{
+ switch ((int)f) {
+ case ERTS_EV_FLAG_CLEAR: return "CLEAR";
+ case ERTS_EV_FLAG_USED: return "USED";
+ case ERTS_EV_FLAG_FALLBACK: return "FLBK";
+ case ERTS_EV_FLAG_FALLBACK | ERTS_EV_FLAG_USED: return "USED|FLBK";
+
+#if ERTS_POLL_USE_SCHEDULER_POLLING
+ case ERTS_EV_FLAG_SCHEDULER: return "SCHD";
+ case ERTS_EV_FLAG_SCHEDULER | ERTS_EV_FLAG_USED: return "USED|SCHD";
+ case ERTS_EV_FLAG_SCHEDULER | ERTS_EV_FLAG_IN_SCHEDULER: return "IN_SCHD";
+ case ERTS_EV_FLAG_SCHEDULER | ERTS_EV_FLAG_IN_SCHEDULER
+ | ERTS_EV_FLAG_USED: return "USED|IN_SCHD";
+#endif
+ default: return "ERROR";
+ }
+}
/* How many events that can be handled at once by one erts_poll_wait call */
#define ERTS_CHECK_IO_POLL_RES_LEN 512
@@ -137,7 +146,7 @@ static ErtsPollThread *psiv;
static ErtsPollSet *flbk_pollset;
#endif
#if ERTS_POLL_USE_SCHEDULER_POLLING
-static ErtsPollSet *sched_pollset;
+ErtsPollSet *sched_pollset;
#endif
typedef struct {
@@ -409,7 +418,7 @@ static ERTS_INLINE ErtsPollSet *
get_scheduler_pollset(ErtsSysFdType fd)
{
#if ERTS_POLL_USE_SCHEDULER_POLLING
- return sched_pollset;
+ return sched_pollset ? sched_pollset : get_pollset(fd);
#else
return get_pollset(fd);
#endif
@@ -488,16 +497,18 @@ erts_io_notify_port_task_executed(ErtsPortTaskType type,
active_events = state->active_events;
- if (!(state->flags & ERTS_EV_FLAG_IN_SCHEDULER) || type == ERTS_PORT_TASK_OUTPUT) {
+ if (state->type == ERTS_EV_TYPE_DRV_SEL) {
switch (type) {
case ERTS_PORT_TASK_INPUT:
DEBUG_PRINT_FD("executed ready_input", state);
- ASSERT(!(state->active_events & ERTS_POLL_EV_IN));
- if (state->events & ERTS_POLL_EV_IN) {
+ if (!(state->flags & ERTS_EV_FLAG_IN_SCHEDULER)
+ && !(active_events & ERTS_POLL_EV_IN)
+ && (state->events & ERTS_POLL_EV_IN)) {
+
active_events |= ERTS_POLL_EV_IN;
- if (state->count > 10 && ERTS_POLL_USE_SCHEDULER_POLLING) {
+ if (state->count > 10 && erts_sched_poll_enabled()) {
if (!(state->flags & ERTS_EV_FLAG_SCHEDULER))
op = ERTS_POLL_OP_ADD;
state->flags |= ERTS_EV_FLAG_IN_SCHEDULER|ERTS_EV_FLAG_SCHEDULER;
@@ -505,7 +516,7 @@ erts_io_notify_port_task_executed(ErtsPortTaskType type,
DEBUG_PRINT_FD("moving to scheduler ps", state);
} else
new_events = active_events;
- if (!(state->flags & ERTS_EV_FLAG_FALLBACK) && ERTS_POLL_USE_SCHEDULER_POLLING)
+ if (!(state->flags & ERTS_EV_FLAG_FALLBACK) && erts_sched_poll_enabled())
state->count++;
}
break;
@@ -513,8 +524,9 @@ erts_io_notify_port_task_executed(ErtsPortTaskType type,
DEBUG_PRINT_FD("executed ready_output", state);
- ASSERT(!(state->active_events & ERTS_POLL_EV_OUT));
- if (state->events & ERTS_POLL_EV_OUT) {
+ if (!(active_events & ERTS_POLL_EV_OUT)
+ && (state->events & ERTS_POLL_EV_OUT)) {
+
active_events |= ERTS_POLL_EV_OUT;
if (state->flags & ERTS_EV_FLAG_IN_SCHEDULER && active_events & ERTS_POLL_EV_IN)
new_events = ERTS_POLL_EV_OUT;
@@ -527,7 +539,8 @@ erts_io_notify_port_task_executed(ErtsPortTaskType type,
break;
}
- if (state->active_events != active_events && new_events) {
+ if (state->active_events != active_events) {
+ ASSERT(new_events);
state->active_events = active_events;
new_events = erts_io_control(state, op, new_events);
}
@@ -1791,7 +1804,7 @@ erts_check_io(ErtsPollThread *psi, ErtsMonotonicTime timeout_time, int poll_only
select/deselect in rapid succession. */
revents &= state->active_events | ERTS_POLL_EV_NVAL;
- if (psi->ps != get_scheduler_pollset(fd) || !ERTS_POLL_USE_SCHEDULER_POLLING) {
+ if (psi->ps != get_scheduler_pollset(fd) || !erts_sched_poll_enabled()) {
ErtsPollEvents reactive_events;
state->active_events &= ~revents;
@@ -2109,7 +2122,7 @@ get_arg(char* rest, char** argv, int* ip)
}
static void
-parse_args(int *argc, char **argv, int concurrent_waiters)
+parse_args(int *argc, char **argv, int concurrent_waiters, int* use_sched_poll)
{
int i = 0, j;
int no_pollsets = 0, no_poll_threads = 0,
@@ -2151,8 +2164,16 @@ parse_args(int *argc, char **argv, int concurrent_waiters)
erts_fprintf(stderr,"bad I/O pollset percentage number: %s\n", arg);
erts_usage();
}
- } else {
- break;
+ } else if (sys_strcmp(argv[i]+2, "Os") == 0) {
+ const char *arg = get_arg(argv[i]+4, argv, &i);
+ if (sys_strcmp(arg, "true") == 0) {
+ *use_sched_poll = 1;
+ } else if (sys_strcmp(arg, "false") == 0) {
+ *use_sched_poll = 0;
+ } else {
+ erts_fprintf(stderr,"bad +IOs boolean argument: %s\n", arg);
+ erts_usage();
+ }
}
break;
}
@@ -2220,6 +2241,8 @@ void
erts_init_check_io(int *argc, char **argv)
{
int j, concurrent_waiters, no_poll_threads;
+ int use_sched_poll = ERTS_POLL_USE_SCHEDULER_POLLING;
+
ERTS_CT_ASSERT((INT_MIN & (ERL_NIF_SELECT_STOP_CALLED |
ERL_NIF_SELECT_STOP_SCHEDULED |
ERL_NIF_SELECT_INVALID_EVENT |
@@ -2231,7 +2254,7 @@ erts_init_check_io(int *argc, char **argv)
erts_poll_init_flbk(NULL);
#endif
- parse_args(argc, argv, concurrent_waiters);
+ parse_args(argc, argv, concurrent_waiters, &use_sched_poll);
/* Create the actual pollsets */
pollsetv = erts_alloc(ERTS_ALC_T_POLLSET,sizeof(ErtsPollSet *) * erts_no_pollsets);
@@ -2243,10 +2266,16 @@ erts_init_check_io(int *argc, char **argv)
j = -1;
+ if (use_sched_poll) {
#if ERTS_POLL_USE_SCHEDULER_POLLING
- sched_pollset = erts_poll_create_pollset(j--);
- no_poll_threads++;
+ sched_pollset = erts_poll_create_pollset(j--);
+ ASSERT(erts_sched_poll_enabled());
+ no_poll_threads++;
+#else
+ erts_fprintf(stderr,"+IOs true: not supported by this emulator\n");
+ erts_usage();
#endif
+ }
#if ERTS_POLL_USE_FALLBACK
flbk_pollset = erts_poll_create_pollset_flbk(j--);
@@ -2263,13 +2292,13 @@ erts_init_check_io(int *argc, char **argv)
psiv++;
#endif
-#if ERTS_POLL_USE_SCHEDULER_POLLING
- psiv[0].pollres_len = ERTS_CHECK_IO_POLL_RES_LEN;
- psiv[0].pollres = erts_alloc(ERTS_ALC_T_POLLSET,
- sizeof(ErtsPollResFd) * ERTS_CHECK_IO_POLL_RES_LEN);
- psiv[0].ps = get_scheduler_pollset(0);
- psiv++;
-#endif
+ if (erts_sched_poll_enabled()) {
+ psiv[0].pollres_len = ERTS_CHECK_IO_POLL_RES_LEN;
+ psiv[0].pollres = erts_alloc(ERTS_ALC_T_POLLSET,
+ sizeof(ErtsPollResFd) * ERTS_CHECK_IO_POLL_RES_LEN);
+ psiv[0].ps = get_scheduler_pollset(0);
+ psiv++;
+ }
for (j = 0; j < erts_no_poll_threads; j++) {
psiv[j].pollres_len = ERTS_CHECK_IO_POLL_RES_LEN;
@@ -2327,12 +2356,12 @@ erts_check_io_size(void)
erts_poll_info(get_fallback_pollset(), &pi);
res += pi.memory_size;
#endif
-
#if ERTS_POLL_USE_SCHEDULER_POLLING
- erts_poll_info(get_scheduler_pollset(0), &pi);
- res += pi.memory_size;
+ if (erts_sched_poll_enabled()) {
+ erts_poll_info(sched_pollset, &pi);
+ res += pi.memory_size;
+ }
#endif
-
for (i = 0; i < erts_no_pollsets; i++) {
erts_poll_info(pollsetv[i], &pi);
res += pi.memory_size;
@@ -2361,9 +2390,9 @@ erts_check_io_info(void *proc)
Uint sz, *szp, *hp, **hpp;
ErtsPollInfo *piv;
Sint i, j = 0, len;
- int no_pollsets = erts_no_pollsets + ERTS_POLL_USE_FALLBACK + ERTS_POLL_USE_SCHEDULER_POLLING;
+ int no_pollsets = erts_no_pollsets + ERTS_POLL_USE_FALLBACK + erts_sched_poll_enabled();
ERTS_CT_ASSERT(ERTS_POLL_USE_FALLBACK == 0 || ERTS_POLL_USE_FALLBACK == 1);
- ERTS_CT_ASSERT(ERTS_POLL_USE_SCHEDULER_POLLING == 0 || ERTS_POLL_USE_SCHEDULER_POLLING == 1);
+ ERTS_ASSERT(erts_sched_poll_enabled() == 0 || erts_sched_poll_enabled() == 1);
piv = erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsPollInfo) * no_pollsets);
@@ -2373,14 +2402,14 @@ erts_check_io_info(void *proc)
piv[0].active_fds = 0;
piv++;
#endif
-
#if ERTS_POLL_USE_SCHEDULER_POLLING
- erts_poll_info(get_scheduler_pollset(0), &piv[0]);
- piv[0].poll_threads = 0;
- piv[0].active_fds = 0;
- piv++;
+ if (erts_sched_poll_enabled()) {
+ erts_poll_info(sched_pollset, &piv[0]);
+ piv[0].poll_threads = 0;
+ piv[0].active_fds = 0;
+ piv++;
+ }
#endif
-
for (j = 0; j < erts_no_pollsets; j++) {
erts_poll_info(pollsetv[j], &piv[j]);
piv[j].active_fds = 0;
@@ -2429,7 +2458,7 @@ erts_check_io_info(void *proc)
sz = 0;
piv -= ERTS_POLL_USE_FALLBACK;
- piv -= ERTS_POLL_USE_SCHEDULER_POLLING;
+ piv -= erts_sched_poll_enabled();
bld_it:
@@ -2534,7 +2563,11 @@ print_events(erts_dsprintf_buf_t *dsbufp, ErtsPollEvents ev)
static ERTS_INLINE void
print_flags(erts_dsprintf_buf_t *dsbufp, EventStateFlags f)
{
- erts_dsprintf(dsbufp, "%s", flag2str(f));
+ if (f & ERTS_EV_FLAG_WANT_ERROR) {
+ erts_dsprintf(dsbufp, "WANTERR|");
+ f &= ~ERTS_EV_FLAG_WANT_ERROR;
+ }
+ erts_dsprintf(dsbufp, "%s", event_state_flag_to_str(f));
}
#ifdef DEBUG_PRINT_MODE
@@ -2680,9 +2713,17 @@ static int erts_debug_print_checkio_state(erts_dsprintf_buf_t *dsbufp,
err = 1;
}
else {
- ErtsPollEvents ev = cio_events;
- if (ev != ep_events && ep_events != ERTS_POLL_EV_NONE)
- err = 1;
+ if (ep_events != ERTS_POLL_EV_NONE) {
+ if (!ERTS_POLL_USE_KERNEL_POLL
+ || (!(state->flags & (ERTS_EV_FLAG_SCHEDULER|ERTS_EV_FLAG_FALLBACK))
+ && ((cio_events ^ ep_events) & ep_events) != 0)) {
+ err = 1;
+ }
+ /* else: Kernel poll with oneshot (used by poller threads)
+ * may cause a race where an event just triggered and
+ * thereby was cleared in the pollset (ep_events).
+ */
+ }
erts_dsprintf(dsbufp, "cio_ev=");
print_events(dsbufp, cio_events);
erts_dsprintf(dsbufp, " ep_ev=");
@@ -2898,18 +2939,19 @@ erts_check_io_debug(ErtsCheckIoDebugInfo *ciodip)
}
#endif
#if ERTS_POLL_USE_SCHEDULER_POLLING
- erts_dsprintf(dsbufp, "--- fds in scheduler pollset ----------------------------\n");
- erts_poll_get_selected_events(get_scheduler_pollset(0), counters.epep,
- drv_ev_state.max_fds);
- for (fd = 0; fd < len; fd++) {
- if (drv_ev_state.v[fd].flags & ERTS_EV_FLAG_SCHEDULER) {
- if (drv_ev_state.v[fd].events && drv_ev_state.v[fd].events != ERTS_POLL_EV_NONE)
- counters.epep[fd] &= ~ERTS_POLL_EV_OUT;
- doit_erts_check_io_debug(&drv_ev_state.v[fd], &counters, dsbufp);
+ if (erts_sched_poll_enabled()) {
+ erts_dsprintf(dsbufp, "--- fds in scheduler pollset ----------------------------\n");
+ erts_poll_get_selected_events(sched_pollset, counters.epep,
+ drv_ev_state.max_fds);
+ for (fd = 0; fd < len; fd++) {
+ if (drv_ev_state.v[fd].flags & ERTS_EV_FLAG_SCHEDULER) {
+ if (drv_ev_state.v[fd].events && drv_ev_state.v[fd].events != ERTS_POLL_EV_NONE)
+ counters.epep[fd] &= ~ERTS_POLL_EV_OUT;
+ doit_erts_check_io_debug(&drv_ev_state.v[fd], &counters, dsbufp);
+ }
}
}
#endif
-
erts_dsprintf(dsbufp, "--- fds in pollset --------------------------------------\n");
for (i = 0; i < erts_no_pollsets; i++) {
@@ -2921,6 +2963,7 @@ erts_check_io_debug(ErtsCheckIoDebugInfo *ciodip)
&& get_pollset_id(fd) == i) {
if (counters.epep[fd] != ERTS_POLL_EV_NONE &&
drv_ev_state.v[fd].flags & ERTS_EV_FLAG_IN_SCHEDULER) {
+ ERTS_ASSERT(erts_sched_poll_enabled());
/* We add the in flag if it is enabled in the scheduler pollset
and get_selected_events works on the platform */
counters.epep[fd] |= ERTS_POLL_EV_IN;
@@ -2929,6 +2972,7 @@ erts_check_io_debug(ErtsCheckIoDebugInfo *ciodip)
}
}
}
+
for (fd = len ; fd < drv_ev_state.max_fds; fd++) {
null_des.fd = fd;
doit_erts_check_io_debug(&null_des, &counters, dsbufp);
@@ -2955,6 +2999,7 @@ erts_check_io_debug(ErtsCheckIoDebugInfo *ciodip)
erts_dsprintf(dsbufp, "internal fds=%d\n", counters.internal_fds);
#endif
erts_dsprintf(dsbufp, "---------------------------------------------------------\n");
+
erts_send_error_to_logger_nogl(dsbufp);
#ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS
erts_free(ERTS_ALC_T_TMP, (void *) counters.epep);
diff --git a/erts/emulator/sys/common/erl_check_io.h b/erts/emulator/sys/common/erl_check_io.h
index b96f4f9609..d44b494223 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -112,6 +112,22 @@ typedef struct {
} ErtsIoTask;
+ERTS_GLB_INLINE int erts_sched_poll_enabled(void);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE int erts_sched_poll_enabled(void)
+{
+#if ERTS_POLL_USE_SCHEDULER_POLLING
+ extern ErtsPollSet *sched_pollset;
+ return (sched_pollset != NULL);
+#else
+ return 0;
+#endif
+}
+
+#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
#endif /* ERL_CHECK_IO_H__ */
#if !defined(ERL_CHECK_IO_C__) && !defined(ERTS_ALLOC_C__)
@@ -133,6 +149,7 @@ extern int erts_no_poll_threads;
#include "erl_poll.h"
#include "erl_port_task.h"
+
typedef struct {
Eterm inport;
Eterm outport;
@@ -152,3 +169,4 @@ typedef struct {
} ErtsNifSelectDataState;
#endif /* #ifndef ERL_CHECK_IO_INTERNAL__ */
+
diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c
index edcdd12d2c..e3300e3c43 100644
--- a/erts/emulator/sys/common/erl_mmap.c
+++ b/erts/emulator/sys/common/erl_mmap.c
@@ -327,7 +327,7 @@ struct ErtsMemMapper_ {
* Super unaligned area is located above super aligned
* area. That is, `sa.bot` is beginning of the super
* carrier, `sua.top` is the end of the super carrier,
- * and sa.top and sua.bot moves towards eachother.
+ * and sa.top and sua.bot moves towards each other.
*/
struct {
char *top;
@@ -2587,10 +2587,10 @@ static void print_tree(enum SortOrder order, RBTNode*);
/*
* Checks that the order between parent and children are correct,
- * and that the Red-Black Tree properies are satisfied. if size > 0,
+ * and that the Red-Black Tree properties are satisfied. if size > 0,
* check_tree() returns the node that satisfies "address order first fit"
*
- * The Red-Black Tree properies are:
+ * The Red-Black Tree properties are:
* 1. Every node is either red or black.
* 2. Every leaf (NIL) is black.
* 3. If a node is red, then both its children are black.
diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h
index e4e9dfb7ae..ecb1ef6a13 100644
--- a/erts/emulator/sys/common/erl_mmap.h
+++ b/erts/emulator/sys/common/erl_mmap.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2013-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2013-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c
index 42c4879a0e..1b6b3aa0f7 100644
--- a/erts/emulator/sys/common/erl_mseg.c
+++ b/erts/emulator/sys/common/erl_mseg.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,6 @@
#include "erl_mseg.h"
#include "global.h"
#include "erl_threads.h"
-#include "erl_mtrace.h"
#include "erl_time.h"
#include "erl_alloc.h"
#include "big.h"
@@ -45,8 +44,6 @@
#if HAVE_ERTS_MSEG
-#define SEGTYPE ERTS_MTRACE_SEGMENT_ID
-
#ifndef HAVE_GETPAGESIZE
#define HAVE_GETPAGESIZE 0
#endif
@@ -570,9 +567,6 @@ static ERTS_INLINE Uint mseg_drop_one_cache_size(ErtsMsegAllctr_t *ma, Uint flag
c = erts_circleq_tail(head);
erts_circleq_remove(c);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_free(SEGTYPE, SEGTYPE, c->seg);
-
mseg_destroy(ma, flags, c->seg, c->size);
mseg_cache_clear_node(c);
erts_circleq_push_head(&(ma->cache_free), c);
@@ -593,9 +587,6 @@ static ERTS_INLINE Uint mseg_drop_cache_size(ErtsMsegAllctr_t *ma, Uint flags, c
c = erts_circleq_tail(head);
erts_circleq_remove(c);
- if (erts_mtrace_enabled)
- erts_mtrace_crr_free(SEGTYPE, SEGTYPE, c->seg);
-
mseg_destroy(ma, flags, c->seg, c->size);
mseg_cache_clear_node(c);
@@ -732,9 +723,6 @@ mseg_alloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, UWord *size_p,
else {
done:
*size_p = size;
- if (erts_mtrace_enabled)
- erts_mtrace_crr_alloc(seg, atype, ERTS_MTRACE_SEGMENT_ID, size);
-
ERTS_MSEG_ALLOC_STAT(ma,size);
}
@@ -753,9 +741,6 @@ mseg_dealloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg, UWord size,
goto done;
}
- if (erts_mtrace_enabled)
- erts_mtrace_crr_free(atype, SEGTYPE, seg);
-
mseg_destroy(ma, flags, seg, size);
done:
@@ -825,9 +810,6 @@ mseg_realloc(ErtsMsegAllctr_t *ma, ErtsAlcType_t atype, void *seg,
}
}
- if (erts_mtrace_enabled)
- erts_mtrace_crr_realloc(new_seg, atype, SEGTYPE, seg, new_size);
-
INC_CC(ma, realloc);
ASSERT(!MSEG_FLG_IS_2POW(flags) || IS_2POW(new_size));
diff --git a/erts/emulator/sys/common/erl_mtrace_sys_wrap.c b/erts/emulator/sys/common/erl_mtrace_sys_wrap.c
deleted file mode 100644
index fc871f94f1..0000000000
--- a/erts/emulator/sys/common/erl_mtrace_sys_wrap.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-#include "sys.h"
-#include "erl_mtrace.h"
-
-#ifdef ERTS_CAN_TRACK_MALLOC
-#if defined(HAVE_END_SYMBOL)
-extern char end;
-#elif defined(HAVE__END_SYMBOL)
-extern char _end;
-#endif
-
-static int inited = 0;
-static int init(void);
-
-static volatile char *heap_start = NULL;
-static volatile char *heap_end = NULL;
-
-#if defined(ERTS___AFTER_MORECORE_HOOK_CAN_TRACK_MALLOC) /* ----------------- */
-
-#ifdef HAVE_MALLOC_H
-# include <malloc.h>
-#endif
-
-#undef SBRK_0
-#define SBRK_0 sbrk(0)
-
-static void
-init_hook(void)
-{
- __after_morecore_hook = erts_mtrace_update_heap_size;
- if (inited)
- return;
- heap_end = NULL;
-#if defined(HAVE_END_SYMBOL)
- heap_start = &end;
-#elif defined(HAVE__END_SYMBOL)
- heap_start = &_end;
-#else
- heap_start = SBRK_0;
- if (heap_start == (SBRK_RET_TYPE) -1) {
- heap_start = NULL;
- return;
- }
-#endif
- inited = 1;
-}
-
-static int
-init(void)
-{
- init_hook();
- return inited;
-}
-
-void (*__malloc_initialize_hook)(void) = init_hook;
-
-#elif defined(ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC) /* ------------------------ */
-#ifdef HAVE_DLFCN_H
-# include <dlfcn.h>
-#endif
-
-#undef SBRK_0
-#define SBRK_0 (*real_sbrk)(0)
-
-#ifndef HAVE_SBRK
-# error no sbrk()
-#endif
-#if !defined(HAVE_END_SYMBOL) && !defined(HAVE__END_SYMBOL)
-# error no 'end' nor '_end'
-#endif
-
-static void update_heap_size(char *new_end);
-
-#define SBRK_IMPL(RET_TYPE, FUNC, ARG_TYPE) \
-RET_TYPE FUNC (ARG_TYPE); \
-static RET_TYPE (*real_ ## FUNC)(ARG_TYPE) = NULL; \
-RET_TYPE FUNC (ARG_TYPE arg) \
-{ \
- RET_TYPE res; \
- if (!inited && !init()) \
- return (RET_TYPE) -1; \
- res = (*real_ ## FUNC)(arg); \
- if (erts_mtrace_enabled && res != ((RET_TYPE) -1)) \
- update_heap_size((char *) (*real_ ## FUNC)(0)); \
- return res; \
-}
-
-#define BRK_IMPL(RET_TYPE, FUNC, ARG_TYPE) \
-RET_TYPE FUNC (ARG_TYPE); \
-static RET_TYPE (*real_ ## FUNC)(ARG_TYPE) = NULL; \
-RET_TYPE FUNC (ARG_TYPE arg) \
-{ \
- RET_TYPE res; \
- if (!inited && !init()) \
- return (RET_TYPE) -1; \
- res = (*real_ ## FUNC)(arg); \
- if (erts_mtrace_enabled && res != ((RET_TYPE) -1)) \
- update_heap_size((char *) arg); \
- return res; \
-}
-
-SBRK_IMPL(SBRK_RET_TYPE, sbrk, SBRK_ARG_TYPE)
-#ifdef HAVE_BRK
- BRK_IMPL(BRK_RET_TYPE, brk, BRK_ARG_TYPE)
-#endif
-
-#ifdef HAVE__SBRK
- SBRK_IMPL(SBRK_RET_TYPE, _sbrk, SBRK_ARG_TYPE)
-#endif
-#ifdef HAVE__BRK
- BRK_IMPL(BRK_RET_TYPE, _brk, BRK_ARG_TYPE)
-#endif
-
-#ifdef HAVE___SBRK
- SBRK_IMPL(SBRK_RET_TYPE, __sbrk, SBRK_ARG_TYPE)
-#endif
-#ifdef HAVE___BRK
- BRK_IMPL(BRK_RET_TYPE, __brk, BRK_ARG_TYPE)
-#endif
-
-static int
-init(void)
-{
- if (inited)
- return 1;
-
-#define INIT_XBRK_SYM(SYM) \
-do { \
- if (!real_ ## SYM) { \
- real_ ## SYM = dlsym(RTLD_NEXT, #SYM); \
- if (!real_ ## SYM) { \
- errno = ENOMEM; \
- return 0; \
- } \
- } \
-} while (0)
-
- heap_end = NULL;
-#if defined(HAVE_END_SYMBOL)
- heap_start = &end;
-#elif defined(HAVE__END_SYMBOL)
- heap_start = &_end;
-#endif
-
- INIT_XBRK_SYM(sbrk);
-#ifdef HAVE_BRK
- INIT_XBRK_SYM(brk);
-#endif
-#ifdef HAVE__SBRK
- INIT_XBRK_SYM(_sbrk);
-#endif
-#ifdef HAVE__BRK
- INIT_XBRK_SYM(_brk);
-#endif
-#ifdef HAVE___SBRK
- INIT_XBRK_SYM(__sbrk);
-#endif
-#ifdef HAVE___BRK
- INIT_XBRK_SYM(__brk);
-#endif
-
- return inited = 1;
-#undef INIT_XBRK_SYM
-}
-
-#endif /* #elif defined(ERTS_BRK_WRAPPERS_CAN_TRACK_MALLOC) */ /* ----------- */
-
-static void
-update_heap_size(char *new_end)
-{
- volatile char *new_start, *old_start, *old_end;
- Uint size;
-
- if (new_end == ((char *) -1))
- return;
-
- new_start = (old_start = heap_start);
- old_end = heap_end;
- heap_end = new_end;
- if (new_end < old_start || !old_start)
- heap_start = (new_start = new_end);
-
- size = (Uint) (new_end - new_start);
-
- if (!old_end) {
- if (size)
- erts_mtrace_crr_alloc((void *) new_start,
- ERTS_ALC_A_SYSTEM,
- ERTS_MTRACE_SEGMENT_ID,
- size);
- else
- heap_end = NULL;
- }
- else {
- if (old_end != new_end || old_start != new_start) {
-
- if (size)
- erts_mtrace_crr_realloc((void *) new_start,
- ERTS_ALC_A_SYSTEM,
- ERTS_MTRACE_SEGMENT_ID,
- (void *) old_start,
- size);
- else {
- if (old_start)
- erts_mtrace_crr_free(ERTS_ALC_A_SYSTEM,
- ERTS_MTRACE_SEGMENT_ID,
- (void *) old_start);
- heap_end = NULL;
- }
- }
- }
-}
-
-#endif /* #ifdef ERTS_CAN_TRACK_MALLOC */
-
-void
-erts_mtrace_update_heap_size(void)
-{
-#ifdef ERTS_CAN_TRACK_MALLOC
- if (erts_mtrace_enabled && (inited || init()))
- update_heap_size((char *) SBRK_0);
-#endif
-}
-
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index ecf0d684c2..6aa001210f 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1965,7 +1965,7 @@ ERTS_POLL_EXPORT(erts_poll_wait)(ErtsPollSet *ps,
/*
* This may have happened because another thread deselected
* a fd in our poll set and then closed it, i.e. the driver
- * behaved correctly. We wan't to avoid looking for a bad
+ * behaved correctly. We want to avoid looking for a bad
* fd, that may even not exist anymore. Therefore, handle
* update requests and try again. This behaviour should only
* happen when using SELECT as the polling mechanism.
@@ -2466,7 +2466,7 @@ ERTS_POLL_EXPORT(erts_poll_get_selected_events)(ErtsPollSet *ps,
char fname[30];
char s[256];
FILE *f;
- unsigned int pos, flags, mnt_id;
+ unsigned int pos, flags, mnt_id, ino;
int hdr_lines, line = 1;
sprintf(fname,"/proc/%d/fdinfo/%d",getpid(), ps->kp_fd);
for (fd = 0; fd < len; fd++)
@@ -2476,14 +2476,16 @@ ERTS_POLL_EXPORT(erts_poll_get_selected_events)(ErtsPollSet *ps,
fprintf(stderr,"failed to open file %s, errno = %d\n", fname, errno);
return;
}
- hdr_lines = fscanf(f,"pos:\t%x\nflags:\t%x\nmnt_id:\t%x\n",
- &pos, &flags, &mnt_id);
+
+ hdr_lines = fscanf(f,"pos:\t%x\nflags:\t%x\nmnt_id:\t%x\nino:\t%x\n",
+ &pos, &flags, &mnt_id, &ino);
if (hdr_lines < 2) {
fprintf(stderr,"failed to parse file %s, errno = %d\n", fname, errno);
ASSERT(0);
fclose(f);
return;
}
+
line += hdr_lines;
while (fgets(s, sizeof(s) / sizeof(*s), f)) {
/* tfd: 10 events: 40000019 data: 180000000a */
diff --git a/erts/emulator/sys/unix/driver_int.h b/erts/emulator/sys/unix/driver_int.h
index 840b832878..5eb9ce54b8 100644
--- a/erts/emulator/sys/unix/driver_int.h
+++ b/erts/emulator/sys/unix/driver_int.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
* %CopyrightEnd%
*/
/*
- * System dependant driver declarations
+ * System dependent driver declarations
*/
#ifndef __DRIVER_INT_H__
diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c
index 652715f5f9..0a2ac9abf7 100644
--- a/erts/emulator/sys/unix/erl_child_setup.c
+++ b/erts/emulator/sys/unix/erl_child_setup.c
@@ -136,6 +136,43 @@ void sys_sigrelease(int sig)
sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)NULL);
}
+
+/* This version of read/write makes sure to read/write the entire size before
+ returning. Normal read/write can handle partial results which we do not want. */
+static ssize_t read_all(int fd, char *buff, size_t size) {
+ ssize_t res, pos = 0;
+ do {
+ if ((res = read(fd, buff + pos, size - pos)) < 0) {
+ if (errno == ERRNO_BLOCK || errno == EINTR)
+ continue;
+ return res;
+ }
+ if (res == 0) {
+ errno = EPIPE;
+ return -1;
+ }
+ pos += res;
+ } while(size - pos != 0);
+ return pos;
+}
+
+static ssize_t write_all(int fd, const char *buff, size_t size) {
+ ssize_t res, pos = 0;
+ do {
+ if ((res = write(fd, buff + pos, size - pos)) < 0) {
+ if (errno == ERRNO_BLOCK || errno == EINTR)
+ continue;
+ return res;
+ }
+ if (res == 0) {
+ errno = EPIPE;
+ return -1;
+ }
+ pos += res;
+ } while (size - pos != 0);
+ return pos;
+}
+
static void add_os_pid_to_port_id_mapping(Eterm, pid_t);
static Eterm get_port_id(pid_t);
static int forker_hash_init(void);
@@ -148,7 +185,7 @@ start_new_child(int pipes[])
{
struct sigaction sa;
int errln = -1;
- int size, res, i, pos = 0;
+ int size, i;
char *buff, *o_buff;
char *cmd, *cwd, *wd, **new_environ, **args = NULL;
@@ -166,12 +203,8 @@ start_new_child(int pipes[])
perror(NULL);
exit(1);
}
-
- do {
- res = read(pipes[0], (char*)&size, sizeof(size));
- } while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK));
- if (res <= 0) {
+ if (read_all(pipes[0], (char*)&size, sizeof(size)) <= 0) {
errln = __LINE__;
goto child_error;
}
@@ -180,20 +213,10 @@ start_new_child(int pipes[])
DEBUG_PRINT("size = %d", size);
- do {
- if ((res = read(pipes[0], buff + pos, size - pos)) < 0) {
- if (errno == ERRNO_BLOCK || errno == EINTR)
- continue;
- errln = __LINE__;
- goto child_error;
- }
- if (res == 0) {
- errno = EPIPE;
- errln = __LINE__;
- goto child_error;
- }
- pos += res;
- } while(size - pos != 0);
+ if (read_all(pipes[0], buff, size) <= 0) {
+ errln = __LINE__;
+ goto child_error;
+ }
o_buff = buff;
@@ -252,18 +275,13 @@ start_new_child(int pipes[])
}
DEBUG_PRINT("read ack");
- do {
+ {
ErtsSysForkerProto proto;
- res = read(pipes[0], &proto, sizeof(proto));
- if (res > 0) {
- ASSERT(proto.action == ErtsSysForkerProtoAction_Ack);
+ if (read_all(pipes[0], (char*)&proto, sizeof(proto)) <= 0) {
+ errln = __LINE__;
+ goto child_error;
}
- } while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK));
-
- if (res < 1) {
- errno = EPIPE;
- errln = __LINE__;
- goto child_error;
+ ASSERT(proto.action == ErtsSysForkerProtoAction_Ack);
}
DEBUG_PRINT("Set cwd to: '%s'",cwd);
@@ -373,15 +391,13 @@ child_error:
* for posterity. */
static void handle_sigchld(int sig) {
- int buff[2], res, __preverrno = errno;
+ int buff[2], __preverrno = errno;
+ ssize_t res;
sys_sigblock(SIGCHLD);
while ((buff[0] = waitpid((pid_t)(-1), buff+1, WNOHANG)) > 0) {
- do {
- res = write(sigchld_pipe[1], buff, sizeof(buff));
- } while (res < 0 && errno == EINTR);
- if (res <= 0)
+ if ((res = write_all(sigchld_pipe[1], (char*)buff, sizeof(buff))) <= 0)
ABORT("Failed to write to sigchld_pipe (%d): %d (%d)", sigchld_pipe[1], res, errno);
DEBUG_PRINT("Reap child %d (%d)", buff[0], buff[1]);
}
@@ -553,13 +569,11 @@ main(int argc, char *argv[])
proto.action = ErtsSysForkerProtoAction_Go;
proto.u.go.os_pid = os_pid;
proto.u.go.error_number = errno;
- while (write(pipes[1], &proto, sizeof(proto)) < 0 && errno == EINTR)
- ; /* remove gcc warning */
+ write_all(pipes[1], (char *)&proto, sizeof(proto));
#ifdef FORKER_PROTO_START_ACK
proto.action = ErtsSysForkerProtoAction_StartAck;
- while (write(uds_fd, &proto, sizeof(proto)) < 0 && errno == EINTR)
- ; /* remove gcc warning */
+ write_all(uds_fd, (char *)&proto, sizeof(proto));
#endif
sys_sigrelease(SIGCHLD);
@@ -571,10 +585,8 @@ main(int argc, char *argv[])
if (FD_ISSET(sigchld_pipe[0], &read_fds)) {
int ibuff[2];
ErtsSysForkerProto proto;
- res = read(sigchld_pipe[0], ibuff, sizeof(ibuff));
+ res = read_all(sigchld_pipe[0], (char *)ibuff, sizeof(ibuff));
if (res <= 0) {
- if (errno == EINTR)
- continue;
ABORT("Failed to read from sigchld pipe: %d (%d)", res, errno);
}
@@ -586,9 +598,7 @@ main(int argc, char *argv[])
proto.action = ErtsSysForkerProtoAction_SigChld;
proto.u.sigchld.error_number = ibuff[1];
DEBUG_PRINT("send sigchld to %d (errno = %d)", uds_fd, ibuff[1]);
- if (write(uds_fd, &proto, sizeof(proto)) < 0) {
- if (errno == EINTR)
- continue;
+ if (write_all(uds_fd, (char *)&proto, sizeof(proto)) < 0) {
/* The uds was close, which most likely means that the VM
has exited. This will be detected when we try to read
from the uds_fd. */
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index ab0de4ad9d..c93c0dc5cc 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -73,15 +73,9 @@
# include <sys/mman.h>
#endif
-#if TIME_WITH_SYS_TIME
+#include <time.h>
+#if HAVE_SYS_TIME_H
# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
#include <sys/times.h>
@@ -113,6 +107,10 @@
# define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 1
#endif
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+
/*
* Make sure that MAXPATHLEN is defined.
*/
diff --git a/erts/emulator/sys/unix/erl_unix_sys_ddll.c b/erts/emulator/sys/unix/erl_unix_sys_ddll.c
index 71a26fc7ef..d8d8fc13a8 100644
--- a/erts/emulator/sys/unix/erl_unix_sys_ddll.c
+++ b/erts/emulator/sys/unix/erl_unix_sys_ddll.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -180,6 +180,31 @@ int erts_sys_ddll_sym2(void *handle, const char *func_name, void **function,
#endif
}
+/*
+ * Find a symbol in the shared object
+ */
+int erts_sys_ddll_vsym2(void *handle, const char *func_name, const char *vers,
+ void **function, ErtsSysDdllError* err)
+{
+#if defined(HAVE_DLVSYM)
+ void *sym;
+ char *e;
+ int ret;
+ dlerror();
+ sym = dlvsym(handle, func_name, vers);
+ if ((e = dlerror()) != NULL) {
+ ret = ERL_DE_DYNAMIC_ERROR_OFFSET - find_errcode(e, err);
+ ASSERT(ret != ERL_DE_NO_ERROR);
+ } else {
+ *function = sym;
+ ret = ERL_DE_NO_ERROR;
+ }
+ return ret;
+#else
+ return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;
+#endif
+}
+
/* XXX:PaN These two will be changed with new driver interface! */
/*
diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c
index 91e8a087ed..f7a043d68b 100644
--- a/erts/emulator/sys/unix/sys_float.c
+++ b/erts/emulator/sys/unix/sys_float.c
@@ -56,7 +56,7 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
if (erts_snprintf(buffer, buffer_size, "%.*e", decimals, fp) >= buffer_size)
return -1;
- /* Search upto decimal point */
+ /* Search up to decimal point */
if (*s == '+' || *s == '-') s++;
while (ISDIGIT(*s)) s++;
if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */
diff --git a/erts/emulator/sys/unix/sys_signal_stack.c b/erts/emulator/sys/unix/sys_signal_stack.c
index f4731a5034..3bd7d98a89 100644
--- a/erts/emulator/sys/unix/sys_signal_stack.c
+++ b/erts/emulator/sys/unix/sys_signal_stack.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -97,7 +97,7 @@
* Assumes Mac OS X >= 10.3 (dlsym operations not available in 10.2 and
* earlier).
*
- * The code below assumes that is is part of the main image (earlier
+ * The code below assumes that is part of the main image (earlier
* in the load order than libSystem and certainly before any dylib
* that might use sigaction) -- a standard RTLD_NEXT caveat.
*
diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c
index 5fd48b793c..eb2c47bb20 100644
--- a/erts/emulator/sys/unix/sys_time.c
+++ b/erts/emulator/sys/unix/sys_time.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2005-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2005-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,7 +89,7 @@ get_tick_count(void)
/*
* init timers, chose a tick length, and return it.
- * Unix is priviliged when it comes to time, as erl_time_sup.c
+ * Unix is privileged when it comes to time, as erl_time_sup.c
* does almost everything. Other platforms have to
* emulate Unix in this sense.
*/
@@ -219,7 +219,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
#endif
init_resp->os_monotonic_time_info.resolution = (Uint64) 1000*1000*1000;
-#if defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID)
+#if defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
init_resp->os_monotonic_time_info.resolution
= mach_clock_getres(&internal_state.r.o.mach.clock.monotonic);
#elif defined(HAVE_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID)
@@ -379,7 +379,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
init_resp->os_system_time_info.locked_use = 0;
init_resp->os_system_time_info.resolution = (Uint64) 1000*1000*1000;
-#if defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(WALL_CLOCK_ID)
+#if defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
init_resp->os_system_time_info.resolution
= mach_clock_getres(&internal_state.r.o.mach.clock.wall);
#elif defined(HAVE_CLOCK_GETRES) && defined(WALL_CLOCK_ID)
diff --git a/erts/emulator/sys/win32/driver_int.h b/erts/emulator/sys/win32/driver_int.h
index 50097d3fd2..a337058f99 100644
--- a/erts/emulator/sys/win32/driver_int.h
+++ b/erts/emulator/sys/win32/driver_int.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
* %CopyrightEnd%
*/
/*----------------------------------------------------------------------
-** Purpose : System dependant driver declarations
+** Purpose : System dependent driver declarations
**---------------------------------------------------------------------- */
#ifndef __DRIVER_INT_H__
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index 3843a27a6e..36b4ebd552 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2007-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2007-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -320,7 +320,7 @@ static void *threaded_waiter(void *param);
static void *break_waiter(void *param);
/*
- * Sychronization macros and functions
+ * Synchronization macros and functions
*/
#define START_WAITER(PS, w) \
SetEvent((w)->go_ahead)
@@ -435,7 +435,7 @@ wake_poller(ErtsPollSet *ps, int io_ready)
/*
* Since we don't know the internals of SetEvent() we issue
* a memory barrier as a safety precaution ensuring that
- * the store we just made to wakeup_state wont be reordered
+ * the store we just made to wakeup_state won't be reordered
* with loads in SetEvent().
*/
ERTS_THR_MEMORY_BARRIER;
@@ -769,7 +769,7 @@ event_happened:
notify_io_ready(ps);
/*
- * The main thread wont start working on our arrays until we're
+ * The main thread won't start working on our arrays until we're
* stopped, so we can work in peace although the main thread runs
*/
ASSERT(i >= WAIT_OBJECT_0+1);
@@ -1044,7 +1044,7 @@ int erts_poll_wait(ErtsPollSet *ps,
/*
* Since we don't know the internals of ResetEvent() we issue
* a memory barrier as a safety precaution ensuring that
- * the load of wakeup_state wont be reordered with stores made
+ * the load of wakeup_state won't be reordered with stores made
* by ResetEvent().
*/
ERTS_THR_MEMORY_BARRIER;
@@ -1287,7 +1287,7 @@ void erts_poll_late_init(void)
}
/*
- * Non windows friendly interface, not used when fd's are not continous
+ * Non windows friendly interface, not used when fd's are not continuous
*/
void erts_poll_get_selected_events(ErtsPollSet *ps,
ErtsPollEvents ev[],
diff --git a/erts/emulator/sys/win32/erl_win32_sys_ddll.c b/erts/emulator/sys/win32/erl_win32_sys_ddll.c
index 7fe1f5cc78..c0714762b0 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-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@ int erts_sys_ddll_open(const char *full_name, void **handle, ErtsSysDdllError* e
/* LOAD_WITH_ALTERED_SEARCH_PATH adds the specified DLL's directory to the
* dependency search path. This also removes the directory we started in,
- * but we've explicitly added that in in erl_sys_ddll_init. */
+ * but we've explicitly added that in erl_sys_ddll_init. */
if ((hinstance = LoadLibraryExW(wcp, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL) {
code = ERL_DE_DYNAMIC_ERROR_OFFSET - GetLastError();
if (err != NULL) {
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index c683e8cf49..8105128f87 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2003-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2003-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -262,7 +262,7 @@ typedef struct {
/* Add new calls here */
} TWinDynDriverCallbacks;
-/* This header is included explicitly by the ddll static driver, it musn't define things then */
+/* This header is included explicitly by the ddll static driver, it mustn't define things then */
#ifndef STATIC_ERLANG_DRIVER
extern TWinDynDriverCallbacks WinDynDriverCallbacks;
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index 513adbed63..a7b1f7ac95 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -95,7 +95,7 @@
#define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 1
/*
- * Practial Windows specific macros.
+ * Practical Windows specific macros.
*/
#define CreateAutoEvent(state) CreateEvent(NULL, FALSE, state, NULL)
@@ -271,7 +271,7 @@ extern volatile int erl_fp_exception;
#include <float.h>
/* 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
+ rather than if it's a MINGW gcc, but I haven't 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);
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index fd3cb34130..2a37c075f8 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -77,7 +77,7 @@ static BOOL create_child_process(wchar_t *, HANDLE, HANDLE,
static int create_pipe(LPHANDLE, LPHANDLE, BOOL, BOOL);
static int application_type(const wchar_t* originalName, wchar_t fullPath[MAX_PATH],
BOOL search_in_path, BOOL handle_quotes,
- int *error_return, BOOL *requote);
+ int *error_return);
static void *build_env_block(const erts_osenv_t *env);
HANDLE erts_service_event;
@@ -704,11 +704,11 @@ release_driver_data(DriverData* dp)
else
#endif
{
- /* This is a workaround for the fact that CancelIo cant cancel
- requests issued by another thread and that we cant use
+ /* This is a workaround for the fact that CancelIo can't cancel
+ requests issued by another thread and that we can't use
CancelIoEx as that's only available in Vista etc.
R14: Avoid scheduler deadlock by only wait for 10ms, and then spawn
- a thread that will keep waiting in in order to close handles. */
+ a thread that will keep waiting in order to close handles. */
HANDLE handles[2];
int i = 0;
int timeout = 10;
@@ -1020,7 +1020,7 @@ async_read_file(AsyncIo* aio, LPVOID buf, DWORD numToRead)
aio->async_io_active = 1; /* Will get 0 when the event actually happened */
if (ReadFile(aio->fd, buf, numToRead,
&aio->bytesTransferred, &aio->ov)) {
- DEBUGF(("async_read_file: ReadFile() suceeded: %d bytes\n",
+ DEBUGF(("async_read_file: ReadFile() succeeded: %d bytes\n",
aio->bytesTransferred));
#ifdef HARD_POLL_DEBUG
poll_debug_async_immediate(aio->ov.hEvent, aio->bytesTransferred);
@@ -1068,7 +1068,7 @@ async_write_file(AsyncIo* aio, /* Pointer to async control block. */
aio->async_io_active = 1; /* Will get 0 when the event actually happened */
if (WriteFile(aio->fd, buf, numToWrite,
&aio->bytesTransferred, &aio->ov)) {
- DEBUGF(("async_write_file: WriteFile() suceeded: %d bytes\n",
+ DEBUGF(("async_write_file: WriteFile() succeeded: %d bytes\n",
aio->bytesTransferred));
aio->async_io_active = 0; /* The event will not be signalled */
ResetEvent(aio->ov.hEvent);
@@ -1137,7 +1137,7 @@ get_overlapped_result(AsyncIo* aio, /* Pointer to async control block. */
DEBUGF(("get_overlapped_result: pending error: %s\n",
win32_errorstr(error)));
return error;
- } else if (aio->flags & DF_OVR_READY) { /* Operation succeded. */
+ } else if (aio->flags & DF_OVR_READY) { /* Operation succeeded. */
aio->flags &= ~DF_OVR_READY;
*pBytesRead = aio->bytesTransferred;
ResetEvent(aio->ov.hEvent);
@@ -1526,7 +1526,7 @@ create_child_process
wchar_t *wd, /* Working dir for the child */
unsigned st, /* Flags for spawn, tells us how to interpret origcmd */
wchar_t **argv, /* Argument vector if given. */
- int *errno_return /* Place to put an errno in in case of failure */
+ int *errno_return /* Place to put an errno in case of failure */
)
{
PROCESS_INFORMATION piProcInfo = {0};
@@ -1542,7 +1542,9 @@ create_child_process
HANDLE hProcess = GetCurrentProcess();
STARTUPINFOW siStartInfo = {0};
wchar_t execPath[MAX_PATH];
- BOOL requote = FALSE;
+ BOOL need_quote;
+ int quotedLen;
+ wchar_t *ptr;
*errno_return = -1;
siStartInfo.cb = sizeof(STARTUPINFOW);
@@ -1557,22 +1559,25 @@ create_child_process
* contain spaces).
*/
cmdlength = parse_command(origcmd);
- newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (MAX_PATH+wcslen(origcmd)-cmdlength)*sizeof(wchar_t));
thecommand = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP, (cmdlength+1)*sizeof(wchar_t));
wcsncpy(thecommand, origcmd, cmdlength);
thecommand[cmdlength] = L'\0';
DEBUGF(("spawn command: %S\n", thecommand));
applType =
- application_type(thecommand, execPath, TRUE, TRUE, errno_return, &requote);
+ application_type(thecommand, execPath, TRUE, TRUE, errno_return);
DEBUGF(("application_type returned for (%S) is %d\n", thecommand, applType));
erts_free(ERTS_ALC_T_TMP, (void *) thecommand);
- if (applType == APPL_NONE) {
- erts_free(ERTS_ALC_T_TMP,newcmdline);
+ if (applType == APPL_NONE) {
return FALSE;
}
- newcmdline[0] = L'\0';
+ quotedLen = escape_and_quote(execPath, NULL, &need_quote);
+ newcmdline = (wchar_t *)
+ erts_alloc(ERTS_ALC_T_TMP,
+ (11+quotedLen+wcslen(origcmd)-cmdlength)*sizeof(wchar_t));
+
+ ptr = newcmdline;
if (applType == APPL_DOS) {
/*
* Under NT, 16-bit DOS applications will not run unless they
@@ -1584,7 +1589,8 @@ create_child_process
siStartInfo.wShowWindow = SW_HIDE;
siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
createFlags = CREATE_NEW_CONSOLE;
- wcscat(newcmdline, L"cmd.exe /c ");
+ wcscpy(newcmdline, L"cmd.exe /c ");
+ ptr += 11;
} else if (hide) {
DEBUGF(("hiding window\n"));
siStartInfo.wShowWindow = SW_HIDE;
@@ -1592,14 +1598,9 @@ create_child_process
createFlags = 0;
}
- if (requote) {
- wcscat(newcmdline, L"\"");
- }
- wcscat(newcmdline, execPath);
- if (requote) {
- wcscat(newcmdline, L"\"");
- }
- wcscat(newcmdline, origcmd+cmdlength);
+ ptr += escape_and_quote(execPath, ptr, &need_quote);
+
+ wcscpy(ptr, origcmd+cmdlength);
DEBUGF(("Creating child process: %S, createFlags = %d\n", newcmdline, createFlags));
ok = CreateProcessW((applType == APPL_DOS) ? appname : execPath,
newcmdline,
@@ -1617,7 +1618,7 @@ create_child_process
int run_cmd = 0;
applType =
- application_type(origcmd, execPath, FALSE, FALSE, errno_return, &requote);
+ application_type(origcmd, execPath, FALSE, FALSE, errno_return);
if (applType == APPL_NONE) {
return FALSE;
}
@@ -1640,7 +1641,7 @@ create_child_process
wchar_t cmdPath[MAX_PATH];
int cmdType;
cmdType =
- application_type(L"cmd.exe", cmdPath, TRUE, FALSE, errno_return, &requote);
+ application_type(L"cmd.exe", cmdPath, TRUE, FALSE, errno_return);
if (cmdType == APPL_NONE || cmdType == APPL_DOS) {
return FALSE;
}
@@ -1759,7 +1760,7 @@ static int create_pipe(HANDLE *phRead, HANDLE *phWrite, BOOL inheritRead, BOOL o
Uint calls;
/*
- * If we should't use named pipes, create anonmous pipes.
+ * If we shouldn't use named pipes, create anonmous pipes.
*/
if (!use_named_pipes) {
@@ -1832,8 +1833,7 @@ static int application_type (const wchar_t *originalName, /* Name of the applica
* application. */
BOOL search_in_path, /* If we should search the system wide path */
BOOL handle_quotes, /* If we should handle quotes around executable */
- int *error_return, /* A place to put an error code */
- BOOL *requote) /* The path needs requoting */
+ int *error_return) /* A place to put an error code */
{
int applType, i;
HANDLE hFile;
@@ -1844,15 +1844,17 @@ static int application_type (const wchar_t *originalName, /* Name of the applica
static wchar_t extensions[][5] = {L"", L".com", L".exe", L".bat"};
int len;
wchar_t xfullpath[MAX_PATH];
+ BOOL is_quoted;
len = wcslen(originalName);
- *requote = handle_quotes && len > 0 && originalName[0] == L'"' &&
- originalName[len-1] == L'"';
+ is_quoted = (handle_quotes && len > 0
+ && originalName[0] == L'"'
+ && originalName[len-1] == L'"');
applType = APPL_NONE;
*error_return = ENOENT;
for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
- if(*requote) {
+ if(is_quoted) {
lstrcpynW(xfullpath, originalName+1, MAX_PATH - 7); /* Cannot start using StringCchCopy yet, we support
older platforms */
len = wcslen(xfullpath);
@@ -2054,7 +2056,7 @@ threaded_writer(LPVOID param)
aio->pendingError = 0;
aio->bytesTransferred = numToWrite;
} else if (aio->pendingError == ERROR_NOT_ENOUGH_MEMORY) {
- /* This could be a console, which limits utput to 64kbytes,
+ /* This could be a console, which limits output to 64kbytes,
which might translate to less on a unicode system.
Try 16k chunks and see if it works before giving up. */
int done = 0;
@@ -2217,7 +2219,7 @@ static void fd_stop(ErlDrvData data)
/*
* There's no way we can terminate an fd port in a consistent way.
* Instead we let it live until it's opened again (which it is,
- * as the only FD-drivers are for 0,1 and 2 adn the only time they
+ * as the only FD-drivers are for 0,1 and 2 and the only time they
* get closed is by init:reboot).
* So - just deselect them and let everything be as is.
* They get woken up in fd_start again, where the DriverData is
diff --git a/erts/emulator/sys/win32/sys_float.c b/erts/emulator/sys/win32/sys_float.c
index 22457a4be4..0c8d961508 100644
--- a/erts/emulator/sys/win32/sys_float.c
+++ b/erts/emulator/sys/win32/sys_float.c
@@ -113,7 +113,7 @@ sys_double_to_chars_ext(double fp, char *buffer, size_t buffer_size, size_t deci
if (erts_snprintf(buffer, buffer_size, "%.*e", decimals, fp) >= buffer_size)
return -1;
- /* Search upto decimal point */
+ /* Search up to decimal point */
if (*s == '+' || *s == '-') s++;
while (isdigit(*s)) s++;
if (*s == ',') *s++ = '.'; /* Replace ',' with '.' */
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index e7849c7dd2..33a80f2e53 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -76,6 +76,7 @@ MODULES= \
hello_SUITE \
hibernate_SUITE \
iovec_SUITE \
+ jit_SUITE \
list_bif_SUITE \
lttng_SUITE \
lcnt_SUITE \
@@ -92,7 +93,6 @@ MODULES= \
message_queue_data_SUITE \
op_SUITE \
os_signal_SUITE \
- perf_SUITE \
port_SUITE \
port_bif_SUITE \
prim_eval_SUITE \
@@ -169,6 +169,7 @@ EMAKEFILE=Emakefile
TEST_SPEC_FILES= emulator.spec \
emulator.spec.win \
emulator_bench.spec \
+ emulator_gh.spec \
emulator_smoke.spec \
emulator_node_container_SUITE.spec
@@ -181,7 +182,7 @@ RELSYSDIR = $(RELEASE_PATH)/emulator_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$($(ERL_COMPILE_FLAGS)))
# ----------------------------------------------------
# Targets
diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl
index e96f0fa075..cea3d610a0 100644
--- a/erts/emulator/test/alloc_SUITE.erl
+++ b/erts/emulator/test/alloc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,9 @@
migration/1,
cpool_opt/1]).
+%% Internal export
+-export([run_drv_case/2]).
+
-include_lib("common_test/include/ct.hrl").
suite() ->
@@ -60,10 +63,10 @@ end_per_suite(_Config) ->
ok.
init_per_testcase(Case, Config) when is_list(Config) ->
- [{testcase, Case},{debug,false}|Config].
+ [{testcase, Case}|Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%
@@ -84,47 +87,41 @@ migration(Cfg) ->
%% Enable test_alloc.
%% Disable driver_alloc to avoid recursive alloc_util calls
%% through enif_mutex_create() in my_creating_mbc().
- drv_case(Cfg, concurrent, "+MZe true +MRe false"),
- drv_case(Cfg, concurrent, "+MZe true +MRe false +MZas ageffcbf"),
- drv_case(Cfg, concurrent, "+MZe true +MRe false +MZas chaosff").
+ drv_case(Cfg, concurrent, ["+MZe", "true", "+MRe", "false"]),
+ drv_case(Cfg, concurrent, ["+MZe", "true", "+MRe", "false", "+MZas", "ageffcbf"]),
+ drv_case(Cfg, concurrent, ["+MZe", "true", "+MRe", "false", "+MZas", "chaosff"]).
cpool_opt(Config) when is_list(Config) ->
- OldEnv = clear_env(),
- try
- {ok, NodeA} = start_node(Config, "+Mue true +Mut true +Muacul de +Mucp @", []),
- {cp, '@'} = get_cp_opt(NodeA, binary_alloc),
- {cp, '@'} = get_cp_opt(NodeA, std_alloc),
- {cp, '@'} = get_cp_opt(NodeA, ets_alloc),
- {cp, '@'} = get_cp_opt(NodeA, fix_alloc),
- {cp, '@'} = get_cp_opt(NodeA, eheap_alloc),
- {cp, '@'} = get_cp_opt(NodeA, ll_alloc),
- {cp, '@'} = get_cp_opt(NodeA, driver_alloc),
- {cp, '@'} = get_cp_opt(NodeA, sl_alloc),
- stop_node(NodeA),
- {ok, NodeB} = start_node(Config, "+Mue true +Mut true +Muacul de +Mucp :", []),
- {cp, 'B'} = get_cp_opt(NodeB, binary_alloc),
- {cp, 'D'} = get_cp_opt(NodeB, std_alloc),
- {cp, 'E'} = get_cp_opt(NodeB, ets_alloc),
- {cp, 'F'} = get_cp_opt(NodeB, fix_alloc),
- {cp, 'H'} = get_cp_opt(NodeB, eheap_alloc),
- {cp, 'L'} = get_cp_opt(NodeB, ll_alloc),
- {cp, 'R'} = get_cp_opt(NodeB, driver_alloc),
- {cp, 'S'} = get_cp_opt(NodeB, sl_alloc),
- stop_node(NodeB),
- {ok, NodeC} = start_node(Config, "+Mue true +Mut true +Muacul de +Mucp : +MEcp H", []),
- {cp, 'B'} = get_cp_opt(NodeC, binary_alloc),
- {cp, 'D'} = get_cp_opt(NodeC, std_alloc),
- {cp, 'H'} = get_cp_opt(NodeC, ets_alloc),
- {cp, 'F'} = get_cp_opt(NodeC, fix_alloc),
- {cp, 'H'} = get_cp_opt(NodeC, eheap_alloc),
- {cp, 'L'} = get_cp_opt(NodeC, ll_alloc),
- {cp, 'R'} = get_cp_opt(NodeC, driver_alloc),
- {cp, 'S'} = get_cp_opt(NodeC, sl_alloc),
- stop_node(NodeC)
- after
- restore_env(OldEnv)
- end,
- ok.
+ {ok, PeerA, NodeA} = ?CT_PEER(["+Mue", "true", "+Mut", "true", "+Muacul", "de", "+Mucp", "@"]),
+ {cp, '@'} = get_cp_opt(NodeA, binary_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, std_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, ets_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, fix_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, eheap_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, ll_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, driver_alloc),
+ {cp, '@'} = get_cp_opt(NodeA, sl_alloc),
+ peer:stop(PeerA),
+ {ok, PeerB, NodeB} = ?CT_PEER(["+Mue", "true", "+Mut", "true", "+Muacul", "de", "+Mucp", ":"]),
+ {cp, 'B'} = get_cp_opt(NodeB, binary_alloc),
+ {cp, 'D'} = get_cp_opt(NodeB, std_alloc),
+ {cp, 'E'} = get_cp_opt(NodeB, ets_alloc),
+ {cp, 'F'} = get_cp_opt(NodeB, fix_alloc),
+ {cp, 'H'} = get_cp_opt(NodeB, eheap_alloc),
+ {cp, 'L'} = get_cp_opt(NodeB, ll_alloc),
+ {cp, 'R'} = get_cp_opt(NodeB, driver_alloc),
+ {cp, 'S'} = get_cp_opt(NodeB, sl_alloc),
+ peer:stop(PeerB),
+ {ok, PeerC, NodeC} = ?CT_PEER(["+Mue", "true", "+Mut", "true", "+Muacul", "de", "+Mucp", ":", "+MEcp", "H"]),
+ {cp, 'B'} = get_cp_opt(NodeC, binary_alloc),
+ {cp, 'D'} = get_cp_opt(NodeC, std_alloc),
+ {cp, 'H'} = get_cp_opt(NodeC, ets_alloc),
+ {cp, 'F'} = get_cp_opt(NodeC, fix_alloc),
+ {cp, 'H'} = get_cp_opt(NodeC, eheap_alloc),
+ {cp, 'L'} = get_cp_opt(NodeC, ll_alloc),
+ {cp, 'R'} = get_cp_opt(NodeC, driver_alloc),
+ {cp, 'S'} = get_cp_opt(NodeC, sl_alloc),
+ peer:stop(PeerC).
get_cp_opt(Node, Alloc) ->
AInfo = rpc:call(Node, erlang, system_info, [{allocator,Alloc}]),
@@ -136,7 +133,7 @@ get_cp_opt(Node, Alloc) ->
erts_mmap(Config) when is_list(Config) ->
case {os:type(), mmsc_flags()} of
{{unix,_}, false} ->
- [erts_mmap_do(Config, SCO, SCRPM, SCRFSD)
+ [erts_mmap_do(SCO, SCRPM, SCRFSD)
|| SCO <-[true,false], SCRFSD <-[1234,0], SCRPM <- [true,false]];
{{unix,_}, Flags} ->
{skipped, Flags};
@@ -162,23 +159,21 @@ mmsc_flags(Env) ->
end
end.
-erts_mmap_do(Config, SCO, SCRPM, SCRFSD) ->
+erts_mmap_do(SCO, SCRPM, SCRFSD) ->
%% We use the number of schedulers + 1 * approx main carriers size
%% to calculate how large the super carrier has to be
%% and then use a minimum of 100 for systems with a low amount of
%% schedulers
Schldr = erlang:system_info(schedulers_online)+1,
SCS = max(round((262144 * 6 + 3 * 1048576) * Schldr / 1024 / 1024),100),
- O1 = "+MMscs" ++ integer_to_list(SCS)
- ++ " +MMsco" ++ atom_to_list(SCO)
- ++ " +MMscrpm" ++ atom_to_list(SCRPM),
+ O1 = ["+MMscs" ++ integer_to_list(SCS),
+ "+MMsco" ++ atom_to_list(SCO),
+ "+MMscrpm" ++ atom_to_list(SCRPM)],
Opts = case SCRFSD of
0 -> O1;
- _ -> O1 ++ " +MMscrfsd"++integer_to_list(SCRFSD)
+ _ -> O1 ++ ["+MMscrfsd"++integer_to_list(SCRFSD)]
end,
- {ok, Node} = start_node(Config, Opts, []),
- Self = self(),
- Ref = make_ref(),
+ {ok, Peer, Node} = ?CT_PEER(Opts),
F = fun() ->
SI = erlang:system_info({allocator,erts_mmap}),
{default_mmap,EM} = lists:keyfind(default_mmap, 1, SI),
@@ -197,12 +192,12 @@ erts_mmap_do(Config, SCO, SCRPM, SCRFSD) ->
{false, {os,_}} -> ok
end,
- Self ! {Ref, ok}
+ exit(ok)
end,
- spawn_link(Node, F),
- Result = receive {Ref, Rslt} -> Rslt end,
- stop_node(Node),
+ {Pid, MRef} = spawn_monitor(Node, F),
+ Result = receive {'DOWN', MRef, process, Pid, Rslt} -> Rslt end,
+ peer:stop(Peer),
Result.
@@ -293,18 +288,11 @@ drv_case(Config) ->
drv_case(Config, Mode, NodeOpts) when is_list(Config) ->
case os:type() of
{Family, _} when Family == unix; Family == win32 ->
- %%Prog = {prog,"/my/own/otp/bin/cerl -debug"},
- Prog = [],
- {ok, Node} = start_node(Config, NodeOpts, Prog),
- Self = self(),
- Ref = make_ref(),
- spawn_link(Node,
- fun () ->
- Res = run_drv_case(Config, Mode),
- Self ! {Ref, Res}
- end),
- Result = receive {Ref, Rslt} -> Rslt end,
- stop_node(Node),
+ %% ?CT_PEER(#{exec => {"/usr/local/bin/erl", ["-emu_type", "debug"]}})
+ TC = proplists:get_value(testcase, Config),
+ {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(TC), args => NodeOpts}),
+ Result = erpc:call(Node, ?MODULE, run_drv_case, [Config, Mode]),
+ peer:stop(Peer),
Result;
SkipOs ->
{skipped,
@@ -493,84 +481,21 @@ handle_result(_State, Result0) ->
continue
end.
-start_node(Config, Opts, Prog) when is_list(Config), is_list(Opts) ->
- case proplists:get_value(debug,Config) of
- true -> {ok, node()};
- _ -> start_node_1(Config, Opts, Prog)
- end.
-
-start_node_1(Config, Opts, Prog) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- ErlArg = case Prog of
- [] -> [];
- _ -> [{erl,[Prog]}]
- end,
- test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa} | ErlArg]).
-
-stop_node(Node) when Node =:= node() -> ok;
-stop_node(Node) ->
- test_server:stop_node(Node).
-
free_memory() ->
%% Free memory in MB.
try
SMD = memsup:get_system_memory_data(),
- {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD),
- TotFree = (Free +
- case lists:keysearch(cached_memory, 1, SMD) of
- {value, {cached_memory, Cached}} -> Cached;
- false -> 0
- end +
- case lists:keysearch(buffered_memory, 1, SMD) of
- {value, {buffered_memory, Buffed}} -> Buffed;
- false -> 0
- end),
+ TotFree = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(free_memory, SMD) +
+ proplists:get_value(cached_memory, SMD, 0) +
+ proplists:get_value(buffered_memory, SMD, 0)
+ ),
TotFree div (1024*1024)
catch
error : undef ->
ct:fail({"os_mon not built"})
end.
-clear_env() ->
- ErlRelFlagsName =
- "ERL_OTP"
- ++ erlang:system_info(otp_release)
- ++ "_FLAGS",
- ErlFlags = os:getenv("ERL_FLAGS"),
- os:unsetenv("ERL_FLAGS"),
- ErlAFlags = os:getenv("ERL_AFLAGS"),
- os:unsetenv("ERL_AFLAGS"),
- ErlZFlags = os:getenv("ERL_ZFLAGS"),
- os:unsetenv("ERL_ZFLAGS"),
- ErlRelFlags = os:getenv(ErlRelFlagsName),
- os:unsetenv(ErlRelFlagsName),
- {ErlFlags, ErlAFlags, ErlZFlags, ErlRelFlags}.
-
-restore_env({ErlFlags, ErlAFlags, ErlZFlags, ErlRelFlags}) ->
- if ErlFlags == false -> ok;
- true -> os:putenv("ERL_FLAGS", ErlFlags)
- end,
- if ErlAFlags == false -> ok;
- true -> os:putenv("ERL_AFLAGS", ErlAFlags)
- end,
- if ErlZFlags == false -> ok;
- true -> os:putenv("ERL_ZFLAGS", ErlZFlags)
- end,
- if ErlRelFlags == false -> ok;
- true ->
- ErlRelFlagsName =
- "ERL_OTP"
- ++ erlang:system_info(otp_release)
- ++ "_FLAGS",
- os:putenv(ErlRelFlagsName, ErlRelFlags)
- end,
- ok.
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
index c94c265f4e..36dbce9f20 100644
--- a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
@@ -24,7 +24,7 @@
#include <stdio.h>
#if defined(__WIN32__) && SIZEOF_VOID_P == 8
-/* Use larger threashold for win64 as block alignment
+/* Use larger threshold for win64 as block alignment
is 16 bytes and not 8 */
#define SBCT ((1024*1024))
#else
diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.c b/erts/emulator/test/alloc_SUITE_data/coalesce.c
index 7791409a34..cbab000db7 100644
--- a/erts/emulator/test/alloc_SUITE_data/coalesce.c
+++ b/erts/emulator/test/alloc_SUITE_data/coalesce.c
@@ -126,7 +126,7 @@ test_free(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz)
FREE(a, p[0]);
FREE(a, p[6]);
- testcase_printf(tcs," --- free() with block size %lu succeded ---\n",bsz);
+ testcase_printf(tcs," --- free() with block size %lu succeeded ---\n",bsz);
}
static void
@@ -195,7 +195,7 @@ test_realloc(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz)
ASSERT(tcs, IS_FREE_BLK(blk));
ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[2]));
- /* Grow upto next alloced block by allocating just enough so that no
+ /* Grow up to next allocated block by allocating just enough so that no
free block fits between them */
nbsz = BLK_SZ(blk) + UMEM_SZ(UMEM2BLK(p[0]));
nbsz -= MIN_BLK_SZ(a) - 1;
@@ -227,7 +227,7 @@ test_realloc(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz)
ASSERT(tcs, blk == UMEM2BLK(p[2]));
/* Shrink just as much so that a free block can fit between
- the alloced blocks */
+ the allocated blocks */
nbsz -= 1;
ptr = REALLOC(a, p[0], nbsz);
ASSERT(tcs, p[0] == ptr);
@@ -253,7 +253,7 @@ test_realloc(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz)
FREE(a, p[0]);
FREE(a, p[2]);
- testcase_printf(tcs, " --- realloc() with block size %lu succeded ---\n",
+ testcase_printf(tcs, " --- realloc() with block size %lu succeeded ---\n",
bsz);
}
diff --git a/erts/emulator/test/beam_SUITE.erl b/erts/emulator/test/beam_SUITE.erl
index 584bec967b..d44e038d1b 100644
--- a/erts/emulator/test/beam_SUITE.erl
+++ b/erts/emulator/test/beam_SUITE.erl
@@ -239,7 +239,7 @@ heap_sizes(Config) when is_list(Config) ->
%% Verify that the largest heap size consists of
%% - 31 bits of bytes on 32 bits arch
- %% - atleast 52 bits of bytes (48 is the maximum virtual address)
+ %% - at least 52 bits of bytes (48 is the maximum virtual address)
%% and at the most 63 bits on 64 bit archs
%% heap sizes are in words
case erlang:system_info(wordsize) of
diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl
index e3b4c4661a..69e911e796 100644
--- a/erts/emulator/test/bif_SUITE.erl
+++ b/erts/emulator/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@
error_stacktrace_during_call_trace/1,
group_leader_prio/1, group_leader_prio_dirty/1,
is_process_alive/1,
+ is_process_alive_signal_from/1,
process_info_blast/1,
os_env_case_sensitivity/1,
verify_middle_queue_save/1,
@@ -57,7 +58,8 @@ all() ->
erl_crash_dump_bytes, min_max, erlang_halt, is_builtin,
error_stacktrace, error_stacktrace_during_call_trace,
group_leader_prio, group_leader_prio_dirty,
- is_process_alive, process_info_blast, os_env_case_sensitivity,
+ is_process_alive, is_process_alive_signal_from,
+ process_info_blast, os_env_case_sensitivity,
verify_middle_queue_save, test_length,fixed_apply_badarg,
external_fun_apply3].
@@ -70,8 +72,8 @@ init_per_testcase(shadow_comments, Config) when is_list(Config) ->
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Config.
-end_per_testcase(_Func, _Config) ->
- ok.
+end_per_testcase(_Func, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
%% erl_bif_types comes from dialyzer which some test runs skip building, so
%% we'll skip the tests that use it as the result shouldn't vary based on
@@ -85,11 +87,9 @@ skip_missing_erl_bif_types(Config) ->
%% Uses erlang:display to test that erts_printf does not do deep recursion
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++"\""}]),
+ {ok, Peer, Node} = ?CT_PEER(),
true = rpc:call(Node,?MODULE,display_huge,[]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
display_huge() ->
@@ -390,6 +390,9 @@ list_to_utf8_atom(Config) when is_list(Config) ->
_ = atom_roundtrip([16#1000]),
_ = atom_roundtrip([16#10FFFF]),
atom_badarg([16#110000]),
+
+ atom_badarg([-1]),
+ [atom_badarg([(-1 bsl N) + $A]) || N <- lists:seq(8,16)],
ok.
atom_roundtrip(String) ->
@@ -777,33 +780,32 @@ erlang_halt(Config) when is_list(Config) ->
try halt(0, [{flush,true,undefined}]) of
_-> ct:fail({halt,{0,[{flush,true,undefined}]}})
catch error:badarg -> ok end,
- H = hostname(),
- {ok,N1} = slave:start(H, halt_node1),
+ {ok, _, N1} = ?CT_PEER(),
{badrpc,nodedown} = rpc:call(N1, erlang, halt, []),
- {ok,N2} = slave:start(H, halt_node2),
+ {ok, _, N2} = ?CT_PEER(),
{badrpc,nodedown} = rpc:call(N2, erlang, halt, [0]),
- {ok,N3} = slave:start(H, halt_node3),
+ {ok, _, N3} = ?CT_PEER(),
{badrpc,nodedown} = rpc:call(N3, erlang, halt, [0,[]]),
- {ok,N4} = slave:start(H, halt_node4),
+ {ok, _, N4} = ?CT_PEER(),
{badrpc,nodedown} = rpc:call(N4, erlang, halt, [lists:duplicate(300,$x)]),
%% Test unicode slogan
- {ok,N4} = slave:start(H, halt_node4),
- {badrpc,nodedown} = rpc:call(N4, erlang, halt, [[339,338,254,230,198,295,167,223,32,12507,12531,12480]]),
+ {ok, _, N5} = ?CT_PEER(),
+ {badrpc,nodedown} = rpc:call(N5, erlang, halt, [[339,338,254,230,198,295,167,223,32,12507,12531,12480]]),
% This test triggers a segfault when dumping a crash dump
% to make sure that we can handle it properly.
%% Prevent address sanitizer from catching SEGV in slave node
AsanOpts = add_asan_opt("handle_segv=0"),
- {ok,N4} = slave:start(H, halt_node4),
+ {ok, _, N6} = ?CT_PEER(),
reset_asan_opts(AsanOpts),
CrashDump = filename:join(proplists:get_value(priv_dir,Config),
"segfault_erl_crash.dump"),
- true = rpc:call(N4, os, putenv, ["ERL_CRASH_DUMP",CrashDump]),
- false = rpc:call(N4, erts_debug, set_internal_state,
+ true = rpc:call(N6, os, putenv, ["ERL_CRASH_DUMP",CrashDump]),
+ false = rpc:call(N6, erts_debug, set_internal_state,
[available_internal_state, true]),
- {badrpc,nodedown} = rpc:call(N4, erts_debug, set_internal_state,
+ {badrpc,nodedown} = rpc:call(N6, erts_debug, set_internal_state,
[broken_halt, "Validate correct crash dump"]),
{ok,_} = wait_until_stable_size(CrashDump,-1),
{ok, Bin} = file:read_file(CrashDump),
@@ -860,8 +862,7 @@ erl_crash_dump_bytes(Config) when is_list(Config) ->
ok.
do_limited_crash_dump(Config, Bytes) ->
- H = hostname(),
- {ok,N} = slave:start(H, halt_node),
+ {ok, _, N} = ?CT_PEER(),
BytesStr = integer_to_list(Bytes),
CrashDump = filename:join(proplists:get_value(priv_dir,Config),
"erl_crash." ++ BytesStr ++ ".dump"),
@@ -1110,7 +1111,7 @@ group_leader_prio_test(Dirty) ->
end,
100};
true ->
- %% These processes wont handle incoming signals by
+ %% These processes won't handle incoming signals by
%% them selves since they are stuck on dirty schedulers
%% when we try to change group leader. A dirty process
%% signal handler process (system process) will be notified
@@ -1209,6 +1210,51 @@ is_process_alive(Config) when is_list(Config) ->
Ps),
ok.
+is_process_alive_signal_from(Config) when is_list(Config) ->
+ process_flag(priority, high),
+ process_flag(scheduler, 1),
+ Schdlr = case erlang:system_info(schedulers_online) of
+ 1 -> 1;
+ _ -> 2
+ end,
+ X = is_process_alive_signal_from_test(100000, 0, Schdlr),
+ erlang:display({exits_detected, X}),
+ {comment, integer_to_list(X) ++ " exited processes detected"}.
+
+is_process_alive_signal_from_test(0, X, _Schdlr) ->
+ X;
+is_process_alive_signal_from_test(N, X, Schdlr) ->
+ Tester = self(),
+ {Testee, TMon} = spawn_opt(fun () ->
+ Mon = erlang:monitor(process, Tester),
+ Tester ! {self(), ready},
+ busy_wait_go(),
+ _ = erlang:demonitor(Mon),
+ exit(normal)
+ end,
+ [link,
+ monitor,
+ {priority, high},
+ {scheduler, Schdlr}]),
+ receive {Testee, ready} -> ok end,
+ {monitored_by, MBList1} = process_info(self(), monitored_by),
+ true = lists:member(Testee, MBList1),
+ erlang:yield(),
+ Testee ! {go, ok},
+ erlang:yield(),
+ NewX = case erlang:is_process_alive(Testee) of
+ true ->
+ X;
+ false ->
+ %% Demonitor signal should have reached us before the
+ %% is-process-alive reply...
+ {monitored_by, MBList2} = process_info(self(), monitored_by),
+ false = lists:member(Testee, MBList2),
+ X+1
+ end,
+ receive {'DOWN', TMon, process, Testee, normal} -> ok end,
+ is_process_alive_signal_from_test(N-1, NewX, Schdlr).
+
process_info_blast(Config) when is_list(Config) ->
Tester = self(),
NoAttackers = 1000,
@@ -1400,7 +1446,16 @@ external_fun_apply3(_Config) ->
ok.
%% helpers
-
+
+busy_wait_go() ->
+ receive
+ {go, Info} ->
+ Info
+ after
+ 0 ->
+ busy_wait_go()
+ end.
+
id(I) -> I.
%% Get code path, including the path for the erts application.
@@ -1432,14 +1487,6 @@ extract_abstract(Mod, Path) ->
{Mod,Abstr}.
-hostname() ->
- hostname(atom_to_list(node())).
-
-hostname([$@ | Hostname]) ->
- list_to_atom(Hostname);
-hostname([_C | Cs]) ->
- hostname(Cs).
-
tok_loop() ->
tok_loop(hej).
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 19b8a22b1e..e6b178475d 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,19 +62,21 @@
t_hash/1,
sub_bin_copy/1,
bad_size/1,
+ unsorted_map_in_map/1,
bad_term_to_binary/1,
bad_binary_to_term_2/1,safe_binary_to_term2/1,
bad_binary_to_term/1, bad_terms/1, more_bad_terms/1,
+ big_binary_to_term/1,
otp_5484/1,otp_5933/1,
ordering/1,unaligned_order/1,gc_test/1,
bit_sized_binary_sizes/1,
otp_6817/1,deep/1,
- term2bin_tuple_fallbacks/1,
robustness/1,otp_8117/1,
otp_8180/1, trapping/1, large/1,
error_after_yield/1, cmp_old_impl/1,
t2b_system_limit/1,
- term_to_iovec/1]).
+ term_to_iovec/1,
+ is_binary_test/1]).
%% Internal exports.
-export([sleeper/0,trapping_loop/4]).
@@ -93,14 +95,16 @@ all() ->
b2t_used_big, t2b_deterministic,
bad_binary_to_term_2, safe_binary_to_term2,
bad_binary_to_term, bad_terms, t_hash, bad_size,
+ big_binary_to_term,
sub_bin_copy, bad_term_to_binary, t2b_system_limit,
term_to_iovec, more_bad_terms,
+ unsorted_map_in_map,
otp_5484, otp_5933,
ordering, unaligned_order, gc_test,
bit_sized_binary_sizes, otp_6817, otp_8117, deep,
- term2bin_tuple_fallbacks,
robustness, otp_8180, trapping, large,
- error_after_yield, cmp_old_impl].
+ error_after_yield, cmp_old_impl,
+ is_binary_test].
groups() ->
[
@@ -471,10 +475,8 @@ bad_term_to_binary(Config) when is_list(Config) ->
t2b_system_limit(Config) when is_list(Config) ->
case erlang:system_info(wordsize) of
8 ->
- case proplists:get_value(system_total_memory,
- memsup:get_system_memory_data()) of
- Memory when is_integer(Memory),
- Memory > 6*1024*1024*1024 ->
+ case total_memory() of
+ Memory when is_integer(Memory), Memory > 6 ->
do_t2b_system_limit();
_ ->
{skipped, "Not enough memory on this machine"}
@@ -497,9 +499,9 @@ do_t2b_system_limit() ->
garbage_collect(),
ok
end,
- Opts = [{args, "-pa " ++ filename:dirname(code:which(?MODULE))}],
- {ok,Node} = test_server:start_node(?FUNCTION_NAME, slave, Opts),
- erpc:call(Node, F).
+ {ok, Peer, Node} = ?CT_PEER(),
+ erpc:call(Node, F),
+ peer:stop(Peer).
test_t2b_system_limit(HugeBin, Name, F1, F2) ->
io:format("Testing ~p(HugeBin)~n", [Name]),
@@ -921,10 +923,8 @@ build_iolist(N0, Base) ->
[47,L,L|Seq]
end.
-approx_4GB_bin() ->
- Bin = lists:duplicate(4194304, 255),
- BinRet = erlang:iolist_to_binary(lists:duplicate(1124, Bin)),
- BinRet.
+approx_1GB_bin() ->
+ iolist_to_binary(lists:duplicate(281, <<-1:4194304/unit:8>>)).
duplicate_iolist(IOList, 0) ->
IOList;
@@ -934,9 +934,15 @@ duplicate_iolist(IOList, NrOfTimes) ->
t_iolist_size_huge_list(Config) when is_list(Config) ->
run_when_enough_resources(
fun() ->
- {TimeToCreateIOList, IOList} = timer:tc(fun()->duplicate_iolist(approx_4GB_bin(), 32) end),
- {IOListSizeTime, CalculatedSize} = timer:tc(fun()->erlang:iolist_size(IOList) end),
- 20248183924657750016 = CalculatedSize,
+ {TimeToCreateIOList, IOList} =
+ timer:tc(fun() ->
+ duplicate_iolist(approx_1GB_bin(), 32)
+ end),
+ {IOListSizeTime, CalculatedSize} =
+ timer:tc(fun() ->
+ iolist_size(IOList)
+ end),
+ 5062045981164437504 = CalculatedSize,
{comment, io_lib:format("Time to create iolist: ~f s. Time to calculate size: ~f s.",
[TimeToCreateIOList / 1000000, IOListSizeTime / 1000000])}
end).
@@ -945,9 +951,10 @@ t_iolist_size_huge_bad_arg_list(Config) when is_list(Config) ->
run_when_enough_resources(
fun() ->
P = self(),
- spawn_link(fun()-> IOListTmp = duplicate_iolist(approx_4GB_bin(), 32),
+ spawn_link(fun() ->
+ IOListTmp = duplicate_iolist(approx_1GB_bin(), 32),
IOList = [IOListTmp, [badarg]],
- {'EXIT',{badarg,_}} = (catch erlang:iolist_size(IOList)),
+ {'EXIT',{badarg,_}} = catch iolist_size(IOList),
P ! ok
end),
receive ok -> ok end
@@ -1034,15 +1041,14 @@ report_throughput(Fun, NrOfItems) ->
total_memory() ->
%% Total memory in GB.
try
- MemoryData = memsup:get_system_memory_data(),
- case lists:keysearch(total_memory, 1, MemoryData) of
- {value, {total_memory, TM}} ->
- TM div (1024*1024*1024);
- false ->
- {value, {system_total_memory, STM}} =
- lists:keysearch(system_total_memory, 1, MemoryData),
- STM div (1024*1024*1024)
- end
+ SMD = memsup:get_system_memory_data(),
+ TM = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(
+ total_memory, SMD,
+ proplists:get_value(
+ system_total_memory, SMD))),
+ TM div (1024*1024*1024)
catch
_ : _ ->
undefined
@@ -1067,7 +1073,7 @@ run_when_enough_resources(Fun) ->
%% OTP-4053
bad_binary_to_term_2(Config) when is_list(Config) ->
- {ok, N} = test_server:start_node(plopp, slave, []),
+ {ok, Peer, N} = ?CT_PEER(),
R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]),
case R of
{badrpc, {'EXIT', _}} ->
@@ -1075,7 +1081,7 @@ bad_binary_to_term_2(Config) when is_list(Config) ->
_Other ->
ct:fail({rpcresult, R})
end,
- test_server:stop_node(N),
+ peer:stop(Peer),
ok.
%% Try bad input to binary_to_term/1.
@@ -1102,6 +1108,36 @@ bad_bin_to_term(BadBin) ->
bad_bin_to_term(BadBin,Opts) ->
{'EXIT',{badarg,_}} = (catch binary_to_term_stress(BadBin,Opts)).
+-define(MAP_EXT, 116).
+-define(SMALL_INTEGER_EXT, 97).
+-define(NIL, 106).
+-define(MAP_SMALL_MAP_LIMIT, 32).
+
+%% OTP-18343: Decode unsorted flatmap as key in hashmap
+unsorted_map_in_map(Config) when is_list(Config) ->
+ K1 = 1,
+ K2 = 2,
+ true = K1 < K2,
+ FMap = #{K1 => [], K2 => []},
+ FMapBin = <<?MAP_EXT, 2:32,
+ %% unsorted list of key/value pairs
+ ?SMALL_INTEGER_EXT, K2, ?NIL,
+ ?SMALL_INTEGER_EXT, K1, ?NIL>>,
+ FMap = binary_to_term(<<131, FMapBin/binary>>),
+
+ HKeys = lists:seq(1, ?MAP_SMALL_MAP_LIMIT+1),
+ HMap0 = maps:from_list([{K,[]} || K <- HKeys]),
+ HMap0Bin = term_to_binary(HMap0),
+
+ %% Replace last key/value pair with FMap => []
+ Prologue = binary:part(HMap0Bin, 0, byte_size(HMap0Bin)-3),
+ HMap1Bin = <<Prologue/binary, FMapBin/binary, ?NIL>>,
+ HMap1 = binary_to_term(HMap1Bin),
+
+ %% Moment of truth, can we lookup key FMap
+ [] = maps:get(FMap, HMap1),
+ ok.
+
%% Test safety options for binary_to_term/2
safe_binary_to_term2(Config) when is_list(Config) ->
bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
@@ -1116,6 +1152,23 @@ safe_binary_to_term2(Config) when is_list(Config) ->
bad_bin_to_term(BadExtFun, [safe]),
ok.
+%% OTP-18306 Decode binary/bitstring with size >= 2Gbyte
+big_binary_to_term(Config) ->
+ run_when_enough_resources(
+ fun() ->
+ Bin = binary:copy(<<0>>, 2 * 1024 * 1024 * 1024),
+ big_binary_roundtrip(Bin),
+ erlang:garbage_collect(),
+ <<_:1, BitStr/bits>> = Bin,
+ big_binary_roundtrip(BitStr),
+ ok
+ end).
+
+big_binary_roundtrip(Bin) ->
+ Bin = erlang:binary_to_term(erlang:term_to_binary(Bin)),
+ ok.
+
+
%% Tests bad input to binary_to_term/1.
bad_terms(Config) when is_list(Config) ->
@@ -1547,11 +1600,14 @@ test_terms(Test_Func) ->
Test_Func("abcdef"),
Test_Func([a, b, 1, 2]),
Test_Func([a|b]),
+ Test_Func([make_port(), make_ref(), make_pid(), fun() -> ok end,
+ Very_Big | lists:seq(1, 75)]),
Test_Func({}),
Test_Func({1}),
Test_Func({a, b}),
Test_Func({a, b, c}),
+ Test_Func({make_port(), make_ref(), make_pid(), fun() -> ok end}),
Test_Func(list_to_tuple(lists:seq(0, 255))),
Test_Func(list_to_tuple(lists:seq(0, 256))),
@@ -1602,9 +1658,11 @@ test_terms(Test_Func) ->
Test_Func(<<42:10>>),
Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
+ %% Funs in a list.
Test_Func(F = fun(A) -> 42*A end),
Test_Func(lists:duplicate(32, F)),
+ %% External funs in a list.
Test_Func(FF = fun binary_SUITE:all/0),
Test_Func(lists:duplicate(32, FF)),
@@ -1745,29 +1803,6 @@ deep_roundtrip(T) ->
B = term_to_binary(T),
T = binary_to_term(B).
-term2bin_tuple_fallbacks(Config) when is_list(Config) ->
- erts_debug:set_internal_state(available_internal_state, true),
-
- term2bin_tf(fun ?MODULE:all/1),
- term2bin_tf(<<1:1>>),
- term2bin_tf(<<90,80:7>>),
-
- erts_debug:set_internal_state(available_internal_state, false),
- ok.
-
-term2bin_tf(Term) ->
- Tuple = case Term of
- Fun when is_function(Fun) ->
- {type, external} = erlang:fun_info(Fun, type),
- {module,M} = erlang:fun_info(Fun, module),
- {name,F} = erlang:fun_info(Fun, name),
- {M,F};
- BS when bit_size(BS) rem 8 =/= 0 ->
- Bits = bit_size(BS) rem 8,
- {<<BS/bitstring, 0:(8-Bits)>>, Bits}
- end,
- Tuple = binary_to_term_stress(erts_debug:get_internal_state({term_to_binary_tuple_fallbacks,Term})).
-
%% Test non-standard encodings never generated by term_to_binary/1
%% but recognized by binary_to_term/1.
@@ -1976,18 +2011,11 @@ cmp_old_impl(Config) when is_list(Config) ->
%% implementation in R16B. Since OTP 22 we can't talk distribution with such
%% old nodes (< 19). The test case it kept but compares with previous major
%% version for semantic regression test.
- Cookie = atom_to_list(erlang:get_cookie()),
- Rel = (integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 1)
- ++ "_latest"),
- case test_server:is_release_available(Rel) of
- false ->
+ Rel = integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 1),
+ case ?CT_PEER_REL([], Rel, proplists:get_value(priv_dir, Config)) of
+ not_available ->
{skipped, "No OTP "++Rel++" available"};
- true ->
- {ok, Node} = test_server:start_node(list_to_atom(atom_to_list(?MODULE)++"_"++Rel),
- peer,
- [{args, " -setcookie "++Cookie},
- {erl, [{release, Rel}]}]),
-
+ {ok, Peer, Node} ->
cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1))]}),
cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10))]}),
cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(100))]}),
@@ -2025,7 +2053,7 @@ cmp_old_impl(Config) when is_list(Config) ->
cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1000000)))]}),
cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10000000)))]}),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok
end.
@@ -2065,6 +2093,28 @@ echo(Papa) ->
receive M -> Papa ! M end,
echo(Papa).
+%% GH-6239.
+is_binary_test(_Config) ->
+ <<"foo42">> = concat_stuff(foo, 42),
+ <<"foo2749963626218098647">> = concat_stuff(foo, 2749963626218098647), %Bignum.
+ <<"foobar">> = concat_stuff(foo, <<"bar">>),
+ <<"bar100">> = concat_stuff(<<"bar">>, 100),
+ <<"bar2749963626218098647">> = concat_stuff(<<"bar">>, 2749963626218098647), %Bignum.
+ <<"barfood">> = concat_stuff(<<"bar">>, <<"food">>),
+
+ ok.
+
+concat_stuff(A, B) when is_integer(B); is_binary(B) ->
+ <<(case A of
+ X when is_binary(X) -> X;
+ _ -> atom_to_binary(A)
+ end)/binary,
+ (case B of
+ %% The JIT would do an unsafe simplification of the is_binary/1 test,
+ %% accepting any boxed term (such as a bignum) as a binary.
+ Y when is_binary(Y) -> Y;
+ _ -> integer_to_binary(B)
+ end)/binary>>.
%% Utilities.
diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl
index 77716f85b5..dfb38fc8ed 100644
--- a/erts/emulator/test/bs_construct_SUITE.erl
+++ b/erts/emulator/test/bs_construct_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,8 @@
huge_float_field/1, system_limit/1, badarg/1,
copy_writable_binary/1, kostis/1, dynamic/1, bs_add/1,
otp_7422/1, zero_width/1, bad_append/1, bs_append_overflow/1,
- reductions/1, fp16/1]).
+ bs_append_offheap/1,
+ reductions/1, fp16/1, error_info/1]).
-include_lib("common_test/include/ct.hrl").
@@ -41,7 +42,8 @@ all() ->
in_guard, mem_leak, coerce_to_float, bjorn, append_empty_is_same,
huge_float_field, system_limit, badarg,
copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width,
- bad_append, bs_append_overflow, reductions, fp16].
+ bad_append, bs_append_overflow, bs_append_offheap,
+ reductions, fp16, error_info].
init_per_suite(Config) ->
Config.
@@ -927,6 +929,29 @@ bs_append_overflow_unsigned() ->
C = <<A/binary,1,B/binary>>,
true = byte_size(B) < byte_size(C).
+bs_append_offheap(Config) when is_list(Config) ->
+ %% test that erts_bs_private_append is reflected correctly in
+ %% process_info(Pid, binary()) report for off-heap binaries.
+ {Pid, MRef} = erlang:spawn_monitor(fun bs_append_offheap_proc/0),
+ receive
+ {'DOWN', MRef, process, Pid, normal} ->
+ ok;
+ {'DOWN', MRef, process, Pid, {{badmatch,[{binary,[]}]}, _}} ->
+ {fail, "missing binary in erts_bs_private_append"}
+ end.
+
+bs_append_offheap_proc() ->
+ Self = self(),
+ Len = 128,
+ OffHeapBin = list_to_binary(lists:duplicate(Len, $b)),
+ erlang:garbage_collect(Self),
+ [{binary, [{_, Len, 1}]}] = erlang:process_info(Self, [binary]),
+ Bin = <<OffHeapBin/binary, "a">>,
+ erlang:garbage_collect(Self),
+ %% expect a single binary (2 bytes longer than the original)
+ [{binary, [{_, _, 1}]}] = erlang:process_info(Self, [binary]),
+ Bin.
+
reductions(_Config) ->
TwoMeg = <<0:(2_000*1024)/unit:8>>,
reds_at_least(2000, fun() -> <<0:8,TwoMeg/binary>> end),
@@ -953,13 +978,15 @@ reds_at_least(N, Fun) ->
Diff ->
ct:fail({expected,N,got,Diff})
end.
-
-id(I) -> I.
-
memsize() ->
application:ensure_all_started(os_mon),
- {Tot,_Used,_} = memsup:get_memory_data(),
- Tot.
+ case proplists:get_value(available_memory, memsup:get_system_memory_data()) of
+ undefined ->
+ {Tot,_Used,_} = memsup:get_memory_data(),
+ Tot;
+ Available ->
+ Available
+ end.
-define(FP16(EncodedInt, Float),
(fun(NlInt, NlFloat) ->
@@ -1002,3 +1029,148 @@ fp16(_Config) ->
?FP16(16#4000, 2),
?FP16(16#4000, 2.0),
ok.
+
+-define(ERROR_INFO(Expr),
+ fun() ->
+ try Expr of
+ _ ->
+ error(should_fail)
+ catch
+ error:Reason:Stk ->
+ error_info_verify(Reason, Stk, ??Expr, #{})
+ end
+ end()).
+
+-define(ERROR_INFO(Expr, Overrides),
+ fun() ->
+ try Expr of
+ _ ->
+ error(should_fail)
+ catch
+ error:Reason:Stk ->
+ error_info_verify(Reason, Stk, ??Expr, Overrides)
+ end
+ end()).
+
+error_info(_Config) ->
+ Atom = id(some_atom),
+ NegSize = id(-1),
+ HugeNegSize = id(-1 bsl 64),
+ Binary = id(<<"abc">>),
+ HugeBig = id(1 bsl 1500),
+ LongList = lists:seq(1, 100),
+
+ {badarg, {1,binary,type,Atom}, _} = ?ERROR_INFO(<<Atom/binary, Binary/binary>>),
+ {badarg, {2,binary,type,Atom}, _} = ?ERROR_INFO(<<Binary/binary, Atom/binary>>),
+ {badarg, {3,binary,type,Atom}, _} = ?ERROR_INFO(<<1:32, Binary/binary, Atom/binary>>),
+ {badarg, {4,binary,type,Atom}, _} = ?ERROR_INFO(<<1:32, "xyz", Binary/binary, Atom/binary>>),
+
+ {badarg, {1,integer,type,Atom}, _} = ?ERROR_INFO(<<Atom:32>>),
+ {badarg, {1,integer,type,Atom}, _} = ?ERROR_INFO(<<Atom:(id(32))>>),
+ {badarg, {1,integer,type,LongList}, _} = ?ERROR_INFO(<<LongList:32>>),
+ {badarg, {1,integer,size,Atom}, _} = ?ERROR_INFO(<<42:Atom>>),
+ {badarg, {1,integer,type,Atom}, _} = ?ERROR_INFO(<<Atom:32>>),
+ {badarg, {1,integer,size,NegSize}, _} = ?ERROR_INFO(<<42:NegSize>>),
+ {badarg, {1,integer,size,HugeNegSize}, _} = ?ERROR_INFO(<<42:HugeNegSize>>),
+ {system_limit, {1,integer,size,1 bsl 58}, _} = ?ERROR_INFO(<<42:(1 bsl 58)/unit:255>>),
+ {system_limit, {1,integer,size,1 bsl 60}, _} = ?ERROR_INFO(<<42:(1 bsl 60)/unit:8>>),
+ {system_limit, {1,integer,size,1 bsl 64}, _} = ?ERROR_INFO(<<42:(1 bsl 64)>>),
+
+ {badarg, {1,binary,type,Atom}, _} = ?ERROR_INFO(<<Atom:10/binary>>),
+ {badarg, {1,binary,type,Atom}, _} = ?ERROR_INFO(<<Atom:(id(10))/binary>>),
+ {badarg, {1,binary,size,Atom}, _} = ?ERROR_INFO(<<Binary:Atom/binary>>),
+ {badarg, {1,binary,size,NegSize}, _} = ?ERROR_INFO(<<Binary:NegSize/binary>>),
+ {badarg, {1,binary,size,HugeNegSize}, _} = ?ERROR_INFO(<<Binary:HugeNegSize/binary>>),
+ {badarg, {1,binary,short,Binary}, _} = ?ERROR_INFO(<<Binary:10/binary>>),
+ {badarg, {1,binary,short,Binary}, _} = ?ERROR_INFO(<<Binary:(id(10))/binary>>),
+ {badarg, {1,binary,type,Atom}, _} = ?ERROR_INFO(<<Atom/binary>>),
+ {badarg, {1,binary,unit,<<1:1>>}, _} = ?ERROR_INFO(<<(id(<<1:1>>))/binary>>),
+ {badarg, {1,binary,unit,<<0:1111>>}, _} = ?ERROR_INFO(<<(id(<<0:1111>>))/binary>>),
+ {badarg, {2,binary,unit,<<1:1>>}, _} = ?ERROR_INFO(<<0, (id(<<1:1>>))/binary>>),
+ {badarg, {2,binary,unit,<<0:1111>>}, _} = ?ERROR_INFO(<<0, (id(<<0:1111>>))/binary>>),
+ {system_limit, {1,binary,size,1 bsl 64}, _} = ?ERROR_INFO(<<Binary:(1 bsl 64)/binary>>),
+ {system_limit, {1,binary,size,1 bsl 64}, _} = ?ERROR_INFO(<<Binary:(id(1 bsl 64))/binary>>),
+
+ {badarg, {1,float,type,Atom}, _} = ?ERROR_INFO(<<Atom:64/float>>),
+ {badarg, {1,float,size,Atom}, _} = ?ERROR_INFO(<<Atom:Atom/float>>),
+ {badarg, {1,float,size,NegSize}, _} = ?ERROR_INFO(<<42.0:NegSize/float>>),
+ {badarg, {1,float,size,HugeNegSize}, _} = ?ERROR_INFO(<<42.0:HugeNegSize/float>>),
+ {badarg, {1,float,invalid,1}, _} = ?ERROR_INFO(<<42.0:(id(1))/float>>),
+ {badarg, {1,float,no_float,HugeBig}, _} = ?ERROR_INFO(<<HugeBig:(id(64))/float>>),
+ {badarg, {1,float,no_float,HugeBig}, _} = ?ERROR_INFO(<<HugeBig:64/float>>),
+ {system_limit, {1,float,size,1 bsl 64}, _} = ?ERROR_INFO(<<42.0:(id(1 bsl 64))/float>>),
+
+ {badarg, {1,utf8,type,Atom}, _} = ?ERROR_INFO(<<Atom/utf8>>),
+ {badarg, {1,utf16,type,Atom}, _} = ?ERROR_INFO(<<Atom/utf16>>),
+ {badarg, {1,utf32,type,Atom}, _} = ?ERROR_INFO(<<Atom/utf32>>),
+
+ Bin = id(<<>>),
+ Float = id(42.0),
+ MaxSmall = (1 bsl 59) - 1, %Max small for 64-bit architectures.
+
+ %% Attempt constructing a binary with total size 1^64 + 32.
+
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(MaxSmall)/unit:32,0:64>>),
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(MaxSmall)/unit:32,(id(0)):64>>),
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(id(MaxSmall))/unit:32,0:64>>),
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(id(MaxSmall))/unit:32,(id(0)):64>>),
+
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(MaxSmall)/binary-unit:32,0:64>>),
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(MaxSmall)/binary-unit:32,(id(0)):64>>),
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(id(MaxSmall))/binary-unit:32,0:64>>),
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(id(MaxSmall))/binary-unit:32,(id(0)):64>>),
+
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(MaxSmall)/float-unit:32,0:64>>),
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(MaxSmall)/float-unit:32,(id(0)):64>>),
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(id(MaxSmall))/float-unit:32,0:64>>),
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(id(MaxSmall))/float-unit:32,(id(0)):64>>),
+
+ %% Test a size exceeding 1^64, where the sign bit (bit 63) is not set.
+ 0 = (((MaxSmall) * 33) bsr 63) band 1, %Assertion: The sign bit is not set.
+
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(MaxSmall)/unit:33>>),
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(MaxSmall)/unit:33>>),
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(id(MaxSmall))/unit:33>>),
+ {system_limit, {1,integer,size,MaxSmall}, _} = ?ERROR_INFO(<<0:(id(MaxSmall))/unit:33>>),
+
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(MaxSmall)/binary-unit:33>>),
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(MaxSmall)/binary-unit:33>>),
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(id(MaxSmall))/binary-unit:33>>),
+ {system_limit, {1,binary,size,MaxSmall}, _} = ?ERROR_INFO(<<Bin:(id(MaxSmall))/binary-unit:33>>),
+
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(MaxSmall)/float-unit:33>>),
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(MaxSmall)/float-unit:33>>),
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(id(MaxSmall))/float-unit:33>>),
+ {system_limit, {1,float,size,MaxSmall}, _} = ?ERROR_INFO(<<Float:(id(MaxSmall))/float-unit:33>>),
+
+ %% error messages with options
+ PP = fun(Term) -> <<"'", (erlang:atom_to_binary(Term))/binary, "'">> end,
+
+ {_, _, <<"segment 1 of type 'float': expected a float or an integer but got: some_atom">>} =
+ ?ERROR_INFO(<<Atom:64/float>>, #{}),
+
+ {_, _, <<"segment 2 of type 'float': expected a float or an integer but got: some_atom">>} =
+ ?ERROR_INFO(<<Atom:64/float>>, #{override_segment_position => 2}),
+
+ {_, _, <<"segment 1 of type 'float': expected a float or an integer but got: 'some_atom'">>} =
+ ?ERROR_INFO(<<Atom:64/float>>, #{pretty_printer => PP}),
+
+ ok.
+
+error_info_verify(Reason, Stk0, Expr, Overrides) ->
+ [{?MODULE, Fun, Arity, Info0}|Rest] = Stk0,
+ {value, {error_info, ErrorInfo}, Info1} = lists:keytake(error_info, 1, Info0),
+ #{cause := Cause, module := Module, function := Function} = ErrorInfo,
+ Info2 = maps:merge(ErrorInfo, Overrides),
+ Stk1 = [{?MODULE, Fun, Arity, Info1 ++ [{error_info, Info2}]} | Rest],
+ Result = Module:Function(Reason, Stk1),
+ #{general := String} = Result,
+ true = is_binary(String),
+ io:format("~ts: ~ts\n", [Expr,String]),
+ {Reason, Cause, String}.
+
+%%%
+%%% Common utilities.
+%%%
+
+id(I) -> I.
diff --git a/erts/emulator/test/bs_match_bin_SUITE.erl b/erts/emulator/test/bs_match_bin_SUITE.erl
index f5c996ae9e..a7f5ad2d6b 100644
--- a/erts/emulator/test/bs_match_bin_SUITE.erl
+++ b/erts/emulator/test/bs_match_bin_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,15 +21,17 @@
-module(bs_match_bin_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]).
+ init_per_group/2,end_per_group/2,
+ byte_split_binary/1,bit_split_binary/1,match_huge_bin/1,
+ bs_match_string_edge_case/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [byte_split_binary, bit_split_binary, match_huge_bin].
+ [byte_split_binary, bit_split_binary, match_huge_bin,
+ bs_match_string_edge_case].
groups() ->
[].
@@ -214,3 +216,22 @@ overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) ->
overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62
overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63
overflow_huge_bin_64(_) -> nomatch.
+
+-define(MATCH512,
+ " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17"
+ " 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32"
+ " 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49"
+ " 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64"
+ " 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81"
+ " 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96"
+ " 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113"
+ " 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128").
+
+%% GH-5871: bs_match_string broke when matching more than 4095 bits (max for a
+%% 12-bit immediate) on ARM.
+bs_match_string_edge_case(_Config) ->
+ Bin = id(<<?MATCH512, " 129 130 131 132 133 134 135 136 137 138">>),
+ <<?MATCH512, Tail0/binary>> = Bin,
+ <<?MATCH512, " ", Tail1/binary>> = Bin,
+ <<" ", Tail1/binary>> = id(Tail0),
+ ok.
diff --git a/erts/emulator/test/bs_match_int_SUITE.erl b/erts/emulator/test/bs_match_int_SUITE.erl
index 0268ba18c8..08b0a72785 100644
--- a/erts/emulator/test/bs_match_int_SUITE.erl
+++ b/erts/emulator/test/bs_match_int_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -275,7 +275,13 @@ match_huge_int(Config) when is_list(Config) ->
4 -> lists:seq(25, 32);
8 -> []
end ++ lists:seq(50, 64),
- ok = overflow_huge_int_unit128(Bin, Sizes)
+ ok = overflow_huge_int_unit128(Bin, Sizes),
+
+ %% GH-6701: [vm] crash with -emu_flavor emu:
+ %% "no next heap size found: 18446744072702918678, offset 0"
+ {'EXIT',{function_clause,_}} =
+ (catch fun(<<X:2147483647/unit:98>>) -> X end(<<>>)),
+ ok
end.
overflow_huge_int_unit128(Bin, [Sz0|Sizes]) ->
diff --git a/erts/emulator/test/bs_match_tail_SUITE.erl b/erts/emulator/test/bs_match_tail_SUITE.erl
index cbebc554c7..7aa4c5efbc 100644
--- a/erts/emulator/test/bs_match_tail_SUITE.erl
+++ b/erts/emulator/test/bs_match_tail_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,14 +22,14 @@
-author('bjorn@erix.ericsson.se').
-export([all/0, suite/0,
- aligned/1,unaligned/1,zero_tail/1]).
+ aligned/1,unaligned/1,zero_tail/1,huge_tail/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [aligned, unaligned, zero_tail].
+ [aligned, unaligned, zero_tail, huge_tail].
%% Test aligned tails.
@@ -86,4 +86,39 @@ test_zero_tail(<<A:8>>) -> A.
test_zero_tail2(<<_A:4,_B:4>>) -> ok.
-mkbin(L) when is_list(L) -> list_to_binary(L).
+huge_tail(_Config) ->
+ 42 = huge_tail_1(id(<<42,0:16#1001>>)),
+ {'EXIT',{function_clause,_}} = catch huge_tail_1(id(<<0:8,0:10>>)),
+
+ {'EXIT',{function_clause,_}} = catch huge_tail_2(id(<<0:8,0:100>>)),
+
+ {'EXIT',{function_clause,_}} = catch huge_tail_3(id(<<0:8,0:200>>)),
+
+ %% The following code is commented out by default because it
+ %% constructs a 2Gb binary.
+
+ %% try huge_tail_2(id(<<100, 0:16#8000_0000>>)) of
+ %% 100 ->
+ %% ok
+ %% catch
+ %% error:function_clause ->
+ %% ct:fail(not_supposed_to_fail)
+ %% end,
+
+ ok.
+
+%% On AArch64, the immediate for the `cmp` instruction is 12 bits (unsigned).
+huge_tail_1(<<B:8,_:16#1001>>) -> B.
+
+%% On x86_64, the immediate for the `cmp` instruction is 32 bits (signed).
+huge_tail_2(<<B:8, _:16#8000_0000>>) -> B.
+
+%% Matching will fail on all platforms.
+huge_tail_3(<<B:8, _:16#1_0000_0000_0000_0000>>) -> B.
+
+%%%
+%%% Common utilities.
+%%%
+mkbin(L) when is_list(L) -> list_to_binary(id(L)).
+
+id(I) -> I.
diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl
index a90a2d13c7..c1f576276f 100644
--- a/erts/emulator/test/busy_port_SUITE.erl
+++ b/erts/emulator/test/busy_port_SUITE.erl
@@ -255,7 +255,7 @@ no_trap_exit(Config) when is_list(Config) ->
Pid = fun_spawn(fun no_trap_exit_process/3, [self(), linked, Config]),
receive
{Pid, port_created, Port} ->
- io:format("Process ~w created port ~w", [Pid, Port]),
+ ct:log("Process ~w created port ~w", [Pid, Port]),
exit(Port, die);
Other1 ->
ct:fail({unexpected_message, Other1})
@@ -278,7 +278,7 @@ no_trap_exit_unlinked(Config) when is_list(Config) ->
[self(), unlink, Config]),
receive
{Pid, port_created, Port} ->
- io:format("Process ~w created port ~w", [Pid, Port]),
+ ct:log("Process ~w created port ~w", [Pid, Port]),
exit(Port, die);
Other1 ->
ct:fail({unexpected_message, Other1})
@@ -320,7 +320,7 @@ trap_exit(Config) when is_list(Config) ->
Pid = fun_spawn(fun busy_port_exit_process/2, [self(), Config]),
receive
{Pid, port_created, Port} ->
- io:format("Process ~w created port ~w", [Pid, Port]),
+ ct:log("Process ~w created port ~w", [Pid, Port]),
unlink(Pid),
{status, suspended} = process_info(Pid, status),
exit(Port, die);
@@ -755,7 +755,7 @@ run_command(_M,spawn,{Args,Opts}) ->
run_command(M,spawn,Args) ->
run_command(M,spawn,{Args,[]});
run_command(Mod,Func,Args) ->
- erlang:display({{Mod,Func,Args}, erlang:system_time(microsecond)}),
+ %% erlang:display({{Mod,Func,Args}, erlang:system_time(microsecond)}),
apply(Mod,Func,Args).
validate_scenario(Data,[{print,Var}|T]) ->
@@ -869,7 +869,7 @@ chk_not_value(_, _) ->
wait_for([]) ->
ok;
wait_for(Pids) ->
- io:format("Waiting for ~p", [Pids]),
+ ct:log("Waiting for ~p", [Pids]),
receive
{'EXIT', Pid, normal} ->
wait_for(lists:delete(Pid, Pids));
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index 95b836219e..020065f6d8 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -746,11 +746,11 @@ verify_lit_terms([], _) ->
ok.
get_external_terms() ->
- {ok,Node} = test_server:start_node(?FUNCTION_NAME, slave, []),
+ {ok, Peer, Node}= ?CT_PEER(),
Ref = rpc:call(Node, erlang, make_ref, []),
Ports = rpc:call(Node, erlang, ports, []),
Pid = rpc:call(Node, erlang, self, []),
- _ = test_server:stop_node(Node),
+ peer:stop(Peer),
{Ref,hd(Ports),Pid}.
%% OTP-7559: c_p->cp could contain garbage and create a false dependency
@@ -1096,9 +1096,9 @@ erl_544(Config) when is_list(Config) ->
File = proplists:get_value(file, Info2),
StackFun = fun(_, _, _) -> false end,
FormatFun = fun (Term, _) -> io_lib:format("~tp", [Term]) end,
- Formated =
+ Formatted =
erl_error:format_stacktrace(1, Stack, StackFun, FormatFun),
- true = is_list(Formated),
+ true = is_list(Formatted),
ok
after
ok = file:set_cwd(CWD)
diff --git a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl
index 6d74b63863..5ed5214c94 100644
--- a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl
+++ b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl
@@ -41,6 +41,19 @@ do_it(Priv, Data, Type, Opts) ->
false
end,
+ %% fun_info/1,2 must behave as documented on purged funs.
+ FunInfoBefore = fun(F) ->
+ {module, my_code_test2} = erlang:fun_info(F, module),
+ {name, []} = erlang:fun_info(F, name),
+ {arity, 1} = erlang:fun_info(F, arity)
+ end,
+ FunInfoAfter = fun(F) ->
+ {module, my_code_test2} = erlang:fun_info(F, module),
+ {name, Name} = erlang:fun_info(F, name),
+ true = is_atom(Name),
+ {arity, 1} = erlang:fun_info(F, arity)
+ end,
+
true = erlang:delete_module(my_code_test2),
ok = receive {P0, "going to sleep"} -> ok
@@ -51,7 +64,9 @@ do_it(Priv, Data, Type, Opts) ->
{P1, M1} = spawn_monitor(fun () ->
[{my_fun,F}] = ets:lookup(T, my_fun),
+ FunInfoBefore(F),
4712 = F(1),
+ FunInfoAfter(F),
exit(completed)
end),
@@ -64,14 +79,18 @@ do_it(Priv, Data, Type, Opts) ->
{P2, M2} = spawn_monitor(fun () ->
[{my_fun,F}] = ets:lookup(T, my_fun),
+ FunInfoBefore(F),
4713 = F(2),
+ FunInfoAfter(F),
exit(completed)
- end),
+ end),
{P3, M3} = spawn_monitor(fun () ->
- [{my_fun,F}] = ets:lookup(T, my_fun),
- 4714 = F(3),
- exit(completed)
- end),
+ [{my_fun,F}] = ets:lookup(T, my_fun),
+ FunInfoBefore(F),
+ 4714 = F(3),
+ FunInfoAfter(F),
+ exit(completed)
+ end),
ok = wait_until(fun () ->
{status, suspended}
diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl
index bedcaf3a08..07653646a2 100644
--- a/erts/emulator/test/decode_packet_SUITE.erl
+++ b/erts/emulator/test/decode_packet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -174,11 +174,7 @@ pack(fcgi,Bin) ->
PaddSz = rand:uniform(16) - 1,
Psz = byte_size(Bin),
Reserv = rand:uniform(256) - 1,
- Padd = case PaddSz of
- 0 -> <<>>;
- _ -> list_to_binary([rand:uniform(256)-1
- || _<- lists:seq(1,PaddSz)])
- end,
+ Padd = rand:bytes(PaddSz),
Res = <<Ver:8,Type:8,Id:16,Psz:16/big,PaddSz:8,Reserv:8,Bin/binary>>,
{<<Res/binary,Padd/binary>>, Res};
pack(tpkt,Bin) ->
diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl
index f8819b4793..efb31f8471 100644
--- a/erts/emulator/test/dirty_bif_SUITE.erl
+++ b/erts/emulator/test/dirty_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -82,8 +82,8 @@ end_per_suite(_Config) ->
init_per_testcase(Case, Config) ->
[{testcase, Case} | Config].
-end_per_testcase(_Case, _Config) ->
- ok.
+end_per_testcase(_Case, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
dirty_bif(Config) when is_list(Config) ->
dirty_cpu = erts_debug:dirty_cpu(scheduler,type),
@@ -216,7 +216,7 @@ dirty_bif_multischedule_exception(Config) when is_list(Config) ->
end.
dirty_scheduler_exit(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config, "+SDio 1"),
+ {ok, Peer, Node} = ?CT_PEER(["+SDio", "1"]),
[ok] = mcall(Node,
[fun() ->
%% Perform a dry run to ensure that all required code
@@ -230,7 +230,7 @@ dirty_scheduler_exit(Config) when is_list(Config) ->
io:format("Time=~p ms~n", [End-Start]),
ok
end]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
test_dirty_scheduler_exit() ->
@@ -289,7 +289,7 @@ dirty_call_while_terminated(Config) when is_list(Config) ->
undefined = process_info(Dirty, status),
false = erlang:is_process_alive(Dirty),
false = lists:member(Dirty, processes()),
- %% Binary still refered by Dirty process not yet cleaned up
+ %% Binary still referred by Dirty process not yet cleaned up
%% since the dirty bif has not yet returned...
{value, {BinAddr, 4711, 2}} = lists:keysearch(4711, 2,
element(2,
@@ -315,7 +315,7 @@ dirty_call_while_terminated(Config) when is_list(Config) ->
end.
dirty_heap_access(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
Me = self(),
RGL = rpc:call(Node,erlang,whereis,[init]),
Ref = rpc:call(Node,erlang,make_ref,[]),
@@ -333,7 +333,7 @@ dirty_heap_access(Config) when is_list(Config) ->
end,
unlink(Dirty),
exit(Dirty, kill),
- stop_node(Node),
+ peer:stop(Peer),
{comment, integer_to_list(N) ++ " GL change loops; "
++ integer_to_list(R) ++ " while running dirty"}.
@@ -369,7 +369,7 @@ access_dirty_heap(Dirty, RGL, N, R) ->
%% the dirty process is still alive immediately after accessing it.
dirty_process_info(Config) when is_list(Config) ->
access_dirty_process(
- Config,
+ ?FUNCTION_NAME,
fun() -> ok end,
fun(BifPid) ->
PI = process_info(BifPid),
@@ -381,7 +381,7 @@ dirty_process_info(Config) when is_list(Config) ->
dirty_process_register(Config) when is_list(Config) ->
access_dirty_process(
- Config,
+ ?FUNCTION_NAME,
fun() -> ok end,
fun(BifPid) ->
register(test_dirty_process_register, BifPid),
@@ -395,7 +395,7 @@ dirty_process_register(Config) when is_list(Config) ->
dirty_process_trace(Config) when is_list(Config) ->
access_dirty_process(
- Config,
+ ?FUNCTION_NAME,
fun() ->
%% BIFs can only be traced when their modules are loaded.
code:ensure_loaded(erts_debug),
@@ -554,13 +554,13 @@ wait_until(Fun) ->
wait_until(Fun)
end.
-access_dirty_process(Config, Start, Test, Finish) ->
- {ok, Node} = start_node(Config, ""),
+access_dirty_process(TestCase, Start, Test, Finish) ->
+ {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(TestCase)}),
[ok] = mcall(Node,
[fun() ->
ok = test_dirty_process_access(Start, Test, Finish)
end]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
test_dirty_process_access(Start, Test, Finish) ->
@@ -586,23 +586,6 @@ test_dirty_process_access(Start, Test, Finish) ->
end,
ok = Finish(BifPid).
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
mcall(Node, Funs) ->
Parent = self(),
Refs = lists:map(fun (Fun) ->
diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl
index 9e6cbab387..59d791eb2b 100644
--- a/erts/emulator/test/dirty_nif_SUITE.erl
+++ b/erts/emulator/test/dirty_nif_SUITE.erl
@@ -144,7 +144,7 @@ nif_raise_exceptions(NifFunc) ->
end, ok, ExcTerms).
dirty_scheduler_exit(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config, "+SDio 1"),
+ {ok, Peer, Node} = ?CT_PEER(["+SDio", "1"]),
Path = proplists:get_value(data_dir, Config),
NifLib = filename:join(Path, atom_to_list(?MODULE)),
[ok] = mcall(Node,
@@ -161,7 +161,7 @@ dirty_scheduler_exit(Config) when is_list(Config) ->
io:format("Time=~p ms~n", [End-Start]),
ok
end]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
test_dirty_scheduler_exit() ->
@@ -249,7 +249,7 @@ dirty_call_while_terminated(Config) when is_list(Config) ->
end.
dirty_heap_access(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
Me = self(),
RGL = rpc:call(Node,erlang,whereis,[init]),
Ref = rpc:call(Node,erlang,make_ref,[]),
@@ -267,7 +267,7 @@ dirty_heap_access(Config) when is_list(Config) ->
end,
unlink(Dirty),
exit(Dirty, kill),
- stop_node(Node),
+ peer:stop(Peer),
{comment, integer_to_list(N) ++ " GL change loops; "
++ integer_to_list(R) ++ " while running dirty"}.
@@ -303,7 +303,8 @@ access_dirty_heap(Dirty, RGL, N, R) ->
%% the dirty process is still alive immediately after accessing it.
dirty_process_info(Config) when is_list(Config) ->
access_dirty_process(
- Config,
+ ?FUNCTION_NAME,
+ ?config(data_dir, Config),
fun() -> ok end,
fun(NifPid) ->
PI = process_info(NifPid),
@@ -315,7 +316,8 @@ dirty_process_info(Config) when is_list(Config) ->
dirty_process_register(Config) when is_list(Config) ->
access_dirty_process(
- Config,
+ ?FUNCTION_NAME,
+ ?config(data_dir, Config),
fun() -> ok end,
fun(NifPid) ->
register(test_dirty_process_register, NifPid),
@@ -329,7 +331,8 @@ dirty_process_register(Config) when is_list(Config) ->
dirty_process_trace(Config) when is_list(Config) ->
access_dirty_process(
- Config,
+ ?FUNCTION_NAME,
+ ?config(data_dir, Config),
fun() ->
erlang:trace_pattern({?MODULE,dirty_sleeper,1},
[{'_',[],[{return_trace}]}],
@@ -537,16 +540,15 @@ literal_area(Config) when is_list(Config) ->
%% Internal...
%%
-access_dirty_process(Config, Start, Test, Finish) ->
- {ok, Node} = start_node(Config, ""),
+access_dirty_process(TestCase, Path, Start, Test, Finish) ->
+ {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(TestCase)}),
[ok] = mcall(Node,
[fun() ->
- Path = ?config(data_dir, Config),
Lib = atom_to_list(?MODULE),
ok = erlang:load_nif(filename:join(Path,Lib), []),
ok = test_dirty_process_access(Start, Test, Finish)
end]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
test_dirty_process_access(Start, Test, Finish) ->
@@ -575,23 +577,6 @@ test_dirty_process_access(Start, Test, Finish) ->
receive_any() ->
receive M -> M end.
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
mcall(Node, Funs) ->
Parent = self(),
Refs = lists:map(fun (Fun) ->
@@ -659,7 +644,7 @@ nif_whereis(Config) when is_list(Config) ->
nif_whereis_parallel(Config) when is_list(Config) ->
- %% try to be at least a little asymetric
+ %% try to be at least a little asymmetric
NProcs = trunc(3.5 * erlang:system_info(schedulers)),
NSeq = lists:seq(1, NProcs),
Names = [list_to_atom("dirty_nif_whereis_proc_" ++ integer_to_list(N))
diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl
index 23a6018e69..c1a31c6abf 100644
--- a/erts/emulator/test/distribution_SUITE.erl
+++ b/erts/emulator/test/distribution_SUITE.erl
@@ -30,18 +30,19 @@
-define(ATOM_UTF8_EXT, 118).
-define(SMALL_ATOM_UTF8_EXT, 119).
+-define(DFLAG_EXPORT_PTR_TAG, 16#200).
+-define(DFLAG_BIT_BINARIES, 16#400).
+
%% Tests distribution and the tcp driver.
-include_lib("common_test/include/ct.hrl").
-%-define(Line, erlang:display({line,?LINE}),).
--define(Line,).
-
-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,
ping/1, bulk_send_small/1,
- group_leader/1,
+ group_leader/1, nodes2/1,
optimistic_dflags/1,
bulk_send_big/1, bulk_send_bigbig/1,
local_send_small/1, local_send_big/1,
@@ -77,13 +78,19 @@
system_limit/1,
hopefull_data_encoding/1,
hopefull_export_fun_bug/1,
- huge_iovec/1]).
+ huge_iovec/1,
+ is_alive/1,
+ dyn_node_name_monitor_node/1,
+ dyn_node_name_monitor/1,
+ async_dist_flag/1,
+ async_dist_port_dctrlr/1,
+ async_dist_proc_dctrlr/1]).
%% Internal exports.
-export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0,
group_leader_1/1,
optimistic_dflags_echo/0, optimistic_dflags_sender/1,
- roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1,
+ roundtrip/1, bounce/1,
dist_parallel_sender/3, dist_parallel_receiver/0,
derr_run/1,
dist_evil_parallel_receiver/0, make_busy/2]).
@@ -97,7 +104,7 @@ suite() ->
all() ->
[ping, {group, bulk_send}, {group, local_send},
- group_leader,
+ group_leader, nodes2,
optimistic_dflags,
link_to_busy, exit_to_busy, lost_exit, link_to_dead,
link_to_dead_new_node,
@@ -110,7 +117,8 @@ all() ->
dist_entry_refc_race,
start_epmd_false, no_epmd, epmd_module, system_limit,
hopefull_data_encoding, hopefull_export_fun_bug,
- huge_iovec].
+ huge_iovec, is_alive, dyn_node_name_monitor_node, dyn_node_name_monitor,
+ {group, async_dist}].
groups() ->
[{bulk_send, [], [bulk_send_small, bulk_send_big, bulk_send_bigbig]},
@@ -129,7 +137,11 @@ groups() ->
[message_latency_large_message,
message_latency_large_link_exit,
message_latency_large_monitor_exit,
- message_latency_large_exit2]}
+ message_latency_large_exit2]},
+ {async_dist, [],
+ [async_dist_flag,
+ async_dist_port_dctrlr,
+ async_dist_proc_dctrlr]}
].
init_per_suite(Config) ->
@@ -154,6 +166,15 @@ init_per_group(_, Config) ->
end_per_group(_, Config) ->
Config.
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ case wait_until(fun() -> nodes(connected) == [] end, 10_000) of
+ ok -> ok;
+ timeout ->
+ erts_test_utils:ept_check_leaked_nodes(Config)
+ end.
+
%% Tests pinging a node in different ways.
ping(Config) when is_list(Config) ->
Times = 1024,
@@ -169,10 +190,10 @@ ping(Config) when is_list(Config) ->
%% Pings another node.
- {ok, OtherNode} = start_node(distribution_SUITE_other),
+ {ok, Peer, OtherNode} = ?CT_PEER(),
io:format("Pinging ~s (assumed to exist)", [OtherNode]),
test_server:do_times(Times, fun() -> pong = net_adm:ping(OtherNode) end),
- stop_node(OtherNode),
+ peer_stop(Peer, OtherNode),
%% Pings our own node many times.
@@ -184,55 +205,333 @@ ping(Config) when is_list(Config) ->
%% Test erlang:group_leader(_, ExternalPid), i.e. DOP_GROUP_LEADER
group_leader(Config) when is_list(Config) ->
- ?Line Sock = start_relay_node(group_leader_1, []),
- ?Line Sock2 = start_relay_node(group_leader_2, []),
- try
- ?Line Node2 = inet_rpc_nodename(Sock2),
- ?Line {ok, ok} = do_inet_rpc(Sock, ?MODULE, group_leader_1, [Node2])
- after
- ?Line stop_relay_node(Sock),
- ?Line stop_relay_node(Sock2)
- end,
- ok.
+ {ok, Peer1, Node1} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"]}),
+ {ok, Peer2, Node2} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"]}),
+ pang = net_adm:ping(Node1), pang = net_adm:ping(Node2), %% extra check, may be skipped
+ ok = peer:call(Peer1, ?MODULE, group_leader_1, [Node2]),
+ peer:stop(Peer1), %% verify_nc() will fail because peer is not dist-connected
+ peer:stop(Peer2).
group_leader_1(Node2) ->
- ?Line ExtPid = spawn(Node2, fun F() ->
+ ExtPid = spawn(Node2, fun F() ->
receive {From, group_leader} ->
From ! {self(), group_leader, group_leader()}
end,
F()
end),
- ?Line GL1 = self(),
- ?Line group_leader(GL1, ExtPid),
- ?Line ExtPid ! {self(), group_leader},
- ?Line {ExtPid, group_leader, GL1} = receive_one(),
+ GL1 = self(),
+ group_leader(GL1, ExtPid),
+ ExtPid ! {self(), group_leader},
+ {ExtPid, group_leader, GL1} = receive_one(),
%% Kill connection and repeat test when group_leader/2 triggers auto-connect
- ?Line net_kernel:monitor_nodes(true),
- ?Line net_kernel:disconnect(Node2),
- ?Line {nodedown, Node2} = receive_one(),
- ?Line GL2 = spawn(fun() -> dummy end),
- ?Line group_leader(GL2, ExtPid),
- ?Line {nodeup, Node2} = receive_one(),
- ?Line ExtPid ! {self(), group_leader},
- ?Line {ExtPid, group_leader, GL2} = receive_one(),
+ net_kernel:monitor_nodes(true),
+ net_kernel:disconnect(Node2),
+ {nodedown, Node2} = receive_one(),
+ GL2 = spawn(fun() -> dummy end),
+ group_leader(GL2, ExtPid),
+ {nodeup, Node2} = receive_one(),
+ ExtPid ! {self(), group_leader},
+ {ExtPid, group_leader, GL2} = receive_one(),
ok.
-%% Test optimistic distribution flags toward pending connections (DFLAG_DIST_HOPEFULLY)
-optimistic_dflags(Config) when is_list(Config) ->
- ?Line Sender = start_relay_node(optimistic_dflags_sender, []),
- ?Line Echo = start_relay_node(optimistic_dflags_echo, []),
- try
- ?Line {ok, ok} = do_inet_rpc(Echo, ?MODULE, optimistic_dflags_echo, []),
-
- ?Line EchoNode = inet_rpc_nodename(Echo),
- ?Line {ok, ok} = do_inet_rpc(Sender, ?MODULE, optimistic_dflags_sender, [EchoNode])
- after
- ?Line stop_relay_node(Sender),
- ?Line stop_relay_node(Echo)
+nodes2(Config) when is_list(Config) ->
+
+ This = node(),
+
+ ok = net_kernel:monitor_nodes(true, #{node_type => all,
+ connection_id => true}),
+
+ AlreadyConnected = maps:from_list(lists:map(fun (N) ->
+ {N, true}
+ end, nodes(connected))),
+ AlreadyVisible = maps:from_list(lists:map(fun (N) ->
+ {N, true}
+ end, nodes(visible))),
+ AlreadyHidden = maps:from_list(lists:map(fun (N) ->
+ {N, true}
+ end, nodes(visible))),
+ AlreadyKnown = maps:from_list(lists:map(fun (N) ->
+ {N, true}
+ end, nodes(known))),
+
+ {ok, PV1, V1} = ?CT_PEER(),
+ {ok, PH1, H1} = ?CT_PEER(["-hidden"]),
+ {ok, PV2, V2} = ?CT_PEER(),
+ {ok, PH2, H2} = ?CT_PEER(["-hidden"]),
+
+ TestNodes = maps:from_list(lists:map(fun (N) ->
+ {N, true}
+ end, [This, V1, H1, V2, H2])),
+
+ V1CId = receive {nodeup, V1, #{connection_id := C1, node_type := visible}} -> C1 end,
+ V2CId = receive {nodeup, V2, #{connection_id := C2, node_type := visible}} -> C2 end,
+ H1CId = receive {nodeup, H1, #{connection_id := C3, node_type := hidden}} -> C3 end,
+ H2CId = receive {nodeup, H2, #{connection_id := C4, node_type := hidden}} -> C4 end,
+
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 2 = maps:size(I),
+ #{connection_id := V1CId, node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 2 = maps:size(I),
+ #{connection_id := V2CId, node_type := visible} = I;
+ ({N, I}) when N == H1 ->
+ 2 = maps:size(I),
+ #{connection_id := H1CId, node_type := hidden} = I;
+ ({N, I}) when N == H2 ->
+ 2 = maps:size(I),
+ #{connection_id := H2CId, node_type := hidden} = I;
+ ({N, I}) ->
+ 2 = maps:size(I),
+ #{connection_id := _, node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyConnected)
+ end, erlang:nodes(connected, #{connection_id => true,
+ node_type => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 2 = maps:size(I),
+ #{connection_id := V1CId, node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 2 = maps:size(I),
+ #{connection_id := V2CId, node_type := visible} = I;
+ ({N, I}) when N == H1 ->
+ 2 = maps:size(I),
+ #{connection_id := H1CId, node_type := hidden} = I;
+ ({N, I}) when N == H2 ->
+ 2 = maps:size(I),
+ #{connection_id := H2CId, node_type := hidden} = I;
+ ({N, I}) when N == This ->
+ 2 = maps:size(I),
+ #{connection_id := undefined, node_type := this} = I;
+ ({N, I}) ->
+ 2 = maps:size(I),
+ #{connection_id := _, node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyConnected)
+ end, erlang:nodes([this, connected], #{connection_id => true,
+ node_type => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 1 = maps:size(I),
+ #{connection_id := V1CId} = I;
+ ({N, I}) when N == V2 ->
+ 1 = maps:size(I),
+ #{connection_id := V2CId} = I;
+ ({N, I}) when N == H1 ->
+ 1 = maps:size(I),
+ #{connection_id := H1CId} = I;
+ ({N, I}) when N == H2 ->
+ 1 = maps:size(I),
+ #{connection_id := H2CId} = I;
+ ({N, I}) ->
+ 1 = maps:size(I),
+ #{connection_id := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyConnected)
+ end, erlang:nodes(connected, #{connection_id => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 1 = maps:size(I),
+ #{node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 1 = maps:size(I),
+ #{node_type := visible} = I;
+ ({N, I}) when N == H1 ->
+ 1 = maps:size(I),
+ #{node_type := hidden} = I;
+ ({N, I}) when N == H2 ->
+ 1 = maps:size(I),
+ #{node_type := hidden} = I;
+ ({N, I}) ->
+ 1 = maps:size(I),
+ #{node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyConnected)
+ end, erlang:nodes(connected, #{node_type => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 2 = maps:size(I),
+ #{connection_id := V1CId, node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 2 = maps:size(I),
+ #{connection_id := V2CId, node_type := visible} = I;
+ ({N, I}) ->
+ 2 = maps:size(I),
+ #{connection_id := _, node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyVisible)
+ end, erlang:nodes(visible, #{connection_id => true,
+ node_type => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 2 = maps:size(I),
+ #{connection_id := V1CId, node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 2 = maps:size(I),
+ #{connection_id := V2CId, node_type := visible} = I;
+ ({N, I}) when N == This ->
+ 2 = maps:size(I),
+ #{connection_id := undefined, node_type := this} = I;
+ ({N, I}) ->
+ 2 = maps:size(I),
+ #{connection_id := _, node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyVisible)
+ end, erlang:nodes([this, visible], #{connection_id => true,
+ node_type => true})),
+ lists:foreach(fun ({N, I}) when N == H1 ->
+ 2 = maps:size(I),
+ #{connection_id := H1CId, node_type := hidden} = I;
+ ({N, I}) when N == H2 ->
+ 2 = maps:size(I),
+ #{connection_id := H2CId, node_type := hidden} = I;
+ ({N, I}) ->
+ 2 = maps:size(I),
+ #{connection_id := _, node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyHidden)
+ end, erlang:nodes(hidden, #{connection_id => true,
+ node_type => true})),
+ [{This, #{connection_id := undefined,
+ node_type := this}}] = erlang:nodes(this, #{connection_id => true,
+ node_type => true}),
+ [{This, #{connection_id := undefined}}] = erlang:nodes(this, #{connection_id => true}),
+ [{This, #{node_type := this}}] = erlang:nodes(this, #{node_type => true}),
+
+ %% Ensure dist these dist entries are not GC:d yet...
+ NKV2 = rpc:call(V2, erlang, whereis, [net_kernel]),
+ true = is_pid(NKV2),
+ NKH2 = rpc:call(H2, erlang, whereis, [net_kernel]),
+ true = is_pid(NKH2),
+
+ peer:stop(PV2),
+ peer:stop(PH2),
+
+ receive {nodedown, V2, #{connection_id := V2CId, node_type := visible}} -> ok end,
+ receive {nodedown, H2, #{connection_id := H2CId, node_type := hidden}} -> ok end,
+
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 2 = maps:size(I),
+ #{connection_id := V1CId, node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 2 = maps:size(I),
+ #{connection_id := undefined, node_type := known} = I;
+ ({N, I}) when N == H1 ->
+ 2 = maps:size(I),
+ #{connection_id := H1CId, node_type := hidden} = I;
+ ({N, I}) when N == H2 ->
+ 2 = maps:size(I),
+ #{connection_id := undefined, node_type := known} = I;
+ ({N, I}) when N == This ->
+ 2 = maps:size(I),
+ #{connection_id := undefined, node_type := this} = I;
+ ({N, I}) ->
+ 2 = maps:size(I),
+ #{connection_id := _, node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyKnown)
+ end, erlang:nodes(known, #{connection_id => true,
+ node_type => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 1 = maps:size(I),
+ #{node_type := visible} = I;
+ ({N, I}) when N == V2 ->
+ 1 = maps:size(I),
+ #{node_type := known} = I;
+ ({N, I}) when N == H1 ->
+ 1 = maps:size(I),
+ #{node_type := hidden} = I;
+ ({N, I}) when N == H2 ->
+ 1 = maps:size(I),
+ #{node_type := known} = I;
+ ({N, I}) when N == This ->
+ 1 = maps:size(I),
+ #{node_type := this} = I;
+ ({N, I}) ->
+ 1 = maps:size(I),
+ #{node_type := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyKnown)
+ end, erlang:nodes(known, #{node_type => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 1 = maps:size(I),
+ #{connection_id := V1CId} = I;
+ ({N, I}) when N == V2 ->
+ 1 = maps:size(I),
+ #{connection_id := undefined} = I;
+ ({N, I}) when N == H1 ->
+ 1 = maps:size(I),
+ #{connection_id := H1CId} = I;
+ ({N, I}) when N == H2 ->
+ 1 = maps:size(I),
+ #{connection_id := undefined} = I;
+ ({N, I}) when N == This ->
+ 1 = maps:size(I),
+ #{connection_id := undefined} = I;
+ ({N, I}) ->
+ 1 = maps:size(I),
+ #{connection_id := _} = I,
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyKnown)
+ end, erlang:nodes(known, #{connection_id => true})),
+ lists:foreach(fun ({N, I}) when N == V1 ->
+ 0 = maps:size(I),
+ #{} = I;
+ ({N, I}) when N == V2 ->
+ 0 = maps:size(I),
+ #{} = I;
+ ({N, I}) when N == H1 ->
+ 0 = maps:size(I),
+ #{} = I;
+ ({N, I}) when N == H2 ->
+ 0 = maps:size(I),
+ #{} = I;
+ ({N, I}) when N == This ->
+ 0 = maps:size(I),
+ #{} = I;
+ ({N, I}) ->
+ 0 = maps:size(I),
+ false = maps:is_key(N, TestNodes),
+ true = maps:is_key(N, AlreadyKnown)
+ end, erlang:nodes(known, #{})),
+
+ peer:stop(PV1),
+ peer:stop(PH1),
+
+ id(NKV2),
+ id(NKH2),
+
+ try erlang:nodes("visible", #{connection_id => true})
+ catch error:badarg -> ok
+ end,
+ try erlang:nodes([another], #{connection_id => true})
+ catch error:badarg -> ok
+ end,
+ try erlang:nodes(visible, #{cid => true})
+ catch error:badarg -> ok
+ end,
+ try erlang:nodes(visible, #{connection_id => yes})
+ catch error:badarg -> ok
+ end,
+ try erlang:nodes(visible, #{node_type => yes})
+ catch error:badarg -> ok
+ end,
+ try erlang:nodes(visible, [{connection_id, true}])
+ catch error:badarg -> ok
+ end,
+ try erlang:nodes(visible, [{node_type, true}])
+ catch error:badarg -> ok
end,
ok.
+id(X) ->
+ X.
+
+%% Test optimistic distribution flags toward pending connections (DFLAG_DIST_HOPEFULLY)
+optimistic_dflags(Config) when is_list(Config) ->
+ {ok, PeerSender, _Sender} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"]}),
+ {ok, PeerEcho, Echo} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"]}),
+ ok = peer:call(PeerEcho, ?MODULE, optimistic_dflags_echo, []),
+ ok = peer:call(PeerSender, ?MODULE, optimistic_dflags_sender, [Echo]),
+ peer:stop(PeerSender),
+ peer:stop(PeerEcho).
+
optimistic_dflags_echo() ->
P = spawn(fun F() ->
receive {From, Term} ->
@@ -246,25 +545,25 @@ optimistic_dflags_echo() ->
ok.
optimistic_dflags_sender(EchoNode) ->
- ?Line net_kernel:monitor_nodes(true),
+ net_kernel:monitor_nodes(true),
optimistic_dflags_do(EchoNode, <<1:1>>),
optimistic_dflags_do(EchoNode, fun lists:map/2),
ok.
optimistic_dflags_do(EchoNode, Term) ->
- ?Line {optimistic_dflags_echo, EchoNode} ! {self(), Term},
- ?Line {nodeup, EchoNode} = receive_one(),
- ?Line {EchoPid, Term} = receive_one(),
+ {optimistic_dflags_echo, EchoNode} ! {self(), Term},
+ {nodeup, EchoNode} = receive_one(),
+ {EchoPid, Term} = receive_one(),
%% repeat with pid destination
- ?Line net_kernel:disconnect(EchoNode),
- ?Line {nodedown, EchoNode} = receive_one(),
- ?Line EchoPid ! {self(), Term},
- ?Line {nodeup, EchoNode} = receive_one(),
- ?Line {EchoPid, Term} = receive_one(),
-
- ?Line net_kernel:disconnect(EchoNode),
- ?Line {nodedown, EchoNode} = receive_one(),
+ net_kernel:disconnect(EchoNode),
+ {nodedown, EchoNode} = receive_one(),
+ EchoPid ! {self(), Term},
+ {nodeup, EchoNode} = receive_one(),
+ {EchoPid, Term} = receive_one(),
+
+ net_kernel:disconnect(EchoNode),
+ {nodedown, EchoNode} = receive_one(),
ok.
@@ -282,13 +581,13 @@ bulk_send(Terms, BinSize) ->
ct:timetrap({seconds, 30}),
io:format("Sending ~w binaries, each of size ~w K", [Terms, BinSize]),
- {ok, Node} = start_node(bulk_receiver),
+ {ok, Peer, Node} = ?CT_PEER(),
Recv = spawn(Node, erlang, apply, [fun receiver/2, [0, 0]]),
Bin = binary:copy(<<253>>, BinSize*1024),
Size = Terms*size(Bin),
{Elapsed, {Terms, Size}} = test_server:timecall(?MODULE, sender,
[Recv, Bin, Terms]),
- stop_node(Node),
+ peer_stop(Peer, Node),
{comment, integer_to_list(round(Size/1024/max(1,Elapsed))) ++ " K/s"}.
sender(To, _Bin, 0) ->
@@ -322,7 +621,7 @@ bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
io:format("\nSending ~w binaries, each of size ~w K",
[Terms, BinSize]),
- {ok, NodeRecv} = start_node(bulk_receiver),
+ {ok, RecvPeer, NodeRecv} = ?CT_PEER(),
Recv = spawn(NodeRecv, erlang, apply, [fun receiver/2, [0, 0]]),
Bin = binary:copy(<<253>>, BinSize*1024),
@@ -335,8 +634,7 @@ bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
%% default busy size and "+zdbbl 5", and if the 5 case gets
%% "many many more" monitor messages, then we know we're working.
- {ok, NodeSend} = start_node(bulk_sender, "+zdbbl " ++
- integer_to_list(BusyBufSize)),
+ {ok, SendPeer, NodeSend} = ?CT_PEER(["+zdbbl", integer_to_list(BusyBufSize)]),
_Send = spawn(NodeSend, erlang, apply,
[fun sendersender/4, [self(), Recv, Bin, Terms]]),
{Elapsed, {_TermsN, SizeN}, MonitorCount} =
@@ -348,8 +646,8 @@ bulk_sendsend2(Terms, BinSize, BusyBufSize) ->
{sendersender, BigRes} ->
BigRes
end,
- stop_node(NodeRecv),
- stop_node(NodeSend),
+ peer_stop(RecvPeer, NodeRecv),
+ peer_stop(SendPeer, NodeSend),
{round(SizeN/1024/Elapsed), MonitorCount}.
%% Sender process to be run on a slave node
@@ -450,7 +748,7 @@ receiver2(Num, TotSize) ->
%% Test that link/1 to a busy distribution port works.
link_to_busy(Config) when is_list(Config) ->
ct:timetrap({seconds, 60}),
- {ok, Node} = start_node(link_to_busy),
+ {ok, Peer, Node} = ?CT_PEER(),
Recv = spawn(Node, erlang, apply, [fun sink/1, [link_to_busy_sink]]),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
@@ -476,7 +774,7 @@ link_to_busy(Config) when is_list(Config) ->
do_busy_test(Node, fun () -> tail_applied_linker(Recv) end),
%% Done.
- stop_node(Node),
+ peer_stop(Peer, Node),
stop_busy_dist_port_tracer(Tracer),
ok.
@@ -496,7 +794,7 @@ tail_applied_linker(Pid) ->
%% Test that exit/2 to a busy distribution port works.
exit_to_busy(Config) when is_list(Config) ->
ct:timetrap({seconds, 60}),
- {ok, Node} = start_node(exit_to_busy),
+ {ok, Peer, Node} = ?CT_PEER(),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
"true" -> start_busy_dist_port_tracer();
@@ -546,7 +844,7 @@ exit_to_busy(Config) when is_list(Config) ->
end,
%% Done.
- stop_node(Node),
+ peer_stop(Peer, Node),
stop_busy_dist_port_tracer(Tracer),
ok.
@@ -665,7 +963,7 @@ sink1() ->
%% Test that EXIT and DOWN messages send to another node are not lost if
%% the distribution port is busy.
lost_exit(Config) when is_list(Config) ->
- {ok, Node} = start_node(lost_exit),
+ {ok, Peer, Node} = ?CT_PEER(),
Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of
"true" -> start_busy_dist_port_tracer();
@@ -718,7 +1016,7 @@ lost_exit(Config) when is_list(Config) ->
%% Done.
stop_busy_dist_port_tracer(Tracer),
- stop_node(Node),
+ peer_stop(Peer, Node),
ok.
dummy_waiter() ->
@@ -731,9 +1029,7 @@ dummy_waiter() ->
%% AND that the link is teared down.
link_to_dead(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- {ok, Node} = start_node(link_to_dead),
- % monitor_node(Node, true),
- net_adm:ping(Node), %% Ts_cross_server workaround.
+ {ok, Peer, Node} = ?CT_PEER(),
Pid = spawn(Node, ?MODULE, dead_process, []),
receive
after 5000 -> ok
@@ -750,13 +1046,14 @@ link_to_dead(Config) when is_list(Config) ->
{links, Links} = process_info(self(), links),
io:format("Pid=~p, links=~p", [Pid, Links]),
false = lists:member(Pid, Links),
- stop_node(Node),
receive
Message ->
ct:fail({unexpected_message, Message})
after 3000 ->
ok
end,
+ process_flag(trap_exit, false),
+ peer_stop(Peer, Node),
ok.
dead_process() ->
@@ -768,18 +1065,24 @@ link_to_dead_new_node(Config) when is_list(Config) ->
process_flag(trap_exit, true),
%% Start the node, get a Pid and stop the node again.
- {ok, Node} = start_node(link_to_dead_new_node),
+ Name = ?CT_PEER_NAME(?FUNCTION_NAME),
+ {ok, Peer, Node} = ?CT_PEER(#{name => Name}),
Pid = spawn(Node, ?MODULE, dead_process, []),
- stop_node(Node),
+
+ peer_stop(Peer, Node),
+ %% since exits are trapped, need to catch exiting peer
+ receive {'EXIT', Peer, normal} -> ok end,
%% Start a new node with the same name.
- {ok, Node} = start_node(link_to_dead_new_node),
+ {ok, Peer2, Node} = ?CT_PEER(#{name => Name}),
link(Pid),
+
receive
{'EXIT', Pid, noproc} ->
ok;
Other ->
- stop_node(Node),
+ process_flag(trap_exit, false),
+ peer_stop(Peer2, Node),
ct:fail({unexpected_message, Other})
after 5000 ->
ct:fail(nothing_received)
@@ -789,13 +1092,16 @@ link_to_dead_new_node(Config) when is_list(Config) ->
{links, Links} = process_info(self(), links),
io:format("Pid=~p, links=~p", [Pid, Links]),
false = lists:member(Pid, Links),
- stop_node(Node),
receive
Message ->
+ process_flag(trap_exit, false),
ct:fail({unexpected_message, Message})
after 3000 ->
ok
end,
+ %% stop trapping exits, and let the peer stop
+ process_flag(trap_exit, false),
+ peer_stop(Peer2, Node),
ok.
%% Test that sending a port or reference to another node and back again
@@ -804,13 +1110,13 @@ ref_port_roundtrip(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Port = make_port(),
Ref = make_ref(),
- {ok, Node} = start_node(ref_port_roundtrip),
+ {ok, Peer, Node} = ?CT_PEER(),
net_adm:ping(Node),
Term = {Port, Ref},
io:format("Term before: ~p", [show_term(Term)]),
Pid = spawn_link(Node, ?MODULE, roundtrip, [Term]),
receive after 5000 -> ok end,
- stop_node(Node),
+ peer_stop(Peer, Node),
receive
{'EXIT', Pid, {Port, Ref}} ->
io:format("Term after: ~p", [show_term(Term)]),
@@ -833,7 +1139,7 @@ roundtrip(Term) ->
%% another node node and back again.
nil_roundtrip(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- {ok, Node} = start_node(nil_roundtrip),
+ {ok, Peer, Node} = ?CT_PEER(),
net_adm:ping(Node),
Pid = spawn_link(Node, ?MODULE, bounce, [self()]),
Pid ! [],
@@ -841,7 +1147,7 @@ nil_roundtrip(Config) when is_list(Config) ->
[] ->
receive
{'EXIT', Pid, []} ->
- stop_node(Node),
+ peer_stop(Peer, Node),
ok
end
end.
@@ -861,9 +1167,9 @@ stop_dist(Config) when is_list(Config) ->
++ " -noshell -pa "
++ proplists:get_value(data_dir, Config)
++ " -s run"),
- %% The "true" may be followed by an error report, so ignore anything that
- %% follows it.
- "true\n"++_ = Str,
+ %% The "true" may be followed or prepended by an error report
+ Lines = string:lexemes(Str, "\n"),
+ true = lists:member("true", Lines),
%% "May fail on FreeBSD due to differently configured name lookup - ask Arndt",
%% if you can find him.
@@ -901,7 +1207,7 @@ tr3() ->
-% This has to be done by nodes with differrent cookies, otherwise global
+% This has to be done by nodes with different cookies, otherwise global
% will connect nodes, which is correct, but makes it hard to test.
% * Start two nodes, n1 and n2. n2 with the dist_auto_connect once parameter
% * n2 pings n1 -> connection
@@ -914,178 +1220,66 @@ tr3() ->
% * n2 now also gets pong when pinging n1
% * disconnect n2 from n1
% * n2 gets pang when pinging n1
-% * n2 forces connection by using net_kernel:connect_node (ovverrides)
+% * n2 forces connection by using net_kernel:connect_node (overrides)
% * n2 gets pong when pinging n1.
%% Test the dist_auto_connect once kernel parameter
dist_auto_connect_once(Config) when is_list(Config) ->
- Sock = start_relay_node(dist_auto_connect_relay_node,[]),
- NN = inet_rpc_nodename(Sock),
- Sock2 = start_relay_node(dist_auto_connect_once_node,
- "-kernel dist_auto_connect once"),
- NN2 = inet_rpc_nodename(Sock2),
- {ok,[]} = do_inet_rpc(Sock,erlang,nodes,[]),
- {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- {ok,[NN2]} = do_inet_rpc(Sock,erlang,nodes,[]),
- {ok,[NN]} = do_inet_rpc(Sock2,erlang,nodes,[]),
- [_,HostPartPeer] = string:lexemes(atom_to_list(NN),"@"),
- [_,MyHostPart] = string:lexemes(atom_to_list(node()),"@"),
+ {ok, PN, NN} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"]}),
+ {ok, PN2, NN2} = ?CT_PEER(#{connection => 0,
+ args => ["-setcookie", "NONE", "-kernel", "dist_auto_connect", "once"]}),
+ [] = peer:call(PN,erlang,nodes,[]),
+ pong = peer:call(PN2,net_adm,ping,[NN]),
+ [NN2] = peer:call(PN,erlang,nodes,[]),
+ [NN] = peer:call(PN2,erlang,nodes,[]),
% Give net_kernel a chance to change the state of the node to up to.
receive after 1000 -> ok end,
- case HostPartPeer of
- MyHostPart ->
- ok = stop_relay_node(Sock),
- {ok,pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]);
- _ ->
- {ok, true} = do_inet_rpc(Sock,net_kernel,disconnect,[NN2]),
- receive
- after 500 -> ok
- end
- end,
- {ok, []} = do_inet_rpc(Sock2,erlang,nodes,[]),
- Sock3 = case HostPartPeer of
- MyHostPart ->
- start_relay_node(dist_auto_connect_relay_node,[]);
- _ ->
- Sock
- end,
+ ok = peer:stop(PN),
+ pang = peer:call(PN2,net_adm,ping,[NN]),
+ [] = peer:call(PN2,erlang,nodes,[]),
+ %% restart NN node
+ {ok, PN3, NN} = ?CT_PEER(#{connection => 0, args => ["-setcookie", "NONE"],
+ name => hd(string:lexemes(atom_to_list(NN), "@"))}),
TS1 = timestamp(),
- {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
+ pang = peer:call(PN2,net_adm,ping,[NN]),
TS2 = timestamp(),
RefT = net_kernel:connecttime() - 1000,
true = ((TS2 - TS1) < RefT),
TS3 = timestamp(),
- {ok, true} = do_inet_rpc(Sock2,erlang,monitor_node,
- [NN,true,[allow_passive_connect]]),
+ true = peer:call(PN2,erlang,monitor_node,
+ [NN,true,[allow_passive_connect]], 60000),
TS4 = timestamp(),
true = ((TS4 - TS3) > RefT),
- {ok, pong} = do_inet_rpc(Sock3,net_adm,ping,[NN2]),
- {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- {ok, true} = do_inet_rpc(Sock3,net_kernel,disconnect,[NN2]),
+ pong = peer:call(PN3,net_adm,ping,[NN2]),
+ pong = peer:call(PN2,net_adm,ping,[NN]),
+ true = peer:call(PN3,net_kernel,disconnect,[NN2]),
receive
after 500 -> ok
end,
- {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- {ok, true} = do_inet_rpc(Sock2,net_kernel,connect_node,[NN]),
- {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]),
- stop_relay_node(Sock3),
- stop_relay_node(Sock2).
+ pang = peer:call(PN2,net_adm,ping,[NN]),
+ true = peer:call(PN2,net_kernel,connect_node,[NN]),
+ pong = peer:call(PN2,net_adm,ping,[NN]),
+ peer:stop(PN3),
+ peer:stop(PN2).
-%% Start a relay node and a lonely (dist_auto_connect never) node.
-%% Lonely node pings relay node. That should fail.
-%% Lonely node connects to relay node with net_kernel:connect_node/1.
-%% Result is sent here through relay node.
+%% Spawn dist_auto_connect never node, ensure it won't
+%% connect to the origin with net_adm:ping(), but will with
+%% explicit net_kernel:connect_node.
dist_auto_connect_never(Config) when is_list(Config) ->
- Self = self(),
- {ok, RelayNode} = start_node(dist_auto_connect_relay),
- spawn(RelayNode,
- fun() ->
- register(dist_auto_connect_relay, self()),
- dist_auto_connect_relay(Self)
- end),
- {ok, Handle} = dist_auto_connect_start(dist_auto_connect, never),
- Result = receive
- {do_dist_auto_connect, ok} ->
- ok;
- {do_dist_auto_connect, Error} ->
- {error, Error};
- %% The io:formats in dos_dist_auto_connect will
- %% generate port output messages that are ok
- Other when not is_port(element(1, Other))->
- {error, Other}
- after 32000 ->
- timeout
- end,
- stop_node(RelayNode),
- Stopped = dist_auto_connect_stop(Handle),
- Junk = receive
- {do_dist_auto_connect, _} = J -> J
- after 0 -> ok
- end,
- {ok, ok, ok} = {Result, Stopped, Junk},
+ {ok, LonelyPeer, Node} = ?CT_PEER(#{connection => 0, args => ["-kernel", "dist_auto_connect", "never"]}),
+ pang = peer:call(LonelyPeer, net_adm, ping, [node()]),
+ false = lists:member(Node, nodes()),
+ true = peer:call(LonelyPeer, net_kernel, connect_node, [node()]),
+ true = lists:member(Node, nodes()),
+ peer:stop(LonelyPeer),
ok.
-
-do_dist_auto_connect([never]) ->
- Node = list_to_atom("dist_auto_connect_relay@" ++ hostname()),
- io:format("~p:do_dist_auto_connect([false]) Node=~p~n", [?MODULE, Node]),
- Ping = net_adm:ping(Node),
- io:format("~p:do_dist_auto_connect([false]) Ping=~p~n", [?MODULE, Ping]),
- Result = case Ping of
- pang -> ok;
- _ -> {error, Ping}
- end,
- io:format("~p:do_dist_auto_connect([false]) Result=~p~n", [?MODULE, Result]),
- net_kernel:connect_node(Node),
- catch {dist_auto_connect_relay, Node} ! {do_dist_auto_connect, Result};
-% receive after 1000 -> ok end,
-% halt();
-
-do_dist_auto_connect(Arg) ->
- io:format("~p:do_dist_auto_connect(~p)~n", [?MODULE, Arg]),
- receive after 10000 -> ok end,
- halt().
-
-
-dist_auto_connect_start(Name, Value) when is_atom(Name) ->
- dist_auto_connect_start(atom_to_list(Name), Value);
-dist_auto_connect_start(Name, Value) when is_list(Name), is_atom(Value) ->
- Node = list_to_atom(lists:append([Name, "@", hostname()])),
- ModuleDir = filename:dirname(code:which(?MODULE)),
- ValueStr = atom_to_list(Value),
- Cookie = atom_to_list(erlang:get_cookie()),
- Cmd = lists:append(
- [%"xterm -e ",
- ct:get_progname(),
- % " -noinput ",
- " -detached ",
- long_or_short(), " ", Name,
- " -setcookie ", Cookie,
- " -pa ", ModuleDir,
- " -s ", atom_to_list(?MODULE),
- " do_dist_auto_connect ", ValueStr,
- " -kernel dist_auto_connect ", ValueStr]),
- io:format("~p:dist_auto_connect_start() cmd: ~p~n", [?MODULE, Cmd]),
- Port = open_port({spawn, Cmd}, [stream]),
- {ok, {Port, Node}}.
-
-
-dist_auto_connect_stop({Port, Node}) ->
- Pid = spawn_link(fun() -> rpc:call(Node, erlang, halt, []) end),
- dist_auto_connect_stop(Port, Node, Pid, 5000).
-
-dist_auto_connect_stop(Port, _Node, Pid, N) when is_integer(N), N =< 0 ->
- exit(Pid, normal),
- catch erlang:port_close(Port),
- Result = {error, node_not_down},
- io:format("~p:dist_auto_connect_stop() ~p~n", [?MODULE, Result]),
- Result;
-dist_auto_connect_stop(Port, Node, Pid, N) when is_integer(N) ->
- case net_adm:ping(Node) of
- pong ->
- receive after 100 -> ok end,
- dist_auto_connect_stop(Port, Node, Pid, N-100);
- pang ->
- exit(Pid, normal),
- catch erlang:port_close(Port),
- io:format("~p:dist_auto_connect_stop() ok~n", [?MODULE]),
- ok
- end.
-
-
-dist_auto_connect_relay(Parent) ->
- receive X ->
- catch Parent ! X
- end,
- dist_auto_connect_relay(Parent).
-
-
dist_parallel_send(Config) when is_list(Config) ->
%% Disabled "connect all" so global wont interfere...
- {ok, RNode} = start_node(dist_parallel_receiver, "-connect_all false"),
- {ok, SNode} = start_node(dist_parallel_sender, "-connect_all false"),
+ {ok, RPeer, RNode} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, SPeer, SNode} = ?CT_PEER(["-connect_all", "false"]),
%% WatchDog = spawn_link(
%% fun () ->
@@ -1145,8 +1339,8 @@ dist_parallel_send(Config) when is_list(Config) ->
%% unlink(WatchDog),
%% exit(WatchDog, bang),
- stop_node(RNode),
- stop_node(SNode),
+ peer_stop(RPeer, RNode),
+ peer_stop(SPeer, SNode),
ok.
@@ -1172,17 +1366,17 @@ dist_evil_parallel_receiver() ->
atom_roundtrip(Config) when is_list(Config) ->
AtomData = atom_data(),
verify_atom_data(AtomData),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
do_atom_roundtrip(Node, AtomData),
- stop_node(Node),
+ peer_stop(Peer, Node),
ok.
unicode_atom_roundtrip(Config) when is_list(Config) ->
AtomData = unicode_atom_data(),
verify_atom_data(AtomData),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
do_atom_roundtrip(Node, AtomData),
- stop_node(Node),
+ peer_stop(Peer, Node),
ok.
do_atom_roundtrip(Node, AtomData) ->
@@ -1278,17 +1472,17 @@ unicode_atom_data() ->
end, lists:seq(1, 2000))].
contended_atom_cache_entry(Config) when is_list(Config) ->
- contended_atom_cache_entry_test(Config, latin1).
+ contended_atom_cache_entry_test(latin1).
contended_unicode_atom_cache_entry(Config) when is_list(Config) ->
- contended_atom_cache_entry_test(Config, unicode).
+ contended_atom_cache_entry_test(unicode).
-contended_atom_cache_entry_test(Config, Type) ->
+contended_atom_cache_entry_test(Type) ->
TestServer = self(),
ProcessPairs = 10,
Msgs = 100000,
- {ok, SNode} = start_node(Config),
- {ok, RNode} = start_node(Config),
+ {ok, SPeer, SNode} = ?CT_PEER(),
+ {ok, RPeer, RNode} = ?CT_PEER(),
Success = make_ref(),
spawn_link(
SNode,
@@ -1350,8 +1544,8 @@ contended_atom_cache_entry_test(Config, Type) ->
Success ->
ok
end,
- stop_node(SNode),
- stop_node(RNode),
+ peer_stop(SPeer, SNode),
+ peer_stop(RPeer, RNode),
ok.
send_ref_atom(_To, _Ref, _Atom, 0) ->
@@ -1426,15 +1620,15 @@ get_conflicting_unicode_atoms(CIX, N) ->
%% they no longer fail when the latency is incorrect. However, they are
%% kept as they continue to find bugs in the distribution implementation.
message_latency_large_message(Config) when is_list(Config) ->
- measure_latency_large_message(?FUNCTION_NAME, fun(Dropper, Payload) -> Dropper ! Payload end).
+ measure_latency_large_message(fun(Dropper, Payload) -> Dropper ! Payload end).
message_latency_large_exit2(Config) when is_list(Config) ->
- measure_latency_large_message(?FUNCTION_NAME, fun erlang:exit/2).
+ measure_latency_large_message(fun erlang:exit/2).
message_latency_large_link_exit(Config) when is_list(Config) ->
- message_latency_large_exit(?FUNCTION_NAME, fun erlang:link/1).
+ message_latency_large_exit(fun erlang:link/1).
message_latency_large_monitor_exit(Config) when is_list(Config) ->
- message_latency_large_exit(?FUNCTION_NAME,
+ message_latency_large_exit(
fun(Dropper) ->
Dropper ! {monitor, self()},
receive ok -> ok end
@@ -1449,9 +1643,8 @@ message_latency_large_link_exit() ->
message_latency_large_monitor_exit() ->
message_latency_large_message().
-message_latency_large_exit(Nodename, ReasonFun) ->
+message_latency_large_exit(ReasonFun) ->
measure_latency_large_message(
- Nodename,
fun(Dropper, Payload) ->
Pid = spawn(fun() ->
receive go -> ok end,
@@ -1476,11 +1669,11 @@ message_latency_large_exit(Nodename, ReasonFun) ->
end
end).
-measure_latency_large_message(Nodename, DataFun) ->
+measure_latency_large_message(DataFun) ->
erlang:system_monitor(self(), [busy_dist_port]),
- {ok, N} = start_node(Nodename),
+ {ok, Peer, N} = ?CT_PEER(),
Dropper = spawn(N, fun F() ->
process_flag(trap_exit, true),
@@ -1514,7 +1707,7 @@ measure_latency_large_message(Nodename, DataFun) ->
ct:pal("~p",[IndexTimes]),
- stop_node(N),
+ peer_stop(Peer, N),
case {lists:max(Times), lists:min(Times)} of
{Max, Min} when Max * 0.25 > Min, BuildType =:= opt ->
@@ -1529,8 +1722,6 @@ measure_latency_large_message(Nodename, DataFun) ->
measure_latency(DataFun, Dropper, Echo, Payload) ->
- TCProc = self(),
-
flush(),
Senders = [spawn_monitor(
@@ -1590,8 +1781,10 @@ flush() ->
system_limit(Config) when is_list(Config) ->
case erlang:system_info(wordsize) of
8 ->
- case proplists:get_value(system_total_memory,
- memsup:get_system_memory_data()) of
+ SMD = memsup:get_system_memory_data(),
+ case proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(system_total_memory, SMD)) of
Memory when is_integer(Memory),
Memory > 6*1024*1024*1024 ->
test_system_limit(Config),
@@ -1608,7 +1801,7 @@ test_system_limit(Config) when is_list(Config) ->
Bits = ((1 bsl 32)+1)*8,
HugeBin = <<0:Bits>>,
HugeListBin = [lists:duplicate(2000000,2000000), HugeBin],
- {ok, N1} = start_node(Config),
+ {ok, _Peer1, N1} = ?CT_PEER(),
monitor_node(N1, true),
receive
{nodedown, N1} ->
@@ -1681,7 +1874,7 @@ test_system_limit(Config) when is_list(Config) ->
end),
receive {nodedown, N1} -> ok end,
- {ok, N2} = start_node(Config),
+ {ok, _Peer2, N2} = ?CT_PEER(),
monitor_node(N2, true),
P2 = spawn(N2,
fun () ->
@@ -1694,7 +1887,7 @@ test_system_limit(Config) when is_list(Config) ->
receive {nodedown, N2} -> ok end,
io:format("~n** distributed monitor down **~n~n", []),
- {ok, N3} = start_node(Config),
+ {ok, _Peer3, N3} = ?CT_PEER(),
monitor_node(N3, true),
Go1 = make_ref(),
LP1 = spawn(fun () ->
@@ -1709,7 +1902,7 @@ test_system_limit(Config) when is_list(Config) ->
end),
receive {nodedown, N3} -> ok end,
- {ok, N4} = start_node(Config),
+ {ok, _Peer4, N4} = ?CT_PEER(),
monitor_node(N4, true),
Go2 = make_ref(),
LP2 = spawn(fun () ->
@@ -1795,8 +1988,8 @@ bad_dist_structure(Config) when is_list(Config) ->
ct:timetrap({seconds, 15}),
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_structure_offender, "-connect_all false"),
- {ok, Victim} = start_node(bad_dist_structure_victim, "-connect_all false"),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
start_node_monitors([Offender,Victim]),
Parent = self(),
P = spawn(Victim,
@@ -1882,8 +2075,8 @@ bad_dist_structure(Config) when is_list(Config) ->
unlink(P),
P ! done,
- stop_node(Offender),
- stop_node(Victim),
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim),
ok.
%% Test various dist fragmentation errors
@@ -1891,8 +2084,8 @@ bad_dist_fragments(Config) when is_list(Config) ->
ct:timetrap({seconds, 15}),
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_fragment_offender, "-connect_all false"),
- {ok, Victim} = start_node(bad_dist_fragment_victim, "-connect_all false"),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
Msg = iolist_to_binary(dmsg_ext(lists:duplicate(255,255))),
@@ -1985,8 +2178,8 @@ bad_dist_fragments(Config) when is_list(Config) ->
unlink(P),
P ! done,
- stop_node(Offender),
- stop_node(Victim),
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim),
ok.
dmsg_frag_hdr(Frag) ->
@@ -2047,8 +2240,8 @@ send_bad_fragments(Offender,VictimNode,Victim,Ctrl,WhereToPutSelf,Fragments) ->
bad_dist_ext_receive(Config) when is_list(Config) ->
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_ext_receive_offender, "-connect_all false"),
- {ok, Victim} = start_node(bad_dist_ext_receive_victim, "-connect_all false"),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
start_node_monitors([Offender,Victim]),
Parent = self(),
@@ -2114,14 +2307,14 @@ bad_dist_ext_receive(Config) when is_list(Config) ->
P ! done,
unlink(P),
verify_no_down(Offender, Victim),
- stop_node(Offender),
- stop_node(Victim).
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim).
bad_dist_ext_process_info(Config) when is_list(Config) ->
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_ext_process_info_offender, "-connect_all false"),
- {ok, Victim} = start_node(bad_dist_ext_process_info_victim, "-connect_all false"),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
start_node_monitors([Offender,Victim]),
Parent = self(),
@@ -2176,13 +2369,13 @@ bad_dist_ext_process_info(Config) when is_list(Config) ->
P ! done,
unlink(P),
verify_no_down(Offender, Victim),
- stop_node(Offender),
- stop_node(Victim).
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim).
bad_dist_ext_control(Config) when is_list(Config) ->
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_ext_control_offender, "-connect_all false"),
- {ok, Victim} = start_node(bad_dist_ext_control_victim, "-connect_all false"),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
start_node_monitors([Offender,Victim]),
pong = rpc:call(Victim, net_adm, ping, [Offender]),
@@ -2196,13 +2389,13 @@ bad_dist_ext_control(Config) when is_list(Config) ->
verify_down(Offender, connection_closed, Victim, killed),
verify_no_down(Offender, Victim),
- stop_node(Offender),
- stop_node(Victim).
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim).
bad_dist_ext_connection_id(Config) when is_list(Config) ->
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_ext_connection_id_offender, "-connect_all false"),
- {ok, Victim} = start_node(bad_dist_ext_connection_id_victim, "-connect_all false"),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
start_node_monitors([Offender,Victim]),
Parent = self(),
@@ -2263,16 +2456,14 @@ bad_dist_ext_connection_id(Config) when is_list(Config) ->
P ! done,
unlink(P),
verify_no_down(Offender, Victim),
- stop_node(Offender),
- stop_node(Victim).
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim).
%% OTP-14661: Bad message is discovered by erts_msg_attached_data_size
bad_dist_ext_size(Config) when is_list(Config) ->
%% Disabled "connect all" so global wont interfere...
- {ok, Offender} = start_node(bad_dist_ext_process_info_offender, "-connect_all false"),
- %%Prog = "Prog=/home/uabseri/src/otp_new3/bin/cerl -rr -debug",
- Prog = [],
- {ok, Victim} = start_node(bad_dist_ext_process_info_victim, "-connect_all false", Prog),
+ {ok, OffenderPeer, Offender} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, VictimPeer, Victim} = ?CT_PEER(["-connect_all", "false"]),
start_node_monitors([Offender,Victim]),
Parent = self(),
@@ -2319,8 +2510,8 @@ bad_dist_ext_size(Config) when is_list(Config) ->
unlink(P),
verify_no_down(Offender, Victim),
- stop_node(Offender),
- stop_node(Victim).
+ peer_stop(OffenderPeer, Offender),
+ peer_stop(VictimPeer, Victim).
bad_dist_struct_check_msgs([]) ->
@@ -2465,7 +2656,7 @@ send_bad_ctl(BadNode, ToNode) when is_atom(BadNode), is_atom(ToNode) ->
spawn_link(BadNode,
fun () ->
pong = net_adm:ping(ToNode),
- %% We creat a valid ctl msg and replace an
+ %% We create a valid ctl msg and replace an
%% atom with an invalid atom cache reference
<<131,Replace/binary>> = term_to_binary(replace),
Ctl = dmsg_ext({?DOP_REG_SEND,
@@ -2522,7 +2713,7 @@ set_internal_state(Op, Val) ->
dmsg_hdr() ->
[131, % Version Magic
$D, % Dist header
- 0]. % No atom cache referenses
+ 0]. % No atom cache references
dmsg_bad_hdr() ->
[131, % Version Magic
@@ -2564,7 +2755,7 @@ dmsg_bad_tag() -> %% Will fail early at heap size calculation
%% We also make sure that the binary memory of the receiving node does not grow
%% without shrinking back as there used to be a memory leak on the receiving side.
exit_dist_fragments(_Config) ->
- {ok, Node} = start_node(?FUNCTION_NAME),
+ {ok, Peer, Node} = ?CT_PEER(),
try
ct:log("Allocations before:~n~p",[erpc:call(Node,instrument,allocations, [])]),
{BinInfo, BinInfoMref} =
@@ -2584,6 +2775,7 @@ exit_dist_fragments(_Config) ->
end)([])
end),
{Tracer, Mref} = spawn_monitor(fun gather_exited/0),
+ link(Tracer), %% Make sure Tracer dies if we die
erlang:trace(self(), true, [{tracer, Tracer}, set_on_spawn, procs, exiting]),
exit_suspend(Node),
receive
@@ -2612,7 +2804,7 @@ exit_dist_fragments(_Config) ->
end
end
after
- stop_node(Node)
+ peer:stop(Peer)
end.
%% Make sure that each spawned process also has exited
@@ -2622,15 +2814,17 @@ gather_exited() ->
gather_exited(Pids) ->
receive
{trace,Pid,spawned,_,_} ->
- gather_exited(Pids#{ Pid => true });
- {trace,Pid,exited_out,_,_} ->
+ gather_exited(maps:update_with(spawned, fun(V) -> V + 1 end, 0, Pids#{ Pid => true }));
+ {trace,Pid,out_exited,_} ->
{true, NewPids} = maps:take(Pid, Pids),
- gather_exited(NewPids);
- _M ->
- gather_exited(Pids)
+ gather_exited(maps:update_with(out_exited, fun(V) -> V + 1 end, 0, NewPids));
+ Trace ->
+ gather_exited(maps:update_with(element(3, Trace), fun(V) -> V + 1 end, 0, Pids))
after 1000 ->
- if Pids == #{} -> ok;
- true -> exit(Pids)
+ MissingPids = maps:size(maps:filter(fun(Key,_) -> not erlang:is_atom(Key) end, Pids)),
+ if MissingPids =:= 0 -> ok;
+ true -> exit({[{Pid,erlang:process_info(Pid)} || Pid <- MissingPids],
+ maps:filter(fun(Key,_) -> erlang:is_atom(Key) end, Pids)})
end
end.
@@ -2656,8 +2850,8 @@ exit_suspend(RemoteNode, N, Payload) ->
fun() ->
false = process_flag(trap_exit, true),
RemotePid = spawn_link(RemoteNode, Echo),
- Iterations = case erlang:system_info(debug_compiled) of
- false ->
+ Iterations = case erlang:system_info(emu_type) of
+ opt ->
100;
_ ->
10
@@ -2722,49 +2916,54 @@ exit_suspend_loop(LocalPid, RemotePid, Suspenders, Payload, N) ->
start_epmd_false(Config) when is_list(Config) ->
%% Start a node with the option -start_epmd false.
- {ok, OtherNode} = start_node(start_epmd_false, "-start_epmd false"),
+ {ok, Peer, OtherNode} = ?CT_PEER(["-start_epmd", "false"]),
%% We should be able to ping it, as epmd was started by us:
pong = net_adm:ping(OtherNode),
- stop_node(OtherNode),
+ peer_stop(Peer,OtherNode),
ok.
no_epmd(Config) when is_list(Config) ->
%% Trying to start a node with -no_epmd but without passing the
%% --proto_dist option should fail.
- {error, timeout} = start_node(no_epmd, "-no_epmd").
+ try
+ ?CT_PEER(#{connection => standard_io, args => ["-no_epmd"]}),
+ ct:fail(unexpected_no_epmd_start)
+ catch
+ exit:{boot_failed, {exit_status, 1}} ->
+ ok
+ end.
epmd_module(Config) when is_list(Config) ->
%% We need a relay node to test this, since the test node uses the
%% standard epmd module.
- {N1,_,S1} = Sock1 = start_relay_node(
- epmd_module_node1,
- "-epmd_module " ++ ?MODULE_STRING,
- [{"ERL_AFLAGS","-sname epmd_module_node1@dummy " ++ os:getenv("ERL_AFLAGS","")}]),
- Node1 = inet_rpc_nodename({N1,"dummy",S1}),
- %% Ask what port it's listening on - it won't have registered with
- %% epmd.
- {ok, {ok, Port1}} = do_inet_rpc(Sock1, application, get_env, [kernel, dist_listen_port]),
-
- %% Start a second node, passing the port number as a secret
- %% argument.
- {N2,_,S2} = Sock2 = start_relay_node(
- epmd_module_node2,
- "-epmd_module " ++ ?MODULE_STRING
- ++ " -other_node_port " ++ integer_to_list(Port1),
- [{"ERL_AFLAGS","-sname epmd_module_node2@dummy " ++ os:getenv("ERL_AFLAGS","")}]),
- Node2 = inet_rpc_nodename({N2,"dummy",S2}),
+ {ok, Peer1, Node1} = ?CT_PEER(
+ #{connection => 0,
+ name => "epmd_module_node1",
+ host => "dummy",
+ args => ["-setcookie", "NONE", "-epmd_module", ?MODULE_STRING]}),
+ %% Ask what port it's listening on - it won't have registered with epmd.
+ {ok, Port1} = peer:call(Peer1, application, get_env, [kernel, dist_listen_port]),
+
+ %% Start a second node, passing the port number as a secret argument.
+ {ok, Peer2, Node2} = ?CT_PEER(
+ #{connection => 0,
+ name => "epmd_module_node2",
+ host => "dummy",
+ args => ["-setcookie", "NONE", "-epmd_module", ?MODULE_STRING,
+ "-other_node_port", integer_to_list(Port1)]}),
+
%% Node 1 can't ping node 2
- {ok, pang} = do_inet_rpc(Sock1, net_adm, ping, [Node2]),
- {ok, []} = do_inet_rpc(Sock1, erlang, nodes, []),
- {ok, []} = do_inet_rpc(Sock2, erlang, nodes, []),
+ pang = peer:call(Peer1, net_adm, ping, [Node2]),
+ [] = peer:call(Peer1, erlang, nodes, []),
+ [] = peer:call(Peer2, erlang, nodes, []),
%% But node 2 can ping node 1
- {ok, pong} = do_inet_rpc(Sock2, net_adm, ping, [Node1]),
- {ok, [Node2]} = do_inet_rpc(Sock1, erlang, nodes, []),
- {ok, [Node1]} = do_inet_rpc(Sock2, erlang, nodes, []),
+ pong = peer:call(Peer2, net_adm, ping, [Node1]),
+ [Node2] = peer:call(Peer1, erlang, nodes, []),
+ [Node1] = peer:call(Peer2, erlang, nodes, []),
- stop_relay_node(Sock2),
- stop_relay_node(Sock1).
+ peer:stop(Peer2),
+ peer:stop(Peer1).
%% epmd_module functions:
@@ -2800,21 +2999,22 @@ address_please(_Name, "dummy", inet6) ->
{ok, {0,0,0,0,0,0,0,1}}.
hopefull_data_encoding(Config) when is_list(Config) ->
- test_hopefull_data_encoding(Config, true),
- test_hopefull_data_encoding(Config, false).
+ MkHopefullData = fun(Ref,Pid) -> mk_hopefull_data(Ref,Pid) end,
+ test_hopefull_data_encoding(MkHopefullData),
+
+ %% Test funs with hopefully encoded term in environment
+ MkBitstringInFunEnv = fun(_,_) -> [mk_fun_with_env(<<5:7>>)] end,
+ test_hopefull_data_encoding(MkBitstringInFunEnv),
+ MkExpFunInFunEnv = fun(_,_) -> [mk_fun_with_env(fun a:a/0)] end,
+ test_hopefull_data_encoding(MkExpFunInFunEnv),
+ ok.
-test_hopefull_data_encoding(Config, Fallback) when is_list(Config) ->
- {ok, ProxyNode} = start_node(hopefull_data_normal),
- {ok, BouncerNode} = start_node(hopefull_data_bouncer, "-hidden"),
- case Fallback of
- false ->
- ok;
- true ->
- rpc:call(BouncerNode, erts_debug, set_internal_state,
- [available_internal_state, true]),
- false = rpc:call(BouncerNode, erts_debug, set_internal_state,
- [remove_hopefull_dflags, true])
- end,
+mk_fun_with_env(Term) ->
+ fun() -> Term end.
+
+test_hopefull_data_encoding(MkDataFun) ->
+ {ok, PeerProxy, ProxyNode} = ?CT_PEER(),
+ {ok, PeerBouncer, BouncerNode} = ?CT_PEER(["-hidden"]),
Tester = self(),
R1 = make_ref(),
R2 = make_ref(),
@@ -2825,7 +3025,7 @@ test_hopefull_data_encoding(Config, Fallback) when is_list(Config) ->
register(bouncer, self()),
%% We create the data on the proxy node in order
%% to create the correct sub binaries
- HData = mk_hopefull_data(R1, Tester),
+ HData = MkDataFun(R1, Tester),
%% Verify same result between this node and tester
Tester ! [R1, HData],
%% Test when connection has not been setup yet
@@ -2844,28 +3044,18 @@ test_hopefull_data_encoding(Config, Fallback) when is_list(Config) ->
end,
receive
[R2, HData2] ->
- case Fallback of
- false ->
- HData = HData2;
- true ->
- check_hopefull_fallback_data(HData, HData2)
- end
+ HData = HData2
end,
receive
[R3, HData3] ->
- case Fallback of
- false ->
- HData = HData3;
- true ->
- check_hopefull_fallback_data(HData, HData3)
- end
+ HData = HData3
end,
unlink(Proxy),
exit(Proxy, bye),
unlink(Bouncer),
exit(Bouncer, bye),
- stop_node(ProxyNode),
- stop_node(BouncerNode),
+ peer_stop(PeerProxy, ProxyNode),
+ peer_stop(PeerBouncer, BouncerNode),
ok.
bounce_loop() ->
@@ -2924,50 +3114,20 @@ mk_hopefull_data(BS) ->
[NewBs]
end, lists:seq(BSsz-32, BSsz-17))]).
-check_hopefull_fallback_data([], []) ->
- ok;
-check_hopefull_fallback_data([X|Xs],[Y|Ys]) ->
- chk_hopefull_fallback(X, Y),
- check_hopefull_fallback_data(Xs,Ys).
-
-chk_hopefull_fallback(Binary, FallbackBinary) when is_binary(Binary) ->
- Binary = FallbackBinary;
-chk_hopefull_fallback([BitStr], [{Bin, BitSize}]) when is_bitstring(BitStr) ->
- chk_hopefull_fallback(BitStr, {Bin, BitSize});
-chk_hopefull_fallback(BitStr, {Bin, BitSize}) when is_bitstring(BitStr) ->
- true = is_binary(Bin),
- true = is_integer(BitSize),
- true = BitSize > 0,
- true = BitSize < 8,
- Hsz = size(Bin) - 1,
- <<Head:Hsz/binary, I/integer>> = Bin,
- IBits = I bsr (8 - BitSize),
- FallbackBitStr = list_to_bitstring([Head,<<IBits:BitSize>>]),
- BitStr = FallbackBitStr,
- ok;
-chk_hopefull_fallback(Func, {ModName, FuncName}) when is_function(Func) ->
- {M, F, _} = erlang:fun_info_mfa(Func),
- M = ModName,
- F = FuncName,
- ok;
-chk_hopefull_fallback(Other, SameOther) ->
- Other = SameOther,
- ok.
-
%% ERL-1254
hopefull_export_fun_bug(Config) when is_list(Config) ->
Msg = [1, fun blipp:blapp/7,
2, fun blipp:blapp/7],
{dummy, dummy@dummy} ! Msg. % Would crash on debug VM
-huge_iovec(Config) ->
+huge_iovec(Config) when is_list(Config) ->
%% Make sure that we can pass a term that will produce
%% an io-vector larger than IOV_MAX over the distribution...
%% IOV_MAX is typically 1024. Currently we produce an
%% element in the io-vector for all off heap binaries...
NoBinaries = 1 bsl 14,
BinarySize = 65,
- {ok, Node} = start_node(huge_iovec),
+ {ok, Peer, Node} = ?CT_PEER(),
P = spawn_link(Node,
fun () ->
receive {From, Data} ->
@@ -2983,7 +3143,7 @@ huge_iovec(Config) ->
P ! {self(), RBL},
receive
{P, EchoedRBL} ->
- stop_node(Node),
+ peer_stop(Peer, Node),
RBL = EchoedRBL
end,
ok.
@@ -2994,23 +3154,14 @@ mk_rand_bin_list(Bytes, Binaries) ->
mk_rand_bin_list(_Bytes, 0, Acc) ->
Acc;
mk_rand_bin_list(Bytes, Binaries, Acc) ->
- mk_rand_bin_list(Bytes, Binaries-1, [mk_rand_bin(Bytes) | Acc]).
-
-mk_rand_bin(Bytes) ->
- mk_rand_bin(Bytes, []).
-
-mk_rand_bin(0, Data) ->
- list_to_binary(Data);
-mk_rand_bin(N, Data) ->
- mk_rand_bin(N-1, [rand:uniform(256) - 1 | Data]).
-
+ mk_rand_bin_list(Bytes, Binaries-1, [rand:bytes(Bytes) | Acc]).
%% Try provoke DistEntry refc bugs (OTP-17513).
dist_entry_refc_race(_Config) ->
- {ok, Node} = start_node(dist_entry_refc_race, "+zdntgc 1"),
+ {ok, Peer, Node} = ?CT_PEER(["+zdntgc", "1"]),
Pid = spawn_link(Node, ?MODULE, derr_run, [self()]),
{Pid, done} = receive M -> M end,
- stop_node(Node),
+ peer_stop(Peer, Node),
ok.
derr_run(Papa) ->
@@ -3046,42 +3197,425 @@ derr_sender(Main, Nodes) ->
Main ! count,
derr_sender(Main, Nodes).
+is_alive(Config) when is_list(Config) ->
+ %% Test that distribution is up when erlang:is_alive() return true...
+ Args = ["-setcookie", atom_to_list(erlang:get_cookie()),
+ "-pa", filename:dirname(code:which(?MODULE))],
+ {ok, Peer, _} = peer:start_link(#{connection => 0, args => Args}),
+ NodeName = peer:random_name(),
+ LongNames = net_kernel:longnames(),
+ StartOpts = #{name_domain => if LongNames -> longnames;
+ true -> shortnames
+ end},
+ ThisNode = node(),
+ TestFun = fun () -> is_alive_test(list_to_atom(NodeName), StartOpts, ThisNode) end,
+ ok = peer:call(Peer, erlang, apply, [TestFun, []]),
+ Node = list_to_atom(NodeName++"@"++hostname()),
+ true = lists:member(Node, nodes()),
+ peer:stop(Peer),
+ ok.
-%%% Utilities
+is_alive_test(NodeName, StartOpts, TestNode) ->
+ try
+ monitor_node(TestNode, true),
+ error(unexpected_success)
+ catch
+ error:notalive ->
+ ok
+ end,
+ Me = self(),
+ {Pid, Mon} = spawn_monitor(fun () ->
+ Me ! {self(), go},
+ is_alive_tester(TestNode),
+ Me ! {self(), ok}
+ end),
+ receive {Pid, go} -> ok end,
+ receive after 500 -> ok end,
+ _ = net_kernel:start(NodeName, StartOpts),
+ receive
+ {Pid, ok} -> erlang:demonitor(Mon, [flush]), ok;
+ {'DOWN', Mon, process, Pid, Reason} -> error(Reason)
+ end.
-timestamp() ->
- erlang:monotonic_time(millisecond).
+is_alive_tester(Node) ->
+ case erlang:is_alive() of
+ false ->
+ is_alive_tester(Node);
+ true ->
+ monitor_node(Node, true),
+ wait_until(fun () -> lists:member(Node, nodes()) end),
+ ok
+ end.
+
+dyn_node_name_monitor_node(Config) ->
+ %% Test that monitor_node() does not fail when erlang:is_alive() return true
+ %% but we have not yet gotten a name...
+ Args = ["-setcookie", atom_to_list(erlang:get_cookie()),
+ "-pa", filename:dirname(code:which(?MODULE))],
+ {ok, Peer, nonode@nohost} = peer:start_link(#{connection => 0, args => Args}),
+ [] = nodes(),
+ LongNames = net_kernel:longnames(),
+ StartOpts = #{name_domain => if LongNames -> longnames;
+ true -> shortnames
+ end},
+ ThisNode = node(),
+ TestFun = fun () -> dyn_node_name_monitor_node_test(StartOpts, ThisNode) end,
+ ok = peer:call(Peer, erlang, apply, [TestFun, []]),
+ peer:stop(Peer),
+ ok.
+
+dyn_node_name_monitor_node_test(StartOpts, TestNode) ->
+ try
+ monitor_node(TestNode, true),
+ error(unexpected_success)
+ catch
+ error:notalive ->
+ ok
+ end,
+ _ = net_kernel:start(undefined, StartOpts),
+ true = erlang:is_alive(),
+ true = monitor_node(TestNode, true),
+ receive {nodedown, TestNode} -> ok end,
+ true = net_kernel:connect_node(TestNode),
+ true = monitor_node(TestNode, true),
+ true = lists:member(TestNode, nodes(hidden)),
+ receive {nodedown, TestNode} -> error(unexpected_nodedown)
+ after 1000 -> ok
+ end,
+ ok.
+
+
+dyn_node_name_monitor(Config) ->
+ %% Test that monitor() does not fail when erlang:is_alive() return true
+ %% but we have not yet gotten a name...
+ Args = ["-setcookie", atom_to_list(erlang:get_cookie()),
+ "-pa", filename:dirname(code:which(?MODULE))],
+ {ok, Peer, _} = peer:start(#{connection => 0, args => Args}),
+ LongNames = net_kernel:longnames(),
+ StartOpts = #{name_domain => if LongNames -> longnames;
+ true -> shortnames
+ end},
+ ThisNode = node(),
+ TestFun = fun () -> dyn_node_name_monitor_test(StartOpts, ThisNode) end,
+ ok = peer:call(Peer, erlang, apply, [TestFun, []]),
+ peer:stop(Peer),
+ ok.
+
+dyn_node_name_monitor_test(StartOpts, TestNode) ->
+ try
+ monitor(process, {net_kernel, TestNode}),
+ error(unexpected_success)
+ catch
+ error:badarg ->
+ ok
+ end,
+ _ = net_kernel:start(undefined, StartOpts),
+ true = erlang:is_alive(),
+ Mon = monitor(process, {net_kernel, TestNode}),
+ receive
+ {'DOWN', Mon, process, {net_kernel, TestNode}, noconnection} ->
+ ok
+ end,
+ true = net_kernel:connect_node(TestNode),
+ Mon2 = monitor(process, {net_kernel, TestNode}),
+ true = lists:member(TestNode, nodes(hidden)),
+ receive
+ {'DOWN', Mon2, process, {net_kernel, TestNode}, noconnection} ->
+ error(unexpected_down)
+ after
+ 1000 ->
+ ok
+ end,
+ ok.
+
+async_dist_flag(Config) when is_list(Config) ->
+ {ok, Peer1, Node1} = ?CT_PEER(),
+ async_dist_flag_test(Node1, false),
+ peer:stop(Peer1),
+ {ok, Peer2, Node2} = ?CT_PEER(["+pad", "false"]),
+ async_dist_flag_test(Node2, false),
+ peer:stop(Peer2),
+ {ok, Peer3, Node3} = ?CT_PEER(["+pad", "true", "+pad", "false"]),
+ async_dist_flag_test(Node3, false),
+ peer:stop(Peer3),
+
+ {ok, Peer4, Node4} = ?CT_PEER(["+pad", "true"]),
+ async_dist_flag_test(Node4, true),
+ peer:stop(Peer4),
+ {ok, Peer5, Node5} = ?CT_PEER(["+pad", "false", "+pad", "true"]),
+ async_dist_flag_test(Node5, true),
+ peer:stop(Peer5),
-start_node(X) ->
- start_node(X, [], []).
+ ok.
-start_node(X, Y) ->
- start_node(X, Y, []).
+async_dist_flag_test(Node, Default) when is_atom(Node), is_boolean(Default) ->
+ Tester = self(),
+ NotDefault = not Default,
+
+ Default = erpc:call(Node, erlang, system_info, [async_dist]),
+
+ {P1, M1} = spawn_opt(Node, fun () ->
+ receive after infinity -> ok end
+ end, [link, monitor]),
+ {P2, M2} = spawn_opt(Node, fun () ->
+ receive after infinity -> ok end
+ end, [link, monitor, {async_dist, false}]),
+ {P3, M3} = spawn_opt(Node, fun () ->
+ receive after infinity -> ok end
+ end, [link, monitor, {async_dist, true}]),
+ {async_dist, Default} = erpc:call(Node, erlang, process_info, [P1, async_dist]),
+ {async_dist, false} = erpc:call(Node, erlang, process_info, [P2, async_dist]),
+ {async_dist, true} = erpc:call(Node, erlang, process_info, [P3, async_dist]),
+
+ R4 = make_ref(),
+ {P4, M4} = spawn_opt(Node, fun () ->
+ Default = process_flag(async_dist, NotDefault),
+ Tester ! R4,
+ receive after infinity -> ok end
+ end, [link, monitor]),
+
+ R5 = make_ref(),
+ {P5, M5} = spawn_opt(Node, fun () ->
+ false = process_flag(async_dist, true),
+ Tester ! R5,
+ receive after infinity -> ok end
+ end, [link, monitor, {async_dist, false}]),
+ R6 = make_ref(),
+ {P6, M6} = spawn_opt(Node, fun () ->
+ true = process_flag(async_dist, false),
+ Tester ! R6,
+ receive after infinity -> ok end
+ end, [link, monitor, {async_dist, true}]),
+ receive R4 -> ok end,
+ {async_dist, NotDefault} = erpc:call(Node, erlang, process_info, [P4, async_dist]),
+ receive R5 -> ok end,
+ {async_dist, true} = erpc:call(Node, erlang, process_info, [P5, async_dist]),
+ receive R6 -> ok end,
+ {async_dist, false} = erpc:call(Node, erlang, process_info, [P6, async_dist]),
+
+
+ R7 = make_ref(),
+ {P7, M7} = spawn_opt(Node, fun () ->
+ Default = process_flag(async_dist, NotDefault),
+ NotDefault = process_flag(async_dist, NotDefault),
+ NotDefault = process_flag(async_dist, NotDefault),
+ NotDefault = process_flag(async_dist, Default),
+ Default = process_flag(async_dist, Default),
+ Default = process_flag(async_dist, Default),
+ Tester ! R7,
+ receive after infinity -> ok end
+ end, [link, monitor]),
+ receive R7 -> ok end,
+
+ unlink(P1),
+ exit(P1, bang),
+ unlink(P2),
+ exit(P2, bang),
+ unlink(P3),
+ exit(P3, bang),
+ unlink(P4),
+ exit(P4, bang),
+ unlink(P5),
+ exit(P5, bang),
+ unlink(P6),
+ exit(P6, bang),
+ unlink(P7),
+ exit(P7, bang),
+
+ receive {'DOWN', M1, process, P1, bang} -> ok end,
+ receive {'DOWN', M2, process, P2, bang} -> ok end,
+ receive {'DOWN', M3, process, P3, bang} -> ok end,
+ receive {'DOWN', M4, process, P4, bang} -> ok end,
+ receive {'DOWN', M5, process, P5, bang} -> ok end,
+ receive {'DOWN', M6, process, P6, bang} -> ok end,
+ receive {'DOWN', M7, process, P7, bang} -> ok end,
+
+ ok.
+
+async_dist_port_dctrlr(Config) when is_list(Config) ->
+ {ok, RecvPeer, RecvNode} = ?CT_PEER(),
+ ok = async_dist_test(RecvNode),
+ peer:stop(RecvPeer),
+ ok.
-start_node(Name, Args, Rel) when is_atom(Name), is_list(Rel) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Cookie = atom_to_list(erlang:get_cookie()),
- RelArg = case Rel of
- [] -> [];
- _ -> [{erl,[{release,Rel}]}]
+async_dist_proc_dctrlr(Config) when is_list(Config) ->
+ {ok, SendPeer, SendNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
+ {ok, RecvPeer, RecvNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
+ {Pid, Mon} = spawn_monitor(SendNode,
+ fun () ->
+ ok = async_dist_test(RecvNode),
+ exit(test_success)
+ end),
+ receive
+ {'DOWN', Mon, process, Pid, Reason} ->
+ test_success = Reason
+ end,
+ peer:stop(SendPeer),
+ peer:stop(RecvPeer),
+ ok.
+
+async_dist_test(Node) ->
+ Scale = case round(test_server:timetrap_scale_factor()/3) of
+ S when S < 1 -> 1;
+ S -> S
+ end,
+ _ = process_flag(async_dist, false),
+ Tester = self(),
+ AliveReceiver1 = spawn_link(Node, fun () ->
+ register(alive_receiver_1, self()),
+ Tester ! {registered, self()},
+ receive after infinity -> ok end
+ end),
+ receive {registered, AliveReceiver1} -> ok end,
+ AliveReceiver2 = spawn(Node, fun () -> receive after infinity -> ok end end),
+ {AliveReceiver3, AR3Mon} = spawn_monitor(Node,
+ fun () ->
+ receive after infinity -> ok end
+ end),
+ {DeadReceiver, DRMon} = spawn_monitor(Node, fun () -> ok end),
+ receive
+ {'DOWN', DRMon, process, DeadReceiver, DRReason} ->
+ normal = DRReason
+ end,
+ Data = lists:duplicate($x, 256),
+ GoNuts = fun GN () ->
+ DeadReceiver ! hello,
+ GN()
end,
- test_server:start_node(Name, slave,
- [{args,
- 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)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive])))),
- start_node(Name, Args, Rel).
-
-stop_node(Node) ->
+ erpc:call(Node, erts_debug, set_internal_state, [available_internal_state, true]),
+ erpc:cast(Node, erts_debug, set_internal_state, [block, 4000*Scale]),
+ DistBufFiller = spawn_link(fun () ->
+ process_flag(async_dist, false),
+ receive go_nuts -> ok end,
+ GoNuts()
+ end),
+ BDMon = spawn_link(fun SysMon () ->
+ receive
+ {monitor, Pid, busy_dist_port, _} ->
+ Tester ! {busy_dist_port, Pid}
+ end,
+ SysMon()
+ end),
+ _ = erlang:system_monitor(BDMon, [busy_dist_port]),
+ DistBufFiller ! go_nuts,
+
+ %% Busy dist entry may release after it has triggered even
+ %% though noone is consuming anything at the receiving end.
+ %% Continue banging until we stop getting new busy_dist_port...
+ WaitFilled = fun WF (Tmo) ->
+ receive
+ {busy_dist_port, DistBufFiller} ->
+ WF(1000*Scale)
+ after
+ Tmo ->
+ ok
+ end
+ end,
+ WaitFilled(infinity),
+
+ BusyDistChecker = spawn_link(fun () ->
+ process_flag(async_dist, false),
+ DeadReceiver ! hello,
+ exit(unexpected_return_from_bang)
+ end),
+ receive {busy_dist_port, BusyDistChecker} -> ok end,
+ {async_dist, false} = process_info(self(), async_dist),
+ {async_dist, false} = process_info(BusyDistChecker, async_dist),
+ false = process_flag(async_dist, true),
+ {async_dist, true} = process_info(self(), async_dist),
+
+ Start = erlang:monotonic_time(millisecond),
+ M1 = erlang:monitor(process, AliveReceiver1),
+ true = is_reference(M1),
+ M2 = erlang:monitor(process, AliveReceiver2),
+ true = is_reference(M2),
+ {pid, Data} = AliveReceiver1 ! {pid, Data},
+ {reg_name, Data} = {alive_receiver_1, Node} ! {reg_name, Data},
+ true = erlang:demonitor(M1),
+ true = link(AliveReceiver2),
+ true = unlink(AliveReceiver1),
+ RId = spawn_request(Node, fun () -> receive bye -> ok end end, [link, monitor]),
+ true = is_reference(RId),
+ erlang:group_leader(self(), AliveReceiver2),
+ AR3XReason = make_ref(),
+ true = exit(AliveReceiver3, AR3XReason),
+ End = erlang:monotonic_time(millisecond),
+
+ %% These signals should have been buffered immediately. Make sure
+ %% it did not take a long time...
+ true = 500*Scale >= End - Start,
+
+ receive after 500*Scale -> ok end,
+
+ unlink(BusyDistChecker),
+ exit(BusyDistChecker, bang),
+ false = is_process_alive(BusyDistChecker),
+
+ unlink(DistBufFiller),
+ exit(DistBufFiller, bang),
+ false = is_process_alive(DistBufFiller),
+
+ %% Verify that the signals eventually get trough when the other
+ %% node continue to work...
+ {links, []}
+ = erpc:call(Node, erlang, process_info, [AliveReceiver1, links]),
+ {links, [Tester]}
+ = erpc:call(Node, erlang, process_info, [AliveReceiver2, links]),
+ {monitored_by, []}
+ = erpc:call(Node, erlang, process_info, [AliveReceiver1, monitored_by]),
+ {monitored_by, [Tester]}
+ = erpc:call(Node, erlang, process_info, [AliveReceiver2, monitored_by]),
+ {messages, [{pid, Data}, {reg_name, Data}]}
+ = erpc:call(Node, erlang, process_info, [AliveReceiver1, messages]),
+ {group_leader, Tester}
+ = erpc:call(Node, erlang, process_info, [AliveReceiver2, group_leader]),
+
+ Spawned = receive
+ {spawn_reply, RId, SpawnRes, Pid} ->
+ ok = SpawnRes,
+ true = is_pid(Pid),
+ Pid
+ end,
+ {links, [Tester]}
+ = erpc:call(Node, erlang, process_info, [Spawned, links]),
+ {monitored_by, [Tester]}
+ = erpc:call(Node, erlang, process_info, [Spawned, monitored_by]),
+
+ receive
+ {'DOWN', AR3Mon, process, AliveReceiver3, ActualAR3XReason} ->
+ AR3XReason = ActualAR3XReason
+ end,
+
+ unlink(AliveReceiver2),
+ unlink(Spawned),
+
+ true = process_flag(async_dist, false),
+ {async_dist, false} = process_info(self(), async_dist),
+
+ ok.
+
+%%% Utilities
+
+wait_until(Fun) ->
+ wait_until(Fun, 24*60*60*1000).
+
+wait_until(Fun, Timeout) when Timeout < 0 ->
+ timeout;
+wait_until(Fun, Timeout) ->
+ case catch Fun() of
+ true ->
+ ok;
+ _ ->
+ receive after 50 -> ok end,
+ wait_until(Fun, Timeout-50)
+ end.
+
+timestamp() ->
+ erlang:monotonic_time(millisecond).
+
+peer_stop(Peer, Node) ->
verify_nc(Node),
- test_server:stop_node(Node).
+ peer:stop(Peer).
verify_nc(Node) ->
P = self(),
@@ -3117,81 +3651,6 @@ freeze_node(Node, MS) ->
receive DoingIt -> ok end,
receive after Own -> ok end.
-inet_rpc_nodename({N,H,_Sock}) ->
- list_to_atom(N++"@"++H).
-
-do_inet_rpc({_,_,Sock},M,F,A) ->
- Bin = term_to_binary({M,F,A}),
- gen_tcp:send(Sock,Bin),
- case gen_tcp:recv(Sock,0) of
- {ok, Bin2} ->
- T = binary_to_term(Bin2),
- {ok,T};
- Else ->
- {error, Else}
- end.
-
-inet_rpc_server([Host, PortList]) ->
- Port = list_to_integer(PortList),
- {ok, Sock} = gen_tcp:connect(Host, Port,[binary, {packet, 4},
- {active, false}]),
- inet_rpc_server_loop(Sock).
-
-inet_rpc_server_loop(Sock) ->
- case gen_tcp:recv(Sock,0) of
- {ok, Bin} ->
- {M,F,A} = binary_to_term(Bin),
- Res = (catch apply(M,F,A)),
- RB = term_to_binary(Res),
- gen_tcp:send(Sock,RB),
- inet_rpc_server_loop(Sock);
- _ ->
- erlang:halt()
- end.
-
-
-start_relay_node(Node, Args) ->
- start_relay_node(Node, Args, []).
-start_relay_node(Node, Args, Env) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Cookie = "NOT"++atom_to_list(erlang:get_cookie()),
- {ok, LSock} = gen_tcp:listen(0, [binary, {packet, 4}, {active, false}]),
- {ok, Port} = inet:port(LSock),
- {ok, Host} = inet:gethostname(),
- RunArg = "-run " ++ atom_to_list(?MODULE) ++ " inet_rpc_server " ++
- Host ++ " " ++ integer_to_list(Port),
- {ok, NN} = test_server:start_node(Node, peer,
- [{env,Env},
- {args, Args ++
- " -setcookie "++Cookie++" -pa "++Pa++" "++
- RunArg}]),
- [N,H] = string:lexemes(atom_to_list(NN),"@"),
- {ok, Sock} = gen_tcp:accept(LSock),
- pang = net_adm:ping(NN),
- {N,H,Sock}.
-
-stop_relay_node({N,H,Sock}) ->
- catch do_inet_rpc(Sock,erlang,halt,[]),
- catch gen_tcp:close(Sock),
- wait_dead(N,H,10).
-
-wait_dead(N,H,0) ->
- {error,{not_dead,N,H}};
-wait_dead(N,H,X) ->
- case erl_epmd:port_please(N,H) of
- {port,_,_} ->
- receive
- after 1000 ->
- ok
- end,
- wait_dead(N,H,X-1);
- noport ->
- ok;
- Else ->
- {error, {unexpected, Else}}
- end.
-
-
start_node_monitors(Nodes) ->
Master = self(),
lists:foreach(fun (Node) ->
@@ -3298,13 +3757,6 @@ from(_, []) -> [].
%% fun_spawn(Fun, Args) ->
%% spawn_link(erlang, apply, [Fun, Args]).
-
-long_or_short() ->
- case net_kernel:longnames() of
- true -> " -name ";
- false -> " -sname "
- end.
-
until(Fun) ->
case Fun() of
true ->
@@ -3517,5 +3969,3 @@ free_memory() ->
error : undef ->
ct:fail({"os_mon not built"})
end.
-
-
diff --git a/erts/emulator/test/distribution_SUITE_data/run.erl b/erts/emulator/test/distribution_SUITE_data/run.erl
index f574b2c02c..4ebf600737 100644
--- a/erts/emulator/test/distribution_SUITE_data/run.erl
+++ b/erts/emulator/test/distribution_SUITE_data/run.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ start() ->
do_it() ->
{ok, _} = net_kernel:start([fideridum,shortnames]),
- {ok, Node} = slave:start(host(), heppel),
+ {ok, _Peer, Node} = peer:start(#{name => peer:random_name(heppel)}),
P = spawn(Node, net_kernel, stop, []),
B1 = term_to_binary(P),
N1 = node(P),
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index b4d1e94d41..1a512e0544 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -84,7 +84,6 @@
env/1,
poll_pipe/1,
lots_of_used_fds_on_boot/1,
- lots_of_used_fds_on_boot_slave/1,
z_test/1]).
-export([bin_prefix/2]).
@@ -124,7 +123,7 @@
-define(heap_binary_size, 64).
suite() ->
- [{ct_hooks,[ts_install_cth]},
+ [{ct_hooks,[cth_log_redirect,ts_install_cth]},
{timetrap, {minutes, 1}}].
all() -> %% Keep a_test first and z_test last...
@@ -172,22 +171,47 @@ groups() ->
ioq_exit_timeout_async]}].
init_per_suite(Config) ->
+ logger:add_handler_filter(default,
+ checkio_filter,
+ {fun F(#{ msg := {string,Str}} = Log, _State) ->
+ case re:run(Str,"(fds in pollset)|(Bad value on output port)") of
+ {match,_} ->
+ stop;
+ _ ->
+ Log
+ end;
+ F(#{ msg := {Fmt,Args}} = Log, State) when not is_atom(Fmt) ->
+ F(Log#{ msg := {string,io_lib:format(Fmt,Args)}}, State);
+ F(Log, _State) ->
+ Log
+ end, undefined}),
Config.
end_per_suite(_Config) ->
- catch erts_debug:set_internal_state(available_internal_state, false).
+ logger:remove_handler_filter(default, checkio_filter),
+ catch erts_debug:set_internal_state(available_internal_state, false),
+
+ case nodes(connected) of
+ [] -> ok;
+ Nodes ->
+ [net_kernel:disconnect(N) || N <- Nodes],
+ io:format("LEAKED connections: ~p\n", [Nodes])
+ end.
+
init_per_group(poll_thread, Config) ->
- [{node_args, "+IOt 2"} | Config];
+ [{node_args, ["+IOt", "2"]} | Config];
init_per_group(poll_set, Config) ->
- [{node_args, "+IOt 2 +IOp 2"} | Config];
+ [{node_args, ["+IOt", "2", "+IOp", "2"]} | Config];
init_per_group(polling, Config) ->
case proplists:get_value(node_args, Config) of
undefined ->
Config;
Args ->
- {ok, Node} = start_node(polling, Args),
- [{node, Node} | Config]
+ {ok, Peer, Node} = ?CT_PEER(Args),
+ unlink(Peer), %% otherwise it will immediately stop
+ setup_logger(Node),
+ [{node, {Peer, Node}} | Config]
end;
init_per_group(_GroupName, Config) ->
Config.
@@ -195,11 +219,11 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
case proplists:get_value(node, Config) of
undefined ->
- ok;
- Node ->
- stop_node(Node)
- end,
- Config.
+ Config;
+ {Peer, _Node} ->
+ ok = peer:stop(Peer),
+ {save_config, proplists:delete(node, Config)}
+ end.
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
CIOD = rpc(Config,
@@ -210,12 +234,13 @@ init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
end,
erts_debug:get_internal_state(check_io_debug)
end),
- erlang:display({init_per_testcase, Case}),
0 = element(1, CIOD),
[{testcase, Case}|Config].
end_per_testcase(Case, Config) ->
- erlang:display({end_per_testcase, Case}),
+ %% Logs some info about the system
+ ct_os_cmd("epmd -names"),
+ ct_os_cmd("ps aux"),
try rpc(Config, fun() ->
get_stable_check_io_info(),
erts_debug:get_internal_state(check_io_debug)
@@ -223,25 +248,23 @@ end_per_testcase(Case, Config) ->
CIOD ->
0 = element(1, CIOD)
catch _E:_R:_ST ->
- %% Logs some info about the system
- ct_os_cmd("epmd -names"),
- ct_os_cmd("ps aux"),
%% Restart the node
case proplists:get_value(node, Config) of
undefined ->
ok;
- Node ->
- timer:sleep(1000), %% Give the node time to die
- [NodeName, _] = string:lexemes(atom_to_list(Node),"@"),
- {ok, Node} = start_node_final(
- list_to_atom(NodeName),
- proplists:get_value(node_args, Config))
+ {Peer, _Node} ->
+ peer:stop(Peer),
+ {ok, Peer2, Node2} = ?CT_PEER(proplists:get_value(node_args, Config)),
+ unlink(Peer2), %% otherwise it will immediately stop
+ setup_logger(Node2),
+ Config2 = [{node, {Peer2, Node2}} | proplists:delete(node, Config)],
+ {save_config, Config2}
end
end,
ok.
ct_os_cmd(Cmd) ->
- ct:log("~s: ~s",[Cmd,os:cmd(Cmd)]).
+ ct:log("~s: ~ts",[Cmd,os:cmd(Cmd)]).
%% Test sending bad types to port with an outputv-capable driver.
outputv_errors(Config) when is_list(Config) ->
@@ -535,7 +558,7 @@ timer_delay(Config) when is_list(Config) ->
stop_driver(Port, Name),
ok.
-%% Test that driver_set_timer with new timout really changes
+%% Test that driver_set_timer with new timeout really changes
%% the timer (ticket OTP-5942), it didn't work before
timer_change(Config) when is_list(Config) ->
@@ -1014,12 +1037,11 @@ chkio_test({erts_poll_info, Before},
chk_chkio_port(Port),
Fun(),
During = get_check_io_total(erlang:system_info(check_io)),
- erlang:display(During),
[0 = element(1, erts_debug:get_internal_state(check_io_debug)) ||
%% The pollset is not stable when running the fallback testcase
Test /= ?CHKIO_USE_FALLBACK_POLLSET],
- io:format("During test: ~p~n", [During]),
+ ct:log("During test: ~p~n", [During]),
chk_chkio_port(Port),
case erlang:port_control(Port, ?CHKIO_STOP, "") of
Res when is_list(Res) ->
@@ -1087,7 +1109,7 @@ get_stable_check_io_info(N) ->
%% Merge return from erlang:system_info(check_io)
%% as if it was one big pollset.
get_check_io_total(ChkIo) ->
- ct:log("ChkIo = ~p~n",[ChkIo]),
+ ct:log("ChkIo = ~p (~p)~n",[ChkIo, nodes()]),
{Fallback, Rest} = get_fallback(ChkIo),
OnlyPollThreads = [PS || PS <- Rest, not is_scheduler_pollset(PS)],
add_fallback_infos(Fallback,
@@ -1155,7 +1177,7 @@ tag_type(poll_threads) -> sum.
%% driver that didn't use the same lock. The lock checker
%% used to trigger on this and dump core.
otp_6602(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
Done = make_ref(),
Parent = self(),
Tester = spawn_link(Node,
@@ -1170,7 +1192,7 @@ otp_6602(Config) when is_list(Config) ->
end),
receive Done -> ok end,
unlink(Tester),
- stop_node(Node),
+ peer:stop(Peer),
ok.
-define(EXPECTED_SYSTEM_INFO_NAMES1,
@@ -1869,68 +1891,20 @@ lots_of_used_fds_on_boot_test(Config) ->
%% open. This used to hang the whole VM at boot in
%% an eternal loop trying to figure out how to size
%% arrays in erts_poll() implementation.
- Name = lots_of_used_fds_on_boot,
- HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end,
- atom_to_list(node())),
- FullName = list_to_atom(atom_to_list(Name) ++ HostSuffix),
- Pa = filename:dirname(code:which(?MODULE)),
Prog = case catch init:get_argument(progname) of
{ok,[[P]]} -> P;
_ -> exit(no_progname_argument_found)
end,
- NameSw = case net_kernel:longnames() of
- false -> "-sname ";
- true -> "-name ";
- _ -> exit(not_distributed_node)
- end,
- {ok, Pwd} = file:get_cwd(),
- NameStr = atom_to_list(Name),
DataDir = proplists:get_value(data_dir, Config),
Wrapper = filename:join(DataDir, "lots_of_fds_used_wrapper"),
- CmdLine = Wrapper ++ " " ++ Prog ++ " -noshell -noinput "
- ++ NameSw ++ " " ++ NameStr ++ " "
- ++ "-pa " ++ Pa ++ " "
- ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr ++ " "
- ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()) ++ " "
- ++ "-s " ++ atom_to_list(?MODULE) ++ " lots_of_used_fds_on_boot_slave "
- ++ atom_to_list(node()),
- io:format("Starting node ~p: ~s~n", [FullName, CmdLine]),
- net_kernel:monitor_nodes(true),
- Port = case open_port({spawn, CmdLine}, [exit_status]) of
- Prt when is_port(Prt) ->
- Prt;
- OPError ->
- exit({failed_to_start_node, {open_port_error, OPError}})
- end,
- receive
- {Port, {exit_status, 17}} ->
- {skip, "Cannot open enough fds to test this"};
- {Port, {exit_status, Error}} ->
- exit({failed_to_start_node, {exit_status, Error}});
- {nodeup, FullName} ->
- io:format("~p connected!~n", [FullName]),
- FullName = rpc:call(FullName, erlang, node, []),
- rpc:cast(FullName, erlang, halt, []),
- receive
- {Port, {exit_status, 0}} ->
- ok;
- {Port, {exit_status, Error}} ->
- exit({unexpected_exit_status, Error})
- after 5000 ->
- exit(missing_exit_status)
- end
- after 5000 ->
- exit(connection_timeout)
+ try
+ {ok, Peer, _Node} = ?CT_PEER(#{connection => standard_io, exec => {Wrapper, [Prog]}}),
+ peer:stop(Peer)
+ catch
+ exit:{boot_failed, {exit_status, 17}} ->
+ {skip, "Cannot open enough fds to test this"}
end.
-lots_of_used_fds_on_boot_slave([Master]) ->
- erlang:monitor_node(Master, true),
- receive
- {nodedown, Master} ->
- erlang:halt()
- end,
- ok.
-
thread_mseg_alloc_cache_clean(Config) when is_list(Config) ->
case {erlang:system_info(threads),
erlang:system_info({allocator,mseg_alloc}),
@@ -2131,12 +2105,11 @@ async_blast(Config) when is_list(Config) ->
end, Ps),
End = os:timestamp(),
MemAfter = driver_alloc_size(),
- io:format("MemBefore=~p, MemMid=~p, MemAfter=~p~n",
+ ct:log("MemBefore=~p, MemMid=~p, MemAfter=~p~n",
[MemBefore, MemMid, MemAfter]),
AsyncBlastTime = timer:now_diff(End,Start)/1000000,
- io:format("AsyncBlastTime=~p~n", [AsyncBlastTime]),
+ ct:log("AsyncBlastTime=~p~n", [AsyncBlastTime]),
MemBefore = MemAfter,
- erlang:display({async_blast_time, AsyncBlastTime}),
ok.
thr_msg_blast_receiver(_Port, N, N) ->
@@ -2187,13 +2160,12 @@ thr_msg_blast(Config) when is_list(Config) ->
ok
end,
MemAfter = driver_alloc_size(),
- io:format("MemBefore=~p, MemAfter=~p~n",
+ ct:log("MemBefore=~p, MemAfter=~p~n",
[MemBefore, MemAfter]),
ThrMsgBlastTime = timer:now_diff(End,Start)/1000000,
- io:format("ThrMsgBlastTime=~p~n", [ThrMsgBlastTime]),
+ ct:log("ThrMsgBlastTime=~p~n", [ThrMsgBlastTime]),
MemBefore = MemAfter,
Res = {thr_msg_blast_time, ThrMsgBlastTime},
- erlang:display(Res),
Res.
-define(IN_RANGE(LoW_, VaLuE_, HiGh_),
@@ -2223,7 +2195,7 @@ consume_timeslice(Config) when is_list(Config) ->
%% scheduling counts.
%%
%% When signal is delivered immediately we must take into account
- %% that process and port are "virtualy" scheduled out and in
+ %% that process and port are "virtually" scheduled out and in
%% in the trace generated.
%%
%% Port ! {_, {command, _}, and port_command() differs. The send
@@ -2454,8 +2426,7 @@ count_pp_sched_stop(Ps) ->
PNs = lists:map(fun (P) -> {P, 0} end, Ps),
receive {trace_delivered, all, Td} -> ok end,
Res = count_proc_sched(Ps, PNs),
- io:format("Scheduling counts: ~p~n", [Res]),
- erlang:display({scheduling_counts, Res}),
+ ct:log("Scheduling counts: ~p~n", [Res]),
Res.
do_inc_pn(_P, []) ->
@@ -2560,8 +2531,9 @@ check_io_debug() ->
has_gethost() ->
has_gethost(erlang:ports()).
has_gethost([P|T]) ->
- case erlang:port_info(P, name) of
- {name,"inet_gethost"++_} ->
+ {name, Name} = erlang:port_info(P, name),
+ case filename:basename(Name) of
+ "inet_gethost"++_ ->
true;
_ ->
has_gethost(T)
@@ -2649,7 +2621,7 @@ make_refc_binaries(Term) ->
transform_bins(F, Term).
build_binary(Elements) ->
- list_to_binary(build_list(Elements)).
+ rand:bytes(Elements).
build_list(Elements) -> build_list(Elements, []).
@@ -2733,32 +2705,14 @@ sleep(Ms) when is_integer(Ms), Ms >= 0 ->
receive after Ms -> ok end.
-start_node(Config) when is_list(Config) ->
- start_node(proplists:get_value(testcase, Config));
-start_node(Name) ->
- start_node(Name, "").
-start_node(NodeName, Args) ->
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(NodeName)
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- start_node_final(Name, Args).
-start_node_final(Name, Args) ->
+setup_logger(Node) ->
{ok, Pwd} = file:get_cwd(),
- FinalArgs = [Args, " -pa ", filename:dirname(code:which(?MODULE))],
- {ok, Node} = test_server:start_node(Name, slave, [{args, FinalArgs}]),
- LogPath = Pwd ++ "/error_log." ++ atom_to_list(Name),
+ Name = hd(string:lexemes(atom_to_list(Node), "@")),
+ LogPath = filename:join(Pwd, "error_log." ++ Name),
ct:pal("Logging to: ~s", [LogPath]),
rpc:call(Node, logger, add_handler, [file_handler, logger_std_h,
#{formatter => {logger_formatter,#{ single_line => false }},
- config => #{file => LogPath }}]),
- {ok, Node}.
-
-stop_node(Node) ->
- test_server:stop_node(Node).
+ config => #{file => LogPath }}]).
wait_deallocations() ->
try
@@ -2776,7 +2730,8 @@ rpc(Config, Fun) ->
case proplists:get_value(node, Config) of
undefined ->
Fun();
- Node ->
+ {_Peer, Node} ->
+ ct:log("Running RPC ~p on ~p/~p~n", [Fun, _Peer, Node]),
Self = self(),
Ref = make_ref(),
Pid = spawn(Node,
diff --git a/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c b/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c
index 6750b8a78b..f1fee767f0 100644
--- a/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c
+++ b/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c
@@ -22,7 +22,7 @@
*
* Description: Implementation of a driver that fakes driver version. It
* is used for checking that version mismatches are handled
- * correct by the emulator. The following makros have to be
+ * correct by the emulator. The following macros have to be
* defined before it can be used:
* * VSN_MISMATCH_DRV_NAME_STR
* * VSN_MISMATCH_DRV_NAME
diff --git a/erts/emulator/test/dump_SUITE.erl b/erts/emulator/test/dump_SUITE.erl
index 654b1c45a5..926e32d216 100644
--- a/erts/emulator/test/dump_SUITE.erl
+++ b/erts/emulator/test/dump_SUITE.erl
@@ -55,7 +55,7 @@ init_per_testcase(_, Config) ->
end_per_testcase(_, Config) ->
- Config.
+ erts_test_utils:ept_check_leaked_nodes(Config).
%%%
%%% The test cases -------------------------------------------------------------
@@ -67,7 +67,7 @@ signal_abort(Config) ->
Dump = filename:join(proplists:get_value(priv_dir, Config),"signal_abort.dump"),
- {ok, Node} = start_node(Config),
+ {ok, _Peer, Node} = ?CT_PEER(),
false = rpc:call(Node, erts_debug, set_internal_state,
[available_internal_state, true]),
@@ -118,7 +118,7 @@ load() ->
exiting_dump(Config) when is_list(Config) ->
Dump = filename:join(proplists:get_value(priv_dir, Config),"signal_abort.dump"),
- {ok, Node} = start_node(Config),
+ {ok, _Peer, Node} = ?CT_PEER(),
Self = self(),
@@ -129,12 +129,13 @@ exiting_dump(Config) when is_list(Config) ->
[ets:insert(T,{I,I}) || I <- lists:seq(1,1000)]
end || _ <- lists:seq(1,1000)],
Self ! ready,
- receive ok -> ok end
+ receive {terminate, Pid} -> Pid ! ok end
end),
true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]),
- receive ready -> unlink(Pid), Pid ! ok end,
+ receive ready -> unlink(Pid), Pid ! {terminate, self()} end,
+ receive ok -> ok end,
rpc:call(Node, erlang, halt, ["dump"]),
@@ -154,8 +155,8 @@ exiting_dump(Config) when is_list(Config) ->
free_dump(Config) when is_list(Config) ->
Dump = filename:join(proplists:get_value(priv_dir, Config),"signal_abort.dump"),
- {ok, NodeA} = start_node(Config),
- {ok, NodeB} = start_node(Config),
+ {ok, _PeerA, NodeA} = ?CT_PEER(),
+ {ok, PeerB, NodeB} = ?CT_PEER(),
Self = self(),
@@ -209,14 +210,14 @@ free_dump(Config) when is_list(Config) ->
unlink(PidB),
- rpc:call(NodeB, erlang, halt, [0]),
+ peer:stop(PeerB),
ok.
%% Test that crash dumping works when heart is used
heart_dump(Config) ->
Dump = filename:join(proplists:get_value(priv_dir, Config),"heart.dump"),
- {ok, Node} = start_node(Config,"-heart"),
+ {ok, _Peer, Node} = ?CT_PEER(#{ args => ["-heart"] }),
true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]),
true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP_SECONDS","10"]),
rpc:call(Node, erlang, halt, ["dump"]),
@@ -226,7 +227,7 @@ heart_dump(Config) ->
%% Test that there is no crash dump if heart is used and DUMP_SECONDS is not set
heart_no_dump(Config) ->
Dump = filename:join(proplists:get_value(priv_dir, Config),"heart_no.dump"),
- {ok, Node} = start_node(Config,"-heart"),
+ {ok, _Peer, Node} = ?CT_PEER(#{ args => ["-heart"] }),
true = rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP",Dump]),
true = rpc:call(Node, os, unsetenv, ["ERL_CRASH_DUMP_SECONDS"]),
rpc:call(Node, erlang, halt, ["dump"]),
@@ -253,16 +254,3 @@ get_dump_when_done(Dump, Sz) ->
{ok, #file_info{ size = NewSz }} ->
get_dump_when_done(Dump, NewSz)
end.
-
-start_node(Config) when is_list(Config) ->
- start_node(Config, "").
-start_node(Config, Extra) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Extra}]).
diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl
index 075051753b..753c41cc1d 100644
--- a/erts/emulator/test/efile_SUITE.erl
+++ b/erts/emulator/test/efile_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
-module(efile_SUITE).
-export([all/0, suite/0]).
+-export([init_per_testcase/2, end_per_testcase/2]).
-export([iter_max_files/1, proc_zero_sized_files/1]).
-export([do_iter_max_files/2]).
@@ -31,6 +32,12 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[iter_max_files, proc_zero_sized_files].
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
%%
%% Open as many files as possible. Do this several times and check
%% that we get the same number of files every time.
@@ -52,11 +59,9 @@ iter_max_files_1(Config) ->
N = 10
end,
%% Run on a different node in order to make the test more stable.
- Dir = filename:dirname(code:which(?MODULE)),
- {ok,Node} = test_server:start_node(test_iter_max_files,slave,
- [{args,"-pa " ++ Dir}]),
+ {ok, Peer, Node} = ?CT_PEER(),
L = rpc:call(Node,?MODULE,do_iter_max_files,[N, TestFile]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
io:format("Number of files opened in each test:~n~w\n", [L]),
verify_max_files(L),
Head = hd(L),
diff --git a/erts/emulator/test/emulator_bench.spec b/erts/emulator/test/emulator_bench.spec
index 8b1bb71a40..a6d07be6db 100644
--- a/erts/emulator/test/emulator_bench.spec
+++ b/erts/emulator/test/emulator_bench.spec
@@ -2,3 +2,4 @@
{groups,"../emulator_test",binary_SUITE,[iolist_size_benchmarks]}.
{groups,"../emulator_test",erts_debug_SUITE,[interpreter_size_bench]}.
{groups,"../emulator_test",hash_SUITE,[phash2_benchmark]}.
+{groups,"../emulator_test",map_SUITE,[benchmarks]}.
diff --git a/erts/emulator/test/emulator_gh.spec b/erts/emulator/test/emulator_gh.spec
new file mode 100644
index 0000000000..22f627f6fe
--- /dev/null
+++ b/erts/emulator/test/emulator_gh.spec
@@ -0,0 +1,4 @@
+{enable_builtin_hooks, false}.
+{suites,"../emulator_test",all}.
+{skip_groups,"../emulator_test",hash_SUITE,[phash2_benchmark],"Benchmark only"}.
+{skip_cases,"../emulator_test",nif_SUITE,[t_dynamic_resource_call],"Unstable TC"}.
diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c b/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c
index 8ceb9eff08..7b07ae4dfe 100644
--- a/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c
+++ b/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c
@@ -242,11 +242,11 @@ testcase_run(TestCaseState_t *tcs)
ASSERT_CLNUP(tcs, tres[1] == &res_tf1, erl_drv_mutex_unlock(mtx));
ASSERT_CLNUP(tcs, res_tf1 == 1, erl_drv_mutex_unlock(mtx));
- /* Test signaling when noone waits */
+ /* Test signaling when no one waits */
erl_drv_cond_signal(cnd);
- /* Test broadcasting when noone waits */
+ /* Test broadcasting when no one waits */
erl_drv_cond_broadcast(cnd);
diff --git a/erts/emulator/test/erl_link_SUITE.erl b/erts/emulator/test/erl_link_SUITE.erl
index de2a62d812..0e3829c275 100644
--- a/erts/emulator/test/erl_link_SUITE.erl
+++ b/erts/emulator/test/erl_link_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -91,8 +91,8 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
end,
Config.
-end_per_testcase(_Func, _Config) ->
- ok.
+end_per_testcase(_Func, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
init_per_suite(Config) ->
Config.
@@ -111,8 +111,8 @@ links(Config) when is_list(Config) ->
%% Tests distributed links
dist_links(Config) when is_list(Config) ->
- [NodeName] = get_names(1, dist_link),
- {ok, Node} = start_node(NodeName),
+ {ok, _Peer, Node} = ?CT_PEER(),
+ rpc:call(Node, erts_debug, set_internal_state, [available_internal_state, true]),
common_link_test(node(), Node),
TP4 = spawn(?MODULE, test_proc, []),
TP5 = spawn(?MODULE, test_proc, []),
@@ -174,11 +174,11 @@ common_link_test(NodeA, NodeB) ->
%% Tests monitor of nodes
monitor_nodes(Config) when is_list(Config) ->
- [An, Bn, Cn, Dn] = get_names(4, dist_link),
- {ok, A} = start_node(An),
- {ok, B} = start_node(Bn),
- C = list_to_atom(lists:concat([Cn, "@", hostname()])),
- D = list_to_atom(lists:concat([Dn, "@", hostname()])),
+ {ok, PeerA, A} = ?CT_PEER(),
+ {ok, PeerB, B} = ?CT_PEER(),
+ [_, HostName] = string:lexemes(atom_to_list(node()), "@"),
+ C = list_to_atom(peer:random_name(?MODULE_STRING) ++ "@" ++ HostName),
+ D = list_to_atom(peer:random_name(?MODULE_STRING) ++ "@" ++ HostName),
0 = no_of_monitor_node(self(), A),
0 = no_of_monitor_node(self(), B),
monitor_node(A, true),
@@ -212,11 +212,11 @@ monitor_nodes(Config) when is_list(Config) ->
check_monitor_node(self(), C, 0),
check_monitor_node(self(), D, 0),
- stop_node(A),
+ peer:stop(PeerA),
receive {nodedown, A} -> ok end,
check_monitor_node(self(), A, 0),
check_monitor_node(self(), B, 3),
- stop_node(B),
+ peer:stop(PeerB),
receive {nodedown, B} -> ok end,
receive {nodedown, B} -> ok end,
receive {nodedown, B} -> ok end,
@@ -235,7 +235,8 @@ process_monitors(Config) when is_list(Config) ->
common_process_monitors(node(), node()),
Mon1 = erlang:monitor(process,self()),
[] = find_erl_monitor(self(), Mon1),
- [Name] = get_names(1, process_monitors),
+ Name = list_to_atom(lists:concat([?FUNCTION_NAME,
+ integer_to_list(erlang:unique_integer([positive]))])),
true = register(Name, self()),
Mon2 = erlang:monitor(process, Name),
[] = find_erl_monitor(self(), Mon2),
@@ -252,8 +253,8 @@ process_monitors(Config) when is_list(Config) ->
%% Tests distributed process monitors
dist_process_monitors(Config) when is_list(Config) ->
- [Name] = get_names(1,dist_process_monitors),
- {ok, Node} = start_node(Name),
+ {ok, _Peer, Node} = ?CT_PEER(),
+ rpc:call(Node, erts_debug, set_internal_state, [available_internal_state, true]),
common_process_monitors(node(), Node),
TP1 = spawn(Node, ?MODULE, test_proc, []),
R1 = erlang:monitor(process, TP1),
@@ -280,7 +281,8 @@ common_process_monitors(NodeA, NodeB) ->
run_common_process_monitors(TP1, TP2),
TP3 = spawn(NodeA, ?MODULE, test_proc, []),
TP4 = spawn(NodeB, ?MODULE, test_proc, []),
- [TP4N] = get_names(1, common_process_monitors),
+ TP4N = list_to_atom(lists:concat([?FUNCTION_NAME,
+ integer_to_list(erlang:unique_integer([positive]))])),
true = tp_call(TP4, fun () -> register(TP4N,self()) end),
run_common_process_monitors(TP3,
case node() == node(TP4) of
@@ -337,8 +339,7 @@ busy_dist_port_monitor(Config) when is_list(Config) ->
_ -> false
end,
- [An] = get_names(1, busy_dist_port_monitor),
- {ok, A} = start_node(An),
+ {ok, PeerA, A} = ?CT_PEER(),
TP1 = spawn(A, ?MODULE, test_proc, []),
%% Check monitor over busy port
M1 = suspend_on_busy_test(A,
@@ -367,7 +368,7 @@ busy_dist_port_monitor(Config) when is_list(Config) ->
end
end),
tp_cast(TP1, fun () -> exit(normal) end),
- stop_node(A),
+ peer:stop(PeerA),
stop_busy_dist_port_tracer(Tracer),
ok.
@@ -379,8 +380,7 @@ busy_dist_port_link(Config) when is_list(Config) ->
_ -> false
end,
- [An] = get_names(1, busy_dist_port_link),
- {ok, A} = start_node(An),
+ {ok, PeerA, A} = ?CT_PEER(),
TP1 = spawn(A, ?MODULE, test_proc, []),
%% Check link over busy port
suspend_on_busy_test(A,
@@ -413,7 +413,7 @@ busy_dist_port_link(Config) when is_list(Config) ->
end
end),
tp_cast(TP1, fun () -> exit(normal) end),
- stop_node(A),
+ peer:stop(PeerA),
stop_busy_dist_port_tracer(Tracer),
ok.
@@ -422,10 +422,9 @@ otp_5772_link(Config) when is_list(Config) ->
otp_5772_link_test(node()).
otp_5772_dist_link(Config) when is_list(Config) ->
- [An] = get_names(1, otp_5772_dist_link),
- {ok, A} = start_node(An),
+ {ok, PeerA, A} = ?CT_PEER(),
otp_5772_link_test(A),
- stop_node(A).
+ peer:stop(PeerA).
otp_5772_link_test(Node) ->
Prio = process_flag(priority, high),
@@ -454,11 +453,9 @@ otp_5772_monitor(Config) when is_list(Config) ->
otp_5772_monitor_test(node()).
otp_5772_dist_monitor(Config) when is_list(Config) ->
- [An] = get_names(1, otp_5772_dist_monitor),
- {ok, A} = start_node(An),
+ {ok, PeerA, A} = ?CT_PEER(),
otp_5772_monitor_test(A),
- stop_node(A),
- ok.
+ peer:stop(PeerA).
otp_5772_monitor_test(Node) ->
Prio = process_flag(priority, high),
@@ -482,8 +479,7 @@ otp_5772_monitor_test(Node) ->
ok.
otp_7946(Config) when is_list(Config) ->
- [NodeName] = get_names(1, otp_7946),
- {ok, Node} = start_node(NodeName),
+ {ok, _Peer, Node} = ?CT_PEER(),
Proc = rpc:call(Node, erlang, whereis, [net_kernel]),
Mon = erlang:monitor(process, Proc),
rpc:cast(Node, erlang, halt, []),
@@ -504,10 +500,9 @@ otp_17127_local_link_with_simultaneous_link_unlink(Config) when is_list(Config)
otp_17127_link_with_simultaneous_link_unlink_test(node(), node()).
otp_17127_dist_link_with_simultaneous_link_unlink(Config) when is_list(Config) ->
- [NodeName] = get_names(1, otp_17127),
- {ok, Node} = start_node(NodeName),
+ {ok, Peer, Node} = ?CT_PEER(),
Res = otp_17127_link_with_simultaneous_link_unlink_test(node(), Node),
- stop_node(Node),
+ peer:stop(Peer),
Res.
otp_17127_link_with_simultaneous_link_unlink_test(NodeA, NodeB) ->
@@ -524,10 +519,10 @@ otp_17127_local_random(Config) when is_list(Config) ->
otp_17127_random_test(node(), node(), 100).
otp_17127_dist_random(Config) when is_list(Config) ->
- [NodeName] = get_names(1, otp_17127),
- {ok, Node} = start_node(NodeName),
+ {ok, Peer, Node} = ?CT_PEER(),
+ rpc:call(Node, erts_debug, set_internal_state, [available_internal_state, true]),
Res = otp_17127_random_test(node(), Node, 20),
- stop_node(Node),
+ peer:stop(Peer),
Res.
otp_17127_random_test(_NodeA, _NodeB, 0) ->
@@ -1182,48 +1177,6 @@ check_monitor_node(From, Node, No) when is_pid(From),
dir = target,
pid = From}] = find_erl_monitor({node(From), Node}, From).
-connection_id(Node) ->
- try
- erts_debug:get_internal_state({connection_id, Node})
- catch
- _:_ -> -1
- end.
-
-hostname() ->
- from($@, atom_to_list(node())).
-
-from(H, [H | T]) -> T;
-from(H, [_ | T]) -> from(H, T);
-from(_H, []) -> [].
-
-get_names(N, T) when is_atom(T) ->
- get_names(N, T, []).
-get_names(0, _, Acc) ->
- Acc;
-get_names(N, T, Acc) ->
- get_names(N-1, T, [list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(T)
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))) | Acc]).
-
-start_node(Name) ->
- start_node(Name, "").
-
-start_node(Name, Args) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Res = test_server:start_node(Name, slave, [{args, Args ++ " -pa " ++ Pa}]),
- {ok, Node} = Res,
- rpc:call(Node, erts_debug, set_internal_state,
- [available_internal_state, true]),
- Res.
-
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-define(COOKIE, '').
-define(DOP_LINK, 1).
-define(DOP_SEND, 2).
@@ -1285,7 +1238,7 @@ dctrl(Node) when is_atom(Node) ->
dmsg_hdr() ->
[131, % Version Magic
$D, % Dist header
- 0]. % No atom cache referenses
+ 0]. % No atom cache references
dmsg_ext(Term) ->
<<131, Res/binary>> = term_to_binary(Term),
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 666afde1c0..2149eac41b 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
-include_lib("common_test/include/ct_event.hrl").
-export([all/0, suite/0, groups/0,
+ init_per_testcase/2, end_per_testcase/2,
test_size/1,flat_size_big/1,df/1,term_type/1,
instructions/1, stack_check/1, alloc_blocks_size/1,
t_copy_shared/1,
@@ -43,6 +44,11 @@ all() ->
groups() ->
[{interpreter_size_bench, [], [interpreter_size_bench]}].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
interpreter_size_bench(_Config) ->
Size = erts_debug:interpreter_size(),
ct_event:notify(#event{name=benchmark_data,
@@ -58,12 +64,12 @@ test_size(Config) when is_list(Config) ->
0 = do_test_size([]),
0 = do_test_size(42),
ConsCellSz = do_test_size(ConsCell1),
- 1 = do_test_size({}),
+ 0 = do_test_size({}),
2 = do_test_size({[]}),
3 = do_test_size({a,b}),
7 = do_test_size({a,[b,c]}),
8 = do_test_size(#{b => 2,c => 3}),
- 4 = do_test_size(#{}),
+ 3 = do_test_size(#{}),
32 = do_test_size(#{b => 2,c => 3,txt => "hello world"}),
true = do_test_size(maps:from_list([{I,I}||I<-lists:seq(1,256)])) >= map_size_lower_bound(256),
@@ -76,7 +82,7 @@ test_size(Config) when is_list(Config) ->
%% Fun environment size = 0 (the smallest fun possible)
SimplestFun = fun() -> ok end,
- FunSz0 = 6,
+ FunSz0 = 5,
FunSz0 = do_test_size(SimplestFun),
%% Fun environment size = 1
@@ -89,7 +95,8 @@ test_size(Config) when is_list(Config) ->
FunSz1 = do_test_size(fun() -> ConsCell1 end) - do_test_size(ConsCell1),
- 2 = do_test_size(fun lists:sort/1),
+ %% External funs are the same size as local ones without environment
+ FunSz0 = do_test_size(fun lists:sort/1),
Arch = 8 * erlang:system_info({wordsize, external}),
case {Arch, do_test_size(mk_ext_pid({a@b, 1}, 17, 42))} of
@@ -259,30 +266,22 @@ instructions(Config) when is_list(Config) ->
alloc_blocks_size(Config) when is_list(Config) ->
F = fun(Args) ->
- Node = start_slave(Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
ok = rpc:call(Node, ?MODULE, do_alloc_blocks_size, []),
- true = test_server:stop_node(Node)
+ peer:stop(Peer)
end,
case test_server:is_asan() of
- false -> F("+Meamax");
+ false -> F(["+Meamax"]);
true -> skip
end,
- F("+Meamin"),
- F(""),
+ F(["+Meamin"]),
+ F([]),
ok.
do_alloc_blocks_size() ->
_ = erts_debug:alloc_blocks_size(binary_alloc),
ok.
-start_slave(Args) ->
- Name = ?MODULE_STRING ++ "_slave",
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(list_to_atom(Name),
- slave,
- [{args, "-pa " ++ Pa ++ " " ++ Args}]),
- Node.
-
id(I) ->
I.
diff --git a/erts/emulator/test/erts_test_utils.erl b/erts/emulator/test/erts_test_utils.erl
index 1759a464e2..85ef8c203f 100644
--- a/erts/emulator/test/erts_test_utils.erl
+++ b/erts/emulator/test/erts_test_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
%%
-module(erts_test_utils).
--compile(r20).
+-compile(r22).
%%
%% THIS MODULE IS ALSO USED BY *OTHER* APPLICATIONS TEST CODE
@@ -29,7 +29,8 @@
mk_ext_port/2,
mk_ext_ref/2,
available_internal_state/1,
- check_node_dist/0, check_node_dist/1, check_node_dist/3]).
+ check_node_dist/0, check_node_dist/1, check_node_dist/3,
+ ept_check_leaked_nodes/1]).
@@ -292,3 +293,21 @@ check_refc(ThisNodeName,ThisCreation,Table,EntryList) when is_list(EntryList) ->
end,
EntryList),
ok.
+
+%% To be called by end_per_testcase
+%% to check and kill leaked node connections.
+ept_check_leaked_nodes(Config) ->
+ case nodes(connected) of
+ [] -> ok;
+ Nodes ->
+ [net_kernel:disconnect(N) || N <- Nodes],
+ Leaked = {"Leaked connections", Nodes},
+ Fail = case proplists:get_value(tc_status, Config) of
+ ok -> Leaked;
+ {failed, Reason} ->
+ [Reason, {end_per_testcase, Leaked}];
+ {skipped, _}=Skipped ->
+ [Skipped, {end_per_testcase, Leaked}]
+ end,
+ {fail, Fail}
+ end.
diff --git a/erts/emulator/test/estone_SUITE.erl b/erts/emulator/test/estone_SUITE.erl
index 967e25f109..0568900afd 100644
--- a/erts/emulator/test/estone_SUITE.erl
+++ b/erts/emulator/test/estone_SUITE.erl
@@ -279,12 +279,12 @@ micro(int_arith) ->
#micro{function = int_arith,
weight = 3,
loops = 4157,
- str = "Small Integer arithmetics"};
+ str = "Small Integer arithmetic"};
micro(float_arith) ->
#micro{function = float_arith,
weight = 1,
loops = 5526,
- str = "Float arithmetics"};
+ str = "Float arithmetic"};
micro(fcalls) ->
#micro{function = fcalls,
weight = 5,
diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl
index 80fc35d2be..ea76a473f2 100644
--- a/erts/emulator/test/exception_SUITE.erl
+++ b/erts/emulator/test/exception_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
-module(exception_SUITE).
-export([all/0, suite/0,
+ init_per_testcase/2, end_per_testcase/2,
badmatch/1, pending_errors/1, nil_arith/1, top_of_stacktrace/1,
stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1,
change_exception_class/1,
@@ -51,6 +52,11 @@ all() ->
error_3, error_info,
no_line_numbers, line_numbers].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
-define(try_match(E),
catch ?MODULE:bar(),
{'EXIT', {{badmatch, nomatch}, _}} = (catch E = id(nomatch))).
@@ -163,7 +169,7 @@ pending({Code,[{?MODULE,Func,Arity,Loc}|_]}, Func, Args, Code)
pending(Reason, _Function, _Args, _Code) ->
ct:fail({bad_exit_reason,Reason}).
-%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash.
+%% Test that doing arithmetic on [] gives a badarith EXIT and not a crash.
nil_arith(Config) when is_list(Config) ->
ba_plus_minus_times([], []),
@@ -699,7 +705,7 @@ error_info(_Config) ->
end,
%% Pick up external pid and port.
- {ok, ExternalNode} = test_server:start_node(?FUNCTION_NAME, slave, []),
+ {ok, Peer, ExternalNode} = ?CT_PEER(),
ExternalPid = rpc:call(ExternalNode, erlang, whereis, [code_server]),
ExternalPort = hd(rpc:call(ExternalNode, erlang, ports, [])),
@@ -1028,7 +1034,21 @@ error_info(_Config) ->
{nif_error, 1},
{nif_error, 2},
{node, [abc]},
- {nodes, [abc]},
+ {nodes, [abc], [{1, ".*not a valid node type.*"}]},
+ {nodes, [[abc]], [{1, ".*not a list of.*"}]},
+ {nodes, [DeadProcess], [{1, ".*not a valid node type or list of valid node types.*"}]},
+ {nodes, [abc, 17], [{1, ".*not a valid node type.*"},{2, ".*not a map.*"}]},
+ {nodes, [hidden, 17], [{2, ".*not a map.*"}]},
+ {nodes, [hidden, #{ 17 => true }], [{2, ".*invalid options in map.*"}]},
+ {nodes, [hidden, #{ connection_id => 17 }], [{2, ".*invalid options in map.*"}]},
+ {nodes, [hidden, #{ node_type => 17 }], [{2, ".*invalid options in map.*"}]},
+ {nodes, [abc, #{}], [{1, ".*not a valid node type.*"}]},
+ {nodes, [DeadProcess,#{node_type=>true}], [{1, ".*not a valid node type or list of valid node types.*"}]},
+ {nodes, [visible, 17], [{2,".*not a map.*"}]},
+ {nodes, [visible, #{connection_id=>blapp}], [{2,".*invalid options in map.*"}]},
+ {nodes, [visible, 17], [{2,".*not a map.*"}]},
+ {nodes, [known, #{connection_id=>true,node_type=>true}], [no_fail]},
+ {nodes, [[this,connected], #{connection_id=>true,node_type=>true}], [no_fail]},
{phash, [any, -1]},
{phash, [any, not_integer]},
{phash2, [any], [no_fail]},
@@ -1314,7 +1334,7 @@ error_info(_Config) ->
try
do_error_info(L)
after
- test_server:stop_node(ExternalNode)
+ peer:stop(Peer)
end.
dead_process() ->
@@ -1443,11 +1463,23 @@ line_numbers(Config) when is_list(Config) ->
[{file,"fake_file.erl"},{line,3}]},
{?MODULE,line_numbers,1,_}|_]}} =
(catch line1(bad_tag, 0)),
- {'EXIT',{badarith,
- [{?MODULE,line1,2,
- [{file,"fake_file.erl"},{line,5}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch line1(a, not_an_integer)),
+
+ %% The stacktrace for operators such a '+' can vary depending on
+ %% whether the JIT is used or not.
+ case catch line1(a, not_an_integer) of
+ {'EXIT',{badarith,
+ [{erlang,'+',[not_an_integer,1],_},
+ {?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,_}|_]}} ->
+ ok;
+ {'EXIT',{badarith,
+ [{?MODULE,line1,2,
+ [{file,"fake_file.erl"},{line,5}]},
+ {?MODULE,line_numbers,1,_}|_]}} ->
+ ok
+ end,
+
{'EXIT',{{badmatch,{ok,1}},
[{?MODULE,line1,2,
[{file,"fake_file.erl"},{line,7}]},
@@ -1480,7 +1512,7 @@ line_numbers(Config) when is_list(Config) ->
<<0,0>> = build_binary1(16),
{'EXIT',{badarg,
[{?MODULE,build_binary1,1,
- [{file,"bit_syntax.erl"},{line,72503}]},
+ [{file,"bit_syntax.erl"},{line,72503},{error_info,_}]},
{?MODULE,line_numbers,1,
[{file,ModFile},{line,_}]}|_]}} =
(catch build_binary1(bad_size)),
@@ -1488,21 +1520,20 @@ line_numbers(Config) when is_list(Config) ->
<<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
{'EXIT',{badarg,
[{?MODULE,build_binary2,2,
- [{file,"bit_syntax.erl"},{line,72507}]},
+ [{file,"bit_syntax.erl"},{line,72507},{error_info,_}]},
{?MODULE,line_numbers,1,
[{file,ModFile},{line,_}]}|_]}} =
(catch build_binary2(bad_size, <<>>)),
{'EXIT',{badarg,
- [{erlang,bit_size,[bad_binary],[{error_info,_}]},
- {?MODULE,build_binary2,2,
- [{file,"bit_syntax.erl"},{line,72507}]},
+ [{?MODULE,build_binary2,2,
+ [{file,"bit_syntax.erl"},{line,72507},{error_info,_}]},
{?MODULE,line_numbers,1,
[{file,ModFile},{line,_}]}|_]}} =
(catch build_binary2(8, bad_binary)),
<<"abc",357:16>> = build_binary3(<<"abc">>),
{'EXIT',{badarg,[{?MODULE,build_binary3,1,
- [{file,"bit_syntax.erl"},{line,72511}]},
+ [{file,"bit_syntax.erl"},{line,72511},{error_info,_}]},
{?MODULE,line_numbers,1,
[{file,ModFile},{line,_}]}|_]}} =
(catch build_binary3(no_binary)),
@@ -1531,14 +1562,29 @@ line_numbers(Config) when is_list(Config) ->
{?MODULE,line_numbers,1,_}|_]}} =
(catch applied_bif_2()),
- {'EXIT',{badarith,
- [{?MODULE,increment1,1,[{file,"increment.erl"},{line,45}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch increment1(x)),
- {'EXIT',{badarith,
- [{?MODULE,increment2,1,[{file,"increment.erl"},{line,48}]},
- {?MODULE,line_numbers,1,_}|_]}} =
- (catch increment2(x)),
+ case catch increment1(x) of
+ {'EXIT',{badarith,
+ [{erlang,'+',[x,1],_},
+ {?MODULE,increment1,1,[{file,"increment.erl"},{line,45}]},
+ {?MODULE,line_numbers,1,_}|_]}} ->
+ ok;
+ {'EXIT',{badarith,
+ [{?MODULE,increment1,1,[{file,"increment.erl"},{line,45}]},
+ {?MODULE,line_numbers,1,_}|_]}} ->
+ ok
+ end,
+
+ case catch increment2(x) of
+ {'EXIT',{badarith,
+ [{erlang,'+',[x,1],_},
+ {?MODULE,increment2,1,[{file,"increment.erl"},{line,48}]},
+ {?MODULE,line_numbers,1,_}|_]}} ->
+ ok;
+ {'EXIT',{badarith,
+ [{?MODULE,increment2,1,[{file,"increment.erl"},{line,48}]},
+ {?MODULE,line_numbers,1,_}|_]}} ->
+ ok
+ end,
{'EXIT',{{badmap,not_a_map},
[{?MODULE,update_map,1,[{file,"map.erl"},{line,3}]}|_]}} =
@@ -1563,6 +1609,21 @@ line_numbers(Config) when is_list(Config) ->
{?MODULE,line_numbers,1,_}|_]}} =
(catch crash_huge_line(gurka)),
+ {'EXIT',{{badrecord,[1,2,3]},
+ [{?MODULE,bad_record,1,[{file,"bad_records.erl"},{line,4}]}|_]}} =
+ catch bad_record([1,2,3]),
+
+ %% GH-5960: When an instruction raised an exception at the very end of the
+ %% instruction (e.g. badmatch), and was directly followed by a line
+ %% instruction, the exception was raised for the wrong line.
+ ok = ambiguous_line(0),
+ {'EXIT',{{badmatch,_},
+ [{?MODULE,ambiguous_line,1,[{file,"ambiguous_line.erl"},
+ {line,3}]}|_]}} = catch ambiguous_line(1),
+ {'EXIT',{{badmatch,_},
+ [{?MODULE,ambiguous_line,1,[{file,"ambiguous_line.erl"},
+ {line,4}]}|_]}} = catch ambiguous_line(2),
+
ok.
id(I) -> I.
@@ -1690,3 +1751,14 @@ foo() -> id(100).
crash_huge_line(_) -> %Line 100000002
erlang:error(crash). %Line 100000003
+
+-file("bad_records.erl", 1).
+-record(foobar, {a,b,c,d}). %Line 2.
+bad_record(R) -> %Line 3.
+ R#foobar.a. %Line 4.
+
+-file("ambiguous_line.erl", 1).
+ambiguous_line(A) -> %Line 2.
+ true = A =/= 1, %Line 3.
+ true = A =/= 2, %Line 4.
+ ok.
diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl
index 18d00e429f..e62f63db6f 100644
--- a/erts/emulator/test/float_SUITE.erl
+++ b/erts/emulator/test/float_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0, groups/0,
+ init_per_testcase/2, end_per_testcase/2,
fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,
t_mul_add_ops/1,negative_zero/1,
bad_float_unpack/1, write/1, cmp_zero/1, cmp_integer/1, cmp_bignum/1]).
@@ -43,6 +44,11 @@ all() ->
groups() ->
[{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
%%
%% OTP-7178, list_to_float on very small numbers should give 0.0
%% instead of exception, i.e. ignore underflow.
@@ -65,10 +71,22 @@ negative_zero(Config) when is_list(Config) ->
do_negative_zero(Op, Ops) ->
Res = <<(my_apply(erlang, Op, Ops))/float>>,
+
+ %% Test the canonical op against its mixed-type instruction
Res = <<(case {Op, Ops} of
{'-', [A]} -> -A;
{'*', [A, B]} -> A * B
end)/float>>,
+
+ %% Test the canonical op against its type-specific instructions, if
+ %% applicable
+ Res = <<(case {Op, Ops} of
+ {'-', [C]} when is_float(C) -> -C;
+ {'-', [C]} -> -C;
+ {'*', [C, D]} when is_float(C), is_float(D) -> C * D;
+ {'*', [C, D]} -> C * D
+ end)/float>>,
+
Res.
%% Forces floating point exceptions and tests that subsequent, legal,
@@ -98,7 +116,7 @@ fp_drv_thread(Config) when is_list(Config) ->
%% Run in a separate node since it used to crash the emulator...
Parent = self(),
DrvDir = proplists:get_value(data_dir, Config),
- {ok,Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
Tester = spawn_link(Node,
fun () ->
Parent !
@@ -107,7 +125,7 @@ fp_drv_thread(Config) when is_list(Config) ->
DrvDir)}
end),
Result = receive {Tester, Res} -> Res end,
- stop_node(Node),
+ peer:stop(Peer),
Result.
fp_drv_test(Test, DrvDir) ->
@@ -192,7 +210,7 @@ cmp_zero(_Config) ->
cmp(0.5e-323,0).
cmp_integer(_Config) ->
- Axis = (1 bsl 53)-2.0, %% The point where floating points become unprecise
+ Axis = (1 bsl 53)-2.0, %% The point where floating points become imprecise
span_cmp(Axis,2,200),
cmp(Axis*Axis,round(Axis)).
@@ -285,23 +303,8 @@ cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig,
id(I) -> I.
-start_node(Config) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-
%% Test that operations that might hide infinite intermediate results
-%% do not supress the badarith.
+%% do not suppress the badarith.
hidden_inf(Config) when is_list(Config) ->
ZeroP = 0.0,
ZeroN = id(ZeroP) * (-1),
@@ -410,7 +413,7 @@ my_apply(M, F, A) ->
catch apply(id(M), id(F), A).
% Unify exceptions be removing stack traces.
-% and add argument info to make it easer to debug failed matches.
+% and add argument info to make it easier to debug failed matches.
unify({'EXIT',{Reason,_Stack}}, Info) ->
{{'EXIT', Reason}, Info};
unify(Other, Info) ->
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index 1a2c235d27..3fea66eadc 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
-module(fun_SUITE).
-export([all/0, suite/0,
+ init_per_testcase/2, end_per_testcase/2,
bad_apply/1,bad_fun_call/1,badarity/1,ext_badarity/1,
bad_arglist/1,
equality/1,ordering/1,
@@ -46,6 +47,12 @@ all() ->
const_propagation, t_arity, t_is_function2, t_fun_info,
t_fun_info_mfa,t_fun_to_list].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
+
%% Test that the correct EXIT code is returned for all types of bad funs.
bad_apply(Config) when is_list(Config) ->
bad_apply_fc(42, [0]),
@@ -574,7 +581,7 @@ refc_ets_bag(F1, Options) ->
ok.
refc_dist(Config) when is_list(Config) ->
- {ok,Node} = start_node(fun_SUITE_refc_dist),
+ {ok, Peer, Node} = ?CT_PEER(),
process_flag(trap_exit, true),
Pid = spawn_link(Node, fun() -> receive
Fun when is_function(Fun) ->
@@ -595,7 +602,7 @@ refc_dist(Config) when is_list(Config) ->
true = erlang:garbage_collect(),
2 = fun_refc(F),
refc_dist_send(Node, F),
- test_server:stop_node(Node).
+ peer:stop(Peer).
refc_dist_send(Node, F) ->
Pid = spawn_link(Node, fun() -> receive
@@ -652,7 +659,7 @@ fun_refc(F) ->
Count.
const_propagation(Config) when is_list(Config) ->
- Fun1 = fun start_node/1,
+ Fun1 = fun wait_until/1,
2 = fun_refc(Fun1),
Fun2 = Fun1,
my_cmp({Fun1,Fun2}),
@@ -678,14 +685,14 @@ t_arity(Config) when is_list(Config) ->
%% Test that the arity is transferred properly.
process_flag(trap_exit, true),
- {ok,Node} = start_node(fun_test_arity),
+ {ok, Peer, Node} = ?CT_PEER(),
hello_world = spawn_call(Node, fun() -> hello_world end),
0 = spawn_call(Node, fun(X) -> X end),
42 = spawn_call(Node, fun(_X) -> A end),
43 = spawn_call(Node, fun(X, Y) -> A+X+Y end),
1 = spawn_call(Node, fun(X, Y) -> X+Y end),
45 = spawn_call(Node, fun(X, Y, Z) -> A+X+Y+Z end),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
t_is_function2(Config) when is_list(Config) ->
@@ -868,12 +875,6 @@ fun_arity(F) ->
{arity,Arity} = erlang:fun_info(F, arity),
Arity.
-start_node(Name) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Cookie = atom_to_list(erlang:get_cookie()),
- test_server:start_node(Name, slave,
- [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
-
wait_until(Fun) ->
case catch Fun() of
true -> ok;
diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl
index 6d0c8e0f93..4a9e98da9b 100644
--- a/erts/emulator/test/gc_SUITE.erl
+++ b/erts/emulator/test/gc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
grow_stack/1,
grow_stack_heap/1,
max_heap_size/1,
+ max_heap_size_large_hfrag/1,
minor_major_gc_option_async/1,
minor_major_gc_option_self/1,
gc_signal_order/1,
@@ -44,6 +45,7 @@ suite() ->
all() ->
[grow_heap, grow_stack, grow_stack_heap, max_heap_size,
+ max_heap_size_large_hfrag,
minor_major_gc_option_self,
minor_major_gc_option_async, gc_signal_order, gc_dirty_exec_proc,
alias_signals_in_gc].
@@ -206,6 +208,30 @@ long_receive() ->
ok
end.
+%% Trigger gc-after-bif with a large heap fragment, which provoked some bugs.
+max_heap_size_large_hfrag(Config) ->
+ max_heap_size_large_hfrag_do(),
+ %% Repeat with major GC
+ process_flag(fullsweep_after, 0),
+ max_heap_size_large_hfrag_do(),
+ ok.
+
+max_heap_size_large_hfrag_do() ->
+ {Pid, Ref} =
+ spawn_opt(
+ fun Fun() ->
+ erlang:make_tuple(2000, []),
+ Fun()
+ end,
+ [monitor, {max_heap_size, 1000}]),
+ %% Verify that max heap was triggered
+ {'DOWN', Ref, process, Pid, killed} =
+ receive M -> M
+ after 5000 ->
+ ct:fail({process_did_not_die, Pid, erlang:process_info(Pid)})
+ end,
+ ok.
+
minor_major_gc_option_self(_Config) ->
%% Try as major, the test process will self-trigger GC
check_gc_tracing_around(
@@ -346,13 +372,13 @@ check_no_unexpected_messages() ->
end.
alias_signals_in_gc(Config) when is_list(Config) ->
- %% Make sure alias signals in rootset wont cause
+ %% Make sure alias signals in rootset won't cause
%% crashes...
process_flag(scheduler, 1),
process_flag(priority, normal),
process_flag(message_queue_data, on_heap),
Alias = alias(),
- %% We deactive the alias since it is no point converting
+ %% We deactivate the alias since it is no point converting
%% the alias signals into messages for this test...
unalias(Alias),
Pid = spawn_opt(fun () ->
diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl
index f2c1595392..5bf6871f8c 100644
--- a/erts/emulator/test/guard_SUITE.erl
+++ b/erts/emulator/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -310,7 +310,7 @@ guard_bifs(Config) when is_list(Config) ->
Big = -237849247829874297658726487367328971246284736473821617265433,
Float = 387924.874,
- %% Succeding use of guard bifs.
+ %% Succeeding use of guard bifs.
try_gbif('abs/1', Big, -Big),
try_gbif('float/1', Big, float(Big)),
@@ -391,6 +391,18 @@ guard_bifs(Config) when is_list(Config) ->
try_fail_gbif('node/0', 0, xxxx),
try_fail_gbif('node/1', self(), xxx),
try_fail_gbif('node/1', yyy, xxx),
+
+ {'EXIT', {function_clause, _}} = catch gh_6634({a,b}),
+ {'EXIT', {function_clause, _}} = catch gh_6634(42),
+
+ ok.
+
+gh_6634(X) when is_tuple(X) andalso not ok ->
+ %% `not ok` would be translated to an is_eq_exact instruction,
+ %% which the JIT would not handle correctly because it had two
+ %% immediate operands. In a release build incorrect code would be
+ %% generated, which might crash the runtime system; in a debug
+ %% build an assertion would fire at load time.
ok.
try_gbif(Id, X, Y) ->
diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl
index ae451a05bd..3232607c9d 100644
--- a/erts/emulator/test/hash_SUITE.erl
+++ b/erts/emulator/test/hash_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
%%
%% Verifying erlang:phash/2. And now also phash2/2, to some extent.
%% Test the hashing algorithm for integer numbers in 2 ways:
-%% 1 Test that numbers in diferent sequences get sufficiently spread
+%% 1 Test that numbers in different sequences get sufficiently spread
%% in a "bit pattern" way (modulo 256 etc).
%% 2 Test that numbers are correctly hashed compared to a reference implementation,
%% regardless of their internal representation. The hashing algorithm should never
@@ -95,6 +95,7 @@ notify(X) ->
test_basic/1,test_cmp/1,test_range/1,test_spread/1,
test_phash2/1,otp_5292/1,bit_level_binaries/1,otp_7127/1,
test_hash_zero/1, init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
init_per_group/2, end_per_group/2]).
suite() ->
@@ -169,6 +170,10 @@ init_per_group(_, Config) ->
end_per_group(_, Config) ->
Config.
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
%% Tests basic functionality of erlang:phash and that the
%% hashes has not changed (neither hash nor phash)
@@ -557,38 +562,41 @@ last_byte(Bin) ->
<<_:NotLastByteSize/bitstring, LastByte:8>> = Bin,
LastByte.
+
+%% This testcase needs 8-10 GB of free memory. If not enough is available
+%% the testcase will fail with {erpc,noconnection}
test_phash2_4GB_plus_bin(Config) when is_list(Config) ->
run_when_enough_resources(
fun() ->
- {ok, N} = start_node(?FUNCTION_NAME),
+ {ok, Peer, N} = ?CT_PEER(),
erpc:call(N,
fun() ->
- erts_debug:set_internal_state(available_internal_state, true),
- %% Created Bin4GB here so it only needs to be created once
- erts_debug:set_internal_state(force_gc, self()),
- Bin4GB = get_4GB_bin(),
- test_phash2_plus_bin_helper1(Bin4GB, <<>>, <<>>, 13708901),
- erts_debug:set_internal_state(force_gc, self()),
- test_phash2_plus_bin_helper1(Bin4GB, <<>>, <<3:5>>, 66617678),
- erts_debug:set_internal_state(force_gc, self()),
- test_phash2_plus_bin_helper1(Bin4GB, <<13>>, <<>>, 31308392),
- erts_debug:set_internal_state(force_gc, self()),
- erts_debug:set_internal_state(available_internal_state, false)
+ test_phash2_4GB_plus_bin_tc()
end),
- stop_node(N)
+ peer:stop(Peer)
end).
+test_phash2_4GB_plus_bin_tc() ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ test_phash2_gc(),
+ test_phash2_plus_bin_helper(fun get_4GB_bin/0, <<>>, <<>>, 13708901),
+ test_phash2_gc(),
+ test_phash2_plus_bin_helper(fun get_4GB_bin/0, <<>>, <<3:5>>, 66617678),
+ test_phash2_gc(),
+ test_phash2_plus_bin_helper(fun get_4GB_bin/0, <<13>>, <<>>, 31308392),
+ test_phash2_gc(),
+ erts_debug:set_internal_state(available_internal_state, false),
+ ok.
test_phash2_10MB_plus_bin(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
- erts_debug:set_internal_state(force_gc, self()),
- Bin10MB = get_10MB_bin(),
- test_phash2_plus_bin_helper1(Bin10MB, <<>>, <<>>, 22776267),
- erts_debug:set_internal_state(force_gc, self()),
- test_phash2_plus_bin_helper1(Bin10MB, <<>>, <<3:5>>, 124488972),
- erts_debug:set_internal_state(force_gc, self()),
- test_phash2_plus_bin_helper1(Bin10MB, <<13>>, <<>>, 72958346),
- erts_debug:set_internal_state(force_gc, self()),
+ test_phash2_gc(),
+ test_phash2_plus_bin_helper(fun get_10MB_bin/0, <<>>, <<>>, 22776267),
+ test_phash2_gc(),
+ test_phash2_plus_bin_helper(fun get_10MB_bin/0, <<>>, <<3:5>>, 124488972),
+ test_phash2_gc(),
+ test_phash2_plus_bin_helper(fun get_10MB_bin/0, <<13>>, <<>>, 72958346),
+ test_phash2_gc(),
erts_debug:set_internal_state(available_internal_state, false).
get_10MB_bin() ->
@@ -612,39 +620,86 @@ duplicate_iolist(IOList, 0) ->
duplicate_iolist(IOList, NrOfTimes) ->
duplicate_iolist([IOList, IOList], NrOfTimes - 1).
-test_phash2_plus_bin_helper1(Bin4GB, ExtraBytes, ExtraBits, ExpectedHash) ->
- test_phash2_plus_bin_helper2(Bin4GB, fun id/1, ExtraBytes, ExtraBits, ExpectedHash),
- test_phash2_plus_bin_helper2(Bin4GB, fun make_unaligned_sub_bitstring/1, ExtraBytes, ExtraBits, ExpectedHash).
-test_phash2_plus_bin_helper2(Bin, TransformerFun, ExtraBytes, ExtraBits, ExpectedHash) ->
+%% This functions is written very carefully so that the binaries
+%% created are released as quickly as possible. If they are not released
+%% then the memory consumption going through the roof and systems will need
+%% lots of memory.
+test_phash2_plus_bin_helper(Bin4GB, ExtraBytes, ExtraBits, ExpectedHash) ->
+ ct:log("Test with ~p extra bytes and ~p extra bits",
+ [ExtraBytes, ExtraBits]),
+ test_phash2_plus_bin_helper(Bin4GB, fun id/1, ExtraBytes, ExtraBits, ExpectedHash),
+ ct:log("Test as unaligned sub bitstring"),
+ test_phash2_plus_bin_helper(Bin4GB, fun make_unaligned_sub_bitstring/1,
+ ExtraBytes, ExtraBits, ExpectedHash).
+test_phash2_plus_bin_helper(Bin, TransformerFun, ExtraBytes, ExtraBits, ExpectedHash) ->
+ %% GC to free any binaries used by previous test cases
+ test_phash2_gc(),
ExtraBitstring = << ExtraBytes/binary, ExtraBits/bitstring >>,
LargerBitstring = << ExtraBytes/binary,
ExtraBits/bitstring,
- Bin/bitstring >>,
+ (Bin())/bitstring >>,
+ %% GC to free binary created by Bin()
+ test_phash2_gc(),
LargerTransformedBitstring = TransformerFun(LargerBitstring),
+ %% GC to free binary LargerBitstring
+ test_phash2_gc(),
ExtraBitstringHash = erlang:phash2(ExtraBitstring),
ExpectedHash =
case size(LargerTransformedBitstring) < 4294967296 of
true ->
- erts_debug:set_internal_state(force_gc, self()),
erts_debug:set_internal_state(reds_left, 1),
Hash = erlang:phash2(LargerTransformedBitstring),
Hash = erlang:phash2(LargerTransformedBitstring),
Hash;
false ->
- erts_debug:set_internal_state(force_gc, self()),
erts_debug:set_internal_state(reds_left, 1),
ExtraBitstringHash = erlang:phash2(LargerTransformedBitstring),
ExtraBitstringHash = erlang:phash2(LargerTransformedBitstring),
ExtraBitstringHash
end.
+test_phash2_gc() ->
+ erts_debug:set_internal_state(force_gc, self()),
+ wait_for_mseg_cache(10).
+
+%% We want to wait for the mseg cache to clear as otherwise the
+%% extra refc binaries may still use memory and cause the system
+%% to run out when it should not.
+wait_for_mseg_cache(0) ->
+ io:format("Cached segments never became zero, continue anyways.");
+wait_for_mseg_cache(N) ->
+ case get_cached_segments() of
+ 0 ->
+ %% We sleep an extra second in order for the OS to catch up
+ timer:sleep(1000);
+ NotZero ->
+ io:format("Cached segments = ~p, sleeping for 1 second~n",
+ [NotZero]),
+ timer:sleep(1000),
+ wait_for_mseg_cache(N-1)
+ end.
+
+get_cached_segments() ->
+ case erlang:system_info({allocator,mseg_alloc}) of
+ false ->
+ 0;
+ MsegInfo ->
+ lists:foldl(
+ fun({instance,_,Info}, Acc) ->
+ Kind = proplists:get_value(memkind, Info),
+ Status = proplists:get_value(status, Kind),
+ {cached_segments,Cached} = lists:keyfind(cached_segments, 1, Status),
+ Acc + Cached
+ end, 0, MsegInfo)
+ end.
+
run_when_enough_resources(Fun) ->
Bits = 8 * erlang:system_info({wordsize,external}),
Mem = total_memory(),
Build = erlang:system_info(build_type),
- if Bits =:= 64, is_integer(Mem), Mem >= 31,
+ if Bits =:= 64, is_integer(Mem), Mem >= 16,
Build =/= valgrind, Build =/= asan ->
Fun();
@@ -654,53 +709,22 @@ run_when_enough_resources(Fun) ->
[Mem, Bits, Build])}
end.
-%% Total memory in GB
total_memory() ->
+ %% Total memory in GB.
try
- MemoryData = memsup:get_system_memory_data(),
- case lists:keysearch(total_memory, 1, MemoryData) of
- {value, {total_memory, TM}} ->
- TM div (1024*1024*1024);
- false ->
- {value, {system_total_memory, STM}} =
- lists:keysearch(system_total_memory, 1, MemoryData),
- STM div (1024*1024*1024)
- end
+ SMD = memsup:get_system_memory_data(),
+ TM = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(
+ total_memory, SMD,
+ proplists:get_value(
+ system_total_memory, SMD))),
+ TM div (1024*1024*1024)
catch
- _ : _ ->
- undefined
+ _ : _ ->
+ undefined
end.
-start_node(X) ->
- start_node(X, [], []).
-
-start_node(X, Y) ->
- start_node(X, Y, []).
-
-start_node(Name, Args, Rel) when is_atom(Name), is_list(Rel) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Cookie = atom_to_list(erlang:get_cookie()),
- RelArg = case Rel of
- [] -> [];
- _ -> [{erl,[{release,Rel}]}]
- end,
- test_server:start_node(Name, slave,
- [{args,
- 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)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive])))),
- start_node(Name, Args, Rel).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-ifdef(FALSE).
f1() ->
abc.
@@ -1257,9 +1281,18 @@ make_unaligned_sub_binary(Bin0) when is_binary(Bin0) ->
<<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
Bin.
+%% This functions is written very carefully so that the bitstrings
+%% created are released as quickly as possible. If they are not released
+%% then the memory consumption going through the roof and systems will need
+%% lots of memory.
make_unaligned_sub_bitstring(Bin0) ->
- Bin1 = <<0:3,Bin0/bitstring,31:5>>,
Sz = erlang:bit_size(Bin0),
+ Bin1 = <<0:3,Bin0/bitstring,31:5>>,
+ make_unaligned_sub_bitstring2(Sz, Bin1).
+
+make_unaligned_sub_bitstring2(Sz, Bin1) ->
+ %% Make sure to release Bin0 if possible
+ erlang:garbage_collect(),
<<0:3,Bin:Sz/bitstring,31:5>> = id(Bin1),
Bin.
diff --git a/erts/emulator/test/hash_property_test_SUITE.erl b/erts/emulator/test/hash_property_test_SUITE.erl
index 70840037e7..f2d44e164b 100644
--- a/erts/emulator/test/hash_property_test_SUITE.erl
+++ b/erts/emulator/test/hash_property_test_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,8 +30,10 @@
-module(hash_property_test_SUITE).
--export([suite/0,all/0,groups/0,init_per_suite/1,
- end_per_suite/1,init_per_group/2,end_per_group/2]).
+-export([suite/0,all/0,groups/0,
+ init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2]).
-export([test_phash2_no_diff/1,
test_phash2_no_diff_long/1,
@@ -69,6 +71,11 @@ init_per_group(_, Config) ->
end_per_group(_, Config) ->
Config.
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
test_phash2_no_diff(Config) when is_list(Config) ->
true = ct_property_test:quickcheck(
phash2_properties:prop_phash2_same_with_same_input(),
@@ -80,35 +87,16 @@ test_phash2_no_diff_long(Config) when is_list(Config) ->
Config).
test_phash2_no_diff_between_versions(Config) when is_list(Config) ->
- R = "21",
- case test_server:is_release_available(R) of
- true ->
- Rel = {release,R},
- %% We clear all ERL_FLAGS for the old node as all options may not
- %% be supported.
- ClearEnv = lists:foldl(
- fun({Key,_Value}, Acc) ->
- case re:run(Key,"^ERL_.*FLAGS$") of
- {match,_} ->
- [{Key,""}|Acc];
- nomatch ->
- Acc
- end
- end, [], os:env()),
- case test_server:start_node(rel21,peer,[{erl,[Rel]},{env,ClearEnv}]) of
- {error, Reason} -> {skip, io_lib:format("Could not start node: ~p~n", [Reason])};
- {ok, Node} ->
- try
- true = ct_property_test:quickcheck(
- phash2_properties:prop_phash2_same_in_different_versions(Node),
- Config),
- true = ct_property_test:quickcheck(
- phash2_properties:prop_phash2_same_in_different_versions_with_long_input(Node),
- Config)
- after
- test_server:stop_node(Node)
- end
- end;
- false ->
+ R = integer_to_list(list_to_integer(erlang:system_info(otp_release))-2) ++ "_latest",
+ case ?CT_PEER_REL([], R, proplists:get_value(priv_dir, Config)) of
+ {ok, Peer, Node} ->
+ true = ct_property_test:quickcheck(
+ phash2_properties:prop_phash2_same_in_different_versions(Node),
+ Config),
+ true = ct_property_test:quickcheck(
+ phash2_properties:prop_phash2_same_in_different_versions_with_long_input(Node),
+ Config),
+ peer:stop(Peer);
+ not_available ->
{skip, io_lib:format("Release ~s not available~n", [R])}
end.
diff --git a/erts/emulator/test/hello_SUITE_data/hello.erl b/erts/emulator/test/hello_SUITE_data/hello.erl
index 7e77a71061..dc068d4621 100644
--- a/erts/emulator/test/hello_SUITE_data/hello.erl
+++ b/erts/emulator/test/hello_SUITE_data/hello.erl
@@ -1662,7 +1662,7 @@ test_hibernate() ->
maximum_hibernate_heap_size(Term) ->
%% When hibernating, a few extra words will be allocated to hold the
%% continuation pointer as well as scratch space for the interpreter/jit.
- erts_debug:flat_size(Term) + 4.
+ erts_debug:flat_size(Term) + 8.
hibernate_wake_up(0, _, _) -> ok;
hibernate_wake_up(N, MaxHeapSz, Child) ->
@@ -1891,12 +1891,12 @@ micro(int_arith) ->
#micro{function = int_arith,
weight = 3,
loops = 4157,
- str = "Small Integer arithmetics"};
+ str = "Small Integer arithmetic"};
micro(float_arith) ->
#micro{function = float_arith,
weight = 1,
loops = 5526,
- str = "Float arithmetics"};
+ str = "Float arithmetic"};
micro(fcalls) ->
#micro{function = fcalls,
weight = 5,
diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl
index 6425e9c212..81b56ba7f8 100644
--- a/erts/emulator/test/hibernate_SUITE.erl
+++ b/erts/emulator/test/hibernate_SUITE.erl
@@ -55,7 +55,7 @@ basic(Config) when is_list(Config) ->
maximum_hibernate_heap_size(Term) ->
%% When hibernating, a few extra words will be allocated to hold the
%% continuation pointer as well as scratch space for the interpreter/jit.
- erts_debug:size(Term) + 4.
+ erts_debug:size(Term) + 8.
hibernate_wake_up(0, _, _) -> ok;
hibernate_wake_up(N, MaxHeapSz, Child) ->
@@ -188,7 +188,7 @@ min_heap_size(Config) when is_list(Config) ->
{heap_size,HeapSz} = process_info(Child, heap_size),
io:format("Heap size: ~p\n", [HeapSz]),
if
- HeapSz < 20 -> ok
+ HeapSz =< 20 -> ok
end,
Child ! wake_up,
receive
@@ -334,7 +334,7 @@ no_heap(Config) when is_list(Config) ->
wait_until(fun () -> is_hibernated(H) end),
[{heap_size, Size}, {total_heap_size, Size}]
= process_info(H, [heap_size, total_heap_size]),
- true = Size =< 4,
+ true = Size =< maximum_hibernate_heap_size(0),
receive after 10 -> ok end,
H ! again
end, lists:seq(1, 100)),
diff --git a/erts/emulator/test/hipe_SUITE_data/ref_cell.erl b/erts/emulator/test/hipe_SUITE_data/ref_cell.erl
deleted file mode 100644
index 2654e4077b..0000000000
--- a/erts/emulator/test/hipe_SUITE_data/ref_cell.erl
+++ /dev/null
@@ -1,64 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(ref_cell).
-
--export([start_link/0, start_link_deep/0, call/2]).
-
--compile(native).
-
--define(DEPTH, 100).
--define(ALLOCS, 500).
-
-start_link() ->
- spawn_link(fun() -> loop(undefined) end).
-
-start_link_deep() ->
- spawn_link(fun() -> go_deep(?DEPTH) end).
-
-%% Create a stack large enough to get a graylimit trap placed next time there's
-%% a minor gc.
-go_deep(0) ->
- alloc_some(?ALLOCS),
- loop(undefined),
- 0;
-go_deep(Depth) ->
- go_deep(Depth-1)+1.
-
-%% Do some allocation to trigger a minor gc
-alloc_some(Amount) ->
- Check = (Amount * (Amount + 1)) div 2,
- Check = lists:sum(lists:seq(1, Amount)).
-
-call(Pid, Call) ->
- Pid ! {Call, self()},
- receive {Pid, Res} -> Res end.
-
-loop(Thing) ->
- receive
- {done, Pid} -> Pid ! {self(), done};
- {{put_res_of, Fun}, Pid} ->
- NewThing = Fun(),
- Pid ! {self(), put},
- loop(NewThing);
- {get, Pid} ->
- Pid ! {self(), Thing},
- loop(Thing)
- end.
diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl
deleted file mode 100644
index f7d0e3bd1e..0000000000
--- a/erts/emulator/test/hipe_SUITE_data/trycatch_1.erl
+++ /dev/null
@@ -1,13 +0,0 @@
--module(trycatch_1).
--export([one_try_catch/1,one_plain_catch/1]).
-
-one_try_catch(Term) ->
- try
- trycatch_2:two(Term)
- catch
- C:R:Stk ->
- {C,R,Stk}
- end.
-
-one_plain_catch(Term) ->
- catch trycatch_2:two(Term).
diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl
deleted file mode 100644
index ffac420197..0000000000
--- a/erts/emulator/test/hipe_SUITE_data/trycatch_2.erl
+++ /dev/null
@@ -1,10 +0,0 @@
--module(trycatch_2).
--export([two/1]).
-
-two(Term) ->
- Res = trycatch_3:three(Term),
- foo(),
- Res.
-
-foo() ->
- ok.
diff --git a/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl b/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl
deleted file mode 100644
index 578fa0e87e..0000000000
--- a/erts/emulator/test/hipe_SUITE_data/trycatch_3.erl
+++ /dev/null
@@ -1,9 +0,0 @@
--module(trycatch_3).
--export([three/1]).
-
-three({error,Term}) ->
- error(Term);
-three({throw,Term}) ->
- throw(Term);
-three({exit,Term}) ->
- exit(Term).
diff --git a/erts/emulator/test/perf_SUITE.erl b/erts/emulator/test/jit_SUITE.erl
index b5483fcc8a..67de1b23dc 100644
--- a/erts/emulator/test/perf_SUITE.erl
+++ b/erts/emulator/test/jit_SUITE.erl
@@ -18,29 +18,47 @@
%% %CopyrightEnd%
%%
--module(perf_SUITE).
+-module(jit_SUITE).
--export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).
--export([symbols/1, annotate/1]).
+-export([suite/0, groups/0, all/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([annotate/1, named_labels/1, symbols/1]).
suite() ->
[{timetrap, {minutes, 4}}].
-all() ->
- [symbols, annotate].
+groups() ->
+ [{perf, [symbols, annotate]}].
+
+all() ->
+ [{group, perf}, named_labels].
init_per_suite(Config) ->
- case erlang:system_info(emu_flavor) =:= jit andalso
- os:find_executable("perf") =/= false of
+ case erlang:system_info(emu_flavor) of
+ jit ->
+ Config;
+ _ ->
+ {skip, "No point in running JIT tests on non-JIT emulator"}
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(perf, Config) ->
+ case os:find_executable("perf") of
false ->
{skip, "perf not found"};
_Perf ->
PerfVsn = os:cmd("perf version"),
- case re:run(PerfVsn, "perf version ([^.])",
+ case re:run(PerfVsn, "perf version (\\d+)\\.(\\d+)",
[{capture,all_but_first,list}]) of
- {match,[Vsn]} ->
- case list_to_integer(Vsn) >= 5 of
- true ->
+ {match,[Major0,Minor0]} ->
+ Major = list_to_integer(Major0),
+ Minor = list_to_integer(Minor0),
+ if
+ Major > 5; Major =:= 5, Minor >= 11 ->
BuildIdDir = "--buildid-dir " ++
filename:join(
proplists:get_value(priv_dir, Config),
@@ -59,15 +77,17 @@ init_per_suite(Config) ->
nomatch ->
{skip, "could not run `"++ Cmd ++"`"}
end;
- false ->
+ true ->
{skip,"too old perf version: " ++ PerfVsn}
end;
_ ->
{skip,"unknown old perf version: " ++ PerfVsn}
end
- end.
+ end;
+init_per_group(_, Config) ->
+ Config.
-end_per_suite(Config) ->
+end_per_group(perf, Config) ->
%% perf inject writes data to /tmp and ~/.debug/tmp so we need to clean
%% that up after the tests are done.
SoToDelete = get_tmp_so_files() -- proplists:get_value(sobefore, Config),
@@ -80,6 +100,31 @@ end_per_suite(Config) ->
ok
end
end, SoToDelete),
+ ok;
+end_per_group(_, _Config) ->
+ ok.
+
+init_per_testcase(named_labels, Config) ->
+ %% Only run named_labels on platforms where we know it works.
+ case erlang:system_info(system_architecture) of
+ "x86" ++ _ ->
+ [{asmbefore,get_tmp_asm_files()}|Config];
+ "aarch64" ++ _ ->
+ [{asmbefore,get_tmp_asm_files()}|Config];
+ _ ->
+ {skip, "Unsupported architecture"}
+ end;
+init_per_testcase(_Case, Config) ->
+ Config.
+
+end_per_testcase(named_labels, Config) ->
+ AsmToDelete = get_tmp_asm_files() -- proplists:get_value(asmbefore, Config),
+ lists:foreach(
+ fun(File) ->
+ ok = file:delete(File)
+ end, AsmToDelete),
+ ok;
+end_per_testcase(_, _Config) ->
ok.
get_tmp_so_files() ->
@@ -114,19 +159,72 @@ annotate(Config) ->
%% When doing "perf inject" the symbol of each function is changed
%% from $lists:seq_loop/3 to lists:seq_loop/3. I don't know why that
- %% is, seems like a very odd bug in perf... so we only include it
- %% in our match if it exists
- {match, Symbols} = re:run(Script, "\\$?lists:seq[^/]+/[0-9]+",
+ %% is, seems like a very odd bug in perf...
+ {match, Symbols} = re:run(Script, "lists:seq[^/]+/[0-9]+",
[global,{capture,first,list}]),
- [Symbol|_] = lists:usort(Symbols),
+ [[Symbol]|_] = lists:usort(Symbols),
JitFile = DataFile ++ ".jit.data",
- "" = os:cmd("perf "++ BuildIdDir ++" inject -j -i " ++ DataFile ++ " -o " ++ JitFile),
+ "" = os:cmd("perf "++ BuildIdDir ++" inject --jit -i " ++ DataFile ++ " -o " ++ JitFile),
Anno = os:cmd("perf "++ BuildIdDir ++" annotate --stdio -i " ++ JitFile ++ " " ++ Symbol ++ ""),
case re:run(Anno,"Disassembly of section .text:") of
{match,_} ->
- ok;
+ case re:run(Anno, "lists\\.erl:\\d+") of
+ {match,_} ->
+ ok;
+ nomatch ->
+ ct:fail("Did not find source line annotation for ~ts.~n~ts",
+ [Symbol, Anno])
+ end;
nomatch ->
- ct:log("Did not find disassembly test for ~ts.~n~ts",
- [Symbol, Anno])
+ ct:fail("Did not find disassembly for ~ts.~n~ts",
+ [Symbol, Anno])
+ end.
+
+get_tmp_asm_files() ->
+ {ok, Cwd} = file:get_cwd(),
+ filelib:wildcard(filename:join(Cwd, "*.asm")).
+
+named_labels(_Config) ->
+ %% Check that pretty printing of named labels is working. We do
+ %% that by loading this module in an emulator running with +JDdump
+ %% true and then checking that the produced jit_SUITE.asm contains
+ %% a label for each exported function. We also check that the
+ %% label for the non-exported function get_tmp_asm_files/0, which
+ %% is used by this test, is present.
+ Exports = proplists:get_value(exports, ?MODULE:module_info()),
+ ModName = atom_to_list(?MODULE),
+ ModulePath = filename:dirname(code:which(?MODULE)),
+ Cmd = "erl +JDdump true -noshell -pa " ++ ModulePath ++ " -eval \""
+ ++ ModName ++ ":module_info(),erlang:halt(0).\"",
+ os:cmd(Cmd),
+ {ok, Cwd} = file:get_cwd(),
+ AsmFile = filename:join(Cwd, ModName ++ ".asm"),
+ {ok, Data} = file:read_file(AsmFile),
+ Expected = sets:from_list([ lists:flatten(io_lib:format("~p/~p", [N,A]))
+ || {N,A} <- Exports]
+ ++ ["get_tmp_asm_files/0"]),
+ StripSeqNo = fun(Lbl) ->
+ %% In the Arm JIT, labels have the form
+ %% @Mod:Name/Arity-SequenceNumber, so strip
+ %% out the Mod part and the sequence number
+ %% as we can't know anything about them.
+ case re:run(Lbl, "^.*\:(.*)-[0-9]*$",
+ [{capture,all_but_first,list}]) of
+ {match,[R]} -> R;
+ nomatch -> Lbl
+ end
+ end,
+ case re:run(Data, "^(.*)\:\n",
+ [global,multiline,{capture,all_but_first,list}]) of
+ {match,Labels} ->
+ Found = sets:from_list([ StripSeqNo(NA) || [NA] <- Labels]),
+ case sets:is_subset(Expected, Found) of
+ true ->
+ ok;
+ false ->
+ ct:fail("Expected ~p, found ~p",
+ [sets:to_list(Expected), sets:to_list(Found)])
+ end;
+ _ ->
+ ct:fail("No labels found in assembly dump")
end.
-
diff --git a/erts/emulator/test/lcnt_SUITE.erl b/erts/emulator/test/lcnt_SUITE.erl
index 323f9fc2d1..4cb246f093 100644
--- a/erts/emulator/test/lcnt_SUITE.erl
+++ b/erts/emulator/test/lcnt_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -194,6 +194,12 @@ remove_untoggleable_locks([{resource_monitors, _, _, _} | T]) ->
remove_untoggleable_locks(T);
remove_untoggleable_locks([{nif_load, _, _, _} | T]) ->
remove_untoggleable_locks(T);
+remove_untoggleable_locks([{'crypto.ensure_engine_loaded', _, _, _} | T]) ->
+ %% Global lock used by crypto NIF
+ remove_untoggleable_locks(T);
+remove_untoggleable_locks([{'init_curve_types', _, _, _} | T]) ->
+ %% Global lock used by crypto NIF
+ remove_untoggleable_locks(T);
remove_untoggleable_locks([{'esock.gcnt', _, _, _} | T]) ->
%% Global lock used by socket NIF
remove_untoggleable_locks(T);
diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl
index b398e22707..2e43e9ad5a 100644
--- a/erts/emulator/test/list_bif_SUITE.erl
+++ b/erts/emulator/test/list_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,8 @@
-module(list_bif_SUITE).
-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0]).
+-export([all/0, suite/0,
+ init_per_testcase/2, end_per_testcase/2]).
-export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1,
t_list_to_ref/1, t_list_to_ext_pidportref/1,
t_list_to_port/1,t_list_to_float/1,t_list_to_integer/1]).
@@ -37,6 +38,11 @@ all() ->
t_list_to_ref, t_list_to_ext_pidportref,
t_list_to_float, t_list_to_integer].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
%% Tests list_to_integer and string:to_integer
t_list_to_integer(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch list_to_integer("12373281903728109372810937209817320981321ABC")),
@@ -44,14 +50,21 @@ t_list_to_integer(Config) when is_list(Config) ->
12373 = (catch list_to_integer("12373")),
-12373 = (catch list_to_integer("-12373")),
12373 = (catch list_to_integer("+12373")),
- {'EXIT',{badarg,_}} = ( catch list_to_integer(abc)),
+ {'EXIT',{badarg,_}} = (catch list_to_integer(abc)),
{'EXIT',{badarg,_}} = (catch list_to_integer("")),
{12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"),
{-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"),
{12,[345]} = string:to_integer([$1,$2,345]),
- {error, badarg} = string:to_integer([$1,$2,a]),
+ {error,badarg} = string:to_integer([$1,$2,a]),
{error,no_integer} = string:to_integer([$A]),
{error,badarg} = string:to_integer($A),
+
+ %% System limit.
+ Digits = lists:duplicate(11_000_000, $9),
+ {'EXIT',{system_limit,_}} = catch list_to_integer(Digits),
+ {'EXIT',{system_limit,_}} = catch list_to_integer(Digits, 16),
+ {error,system_limit} = string:to_integer(Digits),
+
ok.
%% Test hd/1 with correct and incorrect arguments.
@@ -143,7 +156,7 @@ t_list_to_ref(Config) when is_list(Config) ->
%% Test list_to_pid/port/ref for external pids/ports/refs.
t_list_to_ext_pidportref(Config) when is_list(Config) ->
- {ok, Node} = slave:start(net_adm:localhost(), t_list_to_ext_pidportref),
+ {ok, Peer, Node} = ?CT_PEER(),
Pid = rpc:call(Node, erlang, self, []),
Port = hd(rpc:call(Node, erlang, ports, [])),
Ref = rpc:call(Node, erlang, make_ref, []),
@@ -175,27 +188,8 @@ t_list_to_ext_pidportref(Config) when is_list(Config) ->
true = rpc:call(Node, erlang, '=:=', [Ref, Ref2]),
true = rpc:call(Node, erlang, '==', [Ref, Ref2]),
- %% Make sure no ugly comparison with 0-creation as wildcard is done.
- Pid0 = make_0_creation(Pid),
- Port0 = make_0_creation(Port),
- Ref0 = make_0_creation(Ref),
- false = (Pid =:= Pid0),
- false = (Port =:= Port0),
- false = (Ref =:= Ref0),
- false = (Pid == Pid0),
- false = (Port == Port0),
- false = (Ref == Ref0),
-
- %% Check 0-creations are converted to local node creations
- %% when sent to matching node name.
- true = rpc:call(Node, erlang, '=:=', [Pid, Pid0]),
- true = rpc:call(Node, erlang, '==', [Pid, Pid0]),
- true = rpc:call(Node, erlang, '=:=', [Port, Port0]),
- true = rpc:call(Node, erlang, '==', [Port, Port0]),
- true = rpc:call(Node, erlang, '=:=', [Ref, Ref0]),
- true = rpc:call(Node, erlang, '==', [Ref, Ref0]),
-
- slave:stop(Node),
+
+ peer:stop(Peer),
ok.
-define(NEW_PID_EXT, 88).
diff --git a/erts/emulator/test/literal_area_collector_test.erl b/erts/emulator/test/literal_area_collector_test.erl
index 14583db88d..d0b6fb3822 100644
--- a/erts/emulator/test/literal_area_collector_test.erl
+++ b/erts/emulator/test/literal_area_collector_test.erl
@@ -28,38 +28,29 @@ check_idle(Timeout) when is_integer(Timeout) > 0 ->
ScaledTimeout = Timeout*test_server:timetrap_scale_factor(),
Pid = find_literal_area_collector(),
Start = erlang:monotonic_time(millisecond),
- try
- wait_for_idle_literal_collector(Pid, Start, ScaledTimeout, -1, 0)
- catch
- throw:done ->
- ok
- end.
+ Alias = alias(),
+ wait_for_idle_literal_collector(Pid, Alias, Start, ScaledTimeout).
-wait_for_idle_literal_collector(Pid, Start, Timeout, NWaiting, WRedsStart) ->
- {W, R} = case process_info(Pid, [status, reductions]) of
- [{status, waiting}, {reductions, Reds}] ->
- %% Assume that reds aren't bumped more than
- %% 2 in order to service this process info
- %% request...
- case {NWaiting > 100, Reds - WRedsStart =< 2*NWaiting} of
- {true, true} ->
- throw(done);
- {false, true} ->
- {NWaiting+1, WRedsStart};
- _ ->
- {0, Reds}
- end;
- _ ->
- {-1, 0}
- end,
+wait_for_idle_literal_collector(Pid, Alias, Start, Timeout) ->
+ Ref = make_ref(),
+ Pid ! {get_status, Ref, Alias},
Now = erlang:monotonic_time(millisecond),
- if Now - Start > Timeout ->
- error({busy_literal_area_collecor_timout, Timeout});
- true ->
- ok
- end,
- receive after 1 -> ok end,
- wait_for_idle_literal_collector(Pid, Start, Timeout, W, R).
+ TMO = case Start + Timeout - Now of
+ TimeLeft when TimeLeft < 0 -> 0;
+ TimeLeft -> TimeLeft
+ end,
+ receive
+ {Ref, idle} ->
+ unalias(Alias),
+ ok;
+ {Ref, _} ->
+ receive after 10 -> ok end,
+ wait_for_idle_literal_collector(Pid, Alias, Start, Timeout)
+ after TMO ->
+ unalias(Alias),
+ receive {Ref, _} -> ok after 0 -> ok end,
+ error({busy_literal_area_collecor_timout, Timeout})
+ end.
find_literal_area_collector() ->
case get('__literal_area_collector__') of
diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl
index ceeff05e75..1a0891184f 100644
--- a/erts/emulator/test/lttng_SUITE.erl
+++ b/erts/emulator/test/lttng_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,10 +71,10 @@ init_per_testcase(Case, Config) ->
ok = ensure_lttng_started(Name, Config),
[{session, Name}|Config].
-end_per_testcase(Case, _Config) ->
+end_per_testcase(Case, Config) ->
Name = atom_to_list(Case),
ok = ensure_lttng_stopped(Name),
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
%% Not tested yet
%% org_erlang_otp:driver_process_exit
@@ -298,14 +298,14 @@ chk_caller(Port, Callback, ExpectedCaller) ->
ExpectedCaller = Caller
end.
-ets_load(Config) ->
+ets_load(Config) when is_list(Config) ->
%% Have to do on a fresh node to guarantee that carriers are created
- {ok,Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
Res = rpc:call(Node, ?MODULE, ets_load, []),
- stop_node(Node),
+ peer:stop(Peer),
Res.
@@ -447,19 +447,3 @@ cmd(Cmd) ->
io:format(">> ~ts~n", [Res]),
{ok,Res}.
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 5707a8e56c..23c072ce86 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -18,6 +18,7 @@
%%
-module(map_SUITE).
-export([all/0, suite/0, init_per_suite/1, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2,
groups/0]).
-export([t_build_and_match_literals/1, t_build_and_match_literals_large/1,
@@ -84,14 +85,20 @@
%% instruction-level tests
t_has_map_fields/1,
+ t_get_map_elements/1,
y_regs/1,
- badmap_17/1,
%%Bugs
t_large_unequal_bins_same_hash_bug/1]).
+%% Benchmarks
+-export([benchmarks/1]).
+
-include_lib("stdlib/include/ms_transform.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+-include_lib("common_test/include/ct.hrl").
+
-define(CHECK(Cond,Term),
case (catch (Cond)) of
true -> true;
@@ -102,7 +109,7 @@
suite() -> [].
all() ->
- run_once() ++ [{group,main}].
+ [{group,main}, benchmarks].
groups() ->
[{main,[],
@@ -157,11 +164,12 @@ groups() ->
%% instruction-level tests
t_has_map_fields,
+ t_get_map_elements,
y_regs,
%% Bugs
t_large_unequal_bins_same_hash_bug]},
- {once,[],[badmap_17]}].
+ {benchmarks, [{repeat,10}], [benchmarks]}].
run_once() ->
case ?MODULE of
@@ -189,6 +197,12 @@ end_per_suite(Config) ->
lists:foreach(fun (A) -> application:stop(A) end, As),
Config.
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
+
%% tests
t_build_and_match_literals(Config) when is_list(Config) ->
@@ -1630,6 +1644,7 @@ t_map_compare(Config) when is_list(Config) ->
io:format("seed = ~p\n", [rand:export_seed()]),
repeat(100, fun(_) -> float_int_compare() end, []),
repeat(100, fun(_) -> recursive_compare() end, []),
+ repeat(10, fun(_) -> atoms_compare() end, []),
ok.
float_int_compare() ->
@@ -1637,12 +1652,26 @@ float_int_compare() ->
%%io:format("Keys to use: ~p\n", [Terms]),
Pairs = lists:map(fun(K) -> list_to_tuple([{K,V} || V <- Terms]) end, Terms),
lists:foreach(fun(Size) ->
- MapGen = fun() -> map_gen(list_to_tuple(Pairs), Size) end,
+ MapGen = fun() -> map_gen(Pairs, Size) end,
repeat(100, fun do_compare/1, [MapGen, MapGen])
end,
lists:seq(1,length(Terms))),
ok.
+atoms_compare() ->
+ Atoms = [true, false, ok, '', ?MODULE, list_to_atom(id("a new atom"))],
+ Pairs = lists:map(fun(K) -> list_to_tuple([{K,V} || V <- Atoms]) end,
+ Atoms),
+ lists:foreach(
+ fun(Size) ->
+ M1 = map_gen(Pairs, Size),
+ M2 = map_gen(Pairs, Size),
+ %%io:format("Atom maps to compare: ~p AND ~p\n", [M1, M2]),
+ do_cmp(M1, M2)
+ end,
+ lists:seq(1,length(Atoms))),
+ ok.
+
numeric_keys(N) ->
lists:foldl(fun(_,Acc) ->
Int = rand:uniform(N*4) - N*2,
@@ -1758,6 +1787,8 @@ cmp_others(I, F, true) when is_integer(I), is_float(F) ->
-1;
cmp_others(F, I, true) when is_float(F), is_integer(I) ->
1;
+cmp_others(A1, A2, Exact) when is_atom(A1), is_atom(A2) ->
+ cmp_others(atom_to_list(A1), atom_to_list(A2), Exact);
cmp_others(T1, T2, _) ->
case {T1<T2, T1==T2} of
{true,false} -> -1;
@@ -1772,7 +1803,7 @@ map_gen(Pairs, Size) ->
KV = element(rand:uniform(size(K)), K),
{erlang:delete_element(KI,Keys), [KV | Acc]}
end,
- {Pairs, []},
+ {list_to_tuple(Pairs), []},
lists:seq(1,Size)),
maps:from_list(L).
@@ -1784,12 +1815,8 @@ recursive_compare() ->
%%io:format("Recursive term A = ~p\n", [A]),
%%io:format("Recursive term B = ~p\n", [B]),
- ?CHECK({true,false} =:= case do_cmp(A, B, false) of
- -1 -> {A<B, A>=B};
- 0 -> {A==B, A/=B};
- 1 -> {A>B, A=<B}
- end,
- {A,B}),
+ do_cmp(A, B),
+
A2 = copy_term(A),
?CHECK(A == A2, {A,A2}),
?CHECK(0 =:= cmp(A, A2, false), {A,A2}),
@@ -1799,9 +1826,13 @@ recursive_compare() ->
?CHECK(0 =:= cmp(B, B2, false), {B,B2}),
ok.
-do_cmp(A, B, Exact) ->
- C = cmp(A, B, Exact),
- C.
+do_cmp(A, B) ->
+ ?CHECK({true,false} =:= case cmp(A, B, false) of
+ -1 -> {A<B, A>=B};
+ 0 -> {A==B, A/=B};
+ 1 -> {A>B, A=<B}
+ end,
+ {A,B}).
%% Generate two terms {A,B} that may only differ
%% at float vs integer types.
@@ -3143,6 +3174,19 @@ has_map_fields_3(#{a:=_,b:=_}) -> true;
has_map_fields_3(#{[]:=_,42.0:=_}) -> true;
has_map_fields_3(#{}) -> false.
+t_get_map_elements(Config) when is_list(Config) ->
+ %% Tests that the JIT implementation of `get_map_elements` handles
+ %% collisions properly.
+ N = 500000,
+ Is = lists:seq(1, N),
+ Test = maps:from_list([{I,I}||I<-Is]),
+ [begin
+ #{ Key := Val } = Test,
+ Key = Val
+ end || Key <- Is],
+
+ ok.
+
y_regs(Config) when is_list(Config) ->
Val = [length(Config)],
Map0 = y_regs_update(#{}, Val),
@@ -3211,15 +3255,6 @@ do_badmap(Test) ->
[],{a,b,c},[a,b],atom,10.0,42,(1 bsl 65) + 3],
[Test(T) || T <- Terms].
-%% Test that a module compiled with the OTP 17 compiler will
-%% generate the correct 'badmap' exception.
-badmap_17(Config) ->
- Mod = badmap_17,
- DataDir = test_server:lookup_config(data_dir, Config),
- Beam = filename:join(DataDir, Mod),
- {module,Mod} = code:load_abs(Beam),
- do_badmap(fun Mod:update/1).
-
%% Use this function to avoid compile-time evaluation of an expression.
id(I) -> I.
@@ -3261,8 +3296,7 @@ t_hash_entropy(Config) when is_list(Config) ->
%% Provoke major GC with a lot of "fat" maps on external format in msg queue
%% causing heap fragments to be allocated.
t_gc_rare_map_overflow(Config) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(gc_rare_map_overflow, slave, [{args, "-pa \""++Pa++"\""}]),
+ {ok, Peer, Node} = ?CT_PEER(),
erts_debug:set_internal_state(available_internal_state, true),
try
Echo = spawn_link(Node, fun Loop() -> receive {From,Msg} -> From ! Msg
@@ -3293,7 +3327,7 @@ t_gc_rare_map_overflow(Config) when is_list(Config) ->
after
process_flag(trap_exit, false),
erts_debug:set_internal_state(available_internal_state, false),
- test_server:stop_node(Node)
+ peer:stop(Peer)
end.
t_gc_rare_map_overflow_do(Echo, FatMap, GcFun) ->
@@ -3492,16 +3526,154 @@ run_when_enough_resources(Fun) ->
total_memory() ->
%% Total memory in GB.
try
- MemoryData = memsup:get_system_memory_data(),
- case lists:keysearch(total_memory, 1, MemoryData) of
- {value, {total_memory, TM}} ->
- TM div (1024*1024*1024);
- false ->
- {value, {system_total_memory, STM}} =
- lists:keysearch(system_total_memory, 1, MemoryData),
- STM div (1024*1024*1024)
- end
+ SMD = memsup:get_system_memory_data(),
+ TM = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(
+ total_memory, SMD,
+ proplists:get_value(
+ system_total_memory, SMD))),
+ TM div (1024*1024*1024)
catch
_ : _ ->
undefined
end.
+
+%%%
+%%% Benchmarks
+%%%
+
+-define(SMALL_MAP_SIZE, 32).
+-define(BIG_MAP_SIZE, 3333).
+
+benchmarks(_Config) ->
+ N = 5000000,
+
+ %% Looks up a known value in a flatmap and (relatively large) hashmap,
+ %% the value will be near the middle of the tested flatmap in an
+ %% attempt to make the test more representative.
+ lookup_literal_immed_small(N),
+ lookup_literal_immed_big(N),
+
+ %% Looks up a value that _COULD_ be an immediate (and always is in this
+ %% test), benchmarking the common case of looking up an unknown integer
+ %% or similar.
+ %%
+ %% Like literal_immed_small, we try to pick a value that will be in the
+ %% middle of the tested flatmap.
+ lookup_any_immed_small(N),
+ lookup_any_immed_big(N),
+
+ %% Looks up `[{}]`, looking for regressions in pre-hashed complex
+ %% lookups.
+ lookup_literal_complex_small(N),
+ lookup_literal_complex_big(N),
+
+ %% Looks up some unknown complex term, looking for regressions in complex
+ %% lookups that need to be hashed in runtime.
+ lookup_any_complex_small(N),
+ lookup_any_complex_big(N),
+
+ %% Looks up a bunch of keys in parallel, benchmarking maps-as-structs.
+ lookup_literal_multi_small(N),
+ lookup_literal_multi_big(N),
+
+ ok.
+
+lookup_literal_immed_small(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?SMALL_MAP_SIZE), []),
+ F = fun(N) -> literal_immed(N, Map0, []) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+lookup_literal_immed_big(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?BIG_MAP_SIZE), []),
+ F = fun(N) -> literal_immed(N, Map0, []) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+literal_immed(0, _Map, Acc) ->
+ Acc;
+literal_immed(N, Map, _) ->
+ #{ (?SMALL_MAP_SIZE div 2) := Acc } = Map,
+ literal_immed(N - 1, Map, Acc).
+
+lookup_any_immed_small(Iterations) ->
+ Size = ?SMALL_MAP_SIZE div 2 - 1,
+ Map = maps:from_list([{V, -V} || V <- lists:seq(-Size, Size)]),
+ F = fun(N) -> any_immed(N, Map, Size div 2) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+lookup_any_immed_big(Iterations) ->
+ Size = ?BIG_MAP_SIZE div 2 - 1,
+ Map = maps:from_list([{V, -V} || V <- lists:seq(-Size, Size)]),
+ F = fun(N) -> any_immed(N, Map, Size div 2) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+any_immed(0, _Map, Acc) ->
+ Acc;
+any_immed(N, Map, Acc0) ->
+ #{ Acc0 := Acc } = Map,
+ any_immed(N - 1, Map, Acc).
+
+lookup_literal_complex_small(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?SMALL_MAP_SIZE), []),
+ F = fun(N) -> literal_complex(N, Map0#{ [{}] => [{}] }, [{}]) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+lookup_literal_complex_big(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?BIG_MAP_SIZE), []),
+ F = fun(N) -> literal_complex(N, Map0#{ [{}] => [{}] }, [{}]) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+literal_complex(0, Map, Acc) ->
+ {Map, Acc};
+literal_complex(N, Map, _) ->
+ #{ [{}] := Acc } = Map,
+ literal_complex(N - 1, Map, Acc).
+
+lookup_any_complex_small(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?SMALL_MAP_SIZE - 2), []),
+ F = fun(N) ->
+ any_complex(N, Map0#{ [{}] => {[]}, {[]} => [{}] }, [{}])
+ end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+lookup_any_complex_big(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?BIG_MAP_SIZE - 2), []),
+ F = fun(N) ->
+ any_complex(N, Map0#{ [{}] => {[]}, {[]} => [{}] }, [{}])
+ end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+any_complex(0, _Map, Acc) ->
+ Acc;
+any_complex(N, Map, Acc0) ->
+ #{ Acc0 := Acc } = Map,
+ any_complex(N - 1, Map, Acc).
+
+lookup_literal_multi_small(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?SMALL_MAP_SIZE), id([])),
+ F = fun(N) -> literal_multi(N, Map0, []) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+lookup_literal_multi_big(Iterations) ->
+ Map0 = maps:from_keys(lists:seq(1, ?BIG_MAP_SIZE), id([])),
+ F = fun(N) -> literal_multi(N, Map0, []) end,
+ time(?FUNCTION_NAME, F, Iterations).
+
+literal_multi(0, _Map, Acc) ->
+ Acc;
+literal_multi(N, Map, _) ->
+ #{ (?SMALL_MAP_SIZE div 2 + 0) := Same,
+ (?SMALL_MAP_SIZE div 2 + 1) := Same,
+ (?SMALL_MAP_SIZE div 2 - 1) := Same,
+ (?SMALL_MAP_SIZE div 2 + 2) := Same,
+ (?SMALL_MAP_SIZE div 2 - 2) := Same } = Map,
+ literal_multi(N - 1, Map, Same).
+
+time(Name, F, Iterations) ->
+ Time = element(1, timer:tc(F, [Iterations])),
+ ct_event:notify(#event{name=benchmark_data,
+ data=[{value, Time},
+ {suite, ?MODULE_STRING},
+ {name, atom_to_list(Name)}]}),
+ Time.
diff --git a/erts/emulator/test/map_SUITE_data/badmap_17.erl b/erts/emulator/test/map_SUITE_data/badmap_17.erl
deleted file mode 100644
index 887fc2e5e3..0000000000
--- a/erts/emulator/test/map_SUITE_data/badmap_17.erl
+++ /dev/null
@@ -1,58 +0,0 @@
--module(badmap_17).
--export([update/1]).
-
-%% Compile this source file with OTP 17.0.
-
-update(Map) ->
- try
- update_1(Map),
- error(update_did_not_fail)
- catch
- error:{badmap,Map} ->
- ok
- end,
- try
- update_2(Map),
- error(update_did_not_fail)
- catch
- error:{badmap,Map} ->
- ok
- end,
- try
- update_3(Map),
- error(update_did_not_fail)
- catch
- error:{badmap,Map} ->
- ok
- end,
- ok = update_4(Map),
- ok = update_5(Map),
- ok.
-
-update_1(M) ->
- M#{a=>42}.
-
-update_2(M) ->
- M#{a:=42}.
-
-update_3(M) ->
- id(M),
- M#{a=>42}.
-
-update_4(M) when M#{a=>b} =:= M ->
- did_not_fail;
-update_4(_) ->
- ok.
-
-update_5(M) ->
- id(M),
- case id(true) of
- true when M#{a=>b} =:= M ->
- did_not_fail;
- true ->
- ok
- end.
-
-id(I) ->
- I.
-
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index 7f99e40423..eadddfe312 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,9 @@
-module(match_spec_SUITE).
-export([all/0, suite/0]).
--export([test_1/1, test_2/1, test_3/1, caller_and_return_to/1, bad_match_spec_bin/1,
+-export([init_per_testcase/2, end_per_testcase/2]).
+-export([test_1/1, test_2/1, test_3/1, test_4a/1, test_4b/1, test_5a/1,
+ test_5b/1, caller_and_return_to/1, bad_match_spec_bin/1,
trace_control_word/1, silent/1, silent_no_ms/1, silent_test/1,
ms_trace2/1, ms_trace3/1, ms_trace_dead/1, boxed_and_small/1,
destructive_in_test_bif/1, guard_exceptions/1,
@@ -34,6 +36,7 @@
-export([runner/2, loop_runner/3]).
-export([f1/1, f2/2, f3/2, fn/1, fn/2, fn/3]).
-export([do_boxed_and_small/0]).
+-export([f1_test4/1, f2_test4/2, f3_test4/2]).
% This test suite assumes that tracing in general works. What we test is
% the match spec functionality.
@@ -45,7 +48,7 @@ suite() ->
{timetrap, {minutes, 1}}].
all() ->
- [test_1, test_2, test_3, caller_and_return_to, bad_match_spec_bin,
+ [test_1, test_2, test_3, test_4a, test_4b, test_5a, test_5b, caller_and_return_to, bad_match_spec_bin,
trace_control_word, silent, silent_no_ms, silent_test, ms_trace2,
ms_trace3, ms_trace_dead, boxed_and_small, destructive_in_test_bif,
guard_exceptions, unary_plus, unary_minus, fpe,
@@ -55,6 +58,11 @@ all() ->
otp_9422,
maps].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
test_1(Config) when is_list(Config) ->
tr(fun() -> ?MODULE:f1(a) end,
{?MODULE, f1, 1},
@@ -173,10 +181,68 @@ test_3(Config) when is_list(Config) ->
collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]),
ok.
+%% Test `caller_line` trace with `call` and `global`
+test_4a(Config) when is_list(Config) ->
+ Fun = fun() -> ?MODULE:f3_test4(a, b) end,
+ Pat = [{'_', [],[{message, {caller_line}}]}],
+ P = spawn(?MODULE, runner, [self(), Fun]),
+ erlang:trace(P, true, [call]),
+ %% `global` is implied but we still mention explicitly
+ erlang:trace_pattern({?MODULE, f2_test4, 2}, Pat, [global]),
+ erlang:trace_pattern({?MODULE, f1_test4, 1}, Pat, [global]),
+ collect(P, [{trace, P, call, {?MODULE, f2_test4, [a, b]}, {?MODULE, f3_test4, 2, {"test4.erl", 3}}},
+ {trace, P, call, {?MODULE, f1_test4, [a]}, {?MODULE, f3_test4, 2, {"test4.erl", 3}}}]),
+ ok.
+
+%% Test `caller_line` trace with `return_trace`, `call` and `global`
+test_4b(Config) when is_list(Config) ->
+ Fun = fun() -> ?MODULE:f3_test4(a, b) end,
+ P = spawn(?MODULE, runner, [self(), Fun]),
+ Pat = [{'_', [], [{return_trace}, {message, {caller_line}}]}],
+ erlang:trace(P, true, [call]),
+ %% `global` is implied but we still mention explicitly
+ erlang:trace_pattern({?MODULE, f2_test4, 2}, Pat, [global]),
+ erlang:trace_pattern({?MODULE, f1_test4, 1}, Pat, [global]),
+ collect(P, [{trace, P, call, {?MODULE, f2_test4, [a, b]}, {?MODULE, f3_test4, 2, {"test4.erl", 3}}},
+ {trace, P, call, {?MODULE, f1_test4, [a]}, {?MODULE, f3_test4, 2, {"test4.erl", 3}}},
+ {trace, P, return_from, {?MODULE, f1_test4, 1}, {a}},
+ {trace, P, return_from, {?MODULE, f2_test4, 2}, {a}}
+ ]),
+ ok.
+
+%% Test `caller_line` trace with `call` and `local`
+test_5a(Config) when is_list(Config) ->
+ Fun = fun() -> f3_test5(a, b) end,
+ Pat = [{'_', [],[{message, {caller_line}}]}],
+ P = spawn(?MODULE, runner, [self(), Fun]),
+ erlang:trace(P, true, [call]),
+ %% Notice `local` function tracing
+ erlang:trace_pattern({?MODULE, f2_test5, 2}, Pat, [local]),
+ erlang:trace_pattern({?MODULE, f1_test5, 1}, Pat, [local]),
+ collect(P, [{trace, P, call, {?MODULE, f2_test5, [a, b]}, {?MODULE, f3_test5, 2, {"test5.erl", 3}}},
+ {trace, P, call, {?MODULE, f1_test5, [a]}, {?MODULE, f3_test5, 2, {"test5.erl", 3}}}]),
+ ok.
+
+%% Test `caller_line` trace with `return_trace`, `call` and `local`
+test_5b(Config) when is_list(Config) ->
+ Fun = fun() -> f3_test5(a, b) end,
+ P = spawn(?MODULE, runner, [self(), Fun]),
+ Pat = [{'_', [], [{return_trace}, {message, {caller_line}}]}],
+ erlang:trace(P, true, [call]),
+ %% Notice `local` function tracing
+ erlang:trace_pattern({?MODULE, f2_test5, 2}, Pat, [local]),
+ erlang:trace_pattern({?MODULE, f1_test5, 1}, Pat, [local]),
+ collect(P, [{trace, P, call, {?MODULE, f2_test5, [a, b]}, {?MODULE, f3_test5, 2, {"test5.erl", 3}}},
+ {trace, P, call, {?MODULE, f1_test5, [a]}, {?MODULE, f3_test5, 2, {"test5.erl", 3}}},
+ {trace, P, return_from, {?MODULE, f1_test5, 1}, {a}},
+ {trace, P, return_from, {?MODULE, f2_test5, 2}, {a}}
+ ]),
+ ok.
+
%% Test that caller and return to work as they should
%% There was a bug where caller would be undefined when return_to was set
%% for r the bif erlang:put().
-caller_and_return_to(Config) ->
+caller_and_return_to(Config) when is_list(Config) ->
tr(
fun do_put_wrapper/0,
fun (Tracee) ->
@@ -686,10 +752,9 @@ destructive_in_test_bif(Config) when is_list(Config) ->
%% Test that the comparison between boxed and small does not crash emulator
boxed_and_small(Config) when is_list(Config) ->
- {ok, Node} = start_node(match_spec_suite_other),
+ {ok, Peer, Node} = ?CT_PEER(),
ok = rpc:call(Node,?MODULE,do_boxed_and_small,[]),
- stop_node(Node),
- ok.
+ peer:stop(Peer).
do_boxed_and_small() ->
{ok, false, _, _} = erlang:match_spec_test({0,3},[{{1.47,'_'},[],['$_']}],table),
@@ -700,10 +765,9 @@ do_boxed_and_small() ->
%% Test that faulty seq_trace_call does not crash emulator
faulty_seq_trace(Config) when is_list(Config) ->
- {ok, Node} = start_node(match_spec_suite_other),
+ {ok, Peer, Node} = ?CT_PEER(),
ok = rpc:call(Node,?MODULE,do_faulty_seq_trace,[]),
- stop_node(Node),
- ok.
+ peer:stop(Peer).
do_faulty_seq_trace() ->
{ok,'EXIT',_,_} = erlang:match_spec_test([],[{'_',[],[{message,{set_seq_token,yxa,true}}]}],trace),
@@ -1155,11 +1219,24 @@ fbinmatch(<<>>, Acc) -> Acc.
id(X) ->
X.
-start_node(Name) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Cookie = atom_to_list(erlang:get_cookie()),
- test_server:start_node(Name, slave,
- [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
+-file("test4.erl", 1).
+f3_test4(X,Y) ->
+ ?MODULE:f2_test4(X,Y), % Line 3 - This line number should remain stable
+ ok.
+
+f2_test4(X, _) ->
+ ?MODULE:f1_test4(X).
+
+f1_test4(X) ->
+ {X}.
-stop_node(Node) ->
- test_server:stop_node(Node).
+-file("test5.erl", 1).
+f3_test5(X,Y) ->
+ f2_test5(X,Y), % Line 3 - This line number should remain stable
+ ok.
+
+f2_test5(X, _) ->
+ f1_test5(X).
+
+f1_test5(X) ->
+ {X}.
diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl
index 1533026e7a..71921a4eda 100644
--- a/erts/emulator/test/message_queue_data_SUITE.erl
+++ b/erts/emulator/test/message_queue_data_SUITE.erl
@@ -21,6 +21,7 @@
-module(message_queue_data_SUITE).
-export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
-export([basic/1, process_info_messages/1, total_heap_size/1,
change_to_off_heap/1, change_to_off_heap_gc/1]).
@@ -40,7 +41,12 @@ end_per_suite(_Config) ->
erts_debug:set_internal_state(available_internal_state, false),
ok.
-all() ->
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
+all() ->
[basic, process_info_messages, total_heap_size, change_to_off_heap,
change_to_off_heap_gc].
@@ -54,13 +60,13 @@ basic(Config) when is_list(Config) ->
basic_test(erlang:system_info(message_queue_data)),
- {ok, Node1} = start_node(Config, "+hmqd off_heap"),
+ {ok, Peer1, Node1} = ?CT_PEER(["+hmqd", "off_heap"]),
ok = rpc:call(Node1, ?MODULE, basic_test, [off_heap]),
- stop_node(Node1),
+ peer:stop(Peer1),
- {ok, Node2} = start_node(Config, "+hmqd on_heap"),
+ {ok, Peer2, Node2} = ?CT_PEER(["+hmqd", "on_heap"]),
ok = rpc:call(Node2, ?MODULE, basic_test, [on_heap]),
- stop_node(Node2),
+ peer:stop(Peer2),
ok.
@@ -326,7 +332,7 @@ wait_change_off_heap() ->
%% has been made on current process if (and only if) it
%% was previously changed on this process...
%%
- %% Work with *current* inplementation! This may change...
+ %% Work with *current* implementation! This may change...
%%
erts_debug:set_internal_state(wait, thread_progress),
%% We have now flushed later ops including later op that
@@ -356,17 +362,3 @@ spinner(_N, 0) -> ok;
spinner(N, M) -> spinner(?MODULE:id(N) div 1, M - 1).
id(N) -> N.
-
-start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl
index 2b3c3b9477..e17f8db920 100644
--- a/erts/emulator/test/monitor_SUITE.erl
+++ b/erts/emulator/test/monitor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,19 +24,20 @@
-include_lib("eunit/include/eunit.hrl").
-export([all/0, suite/0, groups/0,
+ init_per_testcase/2, end_per_testcase/2,
case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1,
demon_2/1, demon_3/1, demonitor_flush/1, gh_5225_demonitor_alias/1,
local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1,
large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1,
monitor_time_offset/1, monitor_tag_storage/1,
unexpected_alias_at_demonitor_gh5310/1,
- down_on_alias_gh5310/1]).
+ down_on_alias_gh5310/1, monitor_3_noproc_gh6185/1]).
-export([y2/1, g/1, g0/0, g1/0, large_exit_sub/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap, {minutes, 15}}].
+ {timetrap, {seconds, 30}}].
all() ->
[case_1, case_1a, case_2, case_2a, mon_e_1, demon_e_1,
@@ -45,12 +46,17 @@ all() ->
list_cleanup, mixer, named_down, otp_5827,
monitor_time_offset, monitor_tag_storage,
unexpected_alias_at_demonitor_gh5310,
- down_on_alias_gh5310].
+ down_on_alias_gh5310, monitor_3_noproc_gh6185].
groups() ->
[{remove_monitor, [],
[local_remove_monitor, remote_remove_monitor]}].
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
%% A monitors B, B kills A and then exits (yielded core dump)
case_1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -141,13 +147,13 @@ expect_no_msg() ->
%%% Error cases for monitor/2
mon_e_1(Config) when is_list(Config) ->
- {ok, N} = test_server:start_node(hej, slave, []),
+ {ok, Peer, N} = ?CT_PEER(),
mon_error(plutt, self()),
mon_error(process, [bingo]),
mon_error(process, {rex, N, junk}),
mon_error(process, 1),
- true = test_server:stop_node(N),
+ peer:stop(Peer),
ok.
%%% We would also like to have a test case that tries to monitor something
@@ -169,7 +175,7 @@ mon_error(Type, Item) ->
%%% Error cases for demonitor/1
demon_e_1(Config) when is_list(Config) ->
- {ok, N} = test_server:start_node(hej, slave, []),
+ {ok, Peer, N} = ?CT_PEER(),
demon_error(plutt, badarg),
demon_error(1, badarg),
@@ -192,7 +198,7 @@ demon_e_1(Config) when is_list(Config) ->
ct:fail({rec, Other2})
end,
- true = test_server:stop_node(N),
+ peer:stop(Peer),
ok.
demon_error(Ref, Reason) ->
@@ -247,22 +253,22 @@ demon_2(Config) when is_list(Config) ->
%% Distributed case for demonitor/1 (OTP-3499)
demon_3(Config) when is_list(Config) ->
- {ok, N} = test_server:start_node(hej, slave, []),
+ {ok, Peer, N} = ?CT_PEER(),
%% 'DOWN' before demonitor
P2 = spawn(N, timer, sleep, [100000]),
R2 = erlang:monitor(process, P2),
- true = test_server:stop_node(N),
+ peer:stop(Peer),
true = erlang:demonitor(R2),
expect_down(R2, P2, noconnection),
- {ok, N2} = test_server:start_node(hej, slave, []),
+ {ok, Peer2, N2} = ?CT_PEER(),
%% Demonitor before 'DOWN'
P3 = spawn(N2, timer, sleep, [100000]),
R3 = erlang:monitor(process, P3),
true = erlang:demonitor(R3),
- true = test_server:stop_node(N2),
+ peer:stop(Peer2),
expect_no_msg(),
ok.
@@ -271,9 +277,9 @@ demonitor_flush(Config) when is_list(Config) ->
{'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)),
{'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])),
{'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])),
- {ok, N} = test_server:start_node(demonitor_flush, slave, []),
+ {ok, Peer, N} = ?CT_PEER(),
ok = demonitor_flush_test(N),
- true = test_server:stop_node(N),
+ peer:stop(Peer),
ok = demonitor_flush_test(node()).
demonitor_flush_test(Node) ->
@@ -336,7 +342,7 @@ local_remove_monitor(Config) when is_list(Config) ->
"True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}.
remote_remove_monitor(Config) when is_list(Config) ->
- {ok, N} = test_server:start_node(demonitor_flush, slave, []),
+ {ok, Peer, N} = ?CT_PEER(),
Gs = generate(fun () -> start_remove_monitor_group(N) end,
?RM_MON_GROUPS),
{True, False} = lists:foldl(fun (G, {T, F}) ->
@@ -348,7 +354,7 @@ remote_remove_monitor(Config) when is_list(Config) ->
{0, 0},
Gs),
erlang:display({remote_remove_monitor, True, False}),
- true = test_server:stop_node(N),
+ peer:stop(Peer),
{comment,
"True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}.
@@ -433,7 +439,7 @@ mon_1(Config) when is_list(Config) ->
%% Distributed cases for monitor/2
mon_2(Config) when is_list(Config) ->
- {ok, N1} = test_server:start_node(hej1, slave, []),
+ {ok, Peer, N1} = ?CT_PEER(),
%% Normal case
P2 = spawn(N1, timer, sleep, [4000]),
@@ -454,7 +460,7 @@ mon_2(Config) when is_list(Config) ->
P5 = spawn(N1, timer, sleep, [100000]),
R5 = erlang:monitor(process, P5),
- true = test_server:stop_node(N1),
+ peer:stop(Peer),
expect_down(R5, P5, noconnection),
@@ -465,9 +471,7 @@ mon_2(Config) when is_list(Config) ->
true = (R6_Reason == noconnection) orelse (R6_Reason == noproc),
%% Start a new node that can load code in this module
- PA = filename:dirname(code:which(?MODULE)),
- {ok, N2} = test_server:start_node
- (hej2, slave, [{args, "-pa " ++ PA}]),
+ {ok, Peer2, N2} = ?CT_PEER(),
%% Normal case (named process)
P7 = start_jeeves({jeeves, N2}),
@@ -489,7 +493,7 @@ mon_2(Config) when is_list(Config) ->
_P10 = start_jeeves({jeeves, N2}),
R10 = erlang:monitor(process, {jeeves, N2}),
- true = test_server:stop_node(N2),
+ peer:stop(Peer2),
expect_down(R10, {jeeves, N2}, noconnection),
@@ -542,7 +546,6 @@ large_exit_sub(S) ->
list_cleanup(Config) when is_list(Config) ->
P0 = self(),
M = node(),
- PA = filename:dirname(code:which(?MODULE)),
true = register(master_bertie, self()),
%% Normal local case, monitor and demonitor
@@ -578,8 +581,7 @@ list_cleanup(Config) when is_list(Config) ->
{[], []} = monitors(),
%% Start a new node that can load code in this module
- {ok, J} = test_server:start_node
- (jeeves, slave, [{args, "-pa " ++ PA}]),
+ {ok, Peer, J} = ?CT_PEER(),
%% Normal remote case, monitor and demonitor
P3 = start_jeeves({jeeves, J}),
@@ -622,7 +624,7 @@ list_cleanup(Config) when is_list(Config) ->
{[], [P5]} = monitors(),
expect_jeeves(P5, monitors,
{monitors, {[{process, P0}], []}} ),
- test_server:stop_node(J),
+ peer:stop(Peer),
timer:sleep(4000),
{[], []} = monitors(),
@@ -633,12 +635,7 @@ list_cleanup(Config) when is_list(Config) ->
%%% Mixed internal and external monitors
mixer(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- NN = [j0,j1,j2],
- NL0 = [begin
- {ok, J} = test_server:start_node(X,slave,[{args, "-pa " ++ PA}]),
- J
- end || X <- NN],
+ {_, Peers, NL0} = lists:unzip3([?CT_PEER() || _ <- lists:seq(1, 3)]),
NL1 = lists:duplicate(2,node()) ++ NL0,
Perm = perm(NL1),
lists:foreach(
@@ -712,7 +709,7 @@ mixer(Config) when is_list(Config) ->
[tell_jeeves(P,{exit,flaff}) || P <- Js]
end,
Perm),
- [test_server:stop_node(K) || K <- NL0],
+ [peer:stop(P) || P <- Peers],
ok.
%% Test that DOWN message for a named monitor isn't
@@ -792,7 +789,7 @@ otp_5827(Config) when is_list(Config) ->
end.
monitor_time_offset(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config, "+C single_time_warp"),
+ {ok, Peer, Node} = ?CT_PEER(["+C", "single_time_warp"]),
Me = self(),
PMs = lists:map(fun (_) ->
Pid = spawn(Node,
@@ -822,7 +819,7 @@ monitor_time_offset(Config) when is_list(Config) ->
ct:fail(Reason)
end
end, PMs),
- stop_node(Node),
+ peer:stop(Peer),
ok.
check_monitor_time_offset(Leader) ->
@@ -1038,6 +1035,228 @@ down_on_alias_gh5310_test(ImmedExitReason, DeMonSched, TermSched) ->
DeMonPid ! Go,
receive Done -> ok end.
+
+monitor_3_noproc_gh6185(Config) when is_list(Config) ->
+ monitor_3_noproc_gh6185_test(false, false),
+ monitor_3_noproc_gh6185_test(true, false),
+ monitor_3_noproc_gh6185_test(false, true),
+ monitor_3_noproc_gh6185_test(true, true),
+ monitor_3_noproc_gh6185_exit_test(false, false),
+ monitor_3_noproc_gh6185_exit_test(true, false),
+ monitor_3_noproc_gh6185_exit_test(false, true),
+ monitor_3_noproc_gh6185_exit_test(true, true).
+
+monitor_3_noproc_gh6185_test(AliasTest, TagTest) ->
+ NodeName = node(),
+ UN = undefined_name_gh6185,
+ UNN = {UN, NodeName},
+ undefined = whereis(UN),
+
+ {AliasOpt, CheckAlias}
+ = case AliasTest of
+ false ->
+ {[], fun (_NotAnAlias) -> ok end};
+ true ->
+ {[{alias, explicit_unalias}],
+ fun (Alias) ->
+ AMsg1 = make_ref(),
+ OMsg1 = make_ref(),
+ Alias ! AMsg1,
+ self() ! OMsg1,
+ receive OMsg1 -> ok end,
+ receive AMsg1 -> ok
+ after 0 -> ct:fail(missing_alias_message)
+ end,
+ unalias(Alias),
+ AMsg2 = make_ref(),
+ OMsg2 = make_ref(),
+ Alias ! AMsg2,
+ self() ! OMsg2,
+ receive OMsg2 -> ok end,
+ receive AMsg2 -> ct:fail(unexpected_alias_message)
+ after 0 -> ok
+ end
+ end}
+ end,
+
+ TagFun = case TagTest of
+ false ->
+ fun () ->
+ {'DOWN', []}
+ end;
+ true ->
+ fun () ->
+ Tag = make_ref(),
+ {Tag, [{tag, Tag}]}
+ end
+ end,
+
+ %% not registerd process...
+ {Tag1, TagOpt1} = TagFun(),
+ M1 = erlang:monitor(process, UN, AliasOpt ++ TagOpt1),
+ receive
+ {Tag1, M1, process, UNN, noproc} ->
+ ok;
+ ID1 when element(2, ID1) == M1 ->
+ ct:fail({invalid_down, ID1})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M1),
+
+ {Tag2, TagOpt2} = TagFun(),
+ M2 = erlang:monitor(process, UNN, AliasOpt ++ TagOpt2),
+ receive
+ {Tag2, M2, process, UNN, noproc} ->
+ ok;
+ ID2 when element(2, ID2) == M2 ->
+ ct:fail({invalid_down, ID2})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M2),
+
+ %% Not registered port...
+ {Tag3, TagOpt3} = TagFun(),
+ M3 = erlang:monitor(port, UN, AliasOpt ++ TagOpt3),
+ receive
+ {Tag3, M3, port, UNN, noproc} ->
+ ok;
+ ID3 when element(2, ID3) == M3 ->
+ ct:fail({invalid_down, ID3})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M3),
+
+ {Tag4, TagOpt4} = TagFun(),
+ M4 = erlang:monitor(port, UNN, AliasOpt ++ TagOpt4),
+ receive
+ {Tag4, M4, port, UNN, noproc} ->
+ ok;
+ ID4 when element(2, ID4) == M4 ->
+ ct:fail({invalid_down, ID4})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M4),
+
+
+ OldCreation = case erlang:system_info(creation) of
+ Creation when Creation =< 4 -> 16#ffffffff;
+ Creation -> Creation - 1
+ end,
+
+ %% Process of old incarnation...
+ Pid = erts_test_utils:mk_ext_pid({NodeName, OldCreation}, 4711, 17),
+ {Tag5, TagOpt5} = TagFun(),
+ M5 = erlang:monitor(process, Pid, AliasOpt ++ TagOpt5),
+ receive
+ {Tag5, M5, process, Pid, noproc} ->
+ ok;
+ ID5 when element(2, ID5) == M5 ->
+ ct:fail({invalid_down, ID5})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M5),
+
+ %% Port of old incarnation...
+ Prt = erts_test_utils:mk_ext_port({NodeName, OldCreation}, 4711),
+ {Tag6, TagOpt6} = TagFun(),
+ M6 = erlang:monitor(port, Prt, AliasOpt ++ TagOpt6),
+ receive
+ {Tag6, M6, port, Prt, noproc} ->
+ ok;
+ ID6 when element(2, ID6) == M6 ->
+ ct:fail({invalid_down, ID6})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M6),
+
+ ok.
+
+monitor_3_noproc_gh6185_exit_test(AliasTest, TagTest) ->
+ %%
+ %% Testing that we handle these quite unusual monitors correct
+ %% in case the monotoring process dies right after setting up
+ %% the monitor. We cannot check any results, but we might hit
+ %% asserts, crashes, or memory leaks if any bugs exist...
+ %%
+
+ NodeName = node(),
+ UN = undefined_name_gh6185,
+ UNN = {UN, NodeName},
+ undefined = whereis(UN),
+
+ AliasOpt = case AliasTest of
+ false -> [];
+ true -> [{alias, explicit_unalias}]
+ end,
+
+ TagOpt = case TagTest of
+ false -> [];
+ true -> [{tag, make_ref()}]
+ end,
+
+ %% not registerd process...
+ {P1, M1} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(process, UN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M1, process, P1, bang} -> ok end,
+ {P2, M2} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(process, UNN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M2, process, P2, bang} -> ok end,
+
+ %% Not registered port...
+ {P3, M3} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(port, UN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M3, process, P3, bang} -> ok end,
+ {P4, M4} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(port, UNN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M4, process, P4, bang} -> ok end,
+
+
+ OldCreation = case erlang:system_info(creation) of
+ Creation when Creation =< 4 -> 16#ffffffff;
+ Creation -> Creation - 1
+ end,
+
+ %% Process of old incarnation...
+ {P5, M5} = spawn_monitor(fun () ->
+ Pid = erts_test_utils:mk_ext_pid({NodeName,
+ OldCreation},
+ 4711, 17),
+ erlang:yield(),
+ _ = erlang:monitor(process, Pid, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M5, process, P5, bang} -> ok end,
+
+ %% Port of old incarnation...
+ {P6, M6} = spawn_monitor(fun () ->
+ Prt = erts_test_utils:mk_ext_port({NodeName,
+ OldCreation},
+ 4711),
+ erlang:yield(),
+ _ = erlang:monitor(port, Prt, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M6, process, P6, bang} -> ok end,
+ ok.
+
%%
%% ...
%%
@@ -1182,22 +1401,3 @@ generate(_Fun, 0) ->
[];
generate(Fun, N) ->
[Fun() | generate(Fun, N-1)].
-
-start_node(Config, Args) ->
- TestCase = proplists:get_value(testcase, Config),
- PA = filename:dirname(code:which(?MODULE)),
- ESTime = erlang:monotonic_time(1) + erlang:time_offset(1),
- Unique = erlang:unique_integer([positive]),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(TestCase)
- ++ "-"
- ++ integer_to_list(ESTime)
- ++ "-"
- ++ integer_to_list(Unique)),
- test_server:start_node(Name,
- slave,
- [{args, "-pa " ++ PA ++ " " ++ Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl
index 1100f6cf46..e17d56d535 100644
--- a/erts/emulator/test/mtx_SUITE.erl
+++ b/erts/emulator/test/mtx_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -275,7 +275,7 @@ hammer_sched_rwlock_test(FreqRead, LockCheck, Blocking, WaitLocked, WaitUnlocked
_ ->
{_, RunTime} = statistics(runtime),
io:format("RunTime=~p~n", [RunTime]),
- true = RunTime < 700,
+ true = RunTime < max(700, Onln*12),
{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 9fbcde4e3a..2f28b4a0e9 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
init_per_testcase/2, end_per_testcase/2,
basic/1, reload_error/1, upgrade/1, heap_frag/1,
t_on_load/1,
+ t_nifs_attrib/1,
t_load_race/1,
t_call_nif_early/1,
load_traced_nif/1,
@@ -71,6 +72,7 @@
nif_whereis/1, nif_whereis_parallel/1,
nif_whereis_threaded/1, nif_whereis_proxy/1,
nif_ioq/1,
+ match_state_arg/1,
pid/1,
id/1,
nif_term_type/1
@@ -78,6 +80,115 @@
-export([many_args_100/100]).
+-nifs([lib_version/0,
+ call_history/0,
+ hold_nif_mod_priv_data/1,
+ nif_mod_call_history/0,
+ list_seq/1,
+ type_test/0,
+ tuple_2_list/1,
+ is_identical/2,
+ compare/2,
+ hash_nif/3,
+ many_args_100/100,
+ clone_bin/1,
+ make_sub_bin/3,
+ string_to_bin/2,
+ atom_to_bin/2,
+ macros/1,
+ tuple_2_list_and_tuple/1,
+ iolist_2_bin/1,
+ get_resource_type/1,
+ alloc_resource/2,
+ make_resource/1,
+ get_resource/2,
+ release_resource/1,
+ release_resource_from_thread/1,
+ last_resource_dtor_call_nif/0,
+ make_new_resource/2,
+ check_is/11,
+ check_is_exception/0,
+ length_test/6,
+ make_atoms/0,
+ make_strings/0,
+ make_new_resource_binary/1,
+ send_list_seq/2,
+ send_new_blob/2,
+ alloc_msgenv/0,
+ clear_msgenv/1,
+ grow_blob/2,
+ grow_blob/3,
+ send_blob/2,
+ send3_blob/3,
+ send_blob_thread/3,
+ join_send_thread/1,
+ copy_blob/1,
+ send_term/2,
+ send_copy_term/2,
+ reverse_list/1,
+ echo_int/1,
+ type_sizes/0,
+ otp_9668_nif/1,
+ otp_9828_nif/1,
+ consume_timeslice_nif/2,
+ call_nif_schedule/2,
+ call_nif_exception/1,
+ call_nif_nan_or_inf/1,
+ call_nif_atom_too_long/1,
+ unique_integer_nif/1,
+ is_process_alive_nif/1,
+ is_port_alive_nif/1,
+ term_to_binary_nif/2,
+ binary_to_term_nif/3,
+ port_command_nif/2,
+ format_term_nif/2,
+ select_nif/6,
+ dupe_resource_nif/1,
+ pipe_nif/0,
+ write_nif/2,
+ read_nif/2,
+ close_nif/1,
+ is_closed_nif/1,
+ clear_select_nif/1,
+ last_fd_stop_call/0,
+ alloc_monitor_resource_nif/0,
+ monitor_process_nif/4,
+ demonitor_process_nif/2,
+ compare_monitors_nif/2,
+ make_monitor_term_nif/1,
+ monitor_frenzy_nif/4,
+ ioq_nif/1,
+ ioq_nif/2,
+ ioq_nif/3,
+ ioq_nif/4,
+ whereis_send/3,
+ whereis_term/2,
+ whereis_thd_lookup/3,
+ whereis_thd_result/1,
+ is_map_nif/1,
+ get_map_size_nif/1,
+ make_new_map_nif/0,
+ make_map_put_nif/3,
+ get_map_value_nif/2,
+ make_map_update_nif/3,
+ make_map_remove_nif/2,
+ maps_from_list_nif/1,
+ sorted_list_from_maps_nif/1,
+ monotonic_time/1,
+ time_offset/1,
+ convert_time_unit/3,
+ now_time/0,
+ cpu_time/0,
+ get_local_pid_nif/1,
+ make_pid_nif/1,
+ set_pid_undefined_nif/0,
+ is_pid_undefined_nif/1,
+ compare_pids_nif/2,
+ term_type_nif/1,
+ dynamic_resource_call/4,
+ msa_find_y_nif/1
+ ]).
+
-define(nif_stub,nif_stub_error(?LINE)).
-define(is_resource, is_reference).
@@ -97,6 +208,7 @@ all() ->
{group, monitor},
monitor_frenzy,
t_dynamic_resource_call,
+ t_nifs_attrib,
t_load_race,
t_call_nif_early,
load_traced_nif,
@@ -119,6 +231,7 @@ all() ->
nif_phash2,
nif_whereis, nif_whereis_parallel, nif_whereis_threaded,
nif_ioq,
+ match_state_arg,
pid,
nif_term_type].
@@ -505,6 +618,34 @@ t_on_load(Config) when is_list(Config) ->
verify_tmpmem(TmpMem),
ok.
+%% Test the -nifs() attribute
+t_nifs_attrib(Config) when is_list(Config) ->
+ TmpMem = tmpmem(),
+ ensure_lib_loaded(Config),
+
+ Data = proplists:get_value(data_dir, Config),
+ File = filename:join(Data, "nif_mod"),
+ {ok,nif_mod,Bin3} = compile:file(File, [binary,return_errors,
+ {d,'USE_NIFS_ATTRIB',3}]),
+
+ {module,nif_mod} = code:load_binary(nif_mod,File,Bin3),
+ ok = nif_mod:load_nif_lib(Config, 1),
+ 1 = nif_mod:lib_version(),
+
+ {ok,nif_mod,Bin2} = compile:file(File, [binary,return_errors,
+ {d,'USE_NIFS_ATTRIB',2}]),
+ {module,nif_mod} = code:load_binary(nif_mod,File,Bin2),
+ {error, {bad_lib, "Function not declared as nif" ++ _}} =
+ nif_mod:load_nif_lib(Config, 1),
+
+ {ok,nif_mod,Bin1} = compile:file(File, [binary,return_errors,
+ {d,'USE_NIFS_ATTRIB',1}]),
+ {module,nif_mod} = code:load_binary(nif_mod,File,Bin1),
+ {error, {bad_lib, "Function not declared as nif" ++ _}} =
+ nif_mod:load_nif_lib(Config, 1),
+ ok.
+
+
%% Test erlang:load_nif/2 waiting for code_write_permission.
t_load_race(Config) ->
Data = proplists:get_value(data_dir, Config),
@@ -1011,6 +1152,7 @@ monitor_process_c(Config) ->
Pid = spawn_link(fun() ->
R_ptr = alloc_monitor_resource_nif(),
{0,Mon} = monitor_process_nif(R_ptr, self(), true, Papa),
+ receive after 1000 -> ok end,
[R_ptr] = monitored_by(self()),
put(store, make_resource(R_ptr)),
ok = release_resource(R_ptr),
@@ -1018,8 +1160,8 @@ monitor_process_c(Config) ->
Papa ! {self(), done, R_ptr, Mon},
exit
end),
- [{Pid, done, R_ptr, Mon1},
- {monitor_resource_down, R_ptr, Pid, Mon2}] = flush(2),
+ receive {Pid, done, R_ptr, Mon1} -> ok end,
+ [{monitor_resource_down, R_ptr, Pid, Mon2}] = flush(1),
compare_monitors_nif(Mon1, Mon2),
{R_ptr, _, 1} = last_resource_dtor_call(),
ok.
@@ -1298,6 +1440,8 @@ dynamic_resource_call_do(Config, NifModBin) ->
{1, 1000} = dynamic_resource_call(nif_mod, with_dyncall, R, 1000),
true = erlang:purge_module(nif_mod),
[{unload,2,2,202}] = nif_mod_call_history(),
+
+ keep_alive(R),
ok.
@@ -2505,8 +2649,10 @@ neg(Config) when is_list(Config) ->
{ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
{module,nif_mod} = erlang:load_module(nif_mod,Bin),
- {error,{load_failed,_}} = nif_mod:load_nif_lib(Config, 0),
- {error,{bad_lib,_}} = nif_mod:load_nif_lib(Config, no_init),
+ {error,{load_failed,"Failed to load NIF library"++_}} = nif_mod:load_nif_lib(Config, 0),
+ {error,{bad_lib,"Failed to find library init"++_}} = nif_mod:load_nif_lib(Config, 3),
+ {error,{bad_lib,"Function not found"++_}} = nif_mod:load_nif_lib(Config, 4),
+ {error,{bad_lib,"Duplicate NIF entry for"++_}} = nif_mod:load_nif_lib(Config, 5),
verify_tmpmem(TmpMem),
ok.
@@ -3339,12 +3485,7 @@ random_sign() ->
end.
random_binary() ->
- list_to_binary(random_bytes(rand:uniform(32) - 1)).
-
-random_bytes(0) ->
- [];
-random_bytes(N) when N > 0 ->
- [rand:uniform(256) - 1 | random_bytes(N - 1)].
+ rand:bytes(rand:uniform(32) - 1).
random_pid() ->
Processes = erlang:processes(),
@@ -3397,7 +3538,7 @@ nif_whereis(Config) when is_list(Config) ->
nif_whereis_parallel(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
- %% try to be at least a little asymetric
+ %% try to be at least a little asymmetric
NProcs = trunc(3.7 * erlang:system_info(schedulers)),
NSeq = lists:seq(1, NProcs),
Names = [list_to_atom("nif_whereis_proc_" ++ integer_to_list(N))
@@ -3798,6 +3939,30 @@ nif_term_type(Config) ->
ok.
+%% Verify match state arguments are not passed to declared NIFs.
+match_state_arg(Config) ->
+ ensure_lib_loaded(Config),
+ Bin = term_to_binary([<<"x">> | Config]), % a non-literal binary with an $x byte
+ <<"nif says ok">> = msa_find_x_y(Bin),
+ ok.
+
+%% Without declaring msa_find_y_nif/1 as NIF, the compiler would do
+%% optimization and pass it a match state as argument.
+msa_find_x_y(<<$x, Rest/binary>>) ->
+ msa_find_y_nif(Rest);
+msa_find_x_y(<<_, Rest/binary>>) ->
+ msa_find_x_y(Rest);
+msa_find_x_y(<<>>) ->
+ "no x".
+
+msa_find_y_nif(<<$y, Rest/binary>>) ->
+ Rest;
+msa_find_y_nif(<<_, Rest/binary>>) ->
+ msa_find_y_nif(Rest);
+msa_find_y_nif(<<>>) ->
+ "no y".
+
+
last_resource_dtor_call() ->
erts_debug:set_internal_state(wait, aux_work),
last_resource_dtor_call_nif().
diff --git a/erts/emulator/test/nif_SUITE_data/Makefile.src b/erts/emulator/test/nif_SUITE_data/Makefile.src
index 69dd2d6757..ebbdfe5315 100644
--- a/erts/emulator/test/nif_SUITE_data/Makefile.src
+++ b/erts/emulator/test/nif_SUITE_data/Makefile.src
@@ -3,6 +3,8 @@ NIF_LIBS = nif_SUITE.1@dll@ \
nif_mod.1@dll@ \
nif_mod.2@dll@ \
nif_mod.3@dll@ \
+ nif_mod.4@dll@ \
+ nif_mod.5@dll@ \
nif_mod.1.2_0@dll@ \
nif_mod.2.2_0@dll@ \
nif_mod.3.2_0@dll@ \
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index b664594c76..7a47c2ea99 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -3685,6 +3685,22 @@ static ERL_NIF_TERM term_type_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
}
}
+static ERL_NIF_TERM msa_find_y_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ ErlNifBinary bin;
+ const char ok_str[] = "nif says ok";
+ ERL_NIF_TERM ok_bin;
+
+ /* just verify that arg is a binary (and not a match state) */
+ if (!enif_inspect_binary(env, argv[0], &bin) ||
+ !enif_is_binary(env, argv[0])) {
+ return enif_make_string(env, "nif says arg not a binary", ERL_NIF_LATIN1);
+ }
+ memcpy(enif_make_new_binary(env, strlen(ok_str), &ok_bin),
+ ok_str, strlen(ok_str));
+ return ok_bin;
+}
+
static ErlNifFunc nif_funcs[] =
{
{"lib_version", 0, lib_version},
@@ -3794,7 +3810,8 @@ static ErlNifFunc nif_funcs[] =
{"set_pid_undefined_nif", 0, set_pid_undefined_nif},
{"is_pid_undefined_nif", 1, is_pid_undefined_nif},
{"compare_pids_nif", 2, compare_pids_nif},
- {"term_type_nif", 1, term_type_nif}
+ {"term_type_nif", 1, term_type_nif},
+ {"msa_find_y_nif", 1, msa_find_y_nif}
};
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.4.c b/erts/emulator/test/nif_SUITE_data/nif_mod.4.c
new file mode 100644
index 0000000000..78ede3fbec
--- /dev/null
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.4.c
@@ -0,0 +1,2 @@
+#define NIF_LIB_VER 4
+#include "nif_mod.c"
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.5.c b/erts/emulator/test/nif_SUITE_data/nif_mod.5.c
new file mode 100644
index 0000000000..ea6ab1a07b
--- /dev/null
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.5.c
@@ -0,0 +1,2 @@
+#define NIF_LIB_VER 5
+#include "nif_mod.c"
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c
index edc2a7aac5..6aea107513 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_mod.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c
@@ -391,6 +391,13 @@ static ErlNifFunc nif_funcs[] =
#ifdef HAVE_ENIF_MONITOR_PROCESS
{"monitor_process", 3, monitor_process},
#endif
+#if NIF_LIB_VER == 4
+ {"non_existing", 2, get_resource}, /* error: not found */
+#endif
+#if NIF_LIB_VER == 5
+ {"make_new_resource", 2, get_resource}, /* error: duplicate */
+#endif
+
/* Keep lib_version_check last to maximize the loading "patch distance"
between it and lib_version */
{"lib_version_check", 0, lib_version}
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl
index 1fdaf5dae4..38e2c13a46 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_mod.erl
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,16 @@
-define(nif_stub,nif_stub_error(?LINE)).
+-ifdef(USE_NIFS_ATTRIB).
+-nifs([lib_version/0, nif_api_version/0, get_priv_data_ptr/0]).
+-if(?USE_NIFS_ATTRIB > 1).
+-nifs([make_new_resource/2, get_resource/2, monitor_process/3]).
+-if(?USE_NIFS_ATTRIB > 2).
+-nifs([lib_version_check/0]).
+-endif.
+-endif.
+-endif.
+
-ifdef(USE_ON_LOAD).
-on_load(on_load/0).
diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl
index ec1ac3a042..97ee9adcc0 100644
--- a/erts/emulator/test/node_container_SUITE.erl
+++ b/erts/emulator/test/node_container_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -81,7 +81,7 @@ init_per_testcase(_Case, Config) when is_list(Config) ->
Config.
end_per_testcase(_Case, Config) when is_list(Config) ->
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
%%%
%%% The test cases -------------------------------------------------------------
@@ -151,8 +151,7 @@ ttbtteq_do_remote(RNode) ->
%% Tests that node containers that are sent between nodes stay equal to themselves.
round_trip_eq(Config) when is_list(Config) ->
ThisNode = {node(), erlang:system_info(creation)},
- NodeFirstName = get_nodefirstname(),
- {ok, Node} = start_node(NodeFirstName),
+ {ok, Peer, Node} = ?CT_PEER(),
Self = self(),
RPid = spawn_link(Node,
fun () ->
@@ -186,7 +185,7 @@ round_trip_eq(Config) when is_list(Config) ->
RecLRef,
RecHLRef,
RecSRef}} ->
- stop_node(Node),
+ stop_node(Peer, Node),
SentPid = RecPid,
SentXPid = RecXPid,
SentPort = RecPort,
@@ -486,8 +485,7 @@ make_faked_pid_list(Start, No, Creation, Acc) ->
%% Tests that external reference counts are incremented and decremented
%% as they should for distributed links
dist_link_refc(Config) when is_list(Config) ->
- NodeFirstName = get_nodefirstname(),
- {ok, Node} = start_node(NodeFirstName),
+ {ok, Peer, Node} = ?CT_PEER(),
RP = spawn_execer(Node),
LP = spawn_link_execer(node()),
true = sync_exec(RP, fun () -> link(LP) end),
@@ -510,7 +508,7 @@ dist_link_refc(Config) when is_list(Config) ->
refering_entity_id({process, LP},
get_node_references({Node, NodeCre}))),
exit(LP, normal),
- stop_node(Node),
+ stop_node(Peer, Node),
nc_refc_check(node()),
ok.
@@ -521,8 +519,7 @@ dist_link_refc(Config) when is_list(Config) ->
%% Tests that external reference counts are incremented and decremented
%% as they should for distributed monitors
dist_monitor_refc(Config) when is_list(Config) ->
- NodeFirstName = get_nodefirstname(),
- {ok, Node} = start_node(NodeFirstName),
+ {ok, Peer, Node} = ?CT_PEER(),
RP = spawn_execer(Node),
LP = spawn_link_execer(node()),
RMon = sync_exec(RP, fun () -> erlang:monitor(process, LP) end),
@@ -563,7 +560,7 @@ dist_monitor_refc(Config) when is_list(Config) ->
refering_entity_id({process, LP},
get_node_references({Node, NodeCre}))),
exit(LP, normal),
- stop_node(Node),
+ stop_node(Peer, Node),
nc_refc_check(node()),
ok.
@@ -576,8 +573,7 @@ dist_monitor_refc(Config) when is_list(Config) ->
node_controller_refc(Config) when is_list(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
erts_debug:set_internal_state(node_tab_delayed_delete, 0),
- NodeFirstName = get_nodefirstname(),
- {ok, Node} = start_node(NodeFirstName),
+ {ok, Peer, Node} = ?CT_PEER(),
true = lists:member(Node, nodes()),
1 = reference_type_count(control, get_dist_references(Node)),
P = spawn_link_execer(node()),
@@ -590,7 +586,7 @@ node_controller_refc(Config) when is_list(Config) ->
end),
Creation = rpc:call(Node, erlang, system_info, [creation]),
monitor_node(Node,true),
- stop_node(Node),
+ stop_node(Peer, Node),
receive {nodedown, Node} -> ok end,
DistRefs = get_dist_references(Node),
true = reference_type_count(node, DistRefs) > 0,
@@ -952,7 +948,7 @@ magic_ref(Config) when is_list(Config) ->
ok.
persistent_term(Config) when is_list(Config) ->
- {ok, Node} = start_node(get_nodefirstname()),
+ {ok, Peer, Node} = ?CT_PEER(),
Self = self(),
NcData = make_ref(),
RPid = spawn_link(Node,
@@ -964,7 +960,7 @@ persistent_term(Config) when is_list(Config) ->
{RPid, RPort, RRef}
end,
unlink(RPid),
- stop_node(Node),
+ stop_node(Peer, Node),
Stuff = lists:foldl(fun (N, Acc) ->
persistent_term:put({?MODULE, N}, Data),
persistent_term:erase({?MODULE, N-1}),
@@ -996,7 +992,7 @@ lost_pending_connection(Node) ->
dist_entry_gc(Config) when is_list(Config) ->
Me = self(),
- {ok, Node} = start_node(get_nodefirstname(), "+zdntgc 0"),
+ {ok, Peer, Node} = ?CT_PEER(["+zdntgc", "0"]),
P = spawn_link(Node,
fun () ->
LostNode = list_to_atom("lost_pending_connection@" ++ hostname()),
@@ -1008,15 +1004,16 @@ dist_entry_gc(Config) when is_list(Config) ->
{P, ok} -> ok
end,
unlink(P),
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
huge_ref(Config) when is_list(Config) ->
- {ok, Node} = start_node(get_nodefirstname()),
+ {ok, Peer, Node} = ?CT_PEER(),
HRef = mk_ref({Node, 4711}, [4711, 705676, 3456, 1000000, 3456]),
io:format("HRef=~p~n", [HRef]),
HRef = binary_to_term(term_to_binary(HRef)),
HRef = erpc:call(Node, fun () -> HRef end),
+ peer:stop(Peer),
ok.
%%
@@ -1045,14 +1042,14 @@ nc_refc_check(Node) when is_atom(Node) ->
Self ! {Ref, ErrMsg, failed},
exit(normal)
end),
- Self ! {Ref, succeded}
+ Self ! {Ref, succeeded}
end),
receive
{Ref, ErrorMsg, failed} ->
io:format("~s~n", [ErrorMsg]),
ct:fail(reference_count_check_failed);
- {Ref, succeded} ->
- io:format("Reference count check of node ~w succeded!~n", [Node]),
+ {Ref, succeeded} ->
+ io:format("Reference count check of node ~w succeeded!~n", [Node]),
unlink(Pid),
ok
end.
@@ -1119,23 +1116,9 @@ reference_type_count(Type, ReferingEntities) when is_list(ReferingEntities) ->
0,
ReferingEntities).
-
-start_node(Name, Args) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Res = test_server:start_node(Name,
- slave,
- [{args, "-pa "++Pa++" "++Args}]),
- {ok, Node} = Res,
- rpc:call(Node, erts_debug, set_internal_state,
- [available_internal_state, true]),
- Res.
-
-start_node(Name) ->
- start_node(Name, "").
-
-stop_node(Node) ->
+stop_node(Peer, Node) ->
nc_refc_check(Node),
- true = test_server:stop_node(Node).
+ peer:stop(Peer).
hostname() ->
from($@, atom_to_list(node())).
@@ -1157,9 +1140,6 @@ get_nodefirstname_string() ->
++ "-"
++ integer_to_list(erlang:unique_integer([positive])).
-get_nodefirstname() ->
- list_to_atom(get_nodefirstname_string()).
-
get_nodename() ->
list_to_atom(get_nodefirstname_string()
++ "@"
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index b627b1adab..4b1c9491bc 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -191,15 +191,75 @@ t_float_to_string(Config) when is_list(Config) ->
<<NegZero/float>> = <<16#8000000000000000:64>>,
"-0.0" = float_to_list(NegZero, [{decimals, 1}, compact]),
"-0.0" = float_to_list(NegZero, [{decimals, 1}]),
+ "-0.0" = float_to_list(NegZero, [short]),
"-0.0e+00" = float_to_list(NegZero, [{scientific, 1}]),
"-0.0e+00" = float_to_list(NegZero, [{scientific, 1}, compact]),
<<"-0.0">> = float_to_binary(NegZero, [{decimals, 1}, compact]),
<<"-0.0">> = float_to_binary(NegZero, [{decimals, 1}]),
+ <<"-0.0">> = float_to_binary(NegZero, [short]),
<<"-0.0e+00">> = float_to_binary(NegZero, [{scientific, 1}]),
<<"-0.0e+00">> = float_to_binary(NegZero, [{scientific, 1}, compact]),
fts_rand_float_decimals(1000),
+ % test short option
+
+ % test switch for big integers
+ test_fts("-9007199254740991.0", -float((1 bsl 53) -1), [short]),
+ test_fts("-9.007199254740992e15", -float(1 bsl 53), [short]),
+ test_fts("-9.007199254740992e15", -float((1 bsl 53) +1), [short]),
+ test_fts("9007199254740991.0", float((1 bsl 53) -1), [short]),
+ test_fts("9.007199254740992e15", float(1 bsl 53), [short]),
+ test_fts("9.007199254740992e15", float((1 bsl 53) +1), [short]),
+
+ % test basic
+ test_fts("2.018", 2.018, [short]),
+ test_fts("-2.018", -2.018, [short]),
+
+ % test switching logic between decimal and scientific
+ test_fts("1.0e-6", 1.0e-6, [short]),
+ test_fts("1.0e-5", 1.0e-5, [short]),
+ test_fts("0.0001", 1.0e-4, [short]),
+ test_fts("0.001", 1.0e-3, [short]),
+ test_fts("0.01", 1.0e-2, [short]),
+ test_fts("0.1", 1.0e-1, [short]),
+ test_fts("1.0", 1.0e0, [short]),
+ test_fts("10.0", 1.0e1, [short]),
+ test_fts("100.0", 1.0e2, [short]),
+ test_fts("1.0e3", 1.0e3, [short]),
+ test_fts("1.0e4", 1.0e4, [short]),
+ test_fts("1.0e5", 1.0e5, [short]),
+ test_fts("1.0e6", 1.0e6, [short]),
+ test_fts("1.0e7", 1.0e7, [short]),
+ test_fts("1.234e-6", 1.234e-6, [short]),
+ test_fts("1.234e-5", 1.234e-5, [short]),
+ test_fts("1.234e-4", 1.234e-4, [short]),
+ test_fts("0.001234", 1.234e-3, [short]),
+ test_fts("0.01234", 1.234e-2, [short]),
+ test_fts("0.1234", 1.234e-1, [short]),
+ test_fts("1.234", 1.234e0, [short]),
+ test_fts("12.34", 1.234e1, [short]),
+ test_fts("123.4", 1.234e2, [short]),
+ test_fts("1234.0", 1.234e3, [short]),
+ test_fts("12340.0", 1.234e4, [short]),
+ test_fts("1.234e5", 1.234e5, [short]),
+ test_fts("1.234e6", 1.234e6, [short]),
+
+ % test the switch to subnormals
+ test_fts("2.2250738585072014e-308", 2.2250738585072014e-308, [short]),
+
+ % test lots of trailing zeroes
+ test_fts("2.9802322387695312e-8", 2.98023223876953125e-8, [short]),
+
+ % test some ryu regressions
+ test_fts("-2.109808898695963e16", -2.109808898695963e16, [short]),
+ test_fts("4.940656e-318", 4.940656e-318, [short]),
+ test_fts("1.18575755e-316", 1.18575755e-316, [short]),
+ test_fts("2.989102097996e-312", 2.989102097996e-312, [short]),
+ test_fts("9.0608011534336e15", 9.0608011534336e15, [short]),
+ test_fts("4.708356024711512e18", 4.708356024711512e18, [short]),
+ test_fts("9.409340012568248e18", 9.409340012568248e18, [short]),
+ test_fts("1.2345678", 1.2345678, [short]),
ok.
test_fts(Expect, Float) ->
@@ -245,7 +305,7 @@ fts_rand_float_decimals(N) ->
end,
F1 = list_to_float(L1),
Diff = abs(F0-F1),
- MaxDiff = max_diff_decimals(F0, D),
+ MaxDiff = max_diff_decimals(F0, D-1),
ok = case Diff =< MaxDiff of
true -> ok;
false ->
@@ -610,9 +670,11 @@ t_string_to_integer(Config) when is_list(Config) ->
{"10",''} %Base 20
]),
- %% log2 calculation overflow bug in do_integer_to_list (OTP-12624).
- %% Would crash with segementation fault.
- 0 = list_to_integer(lists:duplicate(10000000,$0)),
+ %% System limit
+ Digits = lists:duplicate(11_000_000, $9),
+ {'EXIT',{system_limit,_}} = catch list_to_integer(Digits),
+ {'EXIT',{system_limit,_}} = catch list_to_integer(Digits, 16),
+ {error,system_limit} = string:to_integer(Digits),
ok.
diff --git a/erts/emulator/test/op_SUITE.erl b/erts/emulator/test/op_SUITE.erl
index d572e037c2..dd13fde16d 100644
--- a/erts/emulator/test/op_SUITE.erl
+++ b/erts/emulator/test/op_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,18 +23,19 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,
- bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,complex_relop/1]).
+ bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,
+ complex_relop/1,unsafe_fusing/1,
+ range_tests/1,typed_relop/1]).
--export([]).
-import(lists, [foldl/3,flatmap/2]).
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {minutes, 5}}].
-all() ->
+all() ->
[bsl_bsr, logical, t_not, relop_simple, relop,
- complex_relop].
+ complex_relop, unsafe_fusing, range_tests, typed_relop].
%% Test the bsl and bsr operators.
bsl_bsr(Config) when is_list(Config) ->
@@ -333,18 +334,25 @@ run_test_module(Cases, GuardsOk) ->
Module = erl_parse:new_anno(Module0),
lists:foreach(fun(F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Module),
- %% Compile, load, and run the generated module.
+ %% Compile, load, and run the generated module. Test both with and
+ %% without compiler optimizations to ensure that we test both the
+ %% implementation of the BIFs and the BEAM instructions.
+ do_run_test_module(Module, []),
+ do_run_test_module(Module, [no_copt,no_ssa_opt,no_postopt]).
+
+do_run_test_module(Module, Opts) ->
+ {ok,Mod,Code1} = compile:forms(Module, [time|Opts]),
+ _ = code:delete(Mod),
+ _ = code:purge(Mod),
- {ok,Mod,Code1} = compile:forms(Module, [time]),
- code:delete(Mod),
- code:purge(Mod),
{module,Mod} = code:load_binary(Mod, Mod, Code1),
+
run_function(Mod, guard_tests),
run_function(Mod, body_tests),
run_function(Mod, bif_tests),
true = code:delete(Mod),
- code:purge(Mod),
+ _ = code:purge(Mod),
ok.
@@ -424,6 +432,274 @@ eval(E0) ->
{value,Val,_Bs} -> Val
end.
+unsafe_fusing(_Config) ->
+ 0 = usec_to_seconds(id(1)),
+ 234_567 = usec_to_seconds(id(1_234_567_890*1_000)),
+ ok.
+
+usec_to_seconds(Usec) when is_integer(Usec) ->
+ %% The introduction of typed operands caused the loader
+ %% to incorrectly fuse the following instrutions because
+ %% the result register ({x,0}) from the 'div' instruction
+ %% seemed to be distinct from both operands of the 'rem'
+ %% instruction:
+ %%
+ %% {gc_bif,'div',
+ %% {f,0},
+ %% 1,
+ %% [{tr,{x,0},{t_integer,any}},{integer,1000000}],
+ %% {x,0}}.
+ %% {gc_bif,'rem',
+ %% {f,0},
+ %% 1,
+ %% [{tr,{x,0},{t_integer,any}},{integer,1000000}],
+ %% {x,0}}.
+ Sec = Usec div 1000000,
+ Sec rem 1000000.
+
+range_tests(_Config) ->
+ %% Define the limits for smalls on a 64-bit system.
+ {MinSmall, MaxSmall} = {-1 bsl 59, (1 bsl 59) - 1},
+ case erlang:system_info(wordsize) of
+ 8 ->
+ %% Assertions.
+ 2 = erts_debug:flat_size(MinSmall-1),
+ 0 = erts_debug:flat_size(MinSmall),
+ 0 = erts_debug:flat_size(MaxSmall),
+ 2 = erts_debug:flat_size(MaxSmall+1);
+ 4 ->
+ ok
+ end,
+
+ lesser = range(-1 bsl 64),
+ lesser = range(MinSmall),
+ lesser = range(0),
+ lesser = range(-1),
+ lesser = range(0.9999),
+
+ inside = range_any(1),
+ inside = range_any(2),
+ inside = range_any(2.5),
+ inside = range_any(math:pi()),
+ inside = range_any(5),
+ inside = range_any(9),
+ inside = range_any(10),
+
+ greater = range(10.0001),
+ greater = range(11),
+ greater = range(MaxSmall),
+ greater = range(1 bsl 64),
+ greater = range(atom),
+ greater = range(self()),
+ greater = range(make_ref()),
+ greater = range({a,b}),
+ greater = range([a,b]),
+ greater = range([]),
+ greater = range(<<1,2,3>>),
+ greater = range(fun() -> ok end),
+ greater = range(fun ?MODULE:range_tests/1),
+
+ lesser = range(-1 bsl 64),
+ lesser = range(float(-1 bsl 64)),
+ lesser = range_big(MinSmall - 2),
+ lesser = range_barely_small(MinSmall - 1),
+
+ inside = range_barely_small(MinSmall),
+ inside = range_barely_small(-1 bsl 58),
+ inside = range_barely_small(0),
+ inside = range_barely_small(17.75),
+ inside = range_barely_small(1 bsl 58),
+ inside = range_barely_small(MaxSmall),
+
+ greater = range_barely_small(MaxSmall + 1),
+ greater = range_big(MaxSmall + 2),
+ greater = range_big(1 bsl 64),
+ greater = range_big(float(1 bsl 64)),
+
+ lesser = range(-1 bsl 64),
+ lesser = range(float(-1 bsl 64)),
+ lesser = range_big(MinSmall - 2),
+
+ inside = range_big(MinSmall),
+ inside = range_big(-1 bsl 58),
+ inside = range_big(0),
+ inside = range_barely_small(17.75),
+ inside = range_big(1 bsl 58),
+ inside = range_big(MaxSmall),
+
+ greater = range_big(MaxSmall + 2),
+ greater = range_big(1 bsl 64),
+ greater = range_big(float(1 bsl 64)),
+
+ ok.
+
+range(X) ->
+ Res = range_any(X),
+ if
+ is_integer(X) ->
+ Res = range_any(float(X)),
+ Res = range_number(X),
+ Res = range_number(float(X)),
+ Res = range_int(X),
+ if
+ X =:= X band 16#ffff ->
+ Res = range_small_int(X);
+ true ->
+ Res
+ end;
+ is_number(X) ->
+ Res = range_number(X);
+ true ->
+ Res = range_big(X),
+ Res = range_barely_small(X)
+ end.
+
+range_any(X0) ->
+ X = id(X0),
+ case range_any_1(X) of
+ inside ->
+ inside = range_any_2(X);
+ Other ->
+ outside = range_any_2(X),
+ Other
+ end.
+
+%% The guard tests have different failure labels.
+range_any_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_any_1(X) when X < 1 ->
+ lesser;
+range_any_1(X) when X > 10 ->
+ greater.
+
+%% The guard tests have the same failure label.
+range_any_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_any_2(_) ->
+ outside.
+
+range_number(X) when is_number(X) ->
+ case range_number_1(X) of
+ inside ->
+ inside = range_number_2(X);
+ Other ->
+ outside = range_number_2(X),
+ Other
+ end.
+
+range_number_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_number_1(X) when X < 1 ->
+ lesser;
+range_number_1(X) when X > 10 ->
+ greater.
+
+range_number_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_number_2(_) ->
+ outside.
+
+range_int(X) when is_integer(X) ->
+ case range_int_1(X) of
+ inside ->
+ inside = range_int_2(X);
+ Other ->
+ outside = range_int_2(X),
+ Other
+ end.
+
+range_int_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_int_1(X) when X < 1 ->
+ lesser;
+range_int_1(X) when X > 10 ->
+ greater.
+
+range_int_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_int_2(_) ->
+ outside.
+
+range_small_int(X) when is_integer(X) ->
+ case range_small_int_1(X) of
+ inside ->
+ inside = range_small_int_2(X);
+ Other ->
+ outside = range_small_int_2(X),
+ Other
+ end.
+
+range_small_int_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_small_int_1(X) when X < 1 ->
+ lesser;
+range_small_int_1(X) when X > 10 ->
+ greater.
+
+range_small_int_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_small_int_2(_) ->
+ outside.
+
+range_barely_small(X) ->
+ case range_barely_small_1(X) of
+ inside ->
+ inside = range_barely_small_2(X);
+ Other ->
+ outside = range_barely_small_2(X),
+ Other
+ end.
+
+range_barely_small_1(X) when -1 bsl 59 =< X, X =< (1 bsl 59) - 1 ->
+ inside;
+range_barely_small_1(X) when X < -1 bsl 59 ->
+ lesser;
+range_barely_small_1(X) when X > (1 bsl 59) - 1 ->
+ greater.
+
+range_barely_small_2(X) when -1 bsl 59 =< X, X =< (1 bsl 59) - 1 ->
+ inside;
+range_barely_small_2(_) ->
+ outside.
+
+range_big(X) ->
+ case range_big_1(X) of
+ inside ->
+ inside = range_big_2(X);
+ Other ->
+ outside = range_big_2(X),
+ Other
+ end.
+
+range_big_1(X) when (-1 bsl 59) - 1 =< X, X =< 1 bsl 59 ->
+ inside;
+range_big_1(X) when X < (-1 bsl 59) - 1 ->
+ lesser;
+range_big_1(X) when X > 1 bsl 59 ->
+ greater.
+
+range_big_2(X) when (-1 bsl 59) - 1 =< X, X =< 1 bsl 59 ->
+ inside;
+range_big_2(_) ->
+ outside.
+
+%% Tests operators where type hints are significant.
+typed_relop(Config) when is_list(Config) ->
+ _ = [compare_integer_pid(1 bsl N) || N <- lists:seq(1, 64)],
+ ok.
+
+compare_integer_pid(N) when is_integer(N) ->
+ Immed = self(),
+ true = is_pid(Immed),
+ if
+ N >= Immed -> ct:fail("integer compared greater than pid");
+ N < Immed -> ok
+ end.
+
+%%%
+%%% Utilities.
+%%%
+
unvalue(V) ->
Abstr = erl_parse:abstract(V),
erl_parse:anno_to_term(Abstr).
diff --git a/erts/emulator/test/persistent_term_SUITE.erl b/erts/emulator/test/persistent_term_SUITE.erl
index a96a099bf4..35216aa78d 100644
--- a/erts/emulator/test/persistent_term_SUITE.erl
+++ b/erts/emulator/test/persistent_term_SUITE.erl
@@ -76,10 +76,10 @@ end_per_suite(Config) ->
init_per_testcase(_, Config) ->
Config.
-end_per_testcase(_, _Config) ->
- ok;
end_per_testcase(get_all_race, _Config) ->
get_all_race_cleanup(),
+ ok;
+end_per_testcase(_, _Config) ->
ok.
basic(_Config) ->
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 6d08bbf92b..bbfb6b52ce 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -226,8 +226,8 @@ init_per_testcase(Case, Config) when Case =:= mon_port_driver_die;
init_per_testcase(Case, Config) ->
[{testcase, Case} |Config].
-end_per_testcase(_Case, _Config) ->
- ok.
+end_per_testcase(_Case, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
init_per_suite(Config) when is_list(Config) ->
ignore_cores:init(Config).
@@ -250,15 +250,9 @@ win_massive(Config) when is_list(Config) ->
do_win_massive() ->
ct:timetrap({minutes, 6}),
- SuiteDir = filename:dirname(code:which(?MODULE)),
- Ports = " +Q 8192",
- {ok, Node} =
- test_server:start_node(win_massive,
- slave,
- [{args, " -pa " ++ SuiteDir ++ Ports}]),
+ {ok, Peer, Node} = ?CT_PEER(["+Q", "8192"]),
ok = rpc:call(Node,?MODULE,win_massive_client,[3000]),
- test_server:stop_node(Node),
- ok.
+ peer:stop(Peer).
win_massive_client(N) ->
{ok,P}=gen_tcp:listen(?WIN_MASSIVE_PORT,[{reuseaddr,true}]),
@@ -766,13 +760,11 @@ iter_max_ports_test(Config) ->
_ -> 10
end,
%% Run on a different node in order to limit the effect if this test fails.
- Dir = filename:dirname(code:which(?MODULE)),
- {ok,Node} = test_server:start_node(test_iter_max_socks,slave,
- [{args,"+Q 2048 -pa " ++ Dir}]),
+ {ok, Peer, Node} = ?CT_PEER(["+Q", "2048"]),
L = rpc:call(Node,?MODULE,do_iter_max_ports,[Iters, Command]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
- io:format("Result: ~p",[L]),
+ ct:log("Result: ~p",[L]),
all_equal(L),
all_equal(L),
{comment, "Max ports: " ++ integer_to_list(hd(L))}.
@@ -809,7 +801,7 @@ open_ports(Name, Settings) ->
case os:type() of
{unix, freebsd} ->
%% FreeBsd has issues with sendmsg/recvmsg in fork
- %% implementation and we therefor have to spawn
+ %% implementation and we therefore have to spawn
%% slower to make sure that we always hit the same
%% make roof.
test_server:sleep(10);
@@ -1307,18 +1299,12 @@ otp_3906(Config) when is_list(Config) ->
otp_3906(Config, OSName) ->
DataDir = filename:dirname(proplists:get_value(data_dir,Config)),
- {ok, Variables} = file:consult(
- filename:join([DataDir,"..","..",
- "test_server","variables"])),
+ {ok, Variables, _} = file:path_consult(code:get_path(),"variables"),
case lists:keysearch('CC', 1, Variables) of
{value,{'CC', CC}} ->
- SuiteDir = filename:dirname(code:which(?MODULE)),
PrivDir = proplists:get_value(priv_dir, Config),
Prog = otp_3906_make_prog(CC, PrivDir),
- {ok, Node} = test_server:start_node(otp_3906,
- slave,
- [{args, " -pa " ++ SuiteDir},
- {linked, false}]),
+ {ok, Peer, Node} = ?CT_PEER(),
OP = process_flag(priority, max),
OTE = process_flag(trap_exit, true),
FS = spawn_link(Node,
@@ -1330,11 +1316,11 @@ otp_3906(Config, OSName) ->
{failed, Reason};
{emulator_pid, EmPid} ->
case otp_3906_wait_result(FS, 0, 0) of
- {succeded,
+ {succeeded,
?OTP_3906_CHILDREN,
?OTP_3906_CHILDREN} ->
- succeded;
- {succeded, Forked, Exited} ->
+ succeeded;
+ {succeeded, Forked, Exited} ->
otp_3906_list_defunct(EmPid, OSName),
{failed,
{mismatch,
@@ -1347,9 +1333,9 @@ otp_3906(Config, OSName) ->
end,
process_flag(trap_exit, OTE),
process_flag(priority, OP),
- test_server:stop_node(Node),
+ peer:stop(Peer),
case Result of
- succeded ->
+ succeeded ->
ok;
_ ->
ct:fail(Result)
@@ -1413,8 +1399,8 @@ otp_3906_wait_result(ForkerStarter, F, E) ->
otp_3906_wait_result(ForkerStarter, F, E+1);
tick ->
otp_3906_wait_result(ForkerStarter, F, E);
- succeded ->
- {succeded, F, E}
+ succeeded ->
+ {succeeded, F, E}
after
?OTP_3906_TICK_TIMEOUT ->
unlink(ForkerStarter),
@@ -1451,7 +1437,7 @@ otp_3906_start_forker_starter(N, RefList, Sup, Prog) ->
otp_3906_forker_starter(0, RefList, Sup, _) ->
otp_3906_collect(RefList, Sup),
unlink(Sup),
- Sup ! succeded;
+ Sup ! succeeded;
otp_3906_forker_starter(N, RefList, Sup, Prog)
when length(RefList) >= ?OTP_3906_MAX_CONC_OSP ->
otp_3906_forker_starter(N, otp_3906_collect_one(RefList, Sup), Sup, Prog);
@@ -1773,7 +1759,7 @@ test_bat_file(Dir) ->
[DN,"hello","world"] =
run_echo_args(Dir,FN,
[default,"hello","world"]),
- %% The arg0 argumant should be ignored when running batch files
+ %% The arg0 argument should be ignored when running batch files
[DN,"hello","world"] =
run_echo_args(Dir,FN,
["knaskurt","hello","world"]),
@@ -1929,6 +1915,7 @@ otp_5112(Config) when is_list(Config) ->
true = lists:member(Port, Links1),
Port ! {self(), {command, ""}},
wait_until(fun () -> lists:member(Port, erlang:ports()) == false end),
+ receive after 1000 -> ok end, %% Give signal some time to propagate...
{links, Links2} = process_info(self(),links),
io:format("Links2: ~p~n",[Links2]),
false = lists:member(Port, Links2), %% This used to fail
@@ -2256,7 +2243,7 @@ port_expect(Config, Actions, HSize, CmdLine, Options0) ->
_ -> {packet, HSize}
end,
Options = [PortType|Options0],
- io:format("open_port({spawn, ~p}, ~p)", [Cmd, Options]),
+ ct:log("open_port({spawn, ~p}, ~p)", [Cmd, Options]),
Port = open_port({spawn, Cmd}, Options),
port_expect(Port, Actions, Options),
Port.
diff --git a/erts/emulator/test/port_SUITE_data/port_test.c b/erts/emulator/test/port_SUITE_data/port_test.c
index fa97b4c9d0..6c56cdf956 100644
--- a/erts/emulator/test/port_SUITE_data/port_test.c
+++ b/erts/emulator/test/port_SUITE_data/port_test.c
@@ -559,7 +559,7 @@ char* spec; /* Specification for reply. */
buf = (char *) malloc(total_size);
if (buf == NULL) {
- fprintf(stderr, "%s: insufficent memory for reply buffer of size %d\n",
+ fprintf(stderr, "%s: insufficient memory for reply buffer of size %d\n",
port_data->progname, (int)total_size);
exit(1);
}
diff --git a/erts/emulator/test/port_bif_SUITE_data/port_test.c b/erts/emulator/test/port_bif_SUITE_data/port_test.c
index ef6d12dc93..fa509d5a15 100644
--- a/erts/emulator/test/port_bif_SUITE_data/port_test.c
+++ b/erts/emulator/test/port_bif_SUITE_data/port_test.c
@@ -536,7 +536,7 @@ char* spec; /* Specification for reply. */
buf = (char *) malloc(total_size);
if (buf == NULL) {
- fprintf(stderr, "%s: insufficent memory for reply buffer of size %d\n",
+ fprintf(stderr, "%s: insufficient memory for reply buffer of size %d\n",
port_data->progname, total_size);
exit(1);
}
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index f5abc2cdbd..114fa42da8 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
%% process_info/1,2
%% register/2 (partially)
+-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-define(heap_binary_size, 64).
@@ -37,24 +38,34 @@
t_exit_2_catch/1, trap_exit_badarg/1, trap_exit_badarg_in_bif/1,
exit_and_timeout/1, exit_twice/1,
t_process_info/1, process_info_other/1, process_info_other_msg/1,
+ process_info_other_message_queue_len_signal_race/1,
process_info_other_dist_msg/1,
process_info_other_status/1,
process_info_2_list/1, process_info_lock_reschedule/1,
process_info_lock_reschedule2/1,
process_info_lock_reschedule3/1,
process_info_garbage_collection/1,
+ process_info_parent/1,
process_info_smoke_all/1,
process_info_status_handled_signal/1,
process_info_reductions/1,
+ process_info_self_signal/1,
+ process_info_self_msgq_len/1,
+ process_info_self_msgq_len_messages/1,
+ process_info_self_msgq_len_more/1,
bump_reductions/1, low_prio/1, binary_owner/1, yield/1, yield2/1,
- otp_4725/1, bad_register/1, garbage_collect/1, otp_6237/1,
+ otp_4725/1, dist_unlink_ack_exit_leak/1, bad_register/1,
+ garbage_collect/1, otp_6237/1,
process_info_messages/1, process_flag_badarg/1,
process_flag_fullsweep_after/1, process_flag_heap_size/1,
+ command_line_max_heap_size/1,
spawn_opt_heap_size/1, spawn_opt_max_heap_size/1,
+ more_spawn_opt_max_heap_size/1,
processes_large_tab/1, processes_default_tab/1, processes_small_tab/1,
processes_this_tab/1, processes_apply_trap/1,
processes_last_call_trap/1, processes_gc_trap/1,
processes_term_proc_list/1,
+ processes_send_infant/1,
otp_7738_waiting/1, otp_7738_suspended/1,
otp_7738_resume/1,
garb_other_running/1,
@@ -73,14 +84,18 @@
spawn_request_monitor_child_exit/1,
spawn_request_link_child_exit/1,
spawn_request_link_parent_exit/1,
+ spawn_request_link_parent_exit_compound_reason/1,
+ spawn_request_link_parent_exit_nodedown/1,
spawn_request_abandon_bif/1,
dist_spawn_monitor/1,
- spawn_old_node/1,
- spawn_new_node/1,
+ spawn_against_ei_node/1,
+ spawn_against_old_node/1,
+ spawn_against_new_node/1,
spawn_request_reply_option/1,
alias_bif/1,
monitor_alias/1,
spawn_monitor_alias/1,
+ alias_process_exit/1,
monitor_tag/1]).
-export([prio_server/2, prio_client/2, init/1, handle_event/2]).
@@ -90,6 +105,8 @@
-export([hangaround/2, processes_bif_test/0, do_processes/1,
processes_term_proc_list_test/1, huge_arglist_child/255]).
+-export([spawn_request_test_exit_child/1]).
+
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {minutes, 9}}].
@@ -97,33 +114,17 @@ suite() ->
all() ->
[spawn_with_binaries, t_exit_1, {group, t_exit_2},
trap_exit_badarg, trap_exit_badarg_in_bif,
- t_process_info, process_info_other, process_info_other_msg,
- process_info_other_dist_msg, process_info_other_status,
- process_info_2_list,
- process_info_lock_reschedule,
- process_info_lock_reschedule2,
- process_info_lock_reschedule3,
- process_info_garbage_collection,
- process_info_smoke_all,
- process_info_status_handled_signal,
- process_info_reductions,
bump_reductions, low_prio, yield, yield2, otp_4725,
- bad_register, garbage_collect, process_info_messages,
+ dist_unlink_ack_exit_leak, bad_register, garbage_collect,
process_flag_badarg,
process_flag_fullsweep_after, process_flag_heap_size,
+ command_line_max_heap_size,
spawn_opt_heap_size, spawn_opt_max_heap_size,
+ more_spawn_opt_max_heap_size,
spawn_huge_arglist,
- spawn_request_bif,
- spawn_request_monitor_demonitor,
- spawn_request_monitor_child_exit,
- spawn_request_link_child_exit,
- spawn_request_link_parent_exit,
- spawn_request_abandon_bif,
- dist_spawn_monitor,
- spawn_old_node,
- spawn_new_node,
- spawn_request_reply_option,
otp_6237,
+ {group, spawn_request},
+ {group, process_info_bif},
{group, processes_bif},
{group, otp_7738}, garb_other_running,
{group, system_task},
@@ -135,11 +136,44 @@ groups() ->
[t_exit_2_other, t_exit_2_other_normal, self_exit,
normal_suicide_exit, abnormal_suicide_exit,
t_exit_2_catch, exit_and_timeout, exit_twice]},
+ {spawn_request, [],
+ [spawn_request_bif,
+ spawn_request_monitor_demonitor,
+ spawn_request_monitor_child_exit,
+ spawn_request_link_child_exit,
+ spawn_request_link_parent_exit,
+ spawn_request_link_parent_exit_compound_reason,
+ spawn_request_link_parent_exit_nodedown,
+ spawn_request_abandon_bif,
+ dist_spawn_monitor,
+ spawn_against_ei_node,
+ spawn_against_old_node,
+ spawn_against_new_node,
+ spawn_request_reply_option]},
{processes_bif, [],
[processes_large_tab, processes_default_tab,
processes_small_tab, processes_this_tab,
processes_last_call_trap, processes_apply_trap,
- processes_gc_trap, processes_term_proc_list]},
+ processes_gc_trap, processes_term_proc_list,
+ processes_send_infant]},
+ {process_info_bif, [],
+ [t_process_info, process_info_messages,
+ process_info_other, process_info_other_msg,
+ process_info_other_message_queue_len_signal_race,
+ process_info_other_dist_msg, process_info_other_status,
+ process_info_2_list,
+ process_info_lock_reschedule,
+ process_info_lock_reschedule2,
+ process_info_lock_reschedule3,
+ process_info_garbage_collection,
+ process_info_parent,
+ process_info_smoke_all,
+ process_info_status_handled_signal,
+ process_info_reductions,
+ process_info_self_signal,
+ process_info_self_msgq_len,
+ process_info_self_msgq_len_messages,
+ process_info_self_msgq_len_more]},
{otp_7738, [],
[otp_7738_waiting, otp_7738_suspended,
otp_7738_resume]},
@@ -149,7 +183,7 @@ groups() ->
gc_request_when_gc_disabled, gc_request_blast_when_gc_disabled,
otp_16436, otp_16642]},
{alias, [],
- [alias_bif, monitor_alias, spawn_monitor_alias]}].
+ [alias_bif, monitor_alias, spawn_monitor_alias, alias_process_exit]}].
init_per_suite(Config) ->
A0 = case application:start(sasl) of
@@ -168,9 +202,15 @@ end_per_suite(Config) ->
catch erts_debug:set_internal_state(available_internal_state, false),
Config.
+init_per_group(alias, Config) ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ Config;
init_per_group(_GroupName, Config) ->
Config.
+end_per_group(alias, Config) ->
+ erts_debug:set_internal_state(available_internal_state, false),
+ Config;
end_per_group(_GroupName, Config) ->
Config.
@@ -192,7 +232,7 @@ end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
#{size => 0,
kill => true,
error_logger => true}),
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
fun_spawn(Fun) ->
spawn_link(erlang, apply, [Fun, []]).
@@ -309,7 +349,7 @@ abnormal_suicide_exit(Config) when is_list(Config) ->
Other -> ct:fail({bad_message, Other})
end.
-%% Tests that exit(self(), die) cannot be catched.
+%% Tests that exit(self(), die) cannot be caught.
t_exit_2_catch(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Pid = fun_spawn(fun() -> catch exit(self(), die) end),
@@ -328,7 +368,19 @@ trap_exit_badarg(Config) when is_list(Config) ->
ct:timetrap({seconds, 10}),
start_spawner(),
process_flag(trap_exit, true),
- test_server:do_times(10, fun trap_exit_badarg/0),
+ try
+ %% suppress =ERROR REPORT=== emulator messages
+ ok = logger:add_primary_filter(suppress_log_spam, {
+ fun(#{meta := #{error_logger := #{emulator := true, tag := error}}}, _Report) ->
+ stop;
+ (_Meta, _Report) ->
+ ignore
+ end, ok}),
+ test_server:do_times(10, fun trap_exit_badarg/0),
+ ct:sleep(500) %% flush logging
+ after
+ ok = logger:remove_primary_filter(suppress_log_spam)
+ end,
stop_spawner(),
ok.
@@ -648,12 +700,75 @@ process_info_other_msg(Config) when is_list(Config) ->
Pid ! stop,
ok.
+process_info_other_message_queue_len_signal_race(Config) when is_list(Config) ->
+ %% OTP-18169
+ %%
+ %% The race window triggering this bug is quite small. This test
+ %% wont fail even with the bug present, but it may trigger an
+ %% assertion in the debug compiled emulator if the bug is
+ %% present...
+ process_flag(priority, high),
+ SSchdlr = case erlang:system_info(schedulers_online) of
+ 1 -> 1;
+ _ -> 2
+ end,
+ Flush = fun Flush () ->
+ receive _ -> Flush()
+ after 0 -> ok
+ end
+ end,
+ RFun = fun RFun () ->
+ receive
+ {flush, From} ->
+ Flush(),
+ From ! flushed
+ end,
+ RFun()
+ end,
+ R = spawn_opt(RFun, [link,
+ {scheduler, 1},
+ {message_queue_data, on_heap}]),
+ SFun = fun SFun () ->
+ receive go -> ok end,
+ M = erlang:monitor(process, R),
+ R ! hi,
+ receive
+ {demonitor, From} ->
+ _ = erlang:demonitor(M),
+ From ! demonitored
+ end,
+ SFun()
+ end,
+ S = spawn_opt(SFun, [link,
+ {scheduler, SSchdlr},
+ {priority, high}]),
+ process_info_other_message_queue_len_signal_race_test(10000, S, R),
+ unlink(R),
+ exit(R, kill),
+ unlink(S),
+ exit(S, kill),
+ false = is_process_alive(R),
+ false = is_process_alive(S),
+ ok.
+
+process_info_other_message_queue_len_signal_race_test(0, _S, _R) ->
+ ok;
+process_info_other_message_queue_len_signal_race_test(N, S, R) ->
+ S ! go,
+ erlang:yield(),
+ _ = process_info(R, message_queue_len),
+ S ! {demonitor, self()},
+ receive demonitored -> ok end,
+ R ! {flush, self()},
+ receive flushed -> ok end,
+ process_info_other_message_queue_len_signal_race_test(N-1, S, R).
+
process_info_other_dist_msg(Config) when is_list(Config) ->
%%
%% Check that process_info can handle messages that have not been
%% decoded yet.
%%
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
Self = self(),
Pid = spawn_link(fun() -> other_process(Self) end),
receive {go_ahead,Pid} -> ok end,
@@ -696,7 +811,7 @@ process_info_other_dist_msg(Config) when is_list(Config) ->
end,
{messages,[]} = process_info(Pid, messages),
Pid ! stop,
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
process_info_other_status(Config) when is_list(Config) ->
@@ -1050,6 +1165,30 @@ process_info_garbage_collection(_Config) ->
gv(Key,List) ->
proplists:get_value(Key,List).
+process_info_parent(Config) when is_list(Config) ->
+ Child = spawn_link(fun () -> receive stop -> ok end end),
+ ?assertEqual({parent, self()}, erlang:process_info(Child, parent)),
+ Child ! stop,
+ ?assertEqual({parent, undefined}, erlang:process_info(whereis(init), parent)),
+
+ {ok, Peer, Node} = ?CT_PEER(),
+ RemoteChild = spawn_link(Node,
+ fun () ->
+ {parent, Parent} = process_info(self(), parent),
+ garbage_collect(),
+ {parent, Parent} = process_info(self(), parent),
+ garbage_collect(),
+ Parent ! remote_child_hello,
+ receive stop -> ok end
+ end),
+ ?assertEqual({parent, self()},
+ erpc:call(Node, erlang, process_info, [RemoteChild, parent])),
+ receive remote_child_hello -> ok end,
+ unlink(RemoteChild),
+ RemoteChild ! stop,
+ peer:stop(Peer),
+ ok.
+
process_info_smoke_all_tester() ->
register(process_info_smoke_all_tester, self()),
put(ets_ref, ets:new(blupp, [])),
@@ -1106,7 +1245,7 @@ process_info_smoke_all(Config) when is_list(Config) ->
magic_ref,
fullsweep_after],
- {ok, Node} = start_node(Config, ""),
+ {ok, Peer, Node} = ?CT_PEER(),
RP = spawn_link(Node, fun process_info_smoke_all_tester/0),
LP = spawn_link(fun process_info_smoke_all_tester/0),
RP ! {other_process, LP},
@@ -1126,7 +1265,7 @@ process_info_smoke_all(Config) when is_list(Config) ->
exit(RP, kill),
exit(LP, kill),
false = is_process_alive(LP),
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
process_info_status_handled_signal(Config) when is_list(Config) ->
@@ -1233,6 +1372,146 @@ pi_reductions_main_unlocker_loop(Other) ->
erlang:yield(),
pi_reductions_main_unlocker_loop(Other).
+process_info_self_signal(Config) when is_list(Config) ->
+ %% Test that signals that we have sent to ourselves are
+ %% visible in process_info() result. This is not strictly
+ %% a necessary property, but implemented so now. See
+ %% process_info.c:process_info_bif() for more info.
+ Self = self(),
+ Ref = make_ref(),
+ pi_sig_spam_test(fun () ->
+ process_info_self_signal_spammer(Self)
+ end,
+ fun () ->
+ self() ! Ref,
+ process_info(self(), messages)
+ end,
+ fun (Res) ->
+ {messages, [Ref]} = Res
+ end).
+
+process_info_self_signal_spammer(To) ->
+ erlang:demonitor(erlang:monitor(process, To)),
+ process_info_self_signal_spammer(To).
+
+process_info_self_msgq_len(Config) when is_list(Config) ->
+ %% Spam ourselves with signals forcing us to flush own
+ %% signal queue..
+ Self = self(),
+ pi_sig_spam_test(fun () ->
+ process_info_self_msgq_len_spammer(Self)
+ end,
+ fun () ->
+ process_info(self(), message_queue_len)
+ end,
+ fun (Res) ->
+ {message_queue_len, Len} = Res,
+ true = Len > 0,
+ ok
+ end).
+
+
+process_info_self_msgq_len_messages(Config) when is_list(Config) ->
+ %% Spam ourselves with signals normally forcing us to flush own
+ %% signal queue, but since we also want messages wont be flushed...
+ Self = self(),
+ pi_sig_spam_test(fun () ->
+ process_info_self_msgq_len_spammer(Self, 100000)
+ end,
+ fun () ->
+ process_info(self(),
+ [message_queue_len,
+ messages])
+ end,
+ fun (Res) ->
+ [{message_queue_len, Len},
+ {messages, Msgs}] = Res,
+ Len = length(Msgs),
+ ok
+ end).
+
+process_info_self_msgq_len_more(Config) when is_list(Config) ->
+ self() ! hej,
+ BodyRes = process_info_self_msgq_len_more_caller_body(),
+ ok = process_info_self_msgq_len_more_caller_body_result(BodyRes),
+ TailRes = process_info_self_msgq_len_more_caller_tail(),
+ ok = process_info_self_msgq_len_more_caller_tail_result(TailRes),
+ receive hej -> ok end,
+ %% Check that current_function, current_location, and
+ %% current_stacktrace give sane results flushing or not...
+ Self = self(),
+ pi_sig_spam_test(fun () ->
+ process_info_self_msgq_len_spammer(Self)
+ end,
+ fun process_info_self_msgq_len_more_caller_body/0,
+ fun process_info_self_msgq_len_more_caller_body_result/1),
+ pi_sig_spam_test(fun () ->
+ process_info_self_msgq_len_spammer(Self)
+ end,
+ fun process_info_self_msgq_len_more_caller_tail/0,
+ fun process_info_self_msgq_len_more_caller_tail_result/1).
+
+process_info_self_msgq_len_more_caller_body() ->
+ Res = process_info(self(),
+ [message_queue_len,
+ current_function,
+ current_location,
+ current_stacktrace]),
+ id(Res).
+
+process_info_self_msgq_len_more_caller_body_result(Res) ->
+ [{message_queue_len, Len},
+ {current_function, {process_SUITE,process_info_self_msgq_len_more_caller_body,0}},
+ {current_location, {process_SUITE,process_info_self_msgq_len_more_caller_body,0,_}},
+ {current_stacktrace,
+ [{process_SUITE,process_info_self_msgq_len_more_caller_body,0,_} | _]}] = Res,
+ true = Len > 0,
+ ok.
+
+process_info_self_msgq_len_more_caller_tail() ->
+ process_info(self(),
+ [message_queue_len,
+ current_function,
+ current_location,
+ current_stacktrace]).
+
+process_info_self_msgq_len_more_caller_tail_result(Res) ->
+ [{message_queue_len, Len},
+ {current_function, {process_SUITE,process_info_self_msgq_len_more_caller_tail,0}},
+ {current_location, {process_SUITE,process_info_self_msgq_len_more_caller_tail,0,_}},
+ {current_stacktrace,
+ [{process_SUITE,process_info_self_msgq_len_more_caller_tail,0,_} | _]}] = Res,
+ true = Len > 0,
+ ok.
+
+
+process_info_self_msgq_len_spammer(To) ->
+ process_info_self_msgq_len_spammer(To, 10000000).
+
+process_info_self_msgq_len_spammer(_To, 0) ->
+ ok;
+process_info_self_msgq_len_spammer(To, N) ->
+ To ! hejhopp,
+ erlang:demonitor(erlang:monitor(process, To)),
+ process_info_self_msgq_len_spammer(To, N-1).
+
+pi_sig_spam_test(SpamFun, PITest, PICheckRes) ->
+ SO = erlang:system_flag(schedulers_online, 1),
+ try
+ Self = self(),
+ SigSpammer = spawn_link(SpamFun),
+ process_flag(priority, low),
+ receive after 10 -> ok end,
+ Res = PITest(),
+ process_flag(priority, high),
+ unlink(SigSpammer),
+ exit(SigSpammer, kill),
+ false = is_process_alive(SigSpammer),
+ PICheckRes(Res)
+ after
+ _ = erlang:system_flag(schedulers_online, SO)
+ end.
+
%% Tests erlang:bump_reductions/1.
bump_reductions(Config) when is_list(Config) ->
@@ -1352,7 +1631,7 @@ yield(Config) when is_list(Config) ->
Level when is_integer(Level) ->
{skipped,
"Modified timing (level " ++ integer_to_list(Level)
- ++ ") is enabled. Testcase gets messed up by modfied "
+ ++ ") is enabled. Testcase gets messed up by modified "
"timing."};
_ ->
MS = erlang:system_flag(multi_scheduling, block_normal),
@@ -1491,6 +1770,43 @@ next_tmsg(Pid) ->
none
end.
+dist_unlink_ack_exit_leak(Config) when is_list(Config) ->
+ %% Verification of nc reference counts when stopping node
+ %% will find the bug if it exists...
+ {ok, Peer, Node} = ?CT_PEER(),
+ ParentFun =
+ fun () ->
+ %% Give parent some work to do when
+ %% exiting to increase the likelyhood
+ %% of the bug triggereing...
+ T = ets:new(x,[]),
+ ets:insert(T, lists:map(fun (I) ->
+ {I,I}
+ end,
+ lists:seq(1,10000))),
+ Chld = spawn_link(Node,
+ fun () ->
+ receive
+ after infinity ->
+ ok
+ end
+ end),
+ erlang:yield(),
+ unlink(Chld),
+ exit(bye)
+ end,
+ PMs = lists:map(fun (_) ->
+ spawn_monitor(ParentFun)
+ end, lists:seq(1, 10)),
+ lists:foreach(fun ({P, M}) ->
+ receive
+ {'DOWN', M, process, P, bye} ->
+ ok
+ end
+ end, PMs),
+ stop_node(Peer, Node),
+ ok.
+
%% Test that bad arguments to register/2 cause an exception.
bad_register(Config) when is_list(Config) ->
Name = a_long_and_unused_name,
@@ -1721,9 +2037,9 @@ otp_6237_select_loop() ->
debug_level}).
processes_large_tab(Config) when is_list(Config) ->
- sys_mem_cond_run(2048, fun () -> processes_large_tab_test(Config) end).
+ sys_mem_cond_run(2048, fun () -> processes_large_tab_test() end).
-processes_large_tab_test(Config) ->
+processes_large_tab_test() ->
enable_internal_state(),
MaxDbgLvl = 20,
MinProcTabSize = 2*(1 bsl 15),
@@ -1757,8 +2073,7 @@ processes_large_tab_test(Config) ->
true -> MinProcTabSize;
false -> ProcTabSize3
end,
- {ok, LargeNode} = start_node(Config,
- "+P " ++ integer_to_list(ProcTabSize)),
+ {ok, Peer, LargeNode} = ?CT_PEER(["+P", integer_to_list(ProcTabSize)]),
Res = rpc:call(LargeNode, ?MODULE, processes_bif_test, []),
case rpc:call(LargeNode,
erts_debug,
@@ -1768,23 +2083,23 @@ processes_large_tab_test(Config) ->
Chunks > 1 -> ok;
PBInfo -> ct:fail(PBInfo)
end,
- stop_node(LargeNode),
+ stop_node(Peer, LargeNode),
chk_processes_bif_test_res(Res).
processes_default_tab(Config) when is_list(Config) ->
- sys_mem_cond_run(1024, fun () -> processes_default_tab_test(Config) end).
+ sys_mem_cond_run(1024, fun () -> processes_default_tab_test() end).
-processes_default_tab_test(Config) ->
- {ok, DefaultNode} = start_node(Config, ""),
+processes_default_tab_test() ->
+ {ok, Peer, DefaultNode} = ?CT_PEER(),
Res = rpc:call(DefaultNode, ?MODULE, processes_bif_test, []),
- stop_node(DefaultNode),
+ stop_node(Peer, DefaultNode),
chk_processes_bif_test_res(Res).
processes_small_tab(Config) when is_list(Config) ->
- {ok, SmallNode} = start_node(Config, "+P 1024"),
+ {ok, Peer, SmallNode} = ?CT_PEER(["+P","1024"]),
Res = rpc:call(SmallNode, ?MODULE, processes_bif_test, []),
PBInfo = rpc:call(SmallNode, erts_debug, get_internal_state, [processes_bif_info]),
- stop_node(SmallNode),
+ stop_node(Peer, SmallNode),
true = PBInfo#ptab_list_bif_info.tab_chunks < 10,
chk_processes_bif_test_res(Res).
@@ -1940,7 +2255,7 @@ processes_bif_test() ->
false ->
ok;
true ->
- %% Do it again with a process suspended while
+ %% Do it against with a process suspended while
%% in the processes/0 bif.
erlang:system_flag(multi_scheduling, block_normal),
Suspendee = spawn_link(fun () ->
@@ -2254,6 +2569,18 @@ process_flag_heap_size(Config) when is_list(Config) ->
VHSize = erlang:process_flag(min_bin_vheap_size, OldVHmin),
ok.
+%% test that max_heap_size is correctly handled when passed via command line
+command_line_max_heap_size(Config) when is_list(Config) ->
+ %% test maximum heap size
+ HMax = case erlang:system_info(wordsize) of
+ 8 -> (1 bsl 59) - 1;
+ 4 -> (1 bsl 27) - 1
+ end,
+ {ok, Peer, Node} = ?CT_PEER(["+hmax", integer_to_list(HMax)]),
+ Pid = erlang:spawn(Node, fun () -> receive after infinity -> ok end end),
+ {max_heap_size, #{size := HMax}} = rpc:call(Node, erlang, process_info, [Pid, max_heap_size]),
+ peer:stop(Peer).
+
spawn_opt_heap_size(Config) when is_list(Config) ->
HSize = 987, % must be gc fib+ number
VHSize = 46422, % must be gc fib+ number
@@ -2395,6 +2722,111 @@ flush() ->
ok
end.
+%% Make sure that when maximum allowed heap size is exceeded, the
+%% process will actually terminate.
+%%
+%% Despite the timetrap and limit of number of iterations, bugs
+%% provoked by the test case can cause the runtime system to hang in
+%% this test case.
+more_spawn_opt_max_heap_size(_Config) ->
+ ct:timetrap({minutes,1}),
+ Funs = [fun build_and_bif/0,
+ fun build_bin_and_bif/0,
+ fun build_and_recv_timeout/0,
+ fun build_and_recv_msg/0,
+ fun bif_and_recv_timeout/0,
+ fun bif_and_recv_msg/0
+ ],
+ _ = [begin
+ {Pid,Ref} = spawn_opt(F, [{max_heap_size,
+ #{size => 233, kill => true,
+ error_logger => false}},
+ monitor]),
+ io:format("~p ~p\n", [Pid,F]),
+ receive
+ {'DOWN',Ref,process,Pid,Reason} ->
+ killed = Reason
+ end
+ end || F <- Funs],
+ ok.
+
+%% This number should be greater than the default heap size.
+-define(MANY_ITERATIONS, 10_000).
+
+build_and_bif() ->
+ build_and_bif(?MANY_ITERATIONS, []).
+
+build_and_bif(0, Acc0) ->
+ Acc0;
+build_and_bif(N, Acc0) ->
+ Acc = [0|Acc0],
+ _ = erlang:crc32(Acc),
+ build_and_bif(N-1, Acc).
+
+build_bin_and_bif() ->
+ build_bin_and_bif(?MANY_ITERATIONS, <<>>).
+
+build_bin_and_bif(0, Acc0) ->
+ Acc0;
+build_bin_and_bif(N, Acc0) ->
+ Acc = <<0, Acc0/binary>>,
+ _ = erlang:crc32(Acc),
+ build_bin_and_bif(N-1, Acc).
+
+build_and_recv_timeout() ->
+ build_and_recv_timeout(?MANY_ITERATIONS, []).
+
+build_and_recv_timeout(0, Acc0) ->
+ Acc0;
+build_and_recv_timeout(N, Acc0) ->
+ Acc = [0|Acc0],
+ receive
+ after 1 ->
+ ok
+ end,
+ build_and_recv_timeout(N-1, Acc).
+
+build_and_recv_msg() ->
+ build_and_recv_msg(?MANY_ITERATIONS, []).
+
+build_and_recv_msg(0, Acc0) ->
+ Acc0;
+build_and_recv_msg(N, Acc0) ->
+ Acc = [0|Acc0],
+ receive
+ _ ->
+ ok
+ after 0 ->
+ ok
+ end,
+ build_and_recv_msg(N-1, Acc).
+
+bif_and_recv_timeout() ->
+ Bin = <<0:?MANY_ITERATIONS/unit:8>>,
+ bif_and_recv_timeout(Bin).
+
+bif_and_recv_timeout(Bin) ->
+ List = binary_to_list(Bin),
+ receive
+ after 1 ->
+ ok
+ end,
+ List.
+
+bif_and_recv_msg() ->
+ Bin = <<0:?MANY_ITERATIONS/unit:8>>,
+ bif_and_recv_msg(Bin).
+
+bif_and_recv_msg(Bin) ->
+ List = binary_to_list(Bin),
+ receive
+ _ ->
+ ok
+ after 0 ->
+ ok
+ end,
+ List.
+
%% error_logger report handler proxy
init(Pid) ->
{ok, Pid}.
@@ -2478,11 +2910,11 @@ spawn_huge_arglist(Config) when is_list(Config) ->
spawn_huge_arglist_test(true, node(), ArgList),
io:format("Testing spawn with huge argument list on local node with Node...~n", []),
spawn_huge_arglist_test(false, node(), ArgList),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
_ = rpc:call(Node, ?MODULE, module_info, []),
io:format("Testing spawn with huge argument list on remote node ~p...~n", [Node]),
spawn_huge_arglist_test(false, Node, ArgList),
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
spawn_huge_arglist_test(Local, Node, ArgList) ->
@@ -2564,10 +2996,10 @@ spawn_request_bif(Config) when is_list(Config) ->
spawn_request_bif_test(true, node()),
io:format("Testing spawn_request() on local node with Node...~n", []),
spawn_request_bif_test(false, node()),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
io:format("Testing spawn_request() on remote node ~p...~n", [Node]),
spawn_request_bif_test(false, Node),
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
spawn_request_bif_test(Local, Node) ->
@@ -2836,7 +3268,7 @@ spawn_request_bif_test(Local, Node) ->
spawn_request_monitor_demonitor(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
BlockFun = fun () ->
erts_debug:set_internal_state(available_internal_state, true),
erts_debug:set_internal_state(block, 1000),
@@ -2847,25 +3279,20 @@ spawn_request_monitor_demonitor(Config) when is_list(Config) ->
spawn_request(Node, BlockFun, [{priority,max}, link]),
receive after 100 -> ok end,
- erlang:display(spawning),
erlang:yield(),
R = spawn_request(Node, timer, sleep, [10000], [monitor]),
%% Should not be possible to demonitor
%% before operation has succeeded...
- erlang:display(premature_demonitor),
{monitors, []} = process_info(self(), monitors),
false = erlang:demonitor(R, [info]), %% Should be ignored by VM...
- erlang:display(wait_success),
receive
{spawn_reply, R, ok, P} ->
- erlang:display(demonitor),
{monitors, [{process,P}]} = process_info(self(), monitors),
true = erlang:demonitor(R, [info]),
{monitors, []} = process_info(self(), monitors),
exit(P, kill)
end,
- erlang:display(done),
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
spawn_request_monitor_child_exit(Config) when is_list(Config) ->
@@ -2879,7 +3306,7 @@ spawn_request_monitor_child_exit(Config) when is_list(Config) ->
{undef, _} = Reason1
end
end,
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
R2 = spawn_request(Node, nonexisting_module, nonexisting_function, [], [{reply_tag, Tag}, monitor]),
receive
{Tag, R2, ok, P2} ->
@@ -2888,7 +3315,7 @@ spawn_request_monitor_child_exit(Config) when is_list(Config) ->
{undef, _} = Reason2
end
end,
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
spawn_request_link_child_exit(Config) when is_list(Config) ->
@@ -2903,7 +3330,7 @@ spawn_request_link_child_exit(Config) when is_list(Config) ->
{undef, _} = Reason1
end
end,
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
R2 = spawn_request(Node, nonexisting_module, nonexisting_function, [], [link, {reply_tag, Tag}]),
receive
{Tag, R2, ok, P2} ->
@@ -2912,70 +3339,163 @@ spawn_request_link_child_exit(Config) when is_list(Config) ->
{undef, _} = Reason2
end
end,
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
spawn_request_link_parent_exit(Config) when is_list(Config) ->
- C1 = spawn_request_link_parent_exit_test(node()),
- {ok, Node} = start_node(Config),
- C2 = spawn_request_link_parent_exit_test(Node),
- stop_node(Node),
+ C1 = spawn_request_link_parent_exit_test(node(), false),
+ {ok, Peer, Node} = ?CT_PEER(),
+ C2 = spawn_request_link_parent_exit_test(Node, false),
+ stop_node(Peer, Node),
+ {comment, C1 ++ " " ++ C2}.
+
+spawn_request_link_parent_exit_compound_reason(Config) when is_list(Config) ->
+ C1 = spawn_request_link_parent_exit_test(node(), true),
+ {ok, Peer, Node} = ?CT_PEER(),
+ C2 = spawn_request_link_parent_exit_test(Node, true),
+ stop_node(Peer, Node),
{comment, C1 ++ " " ++ C2}.
-spawn_request_link_parent_exit_test(Node) ->
+spawn_request_link_parent_exit_test(Node, CompoundExitReason) ->
%% Early parent exit...
Tester = self(),
+ ExitReason = if CompoundExitReason -> "kaboom";
+ true -> kaboom
+ end,
+
verify_nc(node()),
%% Ensure code loaded on other node...
_ = rpc:call(Node, ?MODULE, module_info, []),
- ChildFun = fun () ->
- Child = self(),
- spawn_opt(fun () ->
- process_flag(trap_exit, true),
- receive
- {'EXIT', Child, Reason} ->
- Tester ! {parent_exit, Reason}
- end
- end, [link,{priority,max}]),
- receive after infinity -> ok end
- end,
ParentFun = case node() == Node of
true ->
fun (Wait) ->
- spawn_request(ChildFun, [link,{priority,max}]),
+ spawn_request(?MODULE, spawn_request_test_exit_child,
+ [Tester], [link,{priority,max}]),
receive after Wait -> ok end,
- exit(kaboom)
+ exit(ExitReason)
end;
false ->
fun (Wait) ->
- spawn_request(Node, ChildFun, [link,{priority,max}]),
+ spawn_request(Node, ?MODULE,
+ spawn_request_test_exit_child,
+ [Tester], [link,{priority,max}]),
receive after Wait -> ok end,
- exit(kaboom)
+ exit(ExitReason)
end
end,
lists:foreach(fun (N) ->
- spawn(fun () -> ParentFun(N rem 10) end)
+ spawn_opt(fun () ->
+ %% Give parent some work to do when
+ %% exiting and by this increase
+ %% possibilities for races...
+ T = ets:new(x,[]),
+ ets:insert(T, lists:map(fun (I) ->
+ {I,I}
+ end,
+ lists:seq(1,10000))),
+ ParentFun(N rem 10) end,
+ [{priority, max}])
end,
- lists:seq(1, 1000)),
- N = gather_parent_exits(kaboom, false),
- Comment = case node() == Node of
- true ->
- C = "Got " ++ integer_to_list(N) ++ " node local kabooms!",
- erlang:display(C),
- C;
- false ->
- C = "Got " ++ integer_to_list(N) ++ " node remote kabooms!",
- erlang:display(C),
- true = N /= 0,
- C
- end,
+ lists:seq(1, 10000)),
+ N = gather_parent_exits(ExitReason, false),
+ CFs = erpc:call(Node,
+ fun () ->
+ %% Ensure all children have had time to enter an exiting state...
+ receive after 100*test_server:timetrap_scale_factor() -> ok end,
+ lists:map(fun (P) ->
+ {P, process_info(P, current_function)}
+ end, processes())
+ end),
+ lists:foreach(fun ({P, {current_function, {?MODULE, spawn_request_test_exit_child, 1}}}) ->
+ ct:fail({missing_exit_to_child_detected, P});
+ (_) ->
+ ok
+ end, CFs),
+ Comment =
+ "Got "
+ ++ integer_to_list(N)
+ ++ if node() == Node -> " node local";
+ true -> " node remote"
+ end
+ ++ if CompoundExitReason -> " \"kaboom\"";
+ true -> " \'kaboom\'"
+ end
+ ++ " exits!",
+ erlang:display(Comment),
Comment.
+spawn_request_link_parent_exit_nodedown(Config) when is_list(Config) ->
+ {ok, Peer, Node} = ?CT_PEER(#{connection => 0}),
+ N = 1000,
+ ExitCounter = spawn(Node, fun exit_counter/0),
+ lists:foreach(fun (_) ->
+ spawn_request_link_parent_exit_nodedown_test(Node)
+ end,
+ lists:seq(1, N)),
+ ResRef = make_ref(),
+ ExitCounter ! {get_results, self(), ResRef},
+ Cmnt = receive
+ {ResRef, CntMap} ->
+ lists:flatten(
+ ["In total ", integer_to_list(N), " exits. ",
+ "Detected exits: ",
+ maps:fold(fun (ExitReason, Count, "") ->
+ io_lib:format("~p exit ~p times",
+ [ExitReason, Count]);
+ (ExitReason, Count, Acc) ->
+ [Acc, io_lib:format("; ~p exit ~p times",
+ [ExitReason, Count])]
+ end,
+ "",
+ CntMap),
+ "."])
+ end,
+ io:format("~s~n", [Cmnt]),
+ stop_node(Peer, Node),
+ {comment, Cmnt}.
+
+exit_counter() ->
+ true = register(exit_counter, self()),
+ exit_counter(#{}).
+
+exit_counter(CntMap) ->
+ receive
+ {get_results, From, Ref} ->
+ From ! {Ref, CntMap};
+ {exit, Reason} ->
+ OldCnt = maps:get(Reason, CntMap, 0),
+ exit_counter(CntMap#{Reason => OldCnt+1})
+ end.
+
+spawn_request_link_parent_exit_nodedown_test(Node) ->
+ pong = net_adm:ping(Node),
+ ChildFun = fun () ->
+ process_flag(trap_exit, true),
+ receive
+ {'EXIT', _, Reason} ->
+ exit_counter ! {exit, Reason}
+ end
+ end,
+ {Pid, Mon} = spawn_monitor(fun () ->
+ _ReqID = spawn_request(Node,
+ ChildFun,
+ [link,
+ {priority,max}]),
+ exit(bye)
+ end),
+ receive
+ {'DOWN', Mon, process, Pid, Reason} ->
+ bye = Reason,
+ erlang:disconnect_node(Node)
+ end,
+ ok.
+
+
spawn_request_abandon_bif(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
false = spawn_request_abandon(make_ref()),
false = spawn_request_abandon(spawn_request(fun () -> ok end)),
false = spawn_request_abandon(rpc:call(Node, erlang, make_ref, [])),
@@ -3001,19 +3521,10 @@ spawn_request_abandon_bif(Config) when is_list(Config) ->
TotOps = 1000,
Tester = self(),
- ChildFun = fun () ->
- Child = self(),
- spawn_opt(fun () ->
- process_flag(trap_exit, true),
- receive
- {'EXIT', Child, Reason} ->
- Tester ! {parent_exit, Reason}
- end
- end, [link,{priority,max}]),
- receive after infinity -> ok end
- end,
ParentFun = fun (Wait, Opts) ->
- ReqId = spawn_request(Node, ChildFun, Opts),
+ ReqId = spawn_request(Node, ?MODULE,
+ spawn_request_test_exit_child,
+ [Tester], Opts),
receive after Wait -> ok end,
case spawn_request_abandon(ReqId) of
true ->
@@ -3053,6 +3564,19 @@ spawn_request_abandon_bif(Config) when is_list(Config) ->
end,
lists:seq(1, TotOps)),
NoA2 = gather_parent_exits(abandoned, true),
+ CFs = erpc:call(Node,
+ fun () ->
+ %% Ensure all children have had time to enter an exiting state...
+ receive after 100*test_server:timetrap_scale_factor() -> ok end,
+ lists:map(fun (P) ->
+ {P, process_info(P, current_function)}
+ end, processes())
+ end),
+ lists:foreach(fun ({P, {current_function, {?MODULE, spawn_request_test_exit_child, 1}}}) ->
+ ct:fail({missing_exit_to_child_detected, P});
+ (_) ->
+ ok
+ end, CFs),
%% Parent exit early...
lists:foreach(fun (N) ->
spawn_opt(fun () ->
@@ -3075,17 +3599,27 @@ spawn_request_abandon_bif(Config) when is_list(Config) ->
end,
lists:seq(1, TotOps)),
0 = gather_parent_exits(abandoned, true),
- stop_node(Node),
+ stop_node(Peer, Node),
C = "Got " ++ integer_to_list(NoA1) ++ " and "
++ integer_to_list(NoA2) ++ " abandoneds of 2*"
++ integer_to_list(TotOps) ++ " ops!",
- erlang:display(C),
true = NoA1 /= 0,
true = NoA1 /= TotOps,
true = NoA2 /= 0,
true = NoA2 /= TotOps,
{comment, C}.
+spawn_request_test_exit_child(Tester) ->
+ Child = self(),
+ _ = spawn_opt(fun () ->
+ process_flag(trap_exit, true),
+ receive
+ {'EXIT', Child, Reason} ->
+ Tester ! {parent_exit, Reason}
+ end
+ end, [link,{priority,max}]),
+ receive after infinity -> ok end.
+
gather_parent_exits(Reason, AllowOther) ->
receive after 2000 -> ok end,
gather_parent_exits(Reason, AllowOther, 0).
@@ -3105,7 +3639,7 @@ gather_parent_exits(Reason, AllowOther, N) ->
N
end.
dist_spawn_monitor(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
R1 = spawn_request(Node, erlang, exit, [hej], [monitor]),
receive
{spawn_reply, R1, ok, P1} ->
@@ -3124,12 +3658,31 @@ dist_spawn_monitor(Config) when is_list(Config) ->
{'DOWN', Mon3, process, P3, Reason3} ->
hej = Reason3
end,
- stop_node(Node),
+ stop_node(Peer, Node),
ok.
-
-spawn_old_node(Config) when is_list(Config) ->
- Cookie = atom_to_list(erlang:get_cookie()),
- Rel = "22_latest",
+
+spawn_against_ei_node(Config) when is_list(Config) ->
+ %% Spawn against an ei node which does not support spawn
+ {ok, EiNode} = start_ei_node(Config),
+ try
+ %% First spawn triggering a new connection; which
+ %% will trigger hopeful data transcoding
+ %% of spawn requests...
+ io:format("~n~nDoing initial connect tests...~n", []),
+ spawn_ei_node_test(EiNode, true),
+ %% Spawns on an already existing connection...
+ io:format("~n~nDoing already connected tests...~n", []),
+ spawn_ei_node_test(EiNode, false),
+ ok
+ after
+ ok = stop_ei_node(EiNode)
+ end.
+
+spawn_against_old_node(Config) when is_list(Config) ->
+ %% Same spawn tests against a two releases old node as against
+ %% ei node above
+ OldRel = integer_to_list(list_to_integer(erlang:system_info(otp_release))-2),
+ OldRelName = OldRel ++ "_latest",
%% We clear all ERL_FLAGS for the old node as all options may not
%% be supported.
ClearEnv = lists:foldl(
@@ -3141,71 +3694,54 @@ spawn_old_node(Config) when is_list(Config) ->
Acc
end
end, [], os:env()),
- case test_server:is_release_available(Rel) of
- false ->
- {skipped, "No OTP 22 available"};
- true ->
- {ok, OldNode} = test_server:start_node(make_nodename(Config),
- peer,
- [{args, " -setcookie "++Cookie},
- {env, ClearEnv},
- {erl, [{release, Rel}]}]),
+ case ?CT_PEER_REL(#{connection => 0, env => ClearEnv },
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {skipped, "No OTP "++OldRel++" available"};
+ {ok, Peer, OldNode} ->
try
%% Spawns triggering a new connection; which
%% will trigger hopeful data transcoding
%% of spawn requests...
io:format("~n~nDoing initial connect tests...~n", []),
- spawn_old_node_test(OldNode, true),
- %% Spawns on an already existing connection...
+ spawn_node_test(OldNode, true),
io:format("~n~nDoing already connected tests...~n", []),
- spawn_old_node_test(OldNode, false)
+ %% Spawns on an already existing connection...
+ spawn_node_test(OldNode, false),
+ ok
after
- test_server:stop_node(OldNode)
- end,
- ok
+ peer:stop(Peer)
+ end
end.
-spawn_new_node(Config) when is_list(Config) ->
- Cookie = atom_to_list(erlang:get_cookie()),
- %% Test that the same operations as in spawn_old_node test
- %% works as expected on current OTP...
- {ok, CurrNode} = test_server:start_node(make_nodename(Config),
- peer,
- [{args, " -setcookie "++Cookie}]),
+spawn_against_new_node(Config) when is_list(Config) ->
+ {ok, Peer, CurrNode} = ?CT_PEER(#{connection => 0}),
try
%% Spawns triggering a new connection; which
%% will trigger hopeful data transcoding
%% of spawn requests...
io:format("~n~nDoing initial connect tests...~n", []),
- spawn_current_node_test(CurrNode, true),
+ spawn_node_test(CurrNode, true),
io:format("~n~nDoing already connected tests...~n", []),
%% Spawns on an already existing connection...
- spawn_current_node_test(CurrNode, false)
+ spawn_node_test(CurrNode, false),
+ ok
after
- test_server:stop_node(CurrNode)
+ peer:stop(Peer)
end.
-disconnect_node(Node, Disconnect) ->
- case Disconnect of
- false ->
- ok;
- true ->
- monitor_node(Node, true),
- erlang:disconnect_node(Node),
- receive {nodedown, Node} -> ok end
- end.
-
-spawn_old_node_test(Node, Disconnect) ->
- io:format("Testing spawn_request() on old node...", []),
+spawn_ei_node_test(Node, Disconnect) ->
+ io:format("Testing spawn_request() against ei node...", []),
disconnect_node(Node, Disconnect),
- R1 = spawn_request(Node, erlang, exit, [hej], [monitor, {reply_tag, a_tag}]),
+ Ref1 = spawn_request(Node, erlang, exit, [hej], [monitor, {reply_tag, a_tag}]),
receive
- {a_tag, R1, Err, Notsup} ->
+ {a_tag, Ref1, Err, Notsup} ->
error = Err,
notsup = Notsup,
ok
end,
- io:format("Testing spawn_monitor() on old node...", []),
+ io:format("Testing spawn_monitor() against ei node...", []),
disconnect_node(Node, Disconnect),
try
spawn_monitor(Node, erlang, exit, [hej])
@@ -3213,34 +3749,41 @@ spawn_old_node_test(Node, Disconnect) ->
error:notsup ->
ok
end,
- io:format("Testing spawn_opt() with monitor on old node...", []),
+ io:format("Testing spawn_opt() with monitor against ei node...", []),
disconnect_node(Node, Disconnect),
- try
- spawn_opt(Node, erlang, exit, [hej], [monitor])
- catch
- error:badarg ->
- ok
+ {P0, M0} = spawn_opt(Node, erlang, exit, [hej], [monitor]),
+ receive
+ {'DOWN', M0, process, P0, R0} ->
+ notsup = R0
end,
- io:format("Testing spawn_opt() with link on old node...", []),
+ io:format("Testing spawn_opt() with link against ei node...", []),
disconnect_node(Node, Disconnect),
process_flag(trap_exit, true),
P1 = spawn_opt(Node, erlang, exit, [hej], [link]),
- Node = node(P1),
receive
- {'EXIT', P1, hej} ->
- ok
+ {'EXIT', P1, R1} ->
+ notsup = R1
end,
- io:format("Testing spawn_link() on old node...", []),
+ io:format("Testing spawn_link() against ei node...", []),
disconnect_node(Node, Disconnect),
P2 = spawn_link(Node, erlang, exit, [hej]),
- Node = node(P2),
receive
- {'EXIT', P2, hej} ->
- ok
+ {'EXIT', P2, R2} ->
+ notsup = R2
+ end,
+ ok.
+
+disconnect_node(_Node, false) ->
+ ok;
+disconnect_node(Node, true) ->
+ lists:member(Node, nodes([visible, hidden])) andalso begin
+ monitor_node(Node, true),
+ true = erlang:disconnect_node(Node),
+ receive {nodedown, Node} -> ok end
end.
-spawn_current_node_test(Node, Disconnect) ->
- io:format("Testing spawn_request() on new node...", []),
+spawn_node_test(Node, Disconnect) ->
+ io:format("Testing spawn_request()...", []),
disconnect_node(Node, Disconnect),
R1 = spawn_request(Node, erlang, exit, [hej], [monitor, {reply_tag, a_tag}]),
receive
@@ -3250,21 +3793,21 @@ spawn_current_node_test(Node, Disconnect) ->
{'DOWN', R1, process, P1, hej} -> ok
end
end,
- io:format("Testing spawn_monitor() on new node...", []),
+ io:format("Testing spawn_monitor()...", []),
disconnect_node(Node, Disconnect),
{P2, M2} = spawn_monitor(Node, erlang, exit, [hej]),
receive
{'DOWN', M2, process, P2, hej} -> ok
end,
Node = node(P2),
- io:format("Testing spawn_opt() with monitor on new node...", []),
+ io:format("Testing spawn_opt() with monitor...", []),
disconnect_node(Node, Disconnect),
{P3, M3} = spawn_opt(Node, erlang, exit, [hej], [monitor]),
receive
{'DOWN', M3, process, P3, hej} -> ok
end,
Node = node(P3),
- io:format("Testing spawn_opt() with link on new node...", []),
+ io:format("Testing spawn_opt() with link...", []),
disconnect_node(Node, Disconnect),
process_flag(trap_exit, true),
P4 = spawn_opt(Node, erlang, exit, [hej], [link]),
@@ -3273,7 +3816,7 @@ spawn_current_node_test(Node, Disconnect) ->
{'EXIT', P4, hej} ->
ok
end,
- io:format("Testing spawn_link() on new node...", []),
+ io:format("Testing spawn_link()...", []),
disconnect_node(Node, Disconnect),
P5 = spawn_link(Node, erlang, exit, [hej]),
Node = node(P5),
@@ -3283,11 +3826,11 @@ spawn_current_node_test(Node, Disconnect) ->
end.
spawn_request_reply_option(Config) when is_list(Config) ->
- spawn_request_reply_option_test(node()),
- {ok, Node} = start_node(Config),
- spawn_request_reply_option_test(Node).
+ spawn_request_reply_option_test(undefined, node()),
+ {ok, Peer, Node} = ?CT_PEER(),
+ spawn_request_reply_option_test(Peer, Node).
-spawn_request_reply_option_test(Node) ->
+spawn_request_reply_option_test(Peer, Node) ->
io:format("Testing on node: ~p~n", [Node]),
Parent = self(),
Done1 = make_ref(),
@@ -3350,7 +3893,7 @@ spawn_request_reply_option_test(Node) ->
true ->
ok;
false ->
- stop_node(Node),
+ stop_node(Peer, Node),
RID9 = spawn_request(Node, fun () -> ok end, [{reply, yes}]),
receive
{spawn_reply, RID9, error, noconnection} -> ok
@@ -3376,24 +3919,138 @@ processes_term_proc_list(Config) when is_list(Config) ->
Tester = self(),
Run = fun(Args) ->
- {ok, Node} = start_node(Config, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
RT = spawn_link(Node, fun () ->
receive after 1000 -> ok end,
as_expected = processes_term_proc_list_test(false),
Tester ! {it_worked, self()}
end),
receive {it_worked, RT} -> ok end,
- stop_node(Node)
+ stop_node(Peer, Node)
end,
%% We have to run this test case with +S1 since instrument:allocations()
%% will report a free()'d block as present until it's actually deallocated
%% by its employer.
- Run("+MSe true +Muatags false +S1"),
- Run("+MSe true +Muatags true +S1"),
+ Run(["+MSe", "true", "+Muatags", "false", "+S1"]),
+ Run(["+MSe", "true", "+Muatags", "true", "+S1"]),
+
+ ok.
+
+%% OTP-18322: Send msg to spawning process pid returned from processes/0
+processes_send_infant(_Config) ->
+ case erlang:system_info(schedulers_online) of
+ 1 ->
+ {skip, "Only one scheduler online"};
+ NScheds ->
+ processes_send_infant_do(NScheds)
+ end.
+
+processes_send_infant_do(NScheds) ->
+ IgnoreList = erlang:processes(),
+ IgnorePids = maps:from_keys(IgnoreList, ignore),
+ Tester = self(),
+
+ %% To provoke bug we need sender and spawner on different schedulers.
+ %% Let spawners use schedulers nr 2 to NScheds
+ NSpawnerScheds = NScheds - 1,
+ NSpawners = 2 * NSpawnerScheds,
+ [spawn_link(fun() ->
+ processes_send_infant_spawner((I rem NSpawnerScheds) + 2,
+ Tester, Tester, 1)
+ end)
+ || I <- lists:seq(0, NSpawners-1)],
+
+ %% and make sure sender use scheduler 1
+ {Sender,SenderMon} =
+ spawn_opt(
+ fun() ->
+ timeout = processes_send_infant_loop(IgnorePids)
+ end,
+ [link, monitor, {scheduler,1}]),
+
+ %% Run test for a little while and see if VM crashes
+ {ok, _TRef} = timer:send_after(1000, Sender, timeout),
+ {'DOWN', SenderMon, process, Sender, normal} = receive_any(),
+
+ %% Stop spawners and collect stats
+ processes_send_infant_broadcast(erlang:processes(),
+ {processes_send_infant, stop},
+ IgnorePids),
+ {TotSpawn, TheLastOfUs} =
+ lists:foldl(fun(_, {SpawnCnt, Pids}) ->
+ {Pid, Generation} = receive_any(),
+ io:format("Got ~p from ~p\n", [Generation, Pid]),
+ {SpawnCnt+Generation, [Pid | Pids]}
+ end,
+ {0, []},
+ lists:seq(1, NSpawners)),
+ io:format("Total spawned processes: ~p\n", [TotSpawn]),
+ Aliens = (erlang:processes() -- IgnoreList) -- TheLastOfUs,
+ io:format("Alien processes: ~p\n", [Aliens]),
+ ok.
+
+
+
+processes_send_infant_loop(IgnorePids) ->
+ %% Send message identifying this test case, in case we send
+ %% to alien processes spawned during the test.
+ Msg = processes_send_infant,
+ processes_send_infant_broadcast(erlang:processes(),
+ Msg,
+ IgnorePids),
+ receive timeout -> timeout
+ after 0 ->
+ processes_send_infant_loop(IgnorePids)
+ end.
+processes_send_infant_broadcast([Pid | Tail], Msg, IgnorePids) ->
+ case maps:is_key(Pid, IgnorePids) of
+ false ->
+ Pid ! Msg;
+ true ->
+ ignore
+ end,
+ processes_send_infant_broadcast(Tail, Msg, IgnorePids);
+processes_send_infant_broadcast([], _, _) ->
ok.
+processes_send_infant_spawner(Sched, Tester, Parent, Generation) ->
+ link(Tester),
+ case receive_any() of
+ processes_send_infant ->
+ case Parent of
+ Tester -> ok;
+ _ -> Parent ! {die, self()}
+ end,
+ Self = self(),
+ Child = spawn_opt(fun() ->
+ processes_send_infant_spawner(Sched, Tester,
+ Self,
+ Generation+1)
+ end,
+ [{message_queue_data, off_heap},
+ {scheduler, Sched}]),
+ process_send_infant_spawner_epilogue(Child);
+
+ {processes_send_infant, stop} ->
+ Tester ! {self(), Generation}
+ end.
+
+process_send_infant_spawner_epilogue(Child) ->
+ %% Parent stays alive only to ensure child gets stop message
+ case receive_any() of
+ processes_send_infant ->
+ process_send_infant_spawner_epilogue(Child);
+ {die, Child} ->
+ ok;
+ {processes_send_infant, stop}=Stop ->
+ %% We are not sure child was spawned when stop message was sent
+ %% so we relay it.
+ Child ! Stop
+ end.
+
+
-define(CHK_TERM_PROC_LIST(MC, XB),
chk_term_proc_list(?LINE, MC, XB)).
@@ -4032,11 +4689,25 @@ otp_16642(Config) when is_list(Config) ->
false = is_process_alive(Pid),
ok.
+pid_ref_table_size() ->
+ erts_debug:get_internal_state(pid_ref_table_size).
+
+check_pid_ref_table_size(PRTSz) ->
+ receive after 500 -> ok end,
+ case pid_ref_table_size() of
+ PRTSz ->
+ ok;
+ NewPRTSz ->
+ ct:fail({port_ref_table_size_mismatch, PRTSz, NewPRTSz})
+ end.
+
alias_bif(Config) when is_list(Config) ->
+ PRTSz = pid_ref_table_size(),
alias_bif_test(node()),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
alias_bif_test(Node),
- stop_node(Node),
+ stop_node(Peer, Node),
+ check_pid_ref_table_size(PRTSz),
ok.
alias_bif_test(Node) ->
@@ -4081,10 +4752,12 @@ alias_bif_test(Node) ->
monitor_alias(Config) when is_list(Config) ->
+ PRTSz = pid_ref_table_size(),
monitor_alias_test(node()),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
monitor_alias_test(Node),
- stop_node(Node),
+ stop_node(Peer, Node),
+ check_pid_ref_table_size(PRTSz),
ok.
monitor_alias_test(Node) ->
@@ -4168,21 +4841,23 @@ monitor_alias_test(Node) ->
spawn_monitor_alias(Config) when is_list(Config) ->
%% Exit signals with immediate exit reasons are sent
%% in a different manner than compound exit reasons.
- spawn_monitor_alias_test(node(), spawn_opt, normal),
- spawn_monitor_alias_test(node(), spawn_opt, make_ref()),
- spawn_monitor_alias_test(node(), spawn_request, normal),
- spawn_monitor_alias_test(node(), spawn_request, make_ref()),
- {ok, Node1} = start_node(Config),
- spawn_monitor_alias_test(Node1, spawn_opt, normal),
- {ok, Node2} = start_node(Config),
- spawn_monitor_alias_test(Node2, spawn_opt, make_ref()),
- {ok, Node3} = start_node(Config),
- spawn_monitor_alias_test(Node3, spawn_request, normal),
- {ok, Node4} = start_node(Config),
- spawn_monitor_alias_test(Node4, spawn_request, make_ref()),
+ PRTSz = pid_ref_table_size(),
+ spawn_monitor_alias_test(undefined, node(), spawn_opt, normal),
+ spawn_monitor_alias_test(undefined, node(), spawn_opt, make_ref()),
+ spawn_monitor_alias_test(undefined, node(), spawn_request, normal),
+ spawn_monitor_alias_test(undefined, node(), spawn_request, make_ref()),
+ {ok, Peer1, Node1} = ?CT_PEER(),
+ spawn_monitor_alias_test(Peer1, Node1, spawn_opt, normal),
+ {ok, Peer2, Node2} = ?CT_PEER(),
+ spawn_monitor_alias_test(Peer2, Node2, spawn_opt, make_ref()),
+ {ok, Peer3, Node3} = ?CT_PEER(),
+ spawn_monitor_alias_test(Peer3, Node3, spawn_request, normal),
+ {ok, Peer4, Node4} = ?CT_PEER(),
+ spawn_monitor_alias_test(Peer4, Node4, spawn_request, make_ref()),
+ check_pid_ref_table_size(PRTSz),
ok.
-spawn_monitor_alias_test(Node, SpawnType, ExitReason) ->
+spawn_monitor_alias_test(Peer, Node, SpawnType, ExitReason) ->
Spawn = case SpawnType of
spawn_opt ->
fun (F, O) ->
@@ -4309,7 +4984,7 @@ spawn_monitor_alias_test(Node, SpawnType, ExitReason) ->
receive after infinity -> ok end
end, [{monitor, [{alias, demonitor}]}]),
P6 ! {alias, MA6},
- stop_node(Node),
+ stop_node(Peer, Node),
[{MA6,1},{MA6,2},{'DOWN', MA6, _, _, noconnection}] = recv_msgs(3),
{_P6_1, M6_1} = spawn_monitor(fun () ->
MA6 ! {MA6, 3},
@@ -4320,38 +4995,60 @@ spawn_monitor_alias_test(Node, SpawnType, ExitReason) ->
ok
end.
+alias_process_exit(Config) when is_list(Config) ->
+ Tester = self(),
+ CreatedAliases = make_ref(),
+ PRTSz = pid_ref_table_size(),
+ P = spawn_link(fun () ->
+ A0 = alias([explicit_unalias]),
+ A1 = alias([reply]),
+ A2 = monitor(process, Tester, [{alias, explicit_unalias}]),
+ A3 = monitor(process, Tester, [{alias, demonitor}]),
+ A4 = monitor(process, Tester, [{alias, reply_demonitor}]),
+ Tester ! CreatedAliases,
+ receive after infinity -> ok end,
+ some_module:some_function([A0, A1, A2, A3, A4])
+ end),
+ receive CreatedAliases -> ok end,
+ PRTSz = erts_debug:get_internal_state(pid_ref_table_size) - 5,
+ unlink(P),
+ exit(P, kill),
+ false = is_process_alive(P),
+ check_pid_ref_table_size(PRTSz),
+ ok.
+
monitor_tag(Config) when is_list(Config) ->
%% Exit signals with immediate exit reasons are sent
%% in a different manner than compound exit reasons, and
%% immediate tags are stored in a different manner than
%% compound tags.
- monitor_tag_test(node(), spawn_opt, immed, normal),
- monitor_tag_test(node(), spawn_opt, make_ref(), normal),
- monitor_tag_test(node(), spawn_opt, immed, make_ref()),
- monitor_tag_test(node(), spawn_opt, make_ref(), make_ref()),
- monitor_tag_test(node(), spawn_request, immed, normal),
- monitor_tag_test(node(), spawn_request, make_ref(), normal),
- monitor_tag_test(node(), spawn_request, immed, make_ref()),
- monitor_tag_test(node(), spawn_request, make_ref(), make_ref()),
- {ok, Node1} = start_node(Config),
- monitor_tag_test(Node1, spawn_opt, immed, normal),
- {ok, Node2} = start_node(Config),
- monitor_tag_test(Node2, spawn_opt, make_ref(), normal),
- {ok, Node3} = start_node(Config),
- monitor_tag_test(Node3, spawn_opt, immed, make_ref()),
- {ok, Node4} = start_node(Config),
- monitor_tag_test(Node4, spawn_opt, make_ref(), make_ref()),
- {ok, Node5} = start_node(Config),
- monitor_tag_test(Node5, spawn_request, immed, normal),
- {ok, Node6} = start_node(Config),
- monitor_tag_test(Node6, spawn_request, make_ref(), normal),
- {ok, Node7} = start_node(Config),
- monitor_tag_test(Node7, spawn_request, immed, make_ref()),
- {ok, Node8} = start_node(Config),
- monitor_tag_test(Node8, spawn_request, make_ref(), make_ref()),
+ monitor_tag_test(undefined, node(), spawn_opt, immed, normal),
+ monitor_tag_test(undefined, node(), spawn_opt, make_ref(), normal),
+ monitor_tag_test(undefined, node(), spawn_opt, immed, make_ref()),
+ monitor_tag_test(undefined, node(), spawn_opt, make_ref(), make_ref()),
+ monitor_tag_test(undefined, node(), spawn_request, immed, normal),
+ monitor_tag_test(undefined, node(), spawn_request, make_ref(), normal),
+ monitor_tag_test(undefined, node(), spawn_request, immed, make_ref()),
+ monitor_tag_test(undefined, node(), spawn_request, make_ref(), make_ref()),
+ {ok, Peer1, Node1} = ?CT_PEER(),
+ monitor_tag_test(Peer1, Node1, spawn_opt, immed, normal),
+ {ok, Peer2, Node2} = ?CT_PEER(),
+ monitor_tag_test(Peer2, Node2, spawn_opt, make_ref(), normal),
+ {ok, Peer3, Node3} = ?CT_PEER(),
+ monitor_tag_test(Peer3, Node3, spawn_opt, immed, make_ref()),
+ {ok, Peer4, Node4} = ?CT_PEER(),
+ monitor_tag_test(Peer4, Node4, spawn_opt, make_ref(), make_ref()),
+ {ok, Peer5, Node5} = ?CT_PEER(),
+ monitor_tag_test(Peer5, Node5, spawn_request, immed, normal),
+ {ok, Peer6, Node6} = ?CT_PEER(),
+ monitor_tag_test(Peer6, Node6, spawn_request, make_ref(), normal),
+ {ok, Peer7, Node7} = ?CT_PEER(),
+ monitor_tag_test(Peer7, Node7, spawn_request, immed, make_ref()),
+ {ok, Peer8, Node8} = ?CT_PEER(),
+ monitor_tag_test(Peer8, Node8, spawn_request, make_ref(), make_ref()),
ok.
-monitor_tag_test(Node, SpawnType, Tag, ExitReason) ->
+monitor_tag_test(Peer, Node, SpawnType, Tag, ExitReason) ->
P1 = spawn(Node, fun () -> receive go -> ok end, exit(ExitReason) end),
M1 = monitor(process, P1, [{tag, Tag}]),
@@ -4397,7 +5094,7 @@ monitor_tag_test(Node, SpawnType, Tag, ExitReason) ->
false ->
{P3, M3} = Spawn(fun () -> receive after infinity -> ok end end,
[{monitor, [{tag, Tag}]}]),
- stop_node(Node),
+ stop_node(Peer, Node),
[{Tag, M3, process, P3, noconnection}] = recv_msgs(1),
case SpawnType == spawn_opt of
@@ -4440,27 +5137,10 @@ tok_loop(hopp) ->
id(I) -> I.
-make_nodename(Config) when is_list(Config) ->
- list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))).
-
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = make_nodename(Config),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
+stop_node(Peer, Node) ->
verify_nc(node()),
verify_nc(Node),
- test_server:stop_node(Node).
+ peer:stop(Peer).
verify_nc(Node) ->
P = self(),
@@ -4504,18 +5184,135 @@ sys_mem_cond_run(OrigReqSizeMB, TestFun) when is_integer(OrigReqSizeMB) ->
total_memory() ->
- %% Totat memory in MB.
+ %% Total memory in MB.
try
- MemoryData = memsup:get_system_memory_data(),
- case lists:keysearch(total_memory, 1, MemoryData) of
- {value, {total_memory, TM}} ->
- TM div (1024*1024);
- false ->
- {value, {system_total_memory, STM}} =
- lists:keysearch(system_total_memory, 1, MemoryData),
- STM div (1024*1024)
- end
+ SMD = memsup:get_system_memory_data(),
+ TM = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(
+ total_memory, SMD,
+ proplists:get_value(
+ system_total_memory, SMD))),
+ TM div (1024*1024)
catch
_ : _ ->
undefined
end.
+
+start_ei_node(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ FwdNodeExe = filename:join(DataDir, "fwd_node"),
+ Name = atom_to_list(?MODULE)
+ ++ "-" ++ "ei_node"
+ ++ "-" ++ integer_to_list(erlang:system_time(second))
+ ++ "-" ++ integer_to_list(erlang:unique_integer([positive])),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ HostName = get_hostname(),
+ Node = list_to_atom(Name++"@"++HostName),
+ Creation = integer_to_list(rand:uniform((1 bsl 15) - 4) + 3),
+ Parent = self(),
+ Pid = spawn_link(fun () ->
+ register(cnode_forward_receiver, self()),
+ process_flag(trap_exit, true),
+ Args = ["-sname", Name,
+ "-cookie", Cookie,
+ "-creation", Creation],
+ io:format("Starting ei_node: ~p ~p~n",
+ [FwdNodeExe, Args]),
+ Port = erlang:open_port({spawn_executable, FwdNodeExe},
+ [use_stdio, {args, Args}]),
+ receive
+ {Port, {data, "accepting"}} -> ok
+ end,
+ ei_node_handler_loop(Node, Parent, Port)
+ end),
+ put({ei_node_handler, Node}, Pid),
+ case check_ei_node(Node) of
+ ok -> {ok, Node};
+ Error -> Error
+ end.
+
+check_ei_node(Node) ->
+ Key = {ei_node_handler, Node},
+ case get(Key) of
+ undefined ->
+ {error, no_handler};
+ Pid when is_pid(Pid) ->
+ Pid ! {check_node, self()},
+ receive
+ {check_node, Pid, Res} ->
+ Res
+ after 3000 ->
+ {error, no_handler_response}
+ end
+ end.
+
+stop_ei_node(Node) ->
+ case check_ei_node(Node) of
+ ok ->
+ Key = {ei_node_handler, Node},
+ case get(Key) of
+ undefined ->
+ {error, no_handler};
+ Pid when is_pid(Pid) ->
+ Pid ! {stop_node, self()},
+ receive
+ {stop_node, Pid} ->
+ put(Key, undefined),
+ ok
+ after 2000 ->
+ {error, no_handler_response}
+ end
+ end;
+ Error ->
+ Error
+ end.
+
+ei_node_handler_loop(Node, Parent, Port) ->
+ receive
+ {'EXIT', Parent, Reason} ->
+ erlang:disconnect_node(Node),
+ (catch port_close(Port)),
+ exit(Reason);
+ {stop_node, Parent} ->
+ erlang:disconnect_node(Node),
+ (catch port_close(Port)),
+ Parent ! {stop_node, self()},
+ exit(normal);
+ {check_node, Parent} ->
+ Ref = make_ref(),
+ {a_name, Node} ! Ref,
+ receive
+ Ref ->
+ Parent ! {check_node, self(), ok}
+ after
+ 2000 ->
+ Parent ! {check_node, self(), {error, no_node_response}}
+ end;
+ Msg ->
+ Msgs = fetch_all_messages([Msg]),
+ erlang:disconnect_node(Node),
+ (catch port_close(Port)),
+ exit({ei_node_handler, Node, unexpected_messages, Msgs})
+ end,
+ ei_node_handler_loop(Node, Parent, Port).
+
+fetch_all_messages(Msgs) ->
+ receive
+ Msg ->
+ fetch_all_messages([Msg|Msgs])
+ after
+ 0 ->
+ Msgs
+ end.
+
+get_hostname() ->
+ get_hostname(atom_to_list(node())).
+
+get_hostname([$@ | HostName]) ->
+ HostName;
+get_hostname([_ | Rest]) ->
+ get_hostname(Rest).
+
+receive_any() ->
+ receive M -> M end.
diff --git a/erts/emulator/test/process_SUITE_data/Makefile.src b/erts/emulator/test/process_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..0f59ee0b05
--- /dev/null
+++ b/erts/emulator/test/process_SUITE_data/Makefile.src
@@ -0,0 +1,39 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2021. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+
+include @erl_interface_mk_include@
+
+CC = @CC@
+LD = @LD@
+
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@
+
+LIBEI = @erl_interface_eilib@
+LIBFLAGS = $(LIBEI) @LIBS@ @erl_interface_sock_libs@ @erl_interface_threadlib@
+
+all: fwd_node@exe@
+
+fwd_node@exe@: fwd_node@obj@ $(LIBEI)
+ $(LD) @CROSSLDFLAGS@ -o $@ fwd_node@obj@ $(LIBFLAGS)
+
+clean:
+ $(RM) fwd_node@obj@
+ $(RM) fwd_node@exe@
+
diff --git a/erts/emulator/test/process_SUITE_data/fwd_node.c b/erts/emulator/test/process_SUITE_data/fwd_node.c
new file mode 100644
index 0000000000..da26fd4224
--- /dev/null
+++ b/erts/emulator/test/process_SUITE_data/fwd_node.c
@@ -0,0 +1,221 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __WIN32__
+# include <io.h>
+#else
+# include <unistd.h>
+# include <errno.h>
+# include <pthread.h>
+#endif
+#include "ei.h"
+
+static void usage1(char *what);
+static void usage2(char *what, char *val);
+static void fail1(char *what);
+
+char *progname;
+ei_cnode cnode;
+char *node_name = NULL;
+char *cookie = NULL;
+short creation = -1;
+
+#ifdef __WIN32__
+static unsigned __stdcall ei_node_executor(LPVOID unused)
+#else
+static void *ei_node_executor(void *unused)
+#endif
+{
+ int lfd, pfd, res, port;
+
+ ei_init();
+ res = ei_connect_init(&cnode, node_name, cookie, creation);
+ if (res < 0)
+ fail1("ei_connect_init");
+ port = 0;
+ lfd = ei_listen(&cnode, &port, 5);
+ if (lfd < 0)
+ fail1("ei_listen");
+ pfd = ei_publish(&cnode, port);
+ if (pfd < 0)
+ fail1("ei_publish");
+
+ printf("accepting");
+ fflush(stdout);
+
+ while (!0) {
+ ErlConnect conn;
+ int afd = ei_accept(&cnode, lfd, &conn);
+ if (afd < 0)
+ fail1("ei_accept");
+
+ while (!0) {
+ ei_x_buff x;
+ erlang_msg msg;
+ ei_x_new(&x);
+ do {
+ res = ei_xreceive_msg(afd, &msg, &x);
+ } while (res == ERL_TICK);
+ if (res != ERL_MSG) {
+ /* connection closed... */
+ ei_close_connection(afd);
+ break;
+ }
+
+ switch (msg.msgtype) {
+ case ERL_SEND:
+ case ERL_REG_SEND:
+ ei_send_reg_encoded(afd, &cnode.self, "cnode_forward_receiver",
+ x.buff, x.index);
+ break;
+ case ERL_LINK:
+ fail1("received link");
+ break;
+ case ERL_UNLINK:
+ fail1("received unlink");
+ break;
+ case ERL_EXIT:
+ fail1("received exit");
+ break;
+ default:
+ fail1("received invalid signal");
+ break;
+ }
+ ei_x_free(&x);
+ }
+ }
+
+#ifdef __WIN32__
+ return 0;
+#else
+ return NULL;
+#endif
+}
+
+int
+main(int argc, char *argv[])
+{
+#ifdef __WIN32__
+ unsigned tid;
+ HANDLE thndl;
+#else
+ pthread_t tid;
+#endif
+ int i;
+
+ progname = argv[0];
+ i = 1;
+ while (i < argc) {
+ if (strcmp(argv[i], "-sname") == 0) {
+ i++;
+ if (i == argc)
+ usage1("Missing -sname value");
+ node_name = argv[i];
+ }
+ else if (strcmp(argv[i], "-cookie") == 0) {
+ i++;
+ if (i == argc)
+ usage1("Missing -cookie value");
+ cookie = argv[i];
+ }
+ else if (strcmp(argv[i], "-creation") == 0) {
+ char *endp;
+ long int val;
+ i++;
+ if (i == argc)
+ usage1("Missing -creation value");
+ val = strtol(argv[i], &endp, 10);
+ creation = (short) val;
+ if (*endp != '\0' || creation < 4)
+ usage2("Invalid creation", argv[i]);
+ }
+ else {
+ usage2("Unknown parameter", argv[i]);
+ }
+ i++;
+ }
+
+ if (!node_name)
+ usage1("Missing -sname parameter");
+ if (!cookie)
+ usage1("Missing -cookie parameter");
+ if (creation < 0)
+ usage1("Missing -creation parameter");
+
+#ifdef __WIN32__
+ thndl = (HANDLE) _beginthreadex(NULL, 0, ei_node_executor,
+ NULL, 0, &tid);
+ if (thndl == (HANDLE) 0)
+ fail1("_beginthreadex() failed");
+#else
+ if (pthread_create(&tid, NULL, ei_node_executor, NULL) != 0)
+ fail1("pthread_create() failed");
+#endif
+
+ /* Wait until stdin is closed. Terminate when that happens... */
+ while (!0) {
+ char buf[128];
+#ifdef __WIN32__
+ int res = _read(0, (void *) &buf[0], sizeof(buf));
+#else
+ ssize_t res = read(0, (void *) &buf[0], sizeof(buf));
+#endif
+ if (res == 0)
+ exit(0); /* erlang port closed... */
+ if (res < 0 && errno != EINTR) {
+ fail1("read() failed");
+ }
+ }
+
+ return 0;
+}
+
+static void
+usage1(char *what)
+{
+ fprintf(stderr,
+ "ERROR: %s\n\n"
+ " Usage:\n"
+ " %s -sname <node name> -cookie <cookie> -creation <creation>\n",
+ what, progname);
+ exit(1);
+}
+
+static void
+usage2(char *what, char *val)
+{
+ fprintf(stderr,
+ "ERROR: %s: %s\n\n"
+ " Usage:\n"
+ " %s -sname <node name> -cookie <cookie> -creation <creation>\n",
+ what, val, progname);
+ exit(1);
+}
+
+static void
+fail1(char *what)
+{
+ fprintf(stderr, "%s FAILED: %s; %d\n",
+ cnode.thisalivename, what, erl_errno);
+ exit(1);
+}
diff --git a/erts/emulator/test/random_iolist.erl b/erts/emulator/test/random_iolist.erl
index 555f063e0a..6d895e354d 100644
--- a/erts/emulator/test/random_iolist.erl
+++ b/erts/emulator/test/random_iolist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,8 +44,8 @@ random_list(N,Acc) ->
random_list(N-1,[random_byte() | Acc]).
random_binary(N) ->
- B = list_to_binary(random_list(N,[])),
- case {rand:uniform(2),size(B)} of
+ B = rand:bytes(N),
+ case {rand:uniform(2),byte_size(B)} of
{2,M} when M > 1 ->
S = M-1,
<<_:3,C:S/binary,_:5>> = B,
@@ -53,6 +53,7 @@ random_binary(N) ->
_ ->
B
end.
+
random_list(N) ->
random_list(N,[]).
diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl
index 6976e5ffd2..2b2be09f1e 100644
--- a/erts/emulator/test/receive_SUITE.erl
+++ b/erts/emulator/test/receive_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,9 +29,10 @@
receive_opt_exception/1,receive_opt_recursion/1,
receive_opt_deferred_save/1,
erl_1199/1, multi_recv_opt/1,
- multi_recv_opt_clear/1,
+ multi_recv_opt_clear/1,
gh_5235_missing_save_reset/1,
- gh_5235_recv_mark/1]).
+ gh_5235_recv_mark/1,
+ recv_marker_reserve/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -46,7 +47,8 @@ all() ->
erl_1199, multi_recv_opt,
multi_recv_opt_clear,
gh_5235_missing_save_reset,
- gh_5235_recv_mark].
+ gh_5235_recv_mark,
+ recv_marker_reserve].
init_per_testcase(receive_opt_deferred_save, Config) ->
case erlang:system_info(schedulers_online) of
@@ -585,6 +587,45 @@ gh_5235_recv_mark(Config) when is_list(Config) ->
receive init2 -> ok end,
receive Ref2 -> ok end.
+%% ERIERL-905: The `recv_marker_reserve` instruction didn't update heap/stack
+%% pointers despite allocating memory after a per-process counter goes beyond
+%% MAX_SMALL.
+recv_marker_reserve(Config) when is_list(Config) ->
+ Retries = 500,
+ {MinSmall, MaxSmall} = determine_small_limits(0),
+ Counter = -MinSmall + MaxSmall - Retries,
+
+ DummyRef = make_ref(),
+ self() ! DummyRef,
+
+ erts_debug:set_internal_state(available_internal_state, true),
+ erts_debug:set_internal_state(process_uniq_counter, Counter),
+ recv_marker_reserve_retry(Retries * 2),
+ erts_debug:set_internal_state(available_internal_state, false),
+
+ receive
+ DummyRef -> ok
+ end.
+
+recv_marker_reserve_retry(0) ->
+ ok;
+recv_marker_reserve_retry(N) ->
+ Ref = monitor(process, self(), [{alias,demonitor}]),
+ self() ! Ref,
+ receive
+ Ref -> erlang:demonitor(Ref, [flush])
+ end,
+ recv_marker_reserve_retry(N - 1).
+
+determine_small_limits(N) ->
+ case is_small(-1 bsl N) of
+ true -> determine_small_limits(N + 1);
+ false -> {-1 bsl (N - 1), (1 bsl (N - 1)) - 1}
+ end.
+
+is_small(N) when is_integer(N) ->
+ 0 =:= erts_debug:flat_size(N).
+
%%%
%%% Common helpers.
diff --git a/erts/emulator/test/ref_SUITE.erl b/erts/emulator/test/ref_SUITE.erl
index ba590e0a60..597ac51c12 100644
--- a/erts/emulator/test/ref_SUITE.erl
+++ b/erts/emulator/test/ref_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
[{testcase, Func}|Config].
end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
all() ->
[wrap_1, compare_list, compare_ets, internal_size, external_size].
@@ -132,7 +132,7 @@ external_size(Config) when is_list(Config) ->
%% matches what the documentation say in the advanced chapter of the
%% efficiency guide. Note that the values in the efficiency guide
%% also add the word referencing the heap structure.
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
%% Ordinary external reference
ORef = check_external_size(erpc:call(Node, fun () -> make_ref() end)),
@@ -145,7 +145,7 @@ external_size(Config) when is_list(Config) ->
io:format("PRef = ~p~n", [PRef]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
check_external_size(Ref) when is_reference(Ref) ->
@@ -165,25 +165,3 @@ check_external_size(Ref) when is_reference(Ref) ->
error({internal_ref_size_out_of_range, Sz})
end
end.
-
-%% Internal stuff...
-
-make_nodename(Config) when is_list(Config) ->
- list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))).
-
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = make_nodename(Config),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index 32a8511968..65a1c1f925 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -52,11 +52,13 @@
cpu_topology/1,
update_cpu_info/1,
sct_cmd/1,
+ ssrct_cmd/1,
sbt_cmd/1,
scheduler_threads/1,
scheduler_suspend_basic/1,
scheduler_suspend/1,
dirty_scheduler_threads/1,
+ sched_poll/1,
poll_threads/1,
reader_groups/1,
otp_16446/1,
@@ -76,6 +78,7 @@ all() ->
{group, scheduler_bind}, scheduler_threads,
scheduler_suspend_basic, scheduler_suspend,
dirty_scheduler_threads,
+ sched_poll,
poll_threads,
reader_groups,
otp_16446,
@@ -85,7 +88,7 @@ all() ->
groups() ->
[{scheduler_bind, [],
[scheduler_bind_types, cpu_topology, update_cpu_info,
- sct_cmd, sbt_cmd]}].
+ sct_cmd, sbt_cmd, ssrct_cmd]}].
init_per_suite(Config) ->
[{schedulers_online, erlang:system_info(schedulers_online)} | Config].
@@ -120,7 +123,7 @@ init_per_tc(Case, Config) ->
[{testcase, Case}, {ok_res, OkRes} |Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
-define(ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED, (2000*2000)).
-define(DEFAULT_TEST_REDS_PER_SCHED, 200000000).
@@ -283,7 +286,7 @@ bound_loop(NS, N, M, Sched) ->
-define(TOPOLOGY_A_CMD,
- "+sct"
+ ["+sct"
"L0-1t0-1c0p0n0"
":L2-3t0-1c1p0n0"
":L4-5t0-1c0p1n0"
@@ -291,7 +294,7 @@ bound_loop(NS, N, M, Sched) ->
":L8-9t0-1c0p2n1"
":L10-11t0-1c1p2n1"
":L12-13t0-1c0p3n1"
- ":L14-15t0-1c1p3n1").
+ ":L14-15t0-1c1p3n1"]).
-define(TOPOLOGY_A_TERM,
[{node,[{processor,[{core,[{thread,{logical,0}},
@@ -312,7 +315,7 @@ bound_loop(NS, N, M, Sched) ->
{thread,{logical,15}}]}]}]}]).
-define(TOPOLOGY_B_CMD,
- "+sct"
+ ["+sct"
"L0-1t0-1c0n0p0"
":L2-3t0-1c1n0p0"
":L4-5t0-1c2n1p0"
@@ -320,7 +323,7 @@ bound_loop(NS, N, M, Sched) ->
":L8-9t0-1c0n2p1"
":L10-11t0-1c1n2p1"
":L12-13t0-1c2n3p1"
- ":L14-15t0-1c3n3p1").
+ ":L14-15t0-1c3n3p1"]).
-define(TOPOLOGY_B_TERM,
[{processor,[{node,[{core,[{thread,{logical,0}},
@@ -376,7 +379,7 @@ bound_loop(NS, N, M, Sched) ->
-define(TOPOLOGY_C_CMD,
- "+sct"
+ ["+sct"
"L0-1t0-1c0p0n0"
":L2-3t0-1c1p0n0"
":L4-5t0-1c0p1n0"
@@ -392,7 +395,7 @@ bound_loop(NS, N, M, Sched) ->
":L24-25t0-1c0n4p5"
":L26-27t0-1c1n4p5"
":L28-29t0-1c2n5p5"
- ":L30-31t0-1c3n5p5").
+ ":L30-31t0-1c3n5p5"]).
-define(TOPOLOGY_D_TERM,
[{processor,[{node,[{core,[{thread,{logical,0}},
@@ -429,7 +432,7 @@ bound_loop(NS, N, M, Sched) ->
{thread,{logical,31}}]}]}]}]).
-define(TOPOLOGY_D_CMD,
- "+sct"
+ ["+sct"
"L0-1t0-1c0n0p0"
":L2-3t0-1c1n0p0"
":L4-5t0-1c2n1p0"
@@ -445,10 +448,10 @@ bound_loop(NS, N, M, Sched) ->
":L24-25t0-1c0p4n5"
":L26-27t0-1c1p4n5"
":L28-29t0-1c0p5n5"
- ":L30-31t0-1c1p5n5").
+ ":L30-31t0-1c1p5n5"]).
-define(TOPOLOGY_E_CMD,
- "+sct"
+ ["+sct"
"L0-1t0-1c0p0n0"
":L2-3t0-1c1p0n0"
":L4-5t0-1c2p0n0"
@@ -456,7 +459,7 @@ bound_loop(NS, N, M, Sched) ->
":L8-9t0-1c0p1n1"
":L10-11t0-1c1p1n1"
":L12-13t0-1c2p1n1"
- ":L14-15t0-1c3p1n1").
+ ":L14-15t0-1c3p1n1"]).
-define(TOPOLOGY_E_TERM,
[{node,[{processor,[{core,[{thread,{logical,0}},
@@ -477,7 +480,7 @@ bound_loop(NS, N, M, Sched) ->
{thread,{logical,15}}]}]}]}]).
-define(TOPOLOGY_F_CMD,
- "+sct"
+ ["+sct"
"L0-1t0-1c0n0p0"
":L2-3t0-1c1n0p0"
":L4-5t0-1c2n0p0"
@@ -493,7 +496,7 @@ bound_loop(NS, N, M, Sched) ->
":L24-25t0-1c12n3p0"
":L26-27t0-1c13n3p0"
":L28-29t0-1c14n3p0"
- ":L30-31t0-1c15n3p0").
+ ":L30-31t0-1c15n3p0"]).
-define(TOPOLOGY_F_TERM,
[{processor,[{node,[{core,[{thread,{logical,0}},
@@ -550,27 +553,27 @@ bindings(Node, BindType) ->
scheduler_bind_types(Config) when is_list(Config) ->
OldRelFlags = clear_erl_rel_flags(),
try
- scheduler_bind_types_test(Config,
+ scheduler_bind_types_test(
?TOPOLOGY_A_TERM,
?TOPOLOGY_A_CMD,
a),
- scheduler_bind_types_test(Config,
+ scheduler_bind_types_test(
?TOPOLOGY_B_TERM,
?TOPOLOGY_B_CMD,
b),
- scheduler_bind_types_test(Config,
+ scheduler_bind_types_test(
?TOPOLOGY_C_TERM,
?TOPOLOGY_C_CMD,
c),
- scheduler_bind_types_test(Config,
+ scheduler_bind_types_test(
?TOPOLOGY_D_TERM,
?TOPOLOGY_D_CMD,
d),
- scheduler_bind_types_test(Config,
+ scheduler_bind_types_test(
?TOPOLOGY_E_TERM,
?TOPOLOGY_E_CMD,
e),
- scheduler_bind_types_test(Config,
+ scheduler_bind_types_test(
?TOPOLOGY_F_TERM,
?TOPOLOGY_F_CMD,
f)
@@ -579,17 +582,17 @@ scheduler_bind_types(Config) when is_list(Config) ->
end,
ok.
-scheduler_bind_types_test(Config, Topology, CmdLine, TermLetter) ->
+scheduler_bind_types_test(Topology, CmdLine, TermLetter) ->
io:format("Testing (~p): ~p~n", [TermLetter, Topology]),
- {ok, Node0} = start_node(Config),
+ {ok, Peer, Node0} = ?CT_PEER(),
_ = rpc:call(Node0, erlang, system_flag, [cpu_topology, Topology]),
cmp(Topology, rpc:call(Node0, erlang, system_info, [cpu_topology])),
check_bind_types(Node0, TermLetter),
- stop_node(Node0),
- {ok, Node1} = start_node(Config, CmdLine),
+ peer:stop(Peer),
+ {ok, Peer1, Node1} = ?CT_PEER(CmdLine),
cmp(Topology, rpc:call(Node1, erlang, system_info, [cpu_topology])),
check_bind_types(Node1, TermLetter),
- stop_node(Node1).
+ peer:stop(Peer1).
check_bind_types(Node, a) ->
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
@@ -714,7 +717,6 @@ cpu_topology(Config) when is_list(Config) ->
OldRelFlags = clear_erl_rel_flags(),
try
cpu_topology_test(
- Config,
[{node,[{processor,[{core,{logical,0}},
{core,{logical,1}}]}]},
{processor,[{node,[{core,{logical,2}},
@@ -723,13 +725,12 @@ cpu_topology(Config) when is_list(Config) ->
{core,{logical,5}}]}]},
{processor,[{node,[{core,{logical,6}},
{core,{logical,7}}]}]}],
- "+sct "
+ ["+sct",
"L0-1c0-1p0n0"
":L2-3c0-1n1p1"
":L4-5c0-1p2n2"
- ":L6-7c0-1n3p3"),
+ ":L6-7c0-1n3p3"]),
cpu_topology_test(
- Config,
[{node,[{processor,[{core,{logical,0}},
{core,{logical,1}}]},
{processor,[{core,{logical,2}},
@@ -746,7 +747,7 @@ cpu_topology(Config) when is_list(Config) ->
{core,{logical,13}}]},
{node,[{core,{logical,14}},
{core,{logical,15}}]}]}],
- "+sct "
+ ["+sct",
"L0-1c0-1p0n0"
":L2-3c0-1p1n0"
":L4-5c0-1n1p2"
@@ -754,9 +755,8 @@ cpu_topology(Config) when is_list(Config) ->
":L8-9c0-1p3n3"
":L10-11c0-1p4n3"
":L12-13c0-1n4p5"
- ":L14-15c2-3n5p5"),
+ ":L14-15c2-3n5p5"]),
cpu_topology_test(
- Config,
[{node,[{processor,[{core,{logical,0}},
{core,{logical,1}}]}]},
{processor,[{node,[{core,{logical,2}},
@@ -769,39 +769,45 @@ cpu_topology(Config) when is_list(Config) ->
{core,{logical,9}}]}]},
{processor,[{node,[{core,{logical,10}},
{core,{logical,11}}]}]}],
- "+sct "
+ ["+sct",
"L0-1c0-1p0n0"
":L2-3c0-1n1p1"
":L4-5c0-1n2p2"
":L6-7c0-1p3n3"
":L8-9c0-1p4n4"
- ":L10-11c0-1n5p5")
+ ":L10-11c0-1n5p5"])
after
restore_erl_rel_flags(OldRelFlags)
end,
ok.
-cpu_topology_test(Config, Topology, Cmd) ->
+cpu_topology_test(Topology, Cmd) ->
io:format("Testing~n ~p~n ~p~n", [Topology, Cmd]),
- cpu_topology_bif_test(Config, Topology),
- cpu_topology_cmdline_test(Config, Topology, Cmd),
+ cpu_topology_bif_test(Topology),
+ cpu_topology_cmdline_test(Topology, Cmd),
ok.
-cpu_topology_bif_test(_Config, false) ->
+cpu_topology_bif_test(false) ->
ok;
-cpu_topology_bif_test(Config, Topology) ->
- {ok, Node} = start_node(Config),
+cpu_topology_bif_test(Topology) ->
+ {ok, Peer, Node} = ?CT_PEER(),
_ = rpc:call(Node, erlang, system_flag, [cpu_topology, Topology]),
cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])),
- stop_node(Node),
+ cmp(Topology,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, defined}])),
+ peer:stop(Peer),
ok.
-cpu_topology_cmdline_test(_Config, _Topology, false) ->
+cpu_topology_cmdline_test(_Topology, false) ->
ok;
-cpu_topology_cmdline_test(Config, Topology, Cmd) ->
- {ok, Node} = start_node(Config, Cmd),
+cpu_topology_cmdline_test(Topology, Cmd) ->
+ {ok, Peer, Node} = ?CT_PEER(Cmd),
cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])),
- stop_node(Node),
+ cmp(undefined,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, detected}])),
+ cmp(Topology,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, defined}])),
+ peer:stop(Peer),
ok.
update_cpu_info(Config) when is_list(Config) ->
@@ -983,19 +989,39 @@ sct_cmd(Config) when is_list(Config) ->
Topology = ?TOPOLOGY_A_TERM,
OldRelFlags = clear_erl_rel_flags(),
try
- {ok, Node} = start_node(Config, ?TOPOLOGY_A_CMD),
+ {ok, Peer, Node} = ?CT_PEER(?TOPOLOGY_A_CMD),
cmp(Topology,
rpc:call(Node, erlang, system_info, [cpu_topology])),
+ cmp(undefined,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, detected}])),
+ cmp(Topology,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, defined}])),
cmp(Topology,
rpc:call(Node, erlang, system_flag, [cpu_topology, Topology])),
cmp(Topology,
rpc:call(Node, erlang, system_info, [cpu_topology])),
- stop_node(Node)
+ peer:stop(Peer)
after
restore_erl_rel_flags(OldRelFlags)
end,
ok.
+ssrct_cmd(Config) when is_list(Config) ->
+ OldRelFlags = clear_erl_rel_flags(),
+ try
+ {ok, Peer, Node} = ?CT_PEER(["+ssrct"]),
+ cmp(undefined,
+ rpc:call(Node, erlang, system_info, [cpu_topology])),
+ cmp(undefined,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, detected}])),
+ cmp(undefined,
+ rpc:call(Node, erlang, system_info, [{cpu_topology, defined}])),
+ peer:stop(Peer)
+ after
+ restore_erl_rel_flags(OldRelFlags)
+ end,
+ ok.
+
-define(BIND_TYPES,
[{"u", unbound},
{"ns", no_spread},
@@ -1020,7 +1046,7 @@ sbt_cmd(Config) when is_list(Config) ->
OldRelFlags = clear_erl_rel_flags(),
try
lists:foreach(fun ({ClBt, Bt}) ->
- sbt_test(Config, CpuTCmd,
+ sbt_test(CpuTCmd,
ClBt, Bt, LP)
end,
?BIND_TYPES)
@@ -1038,10 +1064,10 @@ sbt_make_topology_args() ->
linux ->
case erlang:system_info(logical_processors) of
1 ->
- "+sctL0";
+ ["+sctL0"];
N ->
NS = integer_to_list(N - 1),
- "+sctL0-"++NS++"p0-"++NS
+ ["+sctL0-"++NS++"p0-"++NS]
end;
_ ->
false
@@ -1085,11 +1111,11 @@ sbt_check_prereqs() ->
throw:{skip,_Reason}=Skip -> Skip
end.
-sbt_test(Config, CpuTCmd, ClBt, Bt, LP) ->
+sbt_test(CpuTCmd, ClBt, Bt, LP) ->
io:format("Testing +sbt ~s (~p)~n", [ClBt, Bt]),
LPS = integer_to_list(LP),
- Cmd = CpuTCmd++" +sbt "++ClBt++" +S"++LPS++":"++LPS,
- {ok, Node} = start_node(Config, Cmd),
+ Cmd = CpuTCmd++["+sbt", ClBt, "+S"++LPS++":"++LPS],
+ {ok, Peer, Node} = ?CT_PEER(Cmd),
Bt = rpc:call(Node,
erlang,
system_info,
@@ -1113,16 +1139,16 @@ sbt_test(Config, CpuTCmd, ClBt, Bt, LP) ->
end,
BS,
tuple_to_list(SB)),
- stop_node(Node),
+ peer:stop(Peer),
ok.
scheduler_threads(Config) when is_list(Config) ->
- {Sched, SchedOnln, _} = get_sstate(Config, ""),
+ {Sched, SchedOnln, _} = get_sstate(""),
%% Configure half the number of both the scheduler threads and
%% the scheduler threads online.
{HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]),
lists:max([1,SchedOnln div 2])},
- {HalfSched, HalfSchedOnln, _} = get_sstate(Config, "+SP 50:50"),
+ {HalfSched, HalfSchedOnln, _} = get_sstate(["+SP", "50:50"]),
%% Use +S to configure 4x the number of scheduler threads and
%% 4x the number of scheduler threads online, but alter that
%% setting using +SP to 50% scheduler threads and 25% scheduler
@@ -1131,19 +1157,19 @@ scheduler_threads(Config) when is_list(Config) ->
TwiceSched = Sched*2,
FourSched = integer_to_list(Sched*4),
FourSchedOnln = integer_to_list(SchedOnln*4),
- CombinedCmd1 = "+S "++FourSched++":"++FourSchedOnln++" +SP50:25",
- {TwiceSched, SchedOnln, _} = get_sstate(Config, CombinedCmd1),
+ CombinedCmd1 = ["+S", FourSched++":"++FourSchedOnln, "+SP50:25"],
+ {TwiceSched, SchedOnln, _} = get_sstate(CombinedCmd1),
%% Now do the same test but with the +S and +SP options in the
%% opposite order, since order shouldn't matter.
- CombinedCmd2 = "+SP50:25 +S "++FourSched++":"++FourSchedOnln,
- {TwiceSched, SchedOnln, _} = get_sstate(Config, CombinedCmd2),
+ CombinedCmd2 = ["+SP50:25", "+S", FourSched++":"++FourSchedOnln],
+ {TwiceSched, SchedOnln, _} = get_sstate(CombinedCmd2),
%% Apply two +SP options to make sure the second overrides the first
- TwoCmd = "+SP 25:25 +SP 100:100",
- {Sched, SchedOnln, _} = get_sstate(Config, TwoCmd),
+ TwoCmd = ["+SP", "25:25", "+SP", "100:100"],
+ {Sched, SchedOnln, _} = get_sstate(TwoCmd),
%% Configure 50% of scheduler threads online only
- {Sched, HalfSchedOnln, _} = get_sstate(Config, "+SP:50"),
+ {Sched, HalfSchedOnln, _} = get_sstate(["+SP:50"]),
%% Configure 2x scheduler threads only
- {TwiceSched, SchedOnln, _} = get_sstate(Config, "+SP 200"),
+ {TwiceSched, SchedOnln, _} = get_sstate(["+SP", "200"]),
LProc = erlang:system_info(logical_processors),
LProcAvail = erlang:system_info(logical_processors_available),
@@ -1157,30 +1183,30 @@ scheduler_threads(Config) when is_list(Config) ->
is_integer(LProc); is_integer(LProcAvail) ->
ExpectedOnln = st_expected_onln(LProcAvail, Quota),
- st_reset(Config, LProc, ExpectedOnln, FourSched, FourSchedOnln),
+ st_reset(LProc, ExpectedOnln, FourSched, FourSchedOnln),
if
LProc =:= 1; LProcAvail =:= 1 ->
{comment, "Skipped reduced amount of schedulers test due "
"to too few logical processors"};
LProc > 1, LProcAvail > 1 ->
- st_reduced(Config, LProc, ExpectedOnln)
+ st_reduced(LProc, ExpectedOnln)
end
end.
-st_reset(Config, LProc, ExpectedOnln, FourSched, FourSchedOnln) ->
+st_reset(LProc, ExpectedOnln, FourSched, FourSchedOnln) ->
%% Test resetting # of schedulers.
- ResetCmd = "+S "++FourSched++":"++FourSchedOnln++" +S 0:0",
- {LProc, ExpectedOnln, _} = get_sstate(Config, ResetCmd),
+ ResetCmd = ["+S", FourSched++":"++FourSchedOnln, "+S", "0:0"],
+ {LProc, ExpectedOnln, _} = get_sstate(ResetCmd),
ok.
-st_reduced(Config, LProc, ExpectedOnln) ->
+st_reduced(LProc, ExpectedOnln) ->
%% Test negative +S settings
SchedMinus1 = LProc-1,
SchedOnlnMinus1 = ExpectedOnln-1,
- {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1"),
- {LProc, SchedOnlnMinus1, _} = get_sstate(Config, "+S :-1"),
- {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1:-1"),
+ {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(["+S", "-1"]),
+ {LProc, SchedOnlnMinus1, _} = get_sstate(["+S", ":-1"]),
+ {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(["+S", "-1:-1"]),
ok.
st_expected_onln(LProcAvail, unknown) -> LProcAvail;
@@ -1192,18 +1218,19 @@ dirty_scheduler_threads(Config) when is_list(Config) ->
_ -> dirty_scheduler_threads_test(Config)
end.
-dirty_scheduler_threads_test(Config) ->
- {Sched, SchedOnln, _} = get_dsstate(Config, ""),
+dirty_scheduler_threads_test(Config) when is_list(Config) ->
+ {Sched, SchedOnln, _} = get_dsstate(""),
{HalfSched, HalfSchedOnln} = {lists:max([1,Sched div 2]),
lists:max([1,SchedOnln div 2])},
- Cmd1 = "+SDcpu "++integer_to_list(HalfSched)++":"++
- integer_to_list(HalfSchedOnln),
- {HalfSched, HalfSchedOnln, _} = get_dsstate(Config, Cmd1),
- {HalfSched, HalfSchedOnln, _} = get_dsstate(Config, "+SDPcpu 50:50"),
+ Cmd1 = ["+SDcpu", integer_to_list(HalfSched)++":"++
+ integer_to_list(HalfSchedOnln)],
+ {HalfSched, HalfSchedOnln, _} = get_dsstate(Cmd1),
+ {HalfSched, HalfSchedOnln, _} = get_dsstate(["+SDPcpu", "50:50"]),
IOSched = 20,
- {_, _, IOSched} = get_dsstate(Config, "+SDio "++integer_to_list(IOSched)),
- {ok, Node} = start_node(Config, ""),
+ {_, _, IOSched} = get_dsstate(["+SDio", integer_to_list(IOSched)]),
+ {ok, Peer, Node} = ?CT_PEER(),
[ok] = mcall(Node, [fun() -> dirty_schedulers_online_test() end]),
+ peer:stop(Peer),
ok.
dirty_schedulers_online_test() ->
@@ -1227,16 +1254,16 @@ dirty_schedulers_online_smp_test(SchedOnln) ->
QrtrDirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online),
ok.
-get_sstate(Config, Cmd) ->
- {ok, Node} = start_node(Config, Cmd),
+get_sstate(Cmd) ->
+ {ok, Peer, Node} = ?CT_PEER(#{ args => Cmd, env => [{"ERL_FLAGS",false}]}),
[SState] = mcall(Node, [fun () ->
erlang:system_info(schedulers_state)
end]),
- stop_node(Node),
+ peer:stop(Peer),
SState.
-get_dsstate(Config, Cmd) ->
- {ok, Node} = start_node(Config, Cmd),
+get_dsstate(Cmd) ->
+ {ok, Peer, Node} = ?CT_PEER(#{ args => Cmd, env => [{"ERL_FLAGS",false}]}),
[DSCPU] = mcall(Node, [fun () ->
erlang:system_info(dirty_cpu_schedulers)
end]),
@@ -1246,7 +1273,7 @@ get_dsstate(Config, Cmd) ->
[DSIO] = mcall(Node, [fun () ->
erlang:system_info(dirty_io_schedulers)
end]),
- stop_node(Node),
+ peer:stop(Peer),
{DSCPU, DSCPUOnln, DSIO}.
scheduler_suspend_basic(Config) when is_list(Config) ->
@@ -1360,18 +1387,19 @@ scheduler_suspend_basic_test() ->
scheduler_suspend(Config) when is_list(Config) ->
ct:timetrap({minutes, 5}),
- lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end,
+ lists:foreach(fun (S) -> scheduler_suspend_test(S) end,
[64, 32, 16, default]),
ok.
-scheduler_suspend_test(Config, Schedulers) ->
+
+scheduler_suspend_test(Schedulers) ->
Cmd = case Schedulers of
default ->
"";
_ ->
S = integer_to_list(Schedulers),
- "+S"++S++":"++S
+ ["+S"++S++":"++S]
end,
- {ok, Node} = start_node(Config, Cmd),
+ {ok, Peer, Node} = ?CT_PEER(Cmd),
[SState] = mcall(Node, [fun () ->
erlang:system_info(schedulers_state)
end]),
@@ -1413,7 +1441,7 @@ scheduler_suspend_test(Config, Schedulers) ->
native)),
erlang:system_info(schedulers_state)
end]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
until(Pred, MaxTime) ->
@@ -1502,59 +1530,102 @@ sst5_loop(N) ->
erlang:system_flag(multi_scheduling, unblock_normal),
sst5_loop(N-1).
+%% Test scheduler polling: +IOs true|false
+sched_poll(Config) when is_list(Config) ->
+
+ Env = case os:getenv("ERL_AFLAGS") of
+ false ->
+ [];
+ AFLAGS1 ->
+ %% Remove any +IOs
+ AFLAGS2 = list_to_binary(re:replace(AFLAGS1,
+ "\\+IOs (true|false)",
+ "", [global])),
+ [{"ERL_AFLAGS", binary_to_list(AFLAGS2)}]
+ end,
+
+ [PS | _] = get_iostate(""),
+ HaveSchedPoll = proplists:get_value(concurrent_updates, PS),
+
+ 0 = get_sched_pollsets(["+IOs", "false"]),
+ if
+ HaveSchedPoll ->
+ 1 = get_sched_pollsets(["+IOs", "true"]),
+ 1 = get_sched_pollsets([], Env);
+
+ not HaveSchedPoll ->
+ fail = get_sched_pollsets(["+IOs", "true"]),
+ 0 = get_sched_pollsets([], Env)
+ end,
+ fail = get_sched_pollsets(["+IOs", "bad"]),
+ ok.
+
+get_sched_pollsets(Cmd) ->
+ get_sched_pollsets(Cmd, []).
+
+get_sched_pollsets(Cmd, Env)->
+ try
+ {ok, Peer, Node} = ?CT_PEER(#{connection => standard_io, args => Cmd,
+ env => [{"ERL_LIBS", false} | Env]}),
+ [IOStates] = mcall(Node,[fun () -> erlang:system_info(check_io) end]),
+ IO = [IOState || IOState <- IOStates,
+ %% We assume non-fallbacks without threads are scheduler pollsets
+ proplists:get_value(fallback, IOState) == false,
+ proplists:get_value(poll_threads, IOState) == 0],
+ peer:stop(Peer),
+ length(IO) % number of scheduler pollsets
+ catch
+ exit:{boot_failed, _} ->
+ fail
+ end.
+
poll_threads(Config) when is_list(Config) ->
- {Conc, PollType, KP} = get_ioconfig(Config),
- {Sched, SchedOnln, _} = get_sstate(Config, ""),
+ [PS | _] = get_iostate(""),
+ Conc = proplists:get_value(concurrent_updates, PS),
- [1, 1] = get_ionum(Config,"+IOt 2 +IOp 2"),
- [1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 5"),
- [1, 1] = get_ionum(Config, "+S 2 +IOPt 100 +IOPp 100"),
+ [1, 1] = get_ionum(["+IOt", "2", "+IOp", "2"]),
+ [1, 1, 1, 1, 1] = get_ionum(["+IOt", "5", "+IOp", "5"]),
+ [1, 1] = get_ionum(["+S", "2", "+IOPt", "100", "+IOPp", "100"]),
if
Conc ->
- [5] = get_ionum(Config,"+IOt 5 +IOp 1"),
- [3, 2] = get_ionum(Config,"+IOt 5 +IOp 2"),
- [2, 2, 2, 2, 2] = get_ionum(Config,"+IOt 10 +IOPp 50"),
+ [5] = get_ionum(["+IOt", "5", "+IOp", "1"]),
+ [3, 2] = get_ionum(["+IOt", "5", "+IOp", "2"]),
+ [2, 2, 2, 2, 2] = get_ionum(["+IOt", "10", "+IOPp", "50"]),
- [2] = get_ionum(Config, "+S 2 +IOPt 100"),
- [4] = get_ionum(Config, "+S 4 +IOPt 100"),
- [4] = get_ionum(Config, "+S 4:2 +IOPt 100"),
- [4, 4] = get_ionum(Config, "+S 8 +IOPt 100 +IOPp 25"),
+ [2] = get_ionum(["+S", "2", "+IOPt", "100"]),
+ [4] = get_ionum(["+S", "4", "+IOPt", "100"]),
+ [4] = get_ionum(["+S", "4:2", "+IOPt", "100"]),
+ [4, 4] = get_ionum(["+S", "8", "+IOPt", "100", "+IOPp", "25"]),
- fail = get_ionum(Config, "+IOt 1 +IOp 2"),
+ fail = get_ionum(["+IOt", "1", "+IOp", "2"]),
ok;
not Conc ->
- [1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 1"),
- [1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 2"),
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 10 +IOPp 50"),
+ [1, 1, 1, 1, 1] = get_ionum(["+IOt", "5", "+IOp", "1"]),
+ [1, 1, 1, 1, 1] = get_ionum(["+IOt", "5", "+IOp", "2"]),
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] = get_ionum(["+IOt", "10", "+IOPp", "50"]),
- [1, 1] = get_ionum(Config, "+S 2 +IOPt 100"),
- [1, 1, 1, 1] = get_ionum(Config, "+S 4 +IOPt 100"),
- [1, 1, 1, 1] = get_ionum(Config, "+S 4:2 +IOPt 100"),
- [1, 1, 1, 1, 1, 1, 1, 1] = get_ionum(Config, "+S 8 +IOPt 100 +IOPp 25"),
+ [1, 1] = get_ionum(["+S", "2", "+IOPt", "100"]),
+ [1, 1, 1, 1] = get_ionum(["+S", "4", "+IOPt", "100"]),
+ [1, 1, 1, 1] = get_ionum(["+S", "4:2", "+IOPt", "100"]),
+ [1, 1, 1, 1, 1, 1, 1, 1] = get_ionum(["+S", "8", "+IOPt", "100" "+IOPp", "25"]),
- [1] = get_ionum(Config, "+IOt 1 +IOp 2"),
+ [1] = get_ionum(["+IOt", "1", "+IOp", "2"]),
ok
end,
- fail = get_ionum(Config, "+IOt 1 +IOPp 101"),
- fail = get_ionum(Config, "+IOt 0"),
- fail = get_ionum(Config, "+IOPt 101"),
+ fail = get_ionum(["+IOt", "1", "+IOPp", "101"]),
+ fail = get_ionum(["+IOt", "0"]),
+ fail = get_ionum(["+IOPt", "101"]),
ok.
-get_ioconfig(Config) ->
- [PS | _] = get_iostate(Config, ""),
- {proplists:get_value(concurrent_updates, PS),
- proplists:get_value(primary, PS),
- proplists:get_value(kernel_poll, PS)}.
-
-get_ionum(Config, Cmd) ->
- case get_iostate(Config, Cmd) of
+get_ionum(Cmd) ->
+ case get_iostate(Cmd) of
fail -> fail;
PSs ->
lists:reverse(
@@ -1562,18 +1633,18 @@ get_ionum(Config, Cmd) ->
[proplists:get_value(poll_threads, PS) || PS <- PSs]))
end.
-get_iostate(Config, Cmd)->
- case start_node(Config, Cmd) of
- {ok, Node} ->
- [IOStates] = mcall(Node,[fun () ->
- erlang:system_info(check_io)
- end]),
- IO = [IOState || IOState <- IOStates,
- proplists:get_value(fallback, IOState) == false,
- proplists:get_value(poll_threads, IOState) /= 0],
- stop_node(Node),
- IO;
- {error,timeout} ->
+get_iostate(Cmd)->
+ try
+ {ok, Peer, Node} = ?CT_PEER(#{connection => standard_io, args => Cmd,
+ env => [{"ERL_LIBS", false}]}),
+ [IOStates] = mcall(Node,[fun () -> erlang:system_info(check_io) end]),
+ IO = [IOState || IOState <- IOStates,
+ proplists:get_value(fallback, IOState) == false,
+ proplists:get_value(poll_threads, IOState) /= 0],
+ peer:stop(Peer),
+ IO
+ catch
+ exit:{boot_failed, _} ->
fail
end.
@@ -2490,24 +2561,6 @@ active_schedulers() ->
enabled -> N
end
end.
-
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
enable_internal_state() ->
case catch erts_debug:get_internal_state(available_internal_state) of
diff --git a/erts/emulator/test/send_term_SUITE.erl b/erts/emulator/test/send_term_SUITE.erl
index 9531c13b9a..35f0d11e67 100644
--- a/erts/emulator/test/send_term_SUITE.erl
+++ b/erts/emulator/test/send_term_SUITE.erl
@@ -212,14 +212,14 @@ make_expected_ext2term_drv([T|Ts]) ->
%%
generate_external_terms_files(BaseDir) ->
- {ok,Node} = slave:start(hostname(), a_node),
+ {ok, Peer, Node} = ?CT_PEER(),
RPid = rpc:call(Node, erlang, self, []),
true = is_pid(RPid),
RRef = rpc:call(Node, erlang, make_ref, []),
true = is_reference(RRef),
RPort = hd(rpc:call(Node, erlang, ports, [])),
true = is_port(RPort),
- slave:stop(Node),
+ peer:stop(Peer),
Terms = [{4711, -4711, [an_atom, "a list"]},
[1000000000000000000000,-1111111111111111, "blupp!", blipp],
{RPid, {RRef, RPort}, self(), hd(erlang:ports()), make_ref()},
@@ -341,12 +341,3 @@ write_license(IoDev) ->
" * and needs to be consistent with each other.~n"
" */~n",
io:format(IoDev, S, []).
-
-
-hostname() ->
- hostname(atom_to_list(node())).
-
-hostname([$@ | Hostname]) ->
- list_to_atom(Hostname);
-hostname([_C | Cs]) ->
- hostname(Cs).
diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl
index 076d9f9885..0c5b27a0b1 100644
--- a/erts/emulator/test/signal_SUITE.erl
+++ b/erts/emulator/test/signal_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,22 +32,43 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,init_per_suite/1, end_per_suite/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
+-export([groups/0, init_per_group/2, end_per_group/2]).
% Test cases
-export([xm_sig_order/1,
kill2killed/1,
contended_signal_handling/1,
+ dirty_signal_handling_race/1,
busy_dist_exit_signal/1,
busy_dist_demonitor_signal/1,
busy_dist_down_signal/1,
busy_dist_spawn_reply_signal/1,
- busy_dist_unlink_ack_signal/1]).
+ busy_dist_unlink_ack_signal/1,
+ unlink_exit/1,
+ monitor_order/1,
+ monitor_named_order_local/1,
+ monitor_named_order_remote/1,
+ monitor_nodes_order/1,
+ move_msgs_off_heap_signal_basic/1,
+ move_msgs_off_heap_signal_recv/1,
+ move_msgs_off_heap_signal_exit/1,
+ move_msgs_off_heap_signal_recv_exit/1,
+ copy_literal_area_signal_basic/1,
+ copy_literal_area_signal_recv/1,
+ copy_literal_area_signal_exit/1,
+ copy_literal_area_signal_recv_exit/1,
+ simultaneous_signals_basic/1,
+ simultaneous_signals_recv/1,
+ simultaneous_signals_exit/1,
+ simultaneous_signals_recv_exit/1]).
+
+-export([spawn_spammers/3]).
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
[{testcase, Func}|Config].
-end_per_testcase(_Func, _Config) ->
- ok.
+end_per_testcase(_Func, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
init_per_suite(Config) ->
Config.
@@ -63,21 +84,48 @@ all() ->
[xm_sig_order,
kill2killed,
contended_signal_handling,
+ dirty_signal_handling_race,
busy_dist_exit_signal,
busy_dist_demonitor_signal,
busy_dist_down_signal,
busy_dist_spawn_reply_signal,
- busy_dist_unlink_ack_signal].
+ busy_dist_unlink_ack_signal,
+ unlink_exit,
+ monitor_order,
+ monitor_named_order_local,
+ monitor_named_order_remote,
+ monitor_nodes_order,
+ {group, adjust_message_queue}].
+
+groups() ->
+ [{adjust_message_queue, [],
+ [move_msgs_off_heap_signal_basic,
+ move_msgs_off_heap_signal_recv,
+ move_msgs_off_heap_signal_exit,
+ move_msgs_off_heap_signal_recv_exit,
+ copy_literal_area_signal_basic,
+ copy_literal_area_signal_recv,
+ copy_literal_area_signal_exit,
+ copy_literal_area_signal_recv_exit,
+ simultaneous_signals_basic,
+ simultaneous_signals_recv,
+ simultaneous_signals_exit,
+ simultaneous_signals_recv_exit]}].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
%% Test that exit signals and messages are received in correct order
xm_sig_order(Config) when is_list(Config) ->
LNode = node(),
- repeat(fun () -> xm_sig_order_test(LNode) end, 1000),
- {ok, RNode} = start_node(Config),
- repeat(fun () -> xm_sig_order_test(RNode) end, 1000),
- stop_node(RNode),
+ repeat(fun (_) -> xm_sig_order_test(LNode) end, 1000),
+ {ok, Peer, RNode} = ?CT_PEER(),
+ repeat(fun (_) -> xm_sig_order_test(RNode) end, 1000),
+ peer:stop(Peer),
ok.
-
xm_sig_order_test(Node) ->
P = spawn(Node, fun () -> xm_sig_order_proc() end),
@@ -105,10 +153,9 @@ xm_sig_order_proc() ->
kill2killed(Config) when is_list(Config) ->
process_flag(trap_exit, true),
kill2killed_test(node()),
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
kill2killed_test(Node),
- stop_node(Node),
- ok.
+ peer:stop(Peer).
kill2killed_test(Node) ->
if Node == node() ->
@@ -186,7 +233,15 @@ contended_signal_handling(Config) when is_list(Config) ->
%% when the bug exists, but this testcase at least
%% sometimes causes a crash when the bug is present.
%%
+ move_dirty_signal_handlers_to_first_scheduler(),
process_flag(priority, high),
+ case erlang:system_info(schedulers_online) of
+ 1 ->
+ ok;
+ SOnln ->
+ process_flag(scheduler, SOnln),
+ ok
+ end,
Drv = unlink_signal_drv,
ok = load_driver(Config, Drv),
try
@@ -209,7 +264,7 @@ contended_signal_handling_test(Drv, N) ->
contended_signal_handling_cmd_ports([]) ->
ok;
contended_signal_handling_cmd_ports([P|Ps]) ->
- P ! {self(), {command, ""}},
+ P ! {self(), {command, "c"}},
contended_signal_handling_cmd_ports(Ps).
contended_signal_handling_make_ports(_Drv, 0, Ports) ->
@@ -219,18 +274,130 @@ contended_signal_handling_make_ports(Drv, N, Ports) ->
true = is_port(Port),
contended_signal_handling_make_ports(Drv, N-1, [Port|Ports]).
+dirty_signal_handling_race(Config) ->
+ %% This test case trigger more or less the same
+ %% problematic scenario as the contended_signal_handling
+ %% test case is trying to trigger. This test case triggers
+ %% it via another signal and is also much more likely
+ %% (close to 100%) to trigger the problematic schenario.
+ Tester = self(),
+ move_dirty_signal_handlers_to_first_scheduler(),
+ {S0, S1} = case erlang:system_info(schedulers_online) of
+ 1 -> {1, 1};
+ 2 -> {2, 1};
+ SOnln -> {SOnln, SOnln-1}
+ end,
+ process_flag(priority, high),
+ process_flag(scheduler, S0),
+ erts_debug:set_internal_state(available_internal_state, true),
+ Drv = unlink_signal_drv,
+ ok = load_driver(Config, Drv),
+ try
+ %% {parallelism, true} option will ensure that each
+ %% signal to the port from a process is scheduled which
+ %% forces the process to release its main lock when
+ %% sending the signal...
+ Port = open_port({spawn, Drv}, [{parallelism, true}]),
+ true = is_port(Port),
+ %% The {alias, reply_demonitor} option will trigger a
+ %% 'demonitor' signal from Tester to the port when an
+ %% alias message sent using the alias is received by
+ %% Tester...
+ MA1 = erlang:monitor(port, Port, [{alias, reply_demonitor}]),
+ MA2 = erlang:monitor(port, Port, [{alias, reply_demonitor}]),
+ Pid = spawn_opt(fun () ->
+ Tester ! go,
+ receive after 500 -> ok end,
+ %% The 'proc_sig_block' test signal will cause
+ %% dirty signal handling to start and be
+ %% blocked in the signal handling.
+ erts_debug:set_internal_state(proc_sig_block,
+ {Tester, 1000}),
+ %% Tester will be stuck waiting for main lock
+ %% when being scheduled out from its dirty
+ %% execution. When this alias message is
+ %% by the dirty signal handler Tester will be
+ %% able to aquire the main lock and complete
+ %% the schedule out operation.
+ MA1 ! {MA1, trigger_demonitor_port_please},
+ erts_debug:set_internal_state(proc_sig_block,
+ {Tester, 100}),
+ %% Tester will have been selected for
+ %% execution, but stuck waiting for main lock.
+ %% When this alias message is handled by the
+ %% dirty signal handler, Tester will be able
+ %% to aquire the main lock which will let it
+ %% enter the problematic scenario. That is,
+ %% ongoing dirty signal handling while it
+ %% begins executing.
+ MA2 ! {MA2, trigger_demonitor_port_please},
+ erts_debug:set_internal_state(proc_sig_block,
+ {Tester, 500}),
+ ok
+ end, [link, {scheduler, S1}]),
+ receive go -> ok end,
+ receive {'DOWN', MA1, port, Port, _} -> ct:fail(unexpected_port_down)
+ after 0 -> ok
+ end,
+ receive {'DOWN', MA2, port, Port, _} -> ct:fail(unexpected_port_down)
+ after 0 -> ok
+ end,
+ erts_debug:dirty_cpu(wait, 1000),
+ receive
+ {MA1, trigger_demonitor_port_please} -> ok
+ end,
+ receive
+ {MA2, trigger_demonitor_port_please} -> ok
+ end,
+ unlink(Pid),
+ unlink(Port),
+ exit(Pid, kill),
+ exit(Port, kill),
+ false = erlang:is_process_alive(Pid)
+ after
+ ok = erl_ddll:unload_driver(Drv)
+ end,
+ ok.
+
+move_dirty_signal_handlers_to_first_scheduler() ->
+ SOnln = erlang:system_flag(schedulers_online, 1),
+ try
+ true = lists:foldl(
+ fun (Pid, FoundOne) ->
+ case process_info(Pid, initial_call) of
+ {initial_call, {erts_dirty_process_signal_handler,start,0}} ->
+ Pid ! please_execute_a_bit,
+ true;
+ _ ->
+ FoundOne
+ end
+ end,
+ false,
+ processes())
+ after
+ erlang:system_flag(schedulers_online, SOnln)
+ end,
+ ok.
+
busy_dist_exit_signal(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
+
BusyTime = 1000,
- {ok, BusyChannelNode} = start_node(Config),
- {ok, OtherNode} = start_node(Config, "-proto_dist gen_tcp"),
+ {ok, BusyChannelPeer, BusyChannelNode} = ?CT_PEER(),
+ {ok, OtherPeer, OtherNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
Tester = self(),
- Exiter = spawn(BusyChannelNode,
- fun () ->
- pong = net_adm:ping(OtherNode),
- Tester ! {self(), alive},
- receive after infinity -> ok end
- end),
- receive {Exiter, alive} -> ok end,
+ {Exiter,MRef} = spawn_monitor(BusyChannelNode,
+ fun () ->
+ pong = net_adm:ping(OtherNode),
+ Tester ! {self(), alive},
+ receive after infinity -> ok end
+ end),
+ receive
+ {Exiter, alive} ->
+ erlang:demonitor(MRef, [flush]);
+ {'DOWN', MRef, process, Why, normal} ->
+ ct:fail({exiter_died, Why})
+ end,
Linker = spawn_link(OtherNode,
fun () ->
process_flag(trap_exit, true),
@@ -243,7 +410,7 @@ busy_dist_exit_signal(Config) when is_list(Config) ->
exit({unexpected_message, Unexpected})
end
end),
- make_busy(BusyChannelNode, OtherNode, 1000),
+ make_busy(BusyChannelNode, OtherNode, BusyTime),
exit(Exiter, tester_killed_me),
receive
{Linker, got_exiter_exit_message} ->
@@ -253,14 +420,16 @@ busy_dist_exit_signal(Config) when is_list(Config) ->
BusyTime*2 ->
ct:fail(missing_exit_signal)
end,
- stop_node(BusyChannelNode),
- stop_node(OtherNode),
+ peer:stop(BusyChannelPeer),
+ peer:stop(OtherPeer),
ok.
busy_dist_demonitor_signal(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
+
BusyTime = 1000,
- {ok, BusyChannelNode} = start_node(Config),
- {ok, OtherNode} = start_node(Config, "-proto_dist gen_tcp"),
+ {ok, BusyChannelPeer, BusyChannelNode} = ?CT_PEER(),
+ {ok, OtherPeer, OtherNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
Tester = self(),
Demonitorer = spawn(BusyChannelNode,
fun () ->
@@ -292,7 +461,7 @@ busy_dist_demonitor_signal(Config) when is_list(Config) ->
end),
Demonitorer ! {self(), monitor, Demonitoree},
receive {Demonitoree, monitored} -> ok end,
- make_busy(BusyChannelNode, OtherNode, 1000),
+ make_busy(BusyChannelNode, OtherNode, BusyTime),
exit(Demonitorer, tester_killed_me),
receive
{Demonitoree, got_demonitorer_demonitor_signal} ->
@@ -302,22 +471,29 @@ busy_dist_demonitor_signal(Config) when is_list(Config) ->
BusyTime*2 ->
ct:fail(missing_demonitor_signal)
end,
- stop_node(BusyChannelNode),
- stop_node(OtherNode),
+ peer:stop(BusyChannelPeer),
+ peer:stop(OtherPeer),
ok.
busy_dist_down_signal(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
+
BusyTime = 1000,
- {ok, BusyChannelNode} = start_node(Config),
- {ok, OtherNode} = start_node(Config, "-proto_dist gen_tcp"),
+ {ok, BusyChannelPeer, BusyChannelNode} = ?CT_PEER(),
+ {ok, OtherPeer, OtherNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
Tester = self(),
- Exiter = spawn(BusyChannelNode,
- fun () ->
- pong = net_adm:ping(OtherNode),
- Tester ! {self(), alive},
- receive after infinity -> ok end
- end),
- receive {Exiter, alive} -> ok end,
+ {Exiter,MRef} = spawn_monitor(BusyChannelNode,
+ fun () ->
+ pong = net_adm:ping(OtherNode),
+ Tester ! {self(), alive},
+ receive after infinity -> ok end
+ end),
+ receive
+ {Exiter, alive} ->
+ erlang:demonitor(MRef, [flush]);
+ {'DOWN', MRef, process, Why, normal} ->
+ ct:fail({exiter_died, Why})
+ end,
Monitorer = spawn_link(OtherNode,
fun () ->
process_flag(trap_exit, true),
@@ -330,7 +506,7 @@ busy_dist_down_signal(Config) when is_list(Config) ->
exit({unexpected_message, Unexpected})
end
end),
- make_busy(BusyChannelNode, OtherNode, 1000),
+ make_busy(BusyChannelNode, OtherNode, BusyTime),
exit(Exiter, tester_killed_me),
receive
{Monitorer, got_exiter_down_message} ->
@@ -340,14 +516,16 @@ busy_dist_down_signal(Config) when is_list(Config) ->
BusyTime*2 ->
ct:fail(missing_down_signal)
end,
- stop_node(BusyChannelNode),
- stop_node(OtherNode),
+ peer:stop(BusyChannelPeer),
+ peer:stop(OtherPeer),
ok.
busy_dist_spawn_reply_signal(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
+
BusyTime = 1000,
- {ok, BusyChannelNode} = start_node(Config),
- {ok, OtherNode} = start_node(Config, "-proto_dist gen_tcp"),
+ {ok, BusyChannelPeer, BusyChannelNode} = ?CT_PEER(),
+ {ok, OtherPeer, OtherNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
Tester = self(),
Spawner = spawn_link(OtherNode,
fun () ->
@@ -366,7 +544,7 @@ busy_dist_spawn_reply_signal(Config) when is_list(Config) ->
end
end),
receive {Spawner, ready} -> ok end,
- make_busy(BusyChannelNode, OtherNode, 1000),
+ make_busy(BusyChannelNode, OtherNode, BusyTime),
Spawner ! {self(), go},
receive
{Spawner, got_spawn_reply_message} ->
@@ -376,8 +554,8 @@ busy_dist_spawn_reply_signal(Config) when is_list(Config) ->
BusyTime*2 ->
ct:fail(missing_spawn_reply_signal)
end,
- stop_node(BusyChannelNode),
- stop_node(OtherNode),
+ peer:stop(BusyChannelPeer),
+ peer:stop(OtherPeer),
ok.
-record(erl_link, {type, % process | port | dist_process
@@ -386,17 +564,24 @@ busy_dist_spawn_reply_signal(Config) when is_list(Config) ->
id}).
busy_dist_unlink_ack_signal(Config) when is_list(Config) ->
+ ct:timetrap({seconds, 10}),
+
BusyTime = 1000,
- {ok, BusyChannelNode} = start_node(Config),
- {ok, OtherNode} = start_node(Config, "-proto_dist gen_tcp"),
+ {ok, BusyChannelPeer, BusyChannelNode} = ?CT_PEER(),
+ {ok, OtherPeer, OtherNode} = ?CT_PEER(["-proto_dist", "gen_tcp"]),
Tester = self(),
- Unlinkee = spawn(BusyChannelNode,
- fun () ->
- pong = net_adm:ping(OtherNode),
- Tester ! {self(), alive},
- receive after infinity -> ok end
- end),
- receive {Unlinkee, alive} -> ok end,
+ {Unlinkee,MRef} = spawn_monitor(BusyChannelNode,
+ fun () ->
+ pong = net_adm:ping(OtherNode),
+ Tester ! {self(), alive},
+ receive after infinity -> ok end
+ end),
+ receive
+ {Unlinkee, alive} ->
+ erlang:demonitor(MRef, [flush]);
+ {'DOWN', MRef, process, Why, normal} ->
+ ct:fail({unlinkee_died, Why})
+ end,
Unlinker = spawn_link(OtherNode,
fun () ->
erts_debug:set_internal_state(available_internal_state, true),
@@ -419,7 +604,7 @@ busy_dist_unlink_ack_signal(Config) when is_list(Config) ->
Tester ! {self(), got_unlink_ack_signal}
end),
receive {Unlinker, ready} -> ok end,
- make_busy(BusyChannelNode, OtherNode, 1000),
+ make_busy(BusyChannelNode, OtherNode, BusyTime),
Unlinker ! {self(), go},
receive
{Unlinker, got_unlink_ack_signal} ->
@@ -429,14 +614,530 @@ busy_dist_unlink_ack_signal(Config) when is_list(Config) ->
BusyTime*2 ->
ct:fail(missing_unlink_ack_signal)
end,
- stop_node(BusyChannelNode),
- stop_node(OtherNode),
+ peer:stop(BusyChannelPeer),
+ peer:stop(OtherPeer),
+ ok.
+
+unlink_exit(Config) when is_list(Config) ->
+ %% OTP-18177
+ %%
+ %% This bug is theoretically possible, at least in the
+ %% node local scenario, but more or less undetectable and
+ %% quite harmless when it hits. A process A (the child in
+ %% the testcase) could get actual exit reason of another
+ %% process B (the parent in the testcase) when it should
+ %% have gotten 'noproc' as exit reason. This can happen if
+ %% 1. B unlinks A
+ %% 2. B begin terminating before it has received an unlink
+ %% ack from A
+ %% 3. A links to B after it has received the unlink signal
+ %%
+ %% This testcase hammers on the above scenario, but I have
+ %% not seen it fail yet though when the bug is present...
+ repeat(fun unlink_exit_test/0, 1000).
+
+unlink_exit_test() ->
+ Tester = self(),
+ ChildFun =
+ fun () ->
+ process_flag(trap_exit, true),
+ Tester ! {child, self()},
+ Parent = receive {tester_parent, Tester, Pid} -> Pid end,
+ Parent ! {go, self()},
+ busy_wait_until(fun () ->
+ receive {go, Parent} -> true
+ after 0 -> false
+ end
+ end),
+ IsAlive = erlang:is_process_alive(Parent),
+ try
+ link(Parent),
+ case IsAlive of
+ false ->
+ receive
+ {'EXIT', Parent, noproc} ->
+ exit(ok);
+ {'EXIT', Parent, R1} ->
+ exit({not_alive_unexpected_exit_reason, R1})
+ after 1000 ->
+ exit(not_alive_missing_exit)
+ end;
+ true ->
+ receive
+ {'EXIT', Parent, R2} when R2 == noproc;
+ R2 == bye ->
+ exit(ok);
+ {'EXIT', Parent, R2} ->
+ exit({alive_unexpected_exit_reason, R2})
+ after 1000 ->
+ exit(alive_missing_exit)
+ end
+ end
+ catch error:noproc ->
+ receive
+ {'EXIT', Parent, _} = X0 ->
+ exit({unexpected_exit, X0})
+ after 1000 ->
+ exit(ok)
+ end
+ end
+ end,
+ {Parent, PMon} = spawn_opt(fun () ->
+ %% Work to do when terminating in order
+ %% to increase the likelyhood of the
+ %% bug triggering (if present)...
+ T = ets:new(x,[]),
+ ets:insert(T, lists:map(fun (I) ->
+ {I,I}
+ end,
+ lists:seq(1,10000))),
+
+ Child = spawn_opt(ChildFun,
+ [{priority, high},
+ link]),
+ receive {go, Child} -> ok end,
+ unlink(Child),
+ Child ! {go, self()},
+ exit(bye)
+ end, [{priority, high}, monitor]),
+ Child = receive {child, Chld} -> Chld end,
+ CMon = erlang:monitor(process, Child),
+ Child ! {tester_parent, Tester, Parent},
+ receive
+ {'DOWN', PMon, process, Parent, bye} ->
+ ok
+ end,
+ receive
+ {'DOWN', CMon, process, Child, ok} ->
+ ok;
+ {'DOWN', CMon, process, Child, ChildReason} ->
+ ct:fail(ChildReason)
+ end.
+
+%% Monitors could be reordered relative to message signals when the parallel
+%% signal sending optimization was active.
+monitor_order(_Config) ->
+ process_flag(message_queue_data, off_heap),
+ monitor_order_1(10).
+
+monitor_order_1(0) ->
+ ok;
+monitor_order_1(N) ->
+ Self = self(),
+ {Pid, MRef} = spawn_monitor(fun() ->
+ receive
+ MRef ->
+ %% The first message sets up
+ %% the parallel signal buffer,
+ %% the second uses it.
+ Self ! {self(), MRef, first},
+ Self ! {self(), MRef, second}
+ end,
+ exit(normal)
+ end),
+ Pid ! MRef,
+ receive
+ {'DOWN', MRef, process, _, normal} ->
+ ct:fail("Down signal arrived before second message!");
+ {Pid, MRef, second} ->
+ receive {Pid, MRef, first} -> ok end,
+ erlang:demonitor(MRef, [flush]),
+ monitor_order_1(N - 1)
+ end.
+
+%% Signal order: Message vs DOWN from local process monitored by name.
+monitor_named_order_local(_Config) ->
+ process_flag(message_queue_data, off_heap),
+ erts_debug:set_internal_state(available_internal_state, true),
+ true = erts_debug:set_internal_state(proc_sig_buffers, true),
+
+ LNode = node(),
+ repeat(fun (N) -> monitor_named_order(LNode, N) end, 100),
+ ok.
+
+%% Signal order: Message vs DOWN from remote process monitored by name.
+monitor_named_order_remote(_Config) ->
+ process_flag(message_queue_data, off_heap),
+ erts_debug:set_internal_state(available_internal_state, true),
+ true = erts_debug:set_internal_state(proc_sig_buffers, true),
+
+ {ok, Peer, RNode} = ?CT_PEER(),
+ repeat(fun (N) -> monitor_named_order(RNode, N) end, 10),
+ peer:stop(Peer),
+ ok.
+
+monitor_named_order(Node, N) ->
+ %% Send messages using pid, name and alias.
+ Pid = self(),
+ register(tester, Pid),
+ Name = {tester, node()},
+ AliasA = alias(),
+ NumMsg = 1000 + N,
+ Sender = spawn_link(Node,
+ fun() ->
+ register(monitor_named_order, self()),
+ Pid ! {self(), ready},
+ {go, AliasM} = receive_any(),
+ send_msg_seq(Pid, Name, AliasA, AliasM, NumMsg),
+ exit(normal)
+ end),
+ {Sender, ready} = receive_any(),
+ AliasM = monitor(process, {monitor_named_order,Node},
+ [{alias,explicit_unalias}]),
+ Sender ! {go, AliasM},
+ recv_msg_seq(NumMsg),
+ {'DOWN', AliasM, process, {monitor_named_order,Node}, normal}
+ = receive_any(),
+ unregister(tester),
+ unalias(AliasA),
+ unalias(AliasM),
+ ok.
+
+send_msg_seq(_, _, _, _, 0) -> ok;
+send_msg_seq(To1, To2, To3, To4, N) ->
+ To1 ! N,
+ send_msg_seq(To2, To3, To4, To1, N-1).
+
+recv_msg_seq(0) -> ok;
+recv_msg_seq(N) ->
+ N = receive M -> M end,
+ recv_msg_seq(N-1).
+
+receive_any() ->
+ receive M -> M end.
+
+receive_any(Timeout) ->
+ receive M -> M
+ after Timeout -> timeout
+ end.
+
+monitor_nodes_order(_Config) ->
+ process_flag(message_queue_data, off_heap),
+ erts_debug:set_internal_state(available_internal_state, true),
+ true = erts_debug:set_internal_state(proc_sig_buffers, true),
+
+ {ok, Peer, RNode} = ?CT_PEER(#{peer_down => continue,
+ connection => 0}),
+ Self = self(),
+ ok = net_kernel:monitor_nodes(true, [nodedown_reason]),
+ [] = nodes(connected),
+ Pids = peer:call(Peer, ?MODULE, spawn_spammers, [64, Self, []]),
+ {nodeup, RNode, []} = receive_any(),
+
+ ok = peer:cast(Peer, erlang, halt, [0]),
+
+ [put(P, 0) || P <- Pids], % spam counters per sender
+ {nodedown, RNode, [{nodedown_reason,connection_closed}]} =
+ receive_filter_spam(),
+ [io:format("From spammer ~p: ~p messages\n", [P, get(P)]) || P <- Pids],
+ timeout = receive_any(100), % Nothing after nodedown
+
+ {down, tcp_closed} = peer:get_state(Peer),
+ peer:stop(Peer),
+ ok.
+
+spawn_spammers(0, _To, Acc) ->
+ Acc;
+spawn_spammers(N, To, Acc) ->
+ Pid = spawn(fun() -> spam_pid(To, 1) end),
+ spawn_spammers(N-1, To, [Pid | Acc]).
+
+spam_pid(To, N) ->
+ To ! {spam, self(), N},
+ erlang:yield(), % Let other spammers run to get lots of different senders
+ spam_pid(To, N+1).
+
+receive_filter_spam() ->
+ receive
+ {spam, From, N} ->
+ match(N, get(From) + 1),
+ put(From, N),
+ receive_filter_spam();
+ M -> M
+ end.
+
+move_msgs_off_heap_signal_basic(Config) when is_list(Config) ->
+ move_msgs_off_heap_signal_test(false, false).
+
+move_msgs_off_heap_signal_recv(Config) when is_list(Config) ->
+ move_msgs_off_heap_signal_test(true, false).
+
+move_msgs_off_heap_signal_exit(Config) when is_list(Config) ->
+ move_msgs_off_heap_signal_test(false, true).
+
+move_msgs_off_heap_signal_recv_exit(Config) when is_list(Config) ->
+ move_msgs_off_heap_signal_test(true, true).
+
+move_msgs_off_heap_signal_test(RecvPair, Exit) ->
+ erlang:trace(new_processes, true, [running_procs]),
+ SFact = test_server:timetrap_scale_factor(),
+ GoTime = erlang:monotonic_time(millisecond) + 1000*SFact,
+ ProcF = fun () ->
+ Now = erlang:monotonic_time(millisecond),
+ Tmo = case GoTime - Now of
+ Left when Left < 0 ->
+ erlang:display({go_time_passed, Left}),
+ 0;
+ Left ->
+ Left
+ end,
+ receive after Tmo -> ok end,
+ on_heap = process_flag(message_queue_data, off_heap),
+ if RecvPair -> receive_integer_pairs(infinity);
+ true -> receive after infinity -> ok end
+ end
+ end,
+ Ps = lists:map(fun (_) ->
+ spawn_opt(ProcF,
+ [link,
+ {message_queue_data, on_heap}])
+ end, lists:seq(1, 100)),
+ lists:foreach(fun (P) ->
+ lists:foreach(fun (N) when N rem 100 == 0 ->
+ P ! [N|N];
+ (N) ->
+ P ! N
+ end, lists:seq(1, 10000))
+ end, Ps),
+ Now = erlang:monotonic_time(millisecond),
+ Tmo = case GoTime - Now + 10 of
+ Left when Left < 0 ->
+ erlang:display({go_time_passed, Left}),
+ 0;
+ Left ->
+ Left
+ end,
+ receive after Tmo -> ok end,
+ if Exit ->
+ _ = lists:foldl(fun (P, N) when N rem 10 ->
+ unlink(P),
+ exit(P, terminated),
+ N+1;
+ (_P, N) ->
+ N+1
+ end,
+ 0,
+ Ps),
+ ok;
+ true ->
+ ok
+ end,
+ wait_traced_not_running(1000 + 200*SFact),
+ erlang:trace(new_processes, false, [running_procs]),
+ lists:foreach(fun (P) ->
+ unlink(P),
+ exit(P, kill)
+ end, Ps),
+ lists:foreach(fun (P) ->
+ false = is_process_alive(P)
+ end, Ps),
+ ok.
+
+copy_literal_area_signal_basic(Config) when is_list(Config) ->
+ copy_literal_area_signal_test(false, false).
+
+copy_literal_area_signal_recv(Config) when is_list(Config) ->
+ copy_literal_area_signal_test(true, false).
+
+copy_literal_area_signal_exit(Config) when is_list(Config) ->
+ copy_literal_area_signal_test(false, true).
+
+copy_literal_area_signal_recv_exit(Config) when is_list(Config) ->
+ copy_literal_area_signal_test(true, true).
+
+copy_literal_area_signal_test(RecvPair, Exit) ->
+ persistent_term:put({?MODULE, ?FUNCTION_NAME}, make_ref()),
+ Literal = persistent_term:get({?MODULE, ?FUNCTION_NAME}),
+ true = is_reference(Literal),
+ 0 = erts_debug:size_shared(Literal), %% Should be a literal...
+ ProcF = fun () ->
+ 0 = erts_debug:size_shared(Literal), %% Should be a literal...
+ if RecvPair ->
+ receive receive_pairs -> ok end,
+ receive_integer_pairs(0);
+ true ->
+ ok
+ end,
+ receive check_literal_conversion -> ok end,
+ receive
+ Literal ->
+ %% Should not be a literal anymore...
+ false = (0 == erts_debug:size_shared(Literal))
+ end
+ end,
+ PMs = lists:map(fun (_) ->
+ spawn_opt(ProcF, [link, monitor])
+ end, lists:seq(1, 100)),
+ lists:foreach(fun ({P,_M}) ->
+ lists:foreach(fun (N) when N rem 100 == 0 ->
+ P ! [N|N];
+ (N) ->
+ P ! N
+ end, lists:seq(1, 10000)),
+ P ! Literal
+ end, PMs),
+ persistent_term:erase({?MODULE, ?FUNCTION_NAME}),
+ receive after 1 -> ok end,
+ if RecvPair ->
+ lists:foreach(fun ({P,_M}) ->
+ P ! receive_pairs
+ end, PMs);
+ true ->
+ ok
+ end,
+ if Exit ->
+ _ = lists:foldl(fun ({P, _M}, N) when N rem 10 ->
+ unlink(P),
+ exit(P, terminated),
+ N+1;
+ (_PM, N) ->
+ N+1
+ end,
+ 0,
+ PMs),
+ ok;
+ true ->
+ ok
+ end,
+ literal_area_collector_test:check_idle(),
+ lists:foreach(fun ({P,_M}) ->
+ P ! check_literal_conversion
+ end, PMs),
+ lists:foreach(fun ({P, M}) ->
+ receive
+ {'DOWN', M, process, P, R} ->
+ case R of
+ normal -> ok;
+ terminated -> ok
+ end
+ end
+ end, PMs),
ok.
+simultaneous_signals_basic(Config) when is_list(Config) ->
+ simultaneous_signals_test(false, false).
+
+simultaneous_signals_recv(Config) when is_list(Config) ->
+ simultaneous_signals_test(true, false).
+
+simultaneous_signals_exit(Config) when is_list(Config) ->
+ simultaneous_signals_test(false, true).
+
+simultaneous_signals_recv_exit(Config) when is_list(Config) ->
+ simultaneous_signals_test(true, true).
+
+simultaneous_signals_test(RecvPairs, Exit) ->
+ erlang:trace(new_processes, true, [running_procs]),
+ persistent_term:put({?MODULE, ?FUNCTION_NAME}, make_ref()),
+ Literal = persistent_term:get({?MODULE, ?FUNCTION_NAME}),
+ true = is_reference(Literal),
+ 0 = erts_debug:size_shared(Literal), %% Should be a literal...
+ SFact = test_server:timetrap_scale_factor(),
+ GoTime = erlang:monotonic_time(millisecond) + 1000*SFact,
+ ProcF = fun () ->
+ 0 = erts_debug:size_shared(Literal), %% Should be a literal...
+ Now = erlang:monotonic_time(millisecond),
+ Tmo = case GoTime - Now of
+ Left when Left < 0 ->
+ erlang:display({go_time_passed, Left}),
+ 0;
+ Left ->
+ Left
+ end,
+ receive after Tmo -> ok end,
+ on_heap = process_flag(message_queue_data, off_heap),
+ if RecvPairs -> receive_integer_pairs(0);
+ true -> ok
+ end,
+ receive check_literal_conversion -> ok end,
+ receive
+ Literal ->
+ %% Should not be a literal anymore...
+ false = (0 == erts_debug:size_shared(Literal))
+ end
+ end,
+ PMs = lists:map(fun (_) ->
+ spawn_opt(ProcF,
+ [link,
+ monitor,
+ {message_queue_data, on_heap}])
+ end, lists:seq(1, 100)),
+ lists:foreach(fun ({P,_M}) ->
+ lists:foreach(fun (N) when N rem 100 == 0 ->
+ P ! [N|N];
+ (N) ->
+ P ! N
+ end, lists:seq(1, 10000)),
+ P ! Literal
+ end, PMs),
+ Now = erlang:monotonic_time(millisecond),
+ Tmo = case GoTime - Now - 5 of % a bit earlier...
+ Left when Left < 0 ->
+ erlang:display({go_time_passed, Left}),
+ 0;
+ Left ->
+ Left
+ end,
+ receive after Tmo -> ok end,
+ persistent_term:erase({?MODULE, ?FUNCTION_NAME}),
+ receive after 10 -> ok end,
+ if Exit ->
+ _ = lists:foldl(fun ({P, _M}, N) when N rem 10 ->
+ unlink(P),
+ exit(P, terminated),
+ N+1;
+ (_PM, N) ->
+ N+1
+ end,
+ 0,
+ PMs),
+ ok;
+ true ->
+ ok
+ end,
+ wait_traced_not_running(1000 + 200*SFact),
+ erlang:trace(new_processes, false, [running_procs]),
+ literal_area_collector_test:check_idle(),
+ lists:foreach(fun ({P,_M}) ->
+ P ! check_literal_conversion
+ end, PMs),
+ lists:foreach(fun ({P, M}) ->
+ receive
+ {'DOWN', M, process, P, R} ->
+ case R of
+ normal -> ok;
+ terminated -> ok
+ end
+ end
+ end, PMs),
+ ok.
+
+
+wait_traced_not_running(Tmo) ->
+ receive
+ {trace,_,What,_} when What == in;
+ What == out ->
+ wait_traced_not_running(Tmo)
+ after
+ Tmo ->
+ ok
+ end.
+
+receive_integer_pairs(Tmo) ->
+ receive
+ [N|N] ->
+ receive_integer_pairs(Tmo)
+ after
+ Tmo ->
+ ok
+ end.
+
%%
%% -- Internal utils --------------------------------------------------------
%%
+match(X,X) -> ok.
+
load_driver(Config, Driver) ->
DataDir = proplists:get_value(data_dir, Config),
case erl_ddll:load_driver(DataDir, Driver) of
@@ -552,20 +1253,15 @@ spam(To, Data) ->
repeat(_Fun, N) when is_integer(N), N =< 0 ->
ok;
-repeat(Fun, N) when is_integer(N) ->
+repeat(Fun, N) when is_function(Fun, 0), is_integer(N) ->
Fun(),
+ repeat(Fun, N-1);
+repeat(Fun, N) when is_function(Fun, 1), is_integer(N) ->
+ Fun(N),
repeat(Fun, N-1).
-start_node(Config, Args) ->
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ " " ++ Args}]).
-
-start_node(Config) ->
- start_node(Config, "").
-
-stop_node(Node) ->
- test_server:stop_node(Node).
+busy_wait_until(Fun) ->
+ case catch Fun() of
+ true -> ok;
+ _ -> busy_wait_until(Fun)
+ end.
diff --git a/erts/emulator/test/small_SUITE.erl b/erts/emulator/test/small_SUITE.erl
index cbd40042b9..10dd36a2cf 100644
--- a/erts/emulator/test/small_SUITE.erl
+++ b/erts/emulator/test/small_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,8 +19,14 @@
%%
-module(small_SUITE).
--export([all/0, suite/0]).
--export([edge_cases/1]).
+-include_lib("syntax_tools/include/merl.hrl").
+
+-export([all/0, suite/0, groups/0]).
+-export([edge_cases/1,
+ addition/1, subtraction/1, multiplication/1, division/1,
+ test_bitwise/1, test_bsl/1,
+ element/1,
+ range_optimization/1]).
-include_lib("common_test/include/ct.hrl").
@@ -29,7 +35,15 @@ suite() ->
{timetrap, {minutes, 1}}].
all() ->
- [edge_cases].
+ [{group, p}].
+
+groups() ->
+ [{p, [parallel],
+ [edge_cases,
+ addition, subtraction, multiplication, division,
+ test_bitwise, test_bsl,
+ element,
+ range_optimization]}].
edge_cases(Config) when is_list(Config) ->
{MinSmall, MaxSmall} = Limits = determine_small_limits(0),
@@ -111,6 +125,658 @@ arith_test_1(A, B, MinS, MaxS) ->
ok.
+%% Test that the JIT only omits the overflow check when it's safe.
+addition(_Config) ->
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+ Mod = list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME])),
+ Pairs = add_gen_pairs(),
+ %% io:format("~p\n", [Pairs]),
+ Fs0 = gen_func_names(Pairs, 0),
+ Fs = [gen_add_function(F) || F <- Fs0],
+ Tree = ?Q(["-module('@Mod@').",
+ "-compile([export_all,nowarn_export_all])."]) ++ Fs,
+ %% merl:print(Tree),
+ {ok,_Bin} = merl:compile_and_load(Tree, []),
+ test_addition(Fs0, Mod),
+ ok.
+
+add_gen_pairs() ->
+ {MinSmall, MaxSmall} = determine_small_limits(0),
+
+ %% Generate random pairs of smalls.
+ N = 1000,
+ M = MaxSmall + N div 2,
+ Pairs0 = [{M - rand:uniform(N), rand:uniform(N)} ||
+ _ <- lists:seq(1, 75)],
+
+ Seq = lists:seq(MinSmall-3, MinSmall+2) ++
+ lists:seq(-5, 5),
+ lists:seq(MaxSmall-2, MaxSmall+2),
+ [{N1, N2} || N1 <- Seq, N2 <- Seq] ++ Pairs0.
+
+gen_add_function({Name,{A,B}}) ->
+ APlusOne = abs(A) + 1,
+ BPlusOne = abs(B) + 1,
+ ?Q("'@Name@'(X0, Y0) when is_integer(X0), is_integer(Y0)->
+ X1 = X0 rem _@APlusOne@,
+ Y1 = Y0 rem _@BPlusOne@,
+ Res = X0 + Y0,
+ Res = X1 + Y1,
+ Res = Y1 + X1,
+ Res = X0 + Y1,
+ Res = X1 + Y0. ").
+
+test_addition([{Name,{A,B}}|T], Mod) ->
+ try
+ Res0 = A + B,
+ Res0 = Mod:Name(A, B),
+
+ Res1 = -A + B,
+ Res1 = Mod:Name(-A, B),
+
+ Res2 = A + (-B),
+ Res2 = Mod:Name(A, -B),
+
+ Res3 = -A + (-B),
+ Res3 = Mod:Name(-A, -B)
+ catch
+ C:R:Stk ->
+ io:format("~p failed. numbers: ~p ~p\n", [Name,A,B]),
+ erlang:raise(C, R, Stk)
+ end,
+
+ test_addition(T, Mod);
+test_addition([], _) ->
+ ok.
+
+%% Test that the JIT only omits the overflow check when it's safe.
+subtraction(_Config) ->
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+ Mod = list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME])),
+ Pairs = sub_gen_pairs(),
+ io:format("~p\n", [Pairs]),
+ Fs0 = gen_func_names(Pairs, 0),
+ Fs = [gen_sub_function(F) || F <- Fs0],
+ Tree = ?Q(["-module('@Mod@').",
+ "-compile([export_all,nowarn_export_all])."]) ++ Fs,
+ %% merl:print(Tree),
+ {ok,_Bin} = merl:compile_and_load(Tree, []),
+ test_subtraction(Fs0, Mod),
+ ok.
+
+sub_gen_pairs() ->
+ {MinSmall, MaxSmall} = determine_small_limits(0),
+
+ %% Generate random pairs of smalls.
+ N = 1000,
+ M = MaxSmall + N div 2,
+ Pairs0 = [{M - rand:uniform(N), M - rand:uniform(N)} ||
+ _ <- lists:seq(1, 75)],
+
+ [{N1, N2} ||
+ N1 <- lists:seq(MinSmall-2, MinSmall+2),
+ N2 <- lists:seq(MaxSmall-2, MaxSmall+2)] ++ Pairs0.
+
+gen_sub_function({Name,{A,B}}) ->
+ APlusOne = abs(A) + 1,
+ BPlusOne = abs(B) + 1,
+ ?Q("'@Name@'(X0, Y0) when is_integer(X0), is_integer(Y0)->
+ X1 = X0 rem _@APlusOne@,
+ Y1 = Y0 rem _@BPlusOne@,
+ Res = X0 - Y0,
+ Res = X1 - Y1,
+ Res = X0 - Y1,
+ Res = X1 - Y0. ").
+
+test_subtraction([{Name,{A,B}}|T], Mod) ->
+ try
+ Res0 = A - B,
+ Res0 = Mod:Name(A, B),
+
+ Res1 = -A - B,
+ Res1 = Mod:Name(-A, B),
+
+ Res2 = A - (-B),
+ Res2 = Mod:Name(A, -B),
+
+ Res3 = -A - (-B),
+ Res3 = Mod:Name(-A, -B)
+ catch
+ C:R:Stk ->
+ io:format("~p failed. numbers: ~p ~p\n", [Name,A,B]),
+ erlang:raise(C, R, Stk)
+ end,
+
+ test_subtraction(T, Mod);
+test_subtraction([], _) ->
+ ok.
+
+%% Test that the JIT only omits the overflow check when it's safe.
+multiplication(_Config) ->
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+ Mod = list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME])),
+ Pairs = mul_gen_pairs(),
+ Fs0 = gen_func_names(Pairs, 0),
+ Fs = [gen_mul_function(F) || F <- Fs0],
+ Tree = ?Q(["-module('@Mod@').",
+ "-compile([export_all,nowarn_export_all])."]) ++ Fs,
+ %% merl:print(Tree),
+ {ok,_Bin} = merl:compile_and_load(Tree, []),
+ test_multiplication(Fs0, Mod),
+ ok.
+
+mul_gen_pairs() ->
+ {_, MaxSmall} = determine_small_limits(0),
+ NumBitsMaxSmall = num_bits(MaxSmall),
+
+ %% Generate random pairs of smalls.
+ Pairs0 = [{rand:uniform(MaxSmall),rand:uniform(MaxSmall)} ||
+ _ <- lists:seq(1, 75)],
+
+ %% Generate pairs of numbers whose product is small.
+ Pairs1 = [{N, MaxSmall div N} || N <- [1,2,3,5,17,63,64,1111,22222]] ++ Pairs0,
+
+ %% Add prime factors of 2^59 - 1 (MAX_SMALL for 64-bit architecture
+ %% at the time of writing).
+ Pairs2 = [{179951,3203431780337}|Pairs1],
+
+ %% Generate pairs of numbers whose product are bignums.
+ LeastBig = MaxSmall + 1,
+ Divisors = [(1 bsl Pow) + Offset ||
+ Pow <- lists:seq(NumBitsMaxSmall - 4, NumBitsMaxSmall - 1),
+ Offset <- [0,1,17,20333]],
+ [{Div,ceil(LeastBig / Div)} || Div <- Divisors] ++ Pairs2.
+
+gen_mul_function({Name,{A,B}}) ->
+ APlusOne = A + 1,
+ BPlusOne = B + 1,
+ NumBitsA = num_bits(A),
+ NumBitsB = num_bits(B),
+ ?Q("'@Name@'(X0, Y0, More) when is_integer(X0), is_integer(Y0)->
+ X1 = X0 rem _@APlusOne@,
+ Y1 = Y0 rem _@BPlusOne@,
+ Res = X0 * Y0,
+ Res = X1 * Y1,
+ Res = Y1 * X1,
+ if More ->
+ Res = X1 * _@B@,
+ Res = _@A@ * Y1,
+ <<X2:_@NumBitsA@>> = <<X0:_@NumBitsA@>>,
+ <<Y2:_@NumBitsB@>> = <<Y0:_@NumBitsB@>>,
+ Res = X2 * Y2,
+ Res = X1 * Y2,
+ Res = X2 * Y1;
+ true ->
+ Res
+ end. ").
+
+test_multiplication([{Name,{A,B}}|T], Mod) ->
+ try
+ Res0 = A * B,
+ %% io:format("~p * ~p = ~p; size = ~p\n",
+ %% [A,B,Res0,erts_debug:flat_size(Res0)]),
+
+ Res0 = Mod:Name(A, B, true),
+ Res0 = Mod:Name(-A, -B, false),
+
+ Res1 = -(A * B),
+ Res1 = Mod:Name(-A, B, false),
+ Res1 = Mod:Name(A, -B, false)
+ catch
+ C:R:Stk ->
+ io:format("~p failed. numbers: ~p ~p\n", [Name,A,B]),
+ erlang:raise(C, R, Stk)
+ end,
+
+ test_multiplication(T, Mod);
+test_multiplication([], _) ->
+ ok.
+
+%% Test that the JIT only omits the overflow check when it's safe.
+division(_Config) ->
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+ Mod = list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME])),
+ Pairs = div_gen_pairs(),
+ Fs0 = gen_func_names(Pairs, 0),
+ Fs = [gen_div_function(F) || F <- Fs0],
+ Tree = ?Q(["-module('@Mod@').",
+ "-compile([export_all,nowarn_export_all])."]) ++ Fs,
+ %% merl:print(Tree),
+ {ok,_Bin} = merl:compile_and_load(Tree, []),
+ test_division(Fs0, Mod),
+
+ 3 = ignore_rem(ignore, 10, 3),
+ 1 = ignore_div(ignore, 16, 5),
+
+ ok.
+
+ignore_rem(_, X, Y) ->
+ _ = X rem Y, %Result in x0.
+ X div Y. %Reuse x0 for result.
+
+ignore_div(_, X, Y) ->
+ _ = X div Y, %Result in x0.
+ X rem Y. %Reuse x0 for result.
+
+div_gen_pairs() ->
+ {_, MaxSmall} = determine_small_limits(0),
+ NumBitsMaxSmall = num_bits(MaxSmall),
+
+ %% Generate random pairs of smalls.
+ Pairs0 = [{rand:uniform(MaxSmall),rand:uniform(MaxSmall)} ||
+ _ <- lists:seq(1, 75)],
+
+ Pairs1 = [{rand:uniform(MaxSmall), N} ||
+ N <- [-3,-2,-1,1,2,3,5,17,63,64,1111,22222]] ++ Pairs0,
+
+ %% Generate pairs of numbers whose product are bignums.
+ [{rand:uniform(MaxSmall),1 bsl Pow} ||
+ Pow <- lists:seq(NumBitsMaxSmall - 4, NumBitsMaxSmall - 1)] ++ Pairs1.
+
+
+gen_div_function({Name,{A,B}}) ->
+ APlusOne = abs(A) + 1,
+ BPlusOne = abs(B) + 1,
+ NumBitsA = num_bits(abs(A)+1),
+ NumBitsB = num_bits(abs(B)+1),
+ ?Q("'@Name@'(integer0, X0, Y0) ->
+ Q = X0 div Y0,
+ R = X0 rem Y0,
+ if X0 > 0, Y0 > 0 ->
+ <<X:_@NumBitsA@>> = <<X0:_@NumBitsA@>>,
+ <<Y:_@NumBitsB@>> = <<Y0:_@NumBitsB@>>,
+ Q = X div Y,
+ R = X rem Y,
+ {Q, R};
+ true ->
+ {Q, R}
+ end;
+ '@Name@'(integer1, X, fixed) when is_integer(X), -_@APlusOne@ < X, X < _@APlusOne@ ->
+ Y = _@B@,
+ Q = X div Y,
+ R = X rem Y,
+ {Q, R};
+ '@Name@'(integer2, X, fixed) when is_integer(X), -_@APlusOne@ < X, X < _@APlusOne@ ->
+ Y = _@B@,
+ R = X rem Y,
+ Q = X div Y,
+ {Q, R};
+ '@Name@'(number0, X, Y) when -_@APlusOne@ < X, X < _@APlusOne@,
+ -_@BPlusOne@ < Y, Y < _@BPlusOne@ ->
+ Q = X div Y,
+ R = X rem Y,
+ {Q, R};
+ '@Name@'(number1, X, Y) when -_@APlusOne@ < X, X < _@APlusOne@,
+ -_@BPlusOne@ < Y, Y < _@BPlusOne@ ->
+ R = X rem Y,
+ Q = X div Y,
+ {Q, R}. ").
+
+test_division([{Name,{A,B}}|T], Mod) ->
+ F = fun Mod:Name/3,
+ try
+ Res0 = {A div B, A rem B},
+ Res0 = F(integer0, A, B),
+ Res0 = F(integer1, A, fixed),
+ Res0 = F(integer2, A, fixed),
+ Res0 = F(number0, A, B),
+ Res0 = F(number1, A, B)
+ catch
+ C:R:Stk ->
+ io:format("~p failed. numbers: ~p ~p\n", [Name,A,B]),
+ erlang:raise(C, R, Stk)
+ end,
+
+ test_division(T, Mod);
+test_division([], _) ->
+ ok.
+
+%% Test that the JIT only omits the overflow check when it's safe.
+test_bitwise(_Config) ->
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+ Mod = list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME])),
+ Pairs = bitwise_gen_pairs(),
+ %% io:format("~p\n", [Pairs]),
+ Fs0 = gen_func_names(Pairs, 0),
+ Fs = [gen_bitwise_function(F) || F <- Fs0],
+ Tree = ?Q(["-module('@Mod@').",
+ "-compile([export_all,nowarn_export_all])."]) ++ Fs,
+ merl:print(Tree),
+ {ok,_Bin} = merl:compile_and_load(Tree, []),
+ test_bitwise(Fs0, Mod),
+
+ %% Test invalid operands.
+ expect_badarith(fun(X) -> 42 band X end),
+ expect_badarith(fun(X) -> 42 bor X end),
+ expect_badarith(fun(X) -> 42 bxor X end),
+ expect_badarith(fun(X) -> X band 42 end),
+ expect_badarith(fun(X) -> X bor 42 end),
+ expect_badarith(fun(X) -> X bxor 42 end),
+ expect_fc(fun(X) when is_integer(42 band X) -> ok end),
+ expect_fc(fun(X) when is_integer(42 bor X) -> ok end),
+ expect_fc(fun(X) when is_integer(42 bxor X) -> ok end),
+ expect_fc(fun(X) when is_integer(X band 42) -> ok end),
+ expect_fc(fun(X) when is_integer(X bor 42) -> ok end),
+ expect_fc(fun(X) when is_integer(X bxor 42) -> ok end),
+
+ ok.
+
+expect_fc(Fun) ->
+ {'EXIT',{function_clause,_}} = catch Fun(id(bad)),
+ ok.
+
+expect_badarith(Fun) ->
+ {'EXIT',{badarith,_}} = catch Fun(id(bad)),
+ ok.
+
+bitwise_gen_pairs() ->
+ {MinSmall, MaxSmall} = determine_small_limits(0),
+
+ %% Generate random pairs of smalls.
+ N = 1000,
+ M = MaxSmall + N div 2,
+ Pairs0 = [{M - rand:uniform(N), rand:uniform(N)} ||
+ _ <- lists:seq(1, 75)],
+
+ Seq = lists:seq(MinSmall-3, MinSmall+2) ++
+ lists:seq(-5, 5),
+ lists:seq(MaxSmall-2, MaxSmall+2),
+ [{N1, N2} || N1 <- Seq, N2 <- Seq] ++ Pairs0.
+
+gen_bitwise_function({Name,{A,B}}) ->
+ APlusOne = abs(A) + 1,
+ BPlusOne = abs(B) + 1,
+ ?Q("'@Name@'(X0, Y0) when is_integer(X0), is_integer(Y0)->
+ X1 = X0 rem _@APlusOne@,
+ Y1 = Y0 rem _@BPlusOne@,
+
+ AndRes = X0 band Y0,
+ AndRes = X1 band Y1,
+ AndRes = Y1 band X1,
+ AndRes = X0 band Y1,
+ AndRes = X1 band Y0,
+
+ OrRes = X0 bor Y0,
+ OrRes = X1 bor Y1,
+ OrRes = Y1 bor X1,
+ OrRes = X0 bor Y1,
+ OrRes = X1 bor Y0,
+
+ XorRes = X0 bxor Y0,
+ XorRes = X1 bxor Y1,
+ XorRes = Y1 bxor X1,
+ XorRes = X0 bxor Y1,
+ XorRes = X1 bxor Y0,
+
+ {AndRes, OrRes, XorRes}. ").
+
+test_bitwise([{Name,{A,B}}|T], Mod) ->
+ try
+ test_bitwise_1(A, B, Mod, Name),
+ test_bitwise_1(-A, B, Mod, Name),
+ test_bitwise_1(A, -B, Mod, Name),
+ test_bitwise_1(-A, -B, Mod, Name)
+ catch
+ C:R:Stk ->
+ io:format("~p failed. numbers: ~p ~p\n", [Name,A,B]),
+ erlang:raise(C, R, Stk)
+ end,
+ test_bitwise(T, Mod);
+test_bitwise([], _) ->
+ ok.
+
+test_bitwise_1(A, B, Mod, Name) ->
+ AndRes = A band B,
+ OrRes = A bor B,
+ XorRes = A bxor B,
+ {AndRes, OrRes, XorRes} = Mod:Name(A, B),
+ ok.
+
+%% Test that the JIT only omits the overflow check when it's safe.
+test_bsl(_Config) ->
+ _ = rand:uniform(), %Seed generator
+ io:format("Seed: ~p", [rand:export_seed()]),
+ Mod = list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME])),
+ Pairs = bsl_gen_pairs(),
+ %% io:format("~p\n", [Pairs]),
+ Fs0 = gen_func_names(Pairs, 0),
+ Fs = [gen_bsl_function(F) || F <- Fs0],
+ Tree = ?Q(["-module('@Mod@').",
+ "-compile([export_all,nowarn_export_all])."]) ++ Fs,
+ %% merl:print(Tree),
+ {ok,_Bin} = merl:compile_and_load(Tree, []),
+ test_bsl(Fs0, Mod),
+ ok.
+
+bsl_gen_pairs() ->
+ {_MinSmall, MaxSmall} = determine_small_limits(0),
+ SmallBits = num_bits(MaxSmall),
+
+ [{N,S} ||
+ P <- lists:seq(20, SmallBits),
+ N <- [(1 bsl P)-rand:uniform(1000), (1 bsl P)-1, 1 bsl P],
+ S <- lists:seq(SmallBits-P-4, SmallBits - P + 3)].
+
+gen_bsl_function({Name,{N,S}}) ->
+ Mask = (1 bsl num_bits(N)) - 1,
+ ?Q("'@Name@'(N0) ->
+ N = N0 band _@Mask@,
+ N bsl _@S@. ").
+
+test_bsl([{Name,{N,S}}|T], Mod) ->
+ Res = N bsl S,
+ try Mod:Name(N) of
+ Res ->
+ ok
+ catch
+ C:R:Stk ->
+ io:format("~p failed. numbers: ~p ~p\n", [Name,N,S]),
+ erlang:raise(C, R, Stk)
+ end,
+ test_bsl(T, Mod);
+test_bsl([], _) ->
+ ok.
+
+element(_Config) ->
+ %% Test element_1: Can't fail for integer arguments.
+ zero = element_1(0),
+ one = element_1(1),
+ two = element_1(2),
+ three = element_1(3),
+
+ three = element_1(3-4),
+ two = element_1(2-4),
+ one = element_1(1-4),
+ zero = element_1(0-4),
+
+ zero = element_1(0+4),
+ one = element_1(1+4),
+
+ {'EXIT',{badarith,_}} = catch element_1(id(a)),
+
+ %% Test element_2: Test that it fails for 0.
+ one = element_2(1),
+ two = element_2(2),
+ three = element_2(3),
+
+ one = element_2(1+4),
+ two = element_2(2+4),
+ three = element_2(3+4),
+
+ {'EXIT',{badarg,[{erlang,element,[0,{one,two,three}],_}|_]}} =
+ catch element_2(id(0)),
+ {'EXIT',{badarith,_}} = catch element_2(id(b)),
+
+ %% Test element_3: Test that if fails for integers less than 1.
+ one = element_3(1),
+ two = element_3(2),
+ three = element_3(3),
+
+ one = element_3(1+4),
+ two = element_3(2+4),
+ three = element_3(3+4),
+
+ {'EXIT',{badarg,[{erlang,element,[0,{one,two,three}],_}|_]}} =
+ catch element_3(id(0)),
+ {'EXIT',{badarg,_}} = catch element_3(id(-1)),
+ {'EXIT',{badarg,_}} = catch element_3(id(-999)),
+ {'EXIT',{badarith,_}} = catch element_3(id(c)),
+
+ %% Test element_4: Test that it fails for integers outside of the range 1..3.
+ one = element_4(1),
+ two = element_4(2),
+ three = element_4(3),
+
+ one = element_4(1+8),
+ two = element_4(2+8),
+ three = element_4(3+8),
+
+ {'EXIT',{badarg,[{erlang,element,[0,{one,two,three}],_}|_]}} =
+ catch element_4(id(0)),
+ {'EXIT',{badarg,[{erlang,element,[5,{one,two,three}],_}|_]}} =
+ catch element_4(id(5)),
+ {'EXIT',{badarg,_}} = catch element_4(id(-1)),
+ {'EXIT',{badarg,[{erlang,element,[-7,{one,two,three}],_}|_]}} =
+ catch element_4(id(-999)),
+ {'EXIT',{badarith,_}} = catch element_4(id(d)),
+
+ %% Test element_5: Test that it fails for integers outside of the
+ %% range 0..3.
+ zero = element_5(0),
+ one = element_5(1),
+ two = element_5(2),
+ three = element_5(3),
+
+ zero = element_5(0+8),
+ one = element_5(1+8),
+ two = element_5(2+8),
+ three = element_5(3+8),
+
+ {'EXIT',{badarg,[{erlang,element,[5,{zero,one,two,three}],_}|_]}} =
+ catch element_5(id(4)),
+ {'EXIT',{badarg,[{erlang,element,[0,{zero,one,two,three}],_}|_]}} =
+ catch element_5(id(-1)),
+ {'EXIT',{badarith,_}} = catch element_5(id(e)),
+
+ %% element_6: Test that it fails for values outside of 0..3.
+ zero = element_6(0),
+ one = element_6(1),
+ two = element_6(2),
+ three = element_6(3),
+
+ {'EXIT',{badarg,[{erlang,element,[5,{zero,one,two,three}],_}|_]}} =
+ catch element_6(id(4)),
+ {'EXIT',{badarg,[{erlang,element,[0,{zero,one,two,three}],_}|_]}} =
+ catch element_6(id(-1)),
+
+ %% Test element_7: Test that it fails for values outside of 1..3.
+ one = element_7(1),
+ two = element_7(2),
+ three = element_7(3),
+
+ one = element_7(1+5),
+ two = element_7(2+5),
+ three = element_7(3+5),
+
+ {'EXIT',{badarg,[{erlang,element,[0,{one,two,three}],_}|_]}} =
+ catch element_7(id(0)),
+ {'EXIT',{badarg,[{erlang,element,[4,{one,two,three}],_}|_]}} =
+ catch element_7(id(4)),
+ {'EXIT',{badarith,_}} = catch element_7(id(f)),
+
+ %% element_8: Test that it works in a guard.
+ ok = element_8(id(1), id(a)),
+ error = element_8(id(1), id(b)),
+ error = element_8(id(-1), whatever),
+ error = element_8(id(0), whatever),
+ error = element_8(id(5), whatever),
+
+ ok.
+
+element_1(N0) ->
+ N = N0 band 3,
+ element(N + 1, {zero,one,two,three}).
+
+element_2(N0) ->
+ N = N0 band 3,
+ element(N, {one,two,three}).
+
+element_3(N0) ->
+ N = N0 rem 4,
+ element(N, {one,two,three}).
+
+element_4(N0) ->
+ N = N0 rem 8,
+ element(N, {one,two,three}).
+
+element_5(N0) ->
+ N = N0 rem 8,
+ element(N + 1, {zero,one,two,three}).
+
+element_6(N) when is_integer(N) ->
+ element(N + 1, {zero,one,two,three}).
+
+element_7(N0) ->
+ N = N0 rem 5,
+ %% Max N is one more than the size of the tuple.
+ element(N, {one,two,three}).
+
+element_8(N0, E) ->
+ N = N0 rem 8,
+ if
+ element(N, {a,b,c,d}) =:= E ->
+ ok;
+ true ->
+ error
+ end.
+
+%% Test basic range optimization of arguments.
+range_optimization(_Config) ->
+ immed_reg_confusion(),
+
+ ok.
+
+%% The JIT confused x15/y15 with smalls when checking whether an argument fell
+%% within the range of a small, because `is_small(arg.getValue())` happened to
+%% be true.
+immed_reg_confusion() ->
+ M = any_integer(1),
+ N = any_integer(1 bsl 128),
+ Res = any_integer(M bor N),
+
+ Res = bor_x0_x15(M, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, N),
+
+ ok.
+
+bor_x0_x15(_x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7, _x8, _x9,
+ _x10, _x11, _x12, _x13, _x14, _x15) ->
+ _x0 bor _x15.
+
+any_integer(I) ->
+ case id(I) of
+ N when is_integer(N) -> N
+ end.
+
+%%%
+%%% Helpers.
+%%%
+
+gen_func_names([E|Es], I) ->
+ Name = list_to_atom("f" ++ integer_to_list(I)),
+ [{Name,E}|gen_func_names(Es, I+1)];
+gen_func_names([], _) -> [].
+
+num_bits(Int) when Int >= 0 ->
+ num_bits(Int, 0).
+
+num_bits(0, N) -> N;
+num_bits(Int, N) -> num_bits(Int bsr 1, N + 1).
+
%% Verifies that N is a small when it should be
verify_kind(N, MinS, MaxS) ->
true = is_small(N) =:= (N >= MinS andalso N =< MaxS).
diff --git a/erts/emulator/test/smoke_test_SUITE.erl b/erts/emulator/test/smoke_test_SUITE.erl
index 5b46342127..b59390a854 100644
--- a/erts/emulator/test/smoke_test_SUITE.erl
+++ b/erts/emulator/test/smoke_test_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,71 +24,63 @@
%-compile(export_all).
-export([all/0, suite/0,
- init_per_testcase/2, end_per_testcase/2]).
+ init_per_testcase/2, end_per_testcase/2]).
-export([boot_combo/1, native_atomics/1, jump_table/1]).
suite() ->
- [{ct_hooks,[ts_install_cth]},
- {timetrap, {minutes, 2}}].
+ [{ct_hooks, [ts_install_cth]},
+ {timetrap, {minutes, 2}}].
-all() ->
+all() ->
[boot_combo, native_atomics, jump_table].
init_per_testcase(boot_combo = Case, Config) when is_list(Config) ->
case erlang:system_info(build_type) of
- opt ->
- init_per_tc(Case, Config);
- _ ->
- {skip,"Cannot test boot_combo in special builds since beam.* may not exist"}
+ opt ->
+ init_per_tc(Case, Config);
+ _ ->
+ {skip, "Cannot test boot_combo in special builds since beam.* may not exist"}
end;
init_per_testcase(Case, Config) when is_list(Config) ->
init_per_tc(Case, Config).
init_per_tc(Case, Config) ->
- [{testcase, Case}|Config].
+ [{testcase, Case} | Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
- ok.
+ erts_test_utils:ept_check_leaked_nodes(Config).
%%%
%%% 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,
- try
- chk_boot(Config, "+Ktrue", NOOP),
- chk_boot(Config, "+A42", A42),
- chk_boot(Config, "+Ktrue +A42", A42),
-
- WBTArgs = ["very_short", "short", "medium", "long", "very_long"],
- WTArgs = ["very_low", "low", "medium", "high", "very_high"],
- [chk_boot(Config,
- " +sbwt " ++ WBT ++
- " +sbwtdcpu " ++ WBT ++
- " +sbwtdio " ++ WBT ++
- " +swt " ++ WT ++
- " +swtdcpu " ++ WT ++
- " +swtdio " ++ WT, NOOP) || WBT <- WBTArgs, WT <- WTArgs],
-
- WSArgs = ["legacy", "default"],
- [chk_boot(Config, " +sws " ++ WS, NOOP) || WS <- WSArgs],
-
- %% A lot more combos could be implemented...
- ok
- after
- os:putenv("ERL_ZFLAGS", ZFlags)
- end.
+ NOOP = fun() -> ok end,
+ A42 = fun() ->
+ case erlang:system_info(threads) of
+ true ->
+ 42 = erlang:system_info(thread_pool_size);
+ false ->
+ ok
+ end
+ end,
+
+ chk_boot(["+Ktrue"], NOOP),
+ chk_boot(["+A42"], A42),
+ chk_boot(["+Ktrue", "+A42"], A42),
+
+ WBTArgs = ["very_short", "short", "medium", "long", "very_long"],
+ WTArgs = ["very_low", "low", "medium", "high", "very_high"],
+ [chk_boot(["+sbwt", WBT,
+ "+sbwtdcpu", WBT,
+ "+sbwtdio", WBT,
+ "+swt", WT,
+ "+swtdcpu", WT,
+ "+swtdio", WT], NOOP) || WBT <- WBTArgs, WT <- WTArgs],
+
+ WSArgs = ["legacy", "default"],
+ [chk_boot(["+sws", WS], NOOP) || WS <- WSArgs].
native_atomics(Config) when is_list(Config) ->
NA32Key = "32-bit native atomics",
@@ -96,70 +88,55 @@ native_atomics(Config) when is_list(Config) ->
DWNAKey = "Double word native atomics",
EthreadInfo = erlang:system_info(ethread_info),
io:format("~p~n", [EthreadInfo]),
- {value,{NA32Key, NA32, _}} = lists:keysearch(NA32Key, 1, EthreadInfo),
- {value,{NA64Key, NA64, _}} = lists:keysearch(NA64Key, 1, EthreadInfo),
- {value,{DWNAKey, DWNA, _}} = lists:keysearch(DWNAKey, 1, EthreadInfo),
+ {value, {NA32Key, NA32, _}} = lists:keysearch(NA32Key, 1, EthreadInfo),
+ {value, {NA64Key, NA64, _}} = lists:keysearch(NA64Key, 1, EthreadInfo),
+ {value, {DWNAKey, DWNA, _}} = lists:keysearch(DWNAKey, 1, EthreadInfo),
case {erlang:system_info(build_type), NA32, NA64, DWNA} of
- {opt, "no", "no", _} ->
- ct:fail(optimized_smp_runtime_without_native_atomics);
- _ ->
- {comment,
- NA32 ++ " 32-bit, "
- ++ NA64 ++ " 64-bit, and "
- ++ DWNA ++ " double word native atomics"}
+ {opt, "no", "no", _} ->
+ ct:fail(optimized_smp_runtime_without_native_atomics);
+ _ ->
+ {comment,
+ NA32 ++ " 32-bit, "
+ ++ NA64 ++ " 64-bit, and "
+ ++ DWNA ++ " double word native atomics"}
end.
jump_table(Config) when is_list(Config) ->
case erlang:system_info(beam_jump_table) of
- true ->
- ok;
- false ->
- case erlang:system_info(build_type) of
- opt ->
- ct:fail(optimized_without_beam_jump_table);
- BT ->
- {comment, "No beam jump table, but build type is " ++ atom_to_list(BT)}
- end
+ true ->
+ ok;
+ false ->
+ case erlang:system_info(build_type) of
+ opt ->
+ ct:fail(optimized_without_beam_jump_table);
+ BT ->
+ {comment, "No beam jump table, but build type is " ++ atom_to_list(BT)}
+ end
end.
-
+
%%%
%%% Aux functions --------------------------------------------------------------
%%%
-chk_boot(Config, Args, Fun) ->
- true = os:putenv("ERL_ZFLAGS", Args),
+chk_boot(Args, Fun) ->
Success = make_ref(),
Parent = self(),
- io:format("--- Testing ~s~n", [Args]),
- {ok, Node} = start_node(Config),
- Pid = spawn_link(Node, fun () ->
- Fun(),
- Parent ! {self(), Success}
- end),
+ io:format("--- Testing ~s~n", [lists:join(" ", Args)]),
+ {ok, Peer, Node} = ?CT_PEER(Args),
+ %% if spawn_link is used, race condition happens when
+ %% remote process exits with 'noconnection' reason and fails
+ %% the test case
+ Pid = spawn(Node, fun() ->
+ Fun(),
+ Parent ! {self(), Success}
+ end),
receive
- {Pid, Success} ->
- Node = node(Pid),
- stop_node(Node),
- io:format("--- Success!~n", []),
- ok
+ {Pid, Success} ->
+ Node = node(Pid),
+ peer:stop(Peer),
+ io:format("--- Success!~n", []),
+ ok
end.
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- Opts = [{args, "-pa "++Pa++" "++Args}],
- test_server:start_node(Name, slave, Opts).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index 7c547fde7a..76efe053f5 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,8 +62,8 @@ init_per_testcase(_, Config) ->
end_per_testcase(procs_bug, Config) ->
procs_bug(end_per_testcase, Config);
-end_per_testcase(_, _) ->
- ok.
+end_per_testcase(_, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
%%%
%%% The test cases -------------------------------------------------------------
@@ -502,16 +502,6 @@ mapn(_Fun, 0) ->
mapn(Fun, N) ->
[Fun(N) | mapn(Fun, N-1)].
-
-get_node_name(Config) ->
- list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))).
-
ets_count(Config) when is_list(Config) ->
[ets_count_do([Type | Named])
|| Type <- [set, bag, duplicate_bag, ordered_set],
@@ -530,77 +520,33 @@ ets_count_do(Opts) ->
%% Verify system_info(ets_limit) reflects max ETS table settings.
ets_limit(Config0) when is_list(Config0) ->
- Config = [{testcase,ets_limit}|Config0],
- true = is_integer(get_ets_limit(Config)),
- 12345 = get_ets_limit(Config, 12345),
+ true = is_integer(get_ets_limit(0)),
+ 12345 = get_ets_limit(12345),
ok.
-get_ets_limit(Config) ->
- get_ets_limit(Config, 0).
-get_ets_limit(Config, EtsMax) ->
+get_ets_limit(EtsMax) ->
Envs = case EtsMax of
0 -> [];
- _ -> [{"ERL_MAX_ETS_TABLES", integer_to_list(EtsMax)}]
+ _ -> ["-env", "ERL_MAX_ETS_TABLES", integer_to_list(EtsMax)]
end,
- {ok, Node} = start_node_ets(Config, Envs),
- Me = self(),
- Ref = make_ref(),
- spawn_link(Node,
- fun() ->
- Res = erlang:system_info(ets_limit),
- unlink(Me),
- Me ! {Ref, Res}
- end),
- receive
- {Ref, Res} ->
- Res
- end,
- stop_node(Node),
+ {ok, Peer, Node} = ?CT_PEER(Envs),
+ Res = rpc:call(Node, erlang, system_info, [ets_limit]),
+ peer:stop(Peer),
Res.
-start_node_ets(Config, Envs) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(get_node_name(Config), peer,
- [{args, "-pa "++Pa}, {env, Envs}]).
-
-start_node_atm(Config, AtomsMax) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(get_node_name(Config), peer,
- [{args, "-pa "++ Pa ++ AtomsMax}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
%% Verify system_info(atom_limit) reflects max atoms settings
%% (using " +t").
atom_limit(Config0) when is_list(Config0) ->
- Config = [{testcase,atom_limit}|Config0],
- 2186042 = get_atom_limit(Config, " +t 2186042 "),
- ok.
-
-get_atom_limit(Config, AtomsMax) ->
- {ok, Node} = start_node_atm(Config, AtomsMax),
- Me = self(),
- Ref = make_ref(),
- spawn_link(Node,
- fun() ->
- Res = erlang:system_info(atom_limit),
- unlink(Me),
- Me ! {Ref, Res}
- end),
- receive
- {Ref, Res} ->
- Res
- end,
- stop_node(Node),
- Res.
+ {ok, Peer, Node} = ?CT_PEER(["+t", "2186042"]),
+ 2186042 = rpc:call(Node, erlang, system_info, [atom_limit]),
+ peer:stop(Peer).
%% Verify that system_info(atom_count) works.
atom_count(Config) when is_list(Config) ->
Limit = erlang:system_info(atom_limit),
Count1 = erlang:system_info(atom_count),
- list_to_atom(integer_to_list(erlang:unique_integer())),
+ _ = list_to_atom(integer_to_list(erlang:unique_integer())),
Count2 = erlang:system_info(atom_count),
true = Limit >= Count2,
true = Count2 > Count1,
diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl
index e01efac86b..ce3e796da5 100644
--- a/erts/emulator/test/time_SUITE.erl
+++ b/erts/emulator/test/time_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,8 @@
monotonic_time_monotonicity_parallel/1,
time_unit_conversion/1,
signed_time_unit_conversion/1,
- erlang_timestamp/1]).
+ erlang_timestamp/1,
+ native_time_unit_gh6165/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -69,8 +70,8 @@
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
[{testcase, Func}|Config].
-end_per_testcase(_Func, _Config) ->
- ok.
+end_per_testcase(_Func, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -85,7 +86,8 @@ all() ->
monotonic_time_monotonicity_parallel,
time_unit_conversion,
signed_time_unit_conversion,
- erlang_timestamp].
+ erlang_timestamp,
+ native_time_unit_gh6165].
groups() ->
[{now, [], [now_unique, now_update]}].
@@ -108,9 +110,7 @@ local_to_univ_utc(Config) when is_list(Config) ->
case os:type() of
{unix,_} ->
%% TZ variable has a meaning
- {ok, Node} =
- test_server:start_node(local_univ_utc,peer,
- [{args, "-env TZ UTC"}]),
+ {ok, Peer, Node} = ?CT_PEER(["-env", "TZ", "UTC"]),
{{2008,8,1},{0,0,0}} =
rpc:call(Node,
erlang,localtime_to_universaltime,
@@ -125,17 +125,33 @@ local_to_univ_utc(Config) when is_list(Config) ->
rpc:call(Node,
calendar,local_time_to_universal_time_dst,
[{{2008, 8, 1}, {0, 0, 0}}]),
- test_server:stop_node(Node),
- ok;
+ peer:stop(Peer);
_ ->
{skip,"Only valid on Unix"}
end.
%% Tests conversion from universal to local time.
+%% These cases are currently implemented only for MET and fail in
+%% all other timezones
+is_stockholm_time() ->
+ case os:type() of
+ {win32, _} -> case os:cmd("tzutil /g") of
+ "W. Europe Standard Time"++_ -> true;
+ _ -> false
+ end;
+ {unix, _} -> case os:cmd("date '+%Z'") of
+ "ME"++_ -> true; %% covers MET/MEST
+ "CE"++_ -> true; %% covers CET/CEST
+ _ -> false
+ end
+ end.
univ_to_local(Config) when is_list(Config) ->
- test_univ_to_local(test_data()).
+ case is_stockholm_time() of
+ true -> test_univ_to_local(test_data());
+ false -> {skip, "This test is only valid for Stockholm timezone"}
+ end.
test_univ_to_local([{Utc, Local}|Rest]) ->
io:format("Testing ~p => ~p~n", [Local, Utc]),
@@ -147,7 +163,10 @@ test_univ_to_local([]) ->
%% Tests conversion from local to universal time.
local_to_univ(Config) when is_list(Config) ->
- test_local_to_univ(test_data()).
+ case is_stockholm_time() of
+ true -> test_local_to_univ(test_data());
+ false -> {skip, "This test is only valid for Stockholm timezone"}
+ end.
test_local_to_univ([{Utc, Local}|Rest]) ->
io:format("Testing ~p => ~p~n", [Utc, Local]),
@@ -241,7 +260,7 @@ compare_local_and_universal(Times) when Times > 0 ->
Diff when abs(Diff) < AcceptableDiff ->
ok;
Diff ->
- io:format("More than ~p seconds difference betwen "
+ io:format("More than ~p seconds difference between "
"local and universal time", [Diff]),
ct:fail(huge_diff)
end.
@@ -431,41 +450,39 @@ now_update1(0) ->
time_warp_modes(Config) when is_list(Config) ->
%% All time warp modes always supported in
%% combination with no time correction...
- check_time_warp_mode(Config, false, no_time_warp),
- check_time_warp_mode(Config, false, single_time_warp),
- check_time_warp_mode(Config, false, multi_time_warp),
+ check_time_warp_mode(false, no_time_warp),
+ check_time_warp_mode(false, single_time_warp),
+ check_time_warp_mode(false, multi_time_warp),
erts_debug:set_internal_state(available_internal_state, true),
try
case erts_debug:get_internal_state({check_time_config,
true, no_time_warp}) of
false -> ok;
- true -> check_time_warp_mode(Config, true, no_time_warp)
+ true -> check_time_warp_mode(true, no_time_warp)
end,
case erts_debug:get_internal_state({check_time_config,
true, single_time_warp}) of
false -> ok;
- true -> check_time_warp_mode(Config, true, single_time_warp)
+ true -> check_time_warp_mode(true, single_time_warp)
end,
case erts_debug:get_internal_state({check_time_config,
true, multi_time_warp}) of
false -> ok;
- true -> check_time_warp_mode(Config, true, multi_time_warp)
+ true -> check_time_warp_mode(true, multi_time_warp)
end
after
erts_debug:set_internal_state(available_internal_state, false)
end.
-check_time_warp_mode(Config, TimeCorrection, TimeWarpMode) ->
+check_time_warp_mode(TimeCorrection, TimeWarpMode) ->
io:format("~n~n~n***** Testing TimeCorrection=~p TimeWarpMode=~p *****~n",
[TimeCorrection, TimeWarpMode]),
Mon = erlang:monitor(time_offset, clock_service),
_ = erlang:time_offset(),
Start = erlang:monotonic_time(1000),
MonotonicityTimeout = 2000,
- {ok, Node} = start_node(Config,
- "+c " ++ atom_to_list(TimeCorrection)
- ++ " +C " ++ atom_to_list(TimeWarpMode)),
+ {ok, Peer, Node} = ?CT_PEER(["+c", atom_to_list(TimeCorrection), "+C", atom_to_list(TimeWarpMode)]),
StartTime = rpc:call(Node, erlang, system_info, [start_time]),
Me = self(),
MonotincityTestStarted = make_ref(),
@@ -494,7 +511,7 @@ check_time_warp_mode(Config, TimeCorrection, TimeWarpMode) ->
millisecond),
io:format("UpMilliSeconds=~p~n", [UpMilliSeconds]),
End = erlang:monotonic_time(millisecond),
- stop_node(Node),
+ peer:stop(Peer),
try
true = (UpMilliSeconds > (98*MonotonicityTimeout) div 100),
true = (UpMilliSeconds < (102*(End-Start)) div 100)
@@ -857,6 +874,41 @@ process_changed_time_offset(Mon, TO, Changed, Wait) ->
end.
+native_time_unit_gh6165(Config) when is_list(Config) ->
+ %% This test could potentially fail even when no bug exists if
+ %% run during heavy load, or if OS system time or Erlang system time
+ %% is changed at an unfortunate time, but it is hard to make the test
+ %% more stable than this without losing actual testing...
+
+ ChkDiff = fun (Val) ->
+ case erlang:convert_time_unit(Val, native, nanosecond) of
+ Ns when -1000000 < Ns andalso Ns < 1000000 ->
+ erlang:display({diff, Ns}),
+ ok;
+ Ns ->
+ erlang:display({large_diff, Ns}),
+ ct:fail({large_diff, Ns})
+ end
+ end,
+
+ process_flag(priority, max),
+
+ erlang:yield(),
+ V1 = erlang:monotonic_time(native) - erlang:monotonic_time(),
+ ChkDiff(V1),
+
+ erlang:yield(),
+ V2 = erlang:system_time(native) - erlang:system_time(),
+ ChkDiff(V2),
+
+ erlang:yield(),
+ V3 = os:system_time(native) - os:system_time(),
+ ChkDiff(V3),
+
+ erlang:yield(),
+ 0 = erlang:time_offset() - erlang:time_offset(native),
+
+ ok.
%% Returns the test data: a list of {Utc, Local} tuples.
@@ -867,6 +919,12 @@ test_data() ->
case os:cmd("date '+%Z'") of
"SAST"++_ ->
{2,2};
+ "PDT"++_ ->
+ {-8,-7};
+ "PST"++_ ->
+ {-8,-7};
+ "UTC"++_ ->
+ {0,0};
_ ->
{?timezone,?dst_timezone}
end;
@@ -992,22 +1050,3 @@ bad_dates() ->
{{1996, 4, 30}, {12, 0, -1}}, % Sec
{{1996, 4, 30}, {12, 0, 60}}].
-
-start_node(Config, Args) ->
- TestCase = proplists:get_value(testcase, Config),
- PA = filename:dirname(code:which(?MODULE)),
- ESTime = erlang:monotonic_time(1) + erlang:time_offset(1),
- Unique = erlang:unique_integer([positive]),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(TestCase)
- ++ "-"
- ++ integer_to_list(ESTime)
- ++ "-"
- ++ integer_to_list(Unique)),
- test_server:start_node(Name,
- slave,
- [{args, "-pa " ++ PA ++ " " ++ Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl
index c02d2c767f..5866553b3c 100644
--- a/erts/emulator/test/timer_bif_SUITE.erl
+++ b/erts/emulator/test/timer_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,8 +47,8 @@ init_per_testcase(_Case, Config) ->
end,
Config.
-end_per_testcase(_Case, _Config) ->
- ok.
+end_per_testcase(_Case, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
init_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
@@ -228,13 +228,10 @@ start_timer_e(Config) when is_list(Config) ->
{'EXIT', _} = (catch erlang:start_timer(4.5, self(), hej)),
{'EXIT', _} = (catch erlang:start_timer(a, self(), hej)),
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
Pid = spawn(Node, timer, sleep, [10000]),
{'EXIT', _} = (catch erlang:start_timer(1000, Pid, hej)),
- stop_slave(Node),
-
-
- ok.
+ peer:stop(Peer).
%% Error cases for send_after/3
send_after_e(Config) when is_list(Config) ->
@@ -245,11 +242,10 @@ send_after_e(Config) when is_list(Config) ->
{'EXIT', _} = (catch erlang:send_after(4.5, self(), hej)),
{'EXIT', _} = (catch erlang:send_after(a, self(), hej)),
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
Pid = spawn(Node, timer, sleep, [10000]),
{'EXIT', _} = (catch erlang:send_after(1000, Pid, hej)),
- stop_slave(Node),
- ok.
+ peer:stop(Peer).
%% Error cases for cancel_timer/1
cancel_timer_e(Config) when is_list(Config) ->
@@ -384,7 +380,7 @@ evil_timers(Config) when is_list(Config) ->
%% in memory
Self = self(),
R1 = make_ref(),
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
spawn_link(Node,
fun () ->
Self ! {R1,
@@ -396,7 +392,7 @@ evil_timers(Config) when is_list(Config) ->
fun (A, B) -> A + B end]]}
end),
ExtList = receive {R1, L} -> L end,
- stop_slave(Node),
+ peer:stop(Peer),
BinList = [<<"bla">>,
<<"blipp">>,
<<"blupp">>,
@@ -813,17 +809,6 @@ get_msg() ->
empty
end.
-start_slave() ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = atom_to_list(?MODULE)
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive])),
- {ok, Node} = test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]),
- Node.
-
-stop_slave(Node) ->
- test_server:stop_node(Node).
-
collect(Last) ->
collect(Last, []).
diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl
index d25e8b6634..37f47cff30 100644
--- a/erts/emulator/test/trace_SUITE.erl
+++ b/erts/emulator/test/trace_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,7 +73,8 @@ end_per_testcase(_Case, Config) ->
Receiver = proplists:get_value(receiver, Config),
unlink(Receiver),
exit(Receiver, die),
- ok.
+
+ erts_test_utils:ept_check_leaked_nodes(Config).
%% No longer testing anything, just reporting whether cpu_timestamp
%% is enabled or not.
@@ -130,8 +131,7 @@ receive_trace(Config) when is_list(Config) ->
{true, true}]),
%% Remote messages
- OtherName = atom_to_list(?MODULE)++"_receive_trace",
- {ok, OtherNode} = start_node(OtherName),
+ {ok, Peer, OtherNode} = ?CT_PEER(),
RemoteProc = spawn_link(OtherNode, ?MODULE, process, [self()]),
io:format("RemoteProc = ~p ~n", [RemoteProc]),
@@ -179,7 +179,7 @@ receive_trace(Config) when is_list(Config) ->
F2(NN, {true, true}),
unlink(RemoteProc),
- true = stop_node(OtherNode),
+ peer:stop(Peer),
%% Timeout
Receiver ! {set_timeout, 10},
@@ -647,8 +647,7 @@ procs_trace(Config) when is_list(Config) ->
dist_procs_trace(Config) when is_list(Config) ->
ct:timetrap({seconds, 15}),
- OtherName = atom_to_list(?MODULE)++"_dist_procs_trace",
- {ok, OtherNode} = start_node(OtherName),
+ {ok, Peer, OtherNode} = ?CT_PEER(),
Self = self(),
process_flag(trap_exit, true),
%%
@@ -695,7 +694,7 @@ dist_procs_trace(Config) when is_list(Config) ->
%%
%% exit (with registered name, due to link)
- Name = list_to_atom(OtherName),
+ Name = list_to_atom(hd(string:lexemes(atom_to_list(OtherNode), "@"))),
Reason2 = make_ref(),
Proc1 ! {link_please, Proc2},
{trace, Proc1, link, Proc2} = receive_first_trace(),
@@ -708,8 +707,7 @@ dist_procs_trace(Config) when is_list(Config) ->
receive_nothing(),
%%
%% Done.
- true = stop_node(OtherNode),
- ok.
+ peer:stop(Peer).
%% Test trace(new, How, [procs]).
procs_new_trace(Config) when is_list(Config) ->
@@ -1724,7 +1722,7 @@ trace_delivered(Config) when is_list(Config) ->
%% This testcase checks that receive trace works on exit signal messages
%% when the sender of the exit signal is the process itself.
-trap_exit_self_receive(Config) ->
+trap_exit_self_receive(Config) when is_list(Config) ->
Parent = self(),
Proc = spawn_link(fun() -> process(Parent) end),
@@ -1754,7 +1752,7 @@ trace_info_badarg(Config) when is_list(Config) ->
%% An incoming suspend monitor down wasn't handled
%% correct when the local monitor half had been
%% removed with an emulator crash as result.
-erl_704(Config) ->
+erl_704(Config) when is_list(Config) ->
erl_704_test(100).
erl_704_test(0) ->
@@ -1944,16 +1942,6 @@ fun_spawn(Fun, Args) ->
spawn_link(erlang, apply, [Fun, Args]).
-start_node(Name) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Cookie = atom_to_list(erlang:get_cookie()),
- test_server:start_node(Name, slave,
- [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-
wait_for_empty_runq(DeadLine) ->
case statistics(run_queue) of
0 -> true;
diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl
index 8cf8c81b7a..741d5c10d9 100644
--- a/erts/emulator/test/trace_local_SUITE.erl
+++ b/erts/emulator/test/trace_local_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -744,15 +744,27 @@ exception_test(Opts) ->
shutdown();
true ->
Exceptions = exceptions(),
- lists:foreach(
- fun ({Func,Args}) ->
- exception_test_setup(
- [procs|ProcFlags],
- PatFlags),
- exception_test(Opts, Func, Args),
- shutdown()
- end,
- Exceptions)
+ try
+ %% suppress =ERROR REPORT=== emulator messages
+ ok = logger:add_primary_filter(suppress_log_spam, {
+ fun(#{meta := #{error_logger := #{emulator := true, tag := error}}}, _) ->
+ stop;
+ (_Meta, _Msg) ->
+ ignore
+ end, ok}),
+ lists:foreach(
+ fun ({Func,Args}) ->
+ exception_test_setup(
+ [procs|ProcFlags],
+ PatFlags),
+ exception_test(Opts, Func, Args),
+ shutdown()
+ end,
+ Exceptions)
+ after
+ %% remove the suppression for ERROR REPORTS
+ ok = logger:remove_primary_filter(suppress_log_spam)
+ end
end,
ok.
@@ -778,7 +790,7 @@ exceptions() ->
exception_test_setup(ProcFlags, PatFlags) ->
Pid = setup(ProcFlags),
- io:format("=== exception_test_setup(~p, ~p): ~p~n",
+ ct:log("=== exception_test_setup(~p, ~p): ~p~n",
[ProcFlags,PatFlags,Pid]),
Mprog = [{'_',[],[{exception_trace}]}],
erlang:trace_pattern({?MODULE,'_','_'}, Mprog, PatFlags),
@@ -792,7 +804,7 @@ exception_test_setup(ProcFlags, PatFlags) ->
-record(exc_opts, {nocatch=false, meta=false}).
exception_test(Opts, Func0, Args0) ->
- io:format("=== exception_test(~p, ~p, ~p)~n",
+ ct:log("=== exception_test(~p, ~p, ~p)~n",
[Opts,Func0,abbr(Args0)]),
Apply = proplists:get_bool(apply, Opts),
Function = proplists:get_bool(function, Opts),
@@ -803,16 +815,16 @@ exception_test(Opts, Func0, Args0) ->
%% Func0 and Args0 are for the innermost call, now we will
%% wrap them in wrappers...
{Func1,Args1} =
- case Function of
- true -> {fun exc/2,[Func0,Args0]};
- false -> {Func0,Args0}
- end,
+ case Function of
+ true -> {fun(F, As) -> exc(F, As) end, [Func0,Args0]};
+ false -> {Func0,Args0}
+ end,
{Func,Args} =
- case Apply of
- true -> {{erlang,apply},[Func1,Args1]};
- false -> {Func1,Args1}
- end,
+ case Apply of
+ true -> {{erlang,apply},[Func1,Args1]};
+ false -> {Func1,Args1}
+ end,
R1 = exc_slave(ExcOpts, Func, Args),
Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}],
diff --git a/erts/emulator/test/tuple_SUITE.erl b/erts/emulator/test/tuple_SUITE.erl
index 8427825cd4..e665c55003 100644
--- a/erts/emulator/test/tuple_SUITE.erl
+++ b/erts/emulator/test/tuple_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -125,10 +125,17 @@ t_element(Config) when is_list(Config) ->
a = element(1, {a}),
a = element(1, {a, b}),
- List = lists:seq(1, 4096),
- Tuple = list_to_tuple(lists:seq(1, 4096)),
+ List = lists:seq(1, 16384),
+ Tuple = list_to_tuple(List),
get_elements(List, Tuple, 1),
+ get_literal_elements(Tuple),
+ get_literal_tuple_elements(Tuple),
+
+ {31,32, 63,64, 127,128, 255,256, 511,512, 1023,1024,
+ 2047,2048, 4095,4096, 8191,8192, 16383, 16384} =
+ get_literal_tuple_element_pairs(Tuple),
+
{'EXIT', {badarg, _}} = (catch element(0, id({a,b}))),
{'EXIT', {badarg, _}} = (catch element(3, id({a,b}))),
{'EXIT', {badarg, _}} = (catch element(1, id({}))),
@@ -150,7 +157,110 @@ get_elements([Element|Rest], Tuple, Pos) ->
get_elements(Rest, Tuple, Pos+1);
get_elements([], _Tuple, _Pos) ->
ok.
-
+
+get_literal_elements(Tuple) ->
+ 31 = element(31, Tuple),
+ 32 = element(32, Tuple),
+
+ 63 = element(63, Tuple),
+ 64 = element(64, Tuple),
+
+ 127 = element(127, Tuple),
+ 128 = element(128, Tuple),
+
+ 255 = element(255, Tuple),
+ 256 = element(256, Tuple),
+
+ 511 = element(511, Tuple),
+ 512 = element(512, Tuple),
+
+ 1023 = element(1023, Tuple),
+ 1024 = element(1024, Tuple),
+
+ 2047 = element(2047, Tuple),
+ 2048 = element(2048, Tuple),
+
+ 4095 = element(4095, Tuple),
+ 4096 = element(4096, Tuple),
+
+ 8191 = element(8191, Tuple),
+ 8192 = element(8192, Tuple),
+
+ 16383 = element(16383, Tuple),
+ 16384 = element(16384, Tuple),
+
+ ok.
+
+get_literal_tuple_elements(Tuple) when tuple_size(Tuple) =:= 16384 ->
+ %% Since the tuple size is known, the element/2 calls will be
+ %% rewritten to get_tuple_element instructions.
+
+ 31 = element(31, Tuple),
+ 32 = element(32, Tuple),
+
+ 63 = element(63, Tuple),
+ 64 = element(64, Tuple),
+
+ 127 = element(127, Tuple),
+ 128 = element(128, Tuple),
+
+ 255 = element(255, Tuple),
+ 256 = element(256, Tuple),
+
+ 511 = element(511, Tuple),
+ 512 = element(512, Tuple),
+
+ 1023 = element(1023, Tuple),
+ 1024 = element(1024, Tuple),
+
+ 2047 = element(2047, Tuple),
+ 2048 = element(2048, Tuple),
+
+ 4095 = element(4095, Tuple),
+ 4096 = element(4096, Tuple),
+
+ 8191 = element(8191, Tuple),
+ 8192 = element(8192, Tuple),
+
+ 16383 = element(16383, Tuple),
+ 16384 = element(16384, Tuple),
+
+ ok.
+
+get_literal_tuple_element_pairs(Tuple) when tuple_size(Tuple) =:= 16384 ->
+ %% Since the tuple size is known, the element/2 calls will be
+ %% rewritten to get_tuple_element instructions.
+
+ {element(31, Tuple),
+ element(32, Tuple),
+
+ element(63, Tuple),
+ element(64, Tuple),
+
+ element(127, Tuple),
+ element(128, Tuple),
+
+ element(255, Tuple),
+ element(256, Tuple),
+
+ element(511, Tuple),
+ element(512, Tuple),
+
+ element(1023, Tuple),
+ element(1024, Tuple),
+
+ element(2047, Tuple),
+ element(2048, Tuple),
+
+ element(4095, Tuple),
+ element(4096, Tuple),
+
+ element(8191, Tuple),
+ element(8192, Tuple),
+
+ element(16383, Tuple),
+ element(16384, Tuple)}.
+
%% Tests set_element/3.
t_setelement(Config) when is_list(Config) ->
@@ -158,9 +268,9 @@ t_setelement(Config) when is_list(Config) ->
{x,2} = setelement(1, id({1,2}), x),
{1,x} = setelement(2, id({1,2}), x),
- Tuple = list_to_tuple(lists:duplicate(2048, x)),
+ Tuple = list_to_tuple(lists:duplicate(16385, x)),
NewTuple = set_all_elements(Tuple, 1),
- NewTuple = list_to_tuple(lists:seq(1+7, 2048+7)),
+ NewTuple = list_to_tuple(lists:seq(1+7, 16385+7)),
{'EXIT', {badarg, _}} = (catch setelement(0, {a, b}, x)),
{'EXIT', {badarg, _}} = (catch setelement(3, {a, b}, x)),
@@ -174,6 +284,9 @@ t_setelement(Config) when is_list(Config) ->
setelement(1, setelement(2, setelement(3, AnotherTuple, gurka),
3.0), 93748793749387837476555412),
+ NewNewTuple = set_literal_tuple_elements(NewTuple),
+ verify_set_elements(1, NewNewTuple),
+
ok.
set_all_elements(Tuple, Pos) when Pos =< size(Tuple) ->
@@ -181,6 +294,71 @@ set_all_elements(Tuple, Pos) when Pos =< size(Tuple) ->
set_all_elements(Tuple, Pos) when Pos > size(Tuple) ->
Tuple.
+set_literal_tuple_elements(Tuple0) when tuple_size(Tuple0) =:= 16385 ->
+ %% Since the tuple size is known, the setelement/3 calls will be
+ %% rewritten to set_tuple_element instructions.
+ Tuple1 = setelement(16385, Tuple0, -16385),
+ Tuple2 = setelement(16384, Tuple1, -16384),
+
+ Tuple3 = setelement(8192, Tuple2, -8192),
+ Tuple4 = setelement(8191, Tuple3, -8191),
+
+ Tuple5 = setelement(4096, Tuple4, -4096),
+ Tuple6 = setelement(4095, Tuple5, -4095),
+
+ Tuple7 = setelement(2048, Tuple6, -2048),
+ Tuple8 = setelement(2047, Tuple7, -2047),
+
+ Tuple9 = setelement(1024, Tuple8, -1024),
+ Tuple10 = setelement(1023, Tuple9, -1023),
+
+ Tuple11 = setelement(512, Tuple10, -512),
+ Tuple12 = setelement(511, Tuple11, -511),
+
+ Tuple13 = setelement(256, Tuple12, -256),
+ Tuple14 = setelement(255, Tuple13, -255),
+
+ Tuple15 = setelement(128, Tuple14, -128),
+ Tuple16 = setelement(127, Tuple15, -127),
+
+ Tuple17 = setelement(64, Tuple16, -64),
+ Tuple18 = setelement(63, Tuple17, -63),
+
+ Tuple19 = setelement(32, Tuple18, -32),
+ Tuple20 = setelement(31, Tuple19, -31),
+
+ Tuple21 = setelement(16, Tuple20, -16),
+ Tuple22 = setelement(15, Tuple21, -15),
+
+ Tuple23 = setelement(8, Tuple22, -8),
+ Tuple24 = setelement(7, Tuple23, -7),
+
+ Tuple25 = setelement(4, Tuple24, -4),
+ Tuple26 = setelement(3, Tuple25, -3),
+
+ Tuple27 = setelement(2, Tuple26, -2),
+ setelement(1, Tuple27, -1).
+
+verify_set_elements(16385, Tuple) ->
+ -16385 = element(16385, Tuple),
+ ok;
+verify_set_elements(N, Tuple) ->
+ El = element(N, Tuple),
+ if
+ El =:= N + 7 ->
+ true = not (is_power_of_two(N + 1) andalso is_power_of_two(N)),
+ verify_set_elements(N + 1, Tuple);
+ El =:= -N ->
+ true = is_power_of_two(N + 1) orelse is_power_of_two(N),
+ verify_set_elements(N + 1, Tuple);
+ true ->
+ io:format("element(~p) =:= ~p\n", [N,El]),
+ ct:fail(bad_element)
+ end.
+
+is_power_of_two(N) ->
+ N band (N - 1) =:= 0.
+
%% Tests list_to_tuple/1.
t_list_to_tuple(Config) when is_list(Config) ->
@@ -205,7 +383,7 @@ t_list_to_tuple(Config) when is_list(Config) ->
t_list_to_upper_boundry_tuple(Config) when is_list(Config) ->
sys_mem_cond_run(2048,
fun () ->
- %% test upper boundry, 16777215 elements
+ %% test upper boundary, 16777215 elements
MaxSize = 1 bsl 24 - 1,
MaxTuple = list_to_tuple(lists:seq(1, MaxSize)),
MaxSize = size(MaxTuple),
@@ -254,7 +432,7 @@ t_make_tuple_2(Config) when is_list(Config) ->
t_make_upper_boundry_tuple_2(Config) when is_list(Config) ->
sys_mem_cond_run(2048,
fun () ->
- %% test upper boundry, 16777215 elements
+ %% test upper boundary, 16777215 elements
t_make_tuple(1 bsl 24 - 1, a)
end).
@@ -347,7 +525,7 @@ t_append_element(Config) when is_list(Config) ->
t_append_element_upper_boundry(Config) when is_list(Config) ->
sys_mem_cond_run(2048,
fun () ->
- %% test upper boundry, 16777215 elements
+ %% test upper boundary, 16777215 elements
MaxSize = 1 bsl 24 - 1,
MaxTuple = list_to_tuple(lists:seq(1, MaxSize)),
{'EXIT',{badarg,_}} = (catch erlang:append_element(MaxTuple, a)),
@@ -419,7 +597,7 @@ get_two_tuple_elements(Config) ->
true = code:delete(GTTEMod),
code:purge(GTTEMod),
- %% Compile from the pre-generated BEAM assmebly code file. (In case that the
+ %% Compile from the pre-generated BEAM assembly code file. (In case that the
%% compiler's code generation has changed.)
{ok,GTTEMod,Code2} = compile:file(GTTETestsFile, [from_asm,binary,report,time]),
{module,GTTEMod} = code:load_binary(GTTEMod, GTTEMod, Code2),
@@ -445,17 +623,16 @@ sys_mem_cond_run(ReqSizeMB, TestFun) when is_integer(ReqSizeMB) ->
total_memory() ->
- %% Totat memory in MB.
+ %% Total memory in MB.
try
- MemoryData = memsup:get_system_memory_data(),
- case lists:keysearch(total_memory, 1, MemoryData) of
- {value, {total_memory, TM}} ->
- TM div (1024*1024);
- false ->
- {value, {system_total_memory, STM}} =
- lists:keysearch(system_total_memory, 1, MemoryData),
- STM div (1024*1024)
- end
+ SMD = memsup:get_system_memory_data(),
+ TM = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(
+ total_memory, SMD,
+ proplists:get_value(
+ system_total_memory, SMD))),
+ TM div (1024*1024)
catch
_ : _ ->
undefined
diff --git a/erts/emulator/test/unique_SUITE.erl b/erts/emulator/test/unique_SUITE.erl
index cfc37bd44f..d041ed5632 100644
--- a/erts/emulator/test/unique_SUITE.erl
+++ b/erts/emulator/test/unique_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
-module(unique_SUITE).
-export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2]).
-export([unique_monotonic_integer_white_box/1,
unique_integer_white_box/1]).
@@ -47,6 +48,11 @@ end_per_suite(_Config) ->
erts_debug:set_internal_state(available_internal_state, false),
ok.
+init_per_testcase(_TestCase, Config) ->
+ Config.
+end_per_testcase(_TestCase, Config) ->
+ erts_test_utils:ept_check_leaked_nodes(Config).
+
%%
%%
%% Unique counter white box test case
@@ -54,7 +60,7 @@ end_per_suite(_Config) ->
%%
unique_monotonic_integer_white_box(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
TestServer = self(),
Success = make_ref(),
%% Run this in a separate node, so we don't mess up
@@ -72,8 +78,7 @@ unique_monotonic_integer_white_box(Config) when is_list(Config) ->
ok
end,
erlang:demonitor(Mon, [flush]),
- stop_node(Node),
- ok.
+ peer:stop(Peer).
set_unique_monotonic_integer_state(MinCounter, NextValue) ->
true = erts_debug:set_internal_state(unique_monotonic_integer_state,
@@ -355,21 +360,3 @@ check_unique_integer_around(Int, #uniqint_info{min_int = MinInt,
print_ret_val(File, Line, Value) ->
io:format("~s:~p: ~p~n", [File, Line, Value]),
Value.
-
-start_node(Config) ->
- start_node(Config, []).
-start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
- Pa = filename:dirname(code:which(?MODULE)),
- A = erlang:monotonic_time(1) + erlang:time_offset(1),
- B = erlang:unique_integer([positive]),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(A)
- ++ "-"
- ++ integer_to_list(B)),
- test_server:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl
index 5b2e77dfa2..cb178704eb 100644
--- a/erts/emulator/test/z_SUITE.erl
+++ b/erts/emulator/test/z_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -169,7 +169,7 @@ schedulers_alive(Config) when is_list(Config) ->
enabled -> ok
end,
erts_debug:set_internal_state(available_internal_state, true),
- %% node_and_dist_references will use emulator interal thread blocking...
+ %% node_and_dist_references will use emulator internal thread blocking...
erts_debug:get_internal_state(node_and_dist_references),
erts_debug:set_internal_state(available_internal_state, false),
io:format("Testing not blocked~n"),
@@ -330,8 +330,9 @@ check_io_debug_test() ->
has_gethost() ->
has_gethost(erlang:ports()).
has_gethost([P|T]) ->
- case erlang:port_info(P, name) of
- {name,"inet_gethost"++_} ->
+ {name, Name} = erlang:port_info(P, name),
+ case filename:basename(Name) of
+ "inet_gethost"++_ ->
true;
_ ->
has_gethost(T)
@@ -346,7 +347,7 @@ lc_graph(Config) when is_list(Config) ->
ok.
leaked_processes(Config) when is_list(Config) ->
- %% Replace the defualt timetrap with a timetrap with
+ %% Replace the default timetrap with a timetrap with
%% known pid.
test_server:timetrap_cancel(),
Dog = test_server:timetrap(test_server:minutes(5)),
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 867f631938..da850ed7cb 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -49,6 +49,10 @@ my $code_pointers_are_short = 0; # Whether code pointers (to C code) are short.
my $code_model = 'unknown';
my $jit = 'no';
my %defs; # Defines (from command line).
+my $pending_errors = 0; # Number of pending errors.
+
+# Intentionally unused macros, predicates, and generators.
+my %intentionally_unused;
# This is shift counts and mask for the packer.
my $WHOLE_WORD = '';
@@ -178,8 +182,82 @@ my %arg_size = ('r' => 0, # x(0) - x register zero,
'h' => 1, # character (not used)
'l' => 1, # float reg
'q' => 1, # literal term
+ 'M' => 1, # pointer to raw string
+ 'H' => 1, # exception handler
);
+# Maps operand type to the argument classes used by the JIT.
+my %arg_jit_class = ('r' => 'ArgXRegister',
+ 'x' => 'ArgXRegister',
+ 'y' => 'ArgYRegister',
+ 'a' => 'ArgAtom',
+ 'n' => 'ArgNil',
+ 'c' => 'ArgConstant',
+ 's' => 'ArgSource',
+ 'S' => 'ArgRegister',
+ 'd' => 'ArgRegister',
+ 'f' => 'ArgLabel',
+ 'j' => 'ArgLabel',
+ 'e' => 'ArgExport',
+ 'L' => 'ArgLabel',
+ 't' => 'ArgWord',
+ 'I' => 'ArgWord',
+ 'W' => 'ArgWord',
+ 'b' => 'ArgWord',
+ 'F' => 'ArgLambda',
+ 'A' => 'ArgWord',
+ 'P' => 'ArgWord',
+ 'Q' => 'ArgWord',
+ 'h' => 'ArgWord',
+ 'l' => 'ArgFRegister',
+ 'q' => 'ArgLiteral',
+ 'M' => 'ArgBytePtr',
+ 'H' => 'ArgCatch',
+ );
+
+# Define a lattice for the parameter classes used in the JIT.
+#
+# The classes are represented as a bitset where each class is represented by
+# a single bit, which is combined with that of its superclasses, letting us
+# find the best superclass for a given set of classes by AND-ing them together.
+my %arg_jit_lattice;
+{
+ # Perl lacks enums, lovely :(
+ my $iota = 0;
+ my %jcl;
+
+ $jcl{'ArgVal'} = (1 << $iota++),
+
+ $jcl{'ArgBytePtr'} = $jcl{'ArgVal'} | (1 << $iota++);
+ $jcl{'ArgCatch'} = $jcl{'ArgVal'} | (1 << $iota++);
+ $jcl{'ArgExport'} = $jcl{'ArgVal'} | (1 << $iota++);
+ $jcl{'ArgLabel'} = $jcl{'ArgVal'} | (1 << $iota++);
+ $jcl{'ArgLambda'} = $jcl{'ArgVal'} | (1 << $iota++);
+ $jcl{'ArgSource'} = $jcl{'ArgVal'} | (1 << $iota++);
+ $jcl{'ArgWord'} = $jcl{'ArgVal'} | (1 << $iota++);
+
+ $jcl{'ArgConstant'} = $jcl{'ArgSource'} | (1 << $iota++);
+ $jcl{'ArgRegister'} = $jcl{'ArgSource'} | (1 << $iota++);
+
+ $jcl{'ArgLiteral'} = $jcl{'ArgConstant'} | (1 << $iota++);
+ $jcl{'ArgImmed'} = $jcl{'ArgConstant'} | (1 << $iota++);
+
+ $jcl{'ArgAtom'} = $jcl{'ArgImmed'} | (1 << $iota++);
+ $jcl{'ArgNil'} = $jcl{'ArgImmed'} | (1 << $iota++);
+ $jcl{'ArgSmall'} = $jcl{'ArgImmed'} | (1 << $iota++);
+
+ $jcl{'ArgXRegister'} = $jcl{'ArgRegister'} | (1 << $iota++);
+ $jcl{'ArgYRegister'} = $jcl{'ArgRegister'} | (1 << $iota++);
+ $jcl{'ArgFRegister'} = $jcl{'ArgRegister'} | (1 << $iota++);
+
+ foreach my $class (keys %jcl) {
+ my $bits = $jcl{$class};
+ $jcl{$bits} = $class;
+ }
+
+ %arg_jit_lattice = %jcl;
+}
+
#
# Types that are forbidden to use for specific operations.
#
@@ -256,6 +334,8 @@ sub define_type_bit {
define_type_bit('e', $type_bit{'u'});
define_type_bit('Q', $type_bit{'u'});
define_type_bit('P', $type_bit{'u'});
+ define_type_bit('M', $type_bit{'u'});
+ define_type_bit('H', $type_bit{'u'});
}
#
@@ -371,8 +451,13 @@ while (<>) {
}
chomp;
if (s/\\$//) {
- $_ .= <>;
- redo unless eof(ARGV);
+ error("line continuation with `\\` is no longer allowed");
+ } elsif (/([|]|=>)$/) {
+ # Automatically continue a line that ends in '|' or '=>'.
+ my $next_line = <>;
+ $_ .= $next_line;
+ chomp $next_line;
+ redo unless eof(ARGV) or $next_line eq '';
}
next if /^\s*$/;
next if /^\#/;
@@ -449,6 +534,24 @@ while (<>) {
}
#
+ # Handle %unused.
+ #
+ if (/^\%unused\s+(\S+)/) {
+ my $name = $1;
+ error("Illegal predicate/generator name '$name'")
+ unless $name =~ /^[a-z][.\w\d_]*$/;
+ $intentionally_unused{$name} = 1;
+ next;
+ }
+
+ #
+ # Handle unrecognized % directives.
+ #
+ if (/^\%(\S+)/) {
+ error("Unrecognized directive '%$1'");
+ }
+
+ #
# Handle transformations.
#
if (/=>/) {
@@ -569,7 +672,6 @@ $num_file_opcodes = @gen_opname;
# or use forbidden types.
#
-my $any_errors;
foreach my $key (keys %specific_op) {
my($arity) = (split('/', $key))[1];
my @specific_ops = @{$specific_op{$key}};
@@ -594,17 +696,18 @@ foreach my $key (keys %specific_op) {
my $cleaned_arg = $arg;
$cleaned_arg =~ s/[?]$//;
if ($jit ne 'no' and $cleaned_arg eq 'r') {
- warn "specific instruction '$name @args' uses type 'r' which is is not supported for BeamAsm\n";
- $any_errors = 1;
+ pending_error("specific instruction '$name @args' uses type " .
+ "'r' which is is not supported for BeamAsm");
} elsif ($forbidden_type{$cleaned_arg}) {
- warn "specific instruction '$name @args' uses forbidden type '$arg'\n";
- $any_errors = 1;
+ pending_error("specific instruction '$name @args' uses " .
+ "forbidden type '$arg'\n");
}
}
}
}
-error("there were previous type errors") if $any_errors;
+error("beam_makeops: terminating because there were previous errors")
+ if $pending_errors > 0;
#
# Produce output for the chosen target.
@@ -612,12 +715,16 @@ error("there were previous type errors") if $any_errors;
&$target();
+error("beam_makeops: terminating because there were previous errors")
+ if $pending_errors > 0;
+
#
# Ensure that all C code implementations have been used.
#
{
my(@unused) = grep(!$c_code_used{$_}, keys %c_code);
- foreach my $unused (@unused) {
+ @unused = grep(!$intentionally_unused{$_}, @unused);
+ foreach my $unused (sort @unused) {
my(undef,$where) = @{$c_code{$unused}};
warn "$where: $unused is unused\n";
}
@@ -633,6 +740,13 @@ sub emulator_output {
my $name;
my $key; # Loop variable.
+ foreach $key (sort keys %c_code) {
+ if ($intentionally_unused{$key}) {
+ delete $c_code{$key};
+ }
+# print STDERR "$key: ", defined($c_code{$key}), "\n";
+ }
+
# Initialize common information always needed.
foreach $key (keys %specific_op) {
foreach (@{$specific_op{$key}}) {
@@ -692,11 +806,11 @@ sub emulator_output {
}
if ($varargs) {
- # We pass variable argument lists as a vector of ArgVal,
+ # We pass variable argument lists as a Span of ArgVal,
# slicing our argument vector after the argument count.
$body .= $sep .
- "std::vector<ArgVal>(" .
- "args.cbegin() + " . scalar(@args) . ", args.cend())";
+ "args.subspan(" . scalar(@args) . "," .
+ "args.size() - " . scalar(@args) . ")";
}
$body .= ");";
@@ -715,17 +829,33 @@ sub emulator_output {
# Sort the generated code to create beamasm_protos.h deterministically
foreach $key (sort keys %specific_op) {
- foreach (@{$specific_op{$key}}) {
- my($name, $hotness, $varargs, @args) = @$_;
+ my @specific_ops = @{$specific_op{$key}};
+ my ($name,
+ $hotness,
+ $varargs,
+ @combined_signs) = @{shift @specific_ops};
+
+ # We want to reduce all specific ops to the same prototype, so
+ # their signs must be combined to find the right argument types.
+ foreach (@specific_ops) {
+ my (undef, undef, undef, @specific_signs) = @$_;
+
+ for my $i (0..$#combined_signs) {
+ $combined_signs[$i] .= $specific_signs[$i];
+ }
+ }
- @args = ("const ArgVal&") x @args;
- if ($varargs) {
- push @args, "const std::vector<ArgVal>&";
- }
+ my @typed_args;
+ for my $signs (@combined_signs) {
+ my $class = get_jit_class($signs);
+ push @typed_args, "const $class&";
+ }
- print "void emit_$name(", join(", ", @args), ");\n";
- last; # We only want to print one prototype
+ if ($varargs) {
+ push @typed_args, "const Span<ArgVal>&";
}
+
+ print "void emit_$name(", join(", ", @typed_args), ");\n";
}
}
@@ -1010,7 +1140,9 @@ sub emulator_output {
print '#include "erl_term.h"', "\n";
print '#include "erl_map.h"', "\n";
print '#include "big.h"', "\n";
+ print '#include "erl_bits.h"', "\n";
print '#include "beam_transform_helpers.h"', "\n";
+ print '#include "erl_global_literals.h"', "\n";
print "\n";
gen_tr_code('pred.');
gen_tr_func('int', 'erts_beam_eval_predicate', @pred_table);
@@ -1248,6 +1380,13 @@ sub parse_c_args {
@res;
}
+sub pending_error {
+ my(@message) = @_;
+ my($where) = $. ? "$ARGV($.): " : "";
+ $pending_errors++;
+ warn $where, @message, "\n";
+}
+
sub error {
my(@message) = @_;
my($where) = $. ? "$ARGV($.): " : "";
@@ -2010,7 +2149,7 @@ sub do_pack_one {
# to the left of the current micro instruction. If that is the
# case, it is essential that we generate stacking and
# unstacking instructions even when no packing is
- # possible. (build_pack_spec() will remove any unecessary
+ # possible. (build_pack_spec() will remove any unnecessary
# stacking and unstacking operations.)
#
# Here is an example. Say that we have this instruction:
@@ -2356,10 +2495,14 @@ sub parse_transformation {
local($_) = @_;
my($orig) = $_;
- my($from, $to) = split(/\s*=>\s*/);
+ my($from, $to, @rest) = split(/\s*=>\s*/);
my(@op);
my $rest_var;
+ if (@rest) {
+ error("only one '=>' operator is allowed");
+ }
+
# The source instructions.
my(@from) = split(/\s*\|\s*/, $from);
@@ -2386,15 +2529,22 @@ sub parse_transformation {
error("garbage after call to '$name()'");
}
@to = (compile_transform_function($name, split(/\s*,\s*/, $arglist)));
+ } elsif ($to =~ /^\s*_\s*$/) {
+ # _ means that instructions on the left side should be removed.
+ @to = ();
} else {
@to = split(/\s*\|\s*/, $to);
+ if (@to == 0) {
+ error("the right-hand side of a transformation must not be empty;\n" .
+ " use _ to indicate that no instructions should be produced");
+ }
foreach (@to) {
(@op) = split;
(undef,$_) = compile_transform(0, $rest_var, @op);
}
}
$orig =~ tr/ \t/ /s;
- push(@transformations, [$., $orig, [@from], [reverse @to]]);
+ push(@transformations, ["$ARGV($.)", $orig, [@from], [reverse @to]]);
}
sub compile_transform_function {
@@ -2599,7 +2749,7 @@ sub tr_gen_from {
my($var_num) = 0;
my(@code);
my($op, $ref); # Loop variables.
- my $where = "left side of transformation in line $line: ";
+ my $where = "$line: (left of =>): ";
my $may_fail = 0;
my $is_first = 1;
my @instrs;
@@ -2708,14 +2858,14 @@ sub tr_gen_from {
if ($var ne '') {
if (defined $var{$var}) {
- $ignored_var = '';
- $may_fail = 1;
- my $op = make_op($var, 'is_same_var', $var{$var});
- op_slot_usage($op, $var{$var});
- push(@code, $op);
+ my $msg = "variable $var used more than once\n" .
+ " (repeated variables in matching is not supported;\n" .
+ " use the predicate equal(Var1, Var2) " .
+ "to compare variables)";
+ pending_error($where, $msg);
} elsif ($type eq '*') {
foreach my $type (values %var_type) {
- error("only one use of a '*' variable is " .
+ error($where, "only one use of a '*' variable is " .
"allowed on the left hand side of " .
"a transformation")
if $type eq 'array';
@@ -2797,7 +2947,7 @@ sub tr_gen_to {
my(%var_type) = %$var_type_ref;
my(@code) = @$code_ref;
my($op, $ref); # Loop variables.
- my($where) = "right side of transformation in line $line: ";
+ my($where) = "$line: (right of =>): ";
my $last_instr = $code[$#code];
my $cannot_fail = is_instr($last_instr, 'commit') &&
@@ -2918,7 +3068,7 @@ sub group_tr {
my($lref) = @_;
#
- # Group tranformations (while keeping the order) that all match the same
+ # Group transformations (while keeping the order) that all match the same
# second instruction.
#
for (my $i = 0; $i < @$lref; $i++) {
@@ -3303,3 +3453,25 @@ sub include_files() {
print '#include "beam_load.h"', "\n";
print "\n";
}
+
+# Converts a sign string to its most specific argument class, e.g. "an" becomes
+# 'ArgImmed' because both are immediates, and "anx" becomes 'ArgSource' because
+# all of them are sources.
+sub get_jit_class {
+ my $signs__ = shift;
+ $signs__ =~ s/[?]//g;
+
+ my @signs = split //, $signs__;
+
+ my $type = $arg_jit_class{shift(@signs)};
+ my $combined_bits = $arg_jit_lattice{$type};
+
+ foreach my $sign (@signs) {
+ my $next_type = $arg_jit_class{$sign};
+ my $next_bits = $arg_jit_lattice{$next_type};
+
+ $combined_bits &= $next_bits;
+ }
+
+ return $arg_jit_lattice{$combined_bits};
+}
diff --git a/erts/emulator/utils/count b/erts/emulator/utils/count
index e0a5e8bb9a..859137ed96 100755
--- a/erts/emulator/utils/count
+++ b/erts/emulator/utils/count
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
main(_) ->
DisDir = "./dis",
ok = filelib:ensure_dir(filename:join(DisDir, "dummy")),
- io:format("Dissambling to ~s\n", [DisDir]),
+ io:format("Disassembling to ~s\n", [DisDir]),
ok = file:set_cwd(DisDir),
Path = code:get_path() -- ["."],
Beams0 = [filelib:wildcard(filename:join(Dir, "*.beam")) ||
@@ -98,7 +98,7 @@ increment(Key, Inc) ->
end.
%%%
-%%% Counting sempahore to limit the number of processes that
+%%% Counting semaphore to limit the number of processes that
%%% can run concurrently.
%%%
diff --git a/erts/emulator/utils/make_driver_tab b/erts/emulator/utils/make_driver_tab
index b55a926c0c..4ed9cb0ce8 100755
--- a/erts/emulator/utils/make_driver_tab
+++ b/erts/emulator/utils/make_driver_tab
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2021. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -130,38 +130,19 @@ foreach (@static_nifs) {
}
# The array itself
-print "static ErtsStaticNifEntry static_nif_tab[] =\n{\n";
+print "ErtsStaticNif erts_static_nif_tab[] =\n{\n";
foreach (@emu_nifs) {
my $d = ${_};
$d =~ s/\.debug//; # strip .debug
- print " {\"${_}\", &".$d."_nif_init, 0},\n";
+ print " {&".$d."_nif_init, 0, THE_NON_VALUE, NULL},\n";
}
foreach (@static_nifs) {
my $d = ${_};
$d =~ s/\.debug//; # strip .debug
- print " {\"${_}\", &".$d."_nif_init, 1},\n";
+ print " {&".$d."_nif_init, 1, THE_NON_VALUE, NULL},\n";
}
-print " {NULL,NULL}\n};\n";
-
-print <<EOF;
-ErtsStaticNifEntry* erts_static_nif_get_nif_init(const char *name, int len) {
- ErtsStaticNifEntry* p;
- for (p = static_nif_tab; p->nif_name != NULL; p++)
- if (strncmp(p->nif_name, name, len) == 0 && p->nif_name[len] == 0)
- return p;
- return NULL;
-}
-
-int erts_is_static_nif(void *handle) {
- ErtsStaticNifEntry* p;
- for (p = static_nif_tab; p->nif_name != NULL; p++)
- if (((void*)p->nif_init) == handle)
- return 1;
- return 0;
-}
-
-EOF
+print " {NULL}\n};\n";
# That's it
diff --git a/erts/emulator/utils/make_preload b/erts/emulator/utils/make_preload
index b596fb0fa2..e8f59def1a 100755
--- a/erts/emulator/utils/make_preload
+++ b/erts/emulator/utils/make_preload
@@ -150,7 +150,9 @@ sub beam_strip {
'ExpT' => 1,
'StrT' => 1,
'FunT' => 1,
- 'LitT' => 1);
+ 'LitT' => 1,
+ 'Type' => 1
+ );
die "$file: can't read Beam files for OTP R4 or earlier (sorry)"
if $beam =~ /^\x7fBEAM!/;
diff --git a/erts/emulator/zlib/crc32.c b/erts/emulator/zlib/crc32.c
index 9580440c0e..a1bdce5c23 100644
--- a/erts/emulator/zlib/crc32.c
+++ b/erts/emulator/zlib/crc32.c
@@ -1,12 +1,10 @@
/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
- * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
- * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
- * tables for updating the shift register in one step with three exclusive-ors
- * instead of four steps with four exclusive-ors. This results in about a
- * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ * This interleaved implementation of a CRC makes use of pipelined multiple
+ * arithmetic-logic units, commonly found in modern CPU cores. It is due to
+ * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
*/
/* @(#) $Id$ */
@@ -14,11 +12,12 @@
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
- of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
- DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
+ MAKECRCH can be #defined to write out crc32.h. A main() routine is also
+ produced, so that this one source file can be compiled to an executable.
*/
#ifdef MAKECRCH
@@ -28,415 +27,1090 @@
# endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
-#include "zutil.h" /* for STDC and FAR definitions */
+#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
-/* Definitions for doing the crc four data bytes at a time. */
-#if !defined(NOBYFOUR) && defined(Z_U4)
-# define BYFOUR
+ /*
+ A CRC of a message is computed on N braids of words in the message, where
+ each word consists of W bytes (4 or 8). If N is 3, for example, then three
+ running sparse CRCs are calculated respectively on each braid, at these
+ indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
+ This is done starting at a word boundary, and continues until as many blocks
+ of N * W bytes as are available have been processed. The results are combined
+ into a single CRC at the end. For this code, N must be in the range 1..6 and
+ W must be 4 or 8. The upper limit on N can be increased if desired by adding
+ more #if blocks, extending the patterns apparent in the code. In addition,
+ crc32.h would need to be regenerated, if the maximum N value is increased.
+
+ N and W are chosen empirically by benchmarking the execution time on a given
+ processor. The choices for N and W below were based on testing on Intel Kaby
+ Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
+ Octeon II processors. The Intel, AMD, and ARM processors were all fastest
+ with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
+ They were all tested with either gcc or clang, all using the -O3 optimization
+ level. Your mileage may vary.
+ */
+
+/* Define N */
+#ifdef Z_TESTN
+# define N Z_TESTN
+#else
+# define N 5
+#endif
+#if N < 1 || N > 6
+# error N must be in 1..6
#endif
-#ifdef BYFOUR
- local unsigned long crc32_little OF((unsigned long,
- const unsigned char FAR *, z_size_t));
- local unsigned long crc32_big OF((unsigned long,
- const unsigned char FAR *, z_size_t));
-# define TBLS 8
+
+/*
+ z_crc_t must be at least 32 bits. z_word_t must be at least as long as
+ z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
+ that bytes are eight bits.
+ */
+
+/*
+ Define W and the associated z_word_t type. If W is not defined, then a
+ braided calculation is not used, and the associated tables and code are not
+ compiled.
+ */
+#ifdef Z_TESTW
+# if Z_TESTW-1 != -1
+# define W Z_TESTW
+# endif
#else
-# define TBLS 1
-#endif /* BYFOUR */
+# ifdef MAKECRCH
+# define W 8 /* required for MAKECRCH */
+# else
+# if defined(__x86_64__) || defined(__aarch64__)
+# define W 8
+# else
+# define W 4
+# endif
+# endif
+#endif
+#ifdef W
+# if W == 8 && defined(Z_U8)
+ typedef Z_U8 z_word_t;
+# elif defined(Z_U4)
+# undef W
+# define W 4
+ typedef Z_U4 z_word_t;
+# else
+# undef W
+# endif
+#endif
-/* Local functions for crc concatenation */
-local unsigned long gf2_matrix_times OF((unsigned long *mat,
- unsigned long vec));
-local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
-local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
+/* Local functions. */
+local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
+local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+/*
+ Swap the bytes in a z_word_t to convert between little and big endian. Any
+ self-respecting compiler will optimize this to a single machine byte-swap
+ instruction, if one is available. This assumes that word_t is either 32 bits
+ or 64 bits.
+ */
+local z_word_t byte_swap(word)
+ z_word_t word;
+{
+# if W == 8
+ return
+ (word & 0xff00000000000000) >> 56 |
+ (word & 0xff000000000000) >> 40 |
+ (word & 0xff0000000000) >> 24 |
+ (word & 0xff00000000) >> 8 |
+ (word & 0xff000000) << 8 |
+ (word & 0xff0000) << 24 |
+ (word & 0xff00) << 40 |
+ (word & 0xff) << 56;
+# else /* W == 4 */
+ return
+ (word & 0xff000000) >> 24 |
+ (word & 0xff0000) >> 8 |
+ (word & 0xff00) << 8 |
+ (word & 0xff) << 24;
+# endif
+}
+#endif
+
+/* CRC polynomial. */
+#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
#ifdef DYNAMIC_CRC_TABLE
-local volatile int crc_table_empty = 1;
-local z_crc_t FAR crc_table[TBLS][256];
+local z_crc_t FAR crc_table[256];
+local z_crc_t FAR x2n_table[32];
local void make_crc_table OF((void));
+#ifdef W
+ local z_word_t FAR crc_big_table[256];
+ local z_crc_t FAR crc_braid_table[W][256];
+ local z_word_t FAR crc_braid_big_table[W][256];
+ local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));
+#endif
#ifdef MAKECRCH
- local void write_table OF((FILE *, const z_crc_t FAR *));
+ local void write_table OF((FILE *, const z_crc_t FAR *, int));
+ local void write_table32hi OF((FILE *, const z_word_t FAR *, int));
+ local void write_table64 OF((FILE *, const z_word_t FAR *, int));
#endif /* MAKECRCH */
+
+/*
+ Define a once() function depending on the availability of atomics. If this is
+ compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
+ multiple threads, and if atomics are not available, then get_crc_table() must
+ be called to initialize the tables and must return before any threads are
+ allowed to compute or combine CRCs.
+ */
+
+/* Definition of once functionality. */
+typedef struct once_s once_t;
+local void once OF((once_t *, void (*)(void)));
+
+/* Check for the availability of atomics. */
+#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
+ !defined(__STDC_NO_ATOMICS__)
+
+#include <stdatomic.h>
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ atomic_flag begun;
+ atomic_int done;
+};
+#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
+
+/*
+ Run the provided init() function exactly once, even if multiple threads
+ invoke once() at the same time. The state must be a once_t initialized with
+ ONCE_INIT.
+ */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!atomic_load(&state->done)) {
+ if (atomic_flag_test_and_set(&state->begun))
+ while (!atomic_load(&state->done))
+ ;
+ else {
+ init();
+ atomic_store(&state->done, 1);
+ }
+ }
+}
+
+#else /* no atomics */
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ volatile int begun;
+ volatile int done;
+};
+#define ONCE_INIT {0, 0}
+
+/* Test and set. Alas, not atomic, but tries to minimize the period of
+ vulnerability. */
+local int test_and_set OF((int volatile *));
+local int test_and_set(flag)
+ int volatile *flag;
+{
+ int was;
+
+ was = *flag;
+ *flag = 1;
+ return was;
+}
+
+/* Run the provided init() function once. This is not thread-safe. */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!state->done) {
+ if (test_and_set(&state->begun))
+ while (!state->done)
+ ;
+ else {
+ init();
+ state->done = 1;
+ }
+ }
+}
+
+#endif
+
+/* State for once(). */
+local once_t made = ONCE_INIT;
+
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
- with the lowest powers in the most significant bit. Then adding polynomials
+ with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
- one. If we call the above polynomial p, and represent a byte as the
+ one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
- byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
- taking the remainder. The register is initialized to zero, and for each
+ taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
- x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
- x (which is shifting right by one and adding x^32 mod p if the bit shifted
- out is a one). We start with the highest power (least significant bit) of
- q and repeat for all eight bits of q.
-
- The first table is simply the CRC of all possible eight bit values. This is
- all the information needed to generate CRCs on data a byte at a time for all
- combinations of CRC register values and incoming bytes. The remaining tables
- allow for word-at-a-time CRC calculation for both big-endian and little-
- endian machines, where a word is four bytes.
-*/
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
+ (which is shifting right by one and adding x^32 mod p if the bit shifted out
+ is a one). We start with the highest power (least significant bit) of q and
+ repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all the
+ information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+ */
+
local void make_crc_table()
{
- z_crc_t c;
- int n, k;
- z_crc_t poly; /* polynomial exclusive-or pattern */
- /* terms of polynomial defining this crc (except x^32): */
- static volatile int first = 1; /* flag to limit concurrent making */
- static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
- /* See if another task is already doing this (not thread-safe, but better
- than nothing -- significantly reduces duration of vulnerability in
- case the advice about DYNAMIC_CRC_TABLE is ignored) */
- if (first) {
- first = 0;
-
- /* make exclusive-or pattern from polynomial (0xedb88320UL) */
- poly = 0;
- for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
- poly |= (z_crc_t)1 << (31 - p[n]);
-
- /* generate a crc for every 8-bit value */
- for (n = 0; n < 256; n++) {
- c = (z_crc_t)n;
- for (k = 0; k < 8; k++)
- c = c & 1 ? poly ^ (c >> 1) : c >> 1;
- crc_table[0][n] = c;
- }
+ unsigned i, j, n;
+ z_crc_t p;
-#ifdef BYFOUR
- /* generate crc for each value followed by one, two, and three zeros,
- and then the byte reversal of those as well as the first table */
- for (n = 0; n < 256; n++) {
- c = crc_table[0][n];
- crc_table[4][n] = ZSWAP32(c);
- for (k = 1; k < 4; k++) {
- c = crc_table[0][c & 0xff] ^ (c >> 8);
- crc_table[k][n] = c;
- crc_table[k + 4][n] = ZSWAP32(c);
- }
- }
-#endif /* BYFOUR */
-
- crc_table_empty = 0;
- }
- else { /* not first */
- /* wait for the other guy to finish (not efficient, but rare) */
- while (crc_table_empty)
- ;
+ /* initialize the CRC of bytes tables */
+ for (i = 0; i < 256; i++) {
+ p = i;
+ for (j = 0; j < 8; j++)
+ p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
+ crc_table[i] = p;
+#ifdef W
+ crc_big_table[i] = byte_swap(p);
+#endif
}
+ /* initialize the x^2^n mod p(x) table */
+ p = (z_crc_t)1 << 30; /* x^1 */
+ x2n_table[0] = p;
+ for (n = 1; n < 32; n++)
+ x2n_table[n] = p = multmodp(p, p);
+
+#ifdef W
+ /* initialize the braiding tables -- needs x2n_table[] */
+ braid(crc_braid_table, crc_braid_big_table, N, W);
+#endif
+
#ifdef MAKECRCH
- /* write out CRC tables to crc32.h */
{
+ /*
+ The crc32.h header file contains tables for both 32-bit and 64-bit
+ z_word_t's, and so requires a 64-bit type be available. In that case,
+ z_word_t must be defined to be 64-bits. This code then also generates
+ and writes out the tables for the case that z_word_t is 32 bits.
+ */
+#if !defined(W) || W != 8
+# error Need a 64-bit integer type in order to generate crc32.h.
+#endif
FILE *out;
+ int k, n;
+ z_crc_t ltl[8][256];
+ z_word_t big[8][256];
out = fopen("crc32.h", "w");
if (out == NULL) return;
- fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
- fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
- fprintf(out, "local const z_crc_t FAR ");
- fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
- write_table(out, crc_table[0]);
-# ifdef BYFOUR
- fprintf(out, "#ifdef BYFOUR\n");
- for (k = 1; k < 8; k++) {
- fprintf(out, " },\n {\n");
- write_table(out, crc_table[k]);
+
+ /* write out little-endian CRC table to crc32.h */
+ fprintf(out,
+ "/* crc32.h -- tables for rapid CRC calculation\n"
+ " * Generated automatically by crc32.c\n */\n"
+ "\n"
+ "local const z_crc_t FAR crc_table[] = {\n"
+ " ");
+ write_table(out, crc_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#ifdef W\n"
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table64(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table32hi(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n");
+
+ /* write out braid tables for each value of N */
+ for (n = 1; n <= 6; n++) {
+ fprintf(out,
+ "\n"
+ "#if N == %d\n", n);
+
+ /* compute braid tables for this N and 64-bit word_t */
+ braid(ltl, big, n, 8);
+
+ /* write out braid tables for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table64(out, big[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n");
+
+ /* compute braid tables for this N and 32-bit word_t */
+ braid(ltl, big, n, 4);
+
+ /* write out braid tables for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table32hi(out, big[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n"
+ "\n"
+ "#endif\n");
}
- fprintf(out, "#endif\n");
-# endif /* BYFOUR */
- fprintf(out, " }\n};\n");
+ fprintf(out,
+ "\n"
+ "#endif\n");
+
+ /* write out zeros operator table to crc32.h */
+ fprintf(out,
+ "\n"
+ "local const z_crc_t FAR x2n_table[] = {\n"
+ " ");
+ write_table(out, x2n_table, 32);
+ fprintf(out,
+ "};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
-local void write_table(out, table)
+
+/*
+ Write the 32-bit values in table[0..k-1] to out, five per line in
+ hexadecimal separated by commas.
+ */
+local void write_table(out, table, k)
FILE *out;
const z_crc_t FAR *table;
+ int k;
{
int n;
- for (n = 0; n < 256; n++)
- fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
(unsigned long)(table[n]),
- n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
}
+
+/*
+ Write the high 32-bits of each value in table[0..k-1] to out, five per line
+ in hexadecimal separated by commas.
+ */
+local void write_table32hi(out, table, k)
+FILE *out;
+const z_word_t FAR *table;
+int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n] >> 32),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the 64-bit values in table[0..k-1] to out, three per line in
+ hexadecimal separated by commas. This assumes that if there is a 64-bit
+ type, then there is also a long long integer type, and it is at least 64
+ bits. If not, then the type cast and format string can be adjusted
+ accordingly.
+ */
+local void write_table64(out, table, k)
+ FILE *out;
+ const z_word_t FAR *table;
+ int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
+ (unsigned long long)(table[n]),
+ n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
+}
+
+/* Actually do the deed. */
+int main()
+{
+ make_crc_table();
+ return 0;
+}
+
#endif /* MAKECRCH */
+#ifdef W
+/*
+ Generate the little and big-endian braid tables for the given n and z_word_t
+ size w. Each array must have room for w blocks of 256 elements.
+ */
+local void braid(ltl, big, n, w)
+ z_crc_t ltl[][256];
+ z_word_t big[][256];
+ int n;
+ int w;
+{
+ int k;
+ z_crc_t i, p, q;
+ for (k = 0; k < w; k++) {
+ p = x2nmodp((n * w + 3 - k) << 3, 0);
+ ltl[k][0] = 0;
+ big[w - 1 - k][0] = 0;
+ for (i = 1; i < 256; i++) {
+ ltl[k][i] = q = multmodp(i << 24, p);
+ big[w - 1 - k][i] = byte_swap(q);
+ }
+ }
+}
+#endif
+
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
- * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
*/
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Routines used for CRC calculation. Some are also required for the table
+ * generation above.
+ */
+
+/*
+ Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+ reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(a, b)
+ z_crc_t a;
+ z_crc_t b;
+{
+ z_crc_t m, p;
+
+ m = (z_crc_t)1 << 31;
+ p = 0;
+ for (;;) {
+ if (a & m) {
+ p ^= b;
+ if ((a & (m - 1)) == 0)
+ break;
+ }
+ m >>= 1;
+ b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+ }
+ return p;
+}
+
+/*
+ Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+ initialized.
+ */
+local z_crc_t x2nmodp(n, k)
+ z_off64_t n;
+ unsigned k;
+{
+ z_crc_t p;
+
+ p = (z_crc_t)1 << 31; /* x^0 == 1 */
+ while (n) {
+ if (n & 1)
+ p = multmodp(x2n_table[k & 31], p);
+ n >>= 1;
+ k++;
+ }
+ return p;
+}
+
/* =========================================================================
- * This function can be used by asm versions of crc32()
+ * This function can be used by asm versions of crc32(), and to force the
+ * generation of the CRC tables in a threaded application.
*/
const z_crc_t FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
- if (crc_table_empty)
- make_crc_table();
+ once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
return (const z_crc_t FAR *)crc_table;
}
-/* ========================================================================= */
-#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
-#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+/* =========================================================================
+ * Use ARM machine instructions if available. This will compute the CRC about
+ * ten times faster than the braided calculation. This code does not check for
+ * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
+ * only be defined if the compilation specifies an ARM processor architecture
+ * that has the instructions. For example, compiling with -march=armv8.1-a or
+ * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
+ * instructions.
+ */
+#ifdef ARMCRC32
+
+/*
+ Constants empirically determined to maximize speed. These values are from
+ measurements on a Cortex-A57. Your mileage may vary.
+ */
+#define Z_BATCH 3990 /* number of words in a batch */
+#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
+#define Z_BATCH_MIN 800 /* fewest words in a final batch */
-/* ========================================================================= */
unsigned long ZEXPORT crc32_z(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
z_size_t len;
{
- if (buf == Z_NULL) return 0UL;
+ z_crc_t val;
+ z_word_t crc1, crc2;
+ const z_word_t *word;
+ z_word_t val0, val1, val2;
+ z_size_t last, last2, i;
+ z_size_t num;
+
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
#ifdef DYNAMIC_CRC_TABLE
- if (crc_table_empty)
- make_crc_table();
+ once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
-#ifdef BYFOUR
- if (sizeof(void *) == sizeof(ptrdiff_t)) {
- z_crc_t endian;
+ /* Pre-condition the CRC */
+ crc ^= 0xffffffff;
- endian = 1;
- if (*((unsigned char *)(&endian)))
- return crc32_little(crc, buf, len);
- else
- return crc32_big(crc, buf, len);
+ /* Compute the CRC up to a word boundary. */
+ while (len && ((z_size_t)buf & 7) != 0) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
}
-#endif /* BYFOUR */
- crc = crc ^ 0xffffffffUL;
- while (len >= 8) {
- DO8;
- len -= 8;
+
+ /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
+ word = (z_word_t const *)buf;
+ num = len >> 3;
+ len &= 7;
+
+ /* Do three interleaved CRCs to realize the throughput of one crc32x
+ instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three
+ CRCs are combined into a single CRC after each set of batches. */
+ while (num >= 3 * Z_BATCH) {
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < Z_BATCH; i++) {
+ val0 = word[i];
+ val1 = word[i + Z_BATCH];
+ val2 = word[i + 2 * Z_BATCH];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * Z_BATCH;
+ num -= 3 * Z_BATCH;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
}
- if (len) do {
- DO1;
- } while (--len);
- return crc ^ 0xffffffffUL;
-}
-/* ========================================================================= */
-unsigned long ZEXPORT crc32(crc, buf, len)
- unsigned long crc;
- const unsigned char FAR *buf;
- uInt len;
-{
- return crc32_z(crc, buf, len);
+ /* Do one last smaller batch with the remaining words, if there are enough
+ to pay for the combination of CRCs. */
+ last = num / 3;
+ if (last >= Z_BATCH_MIN) {
+ last2 = last << 1;
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < last; i++) {
+ val0 = word[i];
+ val1 = word[i + last];
+ val2 = word[i + last2];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * last;
+ num -= 3 * last;
+ val = x2nmodp(last, 6);
+ crc = multmodp(val, crc) ^ crc1;
+ crc = multmodp(val, crc) ^ crc2;
+ }
+
+ /* Compute the CRC on any remaining words. */
+ for (i = 0; i < num; i++) {
+ val0 = word[i];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ }
+ word += num;
+
+ /* Complete the CRC on any remaining bytes. */
+ buf = (const unsigned char FAR *)word;
+ while (len) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
}
-#ifdef BYFOUR
+#else
+
+#ifdef W
/*
- This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
- integer pointer type. This violates the strict aliasing rule, where a
- compiler can assume, for optimization purposes, that two pointers to
- fundamentally different types won't ever point to the same memory. This can
- manifest as a problem only if one of the pointers is written to. This code
- only reads from those pointers. So long as this code remains isolated in
- this compilation unit, there won't be a problem. For this reason, this code
- should not be copied and pasted into a compilation unit in which other code
- writes to the buffer that is passed to these routines.
+ Return the CRC of the W bytes in the word_t data, taking the
+ least-significant byte of the word as the first byte of data, without any pre
+ or post conditioning. This is used to combine the CRCs of each braid.
*/
+local z_crc_t crc_word(data)
+ z_word_t data;
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data >> 8) ^ crc_table[data & 0xff];
+ return (z_crc_t)data;
+}
-/* ========================================================================= */
-#define DOLIT4 c ^= *buf4++; \
- c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
- crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
-#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+local z_word_t crc_word_big(data)
+ z_word_t data;
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data << 8) ^
+ crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
+ return data;
+}
+
+#endif
/* ========================================================================= */
-local unsigned long crc32_little(crc, buf, len)
+unsigned long ZEXPORT crc32_z(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
z_size_t len;
{
- register z_crc_t c;
- register const z_crc_t FAR *buf4;
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
- c = (z_crc_t)crc;
- c = ~c;
- while (len && ((ptrdiff_t)buf & 3)) {
- c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
- len--;
- }
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
- buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
- while (len >= 32) {
- DOLIT32;
- len -= 32;
- }
- while (len >= 4) {
- DOLIT4;
- len -= 4;
- }
- buf = (const unsigned char FAR *)buf4;
+ /* Pre-condition the CRC */
+ crc ^= 0xffffffff;
- if (len) do {
- c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
- } while (--len);
- c = ~c;
- return (unsigned long)c;
-}
+#ifdef W
-/* ========================================================================= */
-#define DOBIG4 c ^= *buf4++; \
- c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
- crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
-#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+ /* If provided enough bytes, do a braided CRC calculation. */
+ if (len >= N * W + W - 1) {
+ z_size_t blks;
+ z_word_t const *words;
+ unsigned endian;
+ int k;
-/* ========================================================================= */
-local unsigned long crc32_big(crc, buf, len)
- unsigned long crc;
- const unsigned char FAR *buf;
- z_size_t len;
-{
- register z_crc_t c;
- register const z_crc_t FAR *buf4;
+ /* Compute the CRC up to a z_word_t boundary. */
+ while (len && ((z_size_t)buf & (W - 1)) != 0) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
- c = ZSWAP32((z_crc_t)crc);
- c = ~c;
- while (len && ((ptrdiff_t)buf & 3)) {
- c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
- len--;
+ /* Compute the CRC on as many N z_word_t blocks as are available. */
+ blks = len / (N * W);
+ len -= blks * N * W;
+ words = (z_word_t const *)buf;
+
+ /* Do endian check at execution time instead of compile time, since ARM
+ processors can change the endianess at execution time. If the
+ compiler knows what the endianess will be, it can optimize out the
+ check and the unused branch. */
+ endian = 1;
+ if (*(unsigned char *)&endian) {
+ /* Little endian. */
+
+ z_crc_t crc0;
+ z_word_t word0;
+#if N > 1
+ z_crc_t crc1;
+ z_word_t word1;
+#if N > 2
+ z_crc_t crc2;
+ z_word_t word2;
+#if N > 3
+ z_crc_t crc3;
+ z_word_t word3;
+#if N > 4
+ z_crc_t crc4;
+ z_word_t word4;
+#if N > 5
+ z_crc_t crc5;
+ z_word_t word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = crc;
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ crc = crc_word(crc0 ^ words[0]);
+#if N > 1
+ crc = crc_word(crc1 ^ words[1] ^ crc);
+#if N > 2
+ crc = crc_word(crc2 ^ words[2] ^ crc);
+#if N > 3
+ crc = crc_word(crc3 ^ words[3] ^ crc);
+#if N > 4
+ crc = crc_word(crc4 ^ words[4] ^ crc);
+#if N > 5
+ crc = crc_word(crc5 ^ words[5] ^ crc);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ }
+ else {
+ /* Big endian. */
+
+ z_word_t crc0, word0, comb;
+#if N > 1
+ z_word_t crc1, word1;
+#if N > 2
+ z_word_t crc2, word2;
+#if N > 3
+ z_word_t crc3, word3;
+#if N > 4
+ z_word_t crc4, word4;
+#if N > 5
+ z_word_t crc5, word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = byte_swap(crc);
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_big_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_big_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_big_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_big_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_big_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_big_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ comb = crc_word_big(crc0 ^ words[0]);
+#if N > 1
+ comb = crc_word_big(crc1 ^ words[1] ^ comb);
+#if N > 2
+ comb = crc_word_big(crc2 ^ words[2] ^ comb);
+#if N > 3
+ comb = crc_word_big(crc3 ^ words[3] ^ comb);
+#if N > 4
+ comb = crc_word_big(crc4 ^ words[4] ^ comb);
+#if N > 5
+ comb = crc_word_big(crc5 ^ words[5] ^ comb);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ crc = byte_swap(comb);
+ }
+
+ /*
+ Update the pointer to the remaining bytes to process.
+ */
+ buf = (unsigned char const *)words;
}
- buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
- while (len >= 32) {
- DOBIG32;
- len -= 32;
+#endif /* W */
+
+ /* Complete the computation of the CRC on any remaining bytes. */
+ while (len >= 8) {
+ len -= 8;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
}
- while (len >= 4) {
- DOBIG4;
- len -= 4;
+ while (len) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
}
- buf = (const unsigned char FAR *)buf4;
- if (len) do {
- c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
- } while (--len);
- c = ~c;
- return (unsigned long)(ZSWAP32(c));
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
}
-#endif /* BYFOUR */
-
-#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+#endif
/* ========================================================================= */
-local unsigned long gf2_matrix_times(mat, vec)
- unsigned long *mat;
- unsigned long vec;
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ uInt len;
{
- unsigned long sum;
-
- sum = 0;
- while (vec) {
- if (vec & 1)
- sum ^= *mat;
- vec >>= 1;
- mat++;
- }
- return sum;
+ return crc32_z(crc, buf, len);
}
/* ========================================================================= */
-local void gf2_matrix_square(square, mat)
- unsigned long *square;
- unsigned long *mat;
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off64_t len2;
{
- int n;
-
- for (n = 0; n < GF2_DIM; n++)
- square[n] = gf2_matrix_times(mat, mat[n]);
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return multmodp(x2nmodp(len2, 3), crc1) ^ crc2;
}
/* ========================================================================= */
-local uLong crc32_combine_(crc1, crc2, len2)
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
- z_off64_t len2;
+ z_off_t len2;
{
- int n;
- unsigned long row;
- unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
- unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
-
- /* degenerate case (also disallow negative lengths) */
- if (len2 <= 0)
- return crc1;
-
- /* put operator for one zero bit in odd */
- odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
- row = 1;
- for (n = 1; n < GF2_DIM; n++) {
- odd[n] = row;
- row <<= 1;
- }
+ return crc32_combine64(crc1, crc2, len2);
+}
- /* put operator for two zero bits in even */
- gf2_matrix_square(even, odd);
-
- /* put operator for four zero bits in odd */
- gf2_matrix_square(odd, even);
-
- /* apply len2 zeros to crc1 (first square will put the operator for one
- zero byte, eight zero bits, in even) */
- do {
- /* apply zeros operator for this bit of len2 */
- gf2_matrix_square(even, odd);
- if (len2 & 1)
- crc1 = gf2_matrix_times(even, crc1);
- len2 >>= 1;
-
- /* if no more bits set, then done */
- if (len2 == 0)
- break;
-
- /* another iteration of the loop with odd and even swapped */
- gf2_matrix_square(odd, even);
- if (len2 & 1)
- crc1 = gf2_matrix_times(odd, crc1);
- len2 >>= 1;
-
- /* if no more bits set, then done */
- } while (len2 != 0);
-
- /* return combined crc */
- crc1 ^= crc2;
- return crc1;
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen64(len2)
+ z_off64_t len2;
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return x2nmodp(len2, 3);
}
/* ========================================================================= */
-uLong ZEXPORT crc32_combine(crc1, crc2, len2)
- uLong crc1;
- uLong crc2;
+uLong ZEXPORT crc32_combine_gen(len2)
z_off_t len2;
{
- return crc32_combine_(crc1, crc2, len2);
+ return crc32_combine_gen64(len2);
}
-uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+/* ========================================================================= */
+uLong crc32_combine_op(crc1, crc2, op)
uLong crc1;
uLong crc2;
- z_off64_t len2;
+ uLong op;
{
- return crc32_combine_(crc1, crc2, len2);
+ return multmodp(op, crc1) ^ crc2;
}
diff --git a/erts/emulator/zlib/crc32.h b/erts/emulator/zlib/crc32.h
index 9e0c778102..137df68d61 100644
--- a/erts/emulator/zlib/crc32.h
+++ b/erts/emulator/zlib/crc32.h
@@ -2,440 +2,9445 @@
* Generated automatically by crc32.c
*/
-local const z_crc_t FAR crc_table[TBLS][256] =
-{
- {
- 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
- 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
- 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
- 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
- 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
- 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
- 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
- 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
- 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
- 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
- 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
- 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
- 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
- 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
- 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
- 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
- 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
- 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
- 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
- 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
- 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
- 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
- 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
- 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
- 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
- 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
- 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
- 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
- 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
- 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
- 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
- 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
- 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
- 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
- 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
- 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
- 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
- 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
- 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
- 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
- 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
- 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
- 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
- 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
- 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
- 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
- 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
- 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
- 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
- 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
- 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
- 0x2d02ef8dUL
-#ifdef BYFOUR
- },
- {
- 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
- 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
- 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
- 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
- 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
- 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
- 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
- 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
- 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
- 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
- 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
- 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
- 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
- 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
- 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
- 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
- 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
- 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
- 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
- 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
- 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
- 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
- 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
- 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
- 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
- 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
- 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
- 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
- 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
- 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
- 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
- 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
- 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
- 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
- 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
- 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
- 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
- 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
- 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
- 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
- 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
- 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
- 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
- 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
- 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
- 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
- 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
- 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
- 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
- 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
- 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
- 0x9324fd72UL
- },
- {
- 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
- 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
- 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
- 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
- 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
- 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
- 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
- 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
- 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
- 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
- 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
- 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
- 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
- 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
- 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
- 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
- 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
- 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
- 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
- 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
- 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
- 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
- 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
- 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
- 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
- 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
- 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
- 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
- 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
- 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
- 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
- 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
- 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
- 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
- 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
- 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
- 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
- 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
- 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
- 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
- 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
- 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
- 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
- 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
- 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
- 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
- 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
- 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
- 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
- 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
- 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
- 0xbe9834edUL
- },
- {
- 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
- 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
- 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
- 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
- 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
- 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
- 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
- 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
- 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
- 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
- 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
- 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
- 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
- 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
- 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
- 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
- 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
- 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
- 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
- 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
- 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
- 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
- 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
- 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
- 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
- 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
- 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
- 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
- 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
- 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
- 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
- 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
- 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
- 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
- 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
- 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
- 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
- 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
- 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
- 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
- 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
- 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
- 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
- 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
- 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
- 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
- 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
- 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
- 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
- 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
- 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
- 0xde0506f1UL
- },
- {
- 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
- 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
- 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
- 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
- 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
- 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
- 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
- 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
- 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
- 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
- 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
- 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
- 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
- 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
- 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
- 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
- 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
- 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
- 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
- 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
- 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
- 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
- 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
- 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
- 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
- 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
- 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
- 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
- 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
- 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
- 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
- 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
- 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
- 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
- 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
- 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
- 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
- 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
- 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
- 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
- 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
- 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
- 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
- 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
- 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
- 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
- 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
- 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
- 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
- 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
- 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
- 0x8def022dUL
- },
- {
- 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
- 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
- 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
- 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
- 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
- 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
- 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
- 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
- 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
- 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
- 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
- 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
- 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
- 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
- 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
- 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
- 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
- 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
- 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
- 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
- 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
- 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
- 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
- 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
- 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
- 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
- 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
- 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
- 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
- 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
- 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
- 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
- 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
- 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
- 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
- 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
- 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
- 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
- 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
- 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
- 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
- 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
- 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
- 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
- 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
- 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
- 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
- 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
- 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
- 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
- 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
- 0x72fd2493UL
- },
- {
- 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
- 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
- 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
- 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
- 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
- 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
- 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
- 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
- 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
- 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
- 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
- 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
- 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
- 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
- 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
- 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
- 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
- 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
- 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
- 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
- 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
- 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
- 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
- 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
- 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
- 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
- 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
- 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
- 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
- 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
- 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
- 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
- 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
- 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
- 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
- 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
- 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
- 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
- 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
- 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
- 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
- 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
- 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
- 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
- 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
- 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
- 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
- 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
- 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
- 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
- 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
- 0xed3498beUL
- },
- {
- 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
- 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
- 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
- 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
- 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
- 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
- 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
- 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
- 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
- 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
- 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
- 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
- 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
- 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
- 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
- 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
- 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
- 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
- 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
- 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
- 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
- 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
- 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
- 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
- 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
- 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
- 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
- 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
- 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
- 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
- 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
- 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
- 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
- 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
- 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
- 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
- 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
- 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
- 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
- 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
- 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
- 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
- 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
- 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
- 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
- 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
- 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
- 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
- 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
- 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
- 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
- 0xf10605deUL
+local const z_crc_t FAR crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d};
+
+#ifdef W
+
+#if W == 8
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000};
+
+#else /* W == 4 */
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d};
+
+#endif
+
+#if N == 1
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c},
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000},
+ {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
+ 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
+ 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
+ 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
+ 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
+ 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
+ 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
+ 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
+ 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
+ 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
+ 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
+ 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
+ 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
+ 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
+ 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
+ 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
+ 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
+ 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
+ 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
+ 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
+ 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
+ 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
+ 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
+ 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
+ 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
+ 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
+ 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
+ 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
+ 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
+ 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
+ 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
+ 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
+ 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
+ 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
+ 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
+ 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
+ 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
+ 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
+ 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
+ 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
+ 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
+ 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
+ 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
+ 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
+ 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
+ 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
+ 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
+ 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
+ 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
+ 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
+ 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
+ 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
+ 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
+ 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
+ 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
+ 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
+ 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
+ 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
+ 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
+ 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
+ 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
+ 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
+ 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
+ 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
+ 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
+ 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
+ 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
+ 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
+ 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
+ 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
+ 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
+ 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
+ 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
+ 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
+ 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
+ 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
+ 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
+ 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
+ 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
+ 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
+ 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
+ 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
+ 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
+ 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
+ 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
+ 0x72fd249300000000},
+ {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
+ 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
+ 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
+ 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
+ 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
+ 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
+ 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
+ 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
+ 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
+ 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
+ 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
+ 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
+ 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
+ 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
+ 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
+ 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
+ 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
+ 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
+ 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
+ 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
+ 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
+ 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
+ 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
+ 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
+ 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
+ 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
+ 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
+ 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
+ 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
+ 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
+ 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
+ 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
+ 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
+ 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
+ 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
+ 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
+ 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
+ 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
+ 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
+ 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
+ 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
+ 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
+ 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
+ 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
+ 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
+ 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
+ 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
+ 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
+ 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
+ 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
+ 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
+ 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
+ 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
+ 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
+ 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
+ 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
+ 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
+ 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
+ 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
+ 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
+ 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
+ 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
+ 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
+ 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
+ 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
+ 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
+ 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
+ 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
+ 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
+ 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
+ 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
+ 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
+ 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
+ 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
+ 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
+ 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
+ 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
+ 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
+ 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
+ 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
+ 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
+ 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
+ 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
+ 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
+ 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
+ 0xed3498be00000000},
+ {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
+ 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
+ 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
+ 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
+ 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
+ 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
+ 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
+ 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
+ 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
+ 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
+ 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
+ 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
+ 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
+ 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
+ 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
+ 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
+ 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
+ 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
+ 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
+ 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
+ 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
+ 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
+ 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
+ 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
+ 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
+ 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
+ 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
+ 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
+ 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
+ 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
+ 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
+ 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
+ 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
+ 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
+ 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
+ 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
+ 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
+ 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
+ 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
+ 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
+ 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
+ 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
+ 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
+ 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
+ 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
+ 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
+ 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
+ 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
+ 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
+ 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
+ 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
+ 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
+ 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
+ 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
+ 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
+ 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
+ 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
+ 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
+ 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
+ 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
+ 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
+ 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
+ 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
+ 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
+ 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
+ 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
+ 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
+ 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
+ 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
+ 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
+ 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
+ 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
+ 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
+ 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
+ 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
+ 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
+ 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
+ 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
+ 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
+ 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
+ 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
+ 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
+ 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
+ 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
+ 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
+ 0xf10605de00000000},
+ {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
+ 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
+ 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
+ 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
+ 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
+ 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
+ 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
+ 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
+ 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
+ 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
+ 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
+ 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
+ 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
+ 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
+ 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
+ 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
+ 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
+ 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
+ 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
+ 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
+ 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
+ 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
+ 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
+ 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
+ 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
+ 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
+ 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
+ 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
+ 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
+ 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
+ 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
+ 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
+ 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
+ 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
+ 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
+ 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
+ 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
+ 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
+ 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
+ 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
+ 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
+ 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
+ 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
+ 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
+ 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
+ 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
+ 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
+ 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
+ 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
+ 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
+ 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
+ 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
+ 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
+ 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
+ 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
+ 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
+ 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
+ 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
+ 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
+ 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
+ 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
+ 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
+ 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
+ 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
+ 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
+ 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
+ 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
+ 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
+ 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
+ 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
+ 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
+ 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
+ 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
+ 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
+ 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
+ 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
+ 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
+ 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
+ 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
+ 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
+ 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
+ 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
+ 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
+ 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
+ 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
+ 0x8cc764ca00000000},
+ {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
+ 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
+ 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
+ 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
+ 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
+ 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
+ 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
+ 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
+ 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
+ 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
+ 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
+ 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
+ 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
+ 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
+ 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
+ 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
+ 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
+ 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
+ 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
+ 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
+ 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
+ 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
+ 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
+ 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
+ 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
+ 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
+ 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
+ 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
+ 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
+ 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
+ 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
+ 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
+ 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
+ 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
+ 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
+ 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
+ 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
+ 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
+ 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
+ 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
+ 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
+ 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
+ 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
+ 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
+ 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
+ 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
+ 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
+ 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
+ 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
+ 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
+ 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
+ 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
+ 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
+ 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
+ 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
+ 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
+ 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
+ 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
+ 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
+ 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
+ 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
+ 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
+ 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
+ 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
+ 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
+ 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
+ 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
+ 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
+ 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
+ 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
+ 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
+ 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
+ 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
+ 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
+ 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
+ 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
+ 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
+ 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
+ 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
+ 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
+ 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
+ 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
+ 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
+ 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
+ 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
+ 0xccabc4e400000000},
+ {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
+ 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
+ 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
+ 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
+ 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
+ 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
+ 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
+ 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
+ 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
+ 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
+ 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
+ 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
+ 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
+ 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
+ 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
+ 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
+ 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
+ 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
+ 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
+ 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
+ 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
+ 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
+ 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
+ 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
+ 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
+ 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
+ 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
+ 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
+ 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
+ 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
+ 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
+ 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
+ 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
+ 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
+ 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
+ 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
+ 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
+ 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
+ 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
+ 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
+ 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
+ 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
+ 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
+ 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
+ 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
+ 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
+ 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
+ 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
+ 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
+ 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
+ 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
+ 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
+ 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
+ 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
+ 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
+ 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
+ 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
+ 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
+ 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
+ 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
+ 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
+ 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
+ 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
+ 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
+ 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
+ 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
+ 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
+ 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
+ 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
+ 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
+ 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
+ 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
+ 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
+ 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
+ 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
+ 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
+ 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
+ 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
+ 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
+ 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
+ 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
+ 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
+ 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
+ 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
+ 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
+ 0x304a369200000000},
+ {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
+ 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
+ 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
+ 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
+ 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
+ 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
+ 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
+ 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
+ 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
+ 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
+ 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
+ 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
+ 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
+ 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
+ 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
+ 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
+ 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
+ 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
+ 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
+ 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
+ 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
+ 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
+ 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
+ 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
+ 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
+ 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
+ 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
+ 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
+ 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
+ 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
+ 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
+ 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
+ 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
+ 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
+ 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
+ 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
+ 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
+ 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
+ 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
+ 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
+ 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
+ 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
+ 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
+ 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
+ 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
+ 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
+ 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
+ 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
+ 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
+ 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
+ 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
+ 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
+ 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
+ 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
+ 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
+ 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
+ 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
+ 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
+ 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
+ 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
+ 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
+ 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
+ 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
+ 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
+ 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
+ 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
+ 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
+ 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
+ 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
+ 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
+ 0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
+ 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
+ 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
+ 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
+ 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
+ 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
+ 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
+ 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
+ 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
+ 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
+ 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
+ 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
+ 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
+ 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
+ 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
+ 0xe6064b2600000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d},
+ {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
+ 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
+ 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
+ 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
+ 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
+ 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
+ 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
+ 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
+ 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
+ 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
+ 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
+ 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
+ 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
+ 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
+ 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
+ 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
+ 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
+ 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
+ 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
+ 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
+ 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
+ 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
+ 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
+ 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
+ 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
+ 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
+ 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
+ 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
+ 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
+ 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
+ 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
+ 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
+ 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
+ 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
+ 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
+ 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
+ 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
+ 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
+ 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
+ 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
+ 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
+ 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
+ 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
+ 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
+ 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
+ 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
+ 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
+ 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
+ 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
+ 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
+ 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
+ 0x72fd2493},
+ {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
+ 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
+ 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
+ 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
+ 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
+ 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
+ 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
+ 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
+ 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
+ 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
+ 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
+ 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
+ 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
+ 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
+ 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
+ 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
+ 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
+ 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
+ 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
+ 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
+ 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
+ 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
+ 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
+ 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
+ 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
+ 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
+ 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
+ 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
+ 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
+ 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
+ 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
+ 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
+ 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
+ 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
+ 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
+ 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
+ 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
+ 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
+ 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
+ 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
+ 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
+ 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
+ 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
+ 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
+ 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
+ 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
+ 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
+ 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
+ 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
+ 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
+ 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
+ 0xed3498be},
+ {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
+ 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
+ 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
+ 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
+ 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
+ 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
+ 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
+ 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
+ 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
+ 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
+ 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
+ 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
+ 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
+ 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
+ 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
+ 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
+ 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
+ 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
+ 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
+ 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
+ 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
+ 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
+ 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
+ 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
+ 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
+ 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
+ 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
+ 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
+ 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
+ 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
+ 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
+ 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
+ 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
+ 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
+ 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
+ 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
+ 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
+ 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
+ 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
+ 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
+ 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
+ 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
+ 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
+ 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
+ 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
+ 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
+ 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
+ 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
+ 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
+ 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
+ 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
+ 0xf10605de}};
+
+#endif
+
+#endif
+
+#if N == 2
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6},
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
+ 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
+ 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
+ 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
+ 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
+ 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
+ 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
+ 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
+ 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
+ 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
+ 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
+ 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
+ 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
+ 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
+ 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
+ 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
+ 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
+ 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
+ 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
+ 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
+ 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
+ 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
+ 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
+ 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
+ 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
+ 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
+ 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
+ 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
+ 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
+ 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
+ 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
+ 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
+ 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
+ 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
+ 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
+ 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
+ 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
+ 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
+ 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
+ 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
+ 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
+ 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
+ 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
+ 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
+ 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
+ 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
+ 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
+ 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
+ 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
+ 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
+ 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
+ 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
+ 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
+ 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
+ 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
+ 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
+ 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
+ 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
+ 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
+ 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
+ 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
+ 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
+ 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
+ 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
+ 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
+ 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
+ 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
+ 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
+ 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
+ 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
+ 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
+ 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
+ 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
+ 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
+ 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
+ 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
+ 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
+ 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
+ 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
+ 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
+ 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
+ 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
+ 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
+ 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
+ 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
+ 0x4b0c4f4900000000},
+ {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
+ 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
+ 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
+ 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
+ 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
+ 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
+ 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
+ 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
+ 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
+ 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
+ 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
+ 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
+ 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
+ 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
+ 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
+ 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
+ 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
+ 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
+ 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
+ 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
+ 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
+ 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
+ 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
+ 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
+ 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
+ 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
+ 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
+ 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
+ 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
+ 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
+ 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
+ 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
+ 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
+ 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
+ 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
+ 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
+ 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
+ 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
+ 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
+ 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
+ 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
+ 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
+ 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
+ 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
+ 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
+ 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
+ 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
+ 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
+ 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
+ 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
+ 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
+ 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
+ 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
+ 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
+ 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
+ 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
+ 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
+ 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
+ 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
+ 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
+ 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
+ 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
+ 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
+ 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
+ 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
+ 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
+ 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
+ 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
+ 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
+ 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
+ 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
+ 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
+ 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
+ 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
+ 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
+ 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
+ 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
+ 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
+ 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
+ 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
+ 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
+ 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
+ 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
+ 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
+ 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
+ 0x14d747e100000000},
+ {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
+ 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
+ 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
+ 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
+ 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
+ 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
+ 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
+ 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
+ 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
+ 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
+ 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
+ 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
+ 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
+ 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
+ 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
+ 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
+ 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
+ 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
+ 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
+ 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
+ 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
+ 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
+ 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
+ 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
+ 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
+ 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
+ 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
+ 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
+ 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
+ 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
+ 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
+ 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
+ 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
+ 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
+ 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
+ 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
+ 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
+ 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
+ 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
+ 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
+ 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
+ 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
+ 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
+ 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
+ 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
+ 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
+ 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
+ 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
+ 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
+ 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
+ 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
+ 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
+ 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
+ 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
+ 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
+ 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
+ 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
+ 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
+ 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
+ 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
+ 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
+ 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
+ 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
+ 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
+ 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
+ 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
+ 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
+ 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
+ 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
+ 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
+ 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
+ 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
+ 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
+ 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
+ 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
+ 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
+ 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
+ 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
+ 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
+ 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
+ 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
+ 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
+ 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
+ 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
+ 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
+ 0xaa933b1a00000000},
+ {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
+ 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
+ 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
+ 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
+ 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
+ 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
+ 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
+ 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
+ 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
+ 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
+ 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
+ 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
+ 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
+ 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
+ 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
+ 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
+ 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
+ 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
+ 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
+ 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
+ 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
+ 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
+ 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
+ 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
+ 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
+ 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
+ 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
+ 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
+ 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
+ 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
+ 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
+ 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
+ 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
+ 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
+ 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
+ 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
+ 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
+ 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
+ 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
+ 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
+ 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
+ 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
+ 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
+ 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
+ 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
+ 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
+ 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
+ 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
+ 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
+ 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
+ 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
+ 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
+ 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
+ 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
+ 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
+ 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
+ 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
+ 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
+ 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
+ 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
+ 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
+ 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
+ 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
+ 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
+ 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
+ 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
+ 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
+ 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
+ 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
+ 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
+ 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
+ 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
+ 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
+ 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
+ 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
+ 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
+ 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
+ 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
+ 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
+ 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
+ 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
+ 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
+ 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
+ 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
+ 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
+ 0x6571193600000000},
+ {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
+ 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
+ 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
+ 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
+ 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
+ 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
+ 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
+ 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
+ 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
+ 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
+ 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
+ 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
+ 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
+ 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
+ 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
+ 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
+ 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
+ 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
+ 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
+ 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
+ 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
+ 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
+ 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
+ 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
+ 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
+ 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
+ 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
+ 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
+ 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
+ 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
+ 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
+ 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
+ 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
+ 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
+ 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
+ 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
+ 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
+ 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
+ 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
+ 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
+ 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
+ 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
+ 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
+ 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
+ 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
+ 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
+ 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
+ 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
+ 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
+ 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
+ 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
+ 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
+ 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
+ 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
+ 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
+ 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
+ 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
+ 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
+ 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
+ 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
+ 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
+ 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
+ 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
+ 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
+ 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
+ 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
+ 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
+ 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
+ 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
+ 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
+ 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
+ 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
+ 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
+ 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
+ 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
+ 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
+ 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
+ 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
+ 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
+ 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
+ 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
+ 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
+ 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
+ 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
+ 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
+ 0xa68cee3d00000000},
+ {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
+ 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
+ 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
+ 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
+ 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
+ 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
+ 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
+ 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
+ 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
+ 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
+ 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
+ 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
+ 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
+ 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
+ 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
+ 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
+ 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
+ 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
+ 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
+ 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
+ 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
+ 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
+ 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
+ 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
+ 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
+ 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
+ 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
+ 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
+ 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
+ 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
+ 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
+ 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
+ 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
+ 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
+ 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
+ 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
+ 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
+ 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
+ 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
+ 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
+ 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
+ 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
+ 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
+ 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
+ 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
+ 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
+ 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
+ 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
+ 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
+ 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
+ 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
+ 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
+ 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
+ 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
+ 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
+ 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
+ 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
+ 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
+ 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
+ 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
+ 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
+ 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
+ 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
+ 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
+ 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
+ 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
+ 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
+ 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
+ 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
+ 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
+ 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
+ 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
+ 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
+ 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
+ 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
+ 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
+ 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
+ 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
+ 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
+ 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
+ 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
+ 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
+ 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
+ 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
+ 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
+ 0x51e8883f00000000},
+ {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
+ 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
+ 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
+ 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
+ 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
+ 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
+ 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
+ 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
+ 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
+ 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
+ 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
+ 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
+ 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
+ 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
+ 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
+ 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
+ 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
+ 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
+ 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
+ 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
+ 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
+ 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
+ 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
+ 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
+ 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
+ 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
+ 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
+ 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
+ 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
+ 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
+ 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
+ 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
+ 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
+ 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
+ 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
+ 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
+ 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
+ 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
+ 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
+ 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
+ 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
+ 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
+ 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
+ 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
+ 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
+ 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
+ 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
+ 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
+ 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
+ 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
+ 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
+ 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
+ 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
+ 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
+ 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
+ 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
+ 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
+ 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
+ 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
+ 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
+ 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
+ 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
+ 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
+ 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
+ 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
+ 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
+ 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
+ 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
+ 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
+ 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
+ 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
+ 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
+ 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
+ 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
+ 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
+ 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
+ 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
+ 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
+ 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
+ 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
+ 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
+ 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
+ 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
+ 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
+ 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
+ 0x8ae9531c00000000},
+ {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
+ 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
+ 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
+ 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
+ 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
+ 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
+ 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
+ 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
+ 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
+ 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
+ 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
+ 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
+ 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
+ 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
+ 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
+ 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
+ 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
+ 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
+ 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
+ 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
+ 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
+ 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
+ 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
+ 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
+ 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
+ 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
+ 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
+ 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
+ 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
+ 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
+ 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
+ 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
+ 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
+ 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
+ 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
+ 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
+ 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
+ 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
+ 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
+ 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
+ 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
+ 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
+ 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
+ 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
+ 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
+ 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
+ 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
+ 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
+ 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
+ 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
+ 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
+ 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
+ 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
+ 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
+ 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
+ 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
+ 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
+ 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
+ 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
+ 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
+ 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
+ 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
+ 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
+ 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
+ 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
+ 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
+ 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
+ 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
+ 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
+ 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
+ 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
+ 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
+ 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
+ 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
+ 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
+ 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
+ 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
+ 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
+ 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
+ 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
+ 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
+ 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
+ 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
+ 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
+ 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
+ 0xd739710d00000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
+ 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
+ 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
+ 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
+ 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
+ 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
+ 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
+ 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
+ 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
+ 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
+ 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
+ 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
+ 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
+ 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
+ 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
+ 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
+ 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
+ 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
+ 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
+ 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
+ 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
+ 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
+ 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
+ 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
+ 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
+ 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
+ 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
+ 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
+ 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
+ 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
+ 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
+ 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
+ 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
+ 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
+ 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
+ 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
+ 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
+ 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
+ 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
+ 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
+ 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
+ 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
+ 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
+ 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
+ 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
+ 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
+ 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
+ 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
+ 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
+ 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
+ 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
+ 0x8cc764ca},
+ {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
+ 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
+ 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
+ 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
+ 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
+ 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
+ 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
+ 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
+ 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
+ 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
+ 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
+ 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
+ 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
+ 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
+ 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
+ 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
+ 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
+ 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
+ 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
+ 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
+ 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
+ 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
+ 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
+ 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
+ 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
+ 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
+ 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
+ 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
+ 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
+ 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
+ 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
+ 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
+ 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
+ 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
+ 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
+ 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
+ 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
+ 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
+ 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
+ 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
+ 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
+ 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
+ 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
+ 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
+ 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
+ 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
+ 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
+ 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
+ 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
+ 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
+ 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
+ 0xccabc4e4},
+ {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
+ 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
+ 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
+ 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
+ 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
+ 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
+ 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
+ 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
+ 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
+ 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
+ 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
+ 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
+ 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
+ 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
+ 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
+ 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
+ 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
+ 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
+ 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
+ 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
+ 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
+ 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
+ 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
+ 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
+ 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
+ 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
+ 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
+ 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
+ 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
+ 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
+ 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
+ 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
+ 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
+ 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
+ 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
+ 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
+ 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
+ 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
+ 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
+ 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
+ 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
+ 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
+ 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
+ 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
+ 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
+ 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
+ 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
+ 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
+ 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
+ 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
+ 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
+ 0x304a3692},
+ {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
+ 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
+ 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
+ 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
+ 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
+ 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
+ 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
+ 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
+ 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
+ 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
+ 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
+ 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
+ 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
+ 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
+ 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
+ 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
+ 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
+ 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
+ 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
+ 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
+ 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
+ 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
+ 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
+ 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
+ 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
+ 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
+ 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
+ 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
+ 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
+ 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
+ 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
+ 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
+ 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
+ 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
+ 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
+ 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
+ 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
+ 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
+ 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
+ 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
+ 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
+ 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
+ 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
+ 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
+ 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
+ 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
+ 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
+ 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
+ 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
+ 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
+ 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
+ 0xe6064b26}};
+
#endif
- }
-};
+
+#endif
+
+#if N == 3
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848},
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
+ 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
+ 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
+ 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
+ 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
+ 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
+ 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
+ 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
+ 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
+ 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
+ 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
+ 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
+ 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
+ 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
+ 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
+ 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
+ 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
+ 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
+ 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
+ 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
+ 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
+ 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
+ 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
+ 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
+ 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
+ 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
+ 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
+ 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
+ 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
+ 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
+ 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
+ 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
+ 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
+ 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
+ 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
+ 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
+ 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
+ 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
+ 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
+ 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
+ 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
+ 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
+ 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
+ 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
+ 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
+ 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
+ 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
+ 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
+ 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
+ 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
+ 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
+ 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
+ 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
+ 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
+ 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
+ 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
+ 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
+ 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
+ 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
+ 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
+ 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
+ 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
+ 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
+ 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
+ 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
+ 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
+ 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
+ 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
+ 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
+ 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
+ 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
+ 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
+ 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
+ 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
+ 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
+ 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
+ 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
+ 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
+ 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
+ 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
+ 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
+ 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
+ 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
+ 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
+ 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
+ 0x4e36ba1800000000},
+ {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
+ 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
+ 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
+ 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
+ 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
+ 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
+ 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
+ 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
+ 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
+ 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
+ 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
+ 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
+ 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
+ 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
+ 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
+ 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
+ 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
+ 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
+ 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
+ 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
+ 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
+ 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
+ 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
+ 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
+ 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
+ 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
+ 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
+ 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
+ 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
+ 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
+ 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
+ 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
+ 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
+ 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
+ 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
+ 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
+ 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
+ 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
+ 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
+ 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
+ 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
+ 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
+ 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
+ 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
+ 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
+ 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
+ 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
+ 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
+ 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
+ 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
+ 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
+ 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
+ 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
+ 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
+ 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
+ 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
+ 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
+ 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
+ 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
+ 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
+ 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
+ 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
+ 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
+ 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
+ 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
+ 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
+ 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
+ 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
+ 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
+ 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
+ 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
+ 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
+ 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
+ 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
+ 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
+ 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
+ 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
+ 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
+ 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
+ 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
+ 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
+ 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
+ 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
+ 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
+ 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
+ 0xa1d67c9100000000},
+ {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
+ 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
+ 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
+ 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
+ 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
+ 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
+ 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
+ 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
+ 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
+ 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
+ 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
+ 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
+ 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
+ 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
+ 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
+ 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
+ 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
+ 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
+ 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
+ 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
+ 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
+ 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
+ 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
+ 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
+ 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
+ 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
+ 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
+ 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
+ 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
+ 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
+ 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
+ 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
+ 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
+ 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
+ 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
+ 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
+ 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
+ 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
+ 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
+ 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
+ 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
+ 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
+ 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
+ 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
+ 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
+ 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
+ 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
+ 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
+ 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
+ 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
+ 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
+ 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
+ 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
+ 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
+ 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
+ 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
+ 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
+ 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
+ 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
+ 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
+ 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
+ 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
+ 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
+ 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
+ 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
+ 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
+ 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
+ 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
+ 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
+ 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
+ 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
+ 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
+ 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
+ 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
+ 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
+ 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
+ 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
+ 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
+ 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
+ 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
+ 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
+ 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
+ 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
+ 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
+ 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
+ 0xa8ef40a100000000},
+ {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
+ 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
+ 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
+ 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
+ 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
+ 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
+ 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
+ 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
+ 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
+ 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
+ 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
+ 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
+ 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
+ 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
+ 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
+ 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
+ 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
+ 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
+ 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
+ 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
+ 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
+ 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
+ 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
+ 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
+ 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
+ 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
+ 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
+ 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
+ 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
+ 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
+ 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
+ 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
+ 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
+ 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
+ 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
+ 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
+ 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
+ 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
+ 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
+ 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
+ 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
+ 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
+ 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
+ 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
+ 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
+ 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
+ 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
+ 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
+ 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
+ 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
+ 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
+ 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
+ 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
+ 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
+ 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
+ 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
+ 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
+ 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
+ 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
+ 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
+ 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
+ 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
+ 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
+ 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
+ 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
+ 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
+ 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
+ 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
+ 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
+ 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
+ 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
+ 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
+ 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
+ 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
+ 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
+ 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
+ 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
+ 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
+ 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
+ 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
+ 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
+ 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
+ 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
+ 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
+ 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
+ 0x356bacd800000000},
+ {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
+ 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
+ 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
+ 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
+ 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
+ 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
+ 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
+ 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
+ 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
+ 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
+ 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
+ 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
+ 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
+ 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
+ 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
+ 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
+ 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
+ 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
+ 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
+ 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
+ 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
+ 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
+ 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
+ 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
+ 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
+ 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
+ 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
+ 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
+ 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
+ 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
+ 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
+ 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
+ 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
+ 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
+ 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
+ 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
+ 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
+ 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
+ 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
+ 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
+ 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
+ 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
+ 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
+ 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
+ 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
+ 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
+ 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
+ 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
+ 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
+ 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
+ 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
+ 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
+ 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
+ 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
+ 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
+ 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
+ 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
+ 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
+ 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
+ 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
+ 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
+ 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
+ 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
+ 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
+ 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
+ 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
+ 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
+ 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
+ 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
+ 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
+ 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
+ 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
+ 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
+ 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
+ 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
+ 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
+ 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
+ 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
+ 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
+ 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
+ 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
+ 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
+ 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
+ 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
+ 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
+ 0x48686b5600000000},
+ {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
+ 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
+ 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
+ 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
+ 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
+ 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
+ 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
+ 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
+ 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
+ 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
+ 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
+ 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
+ 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
+ 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
+ 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
+ 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
+ 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
+ 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
+ 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
+ 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
+ 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
+ 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
+ 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
+ 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
+ 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
+ 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
+ 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
+ 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
+ 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
+ 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
+ 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
+ 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
+ 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
+ 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
+ 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
+ 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
+ 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
+ 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
+ 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
+ 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
+ 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
+ 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
+ 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
+ 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
+ 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
+ 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
+ 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
+ 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
+ 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
+ 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
+ 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
+ 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
+ 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
+ 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
+ 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
+ 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
+ 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
+ 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
+ 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
+ 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
+ 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
+ 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
+ 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
+ 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
+ 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
+ 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
+ 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
+ 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
+ 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
+ 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
+ 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
+ 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
+ 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
+ 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
+ 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
+ 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
+ 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
+ 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
+ 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
+ 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
+ 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
+ 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
+ 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
+ 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
+ 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
+ 0xcaa2517800000000},
+ {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
+ 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
+ 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
+ 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
+ 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
+ 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
+ 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
+ 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
+ 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
+ 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
+ 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
+ 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
+ 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
+ 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
+ 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
+ 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
+ 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
+ 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
+ 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
+ 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
+ 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
+ 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
+ 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
+ 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
+ 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
+ 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
+ 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
+ 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
+ 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
+ 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
+ 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
+ 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
+ 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
+ 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
+ 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
+ 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
+ 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
+ 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
+ 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
+ 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
+ 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
+ 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
+ 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
+ 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
+ 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
+ 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
+ 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
+ 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
+ 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
+ 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
+ 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
+ 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
+ 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
+ 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
+ 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
+ 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
+ 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
+ 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
+ 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
+ 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
+ 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
+ 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
+ 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
+ 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
+ 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
+ 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
+ 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
+ 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
+ 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
+ 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
+ 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
+ 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
+ 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
+ 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
+ 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
+ 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
+ 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
+ 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
+ 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
+ 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
+ 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
+ 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
+ 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
+ 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
+ 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
+ 0x0c7ac97b00000000},
+ {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
+ 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
+ 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
+ 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
+ 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
+ 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
+ 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
+ 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
+ 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
+ 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
+ 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
+ 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
+ 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
+ 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
+ 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
+ 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
+ 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
+ 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
+ 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
+ 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
+ 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
+ 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
+ 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
+ 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
+ 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
+ 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
+ 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
+ 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
+ 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
+ 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
+ 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
+ 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
+ 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
+ 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
+ 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
+ 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
+ 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
+ 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
+ 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
+ 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
+ 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
+ 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
+ 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
+ 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
+ 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
+ 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
+ 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
+ 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
+ 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
+ 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
+ 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
+ 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
+ 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
+ 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
+ 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
+ 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
+ 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
+ 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
+ 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
+ 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
+ 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
+ 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
+ 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
+ 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
+ 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
+ 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
+ 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
+ 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
+ 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
+ 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
+ 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
+ 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
+ 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
+ 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
+ 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
+ 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
+ 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
+ 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
+ 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
+ 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
+ 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
+ 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
+ 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
+ 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
+ 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
+ 0x5185cd0900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
+ 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
+ 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
+ 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
+ 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
+ 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
+ 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
+ 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
+ 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
+ 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
+ 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
+ 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
+ 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
+ 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
+ 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
+ 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
+ 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
+ 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
+ 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
+ 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
+ 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
+ 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
+ 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
+ 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
+ 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
+ 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
+ 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
+ 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
+ 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
+ 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
+ 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
+ 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
+ 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
+ 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
+ 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
+ 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
+ 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
+ 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
+ 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
+ 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
+ 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
+ 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
+ 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
+ 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
+ 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
+ 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
+ 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
+ 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
+ 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
+ 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
+ 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
+ 0x4b0c4f49},
+ {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
+ 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
+ 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
+ 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
+ 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
+ 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
+ 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
+ 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
+ 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
+ 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
+ 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
+ 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
+ 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
+ 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
+ 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
+ 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
+ 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
+ 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
+ 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
+ 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
+ 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
+ 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
+ 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
+ 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
+ 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
+ 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
+ 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
+ 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
+ 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
+ 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
+ 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
+ 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
+ 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
+ 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
+ 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
+ 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
+ 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
+ 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
+ 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
+ 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
+ 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
+ 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
+ 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
+ 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
+ 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
+ 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
+ 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
+ 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
+ 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
+ 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
+ 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
+ 0x14d747e1},
+ {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
+ 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
+ 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
+ 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
+ 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
+ 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
+ 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
+ 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
+ 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
+ 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
+ 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
+ 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
+ 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
+ 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
+ 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
+ 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
+ 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
+ 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
+ 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
+ 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
+ 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
+ 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
+ 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
+ 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
+ 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
+ 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
+ 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
+ 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
+ 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
+ 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
+ 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
+ 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
+ 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
+ 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
+ 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
+ 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
+ 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
+ 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
+ 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
+ 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
+ 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
+ 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
+ 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
+ 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
+ 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
+ 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
+ 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
+ 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
+ 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
+ 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
+ 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
+ 0xaa933b1a},
+ {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
+ 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
+ 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
+ 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
+ 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
+ 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
+ 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
+ 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
+ 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
+ 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
+ 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
+ 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
+ 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
+ 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
+ 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
+ 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
+ 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
+ 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
+ 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
+ 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
+ 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
+ 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
+ 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
+ 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
+ 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
+ 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
+ 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
+ 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
+ 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
+ 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
+ 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
+ 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
+ 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
+ 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
+ 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
+ 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
+ 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
+ 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
+ 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
+ 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
+ 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
+ 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
+ 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
+ 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
+ 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
+ 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
+ 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
+ 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
+ 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
+ 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
+ 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
+ 0x65711936}};
+
+#endif
+
+#endif
+
+#if N == 4
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
+ 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
+ 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
+ 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
+ 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
+ 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
+ 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
+ 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
+ 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
+ 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
+ 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
+ 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
+ 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
+ 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
+ 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
+ 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
+ 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
+ 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
+ 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
+ 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
+ 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
+ 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
+ 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
+ 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
+ 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
+ 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
+ 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
+ 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
+ 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
+ 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
+ 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
+ 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
+ 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
+ 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
+ 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
+ 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
+ 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
+ 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
+ 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
+ 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
+ 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
+ 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
+ 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
+ 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
+ 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
+ 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
+ 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
+ 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
+ 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
+ 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
+ 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
+ 0xe3c45916},
+ {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
+ 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
+ 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
+ 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
+ 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
+ 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
+ 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
+ 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
+ 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
+ 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
+ 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
+ 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
+ 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
+ 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
+ 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
+ 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
+ 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
+ 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
+ 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
+ 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
+ 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
+ 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
+ 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
+ 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
+ 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
+ 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
+ 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
+ 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
+ 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
+ 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
+ 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
+ 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
+ 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
+ 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
+ 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
+ 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
+ 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
+ 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
+ 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
+ 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
+ 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
+ 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
+ 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
+ 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
+ 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
+ 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
+ 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
+ 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
+ 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
+ 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
+ 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
+ 0xa7520488},
+ {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
+ 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
+ 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
+ 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
+ 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
+ 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
+ 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
+ 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
+ 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
+ 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
+ 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
+ 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
+ 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
+ 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
+ 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
+ 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
+ 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
+ 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
+ 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
+ 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
+ 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
+ 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
+ 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
+ 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
+ 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
+ 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
+ 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
+ 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
+ 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
+ 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
+ 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
+ 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
+ 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
+ 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
+ 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
+ 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
+ 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
+ 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
+ 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
+ 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
+ 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
+ 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
+ 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
+ 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
+ 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
+ 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
+ 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
+ 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
+ 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
+ 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
+ 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
+ 0x3522e9e4},
+ {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
+ 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
+ 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
+ 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
+ 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
+ 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
+ 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
+ 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
+ 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
+ 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
+ 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
+ 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
+ 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
+ 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
+ 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
+ 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
+ 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
+ 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
+ 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
+ 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
+ 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
+ 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
+ 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
+ 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
+ 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
+ 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
+ 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
+ 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
+ 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
+ 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
+ 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
+ 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
+ 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
+ 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
+ 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
+ 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
+ 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
+ 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
+ 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
+ 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
+ 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
+ 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
+ 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
+ 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
+ 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
+ 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
+ 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
+ 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
+ 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
+ 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
+ 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
+ 0x97411e28},
+ {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
+ 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
+ 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
+ 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
+ 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
+ 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
+ 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
+ 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
+ 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
+ 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
+ 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
+ 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
+ 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
+ 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
+ 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
+ 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
+ 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
+ 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
+ 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
+ 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
+ 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
+ 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
+ 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
+ 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
+ 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
+ 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
+ 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
+ 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
+ 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
+ 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
+ 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
+ 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
+ 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
+ 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
+ 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
+ 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
+ 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
+ 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
+ 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
+ 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
+ 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
+ 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
+ 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
+ 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
+ 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
+ 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
+ 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
+ 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
+ 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
+ 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
+ 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
+ 0x93c7a00b},
+ {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
+ 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
+ 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
+ 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
+ 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
+ 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
+ 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
+ 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
+ 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
+ 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
+ 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
+ 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
+ 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
+ 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
+ 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
+ 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
+ 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
+ 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
+ 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
+ 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
+ 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
+ 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
+ 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
+ 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
+ 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
+ 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
+ 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
+ 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
+ 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
+ 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
+ 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
+ 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
+ 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
+ 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
+ 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
+ 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
+ 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
+ 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
+ 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
+ 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
+ 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
+ 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
+ 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
+ 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
+ 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
+ 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
+ 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
+ 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
+ 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
+ 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
+ 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
+ 0xce5f968d},
+ {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
+ 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
+ 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
+ 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
+ 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
+ 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
+ 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
+ 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
+ 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
+ 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
+ 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
+ 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
+ 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
+ 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
+ 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
+ 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
+ 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
+ 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
+ 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
+ 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
+ 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
+ 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
+ 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
+ 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
+ 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
+ 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
+ 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
+ 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
+ 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
+ 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
+ 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
+ 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
+ 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
+ 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
+ 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
+ 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
+ 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
+ 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
+ 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
+ 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
+ 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
+ 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
+ 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
+ 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
+ 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
+ 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
+ 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
+ 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
+ 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
+ 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
+ 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
+ 0x3e721277},
+ {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
+ 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
+ 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
+ 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
+ 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
+ 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
+ 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
+ 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
+ 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
+ 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
+ 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
+ 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
+ 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
+ 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
+ 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
+ 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
+ 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
+ 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
+ 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
+ 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
+ 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
+ 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
+ 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
+ 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
+ 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
+ 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
+ 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
+ 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
+ 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
+ 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
+ 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
+ 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
+ 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
+ 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
+ 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
+ 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
+ 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
+ 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
+ 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
+ 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
+ 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
+ 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
+ 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
+ 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
+ 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
+ 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
+ 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
+ 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
+ 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
+ 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
+ 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
+ 0x1c65ace7}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
+ 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
+ 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
+ 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
+ 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
+ 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
+ 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
+ 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
+ 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
+ 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
+ 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
+ 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
+ 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
+ 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
+ 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
+ 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
+ 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
+ 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
+ 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
+ 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
+ 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
+ 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
+ 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
+ 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
+ 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
+ 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
+ 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
+ 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
+ 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
+ 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
+ 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
+ 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
+ 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
+ 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
+ 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
+ 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
+ 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
+ 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
+ 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
+ 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
+ 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
+ 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
+ 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
+ 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
+ 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
+ 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
+ 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
+ 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
+ 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
+ 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
+ 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
+ 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
+ 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
+ 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
+ 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
+ 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
+ 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
+ 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
+ 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
+ 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
+ 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
+ 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
+ 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
+ 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
+ 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
+ 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
+ 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
+ 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
+ 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
+ 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
+ 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
+ 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
+ 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
+ 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
+ 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
+ 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
+ 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
+ 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
+ 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
+ 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
+ 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
+ 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
+ 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
+ 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
+ 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
+ 0xe7ac651c00000000},
+ {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
+ 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
+ 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
+ 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
+ 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
+ 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
+ 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
+ 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
+ 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
+ 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
+ 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
+ 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
+ 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
+ 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
+ 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
+ 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
+ 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
+ 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
+ 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
+ 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
+ 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
+ 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
+ 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
+ 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
+ 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
+ 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
+ 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
+ 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
+ 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
+ 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
+ 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
+ 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
+ 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
+ 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
+ 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
+ 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
+ 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
+ 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
+ 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
+ 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
+ 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
+ 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
+ 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
+ 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
+ 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
+ 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
+ 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
+ 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
+ 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
+ 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
+ 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
+ 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
+ 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
+ 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
+ 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
+ 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
+ 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
+ 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
+ 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
+ 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
+ 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
+ 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
+ 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
+ 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
+ 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
+ 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
+ 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
+ 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
+ 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
+ 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
+ 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
+ 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
+ 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
+ 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
+ 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
+ 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
+ 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
+ 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
+ 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
+ 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
+ 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
+ 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
+ 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
+ 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
+ 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
+ 0x7712723e00000000},
+ {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
+ 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
+ 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
+ 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
+ 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
+ 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
+ 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
+ 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
+ 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
+ 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
+ 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
+ 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
+ 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
+ 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
+ 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
+ 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
+ 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
+ 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
+ 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
+ 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
+ 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
+ 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
+ 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
+ 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
+ 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
+ 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
+ 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
+ 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
+ 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
+ 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
+ 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
+ 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
+ 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
+ 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
+ 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
+ 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
+ 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
+ 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
+ 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
+ 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
+ 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
+ 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
+ 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
+ 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
+ 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
+ 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
+ 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
+ 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
+ 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
+ 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
+ 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
+ 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
+ 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
+ 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
+ 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
+ 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
+ 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
+ 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
+ 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
+ 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
+ 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
+ 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
+ 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
+ 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
+ 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
+ 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
+ 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
+ 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
+ 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
+ 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
+ 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
+ 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
+ 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
+ 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
+ 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
+ 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
+ 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
+ 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
+ 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
+ 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
+ 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
+ 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
+ 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
+ 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
+ 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
+ 0x8d965fce00000000},
+ {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
+ 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
+ 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
+ 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
+ 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
+ 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
+ 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
+ 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
+ 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
+ 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
+ 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
+ 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
+ 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
+ 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
+ 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
+ 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
+ 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
+ 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
+ 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
+ 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
+ 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
+ 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
+ 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
+ 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
+ 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
+ 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
+ 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
+ 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
+ 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
+ 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
+ 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
+ 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
+ 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
+ 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
+ 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
+ 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
+ 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
+ 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
+ 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
+ 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
+ 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
+ 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
+ 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
+ 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
+ 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
+ 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
+ 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
+ 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
+ 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
+ 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
+ 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
+ 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
+ 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
+ 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
+ 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
+ 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
+ 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
+ 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
+ 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
+ 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
+ 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
+ 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
+ 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
+ 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
+ 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
+ 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
+ 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
+ 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
+ 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
+ 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
+ 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
+ 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
+ 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
+ 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
+ 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
+ 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
+ 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
+ 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
+ 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
+ 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
+ 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
+ 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
+ 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
+ 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
+ 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
+ 0x0ba0c79300000000},
+ {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
+ 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
+ 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
+ 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
+ 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
+ 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
+ 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
+ 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
+ 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
+ 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
+ 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
+ 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
+ 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
+ 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
+ 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
+ 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
+ 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
+ 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
+ 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
+ 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
+ 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
+ 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
+ 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
+ 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
+ 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
+ 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
+ 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
+ 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
+ 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
+ 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
+ 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
+ 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
+ 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
+ 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
+ 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
+ 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
+ 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
+ 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
+ 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
+ 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
+ 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
+ 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
+ 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
+ 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
+ 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
+ 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
+ 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
+ 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
+ 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
+ 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
+ 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
+ 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
+ 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
+ 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
+ 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
+ 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
+ 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
+ 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
+ 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
+ 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
+ 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
+ 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
+ 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
+ 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
+ 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
+ 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
+ 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
+ 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
+ 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
+ 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
+ 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
+ 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
+ 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
+ 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
+ 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
+ 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
+ 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
+ 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
+ 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
+ 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
+ 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
+ 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
+ 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
+ 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
+ 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
+ 0x281e419700000000},
+ {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
+ 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
+ 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
+ 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
+ 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
+ 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
+ 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
+ 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
+ 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
+ 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
+ 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
+ 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
+ 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
+ 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
+ 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
+ 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
+ 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
+ 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
+ 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
+ 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
+ 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
+ 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
+ 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
+ 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
+ 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
+ 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
+ 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
+ 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
+ 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
+ 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
+ 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
+ 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
+ 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
+ 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
+ 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
+ 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
+ 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
+ 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
+ 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
+ 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
+ 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
+ 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
+ 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
+ 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
+ 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
+ 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
+ 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
+ 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
+ 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
+ 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
+ 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
+ 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
+ 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
+ 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
+ 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
+ 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
+ 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
+ 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
+ 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
+ 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
+ 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
+ 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
+ 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
+ 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
+ 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
+ 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
+ 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
+ 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
+ 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
+ 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
+ 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
+ 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
+ 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
+ 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
+ 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
+ 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
+ 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
+ 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
+ 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
+ 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
+ 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
+ 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
+ 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
+ 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
+ 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
+ 0xe4e9223500000000},
+ {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
+ 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
+ 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
+ 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
+ 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
+ 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
+ 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
+ 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
+ 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
+ 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
+ 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
+ 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
+ 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
+ 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
+ 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
+ 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
+ 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
+ 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
+ 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
+ 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
+ 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
+ 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
+ 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
+ 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
+ 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
+ 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
+ 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
+ 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
+ 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
+ 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
+ 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
+ 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
+ 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
+ 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
+ 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
+ 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
+ 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
+ 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
+ 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
+ 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
+ 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
+ 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
+ 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
+ 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
+ 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
+ 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
+ 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
+ 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
+ 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
+ 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
+ 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
+ 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
+ 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
+ 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
+ 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
+ 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
+ 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
+ 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
+ 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
+ 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
+ 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
+ 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
+ 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
+ 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
+ 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
+ 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
+ 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
+ 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
+ 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
+ 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
+ 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
+ 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
+ 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
+ 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
+ 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
+ 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
+ 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
+ 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
+ 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
+ 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
+ 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
+ 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
+ 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
+ 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
+ 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
+ 0x880452a700000000},
+ {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
+ 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
+ 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
+ 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
+ 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
+ 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
+ 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
+ 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
+ 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
+ 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
+ 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
+ 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
+ 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
+ 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
+ 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
+ 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
+ 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
+ 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
+ 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
+ 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
+ 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
+ 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
+ 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
+ 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
+ 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
+ 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
+ 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
+ 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
+ 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
+ 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
+ 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
+ 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
+ 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
+ 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
+ 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
+ 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
+ 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
+ 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
+ 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
+ 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
+ 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
+ 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
+ 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
+ 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
+ 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
+ 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
+ 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
+ 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
+ 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
+ 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
+ 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
+ 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
+ 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
+ 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
+ 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
+ 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
+ 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
+ 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
+ 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
+ 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
+ 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
+ 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
+ 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
+ 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
+ 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
+ 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
+ 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
+ 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
+ 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
+ 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
+ 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
+ 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
+ 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
+ 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
+ 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
+ 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
+ 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
+ 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
+ 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
+ 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
+ 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
+ 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
+ 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
+ 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
+ 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
+ 0x1659c4e300000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
+ 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
+ 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
+ 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
+ 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
+ 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
+ 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
+ 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
+ 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
+ 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
+ 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
+ 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
+ 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
+ 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
+ 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
+ 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
+ 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
+ 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
+ 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
+ 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
+ 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
+ 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
+ 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
+ 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
+ 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
+ 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
+ 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
+ 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
+ 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
+ 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
+ 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
+ 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
+ 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
+ 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
+ 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
+ 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
+ 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
+ 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
+ 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
+ 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
+ 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
+ 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
+ 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
+ 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
+ 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
+ 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
+ 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
+ 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
+ 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
+ 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
+ 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
+ 0xa68cee3d},
+ {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
+ 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
+ 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
+ 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
+ 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
+ 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
+ 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
+ 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
+ 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
+ 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
+ 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
+ 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
+ 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
+ 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
+ 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
+ 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
+ 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
+ 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
+ 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
+ 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
+ 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
+ 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
+ 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
+ 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
+ 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
+ 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
+ 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
+ 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
+ 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
+ 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
+ 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
+ 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
+ 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
+ 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
+ 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
+ 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
+ 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
+ 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
+ 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
+ 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
+ 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
+ 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
+ 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
+ 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
+ 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
+ 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
+ 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
+ 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
+ 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
+ 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
+ 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
+ 0x51e8883f},
+ {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
+ 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
+ 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
+ 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
+ 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
+ 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
+ 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
+ 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
+ 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
+ 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
+ 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
+ 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
+ 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
+ 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
+ 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
+ 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
+ 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
+ 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
+ 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
+ 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
+ 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
+ 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
+ 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
+ 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
+ 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
+ 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
+ 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
+ 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
+ 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
+ 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
+ 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
+ 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
+ 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
+ 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
+ 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
+ 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
+ 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
+ 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
+ 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
+ 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
+ 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
+ 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
+ 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
+ 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
+ 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
+ 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
+ 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
+ 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
+ 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
+ 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
+ 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
+ 0x8ae9531c},
+ {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
+ 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
+ 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
+ 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
+ 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
+ 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
+ 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
+ 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
+ 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
+ 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
+ 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
+ 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
+ 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
+ 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
+ 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
+ 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
+ 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
+ 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
+ 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
+ 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
+ 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
+ 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
+ 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
+ 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
+ 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
+ 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
+ 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
+ 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
+ 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
+ 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
+ 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
+ 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
+ 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
+ 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
+ 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
+ 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
+ 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
+ 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
+ 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
+ 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
+ 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
+ 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
+ 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
+ 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
+ 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
+ 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
+ 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
+ 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
+ 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
+ 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
+ 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
+ 0xd739710d}};
+
+#endif
+
+#endif
+
+#if N == 5
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
+ 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
+ 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
+ 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
+ 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
+ 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
+ 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
+ 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
+ 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
+ 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
+ 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
+ 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
+ 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
+ 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
+ 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
+ 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
+ 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
+ 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
+ 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
+ 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
+ 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
+ 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
+ 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
+ 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
+ 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
+ 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
+ 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
+ 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
+ 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
+ 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
+ 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
+ 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
+ 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
+ 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
+ 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
+ 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
+ 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
+ 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
+ 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
+ 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
+ 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
+ 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
+ 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
+ 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
+ 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
+ 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
+ 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
+ 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
+ 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
+ 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
+ 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
+ 0xe9947565},
+ {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
+ 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
+ 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
+ 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
+ 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
+ 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
+ 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
+ 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
+ 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
+ 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
+ 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
+ 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
+ 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
+ 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
+ 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
+ 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
+ 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
+ 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
+ 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
+ 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
+ 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
+ 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
+ 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
+ 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
+ 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
+ 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
+ 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
+ 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
+ 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
+ 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
+ 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
+ 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
+ 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
+ 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
+ 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
+ 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
+ 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
+ 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
+ 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
+ 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
+ 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
+ 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
+ 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
+ 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
+ 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
+ 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
+ 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
+ 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
+ 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
+ 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
+ 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
+ 0xf7d05006},
+ {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
+ 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
+ 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
+ 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
+ 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
+ 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
+ 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
+ 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
+ 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
+ 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
+ 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
+ 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
+ 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
+ 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
+ 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
+ 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
+ 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
+ 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
+ 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
+ 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
+ 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
+ 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
+ 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
+ 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
+ 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
+ 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
+ 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
+ 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
+ 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
+ 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
+ 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
+ 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
+ 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
+ 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
+ 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
+ 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
+ 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
+ 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
+ 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
+ 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
+ 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
+ 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
+ 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
+ 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
+ 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
+ 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
+ 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
+ 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
+ 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
+ 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
+ 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
+ 0xb2075b94},
+ {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
+ 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
+ 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
+ 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
+ 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
+ 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
+ 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
+ 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
+ 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
+ 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
+ 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
+ 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
+ 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
+ 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
+ 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
+ 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
+ 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
+ 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
+ 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
+ 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
+ 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
+ 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
+ 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
+ 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
+ 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
+ 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
+ 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
+ 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
+ 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
+ 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
+ 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
+ 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
+ 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
+ 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
+ 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
+ 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
+ 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
+ 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
+ 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
+ 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
+ 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
+ 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
+ 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
+ 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
+ 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
+ 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
+ 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
+ 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
+ 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
+ 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
+ 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
+ 0xba50bcb9},
+ {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
+ 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
+ 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
+ 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
+ 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
+ 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
+ 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
+ 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
+ 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
+ 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
+ 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
+ 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
+ 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
+ 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
+ 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
+ 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
+ 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
+ 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
+ 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
+ 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
+ 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
+ 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
+ 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
+ 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
+ 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
+ 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
+ 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
+ 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
+ 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
+ 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
+ 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
+ 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
+ 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
+ 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
+ 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
+ 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
+ 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
+ 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
+ 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
+ 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
+ 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
+ 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
+ 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
+ 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
+ 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
+ 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
+ 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
+ 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
+ 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
+ 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
+ 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
+ 0x808abcf4},
+ {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
+ 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
+ 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
+ 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
+ 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
+ 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
+ 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
+ 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
+ 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
+ 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
+ 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
+ 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
+ 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
+ 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
+ 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
+ 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
+ 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
+ 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
+ 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
+ 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
+ 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
+ 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
+ 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
+ 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
+ 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
+ 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
+ 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
+ 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
+ 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
+ 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
+ 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
+ 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
+ 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
+ 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
+ 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
+ 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
+ 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
+ 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
+ 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
+ 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
+ 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
+ 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
+ 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
+ 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
+ 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
+ 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
+ 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
+ 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
+ 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
+ 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
+ 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
+ 0xefdb3f95},
+ {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
+ 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
+ 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
+ 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
+ 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
+ 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
+ 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
+ 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
+ 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
+ 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
+ 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
+ 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
+ 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
+ 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
+ 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
+ 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
+ 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
+ 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
+ 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
+ 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
+ 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
+ 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
+ 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
+ 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
+ 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
+ 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
+ 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
+ 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
+ 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
+ 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
+ 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
+ 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
+ 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
+ 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
+ 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
+ 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
+ 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
+ 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
+ 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
+ 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
+ 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
+ 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
+ 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
+ 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
+ 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
+ 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
+ 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
+ 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
+ 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
+ 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
+ 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
+ 0x0e2fbf43},
+ {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
+ 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
+ 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
+ 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
+ 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
+ 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
+ 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
+ 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
+ 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
+ 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
+ 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
+ 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
+ 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
+ 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
+ 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
+ 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
+ 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
+ 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
+ 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
+ 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
+ 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
+ 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
+ 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
+ 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
+ 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
+ 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
+ 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
+ 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
+ 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
+ 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
+ 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
+ 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
+ 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
+ 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
+ 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
+ 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
+ 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
+ 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
+ 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
+ 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
+ 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
+ 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
+ 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
+ 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
+ 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
+ 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
+ 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
+ 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
+ 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
+ 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
+ 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
+ 0xf4377108}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
+ 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
+ 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
+ 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
+ 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
+ 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
+ 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
+ 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
+ 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
+ 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
+ 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
+ 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
+ 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
+ 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
+ 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
+ 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
+ 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
+ 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
+ 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
+ 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
+ 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
+ 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
+ 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
+ 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
+ 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
+ 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
+ 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
+ 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
+ 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
+ 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
+ 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
+ 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
+ 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
+ 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
+ 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
+ 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
+ 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
+ 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
+ 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
+ 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
+ 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
+ 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
+ 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
+ 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
+ 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
+ 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
+ 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
+ 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
+ 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
+ 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
+ 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
+ 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
+ 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
+ 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
+ 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
+ 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
+ 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
+ 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
+ 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
+ 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
+ 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
+ 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
+ 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
+ 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
+ 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
+ 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
+ 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
+ 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
+ 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
+ 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
+ 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
+ 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
+ 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
+ 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
+ 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
+ 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
+ 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
+ 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
+ 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
+ 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
+ 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
+ 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
+ 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
+ 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
+ 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
+ 0x087137f400000000},
+ {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
+ 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
+ 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
+ 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
+ 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
+ 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
+ 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
+ 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
+ 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
+ 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
+ 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
+ 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
+ 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
+ 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
+ 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
+ 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
+ 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
+ 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
+ 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
+ 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
+ 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
+ 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
+ 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
+ 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
+ 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
+ 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
+ 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
+ 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
+ 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
+ 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
+ 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
+ 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
+ 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
+ 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
+ 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
+ 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
+ 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
+ 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
+ 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
+ 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
+ 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
+ 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
+ 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
+ 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
+ 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
+ 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
+ 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
+ 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
+ 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
+ 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
+ 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
+ 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
+ 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
+ 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
+ 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
+ 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
+ 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
+ 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
+ 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
+ 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
+ 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
+ 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
+ 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
+ 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
+ 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
+ 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
+ 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
+ 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
+ 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
+ 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
+ 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
+ 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
+ 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
+ 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
+ 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
+ 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
+ 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
+ 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
+ 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
+ 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
+ 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
+ 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
+ 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
+ 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
+ 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
+ 0x43bf2f0e00000000},
+ {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
+ 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
+ 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
+ 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
+ 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
+ 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
+ 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
+ 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
+ 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
+ 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
+ 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
+ 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
+ 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
+ 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
+ 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
+ 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
+ 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
+ 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
+ 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
+ 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
+ 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
+ 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
+ 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
+ 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
+ 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
+ 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
+ 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
+ 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
+ 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
+ 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
+ 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
+ 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
+ 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
+ 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
+ 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
+ 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
+ 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
+ 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
+ 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
+ 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
+ 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
+ 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
+ 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
+ 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
+ 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
+ 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
+ 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
+ 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
+ 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
+ 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
+ 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
+ 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
+ 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
+ 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
+ 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
+ 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
+ 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
+ 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
+ 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
+ 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
+ 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
+ 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
+ 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
+ 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
+ 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
+ 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
+ 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
+ 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
+ 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
+ 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
+ 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
+ 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
+ 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
+ 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
+ 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
+ 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
+ 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
+ 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
+ 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
+ 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
+ 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
+ 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
+ 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
+ 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
+ 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
+ 0x953fdbef00000000},
+ {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
+ 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
+ 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
+ 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
+ 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
+ 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
+ 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
+ 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
+ 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
+ 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
+ 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
+ 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
+ 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
+ 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
+ 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
+ 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
+ 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
+ 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
+ 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
+ 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
+ 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
+ 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
+ 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
+ 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
+ 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
+ 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
+ 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
+ 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
+ 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
+ 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
+ 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
+ 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
+ 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
+ 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
+ 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
+ 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
+ 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
+ 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
+ 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
+ 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
+ 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
+ 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
+ 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
+ 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
+ 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
+ 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
+ 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
+ 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
+ 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
+ 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
+ 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
+ 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
+ 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
+ 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
+ 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
+ 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
+ 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
+ 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
+ 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
+ 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
+ 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
+ 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
+ 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
+ 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
+ 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
+ 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
+ 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
+ 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
+ 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
+ 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
+ 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
+ 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
+ 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
+ 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
+ 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
+ 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
+ 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
+ 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
+ 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
+ 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
+ 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
+ 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
+ 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
+ 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
+ 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
+ 0xf4bc8a8000000000},
+ {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
+ 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
+ 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
+ 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
+ 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
+ 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
+ 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
+ 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
+ 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
+ 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
+ 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
+ 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
+ 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
+ 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
+ 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
+ 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
+ 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
+ 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
+ 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
+ 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
+ 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
+ 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
+ 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
+ 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
+ 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
+ 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
+ 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
+ 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
+ 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
+ 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
+ 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
+ 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
+ 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
+ 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
+ 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
+ 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
+ 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
+ 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
+ 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
+ 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
+ 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
+ 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
+ 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
+ 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
+ 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
+ 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
+ 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
+ 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
+ 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
+ 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
+ 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
+ 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
+ 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
+ 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
+ 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
+ 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
+ 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
+ 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
+ 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
+ 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
+ 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
+ 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
+ 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
+ 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
+ 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
+ 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
+ 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
+ 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
+ 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
+ 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
+ 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
+ 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
+ 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
+ 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
+ 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
+ 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
+ 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
+ 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
+ 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
+ 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
+ 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
+ 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
+ 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
+ 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
+ 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
+ 0xb9bc50ba00000000},
+ {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
+ 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
+ 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
+ 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
+ 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
+ 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
+ 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
+ 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
+ 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
+ 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
+ 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
+ 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
+ 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
+ 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
+ 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
+ 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
+ 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
+ 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
+ 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
+ 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
+ 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
+ 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
+ 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
+ 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
+ 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
+ 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
+ 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
+ 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
+ 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
+ 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
+ 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
+ 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
+ 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
+ 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
+ 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
+ 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
+ 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
+ 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
+ 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
+ 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
+ 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
+ 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
+ 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
+ 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
+ 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
+ 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
+ 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
+ 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
+ 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
+ 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
+ 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
+ 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
+ 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
+ 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
+ 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
+ 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
+ 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
+ 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
+ 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
+ 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
+ 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
+ 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
+ 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
+ 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
+ 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
+ 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
+ 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
+ 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
+ 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
+ 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
+ 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
+ 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
+ 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
+ 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
+ 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
+ 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
+ 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
+ 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
+ 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
+ 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
+ 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
+ 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
+ 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
+ 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
+ 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
+ 0x945b07b200000000},
+ {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
+ 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
+ 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
+ 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
+ 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
+ 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
+ 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
+ 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
+ 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
+ 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
+ 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
+ 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
+ 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
+ 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
+ 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
+ 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
+ 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
+ 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
+ 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
+ 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
+ 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
+ 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
+ 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
+ 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
+ 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
+ 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
+ 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
+ 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
+ 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
+ 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
+ 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
+ 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
+ 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
+ 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
+ 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
+ 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
+ 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
+ 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
+ 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
+ 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
+ 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
+ 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
+ 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
+ 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
+ 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
+ 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
+ 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
+ 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
+ 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
+ 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
+ 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
+ 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
+ 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
+ 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
+ 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
+ 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
+ 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
+ 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
+ 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
+ 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
+ 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
+ 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
+ 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
+ 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
+ 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
+ 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
+ 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
+ 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
+ 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
+ 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
+ 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
+ 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
+ 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
+ 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
+ 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
+ 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
+ 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
+ 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
+ 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
+ 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
+ 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
+ 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
+ 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
+ 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
+ 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
+ 0x0650d0f700000000},
+ {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
+ 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
+ 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
+ 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
+ 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
+ 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
+ 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
+ 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
+ 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
+ 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
+ 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
+ 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
+ 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
+ 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
+ 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
+ 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
+ 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
+ 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
+ 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
+ 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
+ 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
+ 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
+ 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
+ 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
+ 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
+ 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
+ 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
+ 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
+ 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
+ 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
+ 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
+ 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
+ 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
+ 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
+ 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
+ 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
+ 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
+ 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
+ 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
+ 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
+ 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
+ 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
+ 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
+ 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
+ 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
+ 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
+ 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
+ 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
+ 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
+ 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
+ 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
+ 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
+ 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
+ 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
+ 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
+ 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
+ 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
+ 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
+ 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
+ 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
+ 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
+ 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
+ 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
+ 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
+ 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
+ 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
+ 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
+ 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
+ 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
+ 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
+ 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
+ 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
+ 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
+ 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
+ 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
+ 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
+ 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
+ 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
+ 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
+ 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
+ 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
+ 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
+ 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
+ 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
+ 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
+ 0x657594e900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
+ 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
+ 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
+ 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
+ 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
+ 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
+ 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
+ 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
+ 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
+ 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
+ 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
+ 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
+ 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
+ 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
+ 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
+ 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
+ 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
+ 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
+ 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
+ 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
+ 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
+ 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
+ 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
+ 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
+ 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
+ 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
+ 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
+ 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
+ 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
+ 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
+ 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
+ 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
+ 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
+ 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
+ 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
+ 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
+ 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
+ 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
+ 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
+ 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
+ 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
+ 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
+ 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
+ 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
+ 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
+ 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
+ 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
+ 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
+ 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
+ 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
+ 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
+ 0x4e36ba18},
+ {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
+ 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
+ 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
+ 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
+ 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
+ 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
+ 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
+ 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
+ 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
+ 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
+ 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
+ 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
+ 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
+ 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
+ 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
+ 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
+ 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
+ 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
+ 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
+ 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
+ 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
+ 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
+ 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
+ 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
+ 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
+ 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
+ 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
+ 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
+ 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
+ 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
+ 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
+ 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
+ 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
+ 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
+ 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
+ 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
+ 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
+ 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
+ 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
+ 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
+ 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
+ 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
+ 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
+ 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
+ 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
+ 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
+ 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
+ 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
+ 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
+ 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
+ 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
+ 0xa1d67c91},
+ {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
+ 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
+ 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
+ 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
+ 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
+ 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
+ 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
+ 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
+ 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
+ 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
+ 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
+ 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
+ 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
+ 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
+ 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
+ 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
+ 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
+ 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
+ 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
+ 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
+ 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
+ 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
+ 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
+ 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
+ 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
+ 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
+ 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
+ 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
+ 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
+ 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
+ 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
+ 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
+ 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
+ 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
+ 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
+ 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
+ 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
+ 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
+ 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
+ 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
+ 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
+ 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
+ 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
+ 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
+ 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
+ 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
+ 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
+ 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
+ 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
+ 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
+ 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
+ 0xa8ef40a1},
+ {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
+ 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
+ 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
+ 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
+ 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
+ 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
+ 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
+ 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
+ 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
+ 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
+ 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
+ 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
+ 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
+ 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
+ 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
+ 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
+ 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
+ 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
+ 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
+ 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
+ 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
+ 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
+ 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
+ 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
+ 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
+ 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
+ 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
+ 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
+ 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
+ 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
+ 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
+ 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
+ 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
+ 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
+ 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
+ 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
+ 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
+ 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
+ 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
+ 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
+ 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
+ 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
+ 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
+ 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
+ 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
+ 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
+ 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
+ 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
+ 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
+ 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
+ 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
+ 0x356bacd8}};
+
+#endif
+
+#endif
+
+#if N == 6
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
+ 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
+ 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
+ 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
+ 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
+ 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
+ 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
+ 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
+ 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
+ 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
+ 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
+ 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
+ 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
+ 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
+ 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
+ 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
+ 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
+ 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
+ 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
+ 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
+ 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
+ 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
+ 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
+ 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
+ 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
+ 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
+ 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
+ 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
+ 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
+ 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
+ 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
+ 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
+ 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
+ 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
+ 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
+ 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
+ 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
+ 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
+ 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
+ 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
+ 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
+ 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
+ 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
+ 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
+ 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
+ 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
+ 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
+ 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
+ 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
+ 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
+ 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
+ 0x8568a0a8},
+ {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
+ 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
+ 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
+ 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
+ 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
+ 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
+ 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
+ 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
+ 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
+ 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
+ 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
+ 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
+ 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
+ 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
+ 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
+ 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
+ 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
+ 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
+ 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
+ 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
+ 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
+ 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
+ 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
+ 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
+ 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
+ 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
+ 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
+ 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
+ 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
+ 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
+ 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
+ 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
+ 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
+ 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
+ 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
+ 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
+ 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
+ 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
+ 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
+ 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
+ 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
+ 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
+ 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
+ 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
+ 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
+ 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
+ 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
+ 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
+ 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
+ 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
+ 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
+ 0x0d907052},
+ {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
+ 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
+ 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
+ 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
+ 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
+ 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
+ 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
+ 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
+ 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
+ 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
+ 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
+ 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
+ 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
+ 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
+ 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
+ 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
+ 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
+ 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
+ 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
+ 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
+ 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
+ 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
+ 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
+ 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
+ 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
+ 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
+ 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
+ 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
+ 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
+ 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
+ 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
+ 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
+ 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
+ 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
+ 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
+ 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
+ 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
+ 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
+ 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
+ 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
+ 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
+ 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
+ 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
+ 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
+ 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
+ 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
+ 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
+ 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
+ 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
+ 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
+ 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
+ 0xfd1a6c8a},
+ {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
+ 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
+ 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
+ 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
+ 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
+ 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
+ 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
+ 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
+ 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
+ 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
+ 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
+ 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
+ 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
+ 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
+ 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
+ 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
+ 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
+ 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
+ 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
+ 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
+ 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
+ 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
+ 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
+ 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
+ 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
+ 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
+ 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
+ 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
+ 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
+ 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
+ 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
+ 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
+ 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
+ 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
+ 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
+ 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
+ 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
+ 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
+ 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
+ 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
+ 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
+ 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
+ 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
+ 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
+ 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
+ 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
+ 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
+ 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
+ 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
+ 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
+ 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
+ 0x7895f01a},
+ {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
+ 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
+ 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
+ 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
+ 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
+ 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
+ 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
+ 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
+ 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
+ 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
+ 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
+ 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
+ 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
+ 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
+ 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
+ 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
+ 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
+ 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
+ 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
+ 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
+ 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
+ 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
+ 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
+ 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
+ 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
+ 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
+ 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
+ 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
+ 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
+ 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
+ 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
+ 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
+ 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
+ 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
+ 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
+ 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
+ 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
+ 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
+ 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
+ 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
+ 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
+ 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
+ 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
+ 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
+ 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
+ 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
+ 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
+ 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
+ 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
+ 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
+ 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
+ 0x9239b848},
+ {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
+ 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
+ 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
+ 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
+ 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
+ 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
+ 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
+ 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
+ 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
+ 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
+ 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
+ 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
+ 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
+ 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
+ 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
+ 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
+ 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
+ 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
+ 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
+ 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
+ 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
+ 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
+ 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
+ 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
+ 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
+ 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
+ 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
+ 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
+ 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
+ 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
+ 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
+ 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
+ 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
+ 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
+ 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
+ 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
+ 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
+ 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
+ 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
+ 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
+ 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
+ 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
+ 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
+ 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
+ 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
+ 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
+ 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
+ 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
+ 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
+ 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
+ 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
+ 0xeb36d3cc},
+ {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
+ 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
+ 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
+ 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
+ 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
+ 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
+ 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
+ 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
+ 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
+ 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
+ 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
+ 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
+ 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
+ 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
+ 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
+ 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
+ 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
+ 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
+ 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
+ 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
+ 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
+ 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
+ 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
+ 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
+ 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
+ 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
+ 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
+ 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
+ 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
+ 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
+ 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
+ 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
+ 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
+ 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
+ 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
+ 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
+ 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
+ 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
+ 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
+ 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
+ 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
+ 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
+ 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
+ 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
+ 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
+ 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
+ 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
+ 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
+ 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
+ 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
+ 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
+ 0x38e5f3c5},
+ {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
+ 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
+ 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
+ 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
+ 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
+ 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
+ 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
+ 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
+ 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
+ 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
+ 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
+ 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
+ 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
+ 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
+ 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
+ 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
+ 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
+ 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
+ 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
+ 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
+ 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
+ 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
+ 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
+ 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
+ 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
+ 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
+ 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
+ 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
+ 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
+ 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
+ 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
+ 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
+ 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
+ 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
+ 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
+ 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
+ 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
+ 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
+ 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
+ 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
+ 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
+ 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
+ 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
+ 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
+ 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
+ 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
+ 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
+ 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
+ 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
+ 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
+ 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
+ 0x3d3101a2}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
+ 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
+ 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
+ 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
+ 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
+ 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
+ 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
+ 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
+ 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
+ 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
+ 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
+ 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
+ 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
+ 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
+ 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
+ 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
+ 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
+ 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
+ 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
+ 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
+ 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
+ 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
+ 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
+ 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
+ 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
+ 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
+ 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
+ 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
+ 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
+ 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
+ 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
+ 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
+ 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
+ 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
+ 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
+ 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
+ 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
+ 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
+ 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
+ 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
+ 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
+ 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
+ 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
+ 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
+ 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
+ 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
+ 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
+ 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
+ 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
+ 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
+ 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
+ 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
+ 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
+ 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
+ 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
+ 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
+ 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
+ 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
+ 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
+ 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
+ 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
+ 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
+ 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
+ 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
+ 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
+ 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
+ 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
+ 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
+ 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
+ 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
+ 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
+ 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
+ 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
+ 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
+ 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
+ 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
+ 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
+ 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
+ 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
+ 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
+ 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
+ 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
+ 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
+ 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
+ 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
+ 0xa201313d00000000},
+ {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
+ 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
+ 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
+ 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
+ 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
+ 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
+ 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
+ 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
+ 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
+ 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
+ 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
+ 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
+ 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
+ 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
+ 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
+ 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
+ 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
+ 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
+ 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
+ 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
+ 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
+ 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
+ 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
+ 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
+ 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
+ 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
+ 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
+ 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
+ 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
+ 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
+ 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
+ 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
+ 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
+ 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
+ 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
+ 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
+ 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
+ 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
+ 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
+ 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
+ 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
+ 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
+ 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
+ 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
+ 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
+ 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
+ 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
+ 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
+ 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
+ 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
+ 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
+ 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
+ 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
+ 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
+ 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
+ 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
+ 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
+ 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
+ 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
+ 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
+ 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
+ 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
+ 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
+ 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
+ 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
+ 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
+ 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
+ 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
+ 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
+ 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
+ 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
+ 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
+ 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
+ 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
+ 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
+ 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
+ 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
+ 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
+ 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
+ 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
+ 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
+ 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
+ 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
+ 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
+ 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
+ 0xc5f3e53800000000},
+ {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
+ 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
+ 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
+ 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
+ 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
+ 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
+ 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
+ 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
+ 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
+ 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
+ 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
+ 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
+ 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
+ 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
+ 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
+ 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
+ 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
+ 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
+ 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
+ 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
+ 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
+ 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
+ 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
+ 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
+ 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
+ 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
+ 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
+ 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
+ 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
+ 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
+ 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
+ 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
+ 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
+ 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
+ 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
+ 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
+ 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
+ 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
+ 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
+ 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
+ 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
+ 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
+ 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
+ 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
+ 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
+ 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
+ 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
+ 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
+ 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
+ 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
+ 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
+ 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
+ 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
+ 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
+ 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
+ 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
+ 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
+ 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
+ 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
+ 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
+ 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
+ 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
+ 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
+ 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
+ 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
+ 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
+ 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
+ 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
+ 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
+ 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
+ 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
+ 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
+ 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
+ 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
+ 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
+ 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
+ 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
+ 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
+ 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
+ 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
+ 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
+ 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
+ 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
+ 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
+ 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
+ 0xccd336eb00000000},
+ {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
+ 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
+ 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
+ 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
+ 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
+ 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
+ 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
+ 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
+ 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
+ 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
+ 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
+ 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
+ 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
+ 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
+ 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
+ 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
+ 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
+ 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
+ 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
+ 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
+ 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
+ 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
+ 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
+ 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
+ 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
+ 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
+ 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
+ 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
+ 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
+ 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
+ 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
+ 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
+ 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
+ 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
+ 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
+ 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
+ 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
+ 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
+ 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
+ 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
+ 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
+ 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
+ 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
+ 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
+ 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
+ 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
+ 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
+ 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
+ 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
+ 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
+ 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
+ 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
+ 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
+ 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
+ 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
+ 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
+ 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
+ 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
+ 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
+ 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
+ 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
+ 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
+ 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
+ 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
+ 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
+ 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
+ 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
+ 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
+ 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
+ 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
+ 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
+ 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
+ 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
+ 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
+ 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
+ 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
+ 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
+ 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
+ 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
+ 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
+ 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
+ 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
+ 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
+ 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
+ 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
+ 0x48b8399200000000},
+ {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
+ 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
+ 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
+ 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
+ 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
+ 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
+ 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
+ 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
+ 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
+ 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
+ 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
+ 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
+ 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
+ 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
+ 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
+ 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
+ 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
+ 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
+ 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
+ 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
+ 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
+ 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
+ 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
+ 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
+ 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
+ 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
+ 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
+ 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
+ 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
+ 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
+ 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
+ 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
+ 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
+ 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
+ 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
+ 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
+ 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
+ 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
+ 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
+ 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
+ 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
+ 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
+ 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
+ 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
+ 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
+ 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
+ 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
+ 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
+ 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
+ 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
+ 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
+ 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
+ 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
+ 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
+ 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
+ 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
+ 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
+ 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
+ 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
+ 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
+ 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
+ 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
+ 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
+ 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
+ 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
+ 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
+ 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
+ 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
+ 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
+ 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
+ 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
+ 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
+ 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
+ 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
+ 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
+ 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
+ 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
+ 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
+ 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
+ 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
+ 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
+ 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
+ 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
+ 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
+ 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
+ 0x1af0957800000000},
+ {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
+ 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
+ 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
+ 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
+ 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
+ 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
+ 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
+ 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
+ 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
+ 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
+ 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
+ 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
+ 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
+ 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
+ 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
+ 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
+ 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
+ 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
+ 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
+ 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
+ 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
+ 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
+ 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
+ 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
+ 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
+ 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
+ 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
+ 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
+ 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
+ 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
+ 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
+ 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
+ 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
+ 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
+ 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
+ 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
+ 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
+ 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
+ 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
+ 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
+ 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
+ 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
+ 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
+ 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
+ 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
+ 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
+ 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
+ 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
+ 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
+ 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
+ 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
+ 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
+ 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
+ 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
+ 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
+ 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
+ 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
+ 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
+ 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
+ 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
+ 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
+ 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
+ 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
+ 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
+ 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
+ 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
+ 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
+ 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
+ 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
+ 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
+ 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
+ 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
+ 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
+ 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
+ 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
+ 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
+ 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
+ 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
+ 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
+ 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
+ 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
+ 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
+ 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
+ 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
+ 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
+ 0x8a6c1afd00000000},
+ {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
+ 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
+ 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
+ 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
+ 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
+ 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
+ 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
+ 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
+ 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
+ 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
+ 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
+ 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
+ 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
+ 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
+ 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
+ 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
+ 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
+ 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
+ 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
+ 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
+ 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
+ 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
+ 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
+ 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
+ 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
+ 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
+ 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
+ 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
+ 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
+ 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
+ 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
+ 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
+ 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
+ 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
+ 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
+ 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
+ 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
+ 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
+ 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
+ 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
+ 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
+ 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
+ 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
+ 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
+ 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
+ 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
+ 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
+ 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
+ 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
+ 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
+ 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
+ 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
+ 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
+ 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
+ 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
+ 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
+ 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
+ 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
+ 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
+ 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
+ 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
+ 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
+ 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
+ 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
+ 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
+ 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
+ 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
+ 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
+ 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
+ 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
+ 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
+ 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
+ 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
+ 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
+ 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
+ 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
+ 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
+ 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
+ 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
+ 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
+ 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
+ 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
+ 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
+ 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
+ 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
+ 0x5270900d00000000},
+ {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
+ 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
+ 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
+ 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
+ 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
+ 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
+ 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
+ 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
+ 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
+ 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
+ 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
+ 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
+ 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
+ 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
+ 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
+ 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
+ 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
+ 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
+ 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
+ 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
+ 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
+ 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
+ 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
+ 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
+ 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
+ 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
+ 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
+ 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
+ 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
+ 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
+ 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
+ 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
+ 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
+ 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
+ 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
+ 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
+ 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
+ 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
+ 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
+ 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
+ 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
+ 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
+ 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
+ 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
+ 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
+ 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
+ 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
+ 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
+ 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
+ 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
+ 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
+ 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
+ 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
+ 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
+ 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
+ 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
+ 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
+ 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
+ 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
+ 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
+ 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
+ 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
+ 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
+ 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
+ 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
+ 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
+ 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
+ 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
+ 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
+ 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
+ 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
+ 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
+ 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
+ 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
+ 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
+ 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
+ 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
+ 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
+ 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
+ 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
+ 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
+ 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
+ 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
+ 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
+ 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
+ 0xa8a0688500000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
+ 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
+ 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
+ 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
+ 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
+ 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
+ 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
+ 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
+ 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
+ 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
+ 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
+ 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
+ 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
+ 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
+ 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
+ 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
+ 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
+ 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
+ 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
+ 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
+ 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
+ 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
+ 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
+ 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
+ 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
+ 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
+ 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
+ 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
+ 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
+ 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
+ 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
+ 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
+ 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
+ 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
+ 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
+ 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
+ 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
+ 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
+ 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
+ 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
+ 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
+ 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
+ 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
+ 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
+ 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
+ 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
+ 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
+ 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
+ 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
+ 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
+ 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
+ 0x48686b56},
+ {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
+ 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
+ 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
+ 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
+ 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
+ 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
+ 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
+ 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
+ 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
+ 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
+ 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
+ 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
+ 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
+ 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
+ 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
+ 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
+ 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
+ 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
+ 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
+ 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
+ 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
+ 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
+ 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
+ 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
+ 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
+ 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
+ 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
+ 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
+ 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
+ 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
+ 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
+ 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
+ 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
+ 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
+ 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
+ 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
+ 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
+ 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
+ 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
+ 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
+ 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
+ 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
+ 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
+ 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
+ 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
+ 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
+ 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
+ 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
+ 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
+ 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
+ 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
+ 0xcaa25178},
+ {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
+ 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
+ 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
+ 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
+ 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
+ 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
+ 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
+ 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
+ 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
+ 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
+ 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
+ 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
+ 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
+ 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
+ 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
+ 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
+ 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
+ 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
+ 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
+ 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
+ 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
+ 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
+ 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
+ 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
+ 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
+ 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
+ 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
+ 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
+ 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
+ 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
+ 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
+ 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
+ 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
+ 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
+ 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
+ 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
+ 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
+ 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
+ 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
+ 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
+ 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
+ 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
+ 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
+ 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
+ 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
+ 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
+ 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
+ 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
+ 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
+ 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
+ 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
+ 0x0c7ac97b},
+ {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
+ 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
+ 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
+ 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
+ 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
+ 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
+ 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
+ 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
+ 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
+ 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
+ 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
+ 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
+ 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
+ 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
+ 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
+ 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
+ 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
+ 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
+ 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
+ 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
+ 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
+ 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
+ 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
+ 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
+ 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
+ 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
+ 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
+ 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
+ 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
+ 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
+ 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
+ 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
+ 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
+ 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
+ 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
+ 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
+ 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
+ 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
+ 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
+ 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
+ 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
+ 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
+ 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
+ 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
+ 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
+ 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
+ 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
+ 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
+ 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
+ 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
+ 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
+ 0x5185cd09}};
+
+#endif
+
+#endif
+
+#endif
+
+local const z_crc_t FAR x2n_table[] = {
+ 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
+ 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
+ 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
+ 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
+ 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
+ 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
+ 0xc40ba6d0, 0xc4e22c3c};
diff --git a/erts/emulator/zlib/deflate.c b/erts/emulator/zlib/deflate.c
index 1ec761448d..799fb93cc0 100644
--- a/erts/emulator/zlib/deflate.c
+++ b/erts/emulator/zlib/deflate.c
@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
+ " deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -190,8 +190,11 @@ local const config configuration_table[10] = {
* prev[] will be initialized on the fly.
*/
#define CLEAR_HASH(s) \
- s->head[s->hash_size-1] = NIL; \
- zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+ do { \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, \
+ (unsigned)(s->hash_size-1)*sizeof(*s->head)); \
+ } while (0)
/* ===========================================================================
* Slide the hash table when sliding the window down (could be avoided with 32
@@ -252,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
int wrap = 1;
static const char my_version[] = ZLIB_VERSION;
- ushf *overlay;
- /* We overlay pending_buf and d_buf+l_buf. This works since the average
- * output size for (length,distance) codes is <= 24 bits.
- */
-
if (version == Z_NULL || version[0] != my_version[0] ||
stream_size != sizeof(z_stream)) {
return Z_VERSION_ERROR;
@@ -326,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
- overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
- s->pending_buf = (uchf *) overlay;
- s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+ /* We overlay pending_buf and sym_buf. This works since the average size
+ * for length/distance pairs over any compressed block is assured to be 31
+ * bits or less.
+ *
+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
+ * possible fixed-codes length/distance pair is then 31 bits total.
+ *
+ * sym_buf starts one-fourth of the way into pending_buf. So there are
+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
+ * in sym_buf is three bytes -- two for the distance and one for the
+ * literal/length. As each symbol is consumed, the pointer to the next
+ * sym_buf value to read moves forward three bytes. From that symbol, up to
+ * 31 bits are written to pending_buf. The closest the written pending_buf
+ * bits gets to the next sym_buf symbol to read is just before the last
+ * code is written. At that time, 31*(n-2) bits have been written, just
+ * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
+ * symbols are written.) The closest the writing gets to what is unread is
+ * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
+ * can range from 128 to 32768.
+ *
+ * Therefore, at a minimum, there are 142 bits of space between what is
+ * written and what is read in the overlain buffers, so the symbols cannot
+ * be overwritten by the compressed data. That space is actually 139 bits,
+ * due to the three-bit fixed-code block header.
+ *
+ * That covers the case where either Z_FIXED is specified, forcing fixed
+ * codes, or when the use of fixed codes is chosen, because that choice
+ * results in a smaller compressed block than dynamic codes. That latter
+ * condition then assures that the above analysis also covers all dynamic
+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
+ * fewer bits than a fixed-code block would for the same set of symbols.
+ * Therefore its average symbol length is assured to be less than 31. So
+ * the compressed data for a dynamic block also cannot overwrite the
+ * symbols from which it is being constructed.
+ */
+
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
s->pending_buf == Z_NULL) {
@@ -337,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
deflateEnd (strm);
return Z_MEM_ERROR;
}
- s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
- s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+ s->sym_buf = s->pending_buf + s->lit_bufsize;
+ s->sym_end = (s->lit_bufsize - 1) * 3;
+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
s->level = level;
s->strategy = strategy;
@@ -488,13 +528,13 @@ int ZEXPORT deflateResetKeep (strm)
#ifdef GZIP
s->wrap == 2 ? GZIP_STATE :
#endif
- s->wrap ? INIT_STATE : BUSY_STATE;
+ INIT_STATE;
strm->adler =
#ifdef GZIP
s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
#endif
adler32(0L, Z_NULL, 0);
- s->last_flush = Z_NO_FLUSH;
+ s->last_flush = -2;
_tr_init(s);
@@ -549,7 +589,8 @@ int ZEXPORT deflatePrime (strm, bits, value)
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;
- if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
+ if (bits < 0 || bits > 16 ||
+ s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
do {
put = Buf_size - s->bi_valid;
@@ -587,12 +628,12 @@ int ZEXPORT deflateParams(strm, level, strategy)
func = configuration_table[s->level].func;
if ((strategy != s->strategy || func != configuration_table[level].func) &&
- s->high_water) {
+ s->last_flush != -2) {
/* Flush the last buffer: */
int err = deflate(strm, Z_BLOCK);
if (err == Z_STREAM_ERROR)
return err;
- if (strm->avail_out == 0)
+ if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
return Z_BUF_ERROR;
}
if (s->level != level) {
@@ -811,6 +852,8 @@ int ZEXPORT deflate (strm, flush)
}
/* Write the header */
+ if (s->status == INIT_STATE && s->wrap == 0)
+ s->status = BUSY_STATE;
if (s->status == INIT_STATE) {
/* zlib header */
uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
@@ -1108,7 +1151,6 @@ int ZEXPORT deflateCopy (dest, source)
#else
deflate_state *ds;
deflate_state *ss;
- ushf *overlay;
if (deflateStateCheck(source) || dest == Z_NULL) {
@@ -1128,8 +1170,7 @@ int ZEXPORT deflateCopy (dest, source)
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
- overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
- ds->pending_buf = (uchf *) overlay;
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
ds->pending_buf == Z_NULL) {
@@ -1143,8 +1184,7 @@ int ZEXPORT deflateCopy (dest, source)
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
- ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
- ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
ds->l_desc.dyn_tree = ds->dyn_ltree;
ds->d_desc.dyn_tree = ds->dyn_dtree;
@@ -1513,6 +1553,8 @@ local void fill_window(s)
s->match_start -= wsize;
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
s->block_start -= (long) wsize;
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
slide_hash(s);
more += wsize;
}
@@ -1742,6 +1784,7 @@ local block_state deflate_stored(s, flush)
s->matches = 2; /* clear hash */
zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
s->strstart = s->w_size;
+ s->insert = s->strstart;
}
else {
if (s->window_size - s->strstart <= used) {
@@ -1750,12 +1793,14 @@ local block_state deflate_stored(s, flush)
zmemcpy(s->window, s->window + s->w_size, s->strstart);
if (s->matches < 2)
s->matches++; /* add a pending slide_hash() */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
}
zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
s->strstart += used;
+ s->insert += MIN(used, s->w_size - s->insert);
}
s->block_start = s->strstart;
- s->insert += MIN(used, s->w_size - s->insert);
}
if (s->high_water < s->strstart)
s->high_water = s->strstart;
@@ -1770,7 +1815,7 @@ local block_state deflate_stored(s, flush)
return block_done;
/* Fill the window with any remaining input. */
- have = s->window_size - s->strstart - 1;
+ have = s->window_size - s->strstart;
if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
/* Slide the window down. */
s->block_start -= s->w_size;
@@ -1779,12 +1824,15 @@ local block_state deflate_stored(s, flush)
if (s->matches < 2)
s->matches++; /* add a pending slide_hash() */
have += s->w_size; /* more space now */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
}
if (have > s->strm->avail_in)
have = s->strm->avail_in;
if (have) {
read_buf(s->strm, s->window + s->strstart, have);
s->strstart += have;
+ s->insert += MIN(have, s->w_size - s->insert);
}
if (s->high_water < s->strstart)
s->high_water = s->strstart;
@@ -1912,7 +1960,7 @@ local block_state deflate_fast(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
@@ -2043,7 +2091,7 @@ local block_state deflate_slow(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
@@ -2118,7 +2166,7 @@ local block_state deflate_rle(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
@@ -2157,7 +2205,7 @@ local block_state deflate_huff(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
diff --git a/erts/emulator/zlib/deflate.h b/erts/emulator/zlib/deflate.h
index 23ecdd312b..17c226113b 100644
--- a/erts/emulator/zlib/deflate.h
+++ b/erts/emulator/zlib/deflate.h
@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
- * Copyright (C) 1995-2016 Jean-loup Gailly
+ * Copyright (C) 1995-2018 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -217,7 +217,7 @@ typedef struct internal_state {
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
- uchf *l_buf; /* buffer for literals or lengths */
+ uchf *sym_buf; /* buffer for distances and literals/lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
@@ -239,13 +239,8 @@ typedef struct internal_state {
* - I can't count above 4
*/
- uInt last_lit; /* running index in l_buf */
-
- ushf *d_buf;
- /* Buffer for distances. To simplify the code, d_buf and l_buf have
- * the same number of elements. To use different lengths, an extra flag
- * array would be necessary.
- */
+ uInt sym_next; /* running index in sym_buf */
+ uInt sym_end; /* symbol table full when sym_next reaches this */
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
@@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
- s->d_buf[s->last_lit] = 0; \
- s->l_buf[s->last_lit++] = cc; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = cc; \
s->dyn_ltree[cc].Freq++; \
- flush = (s->last_lit == s->lit_bufsize-1); \
+ flush = (s->sym_next == s->sym_end); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \
ush dist = (ush)(distance); \
- s->d_buf[s->last_lit] = dist; \
- s->l_buf[s->last_lit++] = len; \
+ s->sym_buf[s->sym_next++] = dist; \
+ s->sym_buf[s->sym_next++] = dist >> 8; \
+ s->sym_buf[s->sym_next++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
- flush = (s->last_lit == s->lit_bufsize-1); \
+ flush = (s->sym_next == s->sym_end); \
}
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
diff --git a/erts/emulator/zlib/gzguts.h b/erts/emulator/zlib/gzguts.h
index 990a4d2514..57faf37165 100644
--- a/erts/emulator/zlib/gzguts.h
+++ b/erts/emulator/zlib/gzguts.h
@@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -39,7 +39,7 @@
# include <io.h>
#endif
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32)
# define WIDECHAR
#endif
@@ -190,6 +190,7 @@ typedef struct {
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
/* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */
diff --git a/erts/emulator/zlib/inffast.c b/erts/emulator/zlib/inffast.c
index 0dbd1dbc09..1fec7f363f 100644
--- a/erts/emulator/zlib/inffast.c
+++ b/erts/emulator/zlib/inffast.c
@@ -70,7 +70,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
- code here; /* retrieved table entry */
+ code const *here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
@@ -107,20 +107,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
- here = lcode[hold & lmask];
+ here = lcode + (hold & lmask);
dolen:
- op = (unsigned)(here.bits);
+ op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
- op = (unsigned)(here.op);
+ op = (unsigned)(here->op);
if (op == 0) { /* literal */
- Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
"inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", here.val));
- *out++ = (unsigned char)(here.val);
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
}
else if (op & 16) { /* length base */
- len = (unsigned)(here.val);
+ len = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
@@ -138,14 +138,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
- here = dcode[hold & dmask];
+ here = dcode + (hold & dmask);
dodist:
- op = (unsigned)(here.bits);
+ op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
- op = (unsigned)(here.op);
+ op = (unsigned)(here->op);
if (op & 16) { /* distance base */
- dist = (unsigned)(here.val);
+ dist = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(*in++) << bits;
@@ -264,7 +264,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
- here = dcode[here.val + (hold & ((1U << op) - 1))];
+ here = dcode + here->val + (hold & ((1U << op) - 1));
goto dodist;
}
else {
@@ -274,7 +274,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
- here = lcode[here.val + (hold & ((1U << op) - 1))];
+ here = lcode + here->val + (hold & ((1U << op) - 1));
goto dolen;
}
else if (op & 32) { /* end-of-block */
diff --git a/erts/emulator/zlib/inflate.c b/erts/emulator/zlib/inflate.c
index ac333e8c2e..7be8c63662 100644
--- a/erts/emulator/zlib/inflate.c
+++ b/erts/emulator/zlib/inflate.c
@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -130,6 +130,7 @@ z_streamp strm;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
+ state->flags = -1;
state->dmax = 32768U;
state->head = Z_NULL;
state->hold = 0;
@@ -447,10 +448,10 @@ unsigned copy;
/* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP
-# define UPDATE(check, buf, len) \
+# define UPDATE_CHECK(check, buf, len) \
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
-# define UPDATE(check, buf, len) adler32(check, buf, len)
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
#endif
/* check macros for header crc */
@@ -670,7 +671,6 @@ int flush;
state->mode = FLAGS;
break;
}
- state->flags = 0; /* expect zlib header */
if (state->head != Z_NULL)
state->head->done = -1;
if (!(state->wrap & 1) || /* check if zlib header allowed */
@@ -697,6 +697,7 @@ int flush;
break;
}
state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -722,6 +723,7 @@ int flush;
CRC2(state->check, hold);
INITBITS();
state->mode = TIME;
+ /* fallthrough */
case TIME:
NEEDBITS(32);
if (state->head != Z_NULL)
@@ -730,6 +732,7 @@ int flush;
CRC4(state->check, hold);
INITBITS();
state->mode = OS;
+ /* fallthrough */
case OS:
NEEDBITS(16);
if (state->head != Z_NULL) {
@@ -740,6 +743,7 @@ int flush;
CRC2(state->check, hold);
INITBITS();
state->mode = EXLEN;
+ /* fallthrough */
case EXLEN:
if (state->flags & 0x0400) {
NEEDBITS(16);
@@ -753,6 +757,7 @@ int flush;
else if (state->head != Z_NULL)
state->head->extra = Z_NULL;
state->mode = EXTRA;
+ /* fallthrough */
case EXTRA:
if (state->flags & 0x0400) {
copy = state->length;
@@ -775,6 +780,7 @@ int flush;
}
state->length = 0;
state->mode = NAME;
+ /* fallthrough */
case NAME:
if (state->flags & 0x0800) {
if (have == 0) goto inf_leave;
@@ -796,6 +802,7 @@ int flush;
state->head->name = Z_NULL;
state->length = 0;
state->mode = COMMENT;
+ /* fallthrough */
case COMMENT:
if (state->flags & 0x1000) {
if (have == 0) goto inf_leave;
@@ -816,6 +823,7 @@ int flush;
else if (state->head != Z_NULL)
state->head->comment = Z_NULL;
state->mode = HCRC;
+ /* fallthrough */
case HCRC:
if (state->flags & 0x0200) {
NEEDBITS(16);
@@ -839,6 +847,7 @@ int flush;
strm->adler = state->check = ZSWAP32(hold);
INITBITS();
state->mode = DICT;
+ /* fallthrough */
case DICT:
if (state->havedict == 0) {
RESTORE();
@@ -846,8 +855,10 @@ int flush;
}
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE;
+ /* fallthrough */
case TYPE:
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case TYPEDO:
if (state->last) {
BYTEBITS();
@@ -898,8 +909,10 @@ int flush;
INITBITS();
state->mode = COPY_;
if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case COPY_:
state->mode = COPY;
+ /* fallthrough */
case COPY:
copy = state->length;
if (copy) {
@@ -935,6 +948,7 @@ int flush;
Tracev((stderr, "inflate: table sizes ok\n"));
state->have = 0;
state->mode = LENLENS;
+ /* fallthrough */
case LENLENS:
while (state->have < state->ncode) {
NEEDBITS(3);
@@ -956,6 +970,7 @@ int flush;
Tracev((stderr, "inflate: code lengths ok\n"));
state->have = 0;
state->mode = CODELENS;
+ /* fallthrough */
case CODELENS:
while (state->have < state->nlen + state->ndist) {
for (;;) {
@@ -1039,8 +1054,10 @@ int flush;
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN_;
if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case LEN_:
state->mode = LEN;
+ /* fallthrough */
case LEN:
if (have >= 6 && left >= 258) {
RESTORE();
@@ -1090,6 +1107,7 @@ int flush;
}
state->extra = (unsigned)(here.op) & 15;
state->mode = LENEXT;
+ /* fallthrough */
case LENEXT:
if (state->extra) {
NEEDBITS(state->extra);
@@ -1100,6 +1118,7 @@ int flush;
Tracevv((stderr, "inflate: length %u\n", state->length));
state->was = state->length;
state->mode = DIST;
+ /* fallthrough */
case DIST:
for (;;) {
here = state->distcode[BITS(state->distbits)];
@@ -1127,6 +1146,7 @@ int flush;
state->offset = (unsigned)here.val;
state->extra = (unsigned)(here.op) & 15;
state->mode = DISTEXT;
+ /* fallthrough */
case DISTEXT:
if (state->extra) {
NEEDBITS(state->extra);
@@ -1143,6 +1163,7 @@ int flush;
#endif
Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH;
+ /* fallthrough */
case MATCH:
if (left == 0) goto inf_leave;
copy = out - left;
@@ -1202,7 +1223,7 @@ int flush;
state->total += out;
if ((state->wrap & 4) && out)
strm->adler = state->check =
- UPDATE(state->check, put - out, out);
+ UPDATE_CHECK(state->check, put - out, out);
out = left;
if ((state->wrap & 4) && (
#ifdef GUNZIP
@@ -1218,10 +1239,11 @@ int flush;
}
#ifdef GUNZIP
state->mode = LENGTH;
+ /* fallthrough */
case LENGTH:
if (state->wrap && state->flags) {
NEEDBITS(32);
- if (hold != (state->total & 0xffffffffUL)) {
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
strm->msg = (char *)"incorrect length check";
state->mode = BAD;
break;
@@ -1231,6 +1253,7 @@ int flush;
}
#endif
state->mode = DONE;
+ /* fallthrough */
case DONE:
ret = Z_STREAM_END;
goto inf_leave;
@@ -1240,6 +1263,7 @@ int flush;
case MEM:
return Z_MEM_ERROR;
case SYNC:
+ /* fallthrough */
default:
return Z_STREAM_ERROR;
}
@@ -1265,7 +1289,7 @@ int flush;
state->total += out;
if ((state->wrap & 4) && out)
strm->adler = state->check =
- UPDATE(state->check, strm->next_out - out, out);
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
@@ -1401,6 +1425,7 @@ int ZEXPORT inflateSync(strm)
z_streamp strm;
{
unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
unsigned long in, out; /* temporary to save total_in and total_out */
unsigned char buf[4]; /* to restore bit buffer to byte string */
struct inflate_state FAR *state;
@@ -1433,9 +1458,15 @@ z_streamp strm;
/* return no joy or set up to restart inflate() on a new block */
if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
in = strm->total_in; out = strm->total_out;
inflateReset(strm);
strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
state->mode = TYPE;
return Z_OK;
}
@@ -1531,7 +1562,7 @@ int check;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
- if (check)
+ if (check && state->wrap)
state->wrap |= 4;
else
state->wrap &= ~4;
diff --git a/erts/emulator/zlib/inflate.h b/erts/emulator/zlib/inflate.h
index a46cce6b6d..f127b6b1fa 100644
--- a/erts/emulator/zlib/inflate.h
+++ b/erts/emulator/zlib/inflate.h
@@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -86,7 +86,8 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
bit 2 true to validate check value */
int havedict; /* true if dictionary provided */
- int flags; /* gzip header method and flags (0 if zlib) */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
diff --git a/erts/emulator/zlib/inftrees.c b/erts/emulator/zlib/inftrees.c
index 2ea08fc13e..7783b162e5 100644
--- a/erts/emulator/zlib/inftrees.c
+++ b/erts/emulator/zlib/inftrees.c
@@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2017 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
+ " inflate 1.2.12 Copyright 1995-2022 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -87,7 +87,7 @@ unsigned short FAR *work;
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
- 1..MAXBITS is interpreted as that code length. zero means that that
+ 1..MAXBITS is interpreted as that code length. zero means that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
diff --git a/erts/emulator/zlib/trees.c b/erts/emulator/zlib/trees.c
index 50cf4b4571..f73fd99c37 100644
--- a/erts/emulator/zlib/trees.c
+++ b/erts/emulator/zlib/trees.c
@@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2017 Jean-loup Gailly
+ * Copyright (C) 1995-2021 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -149,7 +149,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
local void compress_block OF((deflate_state *s, const ct_data *ltree,
const ct_data *dtree));
local int detect_data_type OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned value, int length));
+local unsigned bi_reverse OF((unsigned code, int len));
local void bi_windup OF((deflate_state *s));
local void bi_flush OF((deflate_state *s));
@@ -416,7 +416,7 @@ local void init_block(s)
s->dyn_ltree[END_BLOCK].Freq = 1;
s->opt_len = s->static_len = 0L;
- s->last_lit = s->matches = 0;
+ s->sym_next = s->matches = 0;
}
#define SMALLEST 1
@@ -870,7 +870,8 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
bi_windup(s); /* align on byte boundary */
put_short(s, (ush)stored_len);
put_short(s, (ush)~stored_len);
- zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
+ if (stored_len)
+ zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
s->pending += stored_len;
#ifdef ZLIB_DEBUG
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
@@ -947,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
- s->last_lit));
+ s->sym_next / 3));
if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
@@ -1016,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
unsigned dist; /* distance of matched string */
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
{
- s->d_buf[s->last_lit] = (ush)dist;
- s->l_buf[s->last_lit++] = (uch)lc;
+ s->sym_buf[s->sym_next++] = dist;
+ s->sym_buf[s->sym_next++] = dist >> 8;
+ s->sym_buf[s->sym_next++] = lc;
if (dist == 0) {
/* lc is the unmatched char */
s->dyn_ltree[lc].Freq++;
@@ -1032,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
s->dyn_dtree[d_code(dist)].Freq++;
}
-
-#ifdef TRUNCATE_BLOCK
- /* Try to guess if it is profitable to stop the current block here */
- if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
- /* Compute an upper bound for the compressed length */
- ulg out_length = (ulg)s->last_lit*8L;
- ulg in_length = (ulg)((long)s->strstart - s->block_start);
- int dcode;
- for (dcode = 0; dcode < D_CODES; dcode++) {
- out_length += (ulg)s->dyn_dtree[dcode].Freq *
- (5L+extra_dbits[dcode]);
- }
- out_length >>= 3;
- Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
- s->last_lit, in_length, out_length,
- 100L - out_length*100L/in_length));
- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
- }
-#endif
- return (s->last_lit == s->lit_bufsize-1);
- /* We avoid equality with lit_bufsize because of wraparound at 64K
- * on 16 bit machines and because stored blocks are restricted to
- * 64K-1 bytes.
- */
+ return (s->sym_next == s->sym_end);
}
/* ===========================================================================
@@ -1068,13 +1047,14 @@ local void compress_block(s, ltree, dtree)
{
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
- unsigned lx = 0; /* running index in l_buf */
+ unsigned sx = 0; /* running index in sym_buf */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
- if (s->last_lit != 0) do {
- dist = s->d_buf[lx];
- lc = s->l_buf[lx++];
+ if (s->sym_next != 0) do {
+ dist = s->sym_buf[sx++] & 0xff;
+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
+ lc = s->sym_buf[sx++];
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
@@ -1099,11 +1079,10 @@ local void compress_block(s, ltree, dtree)
}
} /* literal or match pair ? */
- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
- Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
- "pendingBuf overflow");
+ /* Check that the overlay between pending_buf and sym_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
- } while (lx < s->last_lit);
+ } while (sx < s->sym_next);
send_code(s, END_BLOCK, ltree);
}
@@ -1112,9 +1091,9 @@ local void compress_block(s, ltree, dtree)
* Check if the data type is TEXT or BINARY, using the following algorithm:
* - TEXT if the two conditions below are satisfied:
* a) There are no non-portable control characters belonging to the
- * "black list" (0..6, 14..25, 28..31).
+ * "block list" (0..6, 14..25, 28..31).
* b) There is at least one printable character belonging to the
- * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
* - BINARY otherwise.
* - The following partially-portable control characters form a
* "gray list" that is ignored in this detection algorithm:
@@ -1124,19 +1103,19 @@ local void compress_block(s, ltree, dtree)
local int detect_data_type(s)
deflate_state *s;
{
- /* black_mask is the bit mask of black-listed bytes
+ /* block_mask is the bit mask of block-listed bytes
* set bits 0..6, 14..25, and 28..31
* 0xf3ffc07f = binary 11110011111111111100000001111111
*/
- unsigned long black_mask = 0xf3ffc07fUL;
+ unsigned long block_mask = 0xf3ffc07fUL;
int n;
- /* Check for non-textual ("black-listed") bytes. */
- for (n = 0; n <= 31; n++, black_mask >>= 1)
- if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ /* Check for non-textual ("block-listed") bytes. */
+ for (n = 0; n <= 31; n++, block_mask >>= 1)
+ if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
return Z_BINARY;
- /* Check for textual ("white-listed") bytes. */
+ /* Check for textual ("allow-listed") bytes. */
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|| s->dyn_ltree[13].Freq != 0)
return Z_TEXT;
@@ -1144,7 +1123,7 @@ local int detect_data_type(s)
if (s->dyn_ltree[n].Freq != 0)
return Z_TEXT;
- /* There are no "black-listed" or "white-listed" bytes:
+ /* There are no "block-listed" or "allow-listed" bytes:
* this stream either is empty or has tolerated ("gray-listed") bytes only.
*/
return Z_BINARY;
diff --git a/erts/emulator/zlib/zlib.h b/erts/emulator/zlib/zlib.h
index f09cdaf1e0..4a98e38bf3 100644
--- a/erts/emulator/zlib/zlib.h
+++ b/erts/emulator/zlib/zlib.h
@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.11, January 15th, 2017
+ version 1.2.12, March 11th, 2022
- Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -37,11 +37,11 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.2.11"
-#define ZLIB_VERNUM 0x12b0
+#define ZLIB_VERSION "1.2.12"
+#define ZLIB_VERNUM 0x12c0
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 11
+#define ZLIB_VER_REVISION 12
#define ZLIB_VER_SUBREVISION 0
/*
@@ -543,8 +543,7 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
int strategy));
This is another version of deflateInit with more compression options. The
- fields next_in, zalloc, zfree and opaque must be initialized before by the
- caller.
+ fields zalloc, zfree and opaque must be initialized before by the caller.
The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
@@ -712,11 +711,12 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
used to switch between compression and straight copy of the input data, or
to switch to a different kind of input data requiring a different strategy.
If the compression approach (which is a function of the level) or the
- strategy is changed, and if any input has been consumed in a previous
- deflate() call, then the input available so far is compressed with the old
- level and strategy using deflate(strm, Z_BLOCK). There are three approaches
- for the compression levels 0, 1..3, and 4..9 respectively. The new level
- and strategy will take effect at the next call of deflate().
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
not have enough output space to complete, then the parameter change will not
@@ -865,9 +865,11 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
- below), inflate() will not automatically decode concatenated gzip streams.
- inflate() will return Z_STREAM_END at the end of the gzip stream. The state
- would need to be reset to continue decoding a subsequent gzip stream.
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
@@ -1302,14 +1304,14 @@ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
/*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
- Opens a gzip (.gz) file for reading or writing. The mode parameter is as
- in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
- a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
- compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
- for fixed code compression as in "wb9F". (See the description of
- deflateInit2 for more information about the strategy parameter.) 'T' will
- request transparent writing or appending with no compression and not using
- the gzip format.
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
"a" can be used instead of "w" to request that the gzip stream that will
be written be appended to the file. "+" will result in an error, since
@@ -1339,9 +1341,9 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
/*
- gzdopen associates a gzFile with the file descriptor fd. File descriptors
- are obtained from calls like open, dup, creat, pipe or fileno (if the file
- has been previously opened with fopen). The mode parameter is as in gzopen.
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
The next call of gzclose on the returned gzFile will also close the file
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
@@ -1362,13 +1364,13 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
/*
- Set the internal buffer size used by this library's functions. The
- default buffer size is 8192 bytes. This function must be called after
- gzopen() or gzdopen(), and before any other calls that read or write the
- file. The buffer memory allocation is always deferred to the first read or
- write. Three times that size in buffer space is allocated. A larger buffer
- size of, for example, 64K or 128K bytes will noticeably increase the speed
- of decompression (reading).
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
The new buffer size also affects the maximum length for gzprintf().
@@ -1378,9 +1380,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
/*
- Dynamically update the compression level or strategy. See the description
- of deflateInit2 for the meaning of these parameters. Previously provided
- data is flushed before the parameter change.
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
opened for writing, Z_ERRNO if there is an error writing the flushed data,
@@ -1389,7 +1391,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
- Reads the given number of uncompressed bytes from the compressed file. If
+ Read and decompress up to len uncompressed bytes from file into buf. If
the input file is not in gzip format, gzread copies the given number of
bytes into the buffer directly from the file.
@@ -1420,11 +1422,11 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
gzFile file));
/*
- Read up to nitems items of size size from file to buf, otherwise operating
- as gzread() does. This duplicates the interface of stdio's fread(), with
- size_t request and return types. If the library defines size_t, then
- z_size_t is identical to size_t. If not, then z_size_t is an unsigned
- integer type that can contain a pointer.
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
gzfread() returns the number of full items read of size size, or zero if
the end of the file was reached and a full item could not be read, or if
@@ -1443,18 +1445,16 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
file, reseting and retrying on end-of-file, when size is not 1.
*/
-ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
- voidpc buf, unsigned len));
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
/*
- Writes the given number of uncompressed bytes into the compressed file.
- gzwrite returns the number of uncompressed bytes written or 0 in case of
- error.
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
*/
ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
z_size_t nitems, gzFile file));
/*
- gzfwrite() writes nitems items of size size from buf to file, duplicating
+ Compress and write nitems items of size size from buf to file, duplicating
the interface of stdio's fwrite(), with size_t request and return types. If
the library defines size_t, then z_size_t is identical to size_t. If not,
then z_size_t is an unsigned integer type that can contain a pointer.
@@ -1467,22 +1467,22 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
/*
- Converts, formats, and writes the arguments to the compressed file under
- control of the format string, as in fprintf. gzprintf returns the number of
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
uncompressed bytes actually written, or a negative zlib error code in case
of error. The number of uncompressed bytes written is limited to 8191, or
one less than the buffer size given to gzbuffer(). The caller should assure
that this limit is not exceeded. If it is exceeded, then gzprintf() will
return an error (0) with nothing written. In this case, there may also be a
buffer overflow with unpredictable consequences, which is possible only if
- zlib was compiled with the insecure functions sprintf() or vsprintf()
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
because the secure snprintf() or vsnprintf() functions were not available.
This can be determined using zlibCompileFlags().
*/
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
/*
- Writes the given null-terminated string to the compressed file, excluding
+ Compress and write the given null-terminated string s to file, excluding
the terminating null character.
gzputs returns the number of characters written, or -1 in case of error.
@@ -1490,11 +1490,12 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
/*
- Reads bytes from the compressed file until len-1 characters are read, or a
- newline character is read and transferred to buf, or an end-of-file
- condition is encountered. If any characters are read or if len == 1, the
- string is terminated with a null character. If no characters are read due
- to an end-of-file or len < 1, then the buffer is left untouched.
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
gzgets returns buf which is a null-terminated string, or it returns NULL
for end-of-file or in case of error. If there was an error, the contents at
@@ -1503,13 +1504,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
/*
- Writes c, converted to an unsigned char, into the compressed file. gzputc
+ Compress and write c, converted to an unsigned char, into file. gzputc
returns the value that was written, or -1 in case of error.
*/
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
- Reads one byte from the compressed file. gzgetc returns this byte or -1
+ Read and decompress one byte from file. gzgetc returns this byte or -1
in case of end of file or error. This is implemented as a macro for speed.
As such, it does not do all of the checking the other functions do. I.e.
it does not check to see if file is NULL, nor whether the structure file
@@ -1518,8 +1519,8 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
/*
- Push one character back onto the stream to be read as the first character
- on the next read. At least one character of push-back is allowed.
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
fail if c is -1, and may fail if a character has been pushed but not read
yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
@@ -1530,9 +1531,9 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
/*
- Flushes all pending output into the compressed file. The parameter flush
- is as in the deflate() function. The return value is the zlib error number
- (see function gzerror below). gzflush is only permitted when writing.
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
If the flush parameter is Z_FINISH, the remaining data is written and the
gzip stream is completed in the output. If gzwrite() is called again, a new
@@ -1547,8 +1548,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
z_off_t offset, int whence));
- Sets the starting position for the next gzread or gzwrite on the given
- compressed file. The offset represents a number of bytes in the
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
uncompressed data stream. The whence parameter is defined as in lseek(2);
the value SEEK_END is not supported.
@@ -1565,18 +1566,18 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
/*
- Rewinds the given file. This function is supported only for reading.
+ Rewind file. This function is supported only for reading.
- gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
*/
/*
ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
- Returns the starting position for the next gzread or gzwrite on the given
- compressed file. This position represents a number of bytes in the
- uncompressed data stream, and is zero when starting, even if appending or
- reading a gzip stream from the middle of a file using gzdopen().
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/
@@ -1584,22 +1585,22 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
/*
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
- Returns the current offset in the file being read or written. This offset
- includes the count of bytes that precede the gzip stream, for example when
- appending or when using gzdopen() for reading. When reading, the offset
- does not include as yet unused buffered input. This information can be used
- for a progress indicator. On error, gzoffset() returns -1.
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
*/
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
/*
- Returns true (1) if the end-of-file indicator has been set while reading,
- false (0) otherwise. Note that the end-of-file indicator is set only if the
- read tried to go past the end of the input, but came up short. Therefore,
- just like feof(), gzeof() may return false even if there is no more data to
- read, in the event that the last read request was for the exact number of
- bytes remaining in the input file. This will happen if the input file size
- is an exact multiple of the buffer size.
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
If gzeof() returns true, then the read functions will return no more data,
unless the end-of-file indicator is reset by gzclearerr() and the input file
@@ -1608,7 +1609,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
- Returns true (1) if file is being copied directly while reading, or false
+ Return true (1) if file is being copied directly while reading, or false
(0) if file is a gzip stream being decompressed.
If the input file is empty, gzdirect() will return true, since the input
@@ -1629,8 +1630,8 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
/*
- Flushes all pending output if necessary, closes the compressed file and
- deallocates the (de)compression state. Note that once file is closed, you
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
cannot call gzerror with file, since its structures have been deallocated.
gzclose must not be called more than once on the same file, just as free
must not be called more than once on the same allocation.
@@ -1654,10 +1655,10 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
/*
- Returns the error message for the last error which occurred on the given
- compressed file. errnum is set to zlib error number. If an error occurred
- in the file system and not in the compression library, errnum is set to
- Z_ERRNO and the application may consult errno to get the exact error code.
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
The application must not modify the returned string. Future calls to
this function may invalidate the previously returned string. If file is
@@ -1670,7 +1671,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
/*
- Clears the error and end-of-file flags for file. This is analogous to the
+ Clear the error and end-of-file flags for file. This is analogous to the
clearerr() function in stdio. This is useful for continuing to read a gzip
file that is being written concurrently.
*/
@@ -1688,8 +1689,9 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
- return the updated checksum. If buf is Z_NULL, this function returns the
- required initial value for the checksum.
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
much faster.
@@ -1722,12 +1724,13 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
negative, the result has no meaning or utility.
*/
-ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
Update a running CRC-32 with the bytes buf[0..len-1] and return the
- updated CRC-32. If buf is Z_NULL, this function returns the required
- initial value for the crc. Pre- and post-conditioning (one's complement) is
- performed within this function so it shouldn't be done by the application.
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
Usage example:
@@ -1739,7 +1742,7 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
if (crc != original_crc) error();
*/
-ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
+ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
z_size_t len));
/*
Same as crc32(), but with a size_t length.
@@ -1755,6 +1758,20 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
len2.
*/
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op().
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
/* various hacks, don't look :) */
@@ -1842,6 +1859,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
#endif
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
@@ -1852,6 +1870,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
# define z_gzoffset z_gzoffset64
# define z_adler32_combine z_adler32_combine64
# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
# else
# define gzopen gzopen64
# define gzseek gzseek64
@@ -1859,6 +1878,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
# define gzoffset gzoffset64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
# endif
# ifndef Z_LARGE64
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
@@ -1867,6 +1887,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
# endif
#else
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
@@ -1875,12 +1896,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
#endif
#else /* Z_SOLO */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
#endif /* !Z_SOLO */
@@ -1893,7 +1916,7 @@ ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp));
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
+#if defined(_WIN32) && !defined(Z_SOLO)
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
const char *mode));
#endif
diff --git a/erts/emulator/zlib/zutil.c b/erts/emulator/zlib/zutil.c
index a76c6b0c7e..dcab28a0d5 100644
--- a/erts/emulator/zlib/zutil.c
+++ b/erts/emulator/zlib/zutil.c
@@ -136,8 +136,8 @@ const char * ZEXPORT zError(err)
return ERR_MSG(err);
}
-#if defined(_WIN32_WCE)
- /* The Microsoft C Run-Time Library for Windows CE doesn't have
+#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
+ /* The older Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used.
*/
diff --git a/erts/emulator/zlib/zutil.h b/erts/emulator/zlib/zutil.h
index b079ea6a80..d9a20ae1bf 100644
--- a/erts/emulator/zlib/zutil.h
+++ b/erts/emulator/zlib/zutil.h
@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -29,10 +29,6 @@
# include <stdlib.h>
#endif
-#ifdef Z_SOLO
- typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
-#endif
-
#ifndef local
# define local static
#endif
@@ -46,6 +42,17 @@ typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
+#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (ULONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long
+# elif (ULLONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long long
+# elif (UINT_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned
+# endif
+#endif
+
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
@@ -170,10 +177,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
# if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */
-# ifndef _PTRDIFF_T_DEFINED
- typedef int ptrdiff_t;
-# define _PTRDIFF_T_DEFINED
-# endif
# else
# define fdopen(fd,type) _fdopen(fd,type)
# endif
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index c76f32d3cd..e71a0528dd 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -2,7 +2,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -253,7 +253,7 @@ static void run_daemon(EpmdVars *g)
if (( child_pid = fork()) < 0)
{
#ifdef HAVE_SYSLOG_H
- syslog(LOG_ERR,"erlang mapper daemon cant fork %m");
+ syslog(LOG_ERR,"erlang mapper daemon can't fork %m");
#endif
epmd_cleanup_exit(g,1);
}
@@ -265,7 +265,7 @@ static void run_daemon(EpmdVars *g)
if (setsid() < 0)
{
- dbg_perror(g,"epmd: Cant setsid()");
+ dbg_perror(g,"epmd: Can't setsid()");
epmd_cleanup_exit(g,1);
}
@@ -279,7 +279,7 @@ static void run_daemon(EpmdVars *g)
if ((child_pid = fork()) < 0)
{
#ifdef HAVE_SYSLOG_H
- syslog(LOG_ERR,"erlang mapper daemon cant fork 2'nd time %m");
+ syslog(LOG_ERR,"erlang mapper daemon can't fork 2'nd time %m");
#endif
epmd_cleanup_exit(g,1);
}
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index e09dd0ac95..ed2ca33074 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -2,7 +2,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,15 +50,9 @@
#include <fcntl.h>
#ifndef __WIN32__
-# ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-# else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
+# include <time.h>
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
# endif
#endif
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 52fb9e47f3..18a589ac27 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -559,7 +559,7 @@ void run(EpmdVars *g)
/*
* The accept() succeeded, and we have at least one file
* descriptor still free, which means that another accept()
- * could succeed. Go do do another select(), in case there
+ * could succeed. Go do another select(), in case there
* are more incoming connections waiting to be accepted.
*/
goto select_again;
diff --git a/erts/epmd/test/epmd.spec.vxworks b/erts/epmd/test/epmd.spec.vxworks
deleted file mode 100644
index 476308b481..0000000000
--- a/erts/epmd/test/epmd.spec.vxworks
+++ /dev/null
@@ -1,2 +0,0 @@
-{topcase, {dir, "../epmd_test"}}.
-{skip,{epmd_rx_SUITE,"EPMD RX does simply not work on VxWorks"}}.
diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl
index e0dc61878a..b7240ffa29 100644
--- a/erts/epmd/test/epmd_SUITE.erl
+++ b/erts/epmd/test/epmd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -737,7 +737,7 @@ alltrue([_|_]) ->
false.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Ensure that we cannot register throug a nonlocal connection
+%% Ensure that we cannot register through a nonlocal connection
no_nonlocal_register(Config) when is_list(Config) ->
case {os:find_executable("ssh"),ct:get_config(ssh_proxy_host)} of
{SSH,Name} when is_list(Name), is_list(SSH) ->
diff --git a/erts/etc/Makefile b/erts/etc/Makefile
index 788dfff132..b482e08d8f 100644
--- a/erts/etc/Makefile
+++ b/erts/etc/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
SUB_DIRECTORIES = common
ifeq ($(TARGET),win32)
diff --git a/erts/etc/common/Makefile.in b/erts/etc/common/Makefile.in
index e5ff959078..86f63dcf41 100644
--- a/erts/etc/common/Makefile.in
+++ b/erts/etc/common/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -336,11 +336,14 @@ OTP_VSN_COMMA_SEP := $(wordlist 1,4, $(OTP_VSN_COMMA_SEP))
ERTS_VSN_COMMA_SEP := $(subst $(SPACE_CHAR),$(COMMA_CHAR),$(ERTS_VSN_COMMA_SEP))
OTP_VSN_COMMA_SEP := $(subst $(SPACE_CHAR),$(COMMA_CHAR),$(OTP_VSN_COMMA_SEP))
+YEAR := $(shell date +%Y)
+
$(WINETC)/version.h: $(WINETC)/version.h.src
$(vsn_verbose)sed -e 's;%ERTS_VERSION%;$(VSN);' \
-e 's;%ERTS_VERSION_INTS%;$(ERTS_VSN_COMMA_SEP);' \
-e 's;%OTP_VERSION%;$(OTP_VERSION);' \
-e 's;%OTP_VERSION_INTS%;$(OTP_VSN_COMMA_SEP);' \
+ -e 's;%YEAR%;$(YEAR);' \
$(WINETC)/version.h.src > $(WINETC)/version.h
$(OBJDIR)/$(ERLRES_OBJ): $(WINETC)/erl.rc $(WINETC)/erlang.ico \
@@ -517,6 +520,8 @@ erl.src: $(UXETC)/erl.src.src ../../vsn.mk $(TARGET)/Makefile
$(vsn_verbose)sed -e 's;%EMULATOR%;$(EMULATOR);' \
-e 's;%EMULATOR_NUMBER%;$(EMULATOR_NUMBER);' \
-e 's;%VSN%;$(VSN);' \
+ -e 's;%DYN_ERL_PATH%;../erts-$(VSN)/bin/dyn_erl;' \
+ -e 's;%DYN_ROOTDIR_BASE_EXT%;;' \
$(UXETC)/erl.src.src > erl.src
# ----------------------------------------------------
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index bda9a94a95..fa951ae770 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@ static char *plusM_au_alloc_switches[] = {
"acul",
"acnl",
"acfml",
+ "acful",
"cp",
"e",
"t",
@@ -104,7 +105,6 @@ static char *plusM_other_switches[] = {
"usac",
"im",
"is",
- "it",
"lpm",
"Mamcbf",
"Mrmcbf",
@@ -457,21 +457,6 @@ int main(int argc, char **argv)
goto skip_arg_massage;
}
free_env_val(s);
-#else
- int reset_cerl_detached = 0;
-
- s = get_env("CERL_DETACHED_PROG");
- if (s && strcmp(s, "") != 0) {
- emu = s;
- start_detached = 1;
- reset_cerl_detached = 1;
- ensure_EargsSz(argc + 1);
- memcpy((void *) Eargsp, (void *) argv, argc * sizeof(char *));
- Eargsp[argc] = emu;
- Eargsp[argc] = NULL;
- goto skip_arg_massage;
- }
- free_env_val(s);
#endif
initial_argv_massage(&argc, &argv); /* Merge with env; expand -args_file */
@@ -876,6 +861,16 @@ int main(int argc, char **argv)
i++;
break;
}
+ if (argv[i][2] == 'O' && argv[i][3] == 's') {
+ if (argv[i][4] != '\0')
+ goto the_default;
+ NEXT_ARG_CHECK();
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ break;
+ }
usage(argv[i]);
break;
case 'J':
@@ -1005,8 +1000,10 @@ int main(int argc, char **argv)
}
break;
case 'p':
- if (argv[i][2] != 'c' || argv[i][3] != '\0')
+ if (!(argv[i][2] == 'c' && argv[i][3] == '\0')
+ && !(argv[i][2] == 'a' && argv[i][3] == 'd' && argv[i][4] == '\0')) {
goto the_default;
+ }
NEXT_ARG_CHECK();
argv[i][0] = '-';
add_Eargs(argv[i]);
@@ -1081,6 +1078,8 @@ int main(int argc, char **argv)
add_Eargs("--");
add_Eargs("-root");
add_Eargs(rootdir);
+ add_Eargs("-bindir");
+ add_Eargs(bindir);
add_Eargs("-progname");
add_Eargs(progname);
add_Eargs("--");
@@ -1141,15 +1140,11 @@ int main(int argc, char **argv)
#else
- skip_arg_massage:
if (start_detached) {
int status = fork();
if (status != 0) /* Parent */
return 0;
- if (reset_cerl_detached)
- putenv("CERL_DETACHED_PROG=");
-
/* Detach from controlling terminal */
#ifdef HAVE_SETSID
setsid();
@@ -1713,7 +1708,7 @@ static char **build_args_from_string(char *string, int allow_comments)
{
int argc = 0;
char **argv = NULL;
- int alloced = 0;
+ int allocated = 0;
char **cur_s = NULL; /* Initialized to avoid warning. */
int s_alloced = 0;
int s_pos = 0;
@@ -1732,15 +1727,15 @@ static char **build_args_from_string(char *string, int allow_comments)
if (!p)
return NULL;
- argv = emalloc(sizeof(char *) * (alloced = 10));
+ argv = emalloc(sizeof(char *) * (allocated = 10));
state = Start;
for(;;) {
switch (state) {
case Start:
if (!*p)
goto done;
- if (argc >= alloced - 2) { /* Make room for extra NULL and "--" */
- argv = erealloc(argv, (alloced += 10) * sizeof(char *));
+ if (argc >= allocated - 2) { /* Make room for extra NULL and "--" */
+ argv = erealloc(argv, (allocated += 10) * sizeof(char *));
}
cur_s = argc + argv;
*cur_s = NULL;
diff --git a/erts/etc/common/etc_common.h b/erts/etc/common/etc_common.h
index 6e4c326ae6..289a33b42a 100644
--- a/erts/etc/common/etc_common.h
+++ b/erts/etc/common/etc_common.h
@@ -59,11 +59,18 @@
#include "erl_printf.h"
#ifdef __WIN32__
-/* FIXE ME config_win32.h? */
+/* FIXME config_win32.h? */
#define HAVE_STRERROR 1
#define snprintf _snprintf
#endif
+#ifdef __IOS__
+#ifdef system
+#undef system
+#endif
+#define system(X) 0
+#endif
+
#ifdef DEBUG
# define ASSERT(Cnd) ((void)((Cnd) ? 1 : abort()))
#else
diff --git a/erts/etc/common/heart.c b/erts/etc/common/heart.c
index de50eb88c8..297e41dca2 100644
--- a/erts/etc/common/heart.c
+++ b/erts/etc/common/heart.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@
* This program communicates with Erlang through the standard
* input and output file descriptors (0 and 1). These descriptors
* (and the standard error descriptor 2) must NOT be closed
- * explicitely by this program at termination (in UNIX it is
+ * explicitly by this program at termination (in UNIX it is
* taken care of by the operating system itself).
*
* END OF FILE
@@ -74,16 +74,7 @@
*
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#ifdef __WIN32__
-#include <windows.h>
-#include <io.h>
-#include <fcntl.h>
-#include <process.h>
-#endif
+#include "etc_common.h"
/*
* Implement time correction using times() call even on Linuxes
@@ -91,13 +82,7 @@
* a phony gethrtime in this file as the time questions are so infrequent.
*/
-#include <stdio.h>
#include <stddef.h>
-#include <stdlib.h>
-
-#include <stdarg.h>
-
-#include <string.h>
#include <time.h>
#include <errno.h>
@@ -350,7 +335,7 @@ int main(int argc, char **argv) {
AllocConsole();
conh = freopen("CONOUT$","w",stderr);
if (conh != NULL)
- fprintf(conh,"console alloced\n");
+ fprintf(conh,"console allocated\n");
}
debugf("stderr\n");
}
@@ -423,7 +408,7 @@ message_loop(erlin_fd, erlout_fd)
#endif
/*
* Maybe heart beat time-out
- * If we havn't got anything in 60 seconds we reboot, even if we may
+ * If we haven't got anything in 60 seconds we reboot, even if we may
* have got something in the last 5 seconds. We may end up here if
* the system clock is adjusted with more than 55 seconds, but we
* regard this as en error and reboot anyway.
@@ -689,7 +674,7 @@ do_terminate(int erlin_fd, int reason) {
case R_ERROR:
default:
{
-#if defined(__WIN32__) /* Not VxWorks */
+#if defined(__WIN32__)
if(!cmd[0]) {
char *command = get_env(HEART_COMMAND_ENV);
if(!command)
diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index 60a4073d1e..af313e4185 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -973,7 +973,7 @@ static void main_loop(void)
}
if (BEE_GREEDY()) {
- DEBUGF(4,("Beeing greedy!"));
+ DEBUGF(4,("Being greedy!"));
if ((cw = pick_worker_greedy(domainbuff)) != NULL) {
/* Put it in the worker specific que if the
domainname matches... */
@@ -1483,7 +1483,7 @@ static int ignore_reply(Worker *pw)
#endif /* !WIN32 */
/*
- * Domain name "parsing" and worker specific queing
+ * Domain name "parsing" and worker specific queueing
*/
static void domaincopy(AddrByte *out, AddrByte *in)
{
@@ -2333,7 +2333,7 @@ static int read_exact(HANDLE fd, void *vbuff, DWORD nbytes, HANDLE ev)
}
}
} else {
- DEBUGF(4,("Read completed syncronously, result %d",ret));
+ DEBUGF(4,("Read completed synchronously, result %d",ret));
}
if (ret == 0) {
DEBUGF(1, ("End of file detected as zero read from pipe."));
@@ -2369,7 +2369,7 @@ static int write_exact(HANDLE fd, AddrByte *buff, DWORD len, HANDLE ev)
stat = WriteFile(fd,buff,x,&res,&ov);
if (!stat) {
if ((err = GetLastError()) == ERROR_IO_PENDING) {
- DEBUGF(4,("Overlapped write, waiting for competion..."));
+ DEBUGF(4,("Overlapped write, waiting for completion..."));
WaitForSingleObject(ov.hEvent,INFINITE);
stat = GetOverlappedResult(fd,&ov,&res,TRUE);
DEBUGF(4,("Overlapped write, completed with status %d,"
@@ -2383,7 +2383,7 @@ static int write_exact(HANDLE fd, AddrByte *buff, DWORD len, HANDLE ev)
}
}
} else {
- DEBUGF(4,("Write completed syncronously, result %d",res));
+ DEBUGF(4,("Write completed synchronously, result %d",res));
}
if (res < x) {
diff --git a/erts/etc/unix/Install.src b/erts/etc/unix/Install.src
index 7437e073e0..b00dd09f1a 100644
--- a/erts/etc/unix/Install.src
+++ b/erts/etc/unix/Install.src
@@ -81,7 +81,9 @@ chmod 755 erl
# Create start file for embedded system use,
#
(cd "$ERL_ROOT/erts-%I_VSN%/bin";
- sed -e "s;%FINAL_ROOTDIR%;$TARGET_ERL_ROOT;" start.src > start;
+ sed -e "s;%FINAL_ROOTDIR%;$TARGET_ERL_ROOT;" \
+ -e "s;%VSN%;%I_VSN%;" \
+ start.src > start;
chmod 755 start)
cd "$ERL_ROOT/bin"
@@ -111,10 +113,9 @@ 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"
+sed -e "s;%ERL_ROOT%/;;" "$ERL_ROOT/releases/RELEASES.src" > "$ERL_ROOT/releases/RELEASES"
if [ "$start_option" = "query" ]
then
diff --git a/erts/etc/unix/Makefile b/erts/etc/unix/Makefile
index bd1c6d5411..179cce765f 100644
--- a/erts/etc/unix/Makefile
+++ b/erts/etc/unix/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2013-2020. All Rights Reserved.
+# Copyright Ericsson AB 2013-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
include ../../vsn.mk
-opt debug lcnt: etc
+$(TYPES): etc
.PHONY: etc
etc: etp-commands
diff --git a/erts/etc/unix/RELNOTES b/erts/etc/unix/RELNOTES
index 7b4a1746fe..97aec2b100 100644
--- a/erts/etc/unix/RELNOTES
+++ b/erts/etc/unix/RELNOTES
@@ -1,7 +1,7 @@
%CopyrightBegin%
- Copyright Ericsson AB 1996-2016. All Rights Reserved.
+ Copyright Ericsson AB 1996-2021. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -191,9 +191,9 @@ the 4.2 system, but there is a number of incompatibilities.
could fail after a large series of printouts without any
newlines "\n" at all.
--- Formating of floats: a '9' would sometimes become a ':'.
+-- Formatting of floats: a '9' would sometimes become a ':'.
--- Formating with the use of '*' and negativ size fields now work
+-- Formatting with the use of '*' and negative size fields now work
as expected.
-- The format of the 'EXIT' values is now ALWAYS the same
@@ -264,7 +264,7 @@ QNX
-- The 4.3 system is not object code compatible with 4.2.
This means that all source code has to be recompiled. It
is not possible to load 4.2 object code. It is also not
- possible to run distribution between 4.3 and erlier versions
+ possible to run distribution between 4.3 and earlier versions
due to the new alive check.
-- The external term format has been changed. This will only affect
diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src
index faf54e2bdc..8046cee347 100644
--- a/erts/etc/unix/cerl.src
+++ b/erts/etc/unix/cerl.src
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2022. All Rights Reserved.
+# Copyright Ericsson AB 2003-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -81,9 +81,28 @@ run_asan=no
run_rr=no
skip_erlexec=no
+prog="$0"
+progdir="`dirname ${prog}`"
+dyn_erl_path="${progdir}/%DYN_ERL_PATH%"
+if [ -f "$dyn_erl_path" ]
+then
+ dyn_rootdir=`${dyn_erl_path} --realpath`
+ dyn_rootdir=`dirname ${dyn_rootdir}`
+ dyn_rootdir=`dirname ${dyn_rootdir}`
+else
+ dyn_rootdir=""
+fi
+
# Default rootdir
ROOTDIR=%SRC_ROOTDIR%
-BINDIR="$ROOTDIR/bin/`$ROOTDIR/erts/autoconf/config.guess`"
+
+if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
+then
+ # It is likely that the files have been copied or moved
+ ROOTDIR="$dyn_rootdir"
+fi
+
+BINDIR="$ROOTDIR/bin/`$ROOTDIR/make/autoconf/config.guess`"
TARGET=%TARGET%
#BINDIR="$ROOTDIR/bin/%TARGET%"
PROGNAME=$ROOTDIR/bin/cerl
@@ -414,7 +433,7 @@ elif [ "x$GDB" = "xgdb" ]; then
case "x$core" in
x)
# Get emu args to use from erlexec...
- beam_args=`$EXEC -emu_args_exit ${1+"$@"}`
+ beam_args=`$EXEC -emu_args_exit $xargs ${1+"$@"}`
gdbcmd="--args $EMU_NAME $beam_args"
;;
x/*)
@@ -434,7 +453,7 @@ elif [ "x$GDB" = "xgdb" ]; then
elif [ "x$GDB" = "xlldb" ]; then
case "x$core" in
x)
- beam_args=`$EXEC -emu_args_exit ${1+"$@"}`
+ beam_args=`$EXEC -emu_args_exit $xargs ${1+"$@"}`
lldbcmd="-- $beam_args"
;;
*)
@@ -453,18 +472,15 @@ elif [ "x$GDB" = "xegdb" ]; then
case "x$core" in
x)
# Get emu args to use from erlexec...
- beam_args=`$EXEC -emu_args_exit ${1+"$@"} | tr '\n' ' '`
- gdbcmd="(insert-string \"set args $beam_args\") \
- (comint-send-input)"
+ beam_args=`$EXEC -emu_args_exit $xargs ${1+"$@"} | sed 's/"/\\\\"/g' | tr '\n' ' '`
+ gdbcmd="set args $beam_args"
;;
x/*)
- gdbcmd="(insert-string \"core ${core}\") (comint-send-input)"
+ gdbcmd="core $core"
GDBBP=
;;
*)
- dir=`pwd`
- gdbcmd="(insert-string \"core ${dir}/${core}\") \
- (comint-send-input)"
+ gdbcmd="core `pwd`/$core"
GDBBP=
;;
esac
@@ -483,11 +499,13 @@ elif [ "x$GDB" = "xegdb" ]; then
GDBARGS="--annotate=1 "
fi
fi
- gdbcmd="$gdbcmd $GDBBP \
- (insert-string \"source $ROOTDIR/erts/etc/unix/etp-commands\") \
- (comint-send-input)"
# Fire up gdb in emacs...
- exec $EMACS --eval "(progn (gdb \"gdb $GDBARGS$EMU_NAME\") $gdbcmd)"
+ cmdfile="/tmp/.cerlgdb.$$"
+ echo "file $BINDIR/$EMU_NAME" > $cmdfile
+ echo "$gdbcmd" >> $cmdfile
+ echo "source $ROOTDIR/erts/etc/unix/etp-commands" >> $cmdfile
+ EVAL="(progn (gdb \"gdb $GDBARGS -x $cmdfile\"))"
+ exec $EMACS --eval "$EVAL"
elif [ "x$GDB" = "xdump" ]; then
cmdfile="/tmp/.cerlgdb.$$"
## Examine the result of "file $core" in case it is not the emulator
diff --git a/erts/etc/unix/dyn_erl.c b/erts/etc/unix/dyn_erl.c
index 60817d7e65..28f56d645d 100644
--- a/erts/etc/unix/dyn_erl.c
+++ b/erts/etc/unix/dyn_erl.c
@@ -362,6 +362,15 @@ main(int argc, char **argv)
char progname[PATH_MAX]; /* Name of this program. */
char erlexec[PATH_MAX]; /* Path to erlexec */
+ if (argc == 2 && strcmp(argv[1], "--realpath") == 0) {
+ abspath = find_prog(argv[0]);
+ /* Remove program name from output */
+ for (p = abspath+strlen(abspath)-1;p >= abspath && *p != '/'; --p)
+ ;
+ *p = '\0';
+ printf("%s", abspath);
+ return 0;
+ }
/* Determine progname */
abspath = find_prog(argv[0]);
strcpy(progname, abspath);
diff --git a/erts/etc/unix/erl.src.src b/erts/etc/unix/erl.src.src
index 0983132ac1..536fa139d9 100644
--- a/erts/etc/unix/erl.src.src
+++ b/erts/etc/unix/erl.src.src
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2020. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,15 +18,38 @@
#
# %CopyrightEnd%
#
+prog="$0"
+progdir=`dirname "${prog}"`
+dyn_erl_path="${progdir}/%DYN_ERL_PATH%"
+if [ ! -f "$dyn_erl_path" ]
+then
+ dyn_erl_path="${progdir}/dyn_erl"
+fi
+
+if [ -f "$dyn_erl_path" ]
+then
+ dyn_rootdir=`"${dyn_erl_path}" --realpath`
+ dyn_rootdir=`dirname "${dyn_rootdir}"`
+ dyn_rootdir=`dirname "${dyn_rootdir}"`
+ dyn_rootdir="${dyn_rootdir}%DYN_ROOTDIR_BASE_EXT%"
+else
+ dyn_rootdir=""
+fi
+
if [ -z "$ERL_ROOTDIR" ]
then
ROOTDIR="%FINAL_ROOTDIR%"
+ if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
+ then
+ # It is likely that the files have been copied or moved
+ ROOTDIR="$dyn_rootdir"
+ fi
else
ROOTDIR="$ERL_ROOTDIR"
fi
-BINDIR=$ROOTDIR/erts-%VSN%/bin
+BINDIR="$ROOTDIR/erts-%VSN%/bin"
EMU=%EMULATOR%%EMULATOR_NUMBER%
-PROGNAME=`echo $0 | sed 's/.*\///'`
+PROGNAME=`basename "$0"`
export EMU
export ROOTDIR
export BINDIR
diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in
index 179d0a041e..0e764c2430 100644
--- a/erts/etc/unix/etp-commands.in
+++ b/erts/etc/unix/etp-commands.in
@@ -54,9 +54,9 @@ document etp-help
%
% Special commands for not really terms:
% etp-mfa, etp-cp, etp-disasm,
-% etp-msgq, etpf-msgq,
-% etp-stacktrace, etp-stacktrace-emu, etp-stackdump, etp-stackdump-emu,
-% etpf-stackdump, etp-dictdump
+% etp-msgq, etpf-msgq,
+% etp-stacktrace, etp-stacktrace-emu, etp-stacktrace-jit,
+% etp-stackdump, etp-stackdump-emu, etpf-stackdump, etp-dictdump
% etp-process-info, etp-process-info-x, etp-process-memory-info
% etp-port-info, etp-port-state, etp-port-sched-flags
% etp-heapdump, etp-offheapdump, etpf-offheapdump,
@@ -67,8 +67,8 @@ document etp-help
% etp-overlapped-heaps, etp-chart, etp-chart-start, etp-chart-end
%
% System inspection
-% etp-system-info, etp-schedulers, etp-process, etp-ports, etp-lc-dump,
-% etp-migration-info, etp-processes, etp-processes-x, etp-processes-memory,
+% etp-system-info, etp-schedulers, etp-processes, etp-processes-x, etp-ports,
+% etp-lc-dump, etp-migration-info, etp-processes-memory,
% etp-compile-info, etp-config-h-info
%
% Platform specific (when gdb fails you)
@@ -140,7 +140,7 @@ define etp-1
else
if (($arg0) & 0x3) == 2
if $etp_flat
- printf "<etpf-boxed %p>", (($arg0) etp_ptr_mask)
+ printf "<etpf-boxed %p>", (($arg0) & etp_ptr_mask)
else
etp-boxed-1 ($arg0) ($arg1)
end
@@ -1154,17 +1154,24 @@ document etp-mfa
%
% Take an Eterm* to an MFA function name entry and print it.
% These can be found e.g in the process structure;
-% process_tab[i]->current and process_tab[i]->initial.
+% ((Process*)erts_proc->r.o.tab[i])->current and &(((Process*)erts_proc->r.o.tab[i])->u.initial)
%---------------------------------------------------------------------------
end
define etp-export-get
- # Args: Eterm Eterm Uint
+ # Args: M F A [code_ix]
set $etp_h = (((Eterm)$arg0 >> 6) * ((Eterm)$arg1 >> 6)) ^ (Uint)$arg2
+ if $argc == 3
+ set $etp_code_ix = the_active_code_index.counter
+ end
+ if $argc == 4
+ set $etp_code_ix = $arg3
+ end
+
#hash_get_slot
- set $etp_t = &export_tables[the_active_code_index.counter].htable
+ set $etp_t = &export_tables[$etp_code_ix].htable
set $etp_h ^= $etp_h >> $etp_t->shift
if $etp_arch64
set $etp_h = (11400714819323198485UL * $etp_h) >> $etp_t->shift
@@ -1188,9 +1195,10 @@ end
document etp-export-get
%---------------------------------------------------------
-% etp-export-get module function arity
+% etp-export-get module function arity [code_ix]
%
% Lookup and print pointer to Export entry.
+% code_ix is optional, default is the_active_code_index
% Example:
% (gdb) etp-string-to-atom "erlang"
% $1 = 13323
@@ -1207,8 +1215,15 @@ define etp-module-get
set $etp_ix = ((Eterm)$arg0 >> 6)
set $etp_h = $etp_ix
+ if $argc == 1
+ set $etp_code_ix = the_active_code_index.counter
+ end
+ if $argc == 2
+ set $etp_code_ix = $arg1
+ end
+
#hash_get_slot
- set $etp_t = &module_tables[the_active_code_index.counter].htable
+ set $etp_t = &module_tables[$etp_code_ix].htable
set $etp_h ^= $etp_h >> $etp_t->shift
if $etp_arch64
set $etp_h = (11400714819323198485UL * $etp_h) >> $etp_t->shift
@@ -1232,9 +1247,10 @@ end
document etp-module-get
%---------------------------------------------------------
-% etp-module-get module
+% etp-module-get module [code_ix]
%
% Lookup and print pointer to Module entry.
+% code_ix is optional, default is the_active_code_index
% Example:
% (gdb) etp-string-to-atom "erlang"
% $1 = 13323
@@ -1243,19 +1259,67 @@ document etp-module-get
%---------------------------------------------------------
end
+define etp-cp-line-info
+# Args: code_header mfa function_index cp
+#
+# Non-reentrant, sets $etp_cp_line_name and $etp_cp_line_number
+#
+ set $etp_line_hdr = (BeamCodeHeader*)($arg0)
+ set $etp_line_mfa = (ErtsCodeMFA*)($arg1)
+ set $etp_line_fidx = (Eterm)($arg2)
+ set $etp_line_cp = (Eterm)($arg3)
+ set $etp_cp_line_name = $etp_nil
+ set $etp_cp_line_number = 0
+ set $etp_line_table = $etp_line_hdr->line_table
+ if $etp_line_table != 0
+ set $etp_line_low = (void**)$etp_line_table->func_tab[$etp_line_fidx]
+ set $etp_line_high = (void**)$etp_line_table->func_tab[$etp_line_fidx+1]
+ set $etp_line_idx = -1
+ while $etp_line_high > $etp_line_low
+ set $etp_line_mid = $etp_line_low + ($etp_line_high - $etp_line_low) / 2
+ if $etp_line_cp < $etp_line_mid[0]
+ set $etp_line_high = $etp_line_mid
+ else
+ if $etp_line_cp < $etp_line_mid[1]
+ # Found it!
+ set $etp_line_idx = $etp_line_mid - (void**)$etp_line_table->func_tab[0]
+ loop_break
+ else
+ set $etp_line_low = $etp_line_mid + 1
+ end
+ end
+ end
+ set $etp_cp_line_name = $etp_nil
+ set $etp_cp_line_number = 0
+ if $etp_line_idx != -1
+ if $etp_line_table->loc_size == 2
+ set $etp_loc = (Uint32)$etp_line_table->loc_tab.p2[$etp_line_idx]
+ else
+ set $etp_loc = (Uint32)$etp_line_table->loc_tab.p4[$etp_line_idx]
+ end
+ if $etp_loc != 0
+ set $etp_loc_file = $etp_loc >> 24
+ set $etp_cp_line_number = $etp_loc & ((1 << 24) - 1)
+ set $etp_cp_line_name = $etp_line_table->fname_ptr[$etp_loc_file]
+ end
+ end
+ end
+end
define etp-cp-func-info-1
# Args: Eterm cp
#
-# Non-reentrant, takes cp, sets $etp_cp_p to MFA in func_info
+# Non-reentrant, takes cp, sets $etp_cp_p to MFA in func_info, as well as
+# $etp_cp_line_name and $etp_cp_line_number
#
set $etp_cp = (Eterm)($arg0)
- set $etp_ranges = &r[(int)the_active_code_index]
+ set $etp_ranges = &r[(int)the_active_code_index.counter]
set $etp_cp_low = $etp_ranges->modules
set $etp_cp_high = $etp_cp_low + $etp_ranges->n
set $etp_cp_mid = (Range*)$etp_ranges->mid
+ set $etp_cp_range = 0
set $etp_cp_p = 0
- #
+ # Find range
while $etp_cp_low < $etp_cp_high
if $etp_cp < $etp_cp_mid->start
set $etp_cp_high = $etp_cp_mid
@@ -1263,30 +1327,36 @@ define etp-cp-func-info-1
if $etp_cp > (BeamInstr*)$etp_cp_mid->end
set $etp_cp_low = $etp_cp_mid + 1
else
- set $etp_cp_p = $etp_cp_low = $etp_cp_high = $etp_cp_mid
+ set $etp_cp_range = $etp_cp_low = $etp_cp_high = $etp_cp_mid
+ loop_break
end
end
set $etp_cp_mid = $etp_cp_low + ($etp_cp_high-$etp_cp_low)/2
end
- if $etp_cp_p
- # 13 = MI_FUNCTIONS
- set $etp_cp_low = &((Eterm**)$etp_cp_p->start)[13]
- # 0 = MI_NUM_FUNCTIONS
- set $etp_cp_high = $etp_cp_low + ((Eterm*)$etp_cp_p->start)[0]
+ # Find MFA
+ if $etp_cp_range
+ set $etp_cp_hdr = (BeamCodeHeader*)$etp_cp_range->start
+ set $etp_cp_low = (ErtsCodeInfo**)$etp_cp_hdr->functions
+ set $etp_cp_high = $etp_cp_low + $etp_cp_hdr->num_functions
set $etp_cp_p = 0
+ set $etp_cp_fidx = 0
while $etp_cp_low < $etp_cp_high
set $etp_cp_mid = $etp_cp_low + ($etp_cp_high-$etp_cp_low)/2
if $etp_cp < $etp_cp_mid[0]
set $etp_cp_high = $etp_cp_mid
else
if $etp_cp < $etp_cp_mid[1]
- set $etp_cp_p = $etp_cp_mid[0]+2
+ set $etp_cp_fidx = $etp_cp_mid - (ErtsCodeInfo**)$etp_cp_hdr->functions
+ set $etp_cp_p = &$etp_cp_mid[0]->mfa
set $etp_cp_low = $etp_cp_high = $etp_cp_mid
+ loop_break
else
set $etp_cp_low = $etp_cp_mid + 1
end
end
end
+ # Find line number
+ etp-cp-line-info $etp_cp_hdr $etp_cp_p $etp_cp_fidx $etp_cp
end
if $etp_cp_p
set $cp_cp_p_offset = ($etp_cp-((Eterm)($etp_cp_p-2)))
@@ -1304,8 +1374,13 @@ define etp-cp-1
if $etp_cp_p
printf "#Cp"
etp-mfa-1 $etp_cp_p $cp_cp_p_offset
+ if $etp_cp_line_name != $etp_nil
+ printf " @ "
+ etp-1 $etp_cp_line_name 0
+ printf ":%u", $etp_cp_line_number
+ end
else
- if $etp_cp == beam_apply+1
+ if $etp_cp == beam_normal_exit
printf "#Cp<terminate process normally>"
else
if ($etp_cp) == beam_return_trace
@@ -1652,7 +1727,7 @@ document etp-msgq
% Sequential trace tokens are included in comments and
% the current match position in the queue is marked '<='.
%
-% A process's message queue is process_tab[i]->sig_qs.
+% A process's message queue is ((Process*)erts_proc->r.o.tab[i])->sig_qs.
%---------------------------------------------------------------------------
end
@@ -1681,7 +1756,7 @@ define etp-stack-preamble
set $etp_stack_end = ($arg0)->hend
if ($arg0)->state.counter & 0x8000
printf "%%%%%% WARNING: The process is currently running, so c_p->stop will not be correct\r\n"
- printf "%%%%%% Consider using -emu variant instead\r\n"
+ printf "%%%%%% Consider using -emu or -jit variant instead\r\n"
end
printf "%% Stacktrace (%u)\n", $etp_stack_end-$etp_stack_p
if ($arg0)->i != 0
@@ -1698,6 +1773,15 @@ define etp-stack-preamble-emu
etp ((BeamInstr)I)
end
+define etp-stack-preamble-jit
+ set $etp_stack_end = ((Process*)$r13)->hend
+ set $etp_stack_p = (Eterm*)$rsp
+ printf "%% Stacktrace (%u)\n", $etp_stack_end-$etp_stack_p
+ printf "I: "
+ set $etp_stack_i = ((Eterm)$rip) & ~0x3
+ etp $etp_stack_i
+end
+
define etp-stacktrace-1
set $etp_stack_stop = (Eterm*)($arg0)
set $etp_stack_send = (Eterm*)($arg1)
@@ -1732,6 +1816,24 @@ document etp-stacktrace-emu
%---------------------------------------------------------------------------
end
+define etp-stacktrace-jit
+# Args: none
+#
+# Non-reentrant
+#
+ etp-stack-preamble-jit
+ etp-stacktrace-1 $etp_stack_p $etp_stack_end
+end
+
+document etp-stacktrace-jit
+%---------------------------------------------------------------------------
+% etp-stacktrace-jit
+%
+% Prints a stacktrace for the current process, assuming that we're running
+% jitted code.
+%---------------------------------------------------------------------------
+end
+
define etp-stacktrace
# Args: Process*
#
@@ -1776,16 +1878,34 @@ define etp-stackdump-emu
etp-stackdump-1 $etp_stack_p $etp_stack_end
end
-document etp-stacktrace-emu
+document etp-stackdump-emu
%---------------------------------------------------------------------------
-% etp-stacktrace-emu Process*
+% etp-stackdump-emu Process*
%
-% Take an Process* and print a stactdump for the process.
+% Take an Process* and print a stackdump for the process.
% This macro assumes that the current frame is the process_main frame
% and that E is not optimized out.
%---------------------------------------------------------------------------
end
+define etp-stackdump-jit
+# Args: none
+#
+# Non-reentrant
+#
+ etp-stack-preamble-jit
+ etp-stackdump-1 $etp_stack_p $etp_stack_end
+end
+
+document etp-stackdump-jit
+%---------------------------------------------------------------------------
+% etp-stackdump-emu
+%
+% Prints a stackdump for the current process, assuming that we're running
+% jitted code.
+%---------------------------------------------------------------------------
+end
+
define etp-stackdump
# Args: Process*
#
@@ -1801,7 +1921,7 @@ document etp-stackdump
%
% Take an Process* and print a stackdump for the process.
% The stackdump consists of all pushed values on the stack.
-% All code continuation pointers are preceeded with a line
+% All code continuation pointers are preceded with a line
% of dashes to make the stack frames more visible.
%---------------------------------------------------------------------------
end
@@ -2043,24 +2163,45 @@ define etp-term-dump-pid
end
define etp-term-dump-header
-# Args: Header term
+ # Args: Header term
if (($arg0) & 0x3f) == 0
- printf "| H:%4d-tuple ", ($arg0) >> 6
+ printf "| H:%4u-tuple ", ($arg0) >> 6
else
set $etp_heapdump_skips = ($arg0) >> 6
if ((($arg0) & 0x3f) == 0x18)
- printf "| H: float %3d ", ($arg0) >> 6
+ printf "| H: float %3u ", ($arg0) >> 6
else
if ((($arg0) & 0x3f) == 0x28)
- # sub-binary
printf "| H: sub-bin "
else
- if ((($arg0) & 0x3f) == 0x8)
- # pos-bignum
- printf "| H:bignum %3u ", ($arg0) >> 6
+ if ((($arg0) & 0x3f) == 0x24)
+ printf "| H: heap-bin "
else
- printf "| header %5d ", ($arg0) >> 6
- end
+ if ((($arg0) & 0x3f) == 0x20)
+ printf "| H: refc-bin "
+ else
+ if ((($arg0) & 0x3f) == 0x8)
+ # pos-bignum
+ printf "| H:bignum %3u ", ($arg0) >> 6
+ else
+ if ((($arg0) & 0x3f) == 0x14)
+ printf "| H:fun %6u ", ($arg0) >> 6
+ else
+ if ((($arg0) & 0xbc) == 0x3c)
+ set $etp_heapdump_skips = (($arg0)>>(6+2)) & 0xff
+ printf "| flatmap %5u ", $etp_heapdump_skips
+ else
+ if ((($arg0) & 0xbc) == 0xbc)
+ set $etp_heapdump_skips = (($arg0)>>(6+2)) & 0xff
+ printf "| hashmap %4u ", $etp_heapdump_skips
+ else
+ printf "| header %5u ", ($arg0) >> 6
+ end
+ end
+ end
+ end
+ end
+ end
end
end
end
@@ -2211,10 +2352,8 @@ define etp-monitor-info-int
printf "\n Other: "
etp-1 $etp_mon->other.item
end
- if $etp_mon->type == 7
+ if $etp_mon->type == 8
printf "Alias"
- printf "\n Other: "
- etp-1 $etp_mon->other.item
end
printf "\n"
etp-mon-lnk-flags-int $etp_mon->flags
@@ -2356,7 +2495,7 @@ define etp-proc-state-int
printf "active | "
end
if ($arg0 & 0x1000)
- printf "unused | "
+ printf "maybe-self-sigs | "
end
if ($arg0 & 0x800)
printf "exiting | "
@@ -2448,6 +2587,9 @@ define etp-proc-flags-int
printf "GARBAGE<%x> ", ($arg0 & ~((1 << 25)-1))
end
if ($arg0 & (1 << 24))
+ printf "DEBUG-forced-trap "
+ end
+ if ($arg0 & (1 << 23))
printf "fragmented-send "
end
if ($arg0 & (1 << 22))
@@ -3088,6 +3230,196 @@ document etp-ports
%---------------------------------------------------------------------------
end
+define etp-dist-entry
+ set $ede_de = $arg0
+ printf " Name: "
+ etp $ede_de->sysname
+ printf " State: "
+ if $ede_de->state == 0
+ printf "IDLE\n"
+ end
+ if $ede_de->state == 1
+ printf "PENDING\n"
+ end
+ if $ede_de->state == 2
+ printf "CONNECTED\n"
+ end
+ if $ede_de->state == 4
+ printf "EXITING\n"
+ end
+ printf " Creation: %ld\n", $ede_de->creation
+ printf " Queue Flags: "
+ if $ede_de->qflgs.counter & (1 << 0)
+ printf "BUSY "
+ end
+ if $ede_de->qflgs.counter & (1 << 1)
+ printf "EXIT "
+ end
+ if $ede_de->qflgs.counter & (1 << 2)
+ printf "REQ_INFO "
+ end
+ if $ede_de->qflgs.counter & (1 << 3)
+ printf "PORT_CTRL "
+ end
+ if $ede_de->qflgs.counter & (1 << 4)
+ printf "PROC_CTRL "
+ end
+ printf "\n Queue Size: %ld\n", $ede_de->qsize.counter
+ printf " Suspended: "
+ set $ede_suspended_first = $ede_de->suspended
+ if $ede_suspended_first != 0
+ etp-1 $ede_suspended_first->u.pid
+ printf " "
+ set $ede_suspended = $ede_suspended_first->next
+ while $ede_suspended != $ede_suspended_first
+ etp-1 $ede_suspended->u.pid
+ printf " "
+ set $ede_suspended = $ede_suspended->next
+ end
+ end
+ printf "\n Flags: "
+ if $ede_de->dflags & ((Uint64)0x01)
+ printf "PUBLISHED "
+ end
+ if $ede_de->dflags & ((Uint64)0x02)
+ printf "ATOM_CACHE "
+ end
+ if $ede_de->dflags & ((Uint64)0x04)
+ printf "EXTENDED_REFERENCES "
+ end
+ if $ede_de->dflags & ((Uint64)0x08)
+ printf "DIST_MONITOR "
+ end
+ if $ede_de->dflags & ((Uint64)0x10)
+ printf "FUN_TAGS "
+ end
+ if $ede_de->dflags & ((Uint64)0x20)
+ printf "DIST_MONITOR_NAME "
+ end
+ if $ede_de->dflags & ((Uint64)0x40)
+ printf "HIDDEN_ATOM_CACHE "
+ end
+ if $ede_de->dflags & ((Uint64)0x80)
+ printf "NEW_FUN_TAGS "
+ end
+ if $ede_de->dflags & ((Uint64)0x100)
+ printf "EXTENDED_PIDS_PORTS "
+ end
+ if $ede_de->dflags & ((Uint64)0x200)
+ printf "EXPORT_PTR_TAG "
+ end
+ if $ede_de->dflags & ((Uint64)0x400)
+ printf "BIT_BINARIES "
+ end
+ if $ede_de->dflags & ((Uint64)0x800)
+ printf "NEW_FLOATS "
+ end
+ if $ede_de->dflags & ((Uint64)0x1000)
+ printf "UNICODE_IO "
+ end
+ if $ede_de->dflags & ((Uint64)0x2000)
+ printf "DIST_HDR_ATOM_CACHE "
+ end
+ if $ede_de->dflags & ((Uint64)0x4000)
+ printf "SMALL_ATOM_TAGS "
+ end
+ if $ede_de->dflags & ((Uint64)0x8000)
+ printf "ETS_COMPRESSED "
+ end
+ if $ede_de->dflags & ((Uint64)0x10000)
+ printf "UTF8_ATOMS "
+ end
+ if $ede_de->dflags & ((Uint64)0x20000)
+ printf "MAP_TAG "
+ end
+ if $ede_de->dflags & ((Uint64)0x40000)
+ printf "BIG_CREATION "
+ end
+ if $ede_de->dflags & ((Uint64)0x80000)
+ printf "SEND_SENDER "
+ end
+ if $ede_de->dflags & ((Uint64)0x100000)
+ printf "BIG_SEQTRACE_LABELS "
+ end
+ if $ede_de->dflags & ((Uint64)0x200000)
+ printf "PENDING_CONNECT "
+ end
+ if $ede_de->dflags & ((Uint64)0x400000)
+ printf "EXIT_PAYLOAD "
+ end
+ if $ede_de->dflags & ((Uint64)0x800000)
+ printf "FRAGMENTS "
+ end
+ if $ede_de->dflags & ((Uint64)0x1000000)
+ printf "HANDSHAKE_23 "
+ end
+ if $ede_de->dflags & ((Uint64)0x2000000)
+ printf "UNLINK_ID "
+ end
+ if $ede_de->dflags & ((Uint64)0x4000000)
+ printf "MANDATORY_25_DIGEST "
+ end
+ if $ede_de->dflags & ((Uint64)0xf8000000)
+ printf "RESERVED "
+ end
+ if $ede_de->dflags & (((Uint64)0x1) << 32)
+ printf "SPAWN "
+ end
+ if $ede_de->dflags & (((Uint64)0x2) << 32)
+ printf "NAME_ME "
+ end
+ if $ede_de->dflags & (((Uint64)0x4) << 32)
+ printf "V4_NC "
+ end
+ if $ede_de->dflags & (((Uint64)0x8) << 32)
+ printf "ALIAS "
+ end
+ printf "\n Pointer: (DistEntry*)%p\n", $ede_de
+end
+
+document etp-dist-entry
+%---------------------------------------------------------------------------
+% etp-dist-entry DistEntry*
+%
+% Print information about the DistEntry*
+%---------------------------------------------------------------------------
+end
+
+define etp-dist
+ set $de = erts_visible_dist_entries
+ while $de != 0
+ printf "--- visible\n"
+ etp-dist-entry $de
+ set $de = $de->next
+ end
+ set $de = erts_hidden_dist_entries
+ while $de != 0
+ printf "--- hidden\n"
+ etp-dist-entry $de
+ set $de = $de->next
+ end
+ set $de = erts_pending_dist_entries
+ while $de != 0
+ printf "--- pending\n"
+ etp-dist-entry $de
+ set $de = $de->next
+ end
+ set $de = erts_not_connected_dist_entries
+ while $de != 0
+ printf "--- not connected\n"
+ etp-dist-entry $de
+ set $de = $de->next
+ end
+end
+
+document etp-dist
+%---------------------------------------------------------------------------
+% etp-dist
+%
+% Print information about all current dist entries
+%---------------------------------------------------------------------------
+end
+
define etp-rq-flags-int
# Args: int
#
@@ -3490,7 +3822,7 @@ document etp-disasm
%---------------------------------------------------------------------------
% etp-fds BeamInstr* (BeamInstr*)
%
-% Disassemble the instructions inbetween arg0 and arg1,
+% Disassemble the instructions between arg0 and arg1,
% if no second argument is given only the current
% instruction is printed.
%---------------------------------------------------------------------------
@@ -4558,7 +4890,7 @@ define etp-lc-dump
if 0 <= $etp_lc_dump_thread_locked->id && $etp_lc_dump_thread_locked->id < sizeof(erts_lock_order)/sizeof(erts_lc_lock_order_t)
printf " %s:", erts_lock_order[$etp_lc_dump_thread_locked->id].name
else
- printf " unkown:"
+ printf " unknown:"
end
if ($etp_lc_dump_thread_locked->extra & 0x3) == 0x3
etp-1 $etp_lc_dump_thread_locked->extra
diff --git a/erts/etc/unix/etp-thr.py b/erts/etc/unix/etp-thr.py
index fb82dcaf1f..be4593039c 100644
--- a/erts/etc/unix/etp-thr.py
+++ b/erts/etc/unix/etp-thr.py
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2013-2016. All Rights Reserved.
+# Copyright Ericsson AB 2013-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -33,6 +33,12 @@ def get_thread_name(t):
return "child_waiter";
elif f.name() == "sched_thread_func":
return "scheduler";
+ elif f.name() == "sched_dirty_cpu_thread_func":
+ return "dirty_cpu_scheduler";
+ elif f.name() == "sched_dirty_io_thread_func":
+ return "dirty_io_scheduler";
+ elif f.name() == "poll_thread":
+ return "poll_thread";
elif f.name() == "aux_thread":
return "aux";
f = f.older();
diff --git a/erts/etc/unix/etp.py b/erts/etc/unix/etp.py
index 38c9e18408..53b8bd173f 100644
--- a/erts/etc/unix/etp.py
+++ b/erts/etc/unix/etp.py
@@ -686,7 +686,7 @@ def strip_literal_tag(valobj):
return valobj
def init(target):
- names = ['beam_apply', 'beam_normal_exit', 'beam_exit', 'beam_save_calls',
+ names = ['beam_run_process', 'beam_normal_exit', 'beam_exit', 'beam_save_calls',
'beam_bif_export_trap', 'beam_export_trampoline', 'beam_continue_exit',
'beam_return_to_trace', 'beam_return_trace', 'beam_exception_trace',
'beam_return_time_trace']
diff --git a/erts/etc/unix/format_man_pages b/erts/etc/unix/format_man_pages
index 0afff13571..851ec31076 100644
--- a/erts/etc/unix/format_man_pages
+++ b/erts/etc/unix/format_man_pages
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -92,7 +92,7 @@ case :"$TARGET" in
## /usr/sbin/makewhatis -v $ERL_ROOT/man -c $ERL_ROOT/man > /dev/null 2>&1
if [ ! -x /usr/bin/groff ]; then
- echo "Cannot find groff - no formating of manual pages"
+ echo "Cannot find groff - no formatting of manual pages"
exit
fi
diff --git a/erts/etc/unix/jit-reader.c b/erts/etc/unix/jit-reader.c
index 83481ba4f2..4b2714222a 100644
--- a/erts/etc/unix/jit-reader.c
+++ b/erts/etc/unix/jit-reader.c
@@ -22,66 +22,187 @@ static FILE *log = NULL;
#define LOG(...)
#endif
+typedef enum {
+ X64_RBP = 6, /* Frame pointer iff native frames are enabled */
+ X64_RSP = 7, /* Stack pointer when using native stack */
+ X64_R12 = 12, /* Stack pointer when using non-native stack */
+ X64_R13 = 13, /* Current process */
+ X64_RIP = 16
+} X64Register;
+
+typedef enum {
+ /* Return address only */
+ ERTS_FRAME_LAYOUT_RA,
+ /* Frame pointer, return address */
+ ERTS_FRAME_LAYOUT_FP_RA
+} ErtsFrameLayout;
+
+struct emulator_info {
+ /* 0 = regular, 1 = frame pointers */
+ int frame_layout;
+ const void *normal_exit;
+};
+
+struct module_info {
+ uint64_t base_address;
+ uint32_t range_count;
+ uint32_t code_size;
+ /* Module name, including null terminator. */
+ uint16_t name_length;
+ char name[];
+ /* array of range_info structures */
+};
+
+struct range_info {
+ uint32_t start_offset;
+ uint32_t end_offset;
+ uint32_t line_count;
+ /* Range name, including null terminator. */
+ uint16_t name_length;
+ char name[];
+ /* array of line_info structures */
+};
+
+struct line_info {
+ uint32_t start_offset;
+ uint32_t line_number;
+ /* File name, including null terminator. */
+ uint16_t file_length;
+ char file[];
+};
+
+enum debug_info_header {
+ DEBUG_INFO_HEADER_EMULATOR = 0,
+ DEBUG_INFO_HEADER_MODULE = 1,
+};
+
+struct debug_info {
+ enum debug_info_header header;
+ union {
+ struct emulator_info emu;
+ struct module_info mod;
+ } payload;
+};
typedef struct range {
GDB_CORE_ADDR start;
GDB_CORE_ADDR end;
- int global;
+#ifdef HARD_DEBUG
char *name;
+#endif
} range;
typedef struct priv {
range *ranges;
int num_ranges;
- uint64_t normal_exit;
+ ErtsFrameLayout frame_layout;
+ const void *normal_exit;
} priv;
+static enum gdb_status read_module_info(struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ struct module_info *module_info) {
+ struct gdb_object *obj = cb->object_open(cb);
+ GDB_CORE_ADDR mod_start, mod_end;
+ char *symfile = (char*)module_info;
+ priv *priv = self->priv_data;
+
+ symfile += sizeof(*module_info) + module_info->name_length;
+
+ mod_start = module_info->base_address;
+ mod_end = mod_start + module_info->code_size;
+
+ priv->ranges = realloc(priv->ranges, (priv->num_ranges + 1) * sizeof(range));
+ priv->ranges[priv->num_ranges].start = mod_start;
+ priv->ranges[priv->num_ranges].end = mod_end;
+#ifdef HARD_DEBUG
+ priv->ranges[priv->num_ranges].name = strdup(module_info->name);
+#endif
+ priv->num_ranges += 1;
+
+ LOG("Add module `%s` (0x%lx, 0x%lx)\r\n",
+ module_info->name, mod_start, mod_end);
+
+ for (int range = 0; range < module_info->range_count; range++) {
+ struct range_info *range_info;
+ struct gdb_symtab *symtab;
+ GDB_CORE_ADDR begin, end;
+
+ range_info = (struct range_info *)symfile;
+ symfile += sizeof(*range_info) + range_info->name_length;
+
+ begin = mod_start + range_info->start_offset;
+ end = mod_start + range_info->end_offset;
+
+ LOG("Add range `%s` (0x%lx, 0x%lx), %u lines\r\n",
+ range_info->name,
+ begin, end,
+ range_info->line_count);
+
+ /* A bug in GDB < 9 forces us to open and close the symtab for each
+ * iteration. */
+ symtab = cb->symtab_open(cb, obj, module_info->name);
+ cb->block_open(cb, symtab, NULL, begin, end, range_info->name);
+ cb->symtab_close(cb, symtab);
+
+ for (int line = 0; line < range_info->line_count; line++) {
+ struct gdb_line_mapping line_mapping;
+ struct line_info *line_info;
+
+ line_info = (struct line_info *)symfile;
+ symfile += sizeof(*line_info) + line_info->file_length;
+
+ line_mapping.pc = mod_start + line_info->start_offset;
+ line_mapping.line = line_info->line_number;
+
+ LOG("\t%s:%u\r\n", line_info->file, line_info->line_number);
+
+ /* The symbol table must be opened and closed on every single line
+ * for file names to work properly, as there is no other way to
+ * tell GDB that a certain line belongs to a different file than
+ * the rest of the table. Sigh. */
+ symtab = cb->symtab_open(cb, obj, line_info->file);
+
+ cb->block_open(cb, symtab, NULL, line_mapping.pc, end,
+ range_info->name);
+ cb->line_mapping_add(cb, symtab, 1, &line_mapping);
+ cb->symtab_close(cb, symtab);
+ }
+ }
+
+ cb->object_close(cb, obj);
+
+ return GDB_SUCCESS;
+}
+
+static enum gdb_status read_emulator_info(struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ struct emulator_info *emulator_info) {
+ priv *priv = self->priv_data;
+
+ priv->frame_layout = emulator_info->frame_layout;
+ priv->normal_exit = emulator_info->normal_exit;
+
+ LOG("initialize: frame layout = %i\r\n", priv->frame_layout);
+
+ return GDB_SUCCESS;
+}
static enum gdb_status read_debug_info(struct gdb_reader_funcs *self,
struct gdb_symbol_callbacks *cb,
void *memory, long memory_sz) {
- priv *priv = self->priv_data;
- uint64_t num_functions = *(uint64_t*)memory;
- if (num_functions == 0) {
- /* Initialize */
- priv->normal_exit = *(uint64_t*)(memory + sizeof(uint64_t));
- LOG("initialize: normal_exit=%p\r\n",(void*)priv->normal_exit);
- } else {
- GDB_CORE_ADDR mod_start = *(GDB_CORE_ADDR *)(memory + sizeof(uint64_t));
- GDB_CORE_ADDR mod_end = mod_start + *(uint64_t*)(memory + sizeof(uint64_t)*2);
- char* module = memory + sizeof(uint64_t)*3;
- char* curr = module + strlen(module) + 1;
- int i;
- struct gdb_object *obj = cb->object_open(cb);
-
- priv->ranges = realloc(priv->ranges, sizeof(range) * ++priv->num_ranges);
- priv->ranges[priv->num_ranges-1].start = mod_start;
- priv->ranges[priv->num_ranges-1].end = mod_end;
- priv->ranges[priv->num_ranges-1].name = strdup(module);
- priv->ranges[priv->num_ranges-1].global = !strcmp(module, "global");
-
- LOG("Add module %s (0x%lx, 0x%lx)\r\n", module, mod_start, mod_end);
-
- for (i = 0; i < num_functions; i++) {
- // get begin and end of code segment
- // A bug in GDB < 9 forces us to open and close the symtab for each iteration
- struct gdb_symtab *symtab = cb->symtab_open(cb, obj, module);
- GDB_CORE_ADDR begin = *(GDB_CORE_ADDR*)curr;
- GDB_CORE_ADDR end = *(GDB_CORE_ADDR*)(curr + sizeof(GDB_CORE_ADDR));
- // get name of function
- const char *name = (const char*)(curr + sizeof(GDB_CORE_ADDR) * 2);
- curr += strlen(name) + 1 + sizeof(GDB_CORE_ADDR) * 2;
-
- LOG("Add %s (0x%lx, 0x%lx)\r\n", name, begin, end);
-
- // returned value has no use
- cb->block_open(cb, symtab, NULL, begin, end, name);
- cb->symtab_close(cb, symtab);
- }
+ struct debug_info *debug_info = memory;
+
+ (void)memory_sz;
- cb->object_close(cb, obj);
+ switch (debug_info->header) {
+ case DEBUG_INFO_HEADER_EMULATOR:
+ return read_emulator_info(self, cb, &debug_info->payload.emu);
+ case DEBUG_INFO_HEADER_MODULE:
+ return read_module_info(self, cb, &debug_info->payload.mod);
}
- return GDB_SUCCESS;
+
+ return GDB_FAIL;
}
static void regfree(struct gdb_reg_value *reg) {
@@ -89,132 +210,149 @@ static void regfree(struct gdb_reg_value *reg) {
}
static struct range *get_range(priv *priv, GDB_CORE_ADDR rip) {
- int i;
- for (i = 0; i < priv->num_ranges; i++)
- if (rip >= priv->ranges[i].start && rip < priv->ranges[i].end)
+ for (int i = 0; i < priv->num_ranges; i++) {
+ if (rip >= priv->ranges[i].start && rip < priv->ranges[i].end) {
return &priv->ranges[i];
+ }
+ }
+
return NULL;
}
-static enum gdb_status unwind(struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cb) {
- int i;
- priv *priv = self->priv_data;
- GDB_CORE_ADDR rip = *(GDB_CORE_ADDR*)cb->reg_get(cb,16)->value;
- GDB_CORE_ADDR rsp = *(GDB_CORE_ADDR*)cb->reg_get(cb,7)->value;
- GDB_CORE_ADDR rbp = *(GDB_CORE_ADDR*)cb->reg_get(cb,6)->value;
- struct range *range = get_range(priv, rip);
+static enum gdb_status unwind(struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb) {
+ GDB_CORE_ADDR rbp, rsp, rip;
+ struct range *range;
+ priv *priv;
+
+ rbp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RBP)->value;
+ rsp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RSP)->value;
+ rip = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RIP)->value;
+
+ priv = self->priv_data;
+ range = get_range(priv, rip);
/* Check that rip points to one of the addresses that we handle */
if (range) {
- struct gdb_reg_value *prev_rsp = malloc(sizeof(struct gdb_reg_value) + sizeof(char*)),
- *prev_rip = malloc(sizeof(struct gdb_reg_value) + sizeof(char*)),
- *prev_rbp = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
-
- LOG("UNWIND match %s: rip: 0x%lx rsp: 0x%lx rbp: 0x%lx \r\n", range->name, rip, rsp, rbp);
- /* We use the normal frame-pointer logic to unwind the stack, which means
- that rbp will point to where we stored the previous frames rbp. Also
- the previous frames address will be at rbp + 1 and the previous frames
- rsp will be rbp + 2.
-
- 0x00: <- prev_rsp
- 0x80: prev call addr
- 0x10: prev rbp <- curr rbp
- 0x18: current frame
- 0x20: <- curr rip
-
- */
-
- for (i = 0; i < 16; i++) {
- if (i != 16 && i != 7 && i != 6) {
- struct gdb_reg_value *reg = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
- reg->free = &regfree;
- reg->defined = 1;
- reg->size = sizeof(char*);
- *(GDB_CORE_ADDR*)reg->value = *(GDB_CORE_ADDR*)cb->reg_get(cb,i)->value;
- cb->reg_set(cb, i, reg);
- }
- }
+ struct gdb_reg_value *prev_rbp, *prev_rsp, *prev_rip;
+
+ prev_rbp = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
+ prev_rsp = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
+ prev_rip = malloc(sizeof(struct gdb_reg_value) + sizeof(char*));
+
+ LOG("UNWIND match %s: rbp: 0x%lx rsp: 0x%lx rip: 0x%lx \r\n",
+ range->name, rbp, rsp, rip);
- prev_rsp->free = &regfree;
- prev_rsp->defined = 1;
- prev_rsp->size = sizeof(char*);
prev_rbp->free = &regfree;
prev_rbp->defined = 1;
prev_rbp->size = sizeof(char*);
+ prev_rsp->free = &regfree;
+ prev_rsp->defined = 1;
+ prev_rsp->size = sizeof(char*);
prev_rip->free = &regfree;
prev_rip->defined = 1;
prev_rip->size = sizeof(char*);
- if (range->global) {
-
- cb->target_read(rbp + 1 * sizeof(char*), &prev_rip->value, sizeof(char*));
- ((GDB_CORE_ADDR*)prev_rsp->value)[0] = rbp + sizeof(char*) * 2;
- cb->target_read(rbp + 0 * sizeof(char*), &prev_rbp->value, sizeof(char*));
-
+ if (priv->frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
+ /* Frame pointers are enabled, which means that rbp will point to
+ * where we stored the previous frames rbp. Also the previous
+ * frames address will be at rbp + 8 and the previous frames rsp
+ * will be rbp + 16.
+ *
+ * 0x00: <- prev_rsp
+ * 0x08: prev call addr
+ * 0x10: prev rbp <- curr rbp
+ * 0x18: current frame
+ * 0x20: <- curr rip */
+ cb->target_read(rbp + 1 * sizeof(char*), &prev_rip->value,
+ sizeof(char*));
+ cb->target_read(rbp + 0 * sizeof(char*), &prev_rbp->value,
+ sizeof(char*));
+ *(GDB_CORE_ADDR*)prev_rsp->value = rbp + sizeof(char*[2]);
} else {
+ /* Normal frame layout, we need to scan the stack. */
+ cb->target_read(rsp, &prev_rip->value, sizeof(char*));
- if (rip == priv->normal_exit) {
- LOG("Normal exit\r\n");
- ((GDB_CORE_ADDR*)prev_rsp->value)[0] = rsp;
- ((GDB_CORE_ADDR*)prev_rbp->value)[0] = rbp;
- ((GDB_CORE_ADDR*)prev_rip->value)[0] = rip;
- } else {
+ for (rsp += sizeof(char*); ; rsp += sizeof(char*)) {
cb->target_read(rsp, &prev_rip->value, sizeof(char*));
- for (rsp += sizeof(char*); ; rsp += sizeof(char*)) {
- cb->target_read(rsp, &prev_rip->value, sizeof(char*));
- LOG("rsp: 0x%lx rip: 0x%lx\r\n", rsp, *(GDB_CORE_ADDR*)prev_rip->value);
- /* Check if it is a cp */
- if ((*(GDB_CORE_ADDR*)prev_rip->value & 0x3) == 0) {
- break;
- }
+ LOG("rsp: 0x%lx rip: 0x%lx\r\n",
+ rsp, *(GDB_CORE_ADDR*)prev_rip->value);
+
+ /* Check if it is a cp */
+ if ((*(GDB_CORE_ADDR*)prev_rip->value & 0x3) == 0) {
+ break;
}
- ((GDB_CORE_ADDR*)prev_rsp->value)[0] = rsp;
- ((GDB_CORE_ADDR*)prev_rbp->value)[0] = rsp - sizeof(char*);
}
+
+ *(GDB_CORE_ADDR*)prev_rsp->value = rsp;
+ *(GDB_CORE_ADDR*)prev_rbp->value = rsp - sizeof(char*);
+ }
+
+ if (*(GDB_CORE_ADDR*)prev_rip->value == (uintptr_t)priv->normal_exit) {
+ LOG("Normal exit\r\n");
+ *(GDB_CORE_ADDR*)prev_rsp->value = 0;
+ *(GDB_CORE_ADDR*)prev_rbp->value = 0;
+ } else {
+ LOG("UNWIND prev: rbp: 0x%lx rsp: 0x%lx rip: 0x%lx\r\n",
+ *(GDB_CORE_ADDR*)prev_rbp->value,
+ *(GDB_CORE_ADDR*)prev_rsp->value,
+ *(GDB_CORE_ADDR*)prev_rip->value);
}
- LOG("UNWIND prev: rip: 0x%lx rsp: 0x%lx rbp: 0x%lx\r\n",
- *(GDB_CORE_ADDR*)prev_rip->value,
- *(GDB_CORE_ADDR*)prev_rsp->value,
- *(GDB_CORE_ADDR*)prev_rbp->value);
+ cb->reg_set(cb, X64_RIP, prev_rip);
+ cb->reg_set(cb, X64_RSP, prev_rsp);
+ cb->reg_set(cb, X64_RBP, prev_rbp);
- cb->reg_set(cb, 16, prev_rip);
- cb->reg_set(cb, 7, prev_rsp);
- cb->reg_set(cb, 6, prev_rbp);
return GDB_SUCCESS;
}
- LOG("UNWIND no match: rip: 0x%lx rsp: 0x%lx rbp: 0x%lx\r\n", rip, rsp, rbp);
+
+ LOG("UNWIND no match: rbp: 0x%lx rsp: 0x%lx rip: 0x%lx\r\n", rbp, rsp, rip);
return GDB_FAIL;
}
-static struct gdb_frame_id get_frame_id(struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cb){
- priv *priv = self->priv_data;
+static struct gdb_frame_id get_frame_id(struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb){
struct gdb_frame_id frame = {0, 0};
- GDB_CORE_ADDR rip = *(GDB_CORE_ADDR*)cb->reg_get(cb,16)->value;
- GDB_CORE_ADDR rbp = *(GDB_CORE_ADDR*)cb->reg_get(cb,6)->value;
- GDB_CORE_ADDR rsp = *(GDB_CORE_ADDR*)cb->reg_get(cb,7)->value;
- struct range *range = get_range(priv, rip);
+ GDB_CORE_ADDR rbp, rsp, rip;
+ struct range *range;
+ priv *priv;
+
+ rbp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RBP)->value;
+ rsp = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RSP)->value;
+ rip = *(GDB_CORE_ADDR*)cb->reg_get(cb, X64_RIP)->value;
+
+ priv = self->priv_data;
+ range = get_range(priv, rip);
+
LOG("FRAME: rip: 0x%lx rsp: 0x%lx rbp: 0x%lx \r\n", rip, rsp, rbp);
+
if (range) {
frame.code_address = rip;
- if (range->global) {
+
+ if (priv->frame_layout == ERTS_FRAME_LAYOUT_FP_RA) {
frame.stack_address = rbp + sizeof(char*);
} else {
GDB_CORE_ADDR prev_rip;
+
for (rsp += sizeof(char*); ; rsp += sizeof(char*)) {
cb->target_read(rsp, &prev_rip, sizeof(char*));
+
LOG("rsp: 0x%lx rip: 0x%lx\r\n", rsp, prev_rip);
+
/* Check if it is a cp */
if ((prev_rip & 0x3) == 0) {
break;
}
}
+
frame.stack_address = rsp;
}
}
+
LOG("FRAME: code_address: 0x%lx stack_address: 0x%lx\r\n",
frame.code_address, frame.stack_address);
+
return frame;
}
@@ -225,6 +363,7 @@ static void destroy(struct gdb_reader_funcs *self){
struct gdb_reader_funcs *gdb_init_reader(void){
struct gdb_reader_funcs *funcs = malloc(sizeof(struct gdb_reader_funcs));
priv *priv_data = malloc(sizeof(priv));
+
priv_data->num_ranges = 1;
priv_data->ranges = malloc(sizeof(range));
priv_data->ranges[0].start = 0;
diff --git a/erts/etc/unix/makewhatis b/erts/etc/unix/makewhatis
index 047c6efdfa..0d047fe8c4 100644
--- a/erts/etc/unix/makewhatis
+++ b/erts/etc/unix/makewhatis
@@ -22,7 +22,7 @@
# on my 486DX66).
# 960401 - aeb: slight adaptation to work correctly with cat pages.
# 960510 - added fixes by brennan@raven.ca.boeing.com, author of mawk.
-# 971012 - replaced "test -z" - it doesnt work on SunOS 4.1.3_U1.
+# 971012 - replaced "test -z" - it doesn't work on SunOS 4.1.3_U1.
# 980710 - be more careful with TMPFILE
#
# Note for Slackware users: "makewhatis -v -w -c" will work.
@@ -40,7 +40,7 @@ DEFCATPATH=/usr/man/preformat:/usr/man
# We try here to be careful (and avoid preconstructed symlinks)
# in case makewhatis is run as root, by creating a subdirectory of /tmp.
# If that fails we use $HOME.
-# The code below uses test -O which doesnt work on all systems.
+# The code below uses test -O which doesn't work on all systems.
TMPFILE=$HOME/whatis$$
TMPFILEDIR=/tmp/whatis$$
if [ ! -d $TMPFILEDIR ]; then
diff --git a/erts/etc/unix/run_erl.c b/erts/etc/unix/run_erl.c
index 73758daec8..6157646630 100644
--- a/erts/etc/unix/run_erl.c
+++ b/erts/etc/unix/run_erl.c
@@ -828,7 +828,7 @@ static int find_next_log_num(void) {
/* open_log()
* Opens a log file (with given index) for writing. Writing may be
- * at the end or a trucnating write, according to flags.
+ * at the end or a truncating write, according to flags.
* A LOGGING STARTED and time stamp message is inserted into the log file
*/
static int open_log(int log_num, int flags)
@@ -988,7 +988,7 @@ static int open_pty_master(char **ptyslave, int *sfdp)
/* X is in "pqrs" and Y in "0123456789abcdef" but FreeBSD */
/* and some Linux version has extended this. */
- /* This code could probebly be improved alot. For example look at */
+ /* This code could probebly be improved a lot. For example look at */
/* http://www.xcf.berkeley.edu/~ali/K0D/UNIX/PTY/code/pty.c.html */
/* http://www.xcf.berkeley.edu/~ali/K0D/UNIX/PTY/code/upty.h.html */
@@ -1368,7 +1368,7 @@ static int sf_close(int fd) {
return close(fd);
}
-/* Extract any control sequences that are ment only for run_erl
+/* Extract any control sequences that are meant only for run_erl
* and should not be forwarded to the pty.
*/
static int extract_ctrl_seq(char* buf, int len)
diff --git a/erts/etc/unix/start.src b/erts/etc/unix/start.src
index 4cf0e899e4..e645e3a18b 100644
--- a/erts/etc/unix/start.src
+++ b/erts/etc/unix/start.src
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2020. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -25,9 +25,31 @@
#
# Usage: start [Data]
#
+prog="$0"
+progdir="`dirname ${prog}`"
+dyn_erl_path="${progdir}/../erts-%VSN%/bin/dyn_erl"
+if [ ! -f "$dyn_erl_path" ]
+then
+ dyn_erl_path="${progdir}/dyn_erl"
+fi
+
+if [ -f "$dyn_erl_path" ]
+then
+ dyn_rootdir=`${dyn_erl_path} --realpath`
+ dyn_rootdir=`dirname ${dyn_rootdir}`
+ dyn_rootdir=`dirname ${dyn_rootdir}`
+else
+ dyn_rootdir=""
+fi
+
if [ -z "$ERL_ROOTDIR" ]
then
ROOTDIR="%FINAL_ROOTDIR%"
+ if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
+ then
+ # It is likely that the files have been copied or moved
+ ROOTDIR="$dyn_rootdir"
+ fi
else
ROOTDIR="$ERL_ROOTDIR"
fi
diff --git a/erts/etc/unix/to_erl.c b/erts/etc/unix/to_erl.c
index d684b9c3a3..f9ca5f6373 100644
--- a/erts/etc/unix/to_erl.c
+++ b/erts/etc/unix/to_erl.c
@@ -487,7 +487,7 @@ int main(int argc, char **argv)
}
/*
- * Reset terminal characterstics
+ * Reset terminal characteristics
* XXX
*/
tcsetattr(0, TCSADRAIN, &tty_rmode);
diff --git a/erts/etc/win32/cygwin_tools/mingw/cc.sh b/erts/etc/win32/cygwin_tools/mingw/cc.sh
index 0b321a5099..681476d6eb 100755
--- a/erts/etc/win32/cygwin_tools/mingw/cc.sh
+++ b/erts/etc/win32/cygwin_tools/mingw/cc.sh
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2016. All Rights Reserved.
+# Copyright Ericsson AB 2006-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -269,7 +269,7 @@ if [ $LINKING = true ]; then
*)
out_spec="-o $OUTFILE";;
esac
- # Descide which standard library to link against
+ # Decide which standard library to link against
case $MD in
-ML)
stdlib="-lLIBC";;
diff --git a/erts/etc/win32/cygwin_tools/mingw/coffix.c b/erts/etc/win32/cygwin_tools/mingw/coffix.c
index ff3f3de3d1..4ba0ae04e5 100644
--- a/erts/etc/win32/cygwin_tools/mingw/coffix.c
+++ b/erts/etc/win32/cygwin_tools/mingw/coffix.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2006-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ static int v_printf(char *format, ...);
char *progname;
-int verbouse = 0;
+int verbose = 0;
int main(int argc, char **argv)
{
@@ -66,7 +66,7 @@ int main(int argc, char **argv)
break;
case 'v':
case 'V':
- verbouse = 1;
+ verbose = 1;
default:
fprintf(stderr, "%s: unknown option %s\n", progname, argv[findex]);
break;
@@ -152,7 +152,7 @@ static int v_printf(char *format, ...)
{
va_list ap;
int ret = 0;
- if (verbouse) {
+ if (verbose) {
va_start(ap, format);
ret = vfprintf(stdout, format, ap);
va_end(ap);
diff --git a/erts/etc/win32/cygwin_tools/vc/cc.sh b/erts/etc/win32/cygwin_tools/vc/cc.sh
index 9eeb004f0e..5dc9666eea 100755
--- a/erts/etc/win32/cygwin_tools/vc/cc.sh
+++ b/erts/etc/win32/cygwin_tools/vc/cc.sh
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2016. All Rights Reserved.
+# Copyright Ericsson AB 2002-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ ERR_FILE=/tmp/cl.exe.$$.2
MD_FORCED=false
# If we're preprocession (only) i.e. -E
PREPROCESSING=false
-# If we're generating dependencies (implies preprocesing)
+# If we're generating dependencies (implies preprocessing)
DEPENDENCIES=false
# If this is supposed to be a debug build
DEBUG_BUILD=false
@@ -297,7 +297,7 @@ if [ $LINKING = true ]; then
*)
out_spec="-o $OUTFILE";;
esac
- # Descide which standard library to link against
+ # Decide which standard library to link against
case $MD in
-ML)
stdlib="-lLIBC";;
diff --git a/erts/etc/win32/cygwin_tools/vc/coffix.c b/erts/etc/win32/cygwin_tools/vc/coffix.c
index bf1096c425..3221ad6d85 100644
--- a/erts/etc/win32/cygwin_tools/vc/coffix.c
+++ b/erts/etc/win32/cygwin_tools/vc/coffix.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ static int v_printf(char *format, ...);
char *progname;
-int verbouse = 0;
+int verbose = 0;
int main(int argc, char **argv)
{
@@ -66,7 +66,7 @@ int main(int argc, char **argv)
break;
case 'v':
case 'V':
- verbouse = 1;
+ verbose = 1;
default:
fprintf(stderr, "%s: unknown option %s\n", progname, argv[findex]);
break;
@@ -152,7 +152,7 @@ static int v_printf(char *format, ...)
{
va_list ap;
int ret = 0;
- if (verbouse) {
+ if (verbose) {
va_start(ap, format);
ret = vfprintf(stdout, format, ap);
va_end(ap);
diff --git a/erts/etc/win32/erl.rc b/erts/etc/win32/erl.rc
index 035c4a2881..13974c750b 100644
--- a/erts/etc/win32/erl.rc
+++ b/erts/etc/win32/erl.rc
@@ -1,7 +1,7 @@
//
// %CopyrightBegin%
//
-// Copyright Ericsson AB 1998-2021. All Rights Reserved.
+// Copyright Ericsson AB 1998-2023. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -31,10 +31,10 @@ VS_VERSION_INFO VERSIONINFO
{
BLOCK "040904e4"
{
- VALUE "CompanyName", "Ericsson\0"
+ VALUE "CompanyName", "Ericsson AB\0"
VALUE "FileDescription", "Erlang\0"
VALUE "FileVersion", ERTS_VERSION_STR
- VALUE "LegalCopyright", "Ericsson. All rights reserved.\0"
+ VALUE "LegalCopyright", OTP_LEGAL_STR
VALUE "ProductName", "Erlang/OTP\0"
VALUE "ProductVersion", OTP_VERSION_STR
}
diff --git a/erts/etc/win32/erl_log.c b/erts/etc/win32/erl_log.c
index b77491b169..8cebef2719 100644
--- a/erts/etc/win32/erl_log.c
+++ b/erts/etc/win32/erl_log.c
@@ -21,7 +21,7 @@
* erl_log:
*
* Provides a simple debug log for the Erlang emulator.
- * It simples echoes its standard intput to the console.
+ * It simples echoes its standard input to the console.
*
* Author: Bjorn Gustavsson
* Created: 1996-12-06
diff --git a/erts/etc/win32/erlsrv/erlsrv_service.c b/erts/etc/win32/erlsrv/erlsrv_service.c
index fb0ca120ac..2745888091 100644
--- a/erts/etc/win32/erlsrv/erlsrv_service.c
+++ b/erts/etc/win32/erlsrv/erlsrv_service.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -535,10 +535,14 @@ static BOOL start_a_service(ServerInfo *srvi){
HANDLE hJob = CreateJobObject(NULL, NULL);
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
/*
- * Causes all processes associated with the job to terminate when the
- * last handle to the job is closed.
- */
- jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ * JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
+ * Causes all processes associated with the job to terminate when the
+ * last handle to the job is closed.
+ *
+ * JOB_OBJECT_LIMIT_BREAKAWAY_OK
+ * Sometimes we want to break out, for example to start programs in another windows session
+ */
+ jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK;
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));
if (AssignProcessToJobObject(hJob, GetCurrentProcess()) == FALSE) {
log_error(L"Could not AssignProcessToJobObject");
@@ -920,7 +924,7 @@ static VOID WINAPI service_main_loop(DWORD argc, wchar_t **argv){
L"The service is not restarted, ignoring OnFail option.");
} else {
log_error(L"Erlang machine seems to die "
- L"continously, not restarted.");
+ L"continuously, not restarted.");
}
CloseHandle(eventStop);
set_stopped(ERROR_PROCESS_ABORTED);
diff --git a/erts/etc/win32/msys_tools/vc/cc.sh b/erts/etc/win32/msys_tools/vc/cc.sh
index 0c15139bd5..ee24e4bab6 100644
--- a/erts/etc/win32/msys_tools/vc/cc.sh
+++ b/erts/etc/win32/msys_tools/vc/cc.sh
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2020. All Rights Reserved.
+# Copyright Ericsson AB 2002-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ ERR_FILE=/tmp/cl.exe.$$.2
MD_FORCED=false
# If we're preprocession (only) i.e. -E
PREPROCESSING=false
-# If we're generating dependencies (implies preprocesing)
+# If we're generating dependencies (implies preprocessing)
DEPENDENCIES=false
# If this is supposed to be a debug build
DEBUG_BUILD=false
@@ -310,7 +310,7 @@ if [ $LINKING = true ]; then
*)
out_spec="-o $OUTFILE";;
esac
- # Descide which standard library to link against
+ # Decide which standard library to link against
case $MD in
-ML)
stdlib="-lLIBC";;
diff --git a/erts/etc/win32/msys_tools/vc/coffix.c b/erts/etc/win32/msys_tools/vc/coffix.c
index bf1096c425..3221ad6d85 100644
--- a/erts/etc/win32/msys_tools/vc/coffix.c
+++ b/erts/etc/win32/msys_tools/vc/coffix.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ static int v_printf(char *format, ...);
char *progname;
-int verbouse = 0;
+int verbose = 0;
int main(int argc, char **argv)
{
@@ -66,7 +66,7 @@ int main(int argc, char **argv)
break;
case 'v':
case 'V':
- verbouse = 1;
+ verbose = 1;
default:
fprintf(stderr, "%s: unknown option %s\n", progname, argv[findex]);
break;
@@ -152,7 +152,7 @@ static int v_printf(char *format, ...)
{
va_list ap;
int ret = 0;
- if (verbouse) {
+ if (verbose) {
va_start(ap, format);
ret = vfprintf(stdout, format, ap);
va_end(ap);
diff --git a/erts/etc/win32/nsis/Makefile b/erts/etc/win32/nsis/Makefile
index a0c21a5f5d..dd4bbd4de6 100644
--- a/erts/etc/win32/nsis/Makefile
+++ b/erts/etc/win32/nsis/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2021. All Rights Reserved.
+# Copyright Ericsson AB 2003-2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -68,18 +68,25 @@ REDIST_DLL_NAME=$(shell (sh ./dll_version_helper.sh -n "$(NICEREDISTFILE)" || ec
# $(info $$REDIST_DLL_NAME = [${REDIST_DLL_NAME}])
# $(info $$REDIST_FILE = [${REDIST_FILE}])
+VERSION_TICKETS_FILE=$(shell (w32_path.sh -m "$(ERL_TOP)/make/otp_version_tickets" 2>/dev/null || echo "NOTFOUND"))
+# NSIS really want the product version number to be at least 4 digits long
+OTP_VERSION_LONG=$(shell $(ERL_TOP)/bootstrap/bin/escript.exe vsn_number.escript $(OTP_VERSION) $(VERSION_TICKETS_FILE))
+YEAR=$(shell date +%Y)
+
release_spec:
@NSIS_VER=`makensis.exe -version`; \
case $$NSIS_VER in \
- v2.0b*) \
+ v2.* | v3.0 | v3.01) \
echo "Unsupported NSIS version: $$NSIS_VER";;\
- v2.* | v3.*) \
- echo '!define OTP_VERSION "$(SYSTEM_VSN)"' > $(VERSION_HEADER);\
- echo '!define OTP_RELEASE_VERSION "$(OTP_VERSION)"' >> $(VERSION_HEADER);\
+ v3.*) \
+ echo '!define OTP_RELEASE "$(SYSTEM_VSN)"' > $(VERSION_HEADER);\
+ echo '!define OTP_VERSION "$(OTP_VERSION)"' >> $(VERSION_HEADER);\
+ echo '!define OTP_VERSION_LONG "$(OTP_VERSION_LONG)"' >> $(VERSION_HEADER);\
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);\
+ echo '!define YEAR "$(YEAR)"' >> $(VERSION_HEADER);\
if [ -f $(CUSTOM_MODERN) ];\
then \
echo '!define HAVE_CUSTOM_MODERN 1' >> $(VERSION_HEADER); \
@@ -96,6 +103,8 @@ release_spec:
then \
echo '!define HAVE_DOCS 1' >> $(VERSION_HEADER); \
fi;\
+ echo "OTP_VERSION = [${OTP_VERSION}]"; \
+ echo "OTP_VERSION_LONG = [${OTP_VERSION_LONG}]"; \
echo "Running $(MAKENSIS) $(MAKENSISFLAGS) erlang20.nsi";\
$(MAKENSIS) $(MAKENSISFLAGS) erlang20.nsi;;\
*) \
diff --git a/erts/etc/win32/nsis/erlang20.nsi b/erts/etc/win32/nsis/erlang20.nsi
index e744db8bf3..d8d1883e3a 100644
--- a/erts/etc/win32/nsis/erlang20.nsi
+++ b/erts/etc/win32/nsis/erlang20.nsi
@@ -7,7 +7,7 @@
;
; %CopyrightBegin%
;
-; Copyright Ericsson AB 2012-2021. All Rights Reserved.
+; Copyright Ericsson AB 2012-2023. All Rights Reserved.
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
!include "erlang.nsh" ; All release specific parameters come from this
- Name "${OTP_PRODUCT} ${OTP_VERSION}"
+ Name "${OTP_PRODUCT} ${OTP_RELEASE}"
!include "MUI.nsh"
!include "WordFunc.nsh"
@@ -52,13 +52,13 @@ Var STARTMENU_FOLDER
!define MY_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
;General
- OutFile "${OUTFILEDIR}\otp_${WINTYPE}_${OTP_RELEASE_VERSION}.exe"
+ OutFile "${OUTFILEDIR}\otp_${WINTYPE}_${OTP_VERSION}.exe"
;Folder selection page
!if ${WINTYPE} == "win64"
- InstallDir "$PROGRAMFILES64\erl-${OTP_RELEASE_VERSION}"
+ InstallDir "$PROGRAMFILES64\Erlang OTP"
!else
- InstallDir "$PROGRAMFILES\erl-${OTP_RELEASE_VERSION}"
+ InstallDir "$PROGRAMFILES\Erlang OTP"
!endif
;Remember install folder
InstallDirRegKey HKLM "SOFTWARE\Ericsson\Erlang\${ERTS_VERSION}" ""
@@ -66,9 +66,9 @@ Var STARTMENU_FOLDER
; Set the default start menu folder
!if ${WINTYPE} == "win64"
- !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${OTP_PRODUCT} ${OTP_VERSION} (x64)"
+ !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${OTP_PRODUCT} ${OTP_RELEASE} (x64)"
!else
- !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${OTP_PRODUCT} ${OTP_VERSION} (i386)"
+ !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${OTP_PRODUCT} ${OTP_RELEASE} (i386)"
!endif
;--------------------------------
@@ -100,6 +100,17 @@ Var STARTMENU_FOLDER
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
+; Installer file properties
+
+VIProductVersion "${OTP_VERSION_LONG}"
+VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "Ericsson AB"
+VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${OTP_VERSION}"
+VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "Erlang/OTP installer"
+VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright Ericsson AB 2010-${YEAR}. All Rights Reserved."
+VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "Erlang/OTP"
+VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "${OTP_VERSION}"
+
+;--------------------------------
;Language Strings
;Description
@@ -144,21 +155,19 @@ SubSection /e "Erlang" SecErlang
Section "Development" SecErlangDev
SectionIn 1 RO
-
+
SetOutPath "$INSTDIR"
-
-; Don't let Users nor Autenticated Users group create new files
-; Avoid dll injection when installing to non /Program Files/ dirs
-
- StrCmp $INSTDIR $InstallDir cp_files
- ; Remove ANY inherited access control
+
+; Don't let Users nor Authenticated Users group create new files
+; Avoid dll injection when installing to non /Program Files/ dirs
+
+ ; Remove ANY inherited access control
ExecShellWait "open" "$SYSDIR\icacls.exe" '"$INSTDIR" /inheritance:r' SW_HIDE
- ; Grant Admin full control
+ ; Grant Admin full control
ExecShellWait "open" "$SYSDIR\icacls.exe" '"$INSTDIR" /grant:r *S-1-5-32-544:(OI)(CI)F' SW_HIDE
- ; Grant Normal Users read+execute control
+ ; Grant Normal Users read+execute control
ExecShellWait "open" "$SYSDIR\icacls.exe" '"$INSTDIR" /grant:r *S-1-1-0:(OI)(CI)RX' SW_HIDE
-cp_files:
File "${TESTROOT}\Install.ini"
File "${TESTROOT}\Install.exe"
SetOutPath "$INSTDIR\releases"
@@ -201,7 +210,7 @@ continue_create:
StrCmp $MYTEMP "" 0 done_startmenu
-; If startmenu was skipped, this might be unnecessary, but wont hurt...
+; If startmenu was skipped, this might be unnecessary, but won't hurt...
WriteRegStr HKCU "Software\Ericsson\Erlang\${ERTS_VERSION}" \
"" $INSTDIR
WriteRegStr HKCU "${MY_STARTMENUPAGE_REGISTRY_KEY}" \
@@ -214,22 +223,28 @@ done_startmenu:
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr HKLM \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
- "DisplayName" "Erlang OTP ${OTP_RELEASE_VERSION} (${ERTS_VERSION})"
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
+ "DisplayName" "Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})"
+ WriteRegStr HKLM \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
+ "DisplayVersion" "${OTP_VERSION}"
+ WriteRegStr HKLM \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
+ "Publisher" "Ericsson AB"
WriteRegStr HKLM \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegDWORD HKLM \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"NoModify" 1
WriteRegDWORD HKLM \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"NoRepair" 1
; Check that the registry could be written, we only check one key,
; but it should be sufficient...
ReadRegStr $MYTEMP HKLM \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"NoRepair"
StrCmp $MYTEMP "" 0 done
@@ -238,16 +253,22 @@ done_startmenu:
; do the things below...
WriteRegStr HKCU \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
- "DisplayName" "Erlang OTP ${OTP_RELEASE_VERSION} (${ERTS_VERSION})"
+ "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
+ "DisplayName" "Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})"
+ WriteRegStr HKCU \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
+ "DisplayVersion" "${OTP_VERSION}"
+ WriteRegStr HKCU \
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
+ "Publisher" "Ericsson AB"
WriteRegStr HKCU \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegDWORD HKCU \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"NoModify" 1
WriteRegDWORD HKCU \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})" \
+ "Software\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP" \
"NoRepair" 1
done:
@@ -464,9 +485,9 @@ noshortcuts:
DeleteRegKey /ifempty HKLM "SOFTWARE\Ericsson\Erlang\${ERTS_VERSION}"
DeleteRegKey /ifempty HKCU "SOFTWARE\Ericsson\Erlang\${ERTS_VERSION}"
DeleteRegKey HKLM \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})"
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP"
DeleteRegKey HKCU \
- "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP ${OTP_VERSION} (${ERTS_VERSION})"
+ "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Erlang OTP"
; Now remove shell/file associations we'we made...
diff --git a/erts/etc/win32/nsis/find_redist.sh b/erts/etc/win32/nsis/find_redist.sh
index f3fa476fec..f551bc7527 100755
--- a/erts/etc/win32/nsis/find_redist.sh
+++ b/erts/etc/win32/nsis/find_redist.sh
@@ -153,7 +153,7 @@ fi
# Frantic search through two roots with different
# version directories. We want to be very specific about the
-# directory structures as we wouldnt want to find the wrong
+# directory structures as we wouldn't want to find the wrong
# redistributables...
#echo $BPATH_LIST
diff --git a/erts/etc/win32/nsis/vsn_number.escript b/erts/etc/win32/nsis/vsn_number.escript
new file mode 100644
index 0000000000..7854860042
--- /dev/null
+++ b/erts/etc/win32/nsis/vsn_number.escript
@@ -0,0 +1,16 @@
+
+
+main([OtpVsn, WinPathFile]) ->
+ try
+ {ok, Bin} = file:read_file(WinPathFile),
+ <<"OTP-", _/binary>> = Bin,
+ case [list_to_integer(Str) || Str <- string:lexemes(OtpVsn, ".")] of
+ [_,_,_,_|_] -> io:format("~s~n", [OtpVsn]);
+ [_,_,_] -> io:format("~s.0~n",[OtpVsn]);
+ [_,_] -> io:format("~s.0.0~n",[OtpVsn]);
+ [_] -> io:format("~s.0.0.0~n",[OtpVsn])
+ end
+ catch _:_R:_ST -> %% release candidate or development branch set fake version as 0.0.0.0
+ %% io:format("Err: ~p ~p~n ~p~n",[_R,_ST, WinPathFile]),
+ io:format("0.0.0.0~n")
+ end.
diff --git a/erts/etc/win32/port_entry.c b/erts/etc/win32/port_entry.c
index 8b1d3a44b8..50d8f31ba2 100644
--- a/erts/etc/win32/port_entry.c
+++ b/erts/etc/win32/port_entry.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
** erlang process is run as a service.
** Note that this entry point is only for
** Console programs, Windowing programs can just route the WM_QUERYENDSESSION
-** and WM_ENDSESSION to the default window procedure to aquire the same
+** and WM_ENDSESSION to the default window procedure to acquire the same
** functionality.
**
** Creator Patrik Nyblom
diff --git a/erts/etc/win32/start_erl.c b/erts/etc/win32/start_erl.c
index 07bcd19b81..b555dc8c1e 100644
--- a/erts/etc/win32/start_erl.c
+++ b/erts/etc/win32/start_erl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -260,7 +260,7 @@ void parse_commandline(void)
fprintf(stderr, "NoConfig=TRUE\n");
#endif
} else {
- fprintf(stderr, "Unkown option: '%S'\n", cmdline);
+ fprintf(stderr, "Unknown option: '%S'\n", cmdline);
exit_help("Unknown command line option");
}
break;
diff --git a/erts/etc/win32/version.h.src b/erts/etc/win32/version.h.src
index 266ebda47d..45c1e9944e 100644
--- a/erts/etc/win32/version.h.src
+++ b/erts/etc/win32/version.h.src
@@ -5,3 +5,5 @@
#define OTP_VERSION_INTS %OTP_VERSION_INTS%
#define OTP_VERSION_STR "%OTP_VERSION%\0"
+
+#define OTP_LEGAL_STR "Copyright Ericsson AB 2010-%YEAR%. All Rights Reserved.\0"
diff --git a/erts/etc/win32/wsl_tools/vc/cc.sh b/erts/etc/win32/wsl_tools/vc/cc.sh
index bc51e7b9b5..5203ff5f17 100755
--- a/erts/etc/win32/wsl_tools/vc/cc.sh
+++ b/erts/etc/win32/wsl_tools/vc/cc.sh
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2021. All Rights Reserved.
+# Copyright Ericsson AB 2002-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,8 +39,10 @@ ERR_FILE=/tmp/cl.exe.$$.2
MD_FORCED=false
# If we're preprocession (only) i.e. -E
PREPROCESSING=false
-# If we're generating dependencies (implies preprocesing)
+# If we're generating dependencies (implies preprocessing)
DEPENDENCIES=false
+# If we're generating fast dependencies
+FAST_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...)
@@ -91,6 +93,9 @@ while test -n "$1" ; do
LINKING=false;;
#CMD="$CMD -c";;
-MM)
+ LINKING=false;
+ FAST_DEPENDENCIES=true;;
+ -MS)
PREPROCESSING=true;
LINKING=false;
DEPENDENCIES=true;;
@@ -225,7 +230,7 @@ mkdir $TMPOBJDIR
WINTMPDIR=`w32_path.sh -w $TMPOBJDIR`
-# Sometimes the file server doesn't keep up (paralell file creation)
+# Sometimes the file server doesn't keep up (parallel file creation)
while true ; do
DIR_EXISTS=$(cd /mnt/c; cmd.exe /C "IF EXIST $WINTMPDIR (echo yes) ELSE (echo no)")
case $DIR_EXISTS in # Contains trash in the end of string
@@ -241,75 +246,139 @@ while true ; do
esac
done
-# Compile
-for x in $SOURCES; do
- # 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...
- if [ $USEABSPATH = true ]; then
- MPATH=`w32_path.sh -a -d $x`
- else
- MPATH=`w32_path.sh -d $x`
- fi
- if [ $PREPROCESSING = true ]; then
- output_flag="-E"
- else
- output_flag="/FS -c -Fo`w32_path.sh -a -d ${output_filename}`"
- fi
+## This is a faster dependency calculation method that
+## only invokes cl.exe once for all files.
+if [ $FAST_DEPENDENCIES = true ]; then
+ MPATH=
+ for x in $SOURCES; do
+ if [ $USEABSPATH = true ]; then
+ MPATH="$MPATH $(w32_path.sh -a -d $x)"
+ else
+ MPATH="$MPATH $(w32_path.sh -d $x)"
+ fi
+ done
params="$COMMON_CFLAGS $MD $DEBUG_FLAGS $OPTIMIZE_FLAGS \
- $CMD ${output_flag} $MPATH"
+ $CMD /showIncludes '-Fo`w32_path.sh -a -d ${TMPOBJDIR}`\\' $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
+ 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
- perl -e '
+ tail -n +2 $ERR_FILE | grep -v LNK1561 >&2
+ if grep "LNK1561" $ERR_FILE; then
+ rm -f $ERR_FILE $MSG_FILE
+ rm -rf $TMPOBJDIR
+ exit $RES
+ fi
+ perl -e '
+my $deps = "";
+my @sources = split(" ",$ARGV[1]);
+
+open(FH, "<", $ARGV[0]) or die $!;
+
+sub flushDeps() {
+ if ($deps ne "") {
+ ## To start a new shell can be very slow so we run all
+ ## the wslpath translations in a single run
+ my @paths = split("\n",`for x in $deps; do wslpath -u "\$x"; done`);
+ foreach (@paths) {
+ print "\\\n $_";
+ }
+ print "\n\n";
+ }
+}
+
+while (<FH>) {
+ $_ =~ tr/\r\n/\n/d;
+ if (/^(.*)\.(c|cpp)$/) {
+ my $target = "$1";
+ flushDeps();
+ $deps = shift(@sources) . " ";
+ print $target.".o:";
+ }
+ if (/^Note: including file:\s*(.*)$/) {
+ ## Ignore any deps that comes from "Program Files"
+ next if /Program Files/;
+ my $file = $1;
+ $file =~ s/\\/\//g;
+ $deps .= "'"'"'$file'"'"' ";
+ }
+}
+flushDeps();
+' $MSG_FILE "$MPATH"
+
+ rm -f $ERR_FILE $MSG_FILE
+else
+ # Compile
+ for x in $SOURCES; do
+ # 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...
+ if [ $USEABSPATH = true ]; then
+ MPATH=`w32_path.sh -a -d $x`
+ else
+ MPATH=`w32_path.sh -d $x`
+ fi
+ if [ $PREPROCESSING = true ]; then
+ output_flag="-E"
+ else
+ output_flag="/FS -c -Fo`w32_path.sh -a -d ${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
+ perl -e '
my $file = "'$x'";
while (<>) {
next unless /^#line/;
@@ -331,18 +400,18 @@ if (@f) {
print "\n\n";
print STDERR "Made dependencies for $file\n";
}' $MSG_FILE
- else
- cat $MSG_FILE
- fi
- fi
- rm -f $ERR_FILE $MSG_FILE
- if [ $RES != 0 ]; then
- echo Failed: cl.exe $params
- rm -rf $TMPOBJDIR
- exit $RES
- fi
-done
-
+ else
+ cat $MSG_FILE
+ fi
+ fi
+ rm -f $ERR_FILE $MSG_FILE
+ if [ $RES != 0 ]; then
+ echo Failed: cl.exe $params
+ rm -rf $TMPOBJDIR
+ exit $RES
+ fi
+ done
+fi
# 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
@@ -360,7 +429,7 @@ if [ $LINKING = true ]; then
*)
out_spec="-o $OUTFILE";;
esac
- # Descide which standard library to link against
+ # Decide which standard library to link against
case $MD in
-ML)
stdlib="-lLIBC";;
diff --git a/erts/etc/win32/wsl_tools/vc/coffix.c b/erts/etc/win32/wsl_tools/vc/coffix.c
index 25b04e12da..5d7c255045 100755
--- a/erts/etc/win32/wsl_tools/vc/coffix.c
+++ b/erts/etc/win32/wsl_tools/vc/coffix.c
@@ -43,7 +43,7 @@ static int v_printf(char *format, ...);
char *progname;
-int verbouse = 0;
+int verbose = 0;
int main(int argc, char **argv)
{
@@ -66,7 +66,7 @@ int main(int argc, char **argv)
break;
case 'v':
case 'V':
- verbouse = 1;
+ verbose = 1;
default:
fprintf(stderr, "%s: unknown option %s\n", progname, argv[findex]);
break;
@@ -152,7 +152,7 @@ static int v_printf(char *format, ...)
{
va_list ap;
int ret = 0;
- if (verbouse) {
+ if (verbose) {
va_start(ap, format);
ret = vfprintf(stdout, format, ap);
va_end(ap);
diff --git a/erts/example/matrix_nif.erl b/erts/example/matrix_nif.erl
index bdc7228ac0..c6420b6de4 100644
--- a/erts/example/matrix_nif.erl
+++ b/erts/example/matrix_nif.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,9 @@
-export([create/3, pos/3, add/2, size_of/1, to_term/1]).
+-nifs([create/3, pos/3, add/2, size_of/1, to_term/1]).
+
+
-define(nif, nif_error(?LINE)).
-on_load(on_load/0).
diff --git a/erts/example/time_compat.erl b/erts/example/time_compat.erl
index 6472a271b6..169f5587b2 100644
--- a/erts/example/time_compat.erl
+++ b/erts/example/time_compat.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
%% versions. This way your code can automatically take advantage
%% of the improvements in the API when available. This is an
%% example of how to implement such an API, but it can be used
-%% as is if you want to. Just add (a preferrably renamed version of)
+%% as is if you want to. Just add (a preferably renamed version of)
%% this module to your project, and call the API via this module
%% instead of calling the BIFs directly.
%%
@@ -199,7 +199,7 @@ unique_integer(Modifiers) ->
case is_valid_modifier_list(Modifiers) of
true ->
%% now() converted to an integer
- %% fullfill the requirements of
+ %% fulfill the requirements of
%% all modifiers: unique, positive,
%% and monotonic...
{MS, S, US} = erlang:now(),
diff --git a/erts/include/erl_memory_trace_parser.h b/erts/include/erl_memory_trace_parser.h
deleted file mode 100644
index 3170ebc0d0..0000000000
--- a/erts/include/erl_memory_trace_parser.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-
-/*
- * Description:
- *
- * Author: Rickard Green
- */
-
-#ifndef ERL_MTRACE_PARSER_H__
-#define ERL_MTRACE_PARSER_H__
-
-#include <stdlib.h>
-#include "erl_fixed_size_int_types.h"
-
-/* emtp_parse() return values */
-#define EMTP_MIN_ERROR EMTP_NO_TRACE_ERROR
-
-#define EMTP_NO_TRACE_ERROR (-11)
-#define EMTP_HEADER_TAG_IN_BODY_ERROR (-10)
-#define EMTP_BODY_TAG_IN_HEADER_ERROR ( -9)
-#define EMTP_NOT_SUPPORTED_MTRACE_VERSION_ERROR ( -8)
-#define EMTP_NOT_AN_ERL_MTRACE_ERROR ( -7)
-#define EMTP_NO_MEMORY_ERROR ( -6)
-#define EMTP_BAD_OP_SIZE_ERROR ( -5)
-#define EMTP_NO_OPERATIONS_ERROR ( -4)
-#define EMTP_NOT_SUPPORTED_64_BITS_TRACE_ERROR ( -3)
-#define EMTP_PARSE_ERROR ( -2)
-#define EMTP_UNKNOWN_TAG_ERROR ( -1)
-#define EMTP_END_OF_TRACE ( 0)
-#define EMTP_END_OF_TRACE_GARBAGE_FOLLOWS ( 1)
-#define EMTP_ALL_OPS_FILLED ( 2)
-#define EMTP_NEED_MORE_TRACE ( 3)
-#define EMTP_HEADER_PARSED ( 4)
-
-/* Allocator flags */
-#define EMTP_ALLOCATOR_FLAG_HAVE_USED_CARRIERS_INFO (1 << 0)
-
-/* Block type flags */
-/* #define EMTP_BLOCK_TYPE_FLAG_X */
-
-
-typedef struct {
- usgnd_int_32 major;
- usgnd_int_32 minor;
-} emtp_version;
-
-typedef struct {
- emtp_version parser;
- emtp_version trace;
-} emtp_versions;
-
-typedef struct {
- int valid;
- usgnd_int_32 flags;
- char * name;
- struct {
- usgnd_int_16 no_providers;
- usgnd_int_16 * provider;
- } carrier;
-} emtp_allocator;
-
-typedef struct {
- int valid;
- usgnd_int_32 flags;
- char * name;
- sgnd_int_32 allocator;
-} emtp_block_type;
-
-typedef struct {
- emtp_versions version;
- int bits;
- char * nodename;
- char * hostname;
- char * pid;
- struct {
- usgnd_int_32 year;
- usgnd_int_32 month;
- usgnd_int_32 day;
- usgnd_int_32 hour;
- usgnd_int_32 minute;
- usgnd_int_32 second;
- usgnd_int_32 micro_second;
- } start_time;
- usgnd_int_16 segment_ix;
- usgnd_int_16 max_allocator_ix;
- emtp_allocator ** allocator;
- usgnd_int_16 max_block_type_ix;
- emtp_block_type ** block_type;
- int have_carrier_info;
- int have_segment_carrier_info;
-} emtp_info;
-
-typedef struct emtp_state_ emtp_state;
-
-enum emtp_op_type_ {
- EMTP_UNDEF = 0,
- EMTP_ALLOC = 1,
- EMTP_REALLOC = 2,
- EMTP_FREE = 3,
- EMTP_CARRIER_ALLOC = 4,
- EMTP_CARRIER_REALLOC = 5,
- EMTP_CARRIER_FREE = 6,
- EMTP_STOP = 7,
- EMTP_EXIT = 8
-};
-
-typedef enum emtp_op_type_ emtp_op_type;
-
-typedef struct {
- usgnd_int_16 type;
- usgnd_int_16 carrier_type;
- usgnd_int_max new_ptr;
- usgnd_int_max prev_ptr;
- usgnd_int_max new_size;
-} emtp_block_op;
-
-typedef struct {
- emtp_op_type type;
- struct {
- usgnd_int_32 secs;
- usgnd_int_32 usecs;
- } time;
- union {
- emtp_block_op block;
- usgnd_int_32 exit_status;
- } u;
-} emtp_operation;
-
-const char *emtp_error_string(int);
-int emtp_get_info(emtp_info *ip, size_t *isz, emtp_state *sp);
-emtp_state *emtp_state_new(void * (*alloc)(size_t),
- void * (*realloc)(void *, size_t),
- void (*free)(void *));
-void emtp_state_destroy(emtp_state *sp);
-int emtp_parse(emtp_state *sp,
- usgnd_int_8 **tracepp, size_t *trace_lenp,
- emtp_operation *op_start, size_t op_size, size_t *op_lenp);
-#endif
diff --git a/erts/include/internal/erl_memory_trace_protocol.h b/erts/include/internal/erl_memory_trace_protocol.h
deleted file mode 100644
index d3e0bcc1f4..0000000000
--- a/erts/include/internal/erl_memory_trace_protocol.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-
-/*
- * Description:
- *
- * Author: Rickard Green
- */
-
-#ifndef ERL_MEMORY_TRACE_PROTOCOL_H__
-#define ERL_MEMORY_TRACE_PROTOCOL_H__
-
-/*
- * Increase ERTS_MT_MAJOR_VSN and set ERTS_MT_MINOR_VSN to 0
- * when backward incompatible changes are made in the protocol.
- *
- * Increase ERTS_MT_MINOR_VSN when backward compatible changes are
- * made in the protocol.
- */
-#define ERTS_MT_MAJOR_VSN (2)
-#define ERTS_MT_MINOR_VSN (0)
-
-/* Trace flags */
-
-#define ERTS_MT_64_BIT_FLAG (1 << 0)
-#define ERTS_MT_CRR_INFO (1 << 1)
-#define ERTS_MT_SEG_CRR_INFO (1 << 2)
-
-/* Header flags */
-/* Allocator flags */
-
-#define ERTS_MT_ALLCTR_USD_CRR_INFO (1 << 0)
-
-/* Block type flags */
-
-
-
-/* Entry tags */
-
-#define ERTS_MT_V1_ALLOCATOR_TAG (1)
-#define ERTS_MT_V1_BLOCK_TYPE_TAG (2)
-#define ERTS_MT_V1_ALLOC_TAG (3)
-#define ERTS_MT_V1_REALLOC_NPB_TAG (4)
-#define ERTS_MT_V1_REALLOC_MV_TAG (5)
-#define ERTS_MT_V1_REALLOC_NMV_TAG (6)
-#define ERTS_MT_V1_FREE_TAG (7)
-#define ERTS_MT_V1_TIME_INC_TAG (8)
-#define ERTS_MT_V1_STOP_TAG (9)
-#define ERTS_MT_V1_EXIT_TAG (10)
-
-#define ERTS_MT_END_OF_HDR_TAG (0)
-#define ERTS_MT_ALLOCATOR_HDR_TAG (1)
-#define ERTS_MT_BLOCK_TYPE_HDR_TAG (2)
-
-#define ERTS_MT_EXIT_BDY_TAG (0)
-#define ERTS_MT_STOP_BDY_TAG (1)
-#define ERTS_MT_ALLOC_BDY_TAG (2)
-#define ERTS_MT_REALLOC_BDY_TAG (3)
-#define ERTS_MT_FREE_BDY_TAG (4)
-#define ERTS_MT_CRR_ALLOC_BDY_TAG (5)
-#define ERTS_MT_CRR_REALLOC_BDY_TAG (6)
-#define ERTS_MT_CRR_FREE_BDY_TAG (7)
-#define ERTS_MT_TIME_INC_BDY_TAG (8)
-#define ERTS_MT_X_BDY_TAG (9)
-
-/* X subtags */
-#if 0
-#define ERTS_MT_X_ _BDY_TAG (0)
-#endif
-
-#define ERTS_MT_START_WORD (0xfff04711)
-/* Entry header fields */
-
-#define ERTS_MT_UI8_MSB_EHDR_FLD_SZ (0)
-#define ERTS_MT_UI16_MSB_EHDR_FLD_SZ (1)
-#define ERTS_MT_UI32_MSB_EHDR_FLD_SZ (2)
-#define ERTS_MT_UI64_MSB_EHDR_FLD_SZ (3)
-#define ERTS_MT_UI_MSB_EHDR_FLD_SZ ERTS_MT_UI64_MSB_EHDR_FLD_SZ
-#define ERTS_MT_TAG_EHDR_FLD_SZ (4)
-
-#define ERTS_MT_UI8_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI8_MSB_EHDR_FLD_SZ)-1)
-#define ERTS_MT_UI16_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI16_MSB_EHDR_FLD_SZ)-1)
-#define ERTS_MT_UI32_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI32_MSB_EHDR_FLD_SZ)-1)
-#define ERTS_MT_UI64_MSB_EHDR_FLD_MSK ((1 << ERTS_MT_UI64_MSB_EHDR_FLD_SZ)-1)
-#define ERTS_MT_UI_MSB_EHDR_FLD_MSK ERTS_MT_UI64_MSB_EHDR_FLD_MSK
-#define ERTS_MT_TAG_EHDR_FLD_MSK ((1 << ERTS_MT_TAG_EHDR_FLD_SZ)-1)
-
-/* Time increment word */
-#define ERTS_MT_TIME_INC_SECS_SHIFT 20
-#define ERTS_MT_TIME_INC_USECS_SHIFT 0
-
-#define ERTS_MT_TIME_INC_SECS_MASK ((1 << 12) - 1)
-#define ERTS_MT_TIME_INC_USECS_MASK ((1 << 20) - 1)
-
-
-#define ERTS_MT_MAX_V1_HEADER_ENTRY_SIZE (2 + 2 + 1 + 255 + 2)
-/* Largest v1 header entry is block type entry (ERTS_MT_V1_BLOCK_TYPE_TAG) */
-#define ERTS_MT_MAX_V1_BODY_ENTRY_SIZE (2 + 8 + 8 + 8 + 4)
-/* Largest body entry is realloc moved entry (ERTS_MT_V1_REALLOC_MV_TAG) */
-
-
-#define ERTS_MT_MAX_HEADER_ENTRY_SIZE (1 + 2 + 2 + 1 + 255 + 2)
-/* Largest header entry is block type entry (ERTS_MT_BLOCK_TYPE_TAG) */
-#define ERTS_MT_MAX_BODY_ENTRY_SIZE ERTS_MT_MAX_CRR_REALLOC_SIZE
-/* Largest body entry is carrier realloc entry (ERTS_MT_CRR_REALLOC_BDY_TAG) */
-
-/*
- *
- * Entry header:
- *
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | ... |MSB2|MSB1|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * Time inc entry field:
- *
- * 31 23 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Seconds | Micro Seconds |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-
-#define ERTS_MT_MAX_CRR_ALLOC_SIZE (1 + 2 + 2 + 2 + 8 + 8 + 4)
-
-/*
- * ERTS_MT_CRR_ALLOC_BDY_TAG:
- * N 1 2 3 4 5
- * MSB 1-0 1-0 7|3-0 7|3-0 3-0
- * SZ 1 2 2-1 2-1 8|4-1 8|4-1 4-1
- * UIT UI8 UI16 UI16 UI16 UI64|UI32 UI64|UI32 UI32
- * +---+----+...--+...--+...-------+...-------+...-------+
- * |Tag| Hdr|CType| Type| Out ptr | In size | Time inc |
- * +---+----+...--+...--+...-------+...-------+...-------+
- *
- */
-
-#define ERTS_MT_MAX_ALLOC_SIZE (1 + 2 + 2 + 8 + 8 + 4)
-/*
- * ERTS_MT_ALLOC_BDY_TAG:
- * N 1 2 3 4
- * MSB 1-0 7|3-0 7|3-0 3-0
- * SZ 1 2 2-1 8|4-1 8|4-1 4-1
- * UIT UI8 UI16 UI16 UI64|UI32 UI64|UI32 UI32
- * +---+----+...--+...-------+...-------+...-------+
- * |Tag| Hdr| Type| Out ptr | In size | Time inc |
- * +---+----+...--+...-------+...-------+...-------+
- *
- */
-
-#define ERTS_MT_MAX_CRR_REALLOC_SIZE (1 + 2 + 2 + 2 + 8 + 8 + 8 + 4)
-/*
- * ERTS_MT_CRR_REALLOC_BDY_TAG:
- * N 1 2 3 4 5 6
- * MSB 1-0 1-0 7|3-0 7|3-0 7|3-0 3-0
- * SZ 1 2 2-1 2-1 8|4-1 8|4-1 8|4-1 4-1
- * UIT UI8 UI16 UI16 UI16 UI64|UI32 UI64|UI32 UI64|UI32 UI32
- * +---+----+...--+...--+...-------+...-------+...-------+...-------+
- * |Tag| Hdr|CType| Type| Out ptr | In ptr | In size | Time inc |
- * +---+----+...--+...--+...-------+...-------+...-------+...-------+
- *
- */
-
-#define ERTS_MT_MAX_REALLOC_SIZE (1 + 2 + 2 + 8 + 8 + 8 + 4)
-/*
- * ERTS_MT_REALLOC_BDY_TAG:
- * N 1 2 3 4 5
- * MSB 1-0 7|3-0 7|3-0 7|3-0 3-0
- * SZ 1 2 2-1 8|4-1 8|4-1 8|4-1 4-1
- * UIT UI8 UI16 UI16 UI64|UI32 UI64|UI32 UI64|UI32 UI32
- * +---+----+...--+...-------+...-------+...-------+...-------+
- * |Tag| Hdr| Type| Out ptr | In ptr | In size | Time inc |
- * +---+----+...--+...-------+...-------+...-------+...-------+
- *
- */
-
-#define ERTS_MT_MAX_CRR_FREE_SIZE (1 + 2 + 2 + 2 + 8 + 4)
-/*
- * ERTS_MT_CRR_FREE_BDY_TAG:
- * N 1 2 3 4
- * MSB 1-0 1-0 7|3-0 3-0
- * SZ 1 2 2-1 2-1 8|4-1 4-1
- * UIT UI8 UI16 UI16 UI16 UI64|UI32 UI32
- * +---+----+...--+...--+...-------+...-------+
- * |Tag| Hdr|CType| Type| In ptr | Time inc |
- * +---+----+...--+...--+...-------+...-------+
- *
- */
-
-#define ERTS_MT_MAX_FREE_SIZE (1 + 2 + 2 + 8 + 4)
-/*
- * ERTS_MT_FREE_BDY_TAG:
- * N 1 2 3
- * MSB 1-0 7|3-0 3-0
- * SZ 1 2 2-1 8|4-1 4-1
- * UIT UI8 UI16 UI16 UI64|UI32 UI32
- * +---+----+...--+...-------+...-------+
- * |Tag| Hdr| Type| In ptr | Time inc |
- * +---+----+...--+...-------+...-------+
- *
- */
-
-/*
- * ERTS_MT_X_BDY_TAG:
- * N
- * MSB
- * SZ 1 2 1
- * UIT UI8 UI16 UI8
- * +---+-----+------+... ...+
- * |Tag|TotSz|SubTag| |
- * +---+-----+------+... ...+
- *
- * ^ ^
- * | |
- * +------ TotSz bytes -----+
- *
- * X for extension
- *
- * * Tag equals ERTS_MT_X_BDY_TAG.
- * * TotSz contains the total size of the entry.
- * * SubTag is used to distinguish between different sub entries
- * passed in X entries.
- *
- */
-
-
-
-#endif /* #ifndef ERL_MEMORY_TRACE_PROTOCOL_H__ */
-
diff --git a/erts/include/internal/erl_misc_utils.h b/erts/include/internal/erl_misc_utils.h
index b05aeae964..3e6352150d 100644
--- a/erts/include/internal/erl_misc_utils.h
+++ b/erts/include/internal/erl_misc_utils.h
@@ -35,7 +35,7 @@ typedef struct {
erts_cpu_info_t *erts_cpu_info_create(void);
void erts_cpu_info_destroy(erts_cpu_info_t *cpuinfo);
-int erts_cpu_info_update(erts_cpu_info_t *cpuinfo);
+int erts_cpu_info_update(erts_cpu_info_t *cpuinfo, int skip_read_topology);
int erts_get_cpu_configured(erts_cpu_info_t *cpuinfo);
int erts_get_cpu_online(erts_cpu_info_t *cpuinfo);
int erts_get_cpu_available(erts_cpu_info_t *cpuinfo);
diff --git a/erts/include/internal/ethr_atomics.h b/erts/include/internal/ethr_atomics.h
index 06568201ad..02cbc7584b 100644
--- a/erts/include/internal/ethr_atomics.h
+++ b/erts/include/internal/ethr_atomics.h
@@ -10,7 +10,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@
* - read
* - init
*
- * Appart from a function implementing the atomic operation
+ * Apart from a function implementing the atomic operation
* with unspecified memory barrier semantics, there are
* functions implementing each operation with the following
* implied memory barrier semantics:
diff --git a/erts/include/internal/ethr_internal.h b/erts/include/internal/ethr_internal.h
index 986e2b84de..44c26ba952 100644
--- a/erts/include/internal/ethr_internal.h
+++ b/erts/include/internal/ethr_internal.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,28 +56,22 @@ ethr_ts_event *ethr_get_tse__(void);
ETHR_PROTO_NORETURN__ ethr_abort__(void);
#ifdef ETHR_INCLUDE_MONOTONIC_CLOCK__
-#undef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
-#if defined(ETHR_HAVE_CLOCK_GETTIME_MONOTONIC) \
- || defined(ETHR_HAVE_MACH_CLOCK_GET_TIME) \
- || defined(ETHR_HAVE_GETHRTIME)
-#ifdef ETHR_TIME_WITH_SYS_TIME
-# include <time.h>
-# include <sys/time.h>
-#else
-# ifdef ETHR_HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
+# undef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
+# if defined(ETHR_HAVE_CLOCK_GETTIME_MONOTONIC) \
+ || defined(ETHR_HAVE_MACH_CLOCK_GET_TIME) \
+ || defined(ETHR_HAVE_GETHRTIME)
# include <time.h>
+# ifdef ETHR_HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
# endif
-#endif
-#ifdef ETHR_HAVE_MACH_CLOCK_GET_TIME
-#include <mach/clock.h>
-#include <mach/mach.h>
-#endif
-#define ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
+# ifdef ETHR_HAVE_MACH_CLOCK_GET_TIME
+# include <mach/clock.h>
+# include <mach/mach.h>
+# endif
+# define ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
ethr_sint64_t ethr_get_monotonic_time(void);
int ethr_get_monotonic_time_is_broken(void);
-#endif
#endif /* ETHR_INCLUDE_MONOTONIC_CLOCK__ */
void ethr_init_event__(void);
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index 8ef3b1e40b..4a9fa8b3f5 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -341,6 +341,7 @@ struct ethr_rwmutex_ {
int ethr_rwmutex_set_reader_group(int);
int ethr_rwmutex_init_opt(ethr_rwmutex *, ethr_rwmutex_opt *);
int ethr_rwmutex_init(ethr_rwmutex *);
+size_t ethr_rwmutex_size(ethr_rwmutex *);
int ethr_rwmutex_destroy(ethr_rwmutex *);
#if defined(ETHR_USE_OWN_RWMTX_IMPL__) \
|| !defined(ETHR_TRY_INLINE_FUNCS) \
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index a683ccee9b..460849ef2f 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,10 +95,12 @@
#endif
ETHR_PROTO_NORETURN__
-ethr_assert_failed(const char *file, int line, const char *func, char *a);
+ethr_assert_failed(const char *file, int line, const char *func, const char *a);
#ifdef ETHR_DEBUG
-#define ETHR_ASSERT(A) \
- ((void) ((A) ? 1 : ethr_assert_failed(__FILE__, __LINE__, __func__, #A)))
+#define ETHR_ASSERT(A) \
+ ((void) ((A) ? \
+ ((void) 1) : \
+ ethr_assert_failed(__FILE__, __LINE__, __func__, #A)))
#else
#define ETHR_ASSERT(A) ((void) 1)
#endif
@@ -312,6 +314,10 @@ ETHR_PROTO_NORETURN__ ethr_fatal_error__(const char *file,
ETHR_X86_RUNTIME_CONF_HAVE_META(nonstop_tsc_s3)
# define ETHR_X86_RUNTIME_CONF_HAVE_NO_NONSTOP_TSC_S3__ \
ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc_s3)
+# define ETHR_X86_RUNTIME_CONF_HAVE_CPUID__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_META(cpuid)
+# define ETHR_X86_RUNTIME_CONF_HAVE_NO_CPUID__ \
+ ETHR_X86_RUNTIME_CONF_HAVE_NO_META(cpuid)
#endif
@@ -336,6 +342,7 @@ typedef struct {
int have_tsc_reliable;
int have_nonstop_tsc;
int have_nonstop_tsc_s3;
+ int have_cpuid;
#endif
#if defined(ETHR_PPC_RUNTIME_CONF__)
int have_lwsync;
diff --git a/erts/include/internal/ethread_header_config.h.in b/erts/include/internal/ethread_header_config.h.in
index aeb00ef230..7a399aac65 100644
--- a/erts/include/internal/ethread_header_config.h.in
+++ b/erts/include/internal/ethread_header_config.h.in
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -106,6 +106,11 @@
an ARM processor with ARM DMB instruction support, or not */
#undef ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION
+/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'isb sy' instruction, and are compiling for
+ an ARM processor with ARM ISB instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION
+
/* Define as a bitmask corresponding to the word sizes that
__sync_synchronize() can handle on your system */
#undef ETHR_HAVE___sync_synchronize
@@ -182,7 +187,7 @@
/* Define if you use a gcc that supports the double word cmpxchg instruction */
#undef ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT
-/* Define if gcc wont let you clobber ebx with cmpxchg8b and position
+/* Define if gcc won't let you clobber ebx with cmpxchg8b and position
independent code */
#undef ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX
diff --git a/erts/include/internal/gcc/ethr_dw_atomic.h b/erts/include/internal/gcc/ethr_dw_atomic.h
index 7e2d46c354..f1afd12839 100644
--- a/erts/include/internal/gcc/ethr_dw_atomic.h
+++ b/erts/include/internal/gcc/ethr_dw_atomic.h
@@ -72,7 +72,7 @@ typedef volatile ETHR_NATIVE_SU_DW_SINT_T * ethr_native_dw_ptr_t;
* This code assumes 8 byte aligned memory in 64-bit mode, and 4 byte
* aligned memory in 32-bit mode. A malloc implementation that does
* not adhere to these alignment requirements is seriously broken,
- * and we wont bother trying to work around it.
+ * and we won't bother trying to work around it.
*
* Since memory alignment may be off by one word we need to align at
* runtime. We, therefore, need an extra word allocated.
diff --git a/erts/include/internal/gcc/ethr_membar.h b/erts/include/internal/gcc/ethr_membar.h
index 56344452d3..8572d9975a 100644
--- a/erts/include/internal/gcc/ethr_membar.h
+++ b/erts/include/internal/gcc/ethr_membar.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,9 +31,9 @@
* ordered around it according to the semantics of the
* barrier specified.
*
- * The C11 aproch is different. The __atomic builtins
+ * The C11 approach is different. The __atomic builtins
* API takes a memory model parameter. Assuming that all
- * memory syncronizations using the involved atomic
+ * memory synchronizations using the involved atomic
* variables are made using this API, the synchronizations
* will adhere to the memory models used. That is, you do
* *not* know how loads and stores will be ordered around
@@ -69,7 +69,7 @@
* Why is this? Since all synchronizations is expected
* to be made using the __atomic builtins, memory
* barriers only have to be issued by some of them,
- * and you do not know which ones wont issue memory
+ * and you do not know which ones won't issue memory
* barriers.
*
* One can easily be fooled into believing that when
@@ -93,8 +93,8 @@
* __ATOMIC_ACQUIRE and __ATOMIC_RELEASE memory
* models. This since an __atomic builtin memory
* access using the __ATOMIC_ACQUIRE must at least
- * issue an aquire memory barrier and an __atomic
- * builtin memory acess with the __ATOMIC_RELEASE
+ * issue an acquire memory barrier and an __atomic
+ * builtin memory access with the __ATOMIC_RELEASE
* memory model must at least issue a release memory
* barrier. Otherwise the two cannot be paired.
* 4. All __atomic builtins accessing memory using the
@@ -141,6 +141,21 @@
#define ETHR_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
+#if ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION
+#define ETHR_INSTRUCTION_BARRIER ethr_instruction_fence__()
+
+static __inline__ __attribute__((__always_inline__)) void
+ethr_instruction_fence__(void)
+{
+ __asm__ __volatile__("isb sy" : : : "memory");
+}
+#else
+/* !! Note that we DO NOT define a fallback !!
+ *
+ * See the definition of ERTS_THR_INSTRUCTION_BARRIER in erl_threads.h for
+ * details. */
+#endif
+
#if ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION
static __inline__ __attribute__((__always_inline__)) void
@@ -240,7 +255,7 @@ ethr_full_fence__(void)
#endif
/*
- * Define ETHR_READ_DEPEND_MEMORY_BARRIER for all architechtures
+ * Define ETHR_READ_DEPEND_MEMORY_BARRIER for all architectures
* not known to order data dependent loads
*
* This is a bit too conservative, but better safe than sorry...
diff --git a/erts/include/internal/i386/ethr_dw_atomic.h b/erts/include/internal/i386/ethr_dw_atomic.h
index e3dbc82518..45cd668ac5 100644
--- a/erts/include/internal/i386/ethr_dw_atomic.h
+++ b/erts/include/internal/i386/ethr_dw_atomic.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@ typedef volatile ethr_native_sint128_t__ * ethr_native_dw_ptr_t;
* This code assumes 8 byte aligned memory in 64-bit mode, and 4 byte
* aligned memory in 32-bit mode. A malloc implementation that does
* not adhere to these alignment requirements is seriously broken,
- * and we wont bother trying to work around it.
+ * and we won't bother trying to work around it.
*
* Since memory alignment may be off by one word we need to align at
* runtime. We, therefore, need an extra word allocated.
@@ -159,7 +159,7 @@ ethr_native_dw_atomic_cmpxchg_mb(ethr_native_dw_atomic_t *var,
#if ETHR_NO_CLOBBER_EBX__ && ETHR_CMPXCHG8B_REGISTER_SHORTAGE
/*
- * gcc wont let us use ebx as input and we
+ * gcc won't let us use ebx as input and we
* get a register shortage
*/
@@ -176,7 +176,7 @@ ethr_native_dw_atomic_cmpxchg_mb(ethr_native_dw_atomic_t *var,
#elif ETHR_NO_CLOBBER_EBX__
/*
- * gcc wont let us use ebx as input
+ * gcc won't let us use ebx as input
*/
__asm__ __volatile__(
diff --git a/erts/include/internal/i386/ethr_membar.h b/erts/include/internal/i386/ethr_membar.h
index d1b72cd538..cd00ab5974 100644
--- a/erts/include/internal/i386/ethr_membar.h
+++ b/erts/include/internal/i386/ethr_membar.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,27 @@
#define ETHR_StoreLoad (1 << 2)
#define ETHR_StoreStore (1 << 3)
+#ifdef ETHR_X86_RUNTIME_CONF__
+#define ETHR_INSTRUCTION_BARRIER ethr_instruction_fence__()
+
+static __inline__ __attribute__((__always_inline__)) void
+ethr_instruction_fence__(void)
+{
+ ETHR_ASSERT(ETHR_X86_RUNTIME_CONF_HAVE_CPUID__);
+
+#if ETHR_SIZEOF_PTR == 4
+__asm__ __volatile__("cpuid\n\t" :: "a"(0) : "ebx", "ecx", "edx", "memory");
+#else
+__asm__ __volatile__("cpuid\n\t" :: "a"(0) : "rbx", "rcx", "rdx", "memory");
+#endif
+}
+#else
+/* !! Note that we DO NOT define a fallback !!
+ *
+ * See the definition of ERTS_THR_INSTRUCTION_BARRIER in erl_threads.h for
+ * details. */
+#endif
+
#define ETHR_NO_SSE2_MEMORY_BARRIER__ \
do { \
volatile ethr_sint32_t x__ = 0; \
diff --git a/erts/include/internal/win/ethr_dw_atomic.h b/erts/include/internal/win/ethr_dw_atomic.h
index 03311f6025..6275852f93 100644
--- a/erts/include/internal/win/ethr_dw_atomic.h
+++ b/erts/include/internal/win/ethr_dw_atomic.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ typedef volatile __int64 * ethr_native_dw_ptr_t;
* This code assumes 8 byte aligned memory in 64-bit mode, and 4 byte
* aligned memory in 32-bit mode. A malloc implementation that does
* not adhere to these alignment requirements is seriously broken,
- * and we wont bother trying to work around it.
+ * and we won't bother trying to work around it.
*
* Since memory alignment may be off by one word we need to align at
* runtime. We, therefore, need an extra word allocated.
diff --git a/erts/include/internal/win/ethr_membar.h b/erts/include/internal/win/ethr_membar.h
index c018f6d869..80b0e0e533 100644
--- a/erts/include/internal/win/ethr_membar.h
+++ b/erts/include/internal/win/ethr_membar.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,9 +54,28 @@ do { \
#elif defined(_M_AMD64) || defined(_M_IX86)
+#include <immintrin.h>
#include <emmintrin.h>
#include <mmintrin.h>
+#ifdef ETHR_X86_RUNTIME_CONF__
+#define ETHR_INSTRUCTION_BARRIER ethr_instruction_fence__()
+#pragma intrinsic(__cpuid)
+
+static ETHR_FORCE_INLINE void
+ethr_instruction_fence__(void)
+{
+ int ignored[4];
+ ETHR_ASSERT(ETHR_X86_RUNTIME_CONF_HAVE_CPUID__);
+ __cpuid(ignored, 0);
+}
+#else
+/* !! Note that we DO NOT define a fallback !!
+ *
+ * See the definition of ERTS_THR_INSTRUCTION_BARRIER in erl_threads.h for
+ * details. */
+#endif
+
#if ETHR_SIZEOF_PTR == 4
# define ETHR_NO_SSE2_MB__ ETHR_MB_USING_INTERLOCKED__
#endif
diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in
index d5a5fd0f4d..043ef2dbd0 100644
--- a/erts/lib_src/Makefile.in
+++ b/erts/lib_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2021. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -170,15 +170,6 @@ else
THR_DEFS = $(filter-out -D_GNU_SOURCE%, $(ETHR_DEFS))
endif
-#
-# erts (public) library
-#
-
-ERTS_LIB_SRCS = common/erl_memory_trace_parser.c
-
-ERTS_LIB_DIR=../lib/$(TARGET)
-CREATE_DIRS += $(ERTS_LIB_DIR)
-
ifeq ($(USING_VC),yes)
# Windows obj dir
MD_OBJ_DIR=$(OBJ_DIR)/MD
@@ -191,10 +182,10 @@ CREATE_DIRS += $(MD_OBJ_DIR) \
$(MT_OBJ_DIR) \
$(MTd_OBJ_DIR)
-ERTS_MD_LIB_OBJS=$(addprefix $(MD_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o)))
-ERTS_MDd_LIB_OBJS=$(addprefix $(MDd_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o)))
-ERTS_MT_LIB_OBJS=$(addprefix $(MT_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o)))
-ERTS_MTd_LIB_OBJS=$(addprefix $(MTd_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o)))
+ERTS_MD_LIB_OBJS=$(addprefix $(MD_OBJ_DIR)/,$(notdir $(.c=.o)))
+ERTS_MDd_LIB_OBJS=$(addprefix $(MDd_OBJ_DIR)/,$(notdir $(.c=.o)))
+ERTS_MT_LIB_OBJS=$(addprefix $(MT_OBJ_DIR)/,$(notdir $(.c=.o)))
+ERTS_MTd_LIB_OBJS=$(addprefix $(MTd_OBJ_DIR)/,$(notdir $(.c=.o)))
else # --- Not windows ---
@@ -202,31 +193,9 @@ else # --- Not windows ---
ifneq ($(strip $(ETHR_LIB_NAME)),)
r_OBJ_DIR = $(OBJ_DIR)/r
CREATE_DIRS += $(r_OBJ_DIR)
-ERTS_r_LIB_OBJS=$(addprefix $(r_OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o)))
-endif
-ERTS_LIB_OBJS=$(addprefix $(OBJ_DIR)/,$(notdir $(ERTS_LIB_SRCS:.c=.o)))
-
-endif
-
-ifeq ($(USING_VC),yes)
-ERTS_MD_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MD$(TYPE_SUFFIX)$(LIB_SUFFIX)
-ERTS_MDd_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MDd$(TYPE_SUFFIX)$(LIB_SUFFIX)
-ERTS_MT_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MT$(TYPE_SUFFIX)$(LIB_SUFFIX)
-ERTS_MTd_LIB=$(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_MTd$(TYPE_SUFFIX)$(LIB_SUFFIX)
-ERTS_LIBS += \
- $(ERTS_MD_LIB) \
- $(ERTS_MDd_LIB) \
- $(ERTS_MT_LIB) \
- $(ERTS_MTd_LIB)
-else
-
-ERTS_LIB = $(ERTS_LIB_DIR)/$(LIB_PREFIX)erts$(TYPE_SUFFIX)$(LIB_SUFFIX)
-ERTS_LIBS += $(ERTS_LIB)
-
-ifneq ($(strip $(ETHR_LIB_NAME)),)
-ERTS_r_LIB = $(ERTS_LIB_DIR)/$(LIB_PREFIX)erts_r$(TYPE_SUFFIX)$(LIB_SUFFIX)
-ERTS_LIBS += $(ERTS_r_LIB)
+ERTS_r_LIB_OBJS=$(addprefix $(r_OBJ_DIR)/,$(notdir $(.c=.o)))
endif
+ERTS_LIB_OBJS=$(addprefix $(OBJ_DIR)/,$(notdir $(.c=.o)))
endif
@@ -340,7 +309,7 @@ YCF_SOURCE_DIR=$(ERL_TOP)/erts/lib_src/yielding_c_fun
include $(YCF_SOURCE_DIR)/main_target.mk
-$(OBJ_DIR)/MADE: $(YCF_EXECUTABLE) $(ETHREAD_LIB) $(ERTS_LIBS) $(ERTS_INTERNAL_LIBS)
+$(OBJ_DIR)/MADE: $(YCF_EXECUTABLE) $(ETHREAD_LIB) $(ERTS_INTERNAL_LIBS)
$(gen_verbose)
ifeq ($(OMIT_OMIT_FP),yes)
@echo '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
@@ -462,10 +431,8 @@ include ../vsn.mk
RELSYSDIR = $(RELEASE_PATH)/erts-$(VSN)
RELEASE_INCLUDES= \
- $(ERTS_INCL)/erl_memory_trace_parser.h \
$(ERTS_INCL)/$(TARGET)/erl_int_sizes_config.h \
$(ERTS_INCL)/erl_fixed_size_int_types.h
-RELEASE_LIBS=$(ERTS_LIBS)
INTERNAL_RELEASE_INCLUDES= \
$(ERTS_INCL_INT)/README \
@@ -479,7 +446,6 @@ INTERNAL_RELEASE_INCLUDES= \
$(ERTS_INCL_INT)/$(TARGET)/ethread_header_config.h \
$(ERTS_INCL_INT)/erl_printf.h \
$(ERTS_INCL_INT)/erl_printf_format.h \
- $(ERTS_INCL_INT)/erl_memory_trace_protocol.h \
$(ERTS_INCL_INT)/erl_misc_utils.h \
$(ERTS_INCL_INT)/erl_errno.h
@@ -511,12 +477,6 @@ ifneq ($(strip $(INTERNAL_X_RELEASE_INCLUDE_DIRS)),)
"$(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"
-endif
ifneq ($(strip $(INTERNAL_RELEASE_LIBS)),)
$(INSTALL_DIR) "$(RELSYSDIR)/lib/internal"
$(INSTALL_DATA) $(INTERNAL_RELEASE_LIBS) "$(RELSYSDIR)/lib/internal"
diff --git a/erts/lib_src/common/erl_memory_trace_parser.c b/erts/lib_src/common/erl_memory_trace_parser.c
deleted file mode 100644
index 0232708ad1..0000000000
--- a/erts/lib_src/common/erl_memory_trace_parser.c
+++ /dev/null
@@ -1,1962 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-
-/*
- * Description:
- *
- * Author: Rickard Green
- */
-
-#include "erl_memory_trace_parser.h"
-#include "erl_memory_trace_protocol.h"
-#include <string.h> /* For memcpy */
-
-#ifdef DEBUG
-#include <assert.h>
-#define ASSERT assert
-#define PRINT_ERROR_ORIGIN 1
-#if PRINT_ERROR_ORIGIN
-#include <stdio.h>
-#endif
-#define PRINT_PARSED_OP 0
-#if PRINT_PARSED_OP
-#include <stdio.h>
-static void print_op(emtp_operation *op_p);
-#endif
-static void hexdump(void *start, void *end);
-#else
-#define PRINT_ERROR_ORIGIN 0
-#define PRINT_PARSED_OP 0
-#define ASSERT(B)
-#endif
-
-
-#if ERTS_MT_MAJOR_VSN != 2 || ERTS_MT_MINOR_VSN != 0
-#error trace version mismatch (expected version 2.0)
-/* Make sure that older versions are supported when implementing
- support for newer versions! */
-#endif
-
-
-#if defined(__GNUC__)
-# define EMTP_CAN_INLINE 1
-# define EMTP_INLINE __inline__
-#elif defined(__WIN32__)
-# define EMTP_CAN_INLINE 1
-# define EMTP_INLINE __forceinline
-#else
-# define EMTP_CAN_INLINE 0
-# define EMTP_INLINE
-#endif
-
-
-#define UI8_SZ 1
-#define UI16_SZ 2
-#define UI32_SZ 4
-#define UI64_SZ 8
-
-#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
-#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
-
-#define DEFAULT_OVERFLOW_BUF_SZ 128
-
-#define UNKNOWN_BLOCK_TYPE_IX (-1)
-#define UNKNOWN_ALLOCATOR_IX (-1)
-
-#define INVALID_SIZE (((sgnd_int_32) 1) << 31)
-#define INVALID_RESULT ((int) INVALID_SIZE)
-
-typedef enum {
- EMTP_PROGRESS_PARSE_HDR_VSN,
- EMTP_PROGRESS_PARSE_HDR_PROLOG,
- EMTP_PROGRESS_ALLOC_HDR_INFO,
- EMTP_PROGRESS_PARSE_TAGGED_HDR,
- EMTP_PROGRESS_PARSE_BODY,
- EMTP_PROGRESS_ENDED
-} emtp_progress;
-
-struct emtp_state_ {
-
- /* Trace version */
- emtp_version version;
-
- /* Flags */
- usgnd_int_32 flags;
-
- /* Progress */
- emtp_progress progress;
-
- /* Name, host, and pid as strings */
- char nodename[256];
- char hostname[256];
- char pid[256];
-
- /* Local time on the traced node when the node started */
- struct {
- usgnd_int_32 year;
- usgnd_int_32 month;
- usgnd_int_32 day;
- usgnd_int_32 hour;
- usgnd_int_32 minute;
- usgnd_int_32 second;
- usgnd_int_32 micro_second;
- } start_time;
-
- /* Function to parse body with */
- int (*parse_body_func)(emtp_state *,
- usgnd_int_8 **,
- usgnd_int_8 *,
- emtp_operation **,
- emtp_operation *,
- size_t);
- /* Current time elapsed */
- struct {
- usgnd_int_32 secs;
- usgnd_int_32 usecs;
- } time;
-
- /* */
-
- int force_return;
-
- /* Overflow buffer */
- size_t overflow_size;
- size_t overflow_buf_size;
- usgnd_int_8 * overflow;
- sgnd_int_32 fetch_size;
- int known_need;
-
- usgnd_int_16 segment_ix;
- usgnd_int_16 max_allocator_ix;
- emtp_allocator ** allocator;
- usgnd_int_16 max_block_type_ix;
- emtp_block_type ** block_type;
-
- /* Memory allocation functions */
- void * (*alloc)(size_t);
- void * (*realloc)(void *, size_t);
- void (*free)(void *);
-
-};
-
-static char unknown_allocator[] = "unknown_allocator";
-static char unknown_block_type[] = "unknown_block_type";
-
-const char *
-emtp_error_string(int res)
-{
- switch (res) {
- case EMTP_NO_TRACE_ERROR:
- return "no trace error";
- case EMTP_HEADER_TAG_IN_BODY_ERROR:
- return "header tag in body error";
- case EMTP_BODY_TAG_IN_HEADER_ERROR:
- return "body tag in header error";
- case EMTP_NOT_SUPPORTED_MTRACE_VERSION_ERROR:
- return "not supported mtrace version error";
- case EMTP_NOT_AN_ERL_MTRACE_ERROR:
- return "not an erl mtrace error";
- case EMTP_NO_MEMORY_ERROR:
- return "no memory error";
- case EMTP_BAD_OP_SIZE_ERROR:
- return "bad op size error";
- case EMTP_NO_OPERATIONS_ERROR:
- return "no operations error";
- case EMTP_NOT_SUPPORTED_64_BITS_TRACE_ERROR:
- return "not supported 64 bits trace error";
- case EMTP_PARSE_ERROR:
- return "parse error";
- case EMTP_UNKNOWN_TAG_ERROR:
- return "unknown tag error";
- case EMTP_END_OF_TRACE:
- return "end of trace";
- case EMTP_END_OF_TRACE_GARBAGE_FOLLOWS:
- return "end of trace; garbage follows";
- case EMTP_ALL_OPS_FILLED:
- return "all operations filled";
- case EMTP_NEED_MORE_TRACE:
- return "need more trace";
- case EMTP_HEADER_PARSED:
- return "header parsed";
- default:
- return NULL;
- }
-
-}
-
-int
-emtp_get_info(emtp_info *infop, size_t *info_szp, emtp_state *statep)
-{
- if (!infop || !info_szp || *info_szp < sizeof(emtp_info))
- return 0;
-
- infop->version.parser.major = ERTS_MT_MAJOR_VSN;
- infop->version.parser.minor = ERTS_MT_MINOR_VSN;
-
- *info_szp = sizeof(emtp_version);
-
- if (!statep || statep->version.major == 0)
- return 1;
-
- infop->version.trace.major = statep->version.major;
- infop->version.trace.minor = statep->version.minor;
-
- *info_szp = sizeof(emtp_versions);
-
- if (statep->progress != EMTP_PROGRESS_PARSE_BODY
- && statep->progress != EMTP_PROGRESS_ENDED)
- return 1;
-
- infop->bits = (statep->flags & ERTS_MT_64_BIT_FLAG
- ? 64
- : 32);
-
- infop->nodename = statep->nodename;
- infop->hostname = statep->hostname;
- infop->pid = statep->pid;
-
- infop->start_time.year = statep->start_time.year;
- infop->start_time.month = statep->start_time.month;
- infop->start_time.day = statep->start_time.day;
- infop->start_time.hour = statep->start_time.hour;
- infop->start_time.minute = statep->start_time.minute;
- infop->start_time.second = statep->start_time.second;
- infop->start_time.micro_second = statep->start_time.micro_second;
-
- infop->have_carrier_info = statep->flags & ERTS_MT_CRR_INFO;
- infop->have_segment_carrier_info = statep->flags & ERTS_MT_SEG_CRR_INFO;
- infop->segment_ix = statep->segment_ix;
- infop->max_allocator_ix = statep->max_allocator_ix;
- infop->allocator = statep->allocator;
- infop->max_block_type_ix = statep->max_block_type_ix;
- infop->block_type = statep->block_type;
-
- *info_szp = sizeof(emtp_info);
-
- return 1;
-}
-
-emtp_state *
-emtp_state_new(void * (*alloc)(size_t),
- void * (*realloc)(void *, size_t),
- void (*free)(void *))
-{
- emtp_state *statep;
-
- if (!alloc || !realloc || !free)
- return NULL;
-
- statep = (emtp_state *) (*alloc)(sizeof(emtp_state));
- if (!statep)
- return NULL;
-
- statep->version.major = 0;
- statep->version.minor = 0;
- statep->flags = 0;
- statep->progress = EMTP_PROGRESS_PARSE_HDR_VSN;
-
- statep->nodename[0] = '\0';
- statep->hostname[0] = '\0';
- statep->pid[0] = '\0';
-
- statep->start_time.year = 0;
- statep->start_time.month = 0;
- statep->start_time.day = 0;
- statep->start_time.hour = 0;
- statep->start_time.minute = 0;
- statep->start_time.second = 0;
- statep->start_time.micro_second = 0;
-
- statep->parse_body_func = NULL;
- statep->time.secs = 0;
- statep->time.usecs = 0;
- statep->force_return = 0;
- statep->overflow_size = 0;
- statep->overflow_buf_size = DEFAULT_OVERFLOW_BUF_SZ;
- statep->overflow =
- (usgnd_int_8 *) (*alloc)(DEFAULT_OVERFLOW_BUF_SZ*sizeof(usgnd_int_8));
- statep->fetch_size = 0;
- statep->known_need = 0;
- statep->segment_ix = 0;
- statep->max_allocator_ix = 0;
- statep->allocator = NULL;
- statep->max_block_type_ix = 0;
- statep->block_type = NULL;
- statep->alloc = alloc;
- statep->realloc = realloc;
- statep->free = free;
-
- return statep;
-}
-
-void
-emtp_state_destroy(emtp_state *statep)
-{
- void (*freep)(void *);
- int i;
-
- if (!statep)
- return;
-
- freep = statep->free;
-
- if (statep->overflow)
- (*freep)((void *) statep->overflow);
-
- if (statep->allocator) {
- for (i = -1; i <= statep->max_allocator_ix; i++) {
- if (statep->allocator[i]) {
- if (statep->allocator[i]->name
- && statep->allocator[i]->name != unknown_allocator)
- (*freep)((void *) statep->allocator[i]->name);
- if (statep->allocator[i]->carrier.provider)
- (*freep)((void *) statep->allocator[i]->carrier.provider);
- (*freep)((void *) statep->allocator[i]);
- }
- }
- statep->allocator--;
- (*freep)((void *) statep->allocator);
- }
-
- if (statep->block_type) {
- for (i = -1; i <= statep->max_block_type_ix; i++) {
- if (statep->block_type[i]) {
- if (statep->block_type[i]->name
- && statep->block_type[i]->name != unknown_block_type)
- (*freep)((void *) statep->block_type[i]->name);
- (*freep)((void *) statep->block_type[i]);
- }
- }
- statep->block_type--;
- (*freep)((void *) statep->block_type);
- }
-
- (*freep)((void *) statep);
-}
-
-/*
- * The following macros are for use in emtp_parse(), parse_vX_body,
- * and parse_header.
- *
- * Note that some of them depend on function local variable names
- * and lables:
- *
- * Variables:
- * * result -> the result to return
- * * statep -> pointer to the state
- *
- * Lables:
- * * restore_return -> restore then return result
- */
-
-
-#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 { \
- (UI) = ((( (usgnd_int_32) (BP)[0]) << 24) \
- | (((usgnd_int_32) (BP)[1]) << 16) \
- | (((usgnd_int_32) (BP)[2]) << 8) \
- | ( (usgnd_int_32) (BP)[3])); \
- (BP) += UI32_SZ; \
-} while(0)
-#define SKIP_UI32(BP) ((BP) += UI32_SZ)
-
-#define GET_UI64(UI, BP) \
- do { \
- (UI) = ((( (usgnd_int_64) (BP)[0]) << 56) \
- | (((usgnd_int_64) (BP)[1]) << 48) \
- | (((usgnd_int_64) (BP)[2]) << 40) \
- | (((usgnd_int_64) (BP)[3]) << 32) \
- | (((usgnd_int_64) (BP)[4]) << 24) \
- | (((usgnd_int_64) (BP)[5]) << 16) \
- | (((usgnd_int_64) (BP)[6]) << 8) \
- | ( (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 { \
- usgnd_int_16 ui_ = 0; \
- switch ((MSB)) { \
- case 1: ui_ |= (usgnd_int_16) *((BP)++); ui_ <<= 8; \
- case 0: ui_ |= (usgnd_int_16) *((BP)++); break; \
- default: ERROR(EMTP_PARSE_ERROR); \
- } \
- (UI) = ui_; \
-} while (0)
-
-#define GET_VSZ_UI32(UI, BP, MSB) \
-do { \
- usgnd_int_32 ui_ = 0; \
- switch ((MSB)) { \
- case 3: ui_ |= (usgnd_int_32) *((BP)++); ui_ <<= 8; \
- case 2: ui_ |= (usgnd_int_32) *((BP)++); ui_ <<= 8; \
- case 1: ui_ |= (usgnd_int_32) *((BP)++); ui_ <<= 8; \
- case 0: ui_ |= (usgnd_int_32) *((BP)++); break; \
- default: ERROR(EMTP_PARSE_ERROR); \
- } \
- (UI) = ui_; \
-} while (0)
-
-#define GET_VSZ_UI64(UI, BP, MSB) \
-do { \
- usgnd_int_64 ui_ = 0; \
- switch ((MSB)) { \
- case 7: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 6: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 5: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 4: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 3: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 2: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 1: ui_ |= (usgnd_int_64) *((BP)++); ui_ <<= 8; \
- case 0: ui_ |= (usgnd_int_64) *((BP)++); break; \
- default: ERROR(EMTP_PARSE_ERROR); \
- } \
- (UI) = ui_; \
-} while (0)
-
-
-#if HAVE_INT_64
-#define GET_VSZ_UIMAX(UI, BP, MSB) \
-do { \
- usgnd_int_64 ui64_; \
- GET_VSZ_UI64(ui64_, (BP), (MSB)); \
- (UI) = (usgnd_int_max) ui64_; \
-} while (0)
-#else
-#define GET_VSZ_UIMAX(UI, BP, MSB) \
-do { \
- usgnd_int_32 ui32_; \
- GET_VSZ_UI32(ui32_, (BP), (MSB)); \
- (UI) = (usgnd_int_max) ui32_; \
-} while (0)
-#endif
-
-
-
-#define INC_TIME(C_SECS, C_USECS, SECS, USECS) \
-do { \
- if ((USECS) >= 1000000) \
- ERROR(EMTP_PARSE_ERROR); \
- (C_SECS) += (SECS); \
- (C_USECS) += (USECS); \
- if ((C_USECS) >= 1000000) { \
- (C_USECS) -= 1000000; \
- (C_SECS)++; \
- } \
-} while (0)
-
-#if PRINT_ERROR_ORIGIN
-#include <stdio.h>
-#define ERROR(E) \
-do { \
- result = (E); \
- fprintf(stderr,"ERROR:%s:%d: result=%d\n",__FILE__,__LINE__,result);\
- statep->force_return = 1; abort(); \
- goto restore_return; \
-} while (0)
-#else
-#define ERROR(E) do { \
- result = (E); \
- statep->force_return = 1; \
- goto restore_return; \
-} while (0)
-#endif
-
-#define NEED(NSZ, TSZ) \
-do { \
- sgnd_int_32 need_ = (NSZ); \
- if (need_ > (TSZ)) { \
- statep->known_need = 1; \
- statep->fetch_size = need_; \
- result = EMTP_NEED_MORE_TRACE; \
- goto restore_return; \
- } \
-} while (0)
-
-#define NEED_AT_LEAST(NSZ, FSZ, TSZ) \
-do { \
- sgnd_int_32 need_ = (NSZ); \
- ASSERT(need_ <= (FSZ)); \
- if (need_ > (TSZ)) { \
- statep->known_need = 0; \
- statep->fetch_size = (FSZ); \
- result = EMTP_NEED_MORE_TRACE; \
- goto restore_return; \
- } \
-} while (0)
-
-
-#define SECS_PER_DAY (60*60*24)
-#define IS_LEAP_YEAR(X) (((X) % 4 == 0 && (X) % 100 != 0) || (X) % 400 == 0)
-
-static void
-set_start_time(emtp_state *state,
- usgnd_int_32 giga_seconds,
- usgnd_int_32 seconds,
- usgnd_int_32 micro_seconds)
-{
- /* Input is elapsed time since 1970-01-01 00:00.000000 (UTC) */
-
- usgnd_int_32 year, days_of_this_year, days, secs, month;
- usgnd_int_32 days_of_month[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
-
- days = 1000000000 / SECS_PER_DAY;
- secs = 1000000000 % SECS_PER_DAY;
- days *= giga_seconds;
- secs *= giga_seconds;
- secs += seconds;
- days += secs / SECS_PER_DAY;
- secs %= SECS_PER_DAY;
- days++;
-
- year = 1969;
- days_of_this_year = 0;
- while (days > days_of_this_year) {
- days -= days_of_this_year;
- year++;
- days_of_this_year = 365 + (IS_LEAP_YEAR(year) ? 1 : 0);
- }
-
- for (month = 1; month <= 12; month++) {
- usgnd_int_32 days_of_this_month = days_of_month[month];
- if (month == 2 && IS_LEAP_YEAR(year))
- days_of_this_month++;
- if (days <= days_of_this_month)
- break;
- days -= days_of_this_month;
- }
-
- state->start_time.year = year;
- state->start_time.month = month;
- state->start_time.day = days;
- state->start_time.hour = secs / (60*60);
- secs %= 60*60;
- state->start_time.minute = secs / 60;
- state->start_time.second = secs % 60;
- state->start_time.micro_second = micro_seconds;
-}
-
-static int
-parse_v1_body(emtp_state *statep,
- usgnd_int_8 **tracepp, usgnd_int_8 *trace_endp,
- emtp_operation **op_pp, emtp_operation *op_endp, size_t op_size)
-{
- /* "cache" some frequently used values */
- register usgnd_int_8 *c_p = *tracepp;
- register emtp_operation *op_p = *op_pp;
- register usgnd_int_32 current_secs = statep->time.secs;
- register usgnd_int_32 current_usecs = statep->time.usecs;
-
- sgnd_int_32 trace_size = trace_endp - c_p;
- usgnd_int_8 *tracep = c_p;
- int result = 0;
-
- usgnd_int_16 max_block_type = statep->max_block_type_ix;
-
- while (trace_size >= UI16_SZ) {
- usgnd_int_16 ehdr, tag;
- unsigned time_inc_msb;
-
- GET_UI16(ehdr, c_p);
- tag = ehdr & ERTS_MT_TAG_EHDR_FLD_MSK;
- switch (tag) {
- case ERTS_MT_V1_ALLOC_TAG:
-
- op_p->type = EMTP_ALLOC;
-
- alloc_common: {
- usgnd_int_16 block_type;
- unsigned block_type_msb, new_ptr_msb, new_size_msb;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
- block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
- new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ
- + 4
- + block_type_msb
- + new_ptr_msb
- + new_size_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UI16(block_type, c_p, block_type_msb);
- if (block_type > max_block_type)
- ERROR(EMTP_PARSE_ERROR);
- op_p->u.block.type = (int) block_type;
-
- GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb);
-
- op_p->u.block.prev_ptr = 0;
- }
-
- read_time_inc: {
- usgnd_int_32 secs, usecs, time_inc;
-
- GET_VSZ_UI32(time_inc, c_p, time_inc_msb);
-
- secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT)
- & ERTS_MT_TIME_INC_SECS_MASK);
- usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT)
- & ERTS_MT_TIME_INC_USECS_MASK);
-
- INC_TIME(current_secs, current_usecs, secs, usecs);
-
- op_p->time.secs = current_secs;
- op_p->time.usecs = current_usecs;
-
-#if PRINT_PARSED_OP
- print_op(op_p);
-#endif
-
- op_p = (emtp_operation *) (((char *) op_p) + op_size);
- break;
- }
-
- case ERTS_MT_V1_REALLOC_NPB_TAG:
- op_p->type = EMTP_REALLOC;
- goto alloc_common;
-
- case ERTS_MT_V1_REALLOC_MV_TAG: {
- unsigned new_ptr_msb, prev_ptr_msb, new_size_msb;
-
- op_p->type = EMTP_REALLOC;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
- new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ
- + 4
- + new_ptr_msb
- + prev_ptr_msb
- + new_size_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb);
-
- op_p->u.block.type = UNKNOWN_BLOCK_TYPE_IX;
- goto read_time_inc;
- }
-
- case ERTS_MT_V1_REALLOC_NMV_TAG: {
- usgnd_int_max new_ptr;
- unsigned new_ptr_msb, new_size_msb;
-
- op_p->type = EMTP_REALLOC;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
- new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ
- + 3
- + new_ptr_msb
- + new_size_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UIMAX(new_ptr, c_p, new_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb);
-
- op_p->u.block.new_ptr = new_ptr;
- op_p->u.block.prev_ptr = new_ptr;
-
- op_p->u.block.type = UNKNOWN_BLOCK_TYPE_IX;
- goto read_time_inc;
- }
-
- case ERTS_MT_V1_FREE_TAG: {
- unsigned prev_ptr_msb;
-
- op_p->type = EMTP_FREE;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
- prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ
- + 2
- + prev_ptr_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb);
-
- op_p->u.block.new_ptr = 0;
- op_p->u.block.new_size = 0;
-
- op_p->u.block.type = UNKNOWN_BLOCK_TYPE_IX;
- goto read_time_inc;
- }
-
- case ERTS_MT_V1_TIME_INC_TAG: {
- unsigned secs_msb, usecs_msb;
- usgnd_int_32 secs, usecs;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
-
- secs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ;
-
- usecs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ + 2 + secs_msb + usecs_msb, trace_size);
-
- GET_VSZ_UI32(secs, c_p, secs_msb);
- GET_VSZ_UI32(usecs, c_p, usecs_msb);
-
- INC_TIME(current_secs, current_usecs, secs, usecs);
-
- break;
- }
-
- case ERTS_MT_V1_STOP_TAG:
-
- op_p->type = EMTP_STOP;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
-
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ + 1 + time_inc_msb, trace_size);
-
- goto read_ending_time_inc;
-
- case ERTS_MT_V1_EXIT_TAG: {
- unsigned exit_status_msb;
-
- op_p->type = EMTP_EXIT;
-
- ehdr >>= ERTS_MT_TAG_EHDR_FLD_SZ;
- exit_status_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ + 2 + exit_status_msb + time_inc_msb,
- trace_size);
-
- GET_VSZ_UI32(op_p->u.exit_status, c_p, exit_status_msb);
-
- read_ending_time_inc: {
- usgnd_int_32 secs, usecs, time_inc;
-
- GET_VSZ_UI32(time_inc, c_p, time_inc_msb);
-
- secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT)
- & ERTS_MT_TIME_INC_SECS_MASK);
- usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT)
- & ERTS_MT_TIME_INC_USECS_MASK);
-
- INC_TIME(current_secs, current_usecs, secs, usecs);
-
- op_p->time.secs = current_secs;
- op_p->time.usecs = current_usecs;
-
-#if PRINT_PARSED_OP
- print_op(op_p);
-#endif
-
- op_p = (emtp_operation *) (((char *) op_p) + op_size);
- statep->force_return = 1;
- statep->progress = EMTP_PROGRESS_ENDED;
-
- tracep = c_p;
- trace_size = trace_endp - tracep;
- result = (trace_size
- ? EMTP_END_OF_TRACE_GARBAGE_FOLLOWS
- : EMTP_END_OF_TRACE);
- goto restore_return;
- }
- }
-
- case ERTS_MT_V1_ALLOCATOR_TAG:
- case ERTS_MT_V1_BLOCK_TYPE_TAG:
-
-#ifdef DEBUG
- hexdump(tracep, trace_endp);
-#endif
- ERROR(EMTP_HEADER_TAG_IN_BODY_ERROR);
-
- default:
-
-#ifdef DEBUG
- hexdump(tracep, trace_endp);
-#endif
- ERROR(EMTP_UNKNOWN_TAG_ERROR);
- }
-
- tracep = c_p;
- trace_size = trace_endp - tracep;
-
- if (op_p >= op_endp) {
- statep->force_return = 1;
- result = EMTP_ALL_OPS_FILLED;
- goto restore_return;
- }
- }
-
- statep->known_need = 0;
- statep->fetch_size = ERTS_MT_MAX_V1_BODY_ENTRY_SIZE;
-
- result = EMTP_NEED_MORE_TRACE;
-
- restore_return:
- *tracepp = tracep;
- *op_pp = op_p;
- statep->time.secs = current_secs;
- statep->time.usecs = current_usecs;
-
- return result;
-}
-
-#define GET_ALLOC_MSBS(EHDR, BT, NP, NS, TI) \
-do { \
- (BT) = (EHDR) & ERTS_MT_UI16_MSB_EHDR_FLD_MSK; \
- (EHDR) >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ; \
- (NP) = (EHDR) & ERTS_MT_UI_MSB_EHDR_FLD_MSK; \
- (EHDR) >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; \
- (NS) = (EHDR) & ERTS_MT_UI_MSB_EHDR_FLD_MSK; \
- (EHDR) >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ; \
- (TI) = (EHDR) & ERTS_MT_UI32_MSB_EHDR_FLD_MSK; \
-} while (0)
-
-
-static EMTP_INLINE int
-parse_v2_body(emtp_state *statep,
- usgnd_int_8 **tracepp, usgnd_int_8 *trace_endp,
- emtp_operation **op_pp, emtp_operation *op_endp, size_t op_size)
-{
- /* "cache" some frequently used values */
- register usgnd_int_8 *c_p = *tracepp;
- register emtp_operation *op_p = *op_pp;
- register usgnd_int_32 current_secs = statep->time.secs;
- register usgnd_int_32 current_usecs = statep->time.usecs;
-
- sgnd_int_32 trace_size = trace_endp - c_p;
- usgnd_int_8 *tracep = c_p;
- int result = 0;
-
- while (trace_size >= UI8_SZ + UI16_SZ) {
- usgnd_int_8 tag;
- usgnd_int_16 ehdr;
- unsigned time_inc_msb;
-
- tag = *(c_p++);
-
- GET_UI16(ehdr, c_p);
-
- switch (tag) {
-
- case ERTS_MT_CRR_ALLOC_BDY_TAG: {
- usgnd_int_16 type;
- unsigned carrier_bytes, carrier_type_msb, block_type_msb,
- new_ptr_msb, new_size_msb;
-
- op_p->type = EMTP_CARRIER_ALLOC;
-
- carrier_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
-
- if (trace_size < ERTS_MT_MAX_CRR_ALLOC_SIZE)
- NEED_AT_LEAST(UI8_SZ + UI16_SZ + 1 + carrier_type_msb,
- ERTS_MT_MAX_CRR_ALLOC_SIZE,
- trace_size);
-
- GET_VSZ_UI16(type, c_p, carrier_type_msb);
- op_p->u.block.carrier_type = (int) type;
-
- carrier_bytes = carrier_type_msb + 1;
- goto alloc_common;
-
- case ERTS_MT_ALLOC_BDY_TAG:
-
- op_p->type = EMTP_ALLOC;
- carrier_bytes = 0;
-
- alloc_common:
- block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
- new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- if (trace_size < ERTS_MT_MAX_CRR_ALLOC_SIZE)
- NEED(UI8_SZ
- + UI16_SZ
- + 4
- + carrier_bytes
- + block_type_msb
- + new_ptr_msb
- + new_size_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UI16(type, c_p, block_type_msb);
- op_p->u.block.type = (int) type;
-
- GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb);
-
- op_p->u.block.prev_ptr = 0;
- }
-
- read_time_inc: {
- usgnd_int_32 secs, usecs, time_inc;
-
- GET_VSZ_UI32(time_inc, c_p, time_inc_msb);
-
- secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT)
- & ERTS_MT_TIME_INC_SECS_MASK);
- usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT)
- & ERTS_MT_TIME_INC_USECS_MASK);
-
- INC_TIME(current_secs, current_usecs, secs, usecs);
-
- op_p->time.secs = current_secs;
- op_p->time.usecs = current_usecs;
-
-#if PRINT_PARSED_OP
- print_op(op_p);
-#endif
-
- op_p = (emtp_operation *) (((char *) op_p) + op_size);
- break;
- }
-
- case ERTS_MT_CRR_REALLOC_BDY_TAG: {
- usgnd_int_16 type;
- unsigned carrier_bytes, carrier_type_msb, block_type_msb,
- new_ptr_msb, prev_ptr_msb, new_size_msb;
-
- op_p->type = EMTP_CARRIER_REALLOC;
-
- carrier_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
-
- if (trace_size < ERTS_MT_MAX_CRR_REALLOC_SIZE)
- NEED_AT_LEAST(UI8_SZ + UI16_SZ + 1 + carrier_type_msb,
- ERTS_MT_MAX_CRR_REALLOC_SIZE,
- trace_size);
-
- GET_VSZ_UI16(type, c_p, carrier_type_msb);
- op_p->u.block.carrier_type = (int) type;
-
- carrier_bytes = carrier_type_msb + 1;
- goto realloc_common;
-
- case ERTS_MT_REALLOC_BDY_TAG:
-
- op_p->type = EMTP_REALLOC;
- carrier_bytes = 0;
-
- realloc_common:
-
- block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
- new_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- new_size_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- if (trace_size < ERTS_MT_MAX_CRR_REALLOC_SIZE)
- NEED(UI8_SZ
- + UI16_SZ
- + 5
- + carrier_bytes
- + block_type_msb
- + new_ptr_msb
- + prev_ptr_msb
- + new_size_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UI16(op_p->u.block.type, c_p, block_type_msb);
- GET_VSZ_UIMAX(op_p->u.block.new_ptr, c_p, new_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb);
- GET_VSZ_UIMAX(op_p->u.block.new_size, c_p, new_size_msb);
-
- goto read_time_inc;
- }
-
- case ERTS_MT_CRR_FREE_BDY_TAG: {
- usgnd_int_16 type;
- unsigned carrier_bytes, carrier_type_msb, block_type_msb,
- prev_ptr_msb;
-
- op_p->type = EMTP_CARRIER_FREE;
-
- carrier_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
-
- if (trace_size < ERTS_MT_MAX_CRR_FREE_SIZE)
- NEED_AT_LEAST(UI8_SZ + UI16_SZ + 1 + carrier_type_msb,
- ERTS_MT_MAX_CRR_FREE_SIZE,
- trace_size);
-
- GET_VSZ_UI16(type, c_p, carrier_type_msb);
- op_p->u.block.carrier_type = (int) type;
-
- carrier_bytes = carrier_type_msb + 1;
- goto free_common;
-
- case ERTS_MT_FREE_BDY_TAG:
-
- op_p->type = EMTP_FREE;
- carrier_bytes = 0;
-
- free_common:
-
- block_type_msb = ehdr & ERTS_MT_UI16_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI16_MSB_EHDR_FLD_SZ;
- prev_ptr_msb = ehdr & ERTS_MT_UI_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- if (trace_size < ERTS_MT_MAX_CRR_FREE_SIZE)
- NEED(UI8_SZ
- + UI16_SZ
- + 3
- + carrier_bytes
- + block_type_msb
- + prev_ptr_msb
- + time_inc_msb,
- trace_size);
-
- GET_VSZ_UI16(op_p->u.block.type, c_p, block_type_msb);
- GET_VSZ_UIMAX(op_p->u.block.prev_ptr, c_p, prev_ptr_msb);
-
- op_p->u.block.new_ptr = 0;
- op_p->u.block.new_size = 0;
-
- goto read_time_inc;
- }
-
- case ERTS_MT_TIME_INC_BDY_TAG: {
- unsigned secs_msb, usecs_msb;
- usgnd_int_32 secs, usecs;
-
- secs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ;
- usecs_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI8_SZ + UI16_SZ + 2 + secs_msb + usecs_msb, trace_size);
-
- GET_VSZ_UI32(secs, c_p, secs_msb);
- GET_VSZ_UI32(usecs, c_p, usecs_msb);
-
- INC_TIME(current_secs, current_usecs, secs, usecs);
-
- break;
- }
-
- case ERTS_MT_STOP_BDY_TAG:
-
- op_p->type = EMTP_STOP;
-
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ + 1 + time_inc_msb, trace_size);
-
- goto read_ending_time_inc;
-
- case ERTS_MT_EXIT_BDY_TAG: {
- unsigned exit_status_msb;
-
- op_p->type = EMTP_EXIT;
-
- exit_status_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
- ehdr >>= ERTS_MT_UI32_MSB_EHDR_FLD_SZ;
- time_inc_msb = ehdr & ERTS_MT_UI32_MSB_EHDR_FLD_MSK;
-
- NEED(UI16_SZ + 2 + exit_status_msb + time_inc_msb, trace_size);
-
- GET_VSZ_UI32(op_p->u.exit_status, c_p, exit_status_msb);
-
- read_ending_time_inc: {
- usgnd_int_32 secs, usecs, time_inc;
-
- GET_VSZ_UI32(time_inc, c_p, time_inc_msb);
-
- secs = ((time_inc >> ERTS_MT_TIME_INC_SECS_SHIFT)
- & ERTS_MT_TIME_INC_SECS_MASK);
- usecs = ((time_inc >> ERTS_MT_TIME_INC_USECS_SHIFT)
- & ERTS_MT_TIME_INC_USECS_MASK);
-
- INC_TIME(current_secs, current_usecs, secs, usecs);
-
- op_p->time.secs = current_secs;
- op_p->time.usecs = current_usecs;
-
-#if PRINT_PARSED_OP
- print_op(op_p);
-#endif
-
- op_p = (emtp_operation *) (((char *) op_p) + op_size);
- statep->force_return = 1;
- statep->progress = EMTP_PROGRESS_ENDED;
-
- tracep = c_p;
- trace_size = trace_endp - tracep;
- result = (trace_size
- ? EMTP_END_OF_TRACE_GARBAGE_FOLLOWS
- : EMTP_END_OF_TRACE);
- goto restore_return;
- }
- }
-
- case ERTS_MT_X_BDY_TAG: {
- /* X for extension
- * ehdr contains total size of entry
- *
- * Entry should at least consist of tag (1 byte),
- * total size (2 bytes) and subtag (1 byte).
- */
- if (ehdr < UI8_SZ + UI16_SZ + UI8_SZ)
- ERROR(EMTP_PARSE_ERROR);
- NEED(ehdr, trace_size);
- c_p = tracep + ehdr; /* No subtags known yet skip entry... */
- break;
- }
-
- default:
-#ifdef DEBUG
- hexdump(c_p-2, trace_endp);
-#endif
- ERROR(EMTP_UNKNOWN_TAG_ERROR);
- }
-
- tracep = c_p;
- trace_size = trace_endp - tracep;
-
- if (op_p >= op_endp) {
- statep->force_return = 1;
- result = EMTP_ALL_OPS_FILLED;
- goto restore_return;
- }
- }
-
- statep->known_need = 0;
- statep->fetch_size = ERTS_MT_MAX_BODY_ENTRY_SIZE;
-
- result = EMTP_NEED_MORE_TRACE;
-
- restore_return:
- *tracepp = tracep;
- *op_pp = op_p;
- statep->time.secs = current_secs;
- statep->time.usecs = current_usecs;
-
- return result;
-}
-
-static void
-remove_unused_allocators(emtp_state *statep)
-{
- emtp_allocator *allctr;
- sgnd_int_32 i, j, k;
- for (i = -1; i <= statep->max_block_type_ix; i++) {
- if (statep->block_type[i]->valid) {
- allctr = statep->allocator[statep->block_type[i]->allocator];
- if (allctr->name != unknown_allocator)
- allctr->valid = 1;
- }
- }
- for (i = -1; i <= statep->max_allocator_ix; i++) {
- allctr = statep->allocator[i];
- if (allctr->valid && allctr->carrier.provider) {
- for (j = 0; j < allctr->carrier.no_providers; j++) {
- k = allctr->carrier.provider[j];
- if (statep->allocator[k]->name != unknown_allocator)
- statep->allocator[k]->valid = 1;
- }
- }
- }
- for (i = -1; i <= statep->max_allocator_ix; i++) {
- allctr = statep->allocator[i];
- if (!allctr->valid) {
- allctr->flags = 0;
- if (allctr->name != unknown_allocator) {
- (*statep->free)((void *) allctr->name);
- allctr->name = unknown_allocator;
- }
- allctr->carrier.no_providers = 0;
- if (allctr->carrier.provider) {
- (*statep->free)((void *) allctr->carrier.provider);
- }
- }
- }
-}
-
-static int
-parse_header(emtp_state *statep,
- usgnd_int_8 **tracepp, usgnd_int_8 *trace_endp)
-{
- sgnd_int_32 trace_size;
- usgnd_int_8 *tracep;
- int i, result;
-
- tracep = *tracepp;
-
- switch (statep->progress) {
- case EMTP_PROGRESS_PARSE_HDR_VSN: {
- usgnd_int_32 start_word;
-
- trace_size = trace_endp - tracep;
- NEED(3*UI32_SZ, trace_size);
-
- GET_UI32(start_word, tracep);
- if (start_word != ERTS_MT_START_WORD)
- return EMTP_NOT_AN_ERL_MTRACE_ERROR;
-
- GET_UI32(statep->version.major, tracep);
- GET_UI32(statep->version.minor, tracep);
-
- statep->progress = EMTP_PROGRESS_PARSE_HDR_PROLOG;
- }
- case EMTP_PROGRESS_PARSE_HDR_PROLOG:
-
- trace_size = trace_endp - tracep;
-
- switch (statep->version.major) {
- case 1: {
- NEED(2*UI32_SZ + 2*UI16_SZ, trace_size);
-
- GET_UI32(statep->flags, tracep);
- SKIP_UI32(tracep); /* ignore this; may contain garbage! */
- GET_UI16(statep->max_allocator_ix, tracep);
- GET_UI16(statep->max_block_type_ix, tracep);
-
- statep->parse_body_func = parse_v1_body;
-
- break;
- }
- case 2: {
- usgnd_int_32 giga_seconds;
- usgnd_int_32 seconds;
- usgnd_int_32 micro_seconds;
- usgnd_int_8 len;
- usgnd_int_8 *hdr_prolog_start;
- usgnd_int_32 hdr_prolog_sz;
- NEED(UI32_SZ, trace_size);
- hdr_prolog_start = tracep;
- GET_UI32(hdr_prolog_sz, tracep);
- NEED(hdr_prolog_sz - UI32_SZ, trace_size);
-
- GET_UI32(statep->flags, tracep);
- GET_UI16(statep->segment_ix, tracep);
- GET_UI16(statep->max_allocator_ix, tracep);
- GET_UI16(statep->max_block_type_ix, tracep);
-
- GET_UI32(giga_seconds, tracep);
- GET_UI32(seconds, tracep);
- GET_UI32(micro_seconds, tracep);
-
- set_start_time(statep, giga_seconds, seconds, micro_seconds);
-
- GET_UI8(len, tracep);
- memcpy((void *) statep->nodename, (void *) tracep, (size_t) len);
- statep->nodename[len] = '\0';
- tracep += len;
-
- GET_UI8(len, tracep);
- memcpy((void *) statep->hostname, (void *) tracep, (size_t) len);
- statep->hostname[len] = '\0';
- tracep += len;
-
- GET_UI8(len, tracep);
- memcpy((void *) statep->pid, (void *) tracep, (size_t) len);
- statep->pid[len] = '\0';
- tracep += len;
-
-
-
- /* Skip things in header prolog we dont know about */
- tracep = hdr_prolog_start + hdr_prolog_sz;
-
-#if EMTP_CAN_INLINE
- statep->parse_body_func = NULL;
-#else
- statep->parse_body_func = parse_v2_body;
-#endif
-
- break;
- }
- default:
- return EMTP_NOT_SUPPORTED_MTRACE_VERSION_ERROR;
- }
-
- statep->progress = EMTP_PROGRESS_ALLOC_HDR_INFO;
-
- case EMTP_PROGRESS_ALLOC_HDR_INFO:
-
- /* Allocator info */
- if (!statep->allocator) {
- statep->allocator = (emtp_allocator **)
- (*statep->alloc)((statep->max_allocator_ix + 2)
- * sizeof(emtp_allocator *));
- if (!statep->allocator)
- ERROR(EMTP_NO_MEMORY_ERROR);
- statep->allocator++;
- for (i = -1; i <= statep->max_allocator_ix; i++)
- statep->allocator[i] = NULL;
- for (i = -1; i <= statep->max_allocator_ix; i++) {
- statep->allocator[i] = (emtp_allocator *)
- (*statep->alloc)(sizeof(emtp_allocator));
- if (!statep->allocator[i])
- ERROR(EMTP_NO_MEMORY_ERROR);
- statep->allocator[i]->valid = 0;
- statep->allocator[i]->flags = 0;
- statep->allocator[i]->name = unknown_allocator;
- statep->allocator[i]->carrier.no_providers = 0;
- statep->allocator[i]->carrier.provider = NULL;
- }
-
- }
-
- /* Block type info */
- if (!statep->block_type) {
- statep->block_type = (emtp_block_type **)
- (*statep->alloc)((statep->max_block_type_ix + 2)
- * sizeof(emtp_block_type *));
- if (!statep->block_type)
- ERROR(EMTP_NO_MEMORY_ERROR);
- statep->block_type++;
- for (i = -1; i <= statep->max_block_type_ix; i++)
- statep->block_type[i] = NULL;
- for (i = -1; i <= statep->max_block_type_ix; i++) {
- statep->block_type[i] = (emtp_block_type *)
- (*statep->alloc)(sizeof(emtp_block_type));
- if (!statep->block_type[i])
- ERROR(EMTP_NO_MEMORY_ERROR);
- statep->block_type[i]->valid = 0;
- statep->block_type[i]->flags = 0;
- statep->block_type[i]->name = unknown_block_type;
- statep->block_type[i]->allocator = UNKNOWN_ALLOCATOR_IX;
- }
-
- }
-
- statep->progress = EMTP_PROGRESS_PARSE_TAGGED_HDR;
-
- case EMTP_PROGRESS_PARSE_TAGGED_HDR: {
- usgnd_int_8 *c_p = tracep;
- trace_size = trace_endp - tracep;
-
- switch (statep->version.major) {
- case 1: /* Version 1.X ---------------------------------------------- */
-
- while (trace_size >= UI16_SZ) {
- size_t str_len;
- usgnd_int_16 ehdr;
-
- GET_UI16(ehdr, c_p);
-
- switch (ehdr & ERTS_MT_TAG_EHDR_FLD_MSK) {
- case ERTS_MT_V1_ALLOCATOR_TAG: {
- usgnd_int_16 a_ix;
-
- NEED_AT_LEAST(2*UI16_SZ + UI8_SZ,
- ERTS_MT_MAX_HEADER_ENTRY_SIZE,
- trace_size);
-
- GET_UI16(a_ix, c_p);
- if (a_ix > statep->max_allocator_ix)
- ERROR(EMTP_PARSE_ERROR);
-
- GET_UI8(str_len, c_p);
-
- NEED(2*UI16_SZ + UI8_SZ + str_len, trace_size);
-
- statep->allocator[a_ix]->name
- = (char *) (*statep->alloc)(str_len + 1);
- if (!statep->allocator[a_ix]->name)
- ERROR(EMTP_NO_MEMORY_ERROR);
-
- memcpy((void *) statep->allocator[a_ix]->name,
- (void *) c_p,
- str_len);
- c_p += str_len;
-
- statep->allocator[a_ix]->name[str_len] = '\0';
- break;
- }
- case ERTS_MT_V1_BLOCK_TYPE_TAG: {
- usgnd_int_16 bt_ix, a_ix;
-
- NEED_AT_LEAST(2*UI16_SZ + UI8_SZ,
- ERTS_MT_MAX_HEADER_ENTRY_SIZE,
- trace_size);
-
- GET_UI16(bt_ix, c_p);
- if (bt_ix > statep->max_block_type_ix)
- ERROR(EMTP_PARSE_ERROR);
-
- GET_UI8(str_len, c_p);
-
- NEED(2*UI16_SZ + UI8_SZ + str_len + UI16_SZ, trace_size);
-
- statep->block_type[bt_ix]->name
- = (char *) (*statep->alloc)(str_len + 1);
-
- if (!statep->block_type[bt_ix]->name)
- ERROR(EMTP_NO_MEMORY_ERROR);
-
- memcpy((void *) statep->block_type[bt_ix]->name,
- (void *) c_p,
- str_len);
- c_p += str_len;
-
- statep->block_type[bt_ix]->name[str_len] = '\0';
-
- GET_UI16(a_ix, c_p);
-
- if (a_ix > statep->max_allocator_ix)
- ERROR(EMTP_PARSE_ERROR);
-
- statep->block_type[bt_ix]->allocator = (sgnd_int_32) a_ix;
- statep->block_type[bt_ix]->valid = 1;
- break;
- }
-
- case ERTS_MT_V1_ALLOC_TAG:
- case ERTS_MT_V1_REALLOC_NPB_TAG:
- case ERTS_MT_V1_REALLOC_MV_TAG:
- case ERTS_MT_V1_REALLOC_NMV_TAG:
- case ERTS_MT_V1_FREE_TAG:
- case ERTS_MT_V1_TIME_INC_TAG:
- case ERTS_MT_V1_STOP_TAG:
- case ERTS_MT_V1_EXIT_TAG:
- remove_unused_allocators(statep);
- statep->progress = EMTP_PROGRESS_PARSE_BODY;
- result = EMTP_HEADER_PARSED;
- statep->force_return = 1;
- goto restore_return;
- default:
- ERROR(EMTP_UNKNOWN_TAG_ERROR);
- }
-
- tracep = c_p;
- trace_size = trace_endp - tracep;
- }
-
- statep->fetch_size = ERTS_MT_MAX_V1_HEADER_ENTRY_SIZE;
- break;
-
- case 2: /* Version 2.X ---------------------------------------------- */
-
- while (trace_size >= UI8_SZ + UI16_SZ) {
- usgnd_int_16 entry_sz;
- size_t str_len;
- usgnd_int_8 tag;
-
- GET_UI8(tag, c_p);
- GET_UI16(entry_sz, c_p);
- NEED(entry_sz, trace_size);
-
- switch (tag) {
- case ERTS_MT_ALLOCATOR_HDR_TAG: {
- usgnd_int_8 crr_prvds;
- usgnd_int_16 a_ix, aflgs;
-
- if (entry_sz
- < UI8_SZ + 3*UI16_SZ + UI8_SZ + 0 + UI8_SZ)
- ERROR(EMTP_PARSE_ERROR);
-
- GET_UI16(aflgs, c_p);
- GET_UI16(a_ix, c_p);
- if (a_ix > statep->max_allocator_ix)
- ERROR(EMTP_PARSE_ERROR);
-
- if (aflgs & ERTS_MT_ALLCTR_USD_CRR_INFO)
- statep->allocator[a_ix]->flags
- |= EMTP_ALLOCATOR_FLAG_HAVE_USED_CARRIERS_INFO;
-
- GET_UI8(str_len, c_p);
-
- if (entry_sz
- < UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI8_SZ)
- ERROR(EMTP_PARSE_ERROR);
-
- statep->allocator[a_ix]->name
- = (char *) (*statep->alloc)(str_len + 1);
- if (!statep->allocator[a_ix]->name)
- ERROR(EMTP_NO_MEMORY_ERROR);
-
- memcpy((void *) statep->allocator[a_ix]->name,
- (void *) c_p,
- str_len);
- c_p += str_len;
-
- statep->allocator[a_ix]->name[str_len] = '\0';
-
- GET_UI8(crr_prvds, c_p);
- if (entry_sz < (UI8_SZ
- + 3*UI16_SZ
- + UI8_SZ
- + str_len
- + UI8_SZ
- + crr_prvds*UI16_SZ))
- ERROR(EMTP_PARSE_ERROR);
- statep->allocator[a_ix]->carrier.no_providers
- = (usgnd_int_16) crr_prvds;
- statep->allocator[a_ix]->carrier.provider = (usgnd_int_16 *)
- (*statep->alloc)(crr_prvds*sizeof(usgnd_int_16));
- if (!statep->allocator[a_ix]->carrier.provider)
- ERROR(EMTP_NO_MEMORY_ERROR);
- for (i = 0; i < crr_prvds; i++) {
- usgnd_int_16 cp_ix;
- GET_UI16(cp_ix, c_p);
- if (cp_ix > statep->max_allocator_ix)
- ERROR(EMTP_PARSE_ERROR);
- statep->allocator[a_ix]->carrier.provider[i] = cp_ix;
- }
-
- break;
- }
-
- case ERTS_MT_BLOCK_TYPE_HDR_TAG: {
- usgnd_int_16 bt_ix, a_ix;
-
- if (entry_sz
- < UI8_SZ + 3*UI16_SZ + UI8_SZ + 0 + UI16_SZ)
- ERROR(EMTP_PARSE_ERROR);
-
- SKIP_UI16(c_p); /* bitflags */
- GET_UI16(bt_ix, c_p);
- if (bt_ix > statep->max_block_type_ix)
- ERROR(EMTP_PARSE_ERROR);
-
- GET_UI8(str_len, c_p);
-
- if (entry_sz
- < UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI16_SZ)
- ERROR(EMTP_PARSE_ERROR);
-
- statep->block_type[bt_ix]->name
- = (char *) (*statep->alloc)(str_len + 1);
-
- if (!statep->block_type[bt_ix]->name)
- ERROR(EMTP_NO_MEMORY_ERROR);
-
- memcpy((void *) statep->block_type[bt_ix]->name,
- (void *) c_p,
- str_len);
- c_p += str_len;
-
- statep->block_type[bt_ix]->name[str_len] = '\0';
-
- GET_UI16(a_ix, c_p);
-
- if (a_ix > statep->max_allocator_ix)
- ERROR(EMTP_PARSE_ERROR);
-
- statep->block_type[bt_ix]->allocator = (sgnd_int_32) a_ix;
- statep->block_type[bt_ix]->valid = 1;
- break;
- }
-
- case ERTS_MT_END_OF_HDR_TAG:
- tracep = tracep + ((size_t) entry_sz);
- remove_unused_allocators(statep);
- statep->progress = EMTP_PROGRESS_PARSE_BODY;
- result = EMTP_HEADER_PARSED;
- statep->force_return = 1;
- goto restore_return;
-
- default:
- /* Skip tags that we do not understand. */
- break;
- }
-
- tracep = tracep + ((size_t) entry_sz);
- ASSERT(c_p <= tracep);
- c_p = tracep;
- trace_size = trace_endp - tracep;
- }
-
- statep->fetch_size = UI8_SZ + UI16_SZ;
- break;
- default: /* Not supported version --------------------------------- */
- ASSERT(0);
- }
-
- break;
- }
- default:
- ASSERT(0);
- }
-
- statep->known_need = 0;
- result = EMTP_NEED_MORE_TRACE;
-
- restore_return:
-
- *tracepp = tracep;
-
- return result;
-
-}
-
-
-int
-emtp_parse(emtp_state *statep,
- usgnd_int_8 **tracepp, size_t *trace_lenp,
- emtp_operation *op_start, size_t op_size, size_t *op_lenp)
-{
- int result, have_all_in_overflow;
- usgnd_int_8 *tracep, *trace_endp;
- emtp_operation *op_p, *op_endp;
-
-
- have_all_in_overflow = 0;
-
- op_p = op_start;
-
- if (!statep)
- return EMTP_NO_MEMORY_ERROR;
-
- if (!tracepp || !trace_lenp)
- return EMTP_NO_TRACE_ERROR;
-
- if (*trace_lenp <= 0) {
- if (op_lenp)
- *op_lenp = 0;
- return EMTP_NEED_MORE_TRACE;
- }
-
- statep->force_return = 0;
-
- if (statep->overflow_size) { /* Overflow from prevoius parse */
- sgnd_int_32 tsz;
- sgnd_int_32 sz;
-
- fetch_for_overflow:
- sz = statep->fetch_size - statep->overflow_size;
- ASSERT(sz > 0);
-
- if (*trace_lenp <= sz) {
- have_all_in_overflow = 1;
- sz = *trace_lenp;
- }
-
- if (sz > statep->overflow_buf_size) {
- size_t buf_sz = statep->overflow_size + sz;
- void *buf = (*statep->realloc)((void *) statep->overflow, buf_sz);
- if (!buf)
- return EMTP_NO_MEMORY_ERROR;
- statep->overflow_buf_size = buf_sz;
- statep->overflow = (usgnd_int_8 *) buf;
- }
-
- memcpy((void *) (statep->overflow + statep->overflow_size),
- (void *) *tracepp,
- sz);
-
- tsz = statep->overflow_size + sz;
-
- tracep = statep->overflow;
- trace_endp = statep->overflow + tsz;
-
- if (tsz < statep->fetch_size && statep->known_need) {
- ASSERT(have_all_in_overflow);
- statep->overflow_size = tsz;
- op_endp = NULL;
- result = EMTP_NEED_MORE_TRACE;
- goto restore_return;
- }
- }
- else {
- tracep = *tracepp;
- trace_endp = tracep + *trace_lenp;
- }
-
- if (statep->progress == EMTP_PROGRESS_PARSE_BODY) {
-
-#if !HAVE_INT_64
- if (statep->flags & ERTS_MT_64_BIT_FLAG)
- return EMTP_NOT_SUPPORTED_64_BITS_TRACE_ERROR;
-#endif
-
- if (op_size < sizeof(emtp_operation))
- return EMTP_BAD_OP_SIZE_ERROR;
- if (!op_start || !op_lenp || *op_lenp < 1)
- return EMTP_NO_OPERATIONS_ERROR;
- op_endp = (emtp_operation *) (((char *) op_start) + (*op_lenp)*op_size);
-
- restart_parse_body:
-#if EMTP_CAN_INLINE
- if (statep->parse_body_func)
-#endif
- result = (*statep->parse_body_func)(statep,
- &tracep, trace_endp,
- &op_p, op_endp, op_size);
-#if EMTP_CAN_INLINE
- else
- result = parse_v2_body(statep,
- &tracep, trace_endp,
- &op_p, op_endp, op_size);
-#endif
- }
- else {
- restart_parse_header:
- op_endp = NULL;
- if (statep->progress == EMTP_PROGRESS_ENDED) {
- result = EMTP_END_OF_TRACE;
- goto restore_return;
- }
- result = parse_header(statep, &tracep, trace_endp);
- }
-
- /* Check overflow */
- if (statep->overflow_size) {
- if (tracep == statep->overflow) {
- /* Nothing parsed, i.e. less new input than 1 entry :( */
- if (!have_all_in_overflow)
- goto fetch_for_overflow;
- statep->overflow_size = trace_endp - tracep;
- trace_endp = tracep = *tracepp + *trace_lenp;
- }
- else {
- size_t sz = tracep - (statep->overflow + statep->overflow_size);
-
- ASSERT(sz > 0);
-
- statep->overflow_size = 0;
-
- tracep = *tracepp + sz;
- trace_endp = *tracepp + *trace_lenp;
- ASSERT(trace_endp >= tracep);
- if (!statep->force_return && (trace_endp - tracep)) {
- if (statep->progress == EMTP_PROGRESS_PARSE_BODY)
- goto restart_parse_body;
- else
- goto restart_parse_header;
- }
- /* else: got it all in the overflow buffer */
- }
- }
- else {
- size_t sz = trace_endp - tracep;
- if (!statep->force_return && sz) {
- if (sz >= statep->fetch_size) {
- ASSERT(0);
- ERROR(EMTP_PARSE_ERROR);
- }
- if (sz > statep->overflow_buf_size) {
- (*statep->free)((void *) statep->overflow);
- statep->overflow = (usgnd_int_8 *) (*statep->alloc)(sz);
- if (!statep->overflow) {
- statep->overflow_buf_size = 0;
- return EMTP_NO_MEMORY_ERROR;
- }
- statep->overflow_buf_size = sz;
- }
- memcpy((void *) statep->overflow, tracep, sz);
- statep->overflow_size = sz;
- ASSERT(tracep + sz == trace_endp);
- tracep = trace_endp;
- }
- }
-
- restore_return:
- ASSERT(trace_endp >= tracep);
-
- *tracepp = tracep;
- *trace_lenp = trace_endp - tracep;
-
- if (op_lenp && op_size > 0)
- *op_lenp = (int) (((char *) op_p) - ((char *) op_start))/op_size;
-
- return result;
-}
-
-#ifdef DEBUG
-static void
-hexdump(void *start, void *end)
-{
- unsigned char *p = (unsigned char *) start;
-
- fprintf(stderr, "hexdump: ");
- while ((void *) p < end) {
- fprintf(stderr, "%x", (unsigned) *p);
- p++;
- }
- fprintf(stderr, "\n");
-}
-
-#if PRINT_PARSED_OP
-static void
-print_op(emtp_operation *op_p)
-{
- switch (op_p->type) {
- case EMTP_ALLOC:
- fprintf(stderr,
- "alloc: "
- "type=%" USGND_INT_16_FSTR ", "
- "ptr=%" USGND_INT_MAX_FSTR ", "
- "sz=%" USGND_INT_MAX_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.block.type,
- op_p->u.block.new_ptr,
- op_p->u.block.new_size,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_REALLOC:
- fprintf(stderr,
- "realloc: "
- "type=%" USGND_INT_16_FSTR ", "
- "ptr=%" USGND_INT_MAX_FSTR ", "
- "prev_ptr=%" USGND_INT_MAX_FSTR ", "
- "sz=%" USGND_INT_MAX_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.block.type,
- op_p->u.block.new_ptr,
- op_p->u.block.prev_ptr,
- op_p->u.block.new_size,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_FREE:
- fprintf(stderr,
- "free: "
- "type=%" USGND_INT_16_FSTR ", "
- "ptr=%" USGND_INT_MAX_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.block.type,
- op_p->u.block.prev_ptr,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_CARRIER_ALLOC:
- fprintf(stderr,
- "carrier_alloc: "
- "type=%" USGND_INT_16_FSTR ", "
- "carrier_type=%" USGND_INT_16_FSTR ", "
- "ptr=%" USGND_INT_MAX_FSTR ", "
- "sz=%" USGND_INT_MAX_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.block.type,
- op_p->u.block.carrier_type,
- op_p->u.block.new_ptr,
- op_p->u.block.new_size,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_CARRIER_REALLOC:
- fprintf(stderr,
- "carrier_realloc: "
- "type=%" USGND_INT_16_FSTR ", "
- "carrier_type=%" USGND_INT_16_FSTR ", "
- "ptr=%" USGND_INT_MAX_FSTR ", "
- "prev_ptr=%" USGND_INT_MAX_FSTR ", "
- "sz=%" USGND_INT_MAX_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.block.type,
- op_p->u.block.carrier_type,
- op_p->u.block.new_ptr,
- op_p->u.block.prev_ptr,
- op_p->u.block.new_size,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_CARRIER_FREE:
- fprintf(stderr,
- "carrier_free: "
- "type=%" USGND_INT_16_FSTR ", "
- "carrier_type=%" USGND_INT_16_FSTR ", "
- "ptr=%" USGND_INT_MAX_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.block.type,
- op_p->u.block.carrier_type,
- op_p->u.block.prev_ptr,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_STOP:
- fprintf(stderr,
- "stop: "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->time.secs,
- op_p->time.usecs);
- break;
- case EMTP_EXIT:
- fprintf(stderr,
- "exit: "
- "status=%" USGND_INT_32_FSTR ", "
- "(secs=%" USGND_INT_32_FSTR ", usecs=%" USGND_INT_32_FSTR ")"
- "\n",
- op_p->u.exit_status,
- op_p->time.secs,
- op_p->time.usecs);
- break;
- default:
- fprintf(stderr, "Unknown op type: %d\n", op_p->type);
- break;
- }
-}
-
-#endif
-#endif
diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c
index b35d53be7d..62a49c5b08 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-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2006-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,15 +41,9 @@
# ifdef SYS_SELECT_H
# include <sys/select.h>
# endif
-# if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-# else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
+# include <time.h>
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
# endif
# include <string.h>
# include <stdio.h>
@@ -240,7 +234,7 @@ erts_cpu_info_create(void)
cpuinfo->online = -1;
cpuinfo->available = -1;
cpuinfo->quota = -1;
- erts_cpu_info_update(cpuinfo);
+ erts_cpu_info_update(cpuinfo, 1);
return cpuinfo;
}
@@ -265,7 +259,8 @@ erts_cpu_info_destroy(erts_cpu_info_t *cpuinfo)
}
int
-erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
+erts_cpu_info_update(erts_cpu_info_t *cpuinfo,
+ int skip_read_topology)
{
int changed = 0;
int configured = 0;
@@ -430,7 +425,9 @@ erts_cpu_info_update(erts_cpu_info_t *cpuinfo)
old_topology_size = cpuinfo->topology_size;
cpuinfo->topology = NULL;
- read_topology(cpuinfo);
+ if (!skip_read_topology) {
+ read_topology(cpuinfo);
+ }
if (cpuinfo->topology_size != old_topology_size
|| (old_topology_size != 0
diff --git a/erts/lib_src/common/ethr_atomics.c b/erts/lib_src/common/ethr_atomics.c
index 1594d78f5e..ead086e866 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-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@
* - read
* - init
*
- * Appart from a function implementing the atomic operation
+ * Apart from a function implementing the atomic operation
* with unspecified memory barrier semantics, there are
* functions implementing each operation with the following
* implied memory barrier semantics:
diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c
index d51cb5a9fb..937401cff5 100644
--- a/erts/lib_src/common/ethr_aux.c
+++ b/erts/lib_src/common/ethr_aux.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,6 +107,8 @@ x86_init(void)
ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx);
+ ethr_runtime__.conf.have_cpuid = (eax > 0);
+
if (eax > 0
&& (ETHR_IS_X86_VENDOR("GenuineIntel", ebx, ecx, edx)
|| ETHR_IS_X86_VENDOR("AuthenticAMD", ebx, ecx, edx)
@@ -752,7 +754,7 @@ ETHR_IMPL_NORETURN__ ethr_fatal_error__(const char *file,
}
ETHR_IMPL_NORETURN__
-ethr_assert_failed(const char *file, int line, const char *func, char *a)
+ethr_assert_failed(const char *file, int line, const char *func, const char *a)
{
fprintf(stderr, "%s:%d: %s(): Assertion failed: %s\n", file, line, func, a);
ethr_abort__();
diff --git a/erts/lib_src/common/ethr_cbf.c b/erts/lib_src/common/ethr_cbf.c
index 037559be22..87278ef604 100644
--- a/erts/lib_src/common/ethr_cbf.c
+++ b/erts/lib_src/common/ethr_cbf.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
/*
* We keep this function alone in a separate file so the
- * compiler wont optimize it away.
+ * compiler won't optimize it away.
*/
#ifdef HAVE_CONFIG_H
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index dc25c7a759..636adfe397 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -884,7 +884,7 @@ enqueue_mtx(ethr_mutex *mtx, ethr_ts_event *tse_start, ethr_ts_event *tse_end)
* is not currently locked by current thread, we almost certainly have a
* hard to debug race condition. There might however be some (strange)
* use for it. POSIX also allow a call to `pthread_cond_signal' or
- * `pthread_cond_broadcast' even though the the associated mutex isn't
+ * `pthread_cond_broadcast' even though the associated mutex isn't
* locked by the caller. Therefore, we also allow this kind of strange
* usage, but optimize for the case where the mutex is locked by the
* calling thread.
@@ -1905,7 +1905,7 @@ rwmutex_freqread_rdrs_dec_chk_wakeup(ethr_rwmutex *rwmtx,
* A writer that just enqueued (not seen by us
* in flag field) may depend on someone else
* completing the runlock. We just took over
- * that responsibilty since we modified reader
+ * that responsibility since we modified reader
* groups.
*/
rwmutex_try_complete_runlock(rwmtx, act, tse, 1, 0, 0);
@@ -2720,6 +2720,28 @@ ethr_rwmutex_init(ethr_rwmutex *rwmtx)
return ethr_rwmutex_init_opt(rwmtx, NULL);
}
+size_t
+ethr_rwmutex_size(ethr_rwmutex *rwmtx) {
+#if ETHR_XCHK
+ if (ethr_not_inited__) {
+ ETHR_ASSERT(0);
+ return EACCES;
+ }
+ if (!rwmtx || rwmtx->initialized != ETHR_RWMUTEX_INITIALIZED) {
+ ETHR_ASSERT(0);
+ return EINVAL;
+ }
+#endif
+ switch (rwmtx->type) {
+ case ETHR_RWMUTEX_TYPE_FREQUENT_READ:
+ return sizeof(ethr_rwmtx_readers_array__) * (reader_groups_array_size + 1);
+ case ETHR_RWMUTEX_TYPE_EXTREMELY_FREQUENT_READ:
+ return sizeof(ethr_rwmtx_readers_array__) * (main_threads_array_size + 1);
+ default:
+ return 0;
+ }
+}
+
int
ethr_rwmutex_destroy(ethr_rwmutex *rwmtx)
{
@@ -3098,6 +3120,11 @@ ethr_rwmutex_init_opt(ethr_rwmutex *rwmtx, ethr_rwmutex_opt *opt)
return ethr_rwmutex_init(rwmtx);
}
+size_t
+ethr_rwmutex_size(ethr_rwmutex *rwmtx) {
+ return 0;
+}
+
int
ethr_rwmutex_destroy(ethr_rwmutex *rwmtx)
{
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index f7262c02b1..b17aa3a17f 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,15 +30,9 @@
#define ETHR_CHILD_WAIT_SPIN_COUNT 4000
#include <stdio.h>
-#ifdef ETHR_TIME_WITH_SYS_TIME
-# include <time.h>
+#include <time.h>
+#ifdef ETHR_HAVE_SYS_TIME_H
# include <sys/time.h>
-#else
-# ifdef ETHR_HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
#include <sys/types.h>
#include <unistd.h>
@@ -152,7 +146,7 @@ ppc_init__(void)
{
int pid;
- /* If anything what so ever failes we assume no lwsync for safety */
+ /* If anything what so ever fails we assume no lwsync for safety */
ethr_runtime__.conf.have_lwsync = 0;
/*
@@ -225,7 +219,7 @@ ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx)
#endif
#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__
/*
- * When position independet code is used in 32-bit mode, the B register
+ * When position independent code is used in 32-bit mode, the B register
* is used for storage of global offset table address, and we may not
* use it as input or output in an asm. We need to save and restore the
* B register explicitly (for some reason gcc doesn't provide this
diff --git a/erts/lib_src/utils/make_atomics_api b/erts/lib_src/utils/make_atomics_api
index f960b97c87..48b36025bf 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1463,7 +1463,7 @@ comments() ->
end,
?DW_ATOMIC_OPS),
" *
- * Appart from a function implementing the atomic operation
+ * Apart from a function implementing the atomic operation
* with unspecified memory barrier semantics, there are
* functions implementing each operation with the following
* implied memory barrier semantics:",
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md
index ab89576f08..a6a6d3a1e5 100644
--- a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/README.md
@@ -10,7 +10,7 @@ Supports a subset of the syntax and semantics of the Python standard library imp
### Current status
All supported regex-operators seem to work properly according to the test-set, with the following exception:
-There is a problem with ranges (e.g. `[0-9]` for a digit 0-9) combined with inverted character-cases, e.g. `[^ab]` for anything but 'a' or 'b' - like `[^-0-9]` for anything not '-' or a digit 0-9. I think the code mathces too broadly in that case.
+There is a problem with ranges (e.g. `[0-9]` for a digit 0-9) combined with inverted character-cases, e.g. `[^ab]` for anything but 'a' or 'b' - like `[^-0-9]` for anything not '-' or a digit 0-9. I think the code matches too broadly in that case.
I think you should test the patterns you are going to use. You can easily modify the test-harness to generate tests for your intended patterns to check for compliance.
diff --git a/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/UPGRADE_NOTE b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/UPGRADE_NOTE
new file mode 100644
index 0000000000..b895003a69
--- /dev/null
+++ b/erts/lib_src/yielding_c_fun/lib/tiny_regex_c/UPGRADE_NOTE
@@ -0,0 +1,10 @@
+The scripts folder (contained test python scripts) that existed in the
+original repository has been removed as it was not used and contained a
+license text that was incompatible with Erlang/OTP's license.
+
+The tests folder that exited in the original repository has also been
+removed because it was not used.
+
+The file GIT_VERSION contains information of which repository URL and
+GIT version the code in this folder was fetched from. The GIT_VERSION
+file should be updated if the code in this folder is upgraded. \ No newline at end of file
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md
index 167a69d08c..f3d2e8e49a 100644
--- a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/README.md
@@ -13,7 +13,7 @@ At the moment, only SHA-256 is implemented.
- ANSI C with as little specific C99 as possible (e.g. extended
integer types are used, but not bool).
-- Portable. Makes no assumptions on the target system's endianess or
+- Portable. Makes no assumptions on the target system's endianness or
word size.
- The SHA-256 implementation is a straightforward implementation of
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c
index 4338531d7e..c485596e1b 100644
--- a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256.c
@@ -93,7 +93,7 @@ static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state)
* Now:
* - either there is enough space left for the total length, and we can conclude,
* - or there is too little space left, and we have to pad the rest of this chunk with zeroes.
- * In the latter case, we will conclude at the next invokation of this function.
+ * In the latter case, we will conclude at the next invocation of this function.
*/
if (space_in_chunk >= TOTAL_LEN_LEN) {
const size_t left = space_in_chunk - TOTAL_LEN_LEN;
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c
index 53d6ff2e2a..f706429fc6 100644
--- a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha-2/sha-256_orginal.c
@@ -89,7 +89,7 @@ static int calc_chunk(uint8_t chunk[CHUNK_SIZE], struct buffer_state * state)
* Now:
* - either there is enough space left for the total length, and we can conclude,
* - or there is too little space left, and we have to pad the rest of this chunk with zeroes.
- * In the latter case, we will conclude at the next invokation of this function.
+ * In the latter case, we will conclude at the next invocation of this function.
*/
if (space_in_chunk >= TOTAL_LEN_LEN) {
const size_t left = space_in_chunk - TOTAL_LEN_LEN;
diff --git a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c
index 6ad22c1dcd..a7c6746806 100644
--- a/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c
+++ b/erts/lib_src/yielding_c_fun/test/examples/sha256_erlang_nif/c_src/sha256_nif.c
@@ -105,7 +105,7 @@ sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return enif_make_badarg(env);
}
- /* Copy the input binary to the work environemnt so it will be kept when we are yielding */
+ /* Copy the input binary to the work environment so it will be kept when we are yielding */
ERL_NIF_TERM input_bin_term = enif_make_copy(work_env, argv[0]);
ErlNifBinary input_bin;
enif_inspect_binary(work_env, input_bin_term, &input_bin);
diff --git a/erts/lib_src/yielding_c_fun/ycf_lexer.c b/erts/lib_src/yielding_c_fun/ycf_lexer.c
index 91426b88c2..781a5db166 100644
--- a/erts/lib_src/yielding_c_fun/ycf_lexer.c
+++ b/erts/lib_src/yielding_c_fun/ycf_lexer.c
@@ -127,7 +127,7 @@ int string_litteral_finder(symbol_finder* f, char* text){
if(starts_with(&(text[pos]), "\"")){
return pos + 1;
}else {
- printf("Broken string litteral\n");
+ printf("Broken string literal\n");
exit(1);
}
}
diff --git a/erts/lib_src/yielding_c_fun/ycf_node.c b/erts/lib_src/yielding_c_fun/ycf_node.c
index 82f4b9f6b5..6afc23db83 100644
--- a/erts/lib_src/yielding_c_fun/ycf_node.c
+++ b/erts/lib_src/yielding_c_fun/ycf_node.c
@@ -897,7 +897,7 @@ void ycf_node_normalize_function(ycf_node* fun){
ycf_node_insert_scopes_in_complex_statements(&fun->u.function.body);
/* Move out declarations from for loops */
ycf_node_normalize_for_var_declarations(&fun->u.function.body);
- /* Move in code declations to top of scope */
+ /* Move in code declarations to top of scope */
ycf_node_move_in_code_var_declarations_to_top(&fun->u.function.body);
/* Normalize declarations */
ycf_node_normalize_init_definitions_in_scope(&fun->u.function.body);
diff --git a/erts/lib_src/yielding_c_fun/ycf_printers.c b/erts/lib_src/yielding_c_fun/ycf_printers.c
index 23c10d5fa5..1326243dc3 100644
--- a/erts/lib_src/yielding_c_fun/ycf_printers.c
+++ b/erts/lib_src/yielding_c_fun/ycf_printers.c
@@ -348,7 +348,7 @@ void print_definition(ycf_node_definition d){
void print_scope(ycf_node_code_scope node){
printf("NODE: scope\n");
printf(">>>>>>>>>>>>>>>>>>>>>>>\n");
- printf("Defenition Nodes:\n");
+ printf("Definition Nodes:\n");
struct ycf_node* n = node.definition_nodes.head;
while(n != NULL){
print_abstract_syntax_tree(n);
diff --git a/erts/lib_src/yielding_c_fun/ycf_yield_fun.c b/erts/lib_src/yielding_c_fun/ycf_yield_fun.c
index c03cbc19ef..cd927b7716 100644
--- a/erts/lib_src/yielding_c_fun/ycf_yield_fun.c
+++ b/erts/lib_src/yielding_c_fun/ycf_yield_fun.c
@@ -994,7 +994,7 @@ void ast_add_yield_code_generated_define(ycf_node* source_out_tree/*Will be chan
" * static int test(){ return 0;}\n"
" * YCF_GCC_DIAG_ON(unused-function)\n"
" *\n"
- " * These macros were orginally authored by Jonathan Wakely and has\n"
+ " * These macros were originally authored by Jonathan Wakely and has\n"
" * been modified by Patrick Horgan.\n"
" *\n"
" * Source: http://dbp-consulting.com/tutorials/SuppressingGCCWarnings.html\n"
@@ -1653,7 +1653,7 @@ ycf_node* ast_get_ast_with_yieldified_function(ycf_node* source_tree,
ycf_node_rename_function(&fun_change->u.function,
ycf_string_new("%s_ycf_gen_yielding",
yielding_function_name));
- /* Remove unecessary scopes */
+ /* Remove unnecessary scopes */
ycf_node_remove_unecessary_scopes(&fun_change->u.function.body);
/* Exit with error message if a function call to a yielding function
is not transformed */
diff --git a/erts/preloaded/ebin/atomics.beam b/erts/preloaded/ebin/atomics.beam
index 7fdd2502a4..6ab249d8fc 100644
--- a/erts/preloaded/ebin/atomics.beam
+++ b/erts/preloaded/ebin/atomics.beam
Binary files differ
diff --git a/erts/preloaded/ebin/counters.beam b/erts/preloaded/ebin/counters.beam
index 0eb323940e..2d0580cc89 100644
--- a/erts/preloaded/ebin/counters.beam
+++ b/erts/preloaded/ebin/counters.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erl_init.beam b/erts/preloaded/ebin/erl_init.beam
index 4bcd62ed43..b0ee881e2f 100644
--- a/erts/preloaded/ebin/erl_init.beam
+++ b/erts/preloaded/ebin/erl_init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index 1ec35ba8fd..8612761a9c 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/erl_tracer.beam b/erts/preloaded/ebin/erl_tracer.beam
index a82a17a2f5..380f5d8ea9 100644
--- a/erts/preloaded/ebin/erl_tracer.beam
+++ b/erts/preloaded/ebin/erl_tracer.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index a7a7062442..63d08c4614 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_code_purger.beam b/erts/preloaded/ebin/erts_code_purger.beam
index f2b141f2b3..7918e37d6a 100644
--- a/erts/preloaded/ebin/erts_code_purger.beam
+++ b/erts/preloaded/ebin/erts_code_purger.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam b/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam
index 948fef6785..b63e4dd6fc 100644
--- a/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam
+++ b/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index e9a938faa9..c2a9d1fbea 100644
--- a/erts/preloaded/ebin/erts_internal.beam
+++ b/erts/preloaded/ebin/erts_internal.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_literal_area_collector.beam b/erts/preloaded/ebin/erts_literal_area_collector.beam
index b6a13f4034..165bfa4622 100644
--- a/erts/preloaded/ebin/erts_literal_area_collector.beam
+++ b/erts/preloaded/ebin/erts_literal_area_collector.beam
Binary files differ
diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam
index fe06d5c1f4..93c95568ad 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/ebin/persistent_term.beam b/erts/preloaded/ebin/persistent_term.beam
index d11de4ef6d..eee6b18bd4 100644
--- a/erts/preloaded/ebin/persistent_term.beam
+++ b/erts/preloaded/ebin/persistent_term.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_buffer.beam b/erts/preloaded/ebin/prim_buffer.beam
index af58495025..70b331a353 100644
--- a/erts/preloaded/ebin/prim_buffer.beam
+++ b/erts/preloaded/ebin/prim_buffer.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam
index 7c85e0e41b..7253202ea4 100644
--- a/erts/preloaded/ebin/prim_eval.beam
+++ b/erts/preloaded/ebin/prim_eval.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index d5d2d3ab8d..4bb0a1b9e7 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 ad098eeb68..5f61ab8cba 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_net.beam b/erts/preloaded/ebin/prim_net.beam
index 240f27b436..a39a3d1115 100644
--- a/erts/preloaded/ebin/prim_net.beam
+++ b/erts/preloaded/ebin/prim_net.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_socket.beam b/erts/preloaded/ebin/prim_socket.beam
index 1fb181caab..7eb287597f 100644
--- a/erts/preloaded/ebin/prim_socket.beam
+++ b/erts/preloaded/ebin/prim_socket.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam
index fd6c473023..8bee02d875 100644
--- a/erts/preloaded/ebin/prim_zip.beam
+++ b/erts/preloaded/ebin/prim_zip.beam
Binary files differ
diff --git a/erts/preloaded/ebin/socket_registry.beam b/erts/preloaded/ebin/socket_registry.beam
index 41036b0355..c8f4e9e983 100644
--- a/erts/preloaded/ebin/socket_registry.beam
+++ b/erts/preloaded/ebin/socket_registry.beam
Binary files differ
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index a73471d301..53f355e465 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 521e5b6f67..1994aa1302 100644
--- a/erts/preloaded/src/Makefile
+++ b/erts/preloaded/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2021. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -33,14 +33,10 @@ STATIC_EBIN=../ebin
include $(ERL_TOP)/erts/vsn.mk
include $(ERL_TOP)/lib/kernel/vsn.mk
-ifeq ($(USE_ESOCK), yes)
PRE_LOADED_ERL_ESOCK_MODULES = \
socket_registry \
prim_socket \
prim_net
-else
-PRE_LOADED_ERL_ESOCK_MODULES =
-endif
PRE_LOADED_ERL_MODULES = \
erl_prim_loader \
@@ -81,11 +77,7 @@ STATIC_TARGET_FILES = $(PRE_LOADED_MODULES:%=$(STATIC_EBIN)/%.$(EMULATOR))
APP_FILE= erts.app
APP_SRC= $(APP_FILE).src
APP_TARGET= $(STATIC_EBIN)/$(APP_FILE)
-ifeq ($(USE_ESOCK), yes)
APP_ESOCK_MODS= prim_net, prim_socket, socket_registry,
-else
-APP_ESOCK_MODS=
-endif
KERNEL_SRC=$(ERL_TOP)/lib/kernel/src
@@ -94,6 +86,10 @@ STDLIB_INCLUDE=$(ERL_TOP)/lib/stdlib/include
ERL_COMPILE_FLAGS += +debug_info -I$(KERNEL_SRC) -I$(KERNEL_INCLUDE)
+ifeq ($(ERL_DETERMINISTIC),yes)
+ ERL_COMPILE_FLAGS += deterministic
+endif
+
DIA_PLT = erts-preloaded.plt
DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
ifeq ($(DIAW_EH),true)
diff --git a/erts/preloaded/src/add_abstract_code b/erts/preloaded/src/add_abstract_code
index 9040199417..2d426f37d4 100644
--- a/erts/preloaded/src/add_abstract_code
+++ b/erts/preloaded/src/add_abstract_code
@@ -4,7 +4,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,12 @@ main([BeamFile,AbstrFile]) ->
fix_options(CInf0) ->
CInf1 = binary_to_term(CInf0),
- {options,Opts0} = lists:keyfind(options, 1, CInf1),
- Opts = Opts0 -- [from_asm],
+ Opts =
+ case lists:keyfind(options, 1, CInf1) of
+ {options,Opts0} ->
+ Opts0 -- [from_asm];
+ false ->
+ []
+ end,
CInf = lists:keyreplace(options, 1, CInf1, {options,Opts}),
{term_to_binary(CInf), Opts}.
diff --git a/erts/preloaded/src/erl_tracer.erl b/erts/preloaded/src/erl_tracer.erl
index c810069d17..20416d02c2 100644
--- a/erts/preloaded/src/erl_tracer.erl
+++ b/erts/preloaded/src/erl_tracer.erl
@@ -2,6 +2,8 @@
-export([enabled/3, trace/5, on_load/0]).
+-nifs([enabled/3, trace/5]).
+
-type tracee() :: port() | pid() | undefined.
-type trace_tag_running_ports() :: in | out | in_exiting | out_exiting | out_exited.
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index ab42ff437f..41471e51e2 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -36,7 +36,7 @@
-export([dmonitor_node/3]).
-export([delay_trap/2]).
-export([set_cookie/1, set_cookie/2, get_cookie/0, get_cookie/1]).
--export([nodes/0]).
+-export([nodes/0, nodes/1, nodes/2]).
-export([integer_to_list/2]).
-export([integer_to_binary/2]).
@@ -92,8 +92,8 @@
-type integer() :: integer().
-type iodata() :: iolist() | binary().
-type iolist() :: maybe_improper_list(byte() | binary() | iolist(), binary() | []).
--type list() :: list().
--type list(ContentType) :: list(ContentType).
+-type list() :: [any()].
+-type list(ContentType) :: [ContentType].
-type map() :: #{ any() => any() }.
-type maybe_improper_list() :: maybe_improper_list(any(), any()).
-type maybe_improper_list(ContentType, TerminationType) :: maybe_improper_list(ContentType, TerminationType).
@@ -187,6 +187,9 @@
-type iovec() :: [binary()].
-export_type([iovec/0]).
+%% Type for the destination of sends.
+-export_type([send_destination/0]).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Native code BIF stubs and their types
%% (BIF's actually implemented in this module goes last in the file)
@@ -266,7 +269,7 @@
is_list/1, is_map/1, is_number/1, is_pid/1, is_port/1, is_record/2,
is_record/3, is_reference/1, is_tuple/1, load_module/2,
load_nif/2, localtime_to_universaltime/2, make_fun/3,
- make_tuple/2, make_tuple/3, nodes/1, open_port/2,
+ make_tuple/2, make_tuple/3, open_port/2,
port_call/2, port_call/3, port_info/1, port_info/2, process_flag/2,
process_info/2, send/2, send/3, seq_trace_info/1,
setelement/3,
@@ -1004,7 +1007,8 @@ float_to_binary(_Float) ->
Options :: [Option],
Option :: {decimals, Decimals :: 0..253} |
{scientific, Decimals :: 0..249} |
- compact.
+ compact |
+ short.
float_to_binary(_Float, _Options) ->
erlang:nif_error(undefined).
@@ -1020,7 +1024,8 @@ float_to_list(_Float) ->
Options :: [Option],
Option :: {decimals, Decimals :: 0..253} |
{scientific, Decimals :: 0..249} |
- compact.
+ compact |
+ short.
float_to_list(_Float, _Options) ->
erlang:nif_error(undefined).
@@ -1274,7 +1279,7 @@ iolist_to_iovec(_IoListOrBinary) ->
%% is_alive/0
-spec is_alive() -> boolean().
is_alive() ->
- erlang:nif_error(undefined).
+ erlang:node() =/= nonode@nohost orelse erts_internal:dynamic_node_name().
%% is_builtin/3
-spec erlang:is_builtin(Module, Function, Arity) -> boolean() when
@@ -1794,6 +1799,7 @@ put(_Key, _Val) ->
erlang:nif_error(undefined).
%% raise/3
+%% Shadowed by erl_bif_types: erlang:raise/3
-spec erlang:raise(Class, Reason, Stacktrace) -> 'badarg' when
Class :: 'error' | 'exit' | 'throw',
Reason :: term(),
@@ -1914,8 +1920,8 @@ setnode(_P1, _P2) ->
-spec erlang:setnode(Node, DistCtrlr, Opts) -> dist_handle() when
Node :: atom(),
DistCtrlr :: port() | pid(),
- Opts :: {integer(), integer(), pos_integer()}.
-setnode(Node, DistCtrlr, {_Flags, _Ver, _Creation} = Opts) ->
+ Opts :: {integer(), pos_integer()}.
+setnode(Node, DistCtrlr, {_Flags, _Creation} = Opts) ->
case case erts_internal:create_dist_channel(Node, DistCtrlr, Opts) of
{ok, DH} -> DH;
{message, Ref} -> receive {Ref, Res} -> Res end;
@@ -2307,18 +2313,30 @@ is_tuple(_Term) ->
-spec load_module(Module, Binary) -> {module, Module} | {error, Reason} when
Module :: module(),
Binary :: binary(),
- Reason :: badfile | not_purged | on_load.
+ Reason :: badfile | not_purged | on_load
+ | {features_not_allowed, [atom()]}.
load_module(Mod, Code) ->
try
- case erlang:prepare_loading(Mod, Code) of
- {error,_}=Error ->
- Error;
- Prep when erlang:is_reference(Prep) ->
- case erlang:finish_loading([Prep]) of
- ok ->
- {module,Mod};
- {Error,[Mod]} ->
- {error,Error}
+ Allowed =
+ case erlang:module_loaded(erl_features) of
+ true ->
+ erl_features:load_allowed(Code);
+ false -> ok
+ end,
+ case Allowed of
+ {not_allowed, NotEnabled} ->
+ {error, {features_not_allowed, NotEnabled}};
+ ok ->
+ case erlang:prepare_loading(Mod, Code) of
+ {error,_}=Error ->
+ Error;
+ Prep when erlang:is_reference(Prep) ->
+ case erlang:finish_loading([Prep]) of
+ ok ->
+ {module,Mod};
+ {Error,[Mod]} ->
+ {error,Error}
+ end
end
end
catch
@@ -2366,13 +2384,6 @@ make_tuple(_Arity,_InitialValue) ->
make_tuple(_Arity,_DefaultValue,_InitList) ->
erlang:nif_error(undefined).
--spec nodes(Arg) -> Nodes when
- Arg :: NodeType | [NodeType],
- NodeType :: visible | hidden | connected | this | known,
- Nodes :: [node()].
-nodes(_Arg) ->
- erlang:nif_error(undefined).
-
-spec open_port(PortName, PortSettings) -> port() when
PortName :: {spawn, Command :: string() | binary()} |
{spawn_driver, Command :: string() | binary()} |
@@ -2414,7 +2425,10 @@ open_port(PortName, PortSettings) ->
-type message_queue_data() ::
off_heap | on_heap.
--spec process_flag(trap_exit, Boolean) -> OldBoolean when
+-spec process_flag(async_dist, Boolean) -> OldBoolean when
+ Boolean :: boolean(),
+ OldBoolean :: boolean();
+ (trap_exit, Boolean) -> OldBoolean when
Boolean :: boolean(),
OldBoolean :: boolean();
(error_handler, Module) -> OldModule when
@@ -2452,6 +2466,7 @@ process_flag(_Flag, _Value) ->
erlang:nif_error(undefined).
-type process_info_item() ::
+ async_dist |
backtrace |
binary |
catchlevel |
@@ -2475,6 +2490,7 @@ process_flag(_Flag, _Value) ->
monitored_by |
monitors |
message_queue_data |
+ parent |
priority |
reductions |
registered_name |
@@ -2487,6 +2503,7 @@ process_flag(_Flag, _Value) ->
trap_exit.
-type process_info_result_item() ::
+ {async_dist, Enabled :: boolean()} |
{backtrace, Bin :: binary()} |
{binary, BinInfo :: [{non_neg_integer(),
non_neg_integer(),
@@ -2519,6 +2536,7 @@ process_flag(_Flag, _Value) ->
Monitors :: [{process | port, Pid :: pid() | port() |
{RegName :: atom(), Node :: node()}}]} |
{message_queue_data, MQD :: message_queue_data()} |
+ {parent, pid() | undefined} |
{priority, Level :: priority_level()} |
{reductions, Number :: non_neg_integer()} |
{registered_name, [] | (Atom :: atom())} |
@@ -2555,13 +2573,13 @@ process_info(_Pid,_ItemSpec) ->
erlang:nif_error(undefined).
-spec erlang:send(Dest, Msg) -> Msg when
- Dest :: dst(),
+ Dest :: send_destination(),
Msg :: term().
send(_Dest,_Msg) ->
erlang:nif_error(undefined).
-spec erlang:send(Dest, Msg, Options) -> Res when
- Dest :: dst(),
+ Dest :: send_destination(),
Msg :: term(),
Options :: [nosuspend | noconnect],
Res :: ok | nosuspend | noconnect.
@@ -2868,8 +2886,8 @@ tuple_to_list(_Tuple) ->
(dirty_io_schedulers) -> non_neg_integer();
(dist) -> binary();
(dist_buf_busy_limit) -> non_neg_integer();
- (dist_ctrl) -> {Node :: node(),
- ControllingEntity :: port() | pid()};
+ (dist_ctrl) -> [{Node :: node(),
+ ControllingEntity :: port() | pid()}];
(driver_version) -> string();
(dynamic_trace) -> none | dtrace | systemtap;
(dynamic_trace_probes) -> boolean();
@@ -2936,6 +2954,7 @@ tuple_to_list(_Tuple) ->
(update_cpu_info) -> changed | unchanged;
(version) -> string();
(wordsize | {wordsize, internal} | {wordsize, external}) -> 4 | 8;
+ (async_dist) -> boolean();
(overview) -> boolean();
%% Deliberately left undocumented
(sequential_tracer) -> {sequential_tracer, pid() | port() | {module(),term()} | false}.
@@ -3065,7 +3084,8 @@ spawn_monitor(M, F, A) ->
| {min_heap_size, Size :: non_neg_integer()}
| {min_bin_vheap_size, VSize :: non_neg_integer()}
| {max_heap_size, Size :: max_heap_size()}
- | {message_queue_data, MQD :: message_queue_data()}.
+ | {message_queue_data, MQD :: message_queue_data()}
+ | {async_dist, Enabled :: boolean()}.
-spec spawn_opt(Fun, Options) -> pid() | {pid(), reference()} when
Fun :: function(),
@@ -3247,68 +3267,20 @@ spawn_opt(N, M, F, A, O) when erlang:is_atom(N),
end;
{spawn_reply, Ref, error, badopt} ->
badarg_with_cause([N, M, F, A, O], badopt);
- {spawn_reply, Ref, error, noconnection} ->
- try
+ {spawn_reply, Ref, error, Err0} when Err0 == noconnection;
+ Err0 == notsup ->
+ try
erlang:spawn_opt(erts_internal,crasher,
- [N,M,F,A,O,noconnection], O)
+ [N,M,F,A,O,Err0], O)
catch
_:Err1 ->
error_with_info(Err1, [N, M, F, A, O])
end;
- {spawn_reply, Ref, error, notsup} ->
- case old_remote_spawn_opt(N, M, F, A, O) of
- Pid when erlang:is_pid(Pid) ->
- Pid;
- Err2 ->
- error_with_info(Err2, [N, M, F, A, O])
- end;
- {spawn_reply, Ref, error, Err3} ->
- error_with_info(Err3, [N, M, F, A, O])
+ {spawn_reply, Ref, error, Err2} ->
+ error_with_info(Err2, [N, M, F, A, O])
end;
spawn_opt(N,M,F,A,O) ->
badarg_with_info([N,M,F,A,O]).
-
-old_remote_spawn_opt(N, M, F, A, O) ->
- case lists:member(monitor, O) of
- true ->
- badarg;
- _ ->
- {L,NO} = lists:foldl(fun (link, {_, NewOpts}) ->
- {link, NewOpts};
- (Opt, {LO, NewOpts}) ->
- {LO, [Opt|NewOpts]}
- end,
- {no_link,[]},
- O),
- case catch gen_server:call({net_kernel,N},
- {spawn_opt,M,F,A,NO,L,erlang:group_leader()},
- infinity) of
- Pid when erlang:is_pid(Pid) ->
- Pid;
- Error ->
- case remote_spawn_error(Error, {L, N, M, F, A, NO}) of
- {fault, Fault} ->
- Fault;
- Pid ->
- Pid
- end
- end
- end.
-
-remote_spawn_error({'EXIT', {{nodedown,N}, _}}, {L, N, M, F, A, O}) ->
- {Opts, LL} = case L =:= link of
- true ->
- {[link|O], [link]};
- false ->
- {O, []}
- end,
- erlang:spawn_opt(erts_internal,crasher,[N,M,F,A,Opts,noconnection], LL);
-remote_spawn_error({'EXIT', {Reason, _}}, _) ->
- {fault, Reason};
-remote_spawn_error({'EXIT', Reason}, _) ->
- {fault, Reason};
-remote_spawn_error(Other, _) ->
- {fault, Other}.
%%
%% spawn_request/1
@@ -3495,7 +3467,28 @@ yield() ->
-spec nodes() -> Nodes when
Nodes :: [node()].
nodes() ->
- erlang:nodes(visible).
+ erlang:nif_error(undefined).
+
+-spec nodes(Arg) -> Nodes when
+ Arg :: NodeType | [NodeType],
+ NodeType :: visible | hidden | connected | this | known,
+ Nodes :: [node()].
+nodes(_Arg) ->
+ erlang:nif_error(undefined).
+
+-spec nodes(Arg, InfoOpts) -> [NodeInfo] when
+ NodeType :: visible | hidden | connected | this | known,
+ Arg :: NodeType | [NodeType],
+ InfoOpts :: #{connection_id => boolean(),
+ node_type => boolean()},
+ NodeTypeInfo :: visible | hidden | this | known,
+ ConnectionId :: undefined | integer(),
+ Info :: #{connection_id => ConnectionId,
+ node_type => NodeTypeInfo},
+ NodeInfo :: {node(), Info}.
+
+nodes(_Args, _Opts) ->
+ erlang:nif_error(undefined).
-spec disconnect_node(Node) -> boolean() | ignored when
Node :: node().
@@ -3520,14 +3513,14 @@ fun_info_1([K|Ks], Fun, A) ->
end;
fun_info_1([], _, A) -> A.
--type dst() :: pid()
- | reference()
- | port()
- | (RegName :: atom())
- | {RegName :: atom(), Node :: node()}.
+-type send_destination() :: pid()
+ | reference()
+ | port()
+ | (RegName :: atom())
+ | {RegName :: atom(), Node :: node()}.
-spec erlang:send_nosuspend(Dest, Msg) -> boolean() when
- Dest :: dst(),
+ Dest :: send_destination(),
Msg :: term().
send_nosuspend(Pid, Msg) ->
try
@@ -3537,7 +3530,7 @@ send_nosuspend(Pid, Msg) ->
end.
-spec erlang:send_nosuspend(Dest, Msg, Options) -> boolean() when
- Dest :: dst(),
+ Dest :: send_destination(),
Msg :: term(),
Options :: [noconnect].
send_nosuspend(Pid, Msg, Opts) ->
@@ -4032,6 +4025,7 @@ rvrs(Xs) -> rvrs(Xs, []).
rvrs([],Ys) -> Ys;
rvrs([X|Xs],Ys) -> rvrs(Xs, [X|Ys]).
+%% Shadowed by erl_bif_types: erlang:min/2
-spec min(Term1, Term2) -> Minimum when
Term1 :: term(),
Term2 :: term(),
@@ -4039,6 +4033,7 @@ rvrs([X|Xs],Ys) -> rvrs(Xs, [X|Ys]).
min(A, B) when A > B -> B;
min(A, _) -> A.
+%% Shadowed by erl_bif_types: erlang:max/2
-spec max(Term1, Term2) -> Maximum when
Term1 :: term(),
Term2 :: term(),
@@ -4459,7 +4454,7 @@ gc_info(Ref, N, {OrigColls,OrigRecl}) ->
'not'(_A) ->
erlang:nif_error(undefined).
--spec erlang:'!'(dst(), term()) -> term().
+-spec erlang:'!'(send_destination(), term()) -> term().
'!'(_Dst, _Msg) ->
erlang:nif_error(undefined).
diff --git a/erts/preloaded/src/erts.app.src b/erts/preloaded/src/erts.app.src
index 94fd77b80d..4b0d0ae2d7 100644
--- a/erts/preloaded/src/erts.app.src
+++ b/erts/preloaded/src/erts.app.src
@@ -42,7 +42,7 @@
{registered, []},
{applications, []},
{env, []},
- {runtime_dependencies, ["stdlib-3.13", "kernel-8.3", "sasl-3.3"]}
+ {runtime_dependencies, ["stdlib-4.1", "kernel-8.5", "sasl-3.3"]}
]}.
%% vim: ft=erlang
diff --git a/erts/preloaded/src/erts_code_purger.erl b/erts/preloaded/src/erts_code_purger.erl
index 9f6bd6e289..120466bc6f 100644
--- a/erts/preloaded/src/erts_code_purger.erl
+++ b/erts/preloaded/src/erts_code_purger.erl
@@ -411,7 +411,7 @@ do_test_hard_purge(Mod, From, Ref, Reqs) ->
end.
test_progress(_State, _From, _Ref, died) ->
- %% Test process died; continue so we wont
+ %% Test process died; continue so we won't
%% leave the system in an inconsistent
%% state...
died;
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index c7716e2740..2aa8739388 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -116,6 +116,8 @@
-export([no_aux_work_threads/0]).
+-export([dynamic_node_name/0, dynamic_node_name/1]).
+
%%
%% Await result of send to port
%%
@@ -742,11 +744,10 @@ process_display(_Pid, _Type) ->
process_flag(_Pid, _Flag, _Value) ->
erlang:nif_error(undefined).
--spec create_dist_channel(Node, DistCtrlr, {Flags, Ver, Cr}) -> Result when
+-spec create_dist_channel(Node, DistCtrlr, {Flags, Cr}) -> Result when
Node :: atom(),
DistCtrlr :: port() | pid(),
Flags :: integer(),
- Ver :: integer(),
Cr :: pos_integer(),
Result :: {'ok', erlang:dist_handle()}
| {'message', reference()}
@@ -797,7 +798,7 @@ spawn_system_process(_Mod, _Func, _Args) ->
%%
-spec ets_lookup_binary_info(Tab, Key) -> BinInfo when
- Tab :: ets:tab(),
+ Tab :: ets:table(),
Key :: term(),
BinInfo :: [{non_neg_integer(), non_neg_integer(), non_neg_integer()}].
@@ -811,20 +812,20 @@ ets_super_user(_Bool) ->
erlang:nif_error(undef).
-spec ets_raw_first(Tab) -> term() when
- Tab :: ets:tab().
+ Tab :: ets:table().
ets_raw_first(_Tab) ->
erlang:nif_error(undef).
-spec ets_raw_next(Tab, Key) -> term() when
- Tab :: ets:tab(),
+ Tab :: ets:table(),
Key :: term().
ets_raw_next(_Tab, _Key) ->
erlang:nif_error(undef).
-spec ets_info_binary(Tab) -> BinInfo when
- Tab :: ets:tab(),
+ Tab :: ets:table(),
BinInfo :: [{non_neg_integer(), non_neg_integer(), non_neg_integer()}].
ets_info_binary(Tab) ->
@@ -979,3 +980,27 @@ beamfile_module_md5(_Bin) ->
no_aux_work_threads() ->
erlang:nif_error(undefined).
+
+%%
+%% Is dynamic node name enabled?
+%%
+-spec dynamic_node_name() -> boolean().
+
+dynamic_node_name() ->
+ case persistent_term:get({?MODULE, dynamic_node_name}, false) of
+ false -> false;
+ _ -> true
+ end.
+
+%%
+%% Save whether dynamic node name is enabled or not.
+%%
+-spec dynamic_node_name(boolean()) -> ok.
+
+dynamic_node_name(true) ->
+ persistent_term:put({?MODULE, dynamic_node_name}, true);
+dynamic_node_name(false) ->
+ case dynamic_node_name() of
+ false -> ok;
+ _ -> _ = persistent_term:erase({?MODULE, dynamic_node_name}), ok
+ end.
diff --git a/erts/preloaded/src/erts_literal_area_collector.erl b/erts/preloaded/src/erts_literal_area_collector.erl
index 8a73ed1685..bb2ad6b919 100644
--- a/erts/preloaded/src/erts_literal_area_collector.erl
+++ b/erts/preloaded/src/erts_literal_area_collector.erl
@@ -62,39 +62,46 @@ msg_loop(Area, {Ongoing, NeedIReq} = OReqInfo, GcOutstnd, NeedGC) ->
switch_area();
%% Process (_Pid) has completed the request...
- {copy_literals, {Area, _GcAllowed, _Pid}, ok} when Ongoing == 1,
- NeedIReq == [] ->
+ {copy_literals, {Area, _ReqType, _Pid}, ok} when Ongoing == 1,
+ NeedIReq == [] ->
switch_area(); %% Last process completed...
- {copy_literals, {Area, false, _Pid}, ok} ->
+ {copy_literals, {Area, init, _Pid}, ok} ->
msg_loop(Area, check_send_copy_req(Area, Ongoing-1, NeedIReq),
GcOutstnd, NeedGC);
- {copy_literals, {Area, true, _Pid}, ok} when NeedGC == [] ->
+ {copy_literals, {Area, ReqType, _Pid}, ok} when NeedGC == [],
+ ReqType /= init ->
msg_loop(Area, check_send_copy_req(Area, Ongoing-1, NeedIReq),
GcOutstnd-1, []);
- {copy_literals, {Area, true, _Pid}, ok} ->
- send_copy_req(hd(NeedGC), Area, true),
- msg_loop(Area, {Ongoing-1, NeedIReq}, GcOutstnd, tl(NeedGC));
+ {copy_literals, {Area, ReqType, _Pid}, ok} when ReqType /= init ->
+ [{GCPid,GCWork} | NewNeedGC] = NeedGC,
+ send_copy_req(GCPid, Area, GCWork),
+ msg_loop(Area, {Ongoing-1, NeedIReq}, GcOutstnd, NewNeedGC);
%% Process (Pid) failed to complete the request
%% since it needs to garbage collect in order to
%% complete the request...
- {copy_literals, {Area, false, Pid}, need_gc} when GcOutstnd < ?MAX_GC_OUTSTND ->
- send_copy_req(Pid, Area, true),
+ {copy_literals, {Area, init, Pid}, GCWork} when GcOutstnd
+ < ?MAX_GC_OUTSTND ->
+ send_copy_req(Pid, Area, GCWork),
msg_loop(Area, OReqInfo, GcOutstnd+1, NeedGC);
- {copy_literals, {Area, false, Pid}, need_gc} ->
+ {copy_literals, {Area, init, Pid}, GCWork} ->
msg_loop(Area, check_send_copy_req(Area, Ongoing, NeedIReq),
- GcOutstnd, [Pid|NeedGC]);
+ GcOutstnd, [{Pid,GCWork} | NeedGC]);
%% Not handled message regarding the area that we
%% currently are working with. Crash the VM so
%% we notice this bug...
- {copy_literals, {Area, _, _}, _} = Msg when erlang:is_reference(Area) ->
+ {copy_literals, {Area, _, _}, _} = Msg ->
exit({not_handled_message, Msg});
{change_prio, From, Ref, Prio} ->
change_prio(From, Ref, Prio),
msg_loop(Area, OReqInfo, GcOutstnd, NeedGC);
+ {get_status, Ref, From} when is_pid(From); is_reference(From) ->
+ From ! {Ref, if Ongoing == 0 -> idle; true -> working end},
+ msg_loop(Area, OReqInfo, GcOutstnd, NeedGC);
+
%% Unexpected garbage message. Get rid of it...
_Ignore ->
msg_loop(Area, OReqInfo, GcOutstnd, NeedGC)
@@ -126,7 +133,7 @@ switch_area() ->
check_send_copy_req(_Area, Ongoing, []) ->
{Ongoing, []};
check_send_copy_req(Area, Ongoing, [Pid|Pids]) ->
- send_copy_req(Pid, Area, false),
+ send_copy_req(Pid, Area, init),
{Ongoing+1, Pids}.
send_copy_reqs(Ps, Area, OReqLim) ->
@@ -137,23 +144,23 @@ send_copy_reqs([], _Area, _OReqLim, N) ->
send_copy_reqs(Ps, _Area, OReqLim, N) when N >= OReqLim ->
{N, Ps};
send_copy_reqs([P|Ps], Area, OReqLim, N) ->
- send_copy_req(P, Area, false),
+ send_copy_req(P, Area, init),
send_copy_reqs(Ps, Area, OReqLim, N+1).
-send_copy_req(P, Area, GC) ->
- erts_literal_area_collector:send_copy_request(P, Area, GC).
+send_copy_req(P, Area, How) ->
+ erts_literal_area_collector:send_copy_request(P, Area, How).
-spec release_area_switch() -> boolean().
release_area_switch() ->
erlang:nif_error(undef). %% Implemented in beam_bif_load.c
--spec send_copy_request(To, AreaId, GcAllowed) -> 'ok' when
+-spec send_copy_request(To, AreaId, How) -> 'ok' when
To :: pid(),
AreaId :: term(),
- GcAllowed :: boolean().
+ How :: 'init' | 'check_gc' | 'need_gc'.
-send_copy_request(_To, _AreaId, _GcAllowed) ->
+send_copy_request(_To, _AreaId, _How) ->
erlang:nif_error(undef). %% Implemented in beam_bif_load.c
change_prio(From, Ref, Prio) ->
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 784696e834..5ea349511d 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -591,7 +591,7 @@ set_flag(_Flag,false,Flags) ->
{ok,Flags};
set_flag(Flag,Value,Flags) when is_list(Value) ->
%% The flag here can be -boot or -config, which means the value is
- %% a file name! Thus the file name encoding is used when coverting.
+ %% a file name! Thus the file name encoding is used when converting.
Encoding = file:native_name_encoding(),
case catch unicode:characters_to_binary(Value,Encoding,Encoding) of
{'EXIT',_} ->
@@ -889,6 +889,7 @@ do_boot(Flags,Start) ->
do_boot(Init,Flags,Start) ->
process_flag(trap_exit,true),
Root = get_root(Flags),
+ true = check_bindir(Flags),
Path = get_flag_list(path, Flags, false),
{Pa,Pz} = PathFls = path_flags(Flags),
start_prim_loader(Init, bs2ss(Path), PathFls),
@@ -923,6 +924,14 @@ get_root(Flags) ->
exit(no_or_multiple_root_variables)
end.
+check_bindir(Flags) ->
+ case get_argument(bindir, Flags) of
+ {ok,[[_Bindir]]} ->
+ true;
+ _ ->
+ exit(no_or_multiple_bindir_variables)
+ end.
+
get_boot_vars(Root, Flags) ->
BootVars = get_boot_vars_1(#{}, Flags),
RootKey = <<"ROOT">>,
@@ -1552,6 +1561,8 @@ collect_mfas([MFA|MFAs],Info) ->
collect_mfas(MFAs,Info);
{call_time, false} ->
collect_mfas(MFAs,Info);
+ {call_time, undefined} ->
+ collect_mfas(MFAs,Info);
{call_time, Data} ->
case collect_mfa(MFA,Data,0,0) of
{{0,_},_} ->
diff --git a/erts/preloaded/src/prim_buffer.erl b/erts/preloaded/src/prim_buffer.erl
index e0d35a6792..7ee2975333 100644
--- a/erts/preloaded/src/prim_buffer.erl
+++ b/erts/preloaded/src/prim_buffer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,9 @@
-export([try_lock/1, unlock/1]).
+-nifs([new/0, size/1, peek_head/1, copying_read/2, write/2, skip/2,
+ find_byte_index/2, try_lock/1, unlock/1]).
+
-type prim_buffer() :: term().
%% Controls when to copy rather than extract sub-binaries from the buffer,
@@ -106,7 +109,7 @@ skip(_Buffer, _Size) ->
wipe(Buffer) ->
skip(Buffer, prim_buffer:size(Buffer)).
-%% Finds the start-index of the first occurence of Needle, for implementing
+%% Finds the start-index of the first occurrence of Needle, for implementing
%% read_line and similar.
-spec find_byte_index(Buffer, Needle) -> Result when
Buffer :: prim_buffer(),
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 4c588b9ca5..3538b4fbba 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,6 +64,17 @@
internal_normalize_utf8/1,
is_translatable/1]).
+-nifs([open_nif/2, close_nif/1, read_nif/2, write_nif/2, pread_nif/3,
+ pwrite_nif/3, seek_nif/3, sync_nif/2, truncate_nif/1, allocate_nif/3,
+ advise_nif/4, read_handle_info_nif/1,
+ make_hard_link_nif/2, make_soft_link_nif/2, rename_nif/2,
+ read_info_nif/2, set_permissions_nif/2, set_owner_nif/3, set_time_nif/4,
+ read_link_nif/1, list_dir_nif/1, make_dir_nif/1, del_file_nif/1,
+ del_dir_nif/1, get_device_cwd_nif/1, set_cwd_nif/1, get_cwd_nif/0,
+ ipread_s32bu_p32bu_nif/3, read_file_nif/1,
+ get_handle_nif/1, delayed_close_nif/1, altname_nif/1,
+ file_desc_to_ref_nif/1]).
+
-type prim_file_name() :: string() | unicode:unicode_binary().
-type prim_file_name_error() :: 'error' | 'ignore' | 'warning'.
diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl
index ff083d9fc1..c6274f89d6 100644
--- a/erts/preloaded/src/prim_inet.erl
+++ b/erts/preloaded/src/prim_inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
-export([open/3, open/4, fdopen/4, fdopen/5, close/1]).
-export([bind/3, listen/1, listen/2, peeloff/2]).
--export([connect/3, connect/4, async_connect/4]).
+-export([connect/3, connect/4, async_connect/4, connectx/2, connectx/3]).
-export([accept/1, accept/2, accept/3, async_accept/2]).
-export([shutdown/2]).
-export([send/2, send/3, sendto/4, sendmsg/3, sendfile/4]).
@@ -332,7 +332,7 @@ bindx_check_addrs([Addr|Addrs]) ->
bindx_check_addrs([]) ->
true.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% CONNECT(insock(), IP, Port [,Timeout]) -> ok | {error, Reason}
%%
@@ -411,6 +411,41 @@ async_connect0(S, Addr, Time) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
+%% CONNECTX(insock(), IPs, Port) -> {ok, AssocId} | {error, Reason}
+%% CONNECTX(insock(), SockAddrs) -> {ok, AssocId} | {error, Reason}
+%%
+%% For SCTP sockets only
+%%
+%% connect the insock() to the addresses given by IPs and Port or SockAddrs
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+connectx(S, IPs, Port) ->
+ connectx(S, {IPs, Port}).
+
+connectx(S, AddrList) ->
+ case type_value(set, addr_list, AddrList) of
+ true ->
+ connectx0(S, AddrList);
+ false ->
+ {error, einval}
+ end.
+
+
+connectx0(S, Addrs) ->
+ Args = [enc_time(-1),enc_value(set, addr_list, Addrs)],
+ case ctl_cmd(S, ?INET_REQ_CONNECT, Args) of
+ {ok, [R1,R0]} ->
+ Ref = ?u16(R1,R0),
+ receive
+ {inet_async, S, Ref, Status} ->
+ Status
+ end;
+ Error ->
+ Error
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
%% ACCEPT(insock() [,Timeout][,FamilyOpts] ) -> {ok,insock()} | {error, Reason}
%%
%% accept incoming connection on listen socket
@@ -1521,6 +1556,7 @@ enc_opt(show_econnreset) -> ?INET_LOPT_TCP_SHOW_ECONNRESET;
enc_opt(line_delimiter) -> ?INET_LOPT_LINE_DELIM;
enc_opt(raw) -> ?INET_OPT_RAW;
enc_opt(bind_to_device) -> ?INET_OPT_BIND_TO_DEVICE;
+enc_opt(debug) -> ?INET_OPT_DEBUG;
% Names of SCTP opts:
enc_opt(sctp_rtoinfo) -> ?SCTP_OPT_RTOINFO;
enc_opt(sctp_associnfo) -> ?SCTP_OPT_ASSOCINFO;
@@ -1588,6 +1624,7 @@ dec_opt(?INET_LOPT_TCP_SHOW_ECONNRESET) -> show_econnreset;
dec_opt(?INET_LOPT_LINE_DELIM) -> line_delimiter;
dec_opt(?INET_OPT_RAW) -> raw;
dec_opt(?INET_OPT_BIND_TO_DEVICE) -> bind_to_device;
+dec_opt(?INET_OPT_DEBUG) -> debug;
dec_opt(I) when is_integer(I) -> undefined.
@@ -1605,7 +1642,7 @@ dec_opt(I) when is_integer(I) -> undefined.
%% The use of [] and [[Type,Default]] is commented out in enc_value/2
%% and type_value/2 below since they are only used in record fields.
%% And record fields does not call enc_value/2 nor type_value/2.
-%% Anyone introducing these metatypes otherwhere will have to activate
+%% Anyone introducing these metatypes elsewhere will have to activate
%% those clauses in enc_value/2 and type_value/2. You have been warned!
type_opt(get, raw) -> [{[int],[int],[binary_or_uint]}];
@@ -1647,9 +1684,9 @@ type_opt_1(ipv6_v6only) -> bool;
%% multicast
type_opt_1(multicast_ttl) -> int;
type_opt_1(multicast_loop) -> bool;
-type_opt_1(multicast_if) -> ip;
-type_opt_1(add_membership) -> {ip,ip};
-type_opt_1(drop_membership) -> {ip,ip};
+type_opt_1(multicast_if) -> mif;
+type_opt_1(add_membership) -> membership;
+type_opt_1(drop_membership) -> membership;
%% driver options
type_opt_1(header) -> uint;
type_opt_1(buffer) -> int;
@@ -1696,6 +1733,7 @@ type_opt_1(read_packets) -> uint;
type_opt_1(netns) -> binary;
type_opt_1(show_econnreset) -> bool;
type_opt_1(bind_to_device) -> binary;
+type_opt_1(debug) -> bool;
%%
%% SCTP options (to be set). If the type is a record type, the corresponding
%% record signature is returned, otherwise, an "elementary" type tag
@@ -1883,7 +1921,23 @@ type_value_2(uint16, X) when X band 16#ffff =:= X -> true;
type_value_2(uint8, X) when X band 16#ff =:= X -> true;
type_value_2(time, infinity) -> true;
type_value_2(time, X) when is_integer(X), X >= 0 -> true;
-type_value_2(ip,{A,B,C,D}) when ?ip(A,B,C,D) -> true;
+%% type_value_2(ip,{A,B,C,D}) when ?ip(A,B,C,D) -> true;
+type_value_2(mif,{A,B,C,D}) when ?ip(A,B,C,D) -> true;
+type_value_2(mif,Idx) when is_integer(Idx) -> true;
+type_value_2(membership,{{A1,B1,C1,D1}, {A2,B2,C2,D2}})
+ when ?ip(A1,B1,C1,D1) andalso ?ip(A2,B2,C2,D2) -> true;
+type_value_2(membership,{{A1,B1,C1,D1}, any})
+ when ?ip(A1,B1,C1,D1) -> true;
+type_value_2(membership,{{A1,B1,C1,D1}, {A2,B2,C2,D2}, Idx})
+ when ?ip(A1,B1,C1,D1) andalso
+ ?ip(A2,B2,C2,D2) andalso
+ is_integer(Idx) -> true;
+type_value_2(membership,{{A1,B1,C1,D1}, any, Idx})
+ when ?ip(A1,B1,C1,D1) andalso
+ is_integer(Idx) -> true;
+type_value_2(membership,{{A,B,C,D,E,F,G,H}, Idx})
+ when ?ip6(A,B,C,D,E,F,G,H) andalso
+ is_integer(Idx) -> true;
%%
type_value_2(addr, {any,Port}) ->
type_value_2(uint16, Port);
@@ -1907,15 +1961,19 @@ type_value_2(addr, {inet6,{{A,B,C,D,E,F,G,H},Port}})
when ?ip6(A,B,C,D,E,F,G,H) ->
type_value_2(uint16, Port);
type_value_2(addr, #{family := inet,
- addr := {A,B,C,D},
- port := Port})
- when ?ip(A,B,C,D) ->
- type_value_2(uint16, Port);
+ addr := Addr,
+ port := Port}) ->
+ (Addr =:= any orelse
+ Addr =:= loopback orelse
+ ?ip(Addr))
+ andalso type_value_2(uint16, Port);
type_value_2(addr, #{family := inet6,
- addr := {A,B,C,D,E,F,G,H},
- port := Port})
- when ?ip6(A,B,C,D,E,F,G,H) ->
- type_value_2(uint16, Port);
+ addr := Addr,
+ port := Port}) ->
+ (Addr =:= any orelse
+ Addr =:= loopback orelse
+ ?ip6(Addr))
+ andalso type_value_2(uint16, Port);
type_value_2(addr, {local,Addr}) ->
if
is_binary(Addr) ->
@@ -1936,6 +1994,16 @@ type_value_2(addr, {local,Addr}) ->
false
end
end;
+type_value_2(addr_list, [_|_]=SockAddrs)
+ when length(SockAddrs) =< 255 ->
+ lists:all(fun(SockAddr) -> type_value_2(addr, SockAddr) end, SockAddrs);
+type_value_2(addr_list, {[_|_] = IPs, Port})
+ when length(IPs) =< 255 ->
+ lists:all(fun({A,B,C,D}) when ?ip(A,B,C,D) -> true;
+ ({A,B,C,D,E,F,G,H}) when ?ip6(A,B,C,D,E,F,G,H) -> true;
+ (_) -> false
+ end, IPs)
+ andalso type_value_2(uint16, Port);
%%
type_value_2(ether,[X1,X2,X3,X4,X5,X6])
when ?ether(X1,X2,X3,X4,X5,X6) -> true;
@@ -2029,21 +2097,58 @@ enc_value_tuple(_, _, _, _) -> [].
%%
%% Encoding of option VALUES:
%%
-enc_value_2(bool, true) -> [0,0,0,1];
-enc_value_2(bool, false) -> [0,0,0,0];
-enc_value_2(bool8, true) -> [1];
-enc_value_2(bool8, false) -> [0];
-enc_value_2(int, Val) -> ?int32(Val);
-enc_value_2(uint, Val) -> ?int32(Val);
-enc_value_2(uint32, Val) -> ?int32(Val);
-enc_value_2(uint24, Val) -> ?int24(Val);
-enc_value_2(uint16, Val) -> ?int16(Val);
-enc_value_2(uint8, Val) -> ?int8(Val);
-enc_value_2(time, infinity) -> ?int32(-1);
-enc_value_2(time, Val) -> ?int32(Val);
-enc_value_2(ip,{A,B,C,D}) -> [A,B,C,D];
-enc_value_2(ip, any) -> [0,0,0,0];
-enc_value_2(ip, loopback) -> [127,0,0,1];
+enc_value_2(bool, true) -> [0,0,0,1];
+enc_value_2(bool, false) -> [0,0,0,0];
+enc_value_2(bool8, true) -> [1];
+enc_value_2(bool8, false) -> [0];
+enc_value_2(int, Val) -> ?int32(Val);
+enc_value_2(uint, Val) -> ?int32(Val);
+enc_value_2(uint32, Val) -> ?int32(Val);
+enc_value_2(uint24, Val) -> ?int24(Val);
+enc_value_2(uint16, Val) -> ?int16(Val);
+enc_value_2(uint8, Val) -> ?int8(Val);
+enc_value_2(time, infinity) -> ?int32(-1);
+enc_value_2(time, Val) -> ?int32(Val);
+%% enc_value_2(ip, IP)
+%% when (tuple_size(IP) =:= 4) -> ip4_to_bytes(IP);
+%% enc_value_2(ip, any) -> ip4_any();
+%% enc_value_2(ip, loopback) -> ip4_loopback();
+enc_value_2(mif, IP)
+ when (tuple_size(IP) =:= 4) -> ip4_to_bytes(IP);
+enc_value_2(mif, Idx)
+ when is_integer(Idx) -> ?int32(Idx);
+enc_value_2(membership, {IP1, IP2})
+ when (tuple_size(IP1) =:= 4) andalso
+ (tuple_size(IP2) =:= 4) ->
+ enc_value_2(membership, {IP1, IP2, 0});
+enc_value_2(membership, {IP1, IP2})
+ when (tuple_size(IP1) =:= 4) andalso
+ (IP2 =:= any) ->
+ enc_value_2(membership, {IP1, IP2, 0});
+%% enc_value_2(membership, {IP1, any = _IP2})
+%% when (tuple_size(IP1) =:= 4) ->
+%% [?INET_AF_INET, ?int32(0), ip4_to_bytes(IP1), ip4_any()];
+enc_value_2(membership, {IP1, IP2, Idx})
+ when (tuple_size(IP1) =:= 4) andalso
+ (tuple_size(IP2) =:= 4) andalso
+ is_integer(Idx) ->
+ %% The reason for turning this thing around (the interface
+ %% before the two address'es) so that we as much as possible
+ %% "look like" IPv6...se below
+ [?int32(?INET_AF_INET), ?int32(Idx), ip4_to_bytes(IP1), ip4_to_bytes(IP2)];
+enc_value_2(membership, {IP1, any = _IP2, Idx})
+ when (tuple_size(IP1) =:= 4) andalso
+ is_integer(Idx) ->
+ [?int32(?INET_AF_INET), ?int32(Idx), ip4_to_bytes(IP1), ip4_any()];
+enc_value_2(membership, {IP, Idx})
+ when (tuple_size(IP) =:= 8) andalso
+ is_integer(Idx) ->
+ %% The reason for turning this thing around (the interface
+ %% before the address) is because of the inet-driver (it reads out a
+ %% 32-bit value for *all* options, so we might as well put a 32-bit
+ %% value "first".
+ [?int32(?INET_AF_INET6), ?int32(Idx), ip6_to_bytes(IP)];
+
%%
enc_value_2(addr, {any,Port}) ->
[?INET_AF_ANY|?int16(Port)];
@@ -2055,27 +2160,19 @@ enc_value_2(addr, {IP,Port}) when tuple_size(IP) =:= 8 ->
[?INET_AF_INET6,?int16(Port),ip6_to_bytes(IP),?int32(0),?int32(0)];
enc_value_2(addr, #{family := inet,
addr := IP,
- port := Port}) when (tuple_size(IP) =:= 4) ->
+ port := Port}) ->
[?INET_AF_INET,?int16(Port)|ip4_to_bytes(IP)];
enc_value_2(addr, #{family := inet6,
addr := IP,
port := Port,
flowinfo := FlowInfo,
- scope_id := ScopeID}) when (tuple_size(IP) =:= 8) ->
+ scope_id := ScopeID}) ->
[?INET_AF_INET6,?int16(Port),ip6_to_bytes(IP),?int32(FlowInfo),?int32(ScopeID)];
enc_value_2(addr, {File,_}) when is_list(File); is_binary(File) ->
[?INET_AF_LOCAL,iolist_size(File)|File];
%%
-enc_value_2(addr, {inet,{any,Port}}) ->
- [?INET_AF_INET,?int16(Port)|ip4_to_bytes({0,0,0,0})];
-enc_value_2(addr, {inet,{loopback,Port}}) ->
- [?INET_AF_INET,?int16(Port)|ip4_to_bytes({127,0,0,1})];
enc_value_2(addr, {inet,{IP,Port}}) ->
[?INET_AF_INET,?int16(Port)|ip4_to_bytes(IP)];
-enc_value_2(addr, {inet6,{any,Port}}) ->
- [?INET_AF_INET6,?int16(Port),ip6_to_bytes({0,0,0,0,0,0,0,0}),?int32(0),?int32(0)];
-enc_value_2(addr, {inet6,{loopback,Port}}) ->
- [?INET_AF_INET6,?int16(Port),ip6_to_bytes({0,0,0,0,0,0,0,1}),?int32(0),?int32(0)];
enc_value_2(addr, {inet6,{IP,Port}}) ->
[?INET_AF_INET6,?int16(Port),ip6_to_bytes(IP),?int32(0),?int32(0)];
enc_value_2(addr, {local,Addr}) ->
@@ -2091,6 +2188,12 @@ enc_value_2(addr, {local,Addr}) ->
Addr, file:native_name_encoding())
end,
[?INET_AF_LOCAL,byte_size(Bin),Bin];
+enc_value_2(addr_list, {IPs, Port}) ->
+ [?INET_AF_LIST, length(IPs) |
+ [enc_value_2(addr, {IP, Port}) || IP <- IPs]];
+enc_value_2(addr_list, SockAddrs) ->
+ [?INET_AF_LIST, length(SockAddrs) |
+ [enc_value_2(addr, SockAddr) || SockAddr <- SockAddrs]];
%%
enc_value_2(ether, [_,_,_,_,_,_]=Xs) -> Xs;
enc_value_2(sockaddr, any) ->
@@ -2125,7 +2228,7 @@ enc_value_2(binary_or_uint,Datum) when is_integer(Datum) ->
%%
-%% Decoding of option VALUES receved from "getopt":
+%% Decoding of option VALUES received from "getopt":
%% NOT required for SCTP, as it always returns ready terms, not lists:
%%
dec_value(bool, [0,0,0,0|T]) -> {false,T};
@@ -2145,7 +2248,15 @@ dec_value(time, [X3,X2,X1,X0|T]) ->
-1 -> {infinity, T};
Val -> {Val, T}
end;
-dec_value(ip, [A,B,C,D|T]) -> {{A,B,C,D}, T};
+%% dec_value(ip, [A,B,C,D|T]) -> {{A,B,C,D}, T};
+dec_value(mif, [A,B,C,D, X3,X2,X1,X0|T]) ->
+ Domain = ?i32(X3, X2, X1, X0),
+ case Domain of
+ ?INET_AF_INET ->
+ {{A,B,C,D}, T};
+ ?INET_AF_INET6 ->
+ {?i32(A,B,C,D), T}
+ end;
%% dec_value(ether, [X1,X2,X3,X4,X5,X6|T]) -> {[X1,X2,X3,X4,X5,X6],T};
dec_value(sockaddr, [X|T]) ->
get_ip(X, T);
@@ -2451,7 +2562,8 @@ decode_ifopts([B | Buf], Acc) ->
undefined ->
{error, einval};
Opt ->
- {Val,T} = dec_value(type_ifopt(Opt), Buf),
+ OptType = type_ifopt(Opt),
+ {Val,T} = dec_value(OptType, Buf),
decode_ifopts(T, [{Opt,Val} | Acc])
end;
decode_ifopts(_,Acc) -> {ok,Acc}.
@@ -2518,7 +2630,7 @@ dec_subs([]) -> [].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
-%% handle statictics options
+%% handle statistics options
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2731,13 +2843,38 @@ utf8_to_characters(Bs, U, 0) ->
utf8_to_characters([B|Bs], U, N) when ((B band 16#3F) bor 16#80) =:= B ->
utf8_to_characters(Bs, (U bsl 6) bor (B band 16#3F), N-1).
+ip4_to_bytes(any) ->
+ ip4_any();
+ip4_to_bytes(loopback) ->
+ ip4_loopback();
ip4_to_bytes({A,B,C,D}) ->
[A band 16#ff, B band 16#ff, C band 16#ff, D band 16#ff].
+ip4_any() -> [0,0,0,0].
+ip4_loopback() -> [127,0,0,1].
+
+
+ip6_to_bytes(any) ->
+ ip6_any();
+ip6_to_bytes(loopback) ->
+ ip6_loopback();
ip6_to_bytes({A,B,C,D,E,F,G,H}) ->
[?int16(A), ?int16(B), ?int16(C), ?int16(D),
?int16(E), ?int16(F), ?int16(G), ?int16(H)].
+ip6_any() ->
+ Z1 = ?int16(0),
+ Z2 = [Z1, Z1],
+ Z3 = [Z2, Z2],
+ [Z3, Z3].
+
+ip6_loopback() ->
+ Z1 = ?int16(0),
+ Z2 = [Z1, Z1],
+ Z3 = [Z2, Z2],
+ [Z3, Z2, Z1, ?int16(1)].
+
+
get_addrs([]) ->
[];
get_addrs([F|Addrs]) ->
diff --git a/erts/preloaded/src/prim_net.erl b/erts/preloaded/src/prim_net.erl
index 9604704278..d70201d129 100644
--- a/erts/preloaded/src/prim_net.erl
+++ b/erts/preloaded/src/prim_net.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,10 @@
getnameinfo/2,
getaddrinfo/2,
getifaddrs/1,
+ get_adapters_addresses/1,
+ get_if_entry/1,
+ get_interface_info/1,
+ get_ip_address_table/1,
if_name2index/1,
if_index2name/1,
@@ -41,37 +45,236 @@
]).
-export_type([
- address_info/0,
- ifaddrs/0,
- name_info/0,
-
- ifaddrs_flag/0,
- ifaddrs_flags/0,
-
- name_info_flag/0,
- name_info_flag_ext/0,
- name_info_flags/0,
-
- network_interface_name/0,
- network_interface_index/0
+ getifaddrs_args/0,
+ interface_info_args/0,
+ if_entry_args/0,
+ ip_address_table_args/0,
+
+ if_type/0,
+ if_admin_status/0,
+ internal_if_oper_status/0,
+ mib_if_row/0,
+
+ ip_adapter_index_map/0,
+ ip_interface_info/0,
+
+ mib_ip_address_row/0,
+ mib_ip_address_table/0,
+
+ adapters_addresses_flags/0,
+ adapters_addresses_args/0,
+ adapter_unicast_dad_state/0,
+ adapter_unicast_prefix_origin/0,
+ adapter_unicast_suffix_origin/0,
+ adapter_unicast_flags/0,
+ adapter_unicast_addr/0,
+ adapter_anycast_flags/0,
+ adapter_anycast_addr/0,
+ adapter_multicast_flags/0,
+ adapter_multicast_addr/0,
+ adapter_dns_server_addr/0,
+ adapter_flags/0,
+ adapter_type/0,
+ adapter_oper_status/0,
+ adapter_prefix/0,
+ adapter_addresses/0,
+ adapters_addresses/0
]).
+-type getifaddrs_args() :: #{netns => string()}.
+
-type ifaddrs_flag() :: up | broadcast | debug | loopback | pointopoint |
- notrailers | running | noarp | promisc | master | slave |
+ notrailers | running | noarp | promisc |
+ master | slave |
multicast | portsel | automedia | dynamic.
-type ifaddrs_flags() :: [ifaddrs_flag()].
%% Note that not all of these fields are mandatory.
-%% Actually there are (error) cases when only the name will be included.
-%% And broadaddr and dstaddr are mutually exclusive!
+%% *Also*, broadaddr and dstaddr are mutually exclusive!
-type ifaddrs() :: #{name := string(),
flags := ifaddrs_flags(),
- addr := socket:sockaddr(),
- netmask := socket:sockaddr(),
- broadaddr := socket:sockaddr(),
- dstaddr := socket:sockaddr()}.
+ addr => socket:sockaddr(),
+ netmask => socket:sockaddr(),
+ %% 'broadaddr' and 'dstaddr' are mutually exclusive
+ broadaddr => socket:sockaddr(),
+ dstaddr => socket:sockaddr()}.
+
+-type interface_info_args() :: #{debug => boolean()}.
+-type if_entry_args() :: #{index := non_neg_integer(),
+ debug => boolean()}.
+-type ip_address_table_args() :: #{debug => boolean()}.
+
+-type if_type() :: other | ethernet_csmacd | iso88025_tokenring |
+ fddi | ppp | software_loopback | atm | ieee80211 |
+ tunnel | ieee1394 | ieee80216_wman | wwanpp | wwanpp2.
+-type if_admin_status() :: non_operational |
+ unreachable |
+ disconnected |
+ connecting | connected |
+ operational |
+ non_neg_integer().
+-type internal_if_oper_status() :: non_operational |
+ unreachable |
+ disconnected |
+ connecting | connected |
+ operational |
+ non_neg_integer().
+-type mib_if_row() :: #{name := string(),
+ index := non_neg_integer(),
+ type := if_type(),
+ mtu := non_neg_integer(),
+ speed := non_neg_integer(),
+ phys_addr := binary(),
+ admin_status := if_admin_status(),
+ internal_oper_status := internal_if_oper_status(),
+ last_change := non_neg_integer(),
+ in_octets := non_neg_integer(),
+ in_ucast_pkts := non_neg_integer(),
+ in_nucast_pkts := non_neg_integer(),
+ in_discards := non_neg_integer(),
+ in_errors := non_neg_integer(),
+ in_unknown_protos := non_neg_integer(),
+ out_octets := non_neg_integer(),
+ out_ucast_pkts := non_neg_integer(),
+ out_nucast_pkts := non_neg_integer(),
+ out_discards := non_neg_integer(),
+ out_errors := non_neg_integer(),
+ out_qlen := non_neg_integer(),
+ description := binary()}.
+
+-type ip_adapter_index_map() :: #{index := integer(),
+ name := string()}.
+
+-type ip_interface_info() :: [ip_adapter_index_map()].
+
+%% addr: The IPv4 address in network byte order.
+%% index: The index of the interface associated with this
+%% IPv4 address.
+%% mask: The subnet mask for the IPv4 address in network
+%% byte order.
+%% broadcast_addr: The broadcast address in network byte order.
+%% A broadcast address is typically the IPv4 address
+%% with the host portion set to either all zeros or
+%% all ones.
+%% reasm_size: The maximum re-assembly size for received datagrams.
+-type mib_ip_address_row() :: #{addr := non_neg_integer(),
+ index := non_neg_integer(),
+ mask := non_neg_integer(),
+ broadcast_addr := non_neg_integer(),
+ reasm_size := non_neg_integer()}.
+-type mib_ip_address_table() :: [mib_ip_address_row()].
+
+-type adapters_addresses_flags() ::
+ #{skip_unicast => boolean(), % default false
+ skip_anycast => boolean(), % default true
+ skip_multicast => boolean(), % default true
+ skip_dns_server => boolean(), % default true
+ skip_friendly_name => boolean(), % default true
+ include_prefix => boolean(), % default true
+ include_wins_info => boolean(), % default false
+ include_gateways => boolean(), % default false
+ include_all_interfaces => boolean(), % default false
+ include_all_compartments => boolean(), % default false
+ include_tunnel_bindingorder => boolean()}. % default false)
+
+%% defaults to:
+%% #{family => unspec,
+%% flags => #{skip_unicast => false
+%% skip_anycast => true
+%% skip_multicast => true
+%% skip_dns_server => true
+%% skip_friendly_name => true
+%% include_prefix => true
+%% include_wins_info => false
+%% include_gateways => false
+%% include_all_interfaces => false
+%% include_all_compartments => false
+%% include_tunnel_bindingorder => false},
+%% debug => false}.
+-type adapters_addresses_args() :: #{family => unspec | inet | inet6,
+ flags => adapters_addresses_flags(),
+ debug => boolean()}.
+
+-type adapter_unicast_dad_state() :: invalid | tentative | duplicate |
+ deprecated | preferred |
+ integer().
+-type adapter_unicast_prefix_origin() :: other | manual | well_known | dhcp |
+ router_advertisement | unchanged |
+ integer().
+-type adapter_unicast_suffix_origin() :: other | manual | well_known | dhcp |
+ link_layer_address | random |
+ unchanged |
+ integer().
+-type adapter_unicast_flags() :: #{dns_eligible := boolean(),
+ transient := boolean()}.
+
+-type adapter_unicast_addr() ::
+ #{addr := socket:sockaddr(),
+ dad_state := adapter_unicast_dad_state(),
+ flags := adapter_unicast_flags(),
+ prefix_origin := adapter_unicast_prefix_origin(),
+ suffix_origin := adapter_unicast_suffix_origin(),
+ lease_lifetime := non_neg_integer(),
+ preferred_lifetime := non_neg_integer(),
+ valid_lifetime := non_neg_integer()}.
+
+-type adapter_anycast_flags() :: #{dns_eligible := boolean(),
+ transient := boolean()}.
+
+-type adapter_anycast_addr() :: #{addr := socket:sockaddr(),
+ flags := adapter_anycast_flags()}.
+
+-type adapter_multicast_flags() :: #{dns_eligible := boolean(),
+ transient := boolean()}.
+
+-type adapter_multicast_addr() :: #{addr := socket:sockaddr(),
+ flags := adapter_multicast_flags()}.
+
+-type adapter_dns_server_addr() :: #{addr := socket:sockaddr()}.
+
+-type adapter_flags() :: #{ddns_enabled := boolean(),
+ register_adapter_suffix := boolean(),
+ dhcp_v4_enabled := boolean(),
+ receive_only := boolean(),
+ no_multicast := boolean(),
+ ipv6_other_stateful_config := boolean(),
+ netbios_over_tcpip_enabled := boolean(),
+ ipv4_enabled := boolean(),
+ ipv6_enabled := boolean(),
+ ipv6_managed_address_config_supported := boolean()}.
+
+-type adapter_type() :: other | ethernet_csmacd | iso88025_tokenring |
+ fddi | ppp | software_loopback | atm | ieee80211 |
+ tunnel | ieee1394 | ieee80216_wman | wwanpp | wwanpp2 |
+ integer().
+
+-type adapter_oper_status() :: up | down | testing | dormant | not_present |
+ lower_layer_down |
+ integer().
+
+-type adapter_prefix() :: #{addr := socket:sockaddr(),
+ length := non_neg_integer()}.
+-type adapter_addresses() ::
+ #{index := non_neg_integer(),
+ name := string(),
+ unicast_addrs := [adapter_unicast_addr()],
+ anycast_addrs := [adapter_anycast_addr()],
+ multicast_addrs := [adapter_multicast_addr()],
+ dns_server_addrs := [adapter_dns_server_addr()],
+ dns_suffix := string(),
+ description := string(),
+ friendly_name := string(),
+ phys_addr := binary(),
+ flags := adapter_flags(),
+ mtu := non_neg_integer(),
+ type := adapter_type(),
+ oper_status := adapter_oper_status(),
+ zone_indices := [non_neg_integer()], % Length 16
+ ipv6_index := non_neg_integer(),
+ prefixes := [adapter_prefix()]}.
+-type adapters_addresses() :: [adapter_addresses()].
-type name_info_flag() :: namereqd |
dgram |
@@ -93,6 +296,56 @@
-type network_interface_index() :: non_neg_integer().
+-define(NO_SKIPS_ALL_INCLUDES,
+ #{skip_unicast => false,
+ skip_anycast => false,
+ skip_multicast => false,
+ skip_dns_server => false,
+ skip_friendly_name => false,
+ include_prefix => true,
+ include_wins_info => true,
+ include_gateways => true,
+ include_all_interfaces => true,
+ include_all_compartments => true,
+ include_tunnel_bindingorder => true}).
+-define(ALL_SKIPS_NO_INCLUDES,
+ #{skip_unicast => true,
+ skip_anycast => true,
+ skip_multicast => true,
+ skip_dns_server => true,
+ skip_friendly_name => true,
+ include_prefix => false,
+ include_wins_info => false,
+ include_gateways => false,
+ include_all_interfaces => false,
+ include_all_compartments => false,
+ include_tunnel_bindingorder => false}).
+-define(NO_SKIPS_NO_INCLUDES,
+ #{skip_unicast => false,
+ skip_anycast => false,
+ skip_multicast => false,
+ skip_dns_server => false,
+ skip_friendly_name => false,
+ include_prefix => false,
+ include_wins_info => false,
+ include_gateways => false,
+ include_all_interfaces => false,
+ include_all_compartments => false,
+ include_tunnel_bindingorder => false}).
+-define(ALL_SKIPS_ALL_INCLUDES,
+ #{skip_unicast => true,
+ skip_anycast => true,
+ skip_multicast => true,
+ skip_dns_server => true,
+ skip_friendly_name => true,
+ include_prefix => true,
+ include_wins_info => true,
+ include_gateways => true,
+ include_all_interfaces => true,
+ include_all_compartments => true,
+ include_tunnel_bindingorder => true}).
+
+
%% ===========================================================================
%%
%% Administrative and utility API
@@ -109,10 +362,13 @@ on_load() ->
Extra :: map().
on_load(Extra) ->
- ok = erlang:load_nif(atom_to_list(net), Extra).
+ %% This will fail if the user has disabled esock support, making all NIFs
+ %% fall back to their Erlang implementation which throws `notsup`.
+ _ = erlang:load_nif(atom_to_list(net), Extra),
+ ok.
--spec info() -> list().
+-spec info() -> map().
info() ->
nif_info().
@@ -232,6 +488,84 @@ getifaddrs(Extra) when is_map(Extra) ->
%% ===========================================================================
%%
+%% get_adapters_addresses - Get adapters addresses
+%%
+
+-spec get_adapters_addresses(Args) -> {ok, Addrs} | {error, Reason} when
+ Args :: default |
+ no_skips_all_includes | no_skips_no_includes |
+ all_skips_no_includes | all_skips_all_includes |
+ adapters_addresses_args(),
+ Addrs :: adapters_addresses(),
+ Reason :: term().
+
+get_adapters_addresses(default) ->
+ Args = #{},
+ get_adapters_addresses(Args);
+get_adapters_addresses(no_skips_all_includes) ->
+ Args = #{flags => ?NO_SKIPS_ALL_INCLUDES},
+ get_adapters_addresses(Args);
+get_adapters_addresses(no_skips_no_includes) ->
+ Args = #{flags => ?NO_SKIPS_NO_INCLUDES},
+ get_adapters_addresses(Args);
+get_adapters_addresses(all_skips_no_includes) ->
+ Args = #{flags => ?ALL_SKIPS_NO_INCLUDES},
+ get_adapters_addresses(Args);
+get_adapters_addresses(all_skips_all_includes) ->
+ Args = #{flags => ?ALL_SKIPS_ALL_INCLUDES},
+ get_adapters_addresses(Args);
+get_adapters_addresses(Args) when is_map(Args) ->
+ nif_get_adapters_addresses(Args).
+
+
+
+%% ===========================================================================
+%%
+%% get_interface_info - Get interface info
+%%
+
+-spec get_interface_info(Args) -> {ok, IfInfo} | {error, Reason} when
+ Args :: interface_info_args(),
+ IfInfo :: ip_interface_info(),
+ Reason :: term().
+
+get_interface_info(Args) when is_map(Args) ->
+ nif_get_interface_info(Args).
+
+
+
+%% ===========================================================================
+%%
+%% get_if_entry - Get interface info
+%%
+
+-spec get_if_entry(Args) -> {ok, Info} | {error, Reason} when
+ Args :: if_entry_args(),
+ Info :: mib_if_row(),
+ Reason :: term().
+
+get_if_entry(Args) when is_map(Args) ->
+ nif_get_if_entry(Args).
+
+
+
+%% ===========================================================================
+%%
+%% get_ip_address_table - Get (mib) address table
+%%
+
+-spec get_ip_address_table(Args) -> {ok, Info} | {error, Reason} when
+ Args :: ip_address_table_args(),
+ Info :: term(),
+ Reason :: term().
+
+get_ip_address_table(Args) when is_map(Args) ->
+ nif_get_ip_address_table(Args).
+
+
+
+%% ===========================================================================
+%%
%% if_name2index - Mappings between network interface names and indexes:
%% name -> idx
%%
@@ -270,7 +604,7 @@ if_index2name(Idx) when is_integer(Idx) ->
%%
%%
--spec if_names() -> Names | {error, Reason} when
+-spec if_names() -> {ok, Names} | {error, Reason} when
Names :: [{Idx, If}],
Idx :: network_interface_index(),
If :: network_interface_name(),
@@ -320,29 +654,41 @@ if_names() ->
%% ===========================================================================
nif_info() ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_command(_Cmd) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_gethostname() ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_getnameinfo(_Addr, _Flags) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_getaddrinfo(_Host, _Service, _Hints) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_getifaddrs(_Extra) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
+
+nif_get_adapters_addresses(_Args) ->
+ erlang:nif_error(notsup).
+
+nif_get_if_entry(_Args) ->
+ erlang:nif_error(notsup).
+
+nif_get_interface_info(_Args) ->
+ erlang:nif_error(notsup).
+
+nif_get_ip_address_table(_Args) ->
+ erlang:nif_error(notsup).
nif_if_name2index(_Name) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_if_index2name(_Id) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_if_names() ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
diff --git a/erts/preloaded/src/prim_socket.erl b/erts/preloaded/src/prim_socket.erl
index ec92aeb4bf..68c950331a 100644
--- a/erts/preloaded/src/prim_socket.erl
+++ b/erts/preloaded/src/prim_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,6 +49,14 @@
-export([enc_sockaddr/1, p_get/1]).
+-nifs([nif_info/0, nif_info/1, nif_supports/0, nif_supports/1, nif_command/1,
+ nif_open/2, nif_open/4, nif_bind/2, nif_connect/1, nif_connect/3,
+ nif_listen/2, nif_accept/2, nif_send/4, nif_sendto/5, nif_sendmsg/5,
+ nif_sendfile/5, nif_sendfile/4, nif_sendfile/1, nif_recv/4,
+ nif_recvfrom/4, nif_recvmsg/5, nif_close/1, nif_shutdown/2,
+ nif_setopt/5, nif_getopt/3, nif_getopt/4, nif_sockname/1,
+ nif_peername/1, nif_ioctl/2, nif_ioctl/3, nif_ioctl/4, nif_cancel/3,
+ nif_finalize_close/1]).
%% Also in socket
-define(REGISTRY, socket_registry).
@@ -145,8 +153,9 @@ on_load(Extra) when is_map(Extra) ->
socket_debug => true,
debug_filename => enc_path(DebugFilename)}
end,
- ok = erlang:load_nif(atom_to_list(?MODULE), Extra_2),
- %%
+ %% This will fail if the user has disabled esock support, making all NIFs
+ %% fall back to their Erlang implementation which throws `notsup`.
+ _ = erlang:load_nif(atom_to_list(?MODULE), Extra_2),
init().
init() ->
@@ -1128,58 +1137,58 @@ p_get(Name) ->
%% NIF functions
%%
-nif_info() -> erlang:nif_error(undef).
-nif_info(_SockRef) -> erlang:nif_error(undef).
+nif_info() -> erlang:nif_error(notsup).
+nif_info(_SockRef) -> erlang:nif_error(notsup).
-nif_command(_Command) -> erlang:nif_error(undef).
+nif_command(_Command) -> erlang:nif_error(notsup).
-nif_supports() -> erlang:nif_error(undef).
-nif_supports(_Key) -> erlang:nif_error(undef).
+nif_supports() -> erlang:nif_error(notsup).
+nif_supports(_Key) -> erlang:nif_error(notsup).
-nif_open(_FD, _Opts) -> erlang:nif_error(undef).
-nif_open(_Domain, _Type, _Protocol, _Opts) -> erlang:nif_error(undef).
+nif_open(_FD, _Opts) -> erlang:nif_error(notsup).
+nif_open(_Domain, _Type, _Protocol, _Opts) -> erlang:nif_error(notsup).
-nif_bind(_SockRef, _SockAddr) -> erlang:nif_error(undef).
-nif_bind(_SockRef, _SockAddrs, _Action) -> erlang:nif_error(undef).
+nif_bind(_SockRef, _SockAddr) -> erlang:nif_error(notsup).
+nif_bind(_SockRef, _SockAddrs, _Action) -> erlang:nif_error(notsup).
-nif_connect(_SockRef) -> erlang:nif_error(undef).
-nif_connect(_SockRef, _ConnectRef, _SockAddr) -> erlang:nif_error(undef).
+nif_connect(_SockRef) -> erlang:nif_error(notsup).
+nif_connect(_SockRef, _ConnectRef, _SockAddr) -> erlang:nif_error(notsup).
-nif_listen(_SockRef, _Backlog) -> erlang:nif_error(undef).
+nif_listen(_SockRef, _Backlog) -> erlang:nif_error(notsup).
-nif_accept(_SockRef, _Ref) -> erlang:nif_error(undef).
+nif_accept(_SockRef, _Ref) -> erlang:nif_error(notsup).
-nif_send(_SockRef, _Bin, _Flags, _SendRef) -> erlang:nif_error(undef).
-nif_sendto(_SockRef, _Bin, _Dest, _Flags, _SendRef) -> erlang:nif_error(undef).
-nif_sendmsg(_SockRef, _Msg, _Flags, _SendRef, _IOV) -> erlang:nif_error(undef).
+nif_send(_SockRef, _Bin, _Flags, _SendRef) -> erlang:nif_error(notsup).
+nif_sendto(_SockRef, _Bin, _Dest, _Flags, _SendRef) -> erlang:nif_error(notsup).
+nif_sendmsg(_SockRef, _Msg, _Flags, _SendRef, _IOV) -> erlang:nif_error(notsup).
nif_sendfile(_SockRef, _SendRef, _Offset, _Count, _InFileRef) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
nif_sendfile(_SockRef, _SendRef, _Offset, _Count) ->
- erlang:nif_error(undef).
-nif_sendfile(_SockRef) -> erlang:nif_error(undef).
+ erlang:nif_error(notsup).
+nif_sendfile(_SockRef) -> erlang:nif_error(notsup).
-nif_recv(_SockRef, _Length, _Flags, _RecvRef) -> erlang:nif_error(undef).
-nif_recvfrom(_SockRef, _Length, _Flags, _RecvRef) -> erlang:nif_error(undef).
+nif_recv(_SockRef, _Length, _Flags, _RecvRef) -> erlang:nif_error(notsup).
+nif_recvfrom(_SockRef, _Length, _Flags, _RecvRef) -> erlang:nif_error(notsup).
nif_recvmsg(_SockRef, _BufSz, _CtrlSz, _Flags, _RecvRef) ->
- erlang:nif_error(undef).
+ erlang:nif_error(notsup).
-nif_close(_SockRef) -> erlang:nif_error(undef).
-nif_finalize_close(_SockRef) -> erlang:nif_error(undef).
-nif_shutdown(_SockRef, _How) -> erlang:nif_error(undef).
+nif_close(_SockRef) -> erlang:nif_error(notsup).
+nif_finalize_close(_SockRef) -> erlang:nif_error(notsup).
+nif_shutdown(_SockRef, _How) -> erlang:nif_error(notsup).
-nif_setopt(_SockRef, _Lev, _Opt, _Val, _NativeVal) -> erlang:nif_error(undef).
-nif_getopt(_SockRef, _Lev, _Opt) -> erlang:nif_error(undef).
-nif_getopt(_SockRef, _Lev, _Opt, _ValSpec) -> erlang:nif_error(undef).
+nif_setopt(_SockRef, _Lev, _Opt, _Val, _NativeVal) -> erlang:nif_error(notsup).
+nif_getopt(_SockRef, _Lev, _Opt) -> erlang:nif_error(notsup).
+nif_getopt(_SockRef, _Lev, _Opt, _ValSpec) -> erlang:nif_error(notsup).
-nif_sockname(_SockRef) -> erlang:nif_error(undef).
-nif_peername(_SockRef) -> erlang:nif_error(undef).
+nif_sockname(_SockRef) -> erlang:nif_error(notsup).
+nif_peername(_SockRef) -> erlang:nif_error(notsup).
-nif_ioctl(_SockRef, _GReq) -> erlang:nif_error(undef).
-nif_ioctl(_SockRef, _GReq, _Arg) -> erlang:nif_error(undef).
-nif_ioctl(_SockRef, _SReq, _Arg1, _Arg2) -> erlang:nif_error(undef).
+nif_ioctl(_SockRef, _GReq) -> erlang:nif_error(notsup).
+nif_ioctl(_SockRef, _GReq, _Arg) -> erlang:nif_error(notsup).
+nif_ioctl(_SockRef, _SReq, _Arg1, _Arg2) -> erlang:nif_error(notsup).
-nif_cancel(_SockRef, _Op, _SelectRef) -> erlang:nif_error(undef).
+nif_cancel(_SockRef, _Op, _SelectRef) -> erlang:nif_error(notsup).
%% ===========================================================================
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index ca5cfec0e3..51dbf498a2 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@
-define(READ_BLOCK_SIZE, 16*1024).
%% for debugging, to turn off catch
--define(CATCH, catch).
+-define(CATCH(Expr), (catch (Expr))).
-record(primzip_file,
{name,
@@ -203,7 +203,7 @@ get_z_all(?DEFLATED, Compressed, Z, _F) ->
ok = zlib:inflateInit(Z, -?MAX_WBITS),
Uncompressed = zlib:inflate(Z, Compressed),
%%_CRC = zlib:crc32(Z),
- ?CATCH zlib:inflateEnd(Z),
+ _ = ?CATCH(zlib:inflateEnd(Z)),
erlang:iolist_to_binary(Uncompressed); % {erlang:iolist_to_binary(Uncompressed), CRC}
get_z_all(?STORED, Stored, _Z, _F) ->
%%CRC0 = zlib:crc32(Z, <<>>),
@@ -350,7 +350,7 @@ prim_file_io({file_info, F}, _) ->
{error, E} -> throw(E)
end;
prim_file_io({open, FN, Opts}, _) ->
- case ?CATCH prim_file:open(FN, Opts++[binary]) of
+ case prim_file:open(FN, Opts++[binary]) of
{ok, H} ->
H;
{error, E} ->
diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl
index d34d994291..4862547f4a 100644
--- a/erts/preloaded/src/zlib.erl
+++ b/erts/preloaded/src/zlib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,6 +52,14 @@
-export_type([zstream/0, zflush/0, zlevel/0, zwindowbits/0, zmemlevel/0,
zstrategy/0]).
+-nifs([close_nif/1, open_nif/0, set_controller_nif/2, deflateInit_nif/6,
+ deflateSetDictionary_nif/2, deflateReset_nif/1, deflateEnd_nif/1,
+ deflateParams_nif/3, deflate_nif/4, inflateInit_nif/3,
+ inflateSetDictionary_nif/2, inflateGetDictionary_nif/1,
+ inflateReset_nif/1, inflateEnd_nif/1, inflate_nif/4, crc32_nif/1,
+ getStash_nif/1, clearStash_nif/1, setStash_nif/2, getBufSize_nif/1,
+ setBufSize_nif/2, enqueue_nif/2]).
+
%% flush argument encoding
-define(Z_NO_FLUSH, 0).
-define(Z_SYNC_FLUSH, 2).
diff --git a/erts/test/Makefile b/erts/test/Makefile
index 1fe230adaf..addf5f89c5 100644
--- a/erts/test/Makefile
+++ b/erts/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -38,7 +38,8 @@ MODULES= \
run_erl_SUITE \
erlexec_SUITE \
z_SUITE \
- upgrade_SUITE
+ upgrade_SUITE \
+ parallel_messages_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -84,6 +85,8 @@ release_tests_spec: opt
$(INSTALL_DATA) system.spec system.dynspec system_smoke.spec \
$(ERL_FILES) $(TARGET_FILES) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
+ cp "$(ERL_TOP)/otp_versions.table" "$(ERL_TOP)/erts/test/otp_SUITE_data"
+ cp "$(ERL_TOP)/make/otp_version_tickets" "$(ERL_TOP)/erts/test/otp_SUITE_data"
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 544d1a8dcb..84e99675a0 100644
--- a/erts/test/erl_print_SUITE.erl
+++ b/erts/test/erl_print_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ erlang_display(Config) when is_list(Config) ->
chk_display(mk_ref_xstr({e@f, oth_cre(MyCre)}, [1,2,3])),
chk_display(mk_ref_xstr({e@f, oth_cre(oth_cre(MyCre))}, [1,2,3])),
- %% Compund terms
+ %% Compound terms
{Pid, PidStr} = mk_pid_xstr({x@y, oth_cre(MyCre)}, 4712, 41),
{Port, PortStr} = mk_port_xstr({x@y, oth_cre(MyCre)}, 4712),
{Ref, RefStr} = mk_ref_xstr({e@f, oth_cre(MyCre)}, [11,12,13]),
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
index f5a5f8bf5c..449aedf301 100644
--- a/erts/test/erlc_SUITE.erl
+++ b/erts/test/erlc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,28 +21,56 @@
%% Tests the erlc command by compiling various types of files.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, compile_erl/1,
+-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,
+ compile_erl/1,
compile_yecc/1, compile_script/1,
compile_mib/1, good_citizen/1, deep_cwd/1, arg_overflow/1,
- make_dep_options/1]).
+ make_dep_options/1,
+ features_erlc_describe/1,
+ features_erlc_unknown/1,
+ features_directives/1,
+ features_atom_warnings/1,
+ features_macros/1,
+ features_disable/1,
+ features_all/1,
+ features_load/1,
+ features_runtime/1,
+ features_include/1,
+ features/1]).
-include_lib("common_test/include/ct.hrl").
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
- [{group,with_server},{group,without_server}].
+all() ->
+ [{group,with_server},{group,without_server},
+ {group,features_with_server}].
groups() ->
Tests = tests(),
[{with_server,[],Tests},
- {without_server,[],Tests}].
+ {features_with_server,[],feature_tests()},
+ {without_server,[],Tests ++ feature_tests()}].
tests() ->
[compile_erl, compile_yecc, compile_script, compile_mib,
good_citizen, deep_cwd, arg_overflow, make_dep_options].
+feature_tests() ->
+ [features_erlc_describe,
+ features_erlc_unknown,
+ features_directives,
+ features_atom_warnings,
+ features_macros,
+ features_disable,
+ features_all,
+ features_load,
+ features_runtime,
+ features_include,
+ features].
+
init_per_suite(Config) ->
Config.
@@ -52,6 +80,10 @@ end_per_suite(_Config) ->
init_per_group(with_server, Config) ->
os:putenv("ERLC_USE_SERVER", "yes"),
Config;
+init_per_group(features_with_server, Config) ->
+ os:putenv("ERLC_USE_SERVER", "yes"),
+ timer:sleep(12 * 1000),
+ Config;
init_per_group(without_server, Config) ->
os:putenv("ERLC_USE_SERVER", "no"),
Config;
@@ -60,8 +92,28 @@ init_per_group(_, Config) ->
end_per_group(_GroupName, Config) ->
os:unsetenv("ERLC_USE_SERVER"),
+ os:unsetenv("OTP_TEST_FEATURES"),
+ Config.
+
+init_per_testcase(TestCase, Config) ->
+ case lists:member(TestCase, feature_tests()) of
+ true ->
+ os:putenv("OTP_TEST_FEATURES", "true");
+ false ->
+ ok
+ end,
Config.
+end_per_testcase(TestCase, Config) ->
+ case lists:member(TestCase, feature_tests()) of
+ true ->
+ os:putenv("OTP_TEST_FEATURES", "true");
+ false ->
+ ok
+ end,
+ Config.
+
+
%% Copy from erlc_SUITE_data/include/erl_test.hrl.
-record(person, {name, shoe_size}).
@@ -150,7 +202,7 @@ compile_mib(Config) when is_list(Config) ->
%% Try -W option and more verbose.
ok = file:delete(Output),
- case test_server:os_type() of
+ case os:type() of
{unix,_} ->
run(Config, Cmd, FileName, "-W +'{verbosity,info}'",
["\\[GOOD-MIB[.]mib\\]\\[INF\\]: No accessfunction for 'sysDescr' => using default",
@@ -435,6 +487,590 @@ make_dep_options(Config) ->
false = exists(BeamFileName),
ok.
+
+%%% Tests related to the features mechanism
+%% Support macros and functions
+-define(OK(Lines), Lines ++ ["_OK_"]).
+-define(NOTOK(Lines), Lines ++ ["_ERROR_"]).
+
+flatfmt(FStr, Args) ->
+ lists:flatten(io_lib:format(FStr, Args)).
+
+defopt(Name) -> flatfmt("-D~w", [Name]).
+defopt(Name, Value) -> flatfmt("-D~w=~w", [Name, Value]).
+
+longopt(enable, Ftr) -> flatfmt("-enable-feature ~w", [Ftr]);
+longopt(disable, Ftr) -> flatfmt("-disable-feature ~w", [Ftr]).
+
+plusopt(enable, Ftr) -> flatfmt("+\"{feature, ~w, enable}\"", [Ftr]);
+plusopt(disable, Ftr) -> flatfmt("+\"{feature, ~w, disable}\"", [Ftr]).
+
+options(Opts) -> lists:flatten(lists:join(" ", Opts)).
+
+peer(Args) ->
+ {ok, Peer, Node} =
+ ?CT_PEER(#{args => Args,
+ connection => 0}),
+ {Peer, Node}.
+
+%% Error messages to expect
+nosingle(Ftr) -> flatfmt("the feature '~w' does not exist", [Ftr]).
+
+nomultiple(Ftrs) ->
+ Q = fun(A) -> flatfmt("'~w'", [A]) end,
+ flatfmt("the features ~s and '~w' do not exist",
+ [lists:join(", ",
+ lists:map(Q, lists:droplast(Ftrs))),
+ lists:last(Ftrs)]).
+
+not_config(Ftr) -> flatfmt("the feature '~w' is not configurable", [Ftr]).
+
+syntax(Offender) -> flatfmt("syntax error before: ~w", [Offender]).
+
+misplaced_directive() ->
+ "feature directive not allowed after exports or record definitions".
+
+atom_warning(Atom, Ftr) ->
+ flatfmt("atom '~w' is reserved in the experimental feature '~w'",
+ [Atom, Ftr]).
+
+compile_fun(Config) ->
+ {SrcDir, OutDir, Cmd} = get_cmd(Config),
+ Compile = fun(FName, Opts, Expected) ->
+ Path = case FName of
+ "" -> "";
+ FName -> filename:join(SrcDir, FName)
+ end,
+ run(Config, Cmd, Path, Opts, Expected)
+ end,
+ {Compile, SrcDir, OutDir}.
+
+%% Tests
+features_erlc_describe(Config) when is_list(Config) ->
+ {Compile, _, _} = compile_fun(Config),
+
+ Compile("", "-list-features",
+ ?NOTOK(["Available features:",
+ "approved_ftr_1",
+ "approved_ftr_2",
+ "experimental_ftr_1",
+ "experimental_ftr_2"])),
+
+ Compile("", "-describe-feature experimental_ftr_1",
+ ?NOTOK(["experimental_ftr_1",
+ "Type",
+ "Status",
+ "Keywords",
+ skip_lines])),
+
+ Compile("", "-describe-feature loop_macro",
+ ?NOTOK(["Unknown feature: loop_macro"])).
+
+features_erlc_unknown(Config) when is_list(Config) ->
+ {Compile, _, _} = compile_fun(Config),
+
+ %% Test for single invalid feature, using long and +options
+ Compile("nofile.erl", longopt(enable, no_ftr),
+ ?NOTOK([nosingle(no_ftr)])),
+ Compile("nofile.erl", plusopt(enable, no_ftr),
+ ?NOTOK([nosingle(no_ftr)])),
+ Compile("nofile.erl", longopt(disable, no_ftr),
+ ?NOTOK([nosingle(no_ftr)])),
+ Compile("nofile.erl", plusopt(disable, no_ftr),
+ ?NOTOK([nosingle(no_ftr)])),
+
+ %% Test for multiple invalid features
+ Compile("nofile.erl", options([longopt(enable, no_ftr),
+ longopt(enable, un_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr])])),
+ Compile("nofile.erl", options([longopt(enable, no_ftr),
+ longopt(enable, un_ftr),
+ longopt(disable, mis_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr, mis_ftr])])),
+ Compile("nofile.erl", options([plusopt(enable, no_ftr),
+ plusopt(enable, un_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr])])),
+ Compile("nofile.erl", options([plusopt(enable, no_ftr),
+ plusopt(enable, un_ftr),
+ plusopt(disable, mis_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr, mis_ftr])])),
+
+ Compile("nofile.erl", options([longopt(enable, no_ftr),
+ plusopt(enable, un_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr])])),
+ Compile("nofile.erl", options([plusopt(enable, no_ftr),
+ longopt(enable, un_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr])])),
+
+ Compile("nofile.erl", options([longopt(enable, no_ftr),
+ longopt(enable, un_ftr),
+ plusopt(disable, mis_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr, mis_ftr])])),
+ Compile("nofile.erl", options([longopt(enable, no_ftr),
+ plusopt(enable, un_ftr),
+ plusopt(disable, mis_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr, mis_ftr])])),
+
+ Compile("nofile.erl", options([longopt(enable, no_ftr),
+ plusopt(enable, un_ftr),
+ longopt(disable, mis_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr, mis_ftr])])),
+ Compile("nofile.erl", options([plusopt(enable, no_ftr),
+ plusopt(enable, un_ftr),
+ longopt(disable, mis_ftr)]),
+ ?NOTOK([nomultiple([no_ftr, un_ftr, mis_ftr])])),
+
+ %% Rejected and permanent features can not be configured.
+ %% Rejected feature
+ Compile("nofile.erl",
+ options([longopt(enable, rejected_ftr)]),
+ ?NOTOK([not_config(rejected_ftr),
+ skip_lines])),
+
+ %% Permanent feature
+ Compile("nofile.erl",
+ options([longopt(enable, permanent_ftr)]),
+ ?NOTOK([not_config(permanent_ftr),
+ skip_lines])).
+
+features_directives(Config) when is_list(Config) ->
+ {Compile, _, _} = compile_fun(Config),
+
+ %% Test for misplaced feature directive (enable)
+ Compile("f_directives.erl",
+ options([defopt(misplaced_enable)]),
+ ?NOTOK([misplaced_directive(),
+ "[0-9]+\| -feature.*misplaced",
+ skip_lines])),
+ %% Test for misplaced feature directive (disable)
+ Compile("f_directives.erl",
+ options([defopt(misplaced_disable)]),
+ ?NOTOK([misplaced_directive(),
+ "[0-9]+\| -feature.*misplaced",
+ skip_lines])),
+
+ %% Test for unknown feature in directive (enable)
+ Compile("f_directives.erl",
+ options([defopt(enable_unknown)]),
+ ?NOTOK([nosingle(unlesser),
+ "[0-9]+\| -feature",
+ skip_lines])),
+ %% Test for unknown feature in directive (disable)
+ Compile("f_directives.erl",
+ options([defopt(disable_unknown)]),
+ ?NOTOK([nosingle(unlesser),
+ "[0-9]+\| -feature",
+ skip_lines])),
+
+ %% Enable a feature on the command line and disable the same in a
+ %% directive
+ Compile("f_directives.erl",
+ options([longopt(enable, experimental_ftr_2),
+ defopt(disable_exp2),
+ defopt(no_dir_enable_exp2)]),
+ ?OK([])).
+
+features_atom_warnings(Config) when is_list(Config) ->
+ {Compile, _, _} = compile_fun(Config),
+
+ %% Check for keyword warnings. Not all are checked.
+ Compile("ignorant.erl", "+warn_keywords",
+ ?OK([atom_warning(until, experimental_ftr_2),
+ skip_lines,
+ atom_warning(ifn, experimental_ftr_1),
+ skip_lines,
+ atom_warning(while, experimental_ftr_2),
+ skip_lines])),
+
+ %% Check for keyword warnings, resulting in error.
+ %% Not all warnings are checked.
+ Compile("ignorant.erl", "+warn_keywords -Werror",
+ ?NOTOK([skip_lines,
+ atom_warning(until, experimental_ftr_2),
+ skip_lines,
+ atom_warning(ifn, experimental_ftr_1),
+ skip_lines,
+ atom_warning(while, experimental_ftr_2),
+ skip_lines])),
+
+ %% Check for keyword warnings. Not all warnings are checked.
+ %% This file has a -compile attribute for keyword warnings.
+ Compile("ignorant_directive.erl", "",
+ ?OK([atom_warning(ifn, experimental_ftr_1),
+ skip_lines,
+ atom_warning(while, experimental_ftr_2),
+ skip_lines,
+ atom_warning(until, experimental_ftr_2),
+ skip_lines])),
+
+ %% Override warning attribute inside file
+ Compile("ignorant_directive.erl", "+nowarn_keywords",
+ ?OK([])),
+
+ %% File has quoted atoms which are keywords in experimental_ftr_2.
+ %% We should see no warnings.
+ Compile("foo.erl", options([longopt(enable, experimental_ftr_2),
+ "+warn_keywords"]),
+ ?OK([])).
+
+features(Config) when is_list(Config) ->
+ {Compile, _, _} = compile_fun(Config),
+
+ %% Simple compile - baseline for this file. Really needed?
+ %% It uses atoms that are keywords in experimental features.
+ Compile("ignorant.erl",
+ [],
+ ?OK([])),
+
+ %% Enable and disable the same feature on the command line to
+ %% check that the ordering semantics is honoured.
+ Compile("ignorant.erl",
+ options([longopt(enable, experimental_ftr_1),
+ longopt(disable, experimental_ftr_1)]),
+ ?OK([])),
+
+ %% As above, with +options
+ Compile("ignorant.erl",
+ options([plusopt(enable, experimental_ftr_1),
+ plusopt(disable, experimental_ftr_1)]),
+ ?OK([])),
+
+ %% Mixed options
+ Compile("ignorant.erl",
+ options([longopt(enable, experimental_ftr_1),
+ plusopt(disable, experimental_ftr_1)]),
+ ?OK([])),
+
+ %% Mixed options
+ Compile("ignorant.erl",
+ options([plusopt(enable, experimental_ftr_1),
+ longopt(disable, experimental_ftr_1)]),
+ ?OK([])),
+
+ %% Enable a feature and see errors
+ Compile("ignorant.erl",
+ options([longopt(enable, experimental_ftr_1)]),
+ ?NOTOK([syntax(ifn),
+ skip_lines,
+ syntax(ifn),
+ skip_lines])),
+
+ %% Enable another feature and see other errors
+ Compile("ignorant.erl",
+ options([longopt(enable, experimental_ftr_2)]),
+ ?NOTOK([syntax(until),
+ skip_lines,
+ syntax(until),
+ skip_lines,
+ syntax(while),
+ skip_lines,
+ syntax(while),
+ skip_lines,
+ syntax(until),
+ skip_lines])),
+
+ %% Enable both features and see even more errors
+ Compile("ignorant.erl",
+ options([longopt(enable, experimental_ftr_1),
+ longopt(enable, experimental_ftr_2)]),
+ ?NOTOK([syntax(until),
+ skip_lines,
+ syntax(until),
+ skip_lines,
+ syntax(ifn),
+ skip_lines,
+ syntax(while),
+ skip_lines,
+ syntax(until),
+ skip_lines,
+ syntax(ifn),
+ skip_lines])),
+
+ ok.
+
+features_macros(Config) when is_list(Config) ->
+ {Compile, _, OutDir} = compile_fun(Config),
+
+ Compile("f_macros.erl", "", ?OK([])),
+
+ {Peer0, Node0} = peer(["-pa", OutDir]),
+ Call = fun(Node, Fun) ->
+ erpc:call(Node, f_macros, Fun, [])
+ end,
+
+ {module, f_macros} =
+ erpc:call(Node0, code, load_file, [f_macros]),
+
+ true = Call(Node0, has_experimental),
+ false = Call(Node0, has_hindley_milner),
+ false = Call(Node0, with_hm),
+ false = Call(Node0, uses_experimental),
+ false = Call(Node0, uses_exp2),
+
+ peer:stop(Peer0),
+
+ Compile("f_macros.erl", longopt(enable, experimental_ftr_1),
+ ?OK([])),
+
+ {Peer1, Node1} = peer(["-pa", OutDir]),
+
+ true = erpc:call(Node1, erlang, module_loaded, [erl_features]),
+
+ %% We can't load this due to experimental_ftr_1 not being enabled
+ %% in the runtime
+ {error, {features_not_allowed, [experimental_ftr_1]}} =
+ erpc:call(Node1, code, load_file, [f_macros]),
+ %% Check features enabled during compilation
+ [approved_ftr_1, approved_ftr_2, experimental_ftr_1] =
+ erpc:call(Node1, erl_features, used, [f_macros]),
+
+ peer:stop(Peer1),
+
+ %% Restart with feature enabled in runtime
+ {Peer2, Node2} = peer(["-pa", OutDir,
+ "-enable-feature","experimental_ftr_1"]),
+ %% Now we can load it
+ {module, f_macros} =
+ erpc:call(Node2, code, load_file, [f_macros]),
+
+ true = Call(Node2, uses_experimental),
+ false = Call(Node2, uses_exp2),
+ peer:stop(Peer2),
+
+ Compile("f_macros.erl", longopt(enable, experimental_ftr_2),
+ ?OK([])),
+ {Peer3, Node3} = peer(["-pa", OutDir,
+ "-enable-feature","experimental_ftr_2"]),
+ false = Call(Node3, uses_experimental),
+ true = Call(Node3, uses_exp2),
+ peer:stop(Peer3),
+
+ Compile("f_macros.erl", options([longopt(enable, experimental_ftr_1),
+ longopt(enable, experimental_ftr_2)]),
+ ?OK([])),
+ {Peer4, Node4} = peer(["-pa", OutDir,
+ "-enable-feature","experimental_ftr_1",
+ "-enable-feature","experimental_ftr_2"]),
+ true = Call(Node4, uses_experimental),
+ true = Call(Node4, uses_exp2),
+ peer:stop(Peer4),
+
+ ok.
+
+features_disable(Config) when is_list(Config) ->
+ {Compile, _, OutDir} = compile_fun(Config),
+
+ Call = fun(Node, Fun) ->
+ erpc:call(Node, f_disable, Fun, [])
+ end,
+
+ Compile("f_disable.erl", options([longopt(enable, experimental_ftr_1),
+ longopt(enable, experimental_ftr_2)]),
+ ?OK([])),
+
+ {Peer, Node} = peer(["-pa", OutDir,
+ "-enable-feature","experimental_ftr_1",
+ "-enable-feature","experimental_ftr_2"]),
+ %% Check features enabled during compilation
+ [approved_ftr_2] =
+ erpc:call(Node, erl_features, used, [f_disable]),
+
+ no_experimental = Call(Node, no_experimental),
+ no_exp2 = Call(Node, no_ftrs),
+ peer:stop(Peer),
+
+ ok.
+
+features_all(Config) when is_list(Config) ->
+ {Compile, _, OutDir} = compile_fun(Config),
+
+ Compile("foo.erl", longopt(enable, all),
+ ?OK([])),
+
+ {Peer0, Node0} = peer(["-pa", OutDir]),
+ %% Check features enabled during compilation
+ [approved_ftr_1,approved_ftr_2,experimental_ftr_1,experimental_ftr_2] =
+ erpc:call(Node0, erl_features, used, [foo]),
+ peer:stop(Peer0),
+
+ Compile("foo.erl", longopt(disable, all),
+ ?OK([])),
+
+ {Peer1, Node1} = peer(["-pa", OutDir]),
+ %% Check features enabled during compilation
+ [] = erpc:call(Node1, erl_features, used, [foo]),
+ {module, foo} = erpc:call(Node1, code, load_file, [foo]),
+ peer:stop(Peer1),
+
+ Compile("foo.erl", options([longopt(disable, all),
+ longopt(enable, approved_ftr_2)]),
+ ?OK([])),
+
+ {Peer2, Node2} = peer(["-pa", OutDir,
+ "-disable-feature", "all"]),
+ %% Check features enabled during compilation
+ [approved_ftr_2] = erpc:call(Node2, erl_features, used, [foo]),
+ {error, {features_not_allowed, [approved_ftr_2]}} =
+ erpc:call(Node2, code, load_file, [foo]),
+ peer:stop(Peer2),
+
+ ok.
+
+features_load(Config) when is_list(Config) ->
+ {_Compile, SrcDir, _OutDir} = compile_fun(Config),
+
+ %% Note that we put SrcDir in the load path as there is where we
+ %% have the precompiled beam file.
+ {Peer0, Node0} = peer(["-pa", SrcDir]),
+
+ %% For a file compiled with an older version, i.e., with no Meta
+ %% chunk, we should see no used features.
+ [] = erpc:call(Node0, erl_features, used, [older]),
+ %% .. and we should be able to load it.
+ {module,older} = erpc:call(Node0, code, load_file, [older]),
+
+ [] = erpc:call(Node0, erl_features, used,
+ [filename:join(SrcDir, "older.beam")]),
+
+ %% Behaviour for non existent modules
+ not_found = erpc:call(Node0, erl_features, used, [none]),
+ not_found = erpc:call(Node0, erl_features, used, ["none.beam"]),
+ peer:stop(Peer0),
+
+ ok.
+
+features_runtime(Config) when is_list(Config) ->
+ AllFtrs = [approved_ftr_1,
+ approved_ftr_2,
+ experimental_ftr_1,
+ experimental_ftr_2,
+ permanent_ftr,
+ rejected_ftr],
+ ConfigFtrs = [approved_ftr_1,
+ approved_ftr_2,
+ experimental_ftr_1,
+ experimental_ftr_2],
+ Approved = [approved_ftr_2,
+ approved_ftr_1],
+
+ {Compile, _SrcDir, _OutDir} = compile_fun(Config),
+
+ {Peer0, Node0} = peer([]),
+
+ %% Get all known features
+ AllFtrs = erpc:call(Node0, erl_features, all, []),
+ ConfigFtrs = erpc:call(Node0, erl_features, configurable, []),
+ Approved = erpc:call(Node0, erl_features, enabled, []),
+
+ %% Keywords from enabled (here the approved) features
+ %% (does not need to be quoted since it comes from the peer node)
+ [unless] = erpc:call(Node0, erl_features, keywords, []),
+
+ Info = erpc:call(Node0, erl_features, info, [permanent_ftr]),
+ true = is_map(Info),
+ true = lists:all(fun(K) -> is_map_key(K, Info) end,
+ [status,type,description,short,experimental]),
+
+ %% Try to get info for unknown feature - raises error
+ try
+ erpc:call(Node0, erl_features, info, [unknown_feature]) of
+ Value ->
+ ct:fail({value_returned_for_unknown_feature, Value})
+ catch
+ error:{exception, invalid_feature, _} ->
+ ok;
+ Class:Reason ->
+ ct:fail({unexpected_exception, {Class, Reason}})
+ end,
+
+ peer:stop(Peer0),
+
+ {Peer1, Node1} = peer(["-enable-feature", "experimental_ftr_2"]),
+ [experimental_ftr_2, approved_ftr_2, approved_ftr_1] =
+ erpc:call(Node1, erl_features, enabled, []),
+ [while, until, unless] = erpc:call(Node1, erl_features, keywords, []),
+
+ peer:stop(Peer1),
+
+ {Peer2, Node2} = peer(["-disable-feature", "all"]),
+ [] = erpc:call(Node2, erl_features, enabled, []),
+ [] = erpc:call(Node2, erl_features, keywords, []),
+
+ peer:stop(Peer2),
+ ok.
+
+features_include(Config) when is_list(Config) ->
+ {Compile, _SrcDir, OutDir} = compile_fun(Config),
+
+ %% Ensure that the feature experimental_ftr_1 is enabled in the
+ %% include file and generates an error
+ Compile("f_include_1.erl", [],
+ ?NOTOK([syntax(ifn),
+ skip_lines])),
+
+ %% This will disable a feature after a record has been defined.
+ %% Error expected
+ Compile("f_include_1.erl", defopt(end_include),
+ ?NOTOK([misplaced_directive(),
+ skip_lines])),
+
+ %% Ensure that the macro knows that experimental_ftr_1 is enabled
+ %% in the include file.
+ Compile("f_include_2.erl", defopt(end_include),
+ ?OK([])),
+
+ {Peer0, Node0} = peer(["-pa", OutDir,
+ "-enable-feature", "experimental_ftr_1"]),
+
+ {module, f_include_2} = erpc:call(Node0, code, load_file, [f_include_2]),
+ active = erpc:call(Node0, f_include_2, foo, [2]),
+ peer:stop(Peer0),
+
+ Compile("f_include_3.erl", [],
+ ?OK([])),
+
+ {Peer1, Node1} = peer(["-pa", OutDir,
+ "-enable-feature", "all"]),
+ exp2_enabled = erpc:call(Node1, f_include_3, foo, [1]),
+ peer:stop(Peer1),
+
+ Compile("f_include_3.erl", defopt(end_prefix),
+ ?NOTOK([misplaced_directive(),
+ "experimental_ftr_2",
+ skip_lines])),
+
+ Compile("f_include_exp2.erl", defopt(enable_exp_2, 0),
+ ?OK([])),
+ {Peer2, Node2} = peer(["-pa", OutDir]),
+ {conditional, on, until} = erpc:call(Node2, f_include_exp2, foo, []),
+ peer:stop(Peer2),
+
+ Compile("f_include_exp2.erl",
+ options([defopt(enable_exp_2, 0),
+ longopt(enable, experimental_ftr_2)]),
+ ?NOTOK([syntax(until),
+ skip_lines])),
+
+ Compile("f_include_exp2.erl",
+ options([defopt(enable_exp_2, 1)]),
+ ?NOTOK([syntax(until),
+ skip_lines])),
+
+ Compile("f_include_exp2.erl",
+ options([defopt(enable_exp_2, 2),
+ longopt(enable, experimental_ftr_2)]),
+ ?OK([])),
+
+ {Peer3, Node3} = peer(["-pa", OutDir,
+ "-enable-feature", "experimental_ftr_2"]),
+ {conditional, off, none} = erpc:call(Node3, f_include_exp2, foo, []),
+
+ [approved_ftr_1, approved_ftr_2, experimental_ftr_2] =
+ erpc:call(Node3, erl_features, used, [f_include_exp2]),
+ peer:stop(Peer3),
+
+ ok.
+
%% Runs a command.
run(Config, Cmd0, Name, Options, Expect) ->
@@ -447,7 +1083,7 @@ verify_result(Result, Expect) ->
Messages = split(Result, [], []),
io:format("Result: ~p", [Messages]),
io:format("Expected: ~p", [Expect]),
- match_messages(Messages, Expect).
+ match_messages_x(Messages, Expect).
%% insert What before Item, crash if Item is not found
insert_before(Item, What, [Item|List]) ->
@@ -466,15 +1102,27 @@ split([], [], Lines) ->
split([], Current, Lines) ->
split([], [], [lists:reverse(Current)|Lines]).
-match_messages([Msg|Rest1], [Regexp|Rest2]) ->
- case re:run(Msg, Regexp, [{capture,none}, unicode]) of
+match_messages_x(Msgs0, Regexps0) ->
+ Msgs = lists:droplast(Msgs0),
+ Regexps = lists:droplast(Regexps0),
+ Return = lists:last(Msgs0),
+ ExpRet = lists:last(Regexps0),
+ match_messages(Msgs, Regexps),
+ match_one(Return, ExpRet).
+
+match_messages(_, [skip_lines]) ->
+ ok;
+match_messages([_Msg|Rest1], [skip_one|Rest2]) ->
+ match_messages(Rest1, Rest2);
+match_messages([Msg|Rest1], [skip_lines, Regexp|Rest2]) ->
+ case match(Msg, Regexp) of
match ->
- ok;
+ match_messages(Rest1, Rest2);
nomatch ->
- io:format("Not matching: ~s\n", [Msg]),
- io:format("Regexp : ~s\n", [Regexp]),
- ct:fail(message_mismatch)
- end,
+ match_messages(Rest1, [skip_lines, Regexp|Rest2])
+ end;
+match_messages([Msg|Rest1], [Regexp|Rest2]) ->
+ match_one(Msg, Regexp),
match_messages(Rest1, Rest2);
match_messages([], [Expect|Rest]) ->
ct:fail({too_few_messages, [Expect|Rest]});
@@ -483,6 +1131,19 @@ match_messages([Msg|Rest], []) ->
match_messages([], []) ->
ok.
+match_one(Msg, Regexp) ->
+ case match(Msg, Regexp) of
+ match ->
+ ok;
+ nomatch ->
+ io:format("Not matching: ~s\n", [Msg]),
+ io:format("Regexp : ~s\n", [Regexp]),
+ ct:fail(message_mismatch)
+ end.
+
+match(Msg, Regexp) ->
+ re:run(Msg, Regexp, [{capture,none}, unicode]).
+
get_cmd(Cfg) ->
{SrcDir, IncDir, OutDir} = get_dirs(Cfg),
Cmd = erlc() ++ " -I" ++ IncDir ++ " -o" ++ OutDir ++ " ",
@@ -509,7 +1170,7 @@ run_command(Config, Cmd) ->
TmpDir = filename:join(proplists:get_value(priv_dir, Config), "tmp"),
file:make_dir(TmpDir),
{RunFile, Run, Script} = run_command(TmpDir, os:type(), Cmd),
- ok = file:write_file(filename:join(TmpDir, RunFile), unicode:characters_to_binary(Script)),
+ ok = file:write_file(RunFile, unicode:characters_to_binary(Script)),
os:cmd(Run).
run_command(Dir, {win32, _}, Cmd) ->
diff --git a/erts/test/erlc_SUITE_data/src/enable.hrl b/erts/test/erlc_SUITE_data/src/enable.hrl
new file mode 100644
index 0000000000..9d5934723b
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/enable.hrl
@@ -0,0 +1 @@
+-feature(experimental_ftr_2, enable).
diff --git a/erts/test/erlc_SUITE_data/src/exp2.hrl b/erts/test/erlc_SUITE_data/src/exp2.hrl
new file mode 100644
index 0000000000..91fa3b39b5
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/exp2.hrl
@@ -0,0 +1,6 @@
+-if(?enable_exp_2 > 0).
+-feature(experimental_ftr_2, enable).
+-record(conditional, {on=off, 'until'=none}).
+-else.
+-record(conditional, {on=on, until=until}).
+-endif.
diff --git a/erts/test/erlc_SUITE_data/src/f_directives.erl b/erts/test/erlc_SUITE_data/src/f_directives.erl
new file mode 100644
index 0000000000..f8fe4fbf1a
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_directives.erl
@@ -0,0 +1,67 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_directives).
+
+-ifdef(disable_unknown).
+-feature(unlesser, disable).
+-endif.
+
+-ifdef(enable_unknown).
+-feature(unlesser, enable).
+-endif.
+
+%% This module uses both features experimental_ftr_1 and
+%% experimental_ftr_2, so atoms belonging to these need to be quoted.
+
+-feature(experimental_ftr_1, enable).
+
+-ifndef(no_dir_enable_exp2).
+-feature(experimental_ftr_2, enable).
+-endif.
+
+-ifdef(disable_exp2).
+-feature(experimental_ftr_2, disable).
+-endif.
+
+-export([bar/0,
+ foo/0]).
+
+-ifdef(misplaced_enable).
+%% This is out of place and will result in an error
+-feature(misplaced, enable).
+-endif.
+
+-ifdef(misplaced_disable).
+%% This is out of place and will result in an error
+-feature(misplaced, disable).
+-endif.
+
+bar() ->
+ ['ifn'].
+
+-ifdef(disable_exp2).
+foo() ->
+ %% Note: experimental_ftr_2 not active here
+ ['ifn', while, until, 'if'].
+-else.
+foo() ->
+ ['ifn', 'while', 'until', 'if'].
+-endif.
diff --git a/erts/test/erlc_SUITE_data/src/f_disable.erl b/erts/test/erlc_SUITE_data/src/f_disable.erl
new file mode 100644
index 0000000000..d106e038d8
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_disable.erl
@@ -0,0 +1,46 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_disable).
+
+-feature(experimental_ftr_1, disable).
+-feature(experimental_ftr_2, disable).
+-feature(approved_ftr_1, disable).
+
+-export([no_experimental/0,
+ no_ftrs/0]).
+
+-if(?FEATURE_ENABLED(experimental_ftr_1)).
+-define(FOO, has_experimental).
+-else.
+-define(FOO, no_experimental).
+-endif.
+
+no_experimental() ->
+ ?FOO.
+
+-if(?FEATURE_ENABLED(experimental_ftr_2)).
+-define(BAR, has_exp2).
+-else.
+-define(BAR, no_exp2).
+-endif.
+
+no_ftrs() ->
+ ?BAR.
diff --git a/erts/test/erlc_SUITE_data/src/f_include_1.erl b/erts/test/erlc_SUITE_data/src/f_include_1.erl
new file mode 100644
index 0000000000..27ea93565a
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_include_1.erl
@@ -0,0 +1,18 @@
+-module(f_include_1).
+
+-feature(experimental_ftr_1, enable).
+
+-ifdef(end_include).
+-feature(experimental_ftr_2, enable).
+-endif.
+
+%% This defines a record, so ends the prefix.
+-include("is_enabled.hrl").
+
+-ifdef(end_include).
+-feature(approved_ftr_1, disable).
+-endif.
+
+-export([foo/1]).
+
+foo(1) -> one.
diff --git a/erts/test/erlc_SUITE_data/src/f_include_2.erl b/erts/test/erlc_SUITE_data/src/f_include_2.erl
new file mode 100644
index 0000000000..a31d44e43f
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_include_2.erl
@@ -0,0 +1,12 @@
+-module(f_include_2).
+
+-feature(experimental_ftr_1, enable).
+
+%% Include file defines a macro, conditional on whether experimental_ftr_1
+%% is enabled.
+-include("macro_enabled.hrl").
+
+%% At this point the prefix will definitely end, if it has not already
+-export([foo/1]).
+
+foo(2) -> ?UNLESS.
diff --git a/erts/test/erlc_SUITE_data/src/f_include_3.erl b/erts/test/erlc_SUITE_data/src/f_include_3.erl
new file mode 100644
index 0000000000..cce18ca2d4
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_include_3.erl
@@ -0,0 +1,21 @@
+-module(f_include_3).
+
+-feature(experimental_ftr_1, enable).
+
+-ifdef(end_prefix).
+-record(constant, {value = 42}).
+-endif.
+
+%% Enable feature inside include file
+-include("enable.hrl").
+
+%% At this point the prefix will definitely end, if it has not already
+-export([foo/1]).
+
+-if(?FEATURE_ENABLED(experimental_ftr_2)).
+foo(1) ->
+ exp2_enabled.
+-else.
+foo(1) ->
+ exp2_disabled.
+-endif.
diff --git a/erts/test/erlc_SUITE_data/src/f_include_exp2.erl b/erts/test/erlc_SUITE_data/src/f_include_exp2.erl
new file mode 100644
index 0000000000..aef3a5a5f4
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_include_exp2.erl
@@ -0,0 +1,18 @@
+-module(f_include_exp2).
+
+-include("exp2.hrl").
+
+-export([foo/0,
+ bar/0]).
+
+
+foo() ->
+ #conditional{}.
+
+-if(?enable_exp_2 == 1).
+bar() ->
+ until.
+-else.
+bar() ->
+ no.
+-endif.
diff --git a/erts/test/erlc_SUITE_data/src/f_macros.erl b/erts/test/erlc_SUITE_data/src/f_macros.erl
new file mode 100644
index 0000000000..72b73ece52
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/f_macros.erl
@@ -0,0 +1,65 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(f_macros).
+
+-export([has_experimental/0,
+ has_hindley_milner/0,
+ with_hm/0,
+ uses_experimental/0,
+ uses_exp2/0
+ ]).
+
+%% This test feature exists
+-if(?FEATURE_AVAILABLE(experimental_ftr_1)).
+has_experimental() ->
+ true.
+-else.
+has_experimental() ->
+ false.
+-endif.
+
+%% This feature will probably never exist :-(
+-if(?FEATURE_AVAILABLE(hindley_milner)).
+has_hindley_milner() ->
+ true.
+-else.
+has_hindley_milner() ->
+ false.
+-endif.
+
+with_hm() ->
+ ?FEATURE_ENABLED(hindley_milner).
+
+-if(?FEATURE_ENABLED(experimental_ftr_1)).
+uses_experimental() ->
+ true.
+-else.
+uses_experimental() ->
+ false.
+-endif.
+
+-if(?FEATURE_ENABLED(experimental_ftr_2)).
+uses_exp2() ->
+ true.
+-else.
+uses_exp2() ->
+ false.
+-endif.
diff --git a/erts/test/erlc_SUITE_data/src/foo.erl b/erts/test/erlc_SUITE_data/src/foo.erl
new file mode 100644
index 0000000000..b3716803aa
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/foo.erl
@@ -0,0 +1,6 @@
+-module foo.
+
+-export [foo/0].
+
+foo() ->
+ ['while', 'until'].
diff --git a/lib/diameter/test/diameter_ct.hrl b/erts/test/erlc_SUITE_data/src/ignorant.erl
index fdf8782456..f0ae7e6b5d 100644
--- a/lib/diameter/test/diameter_ct.hrl
+++ b/erts/test/erlc_SUITE_data/src/ignorant.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,5 +18,27 @@
%% %CopyrightEnd%
%%
--define(APP, diameter).
--define(ERROR(T), erlang:error({?MODULE, ?LINE, T})).
+%% This module is ignorant about any features and thus use 'ifn',
+%% 'while' and 'until' as ordinary atoms.
+
+-module(ignorant).
+
+-export([foo/0,
+ frob/1,
+ bar/0,
+ until/1,
+ baz/1]).
+
+until(X) ->
+ until(X).
+
+foo() ->
+ [ifn, while, until].
+
+frob(while) -> false.
+
+bar() ->
+ [until, while].
+
+baz(ifn) ->
+ {true, 'ifnot'}.
diff --git a/erts/emulator/test/hipe_SUITE_data/literals.erl b/erts/test/erlc_SUITE_data/src/ignorant_directive.erl
index 31e443970f..5ad8c23e3c 100644
--- a/erts/emulator/test/hipe_SUITE_data/literals.erl
+++ b/erts/test/erlc_SUITE_data/src/ignorant_directive.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,25 @@
%% %CopyrightEnd%
%%
--module(literals).
+%% This module is ignorant about any features and thus use 'ifn',
+%% 'while and 'until' as ordinary atoms.
--export([a/0, b/0]).
+-module(ignorant_directive).
-a() -> [a,b,c].
-b() -> {a,b,c}.
+-compile(warn_keywords).
+
+-export([foo/0,
+ frob/1,
+ bar/0,
+ baz/1]).
+
+foo() ->
+ [ifn, while, until].
+
+frob(while) -> false.
+
+bar() ->
+ [until, while].
+
+baz(ifn) ->
+ true.
diff --git a/erts/test/erlc_SUITE_data/src/is_enabled.hrl b/erts/test/erlc_SUITE_data/src/is_enabled.hrl
new file mode 100644
index 0000000000..e91cfeda8e
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/is_enabled.hrl
@@ -0,0 +1,3 @@
+%% This will fail when experimental_ftr_1 is not enabled
+%% or end the prefix when it is enabled
+-record(random, {ifn = 42, unless = 17}).
diff --git a/erts/test/erlc_SUITE_data/src/macro_enabled.hrl b/erts/test/erlc_SUITE_data/src/macro_enabled.hrl
new file mode 100644
index 0000000000..c23cfd6c71
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/macro_enabled.hrl
@@ -0,0 +1,5 @@
+-if(?FEATURE_ENABLED(experimental_ftr_1)).
+-define(UNLESS, active).
+-else.
+-define(UNLESS, inactive).
+-endif.
diff --git a/erts/test/erlc_SUITE_data/src/older.beam b/erts/test/erlc_SUITE_data/src/older.beam
new file mode 100644
index 0000000000..c2b677586a
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/older.beam
Binary files differ
diff --git a/erts/test/erlc_SUITE_data/src/older.erl b/erts/test/erlc_SUITE_data/src/older.erl
new file mode 100644
index 0000000000..06bb154e28
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/older.erl
@@ -0,0 +1,6 @@
+-module(older).
+
+-export([none/0]).
+
+none() ->
+ old.
diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl
index 8d7ecebc23..ab2439be09 100644
--- a/erts/test/erlexec_SUITE.erl
+++ b/erts/test/erlexec_SUITE.erl
@@ -82,7 +82,7 @@ argument_separation(Config) when is_list(Config) ->
{ok,[[]]} = rpc:call(SName,init,get_argument,[atest]),
{ok,[[]]} = rpc:call(SName,init,get_argument,[cmd_test]),
{ok,[[]]} = rpc:call(SName,init,get_argument,[test]),
- error = rpc:call(SName,init,get_argument,[unkown]),
+ error = rpc:call(SName,init,get_argument,[unknown]),
["cmd_param","env_param","zenv_param"] = rpc:call(SName,init,get_plain_arguments,[]),
ok = cleanup_nodes(),
ok.
diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl
index b2a0445ec1..5754bf5d3b 100644
--- a/erts/test/nt_SUITE.erl
+++ b/erts/test/nt_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -195,7 +195,7 @@ user_env(Config) when is_list(Config) ->
remove_service(Name),
ok.
-%% Check that services are stopped and started syncronous and that
+%% Check that services are stopped and started synchronous and that
%% failed stopactions kill the erlang machine anyway.
synced(Config) when is_list(Config) ->
Name0 = "test_service_4",
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index a4c0f7a50c..1690406314 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -27,7 +27,8 @@
call_to_size_1/1,call_to_now_0/1,strong_components/1,
erl_file_encoding/1,xml_file_encoding/1,
runtime_dependencies_functions/1,
- runtime_dependencies_modules/1]).
+ runtime_dependencies_modules/1,
+ test_runtime_dependencies_versions/1]).
-include_lib("common_test/include/ct.hrl").
@@ -35,15 +36,17 @@
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap, {minutes, 10}}].
+ {timetrap, {minutes, 30}}].
-all() ->
+all() ->
[undefined_functions, deprecated_not_in_obsolete,
obsolete_but_not_deprecated, call_to_deprecated,
call_to_size_1, call_to_now_0, strong_components,
erl_file_encoding, xml_file_encoding,
runtime_dependencies_functions,
- runtime_dependencies_modules].
+ runtime_dependencies_modules,
+ test_runtime_dependencies_versions
+].
init_per_suite(Config) ->
Server = start_xref_server(daily_xref, functions),
@@ -140,7 +143,7 @@ wx_filter(Undef) ->
end.
diameter_filter(Undef) ->
- %% Filter away function calls that are catched.
+ %% Filter away function calls that are caught.
filter(fun({{diameter_lib,_,_},{erlang,convert_time_unit,3}}) ->
false;
({{diameter_lib,_,_},{erlang,monotonic_time,0}}) ->
@@ -541,3 +544,330 @@ start_xref_server(Server, Mode) ->
end
end,
Server.
+
+get_suite_data_dir_path() ->
+ filename:join(filename:dirname(code:which(?MODULE)), "otp_SUITE_data").
+
+get_otp_versions_table_path() ->
+ filename:join(get_suite_data_dir_path(), "otp_versions.table").
+
+get_otp_version_tickets_path() ->
+ filename:join(get_suite_data_dir_path(), "otp_version_tickets").
+
+%% Return a map that maps from app versions to the OTP versions they
+%% were last released in. The function makes use of the file
+%% "otp_versions.table" and the current code:get_path() to
+%% find apps.
+get_runtime_dep_to_otp_version_map() ->
+ %% Find apps in "otp_versions.table"
+ VersionsTableFile = get_otp_versions_table_path(),
+ VersionsTableBin =
+ case file:read_file(VersionsTableFile) of
+ {ok, Bin} -> Bin;
+ Error -> ct:fail("Could not read the file ~s which is needed to perform the test. "
+ "Error: ~p~n",
+ [VersionsTableFile, Error])
+ end,
+ VersionsTableStr = erlang:binary_to_list(VersionsTableBin),
+ Lines = lists:reverse(string:tokens(VersionsTableStr, "\n")),
+ AddVersionsInString =
+ fun(Map, OTPVersion, AppVersionsString0) ->
+ AppVersionsString =
+ lists:flatten(string:replace(AppVersionsString0, "#", "", all)),
+ AppVersions = string:tokens(AppVersionsString, " "),
+ lists:foldl(
+ fun(AppVersion0, MapSoFar) ->
+ case string:trim(AppVersion0) of
+ "" ->
+ MapSoFar;
+ AppVersion1 ->
+ maps:put(AppVersion1, OTPVersion, MapSoFar)
+ end
+ end,
+ Map,
+ AppVersions)
+ end,
+ VersionMap0 =
+ lists:foldl(
+ fun(Line, MapSoFar) ->
+ [OTPVersion, AppVersionsString| _] =
+ string:tokens(Line, ":"),
+ AddVersionsInString(MapSoFar,
+ string:trim(OTPVersion),
+ string:trim(AppVersionsString))
+ end,
+ #{},
+ Lines),
+ %% Find apps in code:get_path()
+ lists:foldl(
+ fun(Path, MapSoFar) ->
+ case filelib:wildcard(filename:join(Path, "*.app")) of
+ [AppFile] ->
+ {ok,[{application, App, Info}]} = file:consult(AppFile),
+ case lists:keyfind(vsn, 1, Info) of
+ false ->
+ MapSoFar;
+ {vsn, VsnStr} ->
+ AppVsnStr =
+ erlang:atom_to_list(App) ++ "-" ++ VsnStr,
+ maps:put(AppVsnStr, {latest, Path}, MapSoFar)
+ end;
+ _ ->
+ MapSoFar
+ end
+ end,
+ VersionMap0,
+ code:get_path()).
+
+%% Find runtime dependencies for an app
+get_runtime_deps(App) ->
+ AppFile = code:where_is_file(atom_to_list(App) ++ ".app"),
+ {ok,[{application, App, Info}]} = file:consult(AppFile),
+ case lists:keyfind(runtime_dependencies, 1, Info) of
+ {runtime_dependencies, RDeps} ->
+ RDeps;
+ false ->
+ []
+ end.
+
+%% Given a release dir find the path to the given dependency
+find_dep_in_rel_dir(Dep, RelDirRoot) ->
+ %% The dependencies that we have found are cached to avoid
+ %% searching through the file system unnecessary many times
+ CacheId = runtime_dep_test_cache,
+ DepCache =
+ case erlang:get(CacheId) of
+ undefined -> #{};
+ M-> M
+ end,
+ case maps:get(Dep, DepCache, none) of
+ none ->
+ DepPaths = filelib:wildcard(filename:join([RelDirRoot, "lib", "**", Dep, "ebin"])),
+ case DepPaths of
+ [Path] ->
+ erlang:put(CacheId, maps:put(Dep, Path, DepCache)),
+ Path;
+ _ ->
+ ErrorMessage =
+ io_lib:format("ERROR: Could not find ~p in ~p (where it is supposed to be)."
+ "Found ~p~n", [Dep, RelDirRoot, DepPaths]),
+ io:format(lists:flatten(ErrorMessage)),
+ ct:fail(ErrorMessage)
+
+ end;
+ Path ->
+ Path
+ end.
+
+%% Get the major OTP version part of an OTP version string
+%% Example: OTP-22.0 gives 22
+get_major_version(OtpVersion) ->
+ [_,MajorVersion|_] = string:tokens(OtpVersion, "-."),
+ MajorVersion.
+
+%% Returns the release directory for the oldest available OTP release
+%% on the current machine
+first_available_otp_rel() ->
+ %% At least one version less than the current version should be available
+ SholdBeAvailable = erlang:list_to_integer(erlang:system_info(otp_release)) - 1,
+ (fun FindOldest(CurrRel, PrevAvailable) ->
+ case test_server:is_release_available(erlang:integer_to_list(CurrRel)) of
+ false -> PrevAvailable;
+ true -> FindOldest(CurrRel-1, erlang:integer_to_list(CurrRel))
+ end
+ end)(SholdBeAvailable, none).
+
+%% Searches for the oldest available version of Dep
+get_oldest_available_version_of_dep(Dep) ->
+ [DepName, _Version] = string:tokens(Dep, "-"),
+ FirstAvailableRel = first_available_otp_rel(),
+ (fun Find(LookInRel) ->
+ case test_server:is_release_available(LookInRel) of
+ true ->
+ RelRoot = find_rel_root(LookInRel),
+ Options0 = filelib:wildcard(filename:join([RelRoot, "lib", "**", "ebin"])),
+ Options1 = [Opt ||
+ Opt <- Options0,
+ string:find(Opt,
+ filename:join("lib", DepName ++ "-")) =/= nomatch],
+ GetVersionTuple =
+ fun(Path) ->
+ [AppVerStr] =
+ [C || C <- filename:split(Path),
+ string:find(C, DepName ++ "-") =/= nomatch],
+ [_,VerStr] = string:tokens(AppVerStr, "-"),
+ erlang:list_to_tuple([erlang:list_to_integer(X) ||
+ X <- string:tokens(VerStr, ".")])
+ end,
+ Options2 =
+ lists:sort(fun(A,B) ->
+ GetVersionTuple(A) =< GetVersionTuple(B)
+ end,
+ Options1),
+ case Options2 of
+ [Path|_] ->
+ Path;
+ _ ->
+ NextRelToTry =
+ erlang:integer_to_list(erlang:list_to_integer(LookInRel)+1),
+ Find(NextRelToTry)
+ end;
+ false ->
+ ct:fail({could_not_find_dep_anywhere, DepName})
+ end
+ end)(FirstAvailableRel).
+
+find_rel_root(Rel) ->
+ case test_server:find_release(Rel) of
+ not_available ->
+ not_available;
+ OtpRelErl -> filename:dirname(filename:dirname(OtpRelErl))
+ end.
+
+%% Find the absolute paths to RuntimeDeps
+get_paths_to_dependencies(App, RuntimeDeps) ->
+ FirstAvailableOTPRel = first_available_otp_rel(),
+ FirstAvailableRel = erlang:list_to_integer(FirstAvailableOTPRel),
+ DepToOtpVerMap = get_runtime_dep_to_otp_version_map(),
+ lists:foldl(
+ fun(Dep, SoFar) ->
+ case maps:get(Dep, DepToOtpVerMap, false) of
+ false ->
+ ct:fail(io_lib:format(
+ "The dependency ~s for ~p could not be found. "
+ "Have you typed a non-existing version?",
+ [Dep, App]));
+ {latest, Path} ->
+ %% The dependency is in Path (one of the paths returned by code:get_paths())
+ [Path | SoFar];
+ OtpVersionWithDep ->
+ OtpMajorVersionWithDep = get_major_version(OtpVersionWithDep),
+ OtpMajorVersionWithDepInt = erlang:list_to_integer(OtpMajorVersionWithDep),
+ case find_rel_root(OtpMajorVersionWithDep) of
+ not_available when FirstAvailableRel > OtpMajorVersionWithDepInt ->
+ io:format("Warning: Could not find runtime dependency ~p for ~p. "
+ "~p belongs to ~p but ~p is too old to be available on this machine. "
+ "Trying to find the oldest available version of ~p...",
+ [Dep, App, Dep, OtpVersionWithDep, OtpVersionWithDep, Dep]),
+ [get_oldest_available_version_of_dep(Dep) | SoFar];
+ RelDirRoot ->
+ [find_dep_in_rel_dir(Dep, RelDirRoot) | SoFar]
+ end
+ end
+ end,
+ [],
+ RuntimeDeps).
+
+test_app_runtime_deps_versions(AppPath, App, IgnoredUndefinedFunctions) ->
+ %% Get a list of all runtime dependencies for app
+ RuntimeDeps = get_runtime_deps(App),
+ %% Get paths to the found runtime dependencies
+ DepPaths = get_paths_to_dependencies(App, RuntimeDeps),
+ XRefSName = test_app_runtime_deps_versions_server,
+ %% Start xref server and do the test
+ {ok, _} = xref:start(XRefSName, []),
+ ok = xref:set_library_path(XRefSName, DepPaths),
+ Dir = filename:join(AppPath, "ebin"),
+ {ok, _} = xref:add_directory(XRefSName, Dir),
+ {ok, UndefinedFunctions0} = xref:analyze(XRefSName, undefined_functions),
+ xref:stop(XRefSName),
+ %% Filter out undefined functions that we should ignore
+ UndefinedFunctions1 =
+ [F || F <- UndefinedFunctions0,
+ not maps:get(F, IgnoredUndefinedFunctions, false),
+ not maps:get({element(1,F),'_','_'}, IgnoredUndefinedFunctions, false),
+ not maps:get({element(1,F),element(2,F),'_'}, IgnoredUndefinedFunctions, false)],
+ case UndefinedFunctions1 of
+ [] ->
+ ok;
+ UndefinedFunctions ->
+ {error_undefined_functions_in_app, App, UndefinedFunctions}
+ end.
+
+test_runtime_dependencies_versions_rels(IgnoreApps, AppsToIgnoredUndefinedFunctions) ->
+ %% Do for every application:
+ %% 1. Find deps from app file
+ %% 2. Find where the deps are installed
+ %% 3. Run xref tests on the apps with the specified dependencies
+ %% 4. Report error if undefined function
+ Apps0 = [{Path, list_to_atom(AppName)}
+ || {match, [Path, AppName]}
+ <- [re:run(X,"(" ++ code:lib_dir()++"/"++"([^/-]*).*)/ebin",
+ [{capture,[1,2],list},unicode]) || X <- code:get_path()]],
+ Apps = [{Path, App} ||
+ {Path, App} <- Apps0,
+ code:where_is_file(atom_to_list(App) ++ ".app") =/= non_existing],
+ Res = [test_app_runtime_deps_versions(AppPath,
+ App,
+ maps:get(App, AppsToIgnoredUndefinedFunctions, #{})) ||
+ {AppPath, App} <- Apps, not lists:member(App, IgnoreApps)],
+ BadRes = [R || R <- Res, R =/= ok],
+ case BadRes =:= [] of
+ true -> ok;
+ _ ->
+ ct:fail(BadRes)
+ end.
+
+is_development_build() ->
+ {ok, FileContentBin} = file:read_file(get_otp_version_tickets_path()),
+ "DEVELOPMENT" =:= string:trim(erlang:binary_to_list(FileContentBin), both, "\n ").
+
+test_runtime_dependencies_versions(_Config) ->
+ ReleasesDir = "/usr/local/otp/releases",
+ IgnoreApps = [],
+ SocketIgnore = case lists:member(prim_socket, erlang:pre_loaded()) of
+ true -> #{};
+ false ->
+ Ignore = #{{prim_socket,'_','_'} => true,
+ {socket_registry,'_','_'} => true,
+ {prim_net,'_','_'} => true },
+ #{ kernel => Ignore, erts => Ignore }
+ end,
+ AppsToIgnoredUndefinedFunctions =
+ #{eunit =>
+ %% Intentional call to nonexisting function
+ #{{eunit_test, nonexisting_function, 0} => true},
+ diameter =>
+ %% The following functions are optional dependencies for diameter
+ #{{dbg,ctp,0} => true,
+ {dbg,p,2} => true,
+ {dbg,stop_clear,0} => true,
+ {dbg,trace_port,2} => true,
+ {dbg,tracer,2} => true,
+ {erl_prettypr,format,1} => true,
+ {erl_syntax,form_list,1} => true},
+ common_test =>
+ %% ftp:start/0 has been part of the ftp application from
+ %% the beginning so it is unclear why xref report this
+ %% as undefined
+ #{{ftp,start,0} => true}},
+ case {erlang:element(1, os:type()) =:= unix,
+ not is_development_build(),
+ filelib:is_dir(ReleasesDir),
+ filelib:is_file(get_otp_versions_table_path()),
+ first_available_otp_rel() =/= none} of
+ {true, true, true, true, true} ->
+ test_runtime_dependencies_versions_rels(
+ IgnoreApps,
+ maps:merge(AppsToIgnoredUndefinedFunctions, SocketIgnore));
+ {_, _ ,_, false, _} -> {skip,
+ "Could not find the file \"otp_versions.table\". "
+ "Check that the test has been built correctly. "
+ "\"otp_versions.table\" is copied to \"erts/test/otp_SUITE_data\" "
+ "by the makefile \"erts/test/Makefile\""};
+ {_, false , _, _, _} -> {skip,
+ "This test case is designed to run in the Erlang/OTP teams "
+ "test system for nightly tests. The test case depend on that "
+ "app versions have been set correctly by scripts that "
+ "are executed before creating builds for the nightly tests."};
+ {_, _ ,false, _, _} -> {skip, "Can not do the tests without a proper releases dir. "
+ "Check that " ++ ReleasesDir ++ " is set up correctly."};
+ {_, _ , _, _, false} ->
+ PrevRelNr = erlang:list_to_integer(erlang:system_info(otp_release)) - 1,
+ PrevRelNrStr = erlang:integer_to_list(PrevRelNr),
+ {skip,
+ "Seems like the releases dir is not set up correctly. "
+ "Is release " ++ PrevRelNrStr ++ " installed in the releases dir? "
+ "(releases dir = " ++ ReleasesDir ++ ")"};
+ {false, _ ,_, _, _} -> {skip, "This test only runs on Unix systems"}
+ end.
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args3 b/erts/test/otp_SUITE_data/.keep
index e69de29bb2..e69de29bb2 100644
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args3
+++ b/erts/test/otp_SUITE_data/.keep
diff --git a/erts/test/parallel_messages_SUITE.erl b/erts/test/parallel_messages_SUITE.erl
new file mode 100644
index 0000000000..9c5d6b4f28
--- /dev/null
+++ b/erts/test/parallel_messages_SUITE.erl
@@ -0,0 +1,465 @@
+-module(parallel_messages_SUITE).
+
+-export([all/0,
+ suite/0,
+ test_throughput_benchmark/1,
+ test_message_queue_data_switching/1,
+ throughput_benchmark/0,
+ large_throughput_benchmark/0]).
+
+all() -> [test_throughput_benchmark,
+ test_message_queue_data_switching].
+
+suite() ->
+ [{timetrap, {minutes, 90}}].
+
+get_op([{_,O}], _RandNum) ->
+ O;
+get_op([{Prob,O}|Rest], RandNum) ->
+ case RandNum < Prob of
+ true -> O;
+ false -> get_op(Rest, RandNum)
+ end.
+do_op(ProbHelpTab, Operations, Receiver) ->
+ RandNum = rand:uniform(),
+ Op = get_op(ProbHelpTab, RandNum),
+ TheOp = Operations(Op),
+ TheOp(Receiver).
+do_work(WorksDoneSoFar, ProbHelpTab, Operations, Receiver) ->
+ receive
+ stop -> WorksDoneSoFar
+ after
+ 0 -> do_op(ProbHelpTab, Operations, Receiver),
+ do_work(WorksDoneSoFar + 1, ProbHelpTab, Operations, Receiver)
+ end.
+
+-record(parallel_messages_bench_config,
+ {benchmark_duration_ms = 500,
+ recover_time_ms = 500,
+ thread_counts = not_set,
+ nr_of_repeats = 1,
+ report_receive_throughput = [false, true],
+ spawn_opts = [[{message_queue_data, off_heap}]],
+ scenarios =
+ [
+ [
+ {1.0, {message_size, 1}}
+ ],
+ [
+ {1.0, {exit_signal_size, 3}}
+ ],
+ [
+ {0.5, {exit_signal_size, 1}},
+ {0.5, {message_size, 1}}
+ ]
+ ],
+ notify_res_fun = fun(_Name, _Throughput) -> ok end,
+ print_result_paths_fun =
+ fun(ResultPath, _LatestResultPath) ->
+ Comment =
+ io_lib:format("<a href=\"file:///~s\">Result visualization</a>",[ResultPath]),
+ {comment, Comment}
+ end
+ }).
+
+stdout_notify_res(ResultPath, LatestResultPath) ->
+ io:format("Result Location: /~s~n", [ResultPath]),
+ io:format("Latest Result Location: ~s~n", [LatestResultPath]).
+
+
+throughput_benchmark(
+ #parallel_messages_bench_config{
+ benchmark_duration_ms = BenchmarkDurationMs,
+ recover_time_ms = RecoverTimeMs,
+ thread_counts = ThreadCountsOpt,
+ nr_of_repeats = NrOfRepeats,
+ report_receive_throughput = ReportReceiveThroughputList,
+ spawn_opts = SpawnOptsList,
+ scenarios = Scenarios,
+ notify_res_fun = NotifyResFun,
+ print_result_paths_fun = PrintResultPathsFun}) ->
+ NrOfSchedulers = erlang:system_info(schedulers),
+ %Parent = self(),
+ %% Mapping benchmark operation names to their action
+ Operations =
+ fun({message_size, Size}) ->
+ case get(Size) of
+ undefined ->
+ Msg = lists:seq(1, Size),
+ NewSendFun =
+ fun(Receiver) ->
+ Receiver ! Msg
+ end,
+ put(Size, NewSendFun),
+ NewSendFun;
+ SendFun ->
+ SendFun
+ end;
+ ({exit_signal_size, Size} = SigType) ->
+ case get(SigType) of
+ undefined ->
+ Msg = lists:seq(1, Size),
+ NewSendFun =
+ fun(Receiver) ->
+ erlang:exit(Receiver, Msg)
+ end,
+ put(SigType, NewSendFun),
+ NewSendFun;
+ SendFun ->
+ SendFun
+ end;
+ ({message_queue_data_change, off_heap}) ->
+ fun(Receiver) ->
+ Receiver ! off_heap
+ end;
+ ({message_queue_data_change, on_heap}) ->
+ fun(Receiver) ->
+ Receiver ! on_heap
+ end
+ end,
+ %% Helper functions
+ CalculateThreadCounts =
+ fun Calculate([Count|Rest]) ->
+ case Count > NrOfSchedulers of
+ true -> lists:reverse(Rest);
+ false -> Calculate([Count*2,Count|Rest])
+ end
+ end,
+ CalculateOpsProbHelpTab =
+ fun Calculate([{_, OpName}], _) ->
+ [{1.0, OpName}];
+ Calculate([{OpPropability, OpName}|Res], Current) ->
+ NewCurrent = Current + OpPropability,
+ [{NewCurrent, OpName}| Calculate(Res, NewCurrent)]
+ end,
+ RenderScenario =
+ fun R([], StringSoFar) ->
+ StringSoFar;
+ R([{Fraction, Operation}], StringSoFar) ->
+ io_lib:format("~s ~f% ~w",[StringSoFar, Fraction * 100.0, Operation]);
+ R([{Fraction, Operation}|Rest], StringSoFar) ->
+ R(Rest,
+ io_lib:format("~s ~f% ~w, ",[StringSoFar, Fraction * 100.0, Operation]))
+ end,
+ DataHolder =
+ fun DataHolderFun(Data)->
+ receive
+ {get_data, Pid} -> Pid ! {message_bench_data, Data};
+ D -> DataHolderFun([Data,D])
+ end
+ end,
+ DataHolderPid = spawn_link(fun()-> DataHolder([]) end),
+ PrintData =
+ fun (Str, List) ->
+ io:format(Str, List),
+ DataHolderPid ! io_lib:format(Str, List)
+ end,
+ GetData =
+ fun () ->
+ DataHolderPid ! {get_data, self()},
+ receive {message_bench_data, Data} -> Data end
+ end,
+ %% Function that runs a benchmark instance and returns the number
+ %% of operations that were performed and how long time they took
+ %% to perform
+ RunBenchmark =
+ fun({NrOfProcs, Scenario, Duration, SpawnOpts}) ->
+ ProbHelpTab = CalculateOpsProbHelpTab(Scenario, 0),
+ ParentPid = self(),
+ ReceiveFun =
+ fun ReceiveFun(NrOfStops, ReceiveCount) when NrOfStops =:= NrOfProcs ->
+ ParentPid ! {done_nothing_more_to_receive, ReceiveCount};
+ ReceiveFun(NrOfStops, ReceiveCount) ->
+ receive
+ Msg ->
+ case Msg of
+ stop ->
+ ReceiveFun(NrOfStops + 1, ReceiveCount);
+ off_heap ->
+ erlang:process_flag(message_queue_data, off_heap),
+ ReceiveFun(NrOfStops, ReceiveCount + 1);
+ on_heap ->
+ erlang:process_flag(message_queue_data, on_heap),
+ ReceiveFun(NrOfStops, ReceiveCount + 1);
+ _X ->
+ ReceiveFun(NrOfStops, ReceiveCount + 1)
+ end
+ end
+ end,
+ Receiver =
+ spawn_opt(
+ fun() ->
+ process_flag(trap_exit, true),
+ ReceiveFun(0, 0)
+ end,
+ SpawnOpts),
+ Worker =
+ fun() ->
+ receive start -> ok end,
+ WorksDone =
+ do_work(0, ProbHelpTab, Operations, Receiver),
+ ParentPid ! {works_done, WorksDone},
+ Receiver ! stop
+ end,
+ ChildPids =
+ lists:map(fun(_N) -> spawn_link(Worker) end, lists:seq(1, NrOfProcs)),
+ erlang:garbage_collect(),
+ timer:sleep(RecoverTimeMs),
+ lists:foreach(fun(Pid) -> Pid ! start end, ChildPids),
+ timer:sleep(Duration),
+ lists:foreach(fun(Pid) -> Pid ! stop end, ChildPids),
+ TotalWorksDone = lists:foldl(
+ fun(_, Sum) ->
+ receive
+ {works_done, Count} -> Sum + Count
+ end
+ end, 0, ChildPids),
+ {TimeAfterSends, ok} =
+ timer:tc(
+ fun() ->
+ receive
+ {done_nothing_more_to_receive, ReceiveCount} ->
+ %% Sanity check
+ ReceiveCount = TotalWorksDone,
+ ok
+ end
+ end),
+ {Duration + (TimeAfterSends div 1000), TotalWorksDone}
+ end,
+ RunBenchmarkInSepProcess =
+ fun(ParameterTuple) ->
+ P = self(),
+ Results =
+ [begin
+ spawn_link(fun()-> P ! {bench_result, RunBenchmark(ParameterTuple)} end),
+ receive {bench_result, Res} -> Res end
+ end || _ <- lists:seq(1, NrOfRepeats)],
+ {R1, R2} = lists:foldl(fun ({I1, I2}, {A1, A2}) ->
+ {I1 + A1, I2 + A2}
+ end, {0, 0}, Results),
+ {R1 / NrOfRepeats, R2 / NrOfRepeats}
+ end,
+ RunBenchmarkAndReport =
+ fun(ThreadCount,
+ Scenario,
+ Duration,
+ ReportReceive,
+ SpawnOpts) ->
+ {ReceiveTime, NrOfSends} =
+ RunBenchmarkInSepProcess({ThreadCount,
+ Scenario,
+ Duration,
+ SpawnOpts}),
+ Throughput =
+ case ReportReceive of
+ true ->
+ NrOfSends/(ReceiveTime/1000.0);
+ false ->
+ NrOfSends/(Duration/1000.0)
+ end,
+ PrintData("; ~f",[Throughput]),
+ Name = io_lib:format("Scenario: ~w, "
+ "# of Processes: ~w",
+ [Scenario, ThreadCount]),
+ NotifyResFun(Name, Throughput)
+ end,
+ ThreadCounts =
+ case ThreadCountsOpt of
+ not_set ->
+ CalculateThreadCounts([1]);
+ _ -> ThreadCountsOpt
+ end,
+ Version =
+ (fun() ->
+ VersionString = erlang:system_info(system_version),
+ case re:run(VersionString, "\\[(source\\-[^\\]]+)\\]") of
+ {match, [_, {StartPos, Length}]} ->
+ string:slice(VersionString, StartPos, Length);
+ _ ->
+ erlang:system_info(otp_release)
+ end
+ end)(),
+ %% Run the benchmark
+ PrintData("# Each instance of the benchmark runs for ~w seconds:~n", [BenchmarkDurationMs/1000]),
+ PrintData("# The result of a benchmark instance is presented as a number representing~n",[]),
+ PrintData("# the number of operations performed per second:~n~n~n",[]),
+ PrintData("# To plot graphs for the results below:~n",[]),
+ PrintData("# 1. Open \"$ERL_TOP/erts/test/parallel_messages_SUITE_data/visualize_throughput.html\" in a web browser~n",[]),
+ PrintData("# 2. Copy the lines between \"#BENCHMARK STARTED$\" and \"#BENCHMARK ENDED$\" below~n",[]),
+ PrintData("# 3. Paste the lines copied in step 2 to the text box in the browser window opened in~n",[]),
+ PrintData("# step 1 and press the Render button~n~n",[]),
+ PrintData("#BENCHMARK STARTED$~n",[]),
+ %% The following loop runs all benchmark scenarios and prints the results (i.e, operations/second)
+ lists:foreach(
+ fun(SpawnOpts) ->
+ lists:foreach(
+ fun(Scenario) ->
+ lists:foreach(
+ fun(ReportReceiveThroughput) ->
+ PrintData("Scenario: ~s, send_duration=~w ms, ~s, Spawn Options=~w$~n",
+ [case ReportReceiveThroughput of
+ true -> "Receive Throughput";
+ false -> "Send Throughput"
+ end,
+ BenchmarkDurationMs,
+ RenderScenario(Scenario, ""),
+ SpawnOpts]),
+ lists:foreach(
+ fun(ThreadCount) ->
+ PrintData("; ~w",[ThreadCount])
+ end,
+ ThreadCounts),
+ PrintData("$~n",[]),
+ PrintData(Version,[]),
+ lists:foreach(
+ fun(ThreadCount) ->
+ %erlang:display({thread_count, ThreadCount}),
+ RunBenchmarkAndReport(ThreadCount,
+ Scenario,
+ BenchmarkDurationMs,
+ ReportReceiveThroughput,
+ SpawnOpts)
+ end,
+ ThreadCounts),
+ PrintData("$~n",[])
+ end,
+ ReportReceiveThroughputList)
+ end,
+ Scenarios)
+ end,
+ SpawnOptsList),
+ PrintData("~n#BENCHMARK ENDED$~n~n",[]),
+ DataDir = filename:join(filename:dirname(code:which(?MODULE)), "parallel_messages_SUITE_data"),
+ TemplatePath = filename:join(DataDir, "visualize_throughput.html"),
+ {ok, Template} = file:read_file(TemplatePath),
+ OutputData = string:replace(Template, "#bench_data_placeholder", GetData()),
+ OutputPath1 = filename:join(DataDir, "message_bench_result.html"),
+ {{Year, Month, Day}, {Hour, Minute, Second}} = calendar:now_to_datetime(erlang:timestamp()),
+ StrTime = lists:flatten(io_lib:format("~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w",[Year,Month,Day,Hour,Minute,Second])),
+ OutputPath2 = filename:join(DataDir, io_lib:format("message_bench_result_~s.html", [StrTime])),
+ file:write_file(OutputPath1, OutputData),
+ file:write_file(OutputPath2, OutputData),
+ PrintResultPathsFun(OutputPath2, OutputPath1).
+
+
+throughput_benchmark() ->
+ throughput_benchmark(
+ #parallel_messages_bench_config{
+ benchmark_duration_ms = 500,
+ recover_time_ms = 500,
+ thread_counts = not_set,
+ nr_of_repeats = 1,
+ report_receive_throughput = [false, true],
+ spawn_opts = [[{message_queue_data, off_heap}]],
+ scenarios =
+ [
+ [
+ {1.0, {message_size, 1}}
+ ],
+ [
+ {1.0, {exit_signal_size, 3}}
+ ],
+ [
+ {0.5, {exit_signal_size, 1}},
+ {0.5, {message_size, 1}}
+ ]
+ ],
+ notify_res_fun = fun(_Name, _Throughput) -> ok end,
+ print_result_paths_fun =
+ fun(ResultPath, _LatestResultPath) ->
+ Comment =
+ io_lib:format("<a href=\"file:///~s\">Result visualization</a>",[ResultPath]),
+ {comment, Comment}
+ end
+ }).
+
+test_throughput_benchmark(_) ->
+ throughput_benchmark().
+
+large_throughput_benchmark() ->
+ throughput_benchmark(
+ #parallel_messages_bench_config{
+ benchmark_duration_ms = 1000,
+ recover_time_ms = 1000,
+ thread_counts = [1,2,4,8,15,16,31,32,47,48,63,64],
+ nr_of_repeats = 3,
+ report_receive_throughput = [false, true],
+ spawn_opts = [[{message_queue_data, off_heap}]],
+ scenarios =
+ [
+ [
+ {1.0, {message_size, 1}}
+ ],
+ [
+ {1.0, {message_size, 10}}
+ ],
+ [
+ {1.0, {message_size, 100}}
+ ],
+ [
+ {1.0, {message_size, 1000}}
+ ],
+ [
+ {1.0, {exit_signal_size, 1}}
+ ],
+ [
+ {1.0, {exit_signal_size, 10}}
+ ],
+ [
+ {1.0, {exit_signal_size, 100}}
+ ],
+ [
+ {1.0, {exit_signal_size, 1000}}
+ ],
+ [
+ {0.5, {exit_signal_size, 1}},
+ {0.5, {message_size, 1}}
+ ],
+ [
+ {0.5, {exit_signal_size, 10}},
+ {0.5, {message_size, 10}}
+ ],
+ [
+ {0.5, {exit_signal_size, 100}},
+ {0.5, {message_size, 100}}
+ ],
+ [
+ {0.5, {exit_signal_size, 1000}},
+ {0.5, {message_size, 1000}}
+ ]
+ ],
+ notify_res_fun =
+ fun(Name, Throughput) ->
+ io:format("~n~n#Name: ~s Throughput: ~w~n~n", [Name, Throughput])
+ end,
+ print_result_paths_fun =
+ fun stdout_notify_res/2
+ }).
+
+test_message_queue_data_switching(_) ->
+ throughput_benchmark(
+ #parallel_messages_bench_config{
+ benchmark_duration_ms = 100,
+ recover_time_ms = 500,
+ thread_counts = [1,2,4],
+ nr_of_repeats = 1,
+ report_receive_throughput = [true],
+ spawn_opts = [[{message_queue_data, off_heap}]],
+ scenarios =
+ [
+ [
+ {0.499995, {exit_signal_size, 1}},
+ {0.499995, {message_size, 1}},
+ %% About 1 in 100k changes message data type
+ {0.000005, {message_queue_data_change, off_heap}},
+ {0.000005, {message_queue_data_change, on_heap}}
+ ]
+ ],
+ notify_res_fun = fun(_Name, _Throughput) -> ok end,
+ print_result_paths_fun =
+ fun(ResultPath, _LatestResultPath) ->
+ Comment =
+ io_lib:format("<a href=\"file:///~s\">Result visualization</a>",[ResultPath]),
+ {comment, Comment}
+ end
+ }).
diff --git a/erts/test/parallel_messages_SUITE_data/visualize_throughput.html b/erts/test/parallel_messages_SUITE_data/visualize_throughput.html
new file mode 100644
index 0000000000..c4ed94b679
--- /dev/null
+++ b/erts/test/parallel_messages_SUITE_data/visualize_throughput.html
@@ -0,0 +1,304 @@
+<!doctype html>
+<html lang="en">
+
+<!-- %% -->
+<!-- %% %CopyrightBegin% -->
+<!-- %% -->
+<!-- %% Copyright Ericsson AB and Kjell Winblad 1996-2021. All Rights Reserved. -->
+<!-- %% -->
+<!-- %% Licensed under the Apache License, Version 2.0 (the "License"); -->
+<!-- %% you may not use this file except in compliance with the License. -->
+<!-- %% You may obtain a copy of the License at -->
+<!-- %% -->
+<!-- %% http://www.apache.org/licenses/LICENSE-2.0 -->
+<!-- %% -->
+<!-- %% Unless required by applicable law or agreed to in writing, software -->
+<!-- %% distributed under the License is distributed on an "AS IS" BASIS, -->
+<!-- %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
+<!-- %% See the License for the specific language governing permissions and -->
+<!-- %% limitations under the License. -->
+<!-- %% -->
+<!-- %% %CopyrightEnd% -->
+<!-- %% -->
+<!-- %% Author: Kjell Winblad -->
+<!-- %% -->
+
+ <head>
+ <meta charset="utf-8">
+ <title>Message Send/Receive Benchmark Result Viewer</title>
+ </head>
+
+ <body>
+ <div id="insertPlaceholder"></div>
+ <h1>Message Send/Receive Benchmark Result Viewer</h1>
+ <p>
+ This page generates graphs from data produced by the Message Send/Receive Benchmark which is defined in the function <code>parallel_messages_SUITE:test_throughput_benchmark/1</code> (see "<code>$ERL_TOP/erts/test/parallel_messages_SUITE.erl</code>").
+ </p>
+ <p>
+ Note that one can paste results from several benchmark runs into the field below. Results from the same scenario but from different benchmark runs will be relabeled and plotted in the same graph automatically.
+ </p>
+ <p>
+ Note also that that lines can be hidden by clicking on the corresponding label.
+ </p>
+ Paste the generated data in the field below and press the Render button:
+ <br>
+ <textarea id="dataField" rows="4" cols="50">#bench_data_placeholder</textarea>
+ <br>
+ <input type="checkbox" id="throughputPlot" checked> Include Throughput Plot
+ <br>
+ <input type="checkbox" id="betterThanWorstPlot"> Include % More Throughput Than Worst Plot
+ <br>
+ <input type="checkbox" id="worseThanBestPlot"> Include % Less Throughput Than Best Plot
+ <br>
+ <input type="checkbox" id="barPlot"> Bar Plot
+ <br>
+ <input type="checkbox" id="sameSpacing" checked> Same X Spacing Between Points
+ <br>
+ <button id="renderButton" type="button">Render</button>
+
+ <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
+ integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E="
+ crossorigin="anonymous"></script>
+ <script>
+ var loading = false;
+ function toggleLoadingScreen(){
+ if(loading){
+ $("#loading").remove();
+ loading = false;
+ }else{
+ $('<div id="loading">'+
+ '<span style="position: fixed; top: 50%;left: 50%;color: white;"><b>Loading...</b></span>'+
+ '</div>')
+ .css({position: "fixed",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+ 'background-color': "#000",
+ filter:"alpha(opacity=50)",
+ '-moz-opacity':"0.5",
+ '-khtml-opacity': "0.5",
+ opacity: "0.5",
+ 'z-index': "10000"})
+ .appendTo(document.body);
+ loading = true;
+
+ }
+ }
+ //Start loading screen before downloading plotly which is quite large
+ toggleLoadingScreen();
+ </script>
+ <script src="https://cdn.plot.ly/plotly-1.5.0.min.js"></script>
+ <script>
+ String.prototype.replaceAll = function(search, replacement) {
+ var target = this;
+ return target.split(search).join(replacement);
+ };
+ String.prototype.myTrim = function() {
+ var target = this;
+ return target.replace(/^\s+|\s+$/g, '');
+ };
+ function plotGraph(lines, sameSpacing, barPlot, prefix) {
+ var xvals = null;
+ var data = [];
+ while(lines.length > 0 &&
+ (lines[0].myTrim() == "" ||
+ lines[0].myTrim().indexOf(";") !== -1)){
+ var line = lines.shift().myTrim();
+ if(line == "" || line.startsWith("#")){
+ continue;
+ } else if(line.startsWith(";")) {
+ xvals = line.split(";")
+ xvals.shift(); // Remove first
+ xvals = $.map(xvals, function (i){
+ if(sameSpacing){
+ return "_"+i.myTrim();
+ }else{
+ return parseInt(i.myTrim(), 10);
+ }
+ });
+ }else{
+ line = line.split(";")
+ var label = prefix + line.shift().myTrim();
+ var yvals = $.map(line, function (i){
+ return parseFloat(i.myTrim(), 10);
+ });
+ var trace = {
+ x: xvals,
+ y: yvals,
+ mode: 'lines+markers',
+ name: label
+ };
+ if(barPlot){
+ trace['type'] = "bar";
+ }
+ data.push(trace);
+ }
+
+ }
+ return data;
+ }
+ function toCompareData(dataParam, compareWithWorst) {
+ var data = $.extend(true, [], dataParam);
+ var worstSoFarMap = {};
+ var defaultSoFarValue = compareWithWorst ? Number.MAX_VALUE : Number.MIN_VALUE;
+ function getWorstBestSoFar(x){
+ return worstSoFarMap[x] === undefined ? defaultSoFarValue : worstSoFarMap[x];
+ }
+ function setWorstBestSoFar(x, y){
+ return worstSoFarMap[x] = y;
+ }
+ function lessOrGreaterThan(n1, n2){
+ return compareWithWorst ? n1 < n2 : n1 > n2;
+ }
+ $.each(data, function(i, allResConfig) {
+ $.each(allResConfig.y, function(index, res) {
+ var xName = allResConfig.x[index];
+ if(lessOrGreaterThan(res, getWorstBestSoFar(xName))){
+ setWorstBestSoFar(xName, res);
+ }
+ });
+ });
+ $.each(data, function(i, allResConfig) {
+ $.each(allResConfig.y, function(index, res) {
+ var xName = allResConfig.x[index];
+ if(compareWithWorst){
+ allResConfig.y[index] = ((res / getWorstBestSoFar(xName))-1.0) * 100;
+ }else{
+ allResConfig.y[index] = (1.0 -(res / getWorstBestSoFar(xName))) * 100;
+ }
+ });
+ });
+ return data;
+ }
+ function toBetterThanWorstData(data){
+ return toCompareData(data, true);
+ }
+ function toWorseThanBestData(data){
+ return toCompareData(data, false);
+ }
+ function plotGraphs(){
+ var insertPlaceholder = $("#insertPlaceholder");
+ var sameSpacing = $('#sameSpacing').is(":checked");
+ var barPlot = $('#barPlot').is(":checked");
+ var throughputPlot = $('#throughputPlot').is(":checked");
+ var betterThanWorstPlot = $('#betterThanWorstPlot').is(":checked");
+ var worseThanBestPlot = $('#worseThanBestPlot').is(":checked");
+ var lines = $("#dataField").val();
+ $('.showCheck').each(function() {
+ var item = $(this);
+ if(!item.is(":checked")){
+ lines = lines.replaceAll(item.val(), "#"+item.val())
+ }
+ });
+ lines = lines.split("$");
+ var nrOfGraphs = 0;
+ var scenarioDataMap = {};
+ var scenarioNrOfVersionsMap = {};
+ var scenarioList = [];
+ while(lines.length > 0){
+ var line = lines.shift().myTrim();
+ if(line == ""){
+ continue;
+ } else if(line.startsWith("Scenario:")) {
+ nrOfGraphs = nrOfGraphs + 1;
+ var name = line;
+ if(scenarioDataMap[name] === undefined){
+ scenarioDataMap[name] = [];
+ scenarioNrOfVersionsMap[name] = 0;
+ scenarioList.push(line);
+ }
+ scenarioNrOfVersionsMap[name] = scenarioNrOfVersionsMap[name] + 1;
+ var prefix = undefined;
+ if(scenarioNrOfVersionsMap[name] === 1){
+ prefix = "";
+ }else{
+ prefix = "Ver: " + scenarioNrOfVersionsMap[name] + " ";
+ }
+ scenarioDataMap[name] =
+ scenarioDataMap[name].concat(
+ plotGraph(lines, sameSpacing, barPlot, prefix));
+ }
+ }
+ var nrOfGraphs = 0;
+ function plotScenario(name, plotType) {
+ var data = scenarioDataMap[name];
+ var yAxisTitle = undefined;
+ var graphId = "graph" + nrOfGraphs;
+ var fullscreenButtonid = "fullscreenButton" + nrOfGraphs;
+ nrOfGraphs = nrOfGraphs + 1;
+ $("<div class='added' id='" + graphId + "'>")
+ .insertBefore(insertPlaceholder);
+ $("<button type='button' class='added' id='" + fullscreenButtonid + "'>Fill screen</button>")
+ .insertBefore(insertPlaceholder);
+ $("<span class='added'><br><hr><br></span>")
+ .insertBefore(insertPlaceholder);
+ if (plotType === 'throughput') {
+ yAxisTitle = 'Operations/Second';
+ } else if (plotType === 'better_than_worst') {
+ yAxisTitle = '% More Throughput Than Worst';
+ data = toBetterThanWorstData(data);
+ } else {
+ yAxisTitle = '% Less Throughput Than Best';
+ data = toWorseThanBestData(data);
+ }
+ var layout = {
+ title: name,
+ xaxis: {
+ title: '# of Processes'
+ },
+ yaxis: {
+ title: yAxisTitle
+ }
+ };
+ $("#" + fullscreenButtonid).click(
+ function () {
+ $('#' + graphId).replaceWith(
+ $("<div class='added' id='" + graphId + "'>"));
+ layout = $.extend({}, layout, {
+ width: $(window).width() - 40,
+ height: $(window).height() - 40
+ });
+ Plotly.newPlot(graphId, data, layout);
+ });
+ Plotly.newPlot(graphId, data, layout);
+ }
+ $.each(scenarioList,
+ function (index, name) {
+ if (throughputPlot) {
+ plotScenario(name, 'throughput');
+ }
+ if (betterThanWorstPlot) {
+ plotScenario(name, 'better_than_worst');
+ }
+ if (worseThanBestPlot) {
+ plotScenario(name, 'worse_than_best');
+ }
+ });
+ }
+ $(document).ready(function(){
+ $('#renderButton').click(
+ function(){
+ toggleLoadingScreen();
+ setTimeout(function(){
+ try {
+ $( ".added" ).remove();
+ plotGraphs();
+ toggleLoadingScreen();
+ } catch(e){
+ toggleLoadingScreen();
+ console.log(e);
+ alert("Error happened when parsing data.\n" +
+ "See console for more info");
+ }
+ }, 10);
+ });
+ setTimeout(function(){
+ $( ".added" ).remove();
+ plotGraphs();
+ toggleLoadingScreen();
+ }, 10);
+ });
+ </script>
+ </body>
+</html>
diff --git a/erts/test/upgrade_SUITE.erl b/erts/test/upgrade_SUITE.erl
index 3a0e4e1600..9c26852e00 100644
--- a/erts/test/upgrade_SUITE.erl
+++ b/erts/test/upgrade_SUITE.erl
@@ -20,7 +20,7 @@
-compile(export_all).
--compile(r21).
+-compile(r22).
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
diff --git a/erts/test/z_SUITE.erl b/erts/test/z_SUITE.erl
index 18a42f7c28..d6120061db 100644
--- a/erts/test/z_SUITE.erl
+++ b/erts/test/z_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
-include_lib("kernel/include/file.hrl").
--record(core_search_conf, {search_dir,
+-record(core_search_conf, {db_top_dir,
+ search_dir,
extra_search_dir,
cerl,
file,
@@ -113,7 +114,8 @@ core_search_conf(RunByTS, DBTop, XDir) ->
_ -> XDir
end
end,
- #core_search_conf{search_dir = SearchDir,
+ #core_search_conf{db_top_dir = DBTop,
+ search_dir = SearchDir,
extra_search_dir = XSearchDir,
cerl = find_cerl(DBTop),
file = os:find_executable("file"),
@@ -326,11 +328,59 @@ core_file_search(#core_search_conf{search_dir = Base,
case {RunByTS, ICores, FCores} of
{true, [], []} -> ok;
{true, _, []} -> {comment, Res};
- {true, _, _} -> ct:fail(Res);
- _ -> Res
+ {true, _, _} ->
+ docker_export_otp_src(Conf),
+ ct:fail(Res);
+ _ ->
+ Res
end
end.
+docker_export_otp_src(#core_search_conf{db_top_dir = DbTop}) ->
+ %% If this is a docker run, export the otp_src directory
+ %% to not get lost when the docker image is purged.
+ try
+ case {is_dir(DbTop), is_dir("/daily_build/otp_src/erts")} of
+ {true, true} ->
+ %% Stolen from get_otp_src script.
+ %% Basically it's a recursive copy of otp_src dir
+ %% with preserved permissions, etc.
+ run("cd /daily_build && "
+ "tar -cf - otp_src | (cd "++DbTop++" && tar -xpf -)"),
+ OtpSrc = DbTop ++ "/otp_src",
+ run("cd " ++ OtpSrc ++ "/erts && "
+ "ERL_TOP=" ++ OtpSrc ++ " make local_setup"),
+ io:format("otp_src directory exported from docker image");
+ _ ->
+ ok
+ end
+ catch
+ C:E:S ->
+ io:format("Failed to export otp_src directory:"
+ "Exception: ~p\nReason: ~p\nStack: ~p\n",
+ [C, E, S])
+ end.
+
+run(Cmd) ->
+ Options = [binary, exit_status,stderr_to_stdout,{line,4096}],
+ Port = open_port({spawn,"sh -c \"" ++ Cmd ++ "\""}, Options),
+ run_loop(Cmd, Port, []).
+
+run_loop(Cmd, Port, Output) ->
+ receive
+ {Port, {exit_status,0}} ->
+ lists:reverse(Output);
+ {Port, {exit_status,Status}} ->
+ io:format("Failed command (~p): ~p\nOutput: ~p\n", [Status, Cmd, Output]),
+ error(bailout);
+ {Port, {data,{eol,Bin}}} ->
+ run_loop(Cmd, Port, [Bin|Output]);
+ Msg ->
+ io:format("Unexpected message: ~p\nCommand was: ~p\n", [Msg, Cmd]),
+ error(bailout)
+ end.
+
+
win32_search(RunByTS, DBTop) ->
case os:getenv("WSLENV") of
false when RunByTS ->
diff --git a/erts/vsn.mk b/erts/vsn.mk
index a6515440d4..c9cabd73d4 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 12.3.2
+VSN = 13.2
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/asn1/c_src/Makefile b/lib/asn1/c_src/Makefile
index 8fb3360f83..82a6b6e87a 100644
--- a/lib/asn1/c_src/Makefile
+++ b/lib/asn1/c_src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2021. All Rights Reserved.
+# Copyright Ericsson AB 2002-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -99,7 +99,8 @@ _create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
opt: $(NIF_SHARED_OBJ_FILE)
-debug: opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
static_lib: $(NIF_LIB_FILE)
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index 0258f7fbd2..8dc0dfedcf 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -228,7 +228,7 @@ static int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
case 30:
/* If we call the following bytes, in the buffer in_ptr points at,
- By1,By2,Rest then Rest is the value that will be transfered to
+ By1,By2,Rest then Rest is the value that will be transferred to
the completed buffer. By1 tells how many of the rightmost bits in
Rest that should not be used. By2 is the length of Rest in bytes.*/
in_unused = (int) *(++in_ptr);
@@ -245,7 +245,7 @@ static int per_complete(ErlNifBinary *out_binary, unsigned char *in_buf,
case 31:
/* If we call the following bytes, in the buffer in_ptr points at,
- By1,By2,By3,Rest then Rest is the value that will be transfered to
+ By1,By2,By3,Rest then Rest is the value that will be transferred to
the completed buffer. By1 tells how many of the rightmost bits in
Rest that should not be used. By2 and By3 is the length of
Rest in bytes.*/
@@ -834,7 +834,7 @@ static int per_insert_octets_except_unused(int no_bytes, unsigned char **input_p
* List is like: [{TagNo,Value},{TagNo,Value},...]
* Rest is a binary, i.e. the undecoded part of the buffer. Most often Rest
* is the empty binary.
- * If some error occured during the decoding of the in_buf an error is returned.
+ * If some error occurred during the decoding of the in_buf an error is returned.
*/
static int ber_decode_begin(ErlNifEnv* env, ERL_NIF_TERM *term, unsigned char *in_buf,
int in_buf_len, unsigned int *err_pos) {
@@ -1087,7 +1087,7 @@ static int ber_encode(ErlNifEnv *env, ERL_NIF_TERM term, mem_chunk_t **curr, uns
}
}
- // We need atleast 5 bytes to encode the next tlv
+ // We need at least 5 bytes to encode the next tlv
if (ber_check_memory(curr, 3))
return ASN1_ERROR;
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml
index e4c5a2a3ee..7b38499d48 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>2020</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -83,7 +83,7 @@
legacy_bit_string | legacy_erlang_types |
noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} |
asn1config | undec_rest | no_ok_wrapper |
- {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v>
+ {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors | deterministic</v>
<v>OldOption = ber | per</v>
<v>Reason = term()</v>
<v>Prefix = string()</v>
@@ -346,6 +346,11 @@ File3.asn</pre>
<item>
<p>Causes warnings to be treated as errors.</p>
</item>
+ <tag><c>deterministic</c></tag>
+ <item>
+ <p>Causes all non-deterministic options to be stripped from the
+ -asn1_info() attribute.</p>
+ </item>
</taglist>
<p>Any more option that is applied is passed to
the final step when the generated <c>.erl</c> file is compiled.
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index 257d3bcc80..b39c5c50a9 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,74 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 5.0.21</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>For the <c>per</c> and <c>uper</c> ASN.1 encoding
+ rules, encoding and decoding the <c>SEQUENCE OF</c> and
+ <c>SET OF</c> constructs with 16384 items or more is now
+ supported.</p>
+ <p>
+ Own Id: OTP-18245 Aux Id: ERIERL-859 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.20</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.19</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The atom <c>maybe</c> has been quoted in the source
+ code.</p>
+ <p>
+ Own Id: OTP-17980</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Asn1 5.0.18.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>For the <c>per</c> and <c>uper</c> ASN.1 encoding
+ rules, encoding and decoding the <c>SEQUENCE OF</c> and
+ <c>SET OF</c> constructs with 16384 items or more is now
+ supported.</p>
+ <p>
+ Own Id: OTP-18245 Aux Id: ERIERL-859 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0.18</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -343,7 +411,7 @@
decoding a recursively enclosed term the length was not
propagated to that term decoding, so if the length of the
enclosed term was longer than the enclosing that error
- was not dectected</p> <p>A hard coded C stack limitation
+ was not detected</p> <p>A hard coded C stack limitation
for decoding recursive ASN.1 terms has been introduced.
This is currently set to 8 kWords giving a nesting depth
of about 1000 levels. Deeper terms can not be decoded,
@@ -405,7 +473,7 @@
<item>
<p>
Compiling an ASN.1 module using the option {n2n,
- EnumTypeName} when EnumTypeName contains a hypen like for
+ EnumTypeName} when EnumTypeName contains a hyphen like for
example Cause-Misc caused syntax errors when compiling
the generated Erlang code. This is now corrected.</p>
<p>
@@ -1060,7 +1128,7 @@
<item>
<p>The ASN.1 compiler will now always include necessary
run-time functions in the generated Erlang modules
- (except for <c>asn1rt_nif</c> which is still neeeded). If
+ (except for <c>asn1rt_nif</c> which is still needed). If
the option '<c>inline</c>' is used the ASN.1 compiler
will generate a warning. But if
'<c>{inline,OutputFile}</c>' is use, the ASN.1 compiler
diff --git a/lib/asn1/examples/ecn_internaldoc.txt b/lib/asn1/examples/ecn_internaldoc.txt
index 71e2b7a2f1..909adc6fe8 100644
--- a/lib/asn1/examples/ecn_internaldoc.txt
+++ b/lib/asn1/examples/ecn_internaldoc.txt
@@ -27,7 +27,7 @@ enable the use of ECN in the OTP ASN1 compiler.
- Unaligned PER backend. Often seems the unaligned PER encoding
as the prefferred main method in ECN applications. One of the
goals with ECN is to use less space for encoding to decrease
- the use of bandwith in transmission. This goal is highly
+ the use of bandwidth in transmission. This goal is highly
supported by unaligned PER.
diff --git a/lib/asn1/examples/encode_decode_formats.txt b/lib/asn1/examples/encode_decode_formats.txt
index 62774cf13b..5b5748c196 100644
--- a/lib/asn1/examples/encode_decode_formats.txt
+++ b/lib/asn1/examples/encode_decode_formats.txt
@@ -13,4 +13,4 @@ per_bin, optimize | binary | binary |
-iolist: deep list with binaries and lists as componets \ No newline at end of file
+iolist: deep list with binaries and lists as components \ No newline at end of file
diff --git a/lib/asn1/notes.html b/lib/asn1/notes.html
index c7da5496c8..9e3feefef7 100644
--- a/lib/asn1/notes.html
+++ b/lib/asn1/notes.html
@@ -52,7 +52,7 @@
<li>An error due to unchecked referenced imported type resulted
in missing tag in some table constraint cases. This error is
- now corrected. Error occured during decode in
+ now corrected. Error occurred during decode in
<c>ber_bin optimized</c> version.
(Own Id: OTP-5022)<p>
</li>
@@ -103,7 +103,7 @@
</li>
<li>
- Object Identifier values with two components and teh first was a
+ Object Identifier values with two components and the first was a
value reference failed due to parsing conflicts. Now it is
corrected.
(Own Id: OTP-4895)<p>
@@ -195,12 +195,12 @@
<ul>
<li>
- The <c>{internal_error,...,{ unrecognized_type,...}}</c> error occuring for a SET type when compiling with options <c>[ber_bin,optimize,der]</c> is now corrected.
+ The <c>{internal_error,...,{ unrecognized_type,...}}</c> error occurring for a SET type when compiling with options <c>[ber_bin,optimize,der]</c> is now corrected.
(Own Id: OTP-4866)<p>
</li>
<li>
- False encode of BIT STRING in PER (per_bin,optimize) is fixed. The error occured when there was a type like BIT STRING (SIZE(C)) and C > 16.
+ False encode of BIT STRING in PER (per_bin,optimize) is fixed. The error occurred when there was a type like BIT STRING (SIZE(C)) and C > 16.
(Own Id: OTP-4869)<p>
</li>
@@ -222,7 +222,7 @@
</li>
<li>
- Bug causing duplicated fuction definitions using exclusive decode is removed.<br>
+ Bug causing duplicated function definitions using exclusive decode is removed.<br>
(Own Id: OTP-4833)<p>
</li>
diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile
index 60a2020dbf..9e13d02c8a 100644
--- a/lib/asn1/src/Makefile
+++ b/lib/asn1/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2020. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -102,13 +102,19 @@ ERL_COMPILE_FLAGS += \
-I$(ERL_TOP)/lib/stdlib \
-Werror
-YRL_FLAGS =
+ifeq ($(ERL_DETERMINISTIC),yes)
+ YRL_FLAGS = +deterministic
+ DETERMINISM_FLAG = +deterministic
+else
+ YRL_FLAGS =
+ DETERMINISM_FLAG =
+endif
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
@@ -182,10 +188,10 @@ asn1ct_rtt.erl: prepare_templates.$(EMULATOR) $(RT_TEMPLATES_TARGET)
$(RT_TEMPLATES_TARGET)
prepare_templates.$(EMULATOR): prepare_templates.erl
- $(V_ERLC) prepare_templates.erl
+ $(V_ERLC) $(DETERMINISM_FLAG) prepare_templates.erl
asn1rtt_%.$(EMULATOR): asn1rtt_%.erl
- $(V_ERLC) +debug_info $<
+ $(V_ERLC) +debug_info $(DETERMINISM_FLAG) $<
$(EVAL_CT_MODULES:%=%.erl): prepare_templates.$(EMULATOR) \
$(EBIN)/asn1ct_rtt.$(EMULATOR) \
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index b8cc102654..de10339c41 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -394,7 +394,7 @@ remove_name_collisions(Modules) ->
remove_name_collisions2(Modules,[]).
%% For each definition in the first module in module list, find
-%% all definitons with same name and rename both definitions in
+%% all definitions with same name and rename both definitions in
%% the first module and in rest of modules
remove_name_collisions2([M|Ms],Acc) ->
TypeOrVal = M#module.typeorval,
@@ -721,7 +721,7 @@ save_automatic_tagged_types([_M|Ms]) ->
%% remove_in_set_imports/3 :
%% input: list with tuples of each module's imports and module name
%% respectively.
-%% output: one list with same format but each occured import from a
+%% output: one list with same format but each occurred import from a
%% module in the input set (IMNameL) is removed.
remove_in_set_imports([{{imports,ImpL},_ModName}|Rest],InputMNameL,Acc) ->
NewImpL = remove_in_set_imports1(ImpL,InputMNameL,[]),
@@ -1454,12 +1454,12 @@ special_decode_prepare_1(#gen{options=Options}=Gen, M) ->
%% create_partial_inc_decode_gen_info/2
%%
-%% Creats a list of tags out of the information in TypeNameList that
+%% Creates a list of tags out of the information in TypeNameList that
%% tells which value will be incomplete decoded, i.e. each end
%% component/type in TypeNameList. The significant types/components in
%% the path from the toptype must be specified in the
%% TypeNameList. Significant elements are all constructed types that
-%% branches the path to the leaf and the leaf it selfs.
+%% branches the path to the leaf and the leaf it self.
%%
%% Returns a list of elements, where an element may be one of
%% mandatory|[opt,Tag]|[bin,Tag]. mandatory correspond to a mandatory
@@ -1621,7 +1621,7 @@ partial_inc_dec_toptype(_) ->
throw({error,{"no top type found for partial incomplete decode"}}).
-%% Creats a list of tags out of the information in TypeList and Types
+%% Creates a list of tags out of the information in TypeList and Types
%% that tells which value will be decoded. Each constructed type that
%% is in the TypeList will get a "choosen" command. Only the last
%% type/component in the TypeList may be a primitive type. Components
diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl
index 16c9292012..12db184b4e 100644
--- a/lib/asn1/src/asn1ct_check.erl
+++ b/lib/asn1/src/asn1ct_check.erl
@@ -695,7 +695,7 @@ check_object(S,_ObjDef,#'Object'{classname=ClassRef,def=ObjectDef}) ->
{po,{object,DefObj},ArgsList} ->
{_,Object} = get_referenced_type(S,DefObj),%DefObj is a
%%#'Externalvaluereference' or a #'Externaltypereference'
- %% Maybe this call should be catched and in case of an exception
+ %% Maybe this call should be caught and in case of an exception
%% a not initialized parameterized object should be returned.
instantiate_po(S,ClassDef,Object,ArgsList);
{pv,{simpledefinedvalue,ObjRef},ArgList} ->
@@ -1170,7 +1170,7 @@ gen_incl1(_,_,[]) ->
gen_incl1(S,Fields,[C|CFields]) ->
case element(1,C) of
typefield ->
- true; %% should check that field is OPTIONAL or DEFUALT if
+ true; %% should check that field is OPTIONAL or DEFAULT if
%% the object lacks this field
objectfield ->
case lists:keysearch(element(2,C),1,Fields) of
@@ -2409,7 +2409,7 @@ normalize_s_of(SorS,S,Value,Type,NameList)
%% character string list case
normalize_restrictedstring(S,[H|T],CType) when is_list(H);is_tuple(H) ->
[normalize_restrictedstring(S,H,CType)|normalize_restrictedstring(S,T,CType)];
-%% character sting case
+%% character string case
normalize_restrictedstring(_S,CString,_) when is_list(CString) ->
CString;
%% definedvalue case or argument in a parameterized type
@@ -2816,7 +2816,7 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) ->
inlined=yes};
#'ObjectClassFieldType'{classname=ClRef0}=OCFT0 ->
- %% this case occures in a SEQUENCE when
+ %% this case occurs in a SEQUENCE when
%% the type of the component is a ObjectClassFieldType
ClRef = match_parameter(S, ClRef0),
OCFT = OCFT0#'ObjectClassFieldType'{classname=ClRef},
@@ -3427,10 +3427,10 @@ check_componentrelation(S, {objectset,Opos,Objset0}, Id) ->
%%% creating sets, and maintained by the intersection and union
%%% operators.
%%%
-%%% Example of invalid set representaions:
+%%% Example of invalid set representations:
%%%
%%% [{range,0,10},{range,5,10}] %Overlapping ranges
-%%% [{range,0,5},{range,6,10}] %Adjancent ranges
+%%% [{range,0,5},{range,6,10}] %Adjacent ranges
%%% [{range,10,20},{a_range,100}] %Not sorted
%%%
@@ -4388,7 +4388,7 @@ check_sequence(S,Type,Comps) ->
%% type
{CRelInf,NewComps2} = componentrelation_leadingattr(S,NewComps),
- %% CompListWithTblInf has got a lot unecessary info about
+ %% CompListWithTblInf has got a lot unnecessary info about
%% the involved class removed, as the class of the object
%% set.
CompListWithTblInf = get_tableconstraint_info(S,Type,NewComps2),
@@ -5183,7 +5183,7 @@ any_component_relation(_,[],_,_,Acc) ->
%% evaluate_atpath/4 finds out whether the at notation refers to the
%% search level. The list of referenced names in the AtNot list shall
%% begin with a name that exists on the level it refers to. If the
-%% found AtPath is refering to the same sub-branch as the simple table
+%% found AtPath is referring to the same sub-branch as the simple table
%% has, then there shall not be any leading attribute info on this
%% level.
evaluate_atpath(_,[],Cnames,{innermost,AtPath=[Ref|_Refs]}) ->
@@ -5354,7 +5354,7 @@ innertype_comprel1(S,T = #type{def=Def,constraint=Cons,tablecinf=TCI},Path) ->
case lists:keyfind(componentrelation, 1, Cons) of
{_,{_,_,ObjectSet},AtList} ->
%% This AtList must have an "outermost" at sign to be
- %% relevent here.
+ %% relevant here.
[{_,AL=[#'Externalvaluereference'{value=_Attr}|_R1]}|_R2]
= AtList,
ClassDef = get_ObjectClassFieldType_classdef(S,Def),
diff --git a/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl b/lib/asn1/src/asn1ct_constructed_ber_bin_v2.erl
index 35cf9691c7..8468010726 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-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -463,8 +463,8 @@ gen_decode_set(Gen, Typename, #type{}=D) ->
emit(["SetFun = fun(FunTlv) ->", nl]),
emit(["case FunTlv of ",nl]),
NextNum = gen_dec_set_cases(Gen, Typename, CompList, 1),
- emit([indent(6), {curr,else}," -> ",nl,
- indent(9),"{",NextNum,", ",{curr,else},"}",nl]),
+ emit([indent(6), {curr,'else'}," -> ",nl,
+ indent(9),"{",NextNum,", ",{curr,'else'},"}",nl]),
emit([indent(3),"end",nl]),
emit([indent(3),"end,",nl]),
@@ -906,18 +906,18 @@ gen_dec_choice(Erules,TopType, _ChTag, CompList, Ext) ->
asn1ct_name:new(choTags),
asn1ct_name:new(res),
gen_dec_choice_cases(Erules,TopType,CompList),
- emit([indent(6), {curr,else}," -> ",nl]),
+ emit([indent(6), {curr,'else'}," -> ",nl]),
case Ext of
noext ->
emit([indent(9),"exit({error,{asn1,{invalid_choice_tag,",
- {curr,else},"}}})",nl]);
+ {curr,'else'},"}}})",nl]);
_ ->
emit([indent(9),"{asn1_ExtAlt,",
- {call,ber,ber_encode,[{curr,else}]},"}",nl])
+ {call,ber,ber_encode,[{curr,'else'}]},"}",nl])
end,
emit([indent(3),"end",nl]),
asn1ct_name:new(tag),
- asn1ct_name:new(else).
+ asn1ct_name:new('else').
gen_dec_choice_cases(_Erules,_TopType, []) ->
ok;
diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl
index aff383479b..26c19c8006 100644
--- a/lib/asn1/src/asn1ct_constructed_per.erl
+++ b/lib/asn1/src/asn1ct_constructed_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -730,23 +730,55 @@ gen_decode_sof(Erules, Typename, SeqOrSetOf, #type{}=D) ->
do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D),
emit([".",nl,nl]).
-do_gen_decode_sof(Erules, Typename, SeqOrSetOf, D) ->
+do_gen_decode_sof(Erules, TypeName, SeqOrSetOf, D) ->
+ case asn1ct_imm:effective_constraint(bitstring, D#type.constraint) of
+ no ->
+ %% Could be fragmented.
+ do_gen_decode_fragmented(Erules, TypeName, SeqOrSetOf, D);
+ SizeConstraint ->
+ do_gen_decode_sof_plain(Erules, TypeName, SeqOrSetOf, D, SizeConstraint)
+ end.
+
+do_gen_decode_fragmented(Erules, TypeName, SeqOrSetOf, D) ->
{_SeqOrSetOf,ComponentType} = D#type.def,
- SizeConstraint = asn1ct_imm:effective_constraint(bitstring,
- D#type.constraint),
- ObjFun =
- case D#type.tablecinf of
- [{objfun,_}|_R] ->
- ", ObjFun";
- _ ->
- ""
- end,
+ ObjFun = obj_fun_arg(D),
+ Key = erlang:md5(term_to_binary({fragmented,TypeName,SeqOrSetOf,ComponentType})),
+ Gen = fun(_Fd, Name) ->
+ do_gen_dec_fragmented_1(Erules, Name, TypeName,
+ SeqOrSetOf, ComponentType, D)
+ end,
+ F = asn1ct_func:call_gen("dec_components", Key, Gen),
+ emit([{asis,F}, "(Bytes", ObjFun,", [])"]).
+
+do_gen_dec_fragmented_1(Erules, Name, TypeName, SeqOrSetOf, ComponentType, D) ->
+ ObjFun = obj_fun_arg(D),
+ emit([{asis,Name}, "(Bytes", ObjFun, ", Acc) ->", nl]),
+ {Num,Buf} = gen_decode_length(no, Erules),
+ Key = erlang:md5(term_to_binary({TypeName,SeqOrSetOf,ComponentType})),
+ Gen = fun(_Fd, Name2) ->
+ gen_decode_sof_components(Erules, Name2,
+ TypeName, SeqOrSetOf,
+ ComponentType, false)
+ end,
+ F = asn1ct_func:call_gen("dec_fragment", Key, Gen),
+ emit([",",nl,
+ "{Acc1,Buf1} = ",
+ {asis,F}, "(", Num, ", ", Buf, ObjFun, ", Acc),",nl]),
+ emit(["if ",Num," >= 16384 ->",nl,
+ {asis,Name},"(Buf1", ObjFun, ", Acc1);",nl,
+ "true ->",nl,
+ "{lists:reverse(Acc1),Buf1}",nl,
+ "end.",nl]).
+
+do_gen_decode_sof_plain(Erules, TypeName, SeqOrSetOf, D, SizeConstraint) ->
+ {_SeqOrSetOf,ComponentType} = D#type.def,
+ ObjFun = obj_fun_arg(D),
{Num,Buf} = gen_decode_length(SizeConstraint, Erules),
- Key = erlang:md5(term_to_binary({Typename,SeqOrSetOf,ComponentType})),
+ Key = erlang:md5(term_to_binary({TypeName,SeqOrSetOf,ComponentType})),
Gen = fun(_Fd, Name) ->
gen_decode_sof_components(Erules, Name,
- Typename, SeqOrSetOf,
- ComponentType)
+ TypeName, SeqOrSetOf,
+ ComponentType, true)
end,
F = asn1ct_func:call_gen("dec_components", Key, Gen),
emit([",",nl,
@@ -759,16 +791,16 @@ gen_decode_length(Constraint, Erule) ->
Imm = asn1ct_imm:per_dec_length(Constraint, true, is_aligned(Erule)),
asn1ct_imm:dec_slim_cg(Imm, "Bytes").
-gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont) ->
- {ObjFun,ObjFun_Var} =
- case Cont#type.tablecinf of
- [{objfun,_}|_R] ->
- {", ObjFun",", _"};
- _ ->
- {"",""}
- end,
- emit([{asis,Name},"(0, Bytes",ObjFun_Var,", Acc) ->",nl,
- "{lists:reverse(Acc),Bytes};",nl]),
+gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont, Reverse) ->
+ ObjFun = obj_fun_arg(Cont),
+ ObjFunPat = obj_fun_pat(Cont),
+ emit([{asis,Name},"(0, Bytes",ObjFunPat,", Acc) ->",nl]),
+ case Reverse of
+ true ->
+ emit(["{lists:reverse(Acc),Bytes};",nl]);
+ false ->
+ emit(["{Acc,Bytes};",nl])
+ end,
emit([{asis,Name},"(Num, Bytes",ObjFun,", Acc) ->",nl,
"{Term,Remain} = "]),
Constructed_Suffix = asn1ct_gen:constructed_suffix(SeqOrSetOf,
@@ -794,6 +826,15 @@ gen_decode_sof_components(Erule, Name, Typename, SeqOrSetOf, Cont) ->
end,
emit([{asis,Name},"(Num-1, Remain",ObjFun,", [Term|Acc]).",nl]).
+obj_fun_arg(#type{tablecinf=[{objfun,_}|_]}) ->
+ ", ObjFun";
+obj_fun_arg(#type{}) ->
+ "".
+
+obj_fun_pat(#type{tablecinf=[{objfun,_}|_]}) ->
+ ", _";
+obj_fun_pat(#type{}) ->
+ "".
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% General and special help functions (not exported)
diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index f759f6783f..cc1a33149c 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -264,7 +264,7 @@ gen_partial_inc_dec_refed_funcs(Rtmod, #gen{erule=ber}=Gen) ->
pgen_partial_dec(_Rtmod,Erules,_Module) ->
Type_pattern = asn1ct:get_gen_state_field(type_pattern),
- %% Get the typedef of the top type and follow into the choosen
+ %% Get the typedef of the top type and follow into the chosen
%% components until the last type/component.
pgen_partial_types(Erules,Type_pattern),
ok.
@@ -1327,9 +1327,25 @@ gen_head(#gen{options=Options}=Gen, Mod, Hrl) ->
0 -> ok;
_ -> emit(["-include(\"",Mod,".hrl\").",nl])
end,
+ Deterministic = proplists:get_bool(deterministic, Options),
+ Options1 =
+ case Deterministic of
+ true ->
+ %% compile:keep_compile_option will filter some of these
+ %% out of generated .beam files, but this will keep
+ %% them out of the generated .erl files
+ lists:filter(
+ fun({cwd, _}) -> false;
+ ({outdir, _}) -> false;
+ ({i, _}) -> false;
+ (_) -> true end,
+ Options);
+ false ->
+ Options
+ end,
emit(["-asn1_info([{vsn,'",asn1ct:vsn(),"'},",nl,
" {module,'",Mod,"'},",nl,
- " {options,",io_lib:format("~p",[Options]),"}]).",nl,nl]),
+ " {options,",io_lib:format("~p",[Options1]),"}]).",nl,nl]),
JerDefines = case Gen of
#gen{erule=jer} ->
true;
diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl
index 446f508998..0e7d07e92a 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-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -764,7 +764,7 @@ gen_encode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
EmitFuncClause("Val"),
gen_encode_default_call(ClassName,Name,DefaultType);
{{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
+ %% A specified field overwrites any 'DEFAULT' or
%% 'OPTIONAL' field in the class
EmitFuncClause("Val"),
gen_encode_field_call(ObjName,Name,TypeSpec)
@@ -912,7 +912,7 @@ gen_decode_objectfields(ClassName,[{typefield,Name,OptOrMand}|Rest],
emit_tlv_format("Bytes"),
gen_decode_default_call(ClassName,Name,"Tlv",DefaultType);
{{Name,TypeSpec},_} ->
- %% A specified field owerwrites any 'DEFAULT' or
+ %% A specified field overwrites any 'DEFAULT' or
%% 'OPTIONAL' field in the class
EmitFuncClause("Bytes"),
emit_tlv_format("Bytes"),
diff --git a/lib/asn1/src/asn1ct_gen_jer.erl b/lib/asn1/src/asn1ct_gen_jer.erl
index 2e7e300e1c..7f6152ad80 100644
--- a/lib/asn1/src/asn1ct_gen_jer.erl
+++ b/lib/asn1/src/asn1ct_gen_jer.erl
@@ -527,7 +527,7 @@ maybe_legacy_bit_string(BitStrType,SizeConstraint) ->
%%===========================================================================
%% Generate DECODING
%%===========================================================================
-%% dummy functions beause we don't generate anything special for decode
+%% dummy functions because we don't generate anything special for decode
%%===========================================================================
gen_decode(_,_) -> ok.
diff --git a/lib/asn1/src/asn1ct_imm.erl b/lib/asn1/src/asn1ct_imm.erl
index 231048694a..c2ec27e195 100644
--- a/lib/asn1/src/asn1ct_imm.erl
+++ b/lib/asn1/src/asn1ct_imm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -381,22 +381,44 @@ per_enc_optional(Val, {call,M,F,A}) ->
[[{eq,Tmp,true},Zero],['_',One]]}].
per_enc_sof(Val0, Constraint, ElementVar, ElementImm, Aligned) ->
- {B,[Val,Len]} = mk_vars(Val0, [len]),
- SzConstraint = effective_constraint(bitstring, Constraint),
- LenImm = enc_length(Len, SzConstraint, Aligned),
- Lc0 = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
- Lc = opt_lc(Lc0, LenImm),
- PreBlock = B ++ [{call,erlang,length,[Val],Len}],
- case LenImm of
- [{'cond',[[C|Action]]}] ->
- PreBlock ++ [{'cond',[[C|Action++Lc]]}];
- [{sub,_,_,_}=Sub,{'cond',[[C|Action]]}] ->
- PreBlock ++
- [Sub,{'cond',[[C|Action++Lc]]}];
- EncLen ->
- PreBlock ++ EncLen ++ Lc
+ case effective_constraint(bitstring, Constraint) of
+ no ->
+ per_enc_sof_fragmented(Val0, ElementVar, ElementImm, Aligned);
+ SzConstraint ->
+ {B,[Val,Len]} = mk_vars(Val0, [len]),
+ LenImm = enc_sof_length(Len, SzConstraint, Aligned),
+ Lc0 = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
+ Lc = opt_lc(Lc0, LenImm),
+ PreBlock = B ++ [{call,erlang,length,[Val],Len}],
+ case LenImm of
+ [{'cond',[[C|Action]]}] ->
+ PreBlock ++ [{'cond',[[C|Action++Lc]]}];
+ [{sub,_,_,_}=Sub,{'cond',[[C|Action]]}] ->
+ PreBlock ++
+ [Sub,{'cond',[[C|Action++Lc]]}];
+ EncLen ->
+ PreBlock ++ EncLen ++ Lc
+ end
end.
+per_enc_sof_fragmented(Val0, ElementVar, ElementImm, Aligned) ->
+ {B,[Val,Len,Fun]} = mk_vars(Val0, [len,fn]),
+ Lc = [{lc,ElementImm,{var,atom_to_list(ElementVar)},Val}],
+ PreBlock = B ++ [{call,erlang,length,[Val],Len}],
+ U = unit(1, Aligned),
+ EncFragmented =
+ [{'fun',
+ [{var,atom_to_list(ElementVar)}],
+ ElementImm,
+ Fun},
+ {call,enc_mod(Aligned),encode_fragmented_sof,[Fun,Val,Len]}],
+ CondImm = build_cond([[{lt,Len,128},
+ {put_bits,Len,8,U}|Lc],
+ [{lt,Len,16384},
+ {put_bits,2,2,U},{put_bits,Len,14,[1]}|Lc],
+ ['_'|EncFragmented]]),
+ PreBlock ++ CondImm.
+
enc_absent(Val0, {call,M,F,A}, Body) ->
{B,[Var,Tmp]} = mk_vars(Val0, [tmp]),
B++[{call,M,F,[Var|A],Tmp},
@@ -586,7 +608,10 @@ decode_unconstrained_length(AllowZero, Aligned) ->
{value,{get_bits,7,[1|Zero]}}},
{test,{get_bits,1,[1|Al]},1,
{test,{get_bits,1,[1]},0,
- {value,{get_bits,14,[1|Zero]}}}}]}.
+ {value,{get_bits,14,[1|Zero]}}}},
+ {test,{get_bits,1,[1|Al]},1,
+ {test,{get_bits,1,[1]},1,
+ {value,{mul,{get_bits,6,[1|Zero]},16384}}}}]}.
uper_num_bits(N) ->
uper_num_bits(N, 1, 0).
@@ -751,6 +776,9 @@ opt_al({value,E0}, A0) ->
opt_al({add,E0,I}, A0) when is_integer(I) ->
{E,A} = opt_al(E0, A0),
{{add,E,I},A};
+opt_al({mul,E0,I}, A0) when is_integer(I) ->
+ {E,A} = opt_al(E0, A0),
+ {{mul,E,I},A};
opt_al({test,E0,V,B0}, A0) ->
{E,A1} = opt_al(E0, A0),
{B,A2} = opt_al(B0, A1),
@@ -838,6 +866,10 @@ flatten({add,E0,I}, Buf0, St0) ->
{{Src,Buf},Pre,St1} = flatten(E0, Buf0, St0),
{Dst,St} = new_var("Add", St1),
{{Dst,Buf},Pre++[{add,Src,I,Dst}],St};
+flatten({mul,E0,I}, Buf0, St0) ->
+ {{Src,Buf},Pre,St1} = flatten(E0, Buf0, St0),
+ {Dst,St} = new_var("Mul", St1),
+ {{Dst,Buf},Pre++[{mul,Src,I,Dst}],St};
flatten({'case',Cs0}, Buf0, St0) ->
{Dst,St1} = new_var_pair(St0),
{Cs1,St} = flatten_cs(Cs0, Buf0, St1),
@@ -951,6 +983,9 @@ dcg_list_outside([{'map',Val,Cs,Dst}|T]) ->
dcg_list_outside([{add,S1,S2,Dst}|T]) ->
emit([Dst," = ",S1," + ",S2]),
iter_dcg_list_outside(T);
+dcg_list_outside([{mul,S1,S2,Dst}|T]) ->
+ emit([Dst," = ",S1," * ",S2]),
+ iter_dcg_list_outside(T);
dcg_list_outside([{return,{V,Buf}}|T]) ->
emit(["{",V,",",Buf,"}"]),
iter_dcg_list_outside(T);
@@ -1055,6 +1090,7 @@ split_off_nonbuilding(Imm) ->
is_nonbuilding({assign,_,_}) -> true;
is_nonbuilding({call,_,_,_,_}) -> true;
is_nonbuilding({comment,_}) -> true;
+is_nonbuilding({'fun',_,_,_}) -> true;
is_nonbuilding({lc,_,_,_,_}) -> true;
is_nonbuilding({set,_,_}) -> true;
is_nonbuilding({list,_,_}) -> true;
@@ -1239,23 +1275,23 @@ per_enc_length(Bin, Unit0, Len, Sv, Aligned, Type) when is_integer(Sv) ->
Pb = {put_bits,Bin,binary,U},
[{'cond',[[{eq,Len,Sv},Pb]]}].
-enc_length(Len, no, Aligned) ->
+enc_sof_length(Len, no, Aligned) ->
U = unit(1, Aligned),
build_cond([[{lt,Len,128},
{put_bits,Len,8,U}],
[{lt,Len,16384},
{put_bits,2,2,U},{put_bits,Len,14,[1]}]]);
-enc_length(Len, {{Lb,Ub},[]}, Aligned) ->
+enc_sof_length(Len, {{Lb,Ub},[]}, Aligned) ->
{Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
NoExt = {put_bits,0,1,[1]},
- [{'cond',ExtConds0}] = enc_length(Len, no, Aligned),
+ [{'cond',ExtConds0}] = enc_sof_length(Len, no, Aligned),
Ext = {put_bits,1,1,[1]},
ExtConds = prepend_to_cond(ExtConds0, Ext),
build_length_cond(Prefix, [[Check,NoExt|PutLen]|ExtConds]);
-enc_length(Len, {Lb,Ub}, Aligned) when is_integer(Lb) ->
+enc_sof_length(Len, {Lb,Ub}, Aligned) when is_integer(Lb) ->
{Prefix,Check,PutLen} = per_enc_constrained(Len, Lb, Ub, Aligned),
build_length_cond(Prefix, [[Check|PutLen]]);
-enc_length(Len, Sv, _Aligned) when is_integer(Sv) ->
+enc_sof_length(Len, Sv, _Aligned) when is_integer(Sv) ->
[{'cond',[[{eq,Len,Sv}]]}].
extensions_bitmap(Vs, Undefined) ->
@@ -1344,7 +1380,7 @@ eval_cond([[Cond|Actions]=H|T], Seen0) ->
eval_cond(T, Seen);
true ->
[['_'|Actions]];
- maybe ->
+ 'maybe' ->
[H|eval_cond(T, Seen)]
end;
true ->
@@ -1362,7 +1398,7 @@ eval_cond_1({ge,I,N}) when is_integer(I), is_integer(N) ->
I >= N;
eval_cond_1({lt,I,N}) when is_integer(I), is_integer(N) ->
I < N;
-eval_cond_1(_) -> maybe.
+eval_cond_1(_) -> 'maybe'.
prepend_to_cond([H|T], Code) ->
[prepend_to_cond_1(H, Code)|prepend_to_cond(T, Code)];
@@ -1730,6 +1766,9 @@ enc_make_cons({integer,Int}, {cons,{binary,H},T}) ->
enc_make_cons(H, T) ->
{cons,H,T}.
+enc_pre_cg_nonbuilding({'fun',Args,B0,Dst}, StL) ->
+ B = enc_pre_cg_1(B0, StL, outside_seq),
+ {'fun',Args,B,Dst};
enc_pre_cg_nonbuilding({lc,B0,Var,List,Dst}, StL) ->
B = enc_pre_cg_1(B0, StL, outside_seq),
{lc,B,Var,List,Dst};
@@ -1943,6 +1982,9 @@ enc_opt({cons,H0,T0}, St0) ->
{{cons,H,T},St#ost{t=t_cons(TypeH, TypeT)}};
enc_opt({error,_}=Imm, St) ->
{Imm,St#ost{t=t_any()}};
+enc_opt({'fun',_,_,Dst}=Imm, St0) ->
+ St = set_type(Dst, t_any(), St0),
+ {Imm,St};
enc_opt({integer,V}, St) ->
{{integer,subst(V, St)},St#ost{t=t_integer()}};
enc_opt({lc,E0,B,C}, St) ->
@@ -2067,7 +2109,7 @@ enc_opt_cs([{Cond,Imm0}|T], St0) ->
true ->
{Imm,#ost{t=Type}} = enc_opt(Imm0, St0),
[{'_',Imm,Type}];
- maybe ->
+ 'maybe' ->
St = update_type_info(Cond, St0),
{Imm,#ost{t=Type}} = enc_opt(Imm0, St),
[{Cond,Imm,Type}|enc_opt_cs(T, St0)]
@@ -2079,18 +2121,18 @@ eo_eval_cond('_', _) ->
eo_eval_cond({Op,{var,_}=Var,Val}, St) ->
Type = get_type(Var, St),
case t_range(Type) of
- any -> maybe;
+ any -> 'maybe';
{_,_}=Range -> eval_cond_range(Op, Range, Val)
end;
-eo_eval_cond({_Op,{expr,_},_Val}, _St) -> maybe.
+eo_eval_cond({_Op,{expr,_},_Val}, _St) -> 'maybe'.
eval_cond_range(lt, {Lb,Ub}, Val) ->
if
Ub < Val -> true;
Val =< Lb -> false;
- true -> maybe
+ true -> 'maybe'
end;
-eval_cond_range(_Op, _Range, _Val) -> maybe.
+eval_cond_range(_Op, _Range, _Val) -> 'maybe'.
update_type_info({ult,{var,_}=Var,Val}, St) ->
Int = t_integer({0,Val-1}),
@@ -2365,6 +2407,13 @@ enc_cg({error,Error}) when is_function(Error, 0) ->
enc_cg({error,{Tag,Var0}}) ->
Var = mk_val(Var0),
emit(["exit({error,{asn1,{",Tag,",",Var,"}}})"]);
+enc_cg({'fun',Args,Body,Dst0}) ->
+ Dst = mk_val(Dst0),
+ emit([Dst," = fun("]),
+ _ = [emit(mk_val(A)) || A <- Args],
+ emit(") -> "),
+ enc_cg(Body),
+ emit(" end");
enc_cg({integer,Int}) ->
emit(mk_val(Int));
enc_cg({lc,Body,Var,List}) ->
@@ -2738,6 +2787,8 @@ per_fixup([{call_gen,_,_,_,_,_}=H|T]) ->
[H|per_fixup(T)];
per_fixup([{error,_}=H|T]) ->
[H|per_fixup(T)];
+per_fixup([{'fun',Args,Body,Dst}|T]) ->
+ [{'fun',Args,per_fixup(Body),Dst}|per_fixup(T)];
per_fixup([{lc,B,V,L}|T]) ->
[{lc,per_fixup(B),V,L}|per_fixup(T)];
per_fixup([{lc,B,V,L,Dst}|T]) ->
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 35c921e98d..2bdc284b12 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1106,7 +1106,7 @@ parse_ObjectAssignment([#identifier{pos=L1,val=ObjName}|Rest]) ->
%% Ret = {object,_} | {object, _, _}
parse_Object(Tokens) ->
%% The ObjectFromObject production is not included here,
- %% since it will have been catched by the ValueFromObject
+ %% since it will have been caught by the ValueFromObject
%% before we reach this point.
Flist = [fun parse_ObjectDefn/1,
fun parse_DefinedObject/1],
diff --git a/lib/asn1/src/asn1ct_pretty_format.erl b/lib/asn1/src/asn1ct_pretty_format.erl
index f4669f7eb0..adf13aef3b 100644
--- a/lib/asn1/src/asn1ct_pretty_format.erl
+++ b/lib/asn1/src/asn1ct_pretty_format.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ term(Term) ->
%%______________________________________________________________________
%% 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>
+%% Note: Indent' is a new indentation level (sometimes printing <Term>
%% the next line to need an "extra" indent!).
term([], Indent) ->
diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl
index 517b5582f5..7b98714e39 100644
--- a/lib/asn1/src/asn1ct_tok.erl
+++ b/lib/asn1/src/asn1ct_tok.erl
@@ -171,7 +171,7 @@ collect_string([], _, _) ->
throw({error,missing_quote_at_eof}).
%% <name> is letters digits hyphens.
-%% Hypen is not the last character. Hypen hyphen is NOT allowed.
+%% Hyphen is not the last character. Hyphen hyphen is NOT allowed.
%%
%% <identifier> ::= <lowercase> <name>
diff --git a/lib/asn1/src/asn1rt_nif.erl b/lib/asn1/src/asn1rt_nif.erl
index a62b476644..e724d60bae 100644
--- a/lib/asn1/src/asn1rt_nif.erl
+++ b/lib/asn1/src/asn1rt_nif.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,10 @@
decode_ber_tlv/1,
encode_ber_tlv/1]).
+-nifs([encode_per_complete/1,
+ decode_ber_tlv_raw/1,
+ encode_ber_tlv/1]).
+
-compile(no_native).
-on_load(load_nif/0).
diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl
index d1cd22579b..f2458d25c5 100644
--- a/lib/asn1/src/asn1rtt_ber.erl
+++ b/lib/asn1/src/asn1rtt_ber.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -774,7 +774,7 @@ do_encode_named_bit_string(Size, [FirstVal | RestVal], NamedBitList, TagIn) ->
%%
%% bitstring NamedBitList
%% Val can be of:
-%% - [identifiers] where only named identifers are set to one,
+%% - [identifiers] where only named identifiers are set to one,
%% the Constraint must then have some information of the
%% bitlength.
%% - [list of ones and zeroes] all bits
@@ -1133,7 +1133,7 @@ e_object_identifier(V) when is_tuple(V) ->
e_object_identifier(tuple_to_list(V));
%%%%%%%%%%%%%%%
-%% e_object_identifier([List of Obect Identifiers]) ->
+%% e_object_identifier([List of Object Identifiers]) ->
%% {[Encoded Octetlist of ObjIds], IntLength}
%%
e_object_identifier([E1,E2|Tail]) ->
diff --git a/lib/asn1/src/asn1rtt_per.erl b/lib/asn1/src/asn1rtt_per.erl
index 753a38aa6e..e5341d0e22 100644
--- a/lib/asn1/src/asn1rtt_per.erl
+++ b/lib/asn1/src/asn1rtt_per.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
%%
-module(asn1rtt_per).
--export([skipextensions/3,complete/1]).
+-export([skipextensions/3,complete/1,encode_fragmented_sof/3]).
skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
Prev = Nr - 1,
@@ -119,3 +119,31 @@ complete(Bin, Bits, More) when is_binary(Bin) ->
[Bin|complete([], Bits, More)];
complete(Bin, Bits, More) ->
[Bin|complete([], Bits+bit_size(Bin), More)].
+
+-define('16K',16384).
+
+encode_fragmented_sof(Fun, Comps, Len) ->
+ encode_fragmented_sof_1(Fun, Comps, Len, 4).
+
+encode_fragmented_sof_1(Encoder, Comps0, Len0, N) ->
+ SegSz = N * ?'16K',
+ if
+ Len0 >= SegSz ->
+ {Comps,B} = encode_components(Comps0, Encoder, SegSz, []),
+ Len = Len0 - SegSz,
+ [align,<<3:2,N:6>>,B|encode_fragmented_sof_1(Encoder, Comps, Len, N)];
+ N > 1 ->
+ encode_fragmented_sof_1(Encoder, Comps0, Len0, N - 1);
+ Len0 < 128 ->
+ {[],B} = encode_components(Comps0, Encoder, Len0, []),
+ [align,Len0|B];
+ Len0 < ?'16K' ->
+ {[],B} = encode_components(Comps0, Encoder, Len0, []),
+ [align,<<2:2,Len0:14>>|B]
+ end.
+
+encode_components(Cs, _Encoder, 0, Acc) ->
+ {Cs,lists:reverse(Acc)};
+encode_components([C|Cs], Encoder, Size, Acc) ->
+ B = Encoder(C),
+ encode_components(Cs, Encoder, Size - 1, [B|Acc]).
diff --git a/lib/asn1/src/asn1rtt_real_common.erl b/lib/asn1/src/asn1rtt_real_common.erl
index 0d53447eb7..88ad15cf84 100644
--- a/lib/asn1/src/asn1rtt_real_common.erl
+++ b/lib/asn1/src/asn1rtt_real_common.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -222,7 +222,7 @@ decode_real2(Buffer0, _C, Len, RemBytes1) ->
First =:= 2#01000000 -> {'PLUS-INFINITY', Buffer2};
First =:= 2#01000001 -> {'MINUS-INFINITY', Buffer2};
First =:= 1 orelse First =:= 2 orelse First =:= 3 ->
- %% charcter string encoding of base 10
+ %% character string encoding of base 10
{NRx,Rest} = split_binary(Buffer2,Len-1),
{binary_to_list(NRx),Rest,Len};
true ->
diff --git a/lib/asn1/src/asn1rtt_uper.erl b/lib/asn1/src/asn1rtt_uper.erl
index 0ab8fab141..0526d616ea 100644
--- a/lib/asn1/src/asn1rtt_uper.erl
+++ b/lib/asn1/src/asn1rtt_uper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
-export([skipextensions/3]).
-export([complete/1, complete_NFP/1]).
+-export([encode_fragmented_sof/3]).
skipextensions(Bytes0, Nr, ExtensionBitstr) when is_bitstring(ExtensionBitstr) ->
Prev = Nr - 1,
@@ -75,3 +76,31 @@ complete_NFP(InList) when is_list(InList) ->
list_to_bitstring(InList);
complete_NFP(InList) when is_bitstring(InList) ->
InList.
+
+-define('16K',16384).
+
+encode_fragmented_sof(Fun, Comps, Len) ->
+ encode_fragmented_sof_1(Fun, Comps, Len, 4).
+
+encode_fragmented_sof_1(Encoder, Comps0, Len0, N) ->
+ SegSz = N * ?'16K',
+ if
+ Len0 >= SegSz ->
+ {Comps,B} = encode_components(Comps0, Encoder, SegSz, []),
+ Len = Len0 - SegSz,
+ [<<3:2,N:6>>,B|encode_fragmented_sof_1(Encoder, Comps, Len, N)];
+ N > 1 ->
+ encode_fragmented_sof_1(Encoder, Comps0, Len0, N - 1);
+ Len0 < 128 ->
+ {[],B} = encode_components(Comps0, Encoder, Len0, []),
+ [Len0|B];
+ Len0 < ?'16K' ->
+ {[],B} = encode_components(Comps0, Encoder, Len0, []),
+ [<<2:2,Len0:14>>|B]
+ end.
+
+encode_components(Cs, _Encoder, 0, Acc) ->
+ {Cs,lists:reverse(Acc)};
+encode_components([C|Cs], Encoder, Size, Acc) ->
+ B = Encoder(C),
+ encode_components(Cs, Encoder, Size - 1, [B|Acc]).
diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile
index a9dd66251c..de2a38e752 100644
--- a/lib/asn1/test/Makefile
+++ b/lib/asn1/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2020. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -138,6 +138,7 @@ RELSYSDIR = $(RELEASE_PATH)/asn1_test
# FLAGS
# ----------------------------------------------------
ERL_COMPILE_FLAGS += +warnings_as_errors +nowarn_export_all
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
# ----------------------------------------------------
@@ -147,7 +148,7 @@ EBIN = .
$(EMAKEFILE): $(ERL_FILES) $(HRL_FILES)
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) $(ERL_FILES) >$(EMAKEFILE)
-tests debug opt: $(EMAKEFILE)
+tests $(TYPES): $(EMAKEFILE)
clean:
rm -f core
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 90d6dd24b6..2a02f08a95 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -731,18 +731,17 @@ ber_decode_error(Config, Rule, Opts) ->
ber_decode_error:run(Opts).
otp_14440(_Config) ->
- Args = " -pa \"" ++ filename:dirname(code:which(?MODULE)) ++ "\"",
- {ok,N} = slave:start(hostname(), otp_14440, Args),
+ {ok, Peer, N} = ?CT_PEER(),
Result = rpc:call(N, ?MODULE, otp_14440_decode, []),
io:format("Decode result = ~p~n", [Result]),
+ peer:stop(Peer),
case Result of
{exit,{error,{asn1,{invalid_value,5}}}} ->
- ok = slave:stop(N);
+ ok;
%% We get this if stack depth limit kicks in:
{exit,{error,{asn1,{unknown,_}}}} ->
- ok = slave:stop(N);
+ ok;
_ ->
- _ = slave:stop(N),
ct:fail(Result)
end.
%%
@@ -1063,7 +1062,8 @@ test_compile_options(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:maps(Config).
+ ok = test_compile_options:maps(Config),
+ ok = test_compile_options:determinism(Config).
testDoubleEllipses(Config) -> test(Config, fun testDoubleEllipses/3).
testDoubleEllipses(Config, Rule, Opts) ->
@@ -1411,11 +1411,3 @@ all_called_1([F|T]) when is_atom(F) ->
L ++ all_called_1(T);
all_called_1([]) ->
[].
-
-hostname() ->
- hostname(atom_to_list(node())).
-
-hostname([$@ | Hostname]) ->
- list_to_atom(Hostname);
-hostname([_C | Cs]) ->
- hostname(Cs).
diff --git a/lib/asn1/test/asn1_SUITE_data/Comment.asn b/lib/asn1/test/asn1_SUITE_data/Comment.asn
index c2a5abd633..af439a1ce4 100644
--- a/lib/asn1/test/asn1_SUITE_data/Comment.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Comment.asn
@@ -4,7 +4,7 @@ BEGIN
/* comments as to the 2002 standard
-this is the new added way of commenting multile lines */
+this is the new added way of commenting multiple lines */
/* it is also allowed to have -- old kind of comment signs inside
this new variant. The two dashes will lose their meaning as a comment
diff --git a/lib/asn1/test/asn1_SUITE_data/CommonDataTypes.py b/lib/asn1/test/asn1_SUITE_data/CommonDataTypes.py
index 2c25f81235..67cd9eae96 100644
--- a/lib/asn1/test/asn1_SUITE_data/CommonDataTypes.py
+++ b/lib/asn1/test/asn1_SUITE_data/CommonDataTypes.py
@@ -923,7 +923,7 @@ ConnectUUIE ::= SEQUENCE
-- @prop dataType
--
-- @descr This parameter holds connection data that are specific for
--- certain types of Equipments.
+-- certain types of Equipment.
-- @
--
-- ---------------------------------
@@ -958,7 +958,7 @@ ConnectionIdentifier ::= ObjectIdentifier
-- @prop dataType
--
-- @descr This parameter specifies information that are of interest for
--- the functionallity handled by component Connection Handler.
+-- the functionality handled by component Connection Handler.
-- @
--
-- ---------------------------------
@@ -1541,7 +1541,7 @@ EquipmentAddressLAN ::= SEQUENCE
--
-- @prop dataType
--
--- @descr Contains the retreived data.
+-- @descr Contains the retrieved data.
--
-- @
--
diff --git a/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn b/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn
index 3b811dafe6..24dd8e85e8 100644
--- a/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn
+++ b/lib/asn1/test/asn1_SUITE_data/EUTRA-RRC-Definitions.asn
@@ -3124,7 +3124,7 @@ maxCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the neigh
-- cell lists in a measurement object
maxCellReport INTEGER ::= 8 -- Maximum number of reported cells
maxDRB INTEGER ::= 11 -- Maximum number of Data Radio Bearers
-maxEARFCN INTEGER ::= 65535 -- Maximum value of EUTRA carrier fequency
+maxEARFCN INTEGER ::= 65535 -- Maximum value of EUTRA carrier frequency
maxFreq INTEGER ::= 8 -- Maximum number of EUTRA carrier frequencies
maxCellInfo-GERAN-r9 INTEGER ::= 32 -- Maximum number of GERAN cells for which system in-
-- formation can be provided as redirection assistance
diff --git a/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1 b/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
index bfc939737f..e784feff8c 100644
--- a/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/Fragmented.asn1
@@ -21,4 +21,13 @@ PDU ::= SEQUENCE {
arg FUNCTION.&ArgumentType ({ObjSet}{@code})
}
+IntBoolSeqs ::= SEQUENCE (SIZE (1..65536)) OF IntBoolSeq
+
+IntBoolSeqsU ::= SEQUENCE OF IntBoolSeq
+
+IntBoolSeq ::= SEQUENCE {
+ a INTEGER,
+ b BOOLEAN
+}
+
END
diff --git a/lib/asn1/test/asn1_SUITE_data/H235-SECURITY-MESSAGES.asn b/lib/asn1/test/asn1_SUITE_data/H235-SECURITY-MESSAGES.asn
index 3401f9599f..76eedc0d2c 100644
--- a/lib/asn1/test/asn1_SUITE_data/H235-SECURITY-MESSAGES.asn
+++ b/lib/asn1/test/asn1_SUITE_data/H235-SECURITY-MESSAGES.asn
@@ -135,7 +135,7 @@ KeySignedMaterial ::= SEQUENCE {
generalId Identifier, -- slave's alias
mrandom RandomVal, -- master's random value
srandom RandomVal OPTIONAL, -- slave's random value
- timeStamp TimeStamp OPTIONAL, -- master's timestamp for unsolicted EU
+ timeStamp TimeStamp OPTIONAL, -- master's timestamp for unsolicited EU
encrptval ENCRYPTED {EncodedKeySyncMaterial }
}
EncodedKeySignedMaterial ::= TYPE-IDENTIFIER.&Type (KeySignedMaterial)
diff --git a/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn b/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn
index fb092f3f9c..9cd8fbea84 100644
--- a/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn
+++ b/lib/asn1/test/asn1_SUITE_data/IN-CS-1-Datatypes.asn
@@ -1431,7 +1431,7 @@ ServiceInteractionIndicators ::=
-- The following example is listed to illustrate the use of this parameter:
-- CallToBeDiverted Allowed/NotAllowed Indicator
-- If the CallToBeDiverted indicator is set to NotAllowed, the destination exchange shall not allow any
--- divertion on the subjected call. By this, each service can pass the applicable indicators to inform the
+-- diversion on the subjected call. By this, each service can pass the applicable indicators to inform the
-- destination exchange of how specific services are to be handled.
ServiceKey ::=
Integer4
diff --git a/lib/asn1/test/asn1_SUITE_data/Mvrasn-11-4.asn b/lib/asn1/test/asn1_SUITE_data/Mvrasn-11-4.asn
index 81c07a2dab..fca635bb1f 100644
--- a/lib/asn1/test/asn1_SUITE_data/Mvrasn-11-4.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Mvrasn-11-4.asn
@@ -140,8 +140,8 @@ InsertSubscriberDataArg ::= SEQUENCE {
-- compiler. Instead of this line the complete definition of
-- "Subscriberdata" has been inserted.
--
--- This results in the same behaviour of the deocder/encoder but
--- means only a replication of the ASN.1 definiton here.
+-- This results in the same behaviour of the decoder/encoder but
+-- means only a replication of the ASN.1 definition here.
--
msisdn [1] ISDN-AddressString OPTIONAL,
category [2] Category OPTIONAL,
diff --git a/lib/asn1/test/asn1_SUITE_data/Nortel.asn b/lib/asn1/test/asn1_SUITE_data/Nortel.asn
index a27c78a0b5..57a4434f2e 100644
--- a/lib/asn1/test/asn1_SUITE_data/Nortel.asn
+++ b/lib/asn1/test/asn1_SUITE_data/Nortel.asn
@@ -153,7 +153,7 @@ LocationAreaCode ::= OCTET STRING (SIZE(2))
CallEventRecord ::= CHOICE
{
--- Record values 0..16 are 3G curcuit switch specifick
+-- Record values 0..16 are 3G circuit switch specifick
--
-- sgsnPDPRecord [20] SGSNPDPRecord,
ggsnPDPRecord [21] GGSNPDPRecord
@@ -372,7 +372,7 @@ FFDAppendIndicator ::= BOOLEAN
FreeFormatData ::= OCTET STRING (SIZE(1..160))
--
- -- Free formated data as sent in the FurnishChargingInformationGPRS
+ -- Free formatted data as sent in the FurnishChargingInformationGPRS
-- see TS 29.078
--
diff --git a/lib/asn1/test/asn1_SUITE_data/PKIX1Explicit93.asn1 b/lib/asn1/test/asn1_SUITE_data/PKIX1Explicit93.asn1
index 714a682160..01c5be2166 100644
--- a/lib/asn1/test/asn1_SUITE_data/PKIX1Explicit93.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/PKIX1Explicit93.asn1
@@ -172,7 +172,7 @@ EntryExtensionSet EXTENSION ::= { reasonCode |
invalidityDate |
certificateIssuer }
- -- information object classes used in the defintion --
+ -- information object classes used in the definition --
-- of certificates and CRLs --
-- Parameterized Type SIGNED --
diff --git a/lib/asn1/test/asn1_SUITE_data/RANAP.asn1 b/lib/asn1/test/asn1_SUITE_data/RANAP.asn1
index 55fb58b163..e821703036 100644
--- a/lib/asn1/test/asn1_SUITE_data/RANAP.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/RANAP.asn1
@@ -872,7 +872,7 @@ RAB-Parameters ::= SEQUENCE {
transferDelay TransferDelay OPTIONAL
-- This IE is only present when traffic class indicates Conversational or Streaming --,
trafficHandlingPriority TrafficHandlingPriority OPTIONAL
- -- This IE is only present when traffic class indicates Interactiv --,
+ -- This IE is only present when traffic class indicates Interactive --,
allocationOrRetentionPriority AllocationOrRetentionPriority OPTIONAL,
sourceStatisticsDescriptor SourceStatisticsDescriptor OPTIONAL
-- This IE is only present when traffic class indicates Conversational or Streaming --,
@@ -1640,7 +1640,7 @@ RelocationCancelAcknowledgeExtensions RANAP-PROTOCOL-EXTENSION ::= {
-- **************************************************************
--
--- SRNS CONTEXT TRANSFER OPEARATION
+-- SRNS CONTEXT TRANSFER OPERATION
--
-- **************************************************************
diff --git a/lib/asn1/test/asn1_SUITE_data/SwCDR.py b/lib/asn1/test/asn1_SUITE_data/SwCDR.py
index 9492183cdf..1ed9c32aba 100644
--- a/lib/asn1/test/asn1_SUITE_data/SwCDR.py
+++ b/lib/asn1/test/asn1_SUITE_data/SwCDR.py
@@ -199,7 +199,7 @@ StartDate ::= OCTET STRING (SIZE (8))
StartTime ::= OCTET STRING (SIZE (6))
CallDuration ::= INTEGER
--- Expressed as number of millseconds
+-- Expressed as number of milliseconds
Cellrate ::= INTEGER
-- Value range 0-2^64
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..b614e86bba 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
@@ -5606,13 +5606,13 @@ DL-CCTrCH-InformationAddItem-RL-ReconfPrepTDD-ExtIEs NBAP-PROTOCOL-EXTENSION ::
{ ID id-DL-DPCH-LCR-InformationAddList-RL-ReconfPrepTDD CRITICALITY reject EXTENSION DL-DPCH-LCR-InformationAddList-RL-ReconfPrepTDD PRESENCE optional }| -- Applicable to 1.28Mcps TDD only
-- This DPCH Information is the for the first RL repetition, DPCH information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
{ ID id-CCTrCH-Initial-DL-Power-RL-ReconfPrepTDD CRITICALITY ignore EXTENSION DL-Power PRESENCE optional }|
--- This DL Power inforrmation is the for the first RL repetition, DL power information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
+-- This DL Power information is the for the first RL repetition, DL power information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
{ ID id-TDD-TPC-DownlinkStepSize-InformationAdd-RL-ReconfPrepTDD CRITICALITY reject EXTENSION TDD-TPC-DownlinkStepSize PRESENCE optional}|
-- This DL step size is the for the first RL repetition, DL step size information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
{ ID id-CCTrCH-Maximum-DL-Power-InformationAdd-RL-ReconfPrepTDD CRITICALITY ignore EXTENSION DL-Power PRESENCE optional }|
--- This DL Power inforrmation is the for the first RL repetition, DL power information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
+-- This DL Power information is the for the first RL repetition, DL power information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
{ ID id-CCTrCH-Minimum-DL-Power-InformationAdd-RL-ReconfPrepTDD CRITICALITY ignore EXTENSION DL-Power PRESENCE optional }|
--- This DL Power inforrmation is the for the first RL repetition, DL power information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
+-- This DL Power information is the for the first RL repetition, DL power information for RL repetitions 2 and on, should be defined in MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD
{ ID id-RL-ID CRITICALITY ignore EXTENSION RL-ID PRESENCE optional }|
-- This is the RL ID for the first RL repetition
{ ID id-multipleRL-ul-DPCH-InformationList CRITICALITY reject EXTENSION MultipleRL-DL-DPCH-InformationAddList-RL-ReconfPrepTDD PRESENCE optional },
diff --git a/lib/asn1/test/asn1_SUITE_data/rfcs/AlgorithmInformation-2009.asn1 b/lib/asn1/test/asn1_SUITE_data/rfcs/AlgorithmInformation-2009.asn1
index f912966c72..7da299c789 100644
--- a/lib/asn1/test/asn1_SUITE_data/rfcs/AlgorithmInformation-2009.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/rfcs/AlgorithmInformation-2009.asn1
@@ -50,7 +50,7 @@ ParamOptions ::= ENUMERATED {
-- Additional information such as the length of the hash could have
-- been encoded. Without a clear understanding of what information
-- is needed by applications, such extraneous information was not
--- considered to be of sufficent importance.
+-- considered to be of sufficient importance.
--
-- Example:
-- mda-sha1 DIGEST-ALGORITHM ::= {
diff --git a/lib/asn1/test/asn1_SUITE_data/rfcs/ISO8571-FTAM.asn1 b/lib/asn1/test/asn1_SUITE_data/rfcs/ISO8571-FTAM.asn1
index a57a276704..3765eb5b65 100644
--- a/lib/asn1/test/asn1_SUITE_data/rfcs/ISO8571-FTAM.asn1
+++ b/lib/asn1/test/asn1_SUITE_data/rfcs/ISO8571-FTAM.asn1
@@ -286,7 +286,7 @@ F-OPEN-response ::= SEQUENCE {
-- This flag is set if the responder is going to follow this response
-- by a P-ALTER-CONTEXT exchange.
--The following are conditional on the negotiation of the concecutive access
- -- or concurent access functional units.
+ -- or concurrent access functional units.
degree-of-overlap Degree-Of-Overlap OPTIONAL,
transfer-window [7] IMPLICIT INTEGER OPTIONAL
}
@@ -571,7 +571,7 @@ Change-Attributes ::= [APPLICATION 8] IMPLICIT SEQUENCE {
-- This Parameter tan only be sent when the
-- enhanced-filestore-management functional unit is available.
--- Atleast one attribute shall be present in the Change-Attributes
+-- At least one attribute shall be present in the Change-Attributes
-- Parameter on the request PDU.
Charging ::=
[APPLICATION 9] IMPLICIT
@@ -1350,7 +1350,7 @@ Attribute-Extensions-Pattern ::=
{@.extension-attribute-identifier})
}}
--- conjunction with the extention attribute in Order to
+-- conjunction with the extension attribute in Order to
-- perform Pattern matthing operations on it. it may be
-- defined in terms of other Patterns within this
-- Standard.
diff --git a/lib/asn1/test/asn1_SUITE_data/tcapsystem/MAP-MS-DataTypes.asn b/lib/asn1/test/asn1_SUITE_data/tcapsystem/MAP-MS-DataTypes.asn
index e905c44077..46c919b772 100644
--- a/lib/asn1/test/asn1_SUITE_data/tcapsystem/MAP-MS-DataTypes.asn
+++ b/lib/asn1/test/asn1_SUITE_data/tcapsystem/MAP-MS-DataTypes.asn
@@ -2100,7 +2100,7 @@ LocationInformation ::= SEQUENCE {
-- sai-Present indicates that the cellGlobalIdOrServiceAreaIdOrLAI parameter contains
-- a Service Area Identity.
-- currentLocationRetrieved shall be present
--- if the location information were retrieved after a successfull paging.
+-- if the location information were retrieved after a successful paging.
LocationInformationGPRS ::= SEQUENCE {
cellGlobalIdOrServiceAreaIdOrLAI [0] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
diff --git a/lib/asn1/test/asn1_SUITE_data/testobj.erl b/lib/asn1/test/asn1_SUITE_data/testobj.erl
index b582935f73..c358c26623 100644
--- a/lib/asn1/test/asn1_SUITE_data/testobj.erl
+++ b/lib/asn1/test/asn1_SUITE_data/testobj.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -427,7 +427,7 @@ run_sm_cmd() ->
{_ProtIEField2,11,_Crit2,DecEI},
{_ProtIEField3,75,_Crit3,DecKS}],
_ASN1novalue} ->
- io:format("Integrity Protection Algoritm: ~w~n~n", [DecIPI]),
+ io:format("Integrity Protection Algorithm: ~w~n~n", [DecIPI]),
io:format("Encryption Information: ~w~n~n", [DecEI]),
io:format("Key Status: ~w~n~n", [DecKS])
end,
@@ -452,7 +452,7 @@ run_sm_cmp() ->
[{_ProtIEField1,6,_Crit1,DecIPA},
{_ProtIEField2,5,_Crit2,DecEI}],
_ASN1novalue} ->
- io:format("Integrity Protection Algoritm: ~w~n~n", [DecIPA]),
+ io:format("Integrity Protection Algorithm: ~w~n~n", [DecIPA]),
io:format("Encryption Information: ~w~n~n", [DecEI])
end,
ok.
@@ -480,7 +480,7 @@ run_sm_rej() ->
% io:format("Value2: ~w~n~n", [Value2]),
% {ok,DecIPA} = wrapper_decode(?ranap, 'IntegrityProtectionAlgorithm', Value1),
% {ok,DecEI} = wrapper_decode(?ranap, 'EncryptionAlgorithm', Value2),
-% io:format("Integrity Protection Algoritm: ~w~n~n", [DecIPA]),
+% io:format("Integrity Protection Algorithm: ~w~n~n", [DecIPA]),
% io:format("Encryption Information: ~w~n~n", [DecEI])
% end,
ok.
@@ -563,7 +563,7 @@ run_reset() ->
run_reset_res() ->
IUP = reset_res([12,13,14,15,16,17,18,19,20]),
- io:format("Reset Rsource: ~w~n~n", [IUP]),
+ io:format("Reset Resource: ~w~n~n", [IUP]),
RanapIUP = ranap_pdu_contents(IUP, 27), % 27 = Reset Res
{ok, Tmp2} = wrapper_encode(?ranap, 'RANAP-PDU', RanapIUP),
EncRanapIUP = lists:flatten(Tmp2),
@@ -1390,7 +1390,7 @@ reset_res_ack(IuSCId) ->
reset_res_ack_ies(IuSCId) ->
[
cn_domain_ind() % Se initial Ue
- ,reset_res_list(IuSCId) % Se Reset Ressource
+ ,reset_res_list(IuSCId) % Se Reset Resource
].
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 0a331d0dd0..cf96c6983a 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -306,7 +306,14 @@ ber_get_len(<<1:1,Octets:7,T0/binary>>) ->
%% Will fail the test case if there were any errors.
p_run(Test, List) ->
- S = erlang:system_info(schedulers),
+ %% Limit the number of parallel processes to avoid running out of
+ %% memory.
+ S = case {erlang:system_info(schedulers),erlang:system_info(wordsize)} of
+ {S0,4} ->
+ min(S0, 2);
+ {S0,_} ->
+ min(S0, 8)
+ end,
N = case test_server:is_cover() of
false ->
S + 1;
diff --git a/lib/asn1/test/syntax_SUITE.erl b/lib/asn1/test/syntax_SUITE.erl
index e78161fbfe..ab3cf2cad0 100644
--- a/lib/asn1/test/syntax_SUITE.erl
+++ b/lib/asn1/test/syntax_SUITE.erl
@@ -187,7 +187,7 @@ objects(Config) ->
{"{&min 1, Max 10}",3,{syntax_error,'Max'}},
{"{min 1, &max 10}",3,{syntax_error,'&max'}},
{"{min 1, &Max 10}",3,{syntax_error,'&Max'}},
- {"{RESERVERD WORD BIT}",3,{syntax_error,'BIT'}},
+ {"{RESERVED WORD BIT}",3,{syntax_error,'BIT'}},
{"{&min 1",4,{syntax_error,'END'}}
],
L = [{Head++S++End,Line,E} || {S,Line,E} <- L0],
diff --git a/lib/asn1/test/testFragmented.erl b/lib/asn1/test/testFragmented.erl
index bd63bd83fc..0efdc4c227 100644
--- a/lib/asn1/test/testFragmented.erl
+++ b/lib/asn1/test/testFragmented.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,37 @@ main(_Erule) ->
K8,K8,K8,K8,K8,K8]}),
roundtrip('PDU', {'PDU',1,false,[K8,K8,K8,K8,K8,K8,K8,K8,
K8,K8,K8,K8,K8,K8,K8,K8]}),
+
+ K16 = 16384,
+ K64 = 4 * K16,
+ K144 = 2 * K64 + K16,
+ roundtrips([1, 2, 3, 17,
+ K16-1, K16, K16+1,
+ 2*K16-1, 2*K16, 2*K16+1,
+ 3*K16-1, 3*K16, 3*K16+1,
+ K64-1, K64, K64+1,
+ K64+K16,
+ K144-1, K144, K144+1]),
+ ok.
+
+roundtrips([Size|Sizes]) ->
+ L = make_seq(Size, []),
+ io:format("~p: ~P\n", [Size,L,6]),
+ roundtrip('IntBoolSeqsU', L),
+ if
+ Size =< 65536 ->
+ roundtrip('IntBoolSeqs', L);
+ true ->
+ ok
+ end,
+ roundtrips(Sizes);
+roundtrips([]) ->
ok.
roundtrip(T, V) ->
asn1_test_lib:roundtrip('Fragmented', T, V).
+
+make_seq(0, Acc) ->
+ Acc;
+make_seq(N, Acc) ->
+ make_seq(N - 1, [{'IntBoolSeq',N,N rem 7 =:= 0}|Acc]).
diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl
index f9997d37d0..9334b8118a 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-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,10 +22,11 @@
-module(test_compile_options).
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
-export([wrong_path/1,comp/2,path/1,noobj/1,
- record_name_prefix/1,verbose/1,maps/1]).
+ record_name_prefix/1,verbose/1,maps/1,determinism/1]).
%% OTP-5689
wrong_path(Config) ->
@@ -150,6 +151,51 @@ do_maps(Erule, InFile, OutDir) ->
ok.
+determinism(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir,Config),
+ OutDir = proplists:get_value(priv_dir,Config),
+ Asn1File = filename:join([DataDir,"Comment.asn"]),
+ ErlFile = filename:join([OutDir,"Comment.erl"]),
+
+ ContainsNonDeterministicOptions =
+ fun
+ ({attribute,_Anno,asn1_info,Elems}) ->
+ lists:any(
+ fun
+ ({options, Opts}) ->
+ lists:any(fun ({i, _}) -> true; (_) -> false end, Opts)
+ andalso
+ lists:any(fun ({outdir, _}) -> true; (_) -> false end, Opts)
+ andalso
+ lists:any(fun ({cwd, _}) -> true; (_) -> false end, Opts);
+ (_) ->
+ false
+ end,
+ Elems);
+ (_) ->
+ false
+ end,
+
+ BaseOptions = [{i,DataDir},{outdir,OutDir},{cwd,DataDir},noobj],
+
+ %% Test deterministic compile
+ ok = asn1ct:compile(Asn1File, BaseOptions ++ [deterministic]),
+ {ok, List1} = epp:parse_file(ErlFile, [{includes, [DataDir]},
+ {source_name, "Comment.erl"}]),
+ ?assertNot(lists:any(ContainsNonDeterministicOptions, List1),
+ "Expected no debugging option values (i, outdir, cwd) in asn1_info attribute " ++
+ "in deterministic mode"),
+
+ %% Test non-deterministic compile
+ ok = asn1ct:compile(Asn1File, BaseOptions),
+ {ok, List2} = epp:parse_file(ErlFile, [{includes, [DataDir]},
+ {source_name, "Comment.erl"}]),
+ ?assert(lists:any(ContainsNonDeterministicOptions, List2),
+ "Expected debugging option values (i, outdir, cwd) in asn1_info attribute " ++
+ "in non-deterministic mode"),
+ ok.
+
+
outfiles_check(OutDir) ->
outfiles_check(OutDir,outfiles1()).
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 5800ce8f67..a3706fd209 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1 +1 @@
-ASN1_VSN = 5.0.18
+ASN1_VSN = 5.0.21
diff --git a/lib/common_test/Makefile b/lib/common_test/Makefile
index ea8506b34a..ca7baaa959 100644
--- a/lib/common_test/Makefile
+++ b/lib/common_test/Makefile
@@ -47,5 +47,6 @@ include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=compiler tools crypto runtime_tools syntax_tools ftp inets \
debugger sasl snmp ssh reltool observer xmerl
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/common_test/configure b/lib/common_test/configure
index 73b2a2d156..567e5a5f24 100755
--- a/lib/common_test/configure
+++ b/lib/common_test/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,41 +167,52 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -227,14 +220,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -252,18 +252,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -290,6 +291,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -307,6 +309,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -321,7 +331,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -330,7 +340,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -369,12 +379,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -386,18 +397,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -409,9 +429,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -438,7 +458,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -482,7 +502,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -496,6 +516,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -509,6 +533,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -574,16 +605,20 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
ac_subst_vars='LTLIBOBJS
LIBOBJS
TARGET
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -706,8 +741,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -748,9 +781,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -774,9 +807,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -987,9 +1020,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1003,9 +1036,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1049,9 +1082,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1067,7 +1100,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1131,7 +1164,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1249,6 +1282,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1272,9 +1306,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1302,7 +1336,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1310,7 +1345,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1320,9 +1355,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1332,14 +1367,34 @@ fi
## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -1372,8 +1427,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -1408,7 +1467,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -1443,11 +1502,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -1458,8 +1519,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -1483,7 +1544,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -1491,14 +1552,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -1506,15 +1567,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -1522,8 +1583,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -1537,63 +1598,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -1603,19 +1649,117 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -1626,12 +1770,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -1640,24 +1784,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -1667,11 +1811,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -1685,57 +1830,124 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in priv/auxdir "$srcdir"/priv/auxdir; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in priv/auxdir \"$srcdir\"/priv/auxdir" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -1754,21 +1966,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -1787,9 +2000,107 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
+fi
+
TARGET=$host
@@ -1823,8 +2134,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -1854,15 +2165,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -1876,8 +2187,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -1930,7 +2241,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -1946,8 +2257,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -1970,14 +2281,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -1987,46 +2300,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -2035,13 +2348,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -2050,8 +2356,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -2063,30 +2373,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -2099,13 +2389,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -2132,18 +2423,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -2155,12 +2448,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -2191,7 +2485,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -2213,6 +2507,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -2226,6 +2524,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -2267,7 +2571,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -2276,7 +2580,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -2339,7 +2643,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -2388,14 +2692,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -2432,21 +2738,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -2474,7 +2780,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -2488,7 +2794,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -2513,7 +2819,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -2741,7 +3047,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -2749,17 +3055,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -2776,7 +3082,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -2800,9 +3106,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -2855,8 +3161,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -2898,9 +3204,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -2947,7 +3253,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/common_test/configure.ac b/lib/common_test/configure.ac
new file mode 100644
index 0000000000..490a64328d
--- /dev/null
+++ b/lib/common_test/configure.ac
@@ -0,0 +1,14 @@
+AC_INIT
+AC_PREREQ([2.71])
+
+m4_include([otp.m4])
+
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
+
+ERL_CANONICAL_SYSTEM_TYPE
+
+TARGET=$host
+AC_SUBST(TARGET)
+
+AC_CONFIG_FILES([priv/$host/Makefile:priv/Makefile.in])
+AC_OUTPUT
diff --git a/lib/common_test/configure.in b/lib/common_test/configure.in
deleted file mode 100644
index b2e6ad997a..0000000000
--- a/lib/common_test/configure.in
+++ /dev/null
@@ -1,14 +0,0 @@
-AC_INIT()
-
-AC_CONFIG_AUX_DIR(priv/auxdir)
-
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
-
-TARGET=$host
-AC_SUBST(TARGET)
-
-AC_OUTPUT(priv/$host/Makefile:priv/Makefile.in)
diff --git a/lib/common_test/doc/src/ct.xml b/lib/common_test/doc/src/ct.xml
index a7a953fa4c..bc0e60f9a3 100644
--- a/lib/common_test/doc/src/ct.xml
+++ b/lib/common_test/doc/src/ct.xml
@@ -649,7 +649,7 @@
case. <c>Scaling</c> indicates if <c>Common Test</c> will attempt
to compensate timetraps automatically for runtime delays
introduced by, for example, tools like cover. <c>ScaleVal</c> is
- the value of the current scaling multipler (always 1 if scaling is
+ the value of the current scaling multiplier (always 1 if scaling is
disabled). Note the <c>Time</c> is not the scaled result.</p>
</desc>
</func>
@@ -1192,7 +1192,7 @@
{machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.</pre>
<note><p>The behavior of this function changed radically in
- <c>Common Test</c> 1.6.2. To keep some backwards compatability,
+ <c>Common Test</c> 1.6.2. To keep some backwards compatibility,
it is still possible to do:<br/>
<c>ct:require(a,{node,[telnet,ftp]}).</c><br/>
This associates the name <c>a</c> with the top-level <c>node</c>
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml
index 875efec305..666ed70c69 100644
--- a/lib/common_test/doc/src/ct_hooks.xml
+++ b/lib/common_test/doc/src/ct_hooks.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2010</year><year>2020</year>
+ <year>2010</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -679,7 +679,7 @@
<list type="bulleted">
<item><p>If <c>init_per_suite</c> fails, this function is called after
<seemfa marker="#Module:post_init_per_suite/4"><c>post_init_per_suite</c></seemfa>.</p></item>
- <item><p>If a test case fails, this funcion is called after
+ <item><p>If a test case fails, this function is called after
<seemfa marker="#Module:post_end_per_testcase/5"><c>post_end_per_testcase</c></seemfa>.</p></item>
</list>
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index 0318387d3c..aab8671f9e 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -317,7 +317,7 @@
{proplists:delete(tc_status, Config), CTHState};
false ->
%% DB is not good, mark as skipped instead of failing
- {{skip, "DB is inconsisten!"}, CTHState}
+ {{skip, "DB is inconsistent!"}, CTHState}
end;
post_end_per_testcase(_Suite, _TC, Config, Return, CTHState) -&gt;
%% Do nothing if tc does not crash.
@@ -505,7 +505,7 @@
logger handler, and prints them to the current test case log.
If an event cannot be associated with a test case, it is printed in
the <c>Common Test</c> framework log.
- This happens for test cases running in parallel and events occuring
+ This happens for test cases running in parallel and events occurring
in-between test cases.</p>
<p>The log events are handled using a <seeerl marker="kernel:logger">Logger</seeerl>
handler called cth_log_redirect. The formatting and level is copied from
diff --git a/lib/common_test/doc/src/ct_netconfc.xml b/lib/common_test/doc/src/ct_netconfc.xml
index 3f764a49d8..f5fd2165c9 100644
--- a/lib/common_test/doc/src/ct_netconfc.xml
+++ b/lib/common_test/doc/src/ct_netconfc.xml
@@ -505,7 +505,7 @@
Specify a <c>receiver</c> option at session creation to
provide a destination for incoming notifications independently
of a call to &create_subscription;, and use &send_rpc; to send
- establish-subscription and other arbirary RPCs.</p>
+ establish-subscription and other arbitrary RPCs.</p>
</note>
</desc>
</func>
@@ -697,7 +697,7 @@
<p>Which target parameters that can be used depends on if
<c>:candidate</c> and/or <c>:startup</c> are supported by the
- server. If successfull, the configuration system of the device is
+ server. If successful, the configuration system of the device is
unavailable to other clients (NETCONF, CORBA, SNMP, and so on).
Locks are intended to be short-lived.</p>
diff --git a/lib/common_test/doc/src/ct_property_test.xml b/lib/common_test/doc/src/ct_property_test.xml
index 5a1f6ab979..01c06501ae 100644
--- a/lib/common_test/doc/src/ct_property_test.xml
+++ b/lib/common_test/doc/src/ct_property_test.xml
@@ -236,7 +236,7 @@ ct_property_test:present_result(?MODULE, Cmds, RunResult, Config)
</item>
<item><c>FrequencyFun/0</c> returns a fun/1 which is supposed to take a list of items as input,
- and return an iolist wich will be printed as the table. Per default, the number of each item is counted
+ and return an iolist which will be printed as the table. Per default, the number of each item is counted
and the percentage is printed for each. The list [a,b,a,a,c] could for example return
<pre>
["a 60%\n","b 20%\n","c 20%\n"]</pre>
diff --git a/lib/common_test/doc/src/ct_ssh.xml b/lib/common_test/doc/src/ct_ssh.xml
index 7659dc986d..5e1385aac4 100644
--- a/lib/common_test/doc/src/ct_ssh.xml
+++ b/lib/common_test/doc/src/ct_ssh.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2010</year><year>2020</year>
+ <year>2010</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -171,7 +171,7 @@
<func>
<name since="">aread(SSH, Server, Handle, Len) -&gt; Result</name>
- <fsummary>For inforamtion and other types, see ssh_sftp(3).</fsummary>
+ <fsummary>For information and other types, see ssh_sftp(3).</fsummary>
<type>
<v>SSH = connection()</v>
<v>Result = ssh_sftp_return() | {error, Reason}</v>
diff --git a/lib/common_test/doc/src/ct_suite.xml b/lib/common_test/doc/src/ct_suite.xml
index 0289a569f0..8740a3ff79 100644
--- a/lib/common_test/doc/src/ct_suite.xml
+++ b/lib/common_test/doc/src/ct_suite.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year>
+ <year>2020</year><year>2021</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -206,7 +206,7 @@
required by test cases (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 details about the <c>require</c> functionality, see funtion
+ For details about the <c>require</c> functionality, see function
<seemfa marker="ct#require/1"><c>ct:require/1,2</c></seemfa>.</p>
<p>With <c>userdata</c>, the user can
diff --git a/lib/common_test/doc/src/dependencies_chapter.xml b/lib/common_test/doc/src/dependencies_chapter.xml
index 236ce99f61..f5d409686e 100644
--- a/lib/common_test/doc/src/dependencies_chapter.xml
+++ b/lib/common_test/doc/src/dependencies_chapter.xml
@@ -78,7 +78,7 @@
</list>
<p>There are obvious dependencies between the listed functions. The server cannot
- be configured if it has not first been started, a client connot be connectd until
+ be configured if it has not first been started, a client cannot be connected until
the server is properly configured, and so on. If we want to have one test
case for each function, we might be tempted to try to always run the
test cases in the stated order and carry possible data (identities, handles,
diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml
index ee758c3199..dd704ef04d 100644
--- a/lib/common_test/doc/src/event_handler_chapter.xml
+++ b/lib/common_test/doc/src/event_handler_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2020</year>
+ <year>2006</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -290,7 +290,7 @@
<p><c>FailedCaseInSequence = atom()</c>, the name of a case that failed in a sequence.</p>
<p><c>RunTimeError = term()</c>, a runtime error, for example <c>badmatch</c> or
<c>undef</c>.</p>
- <p><c>StackTrace = list()</c>, list of function calls preceeding a runtime error.</p>
+ <p><c>StackTrace = list()</c>, list of function calls preceding a runtime error.</p>
<p><c>UserTerm = term()</c>, any data specified by user, or <c>exit/1</c> information.</p>
<p>This event is sent for every test case or configuration function that <c>Common Test</c>
has skipped automatically because of either a failed <c>init_per_suite</c> or
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index d1390b6dfc..c8e8e4a3e3 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,158 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.24</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Renamed undocumented macro <c>CT_PEER/3</c> to
+ <c>CT_PEER_REL/3</c>.</p>
+ <p>
+ Own Id: OTP-18460</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.23.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change timeout to infinity for gen_server calls in
+ cth_log_redirect</p>
+ <p>
+ Own Id: OTP-18363 Aux Id: ERIERL-879 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.23.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix starting of peer nodes on old releases when the
+ compile server was active and the current Erlang
+ installation contained non-latin1 characters in its path.</p>
+ <p>
+ Own Id: OTP-18255 Aux Id: PR-6314 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.23.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix cth_surefire to handle when a suite is not compiled
+ with <c>debug_info</c>. This bug has been present since
+ Erlang/OTP 25.0.</p>
+ <p>
+ Own Id: OTP-18208 Aux Id: ERIERL-852 PR-6229 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Common Test now preserves stack traces for throws.</p>
+ <p>
+ Own Id: OTP-18138 Aux Id: GH-5719, PR-6029 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.23</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug when running parallel test cases and together
+ with one or more ct hooks that would cause the hook lock
+ process to crash and produce printouts in the ct logs.</p>
+ <p>
+ Own Id: OTP-17881 Aux Id: PR-5581 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>
+ Remove unused and undocumented tracer node functionality.</p>
+ <p>
+ Own Id: OTP-17676 Aux Id: PR-5021 </p>
+ </item>
+ <item>
+ <p>
+ The new module <c>peer</c> supersedes the <c>slave</c>
+ module. The <c>slave</c> module is now deprecated and
+ will be removed in OTP 27.</p>
+ <p>
+ <c>peer</c> contains an extended and more robust API for
+ starting erlang nodes.</p>
+ <p>
+ Own Id: OTP-17720 Aux Id: PR-5162 </p>
+ </item>
+ <item>
+ <p>
+ The cth_surefire ct hook has been updated to include the
+ file and line number of the executed test case in the xml
+ output.</p>
+ <p>
+ The performance of the hook has also been improved
+ greatly for test runs with many test cases.</p>
+ <p>
+ Own Id: OTP-17882 Aux Id: PR-5581 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Common_Test 1.22.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change timeout to infinity for gen_server calls in
+ cth_log_redirect</p>
+ <p>
+ Own Id: OTP-18363 Aux Id: ERIERL-879 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.22.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -183,6 +335,21 @@
</section>
+<section><title>Common_Test 1.20.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ OTP internal test fix.</p>
+ <p>
+ Own Id: OTP-17888</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.20.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -258,7 +425,7 @@
<item>
<p>
A race condition could cause ct_netconfc:open/* to return
- a disfunctional handle, resulting in errors when invoking
+ a dysfunctional handle, resulting in errors when invoking
other api functions on it, and making it impossible to
establish a new connection to the server in question.
Similar symptoms were possible with open/* in modules
@@ -349,6 +516,21 @@
</section>
+<section><title>Common_Test 1.18.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ OTP internal test fix.</p>
+ <p>
+ Own Id: OTP-17888</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.18.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2272,7 +2454,7 @@
<c>{end_per_group,GroupName}</c>.</item> <item>When
<c>require</c> fails in an info function, such as suite/0
or group/1, the init configuration function is now
- reported as <c>auto_skipped</c> intead of <c>skipped</c>,
+ reported as <c>auto_skipped</c> instead of <c>skipped</c>,
with the <c>tc_done</c> event.</item> <item>When
<c>require</c> fails in an info function because of a
configuration name already in use, the <c>tc_done</c>
@@ -2573,7 +2755,7 @@
<list>
<item>
<p>
- Removed depricated run_test program, use ct_run instead.</p>
+ Removed deprecated run_test program, use ct_run instead.</p>
<p>
*** POTENTIAL INCOMPATIBILITY ***</p>
<p>
@@ -3066,7 +3248,7 @@
reference manual pages for details about which keys are
allowed.</p>
<p>
- This change introduces a backwards incompatability in the
+ This change introduces a backwards incompatibility in the
<c>ct:require/2</c> interface. Previously when doing
<c>ct:require(a_name,{key,subkey})</c>, a_name would be
associated with key. This has been changed to that
@@ -3413,7 +3595,7 @@
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
+ the fault actually occurred, 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>
@@ -3699,7 +3881,7 @@
</item>
<item>
<p>
- If a timetrap timeout occured during execution of of a
+ If a timetrap timeout occurred during execution of of a
function in a lib module (i.e. a function called directly
or indirectly from a test case), the Suite argument in
the end_tc/3 framework callback function would not
@@ -3966,11 +4148,11 @@
<item>
<p>
Alpha release of Common Test Hooks (CTH). CTHs allow the
- users of common test to abtract out common behaviours
+ users of common test to abstract out common behaviours
from test suites in a much more elegant and flexible way
than was possible before. Note that the addition of this
feature may introduce minor changes in the undocumented
- behaviour of the interface inbetween common_test and
+ behaviour of the interface between common_test and
test_server.</p>
<p>
*** POTENTIAL INCOMPATIBILITY ***</p>
@@ -4118,7 +4300,7 @@
<p>
It is now possible for the user to provide specific
callback modules that handle test configuration data, so
- that data on arbitray form can be accessed (e.g. by
+ that data on arbitrary form can be accessed (e.g. by
reading files or by communicating with a configuration
server process). Two default callback modules have been
introduced in Common Test: ct_config_plain and
@@ -4539,7 +4721,7 @@
definitions). The properties make it possible to execute
test cases in parallel, in sequence and in shuffled
order. It is also possible to repeat test cases according
- to different criterias. The properties can be combined,
+ to different criteria. The properties can be combined,
making it possible to e.g. repeat a conf case a certain
number of times and execute the test cases in different
(random) order every time. Available properties are:
diff --git a/lib/common_test/doc/src/unix_telnet.xml b/lib/common_test/doc/src/unix_telnet.xml
index d9905aec32..1f54d2bef1 100644
--- a/lib/common_test/doc/src/unix_telnet.xml
+++ b/lib/common_test/doc/src/unix_telnet.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2010</year><year>2020</year>
+ <year>2010</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -75,7 +75,7 @@
<p>The <c>{port,PortNum}</c> tuple is optional and if omitted, default
Telnet port 23 is used. Also the <c>keep_alive</c> tuple is optional,
- and the value defauls to <c>true</c> (enabled).</p>
+ and the value default to <c>true</c> (enabled).</p>
</description>
<funcs>
diff --git a/lib/common_test/doc/src/write_test_chapter.xml b/lib/common_test/doc/src/write_test_chapter.xml
index ea5e54f73e..8f7c7e8177 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>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -449,7 +449,7 @@
functions and execution properties. Test case groups are defined by
function
<seemfa marker="ct_suite#Module:groups/0"><c>groups/0</c></seemfa>
- according to the following syntax:</p>
+ that should return a term having the following syntax:</p>
<pre>
groups() -> GroupDefs
@@ -551,6 +551,20 @@
[{tests2, default,
[{tests3, [parallel,{repeat,100}]}]}]}].</pre>
+ <p>For ease of readability, all syntax definitions can be replaced by a function
+ call whose return value should match the expected syntax case.</p>
+ <p><em>Example:</em></p>
+ <pre>
+ all() ->
+ [{group, tests1, default, test_cases()},
+ {group, tests1, default, [shuffle_test(),
+ {tests3, default}]}].
+ test_cases() ->
+ [{tests2, [parallel]}, {tests3, default}].
+
+ shuffle_test() ->
+ {tests2, [shuffle,{repeat,10}]}.</pre>
+
<p>The described syntax can also be used in test specifications
to change group properties at the time of execution,
without having to edit the test suite. For more information, see
@@ -917,7 +931,7 @@
can be enabled with start option <c>scale_timetraps</c>.</p>
<p>If a test case needs to suspend itself for a time that also gets
- multipled by <c>multiply_timetraps</c> (and possibly also scaled up if
+ multiplied by <c>multiply_timetraps</c> (and possibly also scaled up if
<c>scale_timetraps</c> is enabled), the function
<seemfa marker="ct#sleep/1"><c>ct:sleep/1</c></seemfa>
can be used (instead of, for example, <c>timer:sleep/1</c>).</p>
diff --git a/lib/common_test/include/ct.hrl b/lib/common_test/include/ct.hrl
index 2c947020e7..c007db8f44 100644
--- a/lib/common_test/include/ct.hrl
+++ b/lib/common_test/include/ct.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,17 @@
-define(CT_HOOK_INIT_PROCESS, ct_util_server).
-define(CT_HOOK_TERMINATE_PROCESS, ct_util_server).
+%% Peer node names generated for Common Test purposes:
+-define(CT_PEER_NAME(TestCase), test_server:peer_name(?MODULE_STRING, TestCase)).
+-define(CT_PEER_NAME(), ?CT_PEER_NAME(?FUNCTION_NAME)).
+
+%% Start nodes with command line arguments or extended options
+-define(CT_PEER(Opts), test_server:start_peer(Opts, ?MODULE, ?FUNCTION_NAME)).
+%% Start a peer with name prefix of current ?MODULE and ?FUNCTION_NAME
+-define(CT_PEER(), ?CT_PEER([])).
+%% Start a compatibility node - for OTP test suites only
+-define(CT_PEER_REL(Opts, Release, PrivDir), test_server:start_peer(Opts, ?MODULE, ?FUNCTION_NAME, Release, PrivDir)).
+
%% Backward compatibility for test_server test suites.
%% DO NOT USE IN NEW TEST SUITES.
-define(line,).
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 7d7b5ed203..00f13589f3 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2020. All Rights Reserved.
+# Copyright Ericsson AB 2003-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -133,7 +133,7 @@ APPUP_FILE= common_test.appup
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
docs:
diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src
index 8aa15efa7e..fd7025937f 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -79,20 +79,20 @@
{env, []},
{runtime_dependencies,
["compiler-6.0",
- "crypto-3.6",
+ "crypto-4.5",
"debugger-4.1",
"erts-7.0",
- "ftp-1.0.0",
+ "ftp-1.0",
"inets-6.0",
- "kernel-4.0",
+ "kernel-8.4",
"observer-2.1",
"runtime_tools-1.8.16",
- "sasl-2.4.2",
+ "sasl-2.5",
"snmp-5.1.2",
"ssh-4.0",
- "stdlib-3.5",
+ "stdlib-4.0",
"syntax_tools-1.7",
- "tools-2.8",
+ "tools-3.2",
"xmerl-1.3.8"
]}]}.
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index bfa7b25862..02c14651d9 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -296,6 +296,8 @@ capture_get([ExclCat | ExclCategories]) ->
capture_get([]) ->
test_server:capture_get().
+-spec fail(term()) -> no_return().
+
fail(Reason) ->
try
exit({test_case_failed,Reason})
@@ -308,6 +310,8 @@ fail(Reason) ->
erlang:raise(Class, R, Stk)
end.
+-spec fail(io:format(), [term()]) -> no_return().
+
fail(Format, Args) ->
try io_lib:format(Format, Args) of
Str ->
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index 439b941806..7cec4fbfdf 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -347,7 +347,7 @@ get_config(KeyOrName,Default,Opts) when is_atom(KeyOrName) ->
Else
end;
-%% This useage of get_config is only used by internal ct functions
+%% This usage 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);
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 41e9734731..765a90103c 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -735,7 +735,7 @@ end_tc(Mod,Func00,TCPid,Result,Args,Return) ->
%% clean up any saved comments
ct_util:match_delete_testdata({comment,'_'});
true ->
- %% attemp to delete any saved comment for this TC
+ %% attempt to delete any saved comment for this TC
case process_info(TCPid, group_leader) of
{group_leader,TCGL} ->
ct_util:delete_testdata({comment,TCGL});
@@ -1412,7 +1412,7 @@ end_per_group(GroupName, _) ->
report(What,Data) ->
case What of
loginfo ->
- %% logfiles and direcories have been created for a test and the
+ %% logfiles and directories have been created for a test and the
%% top level test index page needs to be refreshed
TestName = filename:basename(?val(topdir, Data), ".logs"),
RunDir = ?val(rundir, Data),
diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl
index 6e0cc76582..e501d60686 100644
--- a/lib/common_test/src/ct_gen_conn.erl
+++ b/lib/common_test/src/ct_gen_conn.erl
@@ -332,7 +332,7 @@ call(Pid, Msg, infinity = Tmo) ->
gen_call(Pid, Msg, Tmo);
%% Spawn a middleman process if the call can timeout to avoid the
-%% possibilty of a reply being left in the caller's mailbox after a
+%% possibility of a reply being left in the caller's mailbox after a
%% timeout.
call(Pid, Msg, Tmo) ->
{_, MRef} = spawn_monitor(fun() -> exit(gen_call(Pid, Msg, Tmo)) end),
diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl
index 11b0f9e665..ee851d5103 100644
--- a/lib/common_test/src/ct_groups.erl
+++ b/lib/common_test/src/ct_groups.erl
@@ -229,7 +229,7 @@ find(Mod, GrNames, TCs, [TC | Gs], Known, Defs, FindAll)
[Case | find(Mod, GrNames, TCs, Gs, Known, Defs, FindAll)]
end;
-%% Unexpeted term in group list
+%% Unexpected term in group list
find(Mod, _GrNames, _TCs, [BadTerm | _Gs], Known, _Defs, _FindAll) ->
Where = if length(Known) == 0 ->
atom_to_list(Mod)++":groups/0";
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index 57c32c17a3..23fadcbc2c 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ groups(Mod, Groups) ->
%% since this might be the first time Mod:suite()
%% is called, and it might just fail or return
%% something bad, we allow any failure here - it
- %% will be catched later if there is something
+ %% will be caught later if there is something
%% really wrong.
[{?config_name,[]}]
end,
@@ -82,7 +82,7 @@ all(Mod, Tests) ->
CTHook when is_atom(CTHook) ->
[{?config_name,[CTHook]}]
catch _:_ ->
- %% just allow any failure here - it will be catched
+ %% just allow any failure here - it will be caught
%% later if there is something really wrong.
[{?config_name,[]}]
end,
@@ -210,7 +210,7 @@ call_init(#ct_hook_config{ module = Mod, opts = Opts, id = Id, prio = P} = Hook,
{Config, Hook#ct_hook_config{ state = NewState, prio = Prio } };
{ok, NewState, _} ->
{Config, Hook#ct_hook_config{ state = NewState } };
- NewState -> %% Keep for backward compatability reasons
+ NewState -> %% Keep for backward compatibility reasons
{Config, Hook#ct_hook_config{ state = NewState } }
end.
diff --git a/lib/common_test/src/ct_hooks_lock.erl b/lib/common_test/src/ct_hooks_lock.erl
index be50a33e01..ebae37bc82 100644
--- a/lib/common_test/src/ct_hooks_lock.erl
+++ b/lib/common_test/src/ct_hooks_lock.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -109,7 +109,11 @@ handle_info({'DOWN',Ref,process,Pid,_},
gen_server:reply(NextFrom, locked),
NextRef = monitor(process, NextPid),
{noreply,State#state{ locked = {true, NextPid, NextRef},
- requests = Rest } }.
+ requests = Rest } };
+handle_info({'DOWN',Ref,process,Pid,_},
+ #state{ locked = {true, Pid, Ref},
+ requests = [] } = State) ->
+ {noreply, State#state{ locked = false } }.
terminate(_Reason, _State) ->
ok.
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index 39ce2ea9d4..679d910942 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -2574,7 +2574,7 @@ sort_and_filter_logdirs2(_,[],Groups) ->
%% new rundir for Test found, add to (not sorted) list of prev rundirs
insert_test(Test,IxDir,[{Test,IxDirs}|Groups]) ->
[{Test,[IxDir|IxDirs]}|Groups];
-%% first occurance of Test
+%% first occurrence of Test
insert_test(Test,IxDir,[]) ->
[{Test,[IxDir]}];
insert_test(Test,IxDir,[TestDir|Groups]) ->
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
index da169236d5..07f6cc1b8f 100644
--- a/lib/common_test/src/ct_netconfc.erl
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -1943,7 +1943,7 @@ indent_line("></"++Rest,Indent,Line) ->
{Indent++lists:reverse(Line)++">","</"++Rest,Indent--" "}
end;
indent_line("><"++Rest,Indent,Line) ->
- %% Stop tag completed, and new tag comming -> keep indentation
+ %% Stop tag completed, and new tag coming -> keep indentation
{Indent++lists:reverse(Line)++">","<"++Rest," "++Indent};
indent_line("</"++Rest,Indent,Line) ->
%% Stop tag starting -> search for end of this tag
diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl
index 6e6ea4086f..da556e1481 100644
--- a/lib/common_test/src/ct_release_test.erl
+++ b/lib/common_test/src/ct_release_test.erl
@@ -21,7 +21,7 @@
%% EXPERIMENTAL support for testing of upgrade.
%%
%% This is a library module containing support for test of release
-%% related activities in one or more applications. Currenty it
+%% related activities in one or more applications. Currently it
%% supports upgrade only.
%%
%% == Configuration ==
@@ -57,7 +57,7 @@
%% CtData = ct_data()
%% State = NewState = cb_state()
%%
-%% Initialyze system before upgrade test starts.
+%% Initialize system before upgrade test starts.
%%
%% This function is called before the upgrade is started. All
%% applications given in upgrade/4 are already started by
@@ -154,7 +154,7 @@
%%
%% If the initialization fails, e.g. if a required release
%% cannot be found, the function returns `{skip,Reason}'. In
-%% this case the other test support functions in this mudule
+%% this case the other test support functions in this module
%% cannot be used.
%%
%% Example:
@@ -230,20 +230,20 @@ init(Config) ->
%% `Level' specifies which OTP release to
%% pick the "From" versions from.
%% major
-%% From verions are picked from the previous major
+%% From versions are picked from the previous major
%% release. For example, if the test is run on an OTP-17
%% node, ct_release_test will pick the application
%% "From" versions from an OTP installation running OTP
%% R16B.
%%
%% minor
-%% From verions are picked from the current major
+%% From versions are picked from the current major
%% release. For example, if the test is run on an OTP-17
%% node, ct_release_test will pick the application
%% "From" versions from an OTP installation running an
%% earlier patch level of OTP-17.
%%
-%% The application "To" versions are allways picked from the
+%% The application "To" versions are always picked from the
%% current node, i.e. the common_test node.
%%
%% `Callback' specifies the module (normally the
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index a80d2476f5..4ce0d562d3 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -212,10 +212,10 @@ finish(Tracing, ExitStatus, Args) ->
case get_start_opt(halt_with,
fun([HaltMod,HaltFunc]) ->
{list_to_atom(HaltMod),
- list_to_atom(HaltFunc)} end,
- Args) of
+ list_to_atom(HaltFunc)}
+ end, Args) of
undefined ->
- halt(ExitStatus);
+ halt(ExitStatus, [{flush, false}]);
{M,F} ->
apply(M, F, [ExitStatus])
end
diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl
index dde33440be..b3cb20f48a 100644
--- a/lib/common_test/src/ct_slave.erl
+++ b/lib/common_test/src/ct_slave.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@
-export([slave_started/2, slave_ready/2, monitor_master/1]).
+-deprecated([{'_','_',"use ?CT_PEER(), or the 'peer' module instead"}]).
+
-record(options, {username, password, boot_timeout, init_timeout,
startup_timeout, startup_functions, monitor_master,
kill_if_fail, erl_flags, env, ssh_port, ssh_opts,
diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl
index 27b74dd04e..1e9333f656 100644
--- a/lib/common_test/src/ct_snmp.erl
+++ b/lib/common_test/src/ct_snmp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -237,7 +237,7 @@ prepare_snmp_env() ->
_ = application:load(snmp),
%% Fix for older versions of snmp where there are some
- %% inappropriate default values for alway starting an
+ %% inappropriate default values for always starting an
%% agent.
application:unset_env(snmp, agent).
%%%---------------------------------------------------------------------------
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index 6b237787cd..d6c69329ad 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1019,7 +1019,7 @@ seq_expect(Name,Pid,Data,Patterns,Acc,EO) ->
end.
%% seq_expect1: For one prompt-chunk, match each pattern - line by
-%% line if it is other than the prompt we are seaching for.
+%% line if it is other than the prompt we are searching for.
seq_expect1(Name,Pid,Data,[prompt|Patterns],Acc,Rest,EO) ->
case EO#eo.found_prompt of
false ->
@@ -1253,7 +1253,7 @@ split_prompt_string([Ch|Rest],_Start,End,N,UptoPrompt,Prompt) when N==End ->
{noprompt,[Ch|Prompt]++UptoPrompt,Rest};
[$\s,$t,$s,$a|_] when Prompt==":nigol" ->
%% This is probably the "Last login:" statement which is
- %% written when telnet connection is openend.
+ %% written when telnet connection is opened.
{noprompt,[Ch|Prompt]++UptoPrompt,Rest};
_ ->
{prompt,[Ch|Prompt]++UptoPrompt,[Ch|Prompt],Rest}
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
index abcf26151d..04e964f51a 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -180,7 +180,7 @@ add_log_category(#{meta:=Meta}=Log,Category) ->
Log#{meta=>Meta#{?MODULE=>#{category=>Category}}}.
do_log(Log,Config) ->
- gen_server:call(?MODULE,{log,Log,Config}).
+ gen_server:call(?MODULE,{log,Log,Config},infinity).
handle_cast(_, State) ->
{noreply,State}.
@@ -254,13 +254,13 @@ terminate(_Arg, _State) ->
ok.
set_curr_func(CurrFunc, Config) ->
- gen_server:call(?MODULE, {set_curr_func, CurrFunc, Config}).
+ gen_server:call(?MODULE, {set_curr_func, CurrFunc, Config}, infinity).
set_log_func(Func) ->
- gen_server:call(?MODULE, {set_logfunc, Func}).
+ gen_server:call(?MODULE, {set_logfunc, Func}, infinity).
handle_remote_events(Bool) ->
- gen_server:call(?MODULE, {handle_remote_events, Bool}).
+ gen_server:call(?MODULE, {handle_remote_events, Bool}, infinity).
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl
index c9b4cb10c6..578bdd6163 100644
--- a/lib/common_test/src/cth_surefire.erl
+++ b/lib/common_test/src/cth_surefire.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,13 +46,15 @@
-export([terminate/1]).
+%% Gen server callbacks
+-export([init/1, handle_call/3]).
+
-record(state, { filepath, axis, properties, package, hostname,
- curr_suite, curr_suite_ts, curr_group = [],
+ curr_suite, curr_suite_file, curr_suite_ast, curr_suite_ts, curr_group = [],
curr_log_dir, timer, tc_log, url_base,
- test_cases = [],
- test_suites = [] }).
+ test_cases = [], test_suites = []}).
--record(testcase, { log, url, group, classname, name, time, result, timestamp }).
+-record(testcase, { log, url, group, file, line, classname, name, time, result, timestamp }).
-record(testsuite, { errors, failures, skipped, hostname, name, tests,
time, timestamp, id, package,
properties, testcases, log, url }).
@@ -66,22 +68,47 @@
%% ct_run.<node>.<timestamp>/<test_name>/run.<timestamp>/<tc_log>.html
-define(log_depth,3).
+%% The gen server proxy wrapper API
+%% The state of this hook can become very large for large test suites
+%% for example diameter_traffic_SUITE
+%% so we keep the state in a separate process in order to not have to
+%% copy the full state to each testcase process. Doing it this way cuts
+%% the execution time of diameter_traffic_SUITE from 30 min to 5 min.
+init(Path, Opts) ->
+ {ok, Pid} = gen_server:start(?MODULE, [Path, Opts], []),
+ Pid.
+
+init([Path, Opts]) ->
+ ct_util:mark_process(),
+ {ok, Host} = inet:gethostname(),
+ {ok, #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,[]),
+ url_base = proplists:get_value(url_base,Opts),
+ timer = ?now }}.
+
+handle_call({terminate, Args}, _From, State) ->
+ Res = apply(?MODULE, terminate, Args ++ [State]),
+ {stop, normal, Res, State};
+handle_call({Function, Args}, _From, State)
+ when Function =:= on_tc_fail;
+ Function =:= on_tc_skip ->
+ NewState = apply(?MODULE, Function, Args ++ [State]),
+ {reply, ok, NewState};
+handle_call({Function, Args}, _From, State) ->
+ {Reply,NewState} = apply(?MODULE, Function, Args ++ [State]),
+ {reply,Reply,NewState}.
+
id(Opts) ->
case proplists:get_value(path, Opts) of
undefined -> ?default_report;
Path -> filename:absname(Path)
end.
-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,[]),
- url_base = proplists:get_value(url_base,Opts),
- timer = ?now }.
-
+pre_init_per_suite(Suite,SkipOrFail,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, SkipOrFail]}),Proxy};
pre_init_per_suite(Suite,SkipOrFail,#state{ test_cases = [] } = State)
when is_tuple(SkipOrFail) ->
{SkipOrFail, init_tc(State#state{curr_suite = Suite,
@@ -98,8 +125,24 @@ pre_init_per_suite(Suite,Config,#state{ test_cases = [] } = State) ->
P ->
P
end,
+ Ast =
+ case beam_lib:chunks(code:which(Suite),[debug_info]) of
+ {ok,{Suite,[{debug_info,
+ {debug_info_v1,
+ erl_abstract_code,
+ {Abstr,_Opts}}}]}} ->
+ if Abstr =:= none ->
+ undefined;
+ true ->
+ Abstr
+ end;
+ _ ->
+ undefined
+ end,
{Config, init_tc(State#state{ filepath = Path,
curr_suite = Suite,
+ curr_suite_file = get_file(Suite),
+ curr_suite_ast = Ast,
curr_suite_ts = ?now,
curr_log_dir = CurrLogDir},
Config) };
@@ -107,45 +150,101 @@ pre_init_per_suite(Suite,Config,State) ->
%% Have to close the previous suite
pre_init_per_suite(Suite,Config,close_suite(State)).
+get_file(Suite) ->
+ case beam_lib:chunks(code:which(Suite),["CInf"]) of
+ {ok,{_,[{"CInf",Bin}]}} ->
+ Source = proplists:get_value(source,binary_to_term(Bin)),
+ case filelib:is_file(Source) of
+ true ->
+ Source;
+ false ->
+ undefined
+ end;
+ _ ->
+ undefined
+ end.
+
+post_init_per_suite(Suite,Config, Result, Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, Config, Result]}),Proxy};
post_init_per_suite(_Suite,Config, Result, State) ->
{Result, end_tc(init_per_suite,Config,Result,State)}.
+pre_end_per_suite(Suite,Config,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, Config]}),Proxy};
pre_end_per_suite(_Suite,Config,State) ->
{Config, init_tc(State, Config)}.
+post_end_per_suite(Suite,Config,Result,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, Config, Result]}),Proxy};
post_end_per_suite(_Suite,Config,Result,State) ->
{Result, end_tc(end_per_suite,Config,Result,State)}.
+pre_init_per_group(Suite,Group,Config,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, Group, Config]}),Proxy};
pre_init_per_group(_Suite,Group,Config,State) ->
{Config, init_tc(State#state{ curr_group = [Group|State#state.curr_group]},
Config)}.
+post_init_per_group(Suite,Group,Config,Result,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, Group, Config, Result]}),Proxy};
post_init_per_group(_Suite,_Group,Config,Result,State) ->
{Result, end_tc(init_per_group,Config,Result,State)}.
+pre_end_per_group(Suite,Group,Config,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, Group, Config]}),Proxy};
pre_end_per_group(_Suite,_Group,Config,State) ->
{Config, init_tc(State, Config)}.
+post_end_per_group(Suite,Group,Config,Result,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite,Group,Config,Result]}),Proxy};
post_end_per_group(_Suite,_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(Suite,TC,Config,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite,TC,Config]}),Proxy};
pre_init_per_testcase(_Suite,_TC,Config,State) ->
{Config, init_tc(State, Config)}.
+post_end_per_testcase(Suite,TC,Config,Result,Proxy) when is_pid(Proxy) ->
+ {gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, TC, Config, Result]}),Proxy};
post_end_per_testcase(_Suite,TC,Config,Result,State) ->
{Result, end_tc(TC,Config, Result,State)}.
+on_tc_fail(Suite,TC,Result,Proxy) when is_pid(Proxy) ->
+ _ = gen_server:call(Proxy,{?FUNCTION_NAME, [Suite, TC, Result]}),
+ Proxy;
on_tc_fail(_Suite,_TC, _Res, State = #state{test_cases = []}) ->
State;
-on_tc_fail(_Suite,_TC, Res, State) ->
+on_tc_fail(Suite, _TC, Res, State) ->
TCs = State#state.test_cases,
TC = hd(TCs),
+ Line = case get_line_from_result(Suite, Res) of
+ undefined ->
+ TC#testcase.line;
+ L -> L
+ end,
NewTC = TC#testcase{
+ line = Line,
result =
{fail,lists:flatten(io_lib:format("~tp",[Res]))} },
State#state{ test_cases = [NewTC | tl(TCs)]}.
+get_line_from_result(Suite, {_Error, [{__M,__F,__A,__I}|_] = StackTrace}) ->
+ case lists:filter(fun({Mod, _Func, _Arity, _Info}) ->
+ Mod =:= Suite
+ end, StackTrace) of
+ [{Suite,_F,_A, Info} | _ ] ->
+ proplists:get_value(line, Info);
+ _ ->
+ undefined
+ end;
+get_line_from_result(_, _) ->
+ undefined.
+
+on_tc_skip(Suite,TC,Result,Proxy) when is_pid(Proxy) ->
+ _ = gen_server:call(Proxy,{?FUNCTION_NAME, [Suite,TC,Result]}),
+ Proxy;
on_tc_skip(Suite,{ConfigFunc,_GrName}, Res, State) ->
on_tc_skip(Suite,ConfigFunc, Res, State);
on_tc_skip(Suite,Tc, Res, State0) ->
@@ -171,23 +270,29 @@ 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, [])}.
+ 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(Func, Config, Res, State = #state{ tc_log = "" }) ->
+ end_tc(Func, Config, Res, State#state{ tc_log = proplists:get_value(tc_logfile, Config) });
end_tc(Name, _Config, _Res, State = #state{ curr_suite = Suite,
curr_group = Groups,
curr_log_dir = CurrLogDir,
timer = TS,
- tc_log = Log0,
url_base = UrlBase } ) ->
Log =
- case Log0 of
- "" ->
+ case State#state.tc_log of
+ undefined ->
LowerSuiteName = string:lowercase(atom_to_list(Suite)),
- filename:join(CurrLogDir,LowerSuiteName++"."++Name++".html");
- _ ->
- Log0
+ case filelib:wildcard(filename:join(CurrLogDir,LowerSuiteName++"."++Name++".*html")) of
+ [] ->
+ "";
+ [LogFile|_] ->
+ LogFile
+ end;
+ LogFile ->
+ LogFile
end,
Url = make_url(UrlBase,Log),
ClassName = atom_to_list(Suite),
@@ -200,6 +305,9 @@ end_tc(Name, _Config, _Res, State = #state{ curr_suite = Suite,
group = PGroup,
name = Name,
time = TimeTakes,
+ file = State#state.curr_suite_file,
+ line = get_line_from_suite(
+ State#state.curr_suite_ast, Name),
result = passed }|
State#state.test_cases],
tc_log = ""}. % so old tc_log is not set if next is on_tc_skip
@@ -232,6 +340,9 @@ close_suite(#state{ test_cases = TCs, url_base = UrlBase } = State) ->
test_cases = [],
test_suites = [Suite | State#state.test_suites]}.
+terminate(Proxy) when is_pid(Proxy) ->
+ gen_server:call(Proxy,{?FUNCTION_NAME, []}),
+ ok;
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\" ?>", []),
@@ -242,15 +353,33 @@ terminate(State) ->
%% Have to close the last suite
terminate(close_suite(State)).
+get_line_from_suite(undefined, _TC) ->
+ undefined;
+get_line_from_suite(Abstr, TC) ->
+ case [Anno || {function,Anno,Name,1,_} <- Abstr, TC =:= atom_to_list(Name)] of
+ [{Line,_Col}] ->
+ Line;
+ _ ->
+ case [Anno || {function,Anno,Name,_,_} <- Abstr, TC =:= atom_to_list(Name)] of
+ [{Line,_}|_] ->
+ Line;
+ _ ->
+ undefined
+ end
+ end.
-to_xml(#testcase{ group = Group, classname = CL, log = L, url = U, name = N, time = T, timestamp = TS, result = R}) ->
+to_xml(#testcase{ group = Group, classname = CL, log = L, url = U,
+ file = File, line = Line,
+ name = N, time = T, timestamp = TS, result = R}) ->
["<testcase ",
[["group=\"",Group,"\" "]||Group /= ""],
"name=\"",N,"\" "
"time=\"",T,"\" "
"timestamp=\"",TS,"\" ",
[["url=\"",U,"\" "]||U /= undefined],
+ [["file=\"",File,"\" "]||File /= undefined],
+ [["line=\"",integer_to_list(Line),"\" "]||Line /= undefined],
"log=\"",L,"\">",
case R of
passed ->
diff --git a/lib/common_test/src/erl2html2.erl b/lib/common_test/src/erl2html2.erl
index 7f3eb699de..cb000bafd6 100644
--- a/lib/common_test/src/erl2html2.erl
+++ b/lib/common_test/src/erl2html2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -287,7 +287,7 @@ encoding(File) ->
end.
%%%-----------------------------------------------------------------
-%%% Covert encoding atom to string for use in HTML header
+%%% Convert encoding atom to string for use in HTML header
html_encoding(latin1) ->
"iso-8859-1";
html_encoding(utf8) ->
diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl
index 1f7c565d09..feb607b46e 100644
--- a/lib/common_test/src/test_server.erl
+++ b/lib/common_test/src/test_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,10 +39,10 @@
-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([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1, find_release/1]).
+-export([peer_name/2, start_peer/3, start_peer/5]).
-export([app_test/1, app_test/2, appup_test/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]).
@@ -347,8 +347,7 @@ stick_all_sticky(Node,Sticky) ->
%% Returns a tuple with the time spent (in seconds) in the test case,
%% the return value from the test case or an {'EXIT',Reason} if the case
%% failed, Loc points out where the test case crashed (if it did). Loc
-%% is either the name of the function, or {<Module>,<Line>} of the last
-%% line executed that had a ?line macro. If the test case did execute
+%% is the name of the function. If the test case did execute
%% erase/0 or similar, it may be empty. Comment is the last comment added
%% by test_server:comment/1, the reason if test_server:fail has been
%% called or the comment given by the return value {comment,Comment} from
@@ -360,7 +359,7 @@ stick_all_sticky(Node,Sticky) ->
%% TimetrapData = {MultiplyTimetrap,ScaleTimetrap}, which indicates a
%% possible extension of all timetraps. Timetraps will be multiplied by
%% MultiplyTimetrap. If it is infinity, no timetraps will be started at all.
-%% ScaleTimetrap indicates if test_server should attemp to automatically
+%% ScaleTimetrap indicates if test_server should attempt to automatically
%% compensate timetraps for runtime delays introduced by e.g. tools like
%% cover.
@@ -1790,7 +1789,7 @@ ts_tc(M, F, A) ->
set_loc(Stk),
case Type of
throw ->
- {failed,{thrown,Reason}};
+ {failed,{thrown,{Reason,Stk}}};
error ->
{'EXIT',{Reason,Stk}};
exit ->
@@ -1889,7 +1888,7 @@ capture_stop() ->
%% Note that since output arrive as messages to the process, it takes
%% a short while from the call to io:format until all output is available
%% by capture_get/0. It is not necessary to call capture_stop/0 before
-%% retreiving the output.
+%% retrieving the output.
capture_get() ->
test_server_sup:capture_get([]).
@@ -1970,6 +1969,9 @@ adjusted_sleep(MSecs) ->
%%
%% Immediately calls exit. Included because test suites are easier
%% to read when using this function, rather than exit directly.
+
+-spec fail(term()) -> no_return().
+
fail(Reason) ->
comment(cast_to_list(Reason)),
try
@@ -1994,6 +1996,9 @@ cast_to_list(X) -> lists:flatten(io_lib:format("~tp", [X])).
%%
%% Immediately calls exit. Included because test suites are easier
%% to read when using this function, rather than exit directly.
+
+-spec fail() -> no_return().
+
fail() ->
try
exit(suite_failed)
@@ -2553,10 +2558,10 @@ m_out_of_n(M,N,Fun) ->
%% Time - integer() in milliseconds.
%% Crash - term()
%%
-%% Spaws a new process that calls MFA. The call is considered
+%% Spawns a new process that calls MFA. The call is considered
%% successful if the call crashes with the given reason (Crash),
%% or any other reason if Crash is not specified.
-%% ** The call must terminate withing the given Time (defaults
+%% ** The call must terminate within the given Time (defaults
%% to infinity), or it is considered a failure (exit with reason
%% 'call_crash_timeout' is generated).
@@ -2575,14 +2580,12 @@ call_crash(Time,Crash,M,F,A) ->
%% Type = slave | peer
%% Options = [{tuple(), term()}]
%%
-%% OptionList is a tuplelist wich may contain one
+%% OptionList is a tuplelist which may contain one
%% or more of these members:
%%
%% Slave and Peer:
%% {remote, true} - Start the node on a remote host. If not specified,
-%% the node will be started on the local host (with
-%% some exceptions, for instance VxWorks,
-%% where all nodes are started on a remote host).
+%% the node will be started on the local host.
%% {args, Arguments} - Arguments passed directly to the node.
%% {cleanup, false} - Nodes started with this option will not be killed
%% by the test server after completion of the test case
@@ -2687,6 +2690,7 @@ wait_for_node(Slave) ->
end,
Result.
+-compile([{nowarn_deprecated_function, [{slave, stop, 1}]}]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% stop_node(Name) -> true|false
@@ -2766,6 +2770,118 @@ is_release_available(Release) ->
{test_server_ctrl,is_release_available,[Release]}},
receive {sync_result,R} -> R end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% find_release(Release) -> PathToReleaseErlFile | not_available
+%% Release -> string()
+%%
+%% Test if a release (such as "r10b") and if so return the path to the
+%% release's erl file
+
+find_release(Release) ->
+ group_leader() ! {sync_apply,
+ self(),
+ {test_server_ctrl,find_release,[Release]}},
+ receive {sync_result,R} -> R end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% API for starting peer nodes according to Common Test conventions
+peer_name(Module, TestCase) ->
+ peer:random_name(lists:concat([Module, "-", TestCase])).
+
+%% Command line arguments passed
+-spec start_peer([string()] | peer:start_options(), atom() | string(), TestCase :: atom() | string()) ->
+ {ok, gen_statem:server_ref(), node()} | {error, term()}.
+start_peer(Args, Module, TestCase) when is_list(Args) ->
+ start_peer(#{args => Args, name => peer_name(Module, TestCase)}, Module);
+
+%% Full set of options passed
+start_peer(#{name := _Name} = Opts, Module, _TestCase) ->
+ start_peer(Opts, Module);
+start_peer(Opts, Module, TestCase) ->
+ start_peer(Opts#{name => peer_name(Module, TestCase)}, Module).
+
+%% Release compatibility testing
+-spec start_peer([string()] | peer:start_options(), atom() | string(), TestCase :: atom() | string(),
+ Release :: string(), OutDir :: file:filename()) ->
+ {ok, gen_statem:server_ref(), node()} | {error, term()} | not_available.
+start_peer(Args, Module, TestCase, Release, OutDir) when is_list(Args) ->
+ start_peer(#{args => Args}, Module, TestCase, Release, OutDir);
+start_peer(Opts, Module, TestCase, Release, OutDir) ->
+ case find_release(Release) of
+ not_available ->
+ not_available;
+ Erl ->
+ %% remove ERL_AFLAGS, because they may contain "-emu_type debug" which does not exist
+ %% for old releases. Keep ERL_FLAGS, and ERL_ZFLAGS for sometimes you might need it...
+ Env = maps:get(env, Opts, []) ++ [{"ERL_AFLAGS", false}],
+ NewArgs = ["-pa", peer_compile(Erl, code:which(peer), OutDir) | maps:get(args, Opts, [])],
+ start_peer(Opts#{exec => Erl, args => NewArgs,
+ env => Env}, Module, TestCase)
+ end.
+
+%% Internal implementation
+start_peer(#{name := Name} = Opts, Module) ->
+ CrashDir = test_server_sup:crash_dump_dir(),
+ CrashFile = filename:join([CrashDir, lists:concat(["erl_crash_dump.", Name])]),
+ Args = maps:get(args, Opts, []),
+ CookieArg =
+ case lists:member("-setcookie", Args) of
+ false ->
+ ["-setcookie", atom_to_list(erlang:get_cookie())];
+ true ->
+ []
+ end,
+ FullArgs = CookieArg ++ ["-pa", filename:dirname(code:which(Module)),
+ "-env", "ERL_CRASH_DUMP", CrashFile] ++ Args,
+ %% start_cover => false is intentionally undocumented, and is not
+ %% expected to be used by anything but cover_SUITE test.
+ case maps:get(start_cover, Opts, true) andalso test_server:is_cover() of
+ true ->
+ %% when cover is active, node must shut down gracefully, otherwise
+ %% coverage information won't be sent to cover master
+ CoverMain = cover:get_main_node(),
+ %% next line is a way to trick Dialyzer into not complaining over undocumented type
+ Shutdown = binary_to_term(term_to_binary({10000, CoverMain})),
+ case peer:start_link(Opts#{args => FullArgs, shutdown => Shutdown}) of
+ {ok, Peer, Node} ->
+ do_cover_for_node(Node, start),
+ {ok, Peer, Node};
+ Other ->
+ Other
+ end;
+ false ->
+ peer:start_link(Opts#{args => FullArgs})
+ end.
+
+%% When a different release is requested, peer.erl needs to be compiled for
+%% that specific release using the path supplied for 'erl'
+peer_compile(Erl, cover_compiled, OutDir) ->
+ {file, Path} = cover:is_compiled(peer),
+ peer_compile(Erl, Path, OutDir);
+peer_compile(Erl, ModPath, OutDir) ->
+ {ok, ModSrc} = filelib:find_source(ModPath),
+ Erlc = filename:join(filename:dirname(Erl), "erlc"),
+ cmd(Erlc, ["-o", OutDir, ModSrc]),
+ OutDir.
+
+%% This should really be implemented as os:cmd.
+cmd(Exec, Args) ->
+ %% remove all ERL_AFLAGS to drop "-emu_type debug" and similar
+ %% remote ERLC_COMPILE_SERVER because of a bug in pre 25.2 Erlang/OTP
+ Env = [{"ERL_AFLAGS", false},{"ERLC_USE_SERVER",false}],
+ Port = open_port({spawn_executable, Exec}, [{args, Args}, {env, Env},
+ stream, binary, exit_status, stderr_to_stdout]),
+ read_std(Port, lists:join(" ", [Exec|Args]), <<>>).
+
+read_std(Port, Exec, Out) ->
+ receive
+ {Port, {data, More}} ->
+ read_std(Port, Exec, <<Out/binary, More/binary>>);
+ {Port, {exit_status, 0}} ->
+ Out;
+ {Port, {exit_status, Status}} ->
+ erlang:error({exit, Status, Exec, Out})
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% run_on_shielded_node(Fun, CArgs) -> term()
@@ -2911,15 +3027,6 @@ make_priv_dir() ->
tc_supervisor_req(make_priv_dir).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% os_type() -> OsType
-%%
-%% Returns the OsType of the target node. OsType is
-%% the same as returned from os:type()
-os_type() ->
- os:type().
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% is_cover() -> boolean()
%%
%% Returns true if cover is running, else false
diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl
index e80e899c44..538ea0de44 100644
--- a/lib/common_test/src/test_server_ctrl.erl
+++ b/lib/common_test/src/test_server_ctrl.erl
@@ -54,15 +54,14 @@
-export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]).
-export([create_priv_dir/1]).
-export([cover/1, cover/2, cover/3,
- cover_compile/7, cover_analyse/2, cross_cover_analyse/2,
- trc/1, stop_trace/0]).
+ cover_compile/7, cover_analyse/2, cross_cover_analyse/2]).
-export([testcase_callback/1]).
-export([set_random_seed/1]).
-export([kill_slavenodes/0]).
%%% TEST_SERVER INTERFACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export([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([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1, find_release/1]).
-export([format/1, format/2, format/3, to_string/1]).
-export([get_target_info/0]).
-export([get_hosts/0]).
@@ -115,7 +114,7 @@
-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=[],
+ target_info, cover=false, wait_for_node=[],
testcase_callback=undefined, idle_notify=[],
get_totals=false, random_seed=undefined}).
@@ -224,55 +223,53 @@ add_tests_with_skip(LogDir, Tests, Skip) ->
%% COMMAND LINE INTERFACE
parse_cmd_line(Cmds) ->
- parse_cmd_line(Cmds, [], [], local, false, false, undefined).
+ parse_cmd_line(Cmds, [], [], local, false, undefined).
-parse_cmd_line(['SPEC',Spec|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+parse_cmd_line(['SPEC',Spec|Cmds], SpecList, Names, Param, Cov, TCCB) ->
case file:consult(Spec) of
{ok, TermList} ->
Name = filename:rootname(Spec),
parse_cmd_line(Cmds, TermList++SpecList, [Name|Names], Param,
- Trc, Cov, TCCB);
+ Cov, TCCB);
{error,Reason} ->
io:format("Can't open ~tw: ~tp\n",[Spec, file:format_error(Reason)]),
- parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, TCCB)
+ parse_cmd_line(Cmds, SpecList, Names, Param, Cov, TCCB)
end;
-parse_cmd_line(['NAME',Name|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+parse_cmd_line(['NAME',Name|Cmds], SpecList, Names, Param, Cov, TCCB) ->
parse_cmd_line(Cmds, SpecList, [{name,atom_to_list(Name)}|Names],
- Param, Trc, Cov, TCCB);
-parse_cmd_line(['SKIPMOD',Mod|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+ Param, Cov, TCCB);
+parse_cmd_line(['SKIPMOD',Mod|Cmds], SpecList, Names, Param, Cov, TCCB) ->
parse_cmd_line(Cmds, [{skip,{Mod,"by command line"}}|SpecList], Names,
- Param, Trc, Cov, TCCB);
-parse_cmd_line(['SKIPCASE',Mod,Case|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+ Param, Cov, TCCB);
+parse_cmd_line(['SKIPCASE',Mod,Case|Cmds], SpecList, Names, Param, Cov, TCCB) ->
parse_cmd_line(Cmds, [{skip,{Mod,Case,"by command line"}}|SpecList], Names,
- Param, Trc, Cov, TCCB);
-parse_cmd_line(['DIR',Dir|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+ Param, Cov, TCCB);
+parse_cmd_line(['DIR',Dir|Cmds], SpecList, Names, Param, Cov, TCCB) ->
Name = filename:basename(Dir),
parse_cmd_line(Cmds, [{topcase,{dir,Name}}|SpecList], [Name|Names],
- Param, Trc, Cov, TCCB);
-parse_cmd_line(['MODULE',Mod|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+ Param, Cov, TCCB);
+parse_cmd_line(['MODULE',Mod|Cmds], SpecList, Names, Param, Cov, TCCB) ->
parse_cmd_line(Cmds,[{topcase,{Mod,all}}|SpecList],[atom_to_list(Mod)|Names],
- Param, Trc, Cov, TCCB);
-parse_cmd_line(['CASE',Mod,Case|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
+ Param, Cov, TCCB);
+parse_cmd_line(['CASE',Mod,Case|Cmds], SpecList, Names, Param, Cov, TCCB) ->
parse_cmd_line(Cmds,[{topcase,{Mod,Case}}|SpecList],[atom_to_list(Mod)|Names],
- Param, Trc, Cov, TCCB);
-parse_cmd_line(['TRACE',Trc|Cmds], SpecList, Names, Param, _Trc, Cov, TCCB) ->
- parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, TCCB);
-parse_cmd_line(['COVER',App,CF,Analyse|Cmds], SpecList, Names, Param, Trc, _Cov, TCCB) ->
- parse_cmd_line(Cmds, SpecList, Names, Param, Trc, {{App,CF}, Analyse}, TCCB);
-parse_cmd_line(['TESTCASE_CALLBACK',Mod,Func|Cmds], SpecList, Names, Param, Trc, Cov, _) ->
- parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, {Mod,Func});
-parse_cmd_line([Obj|_Cmds], _SpecList, _Names, _Param, _Trc, _Cov, _TCCB) ->
+ Param, Cov, TCCB);
+parse_cmd_line(['COVER',App,CF,Analyse|Cmds], SpecList, Names, Param, _Cov, TCCB) ->
+ parse_cmd_line(Cmds, SpecList, Names, Param, {{App,CF}, Analyse}, TCCB);
+parse_cmd_line(['TESTCASE_CALLBACK',Mod,Func|Cmds], SpecList, Names, Param, Cov, _) ->
+ parse_cmd_line(Cmds, SpecList, Names, Param, Cov, {Mod,Func});
+parse_cmd_line([Obj|_Cmds], _SpecList, _Names, _Param, __Cov, _TCCB) ->
io:format("~w: Bad argument: ~tw\n", [?MODULE,Obj]),
io:format(" Use the `ts' module to start tests.\n", []),
io:format(" (If you ARE using `ts', there is a bug in `ts'.)\n", []),
halt(1);
-parse_cmd_line([], SpecList, Names, Param, Trc, Cov, TCCB) ->
+parse_cmd_line([], SpecList, Names, Param, Cov, TCCB) ->
NameList = lists:reverse(Names, ["suite"]),
Name = case lists:keysearch(name, 1, NameList) of
{value,{name,N}} -> N;
false -> hd(NameList)
end,
- {lists:reverse(SpecList), Name, Param, Trc, Cov, TCCB}.
+ {lists:reverse(SpecList), Name, Param, Cov, TCCB}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% cast_to_list(X) -> string()
@@ -311,12 +308,8 @@ start_link() ->
run_test(CommandLine) ->
process_flag(trap_exit,true),
- {SpecList,Name,Param,Trc,Cov,TCCB} = parse_cmd_line(CommandLine),
+ {SpecList,Name,Param,Cov,TCCB} = parse_cmd_line(CommandLine),
{ok,_TSPid} = start_link(Param),
- case Trc of
- false -> ok;
- File -> trc(File)
- end,
case Cov of
false -> ok;
{{App,CoverFile},Analyse} -> cover(App, maybe_file(CoverFile), Analyse)
@@ -399,12 +392,6 @@ get_timetrap_parameters() ->
create_priv_dir(Value) ->
controller_call({create_priv_dir,Value}).
-trc(TraceFile) ->
- controller_call({trace,TraceFile}, 2*?ACCEPT_TIMEOUT).
-
-stop_trace() ->
- controller_call(stop_trace).
-
node_started(Node) ->
gen_server:cast(?MODULE, {node_started,Node}).
@@ -696,7 +683,7 @@ handle_call({finish,Fini}, _From, State) ->
%% handle_call({idle_notify,Fun}, From, State) -> {ok,Pid}
%%
%% Lets a test client subscribe to receive a notification when the
-%% test server becomes idle (can be used to syncronize jobs).
+%% test server becomes idle (can be used to synchronize jobs).
%% test_server calls Fun(From) when idle.
handle_call({idle_notify,Fun}, {Cli,_Ref}, State) ->
@@ -721,7 +708,7 @@ handle_call({start_get_totals,Fun}, {Cli,_Ref}, State) ->
%% handle_call(stop_get_totals, From, State) -> ok
%%
%% Lets a test client subscribe to receive a notification when the
-%% test server becomes idle (can be used to syncronize jobs).
+%% test server becomes idle (can be used to synchronize jobs).
%% test_server calls Fun(From) when idle.
handle_call(stop_get_totals, {_Cli,_Ref}, State) ->
@@ -796,45 +783,6 @@ handle_call(get_timetrap_parameters, _From, State) ->
{reply,{State#state.multiply_timetraps,State#state.scale_timetraps},State};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% handle_call({trace,TraceFile}, _, State) -> ok | {error,Reason}
-%%
-%% Starts a separate node (trace control node) which
-%% starts tracing on target and all slave nodes
-%%
-%% TraceFile is a text file with elements of type
-%% {Trace,Mod,TracePattern}.
-%% {Trace,Mod,Func,TracePattern}.
-%% {Trace,Mod,Func,Arity,TracePattern}.
-%%
-%% Trace = tp | tpl; local or global call trace
-%% Mod,Func = atom(), Arity=integer(); defines what to trace
-%% TracePattern = [] | match_spec()
-%%
-%% The 'call' trace flag is set on all processes, and then
-%% the given trace patterns are set.
-
-handle_call({trace,TraceFile}, _From, State=#state{trc=false}) ->
- TI = State#state.target_info,
- case test_server_node:start_tracer_node(TraceFile, TI) of
- {ok,Tracer} -> {reply,ok,State#state{trc=Tracer}};
- Error -> {reply,Error,State}
- end;
-handle_call({trace,_TraceFile}, _From, State) ->
- {reply,{error,already_tracing},State};
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% handle_call(stop_trace, _, State) -> ok | {error,Reason}
-%%
-%% Stops tracing on target and all slave nodes and
-%% terminates trace control node
-
-handle_call(stop_trace, _From, State=#state{trc=false}) ->
- {reply,{error,not_tracing},State};
-handle_call(stop_trace, _From, State) ->
- R = test_server_node:stop_tracer_node(State#state.trc),
- {reply,R,State#state{trc=false}};
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% handle_call({cover,CoverInfo}, _, State) -> ok | {error,Reason}
%%
%% Set specification of cover analysis to be used when running tests
@@ -962,6 +910,19 @@ handle_call({stop_node, Name}, _From, State) ->
handle_call({is_release_available, Release}, _From, State) ->
R = test_server_node:is_release_available(Release),
+ {reply, R, State};
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% handle_call({find_release,Name}, _, State) -> PathToReleaseErlFile | not_available
+%%
+%% Find the path of the release's erl file if available
+
+handle_call({find_release, Release}, _From, State) ->
+ R =
+ case test_server_node:is_release_available(Release) of
+ true -> test_server_node:find_release(Release);
+ _ -> not_available
+ end,
{reply, R, State}.
%%--------------------------------------------------------------------
@@ -974,10 +935,6 @@ set_hosts(Hosts) ->
%% Called by test_server_node when a slave/peer node is fully started.
handle_cast({node_started,Node}, State) ->
- case State#state.trc of
- false -> ok;
- Trc -> test_server_node:trace_nodes(Trc, [Node])
- end,
NewWaitList =
case lists:keysearch(Node,1,State#state.wait_for_node) of
{value,{Node,From}} ->
@@ -1052,14 +1009,8 @@ handle_info({'EXIT',Pid,Reason}, State) ->
%% handle_info({tcp_closed,Sock}, State)
%%
%% A Socket was closed. This indicates that a node died.
-%% This can be
-%% *Slave or peer node started by a test suite
-%% *Trace controll node
-
-handle_info({tcp_closed,Sock}, State=#state{trc=Sock}) ->
- %% Tracer node died - can't really do anything
- %%! Maybe print something???
- {noreply,State#state{trc=false}};
+%% This can be a slave or peer node started by a test suite
+
handle_info({tcp_closed,Sock}, State) ->
test_server_node:nodedown(Sock),
{noreply,State};
@@ -1076,10 +1027,6 @@ handle_info(_, State) ->
terminate(_Reason, State) ->
test_server_sup:util_stop(),
- case State#state.trc of
- false -> ok;
- Sock -> test_server_node:stop_tracer_node(Sock)
- end,
ok = kill_all_jobs(State#state.jobs),
_ = test_server_node:kill_nodes(),
ok.
@@ -1293,12 +1240,12 @@ do_spec(SpecName, TimetrapSpec) when is_list(SpecName) ->
%% cannot be granted during the test run. Skip has the syntax specified
%% by collect_cases/3.
%%
-%% {nodes,Nodes} Lists node names avaliable to the test suites. Nodes have
+%% {nodes,Nodes} Lists node names available to the test suites. Nodes have
%% the syntax specified by collect_cases/3.
%%
%% {require_nodenames, Num} Specifies how many nodenames the test suite will
-%% need. Theese are automaticly generated and inserted into the Config by the
-%% test_server. The caller may specify other hosts to run theese nodes by
+%% need. These are automatically generated and inserted into the Config by the
+%% test_server. The caller may specify other hosts to run these nodes by
%% using the {hosts, Hosts} option. If there are no hosts specified, all
%% nodenames will be generated from the local host.
%%
@@ -1309,7 +1256,7 @@ do_spec(SpecName, TimetrapSpec) when is_list(SpecName) ->
%% all hosts given in this Hosts list. The hostnames are given as atoms or
%% strings.
%%
-%% {diskless, true}</c></tag> is kept for backwards compatiblilty and
+%% {diskless, true}</c></tag> is kept for backwards compatibility and
%% should not be used. Use a configuration test case instead.
%%
%% This function is meant to be called by a process created by
@@ -2659,7 +2606,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
case get_repeat(Props) of
undefined ->
%% we *must* have a status entry for every conf since we
- %% will continously update status with test case results
+ %% will continuously update status with test case results
%% without knowing the Ref (but update hd(Status))
{false,new_status(Ref, Status1),Cases1,?void_fun};
{_RepType,N} when N =< 1 ->
@@ -4728,7 +4675,7 @@ update_config(Config, []) ->
%% Configuration manipulation functions are called with the current
%% configuration list as only argument, and are expected to return a new
%% configuration list. Such a pair of function may, for example, start a
-%% server and stop it after a serie of test cases.
+%% server and stop it after a series of test cases.
%%
%% SkipCases is expected to be in the format:
%%
@@ -5172,6 +5119,14 @@ is_release_available(Release) ->
controller_call({is_release_available,Release}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% handle_call({find_release,Name}, _, State) -> PathToReleaseErlFile | not_available
+%%
+%% Find the path of the release's erl file if available
+
+find_release(Release) ->
+ controller_call({find_release,Release}).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% stop_node(Name) -> ok | {error,Reason}
%%
%% Clean up - test_server will stop this node
@@ -5406,7 +5361,7 @@ check_cross([]) ->
%% This analysis is executed on the target node once the test is
%% completed for an application. This is not the same as the cross
%% cover analysis, which can be executed on any node after the tests
-%% are finshed.
+%% are finished.
%%
%% This per application analysis writes the file cover.html in the
%% application's run.<timestamp> directory.
diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl
index 5b63a497d7..e5400e5e4d 100644
--- a/lib/common_test/src/test_server_node.erl
+++ b/lib/common_test/src/test_server_node.erl
@@ -18,20 +18,14 @@
%% %CopyrightEnd%
%%
-module(test_server_node).
--compile(r20).
-
-%%%
-%%% The same compiled code for this module must be possible to load
-%%% in R16B and later.
-%%%
+-compile(r22).
%% Test Controller interface
--export([is_release_available/1]).
--export([start_tracer_node/2,trace_nodes/2,stop_tracer_node/1]).
+-export([is_release_available/1, find_release/1]).
-export([start_node/5, stop_node/1]).
-export([kill_nodes/0, nodedown/1]).
%% Internal export
--export([node_started/1,trc/1,handle_debug/4]).
+-export([node_started/1]).
-include("test_server_internal.hrl").
-record(slave_info, {name,socket,client}).
@@ -39,7 +33,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% %%%
%%% All code in this module executes on the test_server_ctrl process %%%
-%%% except for node_started/1 and trc/1 which execute on a new node. %%%
+%%% except for node_started/1 which execute on a new node. %%%
%%% %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -68,212 +62,6 @@ nodedown(Sock) ->
ok
end.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Start trace node
-%%%
-start_tracer_node(TraceFile,TI) ->
- Match = #slave_info{name='$1',_='_'},
- SlaveNodes = lists:map(fun([N]) -> [" ",N] end,
- ets:match(slave_tab,Match)),
- TargetNode = node(),
- Cookie = TI#target_info.cookie,
- {ok,LSock} = gen_tcp:listen(0,[binary,{reuseaddr,true},{packet,2}]),
- {ok,TracePort} = inet:port(LSock),
- {false, Prog0} = pick_erl_program(default),
- Prog = quote_progname(Prog0),
- Cmd = lists:concat([Prog, " -sname tracer -hidden -setcookie ", Cookie,
- " -s ", ?MODULE, " trc ", TraceFile, " ",
- TracePort, " ", TI#target_info.os_family]),
- spawn(fun() -> print_data(open_port({spawn,Cmd},[stream])) end),
-%! open_port({spawn,Cmd},[stream]),
- case gen_tcp:accept(LSock,?ACCEPT_TIMEOUT) of
- {ok,Sock} ->
- gen_tcp:close(LSock),
- receive
- {tcp,Sock,Result} when is_binary(Result) ->
- case unpack(Result) of
- error ->
- gen_tcp:close(Sock),
- {error,timeout};
- {ok,started} ->
- trace_nodes(Sock,[TargetNode | SlaveNodes]),
- {ok,Sock};
- {ok,Error} -> Error
- end;
- {tcp_closed,Sock} ->
- gen_tcp:close(Sock),
- {error,could_not_start_tracernode}
- after ?ACCEPT_TIMEOUT ->
- gen_tcp:close(Sock),
- {error,timeout}
- end;
- Error ->
- gen_tcp:close(LSock),
- {error,{could_not_start_tracernode,Error}}
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Start a tracer on each of these nodes and set flags and patterns
-%%%
-trace_nodes(Sock,Nodes) ->
- Bin = term_to_binary({add_nodes,Nodes}),
- ok = gen_tcp:send(Sock, tag_trace_message(Bin)),
- receive_ack(Sock).
-
-
-receive_ack(Sock) ->
- receive
- {tcp,Sock,Bin} when is_binary(Bin) ->
- case unpack(Bin) of
- error -> receive_ack(Sock);
- {ok,_} -> ok
- end;
- _ ->
- receive_ack(Sock)
- end.
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Stop trace node
-%%%
-stop_tracer_node(Sock) ->
- Bin = term_to_binary(id(stop)),
- ok = gen_tcp:send(Sock, tag_trace_message(Bin)),
- receive {tcp_closed,Sock} -> gen_tcp:close(Sock) end,
- ok.
-
-
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% trc([TraceFile,Nodes]) -> ok
-%%
-%% Start tracing on the given nodes
-%%
-%% This function executes on the new node
-%%
-trc([TraceFile, PortAtom, Type]) ->
- {Result,Patterns} =
- case file:consult(TraceFile) of
- {ok,TI} ->
- Pat = parse_trace_info(lists:flatten(TI)),
- {started,Pat};
- Error ->
- {Error,[]}
- end,
- Port = list_to_integer(atom_to_list(PortAtom)),
- case catch gen_tcp:connect("localhost", Port, [binary,
- {reuseaddr,true},
- {packet,2}]) of
- {ok,Sock} ->
- BinResult = term_to_binary(Result),
- ok = gen_tcp:send(Sock,tag_trace_message(BinResult)),
- trc_loop(Sock,Patterns,Type);
- _else ->
- ok
- end,
- erlang:halt().
-trc_loop(Sock,Patterns,Type) ->
- receive
- {tcp,Sock,Bin} ->
- case unpack(Bin) of
- error ->
- ttb:stop(),
- gen_tcp:close(Sock);
- {ok,{add_nodes,Nodes}} ->
- add_nodes(Nodes,Patterns,Type),
- Bin = term_to_binary(id(ok)),
- ok = gen_tcp:send(Sock, tag_trace_message(Bin)),
- trc_loop(Sock,Patterns,Type);
- {ok,stop} ->
- ttb:stop(),
- gen_tcp:close(Sock)
- end;
- {tcp_closed,Sock} ->
- ttb:stop(),
- gen_tcp:close(Sock)
- end.
-add_nodes(Nodes,Patterns,_Type) ->
- {ok, _} = ttb:tracer(Nodes,[{file,{local, test_server}},
- {handler, {{?MODULE,handle_debug},initial}}]),
- {ok, _} = ttb:p(all,[call,timestamp]),
- lists:foreach(fun({TP,M,F,A,Pat}) -> ttb:TP(M,F,A,Pat);
- ({CTP,M,F,A}) -> ttb:CTP(M,F,A)
- end,
- Patterns).
-
-parse_trace_info([{TP,M,Pat}|Pats]) when TP=:=tp; TP=:=tpl ->
- [{TP,M,'_','_',Pat}|parse_trace_info(Pats)];
-parse_trace_info([{TP,M,F,Pat}|Pats]) when TP=:=tp; TP=:=tpl ->
- [{TP,M,F,'_',Pat}|parse_trace_info(Pats)];
-parse_trace_info([{TP,M,F,A,Pat}|Pats]) when TP=:=tp; TP=:=tpl ->
- [{TP,M,F,A,Pat}|parse_trace_info(Pats)];
-parse_trace_info([CTP|Pats]) when CTP=:=ctp; CTP=:=ctpl; CTP=:=ctpg ->
- [{CTP,'_','_','_'}|parse_trace_info(Pats)];
-parse_trace_info([{CTP,M}|Pats]) when CTP=:=ctp; CTP=:=ctpl; CTP=:=ctpg ->
- [{CTP,M,'_','_'}|parse_trace_info(Pats)];
-parse_trace_info([{CTP,M,F}|Pats]) when CTP=:=ctp; CTP=:=ctpl; CTP=:=ctpg ->
- [{CTP,M,F,'_'}|parse_trace_info(Pats)];
-parse_trace_info([{CTP,M,F,A}|Pats]) when CTP=:=ctp; CTP=:=ctpl; CTP=:=ctpg ->
- [{CTP,M,F,A}|parse_trace_info(Pats)];
-parse_trace_info([]) ->
- [];
-parse_trace_info([_other|Pats]) -> % ignore
- parse_trace_info(Pats).
-
-handle_debug(Out,Trace,TI,initial) ->
- handle_debug(Out,Trace,TI,0);
-handle_debug(_Out,end_of_trace,_TI,N) ->
- N;
-handle_debug(Out,Trace,_TI,N) ->
- print_trc(Out,Trace,N),
- N+1.
-
-print_trc(Out,{trace_ts,P,call,{M,F,A},C,Ts},N) ->
- io:format(Out,
- "~w: ~s~n"
- "Process : ~w~n"
- "Call : ~w:~tw/~w~n"
- "Arguments : ~tp~n"
- "Caller : ~tw~n~n",
- [N,ts(Ts),P,M,F,length(A),A,C]);
-print_trc(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
- io:format(Out,
- "~w: ~s~n"
- "Process : ~w~n"
- "Call : ~w:~tw/~w~n"
- "Arguments : ~tp~n~n",
- [N,ts(Ts),P,M,F,length(A),A]);
-print_trc(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
- io:format(Out,
- "~w: ~s~n"
- "Process : ~w~n"
- "Return from : ~w:~tw/~w~n"
- "Return value : ~tp~n~n",
- [N,ts(Ts),P,M,F,A,R]);
-print_trc(Out,{drop,X},N) ->
- io:format(Out,
- "~w: Tracer dropped ~w messages - too busy~n~n",
- [N,X]);
-print_trc(Out,Trace,N) ->
- Ts = element(size(Trace),Trace),
- io:format(Out,
- "~w: ~s~n"
- "Trace : ~tp~n~n",
- [N,ts(Ts),Trace]).
-ts({_, _, Micro} = Now) ->
- {{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(Now),
- io_lib:format("~4.4.0w-~2.2.0w-~2.2.0w ~2.2.0w:~2.2.0w:~2.2.0w,~6.6.0w",
- [Y,M,D,H,Min,S,Micro]).
-
-
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Start slave/peer nodes (initiated by test_server:start_node/5)
%%%
@@ -395,6 +183,9 @@ start_node_slave(SlaveName, OptList, From, _TI) ->
end,
gen_server:reply(From,Ret).
+%% Temporary suppression, to avoid a warning calling undocumented
+%% but deprecated function.
+-compile([{nowarn_deprecated_function,[{slave,start,5}]}]).
do_start_node_slave(Host0, SlaveName, Args, Prog, Cleanup, ClearAFlags) ->
Host =
@@ -645,7 +436,7 @@ pick_erl_program(L) ->
%% path and spaces that separate arguments. The program is quoted to
%% allow spaces in the path.
%%
-%% Arguments could exist either if the executable is excplicitly given
+%% Arguments could exist either if the executable is explicitly given
%% ({prog,String}) or if the -program switch to beam is used and
%% includes arguments (typically done by cerl in OTP test environment
%% in order to ensure that slave/peer nodes are started with the same
@@ -669,14 +460,38 @@ do_quote_progname([Prog,Arg|Args]) ->
random_element(L) ->
lists:nth(rand:uniform(length(L)), L).
+otp_release_path(RelPath) ->
+ filename:join(otp_release_root(), RelPath).
+
+otp_release_root() ->
+ case get(test_server_release_root) of
+ undefined ->
+ Root = os:getenv("TEST_SERVER_RELEASE_ROOT",
+ "/usr/local/otp/releases"),
+ put(test_server_release_root, Root),
+ Root;
+ Cached ->
+ Cached
+ end.
+
find_release(latest) ->
- "/usr/local/otp/releases/latest/bin/erl";
+ otp_release_path("latest/bin/erl");
find_release(previous) ->
"kaka";
find_release(Rel) ->
case find_release(os:type(), Rel) of
none ->
- find_release_path(Rel);
+ case find_release_path(Rel) of
+ none ->
+ case string:take(Rel,"_",true) of
+ {Rel,[]} ->
+ false;
+ {RelNum,_} ->
+ find_release_path(RelNum)
+ end;
+ Release ->
+ Release
+ end;
Else ->
Else
end.
@@ -710,7 +525,7 @@ find_release_path([], _) ->
find_release({unix,sunos}, Rel) ->
case os:cmd("uname -p") of
"sparc" ++ _ ->
- "/usr/local/otp/releases/otp_beam_solaris8_" ++ Rel ++ "/bin/erl";
+ otp_release_path("otp_beam_solaris8_" ++ Rel ++ "/bin/erl");
_ ->
none
end;
@@ -741,7 +556,7 @@ find_rel_linux(Rel) ->
end.
find_rel_suse(Rel, SuseRel) ->
- Root = "/usr/local/otp/releases/sles",
+ Root = otp_release_path("sles"),
case SuseRel of
"11" ->
%% Try both SuSE 11, SuSE 10 and SuSe 9 in that order.
@@ -817,7 +632,7 @@ suse_release(Fd) ->
find_rel_ubuntu(_Rel, UbuntuRel) when is_integer(UbuntuRel), UbuntuRel < 16 ->
[];
find_rel_ubuntu(Rel, UbuntuRel) when is_integer(UbuntuRel) ->
- Root = "/usr/local/otp/releases/ubuntu",
+ Root = otp_release_path("ubuntu"),
lists:foldl(fun (ChkUbuntuRel, Acc) ->
find_rel_ubuntu_aux1(Rel, Root++integer_to_list(ChkUbuntuRel))
++ Acc
@@ -912,24 +727,3 @@ unpack(Bin) ->
_ -> error
end.
-id(I) -> I.
-
-print_data(Port) ->
- ct_util:mark_process(),
- receive
- {Port, {data, Bytes}} ->
- io:put_chars(Bytes),
- print_data(Port);
- {Port, eof} ->
- Port ! {self(), close},
- receive
- {Port, closed} ->
- true
- end,
- receive
- {'EXIT', Port, _} ->
- ok
- after 1 -> % force context switch
- ok
- end
- end.
diff --git a/lib/common_test/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl
index 01d2ff3baa..dc8b4eeea9 100644
--- a/lib/common_test/src/test_server_sup.erl
+++ b/lib/common_test/src/test_server_sup.erl
@@ -510,8 +510,8 @@ check_change({advanced, _}) -> ok;
check_change(Change) -> throw({error, {bad_change, Change}}).
%% Given two sorted lists, L1 and L2, returns {NotInL2, NotInL1},
-%% NotInL2 is the elements of L1 which don't occurr in L2,
-%% NotInL1 is the elements of L2 which don't ocurr in L1.
+%% NotInL2 is the elements of L1 which don't occur in L2,
+%% NotInL1 is the elements of L2 which don't occur in L1.
common(L1, L2) ->
common(L1, L2, [], []).
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 8b4222f79f..1af9990bb7 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2020. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -99,6 +99,7 @@ RELSYSDIR = $(RELEASE_PATH)/common_test_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -112,7 +113,7 @@ EBIN = .
# $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
# > $(EMAKEFILE)
-tests debug opt:
+tests $(TYPES):
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl b/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
index 3f8d3957cc..cf8a346764 100644
--- a/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
+++ b/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ post_end_per_suite(_Suite, _Config, Return, State) ->
AllProcs = processes(),
Remaining = AllProcs--proplists:get_value(all_procs, State),
ct:pal("Final remaining processes = ~p", [Remaining]),
- %% only the end_per_suite process shoud remain at this point!
+ %% only the end_per_suite process should remain at this point!
Remaining = [self()],
{Return, State}.
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index 5df5b52a48..38d03536b8 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -614,7 +614,7 @@ test_events(cfg_error) ->
{?eh,test_stats,{9,1,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc6}},
%%! we get ok with tc_done since it's only afterwards
- %%! end_tc failes the testcase
+ %%! end_tc fails the testcase
{?eh,tc_done,{cfg_error_9_SUITE,tc6,ok}},
{?eh,test_stats,{9,2,{0,18}}},
{?eh,tc_start,{cfg_error_9_SUITE,tc7}},
@@ -729,9 +729,8 @@ test_events(lib_error) ->
{lib_error_1_SUITE,lines_hang,{failed,{timetrap_timeout,3000}}}},
{?eh,test_stats,{0,3,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,lines_throw}},
- {?eh,tc_done,
- {lib_error_1_SUITE,lines_throw,
- {failed,{error,{thrown,catch_me_if_u_can}}}}},
+ {?eh,tc_done,{lib_error_1_SUITE,lines_throw,{failed,
+ {error,{thrown,{catch_me_if_u_can,'_'}}}}}},
{?eh,test_stats,{0,4,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,no_lines_error}},
{?eh,tc_done,
@@ -748,8 +747,8 @@ test_events(lib_error) ->
{lib_error_1_SUITE,no_lines_hang,{failed,{timetrap_timeout,3000}}}},
{?eh,test_stats,{0,7,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,no_lines_throw}},
- {?eh,tc_done,
- {lib_error_1_SUITE,no_lines_throw,{failed,{error,{thrown,catch_me_if_u_can}}}}},
+ {?eh,tc_done,{lib_error_1_SUITE,no_lines_throw,{failed,
+ {error,{thrown,{catch_me_if_u_can,'_'}}}}}},
{?eh,test_stats,{0,8,{0,0}}},
{?eh,tc_start,{lib_error_1_SUITE,init_tc_error}},
{?eh,tc_done,{lib_error_1_SUITE,init_tc_error,
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_8_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_8_SUITE.erl
index eb5df8c45d..fa7b4507f0 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_8_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_8_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -130,8 +130,8 @@ groups() ->
{pg9,[parallel],[tc5,tc0]}, % exit during testcase
{pg10,[parallel],[tc0,tc5]},% exit during testcase
{pg11,[parallel],[tc3,tc2]},% suite is valid if nothing else is specified
- {sg1,[sequence],[tc5,tc0,tc1,tc2]}, % exit during sequencial testcase
- {sg2,[sequence],[tc5,tc0,tc1,tc2]}].% timeout during sequencial testcase
+ {sg1,[sequence],[tc5,tc0,tc1,tc2]}, % exit during sequential testcase
+ {sg2,[sequence],[tc5,tc0,tc1,tc2]}].% timeout during sequential testcase
group(g0) ->
[{timetrap,{timetrap_utils,timetrap_val,[{seconds,1}]}}];
diff --git a/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl b/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl
index 4bed60e895..7f082c0a9d 100644
--- a/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl
+++ b/lib/common_test/test/ct_group_leader_SUITE_data/group_leader_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -148,7 +148,7 @@ p1(_) ->
%% respond to IO messages. The process is still group leader for the
%% external app, however, which is wrong. It's the IO process for the
%% parallel test case that should be group leader - but only for the
- %% particular invokation, since other parallel test cases could be
+ %% particular invocation, since other parallel test cases could be
%% invoking the external app too.
print("hej\n").
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 08f0c751dd..0133d8f371 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -2109,7 +2109,7 @@ test_events(callbacks_on_skip) ->
[]]}},
%% skip_fail_SUITE is auto-skipped since the suite/0 function
- %% retuns a faluty format.
+ %% returns a faluty format.
%% No group- or testcase-functions shall be called.
{?eh,tc_start,{skip_fail_SUITE,init_per_suite}},
{?eh,tc_done,{skip_fail_SUITE,init_per_suite,
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
index f36092713e..ff0909d725 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -179,7 +179,7 @@ hello_configured_extraopts() ->
[{require, netconf1}].
hello_configured_extraopts(Config) ->
SshDir = ?config(ssh_dir,Config),
- %% Test that the cofiguration overwrites the ExtraOpts parameter
+ %% Test that the configuration overwrites the ExtraOpts parameter
%% to ct_netconfc:open/2.
{ok,Client} = open_configured_success(netconf1,SshDir,[{password,"faulty"}]),
?NS:expect_do_reply('close-session',close,ok),
@@ -1268,7 +1268,7 @@ 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.
+%% give some 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
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
index 12c250457e..c641704b10 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
@@ -120,7 +120,7 @@ open_success(Node,Dir) ->
open_success(Node,Dir,[]).
%% Open a netconf session which is not specified in a config file, and
-%% give som extra options in addition to the test defaults.
+%% give some extra options in addition to the test defaults.
open_success(Node,Dir,ExtraOpts) when is_list(Dir), is_list(ExtraOpts) ->
ns(Node,hello,[1]), % tell server to send hello with session id 1
ns(Node,expect,[hello]), % tell server to expect a hello message from client
diff --git a/lib/common_test/test/ct_surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE.erl
index a71288fb12..e80e5a37b2 100644
--- a/lib/common_test/test/ct_surefire_SUITE.erl
+++ b/lib/common_test/test/ct_surefire_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("kernel/include/file.hrl").
+-include_lib("stdlib/include/assert.hrl").
-define(eh, ct_test_support_eh).
@@ -234,28 +235,36 @@ test_suite_events(Test) ->
{?eh,tc_start,{surefire_SUITE,tc_fail}},
{?eh,tc_done,{surefire_SUITE,tc_fail,
{failed,{error,{test_case_failed,"this test should fail"}}}}},
- {?eh,test_stats,{1,1,{0,0}}}] ++
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_start,{surefire_SUITE,tc_badmatch}},
+ {?eh,tc_done,{surefire_SUITE,tc_badmatch,
+ {failed,{error,{{badmatch,nok},'_'}}}}},
+ {?eh,test_stats,{1,2,{0,0}}}] ++
tc_skip_events(Test,undefined) ++
- [{?eh,test_stats,{1,1,{1,0}}},
+ [{?eh,test_stats,{1,2,{1,0}}},
{?eh,tc_start,{surefire_SUITE,tc_autoskip_require}},
{?eh,tc_done,{surefire_SUITE,tc_autoskip_require,
{auto_skipped,{require_failed,'_'}}}},
- {?eh,test_stats,{1,1,{1,1}}},
+ {?eh,test_stats,{1,2,{1,1}}},
[{?eh,tc_start,{surefire_SUITE,{init_per_group,g,[]}}},
{?eh,tc_done,{surefire_SUITE,{init_per_group,g,[]},ok}},
{?eh,tc_start,{surefire_SUITE,tc_ok}},
{?eh,tc_done,{surefire_SUITE,tc_ok,ok}},
- {?eh,test_stats,{2,1,{1,1}}},
+ {?eh,test_stats,{2,2,{1,1}}},
{?eh,tc_start,{surefire_SUITE,tc_fail}},
{?eh,tc_done,{surefire_SUITE,tc_fail,
{failed,{error,{test_case_failed,"this test should fail"}}}}},
- {?eh,test_stats,{2,2,{1,1}}}] ++
+ {?eh,test_stats,{2,3,{1,1}}},
+ {?eh,tc_start,{surefire_SUITE,tc_badmatch}},
+ {?eh,tc_done,{surefire_SUITE,tc_badmatch,
+ {failed,{error,{{badmatch,nok},'_'}}}}},
+ {?eh,test_stats,{2,4,{1,1}}}] ++
tc_skip_events(Test,g) ++
- [{?eh,test_stats,{2,2,{2,1}}},
+ [{?eh,test_stats,{2,4,{2,1}}},
{?eh,tc_start,{surefire_SUITE,tc_autoskip_require}},
{?eh,tc_done,{surefire_SUITE,tc_autoskip_require,
{auto_skipped,{require_failed,'_'}}}},
- {?eh,test_stats,{2,2,{2,2}}},
+ {?eh,test_stats,{2,4,{2,2}}},
{?eh,tc_start,{surefire_SUITE,{end_per_group,g,[]}}},
{?eh,tc_done,{surefire_SUITE,{end_per_group,g,[]},ok}}],
[{?eh,tc_start,{surefire_SUITE,{init_per_group,g_fail,[]}}},
@@ -265,7 +274,7 @@ test_suite_events(Test) ->
{failed,
{surefire_SUITE,init_per_group,
{'EXIT',all_cases_should_be_skipped}}}}},
- {?eh,test_stats,{2,2,{2,3}}},
+ {?eh,test_stats,{2,4,{2,3}}},
{?eh,tc_auto_skip,{surefire_SUITE,{end_per_group,g_fail},
{failed,
{surefire_SUITE,init_per_group,
@@ -295,7 +304,7 @@ test_events(skip_suite_in_spec) ->
test_suite_events(skip_all_surefire_SUITE) ++
[{?eh,stop_logging,[]}];
test_events(Test) ->
- [{?eh,start_logging,'_'}, {?eh,start_info,{1,1,9}}] ++
+ [{?eh,start_logging,'_'}, {?eh,start_info,{1,1,11}}] ++
test_suite_events(Test) ++
[{?eh,stop_logging,[]}].
@@ -363,6 +372,7 @@ testsuite(_Case,[]) ->
testcase(url=Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) ->
R = failed_or_skipped(C),
+ assert_lines(Case,A),
case R of
[s] ->
case lists:keyfind(url,#xmlAttribute.name,A) of
@@ -379,6 +389,7 @@ testcase(url=Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) ->
[R|testcase(Case,TC)];
testcase(Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) ->
false = lists:keyfind(url,#xmlAttribute.name,A),
+ assert_lines(Case,A),
R = failed_or_skipped(C),
[R|testcase(Case,TC)];
testcase(_Case,[]) ->
@@ -393,6 +404,37 @@ failed_or_skipped([#xmlElement{name=skipped}|E]) ->
failed_or_skipped([]) ->
[].
+assert_lines(Case, A) when Case =/= fail_pre_init_per_suite,
+ Case =/= skip_case_in_spec,
+ Case =/= skip_suite_in_spec ->
+ Name = lists:keyfind(name,#xmlAttribute.name,A),
+ File = lists:keyfind(file,#xmlAttribute.name,A),
+ Line = lists:keyfind(line,#xmlAttribute.name,A),
+ ?assertMatch("surefire_SUITE.erl",filename:basename(File#xmlAttribute.value)),
+ case Name#xmlAttribute.value of
+ "init_per_suite" ->
+ ?assertMatch("51", Line#xmlAttribute.value);
+ "end_per_suite" ->
+ ?assertMatch("54", Line#xmlAttribute.value);
+ "tc_ok" ->
+ ?assertMatch("80", Line#xmlAttribute.value);
+ "tc_fail" ->
+ ?assertMatch("85", Line#xmlAttribute.value);
+ "tc_badmatch" ->
+ ?assertMatch("89", Line#xmlAttribute.value);
+ "tc_skip" ->
+ ?assertMatch("91", Line#xmlAttribute.value);
+ "tc_autoskip_require" ->
+ ?assertMatch("96", Line#xmlAttribute.value);
+ "init_per_group" ->
+ ?assertMatch("57", Line#xmlAttribute.value);
+ "end_per_group" ->
+ ?assertMatch("62", Line#xmlAttribute.value)
+ end;
+assert_lines(_, _) ->
+ ok.
+
+
%% Using the expected events to produce the expected result of the XML scanning.
%% The result is a list of test suites:
%% Testsuites = [Testsuite]
diff --git a/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
index 4644355ca9..eb5f5a4217 100644
--- a/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
+++ b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ groups() ->
testcases() ->
[tc_ok,
tc_fail,
+ tc_badmatch,
tc_skip,
tc_autoskip_require].
@@ -76,12 +77,17 @@ break(_Config) ->
test_server:break(""),
ok.
-tc_ok(_Config) ->
- ok.
+tc_ok(Config) when is_list(Config) ->
+ ok;
+tc_ok(_) ->
+ ct:fail("This should never fail").
tc_fail(_Config) ->
ct:fail("this test should fail").
+tc_badmatch(_Config) ->
+ ok = nok.
+
tc_skip(_Config) ->
{skip,"this test is skipped"}.
diff --git a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_basic_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_basic_SUITE.erl
index 3885c1991d..ec9431c3f0 100644
--- a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_basic_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_basic_SUITE.erl
@@ -131,7 +131,7 @@ sendf(Config) ->
no_newline(Config) ->
{ok, Handle} = ct_telnet:open(?conn_name(?get_n(Config))),
- IAC = 255, % interprete as command
+ IAC = 255, % interpreted as command
AYT = 246, % are you there
ok = ct_telnet:send(Handle, [IAC,AYT], [{newline,false}]),
{ok,_} = ct_telnet:expect(Handle,"yes",[no_prompt_check]),
diff --git a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_timetrap_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_timetrap_SUITE.erl
index c45a4f0984..afb2031f9a 100644
--- a/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_timetrap_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE_data/ct_telnet_timetrap_SUITE.erl
@@ -53,7 +53,7 @@ end_per_testcase(_,_Config) ->
%% The long timetrap timeout and timeout option in the expect call
%% also causes the telnet client to hang so long that the attempt at
%% closing it (in end_per_testcase) will time out (close timeout is 5
-%% sec) without a timetrap timeout occuring in end_per_testcase.
+%% sec) without a timetrap timeout occurring in end_per_testcase.
%%
%% The point is to see that the connection is thoroughly removed and
%% unregistered anyway so that the next test case can successfully
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 05694535ad..3b7fc70313 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1217,6 +1217,9 @@ result_match({failed,{timetrap_timeout,{'$approx',Num}}},
result_match({user_timetrap_error,{Why,'_'}},
{user_timetrap_error,{Why,_Stack}}) ->
true;
+result_match({SkipOrFail,{ErrorInd,{thrown,{Why,'_'}}}},
+ {SkipOrFail,{ErrorInd,{thrown,{Why,_Stack}}}}) ->
+ true;
result_match(Result, Result) ->
true;
result_match(_, _) ->
diff --git a/lib/common_test/test/erl2html2_SUITE.erl b/lib/common_test/test/erl2html2_SUITE.erl
index b2336ff0bc..bac028350a 100644
--- a/lib/common_test/test/erl2html2_SUITE.erl
+++ b/lib/common_test/test/erl2html2_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -262,7 +262,7 @@ sax_event({startElement,_Uri,"a",_QN,Attrs},{Exports,LastExprFuncs,PrevLine}) ->
{match,[FStr,EndStr]} =
re:run(Name,"^(.*)-(last_expr|[0-9]+)$",
[{capture,all_but_first,list}]),
- F = list_to_atom(http_uri:decode(FStr)),
+ F = list_to_atom(uri_string:unquote(FStr)),
case EndStr of
"last_expr" ->
true = lists:member(F,LastExprFuncs),
diff --git a/lib/common_test/test_server/Makefile b/lib/common_test/test_server/Makefile
index f015064b39..4ff5e678ee 100644
--- a/lib/common_test/test_server/Makefile
+++ b/lib/common_test/test_server/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ TS_TARGET_MODULES= $(TS_MODULES:%=$(EBIN)/%)
TS_ERL_FILES = $(TS_MODULES:=.erl)
TS_HRL_FILES = ts.hrl
-AUTOCONF_FILES = configure.in conf_vars.in
+AUTOCONF_FILES = conf_vars.in
PROGRAMS = configure config.sub config.guess install-sh
CONFIG = ts.config ts.unix.config ts.win32.config
@@ -64,7 +64,7 @@ ERL_COMPILE_FLAGS += -I../include -Werror
# Targets
# ----------------------------------------------------
-tests debug opt: $(TS_TARGETS)
+tests $(TYPES): $(TS_TARGETS)
clean:
rm -f $(TS_TARGET_FILES)
@@ -72,9 +72,6 @@ clean:
docs:
-configure: configure.in
- autoconf configure.in > configure
-
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
diff --git a/lib/common_test/test_server/configure b/lib/common_test/test_server/configure
index d190f0250b..38a17b2fab 100755
--- a/lib/common_test/test_server/configure
+++ b/lib/common_test/test_server/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,52 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
-test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +220,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +252,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +291,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +309,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +331,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +340,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +379,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +397,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +429,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +458,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +502,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +516,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +533,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,50 +605,46 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
ac_unique_file="conf_vars.in"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
test_c_compiler
@@ -640,9 +666,6 @@ SHLIB_CFLAGS
SHLIB_LDLIBS
SHLIB_LDFLAGS
SHLIB_LD
-EGREP
-GREP
-CPP
DEBUG_FLAGS
OBJEXT
EXEEXT
@@ -713,8 +736,7 @@ CC
CFLAGS
LDFLAGS
LIBS
-CPPFLAGS
-CPP'
+CPPFLAGS'
# Initialize some variables set by options.
@@ -783,8 +805,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -825,9 +845,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -851,9 +871,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1064,9 +1084,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1080,9 +1100,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1126,9 +1146,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1144,7 +1164,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1208,7 +1228,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1350,7 +1370,6 @@ Some influential environment variables:
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1371,9 +1390,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1401,7 +1420,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1409,7 +1429,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1419,9 +1439,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1438,14 +1458,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1453,14 +1473,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1476,14 +1497,14 @@ fi
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1491,17 +1512,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1516,172 +1538,6 @@ fi
} # ac_fn_c_try_link
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
-ac_fn_c_try_run ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
- ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=$ac_status
-fi
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_run
-
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
@@ -1689,26 +1545,28 @@ fi
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
@@ -1719,11 +1577,12 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -1731,16 +1590,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -1758,35 +1610,56 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -1819,8 +1692,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -1855,7 +1732,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -1890,11 +1767,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -1905,8 +1784,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -1930,7 +1809,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -1938,14 +1817,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -1953,15 +1832,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -1969,8 +1848,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -1984,63 +1863,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2050,19 +1914,434 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2073,12 +2352,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2087,24 +2366,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2114,11 +2393,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2132,55 +2412,32 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2199,21 +2456,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2233,6 +2491,15 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2241,11 +2508,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2253,11 +2521,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2268,11 +2540,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2281,11 +2553,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2293,11 +2566,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2308,11 +2585,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2320,8 +2597,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2334,11 +2611,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2346,11 +2624,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2361,11 +2643,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2374,11 +2656,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2387,15 +2670,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2411,18 +2698,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2433,11 +2720,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2445,11 +2733,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2460,11 +2752,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2477,11 +2769,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2489,11 +2782,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2504,11 +2801,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2520,34 +2817,138 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -2557,7 +2958,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -2565,7 +2966,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2577,9 +2978,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -2600,11 +3001,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -2621,7 +3023,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -2637,44 +3039,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -2688,15 +3092,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -2705,7 +3109,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -2717,8 +3121,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -2726,10 +3130,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -2737,39 +3141,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2783,11 +3188,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -2796,31 +3202,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -2830,29 +3237,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -2861,57 +3272,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -2926,94 +3340,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3030,7 +3494,8 @@ fi
# Check whether --enable-debug-mode was given.
-if test "${enable_debug_mode+set}" = set; then :
+if test ${enable_debug_mode+y}
+then :
enableval=$enable_debug_mode; case "$enableval" in
no) ;;
*) CFLAGS=$DEBUG_FLAGS ;;
@@ -3039,25 +3504,27 @@ fi
# Check whether --enable-m64-build was given.
-if test "${enable_m64_build+set}" = set; then :
+if test ${enable_m64_build+y}
+then :
enableval=$enable_m64_build; case "$enableval" in
no) enable_m64_build=no ;;
*) enable_m64_build=yes ;;
esac
-else
+else $as_nop
enable_m64_build=no
fi
# Check whether --enable-m32-build was given.
-if test "${enable_m32_build+set}" = set; then :
+if test ${enable_m32_build+y}
+then :
enableval=$enable_m32_build; case "$enableval" in
no) enable_m32_build=no ;;
*) enable_m32_build=yes ;;
esac
-else
+else $as_nop
enable_m32_build=no
fi
@@ -3074,11 +3541,12 @@ if test X${enable_m32_build} = Xyes; then
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
-$as_echo_n "checking for sin in -lm... " >&6; }
-if ${ac_cv_lib_m_sin+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
+printf %s "checking for sin in -lm... " >&6; }
+if test ${ac_cv_lib_m_sin+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3087,33 +3555,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char sin ();
int
-main ()
+main (void)
{
return sin ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_m_sin=yes
-else
+else $as_nop
ac_cv_lib_m_sin=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5
-$as_echo "$ac_cv_lib_m_sin" >&6; }
-if test "x$ac_cv_lib_m_sin" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBM 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5
+printf "%s\n" "$ac_cv_lib_m_sin" >&6; }
+if test "x$ac_cv_lib_m_sin" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBM 1" >>confdefs.h
LIBS="-lm $LIBS"
@@ -3125,11 +3590,12 @@ fi
# needs net/errno.h to define the socket-related error codes.
#--------------------------------------------------------------------
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
-$as_echo_n "checking for main in -linet... " >&6; }
-if ${ac_cv_lib_inet_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
+printf %s "checking for main in -linet... " >&6; }
+if test ${ac_cv_lib_inet_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-linet $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3137,446 +3603,80 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_inet_main=yes
-else
+else $as_nop
ac_cv_lib_inet_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
-$as_echo "$ac_cv_lib_inet_main" >&6; }
-if test "x$ac_cv_lib_inet_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5
+printf "%s\n" "$ac_cv_lib_inet_main" >&6; }
+if test "x$ac_cv_lib_inet_main" = xyes
+then :
LIBS="$LIBS -linet"
fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+done
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-
-done
-
-
-ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
-if test "x$ac_cv_header_net_errno_h" = xyes; then :
- $as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h
+ac_fn_c_check_header_compile "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_errno_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NET_ERRNO_H 1" >>confdefs.h
fi
-
#--------------------------------------------------------------------
# Linux/tcp.h may be needed for sockopt test in kernel
#--------------------------------------------------------------------
-ac_fn_c_check_header_mongrel "$LINENO" "linux/tcp.h" "ac_cv_header_linux_tcp_h" "$ac_includes_default"
-if test "x$ac_cv_header_linux_tcp_h" = xyes; then :
- $as_echo "#define HAVE_LINUX_TCP_H 1" >>confdefs.h
+ac_fn_c_check_header_compile "$LINENO" "linux/tcp.h" "ac_cv_header_linux_tcp_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_tcp_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LINUX_TCP_H 1" >>confdefs.h
fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sane linux/tcp.h" >&5
-$as_echo_n "checking for sane linux/tcp.h... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sane linux/tcp.h" >&5
+printf %s "checking for sane linux/tcp.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
@@ -3591,29 +3691,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include <netinet/in.h>
#include <netdb.h>
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
have_sane_linux_tcp_h=yes
-else
+else $as_nop
have_sane_linux_tcp_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test $have_sane_linux_tcp_h = yes; then
-$as_echo "#define HAVE_SANE_LINUX_TCP_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_SANE_LINUX_TCP_H 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3621,26 +3722,26 @@ fi
#--------------------------------------------------------------------
# Linux requires sys/socketio.h instead of sys/sockio.h
#--------------------------------------------------------------------
-ac_fn_c_check_header_mongrel "$LINENO" "sys/socketio.h" "ac_cv_header_sys_socketio_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_socketio_h" = xyes; then :
- $as_echo "#define HAVE_SOCKETIO_H 1" >>confdefs.h
+ac_fn_c_check_header_compile "$LINENO" "sys/socketio.h" "ac_cv_header_sys_socketio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_socketio_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SOCKETIO_H 1" >>confdefs.h
fi
-
#--------------------------------------------------------------------
# Misc
#--------------------------------------------------------------------
-ac_fn_c_check_header_mongrel "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default"
-if test "x$ac_cv_header_poll_h" = xyes; then :
- $as_echo "#define HAVE_POLL_H 1" >>confdefs.h
+ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default"
+if test "x$ac_cv_header_poll_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h
fi
-
#--------------------------------------------------------------------
# The statements below define a collection of symbols related to
# dynamic loading and shared libraries:
@@ -3658,20 +3759,21 @@ fi
# Step 1: set the variable "system" to hold the name and version number
# for the system.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking system version (for dynamic loading)" >&5
-$as_echo_n "checking system version (for dynamic loading)... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version (for dynamic loading)" >&5
+printf %s "checking system version (for dynamic loading)... " >&6; }
system=`./config.sub $host`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $system" >&5
-$as_echo "$system" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $system" >&5
+printf "%s\n" "$system" >&6; }
# Step 2: check for existence of -ldl library. This is needed because
# Linux can use either -ldl or -ldld for dynamic loading.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3680,32 +3782,31 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char dlopen ();
int
-main ()
+main (void)
{
return dlopen ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_dl_dlopen=yes
-else
+else $as_nop
ac_cv_lib_dl_dlopen=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
have_dl=yes
-else
+else $as_nop
have_dl=no
fi
@@ -3714,8 +3815,9 @@ fi
SHLIB_LDLIBS=
fullSrcDir=`cd $srcdir; pwd`
-case $system in
- *-linux-*)
+case $system in #(
+ *-linux-*) :
+
SHLIB_CFLAGS="-fPIC"
SHLIB_SUFFIX=".so"
if test "$have_dl" = yes; then
@@ -3723,14 +3825,14 @@ case $system in
SHLIB_LDFLAGS="$LDFLAGS -shared"
LD_FLAGS="-rdynamic"
else
- ac_fn_c_check_header_mongrel "$LINENO" "dld.h" "ac_cv_header_dld_h" "$ac_includes_default"
-if test "x$ac_cv_header_dld_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "dld.h" "ac_cv_header_dld_h" "$ac_includes_default"
+if test "x$ac_cv_header_dld_h" = xyes
+then :
SHLIB_LD="ld"
SHLIB_LDFLAGS="-shared"
fi
-
if test X${enable_m64_build} = Xyes; then
as_fn_error $? "don't know how to link 64-bit dynamic drivers" "$LINENO" 5
fi
@@ -3739,11 +3841,13 @@ fi
fi
fi
SHLIB_EXTRACT_ALL=""
- ;;
- *-openbsd*|*-netbsd*|*-freebsd*|*-dragonfly*)
+ ;; #(
+ *-openbsd*|*-netbsd*|*-freebsd*|*-dragonfly*) :
+
# Not available on all versions: check for include file.
- ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
-if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
+if test "x$ac_cv_header_dlfcn_h" = xyes
+then :
SHLIB_CFLAGS="-fpic"
SHLIB_LD="${CC}"
@@ -3756,7 +3860,7 @@ if test "x$ac_cv_header_dlfcn_h" = xyes; then :
as_fn_error $? "don't know how to link 32-bit dynamic drivers" "$LINENO" 5
fi
-else
+else $as_nop
# No dynamic loading.
SHLIB_CFLAGS=""
@@ -3767,10 +3871,10 @@ else
fi
-
SHLIB_EXTRACT_ALL=""
- ;;
- *-solaris2*|*-sysv4*)
+ ;; #(
+ *-solaris2*|*-sysv4*) :
+
SHLIB_CFLAGS="-KPIC"
SHLIB_LD="/usr/ccs/bin/ld"
SHLIB_LDFLAGS="$no_mXX_LDFLAGS -G -z text"
@@ -3782,15 +3886,17 @@ fi
fi
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"
@@ -3802,15 +3908,17 @@ fi
fi
SHLIB_SUFFIX=".so"
SHLIB_EXTRACT_ALL=""
- ;;
- *osf5*)
+ ;; #(
+ *osf5*) :
+
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="${CC} -shared"
SHLIB_LDFLAGS="$LDFLAGS"
SHLIB_SUFFIX=".so"
SHLIB_EXTRACT_ALL=""
- ;;
- *)
+ ;; #(
+ *) :
+
# No dynamic loading.
SHLIB_CFLAGS=""
SHLIB_LD="ld"
@@ -3819,7 +3927,7 @@ fi
SHLIB_SUFFIX=""
SHLIB_EXTRACT_ALL=""
as_fn_error $? "don't know how to compile and link dynamic drivers" "$LINENO" 5
- ;;
+ ;;
esac
# If we're running gcc, then change the C flags for compiling shared
@@ -3853,7 +3961,8 @@ EI_CFLAGS="$CFLAGS"
# Add thread-safety flags if requested
# Check whether --enable-shlib-thread-safety was given.
-if test "${enable_shlib_thread_safety+set}" = set; then :
+if test ${enable_shlib_thread_safety+y}
+then :
enableval=$enable_shlib_thread_safety; case "$enableval" in
no) ;;
*) SHLIB_CFLAGS="$SHLIB_CFLAGS -D_THREAD_SAFE -D_REENTRANT"
@@ -3895,18 +4004,22 @@ SHLIB_CFLAGS="$SHLIB_CFLAGS $CFLAGS"
erl_checkBoth=0
ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
-if test "x$ac_cv_func_connect" = xyes; then :
+if test "x$ac_cv_func_connect" = xyes
+then :
erl_checkSocket=0
-else
+else $as_nop
erl_checkSocket=1
fi
-if test "$erl_checkSocket" = 1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
-$as_echo_n "checking for main in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "$erl_checkSocket" = 1
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
+printf %s "checking for main in -lsocket... " >&6; }
+if test ${ac_cv_lib_socket_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3914,51 +4027,60 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_socket_main=yes
-else
+else $as_nop
ac_cv_lib_socket_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
-$as_echo "$ac_cv_lib_socket_main" >&6; }
-if test "x$ac_cv_lib_socket_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
+printf "%s\n" "$ac_cv_lib_socket_main" >&6; }
+if test "x$ac_cv_lib_socket_main" = xyes
+then :
LIBS="$LIBS -lsocket"
-else
+else $as_nop
erl_checkBoth=1
fi
+
fi
-if test "$erl_checkBoth" = 1; then
+if test "$erl_checkBoth" = 1
+then :
+
tk_oldLibs=$LIBS
LIBS="$LIBS -lsocket -lnsl"
ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
-if test "x$ac_cv_func_accept" = xyes; then :
+if test "x$ac_cv_func_accept" = xyes
+then :
erl_checkNsl=0
-else
+else $as_nop
LIBS=$tk_oldLibs
fi
+
fi
ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
-if test "x$ac_cv_func_gethostbyname" = xyes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
-$as_echo_n "checking for main in -lnsl... " >&6; }
-if ${ac_cv_lib_nsl_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "x$ac_cv_func_gethostbyname" = xyes
+then :
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
+printf %s "checking for main in -lnsl... " >&6; }
+if test ${ac_cv_lib_nsl_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lnsl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3966,72 +4088,63 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_nsl_main=yes
-else
+else $as_nop
ac_cv_lib_nsl_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
-$as_echo "$ac_cv_lib_nsl_main" >&6; }
-if test "x$ac_cv_lib_nsl_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
+printf "%s\n" "$ac_cv_lib_nsl_main" >&6; }
+if test "x$ac_cv_lib_nsl_main" = xyes
+then :
LIBS="$LIBS -lnsl"
fi
fi
-for ac_func in strerror
-do :
- ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
-if test "x$ac_cv_func_strerror" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_STRERROR 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRERROR 1" >>confdefs.h
fi
-done
-for ac_func in vsnprintf
-do :
- ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
-if test "x$ac_cv_func_vsnprintf" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_VSNPRINTF 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
+if test "x$ac_cv_func_vsnprintf" = xyes
+then :
+ printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h
fi
-done
-for ac_func in usleep
-do :
- ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep"
-if test "x$ac_cv_func_usleep" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_USLEEP 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep"
+if test "x$ac_cv_func_usleep" = xyes
+then :
+ printf "%s\n" "#define HAVE_USLEEP 1" >>confdefs.h
fi
-done
# First check if the library is available, then if we can choose between
# two versions of gethostbyname
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lresolv" >&5
-$as_echo_n "checking for main in -lresolv... " >&6; }
-if ${ac_cv_lib_resolv_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lresolv" >&5
+printf %s "checking for main in -lresolv... " >&6; }
+if test ${ac_cv_lib_resolv_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lresolv $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4039,39 +4152,40 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_resolv_main=yes
-else
+else $as_nop
ac_cv_lib_resolv_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_main" >&5
-$as_echo "$ac_cv_lib_resolv_main" >&6; }
-if test "x$ac_cv_lib_resolv_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRESOLV 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_main" >&5
+printf "%s\n" "$ac_cv_lib_resolv_main" >&6; }
+if test "x$ac_cv_lib_resolv_main" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBRESOLV 1" >>confdefs.h
LIBS="-lresolv $LIBS"
fi
ac_cv_lib_resolv=ac_cv_lib_resolv_main
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_gethostbyname in -lresolv" >&5
-$as_echo_n "checking for res_gethostbyname in -lresolv... " >&6; }
-if ${ac_cv_lib_resolv_res_gethostbyname+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_gethostbyname in -lresolv" >&5
+printf %s "checking for res_gethostbyname in -lresolv... " >&6; }
+if test ${ac_cv_lib_resolv_res_gethostbyname+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lresolv $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4080,31 +4194,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char res_gethostbyname ();
int
-main ()
+main (void)
{
return res_gethostbyname ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_resolv_res_gethostbyname=yes
-else
+else $as_nop
ac_cv_lib_resolv_res_gethostbyname=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_gethostbyname" >&5
-$as_echo "$ac_cv_lib_resolv_res_gethostbyname" >&6; }
-if test "x$ac_cv_lib_resolv_res_gethostbyname" = xyes; then :
- $as_echo "#define HAVE_RES_GETHOSTBYNAME 1" >>confdefs.h
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_gethostbyname" >&5
+printf "%s\n" "$ac_cv_lib_resolv_res_gethostbyname" >&6; }
+if test "x$ac_cv_lib_resolv_res_gethostbyname" = xyes
+then :
+ printf "%s\n" "#define HAVE_RES_GETHOSTBYNAME 1" >>confdefs.h
fi
@@ -4113,37 +4226,38 @@ fi
# Check for isfinite
#--------------------------------------------------------------------
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for isfinite" >&5
-$as_echo_n "checking for isfinite... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for isfinite" >&5
+printf %s "checking for isfinite... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <math.h>
int
-main ()
+main (void)
{
isfinite(0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
have_isfinite=yes
-else
+else $as_nop
have_isfinite=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $have_isfinite = yes; then
- $as_echo "#define HAVE_ISFINITE 1" >>confdefs.h
+ printf "%s\n" "#define HAVE_ISFINITE 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- $as_echo "#define HAVE_FINITE 1" >>confdefs.h
+ printf "%s\n" "#define HAVE_FINITE 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
#--------------------------------------------------------------------
@@ -4225,11 +4339,12 @@ for ac_prog in javac guavac gcj jikes bock
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_JAVAC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_JAVAC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$JAVAC"; then
ac_cv_prog_JAVAC="$JAVAC" # Let the user override the test.
else
@@ -4237,11 +4352,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_JAVAC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4252,23 +4371,26 @@ fi
fi
JAVAC=$ac_cv_prog_JAVAC
if test -n "$JAVAC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
-$as_echo "$JAVAC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+printf "%s\n" "$JAVAC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
test -n "$JAVAC" && break
done
-if test -n "$JAVAC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JDK version 1.5" >&5
-$as_echo_n "checking for JDK version 1.5... " >&6; }
-if ${ac_cv_prog_javac_ver_1_5+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test -n "$JAVAC"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for JDK version 1.5" >&5
+printf %s "checking for JDK version 1.5... " >&6; }
+if test ${ac_cv_prog_javac_ver_1_5+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
java_link='$JAVAC conftest.java 1>&5'
cat > conftest.java <<EOF
@@ -4279,24 +4401,30 @@ EOF
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$java_link\""; } >&5
(eval $java_link) 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && test -s conftest.class; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest.class
+then :
+
rm -rf conftest*
ac_cv_prog_javac_ver_1_5=yes
-else
+
+else $as_nop
+
echo "configure: failed program was:" 1>&5
cat conftest.java 1>&5
echo "configure: PATH was $PATH" 1>&5
rm -rf conftest*
ac_cv_prog_javac_ver_1_5=no
+
fi
rm -f conftest*
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_ver_1_5" >&5
-$as_echo "$ac_cv_prog_javac_ver_1_5" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_ver_1_5" >&5
+printf "%s\n" "$ac_cv_prog_javac_ver_1_5" >&6; }
if test $ac_cv_prog_javac_ver_1_5 = no; then
unset -v JAVAC
fi
+
fi
if test -n "$JAVAC"; then
@@ -4307,11 +4435,12 @@ for ac_prog in make gmake
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_make_command+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_make_command+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$make_command"; then
ac_cv_prog_make_command="$make_command" # Let the user override the test.
else
@@ -4319,11 +4448,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_make_command="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4334,11 +4467,11 @@ fi
fi
make_command=$ac_cv_prog_make_command
if test -n "$make_command"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $make_command" >&5
-$as_echo "$make_command" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $make_command" >&5
+printf "%s\n" "$make_command" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4384,8 +4517,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -4415,15 +4548,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -4437,8 +4570,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -4491,7 +4624,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -4507,8 +4640,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -4531,14 +4664,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -4548,46 +4683,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -4596,13 +4731,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -4611,8 +4739,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -4624,30 +4756,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -4660,13 +4772,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -4693,18 +4806,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -4716,12 +4831,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -4752,7 +4868,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -4774,6 +4890,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -4787,6 +4907,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -4828,7 +4954,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -4837,7 +4963,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -4900,7 +5026,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -4949,14 +5075,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -4993,21 +5121,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -5035,7 +5163,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -5049,7 +5177,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -5074,7 +5202,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -5302,7 +5430,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -5310,17 +5438,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -5337,7 +5465,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -5361,9 +5489,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -5416,8 +5544,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -5459,9 +5587,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -5508,7 +5636,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/common_test/test_server/configure.in b/lib/common_test/test_server/configure.ac
index d58b4fc51b..da5c1b1608 100644
--- a/lib/common_test/test_server/configure.in
+++ b/lib/common_test/test_server/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script for Erlang.
dnl
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1997-2020. All Rights Reserved.
+dnl Copyright Ericsson AB 1997-2021. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
@@ -19,7 +19,9 @@ dnl
dnl %CopyrightEnd%
dnl
-AC_INIT(conf_vars.in)
+AC_INIT
+AC_CONFIG_SRCDIR([conf_vars.in])
+AC_PREREQ([2.71])
AC_CANONICAL_HOST
@@ -84,7 +86,7 @@ AC_CHECK_HEADER(net/errno.h, AC_DEFINE(HAVE_NET_ERRNO_H))
AC_CHECK_HEADER(linux/tcp.h, AC_DEFINE(HAVE_LINUX_TCP_H))
AC_MSG_CHECKING(for sane linux/tcp.h)
-AC_TRY_COMPILE([#include <stdio.h>
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -94,10 +96,7 @@ AC_TRY_COMPILE([#include <stdio.h>
#include <sys/wait.h>
#include <linux/tcp.h>
#include <netinet/in.h>
- #include <netdb.h>],
- [return 0;],
- have_sane_linux_tcp_h=yes,
- have_sane_linux_tcp_h=no)
+ #include <netdb.h>]], [[return 0;]])],[have_sane_linux_tcp_h=yes],[have_sane_linux_tcp_h=no])
if test $have_sane_linux_tcp_h = yes; then
AC_DEFINE(HAVE_SANE_LINUX_TCP_H,[1],
@@ -150,8 +149,10 @@ AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
SHLIB_LDLIBS=
fullSrcDir=`cd $srcdir; pwd`
-case $system in
- *-linux-*)
+AS_CASE([$system],
+
+ [*-linux-*],
+ [
SHLIB_CFLAGS="-fPIC"
SHLIB_SUFFIX=".so"
if test "$have_dl" = yes; then
@@ -170,8 +171,10 @@ case $system in
fi
fi
SHLIB_EXTRACT_ALL=""
- ;;
- *-openbsd*|*-netbsd*|*-freebsd*|*-dragonfly*)
+ ],
+
+ [*-openbsd*|*-netbsd*|*-freebsd*|*-dragonfly*],
+ [
# Not available on all versions: check for include file.
AC_CHECK_HEADER(dlfcn.h, [
SHLIB_CFLAGS="-fpic"
@@ -193,8 +196,10 @@ case $system in
AC_MSG_ERROR(don't know how to compile and link dynamic drivers)
])
SHLIB_EXTRACT_ALL=""
- ;;
- *-solaris2*|*-sysv4*)
+ ],
+
+ [*-solaris2*|*-sysv4*],
+ [
SHLIB_CFLAGS="-KPIC"
SHLIB_LD="/usr/ccs/bin/ld"
SHLIB_LDFLAGS="$no_mXX_LDFLAGS -G -z text"
@@ -206,15 +211,19 @@ case $system in
fi
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"
@@ -226,15 +235,18 @@ case $system in
fi
SHLIB_SUFFIX=".so"
SHLIB_EXTRACT_ALL=""
- ;;
- *osf5*)
+ ],
+
+ [*osf5*],
+ [
SHLIB_CFLAGS="-fPIC"
SHLIB_LD="${CC} -shared"
SHLIB_LDFLAGS="$LDFLAGS"
SHLIB_SUFFIX=".so"
SHLIB_EXTRACT_ALL=""
- ;;
- *)
+ ],
+
+ [
# No dynamic loading.
SHLIB_CFLAGS=""
SHLIB_LD="ld"
@@ -243,8 +255,7 @@ case $system in
SHLIB_SUFFIX=""
SHLIB_EXTRACT_ALL=""
AC_MSG_ERROR(don't know how to compile and link dynamic drivers)
- ;;
-esac
+ ])
# If we're running gcc, then change the C flags for compiling shared
# libraries to the right flags for gcc, instead of those for the
@@ -317,14 +328,16 @@ AC_SUBST(EI_CFLAGS)
erl_checkBoth=0
AC_CHECK_FUNC(connect, erl_checkSocket=0, erl_checkSocket=1)
-if test "$erl_checkSocket" = 1; then
+AS_IF([test "$erl_checkSocket" = 1],
+ [
AC_CHECK_LIB(socket, main, LIBS="$LIBS -lsocket", erl_checkBoth=1)
-fi
-if test "$erl_checkBoth" = 1; then
+ ])
+AS_IF([test "$erl_checkBoth" = 1],
+ [
tk_oldLibs=$LIBS
LIBS="$LIBS -lsocket -lnsl"
AC_CHECK_FUNC(accept, erl_checkNsl=0, [LIBS=$tk_oldLibs])
-fi
+ ])
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"]))
dnl Checks for library functions.
@@ -334,7 +347,8 @@ AC_CHECK_FUNCS(usleep)
# First check if the library is available, then if we can choose between
# two versions of gethostbyname
-AC_HAVE_LIBRARY(resolv)
+AC_CHECK_LIB([resolv],[main],[],[],[])ac_cv_lib_resolv=ac_cv_lib_resolv_main
+
AC_CHECK_LIB(resolv, res_gethostbyname,[AC_DEFINE(HAVE_RES_GETHOSTBYNAME,1)])
#--------------------------------------------------------------------
@@ -342,8 +356,7 @@ AC_CHECK_LIB(resolv, res_gethostbyname,[AC_DEFINE(HAVE_RES_GETHOSTBYNAME,1)])
#--------------------------------------------------------------------
AC_MSG_CHECKING([for isfinite])
-AC_TRY_LINK([#include <math.h>],
- [isfinite(0);], have_isfinite=yes, have_isfinite=no)
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]], [[isfinite(0);]])],[have_isfinite=yes],[have_isfinite=no])
if test $have_isfinite = yes; then
AC_DEFINE(HAVE_ISFINITE,1)
@@ -438,10 +451,10 @@ SSLEAY_ROOT=$TARGET
#
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 Freely inspired by AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[],[]). (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'
+[java_link='$JAVAC conftest.java 1>&AS_MESSAGE_LOG_FD'
changequote(, )dnl
cat > conftest.java <<EOF
$1
@@ -450,21 +463,24 @@ class conftest { public static void main(String[] args) {
; return; }}
EOF
changequote([, ])dnl
-if AC_TRY_EVAL(java_link) && test -s conftest.class; then
+AS_IF([AC_TRY_EVAL(java_link) && test -s conftest.class],
+ [
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
+ ],
+ [
+ echo "configure: failed program was:" 1>&AS_MESSAGE_LOG_FD
+ cat conftest.java 1>&AS_MESSAGE_LOG_FD
+ echo "configure: PATH was $PATH" 1>&AS_MESSAGE_LOG_FD
ifelse([$4], , , [ rm -rf conftest*
$4
])dnl
-fi
+ ])
rm -f conftest*])
dnl
AC_CHECK_PROGS(JAVAC, javac guavac gcj jikes bock)
-if test -n "$JAVAC"; then
+AS_IF([test -n "$JAVAC"],
+ [
dnl Make sure it's at least JDK 1.5
AC_CACHE_CHECK(for JDK version 1.5,
ac_cv_prog_javac_ver_1_5,
@@ -473,7 +489,7 @@ if test -n "$JAVAC"; then
if test $ac_cv_prog_javac_ver_1_5 = no; then
unset -v JAVAC
fi
-fi
+ ])
if test -n "$JAVAC"; then
AC_SUBST(JAVAC)
:
@@ -489,4 +505,5 @@ else
fi
AC_SUBST(test_c_compiler)
-AC_OUTPUT(conf_vars)
+AC_CONFIG_FILES([conf_vars])
+AC_OUTPUT
diff --git a/lib/common_test/test_server/ts.erl b/lib/common_test/test_server/ts.erl
index 179380a562..702d0a4f03 100644
--- a/lib/common_test/test_server/ts.erl
+++ b/lib/common_test/test_server/ts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
estone/0, estone/1,
cross_cover_analyse/1,
compile_testcases/0, compile_testcases/1,
+ compile_datadirs/2,
help/0]).
%% Functions kept for backwards compatibility
@@ -75,9 +76,9 @@
%%% system running in a git repository/source tree.
%%% ts_make Interface to run the `make' program on Unix
%%% and other platforms.
-%%% ts_make_erl A corrected version of the standar Erlang module
+%%% ts_make_erl A corrected version of the standard Erlang module
%%% make (used for rebuilding test suites).
-%%% ts_lib Miscellanous utility functions, each used by several
+%%% ts_lib Miscellaneous utility functions, each used by several
%%% other modules.
%%% ts_benchmark Supervises otp benchmarks and collects results.
%%%----------------------------------------------------------------------
@@ -310,7 +311,7 @@ cl_run([App,Cat|Options0]) when is_atom(App) ->
false ->
Options0 -- [batch]
end,
- %% Make sure there is exactly one occurence of 'batch'
+ %% Make sure there is exactly one occurrence of 'batch'
Options2 = [batch|Options1],
Result =
@@ -871,7 +872,7 @@ run_test(File, Args, Options, Vars) ->
%% r(Mod, Case, Opts)
%% Each of these functions starts the test server if it
%% isn't already running, then runs the test case(s) selected
-%% by the aguments.
+%% by the arguments.
%% SpecOrMod can be a module name or the name of a test spec file,
%% with the extension .spec or .spec.OsType. The module Mod will
%% be reloaded before running the test cases.
@@ -1011,7 +1012,9 @@ compile_testcases([]) ->
ok.
compile_datadirs(DataDirs) ->
- {ok,Variables} = file:consult("variables"),
+ compile_datadirs("variables", DataDirs).
+compile_datadirs(VariablesFile, DataDirs) ->
+ {ok,Variables} = file:consult(VariablesFile),
lists:foreach(fun(Dir) ->
ts_lib:make_non_erlang(Dir, Variables)
diff --git a/lib/common_test/test_server/ts.hrl b/lib/common_test/test_server/ts.hrl
index 403c62d22e..7fb7b0a0a2 100644
--- a/lib/common_test/test_server/ts.hrl
+++ b/lib/common_test/test_server/ts.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,9 +30,7 @@
-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
-define(TS_PORT, 7887).
--define(TEST_SERVER_SCRIPT, "test_server_vx.script").
+
diff --git a/lib/common_test/test_server/ts_install.erl b/lib/common_test/test_server/ts_install.erl
index 87c2664af6..f1d3528ba1 100644
--- a/lib/common_test/test_server/ts_install.erl
+++ b/lib/common_test/test_server/ts_install.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -183,7 +183,7 @@ get_xcomp_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")];
+ "guess" -> [" --",Tag,"=",os:cmd("$ERL_TOP/make/autoconf/config.guess")];
HostVal -> [" --",Tag,"=",HostVal]
end.
@@ -339,8 +339,8 @@ to_upper(String) ->
word_size() ->
case {erlang:system_info({wordsize,external}),
erlang:system_info({wordsize,internal})} of
- {4,4} -> "";
- {8,8} -> "/64";
+ {4,4} -> "/32-bit";
+ {8,8} -> "/64-bit";
{8,4} -> "/Halfword"
end.
diff --git a/lib/common_test/test_server/ts_run.erl b/lib/common_test/test_server/ts_run.erl
index 702e5dea50..a1d20df69d 100644
--- a/lib/common_test/test_server/ts_run.erl
+++ b/lib/common_test/test_server/ts_run.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -255,6 +255,8 @@ make_command(Vars, Spec, State) ->
%% " -test_server_format_exception false",
" -boot start_sasl -sasl errlog_type error",
" -pz \"",Cwd,"\"",
+ %% FIXME This is too far away from where it is needed.
+ " -enable-feature maybe_expr",
" -ct_test_vars ",TestVars,
" -eval \"ts_run:ct_run_test(\\\"",TestDir,"\\\", ",
backslashify(lists:flatten(State#state.test_server_args)),")\""
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 79ba7cfe07..472bde9027 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.22.1
+COMMON_TEST_VSN = 1.24
diff --git a/lib/compiler/Makefile b/lib/compiler/Makefile
index 2edc743677..a7d896f258 100644
--- a/lib/compiler/Makefile
+++ b/lib/compiler/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -39,3 +39,9 @@ include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=crypto
include $(ERL_TOP)/make/app_targets.mk
+
+# Enable feature maybe_expr in runtime when running tests
+# Note: this overrides, and uses, test target in app_targets.mk
+.PHONY: test
+test:
+ $(MAKE) ERL_ARGS="-enable-feature maybe_expr $(ERL_ARGS)" -f $(ERL_TOP)/make/app_targets.mk $@
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index b2d9a143ab..5828fc6a17 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>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -227,6 +227,30 @@
</p>
</item>
+ <tag><c>{feature, Feature, enable | disable}</c></tag>
+ <item>
+ <p><marker id="feature-option"/>
+ Enable (disable) the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>Feature</c> during compilation. The special feature
+ <c>all</c> can be used to enable (disable) all features.
+ </p>
+ <note>
+ <p>This option has no effect when used in a
+ <c>-compile(..)</c> attribute. Instead, the
+ <c>-feature(..)</c> directive (below) should be used.
+ </p>
+ <p><marker id="feature-directive"/>
+ A feature can also be enabled (disabled) using the
+ <c>-feature(Feature, enable | disable).</c> module directive.
+ Note that this directive can only be present in a prefix
+ of the file, before exports and function definitions.
+ This is the preferred method of enabling and disabling
+ features, since it is a local property of a module.
+ </p>
+ </note>
+ </item>
+
<tag><c>makedep</c></tag>
<item>
<p>Produces a Makefile rule to track headers dependencies.
@@ -255,7 +279,7 @@ module.beam: module.erl \
<tag><c>makedep_side_effect</c></tag>
<item>
- <p>The dependecies are created as a side effect to the
+ <p>The dependencies are created as a side effect to the
normal compilation process. This means that the object
file will also be produced. This option override the
<c>makedep</c> option.
@@ -395,6 +419,14 @@ module.beam: module.erl \
<c>module_info(compile)</c> and stack traces.</p>
</item>
+ <tag><c>absolute_source</c></tag>
+ <item>
+ <p>Turns the source file name (as presented in
+ <c>module_info(compile)</c> and stack traces) into an absolute
+ path, which helps external tools like <c>perf</c> and <c>gdb</c>
+ find Erlang source code.</p>
+ </item>
+
<tag><c>{outdir,Dir}</c></tag>
<item>
<p>Sets a new directory for the object code. The current
@@ -647,6 +679,18 @@ module.beam: module.erl \
emit warnings for such variables.</p>
</item>
+ <tag><c>warn_keywords</c></tag>
+ <item>
+ <p><marker id="warn-keywords"/>
+ Emits warnings when the code contains atoms that are
+ used as keywords in some <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>.
+ When the feature is enabled, any occurrences will lead to
+ a syntax error. To prevent this, the atom has to
+ be renamed or quoted.
+ </p>
+ </item>
+
<tag><c>nowarn_unused_function</c></tag>
<item>
<p>Turns off warnings for unused local functions. Default
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index e6f3b3a38b..af671ff7ba 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,444 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 8.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that would cause the compiler to hang.</p>
+ <p>
+ Own Id: OTP-18378 Aux Id: GH-6604 </p>
+ </item>
+ <item>
+ <p>Fixed a crash when compiling code that contained
+ <c>maybe</c> expressions.</p>
+ <p>
+ Own Id: OTP-18381 Aux Id: GH-6601 </p>
+ </item>
+ <item>
+ <p>Constructing a binary with an explicit size of
+ <c>all</c> for a binary segment would crash the
+ compiler.</p>
+ <p>
+ Own Id: OTP-18407 Aux Id: GH-6707 </p>
+ </item>
+ <item>
+ <p>The compiler would generate incorrect code for the
+ following type of expression:</p>
+ <p><c>Pattern = BoundVar1 = . . . = BoundVarN =
+ Expression</c></p>
+ <p>An exception should be raised if any of the bound
+ variables have different values than <c>Expression</c>.
+ The compiler would generate code that would cause the
+ bound variables to be bound to the value of
+ <c>Expression</c>whether the value matched or not.</p>
+ <p>
+ Own Id: OTP-18470 Aux Id: GH-6873, PR-6877 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that could cause legal code to fail
+ validation.</p>
+ <p>
+ Own Id: OTP-18365</p>
+ </item>
+ <item>
+ <p>Eliminated a rare crash in the <c>beam_types</c>
+ module.</p>
+ <p>
+ Own Id: OTP-18368</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Line number in compiler messages would be truncated to
+ 4 digits for line numbers greater than 9999.</p>
+ <p>
+ Own Id: OTP-18268 Aux Id: GH-6332 </p>
+ </item>
+ <item>
+ <p>In rare circumstance, matching a binary as part of a
+ <c>receive</c> clause could cause the compiler to
+ terminate because of an internal consistency check
+ failure.</p>
+ <p>
+ Own Id: OTP-18273 Aux Id: GH-6341 </p>
+ </item>
+ <item>
+ <p>Compiling a function with complex bit syntax matching
+ such as <c>f(&lt;&lt;X:0, _:X&gt;&gt;, &lt;&lt;Y:0,
+ _:Y&gt;&gt;) -&gt; ok.</c> could crash the compiler.</p>
+ <p>
+ Own Id: OTP-18308 Aux Id: GH-6426 </p>
+ </item>
+ <item>
+ <p>It is not allowed to call functions from guards. The
+ compiler failed to reject a call in a guard when done by
+ constructing a record with a default initialization
+ expression that called a function.</p>
+ <p>
+ Own Id: OTP-18325 Aux Id: GH-6465, GH-6466 </p>
+ </item>
+ <item>
+ <p>The compiler could crash when using a record with
+ complex field initialization expression as a filter in a
+ list comprehension.</p>
+ <p>
+ Own Id: OTP-18336 Aux Id: GH-6501, PR-6502 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The compiler will now forbid using the empty atom
+ <c>''</c> as module name. Also forbidden are modules
+ names containing control characters, and module names
+ containing only spaces and soft hyphens.</p>
+ <p>
+ Own Id: OTP-18125 Aux Id: GH-6026 </p>
+ </item>
+ <item>
+ <p>The <c>bin_opt_info</c> and <c>recv_opt_info</c>
+ options would cause the compiler to crash when attempting
+ to compile generated code without location
+ information.</p>
+ <p>
+ Own Id: OTP-18162 Aux Id: PR-6102 </p>
+ </item>
+ <item>
+ <p>In rare circumstances involving floating point
+ operations, the compiler could terminate with an internal
+ consistency check failure.</p>
+ <p>
+ Own Id: OTP-18182 Aux Id: GH-6163 </p>
+ </item>
+ <item>
+ <p>In rare circumstances when doing arithmetic
+ instructions on non-numbers, the compiler could
+ crash.</p>
+ <p>
+ Own Id: OTP-18183 Aux Id: GH-6169 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, complex boolean expressions in
+ nested cases could cause the compiler to crash.</p>
+ <p>
+ Own Id: OTP-18184 Aux Id: GH-6164 </p>
+ </item>
+ <item>
+ <p>Expression similar to <c>#{assoc:=V} =
+ #key=&gt;self()}, V</c> would return the empty map
+ instead of raising an exception.</p>
+ <p>
+ Own Id: OTP-18186</p>
+ </item>
+ <item>
+ <p>Eliminated a crash in the <c>beam_ssa_bool</c> pass of
+ the compiler when compiling a complex guard
+ expression.</p>
+ <p>
+ Own Id: OTP-18187 Aux Id: GH-6184 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, the compiler could crash with
+ an internal consistency check failure.</p>
+ <p>
+ Own Id: OTP-18202 Aux Id: GH-6222 </p>
+ </item>
+ <item>
+ <p>When compiling with the option
+ <c>inline_list_funcs</c>, the compiler could produce a
+ nonsensical warning.</p>
+ <p>
+ Own Id: OTP-18214 Aux Id: GH-6158 </p>
+ </item>
+ <item>
+ <p>When given the <c>no_ssa_opt</c> option, the compiler
+ could terminate with an internal consistency failure
+ diagnostic when compiling map matching.</p>
+ <p>
+ Own Id: OTP-18234 Aux Id: GH-6277 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Made warnings for existing atoms being keywords in
+ experimental features more precise, by not warning about
+ quoted atoms.</p>
+ <p>
+ Own Id: OTP-18050</p>
+ </item>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>A subtle bug regarding variable scoping has been
+ corrected. Consider this example:</p>
+ <p><c>(A=1) + fun() -&gt; A = 2() end</c></p>
+ <p>In the shell, the expression correctly evaluates to
+ <c>3</c>. In compiled code, it raised a <c>{badmatch,
+ 2}</c> exception.</p>
+ <p>
+ Own Id: OTP-17810 Aux Id: GH-5379 </p>
+ </item>
+ <item>
+ <p>Fixed a rare bug that would crash the compiler during
+ type optimization.</p>
+ <p>
+ Own Id: OTP-17820</p>
+ </item>
+ <item>
+ <p>Starting in OTP 24, when a fun was created and
+ immediately used, it would be inlined. An unintended
+ consequence of the inlining was that what would be a
+ <c>function_clause</c> exception without the inlining
+ would now be a rather confusing <c>case_clause</c>
+ exception. This has been corrected, so that
+ <c>function_clause</c> exceptions remain
+ <c>function_clause</c> exceptions in inlined code.</p>
+ <p>
+ Own Id: OTP-17860 Aux Id: GH-5513, OTP-17226 </p>
+ </item>
+ <item>
+ <p>
+ If a default record field initialization (<c>_ =
+ Expr</c>) was used even though all records fields were
+ explicitly initialized, <c>Expr</c> would not be
+ evaluated. That would not be a problem, except when
+ <c>Expr</c> would bind a variable subsequently used, in
+ which case the compiler would crash.</p>
+ <p>
+ As an example, if record <c>#r{}</c> is defined to have
+ only one field <c>a</c>, the following code would crash
+ the compiler:</p>
+ <p>
+ <c>#r{a=[],_=V=42}, V</c></p>
+ <p>
+ To fix that problem, the compiler will make sure that
+ <c>Expr</c> is always evaluated at least once. The
+ compiler will now rewrite the example to essentially:</p>
+ <p>
+ <c>V=42, #r{a=[]}, V</c></p>
+ <p>
+ Own Id: OTP-18083</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>To enable more optimizations, BEAM files compiled with
+ OTP 21 and earlier cannot be loaded in OTP 25.</p>
+ <p>
+ Own Id: OTP-16702</p>
+ </item>
+ <item>
+ <p>
+ Added support for the compile attribute <c>-nifs()</c> to
+ empower compiler and loader with information about which
+ functions may be overridden as NIFs by
+ <c>erlang:load_nif/2</c>. It is recommended to use this
+ attribute in all modules that load NIF libraries.</p>
+ <p>
+ Own Id: OTP-17151 Aux Id: ERIERL-590, PR-5479 </p>
+ </item>
+ <item>
+ <p>When binary construction using the binary syntax
+ fails, the error message printed in the shell and by
+ <c>erl_error:format_exception/3,4</c> will contain more
+ detailed information about what went wrong.</p>
+ <p>
+ Own Id: OTP-17504 Aux Id: GH-4971, PR-5281, PR-5752 </p>
+ </item>
+ <item>
+ <p>The Erlang compiler now includes type information in
+ BEAM files, and the JIT can now use that type information
+ to do optimizations such as eliminating or simplifying
+ type tests.</p>
+ <p>
+ Own Id: OTP-17684 Aux Id: PR-5316, PR-5664 </p>
+ </item>
+ <item>
+ <p>Improved the JIT's support for external tools like
+ <c>perf</c> and <c>gdb</c>, allowing them to show line
+ numbers and even the original Erlang source code when
+ that can be found.</p>
+ <p>To aid them in finding the source code, the
+ <c>absolute_path</c> compiler option has been added to
+ embed the absolute file path of a module.</p>
+ <p>
+ Own Id: OTP-17685</p>
+ </item>
+ <item>
+ <p>The <c>maybe</c> ... <c>end</c> construction proposed
+ in EEP-49 has been implemented. It can simplify complex
+ code where otherwise deeply nested cases would have to be
+ used.</p> <p>To enable <c>maybe</c>, give the option
+ <c>-enable-feature maybe_expr</c> to <c>erlc</c> or add
+ <c>-feature(maybe_expr, enable).</c> inside the
+ module.</p>
+ <p>
+ Own Id: OTP-17705 Aux Id: PR-5411 </p>
+ </item>
+ <item>
+ <p>When a record matching or record update fails, a
+ <c>{badrecord,ExpectedRecordTag}</c> exception used to be
+ raised. In this release, the exception has been changed
+ to <c>{badrecord,ActualValue}</c>, where
+ <c>ActualValue</c> is the actual that was found instead
+ of the expected record.</p>
+ <p>
+ Own Id: OTP-17841 Aux Id: PR-5694 </p>
+ </item>
+ <item>
+ <p>Improved optimization of try/catch expressions.</p>
+ <p>
+ Own Id: OTP-17842</p>
+ </item>
+ <item>
+ <p>The <c>beam_trim</c> pass of the compiler could be
+ extremely slow for huge straight-line functions. It will
+ now compile such functions much faster (down to seconds
+ from minutes for some huge functions).</p>
+ <p>
+ Own Id: OTP-17885 Aux Id: GH-5140 </p>
+ </item>
+ <item>
+ <p>
+ Added support for configurable features as described in
+ EEP-60. Features can be enabled/disabled during
+ compilation with options (<c>-enable-feature Feature</c>,
+ <c>-disable-feature Feature</c> and <c>+{feature,
+ Feature, enable|disable}</c>) to <c>erlc</c> as well as
+ with directives (<c>-feature(Feature,
+ enable|disable).</c>) in the file. Similar options can be
+ used to <c>erl</c> for enabling/disabling features
+ allowed at runtime. The new <c>maybe</c> expression
+ (EEP-49) is fully supported as the feature
+ <c>maybe_expr</c>. The features support is documented in
+ the reference manual.</p>
+ <p>
+ Own Id: OTP-17988</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.1.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The compiler would generate incorrect code for the
+ following type of expression:</p>
+ <p><c>Pattern = BoundVar1 = . . . = BoundVarN =
+ Expression</c></p>
+ <p>An exception should be raised if any of the bound
+ variables have different values than <c>Expression</c>.
+ The compiler would generate code that would cause the
+ bound variables to be bound to the value of
+ <c>Expression</c>whether the value matched or not.</p>
+ <p>
+ Own Id: OTP-18470 Aux Id: GH-6873, PR-6877 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.1.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>It is not allowed to call functions from guards. The
+ compiler failed to reject a call in a guard when done by
+ constructing a record with a default initialization
+ expression that called a function.</p>
+ <p>
+ Own Id: OTP-18325 Aux Id: GH-6465, GH-6466 </p>
+ </item>
+ <item>
+ <p>Fixed a bug that could cause legal code to fail
+ validation.</p>
+ <p>
+ Own Id: OTP-18365</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 8.1.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The <c>bin_opt_info</c> and <c>recv_opt_info</c>
+ options would cause the compiler to crash when attempting
+ to compile generated code without location
+ information.</p>
+ <p>
+ Own Id: OTP-18162 Aux Id: PR-6102 </p>
+ </item>
+ <item>
+ <p>In rare circumstances involving floating point
+ operations, the compiler could terminate with an internal
+ consistency check failure.</p>
+ <p>
+ Own Id: OTP-18182 Aux Id: GH-6163 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 8.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -441,6 +879,22 @@
</section>
+<section><title>Compiler 7.6.9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>In rare circumstances, the compiler would mistakenly
+ assume that a call to <c>setelement/3</c> would always
+ fail and remove all code following the call.</p>
+ <p>
+ Own Id: OTP-18082</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.6.9.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1154,7 +1608,7 @@
<item>
<p>The type optimization pass of the compiler could hang
or loop for a long time when analyzing a
- <c>setelement/3</c> call with a varible position.</p>
+ <c>setelement/3</c> call with a variable position.</p>
<p>
Own Id: OTP-15828 Aux Id: ERL-948 </p>
</item>
@@ -1871,7 +2325,7 @@
<item>
<p>The compiler could issue an incorrect internal
consistency failure diagnostic for some complicated bit
- syntax maches.</p>
+ syntax matches.</p>
<p>
Own Id: OTP-14640 Aux Id: ERL-490 </p>
</item>
@@ -3612,7 +4066,7 @@
Own Id: OTP-8579</p>
</item>
<item>
- <p>The undocumented, unsupport, and deprecated function
+ <p>The undocumented, unsupported, and deprecated function
<c>lists:flat_length/1</c> has been removed.</p>
<p>
Own Id: OTP-8584</p>
@@ -3661,7 +4115,7 @@
<item>
<p>
Using complex boolean expressions in ifs could cause the
- compiler to either crash or teminate with an internal
+ compiler to either crash or terminate with an internal
error. (Thanks to Simon Cornish.)</p>
<p>
Own Id: OTP-8338</p>
@@ -3861,7 +4315,7 @@
<p>Using <c>andalso</c>/<c>orelse</c> or record access in
a <c>try</c>...<c>catch</c> could cause a compiler
crash.</p>
- <p>Som large and complex functions could require
+ <p>Some large and complex functions could require
extremely long compilation times (hours or days).</p>
<p>
Own Id: OTP-7905</p>
@@ -4761,7 +5215,7 @@
string could cause the compiler to generate dangerous
code that could cause a crash at run-time (e.g.
<c><![CDATA[R#r{a="abc",b=1}]]></c>). (Thanks to Mikael Karlsson.)</p>
- <p>Unecessary tests (such as a 'case' with two case
+ <p>Unnecessary tests (such as a 'case' with two case
branches that were identical) could cause the compiler to
crash. (Thanks to Fredrik Thulin.)</p>
<p>The validation pass of the compiler could generate an
diff --git a/lib/compiler/internal_doc/beam_ssa.md b/lib/compiler/internal_doc/beam_ssa.md
index 29ad019194..d32431ecff 100644
--- a/lib/compiler/internal_doc/beam_ssa.md
+++ b/lib/compiler/internal_doc/beam_ssa.md
@@ -1,6 +1,113 @@
Invariants on the Structure and Format of BEAM SSA
==================================================
+Exception Handling
+------------------
+
+The translation of a `try`-`catch` expression into BEAM SSA has the
+following structure:
+
+ @tag = new_try_tag `try`
+ br @tag, ^protected_block0, ^landing_pad_block
+
+ protected_block0:
+ @success0 = ... % Something that could raise an exception
+ br @success0, ^protected_block1, ^landing_pad_block
+
+ ...
+
+ protected_blockN:
+ % The end of the protected code
+ @ignored0 = kill_try_tag @tag
+ br ^after_try_catch
+
+ landing_pad_block:
+ @aggregate = landingpad try, @tag
+ @class = extract @aggregate, `0` % The error class
+ @reason = extract @aggregate, `1` % The reason
+ @stk = extract @aggregate, `2` % The stack trace
+ @ignored1 = kill_try_tag @tag
+ %% Pattern matching on @class, @reason, and @stk is done here
+ %% to send control to the appropriate catch clause
+ br ^after_try_catch
+
+ after_try_catch:
+ % Normal execution continues
+
+The following invariants must hold for the SSA:
+
+ * All code that can cause an exception in one of the protected blocks
+ must have explicit control flow edges to the landing pad block. If
+ there are no edges to the landing pad block except from the block
+ containing the `new_try_tag`, the compiler will remove the
+ redundant exception handler.
+ * The extraction of the class, reason and stack trace from the result
+ of the `landingpad` instruction must be done in that
+ order. Omitting the extraction of elements which are unused is
+ allowed.
+ * Both the landing pad block and the final protected block must end
+ with a `kill_try_tag` instruction. Trying to share the
+ `kill_try_tag` epilogue between the last protected block and the
+ landing pad is unlikely to work.
+
+The translation of an old-style `catch` expression into BEAM SSA has
+the following structure:
+
+ @tag = new_try_tag `try`
+ br @tag, ^protected_block0, ^landing_pad_block
+
+ protected_block0:
+ @success0 = ... % Something that could raise an exception
+ br @success0, ^protected_block1, ^landing_pad_block
+
+ ...
+
+ protected_blockN:
+ % The end of the protected code
+ @successful_result = .... % The result of a successful computation
+ br ^common_end_of_catch
+
+ landing_pad_block:
+ @aggregate = landingpad catch, @tag
+ @catched_val = extract @ssa_agg, `0`
+ br ^common_end_of_catch
+
+ common_end_of_catch:
+ @tmp = phi { @catched_val, ^landing_pad_block },
+ { @successful_result, ^protected_blockN }
+ @result_of_catch_expr = catch_end @tag, @tmp
+
+Just as for a `try`-`catch` expression all code that can cause an
+exception in one of the protected blocks must have explicit control
+flow edges to the landing pad block.
+
+Exception Re-issuing
+--------------------
+
+A typical user-written `try`-`catch` expression will catch a subset of
+all possible exception classes and reasons and leave unhandled
+exceptions to a handler further up the call stack. Re-issuing an
+exception is done with the `resume` instruction. The `resume` must
+come after the `kill_try_tag` instruction in the program flow. For
+example, if the [example in the Exception Handling Section](#exception-handling)
+was to only handle user `throws`, the relevant blocks would look like this:
+
+ landing_pad_block:
+ @aggregate = landingpad `try`, @tag
+ @class = extract @aggregate, `0` % The error class
+ @reason = extract @aggregate, `1` % The reason
+ @stk = extract @aggregate, `2` % The stack trace
+ @ignored1 = kill_try_tag @tag
+ @is_throw = bif:'=:=' @class, `throw`
+ br @is_throw ^first_block_of_throw_handler, ^reissue
+
+ first_block_of_throw_handler:
+ %% Handle the user-defined throw
+
+ reissue:
+ @tmp = resume @stk, @reason
+ ret @tmp
+
Function Calls
--------------
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index f050e134f8..d801d6baa0 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/compiler-$(VSN)
MODULES = \
beam_a \
beam_asm \
+ beam_bounds \
beam_block \
beam_call_types \
beam_clean \
@@ -58,14 +59,12 @@ MODULES = \
beam_jump \
beam_listing \
beam_opcodes \
- beam_peep \
beam_ssa \
beam_ssa_bc_size \
beam_ssa_bool \
beam_ssa_bsm \
beam_ssa_codegen \
beam_ssa_dead \
- beam_ssa_funs \
beam_ssa_lint \
beam_ssa_opt \
beam_ssa_pp \
@@ -107,6 +106,7 @@ MODULES = \
BEAM_H = $(wildcard ../priv/beam_h/*.h)
HRL_FILES= \
+ beam_asm.hrl \
beam_disasm.hrl \
beam_ssa_opt.hrl \
beam_ssa.hrl \
@@ -138,11 +138,17 @@ ERL_COMPILE_FLAGS += -Werror
ERL_COMPILE_FLAGS += +inline +warn_unused_import \
-I../../stdlib/include -I$(EGEN) -W +warn_missing_spec
+ifeq ($(ERL_DETERMINISTIC),yes)
+ DETERMINISM_FLAG = +deterministic
+else
+ DETERMINISM_FLAG =
+endif
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
docs:
@@ -193,25 +199,29 @@ release_docs_spec:
# Dependencies -- alphabetically, please
# ----------------------------------------------------
+$(EBIN)/beam_asm.beam: beam_asm.hrl
$(EBIN)/beam_call_types.beam: beam_types.hrl
-$(EBIN)/beam_disasm.beam: $(EGEN)/beam_opcodes.hrl beam_disasm.hrl
-$(EBIN)/beam_listing.beam: core_parse.hrl v3_kernel.hrl beam_ssa.hrl
+$(EBIN)/beam_block.beam: beam_asm.hrl
+$(EBIN)/beam_disasm.beam: $(EGEN)/beam_opcodes.hrl beam_disasm.hrl beam_asm.hrl
+$(EBIN)/beam_jump.beam: beam_asm.hrl
$(EBIN)/beam_kernel_to_ssa.beam: v3_kernel.hrl beam_ssa.hrl
+$(EBIN)/beam_listing.beam: core_parse.hrl v3_kernel.hrl beam_ssa.hrl beam_asm.hrl
$(EBIN)/beam_ssa.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_bsm.beam: beam_ssa.hrl
-$(EBIN)/beam_ssa_codegen.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_bool.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_codegen.beam: beam_ssa.hrl beam_asm.hrl
$(EBIN)/beam_ssa_dead.beam: beam_ssa.hrl
-$(EBIN)/beam_ssa_funs.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_lint.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_opt.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_pp.beam: beam_ssa.hrl
-$(EBIN)/beam_ssa_pre_codegen.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_pre_codegen.beam: beam_ssa.hrl beam_asm.hrl
$(EBIN)/beam_ssa_recv.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_share.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_throw.beam: beam_ssa.hrl
$(EBIN)/beam_ssa_type.beam: beam_ssa.hrl beam_types.hrl
+$(EBIN)/beam_trim.beam: beam_asm.hrl
$(EBIN)/beam_types.beam: beam_types.hrl
-$(EBIN)/beam_validator.beam: beam_types.hrl
+$(EBIN)/beam_validator.beam: beam_types.hrl beam_asm.hrl
$(EBIN)/cerl.beam: core_parse.hrl
$(EBIN)/compile.beam: core_parse.hrl ../../stdlib/include/erl_compile.hrl
$(EBIN)/core_lib.beam: core_parse.hrl
@@ -219,6 +229,7 @@ $(EBIN)/core_lint.beam: core_parse.hrl
$(EBIN)/core_parse.beam: core_parse.hrl $(EGEN)/core_parse.erl
$(EBIN)/core_pp.beam: core_parse.hrl
$(EBIN)/sys_core_alias.beam: core_parse.hrl
+$(EBIN)/sys_core_bsm.beam: core_parse.hrl
$(EBIN)/sys_core_fold.beam: core_parse.hrl
$(EBIN)/sys_core_fold_lists.beam: core_parse.hrl
$(EBIN)/sys_core_inline.beam: core_parse.hrl
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index e22604e57b..7317b2409d 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,15 +24,15 @@
-export([module/4]).
-export([encode/2]).
--export_type([fail/0,label/0,reg/0,reg_num/0,src/0,module_code/0,function_name/0]).
+-export_type([fail/0,label/0,src/0,module_code/0,function_name/0]).
-import(lists, [map/2,member/2,keymember/3,duplicate/2,splitwith/2]).
+
-include("beam_opcodes.hrl").
+-include("beam_asm.hrl").
%% Common types for describing operands for BEAM instructions.
--type reg_num() :: 0..1023.
--type reg() :: {'x',reg_num()} | {'y',reg_num()}.
--type src() :: reg() |
+-type src() :: beam_reg() |
{'literal',term()} |
{'atom',atom()} |
{'integer',integer()} |
@@ -64,11 +64,12 @@ module(Code, ExtraChunks, CompileInfo, CompilerOpts) ->
assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, ExtraChunks, CompileInfo, CompilerOpts) ->
{1,Dict0} = beam_dict:atom(Mod, beam_dict:new()),
{0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0),
- Dict2 = shared_fun_wrappers(CompilerOpts, Dict1),
+ {0,Dict2} = beam_dict:type(any, Dict1),
+ Dict3 = shared_fun_wrappers(CompilerOpts, Dict2),
NumFuncs = length(Asm0),
{Asm,Attr} = on_load(Asm0, Attr0),
Exp = sets:from_list(Exp0, [{version, 2}]),
- {Code,Dict} = assemble_1(Asm, Exp, Dict2, []),
+ {Code,Dict} = assemble_1(Asm, Exp, Dict3, []),
build_file(Code, Attr, Dict, NumLabels, NumFuncs,
ExtraChunks, CompileInfo, CompilerOpts).
@@ -130,7 +131,7 @@ assemble_function([H|T], Acc, Dict0) ->
assemble_function([], Code, Dict) ->
{Code, Dict}.
-build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, CompileInfo, CompilerOpts) ->
+build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks0, CompileInfo, CompilerOpts) ->
%% Create the code chunk.
CodeChunk = chunk(<<"Code">>,
@@ -142,9 +143,8 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, CompileInfo, Comp
Code),
%% Create the atom table chunk.
- AtomEncoding = atom_encoding(CompilerOpts),
- {NumAtoms, AtomTab} = beam_dict:atom_table(Dict, AtomEncoding),
- AtomChunk = chunk(atom_chunk_name(AtomEncoding), <<NumAtoms:32>>, AtomTab),
+ {NumAtoms, AtomTab} = beam_dict:atom_table(Dict),
+ AtomChunk = chunk(<<"AtU8">>, <<NumAtoms:32>>, AtomTab),
%% Create the import table chunk.
@@ -191,13 +191,27 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, CompileInfo, Comp
end,
%% Create the line chunk.
-
LineChunk = chunk(<<"Line">>, build_line_table(Dict)),
+ %% Create the type table chunk.
+ {NumTypes, TypeTab} = beam_dict:type_table(Dict),
+ TypeChunk = chunk(<<"Type">>,
+ <<?BEAM_TYPES_VERSION:32, NumTypes:32>>,
+ TypeTab),
+
+ %% Create the meta chunk
+ Meta = proplists:get_value(<<"Meta">>, ExtraChunks0, empty),
+ MetaChunk = case Meta of
+ empty -> [];
+ Meta -> chunk(<<"Meta">>, Meta)
+ end,
+ %% Remove Meta chunk from ExtraChunks since it is essential
+ ExtraChunks = ExtraChunks0 -- [{<<"Meta">>, Meta}],
+
%% Create the attributes and compile info chunks.
Essentials0 = [AtomChunk,CodeChunk,StringChunk,ImportChunk,
- ExpChunk,LambdaChunk,LiteralChunk],
+ ExpChunk,LambdaChunk,LiteralChunk,MetaChunk],
Essentials1 = [iolist_to_binary(C) || C <- Essentials0],
MD5 = module_md5(Essentials1),
Essentials = finalize_fun_table(Essentials1, MD5),
@@ -212,23 +226,16 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, CompileInfo, Comp
%% Create IFF chunk.
Chunks = case member(slim, CompilerOpts) of
- true ->
- [Essentials,AttrChunk];
- false ->
- [Essentials,LocChunk,AttrChunk,
- CompileChunk,CheckedChunks,LineChunk]
- end,
+ true when NumTypes > 0 ->
+ [Essentials,AttrChunk,TypeChunk];
+ true when NumTypes =:= 0 ->
+ [Essentials,AttrChunk];
+ false ->
+ [Essentials,LocChunk,AttrChunk,
+ CompileChunk,CheckedChunks,LineChunk,TypeChunk]
+ end,
build_form(<<"BEAM">>, Chunks).
-atom_encoding(Opts) ->
- case proplists:get_bool(no_utf8_atoms, Opts) of
- false -> utf8;
- true -> latin1
- end.
-
-atom_chunk_name(utf8) -> <<"AtU8">>;
-atom_chunk_name(latin1) -> <<"Atom">>.
-
%% 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
@@ -391,6 +398,12 @@ make_op({make_fun3,{f,Lbl},_Index,_OldUniq,Dst,{list,Env}}, Dict0) ->
NumFree = length(Env),
{Fun,Dict} = beam_dict:lambda(Lbl, NumFree, Dict0),
make_op({make_fun3,Fun,Dst,{list,Env}}, Dict);
+make_op({call_fun2,{f,Lbl},Arity,Func}, Dict0) ->
+ %% call_fun with known target, fill in the fun entry.
+ #tr{t=#t_fun{target={_Name, TotalArity}}} = Func, %Assertion.
+ NumFree = TotalArity - Arity,
+ {Lambda,Dict} = beam_dict:lambda(Lbl, NumFree, Dict0),
+ make_op({call_fun2,Lambda,Arity,Func}, Dict);
make_op({kill,Y}, Dict) ->
make_op({init,Y}, Dict);
make_op({Name,Arg1}, Dict) ->
@@ -401,14 +414,9 @@ make_op({Name,Arg1,Arg2,Arg3}, Dict) ->
encode_op(Name, [Arg1,Arg2,Arg3], Dict);
make_op({Name,Arg1,Arg2,Arg3,Arg4}, Dict) ->
encode_op(Name, [Arg1,Arg2,Arg3,Arg4], Dict);
-make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5], Dict);
-make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5,Arg6], Dict);
-%% make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7}, Dict) ->
-%% encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7], Dict);
-make_op({Name,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8}, Dict) ->
- encode_op(Name, [Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,Arg8], Dict);
+make_op(Instr, Dict) when tuple_size(Instr) >= 6 ->
+ [Name|Args] = tuple_to_list(Instr),
+ encode_op(Name, Args, Dict);
make_op(Op, Dict) when is_atom(Op) ->
encode_op(Op, [], Dict).
@@ -422,6 +430,23 @@ encode_op_1([A0|As], Dict0, Acc) ->
encode_op_1(As, Dict, [Acc,A]);
encode_op_1([], Dict, Acc) -> {Acc,Dict}.
+encode_arg(#tr{r={x, X},t=Type}, Dict0) when is_integer(X), X >= 0 ->
+ %% Gracefully prevent this module from being loaded in OTP 24 and below by
+ %% forcing an opcode it doesn't understand. It would of course fail to load
+ %% without this, but the error message wouldn't be very helpful.
+ Canary = beam_opcodes:opcode(call_fun2, 3),
+ {Index, Dict} = beam_dict:type(Type, beam_dict:opcode(Canary, Dict0)),
+ Data = [encode(?tag_z, 5),
+ encode(?tag_x, X),
+ encode(?tag_u, Index)],
+ {Data, Dict};
+encode_arg(#tr{r={y, Y},t=Type}, Dict0) when is_integer(Y), Y >= 0 ->
+ Canary = beam_opcodes:opcode(call_fun2, 3),
+ {Index, Dict} = beam_dict:type(Type, beam_dict:opcode(Canary, Dict0)),
+ Data = [encode(?tag_z, 5),
+ encode(?tag_y, Y),
+ encode(?tag_u, Index)],
+ {Data, Dict};
encode_arg({x, X}, Dict) when is_integer(X), X >= 0 ->
{encode(?tag_x, X), Dict};
encode_arg({y, Y}, Dict) when is_integer(Y), Y >= 0 ->
diff --git a/lib/compiler/src/beam_asm.hrl b/lib/compiler/src/beam_asm.hrl
new file mode 100644
index 0000000000..5e557bbe74
--- /dev/null
+++ b/lib/compiler/src/beam_asm.hrl
@@ -0,0 +1,44 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-include("beam_types.hrl").
+
+-type reg_num() :: 0 .. 1023.
+
+-type xreg() :: {'x', reg_num()}.
+-type yreg() :: {'y', reg_num()}.
+-type freg() :: {'fr', reg_num()}.
+-type zreg() :: {'z', reg_num()}.
+
+-type beam_reg() :: xreg() | yreg() | freg().
+
+-type beam_literal() :: {atom, [] | atom()} |
+ {float, [] | float()} |
+ {integer, [] | integer()} |
+ {literal, term()} |
+ nil.
+
+%% Type-tagged beam register. Assembly passes that care about registers (e.g.
+%% beam_trim) must be prepared to handle these whenever they inspect a
+%% register.
+%%
+%% To aid in the above, the validator will explode upon encountering them in an
+%% unfamiliar context.
+-record(tr, {r :: beam_reg(), t :: type()}).
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index a38fb51b96..2954d95b7e 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,8 +21,11 @@
-module(beam_block).
+-include("beam_asm.hrl").
+
-export([module/2]).
--import(lists, [keysort/2,reverse/1,reverse/2,splitwith/2]).
+-import(lists, [keysort/2,member/2,reverse/1,reverse/2,
+ splitwith/2,usort/1]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -35,7 +38,8 @@ function({function,Name,Arity,CLabel,Is0}) ->
try
Is1 = swap_opt(Is0),
Is2 = blockify(Is1),
- Is = embed_lines(Is2),
+ Is3 = embed_lines(Is2),
+ Is = opt_maps(Is3),
{function,Name,Arity,CLabel,Is}
catch
Class:Error:Stack ->
@@ -152,8 +156,6 @@ collect({bif,N,{f,0},As,D}) -> {set,[D],As,{bif,N,{f,0}}};
collect({gc_bif,N,{f,0},R,As,D}) -> {set,[D],As,{alloc,R,{gc_bif,N,{f,0}}}};
collect({move,S,D}) -> {set,[D],[S],move};
collect({put_list,S1,S2,D}) -> {set,[D],[S1,S2],put_list};
-collect({put_tuple,A,D}) -> {set,[D],[],{put_tuple,A}};
-collect({put,S}) -> {set,[],[S],put};
collect({put_tuple2,D,{list,Els}}) -> {set,[D],Els,put_tuple2};
collect({get_tuple_element,S,I,D}) -> {set,[D],[S],{get_tuple_element,I}};
collect({set_tuple_element,S,D,I}) -> {set,[],[S,D],{set_tuple_element,I}};
@@ -216,3 +218,77 @@ sort_on_yreg([{set,[Dst],[Src],move}|_]=Moves) ->
{{x,_},{y,_}} ->
keysort(3, Moves)
end.
+
+%%%
+%%% Coalesce adjacent get_map_elements and has_map_fields instructions.
+%%%
+
+opt_maps(Is) ->
+ opt_maps(Is, []).
+
+opt_maps([{get_map_elements,Fail,Src,List}=I|Is], Acc0) ->
+ case simplify_get_map_elements(Fail, Src, List, Acc0) of
+ {ok,Acc} ->
+ opt_maps(Is, Acc);
+ error ->
+ opt_maps(Is, [I|Acc0])
+ end;
+opt_maps([{test,has_map_fields,Fail,Ops}=I|Is], Acc0) ->
+ case simplify_has_map_fields(Fail, Ops, Acc0) of
+ {ok,Acc} ->
+ opt_maps(Is, Acc);
+ error ->
+ opt_maps(Is, [I|Acc0])
+ end;
+opt_maps([I|Is], Acc) ->
+ opt_maps(Is, [I|Acc]);
+opt_maps([], Acc) -> reverse(Acc).
+
+simplify_get_map_elements(Fail, Src, {list,[Key,Dst]},
+ [{get_map_elements,Fail,Src,{list,List1}}|Acc]) ->
+ case are_keys_literals([Key]) andalso are_keys_literals(List1) andalso
+ not is_reg_overwritten(Src, List1) andalso
+ not is_reg_overwritten(Dst, List1) of
+ true ->
+ case member(Key, List1) of
+ true ->
+ %% The key is already in the other list. That is
+ %% very unusual, because there are optimizations to get
+ %% rid of duplicate keys. Therefore, don't try to
+ %% do anything smart here; just keep the
+ %% get_map_elements instructions separate.
+ error;
+ false ->
+ List = [Key,Dst|List1],
+ {ok,[{get_map_elements,Fail,Src,{list,List}}|Acc]}
+ end;
+ false ->
+ %% A destination is used more than once. That should only
+ %% happen if some optimizations are disabled, so we
+ %% will not attempt do anything smart here.
+ error
+ end;
+simplify_get_map_elements(_, _, _, _) -> error.
+
+simplify_has_map_fields(Fail, [Src|Keys0],
+ [{test,has_map_fields,Fail,[Src|Keys1]}|Acc]) ->
+ case are_keys_literals(Keys0) andalso are_keys_literals(Keys1) of
+ true ->
+ Keys = usort(Keys0 ++ Keys1),
+ {ok,[{test,has_map_fields,Fail,[Src|Keys]}|Acc]};
+ false ->
+ error
+ end;
+simplify_has_map_fields(_, _, _) -> error.
+
+are_keys_literals([#tr{}|_]) -> false;
+are_keys_literals([{x,_}|_]) -> false;
+are_keys_literals([{y,_}|_]) -> false;
+are_keys_literals([_|_]) -> true.
+
+is_reg_overwritten(Src, [_Key,Src|_]) ->
+ true;
+is_reg_overwritten(Src, [_Key,_Src|T]) ->
+ is_reg_overwritten(Src, T);
+is_reg_overwritten(_, []) ->
+ false.
diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl
new file mode 100644
index 0000000000..9a0507bb38
--- /dev/null
+++ b/lib/compiler/src/beam_bounds.erl
@@ -0,0 +1,301 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2022-2023. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Calculate tight bounds for integer operations.
+%%
+%% Reference:
+%%
+%% Henry S. Warren, Jr. Hacker's Delight (2 ed). Addison Wesley -
+%% Pearson Education, Inc. Chapter 4. Arithmetic Bounds.
+%%
+%%
+-module(beam_bounds).
+-export(['+'/2, '-'/2, '*'/2, 'div'/2, 'rem'/2,
+ 'band'/2, 'bor'/2, 'bxor'/2, 'bsr'/2, 'bsl'/2,
+ relop/3]).
+
+-type range() :: {integer(), integer()} | 'any'.
+-type range_result() :: range() | 'any'.
+-type relop() :: '<' | '=<' | '>' | '>='.
+-type bool_result() :: 'true' | 'false' | 'maybe'.
+
+-spec '+'(range(), range()) -> range_result().
+
+'+'({A,B}, {C,D}) when abs(A) bsr 256 =:= 0, abs(B) bsr 256 =:= 0,
+ abs(C) bsr 256 =:= 0, abs(D) bsr 256 =:= 0 ->
+ verify_range({A+C,B+D});
+'+'(_, _) ->
+ any.
+
+-spec '-'(range(), range()) -> range_result().
+
+'-'({A,B}, {C,D}) when abs(A) bsr 256 =:= 0, abs(B) bsr 256 =:= 0,
+ abs(C) bsr 256 =:= 0, abs(D) bsr 256 =:= 0 ->
+ verify_range({A-D,B-C});
+'-'(_, _) ->
+ any.
+
+-spec '*'(range(), range()) -> range_result().
+
+'*'({A,B}, {C,D}) when abs(A) bsr 256 =:= 0, abs(B) bsr 256 =:= 0,
+ abs(C) bsr 256 =:= 0, abs(D) bsr 256 =:= 0 ->
+ All = [X * Y || X <- [A,B], Y <- [C,D]],
+ Min = lists:min(All),
+ Max = lists:max(All),
+ verify_range({Min,Max});
+'*'(_, _) ->
+ any.
+
+-spec 'div'(range(), range()) -> range_result().
+
+'div'({_,_}, {0,0}) ->
+ %% Division by zero, don't try to do anything clever.
+ any;
+'div'({A,B}, {C,D}) when is_integer(A), is_integer(B),
+ is_integer(C), is_integer(D) ->
+ Denominators = [min(C, D),max(C, D)|
+ %% Handle zero crossing for the denominator.
+ if
+ C < 0, 0 < D -> [-1, 1];
+ C =:= 0 -> [1];
+ D =:= 0 -> [-1];
+ true -> []
+ end],
+ All = [X div Y || X <- [A,B],
+ Y <- Denominators,
+ Y =/= 0],
+ Min = lists:min(All),
+ Max = lists:max(All),
+ verify_range({Min,Max});
+'div'(_, _) ->
+ any.
+
+-spec 'rem'(range(), range()) -> range_result().
+
+'rem'({A,_}, {C,D}) when C > 0 ->
+ Max = D - 1,
+ Min = if
+ A >= 0 -> 0;
+ true -> -Max
+ end,
+ verify_range({Min,Max});
+'rem'(_, {C,D}) when C =/= 0; D =/= 0 ->
+ Max = max(abs(C), abs(D)) - 1,
+ Min = -Max,
+ verify_range({Min,Max});
+'rem'(_, _) ->
+ any.
+
+-spec 'band'(range(), range()) -> range_result().
+
+'band'({A,B}, {C,D}) when A >= 0, A bsr 256 =:= 0, C >= 0, C bsr 256 =:= 0 ->
+ Min = min_band(A, B, C, D),
+ Max = max_band(A, B, C, D),
+ {Min,Max};
+'band'(_, {C,D}) when C >= 0 ->
+ {0,D};
+'band'({A,B}, _) when A >= 0 ->
+ {0,B};
+'band'(_, _) ->
+ any.
+
+-spec 'bor'(range(), range()) -> range_result().
+
+'bor'({A,B}, {C,D}) when A >= 0, A bsr 256 =:= 0, C >= 0, C bsr 256 =:= 0 ->
+ Min = min_bor(A, B, C, D),
+ Max = max_bor(A, B, C, D),
+ {Min,Max};
+'bor'(_, _) ->
+ any.
+
+-spec 'bxor'(range(), range()) -> range_result().
+
+'bxor'({A,B}, {C,D}) when A >= 0, A bsr 256 =:= 0, C >= 0, C bsr 256 =:= 0 ->
+ Max = max_bxor(A, B, C, D),
+ {0,Max};
+'bxor'(_, _) ->
+ any.
+
+-spec 'bsr'(range(), range()) -> range_result().
+
+'bsr'({A,B}, {C,D}) when C >= 0 ->
+ Min = min(A bsr C, A bsr D),
+ Max = max(B bsr C, B bsr D),
+ {Min,Max};
+'bsr'(_, _) ->
+ any.
+
+-spec 'bsl'(range(), range()) -> range_result().
+
+'bsl'({A,B}, {C,D}) when abs(B) bsr 128 =:= 0, C >= 0, D < 128 ->
+ Min = min(A bsl C, A bsl D),
+ Max = max(B bsl C, B bsl D),
+ {Min,Max};
+'bsl'(_, _) ->
+ any.
+
+-spec relop(relop(), range(), range()) -> bool_result().
+
+relop(Op, {A,B}, {C,D}) ->
+ case {erlang:Op(B, C),erlang:Op(A, D)} of
+ {Bool,Bool} -> Bool;
+ {_,_} -> 'maybe'
+ end;
+relop(_, _, _) ->
+ 'maybe'.
+
+%%%
+%%% Internal functions.
+%%%
+
+verify_range({Min,Max}=T) when Min =< Max -> T.
+
+min_band(A, B, C, D) ->
+ M = 1 bsl (upper_bit(A bor C) + 1),
+ min_band(A, B, C, D, M).
+
+min_band(A, _B, C, _D, 0) ->
+ A band C;
+min_band(A, B, C, D, M) ->
+ if
+ (bnot A) band (bnot C) band M =/= 0 ->
+ case (A bor M) band -M of
+ NewA when NewA =< B ->
+ min_band(NewA, B, C, D, 0);
+ _ ->
+ case (C bor M) band -M of
+ NewC when NewC =< D ->
+ min_band(A, B, NewC, D, 0);
+ _ ->
+ min_band(A, B, C, D, M bsr 1)
+ end
+ end;
+ true ->
+ min_band(A, B, C, D, M bsr 1)
+ end.
+
+max_band(A, B, C, D) ->
+ M = 1 bsl upper_bit(B bxor D),
+ max_band(A, B, C, D, M).
+
+max_band(_A, B, _C, D, 0) ->
+ B band D;
+max_band(A, B, C, D, M) ->
+ if
+ B band (bnot D) band M =/= 0 ->
+ case (B band (bnot M)) bor (M - 1) of
+ NewB when NewB >= A ->
+ max_band(A, NewB, C, D, 0);
+ _ ->
+ max_band(A, B, C, D, M bsr 1)
+ end;
+ (bnot B) band D band M =/= 0 ->
+ case (D band (bnot M)) bor (M - 1) of
+ NewD when NewD >= C ->
+ max_band(A, B, C, NewD, 0);
+ _ ->
+ max_band(A, B, C, D, M bsr 1)
+ end;
+ true ->
+ max_band(A, B, C, D, M bsr 1)
+ end.
+
+min_bor(A, B, C, D) ->
+ M = 1 bsl upper_bit(A bxor C),
+ min_bor(A, B, C, D, M).
+
+min_bor(A, _B, C, _D, 0) ->
+ A bor C;
+min_bor(A, B, C, D, M) ->
+ if
+ (bnot A) band C band M =/= 0 ->
+ case (A bor M) band -M of
+ NewA when NewA =< B ->
+ min_bor(NewA, B, C, D, 0);
+ _ ->
+ min_bor(A, B, C, D, M bsr 1)
+ end;
+ A band (bnot C) band M =/= 0 ->
+ case (C bor M) band -M of
+ NewC when NewC =< D ->
+ min_bor(A, B, NewC, D, 0);
+ _ ->
+ min_bor(A, B, C, D, M bsr 1)
+ end;
+ true ->
+ min_bor(A, B, C, D, M bsr 1)
+ end.
+
+max_bor(A, B, C, D) ->
+ Intersection = B band D,
+ M = 1 bsl upper_bit(Intersection),
+ max_bor(Intersection, A, B, C, D, M).
+
+max_bor(_Intersection, _A, B, _C, D, 0) ->
+ B bor D;
+max_bor(Intersection, A, B, C, D, M) ->
+ if
+ Intersection band M =/= 0 ->
+ case (B - M) bor (M - 1) of
+ NewB when NewB >= A ->
+ max_bor(Intersection, A, NewB, C, D, 0);
+ _ ->
+ case (D - M) bor (M - 1) of
+ NewD when NewD >= C ->
+ max_bor(Intersection, A, B, C, NewD, 0);
+ _ ->
+ max_bor(Intersection, A, B, C, D, M bsr 1)
+ end
+ end;
+ true ->
+ max_bor(Intersection, A, B, C, D, M bsr 1)
+ end.
+
+max_bxor(A, B, C, D) ->
+ M = 1 bsl upper_bit(B band D),
+ max_bxor(A, B, C, D, M).
+
+max_bxor(_A, B, _C, D, 0) ->
+ B bxor D;
+max_bxor(A, B, C, D, M) ->
+ if
+ B band D band M =/= 0 ->
+ case (B - M) bor (M - 1) of
+ NewB when NewB >= A ->
+ max_bxor(A, NewB, C, D, M bsr 1);
+ _ ->
+ case (D - M) bor (M - 1) of
+ NewD when NewD >= C ->
+ max_bxor(A, B, C, NewD, M bsr 1);
+ _ ->
+ max_bxor(A, B, C, D, M bsr 1)
+ end
+ end;
+ true ->
+ max_bxor(A, B, C, D, M bsr 1)
+ end.
+
+upper_bit(Val) ->
+ upper_bit_1(Val, 0).
+
+upper_bit_1(Val0, N) ->
+ case Val0 bsr 1 of
+ 0 -> N;
+ Val -> upper_bit_1(Val, N + 1)
+ end.
diff --git a/lib/compiler/src/beam_call_types.erl b/lib/compiler/src/beam_call_types.erl
index 330fb5a603..bd1d672d4a 100644
--- a/lib/compiler/src/beam_call_types.erl
+++ b/lib/compiler/src/beam_call_types.erl
@@ -22,47 +22,64 @@
-include("beam_types.hrl").
--import(lists, [duplicate/2,foldl/3]).
+-import(lists, [any/2,duplicate/2,foldl/3]).
--export([will_succeed/3, types/3]).
+-export([will_succeed/3, types/3, arith_type/2]).
%%
%% Returns whether a call will succeed or not.
%%
-%% Note that it only answers 'yes' for functions in the 'erlang' module as
+%% Notes:
+%%
+%% This function only answers 'yes' for functions in the 'erlang' module as
%% calls to other modules may fail due to not being loaded, even if we consider
%% the module to be known.
%%
+%% This function MUST return 'no' if types/3 with the same arguments will return
+%% the return type 'none'.
+%%
-spec will_succeed(Mod, Func, ArgTypes) -> Result when
Mod :: atom(),
Func :: atom(),
ArgTypes :: [normal_type()],
- Result :: yes | no | maybe.
-
+ Result :: 'yes' | 'no' | 'maybe'.
+
+will_succeed(erlang, Op, [LHS, RHS])
+ when Op =:= '+'; Op =:= '-'; Op =:= '*' ->
+ succeeds_if_smallish(LHS, RHS);
+will_succeed(erlang, Op, [#t_integer{elements={_,_}},
+ #t_integer{elements={Div,_}}])
+ when (Op =:= 'div' orelse Op =:= 'rem'), Div > 0 ->
+ yes;
+will_succeed(erlang, 'bsr', [#t_integer{elements={_,_}},
+ #t_integer{elements={S,_}}])
+ when S >= 0 ->
+ yes;
+will_succeed(erlang, 'bsl', [#t_integer{}=LHS,#t_integer{elements={S,_}}])
+ when S < 64 ->
+ succeeds_if_smallish(LHS);
will_succeed(erlang, '++', [LHS, _RHS]) ->
succeeds_if_type(LHS, proper_list());
-will_succeed(erlang, '--', [LHS, RHS]) ->
- case {succeeds_if_type(LHS, proper_list()),
- succeeds_if_type(RHS, proper_list())} of
- {yes, yes} -> yes;
- {no, _} -> no;
- {_, no} -> no;
- {_, _} -> maybe
- end;
-will_succeed(erlang, BoolOp, [LHS, RHS]) when BoolOp =:= 'and';
- BoolOp =:= 'or' ->
- case {succeeds_if_type(LHS, beam_types:make_boolean()),
- succeeds_if_type(RHS, beam_types:make_boolean())} of
- {yes, yes} -> yes;
- {no, _} -> no;
- {_, no} -> no;
- {_, _} -> maybe
- end;
+will_succeed(erlang, '--', [_, _] = Args) ->
+ succeeds_if_types(Args, proper_list());
+will_succeed(erlang, BoolOp, [_, _] = Args) when BoolOp =:= 'and';
+ BoolOp =:= 'or' ->
+ succeeds_if_types(Args, beam_types:make_boolean());
+will_succeed(erlang, Op, [_, _] = Args) when Op =:= 'band'; Op =:= 'bor'; Op =:= 'bxor' ->
+ succeeds_if_types(Args, #t_integer{});
will_succeed(erlang, bit_size, [Arg]) ->
succeeds_if_type(Arg, #t_bitstring{});
will_succeed(erlang, byte_size, [Arg]) ->
succeeds_if_type(Arg, #t_bitstring{});
+will_succeed(erlang, element, [Pos, #t_tuple{size=Sz}] = Args) when Sz > 0 ->
+ SizeType = #t_integer{elements={1,Sz}},
+ case beam_types:meet(Pos, SizeType) of
+ Pos ->
+ yes;
+ _ ->
+ fails_on_conflict(Args, [#t_integer{}, #t_tuple{}])
+ end;
will_succeed(erlang, hd, [Arg]) ->
succeeds_if_type(Arg, #t_cons{});
will_succeed(erlang, is_function, [_,#t_integer{elements={Min,_}}])
@@ -95,6 +112,12 @@ will_succeed(erlang, tuple_size, [Arg]) ->
succeeds_if_type(Arg, #t_tuple{});
will_succeed(erlang, tl, [Arg]) ->
succeeds_if_type(Arg, #t_cons{});
+will_succeed(erlang, raise, [Class, _Reason, nil]) ->
+ case beam_types:meet(Class, #t_atom{elements=[error,exit,throw]}) of
+ Class -> no;
+ none -> yes;
+ _ -> 'maybe'
+ end;
will_succeed(Mod, Func, Args) ->
Arity = length(Args),
case erl_bifs:is_safe(Mod, Func, Arity) of
@@ -122,15 +145,59 @@ fails_on_conflict([ArgType | Args], [Required | Types]) ->
_ -> fails_on_conflict(Args, Types)
end;
fails_on_conflict([], []) ->
- maybe.
+ 'maybe'.
+
+succeeds_if_types([LHS, RHS], Required) ->
+ case {succeeds_if_type(LHS, Required),
+ succeeds_if_type(RHS, Required)} of
+ {yes, yes} -> yes;
+ {no, _} -> no;
+ {_, no} -> no;
+ {_, _} -> 'maybe'
+ end.
succeeds_if_type(ArgType, Required) ->
case beam_types:meet(ArgType, Required) of
ArgType -> yes;
none -> no;
- _ -> maybe
+ _ -> 'maybe'
end.
+succeeds_if_smallish(#t_integer{elements={Min,Max}})
+ when abs(Min) bsr 128 =:= 0, abs(Max) bsr 128 =:= 0 ->
+ yes;
+succeeds_if_smallish(ArgType) ->
+ case succeeds_if_type(ArgType, number) of
+ yes ->
+ %% Could potentially fail with a `system_limit` exception.
+ 'maybe';
+ Other ->
+ Other
+ end.
+
+succeeds_if_smallish(LHS, RHS) ->
+ case {succeeds_if_smallish(LHS),
+ succeeds_if_smallish(RHS)} of
+ {yes, yes} -> yes;
+ {no, _} -> no;
+ {_, no} -> no;
+ {_, _} -> 'maybe'
+ end.
+
+%%
+%% Define an upper limit for functions that return sizes of data
+%% structures. The chosen value is about half the maxium size of a
+%% smallnum. That means that adding a small constant to it will result
+%% in a smallnum, but still the value is still sufficiently high to
+%% make it impossible to reach in the foreseeable future.
+%%
+-define(SIZE_UPPER_LIMIT, ((1 bsl 58) - 1)).
+
+%%
+%% The document maximum size of a tuple.
+%%
+-define(MAX_TUPLE_SIZE, (1 bsl 24) - 1).
+
%%
%% Returns the inferred return and argument types for known functions, and
%% whether it's safe to subtract argument types on failure.
@@ -152,13 +219,18 @@ succeeds_if_type(ArgType, Required) ->
%% Note that these are all from the erlang module; suitable functions in other
%% modules could fail due to the module not being loaded.
types(erlang, 'map_size', [_]) ->
- sub_safe(#t_integer{}, [#t_map{}]);
-types(erlang, 'tuple_size', [_]) ->
- sub_safe(#t_integer{}, [#t_tuple{}]);
+ sub_safe(#t_integer{elements={0,?SIZE_UPPER_LIMIT}}, [#t_map{}]);
+types(erlang, 'tuple_size', [Src]) ->
+ Min = case Src of
+ #t_tuple{size=Sz} -> Sz;
+ _ -> 0
+ end,
+ Max = ?MAX_TUPLE_SIZE,
+ sub_safe(#t_integer{elements={Min,Max}}, [#t_tuple{}]);
types(erlang, 'bit_size', [_]) ->
- sub_safe(#t_integer{}, [#t_bitstring{}]);
+ sub_safe(#t_integer{elements={0,?SIZE_UPPER_LIMIT}}, [#t_bitstring{}]);
types(erlang, 'byte_size', [_]) ->
- sub_safe(#t_integer{}, [#t_bitstring{}]);
+ sub_safe(#t_integer{elements={0,?SIZE_UPPER_LIMIT}}, [#t_bitstring{}]);
types(erlang, hd, [Src]) ->
RetType = erlang_hd_type(Src),
sub_safe(RetType, [#t_cons{}]);
@@ -168,8 +240,12 @@ types(erlang, tl, [Src]) ->
types(erlang, 'not', [_]) ->
Bool = beam_types:make_boolean(),
sub_safe(Bool, [Bool]);
-types(erlang, 'length', [_]) ->
- sub_safe(#t_integer{}, [proper_list()]);
+types(erlang, 'length', [Src]) ->
+ Min = case Src of
+ #t_cons{} -> 1;
+ _ -> 0
+ end,
+ sub_safe(#t_integer{elements={Min,?SIZE_UPPER_LIMIT}}, [proper_list()]);
%% Boolean ops
types(erlang, 'and', [_,_]) ->
@@ -182,17 +258,84 @@ types(erlang, 'xor', [_,_]) ->
Bool = beam_types:make_boolean(),
sub_unsafe(Bool, [Bool, Bool]);
+%% Relational operators.
+types(erlang, Op, [#t_integer{elements=Range1},
+ #t_integer{elements=Range2}])
+ when Op =:= '<'; Op =:= '=<'; Op =:= '>='; Op =:= '>' ->
+ case beam_bounds:relop(Op, Range1, Range2) of
+ 'maybe' ->
+ sub_unsafe(beam_types:make_boolean(), [any, any]);
+ Bool when is_boolean(Bool) ->
+ sub_unsafe(#t_atom{elements=[Bool]}, [any, any])
+ end;
+
+%% Type tests.
+types(erlang, is_atom, [Type]) ->
+ sub_unsafe_type_test(Type, #t_atom{});
+types(erlang, is_binary, [Type]) ->
+ sub_unsafe_type_test(Type, #t_bs_matchable{tail_unit=8});
+types(erlang, is_bitstring, [Type]) ->
+ sub_unsafe_type_test(Type, #t_bs_matchable{});
+types(erlang, is_boolean, [Type]) ->
+ case beam_types:is_boolean_type(Type) of
+ true ->
+ sub_unsafe(#t_atom{elements=[true]}, [any]);
+ false ->
+ case beam_types:meet(Type, #t_atom{}) of
+ #t_atom{elements=[_|_]=Es} ->
+ case any(fun is_boolean/1, Es) of
+ true ->
+ sub_unsafe(beam_types:make_boolean(), [any]);
+ false ->
+ sub_unsafe(#t_atom{elements=[false]}, [any])
+ end;
+ #t_atom{} ->
+ sub_unsafe(beam_types:make_boolean(), [any]);
+ none ->
+ sub_unsafe(#t_atom{elements=[false]}, [any])
+ end
+ end;
+types(erlang, is_float, [Type]) ->
+ sub_unsafe_type_test(Type, #t_float{});
+types(erlang, is_function, [Type, #t_integer{elements={Arity,Arity}}])
+ when Arity >= 0, Arity =< ?MAX_FUNC_ARGS ->
+ RetType =
+ case beam_types:meet(Type, #t_fun{arity=Arity}) of
+ Type -> #t_atom{elements=[true]};
+ none -> #t_atom{elements=[false]};
+ _ -> beam_types:make_boolean()
+ end,
+ sub_unsafe(RetType, [any, any]);
+types(erlang, is_function, [Type]) ->
+ sub_unsafe_type_test(Type, #t_fun{});
+types(erlang, is_integer, [Type]) ->
+ sub_unsafe_type_test(Type, #t_integer{});
+types(erlang, is_list, [Type]) ->
+ sub_unsafe_type_test(Type, #t_list{});
+types(erlang, is_map, [Type]) ->
+ sub_unsafe_type_test(Type, #t_map{});
+types(erlang, is_number, [Type]) ->
+ sub_unsafe_type_test(Type, number);
+types(erlang, is_pid, [Type]) ->
+ sub_unsafe_type_test(Type, pid);
+types(erlang, is_port, [Type]) ->
+ sub_unsafe_type_test(Type, port);
+types(erlang, is_reference, [Type]) ->
+ sub_unsafe_type_test(Type, reference);
+types(erlang, is_tuple, [Type]) ->
+ sub_unsafe_type_test(Type, #t_tuple{});
+
%% Bitwise ops
types(erlang, 'band', [_,_]=Args) ->
sub_unsafe(erlang_band_type(Args), [#t_integer{}, #t_integer{}]);
-types(erlang, 'bor', [_,_]) ->
- sub_unsafe(#t_integer{}, [#t_integer{}, #t_integer{}]);
+types(erlang, 'bor', [_,_]=Args) ->
+ sub_unsafe(erlang_bor_type(Args), [#t_integer{}, #t_integer{}]);
types(erlang, 'bxor', [_,_]) ->
sub_unsafe(#t_integer{}, [#t_integer{}, #t_integer{}]);
types(erlang, 'bsl', [_,_]) ->
sub_unsafe(#t_integer{}, [#t_integer{}, #t_integer{}]);
-types(erlang, 'bsr', [_,_]) ->
- sub_unsafe(#t_integer{}, [#t_integer{}, #t_integer{}]);
+types(erlang, 'bsr', [_,_]=Args) ->
+ sub_unsafe(erlang_bsr_type(Args), [#t_integer{}, #t_integer{}]);
types(erlang, 'bnot', [_]) ->
sub_unsafe(#t_integer{}, [#t_integer{}]);
@@ -209,10 +352,12 @@ types(erlang, 'trunc', [_]) ->
sub_unsafe(#t_integer{}, [number]);
types(erlang, '/', [_,_]) ->
sub_unsafe(#t_float{}, [number, number]);
-types(erlang, 'div', [_,_]) ->
- sub_unsafe(#t_integer{}, [#t_integer{}, #t_integer{}]);
-types(erlang, 'rem', [_,_]) ->
- sub_unsafe(#t_integer{}, [#t_integer{}, #t_integer{}]);
+types(erlang, 'div', [_,_]=Args) ->
+ ArgTypes = [#t_integer{}, #t_integer{}],
+ sub_unsafe(erlang_div_type(Args), ArgTypes);
+types(erlang, 'rem', Args) ->
+ ArgTypes = [#t_integer{}, #t_integer{}],
+ sub_unsafe(erlang_rem_type(Args), ArgTypes);
%% Mixed-type arithmetic; '+'/2 and friends are handled in the catch-all
%% clause for the 'erlang' module.
@@ -233,6 +378,11 @@ types(erlang, 'iolist_to_binary', [_]) ->
%% Arg is an iodata(), despite its name.
ArgType = beam_types:join(#t_list{}, #t_bitstring{size_unit=8}),
sub_unsafe(#t_bitstring{size_unit=8}, [ArgType]);
+types(erlang, 'iolist_size', [_]) ->
+ %% Arg is an iodata(), despite its name. The size is NOT limited
+ %% by the size of memory.
+ ArgType = beam_types:join(#t_list{}, #t_bitstring{size_unit=8}),
+ sub_unsafe(#t_integer{}, [ArgType]);
types(erlang, 'list_to_binary', [_]) ->
%% Arg is an iolist(), despite its name.
sub_unsafe(#t_bitstring{size_unit=8}, [#t_list{}]);
@@ -240,6 +390,35 @@ types(erlang, 'list_to_bitstring', [_]) ->
%% As list_to_binary but with bitstrings rather than binaries.
sub_unsafe(#t_bitstring{}, [proper_list()]);
+%% Process operations
+types(erlang, alias, []) ->
+ sub_unsafe(reference, []);
+types(erlang, alias, [_]) ->
+ sub_unsafe(reference, [proper_list()]);
+types(erlang, monitor, [_, _]) ->
+ sub_unsafe(reference, [any, any]);
+types(erlang, monitor, [_, _, _]) ->
+ sub_unsafe(reference, [any, any, proper_list()]);
+types(erlang, 'spawn', [_]) ->
+ sub_unsafe(pid, [#t_fun{arity=0}]);
+types(erlang, 'spawn', [_, _]) ->
+ sub_unsafe(pid, [#t_atom{}, #t_fun{arity=0}]);
+types(erlang, 'spawn', [_, _, _]) ->
+ sub_unsafe(pid, [#t_atom{}, #t_atom{}, proper_list()]);
+types(erlang, 'spawn_link', Args) ->
+ types(erlang, 'spawn', Args);
+types(erlang, 'spawn_monitor', [_]) ->
+ RetType = make_two_tuple(pid, reference),
+ sub_unsafe(RetType, [#t_fun{arity=0}]);
+types(erlang, 'spawn_monitor', [_, _]) ->
+ RetType = make_two_tuple(pid, reference),
+ sub_unsafe(RetType, [#t_atom{}, #t_fun{arity=0}]);
+types(erlang, 'spawn_monitor', [_, _, _]) ->
+ RetType = make_two_tuple(pid, reference),
+ sub_unsafe(RetType, [#t_atom{}, #t_atom{}, proper_list()]);
+types(erlang, 'spawn_request', [_ | _]=Args) when length(Args) =< 5 ->
+ sub_unsafe(reference, [any || _ <- Args]);
+
%% Misc ops.
types(erlang, 'binary_part', [_, _]) ->
PosLen = make_two_tuple(#t_integer{}, #t_integer{}),
@@ -254,6 +433,8 @@ types(erlang, 'is_map_key', [Key, Map]) ->
_ -> beam_types:make_boolean()
end,
sub_unsafe(RetType, [any, #t_map{}]);
+types(erlang, make_ref, []) ->
+ sub_unsafe(reference, []);
types(erlang, 'map_get', [Key, Map]) ->
RetType = erlang_map_get_type(Key, Map),
sub_unsafe(RetType, [any, #t_map{}]);
@@ -282,7 +463,10 @@ types(erlang, element, [PosType, TupleType]) ->
any
end,
- sub_unsafe(RetType, [#t_integer{}, #t_tuple{size=Index}]);
+ ArgTypes = [#t_integer{elements={1,?MAX_TUPLE_SIZE}},
+ #t_tuple{size=Index}],
+
+ sub_unsafe(RetType, ArgTypes);
types(erlang, setelement, [PosType, TupleType, ArgType]) ->
RetType = case {PosType,TupleType} of
{#t_integer{elements={Index,Index}},
@@ -325,7 +509,8 @@ types(erlang, setelement, [PosType, TupleType, ArgType]) ->
types(erlang, make_fun, [_,_,Arity0]) ->
Type = case Arity0 of
- #t_integer{elements={Arity,Arity}} when Arity >= 0 ->
+ #t_integer{elements={Arity,Arity}}
+ when Arity >= 0, Arity =< ?MAX_FUNC_ARGS ->
#t_fun{arity=Arity};
_ ->
#t_fun{}
@@ -572,8 +757,11 @@ types(maps, fold, [Fun, Init, _Map]) ->
end,
sub_unsafe(RetType, [#t_fun{arity=3}, any, #t_map{}]);
types(maps, from_keys, [Keys, Value]) ->
- RetType = #t_map{super_key=erlang_hd_type(Keys),
- super_value=Value},
+ KeyType = erlang_hd_type(Keys),
+ RetType = case KeyType of
+ none -> #t_map{super_key=none,super_value=none};
+ _ -> #t_map{super_key=KeyType,super_value=Value}
+ end,
sub_unsafe(RetType, [proper_list(), any]);
types(maps, from_list, [Pairs]) ->
PairType = erlang_hd_type(Pairs),
@@ -582,6 +770,8 @@ types(maps, from_list, [Pairs]) ->
SKey = beam_types:get_tuple_element(1, Es),
SValue = beam_types:get_tuple_element(2, Es),
#t_map{super_key=SKey,super_value=SValue};
+ none ->
+ #t_map{super_key=none,super_value=none};
_ ->
#t_map{}
end,
@@ -594,8 +784,6 @@ types(maps, get, [Key, Map, Default]) ->
ValueType -> beam_types:join(ValueType, Default)
end,
sub_unsafe(RetType, [any, #t_map{}, any]);
-types(maps, is_key, [_Key, _Map]=Args) ->
- types(erlang, is_map_key, Args);
types(maps, keys, [Map]) ->
RetType = case Map of
#t_map{super_key=none} -> nil;
@@ -675,14 +863,16 @@ types(maps, values, [Map]) ->
end,
sub_unsafe(RetType, [#t_map{}]);
types(maps, with, [Keys, Map]) ->
- RetType = case Map of
- #t_map{super_key=SKey0} ->
+ RetType = case {erlang_hd_type(Keys), Map} of
+ {none, _} ->
+ #t_map{super_key=none,super_value=none};
+ {KeysType, #t_map{super_key=SKey0}} ->
%% Since we know that the Map will only contain the pairs
%% pointed out by Keys, we can restrict the types to
%% those in the list.
- SKey = beam_types:meet(erlang_hd_type(Keys), SKey0),
+ SKey = beam_types:meet(KeysType, SKey0),
Map#t_map{super_key=SKey};
- _ ->
+ {_, _} ->
#t_map{}
end,
sub_unsafe(RetType, [proper_list(), #t_map{}]);
@@ -695,6 +885,37 @@ types(maps, without, [Keys, Map]) ->
types(_, _, Args) ->
sub_unsafe(any, [any || _ <- Args]).
+-spec arith_type(Op, ArgTypes) -> RetType when
+ Op :: beam_ssa:op(),
+ ArgTypes :: [normal_type()],
+ RetType :: type().
+
+arith_type({bif,'+'}, [#t_integer{elements=Range1},
+ #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'+'(Range1, Range2)};
+arith_type({bif,'-'}, [#t_integer{elements=Range1},
+ #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'-'(Range1, Range2)};
+arith_type({bif,'*'}, [#t_integer{elements=Range1},
+ #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'*'(Range1, Range2)};
+arith_type({bif,'div'}, ArgTypes) ->
+ erlang_div_type(ArgTypes);
+arith_type({bif,'rem'}, ArgTypes) ->
+ erlang_rem_type(ArgTypes);
+arith_type({bif,'band'}, ArgTypes) ->
+ erlang_band_type(ArgTypes);
+arith_type({bif,'bor'}, Args) ->
+ erlang_bor_type(Args);
+arith_type({bif,'bxor'}, Args) ->
+ erlang_bxor_type(Args);
+arith_type({bif,'bsr'}, Args) ->
+ erlang_bsr_type(Args);
+arith_type({bif,'bsl'}, Args) ->
+ erlang_bsl_type(Args);
+arith_type(_Op, _Args) ->
+ any.
+
%%
%% Function-specific helpers.
%%
@@ -717,48 +938,61 @@ mixed_arith_types([FirstType | _]=Args0) ->
erlang_hd_type(Src) ->
case beam_types:meet(Src, #t_cons{}) of
#t_cons{type=Type} -> Type;
- _ -> any
+ none -> none
end.
erlang_tl_type(Src) ->
case beam_types:meet(Src, #t_cons{}) of
#t_cons{terminator=Term}=Cons -> beam_types:join(Cons, Term);
- _ -> any
+ none -> none
end.
-erlang_band_type([#t_integer{elements={Int,Int}}, RHS]) when is_integer(Int) ->
- erlang_band_type_1(RHS, Int);
-erlang_band_type([LHS, #t_integer{elements={Int,Int}}]) when is_integer(Int) ->
- erlang_band_type_1(LHS, Int);
-erlang_band_type(_) ->
+erlang_band_type([#t_integer{elements=Range1}, #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'band'(Range1, Range2)};
+erlang_band_type([#t_integer{elements=Range}, _RHS]) ->
+ #t_integer{elements=beam_bounds:'band'(Range, any)};
+erlang_band_type([_LHS, #t_integer{elements=Range}]) ->
+ #t_integer{elements=beam_bounds:'band'(any, Range)};
+erlang_band_type([_, _]) ->
#t_integer{}.
-erlang_band_type_1(LHS, Int) ->
- case LHS of
- #t_integer{elements={Min0,Max0}} when Max0 - Min0 < 1 bsl 256 ->
- {Intersection, Union} = range_masks(Min0, Max0),
-
- Min = Intersection band Int,
- Max = max(Min, min(Max0, Union band Int)),
-
- #t_integer{elements={Min,Max}};
- #t_integer{} when Int >= 0 ->
- %% The range is either unknown or too wide, conservatively assume
- %% that the new range is 0 .. Int.
- %%
- %% NOTE: We must not produce a singleton type unless we are sure
- %% that the operation can't fail. Therefore, we only do this
- %% inference if LHS is known to be an integer.
- beam_types:meet(LHS, #t_integer{elements={0,Int}});
+erlang_bor_type([#t_integer{elements=Range1}, #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'bor'(Range1, Range2)};
+erlang_bor_type([_, _]) ->
+ #t_integer{}.
+
+erlang_bxor_type([#t_integer{elements=Range1}, #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'bxor'(Range1, Range2)};
+erlang_bxor_type([_, _]) ->
+ #t_integer{}.
+
+erlang_bsr_type([#t_integer{elements=Range1}, #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'bsr'(Range1, Range2)};
+erlang_bsr_type([_, _]) ->
+ #t_integer{}.
+
+erlang_bsl_type([#t_integer{elements=Range1}, #t_integer{elements=Range2}]) ->
+ #t_integer{elements=beam_bounds:'bsl'(Range1, Range2)};
+erlang_bsl_type([_, _]) ->
+ #t_integer{}.
+
+erlang_div_type(ArgTypes) ->
+ case ArgTypes of
+ [#t_integer{elements=Range1},#t_integer{elements=Range2}]->
+ #t_integer{elements=beam_bounds:'div'(Range1, Range2)};
_ ->
- %% We can't infer boundaries when LHS is not an integer or
- %% the range is unknown and the other operand is a
- %% negative number, as the latter sign-extends to infinity
- %% and we can't express an inverted range at the moment
- %% (cf. X band -8; either less than -7 or greater than 7).
- beam_types:meet(LHS, #t_integer{})
+ #t_integer{}
end.
+erlang_rem_type([LHS0, #t_integer{elements=Range2}]) ->
+ Range1 = case LHS0 of
+ #t_integer{elements=R1} -> R1;
+ _ -> any
+ end,
+ #t_integer{elements=beam_bounds:'rem'(Range1, Range2)};
+erlang_rem_type(_) ->
+ #t_integer{}.
+
erlang_map_get_type(Key, Map) ->
case Map of
#t_map{super_key=SKey,super_value=SValue} ->
@@ -930,6 +1164,15 @@ maps_remove_type(_Key, _Map) ->
%%% Generic helpers
%%%
+sub_unsafe_type_test(ArgType, Required) ->
+ RetType =
+ case beam_types:meet(ArgType, Required) of
+ ArgType -> #t_atom{elements=[true]};
+ none -> #t_atom{elements=[false]};
+ _ -> beam_types:make_boolean()
+ end,
+ sub_unsafe(RetType, [any]).
+
sub_unsafe(RetType, ArgTypes) ->
{RetType, ArgTypes, false}.
@@ -942,21 +1185,6 @@ discard_tuple_element_info(Min, Max, Es) ->
(_El, Acc) -> Acc
end, Es, maps:keys(Es)).
-%% Returns two bitmasks describing all possible values between From and To.
-%%
-%% The first contains the bits that are common to all values, and the second
-%% contains the bits that are set by any value in the range.
-range_masks(From, To) when From =< To ->
- range_masks_1(From, To, 0, -1, 0).
-
-range_masks_1(From, To, BitPos, Intersection, Union) when From < To ->
- range_masks_1(From + (1 bsl BitPos), To, BitPos + 1,
- Intersection band From, Union bor From);
-range_masks_1(_From, To, _BitPos, Intersection0, Union0) ->
- Intersection = To band Intersection0,
- Union = To bor Union0,
- {Intersection, Union}.
-
proper_cons() ->
#t_cons{terminator=nil}.
diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl
index 0a4db000ae..76d86d116c 100644
--- a/lib/compiler/src/beam_clean.erl
+++ b/lib/compiler/src/beam_clean.erl
@@ -22,7 +22,6 @@
-module(beam_clean).
-export([module/2]).
--export([clean_labels/1]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -35,7 +34,8 @@ module({Mod,Exp,Attr,Fs0,_}, Opts) ->
Fs1 = remove_unused(Order, Used, All),
{Fs2,Lc} = clean_labels(Fs1),
Fs3 = fix_swap(Fs2, Opts),
- Fs = maybe_remove_lines(Fs3, Opts),
+ Fs4 = fix_bs_create_bin(Fs3, Opts),
+ Fs = maybe_remove_lines(Fs4, Opts),
{ok,{Mod,Exp,Attr,Fs,Lc}}.
%% Determine the rootset, i.e. exported functions and
@@ -98,9 +98,6 @@ add_to_work_list(F, {Fs,Used}=Sets) ->
lc :: non_neg_integer() %Label counter
}).
--spec clean_labels([beam_utils:instruction()]) ->
- {[beam_utils:instruction()],pos_integer()}.
-
clean_labels(Fs0) ->
St0 = #st{lmap=[],entry=1,lc=1},
{Fs1,#st{lmap=Lmap0,lc=Lc}} = function_renumber(Fs0, St0, []),
@@ -182,6 +179,144 @@ remove_lines_block([I|Is]) ->
[I|remove_lines_block(Is)];
remove_lines_block([]) -> [].
+%%%
+%%% If compatibility with a previous release (OTP 24 or earlier) has
+%%% been requested, eliminate bs_create_bin instructions by translating
+%%% them to the old binary syntax instructions.
+%%%
+
+fix_bs_create_bin(Fs, Opts) ->
+ case proplists:get_bool(no_bs_create_bin, Opts) of
+ false -> Fs;
+ true -> fold_functions(fun fix_bs_create_bin/1, Fs)
+ end.
+
+fix_bs_create_bin([{bs_create_bin,Fail,Alloc,Live,Unit,Dst,{list,List}}|Is]) ->
+ Tail = fix_bs_create_bin(Is),
+ Flags = {field_flags,[]},
+ try bs_pre_size_calc(List) of
+ SizeCalc0 ->
+ SizeCalc = fold_size_calc(SizeCalc0, 0, []),
+ TmpDst = SizeReg = {x,Live},
+ SizeIs0 = bs_size_calc(SizeCalc, Fail, SizeReg, {x,Live+1}),
+ SizeIs = [{move,{integer,0},SizeReg}|SizeIs0],
+ RestIs = bs_puts(List, Fail) ++ [{move,TmpDst,Dst}|Tail],
+ case List of
+ [{atom,append},_,_,_,Src|_] ->
+ SizeIs ++ [{bs_append,Fail,SizeReg,Alloc,Live+1,Unit,Src,Flags,TmpDst}|RestIs];
+ [{atom,private_append},_,_,_,Src|_] ->
+ TestHeap = {test_heap,Alloc,Live+1},
+ SizeIs ++ [TestHeap,{bs_private_append,Fail,SizeReg,Unit,Src,Flags,TmpDst}|RestIs];
+ _ ->
+ SizeIs ++ [{bs_init_bits,Fail,SizeReg,Alloc,Live+1,Flags,TmpDst}|RestIs]
+ end
+ catch
+ throw:invalid_size ->
+ [{move,{atom,badarg},{x,0}},
+ {call_ext_only,1,{extfunc,erlang,error,1}}|Tail]
+ end;
+fix_bs_create_bin([I|Is]) ->
+ [I|fix_bs_create_bin(Is)];
+fix_bs_create_bin([]) -> [].
+
+bs_pre_size_calc([Type,_Seg,Unit,_Flags,Src,Size|Segs]) ->
+ case Type of
+ {atom,T} when T =:= append; T =:= private_append ->
+ bs_pre_size_calc(Segs);
+ _ ->
+ [bs_pre_size_calc_1(Type, Unit, Src, Size)|bs_pre_size_calc(Segs)]
+ end;
+bs_pre_size_calc([]) -> [].
+
+bs_pre_size_calc_1({atom,Type}, Unit, Src, Size) ->
+ case {Unit,Size} of
+ {0,{atom,undefined}} ->
+ %% No size/unit given.
+ {8,case Type of
+ utf8 -> {{instr,bs_utf8_size},Src};
+ utf16 -> {{instr,bs_utf16_size},Src};
+ utf32 -> {term,{integer,4}}
+ end};
+ {Unit,_} ->
+ case {Type,Size} of
+ {binary,{atom,all}} ->
+ case Unit rem 8 of
+ 0 -> {8,{{bif,byte_size},Src}};
+ _ -> {1,{{bif,bit_size},Src}}
+ end;
+ {_,_} ->
+ ensure_valid_size(Size),
+ {Unit,{term,Size}}
+ end
+ end.
+
+ensure_valid_size({x,_}) -> ok;
+ensure_valid_size({y,_}) -> ok;
+ensure_valid_size({integer,Size}) when Size >= 0 -> ok;
+ensure_valid_size(_) -> throw(invalid_size).
+
+fold_size_calc([{Unit,{term,{integer,Size}}}|T], Bits, Acc) ->
+ fold_size_calc(T, Bits + Unit*Size, Acc);
+fold_size_calc([{Unit,{{bif,Bif},{literal,Lit}}}=H|T], Bits, Acc) ->
+ try erlang:Bif(Lit) of
+ Result ->
+ fold_size_calc([{Unit,{term,{integer,Result}}}|T], Bits, Acc)
+ catch
+ _:_ ->
+ fold_size_calc(T, Bits, [H|Acc])
+ end;
+fold_size_calc([{U,_}=H|T], Bits, Acc) when U =:= 1; U =:= 8 ->
+ fold_size_calc(T, Bits, [H|Acc]);
+fold_size_calc([{U,Var}|T], Bits, Acc) ->
+ fold_size_calc(T, Bits, [{1,{'*',{term,{integer,U}},Var}}|Acc]);
+fold_size_calc([], Bits, Acc) ->
+ Bytes = Bits div 8,
+ RemBits = Bits rem 8,
+ Sizes = [{1,{term,{integer,RemBits}}},{8,{term,{integer,Bytes}}}|Acc],
+ [Pair || {_,Sz}=Pair <- Sizes, Sz =/= {term,{integer,0}}].
+
+bs_size_calc([{Unit,{{bif,Bif},Reg}}|T], Fail, SizeReg, TmpReg) ->
+ Live = element(2, SizeReg) + 1,
+ [{gc_bif,Bif,Fail,Live,[Reg],TmpReg},
+ {bs_add,Fail,[SizeReg,TmpReg,Unit],SizeReg}|bs_size_calc(T, Fail, SizeReg, TmpReg)];
+bs_size_calc([{Unit,{'*',{term,Term1},{term,Term2}}}|T], Fail, SizeReg, TmpReg) ->
+ Live = element(2, SizeReg) + 1,
+ [{gc_bif,'*',Fail,Live,[Term1,Term2],TmpReg},
+ {bs_add,Fail,[SizeReg,TmpReg,Unit],SizeReg}|bs_size_calc(T, Fail, SizeReg, TmpReg)];
+bs_size_calc([{Unit,{{instr,Instr},Reg}}|T], Fail, SizeReg, TmpReg) ->
+ [{Instr,Fail,Reg,TmpReg},
+ {bs_add,Fail,[SizeReg,TmpReg,Unit],SizeReg}|bs_size_calc(T, Fail, SizeReg, TmpReg)];
+bs_size_calc([{Unit,{term,Term}}|T], Fail, SizeReg, TmpReg) ->
+ [{bs_add,Fail,[SizeReg,Term,Unit],SizeReg}|bs_size_calc(T, Fail, SizeReg, TmpReg)];
+bs_size_calc([], _Fail, _SizeReg, _TmpReg) -> [].
+
+bs_puts([{atom,string},_Seg,_Unit,_Flags,{string,_}=Str,{integer,Size}|Is], Fail) ->
+ [{bs_put_string,Size,Str}|bs_puts(Is, Fail)];
+bs_puts([{atom,append},_,_,_,_,_|Is], Fail) ->
+ bs_puts(Is, Fail);
+bs_puts([{atom,private_append},_,_,_,_,_|Is], Fail) ->
+ bs_puts(Is, Fail);
+bs_puts([{atom,Type},_Seg,Unit,Flags0,Src,Size|Is], Fail) ->
+ Op = case Type of
+ integer -> bs_put_integer;
+ float -> bs_put_float;
+ binary -> bs_put_binary;
+ utf8 -> bs_put_utf8;
+ utf16 -> bs_put_utf16;
+ utf32 -> bs_put_utf32
+ end,
+ Flags = case Flags0 of
+ nil -> [];
+ {literal,Fs} -> Fs
+ end,
+ I = if
+ Unit =:= 0 ->
+ {bs_put,Fail,{Op,{field_flags,Flags}},[Src]};
+ true ->
+ {bs_put,Fail,{Op,Unit,{field_flags,Flags}},[Size,Src]}
+ end,
+ [I|bs_puts(Is, Fail)];
+bs_puts([], _Fail) -> [].
%%%
%%% Helpers.
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index dda7eb310d..36bdb01df5 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -23,10 +23,12 @@
-export([new/0,opcode/2,highest_opcode/1,
atom/2,local/4,export/4,import/4,
- string/2,lambda/3,literal/2,line/2,fname/2,
- atom_table/2,local_table/1,export_table/1,import_table/1,
+ string/2,lambda/3,literal/2,line/2,fname/2,type/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]).
+ line_table/1,type_table/1]).
+
+-include("beam_types.hrl").
-type label() :: beam_asm:label().
@@ -37,28 +39,31 @@
-type fname_tab() :: #{Name :: term() => index()}.
-type line_tab() :: #{{Fname :: index(), Line :: term()} => index()}.
-type literal_tab() :: #{Literal :: term() => index()}.
+-type type_tab() :: #{ Type :: binary() => index()}.
-type lambda_info() :: {label(),{index(),label(),non_neg_integer()}}.
-type lambda_tab() :: {non_neg_integer(),[lambda_info()]}.
-type wrapper() :: #{label() => index()}.
-record(asm,
- {atoms = #{} :: atom_tab(),
- exports = [] :: [{label(), arity(), label()}],
- locals = [] :: [{label(), arity(), label()}],
- imports = gb_trees:empty() :: import_tab(),
- strings = <<>> :: binary(), %String pool
- lambdas = {0,[]} :: lambda_tab(),
+ {atoms = #{} :: atom_tab(),
+ exports = [] :: [{label(), arity(), label()}],
+ locals = [] :: [{label(), arity(), label()}],
+ imports = gb_trees:empty() :: import_tab(),
+ strings = <<>> :: binary(), %String pool
+ lambdas = {0,[]} :: lambda_tab(),
+ types = #{} :: type_tab(),
wrappers = #{} :: wrapper(),
- literals = #{} :: literal_tab(),
- fnames = #{} :: fname_tab(),
- lines = #{} :: line_tab(),
- num_lines = 0 :: non_neg_integer(), %Number of line instructions
- next_import = 0 :: non_neg_integer(),
- string_offset = 0 :: non_neg_integer(),
- next_literal = 0 :: non_neg_integer(),
- highest_opcode = 0 :: non_neg_integer()
- }).
+ literals = #{} :: literal_tab(),
+ fnames = #{} :: fname_tab(),
+ lines = #{} :: line_tab(),
+ num_lines = 0 :: non_neg_integer(), %Number of line instructions
+ next_import = 0 :: non_neg_integer(),
+ string_offset = 0 :: non_neg_integer(),
+ next_literal = 0 :: non_neg_integer(),
+ highest_opcode = 0 :: non_neg_integer()
+ }).
+
-type bdict() :: #asm{}.
%%-----------------------------------------------------------------------------
@@ -225,28 +230,41 @@ fname(Name, #asm{fnames=Fnames}=Dict) ->
{Index,Dict#asm{fnames=Fnames#{Name=>Index}}}
end.
+-spec type(type(), bdict()) -> {non_neg_integer(), bdict()} | none.
+
+type(Type, #asm{types=Types0}=Dict) ->
+ ExtType = beam_types:encode_ext(Type),
+ case Types0 of
+ #{ ExtType := Index } ->
+ {Index, Dict};
+ #{} ->
+ Index = map_size(Types0),
+ Types = Types0#{ ExtType => Index },
+ {Index, Dict#asm{types=Types}}
+ end.
+
%% Returns the atom table.
%% atom_table(Dict, Encoding) -> {LastIndex,[Length,AtomString...]}
--spec atom_table(bdict(), latin1 | utf8) -> {non_neg_integer(), [[non_neg_integer(),...]]}.
+-spec atom_table(bdict()) -> {non_neg_integer(), [[non_neg_integer(),...]]}.
-atom_table(#asm{atoms=Atoms}, Encoding) ->
+atom_table(#asm{atoms=Atoms}) ->
NumAtoms = maps:size(Atoms),
Sorted = lists:keysort(2, maps:to_list(Atoms)),
{NumAtoms,[begin
- L = atom_to_binary(A, Encoding),
+ L = atom_to_binary(A, utf8),
[byte_size(L),L]
end || {A,_} <- Sorted]}.
%% Returns the table of local functions.
%% local_table(Dict) -> {NumLocals, [{Function, Arity, Label}...]}
--spec local_table(bdict()) -> {non_neg_integer(), [{label(),arity(),label()}]}.
+-spec local_table(bdict()) -> {non_neg_integer(), [{index(),arity(),label()}]}.
local_table(#asm{locals = Locals}) ->
{length(Locals),Locals}.
%% Returns the export table.
%% export_table(Dict) -> {NumExports, [{Function, Arity, Label}...]}
--spec export_table(bdict()) -> {non_neg_integer(), [{label(),arity(),label()}]}.
+-spec export_table(bdict()) -> {non_neg_integer(), [{index(),arity(),label()}]}.
export_table(#asm{exports = Exports}) ->
{length(Exports),Exports}.
@@ -267,15 +285,17 @@ string_table(#asm{strings=Strings,string_offset=Size}) ->
-spec lambda_table(bdict()) -> {non_neg_integer(), [<<_:192>>]}.
-lambda_table(#asm{locals=Loc0,lambdas={NumLambdas,Lambdas0}}) ->
+lambda_table(#asm{locals=Loc0,exports=Ext0,lambdas={NumLambdas,Lambdas0}}) ->
Lambdas1 = sofs:relation(Lambdas0),
Loc = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Loc0]),
- Lambdas2 = sofs:relative_product1(Lambdas1, Loc),
+ Ext = sofs:relation([{Lbl,{F,A}} || {F,A,Lbl} <- Ext0]),
+ All = sofs:union(Loc, Ext),
+ Lambdas2 = sofs:relative_product1(Lambdas1, All),
%% 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 = [<<F:32,A:32,Lbl:32,Index:32,NumFree:32,OldUniq:32>> ||
- {{Index,Lbl,NumFree},{F,A}} <- sofs:to_external(Lambdas2)],
+ {{Index,Lbl,NumFree},{F,A}} <- sofs:to_external(Lambdas2)],
{NumLambdas,Lambdas}.
%% Returns the literal table.
@@ -301,6 +321,18 @@ my_term_to_binary(Term) ->
term_to_binary(Term, [{minor_version,2},deterministic]).
+%% Returns the type table.
+-spec type_table(bdict()) -> {non_neg_integer(), binary()}.
+
+type_table(#asm{types=Types}) ->
+ Sorted = lists:keysort(2, maps:to_list(Types)),
+ {map_size(Types), build_type_table(Sorted, <<>>)}.
+
+build_type_table([{ExtType, _} | Sorted], Acc) ->
+ build_type_table(Sorted, <<Acc/binary, ExtType/binary>>);
+build_type_table([], Acc) ->
+ Acc.
+
%% Return the line table.
-spec line_table(bdict()) ->
{non_neg_integer(), %Number of line instructions.
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index ec4a006e33..6b41c15970 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,15 +35,25 @@
-include("beam_opcodes.hrl").
-include("beam_disasm.hrl").
+-include("beam_asm.hrl").
%%-----------------------------------------------------------------------
-type index() :: non_neg_integer().
-type literals() :: 'none' | gb_trees:tree(index(), term()).
+-type types() :: 'none' | gb_trees:tree(index(), term()).
-type symbolic_tag() :: 'a' | 'f' | 'h' | 'i' | 'u' | 'x' | 'y' | 'z'.
-type disasm_tag() :: symbolic_tag() | 'fr' | 'atom' | 'float' | 'literal'.
-type disasm_term() :: 'nil' | {disasm_tag(), _}.
+-type asm_form() :: {module(),
+ [{atom(), arity()}],
+ [beam_lib:attrib_entry()],
+ [#function{}],
+ beam_lib:label()}.
+
+-export_type([asm_form/0]).
+
%%-----------------------------------------------------------------------
-define(NO_DEBUG(Str,Xs), ok).
@@ -182,8 +192,10 @@ process_chunks(F) ->
Lambdas = beam_disasm_lambdas(LambdaBin, Atoms),
LiteralBin = optional_chunk(F, "LitT"),
Literals = beam_disasm_literals(LiteralBin),
+ TypeBin = optional_chunk(F, "Type"),
+ Types = beam_disasm_types(TypeBin),
Code = beam_disasm_code(CodeBin, Atoms, mk_imports(ImportsList),
- StrBin, Lambdas, Literals, Module),
+ StrBin, Lambdas, Literals, Types, Module),
Attributes =
case optional_chunk(F, attributes) of
none -> [];
@@ -247,6 +259,24 @@ disasm_literals(<<Sz:32,Ext:Sz/binary,T/binary>>, Index) ->
disasm_literals(<<>>, _) -> [].
%%-----------------------------------------------------------------------
+%% Disassembles the type table of a BEAM file.
+%%-----------------------------------------------------------------------
+
+-spec beam_disasm_types('none' | binary()) -> literals().
+
+beam_disasm_types(none) ->
+ none;
+beam_disasm_types(<<?BEAM_TYPES_VERSION:32,Count:32,Table/binary>>) ->
+ Res = gb_trees:from_orddict(disasm_types(Table, 0)),
+ Count = gb_trees:size(Res), %Assertion.
+ Res.
+
+disasm_types(<<Type:18/binary,Rest/binary>>, Index) ->
+ [{Index,beam_types:decode_ext(Type)}|disasm_types(Rest, Index+1)];
+disasm_types(<<>>, _) ->
+ [].
+
+%%-----------------------------------------------------------------------
%% Disassembles the code chunk of a BEAM file:
%% - The code is first disassembled into a long list of instructions.
%% - This list is then split into functions and all names are resolved.
@@ -257,9 +287,9 @@ beam_disasm_code(<<_SS:32, % Sub-Size (length of information before code)
_OM:32, % Opcode Max
_L:32,_F:32,
CodeBin/binary>>, Atoms, Imports,
- Str, Lambdas, Literals, M) ->
+ Str, Lambdas, Literals, Types, M) ->
Code = binary_to_list(CodeBin),
- try disasm_code(Code, Atoms, Literals) of
+ try disasm_code(Code, Atoms, Literals, Types) of
DisasmCode ->
Functions = get_function_chunks(DisasmCode),
Labels = mk_labels(local_labels(Functions)),
@@ -275,10 +305,11 @@ beam_disasm_code(<<_SS:32, % Sub-Size (length of information before code)
%%-----------------------------------------------------------------------
-disasm_code([B|Bs], Atoms, Literals) ->
- {Instr,RestBs} = disasm_instr(B, Bs, Atoms, Literals),
- [Instr|disasm_code(RestBs, Atoms, Literals)];
-disasm_code([], _, _) -> [].
+disasm_code([B|Bs], Atoms, Literals, Types) ->
+ {Instr,RestBs} = disasm_instr(B, Bs, Atoms, Literals, Types),
+ [Instr|disasm_code(RestBs, Atoms, Literals, Types)];
+disasm_code([], _, _, _) ->
+ [].
%%-----------------------------------------------------------------------
%% Splits the code stream into chunks representing the code of functions.
@@ -358,29 +389,31 @@ local_labels_2(_, R, _) -> R.
%% in a generic way; indexing instructions are handled separately.
%%-----------------------------------------------------------------------
-disasm_instr(B, Bs, Atoms, Literals) ->
+disasm_instr(B, Bs, Atoms, Literals, Types) ->
{SymOp, Arity} = beam_opcodes:opname(B),
case SymOp of
select_val ->
- disasm_select_inst(select_val, Bs, Atoms, Literals);
+ disasm_select_inst(select_val, Bs, Atoms, Literals, Types);
select_tuple_arity ->
- disasm_select_inst(select_tuple_arity, Bs, Atoms, Literals);
+ disasm_select_inst(select_tuple_arity, Bs, Atoms, Literals, Types);
put_map_assoc ->
- disasm_map_inst(put_map_assoc, Arity, Bs, Atoms, Literals);
+ disasm_map_inst(put_map_assoc, Arity, Bs, Atoms, Literals, Types);
put_map_exact ->
- disasm_map_inst(put_map_exact, Arity, Bs, Atoms, Literals);
+ disasm_map_inst(put_map_exact, Arity, Bs, Atoms, Literals, Types);
get_map_elements ->
- disasm_map_inst(get_map_elements, Arity, Bs, Atoms, Literals);
+ disasm_map_inst(get_map_elements, Arity, Bs, Atoms, Literals, Types);
has_map_fields ->
- disasm_map_inst(has_map_fields, Arity, Bs, Atoms, Literals);
+ disasm_map_inst(has_map_fields, Arity, Bs, Atoms, Literals, Types);
put_tuple2 ->
- disasm_put_tuple2(Bs, Atoms, Literals);
+ disasm_put_tuple2(Bs, Atoms, Literals, Types);
make_fun3 ->
- disasm_make_fun3(Bs, Atoms, Literals);
+ disasm_make_fun3(Bs, Atoms, Literals, Types);
init_yregs ->
- disasm_init_yregs(Bs, Atoms, Literals);
+ disasm_init_yregs(Bs, Atoms, Literals, Types);
+ bs_create_bin ->
+ disasm_bs_create_bin(Bs, Atoms, Literals, Types);
_ ->
- try decode_n_args(Arity, Bs, Atoms, Literals) of
+ try decode_n_args(Arity, Bs, Atoms, Literals, Types) of
{Args, RestBs} ->
?NO_DEBUG("instr ~p~n", [{SymOp, Args}]),
{{SymOp, Args}, RestBs}
@@ -400,49 +433,61 @@ disasm_instr(B, Bs, Atoms, Literals) ->
%% where each case is of the form [symbol,{f,Label}].
%%-----------------------------------------------------------------------
-disasm_select_inst(Inst, Bs, Atoms, Literals) ->
- {X, Bs1} = decode_arg(Bs, Atoms, Literals),
- {F, Bs2} = decode_arg(Bs1, Atoms, Literals),
- {Z, Bs3} = decode_arg(Bs2, Atoms, Literals),
- {U, Bs4} = decode_arg(Bs3, Atoms, Literals),
+disasm_select_inst(Inst, Bs, Atoms, Literals, Types) ->
+ {X, Bs1} = decode_arg(Bs, Atoms, Literals, Types),
+ {F, Bs2} = decode_arg(Bs1, Atoms, Literals, Types),
+ {Z, Bs3} = decode_arg(Bs2, Atoms, Literals, Types),
+ {U, Bs4} = decode_arg(Bs3, Atoms, Literals, Types),
{u, Len} = U,
- {List, RestBs} = decode_n_args(Len, Bs4, Atoms, Literals),
+ {List, RestBs} = decode_n_args(Len, Bs4, Atoms, Literals, Types),
{{Inst, [X,F,{Z,U,List}]}, RestBs}.
-disasm_map_inst(Inst, Arity, Bs0, Atoms, Literals) ->
- {Args0,Bs1} = decode_n_args(Arity, Bs0, Atoms, Literals),
+disasm_map_inst(Inst, Arity, Bs0, Atoms, Literals, Types) ->
+ {Args0,Bs1} = decode_n_args(Arity, Bs0, Atoms, Literals, Types),
%% no droplast ..
[Z|Args1] = lists:reverse(Args0),
Args = lists:reverse(Args1),
- {U, Bs2} = decode_arg(Bs1, Atoms, Literals),
+ {U, Bs2} = decode_arg(Bs1, Atoms, Literals, Types),
{u, Len} = U,
- {List, RestBs} = decode_n_args(Len, Bs2, Atoms, Literals),
+ {List, RestBs} = decode_n_args(Len, Bs2, Atoms, Literals, Types),
{{Inst, Args ++ [{Z,U,List}]}, RestBs}.
-disasm_put_tuple2(Bs, Atoms, Literals) ->
- {X, Bs1} = decode_arg(Bs, Atoms, Literals),
- {Z, Bs2} = decode_arg(Bs1, Atoms, Literals),
- {U, Bs3} = decode_arg(Bs2, Atoms, Literals),
+disasm_put_tuple2(Bs, Atoms, Literals, Types) ->
+ {X, Bs1} = decode_arg(Bs, Atoms, Literals, Types),
+ {Z, Bs2} = decode_arg(Bs1, Atoms, Literals, Types),
+ {U, Bs3} = decode_arg(Bs2, Atoms, Literals, Types),
{u, Len} = U,
- {List, RestBs} = decode_n_args(Len, Bs3, Atoms, Literals),
+ {List, RestBs} = decode_n_args(Len, Bs3, Atoms, Literals, Types),
{{put_tuple2, [X,{Z,U,List}]}, RestBs}.
-disasm_make_fun3(Bs, Atoms, Literals) ->
- {Fun, Bs1} = decode_arg(Bs, Atoms, Literals),
- {Dst, Bs2} = decode_arg(Bs1, Atoms, Literals),
- {Z, Bs3} = decode_arg(Bs2, Atoms, Literals),
- {U, Bs4} = decode_arg(Bs3, Atoms, Literals),
+disasm_make_fun3(Bs, Atoms, Literals, Types) ->
+ {Fun, Bs1} = decode_arg(Bs, Atoms, Literals, Types),
+ {Dst, Bs2} = decode_arg(Bs1, Atoms, Literals, Types),
+ {Z, Bs3} = decode_arg(Bs2, Atoms, Literals, Types),
+ {U, Bs4} = decode_arg(Bs3, Atoms, Literals, Types),
{u, Len} = U,
- {List, RestBs} = decode_n_args(Len, Bs4, Atoms, Literals),
+ {List, RestBs} = decode_n_args(Len, Bs4, Atoms, Literals, Types),
{{make_fun3, [Fun,Dst,{Z,U,List}]}, RestBs}.
-disasm_init_yregs(Bs1, Atoms, Literals) ->
- {Z, Bs2} = decode_arg(Bs1, Atoms, Literals),
- {U, Bs3} = decode_arg(Bs2, Atoms, Literals),
+disasm_init_yregs(Bs1, Atoms, Literals, Types) ->
+ {Z, Bs2} = decode_arg(Bs1, Atoms, Literals, Types),
+ {U, Bs3} = decode_arg(Bs2, Atoms, Literals, Types),
{u, Len} = U,
- {List, RestBs} = decode_n_args(Len, Bs3, Atoms, Literals),
+ {List, RestBs} = decode_n_args(Len, Bs3, Atoms, Literals, Types),
{{init_yregs, [{Z,U,List}]}, RestBs}.
+disasm_bs_create_bin(Bs0, Atoms, Literals, Types) ->
+ {A1, Bs1} = decode_arg(Bs0, Atoms, Literals, Types),
+ {A2, Bs2} = decode_arg(Bs1, Atoms, Literals, Types),
+ {A3, Bs3} = decode_arg(Bs2, Atoms, Literals, Types),
+ {A4, Bs4} = decode_arg(Bs3, Atoms, Literals, Types),
+ {A5, Bs5} = decode_arg(Bs4, Atoms, Literals, Types),
+ {Z, Bs6} = decode_arg(Bs5, Atoms, Literals, Types),
+ {U, Bs7} = decode_arg(Bs6, Atoms, Literals, Types),
+ {u, Len} = U,
+ {List, RestBs} = decode_n_args(Len, Bs7, Atoms, Literals, Types),
+ {{bs_create_bin, [{A1,A2,A3,A4,A5,Z,U,List}]}, RestBs}.
+
%%-----------------------------------------------------------------------
%% decode_arg([Byte]) -> {Arg, [Byte]}
%%
@@ -459,21 +504,22 @@ decode_arg([B|Bs]) ->
?NO_DEBUG('Tag = ~p, B = ~p, Bs = ~p~n', [Tag, B, Bs]),
case Tag of
z ->
- decode_z_tagged(Tag, B, Bs, no_literals);
+ decode_z_tagged(Tag, B, Bs, no_literals, no_types);
_ ->
%% all other cases are handled as if they were integers
decode_int(Tag, B, Bs)
end.
--spec decode_arg([byte(),...], gb_trees:tree(index(), _), literals()) ->
+-spec decode_arg([byte(),...],
+ gb_trees:tree(index(), _), literals(), types()) ->
{disasm_term(), [byte()]}.
-decode_arg([B|Bs0], Atoms, Literals) ->
+decode_arg([B|Bs0], Atoms, Literals, Types) ->
Tag = decode_tag(B band 2#111),
?NO_DEBUG('Tag = ~p, B = ~p, Bs = ~p~n', [Tag, B, Bs0]),
case Tag of
z ->
- decode_z_tagged(Tag, B, Bs0, Literals);
+ decode_z_tagged(Tag, B, Bs0, Literals, Types);
a ->
%% atom or nil
case decode_int(Tag, B, Bs0) of
@@ -548,7 +594,7 @@ decode_negative(N, Len) ->
%% Decodes lists and floating point numbers.
%%-----------------------------------------------------------------------
-decode_z_tagged(Tag,B,Bs,Literals) when (B band 16#08) =:= 0 ->
+decode_z_tagged(Tag,B,Bs,Literals,Types) when (B band 16#08) =:= 0 ->
N = B bsr 4,
case N of
0 -> % float
@@ -567,10 +613,12 @@ decode_z_tagged(Tag,B,Bs,Literals) when (B band 16#08) =:= 0 ->
Literal ->
{{literal,Literal},RestBs}
end;
+ 5 -> % type-tagged register
+ decode_tr(Bs, Types);
_ ->
?exit({decode_z_tagged,{invalid_extended_tag,N}})
end;
-decode_z_tagged(_,B,_,_) ->
+decode_z_tagged(_,B,_,_,_) ->
?exit({decode_z_tagged,{weird_value,B}}).
-spec decode_float([byte(),...]) -> {{'float', float()}, [byte()]}.
@@ -580,6 +628,12 @@ decode_float(Bs) ->
<<Float:64/float>> = list_to_binary(FL),
{{float,Float},RestBs}.
+-spec decode_tr([byte(),...], term()) -> {#tr{}, [byte()]}.
+decode_tr(Bs, Types) ->
+ {Reg, RestBs0} = decode_arg(Bs),
+ {{u, TypeIdx}, RestBs} = decode_arg(RestBs0),
+ {#tr{r=Reg,t=gb_trees:get(TypeIdx, Types)}, RestBs}.
+
-spec decode_fr([byte(),...]) -> {{'fr', non_neg_integer()}, [byte()]}.
decode_fr(Bs) ->
@@ -633,13 +687,13 @@ build_arg([], N) ->
%% Decodes a bunch of arguments and returns them in a list
%%-----------------------------------------------------------------------
-decode_n_args(N, Bs, Atoms, Literals) when N >= 0 ->
- decode_n_args(N, [], Bs, Atoms, Literals).
+decode_n_args(N, Bs, Atoms, Literals, Types) when N >= 0 ->
+ decode_n_args(N, [], Bs, Atoms, Literals, Types).
-decode_n_args(N, Acc, Bs0, Atoms, Literals) when N > 0 ->
- {A1,Bs} = decode_arg(Bs0, Atoms, Literals),
- decode_n_args(N-1, [A1|Acc], Bs, Atoms, Literals);
-decode_n_args(0, Acc, Bs, _, _) ->
+decode_n_args(N, Acc, Bs0, Atoms, Literals, Types) when N > 0 ->
+ {A1,Bs} = decode_arg(Bs0, Atoms, Literals, Types),
+ decode_n_args(N-1, [A1|Acc], Bs, Atoms, Literals, Types);
+decode_n_args(0, Acc, Bs, _, _, _) ->
{lists:reverse(Acc),Bs}.
%%-----------------------------------------------------------------------
@@ -1173,6 +1227,18 @@ resolve_inst({recv_marker_reserve,[Reg]},_,_,_) ->
resolve_inst({recv_marker_use,[Reg]},_,_,_) ->
{recv_marker_use,Reg};
+%%
+%% OTP 25.
+%%
+
+resolve_inst({bs_create_bin,Args},_,_,_) ->
+ {bs_create_bin,Args};
+resolve_inst({call_fun2,[Tag,{u,Arity},Func]},_,_,_) ->
+ {call_fun2,Tag,Arity,Func};
+resolve_inst({nif_start,[]},_,_,_) ->
+ nif_start;
+resolve_inst({badrecord,[Arg]},_,_,_) ->
+ {badrecord,resolve_arg(Arg)};
%%
%% Catches instructions that are not yet handled.
@@ -1185,6 +1251,7 @@ resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
resolve_args(Args) -> [resolve_arg(A) || A <- Args].
+resolve_arg(#tr{r=Reg} = Arg) -> _ = resolve_arg(Reg), Arg;
resolve_arg({x,N} = Arg) when is_integer(N), N >= 0 -> Arg;
resolve_arg({y,N} = Arg) when is_integer(N), N >= 0 -> Arg;
resolve_arg({fr,N} = Arg) when is_integer(N), N >= 0 -> Arg;
diff --git a/lib/compiler/src/beam_flatten.erl b/lib/compiler/src/beam_flatten.erl
index 95eba25bfc..c8298d5e6f 100644
--- a/lib/compiler/src/beam_flatten.erl
+++ b/lib/compiler/src/beam_flatten.erl
@@ -55,8 +55,6 @@ norm({set,[D],[S],fmove}) -> {fmove,S,D};
norm({set,[D],[S],fconv}) -> {fconv,S,D};
norm({set,[D],[S1,S2],put_list}) -> {put_list,S1,S2,D};
norm({set,[D],Els,put_tuple2}) -> {put_tuple2,D,{list,Els}};
-norm({set,[D],[],{put_tuple,A}}) -> {put_tuple,A,D};
-norm({set,[],[S],put}) -> {put,S};
norm({set,[D],[S],{get_tuple_element,I}}) -> {get_tuple_element,S,I,D};
norm({set,[],[S,D],{set_tuple_element,I}}) -> {set_tuple_element,S,D,I};
norm({set,[D],[S],get_hd}) -> {get_hd,S,D};
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index aaf327c6a6..555af00ccc 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -107,7 +107,7 @@
%%% Note: This modules depends on (almost) all branches and jumps only
%%% going forward, so that we can remove instructions (including definition
%%% of labels) after any label that has not been referenced by the code
-%%% preceeding the labels. Regarding the few instructions that have backward
+%%% preceding the labels. Regarding the few instructions that have backward
%%% references to labels, we assume that they only transfer control back
%%% to an instruction that has already been executed. That is, code such as
%%%
@@ -135,7 +135,7 @@
-type instruction() :: beam_utils:instruction().
--include("beam_types.hrl").
+-include("beam_asm.hrl").
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -184,9 +184,10 @@ eliminate_moves([{select,select_val,Reg,{f,Fail},List}=I|Is], D0, Acc) ->
D1 = add_unsafe_label(Fail, D0),
D = update_value_dict(List, Reg, D1),
eliminate_moves(Is, D, [I|Acc]);
-eliminate_moves([{test,is_eq_exact,_,[Reg,Val]}=I,
+eliminate_moves([{test,is_eq_exact,_,[Reg0,Val]}=I,
{block,BlkIs0}|Is], D0, Acc) ->
D = update_unsafe_labels(I, D0),
+ Reg = unpack_typed_reg(Reg0),
RegVal = {Reg,Val},
BlkIs = eliminate_moves_blk(BlkIs0, RegVal),
eliminate_moves([{block,BlkIs}|Is], D, [I|Acc]);
@@ -269,7 +270,8 @@ value_to_literal(F) when is_float(F) -> {float,F};
value_to_literal(I) when is_integer(I) -> {integer,I};
value_to_literal(Other) -> {literal,Other}.
-update_value_dict([Lit,{f,Lbl}|T], Reg, D0) ->
+update_value_dict([Lit,{f,Lbl}|T], Reg0, D0) ->
+ Reg = unpack_typed_reg(Reg0),
D = case D0 of
#{Lbl:=unsafe} -> D0;
#{Lbl:={Reg,Lit}} -> D0;
@@ -279,6 +281,9 @@ update_value_dict([Lit,{f,Lbl}|T], Reg, D0) ->
update_value_dict(T, Reg, D);
update_value_dict([], _, D) -> D.
+unpack_typed_reg(#tr{r=Reg}) -> Reg;
+unpack_typed_reg(Reg) -> Reg.
+
add_unsafe_label(L, D) ->
D#{L=>unsafe}.
@@ -353,7 +358,7 @@ share_1([{label,L}=Lbl|Is], Safe, Dict0, Lbls0, [_|_]=Seq0, Acc) ->
%% Find out whether it is safe to share the sequence.
case (map_size(Safe) =:= 0 orelse
is_shareable(Seq)) andalso
- unambigous_exit_call(Seq)
+ unambigous_deallocation(Seq)
of
true ->
%% Either this function does not contain any try/catch
@@ -402,36 +407,30 @@ share_1([I|Is], Safe, Dict, Lbls, Seq, Acc) ->
share_1(Is, Safe, Dict, Lbls, [I], Acc)
end.
-unambigous_exit_call([{call_ext,A,{extfunc,M,F,A}}|Is]) ->
- case erl_bifs:is_exit_bif(M, F, A) of
- true ->
- %% beam_validator requires that the size of the stack
- %% frame is unambigously known when a function is called.
- %%
- %% That means that we must be careful when sharing function
- %% calls.
- %%
- %% In practice, it seems that only exit BIFs can
- %% potentially be shared in an unsafe way, and only in
- %% rare circumstances. (See the undecided_allocation_1/1
- %% function in beam_jump_SUITE.)
- %%
- %% To ensure that the frame size is unambigous, only allow
- %% sharing of a call to exit BIFs if the call is followed
- %% by an instruction that indicates the size of the stack
- %% frame (that is almost always the case in real-world
- %% code).
- case Is of
- [{deallocate,_}|_] -> true;
- [return] -> true;
- _ -> false
- end;
- false ->
- true
- end;
-unambigous_exit_call([_|Is]) ->
- unambigous_exit_call(Is);
-unambigous_exit_call([]) -> true.
+unambigous_deallocation([{call_ext,_,_}|Is]) ->
+ %% beam_validator requires that the size of the stack frame is
+ %% unambigously known when a function is called.
+ %%
+ %% That means that we must be careful when sharing function calls.
+ %%
+ %% To ensure that the frame size is unambigous, only allow sharing
+ %% of calls if the call is followed by instructions that
+ %% indicates the size of the stack frame.
+ find_deallocation(Is);
+unambigous_deallocation([{call,_,_}|Is]) ->
+ find_deallocation(Is);
+unambigous_deallocation([_|Is]) ->
+ unambigous_deallocation(Is);
+unambigous_deallocation([]) -> true.
+
+find_deallocation([{line,_}|Is]) -> find_deallocation(Is);
+find_deallocation([{call,_,_}|Is]) -> find_deallocation(Is);
+find_deallocation([{call_ext,_,_}|Is]) -> find_deallocation(Is);
+find_deallocation([{init_yregs,_}|Is]) -> find_deallocation(Is);
+find_deallocation([{block,_}|Is]) -> find_deallocation(Is);
+find_deallocation([{deallocate,_}|_]) -> true;
+find_deallocation([return]) -> true;
+find_deallocation(_) -> false.
%% If the label has a scope set, assign it to any line instruction
%% in the sequence.
@@ -466,7 +465,7 @@ is_shareable([]) -> true.
%%
%% Classify labels according to where the instructions that branch to
%% the labels are located. Each label is assigned a set of scope
-%% identifers (but usually just one). If two labels have different
+%% identifiers (but usually just one). If two labels have different
%% scope identfiers, sharing a sequence that raises an exception
%% between the labels may not be safe, because one label is inside a
%% try/catch, and the other label is outside. Note that we don't care
@@ -597,21 +596,9 @@ find_fixpoint(OptFun, Is0) ->
Is -> find_fixpoint(OptFun, Is)
end.
-opt([{test,_,{f,L}=Lbl,_}=I|[{jump,{f,L}}|_]=Is], Acc, St) ->
- %% We have
- %% Test Label Ops
- %% jump Label
- %% The test instruction is not needed if the test is pure
- %% (it modifies neither registers nor bit syntax state).
- case beam_utils:is_pure_test(I) of
- false ->
- %% Test is not pure; we must keep it.
- opt(Is, [I|Acc], label_used(Lbl, St));
- true ->
- %% The test is pure and its failure label is the same
- %% as in the jump that follows -- thus it is not needed.
- opt(Is, Acc, St)
- end;
+opt([{test,is_eq_exact,{f,L},_}|[{jump,{f,L}}|_]=Is], Acc, St) ->
+ %% The is_eq_exact test is not needed.
+ opt(Is, Acc, St);
opt([{test,Test0,{f,L}=Lbl,Ops}=I|[{jump,To}|Is]=Is0], Acc, St) ->
case is_label_defined(Is, L) of
false ->
@@ -629,6 +616,28 @@ opt([{test,_,{f,_}=Lbl,_}=I|Is], Acc, St) ->
opt(Is, [I|Acc], label_used(Lbl, St));
opt([{test,_,{f,_}=Lbl,_,_,_}=I|Is], Acc, St) ->
opt(Is, [I|Acc], label_used(Lbl, St));
+opt([{select,select_val,R,F,Vls0}|Is], Acc, St) ->
+ case prune_redundant_values(Vls0, F) of
+ [] ->
+ %% No values left. Must convert to plain jump.
+ I = {jump,F},
+ opt([I|Is], Acc, St);
+ [{atom,_}=Value,Lbl] ->
+ %% Single value left. Convert to regular test.
+ Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
+ opt(Is1, Acc, St);
+ [{integer,_}=Value,Lbl] ->
+ %% Single value left. Convert to regular test.
+ Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
+ opt(Is1, Acc, St);
+ [{atom,B1},Lbl,{atom,B2},Lbl] when B1 =:= not B2 ->
+ %% Replace with is_boolean test.
+ Is1 = [{test,is_boolean,F,[R]},{jump,Lbl}|Is],
+ opt(Is1, Acc, St);
+ [_|_]=Vls ->
+ I = {select,select_val,R,F,Vls},
+ skip_unreachable(Is, [I|Acc], label_used([F|Vls], St))
+ end;
opt([{select,_,_R,Fail,Vls}=I|Is], Acc, St) ->
skip_unreachable(Is, [I|Acc], label_used([Fail|Vls], St));
opt([{label,From}=I,{label,To}|Is], Acc, #st{replace=Replace}=St) ->
@@ -664,6 +673,12 @@ opt([], Acc, #st{replace=Replace0}) when Replace0 =/= #{} ->
opt([], Acc, #st{replace=Replace}) when Replace =:= #{} ->
reverse(Acc).
+prune_redundant_values([_Val,F|Vls], F) ->
+ prune_redundant_values(Vls, F);
+prune_redundant_values([Val,Lbl|Vls], F) ->
+ [Val,Lbl|prune_redundant_values(Vls, F)];
+prune_redundant_values([], _) -> [].
+
normalize_replace([{From,To0}|Rest], Replace, Acc) ->
case Replace of
#{To0 := To} ->
@@ -687,7 +702,7 @@ collect_labels_1(Is, _Label, _Entry, Acc, St) ->
%% label_defined(Is, Label) -> true | false.
%% Test whether the label Label is defined at the start of the instruction
-%% sequence, possibly preceeded by other label definitions.
+%% sequence, possibly preceded by other label definitions.
%%
is_label_defined([{label,L}|_], L) -> true;
is_label_defined([{label,_}|Is], L) -> is_label_defined(Is, L);
@@ -756,6 +771,7 @@ is_exit_instruction(if_end) -> true;
is_exit_instruction({case_end,_}) -> true;
is_exit_instruction({try_case_end,_}) -> true;
is_exit_instruction({badmatch,_}) -> true;
+is_exit_instruction({badrecord,_}) -> true;
is_exit_instruction(_) -> false.
%% remove_unused_labels(Instructions0) -> Instructions
@@ -800,7 +816,7 @@ drop_upto_label([]) -> [].
%% unshare([Instruction]) -> [Instruction].
%% Replace a jump to a return sequence (a `return` instruction
-%% optionally preced by a `deallocate` instruction) with the return
+%% optionally precede by a `deallocate` instruction) with the return
%% sequence. This always saves execution time and may also save code
%% space (depending on the architecture). Eliminating `jump`
%% instructions also gives beam_trim more opportunities to trim the
@@ -880,6 +896,8 @@ instr_labels({bif,_Name,Lbl,_As,_R}) ->
do_instr_labels(Lbl);
instr_labels({gc_bif,_Name,Lbl,_Live,_As,_R}) ->
do_instr_labels(Lbl);
+instr_labels({bs_create_bin,Lbl,_,_,_,_,_}) ->
+ do_instr_labels(Lbl);
instr_labels({bs_init,Lbl,_,_,_,_}) ->
do_instr_labels(Lbl);
instr_labels({bs_put,Lbl,_,_}) ->
diff --git a/lib/compiler/src/beam_kernel_to_ssa.erl b/lib/compiler/src/beam_kernel_to_ssa.erl
index cc2c901a68..52a68efbb6 100644
--- a/lib/compiler/src/beam_kernel_to_ssa.erl
+++ b/lib/compiler/src/beam_kernel_to_ssa.erl
@@ -25,8 +25,8 @@
-export([module/2]).
-import(lists, [all/2,append/1,flatmap/2,foldl/3,
- keysort/2,mapfoldl/3,map/2,member/2,
- reverse/1,reverse/2,sort/1]).
+ keyfind/3,keysort/2,mapfoldl/3,member/2,
+ reverse/1,sort/1]).
-include("v3_kernel.hrl").
-include("beam_ssa.hrl").
@@ -133,20 +133,31 @@ cg(#k_return{args=[Ret0]}, St) ->
cg(#k_break{args=Bs}, #cg{break=Br}=St) ->
Args = ssa_args(Bs, St),
{[#cg_break{args=Args,phi=Br}],St};
-cg(#k_letrec_goto{label=Label,first=First,then=Then,ret=Rs},
+cg(#k_letrec_goto{label=Label,vars=Vs0,first=First,then=Then,ret=Rs},
#cg{break=OldBreak,labels=Labels0}=St0) ->
{Tf,St1} = new_label(St0),
{B,St2} = new_label(St1),
Labels = Labels0#{Label=>Tf},
- {Fis,St3} = cg(First, St2#cg{labels=Labels,break=B}),
- {Sis,St4} = cg(Then, St3),
- St5 = St4#cg{labels=Labels0},
- {BreakVars,St} = new_ssa_vars(Rs, St5),
- Phi = #cg_phi{vars=BreakVars},
- {Fis ++ [{label,Tf}] ++ Sis ++ [{label,B},Phi],St#cg{break=OldBreak}};
-cg(#k_goto{label=Label}, #cg{labels=Labels}=St) ->
+ {Vs,St3} = new_ssa_vars(Vs0, St2),
+ {Fis,St4} = cg(First, St3#cg{labels=Labels,break=B}),
+ {Sis,St5} = cg(Then, St4),
+ St6 = St5#cg{labels=Labels0},
+ {BreakVars,St} = new_ssa_vars(Rs, St6),
+ PostPhi = #cg_phi{vars=BreakVars},
+ FailPhi = case Vs of
+ [] -> [];
+ [_|_] -> [#cg_phi{vars=Vs}]
+ end,
+ {Fis ++ [{label,Tf}] ++ FailPhi ++ Sis ++ [{label,B},PostPhi],
+ St#cg{break=OldBreak}};
+cg(#k_goto{label=Label,args=[]}, #cg{labels=Labels}=St) ->
Branch = map_get(Label, Labels),
- {[make_uncond_branch(Branch)],St}.
+ {[make_uncond_branch(Branch)],St};
+cg(#k_goto{label=Label,args=As0}, #cg{labels=Labels}=St) ->
+ As = ssa_args(As0, St),
+ Branch = map_get(Label, Labels),
+ Break = #cg_break{args=As,phi=Branch},
+ {[Break],St}.
%% match_cg(Matc, [Ret], State) -> {[Ainstr],State}.
%% Generate code for a match.
@@ -683,43 +694,52 @@ call_cg(Func, As, [#k_var{name=R}|MoreRs]=Rs, Le, St0) ->
end.
enter_cg(Func, As0, Le, St0) ->
+ {no_catch,_} = FailCtx = fail_context(St0), %Assertion.
+
As = ssa_args([Func|As0], St0),
- {Ret,St} = new_ssa_var('@ssa_ret', St0),
+ {Ret,St2} = new_ssa_var('@ssa_ret', St0),
Call = #b_set{anno=line_anno(Le),op=call,dst=Ret,args=As},
- {[Call,#b_ret{arg=Ret}],St}.
+
+ {TestIs,St} = make_succeeded(Ret, FailCtx, St2),
+ {[Call | TestIs] ++ [#b_ret{arg=Ret}],St}.
%% bif_cg(#k_bif{}, Le,State) -> {[Ainstr],State}.
%% Generate code for a guard BIF or primop.
bif_cg(#k_bif{anno=A,op=#k_internal{name=Name},args=As,ret=Rs}, _Le, St) ->
- internal_cg(line_anno(A), Name, As, Rs, St);
+ internal_cg(internal_anno(A), Name, As, Rs, St);
bif_cg(#k_bif{op=#k_remote{mod=#k_literal{val=erlang},name=#k_literal{val=Name}},
args=As,ret=Rs}, Le, St) ->
bif_cg(Name, As, Rs, Le, St).
+internal_anno(Le) ->
+ Anno = line_anno(Le),
+ case keyfind(inlined, 1, Le) of
+ false -> Anno;
+ {inlined, NameArity} -> Anno#{ inlined => NameArity }
+ end.
+
%% internal_cg(Bif, [Arg], [Ret], Le, State) ->
%% {[Ainstr],State}.
+internal_cg(Anno, Op, As, Rs, St0)
+ when Op =:= match_fail; Op =:= raise; Op =:= raw_raise ->
+ {Dst, St1} = case Rs of
+ [#k_var{name=Dst0} | Rest] ->
+ {Var, StV} = new_ssa_var(Dst0, St0),
+ {Var, set_unused_ssa_vars(Rest, StV)};
+ [] ->
+ new_ssa_var('@exception', St0)
+ end,
-internal_cg(_Anno, Op0, As, [#k_var{name=Dst0}], St0)
- when Op0 =:= raise; Op0 =:= raw_raise ->
- Args = ssa_args(As, St0),
- Op = fix_op(Op0, St0),
- {Dst,St} = new_ssa_var(Dst0, St0),
- Set = #b_set{op=Op,dst=Dst,args=Args},
- case fail_context(St) of
- {no_catch,_Fail} ->
- %% No current catch in this function. Follow the raw_raise/resume
- %% instruction by a return (instead of branching to
- %% ?EXCEPTION_MARKER) to ensure that the trim optimization can be
- %% applied. (Allowing control to pass through to the next
- %% instruction would mean that the type for the try/catch construct
- %% would be `any`.)
- Is = [Set,#b_ret{arg=Dst},#cg_unreachable{}],
- {Is,St};
- {in_catch,Fail} ->
- Is = [Set,make_uncond_branch(Fail),#cg_unreachable{}],
- {Is,St}
- end;
+ {Kind, _Fail} = Context = fail_context(St1),
+ true = (Kind =/= guard) orelse (Op =:= match_fail), %Assertion.
+
+ Args = ssa_args(As, St1),
+
+ Set = #b_set{anno=Anno,op=fix_op(Op, St1),dst=Dst,args=Args},
+
+ {TestIs, St} = make_succeeded(Dst, Context, St1),
+ {[Set | TestIs], St};
internal_cg(Anno, recv_peek_message, [], [#k_var{name=Succeeded0},
#k_var{name=Dst0}], St0) ->
{Dst,St1} = new_ssa_var(Dst0, St0),
@@ -1048,167 +1068,54 @@ put_cg_map(LineAnno, Op, SrcMap, Dst, List, St0) ->
%%%
cg_binary(Dst, Segs0, FailCtx, Le, St0) ->
- {PutCode0,SzCalc0,St1} = cg_bin_put(Segs0, FailCtx, St0),
+ Segs1 = cg_bin_segments(Segs0, St0),
+ Segs = case Segs1 of
+ [#b_literal{val=binary},UnitFlags,Val,#b_literal{val=all}|Segs2] ->
+ Op = case member(single_use, Le) of
+ true -> private_append;
+ false -> append
+ end,
+ [#b_literal{val=Op},UnitFlags,Val,#b_literal{val=all}|Segs2];
+ _ ->
+ Segs1
+ end,
LineAnno = line_anno(Le),
- Anno = Le,
- case PutCode0 of
- [#b_set{op=bs_put,dst=Bin,args=[_,_,Src,#b_literal{val=all}|_]},
- #b_set{op={succeeded,_},dst=Bool,args=[Bin]},
- #b_br{bool=Bool},
- {label,_}|_] ->
- #k_bin_seg{unit=Unit0,next=Segs} = Segs0,
- Unit = #b_literal{val=Unit0},
- {PutCode,SzCalc1,St2} = cg_bin_put(Segs, FailCtx, St1),
- {_,SzVar,SzCode0,St3} = cg_size_calc(1, SzCalc1, FailCtx, St2),
- SzCode = cg_bin_anno(SzCode0, LineAnno),
- Args = case member(single_use, Anno) of
- true ->
- [#b_literal{val=private_append},Src,SzVar,Unit];
- false ->
- [#b_literal{val=append},Src,SzVar,Unit]
- end,
- BsInit = #b_set{anno=LineAnno,op=bs_init,dst=Dst,args=Args},
- {TestIs,St} = make_succeeded(Dst, FailCtx, St3),
- {SzCode ++ [BsInit] ++ TestIs ++ PutCode,St};
- [#b_set{op=bs_put}|_] ->
- {Unit,SzVar,SzCode0,St2} = cg_size_calc(8, SzCalc0, FailCtx, St1),
- SzCode = cg_bin_anno(SzCode0, LineAnno),
- Args = [#b_literal{val=new},SzVar,Unit],
- BsInit = #b_set{anno=LineAnno,op=bs_init,dst=Dst,args=Args},
- {TestIs,St} = make_succeeded(Dst, FailCtx, St2),
- {SzCode ++ [BsInit] ++ TestIs ++ PutCode0,St}
- end.
-
-cg_bin_anno([Set|Sets], Anno) ->
- [Set#b_set{anno=Anno}|Sets];
-cg_bin_anno([], _) -> [].
-
-%% cg_size_calc(PreferredUnit, SzCalc, FailCtx, St0) ->
-%% {ActualUnit,SizeVariable,SizeCode,St}.
-%% Generate size calculation code.
-
-cg_size_calc(Unit, error, _FailCtx, St) ->
- {#b_literal{val=Unit},#b_literal{val=badarg},[],St};
-cg_size_calc(8, [{1,_}|_]=SzCalc, FailCtx, St) ->
- cg_size_calc(1, SzCalc, FailCtx, St);
-cg_size_calc(8, SzCalc, FailCtx, St0) ->
- {Var,Pre,St} = cg_size_calc_1(SzCalc, FailCtx, St0),
- {#b_literal{val=8},Var,Pre,St};
-cg_size_calc(1, SzCalc0, FailCtx, St0) ->
- SzCalc = map(fun({8,#b_literal{val=Size}}) ->
- {1,#b_literal{val=8*Size}};
- ({8,{{bif,byte_size},Src}}) ->
- {1,{{bif,bit_size},Src}};
- ({8,{_,_}=UtfCalc}) ->
- {1,{'*',#b_literal{val=8},UtfCalc}};
- ({_,_}=Pair) ->
- Pair
- end, SzCalc0),
- {Var,Pre,St} = cg_size_calc_1(SzCalc, FailCtx, St0),
- {#b_literal{val=1},Var,Pre,St}.
-
-cg_size_calc_1(SzCalc, FailCtx, St0) ->
- cg_size_calc_2(SzCalc, #b_literal{val=0}, FailCtx, St0).
-
-cg_size_calc_2([{_,{'*',Unit,{_,_}=Bif}}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {BifDst,Pre1,St2} = cg_size_bif(Bif, FailCtx, St1),
- {Sum,Pre2,St} = cg_size_add(Sum1, BifDst, Unit, FailCtx, St2),
- {Sum,Pre0++Pre1++Pre2,St};
-cg_size_calc_2([{_,#b_literal{}=Sz}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {Sum,Pre,St} = cg_size_add(Sum1, Sz, #b_literal{val=1}, FailCtx, St1),
- {Sum,Pre0++Pre,St};
-cg_size_calc_2([{_,#b_var{}=Sz}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {Sum,Pre,St} = cg_size_add(Sum1, Sz, #b_literal{val=1}, FailCtx, St1),
- {Sum,Pre0++Pre,St};
-cg_size_calc_2([{_,{_,_}=Bif}|T], Sum0, FailCtx, St0) ->
- {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, FailCtx, St0),
- {BifDst,Pre1,St2} = cg_size_bif(Bif, FailCtx, St1),
- {Sum,Pre2,St} = cg_size_add(Sum1, BifDst, #b_literal{val=1}, FailCtx, St2),
- {Sum,Pre0++Pre1++Pre2,St};
-cg_size_calc_2([], Sum, _FailCtx, St) ->
- {Sum,[],St}.
-
-cg_size_bif(#b_var{}=Var, _FailCtx, St) ->
- {Var,[],St};
-cg_size_bif({Name,Src}, FailCtx, St0) ->
- {Dst,St1} = new_ssa_var('@ssa_bif', St0),
- Bif = #b_set{op=Name,dst=Dst,args=[Src]},
- {TestIs,St} = make_succeeded(Dst, FailCtx, St1),
- {Dst,[Bif|TestIs],St}.
-
-cg_size_add(#b_literal{val=0}, Val, #b_literal{val=1}, _FailCtx, St) ->
- {Val,[],St};
-cg_size_add(#b_literal{val=A}, #b_literal{val=B}, #b_literal{val=U}, _FailCtx, St) ->
- {#b_literal{val=A+B*U},[],St};
-cg_size_add(A, B, Unit, FailCtx, St0) ->
- {Dst,St1} = new_ssa_var('@ssa_sum', St0),
- {TestIs,St} = make_succeeded(Dst, FailCtx, St1),
- BsAdd = #b_set{op=bs_add,dst=Dst,args=[A,B,Unit]},
- {Dst,[BsAdd|TestIs],St}.
-
-cg_bin_put(Seg, FailCtx, St) ->
- cg_bin_put_1(Seg, FailCtx, [], [], St).
-
-cg_bin_put_1(#k_bin_seg{size=Size0,unit=U,type=T,flags=Fs,seg=Src0,next=Next},
- FailCtx, Acc, SzCalcAcc, St0) ->
- [Src,Size] = ssa_args([Src0,Size0], St0),
- NeedSize = bs_need_size(T),
- TypeArg = #b_literal{val=T},
- Flags = #b_literal{val=Fs},
- Unit = #b_literal{val=U},
- Args = case NeedSize of
- true -> [TypeArg,Flags,Src,Size,Unit];
- false -> [TypeArg,Flags,Src]
+ Build = #b_set{anno=LineAnno,op=bs_create_bin,args=Segs,dst=Dst},
+ {TestIs,St} = make_succeeded(Dst, FailCtx, St0),
+ {[Build|TestIs],St}.
+
+cg_bin_segments(#k_bin_seg{anno=Anno,type=Type,flags=Flags0,seg=Src0,size=Size0,unit=U,next=Next}, St) ->
+ Seg = case lists:keyfind(segment, 1,Anno) of
+ false -> [];
+ {segment,_}=Seg0 -> [Seg0]
+ end,
+ [Src,Size] = ssa_args([Src0,Size0], St),
+ TypeArg = #b_literal{val=Type},
+ Unit = case U of
+ undefined -> 0;
+ _ -> U
end,
- {Dst,St1} = new_ssa_var('@ssa_bs_put', St0),
- {TestIs,St} = make_succeeded(Dst, FailCtx, St1),
- Is = [#b_set{op=bs_put,dst=Dst,args=Args}|TestIs],
- SzCalc = bin_size_calc(T, Src, Size, U),
- cg_bin_put_1(Next, FailCtx, reverse(Is, Acc), [SzCalc|SzCalcAcc], St);
-cg_bin_put_1(#k_bin_end{}, _, Acc, SzCalcAcc, St) ->
- SzCalc = fold_size_calc(SzCalcAcc, 0, []),
- {reverse(Acc),SzCalc,St}.
+ Flags = strip_bs_construct_flags(Flags0),
+ UnitFlags = #b_literal{val=[Unit|Flags++Seg]},
+ [TypeArg,UnitFlags,Src,Size|cg_bin_segments(Next, St)];
+cg_bin_segments(#k_bin_end{}, _St) -> [].
bs_need_size(utf8) -> false;
bs_need_size(utf16) -> false;
bs_need_size(utf32) -> false;
bs_need_size(_) -> true.
-bin_size_calc(utf8, Src, _Size, _Unit) ->
- {8,{bs_utf8_size,Src}};
-bin_size_calc(utf16, Src, _Size, _Unit) ->
- {8,{bs_utf16_size,Src}};
-bin_size_calc(utf32, _Src, _Size, _Unit) ->
- {8,#b_literal{val=4}};
-bin_size_calc(binary, Src, #b_literal{val=all}, Unit) ->
- case Unit rem 8 of
- 0 -> {8,{{bif,byte_size},Src}};
- _ -> {1,{{bif,bit_size},Src}}
- end;
-bin_size_calc(_Type, _Src, Size, Unit) ->
- {Unit,Size}.
-
-fold_size_calc([{Unit,#b_literal{val=Size}}|T], Bits, Acc) ->
- if
- is_integer(Size) ->
- fold_size_calc(T, Bits + Unit*Size, Acc);
- true ->
- error
- end;
-fold_size_calc([{U,#b_var{}}=H|T], Bits, Acc) when U =:= 1; U =:= 8 ->
- fold_size_calc(T, Bits, [H|Acc]);
-fold_size_calc([{U,#b_var{}=Var}|T], Bits, Acc) ->
- fold_size_calc(T, Bits, [{1,{'*',#b_literal{val=U},Var}}|Acc]);
-fold_size_calc([{_,_}=H|T], Bits, Acc) ->
- fold_size_calc(T, Bits, [H|Acc]);
-fold_size_calc([], Bits, Acc) ->
- Bytes = Bits div 8,
- RemBits = Bits rem 8,
- Sizes = sort([{1,#b_literal{val=RemBits}},{8,#b_literal{val=Bytes}}|Acc]),
- [Pair || {_,Sz}=Pair <- Sizes, Sz =/= #b_literal{val=0}].
+%% Only keep the flags that have a meaning for binary construction and
+%% are distinct from the default value.
+strip_bs_construct_flags(Flags) ->
+ [Flag || Flag <- Flags,
+ case Flag of
+ little -> true;
+ native -> true;
+ big -> false;
+ signed -> false;
+ unsigned -> false
+ end].
%%%
%%% Utilities for creating the SSA types.
diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl
index 6121593b11..ac21f1a1ab 100644
--- a/lib/compiler/src/beam_listing.erl
+++ b/lib/compiler/src/beam_listing.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
-include("beam_ssa.hrl").
-include("beam_disasm.hrl").
--import(lists, [foreach/2]).
+-import(lists, [foldl/3, foreach/2]).
-type code() :: cerl:c_module()
| beam_utils:module_code()
@@ -55,18 +55,29 @@ module(Stream, {Mod,Exp,Attr,Code,NumLabels}) ->
io:format(Stream, "\n{exports, ~p}.\n", [Exp]),
io:format(Stream, "\n{attributes, ~p}.\n", [Attr]),
io:format(Stream, "\n{labels, ~p}.\n", [NumLabels]),
+ Lbl2Fun = foldl(fun({function,Name,Arity,Entry,_}, Map) ->
+ Map#{ Entry => {Name,Arity} }
+ end, #{}, Code),
foreach(
fun ({function,Name,Arity,Entry,Asm}) ->
io:format(Stream, "\n\n{function, ~w, ~w, ~w}.\n",
[Name, Arity, Entry]),
- io:put_chars(Stream, format_asm(Asm))
+ io:put_chars(Stream, format_asm(Asm, Lbl2Fun))
end, Code);
module(Stream, [_|_]=Fs) ->
%% Form-based abstract format.
foreach(fun (F) -> io:format(Stream, "~p.\n", [F]) end, Fs).
-format_asm([{label,L}|Is]) ->
- [io_lib:format(" {label,~p}.\n", [L])|format_asm(Is)];
-format_asm([I|Is]) ->
- [io_lib:format(" ~p", [I]),".\n"|format_asm(Is)];
-format_asm([]) -> [].
+format_asm([{label,L}|Is], Lbl2Fun) ->
+ [io_lib:format(" {label,~p}.\n", [L])|format_asm(Is, Lbl2Fun)];
+format_asm([I={Call,_,L}|Is], Lbl2Fun) when Call =:= call; Call =:= call_only ->
+ format_asm_call(L, I, Is, Lbl2Fun);
+format_asm([I={call_last,_,L,_}|Is], Lbl2Fun) ->
+ format_asm_call(L, I, Is, Lbl2Fun);
+format_asm([I|Is], Lbl2Fun) ->
+ [io_lib:format(" ~p", [I]),".\n"|format_asm(Is, Lbl2Fun)];
+format_asm([], _) -> [].
+
+format_asm_call({f,L}, I, Is, Lbl2Fun) ->
+ {N,A} = map_get(L, Lbl2Fun),
+ [io_lib:format(" ~p. % ~p/~p\n", [I, N, A])|format_asm(Is, Lbl2Fun)].
diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl
deleted file mode 100644
index da59aea2bd..0000000000
--- a/lib/compiler/src/beam_peep.erl
+++ /dev/null
@@ -1,223 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(beam_peep).
-
--export([module/2]).
-
--import(lists, [reverse/1,member/2,usort/1]).
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,_}, _Opts) ->
- %% First coalesce adjacent labels.
- {Fs1,Lc} = beam_clean:clean_labels(Fs0),
-
- %% Do the peep hole optimizations.
- Fs = [function(F) || F <- Fs1],
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}) ->
- try
- Is1 = peep(Is0),
- Is = beam_jump:remove_unused_labels(Is1),
- {function,Name,Arity,CLabel,Is}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-
-%% Peep-hole optimizations suitable to perform when most of the
-%% optimations passes have been run.
-%%
-%% (1) In a sequence of tests, we can remove any test instruction
-%% that has been previously seen, because it will certainly
-%% succeed.
-%%
-%% For instance, in the following code sequence
-%%
-%% is_eq_exact _Fail SomeRegister SomeLiteral
-%% is_ne_exact _Fail SomeOtherRegister SomeOtherLiteral
-%% is_eq_exact _Fail SomeRegister SomeLiteral
-%% is_ne_exact _Fail SomeOtherRegister StillSomeOtherLiteral
-%%
-%% the third test is redundant. The code sequence will be produced
-%% by a combination of semicolon and command guards, such as
-%%
-%% InEncoding =:= latin1, OutEncoding =:= unicode;
-%% InEncoding =:= latin1, OutEncoding =:= utf8 ->
-%%
-
-peep(Is) ->
- peep(Is, gb_sets:empty(), []).
-
-peep([{bif,tuple_size,_,[_]=Ops,Dst}=I|Is], SeenTests0, Acc) ->
- %% Pretend that we have seen {test,is_tuple,_,Ops}.
- SeenTests1 = gb_sets:add({is_tuple,Ops}, SeenTests0),
- %% Kill all remembered tests that depend on the destination register.
- SeenTests = kill_seen(Dst, SeenTests1),
- peep(Is, SeenTests, [I|Acc]);
-peep([{bif,map_get,_,[Key,Map],Dst}=I|Is], SeenTests0, Acc) ->
- %% Pretend that we have seen {test,has_map_fields,_,[Map,Key]}
- SeenTests1 = gb_sets:add({has_map_fields,[Map,Key]}, SeenTests0),
- %% Kill all remembered tests that depend on the destination register.
- SeenTests = kill_seen(Dst, SeenTests1),
- peep(Is, SeenTests, [I|Acc]);
-peep([{bif,_,_,_,Dst}=I|Is], SeenTests0, Acc) ->
- %% Kill all remembered tests that depend on the destination register.
- SeenTests = kill_seen(Dst, SeenTests0),
- peep(Is, SeenTests, [I|Acc]);
-peep([{gc_bif,_,_,_,_,Dst}=I|Is], SeenTests0, Acc) ->
- %% Kill all remembered tests that depend on the destination register.
- SeenTests = kill_seen(Dst, SeenTests0),
- peep(Is, SeenTests, [I|Acc]);
-peep([{jump,{f,L}},{label,L}=I|Is], _, Acc) ->
- %% Sometimes beam_jump has missed this optimization.
- peep(Is, gb_sets:empty(), [I|Acc]);
-peep([{select,select_val,R,F,Vls0}|Is], SeenTests0, Acc0) ->
- case prune_redundant_values(Vls0, F) of
- [] ->
- %% No values left. Must convert to plain jump.
- I = {jump,F},
- peep([I|Is], gb_sets:empty(), Acc0);
- [{atom,_}=Value,Lbl] ->
- %% Single value left. Convert to regular test.
- Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
- peep(Is1, SeenTests0, Acc0);
- [{integer,_}=Value,Lbl] ->
- %% Single value left. Convert to regular test.
- Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
- peep(Is1, SeenTests0, Acc0);
- [{atom,B1},Lbl,{atom,B2},Lbl] when B1 =:= not B2 ->
- %% Replace with is_boolean test.
- Is1 = [{test,is_boolean,F,[R]},{jump,Lbl}|Is],
- peep(Is1, SeenTests0, Acc0);
- [_|_]=Vls ->
- I = {select,select_val,R,F,Vls},
- peep(Is, gb_sets:empty(), [I|Acc0])
- end;
-peep([{get_map_elements,Fail,Src,List}=I|Is], _SeenTests, Acc0) ->
- SeenTests = gb_sets:empty(),
- case simplify_get_map_elements(Fail, Src, List, Acc0) of
- {ok,Acc} ->
- peep(Is, SeenTests, Acc);
- error ->
- peep(Is, SeenTests, [I|Acc0])
- end;
-peep([{test,has_map_fields,Fail,Ops}=I|Is], SeenTests, Acc0) ->
- case simplify_has_map_fields(Fail, Ops, Acc0) of
- {ok,Acc} ->
- peep(Is, SeenTests, Acc);
- error ->
- peep(Is, SeenTests, [I|Acc0])
- end;
-peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) ->
- case beam_utils:is_pure_test(I) of
- false ->
- %% Bit syntax matching, which may modify registers and/or
- %% match state. Clear all information about tests that
- %% has succeeded.
- peep(Is, gb_sets:empty(), [I|Acc]);
- true ->
- case is_test_redundant(Op, Ops, SeenTests0) of
- true ->
- %% This test or a similar test has already succeeded and
- %% is therefore redundant.
- peep(Is, SeenTests0, Acc);
- false ->
- %% Remember that we have seen this test.
- Test = {Op,Ops},
- SeenTests = gb_sets:insert(Test, SeenTests0),
- peep(Is, SeenTests, [I|Acc])
- end
- end;
-peep([I|Is], _, Acc) ->
- %% An unknown instruction. Throw away all information we
- %% have collected about test instructions.
- peep(Is, gb_sets:empty(), [I|Acc]);
-peep([], _, Acc) -> reverse(Acc).
-
-is_test_redundant(Op, Ops, Seen) ->
- gb_sets:is_element({Op,Ops}, Seen) orelse
- is_test_redundant_1(Op, Ops, Seen).
-
-is_test_redundant_1(is_boolean, [R], Seen) ->
- gb_sets:is_element({is_eq_exact,[R,{atom,false}]}, Seen) orelse
- gb_sets:is_element({is_eq_exact,[R,{atom,true}]}, Seen);
-is_test_redundant_1(_, _, _) -> false.
-
-kill_seen(Dst, Seen0) ->
- gb_sets:from_ordset(kill_seen_1(gb_sets:to_list(Seen0), Dst)).
-
-kill_seen_1([{_,Ops}=Test|T], Dst) ->
- case member(Dst, Ops) of
- true -> kill_seen_1(T, Dst);
- false -> [Test|kill_seen_1(T, Dst)]
- end;
-kill_seen_1([], _) -> [].
-
-prune_redundant_values([_Val,F|Vls], F) ->
- prune_redundant_values(Vls, F);
-prune_redundant_values([Val,Lbl|Vls], F) ->
- [Val,Lbl|prune_redundant_values(Vls, F)];
-prune_redundant_values([], _) -> [].
-
-simplify_get_map_elements(Fail, Src, {list,[Key,Dst]},
- [{get_map_elements,Fail,Src,{list,List1}}|Acc]) ->
- case are_keys_literals([Key]) andalso are_keys_literals(List1) andalso
- not is_source_overwritten(Src, List1) of
- true ->
- case member(Key, List1) of
- true ->
- %% The key is already in the other list. That is
- %% very unusual, because there are optimizations to get
- %% rid of duplicate keys. Therefore, don't try to
- %% do anything smart here; just keep the
- %% get_map_elements instructions separate.
- error;
- false ->
- List = [Key,Dst|List1],
- {ok,[{get_map_elements,Fail,Src,{list,List}}|Acc]}
- end;
- false ->
- error
- end;
-simplify_get_map_elements(_, _, _, _) -> error.
-
-simplify_has_map_fields(Fail, [Src|Keys0],
- [{test,has_map_fields,Fail,[Src|Keys1]}|Acc]) ->
- case are_keys_literals(Keys0) andalso are_keys_literals(Keys1) of
- true ->
- Keys = usort(Keys0 ++ Keys1),
- {ok,[{test,has_map_fields,Fail,[Src|Keys]}|Acc]};
- false ->
- error
- end;
-simplify_has_map_fields(_, _, _) -> error.
-
-are_keys_literals([{x,_}|_]) -> false;
-are_keys_literals([{y,_}|_]) -> false;
-are_keys_literals([_|_]) -> true.
-
-is_source_overwritten(Src, [_Key,Src]) -> true;
-is_source_overwritten(_, _) -> false.
diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl
index f3fe0c8c9e..5037811614 100644
--- a/lib/compiler/src/beam_ssa.erl
+++ b/lib/compiler/src/beam_ssa.erl
@@ -105,10 +105,9 @@
%% To avoid the collapsing, change the value of SET_LIMIT to 50 in the
%% file erl_types.erl in the dialyzer application.
--type prim_op() :: 'bs_add' | 'bs_extract' | 'bs_get_tail' |
- 'bs_init' | 'bs_init_writable' |
- 'bs_match' | 'bs_put' | 'bs_start_match' | 'bs_test_tail' |
- 'bs_utf16_size' | 'bs_utf8_size' | 'build_stacktrace' |
+-type prim_op() :: 'bs_extract' | 'bs_get_tail' | 'bs_init_writable' |
+ 'bs_match' | 'bs_start_match' | 'bs_test_tail' |
+ 'build_stacktrace' |
'call' | 'catch_end' |
'extract' |
'get_hd' | 'get_map_element' | 'get_tl' | 'get_tuple_element' |
@@ -116,7 +115,7 @@
'is_nonempty_list' | 'is_tagged_tuple' |
'kill_try_tag' |
'landingpad' |
- 'make_fun' | 'new_try_tag' | 'old_make_fun' |
+ 'make_fun' | 'match_fail' | 'new_try_tag' | 'old_make_fun' |
'peek_message' | 'phi' | 'put_list' | 'put_map' | 'put_tuple' |
'raw_raise' | 'recv_next' | 'remove_message' | 'resume' |
'wait_timeout'.
@@ -133,9 +132,10 @@
-import(lists, [foldl/3,mapfoldl/3,member/2,reverse/1,sort/1]).
--spec add_anno(Key, Value, Construct) -> Construct when
+-spec add_anno(Key, Value, Construct0) -> Construct when
Key :: atom(),
Value :: any(),
+ Construct0 :: construct(),
Construct :: construct().
add_anno(Key, Val, #b_function{anno=Anno}=Bl) ->
@@ -156,7 +156,7 @@ add_anno(Key, Val, #b_switch{anno=Anno}=Bl) ->
get_anno(Key, Construct) ->
map_get(Key, get_anno(Construct)).
--spec get_anno(atom(), construct(),any()) -> any().
+-spec get_anno(atom(), construct(), any()) -> any().
get_anno(Key, Construct, Default) ->
maps:get(Key, get_anno(Construct), Default).
@@ -197,17 +197,13 @@ no_side_effect(#b_set{op=Op}) ->
case Op of
{bif,_} -> true;
{float,get} -> true;
- bs_add -> true;
- bs_init -> true;
+ bs_create_bin -> true;
bs_init_writable -> true;
bs_extract -> true;
bs_match -> true;
bs_start_match -> true;
bs_test_tail -> true;
bs_get_tail -> true;
- bs_put -> true;
- bs_utf16_size -> true;
- bs_utf8_size -> true;
build_stacktrace -> true;
extract -> true;
get_hd -> true;
@@ -218,10 +214,12 @@ no_side_effect(#b_set{op=Op}) ->
is_nonempty_list -> true;
is_tagged_tuple -> true;
make_fun -> true;
+ match_fail -> true;
phi -> true;
put_map -> true;
put_list -> true;
put_tuple -> true;
+ raw_raise -> true;
{succeeded,guard} -> true;
_ -> false
end.
@@ -372,7 +370,7 @@ successors(#b_blk{last=Terminator}) ->
%% switch list to a #b_br{}.
-spec normalize(b_set() | terminator()) ->
- b_set() | terminator().
+ b_set() | terminator().
normalize(#b_set{op={bif,Bif},args=Args}=Set) ->
case {is_commutative(Bif),Args} of
@@ -490,7 +488,7 @@ common_dominators(Ls, Dom, Numbering) ->
dom_intersection(Doms, Numbering).
-spec fold_instrs(Fun, Labels, Acc0, Blocks) -> any() when
- Fun :: fun((b_blk()|terminator(), any()) -> any()),
+ Fun :: fun((b_set()|terminator(), any()) -> any()),
Labels :: [label()],
Acc0 :: any(),
Blocks :: block_map().
@@ -520,7 +518,7 @@ mapfold_blocks_1(Fun, Lbl, {Blocks0, Acc0}) ->
{Blocks, Acc}.
-spec mapfold_instrs(Fun, Labels, Acc0, Blocks0) -> {Blocks,Acc} when
- Fun :: fun((b_blk()|terminator(), any()) -> any()),
+ Fun :: fun((b_set()|terminator(), any()) -> any()),
Labels :: [label()],
Acc0 :: any(),
Acc :: any(),
@@ -531,7 +529,7 @@ mapfold_instrs(Fun, Labels, Acc0, Blocks) ->
mapfold_instrs_1(Labels, Fun, Blocks, Acc0).
-spec flatmapfold_instrs(Fun, Labels, Acc0, Blocks0) -> {Blocks,Acc} when
- Fun :: fun((b_blk()|terminator(), any()) -> any()),
+ Fun :: fun((b_set()|terminator(), any()) -> any()),
Labels :: [label()],
Acc0 :: any(),
Acc :: any(),
@@ -607,7 +605,7 @@ between(From, To, Preds, Blocks) ->
%% skipping the blocks that don't precede `To`.
%%
%% As an optimization we initialize the predecessor set with `From` to stop
- %% gathering once seen since we're only interested in the blocks inbetween.
+ %% gathering once seen since we're only interested in the blocks in between.
%% Uninteresting blocks can still be added if `From` doesn't dominate `To`,
%% but that has no effect on the final result.
Filter = between_make_filter([To], Preds, sets:from_list([From], [{version, 2}])),
@@ -637,8 +635,8 @@ rename_vars(Rename, Labels, Blocks) when is_map(Rename)->
end,
map_instrs_1(Labels, F, Blocks).
-%% split_blocks(Predicate, Blocks0, Count0) -> {Blocks,Count}.
-%% Call Predicate(Instruction) for each instruction in all
+%% split_blocks(Labels, Predicate, Blocks0, Count0) -> {Blocks,Count}.
+%% Call Predicate(Instruction) for each instruction in the given
%% blocks. If Predicate/1 returns true, split the block
%% before this instruction.
diff --git a/lib/compiler/src/beam_ssa_bc_size.erl b/lib/compiler/src/beam_ssa_bc_size.erl
index 11c1adc190..c48a7c8cf6 100644
--- a/lib/compiler/src/beam_ssa_bc_size.erl
+++ b/lib/compiler/src/beam_ssa_bc_size.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -276,32 +276,13 @@ calc_size_is([I|Is], Bs0) ->
calc_size_is(Is, Bs);
calc_size_is([], Bs) -> Bs.
-calc_size_instr(#b_set{op=bs_add,args=[A,B,U],dst=Dst}, Bs) ->
- %% We must make sure that the value of bs_add only depends on literals
- %% and arguments passed from the function that created the writable
- %% binary.
- case {get_value(A, Bs),get_arg_value(B, Bs)} of
- {#b_literal{}=Lit,Val} ->
- Bs#{Dst => {expr,{{bif,'+'},[Lit,{{bif,'*'},[Val,U]}]}}};
- {{expr,Expr},Val} ->
- Bs#{Dst => {expr,{{bif,'+'},[Expr,{{bif,'*'},[Val,U]}]}}};
- {_,_} ->
- %% The value depends on a variable of which we know nothing.
- Bs#{Dst => any}
- end;
-calc_size_instr(#b_set{op=bs_init,args=[#b_literal{val=private_append},
- Writable,Size,Unit],
+calc_size_instr(#b_set{op=bs_create_bin,
+ args=[#b_literal{val=private_append},_,Writable,_|Args],
dst=Dst}, Bs) ->
- case get_value(Size, Bs) of
- {arg,SizeOrigin} ->
- Expr = {{bif,'*'},[SizeOrigin,Unit]},
- update_writable(Dst, Writable, Expr, Bs);
- #b_literal{} ->
- Expr = {{bif,'*'},[Size,Unit]},
- update_writable(Dst, Writable, Expr, Bs);
+ case calc_create_bin_size(Args, Bs) of
{expr,Expr} ->
update_writable(Dst, Writable, Expr, Bs);
- _ ->
+ any ->
Bs#{Dst => any}
end;
calc_size_instr(#b_set{op=bs_match,args=[_Type,Ctx,_Flags,
@@ -347,6 +328,26 @@ calc_size_instr(#b_set{op={succeeded,_},args=[Arg],dst=Dst}, Bs) ->
calc_size_instr(#b_set{dst=Dst}, Bs) ->
Bs#{Dst => any}.
+calc_create_bin_size(Args, Bs) ->
+ calc_create_bin_size(Args, Bs, #b_literal{val=0}).
+
+calc_create_bin_size([_,#b_literal{val=[0|_]},_,_|_], _Bs, _Acc) ->
+ %% Construction without size (utf8/utf16/utf32).
+ any;
+calc_create_bin_size([_,#b_literal{val=[U|_]},_,Size|T], Bs, Acc0) when is_integer(U) ->
+ case get_value(Size, Bs) of
+ #b_literal{val=Val} when is_integer(Val) ->
+ Acc = {{bif,'+'},[Acc0,#b_literal{val=U*Val}]},
+ calc_create_bin_size(T, Bs, Acc);
+ {arg,Var} ->
+ Acc = {{bif,'+'},[Acc0,{{bif,'*'},[Var,#b_literal{val=U}]}]},
+ calc_create_bin_size(T, Bs, Acc);
+ _ ->
+ any
+ end;
+calc_create_bin_size([], _Bs, Acc) ->
+ {expr,Acc}.
+
update_writable(Dst, Writable, Expr, Bs) ->
case get_value(Writable, Bs) of
{writable,#b_literal{val=0}} ->
@@ -585,7 +586,8 @@ cg_bad_generator([Arg|_], Annos, CallLast, FailBlk, Count) ->
cg_bad_generator_1(Anno, Arg, CallLast, FailBlk, Count0) ->
{L,Count1} = new_block(Count0),
{TupleDst,Count2} = new_var('@ssa_tuple', Count1),
- {Ret,Count3} = new_var('@ssa_ret', Count2),
+ {SuccDst,Count3} = new_var('@ssa_bool', Count2),
+ {Ret,Count4} = new_var('@ssa_ret', Count3),
MFA = #b_remote{mod=#b_literal{val=erlang},
name=#b_literal{val=error},
arity=1},
@@ -593,21 +595,18 @@ cg_bad_generator_1(Anno, Arg, CallLast, FailBlk, Count0) ->
args=[#b_literal{val=bad_generator},Arg],
dst=TupleDst},
CallI = #b_set{anno=Anno,op=call,args=[MFA,TupleDst],dst=Ret},
- Is = [TupleI,CallI],
-
- %% When the generator is called within try/catch, the `bad_generator` call
- %% must refer to the same landing pad or else we'll break optimizations
- %% that assume exceptions are always reflected in the control flow.
- Last = case CallLast of
- #b_br{fail=CatchLbl} when CatchLbl =/= ?EXCEPTION_BLOCK ->
- #b_br{bool=#b_literal{val=true},
- succ=CatchLbl,fail=CatchLbl};
- _ ->
- #b_ret{arg=Ret}
- end,
+ SuccI = #b_set{op={succeeded,body},args=[Ret],dst=SuccDst},
+ Is = [TupleI,CallI,SuccI],
+
+ %% The `bad_generator` call must refer to the same fail label (either a
+ %% landing pad or ?EXCEPTION_BLOCK) as the caller, or else we'll break
+ %% optimizations that assume exceptions are always reflected in the control
+ %% flow.
+ #b_br{fail=FailLbl} = CallLast, %Assertion.
+ Last = #b_br{bool=SuccDst,succ=FailLbl,fail=FailLbl},
Blk = #b_blk{is=Is,last=Last},
- {L,[{L,Blk}|FailBlk],Count3}.
+ {L,[{L,Blk}|FailBlk],Count4}.
cg_succeeded(#b_set{dst=OpDst}=I, Succ, Fail, Count0) ->
{Bool,Count} = new_var('@ssa_bool', Count0),
diff --git a/lib/compiler/src/beam_ssa_bool.erl b/lib/compiler/src/beam_ssa_bool.erl
index 7ad38dc3ca..fb72a78c29 100644
--- a/lib/compiler/src/beam_ssa_bool.erl
+++ b/lib/compiler/src/beam_ssa_bool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -435,7 +435,11 @@ pre_opt_terminator(#b_switch{arg=Arg0}=Sw0, Sub, Blocks) ->
pre_opt_sw(#b_switch{arg=Arg,fail=Fail}=Sw, False, True, Sub, Blocks) ->
case Sub of
#{Arg:={true_or_any,PhiL}} ->
- #{Fail:=FailBlk,False:=FalseBlk,PhiL:=PhiBlk} = Blocks,
+ #{Fail := FailBlk,False := FalseBlk} = Blocks,
+ PhiBlk = case Blocks of
+ #{PhiL := PhiBlk0} -> PhiBlk0;
+ #{} -> none
+ end,
case {FailBlk,FalseBlk,PhiBlk} of
{#b_blk{is=[],last=#b_br{succ=PhiL,fail=PhiL}},
#b_blk{is=[],last=#b_br{succ=PhiL,fail=PhiL}},
@@ -938,7 +942,7 @@ opt_digraph_instr(#b_set{dst=Dst}=I, G0, St) ->
%% 'xor' is almost never used in practice.
not_possible();
#b_set{op={bif,'not'}} ->
- %% This is suprisingly rare. The previous attempt to
+ %% This is surprisingly rare. The previous attempt to
%% optimize it was broken, which wasn't noticed because
%% very few test cases triggered this code.
not_possible();
@@ -1030,7 +1034,7 @@ eaten_by_phi(V, G) ->
%% order_args([Arg1,Arg2], G, St) -> {First,Second}.
%% Order arguments for a boolean operator so that there is path in the
%% digraph from the instruction referered to by the first operand to
-%% the instruction refered to by the second operand.
+%% the instruction referred to by the second operand.
order_args([#b_var{}=VarA,#b_var{}=VarB], G, St) ->
{VA,VB} = {get_vertex(VarA, St),get_vertex(VarB, St)},
@@ -1066,10 +1070,13 @@ redirect_test(Bool, SuccFail, G0, St) ->
redirect_test_1(V, SuccFail, G) ->
case get_targets(V, G) of
{br,_Succ,Fail} ->
- %% I have only seen this happen in code generated by LFE
- %% (in lfe_andor_SUITE.core and lfe_guard_SUITE.core)
+ %% This is rare when compiling from Erlang code. It is
+ %% more frequent for generated by another code generator
+ %% such as the one in LFE (see lfe_andor_SUITE.core and
+ %% lfe_guard_SUITE.core).
case SuccFail of
{fail,Fail} -> G;
+ {fail,_} -> not_possible();
{succ,_} -> not_possible()
end;
{br,Next} ->
@@ -1455,7 +1462,7 @@ ensure_init_used_1([], _G, Acc) ->
do_ensure_init_instr(#b_set{op=phi,args=Args},
_VarMap, InitMaps) ->
- _ = [ensure_init_used(Var, map_get(From, InitMaps)) ||
+ _ = [ensure_init_used(Var, maps:get(From, InitMaps, #{})) ||
{#b_var{}=Var,From} <- Args],
ok;
do_ensure_init_instr(#b_set{}=I, VarMap, _InitMaps) ->
diff --git a/lib/compiler/src/beam_ssa_bsm.erl b/lib/compiler/src/beam_ssa_bsm.erl
index 59872290a6..f84ae7dced 100644
--- a/lib/compiler/src/beam_ssa_bsm.erl
+++ b/lib/compiler/src/beam_ssa_bsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -128,15 +128,20 @@ has_bsm_ops(#b_function{bs=Blocks}) ->
hbo_blocks([{_,#b_blk{is=Is}} | Blocks]) ->
case hbo_is(Is) of
- false -> hbo_blocks(Blocks);
- true -> true
+ no -> hbo_blocks(Blocks);
+ yes -> true;
+ nif_start ->
+ %% Disable optimizations for declared -nifs()
+ %% to avoid leaking match contexts as NIF arguments.
+ false
end;
hbo_blocks([]) ->
false.
-hbo_is([#b_set{op=bs_start_match} | _]) -> true;
+hbo_is([#b_set{op=bs_start_match} | _]) -> yes;
+hbo_is([#b_set{op=nif_start} | _]) -> nif_start;
hbo_is([_I | Is]) -> hbo_is(Is);
-hbo_is([]) -> false.
+hbo_is([]) -> no.
%% Checks whether it's legal to make a call with the given argument as a match
%% context, returning the param_info() of the relevant parameter.
@@ -422,7 +427,7 @@ is_var_in_args(_Var, []) -> false.
%%% Subpasses
%%%
-%% Removes superflous chained bs_start_match instructions in the same
+%% Removes superfluous chained bs_start_match instructions in the same
%% function. When matching on an extracted tail binary, or on a binary we've
%% already matched on, we reuse the original match context.
%%
@@ -991,13 +996,7 @@ add_unopt_binary_info(#b_set{op=Follow,dst=Dst}, Nested, Where, UseMap, Acc0)
foldl(fun(Use, Acc) ->
add_unopt_binary_info(Use, Nested, Where, UseMap, Acc)
end, Acc0, Uses);
-add_unopt_binary_info(#b_set{op=call,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error}} |
- _Ignored]},
- _Nested, _Where, _UseMap, Acc) ->
- %% There's no nice way to tell compiler-generated exceptions apart from
- %% user ones so we ignore them all. I doubt anyone cares.
+add_unopt_binary_info(#b_set{op=match_fail}, _Nested, _Where, _UseMap, Acc) ->
Acc;
add_unopt_binary_info(#b_switch{anno=Anno}=I, Nested, Where, _UseMap, Acc) ->
[make_promotion_warning(I, Nested, Anno, Where) | Acc];
@@ -1012,7 +1011,11 @@ make_promotion_warning(I, Nested, Anno, Where) ->
make_warning({binary_created, I, Nested}, Anno, Where).
make_warning(Term, Anno, Where) ->
- {File, Line} = maps:get(location, Anno, Where),
+ {File, Line} =
+ case maps:get(location, Anno, Where) of
+ {_, _} = Location -> Location;
+ _ -> {"no_file", none}
+ end,
{File,[{Line,?MODULE,Term}]}.
format_opt_info(context_reused) ->
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index 1830f9647e..9c430d45b6 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
-export_type([ssa_register/0]).
-include("beam_ssa.hrl").
+-include("beam_asm.hrl").
-import(lists, [foldl/3,keymember/3,keysort/2,map/2,mapfoldl/3,
member/2,reverse/1,reverse/2,sort/1,
@@ -104,11 +105,7 @@ module(#b_module{name=Mod,exports=Es,attributes=Attrs,body=Fs}, _Opts) ->
-type sw_list_item() :: {b_literal(),ssa_label()}.
--type reg_num() :: beam_asm:reg_num().
--type xreg() :: {'x',reg_num()}.
--type yreg() :: {'y',reg_num()}.
-
--type ssa_register() :: xreg() | yreg() | {'fr',reg_num()} | {'z',reg_num()}.
+-type ssa_register() :: xreg() | yreg() | freg() | zreg().
functions(Forms, AtomMod) ->
mapfoldl(fun (F, St) -> function(F, AtomMod, St) end,
@@ -252,7 +249,7 @@ need_heap_blks([], H, Acc) ->
need_heap_is([#cg_alloc{words=Words}=Alloc0|Is], N, Acc) ->
Alloc = Alloc0#cg_alloc{words=add_heap_words(N, Words)},
need_heap_is(Is, #need{}, [Alloc|Acc]);
-need_heap_is([#cg_set{anno=Anno,op=bs_init}=I0|Is], N, Acc) ->
+need_heap_is([#cg_set{anno=Anno,op=bs_create_bin}=I0|Is], N, Acc) ->
Alloc = case need_heap_need(N) of
[#cg_alloc{words=Need}] -> alloc(Need);
[] -> 0
@@ -284,13 +281,11 @@ need_heap_terminator([{_,#cg_blk{is=Is,last=#cg_br{succ=L}}}|_], L, N) ->
[] ->
{[],#need{}};
[_|_]=Alloc ->
- %% If the preceding instructions are a binary construction,
- %% hoist the allocation and incorporate into the bs_init
+ %% If the preceding instruction is a bs_create_bin instruction,
+ %% hoist the allocation and incorporate into the bs_create_bin
%% instruction.
case reverse(Is) of
- [#cg_set{op=succeeded},#cg_set{op=bs_init}|_] ->
- {[],N};
- [#cg_set{op=succeeded},#cg_set{op=bs_put}|_] ->
+ [#cg_set{op=succeeded},#cg_set{op=bs_create_bin}|_] ->
{[],N};
_ ->
%% Not binary construction. Must emit an allocation
@@ -342,8 +337,6 @@ add_heap_float(#need{f=F}=N) ->
classify_heap_need(put_list, _) ->
{put,2};
-classify_heap_need(put_tuple_arity, [#b_literal{val=Words}]) ->
- {put,Words+1};
classify_heap_need(put_tuple, Elements) ->
{put,length(Elements)+1};
classify_heap_need(make_fun, Args) ->
@@ -373,22 +366,16 @@ classify_heap_need(Name, _Args) ->
%% Note: Only handle operations in this function that are not handled
%% by classify_heap_need/2.
-classify_heap_need(bs_add) -> gc;
classify_heap_need(bs_get) -> gc;
classify_heap_need(bs_get_tail) -> gc;
-classify_heap_need(bs_init) -> gc;
classify_heap_need(bs_init_writable) -> gc;
classify_heap_need(bs_match_string) -> gc;
-classify_heap_need(bs_put) -> neutral;
-classify_heap_need(bs_restore) -> neutral;
-classify_heap_need(bs_save) -> neutral;
+classify_heap_need(bs_create_bin) -> gc;
classify_heap_need(bs_get_position) -> gc;
classify_heap_need(bs_set_position) -> neutral;
classify_heap_need(bs_skip) -> gc;
classify_heap_need(bs_start_match) -> gc;
classify_heap_need(bs_test_tail) -> neutral;
-classify_heap_need(bs_utf16_size) -> neutral;
-classify_heap_need(bs_utf8_size) -> neutral;
classify_heap_need(build_stacktrace) -> gc;
classify_heap_need(call) -> gc;
classify_heap_need(catch_end) -> gc;
@@ -404,12 +391,12 @@ classify_heap_need(is_tagged_tuple) -> neutral;
classify_heap_need(kill_try_tag) -> gc;
classify_heap_need(landingpad) -> gc;
classify_heap_need(match_fail) -> gc;
+classify_heap_need(nif_start) -> neutral;
classify_heap_need(nop) -> neutral;
-classify_heap_need(new_try_tag) -> gc;
+classify_heap_need(new_try_tag) -> neutral;
classify_heap_need(old_make_fun) -> gc;
classify_heap_need(peek_message) -> gc;
classify_heap_need(put_map) -> gc;
-classify_heap_need(put_tuple_elements) -> neutral;
classify_heap_need(raw_raise) -> gc;
classify_heap_need(recv_marker_bind) -> neutral;
classify_heap_need(recv_marker_clear) -> neutral;
@@ -682,8 +669,8 @@ get_live(#cg_set{anno=#{live:=Live}}) ->
need_live_anno(Op) ->
case Op of
{bif,_} -> true;
+ bs_create_bin -> true;
bs_get -> true;
- bs_init -> true;
bs_get_position -> true;
bs_get_tail -> true;
bs_start_match -> true;
@@ -806,7 +793,7 @@ need_y_init(#cg_set{anno=#{clobbers:=Clobbers}}) -> Clobbers;
need_y_init(#cg_set{op=bs_get}) -> true;
need_y_init(#cg_set{op=bs_get_position}) -> true;
need_y_init(#cg_set{op=bs_get_tail}) -> true;
-need_y_init(#cg_set{op=bs_init}) -> true;
+need_y_init(#cg_set{op=bs_create_bin}) -> true;
need_y_init(#cg_set{op=bs_skip,args=[#b_literal{val=Type}|_]}) ->
case Type of
utf8 -> true;
@@ -892,7 +879,7 @@ opt_allocate_is([]) -> none.
%% fix_wait_timeout([Block]) -> [Block].
%% In SSA code, the `wait_timeout` instruction is a three-way branch
%% (because there will be an exception for a bad timeout value). In
-%% BEAM code, the potential rasing of an exception for a bad timeout
+%% BEAM code, the potential raising of an exception for a bad timeout
%% duration is not explicitly represented. Thus we will need to
%% rewrite the following code:
%%
@@ -1052,7 +1039,8 @@ cg_block([#cg_set{op=new_try_tag,dst=Tag,args=Args}], {Tag,Fail0}, St) ->
{[{Kind,Reg,Fail}],St};
cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
- [Dst|Args] = beam_args([Dst0|Args0], St),
+ Args = typed_args(Args0, Anno, St),
+ Dst = beam_arg(Dst0, St),
Line0 = call_line(body, {extfunc,erlang,Name,length(Args)}, Anno),
Fail = bif_fail(Fail0),
Line = case Fail of
@@ -1083,9 +1071,10 @@ cg_block([#cg_set{op={bif,tuple_size},dst=Arity0,args=[Tuple0]},
{Is,St} = cg_block([Eq], Context, St0),
{[TupleSize|Is],St}
end;
-cg_block([#cg_set{op={bif,Name},dst=Dst0,args=Args0}]=Is0, {Dst0,Fail}, St0) ->
- [Dst|Args] = beam_args([Dst0|Args0], St0),
- case Dst of
+cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}]=Is0,
+ {Dst0,Fail}, St0) ->
+ Args = typed_args(Args0, Anno, St0),
+ case beam_arg(Dst0, St0) of
{z,_} ->
%% The result of the BIF call will only be used once. Convert to
%% a test instruction.
@@ -1100,7 +1089,8 @@ cg_block([#cg_set{op={bif,Name},dst=Dst0,args=Args0}]=Is0, {Dst0,Fail}, St0) ->
end;
cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}=I|T],
Context, St0) ->
- [Dst|Args] = beam_args([Dst0|Args0], St0),
+ Args = typed_args(Args0, Anno, St0),
+ Dst = beam_arg(Dst0, St0),
{Is0,St} = cg_block(T, Context, St0),
case is_gc_bif(Name, Args) of
true ->
@@ -1113,47 +1103,31 @@ cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}=I|T],
Is = [{bif,Name,{f,0},Args,Dst}|Is0],
{Is,St}
end;
-cg_block([#cg_set{op=bs_init,dst=Dst0,args=Args0,anno=Anno}=I,
+cg_block([#cg_set{op=bs_create_bin,dst=Dst0,args=Args0,anno=Anno}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
+ Args1 = typed_args(Args0, Anno, St),
Fail = bif_fail(Fail0),
Line = line(Anno),
Alloc = map_get(alloc, Anno),
- [#b_literal{val=Kind}|Args1] = Args0,
Live = get_live(I),
- case Kind of
- new ->
- [Dst,Size,{integer,Unit}] = beam_args([Dst0|Args1], St),
- {[Line|cg_bs_init(Dst, Size, Alloc, Unit, Live, Fail)],St};
- private_append ->
- [Dst,Src,Bits,{integer,Unit}] = beam_args([Dst0|Args1], St),
- Flags = {field_flags,[]},
- TestHeap = {test_heap,Alloc,Live},
- BsPrivateAppend = {bs_private_append,Fail,Bits,Unit,Src,Flags,Dst},
- Is = [TestHeap,Line,BsPrivateAppend],
- {Is,St};
- append ->
- [Dst,Src,Bits,{integer,Unit}] = beam_args([Dst0|Args1], St),
- Flags = {field_flags,[]},
- Is = [Line,{bs_append,Fail,Bits,Alloc,Live,Unit,Src,Flags,Dst}],
- {Is,St}
- end;
-cg_block([#cg_set{anno=Anno,
- op=bs_start_match,
+ Dst = beam_arg(Dst0, St),
+ Args = bs_args(Args1),
+ Unit = case Args of
+ [{atom,append},_Seg,U|_] -> U;
+ [{atom,private_append},_Seg,U|_] -> U;
+ _ -> 1
+ end,
+ Is = [Line,{bs_create_bin,Fail,Alloc,Live,Unit,Dst,{list,Args}}],
+ {Is,St};
+cg_block([#cg_set{op=bs_start_match,
dst=Ctx0,
args=[#b_literal{val=new},Bin0]}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
[Dst,Bin1] = beam_args([Ctx0,Bin0], St),
{Bin,Pre} = force_reg(Bin1, Dst),
Live = get_live(I),
- %% num_slots is only set when using the old instructions.
- case maps:find(num_slots, Anno) of
- {ok, Slots} ->
- Is = Pre ++ [{test,bs_start_match2,Fail,Live,[Bin,Slots],Dst}],
- {Is,St};
- error ->
- Is = Pre ++ [{test,bs_start_match3,Fail,Live,[Bin],Dst}],
- {Is,St}
- end;
+ Is = Pre ++ [{test,bs_start_match3,Fail,Live,[Bin],Dst}],
+ {Is,St};
cg_block([#cg_set{op=bs_get}=Set,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
{cg_bs_get(Fail, Set, St),St};
@@ -1169,10 +1143,6 @@ cg_block([#cg_set{op=bs_match_string,args=[CtxVar,#b_literal{val=String0}]},
Is = [{test,bs_match_string,Fail,[CtxReg,Bits,{string,String}]}],
{Is,St};
-cg_block([#cg_set{op=bs_put,args=Args0},
- #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
- Args = beam_args(Args0, St),
- {cg_bs_put(bif_fail(Fail), Args),St};
cg_block([#cg_set{dst=Dst0,op=landingpad,args=Args0}|T], Context, St0) ->
[Dst,{atom,Kind},Tag] = beam_args([Dst0|Args0], St0),
case Kind of
@@ -1197,11 +1167,18 @@ cg_block([#cg_set{op=match_fail}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) ->
%% A match_fail instruction in a try/catch block.
cg_block([I], none, St);
-cg_block([#cg_set{op=get_map_element,dst=Dst0,args=Args0},
+cg_block([#cg_set{op=get_map_element,dst=Dst0,args=Args0,anno=Anno},
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
- [Dst,Map,Key] = beam_args([Dst0|Args0], St),
+ [Map,Key] = typed_args(Args0, Anno, St),
+ Dst = beam_arg(Dst0, St),
Fail = ensure_label(Fail0, St),
{[{get_map_elements,Fail,Map,{list,[Key,Dst]}}],St};
+cg_block([#cg_set{op={float,convert},dst=Dst0,args=Args0,anno=Anno},
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
+ {f,0} = bif_fail(Fail), %Assertion.
+ [Src] = typed_args(Args0, Anno, St),
+ Dst = beam_arg(Dst0, St),
+ {[line(Anno),{fconv,Src,Dst}], St};
cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
[Dst|Args] = beam_args([Dst0|Args0], St),
@@ -1209,9 +1186,19 @@ cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I,
cg_block([#cg_set{op=bs_test_tail,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
[Ctx,{integer,Bits}] = beam_args(Args0, St),
{[{test,bs_test_tail2,bif_fail(Fail),[Ctx,Bits]}],St};
-cg_block([#cg_set{op=is_tagged_tuple,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
- [Src,{integer,Arity},Tag] = beam_args(Args0, St),
- {[{test,is_tagged_tuple,ensure_label(Fail, St),[Src,Arity,Tag]}],St};
+cg_block([#cg_set{op=is_tagged_tuple,anno=Anno,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+ case Anno of
+ #{constraints := arity} ->
+ [Src,{integer,Arity},_Tag] = beam_args(Args0, St),
+ {[{test,test_arity,ensure_label(Fail, St),[Src,Arity]}],St};
+ #{constraints := tuple_arity} ->
+ [Src,{integer,Arity},_Tag] = beam_args(Args0, St),
+ {[{test,is_tuple,ensure_label(Fail, St),[Src]},
+ {test,test_arity,ensure_label(Fail, St),[Src,Arity]}],St};
+ #{} ->
+ [Src,{integer,Arity},Tag] = typed_args(Args0, Anno, St),
+ {[{test,is_tagged_tuple,ensure_label(Fail, St),[Src,Arity,Tag]}],St}
+ end;
cg_block([#cg_set{op=is_nonempty_list,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
Args = beam_args(Args0, St),
{[{test,is_nonempty_list,ensure_label(Fail, St),Args}],St};
@@ -1332,6 +1319,32 @@ cg_block([], {Bool0,Fail}, St) ->
[Bool] = beam_args([Bool0], St),
{[{test,is_eq_exact,Fail,[Bool,{atom,true}]}],St}.
+bs_args([{atom,binary},{literal,[1|_]},{literal,Bs},{atom,all}|Args])
+ when bit_size(Bs) =:= 0 ->
+ bs_args(Args);
+bs_args([{atom,binary},{literal,[1|_]}=UFs,{literal,Bs},{atom,all}|Args0])
+ when is_bitstring(Bs) ->
+ Bits = bit_size(Bs),
+ Bytes = Bits div 8,
+ case Bits rem 8 of
+ 0 ->
+ [{atom,string},0,8,nil,{string,Bs},{integer,byte_size(Bs)}|bs_args(Args0)];
+ Rem ->
+ <<Binary:Bytes/bytes,Int:Rem>> = Bs,
+ Args = [{atom,binary},UFs,{literal,Binary},{atom,all},
+ {atom,integer},{literal,[1]},{integer,Int},{integer,Rem}|Args0],
+ bs_args(Args)
+ end;
+bs_args([Type,{literal,[Unit|Fs0]},Val,Size|Args]) ->
+ Segment = proplists:get_value(segment, Fs0, 0),
+ Fs1 = proplists:delete(segment, Fs0),
+ Fs = case Fs1 of
+ [] -> nil;
+ [_|_] -> {literal,Fs1}
+ end,
+ [Type,Segment,Unit,Fs,Val,Size|bs_args(Args)];
+bs_args([]) -> [].
+
cg_copy(T0, St) ->
{Copies,T} = splitwith(fun(#cg_set{op=copy}) -> true;
(_) -> false
@@ -1564,13 +1577,20 @@ cg_call(#cg_set{anno=Anno0,op=call,dst=Dst0,args=[#b_remote{}=Func0|Args0]},
[line(Anno0)] ++ Apply,
{Is,St}
end;
-cg_call(#cg_set{anno=Anno,op=call,dst=Dst0,args=Args0},
- Where, Context, St) ->
- [Dst,Func|Args] = beam_args([Dst0|Args0], St),
+cg_call(#cg_set{anno=Anno,op=call,dst=Dst0,args=[Func | Args0]},
+ Where, Context, St0) ->
Line = call_line(Where, Func, Anno),
- Arity = length(Args),
- Call = build_call(call_fun, Arity, Func, Context, Dst),
- Is = setup_args(Args++[Func], Anno, Context, St) ++ Line ++ Call,
+ Args = beam_args(Args0 ++ [Func], St0),
+
+ Arity = length(Args0),
+ Dst = beam_arg(Dst0, St0),
+
+ %% Note that we only inspect the (possible) type of the fun while building
+ %% the call, we don't want the arguments to be typed.
+ [TypedFunc] = typed_args([Func], Anno, St0),
+ {Call, St} = build_fun_call(Arity, TypedFunc, Context, Dst, St0),
+
+ Is = setup_args(Args, Anno, Context, St) ++ Line ++ Call,
case Anno of
#{ result_type := Type } ->
Info = {var_info, Dst, [{type,Type}]},
@@ -1615,12 +1635,6 @@ build_stk([V|Vs], TmpReg, Tail) ->
build_stk([], _TmpReg, nil) ->
[{move,nil,{x,1}}].
-build_call(call_fun, Arity, _Func, none, Dst) ->
- [{call_fun,Arity}|copy({x,0}, Dst)];
-build_call(call_fun, Arity, _Func, {return,Dst,N}, Dst) when is_integer(N) ->
- [{call_fun,Arity},{deallocate,N},return];
-build_call(call_fun, Arity, _Func, {return,Val,N}, _Dst) when is_integer(N) ->
- [{call_fun,Arity},{move,Val,{x,0}},{deallocate,N},return];
build_call(call_ext, 2, {extfunc,erlang,'!',2}, none, Dst) ->
[send|copy({x,0}, Dst)];
build_call(call_ext, 2, {extfunc,erlang,'!',2}, {return,Dst,N}, Dst)
@@ -1646,6 +1660,42 @@ build_call(I, Arity, Func, {return,Val,N}, _Dst) when is_integer(N) ->
build_call(I, Arity, Func, none, Dst) ->
[{I,Arity,Func}|copy({x,0}, Dst)].
+build_fun_call(Arity, #tr{}=Func0, none, Dst, St0) ->
+ %% Func0 was the source register prior to copying arguments, and has been
+ %% moved to {x, Arity}. Update it to match.
+ Func = Func0#tr{r={x,Arity}},
+ {Tag, St} = fun_call_tag(Arity, Func, St0),
+ Is = [{call_fun2,Tag,Arity,Func}|copy({x,0}, Dst)],
+ {Is, St};
+build_fun_call(Arity, #tr{}=Func0, {return,Dst,N}, Dst, St0)
+ when is_integer(N) ->
+ Func = Func0#tr{r={x,Arity}},
+ {Tag, St} = fun_call_tag(Arity, Func, St0),
+ Is = [{call_fun2,Tag,Arity,Func},{deallocate,N},return],
+ {Is, St};
+build_fun_call(Arity, #tr{}=Func0, {return,Val,N}, _Dst, St0)
+ when is_integer(N) ->
+ Func = Func0#tr{r={x,Arity}},
+ {Tag, St} = fun_call_tag(Arity, Func, St0),
+ Is = [{call_fun2,Tag,Arity,Func},
+ {move,Val,{x,0}},
+ {deallocate,N},return],
+ {Is, St};
+build_fun_call(Arity, _Func, none, Dst, St) ->
+ {[{call_fun,Arity}|copy({x,0}, Dst)], St};
+build_fun_call(Arity, _Func, {return,Dst,N}, Dst, St) when is_integer(N) ->
+ {[{call_fun,Arity},{deallocate,N},return], St};
+build_fun_call(Arity, _Func, {return,Val,N}, _Dst, St) when is_integer(N) ->
+ {[{call_fun,Arity},{move,Val,{x,0}},{deallocate,N},return], St}.
+
+fun_call_tag(Arity, #tr{t=#t_fun{arity=Arity,target={Name,TotalArity}}}, St0) ->
+ {FuncLbl, St} = local_func_label(Name, TotalArity, St0),
+ {{f,FuncLbl}, St};
+fun_call_tag(Arity, #tr{t=#t_fun{arity=Arity}}, St) ->
+ {{atom,safe}, St};
+fun_call_tag(_Arity, _Func, St) ->
+ {{atom,unsafe}, St}.
+
build_apply(Arity, {return,Dst,N}, Dst) when is_integer(N) ->
[{apply_last,Arity,N}];
build_apply(Arity, {return,Val,N}, _Dst) when is_integer(N) ->
@@ -1669,21 +1719,19 @@ cg_instr(bs_get_position, [Ctx], Dst, Set) ->
cg_instr(put_map, [{atom,assoc},SrcMap|Ss], Dst, Set) ->
Live = get_live(Set),
[{put_map_assoc,{f,0},SrcMap,Dst,Live,{list,Ss}}];
+cg_instr(is_nonempty_list, Ss, Dst, Set) ->
+ #cg_set{anno=#{was_bif_is_list := true}} = Set, %Assertion.
+
+ %% This instruction was a call to is_list/1, which was rewritten
+ %% to an is_nonempty_list test by beam_ssa_type. BEAM has no
+ %% is_nonempty_list instruction that will return a boolean, so
+ %% we must revert it to an is_list/1 call.
+ [{bif,is_list,{f,0},Ss,Dst}];
cg_instr(Op, Args, Dst, _Set) ->
cg_instr(Op, Args, Dst).
cg_instr(bs_init_writable, Args, Dst) ->
setup_args(Args) ++ [bs_init_writable|copy({x,0}, Dst)];
-cg_instr(bs_restore, [Ctx,Slot], _Dst) ->
- case Slot of
- {integer,N} ->
- [{bs_restore2,Ctx,N}];
- {atom,start} ->
- [{bs_restore2,Ctx,Slot}]
- end;
-cg_instr(bs_save, [Ctx,Slot], _Dst) ->
- {integer,N} = Slot,
- [{bs_save2,Ctx,N}];
cg_instr(bs_set_position, [Ctx,Pos], _Dst) ->
[{bs_set_position,Ctx,Pos}];
cg_instr(build_stacktrace, Args, Dst) ->
@@ -1702,16 +1750,14 @@ cg_instr(get_tuple_element=Op, [Src,{integer,N}], Dst) ->
[{Op,Src,N,Dst}];
cg_instr(has_map_field, [Map,Key], Dst) ->
[{bif,is_map_key,{f,0},[Key,Map],Dst}];
+cg_instr(nif_start, [], _Dst) ->
+ [nif_start];
cg_instr(put_list=Op, [Hd,Tl], Dst) ->
[{Op,Hd,Tl,Dst}];
cg_instr(nop, [], _Dst) ->
[];
cg_instr(put_tuple, Elements, Dst) ->
[{put_tuple2,Dst,{list,Elements}}];
-cg_instr(put_tuple_arity, [{integer,Arity}], Dst) ->
- [{put_tuple,Arity,Dst}];
-cg_instr(put_tuple_elements, Elements, _Dst) ->
- [{put,E} || E <- Elements];
cg_instr(raw_raise, Args, Dst) ->
setup_args(Args) ++ [raw_raise|copy({x,0}, Dst)];
cg_instr(recv_marker_bind, [Mark, Ref], _Dst) ->
@@ -1725,17 +1771,8 @@ cg_instr(remove_message, [], _Dst) ->
cg_instr(resume, [A,B], _Dst) ->
[{bif,raise,{f,0},[A,B],{x,0}}].
-cg_test(bs_add=Op, Fail, [Src1,Src2,{integer,Unit}], Dst, _I) ->
- [{Op,Fail,[Src1,Src2,Unit],Dst}];
cg_test(bs_skip, Fail, Args, _Dst, I) ->
cg_bs_skip(Fail, Args, I);
-cg_test(bs_utf8_size=Op, Fail, [Src], Dst, _I) ->
- [{Op,Fail,Src,Dst}];
-cg_test(bs_utf16_size=Op, Fail, [Src], Dst, _I) ->
- [{Op,Fail,Src,Dst}];
-cg_test({float,convert}, Fail, [Src], Dst, #cg_set{anno=Anno}) ->
- {f,0} = Fail, %Assertion.
- [line(Anno),{fconv,Src,Dst}];
cg_test({float,Op0}, Fail, Args, Dst, #cg_set{anno=Anno}) ->
Op = case Op0 of
'+' -> fadd;
@@ -1749,7 +1786,11 @@ cg_test(peek_message, Fail, [], Dst, _I) ->
[{loop_rec,Fail,{x,0}}|copy({x,0}, Dst)];
cg_test(put_map, Fail, [{atom,exact},SrcMap|Ss], Dst, #cg_set{anno=Anno}=Set) ->
Live = get_live(Set),
- [line(Anno),{put_map_exact,Fail,SrcMap,Dst,Live,{list,Ss}}].
+ [line(Anno),{put_map_exact,Fail,SrcMap,Dst,Live,{list,Ss}}];
+cg_test(raw_raise, _Fail, Args, Dst, _I) ->
+ cg_instr(raw_raise, Args, Dst);
+cg_test(resume, _Fail, [_,_]=Args, Dst, _I) ->
+ cg_instr(resume, Args, Dst).
cg_bs_get(Fail, #cg_set{dst=Dst0,args=[#b_literal{val=Type}|Ss0]}=Set, St) ->
Op = case Type of
@@ -1802,34 +1843,6 @@ field_flags(Flags, #cg_set{anno=#{location:={File,Line}}}) ->
field_flags(Flags, _) ->
{field_flags,Flags}.
-cg_bs_put(Fail, [{atom,Type},{literal,Flags}|Args]) ->
- Op = case Type of
- integer -> bs_put_integer;
- float -> bs_put_float;
- binary -> bs_put_binary;
- utf8 -> bs_put_utf8;
- utf16 -> bs_put_utf16;
- utf32 -> bs_put_utf32
- end,
- case Args of
- [Src,Size,{integer,Unit}] ->
- [{Op,Fail,Size,Unit,{field_flags,Flags},Src}];
- [Src] ->
- [{Op,Fail,{field_flags,Flags},Src}]
- end.
-
-cg_bs_init(Dst, Size0, Alloc, Unit, Live, Fail) ->
- Op = case Unit of
- 1 -> bs_init_bits;
- 8 -> bs_init2
- end,
- Size = cg_bs_init_size(Size0),
- [{Op,Fail,Size,Alloc,Live,{field_flags,[]},Dst}].
-
-cg_bs_init_size({x,_}=R) -> R;
-cg_bs_init_size({y,_}=R) -> R;
-cg_bs_init_size({integer,Int}) -> Int.
-
cg_catch(Agg, T0, Context, St0) ->
{Moves,T1} = cg_extract(T0, Agg, St0),
{T,St} = cg_block(T1, Context, St0),
@@ -1855,6 +1868,9 @@ cg_extract([#cg_set{op=extract,dst=Dst0,args=Args0}|Is0], Agg, St) ->
cg_extract(Is, _, _) ->
{[],Is}.
+-spec copy(Src, Dst) -> [{move,Src,Dst}] when
+ Src :: beam_reg() | beam_literal(),
+ Dst :: beam_reg().
copy(Src, Src) -> [];
copy(Src, Dst) -> [{move,Src,Dst}].
@@ -1916,13 +1932,30 @@ translate_block(L, #b_blk{anno=Anno,is=Is0,last=Last0}, Blocks) ->
translate_is([#b_set{op=phi}|Is], Tail) ->
translate_is(Is, Tail);
translate_is([#b_set{anno=Anno0,op=Op,dst=Dst,args=Args}=I|Is], Tail) ->
- Anno = case beam_ssa:clobbers_xregs(I) of
- true -> Anno0#{clobbers=>true};
- false -> Anno0
+ Anno1 = case beam_ssa:clobbers_xregs(I) of
+ true -> Anno0#{clobbers=>true};
+ false -> Anno0
end,
+ Anno = prune_arg_types(Anno1, Args),
[#cg_set{anno=Anno,op=Op,dst=Dst,args=Args}|translate_is(Is, Tail)];
translate_is([], Tail) -> Tail.
+prune_arg_types(#{arg_types := ArgTypes0}=Anno, Args) ->
+ ArgTypes = prune_arg_types_1(Args, 0, ArgTypes0),
+ if
+ ArgTypes =:= #{} ->
+ maps:remove(arg_types, Anno);
+ true ->
+ Anno#{arg_types := ArgTypes}
+ end;
+prune_arg_types(Anno, _Args) -> Anno.
+
+prune_arg_types_1([#b_var{}|As], N, ArgTypes) ->
+ prune_arg_types_1(As, N + 1, ArgTypes);
+prune_arg_types_1([_|As], N, ArgTypes) ->
+ prune_arg_types_1(As, N + 1, maps:remove(N, ArgTypes));
+prune_arg_types_1([], _N, ArgTypes) -> ArgTypes.
+
translate_terminator(#b_ret{anno=Anno,arg=Arg}) ->
Dealloc = case Anno of
#{deallocate:=N} -> N;
@@ -2094,6 +2127,20 @@ get_register(V, Regs) ->
false -> maps:get(V, Regs)
end.
+typed_args(As, Anno, St) ->
+ typed_args_1(As, Anno, St, 0).
+
+typed_args_1([Arg | Args], Anno, St, Index) ->
+ case Anno of
+ #{ arg_types := #{ Index := Type } } ->
+ Typed = #tr{r=beam_arg(Arg, St),t=Type},
+ [Typed | typed_args_1(Args, Anno, St, Index + 1)];
+ #{} ->
+ [beam_arg(Arg, St) | typed_args_1(Args, Anno, St, Index + 1)]
+ end;
+typed_args_1([], _Anno, _St, _Index) ->
+ [].
+
beam_args(As, St) ->
[beam_arg(A, St) || A <- As].
@@ -2163,8 +2210,6 @@ local_func_label(Key, #cg{functable=Map}=St0) ->
%% is_gc_bif(Name, Args) -> true|false.
%% Determines whether the BIF Name/Arity might do a GC.
--spec is_gc_bif(atom(), [beam_ssa:value()]) -> boolean().
-
is_gc_bif(hd, [_]) -> false;
is_gc_bif(tl, [_]) -> false;
is_gc_bif(self, []) -> false;
diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl
index abf287601c..2c0384704e 100644
--- a/lib/compiler/src/beam_ssa_dead.erl
+++ b/lib/compiler/src/beam_ssa_dead.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,24 +27,24 @@
-export([opt/1]).
-include("beam_ssa.hrl").
--import(lists, [append/1,keymember/3,last/1,member/2,
- reverse/1,takewhile/2]).
+-import(lists, [append/1,foldl/3,keymember/3,last/1,member/2,
+ reverse/1,reverse/2,takewhile/2]).
-type used_vars() :: #{beam_ssa:label():=sets:set(beam_ssa:var_name())}.
-type basic_type_test() :: atom() | {'is_tagged_tuple',pos_integer(),atom()}.
-type type_test() :: basic_type_test() | {'not',basic_type_test()}.
-type op_name() :: atom().
--type basic_rel_op() :: {op_name(),beam_ssa:b_var(),beam_ssa:value()} |
- {basic_type_test(),beam_ssa:value()}.
--type rel_op() :: {op_name(),beam_ssa:b_var(),beam_ssa:value()} |
- {type_test(),beam_ssa:value()}.
+-type basic_test() :: {op_name(),beam_ssa:b_var(),beam_ssa:value()} |
+ {basic_type_test(),beam_ssa:value()}.
+-type test() :: {op_name(),beam_ssa:b_var(),beam_ssa:value()} |
+ {type_test(),beam_ssa:value()}.
-record(st,
{bs :: beam_ssa:block_map(),
us :: used_vars(),
skippable :: #{beam_ssa:label():='true'},
- rel_op=none :: 'none' | rel_op(),
+ test=none :: 'none' | test(),
target=any :: 'any' | 'one_way' | beam_ssa:label()
}).
@@ -54,13 +54,13 @@
Label :: beam_ssa:label(),
Block :: beam_ssa:b_blk().
-opt(Linear) ->
- {Used,Skippable} = used_vars(Linear),
- Blocks0 = maps:from_list(Linear),
+opt(Linear0) ->
+ {Used,Skippable} = used_vars(Linear0),
+ Blocks0 = maps:from_list(Linear0),
St0 = #st{bs=Blocks0,us=Used,skippable=Skippable},
St = shortcut_opt(St0),
#st{bs=Blocks} = combine_eqs(St#st{us=#{}}),
- beam_ssa:linearize(Blocks).
+ opt_redundant_tests(Blocks).
%%%
%%% Shortcut br/switch targets.
@@ -116,20 +116,20 @@ shortcut_opt([], St) -> St.
shortcut_terminator(#b_br{bool=#b_literal{val=true},succ=Succ0},
_Is, From, St0) ->
- St = St0#st{rel_op=none},
+ St = St0#st{test=none},
shortcut(Succ0, From, #{}, St);
shortcut_terminator(#b_br{bool=#b_var{}=Bool,succ=Succ0,fail=Fail0}=Br,
Is, From, St0) ->
St = St0#st{target=one_way},
- RelOp = get_rel_op(Bool, Is),
+ Test = get_test(Bool, Is),
%% The boolean in a `br` is seldom used by the successors. By
%% not binding its value unless it is actually used we might be able
%% to skip some work in shortcut/4 and sub/2.
SuccBs = bind_var_if_used(Succ0, Bool, #b_literal{val=true}, St),
- BrSucc = shortcut(Succ0, From, SuccBs, St#st{rel_op=RelOp}),
+ BrSucc = shortcut(Succ0, From, SuccBs, St#st{test=Test}),
FailBs = bind_var_if_used(Fail0, Bool, #b_literal{val=false}, St),
- BrFail = shortcut(Fail0, From, FailBs, St#st{rel_op=invert_op(RelOp)}),
+ BrFail = shortcut(Fail0, From, FailBs, St#st{test=invert_test(Test)}),
case {BrSucc,BrFail} of
{#b_br{bool=#b_literal{val=true},succ=Succ},
@@ -158,8 +158,8 @@ shortcut_sw_fail(Fail0, List, Bool, From, St0) ->
case List of
[{#b_literal{val=false},_},
{#b_literal{val=true},_}] ->
- RelOp = {{'not',is_boolean},Bool},
- St = St0#st{rel_op=RelOp,target=one_way},
+ Test = {{'not',is_boolean},Bool},
+ St = St0#st{test=Test,target=one_way},
#b_br{bool=#b_literal{val=true},succ=Fail} =
shortcut(Fail0, From, #{}, St),
Fail;
@@ -168,18 +168,19 @@ shortcut_sw_fail(Fail0, List, Bool, From, St0) ->
end.
shortcut_sw_list([{Lit,L0}|T], Bool, From, St0) ->
- RelOp = {'=:=',Bool,Lit},
- St = St0#st{rel_op=RelOp},
+ Test = {'=:=',Bool,Lit},
+ St = St0#st{test=Test},
#b_br{bool=#b_literal{val=true},succ=L} =
shortcut(L0, From, bind_var(Bool, Lit, #{}), St#st{target=one_way}),
[{Lit,L}|shortcut_sw_list(T, Bool, From, St0)];
shortcut_sw_list([], _, _, _) -> [].
-shortcut(L, _From, Bs, #st{rel_op=none,target=one_way}) when map_size(Bs) =:= 0 ->
- %% There is no way that we can find a suitable branch, because there is no
- %% relational operator stored, there are no bindings, and the block L can't
- %% have any phi nodes from which we could pick bindings because when the target
- %% is `one_way`, it implies the From block has a two-way `br` terminator.
+shortcut(L, _From, Bs, #st{test=none,target=one_way}) when map_size(Bs) =:= 0 ->
+ %% There is no way that we can find a suitable branch, because
+ %% there are no stored tests, there are no bindings, and the block
+ %% L can't have any phi nodes from which we could pick bindings
+ %% because when the target is `one_way`, it implies that the From
+ %% block has a two-way `br` terminator.
#b_br{bool=#b_literal{val=true},succ=L,fail=L};
shortcut(L, From, Bs, St) ->
shortcut_1(L, From, Bs, sets:new([{version, 2}]), St).
@@ -463,7 +464,7 @@ eval_is([#b_set{op={bif,_},dst=Dst}=I0|Is], From, Bs, St) ->
eval_is([#b_set{op=Op,dst=Dst}=I|Is], From, Bs, St)
when Op =:= is_tagged_tuple; Op =:= is_nonempty_list ->
#b_set{args=Args} = sub(I, Bs),
- case eval_rel_op(Op, Args, St) of
+ case eval_test(Op, Args, St) of
#b_literal{}=Val ->
eval_is(Is, From, bind_var(Dst, Val, Bs), St);
none ->
@@ -524,7 +525,7 @@ eval_terminator(#b_switch{arg=Arg,fail=Fail,list=List}=Sw, Bs, St) ->
eval_terminator(#b_ret{}, _Bs, _St) ->
none.
-eval_switch(List, Arg, #st{rel_op={_,Arg,_}=PrevOp}, Fail) ->
+eval_switch(List, Arg, #st{test={_,Arg,_}=PrevOp}, Fail) ->
%% There is a previous relational operator testing the same variable.
%% Optimization may be possible.
eval_switch_1(List, Arg, PrevOp, Fail);
@@ -534,15 +535,15 @@ eval_switch(_, _, _, _) ->
none.
eval_switch_1([{Lit,Lbl}|T], Arg, PrevOp, Fail) ->
- RelOp = {'=:=',Arg,Lit},
- case will_succeed(PrevOp, RelOp) of
+ Test = {'=:=',Arg,Lit},
+ case will_succeed(PrevOp, Test) of
yes ->
%% Success. This branch will always be taken.
Lbl;
no ->
%% This branch will never be taken.
eval_switch_1(T, Arg, PrevOp, Fail);
- maybe ->
+ 'maybe' ->
%% This label could be reached.
eval_switch_1(T, Arg, PrevOp, none)
end;
@@ -577,7 +578,7 @@ eval_bif(#b_set{op={bif,Bif},args=Args}, St) ->
none ->
%% Not literal arguments. Try to evaluate
%% it based on a previous relational operator.
- eval_rel_op({bif,Bif}, Args, St);
+ eval_test({bif,Bif}, Args, St);
LitArgs ->
try apply(erlang, Bif, LitArgs) of
Val -> #b_literal{val=Val}
@@ -602,61 +603,61 @@ get_lit_args(_) -> none.
%%% Handling of relational operators.
%%%
-get_rel_op(Bool, [_|_]=Is) ->
+get_test(Bool, [_|_]=Is) ->
case last(Is) of
#b_set{op=Op,dst=Bool,args=Args} ->
- normalize_op(Op, Args);
+ normalize_test(Op, Args);
#b_set{} ->
none
end;
-get_rel_op(_, []) -> none.
+get_test(_, []) -> none.
-%% normalize_op(Instruction) -> {Normalized,FailLabel} | error
+%% normalize_test(Instruction) -> {Normalized,FailLabel} | error
%% Normalized = {Operator,Variable,Variable|Literal} |
%% {TypeTest,Variable}
-%% Operation = '<' | '=<' | '=:=' | '=/=' | '>=' | '>'
+%% Operation = '<' | '=<' | '=:=' | '=/=' | '>=' | '>' | '==' | '/='
%% TypeTest = is_atom | is_integer ...
%% Variable = #b_var{}
%% Literal = #b_literal{}
%%
-%% Normalize a relational operator to facilitate further
-%% comparisons between operators. Always make the register
-%% operand the first operand. If there are two registers,
-%% order the registers in lexical order.
+%% Normalize type tests and relational operators to facilitate
+%% further comparisons between test. Always make the register
+%% operand the first operand. If there are two registers, order the
+%% registers in lexical order.
%%
%% For example, this instruction:
%%
-%% #b_set{op={bif,=<},args=[#b_literal{}, #b_var{}}
+%% #b_set{op={bif,'<'},args=[#b_literal{}, #b_var{}}
%%
%% will be normalized to:
%%
-%% {'=<',#b_var{},#b_literal{}}
+%% {'>',#b_var{},#b_literal{}}
--spec normalize_op(Op, Args) -> NormalizedOp | 'none' when
+-spec normalize_test(Op, Args) -> NormalizedTest | 'none' when
Op :: beam_ssa:op(),
Args :: [beam_ssa:value()],
- NormalizedOp :: basic_rel_op().
+ NormalizedTest :: basic_test().
-normalize_op(is_tagged_tuple, [Arg,#b_literal{val=Size},#b_literal{val=Tag}])
+normalize_test(is_tagged_tuple, [Arg,#b_literal{val=Size},#b_literal{val=Tag}])
when is_integer(Size), is_atom(Tag) ->
{{is_tagged_tuple,Size,Tag},Arg};
-normalize_op(is_nonempty_list, [Arg]) ->
+normalize_test(is_nonempty_list, [Arg]) ->
{is_nonempty_list,Arg};
-normalize_op({bif,Bif}, [Arg]) ->
+normalize_test({bif,Bif}, [Arg]) ->
case erl_internal:new_type_test(Bif, 1) of
true -> {Bif,Arg};
false -> none
end;
-normalize_op({bif,Bif}, [_,_]=Args) ->
+normalize_test({bif,Bif}, [_,_]=Args) ->
case erl_internal:comp_op(Bif, 2) of
true ->
- normalize_op_1(Bif, Args);
+ normalize_test_1(Bif, Args);
false ->
none
end;
-normalize_op(_, _) -> none.
+normalize_test(_, _) -> none.
-normalize_op_1(Bif, Args) ->
+normalize_test_1(Bif, Args) ->
case Args of
[#b_literal{}=Arg1,#b_var{}=Arg2] ->
{turn_op(Bif),Arg2,Arg1};
@@ -670,22 +671,22 @@ normalize_op_1(Bif, Args) ->
none
end.
--spec invert_op(basic_rel_op() | 'none') -> rel_op() | 'none'.
+-spec invert_test(basic_test() | 'none') -> test() | 'none'.
-invert_op({Op,Arg1,Arg2}) ->
- {invert_op_1(Op),Arg1,Arg2};
-invert_op({TypeTest,Arg}) ->
+invert_test({Op,Arg1,Arg2}) ->
+ {invert_op(Op),Arg1,Arg2};
+invert_test({TypeTest,Arg}) ->
{{'not',TypeTest},Arg};
-invert_op(none) -> none.
+invert_test(none) -> none.
-invert_op_1('>=') -> '<';
-invert_op_1('<') -> '>=';
-invert_op_1('=<') -> '>';
-invert_op_1('>') -> '=<';
-invert_op_1('=:=') -> '=/=';
-invert_op_1('=/=') -> '=:=';
-invert_op_1('==') -> '/=';
-invert_op_1('/=') -> '=='.
+invert_op('>=') -> '<';
+invert_op('<') -> '>=';
+invert_op('=<') -> '>';
+invert_op('>') -> '=<';
+invert_op('=:=') -> '=/=';
+invert_op('=/=') -> '=:=';
+invert_op('==') -> '/=';
+invert_op('/=') -> '=='.
turn_op('<') -> '>';
turn_op('=<') -> '>=';
@@ -696,21 +697,21 @@ turn_op('=/='=Op) -> Op;
turn_op('=='=Op) -> Op;
turn_op('/='=Op) -> Op.
-eval_rel_op(_Bif, _Args, #st{rel_op=none}) ->
+eval_test(_Bif, _Args, #st{test=none}) ->
none;
-eval_rel_op(Bif, Args, #st{rel_op=Prev}) ->
- case normalize_op(Bif, Args) of
+eval_test(Bif, Args, #st{test=Prev}) ->
+ case normalize_test(Bif, Args) of
none ->
none;
- RelOp ->
- case will_succeed(Prev, RelOp) of
+ Test ->
+ case will_succeed(Prev, Test) of
yes -> #b_literal{val=true};
no -> #b_literal{val=false};
- maybe -> none
+ 'maybe' -> none
end
end.
-%% will_succeed(PrevCondition, Condition) -> yes | no | maybe
+%% will_succeed(PrevCondition, Condition) -> yes | no | 'maybe'
%% PrevCondition is a condition known to be true. This function
%% will tell whether Condition will succeed.
@@ -732,29 +733,29 @@ will_succeed({{'not',is_boolean},Var}, {'=:=',Var,#b_literal{val=Lit}})
when is_boolean(Lit) ->
no;
will_succeed({_,_}, {_,_}) ->
- maybe;
+ 'maybe';
will_succeed({_,_}, {_,_,_}) ->
- maybe;
+ 'maybe';
will_succeed({_,_,_}, {_,_}) ->
- maybe;
+ 'maybe';
will_succeed({_,_,_}, {_,_,_}) ->
- maybe.
+ 'maybe'.
will_succeed_test({'not',Test1}, Test2) ->
case Test1 =:= Test2 of
true -> no;
- false -> maybe
+ false -> 'maybe'
end;
will_succeed_test(is_tuple, {is_tagged_tuple,_,_}) ->
- maybe;
+ 'maybe';
will_succeed_test({is_tagged_tuple,_,_}, is_tuple) ->
yes;
will_succeed_test(is_list, is_nonempty_list) ->
- maybe;
+ 'maybe';
will_succeed_test(is_nonempty_list, is_list) ->
yes;
will_succeed_test(_T1, _T2) ->
- maybe.
+ 'maybe'.
will_succeed_1('=:=', A, '<', B) ->
if
@@ -823,7 +824,7 @@ will_succeed_1('==', A, '/=', B) ->
will_succeed_1('/=', A, '/=', B) when A == B -> yes;
will_succeed_1('/=', A, '==', B) when A == B -> no;
-will_succeed_1(_, _, _, _) -> maybe.
+will_succeed_1(_, _, _, _) -> 'maybe'.
will_succeed_vars('=/=', Val, '=:=', Val) -> no;
will_succeed_vars('=:=', Val, '=/=', Val) -> no;
@@ -833,7 +834,7 @@ will_succeed_vars('=:=', Val, '=<', Val) -> yes;
will_succeed_vars('/=', Val1, '==', Val2) when Val1 == Val2 -> no;
will_succeed_vars('==', Val1, '/=', Val2) when Val1 == Val2 -> no;
-will_succeed_vars(_, _, _, _) -> maybe.
+will_succeed_vars(_, _, _, _) -> 'maybe'.
eval_type_test(Test, Arg) ->
case eval_type_test_1(Test, Arg) of
@@ -1049,6 +1050,320 @@ lit_type(Val) ->
true -> none
end.
+
+%%%
+%%% Remove redundant tests.
+%%%
+%%% Repeated tests can be introduced by inlining, macros, or
+%%% complex guards such as:
+%%%
+%%% is_head(M, S) when M =:= <<1>>, S =:= <<2>> ->
+%%% true;
+%%% is_head(M, S) when M =:= <<1>>, S =:= <<3>> ->
+%%% false.
+%%%
+%%% The repeated test is not removed by any of the other optimizing
+%%% passes:
+%%%
+%%% 0:
+%%% _2 = bif:'=:=' _0, `<<1>>`
+%%% br _2, ^19, ^3
+%%%
+%%% 19:
+%%% _3 = bif:'=:=' _1, `<<2>>`
+%%% br _3, ^7, ^4
+%%%
+%%% 7:
+%%% ret `true`
+%%%
+%%% 4:
+%%% _4 = bif:'=:=' _0, `<<1>>`
+%%% br _4, ^15, ^3
+%%%
+%%% 15:
+%%% _5 = bif:'=:=' _1, `<<3>>`
+%%% br _5, ^11, ^3
+%%%
+%%% 11:
+%%% ret `false`
+%%%
+%%% 3:
+%%% %% Generate function clause error.
+%%% . . .
+%%%
+%%% This sub pass will keep track of all tests that are known to have
+%%% been executed at each block in the SSA code. If a repeated or
+%%% inverted test is seen, it can be eliminated. For the example
+%%% above, this sub pass will rewrite block 4 like this:
+%%%
+%%% 4:
+%%% _4 = bif:'=:=' `true`, `true`
+%%% br ^15
+%%%
+%%% This sub pass also removes redundant inverted test such as the
+%%% last test in this code:
+%%%
+%%% if
+%%% A < B -> . . . ;
+%%% A >= B -> . . .
+%%% end
+%%%
+%%% and this code:
+%%%
+%%% if
+%%% A < B -> . . . ;
+%%% A > B -> . . . ;
+%%% A == B -> . . .
+%%% end
+%%%
+
+opt_redundant_tests(Blocks) ->
+ All = #{0 => #{}, ?EXCEPTION_BLOCK => #{}},
+ RPO = beam_ssa:rpo(Blocks),
+ Linear = opt_redundant_tests(RPO, Blocks, All),
+ beam_ssa:trim_unreachable(Linear).
+
+opt_redundant_tests([L|Ls], Blocks, All0) ->
+ case All0 of
+ #{L := Tests} ->
+ Blk0 = map_get(L, Blocks),
+ Tests = map_get(L, All0),
+ Blk1 = opt_switch(Blk0, Tests),
+ #b_blk{is=Is0} = Blk1,
+ case opt_redundant_tests_is(Is0, Tests, []) of
+ none ->
+ All = update_successors(Blk1, Tests, All0),
+ [{L,Blk1}|opt_redundant_tests(Ls, Blocks, All)];
+ {new_test,Bool,Test,MustInvert} ->
+ All = update_successors(Blk1, Bool, Test, MustInvert,
+ Tests, All0),
+ [{L,Blk1}|opt_redundant_tests(Ls, Blocks, All)];
+ {old_test,Is,BoolVar,BoolValue} ->
+ Blk = case Blk1 of
+ #b_blk{last=#b_br{bool=BoolVar}=Br0} ->
+ Br = beam_ssa:normalize(Br0#b_br{bool=BoolValue}),
+ Blk1#b_blk{is=Is,last=Br};
+ #b_blk{}=Blk2 ->
+ Blk2#b_blk{is=Is}
+ end,
+ All = update_successors(Blk, Tests, All0),
+ [{L,Blk}|opt_redundant_tests(Ls, Blocks, All)]
+ end;
+ #{} ->
+ opt_redundant_tests(Ls, Blocks, All0)
+ end;
+opt_redundant_tests([], _Blocks, _All) -> [].
+
+opt_switch(#b_blk{last=#b_switch{arg=Arg,list=List0}=Sw}=Blk, Tests)
+ when map_size(Tests) =/= 0 ->
+ List = opt_switch_1(List0, Arg, Tests),
+ Blk#b_blk{last=Sw#b_switch{list=List}};
+opt_switch(Blk, _Tests) -> Blk.
+
+opt_switch_1([{Lit,_}=H|T], Arg, Tests) ->
+ case Tests of
+ #{{'=:=',Arg,Lit} := false} ->
+ opt_switch_1(T, Arg, Tests);
+ #{} ->
+ [H|opt_switch_1(T, Arg, Tests)]
+ end;
+opt_switch_1([], _, _) -> [].
+
+opt_redundant_tests_is([#b_set{op=Op,args=Args,dst=Bool}=I0], Tests, Acc) ->
+ case canonical_test(Op, Args) of
+ none ->
+ none;
+ {Test,MustInvert} ->
+ case old_result(Test, Tests) of
+ Result0 when is_boolean(Result0) ->
+ Result = #b_literal{val=Result0 xor MustInvert},
+ I = I0#b_set{op={bif,'=:='},args=[Result,#b_literal{val=true}]},
+ {old_test,reverse(Acc, [I]),Bool,Result};
+ none ->
+ {new_test,Bool,Test,MustInvert}
+ end
+ end;
+opt_redundant_tests_is([I|Is], Tests, Acc) ->
+ opt_redundant_tests_is(Is, Tests, [I|Acc]);
+opt_redundant_tests_is([], _Tests, _Acc) -> none.
+
+old_result(Test, Tests) ->
+ case Tests of
+ #{Test := Val} -> Val;
+ #{} -> old_result_1(Test, Tests)
+ end.
+
+%%
+%% Remove the last test in a sequence of tests (in any order):
+%%
+%% if
+%% Val1 < Val2 -> . . .
+%% Val1 > Val2 -> . . .
+%% Val1 == Val2 -> . . .
+%% end
+%%
+%% NOTE: The same optimization is not possible to do with `=:=`, unless
+%% we have type information so that we know that `==` and `=:=` produces
+%% the same result.
+%%
+
+old_result_1({'==',A,B}, Tests) ->
+ case Tests of
+ #{{'<',A,B} := false, {'=<',A,B} := true} ->
+ %% not A < B, not A > B ==> A == B
+ true;
+ #{} ->
+ none
+ end;
+old_result_1({'=<',A,B}, Tests) ->
+ case Tests of
+ #{{'<',A,B} := false, {'==',A,B} := false} ->
+ %% not A < B, not A == B ==> A > B
+ false;
+ #{} ->
+ none
+ end;
+old_result_1({'<',A,B}, Tests) ->
+ case Tests of
+ #{{'=<',A,B} := true, {'==',A,B} := false} ->
+ %% not A < B, not A == B ==> A < B
+ true;
+ #{} ->
+ none
+ end;
+old_result_1({is_nonempty_list,A}, Tests) ->
+ case Tests of
+ #{{is_list,A} := false} -> false;
+ #{} -> none
+ end;
+old_result_1(_, _) -> none.
+
+%% canonical_test(Op0, Args0) -> {CanonicalTest, MustInvert}
+%% CanonicalTest = {Operator,Variable,Variable|Literal} |
+%% {TypeTest,Variable}
+%% Operation = '<' | '=<' | '=:=' | '=='
+%% TypeTest = is_atom | is_integer ...
+%% Variable = #b_var{}
+%% Literal = #b_literal{}
+%% MustInvert = true | false
+%%
+%% Canonicalize a test. Always make the register
+%% operand the first operand. If there are two registers,
+%% order the registers in lexical order. Invert four of
+%% the relation operators and indicate with MustInvert
+%% whether the operator was inverted.
+%%
+%% For example, this instruction:
+%%
+%% #b_set{op={bif,'=:='},args=[#b_literal{}, #b_var{}}
+%%
+%% will be canonicalized to:
+%%
+%% {{'=:=',#b_var{},#b_literal{}}, false}
+%%
+%% while:
+%%
+%% #b_set{op={bif,'>'},args=[#b_var{}, #b_literal{}}}
+%%
+%% will be canonicalized to:
+%%
+%% {{'=<',#b_var{},#b_literal{}}, true}
+%%
+canonical_test(Op, Args) ->
+ case normalize_test(Op, Args) of
+ none ->
+ none;
+ Test ->
+ Inv = case Test of
+ {'=/=',_,_} -> true;
+ {'/=',_,_} -> true;
+ {'>',_,_} -> true;
+ {'>=',_,_} -> true;
+ _ -> false
+ end,
+ case Inv of
+ true -> {invert_test(Test),true};
+ false -> {Test,false}
+ end
+ end.
+
+update_successors(#b_blk{last=#b_br{bool=Bool,succ=Succ,fail=Fail}},
+ Bool, Test, MustInvert, Tests, All0) ->
+ All1 = update_successor(Succ, Tests#{Test => not MustInvert}, All0),
+ update_successor(Fail, Tests#{Test => MustInvert}, All1);
+update_successors(Blk, _, _, _, TestsA, All) ->
+ update_successors(Blk, TestsA, All).
+
+update_successors(#b_blk{last=#b_ret{}}, _Tests, All) ->
+ All;
+update_successors(#b_blk{last=#b_switch{arg=Arg,fail=Fail,list=List}},
+ Tests, All0) ->
+ All1 = update_successors_sw_fail(List, Arg, Fail, Tests, All0),
+ update_successors_sw(List, Arg, Tests, All1);
+update_successors(Blk, Tests, All) ->
+ foldl(fun(L, A) ->
+ update_successor(L, Tests, A)
+ end, All, beam_ssa:successors(Blk)).
+
+update_successors_sw_fail(List, Arg, Fail, Tests0, All) ->
+ Tests = foldl(fun({Lit,_}, A) ->
+ A#{{'=:=',Arg,Lit} => false}
+ end, Tests0, List),
+ update_successor(Fail, Tests, All).
+
+update_successors_sw([{Lit,L}|T], Arg, Tests, All0) ->
+ All = update_successor(L, Tests#{{'=:=',Arg,Lit} => true}, All0),
+ update_successors_sw(T, Arg, Tests, All);
+update_successors_sw([], _, _, All) -> All.
+
+update_successor(?EXCEPTION_BLOCK, _Tests, All) ->
+ All;
+update_successor(L, TestsA, All0) ->
+ case All0 of
+ #{L := TestsB} ->
+ All0#{L := maps_intersect_kv(TestsA, TestsB)};
+ #{} ->
+ All0#{L => TestsA}
+ end.
+
+maps_intersect_kv(Map, Map) ->
+ Map;
+maps_intersect_kv(Map1, Map2) ->
+ if
+ map_size(Map1) < map_size(Map2) ->
+ map_intersect_kv_1(Map1, Map2);
+ true ->
+ map_intersect_kv_1(Map2, Map1)
+ end.
+
+map_intersect_kv_1(SmallMap, BigMap) ->
+ Next = maps:next(maps:iterator(SmallMap)),
+ case maps_is_subset_kv(Next, BigMap) of
+ true -> SmallMap;
+ false -> map_intersect_kv_2(Next, BigMap, [])
+ end.
+
+map_intersect_kv_2({K, V, Iterator}, BigMap, Acc) ->
+ Next = maps:next(Iterator),
+ case BigMap of
+ #{K := V} ->
+ map_intersect_kv_2(Next, BigMap, [{K,V}|Acc]);
+ #{} ->
+ map_intersect_kv_2(Next, BigMap, Acc)
+ end;
+map_intersect_kv_2(none, _BigMap, Acc) ->
+ maps:from_list(Acc).
+
+maps_is_subset_kv({K, V, Iterator}, BigMap) ->
+ Next = maps:next(Iterator),
+ case BigMap of
+ #{K := V} ->
+ maps_is_subset_kv(Next, BigMap);
+ #{} ->
+ false
+ end;
+maps_is_subset_kv(none, _BigMap) -> true.
+
%%%
%%% Calculate used variables for each block.
%%%
diff --git a/lib/compiler/src/beam_ssa_funs.erl b/lib/compiler/src/beam_ssa_funs.erl
deleted file mode 100644
index a7b648bc47..0000000000
--- a/lib/compiler/src/beam_ssa_funs.erl
+++ /dev/null
@@ -1,152 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%%
-%%% If a fun is defined locally and only used for calls, it can be replaced
-%%% with direct calls to the relevant function. This greatly speeds up "named
-%%% functions" (which rely on make_fun to recreate themselves) and macros that
-%%% wrap their body in a fun.
-%%%
-
--module(beam_ssa_funs).
-
--export([module/2]).
-
--include("beam_ssa.hrl").
-
--import(lists, [foldl/3]).
-
--spec module(Module, Options) -> Result when
- Module :: beam_ssa:b_module(),
- Options :: [compile:option()],
- Result :: {ok, beam_ssa:b_module()}.
-
-module(#b_module{body=Fs0}=Module, _Opts) ->
- Trampolines = foldl(fun find_trampolines/2, #{}, Fs0),
- Fs = [lfo(F, Trampolines) || F <- Fs0],
- {ok, Module#b_module{body=Fs}}.
-
-%% If a function does absolutely nothing beyond calling another function with
-%% the same arguments in the same order, we can shave off a call by short-
-%% circuiting it.
-find_trampolines(#b_function{args=Args,bs=Blocks}=F, Trampolines) ->
- case map_get(0, Blocks) of
- #b_blk{is=[#b_set{op=call,
- args=[#b_local{}=Actual | Args],
- dst=Dst}],
- last=#b_ret{arg=Dst}} ->
- {_, Name, Arity} = beam_ssa:get_anno(func_info, F),
- Trampoline = #b_local{name=#b_literal{val=Name},arity=Arity},
- Trampolines#{Trampoline => Actual};
- _ ->
- Trampolines
- end.
-
-lfo(#b_function{bs=Blocks0}=F, Trampolines) ->
- Linear0 = beam_ssa:linearize(Blocks0),
- Linear = lfo_optimize(Linear0, lfo_analyze(Linear0, #{}), Trampolines),
- F#b_function{bs=maps:from_list(Linear)}.
-
-%% Gather a map of the locally defined funs that are only used for calls.
-lfo_analyze([{_L,#b_blk{is=Is,last=Last}}|Bs], LFuns0) ->
- LFuns = lfo_analyze_last(Last, lfo_analyze_is(Is, LFuns0)),
- lfo_analyze(Bs, LFuns);
-lfo_analyze([], LFuns) ->
- LFuns.
-
-lfo_analyze_is([#b_set{op=make_fun,
- dst=Dst,
- args=[#b_local{} | FreeVars]}=Def | Is],
- LFuns0) ->
- LFuns = maps:put(Dst, Def, maps:without(FreeVars, LFuns0)),
- lfo_analyze_is(Is, LFuns);
-lfo_analyze_is([#b_set{op=call,
- args=[Fun | CallArgs]} | Is],
- LFuns) when is_map_key(Fun, LFuns) ->
- #b_set{args=[#b_local{arity=Arity} | FreeVars]} = map_get(Fun, LFuns),
- case length(CallArgs) + length(FreeVars) of
- Arity ->
- lfo_analyze_is(Is, maps:without(CallArgs, LFuns));
- _ ->
- %% This will `badarity` at runtime, and it's easier to disable the
- %% optimization than to simulate it.
- lfo_analyze_is(Is, maps:without([Fun | CallArgs], LFuns))
- end;
-lfo_analyze_is([#b_set{args=Args} | Is], LFuns) when map_size(LFuns) =/= 0 ->
- %% We disqualify funs that are used outside calls because this forces them
- %% to be created anyway, and the slight performance gain from direct calls
- %% is not enough to offset the potential increase in stack frame size (the
- %% free variables need to be kept alive until the call).
- lfo_analyze_is(Is, maps:without(Args, LFuns));
-lfo_analyze_is([_ | Is], LFuns) ->
- lfo_analyze_is(Is, LFuns);
-lfo_analyze_is([], LFuns) ->
- LFuns.
-
-lfo_analyze_last(#b_switch{arg=Arg}, LFuns) ->
- maps:remove(Arg, LFuns);
-lfo_analyze_last(#b_ret{arg=Arg}, LFuns) ->
- maps:remove(Arg, LFuns);
-lfo_analyze_last(_, LFuns) ->
- LFuns.
-
-%% Replace all calls of suitable funs with a direct call to their
-%% implementation. Liveness optimization will get rid of the make_fun
-%% instruction.
-lfo_optimize(Linear, LFuns, _Trampolines) when map_size(LFuns) =:= 0 ->
- Linear;
-lfo_optimize(Linear, LFuns, Trampolines) ->
- lfo_optimize_1(Linear, LFuns, Trampolines).
-
-lfo_optimize_1([{L,#b_blk{is=Is0}=Blk}|Bs], LFuns, Trampolines) ->
- Is = lfo_optimize_is(Is0, LFuns, Trampolines),
- [{L,Blk#b_blk{is=Is}} | lfo_optimize_1(Bs, LFuns, Trampolines)];
-lfo_optimize_1([], _LFuns, _Trampolines) ->
- [].
-
-lfo_optimize_is([#b_set{op=call,
- args=[Fun | CallArgs]}=Call0 | Is],
- LFuns, Trampolines) when is_map_key(Fun, LFuns) ->
- #b_set{args=[Local | FreeVars]} = map_get(Fun, LFuns),
- Args = [lfo_short_circuit(Local, Trampolines) | CallArgs ++ FreeVars],
- Call = beam_ssa:add_anno(local_fun_opt, Fun, Call0#b_set{args=Args}),
- [Call | lfo_optimize_is(Is, LFuns, Trampolines)];
-lfo_optimize_is([I | Is], LFuns, Trampolines) ->
- [I | lfo_optimize_is(Is, LFuns, Trampolines)];
-lfo_optimize_is([], _LFuns, _Trampolines) ->
- [].
-
-lfo_short_circuit(Call, Trampolines) ->
- lfo_short_circuit(Call, Trampolines, sets:new([{version, 2}])).
-
-lfo_short_circuit(Call, Trampolines, Seen0) ->
- %% Beware of infinite loops! Get out if this call has been seen before.
- case sets:is_element(Call, Seen0) of
- true ->
- Call;
- false ->
- case Trampolines of
- #{Call := Other} ->
- Seen = sets:add_element(Call, Seen0),
- lfo_short_circuit(Other, Trampolines, Seen);
- #{} ->
- Call
- end
- end.
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
index eadbb3cc2b..e10189afd8 100644
--- a/lib/compiler/src/beam_ssa_opt.erl
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@
-include("beam_ssa_opt.hrl").
--import(lists, [all/2,append/1,duplicate/2,flatten/1,foldl/3,
+-import(lists, [all/2,append/1,droplast/1,duplicate/2,flatten/1,foldl/3,
keyfind/3,last/1,mapfoldl/3,member/2,
partition/2,reverse/1,reverse/2,
splitwith/2,sort/1,takewhile/2,unzip/1]).
@@ -124,93 +124,79 @@ phase([], _Ps, StMap, FuncDb) ->
{StMap, FuncDb}.
changed(PrevIds, FuncDb0, FuncDb, StMap0, StMap) ->
- %% Find all functions in FuncDb that can be reached by changes
- %% of argument and/or return types. Those are the functions that
- %% may gain from running the optimization passes again.
- %%
- %% Note that we examine all functions in FuncDb, not only functions
- %% optimized in the previous run, because the argument types can
- %% have been updated for functions not included in the previous run.
-
- F = fun(Id, A) ->
- case sets:is_element(Id, A) of
- true ->
- A;
- false ->
- {#func_info{arg_types=ATs0,succ_types=ST0},
- #func_info{arg_types=ATs1,succ_types=ST1}} =
- {map_get(Id, FuncDb0),map_get(Id, FuncDb)},
-
- %% If the argument types have changed for this
- %% function, re-optimize this function and all
- %% functions it calls directly or indirectly.
- %%
- %% If the return type has changed, re-optimize
- %% this function and all functions that call
- %% this function directly or indirectly.
- Opts = case ATs0 =:= ATs1 of
- true -> [];
- false -> [called]
- end ++
- case ST0 =:= ST1 of
- true -> [];
- false -> [callers]
- end,
- case Opts of
- [] -> A;
- [_|_] -> add_changed([Id], Opts, FuncDb, A)
- end
- end
- end,
- Ids = foldl(F, sets:new([{version, 2}]), maps:keys(FuncDb)),
-
- %% From all functions that were optimized in the previous run,
- %% find the functions that had any change in the SSA code. Those
- %% functions might gain from being optimized again. (For example,
- %% when beam_ssa_dead has shortcut branches, the types for some
- %% variables could become narrower, giving beam_ssa_type new
- %% opportunities for optimization.)
+ EmptySet = sets:new([{version,2}]),
+ Changed0 = changed_types(PrevIds, FuncDb0, FuncDb, EmptySet, EmptySet),
+
+ %% From all functions that were optimized in the previous run, find the
+ %% functions that had any change in the SSA code. Those functions might
+ %% gain from being optimized again. (For example, when beam_ssa_dead has
+ %% shortcut branches, the types for some variables could become narrower,
+ %% giving beam_ssa_type new opportunities for optimization.)
%%
%% Note that the functions examined could be functions with module-level
%% optimization turned off (and thus not included in FuncDb).
-
- foldl(fun(Id, A) ->
- case sets:is_element(Id, A) of
+ foldl(fun(Id, Changed) ->
+ case sets:is_element(Id, Changed) of
true ->
%% Already scheduled for another optimization.
%% No need to compare the SSA code.
- A;
+ Changed;
false ->
%% Compare the SSA code before and after optimization.
- case {map_get(Id, StMap0),map_get(Id, StMap)} of
- {Same,Same} -> A;
- {_,_} -> sets:add_element(Id, A)
+ case {map_get(Id, StMap0), map_get(Id, StMap)} of
+ {Same, Same} -> Changed;
+ {_,_} -> sets:add_element(Id, Changed)
end
end
- end, Ids, PrevIds).
+ end, Changed0, PrevIds).
-add_changed([Id|Ids], Opts, FuncDb, S0) when is_map_key(Id, FuncDb) ->
- case sets:is_element(Id, S0) of
+%% Find all functions in FuncDb that can be reached by changes of argument
+%% and/or return types. Those are the functions that may gain from running the
+%% optimization passes again.
+%%
+%% Note that we examine all functions in FuncDb, not only functions optimized
+%% in the previous run, because the argument types may have been updated for
+%% functions not included in the previous run.
+changed_types([Id | Ids], Fdb0, Fdb, In0, Out0) ->
+ case {Fdb0, Fdb} of
+ {#{ Id := #func_info{arg_types=ATs0,succ_types=ST0} },
+ #{ Id := #func_info{arg_types=ATs,succ_types=ST} }} ->
+ In = case ST0 =:= ST of
+ true -> In0;
+ false -> changed_types_1([Id], #func_info.in, Fdb, In0)
+ end,
+ Out = case ATs0 =:= ATs of
+ true -> Out0;
+ false -> changed_types_1([Id], #func_info.out, Fdb, Out0)
+ end,
+ changed_types(Ids, Fdb0, Fdb, In, Out);
+ _ ->
+ %% This function is exempt from module-level optimization and will
+ %% not provide any more information.
+ changed_types(Ids, Fdb0, Fdb, In0, Out0)
+ end;
+changed_types([], _Fdb0, _Fdb, In, Out) ->
+ sets:union(In, Out).
+
+changed_types_1([Id | Ids], Direction, Fdb, Seen0) ->
+ case sets:is_element(Id, Seen0) of
true ->
- add_changed(Ids, Opts, FuncDb, S0);
+ changed_types_1(Ids, Direction, Fdb, Seen0);
false ->
- S1 = sets:add_element(Id, S0),
- #func_info{in=In,out=Out} = map_get(Id, FuncDb),
- S2 = case member(callers, Opts) of
- true -> add_changed(In, Opts, FuncDb, S1);
- false -> S1
- end,
- S = case member(called, Opts) of
- true -> add_changed(Out, Opts, FuncDb, S2);
- false -> S2
- end,
- add_changed(Ids, Opts, FuncDb, S)
+ case Fdb of
+ #{ Id := FuncInfo } ->
+ Next = element(Direction, FuncInfo),
+
+ Seen1 = sets:add_element(Id, Seen0),
+ Seen2 = changed_types_1(Next, Direction, Fdb, Seen1),
+ changed_types_1(Ids, Direction, Fdb, Seen2);
+ #{} ->
+ changed_types_1(Ids, Direction, Fdb, Seen0)
+ end
end;
-add_changed([_|Ids], Opts, FuncDb, S) ->
- %% This function is exempt from module-level optimization and will not
- %% provide any more information.
- add_changed(Ids, Opts, FuncDb, S);
-add_changed([], _, _, S) -> S.
+changed_types_1([], _, _, Seen) ->
+ Seen.
+
%%
@@ -277,7 +263,7 @@ module_passes(Opts) ->
repeated_passes(Opts) ->
Ps = [?PASS(ssa_opt_live),
?PASS(ssa_opt_ne),
- ?PASS(ssa_opt_bs_puts),
+ ?PASS(ssa_opt_bs_create_bin),
?PASS(ssa_opt_dead),
?PASS(ssa_opt_cse),
?PASS(ssa_opt_tail_phis),
@@ -301,11 +287,13 @@ epilogue_passes(Opts) ->
?PASS(ssa_opt_bsm_shortcut),
?PASS(ssa_opt_sink),
?PASS(ssa_opt_blockify),
+ ?PASS(ssa_opt_redundant_br),
?PASS(ssa_opt_merge_blocks),
?PASS(ssa_opt_get_tuple_element),
- ?PASS(ssa_opt_tail_calls),
+ ?PASS(ssa_opt_tail_literals),
?PASS(ssa_opt_trim_unreachable),
- ?PASS(ssa_opt_unfold_literals)],
+ ?PASS(ssa_opt_unfold_literals),
+ ?PASS(ssa_opt_ranges)],
passes_1(Ps, Opts).
passes_1(Ps, Opts0) ->
@@ -407,12 +395,7 @@ fdb_update(Caller, Callee, FuncDb) ->
get_call_order_po(StMap, FuncDb) ->
Order = gco_po(FuncDb),
- Order ++ maps:fold(fun(K, _V, Acc) ->
- case is_map_key(K, FuncDb) of
- false -> [K | Acc];
- true -> Acc
- end
- end, [], StMap).
+ Order ++ sort([K || K <- maps:keys(StMap), not is_map_key(K, FuncDb)]).
gco_po(FuncDb) ->
All = sort(maps:keys(FuncDb)),
@@ -461,6 +444,9 @@ ssa_opt_merge_blocks({#opt_st{ssa=Blocks0}=St, FuncDb}) ->
Blocks = beam_ssa:merge_blocks(RPO, Blocks0),
{St#opt_st{ssa=Blocks}, FuncDb}.
+ssa_opt_ranges({#opt_st{ssa=Blocks}=St, FuncDb}) ->
+ {St#opt_st{ssa=beam_ssa_type:opt_ranges(Blocks)}, FuncDb}.
+
%%%
%%% Split blocks before certain instructions to enable more optimizations.
%%%
@@ -1019,7 +1005,7 @@ cse_add_inferred_exprs(#b_set{op={bif,tl},dst=Tl,args=[List]}, Es) ->
Es#{{get_tl,[List]} => Tl};
cse_add_inferred_exprs(#b_set{op={bif,map_get},dst=Value,args=[Key,Map]}, Es) ->
Es#{{get_map_element,[Map,Key]} => Value};
-cse_add_inferred_exprs(#b_set{op=put_map,dst=Map,args=Args}, Es) ->
+cse_add_inferred_exprs(#b_set{op=put_map,dst=Map,args=[_,_|Args]}, Es) ->
cse_add_map_get(Args, Map, Es);
cse_add_inferred_exprs(_, Es) -> Es.
@@ -1070,20 +1056,22 @@ cse_suitable(#b_set{}) -> false.
%%% will take special care to keep not using them in guards. Using
%%% them in guards would require a new version of the 'fconv'
%%% instruction that would take a failure label. Since it is unlikely
-%%% that using float instructions in guards would be benefical, why
+%%% that using float instructions in guards would be beneficial, why
%%% bother implementing a new instruction?
%%%
-record(fs,
{regs=#{} :: #{beam_ssa:b_var():=beam_ssa:b_var()},
non_guards :: gb_sets:set(beam_ssa:label()),
- bs :: beam_ssa:block_map()
+ bs :: beam_ssa:block_map(),
+ preds :: #{beam_ssa:label() => [beam_ssa:label()]}
}).
ssa_opt_float({#opt_st{ssa=Linear0,cnt=Count0}=St, FuncDb}) ->
NonGuards = non_guards(Linear0),
Blocks = maps:from_list(Linear0),
- Fs = #fs{non_guards=NonGuards,bs=Blocks},
+ Preds = beam_ssa:predecessors(Blocks),
+ Fs = #fs{non_guards=NonGuards,bs=Blocks,preds=Preds},
{Linear,Count} = float_opt(Linear0, Count0, Fs),
{St#opt_st{ssa=Linear,cnt=Count}, FuncDb}.
@@ -1122,7 +1110,7 @@ float_opt_1(L, #b_blk{is=Is0}=Blk0, Bs0, Count0, Fs0) ->
end.
%% Split out {float,convert} instructions into separate blocks, number
-%% the blocks, and add {succeded,body} in each {float,convert} block.
+%% the blocks, and add {succeeded,body} in each {float,convert} block.
float_fixup_conv(L, Is, Blk, Count0) ->
Split = float_split_conv(Is, Blk),
{Blks,Count} = float_number(Split, L, Count0),
@@ -1207,9 +1195,15 @@ float_maybe_flush(Blk0, Fs0, Count0) ->
{FlushBs,Blk,Fs,Count}
end.
-float_safe_to_skip_flush(L, #fs{bs=Blocks}=Fs) ->
+float_safe_to_skip_flush(L, #fs{bs=Blocks,preds=Preds}=Fs) ->
#b_blk{is=Is} = Blk = map_get(L, Blocks),
- float_can_optimize_blk(Blk, Fs) andalso float_optimizable_is(Is).
+ case Preds of
+ #{L := [_]} ->
+ float_can_optimize_blk(Blk, Fs) andalso float_optimizable_is(Is);
+ #{} ->
+ %% This block can be reached from more than one block; must flush.
+ false
+ end.
float_optimizable_is([#b_set{anno=#{float_op:=_}}|_]) ->
true;
@@ -1232,9 +1226,12 @@ float_opt_is([#b_set{op={succeeded,_},args=[Src]}=I0],
float_opt_is([#b_set{anno=Anno0}=I0|Is0], Fs0, Count0, Acc) ->
case Anno0 of
#{float_op:=FTypes} ->
- Anno = maps:remove(float_op, Anno0),
+ ArgTypes0 = maps:get(arg_types, Anno0, #{}),
+ ArgTypes = float_arg_types(FTypes, 0, ArgTypes0),
+ Anno1 = maps:remove(float_op, Anno0),
+ Anno = maps:remove(arg_types, Anno1),
I1 = I0#b_set{anno=Anno},
- {Is,Fs,Count} = float_make_op(I1, FTypes, Fs0, Count0),
+ {Is,Fs,Count} = float_make_op(I1, FTypes, ArgTypes, Fs0, Count0),
float_opt_is(Is0, Fs, Count, reverse(Is, Acc));
#{} ->
float_opt_is(Is0, Fs0, Count0, [I0|Acc])
@@ -1242,9 +1239,18 @@ float_opt_is([#b_set{anno=Anno0}=I0|Is0], Fs0, Count0, Acc) ->
float_opt_is([], _Fs, _Count, _Acc) ->
none.
+float_arg_types([_|As], Index, ArgTypes) ->
+ case ArgTypes of
+ #{Index := ArgType} ->
+ [ArgType|float_arg_types(As, Index + 1, ArgTypes)];
+ #{} ->
+ [any|float_arg_types(As, Index + 1, ArgTypes)]
+ end;
+float_arg_types([], _, _) -> [].
+
float_make_op(#b_set{op={bif,Op},dst=Dst,args=As0,anno=Anno}=I0,
- Ts, #fs{regs=Rs0}=Fs, Count0) ->
- {As1,Rs1,Count1} = float_load(As0, Ts, Anno, Rs0, Count0, []),
+ Ts, ArgTypes, #fs{regs=Rs0}=Fs, Count0) ->
+ {As1,Rs1,Count1} = float_load(As0, Ts, ArgTypes, Anno, Rs0, Count0, []),
{As,Is0} = unzip(As1),
{FrDst,Count2} = new_var('@fr', Count1),
I = I0#b_set{op={float,Op},dst=FrDst,args=As},
@@ -1252,19 +1258,23 @@ float_make_op(#b_set{op={bif,Op},dst=Dst,args=As0,anno=Anno}=I0,
Is = append(Is0) ++ [I],
{Is,Fs#fs{regs=Rs},Count2}.
-float_load([A|As], [T|Ts], Anno, Rs0, Count0, Acc) ->
- {Load,Rs,Count} = float_reg_arg(A, T, Anno, Rs0, Count0),
- float_load(As, Ts, Anno, Rs, Count, [Load|Acc]);
-float_load([], [], _Anno, Rs, Count, Acc) ->
+float_load([A|As], [T|Ts], [AT|ATs], Anno, Rs0, Count0, Acc) ->
+ {Load,Rs,Count} = float_reg_arg(A, T, AT, Anno, Rs0, Count0),
+ float_load(As, Ts, ATs, Anno, Rs, Count, [Load|Acc]);
+float_load([], [], [], _Anno, Rs, Count, Acc) ->
{reverse(Acc),Rs,Count}.
-float_reg_arg(A, T, Anno, Rs, Count0) ->
+float_reg_arg(A, T, AT, Anno0, Rs, Count0) ->
case Rs of
#{A:=Fr} ->
{{Fr,[]},Rs,Count0};
#{} ->
{Dst,Count} = new_var('@fr_copy', Count0),
I0 = float_load_reg(T, A, Dst),
+ Anno = case AT of
+ any-> Anno0;
+ _ -> Anno0#{arg_types => #{0 => AT}}
+ end,
I = I0#b_set{anno=Anno},
{{Dst,[I]},Rs#{A=>Dst},Count}
end.
@@ -1419,18 +1429,97 @@ live_opt_is([], Live, Acc) ->
%%%
%%% try/catch optimization.
%%%
-%%% Attemps to rewrite try/catches as guards when we know the exception won't
+%%% Attempts to rewrite try/catches as guards when we know the exception won't
%%% be inspected in any way, and removes try/catches whose expressions will
%%% never throw.
%%%
-ssa_opt_try({#opt_st{ssa=Linear0}=St, FuncDb}) ->
- RevLinear = reduce_try(Linear0, []),
+ssa_opt_try({#opt_st{ssa=Linear,cnt=Count0}=St, FuncDb}) ->
+ {Count, Shrunk} = shrink_try(Linear, Count0, []),
+
+ Reduced = reduce_try(Shrunk, []),
EmptySet = sets:new([{version, 2}]),
- Linear = trim_try(RevLinear, EmptySet, EmptySet, []),
+ Trimmed = trim_try(Reduced, EmptySet, EmptySet, []),
- {St#opt_st{ssa=Linear}, FuncDb}.
+ {St#opt_st{ssa=Trimmed,cnt=Count}, FuncDb}.
+
+%% Moves all leading/trailing instructions that cannot fail out of try/catch
+%% expressions. For example, we can move the tuple constructions `{defg,Arg}`
+%% and `{hijk,A}` out of the `try` in the code below:
+%%
+%% try
+%% A = abcd({defg,Arg}),
+%% ... snip ...
+%% {hijk,A}
+%% catch
+%% ... snip ...
+%% end.
+shrink_try([{TryLbl0, #b_blk{is=[#b_set{op=new_try_tag,dst=Dst}],
+ last=#b_br{bool=Dst,succ=SuccLbl}}=TryBlk},
+ {SuccLbl, #b_blk{is=SuccIs0,last=SuccLast}=SuccBlk0} | Bs],
+ Count0, Acc0) ->
+ %% Hoist leading known-safe instructions before `new_try_tag` instructions.
+ {HoistIs, SuccIs} = hoist_try_is(SuccIs0, SuccLast, Dst, []),
+
+ HoistLbl = TryLbl0,
+ TryLbl = Count0,
+ Count = Count0 + 1,
+
+ HoistBlk = #b_blk{is=HoistIs,
+ last=#b_br{bool=#b_literal{val=true},
+ succ=TryLbl,
+ fail=TryLbl}},
+ SuccBlk = SuccBlk0#b_blk{is=SuccIs},
+
+ Acc = [{TryLbl, TryBlk},
+ {HoistLbl, HoistBlk} | Acc0],
+
+ shrink_try([{SuccLbl, SuccBlk} | Bs], Count, Acc);
+shrink_try([{L, #b_blk{is=Is}=Blk0} | Bs], Count, Acc) ->
+ Blk = Blk0#b_blk{is=sink_try_is(Is)},
+ shrink_try(Bs, Count, [{L, Blk} | Acc]);
+shrink_try([], Count, Acc) ->
+ {Count, reverse(Acc)}.
+
+hoist_try_is([#b_set{dst=Dst},
+ #b_set{op={succeeded,_},args=[Dst]}]=Is,
+ #b_br{}, _TryTag, HoistIs) ->
+ {reverse(HoistIs), Is};
+hoist_try_is([#b_set{dst=Dst}]=Is, #b_br{bool=Dst}, _TryTag, HoistIs) ->
+ {reverse(HoistIs), Is};
+hoist_try_is([#b_set{op=kill_try_tag,args=[TryTag]}=Kill | Rest],
+ Last, TryTag, HoistIs0) ->
+ %% We're killing the current try tag before we have a chance to throw an
+ %% exception. Hoist the rest of the block and keep this instruction in the
+ %% current block.
+ {HoistIs, Is} = hoist_try_is(Rest, Last, TryTag, []),
+ {reverse(HoistIs0, HoistIs), [Kill | Is]};
+hoist_try_is([#b_set{}=I | Is], Last, TryTag, HoistIs) ->
+ %% Note that we hoist instructions regardless of whether they side-effect
+ %% or not: as long as they don't throw an exception, we don't need to care
+ %% about side-effects as long as their order is unchanged.
+ hoist_try_is(Is, Last, TryTag, [I | HoistIs]);
+hoist_try_is([], _Last, _TryTag, HoistIs) ->
+ {reverse(HoistIs), []}.
+
+%% Moves trailing known-safe instructions past `kill_try_tag` instructions.
+sink_try_is([#b_set{op=landingpad} | _]=Is) ->
+ Is;
+sink_try_is([#b_set{op=phi}=Phi | Is]) ->
+ [Phi | sink_try_is(Is)];
+sink_try_is(Is) ->
+ sink_try_is_1(Is, []).
+
+sink_try_is_1([#b_set{op=kill_try_tag}=Kill | Is], Acc) ->
+ [Kill | reverse(Acc, Is)];
+sink_try_is_1([I | Is], Acc) ->
+ case beam_ssa:no_side_effect(I) of
+ true -> sink_try_is_1(Is, [I | Acc]);
+ false -> reverse(Acc, [I | Is])
+ end;
+sink_try_is_1([], Acc) ->
+ reverse(Acc).
%% Does a strength reduction of try/catch and catch.
%%
@@ -1677,14 +1766,15 @@ coalesce_skips_is([#b_set{op=bs_match,
args=[#b_literal{val=skip},
Ctx0,Type,Flags,
#b_literal{val=Size0},
- #b_literal{val=Unit0}]}=Skip0,
+ #b_literal{val=Unit0}],
+ dst=Ctx}=Skip0,
#b_set{op={succeeded,guard}}],
#b_br{succ=L2,fail=Fail}=Br0,
Bs0) when is_integer(Size0) ->
case Bs0 of
[{L2,#b_blk{is=[#b_set{op=bs_match,
dst=SkipDst,
- args=[#b_literal{val=skip},_,_,_,
+ args=[#b_literal{val=skip},Ctx,_,_,
#b_literal{val=Size1},
#b_literal{val=Unit1}]},
#b_set{op={succeeded,guard}}=Succeeded],
@@ -1698,7 +1788,7 @@ coalesce_skips_is([#b_set{op=bs_match,
Is = [Skip,Succeeded],
{Is,Br,Bs};
[{L2,#b_blk{is=[#b_set{op=bs_test_tail,
- args=[_Ctx,#b_literal{val=TailSkip}]}],
+ args=[Ctx,#b_literal{val=TailSkip}]}],
last=#b_br{succ=NextSucc,fail=Fail}}}|Bs] ->
SkipBits = Size0 * Unit0,
TestTail = Skip0#b_set{op=bs_test_tail,
@@ -1787,105 +1877,74 @@ bsm_shortcut([], _PosMap) -> [].
%%% If an integer segment or a float segment has a literal size and
%%% a literal value, convert to a binary segment. Coalesce adjacent
%%% literal binary segments. Literal binary segments will be converted
-%%% to bs_put_string instructions in later pass.
+%%% to bs_put_string instructions in a later pass.
%%%
-ssa_opt_bs_puts({#opt_st{ssa=Linear0,cnt=Count0}=St, FuncDb}) ->
- {Linear,Count} = opt_bs_puts(Linear0, Count0, []),
- {St#opt_st{ssa=Linear,cnt=Count}, FuncDb}.
-
-opt_bs_puts([{L,#b_blk{is=Is}=Blk0}|Bs], Count0, Acc0) ->
- case Is of
- [#b_set{op=bs_put},#b_set{op={succeeded,_}}]=Is ->
- case opt_bs_put(L, Is, Blk0, Count0, Acc0) of
- not_possible ->
- opt_bs_puts(Bs, Count0, [{L,Blk0}|Acc0]);
- {Count,Acc1} ->
- Acc = opt_bs_puts_merge(Acc1),
- opt_bs_puts(Bs, Count, Acc)
- end;
- _ ->
- opt_bs_puts(Bs, Count0, [{L,Blk0}|Acc0])
- end;
-opt_bs_puts([], Count, Acc) ->
- {reverse(Acc),Count}.
-
-opt_bs_puts_merge([{L1,#b_blk{is=Is}=Blk0},{L2,#b_blk{is=AccIs}}=BAcc|Acc]) ->
- case {AccIs,Is} of
- {[#b_set{op=bs_put,
- args=[#b_literal{val=binary},
- #b_literal{},
- #b_literal{val=Bin0},
- #b_literal{val=all},
- #b_literal{val=1}]},
- #b_set{op={succeeded,_}}],
- [#b_set{op=bs_put,
- args=[#b_literal{val=binary},
- #b_literal{},
- #b_literal{val=Bin1},
- #b_literal{val=all},
- #b_literal{val=1}]}=I0,
- #b_set{op={succeeded,_}}=Succeeded]} ->
- %% Coalesce the two segments to one.
- Bin = <<Bin0/bitstring,Bin1/bitstring>>,
- I = I0#b_set{args=bs_put_args(binary, Bin, all)},
- Blk = Blk0#b_blk{is=[I,Succeeded]},
- [{L2,Blk}|Acc];
- {_,_} ->
- [{L1,Blk0},BAcc|Acc]
- end.
+ssa_opt_bs_create_bin({#opt_st{ssa=Linear0}=St, FuncDb}) ->
+ Linear = opt_create_bin_fs(Linear0),
+ {St#opt_st{ssa=Linear}, FuncDb}.
-opt_bs_put(L, [I0,Succeeded], #b_blk{last=Br0}=Blk0, Count0, Acc) ->
- case opt_bs_put(I0) of
- [Bin] when is_bitstring(Bin) ->
- Args = bs_put_args(binary, Bin, all),
- I = I0#b_set{args=Args},
- Blk = Blk0#b_blk{is=[I,Succeeded]},
- {Count0,[{L,Blk}|Acc]};
- [{int,Int,Size},Bin] when is_bitstring(Bin) ->
- %% Construct a bs_put_integer instruction following
- %% by a bs_put_binary instruction.
- IntArgs = bs_put_args(integer, Int, Size),
- BinArgs = bs_put_args(binary, Bin, all),
-
- {BinL,BinVarNum,BinBoolNum} = {Count0,Count0+1,Count0+2},
- Count = Count0 + 3,
- BinVar = #b_var{name={'@ssa_bs_put',BinVarNum}},
- BinBool = #b_var{name={'@ssa_bool',BinBoolNum}},
-
- BinI = I0#b_set{dst=BinVar,args=BinArgs},
- BinSucceeded = Succeeded#b_set{dst=BinBool,args=[BinVar]},
- BinBlk = Blk0#b_blk{is=[BinI,BinSucceeded],
- last=Br0#b_br{bool=BinBool}},
-
- IntI = I0#b_set{args=IntArgs},
- IntBlk = Blk0#b_blk{is=[IntI,Succeeded],last=Br0#b_br{succ=BinL}},
-
- {Count,[{BinL,BinBlk},{L,IntBlk}|Acc]};
+opt_create_bin_fs([{L,#b_blk{is=Is0}=Blk0}|Bs]) ->
+ Is = opt_create_bin_is(Is0),
+ Blk = Blk0#b_blk{is=Is},
+ [{L,Blk}|opt_create_bin_fs(Bs)];
+opt_create_bin_fs([]) -> [].
+
+opt_create_bin_is([#b_set{op=bs_create_bin,args=Args0}=I0|Is]) ->
+ Args = opt_create_bin_args(Args0),
+ I = I0#b_set{args=Args},
+ [I|opt_create_bin_is(Is)];
+opt_create_bin_is([I|Is]) ->
+ [I|opt_create_bin_is(Is)];
+opt_create_bin_is([]) -> [].
+
+opt_create_bin_args([#b_literal{val=binary},#b_literal{val=[1|_]},
+ #b_literal{val=Bin0},#b_literal{val=all},
+ #b_literal{val=binary},#b_literal{val=[1|_]},
+ #b_literal{val=Bin1},#b_literal{val=all}|Args0])
+ when is_bitstring(Bin0), is_bitstring(Bin1) ->
+ %% Coalesce two litary binary segments to one.
+ Bin = <<Bin0/bitstring,Bin1/bitstring>>,
+ Args = [#b_literal{val=binary},#b_literal{val=[1]},
+ #b_literal{val=Bin},#b_literal{val=all}|Args0],
+ opt_create_bin_args(Args);
+opt_create_bin_args([#b_literal{val=Type}=Type0,#b_literal{val=UFs}=UFs0,Val,Size|Args0]) ->
+ [Unit|Flags] = UFs,
+ case opt_create_bin_arg(Type, Unit, UFs, Val, Size) of
not_possible ->
- not_possible
- end.
-
-opt_bs_put(#b_set{args=[#b_literal{val=binary},_,#b_literal{val=Val},
- #b_literal{val=all},#b_literal{val=Unit}]})
- when is_bitstring(Val) ->
- if
- bit_size(Val) rem Unit =:= 0 ->
- [Val];
- true ->
- not_possible
- end;
-opt_bs_put(#b_set{args=[#b_literal{val=Type},#b_literal{val=Flags},
- #b_literal{val=Val},#b_literal{val=Size},
- #b_literal{val=Unit}]}=I0) when is_integer(Size) ->
+ [Type0,UFs0,Val,Size|opt_create_bin_args(Args0)];
+ [Bin] when is_bitstring(Bin) ->
+ Args = [#b_literal{val=binary},#b_literal{val=[1]},
+ #b_literal{val=Bin},#b_literal{val=all}|Args0],
+ opt_create_bin_args(Args);
+ [{int,Int,IntSize},Bin] when is_bitstring(Bin) ->
+ Args = [#b_literal{val=integer},#b_literal{val=[1|Flags]},
+ #b_literal{val=Int},#b_literal{val=IntSize},
+ #b_literal{val=binary},#b_literal{val=[1]},
+ #b_literal{val=Bin},#b_literal{val=all}|Args0],
+ opt_create_bin_args(Args)
+ end;
+opt_create_bin_args([]) -> [].
+
+opt_create_bin_arg(binary, Unit, _Flags, #b_literal{val=Val}, #b_literal{val=all})
+ when Unit =/= 1, bit_size(Val) rem Unit =:= 0 ->
+ [Val];
+opt_create_bin_arg(Type, Unit, Flags, #b_literal{val=Val}, #b_literal{val=Size})
+ when is_integer(Size), is_integer(Unit) ->
EffectiveSize = Size * Unit,
if
EffectiveSize > 0 ->
- case {Type,opt_bs_put_endian(Flags)} of
+ case {Type,opt_create_bin_endian(Flags)} of
{integer,big} when is_integer(Val) ->
if
EffectiveSize < 64 ->
[<<Val:EffectiveSize>>];
+ EffectiveSize > 1 bsl 24 ->
+ %% The binary construction could fail with a
+ %% system_limit. Don't optimize to ensure that
+ %% the extended error information will be
+ %% accurate.
+ not_possible;
true ->
opt_bs_put_split_int(Val, EffectiveSize)
end;
@@ -1893,9 +1952,8 @@ opt_bs_put(#b_set{args=[#b_literal{val=Type},#b_literal{val=Flags},
%% To avoid an explosion in code size, we only try
%% to optimize relatively small fields.
<<Int:EffectiveSize>> = <<Val:EffectiveSize/little>>,
- Args = bs_put_args(Type, Int, EffectiveSize),
- I = I0#b_set{args=Args},
- opt_bs_put(I);
+ opt_create_bin_arg(Type, 1, [], #b_literal{val=Int},
+ #b_literal{val=EffectiveSize});
{binary,_} when is_bitstring(Val) ->
case Val of
<<Bitstring:EffectiveSize/bits,_/bits>> ->
@@ -1906,8 +1964,14 @@ opt_bs_put(#b_set{args=[#b_literal{val=Type},#b_literal{val=Flags},
end;
{float,Endian} ->
try
- [opt_bs_put_float(Val, EffectiveSize, Endian)]
- catch error:_ ->
+ case Endian of
+ big ->
+ [<<Val:EffectiveSize/big-float-unit:1>>];
+ little ->
+ [<<Val:EffectiveSize/little-float-unit:1>>]
+ end
+ catch
+ error:_ ->
not_possible
end;
{_,_} ->
@@ -1916,25 +1980,12 @@ opt_bs_put(#b_set{args=[#b_literal{val=Type},#b_literal{val=Flags},
true ->
not_possible
end;
-opt_bs_put(#b_set{}) -> not_possible.
-
-opt_bs_put_float(N, Sz, Endian) ->
- case Endian of
- big -> <<N:Sz/big-float-unit:1>>;
- little -> <<N:Sz/little-float-unit:1>>
- end.
+opt_create_bin_arg(_, _, _, _, _) -> not_possible.
-bs_put_args(Type, Val, Size) ->
- [#b_literal{val=Type},
- #b_literal{val=[unsigned,big]},
- #b_literal{val=Val},
- #b_literal{val=Size},
- #b_literal{val=1}].
-
-opt_bs_put_endian([big=E|_]) -> E;
-opt_bs_put_endian([little=E|_]) -> E;
-opt_bs_put_endian([native=E|_]) -> E;
-opt_bs_put_endian([_|Fs]) -> opt_bs_put_endian(Fs).
+opt_create_bin_endian([little=E|_]) -> E;
+opt_create_bin_endian([native=E|_]) -> E;
+opt_create_bin_endian([_|Fs]) -> opt_create_bin_endian(Fs);
+opt_create_bin_endian([]) -> big.
opt_bs_put_split_int(Int, Size) ->
Pos = opt_bs_put_split_int_1(Int, 0, Size - 1),
@@ -2285,7 +2336,7 @@ do_ssa_opt_sink(Defs, #opt_st{ssa=Linear}=St) ->
%% It is not safe to move get_tuple_element instructions to blocks
%% that begin with certain instructions. It is also unsafe to move
%% the instructions into any part of a receive.
- Unsuitable = unsuitable(Linear, Blocks0),
+ Unsuitable = unsuitable(Linear, Blocks0, Preds),
%% Calculate new positions for get_tuple_element instructions. The new
%% position is a block that dominates all uses of the variable.
@@ -2467,13 +2518,12 @@ is_on_stack(From, Var, Blocks) ->
is_on_stack([L|Ls], Var, Blocks, WillGC0) ->
#b_blk{is=Is} = Blk = map_get(L, Blocks),
GC0 = map_get(L, WillGC0),
- try is_on_stack_is(Is, Var, GC0) of
+ case is_on_stack_is(Is, Var, GC0) of
+ {done,GC} ->
+ GC;
GC ->
WillGC = gc_update_successors(Blk, GC, WillGC0),
is_on_stack(Ls, Var, Blocks, WillGC)
- catch
- throw:{done,GC} ->
- GC
end;
is_on_stack([], _Var, _, _) -> false.
@@ -2482,7 +2532,7 @@ is_on_stack_is([#b_set{op=get_tuple_element}|Is], Var, GC) ->
is_on_stack_is([I|Is], Var, GC0) ->
case GC0 andalso member(Var, beam_ssa:used(I)) of
true ->
- throw({done,GC0});
+ {done,GC0};
false ->
GC = GC0 orelse beam_ssa:clobbers_xregs(I),
is_on_stack_is(Is, Var, GC)
@@ -2498,12 +2548,11 @@ gc_update_successors(Blk, GC, WillGC) ->
end
end, WillGC, beam_ssa:successors(Blk)).
-%% unsuitable(Linear, Blocks) -> Unsuitable.
-%% Return an ordset of block labels for the blocks that are not
+%% unsuitable(Linear, Blocks, Predecessors) -> Unsuitable.
+%% Return an gbset of block labels for the blocks that are not
%% suitable for sinking of get_tuple_element instructions.
-unsuitable(Linear, Blocks) ->
- Predecessors = beam_ssa:predecessors(Blocks),
+unsuitable(Linear, Blocks, Predecessors) ->
Unsuitable0 = unsuitable_1(Linear),
Unsuitable1 = unsuitable_recv(Linear, Blocks, Predecessors),
gb_sets:from_list(Unsuitable0 ++ Unsuitable1).
@@ -2511,7 +2560,6 @@ unsuitable(Linear, Blocks) ->
unsuitable_1([{L,#b_blk{is=[#b_set{op=Op}=I|_]}}|Bs]) ->
Unsuitable = case Op of
bs_extract -> true;
- bs_put -> true;
{float,_} -> true;
landingpad -> true;
_ -> beam_ssa:is_loop_header(I)
@@ -2740,33 +2788,21 @@ collect_get_tuple_element(Is, _Src, Acc) ->
%%% of the constant if the original variable is known to be in an x
%%% register.
%%%
-%%% This optimization sub pass will also undo constant folding of the
-%%% list of arguments in the call to error/2 in the last clause of a
-%%% function. For example:
-%%%
-%%% bar(X, Y) ->
-%%% error(function_clause, [X,42]).
-%%%
-%%% will be rewritten to:
-%%%
-%%% bar(X, Y) ->
-%%% error(function_clause, [X,Y]).
-%%%
ssa_opt_unfold_literals({St,FuncDb}) ->
- #opt_st{ssa=Blocks0,args=Args,anno=Anno,cnt=Count0} = St,
+ #opt_st{ssa=Blocks0,args=Args,anno=Anno} = St,
ParamInfo = maps:get(parameter_info, Anno, #{}),
LitMap = collect_arg_literals(Args, ParamInfo, 0, #{}),
case map_size(LitMap) of
0 ->
%% None of the arguments for this function are known
%% literals. Nothing to do.
- {St,FuncDb};
+ {St, FuncDb};
_ ->
SafeMap = #{0 => true},
- {Blocks,Count} = unfold_literals(beam_ssa:rpo(Blocks0),
- LitMap, SafeMap, Count0, Blocks0),
- {St#opt_st{ssa=Blocks,cnt=Count},FuncDb}
+ Blocks = unfold_literals(beam_ssa:rpo(Blocks0),
+ LitMap, SafeMap, Blocks0),
+ {St#opt_st{ssa=Blocks}, FuncDb}
end.
collect_arg_literals([V|Vs], Info, X, Acc0) ->
@@ -2784,72 +2820,51 @@ collect_arg_literals([V|Vs], Info, X, Acc0) ->
#{} ->
collect_arg_literals(Vs, Info, X + 1, Acc0)
end;
-collect_arg_literals([], _Info, _X, Acc) -> Acc.
+collect_arg_literals([], _Info, _X, Acc) ->
+ Acc.
-unfold_literals([L|Ls], LitMap, SafeMap0, Count0, Blocks0) ->
- {Blocks,Safe,Count} =
+unfold_literals([L|Ls], LitMap, SafeMap0, Blocks0) ->
+ {Blocks,Safe} =
case map_get(L, SafeMap0) of
false ->
%% Before reaching this block, an instruction that
- %% clobbers x registers has been executed. *If* we
+ %% clobbers x registers has been executed. *If* we
%% would use an argument variable instead of literal,
%% it would force the value to be saved to a y
%% register. This is not what we want.
- {Blocks0,false,Count0};
+ {Blocks0,false};
true ->
%% All x registers live when entering the function
%% are still live. Using the variable instead of
%% the substituted value will eliminate a `move`
%% instruction.
#b_blk{is=Is0} = Blk = map_get(L, Blocks0),
- {Is,Safe0,Count1} = unfold_lit_is(Is0, LitMap, Count0, []),
- {Blocks0#{L:=Blk#b_blk{is=Is}},Safe0,Count1}
+ {Is, Safe0} = unfold_lit_is(Is0, LitMap, []),
+ {Blocks0#{ L := Blk#b_blk{is=Is} }, Safe0}
end,
%% Propagate safeness to successors.
Successors = beam_ssa:successors(L, Blocks),
SafeMap = unfold_update_succ(Successors, Safe, SafeMap0),
- unfold_literals(Ls, LitMap, SafeMap, Count,Blocks);
-unfold_literals([], _, _, Count, Blocks) ->
- {Blocks,Count}.
+ unfold_literals(Ls, LitMap, SafeMap,Blocks);
+unfold_literals([], _, _, Blocks) ->
+ Blocks.
unfold_update_succ([S|Ss], Safe, SafeMap0) ->
F = fun(Prev) -> Prev and Safe end,
SafeMap = maps:update_with(S, F, Safe, SafeMap0),
unfold_update_succ(Ss, Safe, SafeMap);
-unfold_update_succ([], _, SafeMap) -> SafeMap.
-
-unfold_lit_is([#b_set{op=call,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error},
- arity=2},
- #b_literal{val=function_clause},
- ArgumentList]}=I0|Is], LitMap, Count0, Acc0) ->
- %% This is a call to error/2 that raises a function_clause
- %% exception in the final clause of a function. Try to undo
- %% constant folding in the list of arguments (the second argument
- %% for error/2).
- case unfold_arg_list(Acc0, ArgumentList, LitMap, Count0, 0, []) of
- {[FinalPutList|_]=Acc,Count} ->
- %% Acc now contains the possibly rewritten code that
- %% creates the argument list. All that remains is to
- %% rewrite the call to error/2 itself so that is will
- %% refer to rewritten argument list. This is essential
- %% when all arguments have known literal values as in this
- %% example:
- %%
- %% foo(X, Y) -> error(function_clause, [0,1]).
- %%
- #b_set{op=put_list,dst=ListVar} = FinalPutList,
- #b_set{args=[ErlangError,Fc,_]} = I0,
- I = I0#b_set{args=[ErlangError,Fc,ListVar]},
- {reverse(Acc, [I|Is]),false,Count};
- {[],_} ->
- %% Handle code such as:
- %%
- %% bar(KnownValue, Stk) -> error(function_clause, Stk).
- {reverse(Acc0, [I0|Is]),false,Count0}
- end;
-unfold_lit_is([#b_set{op=Op,args=Args0}=I0|Is], LitMap, Count, Acc) ->
+unfold_update_succ([], _, SafeMap) ->
+ SafeMap.
+
+unfold_lit_is([#b_set{op=match_fail,
+ args=[#b_literal{val=function_clause} | Args0]}=I0 | Is],
+ LitMap, Acc) ->
+ %% Undoing constant folding for this kind of failure lets us jump
+ %% directly to the `func_info` instruction.
+ Args = unfold_call_args(Args0, LitMap, 0),
+ I = I0#b_set{args=[#b_literal{val=function_clause} | Args]},
+ {reverse(Acc, [I | Is]), false};
+unfold_lit_is([#b_set{op=Op,args=Args0}=I0|Is], LitMap, Acc) ->
%% Using a register instead of a literal is a clear win only for
%% `call` and `old_make_fun` instructions. Substituting into other
%% instructions is unlikely to be an improvement.
@@ -2870,56 +2885,18 @@ unfold_lit_is([#b_set{op=Op,args=Args0}=I0|Is], LitMap, Count, Acc) ->
%% This instruction clobbers x register. Don't do
%% any substitutions in rest of this block or in any
%% of its successors.
- {reverse(Acc, [I|Is]),false,Count};
+ {reverse(Acc, [I|Is]), false};
false ->
- unfold_lit_is(Is, LitMap, Count, [I|Acc])
+ unfold_lit_is(Is, LitMap, [I|Acc])
end;
-unfold_lit_is([], _LitMap, Count, Acc) ->
- {reverse(Acc),true,Count}.
-
-%% unfold_arg_list(Is, ArgumentList, LitMap, Count0, X, Acc) ->
-%% {UpdatedAcc, Count}.
-%%
-%% Unfold the arguments in the argument list (second argument for error/2).
-%%
-%% Note that Is is the reversed list of instructions before the
-%% call to error/2. Because of the way the list is built in reverse,
-%% it means that the first put_list instruction found will add the first
-%% argument (x0) to the list, the second the second argument (x1), and
-%% so on.
-
-unfold_arg_list(Is, #b_literal{val=[Hd|Tl]}, LitMap, Count0, X, Acc) ->
- %% Handle the case that the entire argument list (the second argument
- %% for error/2) is a literal.
- {PutListDst,Count} = new_var('@put_list', Count0),
- PutList = #b_set{op=put_list,dst=PutListDst,
- args=[#b_literal{val=Hd},#b_literal{val=Tl}]},
- unfold_arg_list([PutList|Is], PutListDst, LitMap, Count, X, Acc);
-unfold_arg_list([#b_set{op=put_list,dst=List,
- args=[Hd0,#b_literal{val=[Hd|Tl]}]}=I0|Is0],
- List, LitMap, Count0, X, Acc) ->
- %% The rest of the argument list is a literal list.
- {PutListDst,Count} = new_var('@put_list', Count0),
- PutList = #b_set{op=put_list,dst=PutListDst,
- args=[#b_literal{val=Hd},#b_literal{val=Tl}]},
- I = I0#b_set{args=[Hd0,PutListDst]},
- unfold_arg_list([I,PutList|Is0], List, LitMap, Count, X, Acc);
-unfold_arg_list([#b_set{op=put_list,dst=List,args=[Hd0,Tl]}=I0|Is],
- List, LitMap, Count, X, Acc) ->
- %% Unfold the head of the list.
- Hd = unfold_arg(Hd0, LitMap, X),
- I = I0#b_set{args=[Hd,Tl]},
- unfold_arg_list(Is, Tl, LitMap, Count, X + 1, [I|Acc]);
-unfold_arg_list([I|Is], List, LitMap, Count, X, Acc) ->
- %% Some other instruction, such as bs_get_tail.
- unfold_arg_list(Is, List, LitMap, Count, X, [I|Acc]);
-unfold_arg_list([], _, _, Count, _, Acc) ->
- {reverse(Acc),Count}.
+unfold_lit_is([], _LitMap, Acc) ->
+ {reverse(Acc), true}.
unfold_call_args([A0|As], LitMap, X) ->
A = unfold_arg(A0, LitMap, X),
- [A|unfold_call_args(As, LitMap, X + 1)];
-unfold_call_args([], _, _) -> [].
+ [A | unfold_call_args(As, LitMap, X + 1)];
+unfold_call_args([], _, _) ->
+ [].
unfold_arg(#b_literal{val=Val}=Lit, LitMap, X) ->
case LitMap of
@@ -2935,10 +2912,11 @@ unfold_arg(#b_literal{val=Val}=Lit, LitMap, X) ->
end;
#{} -> Lit
end;
-unfold_arg(Expr, _LitMap, _X) -> Expr.
+unfold_arg(Expr, _LitMap, _X) ->
+ Expr.
%%%
-%%% Optimize tail calls created as the result of optimizations.
+%%% Restore tail calls that were damaged by optimizations.
%%%
%%% Consider the following example of a tail call in Erlang code:
%%%
@@ -2947,159 +2925,202 @@ unfold_arg(Expr, _LitMap, _X) -> Expr.
%%%
%%% The SSA code for the call will look like this:
%%%
-%%% @ssa_ret = call (`foo`/0)
-%%% ret @ssa_ret
-%%%
-%%% Sometimes optimizations create new tail calls. Consider this
-%%% slight variation of the example:
-%%%
-%%% bar() ->
-%%% {_,_} = foo().
-%%%
-%%% foo() -> {a,b}.
-%%%
-%%% If beam_ssa_type can figure out that `foo/0` always returns a tuple
-%%% of size two, the test for a tuple is no longer needed and the call
-%%% to `foo/0` will become a tail call. However, the resulting SSA
-%%% code will look like this:
-%%%
-%%% @ssa_ret = call (`foo`/0)
-%%% @ssa_bool = succeeded:body @ssa_ret
+%%% @ssa_result = call (`foo`/0)
+%%% @ssa_bool = succeeded:body @ssa_result
%%% br @ssa_bool, ^999, ^1
%%%
%%% 999:
-%%% ret @ssa_ret
+%%% ret @ssa_result
%%%
-%%% The beam_ssa_codegen pass will not recognize this code as a tail
-%%% call and will generate an unncessary stack frame. It may also
-%%% generate unecessary `kill` instructions.
-%%%
-%%% To avoid those extra instructions, this optimization will
-%%% eliminate the `succeeded:body` and `br` instructions and insert
-%%% the `ret` in the same block as the call:
-%%%
-%%% @ssa_ret = call (`foo`/0)
-%%% ret @ssa_ret
-%%%
-%%% Finally, consider this example:
-%%%
-%%% bar() ->
-%%% foo_ok(),
-%%% ok.
-%%%
-%%% foo_ok() -> ok.
-%%%
-%%% The SSA code for the call to `foo_ok/0` will look like:
+%%% Now imagine that an optimization has figured out that `foo/0` always
+%%% returns the atom `ok` and substituted the result everywhere, resulting in
+%%% the following SSA:
%%%
%%% %% Result type: `ok`
-%%% @ssa_ignored = call (`foo_ok`/0)
+%%% @ssa_ignored = call (`foo`/0)
%%% @ssa_bool = succeeded:body @ssa_ignored
%%% br @ssa_bool, ^999, ^1
%%%
%%% 999:
%%% ret `ok`
%%%
-%%% Since the call to `foo_ok/0` has an annotation indicating that the
-%%% call will always return the atom `ok`, the code can be simplified
-%%% like this:
-%%%
-%%% @ssa_ignored = call (`foo_ok`/0)
-%%% ret @ssa_ignored
+%%% The `beam_ssa_pre_codegen` pass will not recognize this code as a tail call
+%%% and will generate an unnecessary stack frame, and may also generate
+%%% unnecessary `kill` instructions.
%%%
%%% The beam_jump pass does the same optimization, but it does it too
%%% late to avoid creating an uncessary stack frame or unnecessary
%%% `kill` instructions.
%%%
-ssa_opt_tail_calls({St,FuncDb}) ->
- #opt_st{ssa=Blocks0} = St,
- Blocks = opt_tail_calls(beam_ssa:rpo(Blocks0), Blocks0),
- {St#opt_st{ssa=Blocks},FuncDb}.
+ssa_opt_tail_literals({St,FuncDb}) ->
+ #opt_st{cnt=Count0,ssa=Blocks0} = St,
+ {Count, Blocks} = opt_tail_literals(beam_ssa:rpo(Blocks0), Count0, Blocks0),
+ {St#opt_st{cnt=Count,ssa=Blocks},FuncDb}.
-opt_tail_calls([L|Ls], Blocks0) ->
+opt_tail_literals([L | Ls], Count, Blocks0) ->
#b_blk{is=Is0,last=Last} = Blk0 = map_get(L, Blocks0),
- %% Does this block end with a two-way branch whose success
- %% label targets an empty block with a `ret` terminator?
- case is_potential_tail_call(Last, Blocks0) of
- {yes,Bool,Ret} ->
- %% Yes, `Ret` is the value returned from that block
- %% (either a variable or literal). Do the instructions
- %% in this block end with a `call` instruction that
- %% returns the same value as `Ret`, followed by a
- %% `succeeded:body` instruction?
- case is_tail_call_is(Is0, Bool, Ret, []) of
- {yes,Is,Var} ->
- %% Yes, this is a tail call. `Is` is the instructions
- %% in the block with `succeeded:body` removed, and
- %% `Var` is the destination variable for the return
- %% value of the call. Rewrite this block to directly
- %% return `Var`.
- Blk = Blk0#b_blk{is=Is,last=#b_ret{arg=Var}},
- Blocks = Blocks0#{L:=Blk},
- opt_tail_calls(Ls, Blocks);
- no ->
- %% No, the block does not end with a call, or the
- %% the call instruction has not the same value
- %% as `Ret`.
- opt_tail_calls(Ls, Blocks0)
- end;
+ case is_tail_literal(Is0, Last, Blocks0) of
+ {yes, Var} ->
+ %% Yes, this is a call followed by a block returning the same value
+ %% as the call itself. Create a new block that returns the result
+ %% directly, as the successor block may be reachable from
+ %% elsewhere.
+ RetBlk = #b_blk{is=[],last=#b_ret{arg=Var}},
+ RetLbl = Count,
+
+ Blk = Blk0#b_blk{last=Last#b_br{succ=RetLbl}},
+
+ Blocks = Blocks0#{ L := Blk, RetLbl => RetBlk },
+ opt_tail_literals(Ls, Count + 1, Blocks);
no ->
- opt_tail_calls(Ls, Blocks0)
+ opt_tail_literals(Ls, Count, Blocks0)
end;
-opt_tail_calls([], Blocks) -> Blocks.
+opt_tail_literals([], Count, Blocks) ->
+ {Count, Blocks}.
-is_potential_tail_call(#b_br{bool=#b_var{}=Bool,succ=Succ}, Blocks) ->
+is_tail_literal([#b_set{op=call,dst=Dst}=Call,
+ #b_set{op={succeeded,body},dst=Bool}],
+ #b_br{bool=#b_var{}=Bool,succ=Succ}, Blocks) ->
case Blocks of
- #{Succ := #b_blk{is=[],last=#b_ret{arg=Arg}}} ->
- %% This could be a tail call.
- {yes,Bool,Arg};
+ #{ Succ := #b_blk{is=[],last=#b_ret{arg=#b_literal{val=Val}}} } ->
+ %% Our success block does nothing but return a literal. Now we'll
+ %% check whether it's the same literal as the one returned by the
+ %% call itself.
+ Type = beam_ssa:get_anno(result_type, Call, any),
+ case beam_types:get_singleton_value(Type) of
+ {ok, Val} -> {yes, Dst};
+ _ -> no
+ end;
#{} ->
- %% The block is not empty or does not have a `ret` terminator.
no
end;
-is_potential_tail_call(_, _) ->
- %% Not a two-way branch (a `succeeded:body` instruction must be
- %% followed by a two-way branch).
+is_tail_literal([_ | Is], #b_br{}=Last, Blocks) ->
+ is_tail_literal(Is, Last, Blocks);
+is_tail_literal(_Is, _Last, _Blocks) ->
no.
-is_tail_call_is([#b_set{op=call,dst=Dst}=Call,
- #b_set{op={succeeded,body},dst=Bool}],
- Bool, Ret, Acc) ->
- IsTailCall =
- case Ret of
- #b_literal{val=Val} ->
- %% The return value for this function is a literal.
- %% Now test whether it is the same literal that the
- %% `call` instruction returns.
- Type = beam_ssa:get_anno(result_type, Call, any),
- case beam_types:get_singleton_value(Type) of
- {ok,Val} ->
- %% Same value.
- true;
- {ok,_} ->
- %% Wrong value.
- false;
- error ->
- %% The type for the return value is not a singleton value.
- false
- end;
- #b_var{} ->
- %% It is a tail call if the variable set by the `call` instruction
- %% is the same variable as the argument for the `ret` terminator.
- Ret =:= Dst
- end,
- case IsTailCall of
- true ->
- %% Return the instructions in the block with `succeeded:body` removed.
- Is = reverse(Acc, [Call]),
- {yes,Is,Dst};
- false ->
- no
+%%%
+%%% Eliminate redundant branches.
+%%%
+%%% Redundant `br` instructions following calls to guard BIFs such as:
+%%%
+%%% @bif_result = bif:Bif ...
+%%% br @bif_result, ^100, ^200
+%%%
+%%% 100:
+%%% ret `true`
+%%%
+%%% 200:
+%%% ret `false`
+%%%
+%%% can can be rewritten to:
+%%%
+%%% @bif_result = bif:Bif ...
+%%% ret @bif_result
+%%%
+%%% A similar rewriting is possible if the true and false branches end
+%%% up at a phi node.
+%%%
+%%% A code sequence such as:
+%%%
+%%% @ssa_bool = bif:'=:=' Var, Other
+%%% br @ssa_bool, ^100, ^200
+%%%
+%%% 100:
+%%% ret Other
+%%%
+%%% 200:
+%%% ret Var
+%%%
+%%% can be rewritten to:
+%%%
+%%% ret Var
+%%%
+
+ssa_opt_redundant_br({#opt_st{ssa=Blocks0}=St, FuncDb}) ->
+ Blocks = redundant_br(beam_ssa:rpo(Blocks0), Blocks0),
+ {St#opt_st{ssa=Blocks}, FuncDb}.
+
+redundant_br([L|Ls], Blocks0) ->
+ Blk0 = map_get(L, Blocks0),
+ case Blk0 of
+ #b_blk{is=Is,
+ last=#b_br{bool=#b_var{}=Bool,
+ succ=Succ,
+ fail=Fail}} ->
+ case Blocks0 of
+ #{Succ := #b_blk{is=[],last=#b_ret{arg=#b_literal{val=true}}},
+ Fail := #b_blk{is=[],last=#b_ret{arg=#b_literal{val=false}}}} ->
+ case redundant_br_safe_bool(Is, Bool) of
+ true ->
+ Blk = Blk0#b_blk{last=#b_ret{arg=Bool}},
+ Blocks = Blocks0#{L => Blk},
+ redundant_br(Ls, Blocks);
+ false ->
+ redundant_br(Ls, Blocks0)
+ end;
+ #{Succ := #b_blk{is=[],last=#b_br{succ=PhiL,fail=PhiL}},
+ Fail := #b_blk{is=[],last=#b_br{succ=PhiL,fail=PhiL}}} ->
+ case redundant_br_safe_bool(Is, Bool) of
+ true ->
+ Blocks = redundant_br_phi(L, Blk0, PhiL, Blocks0),
+ redundant_br(Ls, Blocks);
+ false ->
+ redundant_br(Ls, Blocks0)
+ end;
+ #{Succ := #b_blk{is=[],last=#b_ret{arg=Other}},
+ Fail := #b_blk{is=[],last=#b_ret{arg=Var}}} when Is =/= [] ->
+ case last(Is) of
+ #b_set{op={bif,'=:='},args=[Var,Other]} ->
+ Blk = Blk0#b_blk{is=droplast(Is),
+ last=#b_ret{arg=Var}},
+ Blocks = Blocks0#{L => Blk},
+ redundant_br(Ls, Blocks);
+ #b_set{} ->
+ redundant_br(Ls, Blocks0)
+ end;
+ #{} ->
+ redundant_br(Ls, Blocks0)
+ end;
+ _ ->
+ redundant_br(Ls, Blocks0)
end;
-is_tail_call_is([I|Is], Bool, Ret, Acc) ->
- is_tail_call_is(Is, Bool, Ret, [I|Acc]);
-is_tail_call_is([], _Bool, _Ret, _Acc) -> no.
+redundant_br([], Blocks) -> Blocks.
+
+redundant_br_phi(L, Blk0, PhiL, Blocks) ->
+ #b_blk{is=Is0} = PhiBlk0 = map_get(PhiL, Blocks),
+ case Is0 of
+ [#b_set{op=phi},#b_set{op=phi}|_] ->
+ Blocks;
+ [#b_set{op=phi,args=PhiArgs0}=I0|Is] ->
+ #b_blk{last=#b_br{succ=Succ,fail=Fail}} = Blk0,
+ BoolPhiArgs = [{#b_literal{val=false},Fail},
+ {#b_literal{val=true},Succ}],
+ PhiArgs1 = ordsets:from_list(PhiArgs0),
+ case ordsets:is_subset(BoolPhiArgs, PhiArgs1) of
+ true ->
+ #b_blk{last=#b_br{bool=Bool}} = Blk0,
+ PhiArgs = ordsets:add_element({Bool,L}, PhiArgs1),
+ I = I0#b_set{args=PhiArgs},
+ PhiBlk = PhiBlk0#b_blk{is=[I|Is]},
+ Br = #b_br{bool=#b_literal{val=true},succ=PhiL,fail=PhiL},
+ Blk = Blk0#b_blk{last=Br},
+ Blocks#{L := Blk, PhiL := PhiBlk};
+ false ->
+ Blocks
+ end
+ end.
+
+redundant_br_safe_bool([], _Bool) ->
+ true;
+redundant_br_safe_bool(Is, Bool) ->
+ case last(Is) of
+ #b_set{op={bif,_}} -> true;
+ #b_set{op=has_map_field} -> true;
+ #b_set{dst=Dst} -> Dst =/= Bool
+ end.
%%%
%%% Common utilities.
diff --git a/lib/compiler/src/beam_ssa_pp.erl b/lib/compiler/src/beam_ssa_pp.erl
index b290d49e5f..4e6974385e 100644
--- a/lib/compiler/src/beam_ssa_pp.erl
+++ b/lib/compiler/src/beam_ssa_pp.erl
@@ -22,6 +22,7 @@
-export([format_function/1,format_instr/1,format_var/1]).
-include("beam_ssa.hrl").
+-include("beam_types.hrl").
-spec format_function(beam_ssa:b_function()) -> iolist().
@@ -115,7 +116,7 @@ format_param_info([], _Break) ->
format_type(T, Break) ->
%% Gross hack, but it's short and simple.
- Indented = lists:flatten(io_lib:format("~p", [T])),
+ Indented = unicode:characters_to_list(format_type(T)),
string:replace(Indented, [$\n], Break, all).
format_blocks(Ls, Blocks, Anno) ->
@@ -142,7 +143,7 @@ format_instrs([], _FuncAnno, _First) ->
format_instr(#b_set{anno=Anno,op=Op,dst=Dst,args=Args},
FuncAnno, First) ->
- AnnoStr = format_anno(Anno),
+ AnnoStr = format_instr_anno(Anno, FuncAnno, Args),
LiveIntervalStr = format_live_interval(Dst, FuncAnno),
[if
First ->
@@ -241,20 +242,37 @@ format_switch_list(List, FuncAnno) ->
format_label(L) ->
io_lib:format("^~w", [L]).
-format_anno(#{n:=_}=Anno) ->
- format_anno(maps:remove(n, Anno));
-format_anno(#{location:={File,Line}}=Anno0) ->
+format_instr_anno(#{n:=_}=Anno, FuncAnno, Args) ->
+ format_instr_anno(maps:remove(n, Anno), FuncAnno, Args);
+format_instr_anno(#{location:={File,Line}}=Anno0, FuncAnno, Args) ->
Anno = maps:remove(location, Anno0),
- [io_lib:format(" %% ~ts:~p\n", [File,Line])|format_anno(Anno)];
-format_anno(#{result_type:=T}=Anno0) ->
+ [io_lib:format(" %% ~ts:~p\n", [File,Line]) |
+ format_instr_anno(Anno, FuncAnno, Args)];
+format_instr_anno(#{result_type:=T}=Anno0, FuncAnno, Args) ->
Anno = maps:remove(result_type, Anno0),
Break = "\n %% ",
[io_lib:format(" %% Result type:~s~s\n",
- [Break, format_type(T, Break)]) | format_anno(Anno)];
-format_anno(Anno) ->
- format_anno_1(Anno).
+ [Break, format_type(T, Break)]) |
+ format_instr_anno(Anno, FuncAnno, Args)];
+format_instr_anno(#{arg_types:=Ts}=Anno0, FuncAnno, Args) ->
+ Anno = maps:remove(arg_types, Anno0),
-format_anno_1(Anno) ->
+ Break = "\n %% ",
+
+ Iota = lists:seq(0, length(Args) - 1),
+ Formatted0 = [[format_arg(Arg, FuncAnno), " => ",
+ format_type(map_get(Idx, Ts),
+ Break)]
+ || {Idx, Arg} <- lists:zip(Iota, Args), is_map_key(Idx, Ts)],
+ Formatted = lists:join(Break, Formatted0),
+
+ [io_lib:format(" %% Argument types:~s~ts\n",
+ [Break, unicode:characters_to_list(Formatted)]) |
+ format_instr_anno(Anno, FuncAnno, Args)];
+format_instr_anno(Anno, _FuncAnno, _Args) ->
+ format_instr_anno_1(Anno).
+
+format_instr_anno_1(Anno) ->
case map_size(Anno) of
0 ->
[];
@@ -274,3 +292,112 @@ format_live_interval(#b_var{}=Dst, #{live_intervals:=Intervals}) ->
end;
format_live_interval(_, _) -> [].
+format_type(any) ->
+ "any()";
+format_type(#t_atom{elements=any}) ->
+ "atom()";
+format_type(#t_atom{elements=Es}) ->
+ string:join([io_lib:format("'~p'", [E])
+ || E <- ordsets:to_list(Es)], " | ");
+format_type(#t_bs_matchable{tail_unit=U}) ->
+ io_lib:format("bs_matchable(~p)", [U]);
+format_type(#t_bitstring{size_unit=S}) ->
+ io_lib:format("bitstring(~p)", [S]);
+format_type(#t_bs_context{tail_unit=U}) ->
+ io_lib:format("bs_context(~p)", [U]);
+format_type(#t_fun{arity=any,type=any}) ->
+ "fun()";
+format_type(#t_fun{arity=any,type=T}) ->
+ ["fun((...) -> ", format_type(T), ")"];
+format_type(#t_fun{arity=A,type=any}) ->
+ ["fun((", format_fun_args(A), "))"];
+format_type(#t_fun{arity=A,type=T}) ->
+ ["fun((", format_fun_args(A), ") -> ", format_type(T), ")"];
+format_type(#t_map{super_key=any,super_value=any}) ->
+ "map()";
+format_type(#t_map{super_key=none,super_value=none}) ->
+ "#{}";
+format_type(#t_map{super_key=K,super_value=V}) ->
+ ["#{", format_type(K), "=>", format_type(V), "}"];
+format_type(number) ->
+ "number()";
+format_type(#t_float{elements=any}) ->
+ "float()";
+format_type(#t_float{elements={X,X}}) ->
+ io_lib:format("~p", [X]);
+format_type(#t_float{elements={Low,High}}) ->
+ io_lib:format("~p..~p", [Low,High]);
+format_type(#t_integer{elements=any}) ->
+ "integer()";
+format_type(#t_integer{elements={X,X}}) ->
+ io_lib:format("~p", [X]);
+format_type(#t_integer{elements={Low,High}}) ->
+ io_lib:format("~p..~p", [Low,High]);
+format_type(#t_list{type=ET,terminator=nil}) ->
+ ["list(", format_type(ET), ")"];
+format_type(#t_list{type=ET,terminator=TT}) ->
+ ["maybe_improper_list(", format_type(ET), ", ", format_type(TT), ")"];
+format_type(#t_cons{type=ET,terminator=nil}) ->
+ ["nonempty_list(", format_type(ET), ")"];
+format_type(#t_cons{type=ET,terminator=TT}) ->
+ ["nonempty_improper_list(", format_type(ET), ", ", format_type(TT), ")"];
+format_type(nil) ->
+ "nil()";
+format_type(#t_tuple{elements=Es,exact=Ex,size=S}) ->
+ ["{",
+ string:join(format_tuple_elems(S, Ex, Es, 1), ", "),
+ "}"];
+format_type(pid) ->
+ "pid()";
+format_type(port) ->
+ "pid()";
+format_type(reference) ->
+ "reference()";
+format_type(none) ->
+ "none()";
+format_type(#t_union{atom=A,list=L,number=N,tuple_set=Ts,other=O}) ->
+ Es = case A of
+ none -> [];
+ _ -> [format_type(A)]
+ end
+ ++ case L of
+ none -> [];
+ _ -> [format_type(L)]
+ end
+ ++ case N of
+ none -> [];
+ _ -> [format_type(N)]
+ end
+ ++ case Ts of
+ none -> [];
+ _ -> [format_tuple_set(Ts)]
+ end
+ ++ case O of
+ none -> [];
+ _ -> [format_type(O)]
+ end,
+ string:join(Es, " | ").
+
+format_fun_args(A) ->
+ string:join(lists:duplicate(A, "_"), ", ").
+
+format_tuple_elems(Size, true, _Elems, Idx) when Idx > Size ->
+ [];
+format_tuple_elems(Size, false, _Elems, Idx) when Idx > Size ->
+ ["..."];
+format_tuple_elems(Size, Exact, Elems, Idx) ->
+ T = case Elems of
+ #{ Idx := Ty} -> Ty;
+ _ -> any
+ end,
+ [format_type(T)|format_tuple_elems(Size, Exact, Elems, Idx + 1)].
+
+format_tuple_set(#t_tuple{}=T) ->
+ format_type(T);
+format_tuple_set(RecordSet) ->
+ string:join([format_tuple_set_1(T) || T <- ordsets:to_list(RecordSet)],
+ " | ").
+
+format_tuple_set_1({{Arity,Key},#t_tuple{size=Arity,elements=Elems}=Tuple}) ->
+ Key = map_get(1, Elems), % Assertion
+ format_type(Tuple).
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
index 878c830fba..bb9aa75797 100644
--- a/lib/compiler/src/beam_ssa_pre_codegen.erl
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -69,31 +69,30 @@
-export([module/2]).
-include("beam_ssa.hrl").
+-include("beam_asm.hrl").
-import(lists, [all/2,any/2,append/1,duplicate/2,
foldl/3,last/1,member/2,partition/2,
- reverse/1,reverse/2,sort/1,splitwith/2,zip/2]).
+ reverse/1,reverse/2,seq/2,sort/1,
+ splitwith/2,usort/1,zip/2]).
-spec module(beam_ssa:b_module(), [compile:option()]) ->
{'ok',beam_ssa:b_module()}.
module(#b_module{body=Fs0}=Module, Opts) ->
- UseBSM3 = not proplists:get_bool(no_bsm3, Opts),
Ps = passes(Opts),
- Fs = functions(Fs0, Ps, UseBSM3),
+ Fs1 = functions(Fs0, Ps),
+ Fs = create_fc_stubs(Fs1, Module),
{ok,Module#b_module{body=Fs}}.
-functions([F|Fs], Ps, UseBSM3) ->
- [function(F, Ps, UseBSM3)|functions(Fs, Ps, UseBSM3)];
-functions([], _Ps, _UseBSM3) -> [].
+functions([F|Fs], Ps) ->
+ [function(F, Ps)|functions(Fs, Ps)];
+functions([], _Ps) -> [].
-type b_var() :: beam_ssa:b_var().
-type var_name() :: beam_ssa:var_name().
-type instr_number() :: pos_integer().
-type range() :: {instr_number(),instr_number()}.
--type reg_num() :: beam_asm:reg_num().
--type xreg() :: {'x',reg_num()}.
--type yreg() :: {'y',reg_num()}.
-type ypool() :: {'y',beam_ssa:label()}.
-type reservation() :: 'fr' | {'prefer',xreg()} | 'x' | {'x',xreg()} |
ypool() | {yreg(),ypool()} | 'z'.
@@ -103,7 +102,6 @@ functions([], _Ps, _UseBSM3) -> [].
-record(st, {ssa :: beam_ssa:block_map(),
args :: [b_var()],
cnt :: beam_ssa:label(),
- use_bsm3 :: boolean(),
frames=[] :: [beam_ssa:label()],
intervals=[] :: [{b_var(),[range()]}],
res=[] :: [{b_var(),reservation()}] | #{b_var():=reservation()},
@@ -115,17 +113,12 @@ functions([], _Ps, _UseBSM3) -> [].
passes(Opts) ->
AddPrecgAnnos = proplists:get_bool(dprecg, Opts),
- FixTuples = proplists:get_bool(no_put_tuple2, Opts),
Ps = [?PASS(assert_no_critical_edges),
%% Preliminaries.
?PASS(fix_bs),
?PASS(sanitize),
- ?PASS(match_fail_instructions),
- case FixTuples of
- false -> ignore;
- true -> ?PASS(fix_tuples)
- end,
+ ?PASS(expand_match_fail),
?PASS(use_set_tuple_element),
?PASS(place_frames),
?PASS(fix_receives),
@@ -134,10 +127,6 @@ passes(Opts) ->
?PASS(find_yregs),
?PASS(reserve_yregs),
- %% Handle legacy binary match instruction that don't
- %% accept a Y register as destination.
- ?PASS(legacy_bs),
-
%% Improve reuse of Y registers to potentially
%% reduce the size of the stack frame.
?PASS(copy_retval),
@@ -163,11 +152,10 @@ passes(Opts) ->
?PASS(assert_no_critical_edges)],
[P || P <- Ps, P =/= ignore].
-function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0,
- Ps, UseBSM3) ->
+function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0, Ps) ->
try
Location = maps:get(location, Anno, none),
- St0 = #st{ssa=Blocks0,args=Args,use_bsm3=UseBSM3,
+ St0 = #st{ssa=Blocks0,args=Args,
cnt=Count0,location=Location},
St = compile:run_sub_passes(Ps, St0),
#st{ssa=Blocks,cnt=Count,regs=Regs,extra_annos=ExtraAnnos} = St,
@@ -210,14 +198,9 @@ assert_no_ces(_, #b_blk{is=[#b_set{op=phi,args=[_,_]=Phis}|_]}, Blocks) ->
assert_no_ces(_, _, Blocks) -> Blocks.
%% fix_bs(St0) -> St.
-%% Fix up the binary matching instructions:
-%%
-%% * Insert bs_save and bs_restore instructions where needed.
-%%
-%% * Combine bs_match and bs_extract instructions to bs_get
-%% instructions.
+%% Combine bs_match and bs_extract instructions to bs_get instructions.
-fix_bs(#st{ssa=Blocks,cnt=Count0,use_bsm3=UseBSM3}=St) ->
+fix_bs(#st{ssa=Blocks,cnt=Count0}=St) ->
F = fun(#b_set{op=bs_start_match,dst=Dst}, A) ->
%% Mark the root of the match context list.
[{Dst,{context,Dst}}|A];
@@ -237,12 +220,7 @@ fix_bs(#st{ssa=Blocks,cnt=Count0,use_bsm3=UseBSM3}=St) ->
Linear0 = beam_ssa:linearize(Blocks),
%% Insert position instructions where needed.
- {Linear1,Count} = case UseBSM3 of
- true ->
- bs_pos_bsm3(Linear0, CtxChain, Count0);
- false ->
- bs_pos_bsm2(Linear0, CtxChain, Count0)
- end,
+ {Linear1,Count} = bs_pos_bsm3(Linear0, CtxChain, Count0),
%% Rename instructions.
Linear = bs_instrs(Linear1, CtxChain, []),
@@ -296,60 +274,6 @@ make_bs_pos_dict_1([H|T], Ctx, I, Acc) ->
make_bs_pos_dict_1([], Ctx, I, Acc) ->
{[{Ctx,I}|Acc], I}.
-%% As bs_position but without OTP-22 instructions. This is only used when
-%% cross-compiling to older versions.
-bs_pos_bsm2(Linear0, CtxChain, Count0) ->
- Rs0 = bs_restores(Linear0, CtxChain, #{}, #{}),
- Rs = maps:values(Rs0),
- S0 = sofs:relation(Rs, [{context,save_point}]),
- S1 = sofs:relation_to_family(S0),
- S = sofs:to_external(S1),
- Slots = make_save_point_dict(S, []),
- {Saves,Count1} = make_save_map(Rs, Slots, Count0, []),
- {Restores,Count} = make_restore_map(maps:to_list(Rs0), Slots, Count1, []),
-
- %% Now insert all saves and restores.
- {bs_insert_bsm2(Linear0, Saves, Restores, Slots),Count}.
-
-make_save_map([{Ctx,Save}=Ps|T], Slots, Count, Acc) ->
- Ignored = #b_var{name={'@ssa_ignored',Count}},
- case make_slot(Ps, Slots) of
- #b_literal{val=start} ->
- make_save_map(T, Slots, Count, Acc);
- Slot ->
- I = #b_set{op=bs_save,dst=Ignored,args=[Ctx,Slot]},
- make_save_map(T, Slots, Count+1, [{Save,I}|Acc])
- end;
-make_save_map([], _, Count, Acc) ->
- {maps:from_list(Acc),Count}.
-
-make_restore_map([{Bef,{Ctx,_}=Ps}|T], Slots, Count, Acc) ->
- Ignored = #b_var{name={'@ssa_ignored',Count}},
- I = #b_set{op=bs_restore,dst=Ignored,args=[Ctx,make_slot(Ps, Slots)]},
- make_restore_map(T, Slots, Count+1, [{Bef,I}|Acc]);
-make_restore_map([], _, Count, Acc) ->
- {maps:from_list(Acc),Count}.
-
-make_slot({Same,Same}, _Slots) ->
- #b_literal{val=start};
-make_slot({_,_}=Ps, Slots) ->
- #b_literal{val=map_get(Ps, Slots)}.
-
-make_save_point_dict([{Ctx,Pts}|T], Acc0) ->
- Acc = make_save_point_dict_1(Pts, Ctx, 0, Acc0),
- make_save_point_dict(T, Acc);
-make_save_point_dict([], Acc) ->
- maps:from_list(Acc).
-
-make_save_point_dict_1([Ctx|T], Ctx, I, Acc) ->
- %% Special {atom,start} save point. Does not need a
- %% bs_save instruction.
- make_save_point_dict_1(T, Ctx, I, Acc);
-make_save_point_dict_1([H|T], Ctx, I, Acc) ->
- make_save_point_dict_1(T, Ctx, I+1, [{{Ctx,H},I}|Acc]);
-make_save_point_dict_1([], Ctx, I, Acc) ->
- [{Ctx,I}|Acc].
-
bs_restores([{L,#b_blk{is=Is,last=Last}}|Bs], CtxChain, D0, Rs0) ->
InPos = maps:get(L, D0, #{}),
{SuccPos, FailPos, Rs} = bs_restores_is(Is, CtxChain, InPos, InPos, Rs0),
@@ -561,20 +485,6 @@ bs_restore_args([], Pos, _CtxChain, _Dst, Rs) ->
bs_insert_bsm3(Blocks, Saves, Restores) ->
bs_insert_1(Blocks, [], Saves, Restores, fun(I) -> I end).
-bs_insert_bsm2(Blocks, Saves, Restores, Slots) ->
- %% The old instructions require bs_start_match to be annotated with the
- %% number of position slots it needs.
- bs_insert_1(Blocks, [], Saves, Restores,
- fun(#b_set{op=bs_start_match,dst=Dst}=I0) ->
- NumSlots = case Slots of
- #{Dst:=NumSlots0} -> NumSlots0;
- #{} -> 0
- end,
- beam_ssa:add_anno(num_slots, NumSlots, I0);
- (I) ->
- I
- end).
-
bs_insert_1([{L,#b_blk{is=Is0}=Blk} | Bs], Deferred0, Saves, Restores, XFrm) ->
Is1 = bs_insert_deferred(Is0, Deferred0),
{Is, Deferred} = bs_insert_is(Is1, Saves, Restores, XFrm, []),
@@ -668,59 +578,6 @@ bs_subst_ctx(#b_var{}=Var, CtxChain) ->
bs_subst_ctx(Other, _CtxChain) ->
Other.
-%% legacy_bs(St0) -> St.
-%% Binary matching instructions in OTP 21 and earlier don't support
-%% a Y register as destination. If St#st.use_bsm3 is false,
-%% we will need to rewrite those instructions so that the result
-%% is first put in an X register and then moved to a Y register
-%% if the operation succeeded.
-
-legacy_bs(#st{use_bsm3=false,ssa=Blocks0,cnt=Count0,res=Res}=St) ->
- IsYreg = maps:from_list([{V,true} || {V,{y,_}} <- Res]),
- Linear0 = beam_ssa:linearize(Blocks0),
- {Linear,Count} = legacy_bs(Linear0, IsYreg, Count0, #{}, []),
- Blocks = maps:from_list(Linear),
- St#st{ssa=Blocks,cnt=Count};
-legacy_bs(#st{use_bsm3=true}=St) -> St.
-
-legacy_bs([{L,Blk}|Bs], IsYreg, Count0, Copies0, Acc) ->
- #b_blk{is=Is0,last=Last} = Blk,
- Is1 = case Copies0 of
- #{L:=Copy} -> [Copy|Is0];
- #{} -> Is0
- end,
- {Is,Count,Copies} = legacy_bs_is(Is1, Last, IsYreg, Count0, Copies0, []),
- legacy_bs(Bs, IsYreg, Count, Copies, [{L,Blk#b_blk{is=Is}}|Acc]);
-legacy_bs([], _IsYreg, Count, _Copies, Acc) ->
- {Acc,Count}.
-
-legacy_bs_is([#b_set{op=Op,dst=Dst}=I0,
- #b_set{op=succeeded,dst=SuccDst,args=[Dst]}=SuccI0],
- Last, IsYreg, Count0, Copies0, Acc) ->
- NeedsFix = is_map_key(Dst, IsYreg) andalso
- case Op of
- bs_get -> true;
- bs_init -> true;
- _ -> false
- end,
- case NeedsFix of
- true ->
- TempDst = #b_var{name={'@bs_temp_dst',Count0}},
- Count = Count0 + 1,
- I = I0#b_set{dst=TempDst},
- SuccI = SuccI0#b_set{args=[TempDst]},
- Copy = #b_set{op=copy,dst=Dst,args=[TempDst]},
- #b_br{bool=SuccDst,succ=SuccL} = Last,
- Copies = Copies0#{SuccL=>Copy},
- legacy_bs_is([], Last, IsYreg, Count, Copies, [SuccI,I|Acc]);
- false ->
- legacy_bs_is([], Last, IsYreg, Count0, Copies0, [SuccI0,I0|Acc])
- end;
-legacy_bs_is([I|Is], Last, IsYreg, Count, Copies, Acc) ->
- legacy_bs_is(Is, Last, IsYreg, Count, Copies, [I|Acc]);
-legacy_bs_is([], _Last, _IsYreg, Count, Copies, Acc) ->
- {reverse(Acc),Count,Copies}.
-
%% sanitize(St0) -> St.
%% Remove constructs that can cause problems later:
%%
@@ -732,82 +589,84 @@ legacy_bs_is([], _Last, _IsYreg, Count, Copies, Acc) ->
sanitize(#st{ssa=Blocks0,cnt=Count0}=St) ->
Ls = beam_ssa:rpo(Blocks0),
- {Blocks,Count} = sanitize(Ls, Count0, Blocks0, #{}),
+ {Blocks,Count} = sanitize(Ls, Blocks0, Count0, #{}),
St#st{ssa=Blocks,cnt=Count}.
-sanitize([L|Ls], Count0, Blocks0, Values0) ->
+sanitize([L|Ls], Blocks0, Count0, Values0) ->
#b_blk{is=Is0,last=Last0} = Blk0 = map_get(L, Blocks0),
- case sanitize_is(Is0, Last0, Count0, Values0, false, []) of
+ case sanitize_is(Is0, Last0, Blocks0, Count0, Values0, false, []) of
no_change ->
- sanitize(Ls, Count0, Blocks0, Values0);
+ sanitize(Ls, Blocks0, Count0, Values0);
{Is,Last,Count,Values} ->
Blk = Blk0#b_blk{is=Is,last=Last},
Blocks = Blocks0#{L:=Blk},
- sanitize(Ls, Count, Blocks, Values)
+ sanitize(Ls, Blocks, Count, Values)
end;
-sanitize([], Count, Blocks0, Values) ->
+sanitize([], Blocks0, Count, Values) ->
Blocks = if
- map_size(Values) =:= 0 ->
- Blocks0;
- true ->
- RPO = beam_ssa:rpo(Blocks0),
- beam_ssa:rename_vars(Values, RPO, Blocks0)
- end,
+ map_size(Values) =:= 0 ->
+ Blocks0;
+ true ->
+ RPO = beam_ssa:rpo(Blocks0),
+ beam_ssa:rename_vars(Values, RPO, Blocks0)
+ end,
%% Unreachable blocks can cause problems for the dominator calculations.
Ls = beam_ssa:rpo(Blocks),
Reachable = gb_sets:from_list(Ls),
{case map_size(Blocks) =:= gb_sets:size(Reachable) of
- true -> Blocks;
- false -> remove_unreachable(Ls, Blocks, Reachable, [])
- end,Count}.
+ true -> Blocks;
+ false -> remove_unreachable(Ls, Blocks, Reachable, [])
+ end, Count}.
sanitize_is([#b_set{op=get_map_element,args=Args0}=I0|Is],
- Last, Count0, Values, Changed, Acc) ->
+ Last, Blocks, Count0, Values, Changed, Acc) ->
case sanitize_args(Args0, Values) of
[#b_literal{}=Map,Key] ->
%% Bind the literal map to a variable.
{MapVar,Count} = new_var('@ssa_map', Count0),
I = I0#b_set{args=[MapVar,Key]},
Copy = #b_set{op=copy,dst=MapVar,args=[Map]},
- sanitize_is(Is, Last, Count, Values, true, [I,Copy|Acc]);
+ sanitize_is(Is, Last, Blocks, Count, Values, true, [I,Copy|Acc]);
[_,_]=Args0 ->
- sanitize_is(Is, Last, Count0, Values, Changed, [I0|Acc]);
+ sanitize_is(Is, Last, Blocks, Count0, Values, Changed, [I0|Acc]);
[_,_]=Args ->
I = I0#b_set{args=Args},
- sanitize_is(Is, Last, Count0, Values, true, [I|Acc])
- end;
-sanitize_is([#b_set{op={succeeded,guard},dst=Dst,args=[Arg0]}=I0],
- #b_br{bool=Dst}=Last, Count, Values, _Changed, Acc0) ->
- %% We no longer need to distinguish between guard and body checks, so we'll
- %% rewrite this as a plain 'succeeded'.
- case sanitize_arg(Arg0, Values) of
- #b_var{}=Arg ->
- case Acc0 of
- [#b_set{op=call,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error},
- arity=1},_],
- dst=Arg0}|Acc] ->
- %% This erlang:error/1 is the result from a
- %% sanitized bs_add or bs_init instruction. Calls
- %% to erlang:error/1 in receive is not allowed, so
- %% we will have to rewrite this instruction
- %% sequence to an unconditional branch to the
- %% failure label.
- Fail = Last#b_br.fail,
- Br = #b_br{bool=#b_literal{val=true},succ=Fail,fail=Fail},
- {reverse(Acc), Br, Count, Values};
- _ ->
- I = I0#b_set{op=succeeded,args=[Arg]},
- {reverse(Acc0, [I]), Last, Count, Values}
- end;
- #b_literal{} ->
- Value = #b_literal{val=true},
- {reverse(Acc0), Last, Count, Values#{ Dst => Value }}
- end;
-sanitize_is([#b_set{op={succeeded,body},dst=Dst,args=[Arg0]}=I0],
- #b_br{bool=Dst}=Last, Count, Values, _Changed, Acc) ->
+ sanitize_is(Is, Last, Blocks, Count0, Values, true, [I|Acc])
+ end;
+sanitize_is([#b_set{op=call,dst=CallDst}=Call,
+ #b_set{op={succeeded,body},dst=SuccDst,args=[CallDst]}=Succ],
+ #b_br{bool=SuccDst,succ=SuccLbl,fail=?EXCEPTION_BLOCK}=Last0,
+ Blocks, Count, Values, Changed, Acc) ->
+ case Blocks of
+ #{ SuccLbl := #b_blk{is=[],last=#b_ret{arg=CallDst}=Last} } ->
+ %% Tail call that may fail, translate the terminator to an ordinary
+ %% return to simplify code generation.
+ do_sanitize_is(Call, [], Last, Blocks, Count, Values,
+ true, Acc);
+ #{} ->
+ do_sanitize_is(Call, [Succ], Last0, Blocks, Count, Values,
+ Changed, Acc)
+ end;
+sanitize_is([#b_set{op=Op,dst=Dst}=Fail,
+ #b_set{op={succeeded,body},args=[Dst]}],
+ #b_br{fail=?EXCEPTION_BLOCK},
+ Blocks, Count, Values, _Changed, Acc)
+ when Op =:= match_fail; Op =:= resume ->
+ %% Match failure or rethrow without a local handler. Translate the
+ %% terminator to an ordinary return to simplify code generation.
+ Last = #b_ret{arg=Dst},
+ do_sanitize_is(Fail, [], Last, Blocks, Count, Values, true, Acc);
+sanitize_is([#b_set{op=match_fail,dst=RaiseDst},
+ #b_set{op={succeeded,guard},dst=SuccDst,args=[RaiseDst]}],
+ #b_br{bool=SuccDst}=Last0,
+ Blocks, Count, Values, _Changed, Acc) ->
+ %% Match failures may be present in guards when optimizations are turned
+ %% off. They must be treated as if they always fail.
+ Last = beam_ssa:normalize(Last0#b_br{bool=#b_literal{val=false}}),
+ sanitize_is([], Last, Blocks, Count, Values, true, Acc);
+sanitize_is([#b_set{op={succeeded,_Kind},dst=Dst,args=[Arg0]}=I0],
+ #b_br{bool=Dst}=Last, _Blocks, Count, Values, _Changed, Acc) ->
%% We no longer need to distinguish between guard and body checks, so we'll
%% rewrite this as a plain 'succeeded'.
case sanitize_arg(Arg0, Values) of
@@ -819,7 +678,7 @@ sanitize_is([#b_set{op={succeeded,body},dst=Dst,args=[Arg0]}=I0],
{reverse(Acc), Last, Count, Values#{ Dst => Value }}
end;
sanitize_is([#b_set{op={succeeded,Kind},args=[Arg0]} | Is],
- Last, Count, Values, _Changed, Acc) ->
+ Last, Blocks, Count, Values, _Changed, Acc) ->
%% We're no longer branching on this instruction and can safely remove it.
[] = Is, #b_br{succ=Same,fail=Same} = Last, %Assertion.
if
@@ -828,23 +687,24 @@ sanitize_is([#b_set{op={succeeded,Kind},args=[Arg0]} | Is],
%% in a try/catch; rewrite the terminator to a return.
body = Kind, %Assertion.
Arg = sanitize_arg(Arg0, Values),
- sanitize_is(Is, #b_ret{arg=Arg}, Count, Values, true, Acc);
+ sanitize_is(Is, #b_ret{arg=Arg}, Blocks, Count, Values, true, Acc);
Same =/= ?EXCEPTION_BLOCK ->
%% We either always succeed, or always fail to somewhere other than
%% the exception block.
true = Kind =:= guard orelse Kind =:= body, %Assertion.
- sanitize_is(Is, Last, Count, Values, true, Acc)
+ sanitize_is(Is, Last, Blocks, Count, Values, true, Acc)
end;
-sanitize_is([#b_set{op=bs_test_tail}=I], Last, Count, Values, Changed, Acc) ->
+sanitize_is([#b_set{op=bs_test_tail}=I], Last, Blocks, Count, Values,
+ Changed, Acc) ->
case Last of
#b_br{succ=Same,fail=Same} ->
- sanitize_is([], Last, Count, Values, true, Acc);
+ sanitize_is([], Last, Blocks, Count, Values, true, Acc);
_ ->
- do_sanitize_is(I, [], Last, Count, Values, Changed, Acc)
+ do_sanitize_is(I, [], Last, Blocks, Count, Values, Changed, Acc)
end;
-sanitize_is([#b_set{}=I|Is], Last, Count, Values, Changed, Acc) ->
- do_sanitize_is(I, Is, Last, Count, Values, Changed, Acc);
-sanitize_is([], Last, Count, Values, Changed, Acc) ->
+sanitize_is([#b_set{}=I|Is], Last, Blocks, Count, Values, Changed, Acc) ->
+ do_sanitize_is(I, Is, Last, Blocks, Count, Values, Changed, Acc);
+sanitize_is([], Last, _Blocks, Count, Values, Changed, Acc) ->
case Changed of
true ->
{reverse(Acc), Last, Count, Values};
@@ -853,18 +713,19 @@ sanitize_is([], Last, Count, Values, Changed, Acc) ->
end.
do_sanitize_is(#b_set{op=Op,dst=Dst,args=Args0}=I0,
- Is, Last, Count, Values, Changed0, Acc) ->
+ Is, Last, Blocks, Count, Values, Changed0, Acc) ->
Args = sanitize_args(Args0, Values),
case sanitize_instr(Op, Args, I0) of
{value,Value0} ->
Value = #b_literal{val=Value0},
- sanitize_is(Is, Last, Count, Values#{Dst=>Value}, true, Acc);
+ sanitize_is(Is, Last, Blocks, Count, Values#{Dst=>Value},
+ true, Acc);
{ok,I} ->
- sanitize_is(Is, Last, Count, Values, true, [I|Acc]);
+ sanitize_is(Is, Last, Blocks, Count, Values, true, [I|Acc]);
ok ->
I = I0#b_set{args=Args},
Changed = Changed0 orelse Args =/= Args0,
- sanitize_is(Is, Last, Count, Values, Changed, [I|Acc])
+ sanitize_is(Is, Last, Blocks, Count, Values, Changed, [I|Acc])
end.
sanitize_args(Args, Values) ->
@@ -886,7 +747,7 @@ sanitize_instr(phi, PhiArgs, _I) ->
%% turned off.)
%%
%% This phi node always produces the same literal value.
- %% We must do constant progation of the value to ensure
+ %% We must do constant propagation of the value to ensure
%% that we can sanitize any instructions that don't accept
%% literals (such as `get_hd`). This is necessary for
%% correctness, because beam_ssa_codegen:prefer_xregs/2
@@ -946,31 +807,9 @@ sanitize_instr(is_tagged_tuple, [#b_literal{val=Tuple},
true ->
{value,false}
end;
-sanitize_instr(bs_add, [Arg1,Arg2,_|_], I0) ->
- case all(fun(#b_literal{val=Size}) -> is_integer(Size) andalso Size >= 0;
- (#b_var{}) -> true
- end, [Arg1,Arg2]) of
- true -> ok;
- false -> {ok,sanitize_badarg(I0)}
- end;
-sanitize_instr(bs_init, [#b_literal{val=new},#b_literal{val=Sz}|_], I0) ->
- if
- is_integer(Sz), Sz >= 0 -> ok;
- true -> {ok,sanitize_badarg(I0)}
- end;
-sanitize_instr(bs_init, [#b_literal{},_,#b_literal{val=Sz}|_], I0) ->
- if
- is_integer(Sz), Sz >= 0 -> ok;
- true -> {ok,sanitize_badarg(I0)}
- end;
sanitize_instr(_, _, _) ->
ok.
-sanitize_badarg(I) ->
- Func = #b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error},arity=1},
- I#b_set{op=call,args=[Func,#b_literal{val=badarg}]}.
-
remove_unreachable([L|Ls], Blocks, Reachable, Acc) ->
#b_blk{is=Is0} = Blk0 = map_get(L, Blocks),
case split_phis(Is0) of
@@ -1014,123 +853,119 @@ phi_all_same_literal_1(_Phis, _Arg) ->
%%% instruction with the name of the BEAM instruction as the first
%%% argument.
-match_fail_instructions(#st{ssa=Blocks0,args=Args,location=Location}=St) ->
- Ls = maps:to_list(Blocks0),
- Info = {length(Args),Location},
- Blocks = match_fail_instrs_1(Ls, Info, Blocks0),
- St#st{ssa=Blocks}.
+expand_match_fail(#st{ssa=Blocks0,
+ cnt=Count0,
+ args=Args,
+ location=Location}=St) ->
+ Bs = maps:to_list(Blocks0),
+ {Blocks, Count} = expand_mf_bs(Bs, length(Args), Location, Blocks0, Count0),
+ St#st{ssa=Blocks,cnt=Count}.
-match_fail_instrs_1([{L,#b_blk{is=Is0}=Blk}|Bs], Arity, Blocks0) ->
- case match_fail_instrs_blk(Is0, Arity, []) of
+expand_mf_bs([{L,#b_blk{is=Is0}=Blk} | Bs], Arity, Location, Blocks0, Count0) ->
+ case expand_mf_is(Is0, Arity, Location, Count0, []) of
none ->
- match_fail_instrs_1(Bs, Arity, Blocks0);
- Is ->
+ expand_mf_bs(Bs, Arity, Location, Blocks0, Count0);
+ {Is, Count} ->
Blocks = Blocks0#{L:=Blk#b_blk{is=Is}},
- match_fail_instrs_1(Bs, Arity, Blocks)
- end;
-match_fail_instrs_1([], _Arity, Blocks) -> Blocks.
-
-match_fail_instrs_blk([#b_set{op=put_tuple,dst=Dst,
- args=[#b_literal{val=Tag},Val]},
- #b_set{op=call,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error}},
- Dst]}=Call|Is],
- _Arity, Acc) ->
- match_fail_instr(Call, Tag, Val, Is, Acc);
-match_fail_instrs_blk([#b_set{op=call,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error}},
- #b_literal{val={Tag,Val}}]}=Call|Is],
- _Arity, Acc) ->
- match_fail_instr(Call, Tag, #b_literal{val=Val}, Is, Acc);
-match_fail_instrs_blk([#b_set{op=call,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error}},
- #b_literal{val=if_clause}]}=Call|Is],
- _Arity, Acc) ->
- I = Call#b_set{op=match_fail,args=[#b_literal{val=if_end}]},
- reverse(Acc, [I|Is]);
-match_fail_instrs_blk([#b_set{op=call,anno=Anno,
- args=[#b_remote{mod=#b_literal{val=erlang},
- name=#b_literal{val=error}},
- #b_literal{val=function_clause},
- Stk]}=Call],
- {Arity,Location}, Acc) ->
- case match_fail_stk(Stk, Acc, [], []) of
- {[_|_]=Vars,Is} when length(Vars) =:= Arity ->
- case maps:get(location, Anno, none) of
- Location ->
- I = Call#b_set{op=match_fail,
- args=[#b_literal{val=function_clause}|Vars]},
- Is ++ [I];
- _ ->
- %% erlang:error/2 has a different location than the
- %% func_info instruction at the beginning of the function
- %% (probably because of inlining). Keep the original call.
- reverse(Acc, [Call])
- end;
- _ ->
- %% Either the stacktrace could not be picked apart (for example,
- %% if the call to erlang:error/2 was handwritten) or the number
- %% of arguments in the stacktrace was different from the arity
- %% of the host function (because it is the implementation of a
- %% fun). Keep the original call.
- reverse(Acc, [Call])
- end;
-match_fail_instrs_blk([I|Is], Arity, Acc) ->
- match_fail_instrs_blk(Is, Arity, [I|Acc]);
-match_fail_instrs_blk(_, _, _) ->
- none.
+ expand_mf_bs(Bs, Arity, Location, Blocks, Count)
+ end;
+expand_mf_bs([], _Arity, _Location, Blocks, Count) ->
+ {Blocks, Count}.
-match_fail_instr(Call, Tag, Val, Is, Acc) ->
- Op = case Tag of
- badmatch -> Tag;
- case_clause -> case_end;
- try_clause -> try_case_end;
- _ -> none
- end,
- case Op of
- none ->
+expand_mf_is([#b_set{op=match_fail,
+ anno=Anno,
+ args=[#b_literal{val=function_clause} | Args]}=I0 | Is],
+ Arity, Location, Count0, Acc) ->
+ case Anno of
+ #{ location := Location } when length(Args) =:= Arity ->
+ %% We have the same location as the `func_info` instruction at the
+ %% beginning of the function; keep the instruction.
none;
- _ ->
- I = Call#b_set{op=match_fail,args=[#b_literal{val=Op},Val]},
- reverse(Acc, [I|Is])
- end.
-
-match_fail_stk(#b_var{}=V, [#b_set{op=put_list,dst=V,args=[H,T]}|Is], IAcc, VAcc) ->
- match_fail_stk(T, Is, IAcc, [H|VAcc]);
-match_fail_stk(#b_literal{val=[H|T]}, Is, IAcc, VAcc) ->
- match_fail_stk(#b_literal{val=T}, Is, IAcc, [#b_literal{val=H}|VAcc]);
-match_fail_stk(#b_literal{val=[]}, [], IAcc, VAcc) ->
- {reverse(VAcc),IAcc};
-match_fail_stk(T, [#b_set{op=Op}=I|Is], IAcc, VAcc)
- when Op =:= bs_get_tail; Op =:= bs_set_position ->
- match_fail_stk(T, Is, [I|IAcc], VAcc);
-match_fail_stk(_, _, _, _) -> none.
-
-%%%
-%%% Fix tuples.
-%%%
+ #{ inlined := {Name,InlinedArity} } when length(Args) =:= InlinedArity ->
+ %% We're raising this for an inlined function, convert it to a call
+ %% to a stub function that will raise a proper `function_clause`
+ %% exception. The stub function will be created later by
+ %% `create_fc_stubs/2`.
+ Target = #b_local{name=#b_literal{val=Name},arity=InlinedArity},
+ I = I0#b_set{op=call,args=[Target | Args]},
+ {reverse(Acc, [I | Is]), Count0}
+ end;
+expand_mf_is([#b_set{op=match_fail}=I | Is], _Arity, _Location, Count, Acc) ->
+ expand_mf_instr(I, Is, Count, Acc);
+expand_mf_is([I | Is], Arity, Location, Count, Acc) ->
+ expand_mf_is(Is, Arity, Location, Count, [I | Acc]);
+expand_mf_is(_, _, _, _, _) ->
+ none.
-%% fix_tuples(St0) -> St.
-%% If compatibility with a previous version of Erlang has been
-%% requested, tuple creation must be split into two instruction to
-%% mirror the the way tuples are created in BEAM prior to OTP 22.
-%% Each put_tuple instruction is split into put_tuple_arity followed
-%% by put_tuple_elements.
-
-fix_tuples(#st{ssa=Blocks0,cnt=Count0}=St) ->
- F = fun (#b_set{op=put_tuple,args=Args}=Put, C0) ->
- Arity = #b_literal{val=length(Args)},
- {Ignore,C} = new_var('@ssa_ignore', C0),
- {[Put#b_set{op=put_tuple_arity,args=[Arity]},
- #b_set{dst=Ignore,op=put_tuple_elements,args=Args}],C};
- (I, C) -> {[I],C}
+expand_mf_instr(#b_set{args=[#b_literal{val=case_clause} | Args]}=I0,
+ Is, Count, Acc) ->
+ I = I0#b_set{args=[#b_literal{val=case_end} | Args]},
+ {reverse(Acc, [I | Is]), Count};
+expand_mf_instr(#b_set{args=[#b_literal{val=if_clause} | Args]}=I0,
+ Is, Count, Acc) ->
+ I = I0#b_set{args=[#b_literal{val=if_end} | Args]},
+ {reverse(Acc, [I | Is]), Count};
+expand_mf_instr(#b_set{args=[#b_literal{val=try_clause} | Args]}=I0,
+ Is, Count, Acc) ->
+ I = I0#b_set{args=[#b_literal{val=try_case_end} | Args]},
+ {reverse(Acc, [I | Is]), Count};
+expand_mf_instr(#b_set{args=[#b_literal{val=badmatch} | _Args]}=I,
+ Is, Count, Acc) ->
+ {reverse(Acc, [I | Is]), Count};
+expand_mf_instr(#b_set{args=[#b_literal{val=badrecord} | _Args]}=I,
+ Is, Count, Acc) ->
+ {reverse(Acc, [I | Is]), Count};
+expand_mf_instr(#b_set{args=[#b_literal{}|_]=Args}=I0, Is, Count0, Acc) ->
+ %% We don't have a specialized instruction for this: simulate it with
+ %% `erlang:error/1` instead.
+ {Tuple, Count} = new_var('@match_fail', Count0),
+ Put = #b_set{op=put_tuple,dst=Tuple,args=Args},
+ Call = I0#b_set{op=call,
+ args=[#b_remote{mod=#b_literal{val=erlang},
+ name=#b_literal{val=error},
+ arity=1},
+ Tuple]},
+ {reverse(Acc, [Put, Call | Is]), Count}.
+
+%% Create stubs for `function_clause` exceptions generated by
+%% inlined code.
+create_fc_stubs(Fs, #b_module{name=Mod}) ->
+ Stubs0 = usort(find_fc_errors(Fs, [])),
+ Stubs = [begin
+ Seq = seq(0, Arity-1),
+ Args = [#b_var{name=V} || V <- Seq],
+ XRegs = [{x,V} || V <- Seq],
+ Ret = #b_var{name='@ssa_ret'},
+ Regs = maps:from_list([{Ret,{x,0}}|zip(Args, XRegs)]),
+ Anno = #{func_info => {Mod,Name,Arity},
+ location => Location,
+ parameter_info => #{},
+ registers => Regs},
+ Fc = #b_set{op=match_fail,dst=Ret,
+ args=[#b_literal{val=function_clause}|Args]},
+ Blk = #b_blk{is=[Fc],last=#b_ret{arg=Ret}},
+ #b_function{anno=Anno,args=Args,
+ bs=#{0 => Blk},
+ cnt=1}
+ end || {{Name,Arity},Location} <- Stubs0],
+ Fs ++ Stubs.
+
+find_fc_errors([#b_function{bs=Blocks}|Fs], Acc0) ->
+ F = fun(#b_set{anno=Anno,op=call,args=[#b_local{} | _]}, A) ->
+ case Anno of
+ #{ inlined := FA } ->
+ [{FA, maps:get(location, Anno, [])} | A];
+ #{} ->
+ A
+ end;
+ (_, A) ->
+ A
end,
- RPO = beam_ssa:rpo(Blocks0),
- {Blocks,Count} = beam_ssa:flatmapfold_instrs(F, RPO, Count0, Blocks0),
- St#st{ssa=Blocks,cnt=Count}.
+ Acc = beam_ssa:fold_instrs(F, maps:keys(Blocks), Acc0, Blocks),
+ find_fc_errors(Fs, Acc);
+find_fc_errors([], Acc) ->
+ Acc.
+
%%%
%%% Introduce the set_tuple_element instructions to make
@@ -1315,7 +1150,7 @@ place_frames_1([], _, _, Tried, Frames) ->
%% do_place_frame(Label, Blocks, Dominators, Tried0, Frames0) -> {Frames,Tried}.
%% Try to place a frame in this block. This function returns
-%% successfully if it either succeds at placing a frame in this
+%% successfully if it either succeeds at placing a frame in this
%% block, if an ancestor that dominates this block has already placed
%% a frame, or if we have already tried to put a frame in this block.
%%
@@ -1503,16 +1338,17 @@ fix_receives(#st{ssa=Blocks0,cnt=Count0}=St) ->
fix_receives_1([{L,Blk}|Ls], Blocks0, Count0) ->
case Blk of
#b_blk{is=[#b_set{op=peek_message}|_]} ->
- Rm = find_rm_blocks(L, Blocks0),
- LoopExit = find_loop_exit(Rm, Blocks0),
- RPO = beam_ssa:rpo([L], Blocks0),
- Defs0 = beam_ssa:def(RPO, Blocks0),
- CommonUsed = recv_common(Defs0, LoopExit, Blocks0),
- {Blocks1,Count1} = recv_crit_edges(Rm, LoopExit, Blocks0, Count0),
- {Blocks2,Count2} = recv_fix_common(CommonUsed, LoopExit, Rm,
- Blocks1, Count1),
+ Rm0 = find_rm_blocks(L, Blocks0),
+ {Rm,Blocks1,Count1} = split_rm_blocks(Rm0, Blocks0, Count0, []),
+ LoopExit = find_loop_exit(Rm, Blocks1),
+ RPO = beam_ssa:rpo([L], Blocks1),
+ Defs0 = beam_ssa:def(RPO, Blocks1),
+ CommonUsed = recv_common(Defs0, LoopExit, Blocks1),
+ {Blocks2,Count2} = recv_crit_edges(Rm, LoopExit, Blocks1, Count1),
+ {Blocks3,Count3} = recv_fix_common(CommonUsed, LoopExit, Rm,
+ Blocks2, Count2),
Defs = ordsets:subtract(Defs0, CommonUsed),
- {Blocks,Count} = fix_receive(Rm, Defs, Blocks2, Count2),
+ {Blocks,Count} = fix_receive(Rm, Defs, Blocks3, Count3),
fix_receives_1(Ls, Blocks, Count);
#b_blk{} ->
fix_receives_1(Ls, Blocks0, Count0)
@@ -1520,6 +1356,38 @@ fix_receives_1([{L,Blk}|Ls], Blocks0, Count0) ->
fix_receives_1([], Blocks, Count) ->
{Blocks,Count}.
+split_rm_blocks([L|Ls], Blocks0, Count0, Acc) ->
+ #b_blk{is=Is} = map_get(L, Blocks0),
+ case need_split(Is) of
+ false ->
+ %% Don't split because there are no unsafe instructions.
+ split_rm_blocks(Ls, Blocks0, Count0, [L|Acc]);
+ true ->
+ %% An unsafe instruction, such as `bs_get_tail`, was
+ %% found. Split the block before `remove_message`.
+ P = fun(#b_set{op=Op}) ->
+ Op =:= remove_message
+ end,
+ Next = Count0,
+ {Blocks,Count} = beam_ssa:split_blocks([L], P, Blocks0, Count0),
+ true = Count0 =/= Count, %Assertion.
+ split_rm_blocks(Ls, Blocks, Count, [Next|Acc])
+ end;
+split_rm_blocks([], Blocks, Count, Acc) ->
+ {reverse(Acc),Blocks,Count}.
+
+need_split([#b_set{op=Op}|T]) ->
+ case Op of
+ %% Unnecessarily splitting the block can introduce extra
+ %% `move` instructions, so we will avoid splitting as long
+ %% there are only known safe instructions before the
+ %% `remove_message` instruction.
+ get_tuple_element -> need_split(T);
+ recv_marker_clear -> need_split(T);
+ remove_message -> false;
+ _ -> true
+ end.
+
recv_common(_Defs, none, _Blocks) ->
%% There is no common exit block because receive is used
%% in the tail position of a function.
@@ -1608,7 +1476,7 @@ recv_fix_common_1([V|Vs], [Rm|Rms], Msg, Blocks0) ->
Blocks1 = beam_ssa:rename_vars(Ren, RPO, Blocks0),
#b_blk{is=Is0} = Blk0 = map_get(Rm, Blocks1),
Copy = #b_set{op=copy,dst=V,args=[Msg]},
- Is = insert_after_phis(Is0, [Copy]),
+ Is = [Copy|Is0],
Blk = Blk0#b_blk{is=Is},
Blocks = Blocks1#{Rm:=Blk},
recv_fix_common_1(Vs, Rms, Msg, Blocks);
@@ -1643,8 +1511,8 @@ fix_receive([L|Ls], Defs, Blocks0, Count0) ->
Ren = zip(Used, NewVars),
Blocks1 = beam_ssa:rename_vars(Ren, RPO, Blocks0),
#b_blk{is=Is0} = Blk1 = map_get(L, Blocks1),
- CopyIs = [#b_set{op=copy,dst=New,args=[Old]} || {Old,New} <- Ren],
- Is = insert_after_phis(Is0, CopyIs),
+ Is = [#b_set{op=copy,dst=New,args=[Old]} ||
+ {Old,New} <- Ren] ++ Is0,
Blk = Blk1#b_blk{is=Is},
Blocks = Blocks1#{L:=Blk},
fix_receive(Ls, Defs, Blocks, Count);
@@ -2021,10 +1889,6 @@ copy_retval_2([L|Ls], Yregs, Copy0, Blocks0, Count0) ->
copy_retval_2([], _Yregs, none, Blocks, Count) ->
{Blocks,Count}.
-copy_retval_is([#b_set{op=put_tuple_elements,args=Args0}=I0], false, _Yregs,
- Copy, Count, Acc) ->
- I = I0#b_set{args=copy_sub_args(Args0, Copy)},
- {reverse(Acc, [I|acc_copy([], Copy)]),Count};
copy_retval_is([#b_set{op=Op}=I0], false, Yregs, Copy, Count0, Acc0)
when Op =:= call; Op =:= old_make_fun ->
{I,Count,Acc} = place_retval_copy(I0, Yregs, Copy, Count0, Acc0),
@@ -2655,7 +2519,7 @@ reserve_zreg([#b_set{op=Op,dst=Dst}], #b_br{bool=Dst}, ShortLived, A) ->
case use_zreg(Op) of
yes -> [{Dst,z} | A];
no -> A;
- maybe -> reserve_test_zreg(Dst, ShortLived, A)
+ 'maybe' -> reserve_test_zreg(Dst, ShortLived, A)
end;
reserve_zreg([#b_set{op=Op,dst=Dst} | Is], Last, ShortLived, A) ->
case use_zreg(Op) of
@@ -2665,12 +2529,9 @@ reserve_zreg([#b_set{op=Op,dst=Dst} | Is], Last, ShortLived, A) ->
reserve_zreg([], _, _, A) -> A.
use_zreg(bs_match_string) -> yes;
-use_zreg(bs_save) -> yes;
-use_zreg(bs_restore) -> yes;
use_zreg(bs_set_position) -> yes;
use_zreg(kill_try_tag) -> yes;
use_zreg(landingpad) -> yes;
-use_zreg(put_tuple_elements) -> yes;
use_zreg(recv_marker_bind) -> yes;
use_zreg(recv_marker_clear) -> yes;
use_zreg(remove_message) -> yes;
@@ -2680,6 +2541,7 @@ use_zreg(wait_timeout) -> yes;
%% There's no way we can combine these into a test instruction, so we must
%% avoid using a z register if their result is used directly in a branch.
use_zreg(call) -> no;
+use_zreg({bif,element}) -> no;
use_zreg({bif,is_map_key}) -> no;
use_zreg({bif,is_record}) -> no;
use_zreg({bif,map_get}) -> no;
@@ -2689,7 +2551,7 @@ use_zreg(get_tl) -> no;
use_zreg(get_tuple_element) -> no;
%% Assume the instruction can use a z register, provided it's the last in its
%% block and that the result is only used in the terminator.
-use_zreg(_) -> maybe.
+use_zreg(_) -> 'maybe'.
%% If V is defined just before a branch, we may be able to combine it into a
%% test instruction.
@@ -2867,6 +2729,12 @@ reserve_terminator(L, Is, #b_br{bool=#b_var{},succ=Succ,fail=Fail},
#{Arg:=Reg} -> #{Arg=>Reg};
#{} -> #{}
end;
+ #b_set{op=new_try_tag} ->
+ %% We know that no X registers will be used at the
+ %% failure label (a block starting with the
+ %% landingpad instruction), so we can pick up
+ %% register hints from the success label.
+ reserve_terminator_1(L, Succ, Is, Blocks, XsMap, Res);
_ ->
%% Register hints from the success block may not
%% be safe at the failure block, and vice versa.
diff --git a/lib/compiler/src/beam_ssa_recv.erl b/lib/compiler/src/beam_ssa_recv.erl
index 9d6e749fb7..f1d58ffb16 100644
--- a/lib/compiler/src/beam_ssa_recv.erl
+++ b/lib/compiler/src/beam_ssa_recv.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -217,25 +217,37 @@ scan_is([#b_set{op=new_try_tag,dst=Dst}], Blk, Lbl, _Blocks, FuncId, State) ->
%% ignore that branch.
#b_br{bool=Dst,succ=Succ} = Blk#b_blk.last, %Assertion.
scan_add_edge({FuncId, Lbl}, {FuncId, Succ}, State);
-scan_is([#b_set{op=call,dst=Dst,args=[#b_remote{} | _]}=Call | Is],
- Blk, Lbl, Blocks, FuncId, State0) ->
- case {Is, Blk#b_blk.last} of
- {[], #b_ret{arg=Dst}} ->
- scan_is(Is, Blk, Lbl, Blocks, FuncId, State0);
- {[#b_set{op={succeeded,body}}], #b_br{bool=Bool,succ=Succ}} ->
- #b_var{} = Bool, %Assertion.
+scan_is([#b_set{op=call,dst=Dst,args=[#b_remote{} | _]}=Call,
+ #b_set{op={succeeded,body}}],
+ #b_blk{last=#b_br{succ=Succ}}, Lbl, Blocks, FuncId, State0) ->
+ case Blocks of
+ #{ Succ := #b_blk{is=[],last=#b_ret{arg=Dst}}} ->
+ %% External tail call, ignore it altogether.
+ State0;
+ #{} ->
State = si_remote_call(Call, Lbl, Succ, Blocks, FuncId, State0),
- scan_is(Is, Blk, Lbl, Blocks, FuncId, State);
- _ ->
- State = si_remote_call(Call, Lbl, Lbl, Blocks, FuncId, State0),
- scan_is(Is, Blk, Lbl, Blocks, FuncId, State)
+ scan_add_edge({FuncId, Lbl}, {FuncId, Succ}, State)
+ end;
+scan_is([#b_set{op=call,args=[#b_remote{} | _]}=Call | Is],
+ Blk, Lbl, Blocks, FuncId, State0) ->
+ %% Remote call that always succeeds.
+ State = si_remote_call(Call, Lbl, Lbl, Blocks, FuncId, State0),
+ scan_is(Is, Blk, Lbl, Blocks, FuncId, State);
+scan_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | Args]},
+ #b_set{op={succeeded,body},args=[Dst]}],
+ #b_blk{last=#b_br{succ=Succ}},
+ Lbl, Blocks, FuncId, State0) ->
+ case Blocks of
+ #{ Succ := #b_blk{is=[],last=#b_ret{arg=Dst}}} ->
+ %% Local tail call, don't add any edges.
+ scan_add_call(tail, Args, Callee, Lbl, FuncId, State0);
+ #{} ->
+ State = scan_add_call(body, Args, Callee, Lbl, FuncId, State0),
+ scan_add_edge({FuncId, Lbl}, {FuncId, Succ}, State)
end;
-scan_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | Args]}],
- #b_blk{last=#b_ret{arg=Dst}}, Lbl, _Blocks, FuncId, State) ->
- scan_add_call(tail, Args, Callee, Lbl, FuncId, State);
-scan_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | Args]} | Is],
+scan_is([#b_set{op=call,args=[#b_local{}=Callee | Args]} | Is],
Blk, Lbl, Blocks, FuncId, State0) ->
- [#b_set{op={succeeded,body},args=[Dst]}] = Is, %Assertion.
+ %% Local call that always succeeds.
State = scan_add_call(body, Args, Callee, Lbl, FuncId, State0),
scan_is(Is, Blk, Lbl, Blocks, FuncId, State);
scan_is([_I | Is], Blk, Lbl, Blocks, FuncId, State) ->
@@ -894,7 +906,11 @@ coi_creations([], _Blocks, _Defs) ->
[].
make_warning(Term, Anno, Where) ->
- {File, Line} = maps:get(location, Anno, Where),
+ {File, Line} =
+ case maps:get(location, Anno, Where) of
+ {_, _} = Location -> Location;
+ _ -> {"no_file", none}
+ end,
{File,[{Line,?MODULE,Term}]}.
format_opt_info(matches_any_message) ->
diff --git a/lib/compiler/src/beam_ssa_share.erl b/lib/compiler/src/beam_ssa_share.erl
index ae8f582430..bd21655914 100644
--- a/lib/compiler/src/beam_ssa_share.erl
+++ b/lib/compiler/src/beam_ssa_share.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,11 +59,10 @@ block(#b_blk{is=Is0,last=Last0}=Blk, Blocks) ->
%% The terminator was reduced from a two-way branch to a
%% one-way branch.
case reverse(Is0) of
- [#b_set{op={succeeded,Kind},args=[Dst]},#b_set{dst=Dst}|Is] ->
- %% A succeeded instruction must not be followed by a
- %% one-way branch. We must remove both the succeeded
+ [#b_set{op={succeeded,guard},args=[Dst]},#b_set{dst=Dst}|Is] ->
+ %% A {succeeded,guard} instruction must not be followed by
+ %% a one-way branch. We must remove both the succeeded
%% instruction and the instruction preceding it.
- guard = Kind, %Assertion.
Blk#b_blk{is=reverse(Is),last=beam_ssa:normalize(Last)};
_ ->
Blk#b_blk{last=beam_ssa:normalize(Last)}
@@ -151,7 +150,7 @@ are_equivalent(_Succ, #b_blk{is=Is1,last=#b_ret{arg=RetVal1}=Ret1},
false
end;
{#b_var{},#b_var{}} ->
- %% The return values are varibles. We must canonicalize
+ %% The return values are variables. We must canonicalize
%% the blocks (including returns) and compare them.
Can1 = canonical_is(Is1 ++ [Ret1]),
Can2 = canonical_is(Is2 ++ [Ret2]),
@@ -298,7 +297,7 @@ canonical_is(Is) ->
Can.
canonical_is([#b_set{op=Op,dst=Dst,args=Args0}=I|Is], VarMap0, Acc) ->
- Args = [canonical_arg(Arg, VarMap0) || Arg <-Args0],
+ Args = [canonical_arg(Arg, VarMap0) || Arg <- Args0],
Var = {var,map_size(VarMap0)},
VarMap = VarMap0#{Dst=>Var},
LineAnno = case Op of
@@ -313,17 +312,8 @@ canonical_is([#b_set{op=Op,dst=Dst,args=Args0}=I|Is], VarMap0, Acc) ->
beam_ssa:get_anno(location, I, none)
end,
canonical_is(Is, VarMap, {Op,LineAnno,Var,Args,Acc});
-canonical_is([#b_ret{arg=Arg}], VarMap, Acc0) ->
- Acc1 = case Acc0 of
- {call,_Anno,Var,[#b_local{}|_]=Args,PrevAcc} ->
- %% This is a tail-recursive call to a local function.
- %% There will be no line instruction generated;
- %% thus, the annotation is not significant.
- {call,[],Var,Args,PrevAcc};
- _ ->
- Acc0
- end,
- {{ret,canonical_arg(Arg, VarMap),Acc1},VarMap};
+canonical_is([#b_ret{arg=Arg}], VarMap, Acc) ->
+ {{ret,canonical_arg(Arg, VarMap),Acc},VarMap};
canonical_is([#b_br{bool=#b_var{}=Arg,fail=Fail}], VarMap, Acc) ->
%% A previous buggy version of this code omitted the canonicalized
%% argument in the return value. Unfortunately, that worked most
@@ -332,6 +322,19 @@ canonical_is([#b_br{bool=#b_var{}=Arg,fail=Fail}], VarMap, Acc) ->
{{br,canonical_arg(Arg, VarMap),succ,Fail,Acc},VarMap};
canonical_is([#b_br{succ=Succ}], VarMap, Acc) ->
{{br,Succ,Acc},VarMap};
+canonical_is([{tail_br,Arg0,Ret0}], VarMap, Acc0) ->
+ Arg = canonical_arg(Arg0, VarMap),
+ Ret = canonical_arg(Ret0, VarMap),
+ case Acc0 of
+ {{succeeded,body},_,Arg,[Ret],{call,_,Ret,CallArgs,PrevAcc}} ->
+ %% This is a tail-recursive call to a local function.
+ %% There will be no line instruction generated; thus, the
+ %% annotation is not significant.
+ {{tail_call,Ret,CallArgs,PrevAcc},VarMap};
+ _ ->
+ %% Not a tail-recursive call.
+ {{br_ret,Arg,Ret,Acc0},VarMap}
+ end;
canonical_is([], VarMap, Acc) ->
{Acc,VarMap}.
@@ -345,6 +348,14 @@ canonical_terminator(L, #b_br{bool=#b_literal{val=true},succ=Succ}=Br, Blocks) -
[_|_]=Phis ->
{Phis ++ [Br],done}
end;
+canonical_terminator(_L, #b_br{bool=#b_var{}=Arg,succ=Succ,fail=?EXCEPTION_BLOCK}=Br,
+ Blocks) ->
+ case Blocks of
+ #{Succ := #b_blk{is=[],last=#b_ret{arg=Ret}}} ->
+ {[{tail_br,Arg,Ret}],done};
+ #{} ->
+ {[Br],Succ}
+ end;
canonical_terminator(_L, #b_br{bool=#b_var{},succ=Succ}=Br, _Blocks) ->
{[Br],Succ};
canonical_terminator(_, _, _) -> none.
diff --git a/lib/compiler/src/beam_ssa_throw.erl b/lib/compiler/src/beam_ssa_throw.erl
index 8ec64bcd9f..c2dc552119 100644
--- a/lib/compiler/src/beam_ssa_throw.erl
+++ b/lib/compiler/src/beam_ssa_throw.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -170,16 +170,13 @@ si_is([#b_set{op=call,
dst=Dst,
args=[#b_remote{mod=#b_literal{val=erlang},
name=#b_literal{val=throw},
- arity=1}, _Term]}],
- Id, _Lbl, #b_ret{arg=Dst}, Lst, Gst) ->
+ arity=1}, _Term]},
+ #b_set{op={succeeded,body},args=[Dst]}],
+ Id, _Lbl, #b_br{fail=?EXCEPTION_BLOCK}, Lst, Gst) ->
%% Tail throw, handled by caller. We'll need to visit this function again.
#gst{throws=Throws0} = Gst,
Throws = sets:add_element(Id, Throws0),
{Lst, Gst#gst{throws=Throws}};
-si_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | _]}],
- Id, _Lbl, #b_ret{arg=Dst}, Lst, Gst) ->
- %% Tail call, inherit our caller's handler.
- {Lst, inherit_tlh(Id, Callee, Gst)};
si_is([#b_set{op=call,dst=Dst,args=[#b_local{}=Callee | _]},
#b_set{op={succeeded,body},args=[Dst]}],
Id, _Lbl, #b_br{fail=?EXCEPTION_BLOCK}, Lst, Gst) ->
@@ -333,11 +330,12 @@ opt_is([#b_set{op=call,
dst=Dst,
args=[#b_remote{mod=#b_literal{val=erlang},
name=#b_literal{val=throw},
- arity=1}, _Term]}=I0],
- #b_ret{arg=Dst}, Hs) ->
+ arity=1}, _Term]}=I0,
+ #b_set{op={succeeded,body},args=[Dst]}=Succ],
+ #b_br{}, Hs) ->
ThrownType = beam_ssa:get_anno(thrown_type, I0, any),
I = opt_throw(Hs, ThrownType, I0),
- [I];
+ [I, Succ];
opt_is([I | Is], Last, Hs) ->
[I | opt_is(Is, Last, Hs)];
opt_is([], _Last, _Hs) ->
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
index 4ecfdaae8a..77b723caa0 100644
--- a/lib/compiler/src/beam_ssa_type.erl
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,12 +27,12 @@
%%
-module(beam_ssa_type).
--export([opt_start/2, opt_continue/4, opt_finish/3]).
+-export([opt_start/2, opt_continue/4, opt_finish/3, opt_ranges/1]).
-include("beam_ssa_opt.hrl").
-include("beam_types.hrl").
--import(lists, [all/2,any/2,duplicate/2,foldl/3,member/2,
+-import(lists, [duplicate/2,foldl/3,member/2,
keyfind/3,reverse/1,split/2,zip/2]).
%% The maximum number of #b_ret{} terminators a function can have before
@@ -60,35 +60,44 @@
{ func_id :: func_id(),
limit_return :: boolean(),
params :: [beam_ssa:b_var()],
- used_once :: sets:set(beam_ssa:b_var()) }).
+ used_once :: #{ beam_ssa:b_var() => _ } }).
--type type_db() :: #{ beam_ssa:var_name() := type() }.
+-type metadata() :: #metadata{}.
+-type meta_cache() :: #{ func_id() => metadata() }.
+-type type_db() :: #{ beam_ssa:var_name() := ssa_type() }.
+
+%% The types are the same as in 'beam_types.hrl', with the addition of
+%% `(fun(type_db()) -> type())` that defers figuring out the type until it's
+%% actually used. Mainly used to coax more type information out of
+%% `get_tuple_element` where a test on one element (e.g. record tag) may
+%% affect the type of another.
+-type ssa_type() :: fun((type_db()) -> type()) | type().
%%
-spec opt_start(term(), term()) -> term().
opt_start(StMap, FuncDb0) when FuncDb0 =/= #{} ->
- {ArgDb, FuncDb} = signatures(StMap, FuncDb0),
+ {ArgDb, MetaCache, FuncDb} = signatures(StMap, FuncDb0),
- opt_start_1(maps:keys(StMap), ArgDb, StMap, FuncDb);
+ opt_start_1(maps:keys(StMap), ArgDb, StMap, FuncDb, MetaCache);
opt_start(StMap, FuncDb) ->
%% Module-level analysis is disabled, likely because of a call to
%% load_nif/2 or similar. opt_continue/4 will assume that all arguments and
%% return types are 'any'.
{StMap, FuncDb}.
-opt_start_1([Id | Ids], ArgDb, StMap0, FuncDb0) ->
+opt_start_1([Id | Ids], ArgDb, StMap0, FuncDb0, MetaCache) ->
case ArgDb of
#{ Id := ArgTypes } ->
#opt_st{ssa=Linear0,args=Args} = St0 = map_get(Id, StMap0),
Ts = maps:from_list(zip(Args, ArgTypes)),
- {Linear, FuncDb} = opt_function(Linear0, Args, Id, Ts, FuncDb0),
+ {Linear, FuncDb} = opt_function(Linear0, Args, Id, Ts, FuncDb0, MetaCache),
St = St0#opt_st{ssa=Linear},
StMap = StMap0#{ Id := St },
- opt_start_1(Ids, ArgDb, StMap, FuncDb);
+ opt_start_1(Ids, ArgDb, StMap, FuncDb, MetaCache);
#{} ->
%% Unreachable functions must be removed so that opt_continue/4
%% won't process them and potentially taint the argument types of
@@ -96,9 +105,9 @@ opt_start_1([Id | Ids], ArgDb, StMap0, FuncDb0) ->
StMap = maps:remove(Id, StMap0),
FuncDb = maps:remove(Id, FuncDb0),
- opt_start_1(Ids, ArgDb, StMap, FuncDb)
+ opt_start_1(Ids, ArgDb, StMap, FuncDb, MetaCache)
end;
-opt_start_1([], _CommittedArgs, StMap, FuncDb) ->
+opt_start_1([], _CommittedArgs, StMap, FuncDb, _MetaCache) ->
{StMap, FuncDb}.
%%
@@ -124,12 +133,13 @@ opt_start_1([], _CommittedArgs, StMap, FuncDb) ->
-record(sig_st,
{ wl = wl_new() :: worklist(),
committed = #{} :: #{ func_id() => [type()] },
- updates = #{} :: #{ func_id() => [type()] }}).
+ updates = #{} :: #{ func_id() => [type()] },
+ meta_cache = #{} :: meta_cache()}).
signatures(StMap, FuncDb0) ->
State0 = init_sig_st(StMap, FuncDb0),
{State, FuncDb} = signatures_1(StMap, FuncDb0, State0),
- {State#sig_st.committed, FuncDb}.
+ {State#sig_st.committed, State#sig_st.meta_cache, FuncDb}.
signatures_1(StMap, FuncDb0, State0) ->
case wl_next(State0#sig_st.wl) of
@@ -203,11 +213,11 @@ sig_function_1(Id, StMap, State0, FuncDb) ->
Ls = #{ ?EXCEPTION_BLOCK => {incoming, Ts},
0 => {incoming, Ts} },
- Meta = init_metadata(Id, Linear, Args),
+ {Meta, State2} = sig_init_metadata(Id, Linear, Args, State1),
Wl0 = State1#sig_st.wl,
- {State, SuccTypes} = sig_bs(Linear, Ds, Ls, FuncDb, #{}, [], Meta, State1),
+ {State, SuccTypes} = sig_bs(Linear, Ds, Ls, FuncDb, #{}, [], Meta, State2),
WlChanged = wl_changed(Wl0, State#sig_st.wl),
#{ Id := #func_info{succ_types=SuccTypes0}=Entry0 } = FuncDb,
@@ -220,6 +230,17 @@ sig_function_1(Id, StMap, State0, FuncDb) ->
{true, WlChanged, State, FuncDb#{ Id := Entry }}
end.
+%% Get the metadata for a function. If this function has been analysed
+%% previously, retrieve the previously calculated metadata.
+sig_init_metadata(Id, Linear, Args, #sig_st{meta_cache=MetaCache} = State) ->
+ case MetaCache of
+ #{Id := Meta} ->
+ {Meta, State};
+ #{} ->
+ Meta = init_metadata(Id, Linear, Args),
+ {Meta, State#sig_st{meta_cache=MetaCache#{Id => Meta}}}
+ end.
+
sig_bs([{L, #b_blk{is=Is,last=Last0}} | Bs],
Ds0, Ls0, Fdb, Sub0, SuccTypes0, Meta, State0) ->
case Ls0 of
@@ -253,7 +274,7 @@ sig_is([#b_set{op=call,
dst=Dst}=I0 | Is],
Ts0, Ds0, Ls, Fdb, Sub, State0) ->
Args = simplify_args(Args0, Ts0, Sub),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ I1 = I0#b_set{args=Args},
[_ | CallArgs] = Args,
{I, State} = sig_local_call(I1, Callee, CallArgs, Ts0, Fdb, State0),
@@ -264,15 +285,11 @@ sig_is([#b_set{op=call,
sig_is([#b_set{op=call,
args=[#b_var{} | _]=Args0,
dst=Dst}=I0 | Is],
- Ts0, Ds0, Ls, Fdb, Sub, State) ->
+ Ts0, Ds0, Ls, Fdb, Sub, State0) ->
Args = simplify_args(Args0, Ts0, Sub),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ I1 = I0#b_set{args=Args},
- [Fun | _] = Args,
- I = case normalized_type(Fun, Ts0) of
- #t_fun{type=Type} -> beam_ssa:add_anno(result_type, Type, I1);
- _ -> I1
- end,
+ {I, State} = sig_fun_call(I1, Args, Ts0, Ds0, Fdb, Sub, State0),
Ts = update_types(I, Ts0, Ds0),
Ds = Ds0#{ Dst => I },
@@ -281,7 +298,7 @@ sig_is([#b_set{op=MakeFun,args=Args0,dst=Dst}=I0|Is],
Ts0, Ds0, Ls, Fdb, Sub0, State0) when MakeFun =:= make_fun;
MakeFun =:= old_make_fun ->
Args = simplify_args(Args0, Ts0, Sub0),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ I1 = I0#b_set{args=Args},
{I, State} = sig_make_fun(I1, Ts0, Fdb, State0),
@@ -298,6 +315,33 @@ sig_is([I0 | Is], Ts0, Ds0, Ls, Fdb, Sub0, State) ->
sig_is([], Ts, Ds, _Ls, _Fdb, Sub, State) ->
{Ts, Ds, Sub, State}.
+sig_fun_call(I0, Args, Ts, Ds, Fdb, Sub, State0) ->
+ [Fun | CallArgs0] = Args,
+ FunType = normalized_type(Fun, Ts),
+ Arity = length(CallArgs0),
+
+ case {FunType, Ds} of
+ {_, #{ Fun := #b_set{op=make_fun,
+ args=[#b_local{arity=TotalArity}=Callee | Env]} }}
+ when TotalArity =:= Arity + length(Env) ->
+ %% When a fun is used and defined in the same function, we can make
+ %% a direct call since the environment is still available.
+ CallArgs = CallArgs0 ++ simplify_args(Env, Ts, Sub),
+ I = I0#b_set{args=[Callee | CallArgs]},
+ sig_local_call(I, Callee, CallArgs, Ts, Fdb, State0);
+ {#t_fun{target={Name,Arity}}, _} ->
+ %% When a fun lacks free variables, we can make a direct call even
+ %% when we don't know where it was defined.
+ Callee = #b_local{name=#b_literal{val=Name},
+ arity=Arity},
+ I = I0#b_set{args=[Callee | CallArgs0]},
+ sig_local_call(I, Callee, CallArgs0, Ts, Fdb, State0);
+ {#t_fun{type=Type}, _} when Type =/= any ->
+ {beam_ssa:add_anno(result_type, Type, I0), State0};
+ _ ->
+ {I0, State0}
+ end.
+
sig_local_call(I0, Callee, Args, Ts, Fdb, State) ->
ArgTypes = argument_types(Args, Ts),
I = sig_local_return(I0, Callee, ArgTypes, Fdb),
@@ -312,7 +356,7 @@ sig_make_fun(#b_set{op=MakeFun,
MakeFun =:= old_make_fun ->
ArgCount = Callee#b_local.arity - length(FreeVars),
- FVTypes = [raw_type(FreeVar, Ts) || FreeVar <- FreeVars],
+ FVTypes = [concrete_type(FreeVar, Ts) || FreeVar <- FreeVars],
ArgTypes = duplicate(ArgCount, any) ++ FVTypes,
I = sig_local_return(I0, Callee, ArgTypes, Fdb),
@@ -413,23 +457,28 @@ join_arg_types([], [], Ts) ->
%%
%% Optimizes a function based on the type information inferred by signatures/2
-%% and earlier runs of opt_function/5.
+%% and earlier runs of opt_function/5,6.
%%
%% This is pretty straightforward as it only walks through each function once,
%% and because it only makes types narrower it's safe to optimize the functions
%% in any order or not at all.
%%
--spec opt_function(Linear, Args, Id, Ts, FuncDb) -> Result when
+opt_function(Linear, Args, Id, Ts, FuncDb) ->
+ MetaCache = #{},
+ opt_function(Linear, Args, Id, Ts, FuncDb, MetaCache).
+
+-spec opt_function(Linear, Args, Id, Ts, FuncDb, MetaCache) -> Result when
Linear :: [{non_neg_integer(), beam_ssa:b_blk()}],
Args :: [beam_ssa:b_var()],
Id :: func_id(),
Ts :: type_db(),
FuncDb :: func_info_db(),
- Result :: {Linear, FuncDb}.
-opt_function(Linear, Args, Id, Ts, FuncDb) ->
+ Result :: {Linear, FuncDb},
+ MetaCache :: meta_cache().
+opt_function(Linear, Args, Id, Ts, FuncDb, MetaCache) ->
try
- do_opt_function(Linear, Args, Id, Ts, FuncDb)
+ do_opt_function(Linear, Args, Id, Ts, FuncDb, MetaCache)
catch
Class:Error:Stack ->
#b_local{name=#b_literal{val=Name},arity=Arity} = Id,
@@ -437,7 +486,7 @@ opt_function(Linear, Args, Id, Ts, FuncDb) ->
erlang:raise(Class, Error, Stack)
end.
-do_opt_function(Linear0, Args, Id, Ts, FuncDb0) ->
+do_opt_function(Linear0, Args, Id, Ts, FuncDb0, MetaCache) ->
FakeCall = #b_set{op=call,args=[#b_remote{mod=#b_literal{val=unknown},
name=#b_literal{val=unknown},
arity=0}]},
@@ -448,7 +497,12 @@ do_opt_function(Linear0, Args, Id, Ts, FuncDb0) ->
Ls = #{ ?EXCEPTION_BLOCK => {incoming, Ts},
0 => {incoming, Ts} },
- Meta = init_metadata(Id, Linear0, Args),
+ Meta = case MetaCache of
+ #{Id := Meta0} ->
+ Meta0;
+ #{} ->
+ init_metadata(Id, Linear0, Args)
+ end,
{Linear, FuncDb, SuccTypes} =
opt_bs(Linear0, Ds, Ls, FuncDb0, #{}, [], Meta, []),
@@ -473,7 +527,7 @@ opt_bs([{L, #b_blk{is=Is0,last=Last0}=Blk0} | Bs],
{incoming, Ts0} = Incoming, %Assertion.
{Is, Ts, Ds, Fdb, Sub} =
- opt_is(Is0, Ts0, Ds0, Ls0, Fdb0, Sub0, Meta, []),
+ opt_is(Is0, Ts0, Ds0, Ls0, Fdb0, Sub0, Meta, []),
Last1 = simplify_terminator(Last0, Ts, Ds, Sub),
SuccTypes = update_success_types(Last1, Ts, Ds, Meta, SuccTypes0),
@@ -497,7 +551,7 @@ opt_is([#b_set{op=call,
dst=Dst}=I0 | Is],
Ts0, Ds0, Ls, Fdb0, Sub, Meta, Acc) ->
Args = simplify_args(Args0, Ts0, Sub),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ I1 = I0#b_set{args=Args},
[_ | CallArgs] = Args,
{I, Fdb} = opt_local_call(I1, Callee, CallArgs, Dst, Ts0, Fdb0, Meta),
@@ -508,17 +562,12 @@ opt_is([#b_set{op=call,
opt_is([#b_set{op=call,
args=[#b_var{} | _]=Args0,
dst=Dst}=I0 | Is],
- Ts0, Ds0, Ls, Fdb, Sub, Meta, Acc) ->
+ Ts0, Ds0, Ls, Fdb0, Sub, Meta, Acc) ->
Args = simplify_args(Args0, Ts0, Sub),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
- [Fun | _] = Args,
- I = case normalized_type(Fun, Ts0) of
- #t_fun{type=Type} when Type =/= any ->
- beam_ssa:add_anno(result_type, Type, I1);
- _ ->
- I1
- end,
+ I1 = opt_anno_types(I0#b_set{args=Args}, Ts0),
+
+ {I, Fdb} = opt_fun_call(I1, Args, Ts0, Ds0, Fdb0, Sub, Meta),
Ts = update_types(I, Ts0, Ds0),
Ds = Ds0#{ Dst => I },
@@ -527,7 +576,7 @@ opt_is([#b_set{op=MakeFun,args=Args0,dst=Dst}=I0|Is],
Ts0, Ds0, Ls, Fdb0, Sub0, Meta, Acc) when MakeFun =:= make_fun;
MakeFun =:= old_make_fun ->
Args = simplify_args(Args0, Ts0, Sub0),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ I1 = I0#b_set{args=Args},
{I, Fdb} = opt_make_fun(I1, Ts0, Fdb0, Meta),
@@ -536,7 +585,8 @@ opt_is([#b_set{op=MakeFun,args=Args0,dst=Dst}=I0|Is],
opt_is(Is, Ts, Ds, Ls, Fdb, Sub0, Meta, [I|Acc]);
opt_is([I0 | Is], Ts0, Ds0, Ls, Fdb, Sub0, Meta, Acc) ->
case simplify(I0, Ts0, Ds0, Ls, Sub0) of
- {#b_set{}=I, Ts, Ds} ->
+ {#b_set{}=I1, Ts, Ds} ->
+ I = opt_anno_types(I1, Ts),
opt_is(Is, Ts, Ds, Ls, Fdb, Sub0, Meta, [I | Acc]);
Sub when is_map(Sub) ->
opt_is(Is, Ts0, Ds0, Ls, Fdb, Sub, Meta, Acc)
@@ -544,6 +594,88 @@ opt_is([I0 | Is], Ts0, Ds0, Ls, Fdb, Sub0, Meta, Acc) ->
opt_is([], Ts, Ds, _Ls, Fdb, Sub, _Meta, Acc) ->
{reverse(Acc), Ts, Ds, Fdb, Sub}.
+opt_anno_types(#b_set{op=Op,args=Args}=I, Ts) ->
+ case benefits_from_type_anno(Op, Args) of
+ true -> opt_anno_types_1(I, Args, Ts, 0, #{});
+ false -> I
+ end.
+
+opt_anno_types_1(I, [#b_var{}=Var | Args], Ts, Index, Acc0) ->
+ case concrete_type(Var, Ts) of
+ any ->
+ opt_anno_types_1(I, Args, Ts, Index + 1, Acc0);
+ Type ->
+ %% Note that we annotate arguments by their index instead of their
+ %% variable name, as they may be renamed by `beam_ssa_pre_codegen`.
+ Acc = Acc0#{ Index => Type },
+ opt_anno_types_1(I, Args, Ts, Index + 1, Acc)
+ end;
+opt_anno_types_1(I, [_Arg | Args], Ts, Index, Acc) ->
+ opt_anno_types_1(I, Args, Ts, Index + 1, Acc);
+opt_anno_types_1(#b_set{anno=Anno0}=I, [], _Ts, _Index, Acc) ->
+ case Anno0 of
+ #{ arg_types := Acc } ->
+ I;
+ #{ arg_types := _ } when Acc =:= #{} ->
+ %% One or more arguments have been simplified to literal values.
+ Anno = maps:remove(arg_types, Anno0),
+ I#b_set{anno=Anno};
+ #{} ->
+ Anno = Anno0#{ arg_types => Acc },
+ I#b_set{anno=Anno}
+ end.
+
+%% Only add type annotations when we know we'll make good use of them.
+benefits_from_type_anno({bif,'=:='}, _Args) ->
+ true;
+benefits_from_type_anno({bif,'=/='}, _Args) ->
+ true;
+benefits_from_type_anno({bif,Op}, Args) ->
+ not erl_internal:bool_op(Op, length(Args));
+benefits_from_type_anno(bs_create_bin, _Args) ->
+ true;
+benefits_from_type_anno(is_tagged_tuple, _Args) ->
+ true;
+benefits_from_type_anno(call, [#b_var{} | _]) ->
+ true;
+benefits_from_type_anno({float,convert}, _Args) ->
+ %% Note: The {float,convert} instruction does not exist when
+ %% the main type optimizer pass is run. It is created and
+ %% annotated by ssa_opt_float1 in beam_ssa_opt, and can also
+ %% be annotated by opt_ranges/1.
+ true;
+benefits_from_type_anno(get_map_element, _Args) ->
+ true;
+benefits_from_type_anno(has_map_field, _Args) ->
+ true;
+benefits_from_type_anno(_Op, _Args) ->
+ false.
+
+opt_fun_call(#b_set{dst=Dst}=I0, [Fun | CallArgs0], Ts, Ds, Fdb, Sub, Meta) ->
+ FunType = normalized_type(Fun, Ts),
+ Arity = length(CallArgs0),
+ case {FunType, Ds} of
+ {_, #{ Fun := #b_set{op=make_fun,
+ args=[#b_local{arity=TotalArity}=Callee | Env]} }}
+ when TotalArity =:= Arity + length(Env) ->
+ %% When a fun is used and defined in the same function, we can make
+ %% a direct call since the environment is still available.
+ CallArgs = CallArgs0 ++ simplify_args(Env, Ts, Sub),
+ I = I0#b_set{args=[Callee | CallArgs]},
+ opt_local_call(I, Callee, CallArgs, Dst, Ts, Fdb, Meta);
+ {#t_fun{target={Name,Arity}}, _} ->
+ %% When a fun lacks free variables, we can make a direct call even
+ %% when we don't know where it was defined.
+ Callee = #b_local{name=#b_literal{val=Name},
+ arity=Arity},
+ I = I0#b_set{args=[Callee | CallArgs0]},
+ opt_local_call(I, Callee, CallArgs0, Dst, Ts, Fdb, Meta);
+ {#t_fun{type=Type}, _} when Type =/= any ->
+ {beam_ssa:add_anno(result_type, Type, I0), Fdb};
+ _ ->
+ {I0, Fdb}
+ end.
+
opt_local_call(I0, Callee, Args, Dst, Ts, Fdb, Meta) ->
ArgTypes = argument_types(Args, Ts),
I = opt_local_return(I0, Callee, ArgTypes, Fdb),
@@ -571,7 +703,7 @@ opt_make_fun(#b_set{op=MakeFun,
Ts, Fdb, Meta) when MakeFun =:= make_fun;
MakeFun =:= old_make_fun ->
ArgCount = Callee#b_local.arity - length(FreeVars),
- FVTypes = [raw_type(FreeVar, Ts) || FreeVar <- FreeVars],
+ FVTypes = [concrete_type(FreeVar, Ts) || FreeVar <- FreeVars],
ArgTypes = duplicate(ArgCount, any) ++ FVTypes,
I = opt_local_return(I0, Callee, ArgTypes, Fdb),
@@ -636,6 +768,153 @@ opt_finish_1([], [], Acc) ->
Acc.
%%%
+%%% This sub pass is run once after the main type sub pass
+%%% to annotate more instructions with integer ranges.
+%%%
+%%% The main type sub pass annotates certain instructions with
+%%% their types to help the JIT generate better code.
+%%%
+%%% Example:
+%%%
+%%% foo(N0) ->
+%%% N1 = N0 band 3,
+%%% N = N1 + 1, % N1 is in 0..3
+%%% element(N,
+%%% {zero,one,two,three}).
+%%%
+%%% The main type pass is able to figure out the range for `N1` but
+%%% not for `N`. The reason is that the type pass iterates until it
+%%% reaches a fixpoint. To guarantee that it will converge, ranges for
+%%% results must only be calculated for operations that retain or
+%%% shrink the ranges of their arguments.
+%%%
+%%% Therefore, to ensure convergence, the main type pass can only
+%%% safely calculate ranges for results of operations such as `and`,
+%%% `bsr`, and `rem`, but not for operations such as `+`, '-', '*',
+%%% and `bsl`.
+%%%
+%%% This sub pass will start from the types found in the annotations
+%%% and propagate them forward through arithmetic instructions within
+%%% the same function.
+%%%
+%%% For the example, this sub pass adds a new annotation for `N`:
+%%%
+%%% foo(N0) ->
+%%% N1 = N0 band 3,
+%%% N = N1 + 1, % N1 is in 0..3
+%%% element(N, % N is in 1..4
+%%% {zero,one,two,three}).
+%%%
+%%% With a known range and known tuple size, the JIT is able to remove
+%%% all range checks for the `element/2` instruction.
+%%%
+
+-spec opt_ranges(Blocks0) -> Blocks when
+ Blocks0 :: beam_ssa:block_map(),
+ Blocks :: beam_ssa:block_map().
+
+opt_ranges(Blocks) ->
+ RPO = beam_ssa:rpo(Blocks),
+ Tss = #{0 => #{}, ?EXCEPTION_BLOCK => #{}},
+ ranges(RPO, Tss, Blocks).
+
+ranges([L|Ls], Tss0, Blocks0) ->
+ #b_blk{is=Is0} = Blk0 = map_get(L, Blocks0),
+ Ts0 = map_get(L, Tss0),
+ {Is,Ts} = ranges_is(Is0, Ts0, []),
+ Blk = Blk0#b_blk{is=Is},
+ Blocks = Blocks0#{L := Blk},
+ Tss = ranges_successors(beam_ssa:successors(Blk), Ts, Tss0),
+ ranges(Ls, Tss, Blocks);
+ranges([], _Tss, Blocks) -> Blocks.
+
+ranges_is([#b_set{op=Op,args=Args}=I0|Is], Ts0, Acc) ->
+ case benefits_from_type_anno(Op, Args) of
+ false ->
+ ranges_is(Is, Ts0, [I0|Acc]);
+ true ->
+ I = update_anno_types(I0, Ts0),
+ Ts = ranges_propagate_types(I, Ts0),
+ ranges_is(Is, Ts, [I|Acc])
+ end;
+ranges_is([], Ts, Acc) ->
+ {reverse(Acc),Ts}.
+
+ranges_successors([?EXCEPTION_BLOCK|Ls], Ts, Tss) ->
+ ranges_successors(Ls, Ts, Tss);
+ranges_successors([L|Ls], Ts0, Tss0) ->
+ case Tss0 of
+ #{L := Ts1} ->
+ Ts = join_types(Ts0, Ts1),
+ Tss = Tss0#{L := Ts},
+ ranges_successors(Ls, Ts0, Tss);
+ #{} ->
+ Tss = Tss0#{L => Ts0},
+ ranges_successors(Ls, Ts0, Tss)
+ end;
+ranges_successors([], _, Tss) -> Tss.
+
+ranges_propagate_types(#b_set{anno=Anno,op={bif,_}=Op,args=Args,dst=Dst}, Ts) ->
+ case Anno of
+ #{arg_types := ArgTypes0} ->
+ ArgTypes = ranges_get_arg_types(Args, 0, ArgTypes0),
+ case beam_call_types:arith_type(Op, ArgTypes) of
+ any -> Ts;
+ T -> Ts#{Dst => T}
+ end;
+ #{} ->
+ Ts
+ end;
+ranges_propagate_types(_, Ts) -> Ts.
+
+ranges_get_arg_types([#b_var{}|As], Index, ArgTypes) ->
+ case ArgTypes of
+ #{Index := Type} ->
+ [Type|ranges_get_arg_types(As, Index + 1, ArgTypes)];
+ #{} ->
+ [any|ranges_get_arg_types(As, Index + 1, ArgTypes)]
+ end;
+ranges_get_arg_types([#b_literal{val=Value}|As], Index, ArgTypes) ->
+ Type = beam_types:make_type_from_value(Value),
+ [Type|ranges_get_arg_types(As, Index + 1, ArgTypes)];
+ranges_get_arg_types([], _, _) -> [].
+
+update_anno_types(#b_set{anno=Anno,args=Args}=I, Ts) ->
+ ArgTypes1 = case Anno of
+ #{arg_types := ArgTypes0} -> ArgTypes0;
+ #{} -> #{}
+ end,
+ ArgTypes = update_anno_types_1(Args, Ts, 0, ArgTypes1),
+ case Anno of
+ #{arg_types := ArgTypes} ->
+ I;
+ #{} when map_size(ArgTypes) =/= 0 ->
+ I#b_set{anno=Anno#{arg_types => ArgTypes}};
+ #{} ->
+ I
+ end.
+
+update_anno_types_1([#b_var{}=V|As], Ts, Index, ArgTypes) ->
+ T0 = case ArgTypes of
+ #{Index := T00} -> T00;
+ #{} -> any
+ end,
+ T1 = case Ts of
+ #{V := T11} -> T11;
+ #{} -> any
+ end,
+ case beam_types:meet(T0, T1) of
+ any ->
+ update_anno_types_1(As, Ts, Index + 1, ArgTypes);
+ T ->
+ true = T =/= none, %Assertion.
+ update_anno_types_1(As, Ts, Index + 1, ArgTypes#{Index => T})
+ end;
+update_anno_types_1([_|As], Ts, Index, ArgTypes) ->
+ update_anno_types_1(As, Ts, Index + 1, ArgTypes);
+update_anno_types_1([], _, _, ArgTypes) -> ArgTypes.
+
+%%%
%%% Optimization helpers
%%%
@@ -650,7 +929,7 @@ simplify_terminator(#b_switch{arg=Arg0,fail=Fail,list=List0}=Sw0,
List = [{Val,Lbl} || {Val,Lbl} <- List0, Lbl =/= Fail],
case beam_ssa:normalize(Sw0#b_switch{arg=Arg,list=List}) of
#b_switch{}=Sw ->
- case beam_types:is_boolean_type(raw_type(Arg, Ts)) of
+ case beam_types:is_boolean_type(concrete_type(Arg, Ts)) of
true -> simplify_switch_bool(Sw, Ts, Ds, Sub);
false -> Sw
end;
@@ -688,12 +967,12 @@ simplify(#b_set{op=phi,dst=Dst,args=Args0}=I0, Ts0, Ds0, Ls, Sub) ->
Ds = Ds0#{ Dst => I },
{I, Ts, Ds}
end;
-simplify(#b_set{op={succeeded,Kind},args=[Arg],dst=Dst}=I0,
+simplify(#b_set{op={succeeded,Kind},args=[Arg],dst=Dst}=I,
Ts0, Ds0, _Ls, Sub) ->
- Type = case will_succeed(I0, Ts0, Ds0, Sub) of
+ Type = case will_succeed(I, Ts0, Ds0, Sub) of
yes -> beam_types:make_atom(true);
no -> beam_types:make_atom(false);
- maybe -> beam_types:make_boolean()
+ 'maybe' -> beam_types:make_boolean()
end,
case Type of
#t_atom{elements=[true]} ->
@@ -711,14 +990,13 @@ simplify(#b_set{op={succeeded,Kind},args=[Arg],dst=Dst}=I0,
%% Note that we never simplify args; this instruction is specific
%% to the operation being checked, and simplifying could break that
%% connection.
- I = beam_ssa:normalize(I0),
Ts = Ts0#{ Dst => Type },
Ds = Ds0#{ Dst => I },
{I, Ts, Ds}
end;
simplify(#b_set{op=bs_match,dst=Dst,args=Args0}=I0, Ts0, Ds0, _Ls, Sub) ->
Args = simplify_args(Args0, Ts0, Sub),
- I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ I1 = I0#b_set{args=Args},
I2 = case {Args0,Args} of
{[_,_,_,#b_var{},_],[Type,Val,Flags,#b_literal{val=all},Unit]} ->
%% The size `all` is used for the size of the final binary
@@ -730,8 +1008,7 @@ simplify(#b_set{op=bs_match,dst=Dst,args=Args0}=I0, Ts0, Ds0, _Ls, Sub) ->
end,
%% We KNOW that simplify/2 will return a #b_set{} record when called with
%% a bs_match instruction.
- #b_set{} = I3 = simplify(I2, Ts0),
- I = beam_ssa:normalize(I3),
+ #b_set{} = I = simplify(I2, Ts0),
Ts = update_types(I, Ts0, Ds0),
Ds = Ds0#{ Dst => I },
{I, Ts, Ds};
@@ -739,8 +1016,7 @@ simplify(#b_set{dst=Dst,args=Args0}=I0, Ts0, Ds0, _Ls, Sub) ->
Args = simplify_args(Args0, Ts0, Sub),
I1 = beam_ssa:normalize(I0#b_set{args=Args}),
case simplify(I1, Ts0) of
- #b_set{}=I2 ->
- I = beam_ssa:normalize(I2),
+ #b_set{}=I ->
Ts = update_types(I, Ts0, Ds0),
Ds = Ds0#{ Dst => I },
{I, Ts, Ds};
@@ -816,18 +1092,6 @@ simplify(#b_set{op={bif,tuple_size},args=[Term]}=I, Ts) ->
_ ->
I
end;
-simplify(#b_set{op={bif,is_function},args=[Fun,#b_literal{val=Arity}]}=I, Ts)
- when is_integer(Arity), Arity >= 0 ->
- case normalized_type(Fun, Ts) of
- #t_fun{arity=any} ->
- I;
- #t_fun{arity=Arity} ->
- #b_literal{val=true};
- any ->
- I;
- _ ->
- #b_literal{val=false}
- end;
simplify(#b_set{op={bif,is_map_key},args=[Key,Map]}=I, Ts) ->
case normalized_type(Map, Ts) of
#t_map{} ->
@@ -860,8 +1124,8 @@ simplify(#b_set{op={bif,Op0},args=Args}=I, Ts) when Op0 =:= '==';
simplify(#b_set{op={bif,'=:='},args=[Same,Same]}, _Ts) ->
#b_literal{val=true};
simplify(#b_set{op={bif,'=:='},args=[LHS,RHS]}=I, Ts) ->
- LType = raw_type(LHS, Ts),
- RType = raw_type(RHS, Ts),
+ LType = concrete_type(LHS, Ts),
+ RType = concrete_type(RHS, Ts),
case beam_types:meet(LType, RType) of
none ->
#b_literal{val=false};
@@ -886,6 +1150,19 @@ simplify(#b_set{op={bif,'=:='},args=[LHS,RHS]}=I, Ts) ->
eval_bif(I, Ts)
end
end;
+simplify(#b_set{op={bif,is_list},args=[Src]}=I0, Ts) ->
+ case concrete_type(Src, Ts) of
+ #t_union{list=#t_cons{}} ->
+ I = I0#b_set{op=is_nonempty_list,args=[Src]},
+ %% We might need to convert back to is_list/1 if it turns
+ %% out that this instruction is followed by a #b_ret{}
+ %% terminator.
+ beam_ssa:add_anno(was_bif_is_list, true, I);
+ #t_union{list=nil} ->
+ I0#b_set{op={bif,'=:='},args=[Src,#b_literal{val=[]}]};
+ _ ->
+ eval_bif(I0, Ts)
+ end;
simplify(#b_set{op={bif,Op},args=Args}=I, Ts) ->
Types = normalized_types(Args, Ts),
case is_float_op(Op, Types) of
@@ -896,7 +1173,7 @@ simplify(#b_set{op={bif,Op},args=Args}=I, Ts) ->
eval_bif(beam_ssa:add_anno(float_op, AnnoArgs, I), Ts)
end;
simplify(#b_set{op=bs_extract,args=[Ctx]}=I, Ts) ->
- case raw_type(Ctx, Ts) of
+ case concrete_type(Ctx, Ts) of
#t_bitstring{} ->
%% This is a bs_match that has been rewritten as a bs_get_tail;
%% just return the input as-is.
@@ -910,7 +1187,7 @@ simplify(#b_set{op=bs_match,
#b_literal{val=OpUnit}]}=I, Ts) ->
%% <<..., Foo/binary>> can be rewritten as <<..., Foo/bits>> if we know the
%% unit is correct.
- #t_bs_context{tail_unit=CtxUnit} = raw_type(Ctx, Ts),
+ #t_bs_context{tail_unit=CtxUnit} = concrete_type(Ctx, Ts),
if
CtxUnit rem OpUnit =:= 0 ->
I#b_set{op=bs_get_tail,args=[Ctx]};
@@ -918,7 +1195,7 @@ simplify(#b_set{op=bs_match,
I
end;
simplify(#b_set{op=bs_start_match,args=[#b_literal{val=new}, Src]}=I, Ts) ->
- case raw_type(Src, Ts) of
+ case concrete_type(Src, Ts) of
#t_bs_context{} ->
I#b_set{op=bs_start_match,args=[#b_literal{val=resume}, Src]};
_ ->
@@ -945,7 +1222,51 @@ simplify(#b_set{op=is_nonempty_list,args=[Src]}=I, Ts) ->
end;
simplify(#b_set{op=is_tagged_tuple,
args=[Src,#b_literal{val=Size},#b_literal{}=Tag]}=I, Ts) ->
- simplify_is_record(I, normalized_type(Src, Ts), Size, Tag, Ts);
+ case concrete_type(Src, Ts) of
+ #t_union{tuple_set=TupleSet}=U ->
+ %% A union of different types, one of them (probably)
+ %% a tuple. Dig out the tuple type from the union and
+ %% find out whether it will match.
+ TupleOnlyType = #t_union{tuple_set=TupleSet},
+ TT = beam_types:normalize(TupleOnlyType),
+ case simplify_is_record(I, TT, Size, Tag, Ts) of
+ #b_literal{val=true} ->
+ %% The tuple part of the union will always match.
+ %% A simple is_tuple/1 test will be sufficient to
+ %% distinguish the tuple from the other types in
+ %% the union.
+ I#b_set{op={bif,is_tuple},args=[Src]};
+ #b_literal{val=false}=False ->
+ %% Src is never a tuple.
+ False;
+ _ ->
+ %% More than one type of tuple can match. Find out
+ %% whether the possible tuples can be
+ %% distinguished by size.
+ TupleArityType = #t_tuple{size=Size,exact=true},
+ TTT = beam_types:meet(TupleArityType, TupleOnlyType),
+ case simplify_is_record(I, TTT, Size, Tag, Ts) of
+ #b_literal{val=true} ->
+ %% The possible tuple types have different sizes.
+ %% Example: {ok, _} | {error, _, _}.
+ case beam_types:normalize(U) of
+ #t_tuple{} ->
+ %% Src is known to be a tuple, so it will
+ %% be sufficient to test the arity.
+ beam_ssa:add_anno(constraints, arity, I);
+ any ->
+ %% Src might not be a tuple. Must
+ %% test for a tuple with a given
+ %% arity.
+ beam_ssa:add_anno(constraints, tuple_arity, I)
+ end;
+ _ ->
+ I
+ end
+ end;
+ SimpleType ->
+ simplify_is_record(I, SimpleType, Size, Tag, Ts)
+ end;
simplify(#b_set{op=put_list,args=[#b_literal{val=H},
#b_literal{val=T}]}, _Ts) ->
#b_literal{val=[H|T]};
@@ -997,7 +1318,7 @@ will_succeed(#b_set{args=[Src]}, Ts, Ds, Sub) ->
%% There can't be any substitution because the instruction
%% is still there.
false = is_map_key(Src, Sub), %Assertion.
- will_succeed_1(I, Src, Ts, Sub);
+ will_succeed_1(I, Src, Ts);
{#{}, #{}} ->
%% The checked instruction has been removed and substituted, so we
%% can assume it always succeeds.
@@ -1005,10 +1326,10 @@ will_succeed(#b_set{args=[Src]}, Ts, Ds, Sub) ->
yes
end.
-will_succeed_1(#b_set{op=bs_get_tail}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=bs_get_tail}, _Src, _Ts) ->
yes;
-will_succeed_1(#b_set{op=bs_start_match,args=[_, Arg]}, _Src, Ts, _Sub) ->
- ArgType = raw_type(Arg, Ts),
+will_succeed_1(#b_set{op=bs_start_match,args=[_, Arg]}, _Src, Ts) ->
+ ArgType = concrete_type(Arg, Ts),
case beam_types:is_bs_matchable_type(ArgType) of
true ->
%% In the future we may be able to remove this instruction
@@ -1019,90 +1340,66 @@ will_succeed_1(#b_set{op=bs_start_match,args=[_, Arg]}, _Src, Ts, _Sub) ->
%% Is it at all possible to match?
case beam_types:meet(ArgType, #t_bs_matchable{}) of
none -> no;
- _ -> maybe
+ _ -> 'maybe'
end
end;
-will_succeed_1(#b_set{op={bif,Bif},args=BifArgs}, _Src, Ts, _Sub) ->
+will_succeed_1(#b_set{op={bif,Bif},args=BifArgs}, _Src, Ts) ->
ArgTypes = normalized_types(BifArgs, Ts),
beam_call_types:will_succeed(erlang, Bif, ArgTypes);
will_succeed_1(#b_set{op=call,
args=[#b_remote{mod=#b_literal{val=Mod},
- name=#b_literal{val=Func}} |
+ name=#b_literal{val=Func}} |
CallArgs]},
- _Src, Ts, _Sub) ->
- ArgTypes = normalized_types(CallArgs, Ts),
- beam_call_types:will_succeed(Mod, Func, ArgTypes);
+ _Src, Ts) ->
+ ArgTypes = normalized_types(CallArgs, Ts),
+ beam_call_types:will_succeed(Mod, Func, ArgTypes);
-will_succeed_1(#b_set{op=get_hd}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=get_hd}, _Src, _Ts) ->
yes;
-will_succeed_1(#b_set{op=get_tl}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=get_tl}, _Src, _Ts) ->
yes;
-will_succeed_1(#b_set{op=has_map_field}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=has_map_field}, _Src, _Ts) ->
yes;
-will_succeed_1(#b_set{op=get_tuple_element}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=get_tuple_element}, _Src, _Ts) ->
yes;
-will_succeed_1(#b_set{op=put_tuple}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=put_tuple}, _Src, _Ts) ->
yes;
-
-%% Remove the success branch from binary operations with invalid
-%% sizes. That will remove subsequent bs_put and bs_match instructions,
-%% which are probably not loadable.
-will_succeed_1(#b_set{op=bs_add,args=[Arg1,Arg2,_]},
- _Src, _Ts, _Sub) ->
- case all(fun(#b_literal{val=Size}) -> is_integer(Size) andalso Size >= 0;
- (#b_var{}) -> true
- end, [Arg1,Arg2]) of
- true -> maybe;
- false -> no
- end;
-will_succeed_1(#b_set{op=bs_init,
- args=[#b_literal{val=new},#b_literal{val=Size},_Unit]},
- _Src, _Ts, _Sub) ->
- if
- is_integer(Size), Size >= 0 ->
- maybe;
- true ->
- no
- end;
-will_succeed_1(#b_set{op=bs_init,
- args=[#b_literal{},_,#b_literal{val=Size},_Unit]},
- _Src, _Ts, _Sub) ->
- if
- is_integer(Size), Size >= 0 ->
- maybe;
- true ->
- no
- end;
+will_succeed_1(#b_set{op=bs_create_bin}, _Src, _Ts) ->
+ %% Intentionally don't try to determine whether construction will
+ %% fail. Construction is unlikely to fail, and if it fails, the
+ %% instruction in the runtime system will generate an exception with
+ %% better information of what went wrong.
+ 'maybe';
will_succeed_1(#b_set{op=bs_match,
args=[#b_literal{val=Type},_,_,#b_literal{val=Size},_]},
- _Src, _Ts, _Sub) ->
+ _Src, _Ts) ->
if
is_integer(Size), Size >= 0 ->
- maybe;
+ 'maybe';
Type =:= binary, Size =:= all ->
%% `all` is a legal size for binary segments at the end of
%% a binary pattern.
- maybe;
+ 'maybe';
true ->
%% Invalid size. Matching will fail.
no
end;
%% These operations may fail even though we know their return value on success.
-will_succeed_1(#b_set{op=call}, _Src, _Ts, _Sub) ->
- maybe;
-will_succeed_1(#b_set{op=get_map_element}, _Src, _Ts, _Sub) ->
- maybe;
-will_succeed_1(#b_set{op=wait_timeout}, _Src, _Ts, _Sub) ->
+will_succeed_1(#b_set{op=call}, _Src, _Ts) ->
+ 'maybe';
+will_succeed_1(#b_set{op=get_map_element}, _Src, _Ts) ->
+ 'maybe';
+will_succeed_1(#b_set{op=wait_timeout}, _Src, _Ts) ->
%% It is essential to keep the {succeeded,body} instruction to
%% ensure that the failure edge, which potentially leads to a
%% landingpad, is preserved. If the failure edge is removed, a Y
%% register holding a `try` tag could be reused prematurely.
- maybe;
+ 'maybe';
-will_succeed_1(#b_set{}, _Src, _Ts, _Sub) ->
- maybe.
+will_succeed_1(#b_set{}, _Src, _Ts) ->
+ 'maybe'.
simplify_is_record(I, #t_tuple{exact=Exact,
size=Size,
@@ -1114,9 +1411,9 @@ simplify_is_record(I, #t_tuple{exact=Exact,
{ok, _} -> no;
error ->
%% Is it at all possible for the tag to match?
- case beam_types:meet(raw_type(RecTag, Ts), TagType) of
+ case beam_types:meet(concrete_type(RecTag, Ts), TagType) of
none -> no;
- _ -> maybe
+ _ -> 'maybe'
end
end,
if
@@ -1144,7 +1441,7 @@ simplify_switch_bool(#b_switch{arg=B,fail=Fail,list=List0}, Ts, Ds, Sub) ->
simplify_not(#b_br{bool=#b_var{}=V,succ=Succ,fail=Fail}=Br0, Ts, Ds, Sub) ->
case Ds of
#{V:=#b_set{op={bif,'not'},args=[Bool]}} ->
- case beam_types:is_boolean_type(raw_type(Bool, Ts)) of
+ case beam_types:is_boolean_type(concrete_type(Bool, Ts)) of
true ->
Br = Br0#b_br{bool=Bool,succ=Fail,fail=Succ},
simplify_terminator(Br, Ts, Ds, Sub);
@@ -1163,7 +1460,7 @@ simplify_phi_args([{Arg0, From} | Rest], Ls, Sub, Type0, Args) ->
{outgoing, Ts} = Outgoing, %Assertion.
Arg = simplify_arg(Arg0, Ts, Sub),
- Type = beam_types:join(raw_type(Arg, Ts), Type0),
+ Type = beam_types:join(concrete_type(Arg, Ts), Type0),
Phi = {Arg, From},
simplify_phi_args(Rest, Ls, Sub, Type, [Phi | Args]);
@@ -1239,7 +1536,8 @@ simplify_pure_call(Mod, Name, Args0, I) ->
any_non_numeric_argument([#b_literal{val=Lit}|_], _Ts) ->
is_non_numeric(Lit);
any_non_numeric_argument([#b_var{}=V|T], Ts) ->
- is_non_numeric_type(raw_type(V, Ts)) orelse any_non_numeric_argument(T, Ts);
+ is_non_numeric_type(concrete_type(V, Ts)) orelse
+ any_non_numeric_argument(T, Ts);
any_non_numeric_argument([], _Ts) -> false.
is_non_numeric([H|T]) ->
@@ -1292,8 +1590,8 @@ make_literal_list([], Acc) ->
reverse(Acc).
is_safe_bool_op([LHS, RHS], Ts) ->
- LType = raw_type(LHS, Ts),
- RType = raw_type(RHS, Ts),
+ LType = concrete_type(LHS, Ts),
+ RType = concrete_type(RHS, Ts),
beam_types:is_boolean_type(LType) andalso
beam_types:is_boolean_type(RType).
@@ -1305,7 +1603,7 @@ eval_bif(#b_set{op={bif,Bif},args=Args}=I, Ts) ->
true ->
case make_literal_list(Args) of
none ->
- eval_type_test_bif(I, Bif, raw_types(Args, Ts));
+ eval_bif_1(I, Bif, concrete_types(Args, Ts));
LitArgs ->
try apply(erlang, Bif, LitArgs) of
Val -> #b_literal{val=Val}
@@ -1316,44 +1614,7 @@ eval_bif(#b_set{op={bif,Bif},args=Args}=I, Ts) ->
end
end.
-eval_type_test_bif(I, is_atom, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_atom{});
-eval_type_test_bif(I, is_binary, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_bs_matchable{tail_unit=8});
-eval_type_test_bif(I, is_bitstring, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_bs_matchable{});
-eval_type_test_bif(I, is_boolean, [Type]) ->
- case beam_types:is_boolean_type(Type) of
- true ->
- #b_literal{val=true};
- false ->
- case beam_types:meet(Type, #t_atom{}) of
- #t_atom{elements=[_|_]=Es} ->
- case any(fun is_boolean/1, Es) of
- true -> I;
- false -> #b_literal{val=false}
- end;
- #t_atom{} ->
- I;
- none ->
- #b_literal{val=false}
- end
- end;
-eval_type_test_bif(I, is_float, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_float{});
-eval_type_test_bif(I, is_function, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_fun{});
-eval_type_test_bif(I, is_integer, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_integer{});
-eval_type_test_bif(I, is_list, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_list{});
-eval_type_test_bif(I, is_map, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_map{});
-eval_type_test_bif(I, is_number, [Type]) ->
- eval_type_test_bif_1(I, Type, number);
-eval_type_test_bif(I, is_tuple, [Type]) ->
- eval_type_test_bif_1(I, Type, #t_tuple{});
-eval_type_test_bif(I, Op, Types) ->
+eval_bif_1(I, Op, Types) ->
case Types of
[#t_integer{},#t_integer{elements={0,0}}] when Op =:= 'bor'; Op =:= 'bxor' ->
#b_set{args=[Result,_]} = I,
@@ -1376,36 +1637,10 @@ eval_type_test_bif(I, Op, Types) ->
false ->
I
end;
- [#t_integer{elements={LMin,LMax}},#t_integer{elements={RMin,RMax}}] ->
- case is_inequality_op(Op) of
- true ->
- case {erlang:Op(LMin, RMin),erlang:Op(LMax, RMin),
- erlang:Op(LMin, RMax),erlang:Op(LMax, RMax)} of
- {Bool,Bool,Bool,Bool} ->
- #b_literal{val=Bool};
- _ ->
- I
- end;
- false ->
- I
- end;
_ ->
I
end.
-is_inequality_op('<') -> true;
-is_inequality_op('=<') -> true;
-is_inequality_op('>') -> true;
-is_inequality_op('>=') -> true;
-is_inequality_op(_) -> false.
-
-eval_type_test_bif_1(I, ArgType, Required) ->
- case beam_types:meet(ArgType, Required) of
- ArgType -> #b_literal{val=true};
- none -> #b_literal{val=false};
- _ -> I
- end.
-
simplify_args(Args, Ts, Sub) ->
[simplify_arg(Arg, Ts, Sub) || Arg <- Args].
@@ -1414,7 +1649,7 @@ simplify_arg(#b_var{}=Arg0, Ts, Sub) ->
#b_literal{}=LitArg ->
LitArg;
#b_var{}=Arg ->
- case beam_types:get_singleton_value(raw_type(Arg, Ts)) of
+ case beam_types:get_singleton_value(concrete_type(Arg, Ts)) of
{ok, Val} -> #b_literal{val=Val};
error -> Arg
end
@@ -1564,7 +1799,7 @@ update_successors(#b_br{bool=#b_literal{val=true},succ=Succ}=Last,
{Last, update_successor(Succ, Ts, Ls)};
update_successors(#b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail}=Last0,
Ts, Ds, Ls0, UsedOnce) ->
- IsTempVar = sets:is_element(Bool, UsedOnce),
+ IsTempVar = is_map_key(Bool, UsedOnce),
case infer_types_br(Bool, Ts, IsTempVar, Ds) of
{#{}=SuccTs, #{}=FailTs} ->
Ls1 = update_successor(Succ, SuccTs, Ls0),
@@ -1579,10 +1814,11 @@ update_successors(#b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail}=Last0,
end;
update_successors(#b_switch{arg=#b_var{}=V,fail=Fail0,list=List0}=Last0,
Ts, Ds, Ls0, UsedOnce) ->
- IsTempVar = sets:is_element(V, UsedOnce),
+ IsTempVar = is_map_key(V, UsedOnce),
{List1, FailTs, Ls1} =
- update_switch(List0, V, raw_type(V, Ts), Ts, Ds, Ls0, IsTempVar, []),
+ update_switch(List0, V, concrete_type(V, Ts),
+ Ts, Ds, Ls0, IsTempVar, []),
case FailTs of
none ->
@@ -1611,7 +1847,7 @@ update_successors(#b_ret{}=Last, _Ts, _Ds, Ls, _UsedOnce) ->
update_switch([{Val, Lbl}=Sw | List],
V, FailType0, Ts, Ds, Ls0, IsTempVar, Acc) ->
- FailType = beam_types:subtract(FailType0, raw_type(Val, Ts)),
+ FailType = beam_types:subtract(FailType0, concrete_type(Val, Ts)),
case infer_types_switch(V, Val, Ts, IsTempVar, Ds) of
none ->
update_switch(List, V, FailType, Ts, Ds, Ls0, IsTempVar, Acc);
@@ -1630,11 +1866,19 @@ update_switch([], V, FailType, Ts, Ds, Ls, IsTempVar, Acc) ->
%% we can infer types as if we matched it directly.
Lit = #b_literal{val=Value},
infer_types_switch(V, Lit, Ts, IsTempVar, Ds);
- error when IsTempVar ->
- ts_remove_var(V, Ts);
error ->
- Ts#{ V := FailType }
+ %% There's more than one possible value, try a weaker
+ %% variant of the inference for case labels.
+ #{ V := Def } = Ds,
+ PosTypes = [{V, FailType} | infer_eq_type(Def, FailType)],
+
+ case meet_types(PosTypes, Ts) of
+ none -> none;
+ FailTs0 when IsTempVar -> ts_remove_var(V, FailTs0);
+ FailTs0 -> FailTs0
+ end
end,
+
{reverse(Acc), FailTs, Ls}.
update_successor(?EXCEPTION_BLOCK, _Ts, Ls) ->
@@ -1657,19 +1901,29 @@ update_successor(S, Ts0, Ls) ->
update_types(#b_set{op=Op,dst=Dst,anno=Anno,args=Args}, Ts, Ds) ->
T = type(Op, Args, Anno, Ts, Ds),
- Ts#{Dst=>T}.
+ Ts#{ Dst => T }.
type({bif,Bif}, Args, _Anno, Ts, _Ds) ->
ArgTypes = normalized_types(Args, Ts),
- {RetType, _, _} = beam_call_types:types(erlang, Bif, ArgTypes),
- RetType;
-type(bs_init, _Args, _Anno, _Ts, _Ds) ->
+ case beam_call_types:types(erlang, Bif, ArgTypes) of
+ {any, _, _} ->
+ case {Bif, Args} of
+ {element, [_,#b_literal{val=Tuple}]}
+ when tuple_size(Tuple) > 0 ->
+ join_tuple_elements(Tuple);
+ {_, _} ->
+ any
+ end;
+ {RetType, _, _} ->
+ RetType
+ end;
+type(bs_create_bin, _Args, _Anno, _Ts, _Ds) ->
#t_bitstring{};
type(bs_extract, [Ctx], _Anno, _Ts, Ds) ->
#b_set{op=bs_match,args=Args} = map_get(Ctx, Ds),
bs_match_type(Args);
type(bs_start_match, [_, Src], _Anno, Ts, _Ds) ->
- case beam_types:meet(#t_bs_matchable{}, raw_type(Src, Ts)) of
+ case beam_types:meet(#t_bs_matchable{}, concrete_type(Src, Ts)) of
none ->
none;
T ->
@@ -1682,7 +1936,7 @@ type(bs_match, [#b_literal{val=binary}, Ctx, _Flags,
%% This is an explicit tail unit test which does not advance the match
%% position.
- CtxType = raw_type(Ctx, Ts),
+ CtxType = concrete_type(Ctx, Ts),
OpType = #t_bs_context{tail_unit=OpUnit},
beam_types:meet(CtxType, OpType);
@@ -1692,30 +1946,41 @@ type(bs_match, Args, _Anno, Ts, _Ds) ->
%% Matches advance the current position without testing the tail unit. We
%% try to retain unit information by taking the GCD of our current unit and
%% the increments we know the match will advance by.
- #t_bs_context{tail_unit=CtxUnit} = raw_type(Ctx, Ts),
+ #t_bs_context{tail_unit=CtxUnit} = concrete_type(Ctx, Ts),
OpUnit = bs_match_stride(Args, Ts),
#t_bs_context{tail_unit=gcd(OpUnit, CtxUnit)};
type(bs_get_tail, [Ctx], _Anno, Ts, _Ds) ->
- #t_bs_context{tail_unit=Unit} = raw_type(Ctx, Ts),
+ #t_bs_context{tail_unit=Unit} = concrete_type(Ctx, Ts),
#t_bitstring{size_unit=Unit};
type(call, [#b_remote{mod=#b_literal{val=Mod},
- name=#b_literal{val=Name}}|Args], _Anno, Ts, _Ds) ->
+ name=#b_literal{val=Name}}|Args], _Anno, Ts, _Ds)
+ when is_atom(Mod), is_atom(Name) ->
ArgTypes = normalized_types(Args, Ts),
{RetType, _, _} = beam_call_types:types(Mod, Name, ArgTypes),
RetType;
-type(call, [#b_remote{} | _Args], _Anno, _Ts, _Ds) ->
- %% Remote call with variable Module and/or Function.
- any;
+type(call, [#b_remote{mod=Mod,name=Name} | _Args], _Anno, Ts, _Ds) ->
+ %% Remote call with variable Module and/or Function, we can't say much
+ %% about it other than that it will crash when either of the two is not an
+ %% atom.
+ ModType = beam_types:meet(concrete_type(Mod, Ts), #t_atom{}),
+ NameType = beam_types:meet(concrete_type(Name, Ts), #t_atom{}),
+ case {ModType, NameType} of
+ {none, _} -> none;
+ {_, none} -> none;
+ {_, _} -> any
+ end;
type(call, [#b_local{} | _Args], Anno, _Ts, _Ds) ->
case Anno of
#{ result_type := Type } -> Type;
#{} -> any
end;
-type(call, [#b_var{} | _Args], Anno, _Ts, _Ds) ->
- case Anno of
- #{ result_type := Type } -> Type;
- #{} -> any
+type(call, [#b_var{}=Fun | Args], Anno, Ts, _Ds) ->
+ FunType = concrete_type(Fun, Ts),
+ case {beam_types:meet(FunType, #t_fun{arity=length(Args)}), Anno} of
+ {#t_fun{}, #{ result_type := Type }} -> Type;
+ {#t_fun{}, #{}} -> any;
+ {none, #{}} -> none
end;
type(call, [#b_literal{val=Fun} | Args], _Anno, _Ts, _Ds) ->
case is_function(Fun, length(Args)) of
@@ -1751,11 +2016,16 @@ type(get_map_element, [_, _]=Args0, _Anno, Ts, _Ds) ->
[#t_map{}=Map, Key] = normalized_types(Args0, Ts), %Assertion.
{RetType, _, _} = beam_call_types:types(erlang, map_get, [Key, Map]),
RetType;
-type(get_tuple_element, [Tuple, Offset], _Anno, Ts, _Ds) ->
- #t_tuple{size=Size,elements=Es} = normalized_type(Tuple, Ts),
+type(get_tuple_element, [Tuple, Offset], _Anno, _Ts, _Ds) ->
#b_literal{val=N} = Offset,
- true = Size > N, %Assertion.
- beam_types:get_tuple_element(N + 1, Es);
+ Index = N + 1,
+ %% Defer our type until our first use (concrete_type/2), as our type may
+ %% depend on another value extracted from the same container.
+ fun(Ts) ->
+ #t_tuple{size=Size,elements=Es} = normalized_type(Tuple, Ts),
+ true = Index =< Size, %Assertion.
+ beam_types:get_tuple_element(Index, Es)
+ end;
type(has_map_field, [_, _]=Args0, _Anno, Ts, _Ds) ->
[#t_map{}=Map, Key] = normalized_types(Args0, Ts), %Assertion.
{RetType, _, _} = beam_call_types:types(erlang, is_map_key, [Key, Map]),
@@ -1764,27 +2034,41 @@ type(is_nonempty_list, [_], _Anno, _Ts, _Ds) ->
beam_types:make_boolean();
type(is_tagged_tuple, [_,#b_literal{},#b_literal{}], _Anno, _Ts, _Ds) ->
beam_types:make_boolean();
-type(MakeFun, [#b_local{arity=TotalArity} | Env], Anno, _Ts, _Ds)
- when MakeFun =:= make_fun;
- MakeFun =:= old_make_fun ->
+type(MakeFun, Args, Anno, _Ts, _Ds) when MakeFun =:= make_fun;
+ MakeFun =:= old_make_fun ->
RetType = case Anno of
#{ result_type := Type } -> Type;
#{} -> any
end,
- #t_fun{arity=TotalArity - length(Env), type=RetType};
+ [#b_local{name=#b_literal{val=Name},arity=TotalArity} | Env] = Args,
+ Arity = TotalArity - length(Env),
+ #t_fun{arity=Arity,target={Name,TotalArity},type=RetType};
+type(match_fail, _, _Anno, _Ts, _Ds) ->
+ none;
type(put_map, [_Kind, Map | Ss], _Anno, Ts, _Ds) ->
put_map_type(Map, Ss, Ts);
type(put_list, [Head, Tail], _Anno, Ts, _Ds) ->
- HeadType = raw_type(Head, Ts),
- TailType = raw_type(Tail, Ts),
+ HeadType = concrete_type(Head, Ts),
+ TailType = concrete_type(Tail, Ts),
beam_types:make_cons(HeadType, TailType);
type(put_tuple, Args, _Anno, Ts, _Ds) ->
{Es, _} = foldl(fun(Arg, {Es0, Index}) ->
- Type = raw_type(Arg, Ts),
+ Type = concrete_type(Arg, Ts),
Es = beam_types:set_tuple_element(Index, Type, Es0),
{Es, Index + 1}
end, {#{}, 1}, Args),
#t_tuple{exact=true,size=length(Args),elements=Es};
+type(raw_raise, [Class, _, _], _Anno, Ts, _Ds) ->
+ ClassType = concrete_type(Class, Ts),
+ case beam_types:meet(ClassType, #t_atom{elements=[error,exit,throw]}) of
+ ClassType ->
+ %% Unlike erlang:raise/3, the stack argument is always correct as
+ %% it's generated by the emulator, so we KNOW that it will raise an
+ %% exception when the class is correct.
+ none;
+ _ ->
+ beam_types:make_atom(badarg)
+ end;
type(resume, [_, _], _Anno, _Ts, _Ds) ->
none;
type(wait_timeout, [#b_literal{val=infinity}], _Anno, _Ts, _Ds) ->
@@ -1793,6 +2077,16 @@ type(wait_timeout, [#b_literal{val=infinity}], _Anno, _Ts, _Ds) ->
type(_, _, _, _, _) ->
any.
+join_tuple_elements(Tuple) ->
+ join_tuple_elements(tuple_size(Tuple), Tuple, none).
+
+join_tuple_elements(0, _Tuple, Type) ->
+ Type;
+join_tuple_elements(I, Tuple, Type0) ->
+ Type1 = beam_types:make_type_from_value(element(I, Tuple)),
+ Type = beam_types:join(Type0, Type1),
+ join_tuple_elements(I - 1, Tuple, Type).
+
put_map_type(Map, Ss, Ts) ->
pmt_1(Ss, Ts, normalized_type(Map, Ts)).
@@ -1810,7 +2104,7 @@ bs_match_stride([#b_literal{val=Type} | Args], Ts) ->
bs_match_stride(Type, Args, Ts).
bs_match_stride(_, [_,_,Size,#b_literal{val=Unit}], Ts) ->
- case raw_type(Size, Ts) of
+ case concrete_type(Size, Ts) of
#t_integer{elements={Sz, Sz}} when is_integer(Sz) ->
Sz * Unit;
_ ->
@@ -1844,12 +2138,13 @@ bs_match_type(integer, Args) ->
#b_literal{val=Size},
#b_literal{val=Unit}] when Size * Unit < 64 ->
NumBits = Size * Unit,
+ Max = (1 bsl NumBits) - 1,
case member(unsigned, Flags) of
true ->
- beam_types:make_integer(0, (1 bsl NumBits)-1);
+ beam_types:make_integer(0, Max);
false ->
- %% Signed integer. Don't bother.
- #t_integer{}
+ Min = -(Max + 1),
+ beam_types:make_integer(Min, Max)
end;
[_|_] ->
#t_integer{}
@@ -1868,8 +2163,10 @@ bs_match_type(utf32, _) ->
normalized_types(Values, Ts) ->
[normalized_type(Val, Ts) || Val <- Values].
+-spec normalized_type(beam_ssa:value(), type_db()) -> normal_type().
+
normalized_type(V, Ts) ->
- beam_types:normalize(raw_type(V, Ts)).
+ beam_types:normalize(concrete_type(V, Ts)).
argument_types(Values, Ts) ->
[argument_type(Val, Ts) || Val <- Values].
@@ -1877,17 +2174,21 @@ argument_types(Values, Ts) ->
-spec argument_type(beam_ssa:value(), type_db()) -> type().
argument_type(V, Ts) ->
- beam_types:limit_depth(raw_type(V, Ts)).
+ beam_types:limit_depth(concrete_type(V, Ts)).
-raw_types(Values, Ts) ->
- [raw_type(Val, Ts) || Val <- Values].
+concrete_types(Values, Ts) ->
+ [concrete_type(Val, Ts) || Val <- Values].
--spec raw_type(beam_ssa:value(), type_db()) -> type().
+-spec concrete_type(beam_ssa:value(), type_db()) -> type().
-raw_type(#b_literal{val=Value}, _Ts) ->
+concrete_type(#b_literal{val=Value}, _Ts) ->
beam_types:make_type_from_value(Value);
-raw_type(V, Ts) ->
- map_get(V, Ts).
+concrete_type(#b_var{}=Var, Ts) ->
+ #{ Var := Type } = Ts,
+ case is_function(Type) of
+ true -> Type(Ts);
+ false -> Type
+ end.
%% infer_types(Var, Types, #d{}) -> {SuccTypes,FailTypes}
%% Looking at the expression that defines the variable Var, infer
@@ -1965,48 +2266,72 @@ infer_type({succeeded,_}, [#b_var{}=Src], Ts, Ds) ->
%% not branching on 'succeeded'.
infer_type(is_tagged_tuple, [#b_var{}=Src,#b_literal{val=Size},
#b_literal{}=Tag], _Ts, _Ds) ->
- Es = beam_types:set_tuple_element(1, raw_type(Tag, #{}), #{}),
+ Es = beam_types:set_tuple_element(1, concrete_type(Tag, #{}), #{}),
T = {Src,#t_tuple{exact=true,size=Size,elements=Es}},
{[T], [T]};
infer_type(is_nonempty_list, [#b_var{}=Src], _Ts, _Ds) ->
T = {Src,#t_cons{}},
{[T], [T]};
-infer_type({bif,is_atom}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_atom}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_atom{}},
{[T], [T]};
-infer_type({bif,is_binary}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_binary}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_bitstring{size_unit=8}},
{[T], [T]};
-infer_type({bif,is_bitstring}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_bitstring}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_bitstring{}},
{[T], [T]};
-infer_type({bif,is_boolean}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_boolean}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, beam_types:make_boolean()},
{[T], [T]};
-infer_type({bif,is_float}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_float}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_float{}},
{[T], [T]};
-infer_type({bif,is_integer}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_function}, [#b_var{}=Arg], _Ts, _Ds) ->
+ T = {Arg, #t_fun{}},
+ {[T], [T]};
+infer_type({bif,is_function}, [#b_var{}=Arg, Arity], _Ts, _Ds) ->
+ case Arity of
+ #b_literal{val=V} when is_integer(V), V >= 0, V =< ?MAX_FUNC_ARGS ->
+ T = {Arg, #t_fun{arity=V}},
+ {[T], [T]};
+ _ ->
+ %% We cannot subtract the function type when the arity is unknown:
+ %% `Arg` may still be a function if the arity is outside the
+ %% allowed range.
+ T = {Arg, #t_fun{}},
+ {[T], []}
+ end;
+infer_type({bif,is_integer}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_integer{}},
{[T], [T]};
-infer_type({bif,is_list}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_list}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_list{}},
{[T], [T]};
-infer_type({bif,is_map}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_map}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_map{}},
{[T], [T]};
-infer_type({bif,is_number}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_number}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, number},
{[T], [T]};
-infer_type({bif,is_tuple}, [Arg], _Ts, _Ds) ->
+infer_type({bif,is_pid}, [#b_var{}=Arg], _Ts, _Ds) ->
+ T = {Arg, pid},
+ {[T], [T]};
+infer_type({bif,is_port}, [#b_var{}=Arg], _Ts, _Ds) ->
+ T = {Arg, port},
+ {[T], [T]};
+infer_type({bif,is_reference}, [#b_var{}=Arg], _Ts, _Ds) ->
+ T = {Arg, reference},
+ {[T], [T]};
+infer_type({bif,is_tuple}, [#b_var{}=Arg], _Ts, _Ds) ->
T = {Arg, #t_tuple{}},
{[T], [T]};
infer_type({bif,'=:='}, [#b_var{}=LHS,#b_var{}=RHS], Ts, _Ds) ->
%% As an example, assume that L1 is known to be 'list', and L2 is
%% known to be 'cons'. Then if 'L1 =:= L2' evaluates to 'true', it can
%% be inferred that L1 is 'cons' (the meet of 'cons' and 'list').
- LType = raw_type(LHS, Ts),
- RType = raw_type(RHS, Ts),
+ LType = concrete_type(LHS, Ts),
+ RType = concrete_type(RHS, Ts),
Type = beam_types:meet(LType, RType),
PosTypes = [{V,Type} || {V, OrigType} <- [{LHS, LType}, {RHS, RType}],
@@ -2032,13 +2357,13 @@ infer_type({bif,'=:='}, [#b_var{}=LHS,#b_var{}=RHS], Ts, _Ds) ->
{PosTypes, NegTypes};
infer_type({bif,'=:='}, [#b_var{}=Src,#b_literal{}=Lit], Ts, Ds) ->
Def = maps:get(Src, Ds),
- LitType = raw_type(Lit, Ts),
- PosTypes = [{Src, LitType} | infer_eq_lit(Def, LitType)],
+ LitType = concrete_type(Lit, Ts),
+ PosTypes = [{Src, LitType} | infer_eq_type(Def, LitType)],
%% Subtraction is only safe if LitType is single-valued.
NegTypes = case beam_types:is_singleton_type(LitType) of
- true -> PosTypes;
- false -> []
+ true -> PosTypes;
+ false -> []
end,
{PosTypes, NegTypes};
@@ -2073,21 +2398,21 @@ infer_success_type(bs_match, [#b_literal{val=binary},
infer_success_type(_Op, _Args, _Ts, _Ds) ->
{[], []}.
-infer_eq_lit(#b_set{op={bif,tuple_size},args=[#b_var{}=Tuple]},
- #t_integer{elements={Size,Size}}) ->
+infer_eq_type(#b_set{op={bif,tuple_size},args=[#b_var{}=Tuple]},
+ #t_integer{elements={Size,Size}}) ->
[{Tuple,#t_tuple{exact=true,size=Size}}];
-infer_eq_lit(#b_set{op=get_tuple_element,
- args=[#b_var{}=Tuple,#b_literal{val=N}]},
- LitType) ->
+infer_eq_type(#b_set{op=get_tuple_element,
+ args=[#b_var{}=Tuple,#b_literal{val=N}]},
+ ElementType) ->
Index = N + 1,
- case beam_types:set_tuple_element(Index, LitType, #{}) of
+ case beam_types:set_tuple_element(Index, ElementType, #{}) of
#{ Index := _ }=Es ->
[{Tuple,#t_tuple{size=Index,elements=Es}}];
#{} ->
%% Index was above the element limit; subtraction is not safe.
[]
end;
-infer_eq_lit(_, _) ->
+infer_eq_type(_, _) ->
[].
join_types(Ts, Ts) ->
@@ -2105,7 +2430,16 @@ join_types_1([V | Vs], Bigger, Smaller) ->
case {Bigger, Smaller} of
{#{ V := Same }, #{ V := Same }} ->
join_types_1(Vs, Bigger, Smaller);
- {#{ V := LHS }, #{ V := RHS }} ->
+ {#{ V := LHS0 }, #{ V := RHS0 }} ->
+ %% Inlined concrete_type/2 for performance.
+ LHS = case is_function(LHS0) of
+ true -> LHS0(Bigger);
+ false -> LHS0
+ end,
+ RHS = case is_function(RHS0) of
+ true -> RHS0(Smaller);
+ false -> RHS0
+ end,
T = beam_types:join(LHS, RHS),
join_types_1(Vs, Bigger, Smaller#{ V := T });
{#{}, #{ V := _ }} ->
@@ -2115,22 +2449,24 @@ join_types_1([], _Bigger, Smaller) ->
Smaller.
meet_types([{V,T0}|Vs], Ts) ->
- #{V:=T1} = Ts,
+ T1 = concrete_type(V, Ts),
case beam_types:meet(T0, T1) of
none -> none;
T1 -> meet_types(Vs, Ts);
- T -> meet_types(Vs, Ts#{V:=T})
+ T -> meet_types(Vs, Ts#{ V := T })
end;
-meet_types([], Ts) -> Ts.
+meet_types([], Ts) ->
+ Ts.
subtract_types([{V,T0}|Vs], Ts) ->
- #{V:=T1} = Ts,
+ T1 = concrete_type(V, Ts),
case beam_types:subtract(T1, T0) of
none -> none;
T1 -> subtract_types(Vs, Ts);
- T -> subtract_types(Vs, Ts#{V:=T})
+ T -> subtract_types(Vs, Ts#{ V:= T })
end;
-subtract_types([], Ts) -> Ts.
+subtract_types([], Ts) ->
+ Ts.
parallel_join([A | As], [B | Bs]) ->
[beam_types:join(A, B) | parallel_join(As, Bs)];
@@ -2148,9 +2484,8 @@ gcd(A, B) ->
%%%
init_metadata(FuncId, Linear, Params) ->
- {RetCounter, Map0} = init_metadata_1(reverse(Linear), 0, #{}),
- Map = maps:without(Params, Map0),
- UsedOnce = sets:from_list(maps:keys(Map), [{version, 2}]),
+ {RetCounter, UsedOnce0} = init_metadata_1(reverse(Linear), 0, #{}),
+ UsedOnce = maps:without(Params, UsedOnce0),
#metadata{ func_id = FuncId,
limit_return = (RetCounter >= ?RETURN_LIMIT),
@@ -2165,11 +2500,11 @@ init_metadata_1([{L,#b_blk{is=Is,last=Last}} | Bs], RetCounter0, Uses0) ->
_ -> RetCounter0
end,
- %% Calculate the set of variables that are only used once in the terminator
- %% of the block that defines them. That will allow us to discard type
- %% information discard type information for variables that will never be
- %% referenced by the successor blocks, potentially improving compilation
- %% times.
+ %% Calculate the set of variables that are only used once in the
+ %% terminator of the block that defines them. That will allow us
+ %% to discard type information for variables that will never be
+ %% referenced by the successor blocks, potentially improving
+ %% compilation times.
Uses1 = used_once_last_uses(beam_ssa:used(Last), L, Uses0),
Uses = used_once_2(reverse(Is), L, Uses1),
@@ -2180,7 +2515,7 @@ init_metadata_1([], RetCounter, Uses) ->
used_once_2([#b_set{dst=Dst}=I|Is], L, Uses0) ->
Uses = used_once_uses(beam_ssa:used(I), L, Uses0),
case Uses of
- #{Dst:=[L]} ->
+ #{Dst:=L} ->
used_once_2(Is, L, Uses);
#{} ->
%% Used more than once or used once in
@@ -2202,15 +2537,15 @@ used_once_uses([], _, Uses) -> Uses.
used_once_last_uses([V|Vs], L, Uses) ->
case Uses of
- #{V:=[_]} ->
- %% Second time this variable is used.
- used_once_last_uses(Vs, L, Uses#{V:=more_than_once});
#{V:=more_than_once} ->
%% Used at least twice before.
used_once_last_uses(Vs, L, Uses);
+ #{V:=_} ->
+ %% Second time this variable is used.
+ used_once_last_uses(Vs, L, Uses#{V:=more_than_once});
#{} ->
%% First time this variable is used.
- used_once_last_uses(Vs, L, Uses#{V=>[L]})
+ used_once_last_uses(Vs, L, Uses#{V=>L})
end;
used_once_last_uses([], _, Uses) -> Uses.
@@ -2256,7 +2591,7 @@ wl_changed(#worklist{counter=Same}, #worklist{counter=Same}) -> false;
wl_changed(#worklist{}, #worklist{}) -> true.
%% Adds the given elements to the back of the worklist, skipping the elements
-%% that are already present. This lets us append elements arbitrarly after the
+%% that are already present. This lets us append elements arbitrarily after the
%% current front without changing the work order.
wl_defer_list(Elements, #worklist{counter=Counter,elements=Es,indexes=Is}) ->
wl_defer_list_1(Elements, Counter, Es, Is).
diff --git a/lib/compiler/src/beam_trim.erl b/lib/compiler/src/beam_trim.erl
index 0dbe2bb18a..4fb141251d 100644
--- a/lib/compiler/src/beam_trim.erl
+++ b/lib/compiler/src/beam_trim.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,10 +21,13 @@
-module(beam_trim).
-export([module/2]).
--import(lists, [any/2,member/2,reverse/1,reverse/2,sort/1]).
+-import(lists, [any/2,reverse/1,reverse/2,seq/2,sort/1]).
+
+-include("beam_asm.hrl").
-record(st,
- {safe :: sets:set(beam_asm:label()) %Safe labels.
+ {safe :: sets:set(beam_asm:label()), %Safe labels.
+ fsz :: non_neg_integer()
}).
-spec module(beam_utils:module_code(), [compile:option()]) ->
@@ -36,8 +39,9 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
function({function,Name,Arity,CLabel,Is0}) ->
try
- St = #st{safe=safe_labels(Is0, [])},
- Is = trim(Is0, St, []),
+ St = #st{safe=safe_labels(Is0, []),fsz=0},
+ Usage = none,
+ Is = trim(Is0, Usage, St),
{function,Name,Arity,CLabel,Is}
catch
Class:Error:Stack ->
@@ -45,43 +49,45 @@ function({function,Name,Arity,CLabel,Is0}) ->
erlang:raise(Class, Error, Stack)
end.
-trim([{init_yregs,{list,Kills0}}=I|Is0], St, Acc) ->
- Kills = [{kill,Y} || Y <- Kills0],
- try
- %% Find out the size and layout of the stack frame.
- %% Example of a layout:
- %%
- %% [{kill,{y,0}},{dead,{y,1},{live,{y,2}},{kill,{y,3}}]
- %%
- %% That means that y0 and y3 are to be killed, that y1
- %% has been killed previously, and that y2 is live.
- {FrameSize,Layout} = frame_layout(Is0, Kills, St),
-
- %% Calculate all recipes that are not worse in terms
- %% of estimated execution time. The recipes are ordered
- %% in descending order from how much they trim.
- IsNotRecursive = is_not_recursive(Is0),
- Recipes = trim_recipes(Layout, IsNotRecursive),
-
- %% Try the recipes in order. A recipe may not work out because
- %% a register that was previously killed may be
- %% resurrected. If that happens, the next recipe, which trims
- %% less, will be tried.
- try_remap(Recipes, Is0, FrameSize)
- of
- {Is,TrimInstr} ->
- %% One of the recipes was applied.
- trim(Is, St, reverse(TrimInstr)++Acc)
- catch
- not_possible ->
+trim([{init_yregs,_}=I|Is], none, St0) ->
+ case usage(Is, St0) of
+ none ->
+ [I|trim(Is, none, St0)];
+ {FrameSize,Us} ->
+ St = St0#st{fsz=FrameSize},
+ trim([I|Is], Us, St)
+ end;
+trim([{init_yregs,{list,Killed}}=I|Is0], [U|Us], St) ->
+ FrameSize = St#st.fsz,
+
+ %% Find out layout of the stack frame. Example of a layout:
+ %%
+ %% [{kill,{y,0}},{dead,{y,1},{live,{y,2}},{kill,{y,3}}]
+ %%
+ %% That means that y0 and y3 are to be killed, that y1
+ %% has been killed previously, and that y2 is live.
+ Layout = frame_layout(FrameSize, Killed, U),
+
+ %% Find a trim recipe.
+ IsNotRecursive = is_not_recursive(Is0),
+ case trim_recipe(Layout, IsNotRecursive, U) of
+ none ->
%% No recipe worked out. Use the original init_yregs/1
%% instruction.
- trim(Is0, St, [I|Acc])
+ [I|trim(Is0, Us, St)];
+ R ->
+ %% Apply the recipe.
+ {TrimInstr,Remap} = expand_recipe(R, FrameSize),
+ Is = remap(Is0, Remap),
+ TrimInstr ++ trim(Is, none, St)
end;
-trim([I|Is], St, Acc) ->
- trim(Is, St, [I|Acc]);
-trim([], _, Acc) ->
- reverse(Acc).
+trim([I|Is], [_|Us], St) ->
+ [I|trim(Is, Us, St)];
+trim([I|Is], none, St) ->
+ [I|trim(Is, none, St)];
+trim([I|Is], [], St) ->
+ [I|trim(Is, none, St)];
+trim([], _, _) -> [].
%% is_not_recursive([Instruction]) -> true|false.
%% Test whether the next call or apply instruction may
@@ -98,21 +104,26 @@ is_not_recursive([{block,_}|Is]) -> is_not_recursive(Is);
is_not_recursive([{line,_}|Is]) -> is_not_recursive(Is);
is_not_recursive(_) -> false.
-%% trim_recipes([{kill,R}|{live,R}|{dead,R}]) -> [Recipe].
+%% trim_recipe([{kill,R}|{live,R}|{dead,R}]) -> Recipe | none.
%% Recipe = {Kills,NumberToTrim,Moves}
%% Kills = [{kill,Y}]
%% Moves = [{move,SrcY,DstY}]
%%
%% Calculate how to best trim the stack and kill the correct
-%% Y registers. Return a list of possible recipes. The best
-%% recipe (the one that trims the most) is first in the list.
+%% Y registers. Return the recipe that trims the most.
-trim_recipes(Layout, IsNotRecursive) ->
+trim_recipe(Layout, IsNotRecursive, {Us,Ns}) ->
+ UsedRegs = ordsets:union(Us, Ns),
Recipes = construct_recipes(Layout, 0, [], []),
NumOrigKills = length([I || {kill,_}=I <- Layout]),
IsTooExpensive = is_too_expensive_fun(IsNotRecursive),
- [R || R <- Recipes,
- not is_too_expensive(R, NumOrigKills, IsTooExpensive)].
+ Rs = [R || R <- Recipes,
+ is_recipe_viable(R, UsedRegs),
+ not is_too_expensive(R, NumOrigKills, IsTooExpensive)],
+ case Rs of
+ [] -> none;
+ [R|_] -> R
+ end.
construct_recipes([{kill,{y,Trim0}}|Ks], Trim0, Moves, Acc) ->
Trim = Trim0 + 1,
@@ -133,11 +144,14 @@ construct_recipes([{live,{y,Trim0}=Src}|Ks0], Trim0, Moves0, Acc) ->
Recipe = {Ks,Trim,Moves},
construct_recipes(Ks, Trim, Moves, [Recipe|Acc])
end;
-construct_recipes([], _, _, Acc) -> Acc.
+construct_recipes(_, _, _, Acc) ->
+ Acc.
take_last_dead(L) ->
take_last_dead_1(reverse(L)).
+take_last_dead_1([{live,_}|Is]) ->
+ take_last_dead_1(Is);
take_last_dead_1([{kill,Reg}|Is]) ->
{Reg,reverse(Is)};
take_last_dead_1([{dead,Reg}|Is]) ->
@@ -181,142 +195,140 @@ is_too_expensive_fun(false) ->
NumKills + NumMoves > NumOrigKills
end.
-%% try_remap([Recipe], [Instruction], FrameSize) ->
-%% {[Instruction],[TrimInstruction]}.
-%% Try to renumber Y registers in the instruction stream. The
-%% first recipe that works will be used.
-%%
-%% This function will issue a `not_possible` exception if none
-%% of the recipes were possible to apply.
-
-try_remap([R|Rs], Is, FrameSize) ->
- {TrimInstr,Map} = expand_recipe(R, FrameSize),
- try
- {remap(Is, Map, []),TrimInstr}
- catch
- throw:not_possible ->
- try_remap(Rs, Is, FrameSize)
- end;
-try_remap([], _, _) -> throw(not_possible).
+is_recipe_viable({_,Trim,Moves}, UsedRegs) ->
+ Moved = ordsets:from_list([Src || {move,Src,_} <- Moves]),
+ Illegal = ordsets:from_list([Dst || {move,_,Dst} <- Moves]),
+ Eliminated = [{y,N} || N <- seq(0, Trim - 1)],
+ %% All eliminated registers that are also in the used set must be moved.
+ UsedEliminated = ordsets:intersection(Eliminated, UsedRegs),
+ case ordsets:is_subset(UsedEliminated, Moved) andalso
+ ordsets:is_disjoint(Illegal, UsedRegs) of
+ true ->
+ UsedEliminated = Moved, %Assertion.
+ true;
+ _ ->
+ false
+ end.
expand_recipe({Layout,Trim,Moves}, FrameSize) ->
Is = reverse(Moves, [{trim,Trim,FrameSize-Trim}]),
- Map = create_map(Trim, Moves),
+ Map0 = [{Src,Dst-Trim} || {move,{y,Src},{y,Dst}} <- Moves],
+ Map = maps:from_list(Map0),
+ Remap = {Trim,Map},
case [Y || {kill,Y} <- Layout] of
[] ->
- {Is,Map};
+ {Is,Remap};
[_|_]=Yregs ->
- {[{init_yregs,{list,Yregs}}|Is],Map}
- end.
-
-create_map(Trim, []) ->
- fun({y,Y}) when Y < Trim -> throw(not_possible);
- ({y,Y}) -> {y,Y-Trim};
- ({frame_size,N}) -> N - Trim;
- (Any) -> Any
- end;
-create_map(Trim, Moves) ->
- Map0 = [{Src,Dst-Trim} || {move,{y,Src},{y,Dst}} <- Moves],
- Map = maps:from_list(Map0),
- IllegalTargets = sets:from_list([Dst || {move,_,{y,Dst}} <- Moves], [{version, 2}]),
- fun({y,Y0}) when Y0 < Trim ->
- case Map of
- #{Y0:=Y} -> {y,Y};
- #{} -> throw(not_possible)
- end;
- ({y,Y}) ->
- case sets:is_element(Y, IllegalTargets) of
- true -> throw(not_possible);
- false -> {y,Y-Trim}
- end;
- ({frame_size,N}) -> N - Trim;
- (Any) -> Any
+ {[{init_yregs,{list,Yregs}}|Is],Remap}
end.
-remap([{'%',Comment}=I|Is], Map, Acc) ->
+remap([{'%',Comment}=I0|Is], Remap) ->
case Comment of
- {var_info,Var,Type} ->
- remap(Is, Map, [{'%',{var_info,Map(Var),Type}}|Acc]);
+ {var_info,{y,_}=Var,Type} ->
+ I = {'%',{var_info,remap_arg(Var, Remap),Type}},
+ [I|remap(Is, Remap)];
_ ->
- remap(Is, Map, [I|Acc])
+ [I0|remap(Is, Remap)]
end;
-remap([{block,Bl0}|Is], Map, Acc) ->
- Bl = remap_block(Bl0, Map, []),
- remap(Is, Map, [{block,Bl}|Acc]);
-remap([{bs_get_tail,Src,Dst,Live}|Is], Map, Acc) ->
- I = {bs_get_tail,Map(Src),Map(Dst),Live},
- remap(Is, Map, [I|Acc]);
-remap([{bs_start_match4,Fail,Live,Src,Dst}|Is], Map, Acc) ->
- I = {bs_start_match4,Fail,Live,Map(Src),Map(Dst)},
- remap(Is, Map, [I|Acc]);
-remap([{bs_set_position,Src1,Src2}|Is], Map, Acc) ->
- I = {bs_set_position,Map(Src1),Map(Src2)},
- remap(Is, Map, [I|Acc]);
-remap([{call_fun,_}=I|Is], Map, Acc) ->
- remap(Is, Map, [I|Acc]);
-remap([{call,_,_}=I|Is], Map, Acc) ->
- remap(Is, Map, [I|Acc]);
-remap([{call_ext,_,_}=I|Is], Map, Acc) ->
- remap(Is, Map, [I|Acc]);
-remap([{apply,_}=I|Is], Map, Acc) ->
- remap(Is, Map, [I|Acc]);
-remap([{bif,Name,Fail,Ss,D}|Is], Map, Acc) ->
- I = {bif,Name,Fail,[Map(S) || S <- Ss],Map(D)},
- remap(Is, Map, [I|Acc]);
-remap([{gc_bif,Name,Fail,Live,Ss,D}|Is], Map, Acc) ->
- I = {gc_bif,Name,Fail,Live,[Map(S) || S <- Ss],Map(D)},
- remap(Is, Map, [I|Acc]);
-remap([{get_map_elements,Fail,M,{list,L0}}|Is], Map, Acc) ->
- L = [Map(E) || E <- L0],
- I = {get_map_elements,Fail,Map(M),{list,L}},
- remap(Is, Map, [I|Acc]);
-remap([{bs_init,Fail,Info,Live,Ss0,Dst0}|Is], Map, Acc) ->
- Ss = [Map(Src) || Src <- Ss0],
- Dst = Map(Dst0),
- I = {bs_init,Fail,Info,Live,Ss,Dst},
- remap(Is, Map, [I|Acc]);
-remap([{bs_put=Op,Fail,Info,Ss}|Is], Map, Acc) ->
- I = {Op,Fail,Info,[Map(S) || S <- Ss]},
- remap(Is, Map, [I|Acc]);
-remap([{init_yregs,{list,Yregs0}}|Is], Map, Acc) ->
- Yregs = sort([Map(Y) || Y <- Yregs0]),
+remap([{block,Bl0}|Is], Remap) ->
+ Bl = remap_block(Bl0, Remap),
+ I = {block,Bl},
+ [I|remap(Is, Remap)];
+remap([{bs_create_bin,Fail,Alloc,Live,Unit,Dst0,{list,Ss0}}|Is], Remap) ->
+ Dst = remap_arg(Dst0, Remap),
+ Ss = remap_args(Ss0, Remap),
+ I = {bs_create_bin,Fail,Alloc,Live,Unit,Dst,{list,Ss}},
+ [I|remap(Is, Remap)];
+remap([{bs_get_tail,Src,Dst,Live}|Is], Remap) ->
+ I = {bs_get_tail,remap_arg(Src, Remap),remap_arg(Dst, Remap),Live},
+ [I|remap(Is, Remap)];
+remap([{bs_start_match4,Fail,Live,Src,Dst}|Is], Remap) ->
+ I = {bs_start_match4,Fail,Live,remap_arg(Src, Remap),remap_arg(Dst, Remap)},
+ [I|remap(Is, Remap)];
+remap([{bs_set_position,Src1,Src2}|Is], Remap) ->
+ I = {bs_set_position,remap_arg(Src1, Remap),remap_arg(Src2, Remap)},
+ [I|remap(Is, Remap)];
+remap([{call_fun,_}=I|Is], Remap) ->
+ [I|remap(Is, Remap)];
+remap([{call_fun2,Tag,Arity,Func}=I|Is], Remap) ->
+ I = {call_fun2,Tag,Arity,remap_arg(Func, Remap)},
+ [I|remap(Is, Remap)];
+remap([{call,_,_}=I|Is], Remap) ->
+ [I|remap(Is, Remap)];
+remap([{call_ext,_,_}=I|Is], Remap) ->
+ [I|remap(Is, Remap)];
+remap([{apply,_}=I|Is], Remap) ->
+ [I|remap(Is, Remap)];
+remap([{bif,Name,Fail,Ss,D}|Is], Remap) ->
+ I = {bif,Name,Fail,remap_args(Ss, Remap),remap_arg(D, Remap)},
+ [I|remap(Is, Remap)];
+remap([{gc_bif,Name,Fail,Live,Ss,D}|Is], Remap) ->
+ I = {gc_bif,Name,Fail,Live,remap_args(Ss, Remap),remap_arg(D, Remap)},
+ [I|remap(Is, Remap)];
+remap([{get_map_elements,Fail,M,{list,L0}}|Is], Remap) ->
+ L = remap_args(L0, Remap),
+ I = {get_map_elements,Fail,remap_arg(M, Remap),{list,L}},
+ [I|remap(Is, Remap)];
+remap([{init_yregs,{list,Yregs0}}|Is], Remap) ->
+ Yregs = sort(remap_args(Yregs0, Remap)),
I = {init_yregs,{list,Yregs}},
- remap(Is, Map, [I|Acc]);
-remap([{make_fun2,_,_,_,_}=I|T], Map, Acc) ->
- remap(T, Map, [I|Acc]);
-remap([{make_fun3,F,Index,OldUniq,Dst0,{list,Env0}}|T], Map, Acc) ->
- Env = [Map(E) || E <- Env0],
- Dst = Map(Dst0),
+ [I|remap(Is, Remap)];
+remap([{make_fun3,F,Index,OldUniq,Dst0,{list,Env0}}|Is], Remap) ->
+ Env = remap_args(Env0, Remap),
+ Dst = remap_arg(Dst0, Remap),
I = {make_fun3,F,Index,OldUniq,Dst,{list,Env}},
- remap(T, Map, [I|Acc]);
-remap([{deallocate,N}|Is], Map, Acc) ->
- I = {deallocate,Map({frame_size,N})},
- remap(Is, Map, [I|Acc]);
-remap([{recv_marker_clear,Ref}|Is], Map, Acc) ->
- I = {recv_marker_clear,Map(Ref)},
- remap(Is, Map, [I|Acc]);
-remap([{recv_marker_reserve,Mark}|Is], Map, Acc) ->
- I = {recv_marker_reserve,Map(Mark)},
- remap(Is, Map, [I|Acc]);
-remap([{swap,Reg1,Reg2}|Is], Map, Acc) ->
- I = {swap,Map(Reg1),Map(Reg2)},
- remap(Is, Map, [I|Acc]);
-remap([{test,Name,Fail,Ss}|Is], Map, Acc) ->
- I = {test,Name,Fail,[Map(S) || S <- Ss]},
- remap(Is, Map, [I|Acc]);
-remap([{test,Name,Fail,Live,Ss,Dst}|Is], Map, Acc) ->
- I = {test,Name,Fail,Live,[Map(S) || S <- Ss],Map(Dst)},
- remap(Is, Map, [I|Acc]);
-remap([return|_]=Is, _, Acc) ->
- reverse(Acc, Is);
-remap([{line,_}=I|Is], Map, Acc) ->
- remap(Is, Map, [I|Acc]).
-
-remap_block([{set,Ds0,Ss0,Info}|Is], Map, Acc) ->
- Ds = [Map(D) || D <- Ds0],
- Ss = [Map(S) || S <- Ss0],
- remap_block(Is, Map, [{set,Ds,Ss,Info}|Acc]);
-remap_block([], _, Acc) -> reverse(Acc).
+ [I|remap(Is, Remap)];
+remap([{deallocate,N}|Is], {Trim,_}=Remap) ->
+ I = {deallocate,N-Trim},
+ [I|remap(Is, Remap)];
+remap([{recv_marker_clear,Ref}|Is], Remap) ->
+ I = {recv_marker_clear,remap_arg(Ref, Remap)},
+ [I|remap(Is, Remap)];
+remap([{recv_marker_reserve,Mark}|Is], Remap) ->
+ I = {recv_marker_reserve,remap_arg(Mark, Remap)},
+ [I|remap(Is, Remap)];
+remap([{swap,Reg1,Reg2}|Is], Remap) ->
+ I = {swap,remap_arg(Reg1, Remap),remap_arg(Reg2, Remap)},
+ [I|remap(Is, Remap)];
+remap([{test,Name,Fail,Ss}|Is], Remap) ->
+ I = {test,Name,Fail,remap_args(Ss, Remap)},
+ [I|remap(Is, Remap)];
+remap([{test,Name,Fail,Live,Ss,Dst}|Is], Remap) ->
+ I = {test,Name,Fail,Live,remap_args(Ss, Remap),remap_arg(Dst, Remap)},
+ [I|remap(Is, Remap)];
+remap([return|_]=Is, _) ->
+ Is;
+remap([{line,_}=I|Is], Remap) ->
+ [I|remap(Is, Remap)].
+
+remap_block([{set,[{x,_}]=Ds,Ss0,Info}|Is], Remap) ->
+ Ss = remap_args(Ss0, Remap),
+ [{set,Ds,Ss,Info}|remap_block(Is, Remap)];
+remap_block([{set,Ds0,Ss0,Info}|Is], Remap) ->
+ Ds = remap_args(Ds0, Remap),
+ Ss = remap_args(Ss0, Remap),
+ [{set,Ds,Ss,Info}|remap_block(Is, Remap)];
+remap_block([], _) -> [].
+
+remap_args(Args, {Trim,Map}) ->
+ [remap_arg(Arg, Trim, Map) || Arg <- Args].
+
+remap_arg(Arg, {Trim,Map}) ->
+ remap_arg(Arg, Trim, Map).
+
+remap_arg(Arg, Trim, Map) ->
+ case Arg of
+ {y,Y} when Y < Trim ->
+ {y,map_get(Y, Map)};
+ {y,Y} ->
+ {y,Y-Trim};
+ #tr{r={y,Y},t=Type} when Y < Trim ->
+ #tr{r={y,map_get(Y, Map)},t=Type};
+ #tr{r={y,Y},t=Type} ->
+ #tr{r={y,Y-Trim},t=Type};
+ Other ->
+ Other
+ end.
%% safe_labels([Instruction], Accumulator) -> gb_set()
%% Build a gb_set of safe labels. The code at a safe
@@ -350,6 +362,8 @@ is_safe_label([{try_case_end,{Tag,_}}|_]) ->
Tag =/= y;
is_safe_label([if_end|_]) ->
true;
+is_safe_label([{badrecord,{Tag,_}}|_]) ->
+ Tag =/= y;
is_safe_label([{block,Bl}|Is]) ->
is_safe_label_block(Bl) andalso is_safe_label(Is);
is_safe_label([{call_ext,_,{extfunc,M,F,A}}|_]) ->
@@ -357,7 +371,8 @@ is_safe_label([{call_ext,_,{extfunc,M,F,A}}|_]) ->
is_safe_label(_) -> false.
is_safe_label_block([{set,Ds,Ss,_}|Is]) ->
- IsYreg = fun({y,_}) -> true;
+ IsYreg = fun(#tr{r={y,_}}) -> true;
+ ({y,_}) -> true;
(_) -> false
end,
%% This instruction is safe if the instruction
@@ -370,176 +385,210 @@ is_safe_label_block([]) -> true.
%% [{kill,Reg} | {live,Reg} | {dead,Reg}]
%% Figure out the layout of the stack frame.
-frame_layout(Is, Kills, #st{safe=Safe}) ->
- N = frame_size(Is, Safe),
- IsKilled = fun(R) -> is_not_used(R, Is) end,
- {N,frame_layout_1(Kills, 0, N, IsKilled, [])}.
-
-frame_layout_1([{kill,{y,Y}}=I|Ks], Y, N, IsKilled, Acc) ->
- frame_layout_1(Ks, Y+1, N, IsKilled, [I|Acc]);
-frame_layout_1(Ks, Y, N, IsKilled, Acc) when Y < N ->
- R = {y,Y},
- I = case IsKilled(R) of
- false -> {live,R};
- true -> {dead,R}
- end,
- frame_layout_1(Ks, Y+1, N, IsKilled, [I|Acc]);
-frame_layout_1([], Y, Y, _, Acc) ->
- frame_layout_2(Acc).
-
-frame_layout_2([{live,_}|Is]) -> frame_layout_2(Is);
-frame_layout_2(Is) -> reverse(Is).
-
-%% frame_size([Instruction], SafeLabels) -> FrameSize
-%% Find out the frame size by looking at the code that follows.
+frame_layout(N, Killed, {U,_}) ->
+ Dead0 = [{y,R} || R <- seq(0, N - 1)],
+ Dead = ordsets:subtract(Dead0, ordsets:union(U, Killed)),
+ Is = [[{R,{live,R}} || R <- U],
+ [{R,{dead,R}} || R <- Dead],
+ [{R,{kill,R}} || R <- Killed]],
+ [I || {_,I} <- lists:merge(Is)].
+
+%% usage([Instruction], SafeLabels) -> {FrameSize,[UsedYRegs]}
+%% Find out the frame size and usage information by looking at the
+%% code that follows.
%%
%% Implicitly, also check that the instructions are a straight
%% sequence of code that ends in a return. Any branches are
%% to safe labels (i.e., the code at those labels don't depend
%% on the contents of any Y register).
-frame_size([{'%',_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{block,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{call_fun,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{call,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{call_ext,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{apply,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{bif,_,{f,L},_,_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{gc_bif,_,{f,L},_,_,_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{test,_,{f,L},_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{test,_,{f,L},_,_,_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{bs_init,{f,L},_,_,_,_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{bs_put,{f,L},_,_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{init_yregs,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{make_fun2,_,_,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{make_fun3,_,_,_,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{recv_marker_clear,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{recv_marker_reserve,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{get_map_elements,{f,L},_,_}|Is], Safe) ->
- frame_size_branch(L, Is, Safe);
-frame_size([{deallocate,N}|_], _) ->
- N;
-frame_size([{line,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{bs_start_match4,Fail,_,_,_}|Is], Safe) ->
- case Fail of
- {f,L} -> frame_size_branch(L, Is, Safe);
- _ -> frame_size(Is, Safe)
- end;
-frame_size([{bs_set_position,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{bs_get_tail,_,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size([{swap,_,_}|Is], Safe) ->
- frame_size(Is, Safe);
-frame_size(_, _) -> throw(not_possible).
-
-frame_size_branch(0, Is, Safe) ->
- frame_size(Is, Safe);
-frame_size_branch(L, Is, Safe) ->
- case sets:is_element(L, Safe) of
- false -> throw(not_possible);
- true -> frame_size(Is, Safe)
+usage(Is0, St) ->
+ Is = usage_1(Is0, []),
+ do_usage(Is, St).
+
+usage_1([{label,_}|_], Acc) ->
+ Acc;
+usage_1([I|Is], Acc) ->
+ usage_1(Is, [I|Acc]);
+usage_1([], Acc) ->
+ Acc.
+
+do_usage(Is0, #st{safe=Safe}) ->
+ case Is0 of
+ [return,{deallocate,N}|Is] ->
+ Regs = [],
+ case do_usage(Is, Safe, Regs, [], []) of
+ none ->
+ none;
+ Us ->
+ {N,Us}
+ end;
+ _ ->
+ none
end.
-%% is_not_used(Y, [Instruction]) -> true|false.
-%% Test whether the value of Y is unused in the instruction sequence.
-%% Return true if the value of Y is not used, and false if it is used.
-%%
-%% This function handles the same instructions as frame_size/2. It
-%% assumes that any labels in the instructions are safe labels.
-
-is_not_used(Y, [{'%',_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(Y, [{apply,_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(Y, [{bif,_,{f,_},Ss,Dst}|Is]) ->
- is_not_used_ss_dst(Y, Ss, Dst, Is);
-is_not_used(Y, [{block,Bl}|Is]) ->
- case is_not_used_block(Y, Bl) of
- used -> false;
- killed -> true;
- transparent -> is_not_used(Y, Is)
+do_usage([{'%',_}|Is], Safe, Regs, Ns, Acc) ->
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{apply,_}|Is], Safe, Regs, Ns, Acc) ->
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{block,Blk}|Is], Safe, Regs0, Ns0, Acc) ->
+ {Regs,Ns} = U = do_usage_blk(Blk, Regs0, Ns0),
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{bs_create_bin,Fail,_,_,_,Dst,{list,Args}}|Is], Safe, Regs0, Ns0, Acc) ->
+ case is_safe_branch(Fail, Safe) of
+ true ->
+ Regs1 = ordsets:del_element(Dst, Regs0),
+ Regs = ordsets:union(Regs1, yregs(Args)),
+ Ns = ordsets:union(yregs([Dst]), Ns0),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+ false ->
+ none
end;
-is_not_used(Y, [{bs_get_tail,Src,Dst,_}|Is]) ->
- is_not_used_ss_dst(Y, [Src], Dst, Is);
-is_not_used(Y, [{bs_init,_,_,_,Ss,Dst}|Is]) ->
- is_not_used_ss_dst(Y, Ss, Dst, Is);
-is_not_used(Y, [{bs_put,{f,_},_,Ss}|Is]) ->
- not member(Y, Ss) andalso is_not_used(Y, Is);
-is_not_used(Y, [{bs_start_match4,_Fail,_Live,Src,Dst}|Is]) ->
- Y =/= Src andalso Y =/= Dst andalso
- is_not_used(Y, Is);
-is_not_used(Y, [{bs_set_position,Src1,Src2}|Is]) ->
- Y =/= Src1 andalso Y =/= Src2 andalso
- is_not_used(Y, Is);
-is_not_used(Y, [{call,_,_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(Y, [{call_ext,_,_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(Y, [{call_fun,_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(_Y, [{deallocate,_}|_]) ->
- true;
-is_not_used(Y, [{gc_bif,_,{f,_},_Live,Ss,Dst}|Is]) ->
- is_not_used_ss_dst(Y, Ss, Dst, Is);
-is_not_used(Y, [{get_map_elements,{f,_},S,{list,List}}|Is]) ->
- {Ss,Ds} = beam_utils:split_even(List),
- case member(Y, [S|Ss]) of
- true ->
- false;
- false ->
- member(Y, Ds) orelse is_not_used(Y, Is)
+do_usage([{bs_get_tail,Src,Dst,_}|Is], Safe, Regs0, Ns0, Acc) ->
+ Regs1 = ordsets:del_element(Dst, Regs0),
+ Regs = ordsets:union(Regs1, yregs([Src])),
+ Ns = ordsets:union(yregs([Dst]), Ns0),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{bs_set_position,Src1,Src2}|Is], Safe, Regs0, Ns, Acc) ->
+ Regs = ordsets:union(Regs0, yregs([Src1,Src2])),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{bs_start_match4,Fail,_Live,Src,Dst}|Is], Safe, Regs0, Ns, Acc) ->
+ case (Fail =:= {atom,no_fail} orelse
+ Fail =:= {atom,resume} orelse
+ is_safe_branch(Fail, Safe)) of
+ true ->
+ Regs = ordsets:union(Regs0, yregs([Src,Dst])),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+ false ->
+ none
end;
-is_not_used(Y, [{init_yregs,{list,Yregs}}|Is]) ->
- member(Y, Yregs) orelse is_not_used(Y, Is);
-is_not_used(Y, [{line,_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(Y, [{make_fun2,_,_,_,_}|Is]) ->
- is_not_used(Y, Is);
-is_not_used(Y, [{make_fun3,_,_,_,Dst,{list,Env}}|Is]) ->
- is_not_used_ss_dst(Y, Env, Dst, Is);
-is_not_used(Y, [{recv_marker_clear,Ref}|Is]) ->
- Y =/= Ref andalso is_not_used(Y, Is);
-is_not_used(Y, [{recv_marker_reserve,Dst}|Is]) ->
- Y =/= Dst andalso is_not_used(Y, Is);
-is_not_used(Y, [{swap,Reg1,Reg2}|Is]) ->
- Y =/= Reg1 andalso Y =/= Reg2 andalso is_not_used(Y, Is);
-is_not_used(Y, [{test,_,_,Ss}|Is]) ->
- not member(Y, Ss) andalso is_not_used(Y, Is);
-is_not_used(Y, [{test,_Op,{f,_},_Live,Ss,Dst}|Is]) ->
- is_not_used_ss_dst(Y, Ss, Dst, Is).
-
-is_not_used_block(Y, [{set,Ds,Ss,_}|Is]) ->
- case member(Y, Ss) of
+do_usage([{call,_,_}|Is], Safe, Regs, Ns, Acc) ->
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{call_ext,_,_}|Is], Safe, Regs, Ns, Acc) ->
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{call_fun,_}|Is], Safe, Regs, Ns, Acc) ->
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{call_fun2,_,_,Ss}|Is], Safe, Regs0, Ns, Acc) ->
+ Regs = ordsets:union(Regs0, yregs([Ss])),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{bif,_,Fail,Ss,Dst}|Is], Safe, Regs0, Ns0, Acc) ->
+ case is_safe_branch(Fail, Safe) of
true ->
- used;
+ Regs1 = ordsets:del_element(Dst, Regs0),
+ Regs = ordsets:union(Regs1, yregs(Ss)),
+ Ns = ordsets:union(yregs([Dst]), Ns0),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
false ->
- case member(Y, Ds) of
- true ->
- killed;
- false ->
- is_not_used_block(Y, Is)
- end
+ none
end;
-is_not_used_block(_Y, []) -> transparent.
-
-is_not_used_ss_dst(Y, Ss, Dst, Is) ->
- not member(Y, Ss) andalso (Y =:= Dst orelse is_not_used(Y, Is)).
+do_usage([{gc_bif,_,Fail,_,Ss,Dst}|Is], Safe, Regs0, Ns0, Acc) ->
+ case is_safe_branch(Fail, Safe) of
+ true ->
+ Regs1 = ordsets:del_element(Dst, Regs0),
+ Regs = ordsets:union(Regs1, yregs(Ss)),
+ Ns = ordsets:union(yregs([Dst]), Ns0),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+ false ->
+ none
+ end;
+do_usage([{get_map_elements,Fail,S,{list,List}}|Is], Safe, Regs0, Ns0, Acc) ->
+ case is_safe_branch(Fail, Safe) of
+ true ->
+ {Ss,Ds1} = beam_utils:split_even(List),
+ Ds = yregs(Ds1),
+ Regs1 = ordsets:subtract(Regs0, Ds),
+ Regs = ordsets:union(Regs1, yregs([S|Ss])),
+ Ns = ordsets:union(Ns0, Ds),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+ false ->
+ none
+ end;
+do_usage([{init_yregs,{list,Ds}}|Is], Safe, Regs0, Ns0, Acc) ->
+ Regs = ordsets:subtract(Regs0, Ds),
+ Ns = ordsets:union(Ns0, Ds),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{make_fun3,_,_,_,Dst,{list,Ss}}|Is], Safe, Regs0, Ns0, Acc) ->
+ Regs1 = ordsets:del_element(Dst, Regs0),
+ Regs = ordsets:union(Regs1, yregs(Ss)),
+ Ns = ordsets:union(yregs([Dst]), Ns0),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{line,_}|Is], Safe, Regs, Ns, Acc) ->
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{recv_marker_clear,Src}|Is], Safe, Regs0, Ns, Acc) ->
+ Regs = ordsets:union(Regs0, yregs([Src])),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{recv_marker_reserve,Src}|Is], Safe, Regs0, Ns, Acc) ->
+ Regs = ordsets:union(Regs0, yregs([Src])),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{swap,R1,R2}|Is], Safe, Regs0, Ns0, Acc) ->
+ Ds = yregs([R1,R2]),
+ Regs = ordsets:union(Regs0, Ds),
+ Ns = ordsets:union(Ns0, Ds),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+do_usage([{test,_,Fail,Ss}|Is], Safe, Regs0, Ns, Acc) ->
+ case is_safe_branch(Fail, Safe) of
+ true ->
+ Regs = ordsets:union(Regs0, yregs(Ss)),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+ false ->
+ none
+ end;
+do_usage([{test,_,Fail,_,Ss,Dst}|Is], Safe, Regs0, Ns0, Acc) ->
+ case is_safe_branch(Fail, Safe) of
+ true ->
+ Regs1 = ordsets:del_element(Dst, Regs0),
+ Regs = ordsets:union(Regs1, yregs(Ss)),
+ Ns = ordsets:union(yregs([Dst]), Ns0),
+ U = {Regs,Ns},
+ do_usage(Is, Safe, Regs, Ns, [U|Acc]);
+ false ->
+ none
+ end;
+do_usage([_I|_], _, _, _, _) ->
+ none;
+do_usage([], _Safe, _Regs, _Ns, Acc) -> Acc.
+
+do_usage_blk([{set,Ds0,Ss,_}|Is], Regs0, Ns0) ->
+ Ds = yregs(Ds0),
+ {Regs1,Ns1} = do_usage_blk(Is, Regs0, Ns0),
+ Regs2 = ordsets:subtract(Regs1, Ds),
+ Regs = ordsets:union(Regs2, yregs(Ss)),
+ Ns = ordsets:union(Ns1, Ds),
+ {Regs,Ns};
+do_usage_blk([], Regs, Ns) -> {Regs,Ns}.
+
+is_safe_branch({f,0}, _Safe) ->
+ true;
+is_safe_branch({f,L}, Safe) ->
+ sets:is_element(L, Safe).
+
+yregs(Rs) ->
+ ordsets:from_list(yregs_1(Rs)).
+
+yregs_1([{y,_}=Y|Rs]) ->
+ [Y|yregs_1(Rs)];
+yregs_1([{tr,{y,_}=Y,_}|Rs]) ->
+ [Y|yregs_1(Rs)];
+yregs_1([_|Rs]) ->
+ yregs_1(Rs);
+yregs_1([]) -> [].
diff --git a/lib/compiler/src/beam_types.erl b/lib/compiler/src/beam_types.erl
index ecf5d55c3b..b2fef1e7ac 100644
--- a/lib/compiler/src/beam_types.erl
+++ b/lib/compiler/src/beam_types.erl
@@ -49,6 +49,8 @@
-export([limit_depth/1]).
+-export([decode_ext/1, encode_ext/1]).
+
%% This is exported to help catch errors in property test generators and is not
%% meant to be used outside of test suites.
-export([verified_type/1]).
@@ -615,6 +617,8 @@ make_integer(Min, Max) when is_integer(Min), is_integer(Max), Min =< Max ->
limit_depth(Type) ->
limit_depth(Type, ?MAX_TYPE_DEPTH).
+-spec limit_depth(type(), non_neg_integer()) -> type().
+
limit_depth(#t_cons{}=T, Depth) ->
limit_depth_list(T, Depth);
limit_depth(#t_list{}=T, Depth) ->
@@ -669,7 +673,10 @@ limit_depth_map(#t_map{}, Depth) when Depth =< 0 ->
limit_depth_tuple(#t_tuple{elements=Es0}=T, Depth) ->
if
Depth > 0 ->
- Es = maps:map(fun(_, E) -> limit_depth(E, Depth - 1) end, Es0),
+ Es = foldl(fun({Index, E0}, Es1) ->
+ E = limit_depth(E0, Depth - 1),
+ set_tuple_element(Index, E, Es1)
+ end, Es0, maps:to_list(Es0)),
T#t_tuple{elements=Es};
Depth =< 0 ->
#t_tuple{elements=#{}}
@@ -723,20 +730,9 @@ glb(#t_bitstring{size_unit=U1}, #t_bitstring{size_unit=U2}) ->
glb(#t_bitstring{size_unit=UnitA}=T, #t_bs_matchable{tail_unit=UnitB}) ->
Unit = UnitA * UnitB div gcd(UnitA, UnitB),
T#t_bitstring{size_unit=Unit};
-glb(#t_bs_context{tail_unit=UnitA,slots=SlotCountA,valid=ValidSlotsA},
- #t_bs_context{tail_unit=UnitB,slots=SlotCountB,valid=ValidSlotsB}) ->
- CommonSlotMask = (1 bsl min(SlotCountA, SlotCountB)) - 1,
- CommonSlotsA = ValidSlotsA band CommonSlotMask,
- CommonSlotsB = ValidSlotsB band CommonSlotMask,
+glb(#t_bs_context{tail_unit=UnitA}, #t_bs_context{tail_unit=UnitB}) ->
Unit = UnitA * UnitB div gcd(UnitA, UnitB),
- if
- CommonSlotsA =:= CommonSlotsB ->
- #t_bs_context{tail_unit=Unit,
- slots=max(SlotCountA, SlotCountB),
- valid=ValidSlotsA bor ValidSlotsB};
- CommonSlotsA =/= CommonSlotsB ->
- none
- end;
+ #t_bs_context{tail_unit=Unit};
glb(#t_bs_context{tail_unit=UnitA}=T, #t_bs_matchable{tail_unit=UnitB}) ->
Unit = UnitA * UnitB div gcd(UnitA, UnitB),
T#t_bs_context{tail_unit=Unit};
@@ -773,12 +769,17 @@ glb(#t_float{elements={MinA,MaxA}}, #t_float{elements={MinB,MaxB}})
MinB >= MinA, MinB =< MaxA ->
true = MinA =< MaxA andalso MinB =< MaxB, %Assertion.
#t_float{elements={max(MinA, MinB),min(MaxA, MaxB)}};
-glb(#t_fun{arity=Same,type=TypeA}, #t_fun{arity=Same,type=TypeB}=T) ->
- T#t_fun{type=meet(TypeA, TypeB)};
-glb(#t_fun{arity=any,type=TypeA}, #t_fun{type=TypeB}=T) ->
- T#t_fun{type=meet(TypeA, TypeB)};
-glb(#t_fun{type=TypeA}=T, #t_fun{arity=any,type=TypeB}) ->
+glb(#t_fun{arity=SameArity,target=SameTarget,type=TypeA},
+ #t_fun{arity=SameArity,target=SameTarget,type=TypeB}=T) ->
T#t_fun{type=meet(TypeA, TypeB)};
+glb(#t_fun{target=TargetA}=A, #t_fun{target=any}=B) when TargetA =/= any ->
+ glb(A, B#t_fun{target=TargetA});
+glb(#t_fun{target=any}=A, #t_fun{target=TargetB}=B) when TargetB =/= any ->
+ glb(A#t_fun{target=TargetB}, B);
+glb(#t_fun{arity=any}=A, #t_fun{arity=ArityB}=B) when ArityB =/= any->
+ glb(A#t_fun{arity=ArityB}, B);
+glb(#t_fun{arity=ArityA}=A, #t_fun{arity=any}=B) when ArityA =/= any ->
+ glb(A, B#t_fun{arity=ArityA});
glb(#t_integer{elements={_,_}}=T, #t_integer{elements=any}) ->
T;
glb(#t_integer{elements=any}, #t_integer{elements={_,_}}=T) ->
@@ -899,11 +900,8 @@ lub(#t_bitstring{size_unit=U1}, #t_bs_context{tail_unit=U2}) ->
#t_bs_matchable{tail_unit=gcd(U1, U2)};
lub(#t_bitstring{size_unit=UnitA}, #t_bs_matchable{tail_unit=UnitB}) ->
lub_bs_matchable(UnitA, UnitB);
-lub(#t_bs_context{tail_unit=UnitA,slots=SlotsA,valid=ValidA},
- #t_bs_context{tail_unit=UnitB,slots=SlotsB,valid=ValidB}) ->
- #t_bs_context{tail_unit=gcd(UnitA, UnitB),
- slots=min(SlotsA, SlotsB),
- valid=ValidA band ValidB};
+lub(#t_bs_context{tail_unit=UnitA}, #t_bs_context{tail_unit=UnitB}) ->
+ #t_bs_context{tail_unit=gcd(UnitA, UnitB)};
lub(#t_bs_context{tail_unit=U1}, #t_bitstring{size_unit=U2}) ->
#t_bs_matchable{tail_unit=gcd(U1, U2)};
lub(#t_bs_context{tail_unit=UnitA}, #t_bs_matchable{tail_unit=UnitB}) ->
@@ -932,8 +930,11 @@ lub(#t_float{}, #t_integer{}) ->
number;
lub(#t_float{}, number) ->
number;
-lub(#t_fun{arity=Same,type=TypeA}, #t_fun{arity=Same,type=TypeB}) ->
- #t_fun{arity=Same,type=join(TypeA, TypeB)};
+lub(#t_fun{arity=SameArity,target=SameTarget,type=TypeA},
+ #t_fun{arity=SameArity,target=SameTarget,type=TypeB}) ->
+ #t_fun{arity=SameArity,target=SameTarget,type=join(TypeA, TypeB)};
+lub(#t_fun{arity=SameArity,type=TypeA}, #t_fun{arity=SameArity,type=TypeB}) ->
+ #t_fun{arity=SameArity,type=join(TypeA, TypeB)};
lub(#t_fun{type=TypeA}, #t_fun{type=TypeB}) ->
#t_fun{type=join(TypeA, TypeB)};
lub(#t_integer{elements={MinA,MaxA}},
@@ -1109,7 +1110,18 @@ verified_normal_type(#t_cons{type=Type,terminator=Term}=T) ->
_ = verified_type(Type),
_ = verified_type(Term),
T;
-verified_normal_type(#t_fun{arity=Arity,type=ReturnType}=T)
+verified_normal_type(#t_fun{arity=Arity,
+ target={Name,TotalArity},
+ type=ReturnType}=T)
+ when is_integer(Arity),
+ is_atom(Name),
+ is_integer(TotalArity),
+ TotalArity >= Arity ->
+ _ = verified_type(ReturnType),
+ T;
+verified_normal_type(#t_fun{arity=Arity,
+ target=any,
+ type=ReturnType}=T)
when Arity =:= any; is_integer(Arity) ->
_ = verified_type(ReturnType),
T;
@@ -1125,6 +1137,9 @@ verified_normal_type(#t_list{type=Type,terminator=Term}=T) ->
verified_normal_type(#t_map{}=T) -> T;
verified_normal_type(nil=T) -> T;
verified_normal_type(number=T) -> T;
+verified_normal_type(pid=T) -> T;
+verified_normal_type(port=T) -> T;
+verified_normal_type(reference=T) -> T;
verified_normal_type(#t_tuple{size=Size,elements=Es}=T) ->
%% All known elements must have a valid index and type (which may be a
%% union). 'any' is prohibited since it's implicit and should never be
@@ -1137,3 +1152,93 @@ verified_normal_type(#t_tuple{size=Size,elements=Es}=T) ->
verified_type(Element)
end, [], Es),
T.
+
+%%%
+%%% External type format
+%%%
+%%% This is a stripped-down version of our internal format, focusing solely on
+%%% primary types and unions thereof. The idea is to help the JIT skip minor
+%%% details inside instructions when we know they're pointless, such as
+%%% checking whether the source of `is_tagged_tuple` is boxed, or reducing an
+%%% equality check to a single machine compare instruction when we know that
+%%% both arguments are immediates.
+%%%
+
+-define(BEAM_TYPE_ATOM, (1 bsl 0)).
+-define(BEAM_TYPE_BITSTRING, (1 bsl 1)).
+-define(BEAM_TYPE_BS_MATCHSTATE, (1 bsl 2)).
+-define(BEAM_TYPE_CONS, (1 bsl 3)).
+-define(BEAM_TYPE_FLOAT, (1 bsl 4)).
+-define(BEAM_TYPE_FUN, (1 bsl 5)).
+-define(BEAM_TYPE_INTEGER, (1 bsl 6)).
+-define(BEAM_TYPE_MAP, (1 bsl 7)).
+-define(BEAM_TYPE_NIL, (1 bsl 8)).
+-define(BEAM_TYPE_PID, (1 bsl 9)).
+-define(BEAM_TYPE_PORT, (1 bsl 10)).
+-define(BEAM_TYPE_REFERENCE, (1 bsl 11)).
+-define(BEAM_TYPE_TUPLE, (1 bsl 12)).
+
+ext_type_mapping() ->
+ [{?BEAM_TYPE_ATOM, #t_atom{}},
+ {?BEAM_TYPE_BITSTRING, #t_bitstring{}},
+ {?BEAM_TYPE_BS_MATCHSTATE, #t_bs_context{}},
+ {?BEAM_TYPE_CONS, #t_cons{}},
+ {?BEAM_TYPE_FLOAT, #t_float{}},
+ {?BEAM_TYPE_FUN, #t_fun{}},
+ {?BEAM_TYPE_INTEGER, #t_integer{}},
+ {?BEAM_TYPE_MAP, #t_map{}},
+ {?BEAM_TYPE_NIL, nil},
+ {?BEAM_TYPE_PID, pid},
+ {?BEAM_TYPE_PORT, port},
+ {?BEAM_TYPE_REFERENCE, reference},
+ {?BEAM_TYPE_TUPLE, #t_tuple{}}].
+
+-spec decode_ext(binary()) -> type().
+decode_ext(<<TypeBits:16/big,Min:64,Max:64>>) ->
+ Res = foldl(fun({Id, Type}, Acc) ->
+ decode_ext_bits(TypeBits, Id, Type, Acc)
+ end, none, ext_type_mapping()),
+ {Res,Min,Max}.
+
+decode_ext_bits(Input, TypeBit, Type, Acc) ->
+ case Input band TypeBit of
+ 0 -> Acc;
+ _ -> join(Type, Acc)
+ end.
+
+-spec encode_ext(type()) -> binary().
+encode_ext(Input) ->
+ TypeBits = foldl(fun({Id, Type}, Acc) ->
+ encode_ext_bits(Input, Id, Type, Acc)
+ end, 0, ext_type_mapping()),
+ case get_integer_range(Input) of
+ none ->
+ <<TypeBits:16/big,0:64,-1:64>>;
+ {Min,Max} ->
+ <<TypeBits:16/big,Min:64,Max:64>>
+ end.
+
+encode_ext_bits(Input, TypeBit, Type, Acc) ->
+ case meet(Input, Type) of
+ none -> Acc;
+ _ -> Acc bor TypeBit
+ end.
+
+get_integer_range(#t_integer{elements={Min,Max}}) ->
+ case is_small(Min) andalso is_small(Max) of
+ true ->
+ {Min,Max};
+ false ->
+ %% Not an integer with range, or at least one of the
+ %% endpoints is a bignum.
+ none
+ end;
+get_integer_range(#t_union{number=N}) ->
+ get_integer_range(N);
+get_integer_range(_) -> none.
+
+%% Test whether the number is a small on a 64-bit machine.
+%% (Normally the compiler doesn't know/doesn't care whether something is
+%% bignum, but because the type representation is versioned this is safe.)
+is_small(N) ->
+ -(1 bsl 59) =< N andalso N =< (1 bsl 59) - 1.
diff --git a/lib/compiler/src/beam_types.hrl b/lib/compiler/src/beam_types.hrl
index 58ffd18110..18f7e29074 100644
--- a/lib/compiler/src/beam_types.hrl
+++ b/lib/compiler/src/beam_types.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,6 +18,9 @@
%% %CopyrightEnd%
%%
+%% Type version, must be bumped whenever the external type format changes.
+-define(BEAM_TYPES_VERSION, 1).
+
%% Common term types for passes operating on beam SSA and assembly. Helper
%% functions for wrangling these can be found in beam_types.erl
%%
@@ -37,6 +40,9 @@
%% - #t_list{} Any list.
%% -- #t_cons{} Cons (nonempty list).
%% -- nil The empty list.
+%% - pid
+%% - port
+%% - reference
%% - #t_tuple{} Tuple.
%%
%% none No type (bottom element).
@@ -75,15 +81,15 @@
%% [1] https://en.wikipedia.org/wiki/Lattice_(order)#General_lattice
-define(ATOM_SET_SIZE, 5).
+-define(MAX_FUNC_ARGS, 255).
-record(t_atom, {elements=any :: 'any' | ordsets:ordset(atom())}).
-record(t_bitstring, {size_unit=1 :: pos_integer()}).
--record(t_bs_context, {tail_unit=1 :: pos_integer(),
- slots=0 :: non_neg_integer(),
- valid=0 :: non_neg_integer()}).
--record(t_bs_matchable, {tail_unit=1}).
+-record(t_bs_context, {tail_unit=1 :: pos_integer()}).
+-record(t_bs_matchable, {tail_unit=1 :: pos_integer()}).
-record(t_float, {elements=any :: 'any' | {float(),float()}}).
-record(t_fun, {arity=any :: arity() | 'any',
+ target=any :: {atom(), non_neg_integer()} | 'any',
type=any :: type() }).
-record(t_integer, {elements=any :: 'any' | {integer(),integer()}}).
@@ -133,6 +139,9 @@
#t_fun{} |
#t_list{} | #t_cons{} | nil |
#t_map{} |
+ pid |
+ port |
+ reference |
#t_tuple{}.
-type record_key() :: {Arity :: integer(), Tag :: normal_type() }.
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 19cd6282ca..904e1f3e82 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -21,7 +21,7 @@
%%
-module(beam_utils).
--export([replace_labels/4,is_pure_test/1,split_even/1]).
+-export([replace_labels/4,split_even/1]).
-export_type([code_index/0,module_code/0,instruction/0]).
@@ -39,11 +39,6 @@
-type module_code() ::
{module(),[_],[_],[int_function()],pos_integer()}.
-%% Internal types.
--type fail() :: beam_asm:fail() | 'fail'.
--type test() :: {'test',atom(),fail(),[beam_asm:src()]} |
- {'test',atom(),fail(),integer(),list(),beam_asm:reg()}.
-
%% replace_labels(FunctionIs, Tail, ReplaceDb, Fallback) -> FunctionIs.
%% Replace all labels in instructions according to the ReplaceDb.
%% If label is not found the Fallback is called with the label to
@@ -56,28 +51,6 @@
replace_labels(Is, Acc, D, Fb) ->
replace_labels_1(Is, Acc, D, Fb).
-%% is_pure_test({test,Op,Fail,Ops}) -> true|false.
-%% Return 'true' if the test instruction does not modify any
-%% registers and/or bit syntax matching state.
-%%
-
--spec is_pure_test(test()) -> boolean().
-
-is_pure_test({test,is_eq,_,[_,_]}) -> true;
-is_pure_test({test,is_ne,_,[_,_]}) -> true;
-is_pure_test({test,is_eq_exact,_,[_,_]}) -> true;
-is_pure_test({test,is_ne_exact,_,[_,_]}) -> true;
-is_pure_test({test,is_ge,_,[_,_]}) -> true;
-is_pure_test({test,is_lt,_,[_,_]}) -> true;
-is_pure_test({test,is_nonempty_list,_,[_]}) -> true;
-is_pure_test({test,is_tagged_tuple,_,[_,_,_]}) -> true;
-is_pure_test({test,test_arity,_,[_,_]}) -> true;
-is_pure_test({test,has_map_fields,_,[_|_]}) -> true;
-is_pure_test({test,is_bitstr,_,[_]}) -> true;
-is_pure_test({test,is_function2,_,[_,_]}) -> true;
-is_pure_test({test,Op,_,Ops}) ->
- erl_internal:new_type_test(Op, length(Ops)).
-
%% split_even/1
%% [1,2,3,4,5,6] -> {[1,3,5],[2,4,6]}
@@ -120,10 +93,16 @@ replace_labels_1([{gc_bif,Name,{f,Lbl},Live,As,R}|Is], Acc, D, Fb) when Lbl =/=
replace_labels_1(Is, [{gc_bif,Name,{f,label(Lbl, D, Fb)},Live,As,R}|Acc], D, Fb);
replace_labels_1([{call,Ar,{f,Lbl}}|Is], Acc, D, Fb) ->
replace_labels_1(Is, [{call,Ar,{f,label(Lbl, D, Fb)}}|Acc], D, Fb);
+replace_labels_1([{call_fun2,{f,Lbl},Ar,Func}|Is], Acc, D, Fb) ->
+ replace_labels_1(Is, [{call_fun2,{f,label(Lbl, D, Fb)},Ar,Func}|Acc], D, Fb);
replace_labels_1([{make_fun2,{f,Lbl},U1,U2,U3}|Is], Acc, D, Fb) ->
replace_labels_1(Is, [{make_fun2,{f,label(Lbl, D, Fb)},U1,U2,U3}|Acc], D, Fb);
replace_labels_1([{make_fun3,{f,Lbl},U1,U2,U3,U4}|Is], Acc, D, Fb) ->
replace_labels_1(Is, [{make_fun3,{f,label(Lbl, D, Fb)},U1,U2,U3,U4}|Acc], D, Fb);
+replace_labels_1([{bs_create_bin,{f,Lbl},Alloc,Live,Unit,Dst,{list,List}}|Is], Acc, D, Fb)
+ when Lbl =/= 0 ->
+ replace_labels_1(Is, [{bs_create_bin,{f,label(Lbl, D, Fb)},
+ Alloc,Live,Unit,Dst,{list,List}}|Acc], D, Fb);
replace_labels_1([{bs_init,{f,Lbl},Info,Live,Ss,Dst}|Is], Acc, D, Fb) when Lbl =/= 0 ->
replace_labels_1(Is, [{bs_init,{f,label(Lbl, D, Fb)},Info,Live,Ss,Dst}|Acc], D, Fb);
replace_labels_1([{bs_put,{f,Lbl},Info,Ss}|Is], Acc, D, Fb) when Lbl =/= 0 ->
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index d61722e0b4..b38d288f99 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
-module(beam_validator).
--include("beam_types.hrl").
+-include("beam_asm.hrl").
-define(UNICODE_MAX, (16#10FFFF)).
@@ -126,24 +126,24 @@ validate_0([{function, Name, Arity, Entry, Code} | Fs], Module, Level, Ft) ->
-record(t_abstract, {kind}).
-%% The types are the same as in 'beam_types.hrl', with the addition of
-%% #t_abstract{} that describes tuples under construction, match context
-%% positions, and so on.
--type validator_type() :: #t_abstract{} | type().
+%% The types are the same as in 'beam_types.hrl', with the addition of:
+%%
+%% * `#t_abstract{}` which describes tuples under construction, match context
+%% positions, and so on.
+%% * `(fun(values()) -> type())` that defers figuring out the type until it's
+%% actually used. Mainly used to coax more type information out of
+%% `get_tuple_element` where a test on one element (e.g. record tag) may
+%% affect the type of another.
+-type validator_type() :: #t_abstract{} | fun((values()) -> type()) | type().
-record(value_ref, {id :: index()}).
-record(value, {op :: term(), args :: [argument()], type :: validator_type()}).
--type argument() :: #value_ref{} | literal().
+-type argument() :: #value_ref{} | beam_literal().
+-type values() :: #{ #value_ref{} => #value{} }.
-type index() :: non_neg_integer().
--type literal() :: {atom, [] | atom()} |
- {float, [] | float()} |
- {integer, [] | integer()} |
- {literal, term()} |
- nil.
-
%% Register tags describe the state of the register rather than the value they
%% contain (if any).
%%
@@ -173,7 +173,7 @@ validate_0([{function, Name, Arity, Entry, Code} | Fs], Module, Level, Ft) ->
%% Emulation state
-record(st,
{%% All known values.
- vs=#{} :: #{ #value_ref{} => #value{} },
+ vs=#{} :: values(),
%% Register states.
xs=#{} :: x_regs(),
ys=#{} :: y_regs(),
@@ -235,7 +235,7 @@ validate_0([{function, Name, Arity, Entry, Code} | Fs], Module, Level, Ft) ->
ref_ctr=0 :: index()
}).
-build_function_table([{function,_,Arity,Entry,Code0}|Fs], Acc) ->
+build_function_table([{function,Name,Arity,Entry,Code0}|Fs], Acc) ->
Code = dropwhile(fun({label,L}) when L =:= Entry ->
false;
(_) ->
@@ -243,8 +243,10 @@ build_function_table([{function,_,Arity,Entry,Code0}|Fs], Acc) ->
end, Code0),
case Code of
[{label,Entry} | Is] ->
- Info = #{ arity => Arity,
- parameter_info => find_parameter_info(Is, #{}) },
+ Info = #{ name => Name,
+ arity => Arity,
+ parameter_info => find_parameter_info(Is, #{}),
+ always_fails => always_fails(Is) },
build_function_table(Fs, Acc#{ Entry => Info });
_ ->
%% Something is seriously wrong. Ignore it for now.
@@ -261,6 +263,9 @@ find_parameter_info([{'%', _} | Is], Acc) ->
find_parameter_info(_, Acc) ->
Acc.
+always_fails([{jump,_}|_]) -> true;
+always_fails(_) -> false.
+
validate_1(Is, MFA0, Entry, Level, Ft) ->
{Offset, MFA, Header, Body} = extract_header(Is, MFA0, Entry, 1, []),
@@ -274,7 +279,7 @@ validate_1(Is, MFA0, Entry, Level, Ft) ->
validate_branches(MFA, Vst).
extract_header([{func_info, {atom,Mod}, {atom,Name}, Arity}=I | Is],
- MFA0, Entry, Offset, Acc) ->
+ MFA0, Entry, Offset, Acc) ->
{_, Name, Arity} = MFA0, %Assertion.
MFA = {Mod, Name, Arity},
@@ -367,7 +372,8 @@ vi({'%',_}, Vst) ->
Vst;
vi({line,_}, Vst) ->
Vst;
-
+vi(nif_start, Vst) ->
+ Vst;
%%
%% Moves
%%
@@ -425,7 +431,9 @@ vi({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
assert_term(Src, Vst),
assert_choices(Choices),
validate_select_val(Fail, Choices, Src, Vst);
-vi({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
+vi({select_tuple_arity,Tuple0,{f,Fail},{list,Choices}}, Vst) ->
+ Tuple = unpack_typed_arg(Tuple0),
+
assert_type(#t_tuple{}, Tuple, Vst),
assert_arities(Choices),
validate_select_tuple_arity(Fail, Choices, Tuple, Vst);
@@ -441,6 +449,24 @@ vi({test,is_boolean,{f,Lbl},[Src]}, Vst) ->
type_test(Lbl, beam_types:make_boolean(), Src, Vst);
vi({test,is_float,{f,Lbl},[Src]}, Vst) ->
type_test(Lbl, #t_float{}, Src, Vst);
+vi({test,is_function,{f,Lbl},[Src]}, Vst) ->
+ type_test(Lbl, #t_fun{}, Src, Vst);
+vi({test,is_function2,{f,Lbl},[Src,{integer,Arity}]}, Vst)
+ when Arity >= 0, Arity =< ?MAX_FUNC_ARGS ->
+ type_test(Lbl, #t_fun{arity=Arity}, Src, Vst);
+vi({test,is_function2,{f,Lbl},[Src0,_Arity]}, Vst) ->
+ Src = unpack_typed_arg(Src0),
+ assert_term(Src, Vst),
+ branch(Lbl, Vst,
+ fun(FailVst) ->
+ %% We cannot subtract the function type when the arity is
+ %% unknown: `Src` may still be a function if the arity is
+ %% outside the allowed range.
+ FailVst
+ end,
+ fun(SuccVst) ->
+ update_type(fun meet/2, #t_fun{}, Src, SuccVst)
+ end);
vi({test,is_tuple,{f,Lbl},[Src]}, Vst) ->
type_test(Lbl, #t_tuple{}, Src, Vst);
vi({test,is_integer,{f,Lbl},[Src]}, Vst) ->
@@ -453,9 +479,10 @@ vi({test,is_list,{f,Lbl},[Src]}, Vst) ->
type_test(Lbl, #t_list{}, Src, Vst);
vi({test,is_map,{f,Lbl},[Src]}, Vst) ->
type_test(Lbl, #t_map{}, Src, Vst);
-vi({test,is_nil,{f,Lbl},[Src]}, Vst) ->
+vi({test,is_nil,{f,Lbl},[Src0]}, Vst) ->
%% is_nil is an exact check against the 'nil' value, and should not be
%% treated as a simple type test.
+ Src = unpack_typed_arg(Src0),
assert_term(Src, Vst),
branch(Lbl, Vst,
fun(FailVst) ->
@@ -464,18 +491,28 @@ vi({test,is_nil,{f,Lbl},[Src]}, Vst) ->
fun(SuccVst) ->
update_eq_types(Src, nil, SuccVst)
end);
+vi({test,is_pid,{f,Lbl},[Src]}, Vst) ->
+ type_test(Lbl, pid, Src, Vst);
+vi({test,is_port,{f,Lbl},[Src]}, Vst) ->
+ type_test(Lbl, port, Src, Vst);
+vi({test,is_reference,{f,Lbl},[Src]}, Vst) ->
+ type_test(Lbl, reference, Src, Vst);
vi({test,test_arity,{f,Lbl},[Tuple,Sz]}, Vst) when is_integer(Sz) ->
assert_type(#t_tuple{}, Tuple, Vst),
Type = #t_tuple{exact=true,size=Sz},
type_test(Lbl, Type, Tuple, Vst);
-vi({test,is_tagged_tuple,{f,Lbl},[Src,Sz,Atom]}, Vst) ->
+vi({test,is_tagged_tuple,{f,Lbl},[Src0,Sz,Atom]}, Vst) ->
+ Src = unpack_typed_arg(Src0),
assert_term(Src, Vst),
Es = #{ 1 => get_literal_type(Atom) },
Type = #t_tuple{exact=true,size=Sz,elements=Es},
type_test(Lbl, Type, Src, Vst);
-vi({test,is_eq_exact,{f,Lbl},[Src,Val]=Ss}, Vst) ->
+vi({test,is_eq_exact,{f,Lbl},[Src0,Val0]}, Vst) ->
assert_no_exception(Lbl),
- validate_src(Ss, Vst),
+ Src = unpack_typed_arg(Src0),
+ assert_term(Src, Vst),
+ Val = unpack_typed_arg(Val0),
+ assert_term(Val, Vst),
branch(Lbl, Vst,
fun(FailVst) ->
update_ne_types(Src, Val, FailVst)
@@ -483,9 +520,12 @@ vi({test,is_eq_exact,{f,Lbl},[Src,Val]=Ss}, Vst) ->
fun(SuccVst) ->
update_eq_types(Src, Val, SuccVst)
end);
-vi({test,is_ne_exact,{f,Lbl},[Src,Val]=Ss}, Vst) ->
+vi({test,is_ne_exact,{f,Lbl},[Src0,Val0]}, Vst) ->
assert_no_exception(Lbl),
- validate_src(Ss, Vst),
+ Src = unpack_typed_arg(Src0),
+ assert_term(Src, Vst),
+ Val = unpack_typed_arg(Val0),
+ assert_term(Val, Vst),
branch(Lbl, Vst,
fun(FailVst) ->
update_eq_types(Src, Val, FailVst)
@@ -529,8 +569,14 @@ vi({get_tuple_element,Src,N,Dst}, Vst) ->
Index = N+1,
assert_not_literal(Src),
assert_type(#t_tuple{size=Index}, Src, Vst),
- #t_tuple{elements=Es} = normalize(get_term_type(Src, Vst)),
- Type = beam_types:get_tuple_element(Index, Es),
+
+ VRef = get_reg_vref(Src, Vst),
+ Type = fun(Vs) ->
+ #value{type=T} = map_get(VRef, Vs),
+ #t_tuple{elements=Es} = normalize(concrete_type(T, Vs)),
+ beam_types:get_tuple_element(Index, Es)
+ end,
+
extract_term(Type, {bif,element}, [{integer,Index}, Src], Dst, Vst);
%%
@@ -644,6 +690,33 @@ vi({call_last,Live,Func,N}, Vst) ->
validate_tail_call(N, Func, Live, Vst);
vi({call_ext_last,Live,Func,N}, Vst) ->
validate_tail_call(N, Func, Live, Vst);
+vi({call_fun2,{f,Lbl},Live,Fun0}, #vst{ft=Ft}=Vst) ->
+ %% Fun call with known target. Verify that the target exists, agrees with
+ %% the type annotation for `Fun`, and that it has environment variables.
+ %%
+ %% Direct fun calls without environment variables must be expressed as
+ %% local fun calls.
+ #{ name := Name, arity := TotalArity } = map_get(Lbl, Ft),
+ #tr{t=#t_fun{target={Name,TotalArity}},r=Fun} = Fun0, %Assertion.
+ true = Live < TotalArity, %Assertion.
+ assert_term(Fun, Vst),
+ validate_body_call('fun', Live, Vst);
+vi({call_fun2,Tag,Live,Fun0}, Vst) ->
+ Fun = unpack_typed_arg(Fun0),
+ assert_term(Fun, Vst),
+
+ case Tag of
+ {atom,safe} -> ok;
+ {atom,unsafe} -> ok;
+ _ -> error({invalid_tag,Tag})
+ end,
+
+ branch(?EXCEPTION_LABEL, Vst,
+ fun(SuccVst0) ->
+ SuccVst = update_type(fun meet/2, #t_fun{arity=Live},
+ Fun, SuccVst0),
+ validate_body_call('fun', Live, SuccVst)
+ end);
vi({call_fun,Live}, Vst) ->
Fun = {x,Live},
assert_term(Fun, Vst),
@@ -655,26 +728,30 @@ vi({call_fun,Live}, Vst) ->
validate_body_call('fun', Live+1, SuccVst)
end);
vi({make_fun2,{f,Lbl},_,_,NumFree}, #vst{ft=Ft}=Vst0) ->
- #{ arity := Arity0 } = map_get(Lbl, Ft),
- Arity = Arity0 - NumFree,
+ #{ name := Name, arity := TotalArity } = map_get(Lbl, Ft),
+ Arity = TotalArity - NumFree,
true = Arity >= 0, %Assertion.
Vst = prune_x_regs(NumFree, Vst0),
verify_call_args(make_fun, NumFree, Vst),
verify_y_init(Vst),
- Type = #t_fun{arity=Arity},
+
+ Type = #t_fun{target={Name,TotalArity},arity=Arity},
+
create_term(Type, make_fun, [], {x,0}, Vst);
vi({make_fun3,{f,Lbl},_,_,Dst,{list,Env}}, #vst{ft=Ft}=Vst0) ->
_ = [assert_term(E, Vst0) || E <- Env],
NumFree = length(Env),
- #{ arity := Arity0 } = map_get(Lbl, Ft),
- Arity = Arity0 - NumFree,
+ #{ name := Name, arity := TotalArity } = map_get(Lbl, Ft),
+ Arity = TotalArity - NumFree,
true = Arity >= 0, %Assertion.
Vst = eat_heap_fun(Vst0),
- Type = #t_fun{arity=Arity},
+
+ Type = #t_fun{target={Name,TotalArity},arity=Arity},
+
create_term(Type, make_fun, [], Dst, Vst);
vi(return, Vst) ->
assert_durable_term({x,0}, Vst),
@@ -684,7 +761,10 @@ vi(return, Vst) ->
%% BIF calls
%%
-vi({bif,Op,{f,Fail},Ss,Dst}, Vst0) ->
+vi({bif,Op,{f,Fail},Ss0,Dst0}, Vst0) ->
+ Ss = [unpack_typed_arg(Arg) || Arg <- Ss0],
+ Dst = unpack_typed_arg(Dst0),
+
case is_float_arith_bif(Op, Ss) of
true ->
?EXCEPTION_LABEL = Fail, %Assertion.
@@ -693,7 +773,10 @@ vi({bif,Op,{f,Fail},Ss,Dst}, Vst0) ->
validate_src(Ss, Vst0),
validate_bif(bif, Op, Fail, Ss, Dst, Vst0, Vst0)
end;
-vi({gc_bif,Op,{f,Fail},Live,Ss,Dst}, Vst0) ->
+vi({gc_bif,Op,{f,Fail},Live,Ss0,Dst0}, Vst0) ->
+ Ss = [unpack_typed_arg(Arg) || Arg <- Ss0],
+ Dst = unpack_typed_arg(Dst0),
+
validate_src(Ss, Vst0),
verify_live(Live, Vst0),
verify_y_init(Vst0),
@@ -822,7 +905,8 @@ vi(build_stacktrace, Vst0) ->
%% Map instructions.
%%
-vi({get_map_elements,{f,Fail},Src,{list,List}}, Vst) ->
+vi({get_map_elements,{f,Fail},Src0,{list,List}}, Vst) ->
+ Src = unpack_typed_arg(Src0),
verify_get_map(Fail, Src, List, Vst);
vi({put_map_assoc=Op,{f,Fail},Src,Dst,Live,{list,List}}, Vst) ->
verify_put_map(Op, Fail, Src, Dst, Live, List, Vst);
@@ -838,24 +922,22 @@ vi({bs_get_tail,Ctx,Dst,Live}, Vst0) ->
verify_live(Live, Vst0),
verify_y_init(Vst0),
- #t_bs_context{tail_unit=Unit} = get_raw_type(Ctx, Vst0),
+ #t_bs_context{tail_unit=Unit} = get_concrete_type(Ctx, Vst0),
Vst = prune_x_regs(Live, Vst0),
extract_term(#t_bitstring{size_unit=Unit}, bs_get_tail, [Ctx], Dst,
Vst, Vst0);
vi({bs_start_match4,Fail,Live,Src,Dst}, Vst) ->
- validate_bs_start_match(Fail, Live, 0, Src, Dst, Vst);
+ validate_bs_start_match(Fail, Live, Src, Dst, Vst);
vi({test,bs_start_match3,{f,_}=Fail,Live,[Src],Dst}, Vst) ->
- validate_bs_start_match(Fail, Live, 0, Src, Dst, Vst);
-vi({test,bs_start_match2,{f,_}=Fail,Live,[Src,Slots],Dst}, Vst) ->
- validate_bs_start_match(Fail, Live, Slots, Src, Dst, Vst);
+ validate_bs_start_match(Fail, Live, Src, Dst, Vst);
vi({test,bs_match_string,{f,Fail},[Ctx,Stride,{string,String}]}, Vst) ->
true = is_bitstring(String), %Assertion.
validate_bs_skip(Fail, Ctx, Stride, Vst);
vi({test,bs_skip_bits2,{f,Fail},[Ctx,Size,Unit,_Flags]}, Vst) ->
assert_term(Size, Vst),
- Stride = case get_raw_type(Size, Vst) of
+ Stride = case get_concrete_type(Size, Vst) of
#t_integer{elements={Same,Same}} -> Same * Unit;
_ -> Unit
end,
@@ -897,11 +979,18 @@ vi({test,bs_get_integer2=Op,{f,Fail},Live,
NumBits = Unit * Sz,
Stride = NumBits,
- Type = case member(unsigned, Flags) of
- true when 0 =< NumBits, NumBits =< 64 ->
- beam_types:make_integer(0, (1 bsl NumBits)-1);
- _ ->
- %% Signed integer, way too large, or negative size.
+ Type = if
+ 0 =< NumBits, NumBits =< 64 ->
+ Max = (1 bsl NumBits) - 1,
+ case member(unsigned, Flags) of
+ true ->
+ beam_types:make_integer(0, Max);
+ false ->
+ Min = -(Max + 1),
+ beam_types:make_integer(Min, Max)
+ end;
+ true ->
+ %% Way too large or negative size.
#t_integer{}
end,
@@ -920,26 +1009,22 @@ vi({test,bs_get_utf16=Op,{f,Fail},Live,[Ctx,_],Dst}, Vst) ->
vi({test,bs_get_utf32=Op,{f,Fail},Live,[Ctx,_],Dst}, Vst) ->
Type = beam_types:make_integer(0, ?UNICODE_MAX),
validate_bs_get(Op, Fail, Ctx, Live, 32, Type, Dst, Vst);
-vi({test,_Op,{f,Lbl},Src}, Vst) ->
- %% is_pid, is_reference, et cetera.
- validate_src(Src, Vst),
+vi({test,_Op,{f,Lbl},Ss}, Vst) ->
+ %% is_lt, is_gt, et cetera.
+ validate_src([unpack_typed_arg(Arg) || Arg <- Ss], Vst),
branch(Lbl, Vst);
%%
%% Bit syntax positioning
%%
-vi({bs_save2,Ctx,SavePoint}, Vst) ->
- bsm_save(Ctx, SavePoint, Vst);
-vi({bs_restore2,Ctx,SavePoint}, Vst) ->
- bsm_restore(Ctx, SavePoint, Vst);
vi({bs_get_position, Ctx, Dst, Live}, Vst0) ->
assert_type(#t_bs_context{}, Ctx, Vst0),
verify_live(Live, Vst0),
verify_y_init(Vst0),
- #t_bs_context{tail_unit=Unit} = get_raw_type(Ctx, Vst0),
+ #t_bs_context{tail_unit=Unit} = get_concrete_type(Ctx, Vst0),
Vst1 = prune_x_regs(Live, Vst0),
Vst = create_term(#t_abstract{kind={ms_position, Unit}},
@@ -950,7 +1035,7 @@ vi({bs_set_position, Ctx, Pos}, Vst0) ->
assert_type(#t_bs_context{}, Ctx, Vst0),
assert_type(#t_abstract{kind={ms_position,1}}, Pos, Vst0),
- #t_abstract{kind={ms_position,Unit}} = get_raw_type(Pos, Vst0),
+ #t_abstract{kind={ms_position,Unit}} = get_concrete_type(Pos, Vst0),
Vst = override_type(#t_bs_context{tail_unit=Unit}, Ctx, Vst0),
mark_current_ms_position(Ctx, Pos, Vst);
@@ -958,7 +1043,9 @@ vi({bs_set_position, Ctx, Pos}, Vst0) ->
%%
%% Floating-point instructions (excluding BIFs)
%%
-vi({fconv,Src,{fr,_}=Dst}, Vst) ->
+vi({fconv,Src0,{fr,_}=Dst}, Vst) ->
+ Src = unpack_typed_arg(Src0),
+
assert_term(Src, Vst),
branch(?EXCEPTION_LABEL, Vst,
fun(SuccVst0) ->
@@ -992,6 +1079,9 @@ vi(if_end, Vst) ->
vi({try_case_end,Src}, Vst) ->
assert_durable_term(Src, Vst),
branch(?EXCEPTION_LABEL, Vst, fun kill_state/1);
+vi({badrecord,Src}, Vst) ->
+ assert_durable_term(Src, Vst),
+ branch(?EXCEPTION_LABEL, Vst, fun kill_state/1);
vi(raw_raise=I, Vst0) ->
validate_body_call(I, 3, Vst0);
@@ -1001,6 +1091,22 @@ vi(raw_raise=I, Vst0) ->
vi(bs_init_writable=I, Vst) ->
validate_body_call(I, 1, Vst);
+vi({bs_create_bin,{f,Fail},Heap,Live,Unit,Dst,{list,List0}}, Vst0) ->
+ verify_live(Live, Vst0),
+ verify_y_init(Vst0),
+ List = [unpack_typed_arg(Arg) || Arg <- List0],
+ verify_create_bin_list(List, Vst0),
+ Vst = prune_x_regs(Live, Vst0),
+ branch(Fail, Vst,
+ fun(FailVst0) ->
+ heap_alloc(0, FailVst0)
+ end,
+ fun(SuccVst0) ->
+ SuccVst1 = update_create_bin_list(List, SuccVst0),
+ SuccVst = heap_alloc(Heap, SuccVst1),
+ create_term(#t_bitstring{size_unit=Unit}, bs_create_bin, [], Dst,
+ SuccVst)
+ end);
vi({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
verify_live(Live, Vst0),
verify_y_init(Vst0),
@@ -1139,12 +1245,12 @@ validate_tail_call(Deallocate, Func, Live, #vst{current=#st{numy=NumY}}=Vst0) ->
verify_live(Live, Vst0),
verify_call_args(Func, Live, Vst0),
- case will_call_succeed(Func, Vst0) of
+ case will_call_succeed(Func, Live, Vst0) of
yes when Deallocate =:= NumY ->
%% The call cannot fail; we don't need to handle exceptions
Vst = deallocate(Vst0),
verify_return(Vst);
- maybe when Deallocate =:= NumY ->
+ 'maybe' when Deallocate =:= NumY ->
%% The call may fail; make sure we update exception state
Vst = deallocate(Vst0),
branch(?EXCEPTION_LABEL, Vst, fun verify_return/1);
@@ -1174,10 +1280,10 @@ validate_body_call(Func, Live,
create_term(RetType, call, [], {x,0}, SuccVst)
end,
- case will_call_succeed(Func, Vst) of
+ case will_call_succeed(Func, Live, Vst) of
yes ->
SuccFun(Vst);
- maybe ->
+ 'maybe' ->
branch(?EXCEPTION_LABEL, Vst, SuccFun);
no ->
branch(?EXCEPTION_LABEL, Vst, fun kill_state/1)
@@ -1223,7 +1329,7 @@ verify_get_map(Fail, Src, List, Vst0) ->
fun(SuccVst) ->
Keys = extract_map_keys(List),
assert_unique_map_keys(Keys),
- extract_map_vals(List, Src, SuccVst, SuccVst)
+ extract_map_vals(List, Src, SuccVst)
end).
%% get_map_elements may leave its destinations in an inconsistent state when
@@ -1235,7 +1341,8 @@ verify_get_map(Fail, Src, List, Vst0) ->
%%
%% We must be careful to preserve the uninitialized status for Y registers
%% that have been allocated but not yet defined.
-clobber_map_vals([Key,Dst|T], Map, Vst0) ->
+clobber_map_vals([Key0, Dst | T], Map, Vst0) ->
+ Key = unpack_typed_arg(Key0),
case is_reg_initialized(Dst, Vst0) of
true ->
Vst = extract_term(any, {bif,map_get}, [Key, Map], Dst, Vst0),
@@ -1257,20 +1364,35 @@ is_reg_initialized({y,_}=Reg, #vst{current=#st{ys=Ys}}) ->
end;
is_reg_initialized(V, #vst{}) -> error({not_a_register, V}).
-extract_map_keys([Key,_Val|T]) ->
- [Key|extract_map_keys(T)];
-extract_map_keys([]) -> [].
-
-extract_map_vals([Key, Dst | Vs], Map, Vst0, Vsti0) ->
- assert_term(Key, Vst0),
- case bif_types(map_get, [Key, Map], Vst0) of
- {none, _, _} ->
- kill_state(Vsti0);
- {DstType, _, _} ->
- Vsti = extract_term(DstType, {bif,map_get}, [Key, Map], Dst, Vsti0),
- extract_map_vals(Vs, Map, Vst0, Vsti)
+extract_map_keys([Key,_Val | T]) ->
+ [unpack_typed_arg(Key) | extract_map_keys(T)];
+extract_map_keys([]) ->
+ [].
+
+
+extract_map_vals(List, Src, SuccVst) ->
+ Seen = sets:new([{version, 2}]),
+ extract_map_vals(List, Src, Seen, SuccVst, SuccVst).
+
+extract_map_vals([Key0, Dst | Vs], Map, Seen0, Vst0, Vsti0) ->
+ case sets:is_element(Dst, Seen0) of
+ true ->
+ %% The destinations must not overwrite each other.
+ error(conflicting_destinations);
+ false ->
+ Key = unpack_typed_arg(Key0),
+ assert_term(Key, Vst0),
+ case bif_types(map_get, [Key, Map], Vst0) of
+ {none, _, _} ->
+ kill_state(Vsti0);
+ {DstType, _, _} ->
+ Vsti = extract_term(DstType, {bif,map_get},
+ [Key, Map], Dst, Vsti0),
+ Seen = sets:add_element(Dst, Seen0),
+ extract_map_vals(Vs, Map, Seen, Vst0, Vsti)
+ end
end;
-extract_map_vals([], _Map, _Vst0, Vst) ->
+extract_map_vals([], _Map, _Seen, _Vst0, Vst) ->
Vst.
verify_put_map(Op, Fail, Src, Dst, Live, List, Vst0) ->
@@ -1311,6 +1433,54 @@ pmt_1([Key0, Value0 | List], Vst, Acc0) ->
pmt_1([], _Vst, Acc) ->
Acc.
+verify_create_bin_list([{atom,string},_Seg,Unit,Flags,Val,Size|Args], Vst) ->
+ assert_bs_unit({atom,string}, Unit),
+ assert_term(Flags, Vst),
+ case Val of
+ {string,Bs} when is_binary(Bs) -> ok;
+ _ -> error({not_string,Val})
+ end,
+ assert_term(Flags, Vst),
+ assert_term(Size, Vst),
+ verify_create_bin_list(Args, Vst);
+verify_create_bin_list([Type,_Seg,Unit,Flags,Val,Size|Args], Vst) ->
+ assert_term(Type, Vst),
+ assert_bs_unit(Type, Unit),
+ assert_term(Flags, Vst),
+ assert_term(Val, Vst),
+ assert_term(Size, Vst),
+ verify_create_bin_list(Args, Vst);
+verify_create_bin_list([], _Vst) -> ok.
+
+update_create_bin_list([{atom,string},_Seg,_Unit,_Flags,_Val,_Size|T], Vst) ->
+ update_create_bin_list(T, Vst);
+update_create_bin_list([{atom,Op},_Seg,_Unit,_Flags,Val,_Size|T], Vst0) ->
+ Type = update_create_bin_type(Op),
+ Vst = update_type(fun meet/2, Type, Val, Vst0),
+ update_create_bin_list(T, Vst);
+update_create_bin_list([], Vst) -> Vst.
+
+update_create_bin_type(append) -> #t_bitstring{};
+update_create_bin_type(private_append) -> #t_bitstring{};
+update_create_bin_type(binary) -> #t_bitstring{};
+update_create_bin_type(float) -> #t_float{};
+update_create_bin_type(integer) -> #t_integer{};
+update_create_bin_type(utf8) -> #t_integer{};
+update_create_bin_type(utf16) -> #t_integer{};
+update_create_bin_type(utf32) -> #t_integer{}.
+
+assert_bs_unit({atom,Type}, 0) ->
+ case Type of
+ utf8 -> ok;
+ utf16 -> ok;
+ utf32 -> ok;
+ _ -> error({zero_unit_invalid_for_type,Type})
+ end;
+assert_bs_unit({atom,_Type}, Unit) when is_integer(Unit), 0 < Unit, Unit =< 256 ->
+ ok;
+assert_bs_unit(_, Unit) ->
+ error({invalid,Unit}).
+
%%
%% Common code for validating returns, whether naked or as part of a tail call.
%%
@@ -1342,7 +1512,7 @@ validate_bif(Kind, Op, Fail, Ss, Dst, OrigVst, Vst) ->
%% This BIF always fails; jump directly to the fail block or
%% exception handler.
branch(Fail, Vst, fun kill_state/1);
- maybe ->
+ 'maybe' ->
validate_bif_1(Kind, Op, Fail, Ss, Dst, OrigVst, Vst)
end.
@@ -1388,14 +1558,14 @@ validate_bif_1(Kind, Op, Fail, Ss, Dst, OrigVst, Vst) ->
%% Common code for validating bs_start_match* instructions.
%%
-validate_bs_start_match({atom,resume}, Live, 0, Src, Dst, Vst0) ->
+validate_bs_start_match({atom,resume}, Live, Src, Dst, Vst0) ->
assert_type(#t_bs_context{}, Src, Vst0),
verify_live(Live, Vst0),
verify_y_init(Vst0),
Vst = assign(Src, Dst, Vst0),
prune_x_regs(Live, Vst);
-validate_bs_start_match({atom,no_fail}, Live, Slots, Src, Dst, Vst0) ->
+validate_bs_start_match({atom,no_fail}, Live, Src, Dst, Vst0) ->
verify_live(Live, Vst0),
verify_y_init(Vst0),
@@ -1405,11 +1575,10 @@ validate_bs_start_match({atom,no_fail}, Live, Slots, Src, Dst, Vst0) ->
SrcType = get_movable_term_type(Src, Vst1),
TailUnit = beam_types:get_bs_matchable_unit(SrcType),
- CtxType = #t_bs_context{slots=Slots,tail_unit=TailUnit},
-
Vst = prune_x_regs(Live, Vst1),
- extract_term(CtxType, bs_start_match, [Src], Dst, Vst, Vst0);
-validate_bs_start_match({f,Fail}, Live, Slots, Src, Dst, Vst) ->
+ extract_term(#t_bs_context{tail_unit=TailUnit}, bs_start_match,
+ [Src], Dst, Vst, Vst0);
+validate_bs_start_match({f,Fail}, Live, Src, Dst, Vst) ->
assert_no_exception(Fail),
branch(Fail, Vst,
@@ -1417,14 +1586,16 @@ validate_bs_start_match({f,Fail}, Live, Slots, Src, Dst, Vst) ->
update_type(fun subtract/2, #t_bs_matchable{}, Src, FailVst)
end,
fun(SuccVst) ->
- validate_bs_start_match({atom,no_fail}, Live, Slots,
+ validate_bs_start_match({atom,no_fail}, Live,
Src, Dst, SuccVst)
end).
%%
%% Common code for validating bs_get* instructions.
%%
-validate_bs_get(Op, Fail, Ctx, Live, Stride, Type, Dst, Vst) ->
+validate_bs_get(Op, Fail, Ctx0, Live, Stride, Type, Dst, Vst) ->
+ Ctx = unpack_typed_arg(Ctx0),
+
assert_no_exception(Fail),
assert_type(#t_bs_context{}, Ctx, Vst),
@@ -1438,7 +1609,9 @@ validate_bs_get(Op, Fail, Ctx, Live, Stride, Type, Dst, Vst) ->
extract_term(Type, Op, [Ctx], Dst, SuccVst, SuccVst0)
end).
-validate_bs_get_all(Op, Fail, Ctx, Live, Stride, Type, Dst, Vst) ->
+validate_bs_get_all(Op, Fail, Ctx0, Live, Stride, Type, Dst, Vst) ->
+ Ctx = unpack_typed_arg(Ctx0),
+
assert_no_exception(Fail),
assert_type(#t_bs_context{}, Ctx, Vst),
@@ -1492,11 +1665,7 @@ advance_bs_context(_Ctx, Stride, _Vst) when Stride < 0 ->
%% We _KNOW_ we'll fail at runtime.
throw({invalid_argument, {negative_stride, Stride}});
advance_bs_context(Ctx, Stride, Vst0) ->
- %% slots/valid must remain untouched to support +r21.
- CtxType0 = get_raw_type(Ctx, Vst0),
- CtxType = CtxType0#t_bs_context{ tail_unit=Stride },
-
- Vst = update_type(fun join/2, CtxType, Ctx, Vst0),
+ Vst = update_type(fun join/2, #t_bs_context{tail_unit=Stride}, Ctx, Vst0),
%% The latest saved position (if any) is no longer current, make sure
%% it isn't updated on the next match operation.
@@ -1541,7 +1710,9 @@ invalidate_current_ms_position(Ctx, #vst{current=St0}=Vst) ->
%%
%% Common code for is_$type instructions.
%%
-type_test(Fail, Type, Reg, Vst) ->
+type_test(Fail, Type, Reg0, Vst) ->
+ Reg = unpack_typed_arg(Reg0),
+
assert_term(Reg, Vst),
assert_no_exception(Fail),
branch(Fail, Vst,
@@ -1749,10 +1920,10 @@ schedule_out(Live, Vst0) when is_integer(Live) ->
prune_x_regs(Live, #vst{current=St0}=Vst) when is_integer(Live) ->
#st{fragile=Fragile0,xs=Xs0} = St0,
Fragile = sets:filter(fun({x,X}) ->
- X < Live;
- ({y,_}) ->
- true
- end, Fragile0),
+ X < Live;
+ ({y,_}) ->
+ true
+ end, Fragile0),
Xs = maps:filter(fun({x,X}, _) ->
X < Live
end, Xs0),
@@ -1839,43 +2010,8 @@ assert_unique_map_keys([_,_|_]=Ls) ->
L
end || L <- Ls],
case length(Vs) =:= sets:size(sets:from_list(Vs, [{version, 2}])) of
- true -> ok;
- false -> error(keys_not_unique)
- end.
-
-%%%
-%%% New binary matching instructions.
-%%%
-
-bsm_save(Reg, {atom,start}, Vst) ->
- %% Save point refering to where the match started.
- %% It is always valid. But don't forget to validate the context register.
- assert_type(#t_bs_context{}, Reg, Vst),
- Vst;
-bsm_save(Reg, SavePoint, Vst) ->
- case get_movable_term_type(Reg, Vst) of
- #t_bs_context{valid=Bits,slots=Slots}=Ctxt0 when SavePoint < Slots ->
- Ctx = Ctxt0#t_bs_context{valid=Bits bor (1 bsl SavePoint),
- slots=Slots},
- override_type(Ctx, Reg, Vst);
- _ ->
- error({illegal_save, SavePoint})
- end.
-
-bsm_restore(Reg, {atom,start}, Vst) ->
- %% (Mostly) automatic save point refering to where the match started.
- %% It is always valid. But don't forget to validate the context register.
- assert_type(#t_bs_context{}, Reg, Vst),
- Vst;
-bsm_restore(Reg, SavePoint, Vst) ->
- case get_movable_term_type(Reg, Vst) of
- #t_bs_context{valid=Bits,slots=Slots} when SavePoint < Slots ->
- case Bits band (1 bsl SavePoint) of
- 0 -> error({illegal_restore, SavePoint, not_set});
- _ -> Vst
- end;
- _ ->
- error({illegal_restore, SavePoint, range})
+ true -> ok;
+ false -> error(keys_not_unique)
end.
bsm_stride({integer, Size}, Unit) ->
@@ -1963,9 +2099,9 @@ infer_types_1(#value{op={bif,'=:='},args=[LHS,RHS]}, Val, Op, Vst) ->
end;
infer_types_1(#value{op={bif,'=/='},args=[LHS,RHS]}, Val, Op, Vst) ->
case Val of
- {atom, Bool} when Op =:= ne_exact, Bool; Op =:= eq_exact, not Bool ->
- update_ne_types(LHS, RHS, Vst);
{atom, Bool} when Op =:= eq_exact, Bool; Op =:= ne_exact, not Bool ->
+ update_ne_types(LHS, RHS, Vst);
+ {atom, Bool} when Op =:= ne_exact, Bool; Op =:= eq_exact, not Bool ->
update_eq_types(LHS, RHS, Vst);
_ ->
Vst
@@ -1980,6 +2116,22 @@ infer_types_1(#value{op={bif,is_bitstring},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_bitstring{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_float},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_float{}, Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_function},args=[Src,{integer,Arity}]},
+ Val, Op, Vst)
+ when Arity >= 0, Arity =< ?MAX_FUNC_ARGS ->
+ infer_type_test_bif(#t_fun{arity=Arity}, Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_function},args=[Src,_Arity]}, Val, Op, Vst) ->
+ case Val of
+ {atom, Bool} when Op =:= eq_exact, Bool; Op =:= ne_exact, not Bool ->
+ update_type(fun meet/2, #t_fun{}, Src, Vst);
+ _ ->
+ %% We cannot subtract the function type when the arity is unknown:
+ %% `Src` may still be a function if the arity is outside the
+ %% allowed range.
+ Vst
+ end;
+infer_types_1(#value{op={bif,is_function},args=[Src]}, Val, Op, Vst) ->
+ infer_type_test_bif(#t_fun{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_integer},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_integer{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_list},args=[Src]}, Val, Op, Vst) ->
@@ -1988,6 +2140,12 @@ infer_types_1(#value{op={bif,is_map},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_map{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_number},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(number, Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_pid},args=[Src]}, Val, Op, Vst) ->
+ infer_type_test_bif(pid, Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_port},args=[Src]}, Val, Op, Vst) ->
+ infer_type_test_bif(port, Src, Val, Op, Vst);
+infer_types_1(#value{op={bif,is_reference},args=[Src]}, Val, Op, Vst) ->
+ infer_type_test_bif(reference, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,is_tuple},args=[Src]}, Val, Op, Vst) ->
infer_type_test_bif(#t_tuple{}, Src, Val, Op, Vst);
infer_types_1(#value{op={bif,tuple_size}, args=[Tuple]},
@@ -2137,10 +2295,12 @@ update_type(Merge, With, #value_ref{}=Ref, Vst0) ->
%% We therefore throw a 'type_conflict' error instead, which causes
%% validation to fail unless we're in a context where such errors can be
%% handled, such as in a branch handler.
- Current = get_raw_type(Ref, Vst0),
+ Current = get_concrete_type(Ref, Vst0),
case Merge(Current, With) of
none ->
throw({type_conflict, Current, With});
+ Current ->
+ Vst0;
Type ->
Vst = update_container_type(Type, Ref, Vst0),
set_type(Type, Ref, Vst)
@@ -2390,6 +2550,17 @@ validate_src(Ss, Vst) when is_list(Ss) ->
_ = [assert_term(S, Vst) || S <- Ss],
ok.
+unpack_typed_arg(#tr{r=Reg}) ->
+ Reg;
+unpack_typed_arg(Arg) ->
+ Arg.
+
+%% get_term_type(Src, ValidatorState) -> Type
+%% Gets the type of the source Src, resolving deferred types into
+%% a concrete type.
+get_concrete_type(Src, #vst{current=#st{vs=Vs}}=Vst) ->
+ concrete_type(get_raw_type(Src, Vst), Vs).
+
%% get_term_type(Src, ValidatorState) -> Type
%% Get the type of the source Src. The returned type Type will be
%% a standard Erlang type (no catch/try tags or match contexts).
@@ -2406,7 +2577,7 @@ get_term_type(Src, Vst) ->
%% a standard Erlang type (no catch/try tags). Match contexts are OK.
get_movable_term_type(Src, Vst) ->
- case get_raw_type(Src, Vst) of
+ case get_concrete_type(Src, Vst) of
#t_abstract{kind=unfinished_tuple=Kind} -> error({Kind,Src});
initialized -> error({unassigned,Src});
uninitialized -> error({uninitialized_reg,Src});
@@ -2677,24 +2848,31 @@ merge_values(Merge, VsA, VsB) ->
mv_1(Same, Same, VsA, VsB, Acc0) ->
%% We're merging different versions of the same value, so it's safe to
%% reuse old entries if the type's unchanged.
- #value{type=TypeA,args=Args}=EntryA = map_get(Same, VsA),
- #value{type=TypeB,args=Args}=EntryB = map_get(Same, VsB),
-
- Entry = case join(TypeA, TypeB) of
- TypeA -> EntryA;
- TypeB -> EntryB;
- JoinedType -> EntryA#value{type=JoinedType}
+ Entry = case {VsA, VsB} of
+ {#{ Same := Entry0 }, #{ Same := Entry0 } } ->
+ Entry0;
+ {#{ Same := #value{type=TypeA}=Entry0 },
+ #{ Same := #value{type=TypeB} } } ->
+ ConcreteA = concrete_type(TypeA, VsA),
+ ConcreteB = concrete_type(TypeB, VsB),
+ Entry0#value{type=join(ConcreteA, ConcreteB)}
end,
Acc = Acc0#{ Same => Entry },
%% Type inference may depend on values that are no longer reachable from a
%% register, so all arguments must be merged into the new state.
- mv_args(Args, VsA, VsB, Acc);
+ mv_args(Entry#value.args, VsA, VsB, Acc);
mv_1({RefA, RefB}, New, VsA, VsB, Acc) ->
#value{type=TypeA} = map_get(RefA, VsA),
#value{type=TypeB} = map_get(RefB, VsB),
- Acc#{ New => #value{op=join,args=[],type=join(TypeA, TypeB)} }.
+
+ ConcreteA = concrete_type(TypeA, VsA),
+ ConcreteB = concrete_type(TypeB, VsB),
+ Acc#{ New => #value{op=join,args=[],type=join(ConcreteA, ConcreteB)} }.
+
+concrete_type(T, Vs) when is_function(T) -> T(Vs);
+concrete_type(T, _Vs) -> T.
mv_args([#value_ref{}=Arg | Args], VsA, VsB, Acc0) ->
case Acc0 of
@@ -2930,7 +3108,28 @@ assert_not_fragile(Lit, #vst{}) ->
bif_types(Op, Ss, Vst) ->
Args = [normalize(get_term_type(Arg, Vst)) || Arg <- Ss],
- beam_call_types:types(erlang, Op, Args).
+ case {Op,Ss} of
+ {element,[_,{literal,Tuple}]} when tuple_size(Tuple) > 0 ->
+ case beam_call_types:types(erlang, Op, Args) of
+ {any,ArgTypes,Safe} ->
+ RetType = join_tuple_elements(Tuple),
+ {RetType,ArgTypes,Safe};
+ Other ->
+ Other
+ end;
+ {_,_} ->
+ beam_call_types:types(erlang, Op, Args)
+ end.
+
+join_tuple_elements(Tuple) ->
+ join_tuple_elements(tuple_size(Tuple), Tuple, none).
+
+join_tuple_elements(0, _Tuple, Type) ->
+ Type;
+join_tuple_elements(I, Tuple, Type0) ->
+ Type1 = beam_types:make_type_from_value(element(I, Tuple)),
+ Type = beam_types:join(Type0, Type1),
+ join_tuple_elements(I - 1, Tuple, Type).
call_types({extfunc,M,F,A}, A, Vst) ->
Args = get_call_args(A, Vst),
@@ -2945,20 +3144,36 @@ will_bif_succeed(raise, [_,_], _Vst) ->
will_bif_succeed(Op, Ss, Vst) ->
case is_float_arith_bif(Op, Ss) of
true ->
- maybe;
+ 'maybe';
false ->
Args = [normalize(get_term_type(Arg, Vst)) || Arg <- Ss],
beam_call_types:will_succeed(erlang, Op, Args)
end.
-will_call_succeed({extfunc,M,F,A}, Vst) ->
+will_call_succeed({extfunc,M,F,A}, _Live, Vst) ->
beam_call_types:will_succeed(M, F, get_call_args(A, Vst));
-will_call_succeed(bs_init_writable, _Vst) ->
+will_call_succeed(bs_init_writable, _Live, _Vst) ->
yes;
-will_call_succeed(raw_raise, _Vst) ->
+will_call_succeed(raw_raise, _Live, _Vst) ->
no;
-will_call_succeed(_Call, _Vst) ->
- maybe.
+will_call_succeed({f,Lbl}, _Live, #vst{ft=Ft}) ->
+ case Ft of
+ #{Lbl := #{always_fails := true}} ->
+ no;
+ #{} ->
+ 'maybe'
+ end;
+will_call_succeed(apply, Live, Vst) ->
+ Mod = get_term_type({x,Live-2}, Vst),
+ Name = get_term_type({x,Live-1}, Vst),
+ case {Mod,Name} of
+ {#t_atom{},#t_atom{}} ->
+ 'maybe';
+ {_,_} ->
+ no
+ end;
+will_call_succeed(_Call, _Live, _Vst) ->
+ 'maybe'.
get_call_args(Arity, Vst) ->
get_call_args_1(0, Arity, Vst).
diff --git a/lib/compiler/src/beam_z.erl b/lib/compiler/src/beam_z.erl
index 9f467676e5..852000aa3a 100644
--- a/lib/compiler/src/beam_z.erl
+++ b/lib/compiler/src/beam_z.erl
@@ -24,23 +24,21 @@
-export([module/2]).
--import(lists, [dropwhile/2,map/2,sort/1]).
+-import(lists, [dropwhile/2,sort/1]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_asm:module_code()}.
module({Mod,Exp,Attr,Fs0,Lc}, Opts) ->
- NoGetHdTl = proplists:get_bool(no_get_hd_tl, Opts),
NoInitYregs = proplists:get_bool(no_init_yregs, Opts),
- Fs = [function(F, NoGetHdTl, NoInitYregs) || F <- Fs0],
+ Fs = [function(F, NoInitYregs) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is0}, NoGetHdTl, NoInitYregs) ->
+function({function,Name,Arity,CLabel,Is0}, NoInitYregs) ->
try
Is1 = undo_renames(Is0),
- Is2 = maybe_eliminate_get_hd_tl(Is1, NoGetHdTl),
- Is3 = maybe_eliminate_init_yregs(Is2, NoInitYregs),
- Is = remove_redundant_lines(Is3),
+ Is2 = maybe_eliminate_init_yregs(Is1, NoInitYregs),
+ Is = remove_redundant_lines(Is2),
{function,Name,Arity,CLabel,Is}
catch
Class:Error:Stack ->
@@ -89,32 +87,6 @@ undo_renames([{get_hd,Src,Hd},{get_tl,Src,Tl}|Is]) ->
get_list(Src, Hd, Tl, Is);
undo_renames([{get_tl,Src,Tl},{get_hd,Src,Hd}|Is]) ->
get_list(Src, Hd, Tl, Is);
-undo_renames([{bs_put,_,{bs_put_binary,1,_},
- [{atom,all},{literal,<<>>}]}|Is]) ->
- undo_renames(Is);
-undo_renames([{bs_put,Fail,{bs_put_binary,1,_Flags},
- [{atom,all},{literal,BinString}]}|Is0])
- when is_bitstring(BinString)->
- Bits = bit_size(BinString),
- Bytes = Bits div 8,
- case Bits rem 8 of
- 0 ->
- I = {bs_put_string,byte_size(BinString),
- {string,BinString}},
- [undo_rename(I)|undo_renames(Is0)];
- Rem ->
- <<Binary:Bytes/bytes,Int:Rem>> = BinString,
- PutInt = {bs_put_integer,Fail,{integer,Rem},1,
- {field_flags,[unsigned,big]},{integer,Int}},
- Is = [PutInt|undo_renames(Is0)],
- case Binary of
- <<>> ->
- Is;
- _ ->
- [{bs_put_string,byte_size(Binary),
- {string,Binary}}|Is]
- end
- end;
undo_renames([I|Is]) ->
[undo_rename(I)|undo_renames(Is)];
undo_renames([]) -> [].
@@ -162,20 +134,6 @@ undo_rename({select,I,Reg,Fail,List}) ->
undo_rename(I) -> I.
%%%
-%%% Eliminate get_hd/get_tl instructions if requested by
-%%% the no_get_hd_tl option.
-%%%
-
-maybe_eliminate_get_hd_tl(Is, true) ->
- map(fun({get_hd,Cons,Hd}) ->
- {get_list,Cons,Hd,{x,1022}};
- ({get_tl,Cons,Tl}) ->
- {get_list,Cons,{x,1022},Tl};
- (I) -> I
- end, Is);
-maybe_eliminate_get_hd_tl(Is, false) -> Is.
-
-%%%
%%% Eliminate the init_yreg/1 instruction if requested by
%%% the no_init_yregs option.
%%%
diff --git a/lib/compiler/src/cerl_inline.erl b/lib/compiler/src/cerl_inline.erl
index 3f3d162302..54b56d2449 100644
--- a/lib/compiler/src/cerl_inline.erl
+++ b/lib/compiler/src/cerl_inline.erl
@@ -615,7 +615,7 @@ i_case(E, Ctxt, Ren, Env, S) ->
%% the arguments of the application to be evaluated *after* the
%% switch expression, but *before* the body of the selected clause.
%% Such interleaving is not allowed in general, and it does not seem
- %% worthwile to make a more powerful transformation here. Therefore,
+ %% worthwhile to make a more powerful transformation here. Therefore,
%% the clause bodies are conservatively visited for value if the
%% context is `application'.
Ctxt1 = safe_context(Ctxt),
@@ -967,7 +967,7 @@ i_letrec(Es, B, Xs, Ctxt, Ren, Env, NoInline, S) ->
%% Finally, we create new letrec-bindings for any and all
%% residualised definitions. All referenced functions should have
- %% been visited; the call to `visit' below is expected to retreive a
+ %% been visited; the call to `visit' below is expected to retrieve a
%% cached expression.
Rs1 = keep_referenced(Rs, S4),
{Es1, S5} = mapfoldl(fun (R, S) ->
@@ -1013,7 +1013,7 @@ i_apply(E, Ctxt, Ren, Env, S) ->
%% location could be recycled after the flag has been tested, but
%% there is no real advantage to that, because in practice, only
%% 4-5% of all created store locations will ever be reused, while
- %% there will be a noticable overhead for managing the free list.)
+ %% there will be a noticeable overhead for managing the free list.)
case st__get_app_inlined(L, S3) of
true ->
%% The application was inlined, so we have the final
@@ -1124,7 +1124,7 @@ i_call_2(M, F, As, E, S) ->
%% to rewrite the expression.
i_call_3(M, F, As, E, Ctxt, Env, S) ->
- %% Note that we extract the results of argument expessions here; the
+ %% Note that we extract the results of argument expressions here; the
%% expressions could still be sequences with side effects.
Vs = [concrete(result(A)) || A <- As],
try apply(atom_val(M), atom_val(F), Vs) of
@@ -2096,7 +2096,7 @@ residualize_operand(Opnd, E, S) ->
case st__get_opnd_effect(Opnd#opnd.loc, S) of
true ->
%% The operand has not been visited, so we do that now, but
- %% in `effect' context. (Waddell's algoritm does some stuff
+ %% in `effect' context. (Waddell's algorithm does some stuff
%% here to account specially for the operand size, which
%% appears unnecessary.)
{E1, S1} = i(Opnd#opnd.expr, effect, Opnd#opnd.ren,
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 4fc24c43d7..7ef37a6082 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,9 +49,7 @@
-type abstract_code() :: [erl_parse:abstract_form()].
-%% Internal representations used for 'from_asm' compilation can also be valid,
-%% but have no relevant types defined.
--type forms() :: abstract_code() | cerl:c_module().
+-type forms() :: abstract_code() | cerl:c_module() | beam_disasm:asm_form().
-type option() :: atom() | {atom(), term()} | {'d', atom(), term()}.
@@ -264,25 +262,19 @@ expand_opt(report, Os) ->
[report_errors,report_warnings|Os];
expand_opt(return, Os) ->
[return_errors,return_warnings|Os];
-expand_opt(no_bsm3, Os) ->
- %% The new bsm pass requires bsm3 instructions.
- [no_bsm3,no_bsm_opt|expand_opt(no_bsm4, Os)];
expand_opt(no_bsm4, Os) ->
%% bsm4 instructions are only used when type optimization has determined
%% that a match instruction won't fail.
expand_opt(no_type_opt, Os);
-expand_opt(r18, Os) ->
- expand_opt_before_21(Os);
-expand_opt(r19, Os) ->
- expand_opt_before_21(Os);
-expand_opt(r20, Os) ->
- expand_opt_before_21(Os);
-expand_opt(r21, Os) ->
- expand_opt(r22, [no_put_tuple2 | expand_opt(no_bsm3, Os)]);
expand_opt(r22, Os) ->
- expand_opt(r23, [no_shared_fun_wrappers, no_swap | expand_opt(no_bsm4, Os)]);
+ expand_opt(r23, [no_bs_create_bin, no_shared_fun_wrappers,
+ no_swap | expand_opt(no_bsm4, Os)]);
expand_opt(r23, Os) ->
- expand_opt(no_make_fun3, [no_ssa_opt_float, no_recv_opt, no_init_yregs | Os]);
+ expand_opt(no_make_fun3, [no_bs_create_bin, no_ssa_opt_float,
+ no_recv_opt, no_init_yregs |
+ expand_opt(r24, Os)]);
+expand_opt(r24, Os) ->
+ expand_opt(no_type_opt, [no_bs_create_bin, no_ssa_opt_ranges | Os]);
expand_opt(no_make_fun3, Os) ->
[no_make_fun3, no_fun_opt | Os];
expand_opt({debug_info_key,_}=O, Os) ->
@@ -298,15 +290,10 @@ expand_opt(no_module_opt=O, Os) ->
[O,no_recv_opt | Os];
expand_opt(O, Os) -> [O|Os].
-expand_opt_before_21(Os) ->
- [no_init_yregs, no_make_fun3, no_fun_opt,
- no_shared_fun_wrappers, no_swap,
- no_put_tuple2, no_get_hd_tl, no_ssa_opt_record,
- no_utf8_atoms, no_recv_opt | expand_opt(no_bsm3, Os)].
-
-
-spec format_error(error_description()) -> iolist().
+format_error({obsolete_option,Ver}) ->
+ io_lib:fwrite("the ~p option is no longer supported", [Ver]);
format_error(no_crypto) ->
"this system is not configured with crypto support.";
format_error(bad_crypto_key) ->
@@ -817,6 +804,7 @@ abstr_passes(AbstrStatus) ->
?pass(expand_records),
{iff,'dexp',{listing,"expand"}},
+ {iff,'E',?pass(legalize_vars)},
{iff,'E',{src_listing,"E"}},
{iff,'to_exp',{done,"E"}},
@@ -885,10 +873,6 @@ kernel_passes() ->
{iff,dssabsm,{listing,"ssabsm"}},
{unless,no_bsm_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
- {unless,no_fun_opt,{pass,beam_ssa_funs}},
- {iff,dssafuns,{listing,"ssafuns"}},
- {unless,no_fun_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
-
{unless,no_ssa_opt,{pass,beam_ssa_opt}},
{iff,dssaopt,{listing,"ssaopt"}},
{unless,no_ssa_opt,{iff,ssalint,{pass,beam_ssa_lint}}},
@@ -916,8 +900,6 @@ asm_passes() ->
{iff,dblk,{listing,"block"}},
{unless,no_jopt,{pass,beam_jump}},
{iff,djmp,{listing,"jump"}},
- {unless,no_peep_opt,{pass,beam_peep}},
- {iff,dpeep,{listing,"peep"}},
{pass,beam_clean},
{iff,dclean,{listing,"clean"}},
{unless,no_stack_trimming,{pass,beam_trim}},
@@ -1019,8 +1001,13 @@ parse_module(_Code, St) ->
do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
SourceName0 = proplists:get_value(source, Opts, File),
SourceName = case member(deterministic, Opts) of
- true -> filename:basename(SourceName0);
- false -> SourceName0
+ true ->
+ filename:basename(SourceName0);
+ false ->
+ case member(absolute_source, Opts) of
+ true -> paranoid_absname(SourceName0);
+ false -> SourceName0
+ end
end,
StartLocation = case with_columns(Opts) of
true ->
@@ -1028,28 +1015,66 @@ do_parse_module(DefEncoding, #compile{ifile=File,options=Opts,dir=Dir}=St) ->
false ->
1
end,
- R = epp:parse_file(File,
- [{includes,[".",Dir|inc_paths(Opts)]},
- {source_name, SourceName},
- {macros,pre_defs(Opts)},
- {default_encoding,DefEncoding},
- {location,StartLocation},
- extra]),
- case R of
- {ok,Forms0,Extra} ->
- Encoding = proplists:get_value(encoding, Extra),
- Forms = case with_columns(Opts ++ compile_options(Forms0)) of
- true ->
- Forms0;
- false ->
- strip_columns(Forms0)
- end,
- {ok,Forms,St#compile{encoding=Encoding}};
- {error,E} ->
- Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
- {error,St#compile{errors=St#compile.errors ++ Es}}
+ case erl_features:keyword_fun(Opts, fun erl_scan:f_reserved_word/1) of
+ {ok, {Features, ResWordFun}} ->
+ R = epp:parse_file(File,
+ [{includes,[".",Dir|inc_paths(Opts)]},
+ {source_name, SourceName},
+ {deterministic, member(deterministic, Opts)},
+ {macros,pre_defs(Opts)},
+ {default_encoding,DefEncoding},
+ {location,StartLocation},
+ {reserved_word_fun, ResWordFun},
+ {features, Features},
+ extra]),
+ case R of
+ %% FIXME Extra should include used features as well
+ {ok,Forms0,Extra} ->
+ Encoding = proplists:get_value(encoding, Extra),
+ %% Get features used in the module, indicated by
+ %% enabling features with
+ %% -compile({feature, .., enable}).
+ UsedFtrs = proplists:get_value(features, Extra),
+ St1 = metadata_add_features(UsedFtrs, St),
+ Forms = case with_columns(Opts ++ compile_options(Forms0)) of
+ true ->
+ Forms0;
+ false ->
+ strip_columns(Forms0)
+ end,
+ {ok,Forms,St1#compile{encoding=Encoding}};
+ {error,E} ->
+ Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
+ {error,St#compile{errors=St#compile.errors ++ Es}}
+ end;
+ {error, {Mod, Reason}} ->
+ Es = [{St#compile.ifile,[{none, Mod, Reason}]}],
+ {error, St#compile{errors = St#compile.errors ++ Es}}
end.
+%% The atom to be used in the proplist of the meta chunk indicating
+%% the features used when compiling the module.
+-define(META_USED_FEATURES, enabled_features).
+-define(META_CHUNK_NAME, <<"Meta">>).
+
+metadata_add_features(Ftrs, #compile{extra_chunks = Extra} = St) ->
+ MetaData =
+ case proplists:get_value(?META_CHUNK_NAME, Extra) of
+ undefined ->
+ [];
+ Bin ->
+ erlang:binary_to_term(Bin)
+ end,
+ OldFtrs = proplists:get_value(?META_USED_FEATURES, MetaData, []),
+ NewFtrs = (Ftrs -- OldFtrs) ++ OldFtrs,
+ MetaData1 =
+ proplists:from_map(maps:put(?META_USED_FEATURES, NewFtrs,
+ proplists:to_map(MetaData))),
+ Extra1 = proplists:from_map(maps:put(?META_CHUNK_NAME,
+ erlang:term_to_binary(MetaData1),
+ proplists:to_map(Extra))),
+ St#compile{extra_chunks = Extra1}.
+
with_columns(Opts) ->
case proplists:get_value(error_location, Opts, column) of
column -> true;
@@ -1406,7 +1431,7 @@ makedep_output(Code, #compile{options=Opts,ofile=Ofile}=St) ->
if
is_list(Output) ->
- %% Write the depedencies to a file.
+ %% Write the dependencies to a file.
case file:write_file(Output, Code) of
ok ->
{ok,Code,St};
@@ -1415,7 +1440,7 @@ makedep_output(Code, #compile{options=Opts,ofile=Ofile}=St) ->
{error,St#compile{errors=St#compile.errors++[Err]}}
end;
true ->
- %% Write the depedencies to a device.
+ %% Write the dependencies to a device.
try io:fwrite(Output, "~ts", [Code]) of
ok ->
{ok,Code,St}
@@ -1430,9 +1455,43 @@ expand_records(Code0, #compile{options=Opts}=St) ->
Code = erl_expand_records:module(Code0, Opts),
{ok,Code,St}.
-compile_directives(Forms, #compile{options=Opts0}=St) ->
- Opts = expand_opts(flatten([C || {attribute,_,compile,C} <- Forms])),
- {ok, Forms, St#compile{options=Opts ++ Opts0}}.
+legalize_vars(Code0, St) ->
+ Code = map(fun(F={function,_,_,_,_}) ->
+ erl_pp:legalize_vars(F);
+ (F) ->
+ F
+ end, Code0),
+ {ok,Code,St}.
+
+compile_directives(Forms, #compile{options=Opts0}=St0) ->
+ Opts1 = expand_opts(flatten([C || {attribute,_,compile,C} <- Forms])),
+ Opts = Opts1 ++ Opts0,
+ St1 = St0#compile{options=Opts},
+ case any_obsolete_option(Opts) of
+ {yes,Opt} ->
+ Error = {St1#compile.ifile,[{none,?MODULE,{obsolete_option,Opt}}]},
+ St = St1#compile{errors=[Error|St1#compile.errors]},
+ {error,St};
+ no ->
+ {ok,Forms,St1}
+ end.
+
+any_obsolete_option([Opt|Opts]) ->
+ case is_obsolete(Opt) of
+ true -> {yes,Opt};
+ false -> any_obsolete_option(Opts)
+ end;
+any_obsolete_option([]) -> no.
+
+is_obsolete(r18) -> true;
+is_obsolete(r19) -> true;
+is_obsolete(r20) -> true;
+is_obsolete(r21) -> true;
+is_obsolete(no_bsm3) -> true;
+is_obsolete(no_get_hd_tl) -> true;
+is_obsolete(no_put_tuple2) -> true;
+is_obsolete(no_utf8_atoms) -> true;
+is_obsolete(_) -> false.
core(Forms, #compile{options=Opts}=St) ->
{ok,Core,Ws} = v3_core:module(Forms, Opts),
@@ -2020,14 +2079,12 @@ pre_load() ->
beam_jump,
beam_kernel_to_ssa,
beam_opcodes,
- beam_peep,
beam_ssa,
beam_ssa_bc_size,
beam_ssa_bool,
beam_ssa_bsm,
beam_ssa_codegen,
beam_ssa_dead,
- beam_ssa_funs,
beam_ssa_opt,
beam_ssa_pre_codegen,
beam_ssa_recv,
@@ -2046,6 +2103,7 @@ pre_load() ->
epp,
erl_bifs,
erl_expand_records,
+ erl_features,
erl_lint,
erl_parse,
erl_scan,
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index b180f5ab33..b55d6687a4 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
{modules, [
beam_a,
beam_asm,
+ beam_bounds,
beam_block,
beam_call_types,
beam_clean,
@@ -34,14 +35,12 @@
beam_kernel_to_ssa,
beam_listing,
beam_opcodes,
- beam_peep,
beam_ssa,
beam_ssa_bc_size,
beam_ssa_bool,
beam_ssa_bsm,
beam_ssa_codegen,
beam_ssa_dead,
- beam_ssa_funs,
beam_ssa_lint,
beam_ssa_opt,
beam_ssa_pp,
@@ -82,5 +81,5 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["stdlib-3.13","kernel-7.0","erts-11.0",
- "crypto-3.6"]}]}.
+ {runtime_dependencies, ["stdlib-4.0","kernel-8.4","erts-13.0",
+ "crypto-5.1"]}]}.
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index 2b795e8509..e1e36fa4dc 100755
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2021. All Rights Reserved.
+# Copyright Ericsson AB 1998-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -170,7 +170,7 @@ BEAM_FORMAT_NUMBER=0
## receive loop at Label.
25: wait/1
-## @spec wait_timeout Lable Time
+## @spec wait_timeout Label Time
## @doc Sets up a timeout of Time milliseconds and saves the address of the
## following instruction as the entry point if the timeout triggers.
26: wait_timeout/2
@@ -192,7 +192,7 @@ BEAM_FORMAT_NUMBER=0
38: -int_bnot/3
#
-# Comparision operators.
+# Comparison operators.
#
## @spec is_lt Lbl Arg1 Arg2
@@ -332,8 +332,8 @@ BEAM_FORMAT_NUMBER=0
#
68: -put_string/3
69: put_list/3
-70: put_tuple/2
-71: put/1
+70: -put_tuple/2
+71: -put/1
#
# Raising errors.
@@ -438,14 +438,14 @@ BEAM_FORMAT_NUMBER=0
# New bit syntax matching in R11B.
-116: bs_start_match2/5
+116: -bs_start_match2/5
117: bs_get_integer2/7
118: bs_get_float2/7
119: bs_get_binary2/7
120: bs_skip_bits2/5
121: bs_test_tail2/3
-122: bs_save2/2
-123: bs_restore2/2
+122: -bs_save2/2
+123: -bs_restore2/2
# New GC bifs introduced in R11B.
@@ -478,7 +478,7 @@ BEAM_FORMAT_NUMBER=0
129: is_bitstr/2
# R12B
-130: bs_context_to_binary/1
+130: -bs_context_to_binary/1
131: bs_test_unit/3
132: bs_match_string/4
133: bs_init_writable/0
@@ -647,3 +647,26 @@ BEAM_FORMAT_NUMBER=0
## @doc Sets the current receive cursor to the marker associated with
## the given Reference.
176: recv_marker_use/1
+
+# OTP 25
+
+## @spec bs_create_bin Fail Alloc Live Unit Dst OpList
+## @doc Builda a new binary using the binary syntax.
+177: bs_create_bin/6
+
+## @spec call_fun2 Tag Arity Func
+## @doc Calls the fun Func with arity Arity. Assume arguments in registers x(0)
+## to x(Arity-1). Tag can be one of:
+##
+## * FunIndex - `Func` is always a local fun identified by `FunIndex`
+## * {atom,safe} - `Func` is known to be a fun of correct arity.
+## * {atom,unsafe} - Nothing is known about `Func`.
+178: call_fun2/3
+
+## @spec nif_start
+## @doc No-op at start of each function declared in -nifs().
+179: nif_start/0
+
+## @spec badrecord Value
+## @doc Raises a {badrecord,Value} error exception.
+180: badrecord/1
diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl
index 48d39776dc..753eca4c66 100644
--- a/lib/compiler/src/rec_env.erl
+++ b/lib/compiler/src/rec_env.erl
@@ -478,7 +478,7 @@ get(Key, Env) ->
-define(MINIMUM_RANGE, 1000).
-define(START_RANGE_FACTOR, 50).
-define(MAX_RETRIES, 2). % retries before enlarging range
--define(ENLARGE_FACTOR, 10). % range enlargment factor
+-define(ENLARGE_FACTOR, 10). % range enlargement factor
-ifdef(DEBUG).
%% If you want to use these process dictionary counters, make sure to
diff --git a/lib/compiler/src/sys_core_bsm.erl b/lib/compiler/src/sys_core_bsm.erl
index 11bba79155..6e97a05f40 100644
--- a/lib/compiler/src/sys_core_bsm.erl
+++ b/lib/compiler/src/sys_core_bsm.erl
@@ -41,7 +41,7 @@ function([{#c_var{name={F,Arity}}=Name,B0}|Fs]) ->
function([]) ->
[].
-%%% Reorder bit syntax matching to faciliate optimization in further passes.
+%%% Reorder bit syntax matching to facilitate optimization in further passes.
bsm_reorder(#c_case{arg=#c_var{}=V}=Case) ->
bsm_reorder_1([V], Case);
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 1c26fc301d..d96f3a6ae0 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -215,15 +215,15 @@ expr(#c_tuple{anno=Anno,es=Es0}=Tuple, Ctxt, Sub) ->
ann_c_tuple(Anno, Es)
end;
expr(#c_map{anno=Anno,arg=V0,es=Es0}=Map, Ctxt, Sub) ->
- Es = pair_list(Es0, Ctxt, descend(Map, Sub)),
+ %% Warn for useless building, but always build the map
+ %% anyway to preserve a possible exception.
case Ctxt of
- effect ->
- warn_useless_building(Map, Sub),
- make_effect_seq(Es, Sub);
- value ->
- V = expr(V0, Ctxt, Sub),
- ann_c_map(Anno,V,Es)
- end;
+ effect -> warn_useless_building(Map, Sub);
+ value -> ok
+ end,
+ Es = pair_list(Es0, descend(Map, Sub)),
+ V = expr(V0, value, Sub),
+ ann_c_map(Anno, V, Es);
expr(#c_binary{segments=Ss}=Bin0, Ctxt, Sub) ->
%% Warn for useless building, but always build the binary
%% anyway to preserve a possible exception.
@@ -324,19 +324,16 @@ expr(#c_case{}=Case0, Ctxt, Sub) ->
%% (in addition to any warnings that may have been emitted
%% according to the rules above).
%%
- case opt_bool_case(Case0, Sub) of
- #c_case{anno=Anno,arg=Arg0,clauses=Cs0}=Case1 ->
- Arg1 = body(Arg0, value, Sub),
- LitExpr = cerl:is_literal(Arg1),
- {Arg2,Cs1} = case_opt(Arg1, Cs0, Sub),
- Cs2 = clauses(Arg2, Cs1, Ctxt, Sub, LitExpr, Anno),
- Case = Case1#c_case{arg=Arg2,clauses=Cs2},
- warn_no_clause_match(Case1, Case),
- Expr = eval_case(Case, Sub),
- move_case_into_arg(Expr, Sub);
- Other ->
- expr(Other, Ctxt, Sub)
- end;
+ Case1 = opt_bool_case(Case0, Sub),
+ #c_case{anno=Anno,arg=Arg0,clauses=Cs0} = Case1,
+ Arg1 = body(Arg0, value, Sub),
+ LitExpr = cerl:is_literal(Arg1),
+ {Arg2,Cs1} = case_opt(Arg1, Cs0, Sub),
+ Cs2 = clauses(Arg2, Cs1, Ctxt, Sub, LitExpr, Anno),
+ Case = Case1#c_case{arg=Arg2,clauses=Cs2},
+ warn_no_clause_match(Case1, Case),
+ Expr = eval_case(Case, Sub),
+ move_case_into_arg(Expr, Sub);
expr(#c_apply{anno=Anno,op=Op0,args=As0}=Apply0, _, Sub) ->
Op1 = expr(Op0, value, Sub),
As1 = expr_list(As0, value, Sub),
@@ -493,14 +490,12 @@ ifes_list(_FVar, [], _Safe) ->
expr_list(Es, Ctxt, Sub) ->
[expr(E, Ctxt, Sub) || E <- Es].
-pair_list(Es, Ctxt, Sub) ->
- [pair(E, Ctxt, Sub) || E <- Es].
+pair_list(Es, Sub) ->
+ [pair(E, Sub) || E <- Es].
-pair(#c_map_pair{key=K,val=V}, effect, Sub) ->
- make_effect_seq([K,V], Sub);
-pair(#c_map_pair{key=K0,val=V0}=Pair, value=Ctxt, Sub) ->
- K = expr(K0, Ctxt, Sub),
- V = expr(V0, Ctxt, Sub),
+pair(#c_map_pair{key=K0,val=V0}=Pair, Sub) ->
+ K = expr(K0, value, Sub),
+ V = expr(V0, value, Sub),
Pair#c_map_pair{key=K,val=V}.
bitstr_list(Es, Sub) ->
@@ -604,10 +599,7 @@ eval_binary(#c_binary{anno=Anno,segments=Ss}=Bin) ->
Bin;
throw:{badarg,Warning} ->
add_warning(Bin, {failed,Warning}),
- #c_call{anno=Anno,
- module=#c_literal{val=erlang},
- name=#c_literal{val=error},
- args=[#c_literal{val=badarg}]}
+ Bin
end.
eval_binary_1([#c_bitstr{val=#c_literal{val=Val},size=#c_literal{val=Sz},
@@ -1439,15 +1431,15 @@ shadow_warning([C|Cs], Line, Anno) ->
shadow_warning(Cs, Line, Anno);
shadow_warning([], _, _) -> ok.
-%% will_succeed(Guard) -> yes | maybe | no.
+%% will_succeed(Guard) -> yes | 'maybe' | no.
%% Test if we know whether a guard will succeed/fail or just don't
%% know. Be VERY conservative!
will_succeed(#c_literal{val=true}) -> yes;
will_succeed(#c_literal{val=false}) -> no;
-will_succeed(_Guard) -> maybe.
+will_succeed(_Guard) -> 'maybe'.
-%% will_match(Expr, [Pattern]) -> yes | maybe.
+%% will_match(Expr, [Pattern]) -> yes | 'maybe'.
%% We KNOW that this function is only used after optimizations
%% in case_opt/4. Therefore clauses that can definitely not match
%% have already been pruned.
@@ -1457,7 +1449,7 @@ will_match(#c_values{es=Es}, Ps) ->
will_match(E, [P]) ->
will_match_1(cerl_clauses:match(P, E)).
-will_match_1({false,_}) -> maybe;
+will_match_1({false,_}) -> 'maybe';
will_match_1({true,_}) -> yes.
%% opt_bool_case(CoreExpr, Sub) - CoreExpr'.
@@ -1591,34 +1583,12 @@ opt_bool_not(#c_case{arg=Arg,clauses=Cs0}=Case0) ->
Case = Case0#c_case{arg=Expr,clauses=Cs},
opt_bool_not(Case);
_ ->
- opt_bool_case_redundant(Case0)
+ Case0
end.
opt_bool_not_invert(#c_clause{pats=[#c_literal{val=Bool}]}=C) ->
C#c_clause{pats=[#c_literal{val=not Bool}]}.
-%% opt_bool_case_redundant(Core) -> Core'.
-%% If the sole purpose of the case is to verify that the case
-%% expression is indeed boolean, we do not need the case
-%% (since we have already verified that the case expression is
-%% boolean).
-%%
-%% case BoolExpr of
-%% true -> true ==> BoolExpr
-%% false -> false
-%% end.
-%%
-opt_bool_case_redundant(#c_case{arg=Arg,clauses=Cs}=Case) ->
- case all(fun opt_bool_case_redundant_1/1, Cs) of
- true -> Arg;
- false -> Case
- end.
-
-opt_bool_case_redundant_1(#c_clause{pats=[#c_literal{val=B}],
- body=#c_literal{val=B}}) ->
- true;
-opt_bool_case_redundant_1(_) -> false.
-
%% eval_case(Case) -> #c_case{} | #c_let{}.
%% If possible, evaluate a case at compile time. We know that the
%% last clause is guaranteed to match so if there is only one clause
@@ -2773,7 +2743,7 @@ void() -> #c_literal{val=ok}.
%%% While optimizing this code fragment, two warnings for useless
%%% building will be generated: one for the list and one for the tuple
%%% inside. Before the introduction of column numbers, those two warnings
-%%% would be coalesced to one becuase they had the same line number.
+%%% would be coalesced to one because they had the same line number.
%%%
%%% With column numbers, we will need a more sophisticated solution to
%%% avoid emitting annoying duplicate warnings.
diff --git a/lib/compiler/src/sys_core_fold_lists.erl b/lib/compiler/src/sys_core_fold_lists.erl
index f94a25d961..21d1a4687e 100644
--- a/lib/compiler/src/sys_core_fold_lists.erl
+++ b/lib/compiler/src/sys_core_fold_lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,12 +43,13 @@ call(#c_call{anno=Anno}, lists, all, [Arg1,Arg2]) ->
CC2 = #c_clause{anno=Anno,
pats=[#c_literal{val=false}], guard=#c_literal{val=true},
body=#c_literal{val=false}},
- CC3 = #c_clause{anno=Anno,
+ CC3 = #c_clause{anno=[compiler_generated|Anno],
pats=[X], guard=#c_literal{val=true},
body=match_fail(Anno, Err1)},
C1 = #c_clause{anno=Anno,
pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
+ body=#c_case{anno=Anno,
+ arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
C2 = #c_clause{anno=Anno,
pats=[#c_literal{val=[]}],
@@ -59,7 +60,7 @@ call(#c_call{anno=Anno}, lists, all, [Arg1,Arg2]) ->
C3 = #c_clause{anno=Anno, pats=[Xs], guard=#c_literal{val=true},
body=function_clause(Anno, [F, Xs])},
Fun = #c_fun{vars=[Xs],
- body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
+ body=#c_case{anno=Anno, arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
@@ -76,12 +77,13 @@ call(#c_call{anno=Anno}, lists, any, [Arg1,Arg2]) ->
CC2 = #c_clause{anno=Anno,
pats=[#c_literal{val=false}], guard=#c_literal{val=true},
body=#c_apply{anno=Anno, op=Loop, args=[Xs]}},
- CC3 = #c_clause{anno=Anno,
+ CC3 = #c_clause{anno=[compiler_generated|Anno],
pats=[X], guard=#c_literal{val=true},
body=match_fail(Anno, Err1)},
C1 = #c_clause{anno=Anno,
pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
- body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
+ body=#c_case{anno=Anno,
+ arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
C2 = #c_clause{anno=Anno,
pats=[#c_literal{val=[]}],
@@ -92,7 +94,7 @@ call(#c_call{anno=Anno}, lists, any, [Arg1,Arg2]) ->
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
body=function_clause(Anno, [F, Xs])},
Fun = #c_fun{vars=[Xs],
- body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
+ body=#c_case{anno=Anno, arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
#c_let{vars=[F, L], arg=#c_values{es=[Arg1, Arg2]},
body=#c_letrec{defs=[{Loop,Fun}],
diff --git a/lib/compiler/src/sys_messages.erl b/lib/compiler/src/sys_messages.erl
index 5a6928f60d..b49f08e043 100644
--- a/lib/compiler/src/sys_messages.erl
+++ b/lib/compiler/src/sys_messages.erl
@@ -2,7 +2,7 @@
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
-%% Copyright 2020-2021 Facebook, Inc. and its affiliates.
+%% Copyright 2020-2022 Facebook, Inc. and its affiliates.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -125,10 +125,20 @@ line_prefix() ->
"% ".
fmt_line(L, Text) ->
- [line_prefix(), io_lib:format("~4.ts| ", [line_to_txt(L)]), Text, "\n"].
-
-line_to_txt(0) -> "";
-line_to_txt(L) -> integer_to_list(L).
+ {LineText, LineTextLength} = line_to_txt(L),
+ [line_prefix(),
+ io_lib:format("~*.ts| ", [LineTextLength, LineText]),
+ Text, "\n"].
+
+line_to_txt(L) ->
+ LineText = integer_to_list(abs(L)),
+ Length = max(4, length(LineText)),
+ if
+ L < 0 ->
+ {"", Length};
+ true ->
+ {LineText, Length}
+ end.
decorate([{Line, Text} = L | Ls], StartLine, StartCol, EndLine, EndCol) when
Line =:= StartLine, EndLine =:= StartLine ->
@@ -147,8 +157,8 @@ decorate([], _StartLine, _StartCol, _EndLine, _EndCol) ->
%% don't produce empty decoration lines
decorate("", L, Ls, StartLine, StartCol, EndLine, EndCol) ->
[L | decorate(Ls, StartLine, StartCol, EndLine, EndCol)];
-decorate(Text, L, Ls, StartLine, StartCol, EndLine, EndCol) ->
- [L, {0, Text} | decorate(Ls, StartLine, StartCol, EndLine, EndCol)].
+decorate(Text, {Line, _} = L, Ls, StartLine, StartCol, EndLine, EndCol) ->
+ [L, {-Line, Text} | decorate(Ls, StartLine, StartCol, EndLine, EndCol)].
%% End typically points to the first position after the actual region.
%% If End = Start, we adjust it to Start+1 to mark at least one character
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 2fd31656ca..ff7a48e002 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -109,6 +109,7 @@
-record(ifun, {anno=#a{},id,vars,clauses,fc,name=unnamed}).
-record(iletrec, {anno=#a{},defs,body}).
-record(imatch, {anno=#a{},pat,guard=[],arg,fc}).
+-record(iexprs, {anno=#a{},bodies=[]}).
-record(imap, {anno=#a{},arg=#c_literal{val=#{}},es,is_pat=false}).
-record(imappair, {anno=#a{},op,key,val}).
-record(iprimop, {anno=#a{},name,args}).
@@ -170,6 +171,7 @@
-record(imodule, {name = [],
exports = ordsets:new(),
+ nifs = sets:new([{version, 2}]),
attrs = [],
defs = [],
file = [],
@@ -194,9 +196,8 @@ module(Forms0, Opts) ->
Kfs = reverse(Kfs0),
{ok,#c_module{name=#c_literal{val=Mod},exports=Cexp,attrs=As,defs=Kfs},Ws}.
-form({function,_,_,_,_}=F0, Module, Opts) ->
- #imodule{file=File,defs=Defs,ws=Ws0} = Module,
- {F,Ws} = function(F0, Ws0, File, Opts),
+form({function,_,_,_,_}=F0, #imodule{defs=Defs}=Module, Opts) ->
+ {F,Ws} = function(F0, Module, Opts),
Module#imodule{defs=[F|Defs],ws=Ws};
form({attribute,_,module,Mod}, Module, _Opts) ->
true = is_atom(Mod),
@@ -204,11 +205,14 @@ form({attribute,_,module,Mod}, Module, _Opts) ->
form({attribute,_,file,{File,_Line}}=F, #imodule{attrs=As}=Module, _Opts) ->
Module#imodule{file=File, attrs=[attribute(F)|As]};
form({attribute,_,import,_}, Module, _Opts) ->
- %% Ignore. We have no futher use for imports.
+ %% Ignore. We have no further use for imports.
Module;
form({attribute,_,export,Es}, #imodule{exports=Exp0}=Module, _Opts) ->
Exp = ordsets:union(ordsets:from_list(Es), Exp0),
Module#imodule{exports=Exp};
+form({attribute,_,nifs,Ns}, #imodule{nifs=Nifs0}=Module, _Opts) ->
+ Nifs = sets:union(sets:from_list(Ns, [{version,2}]), Nifs0),
+ Module#imodule{nifs=Nifs};
form({attribute,_,_,_}=F, #imodule{attrs=As}=Module, _Opts) ->
Module#imodule{attrs=[attribute(F)|As]};
form(_, Module, _Opts) ->
@@ -232,7 +236,8 @@ defined_functions(Forms) ->
%% io:format("~w/~w " ++ Format,[Name,Arity]++Terms),
%% ok.
-function({function,_,Name,Arity,Cs0}, Ws0, File, Opts) ->
+function({function,_,Name,Arity,Cs0}, Module, Opts) ->
+ #imodule{file=File, ws=Ws0, nifs=Nifs} = Module,
try
St0 = #core{vcount=0,function={Name,Arity},opts=Opts,
dialyzer=member(dialyzer, Opts),
@@ -241,7 +246,7 @@ function({function,_,Name,Arity,Cs0}, Ws0, File, Opts) ->
%% ok = function_dump(Name, Arity, "body:~n~p~n",[B0]),
{B1,St2} = ubody(B0, St1),
%% ok = function_dump(Name, Arity, "ubody:~n~p~n",[B1]),
- {B2,St3} = cbody(B1, St2),
+ {B2,St3} = cbody(B1, Nifs, St2),
%% ok = function_dump(Name, Arity, "cbody:~n~p~n",[B2]),
{B3,#core{ws=Ws}} = lbody(B2, St3),
%% ok = function_dump(Name, Arity, "lbody:~n~p~n",[B3]),
@@ -259,7 +264,7 @@ body(Cs0, Name, Arity, St0) ->
Args = reverse(Args0), %Nicer order
{Cs1,St2} = clauses(Cs0, St1),
{Ps,St3} = new_vars(Arity, St2), %Need new variables here
- Fc = function_clause(Ps, Anno),
+ Fc = function_clause(Ps, FunAnno),
{#ifun{anno=#a{anno=FunAnno},id=[],vars=Args,clauses=Cs1,fc=Fc},St3}.
%% clause(Clause, State) -> {Cclause,State}.
@@ -282,7 +287,7 @@ clause({clause,Lc,H0,G0,B0}, St0) ->
catch
throw:nomatch ->
%% This pattern can't possibly match. If we simply remove
- %% the clause, varibles that are used later might not be
+ %% the clause, variables that are used later might not be
%% bound. Therefore, we must keep the clause, but rewrite
%% the pattern to a pattern that will bind the same
%% variables and ensure that the clause can't be executed
@@ -303,7 +308,7 @@ head(Ps, St) ->
pattern_list(Ps, St).
%% guard([Expr], State) -> {[Cexpr],State}.
-%% Build an explict and/or tree of guard alternatives, then traverse
+%% Build an explicit and/or tree of guard alternatives, then traverse
%% top-level and/or tree and "protect" inner tests.
guard([], St) -> {[],St};
@@ -422,7 +427,7 @@ gexpr_not(A, Bools0, St0, Line) ->
%% which will produce the same result, but may eliminate
%% redundant is_boolean/1 tests (see unforce/3).
%%
- %% Note that this tranformation would not be safe if the
+ %% Note that this transformation would not be safe if the
%% original expression had been:
%%
%% not(Expr =:= true)
@@ -565,6 +570,8 @@ unforce(E, Eps, Vs) ->
Tree = unforce_tree(Eps++[E], gb_trees:empty()),
unforce(Tree, Vs).
+unforce_tree([#iexprs{bodies=Exprs}|Es], D0) ->
+ unforce_tree(lists:append(Exprs) ++ Es, D0);
unforce_tree([#iset{var=#c_var{name=V},arg=Arg0}|Es], D0) ->
Arg = unforce_tree_subst(Arg0, D0),
D = gb_trees:insert(V, Arg, D0),
@@ -616,6 +623,34 @@ exprs([E0|Es0], St0) ->
{Eps ++ [E1] ++ Es1,St2};
exprs([], St) -> {[],St}.
+%% exprs([Expr], State) -> {[Cexpr],State}.
+%% Flatten top-level exprs while handling maybe_match operators.
+
+maybe_match_exprs([{maybe_match,L,P0,E0}|Es0], Fail, St0) ->
+ {Es1,St1} = maybe_match_exprs(Es0, Fail, St0),
+ {C,St2} =
+ case Es1 of
+ [] ->
+ {AllName,StInt} = new_var_name(St1),
+ All = {var,L,AllName},
+ clause({clause,L,[{match,L,P0,All}],[],[All]}, StInt);
+ [_|_] ->
+ {C0,StInt} = clause({clause,L,[P0],[],[{nil,0}]}, St1),
+ {C0#iclause{body=Es1},StInt}
+ end,
+ {E1,Eps,St3} = novars(E0, St2),
+ {Fpat,St4} = new_var(St3),
+ Lanno = lineno_anno(L, St4),
+ Fc = #iclause{anno=#a{anno=[dialyzer_ignore,compiler_generated|Lanno]},pats=[Fpat],guard=[],
+ body=[#iapply{op=Fail,args=[Fpat]}]},
+ {Eps ++ [#icase{anno=#a{anno=Lanno},args=[E1],clauses=[C],fc=Fc}],St4};
+maybe_match_exprs([E0|Es0], Fail, St0) ->
+ {E1,Eps,St1} = expr(E0, St0),
+ {Es1,St2} = maybe_match_exprs(Es0, Fail, St1),
+ {Eps ++ [E1|Es1],St2};
+maybe_match_exprs([], _Fail, St) ->
+ {[],St}.
+
%% expr(Expr, State) -> {Cexpr,[PreExp],State}.
%% Generate an internal core expression.
@@ -627,10 +662,9 @@ expr({atom,L,A}, St) -> {#c_literal{anno=full_anno(L, St),val=A},[],St};
expr({nil,L}, St) -> {#c_literal{anno=full_anno(L, St),val=[]},[],St};
expr({string,L,S}, St) -> {#c_literal{anno=full_anno(L, St),val=S},[],St};
expr({cons,L,H0,T0}, St0) ->
- {H1,Hps,St1} = safe(H0, St0),
- {T1,Tps,St2} = safe(T0, St1),
- A = full_anno(L, St2),
- {annotate_cons(A, H1, T1, St2),Hps ++ Tps,St2};
+ {[H1,T1],Eps,St1} = safe_list([H0,T0], St0),
+ A = full_anno(L, St1),
+ {annotate_cons(A, H1, T1, St1),Eps,St1};
expr({lc,L,E,Qs0}, St0) ->
{Qs1,St1} = preprocess_quals(L, Qs0, St0),
lc_tq(L, E, Qs1, #c_literal{anno=lineno_anno(L, St1),val=[]}, St1);
@@ -662,6 +696,84 @@ expr({block,_,Es0}, St0) ->
{Es1,St1} = exprs(droplast(Es0), St0),
{E1,Eps,St2} = expr(last(Es0), St1),
{E1,Es1 ++ Eps,St2};
+expr({'maybe',L,Es}, St0) ->
+ {V,St1} = new_var_name(St0),
+ Var = {var,L,V},
+ Cs = [{clause,L,[Var],[],[Var]}],
+ expr({'maybe',L,Es,{'else',L,Cs}}, St1);
+expr({'maybe',L,Es0,{'else',_,Cs0}}, St0) ->
+ %% Translate the maybe ... else ... end construct.
+ %%
+ %% As an example, the following Erlang code:
+ %%
+ %% foo(A) ->
+ %% maybe
+ %% {ok, V} ?= A,
+ %% V
+ %% else
+ %% Other ->
+ %% {error, Other}
+ %% end.
+ %%
+ %% is translated into Core Erlang like this:
+ %%
+ %% 'foo'/1 =
+ %% fun (_0) ->
+ %% case _0 of
+ %% <A> when 'true' ->
+ %% ( letrec
+ %% 'maybe_else_fail'/1 =
+ %% fun (_3) ->
+ %% case _3 of
+ %% <_2> when 'true' ->
+ %% case _2 of
+ %% <Other> when 'true' ->
+ %% {'error',Other}
+ %% ( <_1> when 'true' ->
+ %% primop 'match_fail'({'else_clause',_1})
+ %% -| ['compiler_generated'] )
+ %% end
+ %% ( <_1> when 'true' ->
+ %% primop 'match_fail'('never_fails')
+ %% -| ['compiler_generated'] )
+ %% end
+ %% in
+ %% case A of
+ %% <{'ok',V}> when 'true' ->
+ %% V
+ %% ( <_4> when 'true' ->
+ %% apply 'maybe_else_fail'/1(_4)
+ %% -| ['dialyzer_ignore','compiler_generated'] )
+ %% end
+ %% -| ['letrec_goto','no_inline'] )
+ %% ( <_5> when 'true' ->
+ %% primop 'match_fail'({'function_clause',_5})
+ %% -| ['compiler_generated'] )
+ %% end
+ {[V1,V2,FailVar],St1} = new_vars(3, St0),
+
+ %% Translate the body of the letrec.
+ Fail = {maybe_else_fail,1},
+ Lanno = lineno_anno(L, St1),
+ {Es1,St2} = maybe_match_exprs(Es0, #c_var{name=Fail}, St1),
+
+ %% Translate the 'else' clauses. Note that we must not put the clauses
+ %% as the top-level clauses in the fun, because all shawdowing variables
+ %% in a fun head will be renamed.
+ {Cs1,St3} = clauses(Cs0, St2),
+ Fc1 = fail_clause([FailVar], Lanno, c_tuple([#c_literal{val=else_clause},FailVar])),
+ FailCase = #icase{args=[V2],clauses=Cs1,fc=Fc1},
+ FailFunCs = [#iclause{pats=[V2],guard=[#c_literal{val=true}],
+ body=[FailCase]}],
+ Anno = #a{anno=[letrec_goto,no_inline|Lanno]},
+ Fc2 = fail_clause([FailVar], Lanno, #c_literal{val=never_fails}),
+ FailFun = #ifun{id=[],vars=[V1],
+ clauses=FailFunCs,
+ fc=Fc2},
+
+ %% Construct the letrec.
+ Letrec = #iletrec{anno=Anno,defs=[{Fail,FailFun}],body=Es1},
+ {Letrec,[],St3};
expr({'if',L,Cs0}, St0) ->
{Cs1,St1} = clauses(Cs0, St0),
Lanno = lineno_anno(L, St1),
@@ -717,6 +829,8 @@ expr({'catch',L,E0}, St0) ->
Lanno = lineno_anno(L, St1),
{#icatch{anno=#a{anno=Lanno},body=Eps ++ [E1]},[],St1};
expr({'fun',L,{function,F,A}}, St0) ->
+ %% Generate a new name for eta conversion of local funs (`fun local/123`)
+ %% in case `no_shared_fun_wrappers` is given.
{Fname,St1} = new_fun_name(St0),
Lanno = full_anno(L, St1),
Id = {0,0,Fname},
@@ -734,10 +848,20 @@ expr({named_fun,L,'_',Cs}, St) ->
fun_tq(Cs, L, St, unnamed);
expr({named_fun,L,Name,Cs}, St) ->
fun_tq(Cs, L, St, {named,Name});
-expr({call,L,{remote,_,M,F},As0}, St0) ->
- {[M1,F1|As1],Aps,St1} = safe_list([M,F|As0], St0),
+expr({call,L,{remote,_,M0,F0},As0}, St0) ->
+ {[M1,F1|As1],Aps,St1} = safe_list([M0,F0|As0], St0),
Anno = full_anno(L, St1),
- {#icall{anno=#a{anno=Anno},module=M1,name=F1,args=As1},Aps,St1};
+ case {M1,F1,As1} of
+ {#c_literal{val=erlang},
+ #c_literal{val=error},
+ [#c_tuple{es=[#c_literal{val=badrecord},_]}=Tuple]} ->
+ Fail = #iprimop{anno=#a{anno=Anno},
+ name=#c_literal{val=match_fail},
+ args=[Tuple]},
+ {Fail,Aps,St1};
+ {_,_,_} ->
+ {#icall{anno=#a{anno=Anno},module=M1,name=F1,args=As1},Aps,St1}
+ end;
expr({call,Lc,{atom,Lf,F},As0}, St0) ->
{As1,Aps,St1} = safe_list(As0, St0),
Op = #c_var{anno=lineno_anno(Lf, St1),name={F,length(As1)}},
@@ -748,85 +872,47 @@ expr({call,L,FunExp,As0}, St0) ->
Lanno = lineno_anno(L, St2),
{#iapply{anno=#a{anno=Lanno},op=Fun,args=As1},Fps ++ Aps,St2};
expr({match,L,P0,E0}, St0) ->
- %% First fold matches together to create aliases.
- {P1,E1} = fold_match(E0, P0),
- St1 = set_wanted(P1, St0),
- {E2,Eps1,St2} = novars(E1, St1),
- St3 = St2#core{wanted=St0#core.wanted},
- {P2,St4} = try
- pattern(P1, St3)
- catch
- throw:Thrown ->
- {Thrown,St3}
- end,
- {Fpat,St5} = new_var(St4),
- Lanno = lineno_anno(L, St5),
- Fc = fail_clause([Fpat], Lanno, c_tuple([#c_literal{val=badmatch},Fpat])),
- case P2 of
- nomatch ->
- %% The pattern will not match. We must take care here to
- %% bind all variables that the pattern would have bound
- %% so that subsequent expressions do not refer to unbound
- %% variables.
- %%
- %% As an example, this code:
- %%
- %% [X] = {Y} = E,
- %% X + Y.
- %%
- %% will be rewritten to:
- %%
- %% error({badmatch,E}),
- %% case E of
- %% {[X],{Y}} ->
- %% X + Y;
- %% Other ->
- %% error({badmatch,Other})
- %% end.
- %%
- St6 = add_warning(L, {nomatch,pattern}, St5),
- {Expr,Eps3,St7} = safe(E1, St6),
- SanPat0 = sanitize(P1),
- {SanPat,St} = pattern(SanPat0, St7),
- Badmatch = c_tuple([#c_literal{val=badmatch},Expr]),
- Fail = #iprimop{anno=#a{anno=Lanno},
- name=#c_literal{val=match_fail},
- args=[Badmatch]},
- Eps = Eps3 ++ [Fail],
- {#imatch{anno=#a{anno=Lanno},pat=SanPat,arg=Expr,fc=Fc},Eps,St};
- Other when not is_atom(Other) ->
- %% We must rewrite top-level aliases to lets to avoid unbound
- %% variables in code such as:
- %%
- %% <<42:Sz>> = Sz = B
- %%
- %% If we would keep the top-level aliases the example would
- %% be translated like this:
- %%
- %% case B of
- %% <Sz = #{#<42>(Sz,1,'integer',['unsigned'|['big']])}#>
- %% when 'true' ->
- %% .
- %% .
- %% .
- %%
- %% Here the variable Sz would be unbound in the binary pattern.
+ St1 = set_wanted(P0, St0),
+ case fold_match(E0, P0) of
+ {{sequential_match,_,_,_}=P1,E1} ->
+ %% Matching of an expression to more than one pattern. Example:
%%
- %% Instead we bind Sz in a let to ensure it is bound when
- %% used in the binary pattern:
+ %% #rec{f=Val} = A = Expr
+ {E2,Eps1,St2} = safe(E1, St1),
+ St3 = St2#core{wanted=St0#core.wanted},
+
+ %% If necessary, bind the expression to a variable to ensure it is
+ %% only evaluted once.
+ {Var,Eps2,St4} =
+ case E2 of
+ #c_var{} ->
+ {E2,[],St3};
+ _ ->
+ {Var0,StInt} = new_var(St3),
+ {Var0,[#iset{var=Var0,arg=E2}],StInt}
+ end,
+
+ %% Rewrite to a begin/end block matching one pattern at the time
+ %% (using the `single_match` operator). Example:
%%
- %% let <Sz> = B
- %% in case Sz of
- %% <#{#<42>(Sz,1,'integer',['unsigned'|['big']])}#>
- %% when 'true' ->
- %% .
- %% .
- %% .
- %%
- {P3,E3,Eps2} = letify_aliases(P2, E2),
- Eps = Eps1 ++ Eps2,
- {#imatch{anno=#a{anno=Lanno},pat=P3,arg=E3,fc=Fc},Eps,St5}
+ %% begin
+ %% V = Expr,
+ %% A = V,
+ %% #rec{f=Val} = V
+ %% end
+ Block = blockify(L, P1, Var),
+ {E3,Eps3,St5} = expr({block,L,Block}, St4),
+ {E3,Eps1 ++ Eps2 ++ Eps3,St5};
+ {P0,E1} ->
+ %% Matching of an expression to a single pattern. Example:
+ %% {A,B} = Expr
+ {E2,Eps1,St2} = novars(E1, St1),
+ St3 = St2#core{wanted=St0#core.wanted},
+ {E3,Eps2,St4} = single_match(L, P0, E2, St3),
+ {E3,Eps1 ++ Eps2,St4}
end;
+expr({single_match,L,P,#c_var{}=E}, St0) ->
+ single_match(L, P, E, St0);
expr({op,_,'++',{lc,Llc,E,Qs0},More}, St0) ->
%% Optimise '++' here because of the list comprehension algorithm.
%%
@@ -867,6 +953,56 @@ expr({op,L,Op,L0,R0}, St0) ->
module=#c_literal{anno=LineAnno,val=erlang},
name=#c_literal{anno=LineAnno,val=Op},args=As},Aps,St1}.
+blockify(L0, {sequential_match,_L1,First,Then}, E) ->
+ [{single_match,L0,First,E}|blockify(L0, Then, E)];
+blockify(L, P, E) ->
+ [{single_match,L,P,E}].
+
+%% single_match(Line, AbstractPattern, CoreExpr, State0) -> {Expr,Pre,State}.
+%% Generate the code for matching an expression against a single pattern.
+single_match(L, P0, E, St0) ->
+ {Fpat,St1} = new_var(St0),
+ Lanno = lineno_anno(L, St1),
+ Fc = fail_clause([Fpat], Lanno, c_tuple([#c_literal{val=badmatch},Fpat])),
+ try pattern(P0, St1) of
+ {P1,St2} ->
+ St3 = set_wanted(P0, St2),
+ St4 = St3#core{wanted=St0#core.wanted},
+ {#imatch{anno=#a{anno=Lanno},pat=P1,arg=E,fc=Fc},[],St4}
+ catch
+ throw:nomatch ->
+ %% The pattern will not match. We must take care here to
+ %% bind all variables that the pattern would have bound
+ %% so that subsequent expressions do not refer to unbound
+ %% variables.
+ %%
+ %% As an example, this code:
+ %%
+ %% ([X] = {Y}) = E,
+ %% X + Y.
+ %%
+ %% will be rewritten to:
+ %%
+ %% error({badmatch,E}),
+ %% case E of
+ %% {[X],{Y}} ->
+ %% X + Y;
+ %% Other ->
+ %% error({badmatch,Other})
+ %% end.
+ %%
+ St2 = add_warning(L, {nomatch,pattern}, St1),
+ {Expr,Eps0,St3} = force_safe(E, St2),
+ SanPat0 = sanitize(P0),
+ {SanPat,St} = pattern(SanPat0, St3),
+ Badmatch = c_tuple([#c_literal{val=badmatch},Expr]),
+ Fail = #iprimop{anno=#a{anno=Lanno},
+ name=#c_literal{val=match_fail},
+ args=[Badmatch]},
+ Eps = Eps0 ++ [Fail],
+ {#imatch{anno=#a{anno=Lanno},pat=SanPat,arg=Expr,fc=Fc},Eps,St}
+ end.
+
%% set_wanted(Pattern, St) -> St'.
%% Suppress warnings for expressions that are bound to the '_'
%% variable and variables that begin with '_'.
@@ -881,12 +1017,6 @@ set_wanted({var,_,Var}, St) ->
end;
set_wanted(_, St) -> St.
-letify_aliases(#c_alias{var=V,pat=P0}, E0) ->
- {P1,E1,Eps0} = letify_aliases(P0, V),
- {P1,E1,[#iset{var=V,arg=E0}|Eps0]};
-letify_aliases(P, E) ->
- {P,E,[]}.
-
%% sanitize(Pat) -> SanitizedPattern
%% Rewrite Pat so that it will be accepted by pattern/2 and will
%% bind the same variables as the original pattern.
@@ -1162,7 +1292,7 @@ is_iexprs_small_2(_, Threshold) ->
%% record whereas c_literal should not have a wrapped annotation
expr_bin(Es0, Anno, St0) ->
- Es1 = [bin_element(E) || E <- Es0],
+ Es1 = bin_elements(Es0, 1),
case constant_bin(Es1) of
error ->
case expr_bin_1(Es1, St0) of
@@ -1202,12 +1332,12 @@ bitstrs([E0|Es0], St0) ->
bitstrs([], St) ->
{[],[],St}.
-bitstr({bin_element,Line,{string,_,S},{integer,_,8},_}, St) ->
- bitstrs(bin_expand_string(S, Line, 0, 0, []), St);
-bitstr({bin_element,Line,{string,_,[]},Sz0,Ts}, St0) ->
+bitstr({bin_element,{sl,_,Line},{string,_,S},{integer,_,8},_}, St) ->
+ bitstrs(bin_expand_string(S, {sl,0,Line}, 0, 0, []), St);
+bitstr({bin_element,{sl,_,Line},{string,_,[]},Sz0,Ts}, St0) ->
%% Empty string. We must make sure that the type is correct.
{[#c_bitstr{size=Sz}],Eps0,St1} =
- bitstr({bin_element,Line,{char,Line,0},Sz0,Ts}, St0),
+ bitstr({bin_element,{sl,0,Line},{char,Line,0},Sz0,Ts}, St0),
%% At this point, the type is either a correct literal or
%% an expression.
@@ -1234,12 +1364,12 @@ bitstr({bin_element,Line,{string,_,[]},Sz0,Ts}, St0) ->
Eps = Eps0 ++ Eps1,
{[],Eps,St2}
end;
-bitstr({bin_element,Line,{string,_,S},Sz0,Ts}, St0) ->
- {[Bitstr],Eps,St1} = bitstr({bin_element,Line,{char,Line,0},Sz0,Ts}, St0),
+bitstr({bin_element,{sl,_,Line},{string,_,S},Sz0,Ts}, St0) ->
+ {[Bitstr],Eps,St1} = bitstr({bin_element,{sl,0,Line},{char,Line,0},Sz0,Ts}, St0),
Es = [Bitstr#c_bitstr{val=#c_literal{anno=full_anno(Line, St1),val=C}} ||
C <- S],
{Es,Eps,St1};
-bitstr({bin_element,Line,E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
+bitstr({bin_element,{sl,Seg,Line},E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
{E1,Eps0,St1} = safe(E0, St0),
{Size1,Eps1,St2} = safe(Size0, St1),
Eps = Eps0 ++ Eps1,
@@ -1263,36 +1393,56 @@ bitstr({bin_element,Line,E0,Size0,[Type,{unit,Unit}|Flags]}, St0) ->
#c_literal{val=all} -> ok;
_ -> throw({bad_binary,Eps,St2})
end,
- {[#c_bitstr{anno=lineno_anno(Line, St2),
+ Anno0 = lineno_anno(Line, St2),
+
+ %% We will add a 'segment' annotation to segments that could
+ %% fail. There is no need to add it to literal segments of fixed
+ %% sized. The annotation will be used by the runtime system to
+ %% provide extended error information if construction of the
+ %% binary fails.
+ Anno = if Seg =:= 0 ->
+ Anno0;
+ true ->
+ [{segment,Seg}|Anno0]
+ end,
+
+ {[#c_bitstr{anno=Anno,
val=E1,size=Size1,
unit=#c_literal{val=Unit},
type=#c_literal{val=Type},
flags=#c_literal{val=Flags}}],
Eps,St2}.
-bin_element({bin_element,Line,Expr,Size0,Type0}) ->
- {Size,Type} = make_bit_type(Line, Size0, Type0),
- {bin_element,Line,Expr,Size,Type}.
+bin_elements([{bin_element,Line,Expr,Size0,Type0}|Es], Seg) ->
+ {Size,Type} = make_bit_type(Line, Size0, Type0, construction),
+ [{bin_element,{sl,Seg,Line},Expr,Size,Type}|bin_elements(Es, Seg+1)];
+bin_elements([], _) -> [].
-make_bit_type(Line, default, Type0) ->
+make_bit_type(Line, default, Type0, _Context) ->
case erl_bits:set_bit_type(default, Type0) of
{ok,all,Bt} -> {make_all_size(Line),erl_bits:as_list(Bt)};
{ok,undefined,Bt} -> {{atom,Line,undefined},erl_bits:as_list(Bt)};
{ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)}
end;
-make_bit_type(_Line, {atom,Anno,all}=Size, Type0) ->
+make_bit_type(_Line, {atom,Anno,all}=Size, Type0, Context) ->
+ {ok,Size,Bt} = erl_bits:set_bit_type(Size, Type0),
+ Type = erl_bits:as_list(Bt),
case erl_anno:generated(Anno) of
true ->
%% This `all` was created by the compiler from a binary
%% segment without a size.
- {ok,Size,Bt} = erl_bits:set_bit_type(Size, Type0),
- {Size,erl_bits:as_list(Bt)};
+ {Size,Type};
false ->
%% This `all` was present in the source code. It is not
%% a valid size.
- throw(nomatch)
+ case Context of
+ matching ->
+ throw(nomatch);
+ construction ->
+ {{atom,Anno,bad_size},Type}
+ end
end;
-make_bit_type(_Line, Size0, Type0) -> %Integer or 'all'
+make_bit_type(_Line, Size0, Type0, _Context) ->
{ok,Size1,Bt} = erl_bits:set_bit_type(Size0, Type0),
Size = case Size1 of
{char,Anno,CharVal} -> {integer,Anno,CharVal};
@@ -1392,8 +1542,12 @@ bin_expand_string([H|T], Line, Val, Size, Last) ->
bin_expand_string([], Line, Val, Size, Last) ->
[make_combined(Line, Val, Size) | Last].
-make_combined(Line, Val, Size) ->
- {bin_element,Line,{integer,Line,Val},
+make_combined(SegLine, Val, Size) ->
+ Line = case SegLine of
+ {sl,_,Line0} -> Line0;
+ _ -> SegLine
+ end,
+ {bin_element,SegLine,{integer,Line,Val},
{integer,Line,Size},
[integer,{unit,1},unsigned,big]}.
@@ -1777,6 +1931,33 @@ force_novars(#c_map{}=Bin, St) -> {Bin,[],St};
force_novars(Ce, St) ->
force_safe(Ce, St).
+
+%% safe_list(Expr, State) -> {Safe,[PreExpr],State}.
+%% Generate an internal safe expression for a list of
+%% expressions.
+
+safe_list(Es, St0) ->
+ {Vs,Eps0,St} =
+ foldr(fun (E, {Ces,Eps,Sti0}) ->
+ {Ce,Ep,Sti1} = safe(E, Sti0),
+ case Eps of
+ [[#iexprs{bodies=Bs}]|T] ->
+ %% A cons within a cons.
+ {[Ce|Ces],[Ep|Bs]++T,Sti1};
+ _ ->
+ {[Ce|Ces],[Ep|Eps],Sti1}
+ end
+ end, {[],[],St0}, Es),
+ case [Ep || [_|_]=Ep <- Eps0] of
+ [] ->
+ {Vs,[],St};
+ [Ep] ->
+ {Vs,Ep,St};
+ [_|_]=Eps ->
+ %% Two or more bodies. They see the same variables.
+ {Vs,[#iexprs{bodies=Eps}],St}
+ end.
+
%% safe(Expr, State) -> {Safe,[PreExpr],State}.
%% Generate an internal safe expression. These are simples without
%% binaries which can fail. At this level we do not need to do a
@@ -1787,12 +1968,6 @@ safe(E0, St0) ->
{Se,Sps,St2} = force_safe(E1, St1),
{Se,Eps ++ Sps,St2}.
-safe_list(Es, St) ->
- foldr(fun (E, {Ces,Esp,St0}) ->
- {Ce,Ep,St1} = safe(E, St0),
- {[Ce|Ces],Ep ++ Esp,St1}
- end, {[],[],St}, Es).
-
force_safe(#imatch{pat=P,arg=E}=Imatch, St0) ->
{Le,Lps0,St1} = force_safe(E, St0),
Lps = Lps0 ++ [Imatch#imatch{arg=Le}],
@@ -1838,10 +2013,10 @@ is_safe(_) -> false.
%% fold_match(MatchExpr, Pat) -> {MatchPat,Expr}.
%% Fold nested matches into one match with aliased patterns.
-fold_match({match,L,P0,E0}, P) ->
- {P1,E1} = fold_match(E0, P),
- {{match,L,P0,P1},E1};
-fold_match(E, P) -> {P,E}.
+fold_match({match, L, P, E}, E0) ->
+ fold_match(E, {sequential_match, L, P, E0});
+fold_match(E, E0) ->
+ {E0, E}.
%% pattern(Pattern, State) -> {CorePat,[PreExp],State}.
%% Transform a pattern by removing line numbers. We also normalise
@@ -1955,7 +2130,7 @@ pat_segments([P0|Ps0], St0) ->
pat_segments([], St) -> {[],St}.
pat_segment({bin_element,L,Val,Size0,Type0}, St) ->
- {Size1,Type1} = make_bit_type(L, Size0, Type0),
+ {Size1,Type1} = make_bit_type(L, Size0, Type0, matching),
[Type,{unit,Unit}|Flags] = Type1,
Anno = lineno_anno(L, St),
{Pval0,St1} = pattern(Val, St),
@@ -2092,7 +2267,12 @@ new_vars_1(0, _, St, Vs) -> {Vs,St}.
bad_generator(Ps, Generator, Arg) ->
Anno = get_anno(Arg),
Tuple = ann_c_tuple(Anno, [#c_literal{val=bad_generator},Generator]),
- fail_clause(Ps, Anno, Tuple).
+ Call = #icall{anno=#a{anno=Anno}, %Must have an #a{}
+ module=#c_literal{anno=Anno,val=erlang},
+ name=#c_literal{anno=Anno,val=error},
+ args=[Tuple]},
+ #iclause{anno=#a{anno=[compiler_generated]},
+ pats=Ps,guard=[],body=[Call]}.
function_clause(Ps, LineAnno) ->
fail_clause(Ps, LineAnno,
@@ -2129,7 +2309,155 @@ annotate_cons(A, H, T, #core{dialyzer=Dialyzer}) ->
ann_c_cons(A, H, T)
end.
-ubody(B, St) -> uexpr(B, [], St).
+%%%
+%%% Here follows an abstract data structure to help us handle Erlang's
+%%% implicit matching that occurs when a variable is bound more than
+%%% once:
+%%%
+%%% X = Expr1(),
+%%% X = Expr2()
+%%%
+%%% What is implicit in Erlang, must be explicit in Core Erlang; that
+%%% is, repeated variables must be eliminated and explicit matching
+%%% must be added. For simplicity, examples that follow will be given
+%%% in Erlang and not in Core Erlang. Here is how the example can be
+%%% rewritten in Erlang to eliminate the repeated variable:
+%%%
+%%% X = Expr1(),
+%%% X1 = Expr2(),
+%%% if
+%%% X1 =:= X -> X;
+%%% true -> error({badmatch,X1})
+%%% end
+%%%
+%%% To implement the renaming, keeping a set of the variables that
+%%% have been bound so far is **almost** sufficient. When a variable
+%%% in the set is bound a again, it will be renamed and a `case` with
+%%% guard test will be added.
+%%%
+%%% Here is another example:
+%%%
+%%% (X=A) + (X=B)
+%%%
+%%% Note that the operands for a binary operands are allowed to be
+%%% evaluated in any order. Therefore, variables bound on the left
+%%% hand side must not referenced on the right hand side, and vice
+%%% versa. If a variable is bound on both sides, it must be bound
+%%% to the same value.
+%%%
+%%% Using the simple scheme of keeping track of known variables,
+%%% the example can be rewritten like this:
+%%%
+%%% X = A,
+%%% X1 = B,
+%%% if
+%%% X1 =:= X -> ok;
+%%% true -> error({badmatch,X1})
+%%% end,
+%%% X + X1
+%%%
+%%% However, this simple scheme of keeping all previously bound variables in
+%%% a set breaks down for this example:
+%%%
+%%% (X=A) + fun() -> X = B end()
+%%%
+%%% The rewritten code would be:
+%%%
+%%% X = A,
+%%% Tmp = fun() ->
+%%% X1 = B,
+%%% if
+%%% X1 =:= X -> ok;
+%%% true -> error({badmatch,X1})
+%%% end
+%%% end(),
+%%% X + Tmp
+%%%
+%%% That is wrong, because the binding of `X` created on the left hand
+%%% side of `+` must not be seen inside the fun. The correct rewrite
+%%% would be like this:
+%%%
+%%% X = A,
+%%% Tmp = fun() ->
+%%% X1 = B
+%%% end(),
+%%% X + Tmp
+%%%
+%%% To correctly rewrite fun bodies, we will need to keep addtional
+%%% information in a record so that we can remove `X` from the known
+%%% variables when rewriting the body of the fun.
+%%%
+
+-record(known, {base=[],ks=[],prev_ks=[]}).
+
+known_init() ->
+ #known{}.
+
+%% known_get(#known{}) -> [KnownVar].
+%% Get the currently known variables.
+
+known_get(#known{ks=Ks}) ->
+ Ks.
+
+%% known_start_group(#known{}) -> #known{}.
+
+known_start_group(#known{base=OldBase,ks=Ks,prev_ks=PrevKs}=K) ->
+ K#known{base=[Ks|OldBase],prev_ks=[[]|PrevKs]}.
+
+%% known_end_body(#known{}) -> #known{}.
+
+known_end_body(#known{ks=Ks,prev_ks=[_|OldPrevKs]}=K) ->
+ K#known{prev_ks=[Ks|OldPrevKs]}.
+
+%% known_end_group(#known{}) -> #known{}.
+%% Consolidate the known variables after having processed the
+%% last body in a group of bodies that see the same bindings.
+
+known_end_group(#known{base=[_|OldBase],prev_ks=[_|OldPrevKs]}=K) ->
+ K#known{base=OldBase,prev_ks=OldPrevKs}.
+
+%% known_union(#known{}, KnownVarsSet) -> #known{}.
+%% Update the known variables to be the union of the previous
+%% known variables and the set KnownVarsSet.
+
+known_union(#known{ks=Ks}=K, Set) ->
+ K#known{ks=union(Ks, Set)}.
+
+%% known_bind(#known{}, BoundVarsSet) -> #known{}.
+%% Add variables that are known to be bound in the current
+%% body.
+
+known_bind(#known{prev_ks=[PrevKs0|OldPrevKs]}=K, BoundVs) ->
+ PrevKs = subtract(PrevKs0, BoundVs),
+ K#known{prev_ks=[PrevKs|OldPrevKs]};
+known_bind(#known{}=K, _) -> K.
+
+%% known_in_fun(#known{}) -> #known{}.
+%% Update the known variables to only the set of variables that
+%% should be known when entering the fun.
+
+known_in_fun(#known{base=[BaseKs|_],ks=Ks0,prev_ks=[PrevKs|_]}=K) ->
+ %% Within a group of bodies that see the same bindings, calculate
+ %% the known variables for a fun. Example:
+ %%
+ %% A = 1,
+ %% {X = 2, fun() -> X = 99, A = 1 end()}.
+ %%
+ %% In this example:
+ %%
+ %% BaseKs = ['A'], Ks0 = ['A','X'], PrevKs = ['A','X']
+ %%
+ %% Thus, only `A` is known when entering the fun.
+
+ Ks = union(BaseKs, subtract(Ks0, PrevKs)),
+ K#known{base=[],ks=Ks,prev_ks=[]};
+known_in_fun(#known{}=K) -> K.
+
+%%%
+%%% End of abstract data type for known variables.
+%%%
+
+ubody(B, St) -> uexpr(B, known_init(), St).
%% ufun_clauses([Lclause], [KnownVar], State) -> {[Lclause],State}.
@@ -2189,15 +2517,41 @@ do_uclause(#iclause{anno=A0,pats=Ps0,guard=G0,body=B0}, Ks0, St0) ->
false ->
{Pg0,A0}
end,
- Pu = union(Pus, intersection(Pvs, Ks0)),
+ Pu = union(Pus, intersection(Pvs, known_get(Ks0))),
Pn = subtract(Pvs, Pu),
- Ks1 = union(Pn, Ks0),
+ Ks1 = known_union(Ks0, Pn),
{G1,St2} = uguard(Pg, G0, Ks1, St1),
Gu = used_in_any(G1),
Gn = new_in_any(G1),
- Ks2 = union(Gn, Ks1),
- {B1,St3} = uexprs(B0, Ks2, St2),
- Used = intersection(union([Pu,Gu,used_in_any(B1)]), Ks0),
+ Ks2 = known_union(Ks1, Gn),
+
+ %% Consider this example:
+ %%
+ %% {X = A,
+ %% begin X = B, fun() -> X = C end() end}.
+ %%
+ %% At this point it has been rewritten to something similar
+ %% like this (the fun body has not been rewritten yet):
+ %%
+ %% {X = A,
+ %% begin
+ %% X1 = B,
+ %% if
+ %% X1 =:= X -> ok;
+ %% true -> error({badmatch,X1})
+ %% end,
+ %% fun() -> ... end() end
+ %% end}.
+ %%
+ %% In this example, the variable `X` is a known variable that must
+ %% be passed into the fun body (because of `X = B` above). To ensure
+ %% that it is, we must call known_bind/2 with the variables used
+ %% in the guard (`X1` and `X`; any variables used must surely be
+ %% bound).
+
+ Ks3 = known_bind(Ks2, Gu),
+ {B1,_,St3} = uexprs(B0, Ks3, St2),
+ Used = intersection(union([Pu,Gu,used_in_any(B1)]), known_get(Ks0)),
New = union([Pn,Gn,new_in_any(B1)]),
{#iclause{anno=A,pats=Ps1,guard=G1,body=B1},Pvs,Used,New,St3}.
@@ -2222,10 +2576,31 @@ uguard(Pg, Gs0, Ks, St0) ->
St3}
end, {Gs0,St0}, Pg),
%%ok = io:fwrite("core ~w: ~p~n", [?LINE,Gs3]),
- uexprs(Gs3, Ks, St5).
+ {Gs4,_,St6} = uexprs(Gs3, Ks, St5),
+ {Gs4,St6}.
+
+%% ulinearize_exprs([[Kexpr]], [Kexpr]) -> [Kexpr].
+%% Linearize a group of bodies to a linear list of Kernel expressions
+%% while inserting markers for the end of each body and the group
+%% itself.
+
+ulinearize_exprs([Bs|Bss], Les) ->
+ [known_end_body|Bs] ++ ulinearize_exprs(Bss, Les);
+ulinearize_exprs([], Les) ->
+ [known_end_group|Les].
%% uexprs([Kexpr], [KnownVar], State) -> {[Kexpr],State}.
+uexprs([known_end_body|Les], Ks0, St0) ->
+ Ks1 = known_end_body(Ks0),
+ uexprs(Les, Ks1, St0);
+uexprs([known_end_group|Les], Ks0, St0) ->
+ Ks1 = known_end_group(Ks0),
+ uexprs(Les, Ks1, St0);
+uexprs([#iexprs{bodies=Es0}|Les], Ks0, St0) ->
+ Es = ulinearize_exprs(Es0, Les),
+ Ks1 = known_start_group(Ks0),
+ uexprs(Es, Ks1, St0);
uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) ->
case upat_is_new_var(P0, Ks) of
true ->
@@ -2244,18 +2619,54 @@ uexprs([#imatch{anno=A,pat=P0,arg=Arg,fc=Fc}|Les], Ks, St0) ->
uexprs([#icase{anno=A,args=[Arg],
clauses=[Mc],fc=Fc}], Ks, St0)
end;
-uexprs([Le0|Les0], Ks, St0) ->
- {Le1,St1} = uexpr(Le0, Ks, St0),
- {Les1,St2} = uexprs(Les0, union((get_anno(Le1))#a.ns, Ks), St1),
- {[Le1|Les1],St2};
-uexprs([], _, St) -> {[],St}.
+uexprs([#iset{}|_]=Les0, Ks0, St0) ->
+ uexprs_iset(Les0, [], Ks0, St0);
+uexprs([Le0|Les0], Ks0, St0) ->
+ {Le1,St1} = uexpr(Le0, Ks0, St0),
+ {Les1,Ks,St2} = uexprs(Les0, known_union(Ks0, (get_anno(Le1))#a.ns), St1),
+ {[Le1|Les1],Ks,St2};
+uexprs([], Ks, St) -> {[],Ks,St}.
+
+%% Since the set of known variables can grow quite large, try minimize
+%% the number of union operations on it.
+uexprs_iset([#iset{anno=A0,var=V,arg=Arg0}=Le0|Les0], New0, Ks0, St0) ->
+ case uexpr_need_known(Arg0) of
+ true ->
+ Ks1 = known_union(Ks0, New0),
+ {Le1,St1} = uexpr(Le0, Ks1, St0),
+ New = (get_anno(Le1))#a.ns,
+ {Les1,Ks,St2} = uexprs_iset(Les0, New, Ks1, St1),
+ {[Le1|Les1],Ks,St2};
+ false ->
+ %% We don't need the set of known variables when processing
+ %% Arg0, so we can postpone the call to known_union/2. This
+ %% will save time for functions with a huge number of variables.
+ {Arg,St1} = uexpr(Arg0, none, St0),
+ #a{us=Us,ns=Ns} = get_anno(Arg),
+ A = A0#a{us=del_element(V#c_var.name, Us),
+ ns=add_element(V#c_var.name, Ns)},
+ Le1 = Le0#iset{anno=A,arg=Arg},
+ New = union(New0, A#a.ns),
+ {Les1,Ks,St2} = uexprs_iset(Les0, New, Ks0, St1),
+ {[Le1|Les1],Ks,St2}
+ end;
+uexprs_iset(Les, New, Ks0, St) ->
+ Ks = known_union(Ks0, New),
+ uexprs(Les, Ks, St).
+
+uexpr_need_known(#icall{}) -> false;
+uexpr_need_known(#iapply{}) -> false;
+uexpr_need_known(#ibinary{}) -> false;
+uexpr_need_known(#iprimop{}) -> false;
+uexpr_need_known(#c_literal{}) -> false;
+uexpr_need_known(Core) -> not is_simple(Core).
%% upat_is_new_var(Pattern, [KnownVar]) -> true|false.
%% Test whether the pattern is a single, previously unknown
%% variable.
upat_is_new_var(#c_var{name=V}, Ks) ->
- not is_element(V, Ks);
+ not is_element(V, known_get(Ks));
upat_is_new_var(_, _) ->
false.
@@ -2283,7 +2694,7 @@ uexpr(#iletrec{anno=A,defs=Fs0,body=B0}, Ks, St0) ->
{F1,S1} = uexpr(F0, Ks, S0),
{{Name,F1},S1}
end, St0, Fs0),
- {B1,St2} = uexprs(B0, Ks, St1),
+ {B1,_,St2} = uexprs(B0, Ks, St1),
Used = used_in_any(map(fun ({_,F}) -> F end, Fs1) ++ B1),
{#iletrec{anno=A#a{us=Used,ns=[]},defs=Fs1,body=B1},St2};
uexpr(#icase{anno=#a{anno=Anno}=A,args=As0,clauses=Cs0,fc=Fc0}, Ks, St0) ->
@@ -2298,7 +2709,7 @@ uexpr(#icase{anno=#a{anno=Anno}=A,args=As0,clauses=Cs0,fc=Fc0}, Ks, St0) ->
end,
{#icase{anno=A#a{us=Used,ns=New},args=As1,clauses=Cs1,fc=Fc1},St3};
uexpr(#ifun{anno=A0,id=Id,vars=As,clauses=Cs0,fc=Fc0,name=Name}=Fun0, Ks0, St0) ->
- {Fun1,St2} = case Ks0 of
+ {Fun1,St2} = case known_get(Ks0) of
[] ->
{Fun0,St0};
[_|_] ->
@@ -2309,12 +2720,13 @@ uexpr(#ifun{anno=A0,id=Id,vars=As,clauses=Cs0,fc=Fc0,name=Name}=Fun0, Ks0, St0)
Avs = lit_list_vars(As),
Ks1 = case Name of
unnamed -> Ks0;
- {named,FName} -> union(subtract([FName], Avs), Ks0)
+ {named,FName} -> known_union(Ks0, subtract([FName], Avs))
end,
- Ks2 = union(Avs, Ks1),
- {Cs3,St3} = ufun_clauses(Cs2, Ks2, St2),
- {Fc1,St4} = ufun_clause(Fc0, Ks2, St3),
- Used = subtract(intersection(used_in_any(Cs3), Ks1), Avs),
+ Ks2 = known_union(Ks1, Avs),
+ KnownInFun = known_in_fun(Ks2),
+ {Cs3,St3} = ufun_clauses(Cs2, KnownInFun, St2),
+ {Fc1,St4} = ufun_clause(Fc0, KnownInFun, St3),
+ Used = subtract(intersection(used_in_any(Cs3), known_get(Ks1)), Avs),
A1 = A0#a{us=Used,ns=[]},
{#ifun{anno=A1,id=Id,vars=As,clauses=Cs3,fc=Fc1,name=Name},St4};
uexpr(#iapply{anno=A,op=Op,args=As}, _, St) ->
@@ -2331,15 +2743,15 @@ uexpr(#itry{anno=A,args=As0,vars=Vs,body=Bs0,evars=Evs,handler=Hs0}, Ks, St0) ->
%% variables bound in the argument (the code between the 'try' and
%% the 'of' keywords) are exported to the body (the code following
%% the 'of' keyword).
- {As1,St1} = uexprs(As0, Ks, St0),
- ArgKs = union(Ks, new_in_any(As1)),
- {Bs1,St2} = uexprs(Bs0, ArgKs, St1),
- {Hs1,St3} = uexprs(Hs0, Ks, St2),
- Used = intersection(used_in_any(Bs1++Hs1++As1), Ks),
+ {As1,_,St1} = uexprs(As0, Ks, St0),
+ ArgKs = known_union(Ks, new_in_any(As1)),
+ {Bs1,_,St2} = uexprs(Bs0, ArgKs, St1),
+ {Hs1,_,St3} = uexprs(Hs0, Ks, St2),
+ Used = intersection(used_in_any(Bs1++Hs1++As1), known_get(Ks)),
{#itry{anno=A#a{us=Used,ns=[]},
args=As1,vars=Vs,body=Bs1,evars=Evs,handler=Hs1},St3};
uexpr(#icatch{anno=A,body=Es0}, Ks, St0) ->
- {Es1,St1} = uexprs(Es0, Ks, St0),
+ {Es1,_,St1} = uexprs(Es0, Ks, St0),
{#icatch{anno=A#a{us=used_in_any(Es1)},body=Es1},St1};
uexpr(#ireceive1{anno=A,clauses=Cs0}, Ks, St0) ->
{Cs1,St1} = uclauses(Cs0, Ks, St0),
@@ -2349,7 +2761,7 @@ uexpr(#ireceive2{anno=A,clauses=Cs0,timeout=Te0,action=Tes0}, Ks, St0) ->
%% Te0 will never generate new variables.
{Te1,St1} = uexpr(Te0, Ks, St0),
{Cs1,St2} = uclauses(Cs0, Ks, St1),
- {Tes1,St3} = uexprs(Tes0, Ks, St2),
+ {Tes1,_,St3} = uexprs(Tes0, Ks, St2),
Used = union([used_in_any(Cs1),used_in_any(Tes1),(get_anno(Te1))#a.us]),
New = case Cs1 of
[] -> new_in_any(Tes1);
@@ -2358,7 +2770,7 @@ uexpr(#ireceive2{anno=A,clauses=Cs0,timeout=Te0,action=Tes0}, Ks, St0) ->
{#ireceive2{anno=A#a{us=Used,ns=New},
clauses=Cs1,timeout=Te1,action=Tes1},St3};
uexpr(#iprotect{anno=A,body=Es0}, Ks, St0) ->
- {Es1,St1} = uexprs(Es0, Ks, St0),
+ {Es1,_,St1} = uexprs(Es0, Ks, St0),
Used = used_in_any(Es1),
{#iprotect{anno=A#a{us=Used},body=Es1},St1}; %No new variables escape!
uexpr(#ibinary{anno=A,segments=Ss}, _, St) ->
@@ -2383,7 +2795,7 @@ upattern(#c_var{name='_'}, _, St0) ->
{New,St1} = new_var_name(St0),
{#c_var{name=New},[],[New],[],St1};
upattern(#c_var{name=V}=Var, Ks, St0) ->
- case is_element(V, Ks) of
+ case is_element(V, known_get(Ks)) of
true ->
{N,St1} = new_var_name(St0),
New = #c_var{name=N},
@@ -2398,7 +2810,7 @@ upattern(#c_var{name=V}=Var, Ks, St0) ->
end;
upattern(#c_cons{hd=H0,tl=T0}=Cons, Ks, St0) ->
{H1,Hg,Hv,Hu,St1} = upattern(H0, Ks, St0),
- {T1,Tg,Tv,Tu,St2} = upattern(T0, union(Hv, Ks), St1),
+ {T1,Tg,Tv,Tu,St2} = upattern(T0, known_union(Ks, Hv), St1),
{Cons#c_cons{hd=H1,tl=T1},Hg ++ Tg,union(Hv, Tv),union(Hu, Tu),St2};
upattern(#c_tuple{es=Es0}=Tuple, Ks, St0) ->
{Es1,Esg,Esv,Eus,St1} = upattern_list(Es0, Ks, St0),
@@ -2408,7 +2820,7 @@ upattern(#imap{es=Es0}=Map, Ks, St0) ->
{Map#imap{es=Es1},Esg,Esv,Eus,St1};
upattern(#imappair{op=#c_literal{val=exact},key=K0,val=V0}=Pair,Ks,St0) ->
{V,Vg,Vn,Vu,St1} = upattern(V0, Ks, St0),
- {K,St2} = uexprs(K0, Ks, St1),
+ {K,_,St2} = uexprs(K0, Ks, St1),
Ku = used_in_expr(K),
{Pair#imappair{key=K,val=V},Vg,Vn,union(Ku, Vu),St2};
upattern(#ibinary{segments=Es0}=Bin, Ks, St0) ->
@@ -2416,7 +2828,7 @@ upattern(#ibinary{segments=Es0}=Bin, Ks, St0) ->
{Bin#ibinary{segments=Es1},Esg,Esv,Eus,St1};
upattern(#c_alias{var=V0,pat=P0}=Alias, Ks, St0) ->
{V1,Vg,Vv,Vu,St1} = upattern(V0, Ks, St0),
- {P1,Pg,Pv,Pu,St2} = upattern(P0, union(Vv, Ks), St1),
+ {P1,Pg,Pv,Pu,St2} = upattern(P0, known_union(Ks, Vv), St1),
{Alias#c_alias{var=V1,pat=P1},Vg ++ Pg,union(Vv, Pv),union(Vu, Pu),St2};
upattern(Other, _, St) -> {Other,[],[],[],St}. %Constants
@@ -2425,7 +2837,7 @@ upattern(Other, _, St) -> {Other,[],[],[],St}. %Constants
upattern_list([P0|Ps0], Ks, St0) ->
{P1,Pg,Pv,Pu,St1} = upattern(P0, Ks, St0),
- {Ps1,Psg,Psv,Psu,St2} = upattern_list(Ps0, union(Pv, Ks), St1),
+ {Ps1,Psg,Psv,Psu,St2} = upattern_list(Ps0, known_union(Ks, Pv), St1),
{[P1|Ps1],Pg ++ Psg,union(Pv, Psv),union(Pu, Psu),St2};
upattern_list([], _, St) -> {[],[],[],[],St}.
@@ -2452,7 +2864,7 @@ upat_bin(Es0, Ks, St0) ->
%% {[Pat],[GuardTest],[NewVar],[UsedVar],State}.
upat_bin([P0|Ps0], Ks, Bs, St0) ->
{P1,Pg,Pv,Pu,Bs1,St1} = upat_element(P0, Ks, Bs, St0),
- {Ps1,Psg,Psv,Psu,St2} = upat_bin(Ps0, union(Pv, Ks), Bs1, St1),
+ {Ps1,Psg,Psv,Psu,St2} = upat_bin(Ps0, known_union(Ks, Pv), Bs1, St1),
{[P1|Ps1],Pg ++ Psg,union(Pv, Psv),union(Pu, Psu),St2};
upat_bin([], _, _, St) -> {[],[],[],[],St}.
@@ -2475,16 +2887,16 @@ upat_element(#ibitstr{val=H0,size=Sz0}=Seg, Ks, Bs0, St0) ->
case Sz0 of
[#c_var{name=Vname}] ->
{Sz1,Us} = rename_bitstr_size(Vname, Bs0),
- {Sz2,St2} = uexprs([Sz1], Ks, St1),
+ {Sz2,_,St2} = uexprs([Sz1], Ks, St1),
{Seg#ibitstr{val=H1,size=Sz2},Hg,Hv,Us,Bs1,St2};
[#c_literal{}] ->
- {Sz1,St2} = uexprs(Sz0, Ks, St1),
+ {Sz1,_,St2} = uexprs(Sz0, Ks, St1),
Us = [],
{Seg#ibitstr{val=H1,size=Sz1},Hg,Hv,Us,Bs1,St2};
Expr when is_list(Expr) ->
Sz1 = [#iset{var=#c_var{name=Old},arg=#c_var{name=New}} ||
{Old,New} <- Bs0] ++ Expr,
- {Sz2,St2} = uexprs(Sz1, Ks, St1),
+ {Sz2,_,St2} = uexprs(Sz1, Ks, St1),
Us = used_in_expr(Sz2),
{Seg#ibitstr{val=H1,size=Sz2},Hg,Hv,Us,Bs1,St2}
end.
@@ -2558,7 +2970,7 @@ ren_pats([], _Ks, {_,_}=Subs, St) ->
ren_pat(#c_var{name='_'}=P, _Ks, Subs, St) ->
{P,Subs,St};
ren_pat(#c_var{name=V}=Old, Ks, {Isub0,Osub0}=Subs, St0) ->
- case member(V, Ks) of
+ case member(V, known_get(Ks)) of
true ->
case ren_is_subst(V, Osub0) of
{yes,New} ->
@@ -2630,9 +3042,19 @@ ren_is_subst(_V, []) -> no.
%% from case/receive. In subblocks/clauses the AfterVars of the block
%% are just the exported variables.
-cbody(B0, St0) ->
+cbody(B0, Nifs, St0) ->
{B1,_,_,St1} = cexpr(B0, [], St0),
- {B1,St1}.
+ B2 = case sets:is_element(St1#core.function,Nifs) of
+ true ->
+ #c_fun{body=Body0} = B1,
+ Body1 = #c_seq{arg=#c_primop{name=#c_literal{val=nif_start},
+ args=[]},
+ body=Body0},
+ B1#c_fun{body=Body1};
+ false ->
+ B1
+ end,
+ {B2,St1}.
%% cclause(Lclause, [AfterVar], State) -> {Cclause,State}.
%% The AfterVars are the exported variables.
@@ -2916,8 +3338,7 @@ c_add_dummy_export(C, [], St) ->
%%% primop 'recv_wait_timeout'(Timeout)
%%% in case TimedOut of
%%% <'true'> when 'true' ->
-%%% do primop 'timeout'()
-%%% 'no_message'
+%%% 'no_message'
%%% <'false'> when 'true' ->
%%% apply 'recv$^0'/0()
%%% end
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 79352e33ad..febc971427 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -78,10 +78,9 @@
-export([module/2,format_error/1]).
-import(lists, [all/2,droplast/1,flatten/1,foldl/3,foldr/3,
- map/2,mapfoldl/3,member/2,
- keyfind/3,keyreplace/4,
- last/1,partition/2,reverse/1,
- sort/1,sort/2,splitwith/2]).
+ map/2,mapfoldl/3,member/2,keyfind/3,last/1,
+ partition/2,reverse/1,sort/1,sort/2,
+ splitwith/2]).
-import(ordsets, [add_element/2,intersection/2,
subtract/2,union/2,union/1]).
@@ -234,25 +233,19 @@ gexpr_test_add(Ke, St0) ->
%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
%% Convert a Core expression, flattening it at the same time.
-expr(#c_var{anno=A0,name={Name,Arity}}=Fname, Sub, St) ->
- Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
- V <- integers(1, Arity)],
+expr(#c_var{anno=A,name={Name0,Arity}}=Fname, Sub, St) ->
case St#kern.no_shared_fun_wrappers of
false ->
- %% Generate a (possibly shared) wrapper function for calling
- %% this function.
- Wrapper0 = ["-fun.",atom_to_list(Name),"/",integer_to_list(Arity),"-"],
- Wrapper = list_to_atom(flatten(Wrapper0)),
- Id = {id,{0,0,Wrapper}},
- A = keyreplace(id, 1, A0, Id),
- Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
- expr(Fun, Sub, St);
+ Name = get_fsub(Name0, Arity, Sub),
+ {#k_local{anno=A,name=Name,arity=Arity},[],St};
true ->
%% For backward compatibility with OTP 22 and earlier,
%% use the pre-generated name for the fun wrapper.
%% There will be one wrapper function for each occurrence
%% of `fun F/A`.
- Fun = #c_fun{anno=A0,vars=Vs,body=#c_apply{anno=A0,op=Fname,args=Vs}},
+ Vs = [#c_var{name=list_to_atom("V" ++ integer_to_list(V))} ||
+ V <- integers(1, Arity)],
+ Fun = #c_fun{anno=A,vars=Vs,body=#c_apply{anno=A,op=Fname,args=Vs}},
expr(Fun, Sub, St)
end;
expr(#c_var{anno=A,name=V}, Sub, St) ->
@@ -337,7 +330,7 @@ expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) ->
{#k_call{anno=A,op=Remote,args=Kargs},Ap,St1};
error ->
%% Invalid call (e.g. M:42/3). Issue a warning, and let
- %% the generated code use the old explict apply.
+ %% the generated code use the old explicit apply.
St = add_warning(get_location(A), {failed,bad_call}, A, St0),
Call = #c_call{anno=A,
module=#c_literal{val=erlang},
@@ -392,57 +385,74 @@ letrec_local_function(A, Cfs, Cb, Sub0, St0) ->
%% Implement letrec with the single definition as a label and each
%% apply of it as a goto.
-letrec_goto([{#c_var{name={Label,0}},Cfail}], Cb, Sub0,
+letrec_goto([{#c_var{name={Label,_Arity}},Cfail}], Cb, Sub0,
#kern{labels=Labels0}=St0) ->
+ #c_fun{vars=FunVars,body=FunBody} = Cfail,
+ {Kvars,{FunSub,St1}} =
+ mapfoldl(fun(#c_var{anno=A,name=V}, {SubInt,StInt0}) ->
+ {New,StInt1} = new_var_name(StInt0),
+ {#k_var{anno=A,name=New},
+ {set_vsub(V, New, SubInt),
+ StInt1#kern{ds=sets:add_element(New, StInt1#kern.ds)}}}
+ end, {Sub0,St0}, FunVars),
Labels = sets:add_element(Label, Labels0),
- {Kb,Pb,St1} = body(Cb, Sub0, St0#kern{labels=Labels}),
- #c_fun{body=FailBody} = Cfail,
- {Kfail,Fb,St2} = body(FailBody, Sub0, St1),
+ {Kb,Pb,St2} = body(Cb, Sub0, St1#kern{labels=Labels}),
+ {Kfail,Fb,St3} = body(FunBody, FunSub, St2),
case {Kb,Kfail,Fb} of
{#k_goto{label=Label},#k_goto{}=InnerGoto,[]} ->
- {InnerGoto,Pb,St2};
+ {InnerGoto,Pb,St3};
{_,_,_} ->
- St3 = St2#kern{labels=Labels0},
- Alt = #k_letrec_goto{label=Label,first=Kb,then=pre_seq(Fb, Kfail)},
- {Alt,Pb,St3}
+ St4 = St3#kern{labels=Labels0},
+ Alt = #k_letrec_goto{label=Label,vars=Kvars,
+ first=Kb,then=pre_seq(Fb, Kfail)},
+ {Alt,Pb,St4}
end.
%% translate_match_fail(Arg, Sub, Anno, St) -> {Kexpr,[PreKexpr],State}.
-%% Translate a match_fail primop to a call erlang:error/1 or
-%% erlang:error/2.
+%% Translate match_fail primops, paying extra attention to `function_clause`
+%% errors that may have been inlined from other functions.
translate_match_fail(Arg, Sub, Anno, St0) ->
- Cargs = case {cerl:data_type(Arg),cerl:data_es(Arg)} of
- {tuple,[#c_literal{val=function_clause}|As]} ->
- translate_fc_args(As, Sub, St0);
- {_,_} ->
- [Arg]
- end,
- {Kargs,Ap,St} = atomic_list(Cargs, Sub, St0),
+ {Cargs,ExtraAnno,St1} =
+ case {cerl:data_type(Arg),cerl:data_es(Arg)} of
+ {tuple,[#c_literal{val=function_clause} | _]=As} ->
+ translate_fc_args(As, Sub, Anno, St0);
+ {tuple,[#c_literal{} | _]=As} ->
+ {As,[],St0};
+ {{atomic,Reason}, []} ->
+ {[#c_literal{val=Reason}],[],St0}
+ end,
+ {Kargs,Ap,St} = atomic_list(Cargs, Sub, St1),
Ar = length(Cargs),
- Call = #k_call{anno=Anno,
- op=#k_remote{mod=#k_literal{val=erlang},
- name=#k_literal{val=error},
- arity=Ar},args=Kargs},
- {Call,Ap,St}.
-
-translate_fc_args(As, Sub, #kern{fargs=Fargs}) ->
- case same_args(As, Fargs, Sub) of
- true ->
- %% The arguments for the `function_clause` exception are
- %% the arguments for the current function in the correct
- %% order.
- [#c_literal{val=function_clause},cerl:make_list(As)];
- false ->
- %% The arguments in the `function_clause` exception don't
- %% match the arguments for the current function because
- %% of inlining. Keeping the `function_clause`
- %% exception reason would be confusing. Rewrite it to
- %% a `case_clause` exception with the arguments in a
- %% tuple.
- [cerl:c_tuple([#c_literal{val=case_clause},
- cerl:c_tuple(As)])]
- end.
+ Primop = #k_bif{anno=ExtraAnno ++ Anno,
+ op=#k_internal{name=match_fail,arity=Ar},
+ args=Kargs},
+ {Primop,Ap,St}.
+
+translate_fc_args(As, Sub, Anno, #kern{fargs=Fargs}=St0) ->
+ {ExtraAnno, St} =
+ case same_args(As, Fargs, Sub) of
+ true ->
+ %% The arguments for the `function_clause` exception are
+ %% the arguments for the current function in the correct
+ %% order.
+ {[], St0};
+ false ->
+ %% The arguments in the `function_clause` exception don't
+ %% match the arguments for the current function because of
+ %% inlining.
+ case keyfind(function, 1, Anno) of
+ false ->
+ {Name, St1} = new_fun_name("inlined", St0),
+ {[{inlined,{Name,length(As) - 1}}], St1};
+ {_,{Name0,Arity}} ->
+ %% This is function that has been inlined.
+ Name1 = ["-inlined-",Name0,"/",Arity,"-"],
+ Name = list_to_atom(lists:concat(Name1)),
+ {[{inlined,{Name,Arity}}], St0}
+ end
+ end,
+ {As, ExtraAnno, St}.
same_args([#c_var{name=Cv}|Vs], [#k_var{name=Kv}|As], Sub) ->
get_vsub(Cv, Sub) =:= Kv andalso same_args(Vs, As, Sub);
@@ -559,10 +569,11 @@ match_vars(Ka, St0) ->
%% Transform application.
c_apply(A, #c_var{anno=Ra,name={F0,Ar}}, Cargs, Sub, #kern{labels=Labels}=St0) ->
- case Ar =:= 0 andalso sets:is_element(F0, Labels) of
+ case sets:is_element(F0, Labels) of
true ->
%% This is a goto to a label in a letrec_goto construct.
- {#k_goto{label=F0},[],St0};
+ {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
+ {#k_goto{label=F0,args=Kargs},Ap,St1};
false ->
{Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0),
F1 = get_fsub(F0, Ar, Sub), %Has it been rewritten
@@ -1216,7 +1227,7 @@ expand_pat_lit(Lit, A) ->
%% comparing with the literal (that is especially true for binaries).
%%
%% It is important not to do this transformation for atomic literals
-%% (such as `[]`), since that would cause the test for an emtpy list
+%% (such as `[]`), since that would cause the test for an empty list
%% to be executed before the test for a nonempty list.
opt_single_valued(Ttcs) ->
@@ -1610,7 +1621,7 @@ new_clauses(Cs0, U, St) ->
%% will be grouped next.
%%
%% We also try to not create too large groups. If we have too many clauses,
-%% it is preferrable to match on 8-bits, select a branch, then match on the
+%% it is preferable to match on 8-bits, select a branch, then match on the
%% next 8-bits, rather than match on 16-bits which would force us to have
%% to select to many values at the same time, which would not be efficient.
%%
@@ -1823,8 +1834,9 @@ ubody(#ivalues{anno=A,args=As}, return, St) ->
ubody(#ivalues{anno=A,args=As}, {break,_Vbs}, St) ->
Au = lit_list_vars(As),
{#k_break{anno=A,args=As},Au,St};
-ubody(#k_goto{}=Goto, _Br, St) ->
- {Goto,[],St};
+ubody(#k_goto{args=As}=Goto, _Br, St) ->
+ Au = lit_list_vars(As),
+ {Goto,Au,St};
ubody(E, return, St0) ->
%% Enterable expressions need no trailing return.
case is_enter_expr(E) of
@@ -1991,11 +2003,21 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
args=[Local|Fvs],
ret=Rs},
Free,add_local_function(Fun, St)};
-uexpr(#k_letrec_goto{anno=A,first=F0,then=T0}=MatchAlt, Br, St0) ->
+uexpr(#k_local{anno=A,name=Name,arity=Arity}, {break,Rs}, St) ->
+ Free = lit_list_vars(get_free(Name, Arity, St)),
+ Fvs = make_vars(Free),
+ FreeCount = length(Fvs),
+ Bif = #k_bif{anno=A,
+ op=#k_internal{name=make_fun,arity=FreeCount+1},
+ args=[#k_local{name=Name,arity=Arity+FreeCount} | Fvs],
+ ret=Rs},
+ {Bif,Free,St};
+uexpr(#k_letrec_goto{anno=A,vars=Vs,first=F0,then=T0}=MatchAlt, Br, St0) ->
Rs = break_rets(Br),
+ Ns = lit_list_vars(Vs),
{F1,Fu,St1} = ubody(F0, Br, St0),
{T1,Tu,St2} = ubody(T0, Br, St1),
- Used = union(Fu, Tu),
+ Used = subtract(union(Fu, Tu), Ns),
{MatchAlt#k_letrec_goto{anno=A,first=F1,then=T1,ret=Rs},Used,St2};
uexpr(Lit, {break,Rs0}, St0) ->
%% Transform literals to puts here.
@@ -2048,13 +2070,16 @@ break_rets(return) -> [].
%% bif_returns(Op, [Ret], State) -> {[Ret],State}.
-bif_returns(#k_remote{mod=M,name=N,arity=Ar}, Rs, St0) ->
- %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{M,N,Ar,Rs}]),
- {Ns,St1} = new_vars(bif_vals(M, N, Ar) - length(Rs), St0),
- {Rs ++ Ns,St1};
+bif_returns(#k_internal{name=match_fail}, Rs, St) ->
+ %% This is only used for effect, and may have any number of returns.
+ {Rs,St};
bif_returns(#k_internal{name=N,arity=Ar}, Rs, St0) ->
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{N,Ar,Rs}]),
{Ns,St1} = new_vars(bif_vals(N, Ar) - length(Rs), St0),
+ {Rs ++ Ns,St1};
+bif_returns(#k_remote{mod=M,name=N,arity=Ar}, Rs, St0) ->
+ %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,{M,N,Ar,Rs}]),
+ {Ns,St1} = new_vars(bif_vals(M, N, Ar) - length(Rs), St0),
{Rs ++ Ns,St1}.
%% ensure_return_vars([Ret], State) -> {[Ret],State}.
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index 76987640e8..8d3e5dd7e7 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -56,8 +56,8 @@
-record(k_try_enter, {anno=[],arg,vars,body,evars,handler}).
-record(k_catch, {anno=[],body,ret=[]}).
--record(k_letrec_goto, {anno=[],label,first,then,ret=[]}).
--record(k_goto, {anno=[],label}).
+-record(k_letrec_goto, {anno=[],label,vars=[],first,then,ret=[]}).
+-record(k_goto, {anno=[],label,args=[]}).
-record(k_match, {anno=[],body,ret=[]}).
-record(k_alt, {anno=[],first,then}).
diff --git a/lib/compiler/src/v3_kernel_pp.erl b/lib/compiler/src/v3_kernel_pp.erl
index 2c2bd498a9..d1b075ce0f 100644
--- a/lib/compiler/src/v3_kernel_pp.erl
+++ b/lib/compiler/src/v3_kernel_pp.erl
@@ -173,10 +173,11 @@ format_1(#k_alt{first=O,then=T}, Ctxt) ->
format(O, Ctxt1),
nl_indent(Ctxt1),
format(T, Ctxt1)];
-format_1(#k_letrec_goto{label=Label,first=First,then=Then,ret=Rs}, Ctxt) ->
+format_1(#k_letrec_goto{label=Label,vars=Vs,first=First,then=Then,ret=Rs}, Ctxt) ->
Ctxt1 = ctxt_bump_indent(Ctxt, Ctxt#ctxt.item_indent),
["letrec_goto ",
atom_to_list(Label),
+ format_args(Vs, Ctxt),
nl_indent(Ctxt1),
format(Then, Ctxt1),
nl_indent(Ctxt1),
@@ -185,8 +186,8 @@ format_1(#k_letrec_goto{label=Label,first=First,then=Then,ret=Rs}, Ctxt) ->
"end",
format_ret(Rs, Ctxt1)
];
-format_1(#k_goto{label=Label}, _Ctxt) ->
- ["goto ",atom_to_list(Label)];
+format_1(#k_goto{label=Label,args=As}, Ctxt) ->
+ ["goto ",atom_to_list(Label),format_args(As, Ctxt)];
format_1(#k_select{var=V,types=Cs}, Ctxt) ->
Ctxt1 = ctxt_bump_indent(Ctxt, 2),
["select ",
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index 9019429414..8e145ae136 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -9,6 +9,7 @@ MODULES= \
andor_SUITE \
apply_SUITE \
beam_block_SUITE \
+ beam_bounds_SUITE \
beam_validator_SUITE \
beam_disasm_SUITE \
beam_except_SUITE \
@@ -38,6 +39,7 @@ MODULES= \
lc_SUITE \
map_SUITE \
match_SUITE \
+ maybe_SUITE \
misc_SUITE \
overridden_bif_SUITE \
random_code_SUITE \
@@ -72,6 +74,7 @@ NO_OPT= \
lc \
map \
match \
+ maybe \
misc \
overridden_bif \
receive \
@@ -98,16 +101,20 @@ INLINE= \
lc \
map \
match \
+ maybe \
misc \
overridden_bif \
receive \
record
-R21= \
- bs_construct \
- bs_match \
+R23= \
fun
+R24= \
+ bs_construct \
+ bs_utf \
+ bs_bincomp
+
DIALYZER = bs_match
CORE_MODULES = \
@@ -128,8 +135,10 @@ NO_CORE_OPT_MODULES= $(NO_OPT:%=%_no_copt_SUITE)
NO_CORE_OPT_ERL_FILES= $(NO_CORE_OPT_MODULES:%=%.erl)
INLINE_MODULES= $(INLINE:%=%_inline_SUITE)
INLINE_ERL_FILES= $(INLINE_MODULES:%=%.erl)
-R21_MODULES= $(R21:%=%_r21_SUITE)
-R21_ERL_FILES= $(R21_MODULES:%=%.erl)
+R23_MODULES= $(R23:%=%_r23_SUITE)
+R23_ERL_FILES= $(R23_MODULES:%=%.erl)
+R24_MODULES= $(R24:%=%_r24_SUITE)
+R24_ERL_FILES= $(R24_MODULES:%=%.erl)
NO_MOD_OPT_MODULES= $(NO_MOD_OPT:%=%_no_module_opt_SUITE)
NO_MOD_OPT_ERL_FILES= $(NO_MOD_OPT_MODULES:%=%.erl)
NO_SSA_OPT_MODULES= $(NO_SSA_OPT:%=%_no_ssa_opt_SUITE)
@@ -159,6 +168,7 @@ RELSYSDIR = $(RELEASE_PATH)/compiler_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += +clint +clint0 +ssalint
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -169,9 +179,9 @@ EBIN = .
DISABLE_SSA_OPT = +no_bool_opt +no_share_opt +no_bsm_opt +no_fun_opt +no_ssa_opt +no_recv_opt
make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES) \
- $(NO_CORE_OPT_ERL_FILES) $(INLINE_ERL_FILES) $(R21_ERL_FILES) \
+ $(NO_CORE_OPT_ERL_FILES) $(INLINE_ERL_FILES) $(R23_ERL_FILES) \
$(NO_MOD_OPT_ERL_FILES) $(NO_TYPE_OPT_ERL_FILES) \
- $(DIALYZER_ERL_FILES)
+ $(DIALYZER_ERL_FILES) $(R24_ERL_FILES)
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +no_copt $(DISABLE_SSA_OPT) +no_postopt \
@@ -184,8 +194,10 @@ make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES
-o$(EBIN) $(NO_CORE_OPT_MODULES) >> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +inline $(ERL_COMPILE_FLAGS) \
-o$(EBIN) $(INLINE_MODULES) >> $(EMAKEFILE)
- $(ERL_TOP)/make/make_emakefile +r21 $(ERL_COMPILE_FLAGS) \
- -o$(EBIN) $(R21_MODULES) >> $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile +r23 $(ERL_COMPILE_FLAGS) \
+ -o$(EBIN) $(R23_MODULES) >> $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile +r24 $(ERL_COMPILE_FLAGS) \
+ -o$(EBIN) $(R24_MODULES) >> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +no_module_opt $(ERL_COMPILE_FLAGS) \
-o$(EBIN) $(NO_MOD_OPT_MODULES) >> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +from_core $(ERL_COMPILE_FLAGS) \
@@ -195,7 +207,7 @@ make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES
$(ERL_TOP)/make/make_emakefile +dialyzer $(ERL_COMPILE_FLAGS) \
-o$(EBIN) $(DIALYZER_MODULES) >> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
@@ -224,7 +236,10 @@ docs:
%_inline_SUITE.erl: %_SUITE.erl
sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
-%_r21_SUITE.erl: %_SUITE.erl
+%_r23_SUITE.erl: %_SUITE.erl
+ sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
+
+%_r24_SUITE.erl: %_SUITE.erl
sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@
%_no_module_opt_SUITE.erl: %_SUITE.erl
@@ -248,7 +263,9 @@ release_tests_spec: make_emakefile
$(INSTALL_DATA) compiler.spec compiler.cover \
$(EMAKEFILE) $(ERL_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \
- $(INLINE_ERL_FILES) $(R21_ERL_FILES) \
+ $(INLINE_ERL_FILES) \
+ $(R23_ERL_FILES) \
+ $(R24_ERL_FILES) \
$(NO_CORE_OPT_ERL_FILES) \
$(NO_MOD_OPT_ERL_FILES) \
$(NO_SSA_OPT_ERL_FILES) \
diff --git a/lib/compiler/test/beam_bounds_SUITE.erl b/lib/compiler/test/beam_bounds_SUITE.erl
new file mode 100644
index 0000000000..42e7f2bc27
--- /dev/null
+++ b/lib/compiler/test/beam_bounds_SUITE.erl
@@ -0,0 +1,260 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2022-2023. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(beam_bounds_SUITE).
+-export([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
+ addition_bounds/1, subtraction_bounds/1,
+ multiplication_bounds/1, division_bounds/1, rem_bounds/1,
+ band_bounds/1, bor_bounds/1, bxor_bounds/1,
+ bsr_bounds/1, bsl_bounds/1,
+ lt_bounds/1, le_bounds/1, gt_bounds/1, ge_bounds/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [{group,p}].
+
+groups() ->
+ [{p,[parallel],
+ [addition_bounds,
+ subtraction_bounds,
+ multiplication_bounds,
+ division_bounds,
+ rem_bounds,
+ band_bounds,
+ bor_bounds,
+ bxor_bounds,
+ bsr_bounds,
+ bsl_bounds,
+ lt_bounds,
+ le_bounds,
+ gt_bounds,
+ ge_bounds]}].
+
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+addition_bounds(_Config) ->
+ test_commutative('+', {-12,12}).
+
+subtraction_bounds(_Config) ->
+ test_noncommutative('-', {-12,12}).
+
+multiplication_bounds(_Config) ->
+ test_commutative('*', {-12,12}).
+
+division_bounds(_Config) ->
+ test_noncommutative('div', {-12,12}),
+
+ {'EXIT', {badarith, _}} = catch division_bounds_1([], ok),
+
+ ok.
+
+%% GH-6604: Division by zero could cause type analysis to hang forever as
+%% beam_bounds would return a bogus result.
+division_bounds_1([], X) ->
+ -1 div division_bounds_1(X, ok);
+division_bounds_1(_, _) ->
+ 0.
+
+rem_bounds(_Config) ->
+ test_noncommutative('rem', {-12,12}),
+
+ {-7,7} = beam_bounds:'rem'(any, {1,8}),
+ {-11,11} = beam_bounds:'rem'(any, {-12,8}),
+
+ ok.
+
+band_bounds(_Config) ->
+ test_commutative('band'),
+
+ %% Coverage.
+ {0,17} = beam_bounds:'band'(any, {7,17}),
+ {0,42} = beam_bounds:'band'({0,42}, any),
+ any = beam_bounds:'band'({-1,1}, any),
+ any = beam_bounds:'band'(any, {-10,0}),
+ any = beam_bounds:'band'({-10,0},{-1,10}),
+ any = beam_bounds:'band'({-20,-10},{-1,10}),
+
+ ok.
+
+bor_bounds(_Config) ->
+ test_commutative('bor'),
+
+ any = beam_bounds:'bor'({-10,0},{-1,10}),
+ any = beam_bounds:'bor'({-20,-10},{-1,10}),
+
+ ok.
+
+bxor_bounds(_Config) ->
+ test_commutative('bxor'),
+
+ any = beam_bounds:'bxor'({-10,0},{-1,10}),
+ any = beam_bounds:'bxor'({-20,-10},{-1,10}),
+
+ ok.
+
+bsr_bounds(_Config) ->
+ test_noncommutative('bsr', {-12,12}, {0,7}).
+
+bsl_bounds(_Config) ->
+ test_noncommutative('bsl', {-12,12}, {0,7}).
+
+lt_bounds(_Config) ->
+ test_relop('<').
+
+le_bounds(_Config) ->
+ test_relop('=<').
+
+gt_bounds(_Config) ->
+ test_relop('>').
+
+ge_bounds(_Config) ->
+ test_relop('>=').
+
+%%% Utilities
+
+test_commutative(Op) ->
+ test_commutative(Op, {0,32}).
+
+test_commutative(Op, {Min,Max}) ->
+ Seq = lists:seq(Min, Max),
+ _ = [test_commutative_1(Op, {A,B}, {C,D}) ||
+ A <- Seq,
+ B <- lists:nthtail(A-Min, Seq),
+ C <- lists:nthtail(A-Min, Seq),
+ D <- lists:nthtail(C-Min, Seq),
+ {A,B} =< {C,D}],
+ ok.
+
+test_commutative_1(Op, R1, R2) ->
+ {HighestMin,LowestMax} = min_max_op(Op, R1, R2),
+ {Min,Max} = beam_bounds:Op(R1, R2),
+ {Min,Max} = beam_bounds:Op(R2, R1),
+ if
+ Min =< HighestMin, LowestMax =< Max ->
+ ok;
+ true ->
+ io:format("~p(~p, ~p) evaluates to ~p; should be ~p\n",
+ [Op,R1,R2,{Min,Max},{HighestMin,LowestMax}]),
+ ct:fail(bad_min_or_max)
+ end.
+test_noncommutative(Op, Range) ->
+ test_noncommutative(Op, Range, Range).
+
+test_noncommutative(Op, {Min1,Max1}, {Min2,Max2}) ->
+ Seq1 = lists:seq(Min1, Max1),
+ Seq2 = lists:seq(Min2, Max2),
+ _ = [test_noncommutative_1(Op, {A,B}, {C,D}) ||
+ A <- Seq1,
+ B <- lists:nthtail(A-Min1, Seq1),
+ C <- Seq2,
+ D <- lists:nthtail(C-Min2, Seq2)],
+ ok.
+
+test_noncommutative_1(Op, R1, R2) ->
+ {HighestMin,LowestMax} = min_max_op(Op, R1, R2),
+ case beam_bounds:Op(R1, R2) of
+ any ->
+ case {Op,R2} of
+ {'div',{0,0}} -> ok;
+ {'rem',{0,0}} -> ok
+ end;
+ {Min,Max} when Min =< HighestMin, LowestMax =< Max ->
+ ok;
+ {Min,Max} ->
+ io:format("~p(~p, ~p) evaluates to ~p; should be ~p\n",
+ [Op,R1,R2,{Min,Max},{HighestMin,LowestMax}]),
+ ct:fail(bad_min_or_max)
+ end.
+
+min_max_op(Op, {A,B}, {C,D}) ->
+ min_max_op_1(Op, A, B, C, D, {infinity,-(1 bsl 24)}).
+
+min_max_op_1(Op, A, B, C, D, MinMax0) when A =< B ->
+ MinMax = min_max_op_2(Op, A, C, D, MinMax0),
+ min_max_op_1(Op, A + 1, B, C, D, MinMax);
+min_max_op_1(_Op, _, _, _, _, MinMax) ->
+ MinMax.
+
+min_max_op_2(Op, A, 0, D, MinMax) when Op =:= 'div'; Op =:= 'rem' ->
+ min_max_op_2(Op, A, 1, D, MinMax);
+min_max_op_2(Op, A, C, D, MinMax) when C =< D ->
+ Val = erlang:Op(A, C),
+ case MinMax of
+ {Min,Max} when Min =< Val, Val =< Max ->
+ min_max_op_2(Op, A, C + 1, D, {Min,Max});
+ {Min,Max} ->
+ min_max_op_2(Op, A, C + 1, D, {min(Min, Val),max(Max, Val)})
+ end;
+min_max_op_2(_Op, _, _, _, MinMax) ->
+ MinMax.
+
+test_relop(Op) ->
+ Max = 15,
+ Seq = lists:seq(0, Max),
+ _ = [test_relop_1(Op, {A,B}, {C,D}) ||
+ A <- Seq,
+ B <- lists:nthtail(A, Seq),
+ C <- Seq,
+ D <- lists:nthtail(C, Seq)],
+ ok.
+
+test_relop_1(Op, R1, R2) ->
+ Bool = rel_op(Op, R1, R2),
+ case beam_bounds:relop(Op, R1, R2) of
+ Bool ->
+ ok;
+ Wrong ->
+ io:format("~p(~p, ~p) evaluates to ~p; should be ~p\n",
+ [Op,R1,R2,Wrong,Bool]),
+ ct:fail(bad_bool_result)
+ end.
+
+rel_op(Op, {A,B}, {C,D}) ->
+ rel_op_1(Op, A, B, C, D, none).
+
+rel_op_1(Op, A, B, C, D, BoolResult0) when A =< B ->
+ BoolResult = rel_op_2(Op, A, C, D, BoolResult0),
+ rel_op_1(Op, A + 1, B, C, D, BoolResult);
+rel_op_1(_Op, _, _, _, _, BoolResult) ->
+ BoolResult.
+
+rel_op_2(Op, A, C, D, BoolResult0) when C =< D ->
+ Val = erlang:Op(A, C),
+ BoolResult = case BoolResult0 of
+ none -> Val;
+ Val -> BoolResult0;
+ _ -> 'maybe'
+ end,
+ rel_op_2(Op, A, C + 1, D, BoolResult);
+rel_op_2(_Op, _, _, _, BoolResult) ->
+ BoolResult.
diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index ec29659f66..9a90c1b676 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,8 +57,8 @@ multiple_allocs(_Config) ->
ok.
-could(Coupons = pda, Favorite = _pleasure = 0.0, {_, true}, {Presents}) ->
- (0 = true) = #{true => [Presents]}.
+could(_Coupons = pda, _Favorite = _pleasure = 0.0, {_, true}, {Presents}) ->
+ (0 = true) = #{true => [Presents]}.
place(lee) ->
(pregnancy = presentations) = [hours | [purchase || _ <- 0]] + wine.
@@ -114,8 +114,16 @@ coverage(_) ->
{'EXIT',{undef,[{erlang,error,[a,b,c,d],_}|_]}} =
(catch erlang:error(a, b, c, d)),
- {'EXIT',{badarith,[{?MODULE,bar,1,[File,{line,9}]}|_]}} =
- (catch bar(x)),
+ %% The stacktrace for operators such a '+' can vary depending on
+ %% whether the JIT is used or not.
+ case catch bar(x) of
+ {'EXIT',{badarith,[{erlang,'+',[x,1],[_|_]},
+ {?MODULE,bar,1,[File,{line,9}]}|_]}} ->
+ ok;
+ {'EXIT',{badarith,[{?MODULE,bar,1,[File,{line,9}]}|_]}} ->
+ ok
+ end,
+
{'EXIT',{{case_clause,{1}},[{?MODULE,bar,1,[File,{line,9}]}|_]}} =
(catch bar(0)),
@@ -127,14 +135,18 @@ coverage(_) ->
{'EXIT',{function_clause,[{?MODULE,foobar,[[fail],1,2],
[{file,"fake.erl"},{line,16}]}|_]}} =
(catch foobar([fail], 1, 2)),
+
{'EXIT',{function_clause,[{?MODULE,fake_function_clause1,[{a,b},42.0],_}|_]}} =
(catch fake_function_clause1({a,b})),
{'EXIT',{function_clause,[{?MODULE,fake_function_clause2,[42|bad_tl],_}|_]}} =
(catch fake_function_clause2(42, bad_tl)),
+
{'EXIT',{function_clause,[{?MODULE,fake_function_clause3,[x,y],_}|_]}} =
(catch fake_function_clause3(42, id([x,y]))),
+ {'EXIT',{{function_clause,a,b,c}, _}} = catch fake_function_clause4(),
+
{'EXIT',{{badmatch,0.0},_}} = (catch coverage_1(id(42))),
{'EXIT',{badarith,_}} = (catch coverage_1(id(a))),
@@ -145,9 +157,13 @@ coverage_1(X) ->
true = 0 / X.
fake_function_clause1(A) -> error(function_clause, [A,42.0]).
+
fake_function_clause2(A, Tl) -> error(function_clause, [A|Tl]).
+
fake_function_clause3(_, Stk) -> error(function_clause, Stk).
+fake_function_clause4() -> error({function_clause,a,b,c}).
+
binary_construction_allocation(_Config) ->
ok = do_binary_construction_allocation("PUT"),
ok.
diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl
index b199c175b3..f90eec9446 100644
--- a/lib/compiler/test/beam_jump_SUITE.erl
+++ b/lib/compiler/test/beam_jump_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -169,7 +169,7 @@ expects_h(7, Atom) ->
ok.
%% When compiled with +no_copt, beam_validator would complain about
-%% ambigous try/catch state.
+%% ambiguous try/catch state.
ambiguous_catch_try_state_1(<<42:false>>) ->
%% The beam_ssa_bsm pass will duplicate the entire second clause.
%% beam_jump will share the blocks with the build_stacktrace
@@ -232,7 +232,8 @@ ambiguous_catch_try_state_3() ->
-record(message3, {id, p1, p2}).
build_tuple(_Config) ->
- {'EXIT',{{badrecord,message3},_}} = (catch do_build_tuple(#message2{})),
+ Message2 = #message2{},
+ {'EXIT',{{badrecord,Message2},_}} = (catch do_build_tuple(#message2{})),
ok.
do_build_tuple(Message) ->
@@ -319,7 +320,15 @@ cs_2(I) -> I.
undecided_allocation(_Config) ->
ok = catch undecided_allocation_1(<<10:(3*7)>>),
- {'EXIT',{{badrecord,rec},_}} = catch undecided_allocation_1(8),
+ {'EXIT',{{badrecord,<<0>>},_}} = catch undecided_allocation_1(8),
+
+ {bar,1} = undecided_allocation_2(id(<<"bar">>)),
+ {foo,2} = undecided_allocation_2(id(<<"foo">>)),
+ {'EXIT',_} = catch undecided_allocation_2(id(<<"foobar">>)),
+ {'EXIT',{{badmatch,error},_}} = catch undecided_allocation_2(id("foo,bar")),
+ {'EXIT',_} = catch undecided_allocation_2(id(foobar)),
+ {'EXIT',_} = catch undecided_allocation_2(id(make_ref())),
+
ok.
-record(rec, {}).
@@ -340,6 +349,38 @@ undecided_allocation_1(V) ->
>>#rec{},
if whatever -> [] end.
+undecided_allocation_2(Order) ->
+ {_, _} =
+ case Order of
+ <<"bar">> ->
+ {bar, 1};
+ <<"foo">> ->
+ {foo, 2};
+ S ->
+ case string:split("foo", "o") of
+ [] ->
+ ok;
+ _ ->
+ %% The beam_ssa_bsm pass will duplicate this code,
+ %% and beam_jump would undo the duplication by sharing
+ %% the code that calls lists:flatten/1. The problem was
+ %% that the stack frames had different sizes for the
+ %% two calls to lists:flatten/1. The diagnostic would be:
+ %%
+ %% Internal consistency check failed - please report this bug.
+ %% Instruction: {call_ext,1,{extfunc,lists,flatten,1}}
+ %% Error: {allocated,undecided}:
+
+ lists:flatten(
+ case S of
+ Y when is_binary(Y) -> Y;
+ Y -> string:split(Y, ",")
+ end
+ )
+ end,
+ error
+ end.
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl
index a3de26524f..d1330b78bf 100644
--- a/lib/compiler/test/beam_ssa_SUITE.erl
+++ b/lib/compiler/test/beam_ssa_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,8 @@
cover_ssa_dead/1,combine_sw/1,share_opt/1,
beam_ssa_dead_crash/1,stack_init/1,
mapfoldl/0,mapfoldl/1,
- grab_bag/1,coverage/1]).
+ grab_bag/1,redundant_br/1,
+ coverage/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -45,6 +46,7 @@ groups() ->
beam_ssa_dead_crash,
stack_init,
grab_bag,
+ redundant_br,
coverage
]}].
@@ -178,7 +180,7 @@ recv(_Config) ->
self() ! 1,
{1,yes} = tricky_recv_2(),
self() ! 2,
- {2,maybe} = tricky_recv_2(),
+ {2,'maybe'} = tricky_recv_2(),
%% Test 'receive after infinity' in try/catch.
Pid = spawn(fun recv_after_inf_in_try/0),
@@ -282,7 +284,7 @@ tricky_recv_2() ->
end,
a;
X=2 ->
- Y = maybe,
+ Y = 'maybe',
b
end,
{X,Y}.
@@ -667,6 +669,7 @@ do_comb_sw_2(X) ->
share_opt(_Config) ->
ok = do_share_opt_1(0),
ok = do_share_opt_2(),
+ ok = do_share_opt_3(),
ok.
do_share_opt_1(A) ->
@@ -697,7 +700,16 @@ sopt_2({Flags, Opts}, ok) ->
[] ->
ok
end.
-
+
+do_share_opt_3() ->
+ true = sopt_3(id(ok)),
+ false = sopt_3(id(nok)),
+ ok.
+
+sopt_3(X) ->
+ %% Must be one line to trigger bug.
+ case X of ok -> id(?LINE), true; _ -> id(?LINE), false end.
+
beam_ssa_dead_crash(_Config) ->
not_A_B = do_beam_ssa_dead_crash(id(false), id(true)),
not_A_not_B = do_beam_ssa_dead_crash(false, false),
@@ -712,7 +724,7 @@ do_beam_ssa_dead_crash(A, B) ->
%% paths happens to end up in the same place.
%%
%% During the simulated execution of this function, the boolean
- %% varible for a `br` instruction would be replaced with the
+ %% variable for a `br` instruction would be replaced with the
%% literal atom `nil`, which is not allowed, and would crash the
%% compiler. In practice, during the actual execution, control
%% would never be transferred to that `br` instruction when the
@@ -872,6 +884,8 @@ grab_bag(_Config) ->
fact = grab_bag_17(),
+ {'EXIT',{{try_clause,[]},[_|_]}} = catch grab_bag_18(),
+
ok.
grab_bag_1() ->
@@ -933,7 +947,7 @@ grab_bag_4() ->
end
end.
-grab_bag_5(A, B) when <<business:(node(power))>> ->
+grab_bag_5(_A, _B) when <<business:(node(power))>> ->
true.
grab_bag_6(face) ->
@@ -997,7 +1011,7 @@ grab_bag_11() ->
_ -> other
catch
_:_ ->
- catched
+ caught
end.
grab_bag_12() ->
@@ -1084,6 +1098,35 @@ grab_bag_17() ->
[]
end.
+grab_bag_18() ->
+ try 0 of
+ _V0 ->
+ bnot false
+ after
+ try [] of
+ wrong ->
+ ok
+ catch
+ _:_ when false ->
+ error
+ end
+ end.
+
+
+redundant_br(_Config) ->
+ {false,{x,y,z}} = redundant_br_1(id({x,y,z})),
+ {true,[[a,b,c]]} = redundant_br_1(id([[[a,b,c]]])),
+ ok.
+
+redundant_br_1(Specs0) ->
+ {Join,Specs} =
+ if
+ is_list(hd(hd(Specs0))) -> {true,hd(Specs0)};
+ true -> {false,Specs0}
+ end,
+ id({Join,Specs}).
+
+-record(coverage, {name}).
coverage(_Config) ->
@@ -1101,6 +1144,8 @@ coverage(_Config) ->
error = coverage_2(),
ok = coverage_3(),
+ #coverage{name=whatever} = coverage_4(),
+ {'EXIT',{{badrecord,ok},_}} = catch coverage_5(),
ok.
@@ -1115,5 +1160,23 @@ coverage_3() ->
get(),
ok.
+coverage_4() ->
+ try
+ << <<42>> || false >>,
+ #coverage{}
+ catch
+ _:_ ->
+ error
+ end#coverage{name = whatever}.
+
+coverage_5() ->
+ try
+ << <<42>> || false >>,
+ ok
+ catch
+ _:_ ->
+ error
+ end#coverage{name = whatever}.
+
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 0b0e337d24..ceb7ff07b3 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
arity_checks/1,elixir_binaries/1,find_best/1,
test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1,
none_argument/1,success_type_oscillation/1,type_subtraction/1,
- container_subtraction/1]).
+ container_subtraction/1,is_list_opt/1,connected_tuple_elements/1,
+ switch_fail_inference/1,failures/1]).
%% Force id/1 to return 'any'.
-export([id/1]).
@@ -58,7 +59,11 @@ groups() ->
none_argument,
success_type_oscillation,
type_subtraction,
- container_subtraction
+ container_subtraction,
+ is_list_opt,
+ connected_tuple_elements,
+ switch_fail_inference,
+ failures
]}].
init_per_suite(Config) ->
@@ -98,6 +103,8 @@ integers(_Config) ->
{'EXIT',{badarith,_}} = (catch do_integers_8()),
+ -693 = do_integers_9(id(7), id(1)),
+
ok.
do_integers_1(B0) ->
@@ -166,6 +173,9 @@ do_integers_7() ->
do_integers_8() ->
-1 band ((0 div 0) band 0).
+do_integers_9(X, Y) ->
+ X * (-100 bor (Y band 1)).
+
numbers(_Config) ->
Int = id(42),
true = is_integer(Int),
@@ -259,22 +269,51 @@ coverage(Config) ->
false = fun lot:life/147 == #{},
+ {'EXIT',{badarith,_}} = catch coverage_1(),
+
+ {'EXIT',{badarith,_}} = catch coverage_2(),
+
+ {'EXIT',{function_clause,_}} = catch coverage_3("a"),
+ {'EXIT',{function_clause,_}} = catch coverage_3("b"),
+
ok.
+coverage_1() ->
+ try
+ []
+ catch
+ _:_ ->
+ 42
+ end
+ *
+ [].
+
+coverage_2() ->
+ tl("abc") bsr [].
+
+%% Cover beam_ssa_type:infer_br_value(V, Bool, none).
+coverage_3("a" = V) when is_function(V, false) ->
+ 0.
+
booleans(_Config) ->
{'EXIT',{{case_clause,_},_}} = (catch do_booleans_1(42)),
ok = do_booleans_2(42, 41),
error = do_booleans_2(42, 42),
+ ok = do_booleans_3(id([]), id(false)),
+ error = do_booleans_3(id([]), id(true)),
+ error = do_booleans_3(id([a]), id(false)),
+ error = do_booleans_3(id([a]), id(true)),
+
AnyAtom = id(atom),
true = is_atom(AnyAtom),
false = is_boolean(AnyAtom),
- MaybeBool = id(maybe),
+ MaybeBool = id('maybe'),
case MaybeBool of
true -> ok;
- maybe -> ok;
+ 'maybe' -> ok;
false -> ok
end,
false = is_boolean(MaybeBool),
@@ -308,12 +347,34 @@ do_booleans_2(A, B) ->
do_booleans_cmp(A, B) -> A > B.
+do_booleans_3(NewContent, IsAnchor) ->
+ if NewContent == [] andalso not IsAnchor ->
+ ok;
+ true ->
+ error
+ end.
+
+
setelement(_Config) ->
T0 = id({a,42}),
{a,_} = T0,
{b,_} = setelement(1, T0, b),
{z,b} = do_setelement_1(<<(id(1)):32>>, {a,b}, z),
{new,two} = do_setelement_2(<<(id(1)):1>>, {one,two}, new),
+ {x,b} = setelement(id(1), id({a,b}), x),
+
+ Index0 = case id(1) of
+ 0 -> 1;
+ 1 -> 2
+ end,
+ {a,x,c} = setelement(Index0, {a,b,c}, x),
+
+ Index1 = case id(1) of
+ 0 -> 4;
+ 1 -> 5
+ end,
+ {'EXIT',{badarg,_}} = catch setelement(Index1, {a,b,c}, y),
+
ok.
do_setelement_1(<<N:32>>, Tuple, NewValue) ->
@@ -383,11 +444,43 @@ tuple(_Config) ->
[] = [X || X <- [], #bird{b = b} == {bird,X}],
[] = [X || X <- [], 3 == X#bird.a],
+ 1 = do_literal_tuple_1(1),
+ 1 = do_literal_tuple_1(20),
+ {'EXIT', _} = catch do_literal_tuple_1(id(0)),
+ {'EXIT', _} = catch do_literal_tuple_1(id(bad)),
+
+ 2 = do_literal_tuple_2(1),
+ 2 = do_literal_tuple_2(15),
+ 2 = do_literal_tuple_2(20),
+
+ Counters0 = id({0,0,0}), %Inexact size.
+ {1,0,0} = Counters1 = increment_element(1, Counters0),
+ {1,1,0} = increment_element(2, Counters1),
+
+ Counters10 = {id(0),id(0),id(0)}, %Exact size.
+ {0,-1,0} = decrement_element(2, Counters10),
+ {0,0,-1} = decrement_element(3, Counters10),
+ {'EXIT',{badarg,_}} = catch decrement_element(4, Counters10),
+
ok.
do_tuple() ->
{0, _} = {necessary}.
+do_literal_tuple_1(X) ->
+ element(X, {1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1}).
+
+do_literal_tuple_2(X) ->
+ element(X, {2,2,2,2,2, 2,2,2,2,2, 2,2,2,2,2, 2,2,2,2,2}).
+
+increment_element(Pos, Cs) ->
+ Ns = element(Pos, Cs),
+ setelement(Pos, Cs, Ns + 1).
+
+decrement_element(Pos, Cs) ->
+ Ns = element(Pos, Cs),
+ setelement(Pos, Cs, Ns - 1).
+
-record(x, {a}).
record_float(_Config) ->
@@ -530,16 +623,38 @@ do_test_size(Term) when is_binary(Term) ->
size(Term).
cover_lists_functions(Config) ->
+ {data_dir,_DataDir} = lists:keyfind(data_dir, id(1), Config),
+
+ Config = lists:map(id(fun id/1), Config),
+
case lists:suffix([no|Config], Config) of
true ->
ct:fail(should_be_false);
false ->
ok
end,
- Zipped = lists:zipwith(fun(A, B) -> {A,B} end,
+
+ Zipper = fun(A, B) -> {A,B} end,
+
+ [] = lists:zipwith(Zipper, [], []),
+
+ Zipped = lists:zipwith(Zipper,
lists:duplicate(length(Config), zip),
Config),
- true = is_list(Zipped),
+ [{zip,_}|_] = Zipped,
+
+ DoubleZip = lists:zipwith(id(Zipper),
+ lists:duplicate(length(Zipped), zip_zip),
+ Zipped),
+ [{zip_zip,{zip,_}}|_] = DoubleZip,
+
+ {'EXIT',{bad,_}} = (catch lists:zipwith(fun(_A, _B) -> error(bad) end,
+ lists:duplicate(length(Zipped), zip_zip),
+ Zipped)),
+ [{zip_zip,{zip,_}}|_] = DoubleZip,
+
+ {[_|_],[_|_]} = lists:unzip(Zipped),
+
ok.
list_append(_Config) ->
@@ -661,5 +776,156 @@ cs_1({_,_}=Other) ->
cs_2({bar,baz}) ->
ok.
+is_list_opt(_Config) ->
+ true = is_list_opt_1(id(<<"application/a2l">>)),
+ false = is_list_opt_1(id(<<"">>)),
+ ok.
+
+is_list_opt_1(Type) ->
+ %% The call to is_list/1 would be optimized to an is_nonempty_list
+ %% instruction, which is illegal in a return context. That would
+ %% crash beam_ssa_codegen.
+ is_list(is_list_opt_2(Type)).
+
+is_list_opt_2(<<"application/a2l">>) -> [<<"a2l">>];
+is_list_opt_2(_Type) -> nil.
+
+%% We used to determine the type of `get_tuple_element` at the time of
+%% extraction, which is simple but sometimes throws away type information when
+%% on tuple unions.
+%%
+%% This normally doesn't cause any issues other than slightly less optimized
+%% code, but would crash the type pass in rare cases. Consider the following
+%% SSA:
+%%
+%% ----
+%% %% (Assume _0 is either `{a, 1}`, {b, 2}, or `{c, {d}}`)
+%% 0:
+%% _1 = get_tuple_element _0, `0`
+%% _2 = get_tuple_element _0, `1`
+%% switch _1, ^3, [
+%% { `a`, ^1 },
+%% { `b`, ^2 }
+%% ]
+%% 1: ... snip ...
+%% 2: ... snip ...
+%% 3:
+%% _3 = get_tuple_element _0, `1`
+%% @ssa_bool = is_tagged_tuple _3, 1, `d`
+%% br @ssa_bool ^4, ^1234
+%% 4:
+%% _4 = get_tuple_element _3, `0`
+%% ----
+%%
+%% In block 0 we determine that the type of _1 is `a | b | c` and that _2
+%% is `1 | 2 | {d}`. From this, we know that _0 is `{a, 1}` in block 1,
+%% `{b, 2}` in block 2, and `{c, {d}}` in block 3.
+%%
+%% In block 3, we remove the `is_tagged_tuple` test since it's redundant.
+%%
+%% ... but then the compiler replaces _3 with _2 since they're the same value.
+%% However, the type is still the same old `1 | 2 | {d}` we got in block 0,
+%% which is not safe for `get_tuple_element`, crashing the type pass.
+%%
+%% We fixed this by determining the type of `get_tuple_element` when the result
+%% is used instead of when it was extracted, giving the correct type `{d}` in
+%% block 4.
+connected_tuple_elements(_Config) ->
+ {c, 1, 2, 3} = cte_match(id(gurka), cte_generate(id(2))),
+ ok.
+
+cte_match(_, {a, A, B}) ->
+ {a, id(A), id(B)};
+cte_match(_, {b, A, B}) ->
+ {b, id(A), id(B)};
+cte_match(gurka, {c, A, {{B}, {C}}}) ->
+ {c, id(A), id(B), id(C)}.
+
+cte_generate(0) ->
+ {a, id(1), id(2)};
+cte_generate(1) ->
+ {b, id(1), id(2)};
+cte_generate(2) ->
+ {c, id(1), {{id(2)}, {id(3)}}}.
+
+%% ERIERL-799: Type inference for the fail label on switch terminators was
+%% weaker than that of the case labels, sometimes causing the compiler to crash
+%% when they were inverted.
+switch_fail_inference(_Config) ->
+ ok = sfi(id([])),
+ ok = sfi(id([{twiddle,frobnitz}, eof])),
+ {error, gaffel, gurka} = sfi(id([{twiddle, frobnitz}, {error, gurka}])),
+ {error, gaffel, gurka} = sfi(id([{ok, frobnitz}, {error, gurka}])),
+
+ ok = sfi_5(id("GET")),
+ error = sfi_5(id("OTHER")),
+
+ ok.
+
+sfi(Things) ->
+ case sfi_1(Things) of
+ {ok, _} -> ok;
+ {error, {Left, Right}} -> {error, Left, Right}
+ end.
+
+sfi_1(Things) ->
+ case sfi_2(Things) of
+ {ok, Value} -> {ok, Value};
+ {error, Reason} -> {error, Reason}
+ end.
+
+sfi_2([Thing | Rest]) ->
+ case sfi_3(Thing) of
+ {ok, _} -> sfi_2(Rest);
+ {error, Reason} -> {error, Reason}
+ end;
+sfi_2([]) ->
+ {ok, done}.
+
+sfi_3({twiddle, _}) ->
+ {ok, twiddle};
+sfi_3(Thing) ->
+ case sfi_4(Thing) of
+ {twiddle, _}=More -> sfi_3(More);
+ {ok, Value} -> {ok, Value};
+ {error, Reason} -> {error, Reason}
+ end.
+
+sfi_4(eof) ->
+ {ok, eof};
+sfi_4({ok, IgnoredLater}) ->
+ {twiddle, IgnoredLater};
+sfi_4({error, Reason}) ->
+ {error, {gaffel, Reason}}.
+
+sfi_5(Info) ->
+ ReturnValue = case Info of
+ "GET" ->
+ {304};
+ _ ->
+ {412}
+ end,
+ sfi_send_return_value(ReturnValue).
+
+sfi_send_return_value({304}) ->
+ ok;
+sfi_send_return_value({412}) ->
+ error.
+
+failures(_Config) ->
+ {'EXIT',{function_clause,_}} = catch failures_1(id(a), id(b), id(c)),
+ {'EXIT',{badarith,_}} = catch failures_1([], 2, 3),
+ {'EXIT',{badarith,_}} = catch failures_1([], x, y),
+ ok.
+
+failures_1([] = V1, V2, V3) ->
+ %% beam_call_types:types(erlang, '-', [any,nil]) would return
+ %% {none,_,_}, indicating that the call would fail, while
+ %% beam_call_types:will_succeed/3 called with the same arguments
+ %% would return `maybe` instead of `no`. That would cause
+ %% generation of incorrect BEAM code that would ultimately cause
+ %% beam_clean to crash.
+ {V1 - V3, (V1 = V2) - V3}.
+
id(I) ->
I.
diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl
index eb0af59f9d..3c1f986b30 100644
--- a/lib/compiler/test/beam_utils_SUITE.erl
+++ b/lib/compiler/test/beam_utils_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -392,9 +392,9 @@ merchant([Merchant, Laws, Electric]) ->
if true; Electric -> Laws end) + 42.
oklahoma([], Int) -> Int.
-town(overall, {{If}, Healing = alcohol})
- when Healing#{[] => Healing}; include ->
- [If || Healing <- awareness].
+town(overall, {{If}, _Healing = alcohol})
+ when _Healing#{[] => _Healing}; include ->
+ [If || _Healing <- awareness].
%% Cover is_reg_used_at/3.
resulting([Conservation], stone) ->
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index b112bef22e..aba3b8dfe2 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -38,9 +38,11 @@
infer_on_eq/1,infer_dead_value/1,infer_on_ne/1,
branch_to_try_handler/1,call_without_stack/1,
receive_marker/1,safe_instructions/1,
- missing_return_type/1,will_bif_succeed/1,
+ missing_return_type/1,will_succeed/1,
bs_saved_position_units/1,parent_container/1,
- container_performance/1]).
+ container_performance/1,
+ not_equal_inference/1,
+ inert_update_type/1]).
-include_lib("common_test/include/ct.hrl").
@@ -73,9 +75,11 @@ groups() ->
infer_on_eq,infer_dead_value,infer_on_ne,
branch_to_try_handler,call_without_stack,
receive_marker,safe_instructions,
- missing_return_type,will_bif_succeed,
+ missing_return_type,will_succeed,
bs_saved_position_units,parent_container,
- container_performance]}].
+ container_performance,
+ not_equal_inference,
+ inert_update_type]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -805,7 +809,7 @@ bs_saved_position_units(Config) when is_list(Config) ->
{'%',
{var_info,
{x,0},
- [{type,{t_bs_context,8,0,0}},accepts_match_context]}},
+ [{type,{t_bs_context,8}},accepts_match_context]}},
{move,nil,{x,0}},
return]},
{function,no_errors,1,4,
@@ -866,8 +870,8 @@ bs_saved_position_units(Config) when is_list(Config) ->
{{call_only,1,{f,2}},
14,
{bad_arg_type,{x,0},
- {t_bs_context,12,0,0},
- {t_bs_context,8,0,0}}}}] = Errors,
+ {t_bs_context,12},
+ {t_bs_context,8}}}}] = Errors,
ok.
@@ -930,23 +934,57 @@ night(Turned) ->
participating(_, _, _, _) -> ok.
+will_succeed(_Config) ->
+ ok = will_succeed_1(body),
+
+ self() ! whatever,
+ error = will_succeed_2(),
+
+ self() ! whatever,
+ error = will_succeed_3(),
+
+ ok.
+
%% map_get was known as returning 'none', but 'will_succeed' still returned
%% 'maybe' causing validation to continue, eventually exploding when the 'none'
%% value was used.
-will_bif_succeed(_Config) ->
- ok = f1(body).
-
+%%
%% +no_ssa_opt
-f1(body) when map_get(girl, #{friend => node()}); [], community ->
+will_succeed_1(body) when map_get(girl, #{friend => node()}); [], community ->
case $q and $K of
_V0 ->
0.1825965401179273;
0 ->
state#{[] => 0.10577334580729858, $J => 0}
end;
-f1(body) ->
+will_succeed_1(body) ->
ok.
+%% The apply of 42:name/0 was known to fail, but 'will_succeed' still
+%% returned 'maybe', causing validation to continue and fail because
+%% of the jump to the try_case instruction.
+will_succeed_2() ->
+ try
+ receive
+ _ ->
+ 42
+ end:name()
+ catch
+ _:_ ->
+ error
+ end.
+
+will_succeed_3() ->
+ try
+ receive
+ _ ->
+ 42
+ end:name(a, b)
+ catch
+ _:_ ->
+ error
+ end.
+
%% ERL-1426: When a value was extracted from a tuple, subsequent type tests did
%% not update the type of said tuple.
@@ -1001,5 +1039,26 @@ container_performance(Config) ->
_ -> ok
end.
+%% OTP-18365: A brainfart in inference for '=/=' inverted the results.
+not_equal_inference(_Config) ->
+ {'EXIT', {function_clause, _}} = (catch not_equal_inference_1(id([0]))),
+ ok.
+
+not_equal_inference_1(X) when (X /= []) /= is_port(0 div 0) ->
+ [X || _ <- []].
+
+%% GH-6969: A type was made concrete even though that added no additional
+%% information.
+inert_update_type(_Config) ->
+ hello(<<"string">>, id(42)).
+
+hello(A, B) ->
+ mike([{sys_period, {A, B}}, {some_atom, B}]).
+
+mike([Head | _Rest]) -> joe(Head).
+
+joe({Name, 42}) -> Name;
+joe({sys_period, {A, _B}}) -> {41, 42, A}.
+
id(I) ->
I.
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index a23d728715..34bf54a871 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -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,
beam_validator/1,trunc_and_friends/1,cover_safe_and_pure_bifs/1,
- cover_trim/1]).
+ cover_trim/1,
+ head_tail/1]).
suite() ->
[{ct_hooks,[ts_install_cth]}].
@@ -37,7 +38,8 @@ groups() ->
[beam_validator,
trunc_and_friends,
cover_safe_and_pure_bifs,
- cover_trim
+ cover_trim,
+ head_tail
]}].
init_per_suite(Config) ->
@@ -128,6 +130,17 @@ cover_safe_and_pure_bifs(Config) ->
cover_trim(_Config) ->
ok = cover_trim_1(<<"abc">>, id([42])),
ok = cover_trim_1({a,b,c}, id([42])),
+
+ true = cover_trim_2("keep-alive", "1"),
+ false = cover_trim_2("keep-alive", "0"),
+ false = cover_trim_2("other", "1"),
+ false = cover_trim_2("other", "0"),
+
+ true = cover_trim_3("keep-alive", -1),
+ false = cover_trim_3("keep-alive", 100),
+ false = cover_trim_3("other", -10),
+ false = cover_trim_3("other", -100),
+
ok.
cover_trim_1(Something, V) ->
@@ -138,5 +151,46 @@ cover_trim_1(Something, V) ->
ok
end.
+cover_trim_2(Header, NList)->
+ id(0),
+ case id(Header) of
+ "keep-alive" when hd(NList) >= $1 ->
+ true;
+ _Connect ->
+ false
+ end.
+
+cover_trim_3(Header, N)->
+ id(0),
+ case id(Header) of
+ "keep-alive" when abs(N) < 42 ->
+ true;
+ _Connect ->
+ false
+ end.
+
+%% GH-7024: The loader transformations for hd/1 and tl/1 were incorrect and
+%% failed when certain optimizations were turned off.
+head_tail(_Config) ->
+ {1, ok} = head_case(),
+ {1, ok} = tail_case(),
+
+ 1 = hd(id([1])),
+ [] = tl(id([1])),
+
+ ok.
+
+head_case() ->
+ case 1 of
+ X when hd(X) -> blurf;
+ X -> {X, ok}
+ end.
+
+tail_case() ->
+ case 1 of
+ X when tl(X) -> blurf;
+ X -> {X, ok}
+ end.
+
id(I) ->
I.
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index a0e2345025..c3324b64dc 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -387,6 +387,12 @@ sizes(Config) when is_list(Config) ->
<<>> = Fun6([], 42),
<<42,43:20>> = Fun6([42], 20),
+ Fun7 = fun(B) ->
+ cs_default(<< <<C/utf8>> || C <- B >>)
+ end,
+ <<"Foundation"/utf8>> = Fun7("Foundation"),
+ <<"ОÑнование"/utf8>> = Fun7("ОÑнование"),
+
%% Binary generators.
Fun10 = fun(Bin) ->
@@ -437,6 +443,12 @@ sizes(Config) when is_list(Config) ->
<<$a:32,$b:32,$c:32,($a bsl 8 bor $b):32>> = Fun14([8,16], <<"abc">>),
<<$a:32,$b:32,$c:32>> = Fun14([8,bad], <<"abc">>),
+ Fun15 = fun(B) ->
+ cs_default(<< <<C/utf8>> || << C:32 >> <= id(B) >>)
+ end,
+ <<"Foundation"/utf8>> = Fun15(<<"Foundation"/utf32>>),
+ <<"ОÑнование"/utf8>> = Fun15(<<"ОÑнование"/utf32>>),
+
{'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>),
cs_end(),
diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl
index bb9fcb033b..c681f3c21d 100644
--- a/lib/compiler/test/bs_construct_SUITE.erl
+++ b/lib/compiler/test/bs_construct_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,10 +72,10 @@ end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
verify_highest_opcode(_Config) ->
case ?MODULE of
- bs_construct_r21_SUITE ->
+ bs_construct_r24_SUITE ->
{ok,Beam} = file:read_file(code:which(?MODULE)),
case test_lib:highest_opcode(Beam) of
- Highest when Highest =< 163 ->
+ Highest when Highest =< 176 ->
ok;
TooHigh ->
ct:fail({too_high_opcode_for_21,TooHigh})
@@ -164,7 +164,7 @@ l(I_13, I_big1, I_16, Bin) ->
?T(<<869:16/little,3479:I_13,Bin/binary,7:1/unit:3,Bin/binary>>,
[101,3,108,189,42,214,31,165,90,195]),
- %% Test of aligment flag.
+ %% Test of alignment flag.
?T(<<0:I_13/unit:8,1:6,0:2>>,
[0,0,0,0,0,0,0,0,0,0,0,0,0,4]),
@@ -369,6 +369,8 @@ fail(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch << <<$t/little-signed>>:42/native-bytes >>),
{'EXIT',{badarg,_}} = (catch << <<$t/little-signed>>:42/bytes >>),
+ {'EXIT',{badarg,_}} = catch fail_2(true),
+
ok.
fail_1() ->
@@ -376,6 +378,9 @@ fail_1() ->
_ when V0 -> true
end.
+fail_2(True) when True ->
+ <<0,True/bitstring>>.
+
float_bin(Config) when is_list(Config) ->
%% Some more coverage.
{<<1,2,3>>,7.0} = float_bin_1(4),
@@ -703,6 +708,7 @@ bad_size(_Config) ->
{'EXIT',{badarg,_}} = (catch bad_binary_size()),
{'EXIT',{badarg,_}} = (catch bad_binary_size(<<"xyz">>)),
{'EXIT',{badarg,_}} = (catch bad_binary_size2()),
+ {'EXIT',{badarg,_}} = (catch bad_binary_size3(id(<<"abc">>))),
ok.
bad_float_size() ->
@@ -732,3 +738,6 @@ bad_binary_size2() ->
<<
<<(id(42))>>:[ <<>> || <<123:true>> <= <<>> ]/binary,
<<(id(100))>>:7>>.
+
+bad_binary_size3(Bin) ->
+ <<Bin:all/binary>>.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index e935fe98ff..b477109f45 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -48,7 +48,8 @@
exceptions_after_match_failure/1,
bad_phi_paths/1,many_clauses/1,
combine_empty_segments/1,hangs_forever/1,
- bs_saved_position_units/1,empty_matches/1]).
+ bs_saved_position_units/1,empty_matches/1,
+ trim_bs_start_match_resume/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -87,7 +88,8 @@ groups() ->
matching_meets_apply,bs_start_match2_defs,
exceptions_after_match_failure,bad_phi_paths,
many_clauses,combine_empty_segments,hangs_forever,
- bs_saved_position_units,empty_matches]}].
+ bs_saved_position_units,empty_matches,
+ trim_bs_start_match_resume]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -849,6 +851,8 @@ coverage(Config) when is_list(Config) ->
{<<"abc">>,<<"tag">>} = coverage_trim_3([<<"abc","tag">>], 3),
+ <<57348:16/native>> = coverage_trim_4(<<"abc">>),
+
%% Cover code in beam_ssa_codegen.
ok = coverage_beam_ssa_codegen(<<2>>),
@@ -980,6 +984,15 @@ coverage_trim_3(CipherTextFragment, TagLen) ->
iolist_to_binary(CipherTextFragment),
{CipherText, CipherTag}.
+coverage_trim_4(Bin) ->
+ << <<X:16>> || <<X:8>> <= Bin >>,
+ try
+ <<57348:16/native>>
+ catch
+ _:_ ->
+ error
+ end.
+
printable_char($a) -> true;
printable_char(_) -> false.
@@ -1478,10 +1491,11 @@ haystack_2(Haystack) ->
fc({'EXIT',{function_clause,_}}) -> ok;
fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= bs_match_inline_SUITE -> ok.
-fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) -> ok;
-fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}})
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,Name,Args,_}|_]}}) ->
+ ok;
+fc(Name, Args, {'EXIT',{function_clause,[{?MODULE,_,Args,_}|_]}})
when ?MODULE =:= bs_match_inline_SUITE ->
- Args = tuple_to_list(ActualArgs).
+ ok.
%% Cover the clause handling bs_context to binary in
%% beam_block:initialized_regs/2.
@@ -1633,9 +1647,9 @@ mos_int_receive(Msg) ->
Res.
mos_int_fun(B) ->
- L = ignore_me,
- F = fun ([<<L,I:L,X:32>>]) -> {I,X};
- ([<<L,I:L,X:64>>]) -> {I,X}
+ _L = ignore_me,
+ F = fun ([<<_L,I:_L,X:32>>]) -> {I,X};
+ ([<<_L,I:_L,X:64>>]) -> {I,X}
end,
F(B).
@@ -2434,6 +2448,11 @@ empty_matches(Config) when is_list(Config) ->
<<Zero:0/unit:1>> = id(<<>>),
0 = id(Zero),
+ ok = em_4(<<>>, <<>>),
+ {'EXIT',{function_clause,[_|_]}} = catch em_4(<<>>, <<0:1>>),
+ {'EXIT',{function_clause,[_|_]}} = catch em_4(<<0:1>>, <<>>),
+ {'EXIT',{function_clause,[_|_]}} = catch em_4(<<0:1>>, <<0:1>>),
+
ok.
em_1(Bytes) ->
@@ -2457,6 +2476,21 @@ em_3(<<V:0/binary,Rest/bits>>) ->
em_3_1(I) -> I.
+%% GH-6426/OTP-xxxxx
+em_4(<<X:0, _:X>>, <<Y:0, _:Y>>) ->
+ ok.
+
+%% beam_trim would sometimes crash when bs_start_match4 had {atom,resume} as
+%% its fail label.
+trim_bs_start_match_resume(Config) when is_list(Config) ->
+ <<Context/binary>> = id(<<>>),
+ <<>> = trim_bs_start_match_resume_1(Context),
+ ok.
+
+trim_bs_start_match_resume_1(<<Context/binary>>) ->
+ _ = id(Context),
+ Context.
+
id(I) -> I.
expand_and_squeeze(Config) when is_list(Config) ->
diff --git a/lib/compiler/test/compilation_SUITE_data/compiler_1.erl b/lib/compiler/test/compilation_SUITE_data/compiler_1.erl
index 87985bdf80..a182e494b5 100644
--- a/lib/compiler/test/compilation_SUITE_data/compiler_1.erl
+++ b/lib/compiler/test/compilation_SUITE_data/compiler_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -116,13 +116,13 @@ compiler_1() -> ok.
%%% test/0
%%%
%%% Run the complete test suite.
-%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Reads Nodes from nodes.profile and starts them if necessary.
%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
%%%
%%% test/1
%%%
%%% Run parts of the test suite.
-%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Reads Nodes from nodes.profile and starts them if necessary.
%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
%%%
%%% test/2
@@ -615,7 +615,7 @@ replica_management(Nodes) ->
done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Add and drop indecies
+%% Add and drop indices
index_lifecycle(suite) ->
[ add_table_index, create_live_table_index, del_table_index ].
@@ -689,7 +689,7 @@ del_table_index(Nodes) ->
done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Syncronize table with log or disc
+%% Synchronize table with log or disc
%%
table_sync(suite) ->
[ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ].
diff --git a/lib/compiler/test/compilation_SUITE_data/convopts.erl b/lib/compiler/test/compilation_SUITE_data/convopts.erl
index 8404eb82fd..31bd3db4a1 100644
--- a/lib/compiler/test/compilation_SUITE_data/convopts.erl
+++ b/lib/compiler/test/compilation_SUITE_data/convopts.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -108,7 +108,7 @@ convopts(Opts) ->
%% This undocumented clause uses an undocumented
%% feature of the TIPC socket interface that takes
%% advantage of some gory internals of the protocol.
- %% It is protocol implementation dependant and
+ %% It is protocol implementation dependent and
%% breaks the whole idea of location transparency
%% for name addressed messages. Therefore it should
%% only be used when all other possibilities are
diff --git a/lib/compiler/test/compilation_SUITE_data/opt_crash.erl b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
index 4643ce61f6..05b817dbc4 100644
--- a/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
+++ b/lib/compiler/test/compilation_SUITE_data/opt_crash.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ test() ->
nil},
{query,nil}}} = URI_Before,
- %% ... some funky code ommitted, not relevant ...
+ %% ... some funky code omitted, not relevant ...
{absoluteURI,
{scheme,_},
diff --git a/lib/compiler/test/compilation_SUITE_data/otp_4790.erl b/lib/compiler/test/compilation_SUITE_data/otp_4790.erl
index 08769c5303..f1173da97c 100644
--- a/lib/compiler/test/compilation_SUITE_data/otp_4790.erl
+++ b/lib/compiler/test/compilation_SUITE_data/otp_4790.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
% causing a crash at run-time.
% The same error could cause tuple tests to be removed,
-% but that would propbably only cause a crash if the
+% but that would probably only cause a crash if the
% Erlang code was incorrect or if it depended on a catch
% to catch exceptions. Therefore, I consider it unlikely
% that Erlang programs that don't use floating point
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 0e785b3bd9..cbe7179e0a 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,19 +26,19 @@
-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,appup_test/1,
+ app_test/1,appup_test/1,bigE_roundtrip/1,
debug_info/4, custom_debug_info/1, custom_compile_info/1,
file_1/1, forms_2/1, module_mismatch/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
other_output/1, kernel_listing/1, encrypted_abstr/1,
strict_record/1, utf8_atoms/1, utf8_functions/1, extra_chunks/1,
cover/1, env/1, core_pp/1, tuple_calls/1,
- core_roundtrip/1, asm/1,
+ core_roundtrip/1, asm/1, asm_labels/1,
sys_pre_attributes/1, dialyzer/1, no_core_prepare/1,
warnings/1, pre_load_check/1, env_compiler_options/1,
bc_options/1, deterministic_include/1, deterministic_paths/1,
compile_attribute/1, message_printing/1, other_options/1,
- transforms/1, erl_compile_api/1
+ transforms/1, erl_compile_api/1, types_pp/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -48,16 +48,17 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
-spec all() -> all_return_type().
all() ->
- [app_test, appup_test, file_1, forms_2, module_mismatch, outdir,
+ [app_test, appup_test, bigE_roundtrip, file_1,
+ forms_2, module_mismatch, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
other_output, kernel_listing, encrypted_abstr, tuple_calls,
strict_record, utf8_atoms, utf8_functions, extra_chunks,
- cover, env, core_pp, core_roundtrip, asm, no_core_prepare,
+ cover, env, core_pp, core_roundtrip, asm, asm_labels, no_core_prepare,
sys_pre_attributes, dialyzer, warnings, pre_load_check,
env_compiler_options, custom_debug_info, bc_options,
custom_compile_info, deterministic_include, deterministic_paths,
compile_attribute, message_printing, other_options, transforms,
- erl_compile_api].
+ erl_compile_api, types_pp].
groups() ->
[].
@@ -85,6 +86,37 @@ app_test(Config) when is_list(Config) ->
appup_test(Config) when is_list(Config) ->
ok = test_server:appup_test(compiler).
+%% Check that a file compiled to the abstract form and dumped with -E
+%% can be compiled. We use a file constructed to produce errors if the
+%% dumping fails to legalize compiler generated variable names.
+bigE_roundtrip(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Source = filename:join(DataDir, "bigE.erl"),
+ TargetDir = filename:join(PrivDir, "bigE"),
+ Target = filename:join(TargetDir, "bigE.E"),
+ TargetSource = filename:join(TargetDir, "bigE.erl"),
+ ok = file:make_dir(TargetDir),
+ io:format("Source: ~p~nTargetDir: ~p~nTarget: ~p\n",
+ [Source, TargetDir, Target]),
+ case compile:file(Source,
+ ['E', warnings_as_errors, {outdir, TargetDir}]) of
+ {ok, _} -> ok;
+ Other -> ct:fail({unexpected_result, Other})
+ end,
+ %% Rename the output to .erl so that the compiler accepts it and
+ %% we won't get a warning due to the filename not matching the
+ %% module name.
+ ok = file:rename(Target, TargetSource),
+ case compile:file(TargetSource,
+ [warnings_as_errors, {outdir, TargetDir}]) of
+ {ok, _} -> ok;
+ Other1 -> ct:fail({unexpected_result, Other1})
+ end,
+ file:delete(TargetSource),
+ file:del_dir(TargetDir),
+ ok.
+
%% Tests that we can compile and run a simple Erlang program,
%% using compile:file/1.
@@ -146,6 +178,16 @@ file_1(Config) when is_list(Config) ->
error = compile:file(filename:join(DataDir, "bad_core"), [from_core,report]),
error = compile:file(filename:join(DataDir, "bad_core_tokens"), [from_core,report]),
+ %% Cover handling of obsolete options.
+ ObsoleteOptions = [r18,r19,r20,r21,no_bsm3,no_get_hd_tl,no_put_tuple2,no_utf8_atoms],
+ _ = [begin
+ {error,[{_Simple,
+ [{none,compile,{obsolete_option,Opt}}]}],
+ []} =
+ compile:file(Simple, [Opt,return]),
+ error = compile:file(Simple, [Opt,report])
+ end || Opt <- ObsoleteOptions],
+
%% Create a directory with the same name as the temp file to cover
%% handling of write errors.
Simple = filename:join(DataDir, "simple"),
@@ -396,7 +438,7 @@ makedep_canonicalize_result(Mf, DataDir) ->
%% Replace the Datadir by "$(srcdir)".
Mf1 = re:replace(Mf0, DataDir, "$(srcdir)/",
[global,multiline,{return,list}]),
- %% Long lines are splitted, put back everything on one line.
+ %% Long lines are split, put back everything on one line.
Mf2 = re:replace(Mf1, "\\\\\n ", "", [global,multiline,{return,list}]),
list_to_binary(Mf2).
@@ -486,7 +528,6 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
{dblk, ".block"},
{djmp, ".jump"},
{dclean, ".clean"},
- {dpeep, ".peep"},
{dopt, ".optimize"},
{diffable, ".S"}],
p_listings(List, Simple, TargetDir),
@@ -495,16 +536,15 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
do_listing(Simple, TargetDir, to_pp, ".P"),
do_listing(Simple, TargetDir, to_exp, ".E"),
do_listing(Simple, TargetDir, to_core0, ".core"),
- Listings = filename:join(PrivDir, listings),
- ok = file:delete(filename:join(Listings, File ++ ".core")),
+ ok = file:delete(filename:join(TargetDir, File ++ ".core")),
do_listing(Simple, TargetDir, to_core, ".core"),
do_listing(Simple, TargetDir, to_kernel, ".kernel"),
do_listing(Simple, TargetDir, to_dis, ".dis"),
%% Final clean up.
lists:foreach(fun(F) -> ok = file:delete(F) end,
- filelib:wildcard(filename:join(Listings, "*"))),
- ok = file:del_dir(Listings),
+ filelib:wildcard(filename:join(TargetDir, "*"))),
+ ok = file:del_dir(TargetDir),
do_file_listings(DataDir,PrivDir,Files).
@@ -636,7 +676,7 @@ encrypted_abstr(Config) when is_list(Config) ->
%% Now run the tests that require crypto.
encrypted_abstr_1(Simple, Target),
ok = file:delete(Target),
- ok = file:del_dir(filename:dirname(Target))
+ _ = file:del_dir_r(filename:dirname(Target))
end,
%% Cleanup.
@@ -680,22 +720,77 @@ encrypted_abstr_1(Simple, Target) ->
error = compile:file(Simple,
[debug_info,{debug_info_key,42},report]),
- %% Place the crypto key in .erlang.crypt.
beam_lib:clear_crypto_key_fun(),
- {ok,OldCwd} = file:get_cwd(),
- ok = file:set_cwd(TargetDir),
-
- error = compile:file(Simple, [encrypt_debug_info,report]),
- NewKey = "better use another key here",
- write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]),
- {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
- verify_abstract("simple.beam", erl_abstract_code),
- ok = file:delete(".erlang.crypt"),
- beam_lib:clear_crypto_key_fun(),
- {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
- beam_lib:chunks("simple.beam", [abstract_code]),
- ok = file:set_cwd(OldCwd),
+ %% Test to place the crypto file on disk. The test is dependent on the
+ %% $HOME of the emulator, so we do this test in another node.
+ TestHome = filename:join(TargetDir, "home"),
+ filelib:ensure_dir(TestHome),
+ HomeEnv = case os:type() of
+ {win32, _} ->
+ [Drive | Path] = filename:split(TestHome),
+ [{"APPDATA", filename:join(TestHome,"AppData")},
+ {"HOMEDRIVE", Drive}, {"HOMEPATH", filename:join(Path)}];
+ _ ->
+ [{"HOME", TestHome}]
+ end,
+
+ {ok, Peer, Node} = ?CT_PEER(#{ env => HomeEnv }),
+
+ erpc:call(
+ Node,
+ fun() ->
+ {ok,OldCwd} = file:get_cwd(),
+ ok = file:set_cwd(TargetDir),
+
+ error = compile:file(Simple, [encrypt_debug_info,report]),
+
+ CWDKey = "better use another key here",
+ CWDFile = ".erlang.crypt",
+ XDGKey = "better use yet another key here",
+ XDGFile = filename:join(
+ filename:basedir(user_config,"erlang"),
+ ".erlang.crypt"),
+ HOMEKey = "better use the home key here",
+ HOMEFile = filename:join(TestHome,".erlang.crypt"),
+
+ write_crypt_file(CWDFile, CWDKey),
+ write_crypt_file(XDGFile, XDGKey),
+ write_crypt_file(HOMEFile, HOMEKey),
+
+ %% First we test that .erlang.crypt in cwd works
+ {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
+ verify_abstract("simple.beam", erl_abstract_code),
+ ok = file:delete(CWDFile),
+ beam_lib:clear_crypto_key_fun(),
+
+ %% Then we test that .erlang.crypt in HOME does **not** work
+ {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
+ beam_lib:chunks("simple.beam", [abstract_code]),
+
+ %% Then we test that .erlang.crypt in HOME does work
+ {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
+ verify_abstract("simple.beam", erl_abstract_code),
+ ok = file:delete(HOMEFile),
+ beam_lib:clear_crypto_key_fun(),
+
+ %% Then we test that .erlang.crypt in XDG does **not** work
+ {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
+ beam_lib:chunks("simple.beam", [abstract_code]),
+
+
+ %% Then we test that .erlang.crypt in XDG does work
+ {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]),
+ verify_abstract("simple.beam", erl_abstract_code),
+ ok = file:delete(XDGFile),
+
+ beam_lib:clear_crypto_key_fun(),
+ {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} =
+ beam_lib:chunks("simple.beam", [abstract_code])
+
+ end),
+
+ peer:stop(Peer),
%% Test key compatibility by reading a BEAM file produced before
%% the update to the new crypto functions.
@@ -708,11 +803,11 @@ encrypted_abstr_1(Simple, Target) ->
ok.
-
-write_crypt_file(Contents0) ->
- Contents = list_to_binary([Contents0]),
- io:format("~s\n", [binary_to_list(Contents)]),
- ok = file:write_file(".erlang.crypt", Contents).
+write_crypt_file(File, Key) ->
+ Contents = ["[{debug_info,des3_cbc,simple,\"",Key,"\"}].\n"],
+ io:format("~s: ~s\n", [File, Contents]),
+ ok = filelib:ensure_dir(File),
+ ok = file:write_file(File, Contents).
encrypted_abstr_no_crypto(Simple, Target) ->
io:format("simpe: ~p~n", [Simple]),
@@ -744,7 +839,7 @@ install_crypto_key(Key) ->
end,
ok = beam_lib:crypto_key_fun(F).
-%% Miscellanous tests, mainly to get better coverage.
+%% Miscellaneous tests, mainly to get better coverage.
debug_info(erlang_v1, Module, ok, _Opts) ->
{ok, [Module]};
debug_info(erlang_v1, _Module, error, _Opts) ->
@@ -846,21 +941,21 @@ strict_record(Config) when is_list(Config) ->
%% Default (possibly influenced by ERL_COMPILER_OPTIONS).
{ok,M} = c:c(M, [{outdir,Priv},report_errors]),
try
- {1,2} = record_access:test(Turtle),
- {comment,"Default: no_strict_record_tests"}
- catch
- error:{badrecord,tortoise} ->
- {comment,"Default: strict_record_tests"}
- end.
+ {1,2} = record_access:test(Turtle),
+ {comment,"Default: no_strict_record_tests"}
+ catch
+ error:{badrecord,Turtle} ->
+ {comment,"Default: strict_record_tests"}
+ end.
test_strict() ->
Turtle = record_access:turtle(),
try
- record_access:test(Turtle)
- catch
- error:{badrecord,tortoise} ->
- ok
- end,
+ record_access:test(Turtle)
+ catch
+ error:{badrecord,Turtle} ->
+ ok
+ end,
Turtle.
test_sloppy() ->
@@ -881,9 +976,8 @@ utf8_atoms(Config) when is_list(Config) ->
beam_lib:chunks(Utf8AtomBin, [atoms]),
code:load_binary(utf8_atom, "compile_SUITE", Utf8AtomBin),
Atom = utf8_atom:atom(),
-
- NoUtf8AtomForms = [{attribute,Anno,module,no_utf8_atom}|Forms],
- error = compile:forms(NoUtf8AtomForms, [binary, r19]).
+ true = is_atom(Atom),
+ ok.
utf8_functions(Config) when is_list(Config) ->
Anno = erl_anno:new(1),
@@ -1036,7 +1130,7 @@ do_core_pp_1(M, A, Outdir) ->
compile_forms(M, Core, [clint,ssalint,from_core,binary]),
%% Don't optimize to test that we are not dependent
- %% on the Core Erlang optmimization passes.
+ %% on the Core Erlang optimization passes.
%% (Example of a previous bug: The core_parse pass
%% would not turn map literals into #c_literal{}
%% records; if sys_core_fold was run it would fix
@@ -1060,7 +1154,16 @@ core_roundtrip(Config) ->
ok = file:make_dir(Outdir),
TestBeams = get_unique_beam_files(),
- test_lib:p_run(fun(F) -> do_core_roundtrip(F, Outdir) end, TestBeams).
+
+ Test = fun(F) -> do_core_roundtrip(F, Outdir) end,
+ case erlang:system_info(wordsize) of
+ 4 ->
+ %% This test case is very memory intensive. Only
+ %% use a single process.
+ test_lib:p_run(Test, TestBeams, 1);
+ 8 ->
+ test_lib:p_run(Test, TestBeams)
+ end.
do_core_roundtrip(Beam, Outdir) ->
try
@@ -1265,12 +1368,13 @@ do_asm(Beam, Outdir) ->
{ok,{M,[{abstract_code,{raw_abstract_v1,A}}]}} =
beam_lib:chunks(Beam, [abstract_code]),
try
- {ok,M,Asm} = compile:forms(A, ['S']),
+ Opts = test_lib:opt_opts(M),
+ {ok,M,Asm} = compile:forms(A, ['S'|Opts]),
AsmFile = filename:join(Outdir, atom_to_list(M)++".S"),
{ok,Fd} = file:open(AsmFile, [write,{encoding,utf8}]),
beam_listing:module(Fd, Asm),
ok = file:close(Fd),
- case compile:file(AsmFile, [from_asm,binary,report]) of
+ case compile:file(AsmFile, [from_asm,binary,report|Opts]) of
{ok,M,_} ->
ok = file:delete(AsmFile);
Other ->
@@ -1283,6 +1387,26 @@ do_asm(Beam, Outdir) ->
error
end.
+%% Compile a crafted file which produces the three call instructions
+%% which should have a comment with the called function in clear
+%% text. We check that the expected functions and comments occur in
+%% the listing.
+
+asm_labels(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ InFile = filename:join(DataDir, "asm_labels.erl"),
+ OutDir = filename:join(PrivDir, "asm_labels"),
+ OutFile = filename:join(OutDir, "asm_labels.S"),
+ ok = file:make_dir(OutDir),
+ {ok,asm_labels} = compile:file(InFile, ['S',{outdir,OutDir}]),
+ {ok,Listing} = file:read_file(OutFile),
+ Os = [global,multiline,{capture,all_but_first,list}],
+ {match,[_]} = re:run(Listing, "({call,.+,{f,.+}}\\. % foo/1)", Os),
+ {match,[_]} = re:run(Listing, "({call_only,.+,{f,.+}}\\. % foo/1)", Os),
+ {match,[_]} = re:run(Listing, "({call_last,.+,{f,.+},.+}\\. % bar/1)", Os),
+ ok = file:del_dir_r(OutDir).
+
sys_pre_attributes(Config) ->
DataDir = proplists:get_value(data_dir, Config),
File = filename:join(DataDir, "attributes.erl"),
@@ -1335,7 +1459,8 @@ warnings(_Config) ->
test_lib:p_run(fun do_warnings/1, Files).
do_warnings(F) ->
- {ok,_,_,Ws} = compile:file(F, [binary,bin_opt_info,recv_opt_info,return]),
+ Options = [{feature,maybe_expr,enable},binary,bin_opt_info,recv_opt_info,return],
+ {ok,_,_,Ws} = compile:file(F, Options),
do_warnings_1(Ws, F).
do_warnings_1([{"no_file",Ws}|_], F) ->
@@ -1368,8 +1493,9 @@ do_warnings_2([], Next, F) ->
message_printing(Config) ->
DataDir = proplists:get_value(data_dir, Config),
- BadEncFile = filename:join(DataDir, "bad_enc.erl"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ BadEncFile = filename:join(DataDir, "bad_enc.erl"),
{error,BadEncErrors, []} = compile:file(BadEncFile, [return]),
[":7:15: cannot parse file, giving up\n"
@@ -1395,6 +1521,24 @@ message_printing(Config) ->
"% | \t^\n\n"
] = messages(Latin1Errors),
+ LongFile = filename:join(PrivDir, "long.erl"),
+ Long = ["-module(long).\n",
+ "-export([foo/0]).\n",
+ "unused() -> ok.\n",
+ lists:duplicate(10000, $\n),
+ "foo() -> bar().\n"],
+ ok = file:write_file(LongFile, Long),
+ {error,LongErrors,LongWarnings} = compile:file(LongFile, [return]),
+ [":10004:10: function bar/0 undefined\n"
+ "% 10004| foo() -> bar().\n"
+ "% | ^\n\n"
+ ] = messages(LongErrors),
+ [":3:1: function unused/0 is unused\n"
+ "% 3| unused() -> ok.\n"
+ "% | ^\n\n"
+ ] = messages(LongWarnings),
+ ok = file:delete(LongFile),
+
{ok,OldCwd} = file:get_cwd(),
try
ok = file:set_cwd(DataDir),
@@ -1553,46 +1697,50 @@ env_compiler_options(_Config) ->
bc_options(Config) ->
DataDir = proplists:get_value(data_dir, Config),
- L = [{101, small_float, [no_shared_fun_wrappers,
- no_get_hd_tl,no_line_info]},
- {125, small_float, [no_shared_fun_wrappers,no_get_hd_tl,
- no_line_info,
- no_ssa_opt_float]},
-
- {132, small, [no_init_yregs,no_shared_fun_wrappers,
- no_put_tuple2,no_get_hd_tl,no_ssa_opt_record,
- no_ssa_opt_float,no_line_info,no_bsm3]},
+ DataDir = proplists:get_value(data_dir, Config),
- {153, small, [r20]},
- {153, small, [r21]},
+ L = [{101, small_float, [no_shared_fun_wrappers,no_line_info]},
+ {125, small_float, [no_shared_fun_wrappers,
+ no_line_info,
+ no_ssa_opt_float,
+ no_type_opt]},
- {153, big, [r18]},
- {153, big, [r19]},
{153, small_float, [no_shared_fun_wrappers]},
- {158, small_maps, [r18]},
- {158, small_maps, [r19]},
- {158, small_maps, [r20]},
- {158, small_maps, [r21]},
-
- {164, small_maps, [no_init_yregs,no_shared_fun_wrappers]},
+ {164, small_maps, [no_init_yregs,no_shared_fun_wrappers,no_type_opt]},
{164, small_maps, [r22]},
{164, big, [r22]},
+ {164, funs, [r22]},
+ {164, funs, [no_init_yregs,no_shared_fun_wrappers,
+ no_ssa_opt_record,
+ no_line_info,no_stack_trimming,
+ no_make_fun3,no_type_opt]},
{168, small, [r22]},
+ {168, small, [no_init_yregs,no_shared_fun_wrappers,
+ no_ssa_opt_record,no_make_fun3,
+ no_ssa_opt_float,no_line_info,no_type_opt]},
+ {169, small, [r23]},
{169, big, [no_init_yregs,no_shared_fun_wrappers,
- no_put_tuple2,no_get_hd_tl,no_ssa_opt_record,
+ no_ssa_opt_record,
no_line_info,no_stack_trimming,
- no_make_fun3]},
+ no_make_fun3,no_type_opt]},
{169, big, [r23]},
- {169, small_maps, [no_init_yregs]},
+ {169, small_maps, [no_init_yregs,no_type_opt]},
- {170, small, [no_shared_fun_wrappers,no_init_yregs]},
+ {171, big, [no_init_yregs,no_shared_fun_wrappers,
+ no_ssa_opt_record,
+ no_ssa_opt_float,no_line_info,
+ no_type_opt]},
+ {171, funs, [no_init_yregs,no_shared_fun_wrappers,
+ no_ssa_opt_record,
+ no_ssa_opt_float,no_line_info,
+ no_type_opt]},
- {171, big, [no_init_yregs]},
- {172, big, []}
+ {178, funs, []},
+ {178, big, []}
],
Test = fun({Expected,Mod,Options}) ->
@@ -1610,7 +1758,7 @@ bc_options(Config) ->
highest_opcode(DataDir, Mod, Opt) ->
Src = filename:join(DataDir, atom_to_list(Mod)++".erl"),
- {ok,Mod,Beam} = compile:file(Src, [binary|Opt]),
+ {ok,Mod,Beam} = compile:file(Src, [binary,report_errors|Opt]),
test_lib:highest_opcode(Beam).
deterministic_include(Config) when is_list(Config) ->
@@ -1685,10 +1833,15 @@ forms_to_terms(Forms) ->
other_options(Config) ->
DataDir = proplists:get_value(data_dir, Config),
- %% Smoke test of no_spawn_compiler_process and brief options.
+ %% Smoke test of no_spawn_compiler_process, brief, and absolute_source
+ %% options.
Big = filename:join(DataDir, "big"),
{ok,big,<<_/binary>>} =
- compile:file(Big, [binary, no_spawn_compiler_process, brief, report]),
+ compile:file(Big, [binary,
+ no_spawn_compiler_process,
+ brief,
+ absolute_source,
+ report]),
%% Test generating a compressed BEAM file. Also cover the redundant
%% `beam` option and the `no_inline` option.
@@ -1852,6 +2005,94 @@ erl_compile_api(Config) ->
ok.
+%% Check that an ssa dump contains the pretty printed types we expect.
+%% The module we compile and dump, types_pp, is crafted so it contains
+%% calls to functions which have the result types we want to check the
+%% pretty printer for. We check all types except for bs_context,
+%% bs_matchable and the interval form of float as the first two never
+%% seem to appear in result types and the latter doesn't appear in any
+%% module compiled by diffable.
+types_pp(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ TargetDir = filename:join(PrivDir, types_pp),
+ File = filename:join(DataDir, "types_pp.erl"),
+ Listing = filename:join(TargetDir, "types_pp.ssaopt"),
+ ok = file:make_dir(TargetDir),
+
+ {ok,_} = compile:file(File, [dssaopt, {outdir, TargetDir}]),
+ {ok, Data} = file:read_file(Listing),
+ Lines = string:split(binary_to_list(Data), "\n", all),
+ ResultTypes = get_result_types(Lines),
+ io:format("Calls: ~p~n", [ResultTypes]),
+
+ TypesToCheck = [{make_atom, "'an_atom'"},
+ {make_number, "number()"},
+ {make_float, "3.14"},
+ {make_integer, "17"},
+ {make_integer_range, "0..3"},
+ {make_nil, "nil()"},
+ {make_list, "list(any())"},
+ {make_list_of_ints, "list(integer())"},
+ {make_maybe_improper_list,
+ "maybe_improper_list(any(), any())"},
+ {make_nonempty_list, "nonempty_list(any())"},
+ {make_nonempty_improper_list,
+ "nonempty_improper_list(any(), ''end'')"},
+ {make_empty_map, "#{}"},
+ {make_map, "map()"},
+ {make_map_known_types, "#{integer()=>float()}"},
+ {make_fun_unknown_arity_known_type,
+ "fun((...) -> number())"},
+ {make_fun_known_arity_known_type,
+ "fun((_, _) -> number())"},
+ {make_fun_unknown_arity_unknown_type,
+ "fun()"},
+ {make_fun_known_arity_unknown_type,
+ "fun((_, _))"},
+ {make_unconstrained_tuple, "{...}"},
+ {make_known_size_tuple,
+ "{any(), any(), any(), any(), any()}"},
+ {make_inexact_tuple, "{any(), any(), any(), ...}"},
+ {make_union,
+ "'foo' | nonempty_list(1..3) | number() |"
+ " {'tag0', 1, 2} | {'tag1', 3, 4} | bitstring(24)"},
+ {make_bitstring, "bitstring(24)"},
+ {make_none, "none()"}],
+ lists:foreach(fun({FunName, Expected}) ->
+ Actual = map_get(atom_to_list(FunName), ResultTypes),
+ case Actual of
+ Expected ->
+ ok;
+ _ ->
+ ct:fail("Expected type of ~p is ~s, found ~s",
+ [FunName, Expected, Actual])
+ end
+ end, TypesToCheck),
+ ok = file:del_dir_r(TargetDir),
+ ok.
+
+%% We assume that a call starts with a "Result type:"-line followed by
+%% a type line, which is followed by an optional annotation before the
+%% actual call.
+get_result_types(Lines) ->
+ get_result_types(Lines, #{}).
+
+get_result_types([" %% Result type:"++_," %% "++TypeLine|Lines], Acc) ->
+ get_result_types(Lines, TypeLine, Acc);
+get_result_types([_|Lines], Acc) ->
+ get_result_types(Lines, Acc);
+get_result_types([], Acc) ->
+ Acc.
+
+get_result_types([" %% Anno: "++_|Lines], TypeLine, Acc) ->
+ get_result_types(Lines, TypeLine, Acc);
+get_result_types([CallLine|Lines], TypeLine, Acc) ->
+ [_,Callee,_] = string:split(CallLine, "`", all),
+ get_result_types(Lines, Acc#{ Callee => TypeLine }).
+
+
+
%%%
%%% Utilities.
%%%
diff --git a/lib/compiler/test/compile_SUITE_data/asm_labels.erl b/lib/compiler/test/compile_SUITE_data/asm_labels.erl
new file mode 100644
index 0000000000..59571f5539
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/asm_labels.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% A module which when compiled to a BEAM assembly listing will
+%% contain call instructions with comments containing the called
+%% function in clear text.
+
+-module(asm_labels).
+
+-export([foo/0, bar/0]).
+
+%% Expected to generate a `call_only` instruction
+foo() ->
+ foo(10).
+
+%% Expected to generate a `call` instruction
+foo(0) ->
+ 17;
+foo(N) ->
+ foo(N-1) + 1.
+
+%% Expected to generate a `call_last` instruction
+bar() ->
+ receive
+ X ->
+ bar(X)
+ end.
+
+bar([]) ->
+ ok.
diff --git a/lib/compiler/test/compile_SUITE_data/big.erl b/lib/compiler/test/compile_SUITE_data/big.erl
index 765c71c07d..f96aed7615 100644
--- a/lib/compiler/test/compile_SUITE_data/big.erl
+++ b/lib/compiler/test/compile_SUITE_data/big.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -116,13 +116,13 @@ compiler_1() -> ok.
%%% test/0
%%%
%%% Run the complete test suite.
-%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Reads Nodes from nodes.profile and starts them if necessary.
%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
%%%
%%% test/1
%%%
%%% Run parts of the test suite.
-%%% Reads Nodes from nodes.profile and starts them if neccessary.
+%%% Reads Nodes from nodes.profile and starts them if necessary.
%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
%%%
%%% test/2
@@ -615,7 +615,7 @@ replica_management(Nodes) ->
done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Add and drop indecies
+%% Add and drop indices
index_lifecycle(suite) ->
[ add_table_index, create_live_table_index, del_table_index ].
@@ -689,7 +689,7 @@ del_table_index(Nodes) ->
done.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Syncronize table with log or disc
+%% Synchronize table with log or disc
%%
table_sync(suite) ->
[ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ].
diff --git a/lib/compiler/test/compile_SUITE_data/bigE.erl b/lib/compiler/test/compile_SUITE_data/bigE.erl
new file mode 100644
index 0000000000..598b8fc965
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/bigE.erl
@@ -0,0 +1,22 @@
+-module(bigE).
+
+-export([f/1]).
+
+-record(r, {a, b}).
+
+f(#r{b = B} = C) ->
+ receive
+ B ->
+ X = C#r.a,
+ %% The compiler will do a case to extract the `a` field
+ %% using a pattern variable named `rec0`. Without
+ %% legalization the variable will be output as an atom and
+ %% the compiler will report an error as the following `X +
+ %% X` will always fail.
+ REC0 = X + X,
+ %% If the legalization fails to detect that the default
+ %% legalization of uppercasing the pattern variable would
+ %% collide with the `REC0` below, we will get a warning
+ %% for an unsafe use.
+ REC0
+ end.
diff --git a/lib/compiler/test/compile_SUITE_data/funs.erl b/lib/compiler/test/compile_SUITE_data/funs.erl
new file mode 100644
index 0000000000..d605128ef4
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/funs.erl
@@ -0,0 +1,8 @@
+-module(funs).
+-export([go/0]).
+
+go() ->
+ Id = id(fun id/1),
+ {Id(ok), Id(42)}.
+
+id(I) -> I.
diff --git a/lib/compiler/test/compile_SUITE_data/types_pp.erl b/lib/compiler/test/compile_SUITE_data/types_pp.erl
new file mode 100644
index 0000000000..bcbd93a835
--- /dev/null
+++ b/lib/compiler/test/compile_SUITE_data/types_pp.erl
@@ -0,0 +1,127 @@
+-module(types_pp).
+
+-export([doit/0]).
+
+make_atom() ->
+ an_atom.
+
+make_number(X, Y) ->
+ X + Y.
+
+make_float() ->
+ 3.14.
+
+make_integer_range(X) ->
+ case X of
+ a -> 0;
+ b -> 1;
+ c -> 2;
+ _ -> 3
+ end.
+
+make_integer() ->
+ 17.
+
+make_nil() ->
+ [].
+
+make_list(X) when is_list(X) ->
+ X ++ [1, 2, 3].
+
+make_list_of_ints(X) when is_list(X) ->
+ [ Y || Y <- X, is_integer(Y)].
+
+make_maybe_improper_list(X) when is_list(X) ->
+ X.
+
+make_nonempty_list(X) ->
+ [X].
+
+make_nonempty_improper_list(X) ->
+ [X|'end'].
+
+make_empty_map() ->
+ #{}.
+
+make_map(X) when is_map(X) ->
+ X.
+
+make_map_known_types(K, V) when is_integer(K), is_float(V) ->
+ #{ K => V }.
+
+make_fun_unknown_arity_known_type() ->
+ case ext:f() of
+ 0 -> fun(X) -> X + 1 end;
+ 1 -> fun(X, Y) -> X + Y end
+ end.
+
+make_fun_known_arity_known_type() ->
+ fun(Y, Z) ->
+ Y + Z
+ end.
+
+make_fun_unknown_arity_unknown_type() ->
+ case ext:f() of
+ 0 -> fun(X) -> ext:f(X) end;
+ 1 -> fun(X, Y) -> ext:f(X, Y) end
+ end.
+
+make_fun_known_arity_unknown_type() ->
+ fun(Y, Z) ->
+ ext:f(Y, Z)
+ end.
+
+make_none() ->
+ exit(foo).
+
+make_unconstrained_tuple(X) when is_tuple(X) ->
+ X.
+
+make_known_size_tuple(X) when is_tuple(X), tuple_size(X) =:= 5 ->
+ X.
+
+make_inexact_tuple({X1,X2,X3,_X4,_X5,_X6,_X7,_X8,_X9,_X10,_X11,_X12,_X13}=X)
+ when is_integer(X1), is_float(X2), is_integer(X3) ->
+ case ext:f() of
+ 0 ->
+ {1, 2, 3};
+ _ ->
+ X
+ end.
+
+make_union() ->
+ case ext:f() of
+ 0 -> foo;
+ 1 -> [1, 2, 3];
+ 2 -> 7;
+ 3 -> 3.14;
+ 4 -> {tag0,1,2};
+ 5 -> {tag1,3,4};
+ 6 -> <<1,2,3>>
+ end.
+
+make_bitstring() ->
+ <<1, 2, 3>>.
+
+doit() ->
+ {make_number(ext:f(), ext:f()), make_atom(),
+ make_float(),
+ make_integer(), make_integer_range(ext:f()),
+ make_nil(), make_list(ext:f()), make_list_of_ints(ext:f()),
+ make_maybe_improper_list(ext:f()),
+ make_nonempty_list( ext:f()), make_nonempty_improper_list( ext:f()),
+ make_empty_map(), make_map(ext:f()),
+ make_map_known_types(ext:f(), ext:f()),
+ make_fun_unknown_arity_known_type(),
+ make_fun_known_arity_known_type(),
+ make_fun_unknown_arity_unknown_type(),
+ make_fun_known_arity_unknown_type(),
+ make_unconstrained_tuple(ext:f()),
+ make_known_size_tuple(ext:f()),
+ make_inexact_tuple(ext:f()),
+ make_union(),
+ make_bitstring(),
+ make_none()
+ }.
+
+
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index bfe8bfd168..0bdcfab5b7 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
no_no_file/1,configuration/1,supplies/1,
redundant_stack_frame/1,export_from_case/1,
empty_values/1,cover_letrec_effect/1,
- receive_effect/1]).
+ receive_effect/1,map_effect/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -50,7 +50,7 @@ groups() ->
no_no_file,configuration,supplies,
redundant_stack_frame,export_from_case,
empty_values,cover_letrec_effect,
- receive_effect]}].
+ receive_effect,map_effect]}].
init_per_suite(Config) ->
@@ -566,7 +566,7 @@ configuration(_Config) ->
ok.
configuration() ->
- [forgotten || Components <- enemy, is_tuple(fun art/0)].
+ [forgotten || _Components <- enemy, is_tuple(fun art/0)].
art() ->
creating.
@@ -673,8 +673,25 @@ cover_letrec_effect(_Config) ->
Any ->
#{k := {{tag,42},<<42:16>>}} = Any
end,
+
+ _ = catch cover_letrec_effect_1(),
+
ok.
+cover_letrec_effect_1() ->
+ try
+ _ = catch ""
+ after
+ case any_atom of
+ 31 when any_atom, force ->
+ true
+ end,
+ case "RG" of
+ 1 when car, cdr, 3; 3, 4 ->
+ false
+ end
+ end.
+
receive_effect(_Config) ->
self() ! whatever,
{} = do_receive_effect(),
@@ -683,4 +700,20 @@ receive_effect(_Config) ->
do_receive_effect() ->
{} = receive _ -> {} = {} end.
+map_effect(_Config) ->
+ {'EXIT',{{badkey,key},_}} = catch map_effect_1(),
+
+ {'EXIT',{{badkey,key},_}} = catch map_effect_2(#{}),
+ {'EXIT',{{badmap,no_map},_}} = catch map_effect_2(no_map),
+
+ ok.
+
+map_effect_1() ->
+ #{}#{key := value},
+ ok.
+
+map_effect_2(Map) ->
+ Map#{key := value},
+ ok.
+
id(I) -> I.
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index e530a9f7de..7a5aedcec6 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -181,11 +181,19 @@ math_functions(Config) when is_list(Config) ->
mixed_float_and_int(Config) when is_list(Config) ->
129.0 = pc(77, 23, 5),
+
+ {'EXIT',{badarith,_}} = catch mixed_1(id({a,b,c})),
+ {'EXIT',{{badarg,1/42},_}} = catch mixed_1(id(42)),
+
ok.
pc(Cov, NotCov, X) ->
round(Cov/(Cov+NotCov)*100) + 42 + 2.0*X.
+mixed_1(V) ->
+ {is_tuple(V) orelse 1 / V,
+ 1 / V andalso true}.
+
subtract_number_type(Config) when is_list(Config) ->
120 = fact(5).
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 387ed90ee6..d9608ef7d1 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,8 @@
init_per_group/2,end_per_group/2,
test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1,
- duplicated_fun/1,unused_fun/1,coverage/1]).
+ duplicated_fun/1,unused_fun/1,parallel_scopes/1,
+ coverage/1]).
%% Internal exports.
-export([call_me/1,dup1/0,dup2/0]).
@@ -39,6 +40,7 @@ groups() ->
[{p,[parallel],
[test1,overwritten_fun,otp_7202,bif_fun,external,eep37,
eep37_dup,badarity,badfun,duplicated_fun,unused_fun,
+ parallel_scopes,
coverage]}].
init_per_suite(Config) ->
@@ -60,7 +62,7 @@ end_per_group(_GroupName, Config) ->
l1() ->
[
- ?T((begin A = 3, F = fun(A) -> 1; (_) -> 2 end, F(2) end), 1),
+ ?T((begin _A = 3, F = fun(_A) -> 1; (_) -> 2 end, F(2) end), 1),
?T((begin G = fun(1=0) -> ok end, {'EXIT',_} = (catch G(2)), ok end), ok),
?T((begin F = fun(_, 1) -> 1; (F, N) -> N * F(F, N-1) end, F(F, 5) end), 120),
?T((begin F = fun(_, 1) -> 1; (F, N) -> N * F(F, N-1) end, F(F, 1), ok end), ok)
@@ -224,7 +226,7 @@ bad_external_fun() ->
eep37(Config) when is_list(Config) ->
F = fun Fact(N) when N > 0 -> N * Fact(N - 1); Fact(0) -> 1 end,
Add = fun _(N) -> N + 1 end,
- UnusedName = fun BlackAdder(N) -> N + 42 end,
+ UnusedName = fun _BlackAdder(N) -> N + 42 end,
720 = F(6),
10 = Add(9),
50 = UnusedName(8),
@@ -296,6 +298,230 @@ unused_fun(_Config) ->
catch _ -> ok end,
ok.
+parallel_scopes(_Config) ->
+ 1 = parallel_scopes_1a(),
+ 1 = parallel_scopes_1b(),
+ {'EXIT',{{badmatch,99},_}} = catch parallel_scopes_1c(),
+
+ 10 = parallel_scopes_2a(),
+ {'EXIT',{{badmatch,15},_}} = catch parallel_scopes_2b(),
+ 500 = parallel_scopes_2c(500, 500),
+ {'EXIT',{{badmatch,1000},_}} = catch parallel_scopes_2c(500, 1000),
+ 600 = parallel_scopes_2d(600, 600),
+ {'EXIT',{{badmatch,1000},_}} = catch parallel_scopes_2d(600, 1000),
+ {a,20} = parallel_scopes_2e(20, 20),
+ {'EXIT',{{badmatch,{a,25}},_}} = catch parallel_scopes_2e(20, 25),
+
+ {[42,2],42,a} = parallel_scopes_3(a),
+
+ 42 = parallel_scopes_4a(id(42), id(42)),
+ {'EXIT',{{badmatch,77},_}} = catch parallel_scopes_4a(42, 77),
+ 42 = parallel_scopes_4b(id(42), id(42)),
+ {'EXIT',{{badmatch,77},_}} = catch parallel_scopes_4b(42, 77),
+ [same,2,same,2] = parallel_scopes_4c(id(same), id(same)),
+ {'EXIT',{{badmatch,55},_}} = catch parallel_scopes_4c(42, 55),
+
+ 33 = parallel_scopes_5(id(33), id(33)),
+ {'EXIT',{{badmatch,44},_}} = catch parallel_scopes_5(33, 44),
+
+ 99 = parallel_scopes_6(id(99), id(99)),
+ {'EXIT',{{badmatch,88},_}} = catch parallel_scopes_6(77, 88),
+
+ 99 = parallel_scopes_7(id(99), id(99)),
+ {'EXIT',{{badmatch,88},_}} = catch parallel_scopes_7(77, 88),
+
+ 199 = parallel_scopes_8(id(199), id(199)),
+ {'EXIT',{{badmatch,200},_}} = catch parallel_scopes_8(id(199), id(200)),
+
+ {299,299+299} = parallel_scopes_9(id(299), id(299), id(299+299)),
+ {'EXIT',{{badmatch,300},_}} = catch parallel_scopes_9(id(299), id(300), id(0)),
+ {'EXIT',{{badmatch,0},_}} = catch parallel_scopes_9(id(299), id(299), id(0)),
+
+ 999 = parallel_scopes_10(false, 999, ignored, 999),
+ {'EXIT',{{badmatch,999},_}} = catch parallel_scopes_10(false, 700, ignored, 700),
+ {'EXIT',{{badmatch,1000},_}} = catch parallel_scopes_10(false, 999, ignored, 1000),
+ 999 = parallel_scopes_10(true, 999, 999, ignored),
+ 333 = parallel_scopes_10(true, 333, 333, ignored),
+ {'EXIT',{{badmatch,901},_}} = catch parallel_scopes_10(true, 900, 901, ignored),
+
+ 889 = parallel_scopes_11(889, 889, 889),
+ {'EXIT',{{badmatch,800},_}} = catch parallel_scopes_11(889, 800, 889),
+ {'EXIT',{{badmatch,810},_}} = catch parallel_scopes_11(889, 889, 810),
+ {'EXIT',{{badmatch,889},_}} = catch parallel_scopes_11(a, a, a),
+
+ 333 = parallel_scopes_12(333, 333, 333),
+ {'EXIT',{{badmatch,other},_}} = catch parallel_scopes_12(333, other, 333),
+ {'EXIT',{{badmatch,nope},_}} = catch parallel_scopes_12(333, 333, nope),
+
+ [1,100] = parallel_scopes_13(99, 100),
+ {'EXIT',{{badmatch,no},_}} = catch parallel_scopes_13(no, 100),
+ {'EXIT',{{badmatch,nope},_}} = catch parallel_scopes_13(99, nope),
+
+ ok.
+
+parallel_scopes_1a() ->
+ (begin X=1, true end
+ and
+ begin F=(fun () -> X=2 end), F(), true end) andalso X.
+
+parallel_scopes_1b() ->
+ (begin X=1, true end
+ and
+ begin F=(fun () -> X=2 end), F(), true end) andalso (X = 1).
+
+parallel_scopes_1c() ->
+ (begin X=1, true end
+ and
+ begin F=(fun () -> X=2 end), F(), true end) andalso (X = 99).
+
+parallel_scopes_2a() ->
+ begin X=10, true end
+ and
+ begin F=(fun () -> X=20 end), F(), true end
+ and
+ begin X=10, true end andalso X.
+
+parallel_scopes_2b() ->
+ begin X=10, true end
+ and
+ begin F=(fun () -> X=20 end), F(), true end
+ and
+ begin X=15, true end andalso X.
+
+parallel_scopes_2c(A, B) ->
+ begin X=A, true end
+ and
+ begin F = (fun () -> X = make_ref() end), F(), true end
+ and
+ begin X=B, true end andalso X.
+
+parallel_scopes_2d(A, B) ->
+ begin X=A, true end
+ and
+ begin F = (fun () -> X = make_ref() end), F(), true end
+ and
+ begin X=B, true end andalso (X = A).
+
+parallel_scopes_2e(A, B) ->
+ begin X = {a,A}, true end
+ and
+ begin F=(fun () -> X = 20 end), F(), true end
+ and
+ begin X = {a,B}, true end andalso X.
+
+parallel_scopes_3(A) ->
+ L = [X = id(42),
+ fun() -> X = 2 end()],
+ {L,X,A}.
+
+parallel_scopes_4a(A, B) ->
+ 4 = length([X = A,
+ fun() -> X = 2 end(),
+ X = B,
+ fun() -> X = 2 end()]),
+ X.
+
+parallel_scopes_4b(A, B) ->
+ 4 = length([X = A,
+ case id(true) of
+ true ->
+ fun() -> X = 2 end()
+ end,
+ X = B,
+ case id(false) of
+ false ->
+ fun() -> X = 2 end()
+ end]),
+ X.
+
+parallel_scopes_4c(A, B) ->
+ [X = A,
+ fun() -> X = 2 end(),
+ X = B,
+ fun() -> X = 2 end()].
+
+parallel_scopes_5(A, B) ->
+ 4 = length([X = A,
+ [fun() -> X = 2 end()],
+ X = B |
+ case id(false) of
+ false ->
+ [fun() -> X = 2 end()]
+ end]),
+ X.
+
+parallel_scopes_6(A, B) ->
+ 4 = tuple_size({X = A,
+ fun() -> X = 40 end(),
+ X = B,
+ fun() -> X = 50 end()}),
+ X.
+
+parallel_scopes_7(A, B) ->
+ 4 = tuple_size({X = A,
+ [fun() -> X = 40 end()],
+ X = B,
+ [fun() -> X = 50 end()]}),
+ X.
+
+parallel_scopes_8(A, B) ->
+ _ = [X = id(A),
+ begin fun() -> X = 2 end(), X = id(B) end],
+ X.
+
+parallel_scopes_9(A, B, C) ->
+ 3 = length([begin X = id(A), Y = id(A+B) end,
+ fun() -> X = 2 end(),
+ X = id(B)]),
+ {X,Y=C}.
+
+parallel_scopes_10(Bool, A, B, C) ->
+ T = {X = A,
+ case id(Bool) of
+ true ->
+ fun() -> X = 999 end(),
+ X = B;
+ false ->
+ X = C,
+ fun() -> X = 999 end()
+ end},
+ 2 = tuple_size(T),
+ X.
+
+parallel_scopes_11(A, B, C) ->
+ T = {X = A,
+ case id(true) of
+ true ->
+ X = B,
+ 2 = length([X = C, X = C]),
+ fun() -> X = 889 end();
+ false ->
+ X = cannot_happen
+ end},
+ 2 = tuple_size(T),
+ X.
+
+parallel_scopes_12(A, B, C) ->
+ T = {X = A,
+ case id(true) of
+ true ->
+ fun() -> X = whatever end(),
+ 2 = length([X = B, X = B]),
+ X = C;
+ false ->
+ X = cannot_happen
+ end},
+ 2 = tuple_size(T),
+ X.
+
+parallel_scopes_13(A, B) ->
+ [X = 1,
+ fun() ->
+ X = id(whatever),
+ 99 = A,
+ 100 = B
+ end()].
+
coverage(_Config) ->
ok = coverage_1(),
ok.
@@ -308,7 +534,5 @@ coverage_1() ->
("abc") -> party
end,
ok.
-
-
id(I) ->
I.
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 5f45eb3f68..1a96fa4b6c 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,6 +19,10 @@
%%
-module(guard_SUITE).
+%% Warnings for obsolete guards are generated by erl_lint, so we will not
+%% any less testing of the compiler by suppressing them.
+-compile([nowarn_obsolete_guard]).
+
-include_lib("syntax_tools/include/merl.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -1254,8 +1258,30 @@ is_function_2(Config) when is_list(Config) ->
F = fun(_) -> ok end,
if
- is_function(F, 1) -> ok
- end.
+ is_function(F, 1) -> ok
+ end,
+
+ variable_is_function_2(),
+
+ ok.
+
+variable_is_function_2() ->
+ F = fun() -> ok end,
+ [F] = vif_1([id(F)], id(0), []),
+ [F] = vif_2([id(F)], id(0) band 15, []),
+ ok.
+
+%% Completely unknown arity
+vif_1([F | Fs], Arity, Acc) when is_function(F, Arity) ->
+ vif_1(Fs, Arity, [F | Acc]);
+vif_1([], _Arity, Acc) ->
+ Acc.
+
+%% Arity known to be between 0 and 15
+vif_2([F | Fs], Arity, Acc) when is_function(F, Arity) ->
+ vif_2(Fs, Arity, [F | Acc]);
+vif_2([], _Arity, Acc) ->
+ Acc.
tricky(Config) when is_list(Config) ->
not_ok = tricky_1(1, 2),
@@ -1409,23 +1435,37 @@ rel_op_combinations(Config) when is_list(Config) ->
lists:seq(16#06F0, 16#06F9),
Digits = gb_sets:from_list(Digits0),
rel_op_combinations_1(16#0700, Digits),
+ false = is_digit(-1 bsl 59),
+ false = is_digit(-1 bsl 64),
+ false = is_digit((1 bsl 59) - 1),
+ false = is_digit(1 bsl 64),
BrokenRange0 = lists:seq(3, 5) ++
lists:seq(10, 12) ++ lists:seq(14, 20),
BrokenRange = gb_sets:from_list(BrokenRange0),
rel_op_combinations_2(30, BrokenRange),
+ false = broken_range(-1 bsl 64),
+ false = broken_range(1 bsl 64),
Red0 = [{I,2*I} || I <- lists:seq(0, 50)] ++
[{I,5*I} || I <- lists:seq(51, 80)],
Red = gb_trees:from_orddict(Red0),
rel_op_combinations_3(100, Red),
+ 2 * (-1 bsl 64) = redundant(-1 bsl 64),
+ none = redundant(1 bsl 64),
+
+ rel_op_combinations_4(),
- rel_op_combinations_4().
+ rel_op_combinations_5().
rel_op_combinations_1(0, _) ->
ok;
rel_op_combinations_1(N, Digits) ->
Bool = gb_sets:is_member(N, Digits),
+ Bool = is_digit(N),
+ rel_op_combinations_1(N-1, Digits).
+
+is_digit(N) ->
Bool = is_digit_1(N),
Bool = is_digit_2(N),
Bool = is_digit_3(N),
@@ -1436,8 +1476,7 @@ rel_op_combinations_1(N, Digits) ->
Bool = is_digit_8(N),
Bool = is_digit_9(42, N),
Bool = is_digit_10(N, 0),
- Bool = is_digit_11(N, 0),
- rel_op_combinations_1(N-1, Digits).
+ Bool = is_digit_11(N, 0).
is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true;
is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true;
@@ -1502,6 +1541,10 @@ rel_op_combinations_2(0, _) ->
ok;
rel_op_combinations_2(N, Range) ->
Bool = gb_sets:is_member(N, Range),
+ Bool = broken_range(N),
+ rel_op_combinations_2(N-1, Range).
+
+broken_range(N) ->
Bool = broken_range_1(N),
Bool = broken_range_2(N),
Bool = broken_range_3(N),
@@ -1514,8 +1557,7 @@ rel_op_combinations_2(N, Range) ->
Bool = broken_range_10(N),
Bool = broken_range_11(N),
Bool = broken_range_12(N),
- Bool = broken_range_13(N),
- rel_op_combinations_2(N-1, Range).
+ Bool = broken_range_13(N).
broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true;
broken_range_1(X) when X >= 3, X =< 5 -> true;
@@ -1587,6 +1629,10 @@ rel_op_combinations_3(N, Red) ->
none -> none;
{value,V} -> V
end,
+ Val = redundant(N),
+ rel_op_combinations_3(N-1, Red).
+
+redundant(N) ->
Val = redundant_1(N),
Val = redundant_2(N),
Val = redundant_3(N),
@@ -1598,8 +1644,7 @@ rel_op_combinations_3(N, Red) ->
Val = redundant_9(N),
Val = redundant_10(N),
Val = redundant_11(N),
- Val = redundant_12(N),
- rel_op_combinations_3(N-1, Red).
+ Val = redundant_12(N).
redundant_1(X) when X >= 51, X =< 80 -> 5*X;
redundant_1(X) when X < 51 -> 2*X;
@@ -1673,6 +1718,145 @@ rel_op_vars_1(X, N) when X =< N -> le.
rel_op_vars_2(X, N) when X =/= N -> ne;
rel_op_vars_2(X, N) when X >= N -> ge.
+rel_op_combinations_5() ->
+ lt = lt_gt_eq(a, b),
+ lt = lt_gt_eq(1.0, 42),
+ lt = lt_gt_eq(1, 42.0),
+
+ eq = lt_gt_eq(a, a),
+ eq = lt_gt_eq(42, 42),
+ eq = lt_gt_eq(42.0, 42),
+ eq = lt_gt_eq(42, 42.0),
+ eq = lt_gt_eq(42.0, 42.0),
+
+ gt = lt_gt_eq(b, a),
+ gt = lt_gt_eq(42.0, 1),
+ gt = lt_gt_eq(42, 1.0),
+
+ lt = eq_exact_lt_gt(a, b),
+ lt = eq_exact_lt_gt(1.0, 42),
+ lt = eq_exact_lt_gt(1, 42.0),
+
+ eq = eq_exact_lt_gt(a, a),
+ eq = eq_exact_lt_gt(42, 42),
+ none = eq_exact_lt_gt(42, 42.0),
+
+ gt = eq_exact_lt_gt(b, a),
+ gt = eq_exact_lt_gt(42.0, 1),
+ gt = eq_exact_lt_gt(42, 1.0),
+
+ ok.
+
+lt_gt_eq(A, B) ->
+ Res = lt_gt_eq_1(A, B),
+ Res = lt_gt_eq_2(A, B),
+ Res = lt_gt_eq_3(A, B),
+ Res = lt_gt_eq_4(A, B),
+ Res = lt_gt_eq_5(A, B),
+ lt_gt_eq_6(A, B).
+
+%% The last test in each 'if' is unnecessary.
+lt_gt_eq_1(A, B) ->
+ if
+ A < B -> lt;
+ A == B -> eq;
+ A > B -> gt
+ end.
+
+lt_gt_eq_2(A, B) ->
+ if
+ A > B -> gt;
+ A == B -> eq;
+ A < B -> lt
+ end.
+
+lt_gt_eq_3(A, B) ->
+ if
+ A == B -> eq;
+ A < B -> lt;
+ A > B -> gt
+ end.
+
+lt_gt_eq_4(A, B) ->
+ if
+ A == B -> eq;
+ A > B -> gt;
+ A < B -> lt
+ end.
+
+lt_gt_eq_5(A, B) ->
+ if
+ A < B -> lt;
+ A > B -> gt;
+ A == B -> eq
+ end.
+
+lt_gt_eq_6(A, B) ->
+ if
+ A > B -> gt;
+ A < B -> lt;
+ A == B -> eq
+ end.
+
+eq_exact_lt_gt(A, B) ->
+ Res = eq_exact_lt_gt_1(A, B),
+ Res = eq_exact_lt_gt_2(A, B),
+ Res = eq_exact_lt_gt_3(A, B),
+ Res = eq_exact_lt_gt_4(A, B),
+ Res = eq_exact_lt_gt_5(A, B),
+ Res = eq_exact_lt_gt_6(A, B).
+
+%% Not possible to optimize (unless we have type information so we
+%% know that A == B and A =:= B produces the same result).
+
+eq_exact_lt_gt_1(A, B) ->
+ if
+ A < B -> lt;
+ A =:= B -> eq;
+ A > B -> gt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_2(A, B) ->
+ if
+ A > B -> gt;
+ A =:= B -> eq;
+ A < B -> lt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_3(A, B) ->
+ if
+ A =:= B -> eq;
+ A < B -> lt;
+ A > B -> gt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_4(A, B) ->
+ if
+ A =:= B -> eq;
+ A > B -> gt;
+ A < B -> lt;
+ true -> none
+ end.
+
+eq_exact_lt_gt_5(A, B) ->
+ if
+ A < B -> lt;
+ A > B -> gt;
+ A =:= B -> eq;
+ true -> none
+ end.
+
+eq_exact_lt_gt_6(A, B) ->
+ if
+ A > B -> gt;
+ A < B -> lt;
+ A =:= B -> eq;
+ true -> none
+ end.
+
%% Exhaustively test all combinations of relational operators
%% to ensure the correctness of the optimizations in beam_ssa_dead.
@@ -2362,6 +2546,9 @@ beam_bool_SUITE(_Config) ->
erl1384(),
gh4788(),
beam_ssa_bool_coverage(),
+ bad_map_in_guard(),
+ gh_6164(),
+ gh_6184(),
ok.
before_and_inside_if() ->
@@ -2873,6 +3060,42 @@ beam_ssa_bool_coverage_1(V) when V andalso 0, tuple_size(0) ->
beam_ssa_bool_coverage_1(_) ->
error.
+gh_6164() ->
+ true = do_gh_6164(id([])),
+ {'EXIT',{{case_clause,42},_}} = catch do_gh_6164(id(0)),
+
+ ok.
+
+do_gh_6164(V1) ->
+ case 42 of
+ V2 ->
+ case is_list(V1) of
+ V3 ->
+ case V3 orelse V2 of
+ _ when V3 -> 100
+ end =< V3
+ end
+ end.
+
+gh_6184() ->
+ {'EXIT',{function_clause,_}} = catch do_gh_6184(id(true), id({a,b,c})),
+ {'EXIT',{function_clause,_}} = catch do_gh_6184(true, true),
+ {'EXIT',{function_clause,_}} = catch do_gh_6184({a,b,c}, {x,y,z}),
+
+ ok.
+
+do_gh_6184(V1, V2) when (false and is_tuple(V2)) andalso (V1 orelse V2) ->
+ V2 orelse V2.
+
+-record(bad_map_in_guard, {name}).
+bad_map_in_guard() ->
+ error = bad_map_in_guard_1().
+
+bad_map_in_guard_1() when (a#{key => value})#bad_map_in_guard.name ->
+ ok;
+bad_map_in_guard_1() ->
+ error.
+
%%%
%%% End of beam_bool_SUITE tests.
%%%
@@ -2925,5 +3148,4 @@ check(F, Result) ->
ct:fail(check_failed)
end.
-fc({'EXIT',{function_clause,_}}) -> ok;
-fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= guard_inline_SUITE -> ok.
+fc({'EXIT',{function_clause,_}}) -> ok.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index 7482f53ed4..dd93202a38 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -332,7 +332,7 @@ badarg(Reply, _A) ->
Reply.
otp_7223(Config) when is_list(Config) ->
- {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)),
+ {'EXIT', {function_clause, [{?MODULE,_,[1],_}|_]}} = (catch otp_7223_1(1)),
ok.
-compile({inline,[{otp_7223_1,1}]}).
diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl
index fdb93d4b47..7d30f1c74f 100644
--- a/lib/compiler/test/lc_SUITE.erl
+++ b/lib/compiler/test/lc_SUITE.erl
@@ -90,8 +90,8 @@ basic(Config) when is_list(Config) ->
"abc123" = alphanum("?abc123.;"),
%% Aliased patterns.
- [] = [t || {C=D}={_,_} <- []],
- [] = [X || {X,{Y}={X,X}} <- []],
+ [] = [t || {_C=_D}={_,_} <- []],
+ [] = [X || {X,{_Y}={X,X}} <- []],
[t] = [t || "a"++"b" = "ab" <- ["ab"]],
%% Strange filter block.
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index c56dcd40a0..4db5b01109 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -22,123 +22,146 @@
]).
-export([
- %% literals
- t_build_and_match_literals/1, t_build_and_match_literals_large/1,
- t_update_literals/1, t_update_literals_large/1,
- t_match_and_update_literals/1, t_match_and_update_literals_large/1,
- t_update_map_expressions/1,
- t_update_assoc/1, t_update_assoc_large/1,
- t_update_exact/1, t_update_exact_large/1,
- t_guard_bifs/1,
- t_guard_sequence/1, t_guard_sequence_large/1,
- t_guard_update/1, t_guard_update_large/1,
- t_guard_receive/1, t_guard_receive_large/1,
- t_guard_fun/1,
- t_list_comprehension/1,
- t_map_sort_literals/1,
- t_map_size/1, t_map_get/1,
- t_build_and_match_aliasing/1,
- t_is_map/1,
-
- %% variables
- t_build_and_match_variables/1,
- t_update_assoc_variables/1,t_update_exact_variables/1,
- t_nested_pattern_expressions/1,
- t_guard_update_variables/1,
- t_guard_sequence_variables/1,
- t_guard_sequence_mixed/1,
- t_frequency_table/1,
-
- %% warnings
- t_warn_useless_build/1,
- t_warn_pair_key_overloaded/1,
-
- %% not covered in 17.0-rc1
- t_build_and_match_over_alloc/1,
- t_build_and_match_empty_val/1,
- t_build_and_match_val/1,
- t_build_and_match_nil/1,
- t_build_and_match_structure/1,
-
- %% errors in 17.0-rc1
- t_update_values/1,
- t_expand_map_update/1,
- t_export/1,
-
- %% errors in 18
- t_register_corruption/1,
- t_bad_update/1,
-
- %% new in OTP 21
- t_reused_key_variable/1,
-
- %% new in OTP 22
- t_mixed_clause/1,cover_beam_trim/1,
- t_duplicate_keys/1,
-
- %% new in OTP 23
- t_key_expressions/1
- ]).
+ %% literals
+ t_build_and_match_literals/1, t_build_and_match_literals_large/1,
+ t_update_literals/1, t_update_literals_large/1,
+ t_match_and_update_literals/1, t_match_and_update_literals_large/1,
+ t_update_map_expressions/1,
+ t_update_assoc/1, t_update_assoc_large/1,
+ t_update_exact/1, t_update_exact_large/1,
+ t_guard_bifs/1,
+ t_guard_sequence/1, t_guard_sequence_large/1,
+ t_guard_update/1, t_guard_update_large/1,
+ t_guard_receive/1, t_guard_receive_large/1,
+ t_guard_fun/1,
+ t_list_comprehension/1,
+ t_map_sort_literals/1,
+ t_map_size/1, t_map_get/1,
+ t_build_and_match_aliasing/1,
+ t_is_map/1,
+
+ %% variables
+ t_build_and_match_variables/1,
+ t_update_assoc_variables/1,t_update_exact_variables/1,
+ t_nested_pattern_expressions/1,
+ t_guard_update_variables/1,
+ t_guard_sequence_variables/1,
+ t_guard_sequence_mixed/1,
+ t_frequency_table/1,
+
+ %% warnings
+ t_warn_useless_build/1,
+ t_warn_pair_key_overloaded/1,
+
+ %% not covered in 17.0-rc1
+ t_build_and_match_over_alloc/1,
+ t_build_and_match_empty_val/1,
+ t_build_and_match_val/1,
+ t_build_and_match_nil/1,
+ t_build_and_match_structure/1,
+
+ %% errors in 17.0-rc1
+ t_update_values/1,
+ t_expand_map_update/1,
+ t_export/1,
+
+ %% errors in 18
+ t_register_corruption/1,
+ t_bad_update/1,
+
+ %% new in OTP 21
+ t_reused_key_variable/1,
+
+ %% new in OTP 22
+ t_mixed_clause/1,cover_beam_trim/1,
+ t_duplicate_keys/1,
+
+ %% new in OTP 23
+ t_key_expressions/1,
+
+ %% cover more code in beam_call_types
+ t_bif_map_find/1,
+ t_fold_3/1, t_from_keys/1, t_map_2/1, t_maps_take_2/1,
+ t_update_with_3/1, t_update_with_4/1,
+ t_with_2/1,
+
+ %% miscellaneous
+ t_conflicting_destinations/1,
+ t_cse_assoc/1
+ ]).
+
+-define(badmap(V, F, Args), {'EXIT', {{badmap,V}, [{maps,F,Args,_}|_]}}).
+-define(badkey(K, F, Args), {'EXIT', {{badkey,K}, [{maps,F,Args,_}|_]}}).
+-define(badarg(F, Args), {'EXIT', {badarg, [{maps,F,Args,_}|_]}}).
suite() -> [].
all() ->
[
- %% literals
- t_build_and_match_literals, t_build_and_match_literals_large,
- t_update_literals, t_update_literals_large,
- t_match_and_update_literals, t_match_and_update_literals_large,
- t_update_map_expressions,
- t_update_assoc, t_update_assoc_large,
- t_update_exact, t_update_exact_large,
- t_guard_bifs,
- t_guard_sequence, t_guard_sequence_large,
- t_guard_update, t_guard_update_large,
- t_guard_receive, t_guard_receive_large,
- t_guard_fun, t_list_comprehension,
- t_map_sort_literals,
- t_map_size, t_map_get,
- t_build_and_match_aliasing,
- t_is_map,
-
- %% variables
- t_build_and_match_variables,
- t_update_assoc_variables,t_update_exact_variables,
- t_nested_pattern_expressions,
- t_guard_update_variables,
- t_guard_sequence_variables,
- t_guard_sequence_mixed,
- t_frequency_table,
-
- %% warnings
- t_warn_useless_build,
- t_warn_pair_key_overloaded,
-
- %% not covered in 17.0-rc1
- t_build_and_match_over_alloc,
- t_build_and_match_empty_val,
- t_build_and_match_val,
- t_build_and_match_nil,
- t_build_and_match_structure,
-
- %% errors in 17.0-rc1
- t_update_values,
- t_expand_map_update,
- t_export,
-
- %% errors in 18
- t_register_corruption,
- t_bad_update,
-
- %% new in OTP 21
- t_reused_key_variable,
-
- %% new in OTP 22
- t_mixed_clause,cover_beam_trim,
- t_duplicate_keys,
-
- %% new in OTP 23
- t_key_expressions
+ %% literals
+ t_build_and_match_literals, t_build_and_match_literals_large,
+ t_update_literals, t_update_literals_large,
+ t_match_and_update_literals, t_match_and_update_literals_large,
+ t_update_map_expressions,
+ t_update_assoc, t_update_assoc_large,
+ t_update_exact, t_update_exact_large,
+ t_guard_bifs,
+ t_guard_sequence, t_guard_sequence_large,
+ t_guard_update, t_guard_update_large,
+ t_guard_receive, t_guard_receive_large,
+ t_guard_fun, t_list_comprehension,
+ t_map_sort_literals,
+ t_map_size, t_map_get,
+ t_build_and_match_aliasing,
+ t_is_map,
+
+ %% variables
+ t_build_and_match_variables,
+ t_update_assoc_variables,t_update_exact_variables,
+ t_nested_pattern_expressions,
+ t_guard_update_variables,
+ t_guard_sequence_variables,
+ t_guard_sequence_mixed,
+ t_frequency_table,
+
+ %% warnings
+ t_warn_useless_build,
+ t_warn_pair_key_overloaded,
+
+ %% not covered in 17.0-rc1
+ t_build_and_match_over_alloc,
+ t_build_and_match_empty_val,
+ t_build_and_match_val,
+ t_build_and_match_nil,
+ t_build_and_match_structure,
+
+ %% errors in 17.0-rc1
+ t_update_values,
+ t_expand_map_update,
+ t_export,
+
+ %% errors in 18
+ t_register_corruption,
+ t_bad_update,
+
+ %% new in OTP 21
+ t_reused_key_variable,
+
+ %% new in OTP 22
+ t_mixed_clause,cover_beam_trim,
+ t_duplicate_keys,
+
+ %% new in OTP 23
+ t_key_expressions,
+
+ %% cover more code
+ t_bif_map_find,
+ t_fold_3, t_from_keys, t_map_2, t_maps_take_2,
+ t_update_with_3, t_update_with_4, t_with_2,
+
+ %% miscellaneous
+ t_conflicting_destinations,
+ t_cse_assoc
].
groups() -> [].
@@ -2350,6 +2373,179 @@ dup_keys_1(Map) ->
O2
end.
+t_fold_3(_Config) ->
+ Vs = lists:seq(1, 200),
+ M0 = maps:from_list([{{k,I},I} || I<-Vs]),
+ #{ {k,1} := 1, {k,200} := 200} = M0,
+ Tot0 = lists:sum(Vs),
+ Tot1 = maps:fold(fun({k,_},V,A) -> A + V end, 0, M0),
+ true = Tot0 =:= Tot1,
+ Tot2 = maps:fold(fun({k,_},V,A) -> A + V end, 0, maps:iterator(M0)),
+ true = Tot0 =:= Tot2,
+
+ %% error case
+ ?badmap(a, fold, [_,0,a]) = catch maps:fold(fun(_,_,_) -> ok end, 0, id(a)),
+ ?badarg(fold, [<<>>,0,#{}]) = catch maps:fold(id(<<>>),0,#{}),
+ ok.
+
+t_from_keys(_Config) ->
+ Map0 = maps:from_keys(["a", 2, {three}], value),
+ 3 = map_size(Map0),
+ #{"a":=value,2:=value,{three}:=value} = Map0,
+
+ Map1 = maps:from_keys([1, 2, 2], {complex,value}),
+ 2 = map_size(Map1),
+ #{1:={complex,value},2:={complex,value}} = Map1,
+
+ Map2 = maps:from_keys([], value),
+ 0 = map_size(Map2),
+
+ ?badarg(from_keys, [[a|b],value]) = catch maps:from_keys([a|b], value),
+ ?badarg(from_keys, [not_list,value]) = catch maps:from_keys(not_list, value),
+ ok.
+
+t_map_2(_Config) ->
+ Vs = lists:seq(1,200),
+ M0 = maps:from_list([{{k,I},I}||I<-Vs]),
+ #{ {k,1} := 1, {k,200} := 200} = M0,
+ M1 = maps:map(fun({k,_},V) -> V + 42 end, M0),
+ #{ {k,1} := 43, {k,200} := 242} = M1,
+ M2 = maps:map(fun({k,_},V) -> V + 42 end, maps:iterator(M0)),
+ #{ {k,1} := 43, {k,200} := 242} = M2,
+
+ %% error case
+ ?badmap(a, map, [_,a]) = catch maps:map(fun(_,_) -> ok end, id(a)),
+ ?badarg(map, [<<>>,#{}]) = catch maps:map(id(<<>>), #{}),
+ ok.
+
+t_maps_take_2(_Config) ->
+ {yes,Map0} = maps:take(a, #{a => yes, b => no}),
+ true = Map0 =:= #{b => no},
+
+ error = maps:take(a, #{b => no}),
+
+ NotMap = not_map(b),
+ {'EXIT',{{badmap,b},_}} = catch maps:take(a, b),
+
+ ok.
+
+not_map(Term) -> Term.
+
+t_update_with_3(Config) when is_list(Config) ->
+ V1 = value1,
+ V2 = <<"value2">>,
+ V3 = "value3",
+ Map = #{ key1 => V1, key2 => V2, "key3" => V3 },
+ Fun = fun(V) -> [V,V,{V,V}] end,
+
+ #{ key1 := [V1,V1,{V1,V1}] } = maps:update_with(key1, Fun, Map),
+ #{ key2 := [V2,V2,{V2,V2}] } = maps:update_with(key2, Fun, Map),
+ #{ "key3" := [V3,V3,{V3,V3}] } = maps:update_with("key3", Fun, Map),
+
+ %% error case
+ ?badmap(b, update_with, [[a,b],a,b]) = catch maps:update_with([a,b], id(a), b),
+ ?badarg(update_with, [[a,b],a,#{}]) = catch maps:update_with([a,b], id(a), #{}),
+ ?badkey([a,b], update_with, [[a,b],Fun,#{}]) = catch maps:update_with([a,b], Fun,#{}),
+ ok.
+
+t_update_with_4(Config) when is_list(Config) ->
+ V1 = value1,
+ V2 = <<"value2">>,
+ V3 = "value3",
+ Map = #{ key1 => V1, key2 => V2, "key3" => V3 },
+ Fun = fun(V) -> [V,V,{V,V}] end,
+ Init = 3,
+
+ #{ key1 := [V1,V1,{V1,V1}] } = maps:update_with(key1, Fun, Init, Map),
+ #{ key2 := [V2,V2,{V2,V2}] } = maps:update_with(key2, Fun, Init, Map),
+ #{ "key3" := [V3,V3,{V3,V3}] } = maps:update_with("key3", Fun, Init, Map),
+
+ #{ key3 := Init } = maps:update_with(key3, Fun, Init, Map),
+
+ %% error case
+ ?badmap(b, update_with, [[a,b],a,b]) = catch maps:update_with([a,b],id(a), b),
+ ?badarg(update_with, [[a,b],a,#{}]) = catch maps:update_with([a,b], id(a), #{}),
+ ok.
+
+t_with_2(_Config) ->
+ Ki = [11,22,33,44,55,66,77,88,99],
+ M0 = maps:from_list([{{k,I},{v,I}} || I <- lists:seq(1, 100)]),
+ M1 = maps:from_list([{{k,I},{v,I}} || I <- Ki]),
+ M1 = maps:with([{k,I} || I <- Ki], M0),
+
+ %% error case
+ ?badmap(a, with, [[a,b],a]) = catch maps:with([a,b], id(a)),
+ ?badmap(a, with, [{a,b},a]) = catch maps:with({a,b}, id(a)),
+ ?badmap({0,<<>>,97}, with, [[],{0,<<>>,97}]) = catch maps:with([], {0,<<>>,97}),
+ ?badmap({0,<<>>,97}, with, [[false, -20, -8],{0,<<>>,97}]) = catch maps:with([false, -20, -8], {0, <<>>, 97}),
+ ?badarg(with, [a,#{}]) = catch maps:with(a,#{}),
+ ok.
+
+t_bif_map_find(Config) when is_list(Config) ->
+ {ok, 1} = maps:find(a, #{ a=> 1}),
+ {ok, 2} = maps:find(b, #{ a=> 1, b => 2}),
+ {ok, "int"} = maps:find(1, #{ 1 => "int"}),
+ {ok, "float"} = maps:find(1.0, #{ 1.0=> "float"}),
+
+ {ok, "hi"} = maps:find("hello", #{ a=>1, "hello" => "hi"}),
+ {ok, "tuple hi"} = maps:find({1,1.0}, #{ a=>a, {1,1.0} => "tuple hi"}),
+
+ M0 = id(#{ k1=>"v1", <<"k2">> => <<"v3">> }),
+ {ok, "v4"} = maps:find(<<"k2">>, M0#{ <<"k2">> => "v4" }),
+
+
+ %% error case
+ error = maps:find(a, #{}),
+ error = maps:find(a, #{b=>1, c=>2}),
+ error = maps:find(1.0, #{ 1 => "int"}),
+ error = maps:find(1, #{ 1.0 => "float"}),
+ error = maps:find({1.0,1}, #{ a=>a, {1,1.0} => "tuple hi"}), % reverse types in tuple key
+
+ do_badmap(fun(T) ->
+ {'EXIT',{{badmap,T},[{maps,find,_,_}|_]}} =
+ catch maps:find(a, T)
+ end),
+ ok.
+
+t_conflicting_destinations(_Config) ->
+ {'EXIT',{function_clause,_}} =
+ catch do_conflicts(#{{tag,whatever} => true}),
+ {'EXIT',{function_clause,_}} =
+ catch do_conflicts(#{[something] => 42}),
+ {'EXIT',{function_clause,_}} =
+ catch do_conflicts(#{{tag,whatever} => true,
+ #{} => <<0>>,
+ [something] => 42}),
+ ok.
+
+do_conflicts(#{{tag,whatever} := true,
+ #{} := <<bad_integer,0:(is_integer(a))>>} =
+ #{[something] := 42}) ->
+ ok.
+
+t_cse_assoc(_Config) ->
+ {'EXIT',{{case_clause,#{key:=any}},_}} = catch do_cse_assoc(id(any)),
+
+ {'EXIT',{{case_clause,#{key:=value}},_}} = catch do_cse_assoc(id(#{}), id(value)),
+ 42 = do_cse_assoc(id(#{assoc => 42}), id(any)),
+
+ ok.
+
+do_cse_assoc(V) ->
+ case #{key => V} of
+ #{assoc := Assoc} ->
+ %% The CSE optimization would consider the first two arguments in
+ %% the argument for `put_map` to be the key `alloc` and the value
+ %% `#{}`.
+ Assoc
+ end.
+
+do_cse_assoc(M, V) ->
+ case M#{key => V} of
+ #{assoc := Assoc} ->
+ Assoc
+ end.
+
%% aux
rand_terms(0) -> [];
@@ -2408,7 +2604,11 @@ rand_map() ->
3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
end.
-
+do_badmap(Test) ->
+ Terms = [Test,fun erlang:abs/1,make_ref(),self(),0.0/id(-1),
+ <<0:1024>>,<<1:1>>,<<>>,<<1,2,3>>,
+ [],{a,b,c},[a,b],atom,10.0,42,(1 bsl 65) + 3],
+ [Test(T) || T <- Terms].
%% Use this function to avoid compile-time evaluation of an expression.
id(I) -> I.
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 422d3a6cf9..c10e3158e1 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1,
coverage/1,grab_bag/1,literal_binary/1,
unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1,
- tuple_size_in_try/1,match_boolean_list/1]).
+ tuple_size_in_try/1,match_boolean_list/1,
+ mutable_variables/1]).
-include_lib("common_test/include/ct.hrl").
@@ -43,7 +44,8 @@ groups() ->
underscore,match_map,map_vars_used,coverage,
grab_bag,literal_binary,unary_op,eq_types,
match_after_return,match_right_tuple,
- tuple_size_in_try,match_boolean_list]}].
+ tuple_size_in_try,match_boolean_list,
+ mutable_variables]}].
init_per_suite(Config) ->
@@ -351,8 +353,8 @@ entirely() ->
[receive _ -> Voice end || banking <- printer].
printer() ->
- {[Indoor] = [] = associates},
- [ireland || Indoor <- Indoor].
+ {[_Indoor] = [] = associates},
+ [ireland || _Indoor <- _Indoor].
tench() ->
E = begin
@@ -364,7 +366,7 @@ tench() ->
perch(X) ->
begin
put(perch, get(perch)+1),
- [A] = [] = {spine,X}
+ [_A] = [] = {spine,X}
end.
salmon() ->
@@ -497,7 +499,7 @@ untuplify_2(V1, V2) ->
shortcut_boolean(Config) when is_list(Config) ->
false = shortcut_boolean_1([0]),
true = shortcut_boolean_1({42}),
- maybe = shortcut_boolean_1(self()),
+ 'maybe' = shortcut_boolean_1(self()),
{'EXIT',_} = (catch shortcut_boolean_1([a,b])),
{'EXIT',_} = (catch shortcut_boolean_1({a,b})),
ok.
@@ -511,7 +513,7 @@ shortcut_boolean_1(X) ->
end,
not V;
false ->
- maybe
+ 'maybe'
end,
id(Outer).
@@ -1018,4 +1020,24 @@ match_boolean_list(Config) when is_list(Config) ->
[false | _] -> ok
end.
+%% GH-6873. Bound variables would be overwritten.
+mutable_variables(_Config) ->
+ {'EXIT',{{badmatch,0},_}} = catch mutable_variables_1(),
+
+ F = fun() -> id({tag,whatever}) end,
+ whatever = mutable_variables_2(id({tag,whatever}), F),
+ {'EXIT',{{badmatch,{tag,whatever}},_}} = catch mutable_variables_2(id(a), F),
+
+ ok.
+
+mutable_variables_1() ->
+ Zero = 0,
+ One = 1,
+ Result = One = Zero,
+ {Result,One,Zero}.
+
+mutable_variables_2(Middle, Fun) ->
+ {tag,V} = Middle = Fun(),
+ V.
+
id(I) -> I.
diff --git a/lib/compiler/test/maybe_SUITE.erl b/lib/compiler/test/maybe_SUITE.erl
new file mode 100644
index 0000000000..beecb03180
--- /dev/null
+++ b/lib/compiler/test/maybe_SUITE.erl
@@ -0,0 +1,285 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(maybe_SUITE).
+-include_lib("common_test/include/ct.hrl").
+
+%% Note: also require the feature to be set during runtime as long as
+%% the feature is experimental. This is currently done in ../Makefile
+%% by overriding the test target. Ugly and very non local.
+-feature(maybe_expr, enable).
+
+-export([all/0, groups/0, init_per_suite/1, end_per_suite/1]).
+-export([basic/1, nested/1]).
+
+all() ->
+ [{group,p}].
+
+groups() ->
+ [{p,[parallel],
+ [basic,nested]}].
+
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+-record(value, {v}).
+
+basic(_Config) ->
+ {ok,42,fish} = basic_1(0, #{0 => {ok,42}, 42 => {ok,fish}}),
+ error = basic_1(0, #{0 => {ok,42}, 42 => {error,whatever}}),
+ error = basic_1(0, #{0 => {ok,42}, 42 => error}),
+ error = basic_1(0, #{0 => error}),
+ error = basic_1(0, #{0 => {error,whatever}}),
+ some_value = basic_1(0, #{0 => #value{v=some_value}}),
+ {'EXIT',{{else_clause,something_wrong},[_|_]}} = catch basic_1(0, #{0 => something_wrong}),
+
+ {ok,life,"universe",everything} = basic_2(0, #{0 => {ok,life},
+ life => "universe",
+ "universe" => {ok,everything}}),
+ error = basic_2(0, #{0 => {ok,life},
+ life => "universe",
+ "universe" => error}),
+ {'EXIT',{{badmatch,not_a_list},[_|_]}} = catch basic_2(0, #{0 => {ok,life},
+ life => not_a_list}),
+ {'EXIT',{{else_clause,not_ok},[_|_]}} = catch basic_2(0, #{0 => {ok,life},
+ life => "universe",
+ "universe" => not_ok}),
+ {'EXIT',{{else_clause,not_ok},[_|_]}} = catch basic_2(0, #{0 => not_ok}),
+
+ {ok,42,fish,dolphins} = basic_3(0, #{0 => {ok,42}, 42 => {ok,fish},
+ fish => {ok,#value{v=dolphins}}}),
+ {error,whatever} = basic_3(0, #{0 => {ok,42}, 42 => {error,whatever}}),
+ failed = basic_3(0, #{0 => {ok,42}, 42 => failed}),
+ failed_early = basic_3(0, #{0 => failed_early}),
+
+ y = maybe nomatch ?= id(x) else _ -> y end,
+ y = maybe nomatch ?= id(x) else _ -> x, y end,
+
+ x = maybe nomatch ?= id(x) else E1 -> E1 end,
+
+ 6 = maybe X1 = 2+2, X1+2 end,
+ 6 = maybe X2 = 2+2, X2+2 else {error, T} -> T end,
+ {"llo", "hello", "hello"} = maybe Y1 = "he"++X3=Z1 ?= "hello", {X3,Y1,Z1} end,
+ {"llo", "hello", "llo"} = maybe Y2 = "he"++(X4=Z2) ?= "hello", {X4,Y2,Z2} end,
+
+ whatever = maybe
+ AlwaysMatching ?= id(whatever),
+ AlwaysMatching
+ else
+ E2 -> E2
+ end,
+
+ <<0>> = basic_4(id({<<0>>})),
+
+ ok.
+
+basic_1(V0, M) ->
+ Res = basic_1a(V0, M),
+ {wrapped,Res} = basic_1b(V0, M),
+ {wrapped,Res} = basic_1c(V0, M),
+ Res.
+
+basic_1a(V0, M) ->
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ {ok,V2} ?= do_something(V1, M),
+ {ok,V1,V2}
+ else
+ {error,_} ->
+ error;
+ error ->
+ error;
+ #value{v=V} ->
+ V
+ end.
+
+basic_1b(V0, M) ->
+ Result =
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ {ok,V2} ?= do_something(V1, M),
+ {ok,V1,V2}
+ else
+ {error,_} ->
+ error;
+ error ->
+ error;
+ #value{v=V} ->
+ V
+ end,
+ {wrapped,Result}.
+
+basic_1c(V0, M) ->
+ OK = id(ok),
+ Error = id(error),
+ Result =
+ maybe
+ {OK,V1} ?= do_something(V0, M),
+ {OK,V2} ?= do_something(V1, M),
+ {OK,V1,V2}
+ else
+ {Error,_} ->
+ Error;
+ Error ->
+ Error;
+ #value{v=V} ->
+ V
+ end,
+ {wrapped,Result}.
+
+basic_2(V0, M) ->
+ Res = basic_2a(V0, M),
+ {wrapped,Res} = basic_2b(V0, M),
+ Res.
+
+basic_2a(V0, M) ->
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ V2 = [_|_] = do_something(V1, M),
+ {ok,V3} ?= do_something(V2, M),
+ {ok,V1,V2,V3}
+ else
+ {error,_} ->
+ error;
+ error ->
+ error;
+ #value{v=V} ->
+ V
+ end.
+
+basic_2b(V0, M) ->
+ Result =
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ V2 = [_|_] = do_something(V1, M),
+ {ok,V3} ?= do_something(V2, M),
+ {ok,V1,V2,V3}
+ else
+ {error,_} ->
+ error;
+ error ->
+ error;
+ #value{v=V} ->
+ V
+ end,
+ _ = id(0),
+ {wrapped,Result}.
+
+basic_3(V0, M) ->
+ Res = basic_3a(V0, M),
+ {wrapped,Res} = basic_3b(V0, M),
+ Res.
+
+basic_3a(V0, M) ->
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ {ok,V2} ?= do_something(V1, M),
+ {ok,#value{v=V3}} ?= do_something(V2, M),
+ {ok,V1,V2,V3}
+ end.
+
+basic_3b(V0, M) ->
+ Result =
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ {ok,V2} ?= do_something(V1, M),
+ {ok,#value{v=V3}} ?= do_something(V2, M),
+ {ok,V1,V2,V3}
+ end,
+ {wrapped,Result}.
+
+basic_4({X}) ->
+ maybe
+ <<_:(ok)>> ?= X
+ end.
+
+nested(_Config) ->
+ {outer_fail,not_ok} = nested_1(0, #{0 => not_ok}),
+ {x,{error,inner}} = nested_1(0, #{0 => {ok,x}, x => {error,inner}}),
+ {outer_fail,{unexpected,not_error}} = nested_1(0, #{0 => {ok,x}, x => not_error}),
+ ok.
+
+nested_1(V0, M) ->
+ Res = nested_1a(V0, M),
+ {wrapped,Res} = nested_1b(V0, M),
+ {wrapped,Res} = nested_1c(V0, M),
+ Res.
+
+nested_1a(V0, M) ->
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ V2 = {error,_} ?=
+ maybe
+ {error, _} ?= id(do_something(V1, M))
+ else
+ Unexpected -> {unexpected, Unexpected}
+ end,
+ {V1,V2}
+ else
+ Res -> {outer_fail,Res}
+ end.
+
+nested_1b(V0, M) ->
+ Result =
+ maybe
+ {ok,V1} ?= do_something(V0, M),
+ V2 = {error,_} ?=
+ maybe
+ {error, _} ?= id(do_something(V1, M))
+ else
+ Unexpected -> {unexpected, Unexpected}
+ end,
+ {V1,V2}
+ else
+ Res -> {outer_fail,Res}
+ end,
+ {wrapped,Result}.
+
+nested_1c(V0, M) ->
+ Result =
+ maybe
+ R ?= maybe
+ {ok,V1} ?= do_something(V0, M),
+ {error,_} = V2 ?=
+ maybe
+ {error, _} ?= id(do_something(V1, M))
+ else
+ Unexpected -> {unexpected, Unexpected}
+ end,
+ {V1,V2}
+ else
+ Res -> {outer_fail,Res}
+ end,
+ R
+ else
+ Var -> Var
+ end,
+ {wrapped,Result}.
+
+%% Utility functions.
+
+do_something(V, M) ->
+ map_get(id(V), M).
+
+id(X) -> X.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index f0115008fc..37fb3854de 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,6 +49,9 @@
%% opaque types from attributes in v3_kernel.
-opaque misc_SUITE_test_cases() :: [atom()].
+%% Cover handling of the `nifs` attribute.
+-nifs([all/0]).
+
init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) ->
Config.
@@ -71,6 +74,13 @@ groups() ->
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
+ if
+ is_atom(Config) ->
+ %% Cover handling of load_nif. Will never actually be called.
+ _ = erlang:load_nif("no_real_nif", 42);
+ true ->
+ ok
+ end,
Config.
end_per_suite(_Config) ->
@@ -257,17 +267,6 @@ silly_coverage(Config) when is_list(Config) ->
TrimInput = BlockInput,
expect_error(fun() -> beam_trim:module(TrimInput, []) end),
- %% beam_peep. This is tricky. Use a select instruction with
- %% an odd number of elements in the list to crash
- %% prune_redundant_values/2 but not beam_clean:clean_labels/1.
- PeepInput = {?MODULE,[{foo,0}],[],
- [{function,foo,0,2,
- [{label,1},
- {func_info,{atom,?MODULE},{atom,foo},0},
- {label,2},{select,select_val,r,{f,2},[{f,2}]}]}],
- 2},
- expect_error(fun() -> beam_peep:module(PeepInput, []) end),
-
BeamZInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
[{label,1},
diff --git a/lib/compiler/test/property_test/compile_prop.erl b/lib/compiler/test/property_test/compile_prop.erl
index 75ff38285d..e28dc709d2 100644
--- a/lib/compiler/test/property_test/compile_prop.erl
+++ b/lib/compiler/test/property_test/compile_prop.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,24 +36,62 @@
-import(lists, [duplicate/2,foldl/3]).
--define(REPETITIONS, 1000).
-
compile() ->
- numtests(?REPETITIONS, compile_1()).
-
-compile_1() ->
- Opts = [{resize,true}],
+ %% {weight, {yes_multi_field_init, 0}}
+ Opts = [{weight, {yes_multi_field_init, 0}},
+ {resize,true}],
?FORALL(Abstr, proper_erlang_abstract_code:module(Opts),
- ?WHENFAIL(
- begin
- io:format("~ts\n", [[erl_pp:form(F) || F <- Abstr]]),
- compile(Abstr, [binary,report_errors])
- end,
- case compile(Abstr, [binary]) of
- {error, _Es, _Ws} -> false;
- _ -> true
- end)).
-
-compile(Abstr, Opts) ->
- compile:noenv_forms(Abstr, Opts).
+ compile(Abstr)).
+
+compile(Forms) ->
+ compile(Forms, compiler_variants()).
+
+compile(Forms, [Opts|OptsL]) ->
+ case spawn_compile(Forms, [return, binary | Opts]) of
+ {ok,_Mod,Bin,_EsWs} when is_binary(Bin) ->
+ %% Uncomment the following lines to print
+ %% the generated source code.
+ %% io:format("<S>\n~ts\n</S>\n",
+ %% [[erl_pp:form(F) || F <- Forms]]),
+
+ %% Uncomment the following line to print the
+ %% generated abstract code.
+ %% io:format("<abstr>\n~p\n</abstr>\n", [Forms]),
+ compile(Forms, OptsL);
+ Err ->
+ io:format("compile: ~p\n", [Err]),
+ io:format("with options ~p\n", [Opts]),
+ io:format("<S>\n~ts\n</S>\n",
+ [[erl_pp:form(F) || F <- Forms]]),
+ false
+ end;
+compile(_Forms, []) ->
+ true.
+
+spawn_compile(Forms, Options) ->
+ {Pid,Ref} = spawn_monitor(fun() ->
+ exit(compile:noenv_forms(Forms, Options))
+ end),
+ receive
+ {'DOWN',Ref,process,Pid,Ret} ->
+ Ret
+ after 600_000 ->
+ timeout
+ end.
+
+compiler_variants() ->
+ [
+ [ssalint,clint0,clint],
+ [r22,ssalint],
+ [no_type_opt,ssalint],
+ [no_module_opt,ssalint],
+ [no_copt,ssalint,clint0],
+ [no_copt,no_bool_opt,no_share_opt,no_bsm_opt,no_fun_opt,
+ no_ssa_opt,no_recv_opt,no_postopt,ssalint,clint0],
+ [no_bool_opt,no_share_opt,no_bsm_opt,no_fun_opt,no_ssa_opt,
+ no_recv_opt,ssalint,clint0,clint],
+ [no_copt,no_bool_opt,no_share_opt,no_bsm_opt,no_fun_opt,
+ no_ssa_opt,no_recv_opt,ssalint,clint0]
+ ].
+
-endif.
diff --git a/lib/compiler/test/random_code_SUITE.erl b/lib/compiler/test/random_code_SUITE.erl
index 04f6cbc1d2..2c242ba437 100644
--- a/lib/compiler/test/random_code_SUITE.erl
+++ b/lib/compiler/test/random_code_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,20 +20,18 @@
-module(random_code_SUITE).
--export([all/0, suite/0, groups/0,
+-export([all/0, suite/0,
init_per_suite/1, end_per_suite/1]).
-export([compile/1]).
+-define(NUMTESTS, 1000).
+
suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- [{group,property_tests}].
-
-groups() ->
- [{property_tests,[parallel],
- [compile]}].
+ [compile].
init_per_suite(Config0) ->
case ct_property_test:init_per_suite(Config0) of
@@ -52,6 +50,18 @@ init_per_suite(Config0) ->
end_per_suite(Config) ->
Config.
-compile(Config) ->
- true = ct_property_test:quickcheck(compile_prop:compile(), Config),
+compile(_Config) ->
+ NumTests = case os:getenv("ERL_RANDOM_CODE_NUMTESTS") of
+ false ->
+ ?NUMTESTS;
+ NumTests0 ->
+ list_to_integer(NumTests0)
+ end,
+
+ %% Conservatively assume that we can run 10 tests each second.
+ TimeTrap = {seconds,60_000 + (NumTests+99) div 100},
+ ct:timetrap(TimeTrap),
+ io:format("~p tests\n", [NumTests]),
+ true = proper:quickcheck(compile_prop:compile(),
+ [quiet,{numtests,NumTests}]),
ok.
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 5ddabe9346..5b52dd8288 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,8 @@
match_built_terms/1,elusive_common_exit/1,
return_before_receive/1,trapping/1,
after_expression/1,in_after/1,
- type_optimized_markers/1]).
+ type_optimized_markers/1,
+ bs_get_tail/1]).
-include_lib("common_test/include/ct.hrl").
@@ -53,7 +54,8 @@ groups() ->
match_built_terms,elusive_common_exit,
return_before_receive,trapping,
after_expression,in_after,
- type_optimized_markers]},
+ type_optimized_markers,
+ bs_get_tail]},
{slow,[],[ref_opt]}].
init_per_suite(Config) ->
@@ -190,6 +192,10 @@ coverage(Config) when is_list(Config) ->
self() ! whatever,
{'EXIT',{{badmatch,_},_}} = (catch [a || other = receive whatever -> false end]),
+ %% Cover code in beam_ssa_pre_codegen.
+ self() ! 0,
+ 42 = receive_in_try_and_after(),
+
ok.
receive_in_called_function() ->
@@ -355,6 +361,22 @@ commit_participant(Coord, Tid) ->
end,
ok.
+receive_in_try_and_after() ->
+ try
+ id(42)
+ catch
+ _:V0 when true#{}; whatever ->
+ receive
+ _ when 1; V0 ->
+ 1
+ end
+ after
+ receive
+ 0 ->
+ car
+ end
+ end.
+
%% OTP-7980. Thanks to Vincent de Phily. The following code would
%% be inccorrectly optimized by beam_jump.
@@ -527,7 +549,7 @@ recv_in_try_1(Timeout, Format) ->
%% {test,test_arity,{f,148},[{x,0},2]}.
%% {get_tuple_element,{x,0},0,{y,1}}. %y1 is fragile.
%%
- %% %% Here the fragility of y1 would be be progated to
+ %% %% Here the fragility of y1 would be be propagated to
%% %% the 'catch' below. Incorrect, since get_tuple_element
%% %% can't fail.
%% {get_tuple_element,{x,0},1,{x,2}}.
@@ -859,6 +881,9 @@ type_optimized_markers(_Config) ->
self() ! Ref,
gaffel = tom_2(Ref),
+ self() ! {inet_reply, self(), all_well},
+ all_well = tom_3(self(), undefined, 1),
+
ok.
tom_1(Ref) ->
@@ -897,6 +922,36 @@ tom_2(Ref) ->
gaffel
end.
+tom_3(S, Mref, ReplyTimeout) ->
+ receive
+ {inet_reply, S, Status} ->
+ case Mref of
+ undefined ->
+ ok;
+ _ ->
+ demonitor(Mref, [flush])
+ end,
+ Status
+ after
+ ReplyTimeout ->
+ tom_3(S, monitor(process, S), ReplyTimeout)
+ end.
+
+bs_get_tail(_Config) ->
+ Ref = make_ref(),
+ self() ! {<<1,"abc">>, Ref},
+ {<<"abc">>,Ref} = do_bs_get_tail(),
+
+ ok.
+
+do_bs_get_tail() ->
+ receive
+ {<<1, FieldsBin/bits>>, StreamRef} ->
+ A = id(FieldsBin),
+ B = id(StreamRef),
+ {A,B}
+ end.
+
%%%
%%% Common utilities.
%%%
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl
index 7ce6e6103c..ea228d4ac6 100644
--- a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_10.erl
@@ -7,7 +7,7 @@
f() ->
Ref = make_ref(),
receive
- %% Artifical example to cover more code in beam_receive.
+ %% Artificial example to cover more code in beam_receive.
{X,Y} when Ref =/= X, Ref =:= Y ->
ok
end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl
index 62f439fc42..b58d9f7561 100644
--- a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_11.erl
@@ -4,7 +4,7 @@
?MODULE() ->
ok.
-%% Artifical example to cover more code in beam_receive.
+%% Artificial example to cover more code in beam_receive.
do_call(Process, Request) ->
Mref = erlang:monitor(process, Process),
Process ! Request,
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_25.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_25.erl
new file mode 100644
index 0000000000..f9500ca0b5
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_25.erl
@@ -0,0 +1,12 @@
+-module(yes_25).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f() ->
+ {_,Ref} = spawn_monitor(name@host, fun() -> ok end),
+ receive
+ {'DOWN',Ref,_,_,Reason} ->
+ Reason
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_26.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_26.erl
new file mode 100644
index 0000000000..5be91ea6b0
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_26.erl
@@ -0,0 +1,15 @@
+-module(yes_26).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+f() ->
+ {_,Ref} = spawn_monitor(?MODULE, init, []),
+ receive
+ {'DOWN',Ref,_,_,Reason} ->
+ Reason
+ end.
+
+init() ->
+ ok.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_27.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_27.erl
new file mode 100644
index 0000000000..ca35ed7bf5
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_27.erl
@@ -0,0 +1,19 @@
+-module(yes_27).
+-export([?MODULE/0,do_multi_call/0]).
+
+?MODULE() ->
+ ok.
+
+do_multi_call() ->
+ %% The calls to make_ref/0 and erlang:monitor/2 will be
+ %% in the same block.
+ Tag = make_ref(),
+ Receiver = spawn(name@host, fun() -> ok end),
+ Mref = monitor(process, Receiver, []),
+ Receiver ! {self(),Tag},
+ receive
+ {'DOWN',Mref,_,_,{_Receiver,Tag,Result}} ->
+ Result;
+ {'DOWN',Mref,_,_,Reason} ->
+ exit(Reason)
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_28.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_28.erl
new file mode 100644
index 0000000000..ac01af2c4e
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_28.erl
@@ -0,0 +1,21 @@
+-module(yes_28).
+-compile([export_all,nowarn_export_all]).
+
+?MODULE() ->
+ ok.
+
+nested_receives(Pid) ->
+ Ref = make_ref(),
+ MRef = erlang:monitor(process, Pid),
+ ARef = erlang:alias([]),
+ receive
+ Ref ->
+ receive
+ MRef ->
+ receive
+ ARef -> gurka
+ end
+ end;
+ MRef ->
+ gaffel
+ end.
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 2dd40e6a77..cd60525691 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,17 +73,17 @@ errors(Config) when is_list(Config) ->
Foo = #foo{a=1,b=2,c=3,d=4},
#foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42),
- {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)),
- {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)),
- {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)),
- {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)),
-
- {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)),
- {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)),
- {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)),
- {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)),
- {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19,
- 35, 17, 42, -2)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_bar(Foo, 19)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_bar(Foo, 19, 35)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_bar(Foo, 19, 35, 17)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)),
+
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_barf(Foo, 19)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_barf(Foo, 19, 35)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_barf(Foo, 19, 35, 17)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)),
+ {'EXIT',{{badrecord,Foo},_}} = (catch update_foo_barf(Foo, 19,
+ 35, 17, 42, -2)),
ok.
diff --git a/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl
index dbd2419ad2..26c5c74986 100644
--- a/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl
+++ b/lib/compiler/test/record_SUITE_data/record_access_in_guards.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -172,7 +172,7 @@ t() ->
ok = F(R, 42, tab),
error = F(R, 42, a),
error = F(R, 0, tab),
- {'EXIT',{{badrecord,r},_}} = (catch F({x,y,z}, 4, 5)),
+ {'EXIT',{{badrecord,{x,y,z}},_}} = (catch F({x,y,z}, 4, 5)),
ok
end(#r{a=42,b=tab}),
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 5ed222fc54..c4d377e4f1 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
-compile({no_auto_import,[binary_part/2]}).
-export([id/1,recompile/1,recompile_core/1,parallel/0,
uniq/0,opt_opts/1,get_data_dir/1,
- is_cloned_mod/1,smoke_disasm/1,p_run/2,
+ is_cloned_mod/1,smoke_disasm/1,p_run/2,p_run/3,
highest_opcode/1]).
%% Used by test case that override BIFs.
@@ -82,12 +82,15 @@ uniq() ->
opt_opts(Mod) ->
Comp = Mod:module_info(compile),
- {options,Opts} = lists:keyfind(options, 1, Comp),
+ %% `options` may not be set at all if +deterministic is enabled.
+ Opts = proplists:get_value(options, Comp, []),
lists:filter(fun
(debug_info) -> true;
(dialyzer) -> true;
+ ({feature,_,enable}) -> true;
+ ({feature,_,disable}) -> true;
(inline) -> true;
- (no_bsm3) -> true;
+ (no_bs_create_bin) -> true;
(no_bsm_opt) -> true;
(no_copt) -> true;
(no_fun_opt) -> true;
@@ -95,11 +98,11 @@ opt_opts(Mod) ->
(no_make_fun3) -> true;
(no_module_opt) -> true;
(no_postopt) -> true;
- (no_put_tuple2) -> true;
(no_recv_opt) -> true;
(no_share_opt) -> true;
(no_shared_fun_wrappers) -> true;
- (no_ssa_float) -> true;
+ (no_ssa_opt_float) -> true;
+ (no_ssa_opt_ranges) -> true;
(no_ssa_opt) -> true;
(no_stack_trimming) -> true;
(no_swap) -> true;
@@ -118,7 +121,6 @@ get_data_dir(Config) ->
"_no_copt_SUITE",
"_post_opt_SUITE",
"_inline_SUITE",
- "_r21_SUITE",
"_no_module_opt_SUITE",
"_no_type_opt_SUITE",
"_no_ssa_opt_SUITE"],
@@ -130,14 +132,16 @@ get_data_dir(Config) ->
is_cloned_mod(Mod) ->
is_cloned_mod_1(atom_to_list(Mod)).
-%% Test whether Mod is a cloned module.
+%% Test whether Mod is a cloned module. We don't consider modules
+%% compiled with compatibility for an older release cloned (that
+%% will improve coverage).
is_cloned_mod_1("_no_opt_SUITE") -> true;
is_cloned_mod_1("_no_copt_SUITE") -> true;
is_cloned_mod_1("_no_ssa_opt_SUITE") -> true;
+is_cloned_mod_1("_no_type_opt_SUITE") -> true;
is_cloned_mod_1("_post_opt_SUITE") -> true;
is_cloned_mod_1("_inline_SUITE") -> true;
-is_cloned_mod_1("_21_SUITE") -> true;
is_cloned_mod_1("_no_module_opt_SUITE") -> true;
is_cloned_mod_1([_|T]) -> is_cloned_mod_1(T);
is_cloned_mod_1([]) -> false.
@@ -154,9 +158,20 @@ highest_opcode(Beam) ->
%% Will fail the test case if there were any errors.
p_run(Test, List) ->
- S = erlang:system_info(schedulers),
+ %% Limit the number of parallel processes to avoid running out of
+ %% memory.
+ S = case {erlang:system_info(schedulers),erlang:system_info(wordsize)} of
+ {S0,4} ->
+ min(S0, 2);
+ {S0,8} ->
+ min(S0, 8)
+ end,
N = S + 1,
- io:format("p_run: ~p parallel processes\n", [N]),
+ p_run(Test, List, N).
+
+p_run(Test, List, N) ->
+ io:format("p_run: ~p parallel processes; ~p jobs\n",
+ [N,length(List)]),
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 8ba8e39d89..6466234a91 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,11 +21,11 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,basic/1,lean_throw/1,
- try_of/1,try_after/1,%after_bind/1,
+ try_of/1,try_after/1,
catch_oops/1,after_oops/1,eclectic/1,rethrow/1,
nested_of/1,nested_catch/1,nested_after/1,
nested_horrid/1,last_call_optimization/1,bool/1,
- plain_catch_coverage/1,andalso_orelse/1,get_in_try/1,
+ andalso_orelse/1,get_in_try/1,
hockey/1,handle_info/1,catch_in_catch/1,grab_bag/1,
stacktrace/1,nested_stacktrace/1,raise/1,
no_return_in_try_block/1,
@@ -45,7 +45,7 @@ groups() ->
[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,get_in_try,
+ bool,andalso_orelse,get_in_try,
hockey,handle_info,catch_in_catch,grab_bag,
stacktrace,nested_stacktrace,raise,
no_return_in_try_block,expression_export,
@@ -121,7 +121,7 @@ basic(Conf) when is_list(Conf) ->
%% Try/of
ok = try V of
{a,variable} -> ok
- catch nisse -> erro
+ catch nisse -> error
end,
%% Unmatchable clauses.
@@ -327,35 +327,6 @@ try_after_try(X, Y) ->
_ -> ok
end).
--ifdef(begone).
-
-after_bind(Conf) when is_list(Conf) ->
- V = [make_ref(),self()|value],
- {value,{value,V}} =
- after_bind_1({value,V}, V, {value,V}),
- ok.
-
-after_bind_1(X, V, Y) ->
- try
- Try =
- try foo(X) of
- V -> value
- catch
- C1:V -> {caught,C1}
- after
- After = foo(Y)
- end,
- {Try,After}
- of
- V -> {value,V}
- catch
- C:D -> {caught,{C,D}}
- end.
-
--endif.
-
-
-
catch_oops(Conf) when is_list(Conf) ->
V = {v,[a,l|u],{e},self()},
{value,V} = catch_oops_1({value,V}),
@@ -1004,18 +975,10 @@ do_bool(A0, B) ->
error
end.
-plain_catch_coverage(Config) when is_list(Config) ->
- %% Cover some code in beam_block:alloc_may_pass/1.
- {a,[42]} = do_plain_catch_list(42).
-
-do_plain_catch_list(X) ->
- B = [X],
- catch id({a,B}).
-
andalso_orelse(Config) when is_list(Config) ->
{2,{a,42}} = andalso_orelse_1(true, {a,42}),
{b,{b}} = andalso_orelse_1(false, {b}),
- {catched,no_tuple} = andalso_orelse_1(false, no_tuple),
+ {caught,no_tuple} = andalso_orelse_1(false, no_tuple),
ok = andalso_orelse_2({type,[a]}),
also_ok = andalso_orelse_2({type,[]}),
@@ -1031,7 +994,7 @@ andalso_orelse_1(A, B) ->
element(1, B)
end
catch error:_ ->
- catched
+ caught
end,B}.
andalso_orelse_2({Type,Keyval}) ->
@@ -1259,7 +1222,7 @@ stacktrace(_Config) ->
try
throw(x)
catch
- throw:x:IntentionallyUnused ->
+ throw:x:_IntentionallyUnused ->
ok
end.
@@ -1578,10 +1541,13 @@ throw_opt_crash_1(true, {_, _}=Term) ->
throw_opt_crash_1(false, _Term) ->
ok.
-coverage(_Config) ->
+coverage(Config) ->
{'EXIT',{{badfun,true},[_|_]}} = (catch coverage_1()),
ok = coverage_ssa_throw(),
error = coverage_pre_codegen(),
+ {a,[42]} = do_plain_catch_list(42),
+ cover_raise(Config),
+
ok.
%% Cover some code in beam_trim.
@@ -1682,5 +1648,28 @@ coverage_pre_codegen() ->
error
end.
+%% Cover some code in beam_block:alloc_may_pass/1.
+do_plain_catch_list(X) ->
+ B = [X],
+ catch id({a,B}).
+
+cover_raise(Config) ->
+ UncertainClass = uncertain_class(Config),
+ badarg = erlang:raise(UncertainClass, reason, []),
+ BadClass = bad_class(Config),
+ badarg = erlang:raise(BadClass, reason, []),
+ ok.
+
+uncertain_class(Config) ->
+ case Config of
+ [never_ever] -> error;
+ _ -> undefined_class
+ end.
+
+bad_class(Config) ->
+ case Config of
+ [never_ever] -> bad_class;
+ _ -> also_bad
+ end.
id(I) -> I.
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 53f21fcbbe..5f61485b4c 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,8 @@
redundant_boolean_clauses/1,
underscore/1,no_warnings/1,
bit_syntax/1,inlining/1,tuple_calls/1,
- recv_opt_info/1,opportunistic_warnings/1]).
+ recv_opt_info/1,opportunistic_warnings/1,
+ eep49/1,inline_list_funcs/1]).
init_per_testcase(_Case, Config) ->
Config.
@@ -66,7 +67,8 @@ groups() ->
maps_bin_opt_info,
redundant_boolean_clauses,
underscore,no_warnings,bit_syntax,inlining,
- tuple_calls,recv_opt_info,opportunistic_warnings]}].
+ tuple_calls,recv_opt_info,opportunistic_warnings,
+ eep49,inline_list_funcs]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -100,8 +102,7 @@ pattern(Config) when is_list(Config) ->
[warn_unused_vars],
{warnings,
[{{2,15},v3_core,{nomatch,pattern}},
- {{6,20},v3_core,{nomatch,pattern}},
- {{11,18},v3_core,{nomatch,pattern}}
+ {{6,20},v3_core,{nomatch,pattern}}
]}}],
[] = run(Config, Ts),
ok.
@@ -618,6 +619,44 @@ bin_opt_info(Config) when is_list(Config) ->
%% For coverage: don't give the bin_opt_info option.
[] = (catch run_test(Config, Code, [])),
+ %% Now try with abstract code and no location.
+ %%
+ %% t1(Bin) ->
+ %% case Bin of
+ %% _ when byte_size(Bin) > 20 -> erlang:error(too_long);
+ %% <<_,T/binary>> -> t1(T);
+ %% <<>> -> ok
+ %% end.
+ Forms = [{attribute,0,module,nolocation_binary},
+ {attribute,0,export,[{t1,1}]},
+ {function,0,t1,1,
+ [{clause,0,[{var,0,'Bin'}],[],
+ [{'case',0,{var,0,'Bin'},
+ [{clause,0,
+ [{var,0,'_'}],
+ [[{op,0,'>',
+ {call,0,{atom,0,byte_size},[{var,0,'Bin'}]},
+ {integer,0,20}}]],
+ [{call,0,
+ {remote,0,{atom,0,erlang},{atom,0,error}},
+ [{atom,0,too_long}]}]},
+ {clause,0,
+ [{bin,0,
+ [{bin_element,0,{var,0,'_'},default,default},
+ {bin_element,0,{var,0,'T'},default,[binary]}]}],
+ [],
+ [{call,0,{atom,0,t1},[{var,0,'T'}]}]},
+ {clause,0,[{bin,0,[]}],[],[{atom,0,ok}]}]}]}]}],
+ Wsf = (catch run_forms(Forms, [bin_opt_info])),
+
+ {warnings,
+ [{none,beam_ssa_bsm,{unsuitable_call,
+ {{b_local,{b_literal,t1},1},
+ {used_before_match,
+ {b_set,_,_,{bif,byte_size},[_]}}}}},
+ {none,beam_ssa_bsm,{binary_created,_,_}}
+ ]} = Wsf,
+
ok.
bin_construction(Config) when is_list(Config) ->
@@ -1090,6 +1129,28 @@ recv_opt_info(Config) when is_list(Config) ->
%% For coverage: don't give the recv_opt_info option.
[] = (catch run_test(Config, Code, [])),
+ %% Now try with abstract code and no location.
+ %%
+ %% simple_receive() ->
+ %% receive
+ %% Message -> handle:msg(Message)
+ %% end.
+ Forms = [{attribute,0,module,nolocation_recv},
+ {attribute,0,export,[{t1,0}]},
+ {function,0,t1,0,
+ [{clause,0,[],[],
+ [{'receive',0,
+ [{clause,0,
+ [{var,0,'Msg'}],
+ [],
+ [{call,0,
+ {remote,0,{atom,0,handle},{atom,0,msg}},
+ [{var,0,'Msg'}]}]}]}]}]}
+ ],
+
+ Wsf = (catch run_forms(Forms, [recv_opt_info])),
+ {warnings, [{none,beam_ssa_recv,matches_any_message}]} = Wsf,
+
ok.
%% OTP-17260: Test that opportunistic warnings can be disabled.
@@ -1165,6 +1226,57 @@ opportunistic_warnings(Config) ->
ok.
+%% Test value-based error handling (EEP 49).
+eep49(Config) ->
+ Ts = [{basic,
+ <<"foo(X) ->
+ maybe
+ %% There should be no warning.
+ Always ?= X,
+ Always
+ end.
+ ">>,
+ [{feature,maybe_expr,enable}],
+ []},
+ {disabled,
+ <<"foo() -> maybe. %Atom maybe.
+ ">>,
+ [{feature,maybe_expr,disable}],
+ []}
+ ],
+ run(Config, Ts),
+ ok.
+
+%% GH-6158: There would be a warning for a clause that could not match.
+inline_list_funcs(Config) ->
+ Ts = [{basic,
+ <<"all(L) ->
+ lists:all(fun erlang:is_integer/1, L).
+ any(L) ->
+ lists:any(fun erlang:is_integer/1, L).
+ foreach(L) ->
+ lists:foreach(fun erlang:is_integer/1, L).
+ map(L) ->
+ lists:map(fun erlang:abs/1, L).
+ filter(L) ->
+ lists:map(fun erlang:is_integer/1, L).
+ foldl(L) ->
+ lists:foldl(fun erlang:is_function/2, L).
+ foldr(L) ->
+ lists:foldl(fun erlang:is_function/2, L).
+ mapfoldl(L) ->
+ lists:mapfoldl(fun erlang:is_function/2, L).
+ mapfoldr(L) ->
+ lists:mapfoldr(fun erlang:is_function/2, L).
+ ">>,
+ [inline_list_funcs],
+ []}
+ ],
+ run(Config, Ts),
+
+ ok.
+
+
%%%
%%% End of test cases.
%%%
@@ -1223,26 +1335,33 @@ run_test(Conf, Test0, Warnings) ->
compile:file(File, [binary,export_all,report|Warnings]),
%% Test result of compilation.
- Res = case compile:file(File, Opts) of
- {ok, _M, Bin, []} when is_binary(Bin) ->
- [];
- {ok, _M, Bin, Ws0} when is_binary(Bin) ->
- %% We are not interested in warnings from
- %% erl_lint here.
- WsL = [{F,[W || {_,Mod,_}=W <- Ws,
- Mod =/= erl_lint]} ||
- {F,Ws} <- Ws0],
- case WsL of
- [{_File,Ws}] ->
- print_warnings(Ws, Test),
- {warnings, Ws};
- _ ->
- list_to_tuple([warnings, WsL])
- end
- end,
+ Res = get_warnings(compile:file(File, Opts)),
+ case Res of
+ [] -> [];
+ {warnings, Ws} -> print_warnings(Ws, Test)
+ end,
file:delete(File),
Res.
+run_forms(Forms, Warnings) ->
+ get_warnings(compile:forms(Forms, [binary,return|Warnings])).
+
+get_warnings(Result) ->
+ case Result of
+ {ok, _M, Bin, []} when is_binary(Bin) ->
+ [];
+ {ok, _M, Bin, Ws0} when is_binary(Bin) ->
+ %% We are not interested in warnings from
+ %% erl_lint here.
+ WsL = [{F,[W || {_,Mod,_}=W <- Ws,
+ Mod =/= erl_lint]} ||
+ {F,Ws} <- Ws0],
+ case WsL of
+ [{_File,Ws}] -> {warnings, Ws};
+ _ -> list_to_tuple([warnings, WsL])
+ end
+ end.
+
print_warnings(Warnings, Source) ->
Lines = binary:split(Source, <<"\n">>, [global]),
Cs = [print_warning(W, Lines) || W <- Warnings],
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 18c452259a..0a39fcf419 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 8.1.1
+COMPILER_VSN = 8.2.4
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 4478ed7d9c..25167a8a3a 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -42,6 +42,7 @@ SSL_LIBDIR = @SSL_LIBDIR@
SSL_INCLUDE = @SSL_INCLUDE@
SSL_CRYPTO_LIBNAME = @SSL_CRYPTO_LIBNAME@
SSL_SSL_LIBNAME = @SSL_SSL_LIBNAME@
+CRYPTO_NO_DEPRECATE_WARN = @CRYPTO_NO_DEPRECATE_WARN@
INCLUDES = $(SSL_INCLUDE) @DED_INCLUDE@
SSL_EXTRA_LIBS=@SSL_EXTRA_LIBS@
@@ -112,6 +113,7 @@ CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o \
$(OBJDIR)/rand$(TYPEMARKER).o \
$(OBJDIR)/rsa$(TYPEMARKER).o \
$(OBJDIR)/srp$(TYPEMARKER).o \
+ $(OBJDIR)/hash_equals$(TYPEMARKER).o \
$(OBJDIR)/pbkdf2_hmac$(TYPEMARKER).o
CALLBACK_OBJS = $(OBJDIR)/crypto_callback$(TYPEMARKER).o
@@ -150,7 +152,7 @@ CRYPTO_LINK_LIB=$(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) -l$(SSL_CRYPT
EXTRA_FLAGS = -DHAVE_DYNAMIC_CRYPTO_LIB
else
SSL_DED_LD_RUNTIME_LIBRARY_PATH=
-CRYPTO_LINK_LIB=$(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a
+CRYPTO_LINK_LIB=$(SSL_LIBDIR)/lib$(SSL_CRYPTO_LIBNAME).a
EXTRA_FLAGS =
CRYPTO_OBJS := $(CRYPTO_OBJS) $(CALLBACK_OBJS)
CALLBACK_OBJS =
@@ -192,7 +194,7 @@ ifeq ($(DISABLE_OTP_TEST_ENGINE),yes)
else
$(OBJDIR)/otp_test_engine$(TYPEMARKER).o: otp_test_engine.c
$(V_at)$(INSTALL_DIR) $(OBJDIR)
- $(V_CC) -c -o $@ $(filter-out -Wmissing-prototypes,$(ALL_CFLAGS)) $<
+ $(V_CC) -c -o $@ $(filter-out -Wmissing-prototypes,$(ALL_CFLAGS) $(CRYPTO_NO_DEPRECATE_WARN)) $<
$(LIBDIR)/otp_test_engine$(TYPEMARKER).so: $(TEST_ENGINE_OBJS)
$(V_at)$(INSTALL_DIR) $(LIBDIR)
@@ -203,6 +205,10 @@ $(LIBDIR)/otp_test_engine$(TYPEMARKER).dll: $(TEST_ENGINE_OBJS)
$(V_LD) $(LDFLAGS) -o $@ $(SSL_DED_LD_RUNTIME_LIBRARY_PATH) -L$(SSL_LIBDIR) $(TEST_ENGINE_OBJS) -l$(SSL_CRYPTO_LIBNAME) -l$(SSL_SSL_LIBNAME) $(SSL_EXTRA_LIBS)
endif
+$(OBJDIR)/ec$(TYPEMARKER).o: ec.c
+ $(V_at)$(INSTALL_DIR) $(OBJDIR)
+ $(V_CC) -c -o $@ $(ALL_CFLAGS) $(CRYPTO_NO_DEPRECATE_WARN) $<
+
$(OBJDIR)/%$(TYPEMARKER).o: %.c
$(V_at)$(INSTALL_DIR) $(OBJDIR)
$(V_CC) -c -o $@ $(ALL_CFLAGS) $<
@@ -255,7 +261,7 @@ docs:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c
index 4c2167703a..f06ed9002e 100644
--- a/lib/crypto/c_src/bn.c
+++ b/lib/crypto/c_src/bn.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -192,3 +192,58 @@ ERL_NIF_TERM bn2term(ErlNifEnv* env, size_t size, const BIGNUM *bn)
return enif_make_badarg(env);
}
#endif
+
+
+#ifdef HAS_3_0_API
+
+int get_ossl_octet_string_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest)
+{
+ ErlNifBinary tmp;
+
+ if (!enif_inspect_binary(env, bin, &tmp)) return 0;
+
+ *dest = OSSL_PARAM_construct_octet_string(key, tmp.data, tmp.size);
+ return 1;
+}
+
+
+int get_ossl_BN_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest)
+{
+ return get_ossl_BN_param_from_bin_sz(env, key, bin, dest, NULL);
+}
+
+int get_ossl_BN_param_from_bin_sz(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest, size_t *size)
+{
+ BIGNUM *bn = NULL;
+ ErlNifBinary tmp;
+
+ if (!get_bn_from_bin_sz(env, bin, &bn, size) ||
+ !enif_inspect_binary(env, bin_from_bn(env,bn), &tmp) || // Allocate buf
+ BN_bn2nativepad(bn, tmp.data, tmp.size) < 0) {// Fill with BN in right endianity
+ if (bn) BN_free(bn);
+ return 0;
+ }
+
+ *dest = OSSL_PARAM_construct_BN(key, tmp.data, tmp.size);
+ if (bn) BN_free(bn);
+ return 1;
+}
+
+int get_ossl_param_from_bin_in_list(ErlNifEnv* env, char* key, ERL_NIF_TERM *listcell, OSSL_PARAM *dest)
+{
+ ERL_NIF_TERM head;
+
+ return
+ enif_get_list_cell(env, *listcell, &head, listcell) &&
+ get_ossl_BN_param_from_bin(env, key, head, dest);
+}
+
+#endif
+
+
+
+
+
+
+
+
diff --git a/lib/crypto/c_src/bn.h b/lib/crypto/c_src/bn.h
index 8b309db089..5e207aed2d 100644
--- a/lib/crypto/c_src/bn.h
+++ b/lib/crypto/c_src/bn.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,4 +34,13 @@ int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp);
int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp);
int get_bn_from_bin_sz(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp, size_t* binsize);
+#ifdef HAS_3_0_API
+int get_ossl_octet_string_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest);
+int get_ossl_BN_param_from_bin(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest);
+int get_ossl_BN_param_from_bin_sz(ErlNifEnv* env, char* key, ERL_NIF_TERM bin, OSSL_PARAM *dest, size_t *size);
+
+int get_ossl_param_from_bin_in_list(ErlNifEnv* env, char* key, ERL_NIF_TERM *listcell, OSSL_PARAM *dest);
+#endif
+
#endif /* E_BN_H__ */
+
diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c
index 6862187d6b..30c0fbcdb7 100644
--- a/lib/crypto/c_src/cipher.c
+++ b/lib/crypto/c_src/cipher.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,28 +60,32 @@ static struct cipher_type_t cipher_types[] =
#endif
#ifdef HAVE_BF
- {{"blowfish_cbc"}, "BF-CBC", {&EVP_bf_cbc}, 0, NO_FIPS_CIPHER, NOT_AEAD},
- {{"blowfish_cfb64"}, "BF-CFB64", {&EVP_bf_cfb64}, 0, NO_FIPS_CIPHER, NOT_AEAD},
- {{"blowfish_ofb64"}, "BF-OFB64", {&EVP_bf_ofb}, 0, NO_FIPS_CIPHER, NOT_AEAD},
- {{"blowfish_ecb"}, "BF-ECB", {&EVP_bf_ecb}, 0, NO_FIPS_CIPHER | ECB_BUG_0_9_8L, NOT_AEAD},
+ {{"blowfish_cbc"}, "BF-CBC", {&EVP_bf_cbc}, 0, NO_FIPS_CIPHER, NOT_AEAD},
+ {{"blowfish_cfb64"}, "BF-CFB", {&EVP_bf_cfb64}, 0, NO_FIPS_CIPHER, NOT_AEAD},
+ {{"blowfish_ofb64"}, "BF-OFB", {&EVP_bf_ofb}, 0, NO_FIPS_CIPHER, NOT_AEAD},
+ {{"blowfish_ecb"}, "BF-ECB", {&EVP_bf_ecb}, 0, NO_FIPS_CIPHER | ECB_BUG_0_9_8L, NOT_AEAD},
#else
- {{"blowfish_cbc"}, "BF-CBC", {NULL}, 0, 0, NOT_AEAD},
- {{"blowfish_cfb64"}, "BF-CFB64", {NULL}, 0, 0, NOT_AEAD},
- {{"blowfish_ofb64"}, "BF-OFB64", {NULL}, 0, 0, NOT_AEAD},
- {{"blowfish_ecb"}, "BF-ECB", {NULL}, 0, 0, NOT_AEAD},
+ {{"blowfish_cbc"}, "BF-CBC", {NULL}, 0, 0, NOT_AEAD},
+ {{"blowfish_cfb64"}, "BF-CFB", {NULL}, 0, 0, NOT_AEAD},
+ {{"blowfish_ofb64"}, "BF-OFB", {NULL}, 0, 0, NOT_AEAD},
+ {{"blowfish_ecb"}, "BF-ECB", {NULL}, 0, 0, NOT_AEAD},
#endif
{{"aes_128_cbc"}, "aes-128-cbc", {&EVP_aes_128_cbc}, 16, 0, NOT_AEAD},
{{"aes_192_cbc"}, "aes-192-cbc", {&EVP_aes_192_cbc}, 24, 0, NOT_AEAD},
{{"aes_256_cbc"}, "aes-256-cbc", {&EVP_aes_256_cbc}, 32, 0, NOT_AEAD},
+ {{"aes_128_ofb"}, "aes-128-ofb", {&EVP_aes_128_ofb}, 16, 0, NOT_AEAD},
+ {{"aes_192_ofb"}, "aes-192-ofb", {&EVP_aes_192_ofb}, 24, 0, NOT_AEAD},
+ {{"aes_256_ofb"}, "aes-256-ofb", {&EVP_aes_256_ofb}, 32, 0, NOT_AEAD},
+
{{"aes_128_cfb8"}, "aes-128-cfb8", {&EVP_aes_128_cfb8}, 16, AES_CFBx, NOT_AEAD},
{{"aes_192_cfb8"}, "aes-192-cfb8", {&EVP_aes_192_cfb8}, 24, AES_CFBx, NOT_AEAD},
{{"aes_256_cfb8"}, "aes-256-cfb8", {&EVP_aes_256_cfb8}, 32, AES_CFBx, NOT_AEAD},
- {{"aes_128_cfb128"}, "aes-128-cfb128", {&EVP_aes_128_cfb128}, 16, AES_CFBx, NOT_AEAD},
- {{"aes_192_cfb128"}, "aes-192-cfb128", {&EVP_aes_192_cfb128}, 24, AES_CFBx, NOT_AEAD},
- {{"aes_256_cfb128"}, "aes-256-cfb128", {&EVP_aes_256_cfb128}, 32, AES_CFBx, NOT_AEAD},
+ {{"aes_128_cfb128"}, "aes-128-cfb", {&EVP_aes_128_cfb128}, 16, AES_CFBx, NOT_AEAD},
+ {{"aes_192_cfb128"}, "aes-192-cfb", {&EVP_aes_192_cfb128}, 24, AES_CFBx, NOT_AEAD},
+ {{"aes_256_cfb128"}, "aes-256-cfb", {&EVP_aes_256_cfb128}, 32, AES_CFBx, NOT_AEAD},
{{"aes_128_ecb"}, "aes-128-ecb", {&EVP_aes_128_ecb}, 16, ECB_BUG_0_9_8L, NOT_AEAD},
{{"aes_192_ecb"}, "aes-192-ecb", {&EVP_aes_192_ecb}, 24, ECB_BUG_0_9_8L, NOT_AEAD},
diff --git a/lib/crypto/c_src/common.h b/lib/crypto/c_src/common.h
index 593a58373f..5da20fd0c8 100644
--- a/lib/crypto/c_src/common.h
+++ b/lib/crypto/c_src/common.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,4 +46,6 @@ ERL_NIF_TERM raise_exception(ErlNifEnv* env, ERL_NIF_TERM id, int arg_num, char*
#define EXCP_NOTSUP_N(Env, ArgNum, Str) raise_exception((Env), atom_notsup, (ArgNum), (Str), __FILE__, __LINE__)
#define EXCP_BADARG_N(Env, ArgNum, Str) raise_exception((Env), atom_badarg, (ArgNum), (Str), __FILE__, __LINE__)
+#define assign_goto(Var, Goto, CALL) {Var = (CALL); goto Goto;}
+
#endif /* E_COMMON_H__ */
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 5d1c1b306e..ef6d0bdc13 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@
#include "evp.h"
#include "fips.h"
#include "hash.h"
+#include "hash_equals.h"
#include "hmac.h"
#include "info.h"
#include "math.h"
@@ -91,6 +92,9 @@ static ErlNifFunc nif_funcs[] = {
{"rand_uniform_nif", 2, rand_uniform_nif, 0},
{"mod_exp_nif", 4, mod_exp_nif, 0},
{"do_exor", 2, do_exor, 0},
+
+ {"hash_equals_nif", 2, hash_equals_nif, 0},
+
{"pbkdf2_hmac_nif", 5, pbkdf2_hmac_nif, 0},
{"pkey_sign_nif", 5, pkey_sign_nif, 0},
{"pkey_verify_nif", 6, pkey_verify_nif, 0},
@@ -105,7 +109,7 @@ static ErlNifFunc nif_funcs[] = {
{"srp_user_secret_nif", 7, srp_user_secret_nif, 0},
{"srp_host_secret_nif", 5, srp_host_secret_nif, 0},
- {"ec_key_generate", 2, ec_key_generate, 0},
+ {"ec_generate_key_nif", 2, ec_generate_key_nif, 0},
{"ecdh_compute_key_nif", 3, ecdh_compute_key_nif, 0},
{"rand_seed_nif", 1, rand_seed_nif, 0},
@@ -125,7 +129,8 @@ static ErlNifFunc nif_funcs[] = {
{"engine_get_next_nif", 1, engine_get_next_nif, 0},
{"engine_get_id_nif", 1, engine_get_id_nif, 0},
{"engine_get_name_nif", 1, engine_get_name_nif, 0},
- {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif, 0}
+ {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif, 0},
+ {"ensure_engine_loaded_nif", 2, ensure_engine_loaded_nif, 0}
};
#ifdef HAS_3_0_API
@@ -209,6 +214,9 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
if (!init_engine_ctx(env)) {
return __LINE__;
}
+ if (!create_engine_mutex(env)) {
+ return __LINE__;
+ }
#ifdef HAS_3_0_API
prov_cnt = 0;
@@ -217,7 +225,7 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
#endif
if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "default"))) return __LINE__;
if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "base"))) return __LINE__;
- if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "legacy"))) return __LINE__;
+ if (prov_cnt<MAX_NUM_PROVIDERS) {prov_cnt++; OSSL_PROVIDER_load(NULL, "legacy");}
#endif
if (library_initialized) {
@@ -323,8 +331,10 @@ static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
static void unload(ErlNifEnv* env, void* priv_data)
{
- if (--library_refc == 0)
+ if (--library_refc == 0) {
cleanup_algorithms_types(env);
+ destroy_engine_mutex(env);
+ }
#ifdef HAS_3_0_API
while (prov_cnt>0)
@@ -332,3 +342,4 @@ static void unload(ErlNifEnv* env, void* priv_data)
#endif
}
+
diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c
index 67be0c81f0..4bcab0ec6e 100644
--- a/lib/crypto/c_src/dh.c
+++ b/lib/crypto/c_src/dh.c
@@ -21,9 +21,248 @@
#include "dh.h"
#include "bn.h"
+
+#if !defined(HAVE_DH)
+ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ return enif_raise_exception(env, atom_notsup);
+}
+
+ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ return enif_raise_exception(env, atom_notsup);
+}
+
+#else /* HAVE_DH */
+
+
+# ifdef HAS_3_0_API
+
+/* Has 3_0 */
+ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (PrivKey|undefined, DHParams=[P,G], 0, Len|0) */
+ unsigned long len = 0;
+ int i = 0;
+ OSSL_PARAM params[8];
+ EVP_PKEY *pkey = NULL, *pkey_gen = NULL;
+ EVP_PKEY_CTX *pctx = NULL, *pctx_gen = NULL;
+ BIGNUM *pub_key_gen = NULL, *priv_key_gen = NULL;
+ unsigned char *pub_ptr, *prv_ptr;
+ int pub_len, prv_len;
+ ERL_NIF_TERM ret_pub, ret_prv, ret = atom_undefined;
+
+ /* Fetch parameters and assign them to params[] */
+ if (argv[0] != atom_undefined)
+ if (!get_ossl_BN_param_from_bin(env, "priv", argv[0], &params[i++])) {
+ ret = EXCP_BADARG_N(env, 0, "PrivKeyIn");
+ goto done;
+ }
+
+ { /*argv[1] - the lists [P,G] */
+ ERL_NIF_TERM head, tail;
+
+ head = argv[1];
+ if (!get_ossl_param_from_bin_in_list(env, "p", &head, &params[i++]) ) {
+ ret = EXCP_BADARG_N(env, 1, "Bad value of 'p'");
+ goto done;
+ }
+
+ if (!get_ossl_param_from_bin_in_list(env, "g", &head, &params[i++]) ) {
+ ret = EXCP_BADARG_N(env, 1, "Bad value of 'g'");
+ goto done;
+ }
+
+ tail = head;
+ if (!enif_is_empty_list(env,tail)) {
+ ret = EXCP_BADARG_N(env, 1, "Not a two-element list");
+ goto done;
+ }
+ }
+
+ /* argv[2] is always hardcoded to 0 in crypto.erl. A left over from some older version?
+ Let's skip that one
+ */
+
+ /* argv[3] is the length of the private key that is to be generated */
+ if (!enif_get_ulong(env, argv[3], &len) ||
+ (len > LONG_MAX) ) {
+ ret = EXCP_BADARG_N(env, 3, "Bad value of length element");
+ goto done;
+ }
+ else if (len)
+ params[i++] = OSSL_PARAM_construct_uint64("priv_len", &len);
+
+ /* End of parameter fetching */
+ params[i++] = OSSL_PARAM_construct_end();
+
+ pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
+
+ if (EVP_PKEY_fromdata_init(pctx) <= 0) {
+ ret = EXCP_ERROR(env, "Can't init fromdata");
+ goto done;
+ }
+ if (EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
+ ret = EXCP_ERROR(env, "Can't do fromdata");
+ goto done;
+ }
+
+ /* Generate a new pkey from the data in the old */
+
+ pctx_gen = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+
+ if (!EVP_PKEY_keygen_init(pctx_gen)) {
+ ret = EXCP_ERROR(env, "Can't init DH generation");
+ goto done;
+ }
+
+ if (!EVP_PKEY_CTX_set_params(pctx_gen, params)) {
+ ret = EXCP_ERROR(env, "Can't set params");
+ goto done;
+ }
+
+ if (!EVP_PKEY_generate(pctx_gen, &pkey_gen)) {
+ ret = EXCP_ERROR(env, "Can't generate DH key pair");
+ goto done;
+ }
+
+ /* Finally return the OTP representation of the keys: */
+
+ if (!EVP_PKEY_get_bn_param(pkey_gen, "pub", &pub_key_gen)) {
+ ret = EXCP_ERROR(env, "Can't get public key");
+ goto done;
+ }
+ if ((pub_len = BN_num_bytes(pub_key_gen)) < 0 ||
+ (pub_ptr = enif_make_new_binary(env, (size_t)pub_len, &ret_pub)) == NULL ||
+ BN_bn2bin(pub_key_gen, pub_ptr) < 0)
+ {
+ ret = EXCP_ERROR(env, "Can't convert public key");
+ goto done;
+ }
+
+ if (!EVP_PKEY_get_bn_param(pkey_gen, "priv", &priv_key_gen)) {
+ ret = EXCP_ERROR(env, "Can't get private key");
+ goto done;
+ }
+ if ((prv_len = BN_num_bytes(priv_key_gen)) < 0 ||
+ (prv_ptr = enif_make_new_binary(env, (size_t)prv_len, &ret_prv)) == NULL ||
+ BN_bn2bin(priv_key_gen, prv_ptr) < 0)
+ {
+ ret = EXCP_ERROR(env, "Can't convert private key");
+ goto done;
+ }
+
+ ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
+
+ ret = enif_make_tuple2(env, ret_pub, ret_prv);
+
+ done:
+ if (pub_key_gen) BN_free(pub_key_gen);
+ if (priv_key_gen) BN_free(priv_key_gen);
+ if (pkey) EVP_PKEY_free(pkey);
+ if (pkey_gen) EVP_PKEY_free(pkey_gen);
+ if (pctx) EVP_PKEY_CTX_free(pctx);
+ if (pctx_gen) EVP_PKEY_CTX_free(pctx_gen);
+
+ return ret;
+}
+
+/* Has 3_0 */
+ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
+ ERL_NIF_TERM ret;
+ ErlNifBinary ret_bin;
+ size_t sz;
+ int ret_bin_alloc = 0;
+ int i = 0;
+ OSSL_PARAM params[5];
+ EVP_PKEY_CTX *own_pctx = NULL, *peer_pctx = NULL, *pctx_gen = NULL;
+ EVP_PKEY *own_pkey = NULL, *peer_pkey = NULL;
+
+ /* Fetch parameters */
+
+ /* Build peer_pkey */
+
+ if (!get_ossl_BN_param_from_bin(env, "pub", argv[0], &params[i++]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad peer public key; binary expected"));
+
+ { /*argv[2] - the lists [P,G] */
+ ERL_NIF_TERM head, tail;
+
+ head = argv[2];
+ if (!get_ossl_param_from_bin_in_list(env, "p", &head, &params[i++]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Bad value of 'p'"));
+
+ if (!get_ossl_param_from_bin_in_list(env, "g", &head, &params[i++]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Bad value of 'g'"));
+
+ tail = head;
+ if (!enif_is_empty_list(env,tail))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Not a two-element list"));
+ }
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ peer_pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
+
+ if (EVP_PKEY_fromdata_init(peer_pctx) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata"));
+ if (EVP_PKEY_fromdata(peer_pctx, &peer_pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata"));
+
+ /* Build own_pkey. Just replace the pub key with the priv key in params */
+ if (!get_ossl_BN_param_from_bin(env, "priv", argv[1], &params[0]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad peer public key; binary expected"));
+
+ own_pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
+
+ if (EVP_PKEY_fromdata_init(own_pctx) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata"));
+
+ if (EVP_PKEY_fromdata(own_pctx, &own_pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata"));
+
+
+ /* Derive the common secret */
+ pctx_gen = EVP_PKEY_CTX_new(own_pkey, NULL);
+
+ if (!EVP_PKEY_derive_init(pctx_gen))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_derive_init"));
+
+ if (!EVP_PKEY_derive_set_peer(pctx_gen, peer_pkey))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't derive secret or set peer"));
+
+ if (!EVP_PKEY_derive(pctx_gen, NULL, &sz))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get result size"));
+
+ if (!enif_alloc_binary(sz, &ret_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allcate binary"));
+ ret_bin_alloc = 1;
+
+ if (!EVP_PKEY_derive(pctx_gen, ret_bin.data, &ret_bin.size))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get result"));
+
+ if (sz != ret_bin.size)
+ if (!enif_realloc_binary(&ret_bin, ret_bin.size))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't realloc binary"));
+
+ ret = enif_make_binary(env, &ret_bin);
+ ret_bin_alloc = 0;
+
+ err:
+ if (ret_bin_alloc) enif_release_binary(&ret_bin);
+ if (peer_pctx) EVP_PKEY_CTX_free(peer_pctx);
+ if (peer_pkey) EVP_PKEY_free(peer_pkey);
+ if (own_pctx) EVP_PKEY_CTX_free(own_pctx);
+ if (own_pkey) EVP_PKEY_free(own_pkey);
+ if (pctx_gen) EVP_PKEY_CTX_free(pctx_gen);
+ return ret;
+}
+
+# else
+/* Has not 3.0 */
ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */
-#ifdef HAVE_DH
DH *dh_params = NULL;
unsigned int mpint; /* 0 or 4 */
ERL_NIF_TERM head, tail;
@@ -36,52 +275,52 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
int pub_len, prv_len;
ERL_NIF_TERM ret_pub, ret_prv, ret;
const BIGNUM *pub_key_gen, *priv_key_gen;
-#if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
+# if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *dhkey = NULL, *params = NULL;
-#endif
+# endif
ASSERT(argc == 4);
if (argv[0] != atom_undefined) {
if (!get_bn_from_bin(env, argv[0], &priv_key_in))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Can't get bignum from binary"));
}
if (!enif_get_list_cell(env, argv[1], &head, &tail))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "List with exactly two elements expected"));
if (!get_bn_from_bin(env, head, &dh_p))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Can't get bignum from binary"));
if (!enif_get_list_cell(env, tail, &head, &tail))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "List with exactly two elements expected"));
if (!get_bn_from_bin(env, head, &dh_g))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Can't get bignum from binary"));
if (!enif_is_empty_list(env, tail))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "List with exactly two elements expected"));
if (!enif_get_uint(env, argv[2], &mpint))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Integer expected"));
if (mpint != 0 && mpint != 4)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Integer 0 or 4 expected"));
if (!enif_get_ulong(env, argv[3], &len))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Integer expected"));
if (len > LONG_MAX)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Too big integer"));
/* Load dh_params with values to use by the generator.
Mem mgmnt transferred from dh_p etc to dh_params */
if ((dh_params = DH_new()) == NULL)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't do DH_new"));
if (priv_key_in) {
if (!DH_set0_key(dh_params, NULL, priv_key_in))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Not accepted as private key"));
/* On success, dh_params owns priv_key_in */
priv_key_in = NULL;
}
if (!DH_set0_pqg(dh_params, dh_p, NULL, dh_g))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "P and/or G not accepted"));
dh_p_shared = dh_p; /* Don't free this because dh_params owns it */
/* On success, dh_params owns dh_p and dh_g */
dh_p = NULL;
@@ -91,56 +330,56 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
int bn_len;
if ((bn_len = BN_num_bits(dh_p_shared)) < 0)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR(env, "BN_num_bits < 0"));
dh_p_shared = NULL; /* dh_params owns the reference */
if (len >= (size_t)bn_len)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 3, "Too big length"));
if (!DH_set_length(dh_params, (long)len))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 3, "The length is not accepted"));
}
-#if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
+# if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
if ((params = EVP_PKEY_new()) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_new"));
/* set the key referenced by params to dh_params... */
if (EVP_PKEY_set1_DH(params, dh_params) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_set1_DH"));
if ((ctx = EVP_PKEY_CTX_new(params, NULL)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_new"));
if (EVP_PKEY_keygen_init(ctx) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen_init"));
if ((dhkey = EVP_PKEY_new()) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_new"));
/* key gen op, key written to ppkey (=last arg) */
if (EVP_PKEY_keygen(ctx, &dhkey) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen"));
DH_free(dh_params);
if ((dh_params = EVP_PKEY_get1_DH(dhkey)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_get1_DH"));
-#else
+# else
if (!DH_generate_key(dh_params))
- goto err;
-#endif
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_generate_key"));
+# endif
DH_get0_key(dh_params, &pub_key_gen, &priv_key_gen);
if ((pub_len = BN_num_bytes(pub_key_gen)) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get public key length"));
if ((prv_len = BN_num_bytes(priv_key_gen)) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get private key length"));
if ((pub_ptr = enif_make_new_binary(env, (size_t)pub_len+mpint, &ret_pub)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate pub_ptr"));
if ((prv_ptr = enif_make_new_binary(env, (size_t)prv_len+mpint, &ret_prv)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate prv_ptr"));
if (mpint) {
put_uint32(pub_ptr, (unsigned int)pub_len);
@@ -151,9 +390,9 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
if (BN_bn2bin(pub_key_gen, pub_ptr) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't BN_bn2bin"));
if (BN_bn2bin(priv_key_gen, prv_ptr) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't BN_bn2bin"));
ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
@@ -161,13 +400,7 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
ret = enif_make_tuple2(env, ret_pub, ret_prv);
goto done;
- bad_arg:
- ret = enif_make_badarg(env);
- goto done;
-
err:
- ret = atom_error;
-
done:
if (priv_key_in)
BN_free(priv_key_in);
@@ -178,24 +411,21 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
if (dh_params)
DH_free(dh_params);
-#if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
+# if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_DH)
if (ctx)
EVP_PKEY_CTX_free(ctx);
if (dhkey)
EVP_PKEY_free(dhkey);
if (params)
EVP_PKEY_free(params);
-#endif
+# endif
return ret;
-#else
- return enif_raise_exception(env, atom_notsup);
-#endif
}
+
ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
-#ifdef HAVE_DH
BIGNUM *other_pub_key = NULL;
BIGNUM *dh_p = NULL;
BIGNUM *dh_g = NULL;
@@ -216,22 +446,22 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ASSERT(argc == 3);
if (!get_bn_from_bin(env, argv[0], &other_pub_key))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Can't get bignum from binary"));
if (!get_bn_from_bin(env, argv[1], &priv_key))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Can't get bignum from binary"));
if (!enif_get_list_cell(env, argv[2], &head, &tail))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "List with exactly two elements expected"));
if (!get_bn_from_bin(env, head, &dh_p))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Can't get bignum from binary"));
if (!enif_get_list_cell(env, tail, &head, &tail))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "List with exactly two elements expected"));
if (!get_bn_from_bin(env, head, &dh_g))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Can't get bignum from binary"));
if (!enif_is_empty_list(env, tail))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "List with exactly two elements expected"));
/* Note: DH_set0_key() does not allow setting only the
* private key, although DH_compute_key() does not use the
@@ -239,48 +469,45 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
* the public key to a copy of the private key.
*/
if ((dummy_pub_key = BN_dup(priv_key)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't BN_dup"));
if ((dh_priv = DH_new()) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_new"));
if (!DH_set0_key(dh_priv, dummy_pub_key, priv_key))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_set0_key"));
/* dh_priv owns dummy_pub_key and priv_key now */
dummy_pub_key = NULL;
priv_key = NULL;
if (!DH_set0_pqg(dh_priv, dh_p, NULL, dh_g))
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "P and/or G not accepted"));
/* dh_priv owns dh_p and dh_g now */
dh_p = NULL;
dh_g = NULL;
if ((dh_size = DH_size(dh_priv)) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_size"));
if (!enif_alloc_binary((size_t)dh_size, &ret_bin))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allcate binary"));
ret_bin_alloc = 1;
if ((size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv)) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't DH_compute_key"));
if (size == 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "size == 0"));
if ((size_t)size != ret_bin.size) {
if (!enif_realloc_binary(&ret_bin, (size_t)size))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't realloc binary"));
}
ret = enif_make_binary(env, &ret_bin);
ret_bin_alloc = 0;
goto done;
- bad_arg:
err:
if (ret_bin_alloc)
enif_release_binary(&ret_bin);
- ret = enif_make_badarg(env);
-
done:
if (other_pub_key)
BN_free(other_pub_key);
@@ -296,7 +523,10 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
DH_free(dh_priv);
return ret;
-#else
- return enif_raise_exception(env, atom_notsup);
-#endif
}
+
+# endif /* else part of HAS_3_0_API */
+
+
+
+#endif /* HAVE_DH */
diff --git a/lib/crypto/c_src/dss.c b/lib/crypto/c_src/dss.c
index 7669155db6..2e19453e50 100644
--- a/lib/crypto/c_src/dss.c
+++ b/lib/crypto/c_src/dss.c
@@ -23,6 +23,117 @@
#ifdef HAVE_DSA
+# ifdef HAS_3_0_API
+
+int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
+// HAS_3_0_API
+{
+ /* key=[P,Q,G,PRIV_KEY] */
+ ERL_NIF_TERM head, tail;
+ OSSL_PARAM params[5];
+ EVP_PKEY_CTX *ctx = NULL;
+ int i = 0;
+
+ head = key;
+
+ // https://www.openssl.org/docs/man3.0/man7/EVP_PKEY-FFC.html
+ if (!get_ossl_param_from_bin_in_list(env, "p", &head, &params[i++]) ||
+ !get_ossl_param_from_bin_in_list(env, "q", &head, &params[i++]) ||
+ !get_ossl_param_from_bin_in_list(env, "g", &head, &params[i++]) ||
+ !get_ossl_param_from_bin_in_list(env, "priv", &head, &params[i++]))
+ goto bad_arg;
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ tail = head;
+ if (!enif_is_empty_list(env,tail))
+ goto err;
+
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(ctx) <= 0)
+ goto err;
+ if (EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ goto bad_arg;
+
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 1;
+
+bad_arg:
+err:
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 0;
+}
+
+int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
+// HAS_3_0_API
+{
+ /* key=[P, Q, G, PUB_KEY (=Y)] */
+ ERL_NIF_TERM head, tail;
+ OSSL_PARAM params[5];
+ EVP_PKEY_CTX *ctx = NULL;
+ int i = 0;
+
+ head = key;
+
+ // https://www.openssl.org/docs/man3.0/man7/EVP_PKEY-FFC.html
+ if (!get_ossl_param_from_bin_in_list(env, "p", &head, &params[i++]) ||
+ !get_ossl_param_from_bin_in_list(env, "q", &head, &params[i++]) ||
+ !get_ossl_param_from_bin_in_list(env, "g", &head, &params[i++]) ||
+ !get_ossl_param_from_bin_in_list(env, "pub", &head, &params[i++]))
+ goto bad_arg;
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ tail = head;
+ if (!enif_is_empty_list(env,tail))
+ goto err;
+
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(ctx) <= 0)
+ goto err;
+ if (EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
+ goto bad_arg;
+
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 1;
+
+bad_arg:
+err:
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 0;
+}
+
+
+int dss_privkey_to_pubkey(ErlNifEnv* env, EVP_PKEY *pkey, ERL_NIF_TERM *ret)
+// HAS_3_0_API
+{
+ ERL_NIF_TERM result[5];
+ BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL;
+
+ if (
+ !EVP_PKEY_get_bn_param(pkey, "p", &p)
+ || !EVP_PKEY_get_bn_param(pkey, "q", &q)
+ || !EVP_PKEY_get_bn_param(pkey, "g", &g)
+ || !EVP_PKEY_get_bn_param(pkey, "pub", &pub)
+ || ((result[0] = bin_from_bn(env, p)) == atom_error)
+ || ((result[1] = bin_from_bn(env, q)) == atom_error)
+ || ((result[1] = bin_from_bn(env, g)) == atom_error)
+ || ((result[1] = bin_from_bn(env, pub)) == atom_error)
+ )
+ goto err;
+
+ *ret = enif_make_list_from_array(env, result, 4);
+ return 1;
+
+ err:
+ return 0;
+}
+
+# else
+/* Has NOT 3.0 API */
+
int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
{
/* key=[P,Q,G,KEY] */
@@ -78,6 +189,7 @@ int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
dummy_pub_key = NULL;
priv_key = NULL;
+ *pkey = EVP_PKEY_new();
if (EVP_PKEY_assign_DSA(*pkey, dsa) != 1)
goto err;
/* On success, result owns dsa */
@@ -144,6 +256,7 @@ int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
/* dsa takes ownership on success */
dsa_y = NULL;
+ *pkey = EVP_PKEY_new();
if (EVP_PKEY_assign_DSA(*pkey, dsa) != 1)
goto err;
/* On success, result owns dsa */
@@ -195,4 +308,6 @@ int dss_privkey_to_pubkey(ErlNifEnv* env, EVP_PKEY *pkey, ERL_NIF_TERM *ret)
return 0;
}
-#endif
+# endif /* HAS_3_0_API */
+
+#endif /* HAVE_DSA */
diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c
index b52aeed6ea..124582c4f8 100644
--- a/lib/crypto/c_src/ec.c
+++ b/lib/crypto/c_src/ec.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,21 +22,456 @@
#include "bn.h"
#ifdef HAVE_EC
-static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg, size_t *size);
-static ERL_NIF_TERM point2term(ErlNifEnv* env,
- const EC_GROUP *group,
- const EC_POINT *point,
- point_conversion_form_t form);
+# if defined(HAS_3_0_API)
-ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env)
+int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def,
+ OSSL_PARAM params[], int *i,
+ size_t *order_size)
{
- ERL_NIF_TERM reason;
- if (enif_has_pending_exception(env, &reason))
- return reason; /* dummy return value ignored */
+ const ERL_NIF_TERM* curve;
+ int c_arity = -1;
+ const ERL_NIF_TERM *prime;
+ int p_arity = -1;
+ const ERL_NIF_TERM *field;
+ int f_arity = -1;
+ BIGNUM *p = NULL;
+ int arity = -1;
+ const ERL_NIF_TERM* curve_tuple;
+
+ /* Here are two random curve definition examples, one prime_field and
+ one characteristic_two_field. Both are from the crypto/src/crypto_ec_curves.erl.
+
+ curve(secp192r1) ->
+ {
+ {prime_field, <<16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF:192>>}, %% Prime
+ {<<16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC:192>>, %% A
+ <<16#64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1:192>>, %% B
+ <<16#3045AE6FC8422F64ED579528D38120EAE12196D5:160>>}, %% Seed
+ <<16#04:8,
+ 16#188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012:192, %% X(p0)
+ 16#07192B95FFC8DA78631011ED6B24CDD573F977A11E794811:192>>, %% Y(p0)
+ <<16#FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831:192>>, %% Order
+ <<16#01:8>> %% CoFactor
+ };
+
+ curve(c2pnb176v1) ->
+ {
+ {characteristic_two_field, 176, {ppbasis,1,2,43}},
+ {<<16#E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B:176>>, %% A
+ <<16#5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2:176>>, %% B
+ none}, %% Seed
+ <<16#04:8,
+ 16#8D16C2866798B600F9F08BB4A8E860F3298CE04A5798:176, %% X(p0)
+ 16#6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C:176>>, %% Y(p0)
+ <<16#010092537397ECA4F6145799D62B0A19CE06FE26AD:168>>, %% Order
+ <<16#FF6E:16>> %% CoFactor
+ };
+ */
+
+ /* Separate the curve definition from the curve name */
+ if (!enif_get_tuple(env, def, &arity, &curve_tuple) || (arity != 2))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Tuple arity 2 expected."));
+
+ /* {Field, Prime, Point, Order, CoFactor} = CurveDef */
+ if (!enif_get_tuple(env, curve_tuple[0], &c_arity, &curve) ||
+ c_arity != 5)
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad curve def. Expect 5-tuple."));
+
+ if (!get_ossl_octet_string_param_from_bin(env, "generator", curve[2], &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad Generator (Point)"));
+
+ if (!get_ossl_BN_param_from_bin_sz(env, "order", curve[3], &params[(*i)++], order_size))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad order"));
+
+ if (curve[4] == atom_none)
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Cofactor must be != none"));
+
+ if (!get_ossl_BN_param_from_bin(env, "cofactor", curve[4], &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad cofactor"));
+
+ /* {A, B, Seed} = Prime = curve[1] */
+ if (!enif_get_tuple(env, curve[1], &p_arity, &prime))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad Prime"));
+
+ if (!get_ossl_BN_param_from_bin(env, "a", prime[0], &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad a"));
+
+ if (!get_ossl_BN_param_from_bin(env, "b", prime[1], &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad b"));
+
+ if (enif_is_binary(env, prime[2]))
+ if (!get_ossl_octet_string_param_from_bin(env, "seed", prime[2], &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad seed"));
+
+ /* Field = curve[0] */
+ if (!enif_get_tuple(env, curve[0], &f_arity, &field)) {
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad Field"));
+ }
+ else if (f_arity == 2 && field[0] == atom_prime_field) {
+ /* {prime_field, Prime} */
+ params[(*i)++] = OSSL_PARAM_construct_utf8_string("field-type", "prime-field", 0);
+
+ if (!get_ossl_BN_param_from_bin(env, "p", field[1], &params[(*i)++]))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad p (Prime)"));
+ }
+
+ else if (f_arity == 3 && field[0] == atom_characteristic_two_field) {
+ /* {characteristic_two_field, M, Basis} */
+# if defined(OPENSSL_NO_EC2M)
+ assign_goto(*ret, err, EXCP_NOTSUP_N(env, 1, "Unsupported field-type (characteristic_two_field)"));
+# else
+ int b_arity = -1;
+ const ERL_NIF_TERM* basis;
+ long field_bits;
+
+ params[(*i)++] = OSSL_PARAM_construct_utf8_string("field-type", "characteristic-two-field", 0);
+
+ if ((p = BN_new()) == NULL)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Creating bignum failed"));
+
+ if (!enif_get_long(env, field[1], &field_bits) ||
+ (field_bits > OPENSSL_ECC_MAX_FIELD_BITS || field_bits > INT_MAX)
+ )
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad field-bits (M)"));
+
+ if (enif_get_tuple(env, field[2], &b_arity, &basis)) {
+ if (b_arity == 2) {
+ unsigned int k1;
+
+ if (basis[0] != atom_tpbasis)
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad atom"));
+ if (!enif_get_uint(env, basis[1], &k1))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "uint expected (k1)"));
+
+ /* {tpbasis, k} = Basis */
+ if (field_bits <= k1 || k1 == 0 || k1 > INT_MAX)
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "bad values (field_bits or k1)"));
+
+ /* create the polynomial */
+ if (!BN_set_bit(p, (int)field_bits) ||
+ !BN_set_bit(p, (int)k1) ||
+ !BN_set_bit(p, 0))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Polynom bit setting failed"));
+
+ } else if (b_arity == 4) {
+ /* {ppbasis, k1, k2, k3} = Basis */
+ unsigned int k1, k2, k3;
+
+ if (basis[0] != atom_ppbasis)
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad atom"));
+
+ if (!enif_get_uint(env, basis[1], &k1) ||
+ !enif_get_uint(env, basis[2], &k2) ||
+ !enif_get_uint(env, basis[3], &k3))
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Expecting uint (k1,k2,k3)"));
+
+ if (field_bits <= k3 || k3 <= k2 || k2 <= k1 || k1 == 0 ||
+ k3 > INT_MAX || k2 > INT_MAX || k1 > INT_MAX)
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "bad values (field_bits, k1, k2 or k3)"));
+
+ /* create the polynomial */
+ if (!BN_set_bit(p, (int)field_bits) ||
+ !BN_set_bit(p, (int)k1) ||
+ !BN_set_bit(p, (int)k2) ||
+ !BN_set_bit(p, (int)k3) ||
+ !BN_set_bit(p, 0) )
+ assign_goto(*ret, err, EXCP_ERROR(env, "Polynom bit setting failed"));
+
+ } else
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad tuple"));
+
+ } else if (field[2] == atom_onbasis) {
+ /* onbasis = Basis */
+ /* no parameters */
+ assign_goto(*ret, err, EXCP_NOTSUP_N(env, 1, "'onbasis' not supported"));
+ } else
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad last field"));
+
+ {
+ ErlNifBinary tmp;
+
+ if (!enif_inspect_binary(env, bin_from_bn(env,p), &tmp) || // Allocate buf
+ BN_bn2nativepad(p, tmp.data, tmp.size) < 0) {// Fill with BN in right endianity
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "BN padding failed"));
+ }
+ params[(*i)++] = OSSL_PARAM_construct_BN("p", tmp.data, tmp.size);
+ }
+# endif
+ }
else
- return enif_make_badarg(env);
+ assign_goto(*ret, err, EXCP_ERROR_N(env, 1, "Bad field-type"));
+
+ if (p) BN_free(p);
+ return 1;
+
+ err:
+ if (p) BN_free(p);
+ return 0;
+}
+
+int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
+{ /* key :: {CurveDef::{_,_,_,_,_}, PubKey::binary()} */
+ ERL_NIF_TERM ret = atom_undefined;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+ int i = 0;
+ OSSL_PARAM params[15];
+ EVP_PKEY_CTX *pctx = NULL;
+
+ if (!enif_get_tuple(env, key, &tpl_arity, &tpl_terms) ||
+ (tpl_arity != 2) ||
+ !enif_is_tuple(env, tpl_terms[0]) ||
+ !enif_is_binary(env, tpl_terms[1]) )
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad public key format"));
+
+ if (!get_ossl_octet_string_param_from_bin(env, "pub", tpl_terms[1], &params[i++]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad public key"));
+
+ if (!get_curve_definition(env, &ret, tpl_terms[0], params, &i, NULL))
+ goto err;
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't make EVP_PKEY_CTX"));
+
+ if (EVP_PKEY_fromdata_init(pctx) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata"));
+
+ if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata"));
+
+ if (!*pkey)
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't get a public key"));
+
+ if (pctx) EVP_PKEY_CTX_free(pctx);
+ return 1;
+
+ err:
+ if (pctx) EVP_PKEY_CTX_free(pctx);
+ return 0;
}
+
+int get_ec_private_key_2(ErlNifEnv* env,
+ ERL_NIF_TERM curve, ERL_NIF_TERM key,
+ EVP_PKEY **pkey,
+ ERL_NIF_TERM *ret,
+ size_t *order_size);
+
+int get_ec_private_key_2(ErlNifEnv* env,
+ ERL_NIF_TERM curve, ERL_NIF_TERM key,
+ EVP_PKEY **pkey,
+ ERL_NIF_TERM *ret,
+ size_t *order_size)
+{
+ int i = 0;
+ OSSL_PARAM params[15];
+ EVP_PKEY_CTX *pctx = NULL;
+
+ if (!get_ossl_BN_param_from_bin(env, "priv", key, &params[i++]))
+ assign_goto(*ret, err, EXCP_BADARG_N(env, 0, "Bad private key"));
+
+ if (!get_curve_definition(env, ret, curve, params, &i, order_size))
+ goto err;
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Can't make EVP_PKEY_CTX"));
+
+ if (EVP_PKEY_fromdata_init(pctx) <= 0)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Can't init fromdata"));
+
+ if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Can't do fromdata"));
+
+ if (!*pkey)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get a private key"));
+
+ if (pctx) EVP_PKEY_CTX_free(pctx);
+ return 1;
+
+ err:
+ if (pctx) EVP_PKEY_CTX_free(pctx);
+ return 0;
+}
+
+
+int get_ec_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
+{ /* key :: {CurveDef::{_,_,_,_,_}, PrivKey::binary()} */
+ ERL_NIF_TERM ret = atom_undefined;
+ const ERL_NIF_TERM *tpl_terms;
+ int tpl_arity;
+
+ if (!enif_get_tuple(env, key, &tpl_arity, &tpl_terms) ||
+ (tpl_arity != 2) ||
+ !enif_is_tuple(env, tpl_terms[0]) ||
+ !enif_is_binary(env, tpl_terms[1]) )
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad private key format"));
+
+ if (!get_ec_private_key_2(env, tpl_terms[0], tpl_terms[1], pkey, &ret, NULL))
+ goto err;
+
+ return 1;
+
+ err:
+ return 0;
+}
+
+int mk_pub_key_binary(ErlNifEnv* env, EVP_PKEY **peer_pkey, ErlNifBinary *pubkey_bin, ERL_NIF_TERM *ret);
+
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{ /* (Curve, PrivKey|undefined) */
+ ERL_NIF_TERM ret = atom_undefined;
+ int i = 0;
+ OSSL_PARAM params[15];
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *pkey = NULL, *peer_pkey = NULL;
+ size_t sz, order_size;
+ BIGNUM *priv_bn = NULL;
+ ErlNifBinary pubkey_bin;
+
+ if (argv[1] != atom_undefined)
+ {
+ if (!get_ec_private_key_2(env, argv[0], argv[1], &peer_pkey, &ret, &order_size))
+ goto err;
+
+ /* Get the two keys, pub as binary and priv as BN.
+ Since the private key is explicitly given, it must be calculated.
+ I haven't found any way to do that with the pure 3.0 interface yet.
+ */
+ if (!mk_pub_key_binary(env, &peer_pkey, &pubkey_bin, &ret))
+ goto err;
+
+ if (!EVP_PKEY_get_bn_param(peer_pkey, "priv", &priv_bn))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get peer priv key bytes"));
+ }
+ else
+ {
+ /* PrivKey (that is, argv[1]) == atom_undefined */
+ if (!get_curve_definition(env, &ret, argv[0], params, &i, &order_size))
+ // INSERT "ret" parameter in get_curve_definition !!
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Couldn't get Curve definition"));
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ /* Neither the private nor the public key is known, so we generate the pair: */
+ if (!(pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_new_from_name"));
+
+ if (EVP_PKEY_keygen_init(pctx) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen_init"));
+
+ if (!EVP_PKEY_CTX_set_params(pctx, params))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_params"));
+
+ if (!EVP_PKEY_generate(pctx, &pkey))
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't generate EC key"));
+
+ /* Get the two keys, pub as binary and priv as BN */
+ if (!EVP_PKEY_get_octet_string_param(pkey, "encoded-pub-key", NULL, 0, &sz))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get pub octet string size"));
+
+ if (!enif_alloc_binary(sz, &pubkey_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate pub octet string"));
+
+ if (!EVP_PKEY_get_octet_string_param(pkey, "encoded-pub-key",
+ pubkey_bin.data,
+ sz,
+ &pubkey_bin.size))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get pub octet string"));
+
+ if (!EVP_PKEY_get_bn_param(pkey, "priv", &priv_bn))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get priv key bytes"));
+ }
+
+ ret = enif_make_tuple2(env,
+ enif_make_binary(env, &pubkey_bin),
+ bn2term(env, order_size, priv_bn));
+ err:
+ if (pkey) EVP_PKEY_free(pkey);
+ if (peer_pkey) EVP_PKEY_free(peer_pkey);
+ if (pctx) EVP_PKEY_CTX_free(pctx);
+ if (priv_bn) BN_free(priv_bn);
+
+ return ret;
+}
+
+int mk_pub_key_binary(ErlNifEnv* env, EVP_PKEY **peer_pkey, ErlNifBinary *pubkey_bin, ERL_NIF_TERM *ret)
+{
+ EC_KEY *ec_key = NULL;
+ EC_POINT *public_key = NULL;
+ EC_GROUP *group = NULL;
+ BIGNUM *priv_bn = NULL;
+
+ *ret = atom_undefined;
+
+ /* Use the deprecated interface to get the curve and
+ private key in pre 3.0 form: */
+ if ((ec_key = EVP_PKEY_get1_EC_KEY(*peer_pkey)) == NULL)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC key"));
+
+ if ((group = EC_GROUP_dup(EC_KEY_get0_group(ec_key))) == NULL)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get EC_GROUP"));
+
+ if ((public_key = EC_POINT_new(group)) == NULL)
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't create POINT"));
+
+ if (!EC_POINT_copy(public_key, EC_GROUP_get0_generator(group)))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't copy POINT"));
+
+ /* Make the corresponding public key */
+ if (!EVP_PKEY_get_bn_param(*peer_pkey, "priv", &priv_bn))
+ assign_goto(*ret, err, EXCP_BADARG_N(env, 1, "Couldn't get peer priv key bytes"));
+
+ if (BN_is_zero(priv_bn))
+ assign_goto(*ret, err, EXCP_BADARG_N(env, 1, "peer priv key must not be 0"));
+
+ if (!EC_POINT_mul(group, public_key, priv_bn, NULL, NULL, NULL))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't multiply POINT"));
+
+ if (!EC_KEY_set_public_key(ec_key, public_key))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't set EC_KEY"));
+
+ if (!EVP_PKEY_assign_EC_KEY(*peer_pkey, ec_key))
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't assign EC_KEY to PKEY"));
+
+ /* And now get the binary representation (by some reason we can't read it from
+ peer_pubkey in the calling function with 3.0-functions.)
+ */
+ {
+ point_conversion_form_t form = EC_KEY_get_conv_form(ec_key);
+ size_t dlen = EC_POINT_point2oct(group, public_key, form, NULL, 0, NULL);
+
+ if (!enif_alloc_binary(dlen, pubkey_bin) ||
+ !EC_POINT_point2oct(group, public_key, form, pubkey_bin->data, pubkey_bin->size, NULL)
+ )
+ assign_goto(*ret, err, EXCP_ERROR(env, "Couldn't get public key"));
+ }
+
+ err:
+ if (public_key) EC_POINT_free(public_key);
+ if (group) EC_GROUP_free(group);
+ if (priv_bn) BN_free(priv_bn);
+
+ if (*ret == atom_undefined)
+ return 1;
+ else
+ return 0;
+}
+
+# endif /* HAS_3_0_API */
+
+
+
+
+/*----------------------------------------------------------------
+ Non 3.0-specific functions
+*/
+
+# if ! defined(HAS_3_0_API)
+
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg, size_t *size)
{
EC_KEY *key = NULL;
@@ -231,6 +666,33 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg, size_t *size)
return key;
}
+int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pptr)
+{
+ ErlNifBinary bin;
+ EC_POINT *point = NULL;
+
+ if (!enif_inspect_binary(env, term, &bin))
+ goto err;
+
+ if ((point = EC_POINT_new(group)) == NULL)
+ goto err;
+
+ /* set the point conversion form */
+ EC_GROUP_set_point_conversion_form(group, (point_conversion_form_t)(bin.data[0] & ~0x01));
+
+ /* extract the ec point */
+ if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL))
+ goto err;
+
+ *pptr = point;
+ return 1;
+
+ err:
+ if (point)
+ EC_POINT_free(point);
+ return 0;
+}
+
static ERL_NIF_TERM point2term(ErlNifEnv* env,
const EC_GROUP *group,
const EC_POINT *point,
@@ -266,33 +728,6 @@ static ERL_NIF_TERM point2term(ErlNifEnv* env,
return ret;
}
-int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pptr)
-{
- ErlNifBinary bin;
- EC_POINT *point = NULL;
-
- if (!enif_inspect_binary(env, term, &bin))
- goto err;
-
- if ((point = EC_POINT_new(group)) == NULL)
- goto err;
-
- /* set the point conversion form */
- EC_GROUP_set_point_conversion_form(group, (point_conversion_form_t)(bin.data[0] & ~0x01));
-
- /* extract the ec point */
- if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL))
- goto err;
-
- *pptr = point;
- return 1;
-
- err:
- if (point)
- EC_POINT_free(point);
- return 0;
-}
-
int get_ec_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
{
const ERL_NIF_TERM *tpl_terms;
@@ -310,6 +745,7 @@ int get_ec_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
if (!get_ec_key_sz(env, tpl_terms[0], tpl_terms[1], atom_undefined, &ec, NULL))
goto err;
+ *pkey = EVP_PKEY_new();
if (EVP_PKEY_assign_EC_KEY(*pkey, ec) != 1)
goto err;
/* On success, result owns ec */
@@ -339,6 +775,7 @@ int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
if (!get_ec_key_sz(env, tpl_terms[0], atom_undefined, tpl_terms[1], &ec, NULL))
goto err;
+ *pkey = EVP_PKEY_new();
if (EVP_PKEY_assign_EC_KEY(*pkey, ec) != 1)
goto err;
/* On success, result owns ec */
@@ -361,6 +798,8 @@ int get_ec_key_sz(ErlNifEnv* env,
BIGNUM *priv_key = NULL;
EC_POINT *pub_key = NULL;
EC_GROUP *group = NULL;
+ int arity = -1;
+ const ERL_NIF_TERM* curve_tuple;
if (priv != atom_undefined) {
if (!get_bn_from_bin(env, priv, &priv_key))
@@ -371,7 +810,10 @@ int get_ec_key_sz(ErlNifEnv* env,
goto err;
}
- if ((key = ec_key_new(env, curve, size)) == NULL)
+ if (!enif_get_tuple(env, curve, &arity, &curve_tuple) || (arity != 2))
+ goto err;
+
+ if ((key = ec_key_new(env, curve_tuple[0], size)) == NULL)
goto err;
if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL)
@@ -424,11 +866,8 @@ int get_ec_key_sz(ErlNifEnv* env,
return 1;
}
-#endif /* HAVE_EC */
-
-ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{ /* (Curve, PrivKey) */
-#if defined(HAVE_EC)
EC_KEY *key = NULL;
const EC_GROUP *group;
const EC_POINT *public_key;
@@ -438,11 +877,11 @@ ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
size_t size;
if (!get_ec_key_sz(env, argv[0], argv[1], atom_undefined, &key, &size))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get EC key"));
if (argv[1] == atom_undefined) {
if (!EC_KEY_generate_key(key))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't generate EC key"));
}
group = EC_KEY_get0_group(key);
@@ -461,15 +900,20 @@ ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
goto done;
err:
- bad_arg:
- ret = make_badarg_maybe(env);
-
done:
if (key)
EC_KEY_free(key);
return ret;
+}
-#else
- return atom_notsup;
-#endif
+# endif /* ! HAS_3_0_API */
+
+#endif /* HAVE_EC */
+
+
+#if ! defined(HAVE_EC)
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{ /* (Curve, PrivKey) */
+ return EXCP_NOTSUP_N(env, 0, "EC not supported");
}
+#endif
diff --git a/lib/crypto/c_src/ec.h b/lib/crypto/c_src/ec.h
index e7b885cb0f..e53986d64e 100644
--- a/lib/crypto/c_src/ec.h
+++ b/lib/crypto/c_src/ec.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,15 +24,24 @@
#include "common.h"
#if defined(HAVE_EC)
-int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey);
-int get_ec_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey);
+# if defined(HAS_3_0_API)
+int get_curve_definition(ErlNifEnv* env, ERL_NIF_TERM *ret, ERL_NIF_TERM def,
+ OSSL_PARAM params[], int *i,
+ size_t *order_size);
+# endif /* HAS_3_0_API */
+
+# if ! defined(HAS_3_0_API)
int get_ec_key_sz(ErlNifEnv* env, ERL_NIF_TERM curve, ERL_NIF_TERM priv, ERL_NIF_TERM pub,
EC_KEY** res, size_t* size);
+# endif
+
+int get_ec_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey);
+int get_ec_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey);
+
int term2point(ErlNifEnv* env, ERL_NIF_TERM term, EC_GROUP *group, EC_POINT **pptr);
-ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env);
#endif
-ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM ec_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif /* E_EC_H__ */
diff --git a/lib/crypto/c_src/ecdh.c b/lib/crypto/c_src/ecdh.c
index 041c658808..7509d9cb84 100644
--- a/lib/crypto/c_src/ecdh.c
+++ b/lib/crypto/c_src/ecdh.c
@@ -21,15 +21,124 @@
#include "ecdh.h"
#include "ec.h"
-/*
- (_OthersPublicKey, _MyPrivateKey)
- (_OthersPublicKey, _MyEC_Point)
-*/
+#if !defined(HAVE_EC)
+ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+/* (OtherPublicKey, {CurveDef,CurveName}, My) */
+{
+ return EXCP_NOTSUP_N(env, 0, "EC not supported");
+}
+
+#else
+
+# if defined(HAS_3_0_API)
+# include "bn.h"
+
+ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+/* (OtherPublicKey, {CurveDef,CurveName}, My) */
+{
+ ERL_NIF_TERM ret = atom_undefined;
+ ErlNifBinary ret_bin;
+ size_t sz;
+ int ret_bin_alloc = 0;
+ int i = 0, i_key = 0;
+ OSSL_PARAM params[15];
+ EVP_PKEY_CTX *own_pctx = NULL, *peer_pctx = NULL, *pctx_gen = NULL;
+ EVP_PKEY *own_pkey = NULL, *peer_pkey = NULL;
+ int err;
+
+ /**** Fetch parameters ****/
+
+ /* Build peer_pkey */
+ i_key = i;
+ if (!get_ossl_octet_string_param_from_bin(env, "pub", argv[0], &params[i++]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad peer public key; binary expected"));
+
+ /* Curve definition/name */
+ if (!get_curve_definition(env, &ret, argv[1], params, &i, NULL))
+ goto err;
+
+ /* End of params */
+ params[i++] = OSSL_PARAM_construct_end();
+
+ /* Build the remote public key in peer_pkey */
+ peer_pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+
+ if (EVP_PKEY_fromdata_init(peer_pctx) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata"));
+
+ if (EVP_PKEY_fromdata(peer_pctx, &peer_pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata"));
+
+ if (!peer_pkey)
+ assign_goto(ret, err, EXCP_ERROR(env, "No peer_pkey"));
+
+ /* Build the local private (and public) key in own_pkey */
+
+ /* Just replace the pub key with the priv key in params; the
+ curve definition is of course the same
+ */
+ if (!get_ossl_BN_param_from_bin(env, "priv", argv[2], &params[i_key]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Bad peer public key; binary expected"));
+
+ own_pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+
+ if (EVP_PKEY_fromdata_init(own_pctx) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't init fromdata"));
+
+ if (EVP_PKEY_fromdata(own_pctx, &own_pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't do fromdata"));
+
+ if (!own_pkey)
+ assign_goto(ret, err, EXCP_ERROR(env, "No own_pkey"));
+
+ /**** Derive the common secret from own_pkey and peer_pkey ****/
+
+ if (!(pctx_gen = EVP_PKEY_CTX_new(own_pkey, NULL)))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_init"));
+
+ if (EVP_PKEY_derive_init(pctx_gen) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_derive_init"));
+
+ if ((err = EVP_PKEY_derive_set_peer_ex(pctx_gen, peer_pkey, 0)) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't derive secret or set peer"));
+
+ if ((err = EVP_PKEY_derive(pctx_gen, NULL, &sz)) <= 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get result size"));
+
+ if (!enif_alloc_binary(sz, &ret_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allcate binary"));
+ ret_bin_alloc = 1;
+
+ if ((err = EVP_PKEY_derive(pctx_gen, ret_bin.data, &ret_bin.size)) <=0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get result"));
+
+ if (sz != ret_bin.size)
+ if (!enif_realloc_binary(&ret_bin, ret_bin.size))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't realloc binary"));
+
+ ret = enif_make_binary(env, &ret_bin);
+ ret_bin_alloc = 0;
+
+ err:
+ if (ret_bin_alloc) enif_release_binary(&ret_bin);
+ if (peer_pctx) EVP_PKEY_CTX_free(peer_pctx);
+ if (peer_pkey) EVP_PKEY_free(peer_pkey);
+ if (own_pctx) EVP_PKEY_CTX_free(own_pctx);
+ if (own_pkey) EVP_PKEY_free(own_pkey);
+ if (pctx_gen) EVP_PKEY_CTX_free(pctx_gen);
+ return ret;
+}
+
+# endif /* HAS_3_0_API */
+
+
+
+# if ! defined(HAS_3_0_API)
+
ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-/* (OtherPublicKey, Curve, My) */
+/* (OtherPublicKey, {CurveDef,_CurveName}, My) */
{
-#if defined(HAVE_EC)
- ERL_NIF_TERM ret;
+ ERL_NIF_TERM ret = atom_undefined;
unsigned char *p;
EC_KEY* key = NULL;
int degree;
@@ -39,44 +148,37 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
EC_POINT *my_ecpoint = NULL;
EC_KEY *other_ecdh = NULL;
- ASSERT(argc == 3);
-
if (!get_ec_key_sz(env, argv[1], argv[2], atom_undefined, &key, NULL)) // my priv key
- goto bad_arg;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Couldn't get local key"));
+
if ((group = EC_GROUP_dup(EC_KEY_get0_group(key))) == NULL)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't duplicate EC key"));
+
priv_key = EC_KEY_get0_private_key(key);
- if (!term2point(env, argv[0], group, &my_ecpoint)) {
- goto err;
- }
+ if (!term2point(env, argv[0], group, &my_ecpoint))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Couldn't get ecpoint"));
if ((other_ecdh = EC_KEY_new()) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't allocate EC_KEY"));
+
if (!EC_KEY_set_group(other_ecdh, group))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set group"));
+
if (!EC_KEY_set_private_key(other_ecdh, priv_key))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set private key"));
if ((degree = EC_GROUP_get_degree(group)) <= 0)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't get degree"));
field_size = (size_t)degree;
if ((p = enif_make_new_binary(env, (field_size+7)/8, &ret)) == NULL)
- goto err;
- if (ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL) < 1)
- goto err;
-
- goto done;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't allocate binary"));
- bad_arg:
- ret = make_badarg_maybe(env);
- goto done;
+ if (ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL) < 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't compute key"));
err:
- ret = enif_make_badarg(env);
-
- done:
if (group)
EC_GROUP_free(group);
if (my_ecpoint)
@@ -87,8 +189,6 @@ ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
EC_KEY_free(key);
return ret;
-
-#else
- return atom_notsup;
-#endif
}
+# endif /* ! HAS_3_0_API */
+#endif /* HAVE_EC */
diff --git a/lib/crypto/c_src/engine.c b/lib/crypto/c_src/engine.c
index 1ad8fd698a..16de4b8a40 100644
--- a/lib/crypto/c_src/engine.c
+++ b/lib/crypto/c_src/engine.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,10 +31,11 @@ struct engine_ctx {
#define ERROR_Atom(Env, ReasonString) ERROR_Term((Env), enif_make_atom((Env),(ReasonString)))
static ErlNifResourceType* engine_ctx_rtype;
+static ErlNifMutex *ensure_engine_loaded_mtx = NULL;
-static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i);
static int zero_terminate(ErlNifBinary bin, char **buf);
+
static void engine_ctx_dtor(ErlNifEnv* env, struct engine_ctx* ctx) {
if (ctx == NULL)
return;
@@ -47,8 +48,10 @@ static void engine_ctx_dtor(ErlNifEnv* env, struct engine_ctx* ctx) {
PRINTF_ERR0(" empty ctx->id=NULL");
if (ctx->engine) {
- if (ctx->is_functional)
+ if (ctx->is_functional) {
+ //printf("\nCalling finish gc\n\n");
ENGINE_finish(ctx->engine);
+ }
ENGINE_free(ctx->engine);
}
}
@@ -117,11 +120,235 @@ int init_engine_ctx(ErlNifEnv *env) {
PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'");
return 0;
}
+
#endif
return 1;
}
+int create_engine_mutex(ErlNifEnv *env) {
+#ifdef HAS_ENGINE_SUPPORT
+
+ if (!ensure_engine_loaded_mtx && ((ensure_engine_loaded_mtx = enif_mutex_create("crypto.ensure_engine_loaded")) == NULL)) {
+ PRINTF_ERR0("CRYPTO: Could not create mutex 'crypto.ensure_engine_loaded'");
+ return 0;
+ }
+
+#endif
+ return 1;
+}
+
+void destroy_engine_mutex(ErlNifEnv *env) {
+#ifdef HAS_ENGINE_SUPPORT
+
+ enif_mutex_destroy(ensure_engine_loaded_mtx);
+ ensure_engine_loaded_mtx = NULL;
+
+#endif
+}
+
+#ifdef HAS_ENGINE_SUPPORT
+static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i)
+{
+ ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM *tmp_tuple;
+ ErlNifBinary tmpbin;
+ int arity;
+ char *tuple1 = NULL, *tuple2 = NULL;
+
+ if (enif_is_empty_list(env, term)) {
+ cmds[i] = NULL;
+ return 0;
+ }
+
+ if (!enif_get_list_cell(env, term, &head, &tail))
+ goto err;
+ if (!enif_get_tuple(env, head, &arity, &tmp_tuple))
+ goto err;
+ if (arity != 2)
+ goto err;
+ if (!enif_inspect_binary(env, tmp_tuple[0], &tmpbin))
+ goto err;
+
+ if ((tuple1 = enif_alloc(tmpbin.size + 1)) == NULL)
+ goto err;
+
+ (void) memcpy(tuple1, tmpbin.data, tmpbin.size);
+ tuple1[tmpbin.size] = '\0';
+ cmds[i] = tuple1;
+ i++;
+
+ if (!enif_inspect_binary(env, tmp_tuple[1], &tmpbin))
+ goto err;
+
+ if (tmpbin.size == 0) {
+ cmds[i] = NULL;
+ } else {
+ if ((tuple2 = enif_alloc(tmpbin.size + 1)) == NULL)
+ goto err;
+ (void) memcpy(tuple2, tmpbin.data, tmpbin.size);
+ tuple2[tmpbin.size] = '\0';
+ cmds[i] = tuple2;
+ }
+ i++;
+ return get_engine_load_cmd_list(env, tail, cmds, i);
+
+ err:
+ if (tuple1 != NULL) {
+ i--;
+ enif_free(tuple1);
+ }
+ cmds[i] = NULL;
+ return -1;
+}
+
+static int register_method(ENGINE *engine, unsigned int method)
+{
+ int ret = 0;
+
+ switch(method)
+ {
+#ifdef ENGINE_METHOD_RSA
+ case ENGINE_METHOD_RSA:
+ ret = ENGINE_register_RSA(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ case ENGINE_METHOD_DSA:
+ ret = ENGINE_register_DSA(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DH
+ case ENGINE_METHOD_DH:
+ ret = ENGINE_register_DH(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ case ENGINE_METHOD_RAND:
+ ret = ENGINE_register_RAND(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ case ENGINE_METHOD_ECDH:
+ ret = ENGINE_register_ECDH(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ case ENGINE_METHOD_ECDSA:
+ ret = ENGINE_register_ECDSA(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ case ENGINE_METHOD_STORE:
+ ret = ENGINE_register_STORE(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ case ENGINE_METHOD_CIPHERS:
+ ret = ENGINE_register_ciphers(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ case ENGINE_METHOD_DIGESTS:
+ ret = ENGINE_register_digests(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ case ENGINE_METHOD_PKEY_METHS:
+ ret = ENGINE_register_pkey_meths(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ case ENGINE_METHOD_PKEY_ASN1_METHS:
+ ret = ENGINE_register_pkey_asn1_meths(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_EC
+ case ENGINE_METHOD_EC:
+ ret = ENGINE_register_EC(engine);
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ return ret;
+}
+
+static void unregister_method(ENGINE *engine, unsigned int method)
+{
+
+ switch(method)
+ {
+#ifdef ENGINE_METHOD_RSA
+ case ENGINE_METHOD_RSA:
+ ENGINE_unregister_RSA(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DSA
+ case ENGINE_METHOD_DSA:
+ ENGINE_unregister_DSA(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DH
+ case ENGINE_METHOD_DH:
+ ENGINE_unregister_DH(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_RAND
+ case ENGINE_METHOD_RAND:
+ ENGINE_unregister_RAND(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDH
+ case ENGINE_METHOD_ECDH:
+ ENGINE_unregister_ECDH(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_ECDSA
+ case ENGINE_METHOD_ECDSA:
+ ENGINE_unregister_ECDSA(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_STORE
+ case ENGINE_METHOD_STORE:
+ ENGINE_unregister_STORE(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_CIPHERS
+ case ENGINE_METHOD_CIPHERS:
+ ENGINE_unregister_ciphers(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_DIGESTS
+ case ENGINE_METHOD_DIGESTS:
+ ENGINE_unregister_digests(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_METHS
+ case ENGINE_METHOD_PKEY_METHS:
+ ENGINE_unregister_pkey_meths(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
+ case ENGINE_METHOD_PKEY_ASN1_METHS:
+ ENGINE_unregister_pkey_asn1_meths(engine);
+ break;
+#endif
+#ifdef ENGINE_METHOD_EC
+ case ENGINE_METHOD_EC:
+ ENGINE_unregister_EC(engine);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return;
+}
+
+#endif /* HAS_ENGINE_SUPPORT */
+
ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (EngineId) */
#ifdef HAS_ENGINE_SUPPORT
@@ -131,9 +358,10 @@ ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ENGINE *engine;
struct engine_ctx *ctx = NULL;
- // Get Engine Id
+ /* Get Arguments */
ASSERT(argc == 1);
+ /* EngineId */
if (!enif_inspect_binary(env, argv[0], &engine_id_bin))
goto bad_arg;
@@ -142,12 +370,12 @@ ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
(void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size);
engine_id[engine_id_bin.size] = '\0';
+
if ((engine = ENGINE_by_id(engine_id)) == NULL) {
PRINTF_ERR0("engine_by_id_nif Leaved: {error, bad_engine_id}");
ret = ERROR_Atom(env, "bad_engine_id");
goto done;
}
-
if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL)
goto err;
ctx->engine = engine;
@@ -181,9 +409,10 @@ ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
#ifdef HAS_ENGINE_SUPPORT
struct engine_ctx *ctx;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 1);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx))
goto bad_arg;
@@ -213,6 +442,7 @@ ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
if (ctx->engine) {
if (ctx->is_functional) {
+ printf("\nCalling finish\n\n");
if (!ENGINE_finish(ctx->engine))
goto err;
ctx->is_functional = 0;
@@ -224,6 +454,7 @@ ERL_NIF_TERM engine_free_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
else {
ASSERT(!ctx->is_functional);
}
+
return atom_ok;
bad_arg:
@@ -257,15 +488,16 @@ ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF
int optional = 0;
int cmds_loaded = 0;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 3);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
|| !ctx->engine)
goto bad_arg;
PRINTF_ERR1("Engine Id: %s\r\n", ENGINE_get_id(ctx->engine));
- // Get Command List
+ /* Command List */
if (!enif_get_list_length(env, argv[1], &cmds_len))
goto bad_arg;
@@ -326,9 +558,10 @@ ERL_NIF_TERM engine_add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
#ifdef HAS_ENGINE_SUPPORT
struct engine_ctx *ctx;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 1);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
|| !ctx->engine)
goto bad_arg;
@@ -354,9 +587,10 @@ ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
#ifdef HAS_ENGINE_SUPPORT
struct engine_ctx *ctx;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 1);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
|| !ctx->engine)
goto bad_arg;
@@ -382,91 +616,26 @@ ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
struct engine_ctx *ctx;
unsigned int method;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 2);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
|| !ctx->engine)
goto bad_arg;
if (!enif_get_uint(env, argv[1], &method))
goto bad_arg;
- switch(method)
+ switch(register_method(ctx->engine, method))
{
-#ifdef ENGINE_METHOD_RSA
- case ENGINE_METHOD_RSA:
- if (!ENGINE_register_RSA(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_DSA
- case ENGINE_METHOD_DSA:
- if (!ENGINE_register_DSA(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_DH
- case ENGINE_METHOD_DH:
- if (!ENGINE_register_DH(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_RAND
- case ENGINE_METHOD_RAND:
- if (!ENGINE_register_RAND(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_ECDH
- case ENGINE_METHOD_ECDH:
- if (!ENGINE_register_ECDH(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_ECDSA
- case ENGINE_METHOD_ECDSA:
- if (!ENGINE_register_ECDSA(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_STORE
- case ENGINE_METHOD_STORE:
- if (!ENGINE_register_STORE(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_CIPHERS
- case ENGINE_METHOD_CIPHERS:
- if (!ENGINE_register_ciphers(ctx->engine))
- goto failed;
+ case 1:
break;
-#endif
-#ifdef ENGINE_METHOD_DIGESTS
- case ENGINE_METHOD_DIGESTS:
- if (!ENGINE_register_digests(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_PKEY_METHS
- case ENGINE_METHOD_PKEY_METHS:
- if (!ENGINE_register_pkey_meths(ctx->engine))
- goto failed;
- break;
-#endif
-#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
- case ENGINE_METHOD_PKEY_ASN1_METHS:
- if (!ENGINE_register_pkey_asn1_meths(ctx->engine))
- goto failed;
+ case 0:
+ goto failed;
break;
-#endif
-#ifdef ENGINE_METHOD_EC
- case ENGINE_METHOD_EC:
- if (!ENGINE_register_EC(ctx->engine))
- goto failed;
+ case -1:
+ goto not_supported;
break;
-#endif
- default:
- return ERROR_Atom(env, "engine_method_not_supported");
}
return atom_ok;
@@ -477,6 +646,9 @@ ERL_NIF_TERM engine_register_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
failed:
return ERROR_Atom(env, "register_engine_failed");
+ not_supported:
+ return ERROR_Atom(env, "engine_method_not_supported");
+
#else
return atom_notsup;
#endif
@@ -488,80 +660,17 @@ ERL_NIF_TERM engine_unregister_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
struct engine_ctx *ctx;
unsigned int method;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 2);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
|| !ctx->engine)
goto bad_arg;
if (!enif_get_uint(env, argv[1], &method))
goto bad_arg;
- switch(method)
- {
-#ifdef ENGINE_METHOD_RSA
- case ENGINE_METHOD_RSA:
- ENGINE_unregister_RSA(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_DSA
- case ENGINE_METHOD_DSA:
- ENGINE_unregister_DSA(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_DH
- case ENGINE_METHOD_DH:
- ENGINE_unregister_DH(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_RAND
- case ENGINE_METHOD_RAND:
- ENGINE_unregister_RAND(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_ECDH
- case ENGINE_METHOD_ECDH:
- ENGINE_unregister_ECDH(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_ECDSA
- case ENGINE_METHOD_ECDSA:
- ENGINE_unregister_ECDSA(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_STORE
- case ENGINE_METHOD_STORE:
- ENGINE_unregister_STORE(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_CIPHERS
- case ENGINE_METHOD_CIPHERS:
- ENGINE_unregister_ciphers(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_DIGESTS
- case ENGINE_METHOD_DIGESTS:
- ENGINE_unregister_digests(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_PKEY_METHS
- case ENGINE_METHOD_PKEY_METHS:
- ENGINE_unregister_pkey_meths(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_PKEY_ASN1_METHS
- case ENGINE_METHOD_PKEY_ASN1_METHS:
- ENGINE_unregister_pkey_asn1_meths(ctx->engine);
- break;
-#endif
-#ifdef ENGINE_METHOD_EC
- case ENGINE_METHOD_EC:
- ENGINE_unregister_EC(ctx->engine);
- break;
-#endif
- default:
- break;
- }
+ unregister_method(ctx->engine, method);
return atom_ok;
@@ -621,9 +730,10 @@ ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
ErlNifBinary engine_bin;
struct engine_ctx *ctx, *next_ctx = NULL;
- // Get Engine
+ /* Get Arguments */
ASSERT(argc == 1);
+ /* Engine */
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
|| !ctx->engine)
goto bad_arg;
@@ -674,7 +784,7 @@ ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
size_t size;
struct engine_ctx *ctx = NULL;
- // Get Engine
+ // Get arguments
ASSERT(argc == 1);
if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)
@@ -744,62 +854,6 @@ ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
#endif
}
-#ifdef HAS_ENGINE_SUPPORT
-static int get_engine_load_cmd_list(ErlNifEnv* env, const ERL_NIF_TERM term, char **cmds, int i)
-{
- ERL_NIF_TERM head, tail;
- const ERL_NIF_TERM *tmp_tuple;
- ErlNifBinary tmpbin;
- int arity;
- char *tuple1 = NULL, *tuple2 = NULL;
-
- if (enif_is_empty_list(env, term)) {
- cmds[i] = NULL;
- return 0;
- }
-
- if (!enif_get_list_cell(env, term, &head, &tail))
- goto err;
- if (!enif_get_tuple(env, head, &arity, &tmp_tuple))
- goto err;
- if (arity != 2)
- goto err;
- if (!enif_inspect_binary(env, tmp_tuple[0], &tmpbin))
- goto err;
-
- if ((tuple1 = enif_alloc(tmpbin.size + 1)) == NULL)
- goto err;
-
- (void) memcpy(tuple1, tmpbin.data, tmpbin.size);
- tuple1[tmpbin.size] = '\0';
- cmds[i] = tuple1;
- i++;
-
- if (!enif_inspect_binary(env, tmp_tuple[1], &tmpbin))
- goto err;
-
- if (tmpbin.size == 0) {
- cmds[i] = NULL;
- } else {
- if ((tuple2 = enif_alloc(tmpbin.size + 1)) == NULL)
- goto err;
- (void) memcpy(tuple2, tmpbin.data, tmpbin.size);
- tuple2[tmpbin.size] = '\0';
- cmds[i] = tuple2;
- }
- i++;
- return get_engine_load_cmd_list(env, tail, cmds, i);
-
- err:
- if (tuple1 != NULL) {
- i--;
- enif_free(tuple1);
- }
- cmds[i] = NULL;
- return -1;
-}
-#endif /* HAS_ENGINE_SUPPORT */
-
ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* () */
#ifdef HAS_ENGINE_SUPPORT
@@ -850,3 +904,131 @@ ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_
return atom_notsup;
#endif
}
+
+ERL_NIF_TERM ensure_engine_loaded_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (EngineId, LibPath) */
+#ifdef HAS_ENGINE_SUPPORT
+ ERL_NIF_TERM ret, result;
+ ErlNifBinary engine_id_bin,
+ library_path_bin;
+ char *engine_id = NULL,
+ *library_path = NULL;
+ int is_locked = 0;
+
+ ENGINE *engine = NULL;
+ struct engine_ctx *ctx = NULL;
+
+ /* Get Arguments */
+ ASSERT(argc == 2);
+
+ /* EngineId */
+ if (!enif_inspect_binary(env, argv[0], &engine_id_bin))
+ goto bad_arg;
+
+ if ((engine_id = enif_alloc(engine_id_bin.size+1)) == NULL)
+ goto bad_arg;
+
+ (void) memcpy(engine_id, engine_id_bin.data, engine_id_bin.size);
+ engine_id[engine_id_bin.size] = '\0';
+
+ /* LibPath */
+ if (!enif_inspect_binary(env, argv[1], &library_path_bin))
+ goto bad_arg;
+
+ if ((library_path = enif_alloc(library_path_bin.size+1)) == NULL)
+ goto bad_arg;
+
+ (void) memcpy(library_path, library_path_bin.data, library_path_bin.size);
+ library_path[library_path_bin.size] = '\0';
+
+ /* Loading Engine */
+ enif_mutex_lock(ensure_engine_loaded_mtx);
+ is_locked = 1;
+
+ if ((engine = ENGINE_by_id(engine_id)) == NULL)
+ {
+ PRINTF_ERR0("Load engine\r\n");
+ /* Load dynamic engine */
+ ENGINE_load_dynamic();
+ if ((engine = ENGINE_by_id("dynamic")) == NULL) {
+ PRINTF_ERR0("ensure_engine_loaded_nif; couldn't get the dynamic engine");
+ ret = ERROR_Atom(env, "bad_engine_id");
+ goto done;
+ }
+
+ /* Use dynamic engine to load the real engine */
+ /* From this point an ENGINE_free() is done on failure */
+ if(!ENGINE_ctrl_cmd_string(engine, "SO_PATH", library_path, 0)) {
+ PRINTF_ERR1("Cmd: SO_PATH:%s\r\n", library_path);
+ ret = ERROR_Atom(env, "ctrl_cmd_failed");
+ goto err;
+ }
+ if(!ENGINE_ctrl_cmd_string(engine, "ID", engine_id, 0)) {
+ PRINTF_ERR1("Cmd: ID:%s\r\n", engine_id);
+ ret = ERROR_Atom(env, "ctrl_cmd_failed");
+ goto err;
+ }
+ if(!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {
+ PRINTF_ERR0("Cmd: LOAD:(NULL)\r\n");
+ ret = ERROR_Atom(env, "ctrl_cmd_failed");
+ goto err;
+ }
+
+ /* Add engine to OpenSSls internal list */
+ if(!ENGINE_add(engine)) {
+ ret = ERROR_Atom(env, "add_engine_failed");
+ goto err;
+ }
+ }
+
+ PRINTF_ERR0("Initialize engine\r\n");
+
+ /* Init engine and get functional reference */
+ if (!ENGINE_init(engine)) {
+ ret = ERROR_Atom(env, "engine_init_failed");
+ goto err;
+ }
+
+ /* Get structural reference to already loaded engine */
+ if ((ctx = enif_alloc_resource(engine_ctx_rtype, sizeof(struct engine_ctx))) == NULL) {
+ ret = enif_make_badarg(env);
+ ENGINE_finish(engine);
+ goto err;
+ }
+ ctx->engine = engine;
+ ctx->is_functional = 1;
+ ctx->id = engine_id;
+ /* ctx now owns engine_id */
+ engine_id = NULL;
+
+ result = enif_make_resource(env, ctx);
+ ret = enif_make_tuple2(env, atom_ok, result);
+ goto done;
+
+ bad_arg:
+ ret = enif_make_badarg(env);
+
+ err:
+ if(engine)
+ ENGINE_free(engine);
+
+ done:
+
+ enif_free(library_path);
+
+ if(is_locked) {
+ enif_mutex_unlock(ensure_engine_loaded_mtx);
+ is_locked = 0;
+ }
+
+ if (engine_id)
+ enif_free(engine_id);
+ if (ctx)
+ enif_release_resource(ctx);
+
+ return ret;
+
+#else
+ return atom_notsup;
+#endif
+}
diff --git a/lib/crypto/c_src/engine.h b/lib/crypto/c_src/engine.h
index 4a2eed9672..f6a5a2921b 100644
--- a/lib/crypto/c_src/engine.h
+++ b/lib/crypto/c_src/engine.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2018. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@ char *get_key_password(ErlNifEnv *env, ERL_NIF_TERM key);
#endif /* HAS_ENGINE_SUPPORT */
int init_engine_ctx(ErlNifEnv *env);
+int create_engine_mutex(ErlNifEnv *env);
+void destroy_engine_mutex(ErlNifEnv *env);
ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -45,5 +47,6 @@ ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-
+ERL_NIF_TERM ensure_engine_loaded_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM ensure_engine_unloaded_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif /* E_ENGINE_H__ */
diff --git a/lib/crypto/c_src/evp.c b/lib/crypto/c_src/evp.c
index 7491db3d57..3a3f384a60 100644
--- a/lib/crypto/c_src/evp.c
+++ b/lib/crypto/c_src/evp.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,43 +34,53 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
ASSERT(argc == 3);
+ /* Arg 0, Curve */
if (argv[0] == atom_x25519)
type = EVP_PKEY_X25519;
else if (argv[0] == atom_x448)
type = EVP_PKEY_X448;
else
- goto bad_arg;
+ assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 0, "Bad curve"));
- if (!enif_inspect_binary(env, argv[1], &peer_bin))
- goto bad_arg;
+ /* Arg 2, MyBin (My private key) */
if (!enif_inspect_binary(env, argv[2], &my_bin))
- goto bad_arg;
+ assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 2, "Binary expected"));
if ((my_key = EVP_PKEY_new_raw_private_key(type, NULL, my_bin.data, my_bin.size)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Not a valid raw private key"));
+
if ((ctx = EVP_PKEY_CTX_new(my_key, NULL)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 2, "Can't make context"));
if (EVP_PKEY_derive_init(ctx) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_derive_init"));
+
+ /* Arg 1, PeerBin (Peer public key) */
+ if (!enif_inspect_binary(env, argv[1], &peer_bin))
+ assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 1, "Binary expected"));
if ((peer_key = EVP_PKEY_new_raw_public_key(type, NULL, peer_bin.data, peer_bin.size)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Not a raw public peer key"));
+
if (EVP_PKEY_derive_set_peer(ctx, peer_key) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't EVP_PKEY_derive_set_peer"));
+ /* Find max size of the common key */
if (EVP_PKEY_derive(ctx, NULL, &max_size) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
if (!enif_alloc_binary(max_size, &key_bin))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate"));
+
key_bin_alloc = 1;
+
+ /* Derive the common key */
if (EVP_PKEY_derive(ctx, key_bin.data, &key_bin.size) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_derive"));
if (key_bin.size < max_size) {
if (!enif_realloc_binary(&key_bin, (size_t)key_bin.size))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't shrink binary"));
}
ret = enif_make_binary(env, &key_bin);
@@ -81,7 +91,6 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
err:
if (key_bin_alloc)
enif_release_binary(&key_bin);
- ret = enif_make_badarg(env);
done:
if (my_key)
@@ -98,6 +107,7 @@ ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
#endif
}
+
ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve) */
{
@@ -119,46 +129,41 @@ ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
else if (argv[0] == atom_ed448)
type = EVP_PKEY_ED448;
else
- goto bad_arg;
+ assign_goto(ret, bad_arg, EXCP_BADARG_N(env, 0, "Bad curve"));
if (argv[1] == atom_undefined) {
if ((ctx = EVP_PKEY_CTX_new_id(type, NULL)) == NULL)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't make context"));
if (EVP_PKEY_keygen_init(ctx) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen_init"));
if (EVP_PKEY_keygen(ctx, &pkey) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_keygen"));
} else {
if (!enif_inspect_binary(env, argv[1], &prv_key))
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
if ((pkey = EVP_PKEY_new_raw_private_key(type, NULL, prv_key.data, prv_key.size)) == NULL)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't EVP_PKEY_new_raw_private_key"));
}
if (EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
if ((out_pub = enif_make_new_binary(env, key_len, &ret_pub)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate"));
if (EVP_PKEY_get_raw_public_key(pkey, out_pub, &key_len) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_get_raw_public_key"));
if (EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR_N(env, 1, "Can't get max size"));
if ((out_priv = enif_make_new_binary(env, key_len, &ret_prv)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate"));
if (EVP_PKEY_get_raw_private_key(pkey, out_priv, &key_len) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_get_raw_private_key"));
ret = enif_make_tuple2(env, ret_pub, ret_prv);
goto done;
bad_arg:
- ret = enif_make_badarg(env);
- goto done;
-
err:
- ret = atom_error;
-
done:
if (pkey)
EVP_PKEY_free(pkey);
diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c
index 92f599fc61..ba454f5062 100644
--- a/lib/crypto/c_src/hash.c
+++ b/lib/crypto/c_src/hash.c
@@ -104,39 +104,30 @@ ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
unsigned ret_size;
unsigned char *outp;
- ASSERT(argc == 2);
-
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_NOTSUP_N(env, 0, "Bad digest type in FIPS");
+ if ((md = digp->md.p) == NULL)
+ return EXCP_NOTSUP_N(env, 0, "Digest type not supported in this cryptolib");
+
if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 1, "Not iolist");
- if ((md = digp->md.p) == NULL)
- goto err;
ret_size = (unsigned)EVP_MD_size(md);
ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
+
if (EVP_Digest(data.data, data.size, outp, &ret_size, md, NULL) != 1)
- goto err;
+ return EXCP_ERROR(env, "Low-level call failed");
ASSERT(ret_size == (unsigned)EVP_MD_size(md));
CONSUME_REDS(env, data);
return ret;
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- return atom_notsup;
-
- err:
- return atom_notsup;
}
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
@@ -147,31 +138,22 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
struct evp_md_ctx *ctx = NULL;
ERL_NIF_TERM ret;
- ASSERT(argc == 1);
-
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
+
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_NOTSUP_N(env, 0, "Digest type not supported in FIPS");
if (digp->md.p == NULL)
- goto err;
+ return EXCP_NOTSUP_N(env, 0, "Unsupported digest type");
if ((ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate nif resource");
if ((ctx->ctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_new failed"));
if (EVP_DigestInit(ctx->ctx, digp->md.p) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestInit failed"));
ret = enif_make_resource(env, ctx);
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- err:
- ret = atom_notsup;
done:
if (ctx)
@@ -185,31 +167,23 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
ErlNifBinary data;
ERL_NIF_TERM ret;
- ASSERT(argc == 2);
-
if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+
if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 1, "Not iolist");
if ((new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate nif resource");
if ((new_ctx->ctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_new failed"));
if (EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_copy failed"));
if (EVP_DigestUpdate(new_ctx->ctx, data.data, data.size) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestUpdate failed"));
ret = enif_make_resource(env, new_ctx);
CONSUME_REDS(env, data);
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- err:
- ret = atom_notsup;
done:
if (new_ctx)
@@ -228,28 +202,21 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ASSERT(argc == 1);
if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
ret_size = (unsigned)EVP_MD_CTX_size(ctx->ctx);
ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
if ((new_ctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_new failed"));
if (EVP_MD_CTX_copy(new_ctx, ctx->ctx) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_copy failed"));
if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Can't make a new binary"));
if (EVP_DigestFinal(new_ctx, outp, &ret_size) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestFinal failed"));
ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx->ctx));
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- err:
- ret = atom_notsup;
done:
if (new_ctx)
@@ -271,11 +238,12 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ASSERT(argc == 1);
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
+
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_NOTSUP_N(env, 0, "Digest type not supported in FIPS");
if (digp->md.p == NULL)
- goto err;
+ return EXCP_NOTSUP_N(env, 0, "Unsupported digest type");
switch (EVP_MD_type(digp->md.p))
{
@@ -326,27 +294,18 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
break;
#endif
default:
- goto err;
+ return EXCP_NOTSUP_N(env, 0, "Unsupported digest type");
}
ASSERT(ctx_size);
ASSERT(ctx_init);
if ((outp = enif_make_new_binary(env, ctx_size, &ctx)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
if (ctx_init(outp) != 1)
- goto err;
+ return EXCP_ERROR(env, "Can't init ctx");
return enif_make_tuple2(env, argv[0], ctx);
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- return atom_notsup;
-
- err:
- return atom_notsup;
}
ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -361,23 +320,21 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
size_t ctx_size = 0;
update_fun ctx_update = 0;
- ASSERT(argc == 2);
-
if (!enif_get_tuple(env, argv[0], &arity, &tuple))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (arity != 2)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((digp = get_digest_type(tuple[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+ if (digp->md.p == NULL)
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (!enif_inspect_binary(env, tuple[1], &ctx))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+
if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
- goto bad_arg;
-
- if (digp->md.p == NULL)
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad data");
switch (EVP_MD_type(digp->md.p))
{
@@ -428,32 +385,24 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
break;
#endif
default:
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad state");
}
ASSERT(ctx_size);
ASSERT(ctx_update);
if (ctx.size != ctx_size)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
+
memcpy(ctx_buff, ctx.data, ctx_size);
if (ctx_update(ctx_buff, data.data, data.size) != 1)
- goto err;
+ return EXCP_ERROR(env, "Can't update");
CONSUME_REDS(env, data);
return enif_make_tuple2(env, tuple[0], new_ctx);
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- return atom_notsup;
-
- err:
- return atom_notsup;
}
ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -470,21 +419,19 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
final_fun ctx_final = 0;
unsigned char *outp;
- ASSERT(argc == 1);
-
if (!enif_get_tuple(env, argv[0], &arity, &tuple))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (arity != 2)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((digp = get_digest_type(tuple[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
- if (!enif_inspect_binary(env, tuple[1], &ctx))
- goto bad_arg;
-
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((md = digp->md.p) == NULL)
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+
+ if (!enif_inspect_binary(env, tuple[1], &ctx))
+ return EXCP_BADARG_N(env, 0, "Bad data");
switch (EVP_MD_type(md))
{
@@ -535,33 +482,24 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
break;
#endif
default:
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad state");
}
ASSERT(ctx_size);
ASSERT(ctx_final);
if (ctx.size != ctx_size)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((new_ctx = enif_alloc(ctx_size)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate");
memcpy(new_ctx, ctx.data, ctx_size);
if ((outp = enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret)) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Can't allocate binary"));
if (ctx_final(outp, new_ctx) != 1)
- goto err;
-
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- err:
- ret = atom_notsup;
+ assign_goto(ret, done, EXCP_ERROR(env, "Can't do final"));
done:
if (new_ctx)
diff --git a/lib/crypto/c_src/hash_equals.c b/lib/crypto/c_src/hash_equals.c
new file mode 100644
index 0000000000..85f54b14eb
--- /dev/null
+++ b/lib/crypto/c_src/hash_equals.c
@@ -0,0 +1,51 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+
+ */
+
+#include "common.h"
+#include "hash_equals.h"
+
+ERL_NIF_TERM hash_equals_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+#ifdef HAVE_OPENSSL_CRYPTO_MEMCMP
+ ErlNifBinary s1, s2;
+
+ ASSERT(argc == 2);
+
+ if (!enif_inspect_binary(env, argv[0], &s1))
+ goto bad_arg;
+ if (!enif_inspect_binary(env, argv[1], &s2))
+ goto bad_arg;
+
+ if (s1.size != s2.size)
+ goto err;
+
+ if (CRYPTO_memcmp(s1.data, s2.data, s1.size) == 0)
+ return enif_make_atom(env, "true");
+
+ return enif_make_atom(env, "false");
+
+ bad_arg:
+ err:
+ return enif_make_badarg(env);
+#else
+ return EXCP_NOTSUP(env, "Unsupported CRYPTO_memcmp");
+#endif
+}
diff --git a/erts/emulator/beam/erl_sock.h b/lib/crypto/c_src/hash_equals.h
index 3429a52d7e..966862c828 100644
--- a/erts/emulator/beam/erl_sock.h
+++ b/lib/crypto/c_src/hash_equals.h
@@ -1,8 +1,8 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2016. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -14,32 +14,15 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *
+ *
* %CopyrightEnd%
*/
-/*
- * A *very* limited socket interface exported by inet_drv.c.
- * Used by the erl_mtrace.c.
- */
-
-#ifndef ERL_SOCK_H_
-#define ERL_SOCK_H_
-
-#ifdef __WIN32__
-#include <winsock2.h>
-typedef SOCKET erts_sock_t;
-#else
-typedef int erts_sock_t;
-#endif
+#ifndef E_HASH_EQUALS_H__
+#define E_HASH_EQUALS_H__ 1
-#define ERTS_SOCK_INVALID_SOCKET -1
+#include "common.h"
-erts_sock_t erts_sock_open(void);
-void erts_sock_close(erts_sock_t);
-int erts_sock_connect(erts_sock_t, byte *, int, Uint16);
-Sint erts_sock_send(erts_sock_t, const void *, Sint);
-int erts_sock_gethostname(char *, int);
-int erts_sock_errno(void);
+ERL_NIF_TERM hash_equals_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-#endif
+#endif /* E_HASH_EQUALS_H__ */
diff --git a/lib/crypto/c_src/mac.c b/lib/crypto/c_src/mac.c
index bd76fa209a..4223f0567f 100644
--- a/lib/crypto/c_src/mac.c
+++ b/lib/crypto/c_src/mac.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -196,12 +196,20 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ErlNifBinary key_bin, text;
int ret_bin_alloc = 0;
ERL_NIF_TERM return_term;
- const EVP_MD *md = NULL;
ErlNifBinary ret_bin;
-#ifdef HAS_EVP_PKEY_CTX
+#if defined(HAS_3_0_API)
+ const char *name;
+ const char *subalg;
+ unsigned char *out = NULL;
+ size_t outlen;
+#else
+ /* Old style */
+ const EVP_MD *md = NULL;
+# ifdef HAS_EVP_PKEY_CTX
size_t size;
EVP_PKEY *pkey = NULL;
EVP_MD_CTX *mctx = NULL;
+# endif
#endif
/*---------------------------------
@@ -255,32 +263,38 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
return_term = EXCP_BADARG_N(env, 1, "Bad digest algorithm for HMAC");
goto err;
}
- if (digp->md.p == NULL)
+ if (DIGEST_FORBIDDEN_IN_FIPS(digp))
{
- return_term = EXCP_NOTSUP_N(env, 1, "Unsupported digest algorithm");
+ return_term = EXCP_NOTSUP_N(env, 1, "Digest algorithm for HMAC forbidden in FIPS");
goto err;
}
- if (DIGEST_FORBIDDEN_IN_FIPS(digp))
+
+#if defined(HAS_3_0_API)
+ name = "HMAC";
+ subalg = digp->str_v3;
+#else
+ /* Old style */
+ if (digp->md.p == NULL)
{
- return_term = EXCP_NOTSUP_N(env, 1, "Digest algorithm for HMAC forbidden in FIPS");
+ return_term = EXCP_NOTSUP_N(env, 1, "Unsupported digest algorithm");
goto err;
}
md = digp->md.p;
-
-#if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_HMAC)
-# ifdef HAVE_PKEY_new_raw_private_key
+# if defined(HAS_EVP_PKEY_CTX) && (! DISABLE_EVP_HMAC)
+# ifdef HAVE_PKEY_new_raw_private_key
/* Preferred for new applications according to EVP_PKEY_new_mac_key(3) */
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, /*engine*/ NULL, key_bin.data, key_bin.size);
-# else
+# else
/* Available in older versions */
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, /*engine*/ NULL, key_bin.data, key_bin.size);
-# endif
+# endif
-#else
+# else
if (!hmac_low_level(env, md, key_bin, text, &ret_bin, &ret_bin_alloc, &return_term))
goto err;
else
goto success;
+# endif
#endif
}
break;
@@ -315,13 +329,19 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto err;
}
-# ifdef HAVE_EVP_PKEY_new_CMAC_key
- pkey = EVP_PKEY_new_CMAC_key(/*engine*/ NULL, key_bin.data, key_bin.size, cipherp->cipher.p);
+# if defined(HAS_3_0_API)
+ name = "CMAC";
+ subalg = cipherp->str_v3;
# else
+ /* Old style */
+# ifdef HAVE_EVP_PKEY_new_CMAC_key
+ pkey = EVP_PKEY_new_CMAC_key(/*engine*/ NULL, key_bin.data, key_bin.size, cipherp->cipher.p);
+# else
if (!cmac_low_level(env, key_bin, cipherp->cipher.p, text, &ret_bin, &ret_bin_alloc, &return_term))
goto err;
else
goto success;
+# endif
# endif
}
break;
@@ -333,26 +353,49 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
************/
#ifdef HAVE_POLY1305
case POLY1305_mac:
+# if defined(HAS_3_0_API)
+ name = "POLY1305";
+ subalg = NULL;
+# else
+ /* Old style */
/* poly1305 implies that EVP_PKEY_new_raw_private_key exists */
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, /*engine*/ NULL, key_bin.data, key_bin.size);
+# endif
break;
#endif
-
/***************
* Unknown MAC *
***************/
case NO_mac:
default:
- /* We know that this mac is supported with some version(s) of cryptolib */
+ /* We know that this mac is supported with some version(s) of cryptolib, but not here */
return_term = EXCP_NOTSUP_N(env, 1, "Unsupported mac algorithm");
goto err;
}
+#if defined(HAS_3_0_API)
+ /*-----------------------------------------
+ Common computations when we have 3.0 API
+ */
+
+ if (!(out = EVP_Q_mac(NULL, name, NULL,
+ subalg, NULL,
+ key_bin.data, key_bin.size,
+ text.data, text.size,
+ NULL, 0, &outlen)))
+ assign_goto(return_term, err, EXCP_ERROR(env, "Couldn't get mac"));
+
+ if (!enif_alloc_binary(outlen, &ret_bin))
+ assign_goto(return_term, err, EXCP_ERROR(env, "Alloc binary"));
+ ret_bin_alloc = 1;
+
+ memcpy(ret_bin.data, out, outlen);
+#else
/*-----------------------------------------
Common computations when we have EVP_PKEY
*/
-#ifdef HAS_EVP_PKEY_CTX
+# ifdef HAS_EVP_PKEY_CTX
if (!pkey)
{
return_term = EXCP_ERROR(env, "EVP_PKEY_key creation");
@@ -371,13 +414,13 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto err;
}
-# ifdef HAVE_DigestSign_as_single_op
+# ifdef HAVE_DigestSign_as_single_op
if (EVP_DigestSign(mctx, NULL, &size, text.data, text.size) != 1)
{
return_term = EXCP_ERROR(env, "Can't get sign size");
goto err;
}
-# else
+# else
if (EVP_DigestSignUpdate(mctx, text.data, text.size) != 1)
{
return_term = EXCP_ERROR(env, "EVP_DigestSignUpdate");
@@ -389,7 +432,7 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
return_term = EXCP_ERROR(env, "Can't get sign size");
goto err;
}
-# endif
+# endif
if (!enif_alloc_binary(size, &ret_bin))
{
@@ -398,11 +441,11 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
ret_bin_alloc = 1;
-# ifdef HAVE_DigestSign_as_single_op
+# ifdef HAVE_DigestSign_as_single_op
if (EVP_DigestSign(mctx, ret_bin.data, &size, text.data, text.size) != 1)
-# else
+# else
if (EVP_DigestSignFinal(mctx, ret_bin.data, &size) != 1)
-# endif
+# endif
{
return_term = EXCP_ERROR(env, "Signing");
goto err;
@@ -411,25 +454,30 @@ ERL_NIF_TERM mac_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto success; /* The label "success:" could be left without any "goto success"
in some combination of flags. This prevents a compiler warning
*/
-#endif /* ifdef HAS_EVP_PKEY_CTX */
-
+# endif /* ifdef HAS_EVP_PKEY_CTX */
+ success:
+#endif
/****************************
Exit when we got a signature
*****************************/
- success:
CONSUME_REDS(env, text);
return_term = enif_make_binary(env, &ret_bin);
ret_bin_alloc = 0;
err:
-
-#ifdef HAS_EVP_PKEY_CTX
+#if defined(HAS_3_0_API)
+ if (out)
+ OPENSSL_free(out);
+#else
+ /* Old style */
+# ifdef HAS_EVP_PKEY_CTX
if (pkey)
EVP_PKEY_free(pkey);
if (mctx)
EVP_MD_CTX_free(mctx);
+# endif
#endif
if (ret_bin_alloc)
@@ -449,7 +497,11 @@ int init_mac_ctx(ErlNifEnv *env);
struct mac_context
{
+#if defined(HAS_3_0_API)
+ EVP_MAC_CTX *ctx;
+#else
EVP_MD_CTX *ctx;
+#endif
};
static ErlNifResourceType* mac_context_rtype;
@@ -478,7 +530,11 @@ static void mac_context_dtor(ErlNifEnv* env, struct mac_context *obj)
return;
if (obj->ctx)
+#if defined(HAS_3_0_API)
+ EVP_MAC_CTX_free(obj->ctx);
+#else
EVP_MD_CTX_free(obj->ctx);
+#endif
}
/*******************************************************************
@@ -489,13 +545,32 @@ static void mac_context_dtor(ErlNifEnv* env, struct mac_context *obj)
ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (MacType, SubType, Key) */
-#ifdef HAS_EVP_PKEY_CTX
+
+#if ! defined(HAS_EVP_PKEY_CTX) && ! defined(HAS_3_0_API)
+ /* Only realy low-level available */
+ if (argv[0] != atom_hmac)
+ return EXCP_NOTSUP_N(env, 0, "Unsupported mac algorithm");
+
+ return hmac_init_nif(env, argc, argv);
+
+#else
+ /* EVP_PKEY_CTX is available or even the 3.0 API */
struct mac_context *obj = NULL;
struct mac_type_t *macp;
ErlNifBinary key_bin;
ERL_NIF_TERM return_term;
+# if defined(HAS_3_0_API)
+ const char *name = NULL;
+ const char *digest = NULL;
+ const char *cipher = NULL;
+ EVP_MAC *mac = NULL;
+ OSSL_PARAM params[3];
+ size_t params_n = 0;
+# else
+ /* EVP_PKEY_CTX is available */
const EVP_MD *md = NULL;
EVP_PKEY *pkey = NULL;
+# endif
/*---------------------------------
Get common indata and validate it
@@ -542,25 +617,30 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
return_term = EXCP_BADARG_N(env, 1, "Bad digest algorithm for HMAC");
goto err;
}
- if (digp->md.p == NULL)
+ if (DIGEST_FORBIDDEN_IN_FIPS(digp))
{
- return_term = EXCP_NOTSUP_N(env, 1, "Unsupported digest algorithm");
+ return_term = EXCP_NOTSUP_N(env, 1, "Digest algorithm for HMAC forbidden in FIPS");
goto err;
}
- if (DIGEST_FORBIDDEN_IN_FIPS(digp))
+# if defined(HAS_3_0_API)
+ name = "HMAC";
+ digest = digp->str_v3;
+# else
+ if (digp->md.p == NULL)
{
- return_term = EXCP_NOTSUP_N(env, 1, "Digest algorithm for HMAC forbidden in FIPS");
+ return_term = EXCP_NOTSUP_N(env, 1, "Unsupported digest algorithm");
goto err;
}
md = digp->md.p;
-# ifdef HAVE_PKEY_new_raw_private_key
+# ifdef HAVE_PKEY_new_raw_private_key
/* Preferred for new applications according to EVP_PKEY_new_mac_key(3) */
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, /*engine*/ NULL, key_bin.data, key_bin.size);
-# else
+# else
/* Available in older versions */
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, /*engine*/ NULL, key_bin.data, key_bin.size);
-# endif
+# endif
+#endif
}
break;
@@ -568,7 +648,7 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/********
* CMAC *
********/
-#if defined(HAVE_CMAC) && defined(HAVE_EVP_PKEY_new_CMAC_key)
+# if defined(HAVE_CMAC) && defined(HAVE_EVP_PKEY_new_CMAC_key)
case CMAC_mac:
{
const struct cipher_type_t *cipherp;
@@ -594,21 +674,32 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto err;
}
+# if defined(HAS_3_0_API)
+ name = "CMAC";
+ cipher = cipherp->str_v3;
+# else
+ /* Old style */
pkey = EVP_PKEY_new_CMAC_key(/*engine*/ NULL, key_bin.data, key_bin.size, cipherp->cipher.p);
+# endif
}
break;
-#endif /* HAVE_CMAC && HAVE_EVP_PKEY_new_CMAC_key */
+# endif /* HAVE_CMAC && HAVE_EVP_PKEY_new_CMAC_key */
/************
* POLY1305 *
************/
-#ifdef HAVE_POLY1305
+# ifdef HAVE_POLY1305
case POLY1305_mac:
+# if defined(HAS_3_0_API)
+ name = "POLY1305";
+# else
+ /* Old style */
/* poly1305 implies that EVP_PKEY_new_raw_private_key exists */
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, /*engine*/ NULL, key_bin.data, key_bin.size);
+# endif
break;
-#endif
+# endif
/***************
@@ -621,8 +712,34 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto err;
}
+# if defined(HAS_3_0_API)
/*-----------------------------------------
- Common computations
+ Common computations when we have 3.0 API
+ */
+ if (!(mac = EVP_MAC_fetch(NULL, name, NULL)))
+ assign_goto(return_term, err, EXCP_NOTSUP_N(env, 0, "Unsupported mac algorithm"));
+
+ if (cipher != NULL)
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string("cipher", (char*)cipher, 0);
+ if (digest != NULL)
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string("digest", (char*)digest, 0);
+ params[params_n] = OSSL_PARAM_construct_end();
+
+ if ((obj = enif_alloc_resource(mac_context_rtype, sizeof(struct mac_context))) == NULL)
+ assign_goto(return_term, err, EXCP_ERROR(env, "Can't allocate mac_context_rtype"));
+
+ if (!(obj->ctx = EVP_MAC_CTX_new(mac)))
+ assign_goto(return_term, err, EXCP_ERROR(env, "Can't create EVP_MAC_CTX"));
+
+ if (!EVP_MAC_init(obj->ctx, key_bin.data, key_bin.size, params))
+ assign_goto(return_term, err, EXCP_ERROR(env, "Can't initialize EVP_MAC_CTX"));
+
+
+# else
+ /*-----------------------------------------
+ Common computations when we have EVP_PKEY_CTX but not 3.0 API
*/
if (!pkey)
{
@@ -648,6 +765,8 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
goto err;
}
+# endif
+
return_term = enif_make_resource(env, obj);
err:
@@ -655,16 +774,13 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if (obj)
enif_release_resource(obj);
+# if ! defined(HAS_3_0_API)
if (pkey)
EVP_PKEY_free(pkey);
+# endif
return return_term;
-#else
- if (argv[0] != atom_hmac)
- return EXCP_NOTSUP_N(env, 0, "Unsupported mac algorithm");
-
- return hmac_init_nif(env, argc, argv);
#endif
}
@@ -693,7 +809,7 @@ ERL_NIF_TERM mac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ERL_NIF_TERM mac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Ref, Text) */
-#ifdef HAS_EVP_PKEY_CTX
+#if defined(HAS_EVP_PKEY_CTX) || defined(HAS_3_0_API)
struct mac_context *obj = NULL;
ErlNifBinary text;
@@ -703,8 +819,12 @@ ERL_NIF_TERM mac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if (!enif_inspect_iolist_as_binary(env, argv[1], &text))
return EXCP_BADARG_N(env, 1, "Bad text");
+# if defined(HAS_3_0_API)
+ if (!EVP_MAC_update(obj->ctx, text.data, text.size))
+# else
if (EVP_DigestSignUpdate(obj->ctx, text.data, text.size) != 1)
- return EXCP_ERROR(env, "EVP_DigestSignUpdate");
+# endif
+ return EXCP_ERROR(env, "mac update");
CONSUME_REDS(env, text);
return argv[0];
@@ -718,7 +838,7 @@ ERL_NIF_TERM mac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ERL_NIF_TERM mac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Ref) */
-#ifdef HAS_EVP_PKEY_CTX
+#if defined(HAS_EVP_PKEY_CTX) || defined(HAS_3_0_API)
struct mac_context *obj;
size_t size;
ErlNifBinary ret_bin;
@@ -726,13 +846,21 @@ ERL_NIF_TERM mac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if (!enif_get_resource(env, argv[0], (ErlNifResourceType*)mac_context_rtype, (void**)&obj))
return EXCP_BADARG_N(env, 0, "Bad ref");
+# if defined(HAS_3_0_API)
+ if (!EVP_MAC_final(obj->ctx, NULL, &size, 0))
+# else
if (EVP_DigestSignFinal(obj->ctx, NULL, &size) != 1)
+# endif
return EXCP_ERROR(env, "Can't get sign size");
if (!enif_alloc_binary(size, &ret_bin))
return EXCP_ERROR(env, "Alloc binary");
+# if defined(HAS_3_0_API)
+ if (!EVP_MAC_final(obj->ctx, ret_bin.data, &size, size))
+# else
if (EVP_DigestSignFinal(obj->ctx, ret_bin.data, &size) != 1)
+#endif
{
enif_release_binary(&ret_bin);
return EXCP_ERROR(env, "Signing");
diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c
index 6f030c6f93..1530ad311c 100644
--- a/lib/crypto/c_src/otp_test_engine.c
+++ b/lib/crypto/c_src/otp_test_engine.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2017-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2017-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@ EVP_PKEY* test_key_load(ENGINE *er, const char *id, UI_METHOD *ui_method, void *
static int test_init(ENGINE *e) {
printf("OTP Test Engine Initializatzion!\r\n");
-
+
#if defined(FAKE_RSA_IMPL)
if (!RSA_meth_set_finish(test_rsa_method, test_rsa_free))
goto err;
@@ -114,6 +114,15 @@ err:
#endif
}
+static int test_finish(ENGINE *e) {
+ printf("OTP Test Engine Finish!\r\n");
+
+ // EVP_cleanup();
+
+ return 111;
+
+}
+
static void add_test_data(unsigned char *md, unsigned int len)
{
unsigned int i;
@@ -244,7 +253,7 @@ static int test_engine_digest_selector(ENGINE *e, const EVP_MD **digest,
else {
goto err;
}
-
+
return 1;
err:
@@ -267,6 +276,8 @@ static int bind_helper(ENGINE * e, const char *id)
goto err;
if (!ENGINE_set_init_function(e, test_init))
goto err;
+ if (!ENGINE_set_finish_function(e, test_finish))
+ goto err;
if (!ENGINE_set_digests(e, &test_engine_digest_selector))
goto err;
/* For testing of key storage in an Engine: */
@@ -315,6 +326,8 @@ EVP_PKEY* test_key_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void
EVP_PKEY *pkey = NULL;
FILE *f = fopen(id, "r");
+ fprintf(stderr, "%s:%d test_key_load(id=%s,priv=%d)\r\n", __FILE__,__LINE__,id, priv);
+
if (!f) {
fprintf(stderr, "%s:%d fopen(%s) failed\r\n", __FILE__,__LINE__,id);
return NULL;
@@ -326,10 +339,10 @@ EVP_PKEY* test_key_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void
: PEM_read_PUBKEY(f, NULL, NULL, NULL);
fclose(f);
-
+
if (!pkey) {
fprintf(stderr, "%s:%d Key read from file %s failed.\r\n", __FILE__,__LINE__,id);
- if (callback_data)
+ if (callback_data)
fprintf(stderr, "Pwd = \"%s\".\r\n", (char *)callback_data);
fprintf(stderr, "Contents of file \"%s\":\r\n",id);
f = fopen(id, "r");
@@ -347,13 +360,13 @@ EVP_PKEY* test_key_load(ENGINE *eng, const char *id, UI_METHOD *ui_method, void
fclose(f);
return NULL;
}
-
+
return pkey;
}
-int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password)
-{
+int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password)
+{
size_t i;
if (size < 0)
@@ -385,10 +398,10 @@ int pem_passwd_cb_fun(char *buf, int size, int rwflag, void *password)
static unsigned char fake_flag[] = {255,3,124,180,35,10,180,151,101,247,62,59,80,122,220,
142,24,180,191,34,51,150,112,27,43,142,195,60,245,213,80,179};
-int test_rsa_sign(int dtype,
+int test_rsa_sign(int dtype,
/* The digest to sign */
const unsigned char *m, unsigned int m_len,
- /* The allocated buffer to fill with the signature */
+ /* The allocated buffer to fill with the signature */
unsigned char *sigret, unsigned int *siglen,
/* The key */
const RSA *rsa)
@@ -424,10 +437,10 @@ int test_rsa_sign(int dtype,
return -1;
}
-int test_rsa_verify(int dtype,
+int test_rsa_verify(int dtype,
/* The digest to verify */
const unsigned char *m, unsigned int m_len,
- /* The signature */
+ /* The signature */
const unsigned char *sigret, unsigned int siglen,
/* The key */
const RSA *rsa)
diff --git a/lib/crypto/c_src/pbkdf2_hmac.c b/lib/crypto/c_src/pbkdf2_hmac.c
index 7eec603d9c..08360ed558 100644
--- a/lib/crypto/c_src/pbkdf2_hmac.c
+++ b/lib/crypto/c_src/pbkdf2_hmac.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,45 +30,41 @@ ERL_NIF_TERM pbkdf2_hmac_nif(ErlNifEnv* env, int argc,
ErlNifUInt64 iter, keylen;
struct digest_type_t* digp = NULL;
- ASSERT(argc == 5);
-
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
if (digp->md.p == NULL)
- goto bad_arg;
- if ((digp->flags & PBKDF2_ELIGIBLE_DIGEST) == 0) {
- goto bad_arg;
- }
+ return EXCP_BADARG_N(env, 0, "md.p is not NULL");
+ if ((digp->flags & PBKDF2_ELIGIBLE_DIGEST) == 0)
+ return EXCP_BADARG_N(env, 0, "Not eligible digest type");
if (!enif_inspect_binary(env, argv[1], &pass))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 1, "Not binary");
+
if (!enif_inspect_binary(env, argv[2], &salt))
- goto bad_arg;
- if (!enif_get_uint64(env, argv[3], &iter))
- goto bad_arg;
- if (!enif_get_uint64(env, argv[4], &keylen))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 2, "Not binary");
+ if (!enif_get_uint64(env, argv[3], &iter))
+ return EXCP_BADARG_N(env, 3, "Not integer");
if (iter < 1)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 3, "Must be > 0");
+
+ if (!enif_get_uint64(env, argv[4], &keylen))
+ return EXCP_BADARG_N(env, 4, "Not integer");
if (keylen < 1)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 4, "Must be > 0");
if (!enif_alloc_binary(keylen, &out))
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
if (!PKCS5_PBKDF2_HMAC((const char *)pass.data, pass.size,
salt.data, salt.size, iter,
digp->md.p,
keylen, out.data)) {
enif_release_binary(&out);
- goto err;
+ return EXCP_ERROR(env, "Low-level call failed");
}
return enif_make_binary(env, &out);
- bad_arg:
- err:
- return enif_make_badarg(env);
#else
return EXCP_NOTSUP(env, "Unsupported CRYPTO_PKCS5_PBKDF2_HMAC");
#endif
diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c
index 70c6d1bbe4..bfdcfe3553 100644
--- a/lib/crypto/c_src/pkey.c
+++ b/lib/crypto/c_src/pkey.c
@@ -27,10 +27,6 @@
#include "engine.h"
#include "rsa.h"
-#define PKEY_BADARG -1
-#define PKEY_NOTSUP 0
-#define PKEY_OK 1
-
typedef struct PKeyCryptOptions {
const EVP_MD *rsa_mgf1_md;
ErlNifBinary rsa_oaep_label;
@@ -46,55 +42,122 @@ typedef struct PKeySignOptions {
} PKeySignOptions;
-static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM type,
- const EVP_MD **md);
-static int get_pkey_sign_digest(ErlNifEnv *env, ERL_NIF_TERM algorithm,
- ERL_NIF_TERM type, ERL_NIF_TERM data,
+static int check_pkey_algorithm_type(ErlNifEnv *env,
+ int alg_arg_num, ERL_NIF_TERM algorithm,
+ ERL_NIF_TERM *err_return);
+static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm,
+ int type_arg_num, ERL_NIF_TERM type,
+ const EVP_MD **md,
+ ERL_NIF_TERM *err_return);
+static int get_pkey_sign_digest(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int type_arg_num, int data_arg_num,
unsigned char *md_value, const EVP_MD **mdp,
- unsigned char **tbsp, size_t *tbslenp);
-static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options,
- const EVP_MD *md, PKeySignOptions *opt);
-static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, EVP_PKEY **pkey);
-static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key,
- EVP_PKEY **pkey);
-static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options,
- PKeyCryptOptions *opt);
+ unsigned char **tbsp, size_t *tbslenp,
+ ERL_NIF_TERM *err_return);
+static int get_pkey_sign_options(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int options_arg_num,
+ const EVP_MD *md, PKeySignOptions *opt,
+ ERL_NIF_TERM *err_return);
+static int get_pkey_private_key(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int key_arg_num,
+ EVP_PKEY **pkey,
+ ERL_NIF_TERM *err_return);
+static int get_pkey_public_key(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int key_arg_num,
+ EVP_PKEY **pkey,
+ ERL_NIF_TERM *err_return);
+static int get_pkey_crypt_options(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int options_arg_num,
+ PKeyCryptOptions *opt,
+ ERL_NIF_TERM *err_return);
#ifdef HAVE_RSA_SSLV23_PADDING
static size_t size_of_RSA(EVP_PKEY *pkey);
#endif
-static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM type,
- const EVP_MD **md)
+static int check_pkey_algorithm_type(ErlNifEnv *env,
+ int alg_arg_num, ERL_NIF_TERM algorithm,
+ ERL_NIF_TERM *err_return)
+{
+ if (
+#ifndef HAVE_EDDSA
+ (algorithm == atom_eddsa) ||
+#endif
+
+#ifndef HAVE_DSA
+ (algorithm == atom_dss) ||
+#endif
+
+#ifndef HAVE_EC
+ (algorithm == atom_ecdsa) ||
+#endif
+ 0)
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, alg_arg_num, "Unsupported algorithm"));
+
+
+#ifdef HAVE_EDDSA
+ if (FIPS_MODE())
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, alg_arg_num, "Unsupported algorithm in FIPS mode"));
+#endif
+
+ if ((algorithm != atom_rsa) &&
+ (algorithm != atom_dss) &&
+ (algorithm != atom_ecdsa) &&
+ (algorithm != atom_eddsa)
+ )
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, alg_arg_num, "Bad algorithm"));
+
+ return 1;
+
+ err:
+ return 0;
+}
+
+
+static int get_pkey_digest_type(ErlNifEnv *env, ERL_NIF_TERM algorithm,
+ int type_arg_num, ERL_NIF_TERM type,
+ const EVP_MD **md,
+ ERL_NIF_TERM *err_return)
{
struct digest_type_t *digp = NULL;
*md = NULL;
if (type == atom_none && algorithm == atom_rsa)
- return PKEY_OK;
- if (algorithm == atom_eddsa) {
-#ifdef HAVE_EDDSA
- if (!FIPS_MODE()) return PKEY_OK;
-#else
- return PKEY_NOTSUP;
-#endif
- }
+ return 1;
+
+ if (algorithm == atom_eddsa) /* Type was skipped for eddsa in < OTP-25
+ For eddsa the RFC 8032 mandates sha512 in
+ the algorithm */
+ return 1;
+
if ((digp = get_digest_type(type)) == NULL)
- return PKEY_BADARG;
+ assign_goto(*err_return, notsup, EXCP_BADARG_N(env, type_arg_num, "Bad digest type"));
+
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- return PKEY_NOTSUP;
+ assign_goto(*err_return, notsup, EXCP_BADARG_N(env, type_arg_num, "Digest type forbidden in FIPS"));
+
if (digp->md.p == NULL)
- return PKEY_NOTSUP;
+ assign_goto(*err_return, notsup, EXCP_BADARG_N(env, type_arg_num, "Digest type not supported"));
*md = digp->md.p;
- return PKEY_OK;
+ return 1;
+
+ notsup:
+ return 0;
}
-static int get_pkey_sign_digest(ErlNifEnv *env, ERL_NIF_TERM algorithm,
- ERL_NIF_TERM type, ERL_NIF_TERM data,
+static int get_pkey_sign_digest(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int type_arg_num, int data_arg_num,
unsigned char *md_value, const EVP_MD **mdp,
- unsigned char **tbsp, size_t *tbslenp)
+ unsigned char **tbsp, size_t *tbslenp,
+ ERL_NIF_TERM *err_return)
{
- int i, ret;
+ int ret;
const ERL_NIF_TERM *tpl_terms;
int tpl_arity;
ErlNifBinary tbs_bin;
@@ -108,50 +171,55 @@ static int get_pkey_sign_digest(ErlNifEnv *env, ERL_NIF_TERM algorithm,
tbs = *tbsp;
tbslen = *tbslenp;
- if ((i = get_pkey_digest_type(env, algorithm, type, &md)) != PKEY_OK)
- return i;
+ if (!check_pkey_algorithm_type(env, algorithm_arg_num, argv[algorithm_arg_num], err_return))
+ goto err; /* An exception is present in ret */
+
+ if (!get_pkey_digest_type(env, argv[algorithm_arg_num],
+ type_arg_num, argv[type_arg_num],
+ &md, err_return))
+ goto err; /* An exception is present in ret */
- if (enif_get_tuple(env, data, &tpl_arity, &tpl_terms)) {
+ if (enif_get_tuple(env, argv[data_arg_num], &tpl_arity, &tpl_terms)) {
if (tpl_arity != 2)
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Bad list"));
if (tpl_terms[0] != atom_digest)
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Expected 'digest' as head"));
if (!enif_inspect_iolist_as_binary(env, tpl_terms[1], &tbs_bin))
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Bad 2nd element in list"));
if (tbs_bin.size > INT_MAX)
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Too large binary"));
if (md != NULL) {
if ((int)tbs_bin.size != EVP_MD_size(md))
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Bad binary size for the algorithm"));
}
/* We have a digest (= hashed text) in tbs_bin */
tbs = tbs_bin.data;
tbslen = tbs_bin.size;
} else if (md == NULL) {
- if (!enif_inspect_iolist_as_binary(env, data, &tbs_bin))
- goto bad_arg;
+ if (!enif_inspect_iolist_as_binary(env, argv[data_arg_num], &tbs_bin))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Expected a binary or a list"));
/* md == NULL, that is no hashing because DigestType argument was atom_none */
tbs = tbs_bin.data;
tbslen = tbs_bin.size;
} else {
- if (!enif_inspect_iolist_as_binary(env, data, &tbs_bin))
- goto bad_arg;
+ if (!enif_inspect_iolist_as_binary(env, argv[data_arg_num], &tbs_bin))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, data_arg_num, "Expected a binary or a list"));
/* We have the cleartext in tbs_bin and the hash algo info in md */
tbs = md_value;
if ((mdctx = EVP_MD_CTX_create()) == NULL)
- goto err;
+ assign_goto(*err_return, err, EXCP_ERROR(env, "Can't create MD_CTX"));
/* Looks well, now hash the plain text into a digest according to md */
if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
- goto err;
+ assign_goto(*err_return, err, EXCP_ERROR(env, "Can't create EVP_DigestInit_ex"));
if (EVP_DigestUpdate(mdctx, tbs_bin.data, tbs_bin.size) != 1)
- goto err;
+ assign_goto(*err_return, err, EXCP_ERROR(env, "Can't create EVP_DigestUpdate"));
if (EVP_DigestFinal_ex(mdctx, tbs, &tbsleni) != 1)
- goto err;
+ assign_goto(*err_return, err, EXCP_ERROR(env, "Can't create EVP_DigestFinal_ex"));
tbslen = (size_t)tbsleni;
}
@@ -160,32 +228,33 @@ static int get_pkey_sign_digest(ErlNifEnv *env, ERL_NIF_TERM algorithm,
*tbsp = tbs;
*tbslenp = tbslen;
- ret = PKEY_OK;
+ ret = 1;
goto done;
- bad_arg:
err:
- ret = PKEY_BADARG;
-
+ ret = 0;
done:
if (mdctx)
EVP_MD_CTX_destroy(mdctx);
return ret;
}
-static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options,
- const EVP_MD *md, PKeySignOptions *opt)
+static int get_pkey_sign_options(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int options_arg_num,
+ const EVP_MD *md, PKeySignOptions *opt,
+ ERL_NIF_TERM *err_return)
{
ERL_NIF_TERM head, tail;
const ERL_NIF_TERM *tpl_terms;
int tpl_arity;
const EVP_MD *opt_md;
- if (!enif_is_list(env, options))
- goto bad_arg;
+ if (!enif_is_list(env, argv[options_arg_num]))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Expected a list"));
/* defaults */
- if (algorithm == atom_rsa) {
+ if (argv[algorithm_arg_num] == atom_rsa) {
opt->rsa_mgf1_md = NULL;
opt->rsa_padding = RSA_PKCS1_PADDING;
opt->rsa_pss_saltlen = -2;
@@ -195,26 +264,27 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF
opt->rsa_pss_saltlen = 0;
}
- if (enif_is_empty_list(env, options))
- return PKEY_OK;
+ if (enif_is_empty_list(env, argv[options_arg_num]))
+ return 1;
- if (algorithm != atom_rsa)
- goto bad_arg;
+ if (argv[algorithm_arg_num] != atom_rsa)
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Only RSA supports Options"));
- tail = options;
+ tail = argv[options_arg_num];
while (enif_get_list_cell(env, tail, &head, &tail)) {
- if (!enif_get_tuple(env, head, &tpl_arity, &tpl_terms))
- goto bad_arg;
- if (tpl_arity != 2)
- goto bad_arg;
-
- if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) {
- int result;
-
- result = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
- if (result != PKEY_OK)
- return result;
-
+ if (!enif_get_tuple(env, head, &tpl_arity, &tpl_terms) ||
+ (tpl_arity != 2))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Expects only two-tuples in the list"));
+
+ if (tpl_terms[0] == atom_rsa_mgf1_md) {
+ if (!enif_is_atom(env, tpl_terms[1]))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Atom expected as argument to option rsa_mgf1_md"));
+
+ if (!get_pkey_digest_type(env, argv[algorithm_arg_num],
+ options_arg_num, tpl_terms[1],
+ &opt_md, err_return))
+ goto err; /* An exception is present in ret */
+
opt->rsa_mgf1_md = opt_md;
} else if (tpl_terms[0] == atom_rsa_padding) {
@@ -227,7 +297,7 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF
if (opt->rsa_mgf1_md == NULL)
opt->rsa_mgf1_md = md;
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, options_arg_num, "rsa_pkcs1_pss_padding not supported"));
#endif
} else if (tpl_terms[1] == atom_rsa_x931_padding) {
@@ -237,172 +307,163 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF
opt->rsa_padding = RSA_NO_PADDING;
} else {
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Bad value in option rsa_padding"));
}
} else if (tpl_terms[0] == atom_rsa_pss_saltlen) {
- if (!enif_get_int(env, tpl_terms[1], &(opt->rsa_pss_saltlen)))
- goto bad_arg;
- if (opt->rsa_pss_saltlen < -2)
- goto bad_arg;
+ if (!enif_get_int(env, tpl_terms[1], &(opt->rsa_pss_saltlen)) ||
+ (opt->rsa_pss_saltlen < -2) )
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Bad value in option rsa_pss_saltlen"));
} else {
- goto bad_arg;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Bad option"));
}
}
- return PKEY_OK;
+ return 1;
- bad_arg:
- return PKEY_BADARG;
+ err:
+ return 0;
}
-static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key, EVP_PKEY **pkey)
+static int get_pkey_private_key(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int key_arg_num,
+ EVP_PKEY **pkey,
+ ERL_NIF_TERM *err_return)
{
- EVP_PKEY *result = NULL;
char *id = NULL;
char *password = NULL;
+ int ret;
- if (enif_is_map(env, key)) {
+ if (enif_is_map(env, argv[key_arg_num])) {
#ifdef HAS_ENGINE_SUPPORT
/* Use key stored in engine */
ENGINE *e;
- if (!get_engine_and_key_id(env, key, &id, &e))
- goto err;
-
- password = get_key_password(env, key);
- result = ENGINE_load_private_key(e, id, NULL, password);
+ if (!get_engine_and_key_id(env, argv[key_arg_num], &id, &e))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get engine and/or key id"));
+ password = get_key_password(env, argv[key_arg_num]);
+ *pkey = ENGINE_load_private_key(e, id, NULL, password);
+ if (!*pkey)
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get private key from engine"));
#else
- return PKEY_BADARG;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "No engine support"));
#endif
- } else if (algorithm == atom_rsa) {
- if ((result = EVP_PKEY_new()) == NULL)
- goto err;
- if (!get_rsa_private_key(env, key, &result))
- goto err;
+ } else if (argv[algorithm_arg_num] == atom_rsa) {
+ if (!get_rsa_private_key(env, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get RSA private key"));
- } else if (algorithm == atom_ecdsa) {
+ } else if (argv[algorithm_arg_num] == atom_ecdsa) {
#if defined(HAVE_EC)
- if ((result = EVP_PKEY_new()) == NULL)
- goto err;
- if (!get_ec_private_key(env, key, &result))
- goto err;
+ if (!get_ec_private_key(env, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get ECDSA private key"));
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "ECDSA not supported"));
#endif
- } else if (algorithm == atom_eddsa) {
+ } else if (argv[algorithm_arg_num] == atom_eddsa) {
#ifdef HAVE_EDDSA
- if (FIPS_MODE())
- return PKEY_NOTSUP;
- if (!get_eddsa_key(env, 0, key, &result))
- goto err;
+ if (!FIPS_MODE()) {
+ if (!get_eddsa_key(env, 0, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get EDDSA private key"));
+ } else
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "EDDSA not supported in FIPS mode"));
#else
- return PKEY_NOTSUP;
-#endif
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "EDDSA not supported"));
+#endif
- } else if (algorithm == atom_dss) {
+ } else if (argv[algorithm_arg_num] == atom_dss) {
#ifdef HAVE_DSA
- if ((result = EVP_PKEY_new()) == NULL)
- goto err;
- if (!get_dss_private_key(env, key, &result))
- goto err;
+ if (!get_dss_private_key(env, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get DSA private key"));
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "DSA not supported"));
#endif
} else
- return PKEY_BADARG;
-
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, algorithm_arg_num, "Bad algorithm"));
- free_and_return:
+ ret = 1;
+ done:
if (password)
enif_free(password);
if (id)
enif_free(id);
- if (result == NULL) {
- return PKEY_BADARG;
- } else {
- *pkey = result;
- return PKEY_OK;
- }
+ return ret;
err:
- if (result)
- EVP_PKEY_free(result);
- result = NULL;
- goto free_and_return;
+ if (*pkey)
+ EVP_PKEY_free(*pkey);
+ *pkey = NULL;
+ ret = 0;
+ goto done;
}
-static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM key,
- EVP_PKEY **pkey)
+static int get_pkey_public_key(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int key_arg_num,
+ EVP_PKEY **pkey,
+ ERL_NIF_TERM *err_return)
{
- EVP_PKEY *result = NULL;
char *id = NULL;
char *password = NULL;
+ int ret;
- if (enif_is_map(env, key)) {
+ if (enif_is_map(env, argv[key_arg_num])) {
#ifdef HAS_ENGINE_SUPPORT
/* Use key stored in engine */
ENGINE *e;
- if (!get_engine_and_key_id(env, key, &id, &e))
- goto err;
-
- password = get_key_password(env, key);
- result = ENGINE_load_public_key(e, id, NULL, password);
+ if (!get_engine_and_key_id(env, argv[key_arg_num], &id, &e))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get engine and/or key id"));
+ password = get_key_password(env, argv[key_arg_num]);
+ *pkey = ENGINE_load_public_key(e, id, NULL, password);
+ if (!pkey)
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get public key from engine"));
#else
- return PKEY_BADARG;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "No engine support"));
#endif
- } else if (algorithm == atom_rsa) {
- if ((result = EVP_PKEY_new()) == NULL)
- goto err;
- if (!get_rsa_public_key(env, key, &result))
- goto err;
- } else if (algorithm == atom_ecdsa) {
+ } else if (argv[algorithm_arg_num] == atom_rsa) {
+ if (!get_rsa_public_key(env, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get RSA public key"));
+
+ } else if (argv[algorithm_arg_num] == atom_ecdsa) {
#if defined(HAVE_EC)
- if ((result = EVP_PKEY_new()) == NULL)
- goto err;
- if (!get_ec_public_key(env, key, &result))
- goto err;
+ if (!get_ec_public_key(env, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get ECDSA public key"));
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "ECDSA not supported"));
#endif
- } else if (algorithm == atom_eddsa) {
+
+ } else if (argv[algorithm_arg_num] == atom_eddsa) {
#ifdef HAVE_EDDSA
if (!FIPS_MODE()) {
- if (!get_eddsa_key(env, 1, key, &result))
- goto err;
- }
+ if (!get_eddsa_key(env, 1, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get EDDSA public key"));
+ } else
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "EDDSA not supported in FIPS mode"));
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "EDDSA not supported"));
#endif
- } else if (algorithm == atom_dss) {
+
+ } else if (argv[algorithm_arg_num] == atom_dss) {
#ifdef HAVE_DSA
- if ((result = EVP_PKEY_new()) == NULL)
- goto err;
- if (!get_dss_public_key(env, key, &result))
- goto err;
+ if (!get_dss_public_key(env, argv[key_arg_num], pkey))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, key_arg_num, "Couldn't get DSA public key"));
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, algorithm_arg_num, "DSA not supported"));
#endif
- } else {
- return PKEY_BADARG;
- }
-
- goto done;
+ } else
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, algorithm_arg_num, "Bad algorithm"));
- err:
- if (result)
- EVP_PKEY_free(result);
- result = NULL;
+ ret = 1;
done:
if (password)
@@ -410,440 +471,431 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T
if (id)
enif_free(id);
- if (result == NULL) {
- return PKEY_BADARG;
- } else {
- *pkey = result;
- return PKEY_OK;
- }
+ return ret;
+
+ err:
+ if (*pkey)
+ EVP_PKEY_free(*pkey);
+ *pkey = NULL;
+ ret = 0;
+ goto done;
}
ERL_NIF_TERM pkey_sign_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{/* (Algorithm, Type, Data|{digest,Digest}, Key|#{}, Options) */
- int i;
int sig_bin_alloc = 0;
- ERL_NIF_TERM ret;
+ ERL_NIF_TERM ret = atom_undefined;
const EVP_MD *md = NULL;
unsigned char md_value[EVP_MAX_MD_SIZE];
EVP_PKEY *pkey = NULL;
-#ifdef HAVE_EDDSA
- EVP_MD_CTX *mdctx = NULL;
-#endif
#ifdef HAS_EVP_PKEY_CTX
EVP_PKEY_CTX *ctx = NULL;
size_t siglen;
#else
int len;
unsigned int siglen;
+ RSA *rsa = NULL;
+# ifdef HAVE_DSA
+ DSA *dsa = NULL;
+# endif
+# if defined(HAVE_EC)
+ EC_KEY *ec = NULL;
+# endif
#endif
PKeySignOptions sig_opt;
ErlNifBinary sig_bin; /* signature */
unsigned char *tbs = NULL; /* data to be signed */
size_t tbslen = 0;
- RSA *rsa = NULL;
-#ifdef HAVE_DSA
- DSA *dsa = NULL;
-#endif
-#if defined(HAVE_EC)
- EC_KEY *ec = NULL;
-#endif
-/*char buf[1024];
-enif_get_atom(env,argv[0],buf,1024,ERL_NIF_LATIN1); printf("algo=%s ",buf);
-enif_get_atom(env,argv[1],buf,1024,ERL_NIF_LATIN1); printf("hash=%s ",buf);
-*/
#ifndef HAS_ENGINE_SUPPORT
if (enif_is_map(env, argv[3]))
- return atom_notsup;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "No engine support"));
#endif
+ if (!get_pkey_sign_digest(env, argv, 0, 1, 2, md_value, &md, &tbs, &tbslen, &ret))
+ goto err; /* An exception is present in ret */
- i = get_pkey_sign_digest(env, argv[0], argv[1], argv[2], md_value, &md, &tbs, &tbslen);
- switch (i) {
- case PKEY_OK:
- break;
- case PKEY_NOTSUP:
- goto notsup;
- default:
- goto bad_arg;
- }
-
- i = get_pkey_sign_options(env, argv[0], argv[4], md, &sig_opt);
- switch (i) {
- case PKEY_OK:
- break;
- case PKEY_NOTSUP:
- goto notsup;
- default:
- goto bad_arg;
- }
-
- if (get_pkey_private_key(env, argv[0], argv[3], &pkey) != PKEY_OK)
- goto bad_arg;
+ if (!get_pkey_sign_options(env, argv, 0, 4, md, &sig_opt, &ret))
+ goto err; /* An exception is present in ret */
#ifdef HAS_EVP_PKEY_CTX
- if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
- goto err;
-
- if (argv[0] != atom_eddsa) {
- if (EVP_PKEY_sign_init(ctx) != 1)
- goto err;
- if (md != NULL) {
- if (EVP_PKEY_CTX_set_signature_md(ctx, md) != 1)
- goto err;
+ { /* EVP_MD_CTX */
+ if (!get_pkey_private_key(env, argv, 0, 3, &pkey, &ret))
+ goto err; /* An exception is present in ret */
+
+ if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate new EVP_PKEY_CTX"));
+
+ if (argv[0] != atom_eddsa) {
+ if (EVP_PKEY_sign_init(ctx) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_sign_init"));
+ if (md != NULL) {
+ if (EVP_PKEY_CTX_set_signature_md(ctx, md) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_signature_md"));
+ }
}
- }
- if (argv[0] == atom_rsa) {
- if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) != 1)
- goto err;
+ if (argv[0] == atom_rsa) {
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_rsa_padding"));
# ifdef HAVE_RSA_PKCS1_PSS_PADDING
- if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
- if (sig_opt.rsa_mgf1_md != NULL) {
+ if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
+ if (sig_opt.rsa_mgf1_md != NULL) {
# ifdef HAVE_RSA_MGF1_MD
- if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) != 1)
- goto err;
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_rsa_mgf1_md"));
# else
- goto notsup;
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 4, "rsa_mgf1_md unavailable with this cryptolib"));
# endif
+ }
+ if (sig_opt.rsa_pss_saltlen > -2) {
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) != 1)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 4, "Bad rsa_pss_saltlen"));
+ }
}
- if (sig_opt.rsa_pss_saltlen > -2) {
- if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) != 1)
- goto err;
- }
- }
# endif
- }
+ }
- if (argv[0] == atom_eddsa) {
+ if (argv[0] == atom_eddsa) {
# ifdef HAVE_EDDSA
- if (!FIPS_MODE()) {
- if ((mdctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ if (!FIPS_MODE()) {
+ EVP_MD_CTX *mdctx = NULL;
+ if ((mdctx = EVP_MD_CTX_new()) == NULL)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_MD_CTX_new"));
+
+ if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_DigestSignInit"));
+ if (EVP_DigestSign(mdctx, NULL, &siglen, tbs, tbslen) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_DigestSign"));
+ if (!enif_alloc_binary(siglen, &sig_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
+ sig_bin_alloc = 1;
+
+ if (EVP_DigestSign(mdctx, sig_bin.data, &siglen, tbs, tbslen) != 1) {
+ if (mdctx)
+ EVP_MD_CTX_free(mdctx);
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_DigestSign"));
+ }
+ if (mdctx)
+ EVP_MD_CTX_free(mdctx);
+ }
+ else
+# endif
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 0, "eddsa not supported"));
+ } else {
+
+# ifndef HAVE_DSA
+ if (argv[0] == atom_dss) assign_goto(ret, err, EXCP_NOTSUP_N(env, 0, "dsa not supported"));
+ } else {
+# endif
+ if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_sign"));
- if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey) != 1)
- goto err;
- if (EVP_DigestSign(mdctx, NULL, &siglen, tbs, tbslen) != 1)
- goto err;
if (!enif_alloc_binary(siglen, &sig_bin))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
sig_bin_alloc = 1;
- if (EVP_DigestSign(mdctx, sig_bin.data, &siglen, tbs, tbslen) != 1)
- goto bad_key;
+ if (md != NULL) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ }
+ if (EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_sign"));
}
- else
-# endif
- goto notsup;
- } else {
- if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) != 1)
- goto err;
- if (!enif_alloc_binary(siglen, &sig_bin))
- goto err;
- sig_bin_alloc = 1;
-
- if (md != NULL) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
- }
- if (EVP_PKEY_sign(ctx, sig_bin.data, &siglen, tbs, tbslen) != 1)
- goto bad_key;
- }
-#else
-/*printf("Old interface\r\n");
- */
- if (argv[0] == atom_rsa) {
- if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
- goto err;
- if ((len = RSA_size(rsa)) < 0)
- goto err;
- if (!enif_alloc_binary((size_t)len, &sig_bin))
- goto err;
- sig_bin_alloc = 1;
-
- if ((len = EVP_MD_size(md)) < 0)
- goto err;
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
-
- if (RSA_sign(md->type, tbs, (unsigned int)len, sig_bin.data, &siglen, rsa) != 1)
- goto bad_key;
- } else if (argv[0] == atom_dss) {
- if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL)
- goto err;
- if ((len = DSA_size(dsa)) < 0)
- goto err;
- if (!enif_alloc_binary((size_t)len, &sig_bin))
- goto err;
- sig_bin_alloc = 1;
-
- if ((len = EVP_MD_size(md)) < 0)
- goto err;
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
-
- if (DSA_sign(md->type, tbs, len, sig_bin.data, &siglen, dsa) != 1)
- goto bad_key;
- } else if (argv[0] == atom_ecdsa) {
-#if defined(HAVE_EC)
- if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
- goto err;
- if ((len = ECDSA_size(ec)) < 0)
- goto err;
- if (!enif_alloc_binary((size_t)len, &sig_bin))
- goto err;
- sig_bin_alloc = 1;
-
- len = EVP_MD_size(md);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
-
- if (ECDSA_sign(md->type, tbs, len, sig_bin.data, &siglen, ec) != 1)
- goto bad_key;
-#else
- goto notsup;
-#endif
- } else {
- goto bad_arg;
- }
-#endif
ERL_VALGRIND_MAKE_MEM_DEFINED(sig_bin.data, siglen);
if (siglen != sig_bin.size) {
if (!enif_realloc_binary(&sig_bin, siglen))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't reallocate binary"));
ERL_VALGRIND_ASSERT_MEM_DEFINED(sig_bin.data, siglen);
}
+
ret = enif_make_binary(env, &sig_bin);
sig_bin_alloc = 0;
- goto done;
-
- bad_key:
- ret = atom_error;
- goto done;
-
- notsup:
- ret = atom_notsup;
- goto done;
-
- bad_arg:
- err:
- ret = enif_make_badarg(env);
- goto done;
- done:
+ err:
if (sig_bin_alloc)
enif_release_binary(&sig_bin);
- if (rsa)
- RSA_free(rsa);
-#ifdef HAVE_DSA
- if (dsa)
- DSA_free(dsa);
-#endif
-#ifdef HAVE_EC
- if (ec)
- EC_KEY_free(ec);
-#endif
-#ifdef HAS_EVP_PKEY_CTX
if (ctx)
EVP_PKEY_CTX_free(ctx);
-#endif
if (pkey)
EVP_PKEY_free(pkey);
+ return ret;
+ }
+ /* End of HAS_EVP_PKEY_CTX */
+#else
+ /* Old interface - before EVP_PKEY_CTX */
+ {
+ if (!get_pkey_private_key(env, argv, 0, 3, &pkey, &ret))
+ goto err; /* An exception is present in ret */
+
+ if (argv[0] == atom_rsa) {
+ if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Not an RSA private key"));
+ if ((len = RSA_size(rsa)) < 0)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Bad RSA private key length"));
+ if (!enif_alloc_binary((size_t)len, &sig_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
+ sig_bin_alloc = 1;
-#ifdef HAVE_EDDSA
- if (mdctx)
- EVP_MD_CTX_free(mdctx);
+ if ((len = EVP_MD_size(md)) < 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get md length"));
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
+
+ if (RSA_sign(md->type, tbs, (unsigned int)len, sig_bin.data, &siglen, rsa) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't sign"));
+
+ } else if (argv[0] == atom_dss) {
+ if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Not an DSA private key"));
+ if ((len = DSA_size(dsa)) < 0)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Bad DSA private key length"));
+ if (!enif_alloc_binary((size_t)len, &sig_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
+ sig_bin_alloc = 1;
+
+ if ((len = EVP_MD_size(md)) < 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get md length"));
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
+
+ if (DSA_sign(md->type, tbs, len, sig_bin.data, &siglen, dsa) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't sign"));
+ } else if (argv[0] == atom_ecdsa) {
+# if defined(HAVE_EC)
+ if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Not an ECDSA private key"));
+ if ((len = ECDSA_size(ec)) < 0)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't get size"));
+ if (!enif_alloc_binary((size_t)len, &sig_bin))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
+ sig_bin_alloc = 1;
+
+ len = EVP_MD_size(md);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len);
+
+ if (ECDSA_sign(md->type, tbs, len, sig_bin.data, &siglen, ec) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't sign"));
+# else
+ assign_goto(ret, notsup, EXCP_NOTSUP_N(env, 0, "ecdsa not supported"));
+# endif /* HAVE_EC */
+ } else {
+ assign_goto(ret, notsup, EXCP_BADARG_N(env, 0, "Unknown algorithm"));
+ }
+
+ ERL_VALGRIND_MAKE_MEM_DEFINED(sig_bin.data, siglen);
+ if (siglen != sig_bin.size) {
+ if (!enif_realloc_binary(&sig_bin, siglen))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't re-allocate binary"));
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(sig_bin.data, siglen);
+ }
+ ret = enif_make_binary(env, &sig_bin);
+ sig_bin_alloc = 0;
+
+ notsup:
+ err:
+ if (sig_bin_alloc)
+ enif_release_binary(&sig_bin);
+ if (rsa)
+ RSA_free(rsa);
+# ifdef HAVE_DSA
+ if (dsa)
+ DSA_free(dsa);
+# endif
+# ifdef HAVE_EC
+ if (ec)
+ EC_KEY_free(ec);
+# endif
+# ifdef HAS_EVP_PKEY_CTX
+ if (ctx)
+ EVP_PKEY_CTX_free(ctx);
+# endif
+ if (pkey)
+ EVP_PKEY_free(pkey);
+
+ return ret;
+ }
#endif
- return ret;
}
+
+
ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{/* (Algorithm, Type, Data|{digest,Digest}, Signature, Key, Options) */
- int i;
int result;
const EVP_MD *md = NULL;
unsigned char md_value[EVP_MAX_MD_SIZE];
EVP_PKEY *pkey = NULL;
-#ifdef HAS_EVP_PKEY_CTX
- EVP_PKEY_CTX *ctx = NULL;
-#else
-#endif
PKeySignOptions sig_opt;
ErlNifBinary sig_bin; /* signature */
unsigned char *tbs = NULL; /* data to be signed */
size_t tbslen = 0;
- ERL_NIF_TERM ret;
+ ERL_NIF_TERM ret = atom_undefined;
+
+#ifdef HAS_EVP_PKEY_CTX
+ EVP_PKEY_CTX *ctx = NULL;
+#else
RSA *rsa = NULL;
-#ifdef HAVE_DSA
- DSA *dsa = NULL;
-#endif
-#ifdef HAVE_EC
- EC_KEY *ec = NULL;
-#endif
-#ifdef HAVE_EDDSA
- EVP_MD_CTX *mdctx = NULL;
-#endif
+# ifdef HAVE_DSA
+ DSA *dsa = NULL;
+# endif
+# ifdef HAVE_EC
+ EC_KEY *ec = NULL;
+# endif
+#endif // HAS_EVP_PKEY_CTX
+
#ifndef HAS_ENGINE_SUPPORT
- if (enif_is_map(env, argv[4]))
- return atom_notsup;
+ if (enif_is_map(env, argv[3]))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "No engine support"));
#endif
- if (!enif_inspect_binary(env, argv[3], &sig_bin))
- return enif_make_badarg(env);
-
- i = get_pkey_sign_digest(env, argv[0], argv[1], argv[2], md_value, &md, &tbs, &tbslen);
- switch (i) {
- case PKEY_OK:
- break;
- case PKEY_NOTSUP:
- goto notsup;
- default:
- goto bad_arg;
- }
+ if (!get_pkey_sign_digest(env, argv, 0, 1, 2, md_value, &md, &tbs, &tbslen, &ret))
+ goto err; /* An exception is present in ret */
- i = get_pkey_sign_options(env, argv[0], argv[5], md, &sig_opt);
- switch (i) {
- case PKEY_OK:
- break;
- case PKEY_NOTSUP:
- goto notsup;
- default:
- goto bad_arg;
- }
+ if (!get_pkey_sign_options(env, argv, 0, 5, md, &sig_opt, &ret))
+ goto err; /* An exception is present in ret */
- if (get_pkey_public_key(env, argv[0], argv[4], &pkey) != PKEY_OK) {
- goto bad_arg;
- }
+ if (!enif_inspect_binary(env, argv[3], &sig_bin))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Expected a binary"));
#ifdef HAS_EVP_PKEY_CTX
-/* printf("EVP interface\r\n");
- */
- if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
- goto err;
-
- if (argv[0] != atom_eddsa) {
- if (EVP_PKEY_verify_init(ctx) != 1)
- goto err;
- if (md != NULL) {
- if (EVP_PKEY_CTX_set_signature_md(ctx, md) != 1)
- goto err;
+ /* EVP_PKEY_CTX */
+ {
+ if (!get_pkey_public_key(env, argv, 0, 4, &pkey, &ret))
+ goto err; /* An exception is present in ret */
+
+ if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate new EVP_PKEY_CTX"));
+
+ if (argv[0] != atom_eddsa) {
+ if (EVP_PKEY_verify_init(ctx) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_sign_init"));
+ if (md != NULL) {
+ if (EVP_PKEY_CTX_set_signature_md(ctx, md) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_signature_md"));
+ }
}
- }
- if (argv[0] == atom_rsa) {
- if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) != 1)
- goto err;
- if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
- if (sig_opt.rsa_mgf1_md != NULL) {
-# ifdef HAVE_RSA_MGF1_MD
- if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) != 1)
- goto err;
-# else
- goto notsup;
-# endif
- }
- if (sig_opt.rsa_pss_saltlen > -2) {
- if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) != 1)
- goto err;
+ if (argv[0] == atom_rsa) {
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_rsa_padding"));
+# ifdef HAVE_RSA_PKCS1_PSS_PADDING
+ if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
+ if (sig_opt.rsa_mgf1_md != NULL) {
+# ifdef HAVE_RSA_MGF1_MD
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sig_opt.rsa_mgf1_md) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_rsa_mgf1_md"));
+# else
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 5, "rsa_mgf1_md unavailable with this cryptolib"));
+# endif
+ }
+ if (sig_opt.rsa_pss_saltlen > -2) {
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) != 1)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 5, "Bad rsa_pss_saltlen"));
+ }
}
+# endif
}
- }
- if (argv[0] == atom_eddsa) {
-#ifdef HAVE_EDDSA
- if (!FIPS_MODE()) {
- if ((mdctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ if (argv[0] == atom_eddsa) {
+# ifdef HAVE_EDDSA
+ EVP_MD_CTX *mdctx = NULL;
+ if (!FIPS_MODE()) {
+ if ((mdctx = EVP_MD_CTX_new()) == NULL)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_MD_CTX_new"));
- if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1)
- goto err;
+ if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_DigestVerifyInit"));
- result = EVP_DigestVerify(mdctx, sig_bin.data, sig_bin.size, tbs, tbslen);
- }
- else
-#endif
- goto notsup;
- } else {
- if (md != NULL) {
- ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ result = EVP_DigestVerify(mdctx, sig_bin.data, sig_bin.size, tbs, tbslen);
+ if (mdctx)
+ EVP_MD_CTX_free(mdctx);
+ }
+ else
+# endif /* HAVE_EDDSA */
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 0, "eddsa not supported"));
+ } else {
+ /* RSA or DSS */
+ if (md != NULL) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, EVP_MD_size(md));
+ }
+ result = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen);
}
- result = EVP_PKEY_verify(ctx, sig_bin.data, sig_bin.size, tbs, tbslen);
- }
-#else
-/*printf("Old interface\r\n");
-*/
- if (tbslen > INT_MAX)
- goto bad_arg;
- if (sig_bin.size > INT_MAX)
- goto bad_arg;
- if (argv[0] == atom_rsa) {
- if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
- goto err;
- result = RSA_verify(md->type, tbs, (unsigned int)tbslen, sig_bin.data, (unsigned int)sig_bin.size, rsa);
- } else if (argv[0] == atom_dss) {
- if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL)
- goto err;
- result = DSA_verify(0, tbs, (int)tbslen, sig_bin.data, (int)sig_bin.size, dsa);
- } else if (argv[0] == atom_ecdsa) {
-#if defined(HAVE_EC)
- if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
- goto err;
- result = ECDSA_verify(EVP_MD_type(md), tbs, (int)tbslen, sig_bin.data, (int)sig_bin.size, ec);
-#else
- goto notsup;
-#endif
- } else {
- goto bad_arg;
- }
-#endif
- ret = (result == 1 ? atom_true : atom_false);
- goto done;
+ ret = (result == 1 ? atom_true : atom_false);
- bad_arg:
- err:
- ret = enif_make_badarg(env);
- goto done;
+ err:
+ if (ctx)
+ EVP_PKEY_CTX_free(ctx);
+ if (pkey)
+ EVP_PKEY_free(pkey);
- notsup:
- ret = atom_notsup;
+ return ret;
+ }
+ /* End of HAS_EVP_PKEY_CTX */
+#else
+ /* Old interface - before EVP_PKEY_CTX */
+ {
+ if (!get_pkey_public_key(env, argv, 0, 4, &pkey, &ret))
+ goto err; /* An exception is present in ret */
+
+ if (argv[0] == atom_rsa) {
+ if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 4, "Not an RSA public key"));
+ result = RSA_verify(md->type, tbs, (unsigned int)tbslen, sig_bin.data, (unsigned int)sig_bin.size, rsa);
+ } else if (argv[0] == atom_dss) {
+ if ((dsa = EVP_PKEY_get1_DSA(pkey)) == NULL)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 4, "Not an DSA public key"));
+ result = DSA_verify(0, tbs, (int)tbslen, sig_bin.data, (int)sig_bin.size, dsa);
+ } else if (argv[0] == atom_ecdsa) {
+# if defined(HAVE_EC)
+ if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
+ assign_goto(ret, err, EXCP_BADARG_N(env, 4, "Not an ECDSA private key"));
+ result = ECDSA_verify(EVP_MD_type(md), tbs, (int)tbslen, sig_bin.data, (int)sig_bin.size, ec);
+# else
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 0, "ecdsa not supported"));
+# endif /* HAVE_EC */
+ } else {
+ assign_goto(ret, err, EXCP_BADARG_N(env, 0, "Unknown algorithm"));
+ }
+ ret = (result == 1 ? atom_true : atom_false);
+
+ err:
+ if (rsa)
+ RSA_free(rsa);
+# ifdef HAVE_DSA
+ if (dsa)
+ DSA_free(dsa);
+# endif
+# ifdef HAVE_EC
+ if (ec)
+ EC_KEY_free(ec);
+# endif
+ if (pkey)
+ EVP_PKEY_free(pkey);
- done:
-#ifdef HAS_EVP_PKEY_CTX
- if (ctx)
- EVP_PKEY_CTX_free(ctx);
-#endif
-#ifdef HAVE_EDDSA
- if (mdctx)
- EVP_MD_CTX_free(mdctx);
-#endif
- if (pkey)
- EVP_PKEY_free(pkey);
- if (rsa)
- RSA_free(rsa);
-#ifdef HAVE_DSA
- if (dsa)
- DSA_free(dsa);
-#endif
-#ifdef HAVE_EC
- if (ec)
- EC_KEY_free(ec);
-#endif
+ return ret;
+ }
+#endif /* Pre EVP_PKEY_CTX */
- return ret;
}
-static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_TERM options,
- PKeyCryptOptions *opt)
+
+static int get_pkey_crypt_options(ErlNifEnv *env,
+ const ERL_NIF_TERM argv[],
+ int algorithm_arg_num, int options_arg_num,
+ PKeyCryptOptions *opt,
+ ERL_NIF_TERM *err_return)
{
ERL_NIF_TERM head, tail;
const ERL_NIF_TERM *tpl_terms;
int tpl_arity;
const EVP_MD *opt_md;
- if (!enif_is_list(env, options))
- goto bad_arg;
+ if (!enif_is_list(env, argv[options_arg_num]))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Expected a list"));
/* defaults */
- if (algorithm == atom_rsa) {
+ if (argv[algorithm_arg_num] == atom_rsa) {
opt->rsa_mgf1_md = NULL;
opt->rsa_oaep_label.data = NULL;
opt->rsa_oaep_label.size = 0;
@@ -859,18 +911,17 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI
opt->signature_md = NULL;
}
- if (enif_is_empty_list(env, options))
- return PKEY_OK;
+ if (enif_is_empty_list(env, argv[options_arg_num]))
+ return 1; /* There are no options to fetch. Return OK */
- if (algorithm != atom_rsa)
- goto bad_arg;
+ if (argv[algorithm_arg_num] != atom_rsa)
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Only RSA supports Options"));
- tail = options;
+ tail = argv[options_arg_num];
while (enif_get_list_cell(env, tail, &head, &tail)) {
- if (!enif_get_tuple(env, head, &tpl_arity, &tpl_terms))
- goto bad_arg;
- if (tpl_arity != 2)
- goto bad_arg;
+ if (!enif_get_tuple(env, head, &tpl_arity, &tpl_terms) ||
+ (tpl_arity != 2))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Expect only two-tuples in the list"));
if (tpl_terms[0] == atom_rsa_padding
|| tpl_terms[0] == atom_rsa_pad /* Compatibility */
@@ -894,59 +945,62 @@ static int get_pkey_crypt_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NI
} else if (tpl_terms[1] == atom_rsa_no_padding) {
opt->rsa_padding = RSA_NO_PADDING;
- } else {
- goto bad_arg;
- }
+ } else
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Bad padding type in option rsa_padding"));
+
+ } else if (tpl_terms[0] == atom_signature_md) {
+ if (!enif_is_atom(env, tpl_terms[1]))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Atom expected as argument to option signature_md"));
+
+ if (!get_pkey_digest_type(env, argv[algorithm_arg_num],
+ options_arg_num, tpl_terms[1],
+ &opt_md, err_return))
+ goto err; /* An exception is present in ret */
- } else if (tpl_terms[0] == atom_signature_md && enif_is_atom(env, tpl_terms[1])) {
- int i;
- i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
- if (i != PKEY_OK) {
- return i;
- }
opt->signature_md = opt_md;
- } else if (tpl_terms[0] == atom_rsa_mgf1_md && enif_is_atom(env, tpl_terms[1])) {
- int i;
+ } else if (tpl_terms[0] == atom_rsa_mgf1_md) {
+ if (!enif_is_atom(env, tpl_terms[1]))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Atom expected as argument to option rsa_mgf1_md"));
#ifndef HAVE_RSA_MGF1_MD
if (tpl_terms[1] != atom_sha)
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Only 'sha' is supported in option rsa_mgf1_md"));
#endif
- i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
- if (i != PKEY_OK) {
- return i;
- }
+ if (!get_pkey_digest_type(env, argv[algorithm_arg_num],
+ options_arg_num, tpl_terms[1],
+ &opt_md, err_return))
+ goto err; /* An exception is present in ret */
opt->rsa_mgf1_md = opt_md;
- } else if (tpl_terms[0] == atom_rsa_oaep_label
- && enif_inspect_binary(env, tpl_terms[1], &(opt->rsa_oaep_label))) {
+ } else if (tpl_terms[0] == atom_rsa_oaep_label) {
#ifdef HAVE_RSA_OAEP_MD
+ if (!enif_inspect_binary(env, tpl_terms[1], &(opt->rsa_oaep_label)))
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Binary expected for option rsa_oaep_label"));
continue;
#else
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, options_arg_num, "Option rsa_oaep_label is not supported"));
#endif
- } else if (tpl_terms[0] == atom_rsa_oaep_md && enif_is_atom(env, tpl_terms[1])) {
- int i;
+ } else if (tpl_terms[0] == atom_rsa_oaep_md) {
+ if (!enif_is_atom(env, tpl_terms[1]))
+ assign_goto(*err_return, err, EXCP_NOTSUP_N(env, options_arg_num, "Atom expected as argument to option rsa_oaep_md"));
#ifndef HAVE_RSA_OAEP_MD
if (tpl_terms[1] != atom_sha)
- return PKEY_NOTSUP;
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Only 'sha' is supported in option rsa_oaep_md"));
#endif
- i = get_pkey_digest_type(env, algorithm, tpl_terms[1], &opt_md);
- if (i != PKEY_OK) {
- return i;
- }
+ if (!get_pkey_digest_type(env, argv[algorithm_arg_num],
+ options_arg_num, tpl_terms[1],
+ &opt_md, err_return))
+ goto err; /* An exception is present in ret */
opt->rsa_oaep_md = opt_md;
-
- } else {
- goto bad_arg;
- }
+ } else
+ assign_goto(*err_return, err, EXCP_BADARG_N(env, options_arg_num, "Unknown option"))
}
- return PKEY_OK;
+ return 1;
- bad_arg:
- return PKEY_BADARG;
+ err:
+ return 0;
}
#ifdef HAVE_RSA_SSLV23_PADDING
@@ -968,8 +1022,7 @@ static size_t size_of_RSA(EVP_PKEY *pkey) {
ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{/* (Algorithm, Data, PublKey=[E,N]|[E,N,D]|[E,N,D,P1,P2,E1,E2,C], Options, IsPrivate, IsEncrypt) */
- ERL_NIF_TERM ret;
- int i;
+ ERL_NIF_TERM ret = atom_undefined;
int result = 0;
int tmp_bin_alloc = 0;
int out_bin_alloc = 0;
@@ -987,74 +1040,61 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
size_t tmplen;
#endif
int is_private, is_encrypt;
- int algo_init = 0;
unsigned char *label_copy = NULL;
- ASSERT(argc == 6);
-
is_private = (argv[4] == atom_true);
is_encrypt = (argv[5] == atom_true);
-/* char algo[1024]; */
+ if (!check_pkey_algorithm_type(env, 0, argv[0], &ret))
+ goto err; /* An exception is present in ret */
+
+ if (!enif_inspect_binary(env, argv[1], &in_bin))
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Binary expected"));
#ifndef HAS_ENGINE_SUPPORT
if (enif_is_map(env, argv[2]))
- return atom_notsup;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "No engine support"));
#endif
- if (!enif_inspect_binary(env, argv[1], &in_bin))
- goto bad_arg;
-
- i = get_pkey_crypt_options(env, argv[0], argv[3], &crypt_opt);
- switch (i) {
- case PKEY_OK:
- break;
- case PKEY_NOTSUP:
- goto notsup;
- default:
- goto bad_arg;
- }
-
if (is_private) {
- if (get_pkey_private_key(env, argv[0], argv[2], &pkey) != PKEY_OK)
- goto bad_arg;
+ if (!get_pkey_private_key(env, argv, 0, 2, &pkey, &ret))
+ goto err; /* An exception is present in ret */
} else {
- if (get_pkey_public_key(env, argv[0], argv[2], &pkey) != PKEY_OK)
- goto bad_arg;
+ if (!get_pkey_public_key(env, argv, 0, 2, &pkey, &ret))
+ goto err; /* An exception is present in ret */
}
+ if (!get_pkey_crypt_options(env, argv, 0, 3, &crypt_opt, &ret))
+ goto err; /* An exception is present in ret */
+
#ifdef HAS_EVP_PKEY_CTX
- if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
- goto err;
+ {
+ int algo_init = 0;
-/* enif_get_atom(env,argv[0],algo,1024,ERL_NIF_LATIN1); */
+ if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate new EVP_PKEY_CTX"));
- if (is_private) {
- if (is_encrypt) {
- /* private encrypt */
- if ((algo_init = EVP_PKEY_sign_init(ctx)) != 1)
- goto bad_arg;
- } else {
- /* private decrypt */
- if ((algo_init = EVP_PKEY_decrypt_init(ctx)) != 1)
- goto bad_arg;
- }
- } else {
- if (is_encrypt) {
- /* public encrypt */
- if ((algo_init = EVP_PKEY_encrypt_init(ctx)) != 1)
- goto bad_arg;
- } else {
- /* public decrypt */
- if ((algo_init = EVP_PKEY_verify_recover_init(ctx)) != 1)
- goto bad_arg;
- }
+ if (is_private) {
+ if (is_encrypt)
+ algo_init = EVP_PKEY_sign_init(ctx);
+ else
+ algo_init = EVP_PKEY_decrypt_init(ctx);
+
+ } else {
+ if (is_encrypt)
+ algo_init = EVP_PKEY_encrypt_init(ctx);
+ else
+ algo_init = EVP_PKEY_verify_recover_init(ctx);
+ }
+
+ if (algo_init != 1)
+ assign_goto(ret, err, EXCP_NOTSUP(env, "Can't initiate encrypt/decrypt"));
}
if (argv[0] == atom_rsa) {
if (crypt_opt.signature_md != NULL) {
if (EVP_PKEY_CTX_set_signature_md(ctx, crypt_opt.signature_md) != 1)
- goto bad_arg;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't EVP_PKEY_CTX_set_signature_md"));
}
# ifdef HAVE_RSA_SSLV23_PADDING
@@ -1062,40 +1102,38 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
if (is_encrypt) {
tmplen = size_of_RSA(pkey);
if (tmplen < 1 || tmplen > INT_MAX)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "RSA key of wrong size"));
if (!enif_alloc_binary(tmplen, &tmp_bin))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
tmp_bin_alloc = 1;
if (in_bin.size > INT_MAX)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Binary too large"));
if (!RSA_padding_add_SSLv23(tmp_bin.data, (int)tmplen, in_bin.data, (int)in_bin.size))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't RSA_padding_add_SSLv23"));
in_bin = tmp_bin;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set RSA_NO_PADDING"));
} else
# endif
- {
if (EVP_PKEY_CTX_set_rsa_padding(ctx, crypt_opt.rsa_padding) != 1)
- goto err;
- }
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set rsa padding"));
# ifdef HAVE_RSA_OAEP_MD
if (crypt_opt.rsa_padding == RSA_PKCS1_OAEP_PADDING) {
if (crypt_opt.rsa_oaep_md != NULL) {
if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, crypt_opt.rsa_oaep_md) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't EVP_PKEY_CTX_set_rsa_oaep_md"));
}
if (crypt_opt.rsa_mgf1_md != NULL) {
if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, crypt_opt.rsa_mgf1_md) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't EVP_PKEY_CTX_set_rsa_mgf1_md"));
}
if (crypt_opt.rsa_oaep_label.data != NULL && crypt_opt.rsa_oaep_label.size > 0) {
if (crypt_opt.rsa_oaep_label.size > INT_MAX)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "RSA oep label too large"));
if ((label_copy = OPENSSL_malloc(crypt_opt.rsa_oaep_label.size)) == NULL)
goto err;
@@ -1104,7 +1142,7 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_copy,
(int)crypt_opt.rsa_oaep_label.size) != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't set RSA oaep label"));
/* On success, label_copy is owned by ctx */
label_copy = NULL;
}
@@ -1112,105 +1150,77 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
# endif
}
- if (is_private) {
- if (is_encrypt) {
- /* private_encrypt */
- result = EVP_PKEY_sign(ctx, NULL, &outlen, in_bin.data, in_bin.size);
- } else {
- /* private_decrypt */
- result = EVP_PKEY_decrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size);
- }
- } else {
- if (is_encrypt) {
- /* public_encrypt */
- result = EVP_PKEY_encrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size);
- } else {
- /* public_decrypt */
- result = EVP_PKEY_verify_recover(ctx, NULL, &outlen, in_bin.data, in_bin.size);
- }
- }
-
+ /* Get the size of the result */
+ if (is_private)
+ result =
+ is_encrypt ? EVP_PKEY_sign(ctx, NULL, &outlen, in_bin.data, in_bin.size)
+ : EVP_PKEY_decrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size);
+ else
+ result =
+ is_encrypt ? EVP_PKEY_encrypt(ctx, NULL, &outlen, in_bin.data, in_bin.size)
+ : EVP_PKEY_verify_recover(ctx, NULL, &outlen, in_bin.data, in_bin.size);
+
+ /* Check */
if (result != 1)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't get size of result"));
+ /* Allocate */
if (!enif_alloc_binary(outlen, &out_bin))
- goto err;
- out_bin_alloc = 1;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
- if (is_private) {
- if (is_encrypt) {
- /* private_encrypt */
- result = EVP_PKEY_sign(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
- } else {
- /* private_decrypt */
- result = EVP_PKEY_decrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
- }
- } else {
- if (is_encrypt) {
- /* public_encrypt */
- result = EVP_PKEY_encrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
- } else {
- /* public_decrypt */
- result = EVP_PKEY_verify_recover(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
- }
- }
+ out_bin_alloc = 1; /* Flag de-allocation */
+
+ /* Get the result into the newly allocated binary */
+ if (is_private)
+ result =
+ is_encrypt ? EVP_PKEY_sign(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size)
+ : EVP_PKEY_decrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
+ else
+ result=
+ is_encrypt ? EVP_PKEY_encrypt(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size)
+ : EVP_PKEY_verify_recover(ctx, out_bin.data, &outlen, in_bin.data, in_bin.size);
+
+ if (result != 1)
+ assign_goto(ret, err, EXCP_ERROR(env, "Couldn't get the result"));
#else
- /* Non-EVP cryptolib. Only support RSA */
+ /* Non-EVP cryptolib. Only supports RSA */
- if (argv[0] != atom_rsa) {
- algo_init = -2; /* exitcode: notsup */
- goto bad_arg;
- }
+ if (argv[0] != atom_rsa)
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 0, "Only RSA is supported"));
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "Not RSA key"));
if ((len = RSA_size(rsa)) < 0)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 3, "Bad RSA key length"));
if (!enif_alloc_binary((size_t)len, &out_bin))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
out_bin_alloc = 1;
if (in_bin.size > INT_MAX)
- goto err;
- if (is_private) {
- if (is_encrypt) {
- /* non-evp rsa private encrypt */
- ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size);
- result = RSA_private_encrypt((int)in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
- if (result > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result);
- }
- } else {
- /* non-evp rsa private decrypt */
- result = RSA_private_decrypt((int)in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
- if (result > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result);
- if (!enif_realloc_binary(&out_bin, (size_t)result))
- goto err;
- }
- }
- } else {
- if (is_encrypt) {
- /* non-evp rsa public encrypt */
- ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size);
- result = RSA_public_encrypt((int)in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
- if (result > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result);
- }
- } else {
- /* non-evp rsa public decrypt */
- result = RSA_public_decrypt((int)in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
- if (result > 0) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result);
- if (!enif_realloc_binary(&out_bin, (size_t)result))
- goto err;
- }
- }
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Bad indata length"));
+
+ if (is_encrypt) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(in_bin.data,in_bin.size);
+ }
+
+ if (is_private)
+ result =
+ is_encrypt ? RSA_private_encrypt((int)in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding)
+ : RSA_private_decrypt((int)in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding);
+ else
+ result =
+ is_encrypt ? RSA_public_encrypt((int)in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding)
+ : RSA_public_decrypt((int)in_bin.size, in_bin.data,
+ out_bin.data, rsa, crypt_opt.rsa_padding);
+ if (result > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, result);
+ if (!is_encrypt &&
+ !enif_realloc_binary(&out_bin, (size_t)result))
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't re-allocate binary"));
}
outlen = (size_t)result;
@@ -1223,12 +1233,12 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
tmplen = size_of_RSA(pkey);
if (tmplen < 1 || tmplen > INT_MAX)
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 2, "RSA key of wrong size"));
if (!enif_alloc_binary(tmplen, &tmp_bin))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't allocate binary"));
tmp_bin_alloc = 1;
if (out_bin.size > INT_MAX)
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Result too large"));
p = out_bin.data;
p++;
@@ -1249,28 +1259,16 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, outlen);
if (outlen != out_bin.size) {
if (!enif_realloc_binary(&out_bin, outlen))
- goto err;
+ assign_goto(ret, err, EXCP_ERROR(env, "Can't re-allocate binary"));
ERL_VALGRIND_ASSERT_MEM_DEFINED(out_bin.data, outlen);
}
ret = enif_make_binary(env, &out_bin);
out_bin_alloc = 0;
} else {
- ret = atom_error;
+ assign_goto(ret, err, EXCP_ERROR(env, "RSA encrypt/decrypt failed"));
}
- goto done;
-
- notsup:
- ret = atom_notsup;
- goto done;
- bad_arg:
err:
- if (algo_init == -2)
- ret = atom_notsup;
- else
- ret = enif_make_badarg(env);
-
- done:
if (out_bin_alloc)
enif_release_binary(&out_bin);
if (tmp_bin_alloc)
@@ -1290,7 +1288,7 @@ ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
OPENSSL_free(label_copy);
return ret;
-}
+ }
ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{ /* (Algorithm, PrivKey | KeyMap) */
@@ -1299,17 +1297,20 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ASSERT(argc == 2);
- if (get_pkey_private_key(env, argv[0], argv[1], &pkey) != PKEY_OK) // handles engine
- goto bad_arg;
+ if (!check_pkey_algorithm_type(env, 0, argv[0], &ret))
+ goto err; /* An exception is present in ret */
+
+ if (!get_pkey_private_key(env, argv, 0, 1, &pkey, &ret)) // handles engine
+ goto err; /* An exception is present in ret */
if (argv[0] == atom_rsa) {
if (!rsa_privkey_to_pubkey(env, pkey, &ret))
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get RSA public key from private key"));
#ifdef HAVE_DSA
} else if (argv[0] == atom_dss) {
if (!dss_privkey_to_pubkey(env, pkey, &ret))
- goto err;
+ assign_goto(ret, err, EXCP_BADARG_N(env, 1, "Couldn't get DSA public key from private key"));
#endif
} else if (argv[0] == atom_ecdsa) {
#if defined(HAVE_EC)
@@ -1346,18 +1347,12 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
return enif_make_list_from_array(env, ..., ...);
*/
#endif
- goto bad_arg;
+ assign_goto(ret, err, EXCP_NOTSUP_N(env, 0, "ECDSA not implemented"));
} else {
- goto bad_arg;
+ ret = EXCP_BADARG_N(env, 0, "Bad algorithm");
}
- goto done;
-
- bad_arg:
err:
- ret = enif_make_badarg(env);
-
- done:
if (pkey)
EVP_PKEY_free(pkey);
diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c
index 82bf2c7467..cc34f0afc7 100644
--- a/lib/crypto/c_src/rand.c
+++ b/lib/crypto/c_src/rand.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -101,7 +101,11 @@ ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
if (!BN_sub(bn_to, bn_rand, bn_from))
goto err;
+#ifdef HAS_3_0_API
+ if (!BN_rand_range(bn_rand, bn_to))
+#else
if (!BN_pseudo_rand_range(bn_rand, bn_to))
+#endif
goto err;
if (!BN_add(bn_rand, bn_rand, bn_from))
goto err;
diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c
index 5ee389467d..0a543fe6e5 100644
--- a/lib/crypto/c_src/rsa.c
+++ b/lib/crypto/c_src/rsa.c
@@ -21,16 +21,93 @@
#include "rsa.h"
#include "bn.h"
-//#define(CHK_RSA_3_0)
-
static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-#if !defined(HAS_3_0_API) || defined(CHK_RSA_3_0)
+#if !defined(HAS_3_0_API)
static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa);
#endif
#if !defined(HAS_3_0_API)
static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt);
#endif
+#define PUT1(env,bn,t) \
+ if (bn) {if ((t = bin_from_bn(env, bn)) == atom_error) goto err;} \
+ else t = atom_undefined
+
+
+// ERL_NIF_TERM debug_put_pkey(ErlNifEnv* env, EVP_PKEY *pkey);
+// ERL_NIF_TERM debug_put_pkey(ErlNifEnv* env, EVP_PKEY *pkey)
+// {
+// const BIGNUM *e1 = NULL, *n1 = NULL, *d1 = NULL;
+// RSA *rsa = NULL;
+// ERL_NIF_TERM result[3];
+//
+// rsa = EVP_PKEY_get1_RSA(pkey);
+// RSA_get0_key(rsa, &n1, &e1, &d1);
+//
+// PUT1(env, e1, result[0]); // Exponent E
+// PUT1(env, n1, result[1]); // Modulus N = p*q
+// PUT1(env, d1, result[2]);
+//
+// return enif_make_list_from_array(env,result,3);
+//
+// err:
+// return atom_error;
+// }
+
+
+#if !defined(HAS_3_0_API)
+/* Creates a term which can be parsed by get_rsa_private_key(). This is a list of plain integer binaries (not mpints). */
+static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa)
+{
+ ERL_NIF_TERM result[8];
+ const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
+
+ /* Return at least [E,N,D] */
+ RSA_get0_key(rsa, &n, &e, &d);
+
+ if ((result[0] = bin_from_bn(env, e)) == atom_error) // Exponent E
+ goto err;
+ if ((result[1] = bin_from_bn(env, n)) == atom_error) // Modulus N = p*q
+ goto err;
+ if ((result[2] = bin_from_bn(env, d)) == atom_error) // Exponent D
+ goto err;
+
+ /* Check whether the optional additional parameters are available */
+ RSA_get0_factors(rsa, &p, &q);
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+
+ if (p && q && dmp1 && dmq1 && iqmp) {
+ if ((result[3] = bin_from_bn(env, p)) == atom_error) // Factor p
+ goto err;
+ if ((result[4] = bin_from_bn(env, q)) == atom_error) // Factor q
+ goto err;
+ if ((result[5] = bin_from_bn(env, dmp1)) == atom_error) // D mod (p-1)
+ goto err;
+ if ((result[6] = bin_from_bn(env, dmq1)) == atom_error) // D mod (q-1)
+ goto err;
+ if ((result[7] = bin_from_bn(env, iqmp)) == atom_error) // (1/q) mod p
+ goto err;
+
+ return enif_make_list_from_array(env, result, 8);
+ } else {
+ return enif_make_list_from_array(env, result, 3);
+ }
+
+ err:
+ return enif_make_badarg(env);
+}
+
+static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt)
+{
+ ErlNifEnv *env = BN_GENCB_get_arg(ctxt);
+
+ if (!enif_is_current_process_alive(env)) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
{
/* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
@@ -56,6 +133,7 @@ int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
if ((rsa = RSA_new()) == NULL)
goto err;
+ *pkey = EVP_PKEY_new();
if (!RSA_set0_key(rsa, n, e, d))
goto err;
/* rsa now owns n, e, and d */
@@ -135,6 +213,7 @@ int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
return 0;
}
+
int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
{
/* key=[E,N] */
@@ -162,9 +241,11 @@ int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
n = NULL;
e = NULL;
+ *pkey = EVP_PKEY_new();
if (EVP_PKEY_assign_RSA(*pkey, rsa) != 1)
goto err;
+ // enif_fprintf(stderr, "pkey = %T\r\n", debug_put_pkey(env,*pkey));
return 1;
bad_arg:
@@ -179,63 +260,6 @@ int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
return 0;
}
-#if !defined(HAS_3_0_API) || defined(CHK_RSA_3_0)
-/* Creates a term which can be parsed by get_rsa_private_key(). This is a list of plain integer binaries (not mpints). */
-static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa)
-{
- ERL_NIF_TERM result[8];
- const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
-
- /* Return at least [E,N,D] */
- RSA_get0_key(rsa, &n, &e, &d);
-
- if ((result[0] = bin_from_bn(env, e)) == atom_error) // Exponent E
- goto err;
- if ((result[1] = bin_from_bn(env, n)) == atom_error) // Modulus N = p*q
- goto err;
- if ((result[2] = bin_from_bn(env, d)) == atom_error) // Exponent D
- goto err;
-
- /* Check whether the optional additional parameters are available */
- RSA_get0_factors(rsa, &p, &q);
- RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
-
- if (p && q && dmp1 && dmq1 && iqmp) {
- if ((result[3] = bin_from_bn(env, p)) == atom_error) // Factor p
- goto err;
- if ((result[4] = bin_from_bn(env, q)) == atom_error) // Factor q
- goto err;
- if ((result[5] = bin_from_bn(env, dmp1)) == atom_error) // D mod (p-1)
- goto err;
- if ((result[6] = bin_from_bn(env, dmq1)) == atom_error) // D mod (q-1)
- goto err;
- if ((result[7] = bin_from_bn(env, iqmp)) == atom_error) // (1/q) mod p
- goto err;
-
- return enif_make_list_from_array(env, result, 8);
- } else {
- return enif_make_list_from_array(env, result, 3);
- }
-
- err:
- return enif_make_badarg(env);
-}
-#endif
-
-#if !defined(HAS_3_0_API)
-/* Legacy API deprecated from 3.0 is used */
-
-static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt)
-{
- ErlNifEnv *env = BN_GENCB_get_arg(ctxt);
-
- if (!enif_is_current_process_alive(env)) {
- return 0;
- } else {
- return 1;
- }
-}
-
static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (ModulusSize, PublicExponent) */
ERL_NIF_TERM ret;
@@ -303,9 +327,127 @@ static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TER
return ret;
}
+int rsa_privkey_to_pubkey(ErlNifEnv* env, EVP_PKEY *pkey, ERL_NIF_TERM *ret)
+{
+ const BIGNUM *n = NULL, *e = NULL, *d = NULL;
+ ERL_NIF_TERM result[2];
+ RSA *rsa = NULL;
+
+ if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
+ goto err;
+
+ RSA_get0_key(rsa, &n, &e, &d);
+
+ // Exponent E
+ if ((result[0] = bin_from_bn(env, e)) == atom_error)
+ goto err;
+ // Modulus N = p*q
+ if ((result[1] = bin_from_bn(env, n)) == atom_error)
+ goto err;
+
+ *ret = enif_make_list_from_array(env, result, 2);
+ RSA_free(rsa);
+ return 1;
+
+ err:
+ if (rsa)
+ RSA_free(rsa);
+ return 0;
+}
+
+
#else
/* New 3.0 API is used */
+int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
+{
+ /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
+ ERL_NIF_TERM head, tail;
+ OSSL_PARAM params[9];
+ EVP_PKEY_CTX *ctx = NULL;
+ int i = 0;
+
+ head = key;
+
+ if (!get_ossl_param_from_bin_in_list(env, "e", &head, &params[i++]) || // Exponent E
+ !get_ossl_param_from_bin_in_list(env, "n", &head, &params[i++]) || // N = p*q
+ !get_ossl_param_from_bin_in_list(env, "d", &head, &params[i++])) // Exponent D
+ goto bad_arg;
+
+ tail = head;
+
+ if (!enif_is_empty_list(env, tail)) {
+ if (!get_ossl_param_from_bin_in_list(env, "rsa-factor1", &head, &params[i++]) || // p, Factor p
+ !get_ossl_param_from_bin_in_list(env, "rsa-factor2", &head, &params[i++]) || // q, Factor q
+ !get_ossl_param_from_bin_in_list(env, "rsa-exponent1", &head, &params[i++]) || // dmp1, D mod (p-1)
+ !get_ossl_param_from_bin_in_list(env, "rsa-exponent2", &head, &params[i++]) || // dmq1, D mod (q-1)
+ !get_ossl_param_from_bin_in_list(env, "rsa-coefficient1", &head, &params[i++]) ) // iqmp, (1/q) mod p
+ goto bad_arg;
+
+ tail = head;
+
+ if (!enif_is_empty_list(env, tail))
+ goto bad_arg;
+ }
+
+ params[i++] = OSSL_PARAM_construct_end();
+
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(ctx) <= 0)
+ goto err;
+ if (EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0)
+ goto bad_arg;
+
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 1;
+
+ bad_arg:
+ err:
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 0;
+}
+
+
+int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey)
+{
+ ERL_NIF_TERM head, tail;
+ OSSL_PARAM params[3];
+ EVP_PKEY_CTX *ctx = NULL;
+
+ head = key;
+ if (!get_ossl_param_from_bin_in_list(env, "e", &head, &params[0]) )
+ goto bad_arg;
+
+ if (!get_ossl_param_from_bin_in_list(env, "n", &head, &params[1]) )
+ goto bad_arg;
+
+ tail = head;
+ if (!enif_is_empty_list(env, tail))
+ goto bad_arg;
+
+ params[2] = OSSL_PARAM_construct_end();
+
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL)
+ goto err;
+ if (EVP_PKEY_fromdata_init(ctx) <= 0)
+ goto err;
+ if (EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
+ goto bad_arg;
+
+ /* enif_fprintf(stderr, "pkey = %T\r\nn = %T\r\n", */
+ /* debug_put_pkey(env,*pkey), */
+ /* enif_make_binary(env,&tmp) */
+ /* ); */
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 1;
+
+ bad_arg:
+ err:
+ if (ctx) EVP_PKEY_CTX_free(ctx);
+ return 0;
+}
+
static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (ModulusSize, PublicExponent/binary, PublicExponent) */
ERL_NIF_TERM ret;
@@ -378,58 +520,56 @@ static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TER
|| ((result[7] = bin_from_bn(env, iqmp)) == atom_error)
) {
ret = EXCP_ERROR(env, "Can't get RSA keys");
- goto ret;
+ goto local_ret;
}
-
ret = enif_make_list_from_array(env, result, 8);
-
-#ifdef CHK_RSA_3_0
- {RSA *rsa = EVP_PKEY_get1_RSA(pkey);
- if (!rsa)
- ret = enif_make_tuple2(env, ret, atom_error);
- else
- ret = enif_make_tuple2(env, ret, put_rsa_private_key(env,rsa));
- }
-#endif
+ local_ret:
+ if (e) BN_free(e);
+ if (n) BN_free(n);
+ if (d) BN_free(d);
+ if (p) BN_free(p);
+ if (q) BN_free(q);
+ if (dmp1) BN_free(dmp1);
+ if (dmq1) BN_free(dmq1);
+ if (iqmp) BN_free(iqmp);
}
ret:
+ if (pkey) EVP_PKEY_free(pkey);
if (pctx) EVP_PKEY_CTX_free(pctx);
return ret;
}
-#endif /* #else-part of #if !defined(HAS_3_0_API) */
-
-
int rsa_privkey_to_pubkey(ErlNifEnv* env, EVP_PKEY *pkey, ERL_NIF_TERM *ret)
{
- const BIGNUM *n = NULL, *e = NULL, *d = NULL;
+ BIGNUM *e = NULL, *n = NULL;
ERL_NIF_TERM result[2];
- RSA *rsa = NULL;
-
- if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
- goto err;
-
- RSA_get0_key(rsa, &n, &e, &d);
- // Exponent E
- if ((result[0] = bin_from_bn(env, e)) == atom_error)
- goto err;
- // Modulus N = p*q
- if ((result[1] = bin_from_bn(env, n)) == atom_error)
+ /* https://www.openssl.org/docs/man3.0/man7/EVP_PKEY-RSA.html */
+ if (
+ !EVP_PKEY_get_bn_param(pkey, "e", &e) // Exponent E
+ || !EVP_PKEY_get_bn_param(pkey, "n", &n) // Modulus N = p*q
+ || ((result[0] = bin_from_bn(env, e)) == atom_error)
+ || ((result[1] = bin_from_bn(env, n)) == atom_error)
+ )
goto err;
- *ret = enif_make_list_from_array(env, result, 2);
- RSA_free(rsa);
+ *ret = enif_make_list_from_array(env, result, 2);
+ if (e) BN_free(e);
+ if (n) BN_free(n);
return 1;
err:
- if (rsa)
- RSA_free(rsa);
+ if (e) BN_free(e);
+ if (n) BN_free(n);
return 0;
+
}
+#endif /* #else-part of #if !defined(HAS_3_0_API) (That is, end of defined(HAS_3_0_API)) */
+
+
ERL_NIF_TERM rsa_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
/* RSA key generation can take a long time (>1 sec for a large
diff --git a/lib/crypto/configure b/lib/crypto/configure
index 5033d0a33b..14e09d20fb 100755
--- a/lib/crypto/configure
+++ b/lib/crypto/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +430,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +459,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +503,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +517,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +534,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,52 +606,49 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
ac_unique_file="vsn.mk"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
+CRYPTO_NO_DEPRECATE_WARN
DISABLE_OTP_TEST_ENGINE
DISABLE_EVP_HMAC
DISABLE_EVP_DH
@@ -633,6 +661,8 @@ SSL_FLAGS
SSL_LIBDIR
SSL_INCDIR
SSL_INCLUDE
+EGREP
+GREP
DED_OSTYPE
DED_LIBS
DED_WERRORFLAGS
@@ -646,8 +676,6 @@ DED_EXT
DED_GCC
DED_CC
DED_THR_DEFS
-EGREP
-GREP
MIXED_MINGW
MIXED_VC
OBJEXT
@@ -690,6 +718,10 @@ STATIC_CFLAGS
CFLAGS
CC
ERL_TOP
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -749,7 +781,6 @@ enable_dynamic_ssl_lib
enable_evp_dh
enable_evp_hmac
enable_otp_test_engine
-enable_deprecated_warnings
enable_fips
'
ac_precious_vars='build_alias
@@ -860,8 +891,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -902,9 +931,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -928,9 +957,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1141,9 +1170,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1157,9 +1186,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1203,9 +1232,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1221,7 +1250,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1285,7 +1314,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1403,6 +1432,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1426,10 +1456,6 @@ Optional Features:
Disable build of the otp_test_engine. (default is
--enable-otp-test-engine, unless for LibreSSL >=
3.5.0 where default is --disable-otp-test-engine)
- --disable-deprecated-warnings
- disable warnings for deprecated functions in
- cryptolib (default is to warn, except for OpenSSL
- 3.x where the default is not to warn)
--enable-fips enable OpenSSL FIPS mode support
--disable-fips disable OpenSSL FIPS mode support (default)
@@ -1550,9 +1576,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1580,7 +1606,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1588,7 +1615,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1598,9 +1625,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1617,14 +1644,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1632,14 +1659,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1655,14 +1683,14 @@ fi
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1670,17 +1698,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1701,11 +1730,12 @@ fi
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -1713,16 +1743,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -1740,156 +1763,66 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-} # ac_fn_c_check_header_mongrel
+} # ac_fn_c_check_header_compile
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
@@ -1899,25 +1832,26 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
@@ -1928,37 +1862,6 @@ fi
} # ac_fn_c_try_run
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
-
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@@ -1973,7 +1876,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -1983,14 +1886,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2000,9 +1904,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -2010,14 +1915,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -2027,14 +1932,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -2044,9 +1950,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -2054,14 +1961,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -2069,7 +1976,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2079,12 +1986,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -2094,12 +2002,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -2127,9 +2035,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -2141,14 +2050,124 @@ rm -f conftest.val
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
+# ------------------------------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
+ac_fn_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+printf %s "checking whether $as_decl_name is declared... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ eval ac_save_FLAGS=\$$6
+ as_fn_append $6 " $5"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ eval $6=\$ac_save_FLAGS
+
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_check_decl
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2181,8 +2200,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2217,7 +2240,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2252,11 +2275,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2267,8 +2292,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2292,7 +2317,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2300,14 +2325,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2315,15 +2340,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2331,8 +2356,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2346,63 +2371,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2412,19 +2422,434 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2435,12 +2860,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2449,24 +2874,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2476,11 +2901,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2494,62 +2920,125 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-## Delete previous failed configure results
-if test -f ./CONF_INFO; then
- rm ./CONF_INFO
-fi
-ac_aux_dir=
-for ac_dir in ${ERL_TOP}/erts/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in ${ERL_TOP}/erts/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2568,21 +3057,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2601,10 +3091,108 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
+fi
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2657,6 +3245,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+## Delete previous failed configure results
+if test -f ./CONF_INFO; then
+ rm ./CONF_INFO
+fi
+
if test "$cross_compiling" = "yes"; then
CROSS_COMPILING=yes
else
@@ -2675,6 +3268,15 @@ else
fi
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2683,11 +3285,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2695,11 +3298,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2710,11 +3317,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2723,11 +3330,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2735,11 +3343,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2750,11 +3362,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2762,8 +3374,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2776,11 +3388,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2788,11 +3401,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2803,11 +3420,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2816,11 +3433,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2829,15 +3447,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2853,18 +3475,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2875,11 +3497,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2887,11 +3510,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2902,11 +3529,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2919,11 +3546,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2931,11 +3559,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2946,11 +3578,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2962,34 +3594,138 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -2999,7 +3735,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -3007,7 +3743,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3019,9 +3755,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -3042,11 +3778,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -3063,7 +3800,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -3079,44 +3816,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -3130,15 +3869,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -3147,7 +3886,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3159,8 +3898,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -3168,10 +3907,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -3179,39 +3918,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3225,11 +3965,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -3238,31 +3979,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3272,29 +4014,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3303,57 +4049,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3368,94 +4117,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3475,543 +4274,180 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+done
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-done
-
-
-
NEED_NPTL_PTHREAD_H=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
-$as_echo_n "checking for native win32 threads... " >&6; }
-if test "X$host_os" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
+printf %s "checking for native win32 threads... " >&6; }
+if test "X$host_os" = "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
THR_LIB_TYPE=posix_unknown
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4020,40 +4456,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pthread_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_pthread_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
THR_LIBS="-lpthread"
fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
-$as_echo_n "checking for pthread_create in -lc_r... " >&6; }
-if ${ac_cv_lib_c_r_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
+printf %s "checking for pthread_create in -lc_r... " >&6; }
+if test ${ac_cv_lib_c_r_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4062,96 +4500,112 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_c_r_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_c_r_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
-$as_echo "$ac_cv_lib_c_r_pthread_create" >&6; }
-if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_c_r_pthread_create" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_create" = xyes
+then :
THR_LIBS="-lc_r"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
-if test "x$ac_cv_func_pthread_create" = xyes; then :
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes
+then :
THR_LIBS="none_needed"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
-$as_echo_n "checking if the '-pthread' switch can be used... " >&6; }
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
+printf %s "checking if the '-pthread' switch can be used... " >&6; }
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -pthread"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_create((void*)0,(void*)0,(void*)0,(void*)0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
THR_DEFS="-pthread"
THR_LIBS="-pthread"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_cflags
if test "x$THR_LIBS" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- fi
- if test "x$THR_LIBS" != "x"; then
+fi
+
+ if test "x$THR_LIBS" != "x"
+then :
+
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ case $host_os in #(
+ solaris*) :
+
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ;; #(
+ linux*) :
+
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
-if test "$cross_compiling" != "yes"; then
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -4159,11 +4613,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4175,23 +4633,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -4199,11 +4660,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4215,25 +4680,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -4244,11 +4712,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4260,11 +4732,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4273,11 +4745,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -4288,11 +4761,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4304,11 +4781,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -4316,8 +4793,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -4326,11 +4803,13 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
+fi
+
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
-$as_echo_n "checking for Native POSIX Thread Library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
+printf %s "checking for Native POSIX Thread Library... " >&6; }
libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
if test $? -eq 0; then
case "$libpthr_vsn" in
@@ -4346,24 +4825,28 @@ $as_echo_n "checking for Native POSIX Thread Library... " >&6; }
else
nptl=no
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
-$as_echo "$nptl" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
+printf "%s\n" "$nptl" >&6; }
if test $nptl = cross; then
nptl=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
- if test $nptl = yes; then
+ if test $nptl = yes
+then :
+
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- ac_fn_c_check_header_mongrel "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_nptl_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_nptl_pthread_h" = xyes
+then :
need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes
fi
+ if test $need_nptl_incldir = yes
+then :
- if test $need_nptl_incldir = yes; then
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -4384,13 +4867,13 @@ fi
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
nptl_incldir=$dir/nptl
fi
-
if test "x$nptl_incldir" != "x"; then
THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
break
@@ -4399,38 +4882,43 @@ fi
if test "x$nptl_incldir" = "x"; then
as_fn_error $? "Failed to locate nptl system include directory" "$LINENO" 5
fi
- fi
- fi
- ;;
- *) ;;
- esac
+
+fi
+
+fi
+ ;; #(
+ *) :
+ ;;
+esac
saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $THR_DEFS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
-$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
CPPFLAGS=$saved_cppflags
- fi
+
+fi
+
fi
@@ -4474,181 +4962,253 @@ case "$host_cpu" in
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WARN_FLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=return-type $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=implicit $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=implicit $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=undef $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=undef $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$DED_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
DED_INCLUDE=$DED_SYS_INCLUDE
DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Use -fno-common for gcc, that is link error if multiple definitions of
# global variables are encountered. This is ISO C compliant.
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-common $DED_CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_CFLAGS="-fno-common $DED_CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)... " >&6; }
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="-fno-strict-aliasing $DED_CFLAGS";
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ can_enable_flag=true
+else $as_nop
+ can_enable_flag=false
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$saved_CFLAGS;
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ DED_CFLAGS="-fno-strict-aliasing $DED_CFLAGS"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_STATIC_CFLAGS="$DED_CFLAGS"
DED_CFLAGS="$DED_CFLAGS -fPIC"
# Remove -fPIE and -fno-PIE
DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
+
fi
DED_EXT=so
@@ -4735,17 +5295,19 @@ case $host_os in
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4754,14 +5316,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
case "$ac_cv_sizeof_void_p" in
@@ -4828,11 +5388,12 @@ test "$DED_LDFLAGS_CONFTEST" != "" || DED_LDFLAGS_CONFTEST="$DED_LDFLAGS"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$DED_LD"; then
ac_cv_prog_DED_LD="$DED_LD" # Let the user override the test.
else
@@ -4840,11 +5401,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DED_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4855,11 +5420,11 @@ fi
fi
DED_LD=$ac_cv_prog_DED_LD
if test -n "$DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4868,11 +5433,12 @@ if test -z "$ac_cv_prog_DED_LD"; then
ac_ct_DED_LD=$DED_LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_DED_LD"; then
ac_cv_prog_ac_ct_DED_LD="$ac_ct_DED_LD" # Let the user override the test.
else
@@ -4880,11 +5446,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DED_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4895,11 +5465,11 @@ fi
fi
ac_ct_DED_LD=$ac_cv_prog_ac_ct_DED_LD
if test -n "$ac_ct_DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
-$as_echo "$ac_ct_DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
+printf "%s\n" "$ac_ct_DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DED_LD" = x; then
@@ -4907,8 +5477,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DED_LD=$ac_ct_DED_LD
@@ -4919,37 +5489,37 @@ fi
test "$DED_LD" != "false" || as_fn_error $? "No linker found" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
-$as_echo_n "checking for static compiler flags... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
+printf %s "checking for static compiler flags... " >&6; }
DED_STATIC_CFLAGS="$DED_WERRORFLAGS $DED_WFLAGS $DED_THR_DEFS $DED_STATIC_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
-$as_echo "$DED_STATIC_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
-$as_echo_n "checking for basic compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
+printf "%s\n" "$DED_STATIC_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
+printf %s "checking for basic compiler flags for loadable drivers... " >&6; }
DED_BASIC_CFLAGS=$DED_CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
-$as_echo_n "checking for compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
+printf %s "checking for compiler flags for loadable drivers... " >&6; }
DED_CFLAGS="$DED_WERRORFLAGS $DED_WARN_FLAGS $DED_THR_DEFS $DED_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
-$as_echo_n "checking for linker for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
-$as_echo_n "checking for linker flags for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
-$as_echo "$DED_LDFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
-$as_echo_n "checking for 'runtime library path' linker flag... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
+printf %s "checking for linker for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
+printf %s "checking for linker flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
+printf "%s\n" "$DED_LDFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
+printf %s "checking for 'runtime library path' linker flag... " >&6; }
if test "x$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
-$as_echo "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
+printf "%s\n" "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
fi
@@ -4972,8 +5542,8 @@ fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for multiarch directory" >&5
-$as_echo_n "checking for multiarch directory... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for multiarch directory" >&5
+printf %s "checking for multiarch directory... " >&6; }
multiarch_dir=
if test "$GCC" = "yes"; then
multiarch_dir=`$CC $CFLAGS -print-multiarch 2>/dev/null`
@@ -4982,11 +5552,11 @@ if test "$GCC" = "yes"; then
fi
fi
if test "$multiarch_dir" = ""; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $multiarch_dir" >&5
-$as_echo "$multiarch_dir" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $multiarch_dir" >&5
+printf "%s\n" "$multiarch_dir" >&6; }
fi
@@ -4994,17 +5564,19 @@ fi
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -5013,29 +5585,43 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
-std_ssl_locations="/usr/local /usr/sfw /usr /opt/local /usr/pkg /usr/local/openssl /usr/local/opt/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /"
+std_ssl_locations="\
+/usr/local \
+/usr/sfw \
+/usr \
+/opt/local \
+/usr/pkg \
+/usr/local/openssl \
+/usr/local/opt/openssl \
+/opt/homebrew/opt/openssl \
+/usr/lib/openssl \
+/usr/openssl \
+/usr/local/ssl \
+/usr/lib/ssl \
+/usr/ssl \
+/"
# Check whether --with-ssl was given.
-if test "${with_ssl+set}" = set; then :
+if test ${with_ssl+y}
+then :
withval=$with_ssl;
fi
# Check whether --with-ssl-lib-subdir was given.
-if test "${with_ssl_lib_subdir+set}" = set; then :
+if test ${with_ssl_lib_subdir+y}
+then :
withval=$with_ssl_lib_subdir;
case "$with_ssl_lib_subdir" in
yes|no)
@@ -5045,104 +5631,99 @@ case "$with_ssl_lib_subdir" in
;;
esac
-else
+else $as_nop
with_ssl_lib_subdir=
fi
#default
# Check whether --with-ssl-incl was given.
-if test "${with_ssl_incl+set}" = set; then :
+if test ${with_ssl_incl+y}
+then :
withval=$with_ssl_incl;
case X$with_ssl in
X | Xyes | Xno) as_fn_error $? "--with-ssl-incl=PATH set without --with-ssl=PATH" "$LINENO" 5;;
esac
-else
+else $as_nop
with_ssl_incl=$with_ssl
fi
#default
# Check whether --with-ssl-zlib was given.
-if test "${with_ssl_zlib+set}" = set; then :
+if test ${with_ssl_zlib+y}
+then :
withval=$with_ssl_zlib;
-else
+else $as_nop
with_ssl_zlib=default
fi
#default
# Check whether --with-ssl-rpath was given.
-if test "${with_ssl_rpath+set}" = set; then :
+if test ${with_ssl_rpath+y}
+then :
withval=$with_ssl_rpath;
case X$with_ssl in
Xno) as_fn_error $? "--with-ssl-rpath set without --with-ssl" "$LINENO" 5;;
esac
-else
+else $as_nop
with_ssl_rpath=default
fi
#default
# Check whether --enable-dynamic-ssl-lib was given.
-if test "${enable_dynamic_ssl_lib+set}" = set; then :
+if test ${enable_dynamic_ssl_lib+y}
+then :
enableval=$enable_dynamic_ssl_lib; case "$enableval" in
no) enable_dynamic_ssl=no ;;
*) enable_dynamic_ssl=yes ;;
esac
-else
+else $as_nop
enable_dynamic_ssl=undefined
fi
# Check whether --enable-evp-dh was given.
-if test "${enable_evp_dh+set}" = set; then :
+if test ${enable_evp_dh+y}
+then :
enableval=$enable_evp_dh; case "$enableval" in
no) DISABLE_EVP_DH=1;;
*) DISABLE_EVP_DH=0;;
esac
-else
+else $as_nop
DISABLE_EVP_DH=0
fi
# Check whether --enable-evp-hmac was given.
-if test "${enable_evp_hmac+set}" = set; then :
+if test ${enable_evp_hmac+y}
+then :
enableval=$enable_evp_hmac; case "$enableval" in
no) DISABLE_EVP_HMAC=1;;
*) DISABLE_EVP_HMAC=0;;
esac
-else
+else $as_nop
DISABLE_EVP_HMAC=0
fi
-
# Check whether --enable-otp-test-engine was given.
-if test "${enable_otp_test_engine+set}" = set; then :
+if test ${enable_otp_test_engine+y}
+then :
enableval=$enable_otp_test_engine; case "$enableval" in
no) DISABLE_OTP_TEST_ENGINE=yes;;
*) DISABLE_OTP_TEST_ENGINE=no;;
esac
-else
+else $as_nop
DISABLE_OTP_TEST_ENGINE=default
fi
-# Check whether --enable-deprecated_warnings was given.
-if test "${enable_deprecated_warnings+set}" = set; then :
- enableval=$enable_deprecated_warnings; case "$enableval" in
- no) deprecated_warnings=no;;
- *) deprecated_warnings=yes;;
- esac
-else
- deprecated_warnings=default_yes
-fi
-
-
@@ -5170,8 +5751,8 @@ case "$with_ssl_zlib" in
no)
;;
default | yes)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for static zlib" >&5
-$as_echo_n "checking for static zlib... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for static zlib" >&5
+printf %s "checking for static zlib... " >&6; }
for dir in $std_ssl_locations; do
for sdir in $search_subdirs; do
if test -f "$erl_xcomp_sysroot$dir/$sdir/libz.a"; then
@@ -5181,8 +5762,8 @@ $as_echo_n "checking for static zlib... " >&6; }
done
test "$static_zlib" = "no" || break
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $static_zlib" >&5
-$as_echo "$static_zlib" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $static_zlib" >&5
+printf "%s\n" "$static_zlib" >&6; }
if test $with_ssl_zlib = yes; then
if test $static_zlib = no; then
as_fn_error $? "linking with zlib requested by user, but no such library was found" "$LINENO" 5
@@ -5191,8 +5772,8 @@ $as_echo "$static_zlib" >&6; }
static_zlib=no
fi;;
*) # PATH
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for static zlib" >&5
-$as_echo_n "checking for static zlib... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for static zlib" >&5
+printf %s "checking for static zlib... " >&6; }
if test -f "$with_ssl_zlib/libz.a"; then
forced_static_zlib="$with_ssl_zlib/libz.a"
else
@@ -5206,8 +5787,8 @@ $as_echo_n "checking for static zlib... " >&6; }
if test "$forced_static_zlib" = ""; then
as_fn_error $? "linking with zlib requested by user, but no such library was found in $with_ssl_zlib" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $forced_static_zlib" >&5
-$as_echo "$forced_static_zlib" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $forced_static_zlib" >&5
+printf "%s\n" "$forced_static_zlib" >&6; }
;;
esac
@@ -5226,43 +5807,330 @@ case $enable_dynamic_ssl in
SSL_DYNAMIC_ONLY=no;;
esac
-case "$erl_xcomp_without_sysroot-$with_ssl" in
- yes-* | no-no)
- SSL_APP=
- CRYPTO_APP=
- SSH_APP=
- if test "$with_ssl" != "no"; then
- skip="Cannot search for ssl; missing cross system root (erl_xcomp_sysroot)."
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
fi
- for a in ssl crypto ssh; do
- echo "$skip" > $ERL_TOP/lib/$a/SKIP
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
done
- ;;
- no-yes | no- )
- # We search for OpenSSL in the common OS standard locations.
- SSL_APP=ssl
- CRYPTO_APP=crypto
- SSH_APP=ssh
-
- if test "$host_os" = "win32" ; then
- if test "x$ac_cv_sizeof_void_p" = "x8"; then
- std_win_ssl_locations="/mnt/c/OpenSSL-Win64 /c/OpenSSL-Win64 /mnt/c/opt/local64/pgm/OpenSSL /opt/local64/pgm/OpenSSL /cygdrive/c/OpenSSL-Win64"
- lib_bits=64
- else
- std_win_ssl_locations="/mnt/c/OpenSSL-Win32 /c/OpenSSL-Win32 /mnt/c/OpenSSL /c/OpenSSL /cygdrive/c/OpenSSL /opt/local/pgm/OpenSSL /opt/local32/pgm/OpenSSL /mnt/c/opt/local/pgm/OpenSSL /mnt/c/opt/local32/pgm/OpenSSL /cygdrive/c/OpenSSL-Win32"
- lib_bits=32
- fi
- else
- std_win_ssl_locations=""
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
- usable_crypto=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL crypto library with version >= 0.9.8c in standard locations" >&5
-$as_echo_n "checking for OpenSSL crypto library with version >= 0.9.8c in standard locations... " >&6; }
- for rdir in $std_win_ssl_locations $std_ssl_locations; do
- if test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"; then
- SSL_INCDIR="$erl_xcomp_isysroot$rdir"
- SSL_INCLUDE="-I$SSL_INCDIR/include"
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+case "$erl_xcomp_without_sysroot-$with_ssl" in #(
+ yes-* | no-no) :
+
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ if test "$with_ssl" != "no"; then
+ skip="Cannot search for ssl; missing cross system root (erl_xcomp_sysroot)."
+ fi
+ for a in ssl crypto ssh; do
+ echo "$skip" > $ERL_TOP/lib/$a/SKIP
+ done
+ ;; #(
+ no-yes | no-) :
+
+ # We search for OpenSSL in the common OS standard locations.
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+
+ if test "$host_os" != "win32"
+then :
+
+ std_win_ssl_locations=
+
+else $as_nop
+
+ if test "x$ac_cv_sizeof_void_p" = "x8"
+then :
+
+ std_win_ssl_locations="/mnt/c/OpenSSL-Win64 /c/OpenSSL-Win64 /mnt/c/opt/local64/pgm/OpenSSL /opt/local64/pgm/OpenSSL /cygdrive/c/OpenSSL-Win64"
+
+else $as_nop
+
+ std_win_ssl_locations="/mnt/c/OpenSSL-Win32 /c/OpenSSL-Win32 /mnt/c/OpenSSL /c/OpenSSL /cygdrive/c/OpenSSL /opt/local/pgm/OpenSSL /opt/local32/pgm/OpenSSL /mnt/c/opt/local/pgm/OpenSSL /mnt/c/opt/local32/pgm/OpenSSL /cygdrive/c/OpenSSL-Win32"
+
+fi
+
+fi
+
+ usable_crypto=no
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL crypto library with version >= 0.9.8c in standard locations" >&5
+printf %s "checking for OpenSSL crypto library with version >= 0.9.8c in standard locations... " >&6; }
+ for rdir in $std_win_ssl_locations $std_ssl_locations; do
+ if test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"
+then :
+
+ SSL_INCDIR="$erl_xcomp_isysroot$rdir"
+ SSL_INCLUDE="-I$SSL_INCDIR/include"
# Check for static and dynamic crypto library in the directory
# given as argument...
@@ -5296,12 +6164,13 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes.?$" >/dev/null 2>&1; then :
+ $EGREP "^yes.?$" >/dev/null 2>&1
+then :
valid_include=yes
-else
+else $as_nop
valid_include=no
fi
-rm -f conftest*
+rm -rf conftest*
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5313,15 +6182,17 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes.?$" >/dev/null 2>&1; then :
+ $EGREP "^yes.?$" >/dev/null 2>&1
+then :
v3_include=yes
-else
+else $as_nop
v3_include=no
fi
-rm -f conftest*
+rm -rf conftest*
+
-if test "x$DISABLE_OTP_TEST_ENGINE" = "xdefault"; then
+ if test "x$DISABLE_OTP_TEST_ENGINE" = "xdefault"; then
# Get default value for the --disable-otp-test-engine. Depends on cryptolib version
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5333,74 +6204,115 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes.?$" >/dev/null 2>&1; then :
+ $EGREP "^yes.?$" >/dev/null 2>&1
+then :
DISABLE_OTP_TEST_ENGINE=yes
-else
+else $as_nop
DISABLE_OTP_TEST_ENGINE=no
fi
-rm -f conftest*
+rm -rf conftest*
fi
CPPFLAGS="$save_CPPFLAGS"
- if test $valid_include != yes; then
- static_crypto_lib_name=
- static_ssl_lib_name=
- static_extra_libs=
- static_lib_dir=
- dynamic_crypto_lib_name=
- dynamic_ssl_lib_name=
- dynamic_extra_libs=
- dynamic_lib_dir=
- dynamic_runtime_lib_dir=
- elif test "$host_os" = "win32" ; then
- if test -f "$dir/lib/VC/static/libcrypto${lib_bits}MD.lib"; then
- static_crypto_lib_name=libcrypto${lib_bits}MD
- static_ssl_lib_name="libssl${lib_bits}MD"
- static_extra_libs="$static_extra_libs -lCRYPT32 -lWS2_32"
- static_lib_dir="$dir/lib/VC/static"
- found_static_lib=yes
- fi
- if test -f "$dir/lib/VC/libcrypto${lib_bits}MD.lib"; then
- dynamic_crypto_lib_name=libcrypto${lib_bits}MD
- dynamic_ssl_lib_name="libssl${lib_bits}MD"
- dynamic_runtime_lib_dir="$rdir/lib/VC"
- dynamic_lib_dir="$dir/lib/VC"
- found_dynamic_lib=yes
- fi
- else # Non windows...
-
- case "$host_os" in
- darwin*)
- static_ext=.a
- dynamic_ext=.dylib;;
- *)
- static_ext=.a
- dynamic_ext=.so;;
- esac
- for sdir in $search_subdirs; do
- if test -f "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"; then
- found_dynlib=yes
- else
- found_dynlib=no
- case $host_os in
- openbsd*)
- # libcrypto.so got a suffix on (at least some) openbsd.
- # If we find libcrypto.so with suffix, we try to link
- # to it using -lcrypto ...
- for f in "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"*; do
- test -f "$f" && found_dynlib=yes
- break
- done;;
- *)
- ;;
- esac
- fi
- if test $found_dynlib = yes; then
- # Found dynamic library; check if it links...
- dynamic_lib_dir="$dir/$sdir"
- dynamic_runtime_lib_dir="$rdir/$sdir"
+ if test $valid_include != yes
+then :
+
+ # Not a valid include...
+ static_crypto_lib_name=
+ static_ssl_lib_name=
+ static_extra_libs=
+ static_lib_dir=
+ dynamic_crypto_lib_name=
+ dynamic_ssl_lib_name=
+ dynamic_extra_libs=
+ dynamic_lib_dir=
+ dynamic_runtime_lib_dir=
+
+elif test "$host_os" = "win32"
+then :
+
+ # Windows...
+ if test "x$ac_cv_sizeof_void_p" = "x8"
+then :
+
+ lib_bits=64
+
+else $as_nop
+
+ lib_bits=32
+
+fi
+ if test -f "$dir/lib/VC/static/libcrypto${lib_bits}MD.lib"
+then :
+
+ static_crypto_lib_name=libcrypto${lib_bits}MD
+ static_ssl_lib_name="libssl${lib_bits}MD"
+ static_extra_libs="$static_extra_libs -lCRYPT32 -lWS2_32"
+ static_lib_dir="$dir/lib/VC/static"
+ found_static_lib=yes
+
+fi
+ if test -f "$dir/lib/VC/libcrypto${lib_bits}MD.lib"
+then :
+
+ dynamic_crypto_lib_name=libcrypto${lib_bits}MD
+ dynamic_ssl_lib_name="libssl${lib_bits}MD"
+ dynamic_runtime_lib_dir="$rdir/lib/VC"
+ dynamic_lib_dir="$dir/lib/VC"
+ found_dynamic_lib=yes
+
+fi
+
+else $as_nop
+
+ # Not windows...
+ case "$host_os" in #(
+ darwin*) :
+
+ static_ext=.a
+ dynamic_ext=.dylib
+ ;; #(
+ *) :
+
+ static_ext=.a
+ dynamic_ext=.so
+ ;;
+esac
+ for sdir in $search_subdirs; do
+ if test -f "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"
+then :
+
+ found_dynlib=yes
+
+else $as_nop
+
+ found_dynlib=no
+ case $host_os in #(
+ openbsd*) :
+
+ # libcrypto.so got a suffix on (at least some) openbsd.
+ # If we find libcrypto.so with suffix, we try to link
+ # to it using -lcrypto ...
+ for f in "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"*; do
+ if test -f "$f"
+then :
+ found_dynlib=yes; break
+fi
+ done
+ ;; #(
+ *) :
+ ;;
+esac
+
+fi
+ if test $found_dynlib = yes
+then :
+
+ # Found dynamic library; check if it links...
+ dynamic_lib_dir="$dir/$sdir"
+ dynamic_runtime_lib_dir="$rdir/$sdir"
test_cflags="-I$idir/include"
test_ldflags="-L$dynamic_lib_dir"
@@ -5420,7 +6332,7 @@ rm -f conftest*
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5429,25 +6341,28 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_dynamic_lib=yes
-else
+else $as_nop
found_dynamic_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- if test $found_dynamic_lib = no -a $static_zlib != no; then
- # No, but linking with zlib as well might help...
- dynamic_extra_libs="$dynamic_extra_libs $static_zlib"
+ if test $found_dynamic_lib = no -a $static_zlib != no
+then :
+
+ # No, but linking with zlib as well might help...
+ dynamic_extra_libs="$dynamic_extra_libs $static_zlib"
test_cflags="-I$idir/include"
test_ldflags="-L$dynamic_lib_dir"
@@ -5467,7 +6382,7 @@ rm -f core conftest.err conftest.$ac_objext \
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5476,27 +6391,32 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_dynamic_lib=yes
-else
+else $as_nop
found_dynamic_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- fi
- fi
- if test -f "$dir/$sdir/lib$static_crypto_lib_name$static_ext"; then
- # Found static library; check if it links...
- static_lib_dir="$dir/$sdir"
+
+fi
+
+fi
+ if test -f "$dir/$sdir/lib$static_crypto_lib_name$static_ext"
+then :
+
+ # Found static library; check if it links...
+ static_lib_dir="$dir/$sdir"
test_cflags="-I$idir/include"
test_ldflags=
@@ -5516,7 +6436,7 @@ rm -f core conftest.err conftest.$ac_objext \
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5525,25 +6445,28 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_static_lib=yes
-else
+else $as_nop
found_static_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- if test $found_static_lib = no -a $static_zlib != no; then
- # No, but inking with zlib as well might help...
- static_extra_libs="$static_extra_libs $static_zlib"
+ if test $found_static_lib = no -a $static_zlib != no
+then :
+
+ # No, but inking with zlib as well might help...
+ static_extra_libs="$static_extra_libs $static_zlib"
test_cflags="-I$idir/include"
test_ldflags=
@@ -5563,7 +6486,7 @@ rm -f core conftest.err conftest.$ac_objext \
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5572,124 +6495,156 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_static_lib=yes
-else
+else $as_nop
found_static_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- fi
- fi
- if test $found_static_lib = yes -o $found_dynamic_lib = yes; then
- break
- fi
- done
- fi
- case $enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib in
- no-*-no)
- ;; # Dynamic linking against ssl library disabled by user, and no static library found
- yes-no-*)
- ;; # Static linking against ssl library disabled by user, and no dynamic library found
- *-no-no)
- ;; # Neither static nor dynamic ssl library found
- no-*-yes | default_no-*-yes | default_yes-no-yes)
- # Link statically...
- SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
- SSL_SSL_LIBNAME=$static_ssl_lib_name
- SSL_LIBDIR="$static_lib_dir"
- SSL_EXTRA_LIBS="$static_extra_libs"
- SSL_RUNTIME_LIBDIR=
- SSL_DYNAMIC_ONLY=no
- usable_crypto=yes
- break;;
- *-yes-*)
- # Link dynamically...
- SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
- SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
- SSL_EXTRA_LIBS="$dynamic_extra_libs"
- SSL_LIBDIR="$dynamic_lib_dir"
- SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
- SSL_DYNAMIC_ONLY=yes
- usable_crypto=yes
- break;;
- esac
- fi
- done
+fi
- if test $usable_crypto = yes ; then
- if test $SSL_DYNAMIC_ONLY = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
-$as_echo "dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
-$as_echo "static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
- fi
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- SSL_APP=
- CRYPTO_APP=
- SSH_APP=
-
- SSL_INCDIR=
- SSL_INCLUDE=
- SSL_CRYPTO_LIBNAME=
- SSL_SSL_LIBNAME=
- SSL_INCDIR=
- SSL_RUNTIME_LIBDIR=
- SSL_LIBDIR=
-
- case "$with_ssl-$enable_dynamic_ssl" in
- yes-yes)
- as_fn_error $? "crypto library with dynamic linking requested by user, but no such library was found" "$LINENO" 5
- ;;
- yes-no)
- as_fn_error $? "crypto library with static linking requested by user, but no such library was found" "$LINENO" 5
- ;;
- yes-*)
- as_fn_error $? "crypto library requested by user, but no such library was found" "$LINENO" 5
- ;;
- *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No (usable) OpenSSL found, skipping ssl, ssh and crypto applications" >&5
-$as_echo "$as_me: WARNING: No (usable) OpenSSL found, skipping ssl, ssh and crypto applications" >&2;}
- ;;
- esac
+fi
+ if test $found_static_lib = yes -o $found_dynamic_lib = yes
+then :
+ break
+fi
+ done
+
+fi
+
+ case $enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib in #(
+ no-*-no) :
+
+ # Dynamic linking against ssl library disabled by user,
+ # and no static library found...
+ ;; #(
+ yes-no-*) :
+
+ # Static linking against ssl library disabled by user,
+ # and no dynamic library found...
+ ;; #(
+ *-no-no) :
+
+ # Neither static nor dynamic ssl library found...
+ ;; #(
+ no-*-yes | default_no-*-yes | default_yes-no-yes) :
+
+ # Link statically...
+ SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
+ SSL_SSL_LIBNAME=$static_ssl_lib_name
+ SSL_LIBDIR="$static_lib_dir"
+ SSL_EXTRA_LIBS="$static_extra_libs"
+ SSL_RUNTIME_LIBDIR=
+ SSL_DYNAMIC_ONLY=no
+ usable_crypto=yes
+ break
+ ;; #(
+ *-yes-*) :
+
+ # Link dynamically...
+ SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
+ SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
+ SSL_EXTRA_LIBS="$dynamic_extra_libs"
+ SSL_LIBDIR="$dynamic_lib_dir"
+ SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
+ SSL_DYNAMIC_ONLY=yes
+ usable_crypto=yes
+ break
+ ;; #(
+ *) :
+ ;;
+esac
- for a in ssl crypto ssh; do
- echo "No usable OpenSSL found" > $ERL_TOP/lib/$a/SKIP
- done
- fi
- ;;
- *)
- # Option given with PATH to package
- if test ! -d "$with_ssl" ; then
- as_fn_error $? "Invalid path to option --with-ssl=PATH" "$LINENO" 5
- fi
- if test ! -d "$with_ssl_incl" ; then
- as_fn_error $? "Invalid path to option --with-ssl-incl=PATH" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL header in $with_ssl_incl" >&5
-$as_echo_n "checking for OpenSSL header in $with_ssl_incl... " >&6; }
- if test -f "$with_ssl_incl/include/openssl/opensslv.h"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- else
- as_fn_error $? "no OpenSSL header found in $with_ssl_incl" "$LINENO" 5
- fi
- SSL_INCDIR="$with_ssl_incl"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL in $with_ssl" >&5
-$as_echo_n "checking for OpenSSL in $with_ssl... " >&6; }
+fi
+ done
+
+ if test $usable_crypto = yes
+then :
+ if test $SSL_DYNAMIC_ONLY = yes
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
+printf "%s\n" "dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
+printf "%s\n" "static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
+fi
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+
+ SSL_INCDIR=
+ SSL_INCLUDE=
+ SSL_CRYPTO_LIBNAME=
+ SSL_SSL_LIBNAME=
+ SSL_INCDIR=
+ SSL_RUNTIME_LIBDIR=
+ SSL_LIBDIR=
+
+ case "$with_ssl-$enable_dynamic_ssl" in #(
+ yes-yes) :
+
+ as_fn_error $? "crypto library with dynamic linking requested by user, but no such library was found" "$LINENO" 5
+ ;; #(
+ yes-no) :
+
+ as_fn_error $? "crypto library with static linking requested by user, but no such library was found" "$LINENO" 5
+ ;; #(
+ yes-*) :
+
+ as_fn_error $? "crypto library requested by user, but no such library was found" "$LINENO" 5
+ ;; #(
+ *) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No (usable) OpenSSL found, skipping ssl, ssh and crypto applications" >&5
+printf "%s\n" "$as_me: WARNING: No (usable) OpenSSL found, skipping ssl, ssh and crypto applications" >&2;}
+ ;;
+esac
+
+ for a in ssl crypto ssh; do
+ echo "No usable OpenSSL found" > $ERL_TOP/lib/$a/SKIP
+ done
+
+fi
+ ;; #(
+ *) :
+
+ # Option given with PATH to package
+ if test ! -d "$with_ssl"
+then :
+ as_fn_error $? "Invalid path to option --with-ssl=PATH" "$LINENO" 5
+fi
+ if test ! -d "$with_ssl_incl"
+then :
+ as_fn_error $? "Invalid path to option --with-ssl-incl=PATH" "$LINENO" 5
+fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL header in $with_ssl_incl" >&5
+printf %s "checking for OpenSSL header in $with_ssl_incl... " >&6; }
+ if test -f "$with_ssl_incl/include/openssl/opensslv.h"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
+ as_fn_error $? "no OpenSSL header found in $with_ssl_incl" "$LINENO" 5
+fi
+ SSL_INCDIR="$with_ssl_incl"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL in $with_ssl" >&5
+printf %s "checking for OpenSSL in $with_ssl... " >&6; }
# Check for static and dynamic crypto library in the directory
# given as argument...
@@ -5723,12 +6678,13 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes.?$" >/dev/null 2>&1; then :
+ $EGREP "^yes.?$" >/dev/null 2>&1
+then :
valid_include=yes
-else
+else $as_nop
valid_include=no
fi
-rm -f conftest*
+rm -rf conftest*
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5740,15 +6696,17 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes.?$" >/dev/null 2>&1; then :
+ $EGREP "^yes.?$" >/dev/null 2>&1
+then :
v3_include=yes
-else
+else $as_nop
v3_include=no
fi
-rm -f conftest*
+rm -rf conftest*
+
-if test "x$DISABLE_OTP_TEST_ENGINE" = "xdefault"; then
+ if test "x$DISABLE_OTP_TEST_ENGINE" = "xdefault"; then
# Get default value for the --disable-otp-test-engine. Depends on cryptolib version
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5760,74 +6718,115 @@ yes
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "^yes.?$" >/dev/null 2>&1; then :
+ $EGREP "^yes.?$" >/dev/null 2>&1
+then :
DISABLE_OTP_TEST_ENGINE=yes
-else
+else $as_nop
DISABLE_OTP_TEST_ENGINE=no
fi
-rm -f conftest*
+rm -rf conftest*
fi
CPPFLAGS="$save_CPPFLAGS"
- if test $valid_include != yes; then
- static_crypto_lib_name=
- static_ssl_lib_name=
- static_extra_libs=
- static_lib_dir=
- dynamic_crypto_lib_name=
- dynamic_ssl_lib_name=
- dynamic_extra_libs=
- dynamic_lib_dir=
- dynamic_runtime_lib_dir=
- elif test "$host_os" = "win32" ; then
- if test -f "$dir/lib/VC/static/libcrypto${lib_bits}MD.lib"; then
- static_crypto_lib_name=libcrypto${lib_bits}MD
- static_ssl_lib_name="libssl${lib_bits}MD"
- static_extra_libs="$static_extra_libs -lCRYPT32 -lWS2_32"
- static_lib_dir="$dir/lib/VC/static"
- found_static_lib=yes
- fi
- if test -f "$dir/lib/VC/libcrypto${lib_bits}MD.lib"; then
- dynamic_crypto_lib_name=libcrypto${lib_bits}MD
- dynamic_ssl_lib_name="libssl${lib_bits}MD"
- dynamic_runtime_lib_dir="$rdir/lib/VC"
- dynamic_lib_dir="$dir/lib/VC"
- found_dynamic_lib=yes
- fi
- else # Non windows...
-
- case "$host_os" in
- darwin*)
- static_ext=.a
- dynamic_ext=.dylib;;
- *)
- static_ext=.a
- dynamic_ext=.so;;
- esac
- for sdir in $search_subdirs; do
- if test -f "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"; then
- found_dynlib=yes
- else
- found_dynlib=no
- case $host_os in
- openbsd*)
- # libcrypto.so got a suffix on (at least some) openbsd.
- # If we find libcrypto.so with suffix, we try to link
- # to it using -lcrypto ...
- for f in "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"*; do
- test -f "$f" && found_dynlib=yes
- break
- done;;
- *)
- ;;
- esac
- fi
- if test $found_dynlib = yes; then
- # Found dynamic library; check if it links...
- dynamic_lib_dir="$dir/$sdir"
- dynamic_runtime_lib_dir="$rdir/$sdir"
+ if test $valid_include != yes
+then :
+
+ # Not a valid include...
+ static_crypto_lib_name=
+ static_ssl_lib_name=
+ static_extra_libs=
+ static_lib_dir=
+ dynamic_crypto_lib_name=
+ dynamic_ssl_lib_name=
+ dynamic_extra_libs=
+ dynamic_lib_dir=
+ dynamic_runtime_lib_dir=
+
+elif test "$host_os" = "win32"
+then :
+
+ # Windows...
+ if test "x$ac_cv_sizeof_void_p" = "x8"
+then :
+
+ lib_bits=64
+
+else $as_nop
+
+ lib_bits=32
+
+fi
+ if test -f "$dir/lib/VC/static/libcrypto${lib_bits}MD.lib"
+then :
+
+ static_crypto_lib_name=libcrypto${lib_bits}MD
+ static_ssl_lib_name="libssl${lib_bits}MD"
+ static_extra_libs="$static_extra_libs -lCRYPT32 -lWS2_32"
+ static_lib_dir="$dir/lib/VC/static"
+ found_static_lib=yes
+
+fi
+ if test -f "$dir/lib/VC/libcrypto${lib_bits}MD.lib"
+then :
+
+ dynamic_crypto_lib_name=libcrypto${lib_bits}MD
+ dynamic_ssl_lib_name="libssl${lib_bits}MD"
+ dynamic_runtime_lib_dir="$rdir/lib/VC"
+ dynamic_lib_dir="$dir/lib/VC"
+ found_dynamic_lib=yes
+
+fi
+
+else $as_nop
+
+ # Not windows...
+ case "$host_os" in #(
+ darwin*) :
+
+ static_ext=.a
+ dynamic_ext=.dylib
+ ;; #(
+ *) :
+
+ static_ext=.a
+ dynamic_ext=.so
+ ;;
+esac
+ for sdir in $search_subdirs; do
+ if test -f "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"
+then :
+
+ found_dynlib=yes
+
+else $as_nop
+
+ found_dynlib=no
+ case $host_os in #(
+ openbsd*) :
+
+ # libcrypto.so got a suffix on (at least some) openbsd.
+ # If we find libcrypto.so with suffix, we try to link
+ # to it using -lcrypto ...
+ for f in "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"*; do
+ if test -f "$f"
+then :
+ found_dynlib=yes; break
+fi
+ done
+ ;; #(
+ *) :
+ ;;
+esac
+
+fi
+ if test $found_dynlib = yes
+then :
+
+ # Found dynamic library; check if it links...
+ dynamic_lib_dir="$dir/$sdir"
+ dynamic_runtime_lib_dir="$rdir/$sdir"
test_cflags="-I$idir/include"
test_ldflags="-L$dynamic_lib_dir"
@@ -5847,7 +6846,7 @@ rm -f conftest*
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5856,25 +6855,28 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_dynamic_lib=yes
-else
+else $as_nop
found_dynamic_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- if test $found_dynamic_lib = no -a $static_zlib != no; then
- # No, but linking with zlib as well might help...
- dynamic_extra_libs="$dynamic_extra_libs $static_zlib"
+ if test $found_dynamic_lib = no -a $static_zlib != no
+then :
+
+ # No, but linking with zlib as well might help...
+ dynamic_extra_libs="$dynamic_extra_libs $static_zlib"
test_cflags="-I$idir/include"
test_ldflags="-L$dynamic_lib_dir"
@@ -5894,7 +6896,7 @@ rm -f core conftest.err conftest.$ac_objext \
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5903,27 +6905,32 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_dynamic_lib=yes
-else
+else $as_nop
found_dynamic_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- fi
- fi
- if test -f "$dir/$sdir/lib$static_crypto_lib_name$static_ext"; then
- # Found static library; check if it links...
- static_lib_dir="$dir/$sdir"
+
+fi
+
+fi
+ if test -f "$dir/$sdir/lib$static_crypto_lib_name$static_ext"
+then :
+
+ # Found static library; check if it links...
+ static_lib_dir="$dir/$sdir"
test_cflags="-I$idir/include"
test_ldflags=
@@ -5943,7 +6950,7 @@ rm -f core conftest.err conftest.$ac_objext \
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5952,25 +6959,28 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_static_lib=yes
-else
+else $as_nop
found_static_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- if test $found_static_lib = no -a $static_zlib != no; then
- # No, but inking with zlib as well might help...
- static_extra_libs="$static_extra_libs $static_zlib"
+ if test $found_static_lib = no -a $static_zlib != no
+then :
+
+ # No, but inking with zlib as well might help...
+ static_extra_libs="$static_extra_libs $static_zlib"
test_cflags="-I$idir/include"
test_ldflags=
@@ -5990,7 +7000,7 @@ rm -f core conftest.err conftest.$ac_objext \
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -5999,191 +7009,280 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
found_static_lib=yes
-else
+else $as_nop
found_static_lib=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- fi
- fi
- if test $found_static_lib = yes -o $found_dynamic_lib = yes; then
- break
- fi
- done
- fi
- case $enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib in
- no-*-no)
- as_fn_error $? "dynamic linking against crypto library disabled by user, but no static library found in $with_ssl" "$LINENO" 5;;
- yes-no-*)
- as_fn_error $? "static linking against crypto library disabled by user, but no dynamic library found in $with_ssl" "$LINENO" 5;;
- *-no-no)
- as_fn_error $? "neither static nor dynamic crypto library found in $with_ssl" "$LINENO" 5;;
- no-*-yes | default_no-*-yes | default_yes-no-yes)
- # Link statically...
- SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
- SSL_SSL_LIBNAME=$static_ssl_lib_name
- SSL_LIBDIR="$static_lib_dir"
- SSL_EXTRA_LIBS="$static_extra_libs"
- SSL_RUNTIME_LIBDIR=
- SSL_DYNAMIC_ONLY=no;;
- *-yes-*)
- # Link dynamically...
- SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
- SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
- SSL_EXTRA_LIBS="$dynamic_extra_libs"
- SSL_LIBDIR="$dynamic_lib_dir"
- SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
- SSL_DYNAMIC_ONLY=yes;;
- esac
- if test $SSL_DYNAMIC_ONLY = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
-$as_echo "dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
-$as_echo "static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
- fi
- SSL_INCLUDE="-I$with_ssl_incl/include"
- SSL_APP=ssl
- CRYPTO_APP=crypto
- SSH_APP=ssh
- if test "$cross_compiling" = "yes"; then
- SSL_RUNTIME_LIBDIR=`echo "$SSL_LIBDIR" | sed -n "s|^$erl_xcomp_sysroot\(/*\)\(.*\)\$|/\2|p"`
- else
- SSL_RUNTIME_LIBDIR="$SSL_LIBDIR"
- fi
+fi
+
+fi
+ if test $found_static_lib = yes -o $found_dynamic_lib = yes
+then :
+ break
+fi
+ done
+
+fi
+
+ case $enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib in #(
+ no-*-no) :
+
+ as_fn_error $? "dynamic linking against crypto library disabled by user, but no static library found in $with_ssl" "$LINENO" 5
+ ;; #(
+ yes-no-*) :
+
+ as_fn_error $? "static linking against crypto library disabled by user, but no dynamic library found in $with_ssl" "$LINENO" 5
+ ;; #(
+ *-no-no) :
+
+ as_fn_error $? "neither static nor dynamic crypto library found in $with_ssl" "$LINENO" 5
+ ;; #(
+ no-*-yes | default_no-*-yes | default_yes-no-yes) :
+
+ # Link statically...
+ SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
+ SSL_SSL_LIBNAME=$static_ssl_lib_name
+ SSL_LIBDIR="$static_lib_dir"
+ SSL_EXTRA_LIBS="$static_extra_libs"
+ SSL_RUNTIME_LIBDIR=
+ SSL_DYNAMIC_ONLY=no
+ ;; #(
+ *-yes-*) :
+
+ # Link dynamically...
+ SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
+ SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
+ SSL_EXTRA_LIBS="$dynamic_extra_libs"
+ SSL_LIBDIR="$dynamic_lib_dir"
+ SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
+ SSL_DYNAMIC_ONLY=yes
+ ;; #(
+ *) :
+ ;;
esac
+ if test $SSL_DYNAMIC_ONLY = yes
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
+printf "%s\n" "dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&5
+printf "%s\n" "static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR" >&6; }
+fi
+ SSL_INCLUDE="-I$with_ssl_incl/include"
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+ if test "$cross_compiling" = "yes"
+then :
+
+ SSL_RUNTIME_LIBDIR=`echo "$SSL_LIBDIR" | sed -n "s|^$erl_xcomp_sysroot\(/*\)\(.*\)\$|/\2|p"`
+
+else $as_nop
+ SSL_RUNTIME_LIBDIR="$SSL_LIBDIR"
+
+fi
+ ;;
+esac
SSL_DED_LD_RUNTIME_LIBRARY_PATH=
ded_ld_rflg="$DED_LD_FLAG_RUNTIME_LIBRARY_PATH"
+case "$with_ssl_rpath" in #(
+ no) :
-case "$with_ssl_rpath" in
+ # Use no ssl runtime library path
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ ;; #(
+ yes | default) :
-yes | default) # Use standard lib locations for ssl runtime library path
+ # Use standard lib locations for ssl runtime library path
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for runtime library path to use" >&5
+printf %s "checking for runtime library path to use... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for runtime library path to use" >&5
-$as_echo_n "checking for runtime library path to use... " >&6; }
+ if test $enable_dynamic_ssl = no -a "$with_ssl_rpath" = yes; then
+ as_fn_error $? "requested by user, but user also requested static linking" "$LINENO" 5
+ fi
- if test $enable_dynamic_ssl = no -a "$with_ssl_rpath" = yes; then
- as_fn_error $? "requested by user, but user also requested static linking" "$LINENO" 5
- fi
+ if test "$CRYPTO_APP" = ""
+then :
- if test "$CRYPTO_APP" = ""; then
- if test "$with_ssl_rpath" = yes; then
- as_fn_error $? "requested by user, but could not be used since no crypto library was found" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
- elif test "$ded_ld_rflg" = ""; then
- if test "$with_ssl_rpath" = yes; then
- as_fn_error $? "requested by user, but cannot be set on this platform" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
- elif test "$SSL_DYNAMIC_ONLY" != "yes"; then
- if test "$with_ssl_rpath" = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: requested by user, but dynamic linking will not be used" >&5
-$as_echo "$as_me: WARNING: requested by user, but dynamic linking will not be used" >&2;}
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
- fi
- else
+ if test "$with_ssl_rpath" = yes
+then :
+ as_fn_error $? "requested by user, but could not be used since no crypto library was found" "$LINENO" 5
+fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
+printf "%s\n" "" >&6; }
- libdirs="/lib"
+elif test "$ded_ld_rflg" = ""
+then :
- dir_lib64=no
- dir_lib_64=no
- dir_lib32=no
- dir_lib_32=no
- dir_multiarch=no
- dir_with_ssl_lib_subdir=no
+ if test "$with_ssl_rpath" = yes
+then :
+ as_fn_error $? "requested by user, but cannot be set on this platform" "$LINENO" 5
+fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
+printf "%s\n" "" >&6; }
- test "$multiarch_dir" = "" || dir_multiarch=yes
- test "$with_ssl_lib_subdir" = "" || dir_with_ssl_lib_subdir=yes
+elif test "$SSL_DYNAMIC_ONLY" != "yes"
+then :
- case "$SSL_RUNTIME_LIBDIR" in
- */lib/64 | */lib/64/ ) dir_lib_64=yes;;
- */lib64 | */lib64/ ) dir_lib64=yes;;
- */lib/32 | */lib/32/ ) dir_lib_32=yes;;
- */lib32 | */lib32/ ) dir_lib32=yes;;
- *) ;;
- esac
+ if test "$with_ssl_rpath" = yes
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: requested by user, but dynamic linking will not be used" >&5
+printf "%s\n" "$as_me: WARNING: requested by user, but dynamic linking will not be used" >&2;}
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: " >&5
+printf "%s\n" "" >&6; }
+fi
- for dir in $std_ssl_locations; do
- if test "$ac_cv_sizeof_void_p" = "8"; then
- test $dir_lib_64 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib/64" &&
- dir_lib_64=yes
- test $dir_lib64 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib64" &&
- dir_lib64=yes
- else
- test $dir_lib_32 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib/32" &&
- dir_lib_32=yes
- test $dir_lib32 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib32" &&
- dir_lib32=yes
- fi
- test $dir_multiarch = no &&
- test -d "$erl_xcomp_sysroot$dir/lib/$multiarch_dir" &&
- dir_multiarch=yes
- done
+else $as_nop
- test $dir_with_ssl_lib_subdir = yes && libdirs="/$with_ssl_lib_subdir $libdirs"
- test $dir_multiarch = yes && libdirs="/lib/$multiarch_dir $libdirs"
- test $dir_lib_64 = yes && libdirs="/lib/64 $libdirs"
- test $dir_lib64 = yes && libdirs="/lib64 $libdirs"
- test $dir_lib_32 = yes && libdirs="/lib/32 $libdirs"
- test $dir_lib32 = yes && libdirs="/lib32 $libdirs"
+ # Try to find a suitable rpath based on default install directories...
+ libdirs="/lib"
- #
- # We try the following runtime paths in the
- # following order:
- # 1. Standard ssl locations with all variations
- # of lib subdirectories that we know of
- # 2. Standard ssl locations with all variations
- # of lib subdirectories that we know of and
- # exist on this machine
- # 3. Determined $SSL_RUNTIME_LIBDIR
- # If none of the above links, we skip runtime
- # library path...
- #
- for type in std x_std curr; do
-
- ded_ld_rpath="$ded_ld_rflg$SSL_RUNTIME_LIBDIR"
- rpath="$SSL_RUNTIME_LIBDIR"
-
- if test $type != curr; then
- for ldir in $libdirs; do
- for dir in $std_ssl_locations; do
- test "$SSL_RUNTIME_LIBDIR" != "$dir$ldir" || continue
- test $type != x_std || test -d "$erl_xcomp_sysroot$dir$ldir" || continue
- if test "$dir" = "/"; then
- libdir="$ldir"
- else
- libdir="$dir$ldir"
- fi
- ded_ld_rpath="$ded_ld_rpath $ded_ld_rflg$libdir"
- rpath="$rpath:$libdir"
- done
- done
- fi
+ dir_lib64=no
+ dir_lib_64=no
+ dir_lib32=no
+ dir_lib_32=no
+ dir_multiarch=no
+ dir_with_ssl_lib_subdir=no
+
+ if test "$multiarch_dir" != ""
+then :
+ dir_multiarch=yes
+fi
+ if test "$with_ssl_lib_subdir" != ""
+then :
+ dir_with_ssl_lib_subdir=yes
+fi
+
+ case "$SSL_RUNTIME_LIBDIR" in #(
+ */lib/64 | */lib/64/) :
+ dir_lib_64=yes ;; #(
+ */lib64 | */lib64/) :
+ dir_lib64=yes ;; #(
+ */lib/32 | */lib/32/) :
+ dir_lib_32=yes ;; #(
+ */lib32 | */lib32/) :
+ dir_lib32=yes ;; #(
+ *) :
+ ;;
+esac
+
+ for dir in $std_ssl_locations; do
+ if test "$ac_cv_sizeof_void_p" = "8"
+then :
+
+ if test $dir_lib_64 = no && test -d "$erl_xcomp_sysroot$dir/lib/64"
+then :
+ dir_lib_64=yes
+fi
+ if test $dir_lib64 = no && test -d "$erl_xcomp_sysroot$dir/lib64"
+then :
+ dir_lib64=yes
+fi
+
+else $as_nop
+
+ if test $dir_lib_32 = no && test -d "$erl_xcomp_sysroot$dir/lib/32"
+then :
+ dir_lib_32=yes
+fi
+ if test $dir_lib32 = no && test -d "$erl_xcomp_sysroot$dir/lib32"
+then :
+ dir_lib32=yes
+fi
+
+fi
+ if test $dir_multiarch = no && test -d "$erl_xcomp_sysroot$dir/lib/$multiarch_dir"
+then :
+ dir_multiarch=yes
+fi
+ done
+
+ if test $dir_with_ssl_lib_subdir = yes
+then :
+ libdirs="/$with_ssl_lib_subdir $libdirs"
+fi
+ if test $dir_multiarch = yes
+then :
+ libdirs="/lib/$multiarch_dir $libdirs"
+fi
+ if test $dir_lib_64 = yes
+then :
+ libdirs="/lib/64 $libdirs"
+fi
+ if test $dir_lib64 = yes
+then :
+ libdirs="/lib64 $libdirs"
+fi
+ if test $dir_lib_32 = yes
+then :
+ libdirs="/lib/32 $libdirs"
+fi
+ if test $dir_lib32 = yes
+then :
+ libdirs="/lib32 $libdirs"
+fi
+
+ #
+ # We try the follwing runtime paths in the
+ # following order:
+ # 1. Standard ssl locations with all variations
+ # of lib subdirectories that we know of
+ # 2. Standard ssl locations with all variations
+ # of lib subdirectories that we know of and
+ # exist on this machine
+ # 3. Determined $SSL_RUNTIME_LIBDIR
+ # If none of the above links, we skip runtime
+ # library path...
+ #
+ for type in std x_std curr; do
+
+ ded_ld_rpath="$ded_ld_rflg$SSL_RUNTIME_LIBDIR"
+ rpath="$SSL_RUNTIME_LIBDIR"
+
+ if test $type != curr
+then :
+
+ for ldir in $libdirs; do
+ for dir in $std_ssl_locations; do
+ if test "$SSL_RUNTIME_LIBDIR" = "$dir$ldir"
+then :
+ continue
+fi
+ if test $type = x_std && test '!' -d "$erl_xcomp_sysroot$dir$ldir"
+then :
+ continue
+fi
+ if test "$dir" = "/"
+then :
+ libdir="$ldir"
+else $as_nop
+ libdir="$dir$ldir"
+fi
+ ded_ld_rpath="$ded_ld_rpath $ded_ld_rflg$libdir"
+ rpath="$rpath:$libdir"
+ done
+ done
+
+fi
- # Check that it still links when we add the runtime path...
+ # Check that it still links when we add the runtime path...
test_cflags="$SSL_INCLUDE"
test_ldflags="$ded_ld_rpath -L$SSL_LIBDIR"
@@ -6203,7 +7302,7 @@ $as_echo "" >&6; }
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -6212,16 +7311,17 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
rpath_success=yes
-else
+else $as_nop
rpath_success=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
@@ -6229,69 +7329,87 @@ rm -f core conftest.err conftest.$ac_objext \
LIBS="$saveLIBS"
- test "$rpath_success" = "yes" && break
- done
+ if test "$rpath_success" = "yes"
+then :
+ break
+fi
- test "$rpath_success" = "yes" || { ded_ld_rpath=; rpath=; }
+ done
- SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+ if test "$rpath_success" != "yes"
+then :
- if test "$rpath" != ""; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $rpath" >&5
-$as_echo "$rpath" >&6; }
- elif test "$with_ssl_rpath" = yes; then
- as_fn_error $? "requested by user, but could not be used" "$LINENO" 5
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unable to set run path during linking" >&5
-$as_echo "$as_me: WARNING: unable to set run path during linking" >&2;}
- fi
- fi
- ;;
+ ded_ld_rpath=
+ rpath=
-no) # Use no ssl runtime library path
- SSL_DED_LD_RUNTIME_LIBRARY_PATH=
- ;;
+fi
-*) # Use ssl runtime library paths set by --with-ssl-rpath (without any check)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether runtime library path can be set" >&5
-$as_echo_n "checking whether runtime library path can be set... " >&6; }
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
- if test $enable_dynamic_ssl = no; then
- as_fn_error $? "runtime library path requested by user, but user also requested static linking" "$LINENO" 5
- elif test "$CRYPTO_APP" = ""; then
- if test "$with_ssl_rpath" = yes; then
- as_fn_error $? "runtime library path requested by user, but could not be set since no crypto library was found" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
- elif test "$ded_ld_rflg" = ""; then
- if test "$with_ssl_rpath" = yes; then
- as_fn_error $? "runtime library path requested by user, but cannot be set on this platform" "$LINENO" 5
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
- elif test "$SSL_DYNAMIC_ONLY" != "yes"; then
- if test "$with_ssl_rpath" = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: runtime library path requested by user, but dynamic linking will not be used" >&5
-$as_echo "$as_me: WARNING: runtime library path requested by user, but dynamic linking will not be used" >&2;}
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
-$as_echo "" >&6; }
- fi
- else
- ded_ld_rpath=
- delimit=
- rpath=
- rpath_delimit=
- save_ifs="$IFS"; IFS=",:"
- for dir in $with_ssl_rpath; do
- ded_ld_rpath="$ded_ld_rpath$delimit$ded_ld_rflg$dir"
- delimit=" "
- rpath="$rpath$rpath_delimit$dir"
- rpath_delimit=":"
- done
- IFS="$save_ifs"
- SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+ if test "$rpath" != ""
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $rpath" >&5
+printf "%s\n" "$rpath" >&6; }
+
+elif test "$with_ssl_rpath" = yes
+then :
+
+ as_fn_error $? "requested by user, but could not be used" "$LINENO" 5
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to set run path during linking" >&5
+printf "%s\n" "$as_me: WARNING: unable to set run path during linking" >&2;}
+
+fi
+
+fi
+ # end yes|default
+ ;; #(
+ *) :
+
+ # Use ssl runtime library paths set by --with-ssl-rpath
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether runtime library path can be set" >&5
+printf %s "checking whether runtime library path can be set... " >&6; }
+
+ if test $enable_dynamic_ssl = no
+then :
+
+ as_fn_error $? "runtime library path requested by user, but user also requested static linking" "$LINENO" 5
+
+elif test "$CRYPTO_APP" = ""
+then :
+
+ as_fn_error $? "runtime library path requested by user, but could not be set since no crypto library was found" "$LINENO" 5
+
+elif test "$ded_ld_rflg" = ""
+then :
+
+ as_fn_error $? "runtime library path requested by user, but cannot be set on this platform" "$LINENO" 5
+
+elif test "$SSL_DYNAMIC_ONLY" != "yes"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: runtime library path requested by user, but dynamic linking will not be used" >&5
+printf "%s\n" "$as_me: WARNING: runtime library path requested by user, but dynamic linking will not be used" >&2;}
+
+else $as_nop
+
+ # Check that it links...
+ ded_ld_rpath=
+ delimit=
+ rpath=
+ rpath_delimit=
+ save_ifs="$IFS"; IFS=",:"
+ for dir in $with_ssl_rpath; do
+ ded_ld_rpath="$ded_ld_rpath$delimit$ded_ld_rflg$dir"
+ delimit=" "
+ rpath="$rpath$rpath_delimit$dir"
+ rpath_delimit=":"
+ done
+ IFS="$save_ifs"
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
test_cflags="$SSL_INCLUDE"
test_ldflags="$ded_ld_rpath -L$SSL_LIBDIR"
@@ -6311,7 +7429,7 @@ $as_echo "" >&6; }
#include <openssl/hmac.h>
int
-main ()
+main (void)
{
HMAC(0, 0, 0, 0, 0, 0, 0);
@@ -6320,98 +7438,264 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
rpath_success=yes
-else
+else $as_nop
rpath_success=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saveCFLAGS"
LDFLAGS="$saveLDFLAGS"
LIBS="$saveLIBS"
- if test "$rpath_success" = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes; using $rpath" >&5
-$as_echo "yes; using $rpath" >&6; }
- else
- as_fn_error $? "runtime library path requested by user, but link failed" "$LINENO" 5
- fi
- fi
- ;;
+ if test "$rpath_success" = yes
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes; using $rpath" >&5
+printf "%s\n" "yes; using $rpath" >&6; }
+else $as_nop
+ as_fn_error $? "runtime library path requested by user, but link failed" "$LINENO" 5
+fi
+fi
+ ;;
esac
-
-
# Check whether --enable-fips was given.
-if test "${enable_fips+set}" = set; then :
+if test ${enable_fips+y}
+then :
enableval=$enable_fips; case "$enableval" in
yes) enable_fips_support=yes ;;
*) enable_fips_support=no ;;
esac
-else
+else $as_nop
enable_fips_support=no
fi
-if test "x$enable_fips_support" = "xyes" && test "$CRYPTO_APP" != ""; then
- saveCFLAGS="$CFLAGS"
- saveLDFLAGS="$LDFLAGS"
- saveLIBS="$LIBS"
- CFLAGS="$DED_BASIC_CFLAGS $SSL_INCLUDE"
- if test $SSL_DYNAMIC_ONLY = yes; then
- LDFLAGS="$DED_LDFLAGS_CONFTEST $ded_ld_rpath -L$SSL_LIBDIR"
- LIBS="$LIBS -l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"
- else
- LDFLAGS="$DED_LDFLAGS_CONFTEST"
- if test "$host_os" = "win32" ; then
- LIBS="$LIBS $SSL_LIBDIR/$SSL_CRYPTO_LIBNAME.lib $SSL_EXTRA_LIBS"
- else
- LIBS="$LIBS $SSL_LIBDIR/lib$SSL_CRYPTO_LIBNAME.a $SSL_EXTRA_LIBS"
- fi
- fi
- ac_fn_c_check_func "$LINENO" "FIPS_mode_set" "ac_cv_func_FIPS_mode_set"
-if test "x$ac_cv_func_FIPS_mode_set" = xyes; then :
+SSL_FLAGS=
+if test "$enable_fips_support" = "yes"
+then :
+
+ if test "$CRYPTO_APP" = ""
+then :
+ as_fn_error $? "FIPS support requested, but no crypto library found" "$LINENO" 5
+fi
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$DED_BASIC_CFLAGS $SSL_INCLUDE"
+ if test $SSL_DYNAMIC_ONLY = yes
+then :
+
+ LDFLAGS="$DED_LDFLAGS_CONFTEST $ded_ld_rpath -L$SSL_LIBDIR"
+ LIBS="$LIBS -l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"
+
+else $as_nop
+
+ LDFLAGS="$DED_LDFLAGS_CONFTEST"
+ if test "$host_os" = "win32"
+then :
+ LIBS="$LIBS $SSL_LIBDIR/$SSL_CRYPTO_LIBNAME.lib $SSL_EXTRA_LIBS"
+else $as_nop
+ LIBS="$LIBS $SSL_LIBDIR/lib$SSL_CRYPTO_LIBNAME.a $SSL_EXTRA_LIBS"
+fi
+
+fi
+ ac_fn_c_check_func "$LINENO" "FIPS_mode_set" "ac_cv_func_FIPS_mode_set"
+if test "x$ac_cv_func_FIPS_mode_set" = xyes
+then :
SSL_FLAGS="-DFIPS_SUPPORT"
-else
- SSL_FLAGS=
+else $as_nop
+ as_fn_error $? "FIPS support requested, but cannot be enabled" "$LINENO" 5
fi
- CFLAGS="$saveCFLAGS"
- LDFLAGS="$saveLDFLAGS"
- LIBS="$saveLIBS"
-else
- SSL_FLAGS=
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+
fi
-if test "x$v3_include" = "xyes"; then
- echo "Using OpenSSL 3.0 is not yet recommended for production code." >> ./CONF_INFO
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ******************************************************************" >&5
-$as_echo "$as_me: WARNING: ******************************************************************" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: * Using OpenSSL 3.0 is not yet recommended for production code. *" >&5
-$as_echo "$as_me: WARNING: * Using OpenSSL 3.0 is not yet recommended for production code. *" >&2;}
+if test "x$v3_include" = "xyes"
+then :
- if test "x$SSL_DYNAMIC_ONLY" = "xno" ; then
- echo "Static linking with OpenSSL 3.0 *MAY* require special configuring of the cryptolib." >> ./CONF_INFO
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: * Static linking *MAY* require re-configuring the 3.0 cryptolib. *" >&5
-$as_echo "$as_me: WARNING: * Static linking *MAY* require re-configuring the 3.0 cryptolib. *" >&2;}
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ******************************************************************" >&5
-$as_echo "$as_me: WARNING: ******************************************************************" >&2;}
+ if test "x$SSL_DYNAMIC_ONLY" = "xno"
+then :
+
+ echo "Static linking with OpenSSL 3.0 *MAY* require special configuring of the cryptolib." >> ./CONF_INFO
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ******************************************************************" >&5
+printf "%s\n" "$as_me: WARNING: ******************************************************************" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: * Static linking *MAY* require re-configuring the 3.0 cryptolib. *" >&5
+printf "%s\n" "$as_me: WARNING: * Static linking *MAY* require re-configuring the 3.0 cryptolib. *" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ******************************************************************" >&5
+printf "%s\n" "$as_me: WARNING: ******************************************************************" >&2;}
+
+fi
+
+fi
+
+CRYPTO_NO_DEPRECATE_WARN=
+if test "x$v3_include" = "xyes" && test "$CRYPTO_APP" != ""
+then :
+ CRYPTO_NO_DEPRECATE_WARN="-Wno-deprecated-declarations"
+
+fi
+
+saveCFLAGS="$CFLAGS"
+saveLDFLAGS="$LDFLAGS"
+saveLIBS="$LIBS"
+CFLAGS="$DED_BASIC_CFLAGS $SSL_INCLUDE"
+if test $SSL_DYNAMIC_ONLY = yes
+then :
+
+ LDFLAGS="$DED_LDFLAGS_CONFTEST $ded_ld_rpath -L$SSL_LIBDIR"
+ LIBS="$LIBS -l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"
+
+else $as_nop
+
+ LDFLAGS="$DED_LDFLAGS_CONFTEST"
+ if test "$host_os" = "win32"
+then :
+ LIBS="$LIBS $SSL_LIBDIR/$SSL_CRYPTO_LIBNAME.lib $SSL_EXTRA_LIBS"
+else $as_nop
+ LIBS="$LIBS $SSL_LIBDIR/lib$SSL_CRYPTO_LIBNAME.a $SSL_EXTRA_LIBS"
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
+printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
+if test ${ac_cv_c_undeclared_builtin_options+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_CFLAGS=$CFLAGS
+ ac_cv_c_undeclared_builtin_options='cannot detect'
+ for ac_arg in '' -fno-builtin; do
+ CFLAGS="$ac_save_CFLAGS $ac_arg"
+ # This test program should *not* compile successfully.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+(void) strchr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ # This test program should compile successfully.
+ # No library function is consistently available on
+ # freestanding implementations, so test against a dummy
+ # declaration. Include always-available headers on the
+ # off chance that they somehow elicit warnings.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);
+
+int
+main (void)
+{
+(void) ac_decl (0, (char *) 0);
+ (void) ac_decl;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ if test x"$ac_arg" = x
+then :
+ ac_cv_c_undeclared_builtin_options='none needed'
+else $as_nop
+ ac_cv_c_undeclared_builtin_options=$ac_arg
fi
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+ CFLAGS=$ac_save_CFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
+printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
+ case $ac_cv_c_undeclared_builtin_options in #(
+ 'cannot detect') :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot make $CC report undeclared builtins
+See \`config.log' for more details" "$LINENO" 5; } ;; #(
+ 'none needed') :
+ ac_c_undeclared_builtin_options='' ;; #(
+ *) :
+ ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
+esac
+
+ac_fn_check_decl "$LINENO" "CRYPTO_memcmp" "ac_cv_have_decl_CRYPTO_memcmp" "#include <openssl/crypto.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_CRYPTO_memcmp" = xyes
+then :
+ have_crypto_memcmp_decl=yes
+else $as_nop
+ have_crypto_memcmp_decl=no
+fi
+if test $have_crypto_memcmp_decl = yes
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether CRYPTO_memcmp can be linked" >&5
+printf %s "checking whether CRYPTO_memcmp can be linked... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <openssl/crypto.h>
+
+int
+main (void)
+{
+
+ CRYPTO_memcmp("a", "b", 1);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ SSL_FLAGS="-DHAVE_OPENSSL_CRYPTO_MEMCMP $SSL_FLAGS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
-if test "x$v3_include" = "xyes" && test "x$deprecated_warnings" = "xdefault_yes" && test "$CRYPTO_APP" != ""; then
- deprecated_warnings=no
fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
-if test "x$deprecated_warnings" = "xno" && test "$CRYPTO_APP" != "" ; then
- SSL_FLAGS="$SSL_FLAGS -Wno-deprecated-declarations"
fi
+CFLAGS="$saveCFLAGS"
+LDFLAGS="$saveLDFLAGS"
+LIBS="$saveLIBS"
+
@@ -6455,8 +7739,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -6486,15 +7770,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -6508,8 +7792,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -6562,7 +7846,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -6578,8 +7862,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -6602,14 +7886,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -6619,46 +7905,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -6667,13 +7953,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -6682,8 +7961,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -6695,30 +7978,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -6731,13 +7994,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -6764,18 +8028,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -6787,12 +8053,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -6823,7 +8090,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -6845,6 +8112,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -6858,6 +8129,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -6899,7 +8176,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -6908,7 +8185,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6971,7 +8248,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -7020,14 +8297,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -7064,21 +8343,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -7106,7 +8385,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -7120,7 +8399,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -7145,7 +8424,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -7373,7 +8652,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -7381,17 +8660,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -7408,7 +8687,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -7432,9 +8711,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -7487,8 +8766,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -7530,9 +8809,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -7579,8 +8858,9 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/crypto/configure.ac b/lib/crypto/configure.ac
new file mode 100644
index 0000000000..c80e1cf2af
--- /dev/null
+++ b/lib/crypto/configure.ac
@@ -0,0 +1,960 @@
+dnl Process this file with autoconf to produce a configure script. -*-Autoconf-*-
+dnl
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 2018-2023. All Rights Reserved.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+dnl
+dnl %CopyrightEnd%
+dnl
+
+dnl define([AC_CACHE_LOAD], )dnl
+dnl define([AC_CACHE_SAVE], )dnl
+
+AC_INIT
+AC_CONFIG_SRCDIR([vsn.mk])
+AC_PREREQ([2.71])
+
+m4_include([otp.m4])
+
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
+
+ERL_CANONICAL_SYSTEM_TYPE
+
+AC_LANG(C)
+
+LM_PRECIOUS_VARS
+
+## Delete previous failed configure results
+if test -f ./CONF_INFO; then
+ rm ./CONF_INFO
+fi
+
+if test "$cross_compiling" = "yes"; then
+ CROSS_COMPILING=yes
+else
+ CROSS_COMPILING=no
+fi
+AC_SUBST(CROSS_COMPILING)
+
+ERL_XCOMP_SYSROOT_INIT
+
+AC_PROG_CC
+LM_WINDOWS_ENVIRONMENT
+
+ERL_DED
+
+AC_MSG_CHECKING([for multiarch directory])
+multiarch_dir=
+if test "$GCC" = "yes"; then
+ multiarch_dir=`$CC $CFLAGS -print-multiarch 2>/dev/null`
+ if test $? -ne 0; then
+ multiarch_dir=
+ fi
+fi
+if test "$multiarch_dir" = ""; then
+ AC_MSG_RESULT([not found])
+else
+ AC_MSG_RESULT([$multiarch_dir])
+fi
+
+dnl
+dnl SSL, SSH and CRYPTO need the OpenSSL libraries
+dnl
+dnl Check flags --with-ssl, --without-ssl --with-ssl=PATH.
+dnl If no option is given or --with-ssl is set without a path then we
+dnl search for OpenSSL libraries and header files in the standard locations.
+dnl If set to --without-ssl we disable the use of SSL, SSH and CRYPTO.
+dnl If set to --with-ssl=PATH we use that path as the prefix, i.e. we
+dnl use "PATH/include" and "PATH/lib".
+
+AC_CHECK_SIZEOF(void *)
+
+std_ssl_locations="\
+/usr/local \
+/usr/sfw \
+/usr \
+/opt/local \
+/usr/pkg \
+/usr/local/openssl \
+/usr/local/opt/openssl \
+/opt/homebrew/opt/openssl \
+/usr/lib/openssl \
+/usr/openssl \
+/usr/local/ssl \
+/usr/lib/ssl \
+/usr/ssl \
+/"
+
+AC_ARG_WITH(ssl,
+AS_HELP_STRING([--with-ssl=PATH], [base location of OpenSSL include and lib directories])
+AS_HELP_STRING([--with-ssl], [use SSL (default)])
+AS_HELP_STRING([--without-ssl], [don't use SSL]))
+
+AC_ARG_WITH(ssl-lib-subdir,
+AS_HELP_STRING([--with-ssl-lib-subdir=RELATIVE_PATH],
+ [specify extra OpenSSL lib sub-directory to search in (relative to base directory)]),
+[
+case "$with_ssl_lib_subdir" in
+ yes|no)
+ with_ssl_lib_subdir=
+ ;;
+ *)
+ ;;
+esac
+],
+[with_ssl_lib_subdir=]) #default
+
+AC_ARG_WITH(ssl-incl,
+AS_HELP_STRING([--with-ssl-incl=PATH],
+ [base location of OpenSSL include dir (if different than base location specified by --with-ssl=PATH)]),
+[
+case X$with_ssl in
+ X | Xyes | Xno) AC_MSG_ERROR([--with-ssl-incl=PATH set without --with-ssl=PATH]);;
+esac
+],
+[with_ssl_incl=$with_ssl]) #default
+
+AC_ARG_WITH(ssl-zlib,
+AS_HELP_STRING([--with-ssl-zlib=PATH], [Path to static zlib library to link the
+ crypto NIF with. This zlib library is most
+ often not necessary but might be needed in
+ order to link the NIF in some cases.]),
+[], [with_ssl_zlib=default]) #default
+
+AC_ARG_WITH(ssl-rpath,
+AS_HELP_STRING([--with-ssl-rpath=yes|no|PATHS],
+ [runtime library path for OpenSSL. Default is "yes", which equates to a
+ number of standard locations. If "no", then no runtime
+ library paths will be used. Anything else should be a
+ comma or colon separated list of paths.]),
+[
+case X$with_ssl in
+ Xno) AC_MSG_ERROR([--with-ssl-rpath set without --with-ssl]);;
+esac
+],
+[with_ssl_rpath=default]) #default
+
+
+AC_ARG_ENABLE(dynamic-ssl-lib,
+AS_HELP_STRING([--enable-dynamic-ssl-lib],
+ [enable using dynamic openssl libraries when linking the crypto NIF])
+AS_HELP_STRING([--disable-dynamic-ssl-lib],
+ [disable using dynamic openssl libraries when linking the crypto NIF]),
+[ case "$enableval" in
+ no) enable_dynamic_ssl=no ;;
+ *) enable_dynamic_ssl=yes ;;
+ esac ], enable_dynamic_ssl=undefined)
+
+AC_ARG_ENABLE(evp-dh,
+AS_HELP_STRING([--disable-evp-dh],
+ [intentionally undocumented workaround]),
+[ case "$enableval" in
+ no) DISABLE_EVP_DH=1;;
+ *) DISABLE_EVP_DH=0;;
+ esac ], DISABLE_EVP_DH=0)
+
+
+AC_ARG_ENABLE(evp-hmac,
+AS_HELP_STRING([--disable-evp-hmac],
+ [intentionally undocumented workaround]),
+[ case "$enableval" in
+ no) DISABLE_EVP_HMAC=1;;
+ *) DISABLE_EVP_HMAC=0;;
+ esac ], DISABLE_EVP_HMAC=0)
+
+AC_ARG_ENABLE(otp-test-engine,
+AS_HELP_STRING([--disable-otp-test-engine],
+ [Disable build of the otp_test_engine. (default is --enable-otp-test-engine, unless for LibreSSL >= 3.5.0 where default is --disable-otp-test-engine)]),
+[ case "$enableval" in
+ no) DISABLE_OTP_TEST_ENGINE=yes;;
+ *) DISABLE_OTP_TEST_ENGINE=no;;
+ esac ], DISABLE_OTP_TEST_ENGINE=default)
+
+AC_DEFUN([ERL_LINK_CRYPTO_IFELSE], [
+ test_cflags=$1
+ test_ldflags=$2
+ test_libs=$3
+
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$DED_BASIC_CFLAGS $test_cflags"
+ LDFLAGS="$DED_LDFLAGS_CONFTEST $test_ldflags"
+ LIBS="$LIBS $test_libs"
+
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+ #include <stdio.h>
+ #include <openssl/hmac.h>
+ ]],
+ [[
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ]])],
+ [
+ $4
+ ],
+ [
+ $5
+ ])
+
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+])
+
+AC_DEFUN([ERL_CRYPTO_CHECK_LIB], [
+ # Check for static and dynamic crypto library in the directory
+ # given as argument...
+ #
+ # Written as a macro in order to avoid writing the tests twice...
+ idir=$1
+ prfx=$2
+ rdir=$3
+ dir="$prfx$rdir"
+ static_crypto_lib_name=crypto
+ static_ssl_lib_name=ssl
+ static_extra_libs="$forced_static_zlib"
+ static_lib_dir=
+ dynamic_crypto_lib_name=crypto
+ dynamic_ssl_lib_name=ssl
+ dynamic_extra_libs="$forced_static_zlib"
+ dynamic_lib_dir=
+ dynamic_runtime_lib_dir=
+ found_static_lib=no
+ found_dynamic_lib=no
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="-I$idir/include"
+ AC_EGREP_CPP(^yes.?$,[
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER >= 0x0090803fL
+yes
+#endif
+ ],
+ [valid_include=yes],
+ [valid_include=no])
+ AC_EGREP_CPP(^yes.?$,[
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_MAJOR == 3
+yes
+#endif
+ ],
+ [v3_include=yes],
+ [v3_include=no])
+
+
+ if test "x$DISABLE_OTP_TEST_ENGINE" = "xdefault"; then
+# Get default value for the --disable-otp-test-engine. Depends on cryptolib version
+ AC_EGREP_CPP(^yes.?$,[
+#include <openssl/opensslv.h>
+#if LIBRESSL_VERSION_NUMBER >= 0x3050000fL
+yes
+#endif
+ ],
+ [DISABLE_OTP_TEST_ENGINE=yes],
+ [DISABLE_OTP_TEST_ENGINE=no])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+
+ AS_IF([test $valid_include != yes],
+ [
+ # Not a valid include...
+ static_crypto_lib_name=
+ static_ssl_lib_name=
+ static_extra_libs=
+ static_lib_dir=
+ dynamic_crypto_lib_name=
+ dynamic_ssl_lib_name=
+ dynamic_extra_libs=
+ dynamic_lib_dir=
+ dynamic_runtime_lib_dir=
+ ],
+ [test "$host_os" = "win32"],
+ [
+ # Windows...
+ AS_IF([test "x$ac_cv_sizeof_void_p" = "x8"],
+ [
+ lib_bits=64
+ ],
+ [
+ lib_bits=32
+ ])
+ AS_IF([test -f "$dir/lib/VC/static/libcrypto${lib_bits}MD.lib"],
+ [
+ static_crypto_lib_name=libcrypto${lib_bits}MD
+ static_ssl_lib_name="libssl${lib_bits}MD"
+ static_extra_libs="$static_extra_libs -lCRYPT32 -lWS2_32"
+ static_lib_dir="$dir/lib/VC/static"
+ found_static_lib=yes
+ ])
+ AS_IF([test -f "$dir/lib/VC/libcrypto${lib_bits}MD.lib"],
+ [
+ dynamic_crypto_lib_name=libcrypto${lib_bits}MD
+ dynamic_ssl_lib_name="libssl${lib_bits}MD"
+ dynamic_runtime_lib_dir="$rdir/lib/VC"
+ dynamic_lib_dir="$dir/lib/VC"
+ found_dynamic_lib=yes
+ ])
+ ],
+ [
+ # Not windows...
+ AS_CASE(["$host_os"],
+ [darwin*],
+ [
+ static_ext=.a
+ dynamic_ext=.dylib
+ ],
+ [
+ static_ext=.a
+ dynamic_ext=.so
+ ])
+ for sdir in $search_subdirs; do
+ AS_IF([test -f "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"],
+ [
+ found_dynlib=yes
+ ],
+ [
+ found_dynlib=no
+ AS_CASE([$host_os],
+ [openbsd*],
+ [
+ # libcrypto.so got a suffix on (at least some) openbsd.
+ # If we find libcrypto.so with suffix, we try to link
+ # to it using -lcrypto ...
+ for f in "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"*; do
+ AS_IF([test -f "$f"], [found_dynlib=yes; break])
+ done
+ ])
+ ])
+ AS_IF([test $found_dynlib = yes],
+ [
+ # Found dynamic library; check if it links...
+ dynamic_lib_dir="$dir/$sdir"
+ dynamic_runtime_lib_dir="$rdir/$sdir"
+ ERL_LINK_CRYPTO_IFELSE(["-I$idir/include"],
+ ["-L$dynamic_lib_dir"],
+ ["-l$dynamic_crypto_lib_name $dynamic_extra_libs"],
+ [found_dynamic_lib=yes],
+ [found_dynamic_lib=no])
+ AS_IF([test $found_dynamic_lib = no -a $static_zlib != no],
+ [
+ # No, but linking with zlib as well might help...
+ dynamic_extra_libs="$dynamic_extra_libs $static_zlib"
+ ERL_LINK_CRYPTO_IFELSE(["-I$idir/include"],
+ ["-L$dynamic_lib_dir"],
+ ["-l$dynamic_crypto_lib_name $dynamic_extra_libs"],
+ [found_dynamic_lib=yes],
+ [found_dynamic_lib=no])
+ ])
+ ])
+ AS_IF([test -f "$dir/$sdir/lib$static_crypto_lib_name$static_ext"],
+ [
+ # Found static library; check if it links...
+ static_lib_dir="$dir/$sdir"
+ ERL_LINK_CRYPTO_IFELSE(["-I$idir/include"],
+ [],
+ ["$dir/$sdir/lib$static_crypto_lib_name$static_ext $static_extra_libs"],
+ [found_static_lib=yes],
+ [found_static_lib=no])
+ AS_IF([test $found_static_lib = no -a $static_zlib != no],
+ [
+ # No, but inking with zlib as well might help...
+ static_extra_libs="$static_extra_libs $static_zlib"
+ ERL_LINK_CRYPTO_IFELSE(["-I$idir/include"],
+ [],
+ ["$dir/$sdir/lib$static_crypto_lib_name$static_ext $static_extra_libs"],
+ [found_static_lib=yes],
+ [found_static_lib=no])
+ ])
+ ])
+ AS_IF([test $found_static_lib = yes -o $found_dynamic_lib = yes],
+ [break])
+ done
+ ])
+])
+
+# Remove all SKIP files from previous runs
+for a in ssl crypto ssh; do
+ rm -f "$ERL_TOP/lib/$a/SKIP"
+done
+
+# Setup subdirectories to search in...
+search_subdirs="lib"
+if test "$ac_cv_sizeof_void_p" = "8"; then
+ search_subdirs="$search_subdirs lib64 lib/64"
+else
+ search_subdirs="$search_subdirs lib32 lib/32"
+fi
+test "$multiarch_dir" = "" || search_subdirs="lib/$multiarch_dir $search_subdirs"
+test "$with_ssl_lib_subdir" = "" || search_subdirs="$with_ssl_lib_subdir $search_subdirs"
+
+# We might need to link with zlib, so first check if we can find
+# a static zlib to use if needed...
+static_zlib=no
+forced_static_zlib=
+case "$with_ssl_zlib" in
+ no)
+ ;;
+ default | yes)
+ AC_MSG_CHECKING([for static zlib])
+ for dir in $std_ssl_locations; do
+ for sdir in $search_subdirs; do
+ if test -f "$erl_xcomp_sysroot$dir/$sdir/libz.a"; then
+ static_zlib="$erl_xcomp_sysroot$dir/$sdir/libz.a"
+ break
+ fi
+ done
+ test "$static_zlib" = "no" || break
+ done
+ AC_MSG_RESULT([$static_zlib])
+ if test $with_ssl_zlib = yes; then
+ if test $static_zlib = no; then
+ AC_MSG_ERROR([linking with zlib requested by user, but no such library was found])
+ fi
+ forced_static_zlib="$static_zlib"
+ static_zlib=no
+ fi;;
+ *) # PATH
+ AC_MSG_CHECKING([for static zlib])
+ if test -f "$with_ssl_zlib/libz.a"; then
+ forced_static_zlib="$with_ssl_zlib/libz.a"
+ else
+ for sdir in $search_subdirs; do
+ if test -f "$with_ssl_zlib/$sdir/libz.a"; then
+ forced_static_zlib="$with_ssl_zlib/$sdir/libz.a"
+ break
+ fi
+ done
+ fi
+ if test "$forced_static_zlib" = ""; then
+ AC_MSG_ERROR([linking with zlib requested by user, but no such library was found in $with_ssl_zlib])
+ fi
+ AC_MSG_RESULT([$forced_static_zlib])
+ ;;
+esac
+
+if test $enable_dynamic_ssl = undefined; then
+ if test "$host_os" = "win32" ; then
+ enable_dynamic_ssl=default_no
+ else
+ enable_dynamic_ssl=default_yes
+ fi
+fi
+
+case $enable_dynamic_ssl in
+ yes|default_yes)
+ SSL_DYNAMIC_ONLY=yes;;
+ *)
+ SSL_DYNAMIC_ONLY=no;;
+esac
+
+AS_CASE(["$erl_xcomp_without_sysroot-$with_ssl"],
+ [yes-* | no-no],
+ [
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ if test "$with_ssl" != "no"; then
+ skip="Cannot search for ssl; missing cross system root (erl_xcomp_sysroot)."
+ fi
+ for a in ssl crypto ssh; do
+ echo "$skip" > $ERL_TOP/lib/$a/SKIP
+ done
+ ],
+ [no-yes | no-],
+ [
+ # We search for OpenSSL in the common OS standard locations.
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+
+ AS_IF([test "$host_os" != "win32"],
+ [
+ std_win_ssl_locations=
+ ],
+ [
+ AS_IF([test "x$ac_cv_sizeof_void_p" = "x8"],
+ [
+ std_win_ssl_locations="/mnt/c/OpenSSL-Win64 /c/OpenSSL-Win64 /mnt/c/opt/local64/pgm/OpenSSL /opt/local64/pgm/OpenSSL /cygdrive/c/OpenSSL-Win64"
+ ],
+ [
+ std_win_ssl_locations="/mnt/c/OpenSSL-Win32 /c/OpenSSL-Win32 /mnt/c/OpenSSL /c/OpenSSL /cygdrive/c/OpenSSL /opt/local/pgm/OpenSSL /opt/local32/pgm/OpenSSL /mnt/c/opt/local/pgm/OpenSSL /mnt/c/opt/local32/pgm/OpenSSL /cygdrive/c/OpenSSL-Win32"
+ ])
+ ])
+
+ usable_crypto=no
+ AC_MSG_CHECKING([for OpenSSL crypto library with version >= 0.9.8c in standard locations])
+ for rdir in $std_win_ssl_locations $std_ssl_locations; do
+ AS_IF([test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"],
+ [
+ SSL_INCDIR="$erl_xcomp_isysroot$rdir"
+ SSL_INCLUDE="-I$SSL_INCDIR/include"
+ ERL_CRYPTO_CHECK_LIB(["$SSL_INCDIR"], ["$erl_xcomp_sysroot"], ["$rdir"])
+ AS_CASE([$enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib],
+ [no-*-no],
+ [
+ # Dynamic linking against ssl library disabled by user,
+ # and no static library found...
+ ],
+ [yes-no-*],
+ [
+ # Static linking against ssl library disabled by user,
+ # and no dynamic library found...
+ ],
+ [*-no-no],
+ [
+ # Neither static nor dynamic ssl library found...
+ ],
+ [no-*-yes | default_no-*-yes | default_yes-no-yes],
+ [
+ # Link statically...
+ SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
+ SSL_SSL_LIBNAME=$static_ssl_lib_name
+ SSL_LIBDIR="$static_lib_dir"
+ SSL_EXTRA_LIBS="$static_extra_libs"
+ SSL_RUNTIME_LIBDIR=
+ SSL_DYNAMIC_ONLY=no
+ usable_crypto=yes
+ break
+ ],
+ [*-yes-*],
+ [
+ # Link dynamically...
+ SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
+ SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
+ SSL_EXTRA_LIBS="$dynamic_extra_libs"
+ SSL_LIBDIR="$dynamic_lib_dir"
+ SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
+ SSL_DYNAMIC_ONLY=yes
+ usable_crypto=yes
+ break
+ ])
+ ])
+ done
+
+ AS_IF([test $usable_crypto = yes],
+ [AS_IF([test $SSL_DYNAMIC_ONLY = yes],
+ [AC_MSG_RESULT([dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])],
+ [AC_MSG_RESULT([static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])])],
+ [
+ AC_MSG_RESULT([no])
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+
+ SSL_INCDIR=
+ SSL_INCLUDE=
+ SSL_CRYPTO_LIBNAME=
+ SSL_SSL_LIBNAME=
+ SSL_INCDIR=
+ SSL_RUNTIME_LIBDIR=
+ SSL_LIBDIR=
+
+ AS_CASE(["$with_ssl-$enable_dynamic_ssl"],
+ [yes-yes],
+ [
+ AC_MSG_ERROR([crypto library with dynamic linking requested by user, but no such library was found])
+ ],
+ [yes-no],
+ [
+ AC_MSG_ERROR([crypto library with static linking requested by user, but no such library was found])
+ ],
+ [yes-*],
+ [
+ AC_MSG_ERROR([crypto library requested by user, but no such library was found])
+ ],
+ [
+ AC_MSG_WARN([No (usable) OpenSSL found, skipping ssl, ssh and crypto applications])
+ ])
+
+ for a in ssl crypto ssh; do
+ echo "No usable OpenSSL found" > $ERL_TOP/lib/$a/SKIP
+ done
+ ])
+ ],
+ [
+ # Option given with PATH to package
+ AS_IF([test ! -d "$with_ssl"],
+ [AC_MSG_ERROR(Invalid path to option --with-ssl=PATH)])
+ AS_IF([test ! -d "$with_ssl_incl"],
+ [AC_MSG_ERROR(Invalid path to option --with-ssl-incl=PATH)])
+ AC_MSG_CHECKING([for OpenSSL header in $with_ssl_incl])
+ AS_IF([test -f "$with_ssl_incl/include/openssl/opensslv.h"],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_ERROR([no OpenSSL header found in $with_ssl_incl])])
+ SSL_INCDIR="$with_ssl_incl"
+ AC_MSG_CHECKING([for OpenSSL in $with_ssl])
+ ERL_CRYPTO_CHECK_LIB(["$with_ssl_incl"], [""], ["$with_ssl"])
+ AS_CASE([$enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib],
+ [no-*-no],
+ [
+ AC_MSG_ERROR([dynamic linking against crypto library disabled by user, but no static library found in $with_ssl])
+ ],
+ [yes-no-*],
+ [
+ AC_MSG_ERROR([static linking against crypto library disabled by user, but no dynamic library found in $with_ssl])
+ ],
+ [*-no-no],
+ [
+ AC_MSG_ERROR([neither static nor dynamic crypto library found in $with_ssl])
+ ],
+ [no-*-yes | default_no-*-yes | default_yes-no-yes],
+ [
+ # Link statically...
+ SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
+ SSL_SSL_LIBNAME=$static_ssl_lib_name
+ SSL_LIBDIR="$static_lib_dir"
+ SSL_EXTRA_LIBS="$static_extra_libs"
+ SSL_RUNTIME_LIBDIR=
+ SSL_DYNAMIC_ONLY=no
+ ],
+ [*-yes-*],
+ [
+ # Link dynamically...
+ SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
+ SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
+ SSL_EXTRA_LIBS="$dynamic_extra_libs"
+ SSL_LIBDIR="$dynamic_lib_dir"
+ SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
+ SSL_DYNAMIC_ONLY=yes
+ ])
+ AS_IF([test $SSL_DYNAMIC_ONLY = yes],
+ [AC_MSG_RESULT([dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])],
+ [AC_MSG_RESULT([static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])])
+ SSL_INCLUDE="-I$with_ssl_incl/include"
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+ AS_IF([test "$cross_compiling" = "yes"],
+ [
+ SSL_RUNTIME_LIBDIR=`echo "$SSL_LIBDIR" | sed -n "s|^$erl_xcomp_sysroot\(/*\)\(.*\)\$|/\2|p"`
+ ],
+ [
+ SSL_RUNTIME_LIBDIR="$SSL_LIBDIR"
+ ])
+ ])dnl AS_CASE
+
+SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ded_ld_rflg="$DED_LD_FLAG_RUNTIME_LIBRARY_PATH"
+
+AS_CASE(["$with_ssl_rpath"],
+ [no],
+ [
+ # Use no ssl runtime library path
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ ],
+ [yes | default],
+ [
+ # Use standard lib locations for ssl runtime library path
+ AC_MSG_CHECKING([for runtime library path to use])
+
+ if test $enable_dynamic_ssl = no -a "$with_ssl_rpath" = yes; then
+ AC_MSG_ERROR([requested by user, but user also requested static linking])
+ fi
+
+ AS_IF([test "$CRYPTO_APP" = ""],
+ [
+ AS_IF([test "$with_ssl_rpath" = yes],
+ [AC_MSG_ERROR([requested by user, but could not be used since no crypto library was found])])
+ AC_MSG_RESULT([])
+ ],
+ [test "$ded_ld_rflg" = ""],
+ [
+ AS_IF([test "$with_ssl_rpath" = yes],
+ [AC_MSG_ERROR([requested by user, but cannot be set on this platform])])
+ AC_MSG_RESULT([])
+ ],
+ [test "$SSL_DYNAMIC_ONLY" != "yes"],
+ [
+ AS_IF([test "$with_ssl_rpath" = yes],
+ [AC_MSG_WARN([requested by user, but dynamic linking will not be used])],
+ [AC_MSG_RESULT([])])
+ ],
+ [
+ # Try to find a suitable rpath based on default install directories...
+ libdirs="/lib"
+
+ dir_lib64=no
+ dir_lib_64=no
+ dir_lib32=no
+ dir_lib_32=no
+ dir_multiarch=no
+ dir_with_ssl_lib_subdir=no
+
+ AS_IF([test "$multiarch_dir" != ""], [dir_multiarch=yes])
+ AS_IF([test "$with_ssl_lib_subdir" != ""], [dir_with_ssl_lib_subdir=yes])
+
+ AS_CASE(["$SSL_RUNTIME_LIBDIR"],
+ [*/lib/64 | */lib/64/], [dir_lib_64=yes],
+ [*/lib64 | */lib64/], [dir_lib64=yes],
+ [*/lib/32 | */lib/32/], [dir_lib_32=yes],
+ [*/lib32 | */lib32/], [dir_lib32=yes])
+
+ for dir in $std_ssl_locations; do
+ AS_IF([test "$ac_cv_sizeof_void_p" = "8"],
+ [
+ AS_IF([test $dir_lib_64 = no && test -d "$erl_xcomp_sysroot$dir/lib/64"],
+ [dir_lib_64=yes])
+ AS_IF([test $dir_lib64 = no && test -d "$erl_xcomp_sysroot$dir/lib64"],
+ [dir_lib64=yes])
+ ],
+ [
+ AS_IF([test $dir_lib_32 = no && test -d "$erl_xcomp_sysroot$dir/lib/32"],
+ [dir_lib_32=yes])
+ AS_IF([test $dir_lib32 = no && test -d "$erl_xcomp_sysroot$dir/lib32"],
+ [dir_lib32=yes])
+ ])
+ AS_IF([test $dir_multiarch = no && test -d "$erl_xcomp_sysroot$dir/lib/$multiarch_dir"],
+ [dir_multiarch=yes])
+ done
+
+ AS_IF([test $dir_with_ssl_lib_subdir = yes],
+ [libdirs="/$with_ssl_lib_subdir $libdirs"])
+ AS_IF([test $dir_multiarch = yes],
+ [libdirs="/lib/$multiarch_dir $libdirs"])
+ AS_IF([test $dir_lib_64 = yes],
+ [libdirs="/lib/64 $libdirs"])
+ AS_IF([test $dir_lib64 = yes],
+ [libdirs="/lib64 $libdirs"])
+ AS_IF([test $dir_lib_32 = yes],
+ [libdirs="/lib/32 $libdirs"])
+ AS_IF([test $dir_lib32 = yes],
+ [libdirs="/lib32 $libdirs"])
+
+ #
+ # We try the follwing runtime paths in the
+ # following order:
+ # 1. Standard ssl locations with all variations
+ # of lib subdirectories that we know of
+ # 2. Standard ssl locations with all variations
+ # of lib subdirectories that we know of and
+ # exist on this machine
+ # 3. Determined $SSL_RUNTIME_LIBDIR
+ # If none of the above links, we skip runtime
+ # library path...
+ #
+ for type in std x_std curr; do
+
+ ded_ld_rpath="$ded_ld_rflg$SSL_RUNTIME_LIBDIR"
+ rpath="$SSL_RUNTIME_LIBDIR"
+
+ AS_IF([test $type != curr],
+ [
+ for ldir in $libdirs; do
+ for dir in $std_ssl_locations; do
+ AS_IF([test "$SSL_RUNTIME_LIBDIR" = "$dir$ldir"],
+ [continue])
+ AS_IF([test $type = x_std && test '!' -d "$erl_xcomp_sysroot$dir$ldir"],
+ [continue])
+ AS_IF([test "$dir" = "/"],
+ [libdir="$ldir"],
+ [libdir="$dir$ldir"])
+ ded_ld_rpath="$ded_ld_rpath $ded_ld_rflg$libdir"
+ rpath="$rpath:$libdir"
+ done
+ done
+ ])
+
+ # Check that it still links when we add the runtime path...
+ ERL_LINK_CRYPTO_IFELSE(["$SSL_INCLUDE"],
+ ["$ded_ld_rpath -L$SSL_LIBDIR"],
+ ["-l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"],
+ [rpath_success=yes],
+ [rpath_success=no])
+
+ AS_IF([test "$rpath_success" = "yes"], [break])
+
+ done
+
+ AS_IF([test "$rpath_success" != "yes"],
+ [
+ ded_ld_rpath=
+ rpath=
+ ])
+
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+
+ AS_IF([test "$rpath" != ""],
+ [
+ AC_MSG_RESULT([$rpath])
+ ],
+ [test "$with_ssl_rpath" = yes],
+ [
+ AC_MSG_ERROR([requested by user, but could not be used])
+ ],
+ [
+ AC_MSG_WARN([unable to set run path during linking])
+ ])
+ ])
+ # end yes|default
+ ],
+ [
+ # Use ssl runtime library paths set by --with-ssl-rpath
+ AC_MSG_CHECKING([whether runtime library path can be set])
+
+ AS_IF([test $enable_dynamic_ssl = no],
+ [
+ AC_MSG_ERROR([runtime library path requested by user, but user also requested static linking])
+ ],
+ [test "$CRYPTO_APP" = ""],
+ [
+ AC_MSG_ERROR([runtime library path requested by user, but could not be set since no crypto library was found])
+ ],
+ [test "$ded_ld_rflg" = ""],
+ [
+ AC_MSG_ERROR([runtime library path requested by user, but cannot be set on this platform])
+ ],
+ [test "$SSL_DYNAMIC_ONLY" != "yes"],
+ [
+ AC_MSG_WARN([runtime library path requested by user, but dynamic linking will not be used])
+ ],
+ [
+ # Check that it links...
+ ded_ld_rpath=
+ delimit=
+ rpath=
+ rpath_delimit=
+ save_ifs="$IFS"; IFS=",:"
+ for dir in $with_ssl_rpath; do
+ ded_ld_rpath="$ded_ld_rpath$delimit$ded_ld_rflg$dir"
+ delimit=" "
+ rpath="$rpath$rpath_delimit$dir"
+ rpath_delimit=":"
+ done
+ IFS="$save_ifs"
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+ ERL_LINK_CRYPTO_IFELSE(["$SSL_INCLUDE"],
+ ["$ded_ld_rpath -L$SSL_LIBDIR"],
+ ["-l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"],
+ [rpath_success=yes],
+ [rpath_success=no])
+ AS_IF([test "$rpath_success" = yes],
+ [AC_MSG_RESULT([yes; using $rpath])],
+ [AC_MSG_ERROR([runtime library path requested by user, but link failed])])
+ ])
+ ])dnl AS_CASE
+
+AC_ARG_ENABLE(fips,
+AS_HELP_STRING([--enable-fips], [enable OpenSSL FIPS mode support])
+AS_HELP_STRING([--disable-fips], [disable OpenSSL FIPS mode support (default)]),
+[ case "$enableval" in
+ yes) enable_fips_support=yes ;;
+ *) enable_fips_support=no ;;
+ esac ], enable_fips_support=no)
+
+SSL_FLAGS=
+AS_IF([test "$enable_fips_support" = "yes"],
+ [
+ AS_IF([test "$CRYPTO_APP" = ""],
+ [AC_MSG_ERROR([FIPS support requested, but no crypto library found])])
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$DED_BASIC_CFLAGS $SSL_INCLUDE"
+ AS_IF([test $SSL_DYNAMIC_ONLY = yes],
+ [
+ LDFLAGS="$DED_LDFLAGS_CONFTEST $ded_ld_rpath -L$SSL_LIBDIR"
+ LIBS="$LIBS -l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"
+ ],
+ [
+ LDFLAGS="$DED_LDFLAGS_CONFTEST"
+ AS_IF([test "$host_os" = "win32"],
+ [LIBS="$LIBS $SSL_LIBDIR/$SSL_CRYPTO_LIBNAME.lib $SSL_EXTRA_LIBS"],
+ [LIBS="$LIBS $SSL_LIBDIR/lib$SSL_CRYPTO_LIBNAME.a $SSL_EXTRA_LIBS"])
+ ])
+ AC_CHECK_FUNC([FIPS_mode_set],
+ [SSL_FLAGS="-DFIPS_SUPPORT"],
+ [AC_MSG_ERROR([FIPS support requested, but cannot be enabled])])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+ ])
+
+AS_IF([test "x$v3_include" = "xyes"],
+ [
+ AS_IF([test "x$SSL_DYNAMIC_ONLY" = "xno" ],
+ [
+ echo "Static linking with OpenSSL 3.0 *MAY* require special configuring of the cryptolib." >> ./CONF_INFO
+ AC_MSG_WARN(******************************************************************)
+ AC_MSG_WARN(* Static linking *MAY* require re-configuring the 3.0 cryptolib. *)
+ AC_MSG_WARN(******************************************************************)
+ ])
+ ])
+
+CRYPTO_NO_DEPRECATE_WARN=
+AS_IF([test "x$v3_include" = "xyes" && test "$CRYPTO_APP" != ""],
+ [CRYPTO_NO_DEPRECATE_WARN="-Wno-deprecated-declarations"
+ ])
+
+saveCFLAGS="$CFLAGS"
+saveLDFLAGS="$LDFLAGS"
+saveLIBS="$LIBS"
+CFLAGS="$DED_BASIC_CFLAGS $SSL_INCLUDE"
+AS_IF([test $SSL_DYNAMIC_ONLY = yes],
+ [
+ LDFLAGS="$DED_LDFLAGS_CONFTEST $ded_ld_rpath -L$SSL_LIBDIR"
+ LIBS="$LIBS -l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"
+ ],
+ [
+ LDFLAGS="$DED_LDFLAGS_CONFTEST"
+ AS_IF([test "$host_os" = "win32"],
+ [LIBS="$LIBS $SSL_LIBDIR/$SSL_CRYPTO_LIBNAME.lib $SSL_EXTRA_LIBS"],
+ [LIBS="$LIBS $SSL_LIBDIR/lib$SSL_CRYPTO_LIBNAME.a $SSL_EXTRA_LIBS"])
+ ])
+AC_CHECK_DECL([CRYPTO_memcmp],
+ [have_crypto_memcmp_decl=yes],
+ [have_crypto_memcmp_decl=no],
+ [#include <openssl/crypto.h>])
+AS_IF([test $have_crypto_memcmp_decl = yes],
+ [
+ AC_MSG_CHECKING([whether CRYPTO_memcmp can be linked])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[
+ #include <openssl/crypto.h>
+ ]],
+ [[
+ CRYPTO_memcmp("a", "b", 1);
+ ]])],
+ [
+ SSL_FLAGS="-DHAVE_OPENSSL_CRYPTO_MEMCMP $SSL_FLAGS"
+ AC_MSG_RESULT([yes])
+ ],
+ [
+ AC_MSG_RESULT([no])
+ ])
+ ])
+CFLAGS="$saveCFLAGS"
+LDFLAGS="$saveLDFLAGS"
+LIBS="$saveLIBS"
+
+AC_SUBST(SSL_INCLUDE)
+AC_SUBST(SSL_INCDIR)
+AC_SUBST(SSL_LIBDIR)
+AC_SUBST(SSL_FLAGS)
+AC_SUBST(SSL_CRYPTO_LIBNAME)
+AC_SUBST(SSL_SSL_LIBNAME)
+AC_SUBST(SSL_EXTRA_LIBS)
+AC_SUBST(SSL_DED_LD_RUNTIME_LIBRARY_PATH)
+AC_SUBST(SSL_DYNAMIC_ONLY)
+AC_SUBST(DISABLE_EVP_DH)
+AC_SUBST(DISABLE_EVP_HMAC)
+AC_SUBST(DISABLE_OTP_TEST_ENGINE)
+AC_SUBST(CRYPTO_NO_DEPRECATE_WARN)
+
+AC_CONFIG_FILES([c_src/$host/Makefile:c_src/Makefile.in])
+AC_OUTPUT
+
diff --git a/lib/crypto/configure.in b/lib/crypto/configure.in
deleted file mode 100644
index 377acccd80..0000000000
--- a/lib/crypto/configure.in
+++ /dev/null
@@ -1,871 +0,0 @@
-dnl Process this file with autoconf to produce a configure script. -*-m4-*-
-dnl
-dnl %CopyrightBegin%
-dnl
-dnl Copyright Ericsson AB 2018-2022. All Rights Reserved.
-dnl
-dnl Licensed under the Apache License, Version 2.0 (the "License");
-dnl you may not use this file except in compliance with the License.
-dnl You may obtain a copy of the License at
-dnl
-dnl http://www.apache.org/licenses/LICENSE-2.0
-dnl
-dnl Unless required by applicable law or agreed to in writing, software
-dnl distributed under the License is distributed on an "AS IS" BASIS,
-dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-dnl See the License for the specific language governing permissions and
-dnl limitations under the License.
-dnl
-dnl %CopyrightEnd%
-dnl
-
-dnl define([AC_CACHE_LOAD], )dnl
-dnl define([AC_CACHE_SAVE], )dnl
-
-
-AC_INIT(vsn.mk)
-
-## Delete previous failed configure results
-if test -f ./CONF_INFO; then
- rm ./CONF_INFO
-fi
-
-AC_CONFIG_AUX_DIRS(${ERL_TOP}/erts/autoconf)
-
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
-
-AC_LANG(C)
-
-LM_PRECIOUS_VARS
-
-if test "$cross_compiling" = "yes"; then
- CROSS_COMPILING=yes
-else
- CROSS_COMPILING=no
-fi
-AC_SUBST(CROSS_COMPILING)
-
-ERL_XCOMP_SYSROOT_INIT
-
-AC_PROG_CC
-LM_WINDOWS_ENVIRONMENT
-
-ERL_DED
-
-AC_MSG_CHECKING([for multiarch directory])
-multiarch_dir=
-if test "$GCC" = "yes"; then
- multiarch_dir=`$CC $CFLAGS -print-multiarch 2>/dev/null`
- if test $? -ne 0; then
- multiarch_dir=
- fi
-fi
-if test "$multiarch_dir" = ""; then
- AC_MSG_RESULT([not found])
-else
- AC_MSG_RESULT([$multiarch_dir])
-fi
-
-dnl
-dnl SSL, SSH and CRYPTO need the OpenSSL libraries
-dnl
-dnl Check flags --with-ssl, --without-ssl --with-ssl=PATH.
-dnl If no option is given or --with-ssl is set without a path then we
-dnl search for OpenSSL libraries and header files in the standard locations.
-dnl If set to --without-ssl we disable the use of SSL, SSH and CRYPTO.
-dnl If set to --with-ssl=PATH we use that path as the prefix, i.e. we
-dnl use "PATH/include" and "PATH/lib".
-
-AC_CHECK_SIZEOF(void *)
-
-std_ssl_locations="/usr/local /usr/sfw /usr /opt/local /usr/pkg /usr/local/openssl /usr/local/opt/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /"
-
-AC_ARG_WITH(ssl,
-AS_HELP_STRING([--with-ssl=PATH], [base location of OpenSSL include and lib directories])
-AS_HELP_STRING([--with-ssl], [use SSL (default)])
-AS_HELP_STRING([--without-ssl], [don't use SSL]))
-
-AC_ARG_WITH(ssl-lib-subdir,
-AS_HELP_STRING([--with-ssl-lib-subdir=RELATIVE_PATH],
- [specify extra OpenSSL lib sub-directory to search in (relative to base directory)]),
-[
-case "$with_ssl_lib_subdir" in
- yes|no)
- with_ssl_lib_subdir=
- ;;
- *)
- ;;
-esac
-],
-[with_ssl_lib_subdir=]) #default
-
-AC_ARG_WITH(ssl-incl,
-AS_HELP_STRING([--with-ssl-incl=PATH],
- [base location of OpenSSL include dir (if different than base location specified by --with-ssl=PATH)]),
-[
-case X$with_ssl in
- X | Xyes | Xno) AC_MSG_ERROR([--with-ssl-incl=PATH set without --with-ssl=PATH]);;
-esac
-],
-[with_ssl_incl=$with_ssl]) #default
-
-AC_ARG_WITH(ssl-zlib,
-AS_HELP_STRING([--with-ssl-zlib=PATH], [Path to static zlib library to link the
- crypto NIF with. This zlib library is most
- often not necessary but might be needed in
- order to link the NIF in some cases.]),
-[], [with_ssl_zlib=default]) #default
-
-AC_ARG_WITH(ssl-rpath,
-AS_HELP_STRING([--with-ssl-rpath=yes|no|PATHS],
- [runtime library path for OpenSSL. Default is "yes", which equates to a
- number of standard locations. If "no", then no runtime
- library paths will be used. Anything else should be a
- comma or colon separated list of paths.]),
-[
-case X$with_ssl in
- Xno) AC_MSG_ERROR([--with-ssl-rpath set without --with-ssl]);;
-esac
-],
-[with_ssl_rpath=default]) #default
-
-
-AC_ARG_ENABLE(dynamic-ssl-lib,
-AS_HELP_STRING([--enable-dynamic-ssl-lib],
- [enable using dynamic openssl libraries when linking the crypto NIF])
-AS_HELP_STRING([--disable-dynamic-ssl-lib],
- [disable using dynamic openssl libraries when linking the crypto NIF]),
-[ case "$enableval" in
- no) enable_dynamic_ssl=no ;;
- *) enable_dynamic_ssl=yes ;;
- esac ], enable_dynamic_ssl=undefined)
-
-AC_ARG_ENABLE(evp-dh,
-AS_HELP_STRING([--disable-evp-dh],
- [intentionally undocumented workaround]),
-[ case "$enableval" in
- no) DISABLE_EVP_DH=1;;
- *) DISABLE_EVP_DH=0;;
- esac ], DISABLE_EVP_DH=0)
-
-
-AC_ARG_ENABLE(evp-hmac,
-AS_HELP_STRING([--disable-evp-hmac],
- [intentionally undocumented workaround]),
-[ case "$enableval" in
- no) DISABLE_EVP_HMAC=1;;
- *) DISABLE_EVP_HMAC=0;;
- esac ], DISABLE_EVP_HMAC=0)
-
-
-AC_ARG_ENABLE(otp-test-engine,
-AS_HELP_STRING([--disable-otp-test-engine],
- [Disable build of the otp_test_engine. (default is --enable-otp-test-engine, unless for LibreSSL >= 3.5.0 where default is --disable-otp-test-engine)]),
-[ case "$enableval" in
- no) DISABLE_OTP_TEST_ENGINE=yes;;
- *) DISABLE_OTP_TEST_ENGINE=no;;
- esac ], DISABLE_OTP_TEST_ENGINE=default)
-
-AC_ARG_ENABLE(deprecated_warnings,
-AS_HELP_STRING([--disable-deprecated-warnings],
- [disable warnings for deprecated functions in cryptolib (default is to warn, except for OpenSSL 3.x where the default is not to warn)]),
-[ case "$enableval" in
- no) deprecated_warnings=no;;
- *) deprecated_warnings=yes;;
- esac ], deprecated_warnings=default_yes)
-
-AC_DEFUN([ERL_LINK_CRYPTO_IFELSE], [
- test_cflags=$1
- test_ldflags=$2
- test_libs=$3
-
- saveCFLAGS="$CFLAGS"
- saveLDFLAGS="$LDFLAGS"
- saveLIBS="$LIBS"
- CFLAGS="$DED_BASIC_CFLAGS $test_cflags"
- LDFLAGS="$DED_LDFLAGS_CONFTEST $test_ldflags"
- LIBS="$LIBS $test_libs"
-
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM(
- [[
- #include <stdio.h>
- #include <openssl/hmac.h>
- ]],
- [[
- HMAC(0, 0, 0, 0, 0, 0, 0);
- ]])],
- [
- $4
- ],
- [
- $5
- ])
-
- CFLAGS="$saveCFLAGS"
- LDFLAGS="$saveLDFLAGS"
- LIBS="$saveLIBS"
-])
-
-AC_DEFUN([ERL_CRYPTO_CHECK_LIB], [
- # Check for static and dynamic crypto library in the directory
- # given as argument...
- #
- # Written as a macro in order to avoid writing the tests twice...
- idir=$1
- prfx=$2
- rdir=$3
- dir="$prfx$rdir"
- static_crypto_lib_name=crypto
- static_ssl_lib_name=ssl
- static_extra_libs="$forced_static_zlib"
- static_lib_dir=
- dynamic_crypto_lib_name=crypto
- dynamic_ssl_lib_name=ssl
- dynamic_extra_libs="$forced_static_zlib"
- dynamic_lib_dir=
- dynamic_runtime_lib_dir=
- found_static_lib=no
- found_dynamic_lib=no
-
- save_CPPFLAGS=$CPPFLAGS
- CPPFLAGS="-I$idir/include"
- AC_EGREP_CPP(^yes.?$,[
-#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER >= 0x0090803fL
-yes
-#endif
- ],
- [valid_include=yes],
- [valid_include=no])
- AC_EGREP_CPP(^yes.?$,[
-#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_MAJOR == 3
-yes
-#endif
- ],
- [v3_include=yes],
- [v3_include=no])
-
-if test "x$DISABLE_OTP_TEST_ENGINE" = "xdefault"; then
-# Get default value for the --disable-otp-test-engine. Depends on cryptolib version
- AC_EGREP_CPP(^yes.?$,[
-#include <openssl/opensslv.h>
-#if LIBRESSL_VERSION_NUMBER >= 0x3050000fL
-yes
-#endif
- ],
- [DISABLE_OTP_TEST_ENGINE=yes],
- [DISABLE_OTP_TEST_ENGINE=no])
- fi
-
- CPPFLAGS="$save_CPPFLAGS"
-
- if test $valid_include != yes; then
- static_crypto_lib_name=
- static_ssl_lib_name=
- static_extra_libs=
- static_lib_dir=
- dynamic_crypto_lib_name=
- dynamic_ssl_lib_name=
- dynamic_extra_libs=
- dynamic_lib_dir=
- dynamic_runtime_lib_dir=
- elif test "$host_os" = "win32" ; then
- if test -f "$dir/lib/VC/static/libcrypto${lib_bits}MD.lib"; then
- static_crypto_lib_name=libcrypto${lib_bits}MD
- static_ssl_lib_name="libssl${lib_bits}MD"
- static_extra_libs="$static_extra_libs -lCRYPT32 -lWS2_32"
- static_lib_dir="$dir/lib/VC/static"
- found_static_lib=yes
- fi
- if test -f "$dir/lib/VC/libcrypto${lib_bits}MD.lib"; then
- dynamic_crypto_lib_name=libcrypto${lib_bits}MD
- dynamic_ssl_lib_name="libssl${lib_bits}MD"
- dynamic_runtime_lib_dir="$rdir/lib/VC"
- dynamic_lib_dir="$dir/lib/VC"
- found_dynamic_lib=yes
- fi
- else # Non windows...
-
- case "$host_os" in
- darwin*)
- static_ext=.a
- dynamic_ext=.dylib;;
- *)
- static_ext=.a
- dynamic_ext=.so;;
- esac
- for sdir in $search_subdirs; do
- if test -f "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"; then
- found_dynlib=yes
- else
- found_dynlib=no
- case $host_os in
- openbsd*)
- # libcrypto.so got a suffix on (at least some) openbsd.
- # If we find libcrypto.so with suffix, we try to link
- # to it using -lcrypto ...
- for f in "$dir/$sdir/lib$dynamic_crypto_lib_name$dynamic_ext"*; do
- test -f "$f" && found_dynlib=yes
- break
- done;;
- *)
- ;;
- esac
- fi
- if test $found_dynlib = yes; then
- # Found dynamic library; check if it links...
- dynamic_lib_dir="$dir/$sdir"
- dynamic_runtime_lib_dir="$rdir/$sdir"
- ERL_LINK_CRYPTO_IFELSE(
- ["-I$idir/include"],
- ["-L$dynamic_lib_dir"],
- ["-l$dynamic_crypto_lib_name $dynamic_extra_libs"],
- [found_dynamic_lib=yes],
- [found_dynamic_lib=no])
- if test $found_dynamic_lib = no -a $static_zlib != no; then
- # No, but linking with zlib as well might help...
- dynamic_extra_libs="$dynamic_extra_libs $static_zlib"
- ERL_LINK_CRYPTO_IFELSE(
- ["-I$idir/include"],
- ["-L$dynamic_lib_dir"],
- ["-l$dynamic_crypto_lib_name $dynamic_extra_libs"],
- [found_dynamic_lib=yes],
- [found_dynamic_lib=no])
- fi
- fi
- if test -f "$dir/$sdir/lib$static_crypto_lib_name$static_ext"; then
- # Found static library; check if it links...
- static_lib_dir="$dir/$sdir"
- ERL_LINK_CRYPTO_IFELSE(
- ["-I$idir/include"],
- [],
- ["$dir/$sdir/lib$static_crypto_lib_name$static_ext $static_extra_libs"],
- [found_static_lib=yes],
- [found_static_lib=no])
- if test $found_static_lib = no -a $static_zlib != no; then
- # No, but inking with zlib as well might help...
- static_extra_libs="$static_extra_libs $static_zlib"
- ERL_LINK_CRYPTO_IFELSE(
- ["-I$idir/include"],
- [],
- ["$dir/$sdir/lib$static_crypto_lib_name$static_ext $static_extra_libs"],
- [found_static_lib=yes],
- [found_static_lib=no])
- fi
- fi
- if test $found_static_lib = yes -o $found_dynamic_lib = yes; then
- break
- fi
- done
- fi
-])
-
-# Remove all SKIP files from previous runs
-for a in ssl crypto ssh; do
- rm -f "$ERL_TOP/lib/$a/SKIP"
-done
-
-# Setup subdirectories to search in...
-search_subdirs="lib"
-if test "$ac_cv_sizeof_void_p" = "8"; then
- search_subdirs="$search_subdirs lib64 lib/64"
-else
- search_subdirs="$search_subdirs lib32 lib/32"
-fi
-test "$multiarch_dir" = "" || search_subdirs="lib/$multiarch_dir $search_subdirs"
-test "$with_ssl_lib_subdir" = "" || search_subdirs="$with_ssl_lib_subdir $search_subdirs"
-
-# We might need to link with zlib, so first check if we can find
-# a static zlib to use if needed...
-static_zlib=no
-forced_static_zlib=
-case "$with_ssl_zlib" in
- no)
- ;;
- default | yes)
- AC_MSG_CHECKING([for static zlib])
- for dir in $std_ssl_locations; do
- for sdir in $search_subdirs; do
- if test -f "$erl_xcomp_sysroot$dir/$sdir/libz.a"; then
- static_zlib="$erl_xcomp_sysroot$dir/$sdir/libz.a"
- break
- fi
- done
- test "$static_zlib" = "no" || break
- done
- AC_MSG_RESULT([$static_zlib])
- if test $with_ssl_zlib = yes; then
- if test $static_zlib = no; then
- AC_MSG_ERROR([linking with zlib requested by user, but no such library was found])
- fi
- forced_static_zlib="$static_zlib"
- static_zlib=no
- fi;;
- *) # PATH
- AC_MSG_CHECKING([for static zlib])
- if test -f "$with_ssl_zlib/libz.a"; then
- forced_static_zlib="$with_ssl_zlib/libz.a"
- else
- for sdir in $search_subdirs; do
- if test -f "$with_ssl_zlib/$sdir/libz.a"; then
- forced_static_zlib="$with_ssl_zlib/$sdir/libz.a"
- break
- fi
- done
- fi
- if test "$forced_static_zlib" = ""; then
- AC_MSG_ERROR([linking with zlib requested by user, but no such library was found in $with_ssl_zlib])
- fi
- AC_MSG_RESULT([$forced_static_zlib])
- ;;
-esac
-
-if test $enable_dynamic_ssl = undefined; then
- if test "$host_os" = "win32" ; then
- enable_dynamic_ssl=default_no
- else
- enable_dynamic_ssl=default_yes
- fi
-fi
-
-case $enable_dynamic_ssl in
- yes|default_yes)
- SSL_DYNAMIC_ONLY=yes;;
- *)
- SSL_DYNAMIC_ONLY=no;;
-esac
-
-case "$erl_xcomp_without_sysroot-$with_ssl" in
- yes-* | no-no)
- SSL_APP=
- CRYPTO_APP=
- SSH_APP=
- if test "$with_ssl" != "no"; then
- skip="Cannot search for ssl; missing cross system root (erl_xcomp_sysroot)."
- fi
- for a in ssl crypto ssh; do
- echo "$skip" > $ERL_TOP/lib/$a/SKIP
- done
- ;;
- no-yes | no- )
- # We search for OpenSSL in the common OS standard locations.
- SSL_APP=ssl
- CRYPTO_APP=crypto
- SSH_APP=ssh
-
- if test "$host_os" = "win32" ; then
- if test "x$ac_cv_sizeof_void_p" = "x8"; then
- std_win_ssl_locations="/mnt/c/OpenSSL-Win64 /c/OpenSSL-Win64 /mnt/c/opt/local64/pgm/OpenSSL /opt/local64/pgm/OpenSSL /cygdrive/c/OpenSSL-Win64"
- lib_bits=64
- else
- std_win_ssl_locations="/mnt/c/OpenSSL-Win32 /c/OpenSSL-Win32 /mnt/c/OpenSSL /c/OpenSSL /cygdrive/c/OpenSSL /opt/local/pgm/OpenSSL /opt/local32/pgm/OpenSSL /mnt/c/opt/local/pgm/OpenSSL /mnt/c/opt/local32/pgm/OpenSSL /cygdrive/c/OpenSSL-Win32"
- lib_bits=32
- fi
- else
- std_win_ssl_locations=""
- fi
-
- usable_crypto=no
- AC_MSG_CHECKING([for OpenSSL crypto library with version >= 0.9.8c in standard locations])
- for rdir in $std_win_ssl_locations $std_ssl_locations; do
- if test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"; then
- SSL_INCDIR="$erl_xcomp_isysroot$rdir"
- SSL_INCLUDE="-I$SSL_INCDIR/include"
- ERL_CRYPTO_CHECK_LIB(["$SSL_INCDIR"], ["$erl_xcomp_sysroot"], ["$rdir"])
- case $enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib in
- no-*-no)
- ;; # Dynamic linking against ssl library disabled by user, and no static library found
- yes-no-*)
- ;; # Static linking against ssl library disabled by user, and no dynamic library found
- *-no-no)
- ;; # Neither static nor dynamic ssl library found
- no-*-yes | default_no-*-yes | default_yes-no-yes)
- # Link statically...
- SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
- SSL_SSL_LIBNAME=$static_ssl_lib_name
- SSL_LIBDIR="$static_lib_dir"
- SSL_EXTRA_LIBS="$static_extra_libs"
- SSL_RUNTIME_LIBDIR=
- SSL_DYNAMIC_ONLY=no
- usable_crypto=yes
- break;;
- *-yes-*)
- # Link dynamically...
- SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
- SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
- SSL_EXTRA_LIBS="$dynamic_extra_libs"
- SSL_LIBDIR="$dynamic_lib_dir"
- SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
- SSL_DYNAMIC_ONLY=yes
- usable_crypto=yes
- break;;
- esac
- fi
- done
-
- if test $usable_crypto = yes ; then
- if test $SSL_DYNAMIC_ONLY = yes; then
- AC_MSG_RESULT([dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])
- else
- AC_MSG_RESULT([static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])
- fi
- else
- AC_MSG_RESULT([no])
- SSL_APP=
- CRYPTO_APP=
- SSH_APP=
-
- SSL_INCDIR=
- SSL_INCLUDE=
- SSL_CRYPTO_LIBNAME=
- SSL_SSL_LIBNAME=
- SSL_INCDIR=
- SSL_RUNTIME_LIBDIR=
- SSL_LIBDIR=
-
- case "$with_ssl-$enable_dynamic_ssl" in
- yes-yes)
- AC_MSG_ERROR([crypto library with dynamic linking requested by user, but no such library was found])
- ;;
- yes-no)
- AC_MSG_ERROR([crypto library with static linking requested by user, but no such library was found])
- ;;
- yes-*)
- AC_MSG_ERROR([crypto library requested by user, but no such library was found])
- ;;
- *)
- AC_MSG_WARN([No (usable) OpenSSL found, skipping ssl, ssh and crypto applications])
- ;;
- esac
-
- for a in ssl crypto ssh; do
- echo "No usable OpenSSL found" > $ERL_TOP/lib/$a/SKIP
- done
- fi
- ;;
- *)
- # Option given with PATH to package
- if test ! -d "$with_ssl" ; then
- AC_MSG_ERROR(Invalid path to option --with-ssl=PATH)
- fi
- if test ! -d "$with_ssl_incl" ; then
- AC_MSG_ERROR(Invalid path to option --with-ssl-incl=PATH)
- fi
- AC_MSG_CHECKING([for OpenSSL header in $with_ssl_incl])
- if test -f "$with_ssl_incl/include/openssl/opensslv.h"; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_ERROR([no OpenSSL header found in $with_ssl_incl])
- fi
- SSL_INCDIR="$with_ssl_incl"
- AC_MSG_CHECKING([for OpenSSL in $with_ssl])
- ERL_CRYPTO_CHECK_LIB(["$with_ssl_incl"], [""], ["$with_ssl"])
- case $enable_dynamic_ssl-$found_dynamic_lib-$found_static_lib in
- no-*-no)
- AC_MSG_ERROR([dynamic linking against crypto library disabled by user, but no static library found in $with_ssl]);;
- yes-no-*)
- AC_MSG_ERROR([static linking against crypto library disabled by user, but no dynamic library found in $with_ssl]);;
- *-no-no)
- AC_MSG_ERROR([neither static nor dynamic crypto library found in $with_ssl]);;
- no-*-yes | default_no-*-yes | default_yes-no-yes)
- # Link statically...
- SSL_CRYPTO_LIBNAME=$static_crypto_lib_name
- SSL_SSL_LIBNAME=$static_ssl_lib_name
- SSL_LIBDIR="$static_lib_dir"
- SSL_EXTRA_LIBS="$static_extra_libs"
- SSL_RUNTIME_LIBDIR=
- SSL_DYNAMIC_ONLY=no;;
- *-yes-*)
- # Link dynamically...
- SSL_CRYPTO_LIBNAME=$dynamic_crypto_lib_name
- SSL_SSL_LIBNAME=$dynamic_ssl_lib_name
- SSL_EXTRA_LIBS="$dynamic_extra_libs"
- SSL_LIBDIR="$dynamic_lib_dir"
- SSL_RUNTIME_LIBDIR="$dynamic_runtime_lib_dir"
- SSL_DYNAMIC_ONLY=yes;;
- esac
- if test $SSL_DYNAMIC_ONLY = yes; then
- AC_MSG_RESULT([dynamic $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])
- else
- AC_MSG_RESULT([static $SSL_CRYPTO_LIBNAME library in $SSL_LIBDIR])
- fi
- SSL_INCLUDE="-I$with_ssl_incl/include"
- SSL_APP=ssl
- CRYPTO_APP=crypto
- SSH_APP=ssh
- if test "$cross_compiling" = "yes"; then
- SSL_RUNTIME_LIBDIR=`echo "$SSL_LIBDIR" | sed -n "s|^$erl_xcomp_sysroot\(/*\)\(.*\)\$|/\2|p"`
- else
- SSL_RUNTIME_LIBDIR="$SSL_LIBDIR"
- fi
-esac
-
-SSL_DED_LD_RUNTIME_LIBRARY_PATH=
-ded_ld_rflg="$DED_LD_FLAG_RUNTIME_LIBRARY_PATH"
-
-
-case "$with_ssl_rpath" in
-
-yes | default) # Use standard lib locations for ssl runtime library path
-
- AC_MSG_CHECKING([for runtime library path to use])
-
- if test $enable_dynamic_ssl = no -a "$with_ssl_rpath" = yes; then
- AC_MSG_ERROR([requested by user, but user also requested static linking])
- fi
-
- if test "$CRYPTO_APP" = ""; then
- if test "$with_ssl_rpath" = yes; then
- AC_MSG_ERROR([requested by user, but could not be used since no crypto library was found])
- fi
- AC_MSG_RESULT([])
- elif test "$ded_ld_rflg" = ""; then
- if test "$with_ssl_rpath" = yes; then
- AC_MSG_ERROR([requested by user, but cannot be set on this platform])
- fi
- AC_MSG_RESULT([])
- elif test "$SSL_DYNAMIC_ONLY" != "yes"; then
- if test "$with_ssl_rpath" = yes; then
- AC_MSG_WARN([requested by user, but dynamic linking will not be used])
- else
- AC_MSG_RESULT([])
- fi
- else
-
- libdirs="/lib"
-
- dir_lib64=no
- dir_lib_64=no
- dir_lib32=no
- dir_lib_32=no
- dir_multiarch=no
- dir_with_ssl_lib_subdir=no
-
- test "$multiarch_dir" = "" || dir_multiarch=yes
- test "$with_ssl_lib_subdir" = "" || dir_with_ssl_lib_subdir=yes
-
- case "$SSL_RUNTIME_LIBDIR" in
- */lib/64 | */lib/64/ ) dir_lib_64=yes;;
- */lib64 | */lib64/ ) dir_lib64=yes;;
- */lib/32 | */lib/32/ ) dir_lib_32=yes;;
- */lib32 | */lib32/ ) dir_lib32=yes;;
- *) ;;
- esac
-
- for dir in $std_ssl_locations; do
- if test "$ac_cv_sizeof_void_p" = "8"; then
- test $dir_lib_64 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib/64" &&
- dir_lib_64=yes
- test $dir_lib64 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib64" &&
- dir_lib64=yes
- else
- test $dir_lib_32 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib/32" &&
- dir_lib_32=yes
- test $dir_lib32 = no &&
- test -d "$erl_xcomp_sysroot$dir/lib32" &&
- dir_lib32=yes
- fi
- test $dir_multiarch = no &&
- test -d "$erl_xcomp_sysroot$dir/lib/$multiarch_dir" &&
- dir_multiarch=yes
- done
-
- test $dir_with_ssl_lib_subdir = yes && libdirs="/$with_ssl_lib_subdir $libdirs"
- test $dir_multiarch = yes && libdirs="/lib/$multiarch_dir $libdirs"
- test $dir_lib_64 = yes && libdirs="/lib/64 $libdirs"
- test $dir_lib64 = yes && libdirs="/lib64 $libdirs"
- test $dir_lib_32 = yes && libdirs="/lib/32 $libdirs"
- test $dir_lib32 = yes && libdirs="/lib32 $libdirs"
-
- #
- # We try the following runtime paths in the
- # following order:
- # 1. Standard ssl locations with all variations
- # of lib subdirectories that we know of
- # 2. Standard ssl locations with all variations
- # of lib subdirectories that we know of and
- # exist on this machine
- # 3. Determined $SSL_RUNTIME_LIBDIR
- # If none of the above links, we skip runtime
- # library path...
- #
- for type in std x_std curr; do
-
- ded_ld_rpath="$ded_ld_rflg$SSL_RUNTIME_LIBDIR"
- rpath="$SSL_RUNTIME_LIBDIR"
-
- if test $type != curr; then
- for ldir in $libdirs; do
- for dir in $std_ssl_locations; do
- test "$SSL_RUNTIME_LIBDIR" != "$dir$ldir" || continue
- test $type != x_std || test -d "$erl_xcomp_sysroot$dir$ldir" || continue
- if test "$dir" = "/"; then
- libdir="$ldir"
- else
- libdir="$dir$ldir"
- fi
- ded_ld_rpath="$ded_ld_rpath $ded_ld_rflg$libdir"
- rpath="$rpath:$libdir"
- done
- done
- fi
-
- # Check that it still links when we add the runtime path...
- ERL_LINK_CRYPTO_IFELSE(
- ["$SSL_INCLUDE"],
- ["$ded_ld_rpath -L$SSL_LIBDIR"],
- ["-l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"],
- [rpath_success=yes],
- [rpath_success=no])
-
- test "$rpath_success" = "yes" && break
- done
-
- test "$rpath_success" = "yes" || { ded_ld_rpath=; rpath=; }
-
- SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
-
- if test "$rpath" != ""; then
- AC_MSG_RESULT([$rpath])
- elif test "$with_ssl_rpath" = yes; then
- AC_MSG_ERROR([requested by user, but could not be used])
- else
- AC_MSG_WARN([unable to set run path during linking])
- fi
- fi
- ;;
-
-no) # Use no ssl runtime library path
- SSL_DED_LD_RUNTIME_LIBRARY_PATH=
- ;;
-
-*) # Use ssl runtime library paths set by --with-ssl-rpath (without any check)
- AC_MSG_CHECKING([whether runtime library path can be set])
-
- if test $enable_dynamic_ssl = no; then
- AC_MSG_ERROR([runtime library path requested by user, but user also requested static linking])
- elif test "$CRYPTO_APP" = ""; then
- if test "$with_ssl_rpath" = yes; then
- AC_MSG_ERROR([runtime library path requested by user, but could not be set since no crypto library was found])
- fi
- AC_MSG_RESULT([])
- elif test "$ded_ld_rflg" = ""; then
- if test "$with_ssl_rpath" = yes; then
- AC_MSG_ERROR([runtime library path requested by user, but cannot be set on this platform])
- fi
- AC_MSG_RESULT([])
- elif test "$SSL_DYNAMIC_ONLY" != "yes"; then
- if test "$with_ssl_rpath" = yes; then
- AC_MSG_WARN([runtime library path requested by user, but dynamic linking will not be used])
- else
- AC_MSG_RESULT([])
- fi
- else
- ded_ld_rpath=
- delimit=
- rpath=
- rpath_delimit=
- save_ifs="$IFS"; IFS=",:"
- for dir in $with_ssl_rpath; do
- ded_ld_rpath="$ded_ld_rpath$delimit$ded_ld_rflg$dir"
- delimit=" "
- rpath="$rpath$rpath_delimit$dir"
- rpath_delimit=":"
- done
- IFS="$save_ifs"
- SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
- ERL_LINK_CRYPTO_IFELSE(
- ["$SSL_INCLUDE"],
- ["$ded_ld_rpath -L$SSL_LIBDIR"],
- ["-l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"],
- [rpath_success=yes],
- [rpath_success=no])
- if test "$rpath_success" = yes; then
- AC_MSG_RESULT([yes; using $rpath])
- else
- AC_MSG_ERROR([runtime library path requested by user, but link failed])
- fi
- fi
- ;;
-
-esac
-
-
-AC_ARG_ENABLE(fips,
-AS_HELP_STRING([--enable-fips], [enable OpenSSL FIPS mode support])
-AS_HELP_STRING([--disable-fips], [disable OpenSSL FIPS mode support (default)]),
-[ case "$enableval" in
- yes) enable_fips_support=yes ;;
- *) enable_fips_support=no ;;
- esac ], enable_fips_support=no)
-
-if test "x$enable_fips_support" = "xyes" && test "$CRYPTO_APP" != ""; then
- saveCFLAGS="$CFLAGS"
- saveLDFLAGS="$LDFLAGS"
- saveLIBS="$LIBS"
- CFLAGS="$DED_BASIC_CFLAGS $SSL_INCLUDE"
- if test $SSL_DYNAMIC_ONLY = yes; then
- LDFLAGS="$DED_LDFLAGS_CONFTEST $ded_ld_rpath -L$SSL_LIBDIR"
- LIBS="$LIBS -l$SSL_CRYPTO_LIBNAME $SSL_EXTRA_LIBS"
- else
- LDFLAGS="$DED_LDFLAGS_CONFTEST"
- if test "$host_os" = "win32" ; then
- LIBS="$LIBS $SSL_LIBDIR/$SSL_CRYPTO_LIBNAME.lib $SSL_EXTRA_LIBS"
- else
- LIBS="$LIBS $SSL_LIBDIR/lib$SSL_CRYPTO_LIBNAME.a $SSL_EXTRA_LIBS"
- fi
- fi
- AC_CHECK_FUNC([FIPS_mode_set],
- [SSL_FLAGS="-DFIPS_SUPPORT"],
- [SSL_FLAGS=])
- CFLAGS="$saveCFLAGS"
- LDFLAGS="$saveLDFLAGS"
- LIBS="$saveLIBS"
-else
- SSL_FLAGS=
-fi
-
-if test "x$v3_include" = "xyes"; then
- echo "Using OpenSSL 3.0 is not yet recommended for production code." >> ./CONF_INFO
- AC_MSG_WARN(******************************************************************)
- AC_MSG_WARN(* Using OpenSSL 3.0 is not yet recommended for production code. *)
-
- if test "x$SSL_DYNAMIC_ONLY" = "xno" ; then
- echo "Static linking with OpenSSL 3.0 *MAY* require special configuring of the cryptolib." >> ./CONF_INFO
- AC_MSG_WARN(* Static linking *MAY* require re-configuring the 3.0 cryptolib. *)
- fi
- AC_MSG_WARN(******************************************************************)
-fi
-
-if test "x$v3_include" = "xyes" && test "x$deprecated_warnings" = "xdefault_yes" && test "$CRYPTO_APP" != ""; then
- deprecated_warnings=no
-fi
-
-if test "x$deprecated_warnings" = "xno" && test "$CRYPTO_APP" != "" ; then
- SSL_FLAGS="$SSL_FLAGS -Wno-deprecated-declarations"
-fi
-
-AC_SUBST(SSL_INCLUDE)
-AC_SUBST(SSL_INCDIR)
-AC_SUBST(SSL_LIBDIR)
-AC_SUBST(SSL_FLAGS)
-AC_SUBST(SSL_CRYPTO_LIBNAME)
-AC_SUBST(SSL_SSL_LIBNAME)
-AC_SUBST(SSL_EXTRA_LIBS)
-AC_SUBST(SSL_DED_LD_RUNTIME_LIBRARY_PATH)
-AC_SUBST(SSL_DYNAMIC_ONLY)
-AC_SUBST(DISABLE_EVP_DH)
-AC_SUBST(DISABLE_EVP_HMAC)
-AC_SUBST(DISABLE_OTP_TEST_ENGINE)
-
-AC_OUTPUT(c_src/$host/Makefile:c_src/Makefile.in)
-
diff --git a/lib/crypto/doc/src/algorithm_details.xml b/lib/crypto/doc/src/algorithm_details.xml
index dce04a1409..767fa3cd6f 100644
--- a/lib/crypto/doc/src/algorithm_details.xml
+++ b/lib/crypto/doc/src/algorithm_details.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2014</year><year>2021</year>
+ <year>2014</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -111,6 +111,9 @@
<row><cell><c>aes_128_ctr</c></cell> <cell>16</cell> <cell>16</cell> <cell>&nbsp;1</cell> <cell></cell></row>
<row><cell><c>aes_192_ctr</c></cell> <cell>24</cell> <cell>16</cell> <cell>&nbsp;1</cell> <cell></cell></row>
<row><cell><c>aes_256_ctr</c></cell> <cell>32</cell> <cell>16</cell> <cell>&nbsp;1</cell> <cell></cell></row>
+ <row><cell><c>aes_128_ofb</c></cell> <cell>16</cell> <cell>16</cell> <cell>&nbsp;1</cell> <cell></cell></row>
+ <row><cell><c>aes_192_ofb</c></cell> <cell>24</cell> <cell>16</cell> <cell>&nbsp;1</cell> <cell></cell></row>
+ <row><cell><c>aes_256_ofb</c></cell> <cell>32</cell> <cell>16</cell> <cell>&nbsp;1</cell> <cell></cell></row>
<row><cell><c>blowfish_cbc</c></cell> <cell>16</cell> <cell>&nbsp;8</cell> <cell>&nbsp;8</cell> <cell></cell></row>
<row><cell><c>blowfish_cfb64</c></cell><cell>16</cell> <cell>&nbsp;8</cell> <cell>&nbsp;1</cell> <cell></cell></row>
<row><cell><c>blowfish_ofb64</c></cell><cell>16</cell> <cell>&nbsp;8</cell> <cell>&nbsp;1</cell> <cell></cell></row>
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 937a32f21a..0d0ba07d8f 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -184,11 +184,6 @@
</p>
</note>
- <note><p>Compiling, linking and running with OpenSSL 3.0 works although the
- crypto app calls deprecated functions. We do not recommend it for other than
- experimental purposes or alpha testing, since it is not extensively tested yet.</p>
- </note>
-
<p>The <seeguide marker="index">CRYPTO User's Guide</seeguide> has more information on
FIPS, Engines and Algorithm Details like key lengths.
</p>
@@ -547,72 +542,67 @@
</desc>
</datatype>
- <datatype_title>Error types</datatype_title>
+ </datatypes>
- <datatype>
- <name name="run_time_error"/>
- <desc>
- <p>The exception <c>error:badarg</c> signifies that one or more arguments are of wrong data type,
- or are otherwise badly formed.
- </p>
- <p>The exception <c>error:notsup</c> signifies that the algorithm is known but is not supported
- by current underlying libcrypto or explicitly disabled when building that.
- </p>
- <p>For a list of supported algorithms, see <seemfa marker="#supports/1">supports(ciphers)</seemfa>.
- </p>
- </desc>
- </datatype>
- <datatype>
- <name name="descriptive_error"/>
- <desc>
- <p>This is a more developed variant of the older
- <seetype marker="#run_time_error">run_time_error()</seetype>.
- </p>
- <p>The exception is:</p>
- <pre>
- {Tag, {C_FileName,LineNumber}, Description}
+ <section>
+ <title>Exceptions</title>
+ <section>
+ <title>Atoms - the older style</title>
+ <marker id="error_old"/>
+ <p>The exception <c>error:badarg</c> signifies that one or more arguments are of wrong data type,
+ or are otherwise badly formed.
+ </p>
+ <p>The exception <c>error:notsup</c> signifies that the algorithm is known but is not supported
+ by current underlying libcrypto or explicitly disabled when building that.
+ </p>
+ <p>For a list of supported algorithms, see <seemfa marker="#supports/1">supports(ciphers)</seemfa>.
+ </p>
+ </section>
- Tag = badarg | notsup | error
- C_FileName = string()
- LineNumber = integer()
- Description = string()
- </pre>
+ <section>
+ <title>3-tuples - the new style</title>
+ <marker id="error_3tup"/>
+ <p>The exception is:</p>
+ <pre>
+error:{Tag, C_FileInfo, Description}
- <p>It is like the older type an exception of the <c>error</c> class. In addition they contain
- a descriptive text in English. That text is targeted to a developer. Examples are "Bad key size"
- or "Cipher id is not an atom".
- </p>
- <p>The exception tags are:</p>
- <taglist>
- <tag><c>badarg</c></tag>
- <item><p>Signifies that one or more arguments are of wrong data type or are otherwise badly formed.</p>
- </item>
+Tag = badarg | notsup | error
+C_FileInfo = term() % Usually only useful for the OTP maintainer
+Description = string() % Clear text, sometimes only useful for the OTP maintainer
+ </pre>
- <tag><c>notsup</c></tag>
- <item><p>Signifies that the algorithm is known but is not supported by current underlying libcrypto
- or explicitly disabled when building that one.</p>
- </item>
+ <p>The exception tags are:</p>
+ <taglist>
+ <tag><c>badarg</c></tag>
+ <item><p>Signifies that one or more arguments are of wrong data type or are otherwise badly formed.</p>
+ </item>
- <tag><c>error</c></tag>
- <item><p>An error condition that should not occur, for example a memory allocation failed or
- the underlying cryptolib returned an error code, for example "Can't initialize context, step 1".
- Those text usually needs searching the C-code to be understood.</p>
- </item>
- </taglist>
- <p>To catch the exception, use for example:</p>
- <code>
- try crypto:crypto_init(Ciph, Key, IV, true)
- catch
- error:{Tag, {C_FileName,LineNumber}, Description} ->
- do_something(......)
- .....
- end
- </code>
- </desc>
- </datatype>
+ <tag><c>notsup</c></tag>
+ <item><p>Signifies that the algorithm is known but is not supported by current underlying libcrypto
+ or explicitly disabled when building that one.</p>
+ </item>
- </datatypes>
+ <tag><c>error</c></tag>
+ <item><p>An error condition that should not occur, for example a memory allocation failed or
+ the underlying cryptolib returned an error code, for example <c>"Can't initialize context, step 1"</c>.
+ Those text usually needs searching the C-code to be understood.</p>
+ </item>
+ </taglist>
+
+ <p>Usually there are more information in the call stack about which argument caused the exception
+ and what the values where.</p>
+ <p>To catch the exception, use for example:</p>
+ <code>
+try crypto:crypto_init(Ciph, Key, IV, true)
+ catch
+ error:{Tag, _C_FileInfo, Description} ->
+ do_something(......)
+ .....
+end
+ </code>
+ </section>
+ </section>
<!--================ FUNCTIONS ================-->
@@ -622,6 +612,7 @@
<name name="crypto_init" arity="3" since="OTP 22.0"/>
<fsummary>Initializes a series of encryptions or decryptions</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Equivalent to the call
<seemfa marker="#crypto_init/4"><c>crypto_init(Cipher, Key, &lt;&lt;>>, FlagOrOptions)</c></seemfa>.
It is intended for ciphers without an IV (nounce).
@@ -633,6 +624,7 @@
<name name="crypto_init" arity="4" since="OTP 22.0"/>
<fsummary>Initializes a series of encryptions or decryptions</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
Initializes a series of encryptions or decryptions and creates an internal state
with a reference that is returned.
@@ -689,6 +681,7 @@
<name name="crypto_update" arity="2" since="OTP 22.0"/>
<fsummary>Do an actual crypto operation on a part of the full text</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
It does an actual crypto operation on a part of the full text. If the part is less
than a number of full blocks, only the full blocks (possibly none) are encrypted
@@ -708,6 +701,7 @@
<name name="crypto_dyn_iv_init" arity="3" since="OTP 22.0"/>
<fsummary>Initializes a series of encryptions or decryptions where the IV is provided later</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Initializes a series of encryptions or decryptions where the IV is provided later.
The actual encryption or decryption is done by
<seemfa marker="crypto#crypto_dyn_iv_update/3">crypto_dyn_iv_update/3</seemfa>.
@@ -722,6 +716,7 @@
<name name="crypto_final" arity="1" since="OTP 23.0"/>
<fsummary>Ends a series of encryptions or decryptions</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
Finalizes a series of encryptions or decryptions and delivers the final bytes of the final block.
The data returned from this function may be empty if no padding was enabled in
@@ -735,6 +730,7 @@
<name name="crypto_get_data" arity="1" since="OTP 23.0"/>
<fsummary>Get information about crypto states</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
Returns information about the State in the argument. The information is the form of a map,
which currently contains at least:
@@ -763,6 +759,7 @@
<name name="crypto_dyn_iv_update" arity="3" since="OTP 22.0"/>
<fsummary>Do an actual crypto operation on a part of the full text and the IV is supplied for each part</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
Do an actual crypto operation on a part of the full text and the IV is supplied for each part.
The <c>State</c> should be created with
@@ -775,6 +772,7 @@
<name name="crypto_one_time" arity="4" since="OTP 22.0"/>
<fsummary>Do a complete encrypt or decrypt of the full text</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>As <seemfa marker="#crypto_one_time/5">crypto_one_time/5</seemfa> but for ciphers without IVs.</p>
</desc>
</func>
@@ -783,6 +781,7 @@
<name name="crypto_one_time" arity="5" since="OTP 22.0"/>
<fsummary>Do a complete encrypt or decrypt of the full text</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
Do a complete encrypt or decrypt of the full text in the argument <c>Data</c>.
</p>
@@ -800,6 +799,7 @@
<name name="crypto_one_time_aead" arity="7" since="OTP 22.0"/>
<fsummary>Do a complete encrypt or decrypt with an AEAD cipher of the full text</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
Do a complete encrypt or decrypt with an AEAD cipher of the full text.
</p>
@@ -846,6 +846,7 @@
<name name="mac" arity="3" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Short for <seemfa marker="#mac/4">mac(Type, undefined, Key, Data)</seemfa>.
</p>
</desc>
@@ -855,6 +856,7 @@
<name name="mac" arity="4" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Computes a MAC (Message Authentication Code) of type <c>Type</c> from <c>Data</c>.
</p>
@@ -896,6 +898,7 @@
<name name="macN" arity="4" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Short for <seemfa marker="#macN/5">macN(Type, undefined, Key, Data, MacLength)</seemfa>.
</p>
</desc>
@@ -924,6 +927,7 @@
<name name="mac_init" arity="2" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Short for <seemfa marker="#mac_init/3">mac_init(Type, undefined, Key)</seemfa>.
</p>
</desc>
@@ -933,6 +937,7 @@
<name name="mac_init" arity="3" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Initializes the context for streaming MAC operations.
</p>
<p><c>Type</c> determines which mac algorithm to use in the MAC operation.
@@ -979,6 +984,7 @@
<name name="mac_update" arity="2" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Updates the MAC represented by <c>State0</c> using the given <c>Data</c> which
could be of any length.
</p>
@@ -995,6 +1001,7 @@
<name name="mac_final" arity="1" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Finalizes the MAC operation referenced by <c>State</c>. The <c>Mac</c> result will have
a default length depending on the <c>Type</c> and <c>SubType</c> in the
<seemfa marker="#mac_init/3">mac_init/2,3</seemfa> call.
@@ -1010,6 +1017,7 @@
<name name="mac_finalN" arity="2" since="OTP 22.1"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Finalizes the MAC operation referenced by <c>State</c>.
</p>
<p><c>Mac</c> will be a binary with at most <c>MacLength</c> bytes.
@@ -1037,6 +1045,7 @@
<name name="compute_key" arity="4" since="OTP R16B01"/>
<fsummary>Computes the shared secret</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Computes the shared secret from the private key and the other party's public key.
See also <seemfa marker="public_key:public_key#compute_key/2">public_key:compute_key/2</seemfa>
</p>
@@ -1057,19 +1066,34 @@
<name name="generate_key" arity="3" since="OTP R16B01"/>
<fsummary>Generates a public key of type <c>Type</c></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Generates a public key of type <c>Type</c>.
See also <seemfa marker="public_key:public_key#generate_key/1">public_key:generate_key/1</seemfa>.
- May raise exception:
</p>
- <list type="bulleted">
- <item><c>error:badarg</c>: an argument is of wrong type or has an illegal value,</item>
- <item><c>error:low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
- <item><c>error:computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
- </list>
+ <note>
+ <p>If the linked version of cryptolib is OpenSSL 3.0</p>
+ <list type="bulleted">
+ <item>
+ <p>and the <c>Type</c> is <c>dh</c> (diffie-hellman)</p>
+ </item>
+ <item>
+ <p>and the parameter <c>P</c> (in <seetype marker="#dh_params">dh_params()</seetype>)
+ is one of the MODP groups (see <url href="https://tools.ietf.org/html/rfc3526">RFC 3526</url>)</p>
+ </item>
+ <item>
+ <p>and the optional <c>PrivateKeyBitLength</c> parameter
+ (in <seetype marker="#dh_params">dh_params()</seetype>)
+ is present,</p>
+ </item>
+ </list>
+ <p>then the optional key length parameter must be at least
+ 224, 256, 302, 352 and 400 for group sizes of
+ 2048, 3072, 4096, 6144 and 8192, respectively.</p>
+ </note>
<note>
<p>RSA key generation is only available if the runtime was
built with dirty scheduler support. Otherwise, attempting to
- generate an RSA key will raise exception <c>error:notsup</c>.</p>
+ generate an RSA key will raise the exception <c>error:notsup</c>.</p>
</note>
</desc>
</func>
@@ -1078,9 +1102,8 @@
<name name="hash" arity="2" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p>
- <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
@@ -1088,11 +1111,10 @@
<name name="hash_init" arity="1" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<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 <seemfa marker="#hash_update/2">hash_update</seemfa>.</p>
- <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
@@ -1100,6 +1122,7 @@
<name name="hash_update" arity="2" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using <seemfa marker="#hash_init/1">hash_init</seemfa>
or a previous call to this function. <c>Data</c> can be any length. <c>NewContext</c>
@@ -1112,6 +1135,7 @@
<name name="hash_final" arity="1" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
from a previous call to <seemfa marker="#hash_update/2">hash_update</seemfa>.
The size of <c>Digest</c> is determined by the type of hash
@@ -1244,6 +1268,7 @@
<name name="private_decrypt" arity="4" since="OTP R16B01"/>
<fsummary>Decrypts CipherText using the private Key.</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seemfa marker="#public_encrypt/4">public_encrypt/4</seemfa> (or equivalent function)
using the <c>PrivateKey</c>, and returns the
@@ -1258,6 +1283,7 @@
<name name="private_encrypt" arity="4" since="OTP R16B01"/>
<fsummary>Encrypts PlainText using the private Key.</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
and returns the ciphertext. This is a low level signature operation
used for instance by older versions of the SSL protocol. See
@@ -1271,6 +1297,7 @@
<name name="public_decrypt" arity="4" since="OTP R16B01"/>
<fsummary>Decrypts CipherText using the public Key.</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seemfa marker="#private_encrypt/4">private_encrypt/4</seemfa>(or equivalent function)
using the <c>PrivateKey</c>, and returns the
@@ -1285,6 +1312,7 @@
<name name="public_encrypt" arity="4" since="OTP R16B01"/>
<fsummary>Encrypts PlainText using the public Key.</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
and returns the <c>CipherText</c>. This is a low level signature operation
used for instance by older versions of the SSL protocol. See also <seemfa
@@ -1621,6 +1649,7 @@ FloatValue = rand:uniform(). % again
<name name="sign" arity="5" since="OTP 20.1"/>
<fsummary> Create digital signature.</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Creates a digital signature.</p>
<p>The msg is either the binary "cleartext" data to be
signed or it is the hashed value of "cleartext" i.e. the
@@ -1636,6 +1665,7 @@ FloatValue = rand:uniform(). % again
<name name="verify" arity="6" since="OTP 20.1"/>
<fsummary>Verifies a digital signature.</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Verifies a digital signature</p>
<p>The msg is either the binary "cleartext" data to be
signed or it is the hashed value of "cleartext" i.e. the
@@ -1685,33 +1715,11 @@ FloatValue = rand:uniform(). % again
<func>
<name name="engine_load" arity="3" since="OTP 20.2"/>
- <fsummary>Dynamical load an encryption engine</fsummary>
+ <fsummary>Load an encryption engine</fsummary>
<desc>
<p>
- Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
- an engine handle. This function is the same as calling <c>engine_load/4</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
- returned if the engine can't be loaded.
- </p>
- <p>
- The function raises a <c>error:badarg</c> if the parameters are in wrong format.
- It may also raise the exception <c>error:notsup</c> in case there is
- no engine support in the underlying OpenSSL implementation.
- </p>
- <p>
- See also the chapter <seeguide marker="crypto:engine_load#engine_load">Engine Load</seeguide>
- in the User's Guide.
- </p>
- </desc>
- </func>
-
- <func>
- <name name="engine_load" arity="4" since="OTP 20.2"/>
- <fsummary>Dynamical load an encryption engine</fsummary>
- <desc>
- <p>
- Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
- an engine handle. An error tuple is returned if the engine can't be loaded.
+ Loads the OpenSSL engine given by <c>EngineId</c> if it is available and intialize it.
+ Returns ok and an engine handle, if the engine can't be loaded an error tuple is returned.
</p>
<p>
The function raises a <c>error:badarg</c> if the parameters are in wrong format.
@@ -1727,7 +1735,7 @@ FloatValue = rand:uniform(). % again
<func>
<name name="engine_unload" arity="1" since="OTP 20.2"/>
- <fsummary>Dynamical load an encryption engine</fsummary>
+ <fsummary>Unload an encryption engine</fsummary>
<desc>
<p>
Unloads the OpenSSL engine given by <c>Engine</c>.
@@ -1830,10 +1838,10 @@ FloatValue = rand:uniform(). % again
</func>
<func>
- <name name="engine_get_id" arity="1" since="OTP 21.0.6"/>
- <fsummary>Fetch engine ID</fsummary>
+ <name name="engine_register" arity="2" since="OTP 25.1"/>
+ <fsummary>Register engine for some methods</fsummary>
<desc>
- <p>Return the ID for the engine, or an empty binary if there is no id set.</p>
+ <p>Register engine to handle some type of methods, for example engine_method_digests.</p>
<p>
The function raises a <c>error:badarg</c> if the parameters are in wrong format.
It may also raise the exception <c>error:notsup</c> in case there is
@@ -1843,10 +1851,10 @@ FloatValue = rand:uniform(). % again
</func>
<func>
- <name name="engine_get_name" arity="1" since="OTP 21.0.6"/>
- <fsummary>Fetch engine name</fsummary>
+ <name name="engine_unregister" arity="2" since="OTP 25.1"/>
+ <fsummary>Unregister engine for some methods</fsummary>
<desc>
- <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
+ <p>Unregister engine so it don't handle some type of methods.</p>
<p>
The function raises a <c>error:badarg</c> if the parameters are in wrong format.
It may also raise the exception <c>error:notsup</c> in case there is
@@ -1856,60 +1864,37 @@ FloatValue = rand:uniform(). % again
</func>
<func>
- <name name="engine_list" arity="0" since="OTP 20.2"/>
- <fsummary>List the known engine ids</fsummary>
+ <name name="engine_get_id" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Fetch engine ID</fsummary>
<desc>
- <p>List the id's of all engines in OpenSSL's internal list.</p>
+ <p>Return the ID for the engine, or an empty binary if there is no id set.</p>
<p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
- <p>
- See also the chapter <seeguide marker="crypto:engine_load#engine_load">Engine Load</seeguide>
- in the User's Guide.
- </p>
- <p>
- May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying
- OpenSSL implementation.
- </p>
</desc>
</func>
<func>
- <name name="ensure_engine_loaded" arity="2" since="OTP 21.0.6"/>
- <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <name name="engine_get_name" arity="1" since="OTP 21.0.6"/>
+ <fsummary>Fetch engine name</fsummary>
<desc>
- <p>
- Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
- implementing the engine. This function is the same as calling <c>ensure_engine_loaded/3</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
- returned if the engine can't be loaded.
- </p>
+ <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
<p>
The function raises a <c>error:badarg</c> if the parameters are in wrong format.
It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
- <p>
- See also the chapter <seeguide marker="crypto:engine_load#engine_load">Engine Load</seeguide>
- in the User's Guide.
- </p>
</desc>
</func>
<func>
- <name name="ensure_engine_loaded" arity="3" since="OTP 21.0.6"/>
- <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <name name="engine_list" arity="0" since="OTP 20.2"/>
+ <fsummary>List the known engine ids</fsummary>
<desc>
+ <p>List the id's of all engines in OpenSSL's internal list.</p>
<p>
- Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
- implementing the engine. This function differs from the normal engine_load in that sense it
- also add the engine id to the internal list in OpenSSL. Then in the following calls to the function
- it just fetch the reference to the engine instead of loading it again.
- An error tuple is returned if the engine can't be loaded.
- </p>
- <p>
- The function raises a <c>error:badarg</c> if the parameters are in wrong format.
It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
@@ -1917,21 +1902,36 @@ FloatValue = rand:uniform(). % again
See also the chapter <seeguide marker="crypto:engine_load#engine_load">Engine Load</seeguide>
in the User's Guide.
</p>
+ <p>
+ May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying
+ OpenSSL implementation.
+ </p>
</desc>
</func>
<func>
- <name name="ensure_engine_unloaded" arity="1" since="OTP 21.0.6"/>
- <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <name name="ensure_engine_loaded" arity="2" since="OTP 21.0.6"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
<desc>
<p>
- Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
- It both removes the label from the OpenSSL internal engine list and unloads the engine.
- This function is the same as calling <c>ensure_engine_unloaded/2</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
- returned if the engine can't be unloaded.
+ Loads an engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. An error tuple is returned if the engine can't be loaded.
+
+ </p>
+ <p>
+ This function differs from the normal engine_load in the sense that it
+ also add the engine id to OpenSSL's internal engine list. The difference between
+ the first call and the following is that the first loads the engine with the dynamical
+ engine and the following calls fetch it from the OpenSSL's engine list.
+ All references that is returned are equal.
</p>
<p>
+ Use <c>engine_unload/1</c> function to remove the references. But remember that
+ <c>engine_unload/1</c> just removes the references to the engine and not the
+ tag in OpenSSL's engine list. That has to be done with the <c>engine_remove/1</c>
+ function when needed (just called once, from any of the references you got).
+ </p>
+ <p>
The function raises a <c>error:badarg</c> if the parameters are in wrong format.
It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
@@ -1944,22 +1944,15 @@ FloatValue = rand:uniform(). % again
</func>
<func>
- <name name="ensure_engine_unloaded" arity="2" since="OTP 21.0.6"/>
- <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <name name="hash_equals" arity="2" since="OTP 25.0"/>
+ <fsummary>Constant time memory comparison for fixed length binaries</fsummary>
<desc>
- <p>
- Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
- It both removes the label from the OpenSSL internal engine list and unloads the engine.
- An error tuple is returned if the engine can't be unloaded.
- </p>
- <p>
- The function raises a <c>error:badarg</c> if the parameters are in wrong format.
- It may also raise the exception <c>error:notsup</c> in case there is
- no engine support in the underlying OpenSSL implementation.
- </p>
- <p>
- See also the chapter <seeguide marker="crypto:engine_load#engine_load">Engine Load</seeguide>
- in the User's Guide.
+ <p>
+ Constant time memory comparison for fixed length binaries, such as results of HMAC computations.
+ </p>
+ <p>
+ Returns true if the binaries are identical, false if they are of the same length but not identical.
+ The function raises an <c>error:badarg</c> exception if the binaries are of different size.
</p>
</desc>
</func>
@@ -1968,12 +1961,10 @@ FloatValue = rand:uniform(). % again
<name name="pbkdf2_hmac" arity="5" since="OTP 24.2"/>
<fsummary>PBKDF2 in combination with HMAC</fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>
PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination with HMAC.
</p>
- <p>
- The function raises a <c>error:badarg</c> if the parameters are in wrong format.
- </p>
</desc>
</func>
diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml
index 84fad2f5b8..dcc86cd49c 100644
--- a/lib/crypto/doc/src/crypto_app.xml
+++ b/lib/crypto/doc/src/crypto_app.xml
@@ -50,12 +50,9 @@
LibreSSL should also work.</p>
<p>The crypto app is tested daily with at least one version of each of the
- OpenSSL 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0 and 1.1.1. FIPS mode is also tested.</p>
+ OpenSSL 1.0.1, 1.0.2, 1.1.0, 1.1.1 and 3.0. FIPS mode is also tested for 1.0.1 and 1.0.2.</p>
- <note><p>Compiling, linking and running with OpenSSL 3.0 works although the
- crypto app calls deprecated functions. We do not recommend it for other than
- experimental purposes or alpha testing, since it is not extensively tested yet.</p>
- </note>
+ <p>Using OpenSSL 3.0 with Engines or in FIPS mode is not yet supported by the OTP/crypto app.</p>
<p>Source releases of OpenSSL can be downloaded from the <url href="http://www.openssl.org">OpenSSL</url> project home page,
or mirror sites listed there.
diff --git a/lib/crypto/doc/src/engine_load.xml b/lib/crypto/doc/src/engine_load.xml
index 5f7ccc784b..cefb72320d 100644
--- a/lib/crypto/doc/src/engine_load.xml
+++ b/lib/crypto/doc/src/engine_load.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2017</year><year>2018</year>
+ <year>2017</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -81,19 +81,15 @@
replace some engine methods.
</p>
<code>
- 3> Methods = crypto:engine_get_all_methods() -- [engine_method_dh,engine_method_rand,
-engine_method_ciphers,engine_method_digests, engine_method_store,
-engine_method_pkey_meths, engine_method_pkey_asn1_meths].
-[engine_method_rsa,engine_method_dsa,
- engine_method_ecdh,engine_method_ecdsa]
- 4> {ok, Engine} = crypto:engine_load(&lt;&lt;"dynamic">>,
+ 3> {ok, Engine} = crypto:engine_load(&lt;&lt;"dynamic">>,
[{&lt;&lt;"SO_PATH">>,
&lt;&lt;"/some/path/otp_test_engine.so">>},
{&lt;&lt;"ID">>, &lt;&lt;"MD5">>},
&lt;&lt;"LOAD">>],
- [],
- Methods).
- {ok, #Ref}</code>
+ []).
+{ok, #Ref}
+4> ok = crypto:engine_register(Engine, [engine_method_digests]).
+ok</code>
</section>
<section>
@@ -108,12 +104,18 @@ engine_method_pkey_meths, engine_method_pkey_asn1_meths].
&lt;&lt;"/some/path/otp_test_engine.so">>).
{ok, #Ref}</code>
<p>
- To unload it use crypto:ensure_engine_unloaded/1 which removes the ID from the internal list
- before unloading the engine.
+ To remove the tag from the OpenSSL engine list use <c>crypto:engine_remove/1</c>.
+ </p>
+ <code>
+ 6> crypto:engine_remove(Engine).
+ ok</code>
+ <p>
+ To unload it use <c>crypto:engine_unload/1</c> which removes the references to the engine.
</p>
<code>
- 6> crypto:ensure_engine_unloaded(&lt;&lt;"MD5">>).
+ 6> crypto:engine_unload(Engine).
ok</code>
+
</section>
@@ -121,7 +123,7 @@ engine_method_pkey_meths, engine_method_pkey_asn1_meths].
<section>
<title>List all engines currently loaded</title>
<code>
- 5> crypto:engine_list().
+ 8> crypto:engine_list().
[&lt;&lt;"dynamic">>, &lt;&lt;"MD5">>]</code>
</section>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 3d73ee3a76..954d5cd664 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2021</year>
+ <year>1999</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,384 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 5.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A user defined runtime library path configured using
+ <c>--with-ssl-rpath=&lt;PATHS&gt;</c> could fail to be
+ enabled.</p>
+ <p>
+ Own Id: OTP-18384 Aux Id: PR-6596 </p>
+ </item>
+ <item>
+ <p>
+ Ensure that <c>configure</c> fails if a user defined
+ runtime library path has been passed by the user, but
+ cannot set.</p>
+ <p>
+ Own Id: OTP-18408</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 5.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix configure with <c>--with-ssl</c> and
+ <c>--disable-dynamic-ssl-lib</c> on Windows.</p>
+ <p>
+ Own Id: OTP-18147 Aux Id: GH-6024, PR-6056 </p>
+ </item>
+ <item>
+ <p> Remove all references correctly in the garbage
+ collection if an engine handle was not explicit unloaded.
+ </p>
+ <p>
+ Own Id: OTP-18152</p>
+ </item>
+ <item>
+ <p>Changed the behaviour of the engine load/unload
+ functions</p> <p> The engine load/unload functions have
+ got changed semantics to get a more consistent behaviour
+ and work correct when variables are garbage collected.
+ </p> <p> The load functions now don't register the
+ methods for the engine to replace. That will now be
+ handled with the new functions
+ engine_register/engine_unregister if needed. </p> <p>
+ Some functions are removed from the documentation and
+ therefor the API, but they are left in the code for
+ compatibility. </p> <list> <item>engine_load/4: is now
+ the same as engine_load/3</item> <item>engine_unload/2:
+ is now the same as engine_unload/1</item>
+ <item>ensure_engine_loaded/3: is now the same as
+ ensure_engine_loaded/2</item>
+ <item>ensure_engine_unloaded/1, ensure_engine_unloaded/2:
+ is now the same as engine_unload/1</item> </list>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18172 Aux Id: ERIERL-826 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a naming bug for AES-CFB and Blowfish-CFB/OFB when
+ linked with OpenSSL 3.0 cryptolib.</p>
+ <p>
+ Own Id: OTP-18200</p>
+ </item>
+ <item>
+ <p>
+ Sign/verify does now behave as in OTP-24 and earlier for
+ eddsa.</p>
+ <p>
+ Own Id: OTP-18205 Aux Id: GH-6219 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Pass elliptic curve names from crypto.erl to crypto's
+ nif.</p>
+ <p>
+ Own Id: OTP-18037</p>
+ </item>
+ <item>
+ <p>
+ The configure option <c>--disable-deprecated-warnings</c>
+ is removed. It was used for some releases when the
+ support for OpenSSL 3.0 was not completed. It is not
+ needed in OTP 25.</p>
+ <p>
+ Own Id: OTP-18133</p>
+ </item>
+ <item>
+ <p>
+ Crypto is now considered to be usable with the OpenSSL
+ 3.0 cryptolib for production code.</p>
+ <p>
+ ENGINE and FIPS are not yet fully functional.</p>
+ <p>
+ Own Id: OTP-18153</p>
+ </item>
+ <item>
+ <p>
+ Do not exit if the legacy provider is missing in
+ libcrypto 3.0.</p>
+ <p>
+ Own Id: OTP-18217</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 5.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Note in the documentation that MODP (rfc3526) groups and
+ OpenSSL 3.0 can give an error if a call to
+ <c>crypto:generate_key/2</c> specifies a key length, and
+ that length is to small.</p>
+ <p>
+ Own Id: OTP-18046</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The cmac now uses only the 3.0 API</p>
+ <p>
+ Own Id: OTP-18010</p>
+ </item>
+ <item>
+ <p>
+ Documentation is now updated with which OpenSSL cryptolib
+ versions that OTP currently is tested.</p>
+ <p>
+ Own Id: OTP-18132</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix timing bug in ensure_engine_loaded</p> <p>When two
+ ensure_engine_loaded() calls were done in parallel there
+ was a possibility that a crypto lib function was called
+ by both instead of just one of them which resulted in an
+ error. This is solved by moving the implementation from
+ erlang down into a NIF function that uses a mutex to
+ protect the sensitive part.</p>
+ <p>
+ Own Id: OTP-17858 Aux Id: ERIERL-728 </p>
+ </item>
+ <item>
+ <p>
+ Remove faulty types <c>run_time_error()</c> and
+ <c>descriptive_error()</c>.</p>
+ <p>
+ Own Id: OTP-17984</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>
+ Add crypto:hash_equals/2</p>
+ <p>
+ Own Id: OTP-17471 Aux Id: PR-4750 </p>
+ </item>
+ <item>
+ <p>
+ Add /opt/homebrew/opt/openssl to standard locations to
+ search for OpenSSL cryptolib.</p>
+ <p>
+ Own Id: OTP-17561</p>
+ </item>
+ <item>
+ <p>
+ <c>crypto_dyn_iv_init/3</c> and
+ <c>crypto_dyn_iv_update/3</c> are deprecated.</p>
+ <p>
+ Own Id: OTP-17870</p>
+ </item>
+ <item>
+ <p>
+ The information in error messages are increased.</p>
+ <p>
+ Previously the error was signaled with en error class
+ exception <c>badarg</c>, <c>notsup</c> or <c>error</c>,
+ and also in some more ways like an other exception or a
+ return value in a non-standardized format.</p>
+ <p>
+ Now it is an error-class exception
+ <c>{notsup|badarg|error, InfoFromCfile,
+ Description::string()}</c>.</p>
+ <p>
+ The <c>InfoFromCfile</c> is a term with name and line
+ number of the C-file where the error was found. This is
+ primarily intended for a crypto maintainer or an advanced
+ user to find the cause of complicated errors - maybe in
+ crypto itself. The contents of that term might be changed
+ in the future.</p>
+ <p>
+ The <c>Description</c> is a clear text string that
+ describes the error. In case of <c>badarg</c> and
+ <c>notsup</c> the intention is that it should help the
+ user to find the cause ("Bad key size" as an example).
+ Specially for some <c>error</c> that are unlikely, the
+ string may not be possible to understand without deep
+ knowledge of the underlying cryptolib. Such messages are
+ intended for a crypto maintainer.</p>
+ <p>
+ The first element on call stack (the <c>S</c> in <c>try
+ ... catch error:E:S .... end</c>) gives more information
+ like the actual argument list in the call of crypto and
+ the argument number (if possible) in the call to the NIF
+ inside crypto.</p>
+ <p>
+ The functions in crypto affected by this change are:</p>
+ <p>
+ sign/4, sign/5, verify/5, verify/6,</p>
+ <p>
+ generate_key/2, generate_key/3, compute_key/4,</p>
+ <p>
+ hash/2, hash/4, hash_init/1, hash_update/4, hash_final/1,</p>
+ <p>
+ mac/3,4, mac_init/3, mac_update/2, mac_final/2,</p>
+ <p>
+ pbkdf2_hmac/5,</p>
+ <p>
+ public_encrypt/4, private_decrypt/4, private_encrypt/4,
+ public_decrypt/4</p>
+ <p>
+ This schema was introduced earlier in:</p>
+ <p>
+ crypto_init/3, crypto_init/4, crypto_update/2,
+ crypto_final/1, crypto_get_data/1,</p>
+ <p>
+ crypto_one_time/4, crypto_one_time/5,
+ crypto_one_time_aead/6, crypto_one_time_aead/7</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17965</p>
+ </item>
+ <item>
+ <p>
+ Add Output Feedback mode (OFB) support for AES encryption
+ / decryption for key sizes of 128, 192 and 256 bits.</p>
+ <p>
+ Own Id: OTP-18067 Aux Id: PR-5866 </p>
+ </item>
+ <item>
+ <p>
+ The cryptolib API deprecated in OpenSSL 3.0 is now no
+ longer used with a few exceptions listed below.</p>
+ <p>
+ Although OpenSSL 3.0.x itself is stable, its usage in
+ OTP/crypto should still not be considered suitable for
+ production code.</p>
+ <p>
+ The use of ENGINEs is still disabled by default when
+ using 3.0.</p>
+ <p>
+ Deprecated functions are still called in the
+ otp_test_engine.c (only used in tests), in mac.c
+ (EVP_PKEY_new_CMAC_key) and five function calls in ec.c
+ (EVP_PKEY_assign, EC_KEY_get_conv_form,
+ EVP_PKEY_get1_EC_KEY, EC_KEY_get0_group and
+ EC_KEY_set_public_key).</p>
+ <p>
+ Own Id: OTP-18086 Aux Id: OTP-16282, OTP-16643,
+ OTP-16644, OTP-17701, OTP-17702, OTP-17704 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 5.0.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Changed the behaviour of the engine load/unload
+ functions</p> <p> The engine load/unload functions have
+ got changed semantics to get a more consistent behaviour
+ and work correct when variables are garbage collected.
+ </p> <p> The load functions now don't register the
+ methods for the engine to replace. That will now be
+ handled with the new functions
+ engine_register/engine_unregister if needed. </p> <p>
+ Some functions functions are removed from the
+ documentation and therefor the API, but they are left in
+ the code for compatibility. </p> <list>
+ <item>engine_load/4: is now the same as
+ engine_load/3</item> <item>engine_unload/2: is now the
+ same as engine_unload/1</item>
+ <item>ensure_engine_loaded/3: is now the same as
+ ensure_engine_loaded/2</item>
+ <item>ensure_engine_unloaded/1, ensure_engine_unloaded/2:
+ is now the same as engine_unload/1</item> </list>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18172 Aux Id: ERIERL-826 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 5.0.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix configure with <c>--with-ssl</c> and
+ <c>--disable-dynamic-ssl-lib</c> on Windows.</p>
+ <p>
+ Own Id: OTP-18147 Aux Id: GH-6024, PR-6056 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 5.0.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix timing bug in ensure_engine_loaded</p> <p>When two
+ ensure_engine_loaded() calls were done in parallel there
+ was a possibility that a crypto lib function was called
+ by both instead of just one of them which resulted in an
+ error. This is solved by moving the implementation from
+ erlang down into a NIF function that uses a mutex to
+ protect the sensitive part.</p>
+ <p>
+ Own Id: OTP-17858 Aux Id: ERIERL-728 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 5.0.6</title>
<section><title>Improvements and New Features</title>
@@ -411,6 +789,66 @@
</section>
+<section><title>Crypto 4.9.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Changed the behaviour of the engine load/unload
+ functions</p> <p> The engine load/unload functions have
+ got changed semantics to get a more consistent behaviour
+ and work correct when variables are garbage collected.
+ </p> <p> The load functions now don't register the
+ methods for the engine to replace. That will now be
+ handled with the new functions
+ engine_register/engine_unregister if needed. </p> <p>
+ Some functions functions are removed from the
+ documentation and therefor the API, but they are left in
+ the code for compatibility. </p> <list>
+ <item>engine_load/4: is now the same as
+ engine_load/3</item> <item>engine_unload/2: is now the
+ same as engine_unload/1</item>
+ <item>ensure_engine_loaded/3: is now the same as
+ ensure_engine_loaded/2</item>
+ <item>ensure_engine_unloaded/1, ensure_engine_unloaded/2:
+ is now the same as engine_unload/1</item> </list>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18172 Aux Id: ERIERL-826 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.9.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix timing bug in ensure_engine_loaded</p> <p>When two
+ ensure_engine_loaded() calls were done in parallel there
+ was a possibility that a crypto lib function was called
+ by both instead of just one of them which resulted in an
+ error. This is solved by moving the implementation from
+ erlang down into a NIF function that uses a mutex to
+ protect the sensitive part.</p>
+ <p>
+ Own Id: OTP-17858 Aux Id: ERIERL-728 </p>
+ </item>
+ <item>
+ <p> Remove all references correctly in the garbage
+ collection if an engine handle was not explicit unloaded.
+ </p>
+ <p>
+ Own Id: OTP-18152</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.9.0.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile
index fea32dc4e3..893f679390 100644
--- a/lib/crypto/src/Makefile
+++ b/lib/crypto/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2021. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ ERL_COMPILE_FLAGS += -DCRYPTO_VSN=\"$(VSN)\" -Werror -I../include
# Targets
# ----------------------------------------------------
-debug opt valgrind asan: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src
index 492aa10e51..30e804c7e2 100644
--- a/lib/crypto/src/crypto.app.src
+++ b/lib/crypto/src/crypto.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,6 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, [{fips_mode, false}, {rand_cache_size, 896}]},
- {runtime_dependencies, ["erts-9.0","stdlib-3.4","kernel-5.3"]}]}.
+ {runtime_dependencies, ["erts-9.0","stdlib-3.9","kernel-5.3"]}]}.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 70d1ebc2b7..53cdc76830 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,6 +46,12 @@
-export([pbkdf2_hmac/5]).
%%%----------------------------------------------------------------
+%% Deprecated functions
+-deprecated([crypto_dyn_iv_init/3,
+ crypto_dyn_iv_update/3
+ ]).
+
+%%%----------------------------------------------------------------
%% Removed functions.
%%
%% Old interface. Now implemented with the New interface.
@@ -98,6 +104,8 @@
crypto_final/1,
crypto_get_data/1,
+ hash_equals/2,
+
supports/1,
mac/3, mac/4, macN/4, macN/5,
mac_init/2, mac_init/3, mac_update/2, mac_final/1, mac_finalN/2
@@ -110,12 +118,15 @@
engine_load/3,
engine_load/4,
engine_unload/1,
+ engine_unload/2,
engine_by_id/1,
engine_list/0,
engine_ctrl_cmd_string/3,
engine_ctrl_cmd_string/4,
engine_add/1,
engine_remove/1,
+ engine_register/2,
+ engine_unregister/2,
engine_get_id/1,
engine_get_name/1,
ensure_engine_loaded/2,
@@ -124,6 +135,30 @@
ensure_engine_unloaded/2
]).
+-nifs([info_nif/0, info_lib/0, info_fips/0, enable_fips_mode_nif/1,
+ hash_algorithms/0, pubkey_algorithms/0, cipher_algorithms/0,
+ mac_algorithms/0, curve_algorithms/0, rsa_opts_algorithms/0,
+ hash_info/1, hash_nif/2, hash_init_nif/1, hash_update_nif/2,
+ hash_final_nif/1, mac_nif/4, mac_init_nif/3, mac_update_nif/2,
+ mac_final_nif/1, cipher_info_nif/1, ng_crypto_init_nif/4,
+ ng_crypto_update_nif/2, ng_crypto_update_nif/3, ng_crypto_final_nif/1,
+ ng_crypto_get_data_nif/1, ng_crypto_one_time_nif/5,
+ strong_rand_bytes_nif/1, strong_rand_range_nif/1, rand_uniform_nif/2,
+ mod_exp_nif/4, do_exor/2, hash_equals_nif/2, pbkdf2_hmac_nif/5,
+ pkey_sign_nif/5, pkey_verify_nif/6, pkey_crypt_nif/6,
+ rsa_generate_key_nif/2, dh_generate_key_nif/4, dh_compute_key_nif/3,
+ evp_compute_key_nif/3, evp_generate_key_nif/2, privkey_to_pubkey_nif/2,
+ srp_value_B_nif/5, srp_user_secret_nif/7, srp_host_secret_nif/5,
+ ec_generate_key_nif/2, ecdh_compute_key_nif/3, rand_seed_nif/1,
+ aead_cipher_nif/7, engine_by_id_nif/1, engine_init_nif/1,
+ engine_free_nif/1, engine_load_dynamic_nif/0,
+ engine_ctrl_cmd_strings_nif/3, engine_register_nif/2,
+ engine_unregister_nif/2, engine_add_nif/1, engine_remove_nif/1,
+ engine_get_first_nif/0, engine_get_next_nif/1, engine_get_id_nif/1,
+ engine_get_name_nif/1, engine_get_all_methods_nif/0,
+ ensure_engine_loaded_nif/2
+ ]).
+
-export_type([ %% A minimum exported: only what public_key needs.
dh_private/0,
dh_public/0,
@@ -336,6 +371,10 @@
| aes_256_cbc
| aes_cbc
+ | aes_128_ofb
+ | aes_192_ofb
+ | aes_256_ofb
+
| aes_128_cfb128
| aes_192_cfb128
| aes_256_cfb128
@@ -391,18 +430,20 @@
-type crypto_integer() :: binary() | integer().
-%%%
-%% Exceptions
-%% error:badarg
-%% error:notsup
--type run_time_error() :: any().
+%% %%%--------------------------------------------------------------------
+%% %%% Exceptions
+%% %%%
+%% %% Exceptions
+%% %% error:badarg
+%% %% error:notsup
+%% -type run_time_error() :: badarg | notsup.
-%% Exceptions
-%% error:{badarg,Reason::term()}
-%% error:{notsup,Reason::term()}
-%% error:{error,Reason::term()}
--type descriptive_error() :: any() .
+%% %% Exceptions
+%% %% error:{badarg, file_line_info, Reason::term()}
+%% %% error:{notsup,Reason::term()}
+%% %% error:{error,Reason::term()}
+%% -type descriptive_error() :: {badarg | notsup | error, FileLineInfo::any, Reason::string()}.
%%--------------------------------------------------------------------
%% Compilation and loading
@@ -570,7 +611,7 @@ enable_fips_mode_nif(_) -> ?nif_stub.
KeyLen :: pos_integer(),
Result :: binary().
pbkdf2_hmac(Digest, Pass, Salt, Iter, KeyLen) ->
- pbkdf2_hmac_nif(Digest, Pass, Salt, Iter, KeyLen).
+ ?nif_call(pbkdf2_hmac_nif(Digest, Pass, Salt, Iter, KeyLen)).
pbkdf2_hmac_nif(_, _, _, _, _) -> ?nif_stub.
@@ -582,7 +623,7 @@ pbkdf2_hmac_nif(_, _, _, _, _) -> ?nif_stub.
-type hash_algorithm() :: sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash() .
--spec hash_info(Type) -> Result | run_time_error()
+-spec hash_info(Type) -> Result
when Type :: hash_algorithm(),
Result :: #{size := integer(),
block_size := integer(),
@@ -604,7 +645,7 @@ hash(Type, Data) ->
-spec hash_init(Type) -> State when Type :: hash_algorithm(),
State :: hash_state().
hash_init(Type) ->
- notsup_to_error(hash_init_nif(Type)).
+ ?nif_call(hash_init_nif(Type)).
-spec hash_update(State, Data) -> NewState when State :: hash_state(),
NewState :: hash_state(),
@@ -617,7 +658,7 @@ hash_update(Context, Data) ->
-spec hash_final(State) -> Digest when State :: hash_state(),
Digest :: binary().
hash_final(Context) ->
- notsup_to_error(hash_final_nif(Context)).
+ ?nif_call(hash_final_nif(Context)).
%%%================================================================
%%%
@@ -638,7 +679,7 @@ hash_final(Context) ->
%%%----------------------------------------------------------------
%%% Calculate MAC for the whole text at once
--spec mac(Type :: poly1305, Key, Data) -> Mac | descriptive_error()
+-spec mac(Type :: poly1305, Key, Data) -> Mac
when Key :: iodata(),
Data :: iodata(),
Mac :: binary().
@@ -646,7 +687,7 @@ hash_final(Context) ->
mac(poly1305, Key, Data) -> mac(poly1305, undefined, Key, Data).
--spec mac(Type, SubType, Key, Data) -> Mac | descriptive_error()
+-spec mac(Type, SubType, Key, Data) -> Mac
when Type :: hmac | cmac | poly1305,
SubType :: hmac_hash_algorithm() | cmac_cipher_algorithm() | undefined,
Key :: iodata(),
@@ -655,11 +696,10 @@ mac(poly1305, Key, Data) -> mac(poly1305, undefined, Key, Data).
mac(Type, SubType, Key0, Data) ->
Key = iolist_to_binary(Key0),
- mac_nif(Type, alias(SubType,Key), Key, Data).
+ ?nif_call(mac_nif(Type, alias(SubType,Key), Key, Data)).
-
--spec macN(Type :: poly1305, Key, Data, MacLength) -> Mac | descriptive_error()
+-spec macN(Type :: poly1305, Key, Data, MacLength) -> Mac
when Key :: iodata(),
Data :: iodata(),
Mac :: binary(),
@@ -669,7 +709,7 @@ macN(Type, Key, Data, MacLength) ->
macN(Type, undefined, Key, Data, MacLength).
--spec macN(Type, SubType, Key, Data, MacLength) -> Mac | descriptive_error()
+-spec macN(Type, SubType, Key, Data, MacLength) -> Mac
when Type :: hmac | cmac | poly1305,
SubType :: hmac_hash_algorithm() | cmac_cipher_algorithm() | undefined,
Key :: iodata(),
@@ -686,40 +726,40 @@ macN(Type, SubType, Key, Data, MacLength) ->
-opaque mac_state() :: reference() .
--spec mac_init(Type :: poly1305, Key) -> State | descriptive_error()
+-spec mac_init(Type :: poly1305, Key) -> State
when Key :: iodata(),
State :: mac_state() .
mac_init(poly1305, Key) ->
- mac_init_nif(poly1305, undefined, Key).
+ ?nif_call(mac_init_nif(poly1305, undefined, Key)).
--spec mac_init(Type, SubType, Key) -> State | descriptive_error()
+-spec mac_init(Type, SubType, Key) -> State
when Type :: hmac | cmac | poly1305,
SubType :: hmac_hash_algorithm() | cmac_cipher_algorithm() | undefined,
Key :: iodata(),
State :: mac_state() .
mac_init(Type, SubType, Key0) ->
Key = iolist_to_binary(Key0),
- mac_init_nif(Type, alias(SubType,Key), Key).
+ ?nif_call(mac_init_nif(Type, alias(SubType,Key), Key)).
--spec mac_update(State0, Data) -> State | descriptive_error()
+-spec mac_update(State0, Data) -> State
when Data :: iodata(),
State0 :: mac_state(),
State :: mac_state().
mac_update(Ref, Data) ->
- mac_update_nif(Ref, Data).
+ ?nif_call(mac_update_nif(Ref, Data)).
--spec mac_final(State) -> Mac | descriptive_error()
+-spec mac_final(State) -> Mac
when State :: mac_state(),
Mac :: binary().
mac_final(Ref) ->
- mac_final_nif(Ref).
+ ?nif_call(mac_final_nif(Ref)).
--spec mac_finalN(State, MacLength) -> Mac | descriptive_error()
+-spec mac_finalN(State, MacLength) -> Mac
when State :: mac_state(),
MacLength :: pos_integer(),
Mac :: binary().
@@ -747,7 +787,7 @@ mac_final_nif(_Ref) -> ?nif_stub.
%%%---- Cipher info
--spec cipher_info(Type) -> Result | run_time_error()
+-spec cipher_info(Type) -> Result
when Type :: cipher(),
Result :: #{key_length := integer(),
iv_length := integer(),
@@ -802,9 +842,9 @@ cipher_info(Type) ->
-opaque crypto_state() :: reference() .
--type crypto_opts() :: boolean()
+-type crypto_opts() :: boolean()
| [ crypto_opt() ] .
--type crypto_opt() :: {encrypt,boolean()}
+-type crypto_opt() :: {encrypt,boolean()}
| {padding, padding()} .
-type padding() :: cryptolib_padding() | otp_padding().
-type cryptolib_padding() :: none | pkcs_padding .
@@ -816,7 +856,7 @@ cipher_info(Type) ->
%%% Create and initialize a new state for encryption or decryption
%%%
--spec crypto_init(Cipher, Key, FlagOrOptions) -> State | descriptive_error()
+-spec crypto_init(Cipher, Key, FlagOrOptions) -> State
when Cipher :: cipher_no_iv(),
Key :: iodata(),
FlagOrOptions :: crypto_opts() | boolean(),
@@ -826,7 +866,7 @@ crypto_init(Cipher, Key, FlagOrOptions) ->
{1,2,-1,3}
).
--spec crypto_init(Cipher, Key, IV, FlagOrOptions) -> State | descriptive_error()
+-spec crypto_init(Cipher, Key, IV, FlagOrOptions) -> State
when Cipher :: cipher_iv(),
Key :: iodata(),
IV :: iodata(),
@@ -836,7 +876,7 @@ crypto_init(Cipher, Key, IV, FlagOrOptions) ->
?nif_call(ng_crypto_init_nif(alias(Cipher,Key), Key, IV, FlagOrOptions)).
%%%----------------------------------------------------------------
--spec crypto_dyn_iv_init(Cipher, Key, FlagOrOptions) -> State | descriptive_error()
+-spec crypto_dyn_iv_init(Cipher, Key, FlagOrOptions) -> State
when Cipher :: cipher_iv(),
Key :: iodata(),
FlagOrOptions :: crypto_opts() | boolean(),
@@ -855,7 +895,7 @@ crypto_dyn_iv_init(Cipher, Key, FlagOrOptions) ->
%%% blocksize.
%%%
--spec crypto_update(State, Data) -> Result | descriptive_error()
+-spec crypto_update(State, Data) -> Result
when State :: crypto_state(),
Data :: iodata(),
Result :: binary() .
@@ -863,7 +903,7 @@ crypto_update(State, Data) ->
?nif_call(ng_crypto_update_nif(State, Data)).
%%%----------------------------------------------------------------
--spec crypto_dyn_iv_update(State, Data, IV) -> Result | descriptive_error()
+-spec crypto_dyn_iv_update(State, Data, IV) -> Result
when State :: crypto_state(),
Data :: iodata(),
IV :: iodata(),
@@ -877,7 +917,7 @@ crypto_dyn_iv_update(State, Data, IV) ->
%%% to crypto_uptate was not an integer number of blocks, the rest
%%% is returned from this function.
--spec crypto_final(State) -> FinalResult | descriptive_error()
+-spec crypto_final(State) -> FinalResult
when State :: crypto_state(),
FinalResult :: binary() .
crypto_final(State) ->
@@ -900,7 +940,7 @@ crypto_get_data(State) ->
%%%
-spec crypto_one_time(Cipher, Key, Data, FlagOrOptions) ->
- Result | descriptive_error()
+ Result
when Cipher :: cipher_no_iv(),
Key :: iodata(),
Data :: iodata(),
@@ -915,7 +955,7 @@ crypto_one_time(Cipher, Key, Data, FlagOrOptions) ->
-spec crypto_one_time(Cipher, Key, IV, Data, FlagOrOptions) ->
- Result | descriptive_error()
+ Result
when Cipher :: cipher_iv(),
Key :: iodata(),
IV :: iodata(),
@@ -930,7 +970,7 @@ crypto_one_time(Cipher, Key, IV, Data, FlagOrOptions) ->
%%%----------------------------------------------------------------
-spec crypto_one_time_aead(Cipher, Key, IV, InText, AAD, EncFlag::true) ->
- Result | descriptive_error()
+ Result
when Cipher :: cipher_aead(),
Key :: iodata(),
IV :: iodata(),
@@ -948,7 +988,7 @@ crypto_one_time_aead(Cipher, Key, IV, PlainText, AAD, true) ->
-spec crypto_one_time_aead(Cipher, Key, IV, InText, AAD, TagOrTagLength, EncFlag) ->
- Result | descriptive_error()
+ Result
when Cipher :: cipher_aead(),
Key :: iodata(),
IV :: iodata(),
@@ -1415,11 +1455,9 @@ sign(Algorithm, Type, Data, Key) ->
sign(Algorithm0, Type0, Data, Key, Options) ->
{Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
- case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of
- error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]);
- notsup -> erlang:error(notsup);
- Signature -> Signature
- end.
+ ?nif_call(pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options),
+ {1, 2, 3, 4, 5},
+ [Algorithm0, Type0, Data, Key, Options]).
pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
@@ -1464,10 +1502,9 @@ verify(Algorithm, Type, Data, Signature, Key) ->
verify(Algorithm0, Type0, Data, Signature, Key, Options) ->
{Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
- case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
- notsup -> erlang:error(notsup);
- Boolean -> Boolean
- end.
+ ?nif_call(pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options),
+ {1,2,3,4,5},
+ [Algorithm0, Type0, Data, Signature, Key, Options]).
pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
@@ -1553,12 +1590,7 @@ pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) ->
pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec);
pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) ->
- case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of
- error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]);
- error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end.
+ ?nif_call(pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec)).
pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
@@ -1593,9 +1625,11 @@ generate_key(dh, DHParameters0, PrivateKey) ->
[P,G,L] -> {[P,G], L};
[P,G] -> {[P,G], 0}
end,
- dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
- map_ensure_int_as_bin(DHParameters),
- 0, Len);
+ ?nif_call(dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
+ map_ensure_int_as_bin(DHParameters),
+ 0, Len),
+ {3, 2, -1, 2},
+ [dh, DHParameters0, PrivateKey]);
generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
@@ -1639,14 +1673,20 @@ generate_key(ecdh, Curve, PrivKey) when Curve == x448 ;
generate_key(eddh, Curve, PrivKey);
generate_key(eddh, Curve, PrivKey) when Curve == x448 ;
Curve == x25519 ->
- evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey));
+ ?nif_call(evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)),
+ {2, 3},
+ [eddh, Curve, PrivKey]
+ );
generate_key(ecdh, Curve, PrivKey) ->
- ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey));
+ ?nif_call(ec_generate_key_nif(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)));
generate_key(eddsa, Curve, PrivKey) when Curve == ed448 ;
Curve == ed25519 ->
- evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)).
+ ?nif_call(evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)),
+ {2, 3},
+ [eddsa, Curve, PrivKey]
+ ).
evp_generate_key_nif(_Curve, _PrivKey) -> ?nif_stub.
@@ -1661,13 +1701,11 @@ evp_generate_key_nif(_Curve, _PrivKey) -> ?nif_stub.
.
compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
- case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
- ensure_int_as_bin(MyPrivateKey),
- map_ensure_int_as_bin(DHParameters)) of
- error -> erlang:error(computation_failed,
- [dh,OthersPublicKey,MyPrivateKey,DHParameters]);
- Ret -> Ret
- end;
+ ?nif_call(dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
+ ensure_int_as_bin(MyPrivateKey),
+ map_ensure_int_as_bin(DHParameters)),
+ {2, 3, 4},
+ [dh, OthersPublicKey, MyPrivateKey, DHParameters]);
compute_key(srp, HostPublic, {UserPublic, UserPrivate},
{user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when
@@ -1706,12 +1744,16 @@ compute_key(ecdh, Others, My, Curve) when Curve == x448 ;
compute_key(eddh, Others, My, Curve) when Curve == x448 ;
Curve == x25519 ->
- evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My));
+ ?nif_call(evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My)),
+ {2, 3, 4},
+ [eddh, Others, My, Curve]);
compute_key(ecdh, Others, My, Curve) ->
- ecdh_compute_key_nif(ensure_int_as_bin(Others),
- nif_curve_params(Curve),
- ensure_int_as_bin(My)).
+ ?nif_call(ecdh_compute_key_nif(ensure_int_as_bin(Others),
+ nif_curve_params(Curve),
+ ensure_int_as_bin(My)),
+ {2, 4, 3},
+ [ecdh, Others, My, Curve]).
evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
@@ -1794,24 +1836,11 @@ engine_get_all_methods() ->
Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
is_list(PostCmds) ->
- engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
-
-%%----------------------------------------------------------------------
-%% Function: engine_load/4
-%%----------------------------------------------------------------------
--spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) ->
- Result when EngineId::unicode:chardata(),
- PreCmds::[engine_cmnd()],
- PostCmds::[engine_cmnd()],
- EngineMethods::[engine_method_type()],
- Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
-engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
- is_list(PostCmds) ->
try
ok = notsup_to_error(engine_load_dynamic_nif()),
case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
{ok, Engine} ->
- engine_load_1(Engine, PreCmds, PostCmds, EngineMethods);
+ engine_load_1(Engine, PreCmds, PostCmds);
{error, Error1} ->
{error, Error1}
end
@@ -1820,11 +1849,23 @@ engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
Error2
end.
-engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
+-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ EngineMethods::[engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds, _EngineMethods) when is_list(PreCmds),
+ is_list(PostCmds) ->
+ engine_load(EngineId, PreCmds, PostCmds).
+
+
+%%----------------------------------------------------------------------
+engine_load_1(Engine, PreCmds, PostCmds) ->
try
ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
ok = engine_nif_wrapper(engine_init_nif(Engine)),
- engine_load_2(Engine, PostCmds, EngineMethods),
+ engine_load_2(Engine, PostCmds),
{ok, Engine}
catch
throw:Error ->
@@ -1837,15 +1878,13 @@ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
error(badarg)
end.
-engine_load_2(Engine, PostCmds, EngineMethods) ->
+engine_load_2(Engine, PostCmds) ->
try
ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PostCmds), 0)),
- [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
- Method <- EngineMethods],
ok
catch
throw:Error ->
- %% The engine registration failed, release the functional reference
+ %% The engine registration failed, release the structural and functional references
ok = engine_free_nif(Engine),
throw(Error)
end.
@@ -1856,22 +1895,20 @@ engine_load_2(Engine, PostCmds, EngineMethods) ->
-spec engine_unload(Engine) -> Result when Engine :: engine_ref(),
Result :: ok | {error, Reason::term()}.
engine_unload(Engine) ->
- engine_unload(Engine, engine_get_all_methods()).
-
--spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
- EngineMethods :: [engine_method_type()],
- Result :: ok | {error, Reason::term()}.
-engine_unload(Engine, EngineMethods) ->
try
- [ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
- Method <- EngineMethods],
%% Release the reference from engine_by_id_nif
ok = engine_nif_wrapper(engine_free_nif(Engine))
catch
- throw:Error ->
- Error
+ throw:Error ->
+ Error
end.
+-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
+engine_unload(Engine, _EngineMethods) ->
+ engine_unload(Engine).
+
%%----------------------------------------------------------------------
%% Function: engine_by_id/1
%%----------------------------------------------------------------------
@@ -1902,6 +1939,36 @@ engine_remove(Engine) ->
notsup_to_error(engine_remove_nif(Engine)).
%%----------------------------------------------------------------------
+%% Function: engine_register/2
+%%----------------------------------------------------------------------
+-spec engine_register(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods::[engine_method_type()],
+ Result :: ok | {error, Reason::term()} .
+engine_register(Engine, EngineMethods) when is_list(EngineMethods) ->
+ try
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- EngineMethods],
+ ok
+ catch
+ throw:Error -> Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_unregister/2
+%%----------------------------------------------------------------------
+-spec engine_unregister(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods::[engine_method_type()],
+ Result :: ok | {error, Reason::term()} .
+engine_unregister(Engine, EngineMethods) when is_list(EngineMethods) ->
+ try
+ [ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- EngineMethods],
+ ok
+ catch
+ throw:Error -> Error
+ end.
+
+%%----------------------------------------------------------------------
%% Function: engine_get_id/1
%%----------------------------------------------------------------------
-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(),
@@ -1983,12 +2050,18 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
%% Function: ensure_engine_loaded/2
%% Special version of load that only uses dynamic engine to load
%%----------------------------------------------------------------------
--spec ensure_engine_loaded(EngineId, LibPath) ->
- Result when EngineId :: unicode:chardata(),
- LibPath :: unicode:chardata(),
- Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+-spec ensure_engine_loaded(EngineId, LibPath) -> Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} |
+ {error, Reason::term()}.
ensure_engine_loaded(EngineId, LibPath) ->
- ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
+ case notsup_to_error(ensure_engine_loaded_nif(ensure_bin_chardata(EngineId),
+ ensure_bin_chardata(LibPath))) of
+ {ok, Engine} ->
+ {ok, Engine};
+ {error, Error1} ->
+ {error, Error1}
+ end.
%%----------------------------------------------------------------------
%% Function: ensure_engine_loaded/3
@@ -1998,62 +2071,18 @@ ensure_engine_loaded(EngineId, LibPath) ->
Result when EngineId :: unicode:chardata(),
LibPath :: unicode:chardata(),
EngineMethods :: [engine_method_type()],
- Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
-ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
- try
- List = crypto:engine_list(),
- case lists:member(EngineId, List) of
- true ->
- notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)));
- false ->
- ok = notsup_to_error(engine_load_dynamic_nif()),
- case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of
- {ok, Engine} ->
- PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)},
- {<<"ID">>, ensure_bin_chardata(EngineId)},
- <<"LOAD">>],
- ensure_engine_loaded_1(Engine, PreCommands, EngineMethods);
- {error, Error1} ->
- {error, Error1}
- end
- end
- catch
- throw:Error2 ->
- Error2
- end.
-
-ensure_engine_loaded_1(Engine, PreCmds, Methods) ->
- try
- ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
- ok = engine_nif_wrapper(engine_add_nif(Engine)),
- ok = engine_nif_wrapper(engine_init_nif(Engine)),
- ensure_engine_loaded_2(Engine, Methods),
- {ok, Engine}
- catch
- throw:Error ->
- %% The engine couldn't initialise, release the structural reference
- ok = engine_free_nif(Engine),
- throw(Error)
- end.
+ Result :: {ok, Engine::engine_ref()} |
+ {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath, _EngineMethods) ->
+ ensure_engine_loaded(EngineId, LibPath).
-ensure_engine_loaded_2(Engine, Methods) ->
- try
- [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
- Method <- Methods],
- ok
- catch
- throw:Error ->
- %% The engine registration failed, release the functional reference
- ok = engine_free_nif(Engine),
- throw(Error)
- end.
%%----------------------------------------------------------------------
%% Function: ensure_engine_unloaded/1
%%----------------------------------------------------------------------
-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(),
Result :: ok | {error, Reason::term()}.
ensure_engine_unloaded(Engine) ->
- ensure_engine_unloaded(Engine, engine_get_all_methods()).
+ engine_unload(Engine).
%%----------------------------------------------------------------------
%% Function: ensure_engine_unloaded/2
@@ -2062,20 +2091,8 @@ ensure_engine_unloaded(Engine) ->
Result when Engine :: engine_ref(),
EngineMethods :: [engine_method_type()],
Result :: ok | {error, Reason::term()}.
-ensure_engine_unloaded(Engine, EngineMethods) ->
- List = crypto:engine_list(),
- EngineId = crypto:engine_get_id(Engine),
- case lists:member(EngineId, List) of
- true ->
- case engine_remove(Engine) of
- ok ->
- engine_unload(Engine, EngineMethods);
- {error, Error} ->
- {error, Error}
- end;
- false ->
- engine_unload(Engine, EngineMethods)
- end.
+ensure_engine_unloaded(Engine, _EngineMethods) ->
+ ensure_engine_unloaded(Engine).
%%--------------------------------------------------------------------
@@ -2161,17 +2178,17 @@ notsup_to_error(Other) ->
%% HASH --------------------------------------------------------------------
hash(Hash, Data, Size, Max) when Size =< Max ->
- notsup_to_error(hash_nif(Hash, Data));
+ ?nif_call(hash_nif(Hash, Data));
hash(Hash, Data, Size, Max) ->
State0 = hash_init(Hash),
State1 = hash_update(State0, Data, Size, Max),
hash_final(State1).
hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- notsup_to_error(hash_update_nif(State, Data));
+ ?nif_call(hash_update_nif(State, Data), {1,2});
hash_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = notsup_to_error(hash_update_nif(State0, Increment)),
+ State = ?nif_call(hash_update_nif(State0, Increment), {1,2}),
hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
hash_info_nif(_Hash) -> ?nif_stub.
@@ -2265,7 +2282,7 @@ dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint, _Length) -> ?nif_stub.
%% MyPrivKey, OthersPublicKey = mpint()
dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
-ec_key_generate(_Curve, _Key) -> ?nif_stub.
+ec_generate_key_nif(_Curve, _Key) -> ?nif_stub.
ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
@@ -2286,16 +2303,15 @@ ec_curve(X) ->
EnginePrivateKeyRef :: engine_key_ref(),
PublicKey :: rsa_public() | dss_public() .
privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
- try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))
- of
+ try ?nif_call(privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))) of
[_|_]=L -> map_ensure_bin_as_int(L);
X -> X
catch
- error:badarg when Alg==ecdsa ->
+ error:{badarg,_,_} when Alg==ecdsa ->
{error, notsup};
- error:badarg ->
+ error:{badarg,_,_} ->
{error, not_found};
- error:notsup ->
+ error:{notsup,_,_} ->
{error, notsup}
end.
@@ -2315,17 +2331,29 @@ term_to_nif_curve({A, B, Seed}) ->
{ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}.
nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
- {term_to_nif_prime(PrimeField),
- term_to_nif_curve(Curve),
- ensure_int_as_bin(BasePoint),
- ensure_int_as_bin(Order),
- ensure_int_as_bin(CoFactor)};
-nif_curve_params(Curve) when is_atom(Curve) ->
- %% named curve
- case Curve of
- x448 -> {evp,Curve};
- x25519 -> {evp,Curve};
- _ -> crypto_ec_curves:curve(Curve)
+ {
+ {term_to_nif_prime(PrimeField),
+ term_to_nif_curve(Curve),
+ ensure_int_as_bin(BasePoint),
+ ensure_int_as_bin(Order),
+ ensure_int_as_bin(CoFactor)
+ },
+ undefined %% The curve name
+ };
+nif_curve_params(CurveName) when is_atom(CurveName) ->
+ %% A named curve
+ case CurveName of
+ x448 -> {evp,CurveName};
+ x25519 -> {evp,CurveName};
+ _ ->
+ Spec =
+ try
+ crypto_ec_curves:curve(CurveName)
+ catch
+ _:_ ->
+ undefined
+ end,
+ {Spec, CurveName}
end.
@@ -2344,6 +2372,15 @@ exor(Data1, Data2, _Size, MaxByts, Acc) ->
do_exor(_A, _B) -> ?nif_stub.
+-spec hash_equals(BinA, BinB) -> Result
+ when BinA :: binary(),
+ BinB :: binary(),
+ Result :: boolean().
+hash_equals(A, B) ->
+ hash_equals_nif(A, B).
+
+hash_equals_nif(_A, _B) -> ?nif_stub.
+
hash_algorithms() -> ?nif_stub.
pubkey_algorithms() -> ?nif_stub.
cipher_algorithms() -> ?nif_stub.
@@ -2478,6 +2515,7 @@ engine_get_next_nif(_Engine) -> ?nif_stub.
engine_get_id_nif(_Engine) -> ?nif_stub.
engine_get_name_nif(_Engine) -> ?nif_stub.
engine_get_all_methods_nif() -> ?nif_stub.
+ensure_engine_loaded_nif(_EngineId, _LibPath) -> ?nif_stub.
%%--------------------------------------------------------------------
%% Engine internals
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index aaa2df0534..a018b794c5 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -17,6 +17,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
SPEC_FILES = \
crypto.spec \
+ crypto_gh.spec \
crypto_bench.spec
COVER_FILE = crypto.cover
@@ -35,7 +36,7 @@ EBIN = .
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/crypto/test/crypto.spec b/lib/crypto/test/crypto.spec
index 4a95275687..690374b099 100644
--- a/lib/crypto/test/crypto.spec
+++ b/lib/crypto/test/crypto.spec
@@ -1,6 +1,4 @@
{suites,"../crypto_test",all}.
-
-{skip_suites, "../crypto_test", [crypto_bench_SUITE
- ],
+{skip_suites, "../crypto_test", [crypto_bench_SUITE],
"Benchmarks run separately"}.
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 503961ebf9..a2adaf8ed0 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -53,7 +53,9 @@
bad_key_length/1,
bad_cipher_name/1,
bad_generate_key_name/1,
+ bad_cmac_name/1,
bad_hash_name/1,
+ bad_hmac_name/1,
bad_mac_name/1,
bad_sign_name/1,
bad_verify_name/1,
@@ -62,6 +64,10 @@
cipher_info_prop_aead_attr/0,
cipher_info_prop_aead_attr/1,
cipher_padding/1,
+ cmac/0,
+ cmac/1,
+ cmac_update/0,
+ cmac_update/1,
compute/0,
compute/1,
compute_bug/0,
@@ -78,6 +84,10 @@
hash/1,
hash_info/0,
hash_info/1,
+ hmac/0,
+ hmac/1,
+ hmac_update/0,
+ hmac_update/1,
info/1,
mod_pow/0,
mod_pow/1,
@@ -87,11 +97,17 @@
no_generate_compute/1,
no_hash/0,
no_hash/1,
+ no_hmac/0,
+ no_hmac/1,
+ no_poly1305/0,
+ no_poly1305/1,
no_sign_verify/0,
no_sign_verify/1,
no_support/0,
no_support/1,
node_supports_cache/1,
+ poly1305/0,
+ poly1305/1,
private_encrypt/0,
private_encrypt/1,
public_encrypt/0,
@@ -104,6 +120,8 @@
rand_threads/1,
rand_uniform/0,
rand_uniform/1,
+ hash_equals/0,
+ hash_equals/1,
sign_verify/0,
sign_verify/1,
ec_key_padding/1,
@@ -122,6 +140,7 @@
aes_128_ctr/1,
aes_128_ecb/1,
aes_128_gcm/1,
+ aes_128_ofb/1,
aes_192_cbc/1,
aes_192_ccm/1,
aes_192_cfb128/1,
@@ -129,6 +148,7 @@
aes_192_ctr/1,
aes_192_ecb/1,
aes_192_gcm/1,
+ aes_192_ofb/1,
aes_256_cbc/1,
aes_256_ccm/1,
aes_256_cfb128/1,
@@ -136,6 +156,7 @@
aes_256_ctr/1,
aes_256_ecb/1,
aes_256_gcm/1,
+ aes_256_ofb/1,
aes_cbc/1,
aes_cbc128/1,
aes_cbc256/1,
@@ -168,6 +189,11 @@
rsa_oaep_label/0
]).
+
+-compile({nowarn_deprecated_function, [{crypto, crypto_dyn_iv_init, 3},
+ {crypto, crypto_dyn_iv_update, 3}
+ ]}).
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
@@ -195,6 +221,7 @@ all() ->
info,
cipher_info,
hash_info,
+ hash_equals,
pbkdf2_hmac
].
@@ -205,6 +232,7 @@ groups() ->
[{non_fips, [], [
{group, blake2b},
{group, blake2s},
+ {group, poly1305},
{group, dss},
{group, ecdsa},
{group, ed25519},
@@ -265,11 +293,15 @@ groups() ->
{group, aes_256_cfb128},
{group, aes_128_cfb8},
{group, aes_192_cfb8},
- {group, aes_256_cfb8}
+ {group, aes_256_cfb8},
+ {group, aes_128_ofb},
+ {group, aes_192_ofb},
+ {group, aes_256_ofb}
]},
{fips, [], [
{group, no_blake2b},
{group, no_blake2s},
+ {group, no_poly1305},
{group, dss},
{group, ecdsa},
{group, no_ed25519},
@@ -325,25 +357,28 @@ groups() ->
{group, aes_256_cfb128},
{group, aes_128_cfb8},
{group, aes_192_cfb8},
- {group, aes_256_cfb8}
+ {group, aes_256_cfb8},
+ {group, aes_128_ofb},
+ {group, aes_192_ofb},
+ {group, aes_256_ofb}
]},
{md4, [], [hash]},
- {md5, [], [hash]},
+ {md5, [], [hash, hmac, hmac_update]},
{ripemd160, [], [hash]},
- {sha, [], [hash]},
- {sha224, [], [hash]},
- {sha256, [], [hash]},
- {sha384, [], [hash]},
- {sha512, [], [hash]},
- {sha3_224, [], [hash]},
- {sha3_256, [], [hash]},
- {sha3_384, [], [hash]},
- {sha3_512, [], [hash]},
- {blake2b, [], [hash]},
- {blake2s, [], [hash]},
- {no_blake2b, [], [no_hash]},
- {no_blake2s, [], [no_hash]},
+ {sha, [], [hash, hmac, hmac_update]},
+ {sha224, [], [hash, hmac, hmac_update]},
+ {sha256, [], [hash, hmac, hmac_update]},
+ {sha384, [], [hash, hmac, hmac_update]},
+ {sha512, [], [hash, hmac, hmac_update]},
+ {sha3_224, [], [hash, hmac, hmac_update]},
+ {sha3_256, [], [hash, hmac, hmac_update]},
+ {sha3_384, [], [hash, hmac, hmac_update]},
+ {sha3_512, [], [hash, hmac, hmac_update]},
+ {blake2b, [], [hash, hmac, hmac_update]},
+ {blake2s, [], [hash, hmac, hmac_update]},
+ {no_blake2b, [], [no_hash, no_hmac]},
+ {no_blake2s, [], [no_hash, no_hmac]},
{rsa, [], [sign_verify,
public_encrypt,
private_encrypt,
@@ -372,7 +407,7 @@ groups() ->
{srp, [], [generate_compute]},
{des_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{des_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac]},
{des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{rc2_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_cfb8, [], []},
@@ -392,9 +427,11 @@ groups() ->
{rc4, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{chacha20_poly1305, [], [aead_ng, aead_bad_tag]},
{chacha20, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {poly1305, [], [poly1305]},
+ {no_poly1305, [], [no_poly1305]},
{no_aes_cfb128, [], [no_support]},
{no_md4, [], [no_support, no_hash]},
- {no_md5, [], [no_support, no_hash]},
+ {no_md5, [], [no_support, no_hash, no_hmac]},
{no_ed25519, [], [no_support, no_sign_verify
%% Does not work yet: ,public_encrypt, private_encrypt
]},
@@ -420,6 +457,8 @@ groups() ->
bad_generate_key_name,
bad_hash_name,
bad_mac_name,
+ bad_hmac_name,
+ bad_cmac_name,
bad_sign_name,
bad_verify_name
]},
@@ -427,21 +466,24 @@ groups() ->
%% New cipher nameing schema
{des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_128_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_128_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac]},
{aes_128_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_192_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_256_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_128_ccm, [], [aead_ng, aead_bad_tag]},
{aes_192_ccm, [], [aead_ng, aead_bad_tag]},
{aes_256_ccm, [], [aead_ng, aead_bad_tag]},
- {aes_128_ecb, [], [api_ng, api_ng_one_shot]},
+ {aes_128_ecb, [], [api_ng, api_ng_one_shot, cmac_update]},
{aes_192_ecb, [], [api_ng, api_ng_one_shot]},
{aes_256_ecb, [], [api_ng, api_ng_one_shot]},
{aes_128_gcm, [], [aead_ng, aead_bad_tag]},
{aes_192_gcm, [], [aead_ng, aead_bad_tag]},
- {aes_256_gcm, [], [aead_ng, aead_bad_tag]}
+ {aes_256_gcm, [], [aead_ng, aead_bad_tag]},
+ {aes_128_ofb, [], [api_ng, api_ng_one_shot]},
+ {aes_192_ofb, [], [api_ng, api_ng_one_shot]},
+ {aes_256_ofb, [], [api_ng, api_ng_one_shot]}
].
%%-------------------------------------------------------------------
@@ -535,6 +577,13 @@ init_per_testcase(cmac, Config) ->
false ->
{skip, "CMAC is not supported"}
end;
+init_per_testcase(cmac_update, Config) ->
+ case {is_supported(cmac),
+ maps:get(cryptolib_version_linked, crypto:info(), "")} of
+ {true, "OpenSSL 1.0."++_} -> {skip, "cmac_update is not supported"};
+ {false, _} -> {skip, "CMAC is not supported"};
+ _ -> Config
+ end;
init_per_testcase(generate, Config) ->
case proplists:get_value(type, Config) of
rsa ->
@@ -700,36 +749,21 @@ make_crypto_key(String) ->
{[K1,K2,K3],IVec,8}.
%%--------------------------------------------------------------------
%% Test that a spawned node has initialized the cache
--define(at_node,
- (fun(N, M, F, As) ->
- R = rpc:call(N, M, F, As),
- ct:log("~p ~p ~p:~p(~s) = ~p", [?LINE,N,M,F,args2list(As), R]),
- R
- end) ).
-args2list(As) -> lists:join(", ", [io_lib:format("~p",[A]) || A <- As]).
node_supports_cache(_Config) ->
ECs = crypto:supports(curves),
- {ok,Node} = start_slave_node(random_node_name(?MODULE)),
- case ?at_node(Node, crypto, supports, [curves]) of
+ {ok,Peer,Node} = ?CT_PEER(),
+ case erpc:call(Node, crypto, supports, [curves]) of
ECs ->
- test_server:stop_node(Node);
+ peer:stop(Peer);
OtherECs ->
+ peer:stop(Peer),
ct:log("At master:~p~nAt slave:~p~n"
"Missing at slave: ~p~nmissing at master: ~p",
[ECs, OtherECs, ECs--OtherECs, OtherECs--ECs]),
{fail, "different support at slave"}
end.
-
-start_slave_node(Name) ->
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, " -pa " ++ Pa}]).
-
-random_node_name(BaseName) ->
- L = integer_to_list(erlang:unique_integer([positive])),
- lists:concat([BaseName,"___",L]).
-
%%--------------------------------------------------------------------
hash() ->
[{doc, "Test all different hash functions"}].
@@ -749,6 +783,62 @@ no_hash(Config) when is_list(Config) ->
Type = ?config(type, Config),
notsup(fun crypto:hash/2, [Type, <<"Hi There">>]),
notsup(fun crypto:hash_init/1, [Type]).
+%%--------------------------------------------------------------------
+hmac() ->
+ [{doc, "Test hmac function"}].
+hmac(Config) when is_list(Config) ->
+ Tuples = lazy_eval(proplists:get_value(hmac, Config)),
+ do_cipher_tests(fun mac_check/1, Tuples++mac_listify(Tuples)).
+%%--------------------------------------------------------------------
+no_hmac() ->
+ [{doc, "Test all disabled hmac functions"}].
+no_hmac(Config) when is_list(Config) ->
+ Type = ?config(type, Config),
+ notsup(fun crypto:mac/4, [hmac, Type, <<"Key">>, <<"Hi There">>]).
+%%--------------------------------------------------------------------
+hmac_update() ->
+ [{doc, "Test all incremental hmac functions"}].
+hmac_update(Config) ->
+ SubType = ?config(type, Config),
+ Key = hmac_key(SubType),
+ Increments = hmac_inc(SubType),
+ mac_increment(hmac, SubType, Key, Increments).
+%%--------------------------------------------------------------------
+cmac() ->
+ [{doc, "Test all different cmac functions"}].
+cmac(Config) when is_list(Config) ->
+ Pairs = lazy_eval(proplists:get_value(cmac, Config)),
+ do_cipher_tests(fun mac_check/1, Pairs ++ mac_listify(Pairs)).
+%%--------------------------------------------------------------------
+cmac_update() ->
+ [{doc, "Test all incremental cmac functions"}].
+cmac_update(Config) ->
+ SubType = ?config(type, Config),
+ Key = cmac_key(SubType),
+ Increments = cmac_inc(SubType),
+ mac_increment(cmac, SubType, Key, Increments).
+%%--------------------------------------------------------------------
+poly1305() ->
+ [{doc, "Test poly1305 function"}].
+poly1305(Config) ->
+ lists:foreach(
+ fun({Key, Txt, Expect}) ->
+ case crypto:mac(poly1305,Key,Txt) of
+ Expect ->
+ ok;
+ Other ->
+ ct:fail({{crypto, mac, [poly1305, Key, Txt]}, {expected, Expect}, {got, Other}})
+ end
+ end, proplists:get_value(poly1305, Config)).
+
+%%--------------------------------------------------------------------
+no_poly1305() ->
+ [{doc, "Test disabled poly1305 function"}].
+no_poly1305(_Config) ->
+ Key = <<133,214,190,120,87,85,109,51,127,68,82,254,66,213,6,168,1,
+ 3,128,138,251,13,178,253,74,191,246,175,65,73,245,27>>,
+ Txt = <<"Cryptographic Forum Research Group">>,
+ notsup(fun crypto:mac/3, [poly1305,Key,Txt]).
%%--------------------------------------------------------------------
api_ng() ->
@@ -1189,6 +1279,18 @@ use_all_ec_sign_verify(_Config) ->
ok;
_ ->
ct:log("Fails:~n~p",[Fails]),
+ Errors = lists:usort([Err || {_,Err} <- Fails]),
+ FailedCurves = [Curve || {Curve,_} <- Fails],
+ FailedCurvesPerError = [{E, [C || {C,E0} <- Fails,
+ E0 == E]}
+ || E <- Errors],
+ ct:pal("~p failed curves: ~p", [length(FailedCurves), FailedCurves]),
+ ct:pal("Failed curves per error:~n~s",
+ [
+ [io_lib:format(" Error: ~p~n Curves: ~p~n~n", [E,Cs])
+ || {E,Cs} <- FailedCurvesPerError]
+ ]
+ ),
ct:fail("Bad curve(s)",[])
end.
@@ -1233,13 +1335,31 @@ do_dh_curves(_Config, Curves) ->
(_) -> true
end, Results),
+ Succedes =
+ lists:filter(fun({_,true}) -> true;
+ (_) -> false
+ end, Results),
+
case Fails of
[] ->
ct:comment("All ~p passed",[length(Results)]),
ok;
_ ->
- ct:comment("passed: ~p, failed: ~p",[length(Results),length(Fails)]),
+ ct:comment("passed: ~p, failed: ~p",[length(Results)-length(Fails),length(Fails)]),
+ ct:log("Succedes:~n~p",[Succedes]),
ct:log("Fails:~n~p",[Fails]),
+ Errors = lists:usort([Err || {_,Err} <- Fails]),
+ FailedCurves = [C || {C,_} <- Fails],
+ FailedCurvesPerError = [{E, [C || {C,E0} <- Fails,
+ E == E0]}
+ || E <- Errors],
+ ct:pal("~p (~p) failed curves: ~p", [length(FailedCurves), length(Results), FailedCurves]),
+ ct:pal("Failed curves per error:~n~s",
+ [
+ [io_lib:format(" Error: ~p~n Curves: ~p~n~n", [E,Cs])
+ || {E,Cs} <- FailedCurvesPerError]
+ ]
+ ),
ct:fail("Bad curve(s)",[])
end.
@@ -1261,6 +1381,18 @@ exor(Config) when is_list(Config) ->
do_exor(<<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>),
do_exor(term_to_binary(lists:seq(1, 1000000))).
%%--------------------------------------------------------------------
+hash_equals() ->
+ [{doc, "Test the hash_equals function"}].
+hash_equals(Config) when is_list(Config) ->
+ try
+ true = crypto:hash_equals(<<>>, <<>>),
+ true = crypto:hash_equals(<<"abc">>, <<"abc">>),
+ false = crypto:hash_equals(<<"abc">>, <<"abe">>)
+ catch
+ error:{notsup,{"hash_equals.c",_Line},"Unsupported CRYPTO_memcmp"++_} ->
+ {skip, "No CRYPTO_memcmp"}
+ end.
+%%--------------------------------------------------------------------
rand_uniform() ->
[{doc, "rand_uniform and random_bytes testing"}].
rand_uniform(Config) when is_list(Config) ->
@@ -1300,17 +1432,31 @@ rand_plugin_s(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
info(_Config) ->
[{_,_,VerBin}] = crypto:info_lib(),
- Ver = binary:bin_to_list(VerBin),
+ LibVer = binary:bin_to_list(VerBin),
try
crypto:info()
of
- #{cryptolib_version_compiled := Ver,
- cryptolib_version_linked := Ver,
+ #{cryptolib_version_compiled := LibVer,
+ cryptolib_version_linked := LibVer,
+ compile_type := Tc,
+ link_type := Tl} when is_atom(Tc), is_atom(Tl) ->
+ ok;
+
+ %% Version strings in header vs lib seen to differ slightly on SUSE
+ %% but OpenSSL version numbers should be the same
+ #{cryptolib_version_compiled := CompVer,
+ cryptolib_version_linked := LibVer,
compile_type := Tc,
link_type := Tl} when is_atom(Tc), is_atom(Tl) ->
+ RE = "OpenSSL (\\d+\\.\\d+\\.\\d+.)",
+ Opts = [{capture,first,list}],
+ {match,[CompV]} = re:run(CompVer, RE, Opts),
+ {match,[LinkV]} = re:run(LibVer, RE, Opts),
+ {CompV,CompV} = {CompV,LinkV},
ok;
+
Other ->
- ct:log("Ver = ~p~ncrypto:info() -> ~p", [Ver,Other]),
+ ct:log("LibVer = ~p~ncrypto:info() -> ~p", [LibVer,Other]),
ct:fail("Version mismatch", [])
catch
C:E ->
@@ -1430,9 +1576,27 @@ mac_check({MacType, SubType, Key, Text, Mac}=T) ->
mac_check({MacType, SubType, Key, Text, Size, Mac}=T) ->
ExpMac = iolist_to_binary(Mac),
cipher_test(T,
- fun() -> crypto:mac(MacType, SubType, Key, Text, Size) end,
+ fun() -> crypto:macN(MacType, SubType, Key, Text, Size) end,
ExpMac).
+mac_increment(Type, SubType, Key, Increments) ->
+ Expected = crypto:mac(Type, SubType, Key, Increments),
+ State = crypto:mac_init(Type, SubType, Key),
+ case do_mac_increment(State, Increments) of
+ Expected ->
+ ok;
+ Other ->
+ ct:fail({{crypto, "mac_init/update/final", [Type, SubType, Increments]},
+ {expected, Expected},
+ {got, Other}})
+ end.
+
+do_mac_increment(State, []) ->
+ crypto:mac_final(State);
+do_mac_increment(State0, [Increment | Rest]) ->
+ State = crypto:mac_update(State0, Increment),
+ do_mac_increment(State, Rest).
+
aead_cipher_ng({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, _Info}=T) ->
Plain = iolist_to_binary(PlainText),
cipher_test(T,
@@ -1482,7 +1646,7 @@ cipher_test(Tag, T, F, E) ->
E -> ok;
Other -> {other, {Tag,T,Other}}
catch
- error:Error -> {error, {Tag,T,Error}}
+ error:Error -> ct:pal("Tag = ~p,~n T = ~p,~n F = ~p,~n E = ~p,~n Error = ~p", [Tag, T, F, E, Error]), {error, {Tag,T,Error}}
end.
do_cipher_tests(F, TestVectors) when is_function(F,1) ->
@@ -1579,6 +1743,13 @@ do_sign_verify({Type, Hash, Public, Private, Msg, Options}) ->
ct:log("notsup but OK in old cryptolib crypto:sign(~p, ~p, ..., ..., ..., ~p)",
[Type,Hash,Options]),
true;
+ error:{notsup,_,_} when NotSupLow == true,
+ is_integer(LibVer),
+ LibVer < 16#10001000 ->
+ %% Those opts where introduced in 1.0.1
+ ct:log("notsup but OK in old cryptolib crypto:sign(~p, ~p, ..., ..., ..., ~p)",
+ [Type,Hash,Options]),
+ true;
C:E ->
ct:log("~p:~p crypto:sign(~p, ~p, ..., ..., ..., ~p)", [C,E,Type,Hash,Options]),
ct:fail({{crypto, sign_verify, [LibVer, Type, Hash, Msg, Public, Options]}})
@@ -1760,6 +1931,16 @@ decstr2int(S) ->
is_supported(Group) ->
lists:member(Group, lists:append([Algo || {_, Algo} <- crypto:supports()])).
+
+mac_listify(Blocks) ->
+ lists:map(fun do_mac_listify/1, Blocks).
+
+do_mac_listify({MType, Type, Key, Text, CMac}) ->
+ {MType, Type, iolistify(Key), iolistify(Text), CMac};
+do_mac_listify({MType, Type, Key, Text, Size, CMac}) ->
+ {MType, Type, iolistify(Key), iolistify(Text), Size, CMac}.
+
+
iolistify(X) ->
iolistify1(lazy_eval(X)).
@@ -2093,6 +2274,15 @@ group_config(eddh, Config) ->
group_config(dh, Config) ->
GenerateCompute = [dh()],
[{generate_compute, GenerateCompute} | Config];
+group_config(poly1305, Config) ->
+ V = [%% {Key, Txt, Expect}
+ {%% RFC7539 2.5.2
+ hexstr2bin("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"),
+ <<"Cryptographic Forum Research Group">>,
+ hexstr2bin("a8061dc1305136c6c22b8baf0c0127a9")
+ }
+ ],
+ [{poly1305,V} | Config];
group_config(F, Config) ->
TestVectors = fun() -> ?MODULE:F(Config) end,
@@ -2102,7 +2292,7 @@ group_config(F, Config) ->
configure_mac(MacType, SubType, Config) ->
case do_configure_mac(MacType, SubType, Config) of
undefined ->
- {skip, io:format("No ~p test vectors for ~p", [MacType, SubType])};
+ {skip, io_lib:format("No ~p test vectors for ~p", [MacType, SubType])};
Pairs ->
[{MacType, Pairs} | Config]
end.
@@ -2160,15 +2350,23 @@ do_configure_mac(cmac, Cipher, Config) ->
fun() -> read_rsp(Config, Cipher, ["CMACGenAES128.rsp", "CMACVerAES128.rsp"]) end;
aes_256_cbc ->
fun() -> read_rsp(Config, Cipher, ["CMACGenAES256.rsp", "CMACVerAES256.rsp"]) end;
+ des_ede3_cbc ->
+ fun() -> read_rsp(Config, Cipher, ["CMACGenTDES3.rsp", "CMACVerTDES3.rsp"]) end;
_ ->
undefined
end.
zip3_special(Type, SubType, As, Bs, Cs) ->
- [{Type, SubType, A, B, C}
+ [mk_zip3_special_elem(Type, SubType, A, B, C)
|| {A,B,C} <- lists:zip3(As, Bs, Cs)].
+mk_zip3_special_elem(hmac, sha, Key, <<"Test With Truncation">>=Data, Expected) ->
+ {hmac, sha, Key, Data, 20, Expected};
+mk_zip3_special_elem(hmac, SubType, Key, <<"Test With Truncation">>=Data, Expected) ->
+ {hmac, SubType, Key, Data, 16, Expected};
+mk_zip3_special_elem(Type, SubType, A, B, C) ->
+ {Type, SubType, A, B, C}.
rsa_sign_verify_tests(Config, Msg, Public, Private, PublicS, PrivateS, OptsToTry) ->
case ?config(fips, Config) of
@@ -2595,6 +2793,26 @@ rfc_2202_msgs()->
<<"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data">>
].
+hmac_key(md5) ->
+ [<<"A fine speach">>, <<"by a fine man!">>];
+hmac_key(_) ->
+ hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f").
+hmac_inc(_) ->
+ [<<"Sampl">>, <<"e #1">>].
+
+
+cmac_key(aes_128_cbc) ->
+ hexstr2bin("8eeca0d146fd09ffbbe0d47edcddfcec");
+cmac_key(aes_128_ecb) ->
+ hexstr2bin("8eeca0d146fd09ffbbe0d47edcddfcec").
+
+cmac_inc(_) ->
+ [<<"Sampl">>, <<"e #1">>].
+
+
%% https://www.cosic.esat.kuleuven.be/nessie/testvectors/
long_hmac_key(Type) when Type == sha384;
Type == sha512 ->
@@ -2861,6 +3079,21 @@ aes_256_cbc(Config) ->
["CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp",
"CBCMMT256.rsp"]).
+aes_128_ofb(Config) ->
+ read_rsp(Config, aes_128_ofb,
+ ["OFBVarTxt128.rsp", "OFBVarKey128.rsp", "OFBGFSbox128.rsp", "OFBKeySbox128.rsp",
+ "OFBMMT128.rsp"]).
+
+aes_192_ofb(Config) ->
+ read_rsp(Config, aes_192_ofb,
+ ["OFBVarTxt192.rsp", "OFBVarKey192.rsp", "OFBGFSbox192.rsp", "OFBKeySbox192.rsp",
+ "OFBMMT192.rsp"]).
+
+aes_256_ofb(Config) ->
+ read_rsp(Config, aes_256_ofb,
+ ["OFBVarTxt256.rsp", "OFBVarKey256.rsp", "OFBGFSbox256.rsp", "OFBKeySbox256.rsp",
+ "OFBMMT256.rsp"]).
+
aes_ecb(Config) ->
read_rsp(Config, aes_ecb,
["ECBVarTxt128.rsp", "ECBVarKey128.rsp", "ECBGFSbox128.rsp", "ECBKeySbox128.rsp",
@@ -4166,6 +4399,23 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
_ ->
parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, State, Acc)
end;
+parse_rsp(Type, [<<"Count = ", _/binary>>,
+ <<"Klen = ", _/binary>>,
+ <<"Mlen = ", Mlen/binary>>,
+ <<"Tlen = ", Tlen/binary>>,
+ <<"Key1 = ", Key1/binary>>,
+ <<"Key2 = ", Key2/binary>>,
+ <<"Key3 = ", Key3/binary>>,
+ <<"Msg = ", Msg/binary>>,
+ <<"Mac = ", MAC/binary>>|Rest], State, Acc) ->
+ case Rest of
+ [<<"Result = P">>|Next] ->
+ parse_rsp_cmac(Type, [Key1,Key2,Key3], Msg, Mlen, Tlen, MAC, Next, State, Acc);
+ [<<"Result = ", _/binary>>|Next] ->
+ parse_rsp(Type, Next, State, Acc);
+ _ ->
+ parse_rsp_cmac(Type, [Key1,Key2,Key3], Msg, Mlen, Tlen, MAC, Rest, State, Acc)
+ end;
%% GCM format decode format
parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
@@ -4283,7 +4533,9 @@ parse_rsp(Type, [_|Next], State, Acc) ->
parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, State, Acc) ->
- Key = hexstr2bin(Key0),
+ Key = if is_list(Key0) -> lists:map(fun hexstr2bin/1, Key0);
+ true -> hexstr2bin(Key0)
+ end,
Mlen = binary_to_integer(Mlen0),
<<Msg:Mlen/bytes, _/binary>> = hexstr2bin(Msg0),
MAC = hexstr2bin(MAC0),
@@ -4307,13 +4559,12 @@ api_errors_ecdh(Config) when is_list(Config) ->
%%%----- Tests for bad algorithm name as argument
--define(chk_api_name(Call, Expect),
- %% Check that we don't segfault on bad names
+-define(chk_api_name_helper(Call, ExpectPart),
(fun() -> % avoid binding vars
try
Call
catch
- Expect -> ok;
+ ExpectPart
Class:Reason:Stack ->
ct:log("~p:~p~n~p", [Class,Reason,Stack]),
@@ -4322,6 +4573,19 @@ api_errors_ecdh(Config) when is_list(Config) ->
end)()
).
+-define(chk_api_name(Call, Expect),
+ ?chk_api_name_helper(Call, Expect -> ok;)
+ ).
+
+-define(chk_api_name(Call, Expect1, Expect2),
+ ?chk_api_name_helper(Call, Expect1 -> ok; Expect2 -> ok; )
+ ).
+
+-define(chk_api_name(Call, Expect1, Expect2, Expect3),
+ ?chk_api_name_helper(Call, Expect1 -> ok; Expect2 -> ok; Expect3 -> ok; )
+ ).
+
+
bad_combo(_Config) ->
?chk_api_name(crypto:crypto_dyn_iv_init(des_ede3_cbc, <<>>, []),
error:_).
@@ -4340,23 +4604,34 @@ bad_generate_key_name(_Config) ->
bad_hash_name(_Config) ->
?chk_api_name(crypto:hash_init(foobar),
- error:badarg).
+ error:{badarg,{"hash.c",_},"Bad digest type"++_}).
bad_mac_name(_Config) ->
?chk_api_name(crypto:mac(foobar, <<1:1024>>, "nothing"),
error:function_clause).
+bad_hmac_name(_Config) ->
+ ?chk_api_name(crypto:mac(hmac, foobar, <<1:1024>>, "nothing"),
+ error:{badarg,{"mac.c",_},"Bad digest algorithm"++_}).
+
+bad_cmac_name(_Config) ->
+ ?chk_api_name(crypto:mac(cmac, foobar, <<1:1024>>, "nothing"),
+ error:{badarg,{"mac.c",_},"Unknown cipher"++_},
+ error:{notsup,_, "Unsupported mac algorithm"++_},
+ error:{badarg,#{}, "Unknown cipher"++_}
+ ).
+
bad_sign_name(_Config) ->
?chk_api_name(crypto:sign(rsa, foobar, "nothing", <<1:1024>>),
- error:badarg),
+ error:{badarg, {"pkey.c",_}, "Bad digest type"++_}),
?chk_api_name(crypto:sign(foobar, sha, "nothing", <<1:1024>>),
- error:badarg).
+ error:{badarg, {"pkey.c",_}, "Bad algorithm"++_}).
bad_verify_name(_Config) ->
- ?chk_api_name(crypto:verify(rsa, foobar, "nothing","nothing", <<1:1024>>),
- error:badarg),
- ?chk_api_name(crypto:verify(foobar, sha, "nothing", "nothing", <<1:1024>>),
- error:badarg).
+ ?chk_api_name(crypto:verify(rsa, foobar, "nothing", <<"nothing">>, <<1:1024>>),
+ error:{badarg,{"pkey.c",_},"Bad digest type"++_}),
+ ?chk_api_name(crypto:verify(foobar, sha, "nothing", <<"nothing">>, <<1:1024>>),
+ error:{badarg, {"pkey.c",_}, "Bad algorithm"++_}).
%%%----------------------------------------------------------------
@@ -4446,7 +4721,7 @@ pbkdf2_hmac(Config) when is_list(Config) ->
<<"6B9CF26D45455A43A5B8BB276A403B39E7FE37A0C41E02C281FF3069E1E94F52">> =
F(binary:encode_unsigned(16#f09d849e), <<"EXAMPLE.COMpianist">>, 50, 32)
catch
- error:{notsup, _, "Unsupported CRYPTO_PKCS5_PBKDF2_HMAC"} ->
+ error:{notsup, _, "Unsupported CRYPTO_PKCS5_PBKDF2_HMAC"++_} ->
{skip, "No CRYPTO_PKCS5_PBKDF2_HMAC"}
end.
diff --git a/lib/crypto/test/crypto_gh.spec b/lib/crypto/test/crypto_gh.spec
new file mode 100644
index 0000000000..a1119373cd
--- /dev/null
+++ b/lib/crypto/test/crypto_gh.spec
@@ -0,0 +1,5 @@
+{suites,"../crypto_test",all}.
+{skip_suites, "../crypto_test", [crypto_bench_SUITE],
+ "Benchmarks run separately"}.
+{skip_cases, "../crypto_test", engine_SUITE,
+ [multiple_engine_load],"Broken with openssl 1.1.1f and docker"}.
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index cab519fdb9..8907d3968f 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,12 +35,8 @@
end_per_testcase/2,
get_all_possible_methods/0,
get_all_possible_methods/1,
- engine_load_all_methods/0,
- engine_load_all_methods/1,
- engine_load_some_methods/0,
- engine_load_some_methods/1,
- multiple_engine_load/0,
- multiple_engine_load/1,
+ engine_load_register_method/0,
+ engine_load_register_method/1,
engine_list/0,
engine_list/1,
get_id_and_name/0,
@@ -63,10 +59,13 @@
ctrl_cmd_string_optional/1,
ensure_load/0,
ensure_load/1,
+ gc_clean/0,
+ gc_clean/1,
sign_verify_rsa/1,
sign_verify_rsa_fake/1,
sign_verify_dsa/1,
sign_verify_ecdsa/1,
+ sign_verify_eddsa/1,
sign_verify_rsa_pwd/1,
sign_verify_rsa_pwd_bad_pwd/1,
priv_encrypt_pub_decrypt_rsa/1,
@@ -92,9 +91,7 @@ suite() ->
all() ->
[
get_all_possible_methods,
- engine_load_all_methods,
- engine_load_some_methods,
- multiple_engine_load,
+ engine_load_register_method,
engine_list,
get_id_and_name,
engine_by_id,
@@ -106,6 +103,7 @@ all() ->
ctrl_cmd_string,
ctrl_cmd_string_optional,
ensure_load,
+ gc_clean,
{group, engine_stored_key},
{group, engine_fakes_rsa}
].
@@ -116,6 +114,7 @@ groups() ->
sign_verify_rsa,
sign_verify_dsa,
sign_verify_ecdsa,
+ sign_verify_eddsa,
sign_verify_rsa_pwd,
sign_verify_rsa_pwd_bad_pwd,
priv_encrypt_pub_decrypt_rsa,
@@ -129,9 +128,11 @@ groups() ->
get_pub_from_priv_key_dsa,
get_pub_from_priv_key_ecdsa
]},
- {engine_fakes_rsa, [], [sign_verify_rsa_fake
- ]}
- ].
+ {engine_fakes_rsa, [],
+ [
+ sign_verify_rsa_fake
+ ]}
+ ].
init_per_suite(Config) ->
@@ -187,10 +188,10 @@ init_per_group(engine_fakes_rsa, Config) ->
init_per_group(_Group, Config0) ->
Config0.
-
group_load_engine(Config, ExcludeMthds) ->
- case load_storage_engine(Config, ExcludeMthds) of
+ case load_storage_engine(Config) of
{ok, E} ->
+ ok = crypto:engine_register(E, crypto:engine_get_all_methods() -- ExcludeMthds),
KeyDir = key_dir(Config),
ct:log("storage engine ~p loaded.~nKeyDir = ~p", [E,KeyDir]),
[{storage_engine,E}, {storage_dir,KeyDir} | Config];
@@ -205,10 +206,6 @@ group_load_engine(Config, ExcludeMthds) ->
{fail, "Engine load failed"}
end.
-
-
-
-
end_per_group(_, Config) ->
case proplists:get_value(storage_engine, Config) of
undefined ->
@@ -219,18 +216,22 @@ end_per_group(_, Config) ->
%%--------------------------------------------------------------------
init_per_testcase(Case, Config) ->
- case string:tokens(atom_to_list(Case),"_") of
- ["sign","verify",Type|_] ->
- skip_if_unsup(list_to_atom(Type), Config);
-
- ["priv","encrypt","pub","decrypt",Type|_] ->
- skip_if_unsup(list_to_atom(Type), Config);
-
- ["get","pub","from","priv","key",Type|_] ->
- skip_if_unsup(list_to_atom(Type), Config);
-
+ HasMD5 = lists:member(md5, crypto:supports(hashs)),
+ case Case of
+ ensure_load when HasMD5==false -> {skip, "md5 not available"};
+ engine_load_register_method when HasMD5==false -> {skip, "md5 not available"};
+ gc_clean when HasMD5==false -> {skip, "md5 not available"};
_ ->
- Config
+ case string:tokens(atom_to_list(Case),"_") of
+ ["sign","verify",Type|_] ->
+ skip_if_unsup(list_to_atom(Type), Config);
+ ["priv","encrypt","pub","decrypt",Type|_] ->
+ skip_if_unsup(list_to_atom(Type), Config);
+ ["get","pub","from","priv","key",Type|_] ->
+ skip_if_unsup(list_to_atom(Type), Config);
+ _ ->
+ Config
+ end
end.
end_per_testcase(_Case, _Config) ->
@@ -253,12 +254,13 @@ get_all_possible_methods(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
-engine_load_all_methods()->
+%%-------------------------------------------------------------------------
+engine_load_register_method()->
[{doc, "Use a dummy md5 engine that does not implement md5"
"but rather returns a static binary to test that crypto:engine_load "
"functions works."}].
-engine_load_all_methods(Config) when is_list(Config) ->
+engine_load_register_method(Config) when is_list(Config) ->
case crypto:get_test_engine() of
{error, notexist} ->
{skip, "OTP Test engine not found"};
@@ -270,8 +272,10 @@ engine_load_all_methods(Config) when is_list(Config) ->
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
<<"LOAD">>],
- []) of
+ []) of
{ok, E} ->
+ ok = crypto:engine_register(E, [engine_method_digests]),
+
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
ct:fail(fail_to_load_still_original_engine);
@@ -280,128 +284,10 @@ engine_load_all_methods(Config) when is_list(Config) ->
_ ->
ct:fail(fail_to_load_engine)
end,
- ok = crypto:engine_unload(E),
- case crypto:hash(md5, "Don't panic") of
- Md5Hash2 ->
- ct:fail(fail_to_unload_still_test_engine);
- Md5Hash1 ->
- ok;
- _ ->
- ct:fail(fail_to_unload_engine)
- end;
- {error, bad_engine_id} ->
- {skip, "Dynamic Engine not supported"}
- end
- catch
- error:notsup ->
- {skip, "Engine not supported on this SSL version"}
- end
- end.
-
-engine_load_some_methods()->
- [{doc, "Use a dummy md5 engine that does not implement md5"
- "but rather returns a static binary to test that crypto:engine_load "
- "functions works."}].
-engine_load_some_methods(Config) when is_list(Config) ->
- case crypto:get_test_engine() of
- {error, notexist} ->
- {skip, "OTP Test engine not found"};
- {ok, Engine} ->
- try
- Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
- Md5Hash1 = crypto:hash(md5, "Don't panic"),
- Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- EngineMethods = crypto:engine_get_all_methods() --
- [engine_method_dh, engine_method_rand,
- engine_method_ciphers, engine_method_store,
- engine_method_pkey_meths, engine_method_pkey_asn1_meths],
- case crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, Engine},
- <<"LOAD">>],
- [],
- EngineMethods) of
- {ok, E} ->
- case crypto:hash(md5, "Don't panic") of
- Md5Hash1 ->
- ct:fail(fail_to_load_engine_still_original);
- Md5Hash2 ->
- ok;
- _ ->
- ct:fail(fail_to_load_engine)
- end,
+ ok = crypto:engine_unregister(E, [engine_method_digests]),
ok = crypto:engine_unload(E),
- case crypto:hash(md5, "Don't panic") of
- Md5Hash2 ->
- ct:fail(fail_to_unload_still_test_engine);
- Md5Hash1 ->
- ok;
- _ ->
- ct:fail(fail_to_unload_engine)
- end;
- {error, bad_engine_id} ->
- {skip, "Dynamic Engine not supported"}
- end
- catch
- error:notsup ->
- {skip, "Engine not supported on this SSL version"}
- end
- end.
-
-multiple_engine_load()->
- [{doc, "Use a dummy md5 engine that does not implement md5"
- "but rather returns a static binary to test that crypto:engine_load "
- "functions works when called multiple times."}].
-multiple_engine_load(Config) when is_list(Config) ->
- case crypto:get_test_engine() of
- {error, notexist} ->
- {skip, "OTP Test engine not found"};
- {ok, Engine} ->
- try
- Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
- Md5Hash1 = crypto:hash(md5, "Don't panic"),
- Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- case crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, Engine},
- <<"LOAD">>],
- []) of
- {ok, E} ->
- {ok, E1} = crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, Engine},
- <<"LOAD">>],
- []),
- {ok, E2} = crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, Engine},
- <<"LOAD">>],
- []),
- case crypto:hash(md5, "Don't panic") of
- Md5Hash1 ->
- ct:fail(fail_to_load_still_original_engine);
- Md5Hash2 ->
- ok;
- _ ->
- ct:fail(fail_to_load_engine)
- end,
- ok = crypto:engine_unload(E2),
- case crypto:hash(md5, "Don't panic") of
- Md5Hash1 ->
- ct:fail(fail_to_load_still_original_engine);
- Md5Hash2 ->
- ok;
- _ ->
- ct:fail(fail_to_load_engine)
- end,
- ok = crypto:engine_unload(E),
- case crypto:hash(md5, "Don't panic") of
- Md5Hash1 ->
- ct:fail(fail_to_load_still_original_engine);
- Md5Hash2 ->
- ok;
- _ ->
- ct:fail(fail_to_load_engine)
- end,
- ok = crypto:engine_unload(E1),
case crypto:hash(md5, "Don't panic") of
Md5Hash2 ->
ct:fail(fail_to_unload_still_test_engine);
@@ -419,6 +305,7 @@ multiple_engine_load(Config) when is_list(Config) ->
end
end.
+%%-------------------------------------------------------------------------
engine_list()->
[{doc, "Test add and remove engine ID to the SSL internal engine list."}].
@@ -449,6 +336,7 @@ engine_list(Config) when is_list(Config) ->
end
end.
+%%-------------------------------------------------------------------------
get_id_and_name()->
[{doc, "Test fetching id and name from an engine."}].
@@ -475,6 +363,7 @@ get_id_and_name(Config) when is_list(Config) ->
end
end.
+%%-------------------------------------------------------------------------
engine_by_id()->
[{doc, "Test fetching a new reference the the engine when the"
"engine id is added to the SSL engine list."}].
@@ -568,6 +457,7 @@ bad_arguments(Config) when is_list(Config) ->
end
end.
+%%-------------------------------------------------------------------------
unknown_engine() ->
[{doc, "Try to load a non existent engine."}].
@@ -580,6 +470,7 @@ unknown_engine(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
pre_command_fail_bad_value() ->
[{doc, "Test pre command due to bad value"}].
@@ -602,6 +493,7 @@ pre_command_fail_bad_value(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
pre_command_fail_bad_key() ->
[{doc, "Test pre command due to bad key"}].
@@ -627,6 +519,7 @@ pre_command_fail_bad_key(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
failed_engine_init()->
[{doc, "Test failing engine init due to missed pre command"}].
@@ -651,7 +544,6 @@ failed_engine_init(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
-
%%-------------------------------------------------------------------------
%% Test the optional flag in ctrl comands
ctrl_cmd_string()->
@@ -684,6 +576,7 @@ ctrl_cmd_string(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
ctrl_cmd_string_optional()->
[{doc, "Test that a not known optional ctrl command do not fail"}].
ctrl_cmd_string_optional(Config) when is_list(Config) ->
@@ -715,6 +608,9 @@ ctrl_cmd_string_optional(Config) when is_list(Config) ->
{skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
+%
+%
ensure_load()->
[{doc, "Test the special ensure load function."}].
@@ -728,8 +624,9 @@ ensure_load(Config) when is_list(Config) ->
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
- {ok, E1} ->
- {ok, E2} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ {ok, E} ->
+ ok = crypto:engine_register(E, [engine_method_digests]),
+
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
ct:fail(fail_to_load_still_original_engine);
@@ -739,49 +636,155 @@ ensure_load(Config) when is_list(Config) ->
ct:fail(fail_to_load_engine)
end,
- {ok, E3} = crypto:engine_by_id(<<"MD5">>),
-
- ok = crypto:ensure_engine_unloaded(E3),
+ {ok, E1} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+
+ ok = crypto:ensure_engine_unloaded(E1),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_test_engine_unloaded);
Md5Hash2 ->
- ct:fail(fail_to_unload_still_test_engine);
+ ok;
_ ->
- ct:fail(load_engine)
+ ct:fail(fail_to_unload_engine)
end,
- %% ToDo: Why doesn't this work?
- %% {ok, E4} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
- %% case crypto:hash(md5, "Don't panic") of
- %% Md5Hash1 ->
- %% ct:fail(fail_to_load_still_original_engine);
- %% Md5Hash2 ->
- %% ok;
- %% _ ->
- %% ct:fail(fail_to_load_engine)
- %% end,
+ {ok, E2} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_test_engine_not_loaded);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:ensure_engine_unloaded(E2),
- ok = crypto:ensure_engine_unloaded(E1),
+ {ok, E3} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_test_engine_not_loaded);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+
+ ok = crypto:ensure_engine_unloaded(E),
case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_test_engine_not_loaded);
Md5Hash2 ->
- ct:fail(fail_to_unload_still_test_engine);
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end,
+
+ ok = crypto:engine_unregister(E3, [engine_method_digests]),
+ ok = crypto:ensure_engine_unloaded(E3),
+ case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
- ok = crypto:ensure_engine_unloaded(E2),
- %% ok = crypto:ensure_engine_unloaded(E4);
ok;
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
_ ->
ct:fail(fail_to_unload_engine)
end;
+
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
catch
error:notsup ->
- {skip, "Engine not supported on this SSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
+%%-------------------------------------------------------------------------
+gc_clean()->
+ [{doc, "Test the special ensure load function."}].
+
+gc_clean(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+
+ load_without_unload(Engine, Md5Hash1, Md5Hash2),
+
+ erlang:garbage_collect(),
+ timer:sleep(1000),
+
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end,
+
+ try
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ ok = crypto:engine_register(E, [engine_method_digests]),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+
+ ok = crypto:engine_unregister(E, [engine_method_digests]),
+ ok = crypto:engine_remove(E),
+ ok = crypto:ensure_engine_unloaded(E),
+
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+load_without_unload(Engine, Md5Hash1, Md5Hash2) ->
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ ok = crypto:engine_register(E, [engine_method_digests]),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok = crypto:engine_unregister(E, [engine_method_digests]),
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end;
+ {error, bad_engine_id} ->
+ io:format("load_without_unload: bad_engine_id\n", [])
+ end.
%%%----------------------------------------------------------------
%%% Pub/priv key storage tests. Those are for testing the crypto.erl
@@ -816,6 +819,13 @@ sign_verify_ecdsa(Config) ->
key_id => key_id(Config, "ecdsa_public_key.pem")},
sign_verify(ecdsa, sha, Priv, Pub).
+sign_verify_eddsa(Config) ->
+ Priv = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "eddsa_private_key.pem")},
+ Pub = #{engine => engine_ref(Config),
+ key_id => key_id(Config, "eddsa_public_key.pem")},
+ sign_verify(eddsa, sha, Priv, Pub).
+
sign_verify_rsa_pwd(Config) ->
Priv = #{engine => engine_ref(Config),
key_id => key_id(Config, "rsa_private_key_pwd.pem"),
@@ -833,7 +843,7 @@ sign_verify_rsa_pwd_bad_pwd(Config) ->
try sign_verify(rsa, sha, Priv, Pub) of
_ -> {fail, "PWD prot pubkey sign succeeded with no pwd!"}
catch
- error:badarg -> ok
+ error:{badarg,_,_} -> ok
end.
priv_encrypt_pub_decrypt_rsa(Config) ->
@@ -974,16 +984,14 @@ pkey_supported(Type) ->
lists:member(Type, proplists:get_value(public_keys, crypto:supports(), [])).
-load_storage_engine(_Config, ExcludeMthds) ->
+load_storage_engine(_Config) ->
case crypto:get_test_engine() of
- {ok, Engine} ->
+ {ok, EngineLibPath} ->
try crypto:engine_load(<<"dynamic">>,
- [{<<"SO_PATH">>, Engine},
- <<"LOAD">>],
- [],
- crypto:engine_get_all_methods() -- ExcludeMthds
- )
- catch
+ [{<<"SO_PATH">>, EngineLibPath},
+ <<"LOAD">>],
+ [])
+ catch
error:notsup ->
{error, notsup}
end;
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_private_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_private_key.pem
new file mode 100644
index 0000000000..6e2eb18bdd
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_private_key.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIH8U4DpDNRXUDqYK8tYrlcOXPwx4Y6hrWfMpvvd7AioY
+-----END PRIVATE KEY-----
diff --git a/lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_public_key.pem b/lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_public_key.pem
new file mode 100644
index 0000000000..f5728f5708
--- /dev/null
+++ b/lib/crypto/test/engine_SUITE_data/pkcs8/eddsa_public_key.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VwAyEAM/95MNGrel/42ymyPnyOMh1Yfglw8WZ9KPpMajSQBHE=
+-----END PUBLIC KEY-----
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 9e3356b8c2..41dfbaef97 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 5.0.6
+CRYPTO_VSN = 5.1.3
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 94cd320955..6b2188130d 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,6 +33,43 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 5.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that would cause analysis to crash.</p>
+ <p>
+ Own Id: OTP-18372 Aux Id: GH-6580 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Debugger 5.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The configuration files <seecom
+ marker="erts:erl"><c>.erlang</c></seecom>, <seeguide
+ marker="system/reference_manual:distributed"><c>.erlang.cookie</c></seeguide>
+ and <seeerl
+ marker="stdlib:beam_lib#.erlang.crypt"><c>.erlang.crypt</c></seeerl>
+ can now be located in the XDG Config Home directory.</p>
+ <p>
+ See the documentation for each file and
+ <c>filename:basedir/2</c> for more details.</p>
+ <p>
+ Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 5.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -270,7 +307,7 @@
<list>
<item>
<p>
- Update build scripts to not make assumtions about where
+ Update build scripts to not make assumptions about where
env, cp and perl are located.</p>
<p>
Own Id: OTP-13800</p>
diff --git a/lib/debugger/priv/Makefile b/lib/debugger/priv/Makefile
index 726d7eb2f3..9f092b1a02 100644
--- a/lib/debugger/priv/Makefile
+++ b/lib/debugger/priv/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ TOOLBAR_FILES = \
# Rules
#
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/debugger/src/Makefile b/lib/debugger/src/Makefile
index 118cb6b758..2fb955b2e3 100644
--- a/lib/debugger/src/Makefile
+++ b/lib/debugger/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -92,7 +92,7 @@ ERL_COMPILE_FLAGS += -Werror
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(TARGET_TOOLBOX_FILES)
+$(TYPES): $(TARGET_FILES) $(TARGET_TOOLBOX_FILES)
clean:
rm -f $(TARGET_FILES) $(TARGET_TOOLBOX_FILES)
diff --git a/lib/debugger/src/dbg_icmd.erl b/lib/debugger/src/dbg_icmd.erl
index 0eb258567f..38f89d0d9e 100644
--- a/lib/debugger/src/dbg_icmd.erl
+++ b/lib/debugger/src/dbg_icmd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -382,19 +382,14 @@ eval_restricted({From,_Mod,Cmd,SP}, Bs) ->
case catch parse_cmd(Cmd, 1) of
{'EXIT', _Reason} ->
From ! {self(), {eval_rsp, 'Parse error'}};
- {[{var,_,Var}], XBs} ->
+ [{var,_,Var}] ->
Bs2 = bindings(Bs, SP),
Res = case get_binding(Var, Bs2) of
{value, Value} -> Value;
- unbound ->
- case get_binding(Var, XBs) of
- {value, _} ->
- 'Only possible to inspect variables';
- unbound -> unbound
- end
+ unbound -> unbound
end,
From ! {self(), {eval_rsp, Res}};
- {_Forms, _XBs} ->
+ _Forms ->
Rsp = 'Only possible to inspect variables',
From ! {self(), {eval_rsp, Rsp}}
end.
@@ -409,18 +404,17 @@ eval_nonrestricted({From, _Mod, Cmd, _SP}, Bs,
{'EXIT', _Reason} ->
From ! {self(), {eval_rsp, 'Parse error'}},
Bs;
- {Forms, XBs} ->
+ Forms ->
mark_running(Line, Le),
- Bs1 = merge_bindings(Bs, XBs),
- {Res, Bs2} =
+ {Res, Bs1} =
lists:foldl(fun(Expr, {_Res, Bs0}) ->
eval_nonrestricted_1(Expr,Bs0,Ieval)
end,
- {null, Bs1},
+ {null, Bs},
Forms),
mark_break(M, Line, Le),
From ! {self(), {eval_rsp, Res}},
- remove_binding_structs(Bs2, XBs)
+ Bs1
end.
eval_nonrestricted_1({match,_,{var,_,Var},Expr}, Bs, Ieval) ->
@@ -445,14 +439,6 @@ eval_expr(Expr, Bs, Ieval) ->
dbg_ieval:eval_expr(Expr, Bs, Ieval#ieval{top=false}),
{Res,Bs2}.
-%% XBs have unique keys.
-merge_bindings(Bs1, XBs) ->
- Bs1 ++ erl_eval:bindings(XBs).
-
-remove_binding_structs(Bs1, XBs) ->
- lists:foldl(fun({N, _V}, Bs) -> lists:keydelete(N, 1, Bs)
- end, Bs1, erl_eval:bindings(XBs)).
-
mark_running(LineNo, Le) ->
put(next_break, running),
put(user_eval, [{LineNo, Le} | get(user_eval)]),
@@ -467,8 +453,8 @@ mark_break(Cm, LineNo, Le) ->
parse_cmd(Cmd, LineNo) ->
{ok,Tokens,_} = erl_scan:string(Cmd, LineNo, [text]),
- {ok,Forms,Bs} = erl_eval:extended_parse_exprs(Tokens),
- {Forms, Bs}.
+ {ok,Forms} = erl_eval:extended_parse_exprs(Tokens),
+ Forms.
%%====================================================================
%% Library functions for attached process handling
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 49a8f6513c..2d736898d8 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -84,7 +84,7 @@ exit_info(Int, AttPid, OrigPid, Reason, ExitInfo) ->
%%--------------------------------------------------------------------
%% eval_expr(Expr, Bs, Ieval) -> {value, Value, Bs}
%%
-%% Evalute a shell expression in the real process.
+%% Evaluate a shell expression in the real process.
%% Called (dbg_icmd) in response to a user request.
%%--------------------------------------------------------------------
eval_expr(Expr0, Bs, Ieval) ->
@@ -266,7 +266,7 @@ meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
end,
do_exception(Class, Reason, MakeStk, Bs, Ieval);
- %% Error must have occured within a re-entry to
+ %% Error must have occurred within a re-entry to
%% interpreted code, simply raise the exception
_ ->
erlang:Class(Reason)
@@ -669,7 +669,7 @@ expr({map,Line,E0,Fs0}, Bs0, Ieval0) ->
%% Record update
expr({record_update,Line,Es},Bs,#ieval{level=Le}=Ieval0) ->
- %% Incr Level, we don't need to step (next) trough temp
+ %% Incr Level, we don't need to step (next) through temp
%% variables creation and matching
Ieval = Ieval0#ieval{top=false, line=Line, level=Le+1},
Seq = fun(E, {_, _, Bs1}) -> expr(E, Bs1, Ieval) end,
@@ -1043,9 +1043,7 @@ expr({bin,Line,Fs}, Bs0, Ieval0) ->
Ieval = Ieval0#ieval{line=Line,top=false},
try
eval_bits:expr_grp(Fs, Bs0,
- fun (E, B) -> expr(E, B, Ieval) end,
- [],
- false)
+ fun (E, B) -> expr(E, B, Ieval) end)
catch
Class:Reason ->
exception(Class, Reason, Bs0, Ieval)
@@ -1504,7 +1502,7 @@ guard_expr({bin,_,Flds}, Bs) ->
fun(E,B) ->
{value,V} = guard_expr(E,B),
{value,V,B}
- end, [], false),
+ end),
{value,V}.
@@ -1583,8 +1581,7 @@ match1({map,_,Fields}, Map, Bs, BBs) when is_map(Map) ->
match1({bin,_,Fs}, B, Bs0, BBs) when is_bitstring(B) ->
try eval_bits:match_bits(Fs, B, Bs0, BBs,
match_fun(BBs),
- fun(E, Bs) -> expr(E, Bs, #ieval{}) end,
- false)
+ fun(E, Bs) -> expr(E, Bs, #ieval{}) end)
catch
_:_ -> throw(nomatch)
end;
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index 888de26620..4649f7cef4 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -901,7 +901,7 @@ record_pattern(_, _, _, _, _, Acc) -> lists:reverse(Acc).
%% The debugger converts both strings "abc" and lists [67, 68, 69]
%% into {value, Line, [67, 68, 69]}, making it impossible to later
-%% distingish one or the other inside binaries when evaluating. To
+%% distinguish one or the other inside binaries when evaluating. To
%% avoid <<[67, 68, 69]>> from evaluating, we convert strings into
%% chars to avoid the ambiguity.
bin_expand_strings(Es) ->
diff --git a/lib/debugger/src/dbg_wx_break_win.erl b/lib/debugger/src/dbg_wx_break_win.erl
index 10e9272254..e521dca57b 100644
--- a/lib/debugger/src/dbg_wx_break_win.erl
+++ b/lib/debugger/src/dbg_wx_break_win.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -214,9 +214,9 @@ handle_event(#wx{id=?wxID_OK},#winInfo{win=Win,text=Text, entries=Es, trigger=Tr
%% Non function box
Mod = wxComboBox:getValue(Text),
Data = check_input(Es),
- Trigged = get_trigger(Trigger),
+ Triggered = get_trigger(Trigger),
wxDialog:destroy(Win),
- {break, [[list_to_atom(Mod)|Data]], Trigged};
+ {break, [[list_to_atom(Mod)|Data]], Triggered};
handle_event(_WxEvent, _WinInfo) ->
%% io:format("Ev: ~p ~n", [_WxEvent]),
diff --git a/lib/debugger/src/dbg_wx_settings.erl b/lib/debugger/src/dbg_wx_settings.erl
index 3a355f18a9..d39d99ed68 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -80,30 +80,35 @@ default_settings_dir(Win) ->
case filelib:is_dir(DefDir) of
true -> DefDir;
false ->
- {ok, CWD} = file:get_cwd(),
-
- 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),
- case filelib:is_dir(ToolsDir) of
- true ->
- case file:make_dir(DefDir) of
- ok -> DefDir;
- _Error -> CWD
- end;
- false ->
- case file:make_dir(ToolsDir) of
- ok ->
- case file:make_dir(DefDir) of
- ok -> DefDir;
- _Error -> CWD
- end;
- _Error -> CWD
- end
- end;
- cancel -> CWD
- end
+ XDGDir = filename:join(filename:basedir(user_config,"erlang"),"debugger"),
+ case filelib:is_dir(XDGDir) of
+ true -> XDGDir;
+ false ->
+ {ok, CWD} = file:get_cwd(),
+
+ Msg = ["Default directory ", XDGDir, " 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(XDGDir),
+ case filelib:is_dir(ToolsDir) of
+ true ->
+ case file:make_dir(XDGDir) of
+ ok -> XDGDir;
+ _Error -> CWD
+ end;
+ false ->
+ case file:make_dir(ToolsDir) of
+ ok ->
+ case file:make_dir(XDGDir) of
+ ok -> XDGDir;
+ _Error -> CWD
+ end;
+ _Error -> CWD
+ end
+ end;
+ cancel -> CWD
+ end
+ end
end.
diff --git a/lib/debugger/src/dbg_wx_view.erl b/lib/debugger/src/dbg_wx_view.erl
index 86d009238f..6ed1f19c31 100644
--- a/lib/debugger/src/dbg_wx_view.erl
+++ b/lib/debugger/src/dbg_wx_view.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@ stop() ->
%% Main loop and message handling
%%====================================================================
+-spec init(term(), term(), term(), term()) -> no_return().
init(GS, Env, Mod, Title) ->
wx:set_env(Env),
%% Subscribe to messages from the interpreter
diff --git a/lib/debugger/src/i.erl b/lib/debugger/src/i.erl
index 853fa529a0..5bab31cc4a 100644
--- a/lib/debugger/src/i.erl
+++ b/lib/debugger/src/i.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -276,7 +276,7 @@ ia(Pid) ->
%% -------------------------------------------
%% Attach to process.
-%% X,Y,Z is combind to a process identity.
+%% X,Y,Z is combined to a process identity.
%% -------------------------------------------
ia(X,Y,Z) ->
diff --git a/lib/debugger/test/Makefile b/lib/debugger/test/Makefile
index 8677180596..015b5f9c29 100644
--- a/lib/debugger/test/Makefile
+++ b/lib/debugger/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2021. All Rights Reserved.
+# Copyright Ericsson AB 1998-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -71,6 +71,7 @@ RELSYSDIR = $(RELEASE_PATH)/debugger_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -84,7 +85,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
>> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/debugger/test/bs_match_int_SUITE.erl b/lib/debugger/test/bs_match_int_SUITE.erl
index 8ff5fe260e..d89bcfd434 100644
--- a/lib/debugger/test/bs_match_int_SUITE.erl
+++ b/lib/debugger/test/bs_match_int_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -263,7 +263,7 @@ match_huge_int(Config) when is_list(Config) ->
8 ->
%% An attempt will be made to allocate heap space for
%% the bignum (which will probably fail); only if the
- %% allocation succeds will the matching fail because
+ %% allocation succeeds will the matching fail because
%% the binary is too small.
ok
end,
diff --git a/lib/debugger/test/dbg_ui_SUITE.erl b/lib/debugger/test/dbg_ui_SUITE.erl
index 32577d48cd..ca66f49f0a 100644
--- a/lib/debugger/test/dbg_ui_SUITE.erl
+++ b/lib/debugger/test/dbg_ui_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -205,13 +205,13 @@ Interpret one module").
?MAN_CASE(finish3, "Finish the current function body",
- "Call the fucntion test:test1() from the shell. Press Finish to evaluate the remaining lines in the function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
+ "Call the function test:test1() from the shell. Press Finish to evaluate the remaining lines in the function. The result printed in the shell should be: {\"peter\",[1,2,4,a,b,c],\"olin\"}").
?MAN_CASE(killinit3,"Set up for killing and clearing processes",
"Call test:test2() from the shell. Set a break point at the last line of test:test2. Click Continue. This should open three new attach windows. One for each spawn called in test:test2/0. ").
?MAN_CASE(killone3, "Kill a process and clear it",
- "In one of the newly openend Attach windows: select Process->Kill. A message should appear above the Code Area in the Attach window. Use Windows->Monitor to verify that the Monitor window also shows that the process has been killed. In the Monitor window: select Edit->Clear. This should do two things: 1) close/remove the window of the killed process. 2) Remove the entry of the killed process from the monitor window.").
+ "In one of the newly opened Attach windows: select Process->Kill. A message should appear above the Code Area in the Attach window. Use Windows->Monitor to verify that the Monitor window also shows that the process has been killed. In the Monitor window: select Edit->Clear. This should do two things: 1) close/remove the window of the killed process. 2) Remove the entry of the killed process from the monitor window.").
?MAN_CASE(killall3,"KIll all processes, and clear them",
"In the Monitor window: Select Edit->Kill All. Verify that all processes have been killed (in their respective windows and in the monitor window). Windows will be raised as their processes die. Next select, Edit->Clear. All attach windows should now be closed. Their entris should also disappear from the monitor window. The shell should have reported: ** exited: killed **").
@@ -250,7 +250,7 @@ Interpret one module").
%% SET 6 (Distribution)
?MAN_CASE(distsetup6,"Set up distribution",
- "Start two erlang systems [foo,bar] (with option -sname), make them aware of eachother using net_adm:ping/1. Start the debugger on foo. Interpret the modules [test, lists1, ordsets1]. Set attach on First call. ").
+ "Start two erlang systems [foo,bar] (with option -sname), make them aware of each other using net_adm:ping/1. Start the debugger on foo. Interpret the modules [test, lists1, ordsets1]. Set attach on First call. ").
diff --git a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl
index 32aabfcbb9..fd041d05e0 100644
--- a/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl
+++ b/lib/debugger/test/dbg_ui_SUITE_data/manual_data/src/lists1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -156,7 +156,7 @@ sublist([H|T], L) when L > 0 ->
sublist(List, L) -> [].
%% delete(Item, List) -> List'
-%% Delete the first occurance of Item from the list L.
+%% Delete the first occurrence of Item from the list L.
delete(Item, [Item|Rest]) -> Rest;
delete(Item, [H|Rest]) ->
@@ -221,7 +221,7 @@ flatten([], [H|Cont], Tail) ->
flatten([], [], Tail) ->
Tail.
-%% flat_length(List) (undocumented can be rmove later)
+%% flat_length(List) (undocumented can be removed later)
%% Calculate the length of a list of lists.
flat_length(List) -> flatlength(List).
diff --git a/lib/debugger/test/exception_SUITE.erl b/lib/debugger/test/exception_SUITE.erl
index dd19fe4b78..2c638cba06 100644
--- a/lib/debugger/test/exception_SUITE.erl
+++ b/lib/debugger/test/exception_SUITE.erl
@@ -179,7 +179,7 @@ pending({Code,[{?MODULE,Func,Arity,_}|_]}, Func, Args, Code)
pending(Reason, _Function, _Args, _Code) ->
ct:fail({bad_exit_reason,Reason}).
-%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash.
+%% Test that doing arithmetic on [] gives a badarith EXIT and not a crash.
nil_arith(Config) when is_list(Config) ->
ba_plus_minus_times([], []),
diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl
index 7eb53e4ce4..f970ed0438 100644
--- a/lib/debugger/test/fun_SUITE.erl
+++ b/lib/debugger/test/fun_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -289,7 +289,7 @@ eep37(Config) when is_list(Config) ->
10 = Add(9),
50 = UnusedName(8),
[1,1,2,6,24,120] = lists:map(F, lists:seq(0, 5)),
- {'EXIT',{{badarity,_},_}} = (catch lists:map(fun G() -> G() end, [1])),
+ {'EXIT',{function_clause,_}} = (catch lists:map(fun G() -> G() end, [1])),
{'EXIT',{{badarity,_},_}} = (catch F()),
ok.
diff --git a/lib/debugger/test/guard_SUITE.erl b/lib/debugger/test/guard_SUITE.erl
index 02a1bbd66b..f677dc8dc0 100644
--- a/lib/debugger/test/guard_SUITE.erl
+++ b/lib/debugger/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -203,7 +203,7 @@ guard_bifs(Config) when list(Config) ->
Big = -237849247829874297658726487367328971246284736473821617265433,
Float = 387924.874,
- %% Succeding use of guard bifs.
+ %% Succeeding use of guard bifs.
try_gbif('abs/1', Big, -Big),
try_gbif('float/1', Big, float(Big)),
@@ -1436,7 +1436,7 @@ traverse_dcd(Config) when is_list(Config) ->
%% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}.
%% The outer match of a two tuple will places the first element in {x,3} and
%% second in {x,4}. The guard for the first clause must make ensure that all of those
-%% registers are restored befor entering the second clause.
+%% registers are restored before entering the second clause.
%%
%% (From mnesia_checkpoint.erl, modified.)
diff --git a/lib/debugger/test/int_SUITE_data/lists1.erl b/lib/debugger/test/int_SUITE_data/lists1.erl
index 32aabfcbb9..fd041d05e0 100644
--- a/lib/debugger/test/int_SUITE_data/lists1.erl
+++ b/lib/debugger/test/int_SUITE_data/lists1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -156,7 +156,7 @@ sublist([H|T], L) when L > 0 ->
sublist(List, L) -> [].
%% delete(Item, List) -> List'
-%% Delete the first occurance of Item from the list L.
+%% Delete the first occurrence of Item from the list L.
delete(Item, [Item|Rest]) -> Rest;
delete(Item, [H|Rest]) ->
@@ -221,7 +221,7 @@ flatten([], [H|Cont], Tail) ->
flatten([], [], Tail) ->
Tail.
-%% flat_length(List) (undocumented can be rmove later)
+%% flat_length(List) (undocumented can be removed later)
%% Calculate the length of a list of lists.
flat_length(List) -> flatlength(List).
diff --git a/lib/debugger/test/int_SUITE_data/my_lists.erl b/lib/debugger/test/int_SUITE_data/my_lists.erl
index dade8e824c..3c7f767982 100644
--- a/lib/debugger/test/int_SUITE_data/my_lists.erl
+++ b/lib/debugger/test/int_SUITE_data/my_lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -157,7 +157,7 @@ sublist([H|T], L) when L > 0 ->
sublist(List, L) -> [].
%% delete(Item, List) -> List'
-%% Delete the first occurance of Item from the list L.
+%% Delete the first occurrence of Item from the list L.
delete(Item, [Item|Rest]) -> Rest;
delete(Item, [H|Rest]) ->
@@ -222,7 +222,7 @@ flatten([], [H|Cont], Tail) ->
flatten([], [], Tail) ->
Tail.
-%% flat_length(List) (undocumented can be rmove later)
+%% flat_length(List) (undocumented can be removed later)
%% Calculate the length of a list of lists.
flat_length(List) -> flatlength(List).
@@ -618,7 +618,7 @@ sublist_1([H|T], L) when L > 0 ->
sublist_1(List, L) -> [].
%% delete(Item, List) -> List'
-%% Delete the first occurance of Item from the list L.
+%% Delete the first occurrence of Item from the list L.
delete_1(Item, [Item|Rest]) -> Rest;
delete_1(Item, [H|Rest]) ->
@@ -683,7 +683,7 @@ flatten_1([], [H|Cont], Tail) ->
flatten_1([], [], Tail) ->
Tail.
-%% flat_length(List) (undocumented can be rmove later)
+%% flat_length(List) (undocumented can be removed later)
%% Calculate the length of a list of lists.
flat_length_1(List) -> flatlength_1(List).
@@ -1082,7 +1082,7 @@ sublist_2([H|T], L) when L > 0 ->
sublist_2(List, L) -> [].
%% delete_2(Item, List) -> List'
-%% Delete the first occurance of Item from the list L.
+%% Delete the first occurrence of Item from the list L.
delete_2(Item, [Item|Rest]) -> Rest;
delete_2(Item, [H|Rest]) ->
@@ -1147,7 +1147,7 @@ flatten_2([], [H|Cont], Tail) ->
flatten_2([], [], Tail) ->
Tail.
-%% flat_length_2(List) _2(undocumented can be rmove later)
+%% flat_length_2(List) _2(undocumented can be removed later)
%% Calculate the length of a list of lists.
flat_length_2(List) -> flatlength_2(List).
@@ -1544,7 +1544,7 @@ sublist_3([H|T], L) when L > 0 ->
sublist_3(List, L) -> [].
%% delete_3(Item, List) -> List'
-%% Delete the first occurance of Item from the list L.
+%% Delete the first occurrence of Item from the list L.
delete_3(Item, [Item|Rest]) -> Rest;
delete_3(Item, [H|Rest]) ->
@@ -1609,7 +1609,7 @@ flatten_3([], [H|Cont], Tail) ->
flatten_3([], [], Tail) ->
Tail.
-%% flat_length_3(List) _3(undocumented can be rmove later)
+%% flat_length_3(List) _3(undocumented can be removed later)
%% Calculate the length of a list of lists.
flat_length_3(List) -> flatlength_3(List).
diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl
index e564316516..6ec3fb0df7 100644
--- a/lib/debugger/test/int_eval_SUITE.erl
+++ b/lib/debugger/test/int_eval_SUITE.erl
@@ -89,7 +89,7 @@ bifs_outside_erlang(Config) when is_list(Config) ->
ok = spawn_eval(Fun),
ok.
-%% Try evalutate spawn_link/3.
+%% Try evaluating spawn_link/3.
spawning(Config) when is_list(Config) ->
ok = spawn_eval(fun() -> ?IM:spawn_test() end).
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 1033aa9934..82a742b58b 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
@@ -118,7 +118,7 @@ external_call_test(Data) ->
{yes,Data} = i_am_exported(Data),
{yes,Data} = ?MODULE:i_am_exported(Data),
- %% Excercise the function cache in the interpreter.
+ %% Exercise the function cache in the interpreter.
{ok,Data,[a,b]} = not_exported(Data, [a,b]),
{yes,Data} = i_am_exported(Data),
diff --git a/lib/debugger/test/trycatch_SUITE.erl b/lib/debugger/test/trycatch_SUITE.erl
index 2857cac9a3..c3d7e03b3b 100644
--- a/lib/debugger/test/trycatch_SUITE.erl
+++ b/lib/debugger/test/trycatch_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -120,7 +120,7 @@ basic(Conf) when is_list(Conf) ->
%% Try/of
ok = try V of
{a,variable} -> ok
- catch nisse -> erro
+ catch nisse -> error
end,
ok.
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index c95d0fda17..e98a61d2b3 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 5.2.1
+DEBUGGER_VSN = 5.3.1
diff --git a/lib/dialyzer/RELEASE_NOTES b/lib/dialyzer/RELEASE_NOTES
index 299cc8642f..909cada009 100644
--- a/lib/dialyzer/RELEASE_NOTES
+++ b/lib/dialyzer/RELEASE_NOTES
@@ -257,7 +257,7 @@ Version 1.5.1 (in Erlang/OTP R11B-3)
Version 1.5.0 (in Erlang/OTP R11B-2)
------------------------------------
- Dialyzer's building of PLT is based on a different type inference algorithm.
- More specifically, Dialyzer uses inferrence of refined success typings to
+ More specifically, Dialyzer uses inference of refined success typings to
infer function prototypes. As a result, Dialyzer bases its analysis on a
significantly more powerful basis and thus is able to detect more
discrepancies. The downside is that building the PLT is a considerably
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 3a0463a2b4..63a6fb8aca 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2021</year>
+ <year>2006</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -185,6 +185,11 @@ dialyzer --apps inets ssl ./ebin ../other_lib/ebin/my_module.beam</code>
<p>When analyzing from source, pass the <c>include_dir</c>
to Dialyzer. (**)</p>
</item>
+ <tag><c>--input_list_file file</c></tag>
+ <item>
+ <p>Analyze the file names that are listed in the specified file
+ (one file name per line).</p>
+ </item>
<tag><c>--no_check_plt</c></tag>
<item>
<p>Skip the PLT check when running Dialyzer. This is useful when
@@ -316,6 +321,16 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
<item>
<p>Include warnings for functions that only return by an exception.</p>
</item>
+ <tag><c>-Wextra_return</c> (***)</tag>
+ <item>
+ <p>Warn about functions whose specification includes types that the
+ function cannot return.</p>
+ </item>
+ <tag><c>-Wmissing_return</c> (***)</tag>
+ <item>
+ <p>Warn about functions that return values that are not part of the
+ specification.</p>
+ </item>
<tag><c>-Wno_behaviours</c></tag>
<item>
<p>Suppress warnings about behavior callbacks that drift from the
@@ -362,13 +377,6 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
<item>
<p>Suppress warnings for unused functions.</p>
</item>
- <tag><c>-Wrace_conditions</c> (***)</tag>
- <item>
- <p>Include warnings for possible race conditions. Notice that the
- analysis that finds data races performs intra-procedural data flow
- analysis and can sometimes explode in time. Enable it at your own
- risk.</p>
- </item>
<tag><c>-Wunderspecs</c> (***)</tag>
<item>
<p>Warn about underspecified functions (the specification is strictly
@@ -427,6 +435,16 @@ dialyzer --plts plt_1 ... plt_n -- files_to_analyze</code>
specification is strictly more allowing than the success typing).
</p>
</item>
+ <tag><c>-Wno_extra_return</c></tag>
+ <item>
+ <p>Suppress warnings about functions whose specification includes types
+ that the function cannot return.</p>
+ </item>
+ <tag><c>-Wno_missing_return</c></tag>
+ <item>
+ <p>Suppress warnings about functions that return values that are not
+ part of the specification.</p>
+ </item>
</taglist>
</section>
diff --git a/lib/dialyzer/doc/src/dialyzer_chapter.xml b/lib/dialyzer/doc/src/dialyzer_chapter.xml
index d83943a42b..8f0abe3403 100644
--- a/lib/dialyzer/doc/src/dialyzer_chapter.xml
+++ b/lib/dialyzer/doc/src/dialyzer_chapter.xml
@@ -68,9 +68,11 @@ dialyzer --build_plt --apps erts kernel stdlib mnesia</code>
<p>Dialyzer looks if there is an environment variable called
<c>DIALYZER_PLT</c> and places the PLT at this location. If no such
- variable is set, Dialyzer places the PLT at
- <c>$HOME/.dialyzer_plt</c>. The placement can also be specified using
- the options <c>--plt</c> or <c>--output_plt</c>.</p>
+ variable is set, Dialyzer places the PLT in a file called .dialyzer_plt
+ in the <seeerl marker="stdlib:filename#user_cache">
+ <c>filename:basedir(user_cache, "erlang")</c></seeerl> folder.
+ The placement can also be specified using the options
+ <c>--plt</c> or <c>--output_plt</c>.</p>
<p>Information can be added to an existing PLT using option
<c>--add_to_plt</c>. If you also want to include the Erlang compiler in
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 6a40990d7d..fe859092f7 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2021</year>
+ <year>2006</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,251 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 5.0.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that would cause analysis to crash.</p>
+ <p>
+ Own Id: OTP-18372 Aux Id: GH-6580 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 5.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Dialyzer would crash when attempting to analyze a bit
+ syntax segment size having an literal non-integer size
+ such as <c>[]</c>.</p>
+ <p>
+ Own Id: OTP-18307 Aux Id: GH-6419, GH-6473 </p>
+ </item>
+ <item>
+ <p>Dialyzer could crash when trying to analyze a
+ convoluted nested expression involving funs,</p>
+ <p>
+ Own Id: OTP-18347 Aux Id: GH-6518, PR-6525 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 5.0.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Dialyzer could crash when analyzing Elixir code that
+ used intricate macros.</p>
+ <p>
+ Own Id: OTP-18262 Aux Id: GH-6323 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The <c>--input_list_file</c> option has been
+ added.</p>
+ <p>
+ Own Id: OTP-18263 Aux Id: ERIERL-821 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 5.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Two bugs have been fixed in Dialyzer's checking of
+ behaviors:</p>
+ <p>When a <em>mandatory</em> callback function is present
+ but not exported, Dialyzer would not complain about a
+ missing callback.</p>
+ <p>When an <em>optional</em> callback function was not
+ exported and had incompatible arguments and/or the return
+ values were incompatible, Dialyzer would complain. This
+ has been changed to suppress the warning, because the
+ function might not be intended to be a callback function,
+ for instance if a release added a new optional callback
+ function (such as <c>format_status/1</c> for the
+ gen_server behaviour added in OTP 25).</p>
+ <p>
+ Own Id: OTP-18127 Aux Id: ERIERL-817 </p>
+ </item>
+ <item>
+ <p>The <c>no_extra_return</c> and
+ <c>no_missing_return</c> warnings can now be suppressed
+ through <c>-dialyzer</c> directives in source code.</p>
+ <p>
+ Own Id: OTP-18148 Aux Id: PR-6068 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 5.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed the documentation for the <c>missing_return</c>
+ and <c>extra_return</c> options.</p>
+ <p>
+ Own Id: OTP-18120</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 5.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that could cause the type analyzer to
+ enter an infinite loop.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17644 Aux Id: PR-5223 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimize operations in the <c>erl_types</c> module.
+ Parallelize the Dialyzer pass <c>remote</c>.</p>
+ <p>
+ Own Id: OTP-17524</p>
+ </item>
+ <item>
+ <p>Added the <c>missing_return</c> and
+ <c>extra_return</c> options to raise warnings when
+ specifications differ from inferred types. These are
+ similar to, but not quite as verbose as <c>overspecs</c>
+ and <c>underspecs</c>.</p>
+ <p>
+ Own Id: OTP-17654 Aux Id: GH-5214 </p>
+ </item>
+ <item>
+ <p>The <c>race_conditions</c> option has been
+ removed.</p>
+ <p>
+ Own Id: OTP-17819</p>
+ </item>
+ <item>
+ <p>
+ The default location of the plt has been changed from
+ <c>$HOME</c> to
+ <c>filename:basedir(user_cache,"erlang")</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17821 Aux Id: GH-5016 PR-5408 OTP-17554 </p>
+ </item>
+ <item>
+ <p><c>dialyzer</c> will now honor dependencies inside
+ type declarations. That is, if the declaration of an
+ exported type changes, all modules using said type will
+ be revisited.</p>
+ <p>
+ Own Id: OTP-17826 Aux Id: PR-5498 </p>
+ </item>
+ <item>
+ <p>Dialyzer now better understands the types for
+ <c>min/2</c>, <c>max/2</c>, and <c>erlang:raise/3</c>.
+ Because of that, Dialyzer can potentially generate new
+ warnings. In particular, functions that use
+ <c>erlang:raise/3</c> could now need a spec with a
+ <c>no_return()</c> return type to avoid an unwanted
+ warning.</p>
+ <p>
+ Own Id: OTP-17897 Aux Id: PR-5651 </p>
+ </item>
+ <item>
+ <p>The <c>typer_core</c> module has been added to provide
+ an Erlang API for running <c>typer</c>.</p>
+ <p>
+ Own Id: OTP-17964 Aux Id: PR-5660 </p>
+ </item>
+ <item>
+ <p>Added the <c>--annotate-in-place</c> option to
+ <c>typer</c>, which can be used to annotate the specs
+ that the tool inferred directly into the source code
+ files.</p>
+ <p>
+ Own Id: OTP-18035 Aux Id: PR-5802 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Dialyzer 4.4.4.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The <c>--input_list_file</c> option has been
+ added.</p>
+ <p>
+ Own Id: OTP-18263 Aux Id: ERIERL-821 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 4.4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -189,6 +434,21 @@
</section>
+<section><title>Dialyzer 4.3.1.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The <c>--input_list_file</c> option has been
+ added.</p>
+ <p>
+ Own Id: OTP-18263 Aux Id: ERIERL-821 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 4.3.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/doc/src/typer_cmd.xml b/lib/dialyzer/doc/src/typer_cmd.xml
index cfeba9e456..b0aada576d 100644
--- a/lib/dialyzer/doc/src/typer_cmd.xml
+++ b/lib/dialyzer/doc/src/typer_cmd.xml
@@ -4,7 +4,7 @@
<comref>
<header>
<copyright>
- <year>2006</year><year>2021</year>
+ <year>2006</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -52,9 +52,9 @@ typer --help</code>
<code type="none">
typer [--help] [--version] [--plt PLT] [--edoc]
- [--show | --show-exported | --annotate | --annotate-inc-files]
+ [--show | --show-exported | --annotate | --annotate-inc-files | --annotate-in-place]
[-Ddefine]* [-I include_dir]* [-pa dir]* [-pz dir]*
- [-T application]* [-r] file*</code>
+ [-T application]* file* [-r directory*]</code>
<note>
<p>* denotes that multiple occurrences of the option are possible.</p>
@@ -66,7 +66,7 @@ typer [--help] [--version] [--plt PLT] [--edoc]
<tag><c>-r</c></tag>
<item>
- <p>Search directories recursively for .erl files below them.</p>
+ <p>Search directories recursively for .erl files below them. If a list of files is given, this must be after them.</p>
</item>
<tag><c>--show</c></tag>
<item>
@@ -94,6 +94,13 @@ typer [--help] [--version] [--plt PLT] [--edoc]
option with caution - it has not been tested much).</p>
</item>
+ <tag><c>--annotate-in-place</c></tag>
+ <item>
+ <p>Annotate directly on the source code files, instead of dumping the
+ annotated files in a different directory (use this option with
+ caution - has not been tested much)</p>
+ </item>
+
<tag><c>--edoc</c></tag>
<item>
<p>Print type information as Edoc <c>@spec</c> comments, not
diff --git a/lib/dialyzer/src/Makefile b/lib/dialyzer/src/Makefile
index 5f2c24c3c0..c934ecdc2b 100644
--- a/lib/dialyzer/src/Makefile
+++ b/lib/dialyzer/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2021. All Rights Reserved.
+# Copyright Ericsson AB 2006-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -47,11 +47,7 @@ DIALYZER_DIR = $(ERL_TOP)/lib/dialyzer
# Target Specs
# ----------------------------------------------------
MODULES = \
- cerl_closurean \
- cerl_lib \
- cerl_pmatch \
cerl_prettypr \
- cerl_typean \
dialyzer \
dialyzer_analysis_callgraph \
dialyzer_behaviours \
@@ -68,17 +64,17 @@ MODULES = \
dialyzer_gui_wx \
dialyzer_options \
dialyzer_plt \
- dialyzer_race_data_server \
- dialyzer_races \
dialyzer_succ_typings \
dialyzer_timing \
dialyzer_typesig \
+ dialyzer_typegraph \
dialyzer_coordinator \
dialyzer_worker \
dialyzer_utils \
erl_bif_types \
erl_types \
- typer
+ typer \
+ typer_core
HRL_FILES= dialyzer.hrl dialyzer_gui_wx.hrl
ERL_FILES= $(MODULES:%=%.erl)
@@ -104,7 +100,7 @@ ERL_COMPILE_FLAGS += +warn_export_vars +warn_unused_import +warn_missing_spec
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
docs:
@@ -156,6 +152,7 @@ $(EBIN)/dialyzer_race_data_server.beam: dialyzer.hrl
$(EBIN)/dialyzer_races.beam: dialyzer.hrl
$(EBIN)/dialyzer_succ_typings.beam: dialyzer.hrl
$(EBIN)/dialyzer_typesig.beam: dialyzer.hrl
+$(EBIN)/dialyzer_typegraph.beam: dialyzer.hrl
$(EBIN)/dialyzer_utils.beam: dialyzer.hrl
# ----------------------------------------------------
diff --git a/lib/dialyzer/src/cerl_closurean.erl b/lib/dialyzer/src/cerl_closurean.erl
deleted file mode 100644
index 55dcfeed1d..0000000000
--- a/lib/dialyzer/src/cerl_closurean.erl
+++ /dev/null
@@ -1,856 +0,0 @@
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% @copyright 2001-2002 Richard Carlsson
-%% @author Richard Carlsson <carlsson.richard@gmail.com>
-%% @doc Closure analysis of Core Erlang programs.
-
-%% TODO: might need a "top" (`any') element for any-length value lists.
-
--module(cerl_closurean).
-
--export([analyze/1, annotate/1]).
-%% The following functions are exported from this module since they
-%% are also used by Dialyzer (file dialyzer/src/dialyzer_dep.erl)
--export([is_escape_op/2, is_escape_op/3, is_literal_op/2, is_literal_op/3]).
-
--import(cerl, [ann_c_apply/3, ann_c_fun/3, ann_c_var/2, apply_args/1,
- apply_op/1, atom_val/1, bitstr_size/1, bitstr_val/1,
- binary_segments/1, c_letrec/2, c_seq/2, c_tuple/1,
- c_nil/0, call_args/1, call_module/1, call_name/1,
- case_arg/1, case_clauses/1, catch_body/1, clause_body/1,
- clause_guard/1, clause_pats/1, cons_hd/1, cons_tl/1,
- fun_body/1, fun_vars/1, get_ann/1, is_c_atom/1,
- let_arg/1, let_body/1, let_vars/1, letrec_body/1,
- letrec_defs/1, module_defs/1, module_defs/1,
- module_exports/1, pat_vars/1, primop_args/1,
- primop_name/1, receive_action/1, receive_clauses/1,
- receive_timeout/1, seq_arg/1, seq_body/1, set_ann/2,
- try_arg/1, try_body/1, try_vars/1, try_evars/1,
- try_handler/1, tuple_es/1, type/1, values_es/1]).
-
--import(cerl_trees, [get_label/1]).
-
-%% ===========================================================================
-
--type label() :: integer() | 'top' | 'external' | 'external_call'.
--type ordset(X) :: [X]. % XXX: TAKE ME OUT
--type labelset() :: ordset(label()).
--type outlist() :: [labelset()] | 'none'.
--type escapes() :: labelset().
-
-%% ===========================================================================
-%% annotate(Tree) -> {Tree1, OutList, Outputs, Escapes, Dependencies, Parents}
-%%
-%% Tree = cerl:cerl()
-%%
-%% Analyzes `Tree' (see `analyze') and appends terms `{callers,
-%% Labels}' and `{calls, Labels}' to the annotation list of each
-%% fun-expression node and apply-expression node of `Tree',
-%% respectively, where `Labels' is an ordered-set list of labels of
-%% fun-expressions in `Tree', possibly also containing the atom
-%% `external', corresponding to the dependency information derived
-%% by the analysis. Any previous such annotations are removed from
-%% `Tree'. `Tree1' is the modified tree; for details on `OutList',
-%% `Outputs' , `Dependencies', `Escapes' and `Parents', see
-%% `analyze'.
-%%
-%% Note: `Tree' must be annotated with labels in order to use this
-%% function; see `analyze' for details.
-
--spec annotate(cerl:cerl()) ->
- {cerl:cerl(), outlist(), dict:dict(),
- escapes(), dict:dict(), dict:dict()}.
-
-annotate(Tree) ->
- {Xs, Out, Esc, Deps, Par} = analyze(Tree),
- F = fun (T) ->
- case type(T) of
- 'fun' ->
- L = get_label(T),
- X = case dict:find(L, Deps) of
- {ok, X1} -> X1;
- error -> set__new()
- end,
- set_ann(T, append_ann(callers,
- set__to_list(X),
- get_ann(T)));
- apply ->
- L = get_label(T),
- X = case dict:find(L, Deps) of
- {ok, X1} -> X1;
- error -> set__new()
- end,
- set_ann(T, append_ann(calls,
- set__to_list(X),
- get_ann(T)));
- _ ->
-%%% set_ann(T, []) % debug
- T
- end
- end,
- {cerl_trees:map(F, Tree), Xs, Out, Esc, Deps, Par}.
-
-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}].
-
-%% =====================================================================
-%% analyze(Tree) -> {OutList, Outputs, Escapes, Dependencies, Parents}
-%%
-%% Tree = cerl()
-%% OutList = [LabelSet] | none
-%% Outputs = dict(Label, OutList)
-%% Escapes = LabelSet
-%% Dependencies = dict(Label, LabelSet)
-%% LabelSet = ordset(Label)
-%% Label = integer() | top | external | external_call
-%% Parents = dict(Label, Label)
-%%
-%% Analyzes a module or an expression represented by `Tree'.
-%%
-%% The returned `OutList' is a list of sets of labels of
-%% fun-expressions which correspond to the possible closures in the
-%% value list produced by `Tree' (viewed as an expression; the
-%% "value" of a module contains its exported functions). The atom
-%% `none' denotes missing or conflicting information.
-%%
-%% The atom `external' in any label set denotes any possible
-%% function outside `Tree', including those in `Escapes'. The atom
-%% `top' denotes the top-level expression `Tree'.
-%%
-%% `Outputs' is a mapping from the labels of fun-expressions in
-%% `Tree' to corresponding lists of sets of labels of
-%% fun-expressions (or the atom `none'), representing the possible
-%% closures in the value lists returned by the respective
-%% functions.
-%%
-%% `Dependencies' is a similar mapping from the labels of
-%% fun-expressions and apply-expressions in `Tree' to sets of
-%% labels of corresponding fun-expressions which may contain call
-%% sites of the functions or be called from the call sites,
-%% respectively. Any such label not defined in `Dependencies'
-%% represents an unreachable function or a dead or faulty
-%% application.
-%%
-%% `Escapes' is the set of labels of fun-expressions in `Tree' such
-%% that corresponding closures may be accessed from outside `Tree'.
-%%
-%% `Parents' is a mapping from labels of fun-expressions in `Tree'
-%% to the corresponding label of the nearest containing
-%% fun-expression or top-level expression. This can be used to
-%% extend the dependency graph, for certain analyses.
-%%
-%% Note: `Tree' must be annotated with labels (as done by the
-%% function `cerl_trees:label/1') in order to use this function.
-%% The label annotation `{label, L}' (where L should be an integer)
-%% must be the first element of the annotation list of each node in
-%% the tree. Instances of variables bound in `Tree' which denote
-%% the same variable must have the same label; apart from this,
-%% labels should be unique. Constant literals do not need to be
-%% labeled.
-
--record(state, {vars, out, dep, work, funs, par}).
-
-%% Note: In order to keep our domain simple, we assume that all remote
-%% calls and primops return a single value, if any.
-
-%% We use the terms `closure', `label', `lambda' and `fun-expression'
-%% interchangeably. The exact meaning in each case can be grasped from
-%% the context.
-%%
-%% Rules:
-%% 1) The implicit top level lambda escapes.
-%% 2) A lambda returned by an escaped lambda also escapes.
-%% 3) An escaped lambda can be passed an external lambda as argument.
-%% 4) A lambda passed as argument to an external lambda also escapes.
-%% 5) An argument passed to an unknown operation escapes.
-%% 6) A call to an unknown operation can return an external lambda.
-%%
-%% Escaped lambdas become part of the set of external lambdas, but this
-%% does not need to be represented explicitly.
-
-%% We wrap the given syntax tree T in a fun-expression labeled `top',
-%% which is initially in the set of escaped labels. `top' will be
-%% visited at least once.
-%%
-%% We create a separate function labeled `external', defined as:
-%% "'external'/1 = fun (Escape) -> do apply 'external'/1(apply Escape())
-%% 'external'/1", which will represent any and all functions outside T,
-%% and which returns itself, and contains a recursive call; this models
-%% rules 2 and 4 above. It will be revisited if the set of escaped
-%% labels changes, or at least once. Its parameter `Escape' is a
-%% variable labeled `escape', which will hold the set of escaped labels.
-%% initially it contains `top' and `external'.
-
--spec analyze(cerl:cerl()) ->
- {outlist(), dict:dict(), escapes(), dict:dict(), dict:dict()}.
-
-analyze(Tree) ->
- %% Note that we use different name spaces for variable labels and
- %% function/call site labels, so we can reuse some names here. We
- %% assume that the labeling of Tree only uses integers, not atoms.
- External = ann_c_var([{label, external}], {external, 1}),
- Escape = ann_c_var([{label, escape}], 'Escape'),
- ExtBody = c_seq(ann_c_apply([{label, loop}], External,
- [ann_c_apply([{label, external_call}],
- Escape, [])]),
- External),
- ExtFun = ann_c_fun([{label, external}], [Escape], ExtBody),
-%%% io:fwrite("external fun:\n~s.\n",
-%%% [cerl_prettypr:format(ExtFun, [noann])]),
- Top = ann_c_var([{label, top}], {top, 0}),
- TopFun = ann_c_fun([{label, top}], [], Tree),
-
- %% The "start fun" just makes the initialisation easier. It will not
- %% be marked as escaped, and thus cannot be called.
- StartFun = ann_c_fun([{label, start}], [],
- c_letrec([{External, ExtFun}, {Top, TopFun}],
- c_nil())),
-%%% io:fwrite("start fun:\n~s.\n",
-%%% [cerl_prettypr:format(StartFun, [noann])]),
-
- %% Gather a database of all fun-expressions in Tree and initialise
- %% all their outputs and parameter variables. Bind all module- and
- %% letrec-defined variables to their corresponding labels.
- Funs0 = dict:new(),
- Vars0 = dict:new(),
- Out0 = dict:new(),
- Empty = empty(),
- F = fun (T, S = {Fs, Vs, Os}) ->
- case type(T) of
- 'fun' ->
- L = get_label(T),
- As = fun_vars(T),
- {dict:store(L, T, Fs),
- bind_vars_single(As, Empty, Vs),
- dict:store(L, none, Os)};
- letrec ->
- {Fs, bind_defs(letrec_defs(T), Vs), Os};
- module ->
- {Fs, bind_defs(module_defs(T), Vs), Os};
- _ ->
- S
- end
- end,
- {Funs, Vars, Out} = cerl_trees:fold(F, {Funs0, Vars0, Out0},
- StartFun),
-
- %% Initialise Escape to the minimal set of escaped labels.
- Vars1 = dict:store(escape, from_label_list([top, external]), Vars),
-
- %% Enter the fixpoint iteration at the StartFun.
- St = loop(StartFun, start, #state{vars = Vars1,
- out = Out,
- dep = dict:new(),
- work = init_work(),
- funs = Funs,
- par = dict:new()}),
-%%% io:fwrite("dependencies: ~p.\n",
-%%% [[{X, set__to_list(Y)}
-%%% || {X, Y} <- dict:to_list(St#state.dep)]]),
- {dict:fetch(top, St#state.out),
- tidy_dict([start, top, external], St#state.out),
- dict:fetch(escape, St#state.vars),
- tidy_dict([loop], St#state.dep),
- St#state.par}.
-
-tidy_dict([X | Xs], D) ->
- tidy_dict(Xs, dict:erase(X, D));
-tidy_dict([], D) ->
- D.
-
-loop(T, L, St0) ->
-%%% io:fwrite("analyzing: ~w.\n", [L]),
-%%% io:fwrite("work: ~w.\n", [St0#state.work]),
- Xs0 = dict:fetch(L, St0#state.out),
- {Xs, St1} = visit(fun_body(T), L, St0),
- {W, M} = case equal(Xs0, Xs) of
- true ->
- {St1#state.work, St1#state.out};
- false ->
-%%% io:fwrite("out (~w) changed: ~w <- ~w.\n",
-%%% [L, Xs, Xs0]),
- M1 = dict:store(L, Xs, St1#state.out),
- case dict:find(L, St1#state.dep) of
- {ok, S} ->
- {add_work(set__to_list(S), St1#state.work),
- M1};
- error ->
- {St1#state.work, M1}
- end
- end,
- St2 = St1#state{out = M},
- case take_work(W) of
- {ok, L1, W1} ->
- T1 = dict:fetch(L1, St2#state.funs),
- loop(T1, L1, St2#state{work = W1});
- none ->
- St2
- end.
-
-visit(T, L, St) ->
- case type(T) of
- literal ->
- {[empty()], St};
- var ->
- %% If a variable is not already in the store here, we
- %% initialize it to empty().
- L1 = get_label(T),
- Vars = St#state.vars,
- case dict:find(L1, Vars) of
- {ok, X} ->
- {[X], St};
- error ->
- X = empty(),
- St1 = St#state{vars = dict:store(L1, X, Vars)},
- {[X], St1}
- end;
- 'fun' ->
- %% Must revisit the fun also, because its environment might
- %% have changed. (We don't keep track of such dependencies.)
- L1 = get_label(T),
- St1 = St#state{work = add_work([L1], St#state.work),
- par = set_parent([L1], L, St#state.par)},
- {[singleton(L1)], St1};
- values ->
- visit_list(values_es(T), L, St);
- cons ->
- {Xs, St1} = visit_list([cons_hd(T), cons_tl(T)], L, St),
- {[join_single_list(Xs)], St1};
- tuple ->
- {Xs, St1} = visit_list(tuple_es(T), L, St),
- {[join_single_list(Xs)], St1};
- 'let' ->
- {Xs, St1} = visit(let_arg(T), L, St),
- Vars = bind_vars(let_vars(T), Xs, St1#state.vars),
- visit(let_body(T), L, St1#state{vars = Vars});
- seq ->
- {_, St1} = visit(seq_arg(T), L, St),
- visit(seq_body(T), L, St1);
- apply ->
- {Xs, St1} = visit(apply_op(T), L, St),
- {As, St2} = visit_list(apply_args(T), L, St1),
- case Xs of
- [X] ->
- %% We store the dependency from the call site to the
- %% called functions
- Ls = set__to_list(X),
- Out = St2#state.out,
- Xs1 = join_list([dict:fetch(Lx, Out) || Lx <- Ls]),
- St3 = call_site(Ls, L, As, St2),
- L1 = get_label(T),
- D = dict:store(L1, X, St3#state.dep),
- {Xs1, St3#state{dep = D}};
- none ->
- {none, St2}
- end;
- call ->
- M = call_module(T),
- F = call_name(T),
- {_, St1} = visit(M, L, St),
- {_, St2} = visit(F, L, St1),
- {Xs, St3} = visit_list(call_args(T), L, St2),
- remote_call(M, F, Xs, St3);
- primop ->
- As = primop_args(T),
- {Xs, St1} = visit_list(As, L, St),
- primop_call(atom_val(primop_name(T)), length(Xs), Xs, St1);
- 'case' ->
- {Xs, St1} = visit(case_arg(T), L, St),
- visit_clauses(Xs, case_clauses(T), L, St1);
- 'receive' ->
- X = singleton(external),
- {Xs1, St1} = visit_clauses([X], receive_clauses(T), L, St),
- {_, St2} = visit(receive_timeout(T), L, St1),
- {Xs2, St3} = visit(receive_action(T), L, St2),
- {join(Xs1, Xs2), St3};
- 'try' ->
- {Xs1, St1} = visit(try_arg(T), L, St),
- X = singleton(external),
- Vars = bind_vars(try_vars(T), [X], St1#state.vars),
- {Xs2, St2} = visit(try_body(T), L, St1#state{vars = Vars}),
- Evars = bind_vars(try_evars(T), [X, X, X], St2#state.vars),
- {Xs3, St3} = visit(try_handler(T), L, St2#state{vars = Evars}),
- {join(join(Xs1, Xs2), Xs3), St3};
- 'catch' ->
- {_, St1} = visit(catch_body(T), L, St),
- {[singleton(external)], St1};
- binary ->
- {_, St1} = visit_list(binary_segments(T), L, St),
- {[empty()], St1};
- bitstr ->
- %% The other fields are constant literals.
- {_, St1} = visit(bitstr_val(T), L, St),
- {_, St2} = visit(bitstr_size(T), L, St1),
- {none, St2};
- letrec ->
- %% All the bound funs should be revisited, because the
- %% environment might have changed.
- Ls = [get_label(F) || {_, F} <- letrec_defs(T)],
- St1 = St#state{work = add_work(Ls, St#state.work),
- par = set_parent(Ls, L, St#state.par)},
- visit(letrec_body(T), L, St1);
- module ->
- %% All the exported functions escape, and can thus be passed
- %% any external closures as arguments. We regard a module as
- %% a tuple of function variables in the body of a `letrec'.
- visit(c_letrec(module_defs(T), c_tuple(module_exports(T))),
- L, St)
- end.
-
-visit_clause(T, Xs, L, St) ->
- Vars = bind_pats(clause_pats(T), Xs, St#state.vars),
- {_, St1} = visit(clause_guard(T), L, St#state{vars = Vars}),
- visit(clause_body(T), L, St1).
-
-%% We assume correct value-list typing.
-
-visit_list([T | Ts], L, St) ->
- {Xs, St1} = visit(T, L, St),
- {Xs1, St2} = visit_list(Ts, L, St1),
- X = case Xs of
- [X1] -> X1;
- none -> none
- end,
- {[X | Xs1], St2};
-visit_list([], _L, St) ->
- {[], St}.
-
-visit_clauses(Xs, [T | Ts], L, St) ->
- {Xs1, St1} = visit_clause(T, Xs, L, St),
- {Xs2, St2} = visit_clauses(Xs, Ts, L, St1),
- {join(Xs1, Xs2), St2};
-visit_clauses(_, [], _L, St) ->
- {none, St}.
-
-bind_defs([{V, F} | Ds], Vars) ->
- bind_defs(Ds, dict:store(get_label(V), singleton(get_label(F)),
- Vars));
-bind_defs([], Vars) ->
- Vars.
-
-bind_pats(Ps, none, Vars) ->
- bind_pats_single(Ps, empty(), Vars);
-bind_pats(Ps, Xs, Vars) ->
- if length(Xs) =:= length(Ps) ->
- bind_pats_list(Ps, Xs, Vars);
- true ->
- bind_pats_single(Ps, empty(), Vars)
- end.
-
-bind_pats_list([P | Ps], [X | Xs], Vars) ->
- bind_pats_list(Ps, Xs, bind_vars_single(pat_vars(P), X, Vars));
-bind_pats_list([], [], Vars) ->
- Vars.
-
-bind_pats_single([P | Ps], X, Vars) ->
- bind_pats_single(Ps, X, bind_vars_single(pat_vars(P), X, Vars));
-bind_pats_single([], _X, Vars) ->
- Vars.
-
-bind_vars(Vs, none, Vars) ->
- bind_vars_single(Vs, empty(), Vars);
-bind_vars(Vs, Xs, Vars) ->
- if length(Vs) =:= length(Xs) ->
- bind_vars_list(Vs, Xs, Vars);
- true ->
- bind_vars_single(Vs, empty(), Vars)
- end.
-
-bind_vars_list([V | Vs], [X | Xs], Vars) ->
- bind_vars_list(Vs, Xs, dict:store(get_label(V), X, Vars));
-bind_vars_list([], [], Vars) ->
- Vars.
-
-bind_vars_single([V | Vs], X, Vars) ->
- bind_vars_single(Vs, X, dict:store(get_label(V), X, Vars));
-bind_vars_single([], _X, Vars) ->
- Vars.
-
-%% This handles a call site - adding dependencies and updating parameter
-%% variables with respect to the actual parameters. The 'external'
-%% function is handled specially, since it can get an arbitrary number
-%% of arguments, which must be unified into a single argument.
-
-call_site(Ls, L, Xs, St) ->
-%%% io:fwrite("call site: ~w -> ~w (~w).\n", [L, Ls, Xs]),
- {D, W, V} = call_site(Ls, L, Xs, St#state.dep, St#state.work,
- St#state.vars, St#state.funs),
- St#state{dep = D, work = W, vars = V}.
-
-call_site([external | Ls], T, Xs, D, W, V, Fs) ->
- D1 = add_dep(external, T, D),
- X = join_single_list(Xs),
- case bind_arg(escape, X, V) of
- {V1, true} ->
-%%% io:fwrite("escape changed: ~w <- ~w + ~w.\n",
-%%% [dict:fetch(escape, V1), dict:fetch(escape, V),
-%%% X]),
- {W1, V2} = update_esc(set__to_list(X), W, V1, Fs),
- call_site(Ls, T, Xs, D1, add_work([external], W1), V2, Fs);
- {V1, false} ->
- call_site(Ls, T, Xs, D1, W, V1, Fs)
- end;
-call_site([L | Ls], T, Xs, D, W, V, Fs) ->
- D1 = add_dep(L, T, D),
- Vs = fun_vars(dict:fetch(L, Fs)),
- case bind_args(Vs, Xs, V) of
- {V1, true} ->
- call_site(Ls, T, Xs, D1, add_work([L], W), V1, Fs);
- {V1, false} ->
- call_site(Ls, T, Xs, D1, W, V1, Fs)
- end;
-call_site([], _, _, D, W, V, _) ->
- {D, W, V}.
-
-%% Note that `visit' makes sure all lambdas are visited at least once.
-%% For every called function, we add a dependency from the *called*
-%% function to the function containing the call site.
-
-add_dep(Source, Target, Deps) ->
- case dict:find(Source, Deps) of
- {ok, X} ->
- case set__is_member(Target, X) of
- true ->
- Deps;
- false ->
-%%% io:fwrite("new dep: ~w <- ~w.\n", [Target, Source]),
- dict:store(Source, set__add(Target, X), Deps)
- end;
- error ->
-%%% io:fwrite("new dep: ~w <- ~w.\n", [Target, Source]),
- dict:store(Source, set__singleton(Target), Deps)
- end.
-
-%% If the arity does not match the call, nothing is done here.
-
-bind_args(Vs, Xs, Vars) ->
- if length(Vs) =:= length(Xs) ->
- bind_args(Vs, Xs, Vars, false);
- true ->
- {Vars, false}
- end.
-
-bind_args([V | Vs], [X | Xs], Vars, Ch) ->
- L = get_label(V),
- {Vars1, Ch1} = bind_arg(L, X, Vars, Ch),
- bind_args(Vs, Xs, Vars1, Ch1);
-bind_args([], [], Vars, Ch) ->
- {Vars, Ch}.
-
-bind_args_single(Vs, X, Vars) ->
- bind_args_single(Vs, X, Vars, false).
-
-bind_args_single([V | Vs], X, Vars, Ch) ->
- L = get_label(V),
- {Vars1, Ch1} = bind_arg(L, X, Vars, Ch),
- bind_args_single(Vs, X, Vars1, Ch1);
-bind_args_single([], _, Vars, Ch) ->
- {Vars, Ch}.
-
-bind_arg(L, X, Vars) ->
- bind_arg(L, X, Vars, false).
-
-bind_arg(L, X, Vars, Ch) ->
- X0 = dict:fetch(L, Vars),
- X1 = join_single(X, X0),
- case equal_single(X0, X1) of
- true ->
- {Vars, Ch};
- false ->
-%%% io:fwrite("arg (~w) changed: ~w <- ~w + ~w.\n",
-%%% [L, X1, X0, X]),
- {dict:store(L, X1, Vars), true}
- end.
-
-%% This handles escapes from things like primops and remote calls.
-
-%% escape(none, St) ->
-%% St;
-escape([X], St) ->
- Vars = St#state.vars,
- X0 = dict:fetch(escape, Vars),
- X1 = join_single(X, X0),
- case equal_single(X0, X1) of
- true ->
- St;
- false ->
-%%% io:fwrite("escape changed: ~w <- ~w + ~w.\n", [X1, X0, X]),
-%%% io:fwrite("updating escaping funs: ~w.\n", [set__to_list(X)]),
- Vars1 = dict:store(escape, X1, Vars),
- {W, Vars2} = update_esc(set__to_list(set__subtract(X, X0)),
- St#state.work, Vars1,
- St#state.funs),
- St#state{work = add_work([external], W), vars = Vars2}
- end.
-
-%% For all escaping lambdas, since they might be called from outside the
-%% program, all their arguments may be an external lambda. (Note that we
-%% only have to include the `external' label once per escaping lambda.)
-%% If the escape set has changed, we need to revisit the `external' fun.
-
-update_esc(Ls, W, V, Fs) ->
- update_esc(Ls, singleton(external), W, V, Fs).
-
-%% The external lambda is skipped here - the Escape variable is known to
-%% contain `external' from the start.
-
-update_esc([external | Ls], X, W, V, Fs) ->
- update_esc(Ls, X, W, V, Fs);
-update_esc([L | Ls], X, W, V, Fs) ->
- Vs = fun_vars(dict:fetch(L, Fs)),
- case bind_args_single(Vs, X, V) of
- {V1, true} ->
- update_esc(Ls, X, add_work([L], W), V1, Fs);
- {V1, false} ->
- update_esc(Ls, X, W, V1, Fs)
- end;
-update_esc([], _, W, V, _) ->
- {W, V}.
-
-set_parent([L | Ls], L1, D) ->
- set_parent(Ls, L1, dict:store(L, L1, D));
-set_parent([], _L1, D) ->
- D.
-
-%% Handle primop calls: (At present, we assume that all unknown primops
-%% yield exactly one value. This might have to be changed.)
-
-primop_call(F, A, Xs, St0) ->
- case is_pure_op(F, A) of
- %% XXX: this case is currently not possible -- commented out.
- %% true ->
- %% case is_literal_op(F, A) of
- %% true -> {[empty()], St0};
- %% false -> {[join_single_list(Xs)], St0}
- %% end;
- false ->
- St1 = case is_escape_op(F, A) of
- true -> escape([join_single_list(Xs)], St0);
- false -> St0
- end,
- case is_literal_op(F, A) of
- true -> {none, St1};
- false -> {[singleton(external)], St1}
- end
- end.
-
-%% Handle remote-calls: (At present, we assume that all unknown calls
-%% yield exactly one value. This might have to be changed.)
-
-remote_call(M, F, Xs, St) ->
- case is_c_atom(M) andalso is_c_atom(F) of
- true ->
- remote_call_1(atom_val(M), atom_val(F), length(Xs), Xs, St);
- false ->
- %% Unknown function
- {[singleton(external)], escape([join_single_list(Xs)], St)}
- end.
-
-remote_call_1(M, F, A, Xs, St0) ->
- case is_pure_op(M, F, A) of
- true ->
- case is_literal_op(M, F, A) of
- true -> {[empty()], St0};
- false -> {[join_single_list(Xs)], St0}
- end;
- false ->
- St1 = case is_escape_op(M, F, A) of
- true -> escape([join_single_list(Xs)], St0);
- false -> St0
- end,
- case is_literal_op(M, F, A) of
- true -> {[empty()], St1};
- false -> {[singleton(external)], St1}
- end
- end.
-
-%% Domain: none | [Vs], where Vs = set(integer()).
-
-join(none, Xs2) -> Xs2;
-join(Xs1, none) -> Xs1;
-join(Xs1, Xs2) ->
- if length(Xs1) =:= length(Xs2) ->
- join_1(Xs1, Xs2);
- true ->
- none
- end.
-
-join_1([X1 | Xs1], [X2 | Xs2]) ->
- [join_single(X1, X2) | join_1(Xs1, Xs2)];
-join_1([], []) ->
- [].
-
-empty() -> set__new().
-
-singleton(X) -> set__singleton(X).
-
-from_label_list(X) -> set__from_list(X).
-
-join_single(none, Y) -> Y;
-join_single(X, none) -> X;
-join_single(X, Y) -> set__union(X, Y).
-
-join_list([Xs | Xss]) ->
- join(Xs, join_list(Xss));
-join_list([]) ->
- none.
-
-join_single_list([X | Xs]) ->
- join_single(X, join_single_list(Xs));
-join_single_list([]) ->
- empty().
-
-equal(none, none) -> true;
-equal(none, _) -> false;
-equal(_, none) -> false;
-equal(X1, X2) -> equal_1(X1, X2).
-
-equal_1([X1 | Xs1], [X2 | Xs2]) ->
- equal_single(X1, X2) andalso equal_1(Xs1, Xs2);
-equal_1([], []) -> true;
-equal_1(_, _) -> false.
-
-equal_single(X, Y) -> set__equal(X, Y).
-
-%% Set abstraction for label sets in the domain.
-
-set__new() -> [].
-
-set__singleton(X) -> [X].
-
-set__to_list(S) -> S.
-
-set__from_list(S) -> ordsets:from_list(S).
-
-set__union(X, Y) -> ordsets:union(X, Y).
-
-set__add(X, S) -> ordsets:add_element(X, S).
-
-set__is_member(X, S) -> ordsets:is_element(X, S).
-
-set__subtract(X, Y) -> ordsets:subtract(X, Y).
-
-set__equal(X, Y) -> X =:= Y.
-
-%% A simple but efficient functional queue.
-
-queue__new() -> {[], []}.
-
-queue__put(X, {In, Out}) -> {[X | In], Out}.
-
-queue__get({In, [X | Out]}) -> {ok, X, {In, Out}};
-queue__get({[], _}) -> empty;
-queue__get({In, _}) ->
- [X | In1] = lists:reverse(In),
- {ok, X, {[], In1}}.
-
-%% The work list - a queue without repeated elements.
-
-init_work() ->
- {queue__new(), sets:new()}.
-
-add_work(Ls, {Q, Set}) ->
- add_work(Ls, Q, Set).
-
-%% Note that the elements are enqueued in order.
-
-add_work([L | Ls], Q, Set) ->
- case sets:is_element(L, Set) of
- true ->
- add_work(Ls, Q, Set);
- false ->
- add_work(Ls, queue__put(L, Q), sets:add_element(L, Set))
- end;
-add_work([], Q, Set) ->
- {Q, Set}.
-
-take_work({Queue0, Set0}) ->
- case queue__get(Queue0) of
- {ok, L, Queue1} ->
- Set1 = sets:del_element(L, Set0),
- {ok, L, {Queue1, Set1}};
- empty ->
- none
- end.
-
-%% Escape operators may let their arguments escape. Unless we know
-%% otherwise, and the function is not pure, we assume this is the case.
-%% Error-raising functions (fault/match_fail) are not considered as
-%% escapes (but throw/exit are). Zero-argument functions need not be
-%% listed.
-
--spec is_escape_op(atom(), arity()) -> boolean().
-
-is_escape_op(match_fail, 1) -> false;
-is_escape_op(recv_wait_timeout, 1) -> false;
-is_escape_op(F, A) when is_atom(F), is_integer(A) -> true.
-
--spec is_escape_op(atom(), atom(), arity()) -> boolean().
-
-is_escape_op(erlang, error, 1) -> false;
-is_escape_op(erlang, error, 2) -> false;
-is_escape_op(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> true.
-
-%% "Literal" operators will never return functional values even when
-%% found in their arguments. Unless we know otherwise, we assume this is
-%% not the case. (More functions can be added to this list, if needed
-%% for better precision. Note that the result of `term_to_binary' still
-%% contains an encoding of the closure.)
-
--spec is_literal_op(atom(), arity()) -> boolean().
-
-is_literal_op(recv_wait_timeout, 1) -> true;
-is_literal_op(match_fail, 1) -> true;
-is_literal_op(F, A) when is_atom(F), is_integer(A) -> false.
-
--spec is_literal_op(atom(), atom(), arity()) -> boolean().
-
-is_literal_op(erlang, '+', 2) -> true;
-is_literal_op(erlang, '-', 2) -> true;
-is_literal_op(erlang, '*', 2) -> true;
-is_literal_op(erlang, '/', 2) -> true;
-is_literal_op(erlang, '=:=', 2) -> true;
-is_literal_op(erlang, '==', 2) -> true;
-is_literal_op(erlang, '=/=', 2) -> true;
-is_literal_op(erlang, '/=', 2) -> true;
-is_literal_op(erlang, '<', 2) -> true;
-is_literal_op(erlang, '=<', 2) -> true;
-is_literal_op(erlang, '>', 2) -> true;
-is_literal_op(erlang, '>=', 2) -> true;
-is_literal_op(erlang, 'and', 2) -> true;
-is_literal_op(erlang, 'or', 2) -> true;
-is_literal_op(erlang, 'not', 1) -> true;
-is_literal_op(erlang, length, 1) -> true;
-is_literal_op(erlang, size, 1) -> true;
-is_literal_op(erlang, fun_info, 1) -> true;
-is_literal_op(erlang, fun_info, 2) -> true;
-is_literal_op(erlang, fun_to_list, 1) -> true;
-is_literal_op(erlang, throw, 1) -> true;
-is_literal_op(erlang, exit, 1) -> true;
-is_literal_op(erlang, error, 1) -> true;
-is_literal_op(erlang, error, 2) -> true;
-is_literal_op(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> false.
-
-%% Pure functions neither affect the state, nor depend on it.
-
-is_pure_op(F, A) when is_atom(F), is_integer(A) -> false.
-
-is_pure_op(M, F, A) -> erl_bifs:is_pure(M, F, A).
-
-%% =====================================================================
diff --git a/lib/dialyzer/src/cerl_lib.erl b/lib/dialyzer/src/cerl_lib.erl
deleted file mode 100644
index 3a6fb1cf51..0000000000
--- a/lib/dialyzer/src/cerl_lib.erl
+++ /dev/null
@@ -1,457 +0,0 @@
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% @copyright 1999-2002 Richard Carlsson
-%% @author Richard Carlsson <carlsson.richard@gmail.com>
-%% @doc Utility functions for Core Erlang abstract syntax trees.
-%%
-%% <p>Syntax trees are defined in the module <a
-%% href=""><code>cerl</code></a>.</p>
-%%
-%% @type cerl() = cerl:cerl()
-
--module(cerl_lib).
-
--define(NO_UNUSED, true).
-
--export([is_safe_expr/2, reduce_expr/1, is_simple_clause/1,
- is_bool_switch/1, bool_switch_cases/1]).
--ifndef(NO_UNUSED).
--export([is_safe_expr/1, is_pure_expr/1, is_pure_expr/2,
- make_bool_switch/3]).
--endif.
-
-
-%% Test if a clause has a single pattern and an always-true guard.
-
--spec is_simple_clause(cerl:c_clause()) -> boolean().
-
-is_simple_clause(C) ->
- case cerl:clause_pats(C) of
- [_P] ->
- G = cerl:clause_guard(C),
- case cerl_clauses:eval_guard(G) of
- {value, true} -> true;
- _ -> false
- end;
- _ -> false
- end.
-
-%% Creating an if-then-else construct that can be recognized as such.
-%% `Test' *must* be guaranteed to return a boolean.
-
--ifndef(NO_UNUSED).
-make_bool_switch(Test, True, False) ->
- Cs = [cerl:c_clause([cerl:c_atom(true)], True),
- cerl:c_clause([cerl:c_atom(false)], False)],
- cerl:c_case(Test, Cs).
--endif.
-
-%% A boolean switch cannot have a catch-all; only true/false branches.
-
--spec is_bool_switch([cerl:c_clause()]) -> boolean().
-
-is_bool_switch([C1, C2]) ->
- case is_simple_clause(C1) andalso is_simple_clause(C2) of
- true ->
- [P1] = cerl:clause_pats(C1),
- [P2] = cerl:clause_pats(C2),
- case cerl:is_c_atom(P1) andalso cerl:is_c_atom(P2) of
- true ->
- A1 = cerl:concrete(P1),
- A2 = cerl:concrete(P2),
- is_boolean(A1) andalso is_boolean(A2)
- andalso A1 =/= A2;
- false ->
- false
- end;
- false ->
- false
- end;
-is_bool_switch(_) ->
- false.
-
-%% Returns the true-body and the false-body for boolean switch clauses.
-
--spec bool_switch_cases([cerl:c_clause()]) -> {cerl:cerl(), cerl:cerl()}.
-
-bool_switch_cases([C1, C2]) ->
- B1 = cerl:clause_body(C1),
- B2 = cerl:clause_body(C2),
- [P1] = cerl:clause_pats(C1),
- case cerl:concrete(P1) of
- true ->
- {B1, B2};
- false ->
- {B2, B1}
- end.
-
-%%
-%% The type of the check functions like the default check below - XXX: refine
-%%
--type check_fun() :: fun((_, _) -> boolean()).
-
-%% The default function property check always returns `false':
-
-default_check(_Property, _Function) -> false.
-
-
-%% @spec is_safe_expr(Expr::cerl()) -> boolean()
-%%
-%% @doc Returns `true' if `Expr' represents a "safe" Core Erlang
-%% expression, otherwise `false'. An expression is safe if it always
-%% completes normally and does not modify the state (although the return
-%% value may depend on the state).
-%%
-%% Expressions of type `apply', `case', `receive' and `binary' are
-%% always considered unsafe by this function.
-
-%% TODO: update cerl_inline to use these functions instead.
-
--ifndef(NO_UNUSED).
-is_safe_expr(E) ->
- Check = fun default_check/2,
- is_safe_expr(E, Check).
--endif.
-%% @clear
-
--spec is_safe_expr(cerl:cerl(), check_fun()) -> boolean().
-
-is_safe_expr(E, Check) ->
- case cerl:type(E) of
- literal ->
- true;
- var ->
- true;
- 'fun' ->
- true;
- values ->
- is_safe_expr_list(cerl:values_es(E), Check);
- tuple ->
- is_safe_expr_list(cerl:tuple_es(E), Check);
- cons ->
- case is_safe_expr(cerl:cons_hd(E), Check) of
- true ->
- is_safe_expr(cerl:cons_tl(E), Check);
- false ->
- false
- end;
- 'let' ->
- case is_safe_expr(cerl:let_arg(E), Check) of
- true ->
- is_safe_expr(cerl:let_body(E), Check);
- false ->
- false
- end;
- letrec ->
- is_safe_expr(cerl:letrec_body(E), Check);
- seq ->
- case is_safe_expr(cerl:seq_arg(E), Check) of
- true ->
- is_safe_expr(cerl:seq_body(E), Check);
- false ->
- false
- end;
- 'catch' ->
- is_safe_expr(cerl:catch_body(E), Check);
- 'try' ->
- %% If the guarded expression is safe, the try-handler will
- %% never be evaluated, so we need only check the body. If
- %% the guarded expression is pure, but could fail, we also
- %% have to check the handler.
- case is_safe_expr(cerl:try_arg(E), Check) of
- true ->
- is_safe_expr(cerl:try_body(E), Check);
- false ->
- case is_pure_expr(cerl:try_arg(E), Check) of
- true ->
- case is_safe_expr(cerl:try_body(E), Check) of
- true ->
- is_safe_expr(cerl:try_handler(E), Check);
- false ->
- false
- end;
- false ->
- false
- end
- end;
- primop ->
- Name = cerl:atom_val(cerl:primop_name(E)),
- As = cerl:primop_args(E),
- case Check(safe, {Name, length(As)}) of
- true ->
- is_safe_expr_list(As, Check);
- false ->
- false
- end;
- call ->
- Module = cerl:call_module(E),
- Name = cerl:call_name(E),
- case cerl:is_c_atom(Module) and cerl:is_c_atom(Name) of
- true ->
- M = cerl:atom_val(Module),
- F = cerl:atom_val(Name),
- As = cerl:call_args(E),
- case Check(safe, {M, F, length(As)}) of
- true ->
- is_safe_expr_list(As, Check);
- false ->
- false
- end;
- false ->
- false % Call to unknown function
- end;
- _ ->
- false
- end.
-
-is_safe_expr_list([E | Es], Check) ->
- case is_safe_expr(E, Check) of
- true ->
- is_safe_expr_list(Es, Check);
- false ->
- false
- end;
-is_safe_expr_list([], _Check) ->
- true.
-
-
-%% @spec (Expr::cerl()) -> bool()
-%%
-%% @doc Returns `true' if `Expr' represents a "pure" Core Erlang
-%% expression, otherwise `false'. An expression is pure if it does not
-%% affect the state, nor depend on the state, although its evaluation is
-%% not guaranteed to complete normally for all input.
-%%
-%% Expressions of type `apply', `case', `receive' and `binary' are
-%% always considered impure by this function.
-
--ifndef(NO_UNUSED).
-is_pure_expr(E) ->
- Check = fun default_check/2,
- is_pure_expr(E, Check).
--endif.
-%% @clear
-
-is_pure_expr(E, Check) ->
- case cerl:type(E) of
- literal ->
- true;
- var ->
- true;
- 'fun' ->
- true;
- values ->
- is_pure_expr_list(cerl:values_es(E), Check);
- tuple ->
- is_pure_expr_list(cerl:tuple_es(E), Check);
- cons ->
- case is_pure_expr(cerl:cons_hd(E), Check) of
- true ->
- is_pure_expr(cerl:cons_tl(E), Check);
- false ->
- false
- end;
- 'let' ->
- case is_pure_expr(cerl:let_arg(E), Check) of
- true ->
- is_pure_expr(cerl:let_body(E), Check);
- false ->
- false
- end;
- letrec ->
- is_pure_expr(cerl:letrec_body(E), Check);
- seq ->
- case is_pure_expr(cerl:seq_arg(E), Check) of
- true ->
- is_pure_expr(cerl:seq_body(E), Check);
- false ->
- false
- end;
- 'catch' ->
- is_pure_expr(cerl:catch_body(E), Check);
- 'try' ->
- case is_pure_expr(cerl:try_arg(E), Check) of
- true ->
- case is_pure_expr(cerl:try_body(E), Check) of
- true ->
- is_pure_expr(cerl:try_handler(E), Check);
- false ->
- false
- end;
- false ->
- false
- end;
- primop ->
- Name = cerl:atom_val(cerl:primop_name(E)),
- As = cerl:primop_args(E),
- case Check(pure, {Name, length(As)}) of
- true ->
- is_pure_expr_list(As, Check);
- false ->
- false
- end;
- call ->
- Module = cerl:call_module(E),
- Name = cerl:call_name(E),
- case cerl:is_c_atom(Module) and cerl:is_c_atom(Name) of
- true ->
- M = cerl:atom_val(Module),
- F = cerl:atom_val(Name),
- As = cerl:call_args(E),
- case Check(pure, {M, F, length(As)}) of
- true ->
- is_pure_expr_list(As, Check);
- false ->
- false
- end;
- false ->
- false % Call to unknown function
- end;
- _ ->
- false
- end.
-
-is_pure_expr_list([E | Es], Check) ->
- case is_pure_expr(E, Check) of
- true ->
- is_pure_expr_list(Es, Check);
- false ->
- false
- end;
-is_pure_expr_list([], _Check) ->
- true.
-
-
-%% Peephole optimizations
-%%
-%% This is only intended to be a light-weight cleanup optimizer,
-%% removing small things that may e.g. have been generated by other
-%% optimization passes or in the translation from higher-level code.
-%% It is not recursive in general - it only descends until it can do no
-%% more work in the current context.
-%%
-%% To expose hidden cases of final expressions (enabling last call
-%% optimization), we try to remove all trivial let-bindings (`let X = Y
-%% in X', `let X = Y in Y', `let X = Y in let ... in ...', `let X = let
-%% ... in ... in ...', etc.). We do not, however, try to recognize any
-%% other similar cases, even for simple `case'-expressions like `case E
-%% of X -> X end', or simultaneous multiple-value bindings.
-
--spec reduce_expr(cerl:cerl()) -> cerl:cerl().
-
-reduce_expr(E) ->
- Check = fun default_check/2,
- reduce_expr(E, Check).
-
--spec reduce_expr(cerl:cerl(), check_fun()) -> cerl:cerl().
-
-reduce_expr(E, Check) ->
- case cerl:type(E) of
- values ->
- case cerl:values_es(E) of
- [E1] ->
- %% Not really an "optimization" in itself, but
- %% enables other rewritings by removing the wrapper.
- reduce_expr(E1, Check);
- _ ->
- E
- end;
- 'seq' ->
- A = reduce_expr(cerl:seq_arg(E), Check),
- B = reduce_expr(cerl:seq_body(E), Check),
- %% `do <E1> <E2>' is equivalent to `<E2>' if `<E1>' is
- %% "safe" (cannot effect the behaviour in any way).
- case is_safe_expr(A, Check) of
- true ->
- B;
- false ->
- case cerl:is_c_seq(B) of
- true ->
- %% Rewrite `do <E1> do <E2> <E3>' to `do do
- %% <E1> <E2> <E3>' so that the "body" of the
- %% outermost seq-operator is the expression
- %% which produces the final result (i.e.,
- %% E3). This can make other optimizations
- %% easier; see `let'.
- B1 = cerl:seq_arg(B),
- B2 = cerl:seq_body(B),
- cerl:c_seq(cerl:c_seq(A, B1), B2);
- false ->
- cerl:c_seq(A, B)
- end
- end;
- 'let' ->
- A = reduce_expr(cerl:let_arg(E), Check),
- case cerl:is_c_seq(A) of
- true ->
- %% `let X = do <E1> <E2> in Y' is equivalent to `do
- %% <E1> let X = <E2> in Y'. Note that `<E2>' cannot
- %% be a seq-operator, due to the `seq' optimization.
- A1 = cerl:seq_arg(A),
- A2 = cerl:seq_body(A),
- E1 = cerl:update_c_let(E, cerl:let_vars(E),
- A2, cerl:let_body(E)),
- cerl:c_seq(A1, reduce_expr(E1, Check));
- false ->
- B = reduce_expr(cerl:let_body(E), Check),
- Vs = cerl:let_vars(E),
- %% We give up if the body does not reduce to a
- %% single variable. This is not a generic copy
- %% propagation.
- case cerl:type(B) of
- var when length(Vs) =:= 1 ->
- %% We have `let <V1> = <E> in <V2>':
- [V] = Vs,
- N1 = cerl:var_name(V),
- N2 = cerl:var_name(B),
- if N1 =:= N2 ->
- %% `let X = <E> in X' equals `<E>'
- A;
- true ->
- %% `let X = <E> in Y' when X and Y
- %% are different variables is
- %% equivalent to `do <E> Y'.
- reduce_expr(cerl:c_seq(A, B), Check)
- end;
- literal ->
- %% `let X = <E> in T' when T is a literal
- %% term is equivalent to `do <E> T'.
- reduce_expr(cerl:c_seq(A, B), Check);
- _ ->
- cerl:update_c_let(E, Vs, A, B)
- end
- end;
- 'try' ->
- %% Get rid of unnecessary try-expressions.
- A = reduce_expr(cerl:try_arg(E), Check),
- B = reduce_expr(cerl:try_body(E), Check),
- case is_safe_expr(A, Check) of
- true ->
- B;
- false ->
- cerl:update_c_try(E, A, cerl:try_vars(E), B,
- cerl:try_evars(E),
- cerl:try_handler(E))
- end;
- 'catch' ->
- %% Just a simpler form of try-expressions.
- B = reduce_expr(cerl:catch_body(E), Check),
- case is_safe_expr(B, Check) of
- true ->
- B;
- false ->
- cerl:update_c_catch(E, B)
- end;
- _ ->
- E
- end.
diff --git a/lib/dialyzer/src/cerl_pmatch.erl b/lib/dialyzer/src/cerl_pmatch.erl
deleted file mode 100644
index 66fce3c8eb..0000000000
--- a/lib/dialyzer/src/cerl_pmatch.erl
+++ /dev/null
@@ -1,620 +0,0 @@
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% @copyright 2000-2006 Richard Carlsson
-%% @author Richard Carlsson <carlsson.richard@gmail.com>
-%%
-%% @doc Core Erlang pattern matching compiler.
-%%
-%% <p>For reference, see Simon L. Peyton Jones "The Implementation of
-%% Functional Programming Languages", chapter 5 (by Phil Wadler).</p>
-%%
-%% @type cerl() = cerl:cerl().
-%% Abstract Core Erlang syntax trees.
-%% @type cerl_records() = cerl:cerl_records().
-%% An explicit record representation of Core Erlang syntax trees.
-
--module(cerl_pmatch).
-
-%%-define(NO_UNUSED, true).
-
--export([clauses/2]).
--ifndef(NO_UNUSED).
--export([transform/2, core_transform/2, expr/2]).
--endif.
-
--import(lists, [all/2, splitwith/2, foldr/3, keysort/2, foldl/3,
- mapfoldl/3]).
-
--define(binary_id, {binary}).
--define(cons_id, {cons}).
--define(tuple_id, {tuple}).
--define(literal_id(V), V).
-
-
-%% @spec core_transform(Module::cerl_records(), Options::[term()]) ->
-%% cerl_records()
-%%
-%% @doc Transforms a module represented by records. See
-%% <code>transform/2</code> for details.
-%%
-%% <p>Use the compiler option <code>{core_transform, cerl_pmatch}</code>
-%% to insert this function as a compilation pass.</p>
-%%
-%% @see transform/2
-
--ifndef(NO_UNUSED).
--spec core_transform(cerl:c_module(), [_]) -> cerl:c_module().
-
-core_transform(M, Opts) ->
- cerl:to_records(transform(cerl:from_records(M), Opts)).
--endif. % NO_UNUSED
-%% @clear
-
-
-%% @spec transform(Module::cerl(), Options::[term()]) -> cerl()
-%%
-%% @doc Rewrites all <code>case</code>-clauses in <code>Module</code>.
-%% <code>receive</code>-clauses are not affected. Currently, no options
-%% are available.
-%%
-%% @see clauses/2
-%% @see expr/2
-%% @see core_transform/2
-
--ifndef(NO_UNUSED).
--spec transform(cerl:cerl(), [_]) -> cerl:cerl().
-
-transform(M, _Opts) ->
- expr(M, env__empty()).
--endif. % NO_UNUSED
-%% @clear
-
-
-%% @spec clauses(Clauses::[Clause], Env) -> {Expr, Vars}
-%% Clause = cerl()
-%% Expr = cerl()
-%% Vars = [cerl()]
-%% Env = rec_env:environment()
-%%
-%% @doc Rewrites a sequence of clauses to an equivalent expression,
-%% removing as much repeated testing as possible. Returns a pair
-%% <code>{Expr, Vars}</code>, where <code>Expr</code> is the resulting
-%% expression, and <code>Vars</code> is a list of new variables (i.e.,
-%% not already in the given environment) to be bound to the arguments to
-%% the switch. The following is a typical example (assuming
-%% <code>E</code> is a Core Erlang case expression):
-%% <pre>
-%% handle_case(E, Env) ->
-%% Cs = case_clauses(E),
-%% {E1, Vs} = cerl_pmatch(Cs, Env),
-%% c_let(Vs, case_arg(E), E1).
-%% </pre>
-%%
-%% <p>The environment is used for generating new variables which do not
-%% shadow existing bindings.</p>
-%%
-%% @see rec_env
-%% @see expr/2
-%% @see transform/2
-
--spec clauses([cerl:cerl(),...], rec_env:environment()) ->
- {cerl:cerl(), [cerl:cerl()]}.
-
-clauses(Cs, Env) ->
- clauses(Cs, none, Env).
-
-clauses([C | _] = Cs, Else, Env) ->
- Vs = new_vars(cerl:clause_arity(C), Env),
- E = match(Vs, Cs, Else, add_vars(Vs, Env)),
- {E, Vs}.
-
-%% The implementation very closely follows that described in the book.
-
-match([], Cs, Else, _Env) ->
- %% If the "default action" is the atom 'none', it is simply not
- %% added; otherwise it is put in the body of a final catch-all
- %% clause (which is often removed by the below optimization).
- Cs1 = if Else =:= none -> Cs;
- true -> Cs ++ [cerl:c_clause([], Else)]
- end,
- %% This clause reduction is an important optimization. It selects a
- %% clause body if possible, and otherwise just removes dead clauses.
- case cerl_clauses:reduce(Cs1) of
- {true, {C, []}} -> % if we get bindings, something is wrong!
- cerl:clause_body(C);
- {false, Cs2} ->
- %% This happens when guards are nontrivial.
- cerl:c_case(cerl:c_values([]), Cs2)
- end;
-match([V | _] = Vs, Cs, Else, Env) ->
- foldr(fun (CsF, ElseF) ->
- match_var_con(Vs, CsF, ElseF, Env)
- end,
- Else,
- group([unalias(C, V) || C <- Cs], fun is_var_clause/1)).
-
-group([], _F) ->
- [];
-group([X | _] = Xs, F) ->
- group(Xs, F, F(X)).
-
-group(Xs, F, P) ->
- {First, Rest} = splitwith(fun (X) -> F(X) =:= P end, Xs),
- [First | group(Rest, F)].
-
-is_var_clause(C) ->
- cerl:is_c_var(hd(cerl:clause_pats(C))).
-
-%% To avoid code duplication, if the 'Else' expression is too big, we
-%% put it in a local function definition instead, and replace it with a
-%% call. (Note that it is important that 'is_lightweight' does not yield
-%% 'true' for a simple function application, or we will create a lot of
-%% unnecessary extra functions.)
-
-match_var_con(Vs, Cs, none = Else, Env) ->
- match_var_con_1(Vs, Cs, Else, Env);
-match_var_con(Vs, Cs, Else, Env) ->
- case is_lightweight(Else) of
- true ->
- match_var_con_1(Vs, Cs, Else, Env);
- false ->
- F = new_fvar("match_", 0, Env),
- Else1 = cerl:c_apply(F, []),
- Env1 = add_vars([F], Env),
- cerl:c_letrec([{F, cerl:c_fun([], Else)}],
- match_var_con_1(Vs, Cs, Else1, Env1))
- end.
-
-match_var_con_1(Vs, Cs, Else, Env) ->
- case is_var_clause(hd(Cs)) of
- true ->
- match_var(Vs, Cs, Else, Env);
- false ->
- match_con(Vs, Cs, Else, Env)
- end.
-
-match_var([V | Vs], Cs, Else, Env) ->
- Cs1 = [begin
- [P | Ps] = cerl:clause_pats(C),
- G = make_let([P], V, cerl:clause_guard(C)),
- B = make_let([P], V, cerl:clause_body(C)),
- cerl:update_c_clause(C, Ps, G, B)
- end
- || C <- Cs],
- match(Vs, Cs1, Else, Env).
-
-%% Since Erlang is dynamically typed, we must include the possibility
-%% that none of the constructors in the group will match, and in that
-%% case the "Else" code will be executed (unless it is 'none'), in the
-%% body of a final catch-all clause.
-
-match_con([V | Vs], Cs, Else, Env) ->
- case group_con(Cs) of
- [{_, _, Gs}] ->
- %% Don't create a group type switch if there is only one
- %% such group
- make_switch(V, [match_congroup(DG, Vs, CsG, Else, Env)
- || {DG, _, CsG} <- Gs],
- Else, Env);
- Ts ->
- Cs1 = [match_typegroup(T, V, Vs, Gs, Else, Env)
- || {T, _, Gs} <- Ts],
- make_switch(V, Cs1, Else, Env)
- end.
-
-
-match_typegroup(_T, _V, Vs, [{D, _, Cs}], Else, Env) when element(1, D) /= ?binary_id ->
- %% Don't create a group type switch if there is only one constructor
- %% in the group. (Note that this always happens for '[]'.)
- %% Special case for binaries which always get a group switch
- match_congroup(D, Vs, Cs, Else, Env);
-match_typegroup(T, V, Vs, Gs, Else, Env) ->
- Body = make_switch(V, [match_congroup(D, Vs, Cs, Else, Env)
- || {D, _, Cs} <- Gs],
- Else, Env),
- typetest_clause(T, V, Body, Env).
-
-match_congroup({?binary_id, Segs}, Vs, Cs, Else, Env) ->
- Body = match(Vs, Cs, Else, Env),
- cerl:c_clause([make_pat(?binary_id, Segs)], Body);
-
-match_congroup({D, A}, Vs, Cs, Else, Env) ->
- Vs1 = new_vars(A, Env),
- Body = match(Vs1 ++ Vs, Cs, Else, add_vars(Vs1, Env)),
- cerl:c_clause([make_pat(D, Vs1)], Body).
-
-make_switch(V, Cs, Else, Env) ->
- cerl:c_case(V, if Else =:= none -> Cs;
- true -> Cs ++ [cerl:c_clause([new_var(Env)],
- Else)]
- end).
-
-%% We preserve the relative order of different-type constructors as they
-%% were originally listed. This is done by tracking the clause numbers.
-
-group_con(Cs) ->
- {Cs1, _} = mapfoldl(fun (C, N) ->
- [P | Ps] = cerl:clause_pats(C),
- Ps1 = sub_pats(P) ++ Ps,
- G = cerl:clause_guard(C),
- B = cerl:clause_body(C),
- C1 = cerl:update_c_clause(C, Ps1, G, B),
- D = con_desc(P),
- {{D, N, C1}, N + 1}
- end,
- 0, Cs),
- %% Sort and group constructors.
- Css = group(keysort(1, Cs1), fun ({D,_,_}) -> D end),
- %% Sort each group "back" by line number, and move the descriptor
- %% and line number to the wrapper for the group.
- Gs = [finalize_congroup(C) || C <- Css],
- %% Group by type only (put e.g. different-arity tuples together).
- Gss = group(Gs, fun ({D,_,_}) -> con_desc_type(D) end),
- %% Sort and wrap the type groups.
- Ts = [finalize_typegroup(G) || G <- Gss],
- %% Sort type-groups by first clause order
- keysort(2, Ts).
-
-finalize_congroup(Cs) ->
- [{D,N,_}|_] = Cs1 = keysort(2, Cs),
- {D, N, [C || {_,_,C} <- Cs1]}.
-
-finalize_typegroup(Gs) ->
- [{D,N,_}|_] = Gs1 = keysort(2, Gs),
- {con_desc_type(D), N, Gs1}.
-
-%% Since Erlang clause patterns can contain "alias patterns", we must
-%% eliminate these, by turning them into let-definitions in the guards
-%% and bodies of the clauses.
-
-unalias(C, V) ->
- [P | Ps] = cerl:clause_pats(C),
- B = cerl:clause_body(C),
- G = cerl:clause_guard(C),
- unalias(P, V, Ps, B, G, C).
-
-unalias(P, V, Ps, B, G, C) ->
- case cerl:type(P) of
- alias ->
- V1 = cerl:alias_var(P),
- B1 = make_let([V1], V, B),
- G1 = make_let([V1], V, G),
- unalias(cerl:alias_pat(P), V, Ps, B1, G1, C);
- _ ->
- cerl:update_c_clause(C, [P | Ps], G, B)
- end.
-
-%% Generating a type-switch clause
-
-typetest_clause([], _V, E, _Env) ->
- cerl:c_clause([cerl:c_nil()], E);
-typetest_clause(atom, V, E, _Env) ->
- typetest_clause_1(is_atom, V, E);
-typetest_clause(integer, V, E, _Env) ->
- typetest_clause_1(is_integer, V, E);
-typetest_clause(float, V, E, _Env) ->
- typetest_clause_1(is_float, V, E);
-typetest_clause(cons, _V, E, Env) ->
- [V1, V2] = new_vars(2, Env),
- cerl:c_clause([cerl:c_cons(V1, V2)], E); % there is no 'is cons'
-typetest_clause(tuple, V, E, _Env) ->
- typetest_clause_1(is_tuple, V, E);
-typetest_clause(binary, V, E, _Env) ->
- typetest_clause_1(is_binary, V, E).
-
-typetest_clause_1(T, V, E) ->
- cerl:c_clause([V], cerl:c_call(cerl:c_atom('erlang'),
- cerl:c_atom(T), [V]), E).
-
-%% This returns a constructor descriptor, to be used for grouping and
-%% pattern generation. It consists of an identifier term and the arity.
-
-con_desc(E) ->
- case cerl:type(E) of
- cons -> {?cons_id, 2};
- tuple -> {?tuple_id, cerl:tuple_arity(E)};
- binary -> {?binary_id, cerl:binary_segments(E)};
- literal ->
- case cerl:concrete(E) of
- [_|_] -> {?cons_id, 2};
- T when is_tuple(T) -> {?tuple_id, tuple_size(T)};
- V -> {?literal_id(V), 0}
- end;
- _ ->
- throw({bad_constructor, E})
- end.
-
-%% This returns the type class for a constructor descriptor, for
-%% grouping of clauses. It does not distinguish between tuples of
-%% different arity, nor between different values of atoms, integers and
-%% floats.
-
-con_desc_type({?literal_id([]), _}) -> [];
-con_desc_type({?literal_id(V), _}) when is_atom(V) -> atom;
-con_desc_type({?literal_id(V), _}) when is_integer(V) -> integer;
-con_desc_type({?literal_id(V), _}) when is_float(V) -> float;
-con_desc_type({?cons_id, 2}) -> cons;
-con_desc_type({?tuple_id, _}) -> tuple;
-con_desc_type({?binary_id, _}) -> binary.
-
-%% This creates a new constructor pattern from a type descriptor and a
-%% list of variables.
-
-make_pat(?cons_id, [V1, V2]) -> cerl:c_cons(V1, V2);
-make_pat(?tuple_id, Vs) -> cerl:c_tuple(Vs);
-make_pat(?binary_id, Segs) -> cerl:c_binary(Segs);
-make_pat(?literal_id(Val), []) -> cerl:abstract(Val).
-
-%% This returns the list of subpatterns of a constructor pattern.
-
-sub_pats(E) ->
- case cerl:type(E) of
- cons ->
- [cerl:cons_hd(E), cerl:cons_tl(E)];
- tuple ->
- cerl:tuple_es(E);
- binary ->
- [];
- literal ->
- case cerl:concrete(E) of
- [H|T] -> [cerl:abstract(H), cerl:abstract(T)];
- T when is_tuple(T) -> [cerl:abstract(X)
- || X <- tuple_to_list(T)];
- _ -> []
- end;
- _ ->
- throw({bad_constructor_pattern, E})
- end.
-
-%% This avoids generating stupid things like "let X = ... in 'true'",
-%% and "let X = Y in X", keeping the generated code cleaner. It also
-%% prevents expressions from being considered "non-lightweight" when
-%% code duplication is disallowed (see is_lightweight for details).
-
-make_let(Vs, A, B) ->
- cerl_lib:reduce_expr(cerl:c_let(Vs, A, B)).
-
-%% ---------------------------------------------------------------------
-%% Rewriting a module or other expression:
-
-%% @spec expr(Expression::cerl(), Env) -> cerl()
-%% Env = rec_env:environment()
-%%
-%% @doc Rewrites all <code>case</code>-clauses in
-%% <code>Expression</code>. <code>receive</code>-clauses are not
-%% affected.
-%%
-%% <p>The environment is used for generating new variables which do not
-%% shadow existing bindings.</p>
-%%
-%% @see clauses/2
-%% @see rec_env
-
--ifndef(NO_UNUSED).
--spec expr(cerl:cerl(), rec_env:environment()) -> cerl:cerl().
-
-expr(E, Env) ->
- case cerl:type(E) of
- binary ->
- Es = expr_list(cerl:binary_segments(E), Env),
- cerl:update_c_binary(E, Es);
- bitstr ->
- V = expr(cerl:bitstr_val(E), Env),
- Sz = expr(cerl:bitstr_size(E), Env),
- Unit = expr(cerl:bitstr_unit(E), Env),
- Type = expr(cerl:bitstr_type(E), Env),
- cerl:update_c_bitstr(E, V, Sz, Unit, Type, cerl:bitstr_flags(E));
- literal ->
- E;
- var ->
- E;
- values ->
- Es = expr_list(cerl:values_es(E), Env),
- cerl:update_c_values(E, Es);
- cons ->
- H = expr(cerl:cons_hd(E), Env),
- T = expr(cerl:cons_tl(E), Env),
- cerl:update_c_cons(E, H, T);
- tuple ->
- Es = expr_list(cerl:tuple_es(E), Env),
- cerl:update_c_tuple(E, Es);
- 'let' ->
- A = expr(cerl:let_arg(E), Env),
- Vs = cerl:let_vars(E),
- Env1 = add_vars(Vs, Env),
- B = expr(cerl:let_body(E), Env1),
- cerl:update_c_let(E, Vs, A, B);
- seq ->
- A = expr(cerl:seq_arg(E), Env),
- B = expr(cerl:seq_body(E), Env),
- cerl:update_c_seq(E, A, B);
- apply ->
- Op = expr(cerl:apply_op(E), Env),
- As = expr_list(cerl:apply_args(E), Env),
- cerl:update_c_apply(E, Op, As);
- call ->
- M = expr(cerl:call_module(E), Env),
- N = expr(cerl:call_name(E), Env),
- As = expr_list(cerl:call_args(E), Env),
- cerl:update_c_call(E, M, N, As);
- primop ->
- As = expr_list(cerl:primop_args(E), Env),
- cerl:update_c_primop(E, cerl:primop_name(E), As);
- 'case' ->
- A = expr(cerl:case_arg(E), Env),
- Cs = expr_list(cerl:case_clauses(E), Env),
- {E1, Vs} = clauses(Cs, Env),
- make_let(Vs, A, E1);
- clause ->
- Vs = cerl:clause_vars(E),
- Env1 = add_vars(Vs, Env),
- G = expr(cerl:clause_guard(E), Env1),
- B = expr(cerl:clause_body(E), Env1),
- cerl:update_c_clause(E, cerl:clause_pats(E), G, B);
- 'fun' ->
- Vs = cerl:fun_vars(E),
- Env1 = add_vars(Vs, Env),
- B = expr(cerl:fun_body(E), Env1),
- cerl:update_c_fun(E, Vs, B);
- 'receive' ->
- %% NOTE: No pattern matching compilation is done here! The
- %% receive-clauses and patterns cannot be staged as long as
- %% we are working with "normal" Core Erlang.
- Cs = expr_list(cerl:receive_clauses(E), Env),
- T = expr(cerl:receive_timeout(E), Env),
- A = expr(cerl:receive_action(E), Env),
- cerl:update_c_receive(E, Cs, T, A);
- 'try' ->
- A = expr(cerl:try_arg(E), Env),
- Vs = cerl:try_vars(E),
- B = expr(cerl:try_body(E), add_vars(Vs, Env)),
- Evs = cerl:try_evars(E),
- H = expr(cerl:try_handler(E), add_vars(Evs, Env)),
- cerl:update_c_try(E, A, Vs, B, Evs, H);
- 'catch' ->
- B = expr(cerl:catch_body(E), Env),
- cerl:update_c_catch(E, B);
- letrec ->
- Ds = cerl:letrec_defs(E),
- Env1 = add_defs(Ds, Env),
- Ds1 = defs(Ds, Env1),
- B = expr(cerl:letrec_body(E), Env1),
- cerl:update_c_letrec(E, Ds1, B);
- module ->
- Ds = cerl:module_defs(E),
- Env1 = add_defs(Ds, Env),
- Ds1 = defs(Ds, Env1),
- cerl:update_c_module(E, cerl:module_name(E),
- cerl:module_exports(E),
- cerl:module_attrs(E), Ds1)
- end.
-
-expr_list(Es, Env) ->
- [expr(E, Env) || E <- Es].
-
-defs(Ds, Env) ->
- [{V, expr(F, Env)} || {V, F} <- Ds].
--endif. % NO_UNUSED
-%% @clear
-
-%% ---------------------------------------------------------------------
-%% Support functions
-
-new_var(Env) ->
- Name = env__new_vname(Env),
- cerl:c_var(Name).
-
-new_vars(N, Env) ->
- [cerl:c_var(V) || V <- env__new_vnames(N, Env)].
-
-new_fvar(A, N, Env) ->
- Name = env__new_fname(A, N, Env),
- cerl:c_var(Name).
-
-add_vars(Vs, Env) ->
- foldl(fun (V, E) -> env__bind(cerl:var_name(V), [], E) end, Env, Vs).
-
--ifndef(NO_UNUSED).
-add_defs(Ds, Env) ->
- foldl(fun ({V, _F}, E) ->
- env__bind(cerl:var_name(V), [], E)
- end, Env, Ds).
--endif. % NO_UNUSED
-
-%% This decides whether an expression is worth lifting out to a separate
-%% function instead of duplicating the code. In other words, whether its
-%% cost is about the same or smaller than that of a local function call.
-%% Note that variables must always be "lightweight"; otherwise, they may
-%% get lifted out of the case switch that introduces them.
-
-is_lightweight(E) ->
- case get('cerl_pmatch_duplicate_code') of
- never -> cerl:type(E) =:= var; % Avoids all code duplication
- always -> true; % Does not lift code to new functions
- _ -> is_lightweight_1(E)
- end.
-
-is_lightweight_1(E) ->
- case cerl:type(E) of
- var -> true;
- literal -> true;
- 'fun' -> true;
- values -> all(fun is_simple/1, cerl:values_es(E));
- cons -> is_simple(cerl:cons_hd(E))
- andalso is_simple(cerl:cons_tl(E));
- tuple -> all(fun is_simple/1, cerl:tuple_es(E));
- 'let' -> (is_simple(cerl:let_arg(E)) andalso
- is_lightweight_1(cerl:let_body(E)));
- seq -> (is_simple(cerl:seq_arg(E)) andalso
- is_lightweight_1(cerl:seq_body(E)));
- primop ->
- all(fun is_simple/1, cerl:primop_args(E));
- apply ->
- is_simple(cerl:apply_op(E))
- andalso all(fun is_simple/1, cerl:apply_args(E));
- call ->
- is_simple(cerl:call_module(E))
- andalso is_simple(cerl:call_name(E))
- andalso all(fun is_simple/1, cerl:call_args(E));
- _ ->
- %% The default is to lift the code to a new function.
- false
- end.
-
-%% "Simple" things have no (or negligible) runtime cost and are free
-%% from side effects.
-
-is_simple(E) ->
- case cerl:type(E) of
- var -> true;
- literal -> true;
- values -> all(fun is_simple/1, cerl:values_es(E));
- _ -> false
- end.
-
-
-%% ---------------------------------------------------------------------
-%% Abstract datatype: environment()
-
-env__bind(Key, Val, Env) ->
- rec_env:bind(Key, Val, Env).
-
--ifndef(NO_UNUSED).
-%% env__bind_recursive(Ks, Vs, F, Env) ->
-%% rec_env:bind_recursive(Ks, Vs, F, Env).
-
-%% env__lookup(Key, Env) ->
-%% rec_env:lookup(Key, Env).
-
-%% env__get(Key, Env) ->
-%% rec_env:get(Key, Env).
-
-%% env__is_defined(Key, Env) ->
-%% rec_env:is_defined(Key, Env).
-
-env__empty() ->
- rec_env:empty().
--endif. % NO_UNUSED
-
-env__new_vname(Env) ->
- rec_env:new_key(Env).
-
-env__new_vnames(N, Env) ->
- rec_env:new_keys(N, Env).
-
-env__new_fname(F, A, Env) ->
- rec_env:new_key(fun (X) ->
- S = integer_to_list(X),
- {list_to_atom(F ++ S), A}
- end,
- Env).
diff --git a/lib/dialyzer/src/cerl_typean.erl b/lib/dialyzer/src/cerl_typean.erl
deleted file mode 100644
index 3deb4af3e1..0000000000
--- a/lib/dialyzer/src/cerl_typean.erl
+++ /dev/null
@@ -1,994 +0,0 @@
-%% -*- erlang-indent-level: 4 -*-
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% @copyright 2001-2002 Richard Carlsson
-%% @author Richard Carlsson <carlsson.richard@gmail.com>
-%% @doc Type analysis of Core Erlang programs.
-
-%% TODO: filters must handle conjunctions for better precision!
-%% TODO: should get filters from patterns as well as guards.
-%% TODO: unused functions are being included in the analysis.
-
--module(cerl_typean).
-
--export([core_transform/2, analyze/1, pp_hook/0]).
-%%-export([analyze/2, analyze/5, annotate/1, annotate/2, annotate/5]).
-
--import(erl_types, [t_any/0, t_atom/0, t_atom_vals/1, t_binary/0,
- t_cons/2, t_cons_hd/1, t_cons_tl/1, t_float/0,
- t_fun/0, t_fun/2, t_from_range/2, t_from_term/1,
- t_inf/2, t_integer/0,
- t_is_any/1, t_is_atom/1, t_is_cons/1, t_is_list/1,
- t_is_maybe_improper_list/1, t_is_none/1, t_is_tuple/1,
- t_limit/2, t_list_elements/1, t_maybe_improper_list/0,
- t_none/0, t_number/0, t_pid/0, t_port/0, t_product/1,
- t_reference/0, t_sup/2, t_to_tlist/1, t_tuple/0, t_tuple/1,
- t_tuple_args/1, t_tuple_size/1, t_tuple_subtypes/1]).
-
--import(cerl, [ann_c_fun/3, ann_c_var/2, alias_pat/1, alias_var/1,
- apply_args/1, apply_op/1, atom_val/1, bitstr_size/1,
- bitstr_val/1, bitstr_type/1, bitstr_flags/1, binary_segments/1,
- c_letrec/2, c_nil/0,
- c_values/1, call_args/1, call_module/1, call_name/1,
- case_arg/1, case_clauses/1, catch_body/1, clause_body/1,
- clause_guard/1, clause_pats/1, concrete/1, cons_hd/1,
- cons_tl/1, fun_body/1, fun_vars/1, get_ann/1, int_val/1,
- is_c_atom/1, is_c_int/1, let_arg/1, let_body/1, let_vars/1,
- letrec_body/1, letrec_defs/1, module_defs/1,
- module_defs/1, module_exports/1, pat_vars/1,
- primop_args/1, primop_name/1, receive_action/1,
- receive_clauses/1, receive_timeout/1, seq_arg/1,
- seq_body/1, set_ann/2, try_arg/1, try_body/1,
- try_evars/1, try_handler/1, try_vars/1, tuple_arity/1,
- tuple_es/1, type/1, values_es/1, var_name/1]).
-
--import(cerl_trees, [get_label/1]).
-
--ifdef(DEBUG).
--define(ANNOTATE(X), case erl_types:t_to_string(X) of Q when length(Q) < 255 -> list_to_atom(Q); Q -> Q end).
--else.
--define(ANNOTATE(X), X).
--endif.
-
-%% Limit for type representation depth.
--define(DEF_LIMIT, 3).
-
-
-%% @spec core_transform(Module::cerl_records(), Options::[term()]) ->
-%% cerl_records()
-%%
-%% @doc Annotates a module represented by records with type
-%% information. See <code>annotate/1</code> for details.
-%%
-%% <p>Use the compiler option <code>{core_transform, cerl_typean}</code>
-%% to insert this function as a compilation pass.</p>
-%%
-%% @see module/2
-
--spec core_transform(cerl:cerl(), [term()]) -> cerl:cerl().
-
-core_transform(Code, _Opts) ->
- {Code1, _} = cerl_trees:label(cerl:from_records(Code)),
- %% io:fwrite("Running type analysis..."),
- %% {T1,_} = statistics(runtime),
- {Code2, _, _} = annotate(Code1),
- %% {T2,_} = statistics(runtime),
- %% io:fwrite("(~w ms).\n", [T2 - T1]),
- cerl:to_records(Code2).
-
-
-%% =====================================================================
-%% annotate(Tree) -> {Tree1, Type, Vars}
-%%
-%% Tree = cerl:cerl()
-%%
-%% Analyzes `Tree' (see `analyze') and appends terms `{type, Type}'
-%% to the annotation list of each fun-expression node and
-%% apply-expression node of `Tree', respectively, where `Labels' is
-%% an ordered-set list of labels of fun-expressions in `Tree',
-%% possibly also containing the atom `external', corresponding to
-%% the dependency information derived by the analysis. Any previous
-%% such annotations are removed from `Tree'. `Tree1' is the
-%% modified tree; for details on `OutList', `Outputs' ,
-%% `Dependencies' and `Escapes', see `analyze'.
-%%
-%% Note: `Tree' must be annotated with labels in order to use this
-%% function; see `analyze' for details.
-
-annotate(Tree) ->
- annotate(Tree, ?DEF_LIMIT).
-
-annotate(Tree, Limit) ->
- {_, _, Esc, Dep, Par} = cerl_closurean:analyze(Tree),
- annotate(Tree, Limit, Esc, Dep, Par).
-
-annotate(Tree, Limit, Esc, Dep, Par) ->
- {Type, Out, Vars} = analyze(Tree, Limit, Esc, Dep, Par),
- DelAnn = fun (T) -> set_ann(T, delete_ann(type, get_ann(T))) end,
- SetType = fun (T, Dict) ->
- case dict:find(get_label(T), Dict) of
- {ok, X} ->
- case t_is_any(X) of
- true ->
- DelAnn(T);
- false ->
- set_ann(T, append_ann(type,
- ?ANNOTATE(X),
- get_ann(T)))
- end;
- error ->
- DelAnn(T)
- end
- end,
- F = fun (T) ->
- case type(T) of
- var ->
- SetType(T, Vars);
- apply ->
- SetType(T, Out);
- call ->
- SetType(T, Out);
- primop ->
- SetType(T, Out);
- 'fun' ->
- SetType(T, Out);
- _ ->
- DelAnn(T)
- end
- end,
- {cerl_trees:map(F, Tree), Type, Vars}.
-
-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(_, []) ->
- [].
-
-
-%% =====================================================================
-%% analyze(Tree) -> {OutList, Outputs, Dependencies}
-%%
-%% Tree = cerl:cerl()
-%% OutList = [LabelSet] | none
-%% Outputs = dict(integer(), OutList)
-%% Dependencies = dict(integer(), LabelSet)
-%% LabelSet = ordset(Label)
-%% Label = integer() | external
-%%
-%% Analyzes a module or an expression represented by `Tree'.
-%%
-%% The returned `OutList' is a list of sets of labels of
-%% fun-expressions which correspond to the possible closures in the
-%% value list produced by `Tree' (viewed as an expression; the
-%% "value" of a module contains its exported functions). The atom
-%% `none' denotes missing or conflicting information.
-%%
-%% The atom `external' in any label set denotes any possible
-%% function outside `Tree', including those in `Escapes'.
-%%
-%% `Outputs' is a mapping from the labels of fun-expressions in
-%% `Tree' to corresponding lists of sets of labels of
-%% fun-expressions (or the atom `none'), representing the possible
-%% closures in the value lists returned by the respective
-%% functions.
-%%
-%% `Dependencies' is a similar mapping from the labels of
-%% fun-expressions and apply-expressions in `Tree' to sets of
-%% labels of corresponding fun-expressions which may contain call
-%% sites of the functions or be called from the call sites,
-%% respectively. Any such label not defined in `Dependencies'
-%% represents an unreachable function or a dead or faulty
-%% application.
-%%
-%% `Escapes' is the set of labels of fun-expressions in `Tree' such
-%% that corresponding closures may be accessed from outside `Tree'.
-%%
-%% Note: `Tree' must be annotated with labels (as done by the
-%% function `cerl_trees:label/1') in order to use this function.
-%% The label annotation `{label, L}' (where L should be an integer)
-%% must be the first element of the annotation list of each node in
-%% the tree. Instances of variables bound in `Tree' which denote
-%% the same variable must have the same label; apart from this,
-%% labels should be unique. Constant literals do not need to be
-%% labeled.
-
--record(state, {k, vars, out, dep, work, funs, envs}).
-
-%% Note: In order to keep our domain simple, we assume that all remote
-%% calls and primops return a single value, if any.
-
-%% We wrap the given syntax tree T in a fun-expression labeled `top',
-%% which is initially in the set of escaped labels. `top' will be
-%% visited at least once.
-%%
-%% We create a separate function labeled `external', defined as:
-%% "External = fun () -> Any", which will represent any and all
-%% functions outside T, and whose return value has unknown type.
-
--type label() :: integer() | 'external' | 'top'.
--type ordset(X) :: [X]. % XXX: TAKE ME OUT
--type labelset() :: ordset(label()).
--type outlist() :: [labelset()] | 'none'.
-
--spec analyze(cerl:cerl()) -> {outlist(), dict:dict(), dict:dict()}.
-
-analyze(Tree) ->
- analyze(Tree, ?DEF_LIMIT).
-
-analyze(Tree, Limit) ->
- {_, _, Esc, Dep, Par} = cerl_closurean:analyze(Tree),
- analyze(Tree, Limit, Esc, Dep, Par).
-
-analyze(Tree, Limit, Esc0, Dep0, Par) ->
- %% Note that we use different name spaces for variable labels and
- %% function/call site labels. We assume that the labeling of Tree
- %% only uses integers, not atoms.
- LabelExtL = [{label, external}],
- External = ann_c_var(LabelExtL, {external, 1}),
- ExtFun = ann_c_fun(LabelExtL, [], ann_c_var([{label, any}], 'Any')),
-%%% io:fwrite("external fun:\n~s.\n",
-%%% [cerl_prettypr:format(ExtFun, [noann, {paper, 80}])]),
- LabelTopL = [{label, top}],
- Top = ann_c_var(LabelTopL, {top, 0}),
- TopFun = ann_c_fun(LabelTopL, [], Tree),
-
- %% The "start fun" just makes the initialisation easier. It is not
- %% itself in the call graph.
- StartFun = ann_c_fun([{label, start}], [],
- c_letrec([{External, ExtFun}, {Top, TopFun}],
- c_nil())),
-%%% io:fwrite("start fun:\n~s.\n",
-%%% [cerl_prettypr:format(StartFun, [{paper, 80}])]),
-
- %% Gather a database of all fun-expressions in Tree and initialise
- %% their outputs and parameter variables. All escaping functions can
- %% receive any values as inputs. Also add an extra dependency edge
- %% from each fun-expression label to its parent fun-expression.
-%%% io:fwrite("Escape: ~p.\n",[Esc0]),
- Esc = sets:from_list(Esc0),
- Any = t_any(),
- None = t_none(),
- Funs0 = dict:new(),
- Vars0 = dict:store(any, Any, dict:new()),
- Out0 = dict:store(top, None,
- dict:store(external, None, dict:new())),
- Envs0 = dict:store(top, dict:new(),
- dict:store(external, dict:new(), dict:new())),
- F = fun (T, S = {Fs, Vs, Os, Es}) ->
- case type(T) of
- 'fun' ->
- L = get_label(T),
- As = fun_vars(T),
- X = case sets:is_element(L, Esc) of
- true -> Any;
- false -> None
- end,
- {dict:store(L, T, Fs),
- bind_vars_single(As, X, Vs),
- dict:store(L, None, Os),
- dict:store(L, dict:new(), Es)};
- _ ->
- S
- end
- end,
- {Funs, Vars, Out, Envs} = cerl_trees:fold(F, {Funs0, Vars0, Out0,
- Envs0}, StartFun),
-
- %% Add dependencies from funs to their parent funs.
- Dep = lists:foldl(fun ({L, L1}, D) -> add_dep(L, L1, D) end,
- Dep0, dict:to_list(Par)),
-
- %% Enter the fixpoint iteration at the StartFun.
- St = loop(TopFun, top, #state{vars = Vars,
- out = Out,
- dep = Dep,
- work = init_work(),
- funs = Funs,
- envs = Envs,
- k = Limit}),
- {dict:fetch(top, St#state.out),
- tidy_dict([top, external], St#state.out),
- tidy_dict([any], St#state.vars)}.
-
-tidy_dict([X | Xs], D) ->
- tidy_dict(Xs, dict:erase(X, D));
-tidy_dict([], D) ->
- D.
-
-loop(T, L, St0) ->
-%%% io:fwrite("analyzing: ~w.\n",[L]),
-%%% io:fwrite("work: ~w.\n", [Queue0]),
- Env = dict:fetch(L, St0#state.envs),
- X0 = dict:fetch(L, St0#state.out),
- {X1, St1} = visit(fun_body(T), Env, St0),
- X = limit(X1, St1#state.k),
- {W, M} = case equal(X0, X) of
- true ->
- {St1#state.work, St1#state.out};
- false ->
-%%% io:fwrite("out (~w) changed: ~s <- ~s.\n",
-%%% [L, erl_types:t_to_string(X),
-%%% erl_types:t_to_string(X0)]),
- M1 = dict:store(L, X, St1#state.out),
- case dict:find(L, St1#state.dep) of
- {ok, S} ->
-%%% io:fwrite("adding work: ~w.\n", [S]),
- {add_work(S, St1#state.work), M1};
- error ->
- {St1#state.work, M1}
- end
- end,
- St2 = St1#state{out = M},
- case take_work(W) of
- {ok, L1, W1} ->
- T1 = dict:fetch(L1, St2#state.funs),
- loop(T1, L1, St2#state{work = W1});
- none ->
- St2
- end.
-
-visit(T, Env, St) ->
- case type(T) of
- literal ->
- {t_from_term(concrete(T)), St};
- var ->
- %% If a variable is not already in the store at this point,
- %% we initialize it to 'none()'.
- L = get_label(T),
- Vars = St#state.vars,
- case dict:find(L, Vars) of
- {ok, X} ->
- case dict:find(var_name(T), Env) of
- {ok, X1} ->
-%%% io:fwrite("filtered variable reference: ~w:~s.\n",
-%%% [var_name(T), erl_types:t_to_string(X1)]),
- {meet(X, X1), St};
- error ->
- {X, St}
- end;
- error ->
- X = t_none(),
- Vars1 = dict:store(L, X, Vars),
- St1 = St#state{vars = Vars1},
- {X, St1}
- end;
- 'fun' ->
- %% Must revisit the fun also, because its environment might
- %% have changed. (We don't keep track of such dependencies.)
- L = get_label(T),
- Xs = [dict:fetch(get_label(V), St#state.vars)
- || V <- fun_vars(T)],
- X = dict:fetch(L, St#state.out),
- St1 = St#state{work = add_work([L], St#state.work),
- envs = dict:store(L, Env, St#state.envs)},
- {t_fun(Xs, X), St1};
- values ->
- {Xs, St1} = visit_list(values_es(T), Env, St),
- {t_product(Xs), St1};
- cons ->
- {[X1, X2], St1} = visit_list([cons_hd(T), cons_tl(T)], Env, St),
- {t_cons(X1, X2), St1};
- tuple ->
- {Xs, St1} = visit_list(tuple_es(T), Env, St),
- {t_tuple(Xs), St1};
- 'let' ->
- {X, St1} = visit(let_arg(T), Env, St),
- LetVars = let_vars(T),
- St1Vars = St1#state.vars,
- Vars = case t_is_any(X) orelse t_is_none(X) of
- true ->
- bind_vars_single(LetVars, X, St1Vars);
- false ->
- bind_vars(LetVars, t_to_tlist(X), St1Vars)
- end,
- visit(let_body(T), Env, St1#state{vars = Vars});
- seq ->
- {_, St1} = visit(seq_arg(T), Env, St),
- visit(seq_body(T), Env, St1);
- apply ->
- {_F, St1} = visit(apply_op(T), Env, St),
- {As, St2} = visit_list(apply_args(T), Env, St1),
- L = get_label(T),
- Ls = get_deps(L, St#state.dep),
- Out = St2#state.out,
- X = join_list([dict:fetch(L1, Out) || L1 <- Ls]),
- Out1 = dict:store(L, X, Out),
- {X, call_site(Ls, As, St2#state{out = Out1})};
- call ->
- M = call_module(T),
- F = call_name(T),
- As = call_args(T),
- {[X1, X2], St1} = visit_list([M, F], Env, St),
- {Xs, St2} = visit_list(As, Env, St1),
-%%% io:fwrite("call: ~w:~w(~w).\n",[X1,X2,Xs]),
- X = case {t_atom_vals(X1), t_atom_vals(X2)} of
- {[M1], [F1]} ->
- A = length(As),
-%%% io:fwrite("known call: ~w:~w/~w.\n",
-%%% [M1, F1, A]),
- call_type(M1, F1, A, Xs);
- _ ->
- t_any()
- end,
- L = get_label(T),
- {X, St2#state{out = dict:store(L, X, St2#state.out)}};
- primop ->
- As = primop_args(T),
- {Xs, St1} = visit_list(As, Env, St),
- F = atom_val(primop_name(T)),
- A = length(As),
- L = get_label(T),
- X = primop_type(F, A, Xs),
- {X, St1#state{out = dict:store(L, X, St1#state.out)}};
- 'case' ->
- {X, St1} = visit(case_arg(T), Env, St),
- Xs = case t_is_any(X) orelse t_is_none(X) of
- true ->
- [X || _ <- cerl:case_clauses(T)];
- false ->
- t_to_tlist(X)
- end,
- join_visit_clauses(Xs, case_clauses(T), Env, St1);
- 'receive' ->
- Any = t_any(),
- {X1, St1} = join_visit_clauses([Any], receive_clauses(T),
- Env, St),
- {X2, St2} = visit(receive_timeout(T), Env, St1),
- case t_is_atom(X2) andalso (t_atom_vals(X2) =:= [infinity]) of
- true ->
- {X1, St2};
- false ->
- {X3, St3} = visit(receive_action(T), Env, St2),
- {join(X1, X3), St3}
- end;
- 'try' ->
- {X, St1} = visit(try_arg(T), Env, St),
- Any = t_any(),
- Atom = t_atom(),
- TryVars = try_vars(T),
- St1Vars = St1#state.vars,
- Vars = case t_is_any(X) orelse t_is_none(X) of
- true ->
- bind_vars_single(TryVars, X, St1Vars);
- false ->
- bind_vars(TryVars, t_to_tlist(X), St1Vars)
- end,
- {X1, St2} = visit(try_body(T), Env, St1#state{vars = Vars}),
- EVars = bind_vars(try_evars(T), [Atom, Any, Any], St2#state.vars),
- {X2, St3} = visit(try_handler(T), Env, St2#state{vars = EVars}),
- {join(X1, X2), St3};
- 'catch' ->
- {_, St1} = visit(catch_body(T), Env, St),
- {t_any(), St1};
- binary ->
- {_, St1} = visit_list(binary_segments(T), Env, St),
- {t_binary(), St1};
- bitstr ->
- %% The other fields are constant literals.
- {_, St1} = visit(bitstr_val(T), Env, St),
- {_, St2} = visit(bitstr_size(T), Env, St1),
- {t_none(), St2};
- letrec ->
- %% All the bound funs should be revisited, because the
- %% environment might have changed.
- Vars = bind_defs(letrec_defs(T), St#state.vars,
- St#state.out),
- Ls = [get_label(F) || {_, F} <- letrec_defs(T)],
- St1 = St#state{work = add_work(Ls, St#state.work),
- vars = Vars},
- visit(letrec_body(T), Env, St1);
- module ->
- %% We handle a module as a sequence of function variables in
- %% the body of a `letrec'.
- {_, St1} = visit(c_letrec(module_defs(T),
- c_values(module_exports(T))),
- Env, St),
- {t_none(), St1}
- end.
-
-visit_clause(T, Xs, Env, St) ->
- Env1 = Env,
- Vars = bind_pats(clause_pats(T), Xs, St#state.vars),
- G = clause_guard(T),
- {_, St1} = visit(G, Env1, St#state{vars = Vars}),
- Env2 = guard_filters(G, Env1),
- visit(clause_body(T), Env2, St1).
-
-%% We assume correct value-list typing.
-
-visit_list([T | Ts], Env, St) ->
- {X, St1} = visit(T, Env, St),
- {Xs, St2} = visit_list(Ts, Env, St1),
- {[X | Xs], St2};
-visit_list([], _Env, St) ->
- {[], St}.
-
-join_visit_clauses(Xs, [T | Ts], Env, St) ->
- {X1, St1} = visit_clause(T, Xs, Env, St),
- {X2, St2} = join_visit_clauses(Xs, Ts, Env, St1),
- {join(X1, X2), St2};
-join_visit_clauses(_, [], _Env, St) ->
- {t_none(), St}.
-
-bind_defs([{V, F} | Ds], Vars, Out) ->
- Xs = [dict:fetch(get_label(V1), Vars) || V1 <- fun_vars(F)],
- X = dict:fetch(get_label(F), Out),
- bind_defs(Ds, dict:store(get_label(V), t_fun(Xs, X), Vars), Out);
-bind_defs([], Vars, _Out) ->
- Vars.
-
-bind_pats(Ps, Xs, Vars) ->
- if length(Xs) =:= length(Ps) ->
- bind_pats_list(Ps, Xs, Vars);
- true ->
- bind_pats_single(Ps, t_none(), Vars)
- end.
-
-bind_pats_list([P | Ps], [X | Xs], Vars) ->
- Vars1 = bind_pat_vars(P, X, Vars),
- bind_pats_list(Ps, Xs, Vars1);
-bind_pats_list([], [], Vars) ->
- Vars.
-
-bind_pats_single([P | Ps], X, Vars) ->
- bind_pats_single(Ps, X, bind_pat_vars(P, X, Vars));
-bind_pats_single([], _X, Vars) ->
- Vars.
-
-bind_pat_vars(P, X, Vars) ->
- case type(P) of
- var ->
- dict:store(get_label(P), X, Vars);
- literal ->
- Vars;
- cons ->
- case t_is_cons(X) of
- true ->
- %% If X is "nonempty proper list of X1", then the
- %% head has type X1 and the tail has type "proper
- %% list of X1". (If X is just "cons cell of X1",
- %% then both head and tail have type X1.)
- Vars1 = bind_pat_vars(cons_hd(P), t_cons_hd(X),
- Vars),
- bind_pat_vars(cons_tl(P), t_cons_tl(X), Vars1);
- false ->
- case t_is_list(X) of
- true ->
- %% If X is "proper list of X1", then the
- %% head has type X1 and the tail has type
- %% "proper list of X1", i.e., type X.
- Vars1 = bind_pat_vars(cons_hd(P),
- t_list_elements(X),
- Vars),
- bind_pat_vars(cons_tl(P), X, Vars1);
- false ->
- case t_is_maybe_improper_list(X) of
- true ->
- %% If X is "cons cell of X1", both
- %% the head and tail have type X1.
- X1 = t_list_elements(X),
- Vars1 = bind_pat_vars(cons_hd(P),
- X1, Vars),
- bind_pat_vars(cons_tl(P), X1,
- Vars1);
- false ->
- bind_vars_single(pat_vars(P),
- top_or_bottom(X),
- Vars)
- end
- end
- end;
- tuple ->
- case t_is_tuple(X) of
- true ->
- case t_tuple_subtypes(X) of
- unknown ->
- bind_vars_single(pat_vars(P), top_or_bottom(X),
- Vars);
- [Tuple] ->
- case t_tuple_size(Tuple) =:= tuple_arity(P) of
- true ->
- bind_pats_list(tuple_es(P),
- t_tuple_args(Tuple), Vars);
-
- false ->
- bind_vars_single(pat_vars(P),
- top_or_bottom(X), Vars)
- end;
- List when is_list(List) ->
- bind_vars_single(pat_vars(P), top_or_bottom(X),
- Vars)
- end;
- false ->
- bind_vars_single(pat_vars(P), top_or_bottom(X), Vars)
- end;
- binary ->
- bind_pats_single(binary_segments(P), t_none(), Vars);
- bitstr ->
- %% Only the Value field is a new binding. Size is already
- %% bound, and the other fields are constant literals.
- %% We could create a filter for Size being an integer().
- Size = bitstr_size(P),
- ValType =
- case concrete(bitstr_type(P)) of
- float -> t_float();
- binary -> t_binary();
- integer ->
- case is_c_int(Size) of
- false -> t_integer();
- true ->
- SizeVal = int_val(Size),
- Flags = concrete(bitstr_flags(P)),
- case lists:member(signed, Flags) of
- true ->
- t_from_range(-(1 bsl (SizeVal - 1)),
- 1 bsl (SizeVal - 1) - 1);
- false ->
- t_from_range(0,1 bsl SizeVal - 1)
- end
- end
- end,
- bind_pat_vars(bitstr_val(P), ValType, Vars);
- alias ->
- P1 = alias_pat(P),
- Vars1 = bind_pat_vars(P1, X, Vars),
- dict:store(get_label(alias_var(P)), pat_type(P1, Vars1),
- Vars1)
- end.
-
-pat_type(P, Vars) ->
- case type(P) of
- var ->
- dict:fetch(get_label(P), Vars);
- literal ->
- t_from_term(concrete(P));
- cons ->
- t_cons(pat_type(cons_hd(P), Vars),
- pat_type(cons_tl(P), Vars));
- tuple ->
- t_tuple([pat_type(E, Vars) || E <- tuple_es(P)]);
- binary ->
- t_binary();
- alias ->
- pat_type(alias_pat(P), Vars)
- end.
-
-bind_vars(Vs, Xs, Vars) ->
- if length(Vs) =:= length(Xs) ->
- bind_vars_list(Vs, Xs, Vars);
- true ->
- bind_vars_single(Vs, t_none(), Vars)
- end.
-
-bind_vars_list([V | Vs], [X | Xs], Vars) ->
- bind_vars_list(Vs, Xs, dict:store(get_label(V), X, Vars));
-bind_vars_list([], [], Vars) ->
- Vars.
-
-bind_vars_single([V | Vs], X, Vars) ->
- bind_vars_single(Vs, X, dict:store(get_label(V), X, Vars));
-bind_vars_single([], _X, Vars) ->
- Vars.
-
-add_dep(Source, Target, Deps) ->
- case dict:find(Source, Deps) of
- {ok, X} ->
- case set__is_member(Target, X) of
- true ->
- Deps;
- false ->
-%%% io:fwrite("new dep: ~w <- ~w.\n", [Target, Source]),
- dict:store(Source, set__add(Target, X), Deps)
- end;
- error ->
-%%% io:fwrite("new dep: ~w <- ~w.\n", [Target, Source]),
- dict:store(Source, set__singleton(Target), Deps)
- end.
-
-%% This handles a call site, updating parameter variables with respect
-%% to the actual parameters.
-
-call_site(Ls, Xs, St) ->
-%% io:fwrite("call site: ~w ~s.\n",
-%% [Ls, erl_types:t_to_string(erl_types:t_product(Xs))]),
- {W, V} = call_site(Ls, Xs, St#state.work, St#state.vars,
- St#state.funs, St#state.k),
- St#state{work = W, vars = V}.
-
-call_site([L | Ls], Xs, W, V, Fs, Limit) ->
- Vs = fun_vars(dict:fetch(L, Fs)),
- case bind_args(Vs, Xs, V, Limit) of
- {V1, true} ->
- call_site(Ls, Xs, add_work([L], W), V1, Fs, Limit);
- {V1, false} ->
- call_site(Ls, Xs, W, V1, Fs, Limit)
- end;
-call_site([], _, W, V, _, _) ->
- {W, V}.
-
-%% If the arity does not match the call, nothing is done here.
-
-bind_args(Vs, Xs, Vars, Limit) ->
- if length(Vs) =:= length(Xs) ->
- bind_args(Vs, Xs, Vars, Limit, false);
- true ->
- {Vars, false}
- end.
-
-bind_args([V | Vs], [X | Xs], Vars, Limit, Ch) ->
- L = get_label(V),
- {Vars1, Ch1} = bind_arg(L, X, Vars, Limit, Ch),
- bind_args(Vs, Xs, Vars1, Limit, Ch1);
-bind_args([], [], Vars, _Limit, Ch) ->
- {Vars, Ch}.
-
-%% bind_arg(L, X, Vars, Limit) ->
-%% bind_arg(L, X, Vars, Limit, false).
-
-bind_arg(L, X, Vars, Limit, Ch) ->
- X0 = dict:fetch(L, Vars),
- X1 = limit(join(X, X0), Limit),
- case equal(X0, X1) of
- true ->
- {Vars, Ch};
- false ->
-%%% io:fwrite("arg (~w) changed: ~s <- ~s + ~s.\n",
-%%% [L, erl_types:t_to_string(X1),
-%%% erl_types:t_to_string(X0),
-%%% erl_types:t_to_string(X)]),
- {dict:store(L, X1, Vars), true}
- end.
-
-%% Domain: type(), defined in module `erl_types'.
-
-meet(X, Y) -> t_inf(X, Y).
-
-join(X, Y) -> t_sup(X, Y).
-
-join_list([Xs | Xss]) ->
- join(Xs, join_list(Xss));
-join_list([]) ->
- t_none().
-
-equal(X, Y) -> X =:= Y.
-
-limit(X, K) -> t_limit(X, K).
-
-top_or_bottom(T) ->
- case t_is_none(T) of
- true ->
- T;
- false ->
- t_any()
- end.
-
-strict(Xs, T) ->
- case erl_types:any_none(Xs) of
- true ->
- t_none();
- false ->
- T
- end.
-
-%% Set abstraction for label sets.
-
-%% set__new() -> [].
-
-set__singleton(X) -> [X].
-
-%% set__to_list(S) -> S.
-
-%% set__from_list(S) -> ordsets:from_list(S).
-
-%% set__union(X, Y) -> ordsets:union(X, Y).
-
-set__add(X, S) -> ordsets:add_element(X, S).
-
-set__is_member(X, S) -> ordsets:is_element(X, S).
-
-%% set__subtract(X, Y) -> ordsets:subtract(X, Y).
-
-%% set__equal(X, Y) -> X =:= Y.
-
-%% A simple but efficient functional queue.
-
-queue__new() -> {[], []}.
-
-queue__put(X, {In, Out}) -> {[X | In], Out}.
-
-queue__get({In, [X | Out]}) -> {ok, X, {In, Out}};
-queue__get({[], _}) -> empty;
-queue__get({In, _}) ->
- [X | In1] = lists:reverse(In),
- {ok, X, {[], In1}}.
-
-%% The work list - a queue without repeated elements.
-
-init_work() ->
- {queue__put(external, queue__new()), sets:new()}.
-
-add_work(Ls, {Q, Set}) ->
- add_work(Ls, Q, Set).
-
-%% Note that the elements are enqueued in order.
-
-add_work([L | Ls], Q, Set) ->
- case sets:is_element(L, Set) of
- true ->
- add_work(Ls, Q, Set);
- false ->
- add_work(Ls, queue__put(L, Q), sets:add_element(L, Set))
- end;
-add_work([], Q, Set) ->
- {Q, Set}.
-
-take_work({Queue0, Set0}) ->
- case queue__get(Queue0) of
- {ok, L, Queue1} ->
- Set1 = sets:del_element(L, Set0),
- {ok, L, {Queue1, Set1}};
- empty ->
- none
- end.
-
-get_deps(L, Dep) ->
- case dict:find(L, Dep) of
- {ok, Ls} -> Ls;
- error -> []
- end.
-
-%% Type information for built-in functions. We do not check that the
-%% arguments have the correct type; if the call would actually fail,
-%% rather than return a value, this is a safe overapproximation.
-
-primop_type(match_fail, 1, _) -> t_none();
-primop_type(_, _, Xs) -> strict(Xs, t_any()).
-
-call_type(M, F, A, Xs) ->
- erl_bif_types:type(M, F, A, Xs).
-
-guard_filters(T, Env) ->
- guard_filters(T, Env, dict:new()).
-
-guard_filters(T, Env, Vars) ->
- case type(T) of
- call ->
- M = call_module(T),
- F = call_name(T),
- case is_c_atom(M) andalso is_c_atom(F) of
- true ->
- As = call_args(T),
- case {atom_val(M), atom_val(F), length(As)} of
- {erlang, 'and', 2} ->
- [A1, A2] = As,
- guard_filters(A1, guard_filters(A2, Env));
- {erlang, is_atom, 1} ->
- filter(As, t_atom(), Env);
- {erlang, is_binary, 1} ->
- filter(As, t_binary(), Env);
- {erlang, is_float, 1} ->
- filter(As, t_float(), Env);
- {erlang, is_function, 1} ->
- filter(As, t_fun(), Env);
- {erlang, is_integer, 1} ->
- filter(As, t_integer(), Env);
- {erlang, is_list, 1} ->
- filter(As, t_maybe_improper_list(), Env);
- {erlang, is_number, 1} ->
- filter(As, t_number(), Env);
- {erlang, is_pid, 1} ->
- filter(As, t_pid(), Env);
- {erlang, is_port, 1} ->
- filter(As, t_port(), Env);
- {erlang, is_reference, 1} ->
- filter(As, t_reference(), Env);
- {erlang, is_tuple, 1} ->
- filter(As, t_tuple(), Env);
- _ ->
- Env
- end;
- false ->
- Env
- end;
- var ->
- case dict:find(var_name(T), Vars) of
- {ok, T1} ->
- guard_filters(T1, Env, Vars);
- error ->
- Env
- end;
- 'let' ->
- case let_vars(T) of
- [V] ->
- guard_filters(let_body(T), Env,
- dict:store(var_name(V), let_arg(T),
- Vars));
- _ ->
- Env
- end;
- values ->
- case values_es(T) of
- [T1] ->
- guard_filters(T1, Env, Vars);
- _ ->
- Env
- end;
- _ ->
- Env
- end.
-
-filter(As, X, Env) ->
- [A] = As,
- case type(A) of
- var ->
- V = var_name(A),
- case dict:find(V, Env) of
- {ok, X1} ->
- dict:store(V, meet(X, X1), Env);
- error ->
- dict:store(V, X, Env)
- end;
- _ ->
- Env
- end.
-
-%% Callback hook for cerl_prettypr:
-
--spec pp_hook() -> fun((cerl:cerl(), _, fun((_,_) -> any())) -> any()).
-
-pp_hook() ->
- fun pp_hook/3.
-
-pp_hook(Node, Ctxt, Cont) ->
- As = cerl:get_ann(Node),
- As1 = proplists:delete(type, proplists:delete(label, As)),
- As2 = proplists:delete(typesig, proplists:delete(file, As1)),
- D = Cont(cerl:set_ann(Node, []), Ctxt),
- T = case proplists:lookup(type, As) of
- {type, T0} -> T0;
- none ->
- case proplists:lookup(typesig, As) of
- {typesig, T0} -> T0;
- none -> t_any()
- end
- end,
- D1 = case erl_types:t_is_any(T) of
- true ->
- D;
- false ->
- case cerl:is_literal(Node) of
- true ->
- D;
- false ->
- S = erl_types:t_to_string(T),
- Q = prettypr:beside(prettypr:text("::"),
- prettypr:text(S)),
- prettypr:beside(D, Q)
- end
- end,
- cerl_prettypr:annotate(D1, As2, Ctxt).
-
-%% =====================================================================
diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src
index a22f8acd85..f9c7304b9f 100644
--- a/lib/dialyzer/src/dialyzer.app.src
+++ b/lib/dialyzer/src/dialyzer.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,15 +22,12 @@
{application, dialyzer,
[{description, "DIscrepancy AnaLYZer of ERlang programs, version %VSN%"},
{vsn, "%VSN%"},
- {modules, [cerl_closurean,
- cerl_lib,
- cerl_pmatch,
- cerl_prettypr,
- cerl_typean,
+ {modules, [cerl_prettypr,
dialyzer,
dialyzer_analysis_callgraph,
dialyzer_behaviours,
dialyzer_callgraph,
+ dialyzer_typegraph,
dialyzer_cl,
dialyzer_cl_parse,
dialyzer_clean_core,
@@ -44,8 +41,6 @@
dialyzer_gui_wx,
dialyzer_options,
dialyzer_plt,
- dialyzer_race_data_server,
- dialyzer_races,
dialyzer_succ_typings,
dialyzer_typesig,
dialyzer_utils,
@@ -53,10 +48,11 @@
dialyzer_worker,
erl_bif_types,
erl_types,
- typer]},
+ typer,
+ typer_core]},
{registered, []},
{applications, [compiler, kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.4",
- "kernel-5.3","erts-9.0",
- "compiler-7.0"]}]}.
+ {runtime_dependencies, ["wx-2.0","syntax_tools-2.0","stdlib-3.15",
+ "kernel-8.0","erts-12.0",
+ "compiler-8.0"]}]}.
diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl
index ddd08e8679..83d3c03e7e 100644
--- a/lib/dialyzer/src/dialyzer.erl
+++ b/lib/dialyzer/src/dialyzer.erl
@@ -503,10 +503,6 @@ message_to_string({opaque_size, [SizeType, Size]}, I, _E) ->
message_to_string({opaque_call, [M, F, Args, Culprit, OpaqueType]}, I, _E) ->
io_lib:format("The call ~s:~ts~ts breaks the opacity of the term ~ts :: ~ts\n",
[M, F, a(Args, I), c(Culprit, I), t(OpaqueType, I)]);
-%%----- Warnings for concurrency errors --------------------
-message_to_string({race_condition, [M, F, Args, Reason]}, I, _E) ->
- %% There is a possibly huge type in Reason.
- io_lib:format("The call ~w:~tw~ts ~ts\n", [M, F, a(Args, I), Reason]);
%%----- Warnings for behaviour errors --------------------
message_to_string({callback_type_mismatch, [B, F, A, ST, CT]}, I, _E) ->
io_lib:format("The inferred return type of ~tw/~w ~ts has nothing in"
@@ -532,6 +528,9 @@ message_to_string({callback_spec_arg_type_mismatch, [B, F, A, N, ST, CT]},
message_to_string({callback_missing, [B, F, A]}, _I, _E) ->
io_lib:format("Undefined callback function ~tw/~w (behaviour ~w)\n",
[F, A, B]);
+message_to_string({callback_not_exported, [B, F, A]}, _I, _E) ->
+ io_lib:format("Callback function ~tw/~w exists but is not exported (behaviour ~w)\n",
+ [F, A, B]);
message_to_string({callback_info_missing, [B]}, _I, _E) ->
io_lib:format("Callback info about the ~w behaviour is not available\n", [B]);
%%----- Warnings for unknown functions, types, and behaviours -------------
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl
index 3ca63881d3..8f96de884e 100644
--- a/lib/dialyzer/src/dialyzer.hrl
+++ b/lib/dialyzer/src/dialyzer.hrl
@@ -46,11 +46,12 @@
-define(WARN_CONTRACT_SYNTAX, warn_contract_syntax).
-define(WARN_CONTRACT_NOT_EQUAL, warn_contract_not_equal).
-define(WARN_CONTRACT_SUBTYPE, warn_contract_subtype).
+-define(WARN_CONTRACT_MISSING_RETURN, warn_contract_missing_return).
-define(WARN_CONTRACT_SUPERTYPE, warn_contract_supertype).
+-define(WARN_CONTRACT_EXTRA_RETURN, warn_contract_extra_return).
-define(WARN_CONTRACT_RANGE, warn_contract_range).
-define(WARN_CALLGRAPH, warn_callgraph).
-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).
-define(WARN_UNKNOWN, warn_unknown).
@@ -69,7 +70,7 @@
| ?WARN_FUN_APP | ?WARN_MAP_CONSTRUCTION
| ?WARN_MATCHING | ?WARN_NON_PROPER_LIST
| ?WARN_NOT_CALLED | ?WARN_OPAQUE
- | ?WARN_RACE_CONDITION | ?WARN_RETURN_NO_RETURN
+ | ?WARN_RETURN_NO_RETURN
| ?WARN_RETURN_ONLY_EXIT | ?WARN_UNDEFINED_CALLBACK
| ?WARN_UNKNOWN | ?WARN_UNMATCHED_RETURN.
@@ -124,12 +125,15 @@
| 'no_undefined_callbacks'
| 'no_underspecs'
| 'no_unused'
- | 'race_conditions'
| 'underspecs'
| 'unknown'
| 'unmatched_returns'
| 'overspecs'
- | 'specdiffs'.
+ | 'specdiffs'
+ | 'extra_return'
+ | 'no_extra_return'
+ | 'missing_return'
+ | 'no_missing_return'.
-type dial_option() :: {'files', [FileName :: file:filename()]}
| {'files_rec', [DirName :: file:filename()]}
| {'defines', [{Macro :: atom(), Value :: term()}]}
@@ -168,6 +172,7 @@
-define(ERROR_LOCATION, column).
-type doc_plt() :: 'undefined' | dialyzer_plt:plt().
+-record(plt_info, {files :: [dialyzer_plt:file_md5()], mod_deps :: dict:dict()}).
-record(analysis, {analysis_pid :: pid() | 'undefined',
type = succ_typings :: anal_type(),
@@ -178,7 +183,6 @@
start_from = byte_code :: start_from(),
plt :: dialyzer_plt:plt(),
use_contracts = true :: boolean(),
- race_detection = false :: boolean(),
behaviours_chk = false :: boolean(),
timing = false :: boolean() | 'debug',
timing_server = none :: dialyzer_timing:timing_server(),
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index 898ed26daf..ee795a54dc 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -68,9 +68,8 @@
start(Parent, LegalWarnings, Analysis) ->
TimingServer = dialyzer_timing:init(Analysis#analysis.timing),
- RacesOn = ordsets:is_element(?WARN_RACE_CONDITION, LegalWarnings),
Analysis0 =
- Analysis#analysis{race_detection = RacesOn, timing_server = TimingServer},
+ Analysis#analysis{timing_server = TimingServer},
Analysis1 = expand_files(Analysis0),
Analysis2 = run_analysis(Analysis1, LegalWarnings),
State = #server_state{parent = Parent},
@@ -132,7 +131,7 @@ analysis_start(Parent, Analysis, LegalWarnings) ->
solvers = Analysis#analysis.solvers
},
Files = ordsets:from_list(Analysis#analysis.files),
- {Callgraph, TmpCServer0} = compile_and_store(Files, State),
+ {Callgraph, ModCallDeps, Modules, TmpCServer0} = compile_and_store(Files, State),
%% Remote type postprocessing
Args = {Plt, Analysis, Parent},
NewCServer = remote_type_postprocessing(TmpCServer0, Args),
@@ -143,19 +142,16 @@ analysis_start(Parent, Analysis, LegalWarnings) ->
Plt1 = dialyzer_plt:insert_callbacks(Plt1_a, NewCServer),
State1 = State#analysis_state{codeserver = NewCServer, plt = Plt1},
Exports = dialyzer_codeserver:get_exports(NewCServer),
- NonExports = sets:subtract(sets:from_list(AllNodes), Exports),
+ NonExports = sets:subtract(sets:from_list(AllNodes, [{version, 2}]), Exports),
NonExportsList = sets:to_list(NonExports),
- NewCallgraph =
- case Analysis#analysis.race_detection of
- true -> dialyzer_callgraph:put_race_detection(true, Callgraph);
- false -> Callgraph
- end,
- State2 = analyze_callgraph(NewCallgraph, State1),
+ State2 = analyze_callgraph(Callgraph, State1),
+ ModTypeDeps = dict:from_list(maps:to_list(dialyzer_typegraph:module_type_deps(Analysis#analysis.use_contracts, CServer, Modules))),
+ ModDeps = dialyzer_callgraph:merge_module_deps(ModCallDeps, ModTypeDeps),
+ send_mod_deps(Parent, ModDeps),
#analysis_state{plt = Plt2,
doc_plt = DocPlt,
codeserver = Codeserver0} = State2,
{Codeserver, Plt3} = move_data(Codeserver0, Plt2),
- dialyzer_callgraph:dispose_race_server(NewCallgraph),
%% Since the PLT is never used, a dummy is sent:
DummyPlt = dialyzer_plt:new(),
send_codeserver_plt(Parent, Codeserver, DummyPlt),
@@ -240,16 +236,16 @@ analyze_callgraph(Callgraph, #analysis_state{codeserver = Codeserver,
plt_build ->
NewPlt =
dialyzer_succ_typings:analyze_callgraph(Callgraph, Plt, Codeserver,
- TimingServer, Solvers, Parent),
+ TimingServer, Solvers),
dialyzer_callgraph:delete(Callgraph),
State#analysis_state{plt = NewPlt, doc_plt = DocPlt};
succ_typings ->
{Warnings, NewPlt, NewDocPlt} =
dialyzer_succ_typings:get_warnings(Callgraph, Plt, DocPlt, Codeserver,
- TimingServer, Solvers, Parent),
+ TimingServer, Solvers),
dialyzer_callgraph:delete(Callgraph),
Warnings1 = filter_warnings(Warnings, Codeserver),
- send_warnings(State#analysis_state.parent, Warnings1),
+ send_warnings(Parent, Warnings1),
State#analysis_state{plt = NewPlt, doc_plt = NewDocPlt}
end.
@@ -315,13 +311,13 @@ compile_and_store(Files, #analysis_state{codeserver = CServer,
{T2, _} = statistics(wall_clock),
Msg1 = io_lib:format("done in ~.2f secs\nRemoving edges... ", [(T2-T1)/1000]),
send_log(Parent, Msg1),
- Callgraph =
+ {ModCallDeps, Callgraph} =
?timing(Timing, "clean", _C2,
cleanup_callgraph(State, CServer2, Callgraph, Modules)),
{T3, _} = statistics(wall_clock),
Msg2 = io_lib:format("done in ~.2f secs\n", [(T3-T2)/1000]),
send_log(Parent, Msg2),
- {Callgraph, CServer2}.
+ {Callgraph, ModCallDeps, Modules, CServer2}.
-opaque compile_init_data() :: #compile_init{}.
-type error_reason() :: string().
@@ -374,15 +370,14 @@ cleanup_callgraph(#analysis_state{plt = InitPlt, parent = Parent,
codeserver = CodeServer
},
CServer, Callgraph, Modules) ->
- ModuleDeps = dialyzer_callgraph:module_deps(Callgraph),
- send_mod_deps(Parent, ModuleDeps),
+ ModCallDeps = dialyzer_callgraph:module_call_deps(Callgraph),
{Callgraph1, ExtCalls} = dialyzer_callgraph:remove_external(Callgraph),
ExtCalls1 = [Call || Call = {_From, To} <- ExtCalls,
not dialyzer_plt:contains_mfa(InitPlt, To)],
{BadCalls1, RealExtCalls} =
if ExtCalls1 =:= [] -> {[], []};
true ->
- ModuleSet = sets:from_list(Modules),
+ ModuleSet = sets:from_list(Modules, [{version, 2}]),
PltModuleSet = dialyzer_plt:all_modules(InitPlt),
AllModules = sets:union(ModuleSet, PltModuleSet),
Pred = fun({_From, {M, _F, _A}}) -> sets:is_element(M, AllModules) end,
@@ -402,7 +397,7 @@ cleanup_callgraph(#analysis_state{plt = InitPlt, parent = Parent,
{From, To} <- RealExtCalls],
send_ext_calls(Parent, ExtCallsWithFileAndLocation)
end,
- Callgraph1.
+ {ModCallDeps, Callgraph1}.
compile_src(File, Includes, Defines, Callgraph, CServer, UseContracts,
LegalWarnings) ->
@@ -475,7 +470,7 @@ get_exported_types_from_core(Core) ->
cerl:concrete(L1) =:= 'export_type'],
ExpTypes2 = lists:flatten(ExpTypes1),
M = cerl:atom_val(cerl:module_name(Core)),
- sets:from_list([{M, F, A} || {F, A} <- ExpTypes2]).
+ sets:from_list([{M, F, A} || {F, A} <- ExpTypes2], [{version, 2}]).
get_exports_from_core(Core) ->
Tree = cerl:from_records(Core),
diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl
index 4be84502a1..d5c8ac0886 100644
--- a/lib/dialyzer/src/dialyzer_behaviours.erl
+++ b/lib/dialyzer/src/dialyzer_behaviours.erl
@@ -22,7 +22,7 @@
-module(dialyzer_behaviours).
--export([check_callbacks/5]).
+-export([check_callbacks/5, get_behaviours/1]).
-export_type([behaviour/0]).
@@ -39,7 +39,7 @@
-record(state, {plt :: dialyzer_plt:plt(),
codeserver :: dialyzer_codeserver:codeserver(),
filename :: file:filename(),
- behlines :: [{behaviour(), non_neg_integer()}],
+ behlines :: [{behaviour(), file_location()}],
records :: rectab()}).
%%--------------------------------------------------------------------
@@ -64,6 +64,8 @@ check_callbacks(Module, Attrs, Records, Plt, Codeserver) ->
%%--------------------------------------------------------------------
+-spec get_behaviours([{cerl:cerl(), cerl:cerl()}]) -> {[behaviour()], [{behaviour(), term()}]}.
+
get_behaviours(Attrs) ->
BehaviourListsAndLocation =
[{cerl:concrete(L2), hd(cerl:get_ann(L2))} ||
@@ -93,76 +95,85 @@ check_behaviour(Module, Behaviour, #state{plt = Plt} = State, Acc) ->
check_all_callbacks(_Module, _Behaviour, [], _State, Acc) ->
Acc;
check_all_callbacks(Module, Behaviour, [Cb|Rest],
- #state{plt = Plt, codeserver = Codeserver,
- records = Records} = State, Acc) ->
+ #state{plt = Plt, codeserver = Codeserver} = State,
+ Acc0) ->
{{Behaviour, Function, Arity},
{{_BehFile, _BehLocation}, Callback, Xtra}} = Cb,
CbMFA = {Module, Function, Arity},
+ Acc1 = case dialyzer_plt:lookup(Plt, CbMFA) of
+ none ->
+ case lists:member(optional_callback, Xtra) of
+ true -> Acc0;
+ false -> [{callback_missing, [Behaviour, Function, Arity]}|Acc0]
+ end;
+ {value, RetArgTypes} ->
+ case dialyzer_codeserver:is_exported(CbMFA, Codeserver) of
+ true ->
+ check_callback(RetArgTypes, CbMFA, Behaviour, Callback, State, Acc0);
+ false ->
+ case lists:member(optional_callback, Xtra) of
+ true -> Acc0;
+ false -> [{callback_not_exported, [Behaviour, Function, Arity]}|Acc0]
+ end
+ end
+ end,
+ check_all_callbacks(Module, Behaviour, Rest, State, Acc1).
+
+check_callback(RetArgTypes, CbMFA, Behaviour, Callback,
+ #state{plt = _Plt, codeserver = Codeserver,
+ records = Records}, Acc0) ->
+ {_Module, Function, Arity} = CbMFA,
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' ->
- case lists:member(optional_callback, Xtra) of
- true -> Acc0;
- false -> [{callback_missing, [Behaviour, Function, Arity]}|Acc0]
- end;
- {'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,
- 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
- end,
- Acc2 =
- case dialyzer_codeserver:lookup_mfa_contract(CbMFA, Codeserver) of
- 'error' -> Acc1;
- {ok, {{File, Location}, Contract, _Xtra}} ->
- 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, Location, Behaviour, Function, Arity,
- erl_types:t_to_string(ExtraType, Records),
- erl_types:t_to_string(CbReturnType, Records)]}|Acc10]
- end,
- case erl_types:any_none(
- erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of
- false -> Acc11;
- true ->
- find_mismatching_args({spec, File, Location}, SpecArgTypes,
- CbArgTypes, Behaviour, Function,
- Arity, Records, 1, Acc11)
- end
- end,
- NewAcc = Acc2,
- check_all_callbacks(Module, Behaviour, Rest, State, NewAcc).
+ {ReturnType, ArgTypes} = RetArgTypes,
+ Acc1 = case erl_types:t_is_subtype(ReturnType, CbReturnType) of
+ true ->
+ Acc0;
+ false ->
+ case erl_types:t_is_none(erl_types:t_inf(ReturnType, CbReturnType)) of
+ false ->
+ Acc0;
+ true ->
+ [{callback_type_mismatch,
+ [Behaviour, Function, Arity,
+ erl_types:t_to_string(ReturnType, Records),
+ erl_types:t_to_string(CbReturnType, Records)]}|Acc0]
+ end
+ end,
+ Acc2 = case erl_types:any_none(erl_types:t_inf_lists(ArgTypes, CbArgTypes)) of
+ false -> Acc1;
+ true ->
+ find_mismatching_args(type, ArgTypes, CbArgTypes, Behaviour,
+ Function, Arity, Records, 1, Acc1)
+ end,
+ case dialyzer_codeserver:lookup_mfa_contract(CbMFA, Codeserver) of
+ error ->
+ Acc2;
+ {ok, {{File, Location}, Contract, _Xtra}} ->
+ 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],
+ Acc3 =
+ case erl_types:t_is_subtype(SpecReturnType, CbReturnType) of
+ true ->
+ Acc2;
+ false ->
+ ExtraType = erl_types:t_subtract(SpecReturnType, CbReturnType),
+ [{callback_spec_type_mismatch,
+ [File, Location, Behaviour, Function, Arity,
+ erl_types:t_to_string(ExtraType, Records),
+ erl_types:t_to_string(CbReturnType, Records)]}|Acc2]
+ end,
+ case erl_types:any_none(erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of
+ false -> Acc3;
+ true ->
+ find_mismatching_args({spec, File, Location}, SpecArgTypes,
+ CbArgTypes, Behaviour, Function,
+ Arity, Records, 1, Acc3)
+ end
+ end.
find_mismatching_args(_, [], [], _Beh, _Function, _Arity, _Records, _N, Acc) ->
Acc;
diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl
index f858a81e63..aec4bd7169 100644
--- a/lib/dialyzer/src/dialyzer_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_callgraph.erl
@@ -15,7 +15,7 @@
%%%-------------------------------------------------------------------
%%% File : dialyzer_callgraph.erl
%%% Author : Tobias Lindahl <tobiasl@it.uu.se>
-%%% Description :
+%%% Description :
%%%
%%% Created : 30 Mar 2005 by Tobias Lindahl <tobiasl@it.uu.se>
%%%-------------------------------------------------------------------
@@ -35,16 +35,14 @@
lookup_label/2,
lookup_name/2,
modules/1,
- module_deps/1,
+ module_call_deps/1,
+ merge_module_deps/2,
%% 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,
@@ -52,12 +50,6 @@
to_dot/2,
to_ps/3]).
--export([cleanup/1, get_digraph/1, get_named_tables/1, get_public_tables/1,
- 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, dispose_race_server/1, duplicate/1]).
-
-export_type([callgraph/0, mfa_or_funlbl/0, callgraph_edge/0, mod_deps/0]).
-include("dialyzer.hrl").
@@ -72,10 +64,10 @@
%%-----------------------------------------------------------------------------
%% A callgraph is a directed graph where the nodes are functions and a
%% call between two functions is an edge from the caller to the callee.
-%%
+%%
%% calls - A mapping from call site (and apply site) labels
%% to the possible functions that can be called.
-%% digraph - A digraph representing the callgraph.
+%% 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.
%% letrec_map - A dict mapping from letrec bound labels to function labels.
@@ -89,24 +81,15 @@
%% whenever applicable.
%%-----------------------------------------------------------------------------
-%% Types with comment 'race' are due to dialyzer_races.erl.
-record(callgraph, {digraph = digraph:new() :: digraph:graph(),
- active_digraph :: active_digraph()
- | 'undefined', % race
- esc :: ets:tid()
- | 'undefined', % race
- letrec_map :: ets:tid()
- | 'undefined', % race
+ active_digraph :: active_digraph() | 'undefined',
+ esc :: ets:tid(),
+ letrec_map :: ets:tid(),
name_map :: ets:tid(),
rev_name_map :: ets:tid(),
- rec_var_map :: ets:tid()
- | 'undefined', % race
- self_rec :: ets:tid()
- | 'undefined', % race
- calls :: ets:tid()
- | 'undefined', % race
- race_detection = false :: boolean(),
- race_data_server = dialyzer_race_data_server:new() :: pid()}).
+ rec_var_map :: ets:tid(),
+ self_rec :: ets:tid(),
+ calls :: ets:tid()}).
%% Exported Types
@@ -147,7 +130,7 @@ all_nodes(#callgraph{digraph = DG}) ->
-spec lookup_rec_var(label(), callgraph()) -> 'error' | {'ok', mfa()}.
-lookup_rec_var(Label, #callgraph{rec_var_map = RecVarMap})
+lookup_rec_var(Label, #callgraph{rec_var_map = RecVarMap})
when is_integer(Label) ->
ets_lookup_dict(Label, RecVarMap).
@@ -222,7 +205,7 @@ remove_external(#callgraph{digraph = DG} = CG) ->
non_local_calls(#callgraph{digraph = DG}) ->
Edges = digraph_edges(DG),
- find_non_local_calls(Edges, sets:new()).
+ find_non_local_calls(Edges, sets:new([{version, 2}])).
-type call_tab() :: sets:set(mfa_call()).
@@ -234,7 +217,7 @@ find_non_local_calls([{{M,_,_}, {M,_,_}}|Left], Set) ->
find_non_local_calls([{{M1,_,_}, {M2,_,_}} = Edge|Left], Set) when M1 =/= M2 ->
find_non_local_calls(Left, sets:add_element(Edge, Set));
find_non_local_calls([{{_,_,_}, Label}|Left], Set) when is_integer(Label) ->
- find_non_local_calls(Left, Set);
+ find_non_local_calls(Left, Set);
find_non_local_calls([{Label, {_,_,_}}|Left], Set) when is_integer(Label) ->
find_non_local_calls(Left, Set);
find_non_local_calls([{Label1, Label2}|Left], Set) when is_integer(Label1),
@@ -243,6 +226,7 @@ find_non_local_calls([{Label1, Label2}|Left], Set) when is_integer(Label1),
find_non_local_calls([], Set) ->
sets:to_list(Set).
+%% Only considers call dependencies, not type dependencies, which are dealt with elsewhere
-spec get_depends_on(scc() | module(), callgraph()) -> [scc()].
get_depends_on(SCC, #callgraph{active_digraph = {'e', Out, _In, Maps}}) ->
@@ -281,10 +265,10 @@ modules(#callgraph{digraph = DG}) ->
-spec module_postorder(callgraph()) -> {[module()], {'d', digraph:graph()}}.
module_postorder(#callgraph{digraph = DG}) ->
- Edges = lists:foldl(fun edge_fold/2, sets:new(), digraph_edges(DG)),
- Nodes = sets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
+ Edges = lists:foldl(fun edge_fold/2, sets:new([{version, 2}]), digraph_edges(DG)),
+ Modules = ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
MDG = digraph:new([acyclic]),
- digraph_confirm_vertices(sets:to_list(Nodes), MDG),
+ digraph_confirm_vertices(Modules, MDG),
Foreach = fun({M1,M2}) -> _ = digraph:add_edge(MDG, M1, M2) end,
lists:foreach(Foreach, sets:to_list(Edges)),
%% The out-neighbors of a vertex are the vertices called directly.
@@ -299,21 +283,33 @@ edge_fold({{M1,_,_},{M2,_,_}}, Set) ->
edge_fold(_, Set) -> Set.
-%% The module deps of a module are modules that depend on the module
--spec module_deps(callgraph()) -> mod_deps().
+%% The module call deps of a module are modules that depend on the module to
+%% make function calls
+-spec module_call_deps(callgraph()) -> mod_deps().
-module_deps(#callgraph{digraph = DG}) ->
- Edges = lists:foldl(fun edge_fold/2, sets:new(), digraph_edges(DG)),
- Nodes = sets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
+module_call_deps(#callgraph{digraph = DG}) ->
+ Edges = lists:foldl(fun edge_fold/2, sets:new([{version, 2}]), digraph_edges(DG)),
+ Modules = ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]),
MDG = digraph:new(),
- digraph_confirm_vertices(sets:to_list(Nodes), MDG),
+ digraph_confirm_vertices(Modules, MDG),
Foreach = fun({M1,M2}) -> check_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)],
+ || N <- Modules],
digraph_delete(MDG),
dict:from_list(Deps).
+-spec merge_module_deps(mod_deps(), mod_deps()) -> mod_deps().
+merge_module_deps(Left, Right) ->
+ dict:merge(
+ fun (_Mod, L, R) ->
+ gb_sets:to_list(gb_sets:union(
+ gb_sets:from_list(L),
+ gb_sets:from_list(R)))
+ end,
+ Left,
+ Right).
+
-spec strip_module_deps(mod_deps(), sets:set(module())) -> mod_deps().
strip_module_deps(ModDeps, StripSet) ->
@@ -387,10 +383,10 @@ scan_core_tree(Tree, #callgraph{calls = ETSCalls,
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) ->
+ SelfRecs0 = lists:foldl(fun({Key, Key}, Acc) ->
case ets_lookup_dict(Key, ETSNameMap) of
error -> [Key|Acc];
{ok, Name} -> [Key, Name|Acc]
@@ -398,9 +394,9 @@ scan_core_tree(Tree, #callgraph{calls = ETSCalls,
(_, Acc) -> Acc
end, [], LabelEdges),
true = ets:insert(ETSSelfRec, [{S} || S <- SelfRecs0]),
-
+
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
%% top level function. This is OK since the included functions are
@@ -422,7 +418,7 @@ scan_core_tree(Tree, #callgraph{calls = ETSCalls,
build_maps(Tree, ETSRecVarMap, ETSNameMap, ETSRevNameMap, ETSLetrecMap) ->
%% We only care about the named (top level) functions. The anonymous
- %% functions will be analysed together with their parents.
+ %% functions will be analysed together with their parents.
Defs = cerl:module_defs(Tree),
Mod = cerl:atom_val(cerl:module_name(Tree)),
Fun =
@@ -445,7 +441,7 @@ get_edges_from_deps(Deps) ->
%% this information.
Edges = dict:fold(fun(external, _Set, Acc) -> Acc;
(Caller, Set, Acc) ->
- [[{Caller, Callee} || Callee <- Set,
+ [[{Caller, Callee} || Callee <- Set,
Callee =/= external]|Acc]
end, [], Deps),
lists:flatten(Edges).
@@ -487,9 +483,9 @@ scan_one_core_fun(TopTree, FunName) ->
CalleeF = cerl:call_name(Tree),
CalleeArgs = cerl:call_args(Tree),
A = length(CalleeArgs),
- case (cerl:is_c_atom(CalleeM) andalso
+ case (cerl:is_c_atom(CalleeM) andalso
cerl:is_c_atom(CalleeF)) of
- true ->
+ true ->
M = cerl:atom_val(CalleeM),
F = cerl:atom_val(CalleeF),
case erl_bif_types:is_known(M, F, A) of
@@ -518,7 +514,7 @@ scan_one_core_fun(TopTree, FunName) ->
end;
false -> [{FunName, {M, F, A}}|Acc]
end;
- false ->
+ false ->
%% We cannot handle run-time bindings
Acc
end;
@@ -574,14 +570,14 @@ digraph_confirm_vertices([MFA|Left], DG) ->
digraph_confirm_vertices(Left, DG);
digraph_confirm_vertices([], _DG) ->
ok.
-
+
digraph_remove_external(DG) ->
Vertices = digraph:vertices(DG),
Unconfirmed = remove_unconfirmed(Vertices, DG),
{DG, Unconfirmed}.
-remove_unconfirmed(Vertexes, DG) ->
- remove_unconfirmed(Vertexes, DG, []).
+remove_unconfirmed(Vertices, DG) ->
+ remove_unconfirmed(Vertices, DG, []).
remove_unconfirmed([V|Left], DG, Unconfirmed) ->
case digraph:vertex(DG, V) of
@@ -616,138 +612,10 @@ digraph_in_neighbours(V, DG) ->
List -> List
end.
-digraph_reaching_subgraph(Funs, DG) ->
+digraph_reaching_subgraph(Funs, DG) ->
Vertices = digraph_utils:reaching(Funs, DG),
digraph_utils:subgraph(DG, Vertices).
-%%----------------------------------------------------------------------
-%% Races
-%%----------------------------------------------------------------------
-
--spec renew_race_info(callgraph(), dict:dict(), [label()], [string()]) ->
- callgraph().
-
-renew_race_info(#callgraph{race_data_server = RaceDataServer} = CG,
- RaceCode, PublicTables, NamedTables) ->
- ok = dialyzer_race_data_server:cast(
- {renew_race_info, {RaceCode, PublicTables, NamedTables}},
- RaceDataServer),
- CG.
-
--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 = dialyzer_race_data_server:cast(
- {renew_race_code, {Fun, FunArgs, Code}},
- RaceDataServer),
- CG.
-
--spec renew_race_public_tables(label(), callgraph()) -> callgraph().
-
-renew_race_public_tables(VarLabel,
- #callgraph{race_data_server = RaceDataServer} = CG) ->
- ok =
- dialyzer_race_data_server:cast({renew_race_public_tables, VarLabel}, RaceDataServer),
- CG.
-
--spec cleanup(callgraph()) -> callgraph().
-
-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,
- race_data_server = dialyzer_race_data_server:duplicate(RaceDataServer)}.
-
--spec duplicate(callgraph()) -> callgraph().
-
-duplicate(#callgraph{race_data_server = RaceDataServer} = Callgraph) ->
- Callgraph#callgraph{
- race_data_server = dialyzer_race_data_server:duplicate(RaceDataServer)}.
-
--spec dispose_race_server(callgraph()) -> ok.
-
-dispose_race_server(#callgraph{race_data_server = RaceDataServer}) ->
- dialyzer_race_data_server:stop(RaceDataServer).
-
--spec get_digraph(callgraph()) -> digraph:graph().
-
-get_digraph(#callgraph{digraph = Digraph}) ->
- Digraph.
-
--spec get_named_tables(callgraph()) -> [string()].
-
-get_named_tables(#callgraph{race_data_server = RaceDataServer}) ->
- dialyzer_race_data_server:call(get_named_tables, RaceDataServer).
-
--spec get_public_tables(callgraph()) -> [label()].
-
-get_public_tables(#callgraph{race_data_server = RaceDataServer}) ->
- dialyzer_race_data_server:call(get_public_tables, RaceDataServer).
-
--spec get_race_code(callgraph()) -> dict:dict().
-
-get_race_code(#callgraph{race_data_server = RaceDataServer}) ->
- dialyzer_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}) ->
- dialyzer_race_data_server:call(get_behaviour_api_calls, RaceDataServer).
-
--spec race_code_new(callgraph()) -> callgraph().
-
-race_code_new(#callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = dialyzer_race_data_server:cast(race_code_new, RaceDataServer),
- CG.
-
--spec put_digraph(digraph:graph(), callgraph()) -> callgraph().
-
-put_digraph(Digraph, Callgraph) ->
- Callgraph#callgraph{digraph = Digraph}.
-
--spec put_race_code(dict:dict(), callgraph()) -> callgraph().
-
-put_race_code(RaceCode, #callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = dialyzer_race_data_server:cast({put_race_code, RaceCode}, RaceDataServer),
- CG.
-
--spec put_race_detection(boolean(), callgraph()) -> callgraph().
-
-put_race_detection(RaceDetection, Callgraph) ->
- Callgraph#callgraph{race_detection = RaceDetection}.
-
--spec put_named_tables([string()], callgraph()) -> callgraph().
-
-put_named_tables(NamedTables,
- #callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = dialyzer_race_data_server:cast({put_named_tables, NamedTables}, RaceDataServer),
- CG.
-
--spec put_public_tables([label()], callgraph()) -> callgraph().
-
-put_public_tables(PublicTables,
- #callgraph{race_data_server = RaceDataServer} = CG) ->
- ok = dialyzer_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 = dialyzer_race_data_server:cast({put_behaviour_api_calls, Calls}, RaceDataServer),
- CG.
-
%%=============================================================================
%% Utilities for 'dot'
%%=============================================================================
@@ -762,7 +630,7 @@ to_dot(#callgraph{digraph = DG, esc = Esc} = CG, File) ->
{ok, Name} -> Name
end
end,
- Escaping = [{Fun(L), {color, red}}
+ Escaping = [{Fun(L), {color, red}}
|| L <- [E || {E} <- ets:tab2list(Esc)], L =/= external],
Vertices = digraph_edges(DG),
dialyzer_dot:translate_list(Vertices, File, "CG", Escaping).
@@ -799,7 +667,7 @@ do_condensation(G, Parent) ->
IntScc = sofs:relation(IntToSCC, [{int, scc}]),
%% Create mapping from unique integers to SCCs:
ets:insert(MapsETS, IntToSCC),
- %% Subsitute strong components for vertices in edges using the
+ %% Substitute strong components for vertices in edges using the
%% unique numbers:
C2V = sofs:relation([{SC, V} || SC <- SCCs, V <- SC], [{scc, v}]),
I2V = sofs:relative_product(IntScc, C2V), % [{v, int}]
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 2dd56ebb08..25fdef948e 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -47,7 +47,7 @@
indent_opt = ?INDENT_OPT :: iopt(),
error_location = ?ERROR_LOCATION :: error_location(),
output_plt = none :: 'none' | file:filename(),
- plt_info = none :: 'none' | dialyzer_plt:plt_info(),
+ plt_info = none :: 'none' | #plt_info{},
report_mode = normal :: rep_mode(),
return_status= ?RET_NOTHING_SUSPICIOUS :: dial_ret(),
stored_warnings = [] :: [raw_warning()]
@@ -73,7 +73,7 @@ build_plt(Opts) ->
Opts1 = init_opts_for_build(Opts),
Files = get_files_from_opts(Opts1),
Md5 = dialyzer_plt:compute_md5_from_files(Files),
- PltInfo = {Md5, dict:new()},
+ PltInfo = #plt_info{files = Md5, mod_deps = dict:new()},
do_analysis(Files, Opts1, dialyzer_plt:new(), PltInfo).
init_opts_for_build(Opts) ->
@@ -200,7 +200,7 @@ plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
end,
{?RET_NOTHING_SUSPICIOUS, []};
{old_version, Md5} ->
- PltInfo = {Md5, dict:new()},
+ PltInfo = #plt_info{files = Md5, mod_deps = dict:new()},
Files = [F || {F, _} <- Md5],
do_analysis(Files, Opts, dialyzer_plt:new(), PltInfo);
{differ, Md5, DiffMd5, ModDeps} ->
@@ -212,10 +212,10 @@ plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
true ->
%% Only removed stuff. Just write the PLT.
dialyzer_plt:to_file(Opts#options.output_plt, Plt, ModDeps,
- {Md5, ModDeps}),
+ #plt_info{files = Md5, mod_deps = ModDeps}),
{?RET_NOTHING_SUSPICIOUS, []};
false ->
- do_analysis(AnalFiles, Opts, Plt, {Md5, ModDeps1})
+ do_analysis(AnalFiles, Opts, Plt, #plt_info{files = Md5, mod_deps = ModDeps1})
end;
{error, no_such_file} ->
Msg = io_lib:format("Could not find the PLT: ~ts\n~s",
@@ -431,7 +431,18 @@ check_if_writable(PltFile) ->
true -> false;
false ->
DirName = filename:dirname(PltFile),
- filelib:is_dir(DirName) andalso is_writable_file_or_dir(DirName)
+ case filelib:is_dir(DirName) of
+ false ->
+ case filelib:ensure_dir(PltFile) of
+ ok ->
+ io:format(" Creating ~ts as it did not exist...~n", [DirName]),
+ true;
+ {error, _} ->
+ false
+ end;
+ true ->
+ is_writable_file_or_dir(DirName)
+ end
end
end.
@@ -452,8 +463,8 @@ clean_plt(PltFile, RemovedMods) ->
Plt, RemovedMods).
expand_dependent_modules(Md5, DiffMd5, ModDeps) ->
- ChangedMods = sets:from_list([M || {differ, M} <- DiffMd5]),
- RemovedMods = sets:from_list([M || {removed, M} <- DiffMd5]),
+ ChangedMods = sets:from_list([M || {differ, M} <- DiffMd5], [{version, 2}]),
+ RemovedMods = sets:from_list([M || {removed, M} <- DiffMd5], [{version, 2}]),
BigSet = sets:union(ChangedMods, RemovedMods),
BigList = sets:to_list(BigSet),
ExpandedSet = expand_dependent_modules_1(BigList, BigSet, ModDeps),
diff --git a/lib/dialyzer/src/dialyzer_cl_parse.erl b/lib/dialyzer/src/dialyzer_cl_parse.erl
index ff7930f21a..e59f4027ac 100644
--- a/lib/dialyzer/src/dialyzer_cl_parse.erl
+++ b/lib/dialyzer/src/dialyzer_cl_parse.erl
@@ -98,6 +98,11 @@ cl(["-I", Dir|T]) ->
cl(["-I"++Dir|T]) ->
append_include(Dir),
cl(T);
+cl(["--input_list_file"]) ->
+ cl_error("No input list file specified");
+cl(["--input_list_file",File|L]) ->
+ read_input_list_file(File),
+ cl(L);
cl(["-c"++_|T]) ->
NewTail = command_line(T),
cl(NewTail);
@@ -244,6 +249,16 @@ command_line(T0) ->
end,
T.
+read_input_list_file(File) ->
+ case file:read_file(File) of
+ {ok,Bin} ->
+ Files = binary:split(Bin, <<"\n">>, [trim_all,global]),
+ NewFiles = [binary_to_list(string:trim(F)) || F <- Files],
+ append_var(dialyzer_options_files, NewFiles);
+ {error,Reason} ->
+ cl_error(io_lib:format("Reading of ~s failed: ~s", [File,file:format_error(Reason)]))
+ end.
+
-spec cl_error(deep_string()) -> no_return().
cl_error(Str) ->
@@ -395,6 +410,9 @@ Options:
Same as the previous but the specified directories are searched
recursively for subdirectories containing .erl or .beam files in
them, depending on the type of analysis.
+ --input_list_file file
+ Specify the name of a file that contains the names of the files
+ to be analyzed (one file name per line).
--apps applications
Option typically used when building or modifying a plt as in:
dialyzer --build_plt --apps erts kernel stdlib mnesia ...
@@ -544,11 +562,15 @@ warning_options_msg() ->
value or do not match against one of many possible return value(s).
-Werror_handling ***
Include warnings for functions that only return by means of an exception.
- -Wrace_conditions ***
- Include warnings for possible race conditions.
-Wunderspecs ***
Warn about underspecified functions
(those whose -spec is strictly more allowing than the success typing).
+ -Wextra_return ***
+ Warn about functions whose specification includes types that the
+ function cannot return.
+ -Wmissing_return ***
+ Warn about functions that return values that are not part
+ of the specification.
-Wunknown ***
Let warnings about unknown functions and types affect the
exit status of the command line version. The default is to ignore
@@ -572,4 +594,8 @@ They are primarily intended to be used with the -dialyzer attribute:
-Wno_underspecs
Suppress warnings about underspecified functions (those whose -spec
is strictly more allowing than the success typing).
+ -Wno_extra_return
+ Suppress warnings about functions whose specification includes types that the function cannot return.
+ -Wno_missing_return
+ Suppress warnings about functions that return values that are not part of the specification.
".
diff --git a/lib/dialyzer/src/dialyzer_clean_core.erl b/lib/dialyzer/src/dialyzer_clean_core.erl
index d591ad3473..820ce19a06 100644
--- a/lib/dialyzer/src/dialyzer_clean_core.erl
+++ b/lib/dialyzer/src/dialyzer_clean_core.erl
@@ -72,11 +72,6 @@ clean(Tree) ->
Args = clean_list(cerl:primop_args(Tree)),
Name = cerl:primop_name(Tree),
cerl:update_c_primop(Tree, Name, Args);
- 'receive' ->
- Clauses = clean_clauses(cerl:receive_clauses(Tree)),
- Timeout = clean(cerl:receive_timeout(Tree)),
- Action = clean(cerl:receive_action(Tree)),
- cerl:update_c_receive(Tree, Clauses, Timeout, Action);
seq ->
Arg = clean(cerl:seq_arg(Tree)),
Body = clean(cerl:seq_body(Tree)),
@@ -114,6 +109,7 @@ clean_letrec(Tree) ->
FunBody = cerl:fun_body(Fun),
FunBody1 = clean(FunBody),
Body = clean(cerl:letrec_body(Tree)),
+ FunVars = cerl:fun_vars(Fun),
case dialyzer_ignore(Body) of
true ->
%% The body of the letrec directly transfer controls to
@@ -157,8 +153,10 @@ clean_letrec(Tree) ->
%% end
%%
PrimopUnknown = cerl:c_primop(cerl:abstract(dialyzer_unknown), []),
- Clauses = [cerl:c_clause([cerl:abstract(a)], Body),
- cerl:c_clause([cerl:abstract(b)], FunBody1)],
+ PatA = [cerl:abstract(a)],
+ PatB = [cerl:c_tuple([cerl:abstract(b)|FunVars])],
+ Clauses = [cerl:c_clause(PatA, Body),
+ cerl:c_clause(PatB, FunBody1)],
cerl:c_case(PrimopUnknown, Clauses)
end;
false ->
diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl
index 0472e2c128..9b8a165dd0 100644
--- a/lib/dialyzer/src/dialyzer_codeserver.erl
+++ b/lib/dialyzer/src/dialyzer_codeserver.erl
@@ -29,7 +29,7 @@
finalize_records/1,
get_contracts/1,
get_callbacks/1,
- get_exported_types/1,
+ get_exported_types_table/1,
extract_exported_types/1,
get_exports/1,
get_records_table/1,
@@ -122,7 +122,7 @@ ets_set_insert_list(List, Table) ->
ets_set_to_set(Table) ->
Fold = fun({E}, Set) -> sets:add_element(E, Set) end,
- ets:foldl(Fold, sets:new(), Table).
+ ets:foldl(Fold, sets:new([{version, 2}]), Table).
%%--------------------------------------------------------------------
@@ -132,12 +132,15 @@ new() ->
CodeOptions = [compressed, public, {read_concurrency, true}],
Code = ets:new(dialyzer_codeserver_code, CodeOptions),
ReadOptions = [compressed, {read_concurrency, true}],
- [Contracts, Callbacks, Records, ExportedTypes] =
+ [Records, ExportedTypes] =
[ets:new(Name, ReadOptions) ||
- Name <- [dialyzer_codeserver_contracts,
- dialyzer_codeserver_callbacks,
- dialyzer_codeserver_records,
+ Name <- [dialyzer_codeserver_records,
dialyzer_codeserver_exported_types]],
+ ReadWriteOptions = [public | ReadOptions],
+ [Contracts, Callbacks] =
+ [ets:new(Name, ReadWriteOptions) ||
+ Name <- [dialyzer_codeserver_contracts,
+ dialyzer_codeserver_callbacks]],
TempOptions = [public, {write_concurrency, true}],
[Exports, FunMetaInfo, TempExportedTypes, TempRecords, TempContracts,
TempCallbacks] =
@@ -211,10 +214,10 @@ insert_fun_meta_info(List, #codeserver{fun_meta_info = FunMetaInfo} = CS) ->
is_exported(MFA, #codeserver{exports = Exports}) ->
ets_set_is_element(MFA, Exports).
--spec get_exported_types(codeserver()) -> sets:set(mfa()).
+-spec get_exported_types_table(codeserver()) -> map_ets().
-get_exported_types(#codeserver{exported_types = ExpTypes}) ->
- ets_set_to_set(ExpTypes).
+get_exported_types_table(#codeserver{exported_types = ExpTypes}) ->
+ ExpTypes.
-spec extract_exported_types(codeserver()) -> {codeserver(), set_ets()}.
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 2b296e1668..067e7956f3 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -25,14 +25,26 @@
%% get_contract_signature/1,
is_overloaded/1,
process_contract_remote_types/1,
- store_tmp_contract/6]).
+ store_tmp_contract/6,
+ constraint_form_to_remote_modules/1]).
--export_type([file_contract/0, plt_contracts/0]).
+%% For dialyzer_worker.
+-export([process_contract_remote_types_module/2]).
+
+-export_type([file_contract/0, plt_contracts/0,
+ contract_remote_types_init_data/0,
+ contract_remote_types_result/0]).
%%-----------------------------------------------------------------------
-include("dialyzer.hrl").
+-type ext_types_message() :: {pid(), 'ext_types',
+ {mfa(), {file:filename(), erl_anno:location()}}}
+ | {'error', io_lib:chars()}.
+-type contract_remote_types_init_data() :: dialyzer_codeserver:codeserver().
+-type contract_remote_types_result() :: [ext_types_message()].
+
%%-----------------------------------------------------------------------
%% Types used in other parts of the system below
%%-----------------------------------------------------------------------
@@ -143,37 +155,78 @@ sequence([H|T], Delimiter) -> H ++ Delimiter ++ sequence(T, Delimiter).
dialyzer_codeserver:codeserver().
process_contract_remote_types(CodeServer) ->
- Mods = dialyzer_codeserver:all_temp_modules(CodeServer),
+ case dialyzer_codeserver:all_temp_modules(CodeServer) of
+ [] ->
+ CodeServer;
+ Mods ->
+ %% CodeServer is updated by each worker, but is still valid
+ %% after updates. Workers call
+ %% process_contract_remote_types_module/2 below.
+ Return =
+ dialyzer_coordinator:parallel_job(contract_remote_types,
+ Mods,
+ _InitData=CodeServer,
+ _Timing=none),
+ %% We need to pass on messages and thrown errors from erl_types:
+ _ = [self() ! {self(), ext_types, ExtType} ||
+ {_, ext_types, ExtType} <- Return],
+ case [Error || {error, _} = Error <- Return] of
+ [] ->
+ dialyzer_codeserver:finalize_contracts(CodeServer);
+ [Error | _] ->
+ throw(Error)
+ end
+ end.
+
+-spec process_contract_remote_types_module(module(),
+ dialyzer_codeserver:codeserver()) -> [ext_types_message()].
+
+process_contract_remote_types_module(ModuleName, CodeServer) ->
RecordTable = dialyzer_codeserver:get_records_table(CodeServer),
- ExpTypes = dialyzer_codeserver:get_exported_types(CodeServer),
- ModuleFun =
- fun(ModuleName) ->
- ContractFun =
- fun({MFA, {File, TmpContract, Xtra}}, C0) ->
- #tmp_contract{contract_funs = CFuns, forms = Forms} = TmpContract,
- {NewCs, C2} = lists:mapfoldl(fun(CFun, C1) ->
- CFun(ExpTypes, RecordTable, C1)
- end, C0, CFuns),
- Args = general_domain(NewCs),
- Contract = #contract{contracts = NewCs, args = Args, forms = Forms},
- {{MFA, {File, Contract, Xtra}}, C2}
- end,
- Cache = erl_types:cache__new(),
- {ContractMap, CallbackMap} =
- dialyzer_codeserver:get_temp_contracts(ModuleName, CodeServer),
- {NewContractList, Cache1} =
- lists:mapfoldl(ContractFun, Cache, maps:to_list(ContractMap)),
- {NewCallbackList, _NewCache} =
- lists:mapfoldl(ContractFun, Cache1, maps:to_list(CallbackMap)),
- dialyzer_codeserver:store_contracts(ModuleName,
- maps:from_list(NewContractList),
- maps:from_list(NewCallbackList),
- CodeServer)
+ ExpTypes = dialyzer_codeserver:get_exported_types_table(CodeServer),
+ ContractFun =
+ fun({MFA, {File, TmpContract, Xtra}}, C0) ->
+ #tmp_contract{contract_funs = CFuns, forms = Forms} = TmpContract,
+ {NewCs, C2} = lists:mapfoldl(fun(CFun, C1) ->
+ CFun(ExpTypes, RecordTable, C1)
+ end, C0, CFuns),
+ Args = general_domain(NewCs),
+ Contract = #contract{contracts = NewCs, args = Args, forms = Forms},
+ {{MFA, {File, Contract, Xtra}}, C2}
end,
- lists:foreach(ModuleFun, Mods),
- dialyzer_codeserver:finalize_contracts(CodeServer).
+ Cache = erl_types:cache__new(),
+ {ContractMap, CallbackMap} =
+ dialyzer_codeserver:get_temp_contracts(ModuleName, CodeServer),
+ try
+ {NewContractList, Cache1} =
+ lists:mapfoldl(ContractFun, Cache, maps:to_list(ContractMap)),
+ {NewCallbackList, _NewCache} =
+ lists:mapfoldl(ContractFun, Cache1, maps:to_list(CallbackMap)),
+ _NewCodeServer =
+ dialyzer_codeserver:store_contracts(ModuleName,
+ maps:from_list(NewContractList),
+ maps:from_list(NewCallbackList),
+ CodeServer),
+ rcv_ext_types()
+ catch
+ throw:{error, _}=Error ->
+ [Error] ++ rcv_ext_types()
+ end.
+
+rcv_ext_types() ->
+ Self = self(),
+ Self ! {Self, done},
+ rcv_ext_types(Self, []).
+
+rcv_ext_types(Self, ExtTypes) ->
+ receive
+ {Self, ext_types, _} = ExtType ->
+ rcv_ext_types(Self, [ExtType | ExtTypes]);
+ {Self, done} ->
+ lists:usort(ExtTypes)
+ end.
--type fun_types() :: orddict:orddict(label(), erl_types:type_table()).
+-type fun_types() :: orddict:orddict(label(), erl_types:erl_type()).
-spec check_contracts(orddict:orddict(mfa(), #contract{}),
dialyzer_callgraph:callgraph(), fun_types(),
@@ -293,11 +346,11 @@ check_contract_inf_list(List, SuccType, Opaques) ->
check_contract_inf_list([{Contract, FunType}|Left], SuccType, Opaques, OM) ->
FunArgs = erl_types:t_fun_args(FunType),
- case lists:any(fun erl_types:t_is_none_or_unit/1, FunArgs) of
+ case lists:any(fun erl_types:t_is_impossible/1, FunArgs) of
true -> check_contract_inf_list(Left, SuccType, Opaques, OM);
false ->
STRange = erl_types:t_fun_range(SuccType),
- case erl_types:t_is_none_or_unit(STRange) of
+ case erl_types:t_is_impossible(STRange) of
true -> ok;
false ->
Range = erl_types:t_fun_range(FunType),
@@ -846,13 +899,13 @@ overlapping_contract_warning({M, F, A}, WarningInfo) ->
extra_range_warning({M, F, A}, WarningInfo, ExtraRanges, STRange) ->
ERangesStr = erl_types:t_to_string(ExtraRanges),
STRangeStr = erl_types:t_to_string(STRange),
- {?WARN_CONTRACT_SUPERTYPE, WarningInfo,
+ {?WARN_CONTRACT_EXTRA_RETURN, WarningInfo,
{extra_range, [M, F, A, ERangesStr, STRangeStr]}}.
missing_range_warning({M, F, A}, WarningInfo, ExtraRanges, CRange) ->
ERangesStr = erl_types:t_to_string(ExtraRanges),
CRangeStr = erl_types:t_to_string(CRange),
- {?WARN_CONTRACT_SUBTYPE, WarningInfo,
+ {?WARN_CONTRACT_MISSING_RETURN, WarningInfo,
{missing_range, [M, F, A, ERangesStr, CRangeStr]}}.
picky_contract_check(CSig0, Sig0, MFA, WarningInfo, Contract, RecDict,
@@ -967,3 +1020,13 @@ blame_remote_list([CArg|CArgs], [NRArg|NRArgs], [SArg|SArgs], Opaques) ->
is_subtype(T1, T2, Opaques) ->
Inf = erl_types:t_inf(T1, T2, Opaques),
erl_types:t_is_equal(T1, Inf).
+
+-spec constraint_form_to_remote_modules(Constraint :: term()) -> [module()].
+
+constraint_form_to_remote_modules([]) ->
+ [];
+
+constraint_form_to_remote_modules([{type, _, constraint, [{atom, _, _}, Types]}|Rest]) ->
+ ModulesFromTypes = erl_types:type_form_to_remote_modules(Types),
+ ModulesFromSubsequentConstraints = constraint_form_to_remote_modules(Rest),
+ lists:usort(lists:append(ModulesFromTypes, ModulesFromSubsequentConstraints)).
diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl
index 7c1bc1de5a..2ca3acc4cb 100644
--- a/lib/dialyzer/src/dialyzer_coordinator.erl
+++ b/lib/dialyzer/src/dialyzer_coordinator.erl
@@ -11,22 +11,21 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-
-%%%-------------------------------------------------------------------
-%%% File : dialyzer_coordinator.erl
-%%% Authors : Stavros Aronis <aronisstav@gmail.com>
-%%%-------------------------------------------------------------------
+%%
+%% Original author: Stavros Aronis <aronisstav@gmail.com>
+%%
+%% Purpose: Spawn and coordinate parallel jobs.
-module(dialyzer_coordinator).
%%% Export for dialyzer main process
-export([parallel_job/4]).
-%%% Export for all possible workers
--export([job_done/3]).
+%%% Exports for all workers
+-export([request_activation/1, job_done/3]).
%%% Exports for the typesig and dataflow analysis workers
--export([sccs_to_pids/2, request_activation/1]).
+-export([wait_for_success_typings/2]).
%%% Exports for the compilation workers
-export([get_next_label/2]).
@@ -37,40 +36,59 @@
-type collector() :: pid().
-type regulator() :: pid().
--type scc_to_pid() :: ets:tid() | 'unused'.
+-type scc_to_pid() :: ets:tid() | 'none'.
-opaque coordinator() :: {collector(), regulator(), scc_to_pid()}.
-type timing() :: dialyzer_timing:timing_server().
-type scc() :: [mfa_or_funlbl()].
--type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'.
+-type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings' |
+ 'contract_remote_types' | 'record_remote_types'.
-type compile_job() :: file:filename().
-type typesig_job() :: scc().
-type dataflow_job() :: module().
-type warnings_job() :: module().
+-type contract_remote_types_job() :: module().
+-type record_remote_types_job() :: module().
--type job() :: compile_job() | typesig_job() | dataflow_job() | warnings_job().
+-type job() :: compile_job() | typesig_job() | dataflow_job() |
+ warnings_job() | contract_remote_types_job() |
+ record_remote_types_job().
-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 contract_remote_types_init_data() ::
+ dialyzer_contracts:contract_remote_types_init_data().
+-type record_remote_types_init_data() ::
+ dialyzer_utils:record_remote_types_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 contract_remote_types_result() ::
+ dialyzer_contracts:contract_remote_types_result().
+-type record_remote_types_result() ::
+ dialyzer_utils:record_remote_types_result().
-type init_data() :: compile_init_data() | typesig_init_data() |
- dataflow_init_data() | warnings_init_data().
+ dataflow_init_data() | warnings_init_data() |
+ contract_remote_types_init_data() |
+ record_remote_types_init_data().
-type result() :: compile_result() | typesig_result() |
- dataflow_result() | warnings_result().
+ dataflow_result() | warnings_result() |
+ contract_remote_types_result() |
+ record_remote_types_result().
-type job_result() :: dialyzer_analysis_callgraph:one_file_mid_error() |
dialyzer_analysis_callgraph:one_file_result_ok() |
- typesig_result() | dataflow_result() | warnings_result().
+ typesig_result() | dataflow_result() |
+ warnings_result() | contract_remote_types_result() |
+ record_remote_types_result().
-record(state, {mode :: mode(),
active = 0 :: integer(),
@@ -86,6 +104,7 @@
-include("dialyzer.hrl").
%%--------------------------------------------------------------------
+%% API functions for the main dialyzer process.
-spec parallel_job('compile', [compile_job()], compile_init_data(), timing()) ->
{compile_result(), integer()};
@@ -94,76 +113,155 @@
('dataflow', [dataflow_job()], dataflow_init_data(),
timing()) -> dataflow_result();
('warnings', [warnings_job()], warnings_init_data(),
- timing()) -> warnings_result().
+ timing()) -> warnings_result();
+ ('contract_remote_types', [contract_remote_types_job()],
+ contract_remote_types_init_data(), timing()) ->
+ contract_remote_types_result();
+ ('record_remote_types', [record_remote_types_job()],
+ record_remote_types_init_data(), timing()) ->
+ record_remote_types_result().
parallel_job(Mode, Jobs, InitData, Timing) ->
State = spawn_jobs(Mode, Jobs, InitData, Timing),
collect_result(State).
+%%--------------------------------------------------------------------
+%% API functions for workers (dialyzer_worker).
+
+-spec request_activation(coordinator()) -> ok.
+
+request_activation({_Collector, Regulator, _SCCtoPid}) ->
+ Regulator ! {req, self()},
+ wait_activation().
+
+-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().
+
+%% For the 'compile' worker.
+get_next_label(EstimatedSize, {Collector, _Regulator, _SCCtoPid}) ->
+ Collector ! {next_label_request, EstimatedSize, self()},
+ receive
+ {next_label_reply, NextLabel} -> NextLabel
+ end.
+
+-spec wait_for_success_typings([scc() | module()], coordinator()) ->
+ 'ok'.
+
+%% Helper for 'sigtype' and 'dataflow' workers.
+wait_for_success_typings(SCCs, {_Collector, _Regulator, SCCtoPid}) ->
+ F = fun(SCC) ->
+ %% The SCCs that SCC depends on have always been started.
+ try ets:lookup_element(SCCtoPid, SCC, 2) of
+ Pid when is_pid(Pid) ->
+ Ref = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', Ref, process, Pid, _Info} ->
+ ok
+ end
+ catch
+ _:_ ->
+ %% Already finished.
+ ok
+ end
+ end,
+ lists:foreach(F, SCCs).
+
+
+%%--------------------------------------------------------------------
+%% Local functions.
+
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},
- JobFun =
- fun(Job) ->
- Pid = dialyzer_worker:launch(Mode, Job, InitData, Coordinator),
- case TypesigOrDataflow of
- true -> true = ets:insert(SCCtoPID, {Job, Pid});
- false -> true
- end
+
+ SCCtoPid =
+ if
+ Mode =:= 'typesig'; Mode =:= 'dataflow' ->
+ ets:new(scc_to_pid, [{read_concurrency, true}]);
+ true ->
+ none
end,
- JobCount = length(Jobs),
- NumberOfInitJobs = min(JobCount, 20 * dialyzer_utils:parallelism()),
- {InitJobs, RestJobs} = lists:split(NumberOfInitJobs, Jobs),
- lists:foreach(JobFun, InitJobs),
+
+ Coordinator = {Collector, Regulator, SCCtoPid},
+
+ JobFun = job_fun(SCCtoPid, Mode, InitData, Coordinator),
+
+ %% Limit the number of processes we start in order to save memory.
+ MaxNumberOfInitJobs = 20 * dialyzer_utils:parallelism(),
+ RestJobs = launch_jobs(Jobs, JobFun, MaxNumberOfInitJobs),
+
Unit =
case Mode of
'typesig' -> "SCCs";
_ -> "modules"
end,
+ JobCount = length(Jobs),
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, job_fun = JobFun, jobs = RestJobs,
- init_data = InitData, regulator = Regulator, scc_to_pid = SCCtoPID}.
+ init_data = InitData, regulator = Regulator, scc_to_pid = SCCtoPid}.
+
+launch_jobs(Jobs, _JobFun, 0) ->
+ Jobs;
+launch_jobs([Job|Jobs], JobFun, N) ->
+ JobFun(Job),
+ launch_jobs(Jobs, JobFun, N - 1);
+launch_jobs([], _JobFun, _) ->
+ [].
+
+job_fun(none, Mode, InitData, Coordinator) ->
+ fun(Job) ->
+ _ = dialyzer_worker:launch(Mode, Job, InitData, Coordinator),
+ ok
+ end;
+job_fun(SCCtoPid, Mode, InitData, Coordinator) ->
+ fun(Job) ->
+ Pid = dialyzer_worker:launch(Mode, Job, InitData, Coordinator),
+ true = ets:insert(SCCtoPid, {Job, Pid}),
+ ok
+ end.
collect_result(#state{mode = Mode, active = Active, result = Result,
next_label = NextLabel, init_data = InitData,
jobs = JobsLeft, job_fun = JobFun,
- regulator = Regulator, scc_to_pid = SCCtoPID} = State) ->
+ 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),
- TypesigOrDataflow = (Mode =:= 'typesig') orelse (Mode =:= 'dataflow'),
case Active of
1 ->
+ %% This was the last running job. Clean up and return the result.
kill_regulator(Regulator),
case Mode of
'compile' ->
{NewResult, NextLabel};
- _ when TypesigOrDataflow ->
- ets:delete(SCCtoPID),
- NewResult;
- 'warnings' ->
+ _ ->
+ if
+ SCCtoPid =:= none -> ok;
+ true -> ets:delete(SCCtoPid)
+ end,
NewResult
end;
N ->
- case TypesigOrDataflow of
- true -> true = ets:delete(SCCtoPID, Job);
- false -> true
+ if
+ SCCtoPid =:= none -> ok;
+ true -> true = ets:delete(SCCtoPid, Job)
end,
NewJobsLeft =
case JobsLeft of
@@ -180,46 +278,23 @@ collect_result(#state{mode = Mode, active = Active, result = Result,
end.
update_result(Mode, InitData, Job, Data, Result) ->
- case Mode of
- 'compile' ->
+ if
+ Mode =:= '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' ->
+ Mode =:= 'typesig'; Mode =:= 'dataflow' ->
+ dialyzer_succ_typings:add_to_result(Data, Result, InitData);
+ true ->
Data ++ Result
end.
--spec sccs_to_pids([scc() | module()], coordinator()) ->
- [dialyzer_worker:worker()].
-
-sccs_to_pids(SCCs, {_Collector, _Regulator, SCCtoPID}) ->
- Fold =
- fun(SCC, Pids) ->
- %% The SCCs that SCC depends on have always been started.
- try ets:lookup_element(SCCtoPID, SCC, 2) of
- Pid when is_pid(Pid) ->
- [Pid|Pids]
- catch
- _:_ -> Pids
- 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.
+%%--------------------------------------------------------------------
+%% The regulator server
+%%
+%% The regulator limits the number of simultaneous running jobs to the
+%% number of schedulers. Note that there are usually many more worker
+%% processes started, but they are only allowed to do light work (such
+%% as monitoring other processes) when they have not been activated.
-spec wait_activation() -> ok.
@@ -229,12 +304,6 @@ wait_activation() ->
activate_pid(Pid) ->
Pid ! activate.
--spec request_activation(coordinator()) -> ok.
-
-request_activation({_Collector, Regulator, _SCCtoPID}) ->
- Regulator ! {req, self()},
- wait_activation().
-
spawn_regulator() ->
InitTickets = dialyzer_utils:parallelism(),
spawn_link(fun() -> regulator_loop(InitTickets, queue:new()) end).
@@ -250,15 +319,13 @@ regulator_loop(Tickets, Queue) ->
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);
+ case queue:out(Queue) of
+ {empty, NewQueue} ->
+ regulator_loop(Tickets + 1, NewQueue);
+ {{value, Pid}, NewQueue} ->
+ activate_pid(Pid),
+ regulator_loop(Tickets, NewQueue)
+ end;
stop -> ok
end.
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 2323889a51..ece162382f 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -24,16 +24,6 @@
-export([get_fun_types/5, get_warnings/5, format_args/3]).
-%% 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,
- state__find_function/2]).
-
--export_type([state/0]).
-
-include("dialyzer.hrl").
-import(erl_types,
@@ -53,7 +43,7 @@
t_is_any/1, t_is_atom/1, t_is_atom/2, t_is_any_atom/3,
t_is_boolean/2,
t_is_integer/2, t_is_list/1,
- t_is_nil/2, t_is_none/1, t_is_none_or_unit/1,
+ t_is_nil/2, t_is_none/1, t_is_impossible/1,
t_is_number/2, t_is_reference/2, t_is_pid/2, t_is_port/2,
t_is_unit/1,
t_limit/2, t_list/0, t_list_elements/2,
@@ -85,37 +75,23 @@
-type curr_fun() :: 'undefined' | 'top' | mfa_or_funlbl().
--define(no_arg, no_arg).
-
-define(TYPE_LIMIT, 3).
-define(BITS, 128).
-%% Types with comment 'race' are due to dialyzer_races.erl.
--record(state, {callgraph :: dialyzer_callgraph:callgraph()
- | 'undefined', % race
- codeserver :: dialyzer_codeserver:codeserver()
- | 'undefined', % race
- envs :: env_tab()
- | 'undefined', % race
- fun_tab :: fun_tab()
- | 'undefined', % race
- fun_homes :: dict:dict(label(), mfa())
- | 'undefined', % race
- reachable_funs :: sets:set(label())
- | 'undefined', % race
- plt :: dialyzer_plt:plt()
- | 'undefined', % race
- opaques :: [type()]
- | 'undefined', % race
- races = dialyzer_races:new() :: dialyzer_races:races(),
+-record(state, {callgraph :: dialyzer_callgraph:callgraph(),
+ codeserver :: dialyzer_codeserver:codeserver(),
+ envs :: env_tab(),
+ fun_tab :: fun_tab(),
+ fun_homes :: dict:dict(label(), mfa()),
+ reachable_funs :: sets:set(label()),
+ plt :: dialyzer_plt:plt(),
+ opaques :: [type()],
records = dict:new() :: types(),
- tree_map :: dict:dict(label(), cerl:cerl())
- | 'undefined', % race
+ tree_map :: dict:dict(label(), cerl:cerl()),
warning_mode = false :: boolean(),
warnings = [] :: [raw_warning()],
- work :: {[_], [_], sets:set()}
- | 'undefined', % race
+ work :: {[_], [_], sets:set()},
module :: module(),
curr_fun :: curr_fun()
}).
@@ -134,9 +110,7 @@
-type type_tab() :: #{key() => type()}.
-type subst_tab() :: #{key() => cerl:cerl()}.
-%% Exported Types
-
--opaque state() :: #state{}.
+-type state() :: #state{}.
%%--------------------------------------------------------------------
@@ -151,8 +125,7 @@
get_warnings(Tree, Plt, Callgraph, Codeserver, Records) ->
State1 = analyze_module(Tree, Plt, Callgraph, Codeserver, Records, true),
State2 = state__renew_warnings(state__get_warnings(State1), State1),
- State3 = state__get_race_warnings(State2),
- {State3#state.warnings, state__all_fun_types(State3)}.
+ {State2#state.warnings, state__all_fun_types(State2)}.
-spec get_fun_types(cerl:c_module(), dialyzer_plt:plt(),
dialyzer_callgraph:callgraph(),
@@ -174,15 +147,13 @@ analyze_module(Tree, Plt, Callgraph, Codeserver, Records, GetWarnings) ->
Module = cerl:atom_val(cerl:module_name(Tree)),
TopFun = cerl:ann_c_fun([{label, top}], [], Tree),
State = state__new(Callgraph, Codeserver, TopFun, Plt, Module, Records),
- State1 = state__race_analysis(not GetWarnings, State),
- State2 = analyze_loop(State1),
+ State1 = analyze_loop(State),
case GetWarnings of
true ->
- State3 = state__set_warning_mode(State2),
- State4 = analyze_loop(State3),
- dialyzer_races:race(State4);
+ State2 = state__set_warning_mode(State1),
+ analyze_loop(State2);
false ->
- State2
+ State1
end.
analyze_loop(State) ->
@@ -211,32 +182,16 @@ analyze_loop(State) ->
Vars = cerl:fun_vars(Fun),
Map1 = enter_type_lists(Vars, ArgTypes, Map),
Body = cerl:fun_body(Fun),
- FunLabel = get_label(Fun),
- IsRaceAnalysisEnabled = is_race_analysis_enabled(State),
- NewState3 =
- case IsRaceAnalysisEnabled of
- true ->
- NewState2 = state__renew_curr_fun(
- state__lookup_name(FunLabel, NewState1), FunLabel,
- NewState1),
- state__renew_race_list([], 0, NewState2);
- false -> NewState1
- end,
- {NewState4, _Map2, BodyType} =
- traverse(Body, Map1, NewState3),
+ {NewState2, _Map2, BodyType} =
+ traverse(Body, Map1, NewState1),
?debug("Done analyzing: ~w:~ts\n",
[NewState1#state.curr_fun,
t_to_string(t_fun(ArgTypes, BodyType))]),
- NewState5 =
- case IsRaceAnalysisEnabled of
- true -> renew_race_code(NewState4);
- false -> NewState4
- end,
- NewState6 =
- state__update_fun_entry(Fun, ArgTypes, BodyType, NewState5),
+ NewState3 =
+ state__update_fun_entry(Fun, ArgTypes, BodyType, NewState2),
?debug("done adding stuff for ~tw\n",
[state__lookup_name(get_label(Fun), State)]),
- analyze_loop(NewState6)
+ analyze_loop(NewState3)
end
end
end.
@@ -295,63 +250,17 @@ traverse(Tree, Map, State) ->
literal ->
Type = literal_type(Tree),
{State, Map, Type};
- module ->
- handle_module(Tree, Map, State);
primop ->
- case cerl:atom_val(cerl:primop_name(Tree)) of
- match_fail ->
- {State, Map, t_none()};
- raise ->
- {State, Map, t_none()};
- bs_init_writable ->
- {State, Map, t_from_term(<<>>)};
- build_stacktrace ->
- {State, Map, erl_bif_types:type(erlang, build_stacktrace, 0)};
- dialyzer_unknown ->
- {State, Map, t_any()};
- recv_peek_message ->
- {State, Map, t_product([t_boolean(), t_any()])};
- recv_wait_timeout ->
- [Arg] = cerl:primop_args(Tree),
- {State1, Map1, TimeoutType} = traverse(Arg, Map, State),
- Opaques = State1#state.opaques,
- case t_is_atom(TimeoutType, Opaques) andalso
- t_atom_vals(TimeoutType, Opaques) =:= ['infinity'] of
- true ->
- {State1, Map1, t_boolean()};
- false ->
- {State1, Map1, t_boolean()}
- end;
- remove_message ->
- {State, Map, t_any()};
- timeout ->
- {State, Map, t_any()};
- Other -> erlang:error({'Unsupported primop', Other})
- end;
- 'receive' ->
- handle_receive(Tree, Map, State);
+ handle_primop(Tree, Map, State);
seq ->
Arg = cerl:seq_arg(Tree),
Body = cerl:seq_body(Tree),
{State1, Map1, ArgType} = SMA = traverse(Arg, Map, State),
- case t_is_none_or_unit(ArgType) of
+ case t_is_impossible(ArgType) of
true ->
SMA;
false ->
- State2 =
- case
- t_is_any(ArgType)
- orelse t_is_simple(ArgType, State)
- orelse is_call_to_send(Arg)
- orelse is_lc_simple_list(Arg, ArgType, State)
- of
- true -> % do not warn in these cases
- State1;
- false ->
- state__add_warning(State1, ?WARN_UNMATCHED_RETURN, Arg,
- {unmatched_return,
- [format_type(ArgType, State1)]})
- end,
+ State2 = maybe_warn_unmatched_return(Arg, ArgType, State1),
traverse(Body, Map1, State2)
end;
'try' ->
@@ -386,6 +295,27 @@ traverse_list([Tree|Tail], Map, State, Acc) ->
traverse_list([], Map, State, Acc) ->
{State, Map, lists:reverse(Acc)}.
+maybe_warn_unmatched_return(Arg, ArgType, State) ->
+ case state__warning_mode(State) of
+ false ->
+ State;
+ true ->
+ %% Warn when return values such as 'ok' | {'error',any()}
+ %% are ignored. Don't warn when a single value such as 'ok'
+ %% is returned.
+ case t_is_any(ArgType) orelse
+ t_is_simple(ArgType, State) orelse
+ is_call_to_send(Arg) orelse
+ is_lc_simple_list(Arg, ArgType, State) of
+ true ->
+ State;
+ false ->
+ state__add_warning(State, ?WARN_UNMATCHED_RETURN, Arg,
+ {unmatched_return,
+ [format_type(ArgType, State)]})
+ end
+ end.
+
%%________________________________________
%%
%% Special instructions
@@ -550,16 +480,6 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
?debug("ContrRet: ~ts\n", [erl_types:t_to_string(ContrRet)]),
?debug("LocalRet: ~ts\n", [erl_types:t_to_string(LocalRet)]),
- State1 =
- case is_race_analysis_enabled(State) of
- true ->
- Ann = cerl:get_ann(Tree),
- File = get_file(Ann, State),
- Location = get_location(Tree),
- dialyzer_races:store_race_call(Fun, ArgTypes, Args,
- {File, Location}, State);
- false -> State
- end,
FailedConj = any_none([RetWithoutLocal|NewArgTypes]),
IsFailBif = t_is_none(BifRange(BifArgs)),
IsFailSig = t_is_none(SigRange),
@@ -581,7 +501,7 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
%% This Msg will be post_processed by dialyzer_succ_typings
Msg =
{contract_range, [Contract, M1, F1, A1, ArgStrings, CRet]},
- state__add_warning(State1, ?WARN_CONTRACT_RANGE, Tree, Msg);
+ state__add_warning(State, ?WARN_CONTRACT_RANGE, Tree, Msg);
false ->
FailedSig = any_none(NewArgsSig),
FailedContract =
@@ -592,7 +512,7 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
FailReason =
apply_fail_reason(FailedSig, FailedBif, FailedContract),
Msg = get_apply_fail_msg(Fun, Args, ArgTypes, NewArgTypes, InfSig,
- Contr, CArgs, State1, FailReason, Opaques),
+ Contr, CArgs, State, FailReason, Opaques),
WarnType = case Msg of
{call, _} -> ?WARN_FAILING_CALL;
{apply, _} -> ?WARN_FAILING_CALL;
@@ -614,9 +534,9 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
Tree
end,
Frc = {erlang, is_record, 3} =:= state__lookup_name(Fun, State),
- state__add_warning(State1, WarnType, LocTree, Msg, Frc)
+ state__add_warning(State, WarnType, LocTree, Msg, Frc)
end;
- false -> State1
+ false -> State
end,
State3 =
case TypeOfApply of
@@ -767,17 +687,17 @@ find_unknown(ContractOrSigList, ArgTypes, Opaques, NoneArgNs) ->
is_opaque_type_test_problem(Fun, Args, ArgTypes, State) ->
case Fun of
- {erlang, FN, 1} when FN =:= is_atom; FN =:= is_boolean;
- FN =:= is_binary; FN =:= is_bitstring;
- FN =:= is_float; FN =:= is_function;
- FN =:= is_integer; FN =:= is_list;
- FN =:= is_number; FN =:= is_pid; FN =:= is_port;
- FN =:= is_reference; FN =:= is_tuple;
- FN =:= is_map ->
- type_test_opaque_arg(Args, ArgTypes, State#state.opaques);
{erlang, FN, 2} when FN =:= is_function ->
type_test_opaque_arg(Args, ArgTypes, State#state.opaques);
- _ -> no
+ {erlang, FN, 1} ->
+ case t_is_any(type_test_type(FN, 1)) of
+ true ->
+ no;
+ false ->
+ type_test_opaque_arg(Args, ArgTypes, State#state.opaques)
+ end;
+ _ ->
+ no
end.
type_test_opaque_arg([], [], _Opaques) ->
@@ -857,7 +777,7 @@ handle_bitstr(Tree, Map, State) ->
{State1, Map1, SizeType0} = traverse(Size, Map, State),
{State2, Map2, ValType0} = traverse(Val, Map1, State1),
case cerl:bitstr_bitsize(Tree) of
- BitSz when BitSz =:= all orelse BitSz =:= utf ->
+ BitSz when BitSz =:= all; BitSz =:= utf ->
ValType =
case BitSz of
all ->
@@ -878,7 +798,7 @@ handle_bitstr(Tree, Map, State) ->
false ->
{State2, Map3, t_bitstr()}
end;
- BitSz when is_integer(BitSz) orelse BitSz =:= any ->
+ BitSz when is_integer(BitSz); BitSz =:= any ->
SizeType = t_inf(SizeType0, t_non_neg_integer()),
ValType =
case BitstrType of
@@ -1004,29 +924,18 @@ handle_case(Tree, Map, State) ->
Arg = cerl:case_arg(Tree),
Clauses = cerl:case_clauses(Tree),
{State1, Map1, ArgType} = SMA = traverse(Arg, Map, State),
- case t_is_none_or_unit(ArgType) of
+ case t_is_impossible(ArgType) of
true -> SMA;
false ->
- State2 =
- case is_race_analysis_enabled(State) of
- true ->
- {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, Warns} =
- handle_clauses(Clauses, Arg, ArgType, ArgType, State2,
- [], Map2, [], [], []),
+ handle_clauses(Clauses, Arg, ArgType, Map2, State1),
%% Non-Erlang BEAM languages, such as Elixir, expand language constructs
%% into case statements. In that case, we do not want to warn on
%% individual clauses not matching unless none of them can.
- SupressForced = is_compiler_generated(cerl:get_ann(Tree))
- andalso not (t_is_none(Type)),
+ DoForce = not is_compiler_generated(cerl:get_ann(Tree)) orelse t_is_none(Type),
State4 = lists:foldl(fun({T,R,M,F}, S) ->
- state__add_warning(
- S,T,R,M,F andalso (not SupressForced))
+ state__add_warning(S, T, R, M, F andalso DoForce)
end, State3, Warns),
Map3 = join_maps_end(MapList, Map2),
debug_pp_map(Map3),
@@ -1054,99 +963,57 @@ handle_cons(Tree, Map, State) ->
%%----------------------------------------
handle_let(Tree, Map, State) ->
- IsRaceAnalysisEnabled = is_race_analysis_enabled(State),
Arg = cerl:let_arg(Tree),
Vars = cerl:let_vars(Tree),
{Map0, State0} =
case cerl:is_c_var(Arg) of
true ->
[Var] = Vars,
- {enter_subst(Var, Arg, Map),
- case IsRaceAnalysisEnabled of
- true ->
- {RaceList, RaceListSize} = get_race_list_and_size(State),
- state__renew_race_list(
- [dialyzer_races:let_tag_new(Var, Arg)|RaceList],
- RaceListSize + 1, State);
- false -> State
- end};
+ {enter_subst(Var, Arg, Map), State};
false -> {Map, State}
end,
Body = cerl:let_body(Tree),
{State1, Map1, ArgTypes} = SMA = traverse(Arg, Map0, State0),
- State2 =
- case IsRaceAnalysisEnabled andalso cerl:is_c_call(Arg) of
- true ->
- Mod = cerl:call_module(Arg),
- Name = cerl:call_name(Arg),
- case cerl:is_literal(Mod) andalso
- cerl:concrete(Mod) =:= ets andalso
- cerl:is_literal(Name) andalso
- cerl:concrete(Name) =:= new of
- true -> renew_race_public_tables(Vars, State1);
- false -> State1
- end;
- false -> State1
- end,
- case t_is_none_or_unit(ArgTypes) of
+ case t_is_impossible(ArgTypes) of
true -> SMA;
false ->
Map2 = enter_type_lists(Vars, t_to_tlist(ArgTypes), Map1),
- traverse(Body, Map2, State2)
+ traverse(Body, Map2, State1)
end.
%%----------------------------------------
-handle_module(Tree, Map, State) ->
- %% By not including the variables in scope we can assure that we
- %% will get the current function type when using the variables.
- Defs = cerl:module_defs(Tree),
- PartFun = fun({_Var, Fun}) ->
- state__is_escaping(get_label(Fun), State)
- end,
- {Defs1, Defs2} = lists:partition(PartFun, Defs),
- Letrec = cerl:c_letrec(Defs1, cerl:c_int(42)),
- {State1, Map1, _FunTypes} = traverse(Letrec, Map, State),
- %% Also add environments for the other top-level functions.
- VarTypes = [{Var, state__fun_type(Fun, State1)} || {Var, Fun} <- Defs],
- EnvMap = enter_type_list(VarTypes, Map),
- FoldFun = fun({_Var, Fun}, AccState) ->
- state__update_fun_env(Fun, EnvMap, AccState)
- end,
- State2 = lists:foldl(FoldFun, State1, Defs2),
- {State2, Map1, t_any()}.
-
-%%----------------------------------------
-
-handle_receive(Tree, Map, State) ->
- Clauses = cerl:receive_clauses(Tree),
- Timeout = cerl:receive_timeout(Tree),
- State1 =
- case is_race_analysis_enabled(State) of
- true ->
- {RaceList, RaceListSize} = get_race_list_and_size(State),
- state__renew_race_list([beg_case|RaceList],
- RaceListSize + 1, State);
- false -> State
- end,
- {MapList, State2, ReceiveType, Warns} =
- handle_clauses(Clauses, ?no_arg, t_any(), t_any(), State1, [], Map,
- [], [], []),
- State3 = lists:foldl(fun({T,R,M,F}, S) -> state__add_warning(S,T,R,M,F) end,
- State2, Warns),
- Map1 = join_maps(MapList, Map),
- {State4, Map2, TimeoutType} = traverse(Timeout, Map1, State3),
- Opaques = State4#state.opaques,
- case (t_is_atom(TimeoutType, Opaques) andalso
- (t_atom_vals(TimeoutType, Opaques) =:= ['infinity'])) of
- true ->
- {State4, Map2, ReceiveType};
- false ->
- Action = cerl:receive_action(Tree),
- {State5, Map3, ActionType} = traverse(Action, Map, State4),
- Map4 = join_maps([Map3, Map1], Map),
- Type = t_sup(ReceiveType, ActionType),
- {State5, Map4, Type}
+handle_primop(Tree, Map, State) ->
+ case cerl:atom_val(cerl:primop_name(Tree)) of
+ match_fail ->
+ {State, Map, t_none()};
+ raise ->
+ {State, Map, t_none()};
+ bs_init_writable ->
+ {State, Map, t_from_term(<<>>)};
+ build_stacktrace ->
+ {State, Map, erl_bif_types:type(erlang, build_stacktrace, 0)};
+ dialyzer_unknown ->
+ {State, Map, t_any()};
+ recv_peek_message ->
+ {State, Map, t_product([t_boolean(), t_any()])};
+ recv_wait_timeout ->
+ [Arg] = cerl:primop_args(Tree),
+ {State1, Map1, TimeoutType} = traverse(Arg, Map, State),
+ Opaques = State1#state.opaques,
+ case t_is_atom(TimeoutType, Opaques) andalso
+ t_atom_vals(TimeoutType, Opaques) =:= ['infinity'] of
+ true ->
+ {State1, Map1, t_boolean()};
+ false ->
+ {State1, Map1, t_boolean()}
+ end;
+ remove_message ->
+ {State, Map, t_any()};
+ nif_start ->
+ {State, Map, t_any()};
+ Other ->
+ error({'Unsupported primop', Other})
end.
%%----------------------------------------
@@ -1165,14 +1032,14 @@ handle_try(Tree, Map, State) ->
true ->
Map2 = mark_as_fresh(Vars, Map1),
{SuccState, SuccMap, SuccType} =
- case bind_pat_vars(Vars, TypeList, [], Map2, State1) of
+ case bind_pat_vars(Vars, TypeList, Map2, State1) of
{error, _, _, _, _} ->
{State1, map__new(), t_none()};
{SuccMap1, VarTypes} ->
%% Try to bind the argument. Will only succeed if
%% it is a simple structured term.
SuccMap2 =
- case bind_pat_vars_reverse([Arg], [t_product(VarTypes)], [],
+ case bind_pat_vars_reverse([Arg], [t_product(VarTypes)],
SuccMap1, State1) of
{error, _, _, _, _} -> SuccMap1;
{SM, _} -> SM
@@ -1192,7 +1059,7 @@ handle_map(Tree,Map,State) ->
Arg = cerl:map_arg(Tree),
{State1, Map1, ArgType} = traverse(Arg, Map, State),
ArgType1 = t_inf(t_map(), ArgType),
- case t_is_none_or_unit(ArgType1) of
+ case t_is_impossible(ArgType1) of
true ->
{State1, Map1, ArgType1};
false ->
@@ -1208,7 +1075,7 @@ handle_map(Tree,Map,State) ->
try lists:foldl(InsertPair, ArgType1, TypePairs)
of ResT ->
BindT = t_map([{K, t_any()} || K <- ExactKeys]),
- case bind_pat_vars_reverse([Arg], [BindT], [], Map2, State2) of
+ case bind_pat_vars_reverse([Arg], [BindT], Map2, State2) of
{error, _, _, _, _} -> {State2, Map2, ResT};
{Map3, _} -> {State2, Map3, ResT}
end
@@ -1269,7 +1136,7 @@ handle_tuple(Tree, Map, State) ->
{State2, Map1, t_none()};
false ->
case bind_pat_vars(Elements, t_tuple_args(RecType),
- [], Map1, State1) of
+ Map1, State1) of
{error, bind, ErrorPat, ErrorType, _} ->
Msg = {record_constr,
[TagVal, format_patterns(ErrorPat),
@@ -1322,229 +1189,209 @@ field_name(Elements, ErrorPat, FieldNames) ->
%%----------------------------------------
%% Clauses
%%
-handle_clauses([C|Left], Arg, ArgType, OrigArgType, State, CaseTypes, MapIn,
- Acc, ClauseAcc, WarnAcc0) ->
- IsRaceAnalysisEnabled = is_race_analysis_enabled(State),
- State1 =
- case IsRaceAnalysisEnabled of
- true ->
- {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))|
- RaceList], RaceListSize + 1,
- State);
- false -> State
- end,
- {State2, ClauseMap, BodyType, NewArgType, WarnAcc} =
- do_clause(C, Arg, ArgType, OrigArgType, MapIn, State1, WarnAcc0),
- {NewClauseAcc, State3} =
- case IsRaceAnalysisEnabled of
- true ->
- {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],
- state__renew_race_list([EndClause|RaceList1],
- RaceListSize1 + 1, State2)};
- false -> {ClauseAcc, State2}
- end,
- {NewCaseTypes, NewAcc} =
- case t_is_none(BodyType) of
- true -> {CaseTypes, Acc};
- false -> {[BodyType|CaseTypes], [ClauseMap|Acc]}
- end,
- handle_clauses(Left, Arg, NewArgType, OrigArgType, State3,
- NewCaseTypes, MapIn, NewAcc, NewClauseAcc, WarnAcc);
-handle_clauses([], _Arg, _ArgType, _OrigArgType, State, CaseTypes, _MapIn, Acc,
- ClauseAcc, WarnAcc) ->
- State1 =
- 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)|RaceList],
- RaceListSize + 1, State);
- false -> State
- end,
- {lists:reverse(Acc), State1, t_sup(CaseTypes), WarnAcc}.
-do_clause(C, Arg, ArgType0, OrigArgType, Map, State, Warns) ->
+handle_clauses(Cs, Arg, ArgType, Map, State) ->
+ handle_clauses(Cs, Arg, ArgType, ArgType, Map, State, [], [], []).
+
+handle_clauses([C|Cs], Arg, ArgType, OrigArgType, MapIn, State,
+ CaseTypes, Acc, WarnAcc0) ->
+ {State1, ClauseMap, BodyType, NewArgType, WarnAcc} =
+ do_clause(C, Arg, ArgType, OrigArgType, MapIn, State, WarnAcc0),
+ case t_is_none(BodyType) of
+ true ->
+ handle_clauses(Cs, Arg, NewArgType, OrigArgType, MapIn, State1,
+ CaseTypes, Acc, WarnAcc);
+ false ->
+ handle_clauses(Cs, Arg, NewArgType, OrigArgType, MapIn, State1,
+ [BodyType|CaseTypes], [ClauseMap|Acc], WarnAcc)
+ end;
+handle_clauses([], _Arg, _ArgType, _OrigArgType, _MapIn, State,
+ CaseTypes, Acc, WarnAcc) ->
+ {lists:reverse(Acc), State, t_sup(CaseTypes), WarnAcc}.
+
+%%
+%% Process one clause.
+%%
+%% ArgType is the current type of the case argument; the types for
+%% all previously matched clauses have been subtracted from it.
+%%
+%% OrigArgType is the original type of the case argument. We need it
+%% to produce better warnings when a clause does not match.
+%%
+do_clause(C, Arg, ArgType, OrigArgType, Map, State, Warns) ->
Pats = cerl:clause_pats(C),
- Guard = cerl:clause_guard(C),
- Body = cerl:clause_body(C),
- State1 =
- case is_race_analysis_enabled(State) of
- true ->
- state__renew_fun_args(Pats, State);
- false -> State
- end,
Map0 = mark_as_fresh(Pats, Map),
- Map1 = if Arg =:= ?no_arg -> Map0;
- true -> bind_subst(Arg, Pats, Map0)
- end,
+ Map1 = bind_subst(Arg, Pats, Map0),
+
+ %% Try to bind the pattern to the case argument.
BindRes =
- case t_is_none(ArgType0) of
+ case t_is_none(ArgType) of
true ->
- {error, bind, Pats, ArgType0, ArgType0};
+ {error, maybe_covered, OrigArgType, ignore, ignore};
false ->
- ArgTypes =
- case t_is_any(ArgType0) of
- true -> [ArgType0 || _ <- Pats];
- false -> t_to_tlist(ArgType0)
- end,
- bind_pat_vars(Pats, ArgTypes, [], Map1, State1)
+ ArgTypes = get_arg_list(ArgType, Pats),
+ bind_pat_vars(Pats, ArgTypes, Map1, State)
end,
+
+ %% Test whether the binding succeeded.
case BindRes of
- {error, ErrorType, NewPats, Type, OpaqueTerm} ->
+ {error, _ErrorType, _NewPats, _Type, _OpaqueTerm} ->
?debug("Failed binding pattern: ~ts\nto ~ts\n",
- [cerl_prettypr:format(C), format_type(ArgType0, State1)]),
- case state__warning_mode(State1) of
- false ->
- {State1, Map, t_none(), ArgType0, Warns};
- true ->
- {Msg, Force} =
- case t_is_none(ArgType0) of
- true ->
- %% See if this is covered by an earlier clause or if it
- %% simply cannot match
- OrigArgTypes =
- case t_is_any(OrigArgType) of
- true -> Any = t_any(), [Any || _ <- Pats];
- false -> t_to_tlist(OrigArgType)
- end,
- PatString = format_patterns(Pats),
- ArgTypeString = format_type(OrigArgType, State1),
- BindResOrig =
- bind_pat_vars(Pats, OrigArgTypes, [], Map1, State1),
- Tag =
- case BindResOrig of
- {error, bind, _, _, _} -> pattern_match;
- {error, record, _, _, _} -> record_match;
- {error, opaque, _, _, _} -> opaque_match;
- {_, _} -> pattern_match_cov
- end,
- PatTypes = case BindResOrig of
- {error, opaque, _, _, OpaqueType} ->
- [PatString, ArgTypeString,
- format_type(OpaqueType, State1)];
- _ -> [PatString, ArgTypeString]
- end,
- {{Tag, PatTypes}, false};
- false ->
- %% Try to find out if this is a default clause in a list
- %% comprehension and suppress this. A real Hack(tm)
- Force0 =
- case is_compiler_generated(cerl:get_ann(C)) of
- true ->
- case Pats of
- [Pat] ->
- case cerl:is_c_cons(Pat) of
- true ->
- not (cerl:is_c_var(cerl:cons_hd(Pat)) andalso
- cerl:is_c_var(cerl:cons_tl(Pat)) andalso
- cerl:is_literal(Guard) andalso
- (cerl:concrete(Guard) =:= true));
- false ->
- true
- end;
- [Pat0, Pat1] -> % binary comprehension
- case cerl:is_c_cons(Pat0) of
- true ->
- not (cerl:is_c_var(cerl:cons_hd(Pat0)) andalso
- cerl:is_c_var(cerl:cons_tl(Pat0)) andalso
- cerl:is_c_var(Pat1) andalso
- cerl:is_literal(Guard) andalso
- (cerl:concrete(Guard) =:= true));
- false ->
- true
- end;
- _ -> true
- end;
- false ->
- true
- end,
- PatString =
- case ErrorType of
- bind -> format_patterns(Pats);
- record -> format_patterns(NewPats);
- opaque -> format_patterns(NewPats)
- end,
- PatTypes = case ErrorType of
- bind -> [PatString, format_type(ArgType0, State1)];
- record -> [PatString, format_type(Type, State1)];
- opaque -> [PatString, format_type(Type, State1),
- format_type(OpaqueTerm, State1)]
- end,
- FailedTag = case ErrorType of
- bind -> pattern_match;
- record -> record_match;
- opaque -> opaque_match
- end,
- {{FailedTag, PatTypes}, Force0}
- end,
- WarnType = case Msg of
- {opaque_match, _} -> ?WARN_OPAQUE;
- {pattern_match, _} -> ?WARN_MATCHING;
- {record_match, _} -> ?WARN_MATCHING;
- {pattern_match_cov, _} -> ?WARN_MATCHING
- end,
- {State1, Map, t_none(), ArgType0, [{WarnType, C, Msg, Force}|Warns]}
- end;
+ [cerl_prettypr:format(C), format_type(ArgType, State)]),
+ NewWarns =
+ case state__warning_mode(State) of
+ false ->
+ Warns;
+ true ->
+ Warn = clause_error(State, Map1, BindRes, C, Pats, ArgType),
+ [Warn|Warns]
+ end,
+ {State, Map, t_none(), ArgType, NewWarns};
{Map2, PatTypes} ->
+ %% Try to bind the argument. Will only succeed if
+ %% it is a simple structured term.
Map3 =
- case Arg =:= ?no_arg of
- true -> Map2;
- false ->
- %% Try to bind the argument. Will only succeed if
- %% it is a simple structured term.
- case bind_pat_vars_reverse([Arg], [t_product(PatTypes)],
- [], Map2, State1) of
- {error, _, _, _, _} -> Map2;
- {NewMap, _} -> NewMap
- end
+ case bind_pat_vars_reverse([Arg], [t_product(PatTypes)],
+ Map2, State) of
+ {error, _, _, _, _} -> Map2;
+ {NewMap, _} -> NewMap
end,
- NewArgType =
- case Arg =:= ?no_arg of
- true -> ArgType0;
- false ->
- GenType = dialyzer_typesig:get_safe_underapprox(Pats, Guard),
- t_subtract(t_product(t_to_tlist(ArgType0)), GenType)
- end,
- case bind_guard(Guard, Map3, State1) of
+
+ %% Subtract the matched type from the case argument. That will
+ %% allow us to find clauses that are covered by previous
+ %% clauses.
+ Guard = cerl:clause_guard(C),
+ GenType = dialyzer_typesig:get_safe_underapprox(Pats, Guard),
+ NewArgType = t_subtract(t_product(t_to_tlist(ArgType)), GenType),
+
+ %% Now test whether the guard will succeed.
+ case bind_guard(Guard, Map3, State) of
{error, Reason} ->
?debug("Failed guard: ~ts\n",
[cerl_prettypr:format(C, [{hook, cerl_typean:pp_hook()}])]),
- PatString = format_patterns(Pats),
- DefaultMsg =
- case Pats =:= [] of
- true -> {guard_fail, []};
- false ->
- {guard_fail_pat, [PatString, format_type(ArgType0, State1)]}
- end,
- Warn =
- case Reason of
- none -> {?WARN_MATCHING, C, DefaultMsg, false};
- {FailGuard, Msg} ->
- case is_compiler_generated(cerl:get_ann(FailGuard)) of
- false ->
- WarnType = case Msg of
- {guard_fail, _} -> ?WARN_MATCHING;
- {neg_guard_fail, _} -> ?WARN_MATCHING;
- {opaque_guard, _} -> ?WARN_OPAQUE
- end,
- {WarnType, FailGuard, Msg, false};
- true ->
- {?WARN_MATCHING, C, Msg, false}
- end
- end,
- {State1, Map, t_none(), NewArgType, [Warn|Warns]};
+ Warn = clause_guard_error(State, Reason, C, Pats, ArgType),
+ {State, Map, t_none(), NewArgType, [Warn|Warns]};
Map4 ->
- {RetState, RetMap, BodyType} = traverse(Body, Map4, State1),
+ Body = cerl:clause_body(C),
+ {RetState, RetMap, BodyType} = traverse(Body, Map4, State),
{RetState, RetMap, BodyType, NewArgType, Warns}
end
end.
+clause_error(State, Map, {error, maybe_covered, OrigArgType, _, _}, C, Pats, _) ->
+ %% This clause is covered by previous clauses, but it is possible
+ %% that it would never match anyway. Find out by matching the
+ %% original argument types of the case.
+ OrigArgTypes = get_arg_list(OrigArgType, Pats),
+ Msg =
+ case bind_pat_vars(Pats, OrigArgTypes, Map, State) of
+ {_, _} ->
+ %% The pattern would match if it had not been covered.
+ PatString = format_patterns(Pats),
+ ArgTypeString = format_type(OrigArgType, State),
+ {pattern_match_cov, [PatString, ArgTypeString]};
+ {error, ErrorType, _, _, OpaqueTerm} ->
+ %% This pattern can never match.
+ failed_msg(State, ErrorType, Pats, OrigArgType,
+ Pats, OrigArgType, OpaqueTerm)
+ end,
+ Force = false,
+ clause_error_warning(Msg, Force, C);
+clause_error(State, _Map, BindRes, C, Pats, ArgType) ->
+ %% This clause will never match. Always produce a warning
+ %% unless it is the default clause in a list comprehension
+ %% without any filters.
+ Force = not is_lc_default_clause(C),
+ {error, ErrorType, NewPats, NewType, OpaqueTerm} = BindRes,
+ Msg = failed_msg(State, ErrorType, Pats, ArgType, NewPats, NewType, OpaqueTerm),
+ clause_error_warning(Msg, Force, C).
+
+failed_msg(State, ErrorType, Pats, Type, NewPats, NewType, OpaqueTerm) ->
+ case ErrorType of
+ bind ->
+ {pattern_match, [format_patterns(Pats), format_type(Type, State)]};
+ record ->
+ {record_match, [format_patterns(NewPats), format_type(NewType, State)]};
+ opaque ->
+ {opaque_match, [format_patterns(NewPats), format_type(NewType, State),
+ format_type(OpaqueTerm, State)]}
+ end.
+
+clause_error_warning(Msg, Force, C) ->
+ {warn_type(Msg), C, Msg, Force}.
+
+warn_type({Tag, _}) ->
+ case Tag of
+ guard_fail -> ?WARN_MATCHING;
+ neg_guard_fail -> ?WARN_MATCHING;
+ opaque_guard -> ?WARN_OPAQUE;
+ opaque_match -> ?WARN_OPAQUE;
+ pattern_match -> ?WARN_MATCHING;
+ pattern_match_cov -> ?WARN_MATCHING;
+ record_match -> ?WARN_MATCHING
+ end.
+
+get_arg_list(ArgTypes, Pats) ->
+ case t_is_any(ArgTypes) of
+ true ->
+ [ArgTypes || _ <- Pats];
+ false ->
+ t_to_tlist(ArgTypes)
+ end.
+
+%% Test whether this clause is the default clause for a list
+%% or binary comprehension without any filters.
+is_lc_default_clause(C) ->
+ case is_compiler_generated(cerl:get_ann(C)) of
+ false ->
+ false;
+ true ->
+ case cerl:clause_pats(C) of
+ [Pat] -> % list comprehension
+ cerl:is_c_cons(Pat) andalso
+ cerl:is_c_var(cerl:cons_hd(Pat)) andalso
+ cerl:is_c_var(cerl:cons_tl(Pat)) andalso
+ does_guard_succeed(C);
+ [Pat0, Pat1] -> % binary comprehension
+ cerl:is_c_cons(Pat0) andalso
+ cerl:is_c_var(cerl:cons_hd(Pat0)) andalso
+ cerl:is_c_var(cerl:cons_tl(Pat0)) andalso
+ cerl:is_c_var(Pat1) andalso
+ does_guard_succeed(C);
+ _ ->
+ %% This should not happen with code generated by the
+ %% standard Erlang compiler. It can happen if the code was
+ %% generate by another code generator (such as Elixir) or a
+ %% parse transform.
+ false
+ end
+ end.
+
+does_guard_succeed(C) ->
+ Guard = cerl:clause_guard(C),
+ cerl:is_literal(Guard) andalso cerl:concrete(Guard) =:= true.
+
+clause_guard_error(State, Reason, C, Pats, ArgType) ->
+ case Reason of
+ none ->
+ Msg =
+ case Pats of
+ [] ->
+ {guard_fail, []};
+ [_|_] ->
+ PatString = format_patterns(Pats),
+ {guard_fail_pat, [PatString, format_type(ArgType, State)]}
+ end,
+ {?WARN_MATCHING, C, Msg, false};
+ {FailGuard, Msg} ->
+ case is_compiler_generated(cerl:get_ann(FailGuard)) of
+ false ->
+ {warn_type(Msg), FailGuard, Msg, false};
+ true ->
+ {?WARN_MATCHING, C, Msg, false}
+ end
+ end.
+
bind_subst(Arg, Pats, Map) ->
case cerl:type(Arg) of
values ->
@@ -1575,27 +1422,23 @@ bind_subst_list([], [], Map) ->
%% Patterns
%%
-bind_pat_vars(Pats, Types, Acc, Map, State) ->
- try
- bind_pat_vars(Pats, Types, Acc, Map, State, false)
- catch
- throw:Error ->
- %% Error = {error, bind | opaque | record, ErrorPats, ErrorType}
- Error
- end.
+bind_pat_vars(Pats, Types, Map, State) ->
+ bind_pat_vars(Pats, Types, Map, State, false).
-bind_pat_vars_reverse(Pats, Types, Acc, Map, State) ->
+bind_pat_vars_reverse(Pats, Types, Map, State) ->
+ bind_pat_vars(Pats, Types, Map, State, true).
+
+bind_pat_vars(Pats, Types, Map, State, Rev) ->
try
- bind_pat_vars(Pats, Types, Acc, Map, State, true)
+ do_bind_pat_vars(Pats, Types, Map, State, Rev, [])
catch
- throw:Error ->
+ throw:Error ->
%% Error = {error, bind | opaque | record, ErrorPats, ErrorType}
Error
end.
-bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
- ?debug("Binding pat: ~tw to ~ts\n", [cerl:type(Pat), format_type(Type, State)]
-),
+do_bind_pat_vars([Pat|Pats], [Type|Types], Map, State, Rev, Acc) ->
+ ?debug("Binding pat: ~tw to ~ts\n", [cerl:type(Pat), format_type(Type, State)]),
Opaques = State#state.opaques,
{NewMap, TypeOut} =
case cerl:type(Pat) of
@@ -1605,157 +1448,48 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
AliasPat = dialyzer_utils:refold_pattern(cerl:alias_pat(Pat)),
Var = cerl:alias_var(Pat),
Map1 = enter_subst(Var, AliasPat, Map),
- {Map2, [PatType]} = bind_pat_vars([AliasPat], [Type], [],
- Map1, State, Rev),
+ {Map2, [PatType]} = do_bind_pat_vars([AliasPat], [Type],
+ Map1, State, Rev, []),
{enter_type(Var, PatType, Map2), PatType};
binary ->
- %% Cannot bind the binary if we are in reverse match since
- %% binary patterns and binary construction are not symmetric.
case Rev of
- true -> {Map, t_bitstr()};
- false ->
- BinType = t_inf(t_bitstr(), Type, Opaques),
- case t_is_none(BinType) of
- true ->
- case t_find_opaque_mismatch(t_bitstr(), Type, Opaques) of
- {ok, T1, T2} ->
- bind_error([Pat], T1, T2, opaque);
- error ->
- bind_error([Pat], Type, t_none(), bind)
- end;
- false ->
- Segs = cerl:binary_segments(Pat),
- {Map1, SegTypes} = bind_bin_segs(Segs, BinType, Map, State),
- {Map1, t_bitstr_concat(SegTypes)}
- end
- end;
- cons ->
- Cons = t_inf(Type, t_cons(), Opaques),
- case t_is_none(Cons) of
true ->
- bind_opaque_pats(t_cons(), Type, Pat, State);
+ %% Cannot bind the binary if we are in reverse match since
+ %% binary patterns and binary construction are not
+ %% symmetric.
+ {Map, t_bitstr()};
false ->
- {Map1, [HdType, TlType]} =
- bind_pat_vars([cerl:cons_hd(Pat), cerl:cons_tl(Pat)],
- [t_cons_hd(Cons, Opaques),
- t_cons_tl(Cons, Opaques)],
- [], Map, State, Rev),
- {Map1, t_cons(HdType, TlType)}
+ BinType = bind_checked_inf(Pat, t_bitstr(), Type, Opaques),
+ Segs = cerl:binary_segments(Pat),
+ {Map1, SegTypes} = bind_bin_segs(Segs, BinType, Map, State),
+ {Map1, t_bitstr_concat(SegTypes)}
end;
+ cons ->
+ Cons = bind_checked_inf(Pat, t_cons(), Type, Opaques),
+ {Map1, [HdType, TlType]} =
+ do_bind_pat_vars([cerl:cons_hd(Pat), cerl:cons_tl(Pat)],
+ [t_cons_hd(Cons, Opaques),
+ t_cons_tl(Cons, Opaques)],
+ Map, State, Rev, []),
+ {Map1, t_cons(HdType, TlType)};
literal ->
Pat0 = dialyzer_utils:refold_pattern(Pat),
case cerl:is_literal(Pat0) of
true ->
- Literal = literal_type(Pat),
- case t_is_none(t_inf(Literal, Type, Opaques)) of
- true ->
- bind_opaque_pats(Literal, Type, Pat, State);
- false -> {Map, Literal}
- end;
+ LiteralType = bind_checked_inf(Pat, literal_type(Pat), Type, Opaques),
+ {Map, LiteralType};
false ->
- %% Retry with the unfolded pattern
- {Map1, [PatType]}
- = bind_pat_vars([Pat0], [Type], [], Map, State, Rev),
+ {Map1, [PatType]} = do_bind_pat_vars([Pat0], [Type], Map, State, Rev, []),
{Map1, PatType}
end;
map ->
- MapT = t_inf(Type, t_map(), Opaques),
- case t_is_none(MapT) of
- true ->
- bind_opaque_pats(t_map(), Type, Pat, State);
- false ->
- case Rev of
- %% TODO: Reverse matching (propagating a matched subset back to a value)
- true -> {Map, MapT};
- false ->
- FoldFun =
- fun(Pair, {MapAcc, ListAcc}) ->
- %% Only exact (:=) can appear in patterns
- exact = cerl:concrete(cerl:map_pair_op(Pair)),
- Key = cerl:map_pair_key(Pair),
- KeyType =
- case cerl:type(Key) of
- var ->
- case state__lookup_type_for_letrec(Key, State) of
- error -> lookup_type(Key, MapAcc);
- {ok, RecType} -> RecType
- end;
- literal ->
- literal_type(Key)
- end,
- Bind = erl_types:t_map_get(KeyType, MapT),
- {MapAcc1, [ValType]} =
- bind_pat_vars([cerl:map_pair_val(Pair)],
- [Bind], [], MapAcc, State, Rev),
- case t_is_singleton(KeyType, Opaques) of
- true -> {MapAcc1, [{KeyType, ValType}|ListAcc]};
- false -> {MapAcc1, ListAcc}
- end
- end,
- {Map1, Pairs} = lists:foldl(FoldFun, {Map, []}, cerl:map_es(Pat)),
- {Map1, t_inf(MapT, t_map(Pairs))}
- end
- end;
+ bind_map(Pat, Type, Map, State, Opaques, Rev);
tuple ->
- Es = cerl:tuple_es(Pat),
- {TypedRecord, Prototype} =
- case Es of
- [] -> {false, t_tuple([])};
- [Tag|Left] ->
- case cerl:is_c_atom(Tag) andalso is_literal_record(Pat) of
- true ->
- TagAtom = cerl:atom_val(Tag),
- case state__lookup_record(TagAtom, length(Left), State) of
- error -> {false, t_tuple(length(Es))};
- {ok, Record, _FieldNames} ->
- [_Head|AnyTail] = [t_any() || _ <- Es],
- UntypedRecord = t_tuple([t_atom(TagAtom)|AnyTail]),
- {not t_is_equal(Record, UntypedRecord), Record}
- end;
- false -> {false, t_tuple(length(Es))}
- end
- end,
- Tuple = t_inf(Prototype, Type, Opaques),
- case t_is_none(Tuple) of
- true ->
- bind_opaque_pats(Prototype, Type, Pat, State);
- false ->
- SubTuples = t_tuple_subtypes(Tuple, Opaques),
- %% 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, Opaques),
- [], MapJ, State)
- || SubTuple <- SubTuples];
- false ->
- [bind_pat_vars(Es, t_tuple_args(SubTuple, Opaques), [],
- MapJ, State)
- || SubTuple <- SubTuples]
- end,
- case lists:keyfind(opaque, 2, Results) of
- {error, opaque, _PatList, _Type, Opaque} ->
- bind_error([Pat], Tuple, Opaque, opaque);
- false ->
- case [M || {M, _} <- Results, M =/= error] of
- [] ->
- case TypedRecord of
- true -> bind_error([Pat], Tuple, Prototype, record);
- false -> bind_error([Pat], Tuple, t_none(), bind)
- end;
- Maps ->
- Map1 = join_maps_end(Maps, MapJ),
- TupleType = t_sup([t_tuple(EsTypes)
- || {M, EsTypes} <- Results, M =/= error]),
- {Map1, TupleType}
- end
- end
- end;
+ bind_tuple(Pat, Type, Map, State, Opaques, Rev);
values ->
Es = cerl:values_es(Pat),
- {Map1, EsTypes} =
- bind_pat_vars(Es, t_to_tlist(Type), [], Map, State, Rev),
+ {Map1, EsTypes} = do_bind_pat_vars(Es, t_to_tlist(Type),
+ Map, State, Rev, []),
{Map1, t_product(EsTypes)};
var ->
VarType1 =
@@ -1764,28 +1498,100 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
{ok, RecType} -> RecType
end,
%% Must do inf when binding args to pats. Vars in pats are fresh.
- VarType2 = t_inf(VarType1, Type, Opaques),
- case t_is_none(VarType2) of
- true ->
- case t_find_opaque_mismatch(VarType1, Type, Opaques) of
- {ok, T1, T2} ->
- bind_error([Pat], T1, T2, opaque);
- error ->
- bind_error([Pat], Type, t_none(), bind)
- end;
- false ->
- Map1 = enter_type(Pat, VarType2, Map),
- {Map1, VarType2}
- end;
+ VarType2 = bind_checked_inf(Pat, VarType1, Type, Opaques),
+ Map1 = enter_type(Pat, VarType2, Map),
+ {Map1, VarType2};
_Other ->
%% Catch all is needed when binding args to pats
?debug("Failed match for ~p\n", [_Other]),
+ Rev = true, % Assertion.
bind_error([Pat], Type, t_none(), bind)
end,
- bind_pat_vars(PatLeft, TypeLeft, [TypeOut|Acc], NewMap, State, Rev);
-bind_pat_vars([], [], Acc, Map, _State, _Rev) ->
+ do_bind_pat_vars(Pats, Types, NewMap, State, Rev, [TypeOut|Acc]);
+do_bind_pat_vars([], [], Map, _State, _Rev, Acc) ->
{Map, lists:reverse(Acc)}.
+bind_map(Pat, Type, Map, State, Opaques, Rev) ->
+ MapT = bind_checked_inf(Pat, t_map(), Type, Opaques),
+ case Rev of
+ %% TODO: Reverse matching (propagating a matched subset back to a value).
+ true ->
+ {Map, MapT};
+ false ->
+ FoldFun =
+ fun(Pair, {MapAcc, ListAcc}) ->
+ %% Only exact (:=) can appear in patterns.
+ exact = cerl:concrete(cerl:map_pair_op(Pair)),
+ Key = cerl:map_pair_key(Pair),
+ KeyType =
+ case cerl:type(Key) of
+ var ->
+ case state__lookup_type_for_letrec(Key, State) of
+ error -> lookup_type(Key, MapAcc);
+ {ok, RecType} -> RecType
+ end;
+ literal ->
+ literal_type(Key)
+ end,
+ Bind = erl_types:t_map_get(KeyType, MapT),
+ {MapAcc1, [ValType]} =
+ do_bind_pat_vars([cerl:map_pair_val(Pair)],
+ [Bind], MapAcc, State, Rev, []),
+ case t_is_singleton(KeyType, Opaques) of
+ true -> {MapAcc1, [{KeyType, ValType}|ListAcc]};
+ false -> {MapAcc1, ListAcc}
+ end
+ end,
+ {Map1, Pairs} = lists:foldl(FoldFun, {Map, []}, cerl:map_es(Pat)),
+ {Map1, t_inf(MapT, t_map(Pairs))}
+ end.
+
+bind_tuple(Pat, Type, Map, State, Opaques, Rev) ->
+ Es = cerl:tuple_es(Pat),
+ {IsTypedRecord, Prototype} =
+ case Es of
+ [] ->
+ {false, t_tuple([])};
+ [Tag|Tags] ->
+ case cerl:is_c_atom(Tag) andalso is_literal_record(Pat) of
+ true ->
+ Any = t_any(),
+ [_Head|AnyTail] = [Any || _ <- Es],
+ UntypedRecord = t_tuple([Tag|AnyTail]),
+ case state__lookup_record(cerl:atom_val(Tag), length(Tags), State) of
+ error ->
+ {false, UntypedRecord};
+ {ok, Record, _FieldNames} ->
+ {not t_is_equal(Record, UntypedRecord), Record}
+ end;
+ false ->
+ {false, t_tuple(length(Es))}
+ end
+ end,
+ Tuple = bind_checked_inf(Pat, Prototype, Type, Opaques),
+ SubTuples = t_tuple_subtypes(Tuple, Opaques),
+ MapJ = join_maps_begin(Map),
+ %% Need to call the top function to get the try-catch wrapper.
+ Results = [bind_pat_vars(Es, t_tuple_args(SubTuple, Opaques), MapJ, State, Rev) ||
+ SubTuple <- SubTuples],
+ case lists:keyfind(opaque, 2, Results) of
+ {error, opaque, _PatList, _Type, Opaque} ->
+ bind_error([Pat], Tuple, Opaque, opaque);
+ false ->
+ case [M || {M, _} <- Results, M =/= error] of
+ [] ->
+ case IsTypedRecord of
+ true -> bind_error([Pat], Tuple, Prototype, record);
+ false -> bind_error([Pat], Tuple, t_none(), bind)
+ end;
+ Maps ->
+ Map1 = join_maps_end(Maps, MapJ),
+ TupleType = t_sup([t_tuple(EsTypes) ||
+ {M, EsTypes} <- Results, M =/= error]),
+ {Map1, TupleType}
+ end
+ end.
+
bind_bin_segs(BinSegs, BinType, Map, State) ->
bind_bin_segs(BinSegs, BinType, [], Map, State).
@@ -1793,22 +1599,24 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
Val = cerl:bitstr_val(Seg),
SegType = cerl:concrete(cerl:bitstr_type(Seg)),
UnitVal = cerl:concrete(cerl:bitstr_unit(Seg)),
- case cerl:bitstr_bitsize(Seg) of
+ Size = cerl:bitstr_size(Seg),
+ case bitstr_bitsize_type(Size) of
all ->
binary = SegType, [] = Segs, %% just an assert
T = t_inf(t_bitstr(UnitVal, 0), BinType),
- {Map1, [Type]} = bind_pat_vars([Val], [T], [], Map, State, false),
+ {Map1, [Type]} = do_bind_pat_vars([Val], [T], Map,
+ State, false, []),
Type1 = remove_local_opaque_types(Type, State#state.opaques),
bind_bin_segs(Segs, t_bitstr(0, 0), [Type1|Acc], Map1, State);
- utf -> % XXX: possibly can be strengthened
+ utf -> % XXX: can possibly be strengthened
true = lists:member(SegType, [utf8, utf16, utf32]),
- {Map1, [_]} = bind_pat_vars([Val], [t_integer()], [], Map, State, false),
+ {Map1, [_]} = do_bind_pat_vars([Val], [t_integer()],
+ Map, State, false, []),
Type = t_binary(),
bind_bin_segs(Segs, BinType, [Type|Acc], Map1, State);
- BitSz when is_integer(BitSz) orelse BitSz =:= any ->
- Size = cerl:bitstr_size(Seg),
- {Map1, [SizeType]} =
- bind_pat_vars([Size], [t_non_neg_integer()], [], Map, State, false),
+ any ->
+ {Map1, [SizeType]} = do_bind_pat_vars([Size], [t_non_neg_integer()],
+ Map, State, false, []),
Opaques = State#state.opaques,
NumberVals = t_number_vals(SizeType, Opaques),
case t_contains_opaque(SizeType, Opaques) of
@@ -1847,7 +1655,7 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
end
end
end,
- {Map2, [_]} = bind_pat_vars([Val], [ValConstr], [], Map1, State, false),
+ {Map2, [_]} = do_bind_pat_vars([Val], [ValConstr], Map1, State, false, []),
NewBinType = t_bitstr_match(Type, BinType),
case t_is_none(NewBinType) of
true -> bind_error([Seg], BinType, t_none(), bind);
@@ -1857,6 +1665,34 @@ bind_bin_segs([Seg|Segs], BinType, Acc, Map, State) ->
bind_bin_segs([], _BinType, Acc, Map, _State) ->
{Map, lists:reverse(Acc)}.
+bitstr_bitsize_type(Size) ->
+ case cerl:is_literal(Size) of
+ true ->
+ case cerl:concrete(Size) of
+ all -> all;
+ undefined -> utf;
+ _ -> any
+ end;
+ false ->
+ any
+ end.
+
+%% Return the infimum (meet) of ExpectedType and Type if it describes a
+%% possible value (not 'none' or 'unit'), otherwise raise a bind_error().
+bind_checked_inf(Pat, ExpectedType, Type, Opaques) ->
+ Inf = t_inf(ExpectedType, Type, Opaques),
+ case t_is_impossible(Inf) of
+ true ->
+ case t_find_opaque_mismatch(ExpectedType, Type, Opaques) of
+ {ok, T1, T2} ->
+ bind_error([Pat], T1, T2, opaque);
+ error ->
+ bind_error([Pat], Type, Inf, bind)
+ end;
+ false ->
+ Inf
+ end.
+
bind_error(Pats, Type, OpaqueType, Error0) ->
Error = case {Error0, Pats} of
{bind, [Pat]} ->
@@ -1868,17 +1704,6 @@ bind_error(Pats, Type, OpaqueType, Error0) ->
end,
throw({error, Error, Pats, Type, OpaqueType}).
--spec bind_opaque_pats(type(), type(), cerl:c_literal(), state()) ->
- no_return().
-
-bind_opaque_pats(GenType, Type, Pat, State) ->
- case t_find_opaque_mismatch(GenType, Type, State#state.opaques) of
- {ok, T1, T2} ->
- bind_error([Pat], T1, T2, opaque);
- error ->
- bind_error([Pat], Type, t_none(), bind)
- end.
-
%%----------------------------------------
%% Guards
%%
@@ -1923,9 +1748,7 @@ bind_guard(Guard, Map, Env, Eval, State) ->
{{Map2, t_none()}, HE}
end,
BodyEnv = maps:put(get_label(Var), Arg, Env),
- Wanted = case Eval of pos -> t_atom(true); neg -> t_atom(false);
- dont_know -> t_any() end,
- case t_is_none(t_inf(HandlerType, Wanted)) of
+ case t_is_none(guard_eval_inf(Eval, HandlerType)) of
%% Handler won't save us; pretend it does not exist
true -> bind_guard(cerl:try_body(Guard), Map, BodyEnv, Eval, State);
false ->
@@ -1981,13 +1804,7 @@ bind_guard(Guard, Map, Env, Eval, State) ->
error ->
?debug("Did not find it\n", []),
Type = lookup_type(Guard, Map),
- Constr =
- case Eval of
- pos -> t_atom(true);
- neg -> t_atom(false);
- dont_know -> Type
- end,
- Inf = t_inf(Constr, Type),
+ Inf = guard_eval_inf(Eval, Type),
{enter_type(Guard, Inf, Map), Inf};
{ok, Tree} ->
?debug("Found it\n", []),
@@ -2003,17 +1820,9 @@ handle_guard_call(Guard, Map, Env, Eval, State) ->
cerl:atom_val(cerl:call_name(Guard)),
cerl:call_arity(Guard)},
case MFA of
- {erlang, F, 1} when F =:= is_atom; F =:= is_boolean;
- F =:= is_binary; F =:= is_bitstring;
- F =:= is_float; F =:= is_function;
- F =:= is_integer; F =:= is_list; F =:= is_map;
- F =:= is_number; F =:= is_pid; F =:= is_port;
- F =:= is_reference; F =:= is_tuple ->
- handle_guard_type_test(Guard, F, Map, Env, Eval, State);
{erlang, is_function, 2} ->
handle_guard_is_function(Guard, Map, Env, Eval, State);
- MFA when (MFA =:= {erlang, internal_is_record, 3}) or
- (MFA =:= {erlang, is_record, 3}) ->
+ {erlang, F, 3} when F =:= internal_is_record; F =:= is_record ->
handle_guard_is_record(Guard, Map, Env, Eval, State);
{erlang, '=:=', 2} ->
handle_guard_eqeq(Guard, Map, Env, Eval, State);
@@ -2028,8 +1837,14 @@ handle_guard_call(Guard, Map, Env, Eval, State) ->
{erlang, Comp, 2} when Comp =:= '<'; Comp =:= '=<';
Comp =:= '>'; Comp =:= '>=' ->
handle_guard_comp(Guard, Comp, Map, Env, Eval, State);
- _ ->
- handle_guard_gen_fun(MFA, Guard, Map, Env, Eval, State)
+ {erlang, F, A} ->
+ TypeTestType = type_test_type(F, A),
+ case t_is_any(TypeTestType) of
+ true ->
+ handle_guard_gen_fun(MFA, Guard, Map, Env, Eval, State);
+ false ->
+ handle_guard_type_test(Guard, TypeTestType, Map, Env, Eval, State)
+ end
end.
handle_guard_gen_fun({M, F, A}, Guard, Map, Env, Eval, State) ->
@@ -2047,12 +1862,7 @@ handle_guard_gen_fun({M, F, A}, Guard, Map, Env, Eval, State) ->
false ->
BifArgs = bif_args(M, F, A),
Map2 = enter_type_lists(Args, t_inf_lists(BifArgs, As, Opaques), Map1),
- Ret =
- case Eval of
- pos -> t_inf(t_atom(true), BifRet);
- neg -> t_inf(t_atom(false), BifRet);
- dont_know -> BifRet
- end,
+ Ret = guard_eval_inf(Eval, BifRet),
case t_is_none(Ret) of
true ->
case Eval =:= pos of
@@ -2063,10 +1873,10 @@ handle_guard_gen_fun({M, F, A}, Guard, Map, Env, Eval, State) ->
end
end.
-handle_guard_type_test(Guard, F, Map, Env, Eval, State) ->
+handle_guard_type_test(Guard, TypeTestType, Map, Env, Eval, State) ->
[Arg] = cerl:call_args(Guard),
{Map1, ArgType} = bind_guard(Arg, Map, Env, dont_know, State),
- case bind_type_test(Eval, F, ArgType, State) of
+ case bind_type_test(Eval, TypeTestType, ArgType, State) of
error ->
?debug("Type test: ~w failed\n", [F]),
signal_guard_fail(Eval, Guard, [ArgType], State);
@@ -2076,23 +1886,7 @@ handle_guard_type_test(Guard, F, Map, Env, Eval, State) ->
{enter_type(Arg, NewArgType, Map1), Ret}
end.
-bind_type_test(Eval, TypeTest, ArgType, State) ->
- Type = case TypeTest of
- is_atom -> t_atom();
- is_boolean -> t_boolean();
- is_binary -> t_binary();
- is_bitstring -> t_bitstr();
- is_float -> t_float();
- is_function -> t_fun();
- is_integer -> t_integer();
- is_list -> t_maybe_improper_list();
- is_map -> t_map();
- is_number -> t_number();
- is_pid -> t_pid();
- is_port -> t_port();
- is_reference -> t_reference();
- is_tuple -> t_tuple()
- end,
+bind_type_test(Eval, Type, ArgType, State) ->
case Eval of
pos ->
Inf = t_inf(Type, ArgType, State#state.opaques),
@@ -2110,6 +1904,27 @@ bind_type_test(Eval, TypeTest, ArgType, State) ->
{ok, ArgType, t_boolean()}
end.
+type_test_type(TypeTest, 1) ->
+ case TypeTest of
+ is_atom -> t_atom();
+ is_boolean -> t_boolean();
+ is_binary -> t_binary();
+ is_bitstring -> t_bitstr();
+ is_float -> t_float();
+ is_function -> t_fun();
+ is_integer -> t_integer();
+ is_list -> t_maybe_improper_list();
+ is_map -> t_map();
+ is_number -> t_number();
+ is_pid -> t_pid();
+ is_port -> t_port();
+ is_reference -> t_reference();
+ is_tuple -> t_tuple();
+ _ -> t_any() % Not a known type test.
+ end;
+type_test_type(_, _) ->
+ t_any().
+
handle_guard_comp(Guard, Comp, Map, Env, Eval, State) ->
Args = cerl:call_args(Guard),
[Arg1, Arg2] = Args,
@@ -2129,12 +1944,12 @@ handle_guard_comp(Guard, Comp, Map, Env, Eval, State) ->
false when Eval =:= dont_know -> {Map, t_atom(false)};
false when Eval =:= neg -> {Map, t_atom(false)}
end;
- {{literal, Lit1}, var} when IsInt1 andalso IsInt2 andalso (Eval =:= pos) ->
+ {{literal, Lit1}, var} when IsInt1, IsInt2, Eval =:= pos ->
case bind_comp_literal_var(Lit1, Arg2, Type2, Comp, Map1, Opaques) of
error -> signal_guard_fail(Eval, Guard, ArgTypes, State);
{ok, NewMap} -> {NewMap, t_atom(true)}
end;
- {var, {literal, Lit2}} when IsInt1 andalso IsInt2 andalso (Eval =:= pos) ->
+ {var, {literal, Lit2}} when IsInt1, IsInt2, Eval =:= pos ->
case bind_comp_literal_var(Lit2, Arg1, Type1, invert_comp(Comp),
Map1, Opaques) of
error -> signal_guard_fail(Eval, Guard, ArgTypes, State);
@@ -2313,11 +2128,7 @@ bind_eq_guard(Guard, Arg1, Arg2, Map, Env, Eval, State) ->
OpArgs = erl_types:t_find_unknown_opaque(Type1, Type2, Opaques),
case OpArgs =:= [] of
true ->
- case Eval of
- pos -> {Map2, t_atom(true)};
- neg -> {Map2, t_atom(false)};
- dont_know -> {Map2, t_boolean()}
- end;
+ {Map2, guard_eval_inf(Eval, t_boolean())};
false ->
signal_guard_fail(Eval, Guard, [Type1, Type2], State)
end
@@ -2600,7 +2411,7 @@ handle_guard_map(Guard, Map, Env, State) ->
Arg = cerl:map_arg(Guard),
{Map1, ArgType0} = bind_guard(Arg, Map, Env, dont_know, State),
ArgType1 = t_inf(t_map(), ArgType0),
- case t_is_none_or_unit(ArgType1) of
+ case t_is_impossible(ArgType1) of
true -> {Map1, t_none()};
false ->
{Map2, TypePairs} = bind_guard_map_pairs(Pairs, Map1, Env, State, []),
@@ -2621,6 +2432,14 @@ bind_guard_map_pairs([Pair|Pairs], Map, Env, State, PairAcc) ->
-type eval() :: 'pos' | 'neg' | 'dont_know'.
+guard_eval_inf(Eval, Type) ->
+ Constr = case Eval of
+ pos -> t_atom(true);
+ neg -> t_atom(false);
+ dont_know -> Type
+ end,
+ t_inf(Constr, Type).
+
-spec signal_guard_fail(eval(), cerl:c_call(), [type()],
state()) -> no_return().
@@ -2668,16 +2487,10 @@ signal_guard_failure(Eval, Guard, ArgTypes, Tag, State) ->
end,
throw({Tag, {LocTree, Msg}}).
-is_infix_op({erlang, '=:=', 2}) -> true;
-is_infix_op({erlang, '==', 2}) -> true;
-is_infix_op({erlang, '=/=', 2}) -> true;
-is_infix_op({erlang, '=/', 2}) -> true;
-is_infix_op({erlang, '<', 2}) -> true;
-is_infix_op({erlang, '=<', 2}) -> true;
-is_infix_op({erlang, '>', 2}) -> true;
-is_infix_op({erlang, '>=', 2}) -> true;
-is_infix_op({M, F, A}) when is_atom(M), is_atom(F),
- is_integer(A), 0 =< A, A =< 255 -> false.
+is_infix_op({erlang, F, 2}) ->
+ erl_internal:comp_op(F, 2);
+is_infix_op({_, _, _}) ->
+ false.
bif_args(M, F, A) ->
case erl_bif_types:arg_types(M, F, A) of
@@ -2741,7 +2554,7 @@ bind_guard_case_clauses(GenArgType, GenMap, ArgExpr, [Clause|Left],
true -> Any = t_any(), [Any || _ <- Pats];
false -> t_to_tlist(ArgType)
end,
- case bind_pat_vars(Pats, ArgTypes, [], NewMap0, State) of
+ case bind_pat_vars(Pats, ArgTypes, NewMap0, State) of
{error, _, _, _, _} -> none;
{PatMap, _PatTypes} -> PatMap
end
@@ -2880,12 +2693,6 @@ enter_type_lists([Key|KeyTail], [Val|ValTail], Map) ->
enter_type_lists([], [], Map) ->
Map.
-enter_type_list([{Key, Val}|Left], Map) ->
- Map1 = enter_type(Key, Val, Map),
- enter_type_list(Left, Map1);
-enter_type_list([], Map) ->
- Map.
-
enter_type(Key, Val, MS) ->
case cerl:is_literal(Key) of
true -> MS;
@@ -3091,15 +2898,15 @@ state__new(Callgraph, Codeserver, Tree, Plt, Module, Records) ->
dict:new(), Funs),
#state{callgraph = Callgraph, codeserver = Codeserver,
envs = Env, fun_tab = FunTab, fun_homes = FunHomes, opaques = Opaques,
- plt = Plt, races = dialyzer_races:new(), records = Records,
+ plt = Plt, records = Records,
warning_mode = false, warnings = [], work = Work, tree_map = TreeMap,
- module = Module, reachable_funs = sets:new()}.
+ module = Module, reachable_funs = sets:new([{version, 2}])}.
state__warning_mode(#state{warning_mode = WM}) ->
WM.
state__set_warning_mode(#state{tree_map = TreeMap, fun_tab = FunTab,
- races = Races, callgraph = Callgraph,
+ callgraph = Callgraph,
reachable_funs = ReachableFuns} = State) ->
?debug("==========\nStarting warning pass\n==========\n", []),
Funs = dict:fetch_keys(TreeMap),
@@ -3109,37 +2916,11 @@ state__set_warning_mode(#state{tree_map = TreeMap, fun_tab = FunTab,
dialyzer_callgraph:lookup_name(Fun, Callgraph) =/= error orelse
sets:is_element(Fun, ReachableFuns)],
State#state{work = init_work(Work),
- fun_tab = FunTab, warning_mode = true,
- races = dialyzer_races:put_race_analysis(true, Races)}.
-
-state__race_analysis(Analysis, #state{races = Races} = State) ->
- State#state{races = dialyzer_races:put_race_analysis(Analysis, Races)}.
-
-state__renew_curr_fun(CurrFun, CurrFunLabel,
- #state{races = Races} = State) ->
- State#state{races = dialyzer_races:put_curr_fun(CurrFun, CurrFunLabel,
- Races)}.
-
-state__renew_fun_args(Args, #state{races = Races} = State) ->
- case state__warning_mode(State) of
- true -> State;
- false ->
- State#state{races = dialyzer_races:put_fun_args(Args, Races)}
- end.
-
-state__renew_race_list(RaceList, RaceListSize,
- #state{races = Races} = State) ->
- State#state{races = dialyzer_races:put_race_list(RaceList, RaceListSize,
- Races)}.
+ fun_tab = FunTab, warning_mode = true}.
state__renew_warnings(Warnings, State) ->
State#state{warnings = Warnings}.
--spec state__add_warning(raw_warning(), state()) -> state().
-
-state__add_warning(Warn, #state{warnings = Warnings} = State) ->
- State#state{warnings = [Warn|Warnings]}.
-
state__add_warning(State, Tag, Tree, Msg) ->
state__add_warning(State, Tag, Tree, Msg, false).
@@ -3190,15 +2971,6 @@ state__set_curr_fun(undefined, State) ->
state__set_curr_fun(FunLbl, State) ->
State#state{curr_fun = find_function(FunLbl, State)}.
--spec state__find_function(mfa_or_funlbl(), state()) -> mfa_or_funlbl().
-
-state__find_function(FunLbl, State) ->
- find_function(FunLbl, State).
-
-state__get_race_warnings(#state{races = Races} = State) ->
- {Races1, State1} = dialyzer_races:get_race_warnings(Races, State),
- State1#state{races = Races1}.
-
state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab,
callgraph = Callgraph, plt = Plt,
reachable_funs = ReachableFuns} = State) ->
@@ -3526,56 +3298,6 @@ forward_args(Fun, ArgTypes, #state{work = Work, fun_tab = FunTab} = State) ->
State#state{work = NewWork, fun_tab = NewFunTab}
end.
--spec state__cleanup(state()) -> state().
-
-state__cleanup(#state{callgraph = Callgraph,
- races = Races,
- records = Records}) ->
- #state{callgraph = dialyzer_callgraph:cleanup(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}) ->
- Callgraph.
-
--spec state__get_races(state()) -> dialyzer_races:races().
-
-state__get_races(#state{races = Races}) ->
- Races.
-
--spec state__get_records(state()) -> types().
-
-state__get_records(#state{records = Records}) ->
- Records.
-
--spec state__put_callgraph(dialyzer_callgraph:callgraph(), state()) ->
- state().
-
-state__put_callgraph(Callgraph, State) ->
- State#state{callgraph = Callgraph}.
-
--spec state__put_races(dialyzer_races:races(), state()) -> state().
-
-state__put_races(Races, State) ->
- State#state{races = Races}.
-
--spec state__records_only(state()) -> state().
-
-state__records_only(#state{records = Records}) ->
- #state{records = Records}.
-
-spec state__translate_file(file:filename(), state()) -> file:filename().
state__translate_file(FakeFile, State) ->
@@ -3584,51 +3306,12 @@ state__translate_file(FakeFile, State) ->
%%% ===========================================================================
%%%
-%%% Races
-%%%
-%%% ===========================================================================
-
-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 -> State;
- false ->
- NewCallgraph = dialyzer_callgraph:renew_race_code(Races, Callgraph),
- State#state{callgraph = NewCallgraph}
- end.
-
-renew_race_public_tables([Var], #state{races = Races, callgraph = Callgraph,
- warning_mode = WarningMode} = State) ->
- case WarningMode of
- true -> State;
- false ->
- Table = dialyzer_races:get_new_table(Races),
- case Table of
- no_t -> State;
- _Other ->
- VarLabel = get_label(Var),
- NewCallgraph =
- dialyzer_callgraph:renew_race_public_tables(VarLabel, Callgraph),
- State#state{callgraph = NewCallgraph}
- end
- end.
-
-%%% ===========================================================================
-%%%
%%% Worklist
%%%
%%% ===========================================================================
init_work(List) ->
- {List, [], sets:from_list(List)}.
+ {List, [], sets:from_list(List, [{version, 2}])}.
get_work({[], [], _Set}) ->
none;
diff --git a/lib/dialyzer/src/dialyzer_dep.erl b/lib/dialyzer/src/dialyzer_dep.erl
index 1880e1ee5c..c869be76a3 100644
--- a/lib/dialyzer/src/dialyzer_dep.erl
+++ b/lib/dialyzer/src/dialyzer_dep.erl
@@ -124,22 +124,26 @@ traverse(Tree, Out, State, CurrentFun) ->
{merge_outs([HdFuns, TlFuns]), State2};
'fun' ->
%% io:format("Entering fun: ~w\n", [cerl_trees:get_label(Tree)]),
+ OldNumRvals = state__num_rvals(State),
+ State1 = state__store_num_rvals(1, State),
Body = cerl:fun_body(Tree),
Label = cerl_trees:get_label(Tree),
- State1 =
- if CurrentFun =:= top ->
- state__add_deps(top, output(set__singleton(Label)), State);
- true ->
- O1 = output(set__singleton(CurrentFun)),
- O2 = output(set__singleton(Label)),
- TmpState = state__add_deps(Label, O1, State),
- state__add_deps(CurrentFun, O2,TmpState)
+ State2 =
+ if
+ CurrentFun =:= top ->
+ state__add_deps(top, output(set__singleton(Label)), State1);
+ true ->
+ O1 = output(set__singleton(CurrentFun)),
+ O2 = output(set__singleton(Label)),
+ TmpState = state__add_deps(Label, O1, State1),
+ state__add_deps(CurrentFun, O2, TmpState)
end,
Vars = cerl:fun_vars(Tree),
Out1 = bind_single(Vars, output(set__singleton(external)), Out),
- {BodyFuns, State2} =
- traverse(Body, Out1, State1, cerl_trees:get_label(Tree)),
- {output(set__singleton(Label)), state__add_esc(BodyFuns, State2)};
+ {BodyFuns, State3} =
+ traverse(Body, Out1, State2, cerl_trees:get_label(Tree)),
+ State4 = state__store_num_rvals(OldNumRvals, State3),
+ {output(set__singleton(Label)), state__add_esc(BodyFuns, State4)};
'let' ->
Vars = cerl:let_vars(Tree),
Arg = cerl:let_arg(Tree),
@@ -279,7 +283,7 @@ remote_call(Tree, ArgFuns, State) ->
true ->
M1 = cerl:atom_val(M),
F1 = cerl:atom_val(F),
- Literal = cerl_closurean:is_literal_op(M1, F1, A),
+ Literal = is_literal_op(M1, F1, A),
case erl_bifs:is_pure(M1, F1, A) of
true ->
case Literal of
@@ -289,7 +293,7 @@ remote_call(Tree, ArgFuns, State) ->
{output(set__singleton(external)), state__add_esc(ArgFuns, State)}
end;
false ->
- State1 = case cerl_closurean:is_escape_op(M1, F1, A) of
+ State1 = case is_escape_op(M1, F1, A) of
true -> state__add_esc(ArgFuns, State);
false -> State
end,
@@ -303,26 +307,86 @@ remote_call(Tree, ArgFuns, State) ->
primop(Tree, ArgFuns, State) ->
F = cerl:atom_val(cerl:primop_name(Tree)),
A = length(cerl:primop_args(Tree)),
- State1 = case cerl_closurean:is_escape_op(F, A) of
+ State1 = case is_escape_op(F, A) of
true -> state__add_esc(ArgFuns, State);
false -> State
end,
- case cerl_closurean:is_literal_op(F, A) of
+ case is_literal_op(F, A) of
true -> {output(none), State1};
false -> {ArgFuns, State1}
end.
%%------------------------------------------------------------
+
+%% Escape operators may let their arguments escape. Unless we know
+%% otherwise, and the function is not pure, we assume this is the case.
+%% Error-raising functions (fault/match_fail) are not considered as
+%% escapes (but throw/exit are). Zero-argument functions need not be
+%% listed.
+
+-spec is_escape_op(atom(), arity()) -> boolean().
+
+is_escape_op(match_fail, 1) -> false;
+is_escape_op(recv_wait_timeout, 1) -> false;
+is_escape_op(F, A) when is_atom(F), is_integer(A) -> true.
+
+-spec is_escape_op(atom(), atom(), arity()) -> boolean().
+
+is_escape_op(erlang, error, 1) -> false;
+is_escape_op(erlang, error, 2) -> false;
+is_escape_op(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> true.
+
+%% "Literal" operators will never return functional values even when
+%% found in their arguments. Unless we know otherwise, we assume this is
+%% not the case. (More functions can be added to this list, if needed
+%% for better precision. Note that the result of `term_to_binary' still
+%% contains an encoding of the closure.)
+
+-spec is_literal_op(atom(), arity()) -> boolean().
+
+is_literal_op(recv_wait_timeout, 1) -> true;
+is_literal_op(match_fail, 1) -> true;
+is_literal_op(F, A) when is_atom(F), is_integer(A) -> false.
+
+-spec is_literal_op(atom(), atom(), arity()) -> boolean().
+
+is_literal_op(erlang, '+', 2) -> true;
+is_literal_op(erlang, '-', 2) -> true;
+is_literal_op(erlang, '*', 2) -> true;
+is_literal_op(erlang, '/', 2) -> true;
+is_literal_op(erlang, '=:=', 2) -> true;
+is_literal_op(erlang, '==', 2) -> true;
+is_literal_op(erlang, '=/=', 2) -> true;
+is_literal_op(erlang, '/=', 2) -> true;
+is_literal_op(erlang, '<', 2) -> true;
+is_literal_op(erlang, '=<', 2) -> true;
+is_literal_op(erlang, '>', 2) -> true;
+is_literal_op(erlang, '>=', 2) -> true;
+is_literal_op(erlang, 'and', 2) -> true;
+is_literal_op(erlang, 'or', 2) -> true;
+is_literal_op(erlang, 'not', 1) -> true;
+is_literal_op(erlang, length, 1) -> true;
+is_literal_op(erlang, size, 1) -> true;
+is_literal_op(erlang, fun_info, 1) -> true;
+is_literal_op(erlang, fun_info, 2) -> true;
+is_literal_op(erlang, fun_to_list, 1) -> true;
+is_literal_op(erlang, throw, 1) -> true;
+is_literal_op(erlang, exit, 1) -> true;
+is_literal_op(erlang, error, 1) -> true;
+is_literal_op(erlang, error, 2) -> true;
+is_literal_op(M, F, A) when is_atom(M), is_atom(F), is_integer(A) -> false.
+
+%%------------------------------------------------------------
%% Set
%%
-record(set, {set :: sets:set()}).
set__singleton(Val) ->
- #set{set = sets:add_element(Val, sets:new())}.
+ #set{set = sets:add_element(Val, sets:new([{version, 2}]))}.
set__from_list(List) ->
- #set{set = sets:from_list(List)}.
+ #set{set = sets:from_list(List, [{version, 2}])}.
set__is_element(_El, none) ->
false;
diff --git a/lib/dialyzer/src/dialyzer_dot.erl b/lib/dialyzer/src/dialyzer_dot.erl
index 210067a2ab..4caaf53f0c 100644
--- a/lib/dialyzer/src/dialyzer_dot.erl
+++ b/lib/dialyzer/src/dialyzer_dot.erl
@@ -41,7 +41,7 @@
%% filename is the name of the resulting .dot file the GraphName is
%% pretty much useless.
%%
-%% The resulting .dot reprsentation will be stored in the flie FileName.
+%% The resulting .dot representation will be stored in the file FileName.
%%
%% Interfaces:
%%
@@ -115,12 +115,12 @@ node_format(Opt, Fun, V) ->
Tmp = io_lib:format("~p", [Fun(V)]),
String = lists:flatten(Tmp),
%% io:format("~p", [String]),
- {Width, Heigth} = calc_dim(String),
+ {Width, Height} = calc_dim(String),
W = ((Width div 7) + 1) * 0.55,
- H = Heigth * 0.4,
+ H = Height * 0.4,
SL = io_lib:format("~f", [W]),
SH = io_lib:format("~f", [H]),
- [String, " [width=", SL, " heigth=", SH, " ", OptText,"];\n"].
+ [String, " [width=", SL, " height=", SH, " ", OptText,"];\n"].
edge_format(Opt, Fun, V1, V2) ->
OptText =
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl
index 3a24f140e0..3b04b56f80 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.erl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.erl
@@ -242,7 +242,6 @@ create_window(Wx, #options{init_plts = InitPltFiles} = DialyzerOptions) ->
{?WARN_OPAQUE, ?menuID_WARN_OPAQUE},
{?WARN_FAILING_CALL, ?menuID_WARN_FAIL_FUN_CALLS},
{?WARN_CALLGRAPH, ?menuID_WARN_UNEXPORTED_FUN},
- {?WARN_RACE_CONDITION, ?menuID_WARN_RACE_CONDITIONS},
%% For contracts.
{?WARN_CONTRACT_TYPES,?menuID_WARN_WRONG_CONTRACTS},
{?WARN_CONTRACT_SYNTAX, ?menuID_WARN_CONTRACT_SYNTAX}
@@ -313,8 +312,6 @@ createWarningsMenu() ->
"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"),
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.hrl b/lib/dialyzer/src/dialyzer_gui_wx.hrl
index fe763a9abc..0a6ca9e8b2 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.hrl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.hrl
@@ -31,9 +31,8 @@
-define(menuID_WARN_ERROR_HANDLING_FUN, 206).
-define(menuID_WARN_NO_RETURN_FUN, 207).
-define(menuID_WARN_UNEXPORTED_FUN, 208).
--define(menuID_WARN_RACE_CONDITIONS, 209).
--define(menuID_WARN_WRONG_CONTRACTS, 210).
--define(menuID_WARN_CONTRACT_SYNTAX, 211).
+-define(menuID_WARN_WRONG_CONTRACTS, 209).
+-define(menuID_WARN_CONTRACT_SYNTAX, 210).
-define(menuID_PLT_INIT_EMPTY, 300).
-define(menuID_PLT_SHOW_CONTENTS, 301).
diff --git a/lib/dialyzer/src/dialyzer_options.erl b/lib/dialyzer/src/dialyzer_options.erl
index 44c75d60c1..5a56e0b0cb 100644
--- a/lib/dialyzer/src/dialyzer_options.erl
+++ b/lib/dialyzer/src/dialyzer_options.erl
@@ -105,12 +105,12 @@ adapt_get_warnings(Opts = #options{analysis_type = Mode,
%% default.
case is_plt_mode(Mode) of
true ->
- case Warns =:= maybe of
+ case Warns =:= 'maybe' of
true -> Opts#options{get_warnings = false};
false -> Opts
end;
false ->
- case Warns =:= maybe of
+ case Warns =:= 'maybe' of
true -> Opts#options{get_warnings = true};
false -> Opts
end
@@ -333,25 +333,37 @@ build_warnings([Opt|Opts], Warnings) ->
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);
no_missing_calls ->
ordsets:del_element(?WARN_CALLGRAPH, Warnings);
specdiffs ->
- S = ordsets:from_list([?WARN_CONTRACT_SUBTYPE,
- ?WARN_CONTRACT_SUPERTYPE,
- ?WARN_CONTRACT_NOT_EQUAL]),
- ordsets:union(S, Warnings);
+ S = ordsets:from_list([?WARN_CONTRACT_SUBTYPE,
+ ?WARN_CONTRACT_SUPERTYPE,
+ ?WARN_CONTRACT_NOT_EQUAL,
+ ?WARN_CONTRACT_MISSING_RETURN,
+ ?WARN_CONTRACT_EXTRA_RETURN]),
+ ordsets:union(S, Warnings);
overspecs ->
- ordsets:add_element(?WARN_CONTRACT_SUBTYPE, Warnings);
+ S = ordsets:from_list([?WARN_CONTRACT_SUBTYPE,
+ ?WARN_CONTRACT_MISSING_RETURN]),
+ ordsets:union(S, Warnings);
underspecs ->
- ordsets:add_element(?WARN_CONTRACT_SUPERTYPE, Warnings);
+ S = ordsets:from_list([?WARN_CONTRACT_SUPERTYPE,
+ ?WARN_CONTRACT_EXTRA_RETURN]),
+ ordsets:union(S, Warnings);
no_underspecs ->
- ordsets:del_element(?WARN_CONTRACT_SUPERTYPE, Warnings);
+ ordsets:del_element(?WARN_CONTRACT_SUPERTYPE, Warnings);
+ extra_return ->
+ ordsets:add_element(?WARN_CONTRACT_EXTRA_RETURN, Warnings);
+ no_extra_return ->
+ ordsets:del_element(?WARN_CONTRACT_EXTRA_RETURN, Warnings);
+ missing_return ->
+ ordsets:add_element(?WARN_CONTRACT_MISSING_RETURN, Warnings);
+ no_missing_return ->
+ ordsets:del_element(?WARN_CONTRACT_MISSING_RETURN, Warnings);
unknown ->
- ordsets:add_element(?WARN_UNKNOWN, Warnings);
+ ordsets:add_element(?WARN_UNKNOWN, Warnings);
OtherAtom ->
- bad_option("Unknown dialyzer warning option", OtherAtom)
+ bad_option("Unknown dialyzer warning option", OtherAtom)
end,
build_warnings(Opts, NewWarnings);
build_warnings([], Warnings) ->
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 8fd38a8922..409d1f65c5 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -50,13 +50,16 @@
get_specs/1,
get_specs/4,
to_file/4,
- delete/1
+ delete/1,
+ get_all_types/1,
+ get_all_contracts/1,
+ get_all_callbacks/1
]).
%% Debug utilities
-export([pp_non_returning/0, pp_mod/1]).
--export_type([plt/0, plt_info/0]).
+-export_type([plt/0, file_md5/0]).
-include_lib("stdlib/include/ms_transform.hrl").
@@ -89,7 +92,6 @@
-include("dialyzer.hrl").
-type file_md5() :: {file:filename(), binary()}.
--type plt_info() :: {[file_md5()], dict:dict()}.
-record(file_plt, {version = "" :: string(),
file_md5_list = [] :: [file_md5()],
@@ -235,12 +237,12 @@ contains_mfa(#plt{info = Info, contracts = Contracts}, MFA) ->
get_default_plt() ->
case os:getenv("DIALYZER_PLT") of
false ->
- {ok,[[HomeDir]]} = init:get_argument(home),
- filename:join(HomeDir, ".dialyzer_plt");
+ CacheDir = filename:basedir(user_cache, "erlang"),
+ filename:join(CacheDir, ".dialyzer_plt");
UserSpecPlt -> UserSpecPlt
end.
--spec plt_and_info_from_file(file:filename()) -> {plt(), plt_info()}.
+-spec plt_and_info_from_file(file:filename()) -> {plt(), #plt_info{}}.
plt_and_info_from_file(FileName) ->
from_file(FileName, true).
@@ -296,8 +298,8 @@ from_file1(Plt, FileName, ReturnInfo) ->
case ReturnInfo of
false -> {ok, Plt};
true ->
- PltInfo = {Rec#file_plt.file_md5_list,
- Rec#file_plt.mod_deps},
+ PltInfo = #plt_info{files = Rec#file_plt.file_md5_list,
+ mod_deps = Rec#file_plt.mod_deps},
{ok, {Plt, PltInfo}}
end
end;
@@ -407,8 +409,8 @@ find_duplicates(List) ->
ModList = [filename:basename(E) || E <- List],
SortedList = lists:usort(ModList),
lists:usort(ModList -- SortedList).
-
--spec to_file(file:filename(), plt(), mod_deps(), {[file_md5()], mod_deps()}) -> 'ok'.
+
+-spec to_file(file:filename(), plt(), mod_deps(), #plt_info{}) -> 'ok'.
%% Write the PLT to file, and delete the PLT.
to_file(FileName, Plt, ModDeps, MD5_OldModDeps) ->
@@ -423,7 +425,7 @@ to_file(FileName, Plt, ModDeps, MD5_OldModDeps) ->
to_file1(FileName,
#plt{info = ETSInfo, types = ETSTypes, contracts = ETSContracts,
callbacks = ETSCallbacks, exported_types = ETSExpTypes},
- ModDeps, {MD5, OldModDeps}) ->
+ ModDeps, #plt_info{files = MD5, mod_deps = OldModDeps}) ->
NewModDeps = dict:merge(fun(_Key, OldVal, NewVal) ->
ordsets:union(OldVal, NewVal)
end,
@@ -845,3 +847,24 @@ pp_mod(Mod) when is_atom(Mod) ->
io:format("dialyzer: Found no module named '~s' in the PLT\n", [Mod])
end,
delete(Plt).
+
+
+%% Returns all contracts stored in the PLT
+-spec get_all_contracts(plt()) -> #{mfa() => #contract{}}.
+get_all_contracts(#plt{contracts = ETSContracts}) ->
+ maps:from_list(ets:tab2list(ETSContracts)).
+
+%% Returns all callbacks stored in the PLT
+-spec get_all_callbacks(plt()) -> #{mfa() => #contract{}}.
+get_all_callbacks(#plt{callbacks = ETSCallbacks}) ->
+ CallbacksList =
+ [Cb ||
+ {_M, Cbs} <- ets:tab2list(ETSCallbacks),
+ Cb <- Cbs],
+ maps:from_list(CallbacksList).
+
+%% Returns all types stored in the PLT
+-spec get_all_types(plt()) -> #{module() => erl_types:type_table()}.
+get_all_types(#plt{types = ETSTypes}) ->
+ Types = ets:tab2list(ETSTypes),
+ maps:from_list(Types).
diff --git a/lib/dialyzer/src/dialyzer_race_data_server.erl b/lib/dialyzer/src/dialyzer_race_data_server.erl
deleted file mode 100644
index 953cebfdf1..0000000000
--- a/lib/dialyzer/src/dialyzer_race_data_server.erl
+++ /dev/null
@@ -1,127 +0,0 @@
-%% -*- erlang-indent-level: 2 -*-
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-
-%%%-------------------------------------------------------------------
-%%% File : dialyzer_race_data_server.erl
-%%% Author : Tobias Lindahl <tobiasl@it.uu.se>
-%%% Description :
-%%%
-%%% Created : 18 Sep 2015 by Luca Favatella <luca.favatella@erlang-solutions.com>
-%%%-------------------------------------------------------------------
--module(dialyzer_race_data_server).
-
--export([new/0,
- duplicate/1,
- stop/1,
- call/2,
- cast/2]).
-
--include("dialyzer.hrl").
-
-%%----------------------------------------------------------------------
-
--record(state, {race_code = dict:new() :: dict:dict(),
- public_tables = [] :: [label()],
- named_tables = [] :: [string()],
- beh_api_calls = [] :: [{mfa(), mfa()}]}).
-
-%%----------------------------------------------------------------------
-
--spec new() -> pid().
-
-new() ->
- spawn_link(fun() -> loop(#state{}) end).
-
--spec duplicate(pid()) -> pid().
-
-duplicate(Server) ->
- call(dup, Server).
-
--spec stop(pid()) -> ok.
-
-stop(Server) ->
- cast(stop, Server).
-
--spec call(atom(), pid()) -> term().
-
-call(Query, Server) ->
- Ref = make_ref(),
- Server ! {call, self(), Ref, Query},
- receive
- {Ref, Reply} -> Reply
- end.
-
--spec cast(atom() | {atom(), term()}, pid()) -> ok.
-
-cast(Message, Server) ->
- Server ! {cast, Message},
- ok.
-
-%%----------------------------------------------------------------------
-
-loop(State) ->
- receive
- {call, From, Ref, Query} ->
- Reply = handle_call(Query, State),
- From ! {Ref, Reply},
- loop(State);
- {cast, stop} ->
- ok;
- {cast, Message} ->
- NewState = handle_cast(Message, State),
- loop(NewState)
- end.
-
-handle_cast(race_code_new, State) ->
- State#state{race_code = dict:new()};
-handle_cast({Tag, Data}, State) ->
- case Tag of
- renew_race_info -> renew_race_info_handler(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#state{race_code = Data};
- put_public_tables -> State#state{public_tables = Data};
- put_named_tables -> State#state{named_tables = Data};
- put_behaviour_api_calls -> State#state{beh_api_calls = Data}
- end.
-
-handle_call(Query,
- #state{race_code = RaceCode,
- public_tables = PublicTables,
- named_tables = NamedTables,
- beh_api_calls = BehApiCalls}
- = State) ->
- case Query of
- dup -> spawn_link(fun() -> loop(State) end);
- get_race_code -> RaceCode;
- get_public_tables -> PublicTables;
- get_named_tables -> NamedTables;
- get_behaviour_api_calls -> BehApiCalls
- end.
-
-%%----------------------------------------------------------------------
-
-renew_race_info_handler({RaceCode, PublicTables, NamedTables},
- #state{} = State) ->
- State#state{race_code = RaceCode,
- public_tables = PublicTables,
- named_tables = NamedTables}.
-
-renew_race_code_handler({Fun, FunArgs, Code},
- #state{race_code = RaceCode} = State) ->
- State#state{race_code = dict:store(Fun, [FunArgs, Code], RaceCode)}.
-
-renew_race_public_tables_handler(VarLabel,
- #state{public_tables = PT} = State) ->
- State#state{public_tables = ordsets:add_element(VarLabel, PT)}.
diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl
deleted file mode 100644
index adefc16f99..0000000000
--- a/lib/dialyzer/src/dialyzer_races.erl
+++ /dev/null
@@ -1,2483 +0,0 @@
-%% -*- erlang-indent-level: 2 -*-
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-
-%%%----------------------------------------------------------------------
-%%% File : dialyzer_races.erl
-%%% Author : Maria Christakis <christakismaria@gmail.com>
-%%% Description : Utility functions for race condition detection
-%%%
-%%% Created : 21 Nov 2008 by Maria Christakis <christakismaria@gmail.com>
-%%%----------------------------------------------------------------------
--module(dialyzer_races).
-
-%% Race Analysis
-
--export([store_race_call/5, race/1, get_race_warnings/2, format_args/4]).
-
-%% Record Interfaces
-
--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, core_vars/0]).
-
--include("dialyzer.hrl").
-
-%%% ===========================================================================
-%%%
-%%% Definitions
-%%%
-%%% ===========================================================================
-
--define(local, 5).
--define(no_arg, no_arg).
--define(no_label, no_label).
--define(bypassed, bypassed).
-
--define(WARN_WHEREIS_REGISTER, warn_whereis_register).
--define(WARN_WHEREIS_UNREGISTER, warn_whereis_unregister).
--define(WARN_ETS_LOOKUP_INSERT, warn_ets_lookup_insert).
--define(WARN_MNESIA_DIRTY_READ_WRITE, warn_mnesia_dirty_read_write).
--define(WARN_NO_WARN, warn_no_warn).
-
-%%% ===========================================================================
-%%%
-%%% Local Types
-%%%
-%%% ===========================================================================
-
--type label_type() :: label() | [label()] | {label()} | ?no_label.
--type args() :: [label_type() | [string()]].
--type core_vars() :: cerl:cerl() | ?no_arg | ?bypassed.
--type var_to_map1() :: core_vars() | [cerl:cerl()].
--type var_to_map2() :: cerl:cerl() | [cerl:cerl()] | ?bypassed.
--type core_args() :: [core_vars()] | 'empty'.
--type op() :: 'bind' | 'unbind'.
-
--type dep_calls() :: 'whereis' | 'ets_lookup' | 'mnesia_dirty_read'.
--type warn_calls() :: 'register' | 'unregister' | 'ets_insert'
- | 'mnesia_dirty_write'.
--type call() :: 'whereis' | 'register' | 'unregister' | 'ets_new'
- | 'ets_lookup' | 'ets_insert' | 'mnesia_dirty_read1'
- | 'mnesia_dirty_read2' | 'mnesia_dirty_write1'
- | 'mnesia_dirty_write2' | 'function_call'.
--type race_tag() :: 'whereis_register' | 'whereis_unregister'
- | 'ets_lookup_insert' | 'mnesia_dirty_read_write'.
-
-%% The following type is similar to the raw_warning() type but has a
-%% tag which is local to this module and is not propagated to outside
--type dial_race_warning() :: {race_warn_tag(), warning_info(), {atom(), [term()]}}.
--type race_warn_tag() :: ?WARN_WHEREIS_REGISTER | ?WARN_WHEREIS_UNREGISTER
- | ?WARN_ETS_LOOKUP_INSERT | ?WARN_MNESIA_DIRTY_READ_WRITE.
-
--record(beg_clause, {arg :: var_to_map1() | 'undefined',
- pats :: var_to_map1() | 'undefined',
- guard :: cerl:cerl() | 'undefined'}).
--record(end_clause, {arg :: var_to_map1() | 'undefined',
- pats :: var_to_map1() | 'undefined',
- guard :: cerl:cerl() | 'undefined'}).
--record(end_case, {clauses :: [#end_clause{}]}).
--record(curr_fun, {status :: 'in' | 'out' | 'undefined',
- mfa :: dialyzer_callgraph:mfa_or_funlbl()
- | 'undefined',
- label :: label() | 'undefined',
- def_vars :: [core_vars()] | 'undefined',
- arg_types :: [erl_types:erl_type()] | 'undefined',
- call_vars :: [core_vars()] | 'undefined',
- var_map :: dict:dict() | 'undefined'}).
--record(dep_call, {call_name :: dep_calls(),
- args :: args() | 'undefined',
- arg_types :: [erl_types:erl_type()],
- vars :: [core_vars()],
- state :: dialyzer_dataflow:state(),
- file_loc :: file_location(),
- var_map :: dict:dict() | 'undefined'}).
--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(),
- arg :: var_to_map1()}).
--record(warn_call, {call_name :: warn_calls(),
- args :: args(),
- var_map :: dict:dict() | 'undefined'}).
-
--type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}.
--type code() :: [#dep_call{} | #fun_call{} | #warn_call{} |
- #curr_fun{} | #let_tag{} | case_tags() | race_tag()].
-
--type table_var() :: label() | ?no_label.
--type table() :: {'named', table_var(), [string()]} | 'other' | 'no_t'.
-
--record(race_fun, {mfa :: mfa(),
- args :: args(),
- arg_types :: [erl_types:erl_type()],
- vars :: [core_vars()],
- file_loc :: file_location(),
- index :: non_neg_integer(),
- fun_mfa :: dialyzer_callgraph:mfa_or_funlbl(),
- fun_label :: label()}).
-
--record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl()
- | 'undefined',
- curr_fun_label :: label() | 'undefined',
- curr_fun_args = 'empty' :: core_args(),
- new_table = 'no_t' :: table(),
- race_list = [] :: code(),
- race_list_size = 0 :: non_neg_integer(),
- race_tags = [] :: [#race_fun{}],
- %% true for fun types and warning mode
- race_analysis = false :: boolean(),
- race_warnings = [] :: [dial_race_warning()]}).
-
-%%% ===========================================================================
-%%%
-%%% Exported Types
-%%%
-%%% ===========================================================================
-
--opaque races() :: #races{}.
-
-%%% ===========================================================================
-%%%
-%%% Race Analysis
-%%%
-%%% ===========================================================================
-
--spec store_race_call(dialyzer_callgraph:mfa_or_funlbl(),
- [erl_types:erl_type()], [core_vars()],
- file_location(), dialyzer_dataflow:state()) ->
- dialyzer_dataflow:state().
-
-store_race_call(Fun, ArgTypes, Args, FileLocation, State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- CurrFun = Races#races.curr_fun,
- CurrFunLabel = Races#races.curr_fun_label,
- RaceTags = Races#races.race_tags,
- CleanState = dialyzer_dataflow:state__records_only(State),
- {NewRaceList, NewRaceListSize, NewRaceTags, NewTable} =
- case CurrFun of
- {_Module, module_info, A} when A =:= 0 orelse A =:= 1 ->
- {[], 0, RaceTags, no_t};
- _Thing ->
- RaceList = Races#races.race_list,
- RaceListSize = Races#races.race_list_size,
- case Fun of
- {erlang, get_module_info, A} when A =:= 1 orelse A =:= 2 ->
- {[], 0, RaceTags, no_t};
- {erlang, register, 2} ->
- VarArgs = format_args(Args, ArgTypes, CleanState, register),
- RaceFun = #race_fun{mfa = Fun, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- file_loc = FileLocation, index = RaceListSize,
- fun_mfa = CurrFun, fun_label = CurrFunLabel},
- {[#warn_call{call_name = register, args = VarArgs}|
- RaceList], RaceListSize + 1, [RaceFun|RaceTags], no_t};
- {erlang, unregister, 1} ->
- VarArgs = format_args(Args, ArgTypes, CleanState, unregister),
- RaceFun = #race_fun{mfa = Fun, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- file_loc = FileLocation, index = RaceListSize,
- fun_mfa = CurrFun, fun_label = CurrFunLabel},
- {[#warn_call{call_name = unregister, args = VarArgs}|
- RaceList], RaceListSize + 1, [RaceFun|RaceTags], no_t};
- {erlang, whereis, 1} ->
- VarArgs = format_args(Args, ArgTypes, CleanState, whereis),
- {[#dep_call{call_name = whereis, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- state = CleanState, file_loc = FileLocation}|
- RaceList], RaceListSize + 1, RaceTags, no_t};
- {ets, insert, 2} ->
- VarArgs = format_args(Args, ArgTypes, CleanState, ets_insert),
- RaceFun = #race_fun{mfa = Fun, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- file_loc = FileLocation, index = RaceListSize,
- fun_mfa = CurrFun, fun_label = CurrFunLabel},
- {[#warn_call{call_name = ets_insert, args = VarArgs}|
- RaceList], RaceListSize + 1, [RaceFun|RaceTags], no_t};
- {ets, lookup, 2} ->
- VarArgs = format_args(Args, ArgTypes, CleanState, ets_lookup),
- {[#dep_call{call_name = ets_lookup, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- state = CleanState, file_loc = FileLocation}|
- RaceList], RaceListSize + 1, RaceTags, no_t};
- {ets, new, 2} ->
- VarArgs = format_args(Args, ArgTypes, CleanState, ets_new),
- [VarArgs1, VarArgs2, _, Options] = VarArgs,
- NewTable1 =
- case lists:member("'public'", Options) of
- true ->
- case lists:member("'named_table'", Options) of
- true ->
- {named, VarArgs1, VarArgs2};
- false -> other
- end;
- false -> no_t
- end,
- {RaceList, RaceListSize, RaceTags, NewTable1};
- {mnesia, dirty_read, A} when A =:= 1 orelse A =:= 2 ->
- VarArgs =
- case A of
- 1 ->
- format_args(Args, ArgTypes, CleanState, mnesia_dirty_read1);
- 2 ->
- format_args(Args, ArgTypes, CleanState, mnesia_dirty_read2)
- end,
- {[#dep_call{call_name = mnesia_dirty_read, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- state = CleanState, file_loc = FileLocation}|RaceList],
- RaceListSize + 1, RaceTags, no_t};
- {mnesia, dirty_write, A} when A =:= 1 orelse A =:= 2 ->
- VarArgs =
- case A of
- 1 ->
- format_args(Args, ArgTypes, CleanState, mnesia_dirty_write1);
- 2 ->
- format_args(Args, ArgTypes, CleanState, mnesia_dirty_write2)
- end,
- RaceFun = #race_fun{mfa = Fun, args = VarArgs,
- arg_types = ArgTypes, vars = Args,
- file_loc = FileLocation, index = RaceListSize,
- fun_mfa = CurrFun, fun_label = CurrFunLabel},
- {[#warn_call{call_name = mnesia_dirty_write,
- args = VarArgs}|RaceList],
- RaceListSize + 1, [RaceFun|RaceTags], no_t};
- Int when is_integer(Int) ->
- {[#fun_call{caller = CurrFun, callee = Int, arg_types = ArgTypes,
- vars = Args}|RaceList],
- RaceListSize + 1, RaceTags, no_t};
- _Other ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- case digraph:vertex(dialyzer_callgraph:get_digraph(Callgraph),
- Fun) of
- {Fun, confirmed} ->
- {[#fun_call{caller = CurrFun, callee = Fun,
- arg_types = ArgTypes, vars = Args}|RaceList],
- RaceListSize + 1, RaceTags, no_t};
- false ->
- {RaceList, RaceListSize, RaceTags, no_t}
- end
- end
- end,
- state__renew_info(NewRaceList, NewRaceListSize, NewRaceTags, NewTable, State).
-
--spec race(dialyzer_dataflow:state()) -> dialyzer_dataflow:state().
-
-race(State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- RaceTags = Races#races.race_tags,
- RetState =
- case RaceTags of
- [] -> State;
- [#race_fun{mfa = Fun,
- args = VarArgs, arg_types = ArgTypes,
- vars = Args, file_loc = FileLocation,
- index = Index, fun_mfa = CurrFun,
- fun_label = CurrFunLabel}|T] ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- {ok, [_Args, Code]} =
- dict:find(CurrFun, dialyzer_callgraph:get_race_code(Callgraph)),
- RaceList = lists:reverse(Code),
- RaceWarnTag =
- case Fun of
- {erlang, register, 2} -> ?WARN_WHEREIS_REGISTER;
- {erlang, unregister, 1} -> ?WARN_WHEREIS_UNREGISTER;
- {ets, insert, 2} -> ?WARN_ETS_LOOKUP_INSERT;
- {mnesia, dirty_write, _A} -> ?WARN_MNESIA_DIRTY_READ_WRITE
- end,
- State1 =
- state__renew_curr_fun(CurrFun,
- state__renew_curr_fun_label(CurrFunLabel,
- state__renew_race_list(lists:nthtail(length(RaceList) - Index,
- RaceList), State))),
- DepList = fixup_race_list(RaceWarnTag, VarArgs, State1),
- {State2, RaceWarn} =
- get_race_warn(Fun, Args, ArgTypes, DepList, State),
- {File, Location} = FileLocation,
- CurrMFA = dialyzer_dataflow:state__find_function(CurrFun, State),
- WarningInfo = {File, Location, CurrMFA},
- race(
- state__add_race_warning(
- state__renew_race_tags(T, State2), RaceWarn, RaceWarnTag,
- WarningInfo))
- end,
- state__renew_race_tags([], RetState).
-
-fixup_race_list(RaceWarnTag, WarnVarArgs, State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- CurrFun = Races#races.curr_fun,
- CurrFunLabel = Races#races.curr_fun_label,
- RaceList = Races#races.race_list,
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- Digraph = dialyzer_callgraph:get_digraph(Callgraph),
- Calls = digraph:edges(Digraph),
- RaceTag =
- case RaceWarnTag of
- ?WARN_WHEREIS_REGISTER -> whereis_register;
- ?WARN_WHEREIS_UNREGISTER -> whereis_unregister;
- ?WARN_ETS_LOOKUP_INSERT -> ets_lookup_insert;
- ?WARN_MNESIA_DIRTY_READ_WRITE -> mnesia_dirty_read_write
- end,
- NewRaceList = [RaceTag|RaceList],
- CleanState = dialyzer_dataflow:state__cleanup(State),
- NewState = state__renew_race_list(NewRaceList, CleanState),
- DepList1 =
- fixup_race_forward_pullout(CurrFun, CurrFunLabel, Calls,
- lists:reverse(NewRaceList), [], CurrFun,
- WarnVarArgs, RaceWarnTag, dict:new(),
- [], [], [], 2 * ?local, NewState),
- Parents = fixup_race_backward(CurrFun, Calls, Calls, [], ?local),
- UParents = lists:usort(Parents),
- Filtered = filter_parents(UParents, UParents, Digraph),
- NewParents =
- case lists:member(CurrFun, Filtered) of
- true -> Filtered;
- false -> [CurrFun|Filtered]
- end,
- 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,
- State) ->
- case Parents of
- [] -> [];
- [Head|Tail] ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- Code =
- case dict:find(Head, dialyzer_callgraph:get_race_code(Callgraph)) of
- error -> [];
- {ok, [_A, C]} -> C
- end,
- {ok, FunLabel} = dialyzer_callgraph:lookup_label(Head, Callgraph),
- DepList1 =
- fixup_race_forward_pullout(Head, FunLabel, Calls, Code, [], CurrFun,
- WarnVarArgs, RaceWarnTag, dict:new(),
- [], [], [], 2 * ?local, State),
- DepList2 =
- fixup_race_list_helper(Tail, Calls, CurrFun, WarnVarArgs,
- RaceWarnTag, State),
- DepList1 ++ DepList2
- end.
-
-%%% ===========================================================================
-%%%
-%%% Forward Analysis
-%%%
-%%% ===========================================================================
-
-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(TState)),
- dialyzer_dataflow:dispose_state(TState),
- case NewCode of
- [] -> DepList;
- [#fun_call{caller = NewCurrFun, callee = Call, arg_types = FunTypes,
- vars = FunArgs}|Tail] ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- OkCall = {ok, Call},
- {Name, Label} =
- case is_integer(Call) of
- true ->
- case dialyzer_callgraph:lookup_name(Call, Callgraph) of
- error -> {OkCall, OkCall};
- N -> {N, OkCall}
- end;
- false ->
- {OkCall, dialyzer_callgraph:lookup_label(Call, Callgraph)}
- end,
- {NewCurrFun1, NewCurrFunLabel1, NewCalls1, NewCode1, NewRaceList1,
- NewRaceVarMap1, NewFunDefVars1, NewFunCallVars1, NewFunArgTypes1,
- NewNestingLevel1} =
- case Label =:= error of
- true ->
- {NewCurrFun, NewCurrFunLabel, NewCalls, Tail, NewRaceList,
- NewRaceVarMap, NewFunDefVars, NewFunCallVars, NewFunArgTypes,
- NewNestingLevel};
- false ->
- {ok, Fun} = Name,
- {ok, Int} = Label,
- case dict:find(Fun, dialyzer_callgraph:get_race_code(Callgraph)) of
- error ->
- {NewCurrFun, NewCurrFunLabel, NewCalls, Tail, NewRaceList,
- NewRaceVarMap, NewFunDefVars, NewFunCallVars, NewFunArgTypes,
- NewNestingLevel};
- {ok, [Args, CodeB]} ->
- Races = dialyzer_dataflow:state__get_races(State),
- {RetCurrFun, RetCurrFunLabel, RetCalls, RetCode,
- RetRaceList, RetRaceVarMap, RetFunDefVars, RetFunCallVars,
- RetFunArgTypes, RetNestingLevel} =
- fixup_race_forward_helper(NewCurrFun,
- NewCurrFunLabel, Fun, Int, NewCalls, NewCalls,
- [#curr_fun{status = out, mfa = NewCurrFun,
- label = NewCurrFunLabel,
- var_map = NewRaceVarMap,
- def_vars = NewFunDefVars,
- call_vars = NewFunCallVars,
- arg_types = NewFunArgTypes}|
- Tail],
- NewRaceList, InitFun, FunArgs, FunTypes, RaceWarnTag,
- NewRaceVarMap, NewFunDefVars, NewFunCallVars,
- NewFunArgTypes, NewNestingLevel, Args, CodeB,
- Races#races.race_list),
- case RetCode of
- [#curr_fun{}|_CodeTail] ->
- {NewCurrFun, NewCurrFunLabel, RetCalls, RetCode,
- RetRaceList, NewRaceVarMap, NewFunDefVars,
- NewFunCallVars, NewFunArgTypes, RetNestingLevel};
- _Else ->
- {RetCurrFun, RetCurrFunLabel, RetCalls, RetCode,
- RetRaceList, RetRaceVarMap, RetFunDefVars,
- RetFunCallVars, RetFunArgTypes, RetNestingLevel}
- end
- end
- end,
- DepList ++
- fixup_race_forward_pullout(NewCurrFun1, NewCurrFunLabel1, NewCalls1,
- NewCode1, NewRaceList1, InitFun, WarnVarArgs,
- RaceWarnTag, NewRaceVarMap1, NewFunDefVars1,
- NewFunCallVars1, NewFunArgTypes1,
- NewNestingLevel1, State)
- end.
-
-fixup_race_forward(CurrFun, CurrFunLabel, Calls, Code, RaceList,
- InitFun, WarnVarArgs, RaceWarnTag, RaceVarMap,
- FunDefVars, FunCallVars, FunArgTypes, NestingLevel,
- State) ->
- case Code of
- [] ->
- {[], CurrFun, CurrFunLabel, Calls, Code, RaceList, RaceVarMap,
- FunDefVars, FunCallVars, FunArgTypes, NestingLevel};
- [Head|Tail] ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- {NewRL, DepList, NewNL, Return} =
- case Head of
- #dep_call{call_name = whereis} ->
- case RaceWarnTag of
- WarnWhereis when WarnWhereis =:= ?WARN_WHEREIS_REGISTER orelse
- WarnWhereis =:= ?WARN_WHEREIS_UNREGISTER ->
- {[Head#dep_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- _Other ->
- {RaceList, [], NestingLevel, false}
- end;
- #dep_call{call_name = ets_lookup} ->
- case RaceWarnTag of
- ?WARN_ETS_LOOKUP_INSERT ->
- {[Head#dep_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- _Other ->
- {RaceList, [], NestingLevel, false}
- end;
- #dep_call{call_name = mnesia_dirty_read} ->
- case RaceWarnTag of
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- {[Head#dep_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- _Other ->
- {RaceList, [], NestingLevel, false}
- end;
- #warn_call{call_name = RegCall} when RegCall =:= register orelse
- RegCall =:= unregister ->
- case RaceWarnTag of
- WarnWhereis when WarnWhereis =:= ?WARN_WHEREIS_REGISTER orelse
- WarnWhereis =:= ?WARN_WHEREIS_UNREGISTER ->
- {[Head#warn_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- _Other ->
- {RaceList, [], NestingLevel, false}
- end;
- #warn_call{call_name = ets_insert} ->
- case RaceWarnTag of
- ?WARN_ETS_LOOKUP_INSERT ->
- {[Head#warn_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- _Other ->
- {RaceList, [], NestingLevel, false}
- end;
- #warn_call{call_name = mnesia_dirty_write} ->
- case RaceWarnTag of
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- {[Head#warn_call{var_map = RaceVarMap}|RaceList],
- [], NestingLevel, false};
- _Other ->
- {RaceList, [], NestingLevel, false}
- end;
- #fun_call{caller = CurrFun, callee = InitFun} ->
- {RaceList, [], NestingLevel, false};
- #fun_call{caller = CurrFun} ->
- {RaceList, [], NestingLevel - 1, false};
- beg_case ->
- {[Head|RaceList], [], NestingLevel, false};
- #beg_clause{} ->
- {[#beg_clause{}|RaceList], [], NestingLevel, false};
- #end_clause{} ->
- {[#end_clause{}|RaceList], [], NestingLevel, false};
- #end_case{} ->
- {[Head|RaceList], [], NestingLevel, false};
- #let_tag{} ->
- {RaceList, [], NestingLevel, false};
- #curr_fun{status = in, mfa = InitFun,
- label = _InitFunLabel, var_map = _NewRVM,
- def_vars = NewFDV, call_vars = NewFCV,
- arg_types = _NewFAT} ->
- {[#curr_fun{status = out, var_map = RaceVarMap,
- def_vars = NewFDV, call_vars = NewFCV}|
- RaceList], [], NestingLevel - 1, false};
- #curr_fun{status = in, def_vars = NewFDV,
- call_vars = NewFCV} ->
- {[#curr_fun{status = out, var_map = RaceVarMap,
- def_vars = NewFDV, call_vars = NewFCV}|
- RaceList],
- [], NestingLevel - 1, false};
- #curr_fun{status = out} ->
- {[#curr_fun{status = in, var_map = RaceVarMap}|RaceList], [],
- NestingLevel + 1, false};
- RaceTag ->
- PublicTables = dialyzer_callgraph:get_public_tables(Callgraph),
- NamedTables = dialyzer_callgraph:get_named_tables(Callgraph),
- WarnVarArgs1 =
- var_type_analysis(FunDefVars, FunArgTypes, WarnVarArgs,
- RaceWarnTag, RaceVarMap,
- dialyzer_dataflow:state__records_only(State)),
- {NewDepList, IsPublic, _Return} =
- get_deplist_paths(RaceList, WarnVarArgs1, RaceWarnTag,
- RaceVarMap, 0, PublicTables, NamedTables),
- {NewHead, NewDepList1} =
- case RaceTag of
- whereis_register ->
- {[#warn_call{call_name = register, args = WarnVarArgs,
- var_map = RaceVarMap}],
- NewDepList};
- whereis_unregister ->
- {[#warn_call{call_name = unregister, args = WarnVarArgs,
- var_map = RaceVarMap}],
- NewDepList};
- ets_lookup_insert ->
- NewWarnCall =
- [#warn_call{call_name = ets_insert, args = WarnVarArgs,
- var_map = RaceVarMap}],
- [Tab, Names, _, _] = WarnVarArgs,
- case IsPublic orelse
- compare_var_list(Tab, PublicTables, RaceVarMap)
- orelse
- length(Names -- NamedTables) < length(Names) of
- true ->
- {NewWarnCall, NewDepList};
- false -> {NewWarnCall, []}
- end;
- mnesia_dirty_read_write ->
- {[#warn_call{call_name = mnesia_dirty_write,
- args = WarnVarArgs, var_map = RaceVarMap}],
- NewDepList}
- end,
- {NewHead ++ RaceList, NewDepList1, NestingLevel,
- is_last_race(RaceTag, InitFun, Tail, Callgraph)}
- end,
- {NewCurrFun, NewCurrFunLabel, NewCode, NewRaceList, NewRaceVarMap,
- NewFunDefVars, NewFunCallVars, NewFunArgTypes, NewNestingLevel,
- PullOut} =
- case Head of
- #fun_call{caller = CurrFun} ->
- case NewNL =:= 0 of
- true ->
- {CurrFun, CurrFunLabel, Tail, NewRL, RaceVarMap,
- FunDefVars, FunCallVars, FunArgTypes, NewNL, false};
- false ->
- {CurrFun, CurrFunLabel, Code, NewRL, RaceVarMap,
- FunDefVars, FunCallVars, FunArgTypes, NewNL, true}
- end;
- #beg_clause{arg = Arg, pats = Pats, guard = Guard} ->
- {RaceVarMap1, RemoveClause} =
- race_var_map_guard(Arg, Pats, Guard, RaceVarMap, bind),
- case RemoveClause of
- true ->
- {RaceList2,
- #curr_fun{mfa = CurrFun2, label = CurrFunLabel2,
- var_map = RaceVarMap2, def_vars = FunDefVars2,
- call_vars = FunCallVars2, arg_types = FunArgTypes2},
- Code2, NestingLevel2} =
- remove_clause(NewRL,
- #curr_fun{mfa = CurrFun, label = CurrFunLabel,
- var_map = RaceVarMap1,
- def_vars = FunDefVars,
- call_vars = FunCallVars,
- arg_types = FunArgTypes},
- Tail, NewNL),
- {CurrFun2, CurrFunLabel2, Code2, RaceList2,
- RaceVarMap2, FunDefVars2, FunCallVars2, FunArgTypes2,
- NestingLevel2, false};
- false ->
- {CurrFun, CurrFunLabel, Tail, NewRL, RaceVarMap1,
- FunDefVars, FunCallVars, FunArgTypes, NewNL, false}
- end;
- #end_clause{arg = Arg, pats = Pats, guard = Guard} ->
- {RaceVarMap1, _RemoveClause} =
- race_var_map_guard(Arg, Pats, Guard, RaceVarMap, unbind),
- {CurrFun, CurrFunLabel, Tail, NewRL, RaceVarMap1,
- FunDefVars, FunCallVars, FunArgTypes, NewNL,
- false};
- #end_case{clauses = Clauses} ->
- RaceVarMap1 =
- race_var_map_clauses(Clauses, RaceVarMap),
- {CurrFun, CurrFunLabel, Tail, NewRL, RaceVarMap1,
- FunDefVars, FunCallVars, FunArgTypes, NewNL,
- false};
- #let_tag{var = Var, arg = Arg} ->
- {CurrFun, CurrFunLabel, Tail, NewRL,
- race_var_map(Var, Arg, RaceVarMap, bind), FunDefVars,
- FunCallVars, FunArgTypes, NewNL, false};
- #curr_fun{mfa = CurrFun1, label = CurrFunLabel1,
- var_map = RaceVarMap1, def_vars = FunDefVars1,
- call_vars = FunCallVars1, arg_types = FunArgTypes1} ->
- case NewNL =:= 0 of
- true ->
- {CurrFun, CurrFunLabel,
- remove_nonlocal_functions(Tail, 1), NewRL, RaceVarMap,
- FunDefVars, FunCallVars, FunArgTypes, NewNL, false};
- false ->
- {CurrFun1, CurrFunLabel1, Tail, NewRL, RaceVarMap1,
- FunDefVars1, FunCallVars1, FunArgTypes1, NewNL, false}
- end;
- _Thing ->
- {CurrFun, CurrFunLabel, Tail, NewRL, RaceVarMap,
- FunDefVars, FunCallVars, FunArgTypes, NewNL, false}
- end,
- case Return of
- true ->
- {DepList, NewCurrFun, NewCurrFunLabel, Calls,
- [], NewRaceList, NewRaceVarMap, NewFunDefVars,
- NewFunCallVars, NewFunArgTypes, NewNestingLevel};
- false ->
- NewNestingLevel1 =
- case NewNestingLevel =:= 0 of
- true -> NewNestingLevel + 1;
- false -> NewNestingLevel
- end,
- case PullOut of
- true ->
- {DepList, NewCurrFun, NewCurrFunLabel, Calls,
- NewCode, NewRaceList, NewRaceVarMap, NewFunDefVars,
- NewFunCallVars, NewFunArgTypes, NewNestingLevel1};
- false ->
- {RetDepList, NewCurrFun1, NewCurrFunLabel1, NewCalls1,
- NewCode1, NewRaceList1, NewRaceVarMap1, NewFunDefVars1,
- NewFunCallVars1, NewFunArgTypes1, NewNestingLevel2} =
- fixup_race_forward(NewCurrFun, NewCurrFunLabel, Calls,
- NewCode, NewRaceList, InitFun, WarnVarArgs,
- RaceWarnTag, NewRaceVarMap, NewFunDefVars,
- NewFunCallVars, NewFunArgTypes,
- NewNestingLevel1, State),
- {DepList ++ RetDepList, NewCurrFun1, NewCurrFunLabel1,
- NewCalls1, NewCode1, NewRaceList1, NewRaceVarMap1,
- NewFunDefVars1, NewFunCallVars1, NewFunArgTypes1,
- NewNestingLevel2}
- end
- end
- end.
-
-get_deplist_paths(RaceList, WarnVarArgs, RaceWarnTag, RaceVarMap, CurrLevel,
- PublicTables, NamedTables) ->
- case RaceList of
- [] -> {[], false, true};
- [Head|Tail] ->
- case Head of
- #end_case{} ->
- {RaceList1, DepList1, IsPublic1, Continue1} =
- handle_case(Tail, WarnVarArgs, RaceWarnTag, RaceVarMap, CurrLevel,
- PublicTables, NamedTables),
- case Continue1 of
- true ->
- {DepList2, IsPublic2, Continue2} =
- get_deplist_paths(RaceList1, WarnVarArgs, RaceWarnTag,
- RaceVarMap, CurrLevel, PublicTables,
- NamedTables),
- {DepList1 ++ DepList2, IsPublic1 orelse IsPublic2, Continue2};
- false -> {DepList1, IsPublic1, false}
- end;
- #beg_clause{} ->
- get_deplist_paths(fixup_before_case_path(Tail), WarnVarArgs,
- RaceWarnTag, RaceVarMap, CurrLevel, PublicTables,
- NamedTables);
- #curr_fun{status = in, var_map = RaceVarMap1} ->
- {DepList, IsPublic, Continue} =
- get_deplist_paths(Tail, WarnVarArgs, RaceWarnTag, RaceVarMap,
- CurrLevel + 1, PublicTables, NamedTables),
- IsPublic1 =
- case RaceWarnTag of
- ?WARN_ETS_LOOKUP_INSERT ->
- [Tabs, Names, _, _] = WarnVarArgs,
- IsPublic orelse
- lists:any(
- fun (T) ->
- compare_var_list(T, PublicTables, RaceVarMap1)
- end, Tabs)
- orelse
- length(Names -- NamedTables) < length(Names);
- _ -> true
- end,
- {DepList, IsPublic1, Continue};
- #curr_fun{status = out, var_map = RaceVarMap1, def_vars = FunDefVars,
- call_vars = FunCallVars} ->
- WarnVarArgs1 =
- var_analysis([format_arg(DefVar) || DefVar <- FunDefVars],
- [format_arg(CallVar) || CallVar <- FunCallVars],
- WarnVarArgs, RaceWarnTag),
- {WarnVarArgs2, Stop} =
- case RaceWarnTag of
- ?WARN_WHEREIS_REGISTER ->
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs1,
- Vars =
- lists:flatten(
- [find_all_bound_vars(V, RaceVarMap1) || V <- WVA1]),
- case {Vars, CurrLevel} of
- {[], 0} ->
- {WarnVarArgs, true};
- {[], _} ->
- {WarnVarArgs, false};
- _ ->
- {[Vars, WVA2, WVA3, WVA4], false}
- end;
- ?WARN_WHEREIS_UNREGISTER ->
- [WVA1, WVA2] = WarnVarArgs1,
- Vars =
- lists:flatten(
- [find_all_bound_vars(V, RaceVarMap1) || V <- WVA1]),
- case {Vars, CurrLevel} of
- {[], 0} ->
- {WarnVarArgs, true};
- {[], _} ->
- {WarnVarArgs, false};
- _ ->
- {[Vars, WVA2], false}
- end;
- ?WARN_ETS_LOOKUP_INSERT ->
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs1,
- Vars1 =
- lists:flatten(
- [find_all_bound_vars(V1, RaceVarMap1) || V1 <- WVA1]),
- Vars2 =
- lists:flatten(
- [find_all_bound_vars(V2, RaceVarMap1) || V2 <- WVA3]),
- case {Vars1, Vars2, CurrLevel} of
- {[], _, 0} ->
- {WarnVarArgs, true};
- {[], _, _} ->
- {WarnVarArgs, false};
- {_, [], 0} ->
- {WarnVarArgs, true};
- {_, [], _} ->
- {WarnVarArgs, false};
- _ ->
- {[Vars1, WVA2, Vars2, WVA4], false}
- end;
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- [WVA1, WVA2|T] = WarnVarArgs1,
- Vars =
- lists:flatten(
- [find_all_bound_vars(V, RaceVarMap1) || V <- WVA1]),
- case {Vars, CurrLevel} of
- {[], 0} ->
- {WarnVarArgs, true};
- {[], _} ->
- {WarnVarArgs, false};
- _ ->
- {[Vars, WVA2|T], false}
- end
- end,
- case Stop of
- true -> {[], false, false};
- false ->
- CurrLevel1 =
- case CurrLevel of
- 0 -> CurrLevel;
- _ -> CurrLevel - 1
- end,
- get_deplist_paths(Tail, WarnVarArgs2, RaceWarnTag, RaceVarMap1,
- CurrLevel1, PublicTables, NamedTables)
- end;
- #warn_call{call_name = RegCall, args = WarnVarArgs1,
- var_map = RaceVarMap1} when RegCall =:= register orelse
- RegCall =:= unregister ->
- case compare_first_arg(WarnVarArgs, WarnVarArgs1, RaceVarMap1) of
- true -> {[], false, false};
- NewWarnVarArgs ->
- get_deplist_paths(Tail, NewWarnVarArgs, RaceWarnTag, RaceVarMap,
- CurrLevel, PublicTables, NamedTables)
- end;
- #warn_call{call_name = ets_insert, args = WarnVarArgs1,
- var_map = RaceVarMap1} ->
- case compare_ets_insert(WarnVarArgs, WarnVarArgs1, RaceVarMap1) of
- true -> {[], false, false};
- NewWarnVarArgs ->
- get_deplist_paths(Tail, NewWarnVarArgs, RaceWarnTag, RaceVarMap,
- CurrLevel, PublicTables, NamedTables)
- end;
- #warn_call{call_name = mnesia_dirty_write, args = WarnVarArgs1,
- var_map = RaceVarMap1} ->
- case compare_first_arg(WarnVarArgs, WarnVarArgs1, RaceVarMap1) of
- true -> {[], false, false};
- NewWarnVarArgs ->
- get_deplist_paths(Tail, NewWarnVarArgs, RaceWarnTag, RaceVarMap,
- CurrLevel, PublicTables, NamedTables)
- end;
- #dep_call{var_map = RaceVarMap1} ->
- {DepList, IsPublic, Continue} =
- get_deplist_paths(Tail, WarnVarArgs, RaceWarnTag, RaceVarMap,
- CurrLevel, PublicTables, NamedTables),
- {refine_race(Head, WarnVarArgs, RaceWarnTag, DepList, RaceVarMap1),
- IsPublic, Continue}
- end
- end.
-
-handle_case(RaceList, WarnVarArgs, RaceWarnTag, RaceVarMap, CurrLevel,
- PublicTables, NamedTables) ->
- case RaceList of
- [] -> {[], [], false, true};
- [Head|Tail] ->
- case Head of
- #end_clause{} ->
- {RestRaceList, DepList1, IsPublic1, Continue1} =
- do_clause(Tail, WarnVarArgs, RaceWarnTag, RaceVarMap, CurrLevel,
- PublicTables, NamedTables),
- {RetRaceList, DepList2, IsPublic2, Continue2} =
- handle_case(RestRaceList, WarnVarArgs, RaceWarnTag, RaceVarMap,
- CurrLevel, PublicTables, NamedTables),
- {RetRaceList, DepList1 ++ DepList2, IsPublic1 orelse IsPublic2,
- Continue1 orelse Continue2};
- beg_case -> {Tail, [], false, false}
- end
- end.
-
-do_clause(RaceList, WarnVarArgs, RaceWarnTag, RaceVarMap, CurrLevel,
- PublicTables, NamedTables) ->
- {DepList, IsPublic, Continue} =
- get_deplist_paths(fixup_case_path(RaceList, 0), WarnVarArgs,
- RaceWarnTag, RaceVarMap, CurrLevel,
- PublicTables, NamedTables),
- {fixup_case_rest_paths(RaceList, 0), DepList, IsPublic, Continue}.
-
-fixup_case_path(RaceList, NestingLevel) ->
- case RaceList of
- [] -> [];
- [Head|Tail] ->
- {NewNestingLevel, Return} =
- case Head of
- beg_case -> {NestingLevel - 1, false};
- #end_case{} -> {NestingLevel + 1, false};
- #beg_clause{} ->
- case NestingLevel =:= 0 of
- true -> {NestingLevel, true};
- false -> {NestingLevel, false}
- end;
- _Other -> {NestingLevel, false}
- end,
- case Return of
- true -> [];
- false -> [Head|fixup_case_path(Tail, NewNestingLevel)]
- end
- end.
-
-%% Gets the race list before a case clause.
-fixup_before_case_path(RaceList) ->
- case RaceList of
- [] -> [];
- [Head|Tail] ->
- case Head of
- #end_clause{} ->
- fixup_before_case_path(fixup_case_rest_paths(Tail, 0));
- beg_case -> Tail
- end
- end.
-
-fixup_case_rest_paths(RaceList, NestingLevel) ->
- case RaceList of
- [] -> [];
- [Head|Tail] ->
- {NewNestingLevel, Return} =
- case Head of
- beg_case -> {NestingLevel - 1, false};
- #end_case{} -> {NestingLevel + 1, false};
- #beg_clause{} ->
- case NestingLevel =:= 0 of
- true -> {NestingLevel, true};
- false -> {NestingLevel, false}
- end;
- _Other -> {NestingLevel, false}
- end,
- case Return of
- true -> Tail;
- false -> fixup_case_rest_paths(Tail, NewNestingLevel)
- end
- end.
-
-fixup_race_forward_helper(CurrFun, CurrFunLabel, Fun, FunLabel,
- Calls, CallsToAnalyze, Code, RaceList,
- InitFun, NewFunArgs, NewFunTypes,
- RaceWarnTag, RaceVarMap, FunDefVars,
- FunCallVars, FunArgTypes, NestingLevel,
- Args, CodeB, StateRaceList) ->
- case Calls of
- [] ->
- {NewRaceList,
- #curr_fun{mfa = NewCurrFun, label = NewCurrFunLabel,
- var_map = NewRaceVarMap, def_vars = NewFunDefVars,
- call_vars = NewFunCallVars, arg_types = NewFunArgTypes},
- NewCode, NewNestingLevel} =
- remove_clause(RaceList,
- #curr_fun{mfa = CurrFun, label = CurrFunLabel, var_map = RaceVarMap,
- def_vars = FunDefVars, call_vars = FunCallVars,
- arg_types = FunArgTypes},
- Code, NestingLevel),
- {NewCurrFun, NewCurrFunLabel, CallsToAnalyze, NewCode, NewRaceList,
- NewRaceVarMap, NewFunDefVars, NewFunCallVars, NewFunArgTypes,
- NewNestingLevel};
- [Head|Tail] ->
- case Head of
- {InitFun, InitFun} when CurrFun =:= InitFun, Fun =:= InitFun ->
- NewCallsToAnalyze = lists:delete(Head, CallsToAnalyze),
- NewRaceVarMap =
- race_var_map(Args, NewFunArgs, RaceVarMap, bind),
- RetC =
- fixup_all_calls(InitFun, InitFun, FunLabel, Args,
- CodeB ++
- [#curr_fun{status = out, mfa = InitFun,
- label = CurrFunLabel, var_map = RaceVarMap,
- def_vars = FunDefVars, call_vars = FunCallVars,
- arg_types = FunArgTypes}],
- Code, RaceVarMap),
- NewCode =
- fixup_all_calls(InitFun, InitFun, FunLabel, Args,
- CodeB ++
- [#curr_fun{status = out, mfa = InitFun,
- label = CurrFunLabel, var_map = NewRaceVarMap,
- def_vars = Args, call_vars = NewFunArgs,
- arg_types = NewFunTypes}],
- [#curr_fun{status = in, mfa = Fun,
- label = FunLabel, var_map = NewRaceVarMap,
- def_vars = Args, call_vars = NewFunArgs,
- arg_types = NewFunTypes}|
- lists:reverse(StateRaceList)] ++
- RetC, NewRaceVarMap),
- {InitFun, FunLabel, NewCallsToAnalyze, NewCode, RaceList,
- NewRaceVarMap, Args, NewFunArgs, NewFunTypes, NestingLevel};
- {CurrFun, Fun} ->
- NewCallsToAnalyze = lists:delete(Head, CallsToAnalyze),
- NewRaceVarMap = race_var_map(Args, NewFunArgs, RaceVarMap, bind),
- RetC =
- case Fun of
- InitFun ->
- fixup_all_calls(CurrFun, Fun, FunLabel, Args,
- lists:reverse(StateRaceList) ++
- [#curr_fun{status = out, mfa = CurrFun,
- label = CurrFunLabel, var_map = RaceVarMap,
- def_vars = FunDefVars, call_vars = FunCallVars,
- arg_types = FunArgTypes}],
- Code, RaceVarMap);
- _Other1 ->
- fixup_all_calls(CurrFun, Fun, FunLabel, Args,
- CodeB ++
- [#curr_fun{status = out, mfa = CurrFun,
- label = CurrFunLabel, var_map = RaceVarMap,
- def_vars = FunDefVars, call_vars = FunCallVars,
- arg_types = FunArgTypes}],
- Code, RaceVarMap)
- end,
- NewCode =
- case Fun of
- InitFun ->
- [#curr_fun{status = in, mfa = Fun,
- label = FunLabel, var_map = NewRaceVarMap,
- def_vars = Args, call_vars = NewFunArgs,
- arg_types = NewFunTypes}|
- lists:reverse(StateRaceList)] ++ RetC;
- _ ->
- [#curr_fun{status = in, mfa = Fun,
- label = FunLabel, var_map = NewRaceVarMap,
- def_vars = Args, call_vars = NewFunArgs,
- arg_types = NewFunTypes}|CodeB] ++
- RetC
- end,
- {Fun, FunLabel, NewCallsToAnalyze, NewCode, RaceList, NewRaceVarMap,
- Args, NewFunArgs, NewFunTypes, NestingLevel};
- {_TupleA, _TupleB} ->
- fixup_race_forward_helper(CurrFun, CurrFunLabel, Fun, FunLabel,
- Tail, CallsToAnalyze, Code, RaceList, InitFun, NewFunArgs,
- NewFunTypes, RaceWarnTag, RaceVarMap, FunDefVars, FunCallVars,
- FunArgTypes, NestingLevel, Args, CodeB, StateRaceList)
- end
- end.
-
-%%% ===========================================================================
-%%%
-%%% Backward Analysis
-%%%
-%%% ===========================================================================
-
-fixup_race_backward(CurrFun, Calls, CallsToAnalyze, Parents, Height) ->
- case Height =:= 0 of
- true -> Parents;
- false ->
- case Calls of
- [] ->
- case is_integer(CurrFun) orelse lists:member(CurrFun, Parents) of
- true -> Parents;
- false -> [CurrFun|Parents]
- end;
- [Head|Tail] ->
- {Parent, TupleB} = Head,
- case TupleB =:= CurrFun of
- true -> % more paths are needed
- NewCallsToAnalyze = lists:delete(Head, CallsToAnalyze),
- NewParents =
- fixup_race_backward(Parent, NewCallsToAnalyze,
- NewCallsToAnalyze, Parents, Height - 1),
- fixup_race_backward(CurrFun, Tail, NewCallsToAnalyze, NewParents,
- Height);
- false ->
- fixup_race_backward(CurrFun, Tail, CallsToAnalyze, Parents,
- Height)
- end
- end
- end.
-
-%%% ===========================================================================
-%%%
-%%% Utilities
-%%%
-%%% ===========================================================================
-
-are_bound_labels(Label1, Label2, RaceVarMap) ->
- case dict:find(Label1, RaceVarMap) of
- error -> false;
- {ok, Labels} ->
- lists:member(Label2, Labels) orelse
- are_bound_labels_helper(Labels, Label1, Label2, RaceVarMap)
- end.
-
-are_bound_labels_helper(Labels, OldLabel, CompLabel, RaceVarMap) ->
- case dict:size(RaceVarMap) of
- 0 -> false;
- _ ->
- case Labels of
- [] -> false;
- [Head|Tail] ->
- NewRaceVarMap = dict:erase(OldLabel, RaceVarMap),
- are_bound_labels(Head, CompLabel, NewRaceVarMap) orelse
- are_bound_labels_helper(Tail, Head, CompLabel, NewRaceVarMap)
- end
- end.
-
-are_bound_vars(Vars1, Vars2, RaceVarMap) ->
- case is_list(Vars1) andalso is_list(Vars2) of
- true ->
- case Vars1 of
- [] -> false;
- [AHead|ATail] ->
- case Vars2 of
- [] -> false;
- [PHead|PTail] ->
- are_bound_vars(AHead, PHead, RaceVarMap) andalso
- are_bound_vars(ATail, PTail, RaceVarMap)
- end
- end;
- false ->
- {NewVars1, NewVars2, IsList} =
- case is_list(Vars1) of
- true ->
- case Vars1 of
- [Var1] -> {Var1, Vars2, true};
- _Thing -> {Vars1, Vars2, false}
- end;
- false ->
- case is_list(Vars2) of
- true ->
- case Vars2 of
- [Var2] -> {Vars1, Var2, true};
- _Thing -> {Vars1, Vars2, false}
- end;
- false -> {Vars1, Vars2, true}
- end
- end,
- case IsList of
- true ->
- case cerl:type(NewVars1) of
- var ->
- case cerl:type(NewVars2) of
- var ->
- ALabel = cerl_trees:get_label(NewVars1),
- PLabel = cerl_trees:get_label(NewVars2),
- are_bound_labels(ALabel, PLabel, RaceVarMap) orelse
- are_bound_labels(PLabel, ALabel, RaceVarMap);
- alias ->
- are_bound_vars(NewVars1, cerl:alias_var(NewVars2),
- RaceVarMap);
- values ->
- are_bound_vars(NewVars1, cerl:values_es(NewVars2),
- RaceVarMap);
- _Other -> false
- end;
- tuple ->
- case cerl:type(NewVars2) of
- tuple ->
- are_bound_vars(cerl:tuple_es(NewVars1),
- cerl:tuple_es(NewVars2), RaceVarMap);
- alias ->
- are_bound_vars(NewVars1, cerl:alias_var(NewVars2),
- RaceVarMap);
- values ->
- are_bound_vars(NewVars1, cerl:values_es(NewVars2),
- RaceVarMap);
- _Other -> false
- end;
- cons ->
- case cerl:type(NewVars2) of
- cons ->
- are_bound_vars(cerl:cons_hd(NewVars1),
- cerl:cons_hd(NewVars2), RaceVarMap)
- andalso
- are_bound_vars(cerl:cons_tl(NewVars1),
- cerl:cons_tl(NewVars2), RaceVarMap);
- alias ->
- are_bound_vars(NewVars1, cerl:alias_var(NewVars2),
- RaceVarMap);
- values ->
- are_bound_vars(NewVars1, cerl:values_es(NewVars2),
- RaceVarMap);
- _Other -> false
- end;
- alias ->
- case cerl:type(NewVars2) of
- alias ->
- are_bound_vars(cerl:alias_var(NewVars1),
- cerl:alias_var(NewVars2), RaceVarMap);
- _Other ->
- are_bound_vars(cerl:alias_var(NewVars1),
- NewVars2, RaceVarMap)
- end;
- values ->
- case cerl:type(NewVars2) of
- values ->
- are_bound_vars(cerl:values_es(NewVars1),
- cerl:values_es(NewVars2), RaceVarMap);
- _Other ->
- are_bound_vars(cerl:values_es(NewVars1),
- NewVars2, RaceVarMap)
- end;
- _Other -> false
- end;
- false -> false
- end
- end.
-
-callgraph__renew_tables(Table, Callgraph) ->
- case Table of
- {named, NameLabel, Names} ->
- PTablesToAdd =
- case NameLabel of
- ?no_label -> [];
- _Other -> [NameLabel]
- end,
- NamesToAdd = filter_named_tables(Names),
- PTables = dialyzer_callgraph:get_public_tables(Callgraph),
- NTables = dialyzer_callgraph:get_named_tables(Callgraph),
- dialyzer_callgraph:put_public_tables(
- lists:usort(PTablesToAdd ++ PTables),
- dialyzer_callgraph:put_named_tables(
- NamesToAdd ++ NTables, Callgraph));
- _Other ->
- Callgraph
- end.
-
-cleanup_clause_code(#curr_fun{mfa = CurrFun} = CurrTuple, Code,
- NestingLevel, LocalNestingLevel) ->
- case Code of
- [] -> {CurrTuple, []};
- [Head|Tail] ->
- {NewLocalNestingLevel, NewNestingLevel, NewCurrTuple, Return} =
- case Head of
- beg_case ->
- {LocalNestingLevel, NestingLevel + 1, CurrTuple, false};
- #end_case{} ->
- {LocalNestingLevel, NestingLevel - 1, CurrTuple, false};
- #end_clause{} ->
- case NestingLevel =:= 0 of
- true ->
- {LocalNestingLevel, NestingLevel, CurrTuple, true};
- false ->
- {LocalNestingLevel, NestingLevel, CurrTuple, false}
- end;
- #fun_call{caller = CurrFun} ->
- {LocalNestingLevel - 1, NestingLevel, CurrTuple, false};
- #curr_fun{status = in} ->
- {LocalNestingLevel - 1, NestingLevel, Head, false};
- #curr_fun{status = out} ->
- {LocalNestingLevel + 1, NestingLevel, Head, false};
- Other when Other =/= #fun_call{} ->
- {LocalNestingLevel, NestingLevel, CurrTuple, false}
- end,
- case Return of
- true -> {NewCurrTuple, Tail};
- false ->
- cleanup_clause_code(NewCurrTuple, Tail, NewNestingLevel,
- NewLocalNestingLevel)
- end
- end.
-
-cleanup_dep_calls(DepList) ->
- case DepList of
- [] -> [];
- [#dep_call{call_name = CallName, arg_types = ArgTypes,
- vars = Vars, state = State, file_loc = FileLocation}|T] ->
- [#dep_call{call_name = CallName, arg_types = ArgTypes,
- vars = Vars, state = State, file_loc = FileLocation}|
- cleanup_dep_calls(T)]
- end.
-
-cleanup_race_code(State) ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- dialyzer_dataflow:state__put_callgraph(
- dialyzer_callgraph:race_code_new(Callgraph), State).
-
-filter_named_tables(NamesList) ->
- case NamesList of
- [] -> [];
- [Head|Tail] ->
- NewHead =
- case string:find(Head, "()", trailing) of
- nomatch -> [Head];
- _Other -> []
- end,
- NewHead ++ filter_named_tables(Tail)
- end.
-
-filter_parents(Parents, NewParents, Digraph) ->
- case Parents of
- [] -> NewParents;
- [Head|Tail] ->
- NewParents1 = filter_parents_helper1(Head, Tail, NewParents, Digraph),
- filter_parents(Tail, NewParents1, Digraph)
- end.
-
-filter_parents_helper1(First, Rest, NewParents, Digraph) ->
- case Rest of
- [] -> NewParents;
- [Head|Tail] ->
- NewParents1 = filter_parents_helper2(First, Head, NewParents, Digraph),
- filter_parents_helper1(First, Tail, NewParents1, Digraph)
- end.
-
-filter_parents_helper2(Parent1, Parent2, NewParents, Digraph) ->
- case digraph:get_path(Digraph, Parent1, Parent2) of
- false ->
- case digraph:get_path(Digraph, Parent2, Parent1) of
- false -> NewParents;
- _Vertices -> NewParents -- [Parent1]
- end;
- _Vertices -> NewParents -- [Parent2]
- end.
-
-find_all_bound_vars(Label, RaceVarMap) ->
- case dict:find(Label, RaceVarMap) of
- error -> [Label];
- {ok, Labels} ->
- lists:usort(Labels ++
- find_all_bound_vars_helper(Labels, Label, RaceVarMap))
- end.
-
-find_all_bound_vars_helper(Labels, Label, RaceVarMap) ->
- case dict:size(RaceVarMap) of
- 0 -> [];
- _ ->
- case Labels of
- [] -> [];
- [Head|Tail] ->
- NewRaceVarMap = dict:erase(Label, RaceVarMap),
- find_all_bound_vars(Head, NewRaceVarMap) ++
- find_all_bound_vars_helper(Tail, Head, NewRaceVarMap)
- end
- end.
-
-fixup_all_calls(CurrFun, NextFun, NextFunLabel, Args, CodeToReplace,
- Code, RaceVarMap) ->
- case Code of
- [] -> [];
- [Head|Tail] ->
- NewCode =
- case Head of
- #fun_call{caller = CurrFun, callee = Callee,
- arg_types = FunArgTypes, vars = FunArgs}
- when Callee =:= NextFun orelse Callee =:= NextFunLabel ->
- RaceVarMap1 = race_var_map(Args, FunArgs, RaceVarMap, bind),
- [#curr_fun{status = in, mfa = NextFun, label = NextFunLabel,
- var_map = RaceVarMap1, def_vars = Args,
- call_vars = FunArgs, arg_types = FunArgTypes}|
- CodeToReplace];
- _Other -> [Head]
- end,
- RetCode =
- fixup_all_calls(CurrFun, NextFun, NextFunLabel, Args, CodeToReplace,
- Tail, RaceVarMap),
- NewCode ++ RetCode
- end.
-
-is_last_race(RaceTag, InitFun, Code, Callgraph) ->
- case Code of
- [] -> true;
- [Head|Tail] ->
- case Head of
- RaceTag -> false;
- #fun_call{callee = Fun} ->
- FunName =
- case is_integer(Fun) of
- true ->
- case dialyzer_callgraph:lookup_name(Fun, Callgraph) of
- error -> Fun;
- {ok, Name} -> Name
- end;
- false -> Fun
- end,
- Digraph = dialyzer_callgraph:get_digraph(Callgraph),
- case FunName =:= InitFun orelse
- digraph:get_path(Digraph, FunName, InitFun) of
- false -> is_last_race(RaceTag, InitFun, Tail, Callgraph);
- _Vertices -> false
- end;
- _Other -> is_last_race(RaceTag, InitFun, Tail, Callgraph)
- end
- end.
-
-lists_key_member(Member, List, N) when is_integer(Member) ->
- case List of
- [] -> 0;
- [Head|Tail] ->
- NewN = N + 1,
- case Head of
- Member -> NewN;
- _Other -> lists_key_member(Member, Tail, NewN)
- end
- end;
-lists_key_member(_M, _L, _N) ->
- 0.
-
-lists_key_member_lists(MemberList, List) ->
- case MemberList of
- [] -> 0;
- [Head|Tail] ->
- case lists_key_member(Head, List, 0) of
- 0 -> lists_key_member_lists(Tail, List);
- Other -> Other
- end
- end.
-
-lists_key_members_lists(MemberList, List) ->
- case MemberList of
- [] -> [];
- [Head|Tail] ->
- lists:usort(
- lists_key_members_lists_helper(Head, List, 1) ++
- lists_key_members_lists(Tail, List))
- end.
-
-lists_key_members_lists_helper(Elem, List, N) when is_integer(Elem) ->
- case List of
- [] -> [];
- [Head|Tail] ->
- NewHead =
- case Head =:= Elem of
- true -> [N];
- false -> []
- end,
- NewHead ++ lists_key_members_lists_helper(Elem, Tail, N + 1)
- end;
-lists_key_members_lists_helper(_Elem, _List, _N) ->
- [0].
-
-lists_key_replace(N, List, NewMember) ->
- {Before, [_|After]} = lists:split(N - 1, List),
- Before ++ [NewMember|After].
-
-lists_get(0, _List) -> ?no_label;
-lists_get(N, List) -> lists:nth(N, List).
-
-refine_race(RaceCall, WarnVarArgs, RaceWarnTag, DependencyList, RaceVarMap) ->
- case RaceWarnTag of
- WarnWhereis when WarnWhereis =:= ?WARN_WHEREIS_REGISTER orelse
- WarnWhereis =:= ?WARN_WHEREIS_UNREGISTER ->
- case RaceCall of
- #dep_call{call_name = ets_lookup} ->
- DependencyList;
- #dep_call{call_name = mnesia_dirty_read} ->
- DependencyList;
- #dep_call{call_name = whereis, args = VarArgs} ->
- refine_race_helper(RaceCall, VarArgs, WarnVarArgs, RaceWarnTag,
- DependencyList, RaceVarMap)
- end;
- ?WARN_ETS_LOOKUP_INSERT ->
- case RaceCall of
- #dep_call{call_name = whereis} ->
- DependencyList;
- #dep_call{call_name = mnesia_dirty_read} ->
- DependencyList;
- #dep_call{call_name = ets_lookup, args = VarArgs} ->
- refine_race_helper(RaceCall, VarArgs, WarnVarArgs, RaceWarnTag,
- DependencyList, RaceVarMap)
- end;
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- case RaceCall of
- #dep_call{call_name = whereis} ->
- DependencyList;
- #dep_call{call_name = ets_lookup} ->
- DependencyList;
- #dep_call{call_name = mnesia_dirty_read, args = VarArgs} ->
- refine_race_helper(RaceCall, VarArgs, WarnVarArgs, RaceWarnTag,
- DependencyList, RaceVarMap)
- end
- end.
-
-refine_race_helper(RaceCall, VarArgs, WarnVarArgs, RaceWarnTag, DependencyList,
- RaceVarMap) ->
- case compare_types(VarArgs, WarnVarArgs, RaceWarnTag, RaceVarMap) of
- true -> [RaceCall|DependencyList];
- false -> DependencyList
- end.
-
-remove_clause(RaceList, CurrTuple, Code, NestingLevel) ->
- NewRaceList = fixup_case_rest_paths(RaceList, 0),
- {NewCurrTuple, NewCode} =
- cleanup_clause_code(CurrTuple, Code, 0, NestingLevel),
- ReturnTuple = {NewRaceList, NewCurrTuple, NewCode, NestingLevel},
- case NewRaceList of
- [beg_case|RTail] ->
- case NewCode of
- [#end_case{}|CTail] ->
- remove_clause(RTail, NewCurrTuple, CTail, NestingLevel);
- _Other -> ReturnTuple
- end;
- _Else -> ReturnTuple
- end.
-
-remove_nonlocal_functions(Code, NestingLevel) ->
- case Code of
- [] -> [];
- [H|T] ->
- NewNL =
- case H of
- #curr_fun{status = in} ->
- NestingLevel + 1;
- #curr_fun{status = out} ->
- NestingLevel - 1;
- _Other ->
- NestingLevel
- end,
- case NewNL =:= 0 of
- true -> T;
- false -> remove_nonlocal_functions(T, NewNL)
- end
- end.
-
-renew_curr_fun(CurrFun, Races) ->
- Races#races{curr_fun = CurrFun}.
-
-renew_curr_fun_label(CurrFunLabel, Races) ->
- Races#races{curr_fun_label = CurrFunLabel}.
-
-renew_race_list(RaceList, Races) ->
- Races#races{race_list = RaceList}.
-
-renew_race_list_size(RaceListSize, Races) ->
- Races#races{race_list_size = RaceListSize}.
-
-renew_race_tags(RaceTags, Races) ->
- Races#races{race_tags = RaceTags}.
-
-renew_table(Table, Races) ->
- Races#races{new_table = Table}.
-
-state__renew_curr_fun(CurrFun, State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- dialyzer_dataflow:state__put_races(renew_curr_fun(CurrFun, Races), State).
-
-state__renew_curr_fun_label(CurrFunLabel, State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- dialyzer_dataflow:state__put_races(
- renew_curr_fun_label(CurrFunLabel, Races), State).
-
-state__renew_race_list(RaceList, State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- dialyzer_dataflow:state__put_races(renew_race_list(RaceList, Races), State).
-
-state__renew_race_tags(RaceTags, State) ->
- Races = dialyzer_dataflow:state__get_races(State),
- dialyzer_dataflow:state__put_races(renew_race_tags(RaceTags, Races), State).
-
-state__renew_info(RaceList, RaceListSize, RaceTags, Table, State) ->
- Callgraph = dialyzer_dataflow:state__get_callgraph(State),
- Races = dialyzer_dataflow:state__get_races(State),
- dialyzer_dataflow:state__put_callgraph(
- callgraph__renew_tables(Table, Callgraph),
- dialyzer_dataflow:state__put_races(
- renew_table(Table,
- renew_race_list(RaceList,
- renew_race_list_size(RaceListSize,
- renew_race_tags(RaceTags, Races)))), State)).
-
-%%% ===========================================================================
-%%%
-%%% Variable and Type Utilities
-%%%
-%%% ===========================================================================
-
-any_args(StrList) ->
- case StrList of
- [] -> false;
- [Head|Tail] ->
- case string:find(Head, "()", trailing) of
- nomatch -> any_args(Tail);
- _Other -> true
- end
- end.
-
--spec bind_dict_vars(label(), label(), dict:dict()) -> dict:dict().
-
-bind_dict_vars(Key, Label, RaceVarMap) ->
- case Key =:= Label of
- true -> RaceVarMap;
- false ->
- case dict:find(Key, RaceVarMap) of
- error -> dict:store(Key, [Label], RaceVarMap);
- {ok, Labels} ->
- case lists:member(Label, Labels) of
- true -> RaceVarMap;
- false -> dict:store(Key, [Label|Labels], RaceVarMap)
- end
- end
- end.
-
-bind_dict_vars_list(Key, Labels, RaceVarMap) ->
- case Labels of
- [] -> RaceVarMap;
- [Head|Tail] ->
- bind_dict_vars_list(Key, Tail, bind_dict_vars(Key, Head, RaceVarMap))
- end.
-
-compare_ets_insert(OldWarnVarArgs, NewWarnVarArgs, RaceVarMap) ->
- [Old1, Old2, Old3, Old4] = OldWarnVarArgs,
- [New1, New2, New3, New4] = NewWarnVarArgs,
- Bool =
- case any_args(Old2) of
- true -> compare_var_list(New1, Old1, RaceVarMap);
- false ->
- case any_args(New2) of
- true -> compare_var_list(New1, Old1, RaceVarMap);
- false -> compare_var_list(New1, Old1, RaceVarMap)
- orelse (Old2 =:= New2)
- end
- end,
- case Bool of
- true ->
- case any_args(Old4) of
- true ->
- case compare_list_vars(Old3, ets_list_args(New3), [], RaceVarMap) of
- true -> true;
- Args3 -> lists_key_replace(3, OldWarnVarArgs, Args3)
- end;
- false ->
- case any_args(New4) of
- true ->
- case compare_list_vars(Old3, ets_list_args(New3), [],
- RaceVarMap) of
- true -> true;
- Args3 -> lists_key_replace(3, OldWarnVarArgs, Args3)
- end;
- false ->
- case compare_list_vars(Old3, ets_list_args(New3), [],
- RaceVarMap) of
- true -> true;
- Args3 ->
- lists_key_replace(4,
- lists_key_replace(3, OldWarnVarArgs, Args3), Old4 -- New4)
- end
- end
- end;
- false -> OldWarnVarArgs
- end.
-
-compare_first_arg(OldWarnVarArgs, NewWarnVarArgs, RaceVarMap) ->
- [Old1, Old2|_OldT] = OldWarnVarArgs,
- [New1, New2|_NewT] = NewWarnVarArgs,
- case any_args(Old2) of
- true ->
- case compare_var_list(New1, Old1, RaceVarMap) of
- true -> true;
- false -> OldWarnVarArgs
- end;
- false ->
- case any_args(New2) of
- true ->
- case compare_var_list(New1, Old1, RaceVarMap) of
- true -> true;
- false -> OldWarnVarArgs
- end;
- false ->
- case compare_var_list(New1, Old1, RaceVarMap) of
- true -> true;
- false -> lists_key_replace(2, OldWarnVarArgs, Old2 -- New2)
- end
- end
- end.
-
-compare_argtypes(ArgTypes, WarnArgTypes) ->
- lists:any(fun (X) -> lists:member(X, WarnArgTypes) end, ArgTypes).
-
-%% Compares the argument types of the two suspicious calls.
-compare_types(VarArgs, WarnVarArgs, RaceWarnTag, RaceVarMap) ->
- case RaceWarnTag of
- ?WARN_WHEREIS_REGISTER ->
- [VA1, VA2] = VarArgs,
- [WVA1, WVA2, _, _] = WarnVarArgs,
- case any_args(VA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- case any_args(WVA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- compare_var_list(VA1, WVA1, RaceVarMap) orelse
- compare_argtypes(VA2, WVA2)
- end
- end;
- ?WARN_WHEREIS_UNREGISTER ->
- [VA1, VA2] = VarArgs,
- [WVA1, WVA2] = WarnVarArgs,
- case any_args(VA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- case any_args(WVA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- compare_var_list(VA1, WVA1, RaceVarMap) orelse
- compare_argtypes(VA2, WVA2)
- end
- end;
- ?WARN_ETS_LOOKUP_INSERT ->
- [VA1, VA2, VA3, VA4] = VarArgs,
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs,
- Bool =
- case any_args(VA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- case any_args(WVA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- compare_var_list(VA1, WVA1, RaceVarMap) orelse
- compare_argtypes(VA2, WVA2)
- end
- end,
- Bool andalso
- (case any_args(VA4) of
- true ->
- compare_var_list(VA3, WVA3, RaceVarMap);
- false ->
- case any_args(WVA4) of
- true ->
- compare_var_list(VA3, WVA3, RaceVarMap);
- false ->
- compare_var_list(VA3, WVA3, RaceVarMap) orelse
- compare_argtypes(VA4, WVA4)
- end
- end);
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- [VA1, VA2|_] = VarArgs, %% Two or four elements
- [WVA1, WVA2|_] = WarnVarArgs,
- case any_args(VA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- case any_args(WVA2) of
- true -> compare_var_list(VA1, WVA1, RaceVarMap);
- false ->
- compare_var_list(VA1, WVA1, RaceVarMap) orelse
- compare_argtypes(VA2, WVA2)
- end
- end
- end.
-
-compare_list_vars(VarList1, VarList2, NewVarList1, RaceVarMap) ->
- case VarList1 of
- [] ->
- case NewVarList1 of
- [] -> true;
- _Other -> NewVarList1
- end;
- [Head|Tail] ->
- NewHead =
- case compare_var_list(Head, VarList2, RaceVarMap) of
- true -> [];
- false -> [Head]
- end,
- compare_list_vars(Tail, VarList2, NewHead ++ NewVarList1, RaceVarMap)
- end.
-
-compare_vars(Var1, Var2, RaceVarMap) when is_integer(Var1), is_integer(Var2) ->
- Var1 =:= Var2 orelse
- are_bound_labels(Var1, Var2, RaceVarMap) orelse
- are_bound_labels(Var2, Var1, RaceVarMap);
-compare_vars(_Var1, _Var2, _RaceVarMap) ->
- false.
-
--spec compare_var_list(label_type(), [label_type()], dict:dict()) -> boolean().
-
-compare_var_list(Var, VarList, RaceVarMap) ->
- lists:any(fun (V) -> compare_vars(Var, V, RaceVarMap) end, VarList).
-
-ets_list_args(MaybeList) ->
- case is_list(MaybeList) of
- true ->
- try [ets_tuple_args(T) || T <- MaybeList]
- catch _:_ -> [?no_label]
- end;
- false -> [ets_tuple_args(MaybeList)]
- end.
-
-ets_list_argtypes(ListStr) ->
- ListStr1 = string:trim(ListStr, leading, "$["),
- string:trim(ListStr1, trailing, "$]$.$,").
-
-ets_tuple_args(MaybeTuple) ->
- case is_tuple(MaybeTuple) of
- true -> element(1, MaybeTuple);
- false -> ?no_label
- end.
-
-ets_tuple_argtypes2(TupleList, ElemList) ->
- case TupleList of
- [] -> ElemList;
- [H|T] ->
- ets_tuple_argtypes2(T,
- ets_tuple_argtypes2_helper(H, [], 0) ++ ElemList)
- end.
-
-ets_tuple_argtypes2_helper(TupleStr, ElemStr, NestingLevel) ->
- case TupleStr of
- [] -> [];
- [H|T] ->
- {NewElemStr, NewNestingLevel, Return} =
- case H of
- ${ when NestingLevel =:= 0 ->
- {ElemStr, NestingLevel + 1, false};
- ${ ->
- {[H|ElemStr], NestingLevel + 1, false};
- $[ ->
- {[H|ElemStr], NestingLevel + 1, false};
- $( ->
- {[H|ElemStr], NestingLevel + 1, false};
- $} ->
- {[H|ElemStr], NestingLevel - 1, false};
- $] ->
- {[H|ElemStr], NestingLevel - 1, false};
- $) ->
- {[H|ElemStr], NestingLevel - 1, false};
- $, when NestingLevel =:= 1 ->
- {lists:reverse(ElemStr), NestingLevel, true};
- _Other ->
- {[H|ElemStr], NestingLevel, false}
- end,
- case Return of
- true -> string:lexemes(NewElemStr, " |");
- false ->
- ets_tuple_argtypes2_helper(T, NewElemStr, NewNestingLevel)
- end
- end.
-
-ets_tuple_argtypes1(Str, Tuple, TupleList, NestingLevel) ->
- case Str of
- [] -> TupleList;
- [H|T] ->
- {NewTuple, NewNestingLevel, Add} =
- case H of
- ${ ->
- {[H|Tuple], NestingLevel + 1, false};
- $} ->
- case NestingLevel of
- 1 ->
- {[H|Tuple], NestingLevel - 1, true};
- _Else ->
- {[H|Tuple], NestingLevel - 1, false}
- end;
- _Other1 when NestingLevel =:= 0 ->
- {Tuple, NestingLevel, false};
- _Other2 ->
- {[H|Tuple], NestingLevel, false}
- end,
- case Add of
- true ->
- ets_tuple_argtypes1(T, [],
- [lists:reverse(NewTuple)|TupleList],
- NewNestingLevel);
- false ->
- ets_tuple_argtypes1(T, NewTuple, TupleList, NewNestingLevel)
- end
- end.
-
-format_arg(?bypassed) -> ?no_label;
-format_arg(Arg0) ->
- Arg = cerl:fold_literal(Arg0),
- case cerl:type(Arg) of
- var -> cerl_trees:get_label(Arg);
- tuple -> list_to_tuple([format_arg(A) || A <- cerl:tuple_es(Arg)]);
- cons -> [format_arg(cerl:cons_hd(Arg))|format_arg(cerl:cons_tl(Arg))];
- alias -> format_arg(cerl:alias_var(Arg));
- literal ->
- case cerl:is_c_nil(Arg) of
- true -> [];
- false -> ?no_label
- end;
- _Other -> ?no_label
- end.
-
--spec format_args([core_vars()], [erl_types:erl_type()],
- dialyzer_dataflow:state(), call()) ->
- args().
-
-format_args([], [], _State, _Call) ->
- [];
-format_args(ArgList, TypeList, CleanState, Call) ->
- format_args_2(format_args_1(ArgList, TypeList, CleanState), Call).
-
-format_args_1([Arg], [Type], CleanState) ->
- [format_arg(Arg), format_type(Type, CleanState)];
-format_args_1([Arg|Args], [Type|Types], CleanState) ->
- List =
- case Arg =:= ?bypassed of
- true -> [?no_label, format_type(Type, CleanState)];
- false ->
- case cerl:is_literal(cerl:fold_literal(Arg)) of
- true -> [?no_label, format_cerl(Arg)];
- false -> [format_arg(Arg), format_type(Type, CleanState)]
- end
- end,
- List ++ format_args_1(Args, Types, CleanState).
-
-format_args_2(StrArgList, Call) ->
- case Call of
- whereis ->
- lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |"));
- register ->
- lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |"));
- unregister ->
- lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |"));
- ets_new ->
- StrArgList1 = lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |")),
- lists_key_replace(4, StrArgList1,
- string:lexemes(ets_list_argtypes(lists:nth(4, StrArgList1)), " |"));
- ets_lookup ->
- StrArgList1 = lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |")),
- lists_key_replace(4, StrArgList1,
- string:lexemes(lists:nth(4, StrArgList1), " |"));
- ets_insert ->
- StrArgList1 = lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |")),
- lists_key_replace(4, StrArgList1,
- ets_tuple_argtypes2(
- ets_tuple_argtypes1(lists:nth(4, StrArgList1), [], [], 0),
- []));
- mnesia_dirty_read1 ->
- lists_key_replace(2, StrArgList,
- [mnesia_tuple_argtypes(T) || T <- string:lexemes(
- lists:nth(2, StrArgList), " |")]);
- mnesia_dirty_read2 ->
- lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |"));
- mnesia_dirty_write1 ->
- lists_key_replace(2, StrArgList,
- [mnesia_record_tab(R) || R <- string:lexemes(
- lists:nth(2, StrArgList), " |")]);
- mnesia_dirty_write2 ->
- lists_key_replace(2, StrArgList,
- string:lexemes(lists:nth(2, StrArgList), " |"));
- function_call -> StrArgList
- end.
-
-format_cerl(Tree) ->
- cerl_prettypr:format(cerl:set_ann(Tree, []),
- [{hook, dialyzer_utils:pp_hook()},
- {noann, true},
- {paper, 100000},
- {ribbon, 100000}
- ]).
-
-format_type(Type, State) ->
- R = dialyzer_dataflow:state__get_records(State),
- erl_types:t_to_string(Type, R).
-
-mnesia_record_tab(RecordStr) ->
- case erl_scan:string(RecordStr) of
- {ok, [{'#', _}, {atom, _, Name}|_], _} ->
- io_lib:write_string(atom_to_list(Name), $');
- _ -> RecordStr
- end.
-
-mnesia_tuple_argtypes(TupleStr) ->
- TupleStr1 = string:trim(TupleStr, leading, "${"),
- [TupleStr2|_T] = string:lexemes(TupleStr1, " ,"),
- lists:flatten(string:lexemes(TupleStr2, " |")).
-
--spec race_var_map(var_to_map1(), var_to_map2(), dict:dict(), op()) ->
- dict:dict().
-
-race_var_map(Vars1, Vars2, RaceVarMap, Op) ->
- case Vars1 =:= ?no_arg orelse Vars1 =:= ?bypassed
- orelse Vars2 =:= ?bypassed of
- true -> RaceVarMap;
- false ->
- case is_list(Vars1) andalso is_list(Vars2) of
- true ->
- case Vars1 of
- [] -> RaceVarMap;
- [AHead|ATail] ->
- case Vars2 of
- [] -> RaceVarMap;
- [PHead|PTail] ->
- NewRaceVarMap = race_var_map(AHead, PHead, RaceVarMap, Op),
- race_var_map(ATail, PTail, NewRaceVarMap, Op)
- end
- end;
- false ->
- {NewVars1, NewVars2, Bool} =
- case is_list(Vars1) of
- true ->
- case Vars1 of
- [Var1] -> {Var1, Vars2, true};
- _Thing -> {Vars1, Vars2, false}
- end;
- false ->
- case is_list(Vars2) of
- true ->
- case Vars2 of
- [Var2] -> {Vars1, Var2, true};
- _Thing -> {Vars1, Vars2, false}
- end;
- false -> {Vars1, Vars2, true}
- end
- end,
- case Bool of
- true ->
- case cerl:type(NewVars1) of
- var ->
- case cerl:type(NewVars2) of
- var ->
- ALabel = cerl_trees:get_label(NewVars1),
- PLabel = cerl_trees:get_label(NewVars2),
- case Op of
- bind ->
- TempRaceVarMap =
- bind_dict_vars(ALabel, PLabel, RaceVarMap),
- bind_dict_vars(PLabel, ALabel, TempRaceVarMap);
- unbind ->
- TempRaceVarMap =
- unbind_dict_vars(ALabel, PLabel, RaceVarMap),
- unbind_dict_vars(PLabel, ALabel, TempRaceVarMap)
- end;
- alias ->
- race_var_map(NewVars1, cerl:alias_var(NewVars2),
- RaceVarMap, Op);
- values ->
- race_var_map(NewVars1, cerl:values_es(NewVars2),
- RaceVarMap, Op);
- _Other -> RaceVarMap
- end;
- tuple ->
- case cerl:type(NewVars2) of
- tuple ->
- race_var_map(cerl:tuple_es(NewVars1),
- cerl:tuple_es(NewVars2), RaceVarMap, Op);
- alias ->
- race_var_map(NewVars1, cerl:alias_var(NewVars2),
- RaceVarMap, Op);
- values ->
- race_var_map(NewVars1, cerl:values_es(NewVars2),
- RaceVarMap, Op);
- _Other -> RaceVarMap
- end;
- cons ->
- case cerl:type(NewVars2) of
- cons ->
- NewRaceVarMap = race_var_map(cerl:cons_hd(NewVars1),
- cerl:cons_hd(NewVars2), RaceVarMap, Op),
- race_var_map(cerl:cons_tl(NewVars1),
- cerl:cons_tl(NewVars2), NewRaceVarMap, Op);
- alias ->
- race_var_map(NewVars1, cerl:alias_var(NewVars2),
- RaceVarMap, Op);
- values ->
- race_var_map(NewVars1, cerl:values_es(NewVars2),
- RaceVarMap, Op);
- _Other -> RaceVarMap
- end;
- alias ->
- case cerl:type(NewVars2) of
- alias ->
- race_var_map(cerl:alias_var(NewVars1),
- cerl:alias_var(NewVars2), RaceVarMap, Op);
- _Other ->
- race_var_map(cerl:alias_var(NewVars1),
- NewVars2, RaceVarMap, Op)
- end;
- values ->
- case cerl:type(NewVars2) of
- values ->
- race_var_map(cerl:values_es(NewVars1),
- cerl:values_es(NewVars2), RaceVarMap, Op);
- _Other ->
- race_var_map(cerl:values_es(NewVars1),
- NewVars2, RaceVarMap, Op)
- end;
- _Other -> RaceVarMap
- end;
- false -> RaceVarMap
- end
- end
- end.
-
-race_var_map_clauses(Clauses, RaceVarMap) ->
- case Clauses of
- [] -> RaceVarMap;
- [#end_clause{arg = Arg, pats = Pats, guard = Guard}|T] ->
- {RaceVarMap1, _RemoveClause} =
- race_var_map_guard(Arg, Pats, Guard, RaceVarMap, bind),
- race_var_map_clauses(T, RaceVarMap1)
- end.
-
-race_var_map_guard(Arg, Pats, Guard, RaceVarMap, Op) ->
- {NewRaceVarMap, RemoveClause} =
- case cerl:type(Guard) of
- call ->
- CallName = cerl:call_name(Guard),
- case cerl:is_literal(CallName) of
- true ->
- case cerl:concrete(CallName) of
- '=:=' ->
- [Arg1, Arg2] = cerl:call_args(Guard),
- {race_var_map(Arg1, Arg2, RaceVarMap, Op), false};
- '==' ->
- [Arg1, Arg2] = cerl:call_args(Guard),
- {race_var_map(Arg1, Arg2, RaceVarMap, Op), false};
- '=/=' ->
- case Op of
- bind ->
- [Arg1, Arg2] = cerl:call_args(Guard),
- {RaceVarMap, are_bound_vars(Arg1, Arg2, RaceVarMap)};
- unbind -> {RaceVarMap, false}
- end;
- _Other -> {RaceVarMap, false}
- end;
- false -> {RaceVarMap, false}
- end;
- _Other -> {RaceVarMap, false}
- end,
- {RaceVarMap1, RemoveClause1} =
- race_var_map_guard_helper1(Arg, Pats,
- race_var_map(Arg, Pats, NewRaceVarMap, Op), Op),
- {RaceVarMap1, RemoveClause orelse RemoveClause1}.
-
-race_var_map_guard_helper1(Arg, Pats, RaceVarMap, Op) ->
- case Arg =:= ?no_arg orelse Arg =:= ?bypassed of
- true -> {RaceVarMap, false};
- false ->
- case cerl:type(Arg) of
- call ->
- case Pats of
- [NewPat] ->
- ModName = cerl:call_module(Arg),
- CallName = cerl:call_name(Arg),
- case cerl:is_literal(ModName) andalso
- cerl:is_literal(CallName) of
- true ->
- case {cerl:concrete(ModName),
- cerl:concrete(CallName)} of
- {erlang, '=:='} ->
- race_var_map_guard_helper2(Arg, NewPat, true,
- RaceVarMap, Op);
- {erlang, '=='} ->
- race_var_map_guard_helper2(Arg, NewPat, true,
- RaceVarMap, Op);
- {erlang, '=/='} ->
- race_var_map_guard_helper2(Arg, NewPat, false,
- RaceVarMap, Op);
- _Else -> {RaceVarMap, false}
- end;
- false -> {RaceVarMap, false}
- end;
- _Other -> {RaceVarMap, false}
- end;
- _Other -> {RaceVarMap, false}
- end
- end.
-
-race_var_map_guard_helper2(Arg, Pat0, Bool, RaceVarMap, Op) ->
- Pat = cerl:fold_literal(Pat0),
- case cerl:type(Pat) of
- literal ->
- [Arg1, Arg2] = cerl:call_args(Arg),
- case cerl:concrete(Pat) of
- Bool ->
- {race_var_map(Arg1, Arg2, RaceVarMap, Op), false};
- _Else ->
- case Op of
- bind ->
- {RaceVarMap, are_bound_vars(Arg1, Arg2, RaceVarMap)};
- unbind -> {RaceVarMap, false}
- end
- end;
- _Else -> {RaceVarMap, false}
- end.
-
-unbind_dict_vars(Var, Var, RaceVarMap) ->
- RaceVarMap;
-unbind_dict_vars(Var1, Var2, RaceVarMap) ->
- case dict:find(Var1, RaceVarMap) of
- error -> RaceVarMap;
- {ok, Labels} ->
- case Labels of
- [] -> dict:erase(Var1, RaceVarMap);
- _Else ->
- case lists:member(Var2, Labels) of
- true ->
- unbind_dict_vars(Var1, Var2,
- bind_dict_vars_list(Var1, Labels -- [Var2],
- dict:erase(Var1, RaceVarMap)));
- false ->
- unbind_dict_vars_helper(Labels, Var1, Var2, RaceVarMap)
- end
- end
- end.
-
-unbind_dict_vars_helper(Labels, Key, CompLabel, RaceVarMap) ->
- case dict:size(RaceVarMap) of
- 0 -> RaceVarMap;
- _ ->
- case Labels of
- [] -> RaceVarMap;
- [Head|Tail] ->
- NewRaceVarMap =
- case are_bound_labels(Head, CompLabel, RaceVarMap) orelse
- are_bound_labels(CompLabel, Head, RaceVarMap) of
- true ->
- bind_dict_vars_list(Key, Labels -- [Head],
- dict:erase(Key, RaceVarMap));
- false -> RaceVarMap
- end,
- unbind_dict_vars_helper(Tail, Key, CompLabel, NewRaceVarMap)
- end
- end.
-
-var_analysis(FunDefArgs, FunCallArgs, WarnVarArgs, RaceWarnTag) ->
- case RaceWarnTag of
- ?WARN_WHEREIS_REGISTER ->
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs,
- ArgNos = lists_key_members_lists(WVA1, FunDefArgs),
- [[lists_get(N, FunCallArgs) || N <- ArgNos], WVA2, WVA3, WVA4];
- ?WARN_WHEREIS_UNREGISTER ->
- [WVA1, WVA2] = WarnVarArgs,
- ArgNos = lists_key_members_lists(WVA1, FunDefArgs),
- [[lists_get(N, FunCallArgs) || N <- ArgNos], WVA2];
- ?WARN_ETS_LOOKUP_INSERT ->
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs,
- ArgNos1 = lists_key_members_lists(WVA1, FunDefArgs),
- ArgNos2 = lists_key_members_lists(WVA3, FunDefArgs),
- [[lists_get(N1, FunCallArgs) || N1 <- ArgNos1], WVA2,
- [lists_get(N2, FunCallArgs) || N2 <- ArgNos2], WVA4];
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- [WVA1, WVA2|T] = WarnVarArgs,
- ArgNos = lists_key_members_lists(WVA1, FunDefArgs),
- [[lists_get(N, FunCallArgs) || N <- ArgNos], WVA2|T]
- end.
-
-var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag,
- RaceVarMap, CleanState) ->
- FunVarArgs = format_args(FunDefArgs, FunCallTypes, CleanState, function_call),
- case RaceWarnTag of
- ?WARN_WHEREIS_REGISTER ->
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs,
- Vars = find_all_bound_vars(WVA1, RaceVarMap),
- case lists_key_member_lists(Vars, FunVarArgs) of
- 0 -> [Vars, WVA2, WVA3, WVA4];
- N when is_integer(N) ->
- NewWVA2 = string:lexemes(lists:nth(N + 1, FunVarArgs), " |"),
- [Vars, NewWVA2, WVA3, WVA4]
- end;
- ?WARN_WHEREIS_UNREGISTER ->
- [WVA1, WVA2] = WarnVarArgs,
- Vars = find_all_bound_vars(WVA1, RaceVarMap),
- case lists_key_member_lists(Vars, FunVarArgs) of
- 0 -> [Vars, WVA2];
- N when is_integer(N) ->
- NewWVA2 = string:lexemes(lists:nth(N + 1, FunVarArgs), " |"),
- [Vars, NewWVA2]
- end;
- ?WARN_ETS_LOOKUP_INSERT ->
- [WVA1, WVA2, WVA3, WVA4] = WarnVarArgs,
- Vars1 = find_all_bound_vars(WVA1, RaceVarMap),
- FirstVarArg =
- case lists_key_member_lists(Vars1, FunVarArgs) of
- 0 -> [Vars1, WVA2];
- N1 when is_integer(N1) ->
- NewWVA2 = string:lexemes(lists:nth(N1 + 1, FunVarArgs), " |"),
- [Vars1, NewWVA2]
- end,
- Vars2 =
- lists:flatten(
- [find_all_bound_vars(A, RaceVarMap) || A <- ets_list_args(WVA3)]),
- case lists_key_member_lists(Vars2, FunVarArgs) of
- 0 -> FirstVarArg ++ [Vars2, WVA4];
- N2 when is_integer(N2) ->
- NewWVA4 =
- ets_tuple_argtypes2(
- ets_tuple_argtypes1(lists:nth(N2 + 1, FunVarArgs), [], [], 0),
- []),
- FirstVarArg ++ [Vars2, NewWVA4]
-
- end;
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- [WVA1, WVA2|T] = WarnVarArgs,
- Arity =
- case T of
- [] -> 1;
- _Else -> 2
- end,
- Vars = find_all_bound_vars(WVA1, RaceVarMap),
- case lists_key_member_lists(Vars, FunVarArgs) of
- 0 -> [Vars, WVA2|T];
- N when is_integer(N) ->
- NewWVA2 =
- case Arity of
- 1 ->
- [mnesia_record_tab(R) || R <- string:lexemes(
- lists:nth(2, FunVarArgs), " |")];
- 2 ->
- string:lexemes(lists:nth(N + 1, FunVarArgs), " |")
- end,
- [Vars, NewWVA2|T]
- end
- end.
-
-%%% ===========================================================================
-%%%
-%%% Warning Format Utilities
-%%%
-%%% ===========================================================================
-
-add_race_warning(Warn, #races{race_warnings = Warns} = Races) ->
- Races#races{race_warnings = [Warn|Warns]}.
-
-get_race_warn(Fun, Args, ArgTypes, DepList, State) ->
- {M, F, _A} = Fun,
- case DepList of
- [] -> {State, no_race};
- _Other ->
- {State, {race_condition, [M, F, Args, ArgTypes, State, DepList]}}
- end.
-
--spec get_race_warnings(races(), dialyzer_dataflow:state()) ->
- {races(), dialyzer_dataflow:state()}.
-
-get_race_warnings(#races{race_warnings = RaceWarnings}, State) ->
- get_race_warnings_helper(RaceWarnings, State).
-
-get_race_warnings_helper(Warnings, State) ->
- case Warnings of
- [] ->
- {dialyzer_dataflow:state__get_races(State), State};
- [H|T] ->
- {RaceWarnTag, WarningInfo, {race_condition, [M, F, A, AT, S, DepList]}} = H,
- Reason =
- case RaceWarnTag of
- ?WARN_WHEREIS_REGISTER ->
- get_reason(lists:keysort(7, DepList),
- "might fail due to a possible race condition "
- "caused by its combination with ");
- ?WARN_WHEREIS_UNREGISTER ->
- get_reason(lists:keysort(7, DepList),
- "might fail due to a possible race condition "
- "caused by its combination with ");
- ?WARN_ETS_LOOKUP_INSERT ->
- get_reason(lists:keysort(7, DepList),
- "might have an unintended effect due to " ++
- "a possible race condition " ++
- "caused by its combination with ");
- ?WARN_MNESIA_DIRTY_READ_WRITE ->
- get_reason(lists:keysort(7, DepList),
- "might have an unintended effect due to " ++
- "a possible race condition " ++
- "caused by its combination with ")
- end,
- W =
- {?WARN_RACE_CONDITION, WarningInfo,
- {race_condition,
- [M, F, dialyzer_dataflow:format_args(A, AT, S), Reason]}},
- get_race_warnings_helper(T,
- dialyzer_dataflow:state__add_warning(W, State))
- end.
-
-get_reason(DependencyList, Reason) ->
- case DependencyList of
- [] -> "";
- [#dep_call{call_name = Call, arg_types = ArgTypes, vars = Args,
- state = State, file_loc = {File, Location}}|T] ->
- R =
- Reason ++
- case Call of
- whereis -> "the erlang:whereis";
- ets_lookup -> "the ets:lookup";
- mnesia_dirty_read -> "the mnesia:dirty_read"
- end ++
- dialyzer_dataflow:format_args(Args, ArgTypes, State) ++
- " call in " ++
- filename:basename(File) ++
- " on line " ++
- lists:flatten(io_lib:write(Location)),
- case T of
- [] -> R;
- _ -> get_reason(T, R ++ ", ")
- end
- end.
-
-state__add_race_warning(State, RaceWarn, RaceWarnTag, WarningInfo) ->
- case RaceWarn of
- no_race -> State;
- _Else ->
- Races = dialyzer_dataflow:state__get_races(State),
- Warn = {RaceWarnTag, WarningInfo, RaceWarn},
- dialyzer_dataflow:state__put_races(add_race_warning(Warn, Races), State)
- end.
-
-%%% ===========================================================================
-%%%
-%%% Record Interfaces
-%%%
-%%% ===========================================================================
-
--spec beg_clause_new(var_to_map1(), var_to_map1(), cerl:cerl()) ->
- #beg_clause{}.
-
-beg_clause_new(Arg, Pats, Guard) ->
- #beg_clause{arg = Arg, pats = Pats, guard = Guard}.
-
--spec cleanup(races()) -> races().
-
-cleanup(#races{race_list = RaceList}) ->
- #races{race_list = RaceList}.
-
--spec end_case_new([#end_clause{}]) -> #end_case{}.
-
-end_case_new(Clauses) ->
- #end_case{clauses = Clauses}.
-
--spec end_clause_new(var_to_map1(), var_to_map1(), cerl:cerl()) ->
- #end_clause{}.
-
-end_clause_new(Arg, Pats, Guard) ->
- #end_clause{arg = Arg, pats = Pats, guard = Guard}.
-
--spec get_curr_fun(races()) -> dialyzer_callgraph:mfa_or_funlbl().
-
-get_curr_fun(#races{curr_fun = CurrFun}) ->
- CurrFun.
-
--spec get_curr_fun_args(races()) -> core_args().
-
-get_curr_fun_args(#races{curr_fun_args = CurrFunArgs}) ->
- CurrFunArgs.
-
--spec get_new_table(races()) -> table().
-
-get_new_table(#races{new_table = Table}) ->
- Table.
-
--spec get_race_analysis(races()) -> boolean().
-
-get_race_analysis(#races{race_analysis = RaceAnalysis}) ->
- RaceAnalysis.
-
--spec get_race_list(races()) -> code().
-
-get_race_list(#races{race_list = RaceList}) ->
- RaceList.
-
--spec get_race_list_size(races()) -> non_neg_integer().
-
-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) ->
- #let_tag{var = Var, arg = Arg}.
-
--spec new() -> races().
-
-new() -> #races{}.
-
--spec put_curr_fun(dialyzer_callgraph:mfa_or_funlbl(), label(), races()) ->
- races().
-
-put_curr_fun(CurrFun, CurrFunLabel, Races) ->
- Races#races{curr_fun = CurrFun,
- curr_fun_label = CurrFunLabel,
- curr_fun_args = empty}.
-
--spec put_fun_args(core_args(), races()) -> races().
-
-put_fun_args(Args, #races{curr_fun_args = CurrFunArgs} = Races) ->
- case CurrFunArgs of
- empty -> Races#races{curr_fun_args = Args};
- _Other -> Races
- end.
-
--spec put_race_analysis(boolean(), races()) ->
- races().
-
-put_race_analysis(Analysis, Races) ->
- Races#races{race_analysis = Analysis}.
-
--spec put_race_list(code(), non_neg_integer(), races()) ->
- races().
-
-put_race_list(RaceList, RaceListSize, Races) ->
- Races#races{race_list = RaceList, race_list_size = RaceListSize}.
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index c53ea15ae1..248f78a43f 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -11,28 +11,25 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
+%%
+%% Original author: Tobias Lindahl <tobiasl@it.uu.se>
+%%
+%% Purpose: Orchestrate calculation of success typings.
+%%
-%%%-------------------------------------------------------------------
-%%% File : dialyzer_succ_typings.erl
-%%% Author : Tobias Lindahl <tobiasl@it.uu.se>
-%%% Description :
-%%%
-%%% Created : 11 Sep 2006 by Tobias Lindahl <tobiasl@it.uu.se>
-%%%-------------------------------------------------------------------
-module(dialyzer_succ_typings).
--export([analyze_callgraph/3,
- analyze_callgraph/6,
- get_warnings/7
+%% Main entry points.
+-export([analyze_callgraph/5,
+ get_warnings/6
]).
--export([
- find_succ_types_for_scc/2,
+%% Entry points for dialyzer_worker.
+-export([find_succ_types_for_scc/2,
refine_one_module/2,
- %% find_required_by/2,
+ add_to_result/3,
find_depends_on/2,
- collect_warnings/2,
- lookup_names/2
+ collect_warnings/2
]).
-export_type([typesig_init_data/0, dataflow_init_data/0, warnings_init_data/0]).
@@ -54,7 +51,6 @@
%%--------------------------------------------------------------------
%% 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().
@@ -65,80 +61,33 @@
-record(st, {callgraph :: dialyzer_callgraph:callgraph(),
codeserver :: dialyzer_codeserver:codeserver(),
- parent = none :: parent(),
timing_server :: dialyzer_timing:timing_server(),
solvers :: [solver()],
plt :: dialyzer_plt:plt()}).
-%%--------------------------------------------------------------------
-
--spec analyze_callgraph(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
- dialyzer_codeserver:codeserver()) ->
- dialyzer_plt:plt().
-
-analyze_callgraph(Callgraph, Plt, Codeserver) ->
- analyze_callgraph(Callgraph, Plt, Codeserver, none, [], none).
+%% --------------------------------------------------------------------
+%% The main entry points.
-spec analyze_callgraph(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
dialyzer_codeserver:codeserver(),
dialyzer_timing:timing_server(),
- [solver()], parent()) ->
+ [solver()]) ->
dialyzer_plt:plt().
-analyze_callgraph(Callgraph, Plt, Codeserver, TimingServer, Solvers, Parent) ->
- NewState =
- init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
- TimingServer, Solvers, Parent),
- NewState#st.plt.
-
-%%--------------------------------------------------------------------
-
-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 = 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} ->
- {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, NotFixpoint2, State2} ->
- %% Need to reset the callgraph.
- {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.
+analyze_callgraph(Callgraph, Plt, Codeserver, TimingServer, Solvers) ->
+ _ = get_success_typings(Callgraph, Plt, Codeserver, TimingServer, Solvers),
+ Plt.
-spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
doc_plt(), dialyzer_codeserver:codeserver(),
- dialyzer_timing:timing_server(), [solver()], pid()) ->
+ dialyzer_timing:timing_server(), [solver()]) ->
{[raw_warning()], dialyzer_plt:plt(), doc_plt()}.
get_warnings(Callgraph, Plt, DocPlt, Codeserver,
- TimingServer, Solvers, Parent) ->
- InitState =
- init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
- TimingServer, Solvers, Parent),
+ TimingServer, Solvers) ->
+ InitState = get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Solvers),
Mods = dialyzer_callgraph:modules(InitState#st.callgraph),
- Plt = InitState#st.plt,
CWarns =
dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver, Plt),
ModWarns =
@@ -148,18 +97,89 @@ get_warnings(Callgraph, Plt, DocPlt, Codeserver,
Plt,
DocPlt}.
-get_warnings_from_modules(Mods, State, DocPlt) ->
- #st{callgraph = Callgraph, codeserver = Codeserver,
- plt = Plt, timing_server = TimingServer} = State,
- Init = {Codeserver, Callgraph, Plt, DocPlt},
- dialyzer_coordinator:parallel_job(warnings, Mods, Init, TimingServer).
+%% --------------------------------------------------------------------
+%% Callback functions called from dialyzer_worker.
+
+-spec find_succ_types_for_scc(scc(), typesig_init_data()) -> [mfa_or_funlbl()].
+
+find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) ->
+ SCC = [MFA || {_, _, _} = MFA <- SCC0],
+ Label = dialyzer_codeserver:get_next_core_label(Codeserver),
+ F = fun(MFA) ->
+ {_Var, Fun} = dialyzer_codeserver:lookup_mfa_code(MFA, Codeserver),
+ collect_fun_info(Fun)
+ end,
+ AllFuns = lists:flatmap(F, SCC),
+ PropTypes = get_fun_types_from_plt(AllFuns, Callgraph, Plt),
+
+ %% Assume that the PLT contains the current propagated types
+ FunTypes = dialyzer_typesig:analyze_scc(SCC, Label, Callgraph,
+ Codeserver, Plt, PropTypes,
+ Solvers),
+
+ %% FunTypes may now have picked up funs outside of the SCC. Get rid of them.
+ AllFunKeys = [X || {X, _} <- AllFuns],
+ Set = sofs:set(AllFunKeys, [id]),
+ BinRel = sofs:from_external(FunTypes, [{id,type}]), %Already sorted.
+ FilteredFunTypes = sofs:to_external(sofs:restriction(BinRel, Set)),
+
+ FunMFAContracts = get_contracts(FilteredFunTypes, Callgraph, Codeserver),
+ ModOpaques = get_module_opaques(FunMFAContracts, Codeserver),
+ DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques),
+
+ %% Check contracts
+ Contracts = orddict:from_list([{MFA, Contract} ||
+ {_, {MFA, Contract}} <- FunMFAContracts]),
+ PltContracts =
+ dialyzer_contracts:check_contracts(Contracts, Callgraph,
+ DecoratedFunTypes,
+ ModOpaques),
+ debug_pp_functions("SCC", FilteredFunTypes, DecoratedFunTypes, Callgraph),
+ NewPltContracts = [MC ||
+ {MFA, _C}=MC <- PltContracts,
+ %% Check the non-deleted PLT
+ not dialyzer_plt:is_contract(Plt, MFA)],
+ _ = insert_into_plt(DecoratedFunTypes, Callgraph, Plt),
+ _ = dialyzer_plt:insert_contract_list(Plt, NewPltContracts),
+
+ %% Check whether we have reached a fixpoint.
+ case NewPltContracts =:= [] andalso
+ reached_fixpoint_strict(PropTypes, DecoratedFunTypes) of
+ true -> [];
+ false ->
+ ?debug("Not fixpoint for: ~tw\n", [AllFuns]),
+ AllFunKeys
+ end.
+
+-spec refine_one_module(module(), dataflow_init_data()) -> [mfa_or_funlbl()].
+
+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, Callgraph, Plt),
+ Records = dialyzer_codeserver:lookup_mod_records(M, CodeServer),
+ NewFunTypes =
+ dialyzer_dataflow:get_fun_types(ModCode, Plt, Callgraph, CodeServer, Records),
+
+ FunMFAContracts = get_contracts(NewFunTypes, Callgraph, CodeServer),
+ ModOpaques = get_module_opaques(FunMFAContracts, CodeServer),
+ DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques),
+ debug_pp_functions("Refine", NewFunTypes, DecoratedFunTypes, Callgraph),
+
+ case updated_types(FunTypes, DecoratedFunTypes) of
+ [] -> [];
+ [_|_]=NotFixpoint ->
+ ?debug("Not fixpoint\n", []),
+ _ = insert_into_plt(NotFixpoint, Callgraph, Plt),
+ [FunLbl || {FunLbl,_Type} <- NotFixpoint]
+ end.
-spec collect_warnings(module(), warnings_init_data()) -> [raw_warning()].
collect_warnings(M, {Codeserver, Callgraph, Plt, DocPlt}) ->
ModCode = dialyzer_codeserver:lookup_mod_code(M, Codeserver),
Contracts = dialyzer_codeserver:lookup_mod_contracts(M, Codeserver),
- AllFuns = collect_fun_info([ModCode]),
+ AllFuns = collect_fun_info(ModCode),
%% Check if there are contracts for functions that do not exist
Warnings1 =
dialyzer_contracts:contracts_without_fun(Contracts, AllFuns, Callgraph),
@@ -173,6 +193,97 @@ collect_warnings(M, {Codeserver, Callgraph, Plt, DocPlt}) ->
DocPlt = insert_into_doc_plt(FunTypes, Callgraph, DocPlt),
lists:flatten([Warnings1, Warnings2, Warnings3]).
+-spec find_depends_on(scc() | module(), fixpoint_init_data()) -> [scc()].
+
+find_depends_on(SCC, {_Codeserver, Callgraph, _Plt, _Solvers}) ->
+ dialyzer_callgraph:get_depends_on(SCC, Callgraph).
+
+-spec add_to_result([label()], [mfa()], fixpoint_init_data()) -> [mfa()].
+
+add_to_result(Labels, Result, {_Codeserver, Callgraph, _Plt, _Solver}) ->
+ [lookup_name(Label, Callgraph) || Label <- Labels] ++ Result.
+
+%% --------------------------------------------------------------------
+%% Local functions.
+%% --------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Calculate success typings.
+
+get_success_typings(Callgraph, Plt, Codeserver, TimingServer, Solvers) ->
+ %% Condense the call graph to its strongly connected components (SCCs).
+ {SCCs, Callgraph1} =
+ ?timing(TimingServer, "order", dialyzer_callgraph:finalize(Callgraph)),
+ State = #st{callgraph = Callgraph1, plt = Plt,
+ codeserver = Codeserver,
+ timing_server = TimingServer, solvers = Solvers},
+ get_refined_success_typings(SCCs, State).
+
+get_refined_success_typings(SCCs, #st{callgraph = Callgraph,
+ timing_server = TimingServer} = State) ->
+ %% Find the success types for the SCCs.
+ case find_succ_typings(SCCs, State) of
+ [] ->
+ %% No new type information was discovered. We are done.
+ State;
+ NotFixpoint1 ->
+ %% New type information was discovered. Refine the type
+ %% information in each module using a dataflow analysis.
+ {ModulePostorder, ModCallgraph} =
+ ?timing(TimingServer, "order", _C1,
+ dialyzer_callgraph:module_postorder_from_funs(NotFixpoint1,
+ Callgraph)),
+ ?debug("Module postorder: ~p\n", [Modules]),
+
+ ModState = State#st{callgraph = ModCallgraph},
+ case refine_succ_typings(ModulePostorder, ModState) of
+ [] ->
+ %% No new type information was found. We are done.
+ ModState;
+ NotFixpoint2 ->
+ %% Need to reset the callgraph before repeating.
+ {NewSCCs, Callgraph2} =
+ ?timing(TimingServer, "order", _C2,
+ dialyzer_callgraph:reset_from_funs(NotFixpoint2,
+ ModCallgraph)),
+ NewState = ModState#st{callgraph = Callgraph2},
+ get_refined_success_typings(NewSCCs, NewState)
+ end
+ end.
+
+find_succ_typings(SCCs, State) ->
+ {Init, Timing} = init_pass_data(State),
+ Updated =
+ ?timing(Timing, "typesig",
+ dialyzer_coordinator:parallel_job(typesig, SCCs, Init, Timing)),
+ ?debug("==================== Typesig done ====================\n\n", []),
+ Updated.
+
+refine_succ_typings(Modules, State) ->
+ {Init, Timing} = init_pass_data(State),
+ Updated =
+ ?timing(Timing, "refine",
+ dialyzer_coordinator:parallel_job(dataflow, Modules, Init, Timing)),
+ ?debug("==================== Dataflow done ====================\n\n", []),
+ Updated.
+
+init_pass_data(#st{codeserver = Codeserver,
+ callgraph = Callgraph,
+ plt = Plt,
+ timing_server = Timing,
+ solvers = Solvers}) ->
+ Init = {Codeserver, Callgraph, Plt, Solvers},
+ {Init, Timing}.
+
+%%--------------------------------------------------------------------
+%% Produce warnings.
+
+get_warnings_from_modules(Mods, State, DocPlt) ->
+ #st{callgraph = Callgraph, codeserver = Codeserver,
+ plt = Plt, timing_server = TimingServer} = State,
+ Init = {Codeserver, Callgraph, Plt, DocPlt},
+ dialyzer_coordinator:parallel_job(warnings, Mods, Init, TimingServer).
+
postprocess_warnings(RawWarnings, Codeserver) ->
Pred =
fun({?WARN_CONTRACT_RANGE, _, _}) -> true;
@@ -210,177 +321,53 @@ postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, WarningInfo, Msg}|Rest],
W = {?WARN_CONTRACT_RANGE, WarningInfo, NewMsg},
postprocess_dataflow_warns(Rest, Codeserver, WAcc, [W|Acc])
end.
-
-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, NotFixpoint, State}
- end.
-
--spec find_depends_on(scc() | module(), fixpoint_init_data()) -> [scc()].
-
-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, Callgraph, Plt),
- Records = dialyzer_codeserver:lookup_mod_records(M, CodeServer),
- NewFunTypes =
- dialyzer_dataflow:get_fun_types(ModCode, Plt, Callgraph, CodeServer, Records),
- {FunMFAContracts, ModOpaques} =
- prepare_decoration(NewFunTypes, Callgraph, CodeServer),
- DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques),
- %% ?Debug("NewFunTypes ~tp\n ~n", [NewFunTypes]),
- %% ?debug("refine DecoratedFunTypes ~tp\n ~n", [DecoratedFunTypes]),
- debug_pp_functions("Refine", NewFunTypes, DecoratedFunTypes, Callgraph),
-
- case reached_fixpoint(FunTypes, DecoratedFunTypes) of
- true -> [];
- {false, NotFixpoint} ->
- ?debug("Not fixpoint\n", []),
- Plt = insert_into_plt(orddict:from_list(NotFixpoint), Callgraph, Plt),
- [FunLbl || {FunLbl,_Type} <- NotFixpoint]
- end.
-
-reached_fixpoint(OldTypes, NewTypes) ->
- reached_fixpoint(OldTypes, NewTypes, false).
-
-reached_fixpoint_strict(OldTypes, NewTypes) ->
- case reached_fixpoint(OldTypes, NewTypes, true) of
- true -> true;
- {false, _} -> false
- end.
+%%--------------------------------------------------------------------
+%% Helpers.
-reached_fixpoint(OldTypes0, NewTypes0, Strict) ->
- MapFun = fun({Key, Type}) ->
- case is_failed_or_not_called_fun(Type) of
- true -> {Key, failed_fun};
- false -> {Key, erl_types:t_limit(Type, ?TYPE_LIMIT)}
- end
- end,
- OldTypes = lists:map(MapFun, orddict:to_list(OldTypes0)),
- NewTypes = lists:map(MapFun, orddict:to_list(NewTypes0)),
- compare_types(OldTypes, NewTypes, Strict).
+reached_fixpoint_strict([{Key,Type1}|Types1], [{Key,Type2}|Types2]) ->
+ case is_failed_or_not_called_fun(Type2) of
+ true ->
+ reached_fixpoint_strict(Types1, Types2);
+ false ->
+ LimitedType1 = erl_types:t_limit(Type1, ?TYPE_LIMIT),
+ LimitedType2 = erl_types:t_limit(Type2, ?TYPE_LIMIT),
+ erl_types:t_is_equal(LimitedType1, LimitedType2) andalso
+ reached_fixpoint_strict(Types1, Types2)
+ end;
+reached_fixpoint_strict([{Key1,_}|Types1], [{Key2,_}|_]=Types2)
+ when Key1 < Key2 ->
+ %% The function was never called.
+ reached_fixpoint_strict(Types1, Types2);
+reached_fixpoint_strict([], []) ->
+ true.
+
+updated_types(OldTypes, NewTypes) ->
+ updated_types_1(OldTypes, NewTypes, []).
+
+updated_types_1([{Key,Type1}|Types1], [{Key,Type2}|Types2], Acc) ->
+ case is_failed_or_not_called_fun(Type2) of
+ true ->
+ updated_types_1(Types1, Types2, Acc);
+ false ->
+ LimitedType1 = erl_types:t_limit(Type1, ?TYPE_LIMIT),
+ LimitedType2 = erl_types:t_limit(Type2, ?TYPE_LIMIT),
+ case erl_types:t_is_subtype(LimitedType1, LimitedType2) of
+ true ->
+ updated_types_1(Types1, Types2, Acc);
+ false ->
+ ?debug("Failed fixpoint for ~w: ~ts =/= ~ts\n",
+ [Key, erl_types:t_to_string(Type1), erl_types:t_to_string(Type2)]),
+ updated_types_1(Types1, Types2, [{Key, Type2}|Acc])
+ end
+ end;
+updated_types_1([], [], Acc) ->
+ Acc.
is_failed_or_not_called_fun(Type) ->
erl_types:any_none([erl_types:t_fun_range(Type)|erl_types:t_fun_args(Type)]).
-compare_types(List1, List2, Strict) ->
- compare_types_1(List1, List2, Strict, []).
-
-compare_types_1([{X, _Type1}|Left1], [{X, failed_fun}|Left2],
- Strict, NotFixpoint) ->
- compare_types_1(Left1, Left2, Strict, NotFixpoint);
-compare_types_1([{X, failed_fun}|Left1], [{X, _Type2}|Left2],
- Strict, NotFixpoint) ->
- compare_types_1(Left1, Left2, Strict, NotFixpoint);
-compare_types_1([{X, Type1}|Left1], [{X, Type2}|Left2], Strict, NotFixpoint) ->
- Res = case Strict of
- true -> erl_types:t_is_equal(Type1, Type2);
- false -> erl_types:t_is_subtype(Type1, Type2)
- end,
- case Res of
- true -> compare_types_1(Left1, Left2, Strict, NotFixpoint);
- false ->
- ?debug("Failed fixpoint for ~w: ~ts =/= ~ts\n",
- [X, erl_types:t_to_string(Type1), erl_types:t_to_string(Type2)]),
- compare_types_1(Left1, Left2, Strict, [{X, Type2}|NotFixpoint])
- end;
-compare_types_1([_|Left1], List2, Strict, NotFixpoint) ->
- %% If the function was not called.
- compare_types_1(Left1, List2, Strict, NotFixpoint);
-compare_types_1([], [], _Strict, NotFixpoint) ->
- case NotFixpoint =:= [] of
- true -> true;
- false -> {false, NotFixpoint}
- 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.
-
--spec find_succ_types_for_scc(scc(), typesig_init_data()) -> [mfa_or_funlbl()].
-
-find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) ->
- SCC = [MFA || {_, _, _} = MFA <- SCC0],
- Label = dialyzer_codeserver:get_next_core_label(Codeserver),
- AllFuns = lists:append(
- [begin
- {_Var, Fun} =
- dialyzer_codeserver:lookup_mfa_code(MFA, Codeserver),
- collect_fun_info([Fun])
- end || MFA <- SCC]),
- PropTypes = get_fun_types_from_plt(AllFuns, Callgraph, Plt),
- %% Assume that the PLT contains the current propagated types
- FunTypes = dialyzer_typesig:analyze_scc(SCC, Label, Callgraph,
- Codeserver, Plt, PropTypes,
- Solvers),
- AllFunSet = sets:from_list([X || {X, _} <- AllFuns]),
- FilteredFunTypes =
- orddict:filter(fun(F, _T) -> sets:is_element(F, AllFunSet)
- end, FunTypes),
- {FunMFAContracts, ModOpaques} =
- prepare_decoration(FilteredFunTypes, Callgraph, Codeserver),
- DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques),
- %% Check contracts
- Contracts = orddict:from_list([{MFA, Contract} ||
- {_, {MFA, Contract}} <- FunMFAContracts]),
- PltContracts =
- dialyzer_contracts:check_contracts(Contracts, Callgraph,
- DecoratedFunTypes,
- ModOpaques),
- %% ?debug("FilteredFunTypes ~tp\n ~n", [FilteredFunTypes]),
- %% ?debug("SCC DecoratedFunTypes ~tp\n ~n", [DecoratedFunTypes]),
- debug_pp_functions("SCC", FilteredFunTypes, DecoratedFunTypes, Callgraph),
- NewPltContracts = [MC ||
- {MFA, _C}=MC <- PltContracts,
- %% Check the non-deleted PLT
- not dialyzer_plt:is_contract(Plt, MFA)],
- ContractFixpoint = NewPltContracts =:= [],
- Plt = insert_into_plt(DecoratedFunTypes, Callgraph, Plt),
- Plt = dialyzer_plt:insert_contract_list(Plt, NewPltContracts),
- case (ContractFixpoint andalso
- reached_fixpoint_strict(PropTypes, DecoratedFunTypes)) of
- true -> [];
- false ->
- ?debug("Not fixpoint for: ~tw\n", [AllFuns]),
- [Fun || {Fun, _Arity} <- AllFuns]
- end.
-
-prepare_decoration(FunTypes, Callgraph, Codeserver) ->
+get_contracts(FunTypes, Callgraph, Codeserver) ->
F = fun({Label, _Type}=LabelType, Acc) ->
case dialyzer_callgraph:lookup_name(Label, Callgraph) of
{ok, MFA} ->
@@ -392,24 +379,28 @@ prepare_decoration(FunTypes, Callgraph, Codeserver) ->
error -> [{LabelType, no}|Acc]
end
end,
- Contracts = lists:foldl(F, [], orddict:to_list(FunTypes)),
- ModOpaques =
- [{M, lookup_opaques(M, Codeserver)} ||
- M <- lists:usort([M || {_LabelType, {{M, _, _}, _Con}} <- Contracts])],
- {Contracts, orddict:from_list(ModOpaques)}.
+ lists:foldl(F, [], FunTypes).
+
+get_module_opaques(Contracts, Codeserver) ->
+ OpaqueModules = ordsets:from_list([M || {_LabelType, {{M, _, _}, _Con}} <- Contracts]),
+ [{M, lookup_opaques(M, Codeserver)} || M <- OpaqueModules].
decorate_succ_typings(FunTypesContracts, ModOpaques) ->
- F = fun({{Label, Type}, {{M, _, _}, Contract}}) ->
- Args = dialyzer_contracts:get_contract_args(Contract),
- Ret = dialyzer_contracts:get_contract_return(Contract),
- C = erl_types:t_fun(Args, Ret),
- {M, Opaques} = lists:keyfind(M, 1, ModOpaques),
- R = erl_types:t_decorate_with_opaque(Type, C, Opaques),
- {Label, R};
- ({LabelType, no}) ->
- LabelType
+ F = fun({{Label, Type}, {{M, _, _}, Contract}}, Acc) ->
+ case lists:keyfind(M, 1, ModOpaques) of
+ {M, []} ->
+ [{Label, Type}|Acc];
+ {M, Opaques} ->
+ Args = dialyzer_contracts:get_contract_args(Contract),
+ Ret = dialyzer_contracts:get_contract_return(Contract),
+ C = erl_types:t_fun(Args, Ret),
+ R = erl_types:t_decorate_with_opaque(Type, C, Opaques),
+ [{Label, R}|Acc]
+ end;
+ ({LabelType, no}, Acc) ->
+ [LabelType|Acc]
end,
- orddict:from_list(lists:map(F, FunTypesContracts)).
+ orddict:from_list(lists:foldl(F, [], FunTypesContracts)).
lookup_opaques(Module, Codeserver) ->
Records = dialyzer_codeserver:lookup_mod_records(Module, Codeserver),
@@ -424,10 +415,7 @@ get_fun_types_from_plt([{FunLabel, Arity}|Left], Callgraph, Plt, Map) ->
get_fun_types_from_plt([], _Callgraph, _Plt, Map) ->
orddict:from_list(Map).
-collect_fun_info(Trees) ->
- collect_fun_info(Trees, []).
-
-collect_fun_info([Tree|Trees], List) ->
+collect_fun_info(Tree) ->
Fun = fun(SubTree, Acc) ->
case cerl:is_c_fun(SubTree) of
true ->
@@ -435,9 +423,7 @@ collect_fun_info([Tree|Trees], List) ->
false -> Acc
end
end,
- collect_fun_info(Trees, cerl_trees:fold(Fun, List, Tree));
-collect_fun_info([], List) ->
- List.
+ cerl_trees:fold(Fun, [], Tree).
lookup_fun_type(Label, Arity, Callgraph, Plt) ->
ID = lookup_name(Label, Callgraph),
@@ -468,6 +454,15 @@ format_succ_types([{Label, Type0}|Left], Callgraph, Acc) ->
format_succ_types([], _Callgraph, Acc) ->
Acc.
+lookup_name(F, CG) ->
+ case dialyzer_callgraph:lookup_name(F, CG) of
+ error -> F;
+ {ok, Name} -> Name
+ end.
+
+%%--------------------------------------------------------------------
+%% Debugging.
+
-ifdef(DEBUG).
debug_pp_succ_typings(SuccTypes) ->
?debug("Succ typings:\n", []),
@@ -503,9 +498,3 @@ debug_pp_succ_typings(_) ->
debug_pp_functions(_, _, _, _) ->
ok.
-endif.
-
-lookup_name(F, CG) ->
- case dialyzer_callgraph:lookup_name(F, CG) of
- error -> F;
- {ok, Name} -> Name
- end.
diff --git a/lib/dialyzer/src/dialyzer_typegraph.erl b/lib/dialyzer/src/dialyzer_typegraph.erl
new file mode 100644
index 0000000000..5818236fa7
--- /dev/null
+++ b/lib/dialyzer/src/dialyzer_typegraph.erl
@@ -0,0 +1,109 @@
+%% -*- erlang-indent-level: 2 -*-
+-module(dialyzer_typegraph).
+
+-export([module_type_deps/3]).
+
+-export_type([type_mod_deps/0]).
+
+-include("dialyzer.hrl").
+
+%% Maps a module to those modules that depend on it
+-type type_mod_deps() :: #{module() => [module()]}.
+
+%% We track type dependecies so that we know which modules we ultimately
+%% depend upon for type definitions which, in turn, affect the checking
+%% of a module.
+
+%% Any non-local types that are used in a spec (aka contract) / callback, any
+%% locally-defined types that may depend on a non-local type, and any
+%% implementations of a behaviour, introduce type-level dependencies on other
+%% modules such that if the definition of that other module were to change,
+%% this module would need to be checked again to account for those changes.
+
+-spec module_type_deps(UseContracts :: boolean(), dialyzer_codeserver:codeserver(), [module()]) -> type_mod_deps().
+
+%% The module type deps of a module are modules that depend on the module to
+%% define types, contracts, callbacks or behaviours
+module_type_deps(UseContracts, CodeServer, Modules) ->
+
+ Contracts =
+ case UseContracts of
+ true -> maps:from_list(dict:to_list(dialyzer_codeserver:get_contracts(CodeServer)));
+ false -> []
+ end,
+ Callbacks = maps:from_list(dialyzer_codeserver:get_callbacks(CodeServer)),
+ TypeDefinitions =
+ maps:from_list(
+ [{M, dialyzer_codeserver:lookup_mod_records(M, CodeServer)} || M <- Modules]
+ ),
+ Behaviours =
+ maps:from_list(
+ [{M, get_behaviours_for_module(M, CodeServer)} || M <- Modules]
+ ),
+ collect_module_type_deps(Contracts, Callbacks, TypeDefinitions, Behaviours).
+
+-spec get_behaviours_for_module(module(), dialyzer_codeserver:codeserver()) -> [module()].
+
+get_behaviours_for_module(M, CodeServer) ->
+ ModCode = dialyzer_codeserver:lookup_mod_code(M, CodeServer),
+ Attrs = cerl:module_attrs(ModCode),
+ {Behaviours, _BehaviourLocations} = dialyzer_behaviours:get_behaviours(Attrs),
+ Behaviours.
+
+-spec collect_module_type_deps(Specs, Callbacks, TypeDefinitions, Behaviours) -> type_mod_deps() when
+ Specs :: #{mfa() => dialyzer_contracts:file_contract()},
+ Callbacks :: #{mfa() => dialyzer_contracts:file_contract()},
+ TypeDefinitions :: #{module() => erl_types:type_table()},
+ Behaviours :: #{module() => [module()]}.
+
+collect_module_type_deps(Specs, Callbacks, TypeDefinitions, Behaviours) ->
+
+ Contracts =
+ [{M, Spec} || {{M, _F, _A}, {_FileLine, Spec, _Extra}} <- maps:to_list(Specs)] ++
+ [{M, Callback} || {{M, _F, _A}, {_FileLine, Callback, _Extra}} <- maps:to_list(Callbacks)],
+
+ ModulesMentionedInTypeDefinitions =
+ [{FromTypeDefM, erl_types:module_type_deps_of_type_defs(TypeTable)}
+ || {FromTypeDefM, TypeTable} <- maps:to_list(TypeDefinitions)],
+
+ ModulesMentionedInContracts =
+ [{FromContractM, module_type_deps_of_contract(C)}
+ || {FromContractM, C} <- Contracts],
+
+ ModulesMentionedAsBehaviours =
+ maps:to_list(Behaviours),
+
+ AllDepsRaw =
+ ModulesMentionedInContracts ++
+ ModulesMentionedInTypeDefinitions ++
+ ModulesMentionedAsBehaviours,
+
+ %% Find the union of module dependencies from all sources, removing
+ %% self-references, and flipping the direction of the mapping to
+ %% match the expectations of Dialyzer elsewhere,
+ %% i.e., from:
+ %% module -> those modules it depends on
+ %% to
+ %% module -> those modules that depend on it
+ S0 = sofs:relation(AllDepsRaw, [{atom,[atom]}]),
+ S1 = sofs:relation_to_family(S0),
+ S2 = sofs:family_union(S1),
+ S3 = sofs:family_to_relation(S2),
+ S4 = sofs:converse(S3),
+ S5 = sofs:strict_relation(S4),
+ S6 = sofs:relation_to_family(S5),
+ S7 = sofs:to_external(S6),
+ ModuleToThoseModulesThatDependOnIt = maps:from_list(S7),
+
+ ModuleToThoseModulesThatDependOnIt.
+
+-spec module_type_deps_of_contract(#contract{}) -> [module()].
+
+module_type_deps_of_contract(#contract{forms = Forms}) ->
+ TypeForms = [TypeForm || {TypeForm, _Constraints} <- Forms],
+ ConstraintForms =
+ lists:append([Constraints || {_TypeForm, Constraints} <- Forms]),
+ lists:usort(
+ lists:append(
+ erl_types:type_form_to_remote_modules(TypeForms),
+ dialyzer_contracts:constraint_form_to_remote_modules(ConstraintForms))).
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 62ab852fae..bbddf2a0a3 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -28,12 +28,13 @@
%%-import(helper, %% 'helper' could be any module doing sanity checks...
-import(erl_types,
[t_has_var/1, t_inf/2, t_is_equal/2, t_is_subtype/2,
- t_subtract/2, t_subtract_list/2, t_sup/1, t_sup/2,t_unify/2]).
+ t_subtract/2, t_subtract_list/2, t_sup/1, t_sup/2,
+ t_unify_table_only/2]).
-import(erl_types,
[t_any/0, t_atom/0, t_atom_vals/1,
t_binary/0, t_bitstr/0, t_bitstr/2, t_bitstr_concat/1, t_boolean/0,
- t_collect_vars/1, t_cons/2, t_cons_hd/1, t_cons_tl/1,
+ t_collect_var_names/1, t_cons/2, t_cons_hd/1, t_cons_tl/1,
t_float/0, t_from_range/2, t_from_term/1,
t_fun/0, t_fun/2, t_fun_args/1, t_fun_range/1,
t_integer/0,
@@ -41,7 +42,7 @@
t_is_float/1, t_is_fun/1,
t_is_integer/1, t_non_neg_integer/0,
t_is_list/1, t_is_nil/1, t_is_none/1, t_is_number/1,
- t_is_singleton/1, t_is_none_or_unit/1,
+ t_is_singleton/1, t_is_impossible/1,
t_limit/2, t_list/0, t_list/1,
t_list_elements/1, t_nonempty_list/1, t_maybe_improper_list/0,
@@ -97,7 +98,7 @@
-type typesig_funmap() :: #{type_var() => type_var()}.
-type prop_types() :: orddict:orddict(label(), erl_types:erl_type()).
--type dict_prop_types() :: dict:dict(label(), erl_types:erl_type()).
+-type dict_prop_types() :: #{label() => erl_types:erl_type()}.
-record(state, {callgraph :: dialyzer_callgraph:callgraph()
| 'undefined',
@@ -114,7 +115,7 @@
self_rec :: 'false' | erl_types:erl_type(),
plt :: dialyzer_plt:plt()
| 'undefined',
- prop_types = dict:new() :: dict_prop_types(),
+ prop_types = #{} :: dict_prop_types(),
mod_records = [] :: [{module(), types()}],
scc = [] :: ordsets:ordset(type_var()),
mfas :: [mfa()],
@@ -180,7 +181,7 @@ analyze_scc(SCC, NextLabel, CallGraph, CServer, Plt, PropTypes, Solvers0) ->
Solvers = solvers(Solvers0),
State1 = new_state(SCC, NextLabel, CallGraph, CServer, Plt, PropTypes,
Solvers),
- DefSet = add_def_list(maps:values(State1#state.name_map), sets:new()),
+ DefSet = add_def_list(maps:values(State1#state.name_map), sets:new([{version, 2}])),
State2 = traverse_scc(SCC, CServer, DefSet, State1),
State3 = state__finalize(State2),
Funs = state__scc(State3),
@@ -254,17 +255,24 @@ traverse(Tree, DefinedVars, State) ->
{State1, [SizeType, ValType]} =
traverse_list([Size, Val], DefinedVars, State),
{State2, TypeConstr, BinValTypeConstr} =
- case cerl:bitstr_bitsize(Tree) of
- all ->
- T = t_bitstr(UnitVal, 0),
- {State1, T, T};
- utf ->
- %% contains an integer number of bytes
- T = t_binary(),
- {State1, T, T};
- N when is_integer(N) ->
- {State1, t_bitstr(0, N), t_bitstr(1, N)};
- any -> % Size is not a literal
+ case cerl:is_literal(Size) of
+ true ->
+ case cerl:concrete(Size) of
+ all ->
+ T = t_bitstr(UnitVal, 0),
+ {State1, T, T};
+ undefined -> %utf-8/16/32
+ %% contains an integer number of bytes
+ T = t_binary(),
+ {State1, T, T};
+ N0 when is_integer(N0) ->
+ N = N0 * UnitVal,
+ {State1, t_bitstr(0, N), t_bitstr(1, N)};
+ _ ->
+ {State1, t_none(), t_none()}
+ end;
+ false ->
+ %% Size is not a literal
T1 = ?mk_fun_var(bitstr_constr(SizeType, UnitVal), [SizeType]),
T2 =
?mk_fun_var(bitstr_constr(SizeType, UnitVal, match), [SizeType]),
@@ -308,7 +316,7 @@ traverse(Tree, DefinedVars, State) ->
Hd = cerl:cons_hd(Tree),
Tl = cerl:cons_tl(Tree),
{State1, [HdVar, TlVar]} = traverse_list([Hd, Tl], DefinedVars, State),
- case cerl:is_literal(fold_literal_maybe_match(Tree, State)) of
+ case is_foldable(Tree, State) of
true ->
%% We do not need to do anything more here.
{State, t_cons(HdVar, TlVar)};
@@ -350,10 +358,7 @@ traverse(Tree, DefinedVars, State) ->
TreeVar = mk_var(Tree),
State2 =
try
- State1 = case state__add_prop_constrs(Tree, State0) of
- not_called -> State0;
- PropState -> PropState
- end,
+ State1 = state__add_prop_constrs(Tree, State0),
{BodyState, BodyVar} = traverse(Body, DefinedVars1, State1),
state__store_conj(TreeVar, eq,
t_fun(mk_var_list(Vars), BodyVar), BodyState)
@@ -401,18 +406,6 @@ traverse(Tree, DefinedVars, State) ->
end;
_ -> {State, t_from_term(cerl:concrete(Tree))}
end;
- module ->
- Defs = cerl:module_defs(Tree),
- Funs = [Fun || {_Var, Fun} <- Defs],
- Vars = [Var || {Var, _Fun} <- Defs],
- DefinedVars1 = add_def_list(Vars, DefinedVars),
- State1 = state__store_funs(Vars, Funs, State),
- FoldFun = fun(Fun, AccState) ->
- {S, _} = traverse(Fun, DefinedVars1,
- state__new_constraint_context(AccState)),
- S
- end,
- lists:foldl(FoldFun, State1, Funs);
primop ->
case cerl:atom_val(cerl:primop_name(Tree)) of
match_fail -> throw(error);
@@ -442,23 +435,10 @@ traverse(Tree, DefinedVars, State) ->
end;
remove_message ->
{State, t_any()};
- timeout ->
+ nif_start ->
{State, t_any()};
Other -> erlang:error({'Unsupported primop', Other})
end;
- 'receive' ->
- Clauses = cerl:receive_clauses(Tree),
- Timeout = cerl:receive_timeout(Tree),
- case (cerl:is_c_atom(Timeout) andalso
- (cerl:atom_val(Timeout) =:= infinity)) of
- true ->
- handle_clauses(Clauses, mk_var(Tree), [], DefinedVars, State);
- false ->
- Action = cerl:receive_action(Tree),
- {State1, TimeoutVar} = traverse(Timeout, DefinedVars, State),
- State2 = state__store_conj(TimeoutVar, sub, t_timeout(), State1),
- handle_clauses(Clauses, mk_var(Tree), [], Action, DefinedVars, State2)
- end;
seq ->
Body = cerl:seq_body(Tree),
Arg = cerl:seq_arg(Tree),
@@ -470,7 +450,7 @@ traverse(Tree, DefinedVars, State) ->
Elements = cerl:tuple_es(Tree),
{State1, EVars} = traverse_list(Elements, DefinedVars, State),
{State2, TupleType} =
- case cerl:is_literal(fold_literal_maybe_match(Tree, State1)) of
+ case is_foldable(Tree, State) of
true ->
%% We do not need to do anything more here.
{State, t_tuple(EVars)};
@@ -554,14 +534,14 @@ traverse(Tree, DefinedVars, State) ->
false -> t_any();
true ->
MT = t_inf(lookup_type(MapVar, Map), t_map()),
- case t_is_none_or_unit(MT) of
+ case t_is_impossible(MT) of
true -> t_none();
false ->
DisjointFromKeyType =
fun(ShadowKey) ->
ST = t_inf(lookup_type(ShadowKey, Map),
KeyType),
- t_is_none_or_unit(ST)
+ t_is_impossible(ST)
end,
case lists:all(DisjointFromKeyType, ShadowKeys) of
true -> t_map_get(KeyType, MT);
@@ -595,7 +575,7 @@ traverse(Tree, DefinedVars, State) ->
cerl:concrete(OpTree) =:= exact of
true ->
ST = t_inf(ShadowedKeys, KeyType),
- case t_is_none_or_unit(ST) of
+ case t_is_impossible(ST) of
true ->
t_map_put({KeyType, t_any()}, AccType);
false ->
@@ -667,13 +647,14 @@ add_def_list([], Set) ->
Set.
add_def_from_tree(T, DefinedVars) ->
- Vars = cerl_trees:fold(fun(X, Acc) ->
- case cerl:is_c_var(X) of
- true -> [X|Acc];
- false -> Acc
- end
- end, [], T),
- add_def_list(Vars, DefinedVars).
+ cerl_trees:fold(fun(X, Set) ->
+ case cerl:is_c_var(X) of
+ true ->
+ add_def(X, Set);
+ false ->
+ Set
+ end
+ end, DefinedVars, T).
add_def_from_tree_list([H|T], DefinedVars) ->
add_def_from_tree_list(T, add_def_from_tree(H, DefinedVars));
@@ -858,12 +839,6 @@ get_contract_return(C, ArgTypes) ->
-define(MAX_NOF_CLAUSES, 15).
handle_clauses(Clauses, TopVar, Arg, DefinedVars, State) ->
- handle_clauses(Clauses, TopVar, Arg, none, DefinedVars, State).
-
-handle_clauses([], _, _, Action, DefinedVars, State) when Action =/= none ->
- %% Can happen when a receive has no clauses, see filter_match_fail.
- traverse(Action, DefinedVars, State);
-handle_clauses(Clauses, TopVar, Arg, Action, DefinedVars, State) ->
SubtrTypeList =
if length(Clauses) > ?MAX_NOF_CLAUSES -> overflow;
true -> []
@@ -871,23 +846,8 @@ handle_clauses(Clauses, TopVar, Arg, Action, DefinedVars, State) ->
{State1, CList} = handle_clauses_1(Clauses, TopVar, Arg, DefinedVars,
State, SubtrTypeList, []),
{NewCs, NewState} =
- case Action of
- none ->
- if CList =:= [] -> throw(error);
- true -> {CList, State1}
- end;
- _ ->
- try
- {State2, ActionVar} = traverse(Action, DefinedVars, State1),
- TmpC = mk_constraint(TopVar, eq, ActionVar),
- ActionCs = mk_conj_constraint_list([state__cs(State2),TmpC]),
- {[ActionCs|CList], State2}
- catch
- throw:error ->
- if CList =:= [] -> throw(error);
- true -> {CList, State1}
- end
- end
+ if CList =:= [] -> throw(error);
+ true -> {CList, State1}
end,
OldCs = state__cs(State),
NewCList = mk_disj_constraint_list(NewCs),
@@ -901,29 +861,27 @@ handle_clauses_1([Clause|Tail], TopVar, Arg, DefinedVars,
Guard = cerl:clause_guard(Clause),
Body = cerl:clause_body(Clause),
NewSubtrTypes =
- case SubtrTypes =:= overflow of
- true -> overflow;
- false ->
+ case SubtrTypes of
+ overflow ->
+ overflow;
+ _ ->
ordsets:add_element(get_safe_underapprox(Pats, Guard), SubtrTypes)
end,
try
DefinedVars1 = add_def_from_tree_list(Pats, DefinedVars),
State1 = state__set_in_match(State0, true),
{State2, PatVars} = traverse_list(Pats, DefinedVars1, State1),
+ S = state__store_conj(Arg, eq, t_product(PatVars), State2),
State3 =
- case Arg =:= [] of
- true -> State2;
- false ->
- S = state__store_conj(Arg, eq, t_product(PatVars), State2),
- case SubtrTypes =:= overflow of
- true -> S;
- false ->
- SubtrPatVar = ?mk_fun_var(fun(Map) ->
- TmpType = lookup_type(Arg, Map),
- t_subtract_list(TmpType, SubtrTypes)
- end, [Arg]),
- state__store_conj(Arg, sub, SubtrPatVar, S)
- end
+ case SubtrTypes of
+ overflow ->
+ S;
+ _ ->
+ SubtrPatVar = ?mk_fun_var(fun(Map) ->
+ TmpType = lookup_type(Arg, Map),
+ t_subtract_list(TmpType, SubtrTypes)
+ end, [Arg]),
+ state__store_conj(Arg, sub, SubtrPatVar, S)
end,
State4 = handle_guard(Guard, DefinedVars1, State3),
{State5, BodyVar} = traverse(Body, DefinedVars1,
@@ -1089,7 +1047,8 @@ bitstr_constr(SizeType, UnitVal, ConstructOrMatch) ->
end,
fun(Map) ->
TmpSizeType = lookup_type(SizeType, Map),
- case t_is_subtype(TmpSizeType, t_non_neg_integer()) of
+ case t_is_integer(TmpSizeType) andalso
+ t_is_subtype(TmpSizeType, t_non_neg_integer()) of
true ->
case t_number_vals(TmpSizeType) of
[OneSize] -> t_bitstr(Unit, OneSize * UnitVal);
@@ -1105,7 +1064,8 @@ bitstr_constr(SizeType, UnitVal, ConstructOrMatch) ->
bitstr_val_constr(SizeType, UnitVal, Flags) ->
fun(Map) ->
TmpSizeType = lookup_type(SizeType, Map),
- case t_is_subtype(TmpSizeType, t_non_neg_integer()) of
+ case t_is_integer(TmpSizeType) andalso
+ t_is_subtype(TmpSizeType, t_non_neg_integer()) of
true ->
case erl_types:number_max(TmpSizeType) of
N when is_integer(N), N < 128 -> %% Avoid illegal arithmetic
@@ -1800,12 +1760,12 @@ get_bif_test_constr(Dst, Arg, Type, _State) ->
solve([Fun], State) ->
?debug("============ Analyzing Fun: ~tw ===========\n",
[debug_lookup_name(Fun)]),
- solve_fun(Fun, map_new(), State);
+ solve_fun(Fun, #{}, State);
solve([_|_] = SCC, State) ->
?debug("============ Analyzing SCC: ~tw ===========\n",
[[debug_lookup_name(F) || F <- SCC]]),
Users = comp_users(SCC, State),
- solve_scc(SCC, map_new(), State, Users, _ToSolve=SCC, false).
+ solve_scc(SCC, #{}, State, Users, _ToSolve=SCC, false).
comp_users(SCC, State) ->
Vars0 = [{Fun, state__get_rec_var(Fun, State)} || Fun <- SCC],
@@ -1816,11 +1776,8 @@ comp_users(SCC, State) ->
Vars)]).
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.
- NewMap = solve(Fun, Ref, FunMap, State),
+ NewMap = solve(Fun, FunMap, State),
NewType = lookup_type(Fun, NewMap),
NewFunMap1 = case state__get_rec_var(Fun, State) of
error -> FunMap;
@@ -1872,10 +1829,8 @@ affected(Updated, Users) ->
end || V <- Updated]).
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.
- Map = solve(F, Cs, FunMap, State),
+ Map = solve(F, FunMap, State),
NewType0 = unsafe_lookup_type(F, Map),
NewType = t_limit(NewType0, ?TYPE_LIMIT),
NewFunMap = case state__get_rec_var(F, State) of
@@ -1888,65 +1843,9 @@ 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:S ->
- io:format("Solver ~w failed: ~w:~p\n ~tp\n", [Solver, E, R, S]),
- throw(error)
- end.
-
-solve_fun(v1, _Fun, Cs, FunMap, State) ->
- fun() ->
- {ok, _MapDict, NewMap} = solve_ref_or_list(Cs, FunMap, map_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: ~ts\n",
- [_S1, format_type(unsafe_lookup_type(Key, Map1))]),
- ?debug("~w: ~ts\n",
- [_S2, format_type(unsafe_lookup_type(Key, Map2))]),
- false
- end
- end, Keys).
+solve(Fun, FunMap, State) ->
+ {ok, Map} = v2_solve_ref(Fun, FunMap, State),
+ Map.
%% Solver v2
@@ -1996,20 +1895,22 @@ v2_solve_reference(Id, Map, V2State0) ->
{ok, Dom} -> t_fun(Dom, t_none())
end,
{FunType0, V2State1};
- {ok, NewMap, V2State1, U} ->
+ {ok, ResMap, V2State1, ResU} ->
?debug("Done solving fun: ~tp\n", [debug_lookup_name(Id)]),
- FunType0 = lookup_type(Id, NewMap),
- V2State2 = save_local_map(V2State1, Id, U, NewMap),
+ FunType0 = lookup_type(Id, ResMap),
+ V2State2 = save_local_map(V2State1, Id, ResU, ResMap),
{FunType0, V2State2}
end,
?debug("ref Id=~w Assigned ~ts\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)}.
+ {NewMap0, U0} = enter_var_type(Id, FunType, Map),
+ case state__get_rec_var(Id, State) of
+ {ok, Var} ->
+ %% `Id` and `Var` are one and the same, so they need to be unified.
+ {ok, {NewMap, U}} = refine_bindings([{Var, FunType}], NewMap0, U0),
+ {ok, NewMap, V2State, U};
+ error ->
+ {ok, NewMap0, V2State, U0}
+ end.
v2_solve_self_recursive(Cs, Map, Id, RecType0, V2State0) ->
?debug("Solving self recursive ~tw\n", [debug_lookup_name(Id)]),
@@ -2117,33 +2018,34 @@ v2_solve_disj(Is, [C|Cs], I, Map, V2State, UL, MapL, Eval, Uneval0, Failed) ->
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,maps:get(V, Map)} || V <- U],
- Part1 =
- case maps:find(Id, ConData) of
- error -> []; % cannot happen
- {ok, {Part2,[]}} -> Part2
- end,
+save_local_map(#v2_state{constr_data = ConData0}=V2State, Id, U, Map) ->
?debug("save local map Id=~w:\n", [Id]),
- Part = lists:ukeymerge(1, lists:keysort(1, Part0), Part1),
- ?pp_map("New Part", maps:from_list(Part0)),
- ?pp_map("Old Part", maps:from_list(Part1)),
- ?pp_map(" => Part", maps:from_list(Part)),
- V2State#v2_state{constr_data = maps:put(Id, {Part,[]}, ConData)}.
+
+ {Part0, []} = maps:get(Id, ConData0, {#{}, []}),
+ ?pp_map("Old Part", Part0),
+
+ Part = maps:merge(Part0, maps:with(U, Map)),
+ ?pp_map(" => Part", Part),
+
+ ConData = ConData0#{ Id => {Part,[]} },
+ V2State#v2_state{constr_data = ConData}.
restore_local_map(#v2_state{constr_data = ConData}, Id, Map0) ->
- case maps:find(Id, ConData) of
- error -> Map0;
- {ok, failed} -> Map0;
- {ok, {[],_}} -> Map0;
- {ok, {Part0,U}} ->
- Part = [KV || {K,_V} = KV <- Part0, not lists:member(K, U)],
+ case ConData of
+ #{ Id := {Part0, U} } when map_size(Part0) =/= 0 ->
?debug("restore local map Id=~w U=~w\n", [Id, U]),
- ?pp_map("Part", maps:from_list(Part)),
+
?pp_map("Map0", Map0),
- Map = lists:foldl(fun({K,V}, D) -> maps:put(K, V, D) end, Map0, Part),
+
+ Part = maps:without(U, Part0),
+ ?pp_map("Part", Part0),
+
+ Map = maps:merge(Map0, Part),
?pp_map("Map", Map),
- Map
+
+ Map;
+ #{} ->
+ Map0
end.
v2_solve_conjunct(Conj, Map, V2State0) ->
@@ -2189,7 +2091,7 @@ v2_solve_conj([I|Is], [Cs|Tail], I, Map0, Conj, IsFlat, V2State0,
[U|UL], NewFs, VarsUp, LastMap, LastFlags)
end;
v2_solve_conj([], _Cs, _I, Map, Conj, IsFlat, V2State, UL, NewFs, VarsUp,
- LastMap, LastFlags) ->
+ LastMap, LastFlags) ->
U = lists:umerge(UL),
case lists:umerge(NewFs) of
[] ->
@@ -2201,6 +2103,7 @@ v2_solve_conj([], _Cs, _I, Map, Conj, IsFlat, V2State, UL, NewFs, VarsUp,
report_detected_loop(Conj),
{ok, Map, V2State, lists:umerge([U|VarsUp])};
NewFlags ->
+ ?debug("conjunct restart Id=~w\n", [Conj#constraint_list.id]),
#constraint_list{type = conj, list = Cs} = Conj,
v2_solve_conj(NewFlags, Cs, 1, Map, Conj, IsFlat, V2State,
[], [], [U|VarsUp], Map, NewFlags)
@@ -2237,24 +2140,27 @@ umerge_mask(Is, F) ->
lists:umerge(Is, F).
get_mask(V, Masks) ->
- case maps:find(V, Masks) of
- error -> [];
- {ok, M} -> M
+ case Masks of
+ #{ V := M } -> M;
+ #{} -> []
end.
-get_flags(#v2_state{constr_data = ConData}=V2State0, C) ->
+get_flags(#v2_state{constr_data = ConData0}=V2State0, C) ->
#constraint_list{id = Id, list = Cs, masks = Masks} = C,
- case maps:find(Id, ConData) of
- error ->
- ?debug("get_flags Id=~w Flags=all ~w\n", [Id, length(Cs)]),
- V2State = V2State0#v2_state{constr_data = maps:put(Id, {[],[]}, ConData)},
- {V2State, [every_i]};
- {ok, failed} ->
- {V2State0, failed_list};
- {ok, {Part,U}} when U =/= [] ->
+ case ConData0 of
+ #{ Id := {Part, U} } ->
+ true = U =/= [], %Assertion.
?debug("get_flags Id=~w U=~w\n", [Id, U]),
- V2State = V2State0#v2_state{constr_data = maps:put(Id, {Part,[]}, ConData)},
- save_updated_vars_list(Cs, vars_per_child(U, Masks), V2State)
+ ConData = ConData0#{ Id => {Part, []}},
+ V2State = V2State0#v2_state{constr_data = ConData},
+ save_updated_vars_list(Cs, vars_per_child(U, Masks), V2State);
+ #{ Id := failed } ->
+ {V2State0, failed_list};
+ #{} ->
+ ?debug("get_flags Id=~w Flags=all ~w\n", [Id, length(Cs)]),
+ ConData = ConData0#{ Id => {#{}, []}},
+ V2State = V2State0#v2_state{constr_data = ConData},
+ {V2State, [every_i]}
end.
vars_per_child(U, Masks) ->
@@ -2279,16 +2185,16 @@ 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 maps:find(Id, ConData) of
- error -> V2State; % error means everything is flagged
- {ok, failed} -> V2State;
- {ok, {Part,U0}} ->
+save_updated_vars1(#v2_state{constr_data = ConData0} = V2State,
+ #constraint_list{id = Id}, U) ->
+ case ConData0 of
+ #{ Id := {Part, U0} } ->
%% Duplicates are not so common; let masks/2 remove them.
- U1 = U ++ U0,
- V2State#v2_state{constr_data = maps:put(Id, {Part,U1}, ConData)}
+ ConData = ConData0#{ Id => {Part, U ++ U0}},
+ V2State#v2_state{constr_data = ConData};
+ #{} ->
+ %% Everything is flagged
+ V2State
end.
-ifdef(DEBUG).
@@ -2298,7 +2204,7 @@ pp_constr_data(_Tag, #v2_state{constr_data = D}) ->
case _PartU of
{_Part, _U} ->
io:format("Id: ~w Vars: ~w\n", [_Id, _U]),
- [?pp_map("Part", maps:from_list(_Part)) || _Part =/= []];
+ [?pp_map("Part", _Part) || _Part =/= #{}];
failed ->
io:format("Id: ~w failed list\n", [_Id])
end
@@ -2311,168 +2217,17 @@ pp_constr_data(_Tag, _V2State) ->
ok.
-endif.
-failed_list(#constraint_list{id = Id}, #v2_state{constr_data = D}=V2State) ->
+failed_list(#constraint_list{id = Id}, #v2_state{constr_data = D0}=V2State) ->
?debug("error list ~w~n", [Id]),
- V2State#v2_state{constr_data = maps:put(Id, failed, D)}.
+ D = D0#{ Id => failed },
+ V2State#v2_state{constr_data = D}.
is_failed_list(#constraint_list{id = Id}, #v2_state{constr_data = D}) ->
- maps:find(Id, D) =:= {ok, failed}.
-
-%% Solver v1
-
-solve_ref_or_list(#constraint_ref{id = Id, deps = Deps},
- Map, MapDict, State) ->
- {OldLocalMap, Check} =
- case maps:find(Id, MapDict) of
- error -> {map_new(), false};
- {ok, M} -> {M, true}
- end,
- ?debug("Checking ref to fun: ~tw\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", []),
- {ok, MapDict, Map};
- false ->
- ?debug("Not equal. Solving\n", []),
- Cs = state__get_cs(Id, State),
- Res =
- case state__is_self_rec(Id, State) of
- true -> solve_self_recursive(Cs, Map, MapDict, Id, t_none(), State);
- false -> solve_ref_or_list(Cs, Map, MapDict, State)
- end,
- {NewMapDict, FunType} =
- case Res of
- {error, NewMapDict0} ->
- ?debug("Error solving for function ~tp\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: ~tp\n", [debug_lookup_name(Id)]),
- FunType0 = lookup_type(Id, NewMap),
- {NewMapDict0, FunType0}
- end,
- ?debug(" Id=~w Assigned ~ts\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, maps:put(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 maps:find(Id, MapDict) of
- error -> {map_new(), false};
- {ok, M} -> {M, true}
- end,
- ?debug("Checking ref to list: ~w\n", [Id]),
- if
- OldLocalMap =:= error -> {error, MapDict};
- true ->
- case Check andalso maps_are_equal(OldLocalMap, Map, Deps) of
- true ->
- ?debug("~tw equal ~w\n", [Type, Id]),
- {ok, MapDict, Map};
- false ->
- ?debug("~tw not equal: ~w. Solving\n", [Type, Id]),
- solve_clist(Cs, Type, Id, Deps, MapDict, Map, State)
- end
+ case D of
+ #{ Id := failed } -> true;
+ #{} -> false
end.
-solve_self_recursive(Cs, Map, MapDict, Id, RecType0, State) ->
- ?debug("Solving self recursive ~tw\n", [debug_lookup_name(Id)]),
- {ok, RecVar} = state__get_rec_var(Id, State),
- ?debug("OldRecType ~ts\n", [format_type(RecType0)]),
- RecType = t_limit(RecType0, ?TYPE_LIMIT),
- 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
- 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()),
- solve_self_recursive(Cs, Map, MapDict, Id, NewRecType, State);
- false ->
- Error
- end;
- {ok, NewMapDict, NewMap} ->
- ?pp_map("NewMap", NewMap),
- NewRecType = unsafe_lookup_type(Id, NewMap),
- case is_equal(NewRecType, RecType0) of
- true ->
- {ok, NewMapDict, enter_type(RecVar, NewRecType, NewMap)};
- false ->
- solve_self_recursive(Cs, Map, MapDict, Id, NewRecType, State)
- end
- end.
-
-solve_clist(Cs, conj, Id, Deps, MapDict, Map, State) ->
- case solve_cs(Cs, Map, MapDict, State) of
- {error, NewMapDict} ->
- {error, maps:put(Id, error, NewMapDict)};
- {ok, NewMapDict, NewMap} = Ret ->
- case Cs of
- [_] ->
- %% Just a special case for one conjunctive constraint.
- Ret;
- _ ->
- case maps_are_equal(Map, NewMap, Deps) of
- true -> {ok, maps:put(Id, NewMap, NewMapDict), NewMap};
- false -> solve_clist(Cs, conj, Id, Deps, NewMapDict, NewMap, State)
- end
- end
- end;
-solve_clist(Cs, disj, Id, _Deps, MapDict, Map, State) ->
- Fun = fun(C, Dict) ->
- case solve_ref_or_list(C, Map, Dict, State) of
- {ok, NewDict, NewMap} -> {{ok, NewMap}, NewDict};
- {error, _NewDict} = Error -> Error
- end
- end,
- {Maps, NewMapDict} = lists:mapfoldl(Fun, MapDict, Cs),
- case [X || {ok, X} <- Maps] of
- [] -> {error, maps:put(Id, error, NewMapDict)};
- MapList ->
- NewMap = join_maps(MapList),
- {ok, maps:put(Id, NewMap, NewMapDict), NewMap}
- end.
-
-solve_cs([#constraint_ref{} = C|Tail], Map, MapDict, State) ->
- case solve_ref_or_list(C, Map, MapDict, State) of
- {ok, NewMapDict, Map1} -> solve_cs(Tail, Map1, NewMapDict, State);
- {error, _NewMapDict} = Error -> Error
- end;
-solve_cs([#constraint_list{} = C|Tail], Map, MapDict, State) ->
- case solve_ref_or_list(C, Map, MapDict, State) of
- {ok, NewMapDict, Map1} -> solve_cs(Tail, Map1, NewMapDict, State);
- {error, _NewMapDict} = Error -> Error
- end;
-solve_cs([#constraint{} = C|Tail], Map, MapDict, State) ->
- case solve_one_c(C, Map) of
- error ->
- report_failed_constraint(C, Map),
- {error, MapDict};
- {ok, {NewMap, _U}} ->
- solve_cs(Tail, NewMap, MapDict, State)
- end;
-solve_cs([], Map, MapDict, _State) ->
- {ok, MapDict, Map}.
-
solve_one_c(#constraint{lhs = Lhs, rhs = Rhs, op = Op}, Map) ->
LhsType = lookup_type(Lhs, Map),
RhsType = lookup_type(Rhs, Map),
@@ -2498,22 +2253,50 @@ solve_one_c(#constraint{lhs = Lhs, rhs = Rhs, op = Op}, Map) ->
end.
solve_subtype(Type, Inf, Map) ->
- %% case cerl:is_literal(Type) of
- %% true ->
- %% case t_is_subtype(t_from_term(cerl:concrete(Type)), Inf) of
- %% true -> {ok, Map};
- %% false -> error
- %% end;
- %% false ->
- try t_unify(Type, Inf) of
- {_, List} -> {ok, enter_type_list(List, Map)}
- catch
- throw:{mismatch, _T1, _T2} ->
- ?debug("Mismatch between ~ts and ~ts\n",
- [format_type(_T1), format_type(_T2)]),
- error
- end.
- %% end.
+ try t_unify_table_only(Type, Inf) of
+ Bindings ->
+ refine_bindings(maps:to_list(Bindings), Map, [])
+ catch
+ throw:{mismatch, _T1, _T2} ->
+ ?debug("Mismatch between ~ts and ~ts\n",
+ [format_type(_T1), format_type(_T2)]),
+ error
+ end.
+
+%% Similar to enter_type/3 over a list, but refines known types rather than
+%% replaces them.
+refine_bindings([{Key, Val} | Tail], Map, U0) ->
+ ?debug("Unifying ~ts :: ~ts\n",
+ [format_type(t_var(Key)), format_type(Val)]),
+ %% It's important to keep opaque types whose internal structure is any(),
+ %% hence the equality check on t_any() rather than t_is_any/1.
+ case t_is_equal(Val, t_any()) of
+ true ->
+ refine_bindings(Tail, maps:remove(Key, Map), U0);
+ false ->
+ LimitedVal = t_limit(Val, ?INTERNAL_TYPE_LIMIT),
+ case Map of
+ #{ Key := Old } ->
+ LimitedInf = t_inf(Old, LimitedVal),
+ case t_is_none(LimitedInf) of
+ true ->
+ error;
+ false ->
+ case t_is_equal(Old, LimitedInf) of
+ true ->
+ refine_bindings(Tail, Map, U0);
+ false ->
+ U = ordsets:add_element(Key, U0),
+ refine_bindings(Tail, Map#{ Key => LimitedInf }, U)
+ end
+ end;
+ #{} ->
+ U = ordsets:add_element(Key, U0),
+ refine_bindings(Tail, Map#{ Key => LimitedVal }, U)
+ end
+ end;
+refine_bindings([], Map, U) ->
+ {ok, {Map, U}}.
report_failed_constraint(_C, _Map) ->
?debug("+++++++++++\nFailed: ~ts :: ~ts ~w ~ts :: ~ts\n+++++++++++\n",
@@ -2529,15 +2312,6 @@ report_failed_constraint(_C, _Map) ->
%%
%% ============================================================================
-map_new() ->
- maps:new().
-
-join_maps([Map]) ->
- Map;
-join_maps(Maps) ->
- Keys = constrained_keys(Maps),
- join_maps(Keys, Maps, map_new()).
-
constrained_keys(Maps) ->
lists:foldl(fun(TmpMap, AccKeys) ->
[Key || Key <- AccKeys, maps:is_key(Key, TmpMap)]
@@ -2564,43 +2338,6 @@ join_one_key(Key, [Map|Maps], Type) ->
join_one_key(_Key, [], Type) ->
Type.
-maps_are_equal(Map1, Map2, Deps) ->
- NewDeps = prune_keys(Map1, Map2, Deps),
- maps_are_equal_1(Map1, Map2, NewDeps).
-
-maps_are_equal_1(Map1, Map2, [H|Tail]) ->
- T1 = lookup_type(H, Map1),
- T2 = lookup_type(H, Map2),
- case is_equal(T1, T2) of
- true -> maps_are_equal_1(Map1, Map2, Tail);
- false ->
- ?debug("~w: ~ts =/= ~ts\n", [H, format_type(T1), format_type(T2)]),
- false
- end;
-maps_are_equal_1(_Map1, _Map2, []) ->
- true.
-
--define(PRUNE_LIMIT, 100).
-
-prune_keys(Map1, Map2, Deps) ->
- %% This is only worthwhile if the number of deps is reasonably large,
- %% and also bigger than the number of elements in the maps.
- NofDeps = length(Deps),
- case NofDeps > ?PRUNE_LIMIT of
- true ->
- Keys1 = maps:keys(Map1),
- case length(Keys1) > NofDeps of
- true ->
- Set1 = lists:sort(Keys1),
- Set2 = lists:sort(maps:keys(Map2)),
- ordsets:intersection(ordsets:union(Set1, Set2), Deps);
- false ->
- Deps
- end;
- false ->
- Deps
- end.
-
enter_type(Key, Val, Map) when is_integer(Key) ->
?debug("Entering ~ts :: ~ts\n", [format_type(t_var(Key)), format_type(Val)]),
%% Keep any() in the map if it is opaque:
@@ -2632,15 +2369,6 @@ enter_type_lists([Key|KeyTail], [Val|ValTail], Map) ->
enter_type_lists([], [], Map) ->
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),
{Map1, [Key || not is_same(Key, Map, Map1)]}.
@@ -2734,7 +2462,7 @@ new_state(MFAs, NextLabel, CallGraph, CServer, Plt, PropTypes0, Solvers) ->
end;
_Many -> false
end,
- PropTypes = dict:from_list(PropTypes0),
+ PropTypes = maps:from_list(PropTypes0),
#state{callgraph = CallGraph, name_map = NameMap, next_label = NextLabel,
prop_types = PropTypes, plt = Plt, scc = ordsets:from_list(SCC),
mfas = MFAs, self_rec = SelfRec, solvers = Solvers,
@@ -2834,29 +2562,29 @@ state__new_constraint_context(State) ->
State#state{cs = []}.
state__prop_domain(FunLabel, #state{prop_types = PropTypes}) ->
- case dict:find(FunLabel, PropTypes) of
- error -> error;
- {ok, {_Range_Fun, Dom}} -> {ok, Dom};
- {ok, FunType} -> {ok, t_fun_args(FunType)}
+ case PropTypes of
+ #{FunLabel := FunType} -> {ok, t_fun_args(FunType)};
+ #{} -> error
end.
state__add_prop_constrs(Tree, #state{prop_types = PropTypes} = State) ->
Label = cerl_trees:get_label(Tree),
- case dict:find(Label, PropTypes) of
- error -> State;
- {ok, FunType} ->
+ case PropTypes of
+ #{Label := FunType} ->
case t_fun_args(FunType) of
unknown -> State;
ArgTypes ->
case erl_types:any_none(ArgTypes) of
- true -> not_called;
+ true -> State;
false ->
?debug("Adding propagated constr: ~ts for function ~tw\n",
[format_type(FunType), debug_lookup_name(mk_var(Tree))]),
FunVar = mk_var(Tree),
state__store_conj(FunVar, sub, FunType, State)
end
- end
+ end;
+ #{} ->
+ State
end.
state__cs(#state{cs = Cs}) ->
@@ -2947,7 +2675,7 @@ mk_constraint(Lhs, Op, Rhs) ->
case Deps =:= [] of
true ->
%% This constraint is constant. Solve it immediately.
- case solve_one_c(C, map_new()) of
+ case solve_one_c(C, #{}) of
error -> throw(error);
_R ->
%% This is always true, keep it anyway for logistic reasons
@@ -2977,8 +2705,8 @@ constraint_opnd_is_any(Type) -> t_is_any(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))],
- #fun_var{'fun' = Fun, deps = ordsets:from_list(Deps), origin = Line}.
+ Deps = t_collect_var_names(t_product(Types)),
+ #fun_var{'fun' = Fun, deps = Deps, origin = Line}.
pp_map(S, Map) ->
?debug("\t~s: ~p\n",
@@ -2990,8 +2718,8 @@ pp_map(S, Map) ->
-spec mk_fun_var(fun((_) -> erl_types:erl_type()), [erl_types:erl_type()]) -> #fun_var{}.
mk_fun_var(Fun, Types) ->
- Deps = [t_var_name(Var) || Var <- t_collect_vars(t_product(Types))],
- #fun_var{'fun' = Fun, deps = ordsets:from_list(Deps)}.
+ Deps = t_collect_var_names(t_product(Types)),
+ #fun_var{'fun' = Fun, deps = Deps}.
-endif.
@@ -3004,15 +2732,15 @@ get_deps(#constraint_ref{deps = D}) -> D.
-spec find_constraint_deps([fvar_or_type()]) -> deps().
find_constraint_deps(List) ->
- ordsets:from_list(find_constraint_deps(List, [])).
+ find_constraint_deps(List, []).
find_constraint_deps([#fun_var{deps = Deps}|Tail], Acc) ->
- find_constraint_deps(Tail, [Deps|Acc]);
-find_constraint_deps([Type|Tail], Acc) ->
- NewAcc = [[t_var_name(D) || D <- t_collect_vars(Type)]|Acc],
- find_constraint_deps(Tail, NewAcc);
+ find_constraint_deps(Tail, ordsets:union(Deps, Acc));
+find_constraint_deps([Type | Tail], Acc0) ->
+ Acc = ordsets:union(t_collect_var_names(Type), Acc0),
+ find_constraint_deps(Tail, Acc);
find_constraint_deps([], Acc) ->
- lists:append(Acc).
+ Acc.
mk_constraint_1(Lhs, eq, Rhs, Deps) when Lhs < Rhs ->
#constraint{lhs = Lhs, op = eq, rhs = Rhs, deps = Deps};
@@ -3349,14 +3077,12 @@ find_constraint(Tuple, [#constraint_list{list = List}|Cs]) ->
find_constraint(Tuple, [_|Cs]) ->
find_constraint(Tuple, Cs).
--spec fold_literal_maybe_match(cerl:cerl(), state()) -> cerl:cerl().
+%% Test whether the term can be folded into a literal. If `State`
+%% indicates that we are in a match, folding is not possible if any
+%% literal in the term contains a map.
-fold_literal_maybe_match(Tree0, State) ->
- Tree1 = cerl:fold_literal(Tree0),
- case state__is_in_match(State) of
- false -> Tree1;
- true -> dialyzer_utils:refold_pattern(Tree1)
- end.
+is_foldable(Tree, State) ->
+ dialyzer_utils:is_foldable(Tree, state__is_in_match(State)).
lookup_record(State, Tag, Arity) ->
#state{module = M, mod_records = ModRecs, cserver = CServer} = State,
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index c4ac96c9dc..292c01f7aa 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -31,6 +31,7 @@
get_record_and_type_info/1,
get_spec_info/3,
get_fun_meta_info/3,
+ is_foldable/2,
is_suppressed_fun/2,
is_suppressed_tag/3,
is_compiler_generated/1,
@@ -47,9 +48,21 @@
family/1
]).
+%% For dialyzer_worker.
+-export([process_record_remote_types_module/2]).
+
+-export_type([record_remote_types_init_data/0,
+ record_remote_types_result/0]).
+
-include("dialyzer.hrl").
-include("../../compiler/src/core_parse.hrl").
+-type ext_types_message() :: {pid(), 'ext_types',
+ {mfa(), {file:filename(), erl_anno:location()}}}
+ | {'error', io_lib:chars()}.
+-type record_remote_types_init_data() :: codeserver().
+-type record_remote_types_result() :: [ext_types_message()].
+
%%-define(DEBUG, true).
-ifdef(DEBUG).
@@ -233,60 +246,104 @@ get_record_fields([], _RecDict, Acc) ->
%% The field types are cached. Used during analysis when handling records.
process_record_remote_types(CServer) ->
- ExpTypes = dialyzer_codeserver:get_exported_types(CServer),
- Mods = dialyzer_codeserver:all_temp_modules(CServer),
- process_opaque_types0(Mods, CServer, ExpTypes),
+ case dialyzer_codeserver:all_temp_modules(CServer) of
+ [] ->
+ CServer;
+ Mods ->
+ ExpTypes = dialyzer_codeserver:get_exported_types_table(CServer),
+ process_opaque_types0(Mods, CServer, ExpTypes),
+ %% CodeServer is updated by each worker, but is still valid
+ %% after updates. Workers call
+ %% process_record_remote_types_module/2 below.
+ Return =
+ dialyzer_coordinator:parallel_job(record_remote_types,
+ Mods,
+ _InitData=CServer,
+ _Timing=none),
+ %% We need to pass on messages and thrown errors from erl_types:
+ _ = [self() ! {self(), ext_types, ExtType} ||
+ {_, ext_types, ExtType} <- Return],
+ case [Error || {error, _} = Error <- Return] of
+ [] ->
+ check_record_fields(Mods, CServer, ExpTypes),
+ dialyzer_codeserver:finalize_records(CServer);
+ [Error | _] ->
+ throw(Error)
+ end
+ end.
+
+-spec process_record_remote_types_module(module(),
+ dialyzer_codeserver:codeserver()) ->
+ [ext_types_message()].
+
+process_record_remote_types_module(Module, CServer) ->
+
+ ExpTypes = dialyzer_codeserver:get_exported_types_table(CServer),
VarTable = erl_types:var_table__new(),
RecordTable = dialyzer_codeserver:get_temp_records_table(CServer),
- ModuleFun =
- fun(Module) ->
- RecordMap = dialyzer_codeserver:lookup_temp_mod_records(Module, CServer),
- RecordFun =
- fun({Key, Value}, C2) ->
- case Key of
- {record, Name} ->
- {FileLocation, Fields} = Value,
- {File, _Location} = FileLocation,
- FieldFun =
- fun({Arity, Fields0}, C4) ->
- MRA = {Module, Name, Arity},
- Site = {record, MRA, File},
- {Fields1, C7} =
- lists:mapfoldl(fun({FieldName, Field, _}, C5) ->
- check_remote(Field, ExpTypes, MRA,
- File, RecordTable),
- {FieldT, C6} =
- erl_types:t_from_form
- (Field, ExpTypes, Site,
- RecordTable, VarTable,
- C5),
- {{FieldName, Field, FieldT}, C6}
- end, C4, Fields0),
- {{Arity, Fields1}, C7}
- end,
- {FieldsList, C3} =
- lists:mapfoldl(FieldFun, C2, orddict:to_list(Fields)),
- {{Key, {FileLocation, orddict:from_list(FieldsList)}}, C3};
- {_TypeOrOpaque, Name, NArgs} ->
- %% Make sure warnings about unknown types are output
- %% also for types unused by specs.
- MTA = {Module, Name, NArgs},
- {{_Module, FileLocation, Form, _ArgNames}, _Type} = Value,
- {File, _Location} = FileLocation,
- check_remote(Form, ExpTypes, MTA, File, RecordTable),
- {{Key, Value}, C2}
- end
- end,
- Cache = erl_types:cache__new(),
- {RecordList, _NewCache} =
- lists:mapfoldl(RecordFun, Cache, maps:to_list(RecordMap)),
- dialyzer_codeserver:store_temp_records(Module,
- maps:from_list(RecordList),
- CServer)
+ RecordMap = dialyzer_codeserver:lookup_temp_mod_records(Module, CServer),
+ RecordFun =
+ fun({Key, Value}, C2) ->
+ case Key of
+ {record, Name} ->
+ {FileLocation, Fields} = Value,
+ {File, _Location} = FileLocation,
+ FieldFun =
+ fun({Arity, Fields0}, C4) ->
+ MRA = {Module, Name, Arity},
+ Site = {record, MRA, File},
+ {Fields1, C7} =
+ lists:mapfoldl(fun({FieldName, Field, _}, C5) ->
+ check_remote(Field, ExpTypes, MRA,
+ File, RecordTable),
+ {FieldT, C6} =
+ erl_types:t_from_form
+ (Field, ExpTypes, Site,
+ RecordTable, VarTable,
+ C5),
+ {{FieldName, Field, FieldT}, C6}
+ end, C4, Fields0),
+ {{Arity, Fields1}, C7}
+ end,
+ {FieldsList, C3} =
+ lists:mapfoldl(FieldFun, C2, orddict:to_list(Fields)),
+ {{Key, {FileLocation, orddict:from_list(FieldsList)}}, C3};
+ {_TypeOrOpaque, Name, NArgs} ->
+ %% Make sure warnings about unknown types are output
+ %% also for types unused by specs.
+ MTA = {Module, Name, NArgs},
+ {{_Module, FileLocation, Form, _ArgNames}, _Type} = Value,
+ {File, _Location} = FileLocation,
+ check_remote(Form, ExpTypes, MTA, File, RecordTable),
+ {{Key, Value}, C2}
+ end
end,
- lists:foreach(ModuleFun, Mods),
- check_record_fields(Mods, CServer, ExpTypes),
- dialyzer_codeserver:finalize_records(CServer).
+ Cache = erl_types:cache__new(),
+ try
+ {RecordList, _NewCache} =
+ lists:mapfoldl(RecordFun, Cache, maps:to_list(RecordMap)),
+ _NewCodeServer =
+ dialyzer_codeserver:store_temp_records(Module,
+ maps:from_list(RecordList),
+ CServer),
+ rcv_ext_types()
+ catch
+ throw:{error, _}=Error ->
+ [Error] ++ rcv_ext_types()
+ end.
+
+rcv_ext_types() ->
+ Self = self(),
+ Self ! {Self, done},
+ rcv_ext_types(Self, []).
+
+rcv_ext_types(Self, ExtTypes) ->
+ receive
+ {Self, ext_types, _} = ExtType ->
+ rcv_ext_types(Self, [ExtType | ExtTypes]);
+ {Self, done} ->
+ lists:usort(ExtTypes)
+ end.
%% erl_types:t_from_form() substitutes the declaration of opaque types
%% for the expanded type in some cases. To make sure the initial type,
@@ -934,6 +991,32 @@ segs_from_bitstring(Bitstring) ->
%%------------------------------------------------------------------------------
+
+%% Test whether the term can be folded into a literal.
+%% If the boolean `InMatch` indicates that the term is used in a
+%% match, folding is not possible if any literal in the term
+%% contains a map.
+
+-spec is_foldable(cerl:cerl(), boolean()) -> boolean().
+
+is_foldable(Tree, InMatch) ->
+ case cerl:type(Tree) of
+ cons ->
+ is_foldable(cerl:cons_hd(Tree), InMatch) andalso
+ is_foldable(cerl:cons_tl(Tree), InMatch);
+ tuple ->
+ is_foldable_list(cerl:tuple_es(Tree), InMatch);
+ literal ->
+ not (InMatch andalso find_map(cerl:concrete(Tree)));
+ _ ->
+ false
+ end.
+
+is_foldable_list([E|Es], InMatch) ->
+ is_foldable(E, InMatch) andalso is_foldable_list(Es, InMatch);
+is_foldable_list([], _InMatch) ->
+ true.
+
-spec refold_pattern(cerl:cerl()) -> cerl:cerl().
refold_pattern(Pat) ->
diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl
index af0f2e9e08..c9ceb75a40 100644
--- a/lib/dialyzer/src/dialyzer_worker.erl
+++ b/lib/dialyzer/src/dialyzer_worker.erl
@@ -12,6 +12,8 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
+%% Purpose: Run individual jobs in separate processes.
+
-module(dialyzer_worker).
-export([launch/4]).
@@ -29,12 +31,9 @@
mode :: mode(),
job :: job(),
coordinator :: coordinator(),
- init_data :: init_data(),
- depends_on = [] :: list()
+ init_data :: init_data()
}).
--include("dialyzer.hrl").
-
%% -define(DEBUG, true).
-ifdef(DEBUG).
@@ -55,85 +54,46 @@ launch(Mode, Job, InitData, Coordinator) ->
spawn_link(fun() -> init(State) end).
%%--------------------------------------------------------------------
+%% Local functions.
-init(#state{job = SCC, mode = Mode, init_data = InitData,
- coordinator = Coordinator} = State) when
- Mode =:= 'typesig'; Mode =:= 'dataflow' ->
- DependsOnSCCs = dialyzer_succ_typings:find_depends_on(SCC, InitData),
- ?debug("~w: Deps ~p: ~p\n", [self(), SCC, DependsOnSCCs]),
- Pids = dialyzer_coordinator:sccs_to_pids(DependsOnSCCs, Coordinator),
- ?debug("~w: PidsDeps ~p\n", [self(), Pids]),
- DependsOn = [{Pid, erlang:monitor(process, Pid)} || Pid <- Pids],
- loop(updating, State#state{depends_on = DependsOn});
+init(#state{job = SCC, mode = Mode, init_data = InitData} = State)
+ when Mode =:= 'typesig'; Mode =:= 'dataflow' ->
+ wait_for_success_typings(SCC, InitData, State),
+ run(State);
init(#state{mode = Mode} = State) when
- Mode =:= 'compile'; Mode =:= 'warnings' ->
- loop(running, State).
-
-loop(updating, #state{mode = Mode} = State) when
- Mode =:= 'typesig'; Mode =:= 'dataflow' ->
- ?debug("~w: Update: ~p\n", [self(), State#state.job]),
- NextStatus =
- case waits_more_success_typings(State) of
- true -> waiting;
- false -> running
- end,
- loop(NextStatus, State);
-loop(waiting, #state{mode = Mode} = State) when
- Mode =:= 'typesig'; Mode =:= 'dataflow' ->
- ?debug("~w: Wait: ~p\n", [self(), State#state.job]),
- NewState = wait_for_success_typings(State),
- loop(updating, NewState);
-loop(running, #state{mode = 'compile'} = State) ->
- request_activation(State),
- ?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) ->
- request_activation(State),
- ?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("~w: Run: ~p\n", [self(), State#state.job]),
- NotFixpoint = do_work(State),
- report_to_coordinator(NotFixpoint, State).
-
-waits_more_success_typings(#state{depends_on = Depends}) ->
- Depends =/= [].
-
-wait_for_success_typings(#state{depends_on = DependsOn} = State) ->
- receive
- {'DOWN', Ref, process, Pid, _Info} ->
- ?debug("~w: ~p got DOWN: ~p\n", [self(), State#state.job, Pid]),
- State#state{depends_on = DependsOn -- [{Pid, Ref}]}
- after
- 5000 ->
- ?debug("~w: Still Waiting ~p:\n ~p\n", [self(), State#state.job, DependsOn]),
- State
- end.
+ Mode =:= 'compile'; Mode =:= 'warnings';
+ Mode =:= 'contract_remote_types'; Mode =:= 'record_remote_types' ->
+ run(State).
-request_activation(#state{coordinator = Coordinator}) ->
- dialyzer_coordinator:request_activation(Coordinator).
+run(#state{coordinator = Coordinator, job = Job} = State) ->
+ dialyzer_coordinator:request_activation(Coordinator),
+ Result = run_job(State),
+ ?debug("~w: Done: ~p\n",[self(), Job]),
+ dialyzer_coordinator:job_done(Job, Result, Coordinator).
-do_work(#state{mode = Mode, job = Job, init_data = InitData}) ->
+run_job(#state{mode = Mode, job = Job, init_data = InitData} = State) ->
+ ?debug("~w: ~p: ~p\n", [self(), Mode, Job]),
case Mode of
- typesig -> dialyzer_succ_typings:find_succ_types_for_scc(Job, InitData);
- dataflow -> dialyzer_succ_typings:refine_one_module(Job, InitData)
+ compile ->
+ case start_compilation(State) of
+ {ok, EstimatedSize, Data} ->
+ Label = ask_coordinator_for_label(EstimatedSize, State),
+ continue_compilation(Label, Data);
+ {error, _Reason} = Error ->
+ Error
+ end;
+ typesig ->
+ dialyzer_succ_typings:find_succ_types_for_scc(Job, InitData);
+ dataflow ->
+ dialyzer_succ_typings:refine_one_module(Job, InitData);
+ contract_remote_types ->
+ dialyzer_contracts:process_contract_remote_types_module(Job, InitData);
+ record_remote_types ->
+ dialyzer_utils:process_record_remote_types_module(Job, InitData);
+ warnings ->
+ dialyzer_succ_typings:collect_warnings(Job, InitData)
end.
-report_to_coordinator(Result, #state{job = Job, coordinator = Coordinator}) ->
- ?debug("~w: Done: ~p\n",[self(), Job]),
- dialyzer_coordinator:job_done(Job, Result, Coordinator).
-
start_compilation(#state{job = Job, init_data = InitData}) ->
dialyzer_analysis_callgraph:start_compilation(Job, InitData).
@@ -143,5 +103,8 @@ ask_coordinator_for_label(EstimatedSize, #state{coordinator = 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).
+%% Wait for the results of success typings of modules or SCCs that we
+%% depend on. ('typesig' or 'dataflow' mode)
+wait_for_success_typings(SCC, InitData, #state{coordinator = Coordinator}) ->
+ DependsOnSCCs = dialyzer_succ_typings:find_depends_on(SCC, InitData),
+ dialyzer_coordinator:wait_for_success_typings(DependsOnSCCs, Coordinator).
diff --git a/lib/dialyzer/src/erl_bif_types.erl b/lib/dialyzer/src/erl_bif_types.erl
index d755d5e3d9..27e6a8f4cd 100644
--- a/lib/dialyzer/src/erl_bif_types.erl
+++ b/lib/dialyzer/src/erl_bif_types.erl
@@ -67,10 +67,10 @@
t_is_cons/2,
t_is_float/2,
t_is_fun/2,
+ t_is_impossible/1,
t_is_integer/2,
t_is_nil/1, t_is_nil/2,
t_is_none/1,
- t_is_none_or_unit/1,
t_is_number/2,
t_is_pid/2,
t_is_port/2,
@@ -772,6 +772,10 @@ type(erlang, length, 1, Xs, Opaques) ->
%% Guard bif, needs to be here.
type(erlang, map_size, 1, Xs, Opaques) ->
type(maps, size, 1, Xs, Opaques);
+type(erlang, max, 2, Xs, Opaques) ->
+ strict(erlang, max, 2, Xs,
+ fun([A, B]) -> t_sup(A, B) end,
+ Opaques);
%% Guard bif, needs to be here.
type(erlang, map_get, 2, Xs, Opaques) ->
type(maps, get, 2, Xs, Opaques);
@@ -803,6 +807,10 @@ type(erlang, make_tuple, 3, Xs, Opaques) ->
_Other -> t_tuple()
end
end, Opaques);
+type(erlang, min, 2, Xs, Opaques) ->
+ strict(erlang, min, 2, Xs,
+ fun([A, B]) -> t_sup(A, B) end,
+ Opaques);
type(erlang, nif_error, 1, Xs, Opaques) ->
%% this BIF and the next one are stubs for NIFs and never return
strict(erlang, nif_error, 1, Xs, fun (_) -> t_any() end, Opaques);
@@ -813,6 +821,13 @@ type(erlang, node, 0, _, _Opaques) -> t_node();
%% Guard bif, needs to be here.
type(erlang, node, 1, Xs, Opaques) ->
strict(erlang, node, 1, Xs, fun (_) -> t_node() end, Opaques);
+type(erlang, raise, 3, Xs, Opaques) ->
+ Ts = arg_types(erlang, raise, 3),
+ Xs1 = inf_lists(Xs, Ts, Opaques),
+ case any_is_none_or_unit(Xs1) of
+ true -> t_atom('badarg');
+ false -> t_none()
+ end;
%% Guard bif, needs to be here.
type(erlang, round, 1, Xs, Opaques) ->
strict(erlang, round, 1, Xs, fun (_) -> t_integer() end, Opaques);
@@ -1665,7 +1680,7 @@ list_replace(1, E, [_X | Xs]) ->
[E | Xs].
any_is_none_or_unit(Ts) ->
- lists:any(fun erl_types:t_is_none_or_unit/1, Ts).
+ lists:any(fun erl_types:t_is_impossible/1, Ts).
check_guard([X], Test, Type, Opaques) ->
check_guard_single(X, Test, Type, Opaques).
@@ -2290,6 +2305,8 @@ arg_types(erlang, is_tuple, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, length, 1) ->
[t_list()];
+arg_types(erlang, max, 2) ->
+ [t_any(), t_any()];
%% Guard bif, needs to be here.
arg_types(erlang, map_size, 1) ->
[t_map()];
@@ -2302,6 +2319,8 @@ arg_types(erlang, make_tuple, 2) ->
[t_non_neg_fixnum(), t_any()]; % the value 0 is OK as first argument
arg_types(erlang, make_tuple, 3) ->
[t_non_neg_fixnum(), t_any(), t_list(t_tuple([t_pos_integer(), t_any()]))];
+arg_types(erlang, min, 2) ->
+ [t_any(), t_any()];
arg_types(erlang, nif_error, 1) ->
[t_any()];
arg_types(erlang, nif_error, 2) ->
@@ -2312,6 +2331,20 @@ arg_types(erlang, node, 0) ->
%% Guard bif, needs to be here.
arg_types(erlang, node, 1) ->
[t_identifier()];
+arg_types(erlang, raise, 3) ->
+ %% The types are based on the implementation of erlang:raise/3, not
+ %% the documention. That is, those are the types for which
+ %% erlang:raise/3 will raise an exception. If the arguments do not
+ %% conform to those types, erlang:raise/3 will return 'badarg'.
+ Class = t_sup([t_atom('error'), t_atom('exit'), t_atom('throw')]),
+ InfoList = t_list(), %erlang:raise/3 does not check the contents of the list.
+ ArityOrArgs = t_any(), %erlang:raise/3 does not check the type.
+ MFA = t_tuple([t_module(), t_atom(), ArityOrArgs]),
+ MFAS = t_tuple([t_module(), t_atom(), ArityOrArgs, InfoList]),
+ Fun = t_tuple([t_fun(), ArityOrArgs]),
+ FunI = t_tuple([t_fun(), ArityOrArgs, InfoList]),
+ Stack = t_list(t_sup([MFA, MFAS, Fun, FunI])),
+ [Class, t_any(), Stack];
%% Guard bif, needs to be here.
arg_types(erlang, round, 1) ->
[t_number()];
@@ -2532,7 +2565,7 @@ check_fun_application(Fun, Args, Opaques) ->
true ->
case t_fun_args(Fun, Opaques) of
unknown ->
- case t_is_none_or_unit(t_fun_range(Fun, Opaques)) of
+ case t_is_impossible(t_fun_range(Fun, Opaques)) of
true -> error;
false -> ok
end;
@@ -2540,7 +2573,7 @@ check_fun_application(Fun, Args, Opaques) ->
case any_is_none_or_unit(inf_lists(FunDom, Args, Opaques)) of
true -> error;
false ->
- case t_is_none_or_unit(t_fun_range(Fun, Opaques)) of
+ case t_is_impossible(t_fun_range(Fun, Opaques)) of
true -> error;
false -> ok
end
@@ -2551,7 +2584,6 @@ check_fun_application(Fun, Args, Opaques) ->
error
end.
-
%% =====================================================================
%% Some basic types used in various parts of the system
%% =====================================================================
diff --git a/lib/dialyzer/src/erl_types.erl b/lib/dialyzer/src/erl_types.erl
index c75baee3cb..ed0264cc2f 100644
--- a/lib/dialyzer/src/erl_types.erl
+++ b/lib/dialyzer/src/erl_types.erl
@@ -55,7 +55,7 @@
t_boolean/0,
t_byte/0,
t_char/0,
- t_collect_vars/1,
+ t_collect_var_names/1,
t_cons/0,
t_cons/2,
t_cons_hd/1, t_cons_hd/2,
@@ -116,6 +116,7 @@
t_is_float/1, t_is_float/2,
t_is_fun/1, t_is_fun/2,
t_is_identifier/1,
+ t_is_impossible/1,
t_is_instance/2,
t_is_integer/1, t_is_integer/2,
t_is_list/1,
@@ -186,7 +187,6 @@
t_reference/0,
t_singleton_to_term/2,
t_string/0,
- t_struct_from_opaque/2,
t_subst/2,
t_subtract/2,
t_subtract_list/2,
@@ -203,7 +203,7 @@
t_tuple_sizes/1,
t_tuple_subtypes/1,
t_tuple_subtypes/2,
- t_unify/2,
+ t_unify_table_only/2,
t_unit/0,
t_unopaque/1, t_unopaque/2,
t_var/1,
@@ -218,7 +218,9 @@
is_erl_type/1,
atom_to_string/1,
var_table__new/0,
- cache__new/0
+ cache__new/0,
+ module_type_deps_of_type_defs/1,
+ type_form_to_remote_modules/1
]).
-compile({no_auto_import,[min/2,max/2,map_get/2]}).
@@ -320,11 +322,9 @@
-record(int_set, {set :: [integer()]}).
-record(int_rng, {from :: rng_elem(), to :: rng_elem()}).
-%% Note: the definition of #opaque{} was changed to 'mod' and 'name';
-%% it used to be an ordsets of {Mod, Name} pairs. The Dialyzer version
-%% was updated to 2.7 due to this change.
+
-record(opaque, {mod :: module(), name :: atom(),
- args = [] :: [erl_type()], struct :: erl_type()}).
+ arity = 0 :: arity(), struct :: erl_type()}).
-define(atom(Set), #c{tag=?atom_tag, elements=Set}).
-define(bitstr(Unit, Base), #c{tag=?binary_tag, elements=[Unit,Base]}).
@@ -363,17 +363,18 @@
-type file_line() :: {file:name(), erl_anno:line()}.
-type record_key() :: {'record', atom()}.
--type type_key() :: {'type' | 'opaque', mfa()}.
+-type type_key() :: {'type' | 'opaque', {atom(), arity()}}.
-type field() :: {atom(), erl_parse:abstract_expr(), erl_type()}.
-type record_value() :: {file_line(),
[{RecordSize :: non_neg_integer(), [field()]}]}.
-type type_value() :: {{module(), file_line(),
erl_parse:abstract_type(), ArgNames :: [atom()]},
erl_type()}.
--type type_table() :: #{record_key() | type_key() =>
- record_value() | type_value()}.
+-type type_table() :: #{record_key() => record_value()} |
+ #{type_key() => type_value()}.
--opaque var_table() :: #{atom() => erl_type()}.
+-type var_name() :: atom() | integer().
+-type var_table() :: #{ var_name() => erl_type() }.
%%-----------------------------------------------------------------------------
%% Unions
@@ -436,7 +437,7 @@ t_is_none(_) -> false.
-spec t_opaque(module(), atom(), [_], erl_type()) -> erl_type().
t_opaque(Mod, Name, Args, Struct) ->
- O = #opaque{mod = Mod, name = Name, args = Args, struct = Struct},
+ O = #opaque{mod = Mod, name = Name, arity = length(Args), struct = Struct},
?opaque(set_singleton(O)).
-spec t_is_opaque(erl_type(), [erl_type()]) -> boolean().
@@ -747,7 +748,7 @@ decorate_tuples_in_sets([?tuple(Elements, Arity, Tag1) = T1|Tuples] = L1,
if
Tag1 < Tag2 -> decorate_tuples_in_sets(Tuples, L2, Opaques, [T1|Acc]);
Tag1 > Tag2 -> decorate_tuples_in_sets(L1, Ts, Opaques, Acc);
- Tag1 =:= Tag2 ->
+ Tag1 == Tag2 ->
NewElements = list_decorate(Elements, Es, Opaques),
NewAcc = [?tuple(NewElements, Arity, Tag1)|Acc],
decorate_tuples_in_sets(Tuples, Ts, Opaques, NewAcc)
@@ -780,37 +781,6 @@ t_opaque_from_records(RecMap) ->
end, OpaqueRecMap),
[OpaqueType || {_Key, OpaqueType} <- maps:to_list(OpaqueTypeMap)].
-%% Decompose opaque instances of type arg2 to structured types, in arg1
-%% XXX: Same as t_unopaque
--spec t_struct_from_opaque(erl_type(), [erl_type()]) -> erl_type().
-
-t_struct_from_opaque(?function(Domain, Range), Opaques) ->
- ?function(t_struct_from_opaque(Domain, Opaques),
- t_struct_from_opaque(Range, Opaques));
-t_struct_from_opaque(?list(Types, Term, Size), Opaques) ->
- ?list(t_struct_from_opaque(Types, Opaques),
- t_struct_from_opaque(Term, Opaques), Size);
-t_struct_from_opaque(?opaque(_) = T, Opaques) ->
- case is_opaque_type(T, Opaques) of
- true -> t_opaque_structure(T);
- false -> T
- end;
-t_struct_from_opaque(?product(Types), Opaques) ->
- ?product(list_struct_from_opaque(Types, Opaques));
-t_struct_from_opaque(?tuple(?any, _, _) = T, _Opaques) -> T;
-t_struct_from_opaque(?tuple(Types, Arity, Tag), Opaques) ->
- ?tuple(list_struct_from_opaque(Types, Opaques), Arity, Tag);
-t_struct_from_opaque(?tuple_set(Set), Opaques) ->
- NewSet = [{Sz, [t_struct_from_opaque(T, Opaques) || T <- Tuples]}
- || {Sz, Tuples} <- Set],
- ?tuple_set(NewSet);
-t_struct_from_opaque(?union(List), Opaques) ->
- t_sup(list_struct_from_opaque(List, Opaques));
-t_struct_from_opaque(Type, _Opaques) -> Type.
-
-list_struct_from_opaque(Types, Opaques) ->
- [t_struct_from_opaque(Type, Opaques) || Type <- Types].
-
%%-----------------------------------------------------------------------------
%% Unit type. Signals non termination.
%%
@@ -825,11 +795,15 @@ t_unit() ->
t_is_unit(?unit) -> true;
t_is_unit(_) -> false.
+-spec t_is_impossible(erl_type()) -> boolean().
+
+t_is_impossible(?none) -> true;
+t_is_impossible(?unit) -> true;
+t_is_impossible(_) -> false.
+
-spec t_is_none_or_unit(erl_type()) -> boolean().
-t_is_none_or_unit(?none) -> true;
-t_is_none_or_unit(?unit) -> true;
-t_is_none_or_unit(_) -> false.
+t_is_none_or_unit(T) -> t_is_impossible(T).
%%-----------------------------------------------------------------------------
%% Atoms and the derived type boolean
@@ -1710,7 +1684,7 @@ t_map(L) ->
t_map(Pairs0, DefK0, DefV0) ->
DefK1 = lists:foldl(fun({K,_,_},Acc)->t_subtract(Acc,K)end, DefK0, Pairs0),
{DefK2, DefV1} =
- case t_is_none_or_unit(DefK1) orelse t_is_none_or_unit(DefV0) of
+ case t_is_impossible(DefK1) orelse t_is_impossible(DefV0) of
true -> {?none, ?none};
false -> {DefK1, DefV0}
end,
@@ -1971,7 +1945,7 @@ t_map_put(KV, Map, Opaques) ->
map_put(_, ?none, _) -> ?none;
map_put(_, ?unit, _) -> ?none;
map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) ->
- case t_is_none_or_unit(Key) orelse t_is_none_or_unit(Value) of
+ case t_is_impossible(Key) orelse t_is_impossible(Value) of
true -> ?none;
false ->
case is_singleton_type(Key) of
@@ -2359,7 +2333,6 @@ t_has_var(?map(_, DefK, _)= Map) ->
t_has_var_list(map_all_values(Map)) orelse
t_has_var(DefK);
t_has_var(?opaque(Set)) ->
- %% Assume variables in 'args' are also present i 'struct'
t_has_var_list([O#opaque.struct || O <- set_to_list(Set)]);
t_has_var(?union(List)) ->
t_has_var_list(List);
@@ -2371,45 +2344,42 @@ t_has_var_list([T|Ts]) ->
t_has_var(T) orelse t_has_var_list(Ts);
t_has_var_list([]) -> false.
--spec t_collect_vars(erl_type()) -> [erl_type()].
-
-t_collect_vars(T) ->
- Vs = t_collect_vars(T, maps:new()),
- [V || {V, _} <- maps:to_list(Vs)].
+-spec t_collect_var_names(erl_type()) -> any().
--type ctab() :: #{erl_type() => 'any'}.
+t_collect_var_names(T) ->
+ t_collect_var_names(T, []).
--spec t_collect_vars(erl_type(), ctab()) -> ctab().
+-spec t_collect_var_names(erl_type(), ordsets:ordset(term())) ->
+ ordsets:ordset(term()).
-t_collect_vars(?var(_) = Var, Acc) ->
- maps:put(Var, any, Acc);
-t_collect_vars(?function(Domain, Range), Acc) ->
- Acc1 = t_collect_vars(Domain, Acc),
- t_collect_vars(Range, Acc1);
-t_collect_vars(?list(Contents, Termination, _), Acc) ->
- Acc1 = t_collect_vars(Contents, Acc),
- t_collect_vars(Termination, Acc1);
-t_collect_vars(?product(Types), Acc) ->
+t_collect_var_names(?var(Id), Acc) ->
+ ordsets:add_element(Id, Acc);
+t_collect_var_names(?function(Domain, Range), Acc) ->
+ Acc1 = t_collect_var_names(Domain, Acc),
+ t_collect_var_names(Range, Acc1);
+t_collect_var_names(?list(Contents, Termination, _), Acc) ->
+ Acc1 = t_collect_var_names(Contents, Acc),
+ t_collect_var_names(Termination, Acc1);
+t_collect_var_names(?product(Types), Acc) ->
t_collect_vars_list(Types, Acc);
-t_collect_vars(?tuple(?any, ?any, ?any), Acc) ->
+t_collect_var_names(?tuple(?any, ?any, ?any), Acc) ->
Acc;
-t_collect_vars(?tuple(Types, _, _), Acc) ->
+t_collect_var_names(?tuple(Types, _, _), Acc) ->
t_collect_vars_list(Types, Acc);
-t_collect_vars(?tuple_set(_) = TS, Acc) ->
+t_collect_var_names(?tuple_set(_) = TS, Acc) ->
t_collect_vars_list(t_tuple_subtypes(TS), Acc);
-t_collect_vars(?map(_, DefK, _) = Map, Acc0) ->
+t_collect_var_names(?map(_, DefK, _) = Map, Acc0) ->
Acc = t_collect_vars_list(map_all_values(Map), Acc0),
- t_collect_vars(DefK, Acc);
-t_collect_vars(?opaque(Set), Acc) ->
- %% Assume variables in 'args' are also present i 'struct'
+ t_collect_var_names(DefK, Acc);
+t_collect_var_names(?opaque(Set), Acc) ->
t_collect_vars_list([O#opaque.struct || O <- set_to_list(Set)], Acc);
-t_collect_vars(?union(List), Acc) ->
+t_collect_var_names(?union(List), Acc) ->
t_collect_vars_list(List, Acc);
-t_collect_vars(_, Acc) ->
+t_collect_var_names(_, Acc) ->
Acc.
t_collect_vars_list([T|Ts], Acc0) ->
- Acc = t_collect_vars(T, Acc0),
+ Acc = t_collect_var_names(T, Acc0),
t_collect_vars_list(Ts, Acc);
t_collect_vars_list([], Acc) -> Acc.
@@ -2630,7 +2600,7 @@ t_sup(Ts) ->
t_sup1([H1, H2|T], L) ->
t_sup1(T, [t_sup(H1, H2)|L]);
-t_sup1([T], []) -> subst_all_vars_to_any(T);
+t_sup1([T], []) -> do_not_subst_all_vars_to_any(T);
t_sup1(Ts, L) ->
t_sup1(Ts++L, []).
@@ -2642,7 +2612,7 @@ t_sup(?none, T) -> T;
t_sup(T, ?none) -> T;
t_sup(?unit, T) -> T;
t_sup(T, ?unit) -> T;
-t_sup(T, T) -> subst_all_vars_to_any(T);
+t_sup(T, T) -> do_not_subst_all_vars_to_any(T);
t_sup(?var(_), _) -> ?any;
t_sup(_, ?var(_)) -> ?any;
t_sup(?atom(Set1), ?atom(Set2)) ->
@@ -2716,9 +2686,9 @@ t_sup(?tuple(?any, ?any, ?any) = T, ?tuple_set(_)) -> T;
t_sup(?tuple_set(_), ?tuple(?any, ?any, ?any) = T) -> T;
t_sup(?tuple(Elements1, Arity, Tag1) = T1,
?tuple(Elements2, Arity, Tag2) = T2) ->
- if Tag1 =:= Tag2 -> t_tuple(t_sup_lists(Elements1, Elements2));
- Tag1 =:= ?any -> t_tuple(t_sup_lists(Elements1, Elements2));
- Tag2 =:= ?any -> t_tuple(t_sup_lists(Elements1, Elements2));
+ if Tag1 == Tag2 -> t_tuple(t_sup_lists(Elements1, Elements2));
+ Tag1 == ?any -> t_tuple(t_sup_lists(Elements1, Elements2));
+ Tag2 == ?any -> t_tuple(t_sup_lists(Elements1, Elements2));
Tag1 < Tag2 -> ?tuple_set([{Arity, [T1, T2]}]);
Tag1 > Tag2 -> ?tuple_set([{Arity, [T2, T1]}])
end;
@@ -2748,8 +2718,8 @@ sup_opaque(List) ->
?opaque(ordsets:from_list(L)).
sup_opaq(L0) ->
- L1 = [{{Mod,Name,Args}, T} ||
- #opaque{mod = Mod, name = Name, args = Args}=T <- L0],
+ L1 = [{{Mod,Name,Arity}, T} ||
+ #opaque{mod = Mod, name = Name, arity = Arity}=T <- L0],
F = dialyzer_utils:family(L1),
[supl(Ts) || {_, Ts} <- F].
@@ -2824,9 +2794,10 @@ sup_tuples_in_set([?tuple(Elements1, Arity, Tag1) = T1|Left1] = L1,
if
Tag1 < Tag2 -> sup_tuples_in_set(Left1, L2, [T1|Acc]);
Tag1 > Tag2 -> sup_tuples_in_set(L1, Left2, [T2|Acc]);
- Tag2 =:= Tag2 -> NewElements = t_sup_lists(Elements1, Elements2),
- NewAcc = [?tuple(NewElements, Arity, Tag1)|Acc],
- sup_tuples_in_set(Left1, Left2, NewAcc)
+ Tag1 == Tag2 ->
+ NewElements = t_sup_lists(Elements1, Elements2),
+ NewAcc = [?tuple(NewElements, Arity, Tag1)|Acc],
+ sup_tuples_in_set(Left1, Left2, NewAcc)
end;
sup_tuples_in_set([], L2, Acc) -> lists:reverse(Acc, L2);
sup_tuples_in_set(L1, [], Acc) -> lists:reverse(Acc, L1).
@@ -2944,15 +2915,15 @@ t_inf(T1, T2) ->
-spec t_inf(erl_type(), erl_type(), t_inf_opaques()) -> erl_type().
t_inf(?var(_), ?var(_), _Opaques) -> ?any;
-t_inf(?var(_), T, _Opaques) -> subst_all_vars_to_any(T);
-t_inf(T, ?var(_), _Opaques) -> subst_all_vars_to_any(T);
-t_inf(?any, T, _Opaques) -> subst_all_vars_to_any(T);
-t_inf(T, ?any, _Opaques) -> subst_all_vars_to_any(T);
+t_inf(?var(_), T, _Opaques) -> do_not_subst_all_vars_to_any(T);
+t_inf(T, ?var(_), _Opaques) -> do_not_subst_all_vars_to_any(T);
+t_inf(?any, T, _Opaques) -> do_not_subst_all_vars_to_any(T);
+t_inf(T, ?any, _Opaques) -> do_not_subst_all_vars_to_any(T);
t_inf(?none, _, _Opaques) -> ?none;
t_inf(_, ?none, _Opaques) -> ?none;
t_inf(?unit, _, _Opaques) -> ?unit; % ?unit cases should appear below ?none
t_inf(_, ?unit, _Opaques) -> ?unit;
-t_inf(T, T, _Opaques) -> subst_all_vars_to_any(T);
+t_inf(T, T, _Opaques) -> do_not_subst_all_vars_to_any(T);
t_inf(?atom(Set1), ?atom(Set2), _) ->
case set_intersection(Set1, Set2) of
?none -> ?none;
@@ -2988,7 +2959,7 @@ t_inf(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, _Opaques) ->
%% result in a none result.
Pairs =
map_pairwise_merge(
- %% For optional keys in both maps, when the infinimum is none, we have
+ %% For optional keys in both maps, when the infimum is none, we have
%% essentially concluded that K must not be a key in the map.
fun(K, ?opt, V1, ?opt, V2) -> {K, ?opt, t_inf(V1, V2)};
%% When a key is optional in one map, but mandatory in another, it
@@ -3072,13 +3043,13 @@ t_inf(?product(_), _, _Opaques) ->
t_inf(_, ?product(_), _Opaques) ->
?none;
t_inf(?tuple(?any, ?any, ?any), ?tuple(_, _, _) = T, _Opaques) ->
- subst_all_vars_to_any(T);
+ do_not_subst_all_vars_to_any(T);
t_inf(?tuple(_, _, _) = T, ?tuple(?any, ?any, ?any), _Opaques) ->
- subst_all_vars_to_any(T);
+ do_not_subst_all_vars_to_any(T);
t_inf(?tuple(?any, ?any, ?any), ?tuple_set(_) = T, _Opaques) ->
- subst_all_vars_to_any(T);
+ do_not_subst_all_vars_to_any(T);
t_inf(?tuple_set(_) = T, ?tuple(?any, ?any, ?any), _Opaques) ->
- subst_all_vars_to_any(T);
+ do_not_subst_all_vars_to_any(T);
t_inf(?tuple(Elements1, Arity, _Tag1), ?tuple(Elements2, Arity, _Tag2), Opaques) ->
case t_inf_lists_strict(Elements1, Elements2, Opaques) of
bottom -> ?none;
@@ -3196,121 +3167,13 @@ compatible_opaque_types(?opaque(Es1), ?opaque(Es2)) ->
[{O1, O2} || O1 <- Es1, O2 <- Es2, is_compat_opaque_names(O1, O2)].
is_compat_opaque_names(Opaque1, Opaque2) ->
- #opaque{mod = Mod1, name = Name1, args = Args1} = Opaque1,
- #opaque{mod = Mod2, name = Name2, args = Args2} = Opaque2,
- case {{Mod1, Name1, Args1}, {Mod2, Name2, Args2}} of
- {ModNameArgs, ModNameArgs} -> true;
- {{Mod, Name, Args1}, {Mod, Name, Args2}} ->
- is_compat_args(Args1, Args2);
+ #opaque{mod = Mod1, name = Name1, arity = Arity1} = Opaque1,
+ #opaque{mod = Mod2, name = Name2, arity = Arity2} = Opaque2,
+ case {{Mod1, Name1, Arity1}, {Mod2, Name2, Arity2}} of
+ {ModNameArity, ModNameArity} -> true;
_ -> false
end.
-is_compat_args([A1|Args1], [A2|Args2]) ->
- is_compat_arg(A1, A2) andalso is_compat_args(Args1, Args2);
-is_compat_args([], []) -> true;
-is_compat_args(_, _) -> false.
-
--spec is_compat_arg(erl_type(), erl_type()) -> boolean().
-
-%% The intention is that 'true' is to be returned iff one of the
-%% arguments is a specialization of the other argument in the sense
-%% that every type is a specialization of any(). For example, {_,_} is
-%% a specialization of any(), but not of tuple(). Does not handle
-%% variables, but any() and unions (sort of). However, the
-%% implementation is more relaxed as any() is compatible to anything.
-
-is_compat_arg(T, T) -> true;
-is_compat_arg(_, ?any) -> true;
-is_compat_arg(?any, _) -> true;
-is_compat_arg(?function(Domain1, Range1), ?function(Domain2, Range2)) ->
- (is_compat_arg(Domain1, Domain2) andalso
- is_compat_arg(Range1, Range2));
-is_compat_arg(?list(Contents1, Termination1, Size1),
- ?list(Contents2, Termination2, Size2)) ->
- (Size1 =:= Size2 andalso
- is_compat_arg(Contents1, Contents2) andalso
- is_compat_arg(Termination1, Termination2));
-is_compat_arg(?product(Types1), ?product(Types2)) ->
- is_compat_list(Types1, Types2);
-is_compat_arg(?map(Pairs1, DefK1, DefV1), ?map(Pairs2, DefK2, DefV2)) ->
- {Ks1, _, Vs1} = lists:unzip3(Pairs1),
- {Ks2, _, Vs2} = lists:unzip3(Pairs2),
- Key1 = t_sup([DefK1 | Ks1]),
- Key2 = t_sup([DefK2 | Ks2]),
- case is_compat_arg(Key1, Key2) of
- true ->
- Value1 = t_sup([DefV1 | Vs1]),
- Value2 = t_sup([DefV2 | Vs2]),
- is_compat_arg(Value1, Value2);
- false ->
- false
- end;
-is_compat_arg(?tuple(?any, ?any, ?any), ?tuple(_, _, _)) -> false;
-is_compat_arg(?tuple(_, _, _), ?tuple(?any, ?any, ?any)) -> false;
-is_compat_arg(?tuple(Elements1, Arity, _),
- ?tuple(Elements2, Arity, _)) when Arity =/= ?any ->
- is_compat_list(Elements1, Elements2);
-is_compat_arg(?tuple_set([{Arity, List}]),
- ?tuple(Elements2, Arity, _)) when Arity =/= ?any ->
- is_compat_list(sup_tuple_elements(List), Elements2);
-is_compat_arg(?tuple(Elements1, Arity, _),
- ?tuple_set([{Arity, List}])) when Arity =/= ?any ->
- is_compat_list(Elements1, sup_tuple_elements(List));
-is_compat_arg(?tuple_set(List1), ?tuple_set(List2)) ->
- try
- is_compat_list_list([sup_tuple_elements(T) || {_Arity, T} <- List1],
- [sup_tuple_elements(T) || {_Arity, T} <- List2])
- catch _:_ -> false
- end;
-is_compat_arg(?opaque(_) = T1, T2) ->
- is_compat_arg(t_opaque_structure(T1), T2);
-is_compat_arg(T1, ?opaque(_) = T2) ->
- is_compat_arg(T1, t_opaque_structure(T2));
-is_compat_arg(?union(List1)=T1, ?union(List2)=T2) ->
- case is_compat_union2(T1, T2) of
- {yes, Type1, Type2} -> is_compat_arg(Type1, Type2);
- no -> is_compat_list(List1, List2)
- end;
-is_compat_arg(?union(List), T2) ->
- case unify_union(List) of
- {yes, Type} -> is_compat_arg(Type, T2);
- no -> false
- end;
-is_compat_arg(T1, ?union(List)) ->
- case unify_union(List) of
- {yes, Type} -> is_compat_arg(T1, Type);
- no -> false
- end;
-is_compat_arg(?var(_), _) -> exit(error);
-is_compat_arg(_, ?var(_)) -> exit(error);
-is_compat_arg(?none, _) -> false;
-is_compat_arg(_, ?none) -> false;
-is_compat_arg(?unit, _) -> false;
-is_compat_arg(_, ?unit) -> false;
-is_compat_arg(#c{}, #c{}) -> false.
-
-is_compat_list_list(LL1, LL2) ->
- length(LL1) =:= length(LL2) andalso is_compat_list_list1(LL1, LL2).
-
-is_compat_list_list1([], []) -> true;
-is_compat_list_list1([L1|LL1], [L2|LL2]) ->
- is_compat_list(L1, L2) andalso is_compat_list_list1(LL1, LL2).
-
-is_compat_list(L1, L2) ->
- length(L1) =:= length(L2) andalso is_compat_list1(L1, L2).
-
-is_compat_list1([], []) -> true;
-is_compat_list1([T1|L1], [T2|L2]) ->
- is_compat_arg(T1, T2) andalso is_compat_list1(L1, L2).
-
-is_compat_union2(?union(List1)=T1, ?union(List2)=T2) ->
- case {unify_union(List1), unify_union(List2)} of
- {{yes, Type1}, {yes, Type2}} -> {yes, Type1, Type2};
- {{yes, Type1}, no} -> {yes, Type1, T2};
- {no, {yes, Type2}} -> {yes, T1, Type2};
- {no, no} -> no
- end.
-
-spec t_inf_lists([erl_type()], [erl_type()]) -> [erl_type()].
t_inf_lists(L1, L2) ->
@@ -3459,11 +3322,20 @@ findfirst(N1, N2, U1, B1, U2, B2) ->
if Val1 =:= Val2 ->
Val1;
Val1 > Val2 ->
- findfirst(N1, N2+1, U1, B1, U2, B2);
+ N2_1 = N2 + max((Val1 - Val2) div U2, 1),
+ findfirst(N1, N2_1, U1, B1, U2, B2);
Val1 < Val2 ->
- findfirst(N1+1, N2, U1, B1, U2, B2)
+ N1_1 = N1 + max((Val2 - Val1) div U1, 1),
+ findfirst(N1_1, N2, U1, B1, U2, B2)
end.
+%% Optimization. Before Erlang/OTP 25, subst_all_vars_to_any() was
+%% called. It turned out that variables are not to be substituted for
+%% any() since either there are no variables, or variables are
+%% substituted for any() afterwards.
+do_not_subst_all_vars_to_any(T) ->
+ T.
+
%%-----------------------------------------------------------------------------
%% Substitution of variables
%%
@@ -3516,9 +3388,8 @@ t_subst_aux(?map(Pairs, DefK, DefV), Map) ->
t_map([{K, MNess, t_subst_aux(V, Map)} || {K, MNess, V} <- Pairs],
t_subst_aux(DefK, Map), t_subst_aux(DefV, Map));
t_subst_aux(?opaque(Es), Map) ->
- List = [Opaque#opaque{args = [t_subst_aux(Arg, Map) || Arg <- Args],
- struct = t_subst_aux(S, Map)} ||
- Opaque = #opaque{args = Args, struct = S} <- set_to_list(Es)],
+ List = [Opaque#opaque{struct = t_subst_aux(S, Map)} ||
+ Opaque = #opaque{struct = S} <- set_to_list(Es)],
?opaque(ordsets:from_list(List));
t_subst_aux(?union(List), Map) ->
?union([t_subst_aux(E, Map) || E <- List]);
@@ -3529,106 +3400,116 @@ t_subst_aux(T, _Map) ->
%% Unification
%%
--type t_unify_ret() :: {erl_type(), [{_, erl_type()}]}.
-
--spec t_unify(erl_type(), erl_type()) -> t_unify_ret().
-
-t_unify(T1, T2) ->
- {T, VarMap} = t_unify(T1, T2, #{}),
- {t_subst(T, VarMap), lists:keysort(1, maps:to_list(VarMap))}.
-
-t_unify(?var(Id) = T, ?var(Id), VarMap) ->
- {T, VarMap};
-t_unify(?var(Id1) = T, ?var(Id2), VarMap) ->
- case maps:find(Id1, VarMap) of
- error ->
- case maps:find(Id2, VarMap) of
- error -> {T, VarMap#{Id2 => T}};
- {ok, Type} -> t_unify(T, Type, VarMap)
- end;
- {ok, Type1} ->
- case maps:find(Id2, VarMap) of
- error -> {Type1, VarMap#{Id2 => T}};
- {ok, Type2} -> t_unify(Type1, Type2, VarMap)
- end
+-spec t_unify_table_only(erl_type(), erl_type()) -> var_table().
+
+%% A simplified version of t_unify/2 which returns the variable
+%% bindings only. It is faster, mostly because t_subst() is not
+%% called.
+
+t_unify_table_only(T1, T2) ->
+ t_unify_table_only(T1, T2, #{}).
+
+t_unify_table_only(?var(Id), ?var(Id), VarMap) ->
+ VarMap;
+t_unify_table_only(?var(Id1) = LHS, ?var(Id2) = RHS, VarMap) ->
+ case VarMap of
+ #{ Id1 := Type1, Id2 := Type2} ->
+ t_unify_table_only(Type1, Type2, VarMap);
+ #{ Id1 := Type } ->
+ t_unify_table_only(Type, RHS, VarMap);
+ #{ Id2 := Type } ->
+ t_unify_table_only(LHS, Type, VarMap);
+ #{} ->
+ VarMap#{ Id1 => LHS, Id2 => RHS }
end;
-t_unify(?var(Id), Type, VarMap) ->
+t_unify_table_only(?var(Id), Type, VarMap) ->
case maps:find(Id, VarMap) of
- error -> {Type, VarMap#{Id => Type}};
- {ok, VarType} -> t_unify(VarType, Type, VarMap)
+ error -> VarMap#{Id => Type};
+ {ok, VarType} -> t_unify_table_only(VarType, Type, VarMap)
end;
-t_unify(Type, ?var(Id), VarMap) ->
+t_unify_table_only(Type, ?var(Id), VarMap) ->
case maps:find(Id, VarMap) of
- error -> {Type, VarMap#{Id => Type}};
- {ok, VarType} -> t_unify(VarType, Type, VarMap)
+ error -> VarMap#{Id => Type};
+ {ok, VarType} -> t_unify_table_only(VarType, Type, VarMap)
end;
-t_unify(?function(Domain1, Range1), ?function(Domain2, Range2), VarMap) ->
- {Domain, VarMap1} = t_unify(Domain1, Domain2, VarMap),
- {Range, VarMap2} = t_unify(Range1, Range2, VarMap1),
- {?function(Domain, Range), VarMap2};
-t_unify(?list(Contents1, Termination1, Size),
+t_unify_table_only(?function(Domain1, Range1), ?function(Domain2, Range2), VarMap) ->
+ VarMap1 = t_unify_table_only(Domain1, Domain2, VarMap),
+ t_unify_table_only(Range1, Range2, VarMap1);
+t_unify_table_only(?list(Contents1, Termination1, Size),
?list(Contents2, Termination2, Size), VarMap) ->
- {Contents, VarMap1} = t_unify(Contents1, Contents2, VarMap),
- {Termination, VarMap2} = t_unify(Termination1, Termination2, VarMap1),
- {?list(Contents, Termination, Size), VarMap2};
-t_unify(?product(Types1), ?product(Types2), VarMap) ->
- {Types, VarMap1} = unify_lists(Types1, Types2, VarMap),
- {?product(Types), VarMap1};
-t_unify(?tuple(?any, ?any, ?any) = T, ?tuple(?any, ?any, ?any), VarMap) ->
- {T, VarMap};
-t_unify(?tuple(Elements1, Arity, _),
+ VarMap1 = t_unify_table_only(Contents1, Contents2, VarMap),
+ t_unify_table_only(Termination1, Termination2, VarMap1);
+t_unify_table_only(?product(Types1), ?product(Types2), VarMap) ->
+ unify_lists_table_only(Types1, Types2, VarMap);
+t_unify_table_only(?tuple(?any, ?any, ?any), ?tuple(?any, ?any, ?any), VarMap) ->
+ VarMap;
+t_unify_table_only(?tuple(Elements1, Arity, _),
?tuple(Elements2, Arity, _), VarMap) when Arity =/= ?any ->
- {NewElements, VarMap1} = unify_lists(Elements1, Elements2, VarMap),
- {t_tuple(NewElements), VarMap1};
-t_unify(?tuple_set([{Arity, _}]) = T1,
+ unify_lists_table_only(Elements1, Elements2, VarMap);
+t_unify_table_only(?tuple_set([{Arity, _}]) = T1,
?tuple(_, Arity, _) = T2, VarMap) when Arity =/= ?any ->
- unify_tuple_set_and_tuple1(T1, T2, VarMap);
-t_unify(?tuple(_, Arity, _) = T1,
+ unify_tuple_set_and_tuple1_table_only(T1, T2, VarMap);
+t_unify_table_only(?tuple(_, Arity, _) = T1,
?tuple_set([{Arity, _}]) = T2, VarMap) when Arity =/= ?any ->
- unify_tuple_set_and_tuple2(T1, T2, VarMap);
-t_unify(?tuple_set(List1) = T1, ?tuple_set(List2) = T2, VarMap) ->
+ unify_tuple_set_and_tuple2_table_only(T1, T2, VarMap);
+t_unify_table_only(?tuple_set(List1) = T1, ?tuple_set(List2) = T2, VarMap) ->
try
- unify_lists(lists:append([T || {_Arity, T} <- List1]),
- lists:append([T || {_Arity, T} <- List2]), VarMap)
- of
- {Tuples, NewVarMap} -> {t_sup(Tuples), NewVarMap}
+ unify_lists_table_only(lists:append([T || {_Arity, T} <- List1]),
+ lists:append([T || {_Arity, T} <- List2]), VarMap)
catch _:_ -> throw({mismatch, T1, T2})
end;
-t_unify(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, VarMap0) ->
- {DefK, VarMap1} = t_unify(ADefK, BDefK, VarMap0),
- {DefV, VarMap2} = t_unify(ADefV, BDefV, VarMap1),
- {Pairs, VarMap} =
+t_unify_table_only(?map(_, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B, VarMap0) ->
+ VarMap1 = t_unify_table_only(ADefK, BDefK, VarMap0),
+ VarMap2 = t_unify_table_only(ADefV, BDefV, VarMap1),
+ {[], VarMap} =
map_pairwise_merge_foldr(
- fun(K, MNess, V1, MNess, V2, {Pairs0, VarMap3}) ->
+ fun(_K, MNess, V1, MNess, V2, {Pairs0, VarMap3}) ->
%% We know that the keys unify and do not contain variables, or they
%% would not be singletons
%% TODO: Should V=?none (known missing keys) be handled special?
- {V, VarMap4} = t_unify(V1, V2, VarMap3),
- {[{K,MNess,V}|Pairs0], VarMap4};
- (K, _, V1, _, V2, {Pairs0, VarMap3}) ->
+ VarMap4 = t_unify_table_only(V1, V2, VarMap3),
+ {Pairs0, VarMap4};
+ (_K, _, V1, _, V2, {Pairs0, VarMap3}) ->
%% One mandatory and one optional; what should be done in this case?
- {V, VarMap4} = t_unify(V1, V2, VarMap3),
- {[{K,?mand,V}|Pairs0], VarMap4}
+ VarMap4 = t_unify_table_only(V1, V2, VarMap3),
+ {Pairs0, VarMap4}
end, {[], VarMap2}, A, B),
- {t_map(Pairs, DefK, DefV), VarMap};
-t_unify(?opaque(_) = T1, ?opaque(_) = T2, VarMap) ->
- t_unify(t_opaque_structure(T1), t_opaque_structure(T2), VarMap);
-t_unify(T1, ?opaque(_) = T2, VarMap) ->
- t_unify(T1, t_opaque_structure(T2), VarMap);
-t_unify(?opaque(_) = T1, T2, VarMap) ->
- t_unify(t_opaque_structure(T1), T2, VarMap);
-t_unify(T, T, VarMap) ->
- {T, VarMap};
-t_unify(?union(_)=T1, ?union(_)=T2, VarMap) ->
+ VarMap;
+t_unify_table_only(?opaque(_) = T1, ?opaque(_) = T2, VarMap) ->
+ t_unify_table_only(t_opaque_structure(T1), t_opaque_structure(T2), VarMap);
+t_unify_table_only(T1, ?opaque(_) = T2, VarMap) ->
+ t_unify_table_only(T1, t_opaque_structure(T2), VarMap);
+t_unify_table_only(?opaque(_) = T1, T2, VarMap) ->
+ t_unify_table_only(t_opaque_structure(T1), T2, VarMap);
+t_unify_table_only(T, T, VarMap) ->
+ VarMap;
+t_unify_table_only(?union(_)=T1, ?union(_)=T2, VarMap) ->
{Type1, Type2} = unify_union2(T1, T2),
- t_unify(Type1, Type2, VarMap);
-t_unify(?union(_)=T1, T2, VarMap) ->
- t_unify(unify_union1(T1, T1, T2), T2, VarMap);
-t_unify(T1, ?union(_)=T2, VarMap) ->
- t_unify(T1, unify_union1(T2, T1, T2), VarMap);
-t_unify(T1, T2, _) ->
+ t_unify_table_only(Type1, Type2, VarMap);
+t_unify_table_only(?union(_)=T1, T2, VarMap) ->
+ t_unify_table_only(unify_union1(T1, T1, T2), T2, VarMap);
+t_unify_table_only(T1, ?union(_)=T2, VarMap) ->
+ t_unify_table_only(T1, unify_union1(T2, T1, T2), VarMap);
+t_unify_table_only(T1, T2, _) ->
throw({mismatch, T1, T2}).
+%% Two functions since t_unify_table_only is not symmetric.
+unify_tuple_set_and_tuple1_table_only(?tuple_set([{Arity, List}]),
+ ?tuple(Elements2, Arity, _), VarMap) ->
+ %% Can only work if the single tuple has variables at correct places.
+ unify_lists_table_only(sup_tuple_elements(List), Elements2, VarMap).
+
+unify_tuple_set_and_tuple2_table_only(?tuple(Elements2, Arity, _),
+ ?tuple_set([{Arity, List}]), VarMap) ->
+ %% Can only work if the single tuple has variables at correct places.
+ unify_lists_table_only(Elements2, sup_tuple_elements(List), VarMap).
+
+unify_lists_table_only([T1|Left1], [T2|Left2], VarMap) ->
+ NewVarMap = t_unify_table_only(T1, T2, VarMap),
+ unify_lists_table_only(Left1, Left2, NewVarMap);
+unify_lists_table_only([], [], VarMap) ->
+ VarMap.
+
unify_union2(?union(List1)=T1, ?union(List2)=T2) ->
case {unify_union(List1), unify_union(List2)} of
{{yes, Type1}, {yes, Type2}} -> {Type1, Type2};
@@ -3659,46 +3540,20 @@ unify_union(List) ->
is_opaque_type(?opaque(Elements), Opaques) ->
lists:any(fun(Opaque) -> is_opaque_type2(Opaque, Opaques) end, Elements).
-is_opaque_type2(#opaque{mod = Mod1, name = Name1, args = Args1}, Opaques) ->
+is_opaque_type2(#opaque{mod = Mod1, name = Name1, arity = Arity1}, Opaques) ->
F1 = fun(?opaque(Es)) ->
- F2 = fun(#opaque{mod = Mod, name = Name, args = Args}) ->
- is_type_name(Mod1, Name1, Args1, Mod, Name, Args)
+ F2 = fun(#opaque{mod = Mod, name = Name, arity = Arity}) ->
+ is_type_name(Mod1, Name1, Arity1, Mod, Name, Arity)
end,
lists:any(F2, Es)
end,
lists:any(F1, Opaques).
-is_type_name(Mod, Name, Args1, Mod, Name, Args2) ->
- length(Args1) =:= length(Args2);
-is_type_name(_Mod1, _Name1, _Args1, _Mod2, _Name2, _Args2) ->
+is_type_name(Mod, Name, Arity, Mod, Name, Arity) ->
+ true;
+is_type_name(_Mod1, _Name1, _Arity1, _Mod2, _Name2, _Arity2) ->
false.
-%% Two functions since t_unify is not symmetric.
-unify_tuple_set_and_tuple1(?tuple_set([{Arity, List}]),
- ?tuple(Elements2, Arity, _), VarMap) ->
- %% Can only work if the single tuple has variables at correct places.
- %% Collapse the tuple set.
- {NewElements, VarMap1} =
- unify_lists(sup_tuple_elements(List), Elements2, VarMap),
- {t_tuple(NewElements), VarMap1}.
-
-unify_tuple_set_and_tuple2(?tuple(Elements2, Arity, _),
- ?tuple_set([{Arity, List}]), VarMap) ->
- %% Can only work if the single tuple has variables at correct places.
- %% Collapse the tuple set.
- {NewElements, VarMap1} =
- unify_lists(Elements2, sup_tuple_elements(List), VarMap),
- {t_tuple(NewElements), VarMap1}.
-
-unify_lists(L1, L2, VarMap) ->
- unify_lists(L1, L2, VarMap, []).
-
-unify_lists([T1|Left1], [T2|Left2], VarMap, Acc) ->
- {NewT, NewVarMap} = t_unify(T1, T2, VarMap),
- unify_lists(Left1, Left2, NewVarMap, [NewT|Acc]);
-unify_lists([], [], VarMap, Acc) ->
- {lists:reverse(Acc), VarMap}.
-
%%t_assign_variables_to_subtype(T1, T2) ->
%% try
%% Dict = assign_vars(T1, T2, dict:new()),
@@ -3750,7 +3605,7 @@ unify_lists([], [], VarMap, Acc) ->
%% assign_vars_lists(Elements1, Elements2, Dict);
%%assign_vars(?tuple_set(_) = T, ?tuple_set(List2), Dict) ->
%% %% All Rhs tuples must already be subtypes of Lhs, so we can take
-%% %% each one separatly.
+%% %% each one separately.
%% assign_vars_lists([T || _ <- List2], List2, Dict);
%%assign_vars(?tuple(?any, ?any, ?any), ?tuple_set(_), Dict) ->
%% Dict;
@@ -3981,7 +3836,7 @@ t_subtract(?map(APairs, ADefK, ADefV) = A, ?map(_, BDefK, BDefV) = B) ->
%% * The arguments constrain A at least as much as B, i.e. that A so far
%% is a subtype of B. In that case they return false
%% * That for the particular arguments, A being a subtype of B does not
- %% hold, but the infinimum of A and B is nonempty, and by narrowing a
+ %% hold, but the infimum of A and B is nonempty, and by narrowing a
%% pair in A, we can create a type that excludes some elements in the
%% infinumum. In that case, they will return that pair.
%% * That for the particular arguments, A being a subtype of B does not
@@ -4144,7 +3999,7 @@ t_is_instance(ConcreteType, Type) ->
-spec t_do_overlap(erl_type(), erl_type()) -> boolean().
t_do_overlap(TypeA, TypeB) ->
- not (t_is_none_or_unit(t_inf(TypeA, TypeB))).
+ not (t_is_impossible(t_inf(TypeA, TypeB))).
-spec t_unopaque(erl_type()) -> erl_type().
@@ -4200,7 +4055,44 @@ t_unopaque(T, _) ->
-spec t_limit(erl_type(), integer()) -> erl_type().
t_limit(Term, K) when is_integer(K) ->
- t_limit_k(Term, K).
+ case is_limited(Term, K) of
+ true -> Term;
+ false -> t_limit_k(Term, K)
+ end.
+
+is_limited(?any, _) -> true;
+is_limited(_, K) when K =< 0 -> false;
+is_limited(?tuple(?any, ?any, ?any), _K) -> true;
+is_limited(?tuple(Elements, _Arity, _), K) ->
+ if K =:= 1 -> false;
+ true ->
+ K1 = K-1,
+ lists:all(fun(E) -> is_limited(E, K1) end, Elements)
+ end;
+is_limited(?tuple_set(_) = T, K) ->
+ lists:all(fun(Tuple) -> is_limited(Tuple, K) end, t_tuple_subtypes(T));
+is_limited(?list(Elements, Termination, _Size), K) ->
+ if K =:= 1 -> is_limited(Termination, K);
+ true -> is_limited(Termination, K - 1)
+ end
+ andalso is_limited(Elements, K - 1);
+is_limited(?function(Domain, Range), K) ->
+ is_limited(Domain, K) andalso is_limited(Range, K-1);
+is_limited(?product(Elements), K) ->
+ K1 = K-1,
+ lists:all(fun(X) -> is_limited(X, K1) end, Elements);
+is_limited(?union(Elements), K) ->
+ lists:all(fun(X) -> is_limited(X, K) end, Elements);
+is_limited(?opaque(Es), K) ->
+ lists:all(fun(#opaque{struct = S}) -> is_limited(S, K) end, set_to_list(Es));
+is_limited(?map(Pairs, DefK, DefV), K) ->
+ %% Use the fact that t_sup() does not increase the depth.
+ K1 = K - 1,
+ lists:all(fun({Key, _, Value}) ->
+ is_limited(Key, K1) andalso is_limited(Value, K1)
+ end, Pairs)
+ andalso is_limited(DefK, K1) andalso is_limited(DefV, K1);
+is_limited(_, _K) -> true.
t_limit_k(_, K) when K =< 0 -> ?any;
t_limit_k(?tuple(?any, ?any, ?any) = T, _K) -> T;
@@ -4350,8 +4242,8 @@ t_to_string(?identifier(Set), _RecDict) ->
flat_join([flat_format("~w()", [T]) || T <- set_to_list(Set)], " | ")
end;
t_to_string(?opaque(Set), RecDict) ->
- flat_join([opaque_type(Mod, Name, Args, S, RecDict) ||
- #opaque{mod = Mod, name = Name, struct = S, args = Args}
+ flat_join([opaque_type(Mod, Name, Arity, S, RecDict) ||
+ #opaque{mod = Mod, name = Name, struct = S, arity = Arity}
<- set_to_list(Set)],
" | ");
t_to_string(?matchstate(Pres, Slots), RecDict) ->
@@ -4524,19 +4416,18 @@ union_sequence(Types, RecDict) ->
flat_join(List, " | ").
-ifdef(DEBUG).
-opaque_type(Mod, Name, _Args, S, RecDict) ->
- ArgsString = comma_sequence(_Args, RecDict),
+opaque_type(Mod, Name, Arity, S, RecDict) ->
String = t_to_string(S, RecDict),
- opaque_name(Mod, Name, ArgsString) ++ "[" ++ String ++ "]".
+ opaque_name(Mod, Name, Arity) ++ "[" ++ String ++ "]".
-else.
-opaque_type(Mod, Name, Args, _S, RecDict) ->
- ArgsString = comma_sequence(Args, RecDict),
- opaque_name(Mod, Name, ArgsString).
+opaque_type(Mod, Name, Arity, _S, _RecDict) ->
+ opaque_name(Mod, Name, Arity).
-endif.
-opaque_name(Mod, Name, Extra) ->
+opaque_name(Mod, Name, Arity) ->
S = mod_name(Mod, Name),
- flat_format("~ts(~ts)", [S, Extra]).
+ Args = lists:join($,, lists:duplicate(Arity, $_)),
+ flat_format("~ts(~ts)", [S, Args]).
mod_name(Mod, Name) ->
flat_format("~w:~tw", [Mod, Name]).
@@ -4559,6 +4450,7 @@ mod_name(Mod, Name) ->
[erl_type()], type_names()}.
-type mod_type_table() :: ets:tid().
-type mod_records() :: dict:dict(module(), type_table()).
+-type exported_type_table() :: ets:tid().
-record(cache,
{
types = maps:new() :: #{cache_key() => {erl_type(), expand_limit()}},
@@ -4567,7 +4459,7 @@ mod_name(Mod, Name) ->
-opaque cache() :: #cache{}.
--spec t_from_form(parse_form(), sets:set(mfa()), site(), mod_type_table(),
+-spec t_from_form(parse_form(), exported_type_table(), site(), mod_type_table(),
var_table(), cache()) -> {erl_type(), cache()}.
t_from_form(Form, ExpTypes, Site, RecDict, VarTab, Cache) ->
@@ -4592,12 +4484,12 @@ t_from_form_without_remote(Form, Site, TypeTable) ->
-type expand_depth() :: integer().
-record(from_form, {site :: site(),
- xtypes :: sets:set(mfa()) | 'replace_by_none',
+ xtypes :: exported_type_table() | 'replace_by_none',
mrecs :: 'undefined' | mod_type_table(),
vtab :: var_table(),
tnames :: type_names()}).
--spec t_from_form_check_remote(parse_form(), sets:set(mfa()), site(),
+-spec t_from_form_check_remote(parse_form(), exported_type_table(), site(),
mod_type_table()) -> 'ok'.
t_from_form_check_remote(Form, ExpTypes, Site, RecDict) ->
State = #from_form{site = Site,
@@ -4618,7 +4510,7 @@ t_from_form_check_remote(Form, ExpTypes, Site, RecDict) ->
%% types balanced (unions will otherwise collapse to any()) by limiting
%% the depth the same way as t_limit/2 does.
--spec t_from_form1(parse_form(), sets:set(mfa()) | 'replace_by_none',
+-spec t_from_form1(parse_form(), exported_type_table() | 'replace_by_none',
site(), 'undefined' | mod_type_table(), var_table(),
cache()) -> {erl_type(), cache()}.
@@ -4647,6 +4539,10 @@ initial_typenames({type, MTA, _File}) -> [{type, MTA}];
initial_typenames({spec, _MFA, _File}) -> [];
initial_typenames({record, _MRA, _File}) -> [].
+%% 4 is the maximal depth used by any Dialyzer module
+%% (5 is used internally).
+-define(TYPE_LIMIT, 4).
+
from_form_loop(Form, State, D, Limit, C, T0) ->
{T1, L1, C1} = from_form(Form, State, D, Limit, C),
Delta = Limit - L1,
@@ -4656,6 +4552,9 @@ from_form_loop(Form, State, D, Limit, C, T0) ->
Delta * 8 > Limit ->
%% Save some time by assuming next depth will exceed the limit.
{T1, C1};
+ D =:= ?TYPE_LIMIT ->
+ %% No need to go deeper than necessary.
+ {T1, C1};
true ->
D1 = D + 1,
from_form_loop(Form, State, D1, Limit, C1, T1)
@@ -4963,7 +4862,7 @@ remote_from_form(Anno, RemMod, Name, Args, S, D, L, C) ->
self() ! {self(), ext_types, ext_types_message(MFA, Anno, Site)},
{t_any(), L, C};
{RemDict, C1} ->
- case sets:is_element(MFA, ET) of
+ case ets:member(ET, MFA) of
true ->
RemType = {type, MFA},
case can_unfold_more(RemType, TypeNames) of
@@ -5169,7 +5068,7 @@ separate_key(?union(List)) ->
lists:append([separate_key(K) || K <- List, not t_is_none(K)]);
separate_key(Key) -> [Key].
-%% Sorts, combines non-singleton pairs, and applies precendence and
+%% Sorts, combines non-singleton pairs, and applies precedence and
%% mandatoriness rules.
map_from_form([], ShdwPs, MKs, Pairs, DefK, DefV) ->
verify_possible(MKs, ShdwPs),
@@ -5234,7 +5133,7 @@ recur_limit(Fun, D, L, TypeName, TypeNames) ->
Fun(D, L)
end.
--spec t_check_record_fields(parse_form(), sets:set(mfa()), site(),
+-spec t_check_record_fields(parse_form(), exported_type_table(), site(),
mod_type_table(), var_table(), cache()) -> cache().
t_check_record_fields(Form, ExpTypes, Site, RecDict, VarTable, Cache) ->
@@ -5465,7 +5364,7 @@ t_form_to_string({type, _Anno, Name, []} = T) ->
V = var_table__new(),
C = cache__new(),
State = #from_form{site = Site,
- xtypes = sets:new(),
+ xtypes = replace_by_none,
mrecs = 'undefined',
vtab = V,
tnames = []},
@@ -5813,3 +5712,130 @@ handle_base(Unit, Neg) ->
var_table__new() ->
maps:new().
+
+%%=============================================================================
+%%
+%% Utilities for finding a module's type dependencies
+%%
+%%=============================================================================
+
+
+-spec module_type_deps_of_type_defs(type_table()) -> [module()].
+
+module_type_deps_of_type_defs(TypeTable) ->
+ ModuleTypeDependencies =
+ [module_type_deps_of_entry(TypeTableEntry)
+ || TypeTableEntry <- maps:to_list(TypeTable)],
+ lists:append(ModuleTypeDependencies).
+
+-spec module_type_deps_of_entry(
+ {type_key(), type_value()}
+ | {record_key(), record_value()}) -> [module()].
+
+module_type_deps_of_entry({{'type', _TypeName, _A}, {{_FromM, _FileLine, AbstractType, _ArgNames}, _}}) ->
+ type_form_to_remote_modules(AbstractType);
+
+module_type_deps_of_entry({{'opaque', _TypeName, _A}, {{_FromM, _FileLine, AbstractType, _ArgNames}, _}}) ->
+ type_form_to_remote_modules(AbstractType);
+
+module_type_deps_of_entry({{'record', _Name}, {_FileLine, SizesAndFields}}) ->
+ AllFields = lists:append([Fields || {_Size, Fields} <- SizesAndFields]),
+ FieldTypes = [AbstractType || {_, AbstractType, _} <- AllFields],
+ type_form_to_remote_modules(FieldTypes).
+
+%% Whilst this function is depth-limited, it should be limited in precisely
+%% the same way as Dialyzer's other analyses - i.e. it should only ignore
+%% sub-components of types Diaylzer wouldn't explore anyway
+-spec type_form_to_remote_modules(parse_form() | [parse_form()]) -> [module()].
+
+type_form_to_remote_modules([]) ->
+ [];
+
+type_form_to_remote_modules([_|_] = Forms) ->
+ D = ?EXPAND_DEPTH,
+ L = ?EXPAND_LIMIT,
+ {_, Mods} = list_get_modules_mentioned(Forms, D, L, []),
+ lists:usort(Mods);
+
+type_form_to_remote_modules(Form) ->
+ D = ?EXPAND_DEPTH,
+ L = ?EXPAND_LIMIT,
+ {_, Mods} = get_modules_mentioned(Form, D, L, []),
+ lists:usort(Mods).
+
+-spec get_modules_mentioned(TypeForm :: parse_form(), expand_depth(), expand_limit(), Acc :: [module()]) -> {expand_depth(), [module()]}.
+
+get_modules_mentioned(_, D, L, Acc) when D =< 0 ; L =< 0 ->
+ {L, Acc};
+get_modules_mentioned({var, _L, '_'}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({var, _L, _Name}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({ann_type, _L, [_Var, Type]}, D, L, Acc) ->
+ get_modules_mentioned(Type, D, L, Acc);
+get_modules_mentioned({paren_type, _L, [Type]}, D, L, Acc) ->
+ get_modules_mentioned(Type, D, L, Acc);
+get_modules_mentioned({atom, _L, _Atom}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({integer, _L, _Int}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({char, _L, _Char}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({op, _L, _Op, _Arg}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({op, _L, _Op, _Arg1, _Arg2}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({type, _L, 'fun', [{type, _, any}, Range]}, D, L, Acc) ->
+ get_modules_mentioned(Range, D - 1, L - 1, Acc);
+get_modules_mentioned({type, _L, 'fun', [{type, _, product, Domain}, Range]}, D, L, Acc) ->
+ {L1, Acc1} = list_get_modules_mentioned(Domain, D, L, Acc),
+ get_modules_mentioned(Range, D, L1, Acc1);
+get_modules_mentioned({type, _L, list, [Type]}, D, L, Acc) ->
+ get_modules_mentioned(Type, D - 1, L - 1, Acc);
+get_modules_mentioned({type, _L, map, any}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({type, _L, map, List}, D0, L, Acc) ->
+ fun PairsFromForm(_, L1, Acc1) when L1 =< 0 -> Acc1;
+ PairsFromForm([], L1, Acc1) -> {L1, Acc1};
+ PairsFromForm([{type, _, _Oper, [KF, VF]}|T], L1, Acc1) ->
+ D = D0 - 1,
+ {L2, Acc2} = get_modules_mentioned(KF, D, L1, Acc1),
+ {L3, Acc3} = get_modules_mentioned(VF, D, L2, Acc2),
+ PairsFromForm(T, L3 - 1, Acc3)
+ end(List, L, Acc);
+get_modules_mentioned({type, _L, nonempty_list, [Type]}, D, L, Acc) ->
+ get_modules_mentioned(Type, D, L - 1, Acc);
+get_modules_mentioned({type, _L, nonempty_improper_list, [Cont, Term]}, D, L, Acc) ->
+ {L1, Acc1} = get_modules_mentioned(Cont, D, L - 1, Acc),
+ get_modules_mentioned(Term, D, L1, Acc1);
+get_modules_mentioned({type, _L, nonempty_maybe_improper_list, [Cont, Term]}, D, L, Acc) ->
+ {L1, Acc1} = get_modules_mentioned(Cont, D, L - 1, Acc),
+ get_modules_mentioned(Term, D, L1, Acc1);
+get_modules_mentioned({type, _L, maybe_improper_list, [Content, Termination]}, D, L, Acc) ->
+ {L1, Acc1} = get_modules_mentioned(Content, D, L - 1, Acc),
+ get_modules_mentioned(Termination, D, L1, Acc1);
+get_modules_mentioned({type, _L, product, Elements}, D, L, Acc) ->
+ list_get_modules_mentioned(Elements, D - 1, L, Acc);
+get_modules_mentioned({type, _L, range, [_From, _To]}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({type, _L, tuple, any}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({type, _L, tuple, Args}, D, L, Acc) ->
+ list_get_modules_mentioned(Args, D - 1, L, Acc);
+get_modules_mentioned({type, _L, union, Args}, D, L, Acc) ->
+ list_get_modules_mentioned(Args, D, L, Acc);
+get_modules_mentioned({remote_type, _L, [{atom, _, Module}, {atom, _, _Type}, Args]}, D, L, Acc) ->
+ Acc1 = [Module|Acc],
+ list_get_modules_mentioned(Args, D, L, Acc1);
+get_modules_mentioned({user_type, _L, _Name, Args}, D, L, Acc) ->
+ list_get_modules_mentioned(Args, D, L, Acc);
+get_modules_mentioned({type, _L, _Name, []}, _D, L, Acc) ->
+ {L, Acc};
+get_modules_mentioned({type, _L, _Name, Args}, D, L, Acc) ->
+ list_get_modules_mentioned(Args, D, L, Acc).
+
+list_get_modules_mentioned([], _D, L, Acc) ->
+ {L, Acc};
+list_get_modules_mentioned([H|Tail], D, L, Acc) ->
+ {L1, Acc1} = get_modules_mentioned(H, D, L - 1, Acc),
+ list_get_modules_mentioned(Tail, D, L1, Acc1).
diff --git a/lib/dialyzer/src/typer.erl b/lib/dialyzer/src/typer.erl
index 69a622db2d..9fa2cd78a2 100644
--- a/lib/dialyzer/src/typer.erl
+++ b/lib/dialyzer/src/typer.erl
@@ -17,6 +17,9 @@
%% Author(s) : The first version of typer was written by Bingwen He
%% with guidance from Kostis Sagonas and Tobias Lindahl.
%% Since June 2008 typer is maintained by Kostis Sagonas.
+%% On 2022, Brujo, Pablo, and Mackenzie from NextRoll
+%% started working on the rebar3 plugin for typer and,
+%% with that in mind, split typer and typer_core apart.
%% Description : An Erlang/OTP application that shows type information
%% for Erlang modules to the user. Additionally, it can
%% annotate the code of files with such type information.
@@ -31,565 +34,41 @@
-define(SHOW, show).
-define(SHOW_EXPORTED, show_exported).
-define(ANNOTATE, annotate).
+-define(ANNOTATE_IN_PLACE, annotate_in_place).
-define(ANNOTATE_INC_FILES, annotate_inc_files).
--type mode() :: ?SHOW | ?SHOW_EXPORTED | ?ANNOTATE | ?ANNOTATE_INC_FILES.
-
%%-----------------------------------------------------------------------
--type files() :: [file:filename()].
--type callgraph() :: dialyzer_callgraph:callgraph().
--type codeserver() :: dialyzer_codeserver:codeserver().
--type plt() :: dialyzer_plt:plt().
-
--record(analysis,
- {mode :: mode() | 'undefined',
- macros = [] :: [{atom(), term()}],
- includes = [] :: files(),
- codeserver = dialyzer_codeserver:new():: codeserver(),
- callgraph = dialyzer_callgraph:new() :: callgraph(),
- files = [] :: files(), % absolute names
- plt = none :: 'none' | file:filename(),
- no_spec = false :: boolean(),
- show_succ = false :: boolean(),
- %% For choosing between specs or edoc @spec comments
- edoc = false :: boolean(),
- %% Files in 'fms' are compilable with option 'to_pp'; we keep them
- %% as {FileName, ModuleName} in case the ModuleName is different
- fms = [] :: [{file:filename(), module()}],
- ex_func = map__new() :: map_dict(),
- record = map__new() :: map_dict(),
- func = map__new() :: map_dict(),
- inc_func = map__new() :: map_dict(),
- trust_plt = dialyzer_plt:new() :: plt()}).
--type analysis() :: #analysis{}.
-
--record(args, {files = [] :: files(),
- files_r = [] :: files(),
- trusted = [] :: files()}).
--type args() :: #args{}.
-
-%%--------------------------------------------------------------------
-
-spec start() -> no_return().
start() ->
_ = io:setopts(standard_error, [{encoding,unicode}]),
_ = io:setopts([{encoding,unicode}]),
- {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),
- %% io:format("All_Files: ~tp\n", [All_Files]),
- Analysis3 = Analysis2#analysis{files = All_Files},
- 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"),
+ ok = typer_core:run(process_cl_args()),
erlang:halt(0).
%%--------------------------------------------------------------------
-
--spec extract(analysis(), files()) -> analysis().
-
-extract(#analysis{macros = Macros,
- includes = Includes,
- trust_plt = TrustPLT} = Analysis, TrustedFiles) ->
- %% io:format("--- Extracting trusted typer_info... "),
- Ds = [{d, Name, Value} || {Name, Value} <- Macros],
- CodeServer = dialyzer_codeserver:new(),
- Fun =
- fun(File, CS) ->
- %% We include one more dir; the one above the one we are trusting
- %% E.g, for /home/tests/typer_ann/test.ann.erl, we should include
- %% /home/tests/ rather than /home/tests/typer_ann/
- AllIncludes = [filename:dirname(filename:dirname(File)) | Includes],
- Is = [{i, Dir} || Dir <- AllIncludes],
- CompOpts = dialyzer_utils:src_compiler_opts() ++ Is ++ Ds,
- case dialyzer_utils:get_core_from_src(File, CompOpts) of
- {ok, Core} ->
- case dialyzer_utils:get_record_and_type_info(Core) of
- {ok, RecDict} ->
- Mod = list_to_atom(filename:basename(File, ".erl")),
- case dialyzer_utils:get_spec_info(Mod, Core, RecDict) of
- {ok, SpecDict, CbDict} ->
- CS1 = dialyzer_codeserver:store_temp_records(Mod, RecDict, CS),
- dialyzer_codeserver:store_temp_contracts(Mod, SpecDict, CbDict, CS1);
- {error, Reason} -> compile_error([Reason])
- end;
- {error, Reason} -> compile_error([Reason])
- end;
- {error, Reason} -> compile_error(Reason)
- end
- end,
- CodeServer1 = lists:foldl(Fun, CodeServer, TrustedFiles),
- %% Process remote types
- NewCodeServer =
- try
- CodeServer2 =
- dialyzer_utils:merge_types(CodeServer1,
- TrustPLT), % XXX change to the PLT?
- NewExpTypes = dialyzer_codeserver:get_temp_exported_types(CodeServer1),
- case sets:size(NewExpTypes) of 0 -> ok end,
- CodeServer3 = dialyzer_codeserver:finalize_exported_types(NewExpTypes, CodeServer2),
- CodeServer4 = dialyzer_utils:process_record_remote_types(CodeServer3),
- dialyzer_contracts:process_contract_remote_types(CodeServer4)
- catch
- throw:{error, ErrorMsg} ->
- compile_error(ErrorMsg)
- end,
- %% Create TrustPLT
- ContractsDict = dialyzer_codeserver:get_contracts(NewCodeServer),
- Contracts = orddict:from_list(dict:to_list(ContractsDict)),
- NewTrustPLT = dialyzer_plt:insert_contract_list(TrustPLT, Contracts),
- Analysis#analysis{trust_plt = NewTrustPLT}.
-
-%%--------------------------------------------------------------------
-
--spec get_type_info(analysis()) -> analysis().
-
-get_type_info(#analysis{callgraph = CallGraph,
- trust_plt = TrustPLT,
- codeserver = CodeServer} = Analysis) ->
- StrippedCallGraph = remove_external(CallGraph, TrustPLT),
- %% io:format("--- Analyzing callgraph... "),
- try
- NewPlt = dialyzer_succ_typings:analyze_callgraph(StrippedCallGraph,
- TrustPLT,
- CodeServer),
- Analysis#analysis{callgraph = StrippedCallGraph, trust_plt = NewPlt}
- catch
- error:What:Stacktrace ->
- fatal_error(io_lib:format("Analysis failed with message: ~tp",
- [{What, Stacktrace}]));
- throw:{dialyzer_succ_typing_error, Msg} ->
- fatal_error(io_lib:format("Analysis failed with message: ~ts", [Msg]))
- end.
-
--spec remove_external(callgraph(), plt()) -> callgraph().
-
-remove_external(CallGraph, PLT) ->
- {StrippedCG0, Ext} = dialyzer_callgraph:remove_external(CallGraph),
- case get_external(Ext, PLT) of
- [] -> ok;
- Externals ->
- msg(io_lib:format(" Unknown functions: ~tp\n", [lists:usort(Externals)])),
- ExtTypes = rcv_ext_types(),
- case ExtTypes of
- [] -> ok;
- _ -> msg(io_lib:format(" Unknown types: ~tp\n", [ExtTypes]))
- end
- end,
- StrippedCG0.
-
--spec get_external([{mfa(), mfa()}], plt()) -> [mfa()].
-
-get_external(Exts, Plt) ->
- Fun = fun ({_From, To = {M, F, A}}, Acc) ->
- case dialyzer_plt:contains_mfa(Plt, To) of
- false ->
- case erl_bif_types:is_known(M, F, A) of
- true -> Acc;
- false -> [To|Acc]
- end;
- true -> Acc
- end
- end,
- lists:foldl(Fun, [], Exts).
-
-%%--------------------------------------------------------------------
-%% Showing type information or annotating files with such information.
-%%--------------------------------------------------------------------
-
--define(TYPER_ANN_DIR, "typer_ann").
-
--type line() :: non_neg_integer().
--type fa() :: {atom(), arity()}.
--type func_info() :: {line(), atom(), arity()}.
-
--record(info, {records = maps:new() :: erl_types:type_table(),
- functions = [] :: [func_info()],
- types = map__new() :: map_dict(),
- edoc = false :: boolean()}).
--record(inc, {map = map__new() :: map_dict(), filter = [] :: files()}).
--type inc() :: #inc{}.
-
--spec show_or_annotate(analysis()) -> 'ok'.
-
-show_or_annotate(#analysis{mode = Mode, fms = Files} = Analysis) ->
- case Mode of
- ?SHOW -> show(Analysis);
- ?SHOW_EXPORTED -> show(Analysis);
- ?ANNOTATE ->
- Fun = fun ({File, Module}) ->
- Info = get_final_info(File, Module, Analysis),
- write_typed_file(File, Info)
- end,
- lists:foreach(Fun, Files);
- ?ANNOTATE_INC_FILES ->
- IncInfo = write_and_collect_inc_info(Analysis),
- write_inc_files(IncInfo)
- end.
-
-write_and_collect_inc_info(Analysis) ->
- Fun = fun ({File, Module}, Inc) ->
- Info = get_final_info(File, Module, Analysis),
- write_typed_file(File, Info),
- IncFuns = get_functions(File, Analysis),
- collect_imported_functions(IncFuns, Info#info.types, Inc)
- end,
- NewInc = lists:foldl(Fun, #inc{}, Analysis#analysis.fms),
- clean_inc(NewInc).
-
-write_inc_files(Inc) ->
- Fun =
- fun (File) ->
- Val = map__lookup(File, Inc#inc.map),
- %% Val is function with its type info
- %% in form [{{Line,F,A},Type}]
- Functions = [Key || {Key, _} <- Val],
- Val1 = [{{F,A},Type} || {{_Line,F,A},Type} <- Val],
- Info = #info{types = map__from_list(Val1),
- records = maps:new(),
- %% Note we need to sort functions here!
- functions = lists:keysort(1, Functions)},
- %% io:format("Types ~tp\n", [Info#info.types]),
- %% io:format("Functions ~tp\n", [Info#info.functions]),
- %% io:format("Records ~tp\n", [Info#info.records]),
- write_typed_file(File, Info)
- end,
- lists:foreach(Fun, dict:fetch_keys(Inc#inc.map)).
-
-show(Analysis) ->
- Fun = fun ({File, Module}) ->
- Info = get_final_info(File, Module, Analysis),
- show_type_info(File, Info)
- end,
- lists:foreach(Fun, Analysis#analysis.fms).
-
-get_final_info(File, Module, Analysis) ->
- Records = get_records(File, Analysis),
- Types = get_types(Module, Analysis, Records),
- Functions = get_functions(File, Analysis),
- Edoc = Analysis#analysis.edoc,
- #info{records = Records, functions = Functions, types = Types, edoc = Edoc}.
-
-collect_imported_functions(Functions, Types, Inc) ->
- %% Coming from other sourses, including:
- %% FIXME: How to deal with yecc-generated file????
- %% --.yrl (yecc-generated file)???
- %% -- yeccpre.hrl (yecc-generated file)???
- %% -- other cases
- Fun = fun ({File, _} = Obj, I) ->
- case is_yecc_gen(File, I) of
- {true, NewI} -> NewI;
- {false, NewI} ->
- check_imported_functions(Obj, NewI, Types)
- end
- end,
- lists:foldl(Fun, Inc, Functions).
-
--spec is_yecc_gen(file:filename(), inc()) -> {boolean(), inc()}.
-
-is_yecc_gen(File, #inc{filter = Fs} = Inc) ->
- case lists:member(File, Fs) of
- true -> {true, Inc};
- false ->
- case filename:extension(File) of
- ".yrl" ->
- Rootname = filename:rootname(File, ".yrl"),
- Obj = Rootname ++ ".erl",
- case lists:member(Obj, Fs) of
- true -> {true, Inc};
- false ->
- NewInc = Inc#inc{filter = [Obj|Fs]},
- {true, NewInc}
- end;
- _ ->
- case filename:basename(File) of
- "yeccpre.hrl" -> {true, Inc};
- _ -> {false, Inc}
- end
- end
- end.
-
-check_imported_functions({File, {Line, F, A}}, Inc, Types) ->
- IncMap = Inc#inc.map,
- FA = {F, A},
- Type = get_type_info(FA, Types),
- case map__lookup(File, IncMap) of
- none -> %% File is not added. Add it
- Obj = {File,[{FA, {Line, Type}}]},
- NewMap = map__insert(Obj, IncMap),
- Inc#inc{map = NewMap};
- Val -> %% File is already in. Check.
- case lists:keyfind(FA, 1, Val) of
- false ->
- %% Function is not in; add it
- Obj = {File, Val ++ [{FA, {Line, Type}}]},
- NewMap = map__insert(Obj, IncMap),
- Inc#inc{map = NewMap};
- Type ->
- %% Function is in and with same type
- Inc;
- _ ->
- %% Function is in but with diff type
- inc_warning(FA, File),
- Elem = lists:keydelete(FA, 1, Val),
- NewMap = case Elem of
- [] -> map__remove(File, IncMap);
- _ -> map__insert({File, Elem}, IncMap)
- end,
- Inc#inc{map = NewMap}
- end
- end.
-
-inc_warning({F, A}, File) ->
- io:format(" ***Warning: Skip function ~tp/~p ", [F, A]),
- io:format("in file ~tp because of inconsistent type\n", [File]).
-
-clean_inc(Inc) ->
- Inc1 = remove_yecc_generated_file(Inc),
- normalize_obj(Inc1).
-
-remove_yecc_generated_file(#inc{filter = Filter} = Inc) ->
- Fun = fun (Key, #inc{map = Map} = I) ->
- I#inc{map = map__remove(Key, Map)}
- end,
- lists:foldl(Fun, Inc, Filter).
-
-normalize_obj(TmpInc) ->
- Fun = fun (Key, Val, Inc) ->
- NewVal = [{{Line,F,A},Type} || {{F,A},{Line,Type}} <- Val],
- map__insert({Key, NewVal}, Inc)
- end,
- TmpInc#inc{map = map__fold(Fun, map__new(), TmpInc#inc.map)}.
-
-get_records(File, Analysis) ->
- map__lookup(File, Analysis#analysis.record).
-
-get_types(Module, Analysis, Records) ->
- TypeInfoPlt = Analysis#analysis.trust_plt,
- TypeInfo =
- case dialyzer_plt:lookup_module(TypeInfoPlt, Module) of
- none -> [];
- {value, List} -> List
- end,
- CodeServer = Analysis#analysis.codeserver,
- TypeInfoList =
- case Analysis#analysis.show_succ of
- true ->
- [convert_type_info(I) || I <- TypeInfo];
- false ->
- [get_type(I, CodeServer, Records) || I <- TypeInfo]
- end,
- map__from_list(TypeInfoList).
-
-convert_type_info({{_M, F, A}, Range, Arg}) ->
- {{F, A}, {Range, Arg}}.
-
-get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, Records) ->
- case dialyzer_codeserver:lookup_mfa_contract(MFA, CodeServer) of
- error ->
- {{F, A}, {Range, Arg}};
- {ok, {_FileLine, Contract, _Xtra}} ->
- Sig = erl_types:t_fun(Arg, Range),
- case dialyzer_contracts:check_contract(Contract, Sig) of
- ok -> {{F, A}, {contract, Contract}};
- {range_warnings, _} ->
- {{F, A}, {contract, Contract}};
- {error, {overlapping_contract, []}} ->
- {{F, A}, {contract, Contract}};
- {error, invalid_contract} ->
- CString = dialyzer_contracts:contract_to_string(Contract),
- SigString = dialyzer_utils:format_sig(Sig, Records),
- Msg = io_lib:format("Error in contract of function ~w:~tw/~w\n"
- "\t The contract is: " ++ CString ++ "\n" ++
- "\t but the inferred signature is: ~ts",
- [M, F, A, SigString]),
- fatal_error(Msg);
- {error, ErrorStr} when is_list(ErrorStr) -> % ErrorStr is a string()
- Msg = io_lib:format("Error in contract of function ~w:~tw/~w: ~ts",
- [M, F, A, ErrorStr]),
- fatal_error(Msg)
- end
- end.
-
-get_functions(File, Analysis) ->
- case Analysis#analysis.mode of
- ?SHOW ->
- Funcs = map__lookup(File, Analysis#analysis.func),
- Inc_Funcs = map__lookup(File, Analysis#analysis.inc_func),
- remove_module_info(Funcs) ++ normalize_incFuncs(Inc_Funcs);
- ?SHOW_EXPORTED ->
- Ex_Funcs = map__lookup(File, Analysis#analysis.ex_func),
- remove_module_info(Ex_Funcs);
- ?ANNOTATE ->
- Funcs = map__lookup(File, Analysis#analysis.func),
- remove_module_info(Funcs);
- ?ANNOTATE_INC_FILES ->
- map__lookup(File, Analysis#analysis.inc_func)
- end.
-
-normalize_incFuncs(Functions) ->
- [FunInfo || {_FileName, FunInfo} <- Functions].
-
--spec remove_module_info([func_info()]) -> [func_info()].
-
-remove_module_info(FunInfoList) ->
- F = fun ({_,module_info,0}) -> false;
- ({_,module_info,1}) -> false;
- ({Line,F,A}) when is_integer(Line), is_atom(F), is_integer(A) -> true
- end,
- lists:filter(F, FunInfoList).
-
-write_typed_file(File, Info) ->
- io:format(" Processing file: ~tp\n", [File]),
- Dir = filename:dirname(File),
- RootName = filename:basename(filename:rootname(File)),
- Ext = filename:extension(File),
- TyperAnnDir = filename:join(Dir, ?TYPER_ANN_DIR),
- TmpNewFilename = lists:concat([RootName, ".ann", Ext]),
- NewFileName = filename:join(TyperAnnDir, TmpNewFilename),
- case file:make_dir(TyperAnnDir) of
- {error, Reason} ->
- case Reason of
- eexist -> %% TypEr dir exists; remove old typer files if they exist
- case file:delete(NewFileName) of
- ok -> ok;
- {error, enoent} -> ok;
- {error, _} ->
- Msg = io_lib:format("Error in deleting file ~ts\n", [NewFileName]),
- fatal_error(Msg)
- end,
- write_typed_file(File, Info, NewFileName);
- enospc ->
- Msg = io_lib:format("Not enough space in ~tp\n", [Dir]),
- fatal_error(Msg);
- eacces ->
- Msg = io_lib:format("No write permission in ~tp\n", [Dir]),
- fatal_error(Msg);
- _ ->
- Msg = io_lib:format("Unhandled error ~ts when writing ~tp\n",
- [Reason, Dir]),
- fatal_error(Msg)
- end;
- ok -> %% Typer dir does NOT exist
- write_typed_file(File, Info, NewFileName)
- end.
-
-write_typed_file(File, Info, NewFileName) ->
- {ok, Binary} = file:read_file(File),
- Chars = unicode:characters_to_list(Binary),
- write_typed_file(Chars, NewFileName, Info, 1, []),
- io:format(" Saved as: ~tp\n", [NewFileName]).
-
-write_typed_file(Chars, File, #info{functions = []}, _LNo, _Acc) ->
- ok = file:write_file(File, unicode:characters_to_binary(Chars), [append]);
-write_typed_file([Ch|Chs] = Chars, File, Info, LineNo, Acc) ->
- [{Line,F,A}|RestFuncs] = Info#info.functions,
- case Line of
- 1 -> %% This will happen only for inc files
- ok = raw_write(F, A, Info, File, []),
- NewInfo = Info#info{functions = RestFuncs},
- NewAcc = [],
- write_typed_file(Chars, File, NewInfo, Line, NewAcc);
- _ ->
- case Ch of
- 10 ->
- NewLineNo = LineNo + 1,
- {NewInfo, NewAcc} =
- case NewLineNo of
- Line ->
- ok = raw_write(F, A, Info, File, [Ch|Acc]),
- {Info#info{functions = RestFuncs}, []};
- _ ->
- {Info, [Ch|Acc]}
- end,
- write_typed_file(Chs, File, NewInfo, NewLineNo, NewAcc);
- _ ->
- write_typed_file(Chs, File, Info, LineNo, [Ch|Acc])
- end
- end.
-
-raw_write(F, A, Info, File, Content) ->
- TypeInfo = get_type_string(F, A, Info, file),
- ContentList = lists:reverse(Content) ++ TypeInfo ++ "\n",
- ContentBin = unicode:characters_to_binary(ContentList),
- file:write_file(File, ContentBin, [append]).
-
-get_type_string(F, A, Info, Mode) ->
- Type = get_type_info({F,A}, Info#info.types),
- TypeStr =
- case Type of
- {contract, C} ->
- dialyzer_contracts:contract_to_string(C);
- {RetType, ArgType} ->
- Sig = erl_types:t_fun(ArgType, RetType),
- dialyzer_utils:format_sig(Sig, Info#info.records)
- end,
- case Info#info.edoc of
- false ->
- case {Mode, Type} of
- {file, {contract, _}} -> "";
- _ ->
- Prefix = lists:concat(["-spec ", erl_types:atom_to_string(F)]),
- lists:concat([Prefix, TypeStr, "."])
- end;
- true ->
- Prefix = lists:concat(["%% @spec ", F]),
- lists:concat([Prefix, TypeStr, "."])
- end.
-
-show_type_info(File, Info) ->
- io:format("\n%% File: ~tp\n%% ", [File]),
- OutputString = lists:concat(["~.", length(File)+8, "c~n"]),
- io:fwrite(OutputString, [$-]),
- Fun = fun ({_LineNo, F, A}) ->
- TypeInfo = get_type_string(F, A, Info, show),
- io:format("~ts\n", [TypeInfo])
- end,
- lists:foreach(Fun, Info#info.functions).
-
-get_type_info(Func, Types) ->
- case map__lookup(Func, Types) of
- none ->
- %% Note: Typeinfo of any function should exist in
- %% the result offered by dialyzer, otherwise there
- %% *must* be something wrong with the analysis
- Msg = io_lib:format("No type info for function: ~tp\n", [Func]),
- fatal_error(Msg);
- {contract, _Fun} = C -> C;
- {_RetType, _ArgType} = RA -> RA
- end.
-
-%%--------------------------------------------------------------------
%% Processing of command-line options and arguments.
%%--------------------------------------------------------------------
--spec process_cl_args() -> {args(), analysis()}.
+-spec process_cl_args() -> typer_core:opts().
process_cl_args() ->
ArgList = init:get_plain_arguments(),
%% io:format("Args is ~tp\n", [ArgList]),
- {Args, Analysis} = analyze_args(ArgList, #args{}, #analysis{}),
+ Opts = analyze_args(ArgList, #{}),
%% if the mode has not been set, set it to the default mode (show)
- {Args, case Analysis#analysis.mode of
- undefined -> Analysis#analysis{mode = ?SHOW};
- Mode when is_atom(Mode) -> Analysis
- end}.
+ case Opts of
+ #{mode := _} -> Opts;
+ Opts -> Opts#{mode => ?SHOW}
+ end.
-analyze_args([], Args, Analysis) ->
- {Args, Analysis};
-analyze_args(ArgList, Args, Analysis) ->
+analyze_args([], Opts) ->
+ Opts;
+analyze_args(ArgList, Opts) ->
{Result, Rest} = cl(ArgList),
- {NewArgs, NewAnalysis} = analyze_result(Result, Args, Analysis),
- analyze_args(Rest, NewArgs, NewAnalysis).
+ NewOpts = analyze_result(Result, Opts),
+ analyze_args(Rest, NewOpts).
cl(["-h"|_]) -> help_message();
cl(["--help"|_]) -> help_message();
@@ -603,21 +82,16 @@ cl(["--show_success_typings"|Opts]) -> {show_succ, Opts};
cl(["--show-success-typings"|Opts]) -> {show_succ, Opts};
cl(["--annotate"|Opts]) -> {{mode, ?ANNOTATE}, Opts};
cl(["--annotate-inc-files"|Opts]) -> {{mode, ?ANNOTATE_INC_FILES}, Opts};
+cl(["--annotate-in-place"|Opts]) -> {{mode, ?ANNOTATE_IN_PLACE}, Opts};
cl(["--no_spec"|Opts]) -> {no_spec, Opts};
cl(["--plt",Plt|Opts]) -> {{plt, Plt}, Opts};
+cl(["-D"|_Opts]) -> fatal_error("no variable name specified after -D");
cl(["-D"++Def|Opts]) ->
- case Def of
- "" -> fatal_error("no variable name specified after -D");
- _ ->
- DefPair = process_def_list(re:split(Def, "=", [{return, list}, unicode])),
- {{def, DefPair}, Opts}
- end;
+ DefPair = process_def_list(re:split(Def, "=", [{return, list}, unicode])),
+ {{def, DefPair}, Opts};
cl(["-I",Dir|Opts]) -> {{inc, Dir}, Opts};
-cl(["-I"++Dir|Opts]) ->
- case Dir of
- "" -> fatal_error("no include directory specified after -I");
- _ -> {{inc, Dir}, Opts}
- end;
+cl(["-I"|_Opts]) -> fatal_error("no include directory specified after -I");
+cl(["-I"++Dir|Opts]) -> {{inc, Dir}, Opts};
cl(["-T"|Opts]) ->
{Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
case Files of
@@ -630,7 +104,7 @@ cl(["-r"|Opts]) ->
cl(["-pa",Dir|Opts]) -> {{pa,Dir}, Opts};
cl(["-pz",Dir|Opts]) -> {{pz,Dir}, Opts};
cl(["-"++H|_]) -> fatal_error("unknown option -"++H);
-cl(Opts) ->
+cl(Opts) ->
{Files, RestOpts} = dialyzer_cl_parse:collect_args(Opts),
{{files, Files}, RestOpts}.
@@ -645,327 +119,38 @@ process_def_list(L) ->
end.
%% Get information about files that the user trusts and wants to analyze
-analyze_result({files, Val}, Args, Analysis) ->
- NewVal = Args#args.files ++ Val,
- {Args#args{files = NewVal}, Analysis};
-analyze_result({files_r, Val}, Args, Analysis) ->
- NewVal = Args#args.files_r ++ Val,
- {Args#args{files_r = NewVal}, Analysis};
-analyze_result({trusted, Val}, Args, Analysis) ->
- NewVal = Args#args.trusted ++ Val,
- {Args#args{trusted = NewVal}, Analysis};
-analyze_result(edoc, Args, Analysis) ->
- {Args, Analysis#analysis{edoc = true}};
+analyze_result({files, Val}, Opts) ->
+ append_in_map(files, Val, Opts);
+analyze_result({files_r, Val}, Opts) ->
+ append_in_map(files_r, Val, Opts);
+analyze_result({trusted, Val}, Opts) ->
+ append_in_map(trusted, Val, Opts);
+analyze_result(edoc, Opts) ->
+ Opts#{edoc => true};
%% Get useful information for actual analysis
-analyze_result({mode, Mode}, Args, Analysis) ->
- case Analysis#analysis.mode of
- undefined -> {Args, Analysis#analysis{mode = Mode}};
- OldMode -> mode_error(OldMode, Mode)
- end;
-analyze_result({def, Val}, Args, Analysis) ->
- NewVal = Analysis#analysis.macros ++ [Val],
- {Args, Analysis#analysis{macros = NewVal}};
-analyze_result({inc, Val}, Args, Analysis) ->
- NewVal = Analysis#analysis.includes ++ [Val],
- {Args, Analysis#analysis{includes = NewVal}};
-analyze_result({plt, Plt}, Args, Analysis) ->
- {Args, Analysis#analysis{plt = Plt}};
-analyze_result(show_succ, Args, Analysis) ->
- {Args, Analysis#analysis{show_succ = true}};
-analyze_result(no_spec, Args, Analysis) ->
- {Args, Analysis#analysis{no_spec = true}};
-analyze_result({pa, Dir}, Args, Analysis) ->
+analyze_result({mode, Mode}, #{mode := OldMode}) ->
+ mode_error(OldMode, Mode);
+analyze_result({mode, Mode}, Opts) ->
+ Opts#{mode => Mode};
+analyze_result({def, Val}, Opts) ->
+ append_in_map(macros, [Val], Opts);
+analyze_result({inc, Val}, Opts) ->
+ append_in_map(includes, [Val], Opts);
+analyze_result({plt, Plt}, Opts) ->
+ Opts#{plt => Plt};
+analyze_result(show_succ, Opts) ->
+ Opts#{show_succ => true};
+analyze_result(no_spec, Opts) ->
+ Opts#{no_spec => true};
+analyze_result({pa, Dir}, Opts) ->
true = code:add_patha(Dir),
- {Args, Analysis};
-analyze_result({pz, Dir}, Args, Analysis) ->
+ Opts;
+analyze_result({pz, Dir}, Opts) ->
true = code:add_pathz(Dir),
- {Args, Analysis}.
-
-%%--------------------------------------------------------------------
-%% File processing.
-%%--------------------------------------------------------------------
-
--spec get_all_files(args()) -> [file:filename(),...].
-
-get_all_files(#args{files = Fs, files_r = Ds}) ->
- case filter_fd(Fs, Ds, fun test_erl_file_exclude_ann/1) of
- [] -> fatal_error("no file(s) to analyze");
- AllFiles -> AllFiles
- end.
-
--spec test_erl_file_exclude_ann(file:filename()) -> boolean().
-
-test_erl_file_exclude_ann(File) ->
- case is_erl_file(File) of
- true -> %% Exclude files ending with ".ann.erl"
- case re:run(File, "[\.]ann[\.]erl$", [unicode]) of
- {match, _} -> false;
- nomatch -> true
- end;
- false -> false
- end.
-
--spec is_erl_file(file:filename()) -> boolean().
-
-is_erl_file(File) ->
- filename:extension(File) =:= ".erl".
-
--type test_file_fun() :: fun((file:filename()) -> boolean()).
-
--spec filter_fd(files(), files(), test_file_fun()) -> files().
-
-filter_fd(File_Dir, Dir_R, Fun) ->
- All_File_1 = process_file_and_dir(File_Dir, Fun),
- All_File_2 = process_dir_rec(Dir_R, Fun),
- remove_dup(All_File_1 ++ All_File_2).
-
--spec process_file_and_dir(files(), test_file_fun()) -> files().
-
-process_file_and_dir(File_Dir, TestFun) ->
- Fun =
- fun (Elem, Acc) ->
- case filelib:is_regular(Elem) of
- true -> process_file(Elem, TestFun, Acc);
- false -> check_dir(Elem, false, Acc, TestFun)
- end
- end,
- lists:foldl(Fun, [], File_Dir).
-
--spec process_dir_rec(files(), test_file_fun()) -> files().
-
-process_dir_rec(Dirs, TestFun) ->
- Fun = fun (Dir, Acc) -> check_dir(Dir, true, Acc, TestFun) end,
- lists:foldl(Fun, [], Dirs).
-
--spec check_dir(file:filename(), boolean(), files(), test_file_fun()) -> files().
-
-check_dir(Dir, Recursive, Acc, Fun) ->
- case file:list_dir(Dir) of
- {ok, Files} ->
- {TmpDirs, TmpFiles} = split_dirs_and_files(Files, Dir),
- case Recursive of
- false ->
- FinalFiles = process_file_and_dir(TmpFiles, Fun),
- Acc ++ FinalFiles;
- true ->
- TmpAcc1 = process_file_and_dir(TmpFiles, Fun),
- TmpAcc2 = process_dir_rec(TmpDirs, Fun),
- Acc ++ TmpAcc1 ++ TmpAcc2
- end;
- {error, eacces} ->
- fatal_error("no access permission to dir \""++Dir++"\"");
- {error, enoent} ->
- fatal_error("cannot access "++Dir++": No such file or directory");
- {error, _Reason} ->
- fatal_error("error involving a use of file:list_dir/1")
- end.
-
-%% Same order as the input list
--spec process_file(file:filename(), test_file_fun(), files()) -> files().
-
-process_file(File, TestFun, Acc) ->
- case TestFun(File) of
- true -> Acc ++ [File];
- false -> Acc
- end.
-
-%% Same order as the input list
--spec split_dirs_and_files(files(), file:filename()) -> {files(), files()}.
-
-split_dirs_and_files(Elems, Dir) ->
- Test_Fun =
- fun (Elem, {DirAcc, FileAcc}) ->
- File = filename:join(Dir, Elem),
- case filelib:is_regular(File) of
- false -> {[File|DirAcc], FileAcc};
- true -> {DirAcc, [File|FileAcc]}
- end
- end,
- {Dirs, Files} = lists:foldl(Test_Fun, {[], []}, Elems),
- {lists:reverse(Dirs), lists:reverse(Files)}.
-
-%% Removes duplicate filenames but keeps the order of the input list
--spec remove_dup(files()) -> files().
-
-remove_dup(Files) ->
- Test_Dup = fun (File, Acc) ->
- case lists:member(File, Acc) of
- true -> Acc;
- false -> [File|Acc]
- end
- end,
- Reversed_Elems = lists:foldl(Test_Dup, [], Files),
- lists:reverse(Reversed_Elems).
-
-%%--------------------------------------------------------------------
-%% Collect information.
-%%--------------------------------------------------------------------
-
--type inc_file_info() :: {file:filename(), func_info()}.
-
--record(tmpAcc, {file :: file:filename(),
- module :: atom(),
- funcAcc = [] :: [func_info()],
- incFuncAcc = [] :: [inc_file_info()],
- dialyzerObj = [] :: [{mfa(), {_, _}}]}).
-
--spec collect_info(analysis()) -> analysis().
-
-collect_info(Analysis) ->
- NewPlt =
- try get_dialyzer_plt(Analysis) of
- DialyzerPlt ->
- dialyzer_plt:merge_plts([Analysis#analysis.trust_plt, DialyzerPlt])
- catch
- throw:{dialyzer_error,_Reason} ->
- fatal_error("Dialyzer's PLT is missing or is not up-to-date; please (re)create it")
- end,
- NewAnalysis = lists:foldl(fun collect_one_file_info/2,
- Analysis#analysis{trust_plt = NewPlt},
- Analysis#analysis.files),
- %% Process Remote Types
- TmpCServer = NewAnalysis#analysis.codeserver,
- NewCServer =
- try
- TmpCServer1 = dialyzer_utils:merge_types(TmpCServer, NewPlt),
- NewExpTypes = dialyzer_codeserver:get_temp_exported_types(TmpCServer),
- OldExpTypes = dialyzer_plt:get_exported_types(NewPlt),
- MergedExpTypes = sets:union(NewExpTypes, OldExpTypes),
- TmpCServer2 =
- dialyzer_codeserver:finalize_exported_types(MergedExpTypes, TmpCServer1),
- TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2),
- dialyzer_contracts:process_contract_remote_types(TmpCServer3)
- catch
- throw:{error, ErrorMsg} ->
- fatal_error(ErrorMsg)
- end,
- NewAnalysis#analysis{codeserver = NewCServer}.
-
-collect_one_file_info(File, Analysis) ->
- Ds = [{d,Name,Val} || {Name,Val} <- Analysis#analysis.macros],
- %% Current directory should also be included in "Includes".
- Includes = [filename:dirname(File)|Analysis#analysis.includes],
- Is = [{i,Dir} || Dir <- Includes],
- Options = dialyzer_utils:src_compiler_opts() ++ Is ++ Ds,
- case dialyzer_utils:get_core_from_src(File, Options) of
- {error, Reason} ->
- %% io:format("File=~tp\n,Options=~p\n,Error=~p\n", [File,Options,Reason]),
- compile_error(Reason);
- {ok, Core} ->
- case dialyzer_utils:get_record_and_type_info(Core) of
- {error, Reason} -> compile_error([Reason]);
- {ok, Records} ->
- Mod = cerl:concrete(cerl:module_name(Core)),
- case dialyzer_utils:get_spec_info(Mod, Core, Records) of
- {error, Reason} -> compile_error([Reason]);
- {ok, SpecInfo, CbInfo} ->
- ExpTypes = get_exported_types_from_core(Core),
- analyze_core_tree(Core, Records, SpecInfo, CbInfo,
- ExpTypes, Analysis, File)
- end
- end
- end.
-
-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,
- NextLabel = dialyzer_codeserver:get_next_core_label(CS1),
- {Tree, NewLabel} = cerl_trees:label(TmpTree, NextLabel),
- CS2 = dialyzer_codeserver:insert(Module, Tree, CS1),
- CS3 = dialyzer_codeserver:set_next_core_label(NewLabel, CS2),
- CS4 = dialyzer_codeserver:store_temp_records(Module, Records, CS3),
- CS5 =
- case Analysis#analysis.no_spec of
- true -> 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)],
- 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),
- Exported_FuncMap = map__insert({File, Ex_Funcs}, Analysis#analysis.ex_func),
- %% we must sort all functions in the file which
- %% originate from this file by *numerical order* of lineNo
- Sorted_Functions = lists:keysort(1, Acc#tmpAcc.funcAcc),
- FuncMap = map__insert({File, Sorted_Functions}, Analysis#analysis.func),
- %% we do not need to sort functions which are imported from included files
- IncFuncMap = map__insert({File, Acc#tmpAcc.incFuncAcc},
- Analysis#analysis.inc_func),
- FMs = Analysis#analysis.fms ++ [{File, Module}],
- RecordMap = map__insert({File, Records}, Analysis#analysis.record),
- Analysis#analysis{fms = FMs,
- callgraph = CG,
- codeserver = CS6,
- ex_func = Exported_FuncMap,
- inc_func = IncFuncMap,
- record = RecordMap,
- func = FuncMap}.
+ Opts.
-analyze_one_function({Var, FunBody} = Function, Acc) ->
- F = cerl:fname_id(Var),
- A = cerl:fname_arity(Var),
- TmpDialyzerObj = {{Acc#tmpAcc.module, F, A}, Function},
- NewDialyzerObj = Acc#tmpAcc.dialyzerObj ++ [TmpDialyzerObj],
- Anno = cerl:get_ann(FunBody),
- LineNo = get_line(Anno),
- FileName = get_file(Anno),
- BaseName = filename:basename(FileName),
- FuncInfo = {LineNo, F, A},
- OriginalName = Acc#tmpAcc.file,
- {FuncAcc, IncFuncAcc} =
- case (FileName =:= OriginalName) orelse (BaseName =:= OriginalName) of
- true -> %% Coming from original file
- %% io:format("Added function ~tp\n", [{LineNo, F, A}]),
- {Acc#tmpAcc.funcAcc ++ [FuncInfo], Acc#tmpAcc.incFuncAcc};
- false ->
- %% Coming from other sourses, including:
- %% -- .yrl (yecc-generated file)
- %% -- yeccpre.hrl (yecc-generated file)
- %% -- other cases
- {Acc#tmpAcc.funcAcc, Acc#tmpAcc.incFuncAcc ++ [{FileName, FuncInfo}]}
- end,
- Acc#tmpAcc{funcAcc = FuncAcc,
- incFuncAcc = IncFuncAcc,
- dialyzerObj = NewDialyzerObj}.
-
-get_line([Line|_]) when is_integer(Line) -> Line;
-get_line([{Line, _Column} | _Tail]) when is_integer(Line) -> Line;
-get_line([_|Tail]) -> get_line(Tail);
-get_line([]) -> -1.
-
-get_file([{file,File}|_]) -> File;
-get_file([_|T]) -> get_file(T);
-get_file([]) -> "no_file". % should not happen
-
--spec get_dialyzer_plt(analysis()) -> plt().
-
-get_dialyzer_plt(#analysis{plt = PltFile0}) ->
- PltFile =
- case PltFile0 =:= none of
- true -> dialyzer_plt:get_default_plt();
- false -> PltFile0
- end,
- dialyzer_plt:from_file(PltFile).
-
-%% Exported Types
-
-get_exported_types_from_core(Core) ->
- Attrs = cerl:module_attrs(Core),
- ExpTypes1 = [cerl:concrete(L2) || {L1, L2} <- Attrs,
- cerl:is_literal(L1),
- cerl:is_literal(L2),
- cerl:concrete(L1) =:= 'export_type'],
- ExpTypes2 = lists:flatten(ExpTypes1),
- M = cerl:atom_val(cerl:module_name(Core)),
- sets:from_list([{M, F, A} || {F, A} <- ExpTypes2]).
+append_in_map(Key, List, Map) ->
+ maps:update_with(Key, fun(L) -> L ++ List end, List, Map).
%%--------------------------------------------------------------------
%% Utilities for error reporting.
@@ -977,7 +162,7 @@ fatal_error(Slogan) ->
msg(io_lib:format("typer: ~ts\n", [Slogan])),
erlang:halt(1).
--spec mode_error(mode(), mode()) -> no_return().
+-spec mode_error(typer_core:mode(), typer_core:mode()) -> no_return().
mode_error(OldMode, NewMode) ->
Msg = io_lib:format("Mode was previously set to '~s'; "
@@ -985,13 +170,6 @@ mode_error(OldMode, NewMode) ->
[OldMode, NewMode]),
fatal_error(Msg).
--spec compile_error([string()]) -> no_return().
-
-compile_error(Reason) ->
- JoinedString = lists:flatten([X ++ "\n" || X <- Reason]),
- Msg = "Analysis failed with error report:\n" ++ JoinedString,
- fatal_error(Msg).
-
-spec msg(string()) -> 'ok'.
msg(Msg) ->
@@ -1011,7 +189,7 @@ version_message() ->
help_message() ->
S = <<" Usage: typer [--help] [--version] [--plt PLT] [--edoc]
- [--show | --show-exported | --annotate | --annotate-inc-files]
+ [--show | --show-exported | --annotate | --annotate-inc-files | --annotate-in-place]
[-Ddefine]* [-I include_dir]* [-pa dir]* [-pz dir]*
[-T application]* [-r] file*
@@ -1025,10 +203,14 @@ help_message() ->
Same as --show, but prints specifications for exported functions only
Specs are displayed sorted alphabetically on the function's name
--annotate
- Annotates the specified files with type specifications
+ Annotates the specified files with type specifications and writes
+ the resulting files into a new typer_ann folder.
--annotate-inc-files
Same as --annotate but annotates all -include() files as well as
- all .erl files (use this option with caution - has not been tested much)
+ all .erl files
+ --annotate-in-place
+ Annotate directly on the source code files, instead of dumping the
+ annotated files in a different directory
--edoc
Prints type information as Edoc @spec comments, not as type specs
--plt PLT
@@ -1046,7 +228,7 @@ help_message() ->
-pa dir
-pz dir
Set code path options to TypEr
- (This is useful for files that use parse tranforms.)
+ (This is useful for files that use parse transforms.)
--version (or -v)
prints the Typer version and exits
--help (or -h)
@@ -1057,52 +239,3 @@ help_message() ->
">>,
io:put_chars(S),
erlang:halt(0).
-
-%%--------------------------------------------------------------------
-%% Handle messages.
-%%--------------------------------------------------------------------
-
-rcv_ext_types() ->
- Self = self(),
- Self ! {Self, done},
- rcv_ext_types(Self, []).
-
-rcv_ext_types(Self, ExtTypes) ->
- receive
- {Self, ext_types, ExtType} ->
- rcv_ext_types(Self, [ExtType|ExtTypes]);
- {Self, done} ->
- lists:usort(ExtTypes)
- end.
-
-%%--------------------------------------------------------------------
-%% A convenient abstraction of a Key-Value mapping data structure
-%% specialized for the uses in this module
-%%--------------------------------------------------------------------
-
--type map_dict() :: dict:dict().
-
--spec map__new() -> map_dict().
-map__new() ->
- dict:new().
-
--spec map__insert({term(), term()}, map_dict()) -> map_dict().
-map__insert(Object, Map) ->
- {Key, Value} = Object,
- dict:store(Key, Value, Map).
-
--spec map__lookup(term(), map_dict()) -> term().
-map__lookup(Key, Map) ->
- try dict:fetch(Key, Map) catch error:_ -> none end.
-
--spec map__from_list([{fa(), term()}]) -> map_dict().
-map__from_list(List) ->
- dict:from_list(List).
-
--spec map__remove(term(), map_dict()) -> map_dict().
-map__remove(Key, Dict) ->
- dict:erase(Key, Dict).
-
--spec map__fold(fun((term(), term(), term()) -> map_dict()), map_dict(), map_dict()) -> map_dict().
-map__fold(Fun, Acc0, Dict) ->
- dict:fold(Fun, Acc0, Dict).
diff --git a/lib/dialyzer/src/typer_core.erl b/lib/dialyzer/src/typer_core.erl
new file mode 100644
index 0000000000..c9051f825e
--- /dev/null
+++ b/lib/dialyzer/src/typer_core.erl
@@ -0,0 +1,1049 @@
+%% -*- erlang-indent-level: 2 -*-
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+
+%%-----------------------------------------------------------------------
+%% File : typer_core.erl
+%% Author(s) : The first version of typer was written by Bingwen He
+%% with guidance from Kostis Sagonas and Tobias Lindahl.
+%% Since June 2008 typer is maintained by Kostis Sagonas.
+%% On 2022, Brujo Benavides, Pablo Costas, and Mackenzie
+%% Morgan from NextRoll started working on the rebar3
+%% plugin for typer and, with that in mind, splitted typer
+%% and typer_core apart.
+%% Description : An Erlang/OTP module that shows type information
+%% for Erlang modules to the user. Additionally, it can
+%% annotate the code of files with such type information.
+%%-----------------------------------------------------------------------
+
+-module(typer_core).
+
+-export([run/1]).
+
+%%-----------------------------------------------------------------------
+
+-define(SHOW, show).
+-define(SHOW_EXPORTED, show_exported).
+-define(ANNOTATE, annotate).
+-define(ANNOTATE_IN_PLACE, annotate_in_place).
+-define(ANNOTATE_INC_FILES, annotate_inc_files).
+
+-type mode() :: ?SHOW | ?SHOW_EXPORTED | ?ANNOTATE | ?ANNOTATE_IN_PLACE | ?ANNOTATE_INC_FILES.
+
+%%-----------------------------------------------------------------------
+
+-type files() :: [file:filename()].
+-type callgraph() :: dialyzer_callgraph:callgraph().
+-type codeserver() :: dialyzer_codeserver:codeserver().
+-type plt() :: dialyzer_plt:plt().
+-type printer(Return) :: fun((io:format(), [term()]) -> Return).
+-type io() ::
+ #{debug := printer(_),
+ info := printer(_),
+ warn := printer(_),
+ abort := printer(no_return())}.
+-type opts() ::
+ #{mode := mode(),
+ show_succ => boolean(),
+ no_spec => boolean(),
+ edoc => boolean(),
+ plt => file:filename(),
+ trusted => files(),
+ files => files(),
+ files_r => files(),
+ macros => [{atom(), term()}],
+ includes => files(),
+ io => io()}.
+
+-export_type([mode/0, opts/0]).
+
+-record(analysis,
+ {mode :: mode() | 'undefined',
+ macros = [] :: [{atom(), term()}],
+ includes = [] :: files(),
+ codeserver = dialyzer_codeserver:new():: codeserver(),
+ callgraph = dialyzer_callgraph:new() :: callgraph(),
+ files = [] :: files(), % absolute names
+ plt = none :: 'none' | file:filename(),
+ no_spec = false :: boolean(),
+ show_succ = false :: boolean(),
+ %% For choosing between specs or edoc @spec comments
+ edoc = false :: boolean(),
+ %% Files in 'fms' are compilable with option 'to_pp'; we keep them
+ %% as {FileName, ModuleName} in case the ModuleName is different
+ fms = [] :: [{file:filename(), module()}],
+ ex_func = maps:new() :: #{file:filename() => [func_info()]},
+ record = maps:new() :: #{file:filename() => erl_types:type_table()},
+ func = maps:new() :: #{file:filename() => [func_info()]},
+ inc_func = maps:new() :: #{file:filename() => [inc_file_info()]},
+ trust_plt = dialyzer_plt:new() :: plt(),
+ io = default_io() :: io()}).
+-type analysis() :: #analysis{}.
+
+-record(args, {files = [] :: files(),
+ files_r = [] :: files(),
+ trusted = [] :: files()}).
+-type args() :: #args{}.
+
+%%--------------------------------------------------------------------
+
+-spec run(opts()) -> ok.
+
+run(Opts) ->
+ {Args, Analysis} = process_cl_args(Opts),
+ msg(debug, "Opts: ~p\nArgs: ~p\nAnalysis: ~p", [Opts, Args, Analysis], Analysis),
+ Timer = dialyzer_timing:init(false),
+ TrustedFiles = filter_fd(Args#args.trusted, [], fun is_erl_file/1, Analysis),
+ Analysis2 = extract(Analysis, TrustedFiles),
+ All_Files = get_all_files(Args, Analysis2),
+ msg(debug, "All_Files: ~tp", [All_Files], Analysis2),
+ Analysis3 = Analysis2#analysis{files = All_Files},
+ Analysis4 = collect_info(Analysis3),
+ msg(debug, "Final: ~p", [Analysis4#analysis.fms], Analysis3),
+ TypeInfo = get_type_info(Analysis4),
+ dialyzer_timing:stop(Timer),
+ show_or_annotate(TypeInfo),
+ msg(debug, "\nTyper analysis finished", [], Analysis4),
+ ok.
+
+%%--------------------------------------------------------------------
+
+-spec extract(analysis(), files()) -> analysis().
+
+extract(#analysis{macros = Macros,
+ includes = Includes,
+ trust_plt = TrustPLT} = Analysis, TrustedFiles) ->
+ msg(debug, "Extracting trusted typer info...", [], Analysis),
+ Ds = [{d, Name, Value} || {Name, Value} <- Macros],
+ CodeServer = dialyzer_codeserver:new(),
+ Fun =
+ fun(File, CS) ->
+ %% We include one more dir; the one above the one we are trusting
+ %% E.g, for /home/tests/typer_ann/test.ann.erl, we should include
+ %% /home/tests/ rather than /home/tests/typer_ann/
+ AllIncludes = [filename:dirname(filename:dirname(File)) | Includes],
+ Is = [{i, Dir} || Dir <- AllIncludes],
+ CompOpts = dialyzer_utils:src_compiler_opts() ++ Is ++ Ds,
+ case dialyzer_utils:get_core_from_src(File, CompOpts) of
+ {ok, Core} ->
+ case dialyzer_utils:get_record_and_type_info(Core) of
+ {ok, RecDict} ->
+ Mod = list_to_atom(filename:basename(File, ".erl")),
+ case dialyzer_utils:get_spec_info(Mod, Core, RecDict) of
+ {ok, SpecDict, CbDict} ->
+ CS1 = dialyzer_codeserver:store_temp_records(Mod, RecDict, CS),
+ dialyzer_codeserver:store_temp_contracts(Mod, SpecDict, CbDict, CS1);
+ {error, Reason} -> compile_error([Reason], Analysis)
+ end;
+ {error, Reason} -> compile_error([Reason], Analysis)
+ end;
+ {error, Reason} -> compile_error(Reason, Analysis)
+ end
+ end,
+ CodeServer1 = lists:foldl(Fun, CodeServer, TrustedFiles),
+ %% Process remote types
+ NewCodeServer =
+ try
+ CodeServer2 =
+ dialyzer_utils:merge_types(CodeServer1,
+ TrustPLT), % XXX change to the PLT?
+ NewExpTypes = dialyzer_codeserver:get_temp_exported_types(CodeServer1),
+ case sets:size(NewExpTypes) of 0 -> ok end,
+ CodeServer3 = dialyzer_codeserver:finalize_exported_types(NewExpTypes, CodeServer2),
+ CodeServer4 = dialyzer_utils:process_record_remote_types(CodeServer3),
+ dialyzer_contracts:process_contract_remote_types(CodeServer4)
+ catch
+ throw:{error, ErrorMsg} ->
+ compile_error(ErrorMsg, Analysis)
+ end,
+ %% Create TrustPLT
+ ContractsDict = dialyzer_codeserver:get_contracts(NewCodeServer),
+ Contracts = orddict:from_list(dict:to_list(ContractsDict)),
+ NewTrustPLT = dialyzer_plt:insert_contract_list(TrustPLT, Contracts),
+ Analysis#analysis{trust_plt = NewTrustPLT}.
+
+%%--------------------------------------------------------------------
+
+-spec get_type_info(analysis()) -> analysis().
+
+get_type_info(#analysis{callgraph = CallGraph,
+ trust_plt = TrustPLT,
+ codeserver = CodeServer} = Analysis) ->
+ StrippedCallGraph = remove_external(CallGraph, TrustPLT, Analysis),
+ msg(debug, "Analyizing callgraph...", [], Analysis),
+ try
+ NewPlt = dialyzer_succ_typings:analyze_callgraph(StrippedCallGraph,
+ TrustPLT,
+ CodeServer,
+ none, []),
+ Analysis#analysis{callgraph = StrippedCallGraph, trust_plt = NewPlt}
+ catch
+ error:What:Stacktrace ->
+ fatal_error(io_lib:format("Analysis failed with message: ~tp",
+ [{What, Stacktrace}]), Analysis);
+ throw:{dialyzer_succ_typing_error, Msg} ->
+ fatal_error(io_lib:format("Analysis failed with message: ~ts", [Msg]), Analysis)
+ end.
+
+-spec remove_external(callgraph(), plt(), analysis()) -> callgraph().
+
+remove_external(CallGraph, PLT, Analysis) ->
+ {StrippedCG0, Ext} = dialyzer_callgraph:remove_external(CallGraph),
+ case get_external(Ext, PLT) of
+ [] -> ok;
+ Externals ->
+ msg(warn, " Unknown functions: ~tp", [lists:usort(Externals)], Analysis),
+ ExtTypes = rcv_ext_types(),
+ case ExtTypes of
+ [] -> ok;
+ _ -> msg(warn, " Unknown types: ~tp", [ExtTypes], Analysis)
+ end
+ end,
+ StrippedCG0.
+
+-spec get_external([{mfa(), mfa()}], plt()) -> [mfa()].
+
+get_external(Exts, Plt) ->
+ Fun = fun ({_From, To = {M, F, A}}, Acc) ->
+ case dialyzer_plt:contains_mfa(Plt, To) of
+ false ->
+ case erl_bif_types:is_known(M, F, A) of
+ true -> Acc;
+ false -> [To|Acc]
+ end;
+ true -> Acc
+ end
+ end,
+ lists:foldl(Fun, [], Exts).
+
+%%--------------------------------------------------------------------
+%% Showing type information or annotating files with such information.
+%%--------------------------------------------------------------------
+
+-define(TYPER_ANN_DIR, "typer_ann").
+
+-type line() :: non_neg_integer().
+-type func_info() :: {line(), atom(), arity()}.
+-type func_name() :: {atom(), arity()}.
+-type func_type() ::
+ {contract, dialyzer_contract()} |
+ {erl_types:erl_type(), [erl_types:erl_type()] | arity()}.
+-type func_types() :: #{func_name() => func_type()}.
+%% This is a record (#contract{}) defined in dialyzer.hrl
+%% but we can't include_lib that file since it also defines
+%% #analysis
+-type dialyzer_contract() :: tuple().
+
+-record(info, {records = maps:new() :: erl_types:type_table(),
+ functions = [] :: [func_info()],
+ types = maps:new() :: func_types(),
+ edoc = false :: boolean()}).
+-record(inc,
+ {map = maps:new() :: #{file:filename() => [{func_name(), {pos_integer(), func_type()}}]},
+ filter = [] :: [file:filename()]}).
+-type inc() :: #inc{}.
+
+-spec show_or_annotate(analysis()) -> 'ok'.
+
+show_or_annotate(#analysis{mode = Mode, fms = Files} = Analysis) ->
+ case Mode of
+ ?SHOW -> show(Analysis);
+ ?SHOW_EXPORTED -> show(Analysis);
+ Mode when Mode == ?ANNOTATE; Mode == ?ANNOTATE_IN_PLACE ->
+ Fun = fun ({File, Module}) ->
+ Info = get_final_info(File, Module, Analysis),
+ write_typed_file(File, Info, Analysis)
+ end,
+ lists:foreach(Fun, Files);
+ ?ANNOTATE_INC_FILES ->
+ IncInfo = write_and_collect_inc_info(Analysis),
+ write_inc_files(IncInfo, Analysis)
+ end.
+
+write_and_collect_inc_info(Analysis) ->
+ Fun = fun ({File, Module}, Inc) ->
+ Info = get_final_info(File, Module, Analysis),
+ write_typed_file(File, Info, Analysis),
+ IncFuns = get_inc_functions(File, Analysis),
+ collect_imported_functions(IncFuns, Info#info.types, Inc, Analysis)
+ end,
+ NewInc = lists:foldl(Fun, #inc{}, Analysis#analysis.fms),
+ clean_inc(NewInc).
+
+write_inc_files(Inc, Analysis) ->
+ Fun =
+ fun (File) ->
+ Val = maps:get(File, Inc#inc.map, none),
+ %% Val is function with its type info
+ %% in form [{{Line,F,A},Type}]
+ Functions = [Key || {Key, _} <- Val],
+ Val1 = [{{F,A},Type} || {{_Line,F,A},Type} <- Val],
+ Info = #info{types = maps:from_list(Val1),
+ records = maps:new(),
+ %% Note we need to sort functions here!
+ functions = lists:keysort(1, Functions)},
+ msg(debug, "Types ~tp", [Info#info.types], Analysis),
+ msg(debug, "Functions ~tp", [Info#info.functions], Analysis),
+ msg(debug, "Records ~tp", [Info#info.records], Analysis),
+ write_typed_file(File, Info, Analysis)
+ end,
+ lists:foreach(Fun, maps:keys(Inc#inc.map)).
+
+show(Analysis) ->
+ Fun = fun ({File, Module}) ->
+ Info = get_final_info(File, Module, Analysis),
+ show_type_info(File, Info, Analysis)
+ end,
+ lists:foreach(Fun, Analysis#analysis.fms).
+
+get_final_info(File, Module, Analysis) ->
+ Records = get_records(File, Analysis),
+ Types = get_types(Module, Analysis, Records),
+ Functions = get_functions(File, Analysis),
+ Edoc = Analysis#analysis.edoc,
+ #info{records = Records, functions = Functions, types = Types, edoc = Edoc}.
+
+collect_imported_functions(Functions, Types, Inc, Analysis) ->
+ %% Coming from other sourses, including:
+ %% FIXME: How to deal with yecc-generated file????
+ %% --.yrl (yecc-generated file)???
+ %% -- yeccpre.hrl (yecc-generated file)???
+ %% -- other cases
+ Fun = fun ({File, _} = Obj, I) ->
+ case is_yecc_gen(File, I) of
+ {true, NewI} -> NewI;
+ {false, NewI} ->
+ check_imported_functions(Obj, NewI, Types, Analysis)
+ end
+ end,
+ lists:foldl(Fun, Inc, Functions).
+
+-spec is_yecc_gen(file:filename(), inc()) -> {boolean(), inc()}.
+
+is_yecc_gen(File, #inc{filter = Fs} = Inc) ->
+ case lists:member(File, Fs) of
+ true -> {true, Inc};
+ false ->
+ case filename:extension(File) of
+ ".yrl" ->
+ Rootname = filename:rootname(File, ".yrl"),
+ Obj = Rootname ++ ".erl",
+ case lists:member(Obj, Fs) of
+ true -> {true, Inc};
+ false ->
+ NewInc = Inc#inc{filter = [Obj|Fs]},
+ {true, NewInc}
+ end;
+ _ ->
+ case filename:basename(File) of
+ "yeccpre.hrl" -> {true, Inc};
+ _ -> {false, Inc}
+ end
+ end
+ end.
+
+check_imported_functions({File, {Line, F, A}}, Inc, Types, Analysis) ->
+ IncMap = Inc#inc.map,
+ FA = {F, A},
+ Type = get_type_info(FA, Types, Analysis),
+ case IncMap of
+ #{File := Val} -> %% File is already in. Check.
+ case lists:keyfind(FA, 1, Val) of
+ false ->
+ %% Function is not in; add it
+ Inc#inc{map = IncMap#{File => Val ++ [{FA, {Line, Type}}]}};
+ {FA, {_, Type}} ->
+ %% Function is in and with same type
+ Inc;
+ _ ->
+ %% Function is in but with diff type
+ inc_warning(FA, File, Analysis),
+ Elem = lists:keydelete(FA, 1, Val),
+ NewMap =
+ case Elem of
+ [] -> maps:remove(File, IncMap);
+ _ -> IncMap#{File => Elem}
+ end,
+ Inc#inc{map = NewMap}
+ end;
+ _ -> %% File is not added. Add it
+ NewMap = IncMap#{File => [{FA, {Line, Type}}]},
+ Inc#inc{map = NewMap}
+ end.
+
+inc_warning({F, A}, File, Analysis) ->
+ msg(warn,
+ " ***Warning: Skip function ~tp/~p "
+ "in file ~tp because of inconsistent type",
+ [F, A, File],
+ Analysis).
+
+clean_inc(Inc) ->
+ Inc1 = remove_yecc_generated_file(Inc),
+ normalize_obj(Inc1).
+
+remove_yecc_generated_file(#inc{filter = Filter} = Inc) ->
+ Fun = fun(Key, #inc{map = Map} = I) -> I#inc{map = maps:remove(Key, Map)} end,
+ lists:foldl(Fun, Inc, Filter).
+
+normalize_obj(TmpInc) ->
+ Fun = fun (Key, Val, Inc) ->
+ NewVal = [{{Line,F,A},Type} || {{F,A},{Line,Type}} <- Val],
+ Inc#{Key => NewVal}
+ end,
+ TmpInc#inc{map = maps:fold(Fun, maps:new(), TmpInc#inc.map)}.
+
+get_records(File, Analysis) ->
+ maps:get(File, Analysis#analysis.record, none).
+
+get_types(Module, Analysis, Records) ->
+ TypeInfoPlt = Analysis#analysis.trust_plt,
+ TypeInfo =
+ case dialyzer_plt:lookup_module(TypeInfoPlt, Module) of
+ none -> [];
+ {value, List} -> List
+ end,
+ CodeServer = Analysis#analysis.codeserver,
+ TypeInfoList =
+ case Analysis#analysis.show_succ of
+ true ->
+ [convert_type_info(I) || I <- TypeInfo];
+ false ->
+ [get_type(I, CodeServer, Records, Analysis) || I <- TypeInfo]
+ end,
+ maps:from_list(TypeInfoList).
+
+convert_type_info({{_M, F, A}, Range, Arg}) ->
+ {{F, A}, {Range, Arg}}.
+
+get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, Records, Analysis) ->
+ case dialyzer_codeserver:lookup_mfa_contract(MFA, CodeServer) of
+ error ->
+ {{F, A}, {Range, Arg}};
+ {ok, {_FileLine, Contract, _Xtra}} ->
+ Sig = erl_types:t_fun(Arg, Range),
+ case dialyzer_contracts:check_contract(Contract, Sig) of
+ ok -> {{F, A}, {contract, Contract}};
+ {range_warnings, _} ->
+ {{F, A}, {contract, Contract}};
+ {error, {overlapping_contract, []}} ->
+ {{F, A}, {contract, Contract}};
+ {error, invalid_contract} ->
+ CString = dialyzer_contracts:contract_to_string(Contract),
+ SigString = dialyzer_utils:format_sig(Sig, Records),
+ Msg = io_lib:format("Error in contract of function ~w:~tw/~w\n"
+ "\t The contract is: " ++ CString ++ "\n" ++
+ "\t but the inferred signature is: ~ts",
+ [M, F, A, SigString]),
+ fatal_error(Msg, Analysis);
+ {error, ErrorStr} when is_list(ErrorStr) -> % ErrorStr is a string()
+ Msg = io_lib:format("Error in contract of function ~w:~tw/~w: ~ts",
+ [M, F, A, ErrorStr]),
+ fatal_error(Msg, Analysis)
+ end
+ end.
+
+get_functions(File, Analysis) ->
+ case Analysis#analysis.mode of
+ ?SHOW ->
+ Funcs = maps:get(File, Analysis#analysis.func, none),
+ IncFuncs = maps:get(File, Analysis#analysis.inc_func, none),
+ remove_module_info(Funcs) ++ normalize_inc_funcs(IncFuncs);
+ ?SHOW_EXPORTED ->
+ ExFuncs = maps:get(File, Analysis#analysis.ex_func, none),
+ remove_module_info(ExFuncs);
+ Mode when Mode == ?ANNOTATE; Mode == ?ANNOTATE_IN_PLACE ->
+ Funcs = maps:get(File, Analysis#analysis.func, none),
+ remove_module_info(Funcs);
+ ?ANNOTATE_INC_FILES ->
+ normalize_inc_funcs(maps:get(File, Analysis#analysis.inc_func, none))
+ end.
+
+-spec get_inc_functions(file:filename(), analysis()) -> [{file:filename(), func_info()}].
+get_inc_functions(File, Analysis) ->
+ case Analysis#analysis.mode of
+ show ->
+ Funcs = maps:get(File, Analysis#analysis.func, none),
+ IncFuncs = maps:get(File, Analysis#analysis.inc_func, none),
+ extend_functions(File, remove_module_info(Funcs)) ++ IncFuncs;
+ show_exported ->
+ ExFuncs = maps:get(File, Analysis#analysis.ex_func, none),
+ extend_functions(File, remove_module_info(ExFuncs));
+ Mode when Mode =:= annotate orelse Mode =:= annotate_in_place ->
+ Funcs = maps:get(File, Analysis#analysis.func, none),
+ extend_functions(File, remove_module_info(Funcs));
+ annotate_inc_files ->
+ maps:get(File, Analysis#analysis.inc_func, none)
+ end.
+
+extend_functions(FileName, Functions) ->
+ [{FileName, FunInfo} || FunInfo <- Functions].
+
+normalize_inc_funcs(Functions) ->
+ [FunInfo || {_FileName, FunInfo} <- Functions].
+
+-spec remove_module_info([func_info()]) -> [func_info()].
+
+remove_module_info(FunInfoList) ->
+ F = fun ({_,module_info,0}) -> false;
+ ({_,module_info,1}) -> false;
+ ({Line,F,A}) when is_integer(Line), is_atom(F), is_integer(A) -> true
+ end,
+ lists:filter(F, FunInfoList).
+
+write_typed_file(File, Info, Analysis) ->
+ msg(info, " Processing file: ~tp", [File], Analysis),
+ Dir = filename:dirname(File),
+ RootName = filename:basename(filename:rootname(File)),
+ Ext = filename:extension(File),
+ case Analysis#analysis.mode of
+ ?ANNOTATE_IN_PLACE ->
+ write_typed_file(File, Info, File, Analysis);
+ _ ->
+ TyperAnnDir = filename:join(Dir, ?TYPER_ANN_DIR),
+ TmpNewFilename = lists:concat([RootName, ".ann", Ext]),
+ NewFileName = filename:join(TyperAnnDir, TmpNewFilename),
+ case file:make_dir(TyperAnnDir) of
+ {error, Reason} ->
+ case Reason of
+ eexist -> %% TypEr dir exists; remove old typer files if they exist
+ delete_file(NewFileName, Analysis),
+ write_typed_file(File, Info, NewFileName, Analysis);
+ enospc ->
+ Msg = io_lib:format("Not enough space in ~tp", [Dir]),
+ fatal_error(Msg, Analysis);
+ eacces ->
+ Msg = io_lib:format("No write permission in ~tp", [Dir]),
+ fatal_error(Msg, Analysis);
+ _ ->
+ Msg = io_lib:format("Unhandled error ~ts when writing ~tp",
+ [Reason, Dir]),
+ fatal_error(Msg, Analysis)
+ end;
+ ok -> %% Typer dir does NOT exist
+ write_typed_file(File, Info, NewFileName, Analysis)
+ end
+ end.
+
+-spec delete_file(file:filename_all(), analysis()) -> ok.
+delete_file(File, Analysis) ->
+ case file:delete(File) of
+ ok ->
+ ok;
+ {error, enoent} ->
+ ok;
+ {error, _} ->
+ Msg = io_lib:format("Error in deleting file ~ts", [File]),
+ fatal_error(Msg, Analysis)
+ end.
+
+write_typed_file(File, Info, NewFileName, Analysis) ->
+ {ok, Binary} = file:read_file(File),
+ case Analysis#analysis.mode of
+ ?ANNOTATE_IN_PLACE ->
+ delete_file(NewFileName, Analysis);
+ _ ->
+ ok
+ end,
+ Chars = unicode:characters_to_list(Binary),
+ write_typed_file(Chars, NewFileName, Info, 1, [], Analysis),
+ msg(info, " Saved as: ~tp", [NewFileName], Analysis).
+
+write_typed_file(Chars, File, #info{functions = []}, _LNo, _Acc, _Analysis) ->
+ ok = file:write_file(File, unicode:characters_to_binary(Chars), [append]);
+write_typed_file([Ch|Chs] = Chars, File, Info, LineNo, Acc, Analysis) ->
+ [{Line,F,A}|RestFuncs] = Info#info.functions,
+ case Line of
+ 1 -> %% This will happen only for inc files
+ ok = raw_write(F, A, Info, File, [], Analysis),
+ NewInfo = Info#info{functions = RestFuncs},
+ NewAcc = [],
+ write_typed_file(Chars, File, NewInfo, Line, NewAcc, Analysis);
+ _ ->
+ case Ch of
+ 10 ->
+ NewLineNo = LineNo + 1,
+ {NewInfo, NewAcc} =
+ case NewLineNo of
+ Line ->
+ ok = raw_write(F, A, Info, File, [Ch|Acc], Analysis),
+ {Info#info{functions = RestFuncs}, []};
+ _ ->
+ {Info, [Ch|Acc]}
+ end,
+ write_typed_file(Chs, File, NewInfo, NewLineNo, NewAcc, Analysis);
+ _ ->
+ write_typed_file(Chs, File, Info, LineNo, [Ch|Acc], Analysis)
+ end
+ end.
+
+raw_write(F, A, Info, File, Content, #analysis{mode = Mode} = Analysis) ->
+ TypeInfo = get_type_string(F, A, Info, file, Analysis),
+ ContentList =
+ case {TypeInfo, Mode} of
+ %% TypeInfo will be an empty string for functions that already have specs.
+ %% In this case, when annotating directly on the files (with annotate_in_place),
+ %% we don't want to add a newline character on the spec line, as presumably it should
+ %% already have one.
+ {"", ?ANNOTATE_IN_PLACE} ->
+ lists:reverse(Content) ++ TypeInfo;
+ _ ->
+ lists:reverse(Content) ++ TypeInfo ++ "\n"
+ end,
+ ContentBin = unicode:characters_to_binary(ContentList),
+ file:write_file(File, ContentBin, [append]).
+
+get_type_string(F, A, Info, Mode, Analysis) ->
+ Type = get_type_info({F,A}, Info#info.types, Analysis),
+ TypeStr =
+ case Type of
+ {contract, C} ->
+ dialyzer_contracts:contract_to_string(C);
+ {RetType, ArgType} ->
+ Sig = erl_types:t_fun(ArgType, RetType),
+ dialyzer_utils:format_sig(Sig, Info#info.records)
+ end,
+ case Info#info.edoc of
+ false ->
+ case {Mode, Type} of
+ {file, {contract, _}} -> "";
+ _ ->
+ Prefix = lists:concat(["-spec ", erl_types:atom_to_string(F)]),
+ lists:concat([Prefix, TypeStr, "."])
+ end;
+ true ->
+ Prefix = lists:concat(["%% @spec ", F]),
+ lists:concat([Prefix, TypeStr, "."])
+ end.
+
+show_type_info(File, Info, Analysis) ->
+ msg(info, "\n%% File: ~tp", [File], Analysis),
+ OutputString = lists:concat(["~.", length(File) + 8, "c"]),
+ msg(info, [$%, $%, $\s | OutputString], [$-], Analysis),
+ Fun = fun ({_LineNo, F, A}) ->
+ TypeInfo = get_type_string(F, A, Info, show, Analysis),
+ msg(info, "~ts", [TypeInfo], Analysis)
+ end,
+ lists:foreach(Fun, Info#info.functions).
+
+get_type_info(Func, Types, Analysis) ->
+ case Types of
+ #{Func := {contract, _Fun} = C} ->
+ C;
+ #{Func := {_RetType, _ArgType} = RA} ->
+ RA;
+ _ ->
+ %% Note: Typeinfo of any function should exist in
+ %% the result offered by dialyzer, otherwise there
+ %% *must* be something wrong with the analysis
+ Msg = io_lib:format("No type info for function: ~tp\n", [Func]),
+ fatal_error(Msg, Analysis)
+ end.
+
+%%--------------------------------------------------------------------
+%% Processing of command-line options and arguments.
+%%--------------------------------------------------------------------
+
+-spec process_cl_args(opts()) -> {args(), analysis()}.
+
+process_cl_args(Opts) ->
+ analyze_args(maps:to_list(Opts), #args{}, #analysis{}).
+
+analyze_args([], Args, Analysis) ->
+ {Args, Analysis};
+analyze_args([Result | Rest], Args, Analysis) ->
+ {NewArgs, NewAnalysis} = analyze_result(Result, Args, Analysis),
+ analyze_args(Rest, NewArgs, NewAnalysis).
+
+%% Get information about files that the user trusts and wants to analyze
+analyze_result({files, Val}, Args, Analysis) ->
+ NewVal = Args#args.files ++ Val,
+ {Args#args{files = NewVal}, Analysis};
+analyze_result({files_r, Val}, Args, Analysis) ->
+ NewVal = Args#args.files_r ++ Val,
+ {Args#args{files_r = NewVal}, Analysis};
+analyze_result({trusted, Val}, Args, Analysis) ->
+ NewVal = Args#args.trusted ++ Val,
+ {Args#args{trusted = NewVal}, Analysis};
+analyze_result({edoc, Value}, Args, Analysis) ->
+ {Args, Analysis#analysis{edoc = Value}};
+analyze_result({io, Val}, Args, Analysis) ->
+ {Args, Analysis#analysis{io = Val}};
+%% Get useful information for actual analysis
+analyze_result({mode, Mode}, Args, Analysis) ->
+ {Args, Analysis#analysis{mode = Mode}};
+analyze_result({macros, Macros}, Args, Analysis) ->
+ {Args, Analysis#analysis{macros = Macros}};
+analyze_result({includes, Includes}, Args, Analysis) ->
+ {Args, Analysis#analysis{includes = Includes}};
+analyze_result({plt, Plt}, Args, Analysis) ->
+ {Args, Analysis#analysis{plt = Plt}};
+analyze_result({show_succ, Value}, Args, Analysis) ->
+ {Args, Analysis#analysis{show_succ = Value}};
+analyze_result({no_spec, Value}, Args, Analysis) ->
+ {Args, Analysis#analysis{no_spec = Value}}.
+
+%%--------------------------------------------------------------------
+%% File processing.
+%%--------------------------------------------------------------------
+
+-spec get_all_files(args(), analysis()) -> [file:filename(), ...].
+
+get_all_files(#args{files = Fs, files_r = Ds}, Analysis) ->
+ case filter_fd(Fs, Ds, fun test_erl_file_exclude_ann/1, Analysis) of
+ [] ->
+ fatal_error("no file(s) to analyze", Analysis);
+ AllFiles ->
+ AllFiles
+ end.
+
+-spec test_erl_file_exclude_ann(file:filename()) -> boolean().
+
+test_erl_file_exclude_ann(File) ->
+ case is_erl_file(File) of
+ true -> %% Exclude files ending with ".ann.erl"
+ case re:run(File, "[\.]ann[\.]erl$", [unicode]) of
+ {match, _} -> false;
+ nomatch -> true
+ end;
+ false -> false
+ end.
+
+-spec is_erl_file(file:filename()) -> boolean().
+
+is_erl_file(File) ->
+ filename:extension(File) =:= ".erl".
+
+-type test_file_fun() :: fun((file:filename()) -> boolean()).
+
+-spec filter_fd(files(), files(), test_file_fun(), analysis()) -> files().
+
+filter_fd(File_Dir, Dir_R, Fun, Analysis) ->
+ All_File_1 = process_file_and_dir(File_Dir, Fun, Analysis),
+ All_File_2 = process_dir_rec(Dir_R, Fun, Analysis),
+ remove_dup(All_File_1 ++ All_File_2).
+
+-spec process_file_and_dir(files(), test_file_fun(), analysis()) -> files().
+
+process_file_and_dir(File_Dir, TestFun, Analysis) ->
+ Fun =
+ fun (Elem, Acc) ->
+ case filelib:is_regular(Elem) of
+ true -> process_file(Elem, TestFun, Acc);
+ false -> check_dir(Elem, false, Acc, TestFun, Analysis)
+ end
+ end,
+ lists:foldl(Fun, [], File_Dir).
+
+-spec process_dir_rec(files(), test_file_fun(), analysis()) -> files().
+
+process_dir_rec(Dirs, TestFun, Analysis) ->
+ Fun = fun (Dir, Acc) -> check_dir(Dir, true, Acc, TestFun, Analysis) end,
+ lists:foldl(Fun, [], Dirs).
+
+-spec check_dir(file:filename(), boolean(), files(), test_file_fun(), analysis()) -> files().
+
+check_dir(Dir, Recursive, Acc, Fun, Analysis) ->
+ case file:list_dir(Dir) of
+ {ok, Files} ->
+ {TmpDirs, TmpFiles} = split_dirs_and_files(Files, Dir),
+ case Recursive of
+ false ->
+ FinalFiles = process_file_and_dir(TmpFiles, Fun, Analysis),
+ Acc ++ FinalFiles;
+ true ->
+ TmpAcc1 = process_file_and_dir(TmpFiles, Fun, Analysis),
+ TmpAcc2 = process_dir_rec(TmpDirs, Fun, Analysis),
+ Acc ++ TmpAcc1 ++ TmpAcc2
+ end;
+ {error, eacces} ->
+ fatal_error("no access permission to dir \""++Dir++"\"", Analysis);
+ {error, enoent} ->
+ fatal_error("cannot access "++Dir++": No such file or directory", Analysis);
+ {error, _Reason} ->
+ fatal_error("error involving a use of file:list_dir/1", Analysis)
+ end.
+
+%% Same order as the input list
+-spec process_file(file:filename(), test_file_fun(), files()) -> files().
+
+process_file(File, TestFun, Acc) ->
+ case TestFun(File) of
+ true -> Acc ++ [File];
+ false -> Acc
+ end.
+
+%% Same order as the input list
+-spec split_dirs_and_files(files(), file:filename()) -> {files(), files()}.
+
+split_dirs_and_files(Elems, Dir) ->
+ Test_Fun =
+ fun (Elem, {DirAcc, FileAcc}) ->
+ File = filename:join(Dir, Elem),
+ case filelib:is_regular(File) of
+ false -> {[File|DirAcc], FileAcc};
+ true -> {DirAcc, [File|FileAcc]}
+ end
+ end,
+ {Dirs, Files} = lists:foldl(Test_Fun, {[], []}, Elems),
+ {lists:reverse(Dirs), lists:reverse(Files)}.
+
+%% Removes duplicate filenames but keeps the order of the input list
+-spec remove_dup(files()) -> files().
+
+remove_dup(Files) ->
+ Test_Dup = fun (File, Acc) ->
+ case lists:member(File, Acc) of
+ true -> Acc;
+ false -> [File|Acc]
+ end
+ end,
+ Reversed_Elems = lists:foldl(Test_Dup, [], Files),
+ lists:reverse(Reversed_Elems).
+
+%%--------------------------------------------------------------------
+%% Collect information.
+%%--------------------------------------------------------------------
+
+-type inc_file_info() :: {file:filename(), func_info()}.
+
+-record(tmpAcc, {file :: file:filename(),
+ module :: atom(),
+ funcAcc = [] :: [func_info()],
+ incFuncAcc = [] :: [inc_file_info()],
+ dialyzerObj = [] :: [{mfa(), {_, _}}]}).
+
+-spec collect_info(analysis()) -> analysis().
+
+collect_info(Analysis) ->
+ NewPlt =
+ try get_dialyzer_plt(Analysis) of
+ DialyzerPlt ->
+ dialyzer_plt:merge_plts([Analysis#analysis.trust_plt, DialyzerPlt])
+ catch
+ throw:{dialyzer_error,_Reason} ->
+ fatal_error("Dialyzer's PLT is missing or is not up-to-date; please (re)create it",
+ Analysis)
+ end,
+ NewAnalysis = lists:foldl(fun collect_one_file_info/2,
+ Analysis#analysis{trust_plt = NewPlt},
+ Analysis#analysis.files),
+ %% Process Remote Types
+ TmpCServer = NewAnalysis#analysis.codeserver,
+ NewCServer =
+ try
+ TmpCServer1 = dialyzer_utils:merge_types(TmpCServer, NewPlt),
+ NewExpTypes = dialyzer_codeserver:get_temp_exported_types(TmpCServer),
+ OldExpTypes = dialyzer_plt:get_exported_types(NewPlt),
+ MergedExpTypes = sets:union(NewExpTypes, OldExpTypes),
+ TmpCServer2 =
+ dialyzer_codeserver:finalize_exported_types(MergedExpTypes, TmpCServer1),
+ TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2),
+ dialyzer_contracts:process_contract_remote_types(TmpCServer3)
+ catch
+ throw:{error, ErrorMsg} ->
+ fatal_error(ErrorMsg, NewAnalysis)
+ end,
+ NewAnalysis#analysis{codeserver = NewCServer}.
+
+collect_one_file_info(File, Analysis) ->
+ Ds = [{d,Name,Val} || {Name,Val} <- Analysis#analysis.macros],
+ %% Current directory should also be included in "Includes".
+ Includes = [filename:dirname(File)|Analysis#analysis.includes],
+ Is = [{i,Dir} || Dir <- Includes],
+ Options = dialyzer_utils:src_compiler_opts() ++ Is ++ Ds,
+ case dialyzer_utils:get_core_from_src(File, Options) of
+ {error, Reason} ->
+ msg(debug, "File=~tp\n,Options=~p\n,Error=~p", [File, Options, Reason], Analysis),
+ compile_error(Reason, Analysis);
+ {ok, Core} ->
+ case dialyzer_utils:get_record_and_type_info(Core) of
+ {error, Reason} -> compile_error([Reason], Analysis);
+ {ok, Records} ->
+ Mod = cerl:concrete(cerl:module_name(Core)),
+ case dialyzer_utils:get_spec_info(Mod, Core, Records) of
+ {error, Reason} -> compile_error([Reason], Analysis);
+ {ok, SpecInfo, CbInfo} ->
+ ExpTypes = get_exported_types_from_core(Core),
+ analyze_core_tree(Core, Records, SpecInfo, CbInfo,
+ ExpTypes, Analysis, File)
+ end
+ end
+ end.
+
+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,
+ NextLabel = dialyzer_codeserver:get_next_core_label(CS1),
+ {Tree, NewLabel} = cerl_trees:label(TmpTree, NextLabel),
+ CS2 = dialyzer_codeserver:insert(Module, Tree, CS1),
+ CS3 = dialyzer_codeserver:set_next_core_label(NewLabel, CS2),
+ CS4 = dialyzer_codeserver:store_temp_records(Module, Records, CS3),
+ CS5 =
+ case Analysis#analysis.no_spec of
+ true -> 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),
+ ExFuncs = [{0,F,A} || {_,_,{F,A}} <- cerl:module_exports(Tree)],
+ 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),
+ ExportedFuncMap = maps:put(File, ExFuncs, Analysis#analysis.ex_func),
+ %% we must sort all functions in the file which
+ %% originate from this file by *numerical order* of lineNo
+ SortedFunctions = lists:keysort(1, Acc#tmpAcc.funcAcc),
+ FuncMap = maps:put(File, SortedFunctions, Analysis#analysis.func),
+ %% we do not need to sort functions which are imported from included files
+ IncFuncMap = maps:put(File, Acc#tmpAcc.incFuncAcc, Analysis#analysis.inc_func),
+ FMs = Analysis#analysis.fms ++ [{File, Module}],
+ RecordMap = maps:put(File, Records, Analysis#analysis.record),
+ Analysis#analysis{fms = FMs,
+ callgraph = CG,
+ codeserver = CS6,
+ ex_func = ExportedFuncMap,
+ inc_func = IncFuncMap,
+ record = RecordMap,
+ func = FuncMap}.
+
+analyze_one_function({Var, FunBody} = Function, Acc) ->
+ F = cerl:fname_id(Var),
+ A = cerl:fname_arity(Var),
+ TmpDialyzerObj = {{Acc#tmpAcc.module, F, A}, Function},
+ NewDialyzerObj = Acc#tmpAcc.dialyzerObj ++ [TmpDialyzerObj],
+ Anno = cerl:get_ann(FunBody),
+ LineNo = get_line(Anno),
+ FileName = get_file(Anno),
+ BaseName = filename:basename(FileName),
+ FuncInfo = {LineNo, F, A},
+ OriginalName = Acc#tmpAcc.file,
+ {FuncAcc, IncFuncAcc} =
+ case (FileName =:= OriginalName) orelse (BaseName =:= OriginalName) of
+ true -> %% Coming from original file
+ {Acc#tmpAcc.funcAcc ++ [FuncInfo], Acc#tmpAcc.incFuncAcc};
+ false ->
+ %% Coming from other sourses, including:
+ %% -- .yrl (yecc-generated file)
+ %% -- yeccpre.hrl (yecc-generated file)
+ %% -- other cases
+ {Acc#tmpAcc.funcAcc, Acc#tmpAcc.incFuncAcc ++ [{FileName, FuncInfo}]}
+ end,
+ Acc#tmpAcc{funcAcc = FuncAcc,
+ incFuncAcc = IncFuncAcc,
+ dialyzerObj = NewDialyzerObj}.
+
+get_line([Line|_]) when is_integer(Line) -> Line;
+get_line([{Line, _Column} | _Tail]) when is_integer(Line) -> Line;
+get_line([_|Tail]) -> get_line(Tail);
+get_line([]) -> -1.
+
+get_file([{file,File}|_]) -> File;
+get_file([_|T]) -> get_file(T);
+get_file([]) -> "no_file". % should not happen
+
+-spec get_dialyzer_plt(analysis()) -> plt().
+
+get_dialyzer_plt(#analysis{plt = PltFile0}) ->
+ PltFile =
+ case PltFile0 =:= none of
+ true -> dialyzer_plt:get_default_plt();
+ false -> PltFile0
+ end,
+ dialyzer_plt:from_file(PltFile).
+
+%% Exported Types
+
+get_exported_types_from_core(Core) ->
+ Attrs = cerl:module_attrs(Core),
+ ExpTypes1 = [cerl:concrete(L2) || {L1, L2} <- Attrs,
+ cerl:is_literal(L1),
+ cerl:is_literal(L2),
+ cerl:concrete(L1) =:= 'export_type'],
+ ExpTypes2 = lists:flatten(ExpTypes1),
+ M = cerl:atom_val(cerl:module_name(Core)),
+ sets:from_list([{M, F, A} || {F, A} <- ExpTypes2]).
+
+%%--------------------------------------------------------------------
+%% Utilities for error reporting.
+%%--------------------------------------------------------------------
+
+-spec default_io() -> io().
+
+default_io() ->
+ #{debug => fun swallow_output/2,
+ info => fun format/2,
+ warn => fun format_on_stderr/2,
+ abort => fun format_and_halt/2}.
+
+-spec fatal_error(string(), analysis()) -> no_return().
+
+fatal_error(Slogan, Analysis) ->
+ msg(abort, "typer: ~ts", [Slogan], Analysis).
+
+-spec compile_error([string()], analysis()) -> no_return().
+
+compile_error(Reason, Analysis) ->
+ JoinedString = lists:flatten([X ++ "\n" || X <- Reason]),
+ Msg = "Analysis failed with error report:\n" ++ JoinedString,
+ fatal_error(Msg, Analysis).
+
+-spec msg(debug | info | warn | abort, io:format(), [term()], analysis()) -> _.
+
+msg(Level, Format, Data, #analysis{io = Io}) ->
+ Printer = maps:get(Level, Io, fun swallow_output/2),
+ Printer(Format, Data).
+
+-spec format(io:format(), [term()]) -> ok.
+
+format(Format, Data) ->
+ io:format(Format ++ "\n", Data).
+
+-spec swallow_output(io:format(), [term()]) -> ok.
+
+swallow_output(_Format, _Data) ->
+ ok.
+
+-spec format_on_stderr(io:format(), [term()]) -> ok.
+
+format_on_stderr(Format, Data) ->
+ io:format(standard_error, Format ++ "\n", Data).
+
+-spec format_and_halt(io:format(), [term()]) -> no_return().
+
+format_and_halt(Format, Data) ->
+ format_on_stderr(Format, Data),
+ erlang:halt(1).
+
+%%--------------------------------------------------------------------
+%% Handle messages.
+%%--------------------------------------------------------------------
+
+rcv_ext_types() ->
+ Self = self(),
+ Self ! {Self, done},
+ rcv_ext_types(Self, []).
+
+rcv_ext_types(Self, ExtTypes) ->
+ receive
+ {Self, ext_types, ExtType} ->
+ rcv_ext_types(Self, [ExtType|ExtTypes]);
+ {Self, done} ->
+ lists:usort(ExtTypes)
+ end.
diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile
index d5e975453f..7308c20400 100644
--- a/lib/dialyzer/test/Makefile
+++ b/lib/dialyzer/test/Makefile
@@ -12,6 +12,7 @@ AUXILIARY_FILES=\
dialyzer_common.erl\
file_utils.erl\
dialyzer_SUITE.erl\
+ dialyzer_cl_SUITE.erl\
abstract_SUITE.erl\
plt_SUITE.erl\
typer_SUITE.erl\
@@ -33,7 +34,7 @@ release_tests_spec:
$(INSTALL_DIR) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
$(INSTALL_DATA) $(AUXILIARY_FILES) "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ @tar cf - *_SUITE_data property_test | (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/results/gen_server_incorrect_args b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
index 69c2186481..a1412f29e6 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
@@ -2,4 +2,4 @@
gen_server_incorrect_args.erl:3:2: Undefined callback function handle_cast/2 (behaviour gen_server)
gen_server_incorrect_args.erl:3:2: Undefined callback function init/1 (behaviour gen_server)
gen_server_incorrect_args.erl:7:1: The inferred return type of handle_call/3 ({'no'} | {'ok'}) has nothing in common with {'noreply',_} | {'noreply',_,'hibernate' | 'infinity' | non_neg_integer() | {'continue',_}} | {'reply',_,_} | {'stop',_,_} | {'reply',_,_,'hibernate' | 'infinity' | non_neg_integer() | {'continue',_}} | {'stop',_,_,_}, which is the expected return type for the callback of the gen_server behaviour
-gen_server_incorrect_args.erl:7:1: 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
+gen_server_incorrect_args.erl:7:1: The inferred type for the 2nd argument of handle_call/3 ('boo' | 'foo') is not a supertype of {pid(),gen_server:reply_tag()}, 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_not_exported b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_not_exported
new file mode 100644
index 0000000000..d5a375bf58
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_not_exported
@@ -0,0 +1,3 @@
+
+gen_server_not_exported.erl:14:1: Callback function init/1 exists but is not exported (behaviour gen_server)
+gen_server_not_exported.erl:23:1: Callback function handle_cast/2 exists but is not exported (behaviour gen_server)
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_not_exported.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_not_exported.erl
new file mode 100644
index 0000000000..5c5bf3fbff
--- /dev/null
+++ b/lib/dialyzer/test/behaviour_SUITE_data/src/gen_server_not_exported.erl
@@ -0,0 +1,30 @@
+-module(gen_server_not_exported).
+
+-behaviour(gen_server).
+
+-export([main/0, handle_call/3]).
+
+%% Not exported. Should be a warning.
+main() ->
+ _ = init(whatever),
+ _ = handle_cast(whatever, some_state),
+ _ = format_status(<<"xyz">>),
+ ok.
+
+init(_) ->
+ ok.
+
+%% OK. No warning.
+handle_call(_Request, _From, State) ->
+ {noreply, State}.
+
+%% Not exported. Should be a warning.
+-spec handle_cast(any(), any()) -> binary().
+handle_cast(_Request, _State) ->
+ <<"abc">>.
+
+%% Not exported and conflicting arguments and return value. No warning
+%% since format_status/1 is an optional callback.
+-spec format_status(binary()) -> binary().
+format_status(Bin) when is_binary(Bin) ->
+ Bin.
diff --git a/lib/dialyzer/test/dialyzer.spec b/lib/dialyzer/test/dialyzer.spec
index 0ba5df5d1e..6551910461 100644
--- a/lib/dialyzer/test/dialyzer.spec
+++ b/lib/dialyzer/test/dialyzer.spec
@@ -1,5 +1 @@
-{alias, tests, "../dialyzer_test"}.
-
-{suites, tests, all}.
-
-{skip_cases, tests, small_SUITE, "Needs compiler in plt"}.
+{suites, "../dialyzer_test", all}.
diff --git a/lib/dialyzer/test/dialyzer_SUITE.erl b/lib/dialyzer/test/dialyzer_SUITE.erl
index 0676e6c599..058fdc8a50 100644
--- a/lib/dialyzer/test/dialyzer_SUITE.erl
+++ b/lib/dialyzer/test/dialyzer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
-include_lib("common_test/include/ct.hrl").
%% Default timetrap timeout (set in init_per_testcase).
--define(default_timeout, test_server:minutes(1)).
+-define(default_timeout, test_server:minutes(10)).
-define(application, dialyzer).
%% Test server specific exports
@@ -31,12 +31,12 @@
-export([init_per_testcase/2, end_per_testcase/2]).
%% Test cases must be exported.
--export([app_test/1, appup_test/1]).
+-export([app_test/1, appup_test/1, file_list/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app_test, appup_test].
+ [app_test, appup_test, file_list].
groups() ->
[].
@@ -55,7 +55,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),
@@ -71,8 +71,61 @@ app_test(doc) ->
app_test(suite) ->
[];
app_test(Config) when is_list(Config) ->
- ?line test_server:app_test(dialyzer).
+ test_server:app_test(dialyzer).
%% Test that the .appup file does not contain any `basic' errors
appup_test(Config) when is_list(Config) ->
ok = test_server:appup_test(dialyzer).
+
+file_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ case dialyzer_common:check_plt(PrivDir) of
+ fail -> ct:fail("Plt creation/check failed");
+ ok -> ok
+ end,
+
+ Files = generate_modules(PrivDir, 26),
+ ListFile = filename:join(PrivDir, "list_of_files"),
+ ok = file:write_file(ListFile, [lists:join("\n", Files), "\n"]),
+
+ Expected = expected(Files),
+ ExpectedFile = filename:join(PrivDir, "expected"),
+ ok = file:write_file(ExpectedFile, Expected),
+
+ Plt = dialyzer_common:plt_file(PrivDir),
+ Result = os:cmd("dialyzer --plt " ++ Plt ++ " -q --src --input_list_file " ++ ListFile),
+ ResultFile = filename:join(PrivDir, "result"),
+ ok = file:write_file(ResultFile, Result),
+
+ case file_utils:diff(ResultFile, ExpectedFile) of
+ same ->
+ ok;
+ Diff ->
+ io:format("~p\n", [Diff]),
+ ct:fail(unexpected_result)
+ end.
+
+generate_modules(_Dir, 0) ->
+ [];
+generate_modules(Dir, N) ->
+ Name = "module_" ++ integer_to_list(N),
+ File = filename:join(Dir, Name ++ ".erl"),
+ Code = <<"-module(",(list_to_binary(Name))/binary,").\n",
+ "-export([main/1]).\n",
+ "main(L) ->\n",
+ " case list_to_atom(L) of\n",
+ " Atom when is_atom(Atom) -> {ok,Atom};\n",
+ " _ -> error\n",
+ " end.\n"
+ >>,
+ ok = file:write_file(File, Code),
+ [File|generate_modules(Dir, N - 1)].
+
+expected(Files0) ->
+ Files = lists:sort(Files0),
+ S = "\n" ++
+ [filename:basename(F) ++
+ ":6:5: The variable _ can never match since previous clauses completely covered the type \n"
+ " atom()\n" || F <- Files],
+ iolist_to_binary(S).
diff --git a/lib/dialyzer/test/dialyzer_cl_SUITE.erl b/lib/dialyzer/test/dialyzer_cl_SUITE.erl
new file mode 100644
index 0000000000..ed84fc6068
--- /dev/null
+++ b/lib/dialyzer/test/dialyzer_cl_SUITE.erl
@@ -0,0 +1,129 @@
+-module(dialyzer_cl_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
+-include_lib("dialyzer/src/dialyzer.hrl").
+
+%% Test server specific exports
+-export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).
+
+%% Test cases must be exported.
+-export([
+ unknown_function_warning_includes_callsite/1,
+ call_to_missing_warning_includes_callsite/1
+]).
+
+suite() -> [{timetrap, {minutes, 1}}].
+
+all() ->
+ [
+ unknown_function_warning_includes_callsite,
+ call_to_missing_warning_includes_callsite
+ ].
+
+init_per_suite(Config) ->
+ %% Prime PLT with common stuff so we don't get errors about get_module_info
+ %% being unknown, etc.
+ PrivDir = proplists:get_value(priv_dir,Config),
+ PltBase = plt_base_file(PrivDir),
+ _ = dialyzer:run([{analysis_type, plt_build},
+ {apps, [erts]},
+ {output_plt, PltBase}]),
+ Config.
+
+end_per_suite(Config) ->
+ Config.
+
+plt_base_file(PrivDir) ->
+ filename:join(PrivDir, "dialyzer_cl_base.plt").
+
+%%%
+%%% Test cases starts here.
+%%%
+
+%% Test running Dialyzer programatically can yield call to missing
+%% errors with information on both the callsite and the unknown call
+%% itself.
+%% Missing function logic is tested elsewhere, but here we're specifically
+%% interested in the details of the error that are accessible from the
+%% dialyzer_cl API
+call_to_missing_warning_includes_callsite(Config) when is_list(Config) ->
+
+ PrivDir = proplists:get_value(priv_dir,Config),
+ PltBase = plt_base_file(PrivDir),
+ Plt = filename:join(PrivDir, "previously_defined.plt"),
+
+ {ok, BeamFileForPlt} = compile(Config, previously_defined, []),
+ [] = dialyzer:run([{analysis_type, plt_build},
+ {files, [BeamFileForPlt]},
+ {output_plt, Plt}]),
+
+ {ok, Beam} = compile(Config, call_to_missing_example, []),
+ Opts =
+ #options{
+ analysis_type = succ_typings,
+ init_plts = [Plt, PltBase],
+ output_file = none,
+ get_warnings = true,
+ legal_warnings = ordsets:from_list([warn_unknown, warn_callgraph]),
+ erlang_mode = true,
+ files = [Beam]
+ },
+ Res = dialyzer_cl:start(Opts),
+
+ ?assertMatch(
+ {2, [
+ {warn_callgraph, {_Filename, {5, 5}}, {
+ call_to_missing, [
+ previously_defined, function, 0
+ ]
+ }}
+ ]},
+ Res),
+
+ ok.
+
+%% Test running Dialyzer programatically can yield unknown function
+%% errors with information on both the callsite and the unknown call
+%% itself.
+%% Missing function logic is tested elsewhere, but here we're specifically
+%% interested in the details of the error that are accessible from the
+%% dialyzer_cl API
+unknown_function_warning_includes_callsite(Config) when is_list(Config) ->
+
+ PrivDir = proplists:get_value(priv_dir,Config),
+ PltBase = plt_base_file(PrivDir),
+
+ {ok, Beam} = compile(Config, unknown_function_example, []),
+ Opts =
+ #options{
+ analysis_type = succ_typings,
+ init_plts = [PltBase],
+ output_file = none,
+ get_warnings = true,
+ legal_warnings = ordsets:from_list([warn_unknown, warn_callgraph]),
+ erlang_mode = true,
+ files = [Beam]
+ },
+ Res = dialyzer_cl:start(Opts),
+
+ ?assertMatch(
+ {2, [
+ {warn_unknown, {_Filename, {5,5}},
+ {unknown_function, {
+ does_not_exist, function, 0
+ }}
+ }
+ ]},
+ Res),
+
+ ok.
+
+compile(Config, Module, CompileOpts) ->
+ Source = lists:concat([Module, ".erl"]),
+ PrivDir = proplists:get_value(priv_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
+ SrcFilename = filename:join([DataDir, Source]),
+ Opts = [{outdir, PrivDir}, debug_info | CompileOpts],
+ {ok, Module} = compile:file(SrcFilename, Opts),
+ {ok, filename:join([PrivDir, lists:concat([Module, ".beam"])])}.
diff --git a/lib/dialyzer/test/dialyzer_cl_SUITE_data/call_to_missing_example.erl b/lib/dialyzer/test/dialyzer_cl_SUITE_data/call_to_missing_example.erl
new file mode 100644
index 0000000000..96670f1221
--- /dev/null
+++ b/lib/dialyzer/test/dialyzer_cl_SUITE_data/call_to_missing_example.erl
@@ -0,0 +1,5 @@
+-module(call_to_missing_example).
+-export([call_to_missing_test/0]).
+
+call_to_missing_test() ->
+ previously_defined:function().
diff --git a/lib/dialyzer/test/dialyzer_cl_SUITE_data/previously_defined.erl b/lib/dialyzer/test/dialyzer_cl_SUITE_data/previously_defined.erl
new file mode 100644
index 0000000000..5b03eb2b7c
--- /dev/null
+++ b/lib/dialyzer/test/dialyzer_cl_SUITE_data/previously_defined.erl
@@ -0,0 +1,5 @@
+-module(previously_defined).
+
+-export([do_thing/0]).
+
+do_thing() -> ok.
diff --git a/lib/dialyzer/test/dialyzer_cl_SUITE_data/unknown_function_example.erl b/lib/dialyzer/test/dialyzer_cl_SUITE_data/unknown_function_example.erl
new file mode 100644
index 0000000000..c9a93010c8
--- /dev/null
+++ b/lib/dialyzer/test/dialyzer_cl_SUITE_data/unknown_function_example.erl
@@ -0,0 +1,5 @@
+-module(unknown_function_example).
+-export([unknown_function_test/0]).
+
+unknown_function_test() ->
+ does_not_exist:function().
diff --git a/lib/dialyzer/test/dialyzer_common.erl b/lib/dialyzer/test/dialyzer_common.erl
index 392c41306e..ca1fc1993a 100644
--- a/lib/dialyzer/test/dialyzer_common.erl
+++ b/lib/dialyzer/test/dialyzer_common.erl
@@ -13,6 +13,7 @@
-define(suite_suffix, "_SUITE").
-define(data_folder, "_data").
+-define(excludes, ["dialyzer_cl", "plt"]). % _SUITE_data dirs that we shouldn't automatically make suites for
-define(suite_data, ?suite_suffix ++ ?data_folder).
-define(erlang_extension, ".erl").
-define(output_file_mode, write).
@@ -20,7 +21,6 @@
-define(input_files_directory, "src").
-define(result_files_directory, "results").
-define(plt_filename,"dialyzer_plt").
--define(home_plt_filename,".dialyzer_plt").
-define(plt_lockfile,"plt_lock").
-define(required_modules, [erts, kernel, stdlib]).
@@ -45,7 +45,7 @@ check_plt(OutDir) ->
{error, _ } ->
io:format("No plt found in test run directory!"),
PltLockFile = filename:join(OutDir, ?plt_lockfile),
- case file:read_file_info(PltLockFile) of
+ case file:read_file_info(PltLockFile) of
{ok, _} ->
explain_fail_with_lock(),
fail;
@@ -89,14 +89,13 @@ explain_fail_with_lock() ->
obtain_plt(PltFilename) ->
io:format("Obtaining plt:"),
- HomeDir = os:getenv("HOME"),
- HomePlt = filename:join(HomeDir, ?home_plt_filename),
+ InitPlt = dialyzer_plt:get_default_plt(),
io:format("Will try to use ~s as a starting point and add otp apps ~w.",
- [HomePlt, ?required_modules]),
+ [InitPlt, ?required_modules]),
try dialyzer:run([{analysis_type, plt_add},
{apps, ?required_modules},
{output_plt, PltFilename},
- {init_plt, HomePlt}]) of
+ {init_plt, InitPlt}]) of
[] ->
io:format("Successfully added everything!"),
ok
@@ -178,7 +177,7 @@ fix_options([{pa, Path} | Rest], Dir, Acc) ->
true -> fix_options(Rest, Dir, Acc);
{error, _} -> erlang:error("Bad directory for pa: " ++ Path)
end;
-fix_options([{DirOption, RelativeDirs} | Rest], Dir, Acc)
+fix_options([{DirOption, RelativeDirs} | Rest], Dir, Acc)
when DirOption =:= include_dirs ;
DirOption =:= files_rec ;
DirOption =:= files ->
@@ -215,15 +214,21 @@ get_suites(Dir) ->
{error, _} -> [];
{ok, Filenames} ->
FullFilenames = [filename:join(Dir, F) || F <-Filenames ],
- Dirs = [suffix(filename:basename(F), ?suite_data) ||
+ Dirs = [is_suite_data(filename:basename(F), ?suite_data) ||
F <- FullFilenames,
file_utils:file_type(F) =:= {ok, 'directory'}],
[S || {yes, S} <- Dirs]
end.
-suffix(String, Suffix) ->
+is_suite_data(String, Suffix) ->
case string:split(String, Suffix, trailing) of
- [Prefix,[]] -> {yes, Prefix};
+ [Prefix,[]] ->
+ case lists:member(Prefix, ?excludes) of
+ true ->
+ no;
+ false ->
+ {yes, Prefix}
+ end;
_ -> no
end.
diff --git a/lib/dialyzer/test/erl_types_SUITE.erl b/lib/dialyzer/test/erl_types_SUITE.erl
index bc735d3a60..5674ffd1cb 100644
--- a/lib/dialyzer/test/erl_types_SUITE.erl
+++ b/lib/dialyzer/test/erl_types_SUITE.erl
@@ -14,8 +14,11 @@
%%
-module(erl_types_SUITE).
--export([all/0,
- consistency_and_to_string/1, map_multiple_representations/1]).
+-export([all/0,groups/0,init_per_group/2,end_per_group/2,
+ consistency_and_to_string/1,misc/1,map_multiple_representations/1,
+ absorption/1,associativity/1,commutativity/1,idempotence/1,
+ identity/1,limit/1
+ ]).
%% Simplify calls into erl_types and avoid importing the entire module.
-define(M, erl_types).
@@ -23,7 +26,39 @@
-include_lib("common_test/include/ct.hrl").
all() ->
- [consistency_and_to_string, map_multiple_representations].
+ [consistency_and_to_string,
+ misc,
+ map_multiple_representations,
+ {group,property_tests}
+ ].
+
+groups() ->
+ [{property_tests,[parallel],
+ [absorption,
+ associativity,
+ commutativity,
+ idempotence,
+ identity,
+ limit]}].
+
+init_per_group(property_tests, Config0) ->
+ case ct_property_test:init_per_suite(Config0) of
+ [_|_]=Config ->
+ try proper_erlang_abstract_code:module() of
+ _ ->
+ Config
+ catch
+ error:undef ->
+ {skip, "No proper_erlang_abstract_code module"}
+ end;
+ Other ->
+ Other
+ end;
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
consistency_and_to_string(_Config) ->
%% Check consistency of types
@@ -196,6 +231,16 @@ consistency_and_to_string(_Config) ->
"{'false',_} | {'true',_}" = ?M:t_to_string(Union10),
"{'true',integer()}" = ?M:t_to_string(?M:t_inf(Union10, ?M:t_tuple([?M:t_atom(true), ?M:t_integer()]))).
+misc(_Config) ->
+ %% Miscellaneous cases which have been fixed.
+
+ %% Used to take "forever".
+ B1_1 = ?M:t_bitstr(6442450944, 1456),
+ B1_2 = ?M:t_bitstr(85, 7),
+ R1_R = ?M:t_bitstr(547608330240, 347892352432),
+ R1_R = ?M:t_inf(B1_1, B1_2),
+ ok.
+
%% OTP-17537.
map_multiple_representations(_Config) ->
DefV = erl_types:t_atom(),
@@ -311,3 +356,27 @@ map_multiple_representations(_Config) ->
"#{'a'=>atom(), 'b'=>atom()}" = erl_types:t_to_string(T)
end(),
ok.
+
+absorption(Config) ->
+ %% manual test: proper:quickcheck(erl_types_prop:absorption()).
+ true = ct_property_test:quickcheck(erl_types_prop:absorption(), Config).
+
+associativity(Config) ->
+ %% manual test: proper:quickcheck(erl_types_prop:associativity()).
+ true = ct_property_test:quickcheck(erl_types_prop:associativity(), Config).
+
+commutativity(Config) ->
+ %% manual test: proper:quickcheck(erl_types_prop:commutativity()).
+ true = ct_property_test:quickcheck(erl_types_prop:commutativity(), Config).
+
+idempotence(Config) ->
+ %% manual test: proper:quickcheck(erl_types_prop:idempotence()).
+ true = ct_property_test:quickcheck(erl_types_prop:idempotence(), Config).
+
+identity(Config) ->
+ %% manual test: proper:quickcheck(erl_types_prop:identity()).
+ true = ct_property_test:quickcheck(erl_types_prop:identity(), Config).
+
+limit(Config) ->
+ %% manual test: proper:quickcheck(erl_types_prop:limit()).
+ true = ct_property_test:quickcheck(erl_types_prop:limit(), Config).
diff --git a/lib/dialyzer/test/extra_return_SUITE_data/dialyzer_options b/lib/dialyzer/test/extra_return_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..c83f8d286d
--- /dev/null
+++ b/lib/dialyzer/test/extra_return_SUITE_data/dialyzer_options
@@ -0,0 +1 @@
+{dialyzer_options, [{indent_opt, false}, {warnings, [extra_return]}]}.
diff --git a/lib/dialyzer/test/extra_return_SUITE_data/results/extra_return b/lib/dialyzer/test/extra_return_SUITE_data/results/extra_return
new file mode 100644
index 0000000000..63895a231d
--- /dev/null
+++ b/lib/dialyzer/test/extra_return_SUITE_data/results/extra_return
@@ -0,0 +1,2 @@
+
+extra_return.erl:7:2: The specification for extra_return:t1/0 states that the function might also return 'other' but the inferred return is boolean()
diff --git a/lib/dialyzer/test/extra_return_SUITE_data/src/extra_return.erl b/lib/dialyzer/test/extra_return_SUITE_data/src/extra_return.erl
new file mode 100644
index 0000000000..4cebbab02e
--- /dev/null
+++ b/lib/dialyzer/test/extra_return_SUITE_data/src/extra_return.erl
@@ -0,0 +1,21 @@
+-module(extra_return).
+
+-export([t1/0, t2/0]).
+
+
+% Should warn about having `undefined` as return value when it is not returned by the function
+-spec t1() -> true | false | 'other'.
+t1() ->
+ case rand:uniform(2) of
+ 1 -> true;
+ 2 -> false
+ end.
+
+% Should not warn about extra return
+-dialyzer({no_extra_return, t2/0}).
+-spec t2() -> true | false | 'other'.
+t2() ->
+ case rand:uniform(2) of
+ 1 -> true;
+ 2 -> false
+ end.
diff --git a/lib/dialyzer/test/indent_SUITE_data/dialyzer_options b/lib/dialyzer/test/indent_SUITE_data/dialyzer_options
index 7c088f9a65..3ff26b87db 100644
--- a/lib/dialyzer/test/indent_SUITE_data/dialyzer_options
+++ b/lib/dialyzer/test/indent_SUITE_data/dialyzer_options
@@ -1 +1 @@
-{dialyzer_options, [{warnings, [no_unused, no_return, race_conditions]}]}.
+{dialyzer_options, [{warnings, [no_unused, no_return]}]}.
diff --git a/lib/dialyzer/test/indent_SUITE_data/results/whereis_control_flow1 b/lib/dialyzer/test/indent_SUITE_data/results/whereis_control_flow1
deleted file mode 100644
index 1154cada8a..0000000000
--- a/lib/dialyzer/test/indent_SUITE_data/results/whereis_control_flow1
+++ /dev/null
@@ -1,4 +0,0 @@
-
-whereis_control_flow1.erl:13:18: The call erlang:register
- (AnAtom :: atom(),
- Pid :: pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_control_flow1.erl on line {8,8}
diff --git a/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl b/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl
index 99eb73a5f6..616d4d62bf 100644
--- a/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl
+++ b/lib/dialyzer/test/indent_SUITE_data/src/map_galore.erl
@@ -1649,9 +1649,9 @@ cmp_others(T1, T2, _) ->
map_gen(Pairs, Size) ->
{_,L} = lists:foldl(fun(_, {Keys, Acc}) ->
- KI = random:uniform(size(Keys)),
+ KI = random:uniform(tuple_size(Keys)),
K = element(KI,Keys),
- KV = element(random:uniform(size(K)), K),
+ KV = element(random:uniform(tuple_size(K)), K),
{erlang:delete_element(KI,Keys), [KV | Acc]}
end,
{Pairs, []},
diff --git a/lib/dialyzer/test/indent_SUITE_data/src/whereis_control_flow1.erl b/lib/dialyzer/test/indent_SUITE_data/src/whereis_control_flow1.erl
deleted file mode 100644
index e65f6c3e23..0000000000
--- a/lib/dialyzer/test/indent_SUITE_data/src/whereis_control_flow1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> register(AnAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/map_SUITE_data/results/opaque_key b/lib/dialyzer/test/map_SUITE_data/results/opaque_key
index b3a2d2b78c..b70157f1af 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/opaque_key
+++ b/lib/dialyzer/test/map_SUITE_data/results/opaque_key
@@ -4,8 +4,8 @@ opaque_key_adt.erl:41:2: Invalid type specification for function opaque_key_adt:
opaque_key_adt.erl:44:2: Invalid type specification for function opaque_key_adt:s5/0. The success typing is () -> #{2:=3}
opaque_key_adt.erl:56:2: Invalid type specification for function opaque_key_adt:smt1/0. The success typing is () -> #{3:='a'}
opaque_key_adt.erl:59:2: Invalid type specification for function opaque_key_adt:smt2/0. The success typing is () -> #{1:='a'}
-opaque_key_use.erl:13:5: The test opaque_key_use:t() =:= opaque_key_use:t(integer()) can never evaluate to 'true'
-opaque_key_use.erl:24:5: Attempt to test for equality between a term of type opaque_key_adt:t(integer()) and a term of opaque type opaque_key_adt:t()
+opaque_key_use.erl:13:5: The test opaque_key_use:t() =:= opaque_key_use:t(_) can never evaluate to 'true'
+opaque_key_use.erl:24:5: Attempt to test for equality between a term of type opaque_key_adt:t(_) and a term of opaque type opaque_key_adt:t()
opaque_key_use.erl:37:1: Function adt_mm1/0 has no local return
opaque_key_use.erl:40:5: The attempt to match a term of type opaque_key_adt:m() against the pattern #{A:=R} breaks the opacity of the term
opaque_key_use.erl:48:1: Function adt_mu1/0 has no local return
diff --git a/lib/dialyzer/test/missing_return_SUITE_data/dialyzer_options b/lib/dialyzer/test/missing_return_SUITE_data/dialyzer_options
new file mode 100644
index 0000000000..d7ee920ade
--- /dev/null
+++ b/lib/dialyzer/test/missing_return_SUITE_data/dialyzer_options
@@ -0,0 +1 @@
+{dialyzer_options, [{indent_opt, false}, {warnings, [missing_return]}]}.
diff --git a/lib/dialyzer/test/missing_return_SUITE_data/results/missing_return b/lib/dialyzer/test/missing_return_SUITE_data/results/missing_return
new file mode 100644
index 0000000000..3f0464b680
--- /dev/null
+++ b/lib/dialyzer/test/missing_return_SUITE_data/results/missing_return
@@ -0,0 +1,2 @@
+
+missing_return.erl:7:2: The success typing for missing_return:t1/0 implies that the function might also return 'false' but the specification return is 'true'
diff --git a/lib/dialyzer/test/missing_return_SUITE_data/src/missing_return.erl b/lib/dialyzer/test/missing_return_SUITE_data/src/missing_return.erl
new file mode 100644
index 0000000000..64e7766c83
--- /dev/null
+++ b/lib/dialyzer/test/missing_return_SUITE_data/src/missing_return.erl
@@ -0,0 +1,21 @@
+-module(missing_return).
+
+-export([t1/0, t2/0]).
+
+
+% Should warn about only having true when also false is returned
+-spec t1() -> true.
+t1() ->
+ case rand:uniform(2) of
+ 1 -> true;
+ 2 -> false
+ end.
+
+% Should not warn about missing return
+-dialyzer({no_missing_return, t2/0}).
+-spec t2() -> true.
+t2() ->
+ case rand:uniform(2) of
+ 1 -> true;
+ 2 -> false
+ end.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/para b/lib/dialyzer/test/opaque_SUITE_data/results/para
index d0ddab7b66..0ba2a24996 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/results/para
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/para
@@ -1,34 +1,24 @@
-para1.erl:18:5: The test para1:t(atom()) =:= para1:t(integer()) can never evaluate to 'true'
-para1.erl:23:5: The test para1:t(atom()) =:= para1:t() can never evaluate to 'true'
-para1.erl:28:5: The test para1:t() =:= para1:t(integer()) can never evaluate to 'true'
+para1.erl:18:5: The test para1:t(_) =:= para1:t(_) can never evaluate to 'true'
+para1.erl:23:5: The test para1:t(_) =:= para1:t() can never evaluate to 'true'
+para1.erl:28:5: The test para1:t() =:= para1:t(_) can never evaluate to 'true'
para1.erl:33:5: The test {3,2} =:= {'a','b'} can never evaluate to 'true'
-para1.erl:38:5: Attempt to test for equality between a term of type para1_adt:t(integer()) and a term of opaque type para1_adt:t(atom())
-para1.erl:43:5: Attempt to test for equality between a term of type para1_adt:t() and a term of opaque type para1_adt:t(atom())
-para1.erl:48:5: Attempt to test for equality between a term of type para1_adt:t(integer()) and a term of opaque type para1_adt:t()
+para1.erl:38:5: The test para1_adt:t(_) =:= para1_adt:t(_) can never evaluate to 'true'
+para1.erl:43:5: Attempt to test for equality between a term of type para1_adt:t() and a term of opaque type para1_adt:t(_)
+para1.erl:48:5: Attempt to test for equality between a term of type para1_adt:t(_) and a term of opaque type para1_adt:t()
para1.erl:53:5: The test {3,2} =:= {'a','b'} can never evaluate to 'true'
-para2.erl:103:5: Attempt to test for equality between a term of type para2_adt:circ(integer(),integer()) and a term of opaque type para2_adt:circ(integer())
-para2.erl:117:5: Attempt to test for equality between a term of type para2_adt:un(atom(),integer()) and a term of opaque type para2_adt:un(integer(),atom())
+para2.erl:103:5: Attempt to test for equality between a term of type para2_adt:circ(_,_) and a term of opaque type para2_adt:circ(_)
para2.erl:31:5: The test 'a' =:= 'b' can never evaluate to 'true'
para2.erl:61:5: Attempt to test for equality between a term of type para2_adt:c2() and a term of opaque type para2_adt:c1()
para2.erl:66:5: The test 'a' =:= 'b' can never evaluate to 'true'
-para2.erl:88:5: The test para2:circ(integer()) =:= para2:circ(integer(),integer()) can never evaluate to 'true'
+para2.erl:88:5: The test para2:circ(_) =:= para2:circ(_,_) can never evaluate to 'true'
para3.erl:28:2: Invalid type specification for function para3:ot2/0. The success typing is () -> 'foo'
para3.erl:36:5: The pattern {{{17}}} can never match the type {{{{{{_,_,_,_,_}}}}}}
para3.erl:55:2: Invalid type specification for function para3:t2/0. The success typing is () -> 'foo'
para3.erl:65:5: The attempt to match a term of type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}} against the pattern {{{{{17}}}}} breaks the opacity of para3_adt:ot1(_,_,_,_,_)
para3.erl:68:5: The pattern {{{{17}}}} can never match the type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}}
-para3.erl:74:2: The specification for para3:exp_adt/0 has an opaque subtype para3_adt:exp1(para3_adt:exp2()) which is violated by the success typing () -> 3
-para4.erl:21:2: Invalid type specification for function para4:a/1. The success typing is (para4:d_all() | para4:d_atom()) -> [{atom() | integer(),atom() | integer()}]
-para4.erl:26:2: Invalid type specification for function para4:i/1. The success typing is (para4:d_all() | para4:d_integer()) -> [{atom() | integer(),atom() | integer()}]
+para3.erl:74:2: The specification for para3:exp_adt/0 has an opaque subtype para3_adt:exp1(_) which is violated by the success typing () -> 3
para4.erl:31:2: Invalid type specification for function para4:t/1. The success typing is (para4:d_all() | para4:d_tuple()) -> [{atom() | integer(),atom() | integer()}]
-para4.erl:59:5: Attempt to test for equality between a term of type para4_adt:t(atom() | integer()) and a term of opaque type para4_adt:t(integer())
-para4.erl:64:5: Attempt to test for equality between a term of type para4_adt:t(atom() | integer()) and a term of opaque type para4_adt:t(atom())
-para4.erl:69:5: Attempt to test for equality between a term of type para4_adt:int(1 | 2 | 3 | 4) and a term of opaque type para4_adt:int(1 | 2)
-para4.erl:74:5: Attempt to test for equality between a term of type para4_adt:int(2 | 3 | 4) and a term of opaque type para4_adt:int(1 | 2)
-para4.erl:79:5: Attempt to test for equality between a term of type para4_adt:int(2 | 3 | 4) and a term of opaque type para4_adt:int(5 | 6 | 7)
-para4.erl:84:5: Attempt to test for equality between a term of type para4_adt:un(3 | 4) and a term of opaque type para4_adt:un(1 | 2)
-para4.erl:89:5: Attempt to test for equality between a term of type para4_adt:tup({_,_}) and a term of opaque type para4_adt:tup(tuple())
-para4.erl:94:5: Attempt to test for equality between a term of type para4_adt:t(#{1=>'a'}) and a term of opaque type para4_adt:t(#{2=>'b'})
-para5.erl:13:5: Attempt to test for inequality between a term of type para5_adt:dd(atom()) and a term of opaque type para5_adt:d()
+para4.erl:79:5: The test para4_adt:int(_) =:= para4_adt:int(_) can never evaluate to 'true'
+para5.erl:13:5: Attempt to test for inequality between a term of type para5_adt:dd(_) and a term of opaque type para5_adt:d()
para5.erl:8:5: The test para5_adt:d() =:= para5_adt:d() can never evaluate to 'true'
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl
index d286a378ed..a01e20710a 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -409,7 +409,7 @@ normalise({bin,_,Fs}) ->
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
{value, normalise(E), []}
- end, [], true),
+ end),
B;
normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl
index 7daceb5260..78e069ab79 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -406,7 +406,7 @@ normalise({bin,_,Fs}) ->
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
{value, normalise(E), []}
- end, [], true),
+ end),
B;
normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
index 5cbc79f948..3702c30747 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
@@ -55,7 +55,7 @@
bag()}.
-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec')
- and (size(R) =:= 6))).
+ and (tuple_size(R) =:= 6))).
-define(GET_EWGI_READ_INPUT(R), element(2, R)).
-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)).
-define(GET_EWGI_WRITE_ERROR(R), element(3, R)).
@@ -88,7 +88,7 @@
ewgi_header_val(), bag()}.
-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers')
- and (size(R) =:= 8))).
+ and (tuple_size(R) =:= 8))).
-define(GET_HTTP_ACCEPT(R), element(2, R)).
-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)).
-define(GET_HTTP_COOKIE(R), element(3, R)).
@@ -129,7 +129,7 @@
ewgi_val(), ewgi_val()}.
-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request')
- and (size(R) =:= 21))).
+ and (tuple_size(R) =:= 21))).
-define(GET_AUTH_TYPE(R), element(2, R)).
-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)).
-define(GET_CONTENT_LENGTH(R), element(3, R)).
@@ -192,7 +192,7 @@
-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}.
-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response')
- and (size(R) =:= 5))).
+ and (tuple_size(R) =:= 5))).
-define(GET_RESPONSE_STATUS(R), element(2, R)).
-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)).
-define(GET_RESPONSE_HEADERS(R), element(3, R)).
@@ -209,7 +209,7 @@
-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context')
and ?IS_EWGI_REQUEST(element(2, R))
and ?IS_EWGI_RESPONSE(element(3, R))
- and (size(R) =:= 3))).
+ and (tuple_size(R) =:= 3))).
-define(GET_EWGI_REQUEST(R), element(2, R)).
-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)).
-define(GET_EWGI_RESPONSE(R), element(3, R)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
index d8e15cb081..f961c0b67e 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
@@ -56,7 +56,7 @@
bag()}.
-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec')
- and (size(R) =:= 6))).
+ and (tuple_size(R) =:= 6))).
-define(GET_EWGI_READ_INPUT(R), element(2, R)).
-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)).
-define(GET_EWGI_WRITE_ERROR(R), element(3, R)).
@@ -89,7 +89,7 @@
ewgi_header_val(), bag()}.
-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers')
- and (size(R) =:= 8))).
+ and (tuple_size(R) =:= 8))).
-define(GET_HTTP_ACCEPT(R), element(2, R)).
-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)).
-define(GET_HTTP_COOKIE(R), element(3, R)).
@@ -130,7 +130,7 @@
ewgi_val(), ewgi_val()}.
-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request')
- and (size(R) =:= 21))).
+ and (tuple_size(R) =:= 21))).
-define(GET_AUTH_TYPE(R), element(2, R)).
-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)).
-define(GET_CONTENT_LENGTH(R), element(3, R)).
@@ -193,7 +193,7 @@
-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}.
-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response')
- and (size(R) =:= 5))).
+ and (tuple_size(R) =:= 5))).
-define(GET_RESPONSE_STATUS(R), element(2, R)).
-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)).
-define(GET_RESPONSE_HEADERS(R), element(3, R)).
@@ -210,7 +210,7 @@
-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context')
and ?IS_EWGI_REQUEST(element(2, R))
and ?IS_EWGI_RESPONSE(element(3, R))
- and (size(R) =:= 3))).
+ and (tuple_size(R) =:= 3))).
-define(GET_EWGI_REQUEST(R), element(2, R)).
-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)).
-define(GET_EWGI_RESPONSE(R), element(3, R)).
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl
index c71b835123..44fb8510b6 100644
--- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl.erl
@@ -1503,7 +1503,7 @@ tuple_es(#literal{val = V}) ->
tuple_arity(#tuple{es = Es}) ->
length(Es);
tuple_arity(#literal{val = V}) when tuple(V) ->
- size(V).
+ tuple_size(V).
%% ---------------------------------------------------------------------
@@ -3597,7 +3597,7 @@ data_arity(#literal{val = V}) ->
[_ | _] ->
2;
_ when tuple(V) ->
- size(V);
+ tuple_size(V);
_ ->
0
end;
diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl
index 8fca202b8c..d42cc49842 100644
--- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl
+++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/cerl_inline.erl
@@ -2211,7 +2211,7 @@ reduce_bif_call_1(erlang, element, 2, [X, Y], _Env) ->
%% the elements, so lifting out a particular element is OK.
T = list_to_tuple(tuple_es(Y)),
N = int_val(X),
- if integer(N), N > 0, N =< size(T) ->
+ if integer(N), N > 0, N =< tuple_size(T) ->
E = element(N, T),
Es = tuple_to_list(setelement(N, T, void())),
{true, make_seq(c_tuple(Es), E)};
@@ -2255,7 +2255,7 @@ reduce_bif_call_1(erlang, setelement, 3, [X, Y, Z], Env) ->
%% evaluated before any part of `Y'.
T = list_to_tuple(tuple_es(Y)),
N = int_val(X),
- if integer(N), N > 0, N =< size(T) ->
+ if integer(N), N > 0, N =< tuple_size(T) ->
E = element(N, T),
case is_simple(Z) of
true ->
diff --git a/lib/dialyzer/test/plt_SUITE.erl b/lib/dialyzer/test/plt_SUITE.erl
index 800f1fd307..e1c5ecdd95 100644
--- a/lib/dialyzer/test/plt_SUITE.erl
+++ b/lib/dialyzer/test/plt_SUITE.erl
@@ -4,53 +4,139 @@
-module(plt_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
+-include_lib("dialyzer/src/dialyzer.hrl").
-include("dialyzer_test_constants.hrl").
--export([suite/0, all/0, build_plt/1, beam_tests/1, update_plt/1,
+-export([suite/0, all/0,
+ build_plt/1, beam_tests/1, update_plt/1,
local_fun_same_as_callback/1,
remove_plt/1, run_plt_check/1, run_succ_typings/1,
bad_dialyzer_attr/1, merge_plts/1, bad_record_type/1,
- letrec_rvals/1, missing_plt_file/1]).
+ letrec_rvals/1,
+ missing_plt_file/1,
+ build_xdg_plt/1,
+ mod_dep_from_behaviour/1,
+ mod_dep_from_record_definition_field_value_default_used/1,
+ mod_dep_from_record_definition_field_value_default_unused/1,
+ mod_dep_from_record_definition_field_type/1,
+ mod_dep_from_overloaded_callback/1,
+ mod_dep_from_exported_overloaded_fun_spec/1,
+ mod_dep_from_unexported_overloaded_fun_spec/1,
+ mod_dep_from_callback_constraint/1,
+ mod_dep_from_unexported_fun_spec_constraint/1,
+ mod_dep_from_exported_fun_spec_constraint/1,
+ mod_dep_from_exported_type/1,
+ mod_dep_from_callback_return/1,
+ mod_dep_from_callback_args/1,
+ mod_dep_from_unexported_opaque_type_args/1,
+ mod_dep_from_exported_opaque_type_args/1,
+ mod_dep_from_unexported_opaque_type/1,
+ mod_dep_from_exported_opaque_type/1,
+ mod_dep_from_unexported_type_args/1,
+ mod_dep_from_exported_type_args/1,
+ mod_dep_from_unexported_fun_spec_args/1,
+ mod_dep_from_exported_fun_spec_args/1,
+ mod_dep_from_unexported_fun_spec_return/1,
+ mod_dep_from_exported_fun_spec_return/1,
+ mod_dep_from_unexported_type/1
+ ]).
suite() ->
[{timetrap, ?plt_timeout}].
-all() -> [build_plt, beam_tests, update_plt, run_plt_check,
+all() -> [build_plt, build_xdg_plt, beam_tests, update_plt, run_plt_check,
remove_plt, run_succ_typings, local_fun_same_as_callback,
bad_dialyzer_attr, merge_plts, bad_record_type,
- letrec_rvals, missing_plt_file].
+ letrec_rvals,
+ missing_plt_file,
+ mod_dep_from_behaviour,
+ mod_dep_from_record_definition_field_value_default_used,
+ mod_dep_from_record_definition_field_value_default_unused,
+ mod_dep_from_record_definition_field_type,
+ mod_dep_from_overloaded_callback,
+ mod_dep_from_exported_overloaded_fun_spec,
+ mod_dep_from_unexported_overloaded_fun_spec,
+ mod_dep_from_callback_constraint,
+ mod_dep_from_unexported_fun_spec_constraint,
+ mod_dep_from_exported_fun_spec_constraint,
+ mod_dep_from_exported_type,
+ mod_dep_from_callback_return,
+ mod_dep_from_callback_args,
+ mod_dep_from_unexported_opaque_type_args,
+ mod_dep_from_exported_opaque_type_args,
+ mod_dep_from_unexported_opaque_type,
+ mod_dep_from_exported_opaque_type,
+ mod_dep_from_unexported_type_args,
+ mod_dep_from_exported_type_args,
+ mod_dep_from_unexported_fun_spec_args,
+ mod_dep_from_exported_fun_spec_args,
+ mod_dep_from_unexported_fun_spec_return,
+ mod_dep_from_exported_fun_spec_return,
+ mod_dep_from_unexported_type
+ ].
build_plt(Config) ->
- OutDir = ?config(priv_dir, Config),
+ OutDir = proplists:get_value(priv_dir, Config),
case dialyzer_common:check_plt(OutDir) of
ok -> ok;
fail -> ct:fail(plt_build_fail)
end.
+build_xdg_plt(Config) ->
+ TestHome = filename:join(?config(priv_dir, Config), ?FUNCTION_NAME),
+
+ %% We change the $HOME of the emulator to run this test
+ HomeEnv = case os:type() of
+ {win32, _} ->
+ [Drive | Path] = filename:split(TestHome),
+ [{"APPDATA", filename:join(TestHome,"AppData")},
+ {"HOMEDRIVE", Drive}, {"HOMEPATH", filename:join(Path)}];
+ _ ->
+ [{"HOME", TestHome}]
+ end,
+
+ {ok, Peer, Node} = ?CT_PEER(#{ env => HomeEnv }),
+
+ erpc:call(
+ Node,
+ fun() ->
+ ?assertMatch([], dialyzer:run(
+ [{analysis_type, plt_build},
+ {apps, [erts]}])),
+ ?assertMatch(
+ {ok,_}, file:read_file(
+ filename:join(
+ filename:basedir(user_cache, "erlang"),
+ ".dialyzer_plt")))
+ end),
+
+ peer:stop(Peer).
+
beam_tests(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Plt = filename:join(PrivDir, "beam_tests.plt"),
- Prog = <<"
- -module(no_auto_import).
+ Src = <<"
+ -module(no_auto_import).
- %% Copied from erl_lint_SUITE.erl, clash6
+ %% Copied from erl_lint_SUITE.erl, clash6
- -export([size/1]).
+ -export([size/1]).
- size([]) ->
- 0;
- size({N,_}) ->
- N;
- size([_|T]) ->
- 1+size(T).
- ">>,
+ size([]) ->
+ 0;
+ size({N,_}) ->
+ N;
+ size([_|T]) ->
+ 1+size(T).
+ ">>,
Opts = [no_auto_import],
- {ok, BeamFile} = compile(Config, Prog, no_auto_import, Opts),
+ {ok, BeamFile} = compile(Config, Src, no_auto_import, Opts),
[] = run_dialyzer(plt_build, [BeamFile], [{output_plt, Plt}]),
ok.
run_plt_check(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Plt = filename:join(PrivDir, "run_plt_check.plt"),
Mod1 = <<"
-module(run_plt_check1).
@@ -74,14 +160,14 @@ run_plt_check(Config) when is_list(Config) ->
{ok, BeamFile2} = compile(Config, Mod2B, run_plt_check2, []),
- % callgraph warning as run_plt_check2:call/1 makes a call to unexported
- % function run_plt_check1:call/1.
+ %% callgraph warning as run_plt_check2:call/1 makes a call to unexported
+ %% function run_plt_check1:call/1.
[_] = run_dialyzer(plt_check, [], [{init_plt, Plt}]),
ok.
run_succ_typings(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Plt = filename:join(PrivDir, "run_succ_typings.plt"),
Mod1A = <<"
-module(run_succ_typings1).
@@ -113,11 +199,11 @@ run_succ_typings(Config) when is_list(Config) ->
{ok, BeamFile1} = compile(Config, Mod1B, run_succ_typings1, []),
{ok, BeamFile2} = compile(Config, Mod2, run_succ_typings2, []),
- % contract types warning as run_succ_typings2:call/0 makes a call to
- % run_succ_typings1:call/0, which returns a (not b) in the PLT.
+ %% contract types warning as run_succ_typings2:call/0 makes a call to
+ %% run_succ_typings1:call/0, which returns a (not b) in the PLT.
[_] = run_dialyzer(succ_typings, [BeamFile2],
[{check_plt, false}, {init_plt, Plt}]),
- % warning not returned as run_succ_typings1 is updated in the PLT.
+ %% warning not returned as run_succ_typings1 is updated in the PLT.
[] = run_dialyzer(succ_typings, [BeamFile2],
[{check_plt, true}, {init_plt, Plt}]),
@@ -133,7 +219,7 @@ run_succ_typings(Config) when is_list(Config) ->
%%% contract types warning, might be emitted when the removed function
%%% nolonger exists.
update_plt(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Prog1 = <<"-module(plt_gc).
-export([one/0]).
one() ->
@@ -179,7 +265,7 @@ update_plt(Config) ->
%%% up the callback table. This bug was reported by Brujo Benavides.
local_fun_same_as_callback(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Prog1 =
<<"-module(bad_behaviour).
-callback bad() -> bad.
@@ -213,7 +299,7 @@ local_fun_same_as_callback(Config) when is_list(Config) ->
-export([bad/0]).
- %% @doc This function incorreclty implements bad_behaviour.
+ %% @doc This function incorrectly implements bad_behaviour.
bad() -> not_bad.">>,
{ok, TestBeam} = compile(Config, Prog2, bad_child, []),
@@ -231,7 +317,7 @@ local_fun_same_as_callback(Config) when is_list(Config) ->
%%% from a PLT when the beam file no longer exists. Dialyzer should not to
%%% check files exist on disk when removing from the PLT.
remove_plt(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Prog1 = <<"-module(m1).
-export([t/0]).
t() ->
@@ -269,7 +355,7 @@ remove_plt(Config) ->
%% needs to be updated when/if the Dialyzer can analyze Core Erlang
%% without compiling abstract code.
bad_dialyzer_attr(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Source = lists:concat([dial, ".erl"]),
Filename = filename:join(PrivDir, Source),
ok = dialyzer_common:check_plt(PrivDir),
@@ -346,7 +432,7 @@ types() ->
">>,
{Mod1, Mod2}.
-callbacks() -> % A very shallow test.
+callbacks() -> %% A very shallow test.
Mod1 = <<"-module(merge_plts_1).
-callback t() -> merge_plts_2:t().
">>,
@@ -357,7 +443,7 @@ callbacks() -> % A very shallow test.
{Mod1, Mod2}.
create_plts(Mod1, Mod2, Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Plt1 = filename:join(PrivDir, "merge_plts_1.plt"),
Plt2 = filename:join(PrivDir, "merge_plts_2.plt"),
ErlangBeam = erlang_beam(),
@@ -372,7 +458,7 @@ create_plts(Mod1, Mod2, Config) ->
%% End of merge_plts().
bad_record_type(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Source = lists:concat([bad_record_type, ".erl"]),
Filename = filename:join(PrivDir, Source),
PltFilename = dialyzer_common:plt_file(PrivDir),
@@ -398,7 +484,7 @@ bad_record_type(Config) ->
ok.
letrec_rvals(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
Plt = filename:join(PrivDir, "letrec_rvals.plt"),
Prog = <<"
-module(letrec_rvals).
@@ -433,7 +519,7 @@ check_done(_) ->
%% GH-4501
missing_plt_file(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
PltFile = filename:join(PrivDir, "missing_plt_file.plt"),
Prog2 = <<"-module(missing_plt_file2).
t() -> foo.">>,
@@ -485,10 +571,320 @@ succ(PltFile, BeamFile2) ->
{plts,[PltFile]},
{analysis_type, succ_typings}]).
-check(PltFile, BeamFile2) ->
+check(PltFile, _BeamFile2) ->
dialyzer:run([{plts,[PltFile]},
{analysis_type, plt_check}]).
+mod_dep_from_record_definition_field_value_default_unused(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -record(my_record,
+ { num_field = type_deps:get_num() :: number(),
+ str_field,
+ bool_field
+ }).
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, []}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_record_definition_field_value_default_used(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export([f/0]).
+
+ -record(my_record,
+ { num_field = type_deps:get_num() :: number(),
+ str_field,
+ bool_field
+ }).
+
+ f() -> #my_record{str_field = \"foo\", bool_field = true}. % type_deps:get_num() used implicitly here
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_behaviour(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -behaviour(type_deps).
+ -export([quux/1]).
+
+ quux(N) -> N + 1. % Depends on behaviour module to check the callback implementation
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_record_definition_field_type(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -record(my_record,
+ { num_field = 1 :: type_deps:number_like(),
+ str_field,
+ bool_field
+ }).
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_overloaded_callback(Config) ->
+ DependerSrc1 = <<"
+ -module(depender).
+
+ -callback f(string()) -> string()
+ ; (type_deps:number_like()) -> type_deps:number_like().
+ ">>,
+ DependerSrc2 = <<"
+ -module(depender).
+
+ -callback f(type_deps:number_like()) -> type_deps:number_like()
+ ; (string()) -> string().
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc1, ExpectedTypeDepsInPlt),
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc2, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_overloaded_fun_spec(Config) ->
+ DependerSrc1 = <<"
+ -module(depender).
+ -export([f/1]).
+
+ -spec f({a, atom()}) -> atom()
+ ; ({n, type_deps:number_like()}) -> type_deps:number_like().
+ f({a, X}) when is_atom(X) -> X;
+ f({n, X}) when is_number(X) -> X.
+ ">>,
+ DependerSrc2 = <<"
+ -module(depender).
+ -export([f/1]).
+
+ -spec f({n, type_deps:number_like()}) -> type_deps:number_like()
+ ; ({a, atom()}) -> atom().
+ f({n, X}) when is_number(X) -> X;
+ f({a, X}) when is_atom(X) -> X.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc1, ExpectedTypeDepsInPlt),
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc2, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_overloaded_fun_spec(Config) ->
+ DependerSrc1 = <<"
+ -module(depender).
+ -compile({nowarn_unused_function, [f/1]}).
+
+ -spec f({a, atom()}) -> atom()
+ ; ({n, type_deps:number_like()}) -> type_deps:number_like().
+ f({a, X}) when is_atom(X) -> X;
+ f({n, X}) when is_number(X) -> X.
+ ">>,
+ DependerSrc2 = <<"
+ -module(depender).
+ -compile({nowarn_unused_function, [f/1]}).
+
+ -spec f({n, type_deps:number_like()}) -> type_deps:number_like()
+ ; ({a, atom()}) -> atom().
+ f({n, X}) when is_number(X) -> X;
+ f({a, X}) when is_atom(X) -> X.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc1, ExpectedTypeDepsInPlt),
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc2, ExpectedTypeDepsInPlt).
+
+mod_dep_from_callback_constraint(Config) ->
+ DependerSrc1 = <<"
+ -module(depender).
+
+ -callback f(X) -> string() when X :: type_deps:number_like().
+ ">>,
+ DependerSrc2 = <<"
+ -module(depender).
+
+ -callback f(X :: type_deps:number_like()) -> string().
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc1, ExpectedTypeDepsInPlt),
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc2, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_fun_spec_constraint(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -compile({nowarn_unused_function, [f/1]}).
+
+ -spec f(N) -> number() when N :: type_deps:number_like().
+ f(N) -> N.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_fun_spec_constraint(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export([f/1]).
+
+ -spec f(N) -> number() when N :: type_deps:number_like().
+ f(N) -> N.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_callback_return(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -callback f(string()) -> type_deps:number_like().
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_callback_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -callback f(type_deps:number_like()) -> string().
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_opaque_type(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -opaque my_type() :: {string(), type_deps:number_like()}.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_opaque_type(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export_type([my_type/0]).
+
+ -opaque my_type() :: {string(), type_deps:number_like()}.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_opaque_type_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -type my_type() :: type_deps:my_opaque(number()).
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_opaque_type_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export_type([my_type/0]).
+
+ -type my_type() :: type_deps:my_opaque(number()).
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_type_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -type my_type() :: {string(), type_deps:number_like()}.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_type_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export_type([my_type/0]).
+
+ -type my_type() :: {string(), type_deps:number_like()}.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_fun_spec_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -compile({nowarn_unused_function, [f/1]}).
+
+ -spec f(type_deps:number_like()) -> number().
+ f(N) -> N.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_fun_spec_args(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export([f/1]).
+
+ -spec f(N :: type_deps:number_like()) -> number().
+ f(N) -> N.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_fun_spec_return(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -compile({nowarn_unused_function, [f/0]}).
+
+ -spec f() -> type_deps:number_like().
+ f() -> 1.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_fun_spec_return(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export([f/0]).
+
+ -spec f() -> type_deps:number_like().
+ f() -> 1.
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_unexported_type(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+
+ -type my_type() :: type_deps:list_like(number()).
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+mod_dep_from_exported_type(Config) ->
+ DependerSrc = <<"
+ -module(depender).
+ -export_type([my_type/0]).
+
+ -type my_type() :: type_deps:list_like(number()).
+ ">>,
+ ExpectedTypeDepsInPlt = [{depender, []}, {type_deps, [depender]}],
+ ok = check_plt_deps(Config, ?FUNCTION_NAME, DependerSrc, ExpectedTypeDepsInPlt).
+
+check_plt_deps(Config, TestName, DependerSrc, ExpectedTypeDepsInPltUnsorted) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ PltFile = filename:join(PrivDir, atom_to_list(TestName) ++ ".plt"),
+ {ok, DepsBeamFile} = compile(Config, type_deps, []),
+ {ok, DependerBeamFile} = compile(Config, DependerSrc, depender, []),
+ [] = run_dialyzer(plt_build, [DependerBeamFile, DepsBeamFile], [{output_plt, PltFile}]),
+ {_ResPlt, #plt_info{mod_deps = DepsByModule}} = dialyzer_plt:plt_and_info_from_file(PltFile),
+
+ ActualTypeDepsInPlt =
+ lists:sort(dict:to_list(dict:erase(erlang, DepsByModule))),
+ ExpectedTypeDepsInPlt =
+ lists:usort(ExpectedTypeDepsInPltUnsorted),
+
+ ?assertEqual(
+ ExpectedTypeDepsInPlt,
+ ActualTypeDepsInPlt,
+ {missing, ExpectedTypeDepsInPlt -- ActualTypeDepsInPlt,
+ extra, ActualTypeDepsInPlt -- ExpectedTypeDepsInPlt}).
+
erlang_beam() ->
case code:where_is_file("erlang.beam") of
non_existing ->
@@ -499,9 +895,20 @@ erlang_beam() ->
EBeam
end.
+%% Builds the named module using the source in the plt_SUITE_data dir
+compile(Config, Module, CompileOpts) ->
+ Source = lists:concat([Module, ".erl"]),
+ PrivDir = proplists:get_value(priv_dir,Config),
+ DataDir = proplists:get_value(data_dir,Config),
+ SrcFilename = filename:join([DataDir, Source]),
+ Opts = [{outdir, PrivDir}, debug_info | CompileOpts],
+ {ok, Module} = compile:file(SrcFilename, Opts),
+ {ok, filename:join([PrivDir, lists:concat([Module, ".beam"])])}.
+
+%% Builds the named module using the literal source given
compile(Config, Prog, Module, CompileOpts) ->
Source = lists:concat([Module, ".erl"]),
- PrivDir = ?config(priv_dir,Config),
+ PrivDir = proplists:get_value(priv_dir,Config),
Filename = filename:join([PrivDir, Source]),
ok = file:write_file(Filename, Prog),
Opts = [{outdir, PrivDir}, debug_info | CompileOpts],
diff --git a/lib/dialyzer/test/plt_SUITE_data/type_deps.erl b/lib/dialyzer/test/plt_SUITE_data/type_deps.erl
new file mode 100644
index 0000000000..f6fcfc3d23
--- /dev/null
+++ b/lib/dialyzer/test/plt_SUITE_data/type_deps.erl
@@ -0,0 +1,18 @@
+-module(type_deps).
+
+-export([func/1, get_num/0]).
+
+-export_type([number_like/0, my_opaque/1, list_like/1]).
+
+-type number_like() :: number().
+-type list_like(X) :: [X].
+-opaque my_opaque(X) :: {X,X}.
+
+-callback quux(number()) -> number().
+
+-spec func(T) -> T.
+func(X) ->
+ X + X.
+
+get_num() ->
+ 3.
diff --git a/lib/dialyzer/test/property_test/erl_types_prop.erl b/lib/dialyzer/test/property_test/erl_types_prop.erl
new file mode 100644
index 0000000000..0dbcbe555f
--- /dev/null
+++ b/lib/dialyzer/test/property_test/erl_types_prop.erl
@@ -0,0 +1,230 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(erl_types_prop).
+-compile([export_all, nowarn_export_all]).
+
+%% This module only supports proper, as we use features of PropEr's
+%% module erlang_abstract_code not available in quickcheck.
+
+-proptest([proper]).
+
+-ifdef(PROPER).
+
+-include_lib("proper/include/proper.hrl").
+
+-define(REPETITIONS, 5000).
+
+absorption() ->
+ numtests(?REPETITIONS, absorption_1()).
+
+absorption_1() ->
+ ?FORALL({TypeA, TypeB},
+ ?LET(TypeA, type(),
+ ?LET(TypeB, type(), {TypeA, TypeB})),
+ ?WHENFAIL(
+ begin
+ io:format("TypeA = ~p,\n", [TypeA]),
+ io:format("TypeB = ~p,\n", [TypeB]),
+ io:format("~p:absorption_check(TypeA, TypeB).\n",
+ [?MODULE])
+ end,
+ absorption_check(TypeA, TypeB))).
+
+absorption_check(A, B) ->
+ %% a ∨ (a ∧ b) = a
+ R1 = sup(A, inf(A, B)),
+ %% a ∧ (a ∨ b) = a
+ R2 = inf(A, sup(A, B)),
+ equal(A, R1) andalso equal(A, R2).
+
+associativity() ->
+ numtests(?REPETITIONS, associativity_1()).
+
+associativity_1() ->
+ ?FORALL({TypeA, TypeB, TypeC},
+ ?LET(TypeA, type_without_no_return(),
+ ?LET(TypeB, type_without_no_return(),
+ ?LET(TypeC, type_without_no_return(), {TypeA, TypeB, TypeC}))),
+ ?WHENFAIL(
+ begin
+ io:format("TypeA = ~p,\n", [TypeA]),
+ io:format("TypeB = ~p,\n", [TypeB]),
+ io:format("TypeC = ~p,\n", [TypeC]),
+ io:format("~p:associativity_check(TypeA, TypeB, TypeC).\n",
+ [?MODULE])
+ end,
+ associativity_check(TypeA, TypeB, TypeC))).
+
+associativity_check(A, B, C) ->
+ %% a ∨ (b ∨ c) = (a ∨ b) ∨ c
+ LHS_Sup = sup(A, sup(B, C)),
+ RHS_Sup = sup(sup(A, B), C),
+ Test1 = equal(LHS_Sup, RHS_Sup),
+ %% a ∧ (b ∧ c) = (a ∧ b) ∧ c
+ LHS_Inf = inf(A, inf(B, C)),
+ RHS_Inf = inf(inf(A, B), C),
+ Test2 = equal(LHS_Inf, RHS_Inf),
+ Test1 and Test2.
+
+commutativity() ->
+ numtests(?REPETITIONS, commutativity_1()).
+
+commutativity_1() ->
+ ?FORALL({TypeA, TypeB},
+ ?LET(TypeA, type(),
+ ?LET(TypeB, type(), {TypeA, TypeB})),
+ ?WHENFAIL(
+ begin
+ io:format("TypeA = ~p,\n", [TypeA]),
+ io:format("TypeB = ~p,\n", [TypeB]),
+ io:format("~p:commutativity_check(TypeA, TypeB).\n",
+ [?MODULE])
+ end,
+ commutativity_check(TypeA, TypeB))).
+
+commutativity_check(A, B) ->
+ %% a ∨ b = b ∨ a
+ Sup_AB = sup(A, B),
+ Sup_BA = sup(B, A),
+ true = sup(A, B) =:= sup(B, A),
+ Test1 = equal(Sup_AB, Sup_BA),
+ %% a ∧ b = b ∧ a
+ Inf_AB = inf(A, B),
+ Inf_BA = inf(B, A),
+ Test2 = equal(Inf_AB, Inf_BA),
+ Test1 and Test2.
+
+idempotence() ->
+ numtests(?REPETITIONS, idempotence_1()).
+
+idempotence_1() ->
+ ?FORALL(Type,
+ type(),
+ ?WHENFAIL(
+ begin
+ io:format("Type = ~p,\n", [Type]),
+ io:format("~p:idempotence_check(Type).\n", [?MODULE])
+ end,
+ idempotence_check(Type))).
+
+idempotence_check(Type) ->
+ %% a ∨ a = a
+ Sup = sup(Type, Type),
+ Test1 = equal(Sup, Type),
+ %% a ∧ a = a
+ Inf = inf(Type, Type),
+ Test2 = equal(Inf, Type),
+ Test1 and Test2.
+
+identity() ->
+ numtests(?REPETITIONS, identity_1()).
+
+identity_1() ->
+ ?FORALL(Type, type(), identity_check(Type)).
+
+identity_check(Type) ->
+ %% a ∨ [bottom element] = a
+ Sup = sup(Type, none),
+ Test1 = equal(Sup, Type),
+ %% a ∧ [top element] = a
+ Inf = inf(Type, any),
+ Test2 = equal(Inf, Type),
+ Test1 and Test2.
+
+limit() ->
+ numtests(?REPETITIONS, limit_1()).
+
+limit_1() ->
+ ?FORALL(Type,
+ type(),
+ ?WHENFAIL(
+ begin
+ io:format("Type = ~p,\n", [Type]),
+ io:format("~p:limit_check(Type).\n", [?MODULE])
+ end,
+ limit_check(Type))).
+
+limit_check(Type1) ->
+ equal(erl_types:t_limit(Type1, 1000), Type1).
+
+inf(A, B) ->
+ erl_types:t_inf(A, B).
+
+sup(A, B) ->
+ erl_types:t_sup(A, B).
+
+equal(A, B) ->
+ erl_types:t_is_equal(A, B).
+
+type_without_no_return() ->
+ ?SUCHTHAT(Type, type(), not has_no_return(Type)).
+
+has_no_return(unit) ->
+ true;
+has_no_return(Tuple) when is_tuple(Tuple) ->
+ has_no_return(tuple_to_list(Tuple));
+has_no_return([T|Ts]) ->
+ has_no_return(T) orelse has_no_return(Ts);
+has_no_return(_) ->
+ false.
+
+type() ->
+ ?LET(Forms,
+ abstr(),
+ begin
+ [F | _] = [T || {attribute, _, K, {_, T, []}} <- Forms,
+ K =:= type orelse K =:= opaque],
+ form_to_type(F)
+ end).
+
+abstr() ->
+ Opts = [{types, [{Type, 0} || Type <- types()]},
+ {weight, {atom, 10}},
+ {weight, {type_decl, 1}},
+ {weight, {record_decl, 0}},
+ {weight, {function_spec, 0}},
+ {weight, {function_decl, 0}},
+ {weight, {type_variable, 0}}],
+ proper_erlang_abstract_code:module(Opts).
+
+form_to_type(Form) ->
+ Types = [SiteType | _] = types(),
+ Anno = erl_anno:new(0),
+ TableTypes = [{{type, Type, 0},
+ {{m, {"file", Anno}, {type, 0, any, []}, []}, any}} ||
+ Type <- Types],
+ TypeTable = maps:from_list(TableTypes),
+ CodeTable = ets:new(table, [set]),
+ try
+ true = ets:insert(CodeTable, {m, TypeTable}),
+ Site = {type, {m, SiteType, 0}, ""},
+ C = erl_types:cache__new(),
+ ETypes = sets:from_list([]),
+ {T, _} = erl_types:t_from_form(Form, ETypes, Site, CodeTable, #{}, C),
+ T
+ after
+ true = ets:delete(CodeTable)
+ end.
+
+types() ->
+ [t, tt].
+
+-endif.
diff --git a/lib/dialyzer/test/race_SUITE_data/dialyzer_options b/lib/dialyzer/test/race_SUITE_data/dialyzer_options
deleted file mode 100644
index 2be2f47dda..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/dialyzer_options
+++ /dev/null
@@ -1 +0,0 @@
-{dialyzer_options, [{indent_opt, false}, {warnings, [race_conditions]}]}.
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args1
deleted file mode 100644
index 452b623f94..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args1.erl:9:16: The call ets:insert(T::'foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_args1.erl on line {8,28}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args10 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args10
deleted file mode 100644
index cefface2f5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args10
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args10.erl:9:16: The call ets:insert(T::'foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_args10.erl on line {8,28}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args2
deleted file mode 100644
index 1a529812f9..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args2.erl:9:16: The call ets:insert(T::'foo',[{'counter',number()} | {'kostis',number()} | {'maria',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_args2.erl on line {8,27}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args4
deleted file mode 100644
index dd08666fe8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args4.erl:9:16: The call ets:insert(T::'foo',{'counter',number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_args4.erl on line {8,27}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args5
deleted file mode 100644
index ec44a89f8f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args5.erl:9:16: The call ets:insert(T::'foo',{'counter',number(),number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_args5.erl on line {8,27}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args6 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args6
deleted file mode 100644
index b7d4131ff6..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args6.erl:9:16: The call ets:insert(T::'foo',[{'counter',number(),number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_args6.erl on line {8,27}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args7 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args7
deleted file mode 100644
index fc6ea50437..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args7
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args7.erl:17:3: The call ets:insert(Table::'foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo','counter') call in ets_insert_args7.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args8 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args8
deleted file mode 100644
index f263c0eaaf..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_args8
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_args8.erl:16:3: The call ets:insert(Table::atom(),[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::atom(),'counter') call in ets_insert_args8.erl on line {12,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow1
deleted file mode 100644
index 38c507582e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_control_flow1.erl:15:7: The call ets:insert('foo',{'random',integer()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','random') call in ets_insert_control_flow1.erl on line {10,41}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow2
deleted file mode 100644
index 1ca874c4d8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow2
+++ /dev/null
@@ -1,3 +0,0 @@
-
-ets_insert_control_flow2.erl:15:7: The call ets:insert('foo',[{'pass',[pos_integer()]} | {'random',integer()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','random') call in ets_insert_control_flow2.erl on line {10,41}
-ets_insert_control_flow2.erl:19:7: The call ets:insert('foo',[{'pass',[pos_integer()]} | {'random',integer()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','random') call in ets_insert_control_flow2.erl on line {10,41}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3
deleted file mode 100644
index ad011e918c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3
+++ /dev/null
@@ -1,3 +0,0 @@
-
-ets_insert_control_flow3.erl:21:11: The call ets:insert(Table::atom() | ets:tid(),{'root',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'root') call in ets_insert_control_flow3.erl on line {12,15}
-ets_insert_control_flow3.erl:23:11: The call ets:insert(Table::atom() | ets:tid(),{'user',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'user') call in ets_insert_control_flow3.erl on line {13,15}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4
deleted file mode 100644
index ad505c0ab8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4
+++ /dev/null
@@ -1,3 +0,0 @@
-
-ets_insert_control_flow4.erl:21:11: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line {12,15}, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line {13,15}
-ets_insert_control_flow4.erl:23:11: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line {12,15}, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line {13,15}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5
deleted file mode 100644
index f98aa27654..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5
+++ /dev/null
@@ -1,5 +0,0 @@
-
-ets_insert_control_flow5.erl:22:11: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_control_flow5.erl on line {16,16}
-ets_insert_control_flow5.erl:23:11: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line {12,15}, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line {13,15}
-ets_insert_control_flow5.erl:25:11: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_control_flow5.erl on line {16,16}
-ets_insert_control_flow5.erl:26:11: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line {12,15}, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line {13,15}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race1
deleted file mode 100644
index 60e115ff1b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_diff_atoms_race1.erl:22:3: The call ets:insert(Table::'bar' | 'foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo','counter') call in ets_insert_diff_atoms_race1.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race2
deleted file mode 100644
index 0e6546685c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_diff_atoms_race2.erl:22:3: The call ets:insert(Table::'bar' | 'foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo',Counter::'counter') call in ets_insert_diff_atoms_race2.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race3 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race3
deleted file mode 100644
index 9a0e7dc936..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_diff_atoms_race3.erl:22:3: The call ets:insert(Table::'bar' | 'foo',{'counter',number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo','counter') call in ets_insert_diff_atoms_race3.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race4
deleted file mode 100644
index cc17f482ad..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_diff_atoms_race4.erl:22:3: The call ets:insert(Table::'bar' | 'foo',{'counter',number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo',Counter::'counter') call in ets_insert_diff_atoms_race4.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race5
deleted file mode 100644
index c6df36c0e2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_diff_atoms_race5.erl:22:3: The call ets:insert(Table::'foo',[{'counter',number()} | {'index',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo',Counter::'counter') call in ets_insert_diff_atoms_race5.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race6 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race6
deleted file mode 100644
index 21e5cdf8f3..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_diff_atoms_race6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_diff_atoms_race6.erl:22:3: The call ets:insert(Table::'foo',{'counter',number()} | {'index',number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Tab::'foo',Counter::'counter') call in ets_insert_diff_atoms_race6.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double1
deleted file mode 100644
index 5de9983e9e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double1
+++ /dev/null
@@ -1,4 +0,0 @@
-
-ets_insert_double1.erl:15:7: The call ets:insert('foo',[{'pass',[number()]} | {'random',integer()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','random') call in ets_insert_double1.erl on line {10,41}, the ets:lookup('foo','pass') call in ets_insert_double1.erl on line {27,14}
-ets_insert_double1.erl:19:7: The call ets:insert('foo',[{'pass',[number()]} | {'random',integer()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','random') call in ets_insert_double1.erl on line {10,41}, the ets:lookup('foo','pass') call in ets_insert_double1.erl on line {27,14}
-ets_insert_double1.erl:24:3: The call ets:insert('foo',{'pass', 'empty'}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','pass') call in ets_insert_double1.erl on line {22,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double2
deleted file mode 100644
index 532550efb7..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_double2
+++ /dev/null
@@ -1,4 +0,0 @@
-
-ets_insert_double2.erl:15:7: The call ets:insert('foo',[{_,[number()] | integer()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo',Random::any()) call in ets_insert_double2.erl on line {10,41}, the ets:lookup('foo',Pass::any()) call in ets_insert_double2.erl on line {27,14}
-ets_insert_double2.erl:19:7: The call ets:insert('foo',[{_,[number()] | integer()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo',Random::any()) call in ets_insert_double2.erl on line {10,41}, the ets:lookup('foo',Pass::any()) call in ets_insert_double2.erl on line {27,14}
-ets_insert_double2.erl:24:3: The call ets:insert('foo',{_,'empty'}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo',Pass::any()) call in ets_insert_double2.erl on line {22,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs1 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs1
deleted file mode 100644
index 646921b7ab..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_funs1.erl:15:3: The call ets:insert('foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(T::'foo','counter') call in ets_insert_funs1.erl on line {9,9}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs2 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs2
deleted file mode 100644
index 1cb3e3a996..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_funs2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_funs2.erl:9:9: The call ets:insert(T::'foo',[{'counter',number()},...]) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('foo','counter') call in ets_insert_funs2.erl on line {14,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_new b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_new
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_new
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param
deleted file mode 100644
index 29b20f3386..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param
+++ /dev/null
@@ -1,5 +0,0 @@
-
-ets_insert_param.erl:13:7: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_param.erl on line {10,16}
-ets_insert_param.erl:14:7: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_param.erl on line {14,57}, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_param.erl on line {15,67}
-ets_insert_param.erl:17:7: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_param.erl on line {10,16}
-ets_insert_param.erl:18:7: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_param.erl on line {18,57}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_public b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_public
deleted file mode 100644
index 27ce4b181a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_public
+++ /dev/null
@@ -1,2 +0,0 @@
-
-ets_insert_public.erl:14:5: The call ets:insert(Foo::atom(),{'counter',number()}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Foo::atom(),'counter') call in ets_insert_public.erl on line {12,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/extract_translations b/lib/dialyzer/test/race_SUITE_data/results/extract_translations
deleted file mode 100644
index 8804c0b9ee..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/extract_translations
+++ /dev/null
@@ -1,5 +0,0 @@
-
-extract_translations.erl:140:7: The call ets:insert('files',{atom() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | [atom() | [any()] | char()]) call in extract_translations.erl on line {135,11}
-extract_translations.erl:146:6: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line {126,11}
-extract_translations.erl:152:7: The call ets:insert('files',{atom() | [atom() | [any()] | char()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('files',File::atom() | [atom() | [any()] | char()]) call in extract_translations.erl on line {148,11}
-extract_translations.erl:154:6: The call ets:insert('translations',{_,[]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup('translations',Str::any()) call in extract_translations.erl on line {126,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race1 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race1
deleted file mode 100644
index d7886f3b68..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_diff_atoms_race1.erl:33:3: The call mnesia:dirty_write(Table::'employee' | 'employer',Record::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read(Tab::'employee',Eno::any()) call in mnesia_diff_atoms_race1.erl on line {19,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race2 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race2
deleted file mode 100644
index 51906dd548..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_diff_atoms_race2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_diff_atoms_race2.erl:37:3: The call mnesia:dirty_write(Record::#employee{salary::number()} | #employer{}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read(Tab::'employee',Eno::any()) call in mnesia_diff_atoms_race2.erl on line {26,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two
deleted file mode 100644
index 3ac7ed1f04..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_one_write_two
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_one_write_two.erl:20:5: The call mnesia:dirty_write('employee',New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read({'employee',_}) call in mnesia_dirty_read_one_write_two.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one
deleted file mode 100644
index 231e62c2c2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_two_write_one
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_two_write_one.erl:20:5: The call mnesia:dirty_write(New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read('employee',Eno::any()) call in mnesia_dirty_read_two_write_one.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double1 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double1
deleted file mode 100644
index 1e2c4e379f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_write_double1.erl:20:5: The call mnesia:dirty_write('employee',New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read('employee',Eno::any()) call in mnesia_dirty_read_write_double1.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double2 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double2
deleted file mode 100644
index 3d28f32dc9..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_write_double2.erl:20:5: The call mnesia:dirty_write(New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read({'employee',_}) call in mnesia_dirty_read_write_double2.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double3 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double3
deleted file mode 100644
index 5b46129157..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_write_double3.erl:20:5: The call mnesia:dirty_write('employee',New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read({'employee',_}) call in mnesia_dirty_read_write_double3.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double4 b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double4
deleted file mode 100644
index 895faa4cad..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_double4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_write_double4.erl:20:5: The call mnesia:dirty_write(New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read('employee',Eno::any()) call in mnesia_dirty_read_write_double4.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one
deleted file mode 100644
index d88e501f9c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_one
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_write_one.erl:20:5: The call mnesia:dirty_write(New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read({'employee',_}) call in mnesia_dirty_read_write_one.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two b/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two
deleted file mode 100644
index 4ff8c0d9c4..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/mnesia_dirty_read_write_two
+++ /dev/null
@@ -1,2 +0,0 @@
-
-mnesia_dirty_read_write_two.erl:20:5: The call mnesia:dirty_write('employee',New::#employee{salary::number()}) might have an unintended effect due to a possible race condition caused by its combination with the mnesia:dirty_read('employee',Eno::any()) call in mnesia_dirty_read_write_two.erl on line {17,11}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow1
deleted file mode 100644
index c62a764338..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_control_flow1.erl:13:18: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_control_flow1.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow2
deleted file mode 100644
index 1fc47a7218..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow2
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_control_flow2.erl:14:4: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_control_flow2.erl on line {8,8}
-whereis_control_flow2.erl:15:18: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_control_flow2.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow3
deleted file mode 100644
index f04acc840e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_control_flow3.erl:25:3: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_control_flow3.erl on line {11,14}, the erlang:whereis(AnAtom::any()) call in whereis_control_flow3.erl on line {18,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow4
deleted file mode 100644
index 76b60a0db8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow4
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_control_flow4.erl:18:19: The call erlang:register('maria',Pid1::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis('maria') call in whereis_control_flow4.erl on line {8,8}
-whereis_control_flow4.erl:19:19: The call erlang:register('kostis',Pid2::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis('kostis') call in whereis_control_flow4.erl on line {13,16}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow5
deleted file mode 100644
index 0a445d4f10..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_control_flow5.erl:11:7: The call erlang:unregister(AnAtom::atom()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_control_flow5.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow6
deleted file mode 100644
index 2b6726731f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_control_flow6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_control_flow6.erl:11:7: The call erlang:unregister('kostis') might fail due to a possible race condition caused by its combination with the erlang:whereis('kostis') call in whereis_control_flow6.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_no_race
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race
deleted file mode 100644
index 4b7272e203..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_atoms_race
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_atoms_race.erl:34:3: The call erlang:register(Atom::'kostis' | 'maria',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::'maria') call in whereis_diff_atoms_race.erl on line {14,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1
deleted file mode 100644
index aac6a321cd..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_diff_functions1.erl:10:7: The call erlang:register('master',pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis('master') call in whereis_diff_functions1.erl on line {8,8}
-whereis_diff_functions1.erl:18:7: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions1.erl on line {15,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested
deleted file mode 100644
index 85a8546bc6..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_nested
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions1_nested.erl:23:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions1_nested.erl on line {11,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens
deleted file mode 100644
index c9c4fe7b48..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_pathsens
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions1_pathsens.erl:32:3: The call erlang:register(Atom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::'kostis') call in whereis_diff_functions1_pathsens.erl on line {15,14}, the erlang:whereis(AnAtom::'kostis') call in whereis_diff_functions1_pathsens.erl on line {22,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice
deleted file mode 100644
index f2338ed249..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions1_twice
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_diff_functions1_twice.erl:27:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions1_twice.erl on line {11,8}
-whereis_diff_functions1_twice.erl:30:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::atom()) call in whereis_diff_functions1_twice.erl on line {15,12}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2
deleted file mode 100644
index 005428286e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions2.erl:25:3: The call erlang:register(Atom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::'kostis') call in whereis_diff_functions2.erl on line {13,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested
deleted file mode 100644
index 54ea8e70fd..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_nested
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions2_nested.erl:20:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions2_nested.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens
deleted file mode 100644
index 3ec2234046..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_pathsens
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions2_pathsens.erl:29:3: The call erlang:register(Atom::atom(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions2_pathsens.erl on line {12,14}, the erlang:whereis(AnAtom::any()) call in whereis_diff_functions2_pathsens.erl on line {19,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice
deleted file mode 100644
index d14a255040..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions2_twice
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_diff_functions2_twice.erl:24:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions2_twice.erl on line {8,8}
-whereis_diff_functions2_twice.erl:27:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::atom()) call in whereis_diff_functions2_twice.erl on line {12,12}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3
deleted file mode 100644
index 079ec9fb31..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions3.erl:8:3: The call erlang:register(AnAtom::atom(),'undefined' | pid() | port()) might fail due to a possible race condition caused by its combination with the erlang:whereis(Atom::any()) call in whereis_diff_functions3.erl on line {11,3}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested
deleted file mode 100644
index f1a4733585..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_nested
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions3_nested.erl:21:3: The call erlang:unregister(Atom::atom()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions3_nested.erl on line {11,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens
deleted file mode 100644
index 44e1ba6fbc..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions3_pathsens
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions3_pathsens.erl:29:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions3_pathsens.erl on line {12,14}, the erlang:whereis(AnAtom::any()) call in whereis_diff_functions3_pathsens.erl on line {19,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions4
deleted file mode 100644
index 2f39e19a03..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions4.erl:32:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions4.erl on line {13,8}, the erlang:whereis(AnAtom::atom()) call in whereis_diff_functions4.erl on line {17,12}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions5
deleted file mode 100644
index 1e19cb26e7..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions5.erl:22:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions5.erl on line {10,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions6
deleted file mode 100644
index 5c8a093405..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_functions6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_functions6.erl:29:3: The call erlang:register(Atom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_functions6.erl on line {10,8}, the erlang:whereis(AnAtom::atom()) call in whereis_diff_functions6.erl on line {14,12}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1
deleted file mode 100644
index 6a28376c07..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules2.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_modules1.erl on line {10,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens
deleted file mode 100644
index f287ade224..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_pathsens
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules2_pathsens.erl:12:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_modules1_pathsens.erl on line {12,14}, the erlang:whereis(AnAtom::any()) call in whereis_diff_modules1_pathsens.erl on line {19,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec
deleted file mode 100644
index 2d2033d172..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules1_rec
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules1_rec.erl:10:10: The call erlang:register(AnAtom::any(),Id::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_diff_modules1_rec.erl on line {12,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2
deleted file mode 100644
index 3ae7f24bf7..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules3.erl:8:3: The call erlang:register(AnAtom::atom(),'undefined' | pid() | port()) might fail due to a possible race condition caused by its combination with the erlang:whereis(Atom::any()) call in whereis_diff_modules4.erl on line {11,3}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens
deleted file mode 100644
index b3a9a2130a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_pathsens
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules4_pathsens.erl:13:3: The call erlang:register(Atom::atom(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_modules3_pathsens.erl on line {12,14}, the erlang:whereis(AnAtom::any()) call in whereis_diff_modules3_pathsens.erl on line {19,14}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec
deleted file mode 100644
index bca2659836..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules2_rec
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules3_rec.erl:13:10: The call erlang:register(AnAtom::any(),Id::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_diff_modules3_rec.erl on line {15,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules3
deleted file mode 100644
index c8afd6603f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules6.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_modules5.erl on line {10,8}, the erlang:whereis(AnAtom::atom()) call in whereis_diff_modules5.erl on line {14,12}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested
deleted file mode 100644
index b003518eb7..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_nested
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_modules3_nested.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_modules1_nested.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice
deleted file mode 100644
index c8d414d76c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_modules_twice
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_diff_modules2_twice.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::atom()) call in whereis_diff_modules1_twice.erl on line {12,12}
-whereis_diff_modules2_twice.erl:8:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_diff_modules1_twice.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_no_race
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race b/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race
deleted file mode 100644
index 4309c8370c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_diff_vars_race
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_diff_vars_race.erl:16:7: The call erlang:register(Atom2::any(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(Atom1::any()) call in whereis_diff_vars_race.erl on line {13,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module1
deleted file mode 100644
index cf4393654f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module2.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module1.erl on line {10,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module2
deleted file mode 100644
index 4ceffb2f1f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module4.erl:14:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module3.erl on line {10,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module3
deleted file mode 100644
index 9b5aa5c867..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module6.erl:14:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module5.erl on line {10,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module4
deleted file mode 100644
index c42e9b967f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module7.erl:8:3: The call erlang:register(AnAtom::atom(),pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module8.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module5
deleted file mode 100644
index 569d0f5976..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module9.erl:8:3: The call erlang:register(AnAtom::atom(),pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module10.erl on line {11,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module6
deleted file mode 100644
index cc848c493c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module12.erl:14:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module11.erl on line {10,8}, the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module11.erl on line {21,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module7 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module7
deleted file mode 100644
index 5bb9fb794b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module7
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module14.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module13.erl on line {10,8}, the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module14.erl on line {16,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module8 b/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module8
deleted file mode 100644
index 6973b7422c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_intra_inter_module8
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_intra_inter_module16.erl:11:3: The call erlang:register(Atom::any(),Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module15.erl on line {10,8}, the erlang:whereis(AnAtom::any()) call in whereis_intra_inter_module16.erl on line {16,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_param b/lib/dialyzer/test/race_SUITE_data/results/whereis_param
deleted file mode 100644
index f6735807c1..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_param
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_param.erl:8:3: The call erlang:register(AnAtom::atom(),pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_param.erl on line {11,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module b/lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module
deleted file mode 100644
index 97c9d27789..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_param_inter_module
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_param_inter_module1.erl:8:3: The call erlang:register(AnAtom::atom(),pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_param_inter_module2.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function1
deleted file mode 100644
index 66248649a0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function1
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function1.erl:14:4: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_rec_function1.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function2
deleted file mode 100644
index 83298a5c3c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function2.erl:13:10: The call erlang:register(AnAtom::atom(),Id::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_rec_function2.erl on line {15,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function3
deleted file mode 100644
index 7b004aeb12..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function3.erl:13:10: The call erlang:register(AnAtom::atom(),Id::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_rec_function3.erl on line {16,10}, the erlang:whereis(NextAtom::atom()) call in whereis_rec_function3.erl on line {20,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function4
deleted file mode 100644
index b2885774ba..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function4.erl:13:10: The call erlang:register(AnAtom::atom(),Id::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_rec_function4.erl on line {15,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function5
deleted file mode 100644
index d5e9c4328a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function5.erl:10:10: The call erlang:register(AnAtom::any(),Id::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_rec_function5.erl on line {12,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function6
deleted file mode 100644
index c4c7c55b02..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function6.erl:10:10: The call erlang:register(AnAtom::any(),Id::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(NextAtom::any()) call in whereis_rec_function6.erl on line {12,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function7 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function7
deleted file mode 100644
index 0a0b07bcc0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function7
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function7.erl:15:4: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_rec_function7.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function8 b/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function8
deleted file mode 100644
index db37842e6b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_rec_function8
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_rec_function8.erl:18:4: The call erlang:register(AnAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_rec_function8.erl on line {11,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch b/lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch
deleted file mode 100644
index 3cf78cf0d2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_try_catch
+++ /dev/null
@@ -1,3 +0,0 @@
-
-whereis_try_catch.erl:13:14: The call erlang:register('master',Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis('master') call in whereis_try_catch.erl on line {8,8}
-whereis_try_catch.erl:21:9: The call erlang:register('master',Pid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis('master') call in whereis_try_catch.erl on line {18,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars1 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars1
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars1
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars10 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars10
deleted file mode 100644
index 37c060def4..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars10
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars10.erl:17:22: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars10.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars11 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars11
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars11
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars12 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars12
deleted file mode 100644
index bc19f7a756..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars12
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars12.erl:16:37: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars12.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars13 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars13
deleted file mode 100644
index 864231d6b4..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars13
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars13.erl:16:52: The call erlang:register(OtherAtom::'kostis',APid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars13.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars14 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars14
deleted file mode 100644
index 4aaf586141..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars14
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars14.erl:16:52: The call erlang:register(OtherAtom::'kostis',APid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars14.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars15 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars15
deleted file mode 100644
index 2042e119ca..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars15
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars15.erl:17:15: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars15.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars16 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars16
deleted file mode 100644
index 89f5b963a8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars16
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars16.erl:17:15: The call erlang:register(OtherAtom::any(),APid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars16.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars17 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars17
deleted file mode 100644
index 1f94cfef0e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars17
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars17.erl:17:15: The call erlang:register(OtherAtom::any(),APid::any()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars17.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars18 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars18
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars18
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars19 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars19
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars19
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars2 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars2
deleted file mode 100644
index 6aa57fcdc5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars2
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars2.erl:14:18: The call erlang:register(OtherAtom::atom(),Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars2.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars20 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars20
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars20
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars21 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars21
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars21
+++ /dev/null
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars22 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars22
deleted file mode 100644
index 613d788e59..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars22
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars22.erl:21:21: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars22.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars3 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars3
deleted file mode 100644
index 74ab067e56..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars3
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars3.erl:14:18: The call erlang:register(OtherAtom::atom(),APid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars3.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars4 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars4
deleted file mode 100644
index 0584b03a8d..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars4
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars4.erl:14:18: The call erlang:register(OtherAtom::atom() | pid(),APid::atom() | pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars4.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars5 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars5
deleted file mode 100644
index 0482d31215..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars5
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars5.erl:16:26: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars5.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars6 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars6
deleted file mode 100644
index 6edcb8b756..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars6
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars6.erl:16:34: The call erlang:register(OtherAtom::'kostis',APid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars6.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars7 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars7
deleted file mode 100644
index 23c1ef2942..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars7
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars7.erl:16:34: The call erlang:register(OtherAtom::'kostis',APid::atom() | pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars7.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars8 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars8
deleted file mode 100644
index 59019c74c0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars8
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars8.erl:16:21: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars8.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars9 b/lib/dialyzer/test/race_SUITE_data/results/whereis_vars9
deleted file mode 100644
index 89fba57863..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/results/whereis_vars9
+++ /dev/null
@@ -1,2 +0,0 @@
-
-whereis_vars9.erl:16:21: The call erlang:register(OtherAtom::'kostis',Pid::pid()) might fail due to a possible race condition caused by its combination with the erlang:whereis(AnAtom::any()) call in whereis_vars9.erl on line {8,8}
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl
deleted file mode 100644
index 0039195e0a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args1).
--export([start/0]).
-
-start() ->
- F = fun(T) -> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args10.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args10.erl
deleted file mode 100644
index c897a34af0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args10.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args10).
--export([start/0]).
-
-start() ->
- F = fun(T) -> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- A = {counter, 0},
- B = [],
- ets:insert(foo, [A|B]),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1_suppressed.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1_suppressed.erl
deleted file mode 100644
index 5134cc6f0b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args1_suppressed.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args1_suppressed).
--export([start/0]).
-
--dialyzer({nowarn_function,start/0}).
-
-start() ->
- F = fun(T) -> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl
deleted file mode 100644
index c1857eb58b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args2.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args2).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1}, {maria, N+1}, {kostis, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl
deleted file mode 100644
index 74401b76fd..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args3.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args3).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{maria, N+1}, {kostis, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl
deleted file mode 100644
index 2c892074ec..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args4.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args4).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, {counter, N+1})
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl
deleted file mode 100644
index 156f555a7c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args5.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args5).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, {counter, N+1, N+2})
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0, 0}),
- io:format("Inserted ~w\n", [{counter, 0, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl
deleted file mode 100644
index 1e5887f76d..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args6.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args6).
--export([start/0]).
-
-start() ->
- F = fun(T)-> [{_, N}] = ets:lookup(T, counter),
- ets:insert(T, [{counter, N+1, N+2}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0, 0}),
- io:format("Inserted ~w\n", [{counter, 0, 0}]),
- F(foo),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl
deleted file mode 100644
index 912bbf7073..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args7.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args7).
--export([test/0]).
-
-test() ->
- Foo = foo,
- ets:new(Foo, [named_table, public]),
- race(Foo).
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-aux(Table, N) ->
- ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl
deleted file mode 100644
index 275cf0291c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_args8.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the argument types of the calls.
-
--module(ets_insert_args8).
--export([test/1]).
-
-test(Foo) ->
- ets:new(Foo, [named_table, public]),
- race(Foo).
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-aux(Table, N) ->
- ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl
deleted file mode 100644
index cfe0b2b727..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow1.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow1).
--export([start/0]).
-
-start() ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {random, random:uniform(maria:get_int())}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even number\n", []),
- io:format("\nWill make it odd\n", []),
- ets:insert(foo, {random, N+1});
- false -> ok
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, random),
- io:format("Random odd integer: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl
deleted file mode 100644
index d160418bdb..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow2.erl
+++ /dev/null
@@ -1,26 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow2).
--export([start/0]).
-
-start() ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {random, random:uniform(150)}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even integer\n", []),
- io:format("\nWill make it odd and generate password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}]);
- false ->
- io:format("\nInserted an odd integer\n", []),
- io:format("\nWill make it even and generate password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}])
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, pass),
- io:format("New password: ~w\n", [ObjectList]).
-
-generate_password(N) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl
deleted file mode 100644
index 9c6a22eb05..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow3.erl
+++ /dev/null
@@ -1,31 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow3).
--export([start/1]).
-
-start(User) ->
- Table = ets:new(table, [public]),
- mod:process(Table),
- [{_, N}] =
- case User of
- root -> ets:lookup(Table, root);
- user -> ets:lookup(Table, user);
- Other -> [{undefined, -1}]
- end,
- case N of
- -1 -> io:format("\nUnknown User\n", []);
- 0 ->
- case User of
- root ->
- ets:insert(Table, {User, Pass = generate_password(N) ++ generate_password(N+1)});
- user ->
- ets:insert(Table, {User, Pass = generate_password(N)})
- end,
- io:format("\nYour new pass is ~w\n", [Pass]);
- P ->
- io:format("\nYour pass is ~w\n", [P])
- end.
-
-generate_password(N) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl
deleted file mode 100644
index caa3804614..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow4.erl
+++ /dev/null
@@ -1,31 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow4).
--export([start/1]).
-
-start(User) ->
- Table = ets:new(table, [public]),
- mod:process(Table),
- [{_, N}] =
- case User of
- root -> ets:lookup(Table, pass);
- user -> ets:lookup(Table, pass);
- _Other -> [{undefined, -1}]
- end,
- case N of
- -1 -> io:format("\nUnknown User\n", []);
- 0 ->
- case User of
- root ->
- ets:insert(Table, {pass, Pass = generate_password(N) ++ generate_password(N+1)});
- user ->
- ets:insert(Table, {pass, Pass = generate_password(N)})
- end,
- io:format("\nYour new pass is ~w\n", [Pass]);
- P ->
- io:format("\nYour pass is ~w\n", [P])
- end.
-
-generate_password(N) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl
deleted file mode 100644
index b19fd776ec..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_control_flow5.erl
+++ /dev/null
@@ -1,34 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account control flow that might exist.
-
--module(ets_insert_control_flow5).
--export([start/1]).
-
-start(User) ->
- Table = ets:new(table, [public]),
- mod:process(Table),
- [{_, N}] =
- case User of
- root -> ets:lookup(Table, pass);
- user -> ets:lookup(Table, pass);
- Other -> [{undefined, -1}]
- end,
- [{_, Msg}] = ets:lookup(Table, welcome_msg),
- case N of
- -1 -> io:format("\nUnknown User\n", []);
- 0 ->
- case User of
- root ->
- ets:insert(Table, {welcome_msg, Msg ++ "root"}),
- ets:insert(Table, {pass, Pass = generate_password(N) ++ generate_password(N+1)});
- user ->
- ets:insert(Table, {welcome_msg, Msg ++ "user"}),
- ets:insert(Table, {pass, Pass = generate_password(N)})
- end,
- io:format("\nYour new pass is ~w\n", [Pass]);
- P ->
- io:format("\nYour pass is ~w\n", [P])
- end.
-
-generate_password(N) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl
deleted file mode 100644
index 7b2dbb8eff..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race1.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race1).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo), no_race(foo)}.
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-no_race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- AnotherTab = bar,
- aux(AnotherTab, N).
-
-aux(Table, N) ->
- ets:insert(Table, [{counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl
deleted file mode 100644
index d7afc79d07..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race2.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race2).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherTab = bar,
- aux(AnotherTab, Counter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, [{Counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl
deleted file mode 100644
index e05e9be54b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race3.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race3).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo), no_race(foo)}.
-
-race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- aux(Tab, N).
-
-no_race(Tab) ->
- [{_, N}] = ets:lookup(Tab, counter),
- AnotherTab = bar,
- aux(AnotherTab, N).
-
-aux(Table, N) ->
- ets:insert(Table, {counter, N+1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl
deleted file mode 100644
index e2a3588f41..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race4.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race4).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherTab = bar,
- aux(AnotherTab, Counter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, {Counter, N+1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl
deleted file mode 100644
index dd53387c11..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race5.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race5).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherCounter = index,
- aux(Tab, AnotherCounter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, [{Counter, N+1}]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl
deleted file mode 100644
index ec0a0eaadf..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_diff_atoms_race6.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between ets:lookup/
-%% ets:insert is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(ets_insert_diff_atoms_race6).
--export([test/0]).
-
-test() ->
- ets:new(foo, [named_table, public]),
- {race(foo, counter), no_race(foo, counter)}.
-
-race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- aux(Tab, Counter, N).
-
-no_race(Tab, Counter) ->
- [{_, N}] = ets:lookup(Tab, Counter),
- AnotherCounter = index,
- aux(Tab, AnotherCounter, N).
-
-aux(Table, Counter, N) ->
- ets:insert(Table, {Counter, N+1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl
deleted file mode 100644
index d5b6689eb1..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double1.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account multiple ets:inserts that might exist.
-
--module(ets_insert_double1).
--export([start/0]).
-
-start() ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {random, random:uniform(150)}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even integer\n", []),
- io:format("\nWill make it odd and generate new password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}]);
- false ->
- io:format("\nInserted an odd integer\n", []),
- io:format("\nWill make it even and generate new password\n", []),
- ets:insert(foo, [{random, N+1}, {pass, generate_password(N)}])
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, pass),
- io:format("New password: ~w\n", [ObjectList]),
- ets:insert(foo, {pass, 'empty'}).
-
-generate_password(N) ->
- [{_, P}] = ets:lookup(foo, pass),
- lists:map(fun (_) -> random:uniform(90)+P+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl
deleted file mode 100644
index fa653e3090..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_double2.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account multiple ets:inserts that might exist.
-
--module(ets_insert_double2).
--export([start/2]).
-
-start(Random, Pass) ->
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {Random, random:uniform(150)}),
- io:format("Inserted ~w\n", [{_, N}] = ets:lookup(foo, Random)),
- case (N rem 2 == 0) of
- true ->
- io:format("\nInserted an even integer\n", []),
- io:format("\nWill make it odd and generate new password\n", []),
- ets:insert(foo, [{Random, N+1}, {Pass, generate_password(Pass, N)}]);
- false ->
- io:format("\nInserted an odd integer\n", []),
- io:format("\nWill make it even and generate new password\n", []),
- ets:insert(foo, [{Random, N+1}, {Pass, generate_password(Pass, N)}])
- end,
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, Pass),
- io:format("New password: ~w\n", [ObjectList]),
- ets:insert(foo, {Pass, 'empty'}).
-
-generate_password(Pass, N) ->
- [{_, P}] = ets:lookup(foo, Pass),
- lists:map(fun (_) -> random:uniform(90)+P+$\s+1 end, lists:seq(1,N)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl
deleted file mode 100644
index b6b258fd21..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs1.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the anonymous functions.
-
--module(ets_insert_funs1).
--export([start/0]).
-
-start() ->
- F = fun(T) ->
- ets:lookup(T, counter)
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- [{_, N}] = F(foo),
- ets:insert(foo, [{counter, N+1}]),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl
deleted file mode 100644
index 6b9518f314..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_funs2.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account the anonymous functions.
-
--module(ets_insert_funs2).
--export([start/0]).
-
-start() ->
- F = fun(T, N) ->
- ets:insert(T, [{counter, N+1}])
- end,
- io:format("Created ~w\n", [ets:new(foo, [named_table, public])]),
- ets:insert(foo, {counter, 0}),
- io:format("Inserted ~w\n", [{counter, 0}]),
- [{_, N}] = ets:lookup(foo, counter),
- F(foo, N),
- io:format("Update complete\n", []),
- ObjectList = ets:lookup(foo, counter),
- io:format("Counter: ~w\n", [ObjectList]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl
deleted file mode 100644
index 63f3272912..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_new.erl
+++ /dev/null
@@ -1,15 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account multiple ets:new calls that might exist.
-
--module(ets_insert_new).
--export([test/0]).
-
-test() ->
- T1 = ets:new(foo, [public]),
- T2 = ets:new(bar, []),
- ets:lookup(T2, counter),
- aux(T1),
- aux(T2).
-
-aux(Tab) ->
- ets:insert(Tab, {counter, 1}).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl
deleted file mode 100644
index a479a31792..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_param.erl
+++ /dev/null
@@ -1,26 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination in higher order functions.
-
--module(ets_insert_param).
--export([start/1]).
-
-start(User) ->
- Table = ets:new(table, [public]),
- mod:process(Table),
- [{_, Msg}] = ets:lookup(Table, welcome_msg),
- case User of
- root ->
- ets:insert(Table, {welcome_msg, Msg ++ "root"}),
- ets:insert(Table, {pass, Pass = generate_password(ets:lookup(Table, pass))
- ++ generate_strong_password(ets:lookup(Table, pass))});
- user ->
- ets:insert(Table, {welcome_msg, Msg ++ "user"}),
- ets:insert(Table, {pass, Pass = generate_password(ets:lookup(Table, pass))})
- end,
- io:format("\nYour new pass is ~w\n", [Pass]).
-
-generate_password([{_, N}]) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,N)).
-
-generate_strong_password([{_, N}]) ->
- lists:map(fun (_) -> random:uniform(90)+$\s+1 end, lists:seq(1,(N rem 2) * 5)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl b/lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl
deleted file mode 100644
index 4caa9fe8a0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/ets_insert_public.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests the presence of possible races due to an ets:lookup/ets:insert
-%% combination. It takes into account any public ETS tables that might exist.
-
--module(ets_insert_public).
-
--export([main/1]).
-
-%% Main
-main(Foo) ->
- make_table(Foo),
- ets:insert(Foo, {counter, 0}),
- [{_, N}] = ets:lookup(Foo, counter),
- NewN = N + 1,
- ets:insert(Foo, {counter, NewN}),
- NewN.
-
-make_table(Foo) ->
- init(Foo).
-
-init(Foo) ->
- ets:new(Foo, [named_table, public]),
- ets:insert(Foo, {counter, 0}),
- {ok, feeling_good}.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl b/lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl
deleted file mode 100644
index 76ffca4676..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/extract_translations.erl
+++ /dev/null
@@ -1,293 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File : extract_translations.erl
-%%% Author : Sergei Golovan <sgolovan@nes.ru>
-%%% Purpose : Auxiliary tool for interface/messages translators
-%%% Created : 23 Apr 2005 by Sergei Golovan <sgolovan@nes.ru>
-%%% Id : $Id: extract_translations.erl,v 1.1 2009/08/17 09:18:59 maria Exp $
-%%%----------------------------------------------------------------------
-
--module(extract_translations).
--author('sgolovan@nes.ru').
-
--export([start/0]).
-
--define(STATUS_SUCCESS, 0).
--define(STATUS_ERROR, 1).
--define(STATUS_USAGE, 2).
-
--include_lib("kernel/include/file.hrl").
-
-
-start() ->
- ets:new(translations, [named_table, public]),
- ets:new(translations_obsolete, [named_table, public]),
- ets:new(files, [named_table, public]),
- ets:new(vars, [named_table, public]),
- case init:get_plain_arguments() of
- ["-srcmsg2po", Dir, File] ->
- print_po_header(File),
- Status = process(Dir, File, srcmsg2po),
- halt(Status);
- ["-unused", Dir, File] ->
- Status = process(Dir, File, unused),
- halt(Status);
- [Dir, File] ->
- Status = process(Dir, File, used),
- halt(Status);
- _ ->
- print_usage(),
- halt(?STATUS_USAGE)
- end.
-
-
-process(Dir, File, Used) ->
- case load_file(File) of
- {error, Reason} ->
- io:format("~s: ~s~n", [File, file:format_error(Reason)]),
- ?STATUS_ERROR;
- _ ->
- FileList = find_src_files(Dir),
- lists:foreach(
- fun(F) ->
- parse_file(Dir, F, Used)
- end, FileList),
- case Used of
- unused ->
- ets:foldl(fun({Key, _}, _) ->
- io:format("~p~n", [Key])
- end, ok, translations);
- srcmsg2po ->
- ets:foldl(fun({Key, Trans}, _) ->
- print_translation_obsolete(Key, Trans)
- end, ok, translations_obsolete);
- _ ->
- ok
- end,
- ?STATUS_SUCCESS
- end.
-
-parse_file(Dir, File, Used) ->
- ets:delete_all_objects(vars),
- case epp:parse_file(File, [Dir, filename:dirname(File) | code:get_path()], []) of
- {ok, Forms} ->
- lists:foreach(
- fun(F) ->
- parse_form(Dir, File, F, Used)
- end, Forms);
- _ ->
- ok
- end.
-
-parse_form(Dir, File, Form, Used) ->
- case Form of
- %%{undefined, Something} ->
- %% io:format("Undefined: ~p~n", [Something]);
- {call,
- _,
- {remote, _, {atom, _, translate}, {atom, _, translate}},
- [_, {string, Line, Str}]
- } ->
- process_string(Dir, File, Line, Str, Used);
- {call,
- _,
- {remote, _, {atom, _, translate}, {atom, _, translate}},
- [_, {var, _, Name}]
- } ->
- case ets:lookup(vars, Name) of
- [{_Name, Value, Line}] ->
- process_string(Dir, File, Line, Value, Used);
- _ ->
- ok
- end;
- {match,
- _,
- {var, _, Name},
- {string, Line, Value}
- } ->
- ets:insert(vars, {Name, Value, Line});
- L when is_list(L) ->
- lists:foreach(
- fun(F) ->
- parse_form(Dir, File, F, Used)
- end, L);
- T when is_tuple(T) ->
- lists:foreach(
- fun(F) ->
- parse_form(Dir, File, F, Used)
- end, tuple_to_list(T));
- _ ->
- ok
- end.
-
-process_string(_Dir, _File, _Line, "", _Used) ->
- ok;
-
-process_string(_Dir, File, Line, Str, Used) ->
- case {ets:lookup(translations, Str), Used} of
- {[{_Key, _Trans}], unused} ->
- ets:delete(translations, Str);
- {[{_Key, _Trans}], used} ->
- ok;
- {[{_Key, Trans}], srcmsg2po} ->
- ets:delete(translations_obsolete, Str),
- print_translation(File, Line, Str, Trans);
- {_, used} ->
- case ets:lookup(files, File) of
- [{_}] ->
- ok;
- _ ->
- io:format("~n% ~s~n", [File]),
- ets:insert(files, {File})
- end,
- case Str of
- [] -> ok;
- _ -> io:format("{~p, \"\"}.~n", [Str])
- end,
- ets:insert(translations, {Str, ""});
- {_, srcmsg2po} ->
- case ets:lookup(files, File) of
- [{_}] ->
- ok;
- _ ->
- ets:insert(files, {File})
- end,
- ets:insert(translations, {Str, ""}),
- print_translation(File, Line, Str, "");
- _ ->
- ok
- end.
-
-load_file(File) ->
- case file:consult(File) of
- {ok, Terms} ->
- lists:foreach(
- fun({Orig, Trans}) ->
- case Trans of
- "" ->
- ok;
- _ ->
- ets:insert(translations, {Orig, Trans}),
- ets:insert(translations_obsolete, {Orig, Trans})
- end
- end, Terms);
- Err ->
- Err
- end.
-
-find_src_files(Dir) ->
- case file:list_dir(Dir) of
- {ok, FileList} ->
- recurse_filelist(
- lists:map(
- fun(F) ->
- filename:join(Dir, F)
- end, FileList));
- _ ->
- []
- end.
-
-recurse_filelist(FileList) ->
- recurse_filelist(FileList, []).
-
-recurse_filelist([], Acc) ->
- lists:reverse(Acc);
-
-recurse_filelist([H | T], Acc) ->
- case file:read_file_info(H) of
- {ok, #file_info{type = directory}} ->
- recurse_filelist(T, lists:reverse(find_src_files(H)) ++ Acc);
- {ok, #file_info{type = regular}} ->
- case string:substr(H, string:len(H) - 3) of
- ".erl" ->
- recurse_filelist(T, [H | Acc]);
- ".hrl" ->
- recurse_filelist(T, [H | Acc]);
- _ ->
- recurse_filelist(T, Acc)
- end;
- _ ->
- recurse_filelist(T, Acc)
- end.
-
-
-print_usage() ->
- io:format(
- "Usage: extract_translations [-unused] dir file~n"
- "~n"
- "Example:~n"
- " extract_translations . ./msgs/ru.msg~n"
- ).
-
-
-%%%
-%%% Gettext
-%%%
-
-print_po_header(File) ->
- MsgProps = get_msg_header_props(File),
- {Language, [LastT | AddT]} = prepare_props(MsgProps),
- application:load(ejabberd),
- {ok, Version} = application:get_key(ejabberd, vsn),
- print_po_header(Version, Language, LastT, AddT).
-
-get_msg_header_props(File) ->
- {ok, F} = file:open(File, [read]),
- Lines = get_msg_header_props(F, []),
- file:close(F),
- Lines.
-
-get_msg_header_props(F, Lines) ->
- String = io:get_line(F, ""),
- case io_lib:fread("% ", String) of
- {ok, [], RemString} ->
- case io_lib:fread("~s", RemString) of
- {ok, [Key], Value} when Value /= "\n" ->
- %% The first character in Value is a blankspace:
- %% And the last characters are 'slash n'
- ValueClean = string:substr(Value, 2, string:len(Value)-2),
- get_msg_header_props(F, Lines ++ [{Key, ValueClean}]);
- _ ->
- get_msg_header_props(F, Lines)
- end;
- _ ->
- Lines
- end.
-
-prepare_props(MsgProps) ->
- Language = proplists:get_value("Language:", MsgProps),
- Authors = proplists:get_all_values("Author:", MsgProps),
- {Language, Authors}.
-
-print_po_header(Version, Language, LastTranslator, AdditionalTranslatorsList) ->
- AdditionalTranslatorsString = build_additional_translators(AdditionalTranslatorsList),
- HeaderString =
- "msgid \"\"\n"
- "msgstr \"\"\n"
- "\"Project-Id-Version: " ++ Version ++ "\\n\"\n"
- ++ "\"X-Language: " ++ Language ++ "\\n\"\n"
- "\"Last-Translator: " ++ LastTranslator ++ "\\n\"\n"
- ++ AdditionalTranslatorsString ++
- "\"MIME-Version: 1.0\\n\"\n"
- "\"Content-Type: text/plain; charset=UTF-8\\n\"\n"
- "\"Content-Transfer-Encoding: 8bit\\n\"\n",
- io:format("~s~n", [HeaderString]).
-
-build_additional_translators(List) ->
- lists:foldl(
- fun(T, Str) ->
- Str ++ "\"X-Additional-Translator: " ++ T ++ "\\n\"\n"
- end,
- "",
- List).
-
-print_translation(File, Line, Str, StrT) ->
- {ok, StrQ, _} = regexp:gsub(Str, "\"", "\\\""),
- {ok, StrTQ, _} = regexp:gsub(StrT, "\"", "\\\""),
- io:format("#: ~s:~p~nmsgid \"~s\"~nmsgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]).
-
-print_translation_obsolete(Str, StrT) ->
- File = "unknown.erl",
- Line = 1,
- {ok, StrQ, _} = regexp:gsub(Str, "\"", "\\\""),
- {ok, StrTQ, _} = regexp:gsub(StrT, "\"", "\\\""),
- io:format("#: ~s:~p~n#~~ msgid \"~s\"~n#~~ msgstr \"~s\"~n~n", [File, Line, StrQ, StrTQ]).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl
deleted file mode 100644
index 2f499208a2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race1.erl
+++ /dev/null
@@ -1,33 +0,0 @@
-%% This tests that the race condition detection between mnesia:dirty_read/
-%% mnesia:dirty_write is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(mnesia_diff_atoms_race1).
--export([test/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-test(Eno, Raise) ->
- {race(employee, Eno, Raise), no_race(employee, Eno, Raise)}.
-
-race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- aux(Tab, New).
-
-no_race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- AnotherTab = employer,
- aux(AnotherTab, New).
-
-
-aux(Table, Record) ->
- mnesia:dirty_write(Table, Record).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl
deleted file mode 100644
index c1dcfbd8f5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_diff_atoms_race2.erl
+++ /dev/null
@@ -1,37 +0,0 @@
-%% This tests that the race condition detection between mnesia:dirty_read/
-%% mnesia:dirty_write is robust even when the functions are called with
-%% different atoms as arguments.
-
--module(mnesia_diff_atoms_race2).
--export([test/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
--record(employer, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-test(Eno, Raise) ->
- {race(employee, Eno, Raise), no_race(employee, Eno, Raise)}.
-
-race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- aux(New).
-
-no_race(Tab, Eno, Raise) ->
- [E] = mnesia:dirty_read(Tab, Eno),
- AnotherRecord = #employer{},
- aux(AnotherRecord).
-
-aux(Record) ->
- mnesia:dirty_write(Record).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl
deleted file mode 100644
index 4ca62deedc..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_one_write_two.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_one_write_two).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read({employee, Eno}),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(employee, New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl
deleted file mode 100644
index e523a03789..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_two_write_one.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_two_write_one).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read(employee, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl
deleted file mode 100644
index 2bd18e4772..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double1.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account multiple
-%% mnesia:dirty_writes that might exist.
-
--module(mnesia_dirty_read_write_double1).
--export([raise/3]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise, Room) ->
- [E] = mnesia:dirty_read(employee, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(employee, New),
- move(E, Room).
-
-move(E, Room) ->
- New = E#employee{room_no = Room},
- mnesia:dirty_write(employee, New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl
deleted file mode 100644
index cdbfdc700a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double2.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account multiple
-%% mnesia:dirty_writes that might exist.
-
--module(mnesia_dirty_read_write_double2).
--export([raise/3]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise, Room) ->
- [E] = mnesia:dirty_read({employee, Eno}),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(New),
- move(E, Room).
-
-move(E, Room) ->
- New = E#employee{room_no = Room},
- mnesia:dirty_write(New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl
deleted file mode 100644
index 051524917e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double3.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account multiple
-%% mnesia:dirty_writes that might exist.
-
--module(mnesia_dirty_read_write_double3).
--export([raise/3]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise, Room) ->
- [E] = mnesia:dirty_read({employee, Eno}),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(employee, New),
- move(E, Room).
-
-move(E, Room) ->
- New = E#employee{room_no = Room},
- mnesia:dirty_write(employee, New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl
deleted file mode 100644
index 96752a6045..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_double4.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account multiple
-%% mnesia:dirty_writes that might exist.
-
--module(mnesia_dirty_read_write_double4).
--export([raise/3]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise, Room) ->
- [E] = mnesia:dirty_read(employee, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(New),
- move(E, Room).
-
-move(E, Room) ->
- New = E#employee{room_no = Room},
- mnesia:dirty_write(New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl
deleted file mode 100644
index aee6433736..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_one.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_write_one).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read({employee, Eno}),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl b/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl
deleted file mode 100644
index 037aeddafd..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/mnesia_dirty_read_write_two.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests the presence of possible races due to an mnesia:dirty_read/
-%% mnesia:dirty_write combination. It takes into account the argument types
-%% of the calls.
-
--module(mnesia_dirty_read_write_two).
--export([raise/2]).
-
--record(employee, {emp_no,
- name,
- salary,
- sex,
- phone,
- room_no}).
-
-
-raise(Eno, Raise) ->
- [E] = mnesia:dirty_read(employee, Eno),
- Salary = E#employee.salary + Raise,
- New = E#employee{salary = Salary},
- mnesia:dirty_write(employee, New).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl
deleted file mode 100644
index e65f6c3e23..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> register(AnAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl
deleted file mode 100644
index 41039482c9..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow2.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow2).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true ->
- io:format("self",[]),
- register(AnAtom, Pid);
- false -> register(AnAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl
deleted file mode 100644
index 94f8445fad..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow3.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow3).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- register(AnAtom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl
deleted file mode 100644
index 2a59760789..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow4.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow4).
--export([start/1]).
-
-start(Fun) ->
- case whereis(maria) of
- undefined ->
- Pid1 = spawn(Fun),
- case Pid1 =:= self() of
- true ->
- case whereis(kostis) of
- undefined ->
- Pid2 = spawn(Fun),
- case Pid2 =:= self() of
- true ->
- register(maria, Pid1),
- register(kostis, Pid2);
- false -> ok
- end;
- P when is_pid(P) ->
- ok
- end;
- false -> ok
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl
deleted file mode 100644
index 8de9cb2dad..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow5.erl
+++ /dev/null
@@ -1,12 +0,0 @@
-%% This tests the presence of possible races due to a whereis/unregister
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow5).
--export([start/1]).
-
-start(AnAtom) ->
- case whereis(AnAtom) of
- undefined -> ok;
- P when is_pid(P) ->
- unregister(AnAtom)
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl
deleted file mode 100644
index 03c5095a50..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_control_flow6.erl
+++ /dev/null
@@ -1,12 +0,0 @@
-%% This tests the presence of possible races due to a whereis/unregister
-%% combination. It takes into account control flow that might exist.
-
--module(whereis_control_flow6).
--export([start/0]).
-
-start() ->
- case whereis(kostis) of
- undefined -> ok;
- P when is_pid(P) ->
- unregister(kostis)
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl
deleted file mode 100644
index 704ee6015d..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_no_race.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different atoms
-%% as arguments.
-
--module(whereis_diff_atoms_no_race).
--export([test/0]).
-
-test() ->
- Fun = fun () -> foo end,
- {no_race(maria, Fun)}.
-
-no_race(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- AnotherAtom = kostis,
- aux(AnotherAtom, Pid);
- P when is_pid(P) ->
- ok
- end.
-
-aux(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl
deleted file mode 100644
index 6c834caa0c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_atoms_race.erl
+++ /dev/null
@@ -1,34 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different atoms
-%% as arguments.
-
--module(whereis_diff_atoms_race).
--export([test/0]). %, race/1, no_race/1]).
-
-test() ->
- Fun = fun () -> foo end,
- {race(maria, Fun), no_race(maria, Fun)}.
-
-race(AnAtom, Fun) ->
- %AnAtom = maria,
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- aux(AnAtom, Pid);
- P when is_pid(P) ->
- ok
- end.
-
-no_race(AnAtom, Fun) ->
- %AnAtom = maria,
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- AnotherAtom = kostis,
- aux(AnotherAtom, Pid);
- P when is_pid(P) ->
- ok
- end.
-
-aux(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl
deleted file mode 100644
index 6a1c197c06..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions1).
--export([start/2]).
-
-continue(Fun) ->
- case whereis(master) of
- undefined ->
- register(master, spawn(Fun));
- _ -> ok
- end.
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- register(AnAtom, Pid);
- _ ->
- ok
- end,
- continue(Fun).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl
deleted file mode 100644
index 4967dec133..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_nested.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions1_nested).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- race1(AnAtom, Pid);
- P when is_pid(P) ->
- true
- end.
-
-race1(Atom, Pid) ->
- race2(Atom, Pid).
-
-race2(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl
deleted file mode 100644
index ff6506eee8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_pathsens.erl
+++ /dev/null
@@ -1,32 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_functions1_pathsens).
--export([test/1]).
-
-test(FunName) ->
- start(kostis, mod:function(), FunName).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- race(AnAtom, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl
deleted file mode 100644
index dd395bb6d8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions1_twice.erl
+++ /dev/null
@@ -1,30 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having multiple calls in separate functions.
-
--module(whereis_diff_functions1_twice).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid1 = spawn(Fun),
- race(AnAtom, Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race_again(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-race_again(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl
deleted file mode 100644
index eaf98291ed..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions2).
--export([test/0]).
-
-test() ->
- start(kostis, mod:function()).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl
deleted file mode 100644
index 5ae8784389..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_nested.erl
+++ /dev/null
@@ -1,20 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions2_nested).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- race1(AnAtom, Pid);
- P when is_pid(P) ->
- true
- end.
-
-race1(Atom, Pid) ->
- race2(Atom, Pid).
-
-race2(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl
deleted file mode 100644
index e9ce4bc48e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_pathsens.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_functions2_pathsens).
--export([race/4]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end.
-
-race(Atom, Fun, FunName, Pid) ->
- start(Atom, Fun, FunName),
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl
deleted file mode 100644
index d5efe631b8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions2_twice.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having multiple calls in separate functions.
-
--module(whereis_diff_functions2_twice).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid1 = spawn(Fun),
- race(AnAtom, Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race_again(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-race_again(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl
deleted file mode 100644
index 093f02a06f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions3).
--export([start/1]).
-
-start(AnAtom) ->
- register(AnAtom, race(AnAtom)).
-
-race(Atom) ->
- whereis(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl
deleted file mode 100644
index 5c28fc74f6..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_nested.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%% This tests that the race condition detection between whereis/unregister
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions3_nested).
--export([test/1]).
-
-test(AnAtom) ->
- start(AnAtom).
-
-start(AnAtom) ->
- case whereis(AnAtom) of
- undefined -> true;
- P when is_pid(P) ->
- race1(AnAtom)
- end.
-
-race1(Atom) ->
- race2(Atom).
-
-race2(Atom) ->
- unregister(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl
deleted file mode 100644
index a3a245b9ea..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions3_pathsens.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_functions3_pathsens).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- race(AnAtom, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl
deleted file mode 100644
index e40483d487..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions4.erl
+++ /dev/null
@@ -1,32 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions4).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2),
- case whereis(AnAtom) of
- undefined ->
- Pid3 = spawn(Fun),
- race(AnAtom, Pid3);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl
deleted file mode 100644
index a2c4352803..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions5.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions5).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl
deleted file mode 100644
index f016d79533..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_functions6.erl
+++ /dev/null
@@ -1,29 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions.
-
--module(whereis_diff_functions6).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2),
- case whereis(AnAtom) of
- undefined ->
- Pid3 = spawn(Fun),
- race(AnAtom, Pid3);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl
deleted file mode 100644
index 00cb29cec0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules1.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_diff_modules2:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_diff_modules2:race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl
deleted file mode 100644
index e5f6fdeb7b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1/whereis_diff_modules2.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules2).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl
deleted file mode 100644
index a5f1d4d3c7..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules1_pathsens.erl
+++ /dev/null
@@ -1,26 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (backward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules1_pathsens).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end,
- whereis_diff_modules2_pathsens:race(AnAtom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl
deleted file mode 100644
index d24d13976b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_pathsens/whereis_diff_modules2_pathsens.erl
+++ /dev/null
@@ -1,12 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (backward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules2_pathsens).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl
deleted file mode 100644
index a397954eea..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules1_rec.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in an indirectly recursive inter-modular function.
-
--module(whereis_diff_modules1_rec).
--export([start/4]).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- case whereis(NextAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- whereis_diff_modules2_rec:continue(NextAtom, mod:next(), Pid, Id)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl
deleted file mode 100644
index 4b46b4a8e5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules1_rec/whereis_diff_modules2_rec.erl
+++ /dev/null
@@ -1,8 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in a recursive function.
-
--module(whereis_diff_modules2_rec).
--export([continue/4]).
-
-continue(Atom, NextAtom, Fun, Id) ->
- whereis_diff_modules1_rec:start(Atom, NextAtom, Fun, Id).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl
deleted file mode 100644
index 60b5a1d378..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules3.erl
+++ /dev/null
@@ -1,8 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules3).
--export([start/1]).
-
-start(AnAtom) ->
- register(AnAtom, whereis_diff_modules4:race(AnAtom)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl
deleted file mode 100644
index 1ab4fbf8d8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2/whereis_diff_modules4.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules4).
--export([no_race/1, race/1]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom) ->
- whereis(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl
deleted file mode 100644
index cb2f85a103..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules3_pathsens.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (forward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules3_pathsens).
--export([start/3]).
-
-start(AnAtom, Fun, FunName) ->
- Pid =
- case FunName of
- master ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end;
- slave ->
- case whereis(AnAtom) of
- undefined ->
- spawn(Fun);
- P when is_pid(P) ->
- P
- end
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl
deleted file mode 100644
index 952f9312f4..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_pathsens/whereis_diff_modules4_pathsens.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules (forward analysis).
-%% It takes into account control flow that might exist.
-
--module(whereis_diff_modules4_pathsens).
--export([no_race/1, race/4]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Fun, FunName, Pid) ->
- whereis_diff_modules3_pathsens:start(Atom, Fun, FunName),
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl
deleted file mode 100644
index 0320140768..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules3_rec.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in an indirectly recursive inter-modular function.
-
--module(whereis_diff_modules3_rec).
--export([test/0, start/4]).
-
-test() ->
- start(undefined, second, mod:f(), self()).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- case whereis(NextAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- whereis_diff_modules4_rec:continue(NextAtom, mod:next(), Pid, Id)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl
deleted file mode 100644
index d49c59ed5c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules2_rec/whereis_diff_modules4_rec.erl
+++ /dev/null
@@ -1,8 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in a recursive function.
-
--module(whereis_diff_modules4_rec).
--export([continue/4]).
-
-continue(Atom, NextAtom, Fun, Id) ->
- whereis_diff_modules3_rec:start(Atom, NextAtom, Fun, Id).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl
deleted file mode 100644
index 591732aa31..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules5.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules5).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_diff_modules6:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_diff_modules6:race(AnAtom, Pid2),
- case whereis(AnAtom) of
- undefined ->
- Pid3 = spawn(Fun),
- whereis_diff_modules6:race(AnAtom, Pid3);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl
deleted file mode 100644
index 159d96cfc5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules3/whereis_diff_modules6.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules6).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl
deleted file mode 100644
index a25d2f8784..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules1_nested.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules1_nested).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- whereis_diff_modules2_nested:race(AnAtom, Pid);
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl
deleted file mode 100644
index 32a55e731a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules2_nested.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules2_nested).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- whereis_diff_modules3_nested:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl
deleted file mode 100644
index 414129611f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_nested/whereis_diff_modules3_nested.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules3_nested).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl
deleted file mode 100644
index 92f2cb1fbc..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules1_twice.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having multiple calls in separate modules.
-
--module(whereis_diff_modules1_twice).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid1 = spawn(Fun),
- whereis_diff_modules2_twice:race(AnAtom, Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_diff_modules2_twice:race_again(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end;
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl
deleted file mode 100644
index 390c0dcc94..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_modules_twice/whereis_diff_modules2_twice.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate modules.
-
--module(whereis_diff_modules2_twice).
--export([race/2, race_again/2]).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-race_again(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl
deleted file mode 100644
index 8466004ce4..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_no_race.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different variables
-%% as arguments.
-
--module(whereis_diff_vars_no_race).
--export([test/3]).
-
-test(AnAtom, AnotherAtom, Pid) ->
- {aux(AnAtom, Pid), aux(AnotherAtom, Pid)}.
-
-aux(Atom, Pid) ->
- register(Atom, Pid),
- whereis(Atom).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl
deleted file mode 100644
index 90791de1b2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_diff_vars_race.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust even when the functions are called with different variables
-%% as arguments.
-
--module(whereis_diff_vars_race).
--export([test/2]).
-
-test(AnAtom, AnotherAtom) ->
- Fun = fun () -> foo end,
- {aux(AnAtom, AnotherAtom, Fun), aux(AnotherAtom, AnAtom, Fun)}.
-
-aux(Atom1, Atom2, Fun) ->
- case whereis(Atom1) of
- undefined ->
- Pid = spawn(Fun),
- register(Atom2, Pid);
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl
deleted file mode 100644
index 677551c99d..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module1.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module2:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-continue(Atom, Pid) ->
- whereis_intra_inter_module2:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl
deleted file mode 100644
index e7acee0cfd..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module1/whereis_intra_inter_module2.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module2).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl
deleted file mode 100644
index c8103db122..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module3.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module3).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module4:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_intra_inter_module4:race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl
deleted file mode 100644
index 4094a95223..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module2/whereis_intra_inter_module4.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module4).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- continue(Atom, Pid).
-
-continue(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl
deleted file mode 100644
index 2a29779153..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module5.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module5).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module6:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-continue(Atom, Pid) ->
- whereis_intra_inter_module6:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl
deleted file mode 100644
index cd05431cd5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module3/whereis_intra_inter_module6.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module6).
--export([no_race/1, race/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- continue(Atom, Pid).
-
-continue(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl
deleted file mode 100644
index 1f702e7af3..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module7.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module7).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- register(AnAtom, continue(AnAtom, Fun)).
-
-continue(AnAtom, Fun) ->
- whereis_intra_inter_module8:continue(AnAtom, Fun).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl
deleted file mode 100644
index 581817308b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module4/whereis_intra_inter_module8.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module8).
--export([continue/2]).
-
-continue(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun);
- P when is_pid(P) ->
- P
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl
deleted file mode 100644
index 7ed50ea742..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module10.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module10).
--export([continue/2]).
-
-continue(AnAtom, Fun) ->
- aux(AnAtom, Fun).
-
-aux(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun);
- P when is_pid(P) ->
- P
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl
deleted file mode 100644
index 5c5d92b770..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module5/whereis_intra_inter_module9.erl
+++ /dev/null
@@ -1,11 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module9).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- register(AnAtom, continue(AnAtom, Fun)).
-
-continue(AnAtom, Fun) ->
- whereis_intra_inter_module10:continue(AnAtom, Fun).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl
deleted file mode 100644
index 82abe2f4a8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module11.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module11).
--export([start/2, start_again/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module12:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_intra_inter_module12:race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-start_again(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module12:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_intra_inter_module12:continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl
deleted file mode 100644
index c2f5d560a0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module6/whereis_intra_inter_module12.erl
+++ /dev/null
@@ -1,14 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module12).
--export([no_race/1, race/2, continue/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- continue(Atom, Pid).
-
-continue(Atom, Pid) ->
- register(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl
deleted file mode 100644
index 3cd5cc6fa6..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module13.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module13).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module14:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-continue(Atom, Pid) ->
- whereis_intra_inter_module14:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl
deleted file mode 100644
index 6b6a982055..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module7/whereis_intra_inter_module14.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module14).
--export([no_race/1, race/2, start/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- race(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl
deleted file mode 100644
index c60d166fa9..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module15.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module15).
--export([start/2, continue/2]).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- whereis_intra_inter_module16:no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
-
-continue(Atom, Pid) ->
- whereis_intra_inter_module16:race(Atom, Pid).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl
deleted file mode 100644
index 279e633d66..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_intra_inter_module8/whereis_intra_inter_module16.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that the race condition detection between whereis/register
-%% is robust w.r.t. having the calls in separate functions and modules.
-
--module(whereis_intra_inter_module16).
--export([no_race/1, race/2, start/2]).
-
-no_race(Pid) ->
- register(master, Pid).
-
-race(Atom, Pid) ->
- register(Atom, Pid).
-
-start(AnAtom, Fun) ->
- Pid1 = spawn(Fun),
- no_race(Pid1),
- case whereis(AnAtom) of
- undefined ->
- Pid2 = spawn(Fun),
- whereis_intra_inter_module15:continue(AnAtom, Pid2);
- P when is_pid(P) ->
- true
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl
deleted file mode 100644
index 7bcde321a1..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_param.erl
+++ /dev/null
@@ -1,16 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in higher order functions.
-
--module(whereis_param).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- register(AnAtom, continue(AnAtom, Fun)).
-
-continue(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun);
- P when is_pid(P) ->
- P
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl
deleted file mode 100644
index 8bac0326a5..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module1.erl
+++ /dev/null
@@ -1,8 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in higher order functions and inter-module calls.
-
--module(whereis_param_inter_module1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- register(AnAtom, whereis_param_inter_module2:continue(AnAtom, Fun)).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl
deleted file mode 100644
index 61252add9a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_param_inter_module/whereis_param_inter_module2.erl
+++ /dev/null
@@ -1,13 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in higher order functions and inter-module calls.
-
--module(whereis_param_inter_module2).
--export([continue/2]).
-
-continue(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun);
- P when is_pid(P) ->
- P
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl
deleted file mode 100644
index c8095fbf4c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function1.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in a recursive function.
-
--module(whereis_rec_function1).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- register(AnAtom, Pid),
- start(AnAtom, Fun)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl
deleted file mode 100644
index 2721c9e19c..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function2.erl
+++ /dev/null
@@ -1,24 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in a recursive function.
-
--module(whereis_rec_function2).
--export([test/0]).
-
-test() ->
- start(undefined, second, mod:f(), self()).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- case whereis(NextAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> start(NextAtom, mod:next(), Pid, Id)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl
deleted file mode 100644
index e101f34fba..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function3.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in a recursive function.
-
--module(whereis_rec_function3).
--export([test/0]).
-
-test() ->
- start(undefined, second, mod:f(), self()).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- Pid =
- case whereis(NextAtom) of
- undefined -> spawn(Fun);
- P1 when is_pid(P1) -> P1
- end,
- case whereis(NextAtom) of
- undefined ->
- case Pid =:= self() of
- true -> ok;
- false -> start(NextAtom, mod:next(), Pid, Id), io:format("", [])
- end;
- P2 when is_pid(P2) -> ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl
deleted file mode 100644
index 4894d3397b..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function4.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in an indirectly recursive function.
-
--module(whereis_rec_function4).
--export([test/0]).
-
-test() ->
- start(undefined, second, mod:f(), self()).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- case whereis(NextAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> continue(NextAtom, mod:next(), Pid, Id)
- end;
- P when is_pid(P) ->
- ok
- end.
-
-continue(Atom, NextAtom, Fun, Id) ->
- start(Atom, NextAtom, Fun, Id).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl
deleted file mode 100644
index d821f829a2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function5.erl
+++ /dev/null
@@ -1,21 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in a recursive function.
-
--module(whereis_rec_function5).
--export([start/4]).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- case whereis(NextAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> start(NextAtom, mod:next(), Pid, Id)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl
deleted file mode 100644
index 4ec4baf0be..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function6.erl
+++ /dev/null
@@ -1,24 +0,0 @@
-%% This tests the presence of possible races due to a register/whereis
-%% combination in an indirectly recursive function.
-
--module(whereis_rec_function6).
--export([start/4]).
-
-start(AnAtom, NextAtom, Fun, Id) ->
- case AnAtom of
- undefined -> register(start, Id);
- _ -> register(AnAtom, Id)
- end,
- case whereis(NextAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> continue(NextAtom, mod:next(), Pid, Id)
- end;
- P when is_pid(P) ->
- ok
- end.
-
-continue(Atom, NextAtom, Fun, Id) ->
- start(Atom, NextAtom, Fun, Id).
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl
deleted file mode 100644
index 7667443117..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function7.erl
+++ /dev/null
@@ -1,19 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in a recursive function.
-
--module(whereis_rec_function7).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- start(AnAtom, Fun),
- register(AnAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl
deleted file mode 100644
index a06fb75f64..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_rec_function8.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests the presence of possible races due to a whereis/register
-%% combination in a recursive function.
-
--module(whereis_rec_function8).
--export([test/2]).
-
-test(AnAtom, Fun) ->
- start(AnAtom, Fun).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- start(AnAtom, Fun),
- register(AnAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl
deleted file mode 100644
index 39bb440f56..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_try_catch.erl
+++ /dev/null
@@ -1,25 +0,0 @@
-% This tests that warnings do appear when a whereis/register combination
-% is handled by try/catch.
-
--module(whereis_try_catch).
--export([race/1, no_race/1]).
-
-race(Pid) ->
- case whereis(master) of
- undefined ->
- try
- io:format("exception", [])
- catch
- _ -> register(master, Pid)
- end
- end.
-
-no_race(Pid) ->
- case whereis(master) of
- undefined ->
- try
- register(master, Pid)
- catch
- _ -> io:format("exception", [])
- end
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl
deleted file mode 100644
index 9b249e72be..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars1.erl
+++ /dev/null
@@ -1,17 +0,0 @@
-%% This tests that no warnings appear when there is no specific
-%% information about the types and the variables are not bound.
-
--module(whereis_vars1).
--export([start/3]).
-
-start(AnAtom, OtherAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false -> register(OtherAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl
deleted file mode 100644
index 5c1896d6b4..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars10.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars10).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom =/= OtherAtom of
- true -> ok;
- false -> register(OtherAtom, Pid)
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl
deleted file mode 100644
index dc8551b3f2..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars11.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that no warnings appear when there is no specific
-%% information about the types and the variables are not bound.
-
--module(whereis_vars11).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- OtherAtom -> ok;
- _Other -> register(OtherAtom, Pid)
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl
deleted file mode 100644
index 38b0dc5d04..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars12.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars12).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- if
- AnAtom =:= OtherAtom -> register(OtherAtom, Pid);
- AnAtom =/= OtherAtom -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl
deleted file mode 100644
index 3a04bba02f..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars13.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars13).
--export([start/3]).
-
-start(AnAtom, APid, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- if
- {AnAtom, Pid} =:= {OtherAtom, APid} -> register(OtherAtom, APid);
- {AnAtom, Pid} =/= {OtherAtom, APid} -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl
deleted file mode 100644
index c688847551..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars14.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars14).
--export([start/3]).
-
-start(AnAtom, APid, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- if
- [AnAtom, Pid] =:= [OtherAtom, APid] -> register(OtherAtom, APid);
- [AnAtom, Pid] =/= [OtherAtom, APid] -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl
deleted file mode 100644
index 4b3a72537e..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars15.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars15).
--export([start/3]).
-
-start(AnAtom, OtherAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- maria -> ok;
- kostis when AnAtom =:= OtherAtom ->
- register(OtherAtom, Pid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl
deleted file mode 100644
index 7badb8df22..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars16.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars16).
--export([start/4]).
-
-start(AnAtom, OtherAtom, APid, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- maria -> ok;
- kostis when {AnAtom, Pid} =:= {OtherAtom, APid} ->
- register(OtherAtom, APid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl
deleted file mode 100644
index bc7ef5e980..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars17.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars17).
--export([start/4]).
-
-start(AnAtom, OtherAtom, APid, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- maria -> ok;
- kostis when [AnAtom, Pid] =:= [OtherAtom, APid] ->
- register(OtherAtom, APid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl
deleted file mode 100644
index 06416fa987..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars18.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that no warnings appear when there is no specific
-%% information about the types and the variables are not bound.
-
--module(whereis_vars18).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom =:= OtherAtom of
- true -> ok;
- false -> register(OtherAtom, Pid)
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl
deleted file mode 100644
index ae5b28e42d..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars19.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that no warnings appear when there is no specific
-%% information about the types and the variables are not bound.
-
--module(whereis_vars19).
--export([start/3]).
-
-start(AnAtom, OtherAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- maria -> ok;
- kostis when AnAtom =/= OtherAtom ->
- register(OtherAtom, Pid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl
deleted file mode 100644
index bafb5d4644..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars2.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars2).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = AnAtom,
- case Pid =:= self() of
- true -> ok;
- false -> register(OtherAtom, Pid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl
deleted file mode 100644
index 87c6caadf0..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars20.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that no warnings appear when there is no specific
-%% information about the types and the variables are not bound.
-
--module(whereis_vars20).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- if
- AnAtom =:= OtherAtom -> ok;
- AnAtom =/= OtherAtom -> register(OtherAtom, Pid)
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl
deleted file mode 100644
index 73d22d3467..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars21.erl
+++ /dev/null
@@ -1,23 +0,0 @@
-%% This tests that no warnings appear when there is no specific
-%% information about the types and the variables are not bound.
-
--module(whereis_vars21).
--export([start/3]).
-
-start(AnAtom, OtherAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- maria when AnAtom =/= OtherAtom -> ok;
- kostis when AnAtom =/= OtherAtom ->
- register(OtherAtom, Pid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl
deleted file mode 100644
index dd16928e33..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars22.erl
+++ /dev/null
@@ -1,27 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars22).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- Same =
- case AnAtom of
- OtherAtom -> true;
- _Other -> false
- end,
- case Same of
- true -> register(OtherAtom, Pid);
- false -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl
deleted file mode 100644
index 16c9a6c8bc..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars3.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars3).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- {OtherAtom, APid} = {AnAtom, Pid},
- case Pid =:= self() of
- true -> ok;
- false -> register(OtherAtom, APid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl
deleted file mode 100644
index da5b329ca9..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars4.erl
+++ /dev/null
@@ -1,18 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars4).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- [OtherAtom, APid] = [AnAtom, Pid],
- case Pid =:= self() of
- true -> ok;
- false -> register(OtherAtom, APid)
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl
deleted file mode 100644
index dff8646ea8..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars5.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars5).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom of
- OtherAtom -> register(OtherAtom, Pid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl
deleted file mode 100644
index cf22ab1883..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars6.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars6).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case {AnAtom, Pid} of
- {OtherAtom, APid} -> register(OtherAtom, APid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl
deleted file mode 100644
index 4bce53982a..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars7.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars7).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case [AnAtom, Pid] of
- [OtherAtom, APid] -> register(OtherAtom, APid);
- _Other -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl
deleted file mode 100644
index 937b83cf02..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars8.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars8).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom =:= OtherAtom of
- true -> register(OtherAtom, Pid);
- false -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl b/lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl
deleted file mode 100644
index 9beb67ca38..0000000000
--- a/lib/dialyzer/test/race_SUITE_data/src/whereis_vars9.erl
+++ /dev/null
@@ -1,22 +0,0 @@
-%% This tests that warnings do appear when there is no specific
-%% information about the types and the variables are bound.
-
--module(whereis_vars9).
--export([start/2]).
-
-start(AnAtom, Fun) ->
- case whereis(AnAtom) of
- undefined ->
- Pid = spawn(Fun),
- OtherAtom = kostis,
- case Pid =:= self() of
- true -> ok;
- false ->
- case AnAtom == OtherAtom of
- true -> register(OtherAtom, Pid);
- false -> ok
- end
- end;
- P when is_pid(P) ->
- ok
- end.
diff --git a/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr b/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
index ce923a1c88..a6ac6d64e4 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
+++ b/lib/dialyzer/test/small_SUITE_data/results/bs_fail_constr
@@ -3,6 +3,11 @@ bs_fail_constr.erl:11:1: Function w3/1 has no local return
bs_fail_constr.erl:12:8: Binary construction will fail since the size field S in segment 42:S has type neg_integer()
bs_fail_constr.erl:14:1: Function w4/1 has no local return
bs_fail_constr.erl:15:5: Binary construction will fail since the value field V in segment V/utf32 has type float()
+bs_fail_constr.erl:18:1: Function bad_size_1/1 has no local return
+bs_fail_constr.erl:18:1: The pattern <<X:[]>> can never match the type any()
+bs_fail_constr.erl:21:1: Function bad_size_2/1 has no local return
+bs_fail_constr.erl:24:9: The pattern <<X:Size>> can never match the type any()
+bs_fail_constr.erl:29:1: Function bad_size_3/1 has no local return
bs_fail_constr.erl:5:1: Function w1/1 has no local return
bs_fail_constr.erl:6:5: Binary construction will fail since the value field V in segment V has type float()
bs_fail_constr.erl:8:1: Function w2/1 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_hangs b/lib/dialyzer/test/small_SUITE_data/results/fun_hangs
new file mode 100644
index 0000000000..139597f9cb
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/fun_hangs
@@ -0,0 +1,2 @@
+
+
diff --git a/lib/dialyzer/test/small_SUITE_data/results/gencall b/lib/dialyzer/test/small_SUITE_data/results/gencall
index b4dec09e4b..4e32e2aa9c 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/gencall
+++ b/lib/dialyzer/test/small_SUITE_data/results/gencall
@@ -1,4 +1,6 @@
-gencall.erl:11:3: Call to missing or unexported function gencall:foo/0
-gencall.erl:12:3: Call to missing or unexported function gen_server:handle_cast/2
-gencall.erl:9:3: Call to missing or unexported function ets:lookup/3
+gencall.erl:10:3: Call to missing or unexported function gen_server:handle_cast/2
+gencall.erl:5:1: Function f/0 has no local return
+gencall.erl:6:34: The call gen_server:call(pid(),'request',{'not_a_timeout'}) breaks the contract (ServerRef::server_ref(),Request::term(),Timeout::timeout()) -> Reply::term()
+gencall.erl:7:3: Call to missing or unexported function ets:lookup/3
+gencall.erl:9:3: Call to missing or unexported function gencall:foo/0
diff --git a/lib/dialyzer/test/small_SUITE_data/results/guards b/lib/dialyzer/test/small_SUITE_data/results/guards
index 8e2386c77a..9313d3e43a 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/guards
+++ b/lib/dialyzer/test/small_SUITE_data/results/guards
@@ -8,6 +8,10 @@ guards.erl:129:32: The call guards:t15('c') will never return since it differs i
guards.erl:136:16: The call guards:t16('a') will never return since it differs in the 1st argument from the success typing arguments: ('b')
guards.erl:136:1: Function t16_a/0 has no local return
guards.erl:136:32: The call guards:t16('c') will never return since it differs in the 1st argument from the success typing arguments: ('b')
+guards.erl:140:1: Function t17/1 has no local return
+guards.erl:140:1: Guard test #{'x':=_} =:= 'true' can never succeed
+guards.erl:145:1: Function t18/1 has no local return
+guards.erl:145:1: Guard test binary() =:= 'true' can never succeed
guards.erl:55:1: Function t5/1 has no local return
guards.erl:55:27: Guard test is_integer(A::atom()) can never succeed
guards.erl:59:1: Function t6/1 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/results/try2 b/lib/dialyzer/test/small_SUITE_data/results/try2
index 14306bb756..e3fada37ea 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/try2
+++ b/lib/dialyzer/test/small_SUITE_data/results/try2
@@ -1,2 +1,3 @@
+try2.erl:12:1: Function run/2 has no local return
try2.erl:33:1: Function run3/2 has no local return
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
index 9ad4810a5e..50eb8db935 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -412,7 +412,7 @@ normalise({bin,_,Fs}) ->
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
{value, normalise(E), []}
- end, [], true),
+ end),
B;
normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
index fe567ff10d..5e8c1b95da 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -409,7 +409,7 @@ normalise({bin,_,Fs}) ->
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
{value, normalise(E), []}
- end, [], true),
+ end),
B;
normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl
deleted file mode 100644
index 851b8180d3..0000000000
--- a/lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl
+++ /dev/null
@@ -1,22 +0,0 @@
--module(binary_redef).
-
--export([t/0]).
-
--export_type([nonempty_binary/0, nonempty_bitstring/0]).
-
--type nonempty_binary() :: integer().
--type nonempty_bitstring() :: integer().
-
-t() ->
- I = new(),
- t1(I).
-
--spec t1(nonempty_bitstring()) -> nonempty_bitstring().
-
-t1(A) ->
- A + A.
-
--spec new() -> nonempty_binary().
-
-new() ->
- 3.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl b/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
index 8c1f8c009a..2446a3a4dd 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/bs_fail_constr.erl
@@ -1,6 +1,6 @@
-module(bs_fail_constr).
--export([w1/1, w2/1, w3/1, w4/1]).
+-export([w1/1, w2/1, w3/1, w4/1, bad_size_1/1, bad_size_2/1, bad_size_3/1]).
w1(V) when is_float(V) ->
<<V/integer>>.
@@ -13,3 +13,19 @@ w3(S) when is_integer(S), S < 0 ->
w4(V) when is_float(V) ->
<<V/utf32>>.
+
+%% GH-6419
+bad_size_1(<<X:[]>>) ->
+ ok.
+
+bad_size_2(Bin) ->
+ Size = [],
+ case Bin of
+ <<X:Size>> ->
+ ok
+ end.
+
+%% GH-6473
+bad_size_3(X) when X; <<X:X>> ->
+ bad_size_3(X),
+ X.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_named.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_named.erl
new file mode 100644
index 0000000000..4c74f092fa
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/fun_named.erl
@@ -0,0 +1,10 @@
+%% Analysis could enter an infinite loop when a named fun called itself.
+-module(fun_hangs).
+-export([bar/1, foo/0]).
+
+-spec bar(fun((pos_integer()) -> term())) -> term().
+bar(Fun) ->
+ Fun.
+
+foo() ->
+ bar(fun F(_) -> F(1) end).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/gencall.erl b/lib/dialyzer/test/small_SUITE_data/src/gencall.erl
index 762be55007..8e0ac802fb 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/gencall.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/gencall.erl
@@ -1,11 +1,9 @@
-%% Error: gen_server:handle_cast/2 is not logged as an unexported func
-%% but unknown function.
-module(gencall).
-export([f/0]).
f() ->
- gen_server:call(1,2,3),
+ gen_server:call(self(),request,{not_a_timeout}),
ets:lookup(1,2,3),
some_mod:some_function(),
gencall:foo(),
diff --git a/lib/dialyzer/test/small_SUITE_data/src/gh_6518.erl b/lib/dialyzer/test/small_SUITE_data/src/gh_6518.erl
new file mode 100644
index 0000000000..794548b37a
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/gh_6518.erl
@@ -0,0 +1,12 @@
+-module(gh_6518).
+-export([f/1]).
+
+f(X) ->
+ case
+ fun() ->
+ [ok || _ <- []]
+ end
+ of
+ _ ->
+ (Y = X)
+ end andalso Y.
diff --git a/lib/dialyzer/test/small_SUITE_data/src/guards.erl b/lib/dialyzer/test/small_SUITE_data/src/guards.erl
index 34c43d6d12..85d4d32214 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/guards.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/guards.erl
@@ -134,3 +134,24 @@ t16(A) when ((A =:= a) orelse (A =:= b)) andalso
((A =:= b) orelse (A =:= c)) -> ok.
t16_a() -> t16(a), t16(b), t16(c).
+
+%% Should give a warning
+
+t17(X) when #{x => X} ->
+ ok.
+
+%% Should give a warning
+
+t18(X) when <<X>> ->
+ ok.
+
+%% Coverage
+
+cover1() when 1 < 2; 1 > 2 ->
+ ok.
+
+cover2() when is_atom(1 < 2); is_atom(1 > 2) ->
+ ok.
+
+cover3() when not(1 < 2); not(1 > 2) ->
+ ok.
diff --git a/lib/dialyzer/test/user_SUITE_data/results/gh6580 b/lib/dialyzer/test/user_SUITE_data/results/gh6580
new file mode 100644
index 0000000000..6060365082
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/gh6580
@@ -0,0 +1,7 @@
+
+gh6580.erl:11:21: The pattern <[_ | _], _> can never match the type <[],<<>>>
+gh6580.erl:5:1: Function f/0 has no local return
+gh6580.erl:6:5: The created fun has no local return
+gh6580.erl:6:5: The pattern <[], _> can never match the type <<<>>,<<>>>
+gh6580.erl:6:5: The pattern <[_ | _], _> can never match the type <<<>>,<<>>>
+gh6580.erl:9:13: Fun application with arguments (<<>>,<<>>) will never return since it differs in the 1st argument from the success typing arguments: ([],any())
diff --git a/lib/dialyzer/test/user_SUITE_data/src/gh6580.erl b/lib/dialyzer/test/user_SUITE_data/src/gh6580.erl
new file mode 100644
index 0000000000..282e36ed79
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/gh6580.erl
@@ -0,0 +1,15 @@
+-module(gh6580).
+-export([f/0]).
+
+%% GH-6580: dialyzer would crash when binding an impossible cons.
+f() ->
+ <<
+ 0
+ || _ <-
+ case ok of
+ X ->
+ <<0 || _ <- []>>
+ end,
+ X <- 0,
+ #{X := Y} <- 0
+ >>.
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl b/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
index e5b387478f..02212328e4 100644
--- a/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
+++ b/lib/dialyzer/test/user_SUITE_data/src/wsp_pdu.erl
@@ -106,9 +106,9 @@ encode1(Pdu, Version) ->
headers=Headers} ->
EncServerSessionId = e_uintvar(ServerSessionId),
EncCapabilities = encode_capabilities(Capabilities),
- EncCapabilitiesLength = e_uintvar(size(EncCapabilities)),
+ EncCapabilitiesLength = e_uintvar(byte_size(EncCapabilities)),
EncHeaders = encode_headers(Headers,Version),
- EncHeadersLength = e_uintvar(size(EncHeaders)),
+ EncHeadersLength = e_uintvar(byte_size(EncHeaders)),
<<?WSP_ConnectReply,
EncServerSessionId/binary,
EncCapabilitiesLength/binary, EncHeadersLength/binary,
@@ -121,8 +121,8 @@ encode1(Pdu, Version) ->
EncStatus = encode_status_code(Status),
EncContentType = encode_content_type(ContentType,Version),
EncHeaders = encode_headers(Headers,Version),
- EncHeadersLength = e_uintvar(size(EncContentType)+
- size(EncHeaders)),
+ EncHeadersLength = e_uintvar(byte_size(EncContentType)+
+ byte_size(EncHeaders)),
<<?WSP_Reply,
EncStatus:8,
EncHeadersLength/binary,
@@ -137,8 +137,8 @@ encode1(Pdu, Version) ->
UriLength = e_uintvar(length(URI)),
EncContentType = encode_content_type(ContentType,Version),
EncHeaders = encode_headers(Headers,Version),
- EncHeadersLength = e_uintvar(size(EncContentType)+
- size(EncHeaders)),
+ EncHeadersLength = e_uintvar(byte_size(EncContentType)+
+ byte_size(EncHeaders)),
%% FIXME
<<PDUType:8,
UriLength/binary,
@@ -156,8 +156,8 @@ encode1(Pdu, Version) ->
EncHeaders = encode_headers(Headers,Version),
?dbg("Version ~p Headers ~p", [Version, Headers]),
?dbg("EncHeaders ~p", [EncHeaders]),
- EncHeadersLength = e_uintvar(size(EncContentType)+
- size(EncHeaders)),
+ EncHeadersLength = e_uintvar(byte_size(EncContentType)+
+ byte_size(EncHeaders)),
?dbg("EncCT = ~w ~w", [ContentType, EncContentType]),
?dbg("EncHL = ~w", [EncHeadersLength]),
<<PDUType:8,
@@ -278,7 +278,7 @@ decode(Data0, Version) ->
{HL0, D2} = d_uintvar(D1),
<<UriData:URILen/binary,D3/binary>> = D2,
{FieldData,D4} = scan_header_data(D3),
- HL1 = (HL0-(size(D3)-size(D4))),
+ HL1 = (HL0-(byte_size(D3)-byte_size(D4))),
<<D5:HL1/binary,Data/binary>> = D4,
ContentType = decode_content_type(FieldData, Version),
Headers = decode_headers(D5, Version),
@@ -290,7 +290,7 @@ decode(Data0, Version) ->
{HL0, D2} = d_uintvar(D1),
<<UriData:URILen/binary,D3/binary>> = D2,
{FieldData,D4} = scan_header_data(D3),
- HL1 = (HL0-(size(D3)-size(D4))),
+ HL1 = (HL0-(byte_size(D3)-byte_size(D4))),
<<D5:HL1/binary,Data/binary>> = D4,
ContentType = decode_content_type(FieldData, Version),
Headers = decode_headers(D5, Version),
@@ -304,7 +304,7 @@ decode(Data0, Version) ->
{FieldData, D2} = scan_header_data(D1),
ContentType = decode_content_type(FieldData, Version),
%% Headers are headersLength - binary size of content type
- HL1 = (HL0-(size(D1)-size(D2))),
+ HL1 = (HL0-(byte_size(D1)-byte_size(D2))),
<<D3:HL1/binary,Data/binary>> = D2,
Hs = decode_headers(D3, Version),
#wsp_reply{status=Status, content_type=ContentType,
@@ -322,7 +322,7 @@ decode(Data0, Version) ->
{HeadersLength, T200} = d_uintvar(D0),
{FieldData, T300} = scan_header_data(T200),
ContentType = decode_content_type(FieldData, Version),
- RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
+ RealHeadersLength = (HeadersLength-(byte_size(T200)-byte_size(T300))),
<<T400:RealHeadersLength/binary,Data/binary>> = T300,
Headers = decode_headers(T400, Version),
#wsp_push{type=push,content_type=ContentType,
@@ -332,7 +332,7 @@ decode(Data0, Version) ->
{HeadersLength, T200} = d_uintvar(D0),
{FieldData, T300} = scan_header_data(T200),
ContentType = decode_content_type(FieldData, Version),
- RealHeadersLength = (HeadersLength-(size(T200)-size(T300))),
+ RealHeadersLength = (HeadersLength-(byte_size(T200)-byte_size(T300))),
<<T400:RealHeadersLength/binary,Data/binary>> = T300,
Headers = decode_headers(T400, Version),
#wsp_push{type=confirmed_push,
@@ -443,7 +443,7 @@ encode_capabilities(Cap,Def) ->
list_to_binary(
lists:map(fun(<<>>) -> [];
(Bin) ->
- [e_uintvar(size(Bin)), Bin]
+ [e_uintvar(byte_size(Bin)), Bin]
end, Known ++ Unknown)).
@@ -3135,7 +3135,7 @@ encode_cookies([{Name,Value,Ps} | Cs], Acc) ->
[] ->
[]
end],
- Sz = lists:sum(lists:map(fun(B) -> size(B) end, List)),
+ Sz = lists:sum(lists:map(fun(B) -> byte_size(B) end, List)),
encode_cookies(Cs, [[e_uintvar(Sz) | List] | Acc]);
encode_cookies([], Acc) ->
list_to_binary(lists:reverse(Acc)).
@@ -4430,8 +4430,8 @@ encode_multipart_entry(Entry, Version) ->
data = Data } = Entry,
EncContentType = encode_content_type(ContentType,Version),
EncHeaders = encode_headers(Headers, Version),
- EncHeadersLength = e_uintvar(size(EncContentType)+size(EncHeaders)),
- DataLen = e_uintvar(size(Data)),
+ EncHeadersLength = e_uintvar(byte_size(EncContentType)+byte_size(EncHeaders)),
+ DataLen = e_uintvar(byte_size(Data)),
<<EncHeadersLength/binary,
DataLen/binary,
EncContentType/binary,
@@ -4462,7 +4462,7 @@ decode_multipart_entry(Data, Version) ->
{DataLen, Data2} = d_uintvar(Data1),
{FieldData,Data3} = scan_header_data(Data2),
ContentType = decode_content_type(FieldData, Version),
- BinHeadersLen = (HeadersLen-(size(Data2)-size(Data3))),
+ BinHeadersLen = (HeadersLen-(byte_size(Data2)-byte_size(Data3))),
<<BinHeaders:BinHeadersLen/binary,Data4/binary>> = Data3,
Headers = decode_headers(BinHeaders, Version),
<<ValueData:DataLen/binary, Data5/binary>> = Data4,
@@ -5014,7 +5014,7 @@ encode_integer(List) when list(List) ->
decode_integer(Value) when integer(Value) ->
Value;
decode_integer({short,Data}) ->
- Sz = size(Data)*8,
+ Sz = byte_size(Data)*8,
<<Value:Sz>> = Data,
Value.
@@ -5051,7 +5051,7 @@ decode_long_integer(<<0:3,Len:5,Data/binary>>) when Len =/= 31 ->
<<Val:Sz, Tail/binary>> = Data,
{Val, Tail}.
-d_long(Data) ->
+d_long(Data) when is_binary(Data) ->
Sz = size(Data)*8,
<<Value:Sz>> = Data,
Value.
@@ -5176,7 +5176,7 @@ e_uintvar(I,Acc) ->
e_value(B) ->
- Sz = size(B),
+ Sz = byte_size(B),
if Sz =< 30 ->
<<Sz:8, B/binary>>;
true ->
@@ -5184,7 +5184,7 @@ e_value(B) ->
end.
e_value(B1,B2) ->
- Sz = size(B1)+size(B2),
+ Sz = byte_size(B1)+byte_size(B2),
if Sz =< 30 ->
<<Sz:8, B1/binary, B2/binary>>;
true ->
@@ -5192,7 +5192,7 @@ e_value(B1,B2) ->
end.
e_value(B1,B2,B3) ->
- Sz = size(B1)+size(B2)+size(B3),
+ Sz = byte_size(B1)+byte_size(B2)+byte_size(B3),
if Sz =< 30 ->
<<Sz:8, B1/binary,B2/binary,B3/binary>>;
true ->
@@ -5200,7 +5200,7 @@ e_value(B1,B2,B3) ->
end.
e_value(B1,B2,B3,B4) ->
- Sz = size(B1)+size(B2)+size(B3)+size(B4),
+ Sz = byte_size(B1)+byte_size(B2)+byte_size(B3)+byte_size(B4),
if Sz =< 30 ->
<<Sz:8, B1/binary,B2/binary,B3/binary,B4/binary>>;
true ->
@@ -5266,7 +5266,7 @@ encode_address(#wdp_address { bearer = B, address = Addr, portnum = P }) ->
binary(Addr) ->
Addr
end,
- Len = size(BAddr),
+ Len = byte_size(BAddr),
if B == undefined, P == undefined ->
<<0:1, 0:1, Len:6, BAddr/binary>>;
B == undefined ->
@@ -5284,8 +5284,8 @@ encode_address(#wdp_address { bearer = B, address = Addr, portnum = P }) ->
d_date(Val) when integer(Val) ->
calendar:gregorian_seconds_to_datetime(Val+?UNIX_TIME_OFFSET);
-d_date({short,Data}) ->
- Sz = size(Data)*8,
+d_date({short,Data}) when is_binary(Data) ->
+ Sz = byte_size(Data)*8,
<<Sec:Sz>> = Data,
calendar:gregorian_seconds_to_datetime(Sec+?UNIX_TIME_OFFSET).
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index fc10b86d46..965a949121 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 4.4.4
+DIALYZER_VSN = 5.0.5
diff --git a/lib/diameter/Makefile b/lib/diameter/Makefile
index 320e72ada1..fccbba7501 100644
--- a/lib/diameter/Makefile
+++ b/lib/diameter/Makefile
@@ -28,5 +28,6 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=ssl runtime_tools syntax_tools
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 0b664b5b50..3619a118a1 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -11,14 +11,14 @@
<header>
<copyright>
<year>2011</year>
-<year>2021</year>
+<year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -43,6 +43,53 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 2.2.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>diameter 2.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix decode of non-IP address types; that is, of values of
+ the derived AVP data format Address whose first two
+ octets specify an address family other than 1 (IP) or 2
+ (IP6). Such values have never been decoded, and were
+ treated as decode errors. They're now decoded to a
+ 2-tuple of the integer() address family and binary()
+ remaining octets, with no family-specific decode. The
+ 2-tuple distinguishes the decode from the 4-tuple and
+ 8-tuple IP address decodes. 2-tuples are also now
+ encoded.</p>
+ <p>
+ Note that even currently unassigned address families are
+ decoded: only the reserved values, 0 and 65535, are
+ treated as errors.</p>
+ <p>
+ Own Id: OTP-17976 Aux Id: GH-5463 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.2.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -643,7 +690,7 @@ first.</p>
</item>
<item>
<p>
- Update build scripts to not make assumtions about where
+ Update build scripts to not make assumptions about where
env, cp and perl are located.</p>
<p>
Own Id: OTP-13800</p>
@@ -910,7 +957,7 @@ first.</p>
connection over SCTP, and then TCP in case SCTP fails.
Multiple module tuples can be paired with a single config
tuple, but in this case the start order was reversed
- relative to the order in which the modules were specifed.</p>
+ relative to the order in which the modules were specified.</p>
<p>
Own Id: OTP-12851</p>
</item>
diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile
index 348cc350e1..75e23d4191 100644
--- a/lib/diameter/src/Makefile
+++ b/lib/diameter/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2020. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -122,6 +122,12 @@ ERL_COMPILE_FLAGS += \
# -pa is to be able to include_lib from the include directory: the
# path must contain the application name.
+ifeq ($(ERL_DETERMINISTIC),yes)
+ DETERMINISM_FLAG = +deterministic
+else
+ DETERMINISM_FLAG =
+endif
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -146,13 +152,13 @@ patch:
git diff --exit-code HEAD
$(MAKE) opt PRE_VSN="-$(shell git rev-list --max-count=1 HEAD | cut -c 1-8)"
-debug:
- @$(MAKE) TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
# The dictionary parser.
gen/$(DICT_YRL).erl: compiler/$(DICT_YRL).yrl
$(yecc_verbose) \
- $(ERLC) -Werror -o $(@D) $<
+ $(ERLC) -Werror $(DETERMINISM_FLAG) -o $(@D) $<
# Generate the app file.
$(APP_TARGET): $(APP_SRC) ../vsn.mk modules.mk
@@ -256,8 +262,8 @@ release_spec: opt
$(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_%)
+ $(MAKE) ERL_DETERMINISTIC=$(ERL_DETERMINISTIC) $(TARGET_DIRS:%/=release_src_%)
+ $(MAKE) ERL_DETERMINISTIC=$(ERL_DETERMINISTIC) $(EXAMPLE_DIRS:%/=release_examples_%)
$(TARGET_DIRS:%/=release_src_%): release_src_%:
$(INSTALL_DIR) "$(RELSYSDIR)/src/$*"
diff --git a/lib/diameter/src/base/diameter_callback.erl b/lib/diameter/src/base/diameter_callback.erl
index 3bcf550cd8..a2b2ba8ffb 100644
--- a/lib/diameter/src/base/diameter_callback.erl
+++ b/lib/diameter/src/base/diameter_callback.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@
%%
%% {module, [diameter_callback, {peer_down, {mymod, down, []}}]}
%%
-%% The following would result in this module suppying peer_up and
+%% The following would result in this module supplying peer_up and
%% peer_down callback, others taking place in module mymod.
%%
%% {module, #diameter_callback{peer_up = false,
diff --git a/lib/diameter/src/base/diameter_reg.erl b/lib/diameter/src/base/diameter_reg.erl
index c1762a07e3..2fd6abbfbd 100644
--- a/lib/diameter/src/base/diameter_reg.erl
+++ b/lib/diameter/src/base/diameter_reg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -76,7 +76,7 @@
%% # add(T)
%%
%% Associate the specified term with self(). The list of pids having
-%% this or other assocations can be retrieved using match/1.
+%% this or other associations can be retrieved using match/1.
%%
%% An association is removed when the calling process dies or as a
%% result of calling remove/1. Adding the same term more than once is
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 520a7233cc..6ff9de3341 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -686,7 +686,7 @@ cs(undefined, _) ->
%% # i/1
%% ---------------------------------------------------------------------------
-%% Intialize the state of a service gen_server.
+%% Initialize the state of a service gen_server.
i(SvcName) ->
%% Split the config into a server state and a list of transports.
@@ -1072,7 +1072,7 @@ reopen({TPid, {Caps, SupportedApps, _Pkt}},
%% ---------------------------------------------------------------------------
%% Watchdog has recovered a suspect connection. Note that there has
-%% been no new capabilties exchange in this case.
+%% been no new capabilities exchange in this case.
connection_up(#watchdog{peer = TPid} = Wd, #state{local = {PeerT, _, _}}
= S) ->
diff --git a/lib/diameter/src/base/diameter_types.erl b/lib/diameter/src/base/diameter_types.erl
index 86b674dd48..79312dfe13 100644
--- a/lib/diameter/src/base/diameter_types.erl
+++ b/lib/diameter/src/base/diameter_types.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -247,9 +247,19 @@
2 == A, 16 == size(B) ->
list_to_tuple([N || <<N:A/unit:8>> <= B]);
+%% Bytes for non-IP address types are left for the user to interpret.
+'Address'(decode, <<A:16, B/binary>>, _)
+ when 2 < A, A < 65535 ->
+ {A, B};
+
'Address'(decode, B, _) ->
?INVALID_LENGTH(B);
+%% Allow IP address types as both 2- and 4/8-tuples.
+'Address'(encode, {A, B}, _)
+ when 0 < A, A < 65535 ->
+ <<A:16, B/binary>>;
+
'Address'(encode, T, _) ->
Ns = tuple_to_list(diameter_lib:ipaddr(T)), %% length 4 or 8
A = length(Ns) div 4, %% 1 or 2
diff --git a/lib/diameter/src/diameter.app.src b/lib/diameter/src/diameter.app.src
index 18202f033e..27f248e070 100644
--- a/lib/diameter/src/diameter.app.src
+++ b/lib/diameter/src/diameter.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@
{mod, {diameter_app, []}},
{runtime_dependencies, [
"erts-10.0",
- "stdlib-2.4",
+ "stdlib-3.0",
"kernel-3.2",
"ssl-9.0"
%, "syntax-tools-1.6.18"
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index bbfa44086e..97e95c94b6 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -70,12 +70,17 @@
{update, diameter_peer_fsm},
{update, diameter_service},
{load_module, diameter_traffic},
+ {load_module, diameter_types},
{update, diameter_tcp},
{update, diameter_sctp}]},
{"2.2.2", [{load_module, diameter}, %% 22.2.8
+ {load_module, diameter_types},
{update, diameter_sctp}]},
- {"2.2.3", [{update, diameter_sctp}]}, %% 22.3
- {"2.2.4", []} %% 23.3.4
+ {"2.2.3", [{load_module, diameter_types},
+ {update, diameter_sctp}]}, %% 22.3
+ {"2.2.4", [{load_module, diameter_types}]}, %% 23.3.4
+ {"2.2.5", [{load_module, diameter_types}]}, %% 24.3
+ {"2.2.6", [{restart_application, diameter}]}
],
[
{"0.9", [{restart_application, diameter}]},
@@ -127,11 +132,16 @@
{update, diameter_peer_fsm},
{update, diameter_service},
{load_module, diameter_traffic},
+ {load_module, diameter_types},
{update, diameter_tcp},
{update, diameter_sctp}]},
{"2.2.2", [{load_module, diameter},
+ {load_module, diameter_types},
{update, diameter_sctp}]},
- {"2.2.3", [{update, diameter_sctp}]},
- {"2.2.4", []}
+ {"2.2.3", [{load_module, diameter_types},
+ {update, diameter_sctp}]},
+ {"2.2.4", [{load_module, diameter_types}]},
+ {"2.2.5", [{load_module, diameter_types}]},
+ {"2.2.6", [{restart_application, diameter}]}
]
}.
diff --git a/lib/diameter/src/info/diameter_info.erl b/lib/diameter/src/info/diameter_info.erl
index 9ff6769ba5..9d1f392c4e 100644
--- a/lib/diameter/src/info/diameter_info.erl
+++ b/lib/diameter/src/info/diameter_info.erl
@@ -166,7 +166,7 @@ format(Recs, Fields, SFun)
%%% Output: Number of entries output.
%%%
%%% Description: Pretty-print records in a named tables as collected
-%%% from known nodes. Each table listing is preceeded by
+%%% from known nodes. Each table listing is preceded by
%%% a banner.
%%% ----------------------------------------------------------
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl
index 2c5dc2fa2e..f40f2b1fc4 100644
--- a/lib/diameter/src/transport/diameter_tcp.erl
+++ b/lib/diameter/src/transport/diameter_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
-export([listener/1,%% diameter_sync callback
info/1]). %% service_info callback
+%% test
-export([ports/0,
ports/1]).
@@ -450,16 +451,20 @@ sock(_, Sock) ->
resolve(Type, S) ->
Sock = sock(Type, S),
try
- ok(portnr(Sock))
+ {ok, T} = portnr(Sock),
+ T
catch
_:_ -> Sock
end.
-portnr(Sock)
- when is_port(Sock) ->
- portnr(gen_tcp, Sock);
+%% Assume either ssl or gen_tcp. In particular, this can't deal with a
+%% transport module that called start/3 with an own module option.
portnr(Sock) ->
- portnr(ssl, Sock).
+ try
+ {ok, _} = portnr(ssl, Sock)
+ catch
+ _:_ -> portnr(gen_tcp, Sock)
+ end.
%% ---------------------------------------------------------------------------
%% # handle_call/3
@@ -615,7 +620,7 @@ transition({P, Sock, Bin}, #transport{socket = Sock,
P == tcp ->
recv(acc(Frag, Bin), S);
-%% Capabilties exchange has decided on whether or not to run over TLS.
+%% Capabilities exchange has decided on whether or not to run over TLS.
transition({diameter, {tls, Ref, Type, B}}, #transport{parent = Pid}
= S) ->
true = is_boolean(B), %% assert
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
index c574d70e45..98fb9ff652 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -59,22 +59,20 @@ ERL_COMPILE_FLAGS += +warn_export_vars \
-I ../include \
-I ../src/gen \
$(STRICT_FLAGS)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-all debug opt: $(TARGET_FILES)
+all $(TYPES): $(TARGET_FILES)
strict:
$(MAKE) opt STRICT_FLAGS=-Werror
-# Require success ...
-run: $(SUITES)
-
-# ... or not.
-any: opt
- $(MAKE) -i $(SUITES)
+# Run all suites, without/with common_test.
+run: $(SUITES:%=_%)
+ct: $(SUITES)
clean:
rm -f $(TARGET_FILES)
@@ -91,13 +89,11 @@ info:
@echo ========================================
@$(call list,MODULES)
@echo
- @$(call list,HRL_FILES)
- @echo
@$(call list,SUITES)
@echo
@echo erl = $(shell which erl)
@erl -noinput \
- -eval 'io:format("diameter = ~s~n", [code:lib_dir(diameter)])' \
+ -eval 'io:format("diameter = ~ts~n", [code:lib_dir(diameter)])' \
-s init stop
@echo ========================================
@@ -109,13 +105,14 @@ help:
@echo " Compile all test suites."
@echo
@echo " run:"
- @echo " Compile and run all test suites, stop on failure."
+ @echo " Compile and run all test suites without common_test."
@echo
- @echo " any:"
- @echo " Compile and run all test suites, ignore any failures."
+ @echo " ct:"
+ @echo " Compile and run all test suites with common_test."
@echo
@echo " $(SUITES):"
@echo " Compile and run a specific test suite."
+ @echo " Prefix with _ to run without common_test."
@echo
@echo " clean | realclean:"
@echo " Remove generated files."
@@ -124,7 +121,10 @@ help:
@echo " Echo some relevant variables."
@echo ========================================
-.PHONY: all any run clean debug docs help info opt realclean strict
+.PHONY: all ct run clean debug docs help info opt realclean strict
+
+# Disable crash dumps.
+export ERL_CRASH_DUMP_BYTES=0
# ----------------------------------------------------
# Special Targets
@@ -132,7 +132,8 @@ help:
# Exit with a non-zero status if the output looks to indicate failure.
# diameter_ct:run/1 itself can't tell (it seems). The absolute -pa is
-# because ct will change directories.
+# because ct will change directories, and for code:lib_dir(diameter) to
+# return the parent directory.
$(SUITES): log opt
$(ERL) -noinput \
-pa $(realpath ../ebin) \
@@ -142,6 +143,14 @@ $(SUITES): log opt
| awk '{print} / FAILED /{rc=1} END{exit rc}' rc=0
# Shorter in sed but requires a GNU extension (ie. Q).
+# Run suites without common_test.
+$(SUITES:%=_%): opt
+ $(ERL) -noinput \
+ -pa $(realpath ../ebin) \
+ -sname diameter_test_$@ \
+ -s diameter$@_SUITE run \
+ -s init stop
+
cover: log opt coverspec
$(ERL) -noinput \
-pa $(realpath ../ebin) \
@@ -173,7 +182,6 @@ release_tests_spec:
$(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(TEST_SPEC_FILE) \
$(COVER_SPEC_FILE) \
- $(HRL_FILES) \
"$(RELSYSDIR)"
$(MAKE) $(DATA_DIRS:%/=release_data_%)
$(MAKE) $(ERL_FILES:%=/%)
diff --git a/lib/diameter/test/diameter.spec b/lib/diameter/test/diameter.spec
index fae7863bec..be62bb7f2b 100644
--- a/lib/diameter/test/diameter.spec
+++ b/lib/diameter/test/diameter.spec
@@ -1 +1,2 @@
{suites, "../diameter_test", all}.
+{skip_suites, "../diameter_test", [diameter_gen_sctp_SUITE], "Fails due to suspect gen_sctp behaviour."}.
diff --git a/lib/diameter/test/diameter_3xxx_SUITE.erl b/lib/diameter/test/diameter_3xxx_SUITE.erl
index 0f060c4ba7..63de2467a3 100644
--- a/lib/diameter/test/diameter_3xxx_SUITE.erl
+++ b/lib/diameter/test/diameter_3xxx_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,19 +26,17 @@
-module(diameter_3xxx_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
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]).
-
-%% testcases
--export([start/1,
- send_unknown_application/1,
+ traffic/1]).
+
+%% internal
+-export([send_unknown_application/1,
send_unknown_command/1,
send_ok/1,
send_invalid_hdr_bits/1,
@@ -47,9 +45,7 @@
send_5xxx_missing_avp/1,
send_double_error/1,
send_3xxx/1,
- send_5xxx/1,
- counters/1,
- stop/1]).
+ send_5xxx/1]).
%% diameter callbacks
-export([peer_up/3,
@@ -67,11 +63,7 @@
%% ===========================================================================
-define(util, diameter_util).
--define(testcase(), proplists:get_value(testcase, get(?MODULE))).
--define(group(Config), begin
- put(?MODULE, Config),
- ?util:name(proplists:get_value(group, Config))
- end).
+-define(testcase(), get(?MODULE)).
-define(L, atom_to_list).
-define(A, list_to_atom).
@@ -106,34 +98,15 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [{group, ?util:name([E,D])} || E <- ?ERRORS, D <- ?RFCS].
-
-groups() ->
- Tc = tc(),
- [{?util:name([E,D]), [], [start] ++ Tc ++ [counters, stop]}
- || E <- ?ERRORS, D <- ?RFCS].
-
-init_per_suite(Config) ->
- ok = diameter:start(),
- Config.
+ [traffic].
-end_per_suite(_Config) ->
- ok = diameter:stop().
+traffic(_Config) ->
+ run().
-init_per_group(Group, Config) ->
- [{group, Group} | Config].
-
-end_per_group(_, _) ->
- ok.
-
-init_per_testcase(Name, Config) ->
- [{testcase, Name} | Config].
-
-end_per_testcase(_, _) ->
- ok.
+%% ===========================================================================
tc() ->
[send_unknown_application,
@@ -147,25 +120,36 @@ tc() ->
send_3xxx,
send_5xxx].
-%% ===========================================================================
+%% run/0
+
+run() ->
+ ?util:run([[{{?MODULE, run, [{E,D}]}, 60000} || E <- ?ERRORS,
+ D <- ?RFCS]]).
+
+%% run/1
-%% start/1
+run({F, [_,_] = G}) ->
+ put(?MODULE, F),
+ apply(?MODULE, F, [G]);
-start(Config) ->
- Group = proplists:get_value(group, Config),
- [Errors, RFC] = ?util:name(Group),
- ok = diameter:start_service(?SERVER, ?SERVICE(?L(Group),
- Errors,
- RFC)),
+run({E,D}) ->
+ try
+ run([E,D])
+ after
+ ok = diameter:stop()
+ end;
+
+run([Errors, RFC] = G) ->
+ Name = ?L(Errors) ++ "," ++ ?L(RFC),
+ ok = diameter:start(),
+ ok = diameter:start_service(?SERVER, ?SERVICE(Name, Errors, RFC)),
ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT,
callback,
rfc6733)),
LRef = ?util:listen(?SERVER, tcp),
- ?util:connect(?CLIENT, tcp, LRef).
-
-%% stop/1
-
-stop(_Config) ->
+ ?util:connect(?CLIENT, tcp, LRef),
+ ?util:run([{?MODULE, run, [{F,G}]} || F <- tc()]),
+ _ = counters(G),
ok = diameter:remove_transport(?CLIENT, true),
ok = diameter:remove_transport(?SERVER, true),
ok = diameter:stop_service(?SERVER),
@@ -175,9 +159,7 @@ stop(_Config) ->
%%
%% Check that counters are as expected.
-counters(Config) ->
- Group = proplists:get_value(group, Config),
- [_Errors, _Rfc] = G = ?util:name(Group),
+counters([_Errors, _RFC] = G) ->
[] = ?util:run([[fun counters/3, K, S, G]
|| K <- [statistics, transport, connections],
S <- [?CLIENT, ?SERVER]]).
@@ -379,10 +361,7 @@ send_unknown_application([_,_]) ->
%% UNSUPPORTED_APPLICATION
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_unknown_application(Config) ->
- send_unknown_application(?group(Config)).
+ = call().
%% send_unknown_command/1
%%
@@ -398,10 +377,7 @@ send_unknown_command([_,_]) ->
%% UNSUPPORTED_COMMAND
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_unknown_command(Config) ->
- send_unknown_command(?group(Config)).
+ = call().
%% send_ok/1
%%
@@ -412,10 +388,7 @@ send_ok([_,_]) ->
#diameter_base_STA{'Result-Code' = 5002, %% UNKNOWN_SESSION_ID
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_ok(Config) ->
- send_ok(?group(Config)).
+ = call().
%% send_invalid_hdr_bits/1
%%
@@ -433,10 +406,7 @@ send_invalid_hdr_bits([_,_]) ->
#'diameter_base_answer-message'{'Result-Code' = 3008, %% INVALID_HDR_BITS
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_invalid_hdr_bits(Config) ->
- send_invalid_hdr_bits(?group(Config)).
+ = call().
%% send_missing_avp/1
%%
@@ -454,10 +424,7 @@ send_missing_avp([_,_]) ->
#diameter_base_STA{'Result-Code' = 5005, %% MISSING_AVP
'Failed-AVP' = [_],
'AVP' = []}
- = call();
-
-send_missing_avp(Config) ->
- send_missing_avp(?group(Config)).
+ = call().
%% send_ignore_missing_avp/1
%%
@@ -475,10 +442,7 @@ send_ignore_missing_avp([_,_]) ->
#diameter_base_STA{'Result-Code' = 2001, %% SUCCESS
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_ignore_missing_avp(Config) ->
- send_ignore_missing_avp(?group(Config)).
+ = call().
%% send_5xxx_missing_avp/1
%%
@@ -501,10 +465,7 @@ send_5xxx_missing_avp([_,_]) ->
#diameter_base_STA{'Result-Code' = 2001, %% SUCCESS
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_5xxx_missing_avp(Config) ->
- send_5xxx_missing_avp(?group(Config)).
+ = call().
%% send_double_error/1
%%
@@ -522,10 +483,7 @@ send_double_error([_,_]) ->
#'diameter_base_answer-message'{'Result-Code' = 3008, %% INVALID_HDR_BITS
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_double_error(Config) ->
- send_double_error(?group(Config)).
+ = call().
%% send_3xxx/1
%%
@@ -536,10 +494,7 @@ send_3xxx([_,_]) ->
#'diameter_base_answer-message'{'Result-Code' = 3999,
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_3xxx(Config) ->
- send_3xxx(?group(Config)).
+ = call().
%% send_5xxx/1
%%
@@ -555,10 +510,7 @@ send_5xxx([_,_]) ->
#'diameter_base_answer-message'{'Result-Code' = 5999,
'Failed-AVP' = [],
'AVP' = []}
- = call();
-
-send_5xxx(Config) ->
- send_5xxx(?group(Config)).
+ = call().
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl
index ef4a28d3f4..adcc7114a1 100644
--- a/lib/diameter/test/diameter_app_SUITE.erl
+++ b/lib/diameter/test/diameter_app_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,22 +24,24 @@
-module(diameter_app_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
- all/0,
- init_per_suite/1,
- end_per_suite/1]).
+ all/0]).
%% testcases
-export([keys/1,
vsn/1,
- modules/1,
- exports/1,
+ modules/1,
+ exports/1,
release/1,
- xref/1,
+ xref/1,
relup/1]).
--include("diameter_ct.hrl").
-
+-define(util, diameter_util).
-define(A, list_to_atom).
%% Modules not in the app and that should not have dependencies on it
@@ -57,7 +59,7 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 20}}].
all() ->
[keys,
@@ -68,12 +70,22 @@ all() ->
xref,
relup].
-init_per_suite(Config) ->
- [{application, ?APP, App}] = diameter_util:consult(?APP, app),
- [{app, App} | Config].
+%% ===========================================================================
+
+run() ->
+ run(all()).
+
+run(List) ->
+ Tmp = ?util:mktemp("diameter_app"),
+ try
+ run([{priv_dir, Tmp}], List)
+ after
+ file:del_dir_r(Tmp)
+ end.
-end_per_suite(_Config) ->
- ok.
+run(Config, List) ->
+ [{application, diameter, App}] = ?util:consult(diameter, app),
+ ?util:run([{{?MODULE, F, [{App, Config}]}, 10000} || F <- List]).
%% ===========================================================================
%% # keys/1
@@ -82,10 +94,12 @@ end_per_suite(_Config) ->
%% also be caught by other testcases.
%% ===========================================================================
-keys(Config) ->
- App = fetch(app, Config),
+keys({App, _Config}) ->
[] = lists:filter(fun(K) -> not lists:keymember(K, 1, App) end,
- [vsn, description, modules, registered, applications]).
+ [vsn, description, modules, registered, applications]);
+
+keys(Config) ->
+ run(Config, [keys]).
%% ===========================================================================
%% # vsn/1
@@ -93,8 +107,11 @@ keys(Config) ->
%% Ensure that our app version sticks to convention.
%% ===========================================================================
+vsn({App, _Config}) ->
+ true = is_vsn(fetch(vsn, App));
+
vsn(Config) ->
- true = is_vsn(fetch(vsn, fetch(app, Config))).
+ run(Config, [vsn]).
%% ===========================================================================
%% # modules/1
@@ -103,15 +120,17 @@ vsn(Config) ->
%% compiler/info modules.
%% ===========================================================================
-modules(Config) ->
- Mods = fetch(modules, fetch(app, Config)),
+modules({App, _Config}) ->
+ Mods = fetch(modules, App),
Installed = code_mods(),
Help = lists:sort(?INFO_MODULES ++ ?COMPILER_MODULES),
+ {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)};
- {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}.
+modules(Config) ->
+ run(Config, [modules]).
code_mods() ->
- Dir = code:lib_dir(?APP, ebin),
+ Dir = code:lib_dir(diameter, ebin),
{ok, Files} = file:list_dir(Dir),
[?A(lists:reverse(R)) || N <- Files, "maeb." ++ R <- [lists:reverse(N)]].
@@ -121,9 +140,12 @@ code_mods() ->
%% Ensure that no module does export_all.
%% ===========================================================================
+exports({App, _Config}) ->
+ Mods = fetch(modules, App),
+ [] = [M || M <- Mods, exports_all(M)];
+
exports(Config) ->
- Mods = fetch(modules, fetch(app, Config)),
- [] = [M || M <- Mods, exports_all(M)].
+ run(Config, [exports]).
exports_all(Mod) ->
Opts = fetch(options, Mod:module_info(compile)),
@@ -136,8 +158,7 @@ exports_all(Mod) ->
%% Ensure that it's possible to build a minimal release with our app file.
%% ===========================================================================
-release(Config) ->
- App = fetch(app, Config),
+release({App, Config}) ->
Rel = {release,
{"diameter test release", fetch(vsn, App)},
{erts, erlang:system_info(version)},
@@ -146,13 +167,16 @@ release(Config) ->
ok = write_file(filename:join([Dir, "diameter_test.rel"]), Rel),
{ok, _, []} = systools:make_script("diameter_test", [{path, [Dir]},
{outdir, Dir},
- silent]).
+ silent]);
+
+release(Config) ->
+ run(Config, [release]).
%% 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),
+ [{application, Name, App}] = ?util:consult(Name, app),
fetch(vsn, App).
%% ===========================================================================
@@ -162,8 +186,7 @@ appvsn(Name) ->
%% or one in an application we haven't declared as a dependency. (Almost.)
%% ===========================================================================
-xref(Config) ->
- App = fetch(app, Config),
+xref({App, _Config}) ->
Mods = fetch(modules, App), %% modules listed in the app file
%% List of application names extracted from runtime_dependencies.
@@ -179,7 +202,7 @@ xref(Config) ->
%% the sense that there's no .app file, and isn't listed in
%% applications.
ok = lists:foreach(fun(A) -> add_application(XRef, A) end,
- [?APP, erts | fetch(applications, App)]),
+ [diameter, erts | fetch(applications, App)]),
{ok, Undefs} = xref:analyze(XRef, undefined_function_calls),
{ok, RTmods} = xref:analyze(XRef, {module_use, Mods}),
@@ -212,7 +235,10 @@ xref(Config) ->
%% The declared application versions are ignored since we only
%% know what we see now.
[] = lists:filter(fun(M) -> not lists:member(app(M), Deps) end,
- RTdeps -- Mods).
+ RTdeps -- Mods);
+
+xref(Config) ->
+ run(Config, [xref]).
ignored({FromMod,_,_}, {ToMod,_,_} = To, Rel)->
%% diameter_tcp does call ssl despite the latter not being listed
@@ -281,7 +307,7 @@ add_application(XRef, App, Dir)
{ok, App} = xref:add_application(XRef, Dir, []).
make_name(Suf) ->
- list_to_atom(atom_to_list(?APP) ++ "_" ++ atom_to_list(Suf)).
+ list_to_atom("diameter_" ++ atom_to_list(Suf)).
%% ===========================================================================
%% # relup/1
@@ -289,11 +315,10 @@ make_name(Suf) ->
%% Ensure that we can generate release upgrade files using our appup file.
%% ===========================================================================
-relup(Config) ->
- [{Vsn, Up, Down}] = diameter_util:consult(?APP, appup),
+relup({App, Config}) ->
+ [{Vsn, Up, Down}] = ?util:consult(diameter, appup),
true = is_vsn(Vsn),
- App = fetch(app, Config),
Rel = [{erts, erlang:system_info(version)}
| [{A, appvsn(A)} || A <- [sasl | fetch(applications, App)]]],
@@ -303,26 +328,19 @@ relup(Config) ->
UpFrom = acc_rel(Dir, Rel, Up),
DownTo = acc_rel(Dir, Rel, Down),
- {[Name], [Name], [], []} %% no current in up/down and go both ways
- = {[Name] -- UpFrom,
- [Name] -- DownTo,
- UpFrom -- DownTo,
- DownTo -- UpFrom},
-
+ {[], []} = {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]).
+ silent]);
-acc_rel(Dir, Rel, List) ->
- lists:foldl(fun(T,A) -> acc_rel(Dir, Rel, T, A) end,
- [],
- List).
+relup(Config) ->
+ run(Config, [relup]).
-acc_rel(Dir, Rel, {Vsn, _}, Acc) ->
- [write_rel(Dir, Rel, Vsn) | Acc].
+acc_rel(Dir, Rel, List) ->
+ lists:map(fun({V,_}) -> write_rel(Dir, Rel, V) end, List).
%% Write a rel file and return its name.
write_rel(Dir, [Erts | Apps], Vsn) ->
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
index 51b6c1d7f2..35e62b7eda 100644
--- a/lib/diameter/test/diameter_capx_SUITE.erl
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,39 +25,30 @@
-module(diameter_capx_SUITE).
+%% testcases, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
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]).
-
-%% testcases
--export([start/1,
- vendor_id/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]).
+ traffic/1]).
%% diameter callbacks
-export([peer_up/4,
peer_down/4]).
+%% internal
+-export([s_no_common_application/1,
+ s_no_common_security/1,
+ s_unknown_peer/1,
+ s_unable/1,
+ s_client_reject/1,
+ c_no_common_application/1,
+ c_no_common_security/1,
+ c_unknown_peer/1,
+ c_unable/1,
+ c_client_reject/1]).
+
-include("diameter.hrl").
-include("diameter_gen_base_rfc3588.hrl").
%% Use only the Vendor-Specific-Application-Id record from the base
@@ -108,65 +99,20 @@
-define(caps, #diameter_caps).
-define(packet, #diameter_packet).
--define(fail(T), erlang:error({T, process_info(self(), messages)})).
-
--define(TIMEOUT, 10000).
-
-define(DICTS, [rfc3588, rfc6733]).
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
-
-all() -> [start,
- vendor_id,
- start_services,
- add_listeners]
- ++ [{group, D, P} || D <- ?DICTS, P <- [[], [parallel]]]
- ++ [remove_listeners,
- stop_services,
- stop].
-
-groups() ->
- Tc = lists:flatmap(fun tc/1, tc()),
- [{D, [], Tc} || D <- ?DICTS].
-
-init_per_suite(Config) ->
- lists:foreach(fun load_dict/1, ?NOAPPS),
- Config.
-
-end_per_suite(_Config) ->
- [] = [Mod || N <- ?NOAPPS,
- Mod <- [dict(N)],
- false <- [code:delete(Mod)]],
- ok.
+ [{timetrap, {seconds, 20}}].
-%% 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) ->
- [{host, ?L(Name) ++ "." ++ diameter_util:unique_string()}
- | Config].
+all() ->
+ [traffic].
-init_per_group(Name, Config) ->
- [{rfc, Name} | Config].
+traffic(_Config) ->
+ run().
-end_per_group(_, _) ->
- ok.
-
-end_per_testcase(N, _)
- when N == start;
- N == vendor_id;
- 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) ->
@@ -179,17 +125,46 @@ tc() ->
unable,
client_reject].
-%% ===========================================================================
-%% start/stop testcases
+run() ->
+ try
+ ?util:run([{fun traffic/0, 15000}])
+ after
+ ok = diameter:stop(),
+ [] = [M || N <- ?NOAPPS,
+ M <- [dict(N)],
+ B <- [code:delete(M)],
+ _ <- [code:purge(M)],
+ not B]
+ end.
-start(_Config) ->
- ok = diameter:start().
+traffic() ->
+ lists:foreach(fun load_dict/1, ?NOAPPS),
+ ok = diameter:start(),
+ _ = vendor_id(),
+ ok = diameter:start_service(?SERVER, ?SERVICE),
+ ok = diameter:start_service(?CLIENT, ?SERVICE),
+ LRefs = add_listeners(),
+ ?util:run([[fun traffic/3, F, D, LRefs] || D <- ?DICTS,
+ N <- tc(),
+ F <- tc(N)]),
+ ok = diameter:remove_transport(?SERVER, true),
+ ok = diameter:stop_service(?CLIENT),
+ ok = diameter:stop_service(?SERVER).
+
+%% Generate a unique hostname for each testcase so that watchdogs
+%% don't prevent a connection from being brought up immediately.
+traffic(F, Dict, {_Base, _Acct} = LRefs) ->
+ apply(?MODULE,
+ F,
+ [[{lref, LRefs},
+ {rfc, Dict},
+ {host, ?L(F) ++ "." ++ ?util:unique_string()}]]).
%% Ensure that both integer and list-valued vendor id's can be
%% configured in a Vendor-Specific-Application-Id, the arity having
%% changed between RFC 3588 and RFC 6733.
-vendor_id(_Config) ->
- [] = ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]).
+vendor_id() ->
+ ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]).
vid(V) ->
RC = diameter:start_service(make_ref(),
@@ -203,14 +178,10 @@ vid(x, {error, _}) ->
vid(_, ok) ->
ok.
-start_services(_Config) ->
- ok = diameter:start_service(?SERVER, ?SERVICE),
- ok = diameter:start_service(?CLIENT, ?SERVICE).
-
%% 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) ->
+add_listeners() ->
Acct = [listen(?SERVER,
[{capabilities, [{'Origin-Host', ?HOST(H)},
{'Auth-Application-Id', []}]},
@@ -224,17 +195,7 @@ add_listeners(Config) ->
{capabilities_cb, [fun server_capx/3, base]}])
|| {A,H} <- [{[base3588, acct3588], "base3588-srv"},
{[base6733, acct6733], "base6733-srv"}]],
- ?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().
+ {Base, Acct}.
%% ===========================================================================
%% All the testcases come in pairs, one for receiving an event on the
@@ -338,13 +299,10 @@ s_client_reject(Config) ->
receive
?event{service = ?SERVER,
info = {up, LRef,
- {_, ?caps{origin_host = {_, OH}}},
- {listen, _},
- ?packet{}}}
- = Info ->
- Info
- after ?TIMEOUT ->
- ?fail({LRef, OH})
+ {_, ?caps{origin_host = {_, OH}}},
+ {listen, _},
+ ?packet{}}} ->
+ ok
end.
c_client_reject(Config) ->
@@ -404,12 +362,9 @@ server_closed(Config, F, RC) ->
info = {closed, LRef,
{'CER', RC,
?caps{origin_host = {_, OH}},
- ?packet{}}
- = Reason,
+ ?packet{}},
{listen, _}}} ->
- Reason
- after ?TIMEOUT ->
- ?fail({LRef, OH})
+ ok
end.
%% server_reject/3
@@ -425,12 +380,9 @@ server_reject(Config, F, RC) ->
info = {closed, LRef,
{'CER', {capabilities_cb, _, RC},
?caps{origin_host = {_, OH}},
- ?packet{}}
- = Reason,
+ ?packet{}},
{listen, _}}} ->
- Reason
- after ?TIMEOUT ->
- ?fail({LRef, OH})
+ ok
end.
%% client_closed/4
@@ -459,8 +411,6 @@ client_recv(CRef) ->
?event{service = ?CLIENT,
info = {closed, CRef, Reason, {connect, _}}} ->
Reason
- after ?TIMEOUT ->
- ?fail(CRef)
end.
%% server_capx/3
@@ -504,20 +454,14 @@ listen(Name, 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),
- {ok, CRef} = diameter:add_transport(?CLIENT,
- {connect, opts(PortNr, Opts)}),
- CRef.
+ {ok, CRef}
+ = diameter:add_transport(?CLIENT, {connect, opts(H, PortNr, Opts)}),
+ {CRef, LRef}.
-opts(PortNr, Opts) ->
- [{transport_module, diameter_tcp},
+opts(Host, PortNr, Opts) ->
+ [{capabilities, [{'Origin-Host', ?HOST(Host)}]},
+ {transport_module, diameter_tcp},
{transport_config, [{raddr, ?ADDR},
{rport, PortNr},
{ip, ?ADDR},
@@ -531,7 +475,7 @@ lref(rfc6733, [_, LRef]) ->
lref(Config, T) ->
lref(proplists:get_value(rfc, Config),
- case ?util:read_priv(Config, ?MODULE) of
+ case proplists:get_value(lref, Config) of
{R, _} when T == base ->
R;
{_, R} when T == acct ->
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 17112794e4..f92b360dab 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,109 +28,134 @@
-module(diameter_codec_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
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]).
-
-%% testcases
--export([base/1,
+ base/1,
gen/1,
lib/1,
unknown/1,
- success/1,
- grouped_error/1,
- failed_error/1]).
+ recode/1]).
--include("diameter_ct.hrl").
-include("diameter.hrl").
+-define(util, diameter_util).
-define(L, atom_to_list).
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 10}}].
+ [{timetrap, {seconds, 15}}].
all() ->
- [base, gen, lib, unknown, {group, recode}].
+ [base, gen, lib, unknown, recode].
-groups() ->
- [{recode, [], [success,
- grouped_error,
- failed_error]}].
+base(_Config) ->
+ run(base).
-init_per_suite(Config) ->
- Config.
+gen(_Config) ->
+ run(gen).
-end_per_suite(_Config) ->
- ok.
+lib(_Config) ->
+ run(lib).
-init_per_group(recode, Config) ->
- ok = diameter:start(),
- Config.
+unknown(Config) ->
+ Priv = proplists:get_value(priv_dir, Config),
+ Data = proplists:get_value(data_dir, Config),
+ unknown(Priv, Data).
+
+recode(_Config) ->
+ run(recode).
+
+%% ===========================================================================
+
+%% run/0
+
+run() ->
+ run(all()).
+
+%% run/1
-end_per_group(_, _) ->
- ok = diameter:stop().
+run(base) ->
+ diameter_codec_test:base();
-init_per_testcase(gen, Config) ->
- [{application, ?APP, App}] = diameter_util:consult(?APP, app),
+run(gen) ->
+ [{application, diameter, App}] = diameter_util:consult(diameter, app),
{modules, Ms} = lists:keyfind(modules, 1, App),
[_|_] = Gs = lists:filter(fun(M) ->
lists:prefix("diameter_gen_", ?L(M))
end,
Ms),
- [{dicts, Gs} | Config];
+ lists:foreach(fun diameter_codec_test:gen/1, Gs);
-init_per_testcase(_Name, Config) ->
- Config.
+run(lib) ->
+ diameter_codec_test:lib();
-end_per_testcase(_, _) ->
- ok.
-
-%% ===========================================================================
-
-base(_Config) ->
- diameter_codec_test:base().
+%% Have a separate AVP dictionary just to exercise more code.
+run(unknown) ->
+ PD = ?util:mktemp("diameter_codec"),
+ DD = filename:join([code:lib_dir(diameter),
+ "test",
+ "diameter_codec_SUITE_data"]),
+ try
+ unknown(PD, DD)
+ after
+ file:del_dir_r(PD)
+ end;
+
+run(success) ->
+ success();
+
+run(grouped_error) ->
+ grouped_error();
+
+run(failed_error) ->
+ failed_error();
+
+run(recode) ->
+ ok = diameter:start(),
+ try
+ ?util:run([{?MODULE, run, [F]} || F <- [success,
+ grouped_error,
+ failed_error]])
+ after
+ ok = diameter:stop()
+ end;
-gen([{dicts, Ms} | _]) ->
- lists:foreach(fun diameter_codec_test:gen/1, Ms).
+run(List) ->
+ ?util:run([{{?MODULE, run, [F]}, 10000} || F <- List]).
-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"]),
+unknown(Priv, Data) ->
+ ok = make(Data, "recv.dia", Priv),
+ ok = make(Data, "avps.dia", Priv),
+ {ok, _, _} = compile(Priv, "diameter_test_avps.erl"),
+ ok = make(Data, "send.dia", Priv),
+ {ok, _, _} = compile(Priv, "diameter_test_send.erl"),
+ {ok, _, _} = compile(Priv, "diameter_test_recv.erl"),
+ {ok, _, _} = compile(Priv,
+ filename:join([Data, "diameter_test_unknown.erl"]),
[{i, Priv}]),
diameter_test_unknown:run().
-make(Dir, File) ->
- diameter_make:codec(filename:join([Dir, File])).
+make(Dir, File, Out) ->
+ diameter_make:codec(filename:join(Dir, File), [{outdir, Out}]).
-compile(File) ->
- compile(File, []).
+compile(Dir, File) ->
+ compile(Dir, File, []).
-compile(File, Opts) ->
- compile:file(File, [return | Opts]).
+compile(Dir, File, Opts) ->
+ compile:file(filename:join(Dir, File), [return | Opts]).
%% ===========================================================================
%% Ensure a Grouped AVP is represented by a list in the avps field.
-success(_) ->
+success() ->
Avps = [{295, <<1:32>>}, %% Termination-Cause
{284, [{280, "Proxy-Host"}, %% Proxy-Info
{33, "Proxy-State"}, %%
@@ -145,13 +170,13 @@ success(_) ->
value = 2,
data = <<2:32>>}]],
errors = []}
- = str(recode(str(Avps))).
+ = str(repkg(str(Avps))).
%% ===========================================================================
%% Ensure a Grouped AVP is represented by a list in the avps field
%% even in the case of a decode error on a component AVP.
-grouped_error(_) ->
+grouped_error() ->
Avps = [{295, <<1:32>>}, %% Termination-Cause
{284, [{295, <<0:32>>}, %% Proxy-Info, Termination-Cause
{280, "Proxy-Host"},
@@ -166,13 +191,13 @@ grouped_error(_) ->
#diameter_avp{code = 280},
#diameter_avp{code = 33}]],
errors = [{5004, #diameter_avp{code = 284}}]}
- = str(recode(str(Avps))).
+ = str(repkg(str(Avps))).
%% ===========================================================================
%% Ensure that a failed decode in Failed-AVP is acceptable, and that
%% the component AVPs are decoded if possible.
-failed_error(_) ->
+failed_error() ->
Avps = [{279, [{295, <<0:32>>}, %% Failed-AVP, Termination-Cause
{258, <<1:32>>}, %% Auth-Application-Id
{284, [{280, "Proxy-Host"}, %% Proxy-Info
@@ -195,7 +220,7 @@ failed_error(_) ->
value = 2,
data = <<2:32>>}]]],
errors = []}
- = sta(recode(sta(Avps))).
+ = sta(repkg(sta(Avps))).
%% ===========================================================================
@@ -279,9 +304,9 @@ avp([{_,_} | _] = Avps) ->
avp(V) ->
V.
-%% recode/1
+%% repkg/1
-recode(Msg) ->
+repkg(Msg) ->
recode(Msg, diameter_gen_base_rfc6733).
recode(#diameter_packet{} = Pkt, Dict) ->
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index 70e910ffa6..e4ad139d93 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -469,7 +469,7 @@ values(Name, Mod) ->
%%
%% Pack four variants of group values: tagged list containing all
%% values, the corresponding record, a minimal tagged list and the
-%% coresponding record.
+%% corresponding record.
group(Mod, Name, Rec, Avps, Enum) ->
lists:map(fun(B) -> group(Mod, Name, Rec, Avps, Enum, B) end,
diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl
index 73fe1ef6e0..cd886d4e8e 100644
--- a/lib/diameter/test/diameter_compiler_SUITE.erl
+++ b/lib/diameter/test/diameter_compiler_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,16 +24,17 @@
-module(diameter_compiler_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-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,
- flatten1/1, flatten1/3,
+ format/1,
+ replace/1,
+ generate/1,
+ flatten1/1,
flatten2/1]).
-export([dict/0]). %% fake dictionary module
@@ -364,7 +365,7 @@
%% ===========================================================================
suite() ->
- [{timetrap, {minutes, 10}}].
+ [{timetrap, {seconds, 200}}].
all() ->
[format,
@@ -373,36 +374,55 @@ all() ->
flatten1,
flatten2].
-%% 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) ->
+%% ===========================================================================
+
+%% run/0
+
+run() ->
+ run(all()).
+
+%% run/1
+
+run(List)
+ when is_list(List) ->
+ Tmp = ?util:mktemp("diameter_compiler"),
+ try
+ run(List, Tmp)
+ after
+ file:del_dir_r(Tmp)
+ end.
+
+%% run/2
+
+run(List, Dir)
+ when is_list(List) ->
Path = filename:join([code:lib_dir(diameter, src), "dict", ?base]),
{ok, Bin} = file:read_file(Path),
- [{base, Bin} | Config].
+ ?util:run([{{?MODULE, F, [{Bin, Dir}]}, 180000} || F <- List]);
-end_per_suite(_Config) ->
- ok.
+run(F, Config) ->
+ run([F], proplists:get_value(priv_dir, Config)).
%% ===========================================================================
%% 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({<<_/binary>> = Bin, _Dir}) ->
+ ?util:run([{?MODULE, format, [{M, Bin}]} || E <- ?REPLACE,
+ {ok, M} <- [norm(E)]]);
-format(Mods, Bin) ->
+format({Mods, Bin}) ->
B = modify(Bin, Mods),
- {ok, Dict} = parse(B, []),
- {ok, D} = parse(diameter_make:format(Dict), []),
- {Dict, Dict} = {Dict, D}.
+ {ok, Dict} = parse(B),
+ {ok, D} = parse(diameter_make:format(Dict)),
+ {Dict, Dict} = {Dict, D};
+
+format(Config) ->
+ run(format, Config).
-parse(File, Opts) ->
- case diameter_make:codec(File, [parse, hrl, return | Opts]) of
+parse(File) ->
+ case diameter_make:codec(File, [parse, hrl, return]) of
{ok, [Dict, _]} ->
{ok, Dict};
{error, _} = E ->
@@ -415,20 +435,21 @@ parse(File, Opts) ->
%% 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({<<_/binary>> = Bin, _Dir}) ->
+ ?util:run([{?MODULE, replace, [{N, Bin}]} || E <- ?REPLACE,
+ N <- [norm(E)]]);
-replace({E, Mods}, Bin) ->
+replace({{E, Mods}, Bin}) ->
B = modify(Bin, Mods),
- case {E, parse(B, [{include, here()}]), Mods} of
+ case {E, parse(B), Mods} of
{ok, {ok, Dict}, _} ->
Dict;
{_, {error, {E,_} = T}, _} when E /= ok ->
diameter_make:format_error(T)
- end.
+ end;
+
+replace(Config) ->
+ run(replace, Config).
re({RE, Repl}, Bin) ->
re:replace(Bin, RE, Repl, [multiline]).
@@ -438,23 +459,26 @@ re({RE, Repl}, Bin) ->
%%
%% Ensure success when generating code and compiling.
-generate(Config) ->
- Bin = proplists:get_value(base, Config),
+generate({<<_/binary>> = Bin, Dir}) ->
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, parse, forms]]).
+ ?util:run([{?MODULE, generate, [{M, Bin, N, T, Dir}]}
+ || {E,N} <- Rs,
+ {ok, M} <- [norm(E)],
+ T <- [erl, hrl, parse, forms]]);
-generate(Mods, Bin, N, Mode) ->
+generate({Mods, Bin, N, Mode, Dir}) ->
B = modify(Bin, Mods ++ [{"@name .*", "@name dict" ++ ?L(N)}]),
- {ok, Dict} = parse(B, []),
+ {ok, Dict} = parse(B),
File = "dict" ++ integer_to_list(N),
{_, ok} = {Dict, diameter_make:codec(Dict,
[{name, File},
{prefix, "base"},
+ {outdir, Dir},
Mode])},
- generate(Mode, File, Dict).
+ generate(Mode, filename:join(Dir, File), Dict);
+
+generate(Config) ->
+ run(generate, Config).
generate(erl, File, _) ->
{ok, _} = compile:file(File ++ ".erl", [return_errors]);
@@ -473,21 +497,21 @@ generate(hrl, _, _) ->
%% ===========================================================================
%% flatten1/1
-flatten1(_Config) ->
+flatten1({Key, BaseD, FlatD}) ->
+ Vs = orddict:fetch(Key, BaseD),
+ Vs = orddict:fetch(Key, FlatD);
+
+flatten1(_) ->
[Vsn | BaseD] = diameter_gen_base_rfc6733:dict(),
- {ok, I} = parse("@inherits diameter_gen_base_rfc6733\n", []),
+ {ok, I} = parse("@inherits diameter_gen_base_rfc6733\n"),
[Vsn | FlatD] = diameter_make:flatten(I),
- [] = ?util:run([{?MODULE, [flatten1, K, BaseD, FlatD]}
- || K <- [avp_types, grouped, enum]]).
-
-flatten1(Key, BaseD, FlatD) ->
- Vs = orddict:fetch(Key, BaseD),
- Vs = orddict:fetch(Key, FlatD).
+ ?util:run([{?MODULE, flatten1, [{K, BaseD, FlatD}]}
+ || K <- [avp_types, grouped, enum]]).
%% ===========================================================================
%% flatten2/1
-flatten2(_Config) ->
+flatten2(_) ->
Dict1 =
"@name diameter_test1\n"
"@prefix diameter_test1\n"
@@ -576,8 +600,5 @@ norm({E, RE, Repl}) ->
norm({_,_} = T) ->
T.
-here() ->
- filename:dirname(code:which(?MODULE)).
-
dict() ->
[0 | orddict:new()].
diff --git a/lib/diameter/test/diameter_config_SUITE.erl b/lib/diameter/test/diameter_config_SUITE.erl
index 31a6b49041..90773e8f6d 100644
--- a/lib/diameter/test/diameter_config_SUITE.erl
+++ b/lib/diameter/test/diameter_config_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,14 +25,15 @@
-module(diameter_config_SUITE).
--export([suite/0,
- all/0]).
+%% testscases, no common_test dependency
+-export([run/0,
+ run/1]).
-%% testcases
--export([start/1,
+%% common_test wrapping
+-export([suite/0,
+ all/0,
start_service/1,
- add_transport/1,
- stop/1]).
+ add_transport/1]).
-define(util, diameter_util).
@@ -204,38 +205,53 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 15}}].
all() ->
- [start,
- start_service,
- add_transport,
- stop].
+ [start_service,
+ add_transport].
+
+start_service(_Config) ->
+ run([start_service]).
+
+add_transport(_Config) ->
+ run([add_transport]).
%% ===========================================================================
-start(_) ->
- ok = diameter:start().
+run() ->
+ run(all()).
-start_service(T)
- when is_tuple(T) ->
- do(fun start/3, T);
+run(List)
+ when is_list(List) ->
+ try
+ ?util:run([[[fun run/1, {F, 5000}] || F <- List]])
+ after
+ dbg:stop_clear(),
+ diameter:stop()
+ end;
+
+run({F, Tmo}) ->
+ ok = diameter:start(),
+ try
+ ?util:run([{[fun run/1, F], Tmo}])
+ after
+ ok = diameter:stop()
+ end;
-start_service(_) ->
- [] = ?util:run([{?MODULE, start_service, [T]}
- || T <- [lists:keyfind(capabilities, 1, ?TRANSPORT_CONFIG)
- | ?SERVICE_CONFIG]]).
+run(start_service) ->
+ ?util:run([[fun start/1, T]
+ || T <- [lists:keyfind(capabilities, 1, ?TRANSPORT_CONFIG)
+ | ?SERVICE_CONFIG]]);
-add_transport(T)
- when is_tuple(T) ->
- do(fun add/3, T);
+run(add_transport) ->
+ ?util:run([[fun add/1, T] || T <- ?TRANSPORT_CONFIG]).
-add_transport(_) ->
- [] = ?util:run([{?MODULE, add_transport, [T]}
- || T <- ?TRANSPORT_CONFIG]).
+start(T) ->
+ do(fun start/3, T).
-stop(_) ->
- ok = diameter:stop().
+add(T) ->
+ do(fun add/3, T).
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_dist_SUITE.erl b/lib/diameter/test/diameter_dist_SUITE.erl
index 2fda2830ae..81d2dfbf36 100644
--- a/lib/diameter/test/diameter_dist_SUITE.erl
+++ b/lib/diameter/test/diameter_dist_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,16 +25,13 @@
-module(diameter_dist_SUITE).
--export([suite/0,
- all/0]).
+%% all tests, no common_test dependency
+-export([run/0]).
-%% testcases
--export([enslave/1, enslave/0,
- ping/1,
- start/1,
- connect/1,
- send/1,
- stop/1, stop/0]).
+%% common_test wrapping
+-export([suite/0,
+ all/0,
+ traffic/1]).
%% diameter callbacks
-export([peer_up/3,
@@ -46,7 +43,11 @@
handle_error/4,
handle_request/3]).
--export([call/1]).
+%% rpc calls
+-export([start/1,
+ call/1,
+ connect/1,
+ ping/1]).
-include("diameter.hrl").
-include("diameter_gen_base_rfc6733.hrl").
@@ -95,26 +96,35 @@
{server2, ?SERVER},
{client, ?CLIENT}]).
-%% Options to ct_slave:start/2.
--define(TIMEOUTS, [{T, 15000} || T <- [boot_timeout,
- init_timeout,
- start_timeout]]).
-
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [enslave,
- ping,
- start,
- connect,
- send,
- stop].
+ [traffic].
+
+traffic(_Config) ->
+ run().
%% ===========================================================================
-%% start/stop testcases
+
+%% run/0
+
+run() ->
+ [] = ?util:run([{fun traffic/0, 60000}]).
+ %% process for linked peers to die with
+
+%% traffic/0
+
+traffic() ->
+ true = is_alive(), %% need distribution for peer nodes
+ Nodes = enslave(),
+ [] = ping(lists:droplast(Nodes)), %% drop client node
+ [] = start(Nodes),
+ ok = connect(Nodes),
+ ok = send(Nodes).
%% enslave/1
%%
@@ -122,39 +132,29 @@ all() ->
%% one to implement a client.
enslave() ->
- [{timetrap, {seconds, 30*length(?NODES)}}].
-
-enslave(Config) ->
Here = filename:dirname(code:which(?MODULE)),
Ebin = filename:join([Here, "..", "ebin"]),
- Dirs = [Here, Ebin],
- Nodes = [{N,S} || {M,S} <- ?NODES, N <- [slave(M, Dirs)]],
- ?util:write_priv(Config, nodes, [{N,S} || {{N,ok},S} <- Nodes]),
- [] = [{T,S} || {{_,E} = T, S} <- Nodes, E /= ok].
-
-slave(Name, Dirs) ->
- add_pathsa(Dirs, ct_slave:start(Name, ?TIMEOUTS)).
+ Args = ["-pa", Here, Ebin],
+ [{N,S} || {M,S} <- ?NODES, N <- [start(M, Args)]].
-add_pathsa(Dirs, {ok, Node}) ->
- {Node, rpc:call(Node, code, add_pathsa, [Dirs])};
-add_pathsa(_, No) ->
- {No, error}.
+start(Name, Args) ->
+ {ok, _, Node} = ?util:peer(#{name => Name, args => Args}),
+ Node.
%% ping/1
%%
%% Ensure the server nodes are connected so that diameter_dist can attach.
ping({S, Nodes}) ->
- ?SERVER = S,
+ ?SERVER = S, %% assert
[N || {N,_} <- Nodes,
node() /= N,
pang <- [net_adm:ping(N)]];
-ping(Config) ->
- Nodes = lists:droplast(?util:read_priv(Config, nodes)),
- [] = [{N,RC} || {N,S} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, ping, [{S,Nodes}])],
- RC /= []].
+ping(Nodes) ->
+ [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, ping, [{S,Nodes}])],
+ RC /= []].
%% start/1
%%
@@ -168,7 +168,7 @@ ping(Config) ->
%% which case the application needs to be started and diameter_dist is
%% started as a part of this, but only start the server here to ensure
%% everything still works as expected.
-start({_SvcName, [_, {S1, _}, {S2, _}, _]})
+start({_SvcName, [_, {S1, _}, {S2, _}, _]})
when node() == S1; %% server1
node() == S2 -> %% server2
Mod = diameter_dist,
@@ -181,12 +181,10 @@ start({SvcName, [{S0, _}, _, _, {C, _}]})
ok = diameter:start(),
ok = diameter:start_service(SvcName, ?SERVICE((?L(SvcName))));
-start(Config)
- when is_list(Config) ->
- Nodes = ?util:read_priv(Config, nodes),
- [] = [{N,RC} || {N,S} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, start, [{S, Nodes}])],
- RC /= ok].
+start(Nodes) ->
+ [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, start, [{S, Nodes}])],
+ RC /= ok].
sequence() ->
sequence(sname()).
@@ -211,33 +209,24 @@ origin(Server) ->
%% Establish one connection from the client, terminated on the first
%% server node, the others handling requests.
-connect({?SERVER, Config, [{Node, _} | _]})
+connect({?SERVER, [{Node, _} | _], []})
when Node == node() -> %% server0
- ok = ?util:write_priv(Config, lref, {Node, ?util:listen(?SERVER, tcp)});
+ [_LRef = ?util:listen(?SERVER, tcp)];
-connect({?SERVER, _Config, _}) -> %% server[12]: register to receive requests
- ok = diameter_dist:attach([?SERVER]);
+connect({?SERVER, _, [_] = Acc}) -> %% server[12]: register to receive requests
+ ok = diameter_dist:attach([?SERVER]),
+ Acc;
-connect({?CLIENT, Config, _}) ->
- ?util:connect(?CLIENT, tcp, ?util:read_priv(Config, lref)),
+connect({?CLIENT, [{Node, _} | _], [LRef]}) ->
+ ?util:connect(?CLIENT, tcp, {Node, LRef}),
ok;
-connect(Config) ->
- Nodes = ?util:read_priv(Config, nodes),
- [] = [{N,RC} || {N,S} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, connect, [{S, Config, Nodes}])],
- RC /= ok].
-
-%% stop/1
-%%
-%% Stop the slave nodes.
-
-stop() ->
- [{timetrap, {seconds, 30*length(?NODES)}}].
-
-stop(_Config) ->
- [] = [{N,E} || {N,_} <- ?NODES,
- {error, _, _} = E <- [ct_slave:stop(N)]].
+connect(Nodes) ->
+ lists:foldl(fun({N,S}, A) ->
+ rpc:call(N, ?MODULE, connect, [{S, Nodes, A}])
+ end,
+ [],
+ Nodes).
%% ===========================================================================
%% traffic testcases
@@ -247,13 +236,13 @@ stop(_Config) ->
%% Send 100 requests and ensure the node name sent as User-Name isn't
%% the node terminating transport.
-send(Config) ->
- send(Config, 100, dict:new()).
+send(Nodes) ->
+ send(Nodes, 100, dict:new()).
%% send/2
-send(Config, 0, Dict) ->
- [{Server0, _} | _] = ?util:read_priv(Config, nodes) ,
+send(Nodes, 0, Dict) ->
+ [{Server0, _} | _] = Nodes,
Node = atom_to_binary(Server0, utf8),
{false, _} = {dict:is_key(Node, Dict), dict:to_list(Dict)},
%% Check that counters have been incremented as expected on server0.
@@ -266,14 +255,15 @@ send(Config, 0, Dict) ->
Stats},
{[{send, 0, 100, 2001}], _}
= {[{D,R,N,C} || {{{0,275,R}, D, {'Result-Code', C}}, N} <- Stats],
- Stats};
+ Stats},
+ ok;
-send(Config, N, Dict) ->
+send(Nodes, N, Dict) ->
#diameter_base_STA{'Result-Code' = ?SUCCESS,
'User-Name' = [ServerNode]}
- = send(Config, str(?LOGOUT)),
+ = send(Nodes, str(?LOGOUT)),
true = is_binary(ServerNode),
- send(Config, N-1, dict:update_counter(ServerNode, 1, Dict)).
+ send(Nodes, N-1, dict:update_counter(ServerNode, 1, Dict)).
%% ===========================================================================
@@ -284,8 +274,8 @@ str(Cause) ->
%% send/2
-send(Config, Req) ->
- {Node, _} = lists:last(?util:read_priv(Config, nodes)),
+send(Nodes, Req) ->
+ {Node, _} = lists:last(Nodes),
rpc:call(Node, ?MODULE, call, [Req]).
%% call/1
diff --git a/lib/diameter/test/diameter_distribution_SUITE.erl b/lib/diameter/test/diameter_distribution_SUITE.erl
index 5fe02284ae..013c42496e 100644
--- a/lib/diameter/test/diameter_distribution_SUITE.erl
+++ b/lib/diameter/test/diameter_distribution_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,19 +25,19 @@
-module(diameter_distribution_SUITE).
+%% testcases, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
- all/0]).
+ all/0,
+ traffic/1]).
-%% testcases
--export([enslave/1, enslave/0,
- ping/1,
+%% rpc calls
+-export([ping/1,
start/1,
connect/1,
- send_local/1,
- send_remote/1,
- send_timeout/1,
- send_failover/1,
- stop/1, stop/0]).
+ call/1]).
%% diameter callbacks
-export([peer_up/3,
@@ -49,8 +49,6 @@
handle_error/5,
handle_request/3]).
--export([call/1]).
-
-include("diameter.hrl").
-include("diameter_gen_base_rfc6733.hrl").
@@ -99,53 +97,47 @@
{client1, ?CLIENT},
{client2, ?CLIENT}]).
-%% Options to ct_slave:start/2.
--define(TIMEOUTS, [{T, 15000} || T <- [boot_timeout,
- init_timeout,
- start_timeout]]).
-
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [enslave,
- ping,
- start,
- connect,
- send_local,
- send_remote,
- send_timeout,
- send_failover,
- stop].
+ [traffic].
+
+traffic(_Config) ->
+ traffic().
%% ===========================================================================
-%% start/stop testcases
-%% enslave/1
+run() ->
+ [] = ?util:run([{fun traffic/0, 60000}]).
+ %% process for linked peers to die with
+
+%% traffic/0
+
+traffic() ->
+ true = is_alive(), %% need distribution for peer nodes
+ Nodes = enslave(),
+ [] = ping(Nodes), %% drop client node
+ [] = start(Nodes),
+ [_] = connect(Nodes),
+ [] = send(Nodes).
+
+%% enslave/0
%%
%% Start four slave nodes, one to implement a Diameter server,
%% three to implement a client.
enslave() ->
- [{timetrap, {seconds, 30*length(?NODES)}}].
-
-enslave(Config) ->
Here = filename:dirname(code:which(?MODULE)),
Ebin = filename:join([Here, "..", "ebin"]),
- Dirs = [Here, Ebin],
- Nodes = [{N,S} || {M,S} <- ?NODES, N <- [slave(M, Dirs)]],
- ?util:write_priv(Config, nodes, [{N,S} || {{N,ok},S} <- Nodes]),
- [] = [{T,S} || {{_,E} = T, S} <- Nodes, E /= ok].
-
-slave(Name, Dirs) ->
- add_pathsa(Dirs, ct_slave:start(Name, ?TIMEOUTS)).
+ Args = ["-pa", Here, Ebin],
+ [{N,S} || {M,S} <- ?NODES, N <- [start(M, Args)]].
-add_pathsa(Dirs, {ok, Node}) ->
- {Node, rpc:call(Node, code, add_pathsa, [Dirs])};
-add_pathsa(_, No) ->
- {No, error}.
+start(Name, Args) ->
+ {ok, _, Node} = ?util:peer(#{name => Name, args => Args}),
+ Node.
%% ping/1
%%
@@ -160,11 +152,10 @@ ping({?CLIENT, Nodes}) ->
node() /= N,
pang <- [net_adm:ping(N)]];
-ping(Config) ->
- Nodes = ?util:read_priv(Config, nodes),
- [] = [{N,RC} || {N,S} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, ping, [{S, Nodes}])],
- RC /= []].
+ping(Nodes) ->
+ [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, ping, [{S, Nodes}])],
+ RC /= []].
%% start/1
%%
@@ -175,11 +166,10 @@ start(SvcName)
ok = diameter:start(),
ok = diameter:start_service(SvcName, ?SERVICE((?L(SvcName))));
-start(Config) ->
- Nodes = ?util:read_priv(Config, nodes),
- [] = [{N,RC} || {N,S} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, start, [S])],
- RC /= ok].
+start(Nodes) ->
+ [{N,RC} || {N,S} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, start, [S])],
+ RC /= ok].
sequence() ->
sequence(sname()).
@@ -212,66 +202,50 @@ peers(client2) -> nodes().
%% Establish one connection to the server from each of the client
%% nodes.
-connect({?SERVER, Config}) ->
- ?util:write_priv(Config, lref, {node(), ?util:listen(?SERVER, tcp)}),
- ok;
+connect({?SERVER, _, []}) ->
+ [_LRef = ?util:listen(?SERVER, tcp)];
-connect({?CLIENT, Config}) ->
- ?util:connect(?CLIENT, tcp, ?util:read_priv(Config, lref)),
- ok;
+connect({?CLIENT, [{Node, _} | _], [LRef] = Acc}) ->
+ ?util:connect(?CLIENT, tcp, {Node, LRef}),
+ Acc;
-connect(Config) ->
- Nodes = ?util:read_priv(Config, nodes),
- [] = [{N,RC} || {N,S} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, connect, [{S,Config}])],
- RC /= ok].
+connect(Nodes) ->
+ lists:foldl(fun({N,S}, A) ->
+ rpc:call(N, ?MODULE, connect, [{S, Nodes, A}])
+ end,
+ [],
+ Nodes).
-%% stop/1
-%%
-%% Stop the slave nodes.
+%% ===========================================================================
-stop() ->
- [{timetrap, {seconds, 30*length(?NODES)}}].
+%% send/1
-stop(_Config) ->
- [] = [{N,E} || {N,_} <- ?NODES,
- {error, _, _} = E <- [ct_slave:stop(N)]].
+send(Nodes) ->
+ ?util:run([[fun send/2, Nodes, T]
+ || T <- [local, remote, timeout, failover]]).
-%% ===========================================================================
-%% traffic testcases
+%% send/2
-%% send_local/1
-%%
%% Send a request from the first client node, using a the local
%% transport.
-
-send_local(Config) ->
+send(Nodes, local) ->
#diameter_base_STA{'Result-Code' = ?SUCCESS}
- = send(Config, local, str(?LOGOUT)).
+ = send(Nodes, 0, str(?LOGOUT));
-%% send_remote/1
-%%
%% Send a request from the first client node, using a transport on the
%% another node.
-
-send_remote(Config) ->
+send(Nodes, remote) ->
#diameter_base_STA{'Result-Code' = ?SUCCESS}
- = send(Config, remote, str(?LOGOUT)).
+ = send(Nodes, 1, str(?LOGOUT));
-%% send_timeout/1
-%%
%% Send a request that the server discards.
+send(Nodes, timeout) ->
+ {error, timeout} = send(Nodes, 1, str(?TIMEOUT));
-send_timeout(Config) ->
- {error, timeout} = send(Config, remote, str(?TIMEOUT)).
-
-%% send_failover/1
-%%
-%% Send a request that causes the server to remote transports down.
-
-send_failover(Config) ->
+%% Send a request that causes the server to take the transport down.
+send(Nodes, failover) ->
#'diameter_base_answer-message'{'Result-Code' = ?BUSY}
- = send(Config, remote, str(?MOVED)).
+ = send(Nodes, 2, str(?MOVED)).
%% ===========================================================================
@@ -280,10 +254,9 @@ str(Cause) ->
'Auth-Application-Id' = ?DICT:id(),
'Termination-Cause' = Cause}.
-%% send/2
+%% send/3
-send(Config, Where, Req) ->
- [_, {Node, _} | _] = ?util:read_priv(Config, nodes) ,
+send([_, {Node, _} | _], Where, Req) ->
rpc:call(Node, ?MODULE, call, [{Where, Req}]).
%% call/1
@@ -311,14 +284,22 @@ peer_down(_SvcName, _Peer, State) ->
%% pick_peer/4
-pick_peer([LP], [_, _], ?CLIENT, _State, {local, client0}) ->
+pick_peer([LP], _, ?CLIENT, _State, {0, client0}) ->
{ok, LP};
-pick_peer([_], [RP | _], ?CLIENT, _State, {remote, client0}) ->
+pick_peer(_, Peers, ?CLIENT, _State, {1, client0}) ->
+ [RP] = [T || {_, #diameter_caps{origin_state_id = {[1],_}}} = T <- Peers],
{ok, RP};
-pick_peer([LP], [], ?CLIENT, _State, {remote, client0}) ->
- {ok, LP}.
+%% Sending on the remote transport causes the server to take the
+%% transport down. Retransmission on the local.
+pick_peer(LP, RP, ?CLIENT, _State, {2, client0}) ->
+ {ok, case [T || {_, #diameter_caps{origin_state_id = {[2],_}}} = T <- RP] of
+ [T] ->
+ T;
+ _ ->
+ hd([_] = LP)
+ end}.
%% prepare_request/4
diff --git a/lib/diameter/test/diameter_dpr_SUITE.erl b/lib/diameter/test/diameter_dpr_SUITE.erl
index 779b919d3c..45f4ec9b5a 100644
--- a/lib/diameter/test/diameter_dpr_SUITE.erl
+++ b/lib/diameter/test/diameter_dpr_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,22 +24,26 @@
-module(diameter_dpr_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_group/2,
- end_per_group/2]).
-
-%% testcases
--export([start/1,
- connect/1,
+ client/1,
+ server/1,
+ uncommon/1,
+ transport/1,
+ service/1,
+ application/1]).
+
+%% internal
+-export([connect/1,
send_dpr/1,
remove_transport/1,
stop_service/1,
- check/1,
- stop/1]).
+ check/1]).
%% disconnect_cb
-export([disconnect/5]).
@@ -84,42 +88,54 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 30}}].
all() ->
- [{group, R} || R <- [client, server, uncommon | ?REASONS]].
+ [client, server, uncommon, transport, service, application].
-%% The group determines how transports are terminated: by remove_transport,
-%% stop_service or application stop.
-groups() ->
- [{R, [], [start, send_dpr, stop]} || R <- [client, server, uncommon]]
- ++ [{R, [], Ts} || Ts <- [tc()], R <- ?REASONS].
+-define(tc(Name), Name(_) -> run([Name])).
-init_per_suite(Config) -> %% not need, but a useful place to enable trace
- Config.
+?tc(client).
+?tc(server).
+?tc(uncommon).
+?tc(transport).
+?tc(service).
+?tc(application).
-end_per_suite(_Config) ->
- ok.
+%% ===========================================================================
-init_per_group(Name, Config) ->
- [{group, Name} | Config].
+%% run/0
-end_per_group(_, _) ->
- ok.
+run() ->
+ run(all()).
-tc() ->
- [start, connect, remove_transport, stop_service, check, stop].
+%% run/1
-%% ===========================================================================
+run(List)
+ when is_list(List) ->
+ try
+ ?util:run([[{[fun run/1, T], 15000} || T <- List]])
+ after
+ diameter:stop()
+ end;
-%% start/1
-
-start(Config)
- when is_list(Config) ->
- Grp = group(Config),
+run(Grp) ->
ok = diameter:start(),
ok = diameter:start_service(?SERVER, service(?SERVER, Grp)),
- ok = diameter:start_service(?CLIENT, service(?CLIENT, Grp)).
+ ok = diameter:start_service(?CLIENT, service(?CLIENT, Grp)),
+ _ = lists:foldl(fun(F,A) -> apply(?MODULE, F, [A]) end,
+ [{group, Grp}],
+ tc(Grp)),
+ ok = diameter:stop().
+
+tc(T)
+ when T == client;
+ T == server;
+ T == uncommon ->
+ [send_dpr];
+
+tc(_) ->
+ [connect, remove_transport, stop_service, check].
service(?SERVER = Svc, _) ->
?SERVICE(Svc)
@@ -192,26 +208,30 @@ sender(_) ->
%% connect/1
connect(Config) ->
- Pid = spawn(fun init/0), %% process for disconnect_cb to bang
+ Self = self(),
Grp = group(Config),
+ Pid = spawn(fun() -> init(Self) end), %% process for disconnect_cb to bang
LRef = ?util:listen(?SERVER, tcp),
Refs = [?util:connect(?CLIENT, tcp, LRef, opts(RCs, {Grp, Pid}))
|| RCs <- ?RETURNS],
- ?util:write_priv(Config, config, [Pid | Refs]).
+ Pid ! (Grp == application orelse length(Refs)),
+ [{config, [Pid | Refs]} | Config].
%% remove_transport/1
%% Remove all the client transports only in the transport group.
remove_transport(Config) ->
transport == group(Config)
- andalso (ok = diameter:remove_transport(?CLIENT, true)).
+ andalso (ok = diameter:remove_transport(?CLIENT, true)),
+ Config.
%% stop_service/1
%% Stop the service only in the service group.
stop_service(Config) ->
service == group(Config)
- andalso (ok = diameter:stop_service(?CLIENT)).
+ andalso (ok = diameter:stop_service(?CLIENT)),
+ Config.
%% check/1
@@ -219,16 +239,11 @@ stop_service(Config) ->
%% for the timing reason explained below.
check(Config) ->
Grp = group(Config),
- [Pid | Refs] = ?util:read_priv(Config, config),
+ [Pid | Refs] = proplists:get_value(config, Config),
Pid ! self(), %% ask for dictionary
Dict = receive {Pid, D} -> D end, %% get it
check(Refs, ?RETURNS, Grp, Dict). %% check for callbacks
-%% stop/1
-
-stop(_Config) ->
- ok = diameter:stop().
-
%% ===========================================================================
%% Whether or not there are callbacks after diameter:stop() depends on
@@ -258,8 +273,7 @@ check1(Ref, [], _, Dict) ->
%% ----------------------------------------
group(Config) ->
- {group, Grp} = lists:keyfind(group, 1, Config),
- Grp.
+ proplists:get_value(group, Config).
%% Configure the callback with the group name (= disconnect reason) as
%% extra argument.
@@ -274,13 +288,18 @@ disconnect(Reason, Ref, Peer, {Reason, Pid}, RC) ->
Pid ! {Reason, Ref},
RC.
-init() ->
- exit(recv(dict:new())).
+init(Pid) ->
+ monitor(process, Pid),
+ exit(recv(receive T -> T end, dict:new())).
-recv(Dict) ->
+recv(true, Dict) ->
+ recv(0, Dict);
+recv(N, Dict) ->
receive
- Pid when is_pid(Pid) ->
+ Pid when N == 0, is_pid(Pid) ->
Pid ! {self(), Dict};
{Reason, Ref} ->
- recv(dict:store(Ref, Reason, Dict))
+ recv(N - 1, dict:store(Ref, Reason, Dict));
+ {'DOWN', _, process, _, _} ->
+ ok
end.
diff --git a/lib/diameter/test/diameter_event_SUITE.erl b/lib/diameter/test/diameter_event_SUITE.erl
index 6d1d1dfd8f..f4cb5e6d79 100644
--- a/lib/diameter/test/diameter_event_SUITE.erl
+++ b/lib/diameter/test/diameter_event_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,20 +26,18 @@
-module(diameter_event_SUITE).
+%% testcase, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_testcase/2,
- end_per_testcase/2]).
-
-%% testcases
--export([start/1,
- start_server/1,
- up/1,
+ traffic/1]).
+
+%% internal
+-export([up/1,
down/1,
- cea_timeout/1,
- stop/1]).
+ cea_timeout/1]).
-include("diameter.hrl").
@@ -77,43 +75,44 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [start,
- start_server,
- up,
- down,
- cea_timeout,
- stop].
-
-%% Not used, but a convenient place to enable trace.
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
+ [traffic].
-init_per_testcase(Name, Config) ->
- [{name, Name} | Config].
-
-end_per_testcase(_, _) ->
- ok.
+traffic(_Config) ->
+ run().
%% ===========================================================================
-%% start/stop testcases
-start(_Config) ->
- ok = diameter:start().
+%% run/0
-start_server(Config) ->
+run() ->
+ ok = diameter:start(),
+ try
+ ?util:run([{fun traffic/0, 60000}])
+ after
+ ok = diameter:stop()
+ end.
+
+%% traffic/0
+
+traffic() ->
+ PortNr = start_server(),
+ Config = [{portnr, PortNr}],
+ Funs = [up, down, cea_timeout],
+ ?util:run([[{?MODULE, F, [[{name, F} | Config]]} || F <- Funs]]).
+
+%% start_server/0
+
+start_server() ->
diameter:subscribe(?SERVER),
ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER, [?DICT_COMMON])),
LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx_cb/2},
{capx_timeout, ?SERVER_CAPX_TMO}]),
[PortNr] = ?util:lport(tcp, LRef),
- ?util:write_priv(Config, portnr, PortNr),
- start = event(?SERVER).
+ start = event(?SERVER),
+ PortNr.
%% Connect with matching capabilities and expect the connection to
%% come up.
@@ -158,9 +157,6 @@ cea_timeout(Config) ->
start = event(Svc),
{{closed, Ref, {'CEA', timeout}, T}, _} = {event(Svc), T}.
-stop(_Config) ->
- ok = diameter:stop().
-
%% ----------------------------------------
%% Keep the server from sending CEA until the client has timed out.
@@ -201,7 +197,7 @@ start_service(Name, Opts) ->
diameter:start_service(Name, [{monitor, self()} | Opts]).
opts(Config, Opts) ->
- PortNr = ?util:read_priv(Config, portnr),
+ PortNr = proplists:get_value(portnr, Config),
{connect, [{transport_module, diameter_tcp},
{transport_config, [{ip, ?ADDR}, {port, 0},
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
index 7d47efd527..7bb39cace3 100644
--- a/lib/diameter/test/diameter_examples_SUITE.erl
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,25 +24,20 @@
-module(diameter_examples_SUITE).
+%% testcase, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_group/2,
- end_per_group/2]).
-
-%% testcases
--export([dict/1, dict/0,
- code/1,
- slave/1, slave/0,
- enslave/1,
- start/1,
- traffic/1,
- stop/1]).
+ dict/1,
+ code/1]).
+%% rpc calls
-export([install/1,
- call/1]).
+ start/1,
+ traffic/1]).
-include("diameter.hrl").
@@ -54,11 +49,6 @@
%% before the clients connect.
-define(NODES, [server, client]).
-%% Options to ct_slave:start/2.
--define(TIMEOUTS, [{T, 15000} || T <- [boot_timeout,
- init_timeout,
- start_timeout]]).
-
%% @inherits dependencies between example dictionaries. This is needed
%% in order compile them in the right order. Can't compile to erl to
%% find out since @inherits is a beam dependency.
@@ -70,68 +60,74 @@
-define(DICT0, [rfc3588_base, rfc6733_base]).
%% Transport protocols over which the example Diameter nodes are run.
--define(PROTS, [tcp, sctp]).
+-define(PROTS, [sctp || ?util:have_sctp()] ++ [tcp]).
+
+-define(L, atom_to_list).
+-define(A, list_to_atom).
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {minutes, 2}}].
+ [{timetrap, {seconds, 75}}].
all() ->
- [dict,
- code,
- {group, all}].
-
-groups() ->
- Tc = tc(),
- [{all, [parallel], [{group, P} || P <- ?PROTS]}
- | [{P, [], Tc} || P <- ?PROTS]].
-
-%% Not used, but a convenient place to enable trace.
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(all, Config) ->
- Config;
-
-init_per_group(tcp = N, Config) ->
- [{group, N} | Config];
-
-init_per_group(sctp = N, Config) ->
- case ?util:have_sctp() of
- true ->
- [{group, N} | Config];
- false->
- {skip, no_sctp}
+ [dict, code].
+
+dict(Config) ->
+ run(dict, Config).
+
+code(Config) ->
+ run(code, Config).
+
+%% ===========================================================================
+
+%% run/0
+
+run() ->
+ run(all()).
+
+%% run/1
+
+run({dict, Dir}) ->
+ compile_dicts(Dir);
+%% The example code doesn't use the example dictionaries, so a
+%% separate testcase.
+
+run({code, Dir}) ->
+ run_code(Dir);
+
+run(List)
+ when is_list(List) ->
+ Tmp = ?util:mktemp("diameter_examples"),
+ try
+ run(List, Tmp)
+ after
+ file:del_dir_r(Tmp)
end.
-end_per_group(_, _) ->
- ok.
+%% run/2
-tc() ->
- [slave,
- enslave,
- start,
- traffic,
- stop].
+%% Eg. erl -noinput -s diameter_examples_SUITE run code -s init stop ...
+run(List, Dir)
+ when is_list(List) ->
+ ?util:run([{[fun run/1, {F, Dir}], 60000} || F <- List]);
+
+run(F, Config) ->
+ run([F], proplists:get_value(priv_dir, Config)).
%% ===========================================================================
-%% dict/1
+%% compile_dicts/1
%%
%% Compile example dictionaries in examples/dict.
-dict() ->
- [{timetrap, {minutes, 10}}].
-
-dict(_Config) ->
+compile_dicts(Dir) ->
+ Out = mkdir(Dir, "dict"),
Dirs = [filename:join(H ++ ["examples", "dict"])
|| H <- [[code:lib_dir(diameter)], [here(), ".."]]],
[] = [{F,D,RC} || {_,F} <- sort(find_files(Dirs, ".*\\.dia$")),
D <- ?DICT0,
- RC <- [make(F,D)],
+ RC <- [make(F, D, Out)],
RC /= ok].
sort([{_,_} | _] = Files) ->
@@ -162,11 +158,11 @@ dep([{Dict, _} | T], Rest, Acc) ->
dep([], Rest, Acc) ->
dep(Rest, Acc).
-make(Path, Dict0)
+make(Path, Dict0, Out)
when is_atom(Dict0) ->
- make(Path, atom_to_list(Dict0));
+ make(Path, atom_to_list(Dict0), Out);
-make(Path, Dict0) ->
+make(Path, Dict0, Out) ->
Dict = filename:rootname(filename:basename(Path)),
{Mod, Pre} = make_name(Dict),
{"diameter_gen_base" ++ Suf = Mod0, _} = make_name(Dict0),
@@ -174,10 +170,11 @@ make(Path, Dict0) ->
try
ok = to_erl(Path, [{name, Name},
{prefix, Pre},
+ {outdir, Out},
{inherits, "common/" ++ Mod0}
| [{inherits, D ++ "/" ++ M ++ Suf}
|| {D,M} <- dep(Dict)]]),
- ok = to_beam(Name)
+ ok = to_beam(filename:join(Out, Name))
catch
throw: {_,_} = E ->
E
@@ -220,28 +217,35 @@ make_name(Dict) ->
{string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}.
%% ===========================================================================
-%% code/1
+%% compile_code/1
%%
%% Compile example code under examples/code.
-code(Config) ->
+compile_code(Tmpdir) ->
+ {ok, Pid, Node} = slave(peer:random_name(), here()),
try
- [] = rpc:call(slave(compile, here()),
- ?MODULE,
- install,
- [proplists:get_value(priv_dir, Config)])
+ {ok, _Ebin} = rpc:call(Node, ?MODULE, install, [Tmpdir])
after
- {ok, _} = ct_slave:stop(compile)
+ peer:stop(Pid)
end.
-%% Compile on another node since the code path may be modified.
-install(PrivDir) ->
- Top = install(here(), PrivDir),
+%% Compile in another node since the code path is modified.
+install(Tmpdir) ->
+ {Top, Dia, Ebin} = install(here(), Tmpdir),
+
+ %% Prepend the created directory just so that code:lib_dir/1 finds
+ %% it when compile:file/2 tries to resolve include_lib.
+ true = code:add_patha(Ebin),
+ Dia = code:lib_dir(diameter), %% assert
+
Src = filename:join([Top, "examples", "code"]),
Files = find_files([Src], ".*\\.erl$"),
- [] = [{F,E} || {_,F} <- Files,
- {error, _, _} = E <- [compile:file(F, [warnings_as_errors,
- return_errors])]].
+ [] = [{F,T} || {_,F} <- Files,
+ T <- [compile:file(F, [warnings_as_errors,
+ return_errors,
+ {outdir, Ebin}])],
+ ok /= element(1, T)],
+ {ok, Ebin}.
%% Copy include files into a temporary directory and adjust the code
%% path in order for example code to be able to include them with
@@ -251,20 +255,15 @@ install(PrivDir) ->
%% preprocessor to find these otherwise. Generated hrls are only be
%% under include in an installation. ("Installing" them locally is
%% anathema.)
-install(Dir, PrivDir) ->
- %% Remove the path added by slave/1 (needed for the rpc:call/4 in
- %% compile/1 to find ?MODULE) so the call to code:lib_dir/2 below
- %% returns the installed path.
- [Ebin | _] = code:get_path(),
- true = code:del_path(Ebin),
+install(Dir, Tmpdir) ->
Top = top(Dir, code:lib_dir(diameter)),
%% Create a new diameter/include in priv_dir. Copy all includes
%% there, from below ../include and ../src/gen if they exist (in
%% the repo).
- Tmp = filename:join([PrivDir, "diameter"]),
- TmpInc = filename:join([PrivDir, "diameter", "include"]),
- TmpEbin = filename:join([PrivDir, "diameter", "ebin"]),
+ Tmp = filename:join([Tmpdir, "diameter"]),
+ TmpInc = filename:join([Tmp, "include"]),
+ TmpEbin = filename:join([Tmp, "ebin"]),
[] = [{T,E} || T <- [Tmp, TmpInc, TmpEbin],
{error, E} <- [file:make_dir(T)]],
@@ -275,13 +274,7 @@ install(Dir, PrivDir) ->
B <- [filename:basename(F)],
D <- [filename:join([TmpInc, B])],
{error, E} <- [file:copy(F,D)]],
-
- %% Prepend the created directory just so that code:lib_dir/1 finds
- %% it when compile:file/2 tries to resolve include_lib.
- true = code:add_patha(TmpEbin),
- Tmp = code:lib_dir(diameter), %% assert
- %% Return the top directory containing examples/code.
- Top.
+ {Top, Tmp, TmpEbin}.
find_files(Dirs, RE) ->
lists:foldl(fun(D,A) -> fold_files(D, RE, A) end,
@@ -296,49 +289,19 @@ store(Path, Dict) ->
%% ===========================================================================
-%% slave/1
-%%
-%% Return how long slave start/stop is taking since it seems to be
-%% ridiculously long on some hosts.
-
-slave() ->
- [{timetrap, {minutes, 10}}].
-
-slave(_) ->
- T0 = diameter_lib:now(),
- {ok, Node} = ct_slave:start(?MODULE, ?TIMEOUTS),
- T1 = diameter_lib:now(),
- T2 = rpc:call(Node, diameter_lib, now, []),
- {ok, Node} = ct_slave:stop(?MODULE),
- now_diff([T0, T1, T2, diameter_lib:now()]).
-
-now_diff([T1,T2|_] = Ts) ->
- [diameter_lib:micro_diff(T2,T1) | now_diff(tl(Ts))];
-now_diff(_) ->
- [].
-
-%% ===========================================================================
-
%% enslave/1
%%
%% Start two nodes: one for the server, one for the client.
-enslave(Config) ->
- Prot = proplists:get_value(group, Config),
- Dir = here(),
- Nodes = [{S, slave(N, Dir)} || S <- ?NODES, N <- [concat(Prot, S)]],
- ?util:write_priv(Config, Prot, Nodes).
+enslave(Prefix) ->
+ [{S,N} || D <- [here()],
+ S <- ?NODES,
+ M <- [lists:append(["diameter", Prefix, ?L(S)])],
+ {ok, _, N} <- [slave(M,D)]].
slave(Name, Dir) ->
- {ok, Node} = ct_slave:start(Name, ?TIMEOUTS),
- ok = rpc:call(Node,
- code,
- add_pathsa,
- [[Dir, filename:join([Dir, "..", "ebin"])]]),
- Node.
-
-concat(Prot, Svc) ->
- list_to_atom(atom_to_list(Prot) ++ atom_to_list(Svc)).
+ Args = ["-pa", Dir, filename:join([Dir, "..", "ebin"])],
+ {ok, _Pid, _Node} = ?util:peer(#{name => Name, args => Args}).
here() ->
filename:dirname(code:which(?MODULE)).
@@ -350,27 +313,33 @@ top(Dir, LibDir) ->
false -> LibDir
end.
-%% start/1
+%% start/2
-start({server, Prot}) ->
+start({server, Prot, Ebin}) ->
+ true = code:add_patha(Ebin),
ok = diameter:start(),
ok = server:start(),
{ok, Ref} = server:listen({Prot, any, 3868}),
[_] = ?util:lport(Prot, Ref),
ok;
-start({client = Svc, Prot}) ->
+start({client = Svc, Prot, Ebin}) ->
+ true = code:add_patha(Ebin),
ok = diameter:start(),
true = diameter:subscribe(Svc),
ok = client:start(),
{ok, Ref} = client:connect({Prot, loopback, loopback, 3868}),
- receive #diameter_event{info = {up, Ref, _, _, _}} -> ok end;
+ receive
+ #diameter_event{info = {up, Ref, _, _, _}} ->
+ ok
+ after
+ 2000 ->
+ timeout
+ end;
-start(Config) ->
- Prot = proplists:get_value(group, Config),
- Nodes = ?util:read_priv(Config, Prot),
- [] = [RC || {T,N} <- Nodes,
- RC <- [rpc:call(N, ?MODULE, start, [{T, Prot}])],
+start([Prot, Ebin | Nodes]) ->
+ [] = [RC || {S,N} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, start, [{S, Prot, Ebin}])],
RC /= ok].
%% traffic/1
@@ -381,30 +350,35 @@ traffic(server) ->
ok;
traffic(client) ->
- {_, MRef} = spawn_monitor(fun() -> call(100) end),
+ {_, MRef} = spawn_monitor(fun() -> exit(call(100)) end),
receive {'DOWN', MRef, process, _, Reason} -> Reason end;
-traffic(Config) ->
- Prot = proplists:get_value(group, Config),
- Nodes = ?util:read_priv(Config, Prot),
+traffic({Prot, Ebin}) ->
+ Nodes = enslave(?L(Prot)),
+ [] = start([Prot, Ebin | Nodes]),
[] = [RC || {T,N} <- Nodes,
RC <- [rpc:call(N, ?MODULE, traffic, [T])],
RC /= ok].
+%% run_code/1
+
+run_code(Dir) ->
+ true = is_alive(), %% need distribution for peer nodes
+ {ok, Ebin} = compile_code(mkdir(Dir, "code")),
+ ?util:run([[fun traffic/1, {T, Ebin}] || T <- ?PROTS]).
+
+%% call/1
+
call(0) ->
- exit(ok);
+ ok;
call(N) ->
{ok, _} = client:call(),
call(N-1).
-%% stop/1
-
-stop(Name)
- when is_atom(Name) ->
- {ok, _Node} = ct_slave:stop(Name),
- ok;
+%% mkdir/2
-stop(Config) ->
- Prot = proplists:get_value(group, Config),
- [] = [RC || N <- ?NODES, RC <- [catch stop(concat(Prot, N))], RC /= ok].
+mkdir(Top, Dir) ->
+ Tmp = filename:join(Top, Dir),
+ ok = file:make_dir(Tmp),
+ Tmp.
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
index 8a3b3e8413..0c78119e50 100644
--- a/lib/diameter/test/diameter_failover_SUITE.erl
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,20 +36,19 @@
-module(diameter_failover_SUITE).
+%% testcases, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
- all/0]).
-
-%% testcases
--export([start/1,
- start_services/1,
- connect/1,
- send_ok/1,
- send_nok/1,
- send_discard_1/1,
- send_discard_2/1,
- stop_services/1,
- empty/1,
- stop/1]).
+ all/0,
+ parallel/1]).
+
+%% internal
+-export([send_ok/0,
+ send_nok/0,
+ send_discard_1/0,
+ send_discard_2/0]).
%% diameter callbacks
-export([pick_peer/4,
@@ -112,50 +111,61 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [start,
- start_services,
- connect,
- send_ok,
- send_nok,
- send_discard_1,
- send_discard_2,
- stop_services,
- empty,
- stop].
+ [parallel].
+
+parallel(_Config) ->
+ run().
%% ===========================================================================
-%% start/stop testcases
-start(_Config) ->
- ok = diameter:start().
+%% run/0
+
+run() ->
+ ok = diameter:start(),
+ try
+ ?util:run([{fun traffic/0, 60000}])
+ after
+ ok = diameter:stop()
+ end.
+
+%% traffic/0
-start_services(_Config) ->
+traffic() ->
+ Servers = start_services(),
+ ok = connect(Servers),
+ [] = send(),
+ [] = stop_services(),
+ [] = ets:tab2list(diameter_request).
+
+%% start_services/0
+
+start_services() ->
Servers = [server(N) || N <- ?SERVERS],
[] = [T || C <- ?CLIENTS,
T <- [diameter:start_service(C, ?SERVICE(C))],
T /= ok],
+ Servers.
- {save_config, Servers}.
+%% send/0
-connect(Config) ->
- {start_services, Servers} = proplists:get_value(saved_config, Config),
+send() ->
+ Funs = [send_ok, send_nok, send_discard_1, send_discard_2],
+ ?util:run([[{?MODULE, F, []} || F <- Funs]]).
- lists:foreach(fun(C) -> connect(C, Servers) end, ?CLIENTS).
+%% connect/1
-stop_services(_Config) ->
- [] = [{H,T} || H <- ?CLIENTS ++ ?SERVERS,
- T <- [diameter:stop_service(H)],
- T /= ok].
+connect(Servers) ->
+ lists:foreach(fun(C) -> connect(C, Servers) end, ?CLIENTS).
-%% Ensure transports have been removed from request table.
-empty(_Config) ->
- [] = ets:tab2list(diameter_request).
+%% stop_services/0
-stop(_Config) ->
- ok = diameter:stop().
+stop_services() ->
+ [{H,T} || H <- ?CLIENTS ++ ?SERVERS,
+ T <- [diameter:stop_service(H)],
+ T /= ok].
%% ----------------------------------------
@@ -171,7 +181,7 @@ connect(Name, Refs) ->
%% Send an STR and expect success after SERVER3 answers after a couple
%% of failovers.
-send_ok(_Config) ->
+send_ok() ->
Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER1),
'Termination-Cause' = ?LOGOUT,
'Auth-Application-Id' = ?APP_ID},
@@ -180,19 +190,19 @@ send_ok(_Config) ->
= call(?CLIENT1, Req).
%% Send an STR and expect failure when both servers fail.
-send_nok(_Config) ->
+send_nok() ->
Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER4),
'Termination-Cause' = ?LOGOUT,
'Auth-Application-Id' = ?APP_ID},
{failover, ?LOGOUT} = call(?CLIENT1, Req).
%% Send an STR and have prepare_retransmit discard it.
-send_discard_1(_Config) ->
+send_discard_1() ->
Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER1),
'Termination-Cause' = ?TIMEOUT,
'Auth-Application-Id' = ?APP_ID},
{rejected, ?TIMEOUT} = call(?CLIENT2, Req).
-send_discard_2(_Config) ->
+send_discard_2() ->
Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER4),
'Termination-Cause' = ?MOVED,
'Auth-Application-Id' = ?APP_ID},
diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
index ccee6baec1..1333431943 100644
--- a/lib/diameter/test/diameter_gen_sctp_SUITE.erl
+++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,14 +27,19 @@
-module(diameter_gen_sctp_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
init_per_suite/1,
end_per_suite/1]).
%% testcases
--export([send_one_from_many/1, send_one_from_many/0,
- send_many_from_one/1, send_many_from_one/0,
+-export([send_one_from_many/1,
+ send_many_from_one/1,
receive_what_was_sent/1]).
-include_lib("kernel/include/inet_sctp.hrl").
@@ -45,7 +50,7 @@
%% Open sockets on the loopback address.
-define(ADDR, {127,0,0,1}).
-%% An indescribably long number of milliseconds after which everthing
+%% An indescribably long number of milliseconds after which everything
%% that should have happened has.
-define(FOREVER, 2000).
@@ -67,7 +72,7 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 10}}].
+ [{timetrap, {seconds, 15}}].
all() ->
[send_one_from_many,
@@ -89,13 +94,20 @@ end_per_suite(_Config) ->
%% ===========================================================================
-%% send_one_from_many/0
+%% run/0
+
+run() ->
+ run(all()).
+
+%% run/1
+
+run(List) ->
+ diameter_util:run([{{?MODULE, F, [[]]}, 10000} || F <- List]).
+
+%% send_one_from_many/1
%%
%% Demonstrates sluggish delivery of messages.
-send_one_from_many() ->
- [{timetrap, {seconds, 30}}].
-
send_one_from_many(_) ->
?OK = send_multiple(128, 1, 1024).
@@ -402,23 +414,20 @@ unmark(Bin) ->
%% ===========================================================================
-%% send_many_from_one/0
+%% send_many_from_one/1
%%
%% Demonstrates sluggish delivery of messages.
-send_many_from_one() ->
- [{timetrap, {seconds, 30}}].
-
send_many_from_one(_) ->
?OK = send_multiple(1, 128, 1024).
%% ===========================================================================
-%% receive_what_was_sent/1
+%% receive_what_was_sent/0
%%
%% Demonstrates reception of a message that differs from that sent.
-receive_what_was_sent(_Config) ->
+receive_what_was_sent(_) ->
?OK = send_multiple(1, 1, 1024*32).
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_gen_tcp_SUITE.erl b/lib/diameter/test/diameter_gen_tcp_SUITE.erl
index db42ea813e..d1e01da27e 100644
--- a/lib/diameter/test/diameter_gen_tcp_SUITE.erl
+++ b/lib/diameter/test/diameter_gen_tcp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,11 +27,14 @@
-module(diameter_gen_tcp_SUITE).
--export([suite/0,
- all/0]).
+%% testcases, not common_test dependency
+-export([run/0,
+ run/1]).
-%% testcases
--export([send_long/1,
+%% common_test wrapping
+-export([suite/0,
+ all/0,
+ send_long/1,
connect/1]).
-define(LOOPBACK, {127,0,0,1}).
@@ -46,13 +49,29 @@ all() ->
[connect, %% Appears to fail only when run first.
send_long].
+send_long(_) ->
+ send_long().
+
+connect(_) ->
+ connect().
+
%% ===========================================================================
-%% send_long/1
+%% run/0
+
+run() ->
+ run(all()).
+
+%% run/1
+
+run(List) ->
+ diameter_util:run([{{?MODULE, F, [[]]}, 10000} || F <- List]).
+
+%% send_long/0
%%
%% Test that a long message is received.
-send_long(_) ->
+send_long() ->
{Sock, SendF} = connection(),
B = binary:copy(<<$X>>, 1 bsl 20),
ok = SendF(B),
@@ -101,13 +120,13 @@ send(Sock, Bin) ->
%% ===========================================================================
-%% connect/1
+%% connect/0
%%
%% Test that simultaneous connections succeed. This fails sporadically
%% on OS X at the time of writing, when gen_tcp:connect/2 returns
%% {error, econnreset}.
-connect(_) ->
+connect() ->
{ok, LSock} = gen_tcp:listen(0, ?GEN_OPTS),
{ok, {_,PortNr}} = inet:sockname(LSock),
Count = lists:seq(1,8), %% 8 simultaneous connects
diff --git a/lib/diameter/test/diameter_gh.spec b/lib/diameter/test/diameter_gh.spec
new file mode 100644
index 0000000000..9662044402
--- /dev/null
+++ b/lib/diameter/test/diameter_gh.spec
@@ -0,0 +1,2 @@
+{suites, "../diameter_test", all}.
+{skip_suites, "../diameter_test", [diameter_gen_sctp_SUITE], "SCTP does not work on Github actions"}.
diff --git a/lib/diameter/test/diameter_length_SUITE.erl b/lib/diameter/test/diameter_length_SUITE.erl
index daaaae6e00..66d1be114f 100644
--- a/lib/diameter/test/diameter_length_SUITE.erl
+++ b/lib/diameter/test/diameter_length_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,20 +24,14 @@
-module(diameter_length_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
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]).
-
-%% testcases
--export([start/1,
- send/1,
- stop/1]).
+ parallel/1]).
%% diameter callbacks
-export([peer_up/3,
@@ -83,39 +77,20 @@
-define(LOGOUT,
?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
--define(GROUPS, [exit, handle, discard]).
-
-define(L, atom_to_list).
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 120}}].
all() ->
- [{group, G} || G <- ?GROUPS].
-
-groups() ->
- [{G, [], [start, send, stop]} || G <- ?GROUPS].
-
-init_per_suite(Config) ->
- ok = diameter:start(),
- Config.
-
-end_per_suite(_Config) ->
- ok = diameter:stop().
-
-init_per_group(Group, Config) ->
- [{group, Group} | Config].
-
-end_per_group(_, _) ->
- ok.
+ [parallel].
-init_per_testcase(_Name, Config) ->
- Config.
+parallel(_Config) ->
+ run().
-end_per_testcase(_, _) ->
- ok.
+%% ===========================================================================
origin(exit) -> 0;
origin(handle) -> 1;
@@ -127,25 +102,39 @@ origin(2) -> discard.
%% ===========================================================================
+run() ->
+ run([exit, handle, discard]).
+
+run(List)
+ when is_list(List) ->
+ ok = diameter:start(),
+ try
+ ?util:run([[{[fun run/1, T], 30000} || T <- List]])
+ after
+ ok = diameter:stop()
+ end;
+
+run(Group) ->
+ start(Group),
+ send(Group),
+ stop().
+
%% start/1
-start(Config) ->
- Group = proplists:get_value(group, Config),
+start(Group) ->
ok = diameter:start_service(?SERVER, ?SERVICE(?L(Group))),
ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)),
- LRef = ?util:listen(?SERVER,
- tcp,
- [{length_errors, Group}]),
+ LRef = ?util:listen(?SERVER, tcp, [{length_errors, Group}]),
?util:connect(?CLIENT,
tcp,
LRef,
[{capabilities, [{'Origin-State-Id', origin(Group)}]}]).
-%% stop/1
+%% stop/0
-stop(_Config) ->
- ok = diameter:remove_transport(?CLIENT, true),
+stop() ->
ok = diameter:remove_transport(?SERVER, true),
+ ok = diameter:remove_transport(?CLIENT, true),
ok = diameter:stop_service(?SERVER),
ok = diameter:stop_service(?CLIENT).
@@ -194,10 +183,7 @@ send(discard) ->
{error, timeout}
= call(4),
#diameter_base_STA{'Result-Code' = ?SUCCESS}
- = call(0);
-
-send(Config) ->
- send(proplists:get_value(group, Config)).
+ = call(0).
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_pool_SUITE.erl b/lib/diameter/test/diameter_pool_SUITE.erl
index a36a4fa17a..40d34c6237 100644
--- a/lib/diameter/test/diameter_pool_SUITE.erl
+++ b/lib/diameter/test/diameter_pool_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,17 +25,16 @@
-module(diameter_pool_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- init_per_testcase/2,
- end_per_testcase/2,
- init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([tcp_connect/1,
- sctp_connect/1,
- any_connect/1]).
+ tcp/1,
+ sctp/1,
+ any/1]).
%% ===========================================================================
@@ -62,44 +61,53 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 30}}].
+ [{timetrap, {seconds, 45}}].
all() ->
- [tcp_connect,
- sctp_connect,
- any_connect].
+ [tcp, sctp, any].
-init_per_testcase(_Name, Config) ->
- Config.
+tcp(_Config) ->
+ run([tcp]).
-end_per_testcase(_Name, _Config) ->
- diameter:stop().
-
-init_per_suite(Config) ->
- [{sctp, ?util:have_sctp()} | Config].
+sctp(_Config) ->
+ case ?util:have_sctp() of
+ true -> run([sctp]);
+ false -> {skip, no_sctp}
+ end.
-end_per_suite(_Config) ->
- ok.
+any(_Config) ->
+ run([any]).
%% ===========================================================================
-tcp_connect(_Config) ->
- connect(tcp, tcp).
+%% run/0
-sctp_connect(Config) ->
- case lists:member({sctp, true}, Config) of
- true -> connect(sctp, sctp);
- false -> {skip, no_sctp}
- end.
+run() ->
+ run(all()).
+
+%% run/1
+
+run(tcp = T) ->
+ connect(T, T);
-any_connect(_Config) ->
- connect(any, tcp).
+run(sctp = T) ->
+ connect(T, T);
+
+run(any = T) ->
+ connect(T, tcp);
+
+run(List) ->
+ ok = diameter:start(),
+ try
+ ?util:run([[{[fun run/1, T], 30000} || T <- List]])
+ after
+ ok = diameter:stop()
+ end.
%% connect/2
%% Establish multiple connections between a client and server.
connect(ClientProt, ServerProt) ->
- ok = diameter:start(),
[] = [{S,T} || S <- ["server", "client"],
T <- [diameter:start_service(S, ?SERVICE(S))],
T /= ok],
@@ -108,20 +116,24 @@ connect(ClientProt, ServerProt) ->
LRef = ?util:listen("server", ServerProt, [{pool_size, 4}]),
{4,0} = count("server", LRef, accept), %% 4 transports, no connections
%% Establish 5 connections.
- Ref = ?util:connect("client", ClientProt, LRef, [{pool_size, 5}]),
- {5,5} = count("client", Ref, pool), %% 5 connections
+ N = pool_size(5), %% connections to establish
+ Ref = ?util:connect("client", ClientProt, LRef, [{pool_size, N}]),
+ {N,N} = count("client", Ref, pool), %% N connections
%% Ensure the server has started replacement transports within a
%% reasonable time. Sleepsince there's no guarantee the
%% replacements have been started before the client has received
%% 'up' events. (Although it's likely.)
- sleep(),
- {9,5} = count("server", LRef, accept), %% 5 connections + 4 accepting
+ timer:sleep(1000),
+ N4 = N + 4,
+ {N4,N} = count("server", LRef, accept), %% N connections + 4 accepting
%% Ensure there are still the expected number of accepting transports
%% after stopping the client service.
ok = diameter:stop_service("client"),
- sleep(),
+ timer:sleep(1000),
{4,0} = count("server", LRef, accept), %% 4 transports, no connections
%% Done.
+ ok = diameter:remove_transport("client", true),
+ ok = diameter:remove_transport("server", true),
ok = diameter:stop_service("server").
count(Name, Ref, Key) ->
@@ -131,5 +143,10 @@ count(Name, Ref, Key) ->
{Key, Ps} = lists:keyfind(Key, 1, T),
{length(Ps), length(Cs)}. %% number of processes, connections
-sleep() ->
- receive after 1000 -> ok end.
+%% Simultaneous connections are often refused on Darwin: don't try to
+%% establish more than one.
+pool_size(N) ->
+ case os:type() of
+ {_, 'darwin'} -> 1;
+ _ -> rand:uniform(N)
+ end.
diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl
index cd9242faa8..02e10ffb74 100644
--- a/lib/diameter/test/diameter_reg_SUITE.erl
+++ b/lib/diameter/test/diameter_reg_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,86 +24,76 @@
-module(diameter_reg_SUITE).
--export([suite/0,
- all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1]).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
-%% testcases
--export([add/1,
- add_new/1,
- remove/1,
- down/1,
- terms/1,
- pids/1]).
+%% common_test wrapping
+-export([all/0,
+ parallel/1]).
--define(reg, diameter_reg).
--define(util, diameter_util).
+-define(reg, diameter_reg).
%% ===========================================================================
-suite() ->
- [{timetrap, {seconds, 60}}].
-
all() ->
- [{group, all},
- {group, all, [parallel]}].
+ [parallel].
-groups() ->
- [{all, [], tc()}].
+parallel(_Config) ->
+ run().
-tc() ->
- [add,
- add_new,
- remove,
- down,
- terms,
- pids].
+%% ===========================================================================
-init_per_suite(Config) ->
- ok = diameter:start(),
- Config.
+%% run/0
-end_per_suite(_Config) ->
- ok = diameter:stop().
+run() ->
+ run([add, add_new, remove, down, terms, pids]).
-%% ===========================================================================
+%% run/1
+
+run(List)
+ when is_list(List) ->
+ ok = diameter:start(),
+ try
+ diameter_util:run([{[fun run/1, T], 10000} || T <- List])
+ after
+ ok = diameter:stop()
+ end;
-add(_) ->
+run(add) ->
Ref = make_ref(),
true = ?reg:add(Ref),
true = ?reg:add(Ref),
[{Ref, Pid}] = ?reg:match(Ref),
- Pid = self().
+ Pid = self();
-add_new(_) ->
+run(add_new) ->
Ref = make_ref(),
true = ?reg:add_new(Ref),
- false = ?reg:add_new(Ref).
+ false = ?reg:add_new(Ref);
-remove(_) ->
+run(remove) ->
Ref = make_ref(),
true = ?reg:add_new(Ref),
true = ?reg:add_new({Ref}),
true = ?reg:remove({Ref}),
[{Ref, Pid}] = ?reg:match(Ref),
- Pid = self().
+ Pid = self();
-down(_) ->
+run(down) ->
Ref = make_ref(),
{_, MRef} = spawn_monitor(fun() -> ?reg:add_new(Ref), timer:sleep(1000) end),
receive {'DOWN', MRef, process, _, _} -> ok end,
timer:sleep(1000),
- [] = ?reg:match(Ref).
+ [] = ?reg:match(Ref);
-terms(_) ->
+run(terms) ->
Ref = make_ref(),
true = ?reg:add_new(Ref),
[[Pid]] = [L || {T,L} <- ?reg:terms(), T == Ref],
- Pid = self().
+ Pid = self();
-pids(_) ->
+run(pids) ->
Ref = make_ref(),
true = ?reg:add_new(Ref),
%% Don't match [[Ref]] since this will only necessarily be the
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
index 9de5cbe685..2502820e0f 100644
--- a/lib/diameter/test/diameter_relay_SUITE.erl
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,26 +34,13 @@
-module(diameter_relay_SUITE).
+%% testcases, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0]).
-
-%% testcases
--export([start/1,
- start_services/1,
- connect/1,
- send1/1,
- send2/1,
- send3/1,
- send4/1,
- send_loop/1,
- send_timeout_1/1,
- send_timeout_2/1,
- info/1,
- counters/1,
- disconnect/1,
- stop_services/1,
- stop/1]).
+ parallel/1]).
%% diameter callbacks
-export([pick_peer/4,
@@ -115,41 +102,37 @@
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 30}}].
all() ->
- [start,
- start_services,
- connect,
- {group, all},
- counters,
- {group, all, [parallel]},
- disconnect,
- stop_services,
- stop].
-
-groups() ->
- [{all, [], tc()}].
+ [parallel].
-%% Traffic cases run when services are started and connections
-%% established.
-tc() ->
- [send1,
- send2,
- send3,
- send4,
- send_loop,
- send_timeout_1,
- send_timeout_2,
- info].
+parallel(_Config) ->
+ run().
%% ===========================================================================
-%% start/stop testcases
-start(_Config) ->
- ok = diameter:start().
+%% run/0
+
+run() ->
+ ok = diameter:start(),
+ try
+ ?util:run([{fun traffic/0, 20000}])
+ after
+ ok = diameter:stop()
+ end.
-start_services(_Config) ->
+%% traffic/0
+
+traffic() ->
+ Servers = start_services(),
+ Conns = connect(Servers),
+ [] = send(),
+ [] = counters(),
+ [] = disconnect(Conns),
+ [] = stop_services().
+
+start_services() ->
[S1,S2,S3,S4] = [server(N, ?DICT_COMMON) || N <- [?SERVER1,
?SERVER2,
?SERVER3,
@@ -158,30 +141,32 @@ start_services(_Config) ->
ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
- {save_config, [{?RELAY1, [S1,S2,R2]},
- {?RELAY2, [S3,S4]},
- {?CLIENT, [R1,R2]}]}.
-
-connect(Config) ->
- {_, Conns} = proplists:get_value(saved_config, Config),
+ [{?RELAY1, [S1,S2,R2]}, {?RELAY2, [S3,S4]}, {?CLIENT, [R1,R2]}].
- ?util:write_priv(Config,
- "cfg",
- lists:flatmap(fun({CN,Ss}) -> connect(CN, Ss) end,
- Conns)).
+connect(Servers) ->
+ lists:flatmap(fun({CN,Ss}) -> connect(CN, Ss) end, Servers).
-disconnect(Config) ->
- [] = [{T,C} || C <- ?util:read_priv(Config, "cfg"),
- T <- [break(C)],
- T /= ok].
+disconnect(Conns) ->
+ [{T,C} || C <- Conns,
+ T <- [break(C)],
+ T /= ok].
-stop_services(_Config) ->
- [] = [{H,T} || H <- ?SERVICES,
- T <- [diameter:stop_service(H)],
- T /= ok].
+stop_services() ->
+ [{H,T} || H <- ?SERVICES,
+ T <- [diameter:stop_service(H)],
+ T /= ok].
-stop(_Config) ->
- ok = diameter:stop().
+%% Traffic cases run when services are started and connections
+%% established.
+send() ->
+ ?util:run([[fun traffic/1, T] || T <- [send1,
+ send2,
+ send3,
+ send4,
+ send_loop,
+ send_timeout_1,
+ send_timeout_2,
+ info]]).
%% ----------------------------------------
@@ -203,50 +188,50 @@ connect(Name, Refs) ->
%% traffic testcases
%% Send an STR intended for a specific server and expect success.
-send1(_Config) ->
- call(?SERVER1).
-send2(_Config) ->
- call(?SERVER2).
-send3(_Config) ->
- call(?SERVER3).
-send4(_Config) ->
- call(?SERVER4).
+traffic(send1) ->
+ call(?SERVER1);
+traffic(send2) ->
+ call(?SERVER2);
+traffic(send3) ->
+ call(?SERVER3);
+traffic(send4) ->
+ call(?SERVER4);
%% Send an ASR that loops between the relays (RELAY1 -> RELAY2 ->
%% RELAY1) and expect the loop to be detected.
-send_loop(_Config) ->
+traffic(send_loop) ->
Req = ['ASR', {'Destination-Realm', realm(?SERVER1)},
{'Destination-Host', ?SERVER1},
{'Auth-Application-Id', ?APP_ID}],
#'diameter_base_answer-message'{'Result-Code' = ?LOOP_DETECTED}
- = call(Req, [{filter, realm}]).
+ = call(Req, [{filter, realm}]);
%% Send a RAR that is incorrectly routed and then discarded and expect
%% different results depending on whether or not we or the relay
%% timeout first.
-send_timeout_1(_Config) ->
+traffic(send_timeout_1) ->
#'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER}
- = send_timeout(7000).
-send_timeout_2(_Config) ->
- {error, timeout} = send_timeout(3000).
+ = traffic({timeout, 7000});
+traffic(send_timeout_2) ->
+ {error, timeout} = traffic({timeout, 3000});
-send_timeout(Tmo) ->
+traffic({timeout, Tmo}) ->
Req = ['RAR', {'Destination-Realm', realm(?SERVER1)},
{'Destination-Host', ?SERVER1},
{'Auth-Application-Id', ?APP_ID},
{'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}],
- call(Req, [{filter, realm}, {timeout, Tmo}]).
+ call(Req, [{filter, realm}, {timeout, Tmo}]);
-info(_Config) ->
+traffic(info) ->
%% Wait for RELAY1 to have answered all requests, so that the
%% suite doesn't end before all answers are sent and counted.
receive after 6000 -> ok end,
[] = ?util:info().
-counters(_Config) ->
- [] = ?util:run([[fun counters/2, K, S]
- || K <- [statistics, transport, connections],
- S <- ?SERVICES]).
+counters() ->
+ ?util:run([[fun counters/2, K, S]
+ || K <- [statistics, transport, connections],
+ S <- ?SERVICES]).
counters(Key, Svc) ->
counters(Key, Svc, [_|_] = diameter:service_info(Svc, Key)).
diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl
index 4716082394..b48e7a84bf 100644
--- a/lib/diameter/test/diameter_stats_SUITE.erl
+++ b/lib/diameter/test/diameter_stats_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,55 +24,52 @@
-module(diameter_stats_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([reg/1,
- incr/1,
- read/1,
- sum/1,
- flush/1]).
+ parallel/1]).
-define(stat, diameter_stats).
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 30}}].
all() ->
- [{group, all},
- {group, all, [parallel]}].
+ [parallel].
-groups() ->
- [{all, [], tc()}].
+parallel(_Config) ->
+ run().
-tc() ->
- [reg,
- incr,
- read,
- sum,
- flush].
+%% ===========================================================================
-init_per_suite(Config) ->
- ok = diameter:start(),
- Config.
+%% run/0
-end_per_suite(_Config) ->
- ok = diameter:stop().
+run() ->
+ run([reg, incr, read, sum, flush]).
-%% ===========================================================================
+%% run/1
+
+run(List)
+ when is_list(List) ->
+ ok = diameter:start(),
+ try
+ diameter_util:run([{[fun run/1, T], 15000} || T <- List])
+ after
+ ok = diameter:stop()
+ end;
-reg(_) ->
+run(reg) ->
Ref = '$1',
true = ?stat:reg(Ref),
- false = ?stat:reg(Ref). %% duplicate
+ false = ?stat:reg(Ref); %% duplicate
-incr(_) ->
+run(incr) ->
Ref = '_',
Ctr = x,
false = ?stat:incr(Ctr), %% not registered,
@@ -83,9 +80,9 @@ incr(_) ->
2 = ?stat:incr(Ctr, self(), 2)
end),
ok = fold(Ctr, Ref, 3), %% folded
- ?stat:flush([self(), Ref]).
+ ?stat:flush([self(), Ref]);
-read(_) ->
+run(read) ->
Ref = make_ref(),
C1 = {a,b},
C2 = {b,a},
@@ -99,9 +96,9 @@ read(_) ->
= ?stat:read([self(), Ref, make_ref()]),
[] = ?stat:read([]),
[] = ?stat:read([make_ref()]),
- ?stat:flush([self(), Ref, make_ref()]).
+ ?stat:flush([self(), Ref, make_ref()]);
-sum(_) ->
+run(sum) ->
Ref = make_ref(),
C1 = {a,b},
C2 = {b,a},
@@ -116,9 +113,9 @@ sum(_) ->
[{Self, [{C1,1}, {C2,2}]}]
= ?stat:sum([self()]),
[{Ref, [{C1,7}]}, {Self, [{C1,1}, {C2,2}]}]
- = ?stat:flush([self(), Ref]).
+ = ?stat:flush([self(), Ref]);
-flush(_) ->
+run(flush) ->
Ref = make_ref(),
Ctr = '_',
true = ?stat:reg(Ref),
diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl
index 2785bd92d6..395c99bd0b 100644
--- a/lib/diameter/test/diameter_sync_SUITE.erl
+++ b/lib/diameter/test/diameter_sync_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,63 +24,59 @@
-module(diameter_sync_SUITE).
+%% testcases, no common_test depedency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([call/1,
- cast/1,
- timeout/1,
- flush/1]).
+ parallel/1]).
-define(sync, diameter_sync).
--define(util, diameter_util).
-
--define(TIMEOUT, infinity).
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 15}}].
all() ->
- [{group, all},
- {group, all, [parallel]}].
+ [parallel].
-groups() ->
- [{all, [], tc()}].
+parallel(_Config) ->
+ run().
-tc() ->
- [call,
- cast,
- timeout,
- flush].
+%% ===========================================================================
-init_per_suite(Config) ->
- ok = diameter:start(),
- Config.
+%% run/0
-end_per_suite(_Config) ->
- ok = diameter:stop().
+run() ->
+ run([call, cast, timeout, flush]).
-%% ===========================================================================
+%% run/1
+
+run(List)
+ when is_list(List) ->
+ ok = diameter:start(),
+ try
+ diameter_util:run([{[fun run/1, T], 10000} || T <- List])
+ after
+ ok = diameter:stop()
+ end;
-call(_) ->
+run(call) ->
Ref = make_ref(),
Q = {q, Ref},
F = fun() -> Ref end,
- Ref = ?sync:call(Q, F, infinity, ?TIMEOUT),
+ Ref = ?sync:call(Q, F, infinity, infinity),
Ref = ?sync:call(Q, F, 0, infinity),
Ref = call(Q, F),
Ref = call(Q, {fun(_) -> Ref end, x}),
timeout = call(Q, fun() -> exit(unexpected) end),
{_,_,_} = call(Q, {erlang, now, []}),
- {_,_,_} = call(Q, [fun erlang:now/0]).
+ {_,_,_} = call(Q, [fun erlang:now/0]);
-cast(_) ->
+run(cast) ->
Ref = make_ref(),
Q = {q, Ref},
false = ?sync:carp(Q),
@@ -95,26 +91,21 @@ cast(_) ->
true = 2 =< ?sync:pending(),
true = lists:member(Q, ?sync:queues()),
%% ... and that the max number of requests is respected.
- rejected = ?sync:call(Q, {erlang, now, []}, 1, ?TIMEOUT),
- rejected = ?sync:cast(Q, {erlang, now, []}, 1, ?TIMEOUT),
+ rejected = ?sync:call(Q, {erlang, now, []}, 1, infinity),
+ rejected = ?sync:cast(Q, {erlang, now, []}, 1, infinity),
%% Monitor on the identifiable request and see that exits when we
%% let the blocking request finish.
MRef = erlang:monitor(process, Pid),
{value, P} = ?sync:carp(Q),
P ! Ref,
- Ref = receive
- {'DOWN', MRef, process, _, Reason} ->
- Reason
- after ?TIMEOUT ->
- false
- end.
-
-timeout(_) ->
+ Ref = receive {'DOWN', MRef, process, _, Reason} -> Reason end;
+
+run(timeout) ->
Q = make_ref(),
ok = ?sync:cast(Q, {timer, sleep, [2000]}, infinity, 2000),
- timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000).
+ timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000);
-flush(_) ->
+run(flush) ->
Q = make_ref(),
F = {timer, sleep, [2000]},
ok = cast(Q, F),
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
index 1ad897dcd2..1e7f7ed50a 100644
--- a/lib/diameter/test/diameter_tls_SUITE.erl
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,27 +34,15 @@
-module(diameter_tls_SUITE).
+%% testcases, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([start_ssl/1,
- start_diameter/1,
- make_certs/1, make_certs/0,
- start_services/1,
- add_transports/1,
- send1/1,
- send2/1,
- send3/1,
- send4/1,
- send5/1,
- remove_transports/1,
- stop_services/1,
- stop_diameter/1,
- stop_ssl/1]).
+ end_per_suite/1,
+ parallel/1]).
%% diameter callbacks
-export([prepare_request/3,
@@ -126,34 +114,22 @@
-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [start_ssl,
- start_diameter,
- make_certs,
- start_services,
- add_transports,
- {group, all},
- {group, all, [parallel]},
- remove_transports,
- stop_services,
- stop_diameter,
- stop_ssl].
-
-groups() ->
- [{all, [], tc()}].
+ [parallel].
%% 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) ->
try
- false /= os:find_executable("openssl")
- orelse throw({?MODULE, no_openssl}),
- ok == (catch crypto:start())
- orelse throw({?MODULE, no_crypto}),
+ [] == (catch make_certs(dir(Config)))
+ orelse throw({?MODULE, no_certs}),
+ ok == crypto:start() orelse throw({?MODULE, no_crypto}),
+ ok == ssl:start() orelse throw({?MODULE, no_ssl}),
Config
catch
{?MODULE, E} ->
@@ -161,87 +137,81 @@ init_per_suite(Config) ->
end.
end_per_suite(_Config) ->
+ ssl:stop(),
crypto:stop().
-%% Testcases to run when services are started and connections
-%% established.
-tc() ->
- [send1,
- send2,
- send3,
- send4,
- send5].
-
-%% ===========================================================================
-%% testcases
-
-start_ssl(_Config) ->
- ok = ssl:start().
-
-start_diameter(_Config) ->
- ok = diameter:start().
+parallel(Config) ->
+ run(dir(Config), false).
-make_certs() ->
- [{timetrap, {minutes, 2}}].
+dir(Config) ->
+ proplists:get_value(priv_dir, Config).
-make_certs(Config) ->
- Dir = proplists:get_value(priv_dir, Config),
+%% ===========================================================================
- [] = ?util:run([[fun make_cert/2, Dir, B] || B <- ["server1",
- "server2",
- "server4",
- "server5",
- "client"]]).
+run() ->
+ Tmp = ?util:mktemp("diameter_tls"),
+ try
+ run(Tmp, true)
+ after
+ file:del_dir_r(Tmp)
+ end.
-start_services(Config) ->
- Dir = proplists:get_value(priv_dir, Config),
- Servers = [server(S, sopts(S, Dir)) || S <- ?SERVERS],
+run(Dir, B) ->
+ crypto:start(),
+ ssl:start(),
+ try
+ ?util:run([{[fun traffic/2, Dir, B], 60000}])
+ after
+ diameter:stop(),
+ ssl:stop(),
+ crypto:stop()
+ end.
+traffic(Dir, true) ->
+ [] = make_certs(Dir),
+ traffic(Dir, false);
+
+traffic(Dir, false) ->
+ ok = diameter:start(),
+ Servers = start_services(Dir),
+ Connections = add_transports(Dir, Servers),
+ [] = ?util:run([[fun call/1, S] || S <- ?util:scramble(?SERVERS)]),
+ [] = remove_transports(Connections),
+ [] = stop_services().
+
+make_certs(Dir) ->
+ ?util:run([[fun make_cert/2, Dir, B] || B <- ["server1",
+ "server2",
+ "server4",
+ "server5",
+ "client"]]).
+
+start_services(Dir) ->
+ Servers = [{S, {_,_} = server(S, sopts(S, Dir))} || S <- ?SERVERS],
ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+ Servers.
- {save_config, [Dir | Servers]}.
-
-add_transports(Config) ->
- {_, [Dir | Servers]} = proplists:get_value(saved_config, Config),
-
+add_transports(Dir, Servers) ->
true = diameter:subscribe(?CLIENT),
-
Opts = ssl_options(Dir, "client"),
- Connections = [connect(?CLIENT, S, copts(N, Opts))
- || {S,N} <- lists:zip(Servers, ?SERVERS)],
-
- ?util:write_priv(Config, "cfg", lists:zip(Servers, Connections)).
-
+ [{N, S, connect(?CLIENT, S, copts(N, Opts))} || {N,S} <- Servers].
%% Remove the client transports and expect the corresponding server
%% transport to go down.
-remove_transports(Config) ->
- Ts = ?util:read_priv(Config, "cfg"),
+remove_transports(Connections) ->
[] = [T || S <- ?SERVERS, T <- [diameter:subscribe(S)], T /= true],
- lists:map(fun disconnect/1, Ts).
+ [] = ?util:run([[fun disconnect/1, T] || T <- Connections]),
+ [S || S <- ?SERVERS,
+ I <- [receive #diameter_event{service = S, info = I} -> I end],
+ down /= catch element(1, I)].
-stop_services(_Config) ->
- [] = [{H,T} || H <- [?CLIENT | ?SERVERS],
- T <- [diameter:stop_service(H)],
- T /= ok].
+disconnect({_, {_LRef, _PortNr}, CRef}) ->
+ ok = diameter:remove_transport(?CLIENT, CRef).
-stop_diameter(_Config) ->
- ok = diameter:stop().
-
-stop_ssl(_Config) ->
- ok = ssl:stop().
-
-%% Send an STR intended for a specific server and expect success.
-send1(_Config) ->
- call(?SERVER1).
-send2(_Config) ->
- call(?SERVER2).
-send3(_Config) ->
- call(?SERVER3).
-send4(_Config) ->
- call(?SERVER4).
-send5(_Config) ->
- call(?SERVER5).
+stop_services() ->
+ [{H,T} || H <- [?CLIENT | ?SERVERS],
+ T <- [diameter:stop_service(H)],
+ T /= ok].
%% ===========================================================================
%% diameter callbacks
@@ -285,6 +255,7 @@ handle_request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}},
%% ===========================================================================
%% support functions
+%% Send an STR intended for a specific server and expect success.
call(Server) ->
Realm = realm(Server),
Req = ['STR', {'Destination-Realm', Realm},
@@ -301,10 +272,6 @@ call(Req, Opts) ->
set([H|T], Vs) ->
[H | Vs ++ T].
-disconnect({{LRef, _PortNr}, CRef}) ->
- ok = diameter:remove_transport(?CLIENT, CRef),
- receive #diameter_event{info = {down, LRef, _, _}} -> ok end.
-
realm(Host) ->
tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
@@ -364,11 +331,12 @@ ssl([{ssl_options = T, Opts}]) ->
connect(Host, {_LRef, PortNr}, {Caps, Opts}) ->
{ok, Ref} = diameter:add_transport(Host, ?CONNECT(PortNr, Caps, Opts)),
- receive
- #diameter_event{service = Host,
- info = {up, Ref, _, _, #diameter_packet{}}} ->
- ok
- end,
+ {up, Ref, _, _, #diameter_packet{}}
+ = receive
+ #diameter_event{service = Host, info = Info}
+ when element(2, Info) == Ref ->
+ Info
+ end,
Ref.
copts(S, Opts)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index a12759bac2..95ea6be020 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,25 +25,17 @@
-module(diameter_traffic_SUITE).
+%% all tests, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_group/1,
- init_per_group/2,
- end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2]).
+ parallel/1]).
%% testcases
--export([rfc4005/1,
- start/1,
- start_services/1,
- add_transports/1,
- result_codes/1,
- send_ok/1,
+-export([send_ok/1,
send_nok/1,
send_eval/1,
send_bad_answer/1,
@@ -97,11 +89,7 @@
send_multiple_filters_1/1,
send_multiple_filters_2/1,
send_multiple_filters_3/1,
- send_anything/1,
- remove_transports/1,
- empty/1,
- stop_services/1,
- stop/1]).
+ send_anything/1]).
%% diameter callbacks
-export([peer_up/4,
@@ -127,14 +115,6 @@
%% ===========================================================================
-%% Fraction of shuffle/parallel groups to randomly skip.
--define(SKIP, 0.90).
-
-%% Positive number of testcases from which to select (randomly) from
-%% tc(), the list of testcases to run, or [] to run all. The random
-%% selection is to limit the time it takes for the suite to run.
--define(LIMIT, #{tcp => 42, sctp => 5}).
-
-define(util, diameter_util).
-define(A, list_to_atom).
@@ -164,30 +144,19 @@
%% Which dictionary to use in the clients.
-define(RFCS, [rfc3588, rfc6733, rfc4005]).
-%% Whether to decode stringish Diameter types to strings, or leave
-%% them as binary.
--define(STRING_DECODES, [false, true]).
-
%% Which transport protocol to use.
--define(TRANSPORTS, [tcp, sctp]).
-
-%% Send from a dedicated process?
--define(SENDERS, [true, false]).
-
-%% Message callbacks from diameter_{tcp,sctp}?
--define(CALLBACKS, [true, false]).
-
--record(group,
- {transport,
- strings,
- encoding,
- client_service,
- client_dict,
- client_sender,
- server_service,
- server_decoding,
- server_sender,
- server_throttle}).
+-define(TRANSPORTS, [sctp || ?util:have_sctp()] ++ [tcp]).
+
+-record(group, {transport,
+ strings,
+ encoding,
+ client_service,
+ client_dict,
+ client_sender,
+ server_service,
+ server_decoding,
+ server_sender,
+ server_throttle}).
%% Not really what we should be setting unless the message is sent in
%% the common application but diameter doesn't care.
@@ -270,285 +239,156 @@
?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED').
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 10}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [rfc4005, start, result_codes, {group, traffic}, empty, stop].
-
-%% Redefine this to run one or more groups for debugging purposes.
--define(GROUPS, []).
-%-define(GROUPS, [[sctp,rfc6733,record,map,false,false,true,false]]).
-
-%% Issues with gen_sctp sporadically cause huge numbers of failed
-%% testcases when running testcases in parallel.
-groups() ->
- Names = names([] == ?GROUPS orelse ?GROUPS),
- [{P, [P], Ts} || Ts <- [tc()], P <- [shuffle, parallel]]
- ++
- [{?util:name(N), [], [{group, if T == sctp; S -> shuffle;
- true -> parallel end}]}
- || [T,_,_,_,S|_] = N <- Names]
- ++
- [{T, [], [{group, ?util:name(N)} || N <- Names,
- T == hd(N)]}
- || T <- ?TRANSPORTS]
- ++
- [{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
-
-names() ->
- [[T,R,E,D,S,ST,SS,CS] || T <- ?TRANSPORTS,
- R <- ?RFCS,
- E <- ?ENCODINGS,
- D <- ?DECODINGS,
- S <- ?STRING_DECODES,
- ST <- ?CALLBACKS,
- SS <- ?SENDERS,
- CS <- ?SENDERS,
- ?SKIP =< rand:uniform()].
-
-names(true) ->
- names(names());
-
-names(Names) ->
- [N || N <- Names,
- [CS,SS|_] <- [lists:reverse(N)],
- SS orelse CS]. %% avoid deadlock
-
-%% --------------------
-
-init_per_suite() ->
- [{timetrap, {seconds, 60}}].
-
-init_per_suite(Config) ->
- [{rfc4005, compile_and_load()}, {sctp, ?util:have_sctp()} | Config].
-
-end_per_suite(_Config) ->
- code:delete(nas4005),
- code:purge(nas4005),
- ok.
+ [parallel].
-%% --------------------
+parallel(_Config) ->
+ run().
-init_per_group(_) ->
- [{timetrap, {seconds, 30}}].
+%% ===========================================================================
-init_per_group(Name, Config)
- when Name == shuffle;
- Name == parallel ->
- start_services(Config),
- add_transports(Config),
- replace({sleep, Name == parallel}, Config);
+%% run/0
+%%
+%% The test cases proper, do or (meaningfully) die.
+%%
+%% Randomly choose one of many configuration possibilities. Testing
+%% all of them takes too much time, and randomly skipping various
+%% cases (as used to be the case) just unnecessary complexity. There
+%% are run night after night in on various hosts, so just choosing a
+%% configuration results in sufficient coverage over time.
+
+run() ->
+ Svc = ?util:unique_string(),
+ run(#group{transport = ?util:choose(?TRANSPORTS),
+ strings = bool(),
+ encoding = ?util:choose(?ENCODINGS),
+ client_service = [$C | Svc],
+ client_dict = appdict(?util:choose(?RFCS)),
+ client_sender = bool(),
+ server_service = [$S | Svc],
+ server_decoding = ?util:choose(?DECODINGS),
+ server_sender = true, %% avoid deadlock
+ server_throttle = bool()}).
+
+%% run/1
+
+run(#group{} = Cfg) ->
+ _ = result_codes(Cfg),
+ io:format("config: ~p~n", [Cfg]),
+ try
+ ?util:run([{[fun traffic/1, Cfg], 60000}])
+ after
+ code:delete(nas4005),
+ code:purge(nas4005),
+ diameter:stop()
+ end.
-init_per_group(sctp = Name, Config) ->
- {_, Sctp} = lists:keyfind(Name, 1, Config),
- if Sctp ->
- Config;
- true ->
- {skip, Name}
- end;
+%% traffic/1
-init_per_group(Name, Config) ->
- Nas = proplists:get_value(rfc4005, Config, false),
- case ?util:name(Name) of
- [_,R,_,_,_,_,_,_] when R == rfc4005, true /= Nas ->
- {skip, rfc4005};
- [T,R,E,D,S,ST,SS,CS] ->
- G = #group{transport = T,
- strings = S,
- encoding = E,
- client_service = [$C|?util:unique_string()],
- client_dict = appdict(R),
- client_sender = CS,
- server_service = [$S|?util:unique_string()],
- server_decoding = D,
- server_sender = SS,
- server_throttle = ST},
- replace([{group, G}, {runlist, select(T)}], Config);
- _ ->
- Config
- end.
+traffic(#group{} = Cfg) ->
+ _ = compile_and_load(),
+ ok = diameter:start(),
+ LRef = server(Cfg),
+ ok = client(Cfg, LRef),
+ [] = send(Cfg),
+ ok = stop_services(Cfg),
+ [] = ets:tab2list(diameter_request).
-end_per_group(Name, Config)
- when Name == shuffle;
- Name == parallel ->
- remove_transports(Config),
- stop_services(Config);
+%% start_service/2
-end_per_group(_, _) ->
+start_service(Svc, Opts) ->
+ {ok, _} = {diameter:start_service(Svc, Opts), Opts},
ok.
-select(T) ->
- try maps:get(T, ?LIMIT) of
- N ->
- lists:sublist(?util:scramble(tc()), max(5, rand:uniform(N)))
- catch
- error:_ -> ?LIMIT
- end.
+%% send/1
-%% --------------------
-
-%% Work around common_test accumulating Config improperly, causing
-%% testcases to get Config from groups and suites they're not in.
-init_per_testcase(N, Config)
- when N == rfc4005;
- N == start;
- N == result_codes;
- N == empty;
- N == stop ->
- Config;
-
-%% Skip testcases that can reasonably fail under SCTP.
-init_per_testcase(Name, Config) ->
- TCs = proplists:get_value(runlist, Config, []),
- Run = [] == TCs orelse lists:member(Name, TCs),
- case [G || #group{transport = sctp} = G
- <- [proplists:get_value(group, Config)]]
- of
- [_] when Name == send_maxlen;
- Name == send_long ->
- {skip, sctp};
- _ when not Run ->
- {skip, random};
- _ ->
- proplists:get_value(sleep, Config, false)
- andalso timer:sleep(rand:uniform(200)),
- [{testcase, Name} | Config]
- end.
+send(Cfg) ->
+ Ref = make_ref(),
+ Refs = [R || {F,1} <- module_info(exports),
+ "send_" ++ _ <- [atom_to_list(F)],
+ I <- [fun() -> exit({Ref, send(F, Cfg)}) end],
+ {_,R} <- [spawn_monitor(I)]],
+ lists:filter(fun({R,_}) -> R /= Ref; (_) -> true end, wait(Refs)).
-end_per_testcase(_, _) ->
- ok.
+%% send/2
-%% replace/2
-%%
-%% Work around common_test running init functions inappropriately, and
-%% this accumulating more config than expected.
-
-replace(Pairs, Config)
- when is_list(Pairs) ->
- lists:foldl(fun replace/2, Config, Pairs);
-
-replace({Key, _} = T, Config) ->
- [T | lists:keydelete(Key, 1, Config)].
-
-%% --------------------
-
-%% Testcases to run when services are started and connections
-%% established.
-tc() ->
- [send_ok,
- send_nok,
- send_eval,
- send_bad_answer,
- send_protocol_error,
- send_experimental_result,
- send_arbitrary,
- send_proxy_info,
- send_unknown,
- send_unknown_short,
- send_unknown_mandatory,
- send_unknown_short_mandatory,
- send_noreply,
- send_grouped_error,
- send_unsupported,
- send_unsupported_app,
- send_error_bit,
- send_unsupported_version,
- send_long_avp_length,
- send_short_avp_length,
- send_zero_avp_length,
- send_invalid_avp_length,
- send_invalid_reject,
- send_unexpected_mandatory_decode,
- send_unexpected_mandatory,
- send_too_many,
- send_long,
- send_maxlen,
- send_nopeer,
- send_noapp,
- send_discard,
- send_any_1,
- send_any_2,
- send_all_1,
- send_all_2,
- send_timeout,
- send_error,
- send_detach,
- send_encode_error,
- send_destination_1,
- send_destination_2,
- send_destination_3,
- send_destination_4,
- send_destination_5,
- send_destination_6,
- send_bad_option_1,
- send_bad_option_2,
- send_bad_filter_1,
- send_bad_filter_2,
- send_bad_filter_3,
- send_bad_filter_4,
- send_multiple_filters_1,
- send_multiple_filters_2,
- send_multiple_filters_3,
- send_anything].
+send(F, #group{transport = sctp})
+ when F == send_long;
+ F == send_maxlen ->
+ ok;
-%% ===========================================================================
-%% start/stop testcases
+send(F, Cfg) ->
+ timer:sleep(rand:uniform(2000)),
+ apply(?MODULE, F, [[{testcase, F}, {group, Cfg}]]).
-start(_Config) ->
- ok = diameter:start().
+%% wait/1
-start_services(Config) ->
- #group{client_service = CN,
- server_service = SN,
- server_decoding = SD}
- = Grp
- = group(Config),
- ok = diameter:start_service(SN, [{traffic_counters, bool()},
- {decode_format, SD}
- | ?SERVICE(SN, Grp)]),
- ok = diameter:start_service(CN, [{traffic_counters, bool()},
- {sequence, ?CLIENT_MASK},
- {decode_format, map},
- {strict_arities, decode}
- | ?SERVICE(CN, Grp)]).
+wait(Refs)
+ when is_list(Refs) ->
+ lists:map(fun wait/1, Refs);
-bool() ->
- 0.5 =< rand:uniform().
+wait(MRef) ->
+ receive {'DOWN', MRef, process, _, T} -> T end.
+
+%% ===========================================================================
-add_transports(Config) ->
+%% server/1
+
+server(Config) ->
#group{transport = T,
- encoding = E,
- client_service = CN,
client_sender = CS,
server_service = SN,
+ server_decoding = SD,
server_sender = SS,
server_throttle = ST}
+ = Grp
= group(Config),
- LRef = ?util:listen(SN,
- [T,
- {sender, SS},
- {message_cb, ST andalso {?MODULE, message, [0]}}]
- ++ [{packet, hd(?util:scramble([false, raw]))}
- || T == sctp andalso CS]
- ++ [{unordered, unordered()} || T == sctp],
- [{capabilities_cb, fun capx/2},
- {pool_size, 8}
- | server_apps()]),
- Cs = [?util:connect(CN,
- [T, {sender, CS} | client_opts(T)],
- LRef,
- [{id, Id}
- | client_apps(R, [{'Origin-State-Id', origin(Id)}])])
- || D <- ?DECODINGS, %% for multiple candidate peers
- R <- ?RFCS,
- R /= rfc4005 orelse have_nas(),
- Id <- [{D,E}]],
- ?util:write_priv(Config, "transport", [LRef | Cs]).
+ ok = start_service(SN, [{traffic_counters, bool()},
+ {decode_format, SD}
+ | ?SERVICE(SN, Grp)]),
+ Cfg = [{sender, SS},
+ {message_cb, ST andalso {?MODULE, message, [0]}}]
+ ++ [{packet, ?util:choose([false, raw])} || T == sctp andalso CS]
+ ++ [{unordered, unordered()} || T == sctp],
+ Opts = [{capabilities_cb, fun capx/2},
+ {pool_size, 8}
+ | server_apps()],
+ _LRef = ?util:listen(SN, [T | Cfg], Opts).
+
+%% client/1
+
+client(Config, LRef) ->
+ #group{transport = T,
+ encoding = E,
+ client_service = CN,
+ client_sender = CS}
+ = Grp
+ = group(Config),
+ ok = start_service(CN, [{traffic_counters, bool()},
+ {sequence, ?CLIENT_MASK},
+ {decode_format, map},
+ {strict_arities, decode}
+ | ?SERVICE(CN, Grp)]),
+ _ = [?util:connect(CN, [T | C], LRef, O)
+ || C <- [[{sender, CS} | client_opts(T)]],
+ D <- ?DECODINGS, %% for multiple candidate peers
+ R <- ?RFCS,
+ R /= rfc4005 orelse have_nas(),
+ I <- [{D,E}],
+ O <- [[{id, I}
+ | client_apps(R, [{'Origin-State-Id', origin(I)}])]]],
+ ok.
+
+bool() ->
+ 0.5 =< rand:uniform().
unordered() ->
- element(rand:uniform(4), {true, false, 1, 2}).
+ ?util:choose([true, false, 1, 2]).
client_opts(tcp) ->
[];
@@ -567,32 +407,19 @@ server_apps() ->
{capabilities, [{'Auth-Application-Id', [0] ++ [1 || B]}, %% common, NAS
{'Acct-Application-Id', [3]}]}]. %% accounting
+client_apps(rfc4005, Caps) ->
+ [{applications, [nas4005]},
+ {capabilities, [{'Auth-Application-Id', [1]}, %% NAS
+ {'Acct-Application-Id', []}
+ | Caps]}];
client_apps(D, Caps) ->
- if D == rfc4005 ->
- [{applications, [nas4005]},
- {capabilities, [{'Auth-Application-Id', [1]}, %% NAS
- {'Acct-Application-Id', []}
- | Caps]}];
- true ->
- D0 = dict0(D),
- [{applications, [acct(D0), D0]},
- {capabilities, Caps}]
- end.
+ D0 = dict0(D),
+ [{applications, [acct(D0), D0]},
+ {capabilities, Caps}].
have_nas() ->
false /= code:is_loaded(nas4005).
-remove_transports(Config) ->
- #group{client_service = CN,
- server_service = SN}
- = group(Config),
- [LRef | Cs] = ?util:read_priv(Config, "transport"),
- try
- [] = [T || C <- Cs, T <- [?util:disconnect(CN, C, SN, LRef)], T /= ok]
- after
- ok = diameter:remove_transport(SN, LRef)
- end.
-
stop_services(Config) ->
#group{client_service = CN,
server_service = SN}
@@ -600,24 +427,12 @@ stop_services(Config) ->
ok = diameter:stop_service(CN),
ok = diameter:stop_service(SN).
-%% Ensure even transports have been removed from request table.
-empty(_Config) ->
- [] = ets:tab2list(diameter_request).
-
-stop(_Config) ->
- ok = diameter:stop().
-
capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
io:format("connection: ~p -> ~p~n", [DH,OH]),
ok.
%% ===========================================================================
-%% Fail only this testcase if the RFC 4005 dictionary hasn't been
-%% successfully compiled and loaded.
-rfc4005(Config) ->
- true = proplists:get_value(rfc4005, Config).
-
%% Ensure that result codes have the expected values.
result_codes(_Config) ->
{2001,
@@ -1135,6 +950,8 @@ send_anything(Config) ->
%% ===========================================================================
+group(#group{} = Rec) ->
+ Rec;
group(Config) ->
#group{} = proplists:get_value(group, Config).
@@ -1903,25 +1720,19 @@ message(ack, _, N) ->
%% ------------------------------------------------------------------------
compile_and_load() ->
- try
- Path = hd([P || H <- [[here(), ".."], [code:lib_dir(diameter)]],
- P <- [filename:join(H ++ ["examples",
- "dict",
- "rfc4005_nas.dia"])],
- {ok, _} <- [file:read_file_info(P)]]),
- {ok, [Forms]}
- = diameter_make:codec(Path, [return,
- forms,
- {name, "nas4005"},
- {prefix, "nas"},
- {inherits, "common/diameter_gen_base_rfc3588"}]),
- {ok, nas4005, Bin, []} = compile:forms(Forms, [debug_info, return]),
- {module, nas4005} = code:load_binary(nas4005, "nas4005", Bin),
- true
- catch
- E:R:Stack ->
- {E, R, Stack}
- end.
+ Path = hd([P || H <- [[here(), ".."], [code:lib_dir(diameter)]],
+ P <- [filename:join(H ++ ["examples",
+ "dict",
+ "rfc4005_nas.dia"])],
+ {ok, _} <- [file:read_file_info(P)]]),
+ Opts = [return,
+ forms,
+ {name, "nas4005"},
+ {prefix, "nas"},
+ {inherits, "common/diameter_gen_base_rfc3588"}],
+ {ok, [Forms]} = diameter_make:codec(Path, Opts),
+ {ok, nas4005, Bin, []} = compile:forms(Forms, [debug_info, return]),
+ {module, nas4005} = code:load_binary(nas4005, "nas4005", Bin).
here() ->
filename:dirname(code:which(?MODULE)).
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index 284d2b9566..9b763141ff 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,23 +25,17 @@
-module(diameter_transport_SUITE).
+%% all tests, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([start/1,
- tcp_accept/1,
- tcp_connect/1,
- sctp_accept/1,
- sctp_connect/1,
- reconnect/1, reconnect/0,
- stop/1]).
+ parallel/1]).
-export([accept/1,
connect/1,
+ reconnect/1,
init/2]).
-include_lib("kernel/include/inet_sctp.hrl").
@@ -84,93 +78,63 @@
-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}).
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 15}}].
+ [{timetrap, {seconds, 270}}].
all() ->
- [start,
- {group, all},
- {group, all, [parallel]},
- stop].
+ [parallel].
-groups() ->
- [{all, [], tc()}].
+parallel(_) ->
+ run().
-tc() ->
- [tcp_accept,
- tcp_connect,
- sctp_accept,
- sctp_connect,
- reconnect].
+%% ===========================================================================
-init_per_suite(Config) ->
- [{sctp, ?util:have_sctp()} | Config].
+%% run/0
-end_per_suite(_Config) ->
- ok.
+run() ->
+ ok = diameter:start(),
+ try
+ ?util:run([[fun run/1, {P,F}]
+ || P <- [sctp || ?util:have_sctp()] ++ [tcp],
+ F <- [connect, accept, reconnect]])
+ after
+ diameter:stop()
+ end.
-%% ===========================================================================
+%% run/1
-start(_Config) ->
- ok = diameter:start().
+run({Prot, reconnect}) ->
+ reconnect(Prot);
-stop(_Config) ->
- ok = diameter:stop().
+run({Prot, accept}) ->
+ accept(Prot);
+
+run({Prot, connect}) ->
+ connect(Prot).
%% ===========================================================================
-%% tcp_accept/1
-%% sctp_accept/1
+%% accept/1
%%
%% diameter transport accepting, test code connecting.
-tcp_accept(_) ->
- accept(tcp).
-
-sctp_accept(Config) ->
- case lists:member({sctp, true}, Config) of
- true -> accept(sctp);
- false -> {skip, no_sctp}
- end.
-
-%% Start multiple accepting transport processes that are connected to
-%% with an equal number of connecting processes using gen_tcp/sctp
-%% directly.
-
--define(PEER_COUNT, 8).
-
accept(Prot) ->
Ref = make_ref(),
true = diameter_reg:add_new({diameter_config, transport, Ref}), %% fake it
T = {Prot, Ref},
- [] = ?util:run(?util:scramble(acc(2*?PEER_COUNT, T, []))).
-
-acc(0, _, Acc) ->
- Acc;
-acc(N, T, Acc) ->
- acc(N-1, T, [{?MODULE, [init,
- element(1 + N rem 2, {accept, gen_connect}),
- T]}
- | Acc]).
+ ?util:run([{{?MODULE, [init, X, T]}, 15000}
+ || X <- [accept, gen_connect]]).
%% ===========================================================================
-%% tcp_connect/1
-%% sctp_connect/1
+%% connect/1
%%
%% Test code accepting, diameter transport connecting.
-tcp_connect(_) ->
- connect(tcp).
-
-sctp_connect(Config) ->
- case lists:member({sctp, true}, Config) of
- true -> connect(sctp);
- false -> {skip, no_sctp}
- end.
-
connect(Prot) ->
T = {Prot, make_ref()},
- [] = ?util:run([{?MODULE, [init, X, T]} || X <- [gen_accept, connect]]).
+ ?util:run([{{?MODULE, [init, X, T]}, 15000}
+ || X <- [gen_accept, connect]]).
%% ===========================================================================
%% reconnect/1
@@ -179,9 +143,6 @@ connect(Prot) ->
%% doesn't try to establish a new connection until the old one is
%% broken.
-reconnect() ->
- [{timetrap, {minutes, 4}}].
-
reconnect({listen, Ref}) ->
SvcName = make_ref(),
ok = start_service(SvcName),
@@ -222,10 +183,11 @@ reconnect({connect, Ref}) ->
MRef = erlang:monitor(process, Pid),
?RECV({'DOWN', MRef, process, _, _});
-reconnect(_) ->
+reconnect(Prot) ->
Ref = make_ref(),
- [] = ?util:run([{?MODULE, [reconnect, {T, Ref}]}
- || T <- [listen, connect]]).
+ ?util:run([{{?MODULE, [reconnect, {T, Ref}]}, 240000}
+ || Prot == tcp, %% ignore sctp
+ T <- [listen, connect]]).
start_service(SvcName) ->
OH = diameter_util:unique_string(),
@@ -430,8 +392,9 @@ gen_send(tcp, Sock, Bin) ->
gen_recv(sctp, Sock) ->
{_OS, _IS, Id} = getr(assoc),
receive
- ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin})
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = I}], Bin})
when is_binary(Bin) ->
+ {Id, _} = {I, Id}, %% assert
Bin
end;
gen_recv(tcp, Sock) ->
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index d249b0e4fa..cdb6fa410f 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,10 @@
fold/3,
foldl/3,
scramble/1,
+ choose/1,
+ tmpdir/0,
+ mktemp/1,
+ peer/1,
unique_string/0,
have_sctp/0,
eprof/1]).
@@ -42,11 +46,6 @@
disconnect/4,
info/0]).
-%% common_test-specific
--export([write_priv/3,
- read_priv/2,
- map_priv/3]).
-
-define(L, atom_to_list).
%% ---------------------------------------------------------------------------
@@ -63,7 +62,7 @@ eprof(stop) ->
%% ---------------------------------------------------------------------------
%% name/2
%%
-%% Contruct and deconstruct lists of atoms as atoms to work around
+%% Construct and deconstruct lists of atoms as atoms to work around
%% group names in common_test being restricted to atoms.
name(Names)
@@ -102,18 +101,37 @@ consult(Path) ->
%% ---------------------------------------------------------------------------
%% run/1
%%
-%% Evaluate functions in parallel and return a list of those that
-%% failed to return. The fun takes a boolean (did the function return
-%% or not), the function that was evaluated, the return value or exit
-%% reason and the prevailing accumulator.
+%% Evaluate functions in parallel and raise an error exception if any
+%% fail to return.
run(L) ->
- fold(fun cons/4, [], L).
-
-cons(true, _, _, Acc) ->
- Acc;
-cons(false, F, RC, Acc) ->
- [{F, RC} | Acc].
+ Ref = make_ref(),
+ AccF = fun(I, [F|T]) ->
+ Ref == (catch element(1, I))
+ orelse error(#{failed => F, reason => I}),
+ T
+ end,
+ Pid = self(),
+ Funs = [fun() -> down(Pid, self()), {Ref, eval(F)} end || F <- L],
+ [] = fold(AccF, L, Funs).
+
+%% down/2
+
+down(Parent, Worker)
+ when is_pid(Parent) ->
+ spawn(fun() ->
+ monitor(process, Worker),
+ down(monitor(process, Parent), Worker)
+ end);
+
+%% Die with the worker, kill the worker if the parent dies.
+down(MRef, Pid) ->
+ receive
+ {'DOWN', MRef, process, _, _} ->
+ exit(Pid, kill);
+ {'DOWN', _, process, Pid, _} ->
+ ok
+ end.
%% ---------------------------------------------------------------------------
%% fold/3
@@ -121,61 +139,43 @@ cons(false, F, RC, Acc) ->
%% Parallel fold. Results are folded in the order received.
fold(Fun, Acc0, L)
- when is_function(Fun, 4) ->
- Ref = make_ref(),
- %% Spawn a middleman to collect down messages from processes
- %% spawned for each function so as not to assume that all DOWN
- %% messages are ours.
- MRef = run1([fun fold/4, Ref, Fun, Acc0, L], Ref),
- {Ref, RC} = down(MRef),
- RC.
-
-fold(Ref, Fun, Acc0, L) ->
- recv(run(Ref, L), Ref, Fun, Acc0).
-
-run(Ref, L) ->
- [{run1(F, Ref), F} || F <- L].
-
-run1(F, Ref) ->
- {_, MRef} = spawn_monitor(fun() -> exit({Ref, eval(F)}) end),
- MRef.
-
-recv([], _, _, Acc) ->
+ when is_list(L) ->
+ fold(Fun, Acc0, lists:foldl(fun(F,A) ->
+ {P,M} = spawn_eval(F),
+ A#{M => P}
+ end,
+ #{},
+ L));
+
+fold(_, Acc, Map)
+ when 0 == map_size(Map) ->
Acc;
-recv(L, Ref, Fun, Acc) ->
- {MRef, R} = down(),
- {MRef, F} = lists:keyfind(MRef, 1, L),
- recv(lists:keydelete(MRef, 1, L),
- Ref,
- Fun,
- acc(R, Ref, F, Fun, Acc)).
-acc({Ref, RC}, Ref, F, Fun, Acc) ->
- Fun(true, F, RC, Acc);
-acc(Reason, _, F, Fun, Acc) ->
- Fun(false, F, Reason, Acc).
+fold(Fun, Acc, #{} = Map) ->
+ receive
+ {'DOWN', MRef, process, _, Info} when is_map_key(MRef, Map) ->
+ fold(Fun, Fun(Info, Acc), maps:remove(MRef, Map))
+ end.
-down(MRef) ->
- receive {'DOWN', MRef, process, _, Reason} -> Reason end.
+%% spawn_eval/1
-down() ->
- receive {'DOWN', MRef, process, _, Reason} -> {MRef, Reason} end.
+spawn_eval(F) ->
+ spawn_monitor(fun() -> exit(eval(F)) end).
%% ---------------------------------------------------------------------------
%% foldl/3
%%
%% Parallel fold. Results are folded in order of the function list.
-foldl(Fun, Acc0, L)
- when is_function(Fun, 4) ->
- Ref = make_ref(),
- recvl(run(Ref, L), Ref, Fun, Acc0).
+foldl(Fun, Acc0, L) ->
+ lists:foldl(fun(R,A) -> acc(Fun, R, A) end,
+ Acc0,
+ [M || F <- L, {_,M} <- [spawn_eval(F)]]).
-recvl([], _, _, Acc) ->
- Acc;
-recvl([{MRef, F} | L], Ref, Fun, Acc) ->
- R = down(MRef),
- recvl(L, Ref, Fun, acc(R, Ref, F, Fun, Acc)).
+%% acc/3
+
+acc(Fun, MRef, Acc) ->
+ receive {'DOWN', MRef, process, _, Info} -> Fun(Info, Acc) end.
%% ---------------------------------------------------------------------------
%% scramble/1
@@ -186,6 +186,71 @@ scramble(L) ->
[X || {_,X} <- lists:sort([{rand:uniform(), T} || T <- L])].
%% ---------------------------------------------------------------------------
+%% choose/1
+%%
+%% Return a random element from a list.
+
+choose([_|_] = List) ->
+ hd(lists:nthtail(rand:uniform(length(List)) - 1, List)).
+
+%% ---------------------------------------------------------------------------
+%% tmpdir/0
+
+tmpdir() ->
+ case os:getenv("TMPDIR") of
+ false ->
+ "/tmp";
+ Dir ->
+ Dir
+ end.
+
+%% mktemp/1
+
+mktemp(Prefix) ->
+ Suf = integer_to_list(erlang:monotonic_time()),
+ Tmp = filename:join(tmpdir(), Prefix ++ "." ++ Suf),
+ ok = file:make_dir(Tmp),
+ Tmp.
+
+%% ---------------------------------------------------------------------------
+%% peer/1
+%%
+%% Start a peer that dies with the calling process, but start it from
+%% a spawned process to make it insensitive to the exit reason of the
+%% calling process.
+
+peer(#{name := _} = Opts) ->
+ Ref = make_ref(),
+ Pid = self(),
+ {_, MRef} = spawn_monitor(fun() -> peer(Opts, Pid, Ref) end),
+ receive
+ {Ref, T} ->
+ erlang:demonitor(MRef, [flush]),
+ T;
+ {'DOWN', MRef, process, _, T} ->
+ {error, T}
+ end;
+
+peer(#{} = Opts) ->
+ peer(Opts#{name => peer:random_name()}).
+
+%% peer/3
+
+peer(Opts, Pid, Ref) ->
+ Cookie = atom_to_list(erlang:get_cookie()),
+ Args = [str(B) || B <- maps:get(args, Opts, [])],
+ Pid ! {Ref, peer:start_link(Opts#{args => ["-setcookie", Cookie | Args]})},
+ MRef = monitor(process, Pid),
+ receive {'DOWN', MRef, process, _, _} -> ok end.
+
+%% str/1
+%%
+%% Turn possible iodata() into string().
+
+str(Bytes) ->
+ binary_to_list(iolist_to_binary(Bytes)).
+
+%% ---------------------------------------------------------------------------
%% unique_string/0
unique_string() ->
@@ -208,8 +273,7 @@ have_sctp(_) ->
{ok, Sock} ->
gen_sctp:close(Sock),
true;
- {error, E} when E == eprotonosupport;
- E == esocktnosupport -> %% fail on any other reason
+ _ ->
false
end.
@@ -218,6 +282,13 @@ have_sctp(_) ->
%%
%% Evaluate a function in one of a number of forms.
+eval({F, infinity}) ->
+ eval(F);
+eval({F, Tmo})
+ when is_integer(Tmo) ->
+ {ok, _} = timer:exit_after(Tmo, timeout),
+ eval(F);
+
eval({M,[F|A]})
when is_atom(F) ->
apply(M,F,A);
@@ -231,55 +302,13 @@ eval([F|A])
eval(L)
when is_list(L) ->
- run(L);
+ [eval(F) || F <- L];
eval(F)
when is_function(F,0) ->
F().
%% ---------------------------------------------------------------------------
-%% write_priv/3
-%%
-%% Write an arbitrary term to a named file.
-
-write_priv(Config, Name, Term) ->
- write(path(Config, Name), Term).
-
-write(Path, Term) ->
- ok = file:write_file(Path, term_to_binary(Term)).
-
-%% read_priv/2
-%%
-%% Read a term from a file.
-
-read_priv(Config, Name) ->
- read(path(Config, Name)).
-
-read(Path) ->
- {ok, Bin} = file:read_file(Path),
- binary_to_term(Bin).
-
-%% map_priv/3
-%%
-%% Modify a term in a file and return both old and new values.
-
-map_priv(Config, Name, Fun1) ->
- map(path(Config, Name), Fun1).
-
-map(Path, Fun1) ->
- T0 = read(Path),
- T1 = Fun1(T0),
- write(Path, T1),
- {T0, T1}.
-
-path(Config, Name)
- when is_atom(Name) ->
- path(Config, ?L(Name));
-path(Config, Name) ->
- Dir = proplists:get_value(priv_dir, Config),
- filename:join([Dir, Name]).
-
-%% ---------------------------------------------------------------------------
%% lport/2
%%
%% Lookup the port number of a tcp/sctp listening transport.
diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl
index f3f168e671..02f15ff21b 100644
--- a/lib/diameter/test/diameter_watchdog_SUITE.erl
+++ b/lib/diameter/test/diameter_watchdog_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,18 +25,22 @@
-module(diameter_watchdog_SUITE).
+%% testcases, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([reopen/0, reopen/1, reopen/4, reopen/6,
- suspect/1, suspect/4,
- okay/1, okay/4]).
-
--export([id/1, %% jitter callback
- run1/1,
+ reopen/1,
+ suspect/1,
+ okay/1]).
+
+%% internal callbacks
+-export([reopen/4, reopen/6,
+ suspect/4,
+ okay/4,
+ id/1, %% jitter callback
abuse/1,
abuse/2]).
@@ -48,7 +52,6 @@
-export([message/3]).
-include("diameter.hrl").
--include("diameter_ct.hrl").
%% ===========================================================================
@@ -105,49 +108,72 @@
[])).
%% Log to make failures identifiable.
--define(LOG(T), ?LOG("~p", [T])).
--define(LOG(F,A), ct:pal("~p: " ++ F, [self() | A])).
--define(WARN(F,A), ct:pal(error, "~p: " ++ F, [self() | A])).
+-define(LOG(F,A), io:format("~p: " ++ F ++ "~n", [self() | A])).
%% ===========================================================================
suite() ->
- [{timetrap, {seconds, 90}}].
+ [{timetrap, {seconds, 315}}].
all() ->
- [reopen,
- suspect,
- okay].
+ [reopen, suspect, okay].
-init_per_suite(Config) ->
- ok = diameter:start(),
- Config.
+reopen(_Config) ->
+ run([reopen]).
+
+suspect(_Config) ->
+ run([suspect]).
+
+okay(_Config) ->
+ run([okay]).
+
+%% ===========================================================================
+
+%% run/0
-end_per_suite(_Config) ->
- ok = diameter:stop().
+run() ->
+ run(all()).
+
+%% run/1.
+
+run(reopen) ->
+ reopen(); %% 20 watchdogs @ 15 sec
+
+run(suspect) ->
+ suspect();
+
+run(okay) ->
+ okay();
+
+run(List) ->
+ ok = diameter:start(),
+ try
+ ?util:run([{[fun run/1, T], maps:get(T, #{reopen => 300000}, 90000)}
+ || T <- List])
+ after
+ ok = diameter:stop()
+ end.
%% ===========================================================================
-%% # reopen/1
+%% # reopen/0
%% ===========================================================================
%% Test the watchdog state machine for the required failover, failback
%% and reopen behaviour by examining watchdog events.
reopen() ->
- [{timetrap, {minutes, 5}}]. %% 20 watchdogs @ 15 sec
-
-reopen(_) ->
- [] = run([[reopen, T, W, N, M]
- || T <- [listen, connect], %% watchdog to test
- W <- ?WD_TIMERS, %% watchdog_timer value
- N <- [0,1,2], %% DWR's to answer before ignoring
- M <- ['DWR', 'DWA', 'RAA']]). %% how to induce failback
+ ?util:run([{?MODULE, reopen, [T, W, N, M]}
+ || T <- [listen, connect], %% watchdog to test
+ W <- ?WD_TIMERS, %% watchdog_timer value
+ N <- [0,1,2], %% DWR's to answer before ignoring
+ M <- ['DWR', 'DWA', 'RAA']]). %% how to induce failback
reopen(Test, Wd, N, M) ->
%% Publish a ref ensure the connecting transport is added only
%% once events from the listening transport are subscribed to.
Ref = make_ref(),
- [] = run([[reopen, T, Test, Ref, Wd, N, M] || T <- [listen, connect]]).
+ ?util:run([{?MODULE, reopen, [T, Test, Ref, Wd, N, M]}
+ || T <- [listen, connect]]).
%% reopen/6
@@ -377,14 +403,14 @@ tpid(Ref, [[{ref, Ref},
TPid.
%% ===========================================================================
-%% # suspect/1
+%% # suspect/0
%% ===========================================================================
%% Configure transports to require a set number of watchdog timeouts
%% before moving from OKAY to SUSPECT.
-suspect(_) ->
- [] = run([[abuse, [suspect, N]] || N <- [0,1,3]]).
+suspect() ->
+ ?util:run([{?MODULE, abuse, [[suspect, N]]} || N <- [0,1,3]]).
suspect(Type, Fake, Ref, N)
when is_reference(Ref) ->
@@ -417,7 +443,7 @@ suspect(TRef, false, SvcName, N) ->
%% abuse/1
abuse(F) ->
- [] = run([[abuse, F, T] || T <- [listen, connect]]).
+ ?util:run([{?MODULE, abuse, [F, T]} || T <- [listen, connect]]).
abuse(F, [_,_,_|_] = Args) ->
?LOG("~p", [Args]),
@@ -425,21 +451,21 @@ abuse(F, [_,_,_|_] = Args) ->
abuse([F|A], Test) ->
Ref = make_ref(),
- [] = run([[abuse, F, [T, T == Test, Ref] ++ A]
- || T <- [listen, connect]]);
+ ?util:run([{?MODULE, abuse, [F, [T, T == Test, Ref] ++ A]}
+ || T <- [listen, connect]]);
abuse(F, Test) ->
abuse([F], Test).
%% ===========================================================================
-%% # okay/1
+%% # okay/0
%% ===========================================================================
%% Configure the number of watchdog exchanges before moving from
%% REOPEN to OKAY.
-okay(_) ->
- [] = run([[abuse, [okay, N]] || N <- [0,2,3]]).
+okay() ->
+ ?util:run([{?MODULE, abuse, [[okay, N]]} || N <- [0,2,3]]).
okay(Type, Fake, Ref, N)
when is_reference(Ref) ->
@@ -626,23 +652,6 @@ choose(false, _, X) -> X.
id(T) ->
T.
-%% run/1
-%%
-%% A more useful badmatch in case of failure.
-
-run(Fs) ->
- ?util:run([{?MODULE, [run1, F]} || F <- Fs]).
-
-run1([F|A]) ->
- ok = try
- apply(?MODULE, F, A),
- ok
- catch
- E:R:Stack ->
- ?WARN("~p", [{A, E, R, Stack}]),
- Stack
- end.
-
%% jitter/2
jitter(?WD(T), _) ->
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index 90b0a25d5f..fb8cfc445c 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -1,7 +1,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2019. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
#
# %CopyrightEnd%
-TEST_SPEC_FILE = diameter.spec
+TEST_SPEC_FILE = diameter.spec diameter_gh.spec
COVER_SPEC_FILE = diameter.cover
MODULES = \
@@ -50,9 +50,6 @@ MODULES = \
diameter_transport_SUITE \
diameter_watchdog_SUITE
-HRL_FILES = \
- diameter_ct.hrl
-
DATA = \
diameter_codec_SUITE_data/avps.dia \
diameter_codec_SUITE_data/send.dia \
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 0aafdde57c..5eda96f384 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 2.2.5
+DIAMETER_VSN = 2.2.7
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/edoc/bin/Makefile b/lib/edoc/bin/Makefile
index d87c08356f..699c3321d3 100644
--- a/lib/edoc/bin/Makefile
+++ b/lib/edoc/bin/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ ESCRIPT_FILES= \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/edoc/doc/Makefile b/lib/edoc/doc/Makefile
index c635f07d78..0be38971c4 100644
--- a/lib/edoc/doc/Makefile
+++ b/lib/edoc/doc/Makefile
@@ -57,7 +57,7 @@ info:
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 849a816257..a3a89e6810 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -32,6 +32,45 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix unused types warnings in internal edoc module.</p>
+ <p>
+ Own Id: OTP-17550 Aux Id: GH-5094 PR-5106 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add source file to the warning on skipped tags when
+ generating EEP-48 style docs.</p>
+ <p>
+ Own Id: OTP-17556 Aux Id: PR-5023 </p>
+ </item>
+ <item>
+ <p>
+ Fix the doc chunks generators to emit documentation even
+ if there is not module level documentation.</p>
+ <p>
+ Fix the doc chunks generators to respect the
+ <c>@hidden</c> and <c>@private</c> tags properly for both
+ modules and functions.</p>
+ <p>
+ Own Id: OTP-17733 Aux Id: PR-5205 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 1.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/edoc/include/Makefile b/lib/edoc/include/Makefile
index 6318253c27..a3bfd0568f 100644
--- a/lib/edoc/include/Makefile
+++ b/lib/edoc/include/Makefile
@@ -37,7 +37,7 @@ INCLUDE_FILES = edoc_doclet.hrl
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/edoc/priv/Makefile b/lib/edoc/priv/Makefile
index 45bff37b39..66846fad21 100644
--- a/lib/edoc/priv/Makefile
+++ b/lib/edoc/priv/Makefile
@@ -23,7 +23,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/edoc-$(EDOC_VSN)
GEN_SCRIPT = edoc_generate
PRIV_FILES = stylesheet.css erlang.png edoc.dtd
-debug opt:
+$(TYPES):
clean:
rm -f core *~
diff --git a/lib/edoc/src/Makefile b/lib/edoc/src/Makefile
index 8acef15248..a455662049 100644
--- a/lib/edoc/src/Makefile
+++ b/lib/edoc/src/Makefile
@@ -49,7 +49,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# Targets
# ----------------------------------------------------
-debug opt: $(OBJECTS)
+$(TYPES): $(OBJECTS)
all: $(OBJECTS)
diff --git a/lib/edoc/src/edoc.app.src b/lib/edoc/src/edoc.app.src
index 0edee67fce..079be93e9e 100644
--- a/lib/edoc/src/edoc.app.src
+++ b/lib/edoc/src/edoc.app.src
@@ -26,6 +26,6 @@
{registered,[]},
{applications, [compiler, kernel, stdlib, syntax_tools]},
{env, []},
- {runtime_dependencies, ["xmerl-1.3.7", "syntax_tools-1.6.14", "stdlib-3.15",
+ {runtime_dependencies, ["xmerl-1.3.7", "syntax_tools-2.0", "stdlib-3.15",
"kernel-3.0", "inets-5.10", "erts-6.0"]}
]}.
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index b1cf537f07..8ff27b9759 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -562,7 +562,7 @@ read_comments(File) ->
%% @doc Extracts comments from an Erlang source code file. See the
%% module {@link //syntax_tools/erl_comment_scan} for details on the
-%% representation of comments. Currently, no options are avaliable.
+%% representation of comments. Currently, no options are available.
-spec read_comments(File, Opts) -> [comment()] when
File :: filename(),
diff --git a/lib/edoc/src/edoc_doclet_chunks.erl b/lib/edoc/src/edoc_doclet_chunks.erl
index 50eb4086b6..d619df2f0a 100644
--- a/lib/edoc/src/edoc_doclet_chunks.erl
+++ b/lib/edoc/src/edoc_doclet_chunks.erl
@@ -89,11 +89,8 @@ gen(Sources, _App, Modules, Ctxt) ->
sources(Sources, Dir, Modules, Env, Options) ->
Suffix = proplists:get_value(file_suffix, Options, ?DEFAULT_FILE_SUFFIX),
- Private = proplists:get_bool(private, Options),
- Hidden = proplists:get_bool(hidden, Options),
{Ms, E} = lists:foldl(fun (Src, {Set, Error}) ->
- source(Src, Dir, Suffix, Env, Set,
- Private, Hidden, Error, Options)
+ source(Src, Dir, Suffix, Env, Set, Error, Options)
end,
{sets:new(), false}, Sources),
{[M || M <- Modules, sets:is_element(M, Ms)], E}.
@@ -104,10 +101,17 @@ sources(Sources, Dir, Modules, Env, Options) ->
%% Add its name to the set if it was successful.
%% Errors are just flagged at this stage,
%% allowing all source files to be processed even if some of them fail.
-source({_M, Name, Path}, Dir, Suffix, Env, OkSet, _Private, _Hidden, ErrorFlag, Options) ->
+source({_M, Name, Path}, Dir, Suffix, Env, OkSet, ErrorFlag, Options0) ->
File = filename:join(Path, Name),
try
- {_Module, Doc, Entries} = edoc:get_doc(File, Env, [return_entries, private, hidden | Options]),
+ %% Without these opts the entries returned by EDoc core (`edoc_extract:source1/5') won't have
+ %% all the necessary data to generate chunks.
+ RequiredChunkOpts = [return_entries, private, hidden],
+ %% But we also want to have the real user-defined `private' accessible.
+ Options = ([{show_private, proplists:get_bool(private, Options0)}]
+ ++ RequiredChunkOpts
+ ++ Options0),
+ {_Module, Doc, Entries} = edoc:get_doc(File, Env, Options),
Chunk = edoc:layout(Doc, [{entries, Entries}, {source, Name} | Options]),
WriteOptions = [{encoding, utf8}],
ok = write_file(Chunk, Dir, chunk_file_name(Name, Suffix), WriteOptions),
diff --git a/lib/edoc/src/edoc_layout_chunks.erl b/lib/edoc/src/edoc_layout_chunks.erl
index 570511c754..e325346b56 100644
--- a/lib/edoc/src/edoc_layout_chunks.erl
+++ b/lib/edoc/src/edoc_layout_chunks.erl
@@ -135,29 +135,34 @@ edoc_to_chunk(Doc, Opts) ->
Opts :: proplists:proplist().
doc_contents(XPath, Doc, Opts) ->
case doc_visibility(XPath, Doc, Opts) of
- hidden -> hidden;
none -> none;
- regular -> doc_contents_(XPath, Doc, Opts)
+ hidden -> hidden;
+ show -> doc_contents_(XPath, Doc, Opts)
end.
+-spec doc_visibility(_, _, _) -> none | hidden | show.
doc_visibility(_XPath, Doc, Opts) ->
case {xpath_to_text("./@private", Doc, Opts),
+ proplists:get_bool(show_private, Opts),
xpath_to_text("./@hidden", Doc, Opts)}
of
- {<<"yes">>, _} ->
- %% EDoc `@private' is EEP-48 `hidden'
+ %% Generating `@private' documentation was explicitly requested
+ {<<"yes">>, true, _} ->
+ show;
+ %% EDoc `@private' maps to EEP-48 `hidden'
+ {<<"yes">>, _, _} ->
hidden;
- {_, <<"yes">>} ->
- %% EDoc `@hidden' is EEP-48 `none'
+ %% EDoc `@hidden' is EEP-48 `none'
+ {_, _, <<"yes">>} ->
none;
_ ->
- regular
+ show
end.
doc_contents_(_XPath, Doc, Opts) ->
- Equiv = xpath_to_chunk("./equiv", Doc),
- Desc = xpath_to_chunk("./description/fullDescription", Doc),
- See = xpath_to_chunk("./see", Doc),
+ Equiv = xpath_to_chunk("./equiv", Doc, Opts),
+ Desc = xpath_to_chunk("./description/fullDescription", Doc, Opts),
+ See = xpath_to_chunk("./see", Doc, Opts),
doc_content(Equiv ++ Desc ++ See, Opts).
meta_deprecated(Doc, Opts) ->
@@ -226,7 +231,7 @@ callback(Cb = #tag{name = callback, origin = code}, Opts) ->
form = Form} = Cb,
EntryDoc = case MaybeDoc of
none -> none;
- _ -> doc_content([xmerl_to_binary(MaybeDoc)], Opts)
+ _ -> doc_content([xmerl_to_binary(MaybeDoc, Opts)], Opts)
end,
{source, File} = lists:keyfind(source, 1, Opts),
Anno = erl_anno:set_file(File, erl_anno:new(Line)),
@@ -449,7 +454,7 @@ source_file(Opts) ->
Source.
-spec doc_content(_, _) -> doc().
-doc_content([], _Opts) -> none;
+doc_content([], _Opts) -> #{};
doc_content(Content, Opts) ->
DocLanguage = proplists:get_value(lang, Opts, <<"en">>),
#{DocLanguage => Content}.
@@ -477,13 +482,13 @@ xpath_to_text(XPath, Doc, Opts) ->
{_ , Value} = format_attribute(Attr),
hd(shell_docs:normalize([Value]));
[#xmlElement{}] = Elements ->
- xmerl_to_binary(Elements);
+ xmerl_to_binary(Elements, Opts);
[_|_] ->
erlang:error(multiple_nodes, [XPath, Doc, Opts])
end.
-xmerl_to_binary(XML) ->
- iolist_to_binary(chunk_to_text(xmerl_to_chunk(XML))).
+xmerl_to_binary(XML, Opts) ->
+ iolist_to_binary(chunk_to_text(xmerl_to_chunk(XML, Opts))).
chunk_to_text([]) -> [];
chunk_to_text([Node | Nodes]) ->
@@ -498,53 +503,53 @@ xpath_to_atom(XPath, Doc, Opts) ->
xpath_to_integer(XPath, Doc, Opts) ->
binary_to_integer(xpath_to_text(XPath, Doc, Opts)).
-xpath_to_chunk(XPath, Doc) ->
+xpath_to_chunk(XPath, Doc, Opts) ->
XmerlDoc = xmerl_xpath:string(XPath, Doc),
- xmerl_to_chunk(XmerlDoc).
+ xmerl_to_chunk(XmerlDoc, Opts).
%%.
%%' Xmerl to chunk format
%%
--spec xmerl_to_chunk([xmerl_doc_node()]) -> shell_docs:chunk_elements().
-xmerl_to_chunk(Contents) ->
- shell_docs:normalize(format_content(Contents)).
+-spec xmerl_to_chunk([xmerl_doc_node()], proplists:proplist()) -> shell_docs:chunk_elements().
+xmerl_to_chunk(Contents, Opts) ->
+ shell_docs:normalize(format_content(Contents, Opts)).
--spec format_content([xmerl_doc_node()]) -> shell_docs:chunk_elements().
-format_content(Contents) ->
+-spec format_content([xmerl_doc_node()], proplists:proplist()) -> shell_docs:chunk_elements().
+format_content(Contents, Opts) ->
{SeeTags, OtherTags} = lists:partition(fun (#xmlElement{name = see}) -> true;
(_) -> false end,
Contents),
- lists:flatten([ format_content_(T) || T <- OtherTags ] ++ rewrite_see_tags(SeeTags)).
+ lists:flatten([ format_content_(T, Opts) || T <- OtherTags ] ++ rewrite_see_tags(SeeTags, Opts)).
--spec format_content_(xmerl_doc_node()) -> shell_docs:chunk_elements().
-format_content_(#xmlPI{}) -> [];
-format_content_(#xmlComment{}) -> [];
+-spec format_content_(xmerl_doc_node(), proplists:proplist()) -> shell_docs:chunk_elements().
+format_content_(#xmlPI{}, _) -> [];
+format_content_(#xmlComment{}, _) -> [];
-format_content_(#xmlText{} = T) ->
+format_content_(#xmlText{} = T, _) ->
Text = T#xmlText.value,
case edoc_lib:is_space(Text) of
true -> [];
false -> [unicode:characters_to_binary(Text)]
end;
-format_content_(#xmlElement{name = equiv} = E) ->
- format_element(rewrite_equiv_tag(E));
-format_content_(#xmlElement{name = a} = E) ->
- format_element(rewrite_a_tag(E));
-format_content_(#xmlElement{} = E) ->
- format_element(E).
+format_content_(#xmlElement{name = equiv} = E, Opts) ->
+ format_element(rewrite_equiv_tag(E), Opts);
+format_content_(#xmlElement{name = a} = E, Opts) ->
+ format_element(rewrite_a_tag(E), Opts);
+format_content_(#xmlElement{} = E, Opts) ->
+ format_element(E, Opts).
-format_element(#xmlElement{} = E) ->
+format_element(#xmlElement{} = E, Opts) ->
#xmlElement{name = Name, content = Content, attributes = Attributes} = E,
case {is_edoc_tag(Name), is_html_tag(Name)} of
{true, _} ->
- format_content(Content);
+ format_content(Content, Opts);
{_, false} ->
- edoc_report:warning("'~s' is not allowed - skipping tag, extracting content", [Name]),
- format_content(Content);
+ edoc_report:warning(0, source_file(Opts), "'~s' is not allowed - skipping tag, extracting content", [Name]),
+ format_content(Content, Opts);
_ ->
- [{Name, format_attributes(Attributes), format_content(Content)}]
+ [{Name, format_attributes(Attributes), format_content(Content, Opts)}]
end.
-spec format_attributes([xmerl_attribute()]) -> [shell_docs:chunk_element_attr()].
@@ -575,12 +580,12 @@ rewrite_a_tag(#xmlElement{name = a} = E) ->
SimpleE = xmerl_lib:simplify_element(E),
xmerl_lib:normalize_element(rewrite_docgen_link(SimpleE)).
-rewrite_see_tags([]) -> [];
-rewrite_see_tags([#xmlElement{name = see} | _] = SeeTags) ->
+rewrite_see_tags([], _Opts) -> [];
+rewrite_see_tags([#xmlElement{name = see} | _] = SeeTags, Opts) ->
Grouped = [ rewrite_see_tag(T) || T <- SeeTags ],
NewXML = {p, [], [{em,[],["See also: "]}] ++ lists:join(", ", Grouped) ++ ["."]},
%% Convert strings to binaries in the entire new tree:
- [format_content_(xmerl_lib:normalize_element(NewXML))].
+ [format_content_(xmerl_lib:normalize_element(NewXML), Opts)].
rewrite_see_tag(#xmlElement{name = see} = E) ->
%% TODO: this is not formatted nicely by shell_docs...
diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl
index 005c062e23..e467b98a00 100644
--- a/lib/edoc/src/edoc_tags.erl
+++ b/lib/edoc/src/edoc_tags.erl
@@ -340,6 +340,7 @@ parse_contact(Data, Line, _Env, _Where) ->
Info
end.
+-dialyzer({no_match, parse_typedef/4}).
parse_typedef(Data, Line, _Env, Where) ->
edoc_report:warning(Line, Where,
"EDoc @type tags are deprecated. "
diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl
index fd427b2c1a..94e8db5749 100644
--- a/lib/edoc/src/edoc_types.erl
+++ b/lib/edoc/src/edoc_types.erl
@@ -39,9 +39,9 @@
-include("edoc_types.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-%-type t_spec() :: #t_spec{name :: t_name(),
-% type :: t_type(),
-% defs :: [t_def()]}.
+-type t_spec() :: #t_spec{name :: t_name(),
+ type :: t_fun(),
+ defs :: [t_def()]}.
%% Function specification.
-type type() :: t_atom() | t_binary() | t_float() | t_fun() | t_integer()
@@ -49,18 +49,18 @@
| t_record() | t_tuple() | t_type() | t_union() | t_var()
| t_paren().
-%-type t_typedef() :: #t_typedef{name :: t_name(),
-% args :: [type()],
-% type :: type() | undefined,
-% defs :: [t_def()]}.
+-type t_typedef() :: #t_typedef{name :: t_name(),
+ args :: [type()],
+ type :: type() | undefined,
+ defs :: [t_def()]}.
%% Type declaration/definition.
-%-type t_throws() :: #t_throws{type :: type(),
-% defs :: [t_def()]}.
+-type t_throws() :: #t_throws{type :: type(),
+ defs :: [t_def()]}.
%% Exception declaration.
-%-type t_def() :: #t_def{name :: t_type() | t_var(),
-% type :: type()}.
+-type t_def() :: #t_def{name :: t_type() | t_var(),
+ type :: type()}.
%% Local definition `name = type'.
-type t_name() :: #t_name{app :: [] | atom(),
@@ -137,11 +137,9 @@ is_predefined(cons, 2) -> true;
is_predefined(deep_string, 0) -> true;
is_predefined(F, A) -> erl_internal:is_type(F, A).
-is_new_predefined(nonempty_binary, 0) -> true;
-is_new_predefined(nonempty_bitstring, 0) -> true;
-is_new_predefined(map, 0) -> true;
is_new_predefined(_, _) -> false.
+-spec to_ref(t_typedef() | t_def() | t_type() | t_name()) -> edoc_refs:t().
to_ref(#t_typedef{name = N}) ->
to_ref(N);
to_ref(#t_def{name = N}) ->
@@ -172,6 +170,8 @@ infer_module_app(#t_name{app = [], module = M} = TName) when is_atom(M) ->
infer_module_app(Other) ->
Other.
+-spec to_xml(type() | t_spec() | t_typedef() | t_def() | t_throws(),
+ term(), Opts :: proplists:proplist()) -> term().
to_xml(#t_var{name = N}, _Env, _Opts) ->
{typevar, [{name, atom_to_list(N)}], []};
to_xml(#t_name{module = [], name = N}, _Env, _Opts) ->
diff --git a/lib/edoc/src/edoc_wiki.erl b/lib/edoc/src/edoc_wiki.erl
index 574880703c..903d69e84c 100644
--- a/lib/edoc/src/edoc_wiki.erl
+++ b/lib/edoc/src/edoc_wiki.erl
@@ -42,7 +42,7 @@
%% and the resulting text easier to read. The wiki notation should be a
%% small bag of easy-to-remember tricks for making XHTML documentation
%% easier to write, not a complete markup language in itself. As a
-%% typical example, it is hardly worthwile to introduce a special
+%% typical example, it is hardly worthwhile to introduce a special
%% notation like say, ""..."" for emphasized text, since <em>...</em> is
%% not much harder to write, not any less readable, and no more
%% difficult to remember, especially since emphasis is not very often
diff --git a/lib/edoc/test/Makefile b/lib/edoc/test/Makefile
index ecc93e32be..139ba8b8bd 100644
--- a/lib/edoc/test/Makefile
+++ b/lib/edoc/test/Makefile
@@ -27,6 +27,7 @@ RELSYSDIR = $(RELEASE_PATH)/edoc_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -40,7 +41,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
>> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 2dec3951e3..f8feac1c37 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 1.1
+EDOC_VSN = 1.2
diff --git a/lib/eldap/doc/src/eldap.xml b/lib/eldap/doc/src/eldap.xml
index 2af599751c..b3b8dc0a9b 100644
--- a/lib/eldap/doc/src/eldap.xml
+++ b/lib/eldap/doc/src/eldap.xml
@@ -548,8 +548,19 @@ Control2 = eldap:paged_result_control(PageSize, Cookie1),
the series.</p>
</desc>
</func>
+ <func>
+ <name since="OTP @OTP-18480@">info(Handle) -> connection_info()</name>
+ <fsummary>Returns information about the LDAP connection.
+ </fsummary>
+ <type>
+ <v>connection_info() = #{socket := Socket, socket_type := tcp | ssl}</v>
+ <v>Socket = ssl:sslsocket() | gen_tcp:socket()</v>
+ </type>
+ <desc><p>Currently available information reveals the socket and the transport
+ protocol, TCP or TLS (SSL), used by the LDAP connection.</p>
+ </desc>
+ </func>
</funcs>
</erlref>
-
diff --git a/lib/eldap/src/Makefile b/lib/eldap/src/Makefile
index b79a537424..04a84a4766 100644
--- a/lib/eldap/src/Makefile
+++ b/lib/eldap/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2012-2016. All Rights Reserved.
+# Copyright Ericsson AB 2012-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -67,8 +67,8 @@ ERL_COMPILE_FLAGS += -I../include -I../ebin -Werror
# ----------------------------------------------------
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
clean:
rm -f $(TARGET_FILES) $(GEN_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/eldap/src/eldap.app.src b/lib/eldap/src/eldap.app.src
index 03a7d7c562..032a391936 100644
--- a/lib/eldap/src/eldap.app.src
+++ b/lib/eldap/src/eldap.app.src
@@ -5,6 +5,6 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["stdlib-2.0","ssl-5.3.4","kernel-3.0","erts-6.0",
+ {runtime_dependencies, ["stdlib-3.4","ssl-5.3.4","kernel-3.0","erts-6.0",
"asn1-3.0"]}
]}.
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index 22d816c8c8..7edd012263 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -30,7 +30,8 @@
parse_ldap_url/1,
paged_result_control/1,
paged_result_control/2,
- paged_result_cookie/1]).
+ paged_result_cookie/1,
+ info/1]).
-export([neverDerefAliases/0, derefInSearching/0,
derefFindingBaseObj/0, derefAlways/0]).
@@ -155,6 +156,13 @@ controlling_process(Handle, Pid) when is_pid(Handle), is_pid(Pid) ->
recv(Handle).
%%% --------------------------------------------------------------------
+%%% Return LDAP socket information
+%%% --------------------------------------------------------------------
+info(Handle) when is_pid(Handle) ->
+ send(Handle, info),
+ recv(Handle).
+
+%%% --------------------------------------------------------------------
%%% Authenticate ourselves to the Directory
%%% using simple authentication.
%%%
@@ -608,6 +616,18 @@ loop(Cpid, Data) ->
send(From, Result),
?MODULE:loop(Cpid, Data);
+ {From, info} ->
+ SocketType =
+ case Data#eldap.ldaps of
+ true ->
+ ssl;
+ false ->
+ tcp
+ end,
+ Res = #{socket => Data#eldap.fd, socket_type => SocketType},
+ send(From, Res),
+ ?MODULE:loop(Cpid, Data);
+
{Cpid, 'EXIT', Reason} ->
?PRINT("Got EXIT from Cpid, reason=~p~n",[Reason]),
exit(Reason);
@@ -618,7 +638,6 @@ loop(Cpid, Data) ->
end.
-
%%% --------------------------------------------------------------------
%%% startTLS Request
%%% --------------------------------------------------------------------
diff --git a/lib/eldap/test/Makefile b/lib/eldap/test/Makefile
index 81fa8f187a..61cad55c64 100644
--- a/lib/eldap/test/Makefile
+++ b/lib/eldap/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2012-2016. All Rights Reserved.
+# Copyright Ericsson AB 2012-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ RELSYSDIR = $(RELEASE_PATH)/eldap_test
# FLAGS
# ----------------------------------------------------
ERL_COMPILE_FLAGS += $(INCLUDES) -pa $(ERL_TOP)/lib/eldap/ebin
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -61,7 +62,7 @@ EBIN = .
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
clean:
diff --git a/lib/eldap/test/eldap_basic_SUITE.erl b/lib/eldap/test/eldap_basic_SUITE.erl
index 5fa6d4ca69..2b26ed52bd 100644
--- a/lib/eldap/test/eldap_basic_SUITE.erl
+++ b/lib/eldap/test/eldap_basic_SUITE.erl
@@ -46,6 +46,7 @@
more_add/1,
open_ret_val_error/1,
open_ret_val_success/1,
+ plain_ldap_socket_info/1,
search_filter_and/1,
search_filter_and_not/1,
search_filter_equalityMatch/1,
@@ -63,6 +64,7 @@
search_extensible_match_without_dn/1,
search_paged_results/1,
ssl_connection/1,
+ ssl_conn_socket_info/1,
start_tls_on_ssl_should_fail/1,
start_tls_twice_should_fail/1,
tcp_connection/1,
@@ -81,8 +83,8 @@
suite/0
]).
-%%-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
-include_lib("eldap/include/eldap.hrl").
-include_lib("eldap/ebin/ELDAPv3.hrl").
@@ -159,7 +161,9 @@ connection_tests() ->
client_side_bind_timeout,
client_side_add_timeout,
client_side_search_timeout,
- close_after_tcp_error
+ close_after_tcp_error,
+ ssl_conn_socket_info,
+ plain_ldap_socket_info
].
@@ -259,7 +263,7 @@ end_per_group(start_tls_api, Config) -> clear_db(Config);
end_per_group(_Group, Config) -> Config.
-init_per_testcase(ssl_connection, Config) ->
+init_per_testcase(TC, Config) when TC == ssl_connection; TC == ssl_conn_socket_info ->
case proplists:get_value(ssl_available,Config) of
true ->
SSL_Port = 9999,
@@ -423,6 +427,35 @@ ssl_connection(Config) ->
end.
%%%----------------------------------------------------------------
+ssl_conn_socket_info(Config) ->
+ Host = proplists:get_value(listen_host, Config),
+ Port = proplists:get_value(ssl_listen_port, Config),
+ Opts = proplists:get_value(tcp_connect_opts, Config),
+ SSLOpts = proplists:get_value(ssl_connect_opts, Config),
+ case eldap:open([Host], [{port,Port},
+ {ssl,true},
+ {timeout,5000},
+ {sslopts,SSLOpts}|Opts]) of
+ {ok,H} ->
+ #{socket := Socket, socket_type := ssl} = eldap:info(H),
+ ?assertMatch({ok, _Data}, ssl:connection_information(Socket));
+ Other -> ct:fail("eldap:open failed: ~p",[Other])
+ end.
+
+%%%----------------------------------------------------------------
+plain_ldap_socket_info(Config) ->
+ Host = proplists:get_value(listen_host, Config),
+ Port = proplists:get_value(listen_port, Config),
+ Opts = proplists:get_value(tcp_connect_opts, Config),
+ T = 1000,
+ case eldap:open([Host], [{timeout,T},{port,Port}|Opts]) of
+ {ok,H} ->
+ ?assertMatch(#{socket := _, socket_type := tcp},
+ eldap:info(H));
+ Other -> ct:fail("eldap:open failed: ~p",[Other])
+ end.
+
+%%%----------------------------------------------------------------
client_side_add_timeout(Config) ->
client_timeout(
fun(H) ->
diff --git a/lib/erl_docgen/doc/src/doc_storage.xml b/lib/erl_docgen/doc/src/doc_storage.xml
index cc6cf5d549..6f88e36e20 100644
--- a/lib/erl_docgen/doc/src/doc_storage.xml
+++ b/lib/erl_docgen/doc/src/doc_storage.xml
@@ -34,7 +34,7 @@
<p><seeguide marker="kernel:eep48_chapter">EEP-48</seeguide>
defines a common documentation storage format for module documentation in the Erlang/OTP
ecosystem. Erl_Docgen can generate documentation in this format from XML files following
- the DTD's descibed in the other User's Guides in this application.</p>
+ the DTD's described in the other User's Guides in this application.</p>
<p>Some special considerations have to be taken when writing documentation that
should also be available through EEP-48 style storage.</p>
<list>
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 797efb5216..92726daa8a 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -31,7 +31,55 @@
</header>
<p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 1.2.1</title>
+ <section><title>Erl_Docgen 1.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update DTD to allow XML tag <c>em</c> under <c>pre</c>.</p>
+ <p>
+ Own Id: OTP-18244</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix types that are not derived from code to display the
+ correct information in EEP-48 style documentation chunks.</p>
+ <p>
+ Own Id: OTP-18084 Aux Id: PR-5948 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Any exported, but private function or module in
+ Erlang/OTP now generate an EEP-48 style documentation
+ entry with the content set to hidden.</p>
+ <p>
+ Before this change, exported but private functions and
+ modules did not have any entry at all.</p>
+ <p>
+ Own Id: OTP-17669 Aux Id: PR-5226 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 1.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/erl_docgen/priv/bin/Makefile b/lib/erl_docgen/priv/bin/Makefile
index 9ccb84b9c6..2bd1ddc22c 100644
--- a/lib/erl_docgen/priv/bin/Makefile
+++ b/lib/erl_docgen/priv/bin/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@ ESCRIPT_FILES= \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/erl_docgen/priv/bin/github_link.escript b/lib/erl_docgen/priv/bin/github_link.escript
index e0f5a2f471..c554c73a3d 100755
--- a/lib/erl_docgen/priv/bin/github_link.escript
+++ b/lib/erl_docgen/priv/bin/github_link.escript
@@ -2,7 +2,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ sub([], _Pat, _Fn, _Sha, _Cnt) ->
sub([H|T], Pat, Fn, Sha, Cnt) ->
%% We use the maint branch here, it is not as exact as the tag,
%% but it is the best we can do as github does not allow doing
- %% pullrequests on anything but branches.
+ %% pull requests on anything but branches.
[re:replace(H,["<",Pat,">"],
["<",Pat," ghlink=\"maint/",Fn,"#L",
integer_to_list(Cnt),"\">"],[{return,list}]) |
diff --git a/lib/erl_docgen/priv/bin/validate_links.escript b/lib/erl_docgen/priv/bin/validate_links.escript
index a11350ad2f..2373a08b29 100755
--- a/lib/erl_docgen/priv/bin/validate_links.escript
+++ b/lib/erl_docgen/priv/bin/validate_links.escript
@@ -3,7 +3,7 @@
%%! +A 1 +SDio 1 +S 1 -mode minimal
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -231,14 +231,19 @@ validate_link(Filename, "seemfa", Line, Link, CachedFiles) ->
try list_to_integer(Arity) of
_ ->
MF = App ++ ":" ++ Mod ++ "#" ++ Func,
- Funcs = maps:get(funcs,maps:get({App,Mod},CachedFiles)),
- case lists:member({Func,Arity},Funcs) of
- true ->
- validate_type(Line, "seemfa",
- read_link(Line, ParsedLink, CachedFiles));
- false ->
- fail(Line, "Could not find documentation for ~s when "
- "resolving link",[MF ++ "/" ++ Arity])
+ case maps:find({App,Mod},CachedFiles) of
+ error ->
+ fail(Line, "Could not find ~ts in ~ts", [Mod, App]);
+ {ok, ModInfo} ->
+ Funcs = maps:get(funcs,ModInfo),
+ case lists:member({Func,Arity},Funcs) of
+ true ->
+ validate_type(Line, "seemfa",
+ read_link(Line, ParsedLink, CachedFiles));
+ false ->
+ fail(Line, "Could not find documentation for ~s when "
+ "resolving link",[MF ++ "/" ++ Arity])
+ end
end
catch _:_ ->
fail(Line, "Invalid arity for seemfa. "
diff --git a/lib/erl_docgen/priv/css/Makefile b/lib/erl_docgen/priv/css/Makefile
index 7f24128753..d80172b887 100644
--- a/lib/erl_docgen/priv/css/Makefile
+++ b/lib/erl_docgen/priv/css/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ CSS_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
DOC_TARGETS?=html
diff --git a/lib/erl_docgen/priv/dtd/Makefile b/lib/erl_docgen/priv/dtd/Makefile
index bed1827dac..84e61320b1 100644
--- a/lib/erl_docgen/priv/dtd/Makefile
+++ b/lib/erl_docgen/priv/dtd/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -70,7 +70,7 @@ ENT_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd
index 9f5bdc50b8..2b7a83aabc 100644
--- a/lib/erl_docgen/priv/dtd/common.dtd
+++ b/lib/erl_docgen/priv/dtd/common.dtd
@@ -29,7 +29,7 @@
marker|anno|image" >
<!-- XXX -->
<!ELEMENT p (%inline;)* >
-<!ELEMENT pre (#PCDATA|%refs;|input|anno)* >
+<!ELEMENT pre (#PCDATA|%refs;|input|anno|em)* >
<!ELEMENT input (#PCDATA|%refs;|anno)* >
<!ELEMENT code (#PCDATA|anno)* >
<!ATTLIST code type (erl|c|none) "none" >
diff --git a/lib/erl_docgen/priv/dtd_html_entities/Makefile b/lib/erl_docgen/priv/dtd_html_entities/Makefile
index c0026bd04d..fd50fed6e5 100644
--- a/lib/erl_docgen/priv/dtd_html_entities/Makefile
+++ b/lib/erl_docgen/priv/dtd_html_entities/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ ENTITY_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/erl_docgen/priv/dtd_man_entities/Makefile b/lib/erl_docgen/priv/dtd_man_entities/Makefile
index c634417e8c..a6565f55d0 100644
--- a/lib/erl_docgen/priv/dtd_man_entities/Makefile
+++ b/lib/erl_docgen/priv/dtd_man_entities/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -49,7 +49,7 @@ ENTITY_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/erl_docgen/priv/images/Makefile b/lib/erl_docgen/priv/images/Makefile
index 03d3e19997..66a3a4dd0a 100644
--- a/lib/erl_docgen/priv/images/Makefile
+++ b/lib/erl_docgen/priv/images/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ PNG_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
DOC_TARGETS?=html
diff --git a/lib/erl_docgen/priv/js/flipmenu/Makefile b/lib/erl_docgen/priv/js/flipmenu/Makefile
index 030b1fa052..f3f657f3a5 100644
--- a/lib/erl_docgen/priv/js/flipmenu/Makefile
+++ b/lib/erl_docgen/priv/js/flipmenu/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -54,7 +54,7 @@ JS_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
DOC_TARGETS?=html
diff --git a/lib/erl_docgen/priv/xsl/Makefile b/lib/erl_docgen/priv/xsl/Makefile
index d381bd4cf7..5a9a947e00 100644
--- a/lib/erl_docgen/priv/xsl/Makefile
+++ b/lib/erl_docgen/priv/xsl/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2018. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ XSL_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
docs:
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index fc02f8fdc5..f47b294ea9 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -752,7 +752,7 @@
<xsl:template match="marker" mode="local_type">
<xsl:param name="local_types"/>
<xsl:param name="global_types"/>
- <!-- Craete no anchor -->
+ <!-- Create no anchor -->
<!-- It would be possible to create a link to the global type
(if there is one), but that would mean even more code...
-->
diff --git a/lib/erl_docgen/src/Makefile b/lib/erl_docgen/src/Makefile
index e4339dcb1f..458094e35f 100644
--- a/lib/erl_docgen/src/Makefile
+++ b/lib/erl_docgen/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ ERL_COMPILE_FLAGS += -I../../xmerl/include
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
index d5511eae9d..4590926fad 100644
--- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
+++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl
@@ -185,7 +185,7 @@ chapter_title(#xmlElement{content=Es}) -> % name = h3 | h4
%% 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>) cannot occur
-%% within a <p>, such a <p> must be splitted into a sequence of <p>,
+%% within a <p>, such a <p> must be split 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
@@ -282,7 +282,7 @@ otp_xmlify_es([E | Es]) ->
otp_xmlify_e(E) ++ otp_xmlify_es(Es);
%% paragraph contained dl, ul and/or pre and has been
- %% splitted
+ %% split
SubEs ->
lists:flatmap(fun otp_xmlify_e/1, SubEs) ++
otp_xmlify_es(Es)
@@ -452,7 +452,7 @@ otp_xmlify_e(E) ->
%%--Tags with special handling------------------------------------------
%% otp_xmlify_a(A1) -> [A2]
-%% Takes an <a> element and filters the attributes to decide wheather
+%% Takes an <a> element and filters the attributes to decide whether
%% 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.
diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl
index 1807c450d8..633353f34c 100644
--- a/lib/erl_docgen/src/docgen_otp_specs.erl
+++ b/lib/erl_docgen/src/docgen_otp_specs.erl
@@ -164,7 +164,7 @@ collect_localdef(E = #xmlElement{content = Es}, Opts) ->
{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.
+%% Names as B above are kept, but the formatted string is empty.
coalesce_local_defs([], _Last) ->
[];
coalesce_local_defs([{Name,N0,TypeS} | L], Last) when Name =:= N0 ->
diff --git a/lib/erl_docgen/src/docgen_xml_to_chunk.erl b/lib/erl_docgen/src/docgen_xml_to_chunk.erl
index c936c58d31..a26412e557 100644
--- a/lib/erl_docgen/src/docgen_xml_to_chunk.erl
+++ b/lib/erl_docgen/src/docgen_xml_to_chunk.erl
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,14 +31,24 @@
main([_Application, FromBeam, _Escript, ToChunk]) ->
%% The given module is not documented, generate a hidden beam chunk file
Name = filename:basename(filename:rootname(FromBeam)) ++ ".erl",
+ {ok, {_Module, [{exports, Exports}]}} = beam_lib:chunks(FromBeam, [exports]),
- EmptyDocs = #docs_v1{ anno = erl_anno:set_file(Name, erl_anno:new(0)),
- module_doc = hidden, docs = []},
+ Anno = erl_anno:set_file(Name, erl_anno:new(0)),
+
+ EmptyDocs = add_hidden_docs(
+ Exports,
+ #docs_v1{ anno = Anno,
+ module_doc = hidden,
+ docs = []}),
ok = file:write_file(ToChunk, term_to_binary(EmptyDocs,[compressed])),
ok;
-main([Application, FromXML, FromBeam, _Escript, ToChunk]) ->
+main([Application, FromXML, FromBeam, Escript, ToChunk]) ->
_ = erlang:process_flag(max_heap_size,20 * 1000 * 1000),
case docs(Application, FromXML, FromBeam) of
+ {error, not_erlref} ->
+ %% The XML files was not a erlref, so we generate
+ %% a hidden entry for this module.
+ main([Application, FromBeam, Escript, ToChunk]);
{error, Reason} ->
io:format("Failed to create chunks: ~p~n",[Reason]),
erlang:halt(1);
@@ -68,7 +78,7 @@ main([Application, FromXML, FromBeam, _Escript, ToChunk]) ->
erlang:halt(1),
ok;
Docs ->
- ok = file:write_file(ToChunk, term_to_binary(Docs,[compressed]))
+ ok = file:write_file(ToChunk, term_to_binary(Docs, [compressed]))
end.
%% Error handling
@@ -269,17 +279,34 @@ docs(Application, OTPXml, FromBEAM)->
{event_state,initial_state()}]) of
{ok,Tree,_} ->
{ok, {Module, Chunks}} = beam_lib:chunks(FromBEAM,[exports,abstract_code]),
- Dom = get_dom(Tree),
- put(application, Application),
- put(module, filename:basename(filename:rootname(FromBEAM))),
- NewDom = transform(Dom,[]),
- Chunk = to_chunk(NewDom, OTPXml, Module, proplists:get_value(abstract_code, Chunks)),
- verify_chunk(Module,proplists:get_value(exports, Chunks), Chunk),
- Chunk;
+ case get_dom(Tree) of
+ [{erlref,_,_}] = Dom ->
+ put(application, Application),
+ put(module, filename:basename(filename:rootname(FromBEAM))),
+ NewDom = transform(Dom, []),
+ Chunk = add_hidden_docs(
+ proplists:get_value(exports, Chunks),
+ to_chunk(NewDom, OTPXml, Module,
+ proplists:get_value(abstract_code, Chunks))),
+ verify_chunk(Module, proplists:get_value(exports, Chunks), Chunk),
+ Chunk;
+ _Else ->
+ {error,not_erlref}
+ end;
Else ->
{error,Else}
end.
+%% Create hidden function entries for any exported functions that
+%% does not have any documentation.
+add_hidden_docs(Exports, #docs_v1{ anno = Anno, docs = Docs } = Chunk) ->
+ HiddenFuncs =
+ [{{function, F, A}, Anno,
+ [iolist_to_binary(io_lib:format("~p/~p", [F, A]))],
+ hidden, #{}} || {F, A} <- Exports, F =/= module_info,
+ lists:keysearch({function, F, A}, 1, Docs) == false ],
+ Chunk#docs_v1{ docs = HiddenFuncs ++ Docs }.
+
verify_chunk(M, Exports, #docs_v1{ docs = Docs } = Doc) ->
%% Make sure that each documented function actually is exported
@@ -685,15 +712,22 @@ to_chunk(Dom, Source, Module, AST) ->
list_to_integer(Arity)
end,
TypeArgs = lists:join(",",[lists:concat(["Arg",I]) || I <- lists:seq(1,TypeArity)]),
- PlaceholderSig = io_lib:format("-type ~p(~s) :: term().",[TypeName,TypeArgs]),
- TypeSignature = proplists:get_value(
- signature,Attr,[iolist_to_binary(PlaceholderSig)]),
- MetaSig =
- case maps:get({TypeName, TypeArity}, TypeMap, undefined) of
+ {TypeSignature, MetaSig} =
+ case proplists:get_value(signature,Attr) of
undefined ->
- #{};
- Sig ->
- #{ signature => [Sig] }
+ PlaceholderSig =
+ iolist_to_binary(
+ io_lib:format("-type ~p(~s) :: term().",
+ [TypeName,TypeArgs])),
+ {[PlaceholderSig],
+ case maps:get({TypeName, TypeArity}, TypeMap, undefined) of
+ undefined ->
+ #{};
+ Sig ->
+ #{ signature => [Sig] }
+ end};
+ Signature ->
+ {Signature, #{}}
end,
MetaDepr
diff --git a/lib/erl_docgen/src/erl_docgen.app.src b/lib/erl_docgen/src/erl_docgen.app.src
index c7b7967a3d..5a6b48bd26 100644
--- a/lib/erl_docgen/src/erl_docgen.app.src
+++ b/lib/erl_docgen/src/erl_docgen.app.src
@@ -10,6 +10,6 @@
{registered,[]},
{applications, [kernel,stdlib]},
{env, []},
- {runtime_dependencies, ["xmerl-1.3.7","kernel-8.0","stdlib-3.15","edoc-1.0","erts-9.0"]}
+ {runtime_dependencies, ["xmerl-1.3.7","kernel-8.0","stdlib-3.15","edoc-1.0","erts-11.0"]}
]
}.
diff --git a/lib/erl_docgen/test/Makefile b/lib/erl_docgen/test/Makefile
index 9e58157023..9af7824553 100644
--- a/lib/erl_docgen/test/Makefile
+++ b/lib/erl_docgen/test/Makefile
@@ -26,6 +26,7 @@ RELSYSDIR = $(RELEASE_PATH)/erl_docgen_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -39,7 +40,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
>> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index e621f3a897..a887c5c839 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 1.2.1
+ERL_DOCGEN_VSN = 1.4
diff --git a/lib/erl_interface/config.h.in b/lib/erl_interface/config.h.in
index 2ec4f66c3b..51d7403824 100644
--- a/lib/erl_interface/config.h.in
+++ b/lib/erl_interface/config.h.in
@@ -1,17 +1,17 @@
-/* config.h.in. Generated from configure.in by autoheader. */
+/* config.h.in. Generated from configure.ac by autoheader. */
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-#undef CRAY_STACKSEG_END
-
-/* Define to 1 if using `alloca.c'. */
+/* Define to 1 if using 'alloca.c'. */
#undef C_ALLOCA
/* Define if 'errno' should not be exposed as is in 'erl_errno' */
#undef EI_HIDE_REAL_ERRNO
/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'dc cvau' instruction, and are compiling for
+ an ARM processor with ARM DC instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION
+
+/* Define as a boolean indicating whether you have a gcc compatible compiler
capable of generating the ARM 'dmb sy' instruction, and are compiling for
an ARM processor with ARM DMB instruction support, or not */
#undef ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION
@@ -26,6 +26,16 @@
an ARM processor with ARM DMB instruction support, or not */
#undef ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION
+/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'ic ivau' instruction, and are compiling for
+ an ARM processor with ARM IC instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION
+
+/* Define as a boolean indicating whether you have a gcc compatible compiler
+ capable of generating the ARM 'isb sy' instruction, and are compiling for
+ an ARM processor with ARM ISB instruction support, or not */
+#undef ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION
+
/* Define as a boolean indicating whether you have a gcc __atomic builtins or
not */
#undef ETHR_HAVE_GCC___ATOMIC_BUILTINS
@@ -74,11 +84,10 @@
__sync_val_compare_and_swap() can handle on your system */
#undef ETHR_HAVE___sync_val_compare_and_swap
-/* Define to 1 if you have `alloca', as a function or macro. */
+/* Define to 1 if you have 'alloca', as a function or macro. */
#undef HAVE_ALLOCA
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
- */
+/* Define to 1 if <alloca.h> works. */
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the <arpa/inet.h> header file. */
@@ -123,18 +132,12 @@
/* Define to 1 if you have the `gmp' library (-lgmp). */
#undef HAVE_LIBGMP
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
/* Define to 1 if you have the `resolv' library (-lresolv). */
#undef HAVE_LIBRESOLV
/* Define to 1 if you have the `rt' library (-lrt). */
#undef HAVE_LIBRT
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
@@ -147,9 +150,6 @@
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
@@ -180,6 +180,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -284,16 +287,15 @@
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
#undef STDC_HEADERS
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#undef TIME_WITH_SYS_TIME
-
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
diff --git a/lib/erl_interface/configure b/lib/erl_interface/configure
index 50c4b6396e..acfd569e30 100755
--- a/lib/erl_interface/configure
+++ b/lib/erl_interface/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +430,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +459,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +503,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +517,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +534,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,49 +606,46 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
-
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="include/ei.h"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
DED_OSTYPE
DED_LIBS
@@ -650,10 +678,10 @@ INSTALL_SCRIPT
INSTALL_PROGRAM
AR
ARCH
-EGREP
-GREP
LD
RANLIB
+EGREP
+GREP
CPP
OBJEXT
EXEEXT
@@ -664,6 +692,10 @@ CFLAGS
CC
DYNAMIC_LIB
TARGET
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -797,8 +829,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -839,9 +869,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -865,9 +895,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1078,9 +1108,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1094,9 +1124,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1140,9 +1170,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1158,7 +1188,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1222,7 +1252,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1340,6 +1370,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1392,9 +1423,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1422,7 +1453,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1430,7 +1462,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1440,9 +1472,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1459,14 +1491,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1474,14 +1506,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1503,7 +1536,7 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1511,14 +1544,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1530,8 +1564,8 @@ fi
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
@@ -1541,25 +1575,26 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
@@ -1584,7 +1619,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -1594,14 +1629,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1611,9 +1647,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -1621,14 +1658,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -1638,14 +1675,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -1655,9 +1693,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -1665,14 +1704,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -1680,7 +1719,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1690,12 +1729,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -1705,12 +1745,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -1738,9 +1778,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -1760,26 +1801,28 @@ rm -f conftest.val
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
@@ -1790,14 +1833,14 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1805,17 +1848,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1830,93 +1874,6 @@ fi
} # ac_fn_c_try_link
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
@@ -1924,17 +1881,18 @@ fi
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof ($2))
return 0;
@@ -1942,12 +1900,13 @@ if (sizeof ($2))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof (($2)))
return 0;
@@ -1955,18 +1914,19 @@ if (sizeof (($2)))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
eval "$3=yes"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
@@ -1977,11 +1937,12 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -1989,16 +1950,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -2016,35 +1970,56 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2077,8 +2052,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2113,7 +2092,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2148,11 +2127,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2163,8 +2144,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2188,7 +2169,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2196,14 +2177,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2211,15 +2192,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2227,8 +2208,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2242,63 +2223,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2308,19 +2274,435 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+as_fn_append ac_header_c_list " sys/time.h sys_time_h HAVE_SYS_TIME_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="install-sh config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2331,12 +2713,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2345,24 +2727,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2372,11 +2754,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2390,6 +2773,99 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
#### Make srcdir absolute, if it isn't already. It's important to
#### avoid running the path through pwd unnecessary, since pwd can
#### give you automounter prefixes, which can go away.
@@ -2410,57 +2886,32 @@ case "${srcdir}" in
* ) srcdir="`(cd ${srcdir}; pwd)`" ;;
esac
-ac_aux_dir=
-for ac_dir in $srcdir/src/auxdir "$srcdir"/$srcdir/src/auxdir; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in $srcdir/src/auxdir \"$srcdir\"/$srcdir/src/auxdir" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2479,21 +2930,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2512,10 +2964,108 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
fi
+
TARGET=$host
@@ -2526,40 +3076,52 @@ ac_config_headers="$ac_config_headers src/$host/config.h:config.h.in"
# Use --disable-threads to force building single threaded libs even
# if pthreads exists (for test purposes).
# Check whether --enable-threads was given.
-if test "${enable_threads+set}" = set; then :
+if test ${enable_threads+y}
+then :
enableval=$enable_threads; case "$enableval" in
no) threads_disabled=yes ;;
*) threads_disabled=no ;;
esac
-else
+else $as_nop
threads_disabled=maybe
fi
# Check whether --enable-mask-real-errno was given.
-if test "${enable_mask_real_errno+set}" = set; then :
+if test ${enable_mask_real_errno+y}
+then :
enableval=$enable_mask_real_errno; case "$enableval" in
no) mask_real_errno=no ;;
*) mask_real_errno=yes ;;
esac
-else
+else $as_nop
mask_real_errno=yes
fi
# Check whether --enable-ei-dynamic-lib was given.
-if test "${enable_ei_dynamic_lib+set}" = set; then :
+if test ${enable_ei_dynamic_lib+y}
+then :
enableval=$enable_ei_dynamic_lib; case "$enableval" in
yes) DYNAMIC_LIB=yes ;;
*) DYNAMIC_LIB=no ;;
esac
-else
+else $as_nop
DYNAMIC_LIB=no
fi
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2568,11 +3130,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2580,11 +3143,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2595,11 +3162,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2608,11 +3175,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2620,11 +3188,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2635,11 +3207,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2647,8 +3219,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2661,11 +3233,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2673,11 +3246,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2688,11 +3265,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2701,11 +3278,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2714,15 +3292,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2738,18 +3320,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2760,11 +3342,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2772,11 +3355,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2787,11 +3374,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2804,11 +3391,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2816,11 +3404,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2831,11 +3423,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2847,34 +3439,138 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -2884,7 +3580,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -2892,7 +3588,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2904,9 +3600,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -2927,11 +3623,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -2948,7 +3645,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -2964,44 +3661,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -3015,15 +3714,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -3032,7 +3731,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3044,8 +3743,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -3053,10 +3752,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -3064,39 +3763,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3110,11 +3810,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -3123,31 +3824,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3157,29 +3859,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3188,57 +3894,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3253,94 +3962,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3354,40 +4113,36 @@ ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+#include <limits.h>
Syntax error
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
-else
+else $as_nop
# Broken: fails on valid input.
continue
fi
@@ -3399,10 +4154,11 @@ rm -f conftest.err conftest.i conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
# Broken: success on invalid input.
continue
-else
+else $as_nop
# Passes both tests.
ac_preproc_ok=:
break
@@ -3412,7 +4168,8 @@ rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
+if $ac_preproc_ok
+then :
break
fi
@@ -3424,29 +4181,24 @@ fi
else
ac_cv_prog_CPP=$CPP
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+#include <limits.h>
Syntax error
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
-else
+else $as_nop
# Broken: fails on valid input.
continue
fi
@@ -3458,10 +4210,11 @@ rm -f conftest.err conftest.i conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
# Broken: success on invalid input.
continue
-else
+else $as_nop
# Passes both tests.
ac_preproc_ok=:
break
@@ -3471,11 +4224,12 @@ rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
+if $ac_preproc_ok
+then :
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -3486,14 +4240,157 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
@@ -3501,11 +4398,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3516,11 +4417,11 @@ fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3529,11 +4430,12 @@ if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
@@ -3541,11 +4443,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3556,11 +4462,11 @@ fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_RANLIB" = x; then
@@ -3568,8 +4474,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
@@ -3582,11 +4488,12 @@ for ac_prog in ld.sh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$LD"; then
ac_cv_prog_LD="$LD" # Let the user override the test.
else
@@ -3594,11 +4501,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LD="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3609,11 +4520,11 @@ fi
fi
LD=$ac_cv_prog_LD
if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3623,11 +4534,12 @@ done
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$LD"; then
ac_cv_prog_LD="$LD" # Let the user override the test.
else
@@ -3635,11 +4547,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3650,11 +4566,11 @@ fi
fi
LD=$ac_cv_prog_LD
if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3663,11 +4579,12 @@ if test -z "$ac_cv_prog_LD"; then
ac_ct_LD=$LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_LD"; then
ac_cv_prog_ac_ct_LD="$ac_ct_LD" # Let the user override the test.
else
@@ -3675,11 +4592,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3690,11 +4611,11 @@ fi
fi
ac_ct_LD=$ac_cv_prog_ac_ct_LD
if test -n "$ac_ct_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5
-$as_echo "$ac_ct_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5
+printf "%s\n" "$ac_ct_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_LD" = x; then
@@ -3702,8 +4623,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
LD=$ac_ct_LD
@@ -3715,281 +4636,52 @@ fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+done
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-
-done
-
-
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
-$as_echo_n "checking size of short... " >&6; }
-if ${ac_cv_sizeof_short+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+printf %s "checking size of short... " >&6; }
+if test ${ac_cv_sizeof_short+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_short" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (short)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -3998,31 +4690,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
-$as_echo "$ac_cv_sizeof_short" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+printf "%s\n" "$ac_cv_sizeof_short" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-_ACEOF
+printf "%s\n" "#define SIZEOF_SHORT $ac_cv_sizeof_short" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
-$as_echo_n "checking size of int... " >&6; }
-if ${ac_cv_sizeof_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+printf %s "checking size of int... " >&6; }
+if test ${ac_cv_sizeof_int+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_int" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (int)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4031,31 +4723,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
-$as_echo "$ac_cv_sizeof_int" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+printf "%s\n" "$ac_cv_sizeof_int" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
+printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
-$as_echo_n "checking size of long... " >&6; }
-if ${ac_cv_sizeof_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+printf %s "checking size of long... " >&6; }
+if test ${ac_cv_sizeof_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4064,31 +4756,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
-$as_echo "$ac_cv_sizeof_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4097,31 +4789,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
-$as_echo_n "checking size of long long... " >&6; }
-if ${ac_cv_sizeof_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+printf %s "checking size of long long... " >&6; }
+if test ${ac_cv_sizeof_long_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4130,20 +4822,18 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
-$as_echo "$ac_cv_sizeof_long_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
if test $mask_real_errno = yes; then
-$as_echo "#define EI_HIDE_REAL_ERRNO 1" >>confdefs.h
+printf "%s\n" "#define EI_HIDE_REAL_ERRNO 1" >>confdefs.h
fi
@@ -4152,8 +4842,8 @@ if test $ac_cv_sizeof_long = 8; then
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking target hardware architecture" >&5
-$as_echo_n "checking target hardware architecture... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target hardware architecture" >&5
+printf %s "checking target hardware architecture... " >&6; }
if test "x$host_alias" != "x" -a "x$host_cpu" != "x"; then
chk_arch_=$host_cpu
else
@@ -4195,80 +4885,81 @@ $as_echo_n "checking target hardware architecture... " >&6; }
e2k) ARCH=e2k;;
*) ARCH=noarch;;
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ARCH" >&5
-$as_echo "$ARCH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ARCH" >&5
+printf "%s\n" "$ARCH" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compilation mode forces ARCH adjustment" >&5
-$as_echo_n "checking whether compilation mode forces ARCH adjustment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compilation mode forces ARCH adjustment" >&5
+printf %s "checking whether compilation mode forces ARCH adjustment... " >&6; }
case "$ARCH-$ac_cv_sizeof_void_p" in
x86-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=x86 to ARCH=amd64" >&5
-$as_echo "yes: adjusting ARCH=x86 to ARCH=amd64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=x86 to ARCH=amd64" >&5
+printf "%s\n" "yes: adjusting ARCH=x86 to ARCH=amd64" >&6; }
ARCH=amd64
;;
amd64-4)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=amd64 to ARCH=x86" >&5
-$as_echo "yes: adjusting ARCH=amd64 to ARCH=x86" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=amd64 to ARCH=x86" >&5
+printf "%s\n" "yes: adjusting ARCH=amd64 to ARCH=x86" >&6; }
ARCH=x86
;;
ultrasparc-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&5
-$as_echo "yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&5
+printf "%s\n" "yes: adjusting ARCH=ultrasparc to ARCH=sparc64" >&6; }
ARCH=sparc64
;;
sparc64-4)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&5
-$as_echo "yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&5
+printf "%s\n" "yes: adjusting ARCH=sparc64 to ARCH=ultrasparc" >&6; }
ARCH=ultrasparc
;;
ppc64-4)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc64 to ARCH=ppc" >&5
-$as_echo "yes: adjusting ARCH=ppc64 to ARCH=ppc" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc64 to ARCH=ppc" >&5
+printf "%s\n" "yes: adjusting ARCH=ppc64 to ARCH=ppc" >&6; }
ARCH=ppc
;;
ppc-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc to ARCH=ppc64" >&5
-$as_echo "yes: adjusting ARCH=ppc to ARCH=ppc64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=ppc to ARCH=ppc64" >&5
+printf "%s\n" "yes: adjusting ARCH=ppc to ARCH=ppc64" >&6; }
ARCH=ppc64
;;
arm-8)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=arm to ARCH=arm64" >&5
-$as_echo "yes: adjusting ARCH=arm to ARCH=arm64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: adjusting ARCH=arm to ARCH=arm64" >&5
+printf "%s\n" "yes: adjusting ARCH=arm to ARCH=arm64" >&6; }
ARCH=arm64
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no: ARCH is $ARCH" >&5
-$as_echo "no: ARCH is $ARCH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no: ARCH is $ARCH" >&5
+printf "%s\n" "no: ARCH is $ARCH" >&6; }
;;
esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for unaligned word access" >&5
-$as_echo_n "checking for unaligned word access... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for unaligned word access" >&5
+printf %s "checking for unaligned word access... " >&6; }
case "$ARCH" in
x86|amd64)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes: x86 or amd64" >&5
-$as_echo "yes: x86 or amd64" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes: x86 or amd64" >&5
+printf "%s\n" "yes: x86 or amd64" >&6; }
-$as_echo "#define HAVE_UNALIGNED_WORD_ACCESS 1" >>confdefs.h
+printf "%s\n" "#define HAVE_UNALIGNED_WORD_ACCESS 1" >>confdefs.h
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
;;
esac
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
@@ -4276,11 +4967,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_AR="${ac_tool_prefix}ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4291,11 +4986,11 @@ fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4304,11 +4999,12 @@ if test -z "$ac_cv_prog_AR"; then
ac_ct_AR=$AR
# Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
@@ -4316,11 +5012,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_AR="ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4331,11 +5031,11 @@ fi
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_AR" = x; then
@@ -4343,8 +5043,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
@@ -4367,7 +5067,8 @@ case $host in
;;
esac
-# Find a good install program. We prefer a C program (faster),
+
+ # Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
@@ -4381,20 +5082,25 @@ esac
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test ${ac_cv_path_install+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+ ./ | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
@@ -4404,13 +5110,13 @@ case $as_dir/ in #((
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# program-specific install script used by HP pwplus--don't use.
:
else
@@ -4418,12 +5124,12 @@ case $as_dir/ in #((
echo one > conftest.one
echo two > conftest.two
mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
test -s conftest.one && test -s conftest.two &&
test -s conftest.dir/conftest.one &&
test -s conftest.dir/conftest.two
then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
break 3
fi
fi
@@ -4439,7 +5145,7 @@ IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
fi
- if test "${ac_cv_path_install+set}" = set; then
+ if test ${ac_cv_path_install+y}; then
INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. Don't cache a
@@ -4449,8 +5155,8 @@ fi
INSTALL=$ac_install_sh
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
@@ -4460,11 +5166,12 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a directory including parents" >&5
-$as_echo_n "checking how to create a directory including parents... " >&6; }
-if ${ac_cv_prog_mkdir_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to create a directory including parents" >&5
+printf %s "checking how to create a directory including parents... " >&6; }
+if test ${ac_cv_prog_mkdir_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
temp_name_base=config.$$
temp_name=$temp_name_base/x/y/z
@@ -4481,8 +5188,8 @@ fi
rm -fr $temp_name_base
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_mkdir_p" >&5
-$as_echo "$ac_cv_prog_mkdir_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_mkdir_p" >&5
+printf "%s\n" "$ac_cv_prog_mkdir_p" >&6; }
case "${ac_cv_prog_mkdir_p}" in
none) as_fn_error $? "don't know how create directories with parents" "$LINENO" 5 ;;
@@ -4499,393 +5206,395 @@ case $host_os in
esac
# Checks for libraries.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
-$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
-if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnsl $LIBS"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+printf %s "checking for library containing gethostbyname... " >&6; }
+if test ${ac_cv_search_gethostbyname+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char gethostbyname ();
int
-main ()
+main (void)
{
return gethostbyname ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_nsl_gethostbyname=yes
-else
- ac_cv_lib_nsl_gethostbyname=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+for ac_lib in '' nsl
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_gethostbyname+y}
+then :
+ break
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
-$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
-if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNSL 1
-_ACEOF
+done
+if test ${ac_cv_search_gethostbyname+y}
+then :
- LIBS="-lnsl $LIBS"
+else $as_nop
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+printf "%s\n" "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpeername in -lsocket" >&5
-$as_echo_n "checking for getpeername in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_getpeername+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $LIBS"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getpeername" >&5
+printf %s "checking for library containing getpeername... " >&6; }
+if test ${ac_cv_search_getpeername+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char getpeername ();
int
-main ()
+main (void)
{
return getpeername ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_socket_getpeername=yes
-else
- ac_cv_lib_socket_getpeername=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+for ac_lib in '' socket
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_getpeername=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_getpeername+y}
+then :
+ break
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_getpeername" >&5
-$as_echo "$ac_cv_lib_socket_getpeername" >&6; }
-if test "x$ac_cv_lib_socket_getpeername" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
-_ACEOF
+done
+if test ${ac_cv_search_getpeername+y}
+then :
- LIBS="-lsocket $LIBS"
+else $as_nop
+ ac_cv_search_getpeername=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getpeername" >&5
+printf "%s\n" "$ac_cv_search_getpeername" >&6; }
+ac_res=$ac_cv_search_getpeername
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
# Checks for header files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+printf %s "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+if test ${ac_cv_header_sys_wait_h+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
int
-main ()
+main (void)
{
-
+ int s;
+ wait (&s);
+ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_header_sys_wait_h=yes
+else $as_nop
+ ac_cv_header_sys_wait_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f conftest*
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+printf "%s\n" "$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
-fi
+printf "%s\n" "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
+fi
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+ac_fn_c_check_header_compile "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default"
+if test "x$ac_cv_header_arpa_inet_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_ARPA_INET_H 1" >>confdefs.h
-else
- ac_cv_header_stdc=no
fi
-rm -f conftest*
+ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcntl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default"
+if test "x$ac_cv_header_limits_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default"
+if test "x$ac_cv_header_malloc_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_MALLOC_H 1" >>confdefs.h
+
fi
+ac_fn_c_check_header_compile "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default"
+if test "x$ac_cv_header_netdb_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default"
+if test "x$ac_cv_header_netinet_in_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NETINET_IN_H 1" >>confdefs.h
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
+ac_fn_c_check_header_compile "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default"
+if test "x$ac_cv_header_stddef_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_STDDEF_H 1" >>confdefs.h
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+fi
+ac_fn_c_check_header_compile "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_STDLIB_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
+if test "x$ac_cv_header_string_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
-$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
-if ${ac_cv_header_sys_wait_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/wait.h>
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_param_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h
-int
-main ()
-{
- int s;
- wait (&s);
- s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_sys_wait_h=yes
-else
- ac_cv_header_sys_wait_h=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_socket_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
-$as_echo "$ac_cv_header_sys_wait_h" >&6; }
-if test $ac_cv_header_sys_wait_h = yes; then
+ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_select_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h
-$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_time_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default"
+if test "x$ac_cv_header_unistd_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h
-for ac_header in arpa/inet.h fcntl.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/param.h sys/socket.h sys/select.h sys/time.h unistd.h sys/types.h sys/uio.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_types_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "sys/uio.h" "ac_cv_header_sys_uio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_uio_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_UIO_H 1" >>confdefs.h
-done
+fi
# Checks for typedefs, structures, and compiler characteristics.
# fixme AC_C_CONST & AC_C_VOLATILE needed for Windows?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
-$as_echo_n "checking for uid_t in sys/types.h... " >&6; }
-if ${ac_cv_type_uid_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
+printf %s "checking for uid_t in sys/types.h... " >&6; }
+if test ${ac_cv_type_uid_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "uid_t" >/dev/null 2>&1; then :
+ $EGREP "uid_t" >/dev/null 2>&1
+then :
ac_cv_type_uid_t=yes
-else
+else $as_nop
ac_cv_type_uid_t=no
fi
-rm -f conftest*
+rm -rf conftest*
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
-$as_echo "$ac_cv_type_uid_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
+printf "%s\n" "$ac_cv_type_uid_t" >&6; }
if test $ac_cv_type_uid_t = no; then
-$as_echo "#define uid_t int" >>confdefs.h
+printf "%s\n" "#define uid_t int" >>confdefs.h
-$as_echo "#define gid_t int" >>confdefs.h
+printf "%s\n" "#define gid_t int" >>confdefs.h
fi
-ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
-if test "x$ac_cv_type_pid_t" = xyes; then :
-
-else
-cat >>confdefs.h <<_ACEOF
-#define pid_t int
-_ACEOF
-
-fi
-
-ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
-if test "x$ac_cv_type_size_t" = xyes; then :
-
-else
-
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
-_ACEOF
-
-fi
+ ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default
+"
+if test "x$ac_cv_type_pid_t" = xyes
+then :
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
-$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
-if ${ac_cv_header_time+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
+
+ #if defined _WIN64 && !defined __CYGWIN__
+ LLP64
+ #endif
int
-main ()
+main (void)
{
-if ((struct tm *) 0)
-return 0;
+
;
return 0;
}
+
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_time=yes
-else
- ac_cv_header_time=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_pid_type='int'
+else $as_nop
+ ac_pid_type='__int64'
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+printf "%s\n" "#define pid_t $ac_pid_type" >>confdefs.h
+
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
-$as_echo "$ac_cv_header_time" >&6; }
-if test $ac_cv_header_time = yes; then
-$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes
+then :
+
+else $as_nop
+
+printf "%s\n" "#define size_t unsigned int" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t usability" >&5
-$as_echo_n "checking for socklen_t usability... " >&6; }
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socklen_t usability" >&5
+printf %s "checking for socklen_t usability... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
-main ()
+main (void)
{
socklen_t mylen;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_SOCKLEN_T /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_SOCKLEN_T /**/" >>confdefs.h
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Checks for library functions.
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
-$as_echo_n "checking for working alloca.h... " >&6; }
-if ${ac_cv_working_alloca_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
+printf %s "checking for working alloca.h... " >&6; }
+if test ${ac_cv_working_alloca_h+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <alloca.h>
int
-main ()
+main (void)
{
char *p = (char *) alloca (2 * sizeof (int));
if (p) return 0;
@@ -4893,52 +5602,52 @@ char *p = (char *) alloca (2 * sizeof (int));
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_working_alloca_h=yes
-else
+else $as_nop
ac_cv_working_alloca_h=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
-$as_echo "$ac_cv_working_alloca_h" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
+printf "%s\n" "$ac_cv_working_alloca_h" >&6; }
if test $ac_cv_working_alloca_h = yes; then
-$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_ALLOCA_H 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
-$as_echo_n "checking for alloca... " >&6; }
-if ${ac_cv_func_alloca_works+:} false; then :
- $as_echo_n "(cached) " >&6
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
+printf %s "checking for alloca... " >&6; }
+if test ${ac_cv_func_alloca_works+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test $ac_cv_working_alloca_h = yes; then
+ ac_cv_func_alloca_works=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#ifdef __GNUC__
-# define alloca __builtin_alloca
-#else
-# ifdef _MSC_VER
+#include <stdlib.h>
+#include <stddef.h>
+#ifndef alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# elif defined _MSC_VER
# include <malloc.h>
# define alloca _alloca
# else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-void *alloca (size_t);
-# endif
-# endif
+# ifdef __cplusplus
+extern "C"
# endif
+void *alloca (size_t);
# endif
#endif
int
-main ()
+main (void)
{
char *p = (char *) alloca (1);
if (p) return 0;
@@ -4946,20 +5655,22 @@ char *p = (char *) alloca (1);
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_func_alloca_works=yes
-else
+else $as_nop
ac_cv_func_alloca_works=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
-$as_echo "$ac_cv_func_alloca_works" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
+printf "%s\n" "$ac_cv_func_alloca_works" >&6; }
+fi
if test $ac_cv_func_alloca_works = yes; then
-$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
+printf "%s\n" "#define HAVE_ALLOCA 1" >>confdefs.h
else
# The SVR3 libPW and SVR4 libucb both contain incompatible functions
@@ -4969,58 +5680,19 @@ else
ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
-$as_echo "#define C_ALLOCA 1" >>confdefs.h
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
-$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
-if ${ac_cv_os_cray+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#if defined CRAY && ! defined CRAY2
-webecray
-#else
-wenotbecray
-#endif
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "webecray" >/dev/null 2>&1; then :
- ac_cv_os_cray=yes
-else
- ac_cv_os_cray=no
-fi
-rm -f conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
-$as_echo "$ac_cv_os_cray" >&6; }
-if test $ac_cv_os_cray = yes; then
- for ac_func in _getb67 GETB67 getb67; do
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-
-cat >>confdefs.h <<_ACEOF
-#define CRAY_STACKSEG_END $ac_func
-_ACEOF
-
- break
-fi
+printf "%s\n" "#define C_ALLOCA 1" >>confdefs.h
- done
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
-$as_echo_n "checking stack direction for C alloca... " >&6; }
-if ${ac_cv_c_stack_direction+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
+printf %s "checking stack direction for C alloca... " >&6; }
+if test ${ac_cv_c_stack_direction+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "$cross_compiling" = yes
+then :
ac_cv_c_stack_direction=0
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
@@ -5041,9 +5713,10 @@ main (int argc, char **argv)
return find_stack_direction (0, argc + !argv + 20) < 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_c_stack_direction=1
-else
+else $as_nop
ac_cv_c_stack_direction=-1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -5051,22 +5724,21 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
-$as_echo "$ac_cv_c_stack_direction" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define STACK_DIRECTION $ac_cv_c_stack_direction
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
+printf "%s\n" "$ac_cv_c_stack_direction" >&6; }
+printf "%s\n" "#define STACK_DIRECTION $ac_cv_c_stack_direction" >>confdefs.h
fi
# FIXME check that this isn't set in normal cases
if test $ac_cv_c_compiler_gnu = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
-$as_echo_n "checking whether $CC needs -traditional... " >&6; }
-if ${ac_cv_prog_gcc_traditional+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+printf %s "checking whether $CC needs -traditional... " >&6; }
+if test ${ac_cv_prog_gcc_traditional+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_pattern="Autoconf.*'x'"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5074,12 +5746,13 @@ else
Autoconf TIOCGETP
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ $EGREP "$ac_pattern" >/dev/null 2>&1
+then :
ac_cv_prog_gcc_traditional=yes
-else
+else $as_nop
ac_cv_prog_gcc_traditional=no
fi
-rm -f conftest*
+rm -rf conftest*
if test $ac_cv_prog_gcc_traditional = no; then
@@ -5089,34 +5762,37 @@ rm -f conftest*
Autoconf TCGETA
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+ $EGREP "$ac_pattern" >/dev/null 2>&1
+then :
ac_cv_prog_gcc_traditional=yes
fi
-rm -f conftest*
+rm -rf conftest*
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
-$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+printf "%s\n" "$ac_cv_prog_gcc_traditional" >&6; }
if test $ac_cv_prog_gcc_traditional = yes; then
CC="$CC -traditional"
fi
fi
# Check if malloc(0) is ok
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
-$as_echo_n "checking for working memcmp... " >&6; }
-if ${ac_cv_func_memcmp_working+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
+printf %s "checking for working memcmp... " >&6; }
+if test ${ac_cv_func_memcmp_working+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "$cross_compiling" = yes
+then :
ac_cv_func_memcmp_working=no
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
-main ()
+main (void)
{
/* Some versions of memcmp are not 8-bit clean. */
@@ -5147,9 +5823,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_func_memcmp_working=yes
-else
+else $as_nop
ac_cv_func_memcmp_working=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -5157,8 +5834,8 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5
-$as_echo "$ac_cv_func_memcmp_working" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5
+printf "%s\n" "$ac_cv_func_memcmp_working" >&6; }
test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
*" memcmp.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS memcmp.$ac_objext"
@@ -5166,31 +5843,145 @@ test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in
esac
-for ac_func in dup2 gethostbyaddr gethostbyname \
- gethostbyaddr_r \
- gethostbyname_r gethostname writev \
- gethrtime gettimeofday inet_ntoa memchr memmove memset select \
- socket strchr strerror strrchr strstr uname sysconf
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+
+ac_fn_c_check_func "$LINENO" "dup2" "ac_cv_func_dup2"
+if test "x$ac_cv_func_dup2" = xyes
+then :
+ printf "%s\n" "#define HAVE_DUP2 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "gethostbyaddr" "ac_cv_func_gethostbyaddr"
+if test "x$ac_cv_func_gethostbyaddr" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHOSTBYADDR 1" >>confdefs.h
-ac_fn_c_check_func "$LINENO" "res_gethostbyname" "ac_cv_func_res_gethostbyname"
-if test "x$ac_cv_func_res_gethostbyname" = xyes; then :
+fi
+ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHOSTBYNAME 1" >>confdefs.h
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_gethostbyname in -lresolv" >&5
-$as_echo_n "checking for res_gethostbyname in -lresolv... " >&6; }
-if ${ac_cv_lib_resolv_res_gethostbyname+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+fi
+ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r"
+if test "x$ac_cv_func_gethostbyaddr_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
+if test "x$ac_cv_func_gethostbyname_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gethostname" "ac_cv_func_gethostname"
+if test "x$ac_cv_func_gethostname" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHOSTNAME 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "writev" "ac_cv_func_writev"
+if test "x$ac_cv_func_writev" = xyes
+then :
+ printf "%s\n" "#define HAVE_WRITEV 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
+if test "x$ac_cv_func_gettimeofday" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "inet_ntoa" "ac_cv_func_inet_ntoa"
+if test "x$ac_cv_func_inet_ntoa" = xyes
+then :
+ printf "%s\n" "#define HAVE_INET_NTOA 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "memchr" "ac_cv_func_memchr"
+if test "x$ac_cv_func_memchr" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMCHR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove"
+if test "x$ac_cv_func_memmove" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMMOVE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset"
+if test "x$ac_cv_func_memset" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMSET 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select"
+if test "x$ac_cv_func_select" = xyes
+then :
+ printf "%s\n" "#define HAVE_SELECT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket"
+if test "x$ac_cv_func_socket" = xyes
+then :
+ printf "%s\n" "#define HAVE_SOCKET 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strchr" "ac_cv_func_strchr"
+if test "x$ac_cv_func_strchr" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRCHR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRERROR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strrchr" "ac_cv_func_strrchr"
+if test "x$ac_cv_func_strrchr" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRRCHR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr"
+if test "x$ac_cv_func_strstr" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRSTR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname"
+if test "x$ac_cv_func_uname" = xyes
+then :
+ printf "%s\n" "#define HAVE_UNAME 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "sysconf" "ac_cv_func_sysconf"
+if test "x$ac_cv_func_sysconf" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYSCONF 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_func "$LINENO" "res_gethostbyname" "ac_cv_func_res_gethostbyname"
+if test "x$ac_cv_func_res_gethostbyname" = xyes
+then :
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_gethostbyname in -lresolv" >&5
+printf %s "checking for res_gethostbyname in -lresolv... " >&6; }
+if test ${ac_cv_lib_resolv_res_gethostbyname+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lresolv $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5199,33 +5990,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char res_gethostbyname ();
int
-main ()
+main (void)
{
return res_gethostbyname ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_resolv_res_gethostbyname=yes
-else
+else $as_nop
ac_cv_lib_resolv_res_gethostbyname=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_gethostbyname" >&5
-$as_echo "$ac_cv_lib_resolv_res_gethostbyname" >&6; }
-if test "x$ac_cv_lib_resolv_res_gethostbyname" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRESOLV 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_gethostbyname" >&5
+printf "%s\n" "$ac_cv_lib_resolv_res_gethostbyname" >&6; }
+if test "x$ac_cv_lib_resolv_res_gethostbyname" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBRESOLV 1" >>confdefs.h
LIBS="-lresolv $LIBS"
@@ -5235,14 +6023,16 @@ fi
fi
ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
-if test "x$ac_cv_func_clock_gettime" = xyes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
-$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
-if ${ac_cv_lib_rt_clock_gettime+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "x$ac_cv_func_clock_gettime" = xyes
+then :
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5251,33 +6041,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char clock_gettime ();
int
-main ()
+main (void)
{
return clock_gettime ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rt_clock_gettime=yes
-else
+else $as_nop
ac_cv_lib_rt_clock_gettime=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
-$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
-if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRT 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBRT 1" >>confdefs.h
LIBS="-lrt $LIBS"
@@ -5294,7 +6081,8 @@ fi
# Check whether --with-gmp was given.
-if test "${with_gmp+set}" = set; then :
+if test ${with_gmp+y}
+then :
withval=$with_gmp;
fi
@@ -5302,21 +6090,23 @@ fi
# We don't just want any GNU MP version, we want 4.1 or later
# that contain the import/export functions we need.
-if test "x$with_gmp" = "xyes" ;then
+if test "x$with_gmp" = "xyes"
+then :
+
for dir in /usr /usr/pkg /usr/local /usr/local/gmp /usr/lib/gmp /usr/gmp; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/include/gmp.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/include/gmp.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/include/gmp.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/include/gmp.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
ac_cv_gmp=yes
-else
+else $as_nop
ac_cv_gmp=no
fi
-
if test $ac_cv_gmp = yes ; then
CFLAGS="$CFLAGS -I$dir/include -L$dir/lib"
-$as_echo "#define HAVE_GMP_H /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_GMP_H /**/" >>confdefs.h
break
fi
@@ -5324,11 +6114,12 @@ $as_echo "#define HAVE_GMP_H /**/" >>confdefs.h
if test $ac_cv_gmp = no ; then
as_fn_error $? "No GNU MP installation found" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_export in -lgmp" >&5
-$as_echo_n "checking for __gmpz_export in -lgmp... " >&6; }
-if ${ac_cv_lib_gmp___gmpz_export+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __gmpz_export in -lgmp" >&5
+printf %s "checking for __gmpz_export in -lgmp... " >&6; }
+if test ${ac_cv_lib_gmp___gmpz_export+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgmp $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5337,33 +6128,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char __gmpz_export ();
int
-main ()
+main (void)
{
return __gmpz_export ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_gmp___gmpz_export=yes
-else
+else $as_nop
ac_cv_lib_gmp___gmpz_export=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_export" >&5
-$as_echo "$ac_cv_lib_gmp___gmpz_export" >&6; }
-if test "x$ac_cv_lib_gmp___gmpz_export" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBGMP 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_export" >&5
+printf "%s\n" "$ac_cv_lib_gmp___gmpz_export" >&6; }
+if test "x$ac_cv_lib_gmp___gmpz_export" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBGMP 1" >>confdefs.h
LIBS="-lgmp $LIBS"
@@ -5372,22 +6160,23 @@ fi
# FIXME return ERROR if no lib
elif test "x$with_gmp" != "xno" -a -n "$with_gmp" ;then
# Option given with PATH to package
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU MP" >&5
-$as_echo_n "checking for GNU MP... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU MP" >&5
+printf %s "checking for GNU MP... " >&6; }
if test ! -d "$with_gmp" ; then
as_fn_error $? "Invalid path to option --with-gmp=PATH" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$CFLAGS -I$with_gmp/include -L$with_gmp/lib"
-$as_echo "#define HAVE_GMP_H /**/" >>confdefs.h
+printf "%s\n" "#define HAVE_GMP_H /**/" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __gmpz_export in -lgmp" >&5
-$as_echo_n "checking for __gmpz_export in -lgmp... " >&6; }
-if ${ac_cv_lib_gmp___gmpz_export+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __gmpz_export in -lgmp" >&5
+printf %s "checking for __gmpz_export in -lgmp... " >&6; }
+if test ${ac_cv_lib_gmp___gmpz_export+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgmp $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5396,39 +6185,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char __gmpz_export ();
int
-main ()
+main (void)
{
return __gmpz_export ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_gmp___gmpz_export=yes
-else
+else $as_nop
ac_cv_lib_gmp___gmpz_export=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_export" >&5
-$as_echo "$ac_cv_lib_gmp___gmpz_export" >&6; }
-if test "x$ac_cv_lib_gmp___gmpz_export" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBGMP 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gmp___gmpz_export" >&5
+printf "%s\n" "$ac_cv_lib_gmp___gmpz_export" >&6; }
+if test "x$ac_cv_lib_gmp___gmpz_export" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBGMP 1" >>confdefs.h
LIBS="-lgmp $LIBS"
fi
# FIXME return ERROR if no lib
+
fi
@@ -5442,111 +6229,111 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -5559,35 +6346,41 @@ THR_DEFS=
-case "$threads_disabled" in
- no|maybe)
+case "$threads_disabled" in #(
+ no|maybe) :
+
NEED_NPTL_PTHREAD_H=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
-$as_echo_n "checking for native win32 threads... " >&6; }
-if test "X$host_os" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
+printf %s "checking for native win32 threads... " >&6; }
+if test "X$host_os" = "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
THR_LIB_TYPE=posix_unknown
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5596,40 +6389,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pthread_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_pthread_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
THR_LIBS="-lpthread"
fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
-$as_echo_n "checking for pthread_create in -lc_r... " >&6; }
-if ${ac_cv_lib_c_r_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
+printf %s "checking for pthread_create in -lc_r... " >&6; }
+if test ${ac_cv_lib_c_r_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5638,96 +6433,112 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_c_r_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_c_r_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
-$as_echo "$ac_cv_lib_c_r_pthread_create" >&6; }
-if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_c_r_pthread_create" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_create" = xyes
+then :
THR_LIBS="-lc_r"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
-if test "x$ac_cv_func_pthread_create" = xyes; then :
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes
+then :
THR_LIBS="none_needed"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
-$as_echo_n "checking if the '-pthread' switch can be used... " >&6; }
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
+printf %s "checking if the '-pthread' switch can be used... " >&6; }
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -pthread"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_create((void*)0,(void*)0,(void*)0,(void*)0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
THR_DEFS="-pthread"
THR_LIBS="-pthread"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_cflags
if test "x$THR_LIBS" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- fi
- if test "x$THR_LIBS" != "x"; then
+fi
+
+ if test "x$THR_LIBS" != "x"
+then :
+
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ case $host_os in #(
+ solaris*) :
+
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ;; #(
+ linux*) :
+
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
-if test "$cross_compiling" != "yes"; then
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -5735,11 +6546,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5751,23 +6566,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -5775,11 +6593,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5791,25 +6613,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -5820,11 +6645,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5836,11 +6665,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5849,11 +6678,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -5864,11 +6694,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5880,11 +6714,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -5892,8 +6726,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -5902,11 +6736,13 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
-$as_echo_n "checking for Native POSIX Thread Library... " >&6; }
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
+printf %s "checking for Native POSIX Thread Library... " >&6; }
libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
if test $? -eq 0; then
case "$libpthr_vsn" in
@@ -5922,24 +6758,28 @@ $as_echo_n "checking for Native POSIX Thread Library... " >&6; }
else
nptl=no
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
-$as_echo "$nptl" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
+printf "%s\n" "$nptl" >&6; }
if test $nptl = cross; then
nptl=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
- if test $nptl = yes; then
+ if test $nptl = yes
+then :
+
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- ac_fn_c_check_header_mongrel "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_nptl_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_nptl_pthread_h" = xyes
+then :
need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes
fi
+ if test $need_nptl_incldir = yes
+then :
- if test $need_nptl_incldir = yes; then
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -5960,13 +6800,13 @@ fi
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
nptl_incldir=$dir/nptl
fi
-
if test "x$nptl_incldir" != "x"; then
THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
break
@@ -5975,38 +6815,43 @@ fi
if test "x$nptl_incldir" = "x"; then
as_fn_error $? "Failed to locate nptl system include directory" "$LINENO" 5
fi
- fi
- fi
- ;;
- *) ;;
- esac
+
+fi
+
+fi
+ ;; #(
+ *) :
+ ;;
+esac
saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $THR_DEFS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
-$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
CPPFLAGS=$saved_cppflags
- fi
+
+fi
+
fi
@@ -6015,17 +6860,19 @@ fi
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
-$as_echo_n "checking size of short... " >&6; }
-if ${ac_cv_sizeof_short+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+printf %s "checking size of short... " >&6; }
+if test ${ac_cv_sizeof_short+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_short" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (short)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -6034,31 +6881,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
-$as_echo "$ac_cv_sizeof_short" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+printf "%s\n" "$ac_cv_sizeof_short" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-_ACEOF
+printf "%s\n" "#define SIZEOF_SHORT $ac_cv_sizeof_short" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
-$as_echo_n "checking size of int... " >&6; }
-if ${ac_cv_sizeof_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+printf %s "checking size of int... " >&6; }
+if test ${ac_cv_sizeof_int+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_int" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (int)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -6067,31 +6914,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
-$as_echo "$ac_cv_sizeof_int" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+printf "%s\n" "$ac_cv_sizeof_int" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-_ACEOF
+printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
-$as_echo_n "checking size of long... " >&6; }
-if ${ac_cv_sizeof_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+printf %s "checking size of long... " >&6; }
+if test ${ac_cv_sizeof_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -6100,31 +6947,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
-$as_echo "$ac_cv_sizeof_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
-$as_echo_n "checking size of long long... " >&6; }
-if ${ac_cv_sizeof_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+printf %s "checking size of long long... " >&6; }
+if test ${ac_cv_sizeof_long_long+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_long_long" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long long)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -6133,31 +6980,31 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
-$as_echo "$ac_cv_sizeof_long_long" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
-_ACEOF
+printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of __int128_t" >&5
-$as_echo_n "checking size of __int128_t... " >&6; }
-if ${ac_cv_sizeof___int128_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of __int128_t" >&5
+printf %s "checking size of __int128_t... " >&6; }
+if test ${ac_cv_sizeof___int128_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (__int128_t))" "ac_cv_sizeof___int128_t" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type___int128_t" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (__int128_t)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -6166,14 +7013,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int128_t" >&5
-$as_echo "$ac_cv_sizeof___int128_t" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof___int128_t" >&5
+printf "%s\n" "$ac_cv_sizeof___int128_t" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF___INT128_T $ac_cv_sizeof___int128_t
-_ACEOF
+printf "%s\n" "#define SIZEOF___INT128_T $ac_cv_sizeof___int128_t" >>confdefs.h
@@ -6202,28 +7047,30 @@ _ACEOF
else
gcc_atomic_type128="#error "
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working __sync_synchronize()" >&5
-$as_echo_n "checking for a working __sync_synchronize()... " >&6; }
-if ${ethr_cv___sync_synchronize+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working __sync_synchronize()" >&5
+printf %s "checking for a working __sync_synchronize()... " >&6; }
+if test ${ethr_cv___sync_synchronize+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv___sync_synchronize=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__sync_synchronize();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv___sync_synchronize=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test $ethr_cv___sync_synchronize = yes; then
#
@@ -6268,8 +7115,8 @@ EOF
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv___sync_synchronize" >&5
-$as_echo "$ethr_cv___sync_synchronize" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv___sync_synchronize" >&5
+printf "%s\n" "$ethr_cv___sync_synchronize" >&6; }
if test "$ethr_cv___sync_synchronize" = "yes"; then
have_sync_synchronize_value="~0"
@@ -6277,9 +7124,7 @@ $as_echo "$ethr_cv___sync_synchronize" >&6; }
have_sync_synchronize_value="0"
fi
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_synchronize $have_sync_synchronize_value
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_synchronize $have_sync_synchronize_value" >>confdefs.h
@@ -6318,87 +7163,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_add_and_fetch()" >&5
-$as_echo_n "checking for 32-bit __sync_add_and_fetch()... " >&6; }
-if ${ethr_cv_32bit___sync_add_and_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_add_and_fetch()" >&5
+printf %s "checking for 32-bit __sync_add_and_fetch()... " >&6; }
+if test ${ethr_cv_32bit___sync_add_and_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_add_and_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_add_and_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_add_and_fetch" >&5
-$as_echo "$ethr_cv_32bit___sync_add_and_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_add_and_fetch()" >&5
-$as_echo_n "checking for 64-bit __sync_add_and_fetch()... " >&6; }
-if ${ethr_cv_64bit___sync_add_and_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_add_and_fetch" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_add_and_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_add_and_fetch()" >&5
+printf %s "checking for 64-bit __sync_add_and_fetch()... " >&6; }
+if test ${ethr_cv_64bit___sync_add_and_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_add_and_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_add_and_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_add_and_fetch" >&5
-$as_echo "$ethr_cv_64bit___sync_add_and_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_add_and_fetch()" >&5
-$as_echo_n "checking for 128-bit __sync_add_and_fetch()... " >&6; }
-if ${ethr_cv_128bit___sync_add_and_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_add_and_fetch" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_add_and_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_add_and_fetch()" >&5
+printf %s "checking for 128-bit __sync_add_and_fetch()... " >&6; }
+if test ${ethr_cv_128bit___sync_add_and_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_add_and_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_add_and_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_add_and_fetch" >&5
-$as_echo "$ethr_cv_128bit___sync_add_and_fetch" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_add_and_fetch" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_add_and_fetch" >&6; }
case $ethr_cv_128bit___sync_add_and_fetch-$ethr_cv_64bit___sync_add_and_fetch-$ethr_cv_32bit___sync_add_and_fetch in
no-no-no)
@@ -6419,9 +7270,7 @@ $as_echo "$ethr_cv_128bit___sync_add_and_fetch" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_add_and_fetch $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_add_and_fetch $have_atomic_ops" >>confdefs.h
@@ -6460,87 +7309,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_and()" >&5
-$as_echo_n "checking for 32-bit __sync_fetch_and_and()... " >&6; }
-if ${ethr_cv_32bit___sync_fetch_and_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_and()" >&5
+printf %s "checking for 32-bit __sync_fetch_and_and()... " >&6; }
+if test ${ethr_cv_32bit___sync_fetch_and_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_fetch_and_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_fetch_and_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_and" >&5
-$as_echo "$ethr_cv_32bit___sync_fetch_and_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_and()" >&5
-$as_echo_n "checking for 64-bit __sync_fetch_and_and()... " >&6; }
-if ${ethr_cv_64bit___sync_fetch_and_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_and" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_fetch_and_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_and()" >&5
+printf %s "checking for 64-bit __sync_fetch_and_and()... " >&6; }
+if test ${ethr_cv_64bit___sync_fetch_and_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_fetch_and_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_fetch_and_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_and" >&5
-$as_echo "$ethr_cv_64bit___sync_fetch_and_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_and()" >&5
-$as_echo_n "checking for 128-bit __sync_fetch_and_and()... " >&6; }
-if ${ethr_cv_128bit___sync_fetch_and_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_and" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_fetch_and_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_and()" >&5
+printf %s "checking for 128-bit __sync_fetch_and_and()... " >&6; }
+if test ${ethr_cv_128bit___sync_fetch_and_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_fetch_and_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_fetch_and_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_and" >&5
-$as_echo "$ethr_cv_128bit___sync_fetch_and_and" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_and" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_fetch_and_and" >&6; }
case $ethr_cv_128bit___sync_fetch_and_and-$ethr_cv_64bit___sync_fetch_and_and-$ethr_cv_32bit___sync_fetch_and_and in
no-no-no)
@@ -6561,9 +7416,7 @@ $as_echo "$ethr_cv_128bit___sync_fetch_and_and" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_fetch_and_and $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_fetch_and_and $have_atomic_ops" >>confdefs.h
@@ -6602,87 +7455,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_or()" >&5
-$as_echo_n "checking for 32-bit __sync_fetch_and_or()... " >&6; }
-if ${ethr_cv_32bit___sync_fetch_and_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_fetch_and_or()" >&5
+printf %s "checking for 32-bit __sync_fetch_and_or()... " >&6; }
+if test ${ethr_cv_32bit___sync_fetch_and_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_fetch_and_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_fetch_and_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_or" >&5
-$as_echo "$ethr_cv_32bit___sync_fetch_and_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_or()" >&5
-$as_echo_n "checking for 64-bit __sync_fetch_and_or()... " >&6; }
-if ${ethr_cv_64bit___sync_fetch_and_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_fetch_and_or" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_fetch_and_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_fetch_and_or()" >&5
+printf %s "checking for 64-bit __sync_fetch_and_or()... " >&6; }
+if test ${ethr_cv_64bit___sync_fetch_and_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_fetch_and_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_fetch_and_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_or" >&5
-$as_echo "$ethr_cv_64bit___sync_fetch_and_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_or()" >&5
-$as_echo_n "checking for 128-bit __sync_fetch_and_or()... " >&6; }
-if ${ethr_cv_128bit___sync_fetch_and_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_fetch_and_or" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_fetch_and_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_fetch_and_or()" >&5
+printf %s "checking for 128-bit __sync_fetch_and_or()... " >&6; }
+if test ${ethr_cv_128bit___sync_fetch_and_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_fetch_and_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_fetch_and_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_or" >&5
-$as_echo "$ethr_cv_128bit___sync_fetch_and_or" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_fetch_and_or" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_fetch_and_or" >&6; }
case $ethr_cv_128bit___sync_fetch_and_or-$ethr_cv_64bit___sync_fetch_and_or-$ethr_cv_32bit___sync_fetch_and_or in
no-no-no)
@@ -6703,9 +7562,7 @@ $as_echo "$ethr_cv_128bit___sync_fetch_and_or" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_fetch_and_or $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_fetch_and_or $have_atomic_ops" >>confdefs.h
@@ -6744,87 +7601,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_val_compare_and_swap()" >&5
-$as_echo_n "checking for 32-bit __sync_val_compare_and_swap()... " >&6; }
-if ${ethr_cv_32bit___sync_val_compare_and_swap+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __sync_val_compare_and_swap()" >&5
+printf %s "checking for 32-bit __sync_val_compare_and_swap()... " >&6; }
+if test ${ethr_cv_32bit___sync_val_compare_and_swap+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___sync_val_compare_and_swap=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___sync_val_compare_and_swap=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_val_compare_and_swap" >&5
-$as_echo "$ethr_cv_32bit___sync_val_compare_and_swap" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_val_compare_and_swap()" >&5
-$as_echo_n "checking for 64-bit __sync_val_compare_and_swap()... " >&6; }
-if ${ethr_cv_64bit___sync_val_compare_and_swap+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___sync_val_compare_and_swap" >&5
+printf "%s\n" "$ethr_cv_32bit___sync_val_compare_and_swap" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __sync_val_compare_and_swap()" >&5
+printf %s "checking for 64-bit __sync_val_compare_and_swap()... " >&6; }
+if test ${ethr_cv_64bit___sync_val_compare_and_swap+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___sync_val_compare_and_swap=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___sync_val_compare_and_swap=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_val_compare_and_swap" >&5
-$as_echo "$ethr_cv_64bit___sync_val_compare_and_swap" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_val_compare_and_swap()" >&5
-$as_echo_n "checking for 128-bit __sync_val_compare_and_swap()... " >&6; }
-if ${ethr_cv_128bit___sync_val_compare_and_swap+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___sync_val_compare_and_swap" >&5
+printf "%s\n" "$ethr_cv_64bit___sync_val_compare_and_swap" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __sync_val_compare_and_swap()" >&5
+printf %s "checking for 128-bit __sync_val_compare_and_swap()... " >&6; }
+if test ${ethr_cv_128bit___sync_val_compare_and_swap+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___sync_val_compare_and_swap=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___sync_val_compare_and_swap=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_val_compare_and_swap" >&5
-$as_echo "$ethr_cv_128bit___sync_val_compare_and_swap" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___sync_val_compare_and_swap" >&5
+printf "%s\n" "$ethr_cv_128bit___sync_val_compare_and_swap" >&6; }
case $ethr_cv_128bit___sync_val_compare_and_swap-$ethr_cv_64bit___sync_val_compare_and_swap-$ethr_cv_32bit___sync_val_compare_and_swap in
no-no-no)
@@ -6845,9 +7708,7 @@ $as_echo "$ethr_cv_128bit___sync_val_compare_and_swap" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___sync_val_compare_and_swap $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___sync_val_compare_and_swap $have_atomic_ops" >>confdefs.h
@@ -6887,87 +7748,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_store_n()" >&5
-$as_echo_n "checking for 32-bit __atomic_store_n()... " >&6; }
-if ${ethr_cv_32bit___atomic_store_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_store_n()" >&5
+printf %s "checking for 32-bit __atomic_store_n()... " >&6; }
+if test ${ethr_cv_32bit___atomic_store_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_store_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_store_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_store_n" >&5
-$as_echo "$ethr_cv_32bit___atomic_store_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_store_n()" >&5
-$as_echo_n "checking for 64-bit __atomic_store_n()... " >&6; }
-if ${ethr_cv_64bit___atomic_store_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_store_n" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_store_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_store_n()" >&5
+printf %s "checking for 64-bit __atomic_store_n()... " >&6; }
+if test ${ethr_cv_64bit___atomic_store_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_store_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_store_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_store_n" >&5
-$as_echo "$ethr_cv_64bit___atomic_store_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_store_n()" >&5
-$as_echo_n "checking for 128-bit __atomic_store_n()... " >&6; }
-if ${ethr_cv_128bit___atomic_store_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_store_n" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_store_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_store_n()" >&5
+printf %s "checking for 128-bit __atomic_store_n()... " >&6; }
+if test ${ethr_cv_128bit___atomic_store_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_store_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_store_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_store_n" >&5
-$as_echo "$ethr_cv_128bit___atomic_store_n" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_store_n" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_store_n" >&6; }
case $ethr_cv_128bit___atomic_store_n-$ethr_cv_64bit___atomic_store_n-$ethr_cv_32bit___atomic_store_n in
no-no-no)
@@ -6988,9 +7855,7 @@ $as_echo "$ethr_cv_128bit___atomic_store_n" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_store_n $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_store_n $have_atomic_ops" >>confdefs.h
@@ -7029,87 +7894,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_load_n()" >&5
-$as_echo_n "checking for 32-bit __atomic_load_n()... " >&6; }
-if ${ethr_cv_32bit___atomic_load_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_load_n()" >&5
+printf %s "checking for 32-bit __atomic_load_n()... " >&6; }
+if test ${ethr_cv_32bit___atomic_load_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_load_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_load_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_load_n" >&5
-$as_echo "$ethr_cv_32bit___atomic_load_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_load_n()" >&5
-$as_echo_n "checking for 64-bit __atomic_load_n()... " >&6; }
-if ${ethr_cv_64bit___atomic_load_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_load_n" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_load_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_load_n()" >&5
+printf %s "checking for 64-bit __atomic_load_n()... " >&6; }
+if test ${ethr_cv_64bit___atomic_load_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_load_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_load_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_load_n" >&5
-$as_echo "$ethr_cv_64bit___atomic_load_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_load_n()" >&5
-$as_echo_n "checking for 128-bit __atomic_load_n()... " >&6; }
-if ${ethr_cv_128bit___atomic_load_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_load_n" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_load_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_load_n()" >&5
+printf %s "checking for 128-bit __atomic_load_n()... " >&6; }
+if test ${ethr_cv_128bit___atomic_load_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_load_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_load_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_load_n" >&5
-$as_echo "$ethr_cv_128bit___atomic_load_n" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_load_n" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_load_n" >&6; }
case $ethr_cv_128bit___atomic_load_n-$ethr_cv_64bit___atomic_load_n-$ethr_cv_32bit___atomic_load_n in
no-no-no)
@@ -7130,9 +8001,7 @@ $as_echo "$ethr_cv_128bit___atomic_load_n" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_load_n $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_load_n $have_atomic_ops" >>confdefs.h
@@ -7171,87 +8040,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_add_fetch()" >&5
-$as_echo_n "checking for 32-bit __atomic_add_fetch()... " >&6; }
-if ${ethr_cv_32bit___atomic_add_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_add_fetch()" >&5
+printf %s "checking for 32-bit __atomic_add_fetch()... " >&6; }
+if test ${ethr_cv_32bit___atomic_add_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_add_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_add_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_add_fetch" >&5
-$as_echo "$ethr_cv_32bit___atomic_add_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_add_fetch()" >&5
-$as_echo_n "checking for 64-bit __atomic_add_fetch()... " >&6; }
-if ${ethr_cv_64bit___atomic_add_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_add_fetch" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_add_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_add_fetch()" >&5
+printf %s "checking for 64-bit __atomic_add_fetch()... " >&6; }
+if test ${ethr_cv_64bit___atomic_add_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_add_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_add_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_add_fetch" >&5
-$as_echo "$ethr_cv_64bit___atomic_add_fetch" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_add_fetch()" >&5
-$as_echo_n "checking for 128-bit __atomic_add_fetch()... " >&6; }
-if ${ethr_cv_128bit___atomic_add_fetch+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_add_fetch" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_add_fetch" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_add_fetch()" >&5
+printf %s "checking for 128-bit __atomic_add_fetch()... " >&6; }
+if test ${ethr_cv_128bit___atomic_add_fetch+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_add_fetch=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_add_fetch=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_add_fetch" >&5
-$as_echo "$ethr_cv_128bit___atomic_add_fetch" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_add_fetch" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_add_fetch" >&6; }
case $ethr_cv_128bit___atomic_add_fetch-$ethr_cv_64bit___atomic_add_fetch-$ethr_cv_32bit___atomic_add_fetch in
no-no-no)
@@ -7272,9 +8147,7 @@ $as_echo "$ethr_cv_128bit___atomic_add_fetch" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_add_fetch $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_add_fetch $have_atomic_ops" >>confdefs.h
@@ -7313,87 +8186,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_and()" >&5
-$as_echo_n "checking for 32-bit __atomic_fetch_and()... " >&6; }
-if ${ethr_cv_32bit___atomic_fetch_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_and()" >&5
+printf %s "checking for 32-bit __atomic_fetch_and()... " >&6; }
+if test ${ethr_cv_32bit___atomic_fetch_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_fetch_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_fetch_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_and" >&5
-$as_echo "$ethr_cv_32bit___atomic_fetch_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_and()" >&5
-$as_echo_n "checking for 64-bit __atomic_fetch_and()... " >&6; }
-if ${ethr_cv_64bit___atomic_fetch_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_and" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_fetch_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_and()" >&5
+printf %s "checking for 64-bit __atomic_fetch_and()... " >&6; }
+if test ${ethr_cv_64bit___atomic_fetch_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_fetch_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_fetch_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_and" >&5
-$as_echo "$ethr_cv_64bit___atomic_fetch_and" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_and()" >&5
-$as_echo_n "checking for 128-bit __atomic_fetch_and()... " >&6; }
-if ${ethr_cv_128bit___atomic_fetch_and+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_and" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_fetch_and" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_and()" >&5
+printf %s "checking for 128-bit __atomic_fetch_and()... " >&6; }
+if test ${ethr_cv_128bit___atomic_fetch_and+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_fetch_and=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_fetch_and=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_and" >&5
-$as_echo "$ethr_cv_128bit___atomic_fetch_and" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_and" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_fetch_and" >&6; }
case $ethr_cv_128bit___atomic_fetch_and-$ethr_cv_64bit___atomic_fetch_and-$ethr_cv_32bit___atomic_fetch_and in
no-no-no)
@@ -7414,9 +8293,7 @@ $as_echo "$ethr_cv_128bit___atomic_fetch_and" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_fetch_and $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_fetch_and $have_atomic_ops" >>confdefs.h
@@ -7455,87 +8332,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_or()" >&5
-$as_echo_n "checking for 32-bit __atomic_fetch_or()... " >&6; }
-if ${ethr_cv_32bit___atomic_fetch_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_fetch_or()" >&5
+printf %s "checking for 32-bit __atomic_fetch_or()... " >&6; }
+if test ${ethr_cv_32bit___atomic_fetch_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_fetch_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_fetch_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_or" >&5
-$as_echo "$ethr_cv_32bit___atomic_fetch_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_or()" >&5
-$as_echo_n "checking for 64-bit __atomic_fetch_or()... " >&6; }
-if ${ethr_cv_64bit___atomic_fetch_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_fetch_or" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_fetch_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_fetch_or()" >&5
+printf %s "checking for 64-bit __atomic_fetch_or()... " >&6; }
+if test ${ethr_cv_64bit___atomic_fetch_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_fetch_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_fetch_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_or" >&5
-$as_echo "$ethr_cv_64bit___atomic_fetch_or" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_or()" >&5
-$as_echo_n "checking for 128-bit __atomic_fetch_or()... " >&6; }
-if ${ethr_cv_128bit___atomic_fetch_or+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_fetch_or" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_fetch_or" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_fetch_or()" >&5
+printf %s "checking for 128-bit __atomic_fetch_or()... " >&6; }
+if test ${ethr_cv_128bit___atomic_fetch_or+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_fetch_or=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_fetch_or=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_or" >&5
-$as_echo "$ethr_cv_128bit___atomic_fetch_or" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_fetch_or" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_fetch_or" >&6; }
case $ethr_cv_128bit___atomic_fetch_or-$ethr_cv_64bit___atomic_fetch_or-$ethr_cv_32bit___atomic_fetch_or in
no-no-no)
@@ -7556,9 +8439,7 @@ $as_echo "$ethr_cv_128bit___atomic_fetch_or" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_fetch_or $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_fetch_or $have_atomic_ops" >>confdefs.h
@@ -7597,87 +8478,93 @@ _ACEOF
eval atomic${atomic_bit_size}_call=\"$atomic_call\"
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_compare_exchange_n()" >&5
-$as_echo_n "checking for 32-bit __atomic_compare_exchange_n()... " >&6; }
-if ${ethr_cv_32bit___atomic_compare_exchange_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 32-bit __atomic_compare_exchange_n()" >&5
+printf %s "checking for 32-bit __atomic_compare_exchange_n()... " >&6; }
+if test ${ethr_cv_32bit___atomic_compare_exchange_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_32bit___atomic_compare_exchange_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic32_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_32bit___atomic_compare_exchange_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_compare_exchange_n" >&5
-$as_echo "$ethr_cv_32bit___atomic_compare_exchange_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_compare_exchange_n()" >&5
-$as_echo_n "checking for 64-bit __atomic_compare_exchange_n()... " >&6; }
-if ${ethr_cv_64bit___atomic_compare_exchange_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_32bit___atomic_compare_exchange_n" >&5
+printf "%s\n" "$ethr_cv_32bit___atomic_compare_exchange_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit __atomic_compare_exchange_n()" >&5
+printf %s "checking for 64-bit __atomic_compare_exchange_n()... " >&6; }
+if test ${ethr_cv_64bit___atomic_compare_exchange_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_64bit___atomic_compare_exchange_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic64_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_64bit___atomic_compare_exchange_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_compare_exchange_n" >&5
-$as_echo "$ethr_cv_64bit___atomic_compare_exchange_n" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_compare_exchange_n()" >&5
-$as_echo_n "checking for 128-bit __atomic_compare_exchange_n()... " >&6; }
-if ${ethr_cv_128bit___atomic_compare_exchange_n+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_64bit___atomic_compare_exchange_n" >&5
+printf "%s\n" "$ethr_cv_64bit___atomic_compare_exchange_n" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 128-bit __atomic_compare_exchange_n()" >&5
+printf %s "checking for 128-bit __atomic_compare_exchange_n()... " >&6; }
+if test ${ethr_cv_128bit___atomic_compare_exchange_n+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_128bit___atomic_compare_exchange_n=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
$atomic128_call
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_128bit___atomic_compare_exchange_n=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_compare_exchange_n" >&5
-$as_echo "$ethr_cv_128bit___atomic_compare_exchange_n" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_128bit___atomic_compare_exchange_n" >&5
+printf "%s\n" "$ethr_cv_128bit___atomic_compare_exchange_n" >&6; }
case $ethr_cv_128bit___atomic_compare_exchange_n-$ethr_cv_64bit___atomic_compare_exchange_n-$ethr_cv_32bit___atomic_compare_exchange_n in
no-no-no)
@@ -7698,9 +8585,7 @@ $as_echo "$ethr_cv_128bit___atomic_compare_exchange_n" >&6; }
have_atomic_ops=28;;
esac
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE___atomic_compare_exchange_n $have_atomic_ops
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE___atomic_compare_exchange_n $have_atomic_ops" >>confdefs.h
@@ -7708,20 +8593,25 @@ _ACEOF
ethr_arm_dbm_sy_instr_val=0
ethr_arm_dbm_st_instr_val=0
ethr_arm_dbm_ld_instr_val=0
- case "$GCC-$host_cpu" in
- yes-arm*|yes-aarch*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb sy' instruction" >&5
-$as_echo_n "checking for ARM 'dmb sy' instruction... " >&6; }
-if ${ethr_cv_arm_dbm_sy_instr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ ethr_arm_isb_sy_instr_val=0
+ ethr_arm_dc_cvau_instr_val=0
+ ethr_arm_ic_ivau_instr_val=0
+ case "$GCC-$host_cpu" in #(
+ yes-arm*|yes-aarch*) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb sy' instruction" >&5
+printf %s "checking for ARM 'dmb sy' instruction... " >&6; }
+if test ${ethr_cv_arm_dbm_sy_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_arm_dbm_sy_instr=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__asm__ __volatile__("dmb sy" : : : "memory");
@@ -7730,32 +8620,34 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_arm_dbm_sy_instr=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_sy_instr" >&5
-$as_echo "$ethr_cv_arm_dbm_sy_instr" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_sy_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dbm_sy_instr" >&6; }
if test $ethr_cv_arm_dbm_sy_instr = yes; then
ethr_arm_dbm_sy_instr_val=1
test $ethr_cv_64bit___atomic_compare_exchange_n = yes &&
ethr_have_gcc_native_atomics=yes
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb st' instruction" >&5
-$as_echo_n "checking for ARM 'dmb st' instruction... " >&6; }
-if ${ethr_cv_arm_dbm_st_instr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb st' instruction" >&5
+printf %s "checking for ARM 'dmb st' instruction... " >&6; }
+if test ${ethr_cv_arm_dbm_st_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_arm_dbm_st_instr=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__asm__ __volatile__("dmb st" : : : "memory");
@@ -7764,30 +8656,32 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_arm_dbm_st_instr=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_st_instr" >&5
-$as_echo "$ethr_cv_arm_dbm_st_instr" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_st_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dbm_st_instr" >&6; }
if test $ethr_cv_arm_dbm_st_instr = yes; then
ethr_arm_dbm_st_instr_val=1
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb ld' instruction" >&5
-$as_echo_n "checking for ARM 'dmb ld' instruction... " >&6; }
-if ${ethr_cv_arm_dbm_ld_instr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dmb ld' instruction" >&5
+printf %s "checking for ARM 'dmb ld' instruction... " >&6; }
+if test ${ethr_cv_arm_dbm_ld_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ethr_cv_arm_dbm_ld_instr=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
__asm__ __volatile__("dmb ld" : : : "memory");
@@ -7796,35 +8690,144 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ethr_cv_arm_dbm_ld_instr=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_ld_instr" >&5
-$as_echo "$ethr_cv_arm_dbm_ld_instr" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dbm_ld_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dbm_ld_instr" >&6; }
if test $ethr_cv_arm_dbm_ld_instr = yes; then
ethr_arm_dbm_ld_instr_val=1
- fi;;
- *)
- ;;
- esac
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'isb sy' instruction" >&5
+printf %s "checking for ARM 'isb sy' instruction... " >&6; }
+if test ${ethr_cv_arm_isb_sy_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ethr_cv_arm_isb_sy_instr=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION $ethr_arm_dbm_sy_instr_val
+int
+main (void)
+{
+
+ __asm__ __volatile__("isb sy" : : : "memory");
+
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ethr_cv_arm_isb_sy_instr=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_isb_sy_instr" >&5
+printf "%s\n" "$ethr_cv_arm_isb_sy_instr" >&6; }
+ if test $ethr_cv_arm_isb_sy_instr = yes; then
+ ethr_arm_isb_sy_instr_val=1
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'dc cvau' instruction" >&5
+printf %s "checking for ARM 'dc cvau' instruction... " >&6; }
+if test ${ethr_cv_arm_dc_cvau_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ethr_cv_arm_dc_cvau_instr=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+ char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION $ethr_arm_dbm_st_instr_val
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ethr_cv_arm_dc_cvau_instr=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_dc_cvau_instr" >&5
+printf "%s\n" "$ethr_cv_arm_dc_cvau_instr" >&6; }
+ if test $ethr_cv_arm_dc_cvau_instr = yes; then
+ ethr_arm_dc_cvau_instr_val=1
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ARM 'ic ivau' instruction" >&5
+printf %s "checking for ARM 'ic ivau' instruction... " >&6; }
+if test ${ethr_cv_arm_ic_ivau_instr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ethr_cv_arm_ic_ivau_instr=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+ char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC_ASM_ARM_DMB_LD_INSTRUCTION $ethr_arm_dbm_ld_instr_val
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ethr_cv_arm_ic_ivau_instr=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ethr_cv_arm_ic_ivau_instr" >&5
+printf "%s\n" "$ethr_cv_arm_ic_ivau_instr" >&6; }
+ if test $ethr_cv_arm_ic_ivau_instr = yes; then
+ ethr_arm_ic_ivau_instr_val=1
+ fi
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION $ethr_arm_dbm_sy_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION $ethr_arm_dbm_st_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DMB_LD_INSTRUCTION $ethr_arm_dbm_ld_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION $ethr_arm_isb_sy_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION $ethr_arm_dc_cvau_instr_val" >>confdefs.h
+
+
+printf "%s\n" "#define ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION $ethr_arm_ic_ivau_instr_val" >>confdefs.h
+
test $ethr_cv_32bit___sync_val_compare_and_swap = yes &&
ethr_have_gcc_native_atomics=yes
@@ -7844,9 +8847,7 @@ _ACEOF
test $ethr_have_gcc_atomic_builtins = 1 && ethr_native_atomic_implementation=gcc_atomic_sync
fi
-cat >>confdefs.h <<_ACEOF
-#define ETHR_HAVE_GCC___ATOMIC_BUILTINS $ethr_have_gcc_atomic_builtins
-_ACEOF
+printf "%s\n" "#define ETHR_HAVE_GCC___ATOMIC_BUILTINS $ethr_have_gcc_atomic_builtins" >>confdefs.h
test $ethr_have_gcc_native_atomics = yes && ethr_have_native_atomics=yes
@@ -7868,15 +8869,18 @@ _ACEOF
;;
*)
EI_THREADS="true"
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unexpected thread library: $THR_LIB_NAME" >&5
-$as_echo "$as_me: WARNING: Unexpected thread library: $THR_LIB_NAME" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Unexpected thread library: $THR_LIB_NAME" >&5
+printf "%s\n" "$as_me: WARNING: Unexpected thread library: $THR_LIB_NAME" >&2;}
;;
esac
- ;;
- yes)
+ ;; #(
+ yes) :
+
# Threads disabled
EI_THREADS="false"
- ;;
+ ;; #(
+ *) :
+ ;;
esac
# ---------------------------------------------------------------------------
@@ -7884,39 +8888,47 @@ esac
# ---------------------------------------------------------------------------
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Treat certain GCC warnings as errors
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
WERRORFLAGS="-Werror=return-type $WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
WFLAGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline"
# check which GCC version
@@ -7939,40 +8951,49 @@ $as_echo "no" >&6; }
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-common to CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-common to CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-common $CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="-fno-common $CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
-else
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+else $as_nop
+
WFLAGS=""
WERRORFLAGS=""
+
fi
# ---------------------------------------------------------------------------
@@ -8027,181 +9048,253 @@ case "$host_cpu" in
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WARN_FLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=return-type $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=implicit $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=implicit $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=undef $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=undef $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$DED_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
DED_INCLUDE=$DED_SYS_INCLUDE
DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Use -fno-common for gcc, that is link error if multiple definitions of
# global variables are encountered. This is ISO C compliant.
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-common $DED_CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_CFLAGS="-fno-common $DED_CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)... " >&6; }
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="-fno-strict-aliasing $DED_CFLAGS";
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ can_enable_flag=true
+else $as_nop
+ can_enable_flag=false
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$saved_CFLAGS;
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ DED_CFLAGS="-fno-strict-aliasing $DED_CFLAGS"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_STATIC_CFLAGS="$DED_CFLAGS"
DED_CFLAGS="$DED_CFLAGS -fPIC"
# Remove -fPIE and -fno-PIE
DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
+
fi
DED_EXT=so
@@ -8288,17 +9381,19 @@ case $host_os in
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -8307,14 +9402,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
case "$ac_cv_sizeof_void_p" in
@@ -8381,11 +9474,12 @@ test "$DED_LDFLAGS_CONFTEST" != "" || DED_LDFLAGS_CONFTEST="$DED_LDFLAGS"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$DED_LD"; then
ac_cv_prog_DED_LD="$DED_LD" # Let the user override the test.
else
@@ -8393,11 +9487,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DED_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -8408,11 +9506,11 @@ fi
fi
DED_LD=$ac_cv_prog_DED_LD
if test -n "$DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -8421,11 +9519,12 @@ if test -z "$ac_cv_prog_DED_LD"; then
ac_ct_DED_LD=$DED_LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_DED_LD"; then
ac_cv_prog_ac_ct_DED_LD="$ac_ct_DED_LD" # Let the user override the test.
else
@@ -8433,11 +9532,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DED_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -8448,11 +9551,11 @@ fi
fi
ac_ct_DED_LD=$ac_cv_prog_ac_ct_DED_LD
if test -n "$ac_ct_DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
-$as_echo "$ac_ct_DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
+printf "%s\n" "$ac_ct_DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DED_LD" = x; then
@@ -8460,8 +9563,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DED_LD=$ac_ct_DED_LD
@@ -8472,37 +9575,37 @@ fi
test "$DED_LD" != "false" || as_fn_error $? "No linker found" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
-$as_echo_n "checking for static compiler flags... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
+printf %s "checking for static compiler flags... " >&6; }
DED_STATIC_CFLAGS="$DED_WERRORFLAGS $DED_WFLAGS $DED_THR_DEFS $DED_STATIC_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
-$as_echo "$DED_STATIC_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
-$as_echo_n "checking for basic compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
+printf "%s\n" "$DED_STATIC_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
+printf %s "checking for basic compiler flags for loadable drivers... " >&6; }
DED_BASIC_CFLAGS=$DED_CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
-$as_echo_n "checking for compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
+printf %s "checking for compiler flags for loadable drivers... " >&6; }
DED_CFLAGS="$DED_WERRORFLAGS $DED_WARN_FLAGS $DED_THR_DEFS $DED_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
-$as_echo_n "checking for linker for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
-$as_echo_n "checking for linker flags for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
-$as_echo "$DED_LDFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
-$as_echo_n "checking for 'runtime library path' linker flag... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
+printf %s "checking for linker for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
+printf %s "checking for linker flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
+printf "%s\n" "$DED_LDFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
+printf %s "checking for 'runtime library path' linker flag... " >&6; }
if test "x$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
-$as_echo "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
+printf "%s\n" "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
fi
@@ -8526,7 +9629,8 @@ fi
# Check whether --enable-sanitizers was given.
-if test "${enable_sanitizers+set}" = set; then :
+if test ${enable_sanitizers+y}
+then :
enableval=$enable_sanitizers;
case "$enableval" in
no) sanitizers= ;;
@@ -8573,8 +9677,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -8604,15 +9708,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -8626,8 +9730,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -8644,7 +9748,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -8660,8 +9764,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -8684,14 +9788,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -8701,46 +9807,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -8749,13 +9855,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -8764,8 +9863,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -8777,30 +9880,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -8813,13 +9896,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -8846,18 +9930,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -8869,12 +9955,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -8905,7 +9992,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -8927,6 +10014,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -8940,6 +10031,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -8981,7 +10078,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -8990,7 +10087,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -9053,7 +10150,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -9111,14 +10208,16 @@ $config_headers
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -9156,15 +10255,15 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
@@ -9172,7 +10271,7 @@ do
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
@@ -9181,7 +10280,7 @@ do
as_fn_error $? "ambiguous option: \`$1'
Try \`$0 --help' for more information.";;
--help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -9209,7 +10308,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -9223,7 +10322,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -9250,8 +10349,8 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -9587,7 +10686,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -9595,17 +10694,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -9622,7 +10721,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -9646,9 +10745,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -9705,8 +10804,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -9749,9 +10848,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -9767,20 +10866,20 @@ which seems to be undefined. Please make sure it is defined" >&2;}
#
if test x"$ac_file" != x-; then
{
- $as_echo "/* $configure_input */" \
+ printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
} >"$ac_tmp/config.h" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
-$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$ac_tmp/config.h" "$ac_file" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
- $as_echo "/* $configure_input */" \
+ printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
|| as_fn_error $? "could not create -" "$LINENO" 5
fi
@@ -9821,7 +10920,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.ac
index c43ce74016..d24e3f48eb 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.ac
@@ -20,14 +20,16 @@
# Process this file with autoconf to produce a configure script.
# The starting point for this file was the output from 'autoscan'.
-# Strange, VxWorks HAVE_SENS not set here, see "ei_resolve.h"
-
# Find the erl_interface version number and set m4 macro to it.
# We do this because AC_INIT can't handle shell variables. Still broken.
dnl m4_define(EI_VERSION,`grep EI_VSN ../vsn.mk | sed 's/^.*=[ ]*//'`)
dnl m4_define(EI_VERSION,regexp(m4_include(VERSION),[version \([-.0-9A-Za-z]+\)],[\1]))
-AC_INIT()
+AC_INIT
+AC_CONFIG_SRCDIR([include/ei.h])
+AC_PREREQ([2.71])
+
+m4_include([otp.m4])
dnl How to set srcdir absolute is taken from the GNU Emacs distribution
#### Make srcdir absolute, if it isn't already. It's important to
@@ -50,18 +52,14 @@ case "${srcdir}" in
* ) srcdir="`(cd ${srcdir}; pwd)`" ;;
esac
-AC_CONFIG_AUX_DIR([$srcdir/src/auxdir])
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
+ERL_CANONICAL_SYSTEM_TYPE
TARGET=$host
AC_SUBST(TARGET)
-AC_CONFIG_HEADER([src/$host/config.h:config.h.in])
+AC_CONFIG_HEADERS([src/$host/config.h:config.h.in])
dnl ----------------------------------------------------------------------
dnl Optional features
@@ -100,6 +98,7 @@ dnl ----------------------------------------------------------------------
AC_PROG_CC
AC_PROG_CPP
+AC_PROG_EGREP
dnl AC_PROG_LIBTOOL
AC_PROG_RANLIB
AC_CHECK_PROGS(LD, ld.sh)
@@ -168,11 +167,12 @@ case $host_os in
esac
# Checks for libraries.
-AC_CHECK_LIB([nsl], [gethostbyname])
-AC_CHECK_LIB([socket], [getpeername])
+AC_SEARCH_LIBS([gethostbyname], [nsl])
+AC_SEARCH_LIBS([getpeername], [socket])
# Checks for header files.
-AC_HEADER_STDC
+AC_CHECK_INCLUDES_DEFAULT
+
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdlib.h string.h sys/param.h sys/socket.h sys/select.h sys/time.h unistd.h sys/types.h sys/uio.h])
@@ -183,14 +183,12 @@ dnl AC_C_VOLATILE
AC_TYPE_UID_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
-AC_HEADER_TIME
+AC_CHECK_HEADERS_ONCE([sys/time.h])
+
AC_MSG_CHECKING([for socklen_t usability])
-AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/socket.h>],
-[socklen_t mylen;],
-[AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_SOCKLEN_T, [], [Define if you have the `socklen_t' type])],
-[AC_MSG_RESULT(no)])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <sys/socket.h>]], [[socklen_t mylen;]])],[AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SOCKLEN_T, [], [Define if you have the `socklen_t' type])],[AC_MSG_RESULT(no)])
# Checks for library functions.
AC_FUNC_ALLOCA
@@ -202,7 +200,7 @@ dnl AC_FUNC_MALLOC
dnl AC_FUNC_REALLOC
AC_FUNC_MEMCMP
dnl AC_FUNC_SELECT_ARGTYPES
-dnl AC_TYPE_SIGNAL
+
dnl AC_FUNC_STRERROR_R
dnl AC_FUNC_VPRINTF
AC_CHECK_FUNCS([dup2 gethostbyaddr gethostbyname \
@@ -229,7 +227,8 @@ AC_ARG_WITH(gmp,
# We don't just want any GNU MP version, we want 4.1 or later
# that contain the import/export functions we need.
-if test "x$with_gmp" = "xyes" ;then
+AS_IF([test "x$with_gmp" = "xyes"],
+ [
for dir in /usr /usr/pkg /usr/local /usr/local/gmp /usr/lib/gmp /usr/gmp; do
AC_CHECK_HEADER($dir/include/gmp.h, ac_cv_gmp=yes, ac_cv_gmp=no)
if test $ac_cv_gmp = yes ; then
@@ -254,7 +253,7 @@ elif test "x$with_gmp" != "xno" -a -n "$with_gmp" ;then
AC_DEFINE(HAVE_GMP_H, [], [Define if you have "gmp.h"])
AC_CHECK_LIB(gmp, __gmpz_export)
# FIXME return ERROR if no lib
-fi
+ ])
LM_WINDOWS_ENVIRONMENT
@@ -268,8 +267,10 @@ AC_SUBST(THR_LIBS)
AC_SUBST(THR_DEFS)
AC_SUBST(EI_THREADS)
-case "$threads_disabled" in
- no|maybe)
+AS_CASE(["$threads_disabled"],
+
+ [no|maybe],
+ [
LM_CHECK_THR_LIB
ETHR_CHK_GCC_ATOMIC_OPS([])
@@ -278,7 +279,7 @@ case "$threads_disabled" in
EI_THREADS="false"
# Fail if --enable-threads given and no threads found
if test "x$threads_disabled" = "xno"; then
- AC_MSG_ERROR(No threads support found)
+ AC_MSG_ERROR([No threads support found])
fi
;;
win32_threads)
@@ -293,19 +294,21 @@ case "$threads_disabled" in
AC_MSG_WARN([Unexpected thread library: $THR_LIB_NAME])
;;
esac
- ;;
- yes)
+ ],
+
+ [yes],
+ [
# Threads disabled
EI_THREADS="false"
- ;;
-esac
+ ])
# ---------------------------------------------------------------------------
# Warning flags to the C compiler
# ---------------------------------------------------------------------------
AC_SUBST(WFLAGS)
-if test "x$GCC" = xyes; then
+AS_IF([test "x$GCC" = xyes],
+ [
# Treat certain GCC warnings as errors
LM_TRY_ENABLE_CFLAG([-Werror=return-type], [WERRORFLAGS])
WFLAGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline"
@@ -329,10 +332,11 @@ if test "x$GCC" = xyes; then
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
LM_TRY_ENABLE_CFLAG([-fno-common], [CFLAGS])
-else
+ ],
+ [
WFLAGS=""
WERRORFLAGS=""
-fi
+ ])
# ---------------------------------------------------------------------------
# FIXME We want to use libtool but until then....
@@ -382,7 +386,7 @@ LDFLAGS="$LDFLAGS $sanitizers"
# ---------------------------------------------------------------------------
-AC_OUTPUT(
- src/$host/Makefile:src/Makefile.in
+AC_CONFIG_FILES([src/$host/Makefile:src/Makefile.in
src/$host/eidefs.mk:src/eidefs.mk.in
- )
+ ])
+AC_OUTPUT
diff --git a/lib/erl_interface/doc/src/ei_connect.xml b/lib/erl_interface/doc/src/ei_connect.xml
index dc170780b6..390122ae94 100644
--- a/lib/erl_interface/doc/src/ei_connect.xml
+++ b/lib/erl_interface/doc/src/ei_connect.xml
@@ -165,7 +165,7 @@
<p>On success it should set <c>*ctx</c> to point to a context for
the created socket. This context will be passed to all other
socket callbacks. This function will be passed the same
- <c>setup_context</c> as passed to the preceeding
+ <c>setup_context</c> as passed to the preceding
<seecref marker="#ei_connect_init"><c>ei_connect_init_ussi()</c></seecref>
or
<seecref marker="#ei_connect_init"><c>ei_connect_xinit_ussi()</c></seecref>
@@ -192,8 +192,8 @@
<p>The <c>addr</c> and <c>len</c> arguments are both input and output
arguments. When called <c>addr</c> points to an address structure of
- lenght <c>*len</c> containing information on how to bind the socket.
- Uppon return this callback should have updated the structure referred
+ length <c>*len</c> containing information on how to bind the socket.
+ Upon return this callback should have updated the structure referred
by <c>addr</c> with information on how the socket actually was bound.
<c>*len</c> should be updated to reflect the size of <c>*addr</c>
updated. <c>backlog</c> identifies the size of the backlog for the
@@ -211,7 +211,7 @@
connection should be created and <c>*ctx</c> should be updated
to point to the new context for the accepted connection. When
called <c>addr</c> points to an uninitialized address structure
- of lenght <c>*len</c>. Uppon return this callback should have
+ of length <c>*len</c>. Upon return this callback should have
updated this structure with information about the client address.
<c>*len</c> should be updated to reflect the size of <c>*addr</c>
updated.
@@ -233,7 +233,7 @@
identified by <c>addr</c>.</p>
<p>When called <c>addr</c> points to an address structure of
- lenght <c>len</c> containing information on where to connect.</p>
+ length <c>len</c> containing information on where to connect.</p>
<p>If the <c>EI_SCLBK_FLG_FULL_IMPL</c> flag has been set,
<c>tmo</c> contains timeout time in milliseconds.</p>
@@ -541,10 +541,10 @@ fd = ei_xconnect(&ec, &addr, ALIVE);
</func>
<func>
- <name since=""><ret>int</ret><nametext>ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation)</nametext></name>
- <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
- <name since=""><ret>int</ret><nametext>ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation)</nametext></name>
- <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, short creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, unsigned creation)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie, unsigned creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
+ <name since=""><ret>int</ret><nametext>ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, unsigned creation)</nametext></name>
+ <name since="OTP 21.3"><ret>int</ret><nametext>ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename, const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, unsigned creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context)</nametext></name>
<fsummary>Initialize for a connection.</fsummary>
<type>
<v><seecref marker="#ei_cnode"><c>ei_cnode</c></seecref></v>
@@ -573,7 +573,15 @@ fd = ei_xconnect(&ec, &addr, ALIVE);
<item>
<p><c>creation</c> identifies a specific instance of a
C-node. It can help prevent the node from receiving messages
- sent to an earlier process with the same registered name.</p>
+ sent to an earlier process with the same registered name.</p>
+ <note>
+ <p>
+ The type of the <c>creation</c> argument was changed from
+ <c>short</c> (16 bit) to <c>unsigned int</c> (32 bit) in OTP
+ 25. This should cause no practical problem other than maybe a
+ compiler warning.
+ </p>
+ </note>
</item>
<item>
<p><c>thishostname</c> is the name of the machine we are
@@ -620,7 +628,7 @@ fd = ei_xconnect(&ec, &addr, ALIVE);
occurred.</p>
<p><em>Example 1:</em></p>
<code type="none"><![CDATA[
-int n = 0;
+unsigned n = 0;
struct in_addr addr;
ei_cnode ec;
addr.s_addr = inet_addr("150.236.14.75");
diff --git a/lib/erl_interface/doc/src/ei_users_guide.xml b/lib/erl_interface/doc/src/ei_users_guide.xml
index 5c9452b516..f59449c420 100644
--- a/lib/erl_interface/doc/src/ei_users_guide.xml
+++ b/lib/erl_interface/doc/src/ei_users_guide.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2020</year>
+ <year>2002</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -298,7 +298,7 @@ pub = ei_publish(ec, port); ]]></code>
explicitly close the descriptor or if your node fails, it becomes
unregistered from <c>epmd</c>.</p>
- <p>Notice that on some systems (such as VxWorks), a failed node is
+ <p>Notice that on some systems a failed node is
not detected by this mechanism, as the operating system does not
automatically close descriptors that were left open when the node
failed. If a node has failed in this way, <c>epmd</c>
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 75c29257ab..a1bb84f224 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,108 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 5.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Accept connection setup from OTP 23 and 24 nodes that are
+ not using epmd.</p>
+ <p>
+ Own Id: OTP-18404 Aux Id: GH-6595, PR-6625 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ The <c>ei</c> API for decoding/encoding terms is not
+ fully 64-bit compatible since terms that have a
+ representation on the external term format larger than 2
+ GB cannot be handled.</p>
+ <p>
+ Own Id: OTP-16607 Aux Id: OTP-16608 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Interface 5.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>erl_call</c> no longer links against <c>nsl</c> on
+ platforms where <c>gethostbyname</c> is provided by libc.</p>
+ <p>
+ Own Id: OTP-17846 Aux Id: PR-5558 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The following distribution flags are now mandatory:
+ <c>DFLAG_BIT_BINARIES</c>, <c>DFLAG_EXPORT_PTR_TAG</c>,
+ <c>DFLAG_MAP_TAGS</c>, <c>DFLAG_NEW_FLOATS</c>, and
+ <c>DFLAG_FUN_TAGS</c>. This mainly concerns libraries or
+ application that implement the distribution protocol
+ themselves.</p>
+ <p>
+ Own Id: OTP-17318 Aux Id: PR-4972 </p>
+ </item>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>
+ Removed use of node creation value zero as a wildcard.
+ Also prevent zero from being used as creation by
+ <c>erl_interface</c> and <c>jinterface</c> nodes.</p>
+ <p>
+ Own Id: OTP-17682 Aux Id: PR-5347 </p>
+ </item>
+ <item>
+ <p>
+ Changed <c>creation</c> arguments, of function
+ <c>ei_connect_init</c> and friends, from type
+ <c>short</c> to <c>unsigned int</c> for full 32-bit
+ range.</p>
+ <p>
+ Own Id: OTP-17802 Aux Id: PR-5347 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ The <c>ei</c> API for decoding/encoding terms is not
+ fully 64-bit compatible since terms that have a
+ representation on the external term format larger than 2
+ GB cannot be handled.</p>
+ <p>
+ Own Id: OTP-16607 Aux Id: OTP-16608 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 5.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2096,7 +2198,7 @@
</item>
<item>
<p>
- In <c>send_exit.c</c> an errorneous size of memory
+ In <c>send_exit.c</c> an erroneous size of memory
allocation could occur when reallocating a buffer.</p>
<p>
In <c>ei_decode_trace.c</c> the index could be updated
diff --git a/lib/erl_interface/include/ei.h b/lib/erl_interface/include/ei.h
index 84fad3f108..4876d93c30 100644
--- a/lib/erl_interface/include/ei.h
+++ b/lib/erl_interface/include/ei.h
@@ -397,20 +397,20 @@ typedef struct ei_x_buff_TAG {
/* Handle the connection */
int ei_connect_init(ei_cnode* ec, const char* this_node_name,
- const char *cookie, short creation);
+ const char *cookie, unsigned int creation);
int ei_connect_xinit (ei_cnode* ec, const char *thishostname,
const char *thisalivename, const char *thisnodename,
Erl_IpAddr thisipaddr, const char *cookie,
- const short creation);
+ unsigned int creation);
int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
- const char *cookie, short creation,
+ const char *cookie, unsigned int creation,
ei_socket_callbacks *cbs, int cbs_sz,
void *setup_context);
int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
const char *thisalivename, const char *thisnodename,
Erl_IpAddr thisipaddr, const char *cookie,
- const short creation, ei_socket_callbacks *cbs,
+ unsigned int creation, ei_socket_callbacks *cbs,
int cbs_sz, void *setup_context);
int ei_connect(ei_cnode* ec, char *nodename);
diff --git a/lib/erl_interface/src/Makefile b/lib/erl_interface/src/Makefile
index 6b5e2c1e61..9ca8310312 100644
--- a/lib/erl_interface/src/Makefile
+++ b/lib/erl_interface/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2020. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,12 +26,10 @@
include $(ERL_TOP)/make/output.mk
include $(ERL_TOP)/make/target.mk
-debug opt shared gcov:
+debug opt shared gcov lcnt valgrind asan:
ifndef TERTIARY_BOOTSTRAP
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile TYPE=$@
endif
clean depend docs release release_docs tests release_tests check xmllint:
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile $@
-
-lcnt:
diff --git a/lib/erl_interface/src/Makefile.in b/lib/erl_interface/src/Makefile.in
index 92459f6223..0a5ae800be 100644
--- a/lib/erl_interface/src/Makefile.in
+++ b/lib/erl_interface/src/Makefile.in
@@ -22,7 +22,7 @@
##
## This is a standalone make file for erl_interface. It is
## to be preprocessed by the configure script and the result
-## is saved into the TARGER directory.
+## is saved into the TARGET directory.
##
## We use 'vpath' to use plain C file names without the directory
## part in dependency rules.
@@ -405,7 +405,10 @@ MDD_EIOBJECTS = $(addprefix $(MDD_OBJDIR)/,$(notdir $(EISOURCES:.c=.o)))
# FIXME this assumes execution order
# FIXME move up and add exe prefix if needed....
-debug opt: $(TARGETS)
+opt: $(TARGETS)
+
+debug lcnt asan valgrind gcov:
+ @${MAKE} TYPE=$@
docs:
diff --git a/lib/erl_interface/src/README.internal b/lib/erl_interface/src/README.internal
index 51be1159d3..f0e27ec358 100644
--- a/lib/erl_interface/src/README.internal
+++ b/lib/erl_interface/src/README.internal
@@ -3,7 +3,7 @@
******************************************************************************
There are two different interfaces, the old 'erl_interface' and 'ei'.
-The old interface is to depend on the new one, not the other way arount.
+The old interface is to depend on the new one, not the other way around.
Erl_interface should be "thread safe", i.e. you should be able to
handle connections, convert data etc from different threads.
@@ -12,10 +12,6 @@ Ei should be "reentrant" or "async safe", i.e. no locks should be set
so that if an ei function is called inside an signal handler there
could be a deadlock.
-VxWorks call the operating processes "tasks". These are to be handled the
-same way as Unix threads, i.e. there can only be one C node for all tasks
-using the old interface.
-
Try to keep the documented functions, variables and symbols in sync
between
@@ -143,7 +139,7 @@ source. "eidef.h" contains some common constants and macros and
also includes config.h.
In general avoid including other header files from header files.
-The exception is to make the protoypes complete to the user of
+The exception is to make the prototypes complete to the user of
this library, i.e. to include <stdio.h> to defined FILE or
to include "ei_x_encode" to define the type ei_x_buff.
@@ -157,11 +153,11 @@ where size matters ;-) Use uint8 for buffers where we construct
messages.
NOTE!!!! Sending a "char" to macros like isupper(), isalpha() where
-the character is > 127 will cause serios problems on some
+the character is > 127 will cause serious problems on some
machines/OS. The reason is that
'char' may be unsigned, i.e. the Swedish char 'ä' will
- as a number be negativ.
+ as a number be negative.
The implementation of isupper() and others will on some
machines use an array that is indexed with the incoming
@@ -237,7 +233,7 @@ long" operations will create a dependency to a "hidden" library
libei.a[decode_longlong.o]: [6] | 0| 0|NOTY |GLOB |0 |UNDEF |__ashldi3
libei.a[decode_ulonglong.o]: [5] | 0| 0|NOTY |GLOB |0 |UNDEF |__ashldi3
-We can accept that a dependecy is created for code linked with
+We can accept that a dependency is created for code linked with
"libei.a" that actually use 'ei' long long functions. But if we
arrange the 'ei' source badly using a non "long long" functions from
'ei' will still link in an object file that need "libgcc.a". One
diff --git a/lib/erl_interface/src/auxdir/config.guess b/lib/erl_interface/src/auxdir/config.guess
deleted file mode 100755
index 1972fda8eb..0000000000
--- a/lib/erl_interface/src/auxdir/config.guess
+++ /dev/null
@@ -1,1700 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright 1992-2021 Free Software Foundation, Inc.
-
-timestamp='2021-01-25'
-
-# 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 3 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, see <https://www.gnu.org/licenses/>.
-#
-# 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. This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-#
-# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
-#
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-#
-# Please send patches to <config-patches@gnu.org>.
-
-
-me=$(echo "$0" | sed -e 's,.*/,,')
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Options:
- -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 <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright 1992-2021 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
-
-# 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.
-
-tmp=
-# shellcheck disable=SC2172
-trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
-
-set_cc_for_build() {
- # prevent multiple calls if $tmp is already set
- test "$tmp" && return 0
- : "${TMPDIR=/tmp}"
- # shellcheck disable=SC2039
- { 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" 2>/dev/null) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
- dummy=$tmp/dummy
- case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
- ,,) echo "int x;" > "$dummy.c"
- for driver in cc gcc c89 c99 ; do
- if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$driver"
- 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
-}
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if test -f /.attbin/uname ; 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
-
-case "$UNAME_SYSTEM" in
-Linux|GNU|GNU/*)
- LIBC=unknown
-
- set_cc_for_build
- cat <<-EOF > "$dummy.c"
- #include <features.h>
- #if defined(__UCLIBC__)
- LIBC=uclibc
- #elif defined(__dietlibc__)
- LIBC=dietlibc
- #elif defined(__GLIBC__)
- LIBC=gnu
- #else
- #include <stdarg.h>
- /* First heuristic to detect musl libc. */
- #ifdef __DEFINED_va_list
- LIBC=musl
- #endif
- #endif
- EOF
- eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
-
- # Second heuristic to detect musl libc.
- if [ "$LIBC" = unknown ] &&
- command -v ldd >/dev/null &&
- ldd --version 2>&1 | grep -q ^musl; then
- LIBC=musl
- fi
-
- # If the system lacks a compiler, then just pick glibc.
- # We could probably try harder.
- if [ "$LIBC" = unknown ]; then
- LIBC=gnu
- fi
- ;;
-esac
-
-# 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 tuples: *-*-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".
- UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
- /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
- /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
- echo unknown))
- case "$UNAME_MACHINE_ARCH" in
- aarch64eb) machine=aarch64_be-unknown ;;
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- sh5el) machine=sh5le-unknown ;;
- earmv*)
- arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
- endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
- machine="${arch}${endian}"-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) and ABI.
- case "$UNAME_MACHINE_ARCH" in
- earm*)
- os=netbsdelf
- ;;
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ELF__
- 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
- # Determine ABI tags.
- case "$UNAME_MACHINE_ARCH" in
- earm*)
- expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
- ;;
- 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/[-_].*//' | cut -d. -f1,2)
- ;;
- 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}${abi-}"
- exit ;;
- *:Bitrig:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
- exit ;;
- *:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
- exit ;;
- *:LibertyBSD:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
- exit ;;
- *:MidnightBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
- exit ;;
- *:ekkoBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
- exit ;;
- *:SolidBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
- exit ;;
- *:OS108:*:*)
- echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
- exit ;;
- macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
- exit ;;
- *:MirBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
- exit ;;
- *:Sortix:*:*)
- echo "$UNAME_MACHINE"-unknown-sortix
- exit ;;
- *:Twizzler:*:*)
- echo "$UNAME_MACHINE"-unknown-twizzler
- exit ;;
- *:Redox:*:*)
- echo "$UNAME_MACHINE"-unknown-redox
- exit ;;
- mips:OSF1:*.*)
- echo mips-dec-osf1
- 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)"
- # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
- exitcode=$?
- trap '' 0
- exit $exitcode ;;
- 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*:*:*)
- # akee@wpdis03.wpafb.af.mil (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 ;;
- s390x:SunOS:*:*)
- echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
- exit ;;
- 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:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux"$UNAME_RELEASE"
- exit ;;
- i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- set_cc_for_build
- SUN_ARCH=i386
- # If there is a compiler, see if it is configured for 64-bit objects.
- # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
- # This test works for both compilers.
- if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- SUN_ARCH=x86_64
- fi
- fi
- echo "$SUN_ARCH"-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)
- 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 test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
- then
- if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
- test "$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 test -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
- 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:*:[4567])
- 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 test -x /usr/bin/lslpp ; then
- IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
- awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
- 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:4.4BSD:*)
- 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 test -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 test "$HP_ARCH" = ""; then
- 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 test "$HP_ARCH" = hppa2.0w
- then
- 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 -q __LP64__
- 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:*:*)
- 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 test -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 ;;
- arm:FreeBSD:*:*)
- UNAME_PROCESSOR=$(uname -p)
- set_cc_for_build
- if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_PCS_VFP
- then
- echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
- else
- echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
- fi
- exit ;;
- *:FreeBSD:*:*)
- UNAME_PROCESSOR=$(/usr/bin/uname -p)
- case "$UNAME_PROCESSOR" in
- amd64)
- UNAME_PROCESSOR=x86_64 ;;
- i386)
- UNAME_PROCESSOR=i586 ;;
- esac
- echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
- exit ;;
- i*:CYGWIN*:*)
- echo "$UNAME_MACHINE"-pc-cygwin
- exit ;;
- *:MINGW64*:*)
- echo "$UNAME_MACHINE"-pc-mingw64
- exit ;;
- *:MINGW*:*)
- echo "$UNAME_MACHINE"-pc-mingw32
- exit ;;
- *:MSYS*:*)
- echo "$UNAME_MACHINE"-pc-msys
- exit ;;
- i*:PW*:*)
- echo "$UNAME_MACHINE"-pc-pw32
- exit ;;
- *:Interix*:*)
- case "$UNAME_MACHINE" in
- x86)
- echo i586-pc-interix"$UNAME_RELEASE"
- exit ;;
- authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix"$UNAME_RELEASE"
- exit ;;
- IA64)
- echo ia64-unknown-interix"$UNAME_RELEASE"
- exit ;;
- esac ;;
- i*:UWIN*:*)
- echo "$UNAME_MACHINE"-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-pc-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-$LIBC$(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 "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
- exit ;;
- *:Minix:*:*)
- echo "$UNAME_MACHINE"-unknown-minix
- exit ;;
- aarch64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- aarch64_be:Linux:*:*)
- UNAME_MACHINE=aarch64_be
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- alpha:Linux:*:*)
- case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) 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 -q ld.so.1
- if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- arc:Linux:*:* | arceb:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- arm*:Linux:*:*)
- set_cc_for_build
- if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_EABI__
- then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- else
- if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_PCS_VFP
- then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
- else
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
- fi
- fi
- exit ;;
- avr32*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- cris:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
- exit ;;
- crisv32:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
- exit ;;
- e2k:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- frv:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- hexagon:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- i*86:Linux:*:*)
- echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
- exit ;;
- ia64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- k1om:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- m32r*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- m68*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- mips:Linux:*:* | mips64:Linux:*:*)
- set_cc_for_build
- IS_GLIBC=0
- test x"${LIBC}" = xgnu && IS_GLIBC=1
- sed 's/^ //' << EOF > "$dummy.c"
- #undef CPU
- #undef mips
- #undef mipsel
- #undef mips64
- #undef mips64el
- #if ${IS_GLIBC} && defined(_ABI64)
- LIBCABI=gnuabi64
- #else
- #if ${IS_GLIBC} && defined(_ABIN32)
- LIBCABI=gnuabin32
- #else
- LIBCABI=${LIBC}
- #endif
- #endif
-
- #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
- CPU=mipsisa64r6
- #else
- #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
- CPU=mipsisa32r6
- #else
- #if defined(__mips64)
- CPU=mips64
- #else
- CPU=mips
- #endif
- #endif
- #endif
-
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- MIPS_ENDIAN=el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- MIPS_ENDIAN=
- #else
- MIPS_ENDIAN=
- #endif
- #endif
-EOF
- eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
- test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
- ;;
- mips64el:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- openrisc*:Linux:*:*)
- echo or1k-unknown-linux-"$LIBC"
- exit ;;
- or32:Linux:*:* | or1k*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- padre:Linux:*:*)
- echo sparc-unknown-linux-"$LIBC"
- exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-"$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-"$LIBC" ;;
- PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
- *) echo hppa-unknown-linux-"$LIBC" ;;
- esac
- exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-"$LIBC"
- exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-"$LIBC"
- exit ;;
- ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-"$LIBC"
- exit ;;
- ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-"$LIBC"
- exit ;;
- riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
- exit ;;
- sh64*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- sh*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- tile*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- vax:Linux:*:*)
- echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
- exit ;;
- x86_64:Linux:*:*)
- set_cc_for_build
- LIBCABI=$LIBC
- if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_X32 >/dev/null
- then
- LIBCABI="$LIBC"x32
- fi
- fi
- echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
- exit ;;
- xtensa*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- 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.[02]*:*)
- echo i386-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
- i*86:*DOS:*:*)
- echo "$UNAME_MACHINE"-pc-msdosdjgpp
- exit ;;
- i*86:*: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 i586.
- # Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configure will decide that
- # this is a cross-build.
- echo i586-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; } ;;
- NCR*:*:4.2:* | MPRAS*:*:4.2:*)
- OS_REL='.3'
- 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; }
- /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3"$OS_REL"; 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.[02]*:*)
- 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
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo "$UNAME_MACHINE"-stratus-vos
- exit ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- 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 test -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 ;;
- BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
- x86_64:Haiku:*:*)
- echo x86_64-unknown-haiku
- 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 ;;
- SX-ACE:SUPER-UX:*:*)
- echo sxace-nec-superux"$UNAME_RELEASE"
- exit ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody"$UNAME_RELEASE"
- exit ;;
- *:Rhapsody:*:*)
- echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
- exit ;;
- arm64:Darwin:*:*)
- echo aarch64-apple-darwin"$UNAME_RELEASE"
- exit ;;
- *:Darwin:*:*)
- UNAME_PROCESSOR=$(uname -p)
- case $UNAME_PROCESSOR in
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
- if command -v xcode-select > /dev/null 2> /dev/null && \
- ! xcode-select --print-path > /dev/null 2> /dev/null ; then
- # Avoid executing cc if there is no toolchain installed as
- # cc will be a stub that puts up a graphical alert
- # prompting the user to install developer tools.
- CC_FOR_BUILD=no_compiler_found
- else
- set_cc_for_build
- fi
- if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
- # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
- if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_PPC >/dev/null
- then
- UNAME_PROCESSOR=powerpc
- fi
- elif test "$UNAME_PROCESSOR" = i386 ; then
- # uname -m returns i386 or x86_64
- UNAME_PROCESSOR=$UNAME_MACHINE
- fi
- 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 ;;
- NEO-*:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSR-*:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSV-*:NONSTOP_KERNEL:*:*)
- echo nsv-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSX-*:NONSTOP_KERNEL:*:*)
- echo nsx-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.
- # shellcheck disable=SC2154
- 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 ;;
- *:AROS:*:*)
- echo "$UNAME_MACHINE"-unknown-aros
- exit ;;
- x86_64:VMkernel:*:*)
- echo "$UNAME_MACHINE"-unknown-esx
- exit ;;
- amd64:Isilon\ OneFS:*:*)
- echo x86_64-unknown-onefs
- exit ;;
- *:Unleashed:*:*)
- echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
- exit ;;
-esac
-
-# No uname command or uname output not recognized.
-set_cc_for_build
-cat > "$dummy.c" <<EOF
-#ifdef _SEQUENT_
-#include <sys/types.h>
-#include <sys/utsname.h>
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
-#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#include <signal.h>
-#if defined(_SIZE_T_) || defined(SIGLOST)
-#include <sys/utsname.h>
-#endif
-#endif
-#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 (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
-#if defined(_SIZE_T_) || defined(SIGLOST)
- struct utsname un;
- uname (&un);
- printf ("vax-dec-ultrix%s\n", un.release); exit (0);
-#else
- printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
-#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#if defined(_SIZE_T_) || defined(SIGLOST)
- struct utsname *un;
- uname (&un);
- printf ("mips-dec-ultrix%s\n", un.release); exit (0);
-#else
- printf ("mips-dec-ultrix\n"); exit (0);
-#endif
-#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; }
-
-echo "$0: unable to guess system type" >&2
-
-case "$UNAME_MACHINE:$UNAME_SYSTEM" in
- mips:Linux | mips64:Linux)
- # If we got here on MIPS GNU/Linux, output extra information.
- cat >&2 <<EOF
-
-NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
-the system type. Please install a C compiler and try again.
-EOF
- ;;
-esac
-
-cat >&2 <<EOF
-
-This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite *all*
-copies of config.guess and config.sub with the latest versions from:
-
- https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-and
- https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-EOF
-
-year=$(echo $timestamp | sed 's,-.*,,')
-# shellcheck disable=SC2003
-if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
- cat >&2 <<EOF
-
-If $0 has already been updated, send the following data and any
-information you think might be pertinent to config-patches@gnu.org to
-provide the necessary 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
-fi
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'before-save-hook '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
deleted file mode 100755
index 63c1f1c8b5..0000000000
--- a/lib/erl_interface/src/auxdir/config.sub
+++ /dev/null
@@ -1,1860 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright 1992-2021 Free Software Foundation, Inc.
-
-timestamp='2021-01-08'
-
-# 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 3 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, see <https://www.gnu.org/licenses/>.
-#
-# 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. This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-
-
-# Please send patches to <config-patches@gnu.org>.
-#
-# 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.
-
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-
-# 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 or ALIAS
-
-Canonicalize a configuration name.
-
-Options:
- -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 <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright 1992-2021 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 ;;
-
- *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
-
-# Split fields of configuration type
-# shellcheck disable=SC2162
-IFS="-" read field1 field2 field3 field4 <<EOF
-$1
-EOF
-
-# Separate into logical components for further validation
-case $1 in
- *-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
- exit 1
- ;;
- *-*-*-*)
- basic_machine=$field1-$field2
- basic_os=$field3-$field4
- ;;
- *-*-*)
- # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
- # parts
- maybe_os=$field2-$field3
- case $maybe_os in
- nto-qnx* | linux-* | uclinux-uclibc* \
- | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
- | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova*)
- basic_machine=$field1
- basic_os=$maybe_os
- ;;
- android-linux)
- basic_machine=$field1-unknown
- basic_os=linux-android
- ;;
- *)
- basic_machine=$field1-$field2
- basic_os=$field3
- ;;
- esac
- ;;
- *-*)
- # A lone config we happen to match not fitting any pattern
- case $field1-$field2 in
- decstation-3100)
- basic_machine=mips-dec
- basic_os=
- ;;
- *-*)
- # Second component is usually, but not always the OS
- case $field2 in
- # Prevent following clause from handling this valid os
- sun*os*)
- basic_machine=$field1
- basic_os=$field2
- ;;
- # Manufacturers
- dec* | mips* | sequent* | encore* | pc533* | 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 \
- | microblaze* | sim | cisco \
- | oki | wec | wrs | winbond)
- basic_machine=$field1-$field2
- basic_os=
- ;;
- *)
- basic_machine=$field1
- basic_os=$field2
- ;;
- esac
- ;;
- esac
- ;;
- *)
- # Convert single-component short-hands not valid as part of
- # multi-component configurations.
- case $field1 in
- 386bsd)
- basic_machine=i386-pc
- basic_os=bsd
- ;;
- a29khif)
- basic_machine=a29k-amd
- basic_os=udi
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- basic_os=scout
- ;;
- alliant)
- basic_machine=fx80-alliant
- basic_os=
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- basic_os=
- ;;
- am29k)
- basic_machine=a29k-none
- basic_os=bsd
- ;;
- amdahl)
- basic_machine=580-amdahl
- basic_os=sysv
- ;;
- amiga)
- basic_machine=m68k-unknown
- basic_os=
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- basic_os=amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- basic_os=sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- basic_os=sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- basic_os=bsd
- ;;
- aros)
- basic_machine=i386-pc
- basic_os=aros
- ;;
- aux)
- basic_machine=m68k-apple
- basic_os=aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- basic_os=dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- basic_os=linux
- ;;
- cegcc)
- basic_machine=arm-unknown
- basic_os=cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- basic_os=bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- basic_os=bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- basic_os=bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- basic_os=bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- basic_os=bsd
- ;;
- cray)
- basic_machine=j90-cray
- basic_os=unicos
- ;;
- crds | unos)
- basic_machine=m68k-crds
- basic_os=
- ;;
- da30)
- basic_machine=m68k-da30
- basic_os=
- ;;
- decstation | pmax | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- basic_os=
- ;;
- delta88)
- basic_machine=m88k-motorola
- basic_os=sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- basic_os=dicos
- ;;
- djgpp)
- basic_machine=i586-pc
- basic_os=msdosdjgpp
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- basic_os=ebmon
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- basic_os=ose
- ;;
- gmicro)
- basic_machine=tron-gmicro
- basic_os=sysv
- ;;
- go32)
- basic_machine=i386-pc
- basic_os=go32
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- basic_os=hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- basic_os=xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- basic_os=hms
- ;;
- harris)
- basic_machine=m88k-harris
- basic_os=sysv3
- ;;
- hp300 | hp300hpux)
- basic_machine=m68k-hp
- basic_os=hpux
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- basic_os=bsd
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- basic_os=osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- basic_os=proelf
- ;;
- i386mach)
- basic_machine=i386-mach
- basic_os=mach
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- basic_os=sysv
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- basic_os=linux
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- basic_os=sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- basic_os=sysv
- ;;
- mingw64)
- basic_machine=x86_64-pc
- basic_os=mingw64
- ;;
- mingw32)
- basic_machine=i686-pc
- basic_os=mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- basic_os=mingw32ce
- ;;
- monitor)
- basic_machine=m68k-rom68k
- basic_os=coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- basic_os=morphos
- ;;
- moxiebox)
- basic_machine=moxie-unknown
- basic_os=moxiebox
- ;;
- msdos)
- basic_machine=i386-pc
- basic_os=msdos
- ;;
- msys)
- basic_machine=i686-pc
- basic_os=msys
- ;;
- mvs)
- basic_machine=i370-ibm
- basic_os=mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- basic_os=nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- basic_os=sysv4
- ;;
- netbsd386)
- basic_machine=i386-pc
- basic_os=netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- basic_os=linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- basic_os=newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- basic_os=newsos
- ;;
- necv70)
- basic_machine=v70-nec
- basic_os=sysv
- ;;
- nh3000)
- basic_machine=m68k-harris
- basic_os=cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- basic_os=cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- basic_os=nindy
- ;;
- mon960)
- basic_machine=i960-intel
- basic_os=mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- basic_os=nonstopux
- ;;
- os400)
- basic_machine=powerpc-ibm
- basic_os=os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- basic_os=ose
- ;;
- os68k)
- basic_machine=m68k-none
- basic_os=os68k
- ;;
- paragon)
- basic_machine=i860-intel
- basic_os=osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- basic_os=linux
- ;;
- psp)
- basic_machine=mipsallegrexel-sony
- basic_os=psp
- ;;
- pw32)
- basic_machine=i586-unknown
- basic_os=pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- basic_os=rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- basic_os=rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- basic_os=coff
- ;;
- sa29200)
- basic_machine=a29k-amd
- basic_os=udi
- ;;
- sei)
- basic_machine=mips-sei
- basic_os=seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- basic_os=
- ;;
- sps7)
- basic_machine=m68k-bull
- basic_os=sysv2
- ;;
- st2000)
- basic_machine=m68k-tandem
- basic_os=
- ;;
- stratus)
- basic_machine=i860-stratus
- basic_os=sysv4
- ;;
- sun2)
- basic_machine=m68000-sun
- basic_os=
- ;;
- sun2os3)
- basic_machine=m68000-sun
- basic_os=sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- basic_os=sunos4
- ;;
- sun3)
- basic_machine=m68k-sun
- basic_os=
- ;;
- sun3os3)
- basic_machine=m68k-sun
- basic_os=sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- basic_os=sunos4
- ;;
- sun4)
- basic_machine=sparc-sun
- basic_os=
- ;;
- sun4os3)
- basic_machine=sparc-sun
- basic_os=sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- basic_os=sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- basic_os=solaris2
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- basic_os=
- ;;
- sv1)
- basic_machine=sv1-cray
- basic_os=unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- basic_os=dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- basic_os=unicos
- ;;
- t90)
- basic_machine=t90-cray
- basic_os=unicos
- ;;
- toad1)
- basic_machine=pdp10-xkl
- basic_os=tops20
- ;;
- tpf)
- basic_machine=s390x-ibm
- basic_os=tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- basic_os=udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- basic_os=sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- basic_os=none
- ;;
- vaxv)
- basic_machine=vax-dec
- basic_os=sysv
- ;;
- vms)
- basic_machine=vax-dec
- basic_os=vms
- ;;
- vsta)
- basic_machine=i386-pc
- basic_os=vsta
- ;;
- vxworks960)
- basic_machine=i960-wrs
- basic_os=vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- basic_os=vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- basic_os=vxworks
- ;;
- xbox)
- basic_machine=i686-pc
- basic_os=mingw32
- ;;
- ymp)
- basic_machine=ymp-cray
- basic_os=unicos
- ;;
- *)
- basic_machine=$1
- basic_os=
- ;;
- esac
- ;;
-esac
-
-# Decode 1-component or ad-hoc basic machines
-case $basic_machine in
- # 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)
- cpu=hppa1.1
- vendor=winbond
- ;;
- op50n)
- cpu=hppa1.1
- vendor=oki
- ;;
- op60c)
- cpu=hppa1.1
- vendor=oki
- ;;
- ibm*)
- cpu=i370
- vendor=ibm
- ;;
- orion105)
- cpu=clipper
- vendor=highlevel
- ;;
- mac | mpw | mac-mpw)
- cpu=m68k
- vendor=apple
- ;;
- pmac | pmac-mpw)
- cpu=powerpc
- vendor=apple
- ;;
-
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- cpu=m68000
- vendor=att
- ;;
- 3b*)
- cpu=we32k
- vendor=att
- ;;
- bluegene*)
- cpu=powerpc
- vendor=ibm
- basic_os=cnk
- ;;
- decsystem10* | dec10*)
- cpu=pdp10
- vendor=dec
- basic_os=tops10
- ;;
- decsystem20* | dec20*)
- cpu=pdp10
- vendor=dec
- basic_os=tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- cpu=m68k
- vendor=motorola
- ;;
- dpx2*)
- cpu=m68k
- vendor=bull
- basic_os=sysv3
- ;;
- encore | umax | mmax)
- cpu=ns32k
- vendor=encore
- ;;
- elxsi)
- cpu=elxsi
- vendor=elxsi
- basic_os=${basic_os:-bsd}
- ;;
- fx2800)
- cpu=i860
- vendor=alliant
- ;;
- genix)
- cpu=ns32k
- vendor=ns
- ;;
- h3050r* | hiux*)
- cpu=hppa1.1
- vendor=hitachi
- basic_os=hiuxwe2
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- cpu=hppa1.0
- vendor=hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- cpu=m68000
- vendor=hp
- ;;
- hp9k3[2-9][0-9])
- cpu=m68k
- vendor=hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- cpu=hppa1.0
- vendor=hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- cpu=hppa1.0
- vendor=hp
- ;;
- i*86v32)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=sysv32
- ;;
- i*86v4*)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=sysv4
- ;;
- i*86v)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=sysv
- ;;
- i*86sol2)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=solaris2
- ;;
- j90 | j90-cray)
- cpu=j90
- vendor=cray
- basic_os=${basic_os:-unicos}
- ;;
- iris | iris4d)
- cpu=mips
- vendor=sgi
- case $basic_os in
- irix*)
- ;;
- *)
- basic_os=irix4
- ;;
- esac
- ;;
- miniframe)
- cpu=m68000
- vendor=convergent
- ;;
- *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
- cpu=m68k
- vendor=atari
- basic_os=mint
- ;;
- news-3600 | risc-news)
- cpu=mips
- vendor=sony
- basic_os=newsos
- ;;
- next | m*-next)
- cpu=m68k
- vendor=next
- case $basic_os in
- openstep*)
- ;;
- nextstep*)
- ;;
- ns2*)
- basic_os=nextstep2
- ;;
- *)
- basic_os=nextstep3
- ;;
- esac
- ;;
- np1)
- cpu=np1
- vendor=gould
- ;;
- op50n-* | op60c-*)
- cpu=hppa1.1
- vendor=oki
- basic_os=proelf
- ;;
- pa-hitachi)
- cpu=hppa1.1
- vendor=hitachi
- basic_os=hiuxwe2
- ;;
- pbd)
- cpu=sparc
- vendor=tti
- ;;
- pbb)
- cpu=m68k
- vendor=tti
- ;;
- pc532)
- cpu=ns32k
- vendor=pc532
- ;;
- pn)
- cpu=pn
- vendor=gould
- ;;
- power)
- cpu=power
- vendor=ibm
- ;;
- ps2)
- cpu=i386
- vendor=ibm
- ;;
- rm[46]00)
- cpu=mips
- vendor=siemens
- ;;
- rtpc | rtpc-*)
- cpu=romp
- vendor=ibm
- ;;
- sde)
- cpu=mipsisa32
- vendor=sde
- basic_os=${basic_os:-elf}
- ;;
- simso-wrs)
- cpu=sparclite
- vendor=wrs
- basic_os=vxworks
- ;;
- tower | tower-32)
- cpu=m68k
- vendor=ncr
- ;;
- vpp*|vx|vx-*)
- cpu=f301
- vendor=fujitsu
- ;;
- w65)
- cpu=w65
- vendor=wdc
- ;;
- w89k-*)
- cpu=hppa1.1
- vendor=winbond
- basic_os=proelf
- ;;
- none)
- cpu=none
- vendor=none
- ;;
- leon|leon[3-9])
- cpu=sparc
- vendor=$basic_machine
- ;;
- leon-*|leon[3-9]-*)
- cpu=sparc
- vendor=$(echo "$basic_machine" | sed 's/-.*//')
- ;;
-
- *-*)
- # shellcheck disable=SC2162
- IFS="-" read cpu vendor <<EOF
-$basic_machine
-EOF
- ;;
- # 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)
- cpu=$basic_machine
- vendor=pc
- ;;
- # These rules are duplicated from below for sake of the special case above;
- # i.e. things that normalized to x86 arches should also default to "pc"
- pc98)
- cpu=i386
- vendor=pc
- ;;
- x64 | amd64)
- cpu=x86_64
- vendor=pc
- ;;
- # Recognize the basic CPU types without company name.
- *)
- cpu=$basic_machine
- vendor=unknown
- ;;
-esac
-
-unset -v basic_machine
-
-# Decode basic machines in the full and proper CPU-Company form.
-case $cpu-$vendor in
- # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
- # some cases the only manufacturer, in others, it is the most popular.
- craynv-unknown)
- vendor=cray
- basic_os=${basic_os:-unicosmp}
- ;;
- c90-unknown | c90-cray)
- vendor=cray
- basic_os=${Basic_os:-unicos}
- ;;
- fx80-unknown)
- vendor=alliant
- ;;
- romp-unknown)
- vendor=ibm
- ;;
- mmix-unknown)
- vendor=knuth
- ;;
- microblaze-unknown | microblazeel-unknown)
- vendor=xilinx
- ;;
- rs6000-unknown)
- vendor=ibm
- ;;
- vax-unknown)
- vendor=dec
- ;;
- pdp11-unknown)
- vendor=dec
- ;;
- we32k-unknown)
- vendor=att
- ;;
- cydra-unknown)
- vendor=cydrome
- ;;
- i370-ibm*)
- vendor=ibm
- ;;
- orion-unknown)
- vendor=highlevel
- ;;
- xps-unknown | xps100-unknown)
- cpu=xps100
- vendor=honeywell
- ;;
-
- # Here we normalize CPU types with a missing or matching vendor
- dpx20-unknown | dpx20-bull)
- cpu=rs6000
- vendor=bull
- basic_os=${basic_os:-bosx}
- ;;
-
- # Here we normalize CPU types irrespective of the vendor
- amd64-*)
- cpu=x86_64
- ;;
- blackfin-*)
- cpu=bfin
- basic_os=linux
- ;;
- c54x-*)
- cpu=tic54x
- ;;
- c55x-*)
- cpu=tic55x
- ;;
- c6x-*)
- cpu=tic6x
- ;;
- e500v[12]-*)
- cpu=powerpc
- basic_os=${basic_os}"spe"
- ;;
- mips3*-*)
- cpu=mips64
- ;;
- ms1-*)
- cpu=mt
- ;;
- m68knommu-*)
- cpu=m68k
- basic_os=linux
- ;;
- m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
- cpu=s12z
- ;;
- openrisc-*)
- cpu=or32
- ;;
- parisc-*)
- cpu=hppa
- basic_os=linux
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- cpu=i586
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
- cpu=i686
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- cpu=i686
- ;;
- pentium4-*)
- cpu=i786
- ;;
- pc98-*)
- cpu=i386
- ;;
- ppc-* | ppcbe-*)
- cpu=powerpc
- ;;
- ppcle-* | powerpclittle-*)
- cpu=powerpcle
- ;;
- ppc64-*)
- cpu=powerpc64
- ;;
- ppc64le-* | powerpc64little-*)
- cpu=powerpc64le
- ;;
- sb1-*)
- cpu=mipsisa64sb1
- ;;
- sb1el-*)
- cpu=mipsisa64sb1el
- ;;
- sh5e[lb]-*)
- cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/')
- ;;
- spur-*)
- cpu=spur
- ;;
- strongarm-* | thumb-*)
- cpu=arm
- ;;
- tx39-*)
- cpu=mipstx39
- ;;
- tx39el-*)
- cpu=mipstx39el
- ;;
- x64-*)
- cpu=x86_64
- ;;
- xscale-* | xscalee[bl]-*)
- cpu=$(echo "$cpu" | sed 's/^xscale/arm/')
- ;;
- arm64-*)
- cpu=aarch64
- ;;
-
- # Recognize the canonical CPU Types that limit and/or modify the
- # company names they are paired with.
- cr16-*)
- basic_os=${basic_os:-elf}
- ;;
- crisv32-* | etraxfs*-*)
- cpu=crisv32
- vendor=axis
- ;;
- cris-* | etrax*-*)
- cpu=cris
- vendor=axis
- ;;
- crx-*)
- basic_os=${basic_os:-elf}
- ;;
- neo-tandem)
- cpu=neo
- vendor=tandem
- ;;
- nse-tandem)
- cpu=nse
- vendor=tandem
- ;;
- nsr-tandem)
- cpu=nsr
- vendor=tandem
- ;;
- nsv-tandem)
- cpu=nsv
- vendor=tandem
- ;;
- nsx-tandem)
- cpu=nsx
- vendor=tandem
- ;;
- mipsallegrexel-sony)
- cpu=mipsallegrexel
- vendor=sony
- ;;
- tile*-*)
- basic_os=${basic_os:-linux-gnu}
- ;;
-
- *)
- # Recognize the canonical CPU types that are allowed with any
- # company name.
- case $cpu in
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | abacus \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
- | alphapca5[67] | alpha64pca5[67] \
- | am33_2.0 \
- | amdgcn \
- | arc | arceb \
- | arm | arm[lb]e | arme[lb] | armv* \
- | avr | avr32 \
- | asmjs \
- | ba \
- | be32 | be64 \
- | bfin | bpf | bs2000 \
- | c[123]* | c30 | [cjt]90 | c4x \
- | c8051 | clipper | craynv | csky | cydra \
- | d10v | d30v | dlx | dsp16xx \
- | e2k | elxsi | epiphany \
- | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
- | h8300 | h8500 \
- | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i*86 | i860 | i960 | ia16 | ia64 \
- | ip2k | iq2000 \
- | k1om \
- | le32 | le64 \
- | lm32 \
- | loongarch32 | loongarch64 | loongarchx32 \
- | m32c | m32r | m32rle \
- | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
- | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
- | m88110 | m88k | maxq | mb | mcore | mep | metag \
- | microblaze | microblazeel \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64eb | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
- | mmix \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nfp \
- | nios | nios2 | nios2eb | nios2el \
- | none | np1 | ns16k | ns32k | nvptx \
- | open8 \
- | or1k* \
- | or32 \
- | orion \
- | picochip \
- | pdp10 | pdp11 | pj | pjl | pn | power \
- | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
- | pru \
- | pyramid \
- | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
- | rl78 | romp | rs6000 | rx \
- | s390 | s390x \
- | score \
- | sh | shl \
- | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
- | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
- | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
- | spu \
- | tahoe \
- | thumbv7* \
- | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
- | tron \
- | ubicom32 \
- | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
- | vax \
- | visium \
- | w65 \
- | wasm32 | wasm64 \
- | we32k \
- | x86 | x86_64 | xc16x | xgate | xps100 \
- | xstormy16 | xtensa* \
- | ymp \
- | z8k | z80)
- ;;
-
- *)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
- exit 1
- ;;
- esac
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $vendor in
- digital*)
- vendor=dec
- ;;
- commodore*)
- vendor=cbm
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if test x$basic_os != x
-then
-
-# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
-# set os.
-case $basic_os in
- gnu/linux*)
- kernel=linux
- os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
- ;;
- os2-emx)
- kernel=os2
- os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
- ;;
- nto-qnx*)
- kernel=nto
- os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|')
- ;;
- *-*)
- # shellcheck disable=SC2162
- IFS="-" read kernel os <<EOF
-$basic_os
-EOF
- ;;
- # Default OS when just kernel was specified
- nto*)
- kernel=nto
- os=$(echo $basic_os | sed -e 's|nto|qnx|')
- ;;
- linux*)
- kernel=linux
- os=$(echo $basic_os | sed -e 's|linux|gnu|')
- ;;
- *)
- kernel=
- os=$basic_os
- ;;
-esac
-
-# Now, normalize the OS (knowing we just have one component, it's not a kernel,
-# etc.)
-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.
- auroraux)
- os=auroraux
- ;;
- bluegene*)
- os=cnk
- ;;
- solaris1 | solaris1.*)
- os=$(echo $os | sed -e 's|solaris1|sunos4|')
- ;;
- solaris)
- os=solaris2
- ;;
- unixware*)
- os=sysv4.2uw
- ;;
- # es1800 is here to avoid being matched by es* (a different OS)
- es1800*)
- os=ose
- ;;
- # Some version numbers need modification
- chorusos*)
- os=chorusos
- ;;
- isc)
- os=isc2.2
- ;;
- sco6)
- os=sco5v6
- ;;
- sco5)
- os=sco3.2v5
- ;;
- sco4)
- os=sco3.2v4
- ;;
- sco3.2.[4-9]*)
- os=$(echo $os | sed -e 's/sco3.2./sco3.2v/')
- ;;
- sco*v* | scout)
- # Don't match below
- ;;
- sco*)
- os=sco3.2v2
- ;;
- psos*)
- os=psos
- ;;
- qnx*)
- os=qnx
- ;;
- hiux*)
- os=hiuxwe2
- ;;
- lynx*178)
- os=lynxos178
- ;;
- lynx*5)
- os=lynxos5
- ;;
- lynxos*)
- # don't get caught up in next wildcard
- ;;
- lynx*)
- os=lynxos
- ;;
- mac[0-9]*)
- os=$(echo "$os" | sed -e 's|mac|macos|')
- ;;
- opened*)
- os=openedition
- ;;
- os400*)
- os=os400
- ;;
- sunos5*)
- os=$(echo "$os" | sed -e 's|sunos5|solaris2|')
- ;;
- sunos6*)
- os=$(echo "$os" | sed -e 's|sunos6|solaris3|')
- ;;
- wince*)
- os=wince
- ;;
- 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
- ;;
- # 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
- ;;
- ose*)
- os=ose
- ;;
- *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
- os=mint
- ;;
- dicos*)
- os=dicos
- ;;
- pikeos*)
- # Until real need of OS specific support for
- # particular features comes up, bare metal
- # configurations are quite functional.
- case $cpu in
- arm*)
- os=eabi
- ;;
- *)
- os=elf
- ;;
- esac
- ;;
- *)
- # No normalization, but not necessarily accepted, that comes below.
- ;;
-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.
-
-kernel=
-case $cpu-$vendor in
- score-*)
- os=elf
- ;;
- spu-*)
- os=elf
- ;;
- *-acorn)
- os=riscix1.2
- ;;
- arm*-rebel)
- kernel=linux
- os=gnu
- ;;
- arm*-semi)
- os=aout
- ;;
- c4x-* | tic4x-*)
- os=coff
- ;;
- c8051-*)
- os=elf
- ;;
- clipper-intergraph)
- os=clix
- ;;
- hexagon-*)
- os=elf
- ;;
- tic54x-*)
- os=coff
- ;;
- tic55x-*)
- os=coff
- ;;
- tic6x-*)
- 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
- ;;
- 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
- ;;
- pru-*)
- os=elf
- ;;
- *-be)
- os=beos
- ;;
- *-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
- ;;
- *-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
- ;;
- *-wrs)
- os=vxworks
- ;;
- *)
- os=none
- ;;
-esac
-
-fi
-
-# Now, validate our (potentially fixed-up) OS.
-case $os in
- # Sometimes we do "kernel-libc", so those need to count as OSes.
- musl* | newlib* | uclibc*)
- ;;
- # Likewise for "kernel-abi"
- eabi* | gnueabi*)
- ;;
- # VxWorks passes extra cpu info in the 4th filed.
- simlinux | simwindows | spe)
- ;;
- # Now accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST end in a * to match a version number.
- gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
- | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
- | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
- | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
- | hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* \
- | mpw* | magic* | mmixware* | mon960* | lnews* \
- | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
- | aos* | aros* | cloudabi* | sortix* | twizzler* \
- | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
- | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
- | mirbsd* | netbsd* | dicos* | openedition* | ose* \
- | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
- | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
- | udi* | lites* | ieee* | go32* | aux* | hcos* \
- | chorusrdb* | cegcc* | glidix* \
- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
- | midipix* | mingw32* | mingw64* | mint* \
- | uxpv* | beos* | mpeix* | udk* | moxiebox* \
- | interix* | uwin* | mks* | rhapsody* | darwin* \
- | openstep* | oskit* | conix* | pw32* | nonstopux* \
- | storm-chaos* | tops10* | tenex* | tops20* | its* \
- | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
- | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
- | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
- | skyos* | haiku* | rdos* | toppers* | drops* | es* \
- | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
- | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
- ;;
- # This one is extra strict with allowed versions
- sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- ;;
- none)
- ;;
- *)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# As a final step for OS-related things, validate the OS-kernel combination
-# (given a valid OS), if there is a kernel.
-case $kernel-$os in
- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
- ;;
- uclinux-uclibc* )
- ;;
- -dietlibc* | -newlib* | -musl* | -uclibc* )
- # These are just libc implementations, not actual OSes, and thus
- # require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
- exit 1
- ;;
- kfreebsd*-gnu* | kopensolaris*-gnu*)
- ;;
- vxworks-simlinux | vxworks-simwindows | vxworks-spe)
- ;;
- nto-qnx*)
- ;;
- os2-emx)
- ;;
- *-eabi* | *-gnueabi*)
- ;;
- -*)
- # Blank kernel with real OS is always fine.
- ;;
- *-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
- exit 1
- ;;
-esac
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-case $vendor in
- unknown)
- case $cpu-$os in
- *-riscix*)
- vendor=acorn
- ;;
- *-sunos*)
- vendor=sun
- ;;
- *-cnk* | *-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
- ;;
- *-clix*)
- vendor=intergraph
- ;;
- *-mvs* | *-opened*)
- vendor=ibm
- ;;
- *-os400*)
- vendor=ibm
- ;;
- s390-* | s390x-*)
- 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
- ;;
-esac
-
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
-exit
-
-# Local variables:
-# eval: (add-hook 'before-save-hook '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
deleted file mode 100755
index ec298b5374..0000000000
--- a/lib/erl_interface/src/auxdir/install-sh
+++ /dev/null
@@ -1,541 +0,0 @@
-#!/bin/sh
-# install - install a program, script, or datafile
-
-scriptversion=2020-11-14.01; # UTC
-
-# 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.
-
-tab=' '
-nl='
-'
-IFS=" $tab$nl"
-
-# Set DOITPROG to "echo" to test this script.
-
-doit=${DOITPROG-}
-doit_exec=${doit:-exec}
-
-# 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_mkdir=
-
-# Desired mode of installed file.
-mode=0755
-
-# Create dirs (including intermediate dirs) using mode 755.
-# This is like GNU 'install' as of coreutils 8.32 (2020).
-mkdir_umask=22
-
-backupsuffix=
-chgrpcmd=
-chmodcmd=$chmodprog
-chowncmd=
-mvcmd=$mvprog
-rmcmd="$rmprog -f"
-stripcmd=
-
-src=
-dst=
-dir_arg=
-dst_arg=
-
-copy_on_change=false
-is_target_a_directory=possibly
-
-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 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.
- -p pass -p to $cpprog.
- -s $stripprog installed files.
- -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
- -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
-
-By default, rm is invoked with -f; when overridden with RMPROG,
-it's up to you to specify -f if you want it.
-
-If -S is not specified, no backups are attempted.
-
-Email bug reports to bug-automake@gnu.org.
-Automake home page: https://www.gnu.org/software/automake/
-"
-
-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
- *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
- echo "$0: invalid mode: $mode" >&2
- exit 1;;
- esac
- shift;;
-
- -o) chowncmd="$chownprog $2"
- shift;;
-
- -p) cpprog="$cpprog -p";;
-
- -s) stripcmd=$stripprog;;
-
- -S) backupsuffix="$2"
- shift;;
-
- -t)
- is_target_a_directory=always
- dst_arg=$2
- # Protect names problematic for 'test' and other utilities.
- case $dst_arg in
- -* | [=\(\)!]) dst_arg=./$dst_arg;;
- esac
- shift;;
-
- -T) is_target_a_directory=never;;
-
- --version) echo "$0 $scriptversion"; exit $?;;
-
- --) shift
- break;;
-
- -*) echo "$0: invalid option: $1" >&2
- exit 1;;
-
- *) break;;
- esac
- shift
-done
-
-# We allow the use of options -d and -T together, by making -d
-# take the precedence; this is for compatibility with GNU install.
-
-if test -n "$dir_arg"; then
- if test -n "$dst_arg"; then
- echo "$0: target directory not allowed when installing a directory." >&2
- exit 1
- fi
-fi
-
-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
- # Protect names problematic for 'test' and other utilities.
- case $dst_arg in
- -* | [=\(\)!]) dst_arg=./$dst_arg;;
- esac
- 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
- if test $# -gt 1 || test "$is_target_a_directory" = always; then
- if test ! -d "$dst_arg"; then
- echo "$0: $dst_arg: Is not a directory." >&2
- exit 1
- fi
- fi
-fi
-
-if test -z "$dir_arg"; then
- do_exit='(exit $ret); exit $ret'
- trap "ret=129; $do_exit" 1
- trap "ret=130; $do_exit" 2
- trap "ret=141; $do_exit" 13
- trap "ret=143; $do_exit" 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 problematic for 'test' and other utilities.
- case $src in
- -* | [=\(\)!]) src=./$src;;
- esac
-
- if test -n "$dir_arg"; then
- dst=$src
- dstdir=$dst
- test -d "$dstdir"
- dstdir_status=$?
- # Don't chown directories that already exist.
- if test $dstdir_status = 0; then
- chowncmd=""
- fi
- 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
-
- # If destination is a directory, append the input filename.
- if test -d "$dst"; then
- if test "$is_target_a_directory" = never; then
- echo "$0: $dst_arg: Is a directory" >&2
- exit 1
- fi
- dstdir=$dst
- dstbase=`basename "$src"`
- case $dst in
- */) dst=$dst$dstbase;;
- *) dst=$dst/$dstbase;;
- esac
- dstdir_status=0
- else
- dstdir=`dirname "$dst"`
- test -d "$dstdir"
- dstdir_status=$?
- fi
- fi
-
- case $dstdir in
- */) dstdirslash=$dstdir;;
- *) dstdirslash=$dstdir/;;
- esac
-
- obsolete_mkdir_used=false
-
- if test $dstdir_status != 0; then
- case $posix_mkdir in
- '')
- # 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
- # The $RANDOM variable is not portable (e.g., dash). Use it
- # here however when possible just to lower collision chance.
- tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
-
- trap '
- ret=$?
- rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
- exit $ret
- ' 0
-
- # Because "mkdir -p" follows existing symlinks and we likely work
- # directly in world-writeable /tmp, make sure that the '$tmpdir'
- # directory is successfully created first before we actually test
- # 'mkdir -p'.
- if (umask $mkdir_umask &&
- $mkdirprog $mkdir_mode "$tmpdir" &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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-writable bit of parent directory when it shouldn't.
- # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- test_tmpdir="$tmpdir/a"
- ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
- case $ls_ld_tmpdir in
- d????-?r-*) different_mode=700;;
- d????-?--*) different_mode=755;;
- *) false;;
- esac &&
- $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
- test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
- }
- }
- then posix_mkdir=:
- fi
- rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
- else
- # Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
- fi
- trap '' 0;;
- esac
-
- if
- $posix_mkdir && (
- umask $mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
- )
- then :
- else
-
- # 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
-
- oIFS=$IFS
- IFS=/
- set -f
- set fnord $dstdir
- shift
- set +f
- IFS=$oIFS
-
- prefixes=
-
- for d
- do
- test X"$d" = X && 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=${dstdirslash}_inst.$$_
- rmtmp=${dstdirslash}_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 &&
- { test -z "$stripcmd" || {
- # Create $dsttmp read-write so that cp doesn't create it read-only,
- # which would cause strip to fail.
- if test -z "$doit"; then
- : >"$dsttmp" # No need to fork-exec 'touch'.
- else
- $doit touch "$dsttmp"
- fi
- }
- } &&
- $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` &&
- set -f &&
- set X $old && old=:$2:$4:$5:$6 &&
- set X $new && new=:$2:$4:$5:$6 &&
- set +f &&
- test "$old" = "$new" &&
- $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
- then
- rm -f "$dsttmp"
- else
- # If $backupsuffix is set, and the file being installed
- # already exists, attempt a backup. Don't worry if it fails,
- # e.g., if mv doesn't support -f.
- if test -n "$backupsuffix" && test -f "$dst"; then
- $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
- fi
-
- # 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 "$dst" 2>/dev/null ||
- { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
- { $doit $rmcmd "$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 'before-save-hook 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC0"
-# time-stamp-end: "; # UTC"
-# End:
diff --git a/lib/erl_interface/src/connect/ei_connect.c b/lib/erl_interface/src/connect/ei_connect.c
index c310c93012..89a1d2b7fd 100644
--- a/lib/erl_interface/src/connect/ei_connect.c
+++ b/lib/erl_interface/src/connect/ei_connect.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,15 +36,9 @@
#include <unistd.h>
#include <sys/times.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
+#include <time.h>
+#if HAVE_SYS_TIME_H
# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
#include <sys/socket.h>
@@ -110,7 +104,7 @@ static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
int pkt_sz, unsigned char digest[16],
unsigned challenge, unsigned ms);
static int recv_complement(ei_socket_callbacks *cbs, void *ctx,
- int pkt_sz, unsigned ms);
+ int pkt_sz, DistFlags *flags, unsigned ms);
static int recv_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
int pkt_sz, unsigned our_challenge,
char cookie[],
@@ -121,11 +115,7 @@ static int send_challenge_ack(ei_socket_callbacks *cbs, void *ctx,
static int recv_challenge_ack(ei_socket_callbacks *cbs, void *ctx,
int pkt_sz, unsigned our_challenge,
char cookie[], unsigned ms);
-static int send_name(ei_cnode *ec, void *ctx, int pkt_sz,
- unsigned version, unsigned ms);
-static int send_complement(ei_cnode *ec, void *ctx, int pkt_sz,
- unsigned epmd_says_version, DistFlags her_flags,
- unsigned ms);
+static int send_name(ei_cnode *ec, void *ctx, int pkt_sz, unsigned ms);
static int recv_name(ei_socket_callbacks *cbs, void *ctx, int pkt_sz,
char* send_name_tag, DistFlags *flags,
char *namebuf, unsigned ms);
@@ -514,11 +504,6 @@ const char *ei_thisalivename(const ei_cnode* ec)
return ec->thisalivename;
}
-short ei_thiscreation(const ei_cnode* ec)
-{
- return ec->creation;
-}
-
/* FIXME: this function is not an api, why not? */
const char *ei_thiscookie(const ei_cnode* ec)
{
@@ -624,7 +609,7 @@ int ei_make_pid(ei_cnode *ec, erlang_pid *pid)
* of modifying the 'num' field in the pid returned by
* ei_self(). Since 'serial' field in pid returned by
* ei_self() is initialized to 0, pids created by
- * ei_make_pid() wont clash with such badly created pids
+ * ei_make_pid() won't clash with such badly created pids
* using ei_self() unless user also modified serial, but
* that has at least never been suggested by the
* documentation.
@@ -687,7 +672,7 @@ static ei_mutex_t *ref_mtx = NULL;
/*
* We use a global counter for all c-nodes in this process.
- * We wont wrap anyway due to the enormous amount of values
+ * We won't wrap anyway due to the enormous amount of values
* available.
*/
#ifdef EI_MAKE_REF_ATOMIC__
@@ -902,13 +887,13 @@ int ei_init_connect(void)
/*
* Perhaps run this routine instead of ei_connect_init/2 ?
-* Initailize by setting:
+* Initialize by setting:
* thishostname, thisalivename, thisnodename and thisipaddr
*/
int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
const char *thisalivename, const char *thisnodename,
Erl_IpAddr thisipaddr, const char *cookie,
- const short creation, ei_socket_callbacks *cbs,
+ unsigned int creation, ei_socket_callbacks *cbs,
int cbs_sz, void *setup_context)
{
char *dbglevel;
@@ -925,6 +910,10 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
}
ec->creation = creation;
+ if (ec->creation < 4) {
+ /* Avoid invalid 0-creation as well as old tiny 1,2,3 values. */
+ ec->creation += 0xE10000;
+ }
ec->pidsn = 0;
if (cookie) {
@@ -962,7 +951,7 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
strcpy(ec->self.node, thisnodename);
ec->self.num = 0;
ec->self.serial = 0;
- ec->self.creation = creation;
+ ec->self.creation = ec->creation;
}
else {
/* dynamic name */
@@ -987,7 +976,7 @@ int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname,
int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
const char *thisalivename, const char *thisnodename,
Erl_IpAddr thisipaddr, const char *cookie,
- const short creation)
+ unsigned int creation)
{
return ei_connect_xinit_ussi(ec, thishostname, thisalivename, thisnodename,
thisipaddr, cookie, creation,
@@ -1002,7 +991,7 @@ int ei_connect_xinit(ei_cnode* ec, const char *thishostname,
* otherwise return -1.
*/
int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
- const char *cookie, short creation,
+ const char *cookie, unsigned int creation,
ei_socket_callbacks *cbs, int cbs_sz,
void *setup_context)
{
@@ -1083,7 +1072,7 @@ int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name,
}
int ei_connect_init(ei_cnode* ec, const char* this_node_name,
- const char *cookie, short creation)
+ const char *cookie, unsigned int creation)
{
return ei_connect_init_ussi(ec, this_node_name, cookie, creation,
&ei_default_socket_callbacks,
@@ -1146,7 +1135,7 @@ struct hostent *dyn_gethostbyname_r(const char *name,
#endif
}
-/* Finds the the IP address for hostname and saves that IP address at
+/* Finds the IP address for hostname and saves that IP address at
the location that ip_wb points to. Returns a negative error code if
the IP address cannot be found for the hostname. */
static int ip_address_from_hostname(char* hostname,
@@ -1162,7 +1151,7 @@ static int ip_address_from_hostname(char* hostname,
hp = dyn_gethostbyname_r(hostname,&host,buffer_p,buffer_size,&ei_h_errno);
if (hp == NULL) {
char thishostname[EI_MAXHOSTNAMELEN+1];
- /* gethostname requies len to be max(hostname) + 1*/
+ /* gethostname requires len to be max(hostname) + 1*/
if (gethostname(thishostname,EI_MAXHOSTNAMELEN+1) < 0) {
EI_TRACE_ERR0("ip_address_from_hostname",
"Failed to get name of this host");
@@ -1227,7 +1216,6 @@ static int ei_connect_helper(ei_cnode* ec,
ei_socket_callbacks *cbs = ec->cbs;
void *ctx;
int sockd;
- unsigned her_version;
DistFlags her_flags;
unsigned our_challenge, her_challenge;
unsigned char our_digest[16];
@@ -1252,12 +1240,6 @@ static int ei_connect_helper(ei_cnode* ec,
return ERL_ERROR;
}
- if (!ec->thisnodename[0] && epmd_says_version < EI_DIST_6) {
- /* This is a dynamic node name. We have to use at least vsn 6
- of the dist protocol for this to work. */
- epmd_says_version = EI_DIST_6;
- }
-
err = ei_socket_ctx__(cbs, &ctx, ec->setup_context);
if (err) {
EI_TRACE_ERR2("ei_xconnect","-> SOCKET failed: %s (%d)",
@@ -1294,24 +1276,21 @@ static int ei_connect_helper(ei_cnode* ec,
goto error;
}
- if (send_name(ec, ctx, pkt_sz, epmd_says_version, tmo))
+ if (send_name(ec, ctx, pkt_sz, tmo))
goto error;
if (recv_status(ec, ctx, pkt_sz, tmo))
goto error;
if (recv_challenge(cbs, ctx, pkt_sz, &her_challenge,
&her_flags, NULL, tmo))
goto error;
- her_version = (her_flags & DFLAG_HANDSHAKE_23) ? EI_DIST_6 : EI_DIST_5;
our_challenge = gen_challenge();
gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
- if (send_complement(ec, ctx, pkt_sz, epmd_says_version, her_flags, tmo))
- goto error;
if (send_challenge_reply(cbs, ctx, pkt_sz, our_digest, our_challenge, tmo))
goto error;
if (recv_challenge_ack(cbs, ctx, pkt_sz, our_challenge,
ec->ei_connect_cookie, tmo))
goto error;
- if (put_ei_socket_info(sockd, her_version, null_cookie, ec, cbs, ctx) != 0)
+ if (put_ei_socket_info(sockd, EI_DIST_6, null_cookie, ec, cbs, ctx) != 0)
goto error;
if (cbs->connect_handshake_complete) {
@@ -1636,7 +1615,6 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms)
}
{
- unsigned her_version = (her_flags & DFLAG_HANDSHAKE_23) ? 6 : 5;
unsigned our_challenge;
unsigned her_challenge;
unsigned char our_digest[16];
@@ -1646,8 +1624,8 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms)
our_challenge = gen_challenge();
if (send_challenge(ec, ctx, pkt_sz, our_challenge, her_flags, tmo))
goto error;
- if (send_name_tag == 'n' && (her_flags & DFLAG_HANDSHAKE_23)) {
- if (recv_complement(cbs, ctx, pkt_sz, tmo))
+ if (send_name_tag == 'n') {
+ if (recv_complement(cbs, ctx, pkt_sz, &her_flags, tmo))
goto error;
}
if (recv_challenge_reply(cbs, ctx, pkt_sz, our_challenge,
@@ -1656,7 +1634,7 @@ int ei_accept_tmo(ei_cnode* ec, int lfd, ErlConnect *conp, unsigned ms)
gen_digest(her_challenge, ec->ei_connect_cookie, our_digest);
if (send_challenge_ack(cbs, ctx, pkt_sz, our_digest, tmo))
goto error;
- if (put_ei_socket_info(fd, her_version, null_cookie, ec, cbs, ctx) != 0)
+ if (put_ei_socket_info(fd, EI_DIST_6, null_cookie, ec, cbs, ctx) != 0)
goto error;
}
if (conp) {
@@ -2270,7 +2248,8 @@ error:
static DistFlags preferred_flags(void)
{
DistFlags flags =
- DFLAG_EXTENDED_REFERENCES
+ DFLAG_MANDATORY_25_DIGEST
+ | DFLAG_EXTENDED_REFERENCES
| DFLAG_DIST_MONITOR
| DFLAG_EXTENDED_PIDS_PORTS
| DFLAG_FUN_TAGS
@@ -2285,17 +2264,12 @@ static DistFlags preferred_flags(void)
| DFLAG_HANDSHAKE_23
| DFLAG_V4_NC
| DFLAG_UNLINK_ID;
- if (ei_internal_use_21_bitstr_expfun()) {
- flags &= ~(DFLAG_EXPORT_PTR_TAG
- | DFLAG_BIT_BINARIES);
- }
return flags;
}
static int send_name(ei_cnode *ec,
void *ctx,
int pkt_sz,
- unsigned version,
unsigned ms)
{
char *buf;
@@ -2307,25 +2281,18 @@ static int send_name(ei_cnode *ec,
int err, ret;
ssize_t len;
DistFlags flags = preferred_flags();
- char tag;
if (ec->thisnodename[0]) {
name_ptr = ec->thisnodename;
- tag = (version == EI_DIST_5) ? 'n' : 'N';
}
else {
/* dynamic node name */
name_ptr = ec->thishostname;
- tag = 'N'; /* presume ver 6 */
flags |= DFLAG_NAME_ME;
}
name_len = strlen(name_ptr);
-
- if (tag == 'n')
- siz = pkt_sz + 1 + 2 + 4 + name_len;
- else
- siz = pkt_sz + 1 + 8 + 4 + 2 + name_len;
+ siz = pkt_sz + 1 + 8 + 4 + 2 + name_len;
buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf;
if (!buf) {
@@ -2345,16 +2312,10 @@ static int send_name(ei_cnode *ec,
goto done;
}
- put8(s, tag);
- if (tag == 'n') {
- put16be(s, EI_DIST_5); /* some impl (jinterface) demand ver==5 */
- put32be(s, flags);
- }
- else { /* tag == 'N' */
- put64be(s, flags);
- put32be(s, ec->creation);
- put16be(s, name_len);
- }
+ put8(s, 'N');
+ put64be(s, flags);
+ put32be(s, ec->creation);
+ put16be(s, name_len);
memcpy(s, name_ptr, name_len);
len = (ssize_t) siz;
err = ei_write_fill_ctx_t__(ec->cbs, ctx, buf, &len, ms);
@@ -2389,12 +2350,8 @@ static int send_challenge(ei_cnode *ec,
int err, ret;
ssize_t len;
DistFlags flags;
- const char tag = (her_flags & DFLAG_HANDSHAKE_23) ? 'N' : 'n';
- if (tag == 'n')
- siz = pkt_sz + 1 + 2 + 4 + 4 + nodename_len;
- else
- siz = pkt_sz + 1 + 8 + 4 + 4 + 2 + nodename_len;
+ siz = pkt_sz + 1 + 8 + 4 + 4 + 2 + nodename_len;
buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf;
if (!buf) {
@@ -2415,18 +2372,11 @@ static int send_challenge(ei_cnode *ec,
}
flags = preferred_flags();
- put8(s, tag);
- if (tag == 'n') {
- put16be(s, EI_DIST_5); /* choosen version */
- put32be(s, flags);
- put32be(s, challenge);
- }
- else {
- put64be(s, flags);
- put32be(s, challenge);
- put32be(s, ec->creation);
- put16be(s, nodename_len);
- }
+ put8(s, 'N');
+ put64be(s, flags);
+ put32be(s, challenge);
+ put32be(s, ec->creation);
+ put16be(s, nodename_len);
memcpy(s, ec->thisnodename, nodename_len);
len = (ssize_t) siz;
err = ei_write_fill_ctx_t__(ec->cbs, ctx, buf, &len, ms);
@@ -2454,7 +2404,6 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx,
int is_static = 1;
int buflen = DEFBUF_SIZ;
int rlen, nodename_len;
- unsigned version;
char *s;
char tag;
char tmp_nodename[MAXNODELEN+1];
@@ -2469,47 +2418,26 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx,
}
s = buf;
tag = get8(s);
- if (tag != 'n' && tag != 'N') {
+ if (tag != 'N') {
EI_TRACE_ERR2("recv_challenge",
"<- RECV_CHALLENGE incorrect tag, "
- "expected 'n' or 'N', got '%c' (%u)",tag,tag);
+ "expected 'N', got '%c' (%u)", tag, tag);
goto error;
}
- if (tag == 'n') { /* OLD */
- if (rlen < 1+2+4+4) {
- EI_TRACE_ERR1("recv_challenge","<- RECV_CHALLENGE 'n' packet too short (%d)",
- rlen)
- goto error;
- }
-
- version = get16be(s);
- if (version != EI_DIST_5) {
- EI_TRACE_ERR1("recv_challenge",
- "<- RECV_CHALLENGE 'n' incorrect version=%d",
- version);
- goto error;
- }
- *flags = get32be(s);
- *challenge = get32be(s);
- nodename_len = (buf + rlen) - s;
+ if (rlen < 1+8+4+4+2) {
+ EI_TRACE_ERR1("recv_challenge","<- RECV_CHALLENGE 'N' packet too short (%d)",
+ rlen)
+ goto error;
}
- else { /* NEW */
- if (rlen < 1+8+4+4+2) {
- EI_TRACE_ERR1("recv_challenge","<- RECV_CHALLENGE 'N' packet too short (%d)",
- rlen)
- goto error;
- }
- version = EI_DIST_6;
- *flags = get64be(s);
- *challenge = get32be(s);
- s += 4; /* ignore peer 'creation' */
- nodename_len = get16be(s);
- if (nodename_len > (buf + rlen) - s) {
- EI_TRACE_ERR1("recv_challenge",
- "<- RECV_CHALLENGE 'N' nodename too long (%d)",
- nodename_len);
- goto error;
- }
+ *flags = get64be(s);
+ *challenge = get32be(s);
+ s += 4; /* ignore peer 'creation' */
+ nodename_len = get16be(s);
+ if (nodename_len > (buf + rlen) - s) {
+ EI_TRACE_ERR1("recv_challenge",
+ "<- RECV_CHALLENGE 'N' nodename too long (%d)",
+ nodename_len);
+ goto error;
}
if (nodename_len > MAXNODELEN) {
@@ -2518,22 +2446,13 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx,
goto error;
}
- if (!(*flags & DFLAG_EXTENDED_REFERENCES)) {
- EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot "
- "handle extended references");
- goto error;
+ if (*flags & DFLAG_MANDATORY_25_DIGEST) {
+ *flags |= DFLAG_DIST_MANDATORY_25;
}
- if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)) {
- EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot "
- "handle extended pids and ports");
- erl_errno = EIO;
- goto error;
- }
-
- if (!(*flags & DFLAG_NEW_FLOATS)) {
+ if ((*flags & DFLAG_DIST_MANDATORY) != DFLAG_DIST_MANDATORY) {
EI_TRACE_ERR0("recv_challenge","<- RECV_CHALLENGE peer cannot "
- "handle binary float encoding");
+ "handle all mandatory capabilities");
goto error;
}
@@ -2545,12 +2464,10 @@ static int recv_challenge(ei_socket_callbacks *cbs, void *ctx,
if (!is_static)
free(buf);
- EI_TRACE_CONN4("recv_challenge","<- RECV_CHALLENGE (ok) node = %s, "
- "version = %u, "
+ EI_TRACE_CONN3("recv_challenge","<- RECV_CHALLENGE (ok) node = %s, "
"flags = %u, "
"challenge = %d",
namebuf,
- version,
*flags,
*challenge
);
@@ -2562,63 +2479,6 @@ error:
return -1;
}
-static int send_complement(ei_cnode *ec,
- void *ctx,
- int pkt_sz,
- unsigned epmd_says_version,
- DistFlags her_flags,
- unsigned ms)
-{
- int ret = 0;
- if (epmd_says_version == EI_DIST_5 && (her_flags & DFLAG_HANDSHAKE_23)) {
- char *buf;
- unsigned char *s;
- char dbuf[DEFBUF_SIZ];
- int err;
- ssize_t len;
- unsigned int flagsHigh;
- const int siz = pkt_sz + 1 + 4 + 4;
-
- buf = (siz > DEFBUF_SIZ) ? malloc(siz) : dbuf;
- if (!buf) {
- erl_errno = ENOMEM;
- return -1;
- }
- s = (unsigned char *)buf;
- switch (pkt_sz) {
- case 2:
- put16be(s,siz - 2);
- break;
- case 4:
- put32be(s,siz - 4);
- break;
- default:
- ret = -1;
- goto done;
- }
- flagsHigh = preferred_flags() >> 32;
-
- put8(s, 'c');
- put32be(s, flagsHigh);
- put32be(s, ec->creation);
-
- len = (ssize_t) siz;
- err = ei_write_fill_ctx_t__(ec->cbs, ctx, buf, &len, ms);
- if (!err && len != (ssize_t) siz)
- err = EIO;
- if (err) {
- EI_TRACE_ERR0("send_name", "SEND_NAME -> socket write failed");
- EI_CONN_SAVE_ERRNO__(err);
- ret = -1;
- }
- done:
- if (buf != dbuf)
- free(buf);
- }
- return ret;
-}
-
-
static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
int pkt_sz, unsigned char digest[16],
unsigned challenge, unsigned ms)
@@ -2668,6 +2528,7 @@ static int send_challenge_reply(ei_socket_callbacks *cbs, void *ctx,
static int recv_complement(ei_socket_callbacks *cbs,
void *ctx,
int pkt_sz,
+ DistFlags *flags,
unsigned ms)
{
char dbuf[DEFBUF_SIZ];
@@ -2694,6 +2555,14 @@ static int recv_complement(ei_socket_callbacks *cbs,
"expected 'c' got '%c' (%u)",tag,tag);
goto error;
}
+ *flags |= (DistFlags)get32be(s) << 32;
+
+ if ((~*flags) & (DFLAG_DIST_MANDATORY | DFLAG_HANDSHAKE_23)) {
+ EI_TRACE_ERR0("recv_complement","<- RECV_COMPLEMENT peer cannot "
+ "handle all mandatory capabilities");
+ goto error;
+ }
+
creation = get32be(s);
if (!is_static)
free(buf);
@@ -2881,6 +2750,7 @@ static int recv_name(ei_socket_callbacks *cbs, void *ctx,
char *s;
char tmp_nodename[MAXNODELEN+1];
char tag;
+ DistFlags flag_mask;
erl_errno = EIO; /* Default */
@@ -2911,6 +2781,7 @@ static int recv_name(ei_socket_callbacks *cbs, void *ctx,
goto error;
}
*flags = get32be(s);
+ flag_mask = ((DistFlags)1 << 32) - 1;
namelen = rlen - (1+2+4);
}
else { /* tag == 'N' */
@@ -2920,19 +2791,18 @@ static int recv_name(ei_socket_callbacks *cbs, void *ctx,
goto error;
}
*flags = get64be(s);
+ flag_mask = ~(DistFlags)0;
s += 4; /* ignore peer 'creation' */
namelen = get16be(s);
}
- if (!(*flags & DFLAG_EXTENDED_REFERENCES)) {
- EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot handle"
- "extended references");
- goto error;
+ if (*flags & DFLAG_MANDATORY_25_DIGEST) {
+ *flags |= DFLAG_DIST_MANDATORY_25;
}
- if (!(*flags & DFLAG_EXTENDED_PIDS_PORTS)) {
+ if ((~*flags) & flag_mask & (DFLAG_DIST_MANDATORY | DFLAG_HANDSHAKE_23)) {
EI_TRACE_ERR0("recv_name","<- RECV_NAME peer cannot "
- "handle extended pids and ports");
+ "handle all mandatory capabilities");
erl_errno = EIO;
goto error;
}
diff --git a/lib/erl_interface/src/connect/ei_connect_int.h b/lib/erl_interface/src/connect/ei_connect_int.h
index 7ada7b598c..d9be32d42c 100644
--- a/lib/erl_interface/src/connect/ei_connect_int.h
+++ b/lib/erl_interface/src/connect/ei_connect_int.h
@@ -43,15 +43,9 @@
#include <sys/types.h>
#include <sys/times.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
+#include <time.h>
+#if HAVE_SYS_TIME_H
# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
#include <sys/socket.h>
@@ -62,7 +56,7 @@
#include <sys/utsname.h> /* for gen_challenge (NEED FIX?) */
#endif
-/* FIXME remove duplicate defintions */
+/* FIXME remove duplicate definitions */
#define DEFBUF_SIZ 100
@@ -90,19 +84,39 @@ typedef EI_ULONGLONG DistFlags;
#define DFLAG_BIG_CREATION 0x40000
#define DFLAG_HANDSHAKE_23 0x1000000
#define DFLAG_UNLINK_ID 0x2000000
-#define DFLAG_RESERVED 0xfc000000
-#define DFLAG_NAME_ME ((DistFlags)0x2 << 32)
+#define DFLAG_MANDATORY_25_DIGEST 0x4000000
+#define DFLAG_RESERVED 0xf8000000
+#define DFLAG_NAME_ME (((DistFlags)0x2) << 32)
#define DFLAG_V4_NC (((DistFlags)0x4) << 32)
/* Control message tags not exposed to user... */
#define ERL_UNLINK_ID 35
#define ERL_UNLINK_ID_ACK 36
+/* Mandatory flags for distribution in OTP 25. */
+#define DFLAG_DIST_MANDATORY_25 (DFLAG_EXTENDED_REFERENCES \
+ | DFLAG_FUN_TAGS \
+ | DFLAG_EXTENDED_PIDS_PORTS \
+ | DFLAG_UTF8_ATOMS \
+ | DFLAG_NEW_FUN_TAGS \
+ | DFLAG_BIG_CREATION \
+ | DFLAG_NEW_FLOATS \
+ | DFLAG_MAP_TAG \
+ | DFLAG_EXPORT_PTR_TAG \
+ | DFLAG_BIT_BINARIES)
+
+/* Mandatory flags for distribution. */
+
+/*
+ * Mandatory flags for distribution. Keep them in sync with
+ * erts/emulator/beam/dist.h.
+ */
+#define DFLAG_DIST_MANDATORY DFLAG_DIST_MANDATORY_25
+
ei_cnode *ei_fd_to_cnode(int fd);
int ei_distversion(int fd);
const char* ei_getfdcookie(int fd);
-short ei_thiscreation(const ei_cnode* ec);
const char *ei_thiscookie(const ei_cnode* ec);
int ei_do_receive_msg(int fd, int staticbuffer_p,
diff --git a/lib/erl_interface/src/connect/eirecv.c b/lib/erl_interface/src/connect/eirecv.c
index 29decb9d87..fadffd95fb 100644
--- a/lib/erl_interface/src/connect/eirecv.c
+++ b/lib/erl_interface/src/connect/eirecv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
# include <winsock2.h>
# include <windows.h>
# include <winbase.h>
-#else /* Unix/VxWorks */
+#else /* Unix */
# include <unistd.h>
#endif
@@ -369,7 +369,7 @@ send_unlink_id_ack(ei_socket_callbacks *cbs, void *ctx,
s = &ctl[0];
/* packet size */
put32be(s, index - 4);
- /* pass throug */
+ /* pass through */
put8(s, ERL_PASS_THROUGH);
if (ei_tracelevel >= 4) {
diff --git a/lib/erl_interface/src/connect/send_exit.c b/lib/erl_interface/src/connect/send_exit.c
index 231aad0ae0..ed064da438 100644
--- a/lib/erl_interface/src/connect/send_exit.c
+++ b/lib/erl_interface/src/connect/send_exit.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
# include <winsock2.h>
# include <windows.h>
# include <winbase.h>
-#else /* Unix/VxWorks */
+#else /* Unix */
#include <unistd.h>
#endif
diff --git a/lib/erl_interface/src/decode/decode_atom.c b/lib/erl_interface/src/decode/decode_atom.c
index 2bf8ab0552..b9cdec5b22 100644
--- a/lib/erl_interface/src/decode/decode_atom.c
+++ b/lib/erl_interface/src/decode/decode_atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2018. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -100,7 +100,7 @@ typedef unsigned long AsciiWord;
#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
typedef unsigned long long AsciiWord;
#else
-# error "Uknown word type"
+# error "Unknown word type"
#endif
#if SIZEOF_VOID_P == 4
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c
index 3622ebbe02..d9c1236f3d 100644
--- a/lib/erl_interface/src/decode/decode_fun.c
+++ b/lib/erl_interface/src/decode/decode_fun.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -120,7 +120,7 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
/* then the old_uniq */
if (ei_decode_long(s, &ix, p_uniq) < 0)
return -1;
- /* the the pid */
+ /* the pid */
if (ei_decode_pid(s, &ix, p_pid) < 0)
return -1;
/* finally the free vars */
diff --git a/lib/erl_interface/src/encode/encode_atom.c b/lib/erl_interface/src/encode/encode_atom.c
index 6117aae37e..2b4c56af29 100644
--- a/lib/erl_interface/src/encode/encode_atom.c
+++ b/lib/erl_interface/src/encode/encode_atom.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2017. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len,
/*
* Since OTP 20 we totally ignore 'to_enc'
- * and alway encode as UTF8.
+ * and always encode as UTF8.
*/
{
offs = 1 + 1;
diff --git a/lib/erl_interface/src/epmd/ei_epmd.h b/lib/erl_interface/src/epmd/ei_epmd.h
index 6a274b606a..d6f29d5374 100644
--- a/lib/erl_interface/src/epmd/ei_epmd.h
+++ b/lib/erl_interface/src/epmd/ei_epmd.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
#ifndef EI_DIST_HIGH
#define EI_DIST_HIGH EI_DIST_6
-#define EI_DIST_LOW EI_DIST_5
+#define EI_DIST_LOW EI_DIST_6
#endif
#ifndef EPMD_PORT
diff --git a/lib/erl_interface/src/epmd/epmd_publish.c b/lib/erl_interface/src/epmd/epmd_publish.c
index 3e251d6a64..26919ec681 100644
--- a/lib/erl_interface/src/epmd/epmd_publish.c
+++ b/lib/erl_interface/src/epmd/epmd_publish.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,8 +76,8 @@ static int ei_epmd_r4_publish (int port, const char *alive, unsigned ms)
put16be(s,port); /* port number */
put8(s,'h'); /* h = r4 hidden node */
put8(s, EI_MYPROTO); /* protocol 0 ?? */
- put16be(s,EI_DIST_HIGH); /* highest understood version: 1 = R4 */
- put16be(s,EI_DIST_LOW); /* lowest: 0 = R3 */
+ put16be(s,EI_DIST_HIGH); /* highest understood version */
+ put16be(s,EI_DIST_LOW); /* lowest */
put16be(s,nlen); /* length of alivename */
strcpy(s, alive);
s += nlen;
diff --git a/lib/erl_interface/src/epmd/epmd_unpublish.c b/lib/erl_interface/src/epmd/epmd_unpublish.c
index c463732250..269bce278f 100644
--- a/lib/erl_interface/src/epmd/epmd_unpublish.c
+++ b/lib/erl_interface/src/epmd/epmd_unpublish.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ int ei_unpublish_tmo(const char *alive, unsigned ms)
put8(s,EI_EPMD_STOP_REQ);
strcpy(s, alive);
- /* FIXME can't connect, return success?! At least commen whats up */
+ /* FIXME can't connect, return success?! At least comment what's up */
if ((fd = ei_epmd_connect_tmo(NULL,ms)) < 0) return fd;
dlen = (ssize_t) len+2;
diff --git a/lib/erl_interface/src/misc/ei_compat.c b/lib/erl_interface/src/misc/ei_compat.c
index e25a1a015d..95be5d6dde 100644
--- a/lib/erl_interface/src/misc/ei_compat.c
+++ b/lib/erl_interface/src/misc/ei_compat.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,9 +35,3 @@ ei_set_compat_rel(unsigned rel)
{
compat_rel = rel;
}
-
-int ei_internal_use_21_bitstr_expfun(void)
-{
- return compat_rel < 22;
-}
-
diff --git a/lib/erl_interface/src/misc/ei_internal.h b/lib/erl_interface/src/misc/ei_internal.h
index 5b39e3dc37..374fd2975c 100644
--- a/lib/erl_interface/src/misc/ei_internal.h
+++ b/lib/erl_interface/src/misc/ei_internal.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -157,8 +157,6 @@ int ei_init_connect(void);
void ei_trace_printf(const char *name, int level, const char *format, ...);
-int ei_internal_use_21_bitstr_expfun(void);
-
int ei_get_cbs_ctx__(ei_socket_callbacks **cbs, void **ctx, int fd);
#endif /* _EI_INTERNAL_H */
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
index 3dede6343a..d70e76cf1e 100644
--- a/lib/erl_interface/src/misc/ei_pthreads.c
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -158,7 +158,7 @@ static void erl_errno_key_alloc(void)
* If pthread functions fail we fall back to using fallback_errno
* so that the main thread (actually not a thread in all ascpects)
* still will set and get an erl_errno value.
- * Actually this is a bit to nice, it would be preferrable to exit fatal
+ * Actually this is a bit to nice, it would be preferable to exit fatal
* as we do on windows, but we might break some code with one thread
* but still compiled with -D_REENTRANT, so we'll leave it here.
*/
diff --git a/lib/erl_interface/src/misc/eimd5.c b/lib/erl_interface/src/misc/eimd5.c
index 426b96d962..3d7dd960e7 100644
--- a/lib/erl_interface/src/misc/eimd5.c
+++ b/lib/erl_interface/src/misc/eimd5.c
@@ -161,7 +161,7 @@ void ei_MD5Update (MD5_CTX *context, unsigned char *input,
}
/*
- * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * MD5 finalization. Ends an MD5 message-digest operation, writing
the message digest and zeroizing the context.
*/
void ei_MD5Final (unsigned char digest[16], MD5_CTX *context)
diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c
index db1a386496..87fd970165 100644
--- a/lib/erl_interface/src/misc/show_msg.c
+++ b/lib/erl_interface/src/misc/show_msg.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2020. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,19 +29,9 @@
#include "eidef.h"
-#ifndef __WIN32__
-# ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-# else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-# endif
-#else
-# include <time.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
#endif
#include "eiext.h"
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index e62931de35..4548b9f4dd 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,15 +61,9 @@
#include <time.h>
#include <unistd.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
+#include <time.h>
+#if HAVE_SYS_TIME_H
# include <sys/time.h>
-# else
-# include <time.h>
-# endif
#endif
#endif
@@ -1103,7 +1097,7 @@ static char* ei_chk_strdup(char *s)
}
/*
- * Helper function that that:
+ * Helper function that:
*
* 1. Executes a function on a remote node
*
diff --git a/lib/erl_interface/test/Makefile b/lib/erl_interface/test/Makefile
index bdfedecc66..11c60953ca 100644
--- a/lib/erl_interface/test/Makefile
+++ b/lib/erl_interface/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2020. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ RELSYSDIR = $(RELEASE_PATH)/erl_interface_test
# Targets
# ----------------------------------------------------
-tests debug opt:
+tests $(TYPES):
clean:
diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.c b/lib/erl_interface/test/all_SUITE_data/ei_runner.c
index b1a4f1a2c1..3732cb9f5b 100644
--- a/lib/erl_interface/test/all_SUITE_data/ei_runner.c
+++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.c
@@ -274,7 +274,7 @@ void do_fail(const char* file, int line, const char* reason, ...)
/*
* This function sends a message to the Erlang side.
* The message will be written to the test servers log file,
- * but will otherwise be completly ignored.
+ * but will otherwise be completely ignored.
*/
void message(char* format, ...)
diff --git a/lib/erl_interface/test/all_SUITE_data/ei_runner.h b/lib/erl_interface/test/all_SUITE_data/ei_runner.h
index 6d6e0717e8..3073d1b60f 100644
--- a/lib/erl_interface/test/all_SUITE_data/ei_runner.h
+++ b/lib/erl_interface/test/all_SUITE_data/ei_runner.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ void free_packet(char*);
#define fail(reason) do_fail(__FILE__, __LINE__, reason)
#define fail1(reason, a1) do_fail(__FILE__, __LINE__, reason, a1)
#define fail2(reason, a1, a2) do_fail(__FILE__, __LINE__, reason, a1, a2)
+#define fail3(reason, a1, a2, a3) do_fail(__FILE__, __LINE__, reason, a1, a2, a3)
#define report(ok) do_report(__FILE__, __LINE__, ok)
void do_report(char* file, int line, int ok);
diff --git a/lib/erl_interface/test/all_SUITE_data/reclaim.h b/lib/erl_interface/test/all_SUITE_data/reclaim.h
deleted file mode 100644
index fe99bb0afc..0000000000
--- a/lib/erl_interface/test/all_SUITE_data/reclaim.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- *
-
- */
-#ifndef _RECLAIM_H
-#define _RECLAIM_H
-
-
-/* The Erlang release for VxWorks includes a simple mechanism for
- "resource reclamation" at task exit - it allows replacement of the
- functions that open/close "files" and malloc/free memory with versions
- that keep track, to be able to "reclaim" file descriptors and memory
- when a task exits (regardless of *how* it exits).
-
- The interface to this mechanism is made available via this file,
- with the following caveats:
-
- - The interface may change (or perhaps even be removed, though that
- isn't likely until VxWorks itself provides similar functionality)
- in future releases - i.e. you must always use the version of this
- file that comes with the Erlang release you are using.
-
- - Disaster is guaranteed if you use the mechanism incorrectly (see
- below for the correct way), e.g. allocate memory with the "tracking"
- version of malloc() and free it with the "standard" version of free().
-
- - The mechanism (of course) incurs some performance penalty - thus
- for a simple program you may be better off with careful programming,
- making sure that you do whatever close()/free()/etc calls that are
- appropriate at all exit points (though if you need to guard against
- taskDelete() etc, things get messy...).
-
- To use the mechanism, simply program your application normally, i.e.
- use open()/close()/malloc()/free() etc as usual, but #include this
- file before any usage of the relevant functions. NOTE: To avoid the
- "disaster" mentioned above, you *must* #include it in *all* (or none)
- of the files that manipulate a particular file descriptor, allocated
- memory area, etc.
-
- Before any task that uses this utility is loaded (which includes the
- erlang emulator), the reclaim.o object file has to be loaded and
- the function reclaim_init() has to be called. reclaim_init should be called
- only _ONCE_ in a systems lifetime and has only a primitive guard
- against multiple calls (i.e. a global variable is checked). Therefore
- the initialization should occur either in the start script of the system
- or (even better) in the usrInit() part of system initialization. The
- object file itself should be loaded only once, so linking it with the
- kernel is a good idea, linking with each application is an extremely bad
- dito. Make really sure that it's loaded _before_ any application that
- uses it if You want to load it in the startup script.
-
- If You dont want to have #define's for the posix/stdio names
- of the file/memory operations (i.e. no #define malloc save_malloc etc),
- #define RECLAIM_NO_ALIAS in Your source before reclaim.h is included.
-*/
-
-#include <vxWorks.h> /* STATUS, size_t */
-#include <sockLib.h> /* struct sockaddr */
-#include <stdio.h> /* FILE */
-
-#if defined(__STDC__)
-#define _RECLAIM_DECL_FUN(RetType, FunName, ParamList) \
-extern RetType FunName##ParamList
-#define _RECLAIM_VOID_PTR void *
-#define _RECLAIM_VOID_PARAM void
-#define _RECLAIM_VOID_RETURN void
-#elif defined(__cplusplus)
-#define _RECLAIM_DECL_FUN(RetType, FunName, ParamList) \
-extern "C" RetType FunName##ParamList
-#define _RECLAIM_VOID_PTR void *
-#define _RECLAIM_VOID_PARAM
-#define _RECLAIM_VOID_RETURN void
-#else
-#define _RECLAIM_DECL_FUN(RetType, FunName, Ignore) extern RetType FunName()
-#define DECLARE_FUNCTION_TYPE(RetType, Type, PList) typedef RetType (* Type)()
-#define _RECLAIM_VOID_PTR char *
-#define _RECLAIM_VOID_PARAM
-#define _RECLAIM_VOID_RETURN
-#endif /* __STDC__ / __cplusplus */
-
-/* Initialize the facility, on a per system basis. */
-_RECLAIM_DECL_FUN(STATUS, reclaim_init, (_RECLAIM_VOID_PARAM));
-
-/* File descriptor operations */
-_RECLAIM_DECL_FUN(int,save_open,(char *, int, ...));
-_RECLAIM_DECL_FUN(int,save_creat,(char *, int));
-_RECLAIM_DECL_FUN(int,save_socket,(int, int, int));
-_RECLAIM_DECL_FUN(int,save_accept,(int, struct sockaddr *, int *));
-_RECLAIM_DECL_FUN(int,save_close,(int));
-/* Interface to add an fd to what's reclaimed even though it's not open with
- one of the above functions */
-_RECLAIM_DECL_FUN(_RECLAIM_VOID_RETURN, save_fd, (int fd));
-#ifndef RECLAIM_NO_ALIAS
-#define open save_open
-#define creat save_creat
-#define socket save_socket
-#define accept save_accept
-#define close save_close
-#endif
-/* Stdio file operations */
-_RECLAIM_DECL_FUN(FILE *, save_fopen, (char *, char *));
-_RECLAIM_DECL_FUN(FILE *, save_fdopen, (int, char *));
-_RECLAIM_DECL_FUN(FILE *, save_freopen, (char *, char *, FILE *));
-_RECLAIM_DECL_FUN(int, save_fclose, (FILE *));
-/* XXX Should do opendir/closedir too... */
-#ifndef RECLAIM_NO_ALIAS
-#define fopen save_fopen
-#define fdopen save_fdopen
-#define freopen save_freopen
-#define fclose save_fclose
-#endif
-/* Memory allocation */
-_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, save_malloc, (size_t));
-_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, save_calloc, (size_t, size_t));
-_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, save_realloc,
- (_RECLAIM_VOID_PTR, size_t));
-_RECLAIM_DECL_FUN(void, save_free, (_RECLAIM_VOID_PTR));
-_RECLAIM_DECL_FUN(void, save_cfree, (_RECLAIM_VOID_PTR));
-#ifndef RECLAIM_NO_ALIAS
-#define malloc save_malloc
-#define calloc save_calloc
-#define realloc save_realloc
-#define free save_free
-#define cfree save_cfree
-#endif
-/* Generic interfaces to malloc etc... */
-_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, plain_malloc, (size_t));
-_RECLAIM_DECL_FUN(_RECLAIM_VOID_PTR, plain_realloc,
- (_RECLAIM_VOID_PTR, size_t));
-_RECLAIM_DECL_FUN(void, plain_free, (_RECLAIM_VOID_PTR));
-#endif /* _RECLAIM_H */
-
-
-
-
diff --git a/lib/erl_interface/test/ei_accept_SUITE.erl b/lib/erl_interface/test/ei_accept_SUITE.erl
index 612d6e1b81..f563feaa72 100644
--- a/lib/erl_interface/test/ei_accept_SUITE.erl
+++ b/lib/erl_interface/test/ei_accept_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,70 +26,270 @@
-export([all/0, suite/0,
init_per_testcase/2,
- ei_accept/1, ei_threaded_accept/1,
+ ei_accept/1,
+ hopeful_random/1,
+ ei_threaded_accept/1,
monitor_ei_process/1]).
+%% Internals
+-export([id/1]).
+
-import(runner, [get_term/1,send_term/2]).
+
+-define(ERL_ONHEAP_BIN_LIMIT, 64).
+
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {seconds, 30}}].
all() ->
- [ei_accept, ei_threaded_accept,
+ [ei_accept,
+ hopeful_random,
+ ei_threaded_accept,
monitor_ei_process].
init_per_testcase(Case, Config) ->
+ rand:uniform(), % Make sure rand is initialized and seeded.
+ %%rand:seed({exsss, [61781477086241372|88832360391433009]}),
+ io:format("** rand seed = ~p\n", [rand:export_seed()]),
runner:init_per_testcase(?MODULE, Case, Config).
ei_accept(Config) when is_list(Config) ->
- [ei_accept_do(Config, CR, SI)
- || CR <- [0,21],
- SI <- [default, ussi]],
+ _ = [ei_accept_do(Config, SI) || SI <- [default, ussi]],
ok.
-ei_accept_do(Config, CompatRel, SockImpl) ->
- io:format("CompatRel=~p, SockImpl=~p\n", [CompatRel, SockImpl]),
+ei_accept_do(Config, SockImpl) ->
+ io:format("SockImpl=~p\n", [SockImpl]),
P = runner:start(Config, ?interpret),
- 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, CompatRel, SockImpl),
+ 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, 0, SockImpl),
Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
io:format("Myname ~p ~n", [Myname]),
EINode = list_to_atom("c42@"++Myname),
io:format("EINode ~p ~n", [EINode]),
- %% We take this opportunity to also test export-funs and bit-strings
- %% with (ugly) tuple fallbacks in OTP 21 and older.
+ %% We take this opportunity to also test export-funs and bit-strings.
%% Test both toward pending connection and established connection.
- RealTerms = [<<1:1>>, fun lists:map/2],
- EncTerms = case CompatRel of
- 0 -> RealTerms;
- 21 -> [{<<128>>,1}, {lists,map}]
- end,
+ %% OTP-25: This is a bit obsolete now as we no longer support
+ %% tuple fallbacks for export-funs and bit-strings.
+ RealTerms =
+ [<<1:1>>,
+ fun lists:map/2,
+ fun_with_env(<<1:1>>),
+ fun_with_env(fun lists:map/2)],
Self = self(),
Funny = fun() -> hello end,
- TermToSend = {call, Self, "Test", Funny, RealTerms},
- TermToGet = {call, Self, "Test", Funny, EncTerms},
+ Terms = {call, Self, "Test", Funny, RealTerms},
Port = 6543,
{ok, ListenFd} = ei_publish(P, Port),
- {any, EINode} ! TermToSend,
+ {any, EINode} ! Terms,
{ok, Fd, Node} = ei_accept(P, ListenFd),
Node = node(),
Got1 = ei_receive(P, Fd),
%% Send again, now without auto-connect
- {any, EINode} ! TermToSend,
+ {any, EINode} ! Terms,
Got2 = ei_receive(P, Fd),
- io:format("Sent ~p~nExp. ~p~nGot1 ~p~nGot2 ~p~n", [TermToSend, TermToGet, Got1, Got2]),
- TermToGet = Got1,
- TermToGet = Got2,
+ io:format("Sent ~p~nExp. ~p~nGot1 ~p~nGot2 ~p~n", [Terms, Terms, Got1, Got2]),
+ Terms = Got1,
+ Terms = Got2,
runner:finish(P),
ok.
+fun_with_env(Term) ->
+ Env = ?MODULE:id(Term),
+ fun() -> Env end.
+
+id(X) -> X.
+
+
+%% Send random encoded terms from emulator to c-node
+%% and verify correct encoding.
+hopeful_random(Config) when is_list(Config) ->
+ [hopeful_random_do(Config, SI)
+ || SI <- [default, ussi]],
+ ok.
+
+
+hopeful_random_do(Config, SockImpl) ->
+ io:format("SockImpl=~p\n", [SockImpl]),
+ P = runner:start(Config, ?interpret),
+ 0 = ei_connect_init(P, 42, erlang:get_cookie(), 0, 0, SockImpl),
+
+ Myname = hd(tl(string:tokens(atom_to_list(node()), "@"))),
+ io:format("Myname ~p ~n", [Myname]),
+ EINode = list_to_atom("c42@"++Myname),
+ io:format("EINode ~p ~n", [EINode]),
+
+ Port = 6543,
+ {ok, ListenFd} = ei_publish(P, Port),
+
+ Terms = [random_term(20) || _ <- lists:seq(1,10)],
+
+ %% lists:foldl(fun(T,N) ->
+ %% io:format("Term #~p = ~p\n", [N, printable(T)]),
+ %% N+1
+ %% end,
+ %% 1,
+ %% Terms),
+
+ %% Send on pending connection (hopeful encoding)
+ [{any, EINode} ! T || T <- Terms],
+ {ok, Fd, Node} = ei_accept(P, ListenFd),
+ Node = node(),
+ [match(T, ei_receive(P, Fd)) || T <- Terms],
+
+ %% Send again on established connection
+ [{any, EINode} ! T || T <- Terms],
+ [match(T, ei_receive(P, Fd)) || T <- Terms],
+
+ runner:finish(P),
+ ok.
+
+
+match(A, A) -> ok;
+match(A, B) ->
+ io:format("match failed\nA = ~p\nB = ~p\n", [printable(A), printable(B)]),
+ ct:fail("match failed").
+
+random_term(MaxSize) ->
+ rand_term(rand:uniform(MaxSize)).
+
+rand_term(Arity) when Arity > 0 ->
+ List = rand_list(Arity, []),
+ case rand:uniform(6) of
+ 1 -> List;
+ 2 -> list_to_improper_list(List);
+ 3 -> list_to_tuple(List);
+ 4 -> list_to_flatmap(List);
+ 5 -> list_to_hashmap(List);
+ 6 -> list_to_fun(List)
+ end;
+rand_term(0) ->
+ rand_leaf().
+
+rand_list(0, Acc) ->
+ %% Shuffle result list to not favor tail heavy lists.
+ {_, MixedList} = lists:unzip(lists:sort(Acc)),
+ MixedList;
+rand_list(Budget, Acc) ->
+ Depth = rand:uniform(Budget),
+ SortIx = rand:uniform(1 bsl 26),
+ rand_list(Budget-Depth, [{SortIx, rand_term(Depth-1)} | Acc]).
+
+rand_leaf() ->
+ case rand:uniform(19) of
+ 1 -> rand_integer();
+ 2 -> rand_float();
+ 3 -> rand_heapbin();
+ 4 -> rand_procbin();
+ 5 -> rand_subbin(rand_heapbin());
+ 6 -> rand_subbin(rand_procbin());
+ 7 -> atom;
+ 8 -> [];
+ 9 -> {};
+ 10 -> #{};
+ 11 -> fun lists:sort/1;
+ 12 -> fun() -> ok end;
+ 13 -> self();
+ 14 -> lists:last(erlang:ports());
+ 15 -> make_ref();
+ 16 -> atomics:new(10,[]); % Magic ref
+ 17 -> mk_ext_pid({a@b, 17}, 17, 42);
+ 18 -> mk_ext_port({a@b, 21}, 13);
+ 19 -> mk_ext_ref({a@b, 42}, [42, 19, 11])
+ end.
+
+rand_integer() ->
+ Bits = rand:uniform(150),
+ Uint = rand:uniform(1 bsl Bits),
+ case rand:uniform(2) of
+ 1 -> Uint;
+ 2 -> -Uint
+ end.
+
+rand_float() ->
+ rand:uniform().
+
+rand_heapbin() ->
+ HeapBinSz = rand:uniform(?ERL_ONHEAP_BIN_LIMIT + 1) - 1,
+ HeapBig = rand:uniform(1 bsl (HeapBinSz*8)),
+ <<HeapBig:HeapBinSz/unit:8>>.
+
+rand_procbin() ->
+ ProcBinSz = ?ERL_ONHEAP_BIN_LIMIT + rand:uniform(?ERL_ONHEAP_BIN_LIMIT),
+ ProcBig = rand:uniform(1 bsl (ProcBinSz*8)),
+ <<ProcBig:ProcBinSz/unit:8>>.
+
+rand_subbin(Bin) ->
+ TotSz = bit_size(Bin),
+ Offs = rand:uniform(TotSz + 1) - 1,
+ Bits = rand:uniform(TotSz - Offs + 1) - 1,
+ <<_:Offs, BitStr:Bits/bits, _/bits>> = Bin,
+ BitStr.
+
+list_to_improper_list([A,B|T]) ->
+ T ++ [A|B];
+list_to_improper_list([H]) ->
+ [[]|H].
+
+list_to_flatmap(List) ->
+ list_to_map(List, #{}).
+
+list_to_hashmap(List) ->
+ HashMap = #{1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9,10=>0,
+ 11=>1,12=>2,13=>3,14=>4,15=>5,16=>6,17=>7,18=>8,19=>9,20=>0,
+ 21=>1,22=>2,23=>3,24=>4,25=>5,26=>6,27=>7,28=>8,29=>9,30=>0,
+ 31=>1,32=>2,33=>3},
+ list_to_map(List, HashMap).
+
+list_to_map([], Map) ->
+ Map;
+list_to_map([K], Map) ->
+ Map#{K => K};
+list_to_map([K,V|T], Map) ->
+ list_to_map(T, Map#{K => V}).
+
+list_to_fun([X]) ->
+ fun(A) -> A + X end;
+list_to_fun([X, Y]) ->
+ fun(A) -> A + X + Y end;
+list_to_fun([X, Y | T]) ->
+ fun(A) -> [A+X+Y | T] end.
+
+mk_ext_pid({NodeName, Creation}, Number, Serial) ->
+ erts_test_utils:mk_ext_pid({NodeName, Creation}, Number, Serial).
+
+mk_ext_port({NodeName, Creation}, Number) ->
+ erts_test_utils:mk_ext_port({NodeName, Creation}, Number).
+
+mk_ext_ref({NodeName, Creation}, Numbers) ->
+ erts_test_utils:mk_ext_ref({NodeName, Creation}, Numbers).
+
+%% Convert local funs to maps to show fun environment
+printable(Fun) when is_function(Fun) ->
+ case erlang:fun_info(Fun, type) of
+ {type,local} ->
+ {env, Env} = erlang:fun_info(Fun, env),
+ #{'fun' => [printable(T) || T <- Env]};
+ {type,external} ->
+ Fun
+ end;
+printable([H|T]) ->
+ [printable(H)|printable(T)];
+printable(Tuple) when is_tuple(Tuple) ->
+ list_to_tuple(printable(tuple_to_list(Tuple)));
+printable(Map) when is_map(Map) ->
+ maps:from_list(printable(maps:to_list(Map)));
+printable(Leaf) ->
+ Leaf.
+
+
ei_threaded_accept(Config) when is_list(Config) ->
Einode = filename:join(proplists:get_value(data_dir, Config), "eiaccnode"),
ei_threaded_accept_do(Einode, default),
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
index 7cfc0c9da0..97c8721bde 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -198,10 +198,13 @@ static void cmd_ei_accept(char* buf, int len)
static void cmd_ei_receive(char* buf, int len)
{
+ static int call_cnt = 0;
ei_x_buff x;
erlang_msg msg;
long l;
int fd, index = 0;
+
+ call_cnt++;
if (ei_decode_long(buf, &index, &l) < 0)
fail("expected int (fd)");
@@ -215,6 +218,22 @@ static void cmd_ei_receive(char* buf, int len)
fail1("ei_xreceive_msg, got==%d", got);
break;
}
+
+ {
+ int index = 0;
+ int skip_ret;
+
+ if (ei_decode_version(x.buff, &index, NULL) != 0)
+ fail("ei_decode_version failed");
+
+ skip_ret = ei_skip_term(x.buff, &index);
+ if (skip_ret != 0)
+ fail1("ei_skip_term returned %d", skip_ret);
+ if (index != x.index )
+ fail3("ei_skip_term length mismatch %d != %d (call_cnt=%d)\n",
+ index, x.index, call_cnt);
+ }
+
index = 1;
send_bin_term(&x);
ei_x_free(&x);
diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c
index ef1ab96d41..7dc9696611 100644
--- a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c
+++ b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2020. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -145,7 +145,7 @@ static void*
ei_x_free(&x);
ei_x_free(&xs);
} else {
- fprintf(file, "coudn't connect fd %d r %d\n", fd, r); fflush(file);
+ fprintf(file, "couldn't connect fd %d r %d\n", fd, r); fflush(file);
}
ei_close_connection(listen);
fprintf(file, "done thread %d\n", n);
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index 379c3bb4ba..f713637438 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -72,7 +72,7 @@ static struct {
/*
- * Sends a list contaning all data types to the Erlang side.
+ * Sends a list containing all data types to the Erlang side.
*/
TESTCASE(interpret)
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/einode.c b/lib/erl_interface/test/ei_connect_SUITE_data/einode.c
index 54bd0ecd8b..1739245ab8 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/einode.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/einode.c
@@ -89,7 +89,7 @@ static void*
shutdown(fd, SD_SEND);
closesocket(fd);
} else {
- printf("coudn't connect fd %d r %d\n", fd, r); // DebugBreak();
+ printf("couldn't connect fd %d r %d\n", fd, r); // DebugBreak();
}
printf("done thread %d\n", n);
return 0;
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index a51078f7e7..3703e85777 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ init_per_testcase(Case, Config) ->
%% ---------------------------------------------------------------------------
-% NOTE: for historical reasons we don't pach as tight as we can,
+% NOTE: for historical reasons we don't patch as tight as we can,
% we only fill 27 bits in 32 bit INTEGER_EXT
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index d6e026379f..8327398527 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -52,7 +52,7 @@ init_per_testcase(Case, Config) ->
%% ---------------------------------------------------------------------------
-% NOTE: for historical reasons we don't pach as tight as we can,
+% NOTE: for historical reasons we don't patch as tight as we can,
% we only fill 27 bits in 32 bit INTEGER_EXT
diff --git a/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c b/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c
index c018ff625a..5150b78e6d 100644
--- a/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c
+++ b/lib/erl_interface/test/ei_global_SUITE_data/ei_global_test.c
@@ -59,7 +59,7 @@ static struct {
/*
- * Sends a list contaning all data types to the Erlang side.
+ * Sends a list containing all data types to the Erlang side.
*/
TESTCASE(interpret)
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 2e3789a3d9..a6964e3ec0 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,8 @@
ei_send_tmo/1,
ei_send_failure_tmo/1,
ei_connect_unreachable_tmo/0, ei_connect_unreachable_tmo/1,
- ei_recv_tmo/1]).
+ ei_recv_tmo/1,
+ ei_dflags/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -48,7 +49,8 @@ groups() ->
Members = [ei_recv_tmo,
ei_accept_tmo,
ei_connect_tmo,
- ei_send_tmo],
+ ei_send_tmo,
+ ei_dflags],
[{default, [], Members},
{ussi, [], Members}].
@@ -61,6 +63,41 @@ init_per_testcase(Case, Config) ->
end_per_testcase(_Case, _Config) ->
ok.
+-define(DFLAG_PUBLISHED, 16#01).
+-define(DFLAG_ATOM_CACHE, 16#02).
+-define(DFLAG_EXTENDED_REFERENCES, 16#04).
+-define(DFLAG_DIST_MONITOR, 16#08).
+-define(DFLAG_FUN_TAGS, 16#10).
+-define(DFLAG_NEW_FUN_TAGS, 16#80).
+-define(DFLAG_EXTENDED_PIDS_PORTS, 16#100).
+-define(DFLAG_EXPORT_PTR_TAG, 16#200).
+-define(DFLAG_BIT_BINARIES, 16#400).
+-define(DFLAG_NEW_FLOATS, 16#800).
+-define(DFLAG_UTF8_ATOMS, 16#10000).
+-define(DFLAG_MAP_TAG, 16#20000).
+-define(DFLAG_BIG_CREATION, 16#40000).
+-define(DFLAG_HANDSHAKE_23, 16#1000000).
+-define(DFLAG_MANDATORY_25_DIGEST, 16#4000000).
+
+%% From OTP R9 extended references are compulsory.
+%% From OTP R10 extended pids and ports are compulsory.
+%% From OTP 20 UTF8 atoms are compulsory.
+%% From OTP 21 NEW_FUN_TAGS is compulsory (no more tuple fallback {fun, ...}).
+%% From OTP 23 BIG_CREATION is compulsory.
+%% From OTP 25 NEW_FLOATS, MAP_TAG, EXPORT_PTR_TAG, and BIT_BINARIES are compulsory.
+-define(COMPULSORY_DFLAGS,
+ (?DFLAG_EXTENDED_REFERENCES bor
+ ?DFLAG_FUN_TAGS bor
+ ?DFLAG_EXTENDED_PIDS_PORTS bor
+ ?DFLAG_UTF8_ATOMS bor
+ ?DFLAG_NEW_FUN_TAGS bor
+ ?DFLAG_BIG_CREATION bor
+ ?DFLAG_NEW_FLOATS bor
+ ?DFLAG_MAP_TAG bor
+ ?DFLAG_EXPORT_PTR_TAG bor
+ ?DFLAG_BIT_BINARIES bor
+ ?DFLAG_HANDSHAKE_23)).
+
%% Check the framework.
framework_check(Config) when is_list(Config) ->
%%dbg:tracer(),
@@ -106,9 +143,13 @@ do_one_recv_failure(Config,CNode) ->
true = (Ret < 0),
runner:recv_eot(P1).
--define(EI_DIST_LOW, 5).
+-define(EI_DIST_LOW, 6).
-define(EI_DIST_HIGH, 6).
+%% An OTP-23 or 24 node may connect assuming 5 or higher.
+-define(EI_DIST_LOWEST_ASSUMED, 5).
+
+
%% Check send with timeouts.
ei_send_tmo(Config) when is_list(Config) ->
register(ei_send_tmo_1,self()),
@@ -140,15 +181,11 @@ do_one_send(Config,From,CNode) ->
ei_send_failure_tmo(Config) when is_list(Config) ->
register(ei_send_tmo_1,self()),
- [begin
- io:format("Test dist version ~p\n", [Ver]),
- do_one_send_failure(Config,self(),cccc1,c_nod_send_tmo_3, Ver),
- do_one_send_failure(Config,ei_send_tmo_1,cccc2,c_nod_send_tmo_4, Ver)
- end
- || Ver <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH)],
+ do_one_send_failure(Config,self(),cccc1,c_nod_send_tmo_3),
+ do_one_send_failure(Config,ei_send_tmo_1,cccc2,c_nod_send_tmo_4),
ok.
-do_one_send_failure(Config,From,FakeName,CName, OurVer) ->
+do_one_send_failure(Config,From,FakeName,CName) ->
{_,Host} = split(node()),
OurName = join(FakeName,Host),
Node = join(CName,Host),
@@ -158,7 +195,7 @@ do_one_send_failure(Config,From,FakeName,CName, OurVer) ->
Else ->
exit(Else)
end,
- EpmdSocket = epmd_register(OurName, LSocket, OurVer),
+ EpmdSocket = epmd_register(OurName, LSocket),
P3 = runner:start(Config, ?send_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{CName,
@@ -171,10 +208,10 @@ do_one_send_failure(Config,From,FakeName,CName, OurVer) ->
Else2 ->
exit(Else2)
end,
- {hidden,Node} = recv_name(SocketB, OurVer), % See 1)
+ {hidden,Node} = recv_name(SocketB), % See 1)
send_status(SocketB, ok),
MyChallengeB = gen_challenge(),
- send_challenge(SocketB, OurName, MyChallengeB, OurVer),
+ send_challenge(SocketB, OurName, MyChallengeB),
HisChallengeB = recv_challenge_reply(SocketB,
MyChallengeB,
Cookie),
@@ -220,15 +257,8 @@ ei_connect_unreachable_tmo(Config) when is_list(Config) ->
ok.
ei_connect_tmo(Config) when is_list(Config) ->
- [begin
- io:format("Test dist version ~p published as ~p\n", [OurVer,OurEpmdVer]),
- do_ei_connect_tmo(Config, OurVer, OurEpmdVer)
- end
- || OurVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH),
- OurEpmdVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH),
- OurVer >= OurEpmdVer].
+ Flags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
-do_ei_connect_tmo(Config, OurVer, OurEpmdVer) ->
P2 = runner:start(Config, ?connect_tmo),
runner:send_term(P2,{c_nod_connect_tmo_2,
erlang:get_cookie(),
@@ -237,6 +267,7 @@ do_ei_connect_tmo(Config, OurVer, OurEpmdVer) ->
{term, X} = runner:get_term(P2, 10000),
runner:recv_eot(P2),
true = is_integer(X),
+
%% Aborted handshake test...
{_,Host} = split(node()),
OurName = join(cccc,Host),
@@ -247,7 +278,7 @@ do_ei_connect_tmo(Config, OurVer, OurEpmdVer) ->
Else ->
exit(Else)
end,
- EpmdSocket = epmd_register(OurName, LSocket, OurEpmdVer),
+ EpmdSocket = epmd_register(OurName, LSocket),
P3 = runner:start(Config, ?connect_tmo),
Cookie = kaksmula_som_ingen_bryr_sig_om,
runner:send_term(P3,{c_nod_connect_tmo_3,
@@ -260,11 +291,10 @@ do_ei_connect_tmo(Config, OurVer, OurEpmdVer) ->
Else2 ->
exit(Else2)
end,
- {hidden,Node} = recv_name(SocketB, OurEpmdVer), % See 1)
+ {hidden,Node} = recv_name(SocketB), % See 1)
send_status(SocketB, ok),
MyChallengeB = gen_challenge(),
- send_challenge(SocketB, OurName, MyChallengeB, OurVer),
- recv_complement(SocketB, OurVer, OurEpmdVer),
+ send_challenge(SocketB, OurName, MyChallengeB, Flags),
_HisChallengeB = recv_challenge_reply(SocketB,
MyChallengeB,
Cookie),
@@ -278,22 +308,23 @@ do_ei_connect_tmo(Config, OurVer, OurEpmdVer) ->
%% Check accept with timeouts.
ei_accept_tmo(Config) when is_list(Config) ->
[begin
- io:format("Test our dist ver=~p and assumed ver=~p\n",
- [OurVer, AssumedVer]),
- do_ei_accept_tmo(Config, OurVer, AssumedVer)
+ io:format("Test assumed ver=~p\n",
+ [AssumedVer]),
+ do_ei_accept_tmo(Config, AssumedVer)
end
- || OurVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH),
- AssumedVer <- lists:seq(?EI_DIST_LOW, ?EI_DIST_HIGH),
- OurVer >= AssumedVer],
+ || AssumedVer <- lists:seq(?EI_DIST_LOWEST_ASSUMED, ?EI_DIST_HIGH)],
ok.
-do_ei_accept_tmo(Config, OurVer, AssumedVer) ->
+do_ei_accept_tmo(Config, AssumedVer) ->
+ Flags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
+
P = runner:start(Config, ?accept_tmo),
runner:send_term(P,{c_nod_som_ingen_kontaktar_1,
kaksmula_som_ingen_bryr_sig_om,
get_group(Config)}),
{term,{-1,ETimedout,ETimedout}} = runner:get_term(P, 10000),
runner:recv_eot(P),
+
P2 = runner:start(Config, ?accept_tmo),
runner:send_term(P2,{c_nod_som_vi_kontaktar_1,
erlang:get_cookie(),
@@ -304,8 +335,14 @@ do_ei_accept_tmo(Config, OurVer, AssumedVer) ->
{term, X} = runner:get_term(P2, 10000),
runner:recv_eot(P2),
true = is_integer(X),
- P3 = runner:start(Config, ?accept_tmo),
- runner:send_term(P3,{c_nod_som_vi_kontaktar_2,
+
+ normal_accept(Config, AssumedVer, Flags),
+
+ ok.
+
+normal_accept(Config, AssumedVer, Flags) ->
+ P = runner:start(Config, ?accept_tmo),
+ runner:send_term(P,{c_nod_som_vi_kontaktar_2,
erlang:get_cookie(),
get_group(Config)}),
receive after 1000 -> ok end,
@@ -317,17 +354,47 @@ do_ei_accept_tmo(Config, OurVer, AssumedVer) ->
{ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
[{active,false},
{packet,2}]),
- send_name(SocketA,OurName,OurVer,AssumedVer),
+ send_name(SocketA, OurName, AssumedVer, Flags),
ok = recv_status(SocketA),
- {hidden,_Node,HisChallengeA} = recv_challenge(SocketA,OurVer), % See 1)
+ {hidden,_Node,HisChallengeA} = recv_challenge(SocketA), % See 1)
_OurChallengeA = gen_challenge(),
_OurDigestA = gen_digest(HisChallengeA, erlang:get_cookie()),
%% Dont do the last two steps of the connection setup...
%% send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
%% ok = recv_challenge_ack(SocketA, OurChallengeA, erlang:get_cookie()),
- {term, {-1,ETimedout,ETimedout}} = runner:get_term(P3, 10000),
- runner:recv_eot(P3),
- gen_tcp:close(SocketA),
+ {term, {-1,ETimedout,ETimedout}} = runner:get_term(P, 10000),
+ runner:recv_eot(P),
+ gen_tcp:close(SocketA).
+
+normal_connect(Config, Flags) ->
+ {_,Host} = split(node()),
+ OurName = join(cccc,Host),
+ Node = join(c_nod_connect_tmo_3,Host),
+ LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
+ {ok, Socket} ->
+ Socket;
+ Else ->
+ exit(Else)
+ end,
+ EpmdSocket = epmd_register(OurName, LSocket),
+ P3 = runner:start(Config, ?connect_tmo),
+ Cookie = kaksmula_som_ingen_bryr_sig_om,
+ runner:send_term(P3, {c_nod_connect_tmo_3,
+ Cookie,
+ OurName,
+ get_group(Config)}),
+ SocketB = case gen_tcp:accept(LSocket) of
+ {ok, Socket1} ->
+ Socket1;
+ Else2 ->
+ exit(Else2)
+ end,
+ {hidden,Node} = recv_name(SocketB),
+ send_status(SocketB, ok),
+ MyChallengeB = gen_challenge(),
+ send_challenge(SocketB, OurName, MyChallengeB, Flags),
+ gen_tcp:close(SocketB),
+ gen_tcp:close(EpmdSocket),
ok.
make_node(X) ->
@@ -345,6 +412,23 @@ make_and_check_dummy() ->
list_to_atom("dummy@"++HostNotReachable).
+%% Test that erl_interface sets the appropriate distributions flags.
+ei_dflags(Config) ->
+ AssumedVer = 5,
+ OurVer = 6,
+
+ %% Test compatibility with OTP 24 and earlier.
+ normal_connect(Config, ?COMPULSORY_DFLAGS),
+ normal_accept(Config, AssumedVer, ?COMPULSORY_DFLAGS),
+ normal_accept(Config, OurVer, ?COMPULSORY_DFLAGS),
+
+ %% Test compatibility with future versions.
+ normal_connect(Config, ?DFLAG_MANDATORY_25_DIGEST),
+ normal_accept(Config, AssumedVer, ?DFLAG_MANDATORY_25_DIGEST),
+ normal_accept(Config, OurVer, ?DFLAG_MANDATORY_25_DIGEST),
+
+ ok.
+
%%
%% Stolen from the erl_distribution_wb_test in kernel
%% To be able to do partial handshakes...
@@ -359,18 +443,6 @@ make_and_check_dummy() ->
R
end).
--define(DFLAG_PUBLISHED,1).
--define(DFLAG_ATOM_CACHE,2).
--define(DFLAG_EXTENDED_REFERENCES,4).
--define(DFLAG_EXTENDED_PIDS_PORTS,16#100).
--define(DFLAG_NEW_FLOATS,16#800).
--define(DFLAG_DIST_MONITOR,8).
--define(DFLAG_HANDSHAKE_23,16#1000000).
-
-%% From R9 and forward extended references is compulsory
-%% From 14 and forward new float is compulsory
--define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS bor ?DFLAG_NEW_FLOATS)).
-
-define(shutdown(X), exit(X)).
-define(int16(X), [((X) bsr 8) band 16#ff, (X) band 16#ff]).
@@ -411,7 +483,7 @@ gen_digest(Challenge, Cookie) when is_integer(Challenge), is_atom(Cookie) ->
%%
-%% The differrent stages of the MD5 handshake
+%% The different stages of the MD5 handshake
%%
send_status(Socket, Stat) ->
@@ -429,40 +501,27 @@ recv_status(Socket) ->
exit(Bad)
end.
-send_challenge(Socket, Node, Challenge, OurVer) ->
- send_challenge(Socket, Node, Challenge, OurVer, ?COMPULSORY_DFLAGS).
-
-send_challenge(Socket, Node, Challenge, OurVer, Flags) ->
- if OurVer =:= 5 ->
- ?to_port(Socket, [$n, ?int16(OurVer), ?int32(Flags),
- ?int32(Challenge), atom_to_list(Node)]);
- OurVer >= 6 ->
- NodeName = atom_to_binary(Node, latin1),
- NameLen = byte_size(NodeName),
- Creation = erts_internal:get_creation(),
- ?to_port(Socket, [$N,
- <<(Flags bor ?DFLAG_HANDSHAKE_23):64,
- Challenge:32,
- Creation:32,
- NameLen:16>>,
- NodeName])
- end.
-
-recv_challenge(Socket, OurVer) ->
+send_challenge(Socket, Node, Challenge) ->
+ DefaultFlags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
+ send_challenge(Socket, Node, Challenge, DefaultFlags).
+
+send_challenge(Socket, Node, Challenge, Flags) ->
+ NodeName = atom_to_binary(Node, latin1),
+ NameLen = byte_size(NodeName),
+ Creation = erts_internal:get_creation(),
+ ?to_port(Socket, [$N,
+ << Flags:64,
+ Challenge:32,
+ Creation:32,
+ NameLen:16>>,
+ NodeName]).
+
+recv_challenge(Socket) ->
case gen_tcp:recv(Socket, 0) of
- {ok,[$n,V1,V0,Fl1,Fl2,Fl3,Fl4,CA3,CA2,CA1,CA0 | Ns]} ->
- 5 = OurVer,
- Flags = ?u32(Fl1,Fl2,Fl3,Fl4),
- Type = flags_to_type(Flags),
- Node =list_to_atom(Ns),
- OurVer = ?u16(V1,V0), % echoed back
- Challenge = ?u32(CA3,CA2,CA1,CA0),
- {Type,Node,Challenge};
-
{ok,[$N, F7,F6,F5,F4,F3,F2,F1,F0, CA3,CA2,CA1,CA0,
_Cr3,_Cr2,_Cr1,_Cr0, NL1,NL0 | Rest]} ->
- true = (OurVer >= 6),
<<Flags:64>> = <<F7,F6,F5,F4,F3,F2,F1,F0>>,
+ verify_flags(Flags),
Type = flags_to_type(Flags),
NameLen = ?u16(NL1,NL0),
{NodeName,_} = lists:split(NameLen, Rest),
@@ -517,17 +576,11 @@ send_challenge_ack(Socket, Digest) ->
% ?shutdown(bad_challenge_ack)
% end.
-send_name(Socket, MyNode, OurVer, AssumedVer) ->
- Flags = ?COMPULSORY_DFLAGS bor (case OurVer of
- 5 -> 0;
- 6 -> ?DFLAG_HANDSHAKE_23
- end),
- send_name(Socket, MyNode, OurVer, AssumedVer, Flags).
-
-send_name(Socket, MyNode, OurVer, AssumedVer, Flags) ->
+send_name(Socket, MyNode, AssumedVer, Flags0) ->
+ Flags = Flags0 bor?DFLAG_HANDSHAKE_23,
NodeName = atom_to_binary(MyNode, latin1),
if AssumedVer =:= 5 ->
- ?to_port(Socket, [$n,?int16(OurVer),?int32(Flags),NodeName]);
+ ?to_port(Socket, [$n,?int16(?EI_DIST_HIGH),?int32(Flags),NodeName]);
AssumedVer >= 6 ->
Creation = erts_internal:get_creation(),
?to_port(Socket, [$N,
@@ -537,34 +590,18 @@ send_name(Socket, MyNode, OurVer, AssumedVer, Flags) ->
NodeName])
end.
-recv_name(Socket, OurEpmdVer) ->
+recv_name(Socket) ->
case gen_tcp:recv(Socket, 0) of
- {ok,[$n, V1,V0, F3,F2,F1,F0 | OtherNode]} ->
- 5 = OurEpmdVer,
- 5 = ?u16(V1,V0),
- Type = flags_to_type(?u32(F3,F2,F1,F0)),
- {Type, list_to_atom(OtherNode)};
{ok,[$N, F7,F6,F5,F4,F3,F2,F1,F0, _Cr3,_Cr2,_Cr1,_Cr0, NL1, NL0 | Rest]} ->
- true = (OurEpmdVer >= 6),
{OtherNode, _Residue} = lists:split(?u16(NL1,NL0), Rest),
<<Flags:64>> = <<F7,F6,F5,F4,F3,F2,F1,F0>>,
+ verify_flags(Flags),
Type = flags_to_type(Flags),
{Type, list_to_atom(OtherNode)};
Res ->
?shutdown({no_node,Res})
end.
-recv_complement(Socket, OurVer, 5) when OurVer > 5 ->
- case gen_tcp:recv(Socket, 0) of
- {ok,[$c, _F7,_F6,_F5,_F4, _Cr3,_Cr2,_Cr1,_Cr0]} ->
- ok;
- Res ->
- ?shutdown({no_node,Res})
- end;
-recv_complement(_, _OurVer, _OurEpmdVer) ->
- ok.
-
-
%%
%% tell_name is for old handshake
%%
@@ -576,7 +613,7 @@ recv_complement(_, _OurVer, _OurEpmdVer) ->
%%
%% The communication with EPMD follows
%%
-do_register_node(NodeName, TcpPort, VLow, VHigh) ->
+do_register_node(NodeName, TcpPort) ->
case gen_tcp:connect({127,0,0,1}, get_epmd_port(), []) of
{ok, Socket} ->
{N0,_} = split(NodeName),
@@ -588,8 +625,8 @@ do_register_node(NodeName, TcpPort, VLow, VHigh) ->
?int16(TcpPort),
$M,
0,
- ?int16(VHigh),
- ?int16(VLow),
+ ?int16(?EI_DIST_HIGH),
+ ?int16(?EI_DIST_LOW),
?int16(length(Name)),
Name,
?int16(Elen),
@@ -625,15 +662,25 @@ wait_for_reg_reply(Socket, SoFar) ->
end.
-epmd_register(NodeName, ListenSocket, OurVer) ->
+epmd_register(NodeName, ListenSocket) ->
{ok,{_,TcpPort}} = inet:sockname(ListenSocket),
- case do_register_node(NodeName, TcpPort, ?EI_DIST_LOW, OurVer) of
+ case do_register_node(NodeName, TcpPort) of
{alive, Socket, _Creation} ->
Socket;
Other ->
exit(Other)
end.
+verify_flags(Flags) ->
+ RequiredFlags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
+ if
+ Flags band RequiredFlags =:= RequiredFlags ->
+ ok;
+ true ->
+ io:format("Given flags: ~.16.0B\n", [Flags]),
+ io:format("Required flags: ~.16.0B\n", [RequiredFlags]),
+ ct:fail(missing_dflags)
+ end.
%%
%% Utilities
diff --git a/lib/erl_interface/test/runner.erl b/lib/erl_interface/test/runner.erl
index 484890006e..0ebaf0f1d9 100644
--- a/lib/erl_interface/test/runner.erl
+++ b/lib/erl_interface/test/runner.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
-export([test/2, test/3,
init_per_testcase/3,
- start/2, send_term/2, finish/1, send_eot/1, recv_eot/1,
+ start/2, start/3, send_term/2, finish/1, send_eot/1, recv_eot/1,
get_term/1, get_term/2]).
-define(default_timeout, 5000).
@@ -55,14 +55,21 @@ test(Config, Tc, Timeout) ->
%%
%% Returns: {ok, Port}
-start(Config, {Prog, Tc}) when is_list(Prog), is_integer(Tc) ->
- Port = open_port({spawn, prog_cmd(Config, Prog)},
+start(Config, ProgTc) ->
+ start(Config, ProgTc, []).
+
+start(Config, {Prog, Tc}, Opt) when is_list(Prog), is_integer(Tc) ->
+ Port = open_port({spawn, prog_cmd(Config, Prog, Opt)},
[{packet, 4}, exit_status]),
Command = [Tc div 256, Tc rem 256],
Port ! {self(), {command, Command}},
Port.
-prog_cmd(Config, Prog) ->
+prog_cmd(Config, Prog0, Opt) ->
+ Prog = case Opt of
+ rr -> "rr " ++ Prog0;
+ [] -> Prog0
+ end,
case proplists:get_value(valgrind_cmd_fun, Config) of
undefined ->
Prog;
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index b0833390af..badd74c6da 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 5.2.2
+EI_VSN = 5.3.1
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/et/doc/src/et_desc.xmlsrc b/lib/et/doc/src/et_desc.xmlsrc
index 29e0ab1fe3..a1f9546db2 100644
--- a/lib/et/doc/src/et_desc.xmlsrc
+++ b/lib/et/doc/src/et_desc.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -520,7 +520,7 @@ ok]]></code>
<p><c>Hide (excluded actors)</c> - When true, this means that
the <c>Viewer</c> will hide all <c>Events</c> whose actors are
marked as excluded. Excluded actors are normally enclosed in
- round brackets when they are displayed inthe
+ round brackets when they are displayed in the
<c>Viewer</c>.</p>
</item>
diff --git a/lib/et/examples/Makefile b/lib/et/examples/Makefile
index fe6811e45d..c572fb4ce6 100644
--- a/lib/et/examples/Makefile
+++ b/lib/et/examples/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2016. All Rights Reserved.
+# Copyright Ericsson AB 2002-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ EBIN = .
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES) *~
diff --git a/lib/et/src/Makefile b/lib/et/src/Makefile
index b6347d8b6d..fc66cc1eaf 100644
--- a/lib/et/src/Makefile
+++ b/lib/et/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -76,8 +76,8 @@ ERL_COMPILE_FLAGS += -pa $(ERL_TOP)/lib/et/ebin -I../include -Werror
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/et/src/et.erl b/lib/et/src/et.erl
index 91c17ffdc9..b951439ef3 100644
--- a/lib/et/src/et.erl
+++ b/lib/et/src/et.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@
%% et_viewer
%%
%% A graphical sequence chart tool. It is connected to a
-%% et_collector-process, which it polls regulary for more trace
+%% et_collector-process, which it polls regularly for more trace
%% events to display. Before the event is displayed a user defined
%% filter function is applied in order to skip, accept as is or
%% transform the event. Several et_viewer-processes may share the
diff --git a/lib/et/src/et_selector.erl b/lib/et/src/et_selector.erl
index 35db07cd99..b293907aef 100644
--- a/lib/et/src/et_selector.erl
+++ b/lib/et/src/et_selector.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@ make_pattern({Mod, Pattern}) when is_atom(Mod) ->
%% An empty match spec deactivates tracing of calls to trace_me/4,5
%%
%% Other match specs activates tracing of calls to trace_me/4,5
-%% accordlingly with erlang:trace_pattern/2.
+%% accordingly with erlang:trace_pattern/2.
%%----------------------------------------------------------------------
change_pattern({Mod, Pattern}) when is_atom(Mod) ->
diff --git a/lib/et/src/et_wx_viewer.erl b/lib/et/src/et_wx_viewer.erl
index 51e80b73fd..d6fd3a0095 100644
--- a/lib/et/src/et_wx_viewer.erl
+++ b/lib/et/src/et_wx_viewer.erl
@@ -55,7 +55,7 @@
first_event, % Key of first event (regardless of visibility)
last_event, % Key of last event (regardless of visibility)
events_per_page, % Maximum number of shown events
- events, % Queue containg all event keys (regardless of visibility)
+ events, % Queue containing all event keys (regardless of visibility)
n_events, % Number of events available in the collector
max_actors, % Maximum number of shown actors
actors, % List of known actors
diff --git a/lib/et/test/Makefile b/lib/et/test/Makefile
index 45ea2c2ce0..55c6037c10 100644
--- a/lib/et/test/Makefile
+++ b/lib/et/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ EBIN = .
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index fad15b48fc..1f1786159c 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -33,6 +33,89 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.8.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, eunit exact_execution option works with
+ application primitive.</p>
+ <p>
+ Own Id: OTP-18264 Aux Id: PR-6322, GH-6320 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ With this change, Eunit can optionally not try to execute
+ related module with "_tests" suffix. This might be used
+ for avoiding duplicated executions when source and test
+ modules are located in the same folder.</p>
+ <p>
+ Own Id: OTP-18181 Aux Id: ERL-97, GH-3064, PR-5461 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Eunit 2.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Minor internal improvements.</p>
+ <p>
+ Own Id: OTP-17884 Aux Id: GH-5617 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/eunit/examples/Makefile b/lib/eunit/examples/Makefile
index 01620746f5..23433e1a70 100644
--- a/lib/eunit/examples/Makefile
+++ b/lib/eunit/examples/Makefile
@@ -37,7 +37,7 @@ EXAMPLE_FILES = fib.erl tests.txt
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile
index 32f75202a0..f4eaf6807a 100644
--- a/lib/eunit/src/Makefile
+++ b/lib/eunit/src/Makefile
@@ -73,7 +73,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug opt: $(PARSE_TRANSFORM_BIN) $(OBJECTS)
+$(TYPES): $(PARSE_TRANSFORM_BIN) $(OBJECTS)
docs:
@@ -121,7 +121,7 @@ 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_DATA) $(PARSE_TRANSFORM) $(SOURCES) $(BEHAVIOUR_SOURCES) "$(RELSYSDIR)/src"
$(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src"
$(INSTALL_DIR) "$(RELSYSDIR)/include"
$(INSTALL_DATA) $(INCLUDE_DELIVERABLES) "$(RELSYSDIR)/include"
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index 0238885708..f30c238366 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -135,6 +135,11 @@ test(Tests) ->
%% <dd>Displays more details about the running tests.</dd>
%% <dt>`print_depth'</dt>
%% <dd>Maximum depth to which terms are printed in case of error.</dd>
+%% <dt>`exact_execution'</dt>
+%% <dd>If this boolean flag is set to `true' framework will
+%% not automatically execute tests found in related module suffixed with "_tests".
+%% This behaviour might be unwanted if execution of modules found in a folder
+%% is ordered while it contains both source and test modules.</dd>
%% </dl>
%%
%% Options in the environment variable EUNIT are also included last in
diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl
index a16faf2e80..f85e047f33 100644
--- a/lib/eunit/src/eunit_data.erl
+++ b/lib/eunit/src/eunit_data.erl
@@ -31,10 +31,8 @@
-include_lib("kernel/include/file.hrl").
--export([iter_init/2, iter_next/1, iter_prev/1, iter_id/1,
- enter_context/3, get_module_tests/1]).
-
--import(lists, [foldr/3]).
+-export([iter_init/3, iter_next/1, iter_prev/1, iter_id/1,
+ enter_context/3, get_module_tests/2]).
-define(TICKS_PER_SECOND, 1000).
@@ -105,7 +103,7 @@
%% @type fileName() = string()
%% TODO: Can we mark up tests as known-failures?
-%% TODO: Is it possible to handle known timout/setup failures?
+%% TODO: Is it possible to handle known timeout/setup failures?
%% TODO: Add diagnostic tests which never fail, but may cause warnings?
%% ---------------------------------------------------------------------
@@ -115,14 +113,15 @@
{prev = [],
next = [],
tests = [],
+ options,
pos = 0,
parent = []}).
%% @spec (tests(), [integer()]) -> testIterator()
%% @type testIterator()
-iter_init(Tests, ParentID) ->
- #iter{tests = Tests, parent = lists:reverse(ParentID)}.
+iter_init(Tests, ParentID, Options) ->
+ #iter{tests = Tests, parent = lists:reverse(ParentID), options = Options}.
%% @spec (testIterator()) -> [integer()]
@@ -131,8 +130,8 @@ iter_id(#iter{pos = N, parent = Ns}) ->
%% @spec (testIterator()) -> none | {testItem(), testIterator()}
-iter_next(I = #iter{next = []}) ->
- case next(I#iter.tests) of
+iter_next(I = #iter{next = [], options = Options}) ->
+ case next(I#iter.tests, Options) of
{T, Tests} ->
{T, I#iter{prev = [T | I#iter.prev],
tests = Tests,
@@ -169,12 +168,12 @@ iter_prev(#iter{prev = [T | Ts]} = I) ->
%% | {file_read_error, {Reason::atom(), Message::string(),
%% fileName()}}
-next(Tests) ->
+next(Tests, Options) ->
case eunit_lib:dlist_next(Tests) of
[T | Ts] ->
- case parse(T) of
+ case parse(T, Options) of
{data, T1} ->
- next([T1 | Ts]);
+ next([T1 | Ts], Options);
T1 ->
{T1, Ts}
end;
@@ -182,18 +181,21 @@ next(Tests) ->
none
end.
+%% Temporary suppression
+-compile([{nowarn_deprecated_function,[{slave,start_link,3},{slave,stop,1}]}]).
+
%% this returns either a #test{} or #group{} record, or {data, T} to
%% signal that T has been substituted for the given representation
-parse({foreach, S, Fs}) when is_function(S), is_list(Fs) ->
- parse({foreach, S, fun ok/1, Fs});
-parse({foreach, S, C, Fs})
+parse({foreach, S, Fs}, Options) when is_function(S), is_list(Fs) ->
+ parse({foreach, S, fun ok/1, Fs}, Options);
+parse({foreach, S, C, Fs}, Options)
when is_function(S), is_function(C), is_list(Fs) ->
- parse({foreach, ?DEFAULT_SETUP_PROCESS, S, C, Fs});
-parse({foreach, P, S, Fs})
+ parse({foreach, ?DEFAULT_SETUP_PROCESS, S, C, Fs}, Options);
+parse({foreach, P, S, Fs}, Options)
when is_function(S), is_list(Fs) ->
- parse({foreach, P, S, fun ok/1, Fs});
-parse({foreach, P, S, C, Fs} = T)
+ parse({foreach, P, S, fun ok/1, Fs}, Options);
+parse({foreach, P, S, C, Fs} = T, _Options)
when is_function(S), is_function(C), is_list(Fs) ->
check_arity(S, 0, T),
check_arity(C, 1, T),
@@ -203,15 +205,15 @@ parse({foreach, P, S, C, Fs} = T)
[] ->
{data, []}
end;
-parse({foreachx, S1, Ps}) when is_function(S1), is_list(Ps) ->
- parse({foreachx, S1, fun ok/2, Ps});
-parse({foreachx, S1, C1, Ps})
+parse({foreachx, S1, Ps}, Options) when is_function(S1), is_list(Ps) ->
+ parse({foreachx, S1, fun ok/2, Ps}, Options);
+parse({foreachx, S1, C1, Ps}, Options)
when is_function(S1), is_function(C1), is_list(Ps) ->
- parse({foreachx, ?DEFAULT_SETUP_PROCESS, S1, C1, Ps});
-parse({foreachx, P, S1, Ps})
+ parse({foreachx, ?DEFAULT_SETUP_PROCESS, S1, C1, Ps}, Options);
+parse({foreachx, P, S1, Ps}, Options)
when is_function(S1), is_list(Ps) ->
- parse({foreachx, P, S1, fun ok/2, Ps});
-parse({foreachx, P, S1, C1, Ps} = T)
+ parse({foreachx, P, S1, fun ok/2, Ps}, Options);
+parse({foreachx, P, S1, C1, Ps} = T, _Options)
when is_function(S1), is_function(C1), is_list(Ps) ->
check_arity(S1, 1, T),
check_arity(C1, 2, T),
@@ -227,12 +229,12 @@ parse({foreachx, P, S1, C1, Ps} = T)
[] ->
{data, []}
end;
-parse({generator, F}) when is_function(F) ->
+parse({generator, F}, Options) 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)
+ parse({generator, F, {M,N,A}}, Options);
+parse({generator, F, {M,N,A}} = T, _Options)
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
@@ -246,38 +248,38 @@ parse({generator, F, {M,N,A}} = T)
{error, {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:mf_wrapper(M, F), {M,F,0}});
-parse({inorder, T}) ->
- group(#group{tests = T, order = inorder});
-parse({inparallel, T}) ->
- parse({inparallel, 0, T});
-parse({inparallel, N, T}) when is_integer(N), N >= 0 ->
- group(#group{tests = T, order = {inparallel, N}});
-parse({timeout, N, T}) when is_number(N), N >= 0 ->
- group(#group{tests = T, timeout = round(N * ?TICKS_PER_SECOND)});
-parse({spawn, T}) ->
- group(#group{tests = T, spawn = local});
-parse({spawn, N, T}) when is_atom(N) ->
- group(#group{tests = T, spawn = {remote, N}});
-parse({setup, S, I}) when is_function(S); is_list(S) ->
- parse({setup, ?DEFAULT_SETUP_PROCESS, S, I});
-parse({setup, S, C, I}) when is_function(S), is_function(C) ->
- parse({setup, ?DEFAULT_SETUP_PROCESS, S, C, I});
-parse({setup, P, S, I}) when is_function(S) ->
- parse({setup, P, S, fun ok/1, I});
-parse({setup, P, L, I} = T) when is_list(L) ->
+parse({generator, M, F}, Options) when is_atom(M), is_atom(F) ->
+ parse({generator, eunit_test:mf_wrapper(M, F), {M,F,0}}, Options);
+parse({inorder, T}, Options) ->
+ group(#group{tests = T, options = Options, order = inorder});
+parse({inparallel, T}, Options) ->
+ parse({inparallel, 0, T}, Options);
+parse({inparallel, N, T}, Options) when is_integer(N), N >= 0 ->
+ group(#group{tests = T, options = Options, order = {inparallel, N}});
+parse({timeout, N, T}, Options) when is_number(N), N >= 0 ->
+ group(#group{tests = T, options = Options, timeout = round(N * ?TICKS_PER_SECOND)});
+parse({spawn, T}, Options) ->
+ group(#group{tests = T, options = Options, spawn = local});
+parse({spawn, N, T}, Options) when is_atom(N) ->
+ group(#group{tests = T, options = Options, spawn = {remote, N}});
+parse({setup, S, I}, Options) when is_function(S); is_list(S) ->
+ parse({setup, ?DEFAULT_SETUP_PROCESS, S, I}, Options);
+parse({setup, S, C, I}, Options) when is_function(S), is_function(C) ->
+ parse({setup, ?DEFAULT_SETUP_PROCESS, S, C, I}, Options);
+parse({setup, P, S, I}, Options) when is_function(S) ->
+ parse({setup, P, S, fun ok/1, I}, Options);
+parse({setup, P, L, I} = T, Options) when is_list(L) ->
check_setup_list(L, T),
{S, C} = eunit_test:multi_setup(L),
- parse({setup, P, S, C, I});
-parse({setup, P, S, C, I} = T)
+ parse({setup, P, S, C, I}, Options);
+parse({setup, P, S, C, I} = T, Options)
when is_function(S), is_function(C), is_function(I) ->
check_arity(S, 0, T),
check_arity(C, 1, T),
case erlang:fun_info(I, arity) of
{arity, 0} ->
%% if I is nullary, it is a plain test
- parse({setup, S, C, fun (_) -> I end});
+ parse({setup, S, C, fun (_) -> I end}, Options);
_ ->
%% otherwise, I must be an instantiator function
check_arity(I, 1, T),
@@ -287,17 +289,17 @@ parse({setup, P, S, C, I} = T)
{spawn, N} when is_atom(N) -> ok;
_ -> bad_test(T)
end,
- group(#group{tests = I,
+ group(#group{tests = I, options = Options,
context = #context{setup = S, cleanup = C,
process = P}})
end;
-parse({setup, P, S, C, {with, As}}) when is_list(As) ->
- parse({setup, P, S, C, fun (X) -> {with, X, As} end});
-parse({setup, P, S, C, T}) when is_function(S), is_function(C) ->
- parse({setup, P, S, C, fun (_) -> T end});
-parse({node, N, T}) when is_atom(N) ->
- parse({node, N, "", T});
-parse({node, N, A, T1}=T) when is_atom(N) ->
+parse({setup, P, S, C, {with, As}}, Options) when is_list(As) ->
+ parse({setup, P, S, C, fun (X) -> {with, X, As} end}, Options);
+parse({setup, P, S, C, T}, Options) when is_function(S), is_function(C) ->
+ parse({setup, P, S, C, fun (_) -> T end}, Options);
+parse({node, N, T}, Options) when is_atom(N) ->
+ parse({node, N, "", T}, Options);
+parse({node, N, A, T1}=T, Options) when is_atom(N) ->
case eunit_lib:is_string(A) of
true ->
%% TODO: better stack traces for internal funs like these
@@ -333,14 +335,14 @@ parse({node, N, A, T1}=T) when is_atom(N) ->
false -> ok
end
end,
- T1});
+ T1}, Options);
false ->
bad_test(T)
end;
-parse({module, M}) when is_atom(M) ->
- {data, {"module '" ++ atom_to_list(M) ++ "'", get_module_tests(M)}};
-parse({application, A}) when is_atom(A) ->
- try parse({file, atom_to_list(A)++".app"})
+parse({module, M}, Options) when is_atom(M) ->
+ {data, {"module '" ++ atom_to_list(M) ++ "'", get_module_tests(M, Options)}};
+parse({application, A}, Options) when is_atom(A) ->
+ try parse({file, atom_to_list(A)++".app"}, Options)
catch
{file_read_error,{enoent,_,_}} ->
case code:lib_dir(A) of
@@ -349,15 +351,15 @@ parse({application, A}) when is_atom(A) ->
BinDir = filename:join(Dir, "ebin"),
case file:read_file_info(BinDir) of
{ok, #file_info{type=directory}} ->
- parse({dir, BinDir});
+ parse({dir, BinDir}, Options);
_ ->
- parse({dir, Dir})
+ parse({dir, Dir}, Options)
end;
_ ->
throw({application_not_found, A})
end
end;
-parse({application, A, Info}=T) when is_atom(A) ->
+parse({application, A, Info}=T, _Options) when is_atom(A) ->
case proplists:get_value(modules, Info) of
Ms when is_list(Ms) ->
case [M || M <- Ms, not is_atom(M)] of
@@ -369,14 +371,14 @@ parse({application, A, Info}=T) when is_atom(A) ->
_ ->
bad_test(T)
end;
-parse({file, F} = T) when is_list(F) ->
+parse({file, F} = T, _Options) when is_list(F) ->
case eunit_lib:is_string(F) of
true ->
{data, {"file \"" ++ F ++ "\"", get_file_tests(F)}};
false ->
bad_test(T)
end;
-parse({dir, D}=T) when is_list(D) ->
+parse({dir, D}=T, _Options) when is_list(D) ->
case eunit_lib:is_string(D) of
true ->
{data, {"directory \"" ++ D ++ "\"",
@@ -384,45 +386,45 @@ parse({dir, D}=T) when is_list(D) ->
false ->
bad_test(T)
end;
-parse({with, X, As}=T) when is_list(As) ->
+parse({with, X, As}=T, _Options) when is_list(As) ->
case As of
[A | As1] ->
check_arity(A, 1, T),
- {data, [{eunit_lib:fun_parent(A), fun () -> A(X) end},
+ {data, [{erlang:fun_info_mfa(A), fun () -> A(X) end},
{with, X, As1}]};
[] ->
{data, []}
end;
-parse({S, T1} = T) when is_list(S) ->
+parse({S, T1} = T, Options) when is_list(S) ->
case eunit_lib:is_string(S) of
true ->
- group(#group{tests = T1, desc = unicode:characters_to_binary(S)});
+ group(#group{tests = T1, options = Options, desc = unicode:characters_to_binary(S)});
false ->
bad_test(T)
end;
-parse({S, T1}) when is_binary(S) ->
- group(#group{tests = T1, desc = S});
-parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) ->
+parse({S, T1}, Options) when is_binary(S) ->
+ group(#group{tests = T1, options = Options, desc = S});
+parse(T, Options) when tuple_size(T) > 2, is_list(element(1, T)) ->
[S | Es] = tuple_to_list(T),
- parse({S, list_to_tuple(Es)});
-parse(T) when is_tuple(T), size(T) > 2, is_binary(element(1, T)) ->
+ parse({S, list_to_tuple(Es)}, Options);
+parse(T, Options) when tuple_size(T) > 2, is_binary(element(1, T)) ->
[S | Es] = tuple_to_list(T),
- parse({S, list_to_tuple(Es)});
-parse(M) when is_atom(M) ->
- parse({module, M});
-parse(T) when is_list(T) ->
+ parse({S, list_to_tuple(Es)}, Options);
+parse(M, Options) when is_atom(M) ->
+ parse({module, M}, Options);
+parse(T, Options) when is_list(T) ->
case eunit_lib:is_string(T) of
true ->
- try parse({dir, T})
+ try parse({dir, T}, Options)
catch
{file_read_error,{R,_,_}}
when R =:= enotdir; R =:= enoent ->
- parse({file, T})
+ parse({file, T}, Options)
end;
false ->
bad_test(T)
end;
-parse(T) ->
+parse(T, _Options) ->
parse_simple(T).
%% parse_simple always produces a #test{} record
@@ -436,7 +438,7 @@ parse_simple(F) ->
parse_function(F) when is_function(F) ->
check_arity(F, 0, F),
- #test{f = F, location = eunit_lib:fun_parent(F)};
+ #test{f = F, location = erlang:fun_info_mfa(F)};
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) ->
@@ -478,10 +480,10 @@ group(#group{context = #context{}} = G) ->
%% suitable for lookahead (and anyway, properties of the setup
%% should not be merged with properties of its body, e.g. spawn)
G;
-group(#group{tests = T0, desc = Desc, order = Order, context = Context,
- spawn = Spawn, timeout = Timeout} = G) ->
- {T1, Ts} = lookahead(T0),
- {T2, _} = lookahead(Ts),
+group(#group{tests = T0, desc = Desc, options = Options, order = Order,
+ context = Context, spawn = Spawn, timeout = Timeout} = G) ->
+ {T1, Ts} = lookahead(T0, Options),
+ {T2, _} = lookahead(Ts, Options),
case T1 of
#test{desc = Desc1, timeout = Timeout1}
when T2 =:= none, Spawn =:= undefined, Context =:= undefined,
@@ -526,8 +528,8 @@ group(#group{tests = T0, desc = Desc, order = Order, context = Context,
G
end.
-lookahead(T) ->
- case next(T) of
+lookahead(T, Options) ->
+ case next(T, Options) of
{T1, Ts} -> {T1, Ts};
none -> {none, []}
end.
@@ -556,58 +558,62 @@ push_order(_, _, G) ->
%% @throws {module_not_found, moduleName()}
-get_module_tests(M) ->
- try M:module_info(exports) of
- Es ->
- Fs = get_module_tests_1(M, Es),
- W = ?DEFAULT_MODULE_WRAPPER_NAME,
- case lists:member({W,1}, Es) of
- false -> Fs;
- true -> {generator, fun () -> M:W(Fs) end}
+get_module_tests(Module, Options) ->
+ try Module:module_info(exports) of
+ Exports ->
+ TestFuns = extract_module_tests(Module, Exports, Options),
+ case lists:member({?DEFAULT_MODULE_WRAPPER_NAME, 1}, Exports) of
+ false -> TestFuns;
+ true -> {generator,
+ fun() ->
+ Module:?DEFAULT_MODULE_WRAPPER_NAME(TestFuns)
+ end}
end
catch
- error:undef ->
- throw({module_not_found, M})
+ error:undef ->
+ throw({module_not_found, Module})
end.
-get_module_tests_1(M, Es) ->
- Fs = testfuns(Es, M, ?DEFAULT_TEST_SUFFIX,
- ?DEFAULT_GENERATOR_SUFFIX),
- Name = atom_to_list(M),
- case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of
- false ->
- Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX,
- M1 = list_to_atom(Name1),
- try get_module_tests(M1) of
- Fs1 ->
- Fs ++ [{"module '" ++ Name1 ++ "'", Fs1}]
+extract_module_tests(Module, Exports, Options) ->
+ TestFuns = extract_testfuns(Exports, Module, ?DEFAULT_TEST_SUFFIX,
+ ?DEFAULT_GENERATOR_SUFFIX),
+ ModuleName = atom_to_list(Module),
+ Exact = proplists:get_bool(exact_execution, Options),
+ case {lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, ModuleName),
+ Exact} of
+ {false, false} ->
+ ModuleNameWithSuffix = ModuleName ++ ?DEFAULT_TESTMODULE_SUFFIX,
+ ModuleWithSuffix = list_to_atom(ModuleNameWithSuffix),
+ try get_module_tests(ModuleWithSuffix, Options) of
+ MoreTestFuns ->
+ TestFuns ++ [{"module '" ++ ModuleNameWithSuffix ++ "'",
+ MoreTestFuns}]
catch
- {module_not_found, M1} ->
- Fs
+ {module_not_found, ModuleWithSuffix} ->
+ TestFuns
end;
- true ->
- Fs
+ _ ->
+ TestFuns
end.
-testfuns(Es, M, TestSuffix, GeneratorSuffix) ->
- foldr(fun ({F, 0}, Fs) ->
- N = atom_to_list(F),
- case lists:suffix(TestSuffix, N) of
- true ->
- [{test, M, F} | Fs];
- false ->
- case lists:suffix(GeneratorSuffix, N) of
- true ->
- [{generator, M, F} | Fs];
- false ->
- Fs
- end
- end;
- (_, Fs) ->
- Fs
- end,
- [],
- Es).
+extract_testfuns(Exports, Module, TestSuffix, GeneratorSuffix) ->
+ GetTestFun = fun({Function, 0}, Acc) ->
+ FunctionName = atom_to_list(Function),
+ case lists:suffix(TestSuffix, FunctionName) of
+ true ->
+ [{test, Module, Function} | Acc];
+ false ->
+ case lists:suffix(GeneratorSuffix, FunctionName) of
+ true ->
+ [{generator, Module, Function} | Acc];
+ false ->
+ Acc
+ end
+ end;
+ (_, Acc) ->
+ Acc
+ end,
+ lists:foldr(GetTestFun, [], Exports).
%% ---------------------------------------------------------------------
diff --git a/lib/eunit/src/eunit_internal.hrl b/lib/eunit/src/eunit_internal.hrl
index 65f4c433e7..217d4a304c 100644
--- a/lib/eunit/src/eunit_internal.hrl
+++ b/lib/eunit/src/eunit_internal.hrl
@@ -50,6 +50,7 @@
}).
-record(group, {desc = undefined,
+ options = undefined,
order = undefined, % run in order or in parallel
timeout = undefined,
context = undefined, % setup-context record
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index c7555597c2..e3129eb30f 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -32,7 +32,7 @@
-include("eunit_internal.hrl").
--export([dlist_next/1, uniq/1, fun_parent/1, is_string/1, command/1,
+-export([dlist_next/1, uniq/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_error/2,
@@ -378,27 +378,6 @@ split_node_2(As, Cs) ->
{list_to_atom(lists:reverse(As)), list_to_atom(Cs)}.
%% ---------------------------------------------------------------------
-%% Get the name of the containing function for a fun. (This is encoded
-%% in the name of the generated function that implements the fun.)
-fun_parent(F) ->
- {module, M} = erlang:fun_info(F, module),
- {name, N} = erlang:fun_info(F, name),
- case erlang:fun_info(F, type) of
- {type, external} ->
- {arity, A} = erlang:fun_info(F, arity),
- {M, N, A};
- {type, local} ->
- [$-|S] = atom_to_list(N),
- [S2, T] = string:split(S, "/", trailing),
- {M, list_to_atom(S2), element(1, string:to_integer(T))}
- end.
-
--ifdef(TEST).
-fun_parent_test() ->
- {?MODULE,fun_parent_test,0} = fun_parent(fun (A) -> {ok,A} end).
--endif.
-
-%% ---------------------------------------------------------------------
%% Ye olde uniq function
uniq([X, X | Xs]) -> uniq([X | Xs]);
diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl
index 7622bab2a9..48254f53a3 100644
--- a/lib/eunit/src/eunit_proc.erl
+++ b/lib/eunit/src/eunit_proc.erl
@@ -29,13 +29,12 @@
-include("eunit.hrl").
-include("eunit_internal.hrl").
--export([start/4, get_output/0]).
+-export([start/5, get_output/0]).
%% This must be exported; see new_group_leader/1 for details.
-export([group_leader_process/1]).
--record(procstate, {ref, id, super, insulator, parent, order}).
-
+-record(procstate, {ref, id, super, insulator, parent, order, options}).
%% Spawns test process and returns the process Pid; sends {done,
%% Reference, Pid} to caller when finished. See the function
@@ -44,12 +43,13 @@
%% The `Super' process receives a stream of status messages; see
%% message_super/3 for details.
-start(Tests, Order, Super, Reference)
+start(Tests, Order, Super, Reference, Options)
when is_pid(Super), is_reference(Reference) ->
St = #procstate{ref = Reference,
id = [],
super = Super,
- order = Order},
+ order = Order,
+ options = Options},
spawn_group(local, #group{tests = Tests}, St).
%% Fetches the output captured by the eunit group leader. This is
@@ -436,7 +436,7 @@ wait_for_tasks(PidSet, St) ->
%% TODO: Flow control, starting new job as soon as slot is available
tests(T, St) ->
- I = eunit_data:iter_init(T, St#procstate.id),
+ I = eunit_data:iter_init(T, St#procstate.id, St#procstate.options),
case St#procstate.order of
inorder -> tests_inorder(I, St);
inparallel -> tests_inparallel(I, 0, St);
diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl
index e46394d88c..6fb44e0170 100644
--- a/lib/eunit/src/eunit_server.erl
+++ b/lib/eunit/src/eunit_server.erl
@@ -243,7 +243,8 @@ start_job(Job, From, Reference, St) ->
From ! {start, Reference},
%% The default is to run tests in order unless otherwise specified
Order = proplists:get_value(order, Job#job.options, inorder),
- eunit_proc:start(Job#job.test, Order, Job#job.super, Reference),
+ eunit_proc:start(Job#job.test, Order, Job#job.super, Reference,
+ Job#job.options),
St#state{jobs = dict:store(Reference, From, St#state.jobs)}.
handle_done(Reference, St) ->
diff --git a/lib/eunit/test/Makefile b/lib/eunit/test/Makefile
index 0889f31b54..a5b1b719ad 100644
--- a/lib/eunit/test/Makefile
+++ b/lib/eunit/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES = \
+ eunit_test_listener \
eunit_SUITE \
tc0 \
tlatin \
@@ -45,6 +46,7 @@ RELSYSDIR = $(RELEASE_PATH)/eunit_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -57,7 +59,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
$(MODULES) > $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/eunit/test/eunit_SUITE.erl b/lib/eunit/test/eunit_SUITE.erl
index b637b5f314..33bf090eeb 100644
--- a/lib/eunit/test/eunit_SUITE.erl
+++ b/lib/eunit/test/eunit_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,19 +19,24 @@
%%
-module(eunit_SUITE).
--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,appup_test/1,eunit_test/1,surefire_utf8_test/1,surefire_latin_test/1,
- surefire_c0_test/1, surefire_ensure_dir_test/1,
+-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, appup_test/1, eunit_test/1, eunit_exact_test/1,
+ fixture_test/1, primitive_test/1, surefire_utf8_test/1,
+ surefire_latin_test/1, surefire_c0_test/1, surefire_ensure_dir_test/1,
stacktrace_at_timeout_test/1]).
+-export([sample_gen/0]).
+
-include_lib("common_test/include/ct.hrl").
+-define(TIMEOUT, 1000).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [app_test, appup_test, eunit_test, surefire_utf8_test, surefire_latin_test,
- surefire_c0_test, surefire_ensure_dir_test, stacktrace_at_timeout_test].
+ [app_test, appup_test, eunit_test, eunit_exact_test, primitive_test,
+ fixture_test, surefire_utf8_test, surefire_latin_test, surefire_c0_test,
+ surefire_ensure_dir_test, stacktrace_at_timeout_test].
groups() ->
[].
@@ -58,6 +63,100 @@ eunit_test(Config) when is_list(Config) ->
ok = file:set_cwd(code:lib_dir(eunit)),
ok = eunit:test(eunit).
+eunit_exact_test(Config) when is_list(Config) ->
+ ok = file:set_cwd(code:lib_dir(eunit)),
+ {ok, fib} = compile:file("./examples/fib.erl", [{outdir,"./examples/"}]),
+ TestPrimitive =
+ fun(Primitive, Expected) ->
+ ok = eunit:test(Primitive,
+ [{report, {eunit_test_listener, [self()]}},
+ {exact_execution, true}]),
+ check_test_results(Primitive, Expected)
+ end,
+ Primitives =
+ [
+ {[eunit, eunit_tests],
+ #{pass => 7, fail => 0, skip => 0, cancel => 0}},
+ {{application, stdlib},
+ #{pass => 0, fail => 0, skip => 0, cancel => 0}},
+ {{file, "./ebin/eunit.beam"},
+ #{pass => 0, fail => 0, skip => 0, cancel => 0}},
+ {{file, "./ebin/eunit_tests.beam"},
+ #{pass => 7, fail => 0, skip => 0, cancel => 0}},
+ {{dir, "./examples/"},
+ #{pass => 8, fail => 0, skip => 0, cancel => 0}},
+ {{generator, fun() -> fun () -> ok end end},
+ #{pass => 1, fail => 0, skip => 0, cancel => 0}},
+ {{generator, ?MODULE, sample_gen},
+ #{pass => 1, fail => 0, skip => 0, cancel => 0}},
+ {{with, value, [fun(_V) -> ok end]},
+ #{pass => 1, fail => 0, skip => 0, cancel => 0}}
+ ],
+ [TestPrimitive(P, E) || {P, E} <- Primitives],
+ ok.
+
+
+primitive_test(Config) when is_list(Config) ->
+ ok = file:set_cwd(code:lib_dir(eunit)),
+ {ok, fib} = compile:file("./examples/fib.erl", [{outdir,"./examples/"}]),
+ TestPrimitive =
+ fun(Primitive, Expected) ->
+ ok = eunit:test(Primitive,
+ [{report, {eunit_test_listener, [self()]}}]),
+ check_test_results(Primitive, Expected),
+ ok = eunit:test(Primitive,
+ [{report, {eunit_test_listener, [self()]}},
+ {exact_execution, false}]),
+ check_test_results(Primitive, Expected)
+ end,
+ Primitives =
+ [
+ {[eunit, eunit_tests],
+ #{pass => 14, fail => 0, skip => 0, cancel => 0}},
+ {{application, stdlib},
+ #{pass => 0, fail => 0, skip => 0, cancel => 0}},
+ {{file, "./ebin/eunit.beam"},
+ #{pass => 7, fail => 0, skip => 0, cancel => 0}},
+ {{file, "./ebin/eunit_tests.beam"},
+ #{pass => 7, fail => 0, skip => 0, cancel => 0}},
+ {{dir, "./examples/"},
+ #{pass => 8, fail => 0, skip => 0, cancel => 0}},
+ {{generator, fun() -> fun () -> ok end end},
+ #{pass => 1, fail => 0, skip => 0, cancel => 0}},
+ {{generator, ?MODULE, sample_gen},
+ #{pass => 1, fail => 0, skip => 0, cancel => 0}},
+ {{with, value, [fun(_V) -> ok end]},
+ #{pass => 1, fail => 0, skip => 0, cancel => 0}}
+ ],
+ [TestPrimitive(P, E) || {P, E} <- Primitives],
+ ok.
+
+sample_gen() ->
+ fun () -> ok end.
+
+fixture_test(Config) when is_list(Config) ->
+ eunit:test({setup, fun() -> ok end, fun() -> fun() -> ok end end}),
+ eunit:test({setup, fun() -> ok end, [{module, eunit_tests}]}),
+ eunit:test({foreach, fun() -> ok end, [fun() -> ok end]}),
+ eunit:test({foreachx, fun(_A) -> ok end,
+ [{1, fun(_A, _B) -> fun() -> a_test end end}]}),
+ ok.
+
+check_test_results(Primitive, Expected) ->
+ receive
+ {test_report, TestReport} ->
+ case Expected == TestReport of
+ true ->
+ ok;
+ _ ->
+ ct:pal("~p Expected: ~w Received: ~w",
+ [Primitive, Expected, TestReport]),
+ ct:fail(unexpected_result)
+ end
+ after ?TIMEOUT ->
+ ct:fail(no_test_report_not_received)
+ end.
+
surefire_latin_test(Config) when is_list(Config) ->
ok = file:set_cwd(proplists:get_value(priv_dir, Config, ".")),
check_surefire(tlatin),
diff --git a/lib/eunit/test/eunit_test_listener.erl b/lib/eunit/test/eunit_test_listener.erl
new file mode 100644
index 0000000000..95894a02ff
--- /dev/null
+++ b/lib/eunit/test/eunit_test_listener.erl
@@ -0,0 +1,85 @@
+%% Licensed under the Apache License, Version 2.0 (the "License"); you may
+%% not use this file except in compliance with the License. You may obtain
+%% a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% Alternatively, you may use this file under the terms of the GNU Lesser
+%% General Public License (the "LGPL") as published by the Free Software
+%% Foundation; either version 2.1, or (at your option) any later version.
+%% If you wish to allow use of your version of this file only under the
+%% terms of the LGPL, you should delete the provisions above and replace
+%% them with the notice and other provisions required by the LGPL; see
+%% <http://www.gnu.org/licenses/>. If you do not delete the provisions
+%% above, a recipient may use your version of this file under the terms of
+%% either the Apache License or the LGPL.
+%%
+%% @author The OTP team at Ericsson
+%% @copyright Ericsson AB 2022
+%% @private
+%% @see eunit
+%% @doc Module for receiving EUnit events for verification purposes
+
+-module(eunit_test_listener).
+-behaviour(eunit_listener).
+
+-export([start/0, start/1]).
+-export([init/1, handle_begin/3, handle_end/3, handle_cancel/3,
+ terminate/2]).
+
+-record(state, {test_process = undefined}).
+
+start() ->
+ start([]).
+
+start(Options) ->
+ eunit_listener:start(?MODULE, Options).
+
+init(Options) ->
+ [TestProcess] = Options,
+ receive
+ {start, _Reference} ->
+ #state{test_process = TestProcess}
+ end.
+
+terminate({ok, Data}, #state{test_process = TestProcess}) ->
+ Pass = proplists:get_value(pass, Data, 0),
+ Fail = proplists:get_value(fail, Data, 0),
+ Skip = proplists:get_value(skip, Data, 0),
+ Cancel = proplists:get_value(cancel, Data, 0),
+ TestProcess ! {test_report,
+ #{pass => Pass, fail => Fail, skip => Skip,
+ cancel => Cancel}},
+ if Fail =:= 0, Skip =:= 0, Cancel =:= 0 ->
+ sync_end(ok);
+ true ->
+ sync_end(error)
+ end;
+terminate({error, _Reason}, #state{}) ->
+ sync_end(error).
+
+sync_end(Result) ->
+ receive
+ {stop, Reference, ReplyTo} ->
+ ReplyTo ! {result, Reference, Result},
+ ok
+ end.
+
+handle_begin(group, _Data, St) ->
+ St;
+handle_begin(test, _Data, St) ->
+ St.
+
+handle_end(group, _Data, St) ->
+ St;
+handle_end(test, _Data, St) ->
+ St.
+
+handle_cancel(group, _Data, St) ->
+ St;
+handle_cancel(test, _Data, St) ->
+ St.
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index 7528a7d57d..81508f8ab4 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.7
+EUNIT_VSN = 2.8.2
diff --git a/lib/ftp/doc/src/notes.xml b/lib/ftp/doc/src/notes.xml
index 0a6b9ad6a7..b131eee82b 100644
--- a/lib/ftp/doc/src/notes.xml
+++ b/lib/ftp/doc/src/notes.xml
@@ -33,7 +33,73 @@
<file>notes.xml</file>
</header>
- <section><title>Ftp 1.1.1</title>
+ <section><title>Ftp 1.1.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ftp 1.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixes calls to <c>ftp:nlist/2</c> returning <c>{error,
+ epath}</c> when the file / folder exists</p>
+ <p>
+ Own Id: OTP-18409 Aux Id: PR-6721,ERIERL-908 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ftp 1.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ fix unexpected result <c>ok</c> when calling
+ <c>ftp:nlist</c> repeatedly</p>
+ <p>
+ Own Id: OTP-18252 Aux Id: GH-5823 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ftp 1.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ftp/src/Makefile b/lib/ftp/src/Makefile
index 93e3c4a8e5..7f18498b13 100644
--- a/lib/ftp/src/Makefile
+++ b/lib/ftp/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2018. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@ ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(BEHAVIOUR_TARGET_FILES)
diff --git a/lib/ftp/src/ftp.erl b/lib/ftp/src/ftp.erl
index 60bcc85794..07bc5184e2 100644
--- a/lib/ftp/src/ftp.erl
+++ b/lib/ftp/src/ftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1255,7 +1255,7 @@ handle_cast({Pid, close}, State) ->
error_logger:info_report(Report),
{noreply, State};
-%% Catch all - This can oly happen if the application programmer writes
+%% Catch all - This can only happen if the application programmer writes
%% really bad code that violates the API.
handle_cast(Msg, State) ->
{stop, {'API_violation_connection_closed', Msg}, State}.
@@ -1549,6 +1549,12 @@ start_link(Opts, GenServerOptions) ->
%%% Help functions to handle_call and/or handle_ctrl_result
%%--------------------------------------------------------------------------
%% User handling
+-spec handle_user(User, Password, Account, State) -> Result when
+ User :: io:format(),
+ Password :: io:format(),
+ Account :: io:format(),
+ State :: #state{},
+ Result :: {noreply, #state{}}.
handle_user(User, Password, Acc, State0) ->
_ = send_ctrl_message(State0, mk_cmd("USER ~s", [User])),
State = activate_ctrl_connection(State0),
@@ -1568,6 +1574,31 @@ handle_user_account(Acc, State0) ->
%%--------------------------------------------------------------------------
%% handle_ctrl_result
%%--------------------------------------------------------------------------
+-type ctrl_status_operation() :: efnamena
+ | elogin
+ | enofile
+ | epath
+ | error
+ | etnospc
+ | epnospc
+ | efnamena
+ | econn
+ | perm_neg_compl
+ | pos_compl
+ | pos_interm
+ | pos_interm_acct
+ | pos_prel
+ | tls_upgrade
+ | trans_neg_compl.
+
+-spec handle_ctrl_result(Operation, State) -> Result when
+ Operation :: {ctrl_status_operation(), list() | atom()},
+ State :: #state{},
+ Result :: {noreply, #state{}, integer()}
+ | {noreply, #state{}}
+ | {stop, normal | {error, Reason}, #state{}}
+ | {error, term()},
+ Reason :: term().
handle_ctrl_result({pos_compl, _}, #state{csock = {tcp, _Socket},
tls_options = TLSOptions,
timeout = Timeout,
@@ -1753,76 +1784,27 @@ handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State0) ->
ctrl_result_response(error, State0, Error)
end;
-handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir,
- Data}, client = From}
- = State) ->
- case Dir of
- "" -> % Current directory
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined,
- caller = undefined}};
- _ ->
- %% <WTF>
- %% Dir cannot be assumed to be a dir. It is a string that
- %% could be a dir, but could also be a file or even a string
- %% containing wildcards (*).
- %%
- %% %% If there is only one line it might be a directory with one
- %% %% file but it might be an error message that the directory
- %% %% was not found. So in this case we have to endure a little
- %% %% overhead to be able to give a good return value. Alas not
- %% %% all ftp implementations behave the same and returning
- %% %% an error string is allowed by the FTP RFC.
- %% case lists:dropwhile(fun(?CR) -> false;(_) -> true end,
- %% binary_to_list(Data)) of
- %% L when (L =:= [?CR, ?LF]) orelse (L =:= []) ->
- %% send_ctrl_message(State, mk_cmd("PWD", [])),
- %% activate_ctrl_connection(State),
- %% {noreply,
- %% State#state{caller = {handle_dir_data, Dir, Data}}};
- %% _ ->
- %% gen_server:reply(From, {ok, Data}),
- %% {noreply, State#state{client = undefined,
- %% caller = undefined}}
- %% end
- %% </WTF>
- gen_server:reply(From, {ok, Data}),
- {noreply, State#state{client = undefined,
- caller = undefined}}
- end;
+handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, ""=_CurrentDir,
+ Data}, client = From}= State) ->
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined,
+ caller = undefined}};
-handle_ctrl_result({pos_compl, Lines},
- #state{caller = {handle_dir_data, Dir, DirData}} =
- State0) ->
- OldDir = pwd_result(Lines),
- _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [Dir])),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}}};
-handle_ctrl_result({Status, _},
- #state{caller = {handle_dir_data, _, _}} = State) ->
- ctrl_result_response(Status, State, {error, epath});
+handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, _Dir,
+ Data}, client = From}= State) ->
+ gen_server:reply(From, {ok, Data}),
+ {noreply, State#state{client = undefined,
+ caller = undefined}};
+
+handle_ctrl_result({pos_compl, _}=Operation, #state{caller = {handle_dir_result, Dir},
+ data = Data}= State) ->
+ handle_ctrl_result(Operation, State#state{caller = {handle_dir_result, Dir, Data}});
handle_ctrl_result(S={_Status, _},
#state{caller = {handle_dir_result, _, _}} = State) ->
%% OTP-5731, macosx
ctrl_result_response(S, State, {error, epath});
-handle_ctrl_result({pos_compl, _},
- #state{caller = {handle_dir_data_second_phase, OldDir,
- DirData}} = State0) ->
- _ = send_ctrl_message(State0, mk_cmd("CWD ~s", [OldDir])),
- State = activate_ctrl_connection(State0),
- {noreply, State#state{caller = {handle_dir_data_third_phase, DirData}}};
-handle_ctrl_result({Status, _},
- #state{caller = {handle_dir_data_second_phase, _, _}}
- = State) ->
- ctrl_result_response(Status, State, {error, epath});
-handle_ctrl_result(_, #state{caller = {handle_dir_data_third_phase, DirData},
- client = From} = State) ->
- gen_server:reply(From, {ok, DirData}),
- {noreply, State#state{client = undefined, caller = undefined}};
-
handle_ctrl_result({Status, _}, #state{caller = cd} = State) ->
ctrl_result_response(Status, State, {error, Status});
@@ -1959,6 +1941,13 @@ handle_ctrl_result(CtrlMsg, #state{caller = undefined} = State) ->
%%--------------------------------------------------------------------------
%% Help functions to handle_ctrl_result
%%--------------------------------------------------------------------------
+
+-spec ctrl_result_response(Status, State, Error) -> Result when
+ Status :: ctrl_status_operation() | {ctrl_status_operation(), _},
+ State :: #state{},
+ Error :: {error, Reason},
+ Reason :: term(),
+ Result :: {noreply, #state{}} | Error.
ctrl_result_response(pos_compl, #state{client = From} = State, _) ->
gen_server:reply(From, ok),
{noreply, State#state{client = undefined, caller = undefined}};
@@ -1990,6 +1979,9 @@ ctrl_result_response(_, #state{client = From} = State, ErrorMsg) ->
{noreply, State#state{client = undefined, caller = undefined}}.
%%--------------------------------------------------------------------------
+-spec handle_caller(State) -> Result when
+ State :: #state{},
+ Result :: {noreply, #state{}}.
handle_caller(#state{caller = {dir, Dir, Len}} = State0) ->
Cmd = case Len of
short -> "NLST";
@@ -2043,6 +2035,13 @@ handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
%% Connect to FTP server at Host (default is TCP port 21)
%% in order to establish a control connection.
+-spec setup_ctrl_connection(Host, Port, Timeout, State) -> Result when
+ Host :: inet:socket_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ Timeout :: timeout(),
+ State :: #state{},
+ Reason :: timeout | inet:posix(),
+ Result :: {ok, State, integer()} | {error, Reason}.
setup_ctrl_connection(Host, Port, Timeout, #state{sockopts_ctrl = SockOpts} = State0) ->
MsTime = erlang:monotonic_time(),
case connect(Host, Port, SockOpts, Timeout, State0) of
@@ -2060,6 +2059,9 @@ setup_ctrl_connection(Host, Port, Timeout, #state{sockopts_ctrl = SockOpts} = St
Error
end.
+-spec setup_data_connection(State) -> Result when
+ State :: #state{},
+ Result :: {noreply, State}.
setup_data_connection(#state{mode = active,
caller = Caller,
csock = CSock,
@@ -2122,6 +2124,14 @@ setup_data_connection(#state{mode = passive, ipfamily = inet,
State = activate_ctrl_connection(State0),
{noreply, State#state{caller = {setup_data_connection, Caller}}}.
+-spec connect(Host, Port, SockOpts, Timeout, State) -> Result when
+ Host :: inet:socket_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ SockOpts :: [inet:inet_backend() | gen_tcp:connect_option()],
+ Timeout :: timeout(),
+ State :: #state{},
+ Reason :: timeout | inet:posix(),
+ Result :: {ok, inet:address_family(), gen_tcp:socket()} | {error, Reason}.
connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet = IpFam}) ->
connect2(Host, Port, IpFam, SockOpts, Timeout);
@@ -2155,6 +2165,14 @@ connect(Host, Port, SockOpts, Timeout, #state{ipfamily = inet6fb4}) ->
end
end.
+-spec connect2(Host, Port, IpFam, SockOpts, Timeout) -> Result when
+ Host :: inet:socket_address() | inet:hostname(),
+ Port :: inet:port_number(),
+ SockOpts :: [inet:inet_backend() | gen_tcp:connect_option()],
+ Timeout :: timeout(),
+ IpFam :: inet:address_family(),
+ Reason :: timeout | inet:posix(),
+ Result :: {ok, inet:address_family(), gen_tcp:socket()} | {error, Reason}.
connect2(Host, Port, IpFam, SockOpts, Timeout) ->
Opts = [IpFam, binary, {packet, 0}, {active, false} | SockOpts],
case gen_tcp:connect(Host, Port, Opts, Timeout) of
@@ -2164,6 +2182,9 @@ connect2(Host, Port, IpFam, SockOpts, Timeout) ->
Error
end.
+-spec accept_data_connection_tls_options(State) -> Result when
+ State :: #state{},
+ Result :: [tuple()].
accept_data_connection_tls_options(#state{ csock = {ssl,Socket}, tls_options = TO0, tls_ctrl_session_reuse = true }) ->
TO = lists:keydelete(reuse_sessions, 1, TO0),
{ok, [{session_id,SSLSessionId},{session_data,SSLSessionData}]} = ssl:connection_information(Socket, [session_id, session_data]),
@@ -2171,6 +2192,10 @@ accept_data_connection_tls_options(#state{ csock = {ssl,Socket}, tls_options = T
accept_data_connection_tls_options(#state{ tls_options = TO }) ->
TO.
+-spec accept_data_connection(State) -> Result when
+ State :: #state{},
+ Result :: {ok, #state{}} | {error, Reason},
+ Reason :: term().
accept_data_connection(#state{mode = active,
dtimeout = DTimeout,
tls_options = TLSOptions0,
@@ -2208,7 +2233,9 @@ accept_data_connection(#state{mode = passive,
accept_data_connection(#state{mode = passive} = State) ->
{ok,State}.
-
+-spec send_ctrl_message(State, Message) -> _ when
+ State :: #state{},
+ Message :: [term() | Message].
send_ctrl_message(_S=#state{csock = Socket, verbose = Verbose}, Message) ->
verbose(lists:flatten(Message),Verbose,send),
?DBG('<--ctrl ~p ---- ~s~p~n',[Socket,Message,_S]),
@@ -2260,7 +2287,7 @@ activate_connection(API, CloseTag, Socket0) ->
case API:setopts(Socket, [{active, once}]) of
ok ->
ok;
- {error, _} -> %% inet can retrun einval instead of closed
+ {error, _} -> %% inet can return einval instead of closed
self() ! {CloseTag, Socket}
end.
@@ -2311,8 +2338,8 @@ file_close(Fd) ->
file_read(Fd) ->
case file:read(Fd, ?FILE_BUFSIZE) of
- {ok, Bytes} ->
- {ok, size(Bytes), Bytes};
+ {ok, Bytes} when is_binary(Bytes) ->
+ {ok, byte_size(Bytes), Bytes};
eof ->
{ok, 0, []};
Other ->
@@ -2399,8 +2426,8 @@ progress_report(_, #state{progress = ignore}) ->
ok;
progress_report(stop, #state{progress = ProgressPid}) ->
ftp_progress:stop(ProgressPid);
-progress_report({binary, Data}, #state{progress = ProgressPid}) ->
- ftp_progress:report(ProgressPid, {transfer_size, size(Data)});
+progress_report({binary, Data}, #state{progress = ProgressPid}) when is_binary(Data) ->
+ ftp_progress:report(ProgressPid, {transfer_size, byte_size(Data)});
progress_report(Report, #state{progress = ProgressPid}) ->
ftp_progress:report(ProgressPid, Report).
@@ -2481,6 +2508,7 @@ start_options(Options) ->
%% progress
%% ftp_extension
+-spec open_options([tuple()]) -> {ok, [tuple()]} | no_return().
open_options(Options) ->
ValidateMode =
fun(active) -> true;
@@ -2490,8 +2518,7 @@ open_options(Options) ->
ValidateHost =
fun(Host) when is_list(Host) ->
true;
- (Host) when is_tuple(Host) andalso
- ((size(Host) =:= 4) orelse (size(Host) =:= 8)) ->
+ (Host) when tuple_size(Host) =:= 4; tuple_size(Host) =:= 8 ->
true;
(_) ->
false
@@ -2557,6 +2584,8 @@ open_options(Options) ->
{ftp_extension, ValidateFtpExtension, false, ?FTP_EXT_DEFAULT}],
validate_options(Options, ValidOptions, []).
+%% validates socket options and set defaults
+-spec socket_options([tuple()]) -> {ok, tuple()} | no_return().
socket_options(Options) ->
CtrlOpts = proplists:get_value(sock_ctrl, Options, []),
DataActOpts = proplists:get_value(sock_data_act, Options, CtrlOpts),
@@ -2583,6 +2612,11 @@ valid_socket_option({packet_size,_} ) -> false;
valid_socket_option(_) -> true.
+-spec validate_options(Options, ValidOptions, Acc) -> Result when
+ Options :: [tuple()],
+ ValidOptions :: [tuple()],
+ Acc :: [tuple()],
+ Result :: {ok, [tuple()]} | no_return().
validate_options([], [], Acc) ->
{ok, lists:reverse(Acc)};
validate_options([], ValidOptions, Acc) ->
diff --git a/lib/ftp/src/ftp_progress.erl b/lib/ftp/src/ftp_progress.erl
index 64c612519d..c3940140a1 100644
--- a/lib/ftp/src/ftp_progress.erl
+++ b/lib/ftp/src/ftp_progress.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,8 +18,8 @@
%% %CopyrightEnd%
%%
%%
-%% Description: This module impements a temporary process that
-%% performes progress reporting during file transfer calling a user
+%% Description: This module implements a temporary process that
+%% performs progress reporting during file transfer calling a user
%% defined callback function. Its life span is as long as the ftp connection
%% processes that spawned it lives. The purpose of this process is to
%% shild the ftp connection process from errors and time consuming operations
diff --git a/lib/ftp/src/ftp_response.erl b/lib/ftp/src/ftp_response.erl
index 8d00153ba8..053b6893f8 100644
--- a/lib/ftp/src/ftp_response.erl
+++ b/lib/ftp/src/ftp_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
%%
-%% Description: This module impements handling of ftp server responses.
+%% Description: This module implements handling of ftp server responses.
-module(ftp_response).
@@ -50,7 +50,7 @@
%% {continue, {Data,
%% AccLines, StatusCode}}
%%
-%% Data = binary() - data recived on the control connection from the
+%% Data = binary() - data received on the control connection from the
%% ftp-server.
%% AccLines = [string()]
%% StatusCode = start | {byte(), byte(), byte()} | finish -
@@ -80,7 +80,7 @@
%% Make sure we received the first 4 bytes so we know how to parse
%% the FTP server response e.i. is the response composed of one
%% or multiple lines.
-parse_lines(Bin, Lines, start) when size(Bin) < 4 ->
+parse_lines(Bin, Lines, start) when is_binary(Bin), byte_size(Bin) < 4 ->
{continue, {Bin, Lines, start}};
%% Multiple lines exist
parse_lines(<<C1, C2, C3, $-, Rest/binary>>, Lines, start) ->
@@ -95,7 +95,7 @@ parse_lines(<<?CR, ?LF, C1, C2, C3, ?WHITE_SPACE, Rest/binary>>, Lines, {C1, C2,
%% Potential end found wait for more data
parse_lines(<<?CR, ?LF, C1, C2, C3>> = Bin, Lines, {C1, C2, C3}) ->
{continue, {Bin, Lines, {C1, C2, C3}}};
-%% Intermidate line begining with status code
+%% Intermidate line beginning with status code
parse_lines(<<?CR, ?LF, C1, C2, C3, Rest/binary>>, Lines, {C1, C2, C3}) ->
parse_lines(Rest, [C3, C2, C1, ?LF, ?CR | Lines], {C1, C2, C3});
@@ -184,7 +184,7 @@ interpret_status(?POS_PREL,_,_) -> pos_prel;
interpret_status(?POS_COMPL, ?AUTH_ACC, 4) -> tls_upgrade;
%% Positive Completion Reply
interpret_status(?POS_COMPL,_,_) -> pos_compl;
-%% Positive Intermediate Reply nedd account
+%% Positive Intermediate Reply need account
interpret_status(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct;
%% Positive Intermediate Reply
interpret_status(?POS_INTERM,_,_) -> pos_interm;
diff --git a/lib/ftp/test/Makefile b/lib/ftp/test/Makefile
index f649daf4d1..4686d8f1bd 100644
--- a/lib/ftp/test/Makefile
+++ b/lib/ftp/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -98,7 +98,6 @@ FTP_FLAGS += -pa ../ftp/ebin
FTP_ROOT = ../ftp
MODULES = \
- erl_make_certs \
ftp_SUITE \
ftp_format_SUITE \
ftp_test_lib
@@ -153,6 +152,7 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
ERL_COMPILE_FLAGS += \
$(INCLUDES) \
$(FTP_FLAGS)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
@@ -162,7 +162,7 @@ ERL_COMPILE_FLAGS += \
# 1) FTP_PRIV_DIR must be created
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
diff --git a/lib/ftp/test/erl_make_certs.erl b/lib/ftp/test/erl_make_certs.erl
deleted file mode 100644
index 2af2d8c3e9..0000000000
--- a/lib/ftp/test/erl_make_certs.erl
+++ /dev/null
@@ -1,474 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%% Create test certificates
-
--module(erl_make_certs).
--include_lib("public_key/include/public_key.hrl").
-
--export([make_cert/1, gen_rsa/1, gen_dsa/2, gen_ec/1, verify_signature/3, write_pem/3]).
-
-%%--------------------------------------------------------------------
-%% @doc 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|ec Subject PublicKey rsa, dsa or ec generates key
-%%
-%%
-%% (OBS: The generated keys are for testing only)
-%% @spec ([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
-%% @end
-%%--------------------------------------------------------------------
-
-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)}.
-
-%%--------------------------------------------------------------------
-%% @doc Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem"
-%% @spec (::string(), ::string(), {Cert,Key}) -> ok
-%% @end
-%%--------------------------------------------------------------------
-write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
- [{'Certificate', Cert, not_encrypted}]),
- ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
-
-%%--------------------------------------------------------------------
-%% @doc Creates a rsa key (OBS: for testing only)
-%% the size are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_rsa(Size) when is_integer(Size) ->
- Key = gen_rsa2(Size),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Creates a dsa key (OBS: for testing only)
-%% the sizes are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
- Key = gen_dsa2(LSize, NSize),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Creates a ec key (OBS: for testing only)
-%% the sizes are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_ec(Curve) when is_atom(Curve) ->
- Key = gen_ec2(Curve),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Verifies cert signatures
-%% @spec (::binary(), ::tuple()) -> ::boolean()
-%% @end
-%%--------------------------------------------------------------------
-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}});
- #'ECPrivateKey'{version = _Version, privateKey = _PrivKey,
- parameters = Params, publicKey = {0, PubKey}} ->
- public_key:pkix_verify(DerEncodedCert, {#'ECPoint'{point = PubKey}, Params})
- 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);
- ec -> make_key(ec, Opts);
- Key ->
- Password = proplists:get_value(password, Opts, no_passwd),
- decode_key(Key, Password)
- end.
-
-decode_key({Key, Pw}) ->
- decode_key(Key, Pw);
-decode_key(Key) ->
- decode_key(Key, no_passwd).
-
-
-decode_key(#'RSAPublicKey'{} = Key,_) ->
- Key;
-decode_key(#'RSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'DSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'ECPrivateKey'{} = 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', Der, not_encrypted};
-encode_key(Key = #'DSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', Der, not_encrypted};
-encode_key(Key = #'ECPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('ECPrivateKey', Key),
- {'ECPrivateKey', 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(rand: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", "test_user") end,
- Opts = [{email, User ++ "@erlang.org"},
- {name, User},
- {city, "Stockholm"},
- {country, "SE"},
- {org, "erlang"},
- {org_unit, "testing dep"}],
- subject(Opts);
-subject(Opts, _) ->
- subject(Opts).
-
-subject(SubjectOpts) when is_list(SubjectOpts) ->
- Encode = fun(Opt) ->
- {Type,Value} = subject_enc(Opt),
- [#'AttributeTypeAndValue'{type=Type, value=Value}]
- end,
- {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
-
-%% Fill in the blanks
-subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
-subject_enc({email, Email}) -> {?'id-emailAddress', Email};
-subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
-subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
-subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
-subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
-subject_enc({country, Country}) -> {?'id-at-countryName', Country};
-subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
-subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
-subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
-subject_enc(Other) -> Other.
-
-
-extensions(Opts) ->
- case proplists:get_value(extensions, Opts, []) of
- false ->
- asn1_NOVALUE;
- Exts ->
- lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
- end.
-
-default_extensions(Exts) ->
- Def = [{key_usage,undefined},
- {subject_altname, undefined},
- {issuer_altname, undefined},
- {basic_constraints, default},
- {name_constraints, undefined},
- {policy_constraints, undefined},
- {ext_key_usage, undefined},
- {inhibit_any, undefined},
- {auth_key_id, undefined},
- {subject_key_id, undefined},
- {policy_mapping, undefined}],
- Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
- Exts ++ lists:foldl(Filter, Def, Exts).
-
-extension({_, undefined}) -> [];
-extension({basic_constraints, Data}) ->
- case Data of
- default ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true},
- critical=true};
- false ->
- [];
- Len when is_integer(Len) ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
- critical=true};
- _ ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = Data}
- end;
-extension({Id, Data, Critical}) ->
- #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
-
-
-publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
- Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
- Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = Public};
-publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y};
-publickey(#'ECPrivateKey'{version = _Version,
- privateKey = _PrivKey,
- parameters = Params,
- publicKey = {0, PubKey}}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = #'ECPoint'{point = PubKey}}.
-
-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}}};
-sign_algorithm(#'ECPrivateKey'{}, Opts) ->
- Type = case proplists:get_value(digest, Opts, sha1) of
- sha1 -> ?'ecdsa-with-SHA1';
- sha512 -> ?'ecdsa-with-SHA512';
- sha384 -> ?'ecdsa-with-SHA384';
- sha256 -> ?'ecdsa-with-SHA256'
- end,
- {Type, 'NULL'}.
-
-make_key(rsa, _Opts) ->
- %% (OBS: for testing only)
- gen_rsa2(64);
-make_key(dsa, _Opts) ->
- gen_dsa2(128, 20); %% Bytes i.e. {1024, 160}
-make_key(ec, _Opts) ->
- %% (OBS: for testing only)
- gen_ec2(secp256k1).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% 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_pow(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_pow(G, X, P), %% Calculate y = g^x mod p.
-
- #'DSAPrivateKey'{version=0, p = P, q = Q,
- g = crypto:bytes_to_integer(G), y = crypto:bytes_to_integer(Y), x = X}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% EC key generation (OBS: for testing only)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-gen_ec2(CurveId) ->
- {PubKey, PrivKey} = crypto:generate_key(ecdh, CurveId),
-
- #'ECPrivateKey'{version = 1,
- privateKey = binary_to_list(PrivKey),
- parameters = {namedCurve, pubkey_cert_records:namedCurves(CurveId)},
- publicKey = {0, PubKey}}.
-
-%% See fips_186-3.pdf
-dsa_search(T, P0, Q, Iter) when Iter > 0 ->
- P = 2*T*Q*P0 + 1,
- case is_prime(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),
- prime_odd(Rand, 0).
-
-prime_odd(Rand, N) ->
- case is_prime(Rand, 50) of
- true ->
- Rand;
- false ->
- prime_odd(Rand+2, N+1)
- end.
-
-%% see http://en.wikipedia.org/wiki/Fermat_primality_test
-is_prime(_, 0) -> true;
-is_prime(Candidate, Test) ->
- CoPrime = odd_rand(10000, Candidate),
- Result = crypto:mod_pow(CoPrime, Candidate, Candidate) ,
- is_prime(CoPrime, crypto:bytes_to_integer(Result), Candidate, Test).
-
-is_prime(CoPrime, CoPrime, Candidate, Test) ->
- is_prime(Candidate, Test-1);
-is_prime(_,_,_,_) ->
- false.
-
-odd_rand(Size) ->
- Min = 1 bsl (Size*8-1),
- Max = (1 bsl (Size*8))-1,
- odd_rand(Min, Max).
-
-odd_rand(Min,Max) when Min < Max ->
- Rand = Min + rand:uniform(Max - Min - 1),
- case Rand rem 2 of
- 0 ->
- Rand + 1;
- _ ->
- Rand
- end.
-
-extended_gcd(A, B) ->
- case A rem B of
- 0 ->
- {0, 1};
- N ->
- {X, Y} = extended_gcd(B, N),
- {Y, X-Y*(A div B)}
- end.
-
-pem_to_der(File) ->
- {ok, PemBin} = file:read_file(File),
- public_key:pem_decode(PemBin).
-
-der_to_pem(File, Entries) ->
- PemBin = public_key:pem_encode(Entries),
- file:write_file(File, PemBin).
-
diff --git a/lib/ftp/test/ftp_SUITE.erl b/lib/ftp/test/ftp_SUITE.erl
index fb6468b499..961b3b5fe1 100644
--- a/lib/ftp/test/ftp_SUITE.erl
+++ b/lib/ftp/test/ftp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,6 @@
end)(inet:gethostname())
).
--define(BAD_HOST, "badhostname").
-define(BAD_USER, "baduser").
-define(BAD_DIR, "baddirectory").
@@ -498,17 +497,21 @@ ls() ->
"\"test\" directory. We assume that ls never fails, since "
"it's output is meant to be read by humans. "}].
ls(Config0) ->
- Config = set_state([reset,{mkdir,"test"}], Config0),
+ TestFileName = "testing-file",
+ Config = set_state([reset,{mkdir,"test"},{mkfile, TestFileName, TestFileName}], Config0),
Pid = proplists:get_value(ftp, Config),
{ok, _R1} = ftp:ls(Pid),
{ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)),
+ {ok, _R3} = ftp:nlist(Pid, id2ftp(TestFileName, Config)),
+ {ok, []} = ftp:nlist(Pid, id2ftp("non-existing-folder",Config)),
+ {ok, []} = ftp:nlist(Pid, id2ftp("test/non-existing-file",Config)),
%% neither nlist nor ls operates on a directory
%% they operate on a pathname, which *can* be a
%% directory, but can also be a filename or a group
%% of files (including wildcards).
case proplists:get_value(wildcard_support, Config) of
true ->
- {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
+ {ok, _R4} = ftp:ls(Pid, id2ftp("te*",Config));
_ ->
ok
end.
@@ -516,21 +519,25 @@ ls(Config0) ->
%%-------------------------------------------------------------------------
nlist() ->
[{doc,"Open an ftp connection; nlist the current directory, and the "
- "\"test\" directory. Nlist does not behave consistenly over "
+ "\"test\" directory. Nlist does not behave consistently over "
"operating systems. On some it is an error to have an empty "
"directory."}].
nlist(Config0) ->
- Config = set_state([reset,{mkdir,"test"}], Config0),
+ TestFileName = "testing-file",
+ Config = set_state([reset,{mkdir,"test"},{mkfile, TestFileName, TestFileName}], Config0),
Pid = proplists:get_value(ftp, Config),
{ok, _R1} = ftp:nlist(Pid),
{ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)),
+ {ok, _R3} = ftp:nlist(Pid, id2ftp(TestFileName, Config)),
+ {ok, []} = ftp:nlist(Pid, id2ftp("non-existing-folder",Config)),
+ {ok, []} = ftp:nlist(Pid, id2ftp("test/non-existing-file",Config)),
%% neither nlist nor ls operates on a directory
%% they operate on a pathname, which *can* be a
%% directory, but can also be a filename or a group
%% of files (including wildcards).
case proplists:get_value(wildcard_support, Config) of
true ->
- {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
+ {ok, _R4} = ftp:nlist(Pid, id2ftp("te*",Config));
_ ->
ok
end.
@@ -862,7 +869,7 @@ recv_chunk_delay(Config0) when is_list(Config0) ->
delay_recv_chunk(Pid) ->
delay_recv_chunk(Pid, <<>>).
delay_recv_chunk(Pid, Acc) ->
- ct:pal("Received size ~p", [byte_size(Acc)]),
+ ct:log("Received size ~p", [byte_size(Acc)]),
case ftp:recv_chunk(Pid) of
ok ->
{ok, Acc};
@@ -888,7 +895,7 @@ quote(Config) ->
Pid = proplists:get_value(ftp, Config),
["257 \""++_Rest] = ftp:quote(Pid, "pwd"), %% 257
[_| _] = ftp:quote(Pid, "help"),
- %% This negativ test causes some ftp servers to hang. This test
+ %% This negative test causes some ftp servers to hang. This test
%% is not important for the client, so we skip it for now.
%%["425 Can't build data connection: Connection refused."]
%% = ftp:quote(Pid, "list"),
@@ -948,7 +955,7 @@ unexpected_call(Config) when is_list(Config) ->
Flag = process_flag(trap_exit, true),
Pid = proplists:get_value(ftp, Config),
- %% Serious programming fault, connetion will be shut down
+ %% A serious programming fault, the connection will be shut down
case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
{error, {connection_terminated, 'API_violation'}} ->
ok;
@@ -965,7 +972,7 @@ unexpected_cast()->
unexpected_cast(Config) when is_list(Config) ->
Flag = process_flag(trap_exit, true),
Pid = proplists:get_value(ftp, Config),
- %% Serious programming fault, connetion will be shut down
+ %% A serious programming fault, the connection will be shut down
gen_server:cast(Pid, {self(), foobar, 10}),
ct:sleep(500),
undefined = process_info(Pid, status),
@@ -977,7 +984,7 @@ unexpected_bang()->
unexpected_bang(Config) when is_list(Config) ->
Flag = process_flag(trap_exit, true),
Pid = proplists:get_value(ftp, Config),
- %% Could be an innocent misstake the connection lives.
+ %% Could be an innocent mistake the connection lives.
Pid ! foobar,
ct:sleep(500),
{status, _} = process_info(Pid, status),
@@ -1016,7 +1023,7 @@ clean_shutdown(Config) ->
%%-------------------------------------------------------------------------
ftp_worker() ->
[{doc, "Makes sure the ftp worker processes are added and removed "
- "appropriatly to/from the supervison tree."}].
+ "appropriately to/from the supervison tree."}].
ftp_worker(Config) ->
Pid = proplists:get_value(ftp,Config),
case supervisor:which_children(ftp_sup) of
@@ -1217,7 +1224,7 @@ start_ftpd(Config0) ->
ct:log("Ftp server ~p started on ~p:~p but is unusable:~n~p:~p",
[AbsName,Host,Port,Class,Exception]),
catch stop_ftpd(Config),
- {skip, [AbsName," started but unusuable"]}
+ {skip, [AbsName," started but unusable"]}
end;
{error,Msg} ->
{skip, [AbsName," not started: ",Msg]}
@@ -1247,11 +1254,11 @@ ftp_start_service(Config, Options) ->
Host = proplists:get_value(ftpd_host,Config),
Port = proplists:get_value(ftpd_port,Config),
ct:log("Host=~p, Port=~p",[Host,Port]),
- {ok,Pid} = ftp:start_service([{host, Host},{port,Port} | Options]),
+ {ok,Pid} = ftp:open([{host, Host},{port,Port} | Options]),
[{ftp,Pid}|Config].
ftp_stop_service(Config) ->
- ok = ftp:stop_service(proplists:get_value(ftp,Config)),
+ ok = ftp:close(proplists:get_value(ftp,Config)),
Config.
split(Cs) -> string:tokens(Cs, "\r\n").
diff --git a/lib/ftp/test/ftp_SUITE_data/vsftpd.conf b/lib/ftp/test/ftp_SUITE_data/vsftpd.conf
index 51cea2dcd8..7a2bf67805 100644
--- a/lib/ftp/test/ftp_SUITE_data/vsftpd.conf
+++ b/lib/ftp/test/ftp_SUITE_data/vsftpd.conf
@@ -2,7 +2,7 @@
###
### Some parameters are given in the vsftpd start command.
###
-### Typical command-line paramters are such that has a file path
+### Typical command-line parameters are such that has a file path
### component like cert files.
###
diff --git a/lib/ftp/test/ftp_format_SUITE.erl b/lib/ftp/test/ftp_format_SUITE.erl
index e1d0de2390..c5c3c4b06d 100644
--- a/lib/ftp/test/ftp_format_SUITE.erl
+++ b/lib/ftp/test/ftp_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ end_per_testcase(_, _) ->
%%-------------------------------------------------------------------------
ftp_150() ->
- [{doc, "Especially check that respons can be devided in a random place."}].
+ [{doc, "Especially check that a response can be divided in a random place."}].
ftp_150(Config) when is_list(Config) ->
FtpResponse = ["150 ASCII data conn", "ection for /bin/ls ",
"(134.138.177", ".89,50434) (0 bytes).\r\n"],
@@ -75,7 +75,7 @@ ftp_150(Config) when is_list(Config) ->
{pos_prel, _} = ftp_response:interpret(Msg).
ftp_200() ->
- [{doc, "Especially check that respons can be devided after the first status "
+ [{doc, "Especially check that a response can be divided after the first status "
"code character and in the end delimiter."}].
ftp_200(Config) when is_list(Config) ->
FtpResponse = ["2", "00 PORT command successful.", [?CR], [?LF]],
@@ -86,8 +86,8 @@ ftp_200(Config) when is_list(Config) ->
ok.
ftp_220() ->
- [{doc, "Especially check that respons can be devided after the "
- "first with space "}].
+ [{doc, "Especially check that a response can be divided after the "
+ "first white space "}].
ftp_220(Config) when is_list(Config) ->
FtpResponse = ["220 ","fingon FTP server (SunOS 5.8) ready.\r\n"],
@@ -97,7 +97,7 @@ ftp_220(Config) when is_list(Config) ->
ok.
ftp_226() ->
- [{doc, "Especially check that respons can be devided after second status code"
+ [{doc, "Especially check that a response can be divided after second status code"
" character and in the end delimiter."}].
ftp_226(Config) when is_list(Config) ->
FtpResponse = ["22" "6 Transfer complete.\r", [?LF]],
@@ -118,7 +118,7 @@ ftp_257(Config) when is_list(Config) ->
ok.
ftp_331() ->
- [{doc, "Especially check that respons can be devided after the third status "
+ [{doc, "Especially check that a response can be divided after the third status "
" status code character."}].
ftp_331(Config) when is_list(Config) ->
%% Brake before white space after code
@@ -151,7 +151,7 @@ ftp_multiple_lines_status_in_msg(Config) when is_list(Config) ->
ok.
ftp_multiple_lines() ->
- [{doc, "Especially check multiple lines devided in significant places"}].
+ [{doc, "Especially check multiple lines divided in significant places"}].
ftp_multiple_lines(Config) when is_list(Config) ->
FtpResponse = ["21", "4","-The",
" following commands are recognized:\r\n"
@@ -231,9 +231,9 @@ ftp_multiple_lines(Config) when is_list(Config) ->
ftp_other_status_codes() ->
[{doc, "Check that other valid status codes, than the ones above, are handled"
- "by ftp_response:interpret/1. Note there are som ftp status codes"
- "that will not be received with the current ftp instruction support,"
- "they are not included here."}].
+ "by ftp_response:interpret/1. Note that there are some ftp status codes"
+ "that will not be received with the current ftp instruction support."
+ "They are not included here."}].
ftp_other_status_codes(Config) when is_list(Config) ->
%% 1XX
diff --git a/lib/ftp/test/ftp_test_lib.erl b/lib/ftp/test/ftp_test_lib.erl
index f5fbc39037..8ab337b54a 100644
--- a/lib/ftp/test/ftp_test_lib.erl
+++ b/lib/ftp/test/ftp_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,14 +28,15 @@
make_cert_files(Dir) ->
#{server_config := ServerConf,
client_config := _} =
- public_key:pkix_test_data(#{server_chain =>
- #{root => [{key, hardcode_rsa_key(1)}],
- intermediates => [[{key, hardcode_rsa_key(2)}]],
- peer => [{key, hardcode_rsa_key(3)}]},
- client_chain =>
- #{root => [{key, hardcode_rsa_key(1)}],
- intermediates => [[{key, hardcode_rsa_key(3)}]],
- peer => [{key, hardcode_rsa_key(2)}]}}),
+ public_key:pkix_test_data(
+ #{server_chain =>
+ #{root => [{key, hardcode_rsa_key(1)},{digest,appropriate_sha()}],
+ intermediates => [[{key, hardcode_rsa_key(2)},{digest,appropriate_sha()}]],
+ peer => [{key, hardcode_rsa_key(3)},{digest,appropriate_sha()}]},
+ client_chain =>
+ #{root => [{key, hardcode_rsa_key(1)},{digest,appropriate_sha()}],
+ intermediates => [[{key, hardcode_rsa_key(3)},{digest,appropriate_sha()}]],
+ peer => [{key, hardcode_rsa_key(2)},{digest,appropriate_sha()}]}}),
CaCertFile = filename:join(Dir, "server-cacerts.pem"),
CertFile = filename:join(Dir, "server-cert.pem"),
@@ -48,6 +49,20 @@ make_cert_files(Dir) ->
der_to_pem(KeyFile, [key_entry(Key)]),
der_to_pem(CaCertFile, ca_entries(CAs)).
+appropriate_sha() ->
+ Hashes = proplists:get_value(hashs, crypto:supports()),
+ case os:cmd("openssl version") of
+ "OpenSSL 0.9.8" ++ _ ->
+ sha;
+ _ ->
+ case lists:member(sha256, Hashes) of
+ true ->
+ sha256;
+ false ->
+ sha
+ end
+ end.
+
cert_entry(Cert) ->
{'Certificate', Cert, not_encrypted}.
diff --git a/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf b/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf
index fd48e2abf0..dc6d0ff0b3 100644
--- a/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf
+++ b/lib/ftp/test/property_test/ftp_simple_client_server_data/vsftpd.conf
@@ -2,7 +2,7 @@
###
### Some parameters are given in the vsftpd start command.
###
-### Typical command-line paramters are such that has a file path
+### Typical command-line parameters are such that has a file path
### component like cert files.
###
diff --git a/lib/ftp/vsn.mk b/lib/ftp/vsn.mk
index e02ab28682..fa0034ec4b 100644
--- a/lib/ftp/vsn.mk
+++ b/lib/ftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = ftp
-FTP_VSN = 1.1.1
+FTP_VSN = 1.1.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(FTP_VSN)$(PRE_VSN)"
diff --git a/lib/inets/AUTHORS b/lib/inets/AUTHORS
index a0dcc1fe92..8702edd311 100644
--- a/lib/inets/AUTHORS
+++ b/lib/inets/AUTHORS
@@ -14,6 +14,6 @@ Martin Gustafsson
Johan Blom
Torbjörn Törnkvist
Joe Armstrong
-
+Tyler Hughes
diff --git a/lib/inets/doc/specs/.gitignore b/lib/inets/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/inets/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index a81e50afc0..e3c876c5be 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -62,12 +62,27 @@ XML_FILES = \
$(BOOK_FILES) \
$(XML_CHAPTER_FILES) \
$(XML_PART_FILES) \
- $(XML_REF6_FILES) \
$(XML_REF3_FILES) \
$(XML_APPLICATION_FILES)
+SPEC_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+TOP_SPECS_FILE = specs.xml
+
NO_CHUNKS = httpd_custom_api.xml
+# Generate file specs for files with type specs.
+# These are needed because the standard script
+# (otp/make/otp.mk.in) does not traverse folders
+$(SPECDIR)/specs_%.xml: $(SPECS_ESRC)/http_client/%.erl $(TOP_SPECS_FILE)
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) -o$(dir $@) $<
+$(SPECDIR)/specs_%.xml: $(SPECS_ESRC)/inets_app/%.erl $(TOP_SPECS_FILE)
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) -o$(dir $@) $<
+$(SPECDIR)/specs_%.xml: $(SPECS_ESRC)/http_server/%.erl $(TOP_SPECS_FILE)
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) -o$(dir $@) $<
+$(SPECDIR)/specs_%.xml: $(SPECS_ESRC)/http_lib/%.erl $(TOP_SPECS_FILE)
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) -o$(dir $@) $<
+
# ----------------------------------------------------
include $(ERL_TOP)/make/doc.mk
+SPECS_FLAGS += -I../../src/inets_app -I../../include -I../../../kernel/include
diff --git a/lib/inets/doc/src/http_client.xml b/lib/inets/doc/src/http_client.xml
index 0258456966..34868408c6 100644
--- a/lib/inets/doc/src/http_client.xml
+++ b/lib/inets/doc/src/http_client.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -81,27 +81,31 @@
<code type="erl">
4 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
httpc:request("http://www.erlang.org").</code>
+ <p>The following is a https request and with verification of the host:</p>
+ <code type="erl">
+ 5 > {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
+ httpc:request(get, {"https://www.erlang.org", []}, [{ssl, httpc:ssl_verify_host_options(true)}], []).</code>
<p>The following is an ordinary asynchronous request:</p>
<code type="erl">
- 5 > {ok, RequestId} =
+ 6 > {ok, RequestId} =
httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]).</code>
<p>The result is sent to the calling process as
<c>{http, {ReqestId, Result}}</c>.</p>
<p>In this case, the calling process is the shell, so the following
result is received:</p>
<code type="erl">
- 6 > receive {http, {RequestId, Result}} -> ok after 500 -> error end.
+ 7 > receive {http, {RequestId, Result}} -> ok after 500 -> error end.
ok</code>
<p>This sends a request with a specified connection header:</p>
<code type="erl">
- 7 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
+ 8 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]},
[], []).</code>
<p>This sends an HTTP request over a unix domain socket (experimental):</p>
<code type="erl">
- 8 > httpc:set_options([{ipfamily, local},
+ 9 > httpc:set_options([{ipfamily, local},
{unix_socket,"/tmp/unix_socket/consul_http.sock"}]).
- 9 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
+ 10 > {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
httpc:request(put, {"http:///v1/kv/foo", [], [], "hello"}, [], []).</code>
<p>Start an HTTP client profile:</p>
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index eb47a823fb..39b367eb92 100644
--- a/lib/inets/doc/src/http_uri.xml
+++ b/lib/inets/doc/src/http_uri.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2012</year><year>2021</year>
+ <year>2012</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -57,25 +57,10 @@
<tag><c>uri() = string() | binary()</c></tag>
<item><p>Syntax according to the URI definition in RFC 3986,
for example, "http://www.erlang.org/"</p></item>
- <tag><c>user_info() = string() | binary()</c></tag>
- <item><p></p></item>
- <tag><c>scheme() = atom()</c></tag>
- <item><p>Example: http, https</p></item>
- <tag><c>host() = string() | binary()</c></tag>
- <item><p></p></item>
- <tag><c>port() = inet:port_number()</c></tag>
- <item><p></p></item>
- <tag><c>path() = string() | binary()</c></tag>
- <item><p>Represents a file path or directory path</p></item>
- <tag><c>query() = string() | binary()</c></tag>
- <item><p></p></item>
- <tag><c>fragment() = string() | binary()</c></tag>
- <item><p></p></item>
</taglist>
<p>For more information about URI, see
<url href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>.</p>
- <marker id="scheme_defaults"></marker>
</section>
<funcs>
@@ -108,80 +93,6 @@
<marker id="decode"></marker>
</desc>
</func>
-
- <func>
- <name since="OTP R15B01">parse(URI) -> {ok, Result} | {error, Reason}</name>
- <name since="OTP R15B01">parse(URI, Options) -> {ok, Result} | {error, Reason}</name>
- <fsummary>Parses a URI.</fsummary>
- <type>
- <v>URI = uri()</v>
- <v>Options = [Option]</v>
- <v>Option = {ipv6_host_with_brackets, boolean()} |
- {scheme_defaults, scheme_defaults()} |
- {fragment, boolean()} |
- {scheme_validation_fun, fun()}</v>
- <v>Result = {Scheme, UserInfo, Host, Port, Path, Query} |
- {Scheme, UserInfo, Host, Port, Path, Query, Fragment}</v>
- <v>Scheme = scheme()</v>
- <v>UserInfo = user_info()</v>
- <v>Host = host()</v>
- <v>Port = inet:port_number()</v>
- <v>Path = path()</v>
- <v>Query = query()</v>
- <v>Fragment = fragment()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Parses a URI. If no scheme defaults
- are provided, the value of the
- <seeerl marker="#scheme_defaults">scheme_defaults</seeerl>
- function is used.</p>
-
- <p>When parsing a URI with an unknown scheme (that is,
- a scheme not found in the scheme defaults), a port number must be
- provided, otherwise the parsing fails.</p>
-
- <p>If the fragment option is <c>true</c>, the URI fragment is returned as
- part of the parsing result, otherwise it is ignored.</p>
-
- <p>Scheme validation fun is to be defined as follows:</p>
-
- <code>
-fun(SchemeStr :: string() | binary()) ->
- valid | {error, Reason :: term()}.
- </code>
-
- <p>It is called before scheme string gets converted into scheme atom and
- thus possible atom leak could be prevented</p>
-
- <warning>
- <p>The scheme portion of the URI gets converted into atom,
- meaning that atom leak may occur. Specifying a scheme
- validation fun is recommended unless the URI is already
- sanitized.</p>
- </warning>
-
- <marker id="encode"></marker>
- </desc>
- </func>
-
- <func>
- <name since="OTP R15B01">scheme_defaults() -> SchemeDefaults</name>
- <fsummary>A list of the scheme and their default ports.</fsummary>
- <type>
- <v>SchemeDefaults = [{scheme(), default_scheme_port_number()}] </v>
- <v>default_scheme_port_number() = inet:port_number()</v>
- </type>
- <desc>
- <p>Provides a list of the scheme and their default
- port numbers supported (by default) by this utility.</p>
-
- <marker id="parse"></marker>
- </desc>
- </func>
-
-
-
</funcs>
<!--
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index 34010b25e4..0c6437ccec 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>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -60,77 +60,6 @@
<p>Some examples are provided in the <seeguide
marker="http_client">Inets User's Guide</seeguide>.</p>
</description>
-
- <section>
- <title>DATA TYPES</title>
- <marker id="DATA_TYPES"></marker>
- <p>Type definitions that are used more than once in
- this module:</p>
- <p><c>boolean() = true | false</c></p>
- <p><c>http_string()</c> = list of ASCII characters</p>
- <p><c>request_id() = reference()</c></p>
- <p><c>profile() = atom()</c></p>
- <p><c>path() = string()</c> representing a file path or directory path</p>
- <p><c>ip_address()</c> = See the
- <seeerl marker="kernel:inet">inet(3)</seeerl> manual page in Kernel.</p>
- <p><c>socket_opt()</c> = See the options used by
- <seeerl marker="kernel:gen_tcp">gen_tcp(3)</seeerl> <c>gen_tcp(3)</c> and
- <seeerl marker="ssl:ssl">ssl(3)</seeerl> connect(s)</p>
-
- </section>
-
- <section>
- <title>HTTP DATA TYPES</title>
- <p>Type definitions related to HTTP:</p>
-
- <p><c>method() = head | get | put | post | trace | options | delete | patch</c></p>
- <taglist>
- <tag><c>request()</c></tag>
- <item><p>= <c>{url(), headers()}</c></p>
- <p>| <c>{url(), headers(), content_type(), body()}</c></p>
- </item>
- </taglist>
- <p><c>url() = http_string()</c> syntax according to the URI definition in
- <url href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>,
- for example <c>"http://www.erlang.org"</c></p>
- <warning><p>Please note that httpc normalizes input URIs before internal processing
- and special care shall be taken when the URI has percent ("%") characters. A percent
- serves as the indicator for percent-encoded octets and it must be percent-encoded
- as "%25" for that octet to be used as data within the URI.</p>
- <p>For example, in order to send an HTTP GET request with the URI
- <c>http://localhost/foo%25bar</c>, the percent character must be percent-encoded when
- creating the request: <c>httpc:request("http://localhost/foo%2525bar").</c>
- </p></warning>
- <p><c>status_line() = {http_version(), status_code(), reason_phrase()}</c></p>
- <p><c>http_version() = http_string()</c>, for example, <c>"HTTP/1.1"</c></p>
- <p><c>status_code() = integer()</c></p>
- <p><c>reason_phrase() = string()</c></p>
- <p><c>content_type() = http_string()</c></p>
- <p><c>headers() = [header()]</c></p>
- <p><c>header() = {field(), value()}</c></p>
- <p><c>field() = [byte()]</c></p>
- <p><c>value() = binary() | iolist()</c></p>
- <taglist>
- <tag><c>body()</c></tag>
- <item><p>= <c>http_string() | binary()</c></p>
- <p>| <c>{fun(accumulator())</c></p>
- <p><c> -> body_processing_result(), accumulator()}</c></p>
- <p>| <c>{chunkify, fun(accumulator())</c></p>
- <p><c> -> body_processing_result(), accumulator()}</c></p>
- </item>
- </taglist>
- <p><c>body_processing_result() = eof | {ok, iolist(), accumulator()}</c></p>
- <p><c>accumulator() = term()</c></p>
- <p><c>filename() = string()</c></p>
- <p>For more information about HTTP, see
- <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.</p>
-</section>
-
- <section>
- <title>SSL DATA TYPES</title>
- <p>See <seeerl marker="ssl:ssl">ssl(3)</seeerl> for information
- about <c>SSL</c> options (<c>ssloptions()</c>). </p>
- </section>
<section>
<title>HTTP CLIENT SERVICE START/STOP</title>
@@ -142,576 +71,556 @@
see <seeerl marker="inets">inets(3)</seeerl>.
The configuration options are as follows:</p>
<taglist>
- <tag>{profile, profile()}</tag>
- <item><p>Name of the profile, see
- <seeerl marker="#DATA_TYPES">DATA TYPES</seeerl>.
- This option is mandatory.</p></item>
- <tag>{data_dir, path()}</tag>
- <item><p>Directory where the profile
+ <tag>{profile, Profile :: atom() | pid()}</tag>
+ <item>Name of the profile.
+ This option is mandatory.</item>
+ <tag>{data_dir, Path :: string()}</tag>
+ <item>Directory where the profile
can save persistent data. If omitted, all cookies are treated
- as session cookies.</p></item>
+ as session cookies. <c>Path</c> represents a file path or directory path.</item>
</taglist>
- <p>The client can be stopped using <c>inets:stop(httpc, Pid)</c> or
- <c>inets:stop(httpc, Profile)</c>.</p>
+ <p>The client can be stopped using <seemfa marker="inets#stop/2"><c>inets:stop(httpc, Pid)</c></seemfa> or
+ <seemfa marker="inets#stop/2"><c>inets:stop(httpc, Profile)</c></seemfa>.</p>
+
+ <warning><p>Please note that <c>httpc</c> normalizes input URIs before internal
+ processing and special care shall be taken when the URI has percent ("%")
+ characters. A percent serves as the indicator for percent-encoded octets and
+ it must be percent-encoded as "%25" for that octet to be used as data within
+ the URI.</p>
+ <p>For example, in order to send an <c>HTTP GET</c> request with the
+ URI <c>http://localhost/foo%25bar</c>, the percent character must be
+ percent-encoded when creating the request:
+ <c>httpc:request("http://localhost/foo%2525bar").</c> </p></warning>
</section>
-
+
<funcs>
-
<func>
- <name since="OTP R13B04">cancel_request(RequestId) -></name>
- <name since="OTP R13B04">cancel_request(RequestId, Profile) -> ok</name>
+ <name since="OTP R13B04" name="cancel_request" arity="1" />
+ <name since="OTP R13B04" name="cancel_request" arity="2" />
<fsummary>Cancels an asynchronous HTTP request.</fsummary>
- <type>
- <v>RequestId = request_id() - A unique identifier as returned
- by request/4</v>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- </type>
+ <type variable="RequestId" />
+ <type_desc variable="RequestId">
+ A unique identifier as returned by
+ <seemfa marker="#request/4"><c>request/4</c></seemfa>
+ </type_desc>
+ <type variable="Profile" />
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
+ <desc>
+ <p>Cancels an asynchronous HTTP request. Notice that this does not
+ guarantee that the request response is not delivered. Because it is
+ asynchronous, the request can already have been completed when the
+ cancellation arrives.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP R13B04" name="cookie_header" arity="1"/>
+ <name since="OTP R13B04" name="cookie_header" arity="2"/>
+ <fsummary>Returns the cookie header that would have been sent when making
+ a request to <c><anno>URL</anno></c>, using the profile
+ <c><anno>Profile</anno></c>.</fsummary>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Cancels an asynchronous HTTP request. Notice that this does not guarantee
- that the request response is not delivered. Because it is asynchronous,
- the request can already have been completed when the cancellation arrives.
- </p>
+ <p>Returns the cookie header that would have been sent when making a
+ request to <c><anno>Url</anno></c> using profile
+ <c><anno>Profile</anno></c>. If no profile is specified, the default
+ profile is used.</p>
+ <p>Option <c>ipv6_host_with_bracket</c> deals with how to parse IPv6
+ addresses. For details, see argument <c>Options</c> of <seemfa
+ marker="#request/4">request/[4,5]</seemfa>.</p>
</desc>
</func>
<func>
- <name since="OTP R13B04">cookie_header(Url) -> </name>
- <name since="OTP R13B04">cookie_header(Url, Profile | Opts) -> header() | {error, Reason}</name>
- <name since="OTP R15B">cookie_header(Url, Opts, Profile) -> header() | {error, Reason}</name>
- <fsummary>Returns the cookie header that would have been 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()</v>
- <d>When started <c>stand_alone</c>.</d>
- <v>cookie_header_opt() = {ipv6_host_with_brackets, boolean()}</v>
- </type>
+ <name since="OTP R15B" name="cookie_header" arity="3"/>
+ <fsummary>Returns the cookie header that would have been sent when making
+ a request to <c><anno>URL</anno></c> using the profile
+ <c><anno>Profile</anno></c>.</fsummary>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Returns the cookie header that would have been sent
- when making a request to <c>Url</c> using profile <c>Profile</c>.
- If no profile is specified, the default profile is used.</p>
- <p>Option <c>ipv6_host_with_bracket</c> deals with how to
- parse IPv6 addresses. For details,
- see argument <c>Options</c> of
- <seemfa marker="#request/4">request/[4,5]</seemfa>.</p>
+ <p>Returns the cookie header that would have been sent when making a
+ request to <c><anno>Url</anno></c> using profile
+ <c><anno>Profile</anno></c>. If no profile is specified, the default
+ profile is used.</p>
+ <p>Option <c>ipv6_host_with_bracket</c> deals with how to parse IPv6
+ addresses. For details, see argument <c>Options</c> of <seemfa
+ marker="#request/4">request/[4,5]</seemfa>.</p>
</desc>
</func>
<func>
- <name since="OTP R15B01">get_options(OptionItems) -> {ok, Values} | {error, Reason}</name>
- <name since="OTP R15B01">get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason}</name>
+ <name since="OTP R15B01" name="get_options" arity="1"/>
+ <name since="OTP R15B01" name="get_options" arity="2"/>
<fsummary>Gets the currently used options.</fsummary>
- <type>
- <v>OptionItems = all | [option_item()]</v>
- <v>option_item() = proxy |
- https_proxy |
- max_sessions |
- keep_alive_timeout |
- max_keep_alive_length |
- pipeline_timeout |
- max_pipeline_length |
- cookies |
- ipfamily |
- ip |
- port |
- socket_opts |
- verbose |
- unix_socket</v>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can used.</d>
- <v>Values = [{option_item(), term()}]</v>
- <v>Reason = term()</v>
- </type>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
<p>Retrieves the options currently used by the client.</p>
</desc>
</func>
<func>
- <name since="OTP R15B02">info() -> list()</name>
- <name since="OTP R15B02">info(Profile) -> list()</name>
+ <name since="OTP R15B02" name="info" arity="0"/>
+ <name since="OTP R15B02" name="info" arity="1"/>
<fsummary>Produces a list of miscellaneous information.</fsummary>
- <type>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- </type>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Produces a list of miscellaneous information.
- Intended for debugging.
- If no profile is specified, the default profile is used.</p>
+ <p>Produces a list of miscellaneous information. Intended for debugging.
+ If no profile is specified, the default profile is used.</p>
</desc>
</func>
<func>
- <name since="OTP R13B04">reset_cookies() -> void()</name>
- <name since="OTP R13B04">reset_cookies(Profile) -> void()</name>
+ <name since="OTP R13B04" name="reset_cookies" arity="0"/>
+ <name since="OTP R13B04" name="reset_cookies" arity="1"/>
<fsummary>Resets the cookie database.</fsummary>
- <type>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- </type>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Resets (clears) the cookie database for the specified
- <c>Profile</c>. If no profile is specified the default profile
- is used.</p>
+ <p>Resets (clears) the cookie database for the specified
+ <c><anno>Profile</anno></c>. If no profile is specified the default
+ profile is used.</p>
</desc>
</func>
<func>
- <name since="OTP R13B04">request(Url) -> </name>
- <name since="OTP R13B04">request(Url, Profile) -> {ok, Result} | {error, Reason}</name>
+ <name since="OTP R13B04" name="request" arity="1"/>
+ <name since="OTP R13B04" name="request" arity="2"/>
<fsummary>Sends a get HTTP request.</fsummary>
- <type>
- <v>Url = url()</v>
- <v>Result = {status_line(), headers(), Body} |
- {status_code(), Body} | request_id()</v>
- <v>Body = http_string() | binary()</v>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- <v>Reason = term()</v>
- </type>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Equivalent to <c>httpc:request(get, {Url, []}, [], [])</c>.</p>
+ <p>Equivalent to <seemfa marker="httpc#request/4"><c>httpc:request(get, {Url, []}, [], [])</c></seemfa>.</p>
</desc>
</func>
<func>
- <name since="OTP R13B04">request(Method, Request, HTTPOptions, Options) -></name>
- <name since="OTP R13B04">request(Method, Request, HTTPOptions, Options, Profile) -> {ok, Result} | {ok, saved_to_file} | {error, Reason}</name>
-
+ <name since="OTP R13B04" name="request" arity="4"/>
+ <name since="OTP R13B04" name="request" arity="5"/>
<fsummary>Sends an HTTP request.</fsummary>
- <type>
- <v>Method = method()</v>
- <v>Request = request()</v>
- <v>HTTPOptions = http_options()</v>
- <v>http_options() = [http_option()]</v>
- <v>http_option() = {timeout, timeout()} |
- {connect_timeout, timeout()} |
- {ssl, ssloptions()} |
- {essl, ssloptions()} |
- {autoredirect, boolean()} |
- {proxy_auth, {userstring(), passwordstring()}} |
- {version, http_version()} |
- {relaxed, boolean()}</v>
- <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()} |
- {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>
- <v>Module = atom()</v>
- <v>Function = atom()</v>
- <v>Args = list()</v>
- <v>body_format() = string | binary</v>
- <v>Result = {status_line(), headers(), Body} |
- {status_code(), Body} | request_id()</v>
- <v>Body = http_string() | binary()</v>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- <v>Reason = term()</v>
- </type>
-
+ <type_desc variable="Profile">
+ When <c><anno>Profile</anno></c> is <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Sends an HTTP request. The function can be both synchronous
- and asynchronous. In the latter case, the function returns
- <c>{ok, RequestId}</c> and then the information is delivered
- to the <c>receiver</c> depending on that value.</p>
+ <p>Sends an HTTP request. The function can be both synchronous and
+ asynchronous. In the latter case, the function returns <c>{ok,
+ RequestId}</c> and then the information is delivered to the
+ <c>receiver</c> depending on that value.</p>
+ <p>When <c><anno>Profile</anno></c> is <c>stand_alone</c> only the pid can be used.</p>
+ <p>HTTP options:</p>
- <p>HTTP option (<c>http_option()</c>) details:</p>
- <marker id="request2_http_options"></marker>
<taglist>
- <tag><c><![CDATA[timeout]]></c></tag>
+ <tag><c>timeout</c></tag>
<item>
<p>Time-out time for the request.</p>
<p>The clock starts ticking when the request is sent.</p>
<p>Time is in milliseconds.</p>
<p>Default is <c>infinity</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[connect_timeout]]></c></tag>
+ <tag><c>connect_timeout</c></tag>
<item>
- <p>Connection time-out time, used during the initial request,
- when the client is <em>connecting</em> to the server.</p>
+ <p>Connection time-out time, used during the initial request,
+ when the client is <em>connecting</em> to the server.</p>
<p>Time is in milliseconds.</p>
<p>Default is the value of option <c>timeout</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[ssl]]></c></tag>
+ <tag><c>ssl</c></tag>
<item>
<p>This is the <c>SSL/TLS</c> connecting configuration option.</p>
<p>Defaults to <c>[]</c>. See <seeerl marker="ssl:ssl">ssl:connect/[2,3,4]</seeerl> for available options.</p>
- </item>
+ </item>
- <tag><c><![CDATA[autoredirect]]></c></tag>
+ <tag><c>autoredirect</c></tag>
<item>
- <p>The client automatically retrieves the information
- from the new URI and returns that as the result, instead
- of a 30X-result code.</p>
- <p>For some 30X-result codes, automatic redirect
- is not allowed. In these cases the 30X-result is always
- returned.</p>
- <p>Default is <c>true</c>.</p>
- </item>
-
- <tag><c><![CDATA[proxy_auth]]></c></tag>
+ <p>The client automatically retrieves the information from the new
+ URI and returns that as the result, instead of a 30X-result
+ code.</p>
+ <p>For some 30X-result codes, automatic redirect is not allowed. In
+ these cases the 30X-result is always returned.</p>
+ <p>Default is <c>true</c>.</p>
+ </item>
+
+ <tag><c>proxy_auth</c></tag>
<item>
- <p>A proxy-authorization header using the provided username and
- password is added to the request.</p>
- </item>
+ <p>A proxy-authorization header using a tuple where the first element is the <c>username</c> and
+ the second element of the tuple is the <c>password</c> added to the request.</p>
+ </item>
- <tag><c><![CDATA[version]]></c></tag>
+ <tag><c>version</c></tag>
<item>
<p>Can be used to make the client act as an <c>HTTP/1.0</c>
client. By default this is an <c>HTTP/1.1</c>
client. When using <c>HTTP/1.0</c> persistent connections are
not used.</p>
<p>Default is the string <c>"HTTP/1.1"</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[relaxed]]></c></tag>
+ <tag><c>relaxed</c></tag>
<item>
- <p>If set to <c>true</c>, workarounds for known server deviations
- from the HTTP-standard are enabled.</p>
+ <p>If set to <c>true</c>, workarounds for known server deviations
+ from the HTTP-standard are enabled.</p>
<p>Default is <c>false</c>.</p>
- </item>
+ </item>
</taglist>
- <p>Option (<c>option()</c>) details:</p>
+ <p>Options details:</p>
<taglist>
- <tag><c><![CDATA[sync]]></c></tag>
+ <tag><c>sync</c></tag>
<item>
<p>Option for the request to be synchronous or asynchronous.</p>
<p>Default is <c>true</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[stream]]></c></tag>
+ <tag><c>stream</c></tag>
<item>
- <p>Streams the body of a 200 or 206 response to the calling
- process or to a file. When streaming to the calling process
- using option <c>self</c>, the following stream messages
- are sent to that process: <c>{http, {RequestId,
- stream_start, Headers}}, {http, {RequestId, stream,
- BinBodyPart}}, and {http, {RequestId, stream_end, Headers}}</c>.</p>
- <p>When streaming to the calling processes using option
- <c>{self, once}</c>, the first message has an extra
- element, that is, <c>{http, {RequestId, stream_start, Headers, Pid}}</c>.
- This is the process id to be used as an argument to
- <c>httpc:stream_next/1</c> to trigger the next message to be sent to
- the calling process.</p>
- <p>Notice that chunked encoding can add
- headers so that there are more headers in the <c>stream_end</c>
- message than in <c>stream_start</c>.
- When streaming to a file and the request is asynchronous, the
- message <c>{http, {RequestId, saved_to_file}}</c> is sent.</p>
+ <p>Streams the body of a 200 or 206 response to the calling process
+ or to a file. When streaming to the calling process using option
+ <c>self</c>, the following stream messages are sent to that process:
+ <c>{http, {RequestId, stream_start, Headers}}, {http, {RequestId,
+ stream, BinBodyPart}}, and {http, {RequestId, stream_end,
+ Headers}}</c>.</p>
+
+ <p>When streaming to the calling processes using option <c>{self,
+ once}</c>, the first message has an extra element, that is,
+ <c>{http, {RequestId, stream_start, Headers, Pid}}</c>. This is the
+ process id to be used as an argument to <c>httpc:stream_next/1</c>
+ to trigger the next message to be sent to the calling process.</p>
+
+ <p>Notice that chunked encoding can add headers so that there are
+ more headers in the <c>stream_end</c> message than in
+ <c>stream_start</c>. When streaming to a file and the request is
+ asynchronous, the message <c>{http, {RequestId, saved_to_file}}</c>
+ is sent.</p>
<p>Default is <c>none</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[body_format]]></c></tag>
+ <tag><c>body_format</c></tag>
<item>
- <p>Defines if the body is to be delivered as a string or
- binary. This option is only valid for the synchronous
- request.</p>
+ <p>Defines if the body is to be delivered as a string or
+ binary. This option is only valid for the synchronous
+ request.</p>
<p>Default is <c>string</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[full_result]]></c></tag>
+ <tag><c>full_result</c></tag>
<item>
- <p>Defines if a "full result" is to be returned to the caller (that is,
- the body, the headers, and the entire status line) or not
- (the body and the status code).</p>
+ <p>Defines if a "full result" is to be returned to the caller (that
+ is, the body, the headers, and the entire status line) or not (the
+ body and the status code).</p>
<p>Default is <c>true</c>.</p>
- </item>
+ </item>
- <tag><c><![CDATA[headers_as_is]]></c></tag>
+ <tag><c>headers_as_is</c></tag>
<item>
- <p>Defines if the headers provided by the user are to be made
- lower case or to be regarded as case sensitive.</p>
- <p>The HTTP standard requires them to be
- case insensitive. Use this feature only if there is
- no other way to communicate with the server or for testing
- purpose. When this option is used, no headers
- are automatically added. All necessary headers must be
- provided by the user.</p>
- <p>Default is <c>false</c>.</p>
- </item>
-
- <tag><c><![CDATA[socket_opts]]></c></tag>
+ <p>Defines if the headers provided by the user are to be made lower
+ case or to be regarded as case sensitive.</p>
+
+ <p>The HTTP standard requires them to be case insensitive. Use this
+ feature only if there is no other way to communicate with the server
+ or for testing purpose. When this option is used, no headers are
+ automatically added. All necessary headers must be provided by the
+ user.</p>
+ <p>Default is <c>false</c>.</p>
+ </item>
+
+ <tag><c>socket_opts</c></tag>
<item>
<p>Socket options to be used for this request.</p>
- <p>Overrides any value set by function
- <seemfa marker="#set_options/1">set_options</seemfa>.</p>
+ <p>See the options used by
+ <seeerl marker="kernel:gen_tcp">gen_tcp(3)</seeerl> and
+ <seeerl marker="ssl:ssl">ssl(3)</seeerl>
+ </p>
+ <p>Overrides any value set by function
+ <seemfa marker="#set_options/1">set_options</seemfa>.</p>
<p>The validity of the options is <em>not</em> checked by
the HTTP client they are assumed to be correct and passed
on to ssl application and inet driver, which may reject
them if they are not correct.
- </p>
- <note>
- <p>
- Persistent connections are not supported when setting the
- <c>socket_opts</c> option. When <c>socket_opts</c> is not
- set the current implementation assumes the requests to the
- same host, port combination will use the same socket options.
- </p>
- </note>
-
- <p>By default the socket options set by function
- <seemfa marker="#set_options/1">set_options/[1,2]</seemfa>
- are used when establishing a connection.</p>
- </item>
-
- <tag><c><![CDATA[receiver]]></c></tag>
+ </p>
+ <note>
+ <p>
+ Persistent connections are not supported when setting the
+ <c>socket_opts</c> option. When <c>socket_opts</c> is not set
+ the current implementation assumes the requests to the same
+ host, port combination will use the same socket options.
+ </p>
+ </note>
+
+ <p>By default the socket options set by function <seemfa
+ marker="#set_options/1">set_options/[1,2]</seemfa> are used when
+ establishing a connection.</p>
+ </item>
+
+ <tag><c>receiver</c></tag>
<item>
- <p>Defines how the client delivers the result of an
- asynchronous request (<c>sync</c> has the value
- <c>false</c>).</p>
+ <p>Defines how the client delivers the result of an asynchronous
+ request (<c>sync</c> has the value <c>false</c>).</p>
<taglist>
- <tag><c><![CDATA[pid()]]></c></tag>
+ <tag><c>pid()</c></tag>
<item>
- <p>Messages are sent to this process in the format
- <c>{http, ReplyInfo}</c>.</p>
- </item>
+ <p>Messages are sent to this process in the format <c>{http,
+ ReplyInfo}</c>.</p>
+ </item>
- <tag><c><![CDATA[function/1]]></c></tag>
+ <tag><c>function/1</c></tag>
<item>
- <p>Information is delivered to the receiver through calls
- to the provided fun <c>Receiver(ReplyInfo)</c>.</p>
- </item>
+ <p>Information is delivered to the receiver through calls to the
+ provided fun <c>Receiver(ReplyInfo)</c>.</p>
+ </item>
- <tag><c><![CDATA[{Module, Function, Args}]]></c></tag>
+ <tag><c>{Module, Function, Args}</c></tag>
<item>
- <p>Information is delivered to the receiver through calls
- to the callback function
- <c>apply(Module, Function, [ReplyInfo | Args])</c>.</p>
- </item>
+ <p>Information is delivered to the receiver through calls to the
+ callback function <c>apply(Module, Function, [ReplyInfo |
+ Args])</c>.</p>
+ </item>
</taglist>
<p>In all of these cases, <c>ReplyInfo</c> has the following
- structure:</p>
-
-<pre>
-{RequestId, saved_to_file}
-{RequestId, {error, Reason}}
-{RequestId, Result}
-{RequestId, stream_start, Headers}
-{RequestId, stream_start, Headers, HandlerPid}
-{RequestId, stream, BinBodyPart}
-{RequestId, stream_end, Headers}</pre>
-
- <p>Default is the <c>pid</c> of the process calling the request
+ structure:</p>
+
+ <pre>
+ {RequestId, saved_to_file}
+ {RequestId, {error, Reason}}
+ {RequestId, Result}
+ {RequestId, stream_start, Headers}
+ {RequestId, stream_start, Headers, HandlerPid}
+ {RequestId, stream, BinBodyPart}
+ {RequestId, stream_end, Headers}</pre>
+ <p>Default is 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>
+ <marker id="ipv6_host_with_brackets"></marker>
+ </item>
+ <tag><c>ipv6_host_with_brackets</c></tag>
<item>
- <p>Defines when parsing the Host-Port part of an URI with an IPv6 address
- with brackets, if those brackets are to be retained (<c>true</c>)
- or stripped (<c>false</c>).</p>
+ <p>Defines when parsing the Host-Port part of an URI with an IPv6
+ address with brackets, if those brackets are to be retained
+ (<c>true</c>) or stripped (<c>false</c>).</p>
<p>Default is <c>false</c>.</p>
- </item>
-
+ </item>
</taglist>
</desc>
</func>
<func>
- <name since="OTP R13B04">set_options(Options) -> </name>
- <name since="OTP R13B04">set_options(Options, Profile) -> ok | {error, Reason}</name>
+ <name since="OTP R13B04" name="set_options" arity="1"/>
+ <name since="OTP R13B04" name="set_options" arity="2"/>
<fsummary>Sets options to be used for subsequent requests.</fsummary>
- <type>
- <v>Options = [Option]</v>
- <v>Option = {proxy, {Proxy, NoProxy}}</v>
- <v>| {https_proxy, {Proxy, NoProxy}}</v>
- <v>| {max_sessions, MaxSessions}</v>
- <v>| {max_keep_alive_length, MaxKeepAlive}</v>
- <v>| {keep_alive_timeout, KeepAliveTimeout}</v>
- <v>| {max_pipeline_length, MaxPipeline}</v>
- <v>| {pipeline_timeout, PipelineTimeout}</v>
- <v>| {cookies, CookieMode}</v>
- <v>| {ipfamily, IpFamily}</v>
- <v>| {ip, IpAddress}</v>
- <v>| {port, Port}</v>
- <v>| {socket_opts, socket_opts()}</v>
- <v>| {verbose, VerboseMode}</v>
- <v>| {unix_socket, UnixSocket}</v>
- <v>Proxy = {Hostname, Port}</v>
- <v>Hostname = http_string()</v>
- <d>Example: "localhost" or "foo.bar.se"</d>
- <v>Port = integer()</v>
- <d>Example: 8080</d>
- <v>NoProxy = [NoProxyDesc]</v>
- <v>NoProxyDesc = DomainDesc | HostName | IPDesc</v>
- <v>DomainDesc = "*.Domain"</v>
- <d>Example: "*.ericsson.se"</d>
- <v>IpDesc = http_string()</v>
- <d>Example: "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).
- <c>proxy</c> defaults to <c>{undefined, []}</c>,
- that is, no proxy is configured and
- <c>https_proxy</c> defaults to the value of <c>proxy</c>.</d>
- <v>MaxSessions = integer()</v>
- <d>Maximum number of persistent connections to a host.
- Default is <c>2</c>.</d>
- <v>MaxKeepAlive = integer()</v>
- <d>Maximum number of outstanding requests on the same connection to
- a host. Default is <c>5</c>.</d>
- <v>KeepAliveTimeout = integer()</v>
- <d>If a persistent connection is idle longer than the
- <c>keep_alive_timeout</c> in milliseconds,
- the client closes the connection.
- The server can also have such a time-out but do not take that for granted.
- Default is <c>120000</c> (= 2 min).</d>
- <v>MaxPipeline = integer()</v>
- <d>Maximum number of outstanding requests on a pipelined connection
- to a host. Default is <c>2</c>.</d>
- <v>PipelineTimeout = integer()</v>
- <d>If a persistent connection is idle longer than the
- <c>pipeline_timeout</c> in milliseconds,
- the client closes the connection. Default is <c>0</c>,
- which results in pipelining not being used.</d>
- <v>CookieMode = enabled | disabled | verify</v>
- <d>If cookies are enabled, all valid cookies are automatically
- saved in the cookie database of the client manager.
- If option <c>verify</c> is used, function <c>store_cookies/2</c>
- has to be called for the cookies to be saved.
- Default is <c>disabled</c>.</d>
- <v>IpFamily = inet | inet6 | local</v>
- <d>Default is <c>inet</c>.</d>
- <v>IpAddress = ip_address()</v>
- <d>If the host has several network interfaces, this option specifies
- which one to use.
- See <seeerl marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seeerl>
- for details.</d>
- <v>Port = integer()</v>
- <d>Local port number to use.
- See <seeerl marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seeerl>
- for details.</d>
- <v>socket_opts() = [socket_opt()]</v>
- <d>The options are appended to the socket options used by the
- client.
- These are the default values when a new request handler
- is started (for the initial connect). They are passed directly
- to the underlying transport (<c>gen_tcp</c> or <c>SSL</c>)
- <em>without</em> verification.</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()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- <v>UnixSocket = path()</v>
- <d>
- Experimental option for sending HTTP requests over a unix domain socket. The value
- of <c>unix_socket</c> shall be the full path to a unix domain socket file with read/write
- permissions for the erlang process. Default is <c>undefined</c>.
- </d>
- </type>
<desc>
- <p>Sets options to be used for subsequent requests.</p>
- <note>
- <p>If possible, the client keeps its connections
- alive and uses 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 that are
- ideal to be sent on a persistent connection.
- This depends much on the application.</p>
- <p>A long queue of requests can cause a
- user-perceived delay, as earlier requests can take a long time
- to complete. The HTTP/1.1 specification suggests a
- limit of two persistent connections per server, which is the
- default value of option <c>max_sessions</c>.</p>
- <p>
- The current implementation assumes the requests to the same host, port
- combination will use the same socket options.
- </p>
- </note>
+ <p>Sets options to be used for subsequent requests.</p>
+ <taglist>
+ <tag><c>HostName</c></tag>
+ <item>
+ Example: "localhost" or "foo.bar.se"
+ </item>
+ <tag><c>DomainDesc</c></tag>
+ <item>
+ Example <c>"*.Domain"</c> or <c>"*.ericsson.se"</c>
+ </item>
+ <tag><c>IpAddressDesc</c></tag>
+ <item>
+ Example: "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). <c>proxy</c> defaults to <c>{undefined,
+ []}</c>, that is, no proxy is configured and <c>https_proxy</c> defaults
+ to the value of <c>proxy</c>.
+ </item>
+ <tag><c>MaxSessions</c></tag>
+ <item>
+ <c><anno>MaxSessions</anno></c> Maximum number of persistent connections to a host. Default is <c>2</c>.
+ </item>
+
+ <tag><c>MaxKeepAlive</c></tag>
+ <item>
+ <c><anno>MaxKeepAlive</anno></c> Maximum number of outstanding requests
+ on the same connection to a host. Default is <c>5</c>.
+ </item>
+ <tag><c>KeepAliveTimeout</c></tag>
+ <item>
+ <c><anno>KeepAliveTimeout</anno></c> If a persistent connection is idle longer than the
+ <c>keep_alive_timeout</c> in milliseconds, the client closes the
+ connection. The server can also have such a time-out but do not take that
+ for granted. Default is <c>120000</c> (= 2 min).
+ </item>
+ <tag><c>MaxPipeline</c></tag>
+ <item>
+ <c><anno>MaxPipeline</anno></c> Maximum number of outstanding requests on a pipelined connection to a
+ host. Default is <c>2</c>.
+ </item>
+ <tag><c>PipelineTimeout</c></tag>
+ <item>
+ <c><anno>PipelineTimeout</anno></c> If a persistent connection is idle longer than the
+ <c>pipeline_timeout</c> in milliseconds, the client closes the
+ connection. Default is <c>0</c>, which results in pipelining not being
+ used.
+ </item>
+ <tag><c>CookieMode</c></tag>
+ <item>
+ If cookies are enabled, all valid cookies are automatically saved in
+ the cookie database of the client manager. If option <c>verify</c> is
+ used, function <c>store_cookies/2</c> has to be called for the cookies
+ to be saved. Default is <c>disabled</c>.
+ </item>
+ <tag><c>IpFamily</c></tag>
+ <item>
+ Default is <c>inet</c>. With <c>inet6fb4</c> option, IPv6
+ will be preferred but if connection fails, an IPv4 fallback connection
+ attempt will be made.
+ </item>
+ <tag><c>IpAddress</c></tag>
+ <item>
+ If the host has several network interfaces, this option specifies
+ which one to use. See
+ <seeerl marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seeerl> for
+ details.
+ </item>
+ <tag><c>Port</c></tag>
+ <item>
+ Example: <c>8080</c>.
+ Local port number to use. See <seeerl
+ marker="kernel:gen_tcp#connect">gen_tcp:connect/3,4</seeerl> for
+ details.
+ </item>
+ <tag><c>SocketOpts</c></tag>
+ <item>
+ The options are appended to the socket options used by the client.
+ These are the default values when a new request handler is started (for
+ the initial connect). They are passed directly to the underlying
+ transport (<c>gen_tcp</c> or <c>SSL</c>) without
+ verification.
+ <p>See the options used by
+ <seeerl marker="kernel:gen_tcp">gen_tcp(3)</seeerl> and
+ <seeerl marker="ssl:ssl">ssl(3)</seeerl>
+ </p>
+ </item>
+ <tag><c>VerboseMode</c></tag>
+ <item>
+ 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.
+ </item>
+ <tag><c>Profile</c></tag>
+ <item>
+ When started <c>stand_alone</c> only the pid can be used.
+ </item>
+ <tag><c>UnixSocket</c></tag>
+ <item>
+ Experimental option for sending HTTP requests over a unix domain
+ socket. The value of <c>unix_socket</c> shall be the full path to a unix
+ domain socket file with read/write permissions for the erlang process.
+ Default is <c>undefined</c>.
+ </item>
+
+ </taglist>
+
+ <note>
+ <p>If possible, the client keeps its connections alive and uses
+ 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 that are ideal to
+ be sent on a persistent connection. This depends much on the
+ application.</p>
+ <p>A long queue of requests can cause a user-perceived delay, as
+ earlier requests can take a long time to complete. The HTTP/1.1
+ specification suggests a limit of two persistent connections per
+ server, which is the default value of option <c>max_sessions</c>.</p>
+ <p>The current implementation assumes the requests to the same host,
+ port combination will use the same socket options.
+ </p>
+ </note>
<marker id="get_options"></marker>
</desc>
</func>
-
+
+ <func>
+ <name since="OTP 25.1" name="ssl_verify_host_options" arity="1"/>
+ <fsummary>Returns ssl options for host verification.</fsummary>
+ <desc>
+ <p>Returns ssl options which can be used to verify the host, uses
+ <seemfa marker="public_key:public_key#cacerts_get/0"><c>public_key:cacerts_get()</c></seemfa>
+ to read CA certicates and if <c><anno>WildcardHostName</anno></c> is true adds the hostname check from
+ <seemfa marker="public_key:public_key#pkix_verify_hostname_match_fun/1">
+ <c> public_key:public_key:pkix_verify_hostname_match_fun(https)</c></seemfa> to the options.
+ </p>
+ </desc>
+ </func>
+
<func>
- <name since="OTP R14B02">store_cookies(SetCookieHeaders, Url) -> </name>
- <name since="OTP R14B02">store_cookies(SetCookieHeaders, Url, Profile) -> ok | {error, Reason}</name>
+ <name since="OTP R14B02" name="store_cookies" arity="2"/>
+ <name since="OTP R14B02" name="store_cookies" arity="3"/>
<fsummary>Saves the cookies defined in <c>SetCookieHeaders</c> in the
client profile cookie database.</fsummary>
- <type>
- <v>SetCookieHeaders = headers() - where field = "set-cookie"</v>
- <v>Url = url()</v>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- </type>
+ <type_desc variable="SetCookieHeaders">
+ Where field = "set-cookie"
+ </type_desc>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Saves the cookies defined in <c>SetCookieHeaders</c>
- in the client profile cookie database.
- Call this function if option <c>cookies</c> is set to <c>verify</c>.
- If no profile is specified, the default profile is used.</p>
+ <p>Saves the cookies defined in <c>SetCookieHeaders</c> in the client
+ profile cookie database. Call this function if option <c>cookies</c> is
+ set to <c>verify</c>. If no profile is specified, the default profile is
+ used.</p>
</desc>
</func>
<func>
- <name since="OTP R13B04">stream_next(Pid) -> ok</name>
+ <name since="OTP R13B04" name="stream_next" arity="1"/>
<fsummary>Triggers the next message to be streamed, that is,
the same behavior as active one for sockets.
</fsummary>
- <type>
- <v>Pid = pid()</v>
- <d>As received in the <c>stream_start message</c></d>
- </type>
+ <type_desc variable="Pid">
+ As received in the <c>stream_start message</c>
+ </type_desc>
<desc>
- <p>Triggers the next message to be streamed, that is,
- the same behavior as active ones for sockets.</p>
-
+ <p>Triggers the next message to be streamed, that is, the same behavior
+ as active ones for sockets.</p>
<marker id="verify_cookies"></marker>
<marker id="store_cookies"></marker>
</desc>
</func>
<func>
- <name since="OTP R13B04">which_cookies() -> cookies()</name>
- <name since="OTP R13B04">which_cookies(Profile) -> cookies()</name>
+ <name since="OTP R13B04" name="which_cookies" arity="0"/>
+ <name since="OTP R13B04" name="which_cookies" arity="1"/>
<fsummary>Dumps the entire cookie database.</fsummary>
- <type>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- <v>cookies() = [cookie_stores()]</v>
- <v>cookie_stores() = {cookies, cookies()} | {session_cookies, cookies()}</v>
- <v>cookies() = [cookie()]</v>
- <v>cookie() = term()</v>
- </type>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
<desc>
- <p>Produces a list of the entire cookie database.
- Intended for debugging/testing purposes.
- If no profile is specified, the default profile is used.</p>
+ <p>Produces a list of the entire cookie database. Intended for
+ debugging/testing purposes. If no profile is specified, the default
+ profile is used.</p>
</desc>
</func>
<func>
- <name since="OTP R15B02">which_sessions() -> session_info()</name>
- <name since="OTP R15B02">which_sessions(Profile) -> session_info()</name>
+ <name since="OTP R15B02" name="which_sessions" arity="0"/>
+ <name since="OTP R15B02" name="which_sessions" arity="1"/>
<fsummary>Produces a slightly processed dump of the sessions database.</fsummary>
- <type>
- <v>Profile = profile() | pid()</v>
- <d>When started <c>stand_alone</c> only the pid can be used.</d>
- <v>session_info() = {[session()], [term()], [term()]}</v>
- <v>session() = term() - Internal representation of a session</v>
- </type>
+ <type_desc variable="Profile">
+ When started <c>stand_alone</c> only the pid can be used.
+ </type_desc>
+ <type_desc variable="Session">
+ Internal representation of a session.
+ </type_desc>
<desc>
<p> This function is intended for debugging only. It produces
a slightly processed dump of the session database. The first
@@ -722,8 +631,6 @@
profile is used.</p>
</desc>
</func>
-
-
</funcs>
<section>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 3b44a66340..118d38ba2a 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,7 +39,7 @@
Provides web server start options, administrative functions, and
an Erlang callback API.</p>
</description>
-
+
<section>
<title>DATA TYPES</title>
<p>Type definitions that are used more than once in
@@ -49,10 +49,10 @@
<p><c>path() = string()</c> representing a file or a directory path</p>
<p><c> ip_address() = {N1,N2,N3,N4} % IPv4
| {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6</c></p>
- <p><c>hostname() = string()</c> representing a host, for example,
+ <p><c>hostname() = string()</c> representing a host, for example,
"foo.bar.com"</p>
<p><c>property() = atom()</c></p>
-
+
</section>
<section>
@@ -75,7 +75,7 @@
term()</c>, followed by a full stop. If the web server is started
dynamically at runtime, a file can still be specified but also the
complete property list.</p>
-
+
<taglist>
<tag><marker id="prop_proplist_file"></marker>{proplist_file, path()}</tag>
<item>
@@ -94,7 +94,7 @@
<p><em>Mandatory Properties</em></p>
<taglist>
<tag><marker id="prop_port"></marker>{port, integer()} </tag>
- <item>
+ <item>
<p>The port that the HTTP server listen to.
If zero is specified as port, an arbitrary available port
is picked and function <c>httpd:info/2</c> can be used to
@@ -107,8 +107,8 @@
</item>
<tag><marker id="prop_server_root"></marker>{server_root, path()}</tag>
- <item>
- <p>Defines the home directory of the server, where log files, and so on,
+ <item>
+ <p>Defines the home directory of the server, where log files, and so on,
can be stored. Relative paths specified in other properties refer
to this directory.</p>
</item>
@@ -141,14 +141,19 @@
</p>
</item>
- <tag><marker id="prop_socket_type"></marker>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}</tag>
+ <tag><marker id="prop_socket_type"></marker>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {ssl, Config::proplist()}}</tag>
<item>
- <p>For <c>ip_comm</c> configuration options, see
+ <p>For <c>ip_comm</c> configuration options, see
<seemfa marker="kernel:gen_tcp#listen/2">gen_tcp:listen/2</seemfa>, some options
that are used internally by httpd cannot be set.</p>
- <p>For <c>SSL</c> configuration options, see
+ <p>For <c>SSL</c> configuration options, see
<seemfa marker="ssl:ssl#listen/2">ssl:listen/2</seemfa>.</p>
- <p>Default is <c>ip_comm</c>.</p>
+ <p>Default is <c>ip_comm</c>.</p>
+ <note>
+ <p>OTP-25 deprecates the communication properties <c>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}</c>
+ replacing it by <c>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {ssl, Config::proplist()}}</c>.
+ </p>
+ </note>
</item>
<tag><marker id="prop_ipfamily"></marker>{ipfamily, inet | inet6}</tag>
@@ -156,7 +161,7 @@
<p>Default is <c>inet</c>, legacy option <c>inet6fb4</c> no longer makes sense and will be translated
to inet.</p>
</item>
-
+
<tag><marker id="prop_minimum_bytes_per_second"></marker>{minimum_bytes_per_second, integer()}</tag>
<item>
<p>If given, sets a minimum of bytes per second value for connections.</p>
@@ -173,53 +178,53 @@
<p>Defines which modules the HTTP server uses when handling
requests. Default is <c>[mod_alias, mod_auth, mod_esi,
mod_actions, mod_cgi, mod_dir, mod_get, mod_head, mod_log,
- mod_disk_log]</c>.
+ mod_disk_log]</c>.
Notice that some <c>mod</c>-modules are dependent on
others, so the order cannot be entirely arbitrary. See the
<seeguide marker="http_server">Inets Web Server Modules</seeguide> in the
User's Guide for details.</p>
</item>
</taglist>
-
+
<marker id="props_limit"></marker>
<p><em>Limit properties</em> </p>
<taglist>
<tag><marker id="prop_customize"></marker>{customize, atom()}</tag>
- <item>
+ <item>
<p>A callback module to customize the inets HTTP servers behaviour
see <seeerl marker="httpd_custom_api"> httpd_custom_api</seeerl> </p>
</item>
-
+
<tag><marker id="prop_disable_chunked_encoding"></marker>{disable_chunked_transfer_encoding_send, boolean()}</tag>
- <item>
+ <item>
<p>Allows you to disable chunked
transfer-encoding when sending a response to an HTTP/1.1
client. Default is <c>false</c>.</p>
</item>
-
+
<tag><marker id="prop_keep_alive"></marker>{keep_alive, boolean()}</tag>
<item>
<p>Instructs the server whether to use persistent
connections when the client claims to be HTTP/1.1
compliant. Default is <c>true</c>.</p>
</item>
-
+
<tag><marker id="prop_keep_alive_timeout"></marker>{keep_alive_timeout, integer()}</tag>
<item>
<p>The number of seconds the server waits for a
subsequent request from the client before closing the
connection. Default is <c>150</c>.</p>
</item>
-
+
<tag><marker id="prop_max_body_size"></marker>{max_body_size, integer()}</tag>
<item>
<p>Limits the size of the message body of an HTTP request.
Default is no limit.</p>
</item>
-
+
<tag><marker id="prop_max_clients"></marker>{max_clients, integer()}</tag>
- <item>
+ <item>
<p>Limits the number of simultaneous requests that can be
supported. Default is <c>150</c>.</p>
</item>
@@ -243,44 +248,38 @@
<p>Limits the size of the HTTP request URI.
Default is no limit.</p>
</item>
-
+
<tag><marker id="prop_max_keep_alive_req"></marker>{max_keep_alive_request, integer()}</tag>
<item>
<p>The number of requests that a client can do on one
connection. When the server has responded to the number of
- requests defined by <c>max_keep_alive_requests</c>, the server
- closes the connection. The server closes it even if there are
+ requests defined by <c>max_keep_alive_requests</c>, the server
+ closes the connection. The server closes it even if there are
queued request. Default is no limit.</p>
</item>
-
+
<tag><marker id="max_client_body_chunk"></marker>{max_client_body_chunk, integer()}</tag>
<item>
<p>Enforces chunking of a HTTP PUT or POST body data to be delivered
- to the mod_esi callback. Note this is not supported for mod_cgi.
+ to the mod_esi callback. Note this is not supported for mod_cgi.
Default is no limit e.i the whole body is delivered as one entity, which could
be very memory consuming. <seeerl marker="mod_esi">mod_esi(3)</seeerl>.
</p>
</item>
-
+
</taglist>
-
+
<marker id="props_admin"></marker>
<p><em>Administrative Properties</em></p>
- <taglist>
+ <taglist>
<tag><marker id="prop_mime_types"></marker>{mime_types, [{MimeType, Extension}] | path()}</tag>
<item>
<p><c>MimeType = string()</c> and <c>Extension = string()</c>.
Files delivered to the client are MIME typed according to RFC
1590. File suffixes are mapped to MIME types before file delivery.
The mapping between file suffixes and MIME types can be specified
- as an Apache-like file or directly in the property list. Such
- a file can look like the following:</p>
- <pre>
-# MIME type Extension
-text/html html htm
-text/plain asc txt</pre>
-
+ in the property list.</p>
<p>Default is [{"html","text/html"},{"htm","text/html"}].</p>
</item>
@@ -290,7 +289,7 @@ text/plain asc txt</pre>
cannot be determined by the MIME Type Settings, the server
uses this default type.</p>
</item>
-
+
<tag><marker id="prop_server_admin"></marker>{server_admin, string()}</tag>
<item>
<p>Defines the email-address of the server
@@ -301,7 +300,7 @@ text/plain asc txt</pre>
<tag><marker id="prop_server_tokens"></marker>{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}</tag>
<item>
<p>Defines the look of the value of the server header.</p>
- <p>Example: Assuming the version of <c>Inets</c> is 5.8.1,
+ <p>Example: Assuming the version of <c>Inets</c> is 5.8.1,
the server header string can look as follows for
the different values of server-tokens:</p>
<taglist>
@@ -325,22 +324,22 @@ text/plain asc txt</pre>
<p>By default, the value is as before, that is, <c>minimal</c>.</p>
</item>
-
+
<tag><marker id="prop_logger"></marker>{logger, Options::list()}</tag>
<item>
<p>Currently only one option is supported: </p>
-
+
<taglist>
<tag><c>{error, ServerID::atom()}</c></tag>
- <item> <p>Produces
+ <item> <p>Produces
<seetype marker="kernel:logger#log_event">logger events</seetype>
on logger <seetype marker="kernel:logger#level">level error</seetype>
under the hierarchical logger <seetype marker="kernel:logger#log_event">domain:</seetype> <c>[otp, inets, httpd, ServerID, error]</c>
- The built in logger formatting
+ The built in logger formatting
function produces log entries from the
error reports:</p>
-
+
<code>
#{server_name => string()
protocol => internal | 'TCP' | 'TLS' | 'HTTP',
@@ -366,12 +365,12 @@ Transport: TLS
</code>
<p>Using this option makes mod_log and mod_disk_log error logs redundant.</p>
-
+
<p>Add the filter</p>
<code>
{fun logger_filters:domain/2,
{log,equal,[otp,inets, httpd, ServerID, error]}</code>
-
+
to appropriate logger handler to handle the events. For
example to write the error log from an httpd server with a
<c>ServerID</c> of <c>my_server</c> to a file you can use the following
@@ -389,24 +388,24 @@ Transport: TLS
</code>
<p>or if you want to add it to the default logger via an API:</p>
-
+
<code>logger:add_handler_filter(default,
inets_httpd,
{fun logger_filters:domain/2,
{log, equal,
[otp, inets, httpd, my_server, error]}}).</code>
-
- </item>
- </taglist>
-
- </item>
-
+
+ </item>
+ </taglist>
+
+ </item>
+
<tag><marker id="prop_log_format"></marker>{log_format, common | combined}</tag>
<item>
<p>Defines if access logs are to be written according to the <c>common</c>
log format or the extended common log format.
The <c>common</c> format is one line looking like this:
- <c>remotehost rfc931 authuser [date] "request" status bytes</c>.</p>
+ <c>remotehost rfc931 authuser [date] "request" status bytes</c>.</p>
<p>Here:</p>
<taglist>
<tag><c>remotehost</c></tag>
@@ -431,90 +430,90 @@ Transport: TLS
<taglist>
<tag><c>"referer"</c></tag>
<item>The URL the client was on before
- requesting the URL (if it could not be determined,
+ requesting the URL (if it could not be determined,
a minus sign is placed in this field).</item>
<tag><c>"user_agent"</c></tag>
<item>The software the client claims to be using (if it
could not be determined, a minus sign is placed in
this field).</item>
</taglist>
-
- <p>This affects the access logs written by <c>mod_log</c> and
+
+ <p>This affects the access logs written by <c>mod_log</c> and
<c>mod_disk_log</c>.
- </p>
- </item>
+ </p>
+ </item>
<tag><marker id="prop_elog_format"></marker>{error_log_format, pretty | compact}</tag>
<item>
<p>Default is <c>pretty</c>. If the error log is meant to be read
directly by a human, <c>pretty</c> is the best option.</p>
<p><c>pretty</c> has a format corresponding to:</p>
-
+
<code>io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).</code>
<p><c>compact</c> has a format corresponding to:</p>
-
+
<code>io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).</code>
- <p>This affects the error logs written by <c>mod_log</c> and
+ <p>This affects the error logs written by <c>mod_log</c> and
<c>mod_disk_log</c>.
</p>
</item>
-
+
</taglist>
-
+
<marker id="props_alias"></marker>
<p><em>URL Aliasing Properties - Requires mod_alias</em></p>
<taglist>
<tag><marker id="prop_alias"></marker>{alias, {Alias, RealName}}</tag>
<item>
- <p><c>Alias = string()</c> and <c>RealName = string()</c>.
+ <p><c>Alias = string()</c> and <c>RealName = string()</c>.
<c>alias</c> allows documents to be stored in the local file
system instead of the <c>document_root</c> location. URLs with a path
beginning with url-path is mapped to local files beginning with
directory-filename, for example:</p>
-
+
<code>{alias, {"/image", "/ftp/pub/image"}}</code>
-
+
<p>Access to http://your.server.org/image/foo.gif would refer to
the file /ftp/pub/image/foo.gif.</p>
</item>
- <tag><marker id="prop_re_write"></marker>{re_write, {Re, Replacement}}</tag>
+ <tag><marker id="prop_re_write"></marker>{re_write, {Re, Replacement}}</tag>
<item>
- <p><c>Re = string()</c> and <c>Replacement = string()</c>.
+ <p><c>Re = string()</c> and <c>Replacement = string()</c>.
<c>re_write</c> allows documents to be stored in the local file
system instead of the <c>document_root</c> location. URLs are rewritten
by <c>re:replace/3</c> to produce a path in the local file-system,
for example:</p>
-
+
<code>{re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}</code>
-
+
<p>Access to http://your.server.org/~bob/foo.gif would refer to
the file /home/bob/public/foo.gif. </p>
</item>
- <tag><marker id="prop_dir_idx"></marker>{directory_index, [string()]}</tag>
- <item>
+ <tag><marker id="prop_dir_idx"></marker>{directory_index, [string()]}</tag>
+ <item>
<p><c>directory_index</c> specifies a list of resources to look for
if a client requests a directory using a <c>/</c> at the end of the
directory name. <c>file</c> depicts the name of a file in the
directory. Several files can be given, in which case the server
returns the first it finds, for example:</p>
-
+
<code>{directory_index, ["index.html", "welcome.html"]}</code>
-
+
<p>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 does not
exist.</p>
- </item>
+ </item>
</taglist>
<marker id="props_cgi"></marker>
<p><em>CGI Properties - Requires mod_cgi</em></p>
- <taglist>
+ <taglist>
<tag><marker id="prop_script_alias"></marker>{script_alias, {Alias, RealName}}</tag>
<item>
<p><c>Alias = string()</c> and <c>RealName = string()</c>.
@@ -522,13 +521,13 @@ Transport: TLS
they also mark 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:</p>
-
+
<code>{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}}</code>
-
+
<p>Access to http://your.server.org/cgi-bin/foo would cause
the server to run the script /web/cgi-bin/foo.</p>
</item>
-
+
<tag><marker id="prop_script_re_write"></marker>{script_re_write, {Re, Replacement}}</tag>
<item>
<p><c>Re = string()</c> and <c>Replacement = string()</c>.
@@ -536,21 +535,21 @@ Transport: TLS
they also mark 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:</p>
-
+
<code>{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}}</code>
-
+
<p>Access to http://your.server.org/cgi-bin/17/foo would cause
the server to run the script /web/17/cgi-bin/foo.</p>
</item>
-
+
<tag><marker id="prop_script_nocache"></marker>{script_nocache, boolean()}</tag>
- <item>
+ <item>
<p>If <c>script_nocache</c> is set to <c>true</c>, the HTTP server by
default adds the header fields necessary to prevent proxies from
- caching the page. Generally this is preferred.
+ caching the page. Generally this is preferred.
Default to <c>false</c>.</p>
</item>
-
+
<tag><marker id="prop_script_timeout"></marker>{script_timeout, integer()}</tag>
<item>
<p>The time in seconds the web server waits between each
@@ -558,7 +557,7 @@ Transport: TLS
any data before the timeout, the connection to the client is
closed. Default is <c>15</c>.</p>
</item>
-
+
<tag><marker id="prop_action"></marker>{action, {MimeType, CgiScript}} - requires mod_action</tag>
<item>
<p><c>MimeType = string()</c> and <c>CgiScript = string()</c>.
@@ -582,24 +581,24 @@ Transport: TLS
the standard CGI PATH_INFO and PATH_TRANSLATED environment
variables.</p>
<p>Example:</p>
-
+
<code>{script, {"PUT", "/cgi-bin/put"}}</code>
-
+
</item>
</taglist>
-
+
<marker id="props_esi"></marker>
<p><em>ESI Properties - Requires mod_esi</em></p>
<taglist>
- <tag><marker id="prop_esi_alias"></marker>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
+ <tag><marker id="prop_esi_alias"></marker>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
<item>
<p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>.
<c>erl_script_alias</c> marks all URLs matching url-path as erl
scheme scripts. A matching URL is mapped into a specific module
and function, for example:</p>
-
+
<code>{erl_script_alias, {"/cgi-bin/example", [httpd_example]}}</code>
-
+
<p>A request to
http://your.server.org/cgi-bin/example/httpd_example:yahoo
would refer to httpd_example:yahoo/3 or, if that does not exist,
@@ -613,7 +612,7 @@ Transport: TLS
<p>If <c>erl_script_nocache</c> is set to <c>true</c>, the server adds
HTTP header fields preventing proxies from caching the
page. This is generally a good idea for dynamic content, as
- the content often varies between each request.
+ the content often varies between each request.
Default is <c>false</c>.</p>
</item>
@@ -625,7 +624,7 @@ Transport: TLS
for scripts that use the erl scheme.</p>
</item>
</taglist>
-
+
<marker id="props_log"></marker>
<p><em>Log Properties - Requires mod_log</em></p>
<taglist>
@@ -644,7 +643,7 @@ Transport: TLS
</item>
<tag><marker id="prop_tlog"></marker>{transfer_log, path()}</tag>
- <item>
+ <item>
<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 <c>server_root</c>.</p>
@@ -690,24 +689,24 @@ Transport: TLS
<tag><marker id="prop_sdlog_size"></marker>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
- <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
+ <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the <c>disk_log(3)</c> access log
file. This file is of type wrap log and
max bytes is written to each file and max files is
used before the first file is truncated and reused.</p>
</item>
- <tag><marker id="prop_tdlog"></marker>{transfer_disk_log, path()}</tag>
+ <tag><marker id="prop_tdlog"></marker>{transfer_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) access log file
logging incoming requests. If the filename does not begin
with a slash (/), it is assumed to be relative to the
<c>server_root</c>.</p>
</item>
-
+
<tag><marker id="prop_tdlog_size"></marker>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
- <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
+ <p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the <c>disk_log(3)</c> access log
file. This file is of type wrap log and
max bytes is written to each file and max files is
@@ -723,26 +722,26 @@ Transport: TLS
<marker id="props_dir"></marker>
<p>The properties for directories are as follows:</p>
-
+
<taglist>
<tag><marker id="prop_allow_from"></marker>{allow_from, all | [RegxpHostString]}</tag>
<item>
<p>Defines a set of hosts to be granted access to a
given directory, for example:</p>
-
+
<code>{allow_from, ["123.34.56.11", "150.100.23"]}</code>
-
+
<p>The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
subnet are allowed access.</p>
</item>
-
+
<tag><marker id="prop_deny_from"></marker>{deny_from, all | [RegxpHostString]}</tag>
<item>
<p>Defines a set of hosts
to be denied access to a given directory, for example:</p>
-
+
<code>{deny_from, ["123.34.56.11", "150.100.23"]}</code>
-
+
<p>The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
subnet are not allowed access.</p>
</item>
@@ -765,9 +764,9 @@ Transport: TLS
by the non-encrypted password. If usernames are duplicated,
the behavior is undefined.</p>
<p>Example:</p>
-
+
<code> ragnar:s7Xxv7
- edward:wwjau8 </code>
+ edward:wwjau8 </code>
<p>If the Dets storage method is used, the user database is
maintained by Dets and must not be edited by hand. Use the
@@ -778,7 +777,7 @@ Transport: TLS
server. If it is placed in the directory that it protects,
clients can download it.</p>
</item>
-
+
<tag><marker id="prop_auth_group_file"></marker>{auth_group_file, path()}</tag>
<item>
<p>Sets the name of a file containing the list of user
@@ -788,9 +787,9 @@ Transport: TLS
each line contains a group name followed by a colon, followed
by the members usernames separated by spaces.</p>
<p>Example:</p>
-
+
<code>group1: bob joe ante</code>
-
+
<p>If the Dets storage method is used, the group database is
maintained by Dets and must not be edited by hand. Use the
API for module <c>mod_auth</c> to create/edit the group database.
@@ -802,9 +801,9 @@ Transport: TLS
</item>
<tag><marker id="prop_auth_name"></marker>{auth_name, string()}</tag>
- <item>
+ <item>
<p>Sets the name of the authorization realm (auth-domain) for
- a directory. This string informs the client about which
+ a directory. This string informs the client about which
username and password to use.</p>
</item>
@@ -817,9 +816,9 @@ Transport: TLS
web server is started. Otherwise it is written in clear
text in the configuration file.</p>
</item>
-
+
<tag><marker id="prop_req_user"></marker>{require_user, [string()]}</tag>
- <item>
+ <item>
<p>Defines users to grant access to a given
directory using a secret password.</p>
</item>
@@ -829,26 +828,26 @@ Transport: TLS
<p>Defines users to grant access to a given
directory using a secret password.</p>
</item>
-
+
</taglist>
<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="props_sdir"></marker>
<p>The properties for the security directories are as follows:</p>
<taglist>
- <tag><marker id="prop_data_file"></marker>{data_file, path()}</tag>
+ <tag><marker id="prop_data_file"></marker>{data_file, path()}</tag>
<item>
<p>Name of the security data file. The filename can either be
absolute or relative to the <c>server_root</c>. This file is used to
store persistent data for module <c>mod_security</c>.</p>
</item>
-
- <tag><marker id="prop_max_retries"></marker>{max_retries, integer()}</tag>
+
+ <tag><marker id="prop_max_retries"></marker>{max_retries, integer()}</tag>
<item>
<p>Specifies the maximum number of attempts to authenticate a
user before the user is blocked out. If a user
@@ -856,45 +855,41 @@ Transport: TLS
user receives a 403 (Forbidden) response from the
server. If the user makes a failed attempt while blocked, the
server returns 401 (Unauthorized), for security
- reasons.
+ reasons.
Default is <c>3</c>. Can be set to infinity.</p>
</item>
-
+
<tag><marker id="prop_block_time"></marker>{block_time, integer()}</tag>
<item>
<p>Specifies the number of minutes a user is blocked. After
this time has passed, the user automatically regains access.
Default is <c>60</c>.</p>
</item>
-
+
<tag><marker id="prop_fail_exp_time"></marker>{fail_expire_time, integer()}</tag>
<item>
<p>Specifies the number of minutes a failed user authentication
is remembered. If a user authenticates after this
time has passed, the previous failed authentications are
- forgotten.
+ forgotten.
Default is <c>30</c>.</p>
</item>
-
+
<tag><marker id="prop_auth_timeout"></marker>{auth_timeout, integer()}</tag>
<item>
Specifies the number of seconds a successful user
authentication is remembered. After this time has passed, the
authentication is no longer reported. Default is <c>30</c>.
</item>
- </taglist>
+ </taglist>
</section>
+
<funcs>
<func>
- <name since="">info(Pid) -></name>
- <name since="">info(Pid, Properties) -> [{Option, Value}]</name>
+ <name since="" name="info" arity="1" />
+ <name since="" name="info" arity="2" clause_i="1"/>
<fsummary>Fetches information about the HTTP server.</fsummary>
- <type>
- <v>Properties = [property()]</v>
- <v>Option = property()</v>
- <v>Value = term()</v>
- </type>
<desc>
<p>Fetches information about the HTTP server. When called
with only the pid, all properties are fetched. When called
@@ -912,43 +907,28 @@ Transport: TLS
</func>
<func>
- <name since="">info(Address, Port) -> </name>
- <name since="">info(Address, Port, Profile) -> </name>
- <name since="OTP 18.0">info(Address, Port, Profile, Properties) -> [{Option, Value}] </name>
- <name since="">info(Address, Port, Properties) -> [{Option, Value}] </name>
+ <name since="" name="info" arity="2" clause_i="2"/>
+ <name since="" name="info" arity="3" clause_i="1"/>
+ <name since="" name="info" arity="3" clause_i="2"/>
+ <name since="OTP 18.0" name="info" arity="4" />
<fsummary>Fetches information about the HTTP server.</fsummary>
- <type>
- <v>Address = ip_address()</v>
- <v>Port = integer()</v>
- <v>Profile = atom()</v>
- <v>Properties = [property()]</v>
- <v>Option = property()</v>
- <v>Value = term()</v>
- </type>
<desc>
- <p>Fetches information about the HTTP server. When called with
- only <c>Address</c> and <c>Port</c>, all properties are
- fetched. When called with a list of specific properties, they
- are fetched. The available properties are the same as the
- start options of the server.
- </p>
-
- <note><p>The address must be the IP address and cannot be
- the hostname.
- </p></note>
+ <p>Fetches information about the HTTP server. When called with only
+ <c><anno>Address</anno></c> and <c><anno>Port</anno></c>, all properties
+ are fetched. When called with a list of specific properties, they are
+ fetched. The available properties are the same as the start options of
+ the server.
+ </p>
+
+ <note><p>The <c>Address</c> must be the IP address and
+ cannot be the hostname. </p></note>
</desc>
</func>
<func>
- <name since="">reload_config(Config, Mode) -> ok | {error, Reason}</name>
+ <name since="" name="reload_config" arity="2"/>
<fsummary>Reloads the HTTP server configuration without
restarting the server.</fsummary>
- <type>
- <v>Config = path() | [{Option, Value}]</v>
- <v>Option = property()</v>
- <v>Value = term()</v>
- <v>Mode = non_disturbing | disturbing</v>
- </type>
<desc>
<p>Reloads the HTTP server configuration without restarting the
server. Incoming requests are answered with a temporary
@@ -1163,19 +1143,13 @@ Transport: TLS
<title>ERLANG WEB SERVER API HELP FUNCTIONS</title>
</fsdescription>
<func>
- <name since="">parse_query(QueryString) -> [{Key,Value}]</name>
+ <name since="" name="parse_query" arity="1"/>
<fsummary>Parses incoming data to <c>erl</c> and <c>eval</c> scripts.</fsummary>
- <type>
- <v>QueryString = string()</v>
- <v>Key = string()</v>
- <v>Value = string()</v>
- </type>
<desc>
<p><c>parse_query/1</c> parses incoming data to <c>erl</c> and
- <c>eval</c> scripts (see <seeerl marker="mod_esi">mod_esi(3)</seeerl>)
- as defined in the standard
- URL format, that is, '+' becomes 'space' and decoding of
- hexadecimal characters (<c>%xx</c>).</p>
+ <c>eval</c> scripts (see <seeerl marker="mod_esi">mod_esi(3)</seeerl>)
+ as defined in the standard URL format, that is, '+' becomes 'space' and
+ decoding of hexadecimal characters (<c>%xx</c>).</p>
</desc>
</func>
</funcs>
diff --git a/lib/inets/doc/src/httpd_util.xml b/lib/inets/doc/src/httpd_util.xml
index 60a147399d..a334ec9f86 100644
--- a/lib/inets/doc/src/httpd_util.xml
+++ b/lib/inets/doc/src/httpd_util.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,7 +35,8 @@
<description>
<p>This module provides the Erlang web server API module
programmer with miscellaneous utility functions.</p>
-
+ <note><p>Note the module is only recommended for using with httpd - for other
+ cases it should be considered as deprecated.</p></note>
<marker id="convert_request_date"></marker>
</description>
@@ -263,7 +264,10 @@
<name since="">reason_phrase(StatusCode) -> Description</name>
<fsummary>Returns the description of an HTTP 1.1 status code.</fsummary>
<type>
- <v>StatusCode = 100| 200 | 201 | 202 | 204 | 205 | 206 | 300 | 301 | 302 | 303 | 304 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 410 411 | 412 | 413 | 414 415 | 416 | 417 | 500 | 501 | 502 | 503 | 504 | 505</v>
+ <v>StatusCode = 100 | 200 | 201 | 202 | 204 | 205 | 206 | 300 | 301 |
+ 302 | 303 | 304 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 |
+ 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 500 | 501 | 502 |
+ 503 | 504 | 505</v>
<v>Description = string()</v>
</type>
<desc>
diff --git a/lib/inets/doc/src/mod_esi.xml b/lib/inets/doc/src/mod_esi.xml
index 8018e7433d..9bdaac7a95 100644
--- a/lib/inets/doc/src/mod_esi.xml
+++ b/lib/inets/doc/src/mod_esi.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -177,24 +177,7 @@
any data that it needs to keep track of when handling the chunks.
</p>
</desc>
- </func>
-
- <func>
- <name since="">Module:Function(Env, Input)-> Response </name>
- <fsummary>Creates a dynamic web page and returns it as a list.
- This function is deprecated and is only kept for backwards compatibility.</fsummary>
- <type>
- <v>Env = env()</v>
- <v>Input = string() </v>
- <v>Response = string()</v>
- </type>
- <desc>
- <p>This callback format consumes much memory, as the
- whole response must be generated before it is sent to the
- user. This callback format is deprecated.
- For new development, use <c>Module:Function/3</c>.</p>
- </desc>
- </func>
+ </func>
</funcs>
</erlref>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 867980a3bd..d935ad2f11 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>2022</year>
+ <year>2002</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,7 +33,282 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 7.5.3</title>
+ <section><title>Inets 8.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, handling of URI to a folder, with
+ missing trailing / and a query component present is
+ fixed.</p>
+ <p>
+ Own Id: OTP-18472 Aux Id: DAFH-1592 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Adds more type information to the <c>inets</c> app, thus
+ improving the errors that static analysis tools can
+ detect.</p>
+ <p>
+ The addition of type information to records and the
+ updates to function heads help static analysis tools to
+ understand that some values in the records cannot be
+ <c>'undefined'</c>, thus making static tools to type
+ check correctly more modules in the <c>inets</c> app</p>
+ <p>
+ Own Id: OTP-18390 Aux Id: PR-6661 </p>
+ </item>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 8.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Ensure graceful shutdown</p>
+ <p>
+ Own Id: OTP-18461 Aux Id: ERIERL-890 </p>
+ </item>
+ <item>
+ <p>
+ Return type of the type specification for function
+ <c>httpc:cookie_header/{1,2,3}</c> has been fixed from
+ <c>-spec cookie_header(url()) -&gt; [{ field(), value()
+ }] | {error, Reason}</c> to <c>-spec cookie_header(url())
+ -&gt; { field(), value() } | {error, Reason}</c></p>
+ <p>
+ Own Id: OTP-18462 Aux Id: GH-6846 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 8.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ fixes a missing case of the type specification for
+ httpd:info/2/3/4</p>
+ <p>
+ Own Id: OTP-18362 Aux Id: GH-6558, ERIERL-895 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 8.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ This change allows body requests to
+ <c>httpc:request/5</c> be an <c>iolist()</c></p>
+ <p>
+ Own Id: OTP-18250</p>
+ </item>
+ <item>
+ <p>
+ addition of type specs in <c>httpc.erl</c></p>
+ <p>
+ Own Id: OTP-18251 Aux Id: GH-6245 </p>
+ </item>
+ <item>
+ <p>
+ httpc: Add support for HTTP 308 status code</p>
+ <p>
+ Own Id: OTP-18280 Aux Id: GH-6290, PR-6291 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 8.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add <c>httpc:ssl_verify_host_options/1</c> to help
+ setting default ssl options for the https client.</p>
+ <p>
+ Own Id: OTP-18118</p>
+ </item>
+ <item>
+ <p>
+ This change fixes dialyzer warnings generated for
+ inets/httpd examples (includes needed adjustment of spec
+ for ssh_sftp module).</p>
+ <p>
+ Own Id: OTP-18178 Aux Id: ERIERL-833, ERIERL-834,
+ ERIERL-835 </p>
+ </item>
+ <item>
+ <p>
+ Remove documentation of no longer supported callback.</p>
+ <p>
+ Own Id: OTP-18193 Aux Id: GH-6122 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 8.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Adjust uri_string:normalize behavior for URIs with
+ undefined port (URI string with a port colon but no port
+ value or URI map with port => undefined).</p>
+ <p>
+ Remove redundant normalization from http_request module.</p>
+ <p>
+ Before this change, normalize would not remove port
+ subcomponent in such cases and could for example return
+ "http://localhost:" URI.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17627</p>
+ </item>
+ <item>
+ <p>
+ Fixed typo in Reason term returned from
+ httpc_handler:handle_http_body.</p>
+ <p>
+ After this change, could_not_establish_ssl_tunnel atom is
+ returned within Reason term.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17889</p>
+ </item>
+ <item>
+ <p>
+ With this change, inet6fb4 option is documented for
+ inets/httpc. Option can be used when IP family needs to
+ be discovered by a connection attempt.</p>
+ <p>
+ Own Id: OTP-18063 Aux Id: ERIERL-798 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ This change removes deprecated functions:
+ http_uri:parse/1, http_uri:parse/2 and
+ http_uri:scheme_defaults/0.</p>
+ <p>
+ This change delays until OTP-26 removal of deprecated
+ functions: http_uri:encode/1 and http_uri:decode/1.</p>
+ <p>
+ This change marks httpd_util:decode_hex/1 and
+ httpd_util:encode_hex/1 as deprecated.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17866</p>
+ </item>
+ <item>
+ <p>
+ After this change, connect_timeout value is re-used when
+ upgrading TCP connection to TLS over a proxy.</p>
+ <p>
+ Own Id: OTP-17997 Aux Id: GH-5782 </p>
+ </item>
+ <item>
+ <p>
+ Remove reference to unsupported Apache-like config file
+ from httpd manual.</p>
+ <p>
+ Own Id: OTP-18088 Aux Id: GH-5276 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Inets 7.5.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, handling of URI to a folder, with
+ missing trailing / and a query component present is
+ fixed.</p>
+ <p>
+ Own Id: OTP-18472 Aux Id: DAFH-1592 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Inets 7.5.3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Remove documentation of no longer supported callback.</p>
+ <p>
+ Own Id: OTP-18193 Aux Id: GH-6122 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.5.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -233,6 +508,21 @@
</section>
+ <section><title>Inets 7.3.2.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Remove documentation of no longer supported callback.</p>
+ <p>
+ Own Id: OTP-18193 Aux Id: GH-6122 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Inets 7.3.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2568,8 +2858,7 @@
<p>Utility module
<seeerl marker="http_uri">http_uri</seeerl>
now officially supported. </p>
- <p>Also, the
- <seeerl marker="http_uri#parse">parse</seeerl>
+ <p>Also, the <c>http_uri:parse</c>
function has been extended with more
scheme support and a way to provide your own scheme info. </p>
<p>Own Id: OTP-9983</p>
diff --git a/lib/inets/doc/src/specs.xml b/lib/inets/doc/src/specs.xml
new file mode 100644
index 0000000000..82f2f4cfc2
--- /dev/null
+++ b/lib/inets/doc/src/specs.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_inets.xml"/>
+ <xi:include href="../specs/specs_http_uri.xml"/>
+ <xi:include href="../specs/specs_httpc.xml"/>
+ <xi:include href="../specs/specs_httpd.xml"/>
+ <xi:include href="../specs/specs_httpd_custom_api.xml"/>
+ <xi:include href="../specs/specs_httpd_socket.xml"/>
+ <xi:include href="../specs/specs_httpd_util.xml"/>
+ <xi:include href="../specs/specs_mod_alias.xml"/>
+ <xi:include href="../specs/specs_mod_auth.xml"/>
+ <xi:include href="../specs/specs_mod_esi.xml"/>
+ <xi:include href="../specs/specs_mod_security.xml"/>
+</specs>
diff --git a/lib/inets/examples/httpd_load_test/Makefile b/lib/inets/examples/httpd_load_test/Makefile
index 8b1b654593..19edf10cb0 100644
--- a/lib/inets/examples/httpd_load_test/Makefile
+++ b/lib/inets/examples/httpd_load_test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -77,8 +77,8 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl b/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
index c3236545da..7ecf6c3876 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_ctrl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
%%----------------------------------------------------------------------
-module(hdlt_ctrl).
-
+-dialyzer({no_fail_call, proxy_loop/1}).
-export([start/1, stop/0, help/0]).
-export([init/1, proxy/7]).
diff --git a/lib/inets/examples/httpd_load_test/hdlt_slave.erl b/lib/inets/examples/httpd_load_test/hdlt_slave.erl
index 185c8b0e51..2c15db21d5 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_slave.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_slave.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -108,7 +108,7 @@ wait_for_slave(Parent, Host, Name, Node, Paths, Args,
?SET_LEVEL(DebugLevel),
?DEBUG("begin", []),
Waiter = register_unique_name(0),
- case mk_cmd(Host, Name, Paths, Args, Waiter, Prog) of
+ case (catch mk_cmd(Host, Name, Paths, Args, Waiter, Prog)) of
{ok, Cmd} ->
?DEBUG("command generated: ~n~s", [Cmd]),
case (catch ssh_slave_start(Host, Cmd)) of
diff --git a/lib/inets/examples/server_root/Makefile b/lib/inets/examples/server_root/Makefile
index d11389f0a7..5dfb8d1704 100644
--- a/lib/inets/examples/server_root/Makefile
+++ b/lib/inets/examples/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -163,7 +163,7 @@ ERL_COMPILE_FLAGS +=
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/inets/priv/Makefile b/lib/inets/priv/Makefile
index ddd35e8625..0f10e8d3ce 100644
--- a/lib/inets/priv/Makefile
+++ b/lib/inets/priv/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ ERL_COMPILE_FLAGS +=
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile
index a1c1f36b70..62f62792f0 100644
--- a/lib/inets/src/http_client/Makefile
+++ b/lib/inets/src/http_client/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2016. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -77,7 +77,7 @@ ERL_COMPILE_FLAGS += \
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl
index 96906148c7..96d5cd250d 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@
stream_next/1,
default_profile/0,
profile_name/1, profile_name/2,
+ ssl_verify_host_options/1,
info/0, info/1
]).
@@ -52,12 +53,12 @@
stop_service/1,
services/0, service_info/1]).
+
-include_lib("inets/src/http_lib/http_internal.hrl").
-include("httpc_internal.hrl").
-define(DEFAULT_PROFILE, default).
-
%%%=========================================================================
%%% API
%%%=========================================================================
@@ -65,7 +66,8 @@
default_profile() ->
?DEFAULT_PROFILE.
-
+-spec profile_name(pid()) -> pid();
+ (atom()) -> pid() | atom().
profile_name(?DEFAULT_PROFILE) ->
httpc_manager;
profile_name(Profile) when is_pid(Profile) ->
@@ -74,85 +76,169 @@ profile_name(Profile) ->
Prefix = lists:flatten(io_lib:format("~w_", [?MODULE])),
profile_name(Prefix, Profile).
+
profile_name(Prefix, Profile) when is_atom(Profile) ->
list_to_atom(Prefix ++ atom_to_list(Profile));
profile_name(_Prefix, Profile) when is_pid(Profile) ->
Profile.
-%%--------------------------------------------------------------------------
-%% request(Url) -> {ok, {StatusLine, Headers, Body}} | {error,Reason}
-%% request(Url Profile) ->
-%% {ok, {StatusLine, Headers, Body}} | {error,Reason}
-%%
-%% Url - string()
-%% Description: Calls request/4 with default values.
-%%--------------------------------------------------------------------------
-
+-spec request(uri_string:uri_string()) -> {ok, Result} | {error, term()} when
+ Result :: {StatusLine :: { HttpVersion, StatusCode, string()}
+ , [HttpHeader]
+ , HttpBodyResult}
+ | { StatusCode
+ , HttpBodyResult}
+ | RequestId
+ | saved_to_file,
+ HttpBodyResult :: uri_string:uri_string() | binary(),
+ HttpVersion :: uri_string:uri_string(),
+ StatusCode :: non_neg_integer(),
+ HttpHeader :: { Field :: [byte()]
+ , Value :: binary() | iolist()},
+ RequestId :: any().
request(Url) ->
request(Url, default_profile()).
+-spec request(Url, Profile) -> {ok, Result} | {error, term()} when
+ Url :: uri_string:uri_string(),
+ Profile :: atom() | pid(),
+ Result ::{ StatusLine, [HttpHeader], HttpBodyResult}
+ | { StatusCode, HttpBodyResult}
+ | RequestId
+ | saved_to_file,
+ HttpHeader :: { Field :: [byte()]
+ , Value :: binary() | iolist()},
+ HttpBodyResult :: uri_string:uri_string() | binary(),
+ StatusLine :: { HttpVersion
+ , StatusCode
+ , string()},
+ HttpVersion :: uri_string:uri_string(),
+ StatusCode :: non_neg_integer(),
+ RequestId :: any().
request(Url, Profile) ->
request(get, {Url, []}, [], [], Profile).
-
-%%--------------------------------------------------------------------------
-%% request(Method, Request, HTTPOptions, Options [, Profile]) ->
-%% {ok, {StatusLine, Headers, Body}}
-%% | {ok, {Status, Body}}
-%% | {ok, RequestId}
-%% | {ok, {saved_as, FilePath}
-%% | {error, Reason}
%%
-%% Method - atom() = head | get | put | patch | post | trace |
-%% options | delete
-%% Request - {Url, Headers} | {Url, Headers, ContentType, Body}
-%% Url - string()
-%% HTTPOptions - [HttpOption]
-%% HTTPOption - {timeout, Time} | {connect_timeout, Time} |
-%% {ssl, SSLOptions} | {proxy_auth, {User, Password}}
-%% Ssloptions = ssl_options() |
-%% {ssl, ssl_options()} |
-%% {essl, ssl_options()}
-%% ssl_options() = [ssl_option()]
-%% ssl_option() = {verify, code()} |
-%% {depth, depth()} |
-%% {certfile, path()} |
-%% {keyfile, path()} | {password, string()} | {cacertfile, path()} |
-%% {ciphers, string()}
-%% Options - [Option]
-%% Option - {sync, Boolean} |
-%% {body_format, BodyFormat} |
-%% {full_result, Boolean} |
-%% {stream, To} |
-%% {headers_as_is, Boolean}
-%% StatusLine = {HTTPVersion, StatusCode, ReasonPhrase}</v>
-%% HTTPVersion = string()
-%% StatusCode = integer()
-%% ReasonPhrase = string()
-%% Headers = [Header]
-%% Header = {Field, Value}
-%% Field = [byte()]
-%% Value = binary() | iolist()
-%% Body = string() | binary() | {fun(SendAcc) -> SendFunResult, SendAcc} |
-%% {chunkify, fun(SendAcc) -> SendFunResult, SendAcc} - HTML-code
-%% SendFunResult = eof | {ok, iolist(), NewSendAcc}
-%% SendAcc = NewSendAcc = term()
-%%
-%% Description: Sends a HTTP-request. The function can be both
-%% synchronous and asynchronous in the later case the function will
-%% return {ok, RequestId} and later on a message will be sent to the
-%% calling process on the format {http, {RequestId, {StatusLine,
-%% Headers, Body}}} or {http, {RequestId, {error, Reason}}}.
-%% Only octects are accepted in header fields and values.
-%%--------------------------------------------------------------------------
-
+%% @doc Sends a HTTP-request. The function can be both synchronous and
+%% asynchronous in the later case the function will return `{ok, RequestId}' and
+%% and then the information is delivered to the receiver depending on that
+%% value.
+-spec request(Method, Request, HttpOptions, Options) -> {ok, Result} | {error, term()} when
+ Method :: head | get | put | patch | post | trace | options | delete,
+ Request :: { uri_string:uri_string()
+ , [HttpHeader] }
+ | { uri_string:uri_string()
+ , [ HttpHeader ]
+ , ContentType::uri_string:uri_string()
+ , HttpBody},
+ HttpBody :: iolist()
+ | binary()
+ | { fun((Accumulator::term()) ->
+ eof | {ok, iolist(), Accumulator::term()}), Accumulator::term()}
+ | { chunkify
+ , fun((Accumulator::term()) ->
+ eof | {ok, iolist(), Accumulator::term()})
+ , Accumulator::term() },
+ HttpOptions :: [HttpOption],
+ HttpOption :: {timeout, timeout()}
+ | {connect_timeout, timeout()}
+ | {ssl, [ssl:tls_option()]}
+ | {autoredirect, boolean()}
+ | {proxy_auth, {string(), string()}}
+ | {version, HttpVersion} | {relaxed, boolean()},
+ Options :: [OptionRequest],
+ OptionRequest :: {sync, boolean()}
+ | {stream, StreamTo}
+ | {body_format, BodyFormat}
+ | {full_result, boolean()}
+ | {headers_as_is, boolean()}
+ | {socket_opts, [SocketOpt]}
+ | {receiver, Receiver}
+ | {ipv6_host_with_brackets, boolean()},
+ StreamTo :: none | self | {self, once} | file:name_all(),
+ SocketOpt :: term(),
+ BodyFormat :: string() | binary() | atom(),
+ Receiver :: pid()
+ | fun((term()) -> term())
+ | { ReceiverModule::atom()
+ , ReceiverFunction::atom()
+ , ReceiverArgs::list()},
+ Result :: { StatusLine , [HttpHeader], HttpBodyResult}
+ | { StatusCode, HttpBodyResult}
+ | RequestId
+ | saved_to_file,
+ StatusCode::non_neg_integer(),
+ StatusLine :: { HttpVersion
+ , StatusCode
+ , string()},
+ HttpVersion :: uri_string:uri_string(),
+ HttpHeader :: { Field :: [byte()]
+ , Value :: binary() | iolist()},
+ HttpBodyResult :: uri_string:uri_string() | binary(),
+ RequestId :: any().
request(Method, Request, HttpOptions, Options) ->
request(Method, Request, HttpOptions, Options, default_profile()).
+
-define(WITH_BODY, [post, put, patch, delete]).
-define(WITHOUT_BODY, [get, head, options, trace, put, delete]).
+-spec request(Method, Request, HttpOptions, Options, Profile) -> {ok, Result} | {error, term()} when
+ Method :: head | get | put | patch | post | trace | options | delete,
+ Request :: { uri_string:uri_string()
+ , [HttpHeader] }
+ | { uri_string:uri_string()
+ , [ HttpHeader ]
+ , ContentType::uri_string:uri_string()
+ , HttpBody},
+ HttpBody :: iolist()
+ | binary()
+ | { fun((Accumulator::term()) ->
+ eof | {ok, iolist(), Accumulator::term()}), Accumulator::term()}
+ | { chunkify
+ , fun((Accumulator::term()) ->
+ eof | {ok, iolist(), Accumulator::term()})
+ , Accumulator::term() },
+ HttpHeader :: { Field :: [byte()]
+ , Value :: binary() | iolist()},
+ HttpOptions :: [HttpOption],
+ HttpOption :: {timeout, timeout()}
+ | {connect_timeout, timeout()}
+ | {ssl, [ssl:tls_option()]}
+ | {autoredirect, boolean()}
+ | {proxy_auth, {string(), string()}}
+ | {version, HttpVersion} | {relaxed, boolean()},
+ Options :: [OptionRequest],
+ OptionRequest :: {sync, boolean()}
+ | {stream, StreamTo}
+ | {body_format, BodyFormat}
+ | {full_result, boolean()}
+ | {headers_as_is, boolean()}
+ | {socket_opts, [SocketOpt]}
+ | {receiver, Receiver}
+ | {ipv6_host_with_brackets, boolean()},
+ StreamTo :: none | self | {self, once} | file:name_all(),
+ BodyFormat :: string() | binary() | atom(),
+ SocketOpt :: term(),
+ Receiver :: pid()
+ | fun((term()) -> term())
+ | { ReceiverModule::atom()
+ , ReceiverFunction::atom()
+ , ReceiverArgs::list()},
+ Profile :: atom() | pid(),
+ HttpVersion :: uri_string:uri_string(),
+ Result :: {StatusLine
+ , [HttpHeader]
+ , HttpBodyResult}
+ | { StatusCode
+ , HttpBodyResult}
+ | RequestId
+ | saved_to_file,
+ StatusLine :: { HttpVersion, StatusCode, string()},
+ StatusCode :: non_neg_integer(),
+ HttpBodyResult :: uri_string:uri_string() | binary(),
+ RequestId :: any().
request(Method, Request, HTTPOptions, Options, Profile)
when is_atom(Profile) orelse is_pid(Profile) ->
WithBody = lists:member(Method, ?WITH_BODY),
@@ -173,12 +259,12 @@ do_request(Method, {Url, Headers, ContentType, Body}, HTTPOptions, Options, Prof
{error, Reason};
ParsedUrl ->
case header_parse(Headers) of
- {error, Reason} ->
- {error, Reason};
- ok ->
- handle_request(Method, Url,
- ParsedUrl, Headers, ContentType, Body,
- HTTPOptions, Options, Profile)
+ {error, Reason} ->
+ {error, Reason};
+ ok ->
+ handle_request(Method, Url,
+ ParsedUrl, Headers, ContentType, Body,
+ HTTPOptions, Options, Profile)
end
end.
@@ -197,39 +283,104 @@ check_request(true, _, {_URL, _Headers, ContentType, Body})
check_request(_, _, _Request) ->
{error, invalid_request}.
-%%--------------------------------------------------------------------------
-%% cancel_request(RequestId) -> ok
-%% cancel_request(RequestId, Profile) -> ok
-%% RequestId - As returned by request/4
-%%
-%% Description: Cancels a HTTP-request.
-%%-------------------------------------------------------------------------
+%%
+%% @doc Description: Cancels a HTTP-request.
+%%
+-spec cancel_request(RequestId) -> ok when
+ RequestId :: any().
cancel_request(RequestId) ->
cancel_request(RequestId, default_profile()).
-cancel_request(RequestId, Profile)
+%%
+%% @doc Cancels an asynchronous HTTP request. Notice that this does not
+%% guarantee that the request response is not delivered. Because it is
+%% asynchronous, the request can already have been completed when the
+%% cancellation arrives.
+%%
+-spec cancel_request(RequestId, Profile) -> ok when
+ RequestId :: any(),
+ Profile :: atom() | pid().
+cancel_request(RequestId, Profile)
when is_atom(Profile) orelse is_pid(Profile) ->
httpc_manager:cancel_request(RequestId, profile_name(Profile)).
-%%--------------------------------------------------------------------------
-%% set_options(Options) -> ok | {error, Reason}
-%% set_options(Options, Profile) -> ok | {error, Reason}
-%% Options - [Option]
-%% Profile - atom()
-%% Option - {proxy, {Proxy, NoProxy}} | {max_sessions, MaxSessions} |
-%% {max_pipeline_length, MaxPipeline} |
-%% {pipeline_timeout, PipelineTimeout} | {cookies, CookieMode} |
-%% {ipfamily, IpFamily}
-%% Proxy - {Host, Port}
-%% NoProxy - [Domain | HostName | IPAddress]
-%% MaxSessions, MaxPipeline, PipelineTimeout = integer()
-%% CookieMode - enabled | disabled | verify
-%% IpFamily - inet | inet6 | inet6fb4
-%% Description: Informs the httpc_manager of the new settings.
-%%-------------------------------------------------------------------------
+%% @doc Sets options to be used for subsequent requests.
+%% @see set_options/2. Informs the httpc_manager of the new settings.
+-spec set_options(Options) -> ok | {error, Reason} when
+ Options :: [Option],
+ Option :: {proxy, {Proxy, NoProxy}}
+ | {https_proxy, {Proxy, NoProxy}}
+ | {max_sessions, MaxSessions}
+ | {max_keep_alive_length, MaxKeepAlive}
+ | {keep_alive_timeout, KeepAliveTimeout}
+ | {max_pipeline_length, MaxPipeline}
+ | {pipeline_timeout, PipelineTimeout}
+ | {cookies, CookieMode}
+ | {ipfamily, IpFamily}
+ | {ip, IpAddress}
+ | {port, Port}
+ | {socket_opts, SocketOpts}
+ | {verbose, VerboseMode}
+ | {unix_socket, UnixSocket},
+ Proxy :: {HostName, Port},
+ Port :: non_neg_integer(),
+ NoProxy :: [DomainDesc | HostName | IpAddressDesc],
+ MaxSessions :: integer(),
+ MaxKeepAlive :: integer(),
+ KeepAliveTimeout :: integer(),
+ MaxPipeline :: integer(),
+ PipelineTimeout :: integer(),
+ CookieMode :: enabled | disabled | verify,
+ IpFamily :: inet | inet6 | local | inet6fb4,
+ IpAddressDesc :: uri_string:uri_string(),
+ IpAddress :: inet:ip_address(),
+ VerboseMode :: false | verbose | debug | trace,
+ SocketOpts :: [SocketOpt],
+ SocketOpt :: term(),
+ UnixSocket :: file:name_all(),
+ Reason :: term(),
+ DomainDesc :: string(),
+ HostName :: uri_string:uri_string().
set_options(Options) ->
set_options(Options, default_profile()).
+
+%% @doc Sets options to be used for subsequent requests.
+-spec set_options(Options, Profile) -> ok | {error, Reason} when
+ Options :: [Option],
+ Option :: {proxy, {Proxy, NoProxy}}
+ | {https_proxy, {Proxy, NoProxy}}
+ | {max_sessions, MaxSessions}
+ | {max_keep_alive_length, MaxKeepAlive}
+ | {keep_alive_timeout, KeepAliveTimeout}
+ | {max_pipeline_length, MaxPipeline}
+ | {pipeline_timeout, PipelineTimeout}
+ | {cookies, CookieMode}
+ | {ipfamily, IpFamily}
+ | {ip, IpAddress}
+ | {port, Port}
+ | {socket_opts, [SocketOpt]}
+ | {verbose, VerboseMode}
+ | {unix_socket, UnixSocket},
+ Profile :: atom() | pid(),
+ SocketOpt :: term(),
+ Proxy :: {HostName, Port},
+ Port :: non_neg_integer(),
+ NoProxy :: [DomainDesc | HostName | IpAddressDesc],
+ MaxSessions :: integer(),
+ MaxKeepAlive :: integer(),
+ KeepAliveTimeout :: integer(),
+ MaxPipeline :: integer(),
+ PipelineTimeout :: integer(),
+ CookieMode :: enabled | disabled | verify,
+ IpFamily :: inet | inet6 | local | inet6fb4,
+ IpAddressDesc :: uri_string:uri_string(),
+ IpAddress :: inet:ip_address(),
+ VerboseMode :: false | verbose | debug | trace,
+ UnixSocket :: string(),
+ Reason :: term(),
+ DomainDesc :: string(),
+ HostName :: uri_string:uri_string().
set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) ->
case validate_options(Options) of
{ok, Opts} ->
@@ -238,33 +389,43 @@ set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) ->
{error, Reason}
end.
+-spec set_option(atom(), term()) -> ok | {error, term()}.
set_option(Key, Value) ->
set_option(Key, Value, default_profile()).
+-spec set_option(atom(), term(), atom()) -> ok | {error, term()}.
set_option(Key, Value, Profile) ->
set_options([{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.
-%%-------------------------------------------------------------------------
-
+-spec get_options() -> term().
get_options() ->
record_info(fields, options).
+%%
+%% @doc Retrieves the options currently used by the client.
+%%
+-spec get_options(OptionItems) -> {ok, Values} | {error, Reason} when
+ OptionItems :: all | [OptionItem],
+ OptionItem :: proxy | https_proxy | max_sessions | keep_alive_timeout
+ | max_keep_alive_length | pipeline_timeout | max_pipeline_length | cookies
+ | ipfamily | ip | port | socket_opts | verbose | unix_socket,
+ Values :: [{OptionItem, term()}],
+ Reason :: term().
get_options(Options) ->
get_options(Options, default_profile()).
+%%
+%% @doc Retrieves the options currently used by the client.
+%%
+-spec get_options(OptionItems, Profile) -> {ok, Values} | {error, Reason} when
+ OptionItems :: all | [OptionItem],
+ OptionItem :: proxy | https_proxy | max_sessions | keep_alive_timeout
+ | max_keep_alive_length | pipeline_timeout | max_pipeline_length | cookies
+ | ipfamily | ip | port | socket_opts | verbose | unix_socket,
+ Values :: [{OptionItem, term()}],
+ Profile :: atom() | pid(),
+ Reason :: term().
get_options(all = _Options, Profile) ->
get_options(get_options(), Profile);
get_options(Options, Profile)
@@ -296,19 +457,42 @@ get_option(Key, Profile) ->
Error
end.
-
%%--------------------------------------------------------------------------
-%% store_cookies(SetCookieHeaders, Url [, Profile]) -> ok | {error, reason}
-%%
-%%
-%% Description: Store the cookies from <SetCookieHeaders>
-%% in the cookie database
-%% for the profile <Profile>. This function shall be used when the option
-%% cookies is set to verify.
-%%-------------------------------------------------------------------------
+%% Default client ssl options to verify server
+%%
+%% WildcardHostName=true does wildcard matching on the hostname check
+%%--------------------------------------------------------------------------
+-spec ssl_verify_host_options(WildcardHostName) -> list() when
+ WildcardHostName :: boolean().
+ssl_verify_host_options(WildcardHostName) ->
+ WildCard = case WildcardHostName of
+ true ->
+ Fun = public_key:pkix_verify_hostname_match_fun(https),
+ [{customize_hostname_check,[{match_fun, Fun}]}];
+ false ->
+ []
+ end,
+ [{verify, verify_peer}, {cacerts, public_key:cacerts_get()} | WildCard].
+
+
+-spec store_cookies(SetCookieHeaders, Url) -> ok | {error, Reason} when
+ SetCookieHeaders :: [HttpHeader],
+ HttpHeader :: { Field :: [byte()], Value :: binary() | iolist()},
+ Url :: term(),
+ Reason :: term().
store_cookies(SetCookieHeaders, Url) ->
store_cookies(SetCookieHeaders, Url, default_profile()).
+%%
+%% @doc Saves the cookies defined in `SetCookieHeaders; in the client profile
+%% cookie database. Call this function if option `cookies' is set to `verify'. If no
+%% profile is specified, the default profile is used.
+-spec store_cookies(SetCookieHeaders, Url, Profile) -> ok | {error, Reason} when
+ SetCookieHeaders :: [HttpHeader],
+ HttpHeader :: { Field :: [byte()], Value :: binary() | iolist()},
+ Url :: term(),
+ Profile :: atom() | pid(),
+ Reason :: term().
store_cookies(SetCookieHeaders, Url, Profile)
when is_atom(Profile) orelse is_pid(Profile) ->
case normalize_and_parse_url(Url) of
@@ -334,23 +518,40 @@ default_port(http) ->
default_port(https) ->
443.
-%%--------------------------------------------------------------------------
-%% 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>.
-%%-------------------------------------------------------------------------
+
+-spec cookie_header(Url) -> HttpHeader | {error, Reason} when
+ Url :: uri_string:uri_string(),
+ HttpHeader :: { Field :: [byte()], Value :: binary() | iolist()},
+ Reason :: term().
cookie_header(Url) ->
cookie_header(Url, default_profile()).
+-spec cookie_header(Url, ProfileOrOpts) -> HttpHeader | {error, Reason} when
+ Url :: uri_string:uri_string(),
+ HttpHeader :: { Field :: [byte()], Value :: binary() | iolist()},
+ ProfileOrOpts :: Profile | Opts,
+ Profile :: atom() | pid(),
+ Opts :: [CookieHeaderOpt],
+ CookieHeaderOpt :: {ipv6_host_with_brackets, boolean()},
+ Reason :: term().
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)
+%%
+%% @doc Returns the cookie header that would have been sent when making a
+%% request to Url using profile Profile. If no profile is specified, the default
+%% profile is used.
+%%
+-spec cookie_header(Url, Opts, Profile) -> HttpHeader | {error, Reason} when
+ Url :: uri_string:uri_string(),
+ HttpHeader :: { Field :: [byte()], Value :: binary() | iolist()},
+ Profile :: atom() | pid(),
+ Opts :: [CookieHeaderOpt],
+ CookieHeaderOpt :: {ipv6_host_with_brackets, boolean()},
+ Reason :: term().
+cookie_header(Url, Opts, Profile)
when (is_list(Opts) andalso (is_atom(Profile) orelse is_pid(Profile))) ->
try
begin
@@ -362,15 +563,21 @@ cookie_header(Url, Opts, Profile)
end.
-%%--------------------------------------------------------------------------
-%% which_cookies() -> [cookie()]
-%% which_cookies(Profile) -> [cookie()]
-%%
-%% Description: Debug function, dumping the cookie database
-%%-------------------------------------------------------------------------
+-spec which_cookies() -> [CookieStores] when
+ CookieStores :: {cookies, Cookies} | {session_cookies, Cookies},
+ Cookies :: [term()].
which_cookies() ->
which_cookies(default_profile()).
+%%
+%% @doc Produces a list of the entire cookie database. Intended for
+%% debugging/testing purposes. If no profile is specified, the default profile
+%% is used.
+%%
+-spec which_cookies(Profile) -> [CookieStores] when
+ Profile :: atom() | pid(),
+ CookieStores :: {cookies, Cookies} | {session_cookies, Cookies},
+ Cookies :: [term()].
which_cookies(Profile) ->
?hcrt("which cookies", [{profile, Profile}]),
try
@@ -383,16 +590,31 @@ which_cookies(Profile) ->
end.
-%%--------------------------------------------------------------------------
-%% 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).
-%%-------------------------------------------------------------------------
+-spec which_sessions() -> SessionInfo when
+ SessionInfo :: {GoodSession, BadSessions, NonSessions},
+ GoodSession :: [Session],
+ BadSessions :: [term()],
+ NonSessions :: [term()],
+ Session :: term().
which_sessions() ->
which_sessions(default_profile()).
+%%
+%% @doc This function is intended for debugging only. It produces a slightly
+%% processed dump of the session database. The first list of the session
+%% information tuple will contain session information on an internal format. The
+%% last two lists of the session information tuple should always be empty if the
+%% code is working as intended. If no profile is specified, the default profile
+%% is used. The dumped sessions database is sorted into three groups
+%% (Good-, Bad- and Non-sessions).
+%%
+-spec which_sessions(Profile) -> SessionInfo when
+ Profile :: atom() | pid(),
+ SessionInfo :: {GoodSession, BadSessions, NonSessions},
+ GoodSession :: [Session],
+ BadSessions :: [term()],
+ NonSessions :: [term()],
+ Session :: term().
which_sessions(Profile) ->
try
begin
@@ -404,15 +626,23 @@ which_sessions(Profile) ->
end.
-%%--------------------------------------------------------------------------
-%% info() -> list()
-%% info(Profile) -> list()
-%%
-%% Description: Debug function, retrieve info about the profile
-%%-------------------------------------------------------------------------
+
+%%
+%% @doc Produces a list of miscellaneous information. Intended for debugging. If
+%% no profile is specified, the default profile is used.
+%%
+-spec info() -> list() | {error, Reason} when
+ Reason :: term().
info() ->
info(default_profile()).
+%%
+%% @doc Produces a list of miscellaneous information. Intended for debugging. If
+%% no profile is specified, the default profile is used.
+%%
+-spec info(Profile) -> list() | {error, Reason} when
+ Reason :: term(),
+ Profile :: atom() | pid().
info(Profile) ->
try
begin
@@ -424,15 +654,21 @@ info(Profile) ->
end.
-%%--------------------------------------------------------------------------
-%% reset_cookies() -> void()
-%% reset_cookies(Profile) -> void()
-%%
-%% Description: Debug function, reset the cookie database
-%%-------------------------------------------------------------------------
+%%
+%% @doc Debug function. Resets (clears) the cookie database for the default profile
+%%
+-spec reset_cookies() -> Void when
+ Void :: term().
reset_cookies() ->
reset_cookies(default_profile()).
+%%
+%% @doc Debug function. Resets (clears) the cookie database for the specified
+%% `Profile'. If no profile is specified the default profile is used.
+%%
+-spec reset_cookies(Profile) -> Void when
+ Profile :: atom() | pid(),
+ Void :: term().
reset_cookies(Profile) ->
try
begin
@@ -444,12 +680,12 @@ reset_cookies(Profile) ->
end.
-%%--------------------------------------------------------------------------
-%% stream_next(Pid) -> Header | {error, Reason}
-%%
-%% Description: Triggers the next message to be streamed, e.i.
-%% same behavior as active once for sockets.
-%%-------------------------------------------------------------------------
+%%
+%% @doc Triggers the next message to be streamed, that is, the same behavior as
+%% active ones for sockets.
+%%
+-spec stream_next(Pid) -> ok when
+ Pid :: pid().
stream_next(Pid) ->
httpc_handler:stream_next(Pid).
@@ -498,6 +734,10 @@ service_info(Pid) ->
%%%========================================================================
%%% Internal functions
%%%========================================================================
+-spec normalize_and_parse_url(Characters) -> NormalizedURI when
+ Characters :: uri_string:uri_string(),
+ NormalizedURI :: uri_string:uri_string() | uri_string:uri_map()
+ | uri_string:error().
normalize_and_parse_url(Url) ->
uri_string:normalize(unicode:characters_to_list(Url), [return_map]).
@@ -651,6 +891,25 @@ maybe_format_body(BinBody, Options) ->
BinBody
end.
+-spec headers_as_is(HeaderRequest, OptionsRequest) -> HeaderRequest when
+ HeaderRequest :: [{list(), list() | binary()}] | [tuple()],
+ OptionsRequest :: [OptionRequest],
+ OptionRequest :: {sync, boolean()}
+ | {stream, StreamTo}
+ | {body_format, BodyFormat}
+ | {full_result, boolean()}
+ | {headers_as_is, boolean()}
+ | {socket_opts, [SocketOpt]}
+ | {receiver, Receiver}
+ | {ipv6_host_with_brackets, boolean()},
+ BodyFormat :: string() | binary() | atom(),
+ StreamTo :: none | self | {self, once} | file:name_all(),
+ SocketOpt :: term(),
+ Receiver :: pid()
+ | fun((term()) -> term())
+ | { ReceiverModule::atom()
+ , ReceiverFunction::atom()
+ , ReceiverArgs::list()}.
%% This options is a workaround for http servers that do not follow the
%% http standard and have case sensitive header parsing. Should only be
%% used if there is no other way to communicate with the server or for
@@ -663,7 +922,6 @@ headers_as_is(Headers, Options) ->
Headers
end.
-
http_options(HttpOptions) ->
HttpOptionsDefault = http_options_default(),
http_options(HttpOptionsDefault, HttpOptions, #http_options{}).
@@ -704,7 +962,7 @@ http_options([{Tag, Default, Idx, Post} | Defaults], HttpOptions, Acc) ->
Acc2 = setelement(Idx, Acc, DefaultVal),
http_options(Defaults, HttpOptions, Acc2)
end.
-
+
http_options_default() ->
VersionPost =
fun(Value) when is_atom(Value) ->
@@ -762,6 +1020,7 @@ http_options_default() ->
{connect_timeout, {field, #http_options.timeout}, #http_options.connect_timeout, ConnTimeoutPost}
].
+-spec boolfun() -> fun(((true | false)) -> {ok, true | false}) | fun((term()) -> error).
boolfun() ->
fun(Value) when (Value =:= true) orelse
(Value =:= false) ->
@@ -872,6 +1131,23 @@ request_options([{Key, DefaultVal, Verify} | Defaults], Options, Acc) ->
request_options(Defaults, Options, [{Key, DefaultVal} | Acc])
end.
+-spec request_options_sanity_check([OptionRequest]) -> ok | no_return() when
+ OptionRequest :: {sync, boolean()}
+ | {stream, StreamTo}
+ | {body_format, BodyFormat}
+ | {full_result, boolean()}
+ | {headers_as_is, boolean()}
+ | {socket_opts, [SocketOpt]}
+ | {receiver, Receiver}
+ | {ipv6_host_with_brackets, boolean()},
+ StreamTo :: none | self | {self, once} | file:name_all(),
+ BodyFormat :: string() | binary() | atom(),
+ SocketOpt :: term(),
+ Receiver :: pid()
+ | fun((term()) -> term())
+ | { ReceiverModule::atom()
+ , ReceiverFunction::atom()
+ , ReceiverArgs::list()}.
request_options_sanity_check(Opts) ->
case proplists:get_value(sync, Opts) of
Sync when (Sync =:= true) ->
@@ -912,7 +1188,6 @@ validate_ipfamily_unix_socket(IpFamily, UnixSocket, Options, Acc) ->
validate_unix_socket(UnixSocket),
{Options, Acc}.
-
validate_options(Options0) ->
try
{Options, Acc} = validate_ipfamily_unix_socket(Options0),
@@ -991,7 +1266,7 @@ validate_options([{_, _} = Opt| _], _Acc) ->
{error, {not_an_option, Opt}}.
-validate_proxy({{ProxyHost, ProxyPort}, NoProxy} = Proxy)
+validate_proxy({{ProxyHost, ProxyPort}, NoProxy} = Proxy)
when is_list(ProxyHost) andalso
is_integer(ProxyPort) andalso
is_list(NoProxy) ->
@@ -1062,7 +1337,7 @@ validate_ipfamily(BadValue) ->
bad_option(ipfamily, BadValue).
validate_ip(Value)
- when is_tuple(Value) andalso ((size(Value) =:= 4) orelse (size(Value) =:= 8)) ->
+ when tuple_size(Value) =:= 4; tuple_size(Value) =:= 8 ->
Value;
validate_ip(BadValue) ->
bad_option(ip, BadValue).
@@ -1249,11 +1524,13 @@ validate_headers(RequestHeaders = #http_request_h{host = undefined},
validate_headers(RequestHeaders, _, _) ->
RequestHeaders.
-
%%--------------------------------------------------------------------------
%% These functions are just simple wrappers to parse specifically HTTP URIs
%%--------------------------------------------------------------------------
+-spec header_parse(HeaderRequest) -> ok | InvalidHeaderParsed when
+ HeaderRequest :: [{list(), list() | binary()}] | [tuple()],
+ InvalidHeaderParsed :: {error, {headers_error, invalid_field | invalid_value}}.
header_parse([]) ->
ok;
header_parse([{Field, Value}|T])
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 615314ac1d..b7b8dd7055 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,18 +44,18 @@
-record(timers,
{
- request_timers = [] :: [reference()],
- queue_timer :: reference() | 'undefined'
+ request_timers = [] :: [reference() | {reference(), term()}],
+ queue_timer :: reference() | undefined
}).
-record(state,
{
- request :: request() | 'undefined',
- session :: session() | 'undefined',
- status_line, % {Version, StatusCode, ReasonPharse}
- headers :: http_response_h() | 'undefined',
- body :: binary() | 'undefined',
- mfa, % {Module, Function, Args}
+ request :: request() | undefined,
+ session :: session() | undefined,
+ status_line :: tuple() | undefined, % {Version, StatusCode, ReasonPharse}
+ headers :: http_response_h() | undefined,
+ body :: binary() | undefined,
+ mfa :: {atom(), atom(), term()} | undefined, % {Module, Function, Args}
pipeline = queue:new() :: queue:queue(),
keep_alive = queue:new() :: queue:queue(),
status :: undefined | new | pipeline | keep_alive | close | {ssl_tunnel, request()},
@@ -65,7 +65,7 @@
options :: options(),
timers = #timers{} :: #timers{},
profile_name :: atom(), % id of httpc_manager process.
- once = inactive :: 'inactive' | 'once'
+ once = inactive :: inactive | once
}).
@@ -322,7 +322,7 @@ terminate(normal,
cancel_timers(Timers),
%% Maybe deliver answers to requests
- deliver_answer(Request),
+ maybe_deliver_answer(Request, State),
%% And, just in case, close our side (**really** overkill)
http_transport:close(SocketType, Socket);
@@ -515,7 +515,7 @@ do_handle_info({Proto, _Socket, Data},
handle_http_msg(Result, State);
{_, whole_body, _} when Method =:= head ->
handle_response(State#state{body = <<>>});
- {Module, whole_body, [Body, Length]} ->
+ {Module, whole_body, [Body, Length]} when is_binary(Body)->
{_, Code, _} = StatusLine,
{Streamed, NewBody, NewRequest} = stream(Body, Request, Code),
%% When we stream we will not keep the already
@@ -525,7 +525,7 @@ do_handle_info({Proto, _Socket, Data},
false ->
Length;
true ->
- Length - size(Body)
+ Length - byte_size(Body)
end,
NewState = next_body_chunk(State, Code),
@@ -605,7 +605,7 @@ do_handle_info({Proto, Socket, Data},
%% whole body is now sent instead of sending a length
%% indicator. In this case the length indicator will be
%% -1.
-do_handle_info({Info, _}, State = #state{mfa = {_, whole_body, Args}})
+do_handle_info({Info, _}, #state{mfa = {_, whole_body, Args}} = State)
when Info =:= tcp_closed orelse
Info =:= ssl_closed ->
case lists:last(Args) of
@@ -616,25 +616,18 @@ do_handle_info({Info, _}, State = #state{mfa = {_, whole_body, Args}})
end;
%%% Server closes idle pipeline
-do_handle_info({tcp_closed, _}, State = #state{request = undefined}) ->
+do_handle_info({tcp_closed, _}, #state{request = undefined} = State) ->
{stop, normal, State};
-do_handle_info({ssl_closed, _}, State = #state{request = undefined}) ->
+do_handle_info({ssl_closed, _}, #state{request = undefined} = State) ->
{stop, normal, State};
%%% Error cases
-do_handle_info({tcp_closed, _}, #state{session = Session0} = State) ->
- Socket = Session0#session.socket,
+do_handle_info({Closed, _}, #state{session = #session{socket = Socket}=Session0} = State)
+ when Closed == tcp_closed; Closed == ssl_closed ->
Session = Session0#session{socket = {remote_close, Socket}},
%% {stop, session_remotly_closed, State};
{stop, normal, State#state{session = Session}};
-do_handle_info({ssl_closed, _}, #state{session = Session0} = State) ->
- Socket = Session0#session.socket,
- Session = Session0#session{socket = {remote_close, Socket}},
- %% {stop, session_remotly_closed, State};
- {stop, normal, State#state{session = Session}};
-do_handle_info({tcp_error, _, _} = Reason, State) ->
- {stop, Reason, State};
-do_handle_info({ssl_error, _, _} = Reason, State) ->
+do_handle_info({Error, _, _} = Reason, State) when Error == tcp_error; Error == ssl_error ->
{stop, Reason, State};
%% Timeouts
@@ -675,7 +668,7 @@ do_handle_info({timeout, RequestId},
keep_alive = KeepAlive}}
end;
-do_handle_info(timeout_queue, State = #state{request = undefined}) ->
+do_handle_info(timeout_queue, #state{request = undefined} = State) ->
{stop, normal, State};
%% Timing was such as the queue_timeout was not canceled!
@@ -685,12 +678,12 @@ do_handle_info(timeout_queue, #state{timers = Timers} = State) ->
%% Setting up the connection to the server somehow failed.
do_handle_info({init_error, Reason, ClientErrMsg},
- State = #state{request = Request}) ->
+ #state{request = Request} = State) ->
NewState = answer_request(Request, ClientErrMsg, State),
{stop, {shutdown, Reason}, NewState};
%%% httpc_manager process dies.
-do_handle_info({'EXIT', _, _}, State = #state{request = undefined}) ->
+do_handle_info({'EXIT', _, _}, #state{request = undefined} = State) ->
{stop, normal, State};
%%Try to finish the current request anyway,
%% there is a fairly high probability that it can be done successfully.
@@ -713,24 +706,26 @@ call(Msg, Pid) ->
cast(Msg, Pid) ->
gen_server:cast(Pid, Msg).
-maybe_retry_queue(Q, State) ->
- case queue:is_empty(Q) of
- false ->
+maybe_retry_queue(Q, #state{status = new} = State) ->
+ retry_pipeline(queue:to_list(Q), State);
+maybe_retry_queue(Q, #state{request = Request} = State) ->
+ case Request of
+ undefined ->
retry_pipeline(queue:to_list(Q), State);
- true ->
- ok
+ _ ->
+ retry_pipeline(queue:to_list(queue:cons(Request, Q)), State)
end.
-
+
maybe_send_answer(#request{from = answer_sent}, _Reason, State) ->
State;
maybe_send_answer(Request, Answer, State) ->
answer_request(Request, Answer, State).
-deliver_answer(#request{from = From} = Request)
+maybe_deliver_answer(#request{from = From} = Request, #state{status = new})
when From =/= answer_sent ->
Response = httpc_response:error(Request, socket_closed_remotely),
httpc_response:send(From, Response);
-deliver_answer(_Request) ->
+maybe_deliver_answer(_,_) ->
ok.
%%%--------------------------------------------------------------------
@@ -878,7 +873,7 @@ connect_and_send_upgrade_request(Address, Request, #state{options = Options0} =
end.
handler_info(#state{request = Request,
- session = Session,
+ session = #session{socket = Socket}=Session,
status_line = _StatusLine,
pipeline = Pipeline,
keep_alive = KeepAlive,
@@ -906,8 +901,7 @@ handler_info(#state{request = Request,
queue:len(KeepAlive)
end,
Scheme = Session#session.scheme,
- Socket = Session#session.socket,
- SocketType = Session#session.socket_type,
+ SocketType = Session#session.socket_type,
SocketOpts = http_transport:getopts(SocketType, Socket),
SocketStats = http_transport:getstat(SocketType, Socket),
@@ -962,7 +956,7 @@ handle_http_body(_, #state{status = {ssl_tunnel, _},
handle_http_body(_, #state{status = {ssl_tunnel, Request},
status_line = StatusLine} = State) ->
- ClientErrMsg = httpc_response:error(Request,{could_no_establish_ssh_tunnel, StatusLine}),
+ ClientErrMsg = httpc_response:error(Request,{could_not_establish_ssl_tunnel, StatusLine}),
NewState = answer_request(Request, ClientErrMsg, State),
{stop, normal, NewState};
@@ -983,11 +977,10 @@ handle_http_body(Body, #state{headers = Headers,
handle_http_body(_Body, #state{request = #request{method = head}} = State) ->
handle_response(State#state{body = <<>>});
-handle_http_body(Body, #state{headers = Headers,
+handle_http_body(Body, #state{headers = #http_response_h{'transfer-encoding' = TransferEnc}=Headers,
max_body_size = MaxBodySize,
status_line = {_,Code, _},
request = Request} = State) ->
- TransferEnc = Headers#http_response_h.'transfer-encoding',
case case_insensitive_header(TransferEnc) of
"chunked" ->
try http_chunk:decode(Body, State#state.max_body_size,
@@ -1064,7 +1057,7 @@ handle_response(#state{status = Status0} = State0) when Status0 =/= new ->
handle_cookies(Headers, Request, Options, ProfileName),
case httpc_response:result({StatusLine, Headers, Body}, Request) of
%% 100-continue
- continue ->
+ continue ->
%% Send request body
{_, RequestBody} = Request#request.content,
send_raw(Session, RequestBody),
@@ -1080,7 +1073,7 @@ handle_response(#state{status = Status0} = State0) when Status0 =/= new ->
%% Ignore unexpected 100-continue response and receive the
%% actual response that the server will send right away.
- {ignore, Data} ->
+ {ignore, Data} ->
Relaxed = (Request#request.settings)#http_options.relaxed,
MFA = {httpc_response, parse,
[State#state.max_header_size, Relaxed]},
@@ -1116,8 +1109,7 @@ handle_cookies(_,_, #options{cookies = disabled}, _) ->
%% so the user will have to call a store command.
handle_cookies(_,_, #options{cookies = verify}, _) ->
ok;
-handle_cookies(Headers, Request, #options{cookies = enabled}, ProfileName) ->
- {Host, _ } = Request#request.address,
+handle_cookies(Headers, #request{address = {Host, _}}=Request, #options{cookies = enabled}, ProfileName) ->
Cookies = httpc_cookie:cookies(Headers#http_response_h.other,
Request#request.path, Host),
httpc_manager:store_cookies(Cookies, Request#request.address,
@@ -1135,7 +1127,7 @@ handle_queue(#state{status = pipeline} = State, Data) ->
handle_pipeline(State, Data).
handle_pipeline(#state{status = pipeline,
- session = Session,
+ session = #session{}=Session,
profile_name = ProfileName,
options = #options{pipeline_timeout = TimeOut}} = State,
Data) ->
@@ -1637,14 +1629,14 @@ host_header(_, URI) ->
tls_upgrade(#state{status =
{ssl_tunnel,
#request{settings =
- #http_options{ssl = {_, TLSOptions0} = SocketType},
+ #http_options{ssl = {_, TLSOptions0} = SocketType,
+ connect_timeout = ConnectTimeout},
address = {Host, _} = Address} = Request},
session = #session{socket = TCPSocket} = Session0,
options = Options} = State) ->
TLSOptions = maybe_add_sni(Host, TLSOptions0),
-
- case ssl:connect(TCPSocket, TLSOptions) of
+ case ssl:connect(TCPSocket, TLSOptions, ConnectTimeout) of
{ok, TLSSocket} ->
ClientClose = httpc_request:is_client_closing(Request#request.headers),
SessionType = httpc_manager:session_type(Options),
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index 709683ffb0..344b6a2620 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -127,7 +127,7 @@
%% {{Host, Port}, HandlerPid}
id,
- client_close :: 'undefined' | boolean(),
+ client_close = false :: boolean(),
%% http (HTTP/TCP) | https (HTTP/SSL/TCP)
scheme,
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 95d6bffbb3..cb50e8afbf 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -474,9 +474,9 @@ handle_call({which_cookies, Url, Options}, _,
?hcrv("which cookies", [{url, Url}, {options, Options}]),
case uri_parse(Url) of
{ok, {Scheme, Host, Port, Path}} ->
- CookieHeaders =
+ CookieHeader =
httpc_cookie:header(CookieDb, erlang:list_to_existing_atom(Scheme), {Host, Port}, Path),
- {reply, CookieHeaders, State};
+ {reply, CookieHeader, State};
{error, _} = ERROR ->
{reply, ERROR, State}
end;
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index a1ca0da92b..861bb5d683 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -241,10 +241,10 @@ handle_transfer_encoding(Headers) ->
Headers#http_request_h{'content-length' = undefined}.
body_length(Body) when is_binary(Body) ->
- integer_to_list(size(Body));
+ integer_to_list(byte_size(Body));
body_length(Body) when is_list(Body) ->
- integer_to_list(length(Body)).
+ integer_to_list(iolist_size(Body)).
%% Set 'Content-Type' when it is explicitly set.
handle_content_type(Headers, "") ->
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 79895e447e..94693577e8 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -60,8 +60,8 @@ parse_headers([Bin, Rest,Header, Headers, MaxHeaderSize, Result, Relaxed]) ->
parse_headers(<<Rest/binary, Bin/binary>>, Header, Headers,
MaxHeaderSize, Result, Relaxed).
-whole_body(Body, Length) ->
- case size(Body) of
+whole_body(Body, Length) when is_binary(Body)->
+ case byte_size(Body) of
N when (N < Length) andalso (N > 0) ->
{?MODULE, whole_body, [Body, Length]};
%% OBS! The Server may close the connection to indicate that the
@@ -122,17 +122,19 @@ result(Response = {{_, Code, _}, _, _},
(Code =:= 303) ->
redirect(Response, Request#request{method = get});
result(Response = {{_, Code, _}, _, _},
- Request = #request{settings =
- #http_options{autoredirect = true},
- method = post}) when (Code =:= 307) ->
+ Request = #request{settings =
+ #http_options{autoredirect = true},
+ method = post}) when (Code =:= 307) orelse
+ (Code =:= 308) ->
redirect(Response, Request);
result(Response = {{_, Code, _}, _, _},
- Request = #request{settings =
- #http_options{autoredirect = true},
- method = Method}) when (Code =:= 301) orelse
- (Code =:= 302) orelse
- (Code =:= 303) orelse
- (Code =:= 307) ->
+ Request = #request{settings =
+ #http_options{autoredirect = true},
+ method = Method}) when (Code =:= 301) orelse
+ (Code =:= 302) orelse
+ (Code =:= 303) orelse
+ (Code =:= 307) orelse
+ (Code =:= 308) ->
case lists:member(Method, [get, head, options, trace]) of
true ->
redirect(Response, Request);
@@ -590,13 +592,13 @@ is_server_closing(Headers) when is_record(Headers, http_response_h) ->
format_response({StatusLine, Headers, Body = <<>>}) ->
{{StatusLine, http_response:header_list(Headers), Body}, <<>>};
-format_response({StatusLine, Headers, Body}) ->
+format_response({StatusLine, Headers, Body}) when is_binary(Body) ->
Length = list_to_integer(Headers#http_response_h.'content-length'),
{NewBody, Data} =
case Length of
-1 -> % When no length indicator is provided
{Body, <<>>};
- Length when (Length =< size(Body)) ->
+ Length when (Length =< byte_size(Body)) ->
<<BodyThisReq:Length/binary, Next/binary>> = Body,
{BodyThisReq, Next};
_ -> %% Connection prematurely ended.
diff --git a/lib/inets/src/http_lib/Makefile b/lib/inets/src/http_lib/Makefile
index 8248e37c44..481c4f66eb 100644
--- a/lib/inets/src/http_lib/Makefile
+++ b/lib/inets/src/http_lib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2016. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ ERL_COMPILE_FLAGS += \
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl
index 74f4cc1b3d..0588937275 100644
--- a/lib/inets/src/http_lib/http_chunk.erl
+++ b/lib/inets/src/http_lib/http_chunk.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,8 +71,8 @@ decode(ChunkedBody, MaxBodySize, MaxHeaderSize) ->
%% input format. When sending the data on the both formats
%% are accepted.
%%-------------------------------------------------------------------------
-encode(Chunk) when is_binary(Chunk)->
- HEXSize = list_to_binary(http_util:integer_to_hexlist(size(Chunk))),
+encode(Chunk) when is_binary(Chunk) ->
+ HEXSize = list_to_binary(http_util:integer_to_hexlist(byte_size(Chunk))),
<<HEXSize/binary, ?CR, ?LF, Chunk/binary, ?CR, ?LF>>;
encode([<<>>]) ->
@@ -202,7 +202,7 @@ ignore_extensions(<<_Octet, Rest/binary>>, RemainingSize, TotalMaxHeaderSize, Ne
decode_data(ChunkSize, TotalChunk,
Info = {MaxBodySize, BodySoFar, AccLength, MaxHeaderSize})
- when ChunkSize =< size(TotalChunk) ->
+ when is_binary(TotalChunk), ChunkSize =< byte_size(TotalChunk) ->
case TotalChunk of
%% Last chunk
<<Data:ChunkSize/binary, ?CR, ?LF, "0", ";">> ->
diff --git a/lib/inets/src/http_lib/http_request.erl b/lib/inets/src/http_lib/http_request.erl
index 02fa8acb80..af8b6754b1 100644
--- a/lib/inets/src/http_lib/http_request.erl
+++ b/lib/inets/src/http_lib/http_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -103,11 +103,9 @@ is_absolut_uri(_) ->
%% Description: returns a normalized Host header value, with the port
%% number omitted for well-known ports
%%-------------------------------------------------------------------------
-normalize_host(https, Host, Port) when Port =:= 443 orelse
- Port =:= undefined ->
+normalize_host(https, Host, 443 = _Port) ->
Host;
-normalize_host(http, Host, Port) when Port =:= 80 orelse
- Port =:= undefined ->
+normalize_host(http, Host, 80 = _Port) ->
Host;
normalize_host(_Scheme, Host, Port) ->
Host ++ ":" ++ integer_to_list(Port).
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index c18c08c77c..0eb0cc2684 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -199,9 +199,22 @@ get_socket_info(Addr, Port, Fd, BaseOpts) ->
%% Description: Accepts an incoming connection request on a listen socket,
%% using either gen_tcp or ssl.
%%-------------------------------------------------------------------------
+-spec accept(SocketType, ListenSocket) -> {ok, Socket} | {error, Reason} when
+ SocketType :: ip_comm | {ssl, SSLConfig},
+ SSLConfig :: term(),
+ ListenSocket :: gen_tcp:socket(),
+ Socket :: gen_tcp:socket(),
+ Reason :: term().
accept(SocketType, ListenSocket) ->
accept(SocketType, ListenSocket, infinity).
+-spec accept(SocketType, ListenSocket, Timeout) -> {ok, Socket} | {error, Reason} when
+ SocketType :: ip_comm | {ssl | essl, SSLConfig},
+ SSLConfig :: term(),
+ Timeout :: timeout(),
+ ListenSocket :: gen_tcp:socket(),
+ Socket :: gen_tcp:socket(),
+ Reason :: term().
accept(ip_comm, ListenSocket, Timeout) ->
gen_tcp:accept(ListenSocket, Timeout);
accept({ip_comm, _}, ListenSocket, Timeout) ->
@@ -216,13 +229,14 @@ accept({essl, _SSLConfig}, ListenSocket, Timeout) ->
%%-------------------------------------------------------------------------
-%% controlling_process(SocketType, Socket, NewOwner) -> ok | {error, Reason}
-%% SocketType = ip_comm | {ssl, _}
-%% Socket = socket()
-%% NewOwner = pid()
-%%
-%% Description: Assigns a new controlling process to Socket.
+%% Description: Assigns a new controlling process to Socket.
%%-------------------------------------------------------------------------
+-spec controlling_process(SocketType, Socket, NewOwner) -> Object when
+ SocketType :: ip_comm | {ip_comm | ssl | essl, _SSLConfig},
+ Socket :: gen_tcp:socket(),
+ NewOwner :: pid(),
+ Object :: ok | {error, Reason},
+ Reason :: closed | not_owner | badarg | inet:posix().
controlling_process(ip_comm, Socket, NewOwner) ->
gen_tcp:controlling_process(Socket, NewOwner);
controlling_process({ip_comm, _}, Socket, NewOwner) ->
@@ -237,13 +251,13 @@ controlling_process({essl, _}, Socket, NewOwner) ->
%%-------------------------------------------------------------------------
-%% setopts(SocketType, Socket, Options) -> ok | {error, Reason}
-%% SocketType = ip_comm | {ssl, _}
-%% Socket = socket()
-%% Options = list()
%% Description: Sets one or more options for a socket, using either
%% gen_tcp or ssl.
%%-------------------------------------------------------------------------
+-spec setopts(SocketType, Socket, Options) -> ok | {error, inet:posix()} when
+ SocketType :: ip_comm | {ip_comm | ssl | essl, _SSLConfig},
+ Socket :: inet:socket() | ssl:sslsocket(),
+ Options :: [inet:socket_setopt()] | [gen_tcp:option()].
setopts(ip_comm, Socket, Options) ->
inet:setopts(Socket, Options);
setopts({ip_comm, _}, Socket, Options) ->
@@ -258,16 +272,21 @@ setopts({essl, _}, Socket, Options) ->
%%-------------------------------------------------------------------------
-%% getopts(SocketType, Socket [, Opts]) -> ok | {error, Reason}
-%% SocketType = ip_comm | {ssl, _}
-%% Socket = socket()
-%% Opts = socket_options()
-%% Description: Gets the values for some options.
+%% Description: Gets the values for some options.
%%-------------------------------------------------------------------------
+-spec getopts(SocketType, Socket) -> Object when
+ SocketType :: ip_comm | {ip_comm | ssl | essl, _SSLConfig},
+ Socket :: ssl:sslsocket() | inet:socket(),
+ Object :: [gen_tcp:option()] | [inet:socket_setopt() | gen_tcp:pktoptions_value()] | [].
getopts(SocketType, Socket) ->
Opts = [packet, packet_size, recbuf, sndbuf, priority, tos, send_timeout],
getopts(SocketType, Socket, Opts).
+-spec getopts(SocketType, Socket, Options) -> Object when
+ SocketType :: ip_comm | {ip_comm | ssl | essl, _SSLConfig},
+ Socket :: ssl:sslsocket() | inet:socket(),
+ Options :: [gen_tcp:option_name()],
+ Object :: [gen_tcp:option()] | [inet:socket_setopt() | gen_tcp:pktoptions_value()] | [].
getopts({ip_comm, _}, Socket, Options) ->
getopts(ip_comm, Socket, Options);
@@ -286,6 +305,10 @@ getopts({ssl, SSLConfig}, Socket, Options) ->
getopts({essl, _}, Socket, Options) ->
getopts_ssl(Socket, Options).
+-spec getopts_ssl(SslSocket, Options) ->
+ [gen_tcp:option()] | [] when
+ SslSocket :: ssl:sslsocket(),
+ Options :: [gen_tcp:option_name()].
getopts_ssl(Socket, Options) ->
case ssl:getopts(Socket, Options) of
{ok, SocketOpts} ->
@@ -380,11 +403,11 @@ peername({essl, _}, Socket) ->
do_peername(ssl:peername(Socket)).
do_peername({ok, {Addr, Port}})
- when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+ when tuple_size(Addr) =:= 4 ->
PeerName = ipv4_name(Addr),
{Port, PeerName};
do_peername({ok, {Addr, Port}})
- when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+ when tuple_size(Addr) =:= 8 ->
PeerName = ipv6_name(Addr),
{Port, PeerName};
do_peername({error, _}) ->
@@ -413,11 +436,11 @@ sockname({essl, _}, Socket) ->
do_sockname(ssl:sockname(Socket)).
do_sockname({ok, {Addr, Port}})
- when is_tuple(Addr) andalso (size(Addr) =:= 4) ->
+ when tuple_size(Addr) =:= 4 ->
SockName = ipv4_name(Addr),
{Port, SockName};
do_sockname({ok, {Addr, Port}})
- when is_tuple(Addr) andalso (size(Addr) =:= 8) ->
+ when tuple_size(Addr) =:= 8 ->
SockName = ipv6_name(Addr),
{Port, SockName};
do_sockname({error, _}) ->
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index e8bc9b3560..d4f352b692 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -17,124 +17,33 @@
%%
%% %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, parse/2,
- scheme_defaults/0,
- encode/1, decode/1]).
-
+-export([encode/1, decode/1]).
--deprecated({parse, 1, "use uri_string functions instead"}).
--deprecated({parse, 2, "use uri_string functions instead"}).
--deprecated({encode, 1, "use uri_string functions instead"}).
--deprecated({decode, 1, "use uri_string functions instead"}).
--deprecated({scheme_defaults, 0, "use uri_string functions instead"}).
-
+-deprecated({encode, 1, "use uri_string:quote function instead"}).
+-deprecated({decode, 1, "use uri_string:unquote function instead"}).
+-removed({parse, 1, "use uri_string functions instead"}).
+-removed({parse, 2, "use uri_string functions instead"}).
+-removed({scheme_defaults, 0, "use uri_string functions instead"}).
--export_type([uri/0,
- user_info/0,
- scheme/0, default_scheme_port_number/0,
- host/0,
- path/0,
- query/0,
- fragment/0]).
+-export_type([uri/0]).
-type uri() :: string() | binary().
--type user_info() :: string() | binary().
--type scheme() :: atom().
--type host() :: string() | binary().
--type path() :: string() | binary().
--type query() :: string() | binary().
--type fragment() :: string() | binary().
--type port_number() :: inet:port_number().
--type default_scheme_port_number() :: port_number().
-type hex_uri() :: string() | binary(). %% Hexadecimal encoded URI.
-type maybe_hex_uri() :: string() | binary(). %% A possibly hexadecimal encoded URI.
--type scheme_defaults() :: [{scheme(), default_scheme_port_number()}].
--type scheme_validation_fun() :: fun((SchemeStr :: string() | binary()) ->
- valid | {error, Reason :: term()}).
+-removed_type({user_info, 0, "use uri_string instead"}).
+-removed_type({scheme, 0, "use uri_string instead"}).
+-removed_type({host, 0, "use uri_string instead"}).
+-removed_type({path, 0, "use uri_string instead"}).
+-removed_type({query, 0, "use uri_string instead"}).
+-removed_type({fragment, 0, "use uri_string instead"}).
+-removed_type({default_scheme_port_number, 0, "use uri_string instead"}).
%%%=========================================================================
%%% API
%%%=========================================================================
-
--spec scheme_defaults() -> scheme_defaults().
-scheme_defaults() ->
- [{http, 80},
- {https, 443},
- {ftp, 21},
- {ssh, 22},
- {sftp, 22},
- {tftp, 69}].
-
--type parse_result() ::
- {scheme(), user_info(), host(), port_number(), path(), query()} |
- {scheme(), user_info(), host(), port_number(), path(), query(),
- fragment()}.
-
--spec parse(uri()) -> {ok, parse_result()} | {error, term()}.
-parse(AbsURI) ->
- parse(AbsURI, []).
-
--spec parse(uri(), [Option]) -> {ok, parse_result()} | {error, term()} when
- Option :: {ipv6_host_with_brackets, boolean()} |
- {scheme_defaults, scheme_defaults()} |
- {fragment, boolean()} |
- {scheme_validation_fun, scheme_validation_fun() | none}.
-parse(AbsURI, Opts) ->
- case parse_scheme(AbsURI, Opts) of
- {error, Reason} ->
- {error, Reason};
- {Scheme, DefaultPort, Rest} ->
- case (catch parse_uri_rest(Scheme, DefaultPort, Rest, Opts)) of
- {ok, Result} ->
- {ok, Result};
- {error, Reason} ->
- {error, {Reason, Scheme, AbsURI}};
- _ ->
- {error, {malformed_url, Scheme, AbsURI}}
- end
- end.
-
reserved() ->
sets:from_list([$;, $:, $@, $&, $=, $+, $,, $/, $?,
$#, $[, $], $<, $>, $\", ${, $}, $|, %"
@@ -171,145 +80,8 @@ do_decode_binary(<<>>) ->
%%%========================================================================
%%% Internal functions
%%%========================================================================
-
-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};
- {SchemeStr, Rest} ->
- case extract_scheme(SchemeStr, Opts) of
- {error, Error} ->
- {error, Error};
- {ok, Scheme} ->
- 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
- end.
-
-extract_scheme(Str, Opts) ->
- case lists:keysearch(scheme_validation_fun, 1, Opts) of
- {value, {scheme_validation_fun, Fun}} when is_function(Fun) ->
- case Fun(Str) of
- valid ->
- {ok, to_atom(http_util:to_lower(Str))};
- {error, Error} ->
- {error, Error}
- end;
- _ ->
- {ok, to_atom(http_util:to_lower(Str))}
- end.
-
-to_atom(S) when is_list(S) ->
- list_to_atom(S);
-to_atom(S) when is_binary(S) ->
- binary_to_atom(S, unicode).
-
-parse_uri_rest(Scheme, DefaultPort, <<"//", URIPart/binary>>, Opts) ->
- {Authority, PathQueryFragment} =
- split_uri(URIPart, "[/?#]", {URIPart, <<"">>}, 1, 0),
- {RawPath, QueryFragment} =
- split_uri(PathQueryFragment, "[?#]", {PathQueryFragment, <<"">>}, 1, 0),
- {Query, Fragment} =
- split_uri(QueryFragment, "#", {QueryFragment, <<"">>}, 1, 0),
- {UserInfo, HostPort} = split_uri(Authority, "@", {<<"">>, Authority}, 1, 1),
- {Host, Port} = parse_host_port(Scheme, DefaultPort, HostPort, Opts),
- Path = path(RawPath),
- case lists:keyfind(fragment, 1, Opts) of
- {fragment, true} ->
- {ok, {Scheme, UserInfo, Host, Port, Path, Query, Fragment}};
- _ ->
- {ok, {Scheme, UserInfo, Host, Port, Path, Query}}
- end;
-parse_uri_rest(Scheme, DefaultPort, "//" ++ URIPart, Opts) ->
- {Authority, PathQueryFragment} =
- split_uri(URIPart, "[/?#]", {URIPart, ""}, 1, 0),
- {RawPath, QueryFragment} =
- split_uri(PathQueryFragment, "[?#]", {PathQueryFragment, ""}, 1, 0),
- {Query, Fragment} =
- split_uri(QueryFragment, "#", {QueryFragment, ""}, 1, 0),
- {UserInfo, HostPort} = split_uri(Authority, "@", {"", Authority}, 1, 1),
- {Host, Port} = parse_host_port(Scheme, DefaultPort, HostPort, Opts),
- Path = path(RawPath),
- case lists:keyfind(fragment, 1, Opts) of
- {fragment, true} ->
- {ok, {Scheme, UserInfo, Host, Port, Path, Query, Fragment}};
- _ ->
- {ok, {Scheme, UserInfo, Host, Port, Path, Query}}
- end.
-
-
%% In this version of the function, we no longer need
%% the Scheme argument, but just in case...
-parse_host_port(_Scheme, DefaultPort, <<"[", HostPort/binary>>, 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),
- {Host2, int_port(Port)};
-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),
- {Host2, int_port(Port)};
-
-parse_host_port(_Scheme, DefaultPort, HostPort, _Opts) ->
- {Host, Port} = split_uri(HostPort, ":", {HostPort, DefaultPort}, 1, 1),
- {Host, int_port(Port)}.
-
-split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) ->
- case re:run(UriPart, SplitChar, [{capture, first}]) of
- {match, [{Match, _}]} ->
- {string:slice(UriPart, 0, Match + 1 - SkipLeft),
- string:slice(UriPart, Match + SkipRight, string:length(UriPart))};
- nomatch ->
- NoMatchResult
- end.
-
-maybe_ipv6_host_with_brackets(Host, Opts) when is_binary(Host) ->
- case lists:keysearch(ipv6_host_with_brackets, 1, Opts) of
- {value, {ipv6_host_with_brackets, true}} ->
- <<"[", Host/binary, "]">>;
- _ ->
- Host
- end;
-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_binary(Port) ->
- binary_to_integer(Port);
-int_port(Port) when is_list(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(<<"">>) ->
- <<"/">>;
-path("") ->
- "/";
-path(Path) ->
- Path.
-
uri_encode(Char, Reserved) ->
case sets:is_element(Char, Reserved) of
true ->
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index f66a446d40..abf8413f33 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2021. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES)
diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl
index 21eb163278..54d699f500 100644
--- a/lib/inets/src/http_server/httpd.erl
+++ b/lib/inets/src/http_server/httpd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
-behaviour(inets_service).
--include("httpd.hrl").
-include("httpd_internal.hrl").
%% Behavior callbacks
@@ -52,9 +51,18 @@
%%% API
%%%========================================================================
+-spec parse_query(QueryString) -> QueryList | uri_string:error() when
+ QueryString :: string(),
+ QueryList :: [{unicode:chardata(), unicode:chardata() | true}].
parse_query(String) ->
uri_string:dissect_query(String).
+-spec reload_config(Config, Mode) -> ok | {error, Reason} | no_return() when
+ Config :: file:name_all() | [{Option, Value}],
+ Mode :: non_disturbing | disturbing | blocked,
+ Option :: atom(),
+ Value :: term(),
+ Reason :: term().
reload_config(Config = [Value| _], Mode) when is_tuple(Value) ->
do_reload_config(Config, Mode);
reload_config(ConfigFile, Mode) ->
@@ -67,10 +75,121 @@ reload_config(ConfigFile, Mode) ->
throw({error, {could_not_consult_proplist_file, ConfigFile}})
end.
-
+-spec info(Pid) -> HttpInformation when
+ Pid :: pid(),
+ Path :: file:name_all(),
+ HttpInformation :: [CommonOption]
+ | [CommunicationOption]
+ | [ModOption]
+ | [LimitOption]
+ | [AdminOption],
+ CommonOption :: {port, non_neg_integer()}
+ | {server_name, string()}
+ | {server_root, Path}
+ | {document_root, Path},
+ CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any}
+ | {profile, atom()}
+ | { socket_type,
+ ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}}
+ | {ipfamily, inet | inet6}
+ | {minimum_bytes_per_second, integer()},
+ ModOption :: {modules, atom()},
+ LimitOption :: {customize, atom()}
+ | {disable_chunked_transfer_encoding_send, boolean()}
+ | {keep_alive, boolean()}
+ | {keep_alive_timeout, integer()}
+ | {max_body_size, integer()}
+ | {max_clients, integer()}
+ | {max_header_size, integer()}
+ | {max_content_length, integer()}
+ | {max_uri_size, integer()}
+ | {max_keep_alive_request, integer()}
+ | {max_client_body_chunk, integer()},
+ AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path}
+ | {mime_type, string()}
+ | {server_admin, string()}
+ | {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
+ | {logger, Options::list()}
+ | {log_format, common | combined}
+ | {error_log_format, pretty | compact}.
info(Pid) when is_pid(Pid) ->
info(Pid, []).
+-spec info(Pid, Properties) -> HttpInformation when
+ Pid :: pid(),
+ Properties :: [atom()],
+ HttpInformation :: [CommonOption]
+ | [CommunicationOption]
+ | [ModOption]
+ | [LimitOption]
+ | [AdminOption],
+ CommonOption :: {port, non_neg_integer()}
+ | {server_name, string()}
+ | {server_root, Path}
+ | {document_root, Path},
+ CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any}
+ | {profile, atom()}
+ | { socket_type,
+ ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}}
+ | {ipfamily, inet | inet6}
+ | {minimum_bytes_per_second, integer()},
+ ModOption :: {modules, atom()},
+ LimitOption :: {customize, atom()}
+ | {disable_chunked_transfer_encoding_send, boolean()}
+ | {keep_alive, boolean()}
+ | {keep_alive_timeout, integer()}
+ | {max_body_size, integer()}
+ | {max_clients, integer()}
+ | {max_header_size, integer()}
+ | {max_content_length, integer()}
+ | {max_uri_size, integer()}
+ | {max_keep_alive_request, integer()}
+ | {max_client_body_chunk, integer()},
+ AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path}
+ | {mime_type, string()}
+ | {server_admin, string()}
+ | {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
+ | {logger, Options::list()}
+ | {log_format, common | combined}
+ | {error_log_format, pretty | compact};
+ (Address, Port) -> HttpInformation when
+ Address :: inet:ip_address(),
+ Port :: integer(),
+ Path :: file:name_all(),
+ HttpInformation :: [CommonOption]
+ | [CommunicationOption]
+ | [ModOption]
+ | [LimitOption]
+ | [AdminOption],
+ CommonOption :: {port, non_neg_integer()}
+ | {server_name, string()}
+ | {server_root, Path}
+ | {document_root, Path},
+ CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any}
+ | {profile, atom()}
+ | { socket_type,
+ ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}}
+ | {ipfamily, inet | inet6}
+ | {minimum_bytes_per_second, integer()},
+ ModOption :: {modules, atom()},
+ LimitOption :: {customize, atom()}
+ | {disable_chunked_transfer_encoding_send, boolean()}
+ | {keep_alive, boolean()}
+ | {keep_alive_timeout, integer()}
+ | {max_body_size, integer()}
+ | {max_clients, integer()}
+ | {max_header_size, integer()}
+ | {max_content_length, integer()}
+ | {max_uri_size, integer()}
+ | {max_keep_alive_request, integer()}
+ | {max_client_body_chunk, integer()},
+ AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path}
+ | {mime_type, string()}
+ | {server_admin, string()}
+ | {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
+ | {logger, Options::list()}
+ | {log_format, common | combined}
+ | {error_log_format, pretty | compact}.
info(Pid, Properties) when is_pid(Pid) andalso is_list(Properties) ->
{ok, ServiceInfo} = service_info(Pid),
Address = proplists:get_value(bind_address, ServiceInfo),
@@ -83,17 +202,135 @@ info(Pid, Properties) when is_pid(Pid) andalso is_list(Properties) ->
info(Address, Port, Profile, Properties)
end;
-info(Address, Port) when is_integer(Port) ->
+info(Address, Port) when is_integer(Port) ->
info(Address, Port, default).
-info(Address, Port, Profile) when is_integer(Port), is_atom(Profile) ->
+-spec info(Address, Port, Profile) -> HttpInformation when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Profile :: atom(),
+ Path :: file:name_all(),
+ HttpInformation :: [CommonOption]
+ | [CommunicationOption]
+ | [ModOption]
+ | [LimitOption]
+ | [AdminOption],
+ CommonOption :: {port, non_neg_integer()}
+ | {server_name, string()}
+ | {server_root, Path}
+ | {document_root, Path},
+ CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any}
+ | {profile, atom()}
+ | { socket_type,
+ ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}}
+ | {ipfamily, inet | inet6}
+ | {minimum_bytes_per_second, integer()},
+ ModOption :: {modules, atom()},
+ LimitOption :: {customize, atom()}
+ | {disable_chunked_transfer_encoding_send, boolean()}
+ | {keep_alive, boolean()}
+ | {keep_alive_timeout, integer()}
+ | {max_body_size, integer()}
+ | {max_clients, integer()}
+ | {max_header_size, integer()}
+ | {max_content_length, integer()}
+ | {max_uri_size, integer()}
+ | {max_keep_alive_request, integer()}
+ | {max_client_body_chunk, integer()},
+ AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path}
+ | {mime_type, string()}
+ | {server_admin, string()}
+ | {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
+ | {logger, Options::list()}
+ | {log_format, common | combined}
+ | {error_log_format, pretty | compact};
+ (Address, Port, Properties) -> HttpInformation when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Properties :: [atom()],
+ Path :: file:name_all(),
+ HttpInformation :: [CommonOption]
+ | [CommunicationOption]
+ | [ModOption]
+ | [LimitOption]
+ | [AdminOption],
+ CommonOption :: {port, non_neg_integer()}
+ | {server_name, string()}
+ | {server_root, Path}
+ | {document_root, Path},
+ CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any}
+ | {profile, atom()}
+ | { socket_type,
+ ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}}
+ | {ipfamily, inet | inet6}
+ | {minimum_bytes_per_second, integer()},
+ ModOption :: {modules, atom()},
+ LimitOption :: {customize, atom()}
+ | {disable_chunked_transfer_encoding_send, boolean()}
+ | {keep_alive, boolean()}
+ | {keep_alive_timeout, integer()}
+ | {max_body_size, integer()}
+ | {max_clients, integer()}
+ | {max_header_size, integer()}
+ | {max_content_length, integer()}
+ | {max_uri_size, integer()}
+ | {max_keep_alive_request, integer()}
+ | {max_client_body_chunk, integer()},
+ AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path}
+ | {mime_type, string()}
+ | {server_admin, string()}
+ | {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
+ | {logger, Options::list()}
+ | {log_format, common | combined}
+ | {error_log_format, pretty | compact}.
+info(Address, Port, Profile) when is_integer(Port), is_atom(Profile) ->
httpd_conf:get_config(Address, Port, Profile);
info(Address, Port, Properties) when is_integer(Port) andalso
is_list(Properties) ->
httpd_conf:get_config(Address, Port, default, Properties).
-info(Address, Port, Profile, Properties) when is_integer(Port) andalso
+-spec info(Address, Port, Profile, Properties) -> HttpInformation when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Profile :: atom(),
+ Properties :: [atom()],
+ Path :: file:name_all(),
+ HttpInformation :: [CommonOption]
+ | [CommunicationOption]
+ | [ModOption]
+ | [LimitOption]
+ | [AdminOption],
+ CommonOption :: {port, non_neg_integer()}
+ | {server_name, string()}
+ | {server_root, Path}
+ | {document_root, Path},
+ CommunicationOption :: {bind_address, inet:ip_address() | inet:hostname() | any}
+ | {profile, atom()}
+ | { socket_type,
+ ip_comm | {ip_comm, ssl:tls_option() | gen_tcp:option()} | {ssl, ssl:tls_option() | gen_tcp:option()}}
+ | {ipfamily, inet | inet6}
+ | {minimum_bytes_per_second, integer()},
+ ModOption :: {modules, atom()},
+ LimitOption :: {customize, atom()}
+ | {disable_chunked_transfer_encoding_send, boolean()}
+ | {keep_alive, boolean()}
+ | {keep_alive_timeout, integer()}
+ | {max_body_size, integer()}
+ | {max_clients, integer()}
+ | {max_header_size, integer()}
+ | {max_content_length, integer()}
+ | {max_uri_size, integer()}
+ | {max_keep_alive_request, integer()}
+ | {max_client_body_chunk, integer()},
+ AdminOption :: {mime_types, [{MimeType :: string(), Extension :: string()}] | Path}
+ | {mime_type, string()}
+ | {server_admin, string()}
+ | {server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}
+ | {logger, Options::list()}
+ | {log_format, common | combined}
+ | {error_log_format, pretty | compact}.
+info(Address, Port, Profile, Properties) when is_integer(Port) andalso
is_atom(Profile) andalso is_list(Properties) ->
httpd_conf:get_config(Address, Port, Profile, Properties).
@@ -102,11 +339,23 @@ info(Address, Port, Profile, Properties) when is_integer(Port) andalso
%%% Behavior callbacks
%%%========================================================================
-start_standalone(Config) ->
+start_standalone(Config0) ->
+ Config = httpd_ssl_wrapper(Config0),
httpd_sup:start_link([{httpd, Config}], stand_alone).
-start_service(Conf) ->
- httpd_sup:start_child(Conf).
+start_service(Config0) ->
+ Config = httpd_ssl_wrapper(Config0),
+ httpd_sup:start_child(Config).
+
+httpd_ssl_wrapper(Config0) ->
+ case proplists:get_value(socket_type, Config0) of
+ {essl, Value} ->
+ lists:keyreplace(socket_type, 1, Config0, {socket_type, {ssl, Value}});
+ {ssl, Value} ->
+ lists:keyreplace(socket_type, 1, Config0, {socket_type, {essl, Value}});
+ _ -> Config0
+ end.
+
stop_service({Address, Port}) ->
stop_service({Address, Port, ?DEFAULT_PROFILE});
@@ -156,6 +405,13 @@ child_name(Pid, [{Name, Pid} | _]) ->
child_name(Pid, [_ | Children]) ->
child_name(Pid, Children).
+-spec child_name2info(undefined | HTTPSup) -> Object when
+ HTTPSup :: {httpd_instance_sup, any, Port, Profile}
+ | {httpd_instance_sup, Address, Port, Profile},
+ Port :: integer(),
+ Address :: inet:ip_address() | any,
+ Profile :: atom(),
+ Object :: {error, no_such_service} | {ok, [tuple()]}.
child_name2info(undefined) ->
{error, no_such_service};
child_name2info({httpd_instance_sup, any, Port, Profile}) ->
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index a91af84629..91f2020f77 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -506,25 +506,46 @@ remove(ConfigDB) ->
ets:delete(ConfigDB),
ok.
-
+-spec get_config(Address, Port, Profile) -> [tuple()] when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Profile :: atom().
get_config(Address, Port, Profile) ->
Tab = httpd_util:make_name("httpd_conf", Address, Port, Profile),
Properties = ets:tab2list(Tab),
MimeTab = proplists:get_value(mime_types, Properties),
NewProperties = proplists:delete(mime_types, Properties),
[{mime_types, ets:tab2list(MimeTab)} | NewProperties].
-
+
+-spec get_config(Address, Port, Profile, Properties) -> [tuple()] when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Profile :: atom(),
+ Properties :: [tuple() | atom()].
get_config(Address, Port, Profile, Properties) ->
Tab = httpd_util:make_name("httpd_conf", Address, Port, Profile),
Config =
lists:map(fun(Prop) -> {Prop, httpd_util:lookup(Tab, Prop)} end,
Properties),
- [{Proporty, Value} || {Proporty, Value} <- Config, Value =/= undefined].
+ [{Property, Value} || {Property, Value} <- Config, Value =/= undefined].
-
+-spec lookup(Tab, Key) -> Result when
+ Tab :: ets:tab(),
+ Key :: term(),
+ Result :: [tuple()] | atom().
lookup(Tab, Key) ->
httpd_util:lookup(Tab, Key).
+-spec lookup(Tab, Key, Default) -> Object when
+ Tab :: ets:tab(),
+ Key :: atom(),
+ Default :: atom(),
+ Object :: [tuple()] | atom();
+ (Address, Port, Key) -> Object when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Key :: atom(),
+ Object :: [tuple()] | atom().
lookup(Tab, Key, Default) when is_atom(Key) ->
httpd_util:lookup(Tab, Key, Default);
@@ -532,6 +553,12 @@ lookup(Address, Port, Key) when is_integer(Port) ->
Tab = table(Address, Port),
lookup(Tab, Key).
+-spec lookup(Address, Port, Key, Default) -> Object when
+ Address :: inet:ip_address() | any,
+ Port :: integer(),
+ Key :: atom(),
+ Default :: atom(),
+ Object :: [tuple()] | atom().
lookup(Address, Port, Key, Default) when is_integer(Port) ->
Tab = table(Address, Port),
lookup(Tab, Key, Default).
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index a16df6914a..162b5a871b 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,9 +71,9 @@ whole_body([Bin, Body, Length]) ->
%% Separate the body for this request from a possible piplined new
%% request and convert the body data to "string" format.
-body_data(Headers, Body) ->
+body_data(Headers, Body) when is_binary(Body)->
ContentLength = list_to_integer(Headers#http_request_h.'content-length'),
- case size(Body) - ContentLength of
+ case byte_size(Body) - ContentLength of
0 ->
{Body, <<>>};
_ ->
@@ -305,24 +305,24 @@ body_chunk(Body, Length, nolimit) ->
body_chunk(<<>> = Body, Length, MaxChunk) ->
{ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}};
-body_chunk(Body, Length, MaxChunk) when Length > MaxChunk ->
- case size(Body) >= MaxChunk of
+body_chunk(Body, Length, MaxChunk) when Length > MaxChunk, is_binary(Body) ->
+ case byte_size(Body) >= MaxChunk of
true ->
<<Chunk:MaxChunk/binary, Rest/binary>> = Body,
{ok, {{continue, Chunk}, ?MODULE, add_chunk, [Rest, Length - MaxChunk, MaxChunk]}};
false ->
{ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}}
end;
-body_chunk(Body, Length, MaxChunk) ->
- case size(Body) of
+body_chunk(Body, Length, MaxChunk) when is_binary(Body)->
+ case byte_size(Body) of
Length ->
{ok, {last, Body}};
_ ->
{ok, {continue, ?MODULE, add_chunk, [Body, Length, MaxChunk]}}
end.
-whole_body(Body, Length) ->
- case size(Body) of
+whole_body(Body, Length) when is_binary(Body)->
+ case byte_size(Body) of
N when N < Length, Length > 0 ->
{?MODULE, add_chunk, [Body, Length, nolimit]};
N when N >= Length, Length >= 0 ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index 9163225035..26327a2567 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
terminate/2, code_change/3, format_status/2]).
-include("httpd.hrl").
--include("http_internal.hrl").
+-include("../http_lib/http_internal.hrl").
-include_lib("kernel/include/logger.hrl").
-define(HANDSHAKE_TIMEOUT, 5000).
@@ -46,7 +46,7 @@
response_sent = false :: boolean(),
timeout, %% infinity | integer() > 0
timer :: 'undefined' | reference(), % Request timer
- headers, %% #http_request_h{}
+ headers = #http_request_h{},
body, %% binary()
data, %% The total data received in bits, checked after 10s
byte_limit, %% Bit limit per second before kick out
@@ -369,8 +369,8 @@ handle_msg({{continue, Chunk}, Module, Function, Args}, #state{chunk = {_, CbSta
handle_msg({continue, Module, Function, Args}, #state{mod = ModData} = State) ->
setopts(ModData#mod.socket, ModData#mod.socket_type, [{active, once}]),
{noreply, State#state{mfa = {Module, Function, Args}}};
-handle_msg({last, Body}, #state{headers = Headers, chunk = {_, CbState}} = State) ->
- NewHeaders = Headers#http_request_h{'content-length' = integer_to_list(size(Body))},
+handle_msg({last, Body}, #state{headers = Headers, chunk = {_, CbState}} = State) when is_binary(Body) ->
+ NewHeaders = Headers#http_request_h{'content-length' = integer_to_list(byte_size(Body))},
handle_response(State#state{chunk = {last, CbState},
headers = NewHeaders,
body = Body});
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index cedcf6f465..0d4ad772d4 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -104,7 +104,7 @@ init([HttpdServices]) ->
%% The format of the httpd service is:
%% httpd_service() -> {httpd,httpd()}
%% httpd() -> [httpd_config()] | file()
-%% httpd_config() -> {file,file()} |
+%% httpd_config() -> {proplist_file,file()} |
%% {debug,debug()} |
%% {accept_timeout,integer()}
%% debug() -> disable | [debug_options()]
@@ -252,11 +252,14 @@ listen_loop() ->
{'EXIT', _, _} ->
ok
end.
-
+
socket_type(Config) ->
SocketType = proplists:get_value(socket_type, Config, ip_comm),
socket_type(SocketType, Config).
+-spec socket_type(SocketType | Term) -> SocketType when
+ Term :: term(),
+ SocketType :: ip_comm | {ip_comm, _Value} | {ssl, _Value}.
socket_type(ip_comm = SocketType, _) ->
SocketType;
socket_type({ip_comm, _} = SocketType, _) ->
@@ -335,6 +338,9 @@ ssl_ca_certificate_file(Config) ->
[{cacertfile, File}]
end.
+-spec get_fd(Port) -> Object when
+ Port :: integer(),
+ Object :: {ok, integer() | undefined} | {error, {bad_descriptor, term()}}.
get_fd(0) ->
{ok, undefined};
get_fd(Port) ->
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index b4e49dc7f0..9f176b82d5 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,6 +38,8 @@
-deprecated({integer_to_hexlist, 1, "use erlang:integer_to_list/2 with base 16 instead"}).
-deprecated({strip, 1, "use string:trim/1 instead"}).
-deprecated({suffix, 1, "use filename:extension/1 and string:trim/2 instead"}).
+-deprecated({decode_hex, 1, "use uri_string:unquote function instead"}).
+-deprecated({encode_hex, 1, "use uri_string:quote function instead"}).
-compile({nowarn_deprecated_function, [{http_uri, encode, 1}]}).
-compile({nowarn_deprecated_function, [{http_uri, decode, 1}]}).
@@ -127,6 +129,7 @@ reason_phrase(304) -> "Not Modified" ;
reason_phrase(305) -> "Use Proxy" ;
reason_phrase(306) -> "(unused)" ;
reason_phrase(307) -> "Temporary Redirect" ;
+reason_phrase(308) -> "Permanent Redirect" ;
reason_phrase(400) -> "Bad Request";
reason_phrase(401) -> "Unauthorized";
reason_phrase(402) -> "Payment Required";
@@ -396,10 +399,11 @@ month(12) -> "Dec".
%% decode_hex
decode_hex(URI) ->
- http_uri:decode(URI).
+ uri_string:unquote(URI).
encode_hex(URI) ->
- http_uri:encode(URI).
+ SafeChars = "!$()*", %% characters not encoded by deprecated http_uri:encode/1
+ uri_string:quote(URI, SafeChars).
%% flatlength
flatlength(List) ->
@@ -408,7 +412,7 @@ flatlength(List) ->
flatlength([H|T],L) when is_list(H) ->
flatlength(H,flatlength(T,L));
flatlength([H|T],L) when is_binary(H) ->
- flatlength(T,L+size(H));
+ flatlength(T,L+byte_size(H));
flatlength([_H|T],L) ->
flatlength(T,L+1);
flatlength([],L) ->
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl
index 94607e705a..ef6e928058 100644
--- a/lib/inets/src/http_server/mod_alias.erl
+++ b/lib/inets/src/http_server/mod_alias.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -66,7 +66,9 @@ do_alias(#mod{config_db = ConfigDB,
ServerName = which_server_name(ConfigDB),
Port = port_string(which_port(ConfigDB)),
Protocol = get_protocol(SocketType),
- URL = Protocol ++ ServerName ++ Port ++ ReqURI ++ "/",
+ {ReqPath, ReqQuery} = httpd_util:split_path(ReqURI),
+ URL = Protocol ++ ServerName ++ Port ++ ReqPath ++ "/" ++
+ ["?" ++ ReqQuery || [] /= ReqQuery],
ReasonPhrase = httpd_util:reason_phrase(301),
Message = httpd_util:message(301, URL, ConfigDB),
{proceed,
diff --git a/lib/inets/src/http_server/mod_cgi.erl b/lib/inets/src/http_server/mod_cgi.erl
index d961ac655f..15164df576 100644
--- a/lib/inets/src/http_server/mod_cgi.erl
+++ b/lib/inets/src/http_server/mod_cgi.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -208,7 +208,7 @@ deliver_webpage(#mod{config_db = Db} = ModData, Port) ->
{proceed, [{real_name,
httpd_util:split_path(AbsPath)} |
ModData#mod.data]};
- {ok, HTTPHeaders, Status} ->
+ {ok, HTTPHeaders, Status} when is_binary(Body)->
IsDisableChunkedSend =
httpd_response:is_disable_chunked_send(Db),
case (ModData#mod.http_version =/= "HTTP/1.1") or
@@ -222,7 +222,7 @@ deliver_webpage(#mod{config_db = Db} = ModData, Port) ->
[{"transfer-encoding",
"chunked"} | HTTPHeaders])
end,
- handle_body(Port, ModData, Body, Timeout, size(Body),
+ handle_body(Port, ModData, Body, Timeout, byte_size(Body),
IsDisableChunkedSend)
end;
{'EXIT', Port, Reason} ->
@@ -268,8 +268,8 @@ handle_body(Port, #mod{method = "HEAD"} = ModData, _, _, Size, _) ->
handle_body(Port, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
- {Port, {data, Data}} when is_port(Port) ->
- handle_body(Port, ModData, Data, Timeout, Size + size(Data),
+ {Port, {data, Data}} when is_port(Port), is_binary(Data) ->
+ handle_body(Port, ModData, Data, Timeout, Size + byte_size(Data),
IsDisableChunkedSend);
{'EXIT', Port, normal} when is_port(Port) ->
httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index d85df269ce..405e86105a 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2021. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -86,7 +86,7 @@ ERL_COMPILE_FLAGS += \
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 0ec8ca9cd8..cfd963d678 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -97,5 +97,5 @@
%% If the "new" ssl is used then 'crypto' must be started before inets.
{applications,[kernel,stdlib]},
{mod,{inets_app,[]}},
- {runtime_dependencies, ["stdlib-3.5","ssl-5.3.4","runtime_tools-1.8.14",
- "mnesia-4.12","kernel-3.0","erts-6.0"]}]}.
+ {runtime_dependencies, ["stdlib-4.0","ssl-9.0","runtime_tools-1.8.14",
+ "mnesia-4.12","kernel-6.0","erts-6.0", "public_key-1.13"]}]}.
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index b197590bfd..e9b88dc469 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,11 +18,13 @@
%% %CopyrightEnd%
{"%VSN%",
[
+ {<<"8\\..*">>,[{restart_application, inets}]},
{<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
],
[
+ {<<"8\\..*">>,[{restart_application, inets}]},
{<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 2d7efe55df..414884a535 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -200,6 +200,7 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
ERL_COMPILE_FLAGS += \
$(INCLUDES) \
$(INETS_FLAGS)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
@@ -209,7 +210,7 @@ ERL_COMPILE_FLAGS += \
# 1) INETS_PRIV_DIR must be created
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 77a56cf1b8..22bd55355c 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
-module(httpc_SUITE).
+-include_lib("stdlib/include/assert.hrl").
-include_lib("kernel/include/file.hrl").
-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
@@ -73,7 +74,7 @@ groups() ->
{sim_http, [], only_simulated() ++ server_closing_connection() ++ [process_leak_on_keepalive]},
{http_internal, [], real_requests_esi()},
{http_unix_socket, [], simulated_unix_socket()},
- {https, [], real_requests()},
+ {https, [], [def_ssl_opt | real_requests()]},
{sim_https, [], only_simulated()},
{misc, [], misc()},
{sim_mixed, [], sim_mixed()}
@@ -136,8 +137,8 @@ real_requests()->
invalid_method,
no_scheme,
invalid_uri,
- undefined_port,
- binary_url
+ binary_url,
+ iolist_body
].
real_requests_esi() ->
@@ -180,6 +181,7 @@ only_simulated() ->
redirect_found,
redirect_see_other,
redirect_temporary_redirect,
+ redirect_permanent_redirect,
redirect_relative_uri,
port_in_host_header,
redirect_port_in_host_header,
@@ -258,8 +260,8 @@ init_per_group(http_unix_socket = Group, Config0) ->
file:delete(?UNIX_SOCKET),
start_apps(Group),
Config = proplists:delete(port, Config0),
- Port = server_start(Group, server_config(Group, Config)),
- [{port, Port} | Config]
+ {Pid, Port} = server_start(Group, server_config(Group, Config)),
+ lists:append([{dummy_server_pid, Pid}, {port, Port}], Config)
end;
init_per_group(http_ipv6 = Group, Config0) ->
case is_ipv6_supported() of
@@ -277,7 +279,16 @@ init_per_group(Group, Config0) ->
Port = server_start(Group, server_config(Group, Config)),
[{port, Port} | Config].
-end_per_group(http_unix_socket,_Config) ->
+end_per_group(http_unix_socket, Config) ->
+ Pid = ?config(dummy_server_pid, Config),
+ Pid ! {stop, self()},
+ %% request is needed for enforcing dummy server and handlers stop; without a
+ %% it, dummy server waits in gen_tcp:accept and will not process stop request
+ httpc:request(get, {"http://localhost/v1/kv/foo", []}, [], []),
+ receive
+ {stopped, DummyServerPid} ->
+ ok
+ end,
file:delete(?UNIX_SOCKET),
ok;
end_per_group(_, _Config) ->
@@ -420,7 +431,7 @@ post() ->
"only care about the client side of the the post. The server "
"script will not actually use the post data."}].
post(Config) when is_list(Config) ->
- CGI = case test_server:os_type() of
+ CGI = case os:type() of
{win32, _} ->
"/cgi-bin/cgi_echo.exe";
_ ->
@@ -445,7 +456,7 @@ delete() ->
"only care about the client side of the the delete. The server "
"script will not actually use the delete data."}].
delete(Config) when is_list(Config) ->
- CGI = case test_server:os_type() of
+ CGI = case os:type() of
{win32, _} ->
"/cgi-bin/cgi_echo.exe";
_ ->
@@ -469,7 +480,7 @@ patch() ->
"only care about the client side of the the patch. The server "
"script will not actually use the patch data."}].
patch(Config) when is_list(Config) ->
- CGI = case test_server:os_type() of
+ CGI = case os:type() of
{win32, _} ->
"/cgi-bin/cgi_echo.exe";
_ ->
@@ -491,7 +502,7 @@ post_stream() ->
"We only care about the client side of the the post. "
"The server script will not actually use the post data."}].
post_stream(Config) when is_list(Config) ->
- CGI = case test_server:os_type() of
+ CGI = case os:type() of
{win32, _} ->
"/cgi-bin/cgi_echo.exe";
_ ->
@@ -748,6 +759,26 @@ redirect_temporary_redirect(Config) when is_list(Config) ->
= httpc:request(post, {URL307, [],"text/plain", "foobar"},
[], []).
%%-------------------------------------------------------------------------
+redirect_permanent_redirect() ->
+ [{doc, "The server SHOULD generate a Location header field in the response "
+ "containing a preferred URI reference for the new permanent URI. "
+ "The user agent MAY use the Location field value for automatic redirection. "
+ "The server's response content usually contains a short hypertext note with "
+ "a hyperlink to the new URI(s)."}].
+redirect_permanent_redirect(Config) when is_list(Config) ->
+
+ URL308 = url(group_name(Config), "/308.html", Config),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL308, []}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL308, []}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL308, [],"text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
redirect_relative_uri() ->
[{doc, "The server SHOULD generate a Location header field in the response "
"containing a preferred URI reference for the new permanent URI. The user "
@@ -1350,6 +1381,62 @@ binary_url(Config) ->
URL = uri_string:normalize(url(group_name(Config), "/dummy.html", Config)),
{ok, _Response} = httpc:request(unicode:characters_to_binary(URL)).
+%%-------------------------------------------------------------------------
+
+iolist_body(Config) ->
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
+ {ok,{_,Port}} = inet:sockname(ListenSocket),
+
+ ProcessHeaders =
+ fun
+ F([], Acc) ->
+ Acc;
+ F([Line|Tail], Acc0) ->
+ Acc1 =
+ case binary:split(Line, <<": ">>, [trim_all]) of
+ [Key, Value] ->
+ Acc0#{Key => Value};
+ _ ->
+ Acc0
+ end,
+ F(Tail, Acc1)
+ end,
+
+ proc_lib:spawn(fun() ->
+ {ok, Accept} = gen_tcp:accept(ListenSocket),
+ receive
+ {tcp, Accept, Msg} ->
+ ct:log("Message received: ~p", [Msg]),
+ [_HeadLine | HeaderLines] = binary:split(Msg, <<"\r\n">>, [global]),
+ Headers = ProcessHeaders(HeaderLines, #{}),
+ ContentLength = maps:get(<<"content-length">>, Headers, "-1"),
+ gen_tcp:send(Accept, [
+ "HTTP/1.1 200 OK\r\n",
+ "\r\n",
+ ContentLength
+ ])
+ after
+ 1000 ->
+ ct:fail("Timeout: did not receive packet")
+ end
+ end),
+
+ {ok, Host} = inet:gethostname(),
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port),
+ ReqBody = [
+ <<"abc">>,
+ <<"def">>
+ ],
+ {ok, Resp} = httpc:request(post, {URL, _Headers = [], _ContentType = "text/plain", ReqBody}, [], []),
+ ct:log("Got response ~p", [Resp]),
+ case Resp of
+ {{"HTTP/1.1", 200, "OK"}, [], RespBody} ->
+ ReqBody_ContentLength = list_to_integer([C || C <- RespBody, C =/= $\s]),
+ ?assertEqual(iolist_size(ReqBody), ReqBody_ContentLength);
+ _ ->
+ ct:fail("Didn't receive the correct response")
+ end.
+
%%-------------------------------------------------------------------------
@@ -1367,12 +1454,6 @@ invalid_uri(Config) ->
{error, invalid_uri} = httpc:request(URL),
ok.
-%%-------------------------------------------------------------------------
-
-undefined_port(_Config) ->
- {error, {failed_connect, _Reason}} = httpc:request("http://:"),
- ok.
-
%%-------------------------------------------------------------------------
remote_socket_close(Config) when is_list(Config) ->
@@ -1807,7 +1888,16 @@ request_options(Config) when is_list(Config) ->
[{socket_opts,[{ipfamily, inet6}]}]),
{error,{failed_connect,_ }} = httpc:request(get, Request, [], []).
-
+%%--------------------------------------------------------------------
+def_ssl_opt(_Config) ->
+ CaCerts = public_key:cacerts_get(),
+ Ver = {verify, verify_peer},
+ Certs = {cacerts, CaCerts},
+ [Ver, Certs] = httpc:ssl_verify_host_options(false),
+ [Ver, Certs | WildCard] = httpc:ssl_verify_host_options(true),
+ [{customize_hostname_check, [{match_fun, _}]}] = WildCard,
+ {'EXIT', _} = catch httpc:ssl_verify_host_options(other),
+ ok.
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
@@ -1955,9 +2045,9 @@ server_start(http_unix_socket, Config) ->
Inet = local,
Socket = proplists:get_value(unix_socket, Config),
ok = httpc:set_options([{ipfamily, Inet},{unix_socket, Socket}]),
- {_Pid, Port} = http_test_lib:dummy_server(unix_socket, Inet, [{content_cb, ?MODULE},
+ {Pid, Port} = http_test_lib:dummy_server(unix_socket, Inet, [{content_cb, ?MODULE},
{unix_socket, Socket}]),
- Port;
+ {Pid, Port};
server_start(http_ipv6, HttpdConfig) ->
{ok, Pid} = inets:start(httpd, HttpdConfig),
Serv = inets:services_info(),
@@ -2007,7 +2097,7 @@ server_config(http_internal, Config) ->
{erl_script_alias, {"", [httpc_SUITE]}}
];
server_config(https, Config) ->
- [{socket_type, {essl, ssl_config(Config)}} | server_config(http, Config)];
+ [{socket_type, {ssl, ssl_config(Config)}} | server_config(http, Config)];
server_config(sim_https, Config) ->
ssl_config(Config);
server_config(http_unix_socket, _Config) ->
@@ -2051,7 +2141,7 @@ setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
end
end, Files),
- Cgi = case test_server:os_type() of
+ Cgi = case os:type() of
{win32, _} ->
"cgi_echo.exe";
_ ->
@@ -2093,7 +2183,7 @@ receive_replys([ID|IDs]) ->
{http, {ID, {{_, 200, _}, [_|_], _}}} ->
receive_replys(IDs);
{http, {Other, {{_, 200, _}, [_|_], _}}} ->
- ct:pal({recived_canceld_id, Other})
+ ct:pal("~p",[{recived_canceld_id, Other}])
end.
@@ -2262,7 +2352,7 @@ handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket, _) ->
stop;
_ ->
ContentLength = content_length(Headers),
- case size(Body) - ContentLength of
+ case byte_size(Body) - ContentLength of
0 ->
<<>>;
_ ->
@@ -2532,6 +2622,21 @@ handle_uri(_,"/307.html",Port,_,Socket,_) ->
"Location:" ++ NewUri ++ "\r\n" ++
"Content-Length:" ++ integer_to_list(length(Body))
++ "\r\n\r\n" ++ Body;
+handle_uri("HEAD","/308.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ "HTTP/1.1 308 Permanent Redirect \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+handle_uri(_,"/308.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 308 Permanent Redirect \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
handle_uri(_,"/404.html",_,_,_,_) ->
"HTTP/1.1 404 not found\r\n" ++
diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl
index ebd5ed8d02..02751dfdf4 100644
--- a/lib/inets/test/httpc_proxy_SUITE.erl
+++ b/lib/inets/test/httpc_proxy_SUITE.erl
@@ -78,14 +78,15 @@ local_proxy_cases() ->
http_not_modified_otp_6821].
local_proxy_https_cases() ->
- [https_connect_error].
+ [https_connect_error,
+ http_timeout].
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
case init_apps(suite_apps(), Config0) of
Config when is_list(Config) ->
- make_cert_files(dsa, "server-", Config),
+ make_cert_files(Config),
Config;
Other ->
Other
@@ -445,6 +446,21 @@ https_connect_error(Config) when is_list(Config) ->
httpc:request(Method, Request, HttpOpts, Opts).
%%--------------------------------------------------------------------
+http_timeout(doc) ->
+ ["Test http/https connect and upgrade timeouts."];
+http_timeout(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ Timeout = timer:seconds(1),
+ HttpOpts1 = [{timeout, Timeout}, {connect_timeout, 0}],
+ {error,
+ {failed_connect,
+ [{to_address,{"localhost",8000}},
+ {inet,[inet],timeout}]}}
+ = httpc:request(Method, Request, HttpOpts1, []),
+ ok.
+%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -489,7 +505,7 @@ app_start(App, Config) ->
app_stop(App) ->
application:stop(App).
-make_cert_files(Alg, Prefix, Config) ->
+make_cert_files(Config) ->
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client"]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server"]),
GenCertData =
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index c1438ca1ca..bea29a3445 100644
--- a/lib/inets/test/httpd_1_1.erl
+++ b/lib/inets/test/httpd_1_1.erl
@@ -244,7 +244,7 @@ head(Type, Port, Host, Node)->
[{statuscode, 200}]),
%% mod_cgi
Script =
- case test_server:os_type() of
+ case os:type() of
{win32, _} ->
"printenv.bat";
_ ->
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 9645937c36..1df6251d41 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
%%
%% ct:run("../inets_test", httpd_SUITE).
%%
-
+-compile({no_auto_import,[alias/1]}).
-module(httpd_SUITE).
-include_lib("kernel/include/file.hrl").
@@ -30,7 +30,7 @@
-include_lib("public_key/include/public_key.hrl").
-include_lib("inets/include/httpd.hrl").
-include("inets_test_lib.hrl").
-
+-include_lib("stdlib/include/assert.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -1043,7 +1043,7 @@ cgi() ->
cgi(Config) when is_list(Config) ->
{Script, Script2, Script3} =
- case test_server:os_type() of
+ case os:type() of
{win32, _} ->
{"printenv.bat", "printenv.sh", "cgi_echo.exe"};
_ ->
@@ -1118,7 +1118,7 @@ cgi_chunked_encoding_test() ->
cgi_chunked_encoding_test(Config) when is_list(Config) ->
Host = proplists:get_value(host, Config),
Script =
- case test_server:os_type() of
+ case os:type() of
{win32, _} ->
"/cgi-bin/printenv.bat";
_ ->
@@ -1148,30 +1148,48 @@ alias_1_0(Config) when is_list(Config) ->
alias() ->
[{doc, "Test mod_alias"}].
-alias(Config) when is_list(Config) ->
- ok = http_status("GET /pics/icon.sheet.gif ", Config,
- [{statuscode, 200},
- {header, "Content-Type","image/gif"},
- {header, "Server"},
- {header, "Date"}]),
-
- ok = http_status("GET / ", Config,
- [{statuscode, 200},
- {header, "Content-Type","text/html"},
- {header, "Server"},
- {header, "Date"}]),
-
- ok = http_status("GET /misc/ ", Config,
- [{statuscode, 200},
- {header, "Content-Type","text/html"},
- {header, "Server"},
- {header, "Date"}]),
-
- %% Check redirection if trailing slash is missing.
- ok = http_status("GET /misc ", Config,
- [{statuscode, 301},
- {header, "Location"},
- {header, "Content-Type","text/html"}]).
+alias(Config) when is_list(Config) ->
+ TestURIs200 = [
+ {"GET /pics/icon.sheet.gif ", 200, "image/gif"},
+ {"GET / ", 200, "text/html"},
+ {"GET /misc/ ", 200, "text/html"}
+ ],
+ Test200 =
+ fun({Request, ResultCode, ContentType}) ->
+ ct:log("Request: ~s Expecting: ~p ~s",
+ [Request, ResultCode, ContentType]),
+ ok = http_status(Request, Config,
+ [{statuscode, ResultCode},
+ {header, "Content-Type", ContentType},
+ {header, "Server"},
+ {header, "Date"}])
+ end,
+ [Test200(T) || T <- TestURIs200],
+ TestURIs301 =
+ [
+ %% Check redirection if trailing slash is missing.
+ {"GET /misc ", 301, "text/html", "&#47;misc&#47;$"},
+ %% slash character expected after path(misc) not query component
+ {"GET /misc?test=test ", 301, "text/html", "&#47;misc&#47;\\?test=test$"}
+ ],
+ Test301 =
+ fun({Request, ResultCode, ContentType, TargetLinkRegexp}) ->
+ ct:log("Request: ~s Expecting: ~p ~s RE: ~s",
+ [Request, ResultCode, ContentType, TargetLinkRegexp]),
+ {ok, [RedirectLink]} =
+ http_status(Request, Config,
+ [{statuscode, ResultCode},
+ {header, "Content-Type", ContentType},
+ {header, "Server"},
+ {header, "Date"},
+ {fetch_hrefs, true}]),
+ ReResult = re:run(RedirectLink, TargetLinkRegexp),
+ ct:log("RedirectLink = ~p", [RedirectLink]),
+ ?assertMatch({match, _}, ReResult)
+ end,
+ [Test301(T) || T <- TestURIs301],
+ ok.
+
%%-------------------------------------------------------------------------
actions() ->
[{doc, "Test mod_actions"}].
@@ -1958,7 +1976,7 @@ setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
inets_test_lib:copy_dirs(PicsSrc, PicsDir),
inets_test_lib:copy_dirs(ConfigSrc, ConfigDir),
- Cgi = case test_server:os_type() of
+ Cgi = case os:type() of
{win32, _} ->
"cgi_echo.exe";
_ ->
@@ -2125,7 +2143,7 @@ server_config(http_rel_path_script_alias, Config) ->
server_config(https, Config) ->
SSLConf = proplists:get_value(ssl_conf, Config),
ServerConf = proplists:get_value(server_config, SSLConf),
- [{socket_type, {essl,
+ [{socket_type, {ssl,
[{nodelay, true} | ServerConf]}}]
++ proplists:delete(socket_type, server_config(http, Config)).
diff --git a/lib/inets/test/httpd_all.erl b/lib/inets/test/httpd_all.erl
index 9be02e3fd8..b4845e4cf0 100644
--- a/lib/inets/test/httpd_all.erl
+++ b/lib/inets/test/httpd_all.erl
@@ -128,7 +128,7 @@ esi(Version, Type, Port, Host, Node) ->
cgi(Version, Type, Port, Host, Node) ->
{Script, Script2, Script3} =
- case test_server:os_type() of
+ case os:type() of
{win32, _} ->
{"printenv.bat", "printenv.sh", "cgi_echo.exe"};
_ ->
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index c6b35eb756..bbeb49083e 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ DUMMY
DummyFile = filename:join([PrivDir,"dummy.html"]),
CgiDir = filename:join(PrivDir, "cgi-bin"),
ok = file:make_dir(CgiDir),
- {CgiPrintEnv, CgiSleep} = case test_server:os_type() of
+ {CgiPrintEnv, CgiSleep} = case os:type() of
{win32, _} ->
{"printenv.bat", "cgi_sleep.exe"};
_ ->
diff --git a/lib/inets/test/httpd_bench_SUITE.erl b/lib/inets/test/httpd_bench_SUITE.erl
index ecfb32cb6e..65897176a4 100644
--- a/lib/inets/test/httpd_bench_SUITE.erl
+++ b/lib/inets/test/httpd_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -634,7 +634,7 @@ do_handle_request(CB, S, Name, Opts, KeepAlive) when is_list(Name) ->
send_file(CB, S, Fdesc);
do_handle_request(CB, S, {gen, Data}, Opts, KeepAlive) ->
Version = proplists:get_value(http_version, Opts),
- Length = size(Data),
+ Length = byte_size(Data),
Response = response_status_line_and_headers(Version, "Content-Length:"
++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
CB:send(S, Response),
@@ -643,7 +643,7 @@ do_handle_request(CB, S, {gen, Data}, Opts, KeepAlive) ->
send_file(CB, S, {gen, Data}) ->
CB:send(S, Data);
%% ChunkSize = 64*1024,
- %% case size(Data) of
+ %% case byte_size(Data) of
%% N when N > ChunkSize ->
%% <<Chunk:N/binary, Rest/binary>> = Data,
%% %%{Chunk, Rest} = lists:split(N, Data),
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index 2add30099d..a133490cfe 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -611,7 +611,7 @@ htaccess(Type, Port, Host, Node) ->
%%--------------------------------------------------------------------
cgi(Type, Port, Host, Node) ->
{Script, Script2, Script3} =
- case test_server:os_type() of
+ case os:type() of
{win32, _} ->
{"printenv.bat", "printenv.sh", "cgi_echo.exe"};
_ ->
diff --git a/lib/inets/test/httpd_poll.erl b/lib/inets/test/httpd_poll.erl
index f86e3a979b..6fabb572ea 100644
--- a/lib/inets/test/httpd_poll.erl
+++ b/lib/inets/test/httpd_poll.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -299,7 +299,7 @@ add(_N1, N2) when is_integer(N2) ->
sz(L) when is_list(L) ->
length(lists:flatten(L));
sz(B) when is_binary(B) ->
- size(B);
+ byte_size(B);
sz(O) ->
{unknown_size,O}.
@@ -332,6 +332,7 @@ status_to_message(303) -> "Section 10.3.4: See Other";
status_to_message(304) -> "Section 10.3.5: Not Modified";
status_to_message(305) -> "Section 10.3.6: Use Proxy";
status_to_message(307) -> "Section 10.3.8: Temporary Redirect";
+status_to_message(308) -> "RFC 9110, Section 15.4.9: Permanent Redirect";
status_to_message(400) -> "Section 10.4.1: Bad Request";
status_to_message(401) -> "Section 10.4.2: Unauthorized";
status_to_message(402) -> "Section 10.4.3: Peyment Required";
diff --git a/lib/inets/test/httpd_test_data/server_root/Makefile b/lib/inets/test/httpd_test_data/server_root/Makefile
index ed4d63a3bb..4defc918ca 100644
--- a/lib/inets/test/httpd_test_data/server_root/Makefile
+++ b/lib/inets/test/httpd_test_data/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -163,7 +163,7 @@ ERL_COMPILE_FLAGS +=
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 4f26437d78..678ffeaae7 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -407,7 +407,7 @@ check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.1\r\n\r\n", 200, "text
ct:fail({content_length_error, Length});
check_body("GET /cgi-bin/cgi_echo HTTP/1.0\r\n\r\n", 200, "text/plain",
_, Body) ->
- case size(Body) of
+ case byte_size(Body) of
100 ->
ok;
_ ->
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index 87a913fce4..a31f40ce63 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -417,7 +417,7 @@ validate(ExpStatusCode, _SocketType, _Socket, Response) ->
sz(L) when is_list(L) ->
length(lists:flatten(L));
sz(B) when is_binary(B) ->
- size(B);
+ byte_size(B);
sz(O) ->
{unknown_size,O}.
@@ -450,6 +450,7 @@ status_to_message(303) -> "Section 10.3.4: See Other";
status_to_message(304) -> "Section 10.3.5: Not Modified";
status_to_message(305) -> "Section 10.3.6: Use Proxy";
status_to_message(307) -> "Section 10.3.8: Temporary Redirect";
+status_to_message(308) -> "RFC 9110, Section 15.4.9: Permanent Redirect";
status_to_message(400) -> "Section 10.4.1: Bad Request";
status_to_message(401) -> "Section 10.4.2: Unauthorized";
status_to_message(402) -> "Section 10.4.3: Peyment Required";
diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl
index db6a8bdfc3..d8e7b419d9 100644
--- a/lib/inets/test/uri_SUITE.erl
+++ b/lib/inets/test/uri_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,20 +41,7 @@ suite() ->
[{ct_hooks,[ts_install_cth]}].
all() ->
- [
- ipv4,
- ipv6,
- host,
- userinfo,
- scheme,
- queries,
- fragments,
- escaped,
- hexed_query,
- scheme_validation,
- scheme_validation_bin,
- encode_decode
- ].
+ [encode_decode].
%%--------------------------------------------------------------------
@@ -74,225 +61,6 @@ end_per_testcase(_Case, _Config) ->
%% Test cases starts here.
%%-------------------------------------------------------------------------
-ipv4(Config) when is_list(Config) ->
- {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
- http_uri:parse("http://127.0.0.1/foobar.html"),
-
- {ok, {http,<<>>,<<"127.0.0.1">>,80,<<"/foobar.html">>,<<>>}} =
- http_uri:parse(<<"http://127.0.0.1/foobar.html">>).
-
-ipv6(Config) when is_list(Config) ->
- {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"}} =
- 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">>}} =
- http_uri:parse(<<"http://2010:836B:4179::836B:4179/foobar.html">>).
-
-host(Config) when is_list(Config) ->
- {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://localhost:8888/foobar.html"),
-
- {ok, {http,<<>>,<<"localhost">>,8888,<<"/foobar.html">>,<<>>}} =
- http_uri:parse(<<"http://localhost:8888/foobar.html">>).
-
-userinfo(Config) when is_list(Config) ->
- {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("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(Config) when is_list(Config) ->
- {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
- {error, {malformed_url, _, _}} =
- http_uri:parse("localhost:8888/foobar.html"),
-
- {error, no_scheme} = http_uri:parse(<<"localhost/foobar.html">>),
- {error, {malformed_url, _, _}} =
- http_uri:parse(<<"localhost:8888/foobar.html">>).
-
-queries(Config) when is_list(Config) ->
- {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
- http_uri:parse("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">>).
-
-fragments(Config) when is_list(Config) ->
- {ok, {http,[],"localhost",80,"/",""}} =
- http_uri:parse("http://localhost#fragment"),
- {ok, {http,[],"localhost",80,"/path",""}} =
- http_uri:parse("http://localhost/path#fragment"),
- {ok, {http,[],"localhost",80,"/","?query"}} =
- http_uri:parse("http://localhost?query#fragment"),
- {ok, {http,[],"localhost",80,"/path","?query"}} =
- http_uri:parse("http://localhost/path?query#fragment"),
- {ok, {http,[],"localhost",80,"/","","#fragment"}} =
- http_uri:parse("http://localhost#fragment", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/path","","#fragment"}} =
- http_uri:parse("http://localhost/path#fragment", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/","?query","#fragment"}} =
- http_uri:parse("http://localhost?query#fragment", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/path","?query","#fragment"}} =
- http_uri:parse("http://localhost/path?query#fragment",
- [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/","",""}} =
- http_uri:parse("http://localhost", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/path","",""}} =
- http_uri:parse("http://localhost/path", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/","?query",""}} =
- http_uri:parse("http://localhost?query", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/path","?query",""}} =
- http_uri:parse("http://localhost/path?query", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/","","#"}} =
- http_uri:parse("http://localhost#", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/path","","#"}} =
- http_uri:parse("http://localhost/path#", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/","?query","#"}} =
- http_uri:parse("http://localhost?query#", [{fragment,true}]),
- {ok, {http,[],"localhost",80,"/path","?query","#"}} =
- http_uri:parse("http://localhost/path?query#", [{fragment,true}]),
-
-
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>}} =
- http_uri:parse(<<"http://localhost#fragment">>),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>}} =
- http_uri:parse(<<"http://localhost/path#fragment">>),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>}} =
- http_uri:parse(<<"http://localhost?query#fragment">>),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>}} =
- http_uri:parse(<<"http://localhost/path?query#fragment">>),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>,<<"#fragment">>}} =
- http_uri:parse(<<"http://localhost#fragment">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>,<<"#fragment">>}} =
- http_uri:parse(<<"http://localhost/path#fragment">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>,<<"#fragment">>}} =
- http_uri:parse(<<"http://localhost?query#fragment">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>,<<"#fragment">>}} =
- http_uri:parse(<<"http://localhost/path?query#fragment">>,
- [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>,<<"">>}} =
- http_uri:parse(<<"http://localhost">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>,<<"">>}} =
- http_uri:parse(<<"http://localhost/path">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>,<<"">>}} =
- http_uri:parse(<<"http://localhost?query">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>,<<"">>}} =
- http_uri:parse(<<"http://localhost/path?query">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"">>,<<"#">>}} =
- http_uri:parse(<<"http://localhost#">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"">>,<<"#">>}} =
- http_uri:parse(<<"http://localhost/path#">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<"?query">>,<<"#">>}} =
- http_uri:parse(<<"http://localhost?query#">>, [{fragment,true}]),
- {ok, {http,<<>>,<<"localhost">>,80,<<"/path">>,<<"?query">>,<<"#">>}} =
- http_uri:parse(<<"http://localhost/path?query#">>, [{fragment,true}]),
- ok.
-
-escaped(Config) when is_list(Config) ->
- {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
- http_uri:parse("http://www.somedomain.com/%2Eabc"),
- {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
- http_uri:parse("http://www.somedomain.com/%252Eabc"),
- {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
- http_uri:parse("http://www.somedomain.com/%25abc"),
- {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
- http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
-
- {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%2Eabc">>,<<>>}} =
- http_uri:parse(<<"http://www.somedomain.com/%2Eabc">>),
- {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%252Eabc">>,<<>>}} =
- http_uri:parse(<<"http://www.somedomain.com/%252Eabc">>),
- {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%25abc">>,<<>>}} =
- http_uri:parse(<<"http://www.somedomain.com/%25abc">>),
- {ok, {http,<<>>,<<"www.somedomain.com">>,80,<<"/%25abc">>, <<"?foo=bar">>}} =
- http_uri:parse(<<"http://www.somedomain.com/%25abc?foo=bar">>).
-
-hexed_query(doc) ->
- [{doc, "Solves OTP-6191"}];
-hexed_query(Config) when is_list(Config) ->
- Google = ?GOOGLE,
- GoogleSearch = "http://" ++ Google ++ "/search",
- Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
- URI1 = GoogleSearch ++ Search1,
- Search2 = "?hl=en&q=%25%25",
- URI2 = GoogleSearch ++ Search2,
- Search3 = "?hl=en&q=%foo",
- URI3 = GoogleSearch ++ Search3,
-
- 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).
-
-scheme_validation(Config) when is_list(Config) ->
- {ok, {http,[],"localhost",80,"/",""}} =
- http_uri:parse("http://localhost#fragment"),
-
- ValidationFun =
- fun("http") -> valid;
- (_) -> {error, bad_scheme}
- end,
-
- {ok, {http,[],"localhost",80,"/",""}} =
- http_uri:parse("http://localhost#fragment",
- [{scheme_validation_fun, ValidationFun}]),
- {error, bad_scheme} =
- http_uri:parse("https://localhost#fragment",
- [{scheme_validation_fun, ValidationFun}]),
- %% non-fun scheme_validation_fun works as no option passed
- {ok, {https,[],"localhost",443,"/",""}} =
- http_uri:parse("https://localhost#fragment",
- [{scheme_validation_fun, none}]).
-
-scheme_validation_bin(Config) when is_list(Config) ->
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<>>}} =
- http_uri:parse(<<"http://localhost#fragment">>),
-
- ValidationFun =
- fun(<<"http">>) -> valid;
- (_) -> {error, bad_scheme}
- end,
-
- {ok, {http,<<>>,<<"localhost">>,80,<<"/">>,<<>>}} =
- http_uri:parse(<<"http://localhost#fragment">>,
- [{scheme_validation_fun, ValidationFun}]),
- {error, bad_scheme} =
- http_uri:parse(<<"https://localhost#fragment">>,
- [{scheme_validation_fun, ValidationFun}]),
- %% non-fun scheme_validation_fun works as no option passed
- {ok, {https,<<>>,<<"localhost">>,443,<<"/">>,<<>>}} =
- http_uri:parse(<<"https://localhost#fragment">>,
- [{scheme_validation_fun, none}]).
encode_decode(Config) when is_list(Config) ->
?assertEqual("foo%20bar", http_uri:encode("foo bar")),
@@ -304,24 +72,3 @@ encode_decode(Config) when is_list(Config) ->
?assertEqual(<<"foo bar">>, http_uri:decode(<<"foo%20bar">>)),
?assertEqual("foo\r\n", http_uri:decode("foo%0D%0A")),
?assertEqual(<<"foo\r\n">>, http_uri:decode(<<"foo%0D%0A">>)).
-
-
-%%--------------------------------------------------------------------
-%% Internal Functions ------------------------------------------------
-%%--------------------------------------------------------------------
-
-
-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.
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index c2ae51ae51..99285501c5 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 7.5.3
+INETS_VSN = 8.3
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/doc/src/Makefile b/lib/jinterface/doc/src/Makefile
index 47e269a273..304dad5547 100644
--- a/lib/jinterface/doc/src/Makefile
+++ b/lib/jinterface/doc/src/Makefile
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2021. All Rights Reserved.
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ JAVA_SRC_FILES = $(JAVA_FILES:%=$(JAVA_SRC_PATH)/%.java)
../html/java/index.html: $(JAVA_SRC_FILES)
- (cd ../../java_src;$(JAVADOC) -sourcepath . -d $(JAVADOC_DEST) \
+ (cd ../../java_src;$(JAVADOC) -encoding UTF-8 -sourcepath . -d $(JAVADOC_DEST) \
-windowtitle $(JAVADOC_TITLE) $(JAVADOC_PKGS))
html: ../html/java/index.html
diff --git a/lib/jinterface/doc/src/jinterface_users_guide.xml b/lib/jinterface/doc/src/jinterface_users_guide.xml
index 686fb9565e..cffaa50793 100644
--- a/lib/jinterface/doc/src/jinterface_users_guide.xml
+++ b/lib/jinterface/doc/src/jinterface_users_guide.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2021</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
</legalnotice>
<title>The Jinterface Package</title>
@@ -140,17 +140,29 @@
unique name in the form of an identifier composed partly of the
hostname on which the node is running, e.g "gurka@sallad.com". Several
such nodes can run on the same host as long as their names are unique.
- The class <seefile marker="java/com/ericsson/otp/erlang/OtpNode">OtpNode</seefile>
- represents an Erlang node. It is created with a name
- and optionally a port number on which it listens for incoming
- connections. Before creating an instance of
- <seefile marker="java/com/ericsson/otp/erlang/OtpNode">OtpNode</seefile>,
- ensure that Epmd is running on the host machine. See the Erlang documentation
- for more information about Epmd. In this example, the host name is appended
+ The class <seefile marker="java/com/ericsson/otp/erlang/OtpNode">OtpNode</seefile>
+ represents an Erlang node.</p>
+ <p>It is created with a name
+ and optionally a TCP/IP socket port number on which it listens for incoming
+ connections. By default before creating an instance of
+ <seefile marker="java/com/ericsson/otp/erlang/OtpNode">OtpNode</seefile>,
+ ensure that Epmd is running on the host machine. See the Erlang documentation
+ for more information about Epmd.</p>
+ <p>In this example, the host name is appended
automatically to the identifier, and the port number is chosen by the
underlying system:</p>
<code type="none">
OtpNode node = new OtpNode("gurka"); </code>
+ <p>It is also possible to use alternative communication (or distribution)
+ protocols without Epmd by switching to a custom transport factory extending
+ the OtpGenericTransportFactory abstract class, for example based on
+ Unix Domain Sockets instead of the default TCP/IP sockets.</p>
+ <p>In this example, the host name is appended automatically to the identifier
+ and a custom transport factory is used:</p>
+ <code type="none">
+OtpGenericTransportFactory customFactory = new MyCustomFactory();
+OtpNode node = new OtpNode("gurka", customFactory);
+ </code>
</section>
<section>
@@ -227,8 +239,11 @@ OtpNode node = new OtpNode("gurka"); </code>
<title>Transport Factory</title>
<p>All necessary connections are made using methods of
<seefile marker="java/com/ericsson/otp/erlang/OtpTransportFactory">OtpTransportFactory</seefile>
- interface. Default OtpTransportFactory implementation is based on standard Socket class.
- User may provide custom transport factory as needed. See java doc for details.</p>
+ interface. The default OtpTransportFactory implementation is based on standard TCP/IP Socket class
+ and relies on epmd. User may provide custom transport factory as needed. See java doc for details.</p>
+ <p>For alternative distribution protocols working without epmd, using a transport factory extending the
+ <seefile marker="java/com/ericsson/otp/erlang/OtpGenericTransportFactory">OtpGenericTransportFactory</seefile>
+ abstract class will disable the automatic epmd registration and lookup in Jinterface.</p>
</section>
<section>
@@ -356,24 +371,25 @@ OtpNode node = new OtpNode("gurka"); </code>
<section>
<title>Using EPMD</title>
- <p>Epmd is the Erlang Port Mapper Daemon. Distributed Erlang nodes
- register with epmd on the localhost to indicate to other nodes that
- they exist and can accept connections. Epmd maintains a register of
- node and port number information, and when a node wishes to connect to
+ <p>Epmd is the Erlang Port Mapper Daemon. By default distributed Erlang
+ nodes register with epmd on the localhost to indicate to other nodes that
+ they exist and can accept connections. Epmd maintains a register of node
+ and socket port number information, and when a node wishes to connect to
another node, it first contacts epmd in order to find out the correct
- port number to connect to.</p>
- <p>The basic interaction with EPMD is done through instances of
+ socket port number to connect to. It is also possible to use alternative
+ distribution protocols which don't need epmd at all.</p>
+ <p>The basic interaction with EPMD is done through instances of
<seefile marker="java/com/ericsson/otp/erlang/OtpEpmd">OtpEpmd</seefile> class.
- Nodes wishing to contact other nodes must first request information
- from Epmd before a connection can be set up, however this is done automatically
+ Nodes wishing to contact other nodes must first request information
+ from Epmd before a connection can be set up, however this is done automatically
by <seefile marker="java/com/ericsson/otp/erlang/OtpSelf#connect(com.ericsson.otp.erlang.OtpPeer)">OtpSelf.connect()</seefile> when necessary. </p>
- <p>When you use <seefile marker="java/com/ericsson/otp/erlang/OtpSelf#connect(com.ericsson.otp.erlang.OtpPeer)">OtpSelf.connect()</seefile> to connect to an Erlang node,
+ <p>When you use <seefile marker="java/com/ericsson/otp/erlang/OtpSelf#connect(com.ericsson.otp.erlang.OtpPeer)">OtpSelf.connect()</seefile> to connect to an Erlang node,
a connection is first made to epmd and, if the node is known, a
connection is then made to the Erlang node.</p>
<p>Java nodes can also register themselves with epmd if they want other
nodes in the system to be able to find and connect to them.
This is done by call to method <seefile marker="java/com/ericsson/otp/erlang/OtpEpmd#publishPort(com.ericsson.otp.erlang.OtpLocalNode)">OtpEpmd.publishPort()</seefile>.</p>
- <p>Be aware that on some systems (such as VxWorks), a failed node will
+ <p>Be aware that on some systems a failed node will
not be detected by this mechanism since the operating system does not
automatically close descriptors that were left open when the node
failed. If a node has failed in this way, epmd will prevent you from
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index ac51bccec8..01eda410cc 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2021</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,73 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.13.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Accept connection setup from OTP 23 and 24 nodes that are
+ not using epmd.</p>
+ <p>
+ Own Id: OTP-18404 Aux Id: GH-6595, PR-6625 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Jinterface 1.13.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix javadoc build error by adding option <c>-encoding
+ UTF-8</c>.</p>
+ <p>
+ Own Id: OTP-18215 Aux Id: PR-6154 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Jinterface 1.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The following distribution flags are now mandatory:
+ <c>DFLAG_BIT_BINARIES</c>, <c>DFLAG_EXPORT_PTR_TAG</c>,
+ <c>DFLAG_MAP_TAGS</c>, <c>DFLAG_NEW_FLOATS</c>, and
+ <c>DFLAG_FUN_TAGS</c>. This mainly concerns libraries or
+ application that implement the distribution protocol
+ themselves.</p>
+ <p>
+ Own Id: OTP-17318 Aux Id: PR-4972 </p>
+ </item>
+ <item>
+ <p>
+ Removed use of node creation value zero as a wildcard.
+ Also prevent zero from being used as creation by
+ <c>erl_interface</c> and <c>jinterface</c> nodes.</p>
+ <p>
+ Own Id: OTP-17682 Aux Id: PR-5347 </p>
+ </item>
+ <item>
+ <p>
+ Add new abstract class <c>OtpGenericTransportFactory</c>
+ to allow implementation of any transport protocol without
+ dependency on epmd.</p>
+ <p>
+ Own Id: OTP-17961 Aux Id: PR-4839 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.12.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -104,6 +171,23 @@
</section>
+<section><title>Jinterface 1.11.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug in <c>OtpOutputStream.write_pid/4</c> and
+ <c>write_ref/3</c> causing faulty encodig. Bug exists
+ since OTP 23.0.</p>
+ <p>
+ Own Id: OTP-17887 Aux Id: ERIERL-750, PR-5640 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.11.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -287,7 +371,7 @@
<list>
<item>
<p>
- Update build scripts to not make assumtions about where
+ Update build scripts to not make assumptions about where
env, cp and perl are located.</p>
<p>
Own Id: OTP-13800</p>
@@ -613,7 +697,7 @@
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>
+ method, avoiding the issue. (Thanks to Vlad Dumitrescu)</p>
<p>
Own Id: OTP-9927</p>
</item>
@@ -1003,4 +1087,3 @@
</section>
</section>
</chapter>
-
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java
index 7ea5d52da7..9e6a35ec36 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractConnection.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -79,7 +79,7 @@ public abstract class AbstractConnection extends Thread {
protected static final int unlinkIdTag = 35;
protected static final int unlinkIdAckTag = 36;
- // MD5 challenge messsage tags
+ // MD5 challenge message tags
protected static final int ChallengeReply = 'r';
protected static final int ChallengeAck = 'a';
protected static final int ChallengeStatus = 's';
@@ -166,18 +166,12 @@ public abstract class AbstractConnection extends Thread {
throws IOException, OtpAuthException {
peer = other;
localNode = self;
- socket = null;
int port;
traceLevel = defaultLevel;
setDaemon(true);
- // now get a connection between the two...
- port = OtpEpmd.lookupPort(peer);
- if (port == 0)
- throw new IOException("No remote node found - cannot connect");
-
- // now find highest common dist value
+ // Find highest common dist value
if (peer.proto != self.proto || self.distHigh < peer.distLow
|| self.distLow > peer.distHigh) {
throw new IOException("No common protocol found - cannot connect");
@@ -187,7 +181,21 @@ public abstract class AbstractConnection extends Thread {
peer.distChoose = peer.distHigh > self.distHigh ? self.distHigh
: peer.distHigh;
- doConnect(port);
+ // Now get a connection between the two nodes
+ if (self.transportFactory instanceof OtpGenericTransportFactory) {
+ // For alternative distribution protocols using a transport factory
+ // extending the OtpGenericTransportFactory class, the notion of
+ // socket port is not used so the remote node is not registered
+ // with Epmd.
+ doGenericConnect();
+
+ } else {
+ // Get the listening port of the remote node registered with Epmd
+ port = OtpEpmd.lookupPort(peer);
+ if (port == 0)
+ throw new IOException("No remote node found - cannot connect");
+ doPortConnect(port);
+ }
name = peer.node();
connected = true;
@@ -1052,27 +1060,51 @@ public abstract class AbstractConnection extends Thread {
}
}
- protected void doConnect(final int port) throws IOException,
+ protected void doPortConnect(final int port) throws IOException,
OtpAuthException {
try {
socket = peer.createTransport(peer.host(), port);
-
if (traceLevel >= handshakeThreshold) {
System.out.println("-> MD5 CONNECT TO " + peer.host() + ":"
+ port);
}
+ doConnect();
+
+ } catch (final OtpAuthException ae) {
+ close();
+ throw ae;
+ } catch (final Exception e) {
+ close();
+ final IOException ioe = new IOException(
+ "Cannot connect to peer node");
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ protected void doConnect() throws IOException, OtpAuthException {
final int send_name_tag = sendName(peer.distChoose, localNode.flags,
- localNode.creation);
+ localNode.creation());
recvStatus();
final int her_challenge = recvChallenge();
final byte[] our_digest = genDigest(her_challenge,
localNode.cookie());
final int our_challenge = genChallenge();
- sendComplement(send_name_tag);
sendChallengeReply(our_challenge, our_digest);
recvChallengeAck(our_challenge);
cookieOk = true;
sendCookie = false;
+ }
+
+ protected void doGenericConnect() throws IOException,
+ OtpAuthException {
+ try {
+ socket = peer.createTransport(peer);
+ if (traceLevel >= handshakeThreshold) {
+ System.out.println("-> MD5 CONNECT TO " + peer.node());
+ }
+ doConnect();
+
} catch (final OtpAuthException ae) {
close();
throw ae;
@@ -1149,79 +1181,36 @@ public abstract class AbstractConnection extends Thread {
final OtpOutputStream obuf = new OtpOutputStream();
final String str = localNode.node();
int send_name_tag;
- if (dist == 5) {
- obuf.write2BE(1+2+4 + str.length());
- send_name_tag = 'n';
- obuf.write1(send_name_tag);
- obuf.write2BE(dist);
- obuf.write4BE(aflags);
- obuf.write(str.getBytes());
- }
- else {
- obuf.write2BE(1+8+4+2 + str.length());
- send_name_tag = 'N';
- obuf.write1(send_name_tag);
- obuf.write8BE(aflags);
- obuf.write4BE(creation);
- obuf.write2BE(str.length());
- obuf.write(str.getBytes());
- }
+ obuf.write2BE(1+8+4+2 + str.length());
+ send_name_tag = 'N';
+ obuf.write1(send_name_tag);
+ obuf.write8BE(aflags);
+ obuf.write4BE(creation);
+ obuf.write2BE(str.length());
+ obuf.write(str.getBytes());
obuf.writeToAndFlush(socket.getOutputStream());
if (traceLevel >= handshakeThreshold) {
System.out.println("-> " + "HANDSHAKE sendName" + " flags="
- + aflags + " dist=" + dist + " local=" + localNode);
+ + aflags + " local=" + localNode);
}
return send_name_tag;
}
- protected void sendComplement(final int send_name_tag)
- throws IOException {
-
- if (send_name_tag == 'n' &&
- (peer.flags & AbstractNode.dFlagHandshake23) != 0) {
- @SuppressWarnings("resource")
- final OtpOutputStream obuf = new OtpOutputStream();
- obuf.write2BE(1+4+4);
- obuf.write1('c');
- final int flagsHigh = (int)(localNode.flags >> 32);
- obuf.write4BE(flagsHigh);
- obuf.write4BE(localNode.creation);
-
- obuf.writeToAndFlush(socket.getOutputStream());
-
- if (traceLevel >= handshakeThreshold) {
- System.out.println("-> " + "HANDSHAKE sendComplement" +
- " flagsHigh=" + flagsHigh +
- " creation=" + localNode.creation);
- }
- }
- }
-
protected void sendChallenge(final long her_flags, final long our_flags,
final int challenge) throws IOException {
@SuppressWarnings("resource")
final OtpOutputStream obuf = new OtpOutputStream();
final String str = localNode.node();
- if ((her_flags & AbstractNode.dFlagHandshake23) == 0) {
- obuf.write2BE(1+2+4+4 + str.length());
- obuf.write1('n');
- obuf.write2BE(5);
- obuf.write4BE(our_flags & 0xffffffff);
- obuf.write4BE(challenge);
- obuf.write(str.getBytes());
- }
- else {
- obuf.write2BE(1+8+4+4+2 + str.length());
- obuf.write1('N');
- obuf.write8BE(our_flags);
- obuf.write4BE(challenge);
- obuf.write4BE(localNode.creation);
- obuf.write2BE(str.length());
- obuf.write(str.getBytes());
- }
+ obuf.write2BE(1+8+4+4+2 + str.length());
+ obuf.write1('N');
+ obuf.write8BE(our_flags);
+ obuf.write4BE(challenge);
+ obuf.write4BE(localNode.creation());
+ obuf.write2BE(str.length());
+ obuf.write(str.getBytes());
obuf.writeToAndFlush(socket.getOutputStream());
@@ -1257,13 +1246,18 @@ public abstract class AbstractConnection extends Thread {
final OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0);
byte[] tmpname;
final int len = tmpbuf.length;
+ long flag_mask;
+
send_name_tag = ibuf.read1();
switch (send_name_tag) {
case 'n':
- apeer.distLow = apeer.distHigh = ibuf.read2BE();
- if (apeer.distLow != 5)
+ if (ibuf.read2BE() != 5)
throw new IOException("Invalid handshake version");
apeer.flags = ibuf.read4BE();
+ flag_mask = (1L << 32) - 1;
+ if ((apeer.flags & AbstractNode.dFlagHandshake23) == 0)
+ throw new IOException("Missing DFLAG_HANDSHAKE_23");
+ apeer.distLow = apeer.distHigh = 6;
tmpname = new byte[len - 7];
ibuf.readN(tmpname);
hisname = OtpErlangString.newString(tmpname);
@@ -1271,9 +1265,13 @@ public abstract class AbstractConnection extends Thread {
case 'N':
apeer.distLow = apeer.distHigh = 6;
apeer.flags = ibuf.read8BE();
+ flag_mask = ~0L;
+ if ((apeer.flags & AbstractNode.dFlagMandatory25Digest) != 0) {
+ apeer.flags |= AbstractNode.mandatoryFlags25;
+ }
if ((apeer.flags & AbstractNode.dFlagHandshake23) == 0)
throw new IOException("Missing DFLAG_HANDSHAKE_23");
- apeer.creation = ibuf.read4BE();
+ apeer.setCreation(ibuf.read4BE());
int namelen = ibuf.read2BE();
tmpname = new byte[namelen];
ibuf.readN(tmpname);
@@ -1283,21 +1281,16 @@ public abstract class AbstractConnection extends Thread {
throw new IOException("Unknown remote node type");
}
- if ((apeer.flags & AbstractNode.dFlagExtendedReferences) == 0) {
- throw new IOException(
- "Handshake failed - peer cannot handle extended references");
- }
-
- if ((apeer.flags & AbstractNode.dFlagExtendedPidsPorts) == 0) {
+ if ((~apeer.flags & flag_mask & AbstractNode.mandatoryFlags) != 0) {
throw new IOException(
- "Handshake failed - peer cannot handle extended pids and ports");
+ "Handshake failed - peer cannot handle all mandatory capabilities");
}
} catch (final OtpErlangDecodeException e) {
throw new IOException("Handshake failed - not enough data");
}
- final int i = hisname.indexOf('@', 0);
+ final int i = hisname.indexOf('@');
apeer.node = hisname;
apeer.alive = hisname.substring(0, i);
apeer.host = hisname.substring(i + 1, hisname.length());
@@ -1319,23 +1312,16 @@ public abstract class AbstractConnection extends Thread {
final OtpInputStream ibuf = new OtpInputStream(buf, 0);
int namelen;
switch (ibuf.read1()) {
- case 'n':
- if (peer.distChoose != 5)
- throw new IOException("Old challenge wrong version");
- peer.distLow = peer.distHigh = ibuf.read2BE();
- peer.flags = ibuf.read4BE();
- if ((peer.flags & AbstractNode.dFlagHandshake23) != 0)
- throw new IOException("Old challenge unexpected DFLAG_HANDHAKE_23");
- challenge = ibuf.read4BE();
- namelen = buf.length - (1+2+4+4);
- break;
case 'N':
peer.distLow = peer.distHigh = peer.distChoose = 6;
peer.flags = ibuf.read8BE();
+ if ((peer.flags & AbstractNode.dFlagMandatory25Digest) != 0) {
+ peer.flags |= AbstractNode.mandatoryFlags25;
+ }
if ((peer.flags & AbstractNode.dFlagHandshake23) == 0)
throw new IOException("New challenge missing DFLAG_HANDHAKE_23");
challenge = ibuf.read4BE();
- peer.creation = ibuf.read4BE();
+ peer.setCreation(ibuf.read4BE());
namelen = ibuf.read2BE();
break;
default:
@@ -1348,15 +1334,9 @@ public abstract class AbstractConnection extends Thread {
throw new IOException(
"Handshake failed - peer has wrong name: " + hisname);
}
-
- if ((peer.flags & AbstractNode.dFlagExtendedReferences) == 0) {
+ if ((peer.flags & AbstractNode.mandatoryFlags) != AbstractNode.mandatoryFlags) {
throw new IOException(
- "Handshake failed - peer cannot handle extended references");
- }
-
- if ((peer.flags & AbstractNode.dFlagExtendedPidsPorts) == 0) {
- throw new IOException(
- "Handshake failed - peer cannot handle extended pids and ports");
+ "Handshake failed - peer cannot handle all mandatory capabilities");
}
} catch (final OtpErlangDecodeException e) {
@@ -1374,8 +1354,7 @@ public abstract class AbstractConnection extends Thread {
protected void recvComplement(int send_name_tag) throws IOException {
- if (send_name_tag == 'n' &&
- (peer.flags & AbstractNode.dFlagHandshake23) != 0) {
+ if (send_name_tag == 'n') {
try {
final byte[] tmpbuf = read2BytePackage();
@SuppressWarnings("resource")
@@ -1385,8 +1364,11 @@ public abstract class AbstractConnection extends Thread {
final long flagsHigh = ibuf.read4BE();
peer.flags |= flagsHigh << 32;
- peer.creation = ibuf.read4BE();
-
+ if ((~peer.flags & AbstractNode.mandatoryFlags) != 0) {
+ throw new IOException("Handshake failed - peer missing" +
+ " mandatory capabilities");
+ }
+ peer.setCreation(ibuf.read4BE());
} catch (final OtpErlangDecodeException e) {
throw new IOException("Handshake failed - not enough data");
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java
index 0d9635393e..179511c0a5 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/AbstractNode.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,21 +95,35 @@ public class AbstractNode implements OtpTransportFactory {
static final int dFlagBigCreation = 0x40000;
static final int dFlagHandshake23 = 0x1000000;
static final int dFlagUnlinkId = 0x2000000;
+ static final int dFlagMandatory25Digest = 0x4000000;
static final long dFlagV4PidsRefs = 0x4L << 32;
+ /* Mandatory flags in OTP 25. */
+ static final long mandatoryFlags25 = dFlagExtendedReferences
+ | dFlagFunTags
+ | dFlagExtendedPidsPorts
+ | dFlagUtf8Atoms
+ | dflagNewFunTags
+ | dFlagBigCreation
+ | dFlagNewFloats
+ | dFlagMapTag
+ | dFlagExportPtrTag
+ | dFlagBitBinaries
+ | dFlagHandshake23;
+
+ /* Mandatory flags for distribution. Keep them in sync with
+ DFLAG_DIST_MANDATORY in erts/emulator/beam/dist.h. */
+ static final long mandatoryFlags = mandatoryFlags25;
+
int ntype = NTYPE_R6;
int proto = 0; // tcp/ip
int distHigh = 6;
- int distLow = 5; // Cannot talk to nodes before R6
- int creation = 0;
- long flags = dFlagExtendedReferences | dFlagExtendedPidsPorts
- | dFlagBitBinaries | dFlagNewFloats | dFlagFunTags
- | dflagNewFunTags | dFlagUtf8Atoms | dFlagMapTag
- | dFlagExportPtrTag
- | dFlagBigCreation
- | dFlagHandshake23
- | dFlagUnlinkId
- | dFlagV4PidsRefs;
+ int distLow = 6; // Cannot talk to nodes before OTP 23
+ private int creation = 0x710000;
+ long flags = mandatoryFlags
+ | dFlagUnlinkId
+ | dFlagV4PidsRefs
+ | dFlagMandatory25Digest;
/* initialize hostname and default cookie */
static {
@@ -190,7 +204,7 @@ public class AbstractNode implements OtpTransportFactory {
this.cookie = cookie;
this.transportFactory = transportFactory;
- final int i = name.indexOf('@', 0);
+ final int i = name.indexOf('@');
if (i < 0) {
alive = name;
host = localHost;
@@ -271,6 +285,13 @@ public class AbstractNode implements OtpTransportFactory {
return creation;
}
+ void setCreation(int cr) throws OtpErlangDecodeException {
+ if (cr == 0) {
+ throw new OtpErlangDecodeException("Node creation 0 not allowed");
+ }
+ this.creation = cr;
+ }
+
/**
* Set the authorization cookie used by this node.
*
@@ -311,4 +332,44 @@ public class AbstractNode implements OtpTransportFactory {
throws IOException {
return transportFactory.createServerTransport(port);
}
+
+ /**
+ * Create a client-side transport for alternative distribution protocols
+ * using a transport factory extending the OtpGenericTransportFactory
+ * abstract class. Connect it to the specified server.
+ *
+ * @param peer
+ * the peer identifying the server to connect to
+ *
+ */
+ public OtpTransport createTransport(final OtpPeer peer)
+ throws IOException {
+ if (transportFactory instanceof OtpGenericTransportFactory) {
+ return ((OtpGenericTransportFactory) transportFactory)
+ .createTransport(peer);
+ }
+ throw new IOException("Method createTransport(OtpPeer) " +
+ "applicable only for Nodes with a transport " +
+ "factory instance of OtpGenericTransportFactory");
+ }
+
+ /**
+ * Create a server-side transport for alternative distribution protocols
+ * using a transport factory extending the OtpGenericTransportFactory
+ * abstract class.
+ *
+ * @param node
+ * the local node identifying the transport to create server-side
+ *
+ */
+ public OtpServerTransport createServerTransport(final OtpLocalNode node)
+ throws IOException {
+ if (transportFactory instanceof OtpGenericTransportFactory) {
+ return ((OtpGenericTransportFactory) transportFactory)
+ .createServerTransport(node);
+ }
+ throw new IOException("Method createServerTransport(OtpLocalNode) " +
+ "applicable only for Nodes with a transport " +
+ "factory instance of OtpGenericTransportFactory");
+ }
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
index e42fd9468d..089cf4ab1a 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/Makefile
@@ -2,9 +2,9 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2021. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -16,7 +16,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
#
include $(ERL_TOP)/make/target.mk
@@ -82,7 +82,7 @@ ifneq ($(V),0)
JARFLAGS=-cfv
endif
-JAVA_OPTIONS = -Xlint
+JAVA_OPTIONS = -Xlint -encoding UTF-8
ifeq ($(TESTROOT),)
RELEASE_PATH="$(ERL_TOP)/release/$(TARGET)"
@@ -100,7 +100,7 @@ $(APP_TARGET): $(APP_SRC) $(ERL_TOP)/lib/jinterface/vsn.mk
$(APPUP_TARGET): $(APPUP_SRC) $(ERL_TOP)/lib/jinterface/vsn.mk
$(vsn_verbose)sed -e 's;%VSN%;$(JINTERFACE_VSN);' $< > $@
-debug opt: make_dirs $(JAVA_DEST_ROOT)$(JARFILE)
+$(TYPES): make_dirs $(JAVA_DEST_ROOT)$(JARFILE)
make_dirs:
$(V_at)if [ ! -d "$(JAVA_DEST_ROOT)" ];then mkdir "$(JAVA_DEST_ROOT)"; fi
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java
index 125004c9f6..5ca80038cd 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpConnection.java
@@ -38,7 +38,7 @@ import java.io.IOException;
*
* <p>
* If an exception occurs in any of the methods in this class, the connection
- * will be closed and must be explicitely reopened in order to resume
+ * will be closed and must be explicitly reopened in order to resume
* communication with the peer.
*
* <p>
@@ -317,7 +317,7 @@ public class OtpConnection extends AbstractConnection {
}
/**
- * Receive a messge complete with sender and recipient information.
+ * Receive a message complete with sender and recipient information.
*
* @return an {@link OtpMsg OtpMsg} containing the header information about
* the sender and recipient, as well as the actual message contents.
@@ -352,7 +352,7 @@ public class OtpConnection extends AbstractConnection {
}
/**
- * Receive a messge complete with sender and recipient information. This
+ * Receive a message complete with sender and recipient information. This
* method blocks at most for the specified time.
*
* @param timeout
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java
index f70aa4e6e8..948c036e9f 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java
@@ -182,7 +182,7 @@ public class OtpCookedConnection extends AbstractConnection {
}
/*
- * this one called explicitely by user code => use exit2
+ * this one called explicitly by user code => use exit2
*/
void exit2(final OtpErlangPid from, final OtpErlangPid to,
final OtpErlangObject reason) {
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
index 6d6b64225b..dd9d741283 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpEpmd.java
@@ -326,7 +326,7 @@ public class OtpEpmd {
if (response == ALIVE2_RESP || response == ALIVE2_X_RESP) {
final int result = ibuf.read1();
if (result == 0) {
- node.creation = (response == ALIVE2_RESP
+ node.setCreation(response == ALIVE2_RESP
? ibuf.read2BE() : ibuf.read4BE());
if (traceLevel >= traceThreshold) {
System.out.println("<- OK");
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 d73bad5e4f..68351d1210 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-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ public class OtpErlangAtom extends OtpErlangObject {
// don't change this!
private static final long serialVersionUID = -3204386396807876641L;
- /** The maximun allowed length of an atom, in characters */
+ /** The maximum allowed length of an atom, in characters */
public static final int maxAtomLength = 0xff; // one byte length
private final String atom;
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangDouble.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangDouble.java
index 5084848562..8e50755f80 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangDouble.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangDouble.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ public class OtpErlangDouble extends OtpErlangObject {
@Override
protected int doHashCode() {
- final Double v = new Double(d);
+ final Double v = Double.valueOf(d);
return v.hashCode();
}
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
index a2b4e30e18..70d8c5d403 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangLong.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@ public class OtpErlangLong extends OtpErlangObject {
* @return true if this value fits in a long, false otherwise.
*/
public boolean isLong() {
- // To just chech this.bigVal is a wee bit to simple, since
+ // To just check this.bigVal is a wee bit to simple, since
// there just might have be a mean bignum that arrived on
// a stream, and was a long disguised as more than 8 byte integer.
if (bigVal != null) {
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java
index 9f68f6e695..e1ffa2ef43 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java
@@ -85,12 +85,11 @@ public class OtpErlangPid extends OtpErlangObject implements Comparable<Object>
* used.
*
* @param creation
- * yet another arbitrary number. Ony the low order 2 bits will
- * be used.
+ * node incarnation number. Avoid values 0 to 3.
*/
public OtpErlangPid(final String node, final int id, final int serial,
final int creation) {
- this(OtpExternal.pidTag, node, id, serial, creation);
+ this(OtpExternal.newPidTag, node, id, serial, creation);
}
/**
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java
index c5a18caa33..a58101a492 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java
@@ -32,7 +32,7 @@ public class OtpErlangPort extends OtpErlangObject {
/*
* Create a unique Erlang port belonging to the local node. Since it isn't
- * meaninful to do so, this constructor is private...
+ * meaningful to do so, this constructor is private...
*
* @param self the local node.
*
@@ -77,10 +77,10 @@ public class OtpErlangPort extends OtpErlangObject {
* an arbitrary number. Only the low order 28 bits will be used.
*
* @param creation
- * another arbitrary number. Only the low order 2 bits will be used.
+ * node incarnation number. Avoid values 0 to 3.
*/
public OtpErlangPort(final String node, final long id, final int creation) {
- this(OtpExternal.portTag, node, id, creation);
+ this(OtpExternal.newPortTag, node, id, creation);
}
/**
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java
index 5a99ae07c6..7ce539dd94 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java
@@ -106,12 +106,11 @@ public class OtpErlangRef extends OtpErlangObject {
* three numbers will be read from the array.
*
* @param creation
- * another arbitrary number. Only the low order 2 bits will be
- * used.
+ * node incarnation number. Avoid values 0 to 3.
*/
public OtpErlangRef(final String node, final int[] ids, final int creation) {
- this(OtpExternal.newRefTag, node, ids, creation);
- }
+ this(OtpExternal.newerRefTag, node, ids, creation);
+ }
/**
* Create a new(er) style Erlang ref from its components.
@@ -246,7 +245,7 @@ public class OtpErlangRef extends OtpErlangObject {
/**
* Determine if two refs are equal. Refs are equal if their components are
* equal. New refs and old refs are considered equal if the node, creation
- * and first id numnber are equal.
+ * and first id number are equal.
*
* @param o
* the other ref to compare to.
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpGenericTransportFactory.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpGenericTransportFactory.java
new file mode 100644
index 0000000000..c5858c8953
--- /dev/null
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpGenericTransportFactory.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2022 Jérôme de Bretagne
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %ExternalCopyright%
+ */
+
+package com.ericsson.otp.erlang;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * Transport factory abstract class used to create client-side and server-side
+ * transport instances defined using generic peers and local nodes (instead of
+ * a host + port combination as expected in the base OtpTransportFactory).
+ *
+ * It allows the creation of a transport using Unix Domain Sockets for example.
+ *
+ * OtpGenericTransportFactory is created as a subclass of OtpTransportFactory
+ * to keep backwards compatibility and ease the integration within existing
+ * Jinterface code, but in practice it doesn't support the 3 original methods.
+ */
+public abstract class OtpGenericTransportFactory implements OtpTransportFactory {
+
+ /**
+ * Create an instance of a client-side {@link OtpTransport}
+ *
+ * @param peer
+ * the peer identifying the server to connect to
+ *
+ * @return a new transport object
+ *
+ * @throws IOException
+ */
+ public abstract OtpTransport createTransport(final OtpPeer peer)
+ throws IOException;
+
+ /**
+ * Create an instance of a server-side {@link OtpServerTransport}
+ *
+ * @param node
+ * the local node identifying the transport to create server-side
+ *
+ * @return a new transport object
+ *
+ * @throws IOException
+ */
+ public abstract OtpServerTransport createServerTransport(final OtpLocalNode node)
+ throws IOException;
+
+
+ /**
+ * Implement the 3 original methods by throwing an exception as the usage
+ * of a port is not supported by this subclass of OtpTransportFactory.
+ */
+ @Override public OtpTransport createTransport(String addr, int port)
+ throws IOException {
+ throw new IOException("Method createTransport(String, int) " +
+ "not applicable for OtpGenericTransportFactory");
+ }
+
+ @Override public OtpTransport createTransport(final InetAddress addr, final int port)
+ throws IOException {
+ throw new IOException("Method createTransport(InetAddress, int) " +
+ "not applicable for OtpGenericTransportFactory");
+ }
+
+ @Override public OtpServerTransport createServerTransport(final int port)
+ throws IOException {
+ throw new IOException("Method createServerTransport(int) " +
+ "not applicable for OtpGenericTransportFactory");
+ }
+
+}
+
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
index 7578f06ee5..cf4c5be388 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java
@@ -750,7 +750,7 @@ public class OtpInputStream extends ByteArrayInputStream {
nb = new byte[4];
if (this.readN(nb) != 4) { // Big endian
throw new OtpErlangDecodeException(
- "Cannot read from intput stream");
+ "Cannot read from input stream");
}
break;
@@ -775,7 +775,7 @@ public class OtpInputStream extends ByteArrayInputStream {
// with one zero byte to make the value 2's complement positive.
if (this.readN(nb, 0, arity) != arity) {
throw new OtpErlangDecodeException(
- "Cannot read from intput stream");
+ "Cannot read from input stream");
}
// Reverse the array to make it big endian.
for (int i = 0, j = nb.length; i < j--; i++) {
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpLocalNode.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpLocalNode.java
index 6f896aab9f..a07897828f 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpLocalNode.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpLocalNode.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2021. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@ public class OtpLocalNode extends AbstractNode {
*/
public synchronized OtpErlangPid createPid() {
final OtpErlangPid p = new OtpErlangPid(node, pidCount, serial,
- creation);
+ creation());
pidCount++;
if (pidCount > 0x7fff) {
@@ -139,7 +139,7 @@ public class OtpLocalNode extends AbstractNode {
* @return an Erlang port.
*/
public synchronized OtpErlangPort createPort() {
- final OtpErlangPort p = new OtpErlangPort(node, portCount, creation);
+ final OtpErlangPort p = new OtpErlangPort(node, portCount, creation());
portCount++;
if (portCount > 0xfffffff) { /* 28 bits */
@@ -158,7 +158,7 @@ public class OtpLocalNode extends AbstractNode {
* @return an Erlang reference.
*/
public synchronized OtpErlangRef createRef() {
- final OtpErlangRef r = new OtpErlangRef(node, refId, creation);
+ final OtpErlangRef r = new OtpErlangRef(node, refId, creation());
// increment ref ids (3 ints: 18 + 32 + 32 bits)
refId[0]++;
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 18aad6a4a8..ff8b63e64a 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -128,7 +128,7 @@ public class OtpMbox {
* mailbox enables others to send messages without knowing the
* {@link OtpErlangPid pid} of the mailbox. A mailbox can have at most one
* name; if the mailbox already had a name, calling this method will
- * supercede that name.
+ * supersede that name.
* </p>
*
* @param aname
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java
index e14b99d274..c44c0c5bdb 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMsg.java
@@ -242,7 +242,7 @@ public class OtpMsg {
* <p>
* The first time this method is called the actual payload is deserialized
* and the Erlang term is created. Calling this method subsequent times will
- * not cuase the message to be deserialized additional times, instead the
+ * not cause the message to be deserialized additional times, instead the
* same Erlang term object will be returned.
* </p>
*
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 e48e6e8633..b0e43b9c11 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-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,9 +52,12 @@ import java.util.Iterator;
*
* <p>
* Note that the use of this class requires that Epmd (Erlang Port Mapper
- * Daemon) is running on each cooperating host. This class does not start Epmd
- * automatically as Erlang does, you must start it manually or through some
- * other means. See the Erlang documentation for more information about this.
+ * Daemon) is running on each cooperating host, except when using a transport
+ * factory extending the OtpGenericTransportFactory abstract class.
+ *
+ * This class does not start Epmd automatically as Erlang does, you must start
+ * it manually or through some other means. See the Erlang documentation for
+ * more information about this.
* </p>
*/
public class OtpNode extends OtpLocalNode {
@@ -128,7 +131,14 @@ public class OtpNode extends OtpLocalNode {
final OtpTransportFactory transportFactory) throws IOException {
super(node, transportFactory);
- init(0);
+ if (transportFactory instanceof OtpGenericTransportFactory) {
+ // For alternative distribution protocols using a transport factory
+ // extending the OtpGenericTransportFactory abstract class, the
+ // local node is used as the identifier for incoming connections.
+ init();
+ } else {
+ init(0);
+ }
}
/**
@@ -168,7 +178,16 @@ public class OtpNode extends OtpLocalNode {
*/
public OtpNode(final String node, final String cookie,
final OtpTransportFactory transportFactory) throws IOException {
- this(node, cookie, 0, transportFactory);
+ super(node, cookie, transportFactory);
+
+ if (transportFactory instanceof OtpGenericTransportFactory) {
+ // For alternative distribution protocols using a transport factory
+ // extending the OtpGenericTransportFactory abstract class, the
+ // local node is used as the identifier for incoming connections.
+ init();
+ } else {
+ init(0);
+ }
}
/**
@@ -224,6 +243,10 @@ public class OtpNode extends OtpLocalNode {
init(port);
}
+ /*
+ * Initialize a node instance with the port number to use for incoming
+ * connections. Specifying 0 lets the system choose an available port.
+ */
private synchronized void init(final int aport) throws IOException {
if (!initDone) {
connections = new Hashtable<String, OtpCookedConnection>(17,
@@ -234,6 +257,20 @@ public class OtpNode extends OtpLocalNode {
}
}
+ /*
+ * Initialize a node instance using an alternative distribution protocol
+ * with the local node used as the identifier for incoming connections.
+ */
+ private synchronized void init() throws IOException {
+ if (!initDone) {
+ connections = new Hashtable<String, OtpCookedConnection>(17,
+ (float) 0.95);
+ mboxes = new Mailboxes();
+ acceptor = new Acceptor(this);
+ initDone = true;
+ }
+ }
+
/**
* Close the node. Unpublish the node from Epmd (preventing new connections)
* and close all existing connections.
@@ -348,7 +385,7 @@ public class OtpNode extends OtpLocalNode {
* mailbox enables others to send messages without knowing the
* {@link OtpErlangPid pid} of the mailbox. A mailbox can have at most one
* name; if the mailbox already had a name, calling this method will
- * supercede that name.
+ * supersede that name.
* </p>
*
* @param name
@@ -446,8 +483,8 @@ public class OtpNode extends OtpLocalNode {
public boolean ping(final String anode, final long timeout) {
if (anode.equals(node)) {
return true;
- } else if (anode.indexOf('@', 0) < 0
- && anode.equals(node.substring(0, node.indexOf('@', 0)))) {
+ } else if (anode.indexOf('@') < 0
+ && anode.equals(node.substring(0, node.indexOf('@')))) {
return true;
}
@@ -527,7 +564,7 @@ public class OtpNode extends OtpLocalNode {
if (t == OtpMsg.regSendTag) {
final String name = m.getRecipientName();
- /* special case for netKernel requests */
+ // special case for netKernel requests
if (name.equals("net_kernel")) {
return netKernel(m);
}
@@ -569,7 +606,10 @@ public class OtpNode extends OtpLocalNode {
if (conn == null) {
// in case node had no '@' add localhost info and try again
- peer = new OtpPeer(anode);
+ peer = new OtpPeer(anode,
+ // Pass the transport factory to use
+ // when creating connections
+ transportFactory);
conn = connections.get(peer.node());
if (conn == null) {
@@ -578,7 +618,7 @@ public class OtpNode extends OtpLocalNode {
conn.setFlags(connFlags);
addConnection(conn);
} catch (final Exception e) {
- /* false = outgoing */
+ // false = outgoing
connAttempt(peer.node(), false, e);
}
}
@@ -773,10 +813,31 @@ public class OtpNode extends OtpLocalNode {
setDaemon(true);
setName("acceptor");
+ // Publish the node through Epmd
publishPort();
start();
}
+ /*
+ * Constructor for alternative distribution protocols using a transport
+ * factory extending the OtpGenericTransportFactory abstract class.
+ *
+ * The notion of socket port is not used with such protocols so the
+ * node is not published via Epmd.
+ */
+ Acceptor(final OtpLocalNode node) throws IOException {
+ // Set acceptorPort arbitrarily to 0, it won't be used later on.
+ acceptorPort = 0;
+
+ // The local node is passed as the identifier to use for incoming
+ // connections.
+ sock = createServerTransport(node);
+
+ setDaemon(true);
+ setName("acceptor");
+ start();
+ }
+
private boolean publishPort() throws IOException {
if (getEpmd() != null) {
return false; // already published
@@ -786,10 +847,16 @@ public class OtpNode extends OtpLocalNode {
}
private void unPublishPort() {
- // unregister with epmd
+ // The notion of socket port is not used with such an alternative
+ // distribution protocol so the node was not registered with Epmd.
+ if (transportFactory instanceof OtpGenericTransportFactory) {
+ return;
+ }
+
+ // Unregister the node from Epmd
OtpEpmd.unPublishPort(OtpNode.this);
- // close the local descriptor (if we have one)
+ // Close the local descriptor (if we have one)
closeSock(epmd);
epmd = null;
}
@@ -875,7 +942,7 @@ public class OtpNode extends OtpLocalNode {
}
} // while
- // if we have exited loop we must do this too
+ // If we have exited loop we must do this too
unPublishPort();
}
}
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpSelf.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpSelf.java
index 97f7f037e7..9410aba9a5 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpSelf.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpSelf.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ import java.net.UnknownHostException;
* <p>
* When you create an instance of this class, it will bind a socket to a port so
* that incoming connections can be accepted. However the port number will not
- * be made available to other nodes wishing to connect until you explicitely
+ * be made available to other nodes wishing to connect until you explicitly
* register with the port mapper daemon by calling {@link #publishPort()}.
* </p>
*
@@ -196,12 +196,20 @@ public class OtpSelf extends OtpLocalNode {
final OtpTransportFactory transportFactory) throws IOException {
super(node, cookie, transportFactory);
- sock = createServerTransport(port);
+ if (transportFactory instanceof OtpGenericTransportFactory) {
+ // For alternative distribution protocols using a transport factory
+ // extending the OtpGenericTransportFactory abstract class, pass the
+ // local node as the identifier to use for incoming connections.
+ sock = createServerTransport(this);
- if (port != 0) {
- this.port = port;
} else {
- this.port = sock.getLocalPort();
+ sock = createServerTransport(port);
+
+ if (port != 0) {
+ this.port = port;
+ } else {
+ this.port = sock.getLocalPort();
+ }
}
pid = createPid();
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpServer.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpServer.java
index d6a143ca6a..4cc6fd5047 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpServer.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpServer.java
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2000-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2000-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import java.io.IOException;
*
* When you create an instance of this class, it will bind a socket to a port so
* that incoming connections can be accepted. However the port number will not
- * be made available to other nodes wishing to connect until you explicitely
+ * be made available to other nodes wishing to connect until you explicitly
* register with the port mapper daemon by calling {@link #publishPort()}.
*
* <p>
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/java_files b/lib/jinterface/java_src/com/ericsson/otp/erlang/java_files
index cfabbe6271..10709e1059 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/java_files
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/java_files
@@ -2,9 +2,9 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -16,7 +16,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+#
# %CopyrightEnd%
#
@@ -44,6 +44,7 @@ COMM = \
OtpErlangFun \
OtpErlangExternalFun \
OtpExternal \
+ OtpGenericTransportFactory \
OtpInputStream \
OtpLocalNode \
OtpNodeStatus \
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/package.html b/lib/jinterface/java_src/com/ericsson/otp/erlang/package.html
index f7b4884851..eb62e69243 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/package.html
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/package.html
@@ -3,7 +3,7 @@
%CopyrightBegin%
- Copyright Ericsson AB 2000-2016. All Rights Reserved.
+ Copyright Ericsson AB 2000-2022. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -105,7 +105,7 @@ com.ericsson.otp.erlang.OtpConnection}. </p>
<p> The classes {@link com.ericsson.otp.erlang.OtpPeer}, {@link
com.ericsson.otp.erlang.OtpSelf} and {@link
com.ericsson.otp.erlang.OtpServer} are used to represent OTP nodes and
-are neccessary in order to set up communication between the Java
+are necessary in order to set up communication between the Java
thread and a remote node. Once a connection has been established, it
is represented by an {@link com.ericsson.otp.erlang.OtpConnection},
through which all communication goes.
diff --git a/lib/jinterface/test/Makefile b/lib/jinterface/test/Makefile
index 3eff11e4f7..abbd8c6535 100644
--- a/lib/jinterface/test/Makefile
+++ b/lib/jinterface/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ TARGET_FILES = \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-tests debug opt:
+tests $(TYPES):
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/jinterface/test/jinterface_SUITE.erl b/lib/jinterface/test/jinterface_SUITE.erl
index d7bb112bd9..8c771feeea 100644
--- a/lib/jinterface/test/jinterface_SUITE.erl
+++ b/lib/jinterface/test/jinterface_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
--export([transport_factory/1,
+-export([generic_transport_factory/1, transport_factory/1,
nodename/1, register_and_whereis/1, get_names/1, boolean_atom/1,
node_ping/1, mbox_ping/1,
java_erlang_send_receive/1,
@@ -114,14 +114,15 @@ end_per_group(_GroupName, Config) ->
fundamental() ->
[
- transport_factory, % TransportFactoryTest.java
- nodename, % Nodename.java
- register_and_whereis, % RegisterAndWhereis.java
- get_names, % GetNames.java
- boolean_atom, % BooleanAtom.java
- maps, % Maps.java
- fun_equals, % FunEquals.java
- core_match_bind % CoreMatchBind.java
+ generic_transport_factory, % GenericTransportFactoryTest.java
+ transport_factory, % TransportFactoryTest.java
+ nodename, % Nodename.java
+ register_and_whereis, % RegisterAndWhereis.java
+ get_names, % GetNames.java
+ boolean_atom, % BooleanAtom.java
+ maps, % Maps.java
+ fun_equals, % FunEquals.java
+ core_match_bind % CoreMatchBind.java
].
ping() ->
@@ -236,6 +237,17 @@ end_per_testcase(_Case,Config) ->
%%%-----------------------------------------------------------------
%%% TEST CASES
%%%-----------------------------------------------------------------
+generic_transport_factory(doc) ->
+ ["GenericTransportFactoryTest.java: "
+ "Test custom OTP Generic Transport Factory"];
+generic_transport_factory(suite) ->
+ [];
+generic_transport_factory(Config) when is_list(Config) ->
+ ok = jitu:java(?config(java, Config),
+ ?config(data_dir, Config),
+ "GenericTransportFactoryTest").
+
+%%%-----------------------------------------------------------------
transport_factory(doc) ->
["TransportFactoryTest.java: Test custom OTP Transport Factory"];
transport_factory(suite) ->
diff --git a/lib/jinterface/test/jinterface_SUITE_data/GenericTransportFactoryTest.java b/lib/jinterface/test/jinterface_SUITE_data/GenericTransportFactoryTest.java
new file mode 100644
index 0000000000..357462d69b
--- /dev/null
+++ b/lib/jinterface/test/jinterface_SUITE_data/GenericTransportFactoryTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2022 Jérôme de Bretagne
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %ExternalCopyright%
+ */
+
+import java.io.IOException;
+
+import com.ericsson.otp.erlang.OtpGenericTransportFactory;
+import com.ericsson.otp.erlang.OtpLocalNode;
+import com.ericsson.otp.erlang.OtpNode;
+import com.ericsson.otp.erlang.OtpPeer;
+import com.ericsson.otp.erlang.OtpServerTransport;
+import com.ericsson.otp.erlang.OtpSocketTransportFactory;
+import com.ericsson.otp.erlang.OtpTransport;
+import com.ericsson.otp.erlang.OtpTransportFactory;
+
+public class GenericTransportFactoryTest {
+
+ /**
+ * A minimalist custom generic transport factory working without epmd,
+ * using the node name as the identifier of the listening socket port.
+ */
+ public static class TestFactory extends OtpGenericTransportFactory {
+
+ OtpSocketTransportFactory tf = new OtpSocketTransportFactory();
+ String fake_epmd_name;
+ int fake_epmd_port;
+
+ public OtpTransport createTransport(final OtpPeer peer)
+ throws IOException {
+ String addr = "localhost";
+ String peerName = peer.alive();
+ int port = 0;
+ if (peerName == fake_epmd_name) {
+ port = fake_epmd_port;
+ }
+ else {
+ fail("Fake epmd don't know port nr of " + peerName);
+ }
+ System.out.println("Creating transport to " + addr + ", " + port);
+ return tf.createTransport(addr, port);
+ }
+
+ public OtpServerTransport createServerTransport(final OtpLocalNode node)
+ throws IOException {
+ String nodeName = node.alive();
+ OtpServerTransport transport = tf.createServerTransport(0);
+ System.out.println("Creating server transport for node "
+ + nodeName + " to port "
+ + transport.getLocalPort());
+
+ // Store last created server node in our fake "epmd database".
+ fake_epmd_name = nodeName;
+ fake_epmd_port = transport.getLocalPort();
+
+ return transport;
+ }
+
+ }
+
+ public static void main(final String[] args) throws IOException {
+
+ OtpTransportFactory customFactory = new TestFactory();
+
+ // The 2 test nodes with arbitrary socket port numbers
+ String nodeName1 = "Alice";
+ String nodeName2 = "Bob";
+
+ // Create the first node
+ final OtpNode node1 = new OtpNode(nodeName1, customFactory);
+
+ // Create the second node
+ final OtpNode node2 = new OtpNode(nodeName2, customFactory);
+
+ // Finally test the connection between the 2 nodes
+ if (!node1.ping(nodeName2, 2000)) {
+ fail("The 2 nodes couldn't connect");
+ }
+
+ }
+
+ private static void fail(final String string) {
+ System.err.println(string);
+ System.exit(1);
+ }
+}
diff --git a/lib/jinterface/test/jinterface_SUITE_data/Makefile.src b/lib/jinterface/test/jinterface_SUITE_data/Makefile.src
index 19c2157f7a..fe4051ea8f 100644
--- a/lib/jinterface/test/jinterface_SUITE_data/Makefile.src
+++ b/lib/jinterface/test/jinterface_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -23,9 +23,6 @@
# We use both `rm' (Unix) and `del' (Windows) for removing files, but
# with a `-' in front so that the error in not finding `rm' (`del') on
# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
.SUFFIXES:
.SUFFIXES: .java
@@ -39,6 +36,7 @@ JINTERFACE_CLASSPATH = @jinterface_classpath@
CLASSPATH = .@PS@$(JINTERFACE_CLASSPATH)@PS@
JAVA_FILES = \
+ GenericTransportFactoryTest.java \
TransportFactoryTest.java \
Nodename.java \
RegisterAndWhereis.java \
@@ -62,6 +60,6 @@ clean:
-del /F /Q $(CLASS_FILES)
$(CLASS_FILES) : $(JAVA_FILES)
- $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
+ $(JAVAC) -encoding UTF-8 -classpath $(CLASSPATH) $(JAVA_FILES)
#
diff --git a/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java b/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java
index 560786c304..4af73e8fb4 100644
--- a/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java
+++ b/lib/jinterface/test/jinterface_SUITE_data/MboxLinkUnlink.java
@@ -188,7 +188,7 @@ class MboxLinkUnlink {
waiting = true;
expected = tuple.elementAt(2);
mbox2.receive(1000); // hanging waiting for exit
- System.exit(4); // got someting other than exit
+ System.exit(4); // got something other than exit
break;
case internal_link_linked_exits:
dbg("Java got \"internal_link_linked_exits\"");
@@ -198,7 +198,7 @@ class MboxLinkUnlink {
waiting = true;
expected = tuple.elementAt(2);
mbox.receive(1000); // hanging waiting for exit
- System.exit(5); // got someting other than exit
+ System.exit(5); // got something other than exit
break;
case internal_unlink_linking_exits:
dbg("Java got \"internal_unlink_linking_exits\"");
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index 66806a94ab..115571e21e 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -125,8 +125,6 @@ end_per_testcase(_Case, Config) ->
%% Test cases
%%
-pid_roundtrip(doc) -> [];
-pid_roundtrip(suite) -> [];
pid_roundtrip(Config) when is_list(Config)->
ThisNode = {node(), erlang:system_info(creation)},
RemPids = [mk_pid({gurka@sallad, Cr}, Num, Ser)
@@ -138,8 +136,6 @@ pid_roundtrip(Config) when is_list(Config)->
| RemPids],
Config).
-fun_roundtrip(doc) -> [];
-fun_roundtrip(suite) -> [];
fun_roundtrip(Config) when is_list(Config)->
do_echo([fun(A, B) -> A + B end,
fun(A) -> lists:reverse(A) end,
@@ -148,8 +144,6 @@ fun_roundtrip(Config) when is_list(Config)->
fun ?MODULE:fun_roundtrip/1],
Config).
-port_roundtrip(doc) -> [];
-port_roundtrip(suite) -> [];
port_roundtrip(Config) when is_list(Config)->
ThisNode = {node(), erlang:system_info(creation)},
RemPorts = [mk_port({gurka@sallad, Cr}, Num)
@@ -166,8 +160,6 @@ port_roundtrip(Config) when is_list(Config)->
| RemPorts],
Config).
-ref_roundtrip(doc) -> [];
-ref_roundtrip(suite) -> [];
ref_roundtrip(Config) when is_list(Config)->
ThisNode = {node(), erlang:system_info(creation)},
RemRefs = [mk_ref({gurka@sallad, Cr}, Words)
@@ -183,8 +175,6 @@ ref_roundtrip(Config) when is_list(Config)->
| RemRefs],
Config).
-new_float(doc) -> [];
-new_float(suite) -> [];
new_float(Config) when is_list(Config)->
Two16 = float(1 bsl 16),
X = math:sqrt(2),
@@ -193,8 +183,6 @@ new_float(Config) when is_list(Config)->
io:format("~w", [Floats]),
do_echo(Floats, Config).
-old_stuff(doc) -> [];
-old_stuff(suite) -> [];
old_stuff(Config) when is_list(Config)->
Terms = [0.0,math:sqrt(2)],
OutTrans =
@@ -207,8 +195,6 @@ old_stuff(Config) when is_list(Config)->
end,
do_echo(Terms, Config, OutTrans, InTrans).
-binary_roundtrip(doc) -> [];
-binary_roundtrip(suite) -> [];
binary_roundtrip(Config) when is_list(Config) ->
do_echo([<<17>>,
<<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17>>,
@@ -217,8 +203,6 @@ binary_roundtrip(Config) when is_list(Config) ->
<<>>],
Config).
-decompress_roundtrip(doc) -> [];
-decompress_roundtrip(suite) -> [];
decompress_roundtrip(Config) when is_list(Config) ->
RandomBin = erlang:term_to_binary(lists:seq(1, 5 * 1024 * 1024)), % roughly 26MB
<<RandomBin1k:1024/binary,_/binary>> = RandomBin,
@@ -247,8 +231,6 @@ decompress_roundtrip(Config) when is_list(Config) ->
end,
do_echo(Terms, Config, OutTrans, InTrans).
-compress_roundtrip(doc) -> [];
-compress_roundtrip(suite) -> [];
compress_roundtrip(Config) when is_list(Config) ->
RandomBin = erlang:term_to_binary(lists:seq(1, 5 * 1024 * 1024)), % roughly 26MB
<<RandomBin1k:1024/binary,_/binary>> = RandomBin,
@@ -279,8 +261,6 @@ compress_roundtrip(Config) when is_list(Config) ->
-integer_roundtrip(doc) -> [];
-integer_roundtrip(suite) -> [];
integer_roundtrip(Config) when is_list(Config) ->
Xs = [1 bsl X || X <- [26,27,28,29,30,31,32,33,
62,63,64,65,
@@ -319,8 +299,6 @@ bitlength(V) when is_integer(V) ->
-lists_roundtrip(doc) -> [];
-lists_roundtrip(suite) -> [];
lists_roundtrip(Config) when is_list(Config) ->
Ls = [lists:seq(1,10),
lists:seq(11,17)++last_tail,
@@ -332,8 +310,6 @@ lists_roundtrip(Config) when is_list(Config) ->
-lists_roundtrip_2(doc) -> [];
-lists_roundtrip_2(suite) -> [];
lists_roundtrip_2(Config) when is_list(Config) ->
Ls = [{[a,b],tail},
{[c,d,e],tail},
@@ -385,8 +361,6 @@ lists_roundtrip_2(Config) when is_list(Config) ->
-lists_iterator(doc) -> [];
-lists_iterator(suite) -> [];
lists_iterator(Config) when is_list(Config) ->
Ls = [["able ","was ","I ","ere ","I ","saw ","elba"]],
do_echo(Ls, Config,
@@ -398,8 +372,6 @@ lists_iterator(Config) when is_list(Config) ->
-unicode(doc) -> [];
-unicode(suite) -> [];
unicode(Config) when is_list(Config) ->
S1 = "plain ascii",
S2 = "iso-latin åäö ñ",
@@ -447,8 +419,6 @@ unicode_cp_gen(Cont) when is_function(Cont, 0) ->
-unicode_list_to_string(doc) -> [];
-unicode_list_to_string(suite) -> [];
unicode_list_to_string(Config) when is_list(Config) ->
do_echo(cp_gen(73), Config,
fun ({L,_}) -> {self(),L,to_string_neg_int_list} end,
@@ -469,8 +439,6 @@ unicode_list_to_string(Config) when is_list(Config) ->
-unicode_string_to_list(doc) -> [];
-unicode_string_to_list(suite) -> [];
unicode_string_to_list(Config) when is_list(Config) ->
do_echo(cp_gen(79), Config,
fun ({L,_}) -> {self(),L,to_neg_int_list} end,
@@ -592,11 +560,8 @@ cp_validity(UnicodeCP) ->
-connect(doc) -> [];
-connect(suite) -> [];
connect(Config) when is_list(Config) ->
- WD = filename:dirname(code:which(?MODULE)),
- {ok,Other} = test_server:start_node(make_name(), slave, [{args,"-pa "++WD}]),
+ {ok,Peer,Other} = ?CT_PEER(),
Action =
fun (Pid) ->
JName = node(Pid),
@@ -628,7 +593,8 @@ connect(Config) when is_list(Config) ->
end,
Hidden = rpc:call(Other, erlang, nodes, [hidden])
end,
- run_server(connection_server, Config, Action, []).
+ run_server(connection_server, Config, Action, []),
+ peer:stop(Peer).
diff --git a/lib/jinterface/test/nc_SUITE_data/Makefile.src b/lib/jinterface/test/nc_SUITE_data/Makefile.src
index 94e2c1fa47..a278683477 100644
--- a/lib/jinterface/test/nc_SUITE_data/Makefile.src
+++ b/lib/jinterface/test/nc_SUITE_data/Makefile.src
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,9 +24,6 @@
# We use both `rm' (Unix) and `del' (Windows) for removing files, but
# with a `-' in front so that the error in not finding `rm' (`del') on
# Windows (Unix) is ignored.
-#
-# VxWorks? XXX
-#
.SUFFIXES:
.SUFFIXES: .java
@@ -49,6 +46,6 @@ clean:
-del /F /Q $(CLASS_FILES)
$(CLASS_FILES) : $(JAVA_FILES)
- $(JAVAC) -classpath $(CLASSPATH) $(JAVA_FILES)
+ $(JAVAC) -encoding UTF-8 -classpath $(CLASSPATH) $(JAVA_FILES)
#
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index 04de6b642b..909370599e 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1 +1 @@
-JINTERFACE_VSN = 1.12.2
+JINTERFACE_VSN = 1.13.2
diff --git a/lib/kernel/Makefile b/lib/kernel/Makefile
index a6c0253397..534b564c2c 100644
--- a/lib/kernel/Makefile
+++ b/lib/kernel/Makefile
@@ -36,5 +36,6 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=crypto
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index 643324132e..f551fd1ebe 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -847,9 +847,9 @@ rpc:call(Node, code, load_binary, [Module, Filename, Binary]),
<p>Returns the path to a subdirectory directly under the top
directory of an application. Normally the subdirectories
reside under the top directory for the application, but when
- applications at least partly resides in an archive, the
+ applications at least partly reside in an archive, the
situation is different. Some of the subdirectories can reside
- as regular directories while other reside in an archive
+ as regular directories while others reside in an archive
file. It is not checked whether this directory exists.</p>
<p><em>Example:</em></p>
<pre>
diff --git a/lib/kernel/doc/src/config.xml b/lib/kernel/doc/src/config.xml
index cf47c2c231..fe271a1a6f 100644
--- a/lib/kernel/doc/src/config.xml
+++ b/lib/kernel/doc/src/config.xml
@@ -101,7 +101,7 @@
<c>sys.config</c> file and from a configuration that comes
from a file descriptor that has been pointed out with the <seecom
marker="erts:erl#configfd"><c>-configfd</c></seecom> command-line
- arguemnt.</p>
+ argument.</p>
<p>The syntax for including files can be described by the
<seeguide marker="system/reference_manual:typespec">Erlang type
diff --git a/lib/kernel/doc/src/erl_ddll.xml b/lib/kernel/doc/src/erl_ddll.xml
index 798789c2af..a04e36a37d 100644
--- a/lib/kernel/doc/src/erl_ddll.xml
+++ b/lib/kernel/doc/src/erl_ddll.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2020</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -95,7 +95,7 @@
<em>last port</em> using the driver is closed. Function
<c>unload/1</c> can return immediately, as the
<seeerl marker="#users">users</seeerl>
- have no interrest in when the unloading occurs. The
+ have no interest in when the unloading occurs. The
driver is unloaded when no one needs it any longer.</p>
<p>If a process having the driver loaded dies, it has
the same effect as if unloading is done.</p>
@@ -334,7 +334,7 @@
<p>Loads and links the dynamic driver <c><anno>Name</anno></c>.
<c><anno>Path</anno></c>
is a file path to the directory containing the driver.
- <c><anno>Name</anno></c> must be a sharable object/dynamic library. Two
+ <c><anno>Name</anno></c> must be a shareable object/dynamic library. Two
drivers with different <c><anno>Path</anno></c> parameters cannot be
loaded under the same name. <c><anno>Name</anno></c> is a string or
atom containing at least one character.</p>
diff --git a/lib/kernel/doc/src/erpc.xml b/lib/kernel/doc/src/erpc.xml
index 26d1ec4aad..876a8a66b6 100644
--- a/lib/kernel/doc/src/erpc.xml
+++ b/lib/kernel/doc/src/erpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -64,12 +64,55 @@
<name name="request_id"/>
<desc>
<p>
- An opaque type of call request identifiers. For more
- information see
+ An opaque request identifier. For more information see
<seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
</p>
</desc>
</datatype>
+ <datatype>
+ <name name="request_id_collection"/>
+ <desc>
+ <p>
+ An opaque collection of request identifiers
+ (<seetype marker="#request_id"><c>request_id()</c></seetype>)
+ where each request identifier can be associated with a label
+ chosen by the user. For more information see
+ <seemfa marker="#reqids_new/0"><c>reqids_new/0</c></seemfa>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="timeout_time"/>
+ <desc>
+ <taglist>
+ <tag><c>0..4294967295</c></tag>
+ <item><p>
+ Timeout relative to current time in milliseconds.
+ </p></item>
+ <tag><c>infinity</c></tag>
+ <item><p>
+ Infinite timeout. That is, the operation will never time out.
+ </p></item>
+ <tag><c>{abs, Timeout}</c></tag>
+ <item><p>
+ An absolute
+ <seemfa marker="erts:erlang#monotonic_time/1">Erlang monotonic time</seemfa>
+ timeout in milliseconds. That is, the operation will time out when
+ <seemfa marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time(millisecond)</c></seemfa>
+ returns a value larger than or equal to <c>Timeout</c>. <c>Timeout</c>
+ is not allowed to identify a time further into the future than <c>4294967295</c>
+ milliseconds. Identifying the timeout using an absolute timeout value
+ is especially handy when you have a deadline for responses corresponding
+ to a complete collection of requests
+ (<seetype marker="#request_id_collection"><c>request_id_collection()</c></seetype>)
+,
+ since you do not have to recalculate the relative time until the deadline
+ over and over again.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
</datatypes>
<funcs>
@@ -81,8 +124,9 @@
<desc>
<p>
The same as calling
- <seemfa marker="#call/5"><c>erpc:call(<anno>Node</anno>,erlang,apply,[<anno>Fun</anno>,[]],<anno>Timeout</anno>)</c></seemfa>.
- May raise all the same exceptions as <c>erpc:call/5</c>
+ <seemfa marker="#call/5"><c>erpc:call(<anno>Node</anno>,
+ erlang, apply, [<anno>Fun</anno>,[]], <anno>Timeout</anno>)</c></seemfa>.
+ May raise all the same exceptions as <c>call/5</c>
plus an <c>{erpc, badarg}</c> <c>error</c>
exception if <c><anno>Fun</anno></c> is not a fun of
zero arity.
@@ -104,9 +148,8 @@
Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
<anno>Args</anno>)</c> on node <c><anno>Node</anno></c> and returns
the corresponding value <c><anno>Result</anno></c>.
- <c><anno>Timeout</anno></c> is an integer representing
- the timeout in milliseconds or the atom <c>infinity</c>
- which prevents the operation from ever timing out.
+ <c><anno>Timeout</anno></c> sets an upper time limit
+ for the <c>call</c> operation to complete.
</p>
<p>The call <c>erpc:call(<anno>Node</anno>, <anno>Module</anno>,
<anno>Function</anno>, <anno>Args</anno>)</c> is equivalent
@@ -118,7 +161,7 @@
exceptions, the operation did not time out, and no failures
occurred. In all other cases an exception is raised. The
following exceptions, listed by exception class, can
- currently be raised by <c>erpc:call()</c>:
+ currently be raised by <c>call()</c>:
</p>
<taglist>
<tag><c>throw</c></tag>
@@ -158,7 +201,7 @@
<tag><c>{exception, ErrorReason, StackTrace}</c></tag>
<item><p>
- A runtime error occurred which raised and error
+ A runtime error occurred which raised an error
exception while applying the function,
and the applied function did not catch the
exception. The error reason <c>ErrorReason</c>
@@ -186,9 +229,8 @@
<item><p><c><anno>Args</anno></c> is not a list.
Note that the list is not verified to be
a proper list at the client side.</p></item>
- <item><p><c><anno>Timeout</anno></c> is not the
- atom <c>infinity</c> or an integer in valid
- range.</p></item>
+ <item><p><c><anno>Timeout</anno></c> is
+ invalid.</p></item>
</list>
</item>
@@ -256,7 +298,7 @@
The same as calling
<seemfa marker="#cast/4"><c>erpc:cast(<anno>Node</anno>,erlang,apply,[<anno>Fun</anno>,[]])</c></seemfa>.
</p>
- <p><c>erpc:cast/2</c> fails with an <c>{erpc, badarg}</c>
+ <p><c>cast/2</c> fails with an <c>{erpc, badarg}</c>
<c>error</c> exception if:</p>
<list>
<item><p><c><anno>Node</anno></c> is not an atom.</p></item>
@@ -273,11 +315,11 @@
Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
<anno>Args</anno>)</c> on node
<c><anno>Node</anno></c>. No response is delivered to the
- calling process. <c>erpc:cast()</c> returns immediately
+ calling process. <c>cast()</c> returns immediately
after the cast request has been sent. Any failures beside
bad arguments are silently ignored.
</p>
- <p><c>erpc:cast/4</c> fails with an <c>{erpc, badarg}</c>
+ <p><c>cast/4</c> fails with an <c>{erpc, badarg}</c>
<c>error</c> exception if:</p>
<list>
<item><p><c><anno>Node</anno></c> is not an atom.</p></item>
@@ -305,13 +347,13 @@
<p>
Check if a message is a response to a <c>call</c> request
previously made by the calling process using
- <seemfa marker="#send_request/4"><c>erpc:send_request/4</c></seemfa>.
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
<c><anno>RequestId</anno></c> should be the value returned
- from the previously made <c>erpc:send_request()</c> call,
+ from the previously made <c>send_request/4</c> call,
and the corresponding response should not already have been
- received and handled to completion by <c>erpc:check_response()</c>,
- <seemfa marker="#receive_response/2"><c>erpc:receive_response()</c></seemfa>, or
- <seemfa marker="#wait_response/2"><c>erpc:wait_response()</c></seemfa>.
+ received and handled to completion by <c>check_response/2</c>,
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>, or
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>.
<c><anno>Message</anno></c> is the message to check.
</p>
<p>
@@ -323,9 +365,9 @@
corresponds to the value returned from the applied function
or an exception is raised. The exceptions that can be raised
corresponds to the same exceptions as can be raised by
- <seemfa marker="#call/4"><c>erpc:call/4</c></seemfa>.
+ <seemfa marker="#call/4"><c>call/4</c></seemfa>.
That is, no <c>{erpc, timeout}</c> <c>error</c> exception
- can be raised. <c>erpc:check_response()</c> will fail with
+ can be raised. <c>check_response()</c> will fail with
an <c>{erpc, badarg}</c> exception if/when an invalid
<c><anno>RequestId</anno></c> is detected.
</p>
@@ -341,14 +383,89 @@
</func>
<func>
+ <name name="check_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Check if a message is a response corresponding to a
+ previously sent call request.</fsummary>
+ <desc>
+ <p>
+ Check if a message is a response to a <c>call</c> request corresponding
+ to a request identifier saved in <c><anno>RequestIdCollection</anno></c>.
+ All request identifiers of <c><anno>RequestIdCollection</anno></c> must
+ correspond to requests that have been made using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa> or
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>,
+ and all requests must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ <c><anno>Label</anno></c> is the label associated with the request
+ identifier of the request that the response corresponds to.
+ A request identifier is associated with a label when
+ <seemfa marker="#reqids_add/3">adding a request identifier</seemfa>
+ in a <seetype marker="#request_id_collection">request identifier
+ collection</seetype>, or when sending the request using
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>check_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewRequestIdCollection</anno></c> is a possibly modified
+ request identifier collection. The <c>error</c> exception <c>{erpc,
+ badarg}</c> is not associated with any specific request identifier,
+ and will hence not be wrapped.
+ </p>
+ <p>
+ If <c><anno>RequestIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned. If <c><anno>Message</anno></c>
+ does not correspond to any of the request identifiers in
+ <c><anno>RequestIdCollection</anno></c>, the atom
+ <c>no_response</c> is returned.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>RequestIdCollection</anno></c> in the resulting
+ <c><anno>NewRequestIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewRequestIdCollection</anno></c> will equal
+ <c><anno>RequestIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>check_response/3</c>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>check_response/3</c>, it will always
+ return <c>no_response</c>.
+ </p>
+ <p>
+ Note that a response might have been consumed uppon an <c>{erpc,
+ badarg}</c> exception and if so, will be lost for ever.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="multicall" arity="2" since="OTP 23.0"/>
<name name="multicall" arity="3" since="OTP 23.0"/>
<fsummary>Evaluate a function call on a node.</fsummary>
<desc>
<p>
The same as calling
- <seemfa marker="#multicall/5"><c>erpc:multicall(<anno>Nodes</anno>,erlang,apply,[<anno>Fun</anno>,[]],<anno>Timeout</anno>)</c></seemfa>.
- May raise all the same exceptions as <c>erpc:multicall/5</c>
+ <seemfa marker="#multicall/5"><c>erpc:multicall(<anno>Nodes</anno>,
+ erlang, apply, [<anno>Fun</anno>,[]], <anno>Timeout</anno>)</c></seemfa>.
+ May raise all the same exceptions as <c>multicall/5</c>
plus an <c>{erpc, badarg}</c> <c>error</c>
exception if <c><anno>Fun</anno></c> is not a fun of
zero arity.
@@ -372,15 +489,13 @@
Performs multiple <c>call</c> operations in parallel
on multiple nodes. That is, evaluates
<c>apply(<anno>Module</anno>, <anno>Function</anno>,
- <anno>Args</anno>)</c> on the nodes
- <c><anno>Nodes</anno></c> in parallel.
- <c><anno>Timeout</anno></c> is an integer representing
- the timeout in milliseconds or the atom <c>infinity</c>
- which prevents the operation from ever timing out.
- The result is returned as a list where
- the result from each node is placed at the same position
- as the node name is placed in <c><anno>Nodes</anno></c>.
- Each item in the resulting list is formatted as either:
+ <anno>Args</anno>)</c> on the nodes <c><anno>Nodes</anno></c>
+ in parallel. <c><anno>Timeout</anno></c> sets an upper time
+ limit for all <c>call</c> operations to complete. The result
+ is returned as a list where the result from each node is placed
+ at the same position as the node name is placed in
+ <c><anno>Nodes</anno></c>. Each item in the resulting list is
+ formatted as either:
</p>
<taglist>
<tag><c>{ok, Result}</c></tag>
@@ -393,12 +508,12 @@
The <c>call</c> operation for this specific node
raised an exception of class <c>Class</c> with
exception reason <c>ExceptionReason</c>. These
- corresponds the the exceptions that
- <seemfa marker="#call/5"><c>erpc:call/5</c></seemfa>
+ correspond to the exceptions that
+ <seemfa marker="#call/5"><c>call/5</c></seemfa>
can raise.
</p></item>
</taglist>
- <p><c>erpc:multicall/5</c> fails with an <c>{erpc, badarg}</c>
+ <p><c>multicall/5</c> fails with an <c>{erpc, badarg}</c>
<c>error</c> exception if:</p>
<list>
<item><p><c><anno>Nodes</anno></c> is not a proper list of
@@ -416,8 +531,12 @@
to the call <c>erpc:multicall(<anno>Nodes</anno>, <anno>Module</anno>,
<anno>Function</anno>, <anno>Args</anno>, infinity)</c>. These
calls are also equivalent to calling <c>my_multicall(Nodes, Module,
- Function, Args)</c> if one disregard performance and failure
- behavior:
+ Function, Args)</c> below if one disregard performance and failure
+ behavior. <c>multicall()</c> can utilize a selective receive
+ optimization which removes the need to scan the message queue from
+ the beginning in order to find a matching message. The
+ <c>send_request()/receive_response()</c> combination can,
+ however, not utilize this optimization.
</p>
<pre>
my_multicall(Nodes, Module, Function, Args) ->
@@ -436,12 +555,6 @@ my_multicall(Nodes, Module, Function, Args) ->
ReqIds).
</pre>
- <p>
- The <c><anno>Timeout</anno></c> value in milliseconds
- sets an upper time limit for all <c>call</c> operations
- to complete.
- </p>
-
<p>
If an <c>erpc</c> operation fails, but it is unknown if
the function is/will be applied (that is, a timeout,
@@ -473,7 +586,7 @@ my_multicall(Nodes, Module, Function, Args) ->
The same as calling
<seemfa marker="#multicast/4"><c>erpc:multicast(<anno>Nodes</anno>,erlang,apply,[<anno>Fun</anno>,[]])</c></seemfa>.
</p>
- <p><c>erpc:multicast/2</c> fails with an <c>{erpc, badarg}</c>
+ <p><c>multicast/2</c> fails with an <c>{erpc, badarg}</c>
<c>error</c> exception if:</p>
<list>
<item><p><c><anno>Nodes</anno></c> is not a proper list of atoms.</p></item>
@@ -490,11 +603,11 @@ my_multicall(Nodes, Module, Function, Args) ->
Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
<anno>Args</anno>)</c> on the nodes
<c><anno>Nodes</anno></c>. No response is delivered to the
- calling process. <c>erpc:multicast()</c> returns immediately
+ calling process. <c>multicast()</c> returns immediately
after the cast requests have been sent. Any failures beside
bad arguments are silently ignored.
</p>
- <p><c>erpc:multicast/4</c> fails with an <c>{erpc, badarg}</c>
+ <p><c>multicast/4</c> fails with an <c>{erpc, badarg}</c>
<c>error</c> exception if:</p>
<list>
<item><p><c><anno>Nodes</anno></c> is not a proper list of
@@ -515,9 +628,21 @@ my_multicall(Nodes, Module, Function, Args) ->
</note>
</desc>
</func>
-
+
<func>
<name name="receive_response" arity="1" since="OTP 23.0"/>
+ <fsummary>Receive a call response corresponding to a
+ previously sent call request.</fsummary>
+ <desc>
+ <p>
+ The same as calling
+ <seemfa marker="#receive_response/2"><c>erpc:receive_response(<anno>RequestId</anno>,
+ infinity)</c></seemfa>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="receive_response" arity="2" since="OTP 23.0"/>
<fsummary>Receive a call response corresponding to a
previously sent call request.</fsummary>
@@ -525,34 +650,41 @@ my_multicall(Nodes, Module, Function, Args) ->
<p>
Receive a response to a <c>call</c> request previously
made by the calling process using
- <seemfa marker="#send_request/4"><c>erpc:send_request/4</c></seemfa>.
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
<c><anno>RequestId</anno></c> should be the value returned from
- the previously made <c>erpc:send_request()</c> call, and
+ the previously made <c>send_request/4</c> call, and
the corresponding response should not already have been received
- and handled to completion by
- <seemfa marker="#check_response/2"><c>erpc:check_response()</c></seemfa>,
- <c>erpc:receive_response()</c>, or
- <seemfa marker="#wait_response/2"><c>erpc:wait_response()</c></seemfa>.
- <c><anno>Timeout</anno></c> is an integer representing
- the timeout in milliseconds or the atom <c>infinity</c>
- which prevents the operation from ever timing out. The <c>call</c>
- operation is completed once the <c>erpc:receive_response()</c> call
- returns or raise an exception.
- </p>
- <p>
- The call <c>erpc:receive_response(<anno>RequestId</anno>)</c> is
- equivalent to the call
- <c>erpc:receive_response(<anno>RequestId</anno>, infinity)</c>.
+ and handled to completion by <c>receive_response()</c>,
+ <seemfa marker="#check_response/2"><c>check_response/4</c></seemfa>,
+ or
+ <seemfa marker="#wait_response/2"><c>wait_response/4</c></seemfa>.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> sets an upper time limit on how
+ long to wait for a response. If the operation times out, the request
+ identified by <c><anno>RequestId</anno></c> will be abandoned, then an
+ <c>{erpc, timeout}</c> <c>error</c> exception will be raised. That is,
+ no response corresponding to the request will ever be received after a
+ timeout. If a response is received, the <c>call</c> operation is
+ completed and either the result is returned or an exception is raised. The
+ exceptions that can be raised corresponds to the same exceptions as can
+ be raised by <seemfa marker="#call/5"><c>call/5</c></seemfa>.
+ <c>receive_response/2</c> will fail with an <c>{erpc, badarg}</c>
+ exception if/when an invalid <c><anno>RequestId</anno></c> is detected
+ or if an invalid <c><anno>Timeout</anno></c> is passed.
</p>
+
<p>
A call to the function
<c>my_call(Node, Module, Function, Args, Timeout)</c>
below is equivalent to the call
<seemfa marker="#call/5"><c>erpc:call(Node, Module, Function, Args,
- Timeout)</c></seemfa> if one disregards performance. <c>erpc:call()</c>
- can utilize a message queue optimization which removes the need to scan
- the whole message queue which the combination
- <c>erpc:send_request()/erpc:receive_response()</c> cannot.
+ Timeout)</c></seemfa> if one disregards performance. <c>call()</c>
+ can utilize a selective receive optimization which removes
+ the need to scan the message queue from the beginning in
+ order to find a matching message. The
+ <c>send_request()/receive_response()</c> combination can,
+ however, not utilize this optimization.
</p>
<pre>
my_call(Node, Module, Function, Args, Timeout) ->
@@ -568,15 +700,157 @@ my_call(Node, Module, Function, Args, Timeout) ->
communicates with the calling process, such communication
may, of course, reach the calling process.
</p>
-
- <p>
- <c>erpc:receive_response()</c> will return or raise exceptions the
- same way as <seemfa marker="#call/5"><c>erpc:call/5</c></seemfa>
- does with the exception of <c>{erpc, badarg}</c>. An
- <c>{erpc, badarg}</c> exception will be raised if/when an invalid
- <c><anno>RequestId</anno></c> is detected or if an invalid
- <c><anno>Timeout</anno></c> is passed.
+ </desc>
+ </func>
+
+ <func>
+ <name name="receive_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Receive a call response corresponding to a
+ previously sent call request.</fsummary>
+ <desc>
+ <p>
+ Receive a response to a <c>call</c> request corresponding to a request
+ identifier saved in <c><anno>RequestIdCollection</anno></c>. All
+ request identifiers of <c><anno>RequestIdCollection</anno></c> must
+ correspond to requests that have been made using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa> or
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>,
+ and all requests must have been made by the process calling this
+ function.
</p>
+ <p>
+ <c><anno>Label</anno></c> is the label associated with the request
+ identifier of the request that the response corresponds to.
+ A request identifier is associated with a label when
+ <seemfa marker="#reqids_add/3">adding a request identifier</seemfa>
+ in a <seetype marker="#request_id_collection">request identifier
+ collection</seetype>, or when sending the request using
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>receive_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewRequestIdCollection</anno></c> is a possibly modified
+ request identifier collection. The <c>error</c> exceptions <c>{erpc,
+ badarg}</c> and <c>{erpc, timeout}</c> are not associated with any
+ specific request identifiers, and will hence not be wrapped.
+ </p>
+ <p>
+ If <c><anno>RequestIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned.
+ </p>
+ <p>
+ If the operation times out, all requests identified by
+ <c><anno>RequestIdCollection</anno></c> will be abandoned, then an
+ <c>{erpc, timeout}</c> <c>error</c> exception will be raised. That is,
+ no responses corresponding to any of the request identifiers in
+ <c><anno>RequestIdCollection</anno></c> will ever be received after a
+ timeout. The difference between <c>receive_response/3</c> and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>
+ is that <c>receive_response/3</c> abandons the requests at timeout
+ so that any potential future responses are ignored, while
+ <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>RequestIdCollection</anno></c> in the resulting
+ <c><anno>NewRequestIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewRequestIdCollection</anno></c> will equal
+ <c><anno>RequestIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>receive_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>receive_response/3</c>, it will always block
+ until a timeout determined by <c><anno>Timeout</anno></c> is
+ triggered.
+ </p>
+ <p>
+ Note that a response might have been consumed uppon an <c>{erpc,
+ badarg}</c> exception and if so, will be lost for ever.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_add" arity="3" since="OTP 25.0"/>
+ <fsummary>Save a request identifier.</fsummary>
+ <desc>
+ <p>
+ Saves <c><anno>RequestId</anno></c> and associates a
+ <c><anno>Label</anno></c> with the request identifier by adding this
+ information to <c><anno>RequestIdCollection</anno></c> and returning
+ the resulting request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_new" arity="0" since="OTP 25.0"/>
+ <fsummary>Create a new empty request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns a new empty request identifier collection. A
+ request identifier collection can be utilized in order
+ the handle multiple outstanding requests.
+ </p>
+ <p>
+ Request identifiers of requests made by
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>
+ can be saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ </p>
+ <p>
+ <seemfa marker="#reqids_size/1"><c>reqids_size/1</c></seemfa>
+ can be used to determine the amount of request identifiers in a
+ request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_size" arity="1" since="OTP 25.0"/>
+ <fsummary>Get size of a request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns the amount of request identifiers saved in
+ <c><anno>RequestIdCollection</anno></c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_to_list" arity="1" since="OTP 25.0"/>
+ <fsummary>Get a list a request identifier/label associations in a collection.</fsummary>
+ <desc>
+ <p>
+ Returns a list of <c>{<anno>RequestId</anno>, <anno>Label</anno>}</c>
+ tuples which corresponds to all request identifiers with their
+ associated labels present in the <c><anno>RequestIdCollection</anno></c>
+ collection.
+ </p>
</desc>
</func>
@@ -586,10 +860,10 @@ my_call(Node, Module, Function, Args, Timeout) ->
<desc>
<p>
The same as calling
- <seemfa marker="#send_request/4"><c>erpc:send_request(<anno>Node</anno>,erlang,apply,[<anno>Fun</anno>,[]])</c></seemfa>.
+ <seemfa marker="#send_request/4"><c>erpc:send_request(<anno>Node</anno>,
+ erlang, apply, [<anno>Fun</anno>, []])</c></seemfa>.
</p>
- <p><c>erpc:send_request/2</c> fails with an <c>{erpc, badarg}</c>
- <c>error</c> exception if:</p>
+ <p>Fails with an <c>{erpc, badarg}</c> <c>error</c> exception if:</p>
<list>
<item><p><c><anno>Node</anno></c> is not an atom.</p></item>
<item><p><c><anno>Fun</anno></c> is not a fun of
@@ -606,34 +880,158 @@ my_call(Node, Module, Function, Args, Timeout) ->
</func>
<func>
- <name name="send_request" arity="4" since="OTP 23.0"/>
+ <name name="send_request" arity="4" clause_i="1" since="OTP 23.0"/>
<fsummary>Send a request to evaluate a function call on a node.</fsummary>
<desc>
<p>
Send an asynchronous <c>call</c> request to the node
- <c><anno>Node</anno></c>. <c>erpc:send_request()</c>
+ <c><anno>Node</anno></c>. <c>send_request/4</c>
returns a request identifier that later is to be passed
- as argument to either
- <seemfa marker="#receive_response/1"><c>erpc:receive_response()</c></seemfa>,
- <seemfa marker="#wait_response/1"><c>erpc:wait_response()</c></seemfa>,
+ to either
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>
+ in order to get the response of the call request. Besides passing
+ the request identifier directly to these functions, it can also be
+ added in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
or,
- <seemfa marker="#check_response/2"><c>erpc:check_response()</c></seemfa>
- in order to get the response of the call request.
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ If you are about to save the request identifier in a request identifier
+ collection, you may want to consider using
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>
+ instead.
+ </p>
+ <p>
+ A call to the function
+ <c>my_call(Node, Module, Function, Args, Timeout)</c>
+ below is equivalent to the call
+ <seemfa marker="#call/5"><c>erpc:call(Node, Module, Function, Args,
+ Timeout)</c></seemfa> if one disregards performance. <c>call()</c>
+ can utilize a selective receive optimization which removes
+ the need to scan the message queue from the beginning in
+ order to find a matching message. The
+ <c>send_request()/receive_response()</c> combination can,
+ however, not utilize this optimization.
</p>
- <p><c>erpc:send_request()</c> fails with an <c>{erpc, badarg}</c>
- <c>error</c> exception if:</p>
+ <pre>
+my_call(Node, Module, Function, Args, Timeout) ->
+ RequestId = erpc:send_request(Node, Module, Function, Args),
+ <seemfa marker="#receive_response/2">erpc:receive_response(RequestId, Timeout)</seemfa>.
+</pre>
+ <p>Fails with an <c>{erpc, badarg}</c> <c>error</c> exception if:</p>
+ <list>
+ <item><p><c><anno>Node</anno></c> is not an atom.</p></item>
+ <item><p><c><anno>Module</anno></c> is not an atom.</p></item>
+ <item><p><c><anno>Function</anno></c> is not an atom.</p></item>
+ <item><p><c><anno>Args</anno></c> is not a list. Note that the
+ list is not verified to be a proper list at the client side.</p></item>
+ </list>
+ <note>
+ <p>
+ You cannot make <em>any</em> assumptions about the
+ process that will perform the <c>apply()</c>. It may
+ be a server, or a freshly spawned process.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send_request" arity="4" clause_i="2" since="OTP 25.0"/>
+ <fsummary>Send a request to evaluate a function call on a node.</fsummary>
+ <desc>
+ <p>
+ The same as calling
+ <seemfa marker="#send_request/6"><c>erpc:send_request(<anno>Node</anno>,
+ erlang, apply, [<anno>Fun</anno>,[]]), <anno>Label</anno>,
+ <anno>RequestIdCollection</anno>)</c></seemfa>.
+ </p>
+ <p>Fails with an <c>{erpc, badarg}</c> <c>error</c> exception if:</p>
+ <list>
+ <item><p><c><anno>Node</anno></c> is not an atom.</p></item>
+ <item><p><c><anno>Fun</anno></c> is not a fun of zero arity.</p></item>
+ <item><p><c><anno>RequestIdCollection</anno></c> is detected not to
+ be request identifier collection.</p></item>
+ </list>
+ <note>
+ <p>
+ You cannot make <em>any</em> assumptions about the
+ process that will perform the <c>apply()</c>. It may
+ be a server, or a freshly spawned process.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send_request" arity="6" since="OTP 25.0"/>
+ <fsummary>Send a request to evaluate a function call on a node.</fsummary>
+ <desc>
+ <p>
+ Send an asynchronous <c>call</c> request to the node
+ <c><anno>Node</anno></c>. The <c><anno>Label</anno></c> will be
+ associated with the request identifier of the operation and
+ added to the returned request identifier collection
+ <c><anno>NewRequestIdCollection</anno></c>. The collection can
+ later be used in order to get one response corresponding to a
+ request in the collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+
+ <p>
+ The same as calling
+ <seemfa marker="#reqids_add/3"><c>erpc:reqids_add</c></seemfa>(<seemfa
+ marker="#send_request/4"><c>erpc:send_request</c></seemfa><c>(<anno>Node</anno>,
+ <anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>),
+ <anno>Label</anno>, <anno>RequestIdCollection</anno>)</c>, but
+ calling <c>send_request/6</c> is slightly more efficient.
+ </p>
+
+ <p>Fails with an <c>{erpc, badarg}</c> <c>error</c> exception if:</p>
<list>
<item><p><c><anno>Node</anno></c> is not an atom.</p></item>
<item><p><c><anno>Module</anno></c> is not an atom.</p></item>
<item><p><c><anno>Function</anno></c> is not an atom.</p></item>
<item><p><c><anno>Args</anno></c> is not a list. Note that the
list is not verified to be a proper list at the client side.</p></item>
+ <item><p><c><anno>RequestIdCollection</anno></c> is detected not to
+ be request identifier collection.</p></item>
</list>
+ <note>
+ <p>
+ You cannot make <em>any</em> assumptions about the
+ process that will perform the <c>apply()</c>. It may
+ be a server, or a freshly spawned process.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="wait_response" arity="1" clause_i="1" since="OTP 23.0"/>
+ <fsummary>Poll for a call response corresponding to a previously
+ sent call request.</fsummary>
+ <desc>
+ <p>
+ The same as calling
+ <seemfa marker="#wait_response/2"><c>erpc:wait_response(<anno>RequestId</anno>,
+ 0)</c></seemfa>. That is, poll for a response message to a <c>call</c>
+ request previously made by the calling process.
+ </p>
</desc>
</func>
<func>
- <name name="wait_response" arity="1" since="OTP 23.0"/>
<name name="wait_response" arity="2" since="OTP 23.0"/>
<fsummary>Wait or poll for a call response corresponding to a previously
sent call request.</fsummary>
@@ -641,40 +1039,30 @@ my_call(Node, Module, Function, Args, Timeout) ->
<p>
Wait or poll for a response message to a <c>call</c> request
previously made by the calling process using
- <seemfa marker="#send_request/4"><c>erpc:send_request/4</c></seemfa>.
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
<c><anno>RequestId</anno></c> should be the value returned from
- the previously made <c>erpc:send_request()</c> call, and the
+ the previously made <c>send_request()</c> call, and the
corresponding response should not already have been received and handled
to completion by
- <seemfa marker="#check_response/2"><c>erpc:check_response()</c></seemfa>,
- <seemfa marker="#receive_response/2"><c>erpc:receive_response()</c></seemfa>,
- or <c>erpc:wait_response()</c>. <c><anno>WaitTime</anno></c> equals the
- time to wait in milliseconds (or the atom <c>infinity</c>) during the wait.
- <c><anno>WaitTime</anno></c> is an integer representing time to wait
- in milliseconds or the atom <c>infinity</c> which will cause
- <c>wait_response/2</c> to wait for a response until it appears
- regardless of how long time that is.
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>,
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ or <c>wait_response()</c>.
</p>
<p>
- The call <c>erpc:wait_response(<anno>RequestId</anno>)</c> is equivalent
- to the call <c>erpc:wait_response(<anno>RequestId</anno>, 0)</c>. That is,
- poll for a response message to a <c>call</c> request previously made by
- the calling process.
- </p>
- <p>
- If no response is received before <c><anno>WaitTime</anno></c> milliseconds,
- the atom <c>no_response</c> is returned. It is valid to continue waiting
- for a response as many times as needed up until a response has
- been received and completed by <c>erpc:check_response()</c>,
- <c>erpc:receive_response()</c>, or <c>erpc:wait_response()</c>. If a
- response is received, the <c>call</c> operation is completed and either
- the result is returned as <c>{response, Result}</c> where <c>Result</c>
- corresponds to the value returned from the applied function or an
- exception is raised. The exceptions that can be raised corresponds to the
- same exceptions as can be raised by
- <seemfa marker="#call/4"><c>erpc:call/4</c></seemfa>.
+ <c><anno>WaitTime</anno></c> sets an upper time limit on how long to wait
+ for a response. If no response is received before the
+ <c><anno>WaitTime</anno></c> timeout has triggered, the atom
+ <c>no_response</c> is returned. It is valid to continue waiting for a
+ response as many times as needed up until a response has been received
+ and completed by <c>check_response()</c>, <c>receive_response()</c>, or
+ <c>wait_response()</c>. If a response is received, the <c>call</c>
+ operation is completed and either the result is returned as
+ <c>{response, Result}</c> where <c>Result</c> corresponds to the value
+ returned from the applied function or an exception is raised. The
+ exceptions that can be raised corresponds to the same exceptions as can
+ be raised by <seemfa marker="#call/4"><c>call/4</c></seemfa>.
That is, no <c>{erpc, timeout}</c> <c>error</c> exception can be raised.
- <c>erpc:wait_response()</c> will fail with an <c>{erpc, badarg}</c>
+ <c>wait_response/2</c> will fail with an <c>{erpc, badarg}</c>
exception if/when an invalid <c><anno>RequestId</anno></c> is detected
or if an invalid <c><anno>WaitTime</anno></c> is passed.
</p>
@@ -690,6 +1078,87 @@ my_call(Node, Module, Function, Args, Timeout) ->
</desc>
</func>
+ <func>
+ <name name="wait_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Wait or poll for a call response corresponding to a previously
+ sent call request.</fsummary>
+ <desc>
+ <p>
+ Wait or poll for a response to a <c>call</c> request corresponding
+ to a request identifier saved in <c><anno>RequestIdCollection</anno></c>. All
+ request identifiers of <c><anno>RequestIdCollection</anno></c> must
+ correspond to requests that have been made using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa> or
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>,
+ and all requests must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ <c><anno>Label</anno></c> is the label associated with the request
+ identifier of the request that the response corresponds to.
+ A request identifier is associated with a label when
+ <seemfa marker="#reqids_add/3">adding a request identifier</seemfa>
+ in a <seetype marker="#request_id_collection">request identifier
+ collection</seetype>, or when sending the request using
+ <seemfa marker="#send_request/6"><c>send_request/6</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>wait_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewRequestIdCollection</anno></c> is a possibly modified
+ request identifier collection. The <c>error</c> exception <c>{erpc,
+ badarg}</c> is not associated with any specific request identifier,
+ and will hence not be wrapped.
+ </p>
+ <p>
+ If <c><anno>RequestIdCollection</anno></c> is empty, <c>no_request</c>
+ will be returned. If no response is received before the
+ <c><anno>WaitTime</anno></c> timeout has triggered, the atom
+ <c>no_response</c> is returned. It is valid to continue waiting for a
+ response as many times as needed up until a response has been received
+ and completed by <c>check_response()</c>, <c>receive_response()</c>,
+ or <c>wait_response()</c>. The difference between
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>
+ and <c>wait_response/3</c> is that <c>receive_response/3</c>
+ abandons requests at timeout so that any potential future
+ responses are ignored, while <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>RequestIdCollection</anno></c> in the resulting
+ <c><anno>NewRequestIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewRequestIdCollection</anno></c> will equal
+ <c><anno>RequestIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>wait_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>wait_response/3</c>, it will always block
+ until a timeout determined by <c><anno>WaitTime</anno></c> is
+ triggered and then return <c>no_response</c>.
+ </p>
+ <p>
+ Note that a response might have been consumed uppon an <c>{erpc,
+ badarg}</c> exception and if so, will be lost for ever.
+ </p>
+ </desc>
+ </func>
+
</funcs>
</erlref>
diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index aa1201d381..131eba8284 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -867,6 +867,12 @@ f.txt: {person, "kalle", 25}.
does probably not match the number of bytes that can be
read from a compressed file.</p>
</item>
+ <tag><c>compressed_one</c></tag>
+ <item>
+ <p>Read one member of a gzip compressed file.
+ Option <c>compressed_one</c> can only be combined
+ with <c>read</c>.</p>
+ </item>
<tag><c>{encoding, Encoding}</c></tag>
<item>
<p>Makes the file perform automatic translation of characters to
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 0e980e9ec8..11d17beed7 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2021</year>
+ <year>2007</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -69,6 +69,7 @@
</description>
<datatypes>
+ <datatype_title>Exported data types</datatype_title>
<datatype>
<name>assoc_id()</name>
<desc>
@@ -81,12 +82,32 @@
<datatype>
<name name="option"/>
<desc>
- <p>One of the
- <seeerl marker="#options">SCTP Socket Options</seeerl>.</p>
+ <p>
+ One of the
+ <seeerl marker="#options">SCTP Socket Options</seeerl>
+ used to set an option.
+ </p>
</desc>
</datatype>
<datatype>
<name name="option_name"/>
+ <desc>
+ <p>
+ An option name or one of the
+ <seeerl marker="#options">SCTP Socket Options</seeerl>
+ used to get an option.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="option_value"/>
+ <desc>
+ <p>
+ One of the
+ <seeerl marker="#options">SCTP Socket Options</seeerl>
+ as returned when getting an option.
+ </p>
+ </desc>
</datatype>
<datatype>
<name>sctp_socket()</name>
@@ -98,6 +119,22 @@
</datatype>
</datatypes>
+ <datatypes>
+ <datatype_title>Internal data types</datatype_title>
+ <datatype>
+ <name name="elementary_option"/>
+ </datatype>
+ <datatype>
+ <name name="elementary_option_name"/>
+ </datatype>
+ <datatype>
+ <name name="record_option"/>
+ </datatype>
+ <datatype>
+ <name name="ro_option"/>
+ </datatype>
+ </datatypes>
+
<funcs>
<func>
<name name="abort" arity="2" since=""/>
@@ -305,6 +342,53 @@ connect(Socket, Ip, Port>,
</func>
<func>
+ <name name="connectx_init" arity="3" since="OTP 25.0"/>
+ <fsummary>Same as <c>connectx_init(Socket, SockAddrs, Opts, infinity)</c>..</fsummary>
+ <desc>
+ <p>Similar to
+ <seemfa marker="#connectx_init/5"><c>connectx_init/5</c></seemfa>
+ except using socket addresses, and not having a <c>Timeout</c>.
+ Since the addresses do not need lookup and the connect
+ is non-blocking this call returns immediately.</p>
+ <p>The value of each socket address <c>port</c>
+ must be the same or zero. At least one socket address
+ must have a non-zero <c>port</c></p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="connectx_init" arity="4" since="OTP 25.0"/>
+ <fsummary>Same as <c>connectx_init(Socket, Addrs, Port, Opts, infinity)</c>..</fsummary>
+ <desc>
+ <p>Same as <c>connectx_init(<anno>Socket</anno>, <anno>Addrs</anno>,
+ <anno>Port</anno>, <anno>Opts</anno>, infinity)</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="connectx_init" arity="5" since="OTP 25.0"/>
+ <fsummary>Initiate a new association for socket <c>Socket</c>, with a
+ peer (SCTP server socket).</fsummary>
+ <desc>
+ <p>Initiates a new association for socket <c><anno>Socket</anno></c>,
+ with the peer (SCTP server socket) specified by
+ <c><anno>Addrs</anno></c> and <c><anno>Port</anno></c>.</p>
+ <p>This API is similar to <c>connect_init/*</c> except the
+ underlying OS <c>sctp_connectx(3)</c> system call is used.</p>
+ <p>If successful, the association ID is returned which will be received
+ in a subsequent
+ <seeerl marker="#record-sctp_assoc_change"><c>#sctp_assoc_change{}</c></seeerl>
+ event.</p>
+ <p>The parameters are as described in
+ <seemfa marker="#connect_init/5"><c>connect_init/5</c></seemfa></p>
+ <p>NOTE: This API allows the OS to use all <anno>Addrs</anno>
+ when establishing an association, but does not guarantee it will.
+ Therefore, if the connection fails the user may want to rotate
+ the order of addresses for a subsequent call.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="controlling_process" arity="2" since=""/>
<fsummary>Assign a new controlling process pid to the socket.</fsummary>
<desc>
@@ -479,7 +563,7 @@ connect(Socket, Ip, Port>,
ancillary data
</seetype>
from the socket
- <seetype marker="#option">options</seetype>
+ <seeerl marker="#options">options</seeerl>
<seeerl marker="inet#option-recvtos"><c>recvtos</c></seeerl>,
<seeerl marker="inet#option-recvtclass"><c>recvtclass</c></seeerl>
or
@@ -877,7 +961,7 @@ connect(Socket, Ip, Port>,
<url href="http://www.rfc-archive.org/getrfc.php?rfc=2960">RFC 2960</url>
and
<url href="http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13">Sockets
- API Extenstions for SCTP</url>.</p>
+ API Extensions for SCTP</url>.</p>
</item>
<tag><c>{sctp_peer_addr_params, #sctp_paddrparams{}}</c></tag>
<item>
@@ -1255,4 +1339,3 @@ client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -&gt;
API Extensions for SCTP</url></p>
</section>
</erlref>
-
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index b63980eb61..e455cfdaf5 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>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -126,7 +126,7 @@ do_recv(Sock, Bs) ->
implementation.
A send operation will detect a remote close and immediately
return this to the caller, but do nothing else.
- A reader will therefor be able to extract any data from the OS buffers.
+ A reader will therefore be able to extract any data from the OS buffers.
If the socket is set to <c>active</c> to not <c>false</c>, the data
will be received as expected (<c>{tcp, ...}</c> and then a closed
message (<c>{tcp_closed, ...}</c> will be received (not an error). </p>
@@ -153,7 +153,7 @@ do_recv(Sock, Bs) ->
<em>will fail</em> with <c>{error, enotsup}</c>. </p>
<p>This does not actually work for <c>inet_backend = inet</c> either,
but in that case the error is simply <em>ignored</em>,
- which is a <em>bad</em> idea. We have choosen to <em>not</em>
+ which is a <em>bad</em> idea. We have chosen to <em>not</em>
ignore this error for <c>inet_backend = socket</c>. </p>
</item>
@@ -195,7 +195,7 @@ do_recv(Sock, Bs) ->
which is since long (2003) obsoleted by RFC 3542
that <em>explicitly</em> removes this possibility to get
packet information from a stream socket.
- For comparision: it has existed in FreeBSD but is now removed,
+ For comparison: it has existed in FreeBSD but is now removed,
at least since FreeBSD 10.
</p>
</note>
@@ -582,7 +582,7 @@ do_recv(Sock, Bs) ->
expires (the function can hang even when using 'inet' backend
if the internal buffers are full). </p>
<p>If this happens when using <c>packet =/= raw</c>, we have a partial
- package written. A new package therefor <em>must not</em> be written
+ package written. A new package therefore <em>must not</em> be written
at this point, as there is no way for the peer to distinguish this
from the data portion of the current package. Instead, set package
to raw, send the rest data (as raw data) and then set package to
@@ -740,4 +740,3 @@ loop(Sock) ->
comes in handy.</p>
</section>
</erlref>
-
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index 042a73823d..b21cd3e35e 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -91,6 +91,32 @@
<seemfa marker="#open/1"><c>open/1,2</c></seemfa>.</p>
</desc>
</datatype>
+ <datatype>
+ <name name="multicast_if"/>
+ </datatype>
+ <datatype>
+ <name name="ip_multicast_if"/>
+ </datatype>
+ <datatype>
+ <name name="ip6_multicast_if"/>
+ <desc>
+ <p>For IPv6 this is an interface index (an integer).</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="membership"/>
+ </datatype>
+ <datatype>
+ <name name="ip_membership"/>
+ <desc>
+ <p>The tuple with size 3 is *not* supported on all platforms.
+ 'ifindex' defaults to zero (0) on platforms that supports the
+ 3-tuple variant. </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="ip6_membership"/>
+ </datatype>
</datatypes>
<funcs>
diff --git a/lib/kernel/doc/src/global.xml b/lib/kernel/doc/src/global.xml
index 5c96850511..407ca52a8b 100644
--- a/lib/kernel/doc/src/global.xml
+++ b/lib/kernel/doc/src/global.xml
@@ -38,38 +38,45 @@
<item>Maintenance of the fully connected network</item>
</list>
<marker id="prevent_overlapping_partitions"/>
+ <p>
+ As of OTP 25, <c>global</c> will by default prevent overlapping
+ partitions due to network issues by actively disconnecting from
+ nodes that reports that they have lost connections to other
+ nodes. This will cause fully connected partitions to form instead
+ of leaving the network in a state with overlapping partitions.
+ </p>
<warning>
<p>
- By default <c>global</c> does <i>not</i> take any actions to restore
- a fully connected network when connections are lost due to network
- issues. This is problematic for all applications expecting a fully
- connected network to be provided, such as for example <c>mnesia</c>,
- but also for <c>global</c> itself. A network of overlapping partitions
- might cause the internal state of <c>global</c> to become inconsistent.
- Such an inconsistency can remain even after such partitions have been
- brought together to form a fully connected network again. The effect
- on other applications that expects that a fully connected network is
- maintained may vary, but they might misbehave in very subtle hard to
- detect ways during such a partitioning.
- </p>
- <p>
- In order to prevent such issues, we have introduced a <i>prevent
- overlapping partitions</i> fix which can be enabled using the
+ Prevention of overlapping partitions can be disabled using the
<seeapp marker="kernel_app#prevent_overlapping_partitions">
- <c>prevent_overlapping_partitions</c></seeapp> <c>kernel(6)</c>
- parameter. When this fix has been enabled, <c>global</c> will actively
- disconnect from nodes that reports that they have lost connections to
- other nodes. This will cause fully connected partitions to form
- instead of leaving the network in a state with overlapping partitions.
- Note that this fix <i>has</i> to be enabled on <i>all</i> nodes in the
- network in order to work properly. Since this quite substantially
- changes the behavior, this fix is currently disabled by default. Since
- you might get hard to detect issues without this fix you are, however,
- <i>strongly</i> advised to enable this fix in order to avoid issues
- such as the ones described above. As of OTP 25 this fix will become
- enabled by default.
+ <c>prevent_overlapping_partitions</c></seeapp>
+ <c>kernel(6)</c> parameter, making <c>global</c>
+ behave like it used to do. This is, however, problematic for all
+ applications expecting a fully connected network to be provided,
+ such as for example <c>mnesia</c>, but also for <c>global</c> itself.
+ A network of overlapping partitions might cause the internal state of
+ <c>global</c> to become inconsistent. Such an inconsistency can
+ remain even after such partitions have been brought together to form
+ a fully connected network again. The effect on other applications
+ that expects that a fully connected network is maintained may vary,
+ but they might misbehave in very subtle hard to detect ways during
+ such a partitioning. Since you might get hard to detect issues without
+ this fix, you are <i>strongly</i> advised <i>not</i> to disable this
+ fix. Also note that this fix <i>has</i> to be enabled on <i>all</i>
+ nodes in the network in order to work properly.
</p>
</warning>
+ <note>
+ <p>
+ None of the above services will be reliably delivered unless both of
+ the kernel parameters
+ <seeapp marker="kernel_app#connect_all"><c>connect_all</c></seeapp>
+ and <seeapp marker="kernel_app#prevent_overlapping_partitions">
+ <c>prevent_overlapping_partitions</c></seeapp> are enabled. Calls to
+ the <c>global</c> API will, however, <i>not</i> fail even though one or
+ both of them are disabled. You will just get unreliable results.
+ </p>
+ </note>
<p>These services are controlled through the process
<c>global_name_server</c> that exists on every node. The global
name server starts automatically when a node is started.
@@ -108,9 +115,7 @@
example, if node <c>N1</c> connects to node <c>N2</c> (which is
already connected to <c>N3</c>), the global name servers on the
nodes <c>N1</c> and <c>N3</c> ensure that also <c>N1</c>
- and <c>N3</c> are connected. If this is not desired,
- command-line flag <c>-connect_all false</c> can be used (see also
- <seecom marker="erts:erl#connect_all"><c>erl(1)</c></seecom>).
+ and <c>N3</c> are connected.
In this case, the name registration service cannot be used, but the
lock mechanism still works.</p>
<p>If the global name server fails to connect nodes (<c>N1</c> and
@@ -142,6 +147,74 @@
</func>
<func>
+ <name name="disconnect" arity="0" since="OTP 25.1"/>
+ <fsummary>Disconnect from all other nodes known to global</fsummary>
+ <desc>
+ <p>
+ Disconnect from all other nodes known to <c>global</c>. A list
+ of node names (in an unspecified order) is returned which corresponds
+ to the nodes that were disconnected. All disconnect operations
+ performed have completed when <c>global:disconnect/0</c> returns.
+ </p>
+
+ <p>
+ The disconnects will be made in such a way that only the current
+ node will be removed from the cluster of <c>global</c> nodes. If
+ <seeerl marker="#prevent_overlapping_partitions">
+ <c>prevent_overlapping_partitions</c></seeerl> is enabled and
+ you disconnect, from other nodes in the cluster of <c>global</c>
+ nodes, by other means, <c>global</c> on the other nodes may
+ partition the remaining nodes in order to ensure that no
+ overlapping partitions appear. Even if
+ <c>prevent_overlapping_partitions</c> is disabled, you should
+ preferably use <c>global:disconnect/0</c> in order to remove
+ current node from a cluster of <c>global</c> nodes, since you
+ otherwise likely <em>will</em> create overlapping partitions which
+ might <seeerl marker="#prevent_overlapping_partitions">cause
+ problems</seeerl>.
+ </p>
+
+ <p>
+ Note that if the node is going to be halted, there is <em>no</em>
+ need to remove it from a cluster of <c>global</c> nodes explicitly by
+ calling <c>global:disconnect/0</c> before halting it. The removal
+ from the cluster is taken care of automatically when the node
+ halts regardless of whether <c>prevent_overlapping_partitions</c> is
+ enabled or not.
+ </p>
+
+ <p>
+ If current node has been configured to be part of a
+ <seeerl marker="global_group"><i>global group</i></seeerl>, only
+ connected and/or synchronized nodes in that group are known to
+ <c>global</c>, so <c>global:disconnect/0</c> will <em>only</em>
+ disconnect from those nodes. If current node is <em>not</em> part of
+ a <i>global group</i>, all
+ <seemfa marker="erts:erlang#nodes/0">connected visible nodes</seemfa>
+ will be known to <c>global</c>, so <c>global:disconnect/0</c> will
+ disconnect from all those nodes.
+ </p>
+ <p>
+ Note that information about connected nodes does not instantaneously
+ reach <c>global</c>, so the caller might see a node part of the
+ result returned by
+ <seemfa marker="erts:erlang#nodes/0"><c>nodes()</c></seemfa> while
+ it still is not known to <c>global</c>. The disconnect operation
+ will, however, still not cause any overlapping partitions when
+ <c>prevent_overlapping_partitions</c> is enabled. If
+ <c>prevent_overlapping_partitions</c> is disabled, overlapping
+ partitions might form in this case.
+ </p>
+ <p>
+ Note that when <c>prevent_overlapping_partitions</c> is enabled,
+ you may see warning reports on other nodes when they detect that
+ current node has disconnected. These are in this case completely
+ harmless and can be ignored.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="notify_all_name" arity="3" since=""/>
<fsummary>Name resolving function that notifies both pids.</fsummary>
<desc>
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index e1fb1323a5..6f956924b3 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -98,7 +98,7 @@
</item>
<tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag>
<item><p>Setting the environment variable to a negative value does not
- reboot the runtime system until the crash dump file is completly
+ reboot the runtime system until the crash dump file is completely
written.</p>
</item>
<tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 8e7fe2f7bf..0dac35f9a9 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>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -92,6 +92,7 @@ fe80::204:acff:fe17:bf38
</description>
<datatypes>
+ <datatype_title>Exported data types</datatype_title>
<datatype>
<name name="hostent"/>
<desc>
@@ -130,30 +131,6 @@ fe80::204:acff:fe17:bf38
</desc>
</datatype>
<datatype>
- <name name="inet_address" since="OTP 22.1"/>
- <desc>
- <warning>
- <p>
- This address format is for now experimental
- and for completeness to make all address families have a
- <c>{Family, Destination}</c> representation.
- </p>
- </warning>
- </desc>
- </datatype>
- <datatype>
- <name name="inet6_address" since="OTP 22.1"/>
- <desc>
- <warning>
- <p>
- This address format is for now experimental
- and for completeness to make all address families have a
- <c>{Family, Destination}</c> representation.
- </p>
- </warning>
- </desc>
- </datatype>
- <datatype>
<name name="local_address"/>
<desc>
<p>
@@ -210,6 +187,9 @@ fe80::204:acff:fe17:bf38
<name name="socket_setopt"/>
</datatype>
<datatype>
+ <name name="socket_optval"/>
+ </datatype>
+ <datatype>
<name name="returned_non_ip_address"/>
<desc>
<p>
@@ -257,6 +237,61 @@ fe80::204:acff:fe17:bf38
</desc>
</datatype>
<datatype>
+ <name name="posix"/>
+ <desc>
+ <p>An atom that is named from the POSIX error codes used in Unix,
+ and in the runtime libraries of most C compilers. See section
+ <seeerl marker="#error_codes">POSIX Error Codes</seeerl>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name>socket()</name>
+ <desc>
+ <p>See
+ <seetype marker="gen_tcp#socket"><c>gen_tcp:type-socket</c></seetype>
+ and
+ <seetype marker="gen_udp#socket"><c>gen_udp:type-socket</c></seetype>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="address_family"/>
+ </datatype>
+ <datatype>
+ <name name="socket_protocol"/>
+ </datatype>
+ <datatype>
+ <name name="stat_option"/>
+ </datatype>
+ </datatypes>
+
+ <datatypes>
+ <datatype_title>Internal data types</datatype_title>
+ <datatype>
+ <name name="inet_address" since="OTP 22.1"/>
+ <desc>
+ <warning>
+ <p>
+ This address format is for now experimental
+ and for completeness to make all address families have a
+ <c>{Family, Destination}</c> representation.
+ </p>
+ </warning>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="inet6_address" since="OTP 22.1"/>
+ <desc>
+ <warning>
+ <p>
+ This address format is for now experimental
+ and for completeness to make all address families have a
+ <c>{Family, Destination}</c> representation.
+ </p>
+ </warning>
+ </desc>
+ </datatype>
+ <datatype>
<name name="getifaddrs_ifopts"/>
<desc>
<p>
@@ -329,35 +364,9 @@ fe80::204:acff:fe17:bf38
</warning>
</desc>
</datatype>
- <datatype>
- <name name="posix"/>
- <desc>
- <p>An atom that is named from the POSIX error codes used in Unix,
- and in the runtime libraries of most C compilers. See section
- <seeerl marker="#error_codes">POSIX Error Codes</seeerl>.</p>
- </desc>
- </datatype>
- <datatype>
- <name>socket()</name>
- <desc>
- <p>See
- <seetype marker="gen_tcp#socket"><c>gen_tcp:type-socket</c></seetype>
- and
- <seetype marker="gen_udp#socket"><c>gen_udp:type-socket</c></seetype>.
- </p>
- </desc>
- </datatype>
- <datatype>
- <name name="address_family"/>
- </datatype>
- <datatype>
- <name name="socket_protocol"/>
- </datatype>
- <datatype>
- <name name="stat_option"/>
- </datatype>
</datatypes>
+
<funcs>
<func>
<name name="close" arity="1" since=""/>
@@ -555,11 +564,12 @@ fe80::204:acff:fe17:bf38
<fsummary>Get one or more options for a socket.</fsummary>
<desc>
<p>Gets one or more options for a socket. For a list of available
- options, see
+ inet options, see
<seemfa marker="#setopts/2"><c>setopts/2</c></seemfa>.
- See also the description for the type
- <seetype marker="gen_tcp#pktoptions_value">
- <c>gen_tcp:pktoptions_value()</c>
+ See also the descriptions
+ for the protocol specific types referenced by
+ <seetype marker="#socket_optval">
+ <c>socket_optval()</c>
</seetype>.</p>
<p>The number of elements in the returned
<c><anno>OptionValues</anno></c>
@@ -588,7 +598,7 @@ fe80::204:acff:fe17:bf38
correspond to the second, third, and fourth/fifth parameters to the
<c>getsockopt</c> call in the C socket API. The value stored
in the buffer is returned as a binary <c>ValueBin</c>,
- where all values are coded in the native endianess.</p>
+ where all values are coded in the native endianness.</p>
<p>Asking for and inspecting raw socket options require low-level
information about the current operating system and TCP stack.</p>
<p><em>Example:</em></p>
@@ -734,10 +744,10 @@ get_tcpi_sacked(Sock) ->
<func>
<name name="info" arity="1" since="OTP 24.0"/>
- <fsummary>Retreive miscellaneous information about a socket</fsummary>
+ <fsummary>Retrieve miscellaneous information about a socket</fsummary>
<desc>
<p>
- Produces a term containg miscellaneous information about a socket.
+ Produces a term containing miscellaneous information about a socket.
</p>
</desc>
</func>
@@ -783,6 +793,36 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
+ <name name="is_ip_address" arity="1" since="OTP 25.0"/>
+ <fsummary>Tests if <c>IPAddress</c> is an IPv4 or IPv6 address tuple.</fsummary>
+ <desc>
+ <p>Tests if <c>IPAddress</c> is an
+ <seetype marker="#ip_address"><c>ip_address()</c></seetype>
+ and returns <c>true</c> if so, otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="is_ipv4_address" arity="1" since="OTP 25.0"/>
+ <fsummary>Tests if <c>IPAddress</c> is an IPv4 address tuple.</fsummary>
+ <desc>
+ <p>Tests if <c>IPAddress</c> is an
+ <seetype marker="#ip4_address"><c>ip4_address()</c></seetype>
+ and returns <c>true</c> if so, otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="is_ipv6_address" arity="1" since="OTP 25.0"/>
+ <fsummary>Tests if <c>IPAddress</c> is an IPv6 address tuple.</fsummary>
+ <desc>
+ <p>Tests if <c>IPAddress</c> is an
+ <seetype marker="#ip6_address"><c>ip6_address()</c></seetype>
+ and returns <c>true</c> if so, otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="ntoa" arity="1" since="OTP R16B02"/>
<fsummary>Convert IPv6/IPV4 address to ASCII.</fsummary>
<desc>
@@ -1528,8 +1568,16 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
</item>
<tag><c>{reuseaddr, Boolean}</c></tag>
<item>
- <p>Allows or disallows local reuse of port numbers. By
- default, reuse is disallowed.</p>
+ <p>
+ Allows or disallows local reuse of address. By
+ default, reuse is disallowed.
+ </p>
+ <note><p>
+ On Windows this option will be ignored unless
+ <c><anno>Socket</anno></c> is an UDP socket. This since the
+ behavior of <c>reuseaddr</c> is very different on Windows
+ compared to other system.
+ </p></note>
</item>
<tag><c>{send_timeout, Integer}</c></tag>
<item>
@@ -1621,7 +1669,7 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
and the option value specified as a binary. This
corresponds to the second, third, and fourth arguments to the
<c>setsockopt</c> call in the C socket API. The option value
- must be coded in the native endianess of the platform and,
+ must be coded in the native endianness of the platform and,
if a structure is required, must follow the structure
alignment conventions on the specific platform.</p>
<p>Using raw socket options requires detailed knowledge about
diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml
index 0d654bbc0e..0c25f59840 100644
--- a/lib/kernel/doc/src/inet_res.xml
+++ b/lib/kernel/doc/src/inet_res.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2021</year>
+ <year>2009</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -76,7 +76,7 @@
<p>But before all name servers are tried again, there is a
(user configurable) timeout, <c>servfail_retry_timeout</c>.
The point of this is to prevent the new query to be handled by
- a server's servfail cache (a client that is to eager will
+ a server's servfail cache (a client that is too eager will
actually only get what is in the servfail cache).
If there is too little time left
of the resolver call's timeout to do a retry,
@@ -117,7 +117,7 @@
<desc><p>A string with no adjacent dots.</p></desc>
</datatype>
<datatype>
- <name name="rr_type"/>
+ <name name="dns_rr_type"/>
</datatype>
<datatype>
<name name="dns_class"/>
@@ -125,7 +125,7 @@
<datatype>
<name name="dns_msg"/>
<desc>
- <p>This is the start of a hiearchy of opaque data structures
+ <p>This is the start of a hierarchy of opaque data structures
that can be examined with access functions in <c>inet_dns</c>, which
return lists of <c>{Field,Value}</c> tuples. The arity 2 functions
only return the value for a specified field.</p>
@@ -153,7 +153,7 @@ dns_header() = DnsHeader
| {rcode, integer(0..16)} ]
inet_dns:header(DnsHeader, Field) -> Value
-query_type() = axfr | mailb | maila | any | rr_type()
+query_type() = axfr | mailb | maila | any | dns_rr_type()
dns_query() = DnsQuery
inet_dns:dns_query(DnsQuery) ->
@@ -165,7 +165,7 @@ dns_query() = DnsQuery
dns_rr() = DnsRr
inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields
DnsRrFields = [ {domain, dns_name()}
- | {type, rr_type()}
+ | {type, dns_rr_type()}
| {class, dns_class()}
| {ttl, integer()}
| {data, dns_data()} ]
@@ -195,6 +195,9 @@ inet_dns:record_type(_) -> undefined.</pre>
in the UTF-8 coding standard.</p>
</desc>
</datatype>
+ <datatype>
+ <name name="hostent"/>
+ </datatype>
</datatypes>
<funcs>
@@ -204,9 +207,23 @@ inet_dns:record_type(_) -> undefined.</pre>
<fsummary>Resolve a DNS record of the specified type for the specified
host.</fsummary>
<desc>
- <p>Resolves a DNS record of the specified type for the specified host,
- of class <c>in</c>. Returns, on success, a <c>hostent()</c> record
- with <c>dns_data()</c> elements in the address list field.</p>
+ <p>Resolves a DNS record of the specified <c><anno>Type</anno></c>
+ for the specified host, of class <c>in</c>.
+ Returns, on success, when resolving a
+ <c><anno>Type</anno>&nbsp;=&nbsp;a|aaaa</c> DNS record,
+ a <c>#hostent{}</c> record with
+ <c>#hostent.h_addrtype&nbsp;=&nbsp;inet|inet6</c>,
+ respectively; see
+ <seetype marker="inet#hostent"><c>inet:hostent()</c></seetype>.</p>
+ <p>When resolving other
+ <c><anno>Type</anno>&nbsp;=&nbsp;dns_rr_type()</c>:s
+ (of class <c>in</c>),
+ also returns a <c>#hostent{}</c> record but with
+ <seetype marker="#dns_rr_type"><c>dns_rr_type()</c></seetype>
+ in <c>#hostent.h_addrtype</c>, and the resolved
+ <seetype marker="#dns_data"><c>dns_data()</c></seetype> in
+ <c>#hostent.h_addr_list</c>; see
+ <seetype marker="#hostent"><c>hostent()</c></seetype>.</p>
<p>This function uses resolver option <c>search</c> that
is a list of domain names. If the name to resolve contains
no dots, it is prepended to each domain name in the
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index fb1d11fad4..326b53a873 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -121,7 +121,31 @@
application. For more information about configuration parameters,
see file <seefile marker="app"><c>app(4)</c></seefile>.</p>
<taglist>
- <tag><c>distributed = [Distrib]</c></tag>
+ <tag><marker id="connect_all"/>
+ <c>connect_all = true | false</c></tag>
+ <item>
+ <p>
+ If enabled (<c>true</c>), which also is the default,
+ <seeerl marker="global"><c>global(3)</c></seeerl> will
+ actively connect to all nodes that becomes known to it. Note
+ that you also want to enable
+ <seeapp marker="#prevent_overlapping_partitions">
+ <c>prevent_overlapping_partitions</c></seeapp> in order for
+ <c>global</c> to ensure that a fully connected network
+ is maintained. <c>prevent_overlapping_partitions</c>
+ will also prevent inconsistencies in <c>global</c>'s
+ name registration and locking.
+ </p>
+ <p>
+ The now deprecated command line argument
+ <seecom marker="erts:erl#connect_all"><c>-connect_all
+ &lt;boolean&gt;</c></seecom> has the same effect as the
+ <c>connect_all</c> configuration parameter. If this
+ configuration parameter is defined, it will override
+ the command line argument.
+ </p>
+ </item>
+ <tag><marker id="distributed"/><c>distributed = [Distrib]</c></tag>
<item>
<p>Specifies which applications that are distributed and on which
nodes they are allowed to execute. In this parameter:</p>
@@ -152,13 +176,7 @@
<seeerl marker="net_kernel"><c>net_kernel(3)</c></seeerl>.</p></item>
</taglist>
</item>
- <tag><marker id="dist_listen"/><c>dist_listen = boolean()</c></tag>
- <item>
- <p>Specifies whether this node should be listening for incoming
- distribution connections. Using this option implies that the node
- also is <seecom marker="erts:erl#hidden"><c>-hidden</c></seecom>.</p>
- </item>
- <tag><c>permissions = [Perm]</c></tag>
+ <tag><marker id="permissions"/><c>permissions = [Perm]</c></tag>
<item>
<p>Specifies the default permission for applications when they
are started. In this parameter:</p>
@@ -244,9 +262,8 @@
to be forwarded to the handlers.</p>
</note>
</item>
- <tag><c>global_groups = [GroupTuple]</c></tag>
+ <tag><marker id="global_groups"/><c>global_groups = [GroupTuple]</c></tag>
<item>
- <marker id="global_groups"></marker>
<p>Defines global groups, see
<seeerl marker="global_group"><c>global_group(3)</c></seeerl>.
In this parameter:</p>
@@ -257,56 +274,54 @@
<item><p><c>Node = node()</c></p></item>
</list>
</item>
- <tag><c>inet_default_connect_options = [{Opt, Val}]</c></tag>
+ <tag><marker id="inet_default_connect_options"/><c>inet_default_connect_options = [{Opt, Val}]</c></tag>
<item>
<p>Specifies default options for <c>connect</c> sockets,
see <seeerl marker="inet"><c>inet(3)</c></seeerl>.</p>
</item>
- <tag><c>inet_default_listen_options = [{Opt, Val}]</c></tag>
+ <tag><marker id="inet_default_listen_options"/><c>inet_default_listen_options = [{Opt, Val}]</c></tag>
<item>
<p>Specifies default options for <c>listen</c> (and
<c>accept</c>) sockets, see <seeerl marker="inet"><c>inet(3)</c></seeerl>.</p>
</item>
- <tag><c>{inet_dist_use_interface, ip_address()}</c></tag>
+ <tag><marker id="inet_dist_use_interface"/><c>inet_dist_use_interface = ip_address()</c></tag>
<item>
<p>If the host of an Erlang node has many network interfaces,
this parameter specifies which one to listen on. For the type definition
of <c>ip_address()</c>,
see <seeerl marker="inet"><c>inet(3)</c></seeerl>.</p>
</item>
- <tag><c>{inet_dist_listen_min, First}</c> and <c>{inet_dist_listen_max, Last}</c></tag>
+ <tag><marker id="inet_dist_listen"/><c>inet_dist_listen_min = First</c><br/><c>inet_dist_listen_max = Last</c></tag>
<item>
<p>Defines the <c>First..Last</c> port range for the listener
socket of a distributed Erlang node.</p>
</item>
- <tag><c>{inet_dist_listen_options, Opts}</c></tag>
+ <tag><marker id="inet_dist_listen_options"/><c>inet_dist_listen_options = Opts</c></tag>
<item>
- <marker id="inet_dist_listen_options"></marker>
<p>Defines a list of extra socket options to be used when opening the
listening socket for a distributed Erlang node.
See <seemfa marker="gen_tcp#listen/2"><c>gen_tcp:listen/2</c></seemfa>.</p>
</item>
- <tag><c>{inet_dist_connect_options, Opts}</c></tag>
+ <tag><marker id="inet_dist_connect_options"/><c>inet_dist_connect_options = Opts</c></tag>
<item>
- <marker id="inet_dist_connect_options"></marker>
<p>Defines a list of extra socket options to be used when connecting to
other distributed Erlang nodes.
See <seemfa marker="gen_tcp#connect/4"><c>gen_tcp:connect/4</c></seemfa>.</p>
</item>
- <tag><c>inet_parse_error_log = silent</c></tag>
+ <tag><marker id="inet_parse_error_log"/><c>inet_parse_error_log = silent</c></tag>
<item>
<p>If set, no log events are issued when erroneous lines are
found and skipped in the various Inet configuration
files.</p>
</item>
- <tag><c>inetrc = Filename</c></tag>
+ <tag><marker id="inetrc"/><c>inetrc = Filename</c></tag>
<item>
<p>The name (string) of an Inet user configuration file. For details,
see section
<seeguide marker="erts:inet_cfg"><c>Inet Configuration</c></seeguide>
in the ERTS User's Guide.</p>
</item>
- <tag><c>net_setuptime = SetupTime</c></tag>
+ <tag><marker id="net_setuptime"/><c>net_setuptime = SetupTime</c></tag>
<item>
<marker id="net_setuptime"></marker>
<p><c>SetupTime</c> must be a positive integer or floating point
@@ -319,6 +334,35 @@
setup time, but rather each individual network operation during
the connection setup and handshake.</p>
</item>
+ <tag><marker id="net_ticker_spawn_options"/><c>net_ticker_spawn_options = Opts</c></tag>
+ <item>
+ <p>
+ Defines a list of extra spawn options for net ticker processes. There exist
+ one such process for each connection to another node. A net ticker process is
+ responsible for supervising the connection it is associated with. These
+ processes also execute the distribution handshake protocol when setting up
+ connections. When there is a large number of distribution connections,
+ setting up garbage collection options can be helpful to reduce memory usage.
+ Default is <c>[link, {priority, max}]</c>, and these two options cannot be
+ changed. The <c>monitor</c> and <c>{monitor, MonitorOpts}</c> options are
+ not allowed and will be dropped if present. See the documentation of the
+ <seemfa marker="erts:erlang#spawn_opt/4"><c>erlang:spawn_opt/4</c></seemfa>
+ BIF for information about valid options. If the <c>Opts</c> list is not
+ a proper list, or containing invalid options the setup of connections
+ will fail.
+ </p>
+ <p>
+ Note that the behavior described above is only true if the distribution
+ carrier protocol used is implemented as described in
+ <seeguide marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution Module</seeguide> without
+ further alterations. The implementer of the distribution carrier protocol
+ used, may have chosen to ignore the <c>net_ticker_spawn_options</c> parameter
+ or altered its behavior. Currently all distribution modules shipped with OTP
+ do, however, behave as described above.
+ </p>
+ </item>
<tag><marker id="net_tickintensity"/><c>net_tickintensity = NetTickIntensity</c></tag>
<item>
<p><i>Net tick intensity</i> specifies how many ticks to send during a
@@ -389,14 +433,14 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
<p>
If enabled (<c>true</c>), <c>global</c> will actively prevent
overlapping partitions from forming when connections are lost
- between nodes. This fix is, however, currently disabled by
- default. See the
+ between nodes. This fix is enabled by default. If you are about
+ to disable this fix, make sure to read the
<seeerl marker="kernel:global#prevent_overlapping_partitions">
- <c>global(3)</c></seeerl> documentation for more
- information.
+ <c>global(3)</c></seeerl> documentation about this fix for
+ more important information about this.
</p>
</item>
- <tag><c>shutdown_timeout = integer() | infinity</c></tag>
+ <tag><marker id="shutdown_timeout"/><c>shutdown_timeout = integer() | infinity</c></tag>
<item>
<p>Specifies the time <c>application_controller</c> waits
for an application to terminate during node shutdown. If the
@@ -405,7 +449,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
application. If this parameter is undefined, it defaults
to <c>infinity</c>.</p>
</item>
- <tag><c>sync_nodes_mandatory = [NodeName]</c></tag>
+ <tag><marker id="sync_nodes_mandatory"/><c>sync_nodes_mandatory = [NodeName]</c></tag>
<item>
<p>Specifies which other nodes that <em>must</em> be alive
for this node to start properly. If some node in the list
@@ -413,7 +457,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
start either. If this parameter is undefined, it defaults to
<c>[]</c>.</p>
</item>
- <tag><c>sync_nodes_optional = [NodeName]</c></tag>
+ <tag><marker id="sync_nodes_optional"/><c>sync_nodes_optional = [NodeName]</c></tag>
<item>
<p>Specifies which other nodes that <em>can</em> be alive
for this node to start properly. If some node in this list
@@ -421,7 +465,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
anyway. If this parameter is undefined, it defaults to
the empty list.</p>
</item>
- <tag><c>sync_nodes_timeout = integer() | infinity</c></tag>
+ <tag><marker id="sync_nodes_timeout"/><c>sync_nodes_timeout = integer() | infinity</c></tag>
<item>
<p>Specifies the time (in milliseconds) that this node
waits for the mandatory and optional nodes to start. If
@@ -429,7 +473,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
performed. This option ensures that <c>global</c> is
synchronized.</p>
</item>
- <tag><c>start_distribution = true | false</c></tag>
+ <tag><marker id="start_distribution"/><c>start_distribution = true | false</c></tag>
<item>
<p>Starts all distribution services, such as <c>rpc</c>,
<c>global</c>, and <c>net_kernel</c> if the parameter is
@@ -437,7 +481,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
for systems who want to disable all distribution functionality.</p>
<p>Defaults to <c>true</c>.</p>
</item>
- <tag><c>start_dist_ac = true | false</c></tag>
+ <tag><marker id="start_dist_ac"/><c>start_dist_ac = true | false</c></tag>
<item>
<p>Starts the <c>dist_ac</c> server if the parameter is
<c>true</c>. This parameter is to be set to <c>true</c> for
@@ -446,7 +490,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
undefined, the server is started if parameter
<c>distributed</c> is set.</p>
</item>
- <tag><c>start_boot_server = true | false</c></tag>
+ <tag><marker id="start_boot_server"/><c>start_boot_server = true | false</c></tag>
<item>
<p>Starts the <c>boot_server</c> if the parameter is <c>true</c>
(see <seeerl marker="erl_boot_server"><c>erl_boot_server(3)</c></seeerl>).
@@ -454,7 +498,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
using this service.</p>
<p>Defaults to <c>false</c>.</p>
</item>
- <tag><c>boot_server_slaves = [SlaveIP]</c></tag>
+ <tag><marker id="boot_server_slaves"/><c>boot_server_slaves = [SlaveIP]</c></tag>
<item>
<p>If configuration parameter <c>start_boot_server</c> is
<c>true</c>, this parameter can be used to initialize
@@ -466,7 +510,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
<p><c>'150.236.16.70', "150,236,16,70", {150,236,16,70}</c>.</p>
<p>Defaults to <c>[]</c>.</p>
</item>
- <tag><c>start_disk_log = true | false</c></tag>
+ <tag><marker id="start_disk_log"/><c>start_disk_log = true | false</c></tag>
<item>
<p>Starts the <c>disk_log_server</c> if the parameter is
<c>true</c> (see <seeerl marker="disk_log"><c>disk_log(3)</c></seeerl>).
@@ -474,7 +518,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
using this service.</p>
<p>Defaults to <c>false</c>.</p>
</item>
- <tag><c>start_pg = true | false</c></tag>
+ <tag><marker id="start_pg"/><c>start_pg = true | false</c></tag>
<item>
<marker id="start_pg"></marker>
<p>Starts the default <c>pg</c> scope server (see
@@ -483,7 +527,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
<c>true</c> in an embedded system that uses this service.</p>
<p>Defaults to <c>false</c>.</p>
</item>
- <tag><c>start_timer = true | false</c></tag>
+ <tag><marker id="start_timer"/><c>start_timer = true | false</c></tag>
<item>
<p>Starts the <c>timer_server</c> if the parameter is
<c>true</c> (see <seeerl marker="stdlib:timer"><c>timer(3)</c></seeerl>).
@@ -491,7 +535,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
using this service.</p>
<p>Defaults to <c>false</c>.</p>
</item>
- <tag><c>shell_history = enabled | disabled | module()</c></tag>
+ <tag><marker id="shell_history"/><c>shell_history = enabled | disabled | module()</c></tag>
<item>
<p>Specifies whether shell history should be logged to disk
between usages of <c>erl</c> (<c>enabled</c>), not logged
@@ -502,25 +546,25 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
called every time new line is entered in the shell. By default
logging is disabled.</p>
</item>
- <tag><c>shell_history_drop = [string()]</c></tag>
+ <tag><marker id="shell_history_drop"/><c>shell_history_drop = [string()]</c></tag>
<item>
<p>Specific log lines that should not be persisted. For
example <c>["q().", "init:stop()."]</c> will allow to
ignore commands that shut the node down. Defaults to
<c>[]</c>.</p>
</item>
- <tag><c>shell_history_file_bytes = integer()</c></tag>
+ <tag><marker id="shell_history_file_bytes"/><c>shell_history_file_bytes = integer()</c></tag>
<item>
<p>How many bytes the shell should remember. By default, the
value is set to 512kb, and the minimal value is 50kb.</p>
</item>
- <tag><c>shell_history_path = string()</c></tag>
+ <tag><marker id="shell_history_path"/><c>shell_history_path = string()</c></tag>
<item>
<p>Specifies where the shell history files will be stored.
defaults to the user's cache directory as returned by
<c>filename:basedir(user_cache, "erlang-history")</c>.</p>
</item>
- <tag><c>shutdown_func = {Mod, Func}</c></tag>
+ <tag><marker id="shutdown_func"/><c>shutdown_func = {Mod, Func}</c></tag>
<item>
<p>Where:</p>
<list type="bulleted">
@@ -534,7 +578,7 @@ MaxT = NetTickTime + NetTickTime / NetTickIntensity</code>
return as soon as possible for <c>application_controller</c>
to terminate properly.</p>
</item>
- <tag><c>source_search_rules = [DirRule] | [SuffixRule] </c></tag>
+ <tag><marker id="source_search_rules"/><c>source_search_rules = [DirRule] | [SuffixRule] </c></tag>
<item>
<marker id="source_search_rules"></marker>
<p>Where:</p>
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
index 45ee802cfc..647c970b10 100644
--- a/lib/kernel/doc/src/logger.xml
+++ b/lib/kernel/doc/src/logger.xml
@@ -480,7 +480,7 @@ logger:log(warning, #{ what => roof, cause => Cause }).
<p>The message and metadata can either be given directly in the arguments,
or returned from a fun. Passing a fun instead of the message/metadata directly is
useful in scenarios when the message/metadata is very expensive to compute.
- This is because the fun is only evaluted when the message/metadata is
+ This is because the fun is only evaluated when the message/metadata is
actually needed, which may be not at all if the log event is not
to be logged. Examples:</p>
<code>
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
index 45ee5eefad..df2edff724 100644
--- a/lib/kernel/doc/src/logger_chapter.xml
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -218,7 +218,7 @@
<pre>fun((<seetype marker="logger#report"><c>logger:report()</c></seetype>) -> {<seetype marker="stdlib:io#format"><c>io:format()</c></seetype>,[term()]})</pre>
<p>If it takes two arguments, the first is the report, and the
second is a map containing extra data that allows direct
- coversion to a string:</p>
+ conversion to a string:</p>
<pre>fun((<seetype marker="logger#report"><c>logger:report()</c></seetype>,<seetype marker="logger#report_cb_config"><c>logger:report_cb_config()</c></seetype>) -> <seetype marker="stdlib:unicode#chardata"><c>unicode:chardata()</c></seetype>)
</pre>
<p>The fun must obey the <c>depth</c> and <c>chars_limit</c>
@@ -925,7 +925,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
and progress reports.</p>
<p>Prior to Erlang/OTP 21.0, these reports were only logged
when the SASL application was running, and they were printed
- trough SASL's own event handlers <c>sasl_report_tty_h</c>
+ through SASL's own event handlers <c>sasl_report_tty_h</c>
and <c>sasl_report_file_h</c>.</p>
<p>The destination of these log events was configured by
<seeapp marker="sasl:sasl_app#deprecated_error_logger_config">SASL
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
index 0c4fac2679..527d2d0364 100644
--- a/lib/kernel/doc/src/logger_formatter.xml
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2017</year><year>2021</year>
+ <year>2017</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -154,7 +154,7 @@
<p>The value of this parameter is used as
the <c>time_designator</c> option
to <seemfa marker="stdlib:calendar#system_time_to_rfc3339/2">
- <c>calendar:system_time_to_rcf3339/2</c></seemfa>.</p>
+ <c>calendar:system_time_to_rfc3339/2</c></seemfa>.</p>
</item>
<tag><c>time_offset = integer() | [byte()]</c></tag>
<item>
@@ -179,7 +179,7 @@
<p>The value of this parameter is used as
the <c>offset</c> option
to <seemfa marker="stdlib:calendar#system_time_to_rfc3339/2">
- <c>calendar:system_time_to_rcf3339/2</c></seemfa>.</p>
+ <c>calendar:system_time_to_rfc3339/2</c></seemfa>.</p>
</item>
</taglist>
</desc>
diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml
index d0d6268e34..5d839b2b88 100644
--- a/lib/kernel/doc/src/logger_std_h.xml
+++ b/lib/kernel/doc/src/logger_std_h.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2017</year><year>2020</year>
+ <year>2017</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -149,7 +149,7 @@
information prior to writing, as long as no more
than <c>N</c> milliseconds have passed since it was last
read.</p>
- <p>Notice that the risk of loosing log events grows when
+ <p>Notice that the risk of losing log events grows when
the <c>file_check</c> value grows.</p>
<p>Defaults to 0.</p>
</item>
diff --git a/lib/kernel/doc/src/net.xml b/lib/kernel/doc/src/net.xml
index d63df8e8ca..cb5b7050a6 100644
--- a/lib/kernel/doc/src/net.xml
+++ b/lib/kernel/doc/src/net.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2018</year><year>2020</year>
+ <year>2018</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,13 +33,6 @@
<modulesummary>Network interface.</modulesummary>
<description>
<p>This module provides an API for the network interface.</p>
- <note>
- <p>There is currently <em>no</em> support for Windows. </p>
- </note>
- <note>
- <p>The content of this file is <em>only</em> valid if the system has
- been built with 'socket' (esock) support, which is the default. </p>
- </note>
</description>
<datatypes>
@@ -51,16 +44,21 @@
<desc>
<p>This type defines all addresses (and flags) associated with
the interface. </p>
- <p>Not all fields of this map has to be present.
- The flags field can be used to test for some of the fields.
- For example <c>broadaddr</c> will only be present if the
- <c>broadcast</c> flag is present in flags. </p>
+ <note>
+ <p>Not all fields of this map has to be present.
+ The flags field can be used to test for some of the fields.
+ For example <c>broadaddr</c> will only be present if the
+ <c>broadcast</c> flag is present in flags. </p>
+ </note>
</desc>
</datatype>
<datatype>
<name name="ifaddrs_flag"/>
</datatype>
<datatype>
+ <name name="ifaddrs_flags"/>
+ </datatype>
+ <datatype>
<name name="ifaddrs_filter"/>
<desc>
<taglist>
@@ -132,7 +130,7 @@
<func>
<name name="getnameinfo" arity="1" since="OTP 22.0"/>
<name name="getnameinfo" arity="2" since="OTP 22.0"/>
- <fsummary>Address-to-name transaltion.</fsummary>
+ <fsummary>Address-to-name translation.</fsummary>
<desc>
<p>Address-to-name translation in a protocol-independant manner.</p>
<p>This function is the inverse of
@@ -146,7 +144,7 @@
<name name="getaddrinfo" arity="2" clause_i="1" since="OTP 22.0"/>
<name name="getaddrinfo" arity="2" clause_i="2" since="OTP 22.0"/>
<name name="getaddrinfo" arity="2" clause_i="3" since="OTP 22.0"/>
- <fsummary>Network address and service transation.</fsummary>
+ <fsummary>Network address and service transaction.</fsummary>
<desc>
<p>Network address and service translation.</p>
<p>This function is the inverse of
@@ -169,7 +167,7 @@
possibly filtered according to <c>Filter</c>. </p>
<p>By default, a filter with the content:
<c>#{family => default, flags => any}</c> is used.
- This will return all interfaces with adresses in the
+ This will return all interfaces with addresses in the
<c>inet</c> and <c>inet6</c> families. </p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 977fb35caf..3ee52a3637 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -150,6 +150,83 @@ $ <input>erl -sname foobar</input></pre>
</func>
<func>
+ <name name="get_state" arity="0" since="OTP 25.0"/>
+ <fsummary>Get various distribution state.</fsummary>
+ <desc>
+ <p>Get the current state of the distribution for the local node.</p>
+ <p>Returns a map with (at least) the following key-value pairs:</p>
+ <taglist>
+ <tag><c>started => Started</c></tag>
+ <item>
+ <p>Valid values for <c>Started</c>:</p>
+ <taglist>
+ <tag><c>no</c></tag>
+ <item>
+ <p>The distribution is not started. In this state none of
+ the other keys below are present in the map.</p>
+ </item>
+ <tag><c>static</c></tag>
+ <item>
+ <p>The distribution was started with command line arguments
+ <seecom marker="erts:erl#name"><c>-name</c></seecom> or
+ <seecom marker="erts:erl#sname"><c>-sname</c></seecom>.</p>
+ </item>
+ <tag><c>dynamic</c></tag>
+ <item>
+ <p>The distribution was started with
+ <seemfa marker="#start/1"><c>net_kernel:start/1</c></seemfa>
+ and can be stopped with
+ <seemfa marker="#start/1"><c>net_kernel:stop/0</c></seemfa>.</p>
+ </item>
+ </taglist>
+ </item>
+ <tag><c>name => Name</c></tag>
+ <item>
+ <p>The name of the node. Same as returned by
+ <seemfa marker="erts:erlang#node/0"><c>erlang:node/0</c></seemfa>
+ except when <c>name_type</c> is <c>dynamic</c> in which case
+ <c>Name</c> may be <c>undefined</c> (instead of <c>nonode@nohost</c>).
+ </p>
+ </item>
+ <tag><c>name_type => NameType</c></tag>
+ <item>
+ <p>Valid values for <c>NameType</c>:</p>
+ <taglist>
+ <tag><c>static</c></tag>
+ <item>
+ <p>The node has a static node name set by the node itself.</p>
+ </item>
+ <tag><c>dynamic</c></tag>
+ <item>
+ <p>The distribution was started in
+ <seeguide marker="system/reference_manual:distributed#dyn_node_name">
+ dynamic node name</seeguide> mode, and will get its node name assigned
+ from the first node it connects to. If key <c>name</c> has value
+ <c>undefined</c> that has not happened yet.</p>
+ </item>
+ </taglist>
+ </item>
+ <tag><c>name_domain => NameDomain</c></tag>
+ <item>
+ <p>Valid values for <c>NameDomain</c>:</p>
+ <taglist>
+ <tag><c>shortnames</c></tag>
+ <item>
+ <p>The distribution was started to use node names with a short
+ host portion (not fully qualified).</p>
+ </item>
+ <tag><c>longnames</c></tag>
+ <item>
+ <p>The distribution was started to use node names with a long
+ fully qualified host portion.</p>
+ </item>
+ </taglist>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
<name name="monitor_nodes" arity="1" since=""/>
<name name="monitor_nodes" arity="2" since=""/>
<fsummary>Subscribe to node status change messages.</fsummary>
@@ -165,82 +242,121 @@ $ <input>erl -sname foobar</input></pre>
are stopped. Two
option lists are considered the same if they contain the same
set of options.</p>
- <p>As from Kernel version 2.11.4, and ERTS version
- 5.5.4, the following is guaranteed:</p>
- <list type="bulleted">
- <item><p><c>nodeup</c> messages are delivered before delivery
- of any message from the remote node passed through the
- newly established connection.</p></item>
- <item><p><c>nodedown</c> messages are not delivered until all
- messages from the remote node that have been passed
- through the connection have been delivered.</p></item>
- </list>
- <p>Notice that this is <em>not</em> guaranteed for Kernel
- versions before 2.11.4.</p>
- <p>As from Kernel version 2.11.4, subscriptions can also be
- made before the <c>net_kernel</c> server is started, that is,
- <c>net_kernel:monitor_nodes/[1,2]</c> does not return
- <c>ignored</c>.</p>
- <p>As from Kernel version 2.13, and ERTS version
- 5.7, the following is guaranteed:</p>
- <list type="bulleted">
- <item><p><c>nodeup</c> messages are delivered after the
+ <p>Delivery guarantees of <c>nodeup</c>/<c>nodedown</c> messages:</p>
+ <list>
+ <item><p>
+ <c>nodeup</c> messages are delivered before delivery
+ of any signals from the remote node through the newly
+ established connection.
+ </p></item>
+ <item>
+ <p><c>nodedown</c> messages are delivered after all
+ the signals from the remote node over the connection
+ have been delivered.
+ </p></item>
+ <item><p>
+ <c>nodeup</c> messages are delivered after the
corresponding node appears in results from
- <c>erlang:nodes/X</c>.</p></item>
- <item><p><c>nodedown</c> messages are delivered after the
+ <c>erlang:nodes()</c>.
+ </p></item>
+ <item>
+ <p><c>nodedown</c> messages are delivered after the
corresponding node has disappeared in results from
- <c>erlang:nodes/X</c>.</p></item>
+ <c>erlang:nodes()</c>.
+ </p></item>
+ <item><p>
+ As of OTP 23.0, a <c>nodedown</c> message for a
+ connection being taken down will be delivered before a
+ <c>nodeup</c> message due to a new connection to the
+ same node. Prior to OTP 23.0, this was not
+ guaranteed to be the case.
+ </p></item>
</list>
- <p>Notice that this is <em>not</em> guaranteed for Kernel
- versions before 2.13.</p>
<p>The format of the node status change messages depends on
<c><anno>Options</anno></c>. If <c><anno>Options</anno></c> is
- <c>[]</c>, which is the default, the format is as follows:</p>
- <code type="none">
+ the empty list or if <c>net_kernel:monitor_nodes/1</c> is called,
+ the format is as follows:</p>
+ <code type="erl">
{nodeup, Node} | {nodedown, Node}
Node = node()</code>
- <p>If <c><anno>Options</anno></c> is not <c>[]</c>, the format is
- as follows:</p>
- <code type="none">
-{nodeup, Node, InfoList} | {nodedown, Node, InfoList}
+ <p>
+ When <c><anno>Options</anno></c> is the empty map or empty
+ list, the caller will only subscribe for status change messages
+ for visible nodes. That is, only nodes that appear in the
+ result of
+ <seemfa marker="erts:erlang#nodes/0"><c>erlang:nodes/0</c></seemfa>.
+ </p>
+ <p>
+ If <c><anno>Options</anno></c> equals anything other than the
+ empty list, the format of the status change messages is as follows:
+ </p>
+ <code type="erl">
+{nodeup, Node, Info} | {nodedown, Node, Info}
Node = node()
- InfoList = [{Tag, Val}]</code>
- <p><c>InfoList</c> is a list of tuples. Its contents depends on
- <c><anno>Options</anno></c>, see below.</p>
- <p>Also, when <c>OptionList == []</c>, only visible nodes, that
- is, nodes that appear in the result of
- <seemfa marker="erts:erlang#nodes/0"><c>erlang:nodes/0</c></seemfa>,
- are monitored.</p>
- <p><c><anno>Option</anno></c> can be any of the following:</p>
+ Info = #{Tag => Val} | [{Tag, Val}]</code>
+ <p>
+ <c>Info</c> is either a map or a list of 2-tuples. Its content
+ depends on <c><anno>Options</anno></c>. If <c><anno>Options</anno></c>
+ is a map, <c>Info</c> will also be a map. If <c><anno>Options</anno></c>
+ is a list, <c>Info</c> will also be a list.
+ </p>
+ <p>
+ When <c><anno>Options</anno></c> is a map, currently
+ the following associations are allowed:
+ </p>
<taglist>
- <tag><c>{node_type, NodeType}</c></tag>
+ <tag><c>connection_id => boolean()</c></tag>
+ <item>
+ <p>
+ If the value of the association equals <c>true</c>, a
+ <c>connection_id => ConnectionId</c> association will be
+ included in the <c>Info</c> map where <c>ConnectionId</c>
+ is the connection identifier of the connection coming up
+ or going down. For more info about this connection
+ identifier see the documentation of
+ <seeerl marker="erts:erlang#connection_id">erlang:nodes/2</seeerl>.
+ </p>
+ </item>
+ <tag><c>node_type => <anno>NodeType</anno></c></tag>
<item>
<p>Valid values for <c>NodeType</c>:</p>
<taglist>
<tag><c>visible</c></tag>
<item><p>Subscribe to node status change messages for visible
- nodes only. The tuple <c>{node_type, visible}</c> is
- included in <c>InfoList</c>.</p></item>
+ nodes only. The association <c>node_type => visible</c> will
+ be included in the <c>Info</c> map.</p></item>
<tag><c>hidden</c></tag>
<item><p>Subscribe to node status change messages for hidden
- nodes only. The tuple <c>{node_type, hidden}</c> is
- included in <c>InfoList</c>.</p></item>
+ nodes only. The association <c>node_type => hidden</c> will
+ be included in the <c>Info</c> map.</p></item>
<tag><c>all</c></tag>
<item><p>Subscribe to node status change messages for both
- visible and hidden nodes. The tuple
- <c>{node_type, visible | hidden}</c> is included in
- <c>InfoList</c>.</p></item>
+ visible and hidden nodes. The association
+ <c>node_type => visible | hidden</c> will be included in
+ the <c>Info</c> map.</p></item>
</taglist>
+ <p>
+ If no <c>node_type => <anno>NodeType</anno></c> association
+ is included in the <c><anno>Options</anno></c> map, the
+ caller will subscribe for status change messages for visible
+ nodes only, but <i>no</i> <c>node_type => visible</c>
+ association will be included in the <c>Info</c> map.
+ </p>
</item>
- <tag><c>nodedown_reason</c></tag>
+ <tag><c>nodedown_reason => boolean()</c></tag>
<item>
- <p>The tuple <c>{nodedown_reason, Reason}</c> is included in
- <c>InfoList</c> in <c>nodedown</c> messages.</p>
+ <p>
+ If the value of the association equals <c>true</c>, a
+ <c>nodedown_reason => Reason</c> association will be
+ included in the <c>Info</c> map for <c>nodedown</c>
+ messages.
+ </p>
+ <marker id="nodedown_reasons"/>
<p>
<c>Reason</c> can, depending on which
- distribution module or process that is used be any term,
+ distribution module or process that is used, be any term,
but for the standard TCP distribution module it is
- any of the following:
+ one of the following:
</p>
<taglist>
<tag><c>connection_setup_failed</c></tag>
@@ -267,6 +383,82 @@ $ <input>erl -sname foobar</input></pre>
</taglist>
</item>
</taglist>
+ <p>
+ When <c><anno>Options</anno></c> is a list, currently
+ <c><anno>ListOption</anno></c> can be one of the following:
+ </p>
+ <taglist>
+ <tag><c>connection_id</c></tag>
+ <item>
+ <p>
+ A <c>{connection_id, ConnectionId}</c> tuple will be
+ included in <c>Info</c> where <c>ConnectionId</c> is the
+ connection identifier of the connection coming up or
+ going down. For more info about this connection identifier
+ see the documentation of
+ <seeerl marker="erts:erlang#connection_id">erlang:nodes/2</seeerl>.
+ </p>
+ </item>
+ <tag><c>{node_type, <anno>NodeType</anno>}</c></tag>
+ <item>
+ <p>Valid values for <c><anno>NodeType</anno></c>:</p>
+ <taglist>
+ <tag><c>visible</c></tag>
+ <item><p>Subscribe to node status change messages for visible
+ nodes only. The tuple <c>{node_type, visible}</c> will be
+ included in the <c>Info</c> list.</p></item>
+ <tag><c>hidden</c></tag>
+ <item><p>Subscribe to node status change messages for hidden
+ nodes only. The tuple <c>{node_type, hidden}</c> will be
+ included in the <c>Info</c> list.</p></item>
+ <tag><c>all</c></tag>
+ <item><p>Subscribe to node status change messages for both
+ visible and hidden nodes. The tuple
+ <c>{node_type, visible | hidden}</c> will be included in
+ the <c>Info</c> list.</p></item>
+ </taglist>
+ <p>
+ If no <c>{node_type, <anno>NodeType</anno>}</c> option
+ has been given. The caller will subscribe for status
+ change messages for visible nodes only, but <i>no</i>
+ <c>{node_type, visible}</c> tuple will be included in the
+ <c>Info</c> list.
+ </p>
+ </item>
+ <tag><c>nodedown_reason</c></tag>
+ <item>
+ <p>
+ The tuple <c>{nodedown_reason, Reason}</c> will be included
+ in the <c>Info</c> list for <c>nodedown</c> messages.
+ </p>
+ <p>
+ See the documentation of the
+ <seeerl marker="#nodedown_reasons"><c>nodedown_reason
+ => boolean()</c></seeerl> association above for information
+ about possible <c>Reason</c> values.
+ </p>
+ </item>
+ </taglist>
+ <p>Example:</p>
+ <code type="erl">
+(a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
+ok
+(a@localhost)2> flush().
+Shell got {nodeup,b@localhost,
+ #{connection_id => 3067552,node_type => visible}}
+Shell got {nodeup,c@localhost,
+ #{connection_id => 13892107,node_type => hidden}}
+Shell got {nodedown,b@localhost,
+ #{connection_id => 3067552,node_type => visible,
+ nodedown_reason => connection_closed}}
+Shell got {nodedown,c@localhost,
+ #{connection_id => 13892107,node_type => hidden,
+ nodedown_reason => net_tick_timeout}}
+Shell got {nodeup,b@localhost,
+ #{connection_id => 3067553,node_type => visible}}
+ok
+(a@localhost)3>
+ </code>
</desc>
</func>
@@ -340,7 +532,7 @@ $ <input>erl -sname foobar</input></pre>
or <c>{error, noconnection}</c> if <c><anno>Node</anno></c> is not
a connected node or <c>new</c>.</p>
<p>If <c><anno>Node</anno></c> is <c>new</c> the <c><anno>Options</anno></c>
- will then also be added to kernel configration parameters
+ will then also be added to kernel configuration parameters
<seeapp marker="kernel:kernel_app#inet_dist_listen_options">inet_dist_listen_options</seeapp>
and
<seeapp marker="kernel:kernel_app#inet_dist_connect_options">inet_dist_connect_options</seeapp>.</p>
@@ -358,10 +550,13 @@ $ <input>erl -sname foobar</input></pre>
</p>
<p>
- If <c>Name</c> is set to <em><c>undefined</c></em> the distribution
- will be started to request a dynamic node name from the first node it
- connects to. See <seeguide marker="system/reference_manual:distributed#dyn_node_name">
- Dynamic Node Name</seeguide>.
+ If <c><anno>Name</anno></c> is set to <em><c>undefined</c></em> the
+ distribution will be started to request a dynamic node name from the
+ first node it connects to. See
+ <seeguide marker="system/reference_manual:distributed#dyn_node_name">
+ Dynamic Node Name</seeguide>. Setting <c><anno>Name</anno></c> to
+ <c>undefined</c> implies options <c>dist_listen => false</c> and
+ <c>hidden => true</c>.
</p>
<p>Currently supported options:</p>
@@ -396,6 +591,30 @@ $ <input>erl -sname foobar</input></pre>
<c><anno>NetTickIntensity</anno></c> value is passed as option value
to this function, the call will fail.
</p></item>
+ <tag><c>dist_listen => boolean()</c></tag>
+ <item><p>
+ Enable or disable listening for incoming connections. Defaults to
+ the value of the
+ <seecom marker="erts:erl#dist_listen"><c>-dist_listen</c></seecom>
+ <c>erl</c> command line argument. Note that
+ <c>dist_listen => false</c> implies <c>hidden => true</c>.
+ </p>
+ <p>
+ If <c>undefined</c> has been passed as <c><anno>Name</anno></c>,
+ the <c>dist_listen</c> option will be overridden with
+ <c>dist_listen => false</c>.
+ </p></item>
+ <tag><c>hidden => boolean()</c></tag>
+ <item><p>
+ Enable or disable hidden node. Defaults to <c>true</c> if the
+ <seecom marker="erts:erl#hidden"><c>-hidden</c></seecom> <c>erl</c>
+ command line argument has been passed; otherwise <c>false</c>.
+ </p>
+ <p>
+ If <c>undefined</c> has been passed as <c><anno>Name</anno></c>,
+ or the option <c>dist_listen</c> equals <c>false</c>, the
+ <c>hidden</c> option will be overridden with <c>hidden => true</c>.
+ </p></item>
</taglist>
</desc>
</func>
@@ -463,4 +682,3 @@ $ <input>erl -sname foobar</input></pre>
</func>
</funcs>
</erlref>
-
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 0c96c6e50e..2a2992b720 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,781 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 8.5.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug on Windows where
+ <c>file:read_file_info/1</c> would fail for files with
+ corrupt metadata.</p>
+ <p>
+ Own Id: OTP-18348 Aux Id: GH-6356 </p>
+ </item>
+ <item>
+ <p>
+ Accept connection setup from OTP 23 and 24 nodes that are
+ not using epmd.</p>
+ <p>
+ Own Id: OTP-18404 Aux Id: GH-6595, PR-6625 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.5.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The tcp connect option 'bind_to_device' could not be used
+ with inet_backend = 'socket'. 'inet' requires value type
+ binarry() and 'socket' requires value type 'string()'.</p>
+ <p>
+ Own Id: OTP-18357 Aux Id: #6509 </p>
+ </item>
+ <item>
+ <p>
+ Minor issue processing options when calling
+ gen_tcp:connect with a sockaddr() and inet_backend =
+ socket.</p>
+ <p>
+ Own Id: OTP-18358 Aux Id: #6528 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed shutdown crash in gen_tcp socket backend, when the
+ other end closed the socket.</p>
+ <p>
+ Own Id: OTP-18270 Aux Id: #6331 </p>
+ </item>
+ <item>
+ <p><c>erl_tar</c> can now read gzip-compressed tar files
+ that are padded. There is a new option
+ <c>compressed_one</c> for <c>file:open/2</c> that will
+ read a single member from a gzip file,</p>
+ <p>
+ Own Id: OTP-18289 Aux Id: PR-6343 </p>
+ </item>
+ <item>
+ <p>
+ Fix <c>os:cmd</c> to not translate all exceptions thrown
+ to <c>badarg</c>. For example <c>emfile</c> from
+ <c>erlang:open_port</c> was translated to <c>badarg</c>.</p>
+ <p>
+ This bug has existed since Erlang/OTP 24.</p>
+ <p>
+ Own Id: OTP-18291 Aux Id: PR-6382 </p>
+ </item>
+ <item>
+ <p>
+ Spec for function net:if_names/0 incorrect</p>
+ <p>
+ Own Id: OTP-18296 Aux Id: OTP-16464 </p>
+ </item>
+ <item>
+ <p>
+ Missing ctrl option name transation for TOS and TTL (on
+ FreeBSD) when using gen_udp with the 'socket'
+ inet_backend.</p>
+ <p>
+ Own Id: OTP-18315</p>
+ </item>
+ <item>
+ <p>
+ gen_udp:open/2 with option(s) add_membership or
+ drop_membership would drop earlier options.</p>
+ <p>
+ Own Id: OTP-18323 Aux Id: #6476 </p>
+ </item>
+ <item>
+ <p>
+ The <seemfa
+ marker="kernel:inet#setopts/2"><c>inet:setopts/2</c></seemfa>
+ <c>{reuseaddr, true}</c> option will now be ignored on
+ Windows unless the socket is an UDP socket. For more
+ information see the documentation of the <c>reuseaddr</c>
+ option part of the documentation of
+ <c>inet:setopts/2</c>.</p>
+ <p>
+ Prior to OTP 25 the <c>{reuseaddr, true}</c> option was
+ ignored for all sockets on Windows, but as of OTP 25.0
+ this was changed so that it was not ignored for any
+ sockets.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18324 Aux Id: GH-6461, PR-6481 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>The distribution socket option handling in
+ <c>inet_tcp_dist</c> has been cleaned up to clarify which
+ were mandatory and which just had default values. </p>
+ <p>
+ Own Id: OTP-18293</p>
+ </item>
+ <item>
+ <p>
+ Improve warning message format for gen_tcp_socket.</p>
+ <p>
+ Own Id: OTP-18317</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.5.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Listen sockets created with the socket module, leaked
+ (erlang-) monitors.</p>
+ <p>
+ Own Id: OTP-18240 Aux Id: #6285 </p>
+ </item>
+ <item>
+ <p>
+ <seeerl marker="stdlib:peer"><c>peer</c></seeerl> nodes
+ failed to halt when the process supervising the control
+ connection crashed. When an alternative control
+ connection was used, this supervision process also quite
+ frequently crashed when the <c>peer</c> node was stopped
+ by the node that started it which caused the <c>peer</c>
+ node to linger without ever halting.</p>
+ <p>
+ Own Id: OTP-18249 Aux Id: PR-6301 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed inconsistency bugs in <seeerl
+ marker="kernel:global"><c>global</c></seeerl> due to
+ <c>nodeup</c>/<c>nodedown</c> messages not being
+ delivered before/after traffic over connections. Also
+ fixed various other inconsistency bugs and deadlocks in
+ both <seeerl
+ marker="kernel:global_group"><c>global_group</c></seeerl>
+ and <c>global</c>.</p>
+ <p>
+ As building blocks for these fixes, a new BIF <seemfa
+ marker="erts:erlang#nodes/2"><c>erlang:nodes/2</c></seemfa>
+ has been introduced and <seemfa
+ marker="kernel:net_kernel#monitor_nodes/2"><c>net_kernel:monitor_nodes/2</c></seemfa>
+ has been extended.</p>
+ <p>
+ The <seecom
+ marker="erts:erl#hidden"><c>-hidden</c></seecom> and
+ <seecom
+ marker="erts:erl#connect_all"><c>-connect_all</c></seecom>
+ command line arguments did not work if multiple instances
+ were present on the command line which has been fixed.
+ The new kernel parameter <seeapp
+ marker="kernel:kernel_app#connect_all"><c>connect_all</c></seeapp>
+ has also been introduced in order to replace the
+ <c>-connect_all</c> command line argument.</p>
+ <p>
+ Own Id: OTP-17934 Aux Id: PR-6007 </p>
+ </item>
+ <item>
+ <p>
+ Fixed IPv6 multicast_if and membership socket options.</p>
+ <p>
+ Own Id: OTP-18091 Aux Id: #5789 </p>
+ </item>
+ <item>
+ <p>
+ Fixed issue with inet:getifaddrs hanging on pure IPv6
+ Windows</p>
+ <p>
+ Own Id: OTP-18102 Aux Id: #5904 </p>
+ </item>
+ <item>
+ <p>
+ The type specifications for <c>inet:getopts/2</c> and
+ <c>inet:setopts/2</c> have been corrected regarding SCTP
+ options.</p>
+ <p>
+ Own Id: OTP-18115 Aux Id: PR-5939 </p>
+ </item>
+ <item>
+ <p>
+ The type specifications for <c>inet:parse_*</c> have been
+ tightened.</p>
+ <p>
+ Own Id: OTP-18121 Aux Id: PR-5972 </p>
+ </item>
+ <item>
+ <p>
+ Fix gen_tcp:connect/3 spec to include the inet_backend
+ option.</p>
+ <p>
+ Own Id: OTP-18171 Aux Id: PR-6131 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where using a binary as the format when calling
+ <c>logger:log(Level, Format, Args)</c> (or any other
+ logging function) would cause a crash or incorrect
+ logging.</p>
+ <p>
+ Own Id: OTP-18229 Aux Id: PR-6212 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add rudimentary debug feature (option) for the
+ inet-driver based sockets, such as gen_tcp and gen_udp.</p>
+ <p>
+ Own Id: OTP-18032</p>
+ </item>
+ <item>
+ <p>
+ Introduced the <c>hidden</c> and <c>dist_listen</c>
+ options to <seemfa
+ marker="kernel:net_kernel#start/2"><c>net_kernel:start/2</c></seemfa>.</p>
+ <p>
+ Also documented the <seecom
+ marker="erts:erl#dist_listen"><c>-dist_listen</c></seecom>
+ command line argument which was erroneously documented as
+ a <c>kernel</c> parameter and not as a command line
+ argument.</p>
+ <p>
+ Own Id: OTP-18107 Aux Id: PR-6009 </p>
+ </item>
+ <item>
+ <p>
+ Scope and group monitoring have been introduced in
+ <seeerl marker="kernel:pg"><c>pg</c></seeerl>. For more
+ information see the documentation of <seemfa
+ marker="kernel:pg#monitor_scope/0"><c>pg:monitor_scope()</c></seemfa>,
+ <seemfa
+ marker="kernel:pg#monitor/1"><c>pg:monitor()</c></seemfa>,
+ and <seemfa
+ marker="kernel:pg#demonitor/1"><c>pg:demonitor()</c></seemfa>.</p>
+ <p>
+ Own Id: OTP-18163 Aux Id: PR-6058, PR-6275 </p>
+ </item>
+ <item>
+ <p>
+ A new function <seemfa
+ marker="kernel:global#disconnect/0"><c>global:disconnect/0</c></seemfa>
+ has been introduced with which one can cleanly disconnect
+ a node from all other nodes in a cluster of <c>global</c>
+ nodes.</p>
+ <p>
+ Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A call to <seemfa
+ marker="net_kernel#setopts/2"><c>net_kernel:setopts(new,
+ Opts)</c></seemfa> at the same time as a connection was
+ being set up could cause a deadlock between the
+ <c>net_kernel</c> process and the process setting up the
+ connection.</p>
+ <p>
+ Own Id: OTP-18198 Aux Id: GH-6129, PR-6216 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The DNS resolver <c>inet_res</c> has been fixed to ignore
+ trailing dot difference in the request domain between the
+ sent request and the received response, when validating a
+ response.</p>
+ <p>
+ Own Id: OTP-18112 Aux Id: ERIERL-811 </p>
+ </item>
+ <item>
+ <p>
+ A bug in <c>inet_res</c> has been fixed where a missing
+ internal <c>{ok,_}</c> wrapper caused
+ <c>inet_res:resolve/*</c> to return a calculated host
+ name instead of an `<c>{ok,Msg}</c> tuple, when resolving
+ an IP address or a host name that is an IP address
+ string.</p>
+ <p>
+ Own Id: OTP-18122 Aux Id: GH-6015, PR-6020 </p>
+ </item>
+ <item>
+ <p>
+ The <c>erlang:is_alive()</c> BIF could return <c>true</c>
+ before configured distribution service was available.
+ This bug was introduced in OTP 25.0 ERTS version 13.0.</p>
+ <p>
+ The <c>erlang:monitor_node()</c> and
+ <c>erlang:monitor()</c> BIFs could erroneously fail even
+ though configured distribution service was available.
+ This occurred if these BIFs were called after the
+ distribution had been started using dynamic node name
+ assignment but before the name had been assigned.</p>
+ <p>
+ Own Id: OTP-18124 Aux Id: OTP-17558, PR-6032 </p>
+ </item>
+ <item>
+ <p>
+ Added the missing mandatory <c>address/0</c> callback in
+ the <c>gen_tcp_dist</c> example.</p>
+ <p>
+ Own Id: OTP-18136</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The DNS resolver implementation has been rewritten to
+ validate replies more thoroughly, and a bit optimized to
+ create less garbage.</p>
+ <p>
+ Own Id: OTP-17323</p>
+ </item>
+ <item>
+ <p>
+ The socket option 'reuseaddr' is *no longer* ignored on
+ Windows.</p>
+ <p>
+ Own Id: OTP-17447 Aux Id: GH-4819 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug where using the atoms <c>string</c> or
+ <c>report</c> as the format when calling
+ <c>logger:log(Level, Format, Args)</c> (or any other
+ logging function) would cause a crash or incorrect
+ logging.</p>
+ <p>
+ Own Id: OTP-17551 Aux Id: GH-5071 PR-5075 </p>
+ </item>
+ <item>
+ <p> As of OTP 25, <c>global</c> will by default prevent
+ overlapping partitions due to network issues by actively
+ disconnecting from nodes that reports that they have lost
+ connections to other nodes. This will cause fully
+ connected partitions to form instead of leaving the
+ network in a state with overlapping partitions. </p> <p>
+ Prevention of overlapping partitions can be disabled
+ using the <seeapp
+ marker="kernel_app#prevent_overlapping_partitions"><c>prevent_overlapping_partitions</c></seeapp>
+ <c>kernel(6)</c> parameter, making <c>global</c> behave
+ like it used to do. This is, however, problematic for all
+ applications expecting a fully connected network to be
+ provided, such as for example <c>mnesia</c>, but also for
+ <c>global</c> itself. A network of overlapping partitions
+ might cause the internal state of <c>global</c> to become
+ inconsistent. Such an inconsistency can remain even after
+ such partitions have been brought together to form a
+ fully connected network again. The effect on other
+ applications that expects that a fully connected network
+ is maintained may vary, but they might misbehave in very
+ subtle hard to detect ways during such a partitioning.
+ Since you might get hard to detect issues without this
+ fix, you are <i>strongly</i> advised <i>not</i> to
+ disable this fix. Also note that this fix <i>has</i> to
+ be enabled on <i>all</i> nodes in the network in order to
+ work properly. </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17911 Aux Id: PR-5687, PR-5611, OTP-17843 </p>
+ </item>
+ <item>
+ <p> Starting the helper program for name resolving;
+ <c>inet_gethost</c>, has been improved to use an absolute
+ file system path to ensure that the right program is
+ started. </p><p> If the helper program can not be started
+ - the system now halts, to avoid running with a silently
+ broken name resolver. </p>
+ <p>
+ Own Id: OTP-17958 Aux Id: OTP-17978 </p>
+ </item>
+ <item>
+ <p>
+ The type specification for <c>inet_res:getbyname/2,3</c>
+ has been corrected to reflect that it can return peculiar
+ <c>#hostent{}</c> records.</p>
+ <p>
+ Own Id: OTP-17986 Aux Id: PR-5412, PR-5803 </p>
+ </item>
+ <item>
+ <p><c>code:module_status/1</c> would always report BEAM
+ files loaded from an archive as <c>modified</c>, and
+ <c>code:modified_modules/0</c> would always return the
+ name of all modules loaded from archives.</p>
+ <p>
+ Own Id: OTP-17990 Aux Id: GH-5801 </p>
+ </item>
+ <item>
+ <p>
+ In logger fix file handler shutdown delay by using erlang
+ timers instead of the timer module's timers.</p>
+ <p>
+ Own Id: OTP-18001 Aux Id: GH-5780 PR-5829 </p>
+ </item>
+ <item>
+ <p>
+ Fix the meta data in log events generated by logger on
+ failure to not contain the original log event's meta
+ data.</p>
+ <p>
+ Own Id: OTP-18003 Aux Id: PR-5771 </p>
+ </item>
+ <item>
+ <p>
+ Fix logger file backend to re-create the log folder if it
+ has been deleted.</p>
+ <p>
+ Own Id: OTP-18015 Aux Id: GH-5828 PR-5845 </p>
+ </item>
+ <item>
+ <p>
+ [socket] Encode of sockaddr has been improved.</p>
+ <p>
+ Own Id: OTP-18020</p>
+ </item>
+ <item>
+ <p>
+ Fix <c>put_chars</c> requests to the io server with
+ incomplete unicode data to exit with
+ <c>no_translation</c> error.</p>
+ <p>
+ Own Id: OTP-18070 Aux Id: PR-5885 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The net module now works on Windows.</p>
+ <p>
+ Own Id: OTP-16464</p>
+ </item>
+ <item>
+ <p>
+ An Erlang installation directory is now relocatable on
+ the file system given that the paths in the
+ installation's <c>RELEASES</c> file are paths that are
+ relative to the installations root directory. The
+ <c>`release_handler:create_RELEASES/4</c> function can
+ generate a <c>RELEASES</c> file with relative paths if
+ its <c>RootDir</c> parameter is set to the empty string.</p>
+ <p>
+ Own Id: OTP-17304</p>
+ </item>
+ <item>
+ <p>The following distribution flags are now mandatory:
+ <c>DFLAG_BIT_BINARIES</c>, <c>DFLAG_EXPORT_PTR_TAG</c>,
+ <c>DFLAG_MAP_TAGS</c>, <c>DFLAG_NEW_FLOATS</c>, and
+ <c>DFLAG_FUN_TAGS</c>. This mainly concerns libraries or
+ application that implement the distribution protocol
+ themselves.</p>
+ <p>
+ Own Id: OTP-17318 Aux Id: PR-4972 </p>
+ </item>
+ <item>
+ <p>
+ Fix <c>os:cmd</c> to work on Android OS.</p>
+ <p>
+ Own Id: OTP-17479 Aux Id: PR-4917 </p>
+ </item>
+ <item>
+ <p>
+ The configuration files <seecom
+ marker="erts:erl"><c>.erlang</c></seecom>, <seeguide
+ marker="system/reference_manual:distributed"><c>.erlang.cookie</c></seeguide>
+ and <seeerl
+ marker="stdlib:beam_lib#.erlang.crypt"><c>.erlang.crypt</c></seeerl>
+ can now be located in the XDG Config Home directory.</p>
+ <p>
+ See the documentation for each file and
+ <c>filename:basedir/2</c> for more details.</p>
+ <p>
+ Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821 </p>
+ </item>
+ <item>
+ <p>
+ Dynamic node name improvements: <c>erlang:is_alive/0</c>
+ changed to return true for pending dynamic node name and
+ new function <c>net_kernel:get_state/0</c>.</p>
+ <p>
+ Own Id: OTP-17558 Aux Id: OTP-17538, PR-5111, GH-5402 </p>
+ </item>
+ <item>
+ <p>
+ The types for callback result types in <c>gen_statem</c>
+ has bee augmented with arity 2 types where it is possible
+ for a callback module to specify the type of the callback
+ data, so the callback module can get type validation of
+ it.</p>
+ <p>
+ Own Id: OTP-17589 Aux Id: PR-4926 </p>
+ </item>
+ <item>
+ <p>
+ The tagged tuple tests and fun-calls have been optimized
+ and are now a little bit cheaper than previously.</p>
+ <p>
+ These optimizations become possible after making sure
+ that all boxed terms have at least one word allocated
+ after the arity word. This has been accomplished by
+ letting all empty tuples refer to the same empty tuple
+ literal which also reduces memory usage for empty tuples.</p>
+ <p>
+ Own Id: OTP-17608</p>
+ </item>
+ <item>
+ <p>
+ A <seeapp
+ marker="kernel:kernel_app#net_ticker_spawn_options"><c>net_ticker_spawn_options</c></seeapp>
+ <c>kernel</c> configuration parameter with which one can
+ set spawn options for the distribution channel ticker
+ processes has been introduced.</p>
+ <p>
+ Own Id: OTP-17617 Aux Id: PR-5069 </p>
+ </item>
+ <item>
+ <p>
+ The most, or at least the most used, <seeerl
+ marker="kernel:rpc"><c>rpc</c></seeerl> operations now
+ require <seeerl marker="kernel:erpc"><c>erpc</c></seeerl>
+ support in order to communicate with other Erlang nodes.
+ <c>erpc</c> was introduced in OTP 23. That is, <c>rpc</c>
+ operations against Erlang nodes of releases prior to OTP
+ 23 will fail.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17681 Aux Id: PR-5307 </p>
+ </item>
+ <item>
+ <p>
+ The new module <c>peer</c> supersedes the <c>slave</c>
+ module. The <c>slave</c> module is now deprecated and
+ will be removed in OTP 27.</p>
+ <p>
+ <c>peer</c> contains an extended and more robust API for
+ starting erlang nodes.</p>
+ <p>
+ Own Id: OTP-17720 Aux Id: PR-5162 </p>
+ </item>
+ <item>
+ <p>
+ In order to make it easier for the user to manage
+ multiple outstanding asynchronous <c>call</c> requests,
+ new functionality utilizing request identifier
+ collections have been introduced in <seetype
+ marker="kernel:erpc#request_id_collection"><c>erpc</c></seetype>,
+ <seetype
+ marker="stdlib:gen_server#request_id_collection"><c>gen_server</c></seetype>,
+ <seetype
+ marker="stdlib:gen_statem#request_id_collection"><c>gen_statem</c></seetype>,
+ and <seetype
+ marker="stdlib:gen_event#request_id_collection"><c>gen_event</c></seetype>.</p>
+ <p>
+ Own Id: OTP-17784 Aux Id: PR-5792 </p>
+ </item>
+ <item>
+ <p>Type specifications have been added to the
+ <c>gen_server</c>, and the documentation has been updated
+ to utilize this. </p><p>This surfaced a few type
+ violations that has been corrected in <c>global</c>,
+ <c>logger_olp</c> and <c>rpc</c>. </p>
+ <p>
+ Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690 </p>
+ </item>
+ <item>
+ <p>
+ IP address validation functions <c>is_ipv4_address/1</c>,
+ <c>is_ipv6_address/1</c> and <c>is_ip_address/1</c> have
+ been added to the module <c>inet</c> in Kernel.</p>
+ <p>
+ Own Id: OTP-17923 Aux Id: PR-5646 </p>
+ </item>
+ <item>
+ <p>
+ An API for multihomed SCTP connect has been added in the
+ guise of <c>gen_sctp:connectx_init/*</c></p>
+ <p>
+ Own Id: OTP-17951 Aux Id: PR-5656 </p>
+ </item>
+ <item>
+ <p>
+ [socket] Add encoding of the field hatype of the type
+ sockaddr_ll (family 'packet').</p>
+ <p>
+ Own Id: OTP-17968 Aux Id: OTP-16464 </p>
+ </item>
+ <item>
+ <p>
+ Added support for configurable features as described in
+ EEP-60. Features can be enabled/disabled during
+ compilation with options (<c>-enable-feature Feature</c>,
+ <c>-disable-feature Feature</c> and <c>+{feature,
+ Feature, enable|disable}</c>) to <c>erlc</c> as well as
+ with directives (<c>-feature(Feature,
+ enable|disable).</c>) in the file. Similar options can be
+ used to <c>erl</c> for enabling/disabling features
+ allowed at runtime. The new <c>maybe</c> expression
+ (EEP-49) is fully supported as the feature
+ <c>maybe_expr</c>. The features support is documented in
+ the reference manual.</p>
+ <p>
+ Own Id: OTP-17988</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.3.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Spec for function net:if_names/0 incorrect</p>
+ <p>
+ Own Id: OTP-18296 Aux Id: OTP-16464 </p>
+ </item>
+ <item>
+ <p>
+ Missing ctrl option name transation for TOS and TTL (on
+ FreeBSD) when using gen_udp with the 'socket'
+ inet_backend.</p>
+ <p>
+ Own Id: OTP-18315</p>
+ </item>
+ <item>
+ <p>
+ The tcp connect option 'bind_to_device' could not be used
+ with inet_backend = 'socket'. 'inet' requires value type
+ binarry() and 'socket' requires value type 'string()'.</p>
+ <p>
+ Own Id: OTP-18357 Aux Id: #6509 </p>
+ </item>
+ <item>
+ <p>
+ Minor issue processing options when calling
+ gen_tcp:connect with a sockaddr() and inet_backend =
+ socket.</p>
+ <p>
+ Own Id: OTP-18358 Aux Id: #6528 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improve warning message format for gen_tcp_socket.</p>
+ <p>
+ Own Id: OTP-18317</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.3.2.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new function <seemfa
+ marker="kernel:global#disconnect/0"><c>global:disconnect/0</c></seemfa>
+ has been introduced with which one can cleanly disconnect
+ a node from all other nodes in a cluster of <c>global</c>
+ nodes.</p>
+ <p>
+ Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 8.3.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A call to <seemfa
+ marker="net_kernel#setopts/2"><c>net_kernel:setopts(new,
+ Opts)</c></seemfa> at the same time as a connection was
+ being set up could cause a deadlock between the
+ <c>net_kernel</c> process and the process setting up the
+ connection.</p>
+ <p>
+ Own Id: OTP-18198 Aux Id: GH-6129, PR-6216 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 8.3.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -826,7 +1601,7 @@
order to prevent late responses. The <c>gen_statem</c>
behavior still use a proxy process in the distributed
case, since it has always prevented late replies and
- aliases wont work against pre OTP 24 nodes. The proxy
+ aliases won't work against pre OTP 24 nodes. The proxy
process can be removed in OTP 26.</p>
<p>
The alias feature also made it possible to introduce new
@@ -1093,6 +1868,122 @@
</section>
+<section><title>Kernel 7.3.1.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new function <seemfa
+ marker="kernel:global#disconnect/0"><c>global:disconnect/0</c></seemfa>
+ has been introduced with which one can cleanly disconnect
+ a node from all other nodes in a cluster of <c>global</c>
+ nodes.</p>
+ <p>
+ Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 7.3.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A call to <seemfa
+ marker="net_kernel#setopts/2"><c>net_kernel:setopts(new,
+ Opts)</c></seemfa> at the same time as a connection was
+ being set up could cause a deadlock between the
+ <c>net_kernel</c> process and the process setting up the
+ connection.</p>
+ <p>
+ Own Id: OTP-18198 Aux Id: GH-6129, PR-6216 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 7.3.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> By default <c>global</c> does <i>not</i> take any
+ actions to restore a fully connected network when
+ connections are lost due to network issues. This is
+ problematic for all applications expecting a fully
+ connected network to be provided, such as for example
+ <c>mnesia</c>, but also for <c>global</c> itself. A
+ network of overlapping partitions might cause the
+ internal state of <c>global</c> to become inconsistent.
+ Such an inconsistency can remain even after such
+ partitions have been brought together to form a fully
+ connected network again. The effect on other applications
+ that expects that a fully connected network is maintained
+ may vary, but they might misbehave in very subtle hard to
+ detect ways during such a partitioning. </p> <p> In order
+ to prevent such issues, we have introduced a <i>prevent
+ overlapping partitions</i> fix which can be enabled using
+ the <seeapp
+ marker="kernel:kernel_app#prevent_overlapping_partitions"><c>prevent_overlapping_partitions</c></seeapp>
+ <c>kernel(6)</c> parameter. When this fix has been
+ enabled, <c>global</c> will actively disconnect from
+ nodes that reports that they have lost connections to
+ other nodes. This will cause fully connected partitions
+ to form instead of leaving the network in a state with
+ overlapping partitions. Note that this fix <i>has</i> to
+ be enabled on <i>all</i> nodes in the network in order to
+ work properly. Since this quite substantially changes the
+ behavior, this fix is currently disabled by default.
+ Since you might get hard to detect issues without this
+ fix you are, however, <i>strongly</i> advised to enable
+ this fix in order to avoid issues such as the ones
+ described above. As of OTP 25 this fix will become
+ enabled by default. </p>
+ <p>
+ Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611 </p>
+ </item>
+ <item>
+ <p>
+ Fix failed accepted connection setup after previous
+ established connection from same node closed down
+ silently.</p>
+ <p>
+ Own Id: OTP-17979 Aux Id: ERIERL-780 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A <seeapp
+ marker="kernel:kernel_app#net_tickintensity"><c>net_tickintensity</c></seeapp>
+ <c>kernel</c> parameter has been introduced. It can be
+ used to control the amount of ticks during a <seeapp
+ marker="kernel:kernel_app#net_ticktime"><c>net_ticktime</c></seeapp>
+ period.</p>
+ <p>
+ A new <seemfa
+ marker="kernel:net_kernel#start/2"><c>net_kernel:start/2</c></seemfa>
+ function has also been introduced in order to make it
+ easier to add new options. The use of <seemfa
+ marker="kernel:net_kernel#start/1"><c>net_kernel:start/1</c></seemfa>
+ has been deprecated.</p>
+ <p>
+ Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 7.3.1.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1216,7 +2107,7 @@
</item>
<item>
<p>When running Xref in the <c>modules</c> mode, the
- Debugger application would show up as a depency for the
+ Debugger application would show up as a dependency for the
Kernel applications.</p>
<p>
Own Id: OTP-17223 Aux Id: GH-4546, PR-4554 </p>
@@ -1825,6 +2716,68 @@
</section>
+<section><title>Kernel 6.5.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> By default <c>global</c> does <i>not</i> take any
+ actions to restore a fully connected network when
+ connections are lost due to network issues. This is
+ problematic for all applications expecting a fully
+ connected network to be provided, such as for example
+ <c>mnesia</c>, but also for <c>global</c> itself. A
+ network of overlapping partitions might cause the
+ internal state of <c>global</c> to become inconsistent.
+ Such an inconsistency can remain even after such
+ partitions have been brought together to form a fully
+ connected network again. The effect on other applications
+ that expects that a fully connected network is maintained
+ may vary, but they might misbehave in very subtle hard to
+ detect ways during such a partitioning. </p> <p> In order
+ to prevent such issues, we have introduced a <i>prevent
+ overlapping partitions</i> fix which can be enabled using
+ the <c>prevent_overlapping_partitions</c>
+ <c>kernel(6)</c> parameter. When this fix has been
+ enabled, <c>global</c> will actively disconnect from
+ nodes that reports that they have lost connections to
+ other nodes. This will cause fully connected partitions
+ to form instead of leaving the network in a state with
+ overlapping partitions. Note that this fix <i>has</i> to
+ be enabled on <i>all</i> nodes in the network in order to
+ work properly. Since this quite substantially changes the
+ behavior, this fix is currently disabled by default.
+ Since you might get hard to detect issues without this
+ fix you are, however, <i>strongly</i> advised to enable
+ this fix in order to avoid issues such as the ones
+ described above. As of OTP 25 this fix will become
+ enabled by default. </p>
+ <p>
+ Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A <c>net_tickintensity</c> <c>kernel</c> parameter has
+ been introduced. It can be used to control the amount of
+ ticks during a <c>net_ticktime</c> period.</p>
+ <p>
+ A new <c>net_kernel:start/2</c> function has also been
+ introduced in order to make it easier to add new options.
+ The use of <c>net_kernel:start/1</c> has been deprecated.</p>
+ <p>
+ Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 6.5.2.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1865,7 +2818,7 @@
<list>
<item>
<p>When running Xref in the <c>modules</c> mode, the
- Debugger application would show up as a depency for the
+ Debugger application would show up as a dependency for the
Kernel applications.</p>
<p>
Own Id: OTP-17223 Aux Id: GH-4546, PR-4554 </p>
@@ -2428,7 +3381,7 @@
The default value is 0, which means that this check is
done prior to each write operation. Setting a higher
number may improve performance, but adds the risk of
- loosing log events.</p>
+ losing log events.</p>
<p>
Own Id: OTP-15663</p>
</item>
@@ -4348,11 +5301,11 @@
Characteristics impact: A call to the
<c>garbage_collect/1</c> BIF or the
<c>check_process_code/2</c> BIF will normally take longer
- time to complete while the system as a whole wont be as
+ time to complete while the system as a whole won't be as
much negatively effected by the operation as before. A
call to <c>code:purge/1</c> and <c>code:soft_purge/1</c>
may complete faster or slower depending on the state of
- the system while the system as a whole wont be as much
+ the system while the system as a whole won't be as much
negatively effected by the operation as before.</p>
<p>
Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648 </p>
@@ -4713,7 +5666,7 @@
<item>
<p>
Change printout of application crash message on startup
- to formated strings (Thanks to Serge Aleynikov)</p>
+ to formatted strings (Thanks to Serge Aleynikov)</p>
<p>
Own Id: OTP-10620</p>
</item>
@@ -5495,7 +6448,7 @@
</item>
<item>
<p>
- - Add spec for function that does not return - Strenghen
+ - Add spec for function that does not return - Strengthen
spec - Introduce types to avoid duplication in specs -
Add specs for functions that do not return - Add specs
for behaviour callbacks - Simplify two specs</p>
@@ -5875,7 +6828,7 @@
app-vsn/ebin/mod.beam file, the file info for the app-vsn
and app-vsn/ebin directories are faked using the file
info from the archive file as origin. The virtual
- direcories can also be listed. For short, the top
+ directories can also be listed. For short, the top
directories are virtual if they does not exist.</p>
<p>
Own Id: OTP-8387</p>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 02f36a25ff..9ac0583d0a 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -345,7 +345,7 @@ calendar:now_to_universal_time(TS),
<pre>
1> <input>io:format("~s~n",[print_time:format_utc_timestamp()]).</input>
29 Apr 2009 9:55:30.051711</pre>
- <p>OS system time can also be retreived by
+ <p>OS system time can also be retrieved by
<seemfa marker="#system_time/0"><c>system_time/0</c></seemfa> and
<seemfa marker="#system_time/1"><c>system_time/1</c></seemfa>.</p>
</desc>
diff --git a/lib/kernel/doc/src/pg.xml b/lib/kernel/doc/src/pg.xml
index 9b6d20f818..33562c828c 100644
--- a/lib/kernel/doc/src/pg.xml
+++ b/lib/kernel/doc/src/pg.xml
@@ -6,7 +6,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2020</year>
+ <year>2020</year><year>2022</year>
<holder>Maxim Fedorov, WhatsApp Inc.</holder>
</copyright>
<legalnotice>
@@ -89,8 +89,15 @@
If there is another process registered under this name, or another ETS table
exists, scope fails to start.</p>
<p>Local membership is not preserved if scope process exits and
- restarts.
- </p></note>
+ restarts.</p>
+ <p>A scope can be kept local-only by using a scope name that is unique
+ cluster-wide, e.g. the node name:</p>
+ <taglist>
+ <!-- NOTE THAT THE EMPTY TAG IS INTENTIONAL -->
+ <tag></tag>
+ <item><c>pg:start_link(node()).</c></item>
+ </taglist>
+ </note>
</description>
@@ -150,6 +157,46 @@
</func>
<func>
+ <name name="monitor_scope" arity="0" since="OTP 25.1"/>
+ <name name="monitor_scope" arity="1" since="OTP 25.1"/>
+ <fsummary>Starts group membership monitoring for a scope.</fsummary>
+ <desc>
+ <p>Subscribes the caller to updates from the specified scope. Returns
+ content of the entire scope and a reference to match the upcoming
+ notifications.</p>
+
+ <p>Whenever any group membership changes, an update message is sent
+ to the subscriber:</p>
+ <code type="none">{Ref, join, Group, [JoinPid1, JoinPid2]}</code>
+ <code type="none">{Ref, leave, Group, [LeavePid1]}</code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="monitor" arity="1" since="OTP 25.1"/>
+ <name name="monitor" arity="2" since="OTP 25.1"/>
+ <fsummary>Starts membership monitoring for a specified group.</fsummary>
+ <desc>
+ <p>Subscribes the caller to updates for the specified group. Returns
+ list of processes currently in the group, and a reference to match
+ the upcoming notifications.</p>
+ <p>See <seemfa marker="#monitor_scope/0"><c>monitor_scope/0</c></seemfa>
+ for the update message structure.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="demonitor" arity="1" since="OTP 25.1"/>
+ <name name="demonitor" arity="2" since="OTP 25.1"/>
+ <fsummary>Stops group membership monitoring.</fsummary>
+ <desc>
+ <p>Unsubscribes the caller from updates (scope or group).
+ Flushes all outstanding updates that were already in the message
+ queue of the calling process.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="get_local_members" arity="1" since="OTP 23.0"/>
<name name="get_local_members" arity="2" since="OTP 23.0"/>
<fsummary>Return all local processes in a group.</fsummary>
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index a3e96e99f4..6b471d0d42 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,14 +43,14 @@
This cannot be changed due to compatibility reasons. As of OTP 23,
a new module <seeerl marker="erpc"><c>erpc</c></seeerl> was
introduced in order to provide an API that makes it possible
- to distingush between the different results. The <c>erpc</c>
+ to distinguish between the different results. The <c>erpc</c>
module provides a subset (however, the central subset) of the
functionality available in the <c>rpc</c> module. The <c>erpc</c>
implementation also provides a more scalable implementation with
better performance than the original <c>rpc</c> implementation.
However, since the introduction of <c>erpc</c>, the <c>rpc</c>
module implements large parts of its central functionality using
- <c>erpc</c>, so the <c>rpc</c> module wont not suffer scalability
+ <c>erpc</c>, so the <c>rpc</c> module won't not suffer scalability
wise and performance wise compared to <c>erpc</c>.
</p></note>
</description>
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index b20a1f2f9d..4f3349af6b 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2020</year>
+ <year>1998</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -90,7 +90,7 @@ seq_trace:set_token(OldToken), % activate the trace token again
the separate traces. Default is 0.</p>
<warning>
<p>Labels were restricted to small signed integers (28 bits)
- prior to OTP 21. The trace token will be silenty dropped if it
+ prior to OTP 21. The trace token will be silently dropped if it
crosses over to a node that does not support the label.</p>
</warning>
</item>
diff --git a/lib/kernel/doc/src/socket.xml b/lib/kernel/doc/src/socket.xml
index 541f4aaba4..753517bee4 100644
--- a/lib/kernel/doc/src/socket.xml
+++ b/lib/kernel/doc/src/socket.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2018</year><year>2021</year>
+ <year>2018</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -292,6 +292,10 @@
<desc></desc>
</datatype>
<datatype>
+ <name name="sockaddr_dl"/>
+ <desc></desc>
+ </datatype>
+ <datatype>
<name name="sockaddr_unspec"/>
<desc></desc>
</datatype>
@@ -304,6 +308,10 @@
<desc></desc>
</datatype>
<datatype>
+ <name name="hatype"/>
+ <desc></desc>
+ </datatype>
+ <datatype>
<name name="port_number"/>
<desc></desc>
</datatype>
@@ -1314,7 +1322,7 @@
A control message has got a <c>data</c> field with
a native (<c>binary</c>) value for the message data,
and may also have a decoded <c>value</c> field
- if this socket library succesfully decoded the data.
+ if this socket library successfully decoded the data.
</p>
</desc>
</datatype>
@@ -1543,7 +1551,7 @@
<note>
<p>
Note that when this call has returned
- <c>{error, timeout</c> the connection state of the socket
+ <c>{error, timeout}</c> the connection state of the socket
is uncertain since the platform's network stack
may complete the connection at any time,
up to some platform specific time-out.
@@ -1629,7 +1637,7 @@
<seetype marker="#select_info"><c>{select, SelectInfo}</c></seetype>,
and receiving the select message
<c>{'$socket', Socket, select, SelectHandle}</c>,
- and returns whether the connection setup was succesful or not.
+ and returns whether the connection setup was successful or not.
</p>
<p>
Instead of calling this function, for backwards compatibility,
@@ -1704,7 +1712,7 @@
<seetype marker="#socket_option">socket_option()</seetype>
for which options that this implementation knows about,
how they are related to option names in the OS,
- and if there are known pecularities with any of them.
+ and if there are known peculiarities with any of them.
</p>
<p>
What options are valid depends on what kind of socket it is
@@ -1966,7 +1974,7 @@
<fsummary>Control device.</fsummary>
<desc>
<p>Retrieve socket (device) parameters.
- This function retreives a specific parameter,
+ This function retrieves a specific parameter,
according to <c>GetRequest</c> argument. The third
argument is the (lookup) "key", identifying the
interface (usually the name of the interface).</p>
@@ -2119,7 +2127,7 @@
<fsummary>Report info about what the platform supports.</fsummary>
<desc>
<p>
- This function retreives information about what the
+ This function retrieves information about what the
platform supports, such as if SCTP is supported,
or if a socket options are supported.
</p>
@@ -2274,7 +2282,7 @@
<p>
On some platforms it is <em>necessary</em> to provide
<c>domain</c>, <c>type</c> and <c>protocol</c>
- since they cannot be retreived from the platform.
+ since they cannot be retrieved from the platform.
</p>
</note>
</desc>
@@ -2839,7 +2847,7 @@
<p>
This cannot happen for a socket of
<seetype marker="#type">type <c>stream</c></seetype>
- where a partially succesful send is retried until
+ where a partially successful send is retried until
the data is either accepted or there is an error.
</p>
<p>
@@ -2882,8 +2890,8 @@
<p>
This can only happen for a socket of
<seetype marker="#type">type <c>stream</c></seetype>
- when a partially succesful send is retried
- untill there is an error.
+ when a partially successful send is retried
+ until there is an error.
</p>
</item>
</taglist>
@@ -3431,7 +3439,7 @@
<tag><c>{ok,&nbsp;<anno>BytesSent</anno>}</c></tag>
<item>
<p>
- The transfer completed succesfully after
+ The transfer completed successfully after
<c><anno>BytesSent</anno></c> bytes of data.
</p>
</item>
@@ -3726,7 +3734,7 @@
<seetype marker="#socket_option">socket_option()</seetype>
for which options that this implementation knows about,
how they are related to option names in the OS,
- and if there are known pecularities with any of them.
+ and if there are known peculiarities with any of them.
</p>
<p>
What options are valid depends on what kind of socket it is
@@ -3856,7 +3864,7 @@
<fsummary>Report info about what the platform supports.</fsummary>
<desc>
<p>
- These functions function retreives information about what the
+ These functions function retrieves information about what the
platform supports, such which platform features
or which socket options, are supported.
</p>
@@ -4015,7 +4023,7 @@
<p>The general filter rule.
<br/>A fun that takes the socket info and returns a
<c><![CDATA[boolean()]]></c>
- (<c><![CDATA[true]]></c> if the socket sould be included and
+ (<c><![CDATA[true]]></c> if the socket could be included and
<c><![CDATA[false]]></c> if should not). </p>
</item>
</taglist>
diff --git a/lib/kernel/doc/src/socket_usage.xml b/lib/kernel/doc/src/socket_usage.xml
index c549ea0e19..39d9ded99e 100644
--- a/lib/kernel/doc/src/socket_usage.xml
+++ b/lib/kernel/doc/src/socket_usage.xml
@@ -34,7 +34,7 @@
<title>Introduction</title>
<p>The socket interface (module) is basically a "thin" layer on top of
the OS socket interface. It is assumed that, unless you have special needs,
- gen_[tcp|udp|sctp] should be sufficent (when they become available). </p>
+ gen_[tcp|udp|sctp] should be sufficient (when they become available). </p>
<p>Note that just because we have a documented and described option,
it does <em>not</em> mean that the OS supports it. So its recommended
that the user reads the platform specific documentation for the
@@ -352,7 +352,7 @@
Since our implementation is <em>nonblocking</em>,
its unknown if and how this option works, or even if
it may cause malfunctions.
- Therefor, we do not recommend setting this option.
+ Therefore, we do not recommend setting this option.
Instead, use the <c>Timeout</c> argument to, for instance,
the
<seemfa marker="socket#recv/3"><c>recv/3</c></seemfa>
@@ -400,7 +400,7 @@
Since our implementation is <em>nonblocking</em>,
its unknown if and how this option works, or even if
it may cause malfunctions.
- Therefor, we do not recommend setting this option.
+ Therefore, we do not recommend setting this option.
Instead, use the <c>Timeout</c> argument to, for instance,
the
<seemfa marker="socket#send/3"><c>send/3</c></seemfa>
diff --git a/lib/kernel/examples/Makefile b/lib/kernel/examples/Makefile
index 21f3f26cf7..2356bbf602 100644
--- a/lib/kernel/examples/Makefile
+++ b/lib/kernel/examples/Makefile
@@ -29,7 +29,7 @@ include ../vsn.mk
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/kernel/examples/erl_uds_dist/src/erl_uds_dist.erl b/lib/kernel/examples/erl_uds_dist/src/erl_uds_dist.erl
index c69947184f..d6310bdd19 100644
--- a/lib/kernel/examples/erl_uds_dist/src/erl_uds_dist.erl
+++ b/lib/kernel/examples/erl_uds_dist/src/erl_uds_dist.erl
@@ -25,7 +25,7 @@
%% This is an example of how to plug in an alternative distribution
%% protocol using distribution controller processes. Erlang
%% distribution can use whatever underlying protocols as long as the
-%% implementation reliably delivers data chuncks to the receiving
+%% implementation reliably delivers data chunks to the receiving
%% Erlang node in the order they were sent by the sending node.
%%
%% This example uses stream-oriented Unix Domain Sockets (of the
@@ -74,7 +74,7 @@
%% If tracing is wanted, uncomment the dist_trace macro in dist_util.hrl
%% to enable all the calls to trace below, or copy the trace macro here.
%%
-%% Tracing will freeze the initial boot when a -name or -sname paramater
+%% Tracing will freeze the initial boot when a -name or -sname parameter
%% is passed to start directly distributed nodes. To make it work,
%% launch non-distributed nodes first (without -name and -sname) then
%% call net_kernel:start/1 to enable the distribution in a second stage.
@@ -417,7 +417,7 @@ accept_loop(Kernel, ListeningSocket) ->
%% The caller of accept_supervisor is a representative for net_kernel and
%% is identified as Kernel below.
%%
-%% AcceptPid is the process identifer created by accept/1.
+%% AcceptPid is the process identifier created by accept/1.
%%
%% DistCtrl is the identifier of the distribution controller process in
%% charge of the connection, as created by the accept_loop process above.
@@ -432,8 +432,7 @@ accept_loop(Kernel, ListeningSocket) ->
accept_connection(AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
spawn_opt(?MODULE, accept_supervisor,
[self(), AcceptPid, DistCtrl, MyNode, Allowed, SetupTime],
- %% Spawn on max priority
- [link, {priority, max}]).
+ dist_util:net_ticker_spawn_options()).
accept_supervisor(Kernel, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
?trace("~p~n", [{?MODULE, accept_connection, self()}]),
@@ -473,7 +472,6 @@ accept_supervisor(Kernel, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
dist_util:handshake_other_started(HSData)
end.
-
%% ---------------------------------------------------------------------
%% Define common values of the handshake data record, defined in
%% kernel/include/dist_util.hrl
@@ -666,8 +664,7 @@ getopts(ListeningSocket, Options) ->
setup(Node, Type, MyNode, _LongOrShortNames, SetupTime) ->
spawn_opt(?MODULE, setup_supervisor,
[self(), Node, Type, MyNode, SetupTime],
- %% Spawn on max priority
- [link, {priority, max}]).
+ dist_util:net_ticker_spawn_options()).
setup_supervisor(Kernel, Node, Type, MyNode, SetupTime) ->
?trace("~p~n", [{?MODULE, setup, self(), Node}]),
diff --git a/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl b/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl
index f4eb12818d..b00de7a55e 100644
--- a/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl
+++ b/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,8 @@
%%
-export([listen/1, accept/1, accept_connection/5,
- setup/5, close/1, select/1, is_node_name/1]).
+ setup/5, close/1, select/1, is_node_name/1,
+ address/0]).
%% Optional
-export([setopts/2, getopts/2]).
@@ -73,6 +74,12 @@ select(Node) ->
end.
%% ------------------------------------------------------------
+%% Get the address family that this distribution uses
+%% ------------------------------------------------------------
+address() ->
+ get_tcp_address().
+
+%% ------------------------------------------------------------
%% Create the listen socket, i.e. the port that this erlang
%% node is accessible through.
%% ------------------------------------------------------------
@@ -183,7 +190,7 @@ flush_controller(Pid, Socket) ->
accept_connection(AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
spawn_opt(?MODULE, do_accept,
[self(), AcceptPid, DistCtrl, MyNode, Allowed, SetupTime],
- [link, {priority, max}]).
+ dist_util:net_ticker_spawn_options()).
do_accept(Kernel, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) ->
?trace("~p~n",[{?MODULE, do_accept, self(), MyNode}]),
@@ -230,7 +237,7 @@ nodelay() ->
setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
spawn_opt(?MODULE, do_setup,
[self(), Node, Type, MyNode, LongOrShortNames, SetupTime],
- [link, {priority, max}]).
+ dist_util:net_ticker_spawn_options()).
do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
?trace("~p~n",[{?MODULE, do_setup, self(), Node}]),
@@ -344,9 +351,12 @@ split_node([], _, Ack) -> [lists:reverse(Ack)].
%% ------------------------------------------------------------
get_tcp_address(Socket) ->
{ok, Address} = inet:sockname(Socket),
+ NetAddr = get_tcp_address(),
+ NetAddr#net_address{address = Address}.
+
+get_tcp_address() ->
{ok, Host} = inet:gethostname(),
#net_address {
- address = Address,
host = Host,
protocol = tcp,
family = inet
@@ -444,7 +454,7 @@ hs_data_common(DistCtrl) ->
%% the connection down if no incoming traffic is seen.
%% This process also executes on max priority.
%%
-%% These parties are linked togheter so should one
+%% These parties are linked together so should one
%% of them fail, all of them are terminated and the
%% connection is taken down.
%%
@@ -569,7 +579,7 @@ call_ctrlr(Ctrlr, Msg) ->
%% non-blocking send operation exposed in its API
%% and we don't want to run the distribution
%% controller under high priority. Therefore this
-%% sparate process with max prio that dispatches
+%% separate process with max prio that dispatches
%% ticks.
%%
dist_cntrlr_tick_handler(Socket) ->
@@ -700,7 +710,7 @@ dist_cntrlr_setup_loop(Socket, TickHandler, Sup) ->
dist_cntrlr_input_setup(DHandle, Socket, Sup) ->
link(Sup),
- %% Ensure we don't try to put data before registerd
+ %% Ensure we don't try to put data before we are registered
%% as input handler...
receive
DHandle ->
@@ -775,7 +785,7 @@ death_row() ->
death_row(normal) ->
%% We do not want to exit with normal
- %% exit reason since it wont bring down
+ %% exit reason since it won't bring down
%% linked processes...
death_row();
death_row(Reason) ->
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 8c028ba910..6110ce6a72 100644
--- a/lib/kernel/examples/uds_dist/c_src/uds_drv.c
+++ b/lib/kernel/examples/uds_dist/c_src/uds_drv.c
@@ -1039,7 +1039,7 @@ static int try_lock(char *sockname, Byte *p_creation)
}
lseek(lockfd, 0, SEEK_SET);
write(lockfd, &creation, 1);
- fsync(lockfd); /* This could be concidered dangerous (blocking) */
+ fsync(lockfd); /* This could be considered dangerous (blocking) */
*p_creation = creation;
return lockfd;
}
diff --git a/lib/kernel/examples/uds_dist/src/uds_server.erl b/lib/kernel/examples/uds_dist/src/uds_server.erl
index c060130f9d..76eb869c5e 100644
--- a/lib/kernel/examples/uds_dist/src/uds_server.erl
+++ b/lib/kernel/examples/uds_dist/src/uds_server.erl
@@ -113,7 +113,7 @@ load_driver() ->
find_priv_lib() ->
PrivDir = case (catch code:priv_dir(uds_dist)) of
{'EXIT', _} ->
- %% Code server probably not startet yet
+ %% Code server probably not started yet
{ok, P} = erl_prim_loader:get_path(),
ModuleFile = atom_to_list(?MODULE) ++ extension(),
Pd = (catch lists:foldl
diff --git a/lib/kernel/include/dist.hrl b/lib/kernel/include/dist.hrl
index 10460ba3e8..16320b64e9 100644
--- a/lib/kernel/include/dist.hrl
+++ b/lib/kernel/include/dist.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,43 +22,90 @@
%% Distribution capabilities flags (corresponds with dist.h).
%%
--define(DFLAG_PUBLISHED,1).
--define(DFLAG_ATOM_CACHE,2).
--define(DFLAG_EXTENDED_REFERENCES,4).
--define(DFLAG_DIST_MONITOR,8).
--define(DFLAG_FUN_TAGS,16#10).
--define(DFLAG_DIST_MONITOR_NAME,16#20).
--define(DFLAG_HIDDEN_ATOM_CACHE,16#40).
--define(DFLAG_NEW_FUN_TAGS,16#80).
--define(DFLAG_EXTENDED_PIDS_PORTS,16#100).
--define(DFLAG_EXPORT_PTR_TAG,16#200).
--define(DFLAG_BIT_BINARIES,16#400).
--define(DFLAG_NEW_FLOATS,16#800).
--define(DFLAG_UNICODE_IO,16#1000).
--define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000).
--define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
--define(DFLAG_UTF8_ATOMS, 16#10000).
--define(DFLAG_MAP_TAG, 16#20000).
--define(DFLAG_BIG_CREATION, 16#40000).
--define(DFLAG_SEND_SENDER, 16#80000).
--define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000).
-%% -define(DFLAG_NO_MAGIC, 16#200000). %% Used internally only
--define(DFLAG_EXIT_PAYLOAD, 16#400000).
--define(DFLAG_FRAGMENTS, 16#00800000).
--define(DFLAG_HANDSHAKE_23, 16#01000000).
--define(DFLAG_RESERVED, 16#fe000000).
--define(DFLAG_SPAWN, 16#100000000).
--define(DFLAG_NAME_ME, 16#200000000).
--define(DFLAG_V4_NC, 16#400000000).
--define(DFLAG_ALIAS, 16#800000000).
+-define(DFLAG_PUBLISHED, 16#01).
+-define(DFLAG_ATOM_CACHE, 16#02).
+-define(DFLAG_EXTENDED_REFERENCES, 16#04).
+-define(DFLAG_DIST_MONITOR, 16#08).
+-define(DFLAG_FUN_TAGS, 16#10).
+-define(DFLAG_DIST_MONITOR_NAME, 16#20).
+-define(DFLAG_HIDDEN_ATOM_CACHE, 16#40).
+-define(DFLAG_NEW_FUN_TAGS, 16#80).
+-define(DFLAG_EXTENDED_PIDS_PORTS, 16#100).
+-define(DFLAG_EXPORT_PTR_TAG, 16#200).
+-define(DFLAG_BIT_BINARIES, 16#400).
+-define(DFLAG_NEW_FLOATS, 16#800).
+-define(DFLAG_UNICODE_IO, 16#1000).
+-define(DFLAG_DIST_HDR_ATOM_CACHE, 16#2000).
+-define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
+-define(DFLAG_UTF8_ATOMS, 16#10000).
+-define(DFLAG_MAP_TAG, 16#20000).
+-define(DFLAG_BIG_CREATION, 16#40000).
+-define(DFLAG_SEND_SENDER, 16#80000).
+-define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000).
+%% -define(DFLAG_NO_MAGIC, 16#200000). %% Used internally only
+-define(DFLAG_EXIT_PAYLOAD, 16#400000).
+-define(DFLAG_FRAGMENTS, 16#00800000).
+-define(DFLAG_HANDSHAKE_23, 16#01000000).
+-define(DFLAG_UNLINK_ID, 16#02000000).
+-define(DFLAG_MANDATORY_25_DIGEST, 16#04000000).
+-define(DFLAG_RESERVED, 16#f8000000).
+
+%% Second 32-bit flag word.
+-define(DFLAG_SPAWN, (16#01 bsl 32)).
+-define(DFLAG_NAME_ME, (16#02 bsl 32)).
+-define(DFLAG_V4_NC, (16#04 bsl 32)).
+-define(DFLAG_ALIAS, (16#08 bsl 32)).
+
+%% The following flags are mandatory in OTP 25. OTP 25 and higher
+%% will accept ?DFLAG_MANDATORY_25_DIGEST as a shorthand for all those
+%% flags.
+-define(MANDATORY_DFLAGS_25,
+ (?DFLAG_EXTENDED_REFERENCES bor
+ ?DFLAG_FUN_TAGS bor
+ ?DFLAG_EXTENDED_PIDS_PORTS bor
+ ?DFLAG_NEW_FUN_TAGS bor
+ ?DFLAG_EXPORT_PTR_TAG bor
+ ?DFLAG_BIT_BINARIES bor
+ ?DFLAG_NEW_FLOATS bor
+ ?DFLAG_UTF8_ATOMS bor
+ ?DFLAG_MAP_TAG bor
+ ?DFLAG_BIG_CREATION bor
+ ?DFLAG_HANDSHAKE_23)).
%% Also update dflag2str() in ../src/dist_util.erl
%% when adding flags...
+-define(ERL_DIST_VER_6, 6). % OTP-23 at least
--define(ERL_DIST_VER_5, 5). % OTP-22 or (much) older
--define(ERL_DIST_VER_6, 6). % OTP-23 (or maybe newer?)
-
--define(ERL_DIST_VER_LOW, ?ERL_DIST_VER_5).
+-define(ERL_DIST_VER_LOW, ?ERL_DIST_VER_6).
-define(ERL_DIST_VER_HIGH, ?ERL_DIST_VER_6).
+%%%
+%%% To avoid having to extend the number of distribution flags from 64
+%%% to 128, a scheme for garbage collection of the flags was
+%%% introduced in OTP 25.
+%%%
+%%% In OTP 25, ?DFLAG_MANDATORY_25_DIGEST was introduced as a synonym
+%%% for the flags defined by ?MANDATORY_DFLAGS_25. OTP 25/26 will
+%%% accept the old flags to support communication with 24 and earlier,
+%%% as well as ?DFLAG_MANDATORY_25_DIGEST.
+%%%
+%%% OTP 27 will make ?DFLAG_MANDATORY_25_DIGEST mandatory, meaning that an
+%%% OTP 27 node can only communicate with OTP 25 and higher.
+%%%
+%%% An OTP 27 node will also introduce the new flag
+%%% ?DFLAG_MANDATORY_27_DIGEST:
+%%%
+%%% * If ?DFLAG_MANDATORY_27_DIGEST is set, it means that all bit
+%%% numbers defined by ?MANDATORY_DFLAGS_25, as well as the bit
+%%% number defined by ?DFLAG_MANDATORY_25_DIGEST and any other bits
+%%% made mandatory in OTP 26/27, lose their previous meanings. New
+%%% meanings can then be assigned to those bit numbers as
+%%% needed. (This is for communication between nodes from OTP 27 and
+%%% up.)
+%%%
+%%% * If ?DFLAG_MANDATORY_27_DIGEST is not set, then
+%%% ?DFLAG_MANDATORY_25_DIGEST must be set and all bit numbers
+%%% defined by ?MANDATORY_DFLAGS_25 are ignored. (This is for
+%%% communication between an OTP 27 node and an OTP 25/26 node.)
+%%%
diff --git a/lib/kernel/include/inet_sctp.hrl b/lib/kernel/include/inet_sctp.hrl
index ddb3cdc26c..11b06fd8e6 100644
--- a/lib/kernel/include/inet_sctp.hrl
+++ b/lib/kernel/include/inet_sctp.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -120,7 +120,7 @@
}).
%% sctp_partial_delivery_event: XXX: Not clear whether it is delivered to
-%% the Sender or to the Recepient (probably the
+%% the Sender or to the Recipient (probably the
%% former). Currently, there is only 1 possible
%% value for "indication":
-record(sctp_pdapi_event,
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index b2299188eb..2149e89776 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -188,7 +188,7 @@ ERL_COMPILE_FLAGS += -I../include
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
# Note: In the open-source build clean must not destroyed the preloaded
# beam files.
diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index bf7843b92b..1f428c560b 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -509,7 +509,7 @@ init(Init, Kernel) ->
{ok, ConfData} ->
%% Actually, we don't need this info in an ets table anymore.
%% This table was introduced because starting applications
- %% should be able to get som info from AC (e.g. loaded_apps).
+ %% should be able to get some info from AC (e.g. loaded_apps).
%% The new implementation makes sure the AC process can be
%% called during start-up of any app.
case check_conf_data(ConfData) of
@@ -670,7 +670,7 @@ handle_call({start_application, AppName, RestartType}, From, S) ->
#state{running = Running, starting = Starting, start_p_false = SPF,
started = Started, start_req = Start_req} = S,
%% Check if the commandline environment variables are OK.
- %% Incase of erroneous variables do not start the application,
+ %% In case of erroneous variables do not start the application,
%% if the application is permanent crash the node.
%% Check if the application is already starting.
case lists:keyfind(AppName, 1, Start_req) of
@@ -1731,7 +1731,7 @@ check_user() ->
%%-----------------------------------------------------------------
-%% Prepare for a release upgrade by reading all the evironment variables.
+%% Prepare for a release upgrade by reading all the environment variables.
%%-----------------------------------------------------------------
do_prep_config_change(Apps) ->
do_prep_config_change(Apps, []).
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index f61ceb9461..8f2fc99647 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@
-type cookie() :: atom().
-record(state, {
our_cookie :: cookie(), %% Our own cookie
- other_cookies :: ets:tab() %% The send-cookies of other nodes
+ other_cookies :: ets:table()%% The send-cookies of other nodes
}).
-type state() :: #state{}.
@@ -375,26 +375,64 @@ init_setcookie([], OurCookies, OtherCookies) ->
ets_new_cookies() ->
ets:new(cookies, [?COOKIE_ETS_PROTECTION]).
+%% Read cookie from:
+%% 1. $HOME/.erlang.cookie
+%% 2. $XDG_CONFIG_HOME/erlang/.erlang.cookie
+%%
+%% If neither are present, we generate $HOME/.erlang.cookie
read_cookie() ->
+ XDGPath = filename:join(
+ filename:basedir(user_config, "erlang"),
+ ".erlang.cookie"),
case init:get_argument(home) of
{ok, [[Home]]} ->
- read_cookie(filename:join(Home, ".erlang.cookie"));
+ HomePath = filename:join(Home, ".erlang.cookie"),
+ case read_cookie(HomePath) of
+ {error, enoent} ->
+ case read_cookie(XDGPath) of
+ {error, enoent} ->
+ case create_cookie(HomePath) of
+ ok ->
+ {ok, Cookie} = read_cookie(HomePath),
+ Cookie;
+ Error -> Error
+ end;
+ {ok, Cookie} ->
+ Cookie;
+ Error ->
+ Error
+ end;
+ {ok, Cookie} ->
+ Cookie;
+ Error ->
+ Error
+ end;
_ ->
- {error, "No home for cookie file"}
+ %% Failed to read find home, try xdg path
+ case read_cookie(XDGPath) of
+ {error, enoent} ->
+ case create_cookie(XDGPath) of
+ ok ->
+ {ok, Cookie} = read_cookie(XDGPath),
+ Cookie;
+ Error -> Error
+ end;
+ {ok, Cookie} ->
+ Cookie;
+ _Error ->
+ {error, "No home for cookie file"}
+ end
end.
read_cookie(Name) ->
case file:raw_read_file_info(Name) of
{ok, #file_info {type=Type, mode=Mode, size=Size}} ->
case check_attributes(Name, Type, Mode, os:type()) of
- ok -> read_cookie(Name, Size);
- Error -> Error
- end;
- {error, enoent} ->
- case create_cookie(Name) of
- ok -> read_cookie(Name);
+ ok -> {ok, read_cookie(Name, Size)};
Error -> Error
end;
+ {error, enoent} ->
+ {error, enoent};
{error, Reason} ->
{error, make_error(Name, Reason)}
end.
@@ -454,24 +492,24 @@ create_cookie(Name) ->
bxor erlang:unique_integer()),
Cookie = random_cookie(20, Seed, []),
case file:open(Name, [write, raw]) of
- {ok, File} ->
- R1 = file:write(File, Cookie),
- ok = file:close(File),
- R2 = file:raw_write_file_info(Name, make_info(Name)),
- case {R1, R2} of
- {ok, ok} ->
- ok;
- {{error,Reason}, _} ->
- {error,
- lists:flatten(
- io_lib:format("Failed to write to cookie file '~ts': ~p", [Name, Reason]))};
- {ok, {error, Reason}} ->
- {error, "Failed to change mode: " ++ atom_to_list(Reason)}
- end;
- {error,Reason} ->
- {error,
- lists:flatten(
- io_lib:format("Failed to create cookie file '~ts': ~p", [Name, Reason]))}
+ {ok, File} ->
+ R1 = file:write(File, Cookie),
+ ok = file:close(File),
+ R2 = file:raw_write_file_info(Name, make_info(Name)),
+ case {R1, R2} of
+ {ok, ok} ->
+ ok;
+ {{error,Reason}, _} ->
+ {error,
+ lists:flatten(
+ io_lib:format("Failed to write to cookie file '~ts': ~p", [Name, Reason]))};
+ {ok, {error, Reason}} ->
+ {error, "Failed to change mode: " ++ atom_to_list(Reason)}
+ end;
+ {error,Reason} ->
+ {error,
+ lists:flatten(
+ io_lib:format("Failed to create cookie file '~ts': ~p", [Name, Reason]))}
end.
random_cookie(0, _, Result) ->
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index 71a570fa7b..001f3ac981 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -739,7 +739,8 @@ do_start() ->
load_code_server_prerequisites() ->
%% Please keep the alphabetical order.
- Needed = [binary,
+ Needed = [beam_lib,
+ binary,
ets,
filename,
gb_sets,
@@ -748,6 +749,7 @@ load_code_server_prerequisites() ->
os,
unicode],
_ = [M = M:module_info(module) || M <- Needed],
+ _ = erl_features:enabled(),
ok.
maybe_stick_dirs(interactive) ->
@@ -1048,20 +1050,20 @@ module_status(Module) ->
%% Note that we don't want to go via which/1, since it doesn't look at the
%% disk contents at all if the module is already loaded.
module_status(Module, PathFiles) ->
- case code:is_loaded(Module) of
+ case is_loaded(Module) of
false -> not_loaded;
{file, preloaded} -> loaded;
{file, cover_compiled} ->
- %% cover compilation loads directly to memory and does not
- %% create a beam file, so report 'modified' if a file exists
+ %% Cover compilation loads directly to memory and does not
+ %% create a beam file, so report 'modified' if a file exists.
case which(Module, PathFiles) of
non_existing -> removed;
_File -> modified
end;
{file, []} -> loaded; % no beam file - generated code
- {file, OldFile} when is_list(OldFile) ->
- %% we don't care whether or not the file is in the same location
- %% as when last loaded, as long as it can be found in the path
+ {file, [_|_]} ->
+ %% We don't care whether or not the file is in the same location
+ %% as when last loaded, as long as it can be found in the path.
case which(Module, PathFiles) of
non_existing -> removed;
Path ->
@@ -1076,10 +1078,24 @@ module_status(Module, PathFiles) ->
%% be reloaded; does not care about file timestamps or compilation time
module_changed_on_disk(Module, Path) ->
MD5 = erlang:get_module_info(Module, md5),
- MD5 =/= beam_file_md5(Path).
+ MD5 =/= beam_file_md5(Module, Path).
+
+beam_file_md5(Module, Path) ->
+ case do_beam_file_md5(Path) of
+ MD5 when is_binary(MD5) ->
+ MD5;
+ undefined ->
+ %% This module is probably embedded in an archive.
+ case get_object_code(Module) of
+ {Module, Code, _Path} ->
+ do_beam_file_md5(Code);
+ error ->
+ undefined
+ end
+ end.
-beam_file_md5(Path) ->
- case beam_lib:md5(Path) of
+do_beam_file_md5(PathOrCode) ->
+ case beam_lib:md5(PathOrCode) of
{ok,{_Mod,MD5}} -> MD5;
_ -> undefined
end.
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 3ab50cafe0..af8531271f 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,8 +42,8 @@
-record(state, {supervisor :: pid(),
root :: file:name_all(),
path :: [file:name_all()],
- moddb :: ets:tab(),
- namedb :: ets:tab(),
+ moddb :: ets:table(),
+ namedb :: ets:table(),
mode = interactive :: 'interactive' | 'embedded',
on_load = [] :: [on_load_item()]}).
-type state() :: #state{}.
@@ -1334,7 +1334,7 @@ handle_pending_on_load(Action, Mod, From, #state{on_load=OnLoad0}=St) ->
%% call to its own module. That would be a deadlock.
%% Fail the call. (The call is probably from error_handler,
%% and it will ignore the actual error reason and cause
- %% an undef execption.)
+ %% an undef exception.)
{reply,{error,deadlock},St};
{_,_,_} ->
OnLoad = handle_pending_on_load_1(Mod, {From,Action}, OnLoad0),
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index a420a133d0..19225c9be5 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -368,7 +368,7 @@ pid2name(Pid) ->
end.
%% This function Takes 3 args, a Log, a Continuation and N.
-%% It retuns a {Cont2, ObjList} | eof | {error, Reason}
+%% It returns a {Cont2, ObjList} | eof | {error, Reason}
%% The initial continuation is the atom 'start'
-type chunk_error_rsn() :: no_such_log
@@ -1151,7 +1151,7 @@ system_terminate(Reason, _Parent, _, State) ->
exit(Reason).
%%-----------------------------------------------------------------
-%% Temporay code for upgrade.
+%% Temporary code for upgrade.
%%-----------------------------------------------------------------
system_code_change(State, _Module, _OldVsn, _Extra) ->
{ok, State}.
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 1e773e4730..6cb2c13f02 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -143,7 +143,7 @@
%% since log was opened if info/1
%% has not yet been used on this log.
accFull :: non_neg_integer()} %% noFull+accFull is number of
- %% oveflows since the log was opened.
+ %% overflows since the log was opened.
).
-record(log,
diff --git a/lib/kernel/src/dist_ac.erl b/lib/kernel/src/dist_ac.erl
index 2a5cf0ba92..32f9cc461f 100644
--- a/lib/kernel/src/dist_ac.erl
+++ b/lib/kernel/src/dist_ac.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@
-define(DIST_AC, ?MODULE).
-define(LOCK_ID, ?MODULE).
-%% This is the protocol version for the dist_ac protcol (between nodes)
+%% This is the protocol version for the dist_ac protocol (between nodes)
-define(vsn, 1).
%%%-----------------------------------------------------------------
@@ -862,8 +862,8 @@ wait_dist_start(Node, Appl, Name, Nodes, PermittedNodes, S, Type) ->
{dist_ac_weight, Name, _Weigth, Node} ->
%% This is the situation: {Name, [RNode, {Node}, node()]}
%% and permit(false) is called on RNode, and we sent the
- %% weigth first. Node handled it in handle_info, and
- %% now we must send him a weigth msg. We can use any weigth;
+ %% weight first. Node handled it in handle_info, and
+ %% now we must send him a weight msg. We can use any weight;
%% he wins anyway.
monitor_node(Node, false),
{?DIST_AC, Node} !
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index 7fe5edf80d..a1b7c22c21 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,8 @@
start_timer/1, setup_timer/2,
reset_timer/1, cancel_timer/1,
is_node_name/1, split_node/1, is_allowed/2,
- shutdown/3, shutdown/4]).
+ shutdown/3, shutdown/4,
+ net_ticker_spawn_options/0]).
-import(error_logger,[error_msg/2]).
@@ -70,8 +71,6 @@
-define(u32(X3,X2,X1,X0),
(((X3) bsl 24) bor ((X2) bsl 16) bor ((X1) bsl 8) bor (X0))).
--define(CREATION_UNKNOWN,0).
-
-record(tick, {read = 0,
write = 0,
tick = 0,
@@ -124,6 +123,10 @@ dflag2str(?DFLAG_FRAGMENTS) ->
"FRAGMENTS";
dflag2str(?DFLAG_HANDSHAKE_23) ->
"HANDSHAKE_23";
+dflag2str(?DFLAG_UNLINK_ID) ->
+ "UNLINK_ID";
+dflag2str(?DFLAG_MANDATORY_25_DIGEST) ->
+ "MANDATORY_25_DIGEST";
dflag2str(?DFLAG_SPAWN) ->
"SPAWN";
dflag2str(?DFLAG_NAME_ME) ->
@@ -132,8 +135,8 @@ dflag2str(?DFLAG_V4_NC) ->
"V4_NC";
dflag2str(?DFLAG_ALIAS) ->
"ALIAS";
-dflag2str(_) ->
- "UNKNOWN".
+dflag2str(Other) ->
+ lists:flatten(io_lib:format("UNKNOWN<~.16.0B>", [Other])).
adjust_flags(ThisFlags, OtherFlags) ->
@@ -143,7 +146,7 @@ publish_flag(_, NameMeFlg, _) when (NameMeFlg band ?DFLAG_NAME_ME) =/= 0 ->
?DFLAG_NAME_ME;
publish_flag(hidden, _, _) ->
0;
-publish_flag(_, _, OtherNode) when is_atom(OtherNode) ->
+publish_flag(_, _, OtherNode) ->
case net_kernel:publish_on_node(OtherNode) of
true ->
?DFLAG_PUBLISHED;
@@ -200,13 +203,13 @@ handshake_other_started(#hs_data{request_type=ReqType,
AddFlgs = convert_flags(AddFlgs0),
RejFlgs = convert_flags(RejFlgs0),
ReqFlgs = convert_flags(ReqFlgs0),
- {PreOtherFlags,NodeOrHost,Creation,SendNameVersion} = recv_name(HSData0),
+ {PreOtherFlags0,NodeOrHost,Creation} = recv_name(HSData0),
+ PreOtherFlags = expand_mandatory_25_flag(PreOtherFlags0),
EDF = erts_internal:get_dflags(),
PreThisFlags = make_this_flags(ReqType, AddFlgs, RejFlgs, NodeOrHost, EDF,
PreOtherFlags),
HSData1 = HSData0#hs_data{this_flags=PreThisFlags,
other_flags=PreOtherFlags,
- other_version=flags_to_version(PreOtherFlags),
other_node=NodeOrHost,
other_started=true,
other_creation=Creation,
@@ -221,7 +224,7 @@ handshake_other_started(#hs_data{request_type=ReqType,
ChallengeA = gen_challenge(),
send_challenge(HSData2, ChallengeA),
reset_timer(HSData2#hs_data.timer),
- HSData3 = recv_complement(HSData2, SendNameVersion),
+ HSData3 = recv_complement(HSData2),
check_dflags(HSData3, EDF),
ChosenFlags = adjust_flags(HSData3#hs_data.this_flags,
HSData3#hs_data.other_flags),
@@ -239,6 +242,15 @@ handshake_other_started(#hs_data{request_type=ReqType,
handshake_other_started(OldHsData) when element(1,OldHsData) =:= hs_data ->
handshake_other_started(convert_old_hsdata(OldHsData)).
+expand_mandatory_25_flag(Flags) ->
+ if
+ Flags band ?DFLAG_MANDATORY_25_DIGEST =/= 0 ->
+ %% From OTP 25, the single flag ?DFLAG_MANDATORY_25_DIGEST can
+ %% replace all the flags in ?MANDATORY_DFLAGS_25.
+ Flags bor ?MANDATORY_DFLAGS_25;
+ true ->
+ Flags
+ end.
%%
%% Check mandatory flags...
@@ -246,10 +258,19 @@ handshake_other_started(OldHsData) when element(1,OldHsData) =:= hs_data ->
check_dflags(#hs_data{other_node = Node,
other_flags = OtherFlags,
other_started = OtherStarted,
- require_flags = RequiredFlags} = HSData,
+ require_flags = RequiredFlags,
+ other_creation = OtherCreation} = HSData,
#erts_dflags{}=EDF) ->
- Mandatory = (EDF#erts_dflags.mandatory bor RequiredFlags),
+ Mask = case OtherCreation of
+ undefined ->
+ %% Old 'send_name' without creation and high flag bits
+ %% Only check low 32 flag bits for now
+ (1 bsl 32) - 1;
+ _ ->
+ bnot 0
+ end,
+ Mandatory = Mask band (EDF#erts_dflags.mandatory bor RequiredFlags),
Missing = check_mandatory(Mandatory, OtherFlags, []),
case Missing of
[] ->
@@ -412,36 +433,33 @@ handshake_we_started(#hs_data{request_type=ReqType,
RejFlgs = convert_flags(RejFlgs0),
ReqFlgs = convert_flags(ReqFlgs0),
EDF = erts_internal:get_dflags(),
- {NameMeFlg, NameToSend, MinVersion} =
+ {NameMeFlg, NameToSend} =
case node() of
nonode@nohost ->
{node, "undefined", Host} = split_node(MyNode),
- false = net_kernel:dist_listen(),
- {?DFLAG_NAME_ME, Host, ?ERL_DIST_VER_6};
+ {?DFLAG_NAME_ME, Host};
_ ->
- {0, MyNode, PreHSData#hs_data.other_version}
+ {0, MyNode}
end,
PreThisFlags = make_this_flags(ReqType, AddFlgs, RejFlgs, Node, EDF, NameMeFlg),
HSData = PreHSData#hs_data{this_node = NameToSend,
this_flags = PreThisFlags,
- other_version = MinVersion,
add_flags = AddFlgs,
reject_flags = RejFlgs,
require_flags = ReqFlgs},
- SendNameVersion = send_name(HSData),
+ send_name(HSData),
HSData1 = recv_status(HSData),
- {PreOtherFlags, ChallengeA, Creation} = recv_challenge(HSData1),
+ {PreOtherFlags0, ChallengeA, Creation} = recv_challenge(HSData1),
+ PreOtherFlags = expand_mandatory_25_flag(PreOtherFlags0),
ChosenFlags = adjust_flags(PreThisFlags, PreOtherFlags),
HSData2 = HSData1#hs_data{this_flags = ChosenFlags,
other_flags = ChosenFlags,
other_started = false,
- other_version = flags_to_version(PreOtherFlags),
other_creation = Creation},
check_dflags(HSData2, EDF),
ChallengeB = gen_challenge(),
Cookie = auth:get_cookie(Node),
- send_complement(HSData2, SendNameVersion),
send_challenge_reply(HSData2, ChallengeB,
gen_digest(ChallengeA, Cookie)),
reset_timer(HSData2#hs_data.timer),
@@ -462,16 +480,6 @@ convert_flags(Flags) when is_integer(Flags) ->
convert_flags(_Undefined) ->
0.
-flags_to_version(Flags) ->
- case Flags band ?DFLAG_HANDSHAKE_23 of
- 0 ->
- ?ERL_DIST_VER_5;
- ?DFLAG_HANDSHAKE_23 ->
- ?ERL_DIST_VER_6
- end.
-
-
-
%% --------------------------------------------------------------
%% The connection has been established.
%% --------------------------------------------------------------
@@ -548,7 +556,7 @@ gen_challenge() ->
%% No error return; either succeeds or terminates the process.
do_setnode(#hs_data{other_node = Node, socket = Socket,
this_node = MyNode,
- other_flags = Flags, other_version = Version,
+ other_flags = Flags,
f_getll = GetLL,
other_creation = Creation}=HSData) ->
case GetLL(Socket) of
@@ -561,12 +569,12 @@ do_setnode(#hs_data{other_node = Node, socket = Socket,
MyNode ->
false
end,
- ?trace("setnode: node=~p port=~p flags=~p(~p) ver=~p creation=~p~n",
- [Node, Port, Flags, publish_type(Flags), Version, Creation]),
+ ?trace("setnode: node=~p port=~p flags=~p(~p) creation=~p~n",
+ [Node, Port, Flags, publish_type(Flags), Creation]),
MyNode = node(), % ASSERT
try
- DHandle = erlang:setnode(Node, Port, {Flags, Version, Creation}),
+ DHandle = erlang:setnode(Node, Port, {Flags, Creation}),
{DHandle, NamedMe}
catch
error:system_limit ->
@@ -672,35 +680,18 @@ con_loop(#state{kernel = Kernel, node = Node,
send_name(#hs_data{socket = Socket, this_node = Node,
f_send = FSend,
- this_flags = Flags,
- other_version = Version}) ->
+ this_flags = Flags}) ->
NameBin = to_binary(Node),
- if Version =:= undefined;
- Version =:= ?ERL_DIST_VER_5 ->
- %% We treat "5" the same as 'undefined' as there are
- %% custom made epmd modules out there with a hardcoded "5".
- %%
- %% Send old 'n' message but with DFLAG_HANDSHAKE_23
- %% Old nodes will ignore DFLAG_HANDSHAKE_23 and reply old 'n' challenge.
- %% New nodes will see DFLAG_HANDSHAKE_23 and reply new 'N' challenge.
- ?trace("send_name: 'n' node=~p, version=~w\n",
- [Node, ?ERL_DIST_VER_5]),
- _ = ?to_port(FSend, Socket,
- [<<$n, ?ERL_DIST_VER_5:16, Flags:32>>, NameBin]),
- ?ERL_DIST_VER_5;
-
- is_integer(Version), Version >= ?ERL_DIST_VER_6 ->
- Creation = case name_type(Flags) of
- static -> erts_internal:get_creation();
- dynamic -> 0
- end,
- NameLen = byte_size(NameBin),
- ?trace("send_name: 'N' node=~p creation=~w\n",
- [Node, Creation]),
- _ = ?to_port(FSend, Socket,
- [<<$N, Flags:64, Creation:32, NameLen:16>>, NameBin]),
- ?ERL_DIST_VER_6
- end.
+ Creation = case name_type(Flags) of
+ static -> erts_internal:get_creation();
+ dynamic -> 0
+ end,
+ NameLen = byte_size(NameBin),
+ ?trace("send_name: 'N' node=~p creation=~w\n",
+ [Node, Creation]),
+ _ = ?to_port(FSend, Socket,
+ [<<$N, Flags:64, Creation:32, NameLen:16>>, NameBin]),
+ ok.
to_binary(Atom) when is_atom(Atom) ->
atom_to_binary(Atom, latin1);
@@ -709,50 +700,20 @@ to_binary(List) when is_list(List) ->
send_challenge(#hs_data{socket = Socket, this_node = Node,
this_flags = ThisFlags,
- other_flags = OtherFlags,
f_send = FSend},
Challenge ) ->
- case OtherFlags band ?DFLAG_HANDSHAKE_23 of
- 0 ->
- %% Reply with old 'n' message
- ?trace("send: 'n' challenge=~w\n", [Challenge]),
-
- ?to_port(FSend, Socket, [<<$n,
- ?ERL_DIST_VER_5:16, % echo same Version back
- ThisFlags:32,
- Challenge:32>>,
- atom_to_list(Node)]);
-
- ?DFLAG_HANDSHAKE_23 ->
- %% Reply with new 'N' message
- Creation = erts_internal:get_creation(),
- NodeName = atom_to_binary(Node, latin1),
- NameLen = byte_size(NodeName),
- ?trace("send: 'N' challenge=~w creation=~w\n",
- [Challenge,Creation]),
- ?to_port(FSend, Socket, [<<$N,
- ThisFlags:64,
- Challenge:32,
- Creation:32,
- NameLen:16>>, NodeName])
- end.
-
-send_complement(#hs_data{socket = Socket,
- f_send = FSend,
- this_flags = Flags,
- other_flags = Flags},
- SendNameVersion) ->
- if SendNameVersion =:= ?ERL_DIST_VER_5,
- (Flags band ?DFLAG_HANDSHAKE_23) =/= 0 ->
- %% We sent an old 'n' name message and need to complement
- %% with creation value.
- Creation = erts_internal:get_creation(),
- FlagsHigh = Flags bsr 32,
- ?trace("send_complement: 'c' flags_high=~w creation=~w\n", [FlagsHigh,Creation]),
- ?to_port(FSend, Socket, [<<$c, FlagsHigh:32, Creation:32>>]);
- true->
- ok % no complement msg needed
- end.
+ %% Reply with new 'N' message
+ Creation = erts_internal:get_creation(),
+ NodeName = atom_to_binary(Node, latin1),
+ NameLen = byte_size(NodeName),
+ ?trace("send: 'N' challenge=~w creation=~w\n",
+ [Challenge,Creation]),
+ _ = ?to_port(FSend, Socket, [<<$N,
+ ThisFlags:64,
+ Challenge:32,
+ Creation:32,
+ NameLen:16>>, NodeName]),
+ ok.
send_challenge_reply(#hs_data{socket = Socket, f_send = FSend},
Challenge, Digest) ->
@@ -780,6 +741,15 @@ recv_name(#hs_data{socket = Socket, f_recv = Recv} = HSData) ->
?shutdown(no_node)
end.
+%% OTP 25.3:
+%% We accept old 'send_name' messages ($n) used by OTP-22 and older.
+%% OTP-23 or OTP-24 nodes, not using epmd, may send the old message
+%% to us if they do not know our OTP version.
+%% Hence, we accept the old 'send_name' and the accompanying
+%% 'send_complement', but we do not send them ourself.
+%% This was removed prematurely in OTP-25.0,
+%% therefore versions 25.0 to 25.2.* are broken in this regard.
+%% Can be safely removed in OTP-27.0.
recv_name_old(HSData,
[$n, V1, V0, F3, F2, F1, F0 | Node] = Data) ->
<<_Version:16>> = <<V1,V0>>,
@@ -788,7 +758,7 @@ recv_name_old(HSData,
case is_node_name(Node) of
true ->
check_allowed(HSData, Node),
- {Flags, list_to_atom(Node), ?CREATION_UNKNOWN, ?ERL_DIST_VER_5};
+ {Flags, list_to_atom(Node), undefined};
false ->
?shutdown(Data)
end.
@@ -811,7 +781,7 @@ recv_name_new(HSData,
%% Keep host name as string
Name
end,
- {Flags, NodeOrHost, Creation, ?ERL_DIST_VER_6};
+ {Flags, NodeOrHost, Creation};
false ->
?shutdown(Data)
end.
@@ -946,33 +916,12 @@ publish_type(Flags) ->
%% wait for challenge after connect
recv_challenge(#hs_data{socket=Socket, f_recv=Recv}=HSData) ->
case Recv(Socket, 0, infinity) of
- {ok, [$n | _]=Msg} ->
- recv_challenge_old(HSData, Msg);
{ok,[$N | _]=Msg} ->
recv_challenge_new(HSData, Msg);
Other ->
?shutdown2(no_node, {recv_challenge_failed, Other})
end.
-recv_challenge_old(#hs_data{other_node=Node},
- [$n, V1,V0, F3,F2,F1,F0, C3,C2,C1,C0 | Ns]=Msg) ->
- <<_Version:16>> = <<V1,V0>>,
- <<Flags:32>> = <<F3,F2,F1,F0>>,
- <<Challenge:32>> = <<C3,C2,C1,C0>>,
- ?trace("recv: 'n' node=~p, challenge=~w version=~w\n",
- [Ns, Challenge, _Version]),
- try {list_to_existing_atom(Ns), Flags band ?DFLAG_HANDSHAKE_23} of
- {Node, 0} ->
- {Flags, Challenge, ?CREATION_UNKNOWN};
- _ ->
- ?shutdown2(no_node, {recv_challenge_failed, version, Msg})
- catch
- error:badarg ->
- ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
- end;
-recv_challenge_old(_, Other) ->
- ?shutdown2(no_node, {recv_challenge_failed, Other}).
-
recv_challenge_new(#hs_data{other_node=Node},
[$N,
F7,F6,F5,F4,F3,F2,F1,F0,
@@ -993,43 +942,36 @@ recv_challenge_new(#hs_data{other_node=Node},
?trace("recv: 'N' node=~p, challenge=~w creation=~w\n",
[Ns, Challenge, Creation]),
- case Flags band ?DFLAG_HANDSHAKE_23 of
- ?DFLAG_HANDSHAKE_23 ->
- try list_to_existing_atom(Ns) of
- Node ->
- {Flags, Challenge, Creation};
- _ ->
- ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
- catch
- error:badarg ->
- ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
- end;
- 0 ->
- ?shutdown2(no_node, {recv_challenge_failed, version, Msg})
+ try list_to_existing_atom(Ns) of
+ Node ->
+ {Flags, Challenge, Creation};
+ _ ->
+ ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
+ catch
+ error:badarg ->
+ ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
end;
recv_challenge_new(_, Other) ->
?shutdown2(no_node, {recv_challenge_failed, Other}).
+%% See comment for recv_name_old
recv_complement(#hs_data{socket = Socket,
f_recv = Recv,
- other_flags = Flags} = HSData,
- SendNameVersion) ->
- if SendNameVersion =:= ?ERL_DIST_VER_5,
- (Flags band ?DFLAG_HANDSHAKE_23) =/= 0 ->
- case Recv(Socket, 0, infinity) of
- {ok, [$c, F7,F6,F5,F4, Cr3,Cr2,Cr1,Cr0]} ->
- <<FlagsHigh:32>> = <<F7,F6,F5,F4>>,
- <<Creation:32>> = <<Cr3,Cr2,Cr1,Cr0>>,
- ?trace("recv_complement: creation=~w\n", [Creation]),
- HSData#hs_data{other_creation = Creation,
- other_flags = Flags bor (FlagsHigh bsl 32)};
- Other ->
- ?shutdown2(no_node, {recv_complement_failed, Other})
- end;
- true ->
- HSData
- end.
+ other_flags = Flags,
+ other_creation = undefined} = HSData) ->
+ case Recv(Socket, 0, infinity) of
+ {ok, [$c, F7,F6,F5,F4, Cr3,Cr2,Cr1,Cr0]} ->
+ <<FlagsHigh:32>> = <<F7,F6,F5,F4>>,
+ <<Creation:32>> = <<Cr3,Cr2,Cr1,Cr0>>,
+ ?trace("recv_complement: creation=~w\n", [Creation]),
+ HSData#hs_data{other_creation = Creation,
+ other_flags = Flags bor (FlagsHigh bsl 32)};
+ Other ->
+ ?shutdown2(no_node, {recv_complement_failed, Other})
+ end;
+recv_complement(HSData) ->
+ HSData.
%%
@@ -1193,8 +1135,8 @@ send_status(#hs_data{socket = Socket, other_node = Node,
%% ticker process, In that case this code will never run
%% And then every 60 seconds we also check the connection and
-%% close it if we havn't received anything on it for the
-%% last 60 secs. If ticked == tick we havn't received anything
+%% close it if we haven't received anything on it for the
+%% last 60 secs. If ticked == tick we haven't received anything
%% on the connection the last 60 secs.
%% The detection time interval is thus, by default, 45s < DT < 75s
@@ -1283,3 +1225,20 @@ cancel_timer(Timer) ->
unlink(Timer),
exit(Timer, shutdown).
+net_ticker_spawn_options() ->
+ Opts = application:get_env(kernel, net_ticker_spawn_options, []),
+ [link, {priority, max} | cleanup_net_ticker_spawn_options(Opts)].
+
+cleanup_net_ticker_spawn_options([]) ->
+ [];
+cleanup_net_ticker_spawn_options([link|Opts]) ->
+ cleanup_net_ticker_spawn_options(Opts);
+cleanup_net_ticker_spawn_options([{priority, _}|Opts]) ->
+ cleanup_net_ticker_spawn_options(Opts);
+cleanup_net_ticker_spawn_options([monitor|Opts]) ->
+ cleanup_net_ticker_spawn_options(Opts);
+cleanup_net_ticker_spawn_options([{monitor, _}|Opts]) ->
+ cleanup_net_ticker_spawn_options(Opts);
+cleanup_net_ticker_spawn_options([Opt|Opts]) ->
+ [Opt|cleanup_net_ticker_spawn_options(Opts)].
+
diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl
index 4ac945ce01..adbf1bdbcf 100644
--- a/lib/kernel/src/erl_boot_server.erl
+++ b/lib/kernel/src/erl_boot_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
add_subnet/2, delete_subnet/2,
which_slaves/0]).
-%% Exports for testing (dont't remove; tests suites depend on them).
+%% Exports for testing (don't remove; tests suites depend on them).
-export([would_be_booted/1]).
%% Internal exports
@@ -46,7 +46,7 @@
{
priority = 0, %% priority of this server
version = "" :: string(), %% Version handled i.e "4.5.3" etc
- udp_sock, %% listen port for broadcase requests
+ udp_sock, %% listen port for broadcast requests
udp_port, %% port number must be ?EBOOT_PORT!
listen_sock, %% listen sock for incoming file requests
listen_port, %% listen port number
diff --git a/lib/kernel/src/erl_erts_errors.erl b/lib/kernel/src/erl_erts_errors.erl
index b6a8ce846f..4d23112b83 100644
--- a/lib/kernel/src/erl_erts_errors.erl
+++ b/lib/kernel/src/erl_erts_errors.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
%%
-module(erl_erts_errors).
--export([format_error/2]).
+-export([format_error/2, format_bs_fail/2]).
-spec format_error(Reason, StackTrace) -> ErrorMap when
Reason :: term(),
@@ -43,6 +43,26 @@ format_error(Reason, [{M,F,As,Info}|_]) ->
end,
format_error_map(Res, 1, #{}).
+-spec format_bs_fail(Reason, StackTrace) -> ErrorMap when
+ Reason :: term(),
+ StackTrace :: erlang:stacktrace(),
+ ErrorMap :: #{'general' => unicode:chardata()}.
+
+format_bs_fail(Reason, [{_,_,_,Info}|_]) ->
+ ErrorInfoMap = proplists:get_value(error_info, Info, #{}),
+ case ErrorInfoMap of
+ #{cause := {Segment0,Type,Error,Value}} ->
+ Segment1 = maps:get(override_segment_position, ErrorInfoMap, Segment0),
+ PrettyPrinter = maps:get(pretty_printer, ErrorInfoMap, fun possibly_truncated/1),
+ Str0 = do_format_bs_fail(Reason, Type, Error, Value, PrettyPrinter),
+ Str1 = io_lib:format("segment ~p of type '~ts': ~ts",
+ [Segment1,Type,Str0]),
+ Str = iolist_to_binary(Str1),
+ #{general => Str, reason => <<"construction of binary failed">>};
+ #{} ->
+ #{}
+ end.
+
format_atomics_error(new, [Size,Options], Reason, Cause) ->
case Reason of
system_limit ->
@@ -575,7 +595,7 @@ format_erlang_error(monitor_node, [Node,Flag], _) ->
format_erlang_error(monitor_node, [Node,Flag,Options], Cause) ->
Arg3 = case Cause of
badopt -> bad_option;
- true -> []
+ _ -> []
end,
case format_erlang_error(monitor_node, [Node,Flag], Cause) of
[[],[]] ->
@@ -587,8 +607,56 @@ format_erlang_error(monotonic_time, [_], _) ->
[bad_time_unit];
format_erlang_error(node, [_], _) ->
[not_pid];
-format_erlang_error(nodes, [_], _) ->
+format_erlang_error(nodes, [NTVal], _) when is_atom(NTVal) ->
[<<"not a valid node type">>];
+format_erlang_error(nodes, [NTVal], _) when is_list(NTVal) ->
+ [<<"not a list of valid node types">>];
+format_erlang_error(nodes, [_NTVal], _) ->
+ [<<"not a valid node type or list of valid node types">>];
+format_erlang_error(nodes, [NTVal, Opts], _) ->
+ ValidNodeTypes = [this, connected, visible, hidden, known],
+ [if is_atom(NTVal) ->
+ case lists:member(NTVal, ValidNodeTypes) of
+ true -> [];
+ false -> <<"not a valid node type">>
+ end;
+ is_list(NTVal) ->
+ try
+ lists:foreach(
+ fun (NT) ->
+ case lists:member(NT, ValidNodeTypes) of
+ true -> [];
+ false -> throw(invalid)
+ end
+ end,
+ NTVal),
+ []
+ catch
+ throw:invalid ->
+ <<"not a list of valid node types">>
+ end;
+ true ->
+ <<"not a valid node type or list of valid node types">>
+ end,
+ if is_map(Opts) ->
+ try
+ maps:foreach(
+ fun (connection_id, Bool) when is_boolean(Bool) ->
+ ok;
+ (node_type, Bool) when is_boolean(Bool) ->
+ ok;
+ (_, _) ->
+ throw(invalid)
+ end,
+ Opts),
+ []
+ catch
+ throw:invalid ->
+ <<"invalid options in map">>
+ end;
+ true ->
+ not_map
+ end];
format_erlang_error(open_port, [Name, Settings], Cause) ->
case Cause of
badopt ->
@@ -734,7 +802,7 @@ format_erlang_error(send, [_,_,Options], Cause) ->
case Cause of
badopt ->
[[],[],must_be_list(Options, bad_option)];
- true ->
+ _ ->
[bad_destination]
end;
format_erlang_error(send_after, Args, Cause) ->
@@ -1034,6 +1102,76 @@ format_erlang_error(whereis, [_], _) ->
format_erlang_error(_, _, _) ->
[].
+do_format_bs_fail(system_limit, binary, binary, size, _PrettyPrinter) ->
+ %% On a 32-bit system, the size of the binary is 256 MiB or
+ %% more, which is not supported because the size in bits does not
+ %% fit in a 32-bit signed integer. In practice, an application
+ %% that uses any binaries of that size is likely to quickly run
+ %% out of memory.
+ io_lib:format(<<"the size of the binary/bitstring is too large (exceeding ~p bits)">>,
+ [(1 bsl 31) - 1]);
+do_format_bs_fail(system_limit, _Type, size, Value, _PrettyPrinter) ->
+ io_lib:format(<<"the size ~p is too large">>, [Value]);
+do_format_bs_fail(badarg, Type, Info, Value, PrettyPrinter) ->
+ do_format_bs_fail(Type, Info, Value, PrettyPrinter).
+
+do_format_bs_fail(float, invalid, Value, _PrettyPrinter) ->
+ io_lib:format(<<"expected one of the supported sizes 16, 32, or 64 but got: ~p">>,
+ [Value]);
+do_format_bs_fail(float, no_float, Value, PrettyPrinter) ->
+ io_lib:format(<<"the value ~ts is outside the range expressible as a float">>,
+ [PrettyPrinter(Value)]);
+do_format_bs_fail(binary, unit, Value, PrettyPrinter) ->
+ io_lib:format(<<"the size of the value ~ts is not a multiple of the unit for the segment">>,
+ [PrettyPrinter(Value)]);
+do_format_bs_fail(_Type, short, Value, PrettyPrinter) ->
+ io_lib:format(<<"the value ~ts is shorter than the size of the segment">>,
+ [PrettyPrinter(Value)]);
+do_format_bs_fail(_Type, size, Value, PrettyPrinter) ->
+ io_lib:format(<<"expected a non-negative integer as size but got: ~ts">>,
+ [PrettyPrinter(Value)]);
+do_format_bs_fail(Type, type, Value, PrettyPrinter) ->
+ F = <<"expected a",
+ (case Type of
+ binary ->
+ <<" binary">>;
+ float ->
+ <<" float or an integer">>;
+ integer ->
+ <<"n integer">>;
+ _ ->
+ <<" non-negative integer encodable as ", (atom_to_binary(Type))/binary>>
+ end)/binary, " but got: ~ts">>,
+ io_lib:format(F, [PrettyPrinter(Value)]).
+
+possibly_truncated(Int) when is_integer(Int) ->
+ Bin = integer_to_binary(Int),
+ case byte_size(Bin) of
+ Size when Size < 48 ->
+ Bin;
+ Size ->
+ <<Prefix:12/binary, _:(Size-24)/binary, Suffix/binary>> = Bin,
+ [Prefix, <<"...">>, Suffix]
+ end;
+possibly_truncated(Bin) when is_bitstring(Bin) ->
+ case byte_size(Bin) of
+ Size when Size < 16 ->
+ io_lib:format("~p", [Bin]);
+ Size ->
+ <<Prefix0:8/binary, _:(Size-10)/binary, Suffix0/bitstring>> = Bin,
+ Prefix1 = iolist_to_binary(io_lib:format("~w", [Prefix0])),
+ <<Prefix:(byte_size(Prefix1)-2)/binary,_/binary>> = Prefix1,
+ <<_:2/unit:8,Suffix/binary>> = iolist_to_binary(io_lib:format("~w", [Suffix0])),
+ [Prefix, <<"...,">>, Suffix]
+ end;
+%% possibly_truncated(Value) when is_bitstring(Value) ->
+possibly_truncated(Value) ->
+ io_lib:format("~P", [Value,20]).
+
+%%%
+%%% Utility functions.
+%%%
+
list_to_something(List, Error) ->
try length(List) of
_ ->
diff --git a/lib/kernel/src/erl_kernel_errors.erl b/lib/kernel/src/erl_kernel_errors.erl
index 376ce31f16..80660d46c8 100644
--- a/lib/kernel/src/erl_kernel_errors.erl
+++ b/lib/kernel/src/erl_kernel_errors.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,6 +42,8 @@ format_error(_Reason, [{M,F,As,Info}|_]) ->
format_erl_ddll_error(_, _, _) ->
[].
+format_os_error(cmd, _, {open_port, Reason}) ->
+ [{general, maybe_posix_message(Reason)}];
format_os_error(cmd, [_], _) ->
[not_charlist];
format_os_error(cmd, [_, _], Cause) ->
@@ -71,6 +73,14 @@ format_os_error(unsetenv, [Name], _) ->
format_os_error(_, _, _) ->
[].
+maybe_posix_message(Reason) ->
+ case erl_posix_msg:message(Reason) of
+ "unknown POSIX error" ->
+ io_lib:format("open_port failed with reason: ~tp",[Reason]);
+ PosixStr ->
+ io_lib:format("~ts (~tp)",[PosixStr, Reason])
+ end.
+
must_be_atom(Term, Default) when is_atom(Term) -> Default;
must_be_atom(_, _) -> not_atom.
@@ -129,6 +139,8 @@ must_be_env_charlist(_) ->
format_error_map([""|Es], ArgNum, Map) ->
format_error_map(Es, ArgNum + 1, Map);
+format_error_map([{general, E}|Es], ArgNum, Map) ->
+ format_error_map(Es, ArgNum, Map#{ general => expand_error(E)});
format_error_map([E|Es], ArgNum, Map) ->
format_error_map(Es, ArgNum + 1, Map#{ArgNum => expand_error(E)});
format_error_map([], _, Map) ->
@@ -155,4 +167,6 @@ expand_error(not_list) ->
expand_error(not_map) ->
<<"not a map">>;
expand_error(not_proper_list) ->
- <<"not a proper list">>.
+ <<"not a proper list">>;
+expand_error(Other) ->
+ Other.
diff --git a/lib/kernel/src/erpc.erl b/lib/kernel/src/erpc.erl
index d591fc7025..ce34d1a62f 100644
--- a/lib/kernel/src/erpc.erl
+++ b/lib/kernel/src/erpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,19 +32,27 @@
cast/4,
send_request/2,
send_request/4,
+ send_request/6,
receive_response/1,
receive_response/2,
+ receive_response/3,
wait_response/1,
wait_response/2,
+ wait_response/3,
check_response/2,
+ check_response/3,
multicall/2,
multicall/3,
multicall/4,
multicall/5,
multicast/2,
- multicast/4]).
+ multicast/4,
+ reqids_new/0,
+ reqids_size/1,
+ reqids_add/3,
+ reqids_to_list/1]).
--export_type([request_id/0]).
+-export_type([request_id/0, request_id_collection/0, timeout_time/0]).
%% Internal exports (also used by the 'rpc' module)
@@ -57,14 +65,15 @@
%%------------------------------------------------------------------------
--compile({inline,[{result,4}]}). %% Nicer error stack trace...
+%% Nicer error stack trace...
+-compile({inline,[{result,4},{collection_result,6},{timeout_value,1}]}).
-define(MAX_INT_TIMEOUT, 4294967295).
--define(TIMEOUT_TYPE, 0..?MAX_INT_TIMEOUT | 'infinity').
-define(IS_VALID_TMO_INT(TI_), (is_integer(TI_)
andalso (0 =< TI_)
andalso (TI_ =< ?MAX_INT_TIMEOUT))).
--define(IS_VALID_TMO(T_), ((T_ == infinity) orelse ?IS_VALID_TMO_INT(T_))).
+
+-type timeout_time() :: 0..?MAX_INT_TIMEOUT | 'infinity' | {abs, integer()}.
%%------------------------------------------------------------------------
%% Exported API
@@ -81,7 +90,7 @@ call(N, Fun) ->
-spec call(Node, Fun, Timeout) -> Result when
Node :: node(),
Fun :: function(),
- Timeout :: ?TIMEOUT_TYPE,
+ Timeout :: timeout_time(),
Result :: term().
call(N, Fun, Timeout) when is_function(Fun, 0) ->
@@ -106,7 +115,7 @@ call(N, M, F, A) ->
Module :: atom(),
Function :: atom(),
Args :: [term()],
- Timeout :: ?TIMEOUT_TYPE,
+ Timeout :: timeout_time(),
Result :: term().
call(N, M, F, A, infinity) when node() =:= N, %% Optimize local call
@@ -131,8 +140,8 @@ call(N, M, F, A, infinity) when node() =:= N, %% Optimize local call
call(N, M, F, A, T) when is_atom(N),
is_atom(M),
is_atom(F),
- is_list(A),
- ?IS_VALID_TMO(T) ->
+ is_list(A) ->
+ Timeout = timeout_value(T),
Res = make_ref(),
ReqId = spawn_request(N, ?MODULE, execute_call, [Res, M, F, A],
[{reply, error_only}, monitor]),
@@ -141,7 +150,7 @@ call(N, M, F, A, T) when is_atom(N),
result(spawn_reply, ReqId, Res, Reason);
{'DOWN', ReqId, process, _Pid, Reason} ->
result(down, ReqId, Res, Reason)
- after T ->
+ after Timeout ->
result(timeout, ReqId, Res, undefined)
end;
call(_N, _M, _F, _A, _T) ->
@@ -149,24 +158,34 @@ call(_N, _M, _F, _A, _T) ->
%% Asynchronous call
--opaque request_id() :: {reference(), reference()}.
+-opaque request_id() :: nonempty_improper_list(reference(), reference()).
+-opaque request_id_collection() :: #{ reference() => [reference() | term()] }.
-spec send_request(Node, Fun) -> RequestId when
Node :: node(),
Fun :: function(),
RequestId :: request_id().
-send_request(N, F) when is_function(F, 0) ->
+send_request(N, F) when is_atom(N), is_function(F, 0) ->
send_request(N, erlang, apply, [F, []]);
send_request(_N, _F) ->
error({?MODULE, badarg}).
+-dialyzer({no_improper_lists, send_request/4}).
+
-spec send_request(Node, Module, Function, Args) -> RequestId when
Node :: node(),
Module :: atom(),
Function :: atom(),
Args :: [term()],
- RequestId :: request_id().
+ RequestId :: request_id();
+ (Node, Fun, Label, RequestIdCollection) ->
+ NewRequestIdCollection when
+ Node :: node(),
+ Fun :: function(),
+ Label :: term(),
+ RequestIdCollection :: request_id_collection(),
+ NewRequestIdCollection :: request_id_collection().
send_request(N, M, F, A) when is_atom(N),
is_atom(M),
@@ -175,16 +194,43 @@ send_request(N, M, F, A) when is_atom(N),
Res = make_ref(),
ReqId = spawn_request(N, ?MODULE, execute_call, [Res, M, F, A],
[{reply, error_only}, monitor]),
- {Res, ReqId};
-send_request(_N, _M, _F, _A) ->
+ [Res|ReqId];
+send_request(N, F, L, C) when is_atom(N), is_function(F, 0), is_map(C) ->
+ send_request(N, erlang, apply, [F, []], L, C);
+send_request(_, _, _, _) ->
+ error({?MODULE, badarg}).
+
+-dialyzer({no_improper_lists, send_request/6}).
+
+-spec send_request(Node, Module, Function, Args,
+ Label, RequestIdCollection) ->
+ NewRequestIdCollection when
+ Node :: node(),
+ Module :: atom(),
+ Function :: atom(),
+ Args :: [term()],
+ Label :: term(),
+ RequestIdCollection :: request_id_collection(),
+ NewRequestIdCollection :: request_id_collection().
+
+send_request(N, M, F, A, L, C) when is_atom(N),
+ is_atom(M),
+ is_atom(F),
+ is_list(A),
+ is_map(C) ->
+ Res = make_ref(),
+ ReqId = spawn_request(N, ?MODULE, execute_call, [Res, M, F, A],
+ [{reply, error_only}, monitor]),
+ maps:put(ReqId, [Res|L], C);
+send_request(_N, _M, _F, _A, _L, _C) ->
error({?MODULE, badarg}).
-spec receive_response(RequestId) -> Result when
RequestId :: request_id(),
Result :: term().
-receive_response({Res, ReqId} = RId) when is_reference(Res),
- is_reference(ReqId) ->
+receive_response([Res|ReqId] = RId) when is_reference(Res),
+ is_reference(ReqId) ->
receive_response(RId, infinity);
receive_response(_) ->
error({?MODULE, badarg}).
@@ -193,53 +239,118 @@ receive_response(_) ->
-spec receive_response(RequestId, Timeout) -> Result when
RequestId :: request_id(),
- Timeout :: ?TIMEOUT_TYPE,
+ Timeout :: timeout_time(),
Result :: term().
-receive_response({Res, ReqId}, Tmo) when is_reference(Res),
- is_reference(ReqId),
- ?IS_VALID_TMO(Tmo) ->
+receive_response([Res|ReqId], Tmo) when is_reference(Res),
+ is_reference(ReqId) ->
+ Timeout = timeout_value(Tmo),
receive
{spawn_reply, ReqId, error, Reason} ->
result(spawn_reply, ReqId, Res, Reason);
{'DOWN', ReqId, process, _Pid, Reason} ->
result(down, ReqId, Res, Reason)
- after Tmo ->
+ after Timeout ->
result(timeout, ReqId, Res, undefined)
end;
receive_response(_, _) ->
error({?MODULE, badarg}).
--spec wait_response(RequestId) -> {'response', Result} | 'no_response' when
+-dialyzer([{nowarn_function, receive_response/3}, no_return]).
+
+-spec receive_response(RequestIdCollection, Timeout, Delete) ->
+ {Result, Label, NewRequestIdCollection} | 'no_request' when
+ RequestIdCollection :: request_id_collection(),
+ Timeout :: timeout_time(),
+ Delete :: boolean(),
+ Result :: term(),
+ Label :: term(),
+ NewRequestIdCollection :: request_id_collection().
+
+receive_response(ReqIdCol, WT, Del) when map_size(ReqIdCol) == 0,
+ is_boolean(Del) ->
+ _ = timeout_value(WT),
+ no_request;
+receive_response(ReqIdCol, Tmo, Del) when is_map(ReqIdCol),
+ is_boolean(Del) ->
+ Timeout = timeout_value(Tmo),
+ receive
+ {spawn_reply, ReqId, error, Reason}
+ when is_map_key(ReqId, ReqIdCol), is_reference(ReqId) ->
+ collection_result(spawn_reply, ReqId, Reason, ReqIdCol, false, Del);
+ {'DOWN', ReqId, process, _Pid, Reason}
+ when is_map_key(ReqId, ReqIdCol), is_reference(ReqId) ->
+ collection_result(down, ReqId, Reason, ReqIdCol, false, Del)
+ after Timeout ->
+ collection_result(timeout, ok, ok, ReqIdCol, false, Del)
+ end;
+receive_response(_, _, _) ->
+ error({?MODULE, badarg}).
+
+-spec wait_response(RequestId) ->
+ {'response', Result} | 'no_response' when
RequestId :: request_id(),
Result :: term().
-wait_response({Res, ReqId} = RId) when is_reference(Res),
- is_reference(ReqId) ->
- wait_response(RId, 0).
+wait_response([Res|ReqId] = RId) when is_reference(Res),
+ is_reference(ReqId) ->
+ wait_response(RId, 0);
+wait_response(_) ->
+ error({?MODULE, badarg}).
-dialyzer([{nowarn_function, wait_response/2}, no_return]).
-spec wait_response(RequestId, WaitTime) ->
{'response', Result} | 'no_response' when
RequestId :: request_id(),
- WaitTime :: ?TIMEOUT_TYPE,
+ WaitTime :: timeout_time(),
Result :: term().
-wait_response({Res, ReqId}, WT) when is_reference(Res),
- is_reference(ReqId),
- ?IS_VALID_TMO(WT) ->
+wait_response([Res|ReqId], WT) when is_reference(Res),
+ is_reference(ReqId) ->
+ Timeout = timeout_value(WT),
receive
{spawn_reply, ReqId, error, Reason} ->
result(spawn_reply, ReqId, Res, Reason);
{'DOWN', ReqId, process, _Pid, Reason} ->
{response, result(down, ReqId, Res, Reason)}
- after WT ->
+ after Timeout ->
no_response
end;
wait_response(_, _) ->
error({?MODULE, badarg}).
+-spec wait_response(RequestIdCollection, WaitTime, Delete) ->
+ {{'response', Result}, Label, NewRequestIdCollection} |
+ 'no_response' |
+ 'no_request' when
+ RequestIdCollection :: request_id_collection(),
+ WaitTime :: timeout_time(),
+ Delete :: boolean(),
+ Label :: term(),
+ NewRequestIdCollection :: request_id_collection(),
+ Result :: term().
+
+wait_response(ReqIdCol, WT, Del) when map_size(ReqIdCol) == 0,
+ is_boolean(Del) ->
+ _ = timeout_value(WT),
+ no_request;
+wait_response(ReqIdCol, WT, Del) when is_map(ReqIdCol),
+ is_boolean(Del) ->
+ Timeout = timeout_value(WT),
+ receive
+ {spawn_reply, ReqId, error, Reason}
+ when is_map_key(ReqId, ReqIdCol), is_reference(ReqId) ->
+ collection_result(spawn_reply, ReqId, Reason, ReqIdCol, true, Del);
+ {'DOWN', ReqId, process, _Pid, Reason}
+ when is_map_key(ReqId, ReqIdCol), is_reference(ReqId) ->
+ collection_result(down, ReqId, Reason, ReqIdCol, true, Del)
+ after Timeout ->
+ no_response
+ end;
+wait_response(_, _, _) ->
+ error({?MODULE, badarg}).
+
-dialyzer([{nowarn_function, check_response/2}, no_return]).
-spec check_response(Message, RequestId) ->
@@ -247,21 +358,106 @@ wait_response(_, _) ->
Message :: term(),
RequestId :: request_id(),
Result :: term().
-
+
check_response({spawn_reply, ReqId, error, Reason},
- {Res, ReqId}) when is_reference(Res),
- is_reference(ReqId) ->
+ [Res|ReqId]) when is_reference(Res),
+ is_reference(ReqId) ->
result(spawn_reply, ReqId, Res, Reason);
check_response({'DOWN', ReqId, process, _Pid, Reason},
- {Res, ReqId}) when is_reference(Res),
- is_reference(ReqId) ->
+ [Res|ReqId]) when is_reference(Res),
+ is_reference(ReqId) ->
{response, result(down, ReqId, Res, Reason)};
-check_response(_Msg, {Res, ReqId}) when is_reference(Res),
- is_reference(ReqId) ->
+check_response(_Msg, [Res|ReqId]) when is_reference(Res),
+ is_reference(ReqId) ->
no_response;
check_response(_, _) ->
error({?MODULE, badarg}).
+-spec check_response(Message, RequestIdCollection, Delete) ->
+ {{'response', Result}, Label, NewRequestIdCollection} |
+ 'no_response' |
+ 'no_request' when
+ Message :: term(),
+ RequestIdCollection :: request_id_collection(),
+ Delete :: boolean(),
+ Result :: term(),
+ Label :: term(),
+ NewRequestIdCollection :: request_id_collection().
+
+check_response(_Msg, ReqIdCol, Del) when map_size(ReqIdCol) == 0,
+ is_boolean(Del) ->
+ no_request;
+check_response({spawn_reply, ReqId, error, Reason},
+ ReqIdCol, Del) when is_reference(ReqId),
+ is_map_key(ReqId, ReqIdCol),
+ is_boolean(Del) ->
+ collection_result(spawn_reply, ReqId, Reason, ReqIdCol, true, Del);
+check_response({'DOWN', ReqId, process, _Pid, Reason},
+ ReqIdCol, Del) when is_reference(ReqId),
+ is_map_key(ReqId, ReqIdCol),
+ is_boolean(Del) ->
+ collection_result(down, ReqId, Reason, ReqIdCol, true, Del);
+check_response(_Msg, ReqIdCol, Del) when is_map(ReqIdCol),
+ is_boolean(Del) ->
+ no_response;
+check_response(_, _, _) ->
+ error({?MODULE, badarg}).
+
+-spec reqids_new() ->
+ NewRequestIdCollection::request_id_collection().
+
+reqids_new() ->
+ maps:new().
+
+-spec reqids_size(RequestIdCollection::request_id_collection()) ->
+ non_neg_integer().
+reqids_size(ReqIdCollection) ->
+ try
+ maps:size(ReqIdCollection)
+ catch
+ _:_ ->
+ error({?MODULE, badarg})
+ end.
+
+-dialyzer({no_improper_lists, reqids_add/3}).
+
+-spec reqids_add(RequestId::request_id(), Label::term(),
+ RequestIdCollection::request_id_collection()) ->
+ NewRequestIdCollection::request_id_collection().
+
+reqids_add([_|ReqId], _, ReqIdCollection) when is_reference(ReqId),
+ is_map_key(ReqId,
+ ReqIdCollection) ->
+ error({?MODULE, badarg});
+reqids_add([Res|ReqId], Label, ReqIdCollection) when is_reference(Res),
+ is_reference(ReqId),
+ is_map(ReqIdCollection) ->
+ maps:put(ReqId, [Res|Label], ReqIdCollection);
+reqids_add(_, _, _) ->
+ error({?MODULE, badarg}).
+
+-dialyzer({no_improper_lists, reqids_to_list/1}).
+
+-spec reqids_to_list(RequestIdCollection::request_id_collection()) ->
+ [{RequestId::request_id(), Label::term()}].
+
+reqids_to_list(ReqIdCollection) when is_map(ReqIdCollection) ->
+ try
+ maps:fold(fun (ReqId, [Res|Label], Acc) when is_reference(ReqId),
+ is_reference(Res) ->
+ [{[Res|ReqId], Label}|Acc];
+ (_, _, _) ->
+ throw(badarg)
+ end,
+ [],
+ ReqIdCollection)
+ catch
+ throw:badarg ->
+ error({?MODULE, badarg})
+ end;
+reqids_to_list(_) ->
+ error({?MODULE, badarg}).
+
-type stack_item() ::
{Module :: atom(),
Function :: atom(),
@@ -288,7 +484,7 @@ multicall(Ns, Fun) ->
-spec multicall(Nodes, Fun, Timeout) -> Result when
Nodes :: [atom()],
Fun :: function(),
- Timeout :: ?TIMEOUT_TYPE,
+ Timeout :: timeout_time(),
Result :: term().
multicall(Ns, Fun, Timeout) when is_function(Fun, 0) ->
@@ -311,7 +507,7 @@ multicall(Ns, M, F, A) ->
Module :: atom(),
Function :: atom(),
Args :: [term()],
- Timeout :: ?TIMEOUT_TYPE,
+ Timeout :: timeout_time(),
Result :: [{ok, ReturnValue :: term()} | caught_call_exception()].
multicall(Ns, M, F, A, T) ->
@@ -320,7 +516,8 @@ multicall(Ns, M, F, A, T) ->
true = is_atom(F),
true = is_list(A),
Tag = make_ref(),
- SendState = mcall_send_requests(Tag, Ns, M, F, A, T),
+ Timeout = timeout_value(T),
+ SendState = mcall_send_requests(Tag, Ns, M, F, A, Timeout),
mcall_receive_replies(Tag, SendState)
catch
error:NotIErr when NotIErr /= internal_error ->
@@ -531,6 +728,74 @@ result(timeout, ReqId, Res, _Reason) ->
end
end.
+collection_result(timeout, _, _, ReqIdCollection, _, _) ->
+ Abandon = fun (ReqId, [Res|_Label]) when is_reference(ReqId),
+ is_reference(Res) ->
+ case call_abandon(ReqId) of
+ true ->
+ ok;
+ false ->
+ %% Spawn error or DOWN has arrived if
+ %% ReqId corresponds to an outstanding
+ %% request; fetch and drop it...
+ receive
+ {spawn_reply, ReqId, error, _} ->
+ ok;
+ {'DOWN', ReqId, process, _, _} ->
+ ok
+ after
+ 0 ->
+ ok %% Already handled...
+ end
+ end;
+ (_, _) ->
+ %% Invalid request id collection...
+ throw(badarg)
+ end,
+ try
+ maps:foreach(Abandon, ReqIdCollection)
+ catch
+ throw:badarg -> error({?MODULE, badarg})
+ end,
+ error({?MODULE, timeout});
+collection_result(Type, ReqId, ResultReason, ReqIdCol, WrapResponse, Delete) ->
+ ReqIdInfo = case Delete of
+ true -> maps:take(ReqId, ReqIdCol);
+ false -> {maps:get(ReqId, ReqIdCol), ReqIdCol}
+ end,
+ case ReqIdInfo of
+ {[Res|Label], NewReqIdCol} when is_reference(Res) ->
+ try
+ Result = result(Type, ReqId, Res, ResultReason),
+ Response = if WrapResponse -> {response, Result};
+ true -> Result
+ end,
+ {Response, Label, NewReqIdCol}
+ catch
+ Class:Reason ->
+ erlang:Class({Reason, Label, NewReqIdCol})
+ end;
+ _ ->
+ %% Invalid request id collection...
+ error({?MODULE, badarg})
+ end.
+
+timeout_value(infinity) ->
+ infinity;
+timeout_value(Timeout) when ?IS_VALID_TMO_INT(Timeout) ->
+ Timeout;
+timeout_value({abs, Timeout}) when is_integer(Timeout) ->
+ case Timeout - erlang:monotonic_time(millisecond) of
+ TMO when TMO < 0 ->
+ 0;
+ TMO when TMO > ?MAX_INT_TIMEOUT ->
+ error({?MODULE, badarg});
+ TMO ->
+ TMO
+ end;
+timeout_value(_) ->
+ error({?MODULE, badarg}).
+
deadline(infinity) ->
infinity;
deadline(?MAX_INT_TIMEOUT) ->
@@ -590,7 +855,7 @@ mcall_send_requests(Tag, Ns, M, F, A, Tmo) ->
mcall_send_requests(_Tag, [], M, F, A, RIDs, DL, local_call, NRs) ->
%% Timeout infinity and call on local node wanted;
- %% excecute local call in this process...
+ %% execute local call in this process...
LRes = mcall_local_call(M, F, A),
{ok, RIDs, #{local_call => LRes}, NRs, DL};
mcall_send_requests(_Tag, [], _M, _F, _A, RIDs, DL, _LC, NRs) ->
diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl
index 291af484a5..ae688ee717 100644
--- a/lib/kernel/src/erts_debug.erl
+++ b/lib/kernel/src/erts_debug.erl
@@ -256,6 +256,10 @@ size([H|T]=Term, Seen0, Sum0) ->
{Sum,Seen} = size(H, Seen1, Sum0+2),
size(T, Seen, Sum)
end;
+size({}, Seen0, Sum0) ->
+ %% Tuples of size 0 all points to a constant literal so we count
+ %% them as size zero
+ {Sum0,Seen0};
size(Tuple, Seen0, Sum0) when is_tuple(Tuple) ->
case remember_term(Tuple, Seen0) of
seen -> {Sum0,Seen0};
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 57d3add4cb..49ad387a3a 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -95,7 +95,7 @@
Size :: non_neg_integer(),
Delay :: non_neg_integer()}
| 'delayed_write' | {'read_ahead', Size :: pos_integer()}
- | 'read_ahead' | 'compressed'
+ | 'read_ahead' | 'compressed' | 'compressed_one'
| {'encoding', unicode:encoding()}
| sync.
-type deep_list() :: [char() | atom() | deep_list()].
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index b848e5ef75..723325bdfb 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -445,6 +445,10 @@ put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) ->
{error,_,_} ->
{stop,no_translation,
{error,{no_translation, InEncoding, OutEncoding}},
+ NewState};
+ {incomplete,_,_} ->
+ {stop,no_translation,
+ {error,{no_translation, InEncoding, OutEncoding}},
NewState}
end.
@@ -673,7 +677,7 @@ get_chars_apply(Mod, Func, XtraArg, S0, OutEnc,
end.
%% A hack that tries to inform the caller about the position where the
-%% error occured.
+%% error occurred.
invalid_unicode_error(Mod, Func, XtraArg, S) ->
try
{erl_scan,tokens,_Args} = XtraArg,
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index d3582f89e6..f53a9dca3e 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,16 +30,33 @@
-export([open/0, open/1, open/2, close/1]).
-export([listen/2, peeloff/2]).
-export([connect/3, connect/4, connect/5,
- connect_init/3, connect_init/4, connect_init/5]).
+ connect_init/3, connect_init/4, connect_init/5,
+ connectx_init/3, connectx_init/4,connectx_init/5]).
-export([eof/2, abort/2]).
-export([send/3, send/4, recv/1, recv/2]).
-export([error_string/1]).
-export([controlling_process/2]).
-type assoc_id() :: term().
+
-type option() ::
+ elementary_option() |
+ record_option().
+
+-type option_name() ::
+ elementary_option_name() |
+ record_option() |
+ ro_option().
+
+-type option_value() ::
+ elementary_option() |
+ record_option() |
+ ro_option().
+
+-type elementary_option() ::
{active, true | false | once | -32768..32767} |
{buffer, non_neg_integer()} |
+ {debug, boolean()} |
{dontroute, boolean()} |
{high_msgq_watermark, pos_integer()} |
{linger, {boolean(), non_neg_integer()}} |
@@ -49,33 +66,23 @@
{recbuf, non_neg_integer()} |
{reuseaddr, boolean()} |
{ipv6_v6only, boolean()} |
- {sctp_adaptation_layer, #sctp_setadaptation{}} |
- {sctp_associnfo, #sctp_assocparams{}} |
+ {sndbuf, non_neg_integer()} |
{sctp_autoclose, non_neg_integer()} |
- {sctp_default_send_param, #sctp_sndrcvinfo{}} |
- {sctp_delayed_ack_time, #sctp_assoc_value{}} |
{sctp_disable_fragments, boolean()} |
- {sctp_events, #sctp_event_subscribe{}} |
- {sctp_get_peer_addr_info, #sctp_paddrinfo{}} |
{sctp_i_want_mapped_v4_addr, boolean()} |
- {sctp_initmsg, #sctp_initmsg{}} |
{sctp_maxseg, non_neg_integer()} |
{sctp_nodelay, boolean()} |
- {sctp_peer_addr_params, #sctp_paddrparams{}} |
- {sctp_primary_addr, #sctp_prim{}} |
- {sctp_rtoinfo, #sctp_rtoinfo{}} |
- {sctp_set_peer_primary_addr, #sctp_setpeerprim{}} |
- {sctp_status, #sctp_status{}} |
- {sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
{tclass, non_neg_integer()} |
{ttl, non_neg_integer()} |
{recvtos, boolean()} |
{recvtclass, boolean()} |
{recvttl, boolean()}.
--type option_name() ::
+
+-type elementary_option_name() ::
active |
buffer |
+ debug |
dontroute |
high_msgq_watermark |
linger |
@@ -85,23 +92,11 @@
recbuf |
reuseaddr |
ipv6_v6only |
- sctp_adaptation_layer |
- sctp_associnfo |
sctp_autoclose |
- sctp_default_send_param |
- sctp_delayed_ack_time |
sctp_disable_fragments |
- sctp_events |
- sctp_get_peer_addr_info |
sctp_i_want_mapped_v4_addr |
- sctp_initmsg |
sctp_maxseg |
sctp_nodelay |
- sctp_peer_addr_params |
- sctp_primary_addr |
- sctp_rtoinfo |
- sctp_set_peer_primary_addr |
- sctp_status |
sndbuf |
tos |
tclass |
@@ -109,9 +104,27 @@
recvtos |
recvtclass |
recvttl.
+
+-type record_option() ::
+ {sctp_adaptation_layer, #sctp_setadaptation{}} |
+ {sctp_associnfo, #sctp_assocparams{}} |
+ {sctp_default_send_param, #sctp_sndrcvinfo{}} |
+ {sctp_delayed_ack_time, #sctp_assoc_value{}} |
+ {sctp_events, #sctp_event_subscribe{}} |
+ {sctp_initmsg, #sctp_initmsg{}} |
+ {sctp_peer_addr_params, #sctp_paddrparams{}} |
+ {sctp_primary_addr, #sctp_prim{}} |
+ {sctp_rtoinfo, #sctp_rtoinfo{}} |
+ {sctp_set_peer_primary_addr, #sctp_setpeerprim{}}.
+
+-type ro_option() ::
+ {sctp_get_peer_addr_info, #sctp_paddrinfo{}} |
+ {sctp_status, #sctp_status{}}.
+
-type sctp_socket() :: port().
--export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]).
+-export_type(
+ [assoc_id/0, option/0, option_name/0, option_value/0, sctp_socket/0]).
-spec open() -> {ok, Socket} | {error, inet:posix()} when
Socket :: sctp_socket().
@@ -357,11 +370,11 @@ do_connect(_S, _SockAddr, _Opts, _Timeout, _ConnWait) ->
badarg.
-do_connect(S, Addr, Port, Opts, Timeout, ConnWait)
+do_connect(S, Addr, Service, Opts, Timeout, ConnWait)
when is_port(S) andalso is_list(Opts) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
- case Mod:getserv(Port) of
+ case Mod:getserv(Service) of
{ok,Port} ->
try inet:start_timer(Timeout) of
Timer ->
@@ -389,6 +402,177 @@ do_connect(_S, _Addr, _Port, _Opts, _Timeout, _ConnWait) ->
badarg.
+
+-spec connectx_init(Socket, SockAddrs, Opts) ->
+ {ok, assoc_id()} | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ SockAddrs:: [{inet:ip_address(), inet:port_number()} |
+ inet:family_address() |
+ socket:sockaddr_in() | socket:sockaddr_in6()],
+ Opts :: [option()].
+%%
+connectx_init(S, SockAddrs, Opts) ->
+ case do_connectx(S, SockAddrs, Opts) of
+ badarg ->
+ erlang:error(badarg, [S, SockAddrs, Opts]);
+ Result ->
+ Result
+ end.
+
+-spec connectx_init(Socket, Addrs, Port, Opts) ->
+ {ok, assoc_id()} | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Addrs :: [inet:ip_address() | inet:hostname()],
+ Port :: inet:port_number() | atom(),
+ Opts :: [option()].
+%%
+connectx_init(S, Addrs, Port, Opts) ->
+ connectx_init(S, Addrs, Port, Opts, infinity).
+
+-spec connectx_init(Socket, Addrs, Port, Opts, Timeout) ->
+ {ok, assoc_id()} | {error, inet:posix()} when
+ Socket :: sctp_socket(),
+ Addrs :: [inet:ip_address() | inet:hostname()],
+ Port :: inet:port_number() | atom(),
+ Opts :: [option()],
+ Timeout :: timeout().
+%%
+connectx_init(S, Addrs, Port, Opts, Timeout) ->
+ case do_connectx(S, Addrs, Port, Opts, Timeout) of
+ badarg ->
+ erlang:error(badarg, [S, Addrs, Port, Opts, Timeout]);
+ Result ->
+ Result
+ end.
+
+
+do_connectx(S, SockAddrs, Opts)
+ when is_port(S), is_list(SockAddrs), is_list(Opts) ->
+ case inet_db:lookup_socket(S) of
+ {ok, Mod} ->
+ case ensure_sockaddrs(SockAddrs) of
+ {SockAddrs_1, Port} ->
+ SockAddrs_2 = set_port(SockAddrs_1, Port),
+ Mod:connectx(S, SockAddrs_2, Opts);
+ Error1 ->
+ Error1
+ end;
+ {error, _} = Error2->
+ Error2
+ end;
+do_connectx(_S, _SockAddrs, _Opts) ->
+ badarg.
+
+do_connectx(S, Addrs, Service, Opts, Timeout)
+ when is_port(S), is_list(Addrs), is_list(Opts) ->
+ case inet_db:lookup_socket(S) of
+ {ok,Mod} ->
+ case Mod:getserv(Service) of
+ {ok,Port} ->
+ try inet:start_timer(Timeout) of
+ Timer ->
+ try
+ case getaddrs(Mod, Addrs, Timer) of
+ IPs when is_list(IPs) ->
+ Mod:connectx(S, IPs, Port, Opts);
+ Error1 ->
+ Error1
+ end
+ after
+ _ = inet:stop_timer(Timer)
+ end
+ catch
+ error:badarg ->
+ badarg
+ end;
+ {error, _} = Error2 ->
+ Error2
+ end;
+ {error, _} = Error3 ->
+ Error3
+ end;
+do_connectx(_S, _Addrs, _Port, _Opts, _Timeout) ->
+ badarg.
+
+ensure_sockaddrs(SockAddrs) ->
+ ensure_sockaddrs(SockAddrs, 0, []).
+%%
+ensure_sockaddrs([SockAddr | SockAddrs], Port, Acc) ->
+ case SockAddr of
+ {IP, P} when is_tuple(IP) ->
+ ensure_sockaddrs(SockAddrs, Port, [SockAddr | Acc], P);
+ {Family, {_, P}}
+ when Family =:= inet;
+ Family =:= inet6 ->
+ ensure_sockaddrs(SockAddrs, Port, [SockAddr | Acc], P);
+ #{family := Family}
+ when Family =:= inet;
+ Family =:= inet6 ->
+ SockAddr_1 = inet:ensure_sockaddr(SockAddr),
+ ensure_sockaddrs(
+ SockAddrs, Port, [SockAddr_1 | Acc],
+ maps:get(port, SockAddr_1, 0));
+ _ -> badarg
+ end;
+ensure_sockaddrs([], 0, _) ->
+ badarg;
+ensure_sockaddrs([], Port, Acc) ->
+ {lists:reverse(Acc), Port}.
+%%
+ensure_sockaddrs(SockAddrs, Port, Acc, P) ->
+ if
+ is_integer(P) ->
+ if
+ 0 < P ->
+ ensure_sockaddrs(SockAddrs, P, Acc);
+ P < 0 ->
+ badarg;
+ true ->
+ ensure_sockaddrs(SockAddrs, Port, Acc)
+ end;
+ true ->
+ badarg
+ end.
+
+set_port([SockAddr | SockAddrs], Port) ->
+ case SockAddr of
+ {IP, P} when is_tuple(IP) ->
+ set_port(
+ SockAddrs, Port, SockAddr, P,
+ fun () -> {IP, Port} end);
+ {Family, {Addr, P}} ->
+ set_port(
+ SockAddrs, Port, SockAddr, P,
+ fun () -> {Family, {Addr, Port}} end);
+ #{port := P} ->
+ set_port(
+ SockAddrs, Port, SockAddr, P,
+ fun () -> SockAddr#{port := Port} end)
+ end;
+set_port([], _Port) ->
+ [].
+%%
+set_port(SockAddrs, Port, SockAddr, P, NewSockAddrFun) ->
+ [case P of
+ Port -> SockAddr;
+ _ -> NewSockAddrFun()
+ end | set_port(SockAddrs, Port)].
+
+getaddrs(Mod, Addrs, Timer) ->
+ getaddrs(Mod, Addrs, Timer, []).
+%%
+getaddrs(Mod, [Addr | Addrs], Timer, Acc) ->
+ case Mod:getaddr(Addr, Timer) of
+ {ok, IP} ->
+ getaddrs(Mod, Addrs, Timer, [IP | Acc]);
+ {error, _} ->
+ badarg
+ end;
+getaddrs(_Mod, [], _Timer, Acc) ->
+ lists:reverse(Acc).
+
+
+
-spec eof(Socket, Assoc) -> ok | {error, Reason} when
Socket :: sctp_socket(),
Assoc :: #sctp_assoc_change{},
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 99d65c2929..1cba7fa624 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@
-type option() ::
{active, true | false | once | -32768..32767} |
{buffer, non_neg_integer()} |
+ {debug, boolean()} |
{delay_send, boolean()} |
{deliver, port | term} |
{dontroute, boolean()} |
@@ -78,6 +79,7 @@
-type option_name() ::
active |
buffer |
+ debug |
delay_send |
deliver |
dontroute |
@@ -161,7 +163,7 @@ connect(SockAddr, Opts) ->
-spec connect(Address, Port, Opts) -> {ok, Socket} | {error, Reason} when
Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
- Opts :: [connect_option()],
+ Opts :: [inet:inet_backend() | connect_option()],
Socket :: socket(),
Reason :: inet:posix();
(SockAddr, Opts, Timeout) -> {ok, Socket} | {error, Reason} when
@@ -193,8 +195,8 @@ connect(#{family := Fam} = SockAddr, Opts, Timeout)
{'EXIT', Reason} -> exit(Reason);
Error -> Error
end;
- {GenTcpMod, Opts} ->
- GenTcpMod:connect(SockAddr2, Opts, Timeout)
+ {GenTcpMod, Opts2} ->
+ GenTcpMod:connect(SockAddr2, Opts2, Timeout)
end.
diff --git a/lib/kernel/src/gen_tcp_socket.erl b/lib/kernel/src/gen_tcp_socket.erl
index 467041d92d..7f37e8414d 100644
--- a/lib/kernel/src/gen_tcp_socket.erl
+++ b/lib/kernel/src/gen_tcp_socket.erl
@@ -915,6 +915,12 @@ socket_setopt(Socket, DomainProps, Value) when is_list(DomainProps) ->
socket_setopt_value({socket,linger}, {OnOff, Linger}) ->
#{onoff => OnOff, linger => Linger};
+socket_setopt_value({socket,bindtodevice}, DeviceBin)
+ when is_binary(DeviceBin) ->
+ %% Currently:
+ %% prim_inet: Require that device is a binary()
+ %% socket: Require that device is a string()
+ binary_to_list(DeviceBin);
socket_setopt_value(_Opt, Value) -> Value.
@@ -1145,7 +1151,7 @@ call(Server, Call) ->
end.
stop_server(Server) ->
- try gen_statem:stop(Server) of
+ try gen_statem:stop(Server, {shutdown, closed}, infinity) of
_ -> ok
catch
_:_ -> ok
@@ -1463,7 +1469,7 @@ handle_event({call, From}, {setopts, Opts}, State, {P, D}) ->
%% we are in state 'recv' but are inactive is simply stored in the buffer.
%% If activated: active: false -> once | true | N > 0
%% We need to check if there is something in our buffers, and maybe deliver
- %% it to its owner. This is what we do here. This should only occure
+ %% it to its owner. This is what we do here. This should only occur
%% if we are in state connected (state 'recv' and in-active when data
%% arrives => put data in buffer and then enter state 'connected', since
%% we are in-active).
@@ -1768,9 +1774,12 @@ handle_shutdown2(Socket, NextState, How) ->
handle_unexpected(Type, Content, State, {P, _D}) ->
- warning_report([{socket, P#params.socket},
- {unknown_event, {Type, Content}},
- {state, State}]),
+ warning_msg("Received unexpected event:"
+ "~n Socket: ~p"
+ "~n State: ~p"
+ "~n Event Type: ~p"
+ "~n Content: ~p",
+ [P#params.socket, State, Type, Content]),
case Type of
{call, From} ->
{keep_state_and_data,
@@ -1785,9 +1794,12 @@ handle_closed(Type, Content, State, {P, _D}) ->
{keep_state_and_data,
[{reply, From, {error, closed}}]};
_ ->
- warning_report([{socket, P#params.socket},
- {unknown_event, {Type, Content}},
- {state, State}]),
+ warning_msg("Received unexpected event when closed:"
+ "~n Socket: ~p"
+ "~n State: ~p"
+ "~n Event Type: ~p"
+ "~n Content: ~p",
+ [P#params.socket, State, Type, Content]),
keep_state_and_data
end.
@@ -2854,8 +2866,8 @@ warning_msg(F, A) ->
error_report(Report) ->
error_logger:error_report(Report).
-warning_report(Report) ->
- error_logger:warning_report([{module, ?MODULE}|Report]).
+%% warning_report(Report) ->
+%% error_logger:warning_report([{module, ?MODULE}|Report]).
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 34567a578d..c652a7663f 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,17 +31,18 @@
-type option() ::
{active, true | false | once | -32768..32767} |
- {add_membership, {inet:ip_address(), inet:ip_address()}} |
+ {add_membership, membership()} |
{broadcast, boolean()} |
{buffer, non_neg_integer()} |
+ {debug, boolean()} |
{deliver, port | term} |
{dontroute, boolean()} |
- {drop_membership, {inet:ip_address(), inet:ip_address()}} |
+ {drop_membership, membership()} |
{header, non_neg_integer()} |
{high_msgq_watermark, pos_integer()} |
{low_msgq_watermark, pos_integer()} |
{mode, list | binary} | list | binary |
- {multicast_if, inet:ip_address()} |
+ {multicast_if, multicast_if()} |
{multicast_loop, boolean()} |
{multicast_ttl, non_neg_integer()} |
{priority, non_neg_integer()} |
@@ -64,6 +65,7 @@
active |
broadcast |
buffer |
+ debug |
deliver |
dontroute |
header |
@@ -103,7 +105,27 @@
-type socket() :: inet:socket().
--export_type([option/0, open_option/0, option_name/0, socket/0]).
+-type ip_multicast_if() :: inet:ip4_address().
+-type ip6_multicast_if() :: integer(). % interface index
+-type multicast_if() :: ip_multicast_if() | ip6_multicast_if().
+
+
+%% Note that for IPv4, the tuple with size 3 is *not*
+%% supported on all platforms.
+%% 'ifindex' defaults to zero (0) on platforms that
+%% supports the 3-tuple variant.
+-type ip_membership() :: {MultiAddress :: inet:ip4_address(), % multiaddr
+ Interface :: inet:ip4_address()} | % local addr
+ {MultiAddress :: inet:ip4_address(), % multiaddr
+ Address :: inet:ip4_address(), % local addr
+ IfIndex :: integer()}. % ifindex
+-type ip6_membership() :: {MultiAddress :: inet:ip6_address(), % multiaddr
+ IfIndex :: integer()}. % ifindex
+-type membership() :: ip_membership() | ip6_membership().
+
+-export_type([option/0, open_option/0, option_name/0, socket/0,
+ multicast_if/0, ip_multicast_if/0, ip6_multicast_if/0,
+ membership/0, ip_membership/0, ip6_membership/0]).
%% -- open ------------------------------------------------------------------
diff --git a/lib/kernel/src/gen_udp_socket.erl b/lib/kernel/src/gen_udp_socket.erl
index 505dfea4ef..5af11f0f1a 100644
--- a/lib/kernel/src/gen_udp_socket.erl
+++ b/lib/kernel/src/gen_udp_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2021-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -444,7 +444,7 @@ do_sendmsg(?MODULE_socket(_Server, Socket), SockAddr, IOV, Ctrl)
recv(Socket, Length) ->
recv(Socket, Length, infinity).
-%% This is a bit wierd. If two calls to recv is made with short intervalls
+%% This is a bit weird. If two calls to recv is made with short intervals
%% from different processes, with say timeout 10s and then 5s. The second
%% call will be postponed until the first has been processed, which can
%% take up to 10s. If the first times out (after 10s) the second is
@@ -839,7 +839,7 @@ socket_getopt_opt(Socket, Opt, Tag) ->
%% Its possible for *one* option to be mapped to several 'socket' options.
%% But, its *always* the first element in th elist that is the "real"
-%% option. This is the one used when *reading*. The other elemnts in the list
+%% option. This is the one used when *reading*. The other elements in the list
%% is basically side effect options, which is not used when reading.
socket_getopt_opts([{_Domain, _} = Opt|_], Socket, Tag) ->
socket_getopt_opt(Socket, Opt, Tag);
@@ -1703,7 +1703,7 @@ handle_recv_error(P, D, ActionsR, Reason) ->
{next_state, 'open',
{P, recv_stop(D#{active := false})}, reverse(ActionsR_1)};
_ ->
- %% Temporary ... need somthing better here...maybe
+ %% Temporary ... need something better here...maybe
{next_state, 'open',
{P, recv_stop(D#{active := false})}, reverse(ActionsR_1)}
end.
@@ -1850,6 +1850,9 @@ deliver_data(#{addr := #{family := Fam, addr := Addr, port := Port},
Data = deliver_data_mode(IOV, Mode),
Ctrl2 = ctrl2ancdata(Ctrl),
{Addr, Port, Ctrl2, Data};
+deliver_data({#{family := unspec, addr := Addr}, <<Data/binary>>}, Mode)
+ when is_binary(Addr) ->
+ {{unspec, Addr}, 0, undefined, deliver_data_mode(Data, Mode)};
deliver_data({Unspec, <<Data/binary>>}, Mode) when is_binary(Unspec) ->
{{unspec, Unspec}, 0, undefined, deliver_data_mode(Data, Mode)}.
%% deliver_data(_Arg1, _Arg2) ->
@@ -1885,17 +1888,17 @@ ctrl2ancdata(CTRL) ->
ctrl2ancdata([], AncData) ->
lists:reverse(AncData);
ctrl2ancdata([#{level := ip,
- type := tos,
- value := TOS,
+ type := TOS,
+ value := Value,
data := _Data}| CTRL],
- AncData) ->
- ctrl2ancdata(CTRL, [{tos, TOS}|AncData]);
+ AncData) when (TOS =:= tos) orelse (TOS =:= recvtos) ->
+ ctrl2ancdata(CTRL, [{tos, Value}|AncData]);
ctrl2ancdata([#{level := ip,
- type := ttl,
- value := TTL,
+ type := TTL,
+ value := Value,
data := _Data}| CTRL],
- AncData) ->
- ctrl2ancdata(CTRL, [{ttl, TTL}|AncData]);
+ AncData) when (TTL =:= ttl) orelse (TTL =:= recvttl) ->
+ ctrl2ancdata(CTRL, [{ttl, Value}|AncData]);
ctrl2ancdata([#{level := ipv6,
type := tclass,
value := TClass,
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 17d7b0f396..4854ed2900 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -36,11 +36,12 @@
set_lock/1, set_lock/2, set_lock/3,
del_lock/1, del_lock/2,
trans/2, trans/3, trans/4,
- random_exit_name/3, random_notify_name/3, notify_all_name/3]).
+ random_exit_name/3, random_notify_name/3, notify_all_name/3,
+ disconnect/0]).
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
- code_change/3, resolve_it/4]).
+ code_change/3, resolve_it/4, get_locker/0]).
-export([info/0]).
@@ -92,11 +93,22 @@
%% Vsn 7 - propagate global versions between nodes, so we always know
%% versions of known nodes
%% - optional "prevent overlapping partitions" fix supported
+%% Vsn 8 - "verify connection" part of the protocol preventing
+%% deadlocks in connection setup due to locker processes
+%% being out of sync
+%% - "prevent overlapping partitions" fix also for systems
+%% configured to use global groups
%% Current version of global does not support vsn 4 or earlier.
--define(vsn, 7).
+-define(vsn, 8).
+%% Version when the "verify connection" part of the protocol
+%% was introduced.
+-define(verify_connect_vsn, 8).
+%% Version where "prevent overlapping partitions" fix for global groups
+%% was introduced.
+-define(gg_pop_vsn, 8).
%% Version when the "prevent overlapping partitions" fix was introduced.
-define(pop_vsn, 7).
%% Version when the "propagate global protocol versions" feature
@@ -143,7 +155,9 @@
%% protocol version as value
{pending, node()} => non_neg_integer(),
%% Node currently being removed
- {removing, node()} => yes
+ {removing, node()} => yes,
+ %% Connection id of connected nodes
+ {connection_id, node()} => integer()
},
synced = [] :: [node()],
resolvers = [],
@@ -275,9 +289,9 @@ register_name(Name, Pid, Method0) when is_pid(Pid) ->
Fun = fun(Nodes) ->
case (where(Name) =:= undefined) andalso check_dupname(Name, Pid) of
true ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {register, Name, Pid, Method}),
+ _ = gen_server:multi_call(Nodes,
+ global_name_server,
+ {register, Name, Pid, Method}),
yes;
_ ->
no
@@ -297,7 +311,7 @@ check_dupname(Name, Pid) ->
_ ->
S = "global: ~w registered under several names: ~tw\n",
Names = [Name | [Name1 || {_Pid, Name1} <- PidNames]],
- error_logger:error_msg(S, [Pid, Names]),
+ logger:log(error, S, [Pid, Names]),
false
end
end.
@@ -310,9 +324,9 @@ unregister_name(Name) ->
ok;
_ ->
Fun = fun(Nodes) ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {unregister, Name}),
+ _ = gen_server:multi_call(Nodes,
+ global_name_server,
+ {unregister, Name}),
ok
end,
?trace({unregister_name, self(), Name}),
@@ -332,9 +346,9 @@ re_register_name(Name, Pid) when is_pid(Pid) ->
re_register_name(Name, Pid, Method0) when is_pid(Pid) ->
Method = allow_tuple_fun(Method0),
Fun = fun(Nodes) ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {register, Name, Pid, Method}),
+ _ = gen_server:multi_call(Nodes,
+ global_name_server,
+ {register, Name, Pid, Method}),
yes
end,
?trace({re_register_name, self(), Name, Pid, Method}),
@@ -368,10 +382,10 @@ register_name_external(Name, Pid, Method) when is_pid(Pid) ->
Fun = fun(Nodes) ->
case where(Name) of
undefined ->
- gen_server:multi_call(Nodes,
- global_name_server,
- {register_ext, Name, Pid,
- Method, node()}),
+ _ = gen_server:multi_call(Nodes,
+ global_name_server,
+ {register_ext, Name, Pid,
+ Method, node()}),
yes;
_Pid -> no
end
@@ -432,7 +446,7 @@ del_lock(Id) ->
Nodes :: [node()].
del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) ->
?trace({del_lock, {me,self()}, Id, {nodes,Nodes}}),
- gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
+ _ = gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
true.
-type trans_fun() :: function() | {module(), atom()}.
@@ -471,6 +485,11 @@ trans(Id, Fun, Nodes, Retries) ->
info() ->
gen_server:call(global_name_server, info, infinity).
+-spec disconnect() -> [node()].
+
+disconnect() ->
+ gen_server:call(global_name_server, disconnect, infinity).
+
%%%-----------------------------------------------------------------
%%% Call-back functions from gen_server
%%%-----------------------------------------------------------------
@@ -479,6 +498,40 @@ info() ->
init([]) ->
process_flag(trap_exit, true),
+
+ %% Monitor all 'nodeup'/'nodedown' messages of visible nodes.
+ %% In case
+ %%
+ %% * no global group is configured, we use these as is. This
+ %% way we know that 'nodeup' comes before any traffic from
+ %% the node on the newly established connection and 'nodedown'
+ %% comes after any traffic on this connection from the node.
+ %%
+ %% * global group is configured, we ignore 'nodeup' and instead
+ %% rely on 'group_nodeup' messages passed by global_group and
+ %% filter 'nodedown' based on if the node is part of our group
+ %% or not. We need to be prepared for traffic from the node
+ %% on the newly established connection arriving before the
+ %% 'group_nodeup'. 'nodedown' will however not arrive until
+ %% all traffic from the node on this connection has arrived.
+ %%
+ %% In case a connection goes down and then up again, the
+ %% 'nodedown' for the old connection is nowadays guaranteed to
+ %% be delivered before the 'nodeup' for the new connection.
+ %%
+ %% By keeping track of connection_id for all connections we
+ %% can differentiate between different instances of connections
+ %% to the same node.
+ ok = net_kernel:monitor_nodes(true, #{connection_id => true}),
+
+ %% There are most likely no connected nodes at this stage,
+ %% but check to make sure...
+ Known = lists:foldl(fun ({N, #{connection_id := CId}}, Cs) ->
+ Cs#{{connection_id, N} => CId}
+ end,
+ #{},
+ nodes(visible, #{connection_id => true})),
+
_ = ets:new(global_locks, [set, named_table, protected]),
_ = ets:new(global_names, [set, named_table, protected,
{read_concurrency, true}]),
@@ -487,6 +540,7 @@ init([]) ->
_ = ets:new(global_pid_names, [bag, named_table, protected]),
_ = ets:new(global_pid_ids, [bag, named_table, protected]),
_ = ets:new(global_lost_connections, [set, named_table, protected]),
+ _ = ets:new(global_node_resources, [set, named_table, protected]),
%% This is for troubleshooting only.
DoTrace = os:getenv("GLOBAL_HIGH_LEVEL_TRACE") =:= "TRUE",
@@ -498,24 +552,37 @@ init([]) ->
no_trace
end,
- Ca = case init:get_argument(connect_all) of
- {ok, [["false"]]} ->
- false;
- _ ->
- true
+ Ca = case application:get_env(kernel, connect_all) of
+ {ok, CaBool} when is_boolean(CaBool) ->
+ CaBool;
+ {ok, CaInvalid} ->
+ error({invalid_parameter_value, connect_all, CaInvalid});
+ undefined ->
+ CaBool = case init:get_argument(connect_all) of
+ {ok, [["false" | _] | _]} ->
+ false;
+ _ ->
+ true
+ end,
+ ok = application:set_env(kernel, connect_all, CaBool,
+ [{timeout, infinity}]),
+ CaBool
end,
+
POP = case application:get_env(kernel,
prevent_overlapping_partitions) of
- {ok, Bool} when Bool == true; Bool == false ->
- Bool;
- {ok, Invalid} ->
+ {ok, PopBool} when is_boolean(PopBool) ->
+ PopBool;
+ {ok, PopInvalid} ->
error({invalid_parameter_value,
prevent_overlapping_partitions,
- Invalid});
+ PopInvalid});
undefined ->
- false
+ true
end,
+
S = #state{the_locker = start_the_locker(DoTrace),
+ known = Known,
trace = T0,
the_registrar = start_the_registrar(),
conf = #conf{connect_all = Ca,
@@ -579,6 +646,16 @@ init([]) ->
%% which makes it possible to discard those messages and cancel the
%% corresponding lock.
%%
+%% - The lockers begin locking operations as soon as the init_connect
+%% messages has been exchanged and do not wait for init_connect_ack.
+%% They could even complete before init_connect_ack messages are
+%% received. The init_connect_ack messages are only there to confirm
+%% that both nodes has the same view of which connect session is
+%% ongoing. If lockers get out of sync, the lock will not be able
+%% to be aquired on both nodes. The out of sync lock operation will
+%% be detected when the init_connect_ack message is received and the
+%% operation can be cancelled and then restarted.
+%%
%% Suppose nodes A and B connect, and C is connected to A.
%% Here's the algorithm's flow:
%%
@@ -588,6 +665,8 @@ init([]) ->
%% TheLocker ! {nodeup, ..., Node, ...} (there is one locker per node)
%% B ! {init_connect, ..., {..., TheLockerAtA, ...}}
%% << {init_connect, TheLockerAtB}
+%% B ! {init_connect_ack, ...}
+%% << {init_connect_ack, ...}
%% [The lockers try to set the lock]
%% << {lock_is_set, B, ...}
%% [Now, lock is set in both partitions]
@@ -598,6 +677,10 @@ init([]) ->
%% << {resolved, B, ResolvedB, KnownAtB, ...}
%% C ! {new_nodes, ResolvedAandB, [B]}
%%
+%% When cancelling a connect, also the remote node is nowadays also
+%% informed using:
+%% B ! {cancel_connect, ...}
+%%
%% Node C
%% ------
%% << {new_nodes, ResolvedOps, NewNodes}
@@ -744,6 +827,32 @@ handle_call(get_names_ext, _From, S) ->
handle_call(info, _From, S) ->
{reply, S, S};
+handle_call(disconnect, _From, #state{known = Known} = S0) ->
+ %% Disconnect from all nodes global knows of without
+ %% sending any lost_connection messages...
+ Nodes = maps:fold(fun ({connection_id, N}, _, Ns) when is_atom(N) ->
+ case global_group:participant(N) of
+ false ->
+ Ns;
+ true ->
+ ?trace({'####', disconnect, {node,N}}),
+ net_kernel:async_disconnect(N),
+ [N|Ns]
+ end;
+ (_, _, Ns) ->
+ Ns
+ end, [], Known),
+ S1 = lists:foldl(fun (N, SAcc0) ->
+ receive {nodedown, N, I} -> ok end,
+ ?trace({'####', nodedown, {node,N,I}}),
+ SAcc1 = trace_message(SAcc0, {nodedown, N, I}, []),
+ SAcc2 = handle_nodedown(N, SAcc1, ignore_node),
+ NewKnown = maps:remove({connection_id, N},
+ SAcc2#state.known),
+ SAcc2#state{known = NewKnown}
+ end, S0, Nodes),
+ {reply, Nodes, S1};
+
%% "High level trace". For troubleshooting only.
handle_call(high_level_trace_start, _From, S) ->
S#state.the_locker ! {do_trace, true},
@@ -761,10 +870,10 @@ handle_call(stop, _From, S) ->
{stop, normal, stopped, S};
handle_call(Request, From, S) ->
- error_logger:warning_msg("The global_name_server "
- "received an unexpected message:\n"
- "handle_call(~tp, ~tp, _)\n",
- [Request, From]),
+ logger:log(warning, "The global_name_server "
+ "received an unexpected message:\n"
+ "handle_call(~tp, ~tp, _)\n",
+ [Request, From]),
{noreply, S}.
%%========================================================================
@@ -793,7 +902,7 @@ handle_cast({init_connect, Vsn, Node, InitMsg}, S0) ->
_ ->
Txt = io_lib:format("Illegal global protocol version ~p Node: ~p\n",
[Vsn, Node]),
- error_logger:info_report(lists:flatten(Txt)),
+ logger:log(info, lists:flatten(Txt)),
S0
end,
{noreply, S};
@@ -904,18 +1013,22 @@ handle_cast({new_nodes, Node, Ops, Names_ext, Nodes, ExtraInfo}, S) ->
%%
%% We are in sync with this node (from the other node's known world).
%%========================================================================
-handle_cast({in_sync, Node, _IsKnown}, #state{known = Known} = S) ->
+handle_cast({in_sync, Node, _IsKnown}, #state{known = Known,
+ synced = Synced} = S0) ->
%% Sent from global_name_server at Node (in the other partition).
?trace({'####', in_sync, {Node, _IsKnown}}),
- lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S#state.syncers),
- NewS = cancel_locker(Node, S, get({sync_tag_my, Node})),
- reset_node_state(Node),
- NSynced = case lists:member(Node, Synced = NewS#state.synced) of
+ lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S0#state.syncers),
+ NSynced = case lists:member(Node, Synced) of
true -> Synced;
false -> [Node | Synced]
end,
- {noreply, NewS#state{known = maps:remove({pending, Node}, Known),
- synced = NSynced}};
+ S1 = S0#state{known = maps:remove({pending, Node}, Known),
+ synced = NSynced},
+ %% {pending, Node} removed, i.e., we wont send a cancel_connect
+ %% message to Node in cancel_locker()...
+ S2 = cancel_locker(Node, S1, get({sync_tag_my, Node})),
+ reset_node_state(Node),
+ {noreply, S2};
%% Called when Pid on other node crashed
handle_cast({async_del_name, _Name, _Pid}, S) ->
@@ -931,15 +1044,26 @@ handle_cast({async_del_lock, _ResourceId, _Pid}, S) ->
%% R14A nodes and later do not send async_del_lock messages.
{noreply, S};
+handle_cast({lock_set, Pid, _Set, _HisKnown, MyTag} = Message, S) ->
+ #state{the_locker = Locker} = S,
+ Node = node(Pid),
+ case get({sync_tag_my, Node}) of
+ MyTag ->
+ Locker ! Message,
+ ok;
+ _NewMyTag ->
+ ok
+ end,
+ {noreply, S};
handle_cast({lock_set, _Pid, _Set, _HisKnown} = Message, S) ->
#state{the_locker = Locker} = S,
Locker ! Message,
{noreply, S};
handle_cast(Request, S) ->
- error_logger:warning_msg("The global_name_server "
- "received an unexpected message:\n"
- "handle_cast(~tp, _)\n", [Request]),
+ logger:log(warning, "The global_name_server "
+ "received an unexpected message:\n"
+ "handle_cast(~tp, _)\n", [Request]),
{noreply, S}.
%%========================================================================
@@ -960,77 +1084,106 @@ handle_info({'EXIT', Pid, _Reason}, S) when is_pid(Pid) ->
Syncers = lists:delete(Pid, S#state.syncers),
{noreply, S#state{syncers = Syncers}};
-handle_info({nodedown, Node}, S) when Node =:= S#state.node_name ->
+handle_info({nodedown, Node, _Info}, S) when Node =:= S#state.node_name ->
%% Somebody stopped the distribution dynamically - change
%% references to old node name (Node) to new node name ('nonode@nohost')
{noreply, change_our_node_name(node(), S)};
-handle_info({nodedown, Node}, S0) ->
- ?trace({'####', nodedown, {node,Node}}),
- S1 = trace_message(S0, {nodedown, Node}, []),
- S = handle_nodedown(Node, S1, disconnected),
- {noreply, S};
+handle_info({nodedown, Node, Info}, S0) ->
+ ?trace({'####', nodedown, {node,Node, Info}}),
+ S1 = trace_message(S0, {nodedown, Node, Info}, []),
+ NodeDownType = case global_group:participant(Node) of
+ true -> disconnected;
+ false -> ignore_node
+ end,
+ S2 = handle_nodedown(Node, S1, NodeDownType),
+ Known = maps:remove({connection_id, Node}, S2#state.known),
+ {noreply, S2#state{known = Known}};
handle_info({extra_nodedown, Node}, S0) ->
?trace({'####', extra_nodedown, {node,Node}}),
S1 = trace_message(S0, {extra_nodedown, Node}, []),
- S = handle_nodedown(Node, S1, disconnected),
- {noreply, S};
+ NodeDownType = case global_group:participant(Node) of
+ true -> disconnected;
+ false -> ignore_node
+ end,
+ %% Syncers wont notice this unless we send them
+ %% a nodedown...
+ lists:foreach(fun(Pid) -> Pid ! {nodedown, Node} end, S1#state.syncers),
+ S2 = handle_nodedown(Node, S1, NodeDownType),
+ Known = maps:remove({connection_id, Node}, S2#state.known),
+ {noreply, S2#state{known = Known}};
+
+handle_info({group_nodedown, Node, CId},
+ #state{known = Known,
+ conf = #conf{connect_all = CA,
+ prevent_over_part = POP}} = S0) ->
+ %% Node is either not part of our group or its global_group
+ %% configuration is not in sync with our configuration...
+ ?trace({'####', group_nodedown, {node,Node}}),
+ S1 = trace_message(S0, {group_nodedown, Node, CId}, []),
+ S = case maps:get({connection_id, Node}, Known, not_connected) of
+ CId ->
+ %% We cannot rely on 'DOWN' messages for locks and
+ %% names on this node since the connection can remain
+ %% up. Explicitly take care of them...
+ S2 = delete_node_resources(Node, S1),
+
+ %% Syncers wont notice this unless we send them
+ %% a nodedown...
+ lists:foreach(fun(Pid) -> Pid ! {nodedown, Node} end,
+ S2#state.syncers),
+ NodeDownType = case (CA andalso POP
+ andalso global_group:member(Node)) of
+ false -> ignore_node;
+ true -> disconnected
+ end,
+ handle_nodedown(Node, S2, NodeDownType);
-handle_info({ignore_node, Node}, S0) ->
- %% global_group wants us to ignore this node...
- ?trace({'####', ignore_node, {node,Node}}),
- S1 = trace_message(S0, {ignore_node, Node}, []),
- S = handle_nodedown(Node, S1, ignore_node),
+ _ ->
+ %% Corresponding connection no longer exist; ignore it...
+ S1
+ end,
{noreply, S};
-handle_info({nodeup, Node}, S) when Node =:= node() ->
+handle_info({nodeup, Node, _Info}, S) when Node =:= node() ->
?trace({'####', local_nodeup, {node, Node}}),
%% Somebody started the distribution dynamically - change
%% references to old node name ('nonode@nohost') to Node.
{noreply, change_our_node_name(Node, S)};
-handle_info({nodeup, _Node},
- #state{conf = #conf{connect_all = false}} = S) ->
- {noreply, S};
-
-handle_info({nodeup, Node}, S0) ->
- IsKnown = maps:is_key(Node, S0#state.known) or
- %% This one is only for double nodeups (shouldn't occur!)
- lists:keymember(Node, 1, S0#state.resolvers),
- ?trace({'####', nodeup, {node,Node}, {isknown,IsKnown}}),
- S1 = trace_message(S0, {nodeup, Node}, []),
- case IsKnown of
- true ->
- {noreply, S1};
- false ->
- resend_pre_connect(Node),
-
- %% erlang:unique_integer([monotonic]) is used as a tag to
- %% separate different synch sessions
- %% from each others. Global could be confused at bursty nodeups
- %% because it couldn't separate the messages between the different
- %% synch sessions started by a nodeup.
- MyTag = erlang:unique_integer([monotonic]),
- put({sync_tag_my, Node}, MyTag),
- ?trace({sending_nodeup_to_locker, {node,Node},{mytag,MyTag}}),
- S1#state.the_locker ! {nodeup, Node, MyTag},
-
- %% In order to be compatible with unpatched R7 a locker
- %% process was spawned. Vsn 5 is no longer compatible with
- %% vsn 3 nodes, so the locker process is no longer needed.
- %% The permanent locker takes its place.
- NotAPid = no_longer_a_pid,
- Locker = {locker, NotAPid, S1#state.known, S1#state.the_locker},
- InitC = {init_connect, {?vsn, MyTag}, node(), Locker},
- Rs = S1#state.resolvers,
- ?trace({casting_init_connect, {node,Node},{initmessage,InitC},
- {resolvers,Rs}}),
- gen_server:cast({global_name_server, Node}, InitC),
- Resolver = start_resolver(Node, MyTag),
- S = trace_message(S1, {new_resolver, Node}, [MyTag, Resolver]),
- {noreply, S#state{resolvers = [{Node, MyTag, Resolver} | Rs]}}
- end;
+handle_info({nodeup, Node, #{connection_id := CId}},
+ #state{known = Known,
+ conf = #conf{connect_all = false}} = S) ->
+ {noreply, S#state{known = Known#{{connection_id, Node} => CId}}};
+
+handle_info({nodeup, Node, #{connection_id := CId}},
+ #state{known = Known} = S0) ->
+ ?trace({'####', nodeup, {node,Node}}),
+ S1 = S0#state{known = Known#{{connection_id, Node} => CId}},
+ S2 = trace_message(S1, {nodeup, Node}, []),
+ S3 = case global_group:group_configured() of
+ false ->
+ handle_nodeup(Node, S2);
+ true ->
+ %% We will later get a 'group_nodeup' message if
+ %% the node is in our group, and has a group
+ %% configuration that is in sync with our
+ %% configuration...
+ S2
+ end,
+ {noreply, S3};
+
+handle_info({group_nodeup, Node, CId}, #state{known = Known} = S0) ->
+ %% This message may arrive after other traffic from Node
+ %% on the current connection...
+ ?trace({'####', group_nodeup, {node,Node,CId}}),
+ S1 = trace_message(S0, {group_nodeup, Node, CId}, []),
+ S2 = case maps:get({connection_id, Node}, Known, not_connected) of
+ CId -> handle_nodeup(Node, S1);
+ _ -> S1 %% Late group_nodeup; connection has gone down...
+ end,
+ {noreply, S2};
handle_info({whereis, Name, From}, S) ->
_ = do_whereis(Name, From),
@@ -1079,30 +1232,35 @@ handle_info({lost_connection, NodeA, XCreationA, OpIdA, NodeB} = Msg,
NodeA
end,
- case is_node_potentially_known(RmNode, S0) of
+ case is_node_potentially_known(RmNode, S0)
+ andalso global_group:participant(RmNode) of
false ->
S0;
true ->
- case node_vsn(RmNode, S0) of
- Vsn when Vsn < ?pop_vsn ->
- erlang:disconnect_node(RmNode),
- error_logger:warning_msg(
- "'global' at node ~p disconnected old "
- "node ~p in order to prevent overlapping "
- "partitions",
- [node(), RmNode]),
- ok;
- _Vsn ->
- gns_volatile_send(RmNode,
- {remove_connection, node()}),
- error_logger:warning_msg(
- "'global' at node ~p requested disconnect "
- "from node ~p in order to prevent "
- "overlapping partitions",
- [node(), RmNode]),
- ok
- end,
- handle_nodedown(RmNode, S0, remove_connection)
+ {NDType, What} =
+ case node_vsn(RmNode, S0) of
+ Vsn when Vsn < ?pop_vsn ->
+ net_kernel:async_disconnect(RmNode),
+ {remove_connection, "disconnected old"};
+ Vsn ->
+ gns_volatile_send(RmNode,
+ {remove_connection,
+ node()}),
+ case global_group:member(RmNode)
+ andalso Vsn >= ?gg_pop_vsn of
+ true ->
+ {ignore_node,
+ "excluded global group member"};
+ false ->
+ {remove_connection,
+ "requested disconnect from"}
+ end
+ end,
+ logger:log(warning,
+ "'global' at node ~p ~s node ~p in order "
+ "to prevent overlapping partitions",
+ [node(), What, RmNode]),
+ handle_nodedown(RmNode, S0, NDType)
end
end,
@@ -1123,15 +1281,58 @@ handle_info({remove_connection, Node}, S0) ->
false ->
S0;
true ->
- erlang:disconnect_node(Node),
- S1 = handle_nodedown(Node, S0, remove_connection),
- error_logger:warning_msg(
- "'global' at node ~p disconnected node ~p in order to "
- "prevent overlapping partitions", [node(), Node]),
+ {NDType, What}
+ = case global_group:member(Node) of
+ true ->
+ global_group ! {disconnect_node, Node},
+ {ignore_node, "excluded global group member"};
+ false ->
+ net_kernel:async_disconnect(Node),
+ {remove_connection, "disconnected"}
+ end,
+ S1 = handle_nodedown(Node, S0, NDType),
+ logger:log(warning,
+ "'global' at node ~p ~s node ~p in order to "
+ "prevent overlapping partitions",
+ [node(), What, Node]),
S1
end,
{noreply, S2};
+handle_info({cancel_connect, Node, MyTag}, S0) ->
+ %% An ongoing connect was canceled by the other side...
+ %%
+ %% Message introduced in protocol version ?verify_connect_vsn
+
+ S3 = case get({sync_tag_my, Node}) of
+ MyTag ->
+ S1 = cancel_locker(Node, S0, MyTag),
+ reset_node_state(Node),
+ S2 = S1#state{known = maps:remove({pending, Node},
+ S1#state.known)},
+ restart_connect(Node, MyTag, S2);
+ _ ->
+ S0
+ end,
+ {noreply, S3};
+
+handle_info({init_connect_ack, Node, HisMyTag, HisHisTag}, S0) ->
+ %% Message introduced in protocol version ?verify_connect_vsn
+
+ MyMyTag = get({sync_tag_my, Node}),
+ MyHisTag = get({sync_tag_his, Node}),
+ S1 = case MyMyTag =:= HisMyTag andalso MyHisTag =:= HisHisTag of
+ true ->
+ S0;
+ false ->
+ %% Connection attempt out of sync; cancel
+ %% this attempt and start over...
+
+ send_cancel_connect_message(Node, HisHisTag),
+ restart_connect(Node, MyMyTag, S0)
+ end,
+ {noreply, S1};
+
handle_info({prepare_shutdown, From, Ref}, S0) ->
%% Prevent lost_connection messages being sent due to
%% connections being taken down during the shutdown...
@@ -1171,14 +1372,15 @@ handle_info({trace_message, M, X}, S) ->
{noreply, trace_message(S, M, X)};
handle_info({'DOWN', MonitorRef, process, _Pid, _Info}, S0) ->
+ delete_node_resource_info(MonitorRef),
S1 = delete_lock(MonitorRef, S0),
S = del_name(MonitorRef, S1),
{noreply, S};
handle_info(Message, S) ->
- error_logger:warning_msg("The global_name_server "
- "received an unexpected message:\n"
- "handle_info(~tp, _)\n", [Message]),
+ logger:log(warning, "The global_name_server "
+ "received an unexpected message:\n"
+ "handle_info(~tp, _)\n", [Message]),
{noreply, S}.
@@ -1188,6 +1390,47 @@ handle_info(Message, S) ->
%%========================================================================
%%========================================================================
+save_node_resource_info(Node, Mon) ->
+ NewRes = case ets:lookup(global_node_resources, Node) of
+ [] -> #{Mon => ok};
+ [{Node, OldRes}] -> OldRes#{Mon => ok}
+ end,
+ true = ets:insert(global_node_resources, [{Node, NewRes}, {Mon, Node}]),
+ ok.
+
+delete_node_resource_info(Mon) ->
+ case ets:lookup(global_node_resources, Mon) of
+ [] ->
+ ok;
+ [{Mon, Node}] ->
+ [{Node, OldRes}] = ets:lookup(global_node_resources, Node),
+ NewRes = maps:remove(Mon, OldRes),
+ true = ets:delete(global_node_resources, Mon),
+ case maps:size(NewRes) of
+ 0 ->
+ true = ets:delete(global_node_resources, Node),
+ ok;
+ _ ->
+ true = ets:insert(global_node_resources, {Node, NewRes}),
+ ok
+ end
+ end.
+
+delete_node_resources(Node, #state{} = State) ->
+ case ets:lookup(global_node_resources, Node) of
+ [] ->
+ State;
+ [{Node, Resources}] ->
+ true = ets:delete(global_node_resources, Node),
+ maps:fold(fun (Mon, ok, AccS0) ->
+ erlang:demonitor(Mon, [flush]),
+ true = ets:delete(global_node_resources, Mon),
+ AccS1 = delete_lock(Mon, AccS0),
+ del_name(Mon, AccS1)
+ end,
+ State, Resources)
+ end.
+
-define(HIGH_LEVEL_TRACE_INTERVAL, 500). % ms
wait_high_level_trace() ->
@@ -1270,7 +1513,8 @@ check_replies([{_Node, false=Reply} | _T], _Id, [_]) ->
check_replies([{_Node, false=Reply} | _T], Id, Replies) ->
TrueReplyNodes = [N || {N, true} <- Replies],
?trace({check_replies, {true_reply_nodes, TrueReplyNodes}}),
- gen_server:multi_call(TrueReplyNodes, global_name_server, {del_lock, Id}),
+ _ = gen_server:multi_call(
+ TrueReplyNodes, global_name_server, {del_lock, Id}),
Reply;
check_replies([], _Id, _Replies) ->
true.
@@ -1280,25 +1524,90 @@ check_replies([], _Id, _Replies) ->
%% Both nodes must have a lock before they are allowed to continue.
%%========================================================================
init_connect(Vsn, Node, InitMsg, HisTag, HisVsn,
- #state{resolvers = Resolvers, known = Known} = S) ->
+ #state{known = Known0} = S0) ->
%% It is always the responsibility of newer versions to understand
%% older versions of the protocol.
- put({prot_vsn, Node}, Vsn),
- put({sync_tag_his, Node}, HisTag),
- case lists:keyfind(Node, 1, Resolvers) of
- {Node, MyTag, _Resolver} ->
- MyTag = get({sync_tag_my, Node}), % assertion
- {locker, _NoLongerAPid, _HisKnown0, HisTheLocker} = InitMsg,
- ?trace({init_connect,{histhelocker,HisTheLocker}}),
- HisKnown = [],
- S#state.the_locker ! {his_the_locker, HisTheLocker,
- {Vsn,HisKnown}, S#state.known};
- false ->
- ?trace({init_connect,{pre_connect,Node},{histag,HisTag}}),
- put({pre_connect, Node}, {Vsn, InitMsg, HisTag})
- end,
- S#state{known = maps:put({pending, Node}, HisVsn, Known)}.
+ try
+ S1 = case maps:is_key({pending, Node}, Known0) of
+ false ->
+ S0;
+ true ->
+ %% This should not be possible unless global group has
+ %% been configured. We got an already ongoing connection
+ %% setup with Node and get yet another connection attempt
+ %% from Node.
+
+ if HisVsn < ?verify_connect_vsn ->
+ %% Old node that cannot handle this; give up...
+ erlang:disconnect_node(Node),
+ logger:log(error,
+ "'global' at node ~p got an out of "
+ "sync connection attempt from old "
+ "version ~p node ~p. Disconnecting "
+ "from it.", [node(), HisVsn, Node]),
+ throw({return, S0});
+
+ true ->
+ %% Cancel this new connection attempt as well
+ %% as the ongoing connection setup then restart
+ %% the connect by making a new connection
+ %% attempt...
+
+ send_cancel_connect_message(Node, HisTag),
+ MyOldTag = get({sync_tag_my, Node}),
+ restart_connect(Node, MyOldTag, S0)
+ end
+ end,
+ put({prot_vsn, Node}, Vsn),
+ put({sync_tag_his, Node}, HisTag),
+ case lists:keyfind(Node, 1, S1#state.resolvers) of
+ {Node, MyTag, _Resolver} ->
+ MyTag = get({sync_tag_my, Node}), % assertion
+ {locker, _NoLongerAPid, _HisKnown0, HisTheLocker} = InitMsg,
+ ?trace({init_connect,{histhelocker,HisTheLocker}}),
+ HisKnown = [],
+ S1#state.the_locker ! {his_the_locker, HisTheLocker,
+ {Vsn,HisKnown}, HisTag, MyTag},
+ if HisVsn < ?verify_connect_vsn ->
+ ok;
+ true ->
+ gns_volatile_send(Node,
+ {init_connect_ack, node(),
+ HisTag, MyTag})
+ end,
+ Known1 = S1#state.known,
+ S1#state{known = Known1#{{pending, Node} => HisVsn}};
+ false ->
+ ?trace({init_connect,{pre_connect,Node},{histag,HisTag}}),
+ put({pre_connect, Node}, {Vsn, InitMsg, HisTag}),
+ S1
+ end
+
+ catch
+ throw:{return, S} ->
+ S
+ end.
+
+restart_connect(Node, MyTag, S0) ->
+ %% We got a mismatch in connection setup; cancel
+ %% current connection setup and try again...
+
+ S1 = cancel_locker(Node, S0, MyTag),
+ reset_node_state(Node),
+ S2 = S1#state{known = maps:remove({pending, Node},
+ S1#state.known)},
+
+ if is_integer(MyTag) ->
+ %% Node is up from our perspective; start a new resolver
+ %% and send a new init_connect...
+ handle_nodeup(Node, S2);
+ true ->
+ %% Node is down from our prespective; wait until
+ %% global_group say Node is up by sending us a
+ %% group_nodeup message...
+ S2
+ end.
%%========================================================================
%% In the simple case, we'll get lock_is_set before we get exchange,
@@ -1348,13 +1657,15 @@ resolved(Node, HisResolved, HisKnown, Names_ext, S0) ->
HisKnownNodes = node_list(HisKnown),
sync_others(HisKnownNodes),
ExtraInfo = [{vsn,get({prot_vsn, Node})}, {lock, get({lock_id, Node})}],
- S = do_ops(Ops, node(), Names_ext, ExtraInfo, S0),
+ S1 = do_ops(Ops, node(), Names_ext, ExtraInfo, S0),
%% I am synced with Node, but not with HisKnown yet
- lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S#state.syncers),
- S3 = lists:foldl(fun(Node1, S1) ->
- F = fun(Tag) -> cancel_locker(Node1,S1,Tag) end,
- cancel_resolved_locker(Node1, F)
- end, S, HisKnownNodes),
+ lists:foreach(fun(Pid) -> Pid ! {synced, [Node]} end, S1#state.syncers),
+ S2 = lists:foldl(fun(CnclNode, AccS) ->
+ F = fun(Tag, CnclS) ->
+ cancel_locker(CnclNode, CnclS, Tag)
+ end,
+ cancel_resolved_locker(CnclNode, F, AccS)
+ end, S1, HisKnownNodes),
%% The locker that took the lock is asked to send
%% the {new_nodes, ...} message. This ensures that
%% {del_lock, ...} is received after {new_nodes, ...}
@@ -1374,21 +1685,26 @@ resolved(Node, HisResolved, HisKnown, Names_ext, S0) ->
end,
Known)
end,
- F = fun(Tag) -> cancel_locker(Node, S3, Tag, NewNodesF) end,
- S4 = cancel_resolved_locker(Node, F),
+ F = fun(Tag, CnclS) ->
+ cancel_locker(Node, CnclS, Tag, NewNodesF)
+ end,
+ S3 = cancel_resolved_locker(Node, F, S2),
%% See (*) below... we're node b in that description
- {AddedNodes, S5} = add_to_known(NewNodes, S4),
- S5#state.the_locker ! {add_to_known, AddedNodes},
- S6 = trace_message(S5, {added, AddedNodes},
+ {AddedNodes, S4} = add_to_known(NewNodes, S3),
+ S4#state.the_locker ! {add_to_known, AddedNodes},
+ S5 = trace_message(S4, {added, AddedNodes},
[{new_nodes, NewNodes}, {abcast, Known}, {ops,Ops}]),
- S6#state{synced = [Node | Synced]}.
+ S5#state{synced = [Node | Synced]}.
-cancel_resolved_locker(Node, CancelFun) ->
+cancel_resolved_locker(Node, CancelFun, #state{known = Known} = S0) ->
Tag = get({sync_tag_my, Node}),
?trace({calling_cancel_locker,Tag,get()}),
- S = CancelFun(Tag),
+ S1 = S0#state{known = maps:remove({pending, Node}, Known)},
+ %% {pending, Node} removed, i.e., we wont send a cancel_connect
+ %% message to Node in CancelFun()...
+ S2 = CancelFun(Tag, S1),
reset_node_state(Node),
- S#state{known = maps:remove({pending, Node}, S#state.known)}.
+ S2.
new_nodes(Ops, ConnNode, Names_ext, Nodes, ExtraInfo, S0) ->
%% (*) This one requires some thought...
@@ -1447,9 +1763,9 @@ resolver(Node, Tag) ->
resend_pre_connect(Node) ->
case erase({pre_connect, Node}) of
{Vsn, InitMsg, HisTag} ->
- gen_server:cast(self(),
+ gen_server:cast(self(),
{init_connect, {Vsn, HisTag}, Node, InitMsg});
- _ ->
+ _ ->
ok
end.
@@ -1507,6 +1823,7 @@ can_set_lock({ResourceId, LockRequesterId}) ->
insert_lock({ResourceId, LockRequesterId}=Id, Pid, PidRefs, S) ->
Ref = erlang:monitor(process, Pid),
+ save_node_resource_info(node(Pid), Ref),
true = ets:insert(global_pid_ids, {Pid, ResourceId}),
true = ets:insert(global_pid_ids, {Ref, ResourceId}),
Lock = {ResourceId, LockRequesterId, [{Pid,Ref} | PidRefs]},
@@ -1529,6 +1846,7 @@ handle_del_lock({ResourceId, LockReqId}, Pid, S0) ->
remove_lock(ResourceId, LockRequesterId, Pid, [{Pid,Ref}], Down, S0) ->
?trace({remove_lock_1, {id,ResourceId},{pid,Pid}}),
+ delete_node_resource_info(Ref),
true = erlang:demonitor(Ref, [flush]),
true = ets:delete(global_locks, ResourceId),
true = ets:delete_object(global_pid_ids, {Pid, ResourceId}),
@@ -1543,6 +1861,7 @@ remove_lock(ResourceId, LockRequesterId, Pid, PidRefs0, _Down, S) ->
?trace({remove_lock_2, {id,ResourceId},{pid,Pid}}),
PidRefs = case lists:keyfind(Pid, 1, PidRefs0) of
{Pid, Ref} ->
+ delete_node_resource_info(Ref),
true = erlang:demonitor(Ref, [flush]),
true = ets:delete_object(global_pid_ids,
{Ref, ResourceId}),
@@ -1611,8 +1930,8 @@ sync_other(Node, N) ->
sync_other(Node, N - 1);
{nodedown, Node} ->
?trace({missing_nodedown, {node, Node}}),
- error_logger:warning_msg("global: ~w failed to connect to ~w\n",
- [node(), Node]),
+ logger:log(warning, "'global' at ~w failed to connect to ~w\n",
+ [node(), Node]),
global_name_server ! {extra_nodedown, Node}
after 0 ->
gen_server:cast({global_name_server,Node}, {in_sync,node(),true})
@@ -1622,6 +1941,7 @@ sync_other(Node, N) ->
insert_global_name(Name, Pid, Method, FromPidOrNode, ExtraInfo, S) ->
Ref = erlang:monitor(process, Pid),
+ save_node_resource_info(node(Pid), Ref),
true = ets:insert(global_names, {Name, Pid, Method, Ref}),
true = ets:insert(global_pid_names, {Pid, Name}),
true = ets:insert(global_pid_names, {Ref, Name}),
@@ -1693,6 +2013,7 @@ delete_global_name2(Name, S) ->
end.
delete_global_name2(Name, Pid, Ref, S) ->
+ delete_node_resource_info(Ref),
true = erlang:demonitor(Ref, [flush]),
delete_global_name(Name, Pid),
?trace({delete_global_name,{item,Name},{pid,Pid}}),
@@ -1749,7 +2070,7 @@ delete_global_name(_Name, _Pid) ->
do_trace % bool()
}).
--record(him, {node, locker, vsn, my_tag}).
+-record(him, {node, locker, vsn, my_tag, his_tag}).
start_the_locker(DoTrace) ->
spawn_link(init_the_locker_fun(DoTrace)).
@@ -1768,7 +2089,7 @@ init_the_locker_fun(DoTrace) ->
loop_the_locker(S) ->
?trace({loop_the_locker,S}),
receive
- Message when element(1, Message) =/= nodeup ->
+ Message ->
the_locker_message(Message, S)
after 0 ->
Timeout =
@@ -1792,7 +2113,7 @@ loop_the_locker(S) ->
end,
S1 = S#multi{just_synced = false},
receive
- Message when element(1, Message) =/= nodeup ->
+ Message ->
the_locker_message(Message, S1)
after Timeout ->
case is_global_lock_set() of
@@ -1804,51 +2125,36 @@ loop_the_locker(S) ->
end
end.
-the_locker_message({his_the_locker, HisTheLocker, HisKnown0, _MyKnown}, S) ->
- ?trace({his_the_locker, HisTheLocker, {node,node(HisTheLocker)}}),
+the_locker_message({his_the_locker, HisTheLocker, HisKnown0, HisTag, MyTag} = _HtlMsg, S) ->
+ ?trace({the_locker, his_the_locker, {node,node(HisTheLocker)}, _HtlMsg}),
{HisVsn, _HisKnown} = HisKnown0,
true = HisVsn > 4,
- receive
- {nodeup, Node, MyTag} when node(HisTheLocker) =:= Node ->
- ?trace({the_locker_nodeup, {node,Node},{mytag,MyTag}}),
- Him = #him{node = node(HisTheLocker), my_tag = MyTag,
- locker = HisTheLocker, vsn = HisVsn},
- loop_the_locker(add_node(Him, S));
- {cancel, Node, _Tag, no_fun} when node(HisTheLocker) =:= Node ->
- loop_the_locker(S)
- after 60000 ->
- ?trace({nodeupnevercame, node(HisTheLocker)}),
- error_logger:error_msg("global: nodeup never came ~w ~w\n",
- [node(), node(HisTheLocker)]),
- loop_the_locker(S#multi{just_synced = false})
- end;
-the_locker_message({cancel, _Node, undefined, no_fun}, S) ->
- ?trace({cancel_the_locker, undefined, {node,_Node}}),
+ Him = #him{node = node(HisTheLocker), my_tag = MyTag,
+ his_tag = HisTag, locker = HisTheLocker, vsn = HisVsn},
+ loop_the_locker(add_node(Him, S));
+the_locker_message({cancel, _Node, undefined, no_fun} = _CMsg, S) ->
+ ?trace({cancel_the_locker, undefined, {node,_Node}, _CMsg}),
%% If we actually cancel something when a cancel message with the
%% tag 'undefined' arrives, we may be acting on an old nodedown,
%% to cancel a new nodeup, so we can't do that.
loop_the_locker(S);
-the_locker_message({cancel, Node, Tag, no_fun}, S) ->
+the_locker_message({cancel, Node, Tag, no_fun} = _CMsg, S) ->
?trace({the_locker, cancel, {multi,S}, {tag,Tag},{node,Node}}),
- receive
- {nodeup, Node, Tag} ->
- ?trace({cancelnodeup2, {node,Node},{tag,Tag}}),
- ok
- after 0 ->
- ok
- end,
- loop_the_locker(remove_node(Node, S));
-the_locker_message({lock_set, _Pid, false, _}, S) ->
- ?trace({the_locker, spurious, {node,node(_Pid)}}),
+ loop_the_locker(remove_node(Node, Tag, S));
+the_locker_message({lock_set, _Pid, false, _, _} = _Msg, S) ->
+ ?trace({the_locker, spurious, {node,node(_Pid)}, _Msg}),
+ loop_the_locker(S);
+the_locker_message({lock_set, _Pid, false, _} = _Msg, S) ->
+ ?trace({the_locker, spurious, {node,node(_Pid)}, _Msg}),
loop_the_locker(S);
-the_locker_message({lock_set, Pid, true, _HisKnown}, S) ->
+the_locker_message({lock_set, Pid, true, _HisKnown, MyTag} = _Msg, S) ->
Node = node(Pid),
- ?trace({the_locker, self(), spontaneous, {node,Node}}),
+ ?trace({the_locker, self(), spontaneous, {node,Node}, _Msg}),
case find_node_tag(Node, S) of
- {true, MyTag, HisVsn} ->
+ {true, MyTag, HisVsn, HisTag} ->
LockId = locker_lock_id(Pid, HisVsn),
{IsLockSet, S1} = lock_nodes_safely(LockId, [], S),
- send_lock_set(S1, IsLockSet, Pid, HisVsn),
+ send_lock_set(S1, IsLockSet, Pid, HisVsn, HisTag),
Known2 = [node() | S1#multi.known],
?trace({the_locker, spontaneous, {known2, Known2},
{node,Node}, {is_lock_set,IsLockSet}}),
@@ -1862,20 +2168,25 @@ the_locker_message({lock_set, Pid, true, _HisKnown}, S) ->
%% Should the other locker's node die,
%% global_name_server will receive nodedown, and
%% then send {cancel, Node, Tag}.
- receive
- {cancel, Node, _Tag, Fun} ->
- ?trace({cancel_the_lock,{node,Node}}),
- call_fun(Fun),
- delete_global_lock(LockId, Known2)
- end,
+ wait_cancel_lock(Node, LockId, MyTag, Known2,
+ the_locker_message_wait_cancel, S1),
S2 = S1#multi{just_synced = true},
- loop_the_locker(remove_node(Node, S2));
+ loop_the_locker(remove_node(Node, MyTag, S2));
false ->
loop_the_locker(S1#multi{just_synced = false})
end;
false ->
?trace({the_locker, not_there, {node,Node}}),
- send_lock_set(S, false, Pid, _HisVsn=5),
+ send_lock_set(S, false, Pid, _HisVsn=5, 0),
+ loop_the_locker(S)
+ end;
+the_locker_message({lock_set, Pid, true, HisKnown}, S) ->
+ case find_node_tag(node(Pid), S) of
+ {true, MyTag, _HisVsn, _HisTag} ->
+ the_locker_message({lock_set, Pid, true, HisKnown, MyTag}, S);
+ false ->
+ ?trace({the_locker, not_there, {node,Node}}),
+ send_lock_set(S, false, Pid, _HisVsn=5, 0),
loop_the_locker(S)
end;
the_locker_message({add_to_known, Nodes}, S) ->
@@ -1886,11 +2197,23 @@ the_locker_message({remove_from_known, Node}, S) ->
loop_the_locker(S1);
the_locker_message({do_trace, DoTrace}, S) ->
loop_the_locker(S#multi{do_trace = DoTrace});
+the_locker_message({get_state, _, _} = Msg, S) ->
+ get_state_reply(Msg, the_locker_message, S),
+ loop_the_locker(S);
the_locker_message(Other, S) ->
unexpected_message(Other, locker),
?trace({the_locker, {other_msg, Other}}),
loop_the_locker(S).
+get_state_reply({get_state, From, Ref}, Where, S) ->
+ %% Ref should always be in first element of the reply!
+ From ! {Ref, Where, S},
+ ok.
+
+get_locker() ->
+ #state{the_locker = TheLocker} = info(),
+ TheLocker.
+
%% Requests from nodes on the local host are chosen before requests
%% from other nodes. This should be a safe optimization.
select_node(S) ->
@@ -1907,7 +2230,7 @@ select_node(S) ->
true ->
Him = random_element(Others2),
#him{locker = HisTheLocker, vsn = HisVsn,
- node = Node, my_tag = MyTag} = Him,
+ node = Node, my_tag = MyTag, his_tag = HisTag} = Him,
HisNode = [Node],
Us = [node() | HisNode],
LockId = locker_lock_id(HisTheLocker, HisVsn),
@@ -1917,7 +2240,7 @@ select_node(S) ->
case IsLockSet of
true ->
Known1 = Us ++ S2#multi.known,
- send_lock_set(S2, true, HisTheLocker, HisVsn),
+ send_lock_set(S2, true, HisTheLocker, HisVsn, HisTag),
S3 = lock_is_set(S2, Him, MyTag, Known1, LockId),
loop_the_locker(S3);
false ->
@@ -1925,9 +2248,13 @@ select_node(S) ->
end
end.
-send_lock_set(S, IsLockSet, HisTheLocker, Vsn) ->
+send_lock_set(S, IsLockSet, HisTheLocker, Vsn, HisTag) ->
?trace({sending_lock_set, self(), {his,HisTheLocker}}),
- Message = {lock_set, self(), IsLockSet, S#multi.known},
+ Message = if Vsn < ?verify_connect_vsn ->
+ {lock_set, self(), IsLockSet, S#multi.known};
+ true ->
+ {lock_set, self(), IsLockSet, S#multi.known, HisTag}
+ end,
if
Vsn < 6 ->
HisTheLocker ! Message,
@@ -2018,7 +2345,8 @@ update_locker_known(Upd, S) ->
{remove, Node} -> lists:delete(Node, S#multi.known)
end,
TheBoss = the_boss([node() | Known]),
- S#multi{known = Known, the_boss = TheBoss}.
+ NewS = S#multi{known = Known, the_boss = TheBoss},
+ NewS.
random_element(L) ->
E = abs(erlang:monotonic_time()
@@ -2031,39 +2359,34 @@ exclude_known(Others, Known) ->
lock_is_set(S, Him, MyTag, Known1, LockId) ->
Node = Him#him.node,
receive
+ {lock_set, P, true, _, MyTag} when node(P) =:= Node ->
+ lock_is_set_true_received(S, Him, MyTag, Known1, LockId, P);
+ {lock_set, P, true, _, _OldMyTag} when node(P) =:= Node ->
+ lock_is_set(S, Him, MyTag, Known1, LockId);
{lock_set, P, true, _} when node(P) =:= Node ->
- gen_server:cast(global_name_server,
- {lock_is_set, Node, MyTag, LockId}),
- ?trace({lock_sync_done, {p,P, node(P)}, {me,self()}}),
-
- %% Wait for global to tell us to remove lock. Should the
- %% other locker's node die, global_name_server will
- %% receive nodedown, and then send {cancel, Node, Tag, Fun}.
- receive
- {cancel, Node, _, Fun} ->
- ?trace({lock_set_loop, {known1,Known1}}),
- call_fun(Fun),
- delete_global_lock(LockId, Known1)
- end,
- S#multi{just_synced = true,
- local = lists:delete(Him, S#multi.local),
- remote = lists:delete(Him, S#multi.remote)};
- {lock_set, P, false, _} when node(P) =:= Node ->
+ lock_is_set_true_received(S, Him, MyTag, Known1, LockId, P);
+ {lock_set, P, false, _, MyTag} when node(P) =:= Node ->
?trace({not_both_set, {node,Node},{p, P},{known1,Known1}}),
_ = locker_trace(S, rejected, Known1),
delete_global_lock(LockId, Known1),
S;
- {cancel, Node, _, Fun} ->
- ?trace({the_locker, cancel2, {node,Node}}),
- call_fun(Fun),
+ {lock_set, P, false, _, _OldMyTag} when node(P) =:= Node ->
+ lock_is_set(S, Him, MyTag, Known1, LockId);
+ {lock_set, P, false, _} when node(P) =:= Node ->
+ ?trace({not_both_set, {node,Node},{p, P},{known1,Known1}}),
_ = locker_trace(S, rejected, Known1),
delete_global_lock(LockId, Known1),
- remove_node(Node, S);
- {'EXIT', _, _} ->
- ?trace({the_locker, exit, {node,Node}}),
+ S;
+ {cancel, Node, MyTag, Fun} = _CMsg ->
+ ?trace({the_locker, cancel2, {node,Node}, _CMsg}),
+ call_fun(Fun),
_ = locker_trace(S, rejected, Known1),
delete_global_lock(LockId, Known1),
- S
+ remove_node(Node, MyTag, S);
+ {get_state, _, _} = Msg ->
+ get_state_reply(Msg, lock_is_set, S),
+ lock_is_set(S, Him, MyTag, Known1, LockId)
+
%% There used to be an 'after' clause (OTP-4902), but it is
%% no longer needed:
%% OTP-5770. Version 5 of the protocol. Deadlock can no longer
@@ -2074,6 +2397,35 @@ lock_is_set(S, Him, MyTag, Known1, LockId) ->
%% with the first partition.
end.
+lock_is_set_true_received(S, Him, MyTag, Known1, LockId, P) ->
+ Node = node(P),
+ gen_server:cast(global_name_server,
+ {lock_is_set, Node, MyTag, LockId}),
+ ?trace({lock_sync_done, {p,P, node(P)}, {me,self()}}),
+
+ %% Wait for global to tell us to remove lock. Should the
+ %% other locker's node die, global_name_server will
+ %% receive nodedown, and then send {cancel, Node, Tag, Fun}.
+ wait_cancel_lock(Node, LockId, MyTag, Known1,
+ lock_is_set_wait_cancel, S),
+ S#multi{just_synced = true,
+ local = lists:delete(Him, S#multi.local),
+ remote = lists:delete(Him, S#multi.remote)}.
+
+wait_cancel_lock(Node, LockId, MyTag, Known, Where, S) ->
+ receive
+ {cancel, Node, MyTag, Fun} = _CMsg ->
+ ?trace({cancel_the_lock, {where, _Where},
+ {node,Node}, {known, Known}, _CMsg}),
+ call_fun(Fun),
+ delete_global_lock(LockId, Known);
+
+ {get_state, _, _} = Msg ->
+ get_state_reply(Msg, Where, S),
+ wait_cancel_lock(Node, LockId, MyTag, Known, Where, S)
+ end.
+
+
%% The locker does the {new_nodes, ...} call before removing the lock.
call_fun(no_fun) ->
ok;
@@ -2101,21 +2453,21 @@ find_node_tag(Node, S) ->
find_node_tag2(_Node, []) ->
false;
-find_node_tag2(Node, [#him{node = Node, my_tag = MyTag, vsn = HisVsn} | _]) ->
- {true, MyTag, HisVsn};
+find_node_tag2(Node, [#him{node = Node, my_tag = MyTag, vsn = HisVsn, his_tag = HisTag} | _]) ->
+ {true, MyTag, HisVsn, HisTag};
find_node_tag2(Node, [_E | Rest]) ->
find_node_tag2(Node, Rest).
-remove_node(Node, S) ->
- S#multi{local = remove_node2(Node, S#multi.local),
- remote = remove_node2(Node, S#multi.remote)}.
+remove_node(Node, Tag, S) ->
+ S#multi{local = remove_node2(Node, Tag, S#multi.local),
+ remote = remove_node2(Node, Tag, S#multi.remote)}.
-remove_node2(_Node, []) ->
+remove_node2(_Node, _Tag, []) ->
[];
-remove_node2(Node, [#him{node = Node} | Rest]) ->
+remove_node2(Node, Tag, [#him{node = Node, my_tag = Tag} | Rest]) ->
Rest;
-remove_node2(Node, [E | Rest]) ->
- [E | remove_node2(Node, Rest)].
+remove_node2(Node, Tag, [E | Rest]) ->
+ [E | remove_node2(Node, Tag, Rest)].
add_node(Him, S) ->
case is_node_local(Him#him.node) of
@@ -2142,10 +2494,12 @@ cancel_locker(Node, S, Tag) ->
cancel_locker(Node, S, Tag, no_fun).
cancel_locker(Node, S, Tag, ToBeRunOnLockerF) ->
- S#state.the_locker ! {cancel, Node, Tag, ToBeRunOnLockerF},
+ CMsg = {cancel, Node, Tag, ToBeRunOnLockerF},
+ S#state.the_locker ! CMsg,
Resolvers = S#state.resolvers,
?trace({cancel_locker, {node,Node},{tag,Tag},
{sync_tag_my, get({sync_tag_my, Node})},{resolvers,Resolvers}}),
+ send_cancel_connect(Node, Tag, S),
case lists:keyfind(Node, 1, Resolvers) of
{_, Tag, Resolver} ->
?trace({{resolver, Resolver}}),
@@ -2156,6 +2510,34 @@ cancel_locker(Node, S, Tag, ToBeRunOnLockerF) ->
S
end.
+send_cancel_connect(Node, MyTag, #state{known = Known}) ->
+ %% Send a cancel_connect message if we got an ongoing
+ %% connect...
+ try
+ case maps:find({pending, Node}, Known) of
+ {ok, Vsn} when Vsn < ?verify_connect_vsn ->
+ throw(ignore);
+ error ->
+ throw(ignore);
+ {ok, _Vsn} ->
+ ok
+ end,
+ case get({sync_tag_my, Node}) of
+ MyTag -> ok;
+ _ -> throw(ignore)
+ end,
+ send_cancel_connect_message(Node, get({sync_tag_his, Node}))
+ catch
+ throw:ignore ->
+ ok
+ end.
+
+send_cancel_connect_message(Node, HisTag) ->
+ Msg = {cancel_connect, node(), HisTag},
+ To = {global_name_server, Node},
+ _ = erlang:send(To, Msg, [noconnect]),
+ ok.
+
reset_node_state(Node) ->
?trace({{node,Node}, reset_node_state, get()}),
erase({wait_lock, Node}),
@@ -2190,15 +2572,15 @@ exchange_names([{Name, Pid, Method} | Tail], Node, Ops, Res) ->
Op = {delete, Name},
exchange_names(Tail, Node, [Op | Ops], [Op | Res]);
{badrpc, Badrpc} ->
- error_logger:info_msg("global: badrpc ~w received when "
- "conflicting name ~tw was found\n",
- [Badrpc, Name]),
+ logger:log(info, "global: badrpc ~w received when "
+ "conflicting name ~tw was found\n",
+ [Badrpc, Name]),
Op = {insert, {Name, Pid, Method}},
exchange_names(Tail, Node, [Op | Ops], Res);
Else ->
- error_logger:info_msg("global: Resolve method ~w for "
- "conflicting name ~tw returned ~tw\n",
- [Method, Name, Else]),
+ logger:log(info, "global: Resolve method ~w for "
+ "conflicting name ~tw returned ~tw\n",
+ [Method, Name, Else]),
Op = {delete, Name},
exchange_names(Tail, Node, [Op | Ops], [Op | Res])
end;
@@ -2226,8 +2608,8 @@ minmax(P1,P2) ->
Pid2 :: pid().
random_exit_name(Name, Pid, Pid2) ->
{Min, Max} = minmax(Pid, Pid2),
- error_logger:info_msg("global: Name conflict terminating ~tw\n",
- [{Name, Max}]),
+ logger:log(info, "global: Name conflict terminating ~tw\n",
+ [{Name, Max}]),
exit(Max, kill),
Min.
@@ -2291,7 +2673,50 @@ pid_locks(Ref) ->
ref_is_locking(Ref, PidRefs)].
ref_is_locking(Ref, PidRefs) ->
- lists:keyfind(Ref, 2, PidRefs) =/= false.
+ lists:keyfind(Ref, 2, PidRefs) =/= false.
+
+handle_nodeup(Node, #state{the_locker = TheLocker,
+ resolvers = Rs,
+ known = Known} = S0) ->
+ case maps:is_key(Node, Known) orelse lists:keymember(Node, 1, Rs) of
+ true ->
+ %% Already known or in progress...
+ S0;
+
+ false ->
+ %% Make ourselves known to Node...
+
+ %%
+ %% In case a global group is configured, we might already
+ %% have received an init_connect message from Node (the
+ %% group_nodeup message may be delivered after early traffic
+ %% over the channel have been delivered). If we already have
+ %% gotten an init_connect, resend it to ourselves...
+ %%
+ resend_pre_connect(Node),
+
+ %% erlang:unique_integer([monotonic]) is used as a tag to
+ %% separate different synch sessions
+ %% from each others. Global could be confused at bursty nodeups
+ %% because it couldn't separate the messages between the different
+ %% synch sessions started by a nodeup.
+ MyTag = erlang:unique_integer([monotonic]),
+ put({sync_tag_my, Node}, MyTag),
+
+ %% In order to be compatible with unpatched R7 a locker
+ %% process was spawned. Vsn 5 is no longer compatible with
+ %% vsn 3 nodes, so the locker process is no longer needed.
+ %% The permanent locker takes its place.
+ NotAPid = no_longer_a_pid,
+ Locker = {locker, NotAPid, Known, TheLocker},
+ InitC = {init_connect, {?vsn, MyTag}, node(), Locker},
+ ?trace({casting_init_connect, {node,Node},{initmessage,InitC},
+ {resolvers,Rs}}),
+ gen_server:cast({global_name_server, Node}, InitC),
+ Resolver = start_resolver(Node, MyTag),
+ S1 = trace_message(S0, {new_resolver, Node}, [MyTag, Resolver]),
+ S1#state{resolvers = [{Node, MyTag, Resolver} | Rs]}
+ end.
handle_nodedown(Node, #state{synced = Syncs,
known = Known0} = S, What) ->
@@ -2313,9 +2738,9 @@ handle_nodedown(Node, #state{synced = Syncs,
Known0
end
end,
- NewS#state{known = maps:remove(Node,
- maps:remove({pending, Node}, Known1)),
- synced = lists:delete(Node, Syncs)}.
+ Known2 = maps:remove({pending, Node}, Known1),
+ Known3 = maps:remove(Node, Known2),
+ NewS#state{known = Known3, synced = lists:delete(Node, Syncs)}.
inform_connection_loss(Node,
#state{conf = #conf{connect_all = true,
@@ -2565,7 +2990,7 @@ check_sync_nodes() ->
{ok, NodesNG} ->
%% global_groups parameter is defined, we are not allowed to sync
%% with nodes not in our own global group.
- intersection(nodes(), NodesNG);
+ intersection(NodesNG, nodes());
{error, _} = Error ->
Error
end.
@@ -2577,7 +3002,7 @@ check_sync_nodes(SyncNodes) ->
{ok, NodesNG} ->
%% global_groups parameter is defined, we are not allowed to sync
%% with nodes not in our own global group.
- OwnNodeGroup = intersection(nodes(), NodesNG),
+ OwnNodeGroup = intersection(NodesNG, nodes()),
IllegalSyncNodes = (SyncNodes -- [node() | OwnNodeGroup]),
case IllegalSyncNodes of
[] -> SyncNodes;
@@ -2618,9 +3043,9 @@ unexpected_message({'EXIT', _Pid, _Reason}, _What) ->
%% global_name_server died
ok;
unexpected_message(Message, What) ->
- error_logger:warning_msg("The global_name_server ~w process "
- "received an unexpected message:\n~tp\n",
- [What, Message]).
+ logger:log(warning, "The global_name_server ~w process "
+ "received an unexpected message:\n~tp\n",
+ [What, Message]).
%%% Utilities
diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl
index c288fdde26..9117a54b61 100644
--- a/lib/kernel/src/global_group.erl
+++ b/lib/kernel/src/global_group.erl
@@ -36,26 +36,29 @@
-export([send/3]).
-export([whereis_name/1]).
-export([whereis_name/2]).
--export([global_groups_changed/1]).
--export([global_groups_added/1]).
--export([global_groups_removed/1]).
-export([sync/0]).
--export([ng_add_check/2, ng_add_check/3]).
-
-export([info/0]).
--export([registered_names_test/1]).
--export([send_test/2]).
--export([whereis_name_test/1]).
--export([get_own_nodes/0, get_own_nodes_with_errors/0]).
--export([publish_on_nodes/0]).
--export([config_scan/1, config_scan/2]).
+%% Kernel application internal exports
-%% Internal exports
--export([sync_init/4]).
+-export([global_groups_changed/1,
+ global_groups_added/1,
+ global_groups_removed/1,
+ get_own_nodes/0,
+ get_own_nodes_with_errors/0,
+ member/1,
+ participant/1,
+ publish/2,
+ group_configured/0]).
+%% Internal exports
+-export([ng_add_check/2,
+ ng_add_check/3,
+ registered_names_test/1,
+ send_test/2,
+ whereis_name_test/1]).
--define(cc_vsn, 2).
+-define(cc_vsn, 3).
%%%====================================================================================
@@ -67,33 +70,56 @@
| {GroupName :: group_name(),
PublishType :: publish_type(),
[node()]}.
-
+-type node_state() :: 'sync' | 'sync_error' | 'no_contact'.
%%%====================================================================================
%%% The state of the global_group process
%%%
-%%% sync_state = no_conf (global_groups not defined, inital state) |
+%%% sync_state = no_conf (global_groups not defined, initial state) |
%%% synced
%%% group_name = Own global group name
%%% nodes = Nodes in the own global group
%%% no_contact = Nodes which we haven't had contact with yet
%%% sync_error = Nodes which we haven't had contact with yet
%%% other_grps = list of other global group names and nodes, [{otherName, [Node]}]
-%%% node_name = Own node
%%% monitor = List of Pids requesting nodeup/nodedown
%%%====================================================================================
-record(state, {sync_state = no_conf :: sync_state(),
- connect_all :: boolean(),
group_name = [] :: group_name() | [],
- nodes = [] :: [node()],
- no_contact = [] :: [node()],
- sync_error = [],
+ nodes = #{} :: #{node() => node_state()},
other_grps = [],
- node_name = node() :: node(),
monitor = [],
- publish_type = normal :: publish_type(),
- group_publish_type = normal :: publish_type()}).
-
+ group_publish_type = normal :: publish_type(),
+ connections :: #{node() => non_neg_integer()},
+ erpc_requests :: erpc:request_id_collection(),
+ config_check :: 'undefined'
+ | {reference(),
+ #{node() => reference()}}}).
+
+%%%====================================================================================
+%%% Configuration record. Returned by:
+%%% * fetch_new_group_conf/1,2 -- Fetch and install new configuration
+%%% * new_group_conf/2,3 -- Install new configuration
+%%% * lookup_group_conf/1 -- Lookup installed configuration (will fetch
+%%% and install configuration if it has not
+%%% been initialized)
+%%% * alive_state_change_group_conf/1 -- Adjust configuration according to alive
+%%% state
+%%%====================================================================================
+-record(gconf, {parameter_value = invalid :: [group_tuple()]
+ | undefined
+ | invalid,
+ node_name :: node() | 'undefined',
+ group_name = [] :: group_name() | [],
+ group_publish_type = normal :: publish_type(),
+ group_list = [] :: [node()],
+ group_map = all :: 'all' | #{ node() => ok },
+ other_groups = [] :: [group_tuple()],
+ state = no_conf :: 'no_conf'
+ | 'conf'
+ | {error,
+ term(),
+ [group_tuple()]}}).
%%%====================================================================================
%%% External exported
@@ -165,12 +191,6 @@ global_groups_removed(NewPara) ->
sync() ->
request(sync).
-ng_add_check(Node, OthersNG) ->
- ng_add_check(Node, normal, OthersNG).
-
-ng_add_check(Node, PubType, OthersNG) ->
- request({ng_add_check, Node, PubType, OthersNG}).
-
-type info_item() :: {'state', State :: sync_state()}
| {'own_group_name', GroupName :: group_name()}
| {'own_group_nodes', Nodes :: [node()]}
@@ -184,6 +204,14 @@ ng_add_check(Node, PubType, OthersNG) ->
info() ->
request(info, 3000).
+%% global_group internal...
+
+ng_add_check(Node, OthersNG) ->
+ ng_add_check(Node, normal, OthersNG).
+
+ng_add_check(Node, PubType, OthersNG) ->
+ request({ng_add_check, Node, PubType, OthersNG}).
+
%% ==== ONLY for test suites ====
registered_names_test(Arg) ->
request({registered_names_test, Arg}).
@@ -214,14 +242,14 @@ request(Req, Time) ->
%%% Otherwise a sync process is started to check that all nodes in the own global
%%% group have the same configuration. This is done by sending 'conf_check' to all
%%% other nodes and requiring 'conf_check_result' back.
-%%% If the nodes are not in agreement of the configuration the global_group process
-%%% will remove these nodes from the #state.nodes list. This can be a normal case
+%%% If the nodes are not in agreement of the configuration the global_group process,
+%%% these nodes will be set in a state different than 'sync'. This can be a normal case
%%% at release upgrade when all nodes are not yet upgraded.
%%%
%%% It is possible to manually force a sync of the global_group. This is done for
-%%% instance after a release upgrade, after all nodes in the group beeing upgraded.
+%%% instance after a release upgrade, after all nodes in the group being upgraded.
%%% The nodes are not synced automatically because it would cause the node to be
-%%% disconnected from those not yet beeing upgraded.
+%%% disconnected from those not yet being upgraded.
%%%
%%% The three process dictionary variables (registered_names, send, and whereis_name)
%%% are used to store information needed if the search process crashes.
@@ -233,88 +261,119 @@ stop() -> gen_server:call(global_group, stop, infinity).
init([]) ->
process_flag(priority, max),
- ok = net_kernel:monitor_nodes(true),
+ ok = net_kernel:monitor_nodes(true, #{connection_id => true}),
put(registered_names, [undefined]),
put(send, [undefined]),
put(whereis_name, [undefined]),
process_flag(trap_exit, true),
- Ca = case init:get_argument(connect_all) of
- {ok, [["false"]]} ->
- false;
- _ ->
- true
- end,
- PT = publish_arg(),
- case application:get_env(kernel, global_groups) of
- undefined ->
- update_publish_nodes(PT),
- {ok, #state{publish_type = PT,
- connect_all = Ca}};
- {ok, []} ->
- update_publish_nodes(PT),
- {ok, #state{publish_type = PT,
- connect_all = Ca}};
- {ok, NodeGrps} ->
- {DefGroupName, PubTpGrp, DefNodes, DefOther} =
- case catch config_scan(NodeGrps, publish_type) of
- {error, _Error2} ->
- update_publish_nodes(PT),
- exit({error, {'invalid global_groups definition', NodeGrps}});
- {DefGroupNameT, PubType, DefNodesT, DefOtherT} ->
- update_publish_nodes(PT, {PubType, DefNodesT}),
- %% First disconnect any nodes not belonging to our own group
- disconnect_nodes(nodes(connected) -- DefNodesT),
- lists:foreach(fun(Node) ->
- erlang:monitor_node(Node, true)
- end,
- DefNodesT),
- {DefGroupNameT, PubType, lists:delete(node(), DefNodesT), DefOtherT}
- end,
- {ok, #state{publish_type = PT, group_publish_type = PubTpGrp,
- sync_state = synced, group_name = DefGroupName,
- no_contact = lists:sort(DefNodes),
- other_grps = DefOther, connect_all = Ca}}
- end.
+ GGC = spawn_link(fun global_group_check_dispatcher/0),
+ register(global_group_check, GGC),
+ put(global_group_check, GGC),
+
+ %% There are most likely no connected nodes at this stage,
+ %% but check to make sure...
+ Conns = lists:foldl(fun ({N, #{connection_id := CId}}, Cs) ->
+ Cs#{N => CId}
+ end,
+ #{},
+ nodes(visible, #{connection_id => true})),
+ S = initial_group_setup(fetch_new_group_conf(true, node()), Conns,
+ erpc:reqids_new()),
+ {ok, S}.
+
+initial_group_setup(#gconf{state = no_conf}, Conns, Reqs) ->
+ #state{connections = Conns,
+ erpc_requests = Reqs};
+initial_group_setup(#gconf{state = {error, _Err, NodeGrps}},
+ _Conns, _Reqs) ->
+ exit({error, {'invalid global_groups definition', NodeGrps}});
+initial_group_setup(#gconf{node_name = NodeName,
+ group_name = DefGroupName,
+ group_list = DefNodesT,
+ group_publish_type = PubTpGrp,
+ other_groups = DefOther}, Conns, Reqs) ->
+
+ DefNodes = lists:delete(NodeName, DefNodesT),
+ ConnectedNodes = maps:keys(Conns),
+ DisconnectNodes = ConnectedNodes -- DefNodes,
+ NotConnectedOwnNodes = DefNodes -- ConnectedNodes,
+ ConnectedOwnNodes = DefNodes -- NotConnectedOwnNodes,
+ %% First disconnect any nodes not belonging to our own group
+ disconnect_nodes(DisconnectNodes, Conns),
+
+ %% Schedule group consistency check for all nodes. The response
+ %% is later handled in handle_erpc_response().
+ NewReqs = schedule_conf_changed_checks(DefNodes, Reqs, Conns),
+
+ %% Set connected nodes in sync_error state since, we
+ %% have not yet verified their configuration...
+ Nodes0 = lists:foldl(fun (Node, Acc) ->
+ Acc#{Node => sync_error}
+ end,
+ #{}, ConnectedOwnNodes),
+ Nodes = lists:foldl(fun (Node, Acc) ->
+ Acc#{Node => no_contact}
+ end,
+ Nodes0, NotConnectedOwnNodes),
+
+ #state{group_publish_type = PubTpGrp,
+ sync_state = synced, group_name = DefGroupName,
+ nodes = Nodes, other_grps = DefOther,
+ connections = Conns, erpc_requests = NewReqs}.
%%%====================================================================================
%%% sync() -> ok
%%%
%%% An operator ordered sync of the own global group. This must be done after
-%%% a release upgrade. It can also be ordered if somthing has made the nodes
+%%% a release upgrade. It can also be ordered if something has made the nodes
%%% to disagree of the global_groups definition.
%%%====================================================================================
-handle_call(sync, _From, S) ->
+handle_call(sync, _From, #state{nodes = OldNodes,
+ connections = Conns} = S) ->
% io:format("~p sync ~p~n",[node(), application:get_env(kernel, global_groups)]),
- case application:get_env(kernel, global_groups) of
- undefined ->
- update_publish_nodes(S#state.publish_type),
- {reply, ok, S};
- {ok, []} ->
- update_publish_nodes(S#state.publish_type),
- {reply, ok, S};
- {ok, NodeGrps} ->
- {DefGroupName, PubTpGrp, DefNodes, DefOther} =
- case catch config_scan(NodeGrps, publish_type) of
- {error, _Error2} ->
- exit({error, {'invalid global_groups definition', NodeGrps}});
- {DefGroupNameT, PubType, DefNodesT, DefOtherT} ->
- update_publish_nodes(S#state.publish_type, {PubType, DefNodesT}),
- %% First inform global on all nodes not belonging to our own group
- disconnect_nodes(nodes(connected) -- DefNodesT),
- %% Sync with the nodes in the own group
- kill_global_group_check(),
- Pid = spawn_link(?MODULE, sync_init,
- [sync, DefGroupNameT, PubType, DefNodesT]),
- register(global_group_check, Pid),
- {DefGroupNameT, PubType, lists:delete(node(), DefNodesT), DefOtherT}
- end,
- {reply, ok, S#state{sync_state = synced, group_name = DefGroupName,
- no_contact = lists:sort(DefNodes),
- other_grps = DefOther, group_publish_type = PubTpGrp}}
- end;
-
+ case lookup_group_conf(true) of
+ #gconf{state = no_conf,
+ group_name = DefGroupName,
+ group_list = _DefNodesT,
+ group_publish_type = PubTpGrp,
+ other_groups = DefOther} ->
+ {reply, ok, S#state{sync_state = no_conf,
+ group_name = DefGroupName,
+ nodes = #{},
+ group_publish_type = PubTpGrp,
+ other_grps = DefOther}};
+
+ #gconf{state = {error, _Err, NodeGrps}} ->
+ exit({error, {'invalid global_groups definition', NodeGrps}});
+
+ #gconf{group_name = DefGroupName,
+ group_list = DefNodesT,
+ group_publish_type = PubTpGrp,
+ other_groups = DefOther} ->
+ DefNodes = lists:delete(node(), DefNodesT),
+ %% First inform global on all nodes not belonging to our own group
+ disconnect_nodes(nodes() -- DefNodes, Conns),
+ %% Sync with the nodes in the own group
+
+ SyncSession = make_ref(),
+
+ CCMsg = {conf_check, ?cc_vsn, node(), {self(), SyncSession},
+ sync, DefGroupName, PubTpGrp, DefNodesT},
+ {NewNodes, Mons}
+ = lists:foldl(fun (N, {Nacc, Macc}) ->
+ GG = {global_group, N},
+ M = erlang:monitor(process, GG),
+ gen_server:cast(GG, CCMsg),
+ NS = maps:get(N, OldNodes, no_contact),
+ {Nacc#{N => NS}, Macc#{N => M}}
+ end, {#{}, #{}}, DefNodes),
+ {reply, ok, S#state{sync_state = synced, group_name = DefGroupName,
+ nodes = NewNodes, other_grps = DefOther,
+ group_publish_type = PubTpGrp,
+ config_check = {SyncSession, Mons}}}
+ end;
%%%====================================================================================
%%% global_groups() -> {OwnGroupName, [OtherGroupName]} | undefined
@@ -347,7 +406,6 @@ handle_call({monitor_nodes, Flag}, {Pid, _}, StateIn) ->
{Res, State} = monitor_nodes(Flag, Pid, StateIn),
{reply, Res, State};
-
%%%====================================================================================
%%% own_nodes() -> [Node]
%%%
@@ -358,8 +416,7 @@ handle_call(own_nodes, _From, S) ->
no_conf ->
[node() | nodes()];
synced ->
- get_own_nodes()
-% S#state.nodes
+ get_own_nodes(true)
end,
{reply, Nodes, S};
@@ -503,84 +560,108 @@ handle_call({whereis_name, {node, Node}, Name}, From, S) ->
%%% The node is not resynced automatically because it would cause this node to
%%% be disconnected from those nodes not yet been upgraded.
%%%====================================================================================
-handle_call({global_groups_changed, NewPara}, _From, S) ->
- {NewGroupName, PubTpGrp, NewNodes, NewOther} =
- case catch config_scan(NewPara, publish_type) of
- {error, _Error2} ->
- exit({error, {'invalid global_groups definition', NewPara}});
- {DefGroupName, PubType, DefNodes, DefOther} ->
- update_publish_nodes(S#state.publish_type, {PubType, DefNodes}),
- {DefGroupName, PubType, DefNodes, DefOther}
- end,
-
- %% #state.nodes is the common denominator of previous and new definition
- NN = NewNodes -- (NewNodes -- S#state.nodes),
- %% rest of the nodes in the new definition are marked as not yet contacted
- NNC = (NewNodes -- S#state.nodes) -- S#state.sync_error,
- %% remove sync_error nodes not belonging to the new group
- NSE = NewNodes -- (NewNodes -- S#state.sync_error),
+handle_call({global_groups_changed, NewPara}, _From,
+ #state{erpc_requests = Reqs,
+ nodes = OldNodes,
+ connections = Conns} = S) ->
+
+ #gconf{group_name = NewGroupName,
+ group_publish_type = PubTpGrp,
+ group_list = NewNodesListT,
+ other_groups = NewOther,
+ state = GState} = new_group_conf(true, NewPara),
+
+ case GState of
+ no_conf ->
+ exit({error, 'no global_groups definiton'});
+ {error, _Err, NodeGrps} ->
+ exit({error, {'invalid global_groups definition', NodeGrps}});
+ _ ->
+ ok
+ end,
+
+ NewNodesList = lists:delete(node(), NewNodesListT),
%% Disconnect the connection to nodes which are not in our old global group.
%% This is done because if we already are aware of new nodes (to our global
%% group) global is not going to be synced to these nodes. We disconnect instead
%% of connect because upgrades can be done node by node and we cannot really
%% know what nodes these new nodes are synced to. The operator can always
- %% manually force a sync of the nodes after all nodes beeing uppgraded.
+ %% manually force a sync of the nodes after all nodes being uppgraded.
%% We must disconnect also if some nodes to which we have a connection
%% will not be in any global group at all.
- force_nodedown(nodes(connected) -- NewNodes),
+ force_nodedown(nodes(connected) -- NewNodesList, Conns),
+
+ NewNodes = lists:foldl(fun (N, Nacc) ->
+ NS = maps:get(N, OldNodes, no_contact),
+ Nacc#{N => NS}
+ end, #{}, NewNodesList),
+
+ %% Schedule group consistency check due to config change. The response is
+ %% later handled in handle_erpc_response()...
+ NewReqs = schedule_conf_changed_checks(NewNodesList, Reqs, Conns),
- NewS = S#state{group_name = NewGroupName,
- nodes = lists:sort(NN),
- no_contact = lists:sort(lists:delete(node(), NNC)),
- sync_error = lists:sort(NSE),
+ NewS = S#state{group_name = NewGroupName,
+ nodes = NewNodes,
other_grps = NewOther,
- group_publish_type = PubTpGrp},
+ group_publish_type = PubTpGrp,
+ erpc_requests = NewReqs,
+ config_check = undefined},
{reply, ok, NewS};
-
%%%====================================================================================
%%% global_groups parameter added
%%% The node is not resynced automatically because it would cause this node to
%%% be disconnected from those nodes not yet been upgraded.
%%%====================================================================================
-handle_call({global_groups_added, NewPara}, _From, S) ->
+handle_call({global_groups_added, NewPara}, _From,
+ #state{connections = Conns,
+ erpc_requests = Reqs} = S) ->
% io:format("### global_groups_changed, NewPara ~p ~n",[NewPara]),
- {NewGroupName, PubTpGrp, NewNodes, NewOther} =
- case catch config_scan(NewPara, publish_type) of
- {error, _Error2} ->
- exit({error, {'invalid global_groups definition', NewPara}});
- {DefGroupName, PubType, DefNodes, DefOther} ->
- update_publish_nodes(S#state.publish_type, {PubType, DefNodes}),
- {DefGroupName, PubType, DefNodes, DefOther}
- end,
+
+ #gconf{group_name = NewGroupName,
+ group_publish_type = PubTpGrp,
+ group_list = NewNodesList,
+ other_groups = NewOther,
+ state = GState} = new_group_conf(true, NewPara),
+
+ case GState of
+ no_conf ->
+ exit({error, 'no global_groups definiton'});
+ {error, _Err, NodeGrps} ->
+ exit({error, {'invalid global_groups definition', NodeGrps}});
+ _ ->
+ ok
+ end,
%% disconnect from those nodes which are not going to be in our global group
- force_nodedown(nodes(connected) -- NewNodes),
+ force_nodedown(nodes(connected) -- NewNodesList, Conns),
%% Check which nodes are already updated
- OwnNG = get_own_nodes(),
- NGACArgs = case S#state.group_publish_type of
- normal ->
- [node(), OwnNG];
- _ ->
- [node(), S#state.group_publish_type, OwnNG]
- end,
- {NN, NNC, NSE} =
- lists:foldl(fun(Node, {NN_acc, NNC_acc, NSE_acc}) ->
- case rpc:call(Node, global_group, ng_add_check, NGACArgs) of
- {badrpc, _} ->
- {NN_acc, [Node | NNC_acc], NSE_acc};
- agreed ->
- {[Node | NN_acc], NNC_acc, NSE_acc};
- not_agreed ->
- {NN_acc, NNC_acc, [Node | NSE_acc]}
- end
- end,
- {[], [], []}, lists:delete(node(), NewNodes)),
- NewS = S#state{sync_state = synced, group_name = NewGroupName, nodes = lists:sort(NN),
- sync_error = lists:sort(NSE), no_contact = lists:sort(NNC),
- other_grps = NewOther, group_publish_type = PubTpGrp},
+ NGACArgs = [node(), PubTpGrp, NewNodesList],
+
+ %% Schedule ng_add_check on all nodes in our configuration and build up
+ %% the nodes map. The responses to the ng_add_check are later handled in
+ %% handle_erpc_response().
+ {NewReqs, NewNodes}
+ = lists:foldl(
+ fun (N, {Racc, Nacc}) ->
+ CId = maps:get(N, Conns, not_connected),
+ NRacc = erpc:send_request(N, ?MODULE, ng_add_check,
+ NGACArgs,
+ {ng_add_check, N, CId},
+ Racc),
+ What = if CId == not_connected -> no_contact;
+ true -> sync_error
+ end,
+ {NRacc, Nacc#{N => What}}
+ end,
+ {Reqs, #{}}, lists:delete(node(), NewNodesList)),
+
+ NewS = S#state{sync_state = synced, group_name = NewGroupName,
+ nodes = NewNodes, erpc_requests = NewReqs,
+ other_grps = NewOther, group_publish_type = PubTpGrp,
+ config_check = undefined},
{reply, ok, NewS};
@@ -589,10 +670,16 @@ handle_call({global_groups_added, NewPara}, _From, S) ->
%%%====================================================================================
handle_call({global_groups_removed, _NewPara}, _From, S) ->
% io:format("### global_groups_removed, NewPara ~p ~n",[_NewPara]),
- update_publish_nodes(S#state.publish_type),
- NewS = S#state{sync_state = no_conf, group_name = [], nodes = [],
- sync_error = [], no_contact = [],
- other_grps = []},
+
+ #gconf{group_name = NewGroupName,
+ group_publish_type = PubTpGrp,
+ group_list = _NewNodes,
+ other_groups = NewOther,
+ state = no_conf} = new_group_conf(true, undefined),
+
+ NewS = S#state{sync_state = no_conf, group_name = NewGroupName, nodes = #{},
+ other_grps = NewOther, group_publish_type = PubTpGrp,
+ config_check = undefined},
{reply, ok, NewS};
@@ -601,40 +688,37 @@ handle_call({global_groups_removed, _NewPara}, _From, S) ->
%%% belong to the same global group.
%%% It could happen that our node is not yet updated with the new node_group parameter
%%%====================================================================================
-handle_call({ng_add_check, Node, PubType, OthersNG}, _From, S) ->
+handle_call({ng_add_check, Node, PubType, OthersNG}, _From,
+ #state{group_publish_type = OwnPubType} = S) ->
%% Check which nodes are already updated
- OwnNG = get_own_nodes(),
- case S#state.group_publish_type =:= PubType of
- true ->
- case OwnNG of
- OthersNG ->
- NN = [Node | S#state.nodes],
- NSE = lists:delete(Node, S#state.sync_error),
- NNC = lists:delete(Node, S#state.no_contact),
- NewS = S#state{nodes = lists:sort(NN),
- sync_error = NSE,
- no_contact = NNC},
- {reply, agreed, NewS};
- _ ->
- {reply, not_agreed, S}
- end;
- _ ->
- {reply, not_agreed, S}
+ OwnNodes = get_own_nodes(true),
+ case {PubType, lists:sort(OthersNG)} of
+ {OwnPubType, OwnNodes} ->
+ {reply, agreed, node_state(sync, Node, S)};
+ _ ->
+ {reply, not_agreed, node_state(sync_error, Node, S)}
end;
-
-
%%%====================================================================================
%%% Misceleaneous help function to read some variables
%%%====================================================================================
-handle_call(info, _From, S) ->
+handle_call(info, _From, S) ->
+ {InSync, SyncError, NoContact}
+ = maps:fold(fun (N, sync, {ISacc, SEacc, NCacc}) ->
+ {[N|ISacc], SEacc, NCacc};
+ (N, sync_error, {ISacc, SEacc, NCacc}) ->
+ {ISacc, [N|SEacc], NCacc};
+ (N, no_contact, {ISacc, SEacc, NCacc}) ->
+ {ISacc, SEacc, [N|NCacc]}
+ end,
+ {[],[],[]},
+ S#state.nodes),
Reply = [{state, S#state.sync_state},
{own_group_name, S#state.group_name},
- {own_group_nodes, get_own_nodes()},
-% {"nodes()", lists:sort(nodes())},
- {synced_nodes, S#state.nodes},
- {sync_error, S#state.sync_error},
- {no_contact, S#state.no_contact},
+ {own_group_nodes, get_own_nodes(true)},
+ {synced_nodes, lists:sort(InSync)},
+ {sync_error, lists:sort(SyncError)},
+ {no_contact, lists:sort(NoContact)},
{other_groups, S#state.other_grps},
{monitoring, S#state.monitor}],
@@ -755,221 +839,270 @@ handle_cast({find_name_res, Result, Pid, From}, S) ->
gen_server:reply(From, Result),
{noreply, S};
-
-%%%====================================================================================
-%%% The node is synced successfully
-%%%====================================================================================
-handle_cast({synced, NoContact}, S) ->
-% io:format("~p>>>>> synced ~p ~n",[node(), NoContact]),
- kill_global_group_check(),
- Nodes = get_own_nodes() -- [node() | NoContact],
- {noreply, S#state{nodes = lists:sort(Nodes),
- sync_error = [],
- no_contact = NoContact}};
-
-
-%%%====================================================================================
-%%% The node could not sync with some other nodes.
-%%%====================================================================================
-handle_cast({sync_error, NoContact, ErrorNodes}, S) ->
-% io:format("~p>>>>> sync_error ~p ~p ~n",[node(), NoContact, ErrorNodes]),
- Txt = io_lib:format("Global group: Could not synchronize with these nodes ~p~n"
- "because global_groups were not in agreement. ~n", [ErrorNodes]),
- error_logger:error_report(Txt),
- kill_global_group_check(),
- Nodes = (get_own_nodes() -- [node() | NoContact]) -- ErrorNodes,
- {noreply, S#state{nodes = lists:sort(Nodes),
- sync_error = ErrorNodes,
- no_contact = NoContact}};
-
-
%%%====================================================================================
%%% Another node is checking this node's group configuration
%%%====================================================================================
handle_cast({conf_check, Vsn, Node, From, sync, CCName, CCNodes}, S) ->
handle_cast({conf_check, Vsn, Node, From, sync, CCName, normal, CCNodes}, S);
-handle_cast({conf_check, Vsn, Node, From, sync, CCName, PubType, CCNodes}, S) ->
- CurNodes = S#state.nodes,
+handle_cast({conf_check, Vsn, Node, From, sync, CCName, PubType, CCNodes},
+ #state{connections = Conns} = S) ->
% io:format(">>>>> conf_check,sync Node ~p~n",[Node]),
%% Another node is syncing,
%% done for instance after upgrade of global_groups parameter
- NS =
- case application:get_env(kernel, global_groups) of
- undefined ->
- %% We didn't have any node_group definition
- update_publish_nodes(S#state.publish_type),
- disconnect_nodes([Node]),
- {global_group_check, Node} ! {config_error, Vsn, From, node()},
- S;
- {ok, []} ->
- %% Our node_group definition was empty
- update_publish_nodes(S#state.publish_type),
- disconnect_nodes([Node]),
- {global_group_check, Node} ! {config_error, Vsn, From, node()},
- S;
- %%---------------------------------
- %% global_groups defined
- %%---------------------------------
- {ok, NodeGrps} ->
- case catch config_scan(NodeGrps, publish_type) of
- {error, _Error2} ->
- %% Our node_group definition was erroneous
- disconnect_nodes([Node]),
- {global_group_check, Node} ! {config_error, Vsn, From, node()},
- S#state{nodes = lists:delete(Node, CurNodes)};
-
- {CCName, PubType, CCNodes, _OtherDef} ->
- %% OK, add the node to the #state.nodes if it isn't there
- update_publish_nodes(S#state.publish_type, {PubType, CCNodes}),
- global_name_server ! {nodeup, Node},
- {global_group_check, Node} ! {config_ok, Vsn, From, node()},
- case lists:member(Node, CurNodes) of
- false ->
- NewNodes = lists:sort([Node | CurNodes]),
- NSE = lists:delete(Node, S#state.sync_error),
- NNC = lists:delete(Node, S#state.no_contact),
- S#state{nodes = NewNodes,
- sync_error = NSE,
- no_contact = NNC};
- true ->
- S
- end;
- _ ->
- %% node_group definitions were not in agreement
- disconnect_nodes([Node]),
- {global_group_check, Node} ! {config_error, Vsn, From, node()},
- NN = lists:delete(Node, S#state.nodes),
- NSE = lists:delete(Node, S#state.sync_error),
- NNC = lists:delete(Node, S#state.no_contact),
- S#state{nodes = NN,
- sync_error = NSE,
- no_contact = NNC}
- end
- end,
- {noreply, NS};
-
+ try
+ CId = case maps:get(Node, Conns, undefined) of
+ undefined ->
+ %% We got garbage from someone...
+ throw({noreply, S});
+ CId0 ->
+ CId0
+ end,
+ To = if is_integer(Vsn) andalso Vsn >= 3 ->
+ case From of
+ {Pid, _Session} when is_pid(Pid) ->
+ %% New node that does not use the
+ %% global_group_check process...
+ Pid;
+ _Garbage ->
+ %% We got garbage from someone...
+ throw({noreply, S})
+ end;
+ true ->
+ %% Old node that still use the
+ %% global_group_check process...
+ {global_group_check, Node}
+ end,
+ case lookup_group_conf(true) of
+ #gconf{state = no_conf} ->
+ %% We didn't have any node_group definition
+ disconnect_nodes([Node], Conns),
+ To ! {config_error, Vsn, From, node()},
+ {noreply, S};
+
+ #gconf{state = {error, _Err, _NodeGrps}} ->
+ disconnect_nodes([Node], Conns),
+ To ! {config_error, Vsn, From, node()},
+ {noreply, node_state(remove, Node, S)};
+
+ #gconf{group_name = CCName,
+ group_list = CCNodes,
+ group_publish_type = PubType} ->
+ %% OK, change the state of the node to 'sync'
+ global_name_server ! {group_nodeup, Node, CId},
+ To ! {config_ok, Vsn, From, node()},
+ {noreply, node_state(sync, Node, S)};
+
+ #gconf{} ->
+ %% group definitions were not in agreement
+ disconnect_nodes([Node], Conns),
+ To ! {config_error, Vsn, From, node()},
+ {noreply, node_state(sync_error, Node, S)}
+ end
+ catch
+ throw:{noreply, _} = Return -> Return
+ end;
handle_cast(_Cast, S) ->
% io:format("***** handle_cast ~p~n",[_Cast]),
{noreply, S}.
-
+handle_info(Msg, #state{erpc_requests = Requests} = S) ->
+ try erpc:check_response(Msg, Requests, true) of
+ NoMatch when NoMatch == no_request; NoMatch == no_response ->
+ continue_handle_info(Msg, S);
+ {{response, Result}, Label, NewRequests} ->
+ {noreply,
+ handle_erpc_response(ok, Result, Label,
+ S#state{erpc_requests = NewRequests})}
+ catch
+ Class:{Reason, Label, NewRequests} ->
+ {noreply,
+ handle_erpc_response(Class, Reason, Label,
+ S#state{erpc_requests = NewRequests})}
+ end.
%%%====================================================================================
-%%% A node went down. If no global group configuration inform global;
-%%% if global group configuration inform global only if the node is one in
-%%% the own global group.
+%%% Distribution on this node was started...
%%%====================================================================================
-handle_info({nodeup, Node}, S) when S#state.sync_state =:= no_conf ->
-% io:format("~p>>>>> nodeup, Node ~p ~n",[node(), Node]),
+continue_handle_info({nodeup, Node, #{connection_id := undefined}},
+ #state{connections = Conns, erpc_requests = Reqs}) ->
+ %% Check configuration since we now know how to interpret it
+ %% w<hen we know our name...
+ S = initial_group_setup(alive_state_change_group_conf(Node), Conns, Reqs),
send_monitor(S#state.monitor, {nodeup, Node}, S#state.sync_state),
- global_name_server ! {nodeup, Node},
{noreply, S};
-handle_info({nodeup, Node}, S) ->
+
+%%%====================================================================================
+%%% A new node connected...
+%%%====================================================================================
+continue_handle_info({nodeup, Node, #{connection_id := CId}},
+ #state{sync_state = no_conf,
+ connections = Conns} = S) ->
% io:format("~p>>>>> nodeup, Node ~p ~n",[node(), Node]),
- OthersNG = case S#state.sync_state of
- synced ->
- X = (catch rpc:call(Node, global_group, get_own_nodes, [])),
- case X of
- X when is_list(X) ->
- lists:sort(X);
- _ ->
- []
- end;
- no_conf ->
- []
- end,
-
- NNC = lists:delete(Node, S#state.no_contact),
- NSE = lists:delete(Node, S#state.sync_error),
- OwnNG = get_own_nodes(),
- case OwnNG of
- OthersNG ->
- send_monitor(S#state.monitor, {nodeup, Node}, S#state.sync_state),
- global_name_server ! {nodeup, Node},
- case lists:member(Node, S#state.nodes) of
- false ->
- NN = lists:sort([Node | S#state.nodes]),
- {noreply, S#state{nodes = NN,
- no_contact = NNC,
- sync_error = NSE}};
- true ->
- {noreply, S#state{no_contact = NNC,
- sync_error = NSE}}
- end;
- _ ->
- case {lists:member(Node, get_own_nodes()),
- lists:member(Node, S#state.sync_error)} of
- {true, false} ->
- NSE2 = lists:sort([Node | S#state.sync_error]),
- {noreply, S#state{no_contact = NNC,
- sync_error = NSE2}};
- _ ->
- {noreply, S}
- end
+ send_monitor(S#state.monitor, {nodeup, Node}, S#state.sync_state),
+ {noreply, S#state{connections = Conns#{Node => CId}}};
+continue_handle_info({nodeup, Node, #{connection_id := CId}},
+ #state{erpc_requests = Reqs, connections = Conns} = S) ->
+% io:format("~p>>>>> nodeup, Node ~p ~n",[node(), Node]),
+
+ NewConns = Conns#{Node => CId},
+ case member(true, Node) of
+ false ->
+ %% Node is not part of our group configuration...
+ disconnect_nodes([Node], NewConns),
+ {noreply, S#state{connections = NewConns}};
+ true ->
+
+ %% Node is part of our group configuration. Check that it has the
+ %% same view of the configuration as us...
+
+ NewReqs = erpc:send_request(Node, global_group, get_own_nodes, [],
+ {nodeup_conf_check, Node, CId}, Reqs),
+
+ %% The response is later handled in handle_erpc_response()...
+
+ %% Set the node in 'sync_error' state. It will later be changed
+ %% to 'sync' if it passes the 'nodeup_conf_check' test...
+ {noreply, node_state(sync_error, Node,
+ S#state{erpc_requests = NewReqs,
+ connections = NewConns})}
end;
%%%====================================================================================
+%%% Distribution on this node was shut down...
+%%%====================================================================================
+continue_handle_info({nodedown, Node, #{connection_id := undefined}}, S) ->
+ %% Clear group configuration. We don't know how to interpret it
+ %% unless we know our own name...
+ #gconf{state = no_conf,
+ group_name = DefGroupName,
+ group_list = _DefNodes,
+ group_publish_type = PubTpGrp,
+ other_groups = DefOther} = alive_state_change_group_conf(nonode@nohost),
+ send_monitor(S#state.monitor, {nodedown, Node}, no_conf),
+ {noreply, S#state{group_publish_type = PubTpGrp,
+ sync_state = no_conf, group_name = DefGroupName,
+ nodes = #{}, other_grps = DefOther,
+ config_check = undefined}};
+
+%%%====================================================================================
%%% A node has crashed.
-%%% nodedown must always be sent to global; this is a security measurement
-%%% because during release upgrade the global_groups parameter is upgraded
-%%% before the node is synced. This means that nodedown may arrive from a
-%%% node which we are not aware of.
%%%====================================================================================
-handle_info({nodedown, Node}, S) when S#state.sync_state =:= no_conf ->
+continue_handle_info({nodedown, Node, _Info},
+ #state{sync_state = no_conf,
+ monitor = Monitor,
+ connections = Conns} = S) ->
% io:format("~p>>>>> nodedown, no_conf Node ~p~n",[node(), Node]),
- send_monitor(S#state.monitor, {nodedown, Node}, S#state.sync_state),
- global_name_server ! {nodedown, Node},
- {noreply, S};
-handle_info({nodedown, Node}, S) ->
+ send_monitor(Monitor, {nodedown, Node}, no_conf),
+ {noreply, S#state{connections = maps:remove(Node, Conns)}};
+continue_handle_info({nodedown, Node, _Info},
+ #state{sync_state = SyncState,
+ monitor = Monitor,
+ connections = Conns} = S) ->
% io:format("~p>>>>> nodedown, Node ~p ~n",[node(), Node]),
- send_monitor(S#state.monitor, {nodedown, Node}, S#state.sync_state),
- NN = lists:delete(Node, S#state.nodes),
- NSE = lists:delete(Node, S#state.sync_error),
- NNC = case lists:member(Node, get_own_nodes()) of
- false ->
- global_name_server ! {ignore_node, Node},
- S#state.no_contact;
- true ->
- global_name_server ! {nodedown, Node},
- case lists:member(Node, S#state.no_contact) of
- false ->
- [Node | S#state.no_contact];
- true ->
- S#state.no_contact
- end
- end,
- {noreply, S#state{nodes = NN, no_contact = NNC, sync_error = NSE}};
+ send_monitor(Monitor, {nodedown, Node}, SyncState),
+ {noreply, node_state(no_contact, Node,
+ S#state{connections = maps:remove(Node, Conns)})};
%%%====================================================================================
%%% A node has changed its global_groups definition, and is telling us that we are not
%%% included in his group any more. This could happen at release upgrade.
%%%====================================================================================
-handle_info({disconnect_node, Node}, S) ->
+continue_handle_info({disconnect_node, Node}, #state{monitor = Monitor,
+ sync_state = SyncState,
+ nodes = Nodes,
+ connections = Conns} = S) ->
% io:format("~p>>>>> disconnect_node Node ~p CN ~p~n",[node(), Node, S#state.nodes]),
- case {S#state.sync_state, lists:member(Node, S#state.nodes)} of
- {synced, true} ->
- send_monitor(S#state.monitor, {nodedown, Node}, S#state.sync_state);
- _ ->
- cont
+ case {SyncState, maps:get(Node, Nodes, not_member)} of
+ {synced, sync} -> send_monitor(Monitor, {nodedown, Node}, SyncState);
+ _ -> ok
end,
- global_name_server ! {ignore_node, Node},
- NN = lists:delete(Node, S#state.nodes),
- NNC = lists:delete(Node, S#state.no_contact),
- NSE = lists:delete(Node, S#state.sync_error),
- {noreply, S#state{nodes = NN, no_contact = NNC, sync_error = NSE}};
-
+ CId = maps:get(Node, Conns, not_connected),
+ global_name_server ! {group_nodedown, Node, CId},
+ {noreply, node_state(sync_error, Node, S)};
+
+continue_handle_info({config_ok, ?cc_vsn, {Pid, CCSession}, Node},
+ #state{config_check = {CCSession, Mons},
+ connections = Conns} = S0) when Pid == self() ->
+ try
+ {Mon, NewMons} = case maps:take(Node, Mons) of
+ error -> throw({noreply, S0});
+ MonTake -> MonTake
+ end,
+ erlang:demonitor(Mon),
+ S1 = if map_size(NewMons) == 0 ->
+ S0#state{config_check = undefined};
+ true ->
+ S0#state{config_check = {CCSession, NewMons}}
+ end,
+ CId = case maps:get(Node, Conns, undefined) of
+ undefined -> throw({noreply, S1});
+ CId0 -> CId0
+ end,
+ global_name_server ! {group_nodeup, Node, CId},
+ {noreply, node_state(sync, Node, S0)}
+ catch
+ throw:{noreply, _} = Return -> Return
+ end;
+continue_handle_info({config_error, ?cc_vsn, {Pid, CCSession}, Node},
+ #state{config_check = {CCSession, Mons},
+ connections = Conns} = S0) when Pid == self() ->
+ try
+ {Mon, NewMons} = case maps:take(Node, Mons) of
+ error -> throw({noreply, S0});
+ MonTake -> MonTake
+ end,
+ erlang:demonitor(Mon),
+ S1 = if map_size(NewMons) == 0 ->
+ S0#state{config_check = undefined};
+ true ->
+ S0#state{config_check = {CCSession, NewMons}}
+ end,
+ CId = maps:get(Node, Conns, not_connected),
+ global_name_server ! {group_nodedown, Node, CId},
+ log_sync_error(Node),
+ {noreply, node_state(sync_error, Node, S1)}
+ catch
+ throw:{noreply, _} = Return -> Return
+ end;
+continue_handle_info({'DOWN', Mon, process, {global_group, Node}, Reason},
+ #state{config_check = {CCSession, Mons},
+ connections = Conns} = S0) ->
+ %% This clause needs to be the last one matching on 'DOWN'
+ %% messages...
+ try
+ NewMons = case maps:take(Node, Mons) of
+ {Mon, NewMons0} -> NewMons0;
+ _ -> throw({noreply, S0})
+ end,
+ S1 = if map_size(NewMons) == 0 ->
+ S0#state{config_check = undefined};
+ true ->
+ S0#state{config_check = {CCSession, NewMons}}
+ end,
+ CId = maps:get(Node, Conns, not_connected),
+ global_name_server ! {group_nodedown, Node, CId},
+ What = if Reason == noconnection ->
+ no_contact;
+ true ->
+ log_sync_error(Node),
+ sync_error
+ end,
+ {noreply, node_state(What, Node, S1)}
+ catch
+ throw:{noreply, _} = Return -> Return
+ end;
-handle_info({'EXIT', ExitPid, Reason}, S) ->
+continue_handle_info({'EXIT', ExitPid, Reason}, S) ->
check_exit(ExitPid, Reason),
{noreply, S};
-handle_info(_Info, S) ->
+continue_handle_info(_Info, S) ->
% io:format("***** handle_info = ~p~n",[_Info]),
{noreply, S}.
@@ -982,26 +1115,178 @@ terminate(_Reason, _S) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
+log_sync_error(Node) ->
+ Txt = io_lib:format("global_group: Could not synchronize with node ~p~n"
+ "because global_groups parameter were not in agreement.~n",
+ [Node]),
+ error_logger:error_report(Txt),
+ ok.
+%%%====================================================================================
+%%% Schedule group consistency check due to config change. The response is
+%%% later handled in handle_erpc_response()...
+%%%====================================================================================
-
+schedule_conf_changed_checks(Nodes, Requests, Connections) ->
+ lists:foldl(fun (Node, RequestsAcc) ->
+ CId = maps:get(Node, Connections, not_connected),
+ erpc:send_request(Node, global_group, get_own_nodes, [],
+ {conf_changed_check, Node, CId},
+ RequestsAcc)
+ end, Requests, Nodes).
%%%====================================================================================
-%%% Check the global group configuration.
+%%% We got a response to an asynchronous erpc request
%%%====================================================================================
-config_scan(NodeGrps) ->
- config_scan(NodeGrps, original).
+handle_erpc_response(ok, Nodes, {nodeup_conf_check, Node, ReqCId},
+ #state{connections = Conns} = S) when is_list(Nodes) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ OwnNodes = get_own_nodes(true),
+
+ case lists:sort(Nodes) of
+ OwnNodes -> %% Node has the same group config as us...
+ send_monitor(S#state.monitor, {nodeup, Node}, S#state.sync_state),
+ global_name_server ! {group_nodeup, Node, CId},
+ node_state(sync, Node, S);
-config_scan(NodeGrps, original) ->
- case config_scan(NodeGrps, publish_type) of
- {DefGroupName, _, DefNodes, DefOther} ->
- {DefGroupName, DefNodes, DefOther};
- Error ->
- Error
+ _ -> %% Node has not the same group config but is in our config...
+ disconnect_nodes([Node], Conns),
+ node_state(sync_error, Node, S)
+ end;
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(error, {erpc,noconnection},
+ {nodeup_conf_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ node_state(no_contact, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(_, _, {nodeup_conf_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ disconnect_nodes([Node], Conns),
+ node_state(sync_error, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(ok, Nodes, {conf_changed_check, Node, ReqCId},
+ #state{connections = Conns} = S) when is_list(Nodes) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ OwnNodes = get_own_nodes(true),
+
+ case lists:sort(Nodes) of
+ OwnNodes -> %% Node has the same group config as us...
+ node_state(sync, Node, S);
+
+ _ -> %% Node has not the same group config but is in our config...
+ disconnect_nodes([Node], Conns),
+ node_state(sync_error, Node, S)
+ end;
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(error, {erpc,noconnection},
+ {conf_changed_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ node_state(no_contact, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(_, _, {conf_changed_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ disconnect_nodes([Node], Conns),
+ node_state(sync_error, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
end;
-config_scan(NodeGrps, publish_type) ->
- config_scan(node(), normal, NodeGrps, no_name, [], []).
+handle_erpc_response(ok, agreed, {ng_add_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ node_state(sync, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(error, {erpc,noconnection}, {ng_add_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ node_state(no_contact, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end;
+handle_erpc_response(_, _, {ng_add_check, Node, ReqCId},
+ #state{connections = Conns} = S) ->
+ case maps:get(Node, Conns, undefined) of
+ CId when ReqCId == CId orelse (ReqCId == not_connected
+ andalso is_integer(CId)) ->
+ disconnect_nodes([Node], Conns),
+ node_state(sync_error, Node, S);
+ _ ->
+ %% Connection has gone down since we issued the request;
+ %% no action taken...
+ S
+ end.
+
+
+%%%====================================================================================
+%%% Change state of node
+%%%====================================================================================
+
+node_state(What, Node, #state{nodes = Ns} = S)
+ when What == sync; What == sync_error; What == no_contact ->
+ case member(true, Node) of
+ true -> S#state{nodes = Ns#{Node => What}};
+ false -> S#state{nodes = maps:remove(Node, Ns)}
+ end;
+node_state(remove, Node, #state{nodes = Ns} = S) ->
+ case member(true, Node) of
+ true -> error({removing_node_state_of_member_node, Node});
+ false -> S#state{nodes = maps:remove(Node, Ns)}
+ end.
+
+%%%====================================================================================
+%%% Check the global group configuration.
+%%%====================================================================================
+
+config_scan(MyNode, NodeGrps) ->
+ config_scan(MyNode, normal, NodeGrps, no_name, [], []).
config_scan(_MyNode, PubType, [], Own_name, OwnNodes, OtherNodeGrps) ->
{Own_name, PubType, lists:sort(OwnNodes), lists:reverse(OtherNodeGrps)};
@@ -1027,98 +1312,121 @@ grp_tuple({Name, hidden, Nodes}) ->
grp_tuple({Name, normal, Nodes}) ->
{Name, normal, Nodes}.
-
%%%====================================================================================
-%%% The special process which checks that all nodes in the own global group
-%%% agrees on the configuration.
-%%%====================================================================================
--spec sync_init(_, _, _, _) -> no_return().
-sync_init(Type, Cname, PubType, Nodes) ->
- {Up, Down} = sync_check_node(lists:delete(node(), Nodes), [], []),
- sync_check_init(Type, Up, Cname, Nodes, Down, PubType).
-
-sync_check_node([], Up, Down) ->
- {Up, Down};
-sync_check_node([Node|Nodes], Up, Down) ->
- case net_adm:ping(Node) of
- pang ->
- sync_check_node(Nodes, Up, [Node|Down]);
- pong ->
- sync_check_node(Nodes, [Node|Up], Down)
- end.
+%%% Get/set configuration
+%%%====================================================================================
+%%
+%% Fetch and install group configuration...
+%%
+fetch_new_group_conf(GG) ->
+ fetch_new_group_conf(GG, undefined).
+fetch_new_group_conf(GG, NodeName) ->
+ GGConf = case application:get_env(kernel, global_groups) of
+ undefined -> undefined;
+ {ok, V} -> V
+ end,
+ new_group_conf(GG, GGConf, NodeName).
-%%%-------------------------------------------------------------
-%%% Check that all nodes are in agreement of the global
-%%% group configuration.
-%%%-------------------------------------------------------------
--spec sync_check_init(_, _, _, _, _, _) -> no_return().
-sync_check_init(Type, Up, Cname, Nodes, Down, PubType) ->
- sync_check_init(Type, Up, Cname, Nodes, 3, [], Down, PubType).
+%%
+%% Install new group configuration...
+%%
+new_group_conf(GG, KernParamValue) ->
+ new_group_conf(GG, KernParamValue, undefined).
+
+new_group_conf(GG, KernParamValue, NodeName) ->
+ case persistent_term:get(?MODULE, #gconf{}) of
+ #gconf{parameter_value = KernParamValue,
+ node_name = Name} = GConf when NodeName == Name;
+ NodeName == undefined ->
+ GConf;
+ #gconf{node_name = Name} ->
+ UseNodeName = if NodeName == undefined -> Name;
+ true -> NodeName
+ end,
+ GConf = make_group_conf(UseNodeName, KernParamValue),
+ %% Only save in persistent term if called by
+ %% the global_group server...
+ if GG == true -> persistent_term:put(?MODULE, GConf);
+ true -> ok
+ end,
+ GConf
+ end.
--spec sync_check_init(_, _, _, _, _, _, _, _) -> no_return().
-sync_check_init(_Type, NoContact, _Cname, _Nodes, 0, ErrorNodes, Down, _PubType) ->
- case ErrorNodes of
- [] ->
- gen_server:cast(global_group, {synced, lists:sort(NoContact ++ Down)});
- _ ->
- gen_server:cast(global_group, {sync_error, lists:sort(NoContact ++ Down),
- ErrorNodes})
- end,
- receive
- kill ->
- exit(normal)
- after 5000 ->
- exit(normal)
- end;
+make_group_conf(NodeName, KernParamValue) when KernParamValue == undefined;
+ KernParamValue == [];
+ NodeName == nonode@nohost ->
+ %% Empty group configuration if it is not defined, or if we are not
+ %% alive (if we are not alive we cannot interpret the configuration
+ %% since we don't know our own node name)...
+ #gconf{parameter_value = KernParamValue,
+ node_name = NodeName};
+make_group_conf(NodeName, KernParamValue) ->
+ case catch config_scan(NodeName, KernParamValue) of
+
+ {error, Error} ->
+ #gconf{parameter_value = KernParamValue,
+ node_name = NodeName,
+ state = {error, Error, KernParamValue}};
+
+ {GName, PubTpGrp, OwnNodes, OtherGroups} ->
+ GMap = if OwnNodes == [] ->
+ all;
+ true ->
+ maps:from_list(lists:map(fun (Node) ->
+ {Node, ok}
+ end, OwnNodes))
+ end,
+ #gconf{parameter_value = KernParamValue,
+ node_name = NodeName,
+ group_name = GName,
+ group_publish_type = PubTpGrp,
+ group_list = lists:sort(OwnNodes),
+ group_map = GMap,
+ other_groups = OtherGroups,
+ state = conf}
+ end.
-sync_check_init(Type, Up, Cname, Nodes, N, ErrorNodes, Down, PubType) ->
- ConfCheckMsg = case PubType of
- normal ->
- {conf_check, ?cc_vsn, node(), self(), Type, Cname, Nodes};
- _ ->
- {conf_check, ?cc_vsn, node(), self(), Type, Cname, PubType, Nodes}
- end,
- lists:foreach(fun(Node) ->
- gen_server:cast({global_group, Node}, ConfCheckMsg)
- end, Up),
- case sync_check(Up) of
- {ok, synced} ->
- sync_check_init(Type, [], Cname, Nodes, 0, ErrorNodes, Down, PubType);
- {error, NewErrorNodes} ->
- sync_check_init(Type, [], Cname, Nodes, 0, ErrorNodes ++ NewErrorNodes, Down, PubType);
- {more, Rem, NewErrorNodes} ->
- %% Try again to reach the global_group,
- %% obviously the node is up but not the global_group process.
- sync_check_init(Type, Rem, Cname, Nodes, N-1, ErrorNodes ++ NewErrorNodes, Down, PubType)
+%%
+%% Adjust group configuration according to alive state
+%%
+alive_state_change_group_conf(NodeName) when NodeName /= undefined ->
+ case persistent_term:get(?MODULE, #gconf{}) of
+ #gconf{parameter_value = ParamValue} when ParamValue /= invalid ->
+ new_group_conf(true, ParamValue, NodeName);
+ #gconf{} ->
+ fetch_new_group_conf(true, NodeName)
end.
-sync_check(Up) ->
- sync_check(Up, Up, []).
+%%
+%% Lookup current group configuration
+%%
-sync_check([], _Up, []) ->
- {ok, synced};
-sync_check([], _Up, ErrorNodes) ->
- {error, ErrorNodes};
-sync_check(Rem, Up, ErrorNodes) ->
- receive
- {config_ok, ?cc_vsn, Pid, Node} when Pid =:= self() ->
- global_name_server ! {nodeup, Node},
- sync_check(Rem -- [Node], Up, ErrorNodes);
- {config_error, ?cc_vsn, Pid, Node} when Pid =:= self() ->
- sync_check(Rem -- [Node], Up, [Node | ErrorNodes]);
- {no_global_group_configuration, ?cc_vsn, Pid, Node} when Pid =:= self() ->
- sync_check(Rem -- [Node], Up, [Node | ErrorNodes]);
- %% Ignore, illegal vsn or illegal Pid
- _ ->
- sync_check(Rem, Up, ErrorNodes)
- after 2000 ->
- %% Try again, the previous conf_check message
- %% apparently disapared in the magic black hole.
- {more, Rem, ErrorNodes}
+lookup_group_conf(GG) ->
+ try
+ persistent_term:get(?MODULE)
+ catch
+ error:badarg -> fetch_new_group_conf(GG)
end.
+%%%====================================================================================
+%%% The global_group_check process. It used to take care of syncing other nodes,
+%%% but nowadays only serve as a dispatcher config check reply messages from old
+%%% global_group servers to our global_group server.
+%%%====================================================================================
+
+global_group_check_dispatcher() ->
+ receive
+ {config_ok, _Vsn, _From, _Node} = Msg ->
+ global_group ! Msg, ok;
+ {config_error, _Vsn, _From, _Node} = Msg ->
+ global_group ! Msg, ok;
+ _Garbage ->
+ ok
+ end,
+ global_group_check_dispatcher().
+
%%%====================================================================================
%%% A process wants to toggle monitoring nodeup/nodedown from nodes.
@@ -1164,7 +1472,7 @@ send_monitor([], _, _) ->
ok.
safesend(Name, {Msg, Node}) when is_atom(Name) ->
- case lists:member(Node, get_own_nodes()) of
+ case member(true, Node) of
true ->
case whereis(Name) of
undefined ->
@@ -1176,7 +1484,7 @@ safesend(Name, {Msg, Node}) when is_atom(Name) ->
not_own_group
end;
safesend(Pid, {Msg, Node}) ->
- case lists:member(Node, get_own_nodes()) of
+ case member(true, Node) of
true ->
Pid ! {Msg, Node};
false ->
@@ -1205,7 +1513,8 @@ check_exit(ExitPid, Reason) ->
% io:format("===EXIT=== ~p ~p ~n~p ~n~p ~n~p ~n~n",[ExitPid, Reason, get(registered_names), get(send), get(whereis_name)]),
check_exit_reg(get(registered_names), ExitPid, Reason),
check_exit_send(get(send), ExitPid, Reason),
- check_exit_where(get(whereis_name), ExitPid, Reason).
+ check_exit_where(get(whereis_name), ExitPid, Reason),
+ check_exit_ggc(ExitPid, Reason).
check_exit_reg(undefined, _ExitPid, _Reason) ->
@@ -1246,29 +1555,23 @@ check_exit_where(Where, ExitPid, Reason) ->
not_found_ignored
end.
-
-
-%%%====================================================================================
-%%% Kill any possible global_group_check processes
-%%%====================================================================================
-kill_global_group_check() ->
- case whereis(global_group_check) of
- undefined ->
- ok;
- Pid ->
- unlink(Pid),
- global_group_check ! kill,
- unregister(global_group_check)
+check_exit_ggc(ExitPid, Reason) ->
+ case get(global_group_check) of
+ ExitPid ->
+ %% Our global_group_check companion died; terminate...
+ exit(Reason);
+ _ ->
+ ok
end.
-
%%%====================================================================================
%%% Disconnect nodes not belonging to own global_groups
%%%====================================================================================
-disconnect_nodes(DisconnectNodes) ->
+disconnect_nodes(DisconnectNodes, Conns) ->
lists:foreach(fun(Node) ->
- {global_group, Node} ! {disconnect_node, node()},
- global_name_server ! {ignore_node, Node}
+ CId = maps:get(Node, Conns, not_connected),
+ global_name_server ! {group_nodedown, Node, CId},
+ {global_group, Node} ! {disconnect_node, node()}
end,
DisconnectNodes).
@@ -1276,10 +1579,11 @@ disconnect_nodes(DisconnectNodes) ->
%%%====================================================================================
%%% Disconnect nodes not belonging to own global_groups
%%%====================================================================================
-force_nodedown(DisconnectNodes) ->
+force_nodedown(DisconnectNodes, Conns) ->
lists:foreach(fun(Node) ->
- erlang:disconnect_node(Node),
- global_name_server ! {ignore_node, Node}
+ CId = maps:get(Node, Conns, not_connected),
+ global_name_server ! {group_nodedown, Node, CId},
+ erlang:disconnect_node(Node)
end,
DisconnectNodes).
@@ -1288,92 +1592,96 @@ force_nodedown(DisconnectNodes) ->
%%% Get the current global_groups definition
%%%====================================================================================
get_own_nodes_with_errors() ->
- case application:get_env(kernel, global_groups) of
- undefined ->
- {ok, all};
- {ok, []} ->
- {ok, all};
- {ok, NodeGrps} ->
- case catch config_scan(NodeGrps, publish_type) of
- {error, Error} ->
- {error, Error};
- {_, _, NodesDef, _} ->
- {ok, lists:sort(NodesDef)}
- end
+ case lookup_group_conf(false) of
+ #gconf{state = {error, Error, _NodeGrps}} ->
+ {error, Error};
+ #gconf{group_list = []} ->
+ {ok, all};
+ #gconf{group_list = Nodes} ->
+ {ok, Nodes}
end.
get_own_nodes() ->
- case get_own_nodes_with_errors() of
- {ok, all} ->
- [];
- {error, _} ->
- [];
- {ok, Nodes} ->
- Nodes
- end.
+ get_own_nodes(false).
+
+get_own_nodes(GG) when is_boolean(GG) ->
+ get_own_nodes(lookup_group_conf(GG));
+get_own_nodes(#gconf{group_list = Nodes}) ->
+ Nodes.
%%%====================================================================================
-%%% -hidden command line argument
+%%% Is a group configured?
%%%====================================================================================
-publish_arg() ->
- case net_kernel:dist_listen() of
- false ->
- hidden;
- _ ->
- case init:get_argument(hidden) of
- {ok,[[]]} ->
- hidden;
- {ok,[["true"]]} ->
- hidden;
- _ ->
- normal
- end
+
+-spec group_configured() -> boolean().
+
+group_configured() ->
+ group_configured(lookup_group_conf(false)).
+
+group_configured(GConf) ->
+ case GConf of
+ #gconf{state = no_conf} ->
+ false;
+ #gconf{} ->
+ true
end.
%%%====================================================================================
-%%% Own group publication type and nodes
+%%% Is node a participant?
+%%%
+%%% That is, a node is a participant if it either is a member of our configured group,
+%%% or there are no group configured (in which case all nodes are participants).
%%%====================================================================================
-own_group() ->
- case application:get_env(kernel, global_groups) of
- undefined ->
- no_group;
- {ok, []} ->
- no_group;
- {ok, NodeGrps} ->
- case catch config_scan(NodeGrps, publish_type) of
- {error, _} ->
- no_group;
- {_, PubTpGrp, NodesDef, _} ->
- {PubTpGrp, NodesDef}
- end
- end.
+-spec participant(Node::node()) -> boolean().
-%%%====================================================================================
-%%% Help function which computes publication list
-%%%====================================================================================
-publish_on_nodes(normal, no_group) ->
- all;
-publish_on_nodes(hidden, no_group) ->
- [];
-publish_on_nodes(normal, {normal, _}) ->
- all;
-publish_on_nodes(hidden, {_, Nodes}) ->
- Nodes;
-publish_on_nodes(_, {hidden, Nodes}) ->
- Nodes.
+participant(Node) ->
+ case lookup_group_conf(false) of
+ #gconf{group_map = all} ->
+ true;
+ #gconf{group_map = #{Node := ok}} ->
+ true;
+ #gconf{} ->
+ false
+ end.
%%%====================================================================================
-%%% Update net_kernels publication list
+%%% Is node member of our configured group?
%%%====================================================================================
-update_publish_nodes(PubArg) ->
- update_publish_nodes(PubArg, no_group).
-update_publish_nodes(PubArg, MyGroup) ->
- net_kernel:update_publish_nodes(publish_on_nodes(PubArg, MyGroup)).
+-spec member(Node::node()) -> boolean().
+
+member(Node) ->
+ member(false, Node).
+
+member(GG, Node) ->
+ case lookup_group_conf(GG) of
+ #gconf{group_map = #{Node := ok}} ->
+ true;
+ #gconf{} ->
+ false
+ end.
%%%====================================================================================
-%%% Fetch publication list
+%%% Publish on node?
%%%====================================================================================
-publish_on_nodes() ->
- publish_on_nodes(publish_arg(), own_group()).
+
+-spec publish(OwnPublishType, Node) -> boolean() when
+ OwnPublishType :: 'hidden' | 'normal',
+ Node :: node().
+
+publish(OwnPublishType, Node) when (OwnPublishType == normal
+ orelse OwnPublishType == hidden)
+ andalso is_atom(Node) ->
+ case lookup_group_conf(false) of
+ #gconf{group_map = all} when OwnPublishType == normal ->
+ true;
+ #gconf{group_map = all} when OwnPublishType == hidden ->
+ false;
+ #gconf{group_publish_type = normal} when OwnPublishType == normal ->
+ true;
+ #gconf{group_map = #{Node := ok}} ->
+ true;
+ #gconf{} ->
+ false
+ end.
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index ffd9fd668a..dadcfaea0e 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -370,7 +370,7 @@ check_system([?SCHEDULER_CHECK_OPT|Opts]) ->
%% return 'ok' if everything is alright.
%% Terminate if with reason if something is a miss.
%% It is fine to timeout in the callback, in fact that is the intention
-%% if something goes wront -> no heartbeat.
+%% if something goes wrong -> no heartbeat.
check_callback(Callback) ->
case Callback of
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 16bdc8e099..d836f6b367 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,8 @@
ifget/3, ifget/2, ifset/3, ifset/2,
getstat/1, getstat/2,
info/1, socket_to_list/1,
- ip/1, stats/0, options/0,
+ ip/1, is_ipv4_address/1, is_ipv6_address/1, is_ip_address/1,
+ stats/0, options/0,
pushf/3, popf/1, close/1, gethostname/0, gethostname/1,
parse_ipv4_address/1, parse_ipv6_address/1, parse_ipv4strict_address/1,
parse_ipv6strict_address/1, parse_address/1, parse_strict_address/1,
@@ -85,7 +86,8 @@
ip6_address/0, ip_address/0, port_number/0,
family_address/0, local_address/0,
socket_address/0, returned_non_ip_address/0,
- socket_setopt/0, socket_getopt/0, ancillary_data/0,
+ socket_setopt/0, socket_getopt/0, socket_optval/0,
+ ancillary_data/0,
posix/0, socket/0, inet_backend/0, stat_option/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -146,8 +148,13 @@
-type socket_setopt() ::
gen_sctp:option() | gen_tcp:option() | gen_udp:option().
+-type socket_optval() ::
+ gen_sctp:option_value() | gen_tcp:option() | gen_udp:option() |
+ gen_tcp:pktoptions_value().
+
-type socket_getopt() ::
gen_sctp:option_name() | gen_tcp:option_name() | gen_udp:option_name().
+
-type ether_address() :: [0..255].
-type if_setopt() ::
@@ -398,7 +405,7 @@ setopts(Socket, Opts) ->
{'ok', OptionValues} | {'error', posix()} when
Socket :: socket(),
Options :: [socket_getopt()],
- OptionValues :: [socket_setopt() | gen_tcp:pktoptions_value()].
+ OptionValues :: [socket_optval()].
getopts(?module_socket(GenSocketMod, _) = Socket, Opts)
when is_atom(GenSocketMod) ->
@@ -754,6 +761,25 @@ ip(Name) ->
Error -> Error
end.
+-spec is_ipv4_address(IPv4Address) -> boolean() when
+ IPv4Address :: ip4_address() | term().
+is_ipv4_address({A,B,C,D}) when ?ip(A,B,C,D) ->
+ true;
+is_ipv4_address(_) ->
+ false.
+
+-spec is_ipv6_address(IPv6Address) -> boolean() when
+ IPv6Address :: ip6_address() | term().
+is_ipv6_address({A,B,C,D,E,F,G,H}) when ?ip6(A,B,C,D,E,F,G,H) ->
+ true;
+is_ipv6_address(_) ->
+ false.
+
+-spec is_ip_address(IPAddress) -> boolean() when
+ IPAddress :: ip_address() | term().
+is_ip_address(Address) ->
+ is_ipv4_address(Address) orelse is_ipv6_address(Address).
+
%% This function returns the erlang port used (with inet_drv)
-spec getll(Socket :: socket()) -> {'ok', socket()}.
@@ -854,28 +880,28 @@ ntoa(Addr) ->
-spec parse_ipv4_address(Address) ->
{ok, IPv4Address} | {error, einval} when
Address :: string(),
- IPv4Address :: ip_address().
+ IPv4Address :: ip4_address().
parse_ipv4_address(Addr) ->
inet_parse:ipv4_address(Addr).
-spec parse_ipv6_address(Address) ->
{ok, IPv6Address} | {error, einval} when
Address :: string(),
- IPv6Address :: ip_address().
+ IPv6Address :: ip6_address().
parse_ipv6_address(Addr) ->
inet_parse:ipv6_address(Addr).
-spec parse_ipv4strict_address(Address) ->
{ok, IPv4Address} | {error, einval} when
Address :: string(),
- IPv4Address :: ip_address().
+ IPv4Address :: ip4_address().
parse_ipv4strict_address(Addr) ->
inet_parse:ipv4strict_address(Addr).
-spec parse_ipv6strict_address(Address) ->
{ok, IPv6Address} | {error, einval} when
Address :: string(),
- IPv6Address :: ip_address().
+ IPv6Address :: ip6_address().
parse_ipv6strict_address(Addr) ->
inet_parse:ipv6strict_address(Addr).
@@ -926,7 +952,8 @@ stats() ->
%% Available options for tcp:connect
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
connect_options() ->
- [tos, tclass, priority, reuseaddr, keepalive, linger, nodelay,
+ [debug,
+ tos, tclass, priority, reuseaddr, keepalive, linger, nodelay,
sndbuf, recbuf,
recvtos, recvtclass, ttl, recvttl,
header, active, packet, packet_size, buffer, mode, deliver, line_delimiter,
@@ -1015,7 +1042,9 @@ con_add(Name, Val, #connect_opts{} = R, Opts, AllOpts) ->
%% Available options for tcp:listen
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listen_options() ->
- [tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ [debug,
+ tos, tclass,
+ priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
recvtos, recvtclass, ttl, recvttl,
header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
@@ -1123,6 +1152,7 @@ gen_tcp_module(Opts, socket) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
udp_options() ->
[
+ debug,
tos, tclass,
priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode,
recvtos, recvtclass, ttl, recvttl, deliver, ipv6_v6only,
@@ -1173,9 +1203,20 @@ udp_opt([Opt | Opts], #udp_opts{ifaddr = IfAddr} = R, As) ->
{error, badarg}
end;
{active,N} when is_integer(N), N < 32768, N >= -32768 ->
- NOpts = lists:keydelete(active, 1, R#udp_opts.opts),
- udp_opt(Opts, R#udp_opts { opts = [{active,N}|NOpts] }, As);
+ POpts = lists:keydelete(active, 1, R#udp_opts.opts),
+ udp_opt(Opts, R#udp_opts { opts = [{active,N}|POpts] }, As);
+
+ {Membership, {MAddr, If}}
+ when ((Membership =:= add_membership) orelse
+ (Membership =:= drop_membership)) andalso
+ (tuple_size(MAddr) =:= 4) andalso
+ ((If =:= any) orelse (tuple_size(If) =:= 4)) ->
+ MembershipOpt = {Membership, {MAddr, If, 0}},
+ POpts = R#udp_opts.opts,
+ udp_opt(Opts, R#udp_opts{opts = [MembershipOpt|POpts]}, As);
+
{Name,Val} when is_atom(Name) -> udp_add(Name, Val, R, Opts, As);
+
_ -> {error, badarg}
end;
udp_opt([], #udp_opts{} = R, _SockOpts) ->
@@ -1222,6 +1263,7 @@ gen_udp_module(Opts, socket) ->
% (*) passing of open FDs ("fdopen") is not supported.
sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
+ debug,
mode, active, buffer, tos, tclass, ttl,
priority, dontroute, reuseaddr, linger,
recvtos, recvtclass, recvttl,
@@ -1752,7 +1794,7 @@ open_bind(
open_fd(Fd, BAddr, BPort, Opts, Protocol, Family, Type, Module) ->
DoNotBind =
%% We do not do any binding if no port+addr options
- %% were given, in order to keep backwards compatability
+ %% were given, in order to keep backwards compatibility
%% with pre Erlang/OTP 17
BAddr =:= undefined, % Presumably already bound
if
@@ -2289,4 +2331,8 @@ lock_socket(S,Val) ->
ensure_sockaddr(SockAddr) ->
- prim_socket:enc_sockaddr(SockAddr).
+ try prim_socket:enc_sockaddr(SockAddr)
+ catch
+ throw : {invalid, _} = Invalid : Stacktrace ->
+ erlang:raise(error, Invalid, Stacktrace)
+ end.
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index 0e04088736..6e3d2ad26e 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
-include("inet_int.hrl").
-export([getserv/1, getaddr/1, getaddr/2, translate_ip/1]).
--export([open/1, close/1, listen/2, peeloff/2, connect/4, connect/5]).
+-export([open/1, close/1, listen/2, peeloff/2, connect/4, connect/5, connectx/3, connectx/4]).
-export([sendmsg/3, send/4, recv/2]).
-define(PROTO, sctp).
@@ -81,6 +81,12 @@ connect(S, SockAddr, Opts, Timer) ->
connect(S, Addr, Port, Opts, Timer) ->
inet_sctp:connect(S, Addr, Port, Opts, Timer).
+connectx(S, SockAddrs, Opts) ->
+ inet_sctp:connectx(S, SockAddrs, Opts).
+
+connectx(S, Addr, Port, Opts) ->
+ inet_sctp:connectx(S, Addr, Port, Opts).
+
sendmsg(S, SRI, Data) ->
prim_inet:sendmsg(S, SRI, Data).
diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl
index c1ff478cc2..3b4c4287bc 100644
--- a/lib/kernel/src/inet_config.erl
+++ b/lib/kernel/src/inet_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -213,7 +213,7 @@ add_dns_lookup([],Acc) ->
%%
%% Set the hostname (SHORT)
%% If hostname is long use the suffix as default domain
-%% and initalize the search option with the parts of domain
+%% and initialize the search option with the parts of domain
%%
set_hostname() ->
case inet_udp:open(0,[]) of
diff --git a/lib/kernel/src/inet_db.erl b/lib/kernel/src/inet_db.erl
index e2d9b25868..408f563909 100644
--- a/lib/kernel/src/inet_db.erl
+++ b/lib/kernel/src/inet_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -67,11 +67,11 @@
-export([res_option/1, res_option/2, res_check_option/2]).
-export([socks_option/1]).
-export([getbyname/2, get_searchlist/0]).
--export([gethostbyaddr/1]).
--export([res_gethostbyaddr/2,res_hostent_by_domain/3]).
+-export([gethostbyaddr/2]).
+-export([res_gethostbyaddr/3,res_hostent_by_domain/3]).
-export([res_update_conf/0, res_update_hosts/0]).
%% inet help functions
--export([tolower/1]).
+-export([tolower/1, eq_domains/2]).
-ifdef(DEBUG).
-define(dbg(Fmt, Args), io:format(Fmt, Args)).
-else.
@@ -308,7 +308,7 @@ translate_lookup([]) -> [].
valid_lookup() -> [dns, file, yp, nis, nisplus, native].
-%% Reconstruct an inetrc sturcture from inet_db
+%% Reconstruct an inetrc structure from inet_db
get_rc() ->
get_rc([hosts, domain, nameservers, search, alt_nameservers,
timeout, retry, servfail_retry_timeout, inet6, usevc,
@@ -498,7 +498,7 @@ res_check_option(nameservers, NSs) ->
res_check_option(alt_nameservers, NSs) ->
res_check_list(NSs, fun res_check_ns/1);
res_check_option(domain, Dom) ->
- inet_parse:visible_string(Dom);
+ Dom =:= "" orelse inet_parse:visible_string(Dom);
res_check_option(lookup, Methods) ->
try lists_subtract(Methods, valid_lookup()) of
[] -> true;
@@ -584,19 +584,35 @@ db_get(Name) ->
end.
add_rr(RR) ->
- call({add_rr, RR}).
+ %% Questionable if we need to support this;
+ %% not used by OTP
+ %%
+ res_cache_answer([RR]).
add_rr(Domain, Class, Type, TTL, Data) ->
- call({add_rr, dns_rr_add(Domain, Class, Type, TTL, Data)}).
+ %% Only used from a test suite within OTP,
+ %% can be optimized to create the whole record inline
+ %% and call {add_rrs, [RR]} directly
+ RR =
+ #dns_rr{
+ domain = Domain, class = Class, type = Type,
+ ttl = TTL, data = Data},
+ res_cache_answer([RR]).
del_rr(Domain, Class, Type, Data) ->
- call({del_rr, dns_rr_match(Domain, Class, Type, Data)}).
-
-res_cache_answer(Rec) ->
- lists:foreach( fun(RR) -> add_rr(RR) end, Rec#dns_rec.anlist).
+ call({del_rr, dns_rr_match(tolower(Domain), Class, Type, Data)}).
-
+res_cache_answer(RRs) ->
+ TM = times(),
+ call(
+ {add_rrs,
+ [RR#dns_rr{
+ bm = tolower(RR#dns_rr.domain), tm = TM, cnt = TM}
+ || #dns_rr{ttl = TTL} = RR <- RRs,
+ %% Do not cache TTL 0 entries - they are only used
+ %% to resolve the current lookup
+ 0 < TTL]}).
%%
%% getbyname (cache version)
@@ -638,6 +654,34 @@ get_searchlist() ->
end.
+%%
+%% hostent_by_domain (cache version)
+%%
+hostent_by_domain(Domain, Type) ->
+ ?dbg("hostent_by_domain: ~p~n", [Domain]),
+ case resolve_cnames(stripdot(Domain), Type, fun lookup_cache_data/2) of
+ {error, _} = Error ->
+ Error;
+ {D, Addrs, Aliases} ->
+ {ok, make_hostent(D, Addrs, Aliases, Type)}
+ end.
+
+%%
+%% hostent_by_domain (newly resolved version)
+%% match data field directly and cache RRs.
+%%
+res_hostent_by_domain(Domain, Type, Rec) ->
+ RRs = res_filter_rrs(Type, Rec#dns_rec.anlist),
+ ?dbg("res_hostent_by_domain: ~p - ~p~n", [Domain, RRs]),
+ LookupFun = res_lookup_fun(RRs),
+ case resolve_cnames(stripdot(Domain), Type, LookupFun) of
+ {error, _} = Error ->
+ Error;
+ {D, Addrs, Aliases} ->
+ res_cache_answer(RRs),
+ {ok, make_hostent(D, Addrs, Aliases, Type)}
+ end.
+
make_hostent(Name, Addrs, Aliases, ?S_A) ->
#hostent {
h_name = Name,
@@ -664,149 +708,114 @@ make_hostent(Name, Datas, Aliases, Type) ->
h_aliases = Aliases
}.
-hostent_by_domain(Domain, Type) ->
- ?dbg("hostent_by_domain: ~p~n", [Domain]),
- hostent_by_domain(stripdot(Domain), [], [], Type).
-hostent_by_domain(Domain, Aliases, LAliases, Type) ->
- case lookup_type(Domain, Type) of
- [] ->
- case lookup_cname(Domain) of
- [] ->
- {error, nxdomain};
- [CName | _] ->
- LDomain = tolower(Domain),
- case lists:member(CName, [LDomain | LAliases]) of
- true ->
- {error, nxdomain};
- false ->
- hostent_by_domain(CName, [Domain | Aliases],
- [LDomain | LAliases], Type)
- end
- end;
- Addrs ->
- {ok, make_hostent(Domain, Addrs, Aliases, Type)}
- end.
-
-%% lookup address record
-lookup_type(Domain, Type) ->
- [R#dns_rr.data || R <- lookup_rr(Domain, in, Type) ].
-%% lookup canonical name
-lookup_cname(Domain) ->
- [R#dns_rr.data || R <- lookup_rr(Domain, in, ?S_CNAME) ].
+res_filter_rrs(Type, RRs) ->
+ [RR#dns_rr{bm = tolower(N)} ||
+ #dns_rr{
+ domain = N,
+ class = in,
+ type = T} = RR <- RRs,
+ T =:= Type orelse T =:= ?S_CNAME].
-lookup_cname(Domain, Type) ->
- case Type of
- a -> [];
- aaaa -> [];
- cname -> lookup_cname(Domain);
- _ -> []
+res_lookup_fun(RRs) ->
+ fun (LcDomain, Type) ->
+ [Data
+ || #dns_rr{bm = LcD, type = T, data = Data}
+ <- RRs,
+ LcD =:= LcDomain,
+ T =:= Type]
end.
-%% lookup resource record
-lookup_rr(Domain, Class, Type) ->
- match_rr(dns_rr_match(tolower(Domain), Class, Type)).
-
-%%
-%% hostent_by_domain (newly resolved version)
-%% match data field directly and cache RRs.
-%%
-res_hostent_by_domain(Domain, Type, Rec) ->
- RRs = lists:map(fun lower_rr/1, Rec#dns_rec.anlist),
- res_cache_answer(Rec#dns_rec{anlist = RRs}),
- ?dbg("res_hostent_by_domain: ~p - ~p~n", [Domain, RRs]),
- res_hostent_by_domain(stripdot(Domain), [], [], Type, RRs).
-
-res_hostent_by_domain(Domain, Aliases, LAliases, Type, RRs) ->
- LDomain = tolower(Domain),
- case res_lookup_type(LDomain, Type, RRs) of
- [] ->
- case res_lookup_type(LDomain, ?S_CNAME, RRs) of
- [] ->
- {error, nxdomain};
- [CName | _] ->
- case lists:member(tolower(CName), [LDomain | LAliases]) of
- true ->
- {error, nxdomain};
- false ->
- res_hostent_by_domain(CName, [Domain | Aliases],
- [LDomain | LAliases], Type,
- RRs)
- end
- end;
- Addrs ->
- {ok, make_hostent(Domain, Addrs, Aliases, Type)}
+resolve_cnames(Domain, Type, LookupFun) ->
+ resolve_cnames(Domain, Type, LookupFun, tolower(Domain), [], []).
+
+resolve_cnames(Domain, Type, LookupFun, LcDomain, Aliases, LcAliases) ->
+ case LookupFun(LcDomain, Type) of
+ [] ->
+ case LookupFun(LcDomain, ?S_CNAME) of
+ [] ->
+ %% Did not find neither Type nor CNAME record
+ {error, nxdomain};
+ [CName] ->
+ LcCname = tolower(CName),
+ case lists:member(LcCname, [LcDomain | LcAliases]) of
+ true ->
+ %% CNAME loop
+ {error, nxdomain};
+ false ->
+ %% Repeat with the (more) canonical domain name
+ resolve_cnames(
+ CName, Type, LookupFun, LcCname,
+ [Domain | Aliases], [LcDomain, LcAliases])
+ end;
+ [_ | _] = _CNames ->
+ ?dbg("resolve_cnames duplicate cnames=~p~n", [_CNames]),
+ {error, nxdomain}
+ end;
+ [_ | _] = Results ->
+ {Domain, Results, Aliases}
end.
-%% newly resolved lookup address record
-res_lookup_type(Domain,Type,RRs) ->
- [R#dns_rr.data || R <- RRs,
- R#dns_rr.domain =:= Domain,
- R#dns_rr.type =:= Type].
%%
%% gethostbyaddr (cache version)
%% match data field directly
%%
-gethostbyaddr(IP) ->
- case dnip(IP) of
- {ok, {IP1, HType, HLen, DnIP}} ->
- RRs = match_rr(dns_rr_match(DnIP, in, ptr)),
- ent_gethostbyaddr(RRs, IP1, HType, HLen);
- Error -> Error
+gethostbyaddr(Domain, IP) ->
+ ?dbg("gethostbyaddr: ~p~n", [IP]),
+ case resolve_cnames(Domain, ?S_PTR, fun lookup_cache_data/2) of
+ {error, _} = Error ->
+ Error;
+ {_D, Domains, _Aliases} ->
+ ent_gethostbyaddr(Domains, IP)
end.
%%
%% res_gethostbyaddr (newly resolved version)
%% match data field directly and cache RRs.
%%
-res_gethostbyaddr(IP, Rec) ->
- {ok, {IP1, HType, HLen}} = dnt(IP),
- RRs = lists:map(fun lower_rr/1, Rec#dns_rec.anlist),
- res_cache_answer(Rec#dns_rec{anlist = RRs}),
- ent_gethostbyaddr(Rec#dns_rec.anlist, IP1, HType, HLen).
-
-ent_gethostbyaddr(RRs, IP, AddrType, Length) ->
- case RRs of
- [] -> {error, nxdomain};
- [RR|TR] ->
- %% debug
- if TR =/= [] ->
- ?dbg("gethostbyaddr found extra=~p~n", [TR]);
- true -> ok
- end,
- Type = RR#dns_rr.type,
- Domain = RR#dns_rr.data,
- H = #hostent { h_name = Domain,
- h_aliases = lookup_cname(Domain, Type),
- h_addr_list = [IP],
- h_addrtype = AddrType,
- h_length = Length },
- {ok, H}
- end.
-
-dnip(IP) ->
- case dnt(IP) of
- {ok,{IP1 = {A,B,C,D}, inet, HLen}} ->
- {ok,{IP1, inet, HLen, dn_in_addr_arpa(A,B,C,D)}};
- {ok,{IP1 = {A,B,C,D,E,F,G,H}, inet6, HLen}} ->
- {ok,{IP1, inet6, HLen, dn_ip6_int(A,B,C,D,E,F,G,H)}};
- _ ->
- {error, formerr}
+res_gethostbyaddr(Domain, IP, Rec) ->
+ RRs = res_filter_rrs(?S_PTR, Rec#dns_rec.anlist),
+ ?dbg("res_gethostbyaddr: ~p - ~p~n", [IP, RRs]),
+ LookupFun = res_lookup_fun(RRs),
+ case resolve_cnames(Domain, ?S_PTR, LookupFun) of
+ {error, _} = Error ->
+ Error;
+ {_D, Domains, _Aliases} ->
+ case ent_gethostbyaddr(Domains, IP) of
+ {ok, _HEnt} = Result ->
+ res_cache_answer(RRs),
+ Result;
+ {error, _} = Error ->
+ Error
+ end
end.
+ent_gethostbyaddr([Domain], IP) ->
+ HEnt =
+ if
+ tuple_size(IP) =:= 4 ->
+ #hostent{
+ h_name = Domain,
+ h_aliases = [],
+ h_addr_list = [IP],
+ h_addrtype = inet,
+ h_length = 4};
+ tuple_size(IP) =:= 8 ->
+ #hostent{
+ h_name = Domain,
+ h_aliases = [],
+ h_addr_list = [IP],
+ h_addrtype = inet6,
+ h_length = 16}
+ end,
+ {ok, HEnt};
+ent_gethostbyaddr([_ | _] = _Domains, _IP) ->
+ ?dbg("gethostbyaddr duplicate domains=~p~n", [_Domains]),
+ {error, nxdomain}.
-dnt(IP = {A,B,C,D}) when ?ip(A,B,C,D) ->
- {ok, {IP, inet, 4}};
-dnt({0,0,0,0,0,16#ffff,G,H}) when is_integer(G+H) ->
- A = G div 256, B = G rem 256, C = H div 256, D = H rem 256,
- {ok, {{A,B,C,D}, inet, 4}};
-dnt(IP = {A,B,C,D,E,F,G,H}) when ?ip6(A,B,C,D,E,F,G,H) ->
- {ok, {IP, inet6, 16}};
-dnt(_) ->
- {error, formerr}.
%%
%% Register socket Modules
@@ -890,7 +899,7 @@ take_socket_type(MRef) ->
%% --------------------
%% {node_auth,N} Ls - List of authentication for node N
%% {node_crypt,N} Ls - List of encryption methods for node N
-%% node_auth Ls - Default authenication
+%% node_auth Ls - Default authentication
%% node_crypt Ls - Default encryption
%%
%% Socket type (used for socket monitors)
@@ -911,7 +920,7 @@ init([]) ->
end,
Db = ets:new(inet_db, [public, named_table]),
reset_db(Db),
- CacheOpts = [public, bag, {keypos,#dns_rr.domain}, named_table],
+ CacheOpts = [public, bag, {keypos,#dns_rr.bm}, named_table],
Cache = ets:new(inet_cache, CacheOpts),
HostsByname = ets:new(inet_hosts_byname, [named_table]),
HostsByaddr = ets:new(inet_hosts_byaddr, [named_table]),
@@ -999,10 +1008,9 @@ handle_call(Request, From, #state{db=Db}=State) ->
IP),
{reply, ok, State};
- {add_rr, RR} when is_record(RR, dns_rr) ->
- ?dbg("add_rr: ~p~n", [RR]),
- do_add_rr(RR, Db, State),
- {reply, ok, State};
+ {add_rrs, RRs} ->
+ ?dbg("add_rrs: ~p~n", [RRs]),
+ {reply, do_add_rrs(RRs, Db, State), State};
{del_rr, RR} when is_record(RR, dns_rr) ->
Cache = State#state.cache,
@@ -1197,7 +1205,7 @@ handle_call(Request, From, #state{db=Db}=State) ->
Reply = handle_put_socket_type(State#state.sockets, MRef, Type),
{reply, Reply, State};
- %% Take (in the 'maps' sence of the word) the socket type of
+ %% Take (in the 'maps' sense of the word) the socket type of
%% this socket monitor (reference).
{take_socket_type, MRef} ->
Reply = handle_take_socket_type(State#state.sockets, MRef),
@@ -1646,35 +1654,40 @@ is_reqname(_) -> false.
%% #dns_rr.cnt is used to store the access time
%% instead of number of accesses.
%%
-do_add_rr(RR, Db, State) ->
+do_add_rrs(RRs, Db, State) ->
CacheDb = State#state.cache,
- TM = times(),
- case alloc_entry(Db, CacheDb, TM) of
+ do_add_rrs(RRs, Db, State, CacheDb).
+
+do_add_rrs([], _Db, _State, _CacheDb) ->
+ ok;
+do_add_rrs([RR | RRs], Db, State, CacheDb) ->
+ case alloc_entry(Db, CacheDb, #dns_rr.tm) of
true ->
%% Add to cache
+ %%
#dns_rr{
- domain = Domain, class = Class, type = Type,
+ bm = LcDomain, class = Class, type = Type,
data = Data} = RR,
DeleteRRs =
ets:match_object(
- CacheDb, dns_rr_match(Domain, Class, Type, Data)),
- InsertRR = RR#dns_rr{tm = TM, cnt = TM},
+ CacheDb, dns_rr_match(LcDomain, Class, Type, Data)),
%% Insert before delete to always have an RR present.
%% Watch out to not delete what we insert.
- case lists:member(InsertRR, DeleteRRs) of
+ case lists:member(RR, DeleteRRs) of
true ->
_ = [ets:delete_object(CacheDb, DelRR) ||
DelRR <- DeleteRRs,
- DelRR =/= InsertRR],
- true;
+ DelRR =/= RR],
+ ok;
false ->
- ets:insert(CacheDb, InsertRR),
+ ets:insert(CacheDb, RR),
_ = [ets:delete_object(CacheDb, DelRR) ||
DelRR <- DeleteRRs],
- true
- end;
+ ok
+ end,
+ do_add_rrs(RRs, Db, State, CacheDb);
false ->
- false
+ ok
end.
@@ -1698,34 +1711,30 @@ dns_rr_match_cnt(Cnt) ->
domain = '_', class = '_', type = '_', data = '_',
cnt = Cnt, tm = '_', ttl = '_', bm = '_', func = '_'}.
%%
-dns_rr_match(Domain, Class, Type) ->
+dns_rr_match(LcDomain, Class, Type) ->
#dns_rr{
- domain = Domain, class = Class, type = Type, data = '_',
- cnt = '_', tm = '_', ttl = '_', bm = '_', func = '_'}.
+ domain = '_', class = Class, type = Type, data = '_',
+ cnt = '_', tm = '_', ttl = '_', bm = LcDomain, func = '_'}.
%%
-dns_rr_match(Domain, Class, Type, Data) ->
+dns_rr_match(LcDomain, Class, Type, Data) ->
#dns_rr{
- domain = Domain, class = Class, type = Type, data = Data,
- cnt = '_', tm = '_', ttl = '_', bm = '_', func = '_'}.
+ domain = '_', class = Class, type = Type, data = Data,
+ cnt = '_', tm = '_', ttl = '_', bm = LcDomain, func = '_'}.
-%% RR creation
--compile({inline, [dns_rr_add/5]}).
-%%
-dns_rr_add(Domain, Class, Type, TTL, Data) ->
- #dns_rr{
- domain = Domain, class = Class, type = Type,
- ttl = TTL, data = Data}.
+lookup_cache_data(LcDomain, Type) ->
+ [Data
+ || #dns_rr{data = Data}
+ <- match_rr(dns_rr_match(LcDomain, in, Type))].
%% We are simultaneously updating the table from all clients
-%% and the server, so we might get duplicate recource records
+%% and the server, so we might get duplicate resource records
%% in the table, i.e identical domain, class, type and data.
%% We embrace that and eliminate duplicates here.
%%
%% Look up all matching objects. The still valid ones
%% should be returned, and updated with a new cnt time.
-%% All expired ones should be deleted. We count TTL 0
-%% RRs as valid but immediately expired.
+%% All expired ones should be deleted.
%%
match_rr(MatchRR) ->
CacheDb = inet_cache,
@@ -1742,12 +1751,6 @@ match_rr(CacheDb, [RR | RRs], Time, ResultRRs, InsertRRs, DeleteRRs) ->
%%
#dns_rr{ttl = TTL, tm = TM, cnt = Cnt} = RR,
if
- TTL =:= 0 ->
- %% Valid, immediately expired; return and delete
- Key = match_rr_key(RR),
- match_rr(
- CacheDb, RRs, Time,
- ResultRRs#{Key => RR}, InsertRRs, [RR | DeleteRRs]);
TM + TTL < Time ->
%% Expired, delete
match_rr(
@@ -1774,16 +1777,10 @@ match_rr(CacheDb, [RR | RRs], Time, ResultRRs, InsertRRs, DeleteRRs) ->
-compile({inline, [match_rr_key/1]}).
match_rr_key(
- #dns_rr{domain = Domain, class = Class, type = Type, data = Data}) ->
- {Domain, Class, Type, Data}.
+ #dns_rr{bm = LcDomain, class = Class, type = Type, data = Data}) ->
+ {LcDomain, Class, Type, Data}.
-%% Lowercase the domain name before storage.
-%%
-lower_rr(#dns_rr{domain=Domain}=RR) when is_list(Domain) ->
- RR#dns_rr { domain = tolower(Domain) };
-lower_rr(RR) -> RR.
-
%%
%% Case fold upper-case to lower-case according to RFC 4343
%% "Domain Name System (DNS) Case Insensitivity Clarification".
@@ -1792,32 +1789,74 @@ lower_rr(RR) -> RR.
%% to much on stdlib. Furthermore string:to_lower/1
%% does not follow RFC 4343.
%%
-tolower([]) -> [];
-tolower([C|Cs]) when is_integer(C) ->
- if C >= $A, C =< $Z ->
- [(C-$A)+$a|tolower(Cs)];
- true ->
- [C|tolower(Cs)]
+tolower(Domain) ->
+ case rfc_4343_lc(Domain) of
+ ok ->
+ %% Optimization for already lowercased domain
+ Domain;
+ LcDomain ->
+ LcDomain
end.
-dn_ip6_int(A,B,C,D,E,F,G,H) ->
- dnib(H) ++ dnib(G) ++ dnib(F) ++ dnib(E) ++
- dnib(D) ++ dnib(C) ++ dnib(B) ++ dnib(A) ++ "ip6.int".
+rfc_4343_lc([]) -> ok; % Optimization for already lowercased domain
+rfc_4343_lc([C | Cs]) when is_integer(C), 0 =< C, C =< 16#10FFFF ->
+ if
+ $A =< C, C =< $Z ->
+ [(C - $A) + $a |
+ case rfc_4343_lc(Cs) of
+ ok ->
+ Cs;
+ LCs ->
+ LCs
+ end];
+ true ->
+ case rfc_4343_lc(Cs) of
+ ok ->
+ ok;
+ LCs ->
+ [C | LCs]
+ end
+ end.
-dn_in_addr_arpa(A,B,C,D) ->
- integer_to_list(D) ++ "." ++
- integer_to_list(C) ++ "." ++
- integer_to_list(B) ++ "." ++
- integer_to_list(A) ++ ".in-addr.arpa".
-dnib(X) ->
- [hex(X), $., hex(X bsr 4), $., hex(X bsr 8), $., hex(X bsr 12), $.].
+%% Case insensitive domain name comparison according to RFC 4343
+%% "Domain Name System (DNS) Case Insensitivity Clarification",
+%% i.e regard $a through $z as equal to $A through $Z.
+%%
+eq_domains([A | As], [B | Bs]) ->
+ if
+ is_integer(A), 0 =< A, A =< 16#10FFFF,
+ is_integer(B), 0 =< B, B =< 16#10FFFF ->
+ %% An upper bound of 255 would be right right now,
+ %% but this algorithm works for any integer. That
+ %% guard just gives the compiler the opportuinity
+ %% to optimize bit operations for machine word size,
+ %% so we might as well use the Unicode upper bound instead.
+ Xor = (A bxor B),
+ if
+ Xor =:= 0 ->
+ eq_domains(As, Bs);
+ Xor =:= ($A bxor $a) ->
+ And = (A band B),
+ if
+ ($A band $a) =< And, And =< ($Z band $z) ->
+ eq_domains(As, Bs);
+ true ->
+ false
+ end;
+ true ->
+ false
+ end
+ end;
+eq_domains([$.], []) ->
+ true;
+eq_domains([], [$.]) ->
+ true;
+eq_domains([], []) ->
+ true;
+eq_domains(As, Bs) when is_list(As), is_list(Bs) ->
+ false.
-hex(X) ->
- X4 = (X band 16#f),
- if X4 < 10 -> X4 + $0;
- true -> (X4-10) + $a
- end.
%% Strip trailing dot, do not produce garbage unless necessary.
%%
@@ -1925,7 +1964,7 @@ delete_oldest(CacheDb, TM, N) ->
%% many duplicate times, which is not unlikely
%% given the second resolution. Therefore it is
%% possible that gb_trees and storing the number
- %% of occurences for a cnt time might be needed,
+ %% of occurrences for a cnt time might be needed,
%% so insertion gets more complicated and slower,
%% and we need our own concept of set size.
%%
diff --git a/lib/kernel/src/inet_dns.hrl b/lib/kernel/src/inet_dns.hrl
index c87786390c..5288c570b2 100644
--- a/lib/kernel/src/inet_dns.hrl
+++ b/lib/kernel/src/inet_dns.hrl
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
%%
-%% Defintion for Domain Name System
+%% Definition for Domain Name System
%%
%%
@@ -153,7 +153,7 @@
%%
%% Structure for query header, the order of the fields is machine and
%% compiler dependent, in our case, the bits within a byte are assignd
-%% least significant first, while the order of transmition is most
+%% least significant first, while the order of transmission is most
%% significant first. This requires a somewhat confusing rearrangement.
%%
-record(dns_header,
@@ -162,7 +162,7 @@
%% byte F0
qr = 0, %% :1 response flag
opcode = 0, %% :4 purpose of message
- aa = 0, %% :1 authoritive answer
+ aa = 0, %% :1 authoritative answer
tc = 0, %% :1 truncated message
rd = 0, %% :1 recursion desired
%% byte F1
@@ -190,9 +190,11 @@
cnt = 0, %% access count
ttl = 0, %% time to live
data = [], %% raw data
- %%
+ %%
tm, %% creation time
- bm = [], %% Bitmap storing domain character case information.
+ bm = "", %% Used to be defined as:
+ %% Bitmap storing domain character case information
+ %% but now; Case normalized domain
func = false %% Was: Optional function calculating the data field.
%% Now: cache-flush Class flag from mDNS RFC 6762
}).
diff --git a/lib/kernel/src/inet_gethost_native.erl b/lib/kernel/src/inet_gethost_native.erl
index d9e817f8e5..328cb01e05 100644
--- a/lib/kernel/src/inet_gethost_native.erl
+++ b/lib/kernel/src/inet_gethost_native.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-behaviour(supervisor_bridge).
%% Supervisor bridge exports
--export([start_link/0, init/1, terminate/2, start_raw/0, run_once/0]).
+-export([start_link/0, init/1, terminate/2]).
%% Server export
-export([server_init/2, main_loop/1]).
@@ -131,10 +131,16 @@ init([]) -> % Called by supervisor_bridge:start_link
start_link() ->
supervisor_bridge:start_link({local, ?PROCNAME_SUP}, ?MODULE, []).
+
+-spec terminate(term(), pid()) -> 'ok'.
+
+terminate(_Reason, Pid) ->
+ (catch exit(Pid, kill)),
+ ok.
+
+%%-----------------------------------------------------------------------
%% Only used in fallback situations, no supervisor, no bridge, serve only until
%% no requests present...
-start_raw() ->
- spawn(?MODULE,run_once,[]).
run_once() ->
Port = do_open_port(get_poolsize(), get_extra_args()),
@@ -158,12 +164,6 @@ run_once() ->
Pid ! {R, {error, timeout}}
end.
--spec terminate(term(), pid()) -> 'ok'.
-
-terminate(_Reason, Pid) ->
- (catch exit(Pid, kill)),
- ok.
-
%%-----------------------------------------------------------------------
%% Server API
%%-----------------------------------------------------------------------
@@ -389,34 +389,43 @@ restart_port(#state{port = Port, requests = Requests}) ->
Requests),
NewPort.
-
+-dialyzer({no_improper_lists, do_open_port/2}).
do_open_port(Poolsize, ExtraArgs) ->
- try
- open_port({spawn,
- ?PORT_PROGRAM++" "++integer_to_list(Poolsize)++" "++
- ExtraArgs},
- [{packet,4},eof,binary,overlapped_io])
+ Args = [integer_to_list(Poolsize)] ++ ExtraArgs,
+ %% open_executable/2 below assumes overlapped_io is at the head
+ Opts = [overlapped_io, {args, Args}, {packet,4}, eof, binary],
+ {ok,[BinDir]} = init:get_argument(bindir),
+ Prog = filename:join(BinDir, ?PORT_PROGRAM),
+ open_executable(Prog, Opts).
+
+open_executable(Prog, Opts) ->
+ try open_port({spawn_executable, Prog}, Opts)
catch
- error:_ ->
- open_port({spawn,
- ?PORT_PROGRAM++" "++integer_to_list(Poolsize)++
- " "++ExtraArgs},
- [{packet,4},eof,binary])
+ error : badarg when hd(Opts) =:= overlapped_io ->
+ open_executable(Prog, tl(Opts));
+ error : Reason ->
+ erlang:halt(
+ "Can not execute "++Prog++" : "++term2string(Reason))
end.
+term2string(Term) ->
+ unicode:characters_to_list(io_lib:format("~tw", [Term])).
+
+
+
get_extra_args() ->
- FirstPart = case application:get_env(kernel, gethost_prioritize) of
- {ok, false} ->
- " -ng";
- _ ->
- ""
- end,
- case application:get_env(kernel, gethost_extra_args) of
- {ok, L} when is_list(L) ->
- FirstPart++" "++L;
- _ ->
- FirstPart++""
- end.
+ case application:get_env(kernel, gethost_prioritize) of
+ {ok, false} ->
+ ["-ng"];
+ _ ->
+ []
+ end ++
+ case application:get_env(kernel, gethost_extra_args) of
+ {ok, L} when is_list(L) ->
+ string:tokens(L, " ");
+ _ ->
+ []
+ end.
get_poolsize() ->
case application:get_env(kernel, gethost_poolsize) of
@@ -508,6 +517,34 @@ getit(Req, DefaultName) ->
Res2
end.
+ensure_started() ->
+ case whereis(?MODULE) of
+ undefined ->
+ ChildSpec =
+ {?PROCNAME_SUP, {?MODULE, start_link, []}, temporary,
+ 1000, worker, [?MODULE]},
+ ensure_started([kernel_safe_sup, net_sup], ChildSpec);
+ Pid ->
+ Pid
+ end.
+
+ensure_started([Supervisor|Supervisors], ChildSpec) ->
+ case whereis(Supervisor) of
+ undefined ->
+ ensure_started(Supervisors, ChildSpec);
+ _ ->
+ do_start(Supervisor, ChildSpec),
+ case whereis(?MODULE) of
+ undefined ->
+ exit({could_not_start_server, ?MODULE});
+ Pid ->
+ Pid
+ end
+ end;
+ensure_started([], _ChildSpec) ->
+ %% Icky fallback, run once without supervisor
+ spawn(fun run_once/0).
+
do_start(Sup, C) ->
{Child,_,_,_,_,_} = C,
case supervisor:start_child(Sup,C) of
@@ -522,38 +559,6 @@ do_start(Sup, C) ->
do_start(Sup, C)
end.
-ensure_started() ->
- case whereis(?MODULE) of
- undefined ->
- C = {?PROCNAME_SUP, {?MODULE, start_link, []}, temporary,
- 1000, worker, [?MODULE]},
- case whereis(kernel_safe_sup) of
- undefined ->
- case whereis(net_sup) of
- undefined ->
- %% Icky fallback, run once without supervisor
- start_raw();
- _ ->
- do_start(net_sup,C),
- case whereis(?MODULE) of
- undefined ->
- exit({could_not_start_server, ?MODULE});
- Pid0 ->
- Pid0
- end
- end;
- _ ->
- do_start(kernel_safe_sup,C),
- case whereis(?MODULE) of
- undefined ->
- exit({could_not_start_server, ?MODULE});
- Pid1 ->
- Pid1
- end
- end;
- Pid ->
- Pid
- end.
parse_address(BinHostent, DefaultName) ->
case catch
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index c19df16205..f4e16c6a76 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
-define(INET_AF_LOOPBACK, 4). % Fake for LOOPBACK in any address family
-define(INET_AF_LOCAL, 5). % For Unix Domain address family
-define(INET_AF_UNDEFINED, 6). % For any unknown address family
+-define(INET_AF_LIST, 7). % List of addresses for sctp connectx
%% type codes to open and gettype - INET_REQ_GETTYPE
-define(INET_TYPE_STREAM, 1).
@@ -163,6 +164,7 @@
-define(INET_OPT_TTL, 46).
-define(INET_OPT_RECVTTL, 47).
-define(TCP_OPT_NOPUSH, 48).
+-define(INET_OPT_DEBUG, 99).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
@@ -370,21 +372,26 @@
(?u8(X0) -
(if (X0) > 127 -> 16#100; true -> 0 end))).
-%% macro for use in guard for checking ip address {A,B,C,D}
+%% macro for guards only that checks IP address {A,B,C,D}
+%% that returns true for an IP address, but returns false
+%% or crashes for other terms
-define(ip(A,B,C,D),
(((A) bor (B) bor (C) bor (D)) band (bnot 16#ff)) =:= 0).
+%% d:o for IP address as one term
-define(ip(Addr),
- ?ip(element(1, (Addr)), element(2, (Addr)),
- element(3, (Addr)), element(4, (Addr)))).
-
+ (tuple_size(Addr) =:= 4 andalso
+ ?ip(element(1, (Addr)), element(2, (Addr)),
+ element(3, (Addr)), element(4, (Addr))))).
+%% d:o IPv6 address
-define(ip6(A,B,C,D,E,F,G,H),
(((A) bor (B) bor (C) bor (D) bor (E) bor (F) bor (G) bor (H))
band (bnot 16#ffff)) =:= 0).
-define(ip6(Addr),
- ?ip6(element(1, (Addr)), element(2, (Addr)),
- element(3, (Addr)), element(4, (Addr)),
- element(5, (Addr)), element(6, (Addr)),
- element(7, (Addr)), element(8, (Addr)))).
+ (tuple_size(Addr) =:= 8 andalso
+ ?ip6(element(1, (Addr)), element(2, (Addr)),
+ element(3, (Addr)), element(4, (Addr)),
+ element(5, (Addr)), element(6, (Addr)),
+ element(7, (Addr)), element(8, (Addr))))).
-define(ether(A,B,C,D,E,F),
(((A) bor (B) bor (C) bor (D) bor (E) bor (F))
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index 4e71944492..4e7809564c 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -71,7 +71,7 @@
-type dns_name() :: string().
--type rr_type() :: a | aaaa | caa | cname | gid | hinfo | ns | mb | md | mg
+-type dns_rr_type() :: a | aaaa | caa | cname | gid | hinfo | ns | mb | md | mg
| mf | minfo | mx | naptr | null | ptr | soa | spf | srv
| txt | uid | uinfo | unspec | uri | wks.
@@ -109,7 +109,7 @@
-spec resolve(Name, Class, Type) -> {ok, dns_msg()} | Error when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Error :: {error, Reason} | {error,{Reason,dns_msg()}},
Reason :: inet:posix() | res_error().
@@ -120,7 +120,7 @@ resolve(Name, Class, Type) ->
{ok, dns_msg()} | Error when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Opts :: [Opt],
Opt :: res_option() | verbose | atom(),
Error :: {error, Reason} | {error,{Reason,dns_msg()}},
@@ -133,7 +133,7 @@ resolve(Name, Class, Type, Opts) ->
{ok, dns_msg()} | Error when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Opts :: [Opt],
Opt :: res_option() | verbose | atom(),
Timeout :: timeout(),
@@ -147,7 +147,7 @@ resolve(Name, Class, Type, Opts, Timeout) ->
Res = res_query(Nm, Class, Type, Opts, Timer),
_ = inet:stop_timer(Timer),
Res;
- Error ->
+ {error, _} = Error ->
Error
end.
@@ -160,7 +160,7 @@ resolve(Name, Class, Type, Opts, Timeout) ->
-spec lookup(Name, Class, Type) -> [dns_data()] when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type().
+ Type :: dns_rr_type().
lookup(Name, Class, Type) ->
lookup(Name, Class, Type, []).
@@ -168,7 +168,7 @@ lookup(Name, Class, Type) ->
-spec lookup(Name, Class, Type, Opts) -> [dns_data()] when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Opts :: [res_option() | verbose].
lookup(Name, Class, Type, Opts) ->
@@ -177,7 +177,7 @@ lookup(Name, Class, Type, Opts) ->
-spec lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()] when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Opts :: [res_option() | verbose],
Timeout :: timeout().
@@ -203,7 +203,7 @@ lookup_filter({error,_}, _, _) -> [].
-spec nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason} when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Reason :: inet:posix() | res_error().
nslookup(Name, Class, Type) ->
@@ -213,14 +213,14 @@ nslookup(Name, Class, Type) ->
{ok, dns_msg()} | {error, Reason} when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Timeout :: timeout(),
Reason :: inet:posix() | res_error();
(Name, Class, Type, Nameservers) ->
{ok, dns_msg()} | {error, Reason} when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Nameservers :: [nameserver()],
Reason :: inet:posix() | res_error().
@@ -233,7 +233,7 @@ nslookup(Name, Class, Type, NSs) -> % For backwards compatibility
{ok, dns_msg()} | {error, Reason} when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Nameservers :: [nameserver()],
Reason :: inet:posix().
@@ -244,7 +244,7 @@ nnslookup(Name, Class, Type, NSs) ->
{ok, dns_msg()} | {error, Reason} when
Name :: dns_name() | inet:ip_address(),
Class :: dns_class(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Timeout :: timeout(),
Nameservers :: [nameserver()],
Reason :: inet:posix().
@@ -355,40 +355,42 @@ gethostbyaddr(IP,Timeout) ->
_ = inet:stop_timer(Timer),
Res.
-gethostbyaddr_tm({A,B,C,D} = IP, Timer) when ?ip(A,B,C,D) ->
- inet_db:res_update_conf(),
- case inet_db:gethostbyaddr(IP) of
- {ok, HEnt} -> {ok, HEnt};
- _ -> res_gethostbyaddr(dn_in_addr_arpa(A,B,C,D), IP, Timer)
- end;
-gethostbyaddr_tm({A,B,C,D,E,F,G,H} = IP, Timer) when ?ip6(A,B,C,D,E,F,G,H) ->
- inet_db:res_update_conf(),
- case inet_db:gethostbyaddr(IP) of
- {ok, HEnt} -> {ok, HEnt};
- _ -> res_gethostbyaddr(dn_ip6_int(A,B,C,D,E,F,G,H), IP, Timer)
- end;
-gethostbyaddr_tm(Addr,Timer) when is_list(Addr) ->
+gethostbyaddr_tm(Addr, Timer) when is_atom(Addr) ->
+ gethostbyaddr_tm(atom_to_list(Addr), Timer);
+gethostbyaddr_tm(Addr, Timer) when is_list(Addr) ->
case inet_parse:address(Addr) of
- {ok, IP} -> gethostbyaddr_tm(IP,Timer);
+ {ok, IP} -> gethostbyaddr_tm(IP, Timer);
_Error -> {error, formerr}
end;
-gethostbyaddr_tm(Addr,Timer) when is_atom(Addr) ->
- gethostbyaddr_tm(atom_to_list(Addr),Timer);
-gethostbyaddr_tm(_,_) -> {error, formerr}.
-
-%%
-%% Send the gethostbyaddr query to:
-%% 1. the list of normal names servers
-%% 2. the list of alternative name servers
-%%
-res_gethostbyaddr(Addr, IP, Timer) ->
- case res_query(Addr, in, ptr, [], Timer) of
- {ok, Rec} ->
- inet_db:res_gethostbyaddr(IP, Rec);
- {error,{qfmterror,_}} -> {error,einval};
- {error,{Reason,_}} -> {error,Reason};
- Error ->
- Error
+gethostbyaddr_tm(IP, Timer) ->
+ %% The call to norm_ip/1 here translates a lookup of
+ %% ::ffff:A.B.C.D (AAAA in ...ip6.arpa) into a plain
+ %% A.B.C.D (A in ...in-addr.arpa) lookup, and pretends
+ %% the result as if it was from the original IPv6 lookup
+ %%
+ case dn_ip(norm_ip(IP)) of
+ {error, _} = Error ->
+ Error;
+ {ok, Name} ->
+ %% Try cached first
+ inet_db:res_update_conf(),
+ case inet_db:gethostbyaddr(Name, IP) of
+ {ok, _HEnt} = Result ->
+ Result;
+ {error, nxdomain} ->
+ %% Do a resolver lookup
+ case res_query(Name, in, ?S_PTR, [], Timer) of
+ {ok, Rec} ->
+ %% Process and cache DNS Record
+ inet_db:res_gethostbyaddr(Name, IP, Rec);
+ {error,{qfmterror,_}} ->
+ {error,einval};
+ {error,{Reason,_}} ->
+ {error,Reason};
+ Error ->
+ Error
+ end
+ end
end.
%% --------------------------------------------------------------------------
@@ -453,10 +455,20 @@ gethostbyname_tm(_Name, _Family, _Timer) ->
%% Caches the answer.
%% --------------------------------------------------------------------------
+%% Duplicate of inet.hrl: #hostent{}, but with DNS RR types in h_addrtype
+%% and dns_data() in h_addr_list.
+-type hostent() ::
+ {'hostent',
+ H_name :: inet:hostname(),
+ H_aliases :: [inet:hostname()],
+ H_addrtype :: dns_rr_type(),
+ H_length :: non_neg_integer(),
+ H_addr_list :: [dns_data()]}.
+
-spec getbyname(Name, Type) -> {ok, Hostent} | {error, Reason} when
Name :: dns_name(),
- Type :: rr_type(),
- Hostent :: inet:hostent(),
+ Type :: dns_rr_type(),
+ Hostent :: inet:hostent() | hostent(),
Reason :: inet:posix() | res_error().
getbyname(Name, Type) ->
@@ -464,9 +476,9 @@ getbyname(Name, Type) ->
-spec getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason} when
Name :: dns_name(),
- Type :: rr_type(),
+ Type :: dns_rr_type(),
Timeout :: timeout(),
- Hostent :: inet:hostent(),
+ Hostent :: inet:hostent() | hostent(),
Reason :: inet:posix() | res_error().
getbyname(Name, Type, Timeout) ->
@@ -479,12 +491,17 @@ getbyname_tm(Name, Type, Timer) when is_list(Name) ->
case type_p(Type) of
true ->
case inet_parse:visible_string(Name) of
- false -> {error, formerr};
+ false ->
+ {error, formerr};
true ->
+ %% Try cached first
inet_db:res_update_conf(),
case inet_db:getbyname(Name, Type) of
- {ok, HEnt} -> {ok, HEnt};
- _ -> res_getbyname(Name, Type, Timer)
+ {ok, HEnt} ->
+ {ok, HEnt};
+ _ ->
+ %% Do a resolver lookup
+ res_getbyname(Name, Type, Timer)
end
end;
false ->
@@ -577,6 +594,7 @@ res_getby_search(_Name, [], Reason,_,_) ->
res_getby_query(Name, Type, Timer) ->
case res_query(Name, in, Type, [], Timer) of
{ok, Rec} ->
+ %% Process and cache DNS Record
inet_db:res_hostent_by_domain(Name, Type, Rec);
{error,{qfmterror,_}} -> {error,einval};
{error,{Reason,_}} -> {error,Reason};
@@ -586,6 +604,7 @@ res_getby_query(Name, Type, Timer) ->
res_getby_query(Name, Type, Timer, NSs) ->
case res_query(Name, in, Type, [], Timer, NSs) of
{ok, Rec} ->
+ %% Process and cache DNS Record
inet_db:res_hostent_by_domain(Name, Type, Rec);
{error,{qfmterror,_}} -> {error,einval};
{error,{Reason,_}} -> {error,Reason};
@@ -649,6 +668,7 @@ make_query(Dname, Class, Type, Opts) ->
make_query(Dname, Class, Type, Options, Edns) ->
Id = inet_db:res_option(next_id),
Recurse = Options#options.recurse,
+ RD = Recurse =:= 1 orelse Recurse =:= true, % (0 | 1 | true | false)
ARList = case Edns of
false -> [];
_ ->
@@ -656,17 +676,18 @@ make_query(Dname, Class, Type, Options, Edns) ->
[#dns_rr_opt{udp_payload_size=PSz,
version=Edns}]
end,
- Msg = #dns_rec{header=#dns_header{id=Id,
+ Msg = #dns_rec{header=#dns_header{id=Id,
+ qr=false,
opcode='query',
- rd=Recurse,
+ rd=RD,
rcode=?NOERROR},
- qdlist=[#dns_query{domain=Dname,
- type=Type,
- class=Class}],
+ qdlist=[#dns_query{domain=Dname,
+ type=Type,
+ class=Class}],
arlist=ARList},
?verbose(Options#options.verbose, "Query: ~p~n", [dns_msg(Msg)]),
Buffer = inet_dns:encode(Msg),
- {Id, Buffer}.
+ {Msg, Buffer}.
%% --------------------------------------------------------------------------
%% socket helpers
@@ -727,7 +748,7 @@ do_udp_recv(I, IP, Port, Timeout, Decode, Time, PollCnt) ->
{ok,Reply} ->
case Decode(Reply) of
false when Timeout =:= 0 ->
- %% This is a compromize between the hard way i.e
+ %% This is a compromise between the hard way i.e
%% in the clause below if Timeout becomes 0 bailout
%% immediately and risk that the right reply lies
%% ahead after some bad id replies, and the
@@ -820,13 +841,13 @@ query_nss_edns(
#q{options =
#options{
udp_payload_size = PSz}=Options,
- edns = {Id,Buffer}}=Q,
+ edns = EDNSQuery}=Q,
[NsSpec|NSs], Timer, Retry, I, S_0, Reason, RetryNSs) ->
%%
{IP,Port} = NS = servfail_retry_wait(NsSpec),
{S,Result} =
query_ns(
- S_0, Id, Buffer, IP, Port, Timer, Retry, I, Options, PSz),
+ S_0, EDNSQuery, IP, Port, Timer, Retry, I, Options, PSz),
case Result of
{error,{E,_}}
when E =:= qfmterror;
@@ -848,19 +869,21 @@ query_nss_edns(
end.
query_nss_dns(
- #q{dns = Qdns}=Q_0,
+ #q{dns = DNSQuery_0}=Q_0,
[NsSpec|NSs], Timer, Retry, I, S_0, Reason, RetryNSs) ->
%%
{IP,Port} = NS = servfail_retry_wait(NsSpec),
#q{options = Options,
- dns = {Id,Buffer}}=Q =
+ dns = DNSQuery}=Q =
if
- is_function(Qdns, 0) -> Q_0#q{dns=Qdns()};
- true -> Q_0
+ is_function(DNSQuery_0, 0) ->
+ Q_0#q{dns=DNSQuery_0()};
+ true ->
+ Q_0
end,
{S,Result} =
query_ns(
- S_0, Id, Buffer, IP, Port, Timer, Retry, I, Options, ?PACKETSZ),
+ S_0, DNSQuery, IP, Port, Timer, Retry, I, Options, ?PACKETSZ),
query_nss_result(
Q, NSs, Timer, Retry, I, S, Reason, RetryNSs, NS, Result).
@@ -952,14 +975,14 @@ query_retries_error(#q{options=#options{nxdomain_reply=NxReply}}, S, Reason) ->
end.
-query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I,
+query_ns(S0, {Msg, Buffer}, IP, Port, Timer, Retry, I,
#options{timeout=Tm,usevc=UseVC,verbose=Verbose},
PSz) ->
case UseVC orelse iolist_size(Buffer) > PSz of
true ->
TcpTimeout = inet:timeout(Tm*5, Timer),
{S0,
- query_tcp(TcpTimeout, Id, Buffer, IP, Port, Verbose)};
+ query_tcp(TcpTimeout, Msg, Buffer, IP, Port, Verbose)};
false ->
case udp_open(S0, IP) of
{ok,S} ->
@@ -967,13 +990,13 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I,
inet:timeout( (Tm * (1 bsl I)) div Retry, Timer),
case
query_udp(
- S, Id, Buffer, IP, Port, UdpTimeout, Verbose)
+ S, Msg, Buffer, IP, Port, UdpTimeout, Verbose)
of
{ok,#dns_rec{header=H}} when H#dns_header.tc ->
TcpTimeout = inet:timeout(Tm*5, Timer),
{S,
query_tcp(
- TcpTimeout, Id, Buffer, IP, Port, Verbose)};
+ TcpTimeout, Msg, Buffer, IP, Port, Verbose)};
{error, econnrefused} = Err ->
ok = udp_close(S),
{#sock{}, Err};
@@ -984,9 +1007,9 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I,
end
end.
-query_udp(_S, _Id, _Buffer, _IP, _Port, 0, _Verbose) ->
+query_udp(_S, _Msg, _Buffer, _IP, _Port, 0, _Verbose) ->
timeout;
-query_udp(S, Id, Buffer, IP, Port, Timeout, Verbose) ->
+query_udp(S, Msg, Buffer, IP, Port, Timeout, Verbose) ->
?verbose(Verbose, "Try UDP server : ~p:~p (timeout=~w)\n",
[IP,Port,Timeout]),
case
@@ -999,7 +1022,7 @@ query_udp(S, Id, Buffer, IP, Port, Timeout, Verbose) ->
Decode =
fun ({RecIP,RecPort,Answer})
when RecIP =:= IP, RecPort =:= Port ->
- case decode_answer(Answer, Id, Verbose) of
+ case decode_answer(Answer, Msg, Verbose) of
{error,badid} ->
false;
Reply ->
@@ -1020,9 +1043,9 @@ query_udp(S, Id, Buffer, IP, Port, Timeout, Verbose) ->
{error,econnrefused}
end.
-query_tcp(0, _Id, _Buffer, _IP, _Port, _Verbose) ->
+query_tcp(0, _Msg, _Buffer, _IP, _Port, _Verbose) ->
timeout;
-query_tcp(Timeout, Id, Buffer, IP, Port, Verbose) ->
+query_tcp(Timeout, Msg, Buffer, IP, Port, Verbose) ->
?verbose(Verbose, "Try TCP server : ~p:~p (timeout=~w)\n",
[IP, Port, Timeout]),
Family = case IP of
@@ -1038,7 +1061,7 @@ query_tcp(Timeout, Id, Buffer, IP, Port, Verbose) ->
case gen_tcp:recv(S, 0, Timeout) of
{ok, Answer} ->
gen_tcp:close(S),
- case decode_answer(Answer, Id, Verbose) of
+ case decode_answer(Answer, Msg, Verbose) of
{ok, _} = OK -> OK;
{error, badid} -> {error, servfail};
Error -> Error
@@ -1062,96 +1085,147 @@ query_tcp(Timeout, Id, Buffer, IP, Port, Verbose) ->
_:_ -> {error, einval}
end.
-decode_answer(Answer, Id, Verbose) ->
+decode_answer(Answer, Q_Msg, Verbose) ->
case inet_dns:decode(Answer) of
- {ok, Msg} ->
+ {ok, #dns_rec{header = H, arlist = ARList} = Msg} ->
?verbose(Verbose, "Got reply: ~p~n", [dns_msg(Msg)]),
- E = case lists:keyfind(dns_rr_opt, 1, Msg#dns_rec.arlist) of
+ E = case lists:keyfind(dns_rr_opt, 1, ARList) of
false -> 0;
#dns_rr_opt{ext_rcode=ExtRCode} -> ExtRCode
end,
- H = Msg#dns_rec.header,
RCode = (E bsl 4) bor H#dns_header.rcode,
case RCode of
- ?NOERROR ->
- if H#dns_header.id =/= Id ->
- {error,badid};
- length(Msg#dns_rec.qdlist) =/= 1 ->
- {error,{noquery,Msg}};
- true ->
- {ok, Msg}
- end;
+ ?NOERROR -> decode_answer_noerror(Q_Msg, Msg, H);
?FORMERR -> {error,{qfmterror,Msg}};
?SERVFAIL -> {error,{servfail,Msg}};
?NXDOMAIN -> {error,{nxdomain,Msg}};
?NOTIMP -> {error,{notimp,Msg}};
?REFUSED -> {error,{refused,Msg}};
?BADVERS -> {error,{badvers,Msg}};
- _ -> {error,{unknown,Msg}}
+ _ -> {error,{unknown,Msg}}
end;
{error, formerr} = Error ->
?verbose(Verbose, "Got reply: decode format error~n", []),
Error
end.
+decode_answer_noerror(
+ #dns_rec{header = Q_H, qdlist = [Q_RR]},
+ #dns_rec{qdlist = QDList} = Msg,
+ H) ->
+ %% Validate the reply
+ if
+ H#dns_header.id =/= Q_H#dns_header.id ->
+ {error,badid};
+ H#dns_header.qr =/= true;
+ H#dns_header.opcode =/= Q_H#dns_header.opcode;
+ H#dns_header.rd =/= Q_H#dns_header.rd ->
+ {error,{unknown,Msg}};
+ true ->
+ case QDList of
+ [RR] ->
+ case
+ (RR#dns_query.class =:= Q_RR#dns_query.class)
+ andalso
+ (RR#dns_query.type =:= Q_RR#dns_query.type)
+ andalso
+ inet_db:eq_domains(
+ RR#dns_query.domain, Q_RR#dns_query.domain)
+ of
+ true ->
+ {ok, Msg};
+ false ->
+ {error,{noquery,Msg}}
+ end;
+ _ when is_list(QDList) ->
+ {error,{noquery,Msg}}
+ end
+ end.
+
%%
%% Transform domain name or address
%% 1. "a.b.c" =>
%% "a.b.c"
%% 2. "1.2.3.4" =>
-%% "4.3.2.1.IN-ADDR.ARPA"
+%% "4.3.2.1.in-addr.arpa"
%% 3. "4321:0:1:2:3:4:567:89ab" =>
-%% "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.1.2.3.4.IP6.ARPA"
+%% "b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.1.2.3.4.ip6.arpa"
%% 4. {1,2,3,4} => as 2.
%% 5. {1,2,3,4,5,6,7,8} => as 3.
+%% 6. Atom -> Recurse(String(Atom))
+%% 7. Term => {error, formerr}
%%
-nsdname({A,B,C,D}) ->
- {ok, dn_in_addr_arpa(A,B,C,D)};
-nsdname({A,B,C,D,E,F,G,H}) ->
- {ok, dn_ip6_int(A,B,C,D,E,F,G,H)};
+nsdname(Name) when is_atom(Name) ->
+ nsdname(atom_to_list(Name));
nsdname(Name) when is_list(Name) ->
case inet_parse:visible_string(Name) of
true ->
case inet_parse:address(Name) of
- {ok, Addr} ->
- nsdname(Addr);
+ {ok, IP} ->
+ dn_ip(IP);
_ ->
{ok, Name}
end;
_ -> {error, formerr}
end;
-nsdname(Name) when is_atom(Name) ->
- nsdname(atom_to_list(Name));
-nsdname(_) -> {error, formerr}.
-
-dn_in_addr_arpa(A,B,C,D) ->
- integer_to_list(D) ++
- ("." ++ integer_to_list(C) ++
- ("." ++ integer_to_list(B) ++
- ("." ++ integer_to_list(A) ++ ".IN-ADDR.ARPA"))).
-
-dn_ip6_int(A,B,C,D,E,F,G,H) ->
- dnib(H) ++
- (dnib(G) ++
- (dnib(F) ++
- (dnib(E) ++
- (dnib(D) ++
- (dnib(C) ++
- (dnib(B) ++
- (dnib(A) ++ "IP6.ARPA"))))))).
-
-
-
--compile({inline, [dnib/1, dnib/3]}).
-dnib(X) ->
- L = erlang:integer_to_list(X, 16),
- dnib(4-length(L), L, []).
+nsdname(IP) ->
+ dn_ip(IP).
+
+%% Return the domain name for a PTR lookup of
+%% the argument IP address
+%%
+dn_ip({A,B,C,D}) when ?ip(A,B,C,D) ->
+ dn_ipv4([A,B,C,D], "in-addr.arpa");
+dn_ip({A,B,C,D,E,F,G,H}) when ?ip6(A,B,C,D,E,F,G,H) ->
+ dn_ipv6([A,B,C,D,E,F,G,H], "ip6.arpa");
+dn_ip(_) ->
+ {error, formerr}.
+
+dn_ipv4([], Dn) ->
+ {ok, Dn};
+dn_ipv4([A | As], Dn_0) when is_integer(A), A =< 255 ->
+ Dn = [$. | Dn_0],
+ if
+ A < 10 ->
+ dn_ipv4(As, dn_dec(A, Dn));
+ A < 100 ->
+ dn_ipv4(As, dn_dec(A div 10, dn_dec(A rem 10, Dn)));
+ true ->
+ B = A rem 100,
+ dn_ipv4(
+ As,
+ dn_dec(A div 100, dn_dec(B div 10, dn_dec(B rem 10, Dn))))
+ end.
+
+dn_ipv6([], Dn) ->
+ {ok, Dn};
+dn_ipv6([W | Ws], Dn) when is_integer(W), W =< 16#ffff ->
+ D = W band 16#f, W_1 = W bsr 4,
+ C = W_1 band 16#f, W_2 = W_1 bsr 4,
+ B = W_2 band 16#f,
+ A = W_2 bsr 4,
+ dn_ipv6(Ws, dn_hex(D, dn_hex(C, dn_hex(B, dn_hex(A, Dn))))).
+
+-compile({inline, [dn_dec/2, dn_hex/2]}).
+dn_dec(N, Tail) when is_integer(N) ->
+ [N + $0 | Tail].
+
+dn_hex(N, Tail) when is_integer(N) ->
+ if
+ N < 10 ->
+ [N + $0, $. | Tail];
+ true ->
+ [(N - 10) + $a, $. | Tail]
+end.
+
+%% Normalize an IPv4-compatible IPv6 address
+%% into a plain IPv4 address
%%
-dnib(0, [], Acc) -> Acc;
-dnib(0, [C|Cs], Acc) ->
- dnib(0, Cs, [C,$.|Acc]);
-dnib(N, Cs, Acc) ->
- dnib(N-1, Cs, [$0,$.|Acc]).
+norm_ip({0,0,0,0,0,16#ffff,G,H}) ->
+ A = G bsr 8, B = G band 16#ff, C = H bsr 8, D = H band 16#ff,
+ {A,B,C,D};
+norm_ip(IP) ->
+ IP.
diff --git a/lib/kernel/src/inet_res.hrl b/lib/kernel/src/inet_res.hrl
index c812550328..19e3f04e75 100644
--- a/lib/kernel/src/inet_res.hrl
+++ b/lib/kernel/src/inet_res.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
%% %CopyrightEnd%
%%
%%
-%% Dns & resolver defintions
+%% Dns & resolver definitions
%%
%% milli second for requests
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index d7020b4bf6..61f6ab0bcd 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
-include("inet_int.hrl").
-export([getserv/1, getaddr/1, getaddr/2, translate_ip/1]).
--export([open/1, close/1, listen/2, peeloff/2, connect/4, connect/5]).
+-export([open/1, close/1, listen/2, peeloff/2, connect/4, connect/5, connectx/3, connectx/4]).
-export([sendmsg/3, send/4, recv/2]).
-define(PROTO, sctp).
@@ -119,6 +119,20 @@ connect(S, Addr, Port, Opts, Timer) ->
Err3 -> Err3
end.
+%% connectx is always non-blocking so there is no timer
+connectx(S, SockAddrs, Opts) ->
+ case prim_inet:chgopts(S, Opts) of
+ ok ->
+ prim_inet:connectx(S, SockAddrs);
+ Err2 -> Err2
+ end.
+
+connectx(S, Addrs, Port, Opts) ->
+ case prim_inet:chgopts(S, Opts) of
+ ok ->
+ prim_inet:connectx(S, Addrs, Port);
+ Err2 -> Err2
+ end.
%% XXX race condition problem
%%
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index d84d5d56bf..b53de6281b 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -86,7 +86,7 @@ listen(Name) ->
gen_listen(Driver, Name, Host) ->
ErlEpmd = net_kernel:epmd_module(),
- case gen_listen(ErlEpmd, Name, Host, Driver, [{active, false}, {packet,2}, {reuseaddr, true}]) of
+ case gen_listen(ErlEpmd, Name, Host, Driver) of
{ok, Socket} ->
TcpAddress = get_tcp_address(Driver, Socket),
{_,Port} = TcpAddress#net_address.address,
@@ -100,8 +100,8 @@ gen_listen(Driver, Name, Host) ->
Error
end.
-gen_listen(ErlEpmd, Name, Host, Driver, Options) ->
- ListenOptions = listen_options(Options),
+gen_listen(ErlEpmd, Name, Host, Driver) ->
+ ListenOptions = listen_options(),
case call_epmd_function(ErlEpmd, listen_port_please, [Name, Host]) of
{ok, 0} ->
{First,Last} = get_port_range(),
@@ -133,25 +133,52 @@ do_listen(Driver, First,Last,Options) ->
Other
end.
-listen_options(Opts0) ->
- Opts1 =
- case application:get_env(kernel, inet_dist_use_interface) of
- {ok, Ip} ->
- [{ip, Ip} | Opts0];
- _ ->
- Opts0
- end,
- case application:get_env(kernel, inet_dist_listen_options) of
- {ok,ListenOpts} ->
- case proplists:is_defined(backlog, ListenOpts) of
- true ->
- ListenOpts ++ Opts1;
- false ->
- ListenOpts ++ [{backlog, 128} | Opts1]
- end;
- _ ->
- [{backlog, 128} | Opts1]
- end.
+listen_options() ->
+ DefaultOpts = [{reuseaddr, true}, {backlog, 128}],
+ ForcedOpts =
+ [{active, false}, {packet,2} |
+ case application:get_env(kernel, inet_dist_use_interface) of
+ {ok, Ip} -> [{ip, Ip}];
+ undefined -> []
+ end],
+ Force = maps:from_list(ForcedOpts),
+ InetDistListenOpts =
+ case application:get_env(kernel, inet_dist_listen_options) of
+ {ok, Opts} -> Opts;
+ undefined -> []
+ end,
+ ListenOpts = listen_options(InetDistListenOpts, ForcedOpts, Force),
+ Seen =
+ maps:from_list(
+ lists:filter(
+ fun ({_,_}) -> true;
+ (_) -> false
+ end, ListenOpts)),
+ lists:filter(
+ fun ({OptName,_}) when is_map_key(OptName, Seen) ->
+ false;
+ (_) ->
+ true
+ end, DefaultOpts) ++ ListenOpts.
+
+%% Pass through all but forced
+listen_options([Opt | Opts], ForcedOpts, Force) ->
+ case Opt of
+ {OptName,_} ->
+ case is_map_key(OptName, Force) of
+ true ->
+ listen_options(Opts, ForcedOpts, Force);
+ false ->
+ [Opt |
+ listen_options(Opts, ForcedOpts, Force)]
+ end;
+ _ ->
+ [Opt |
+ listen_options(Opts, ForcedOpts, Force)]
+ end;
+listen_options([], ForcedOpts, _Force) ->
+ %% Append forced
+ ForcedOpts.
%% ------------------------------------------------------------
@@ -208,7 +235,7 @@ accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
spawn_opt(?MODULE, do_accept,
[Driver, self(), AcceptPid, Socket, MyNode, Allowed, SetupTime],
- [link, {priority, max}]).
+ dist_util:net_ticker_spawn_options()).
do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) ->
receive
@@ -274,7 +301,6 @@ nodelay() ->
{nodelay, true}
end.
-
%% ------------------------------------------------------------
%% Get remote information about a Socket.
%% ------------------------------------------------------------
@@ -304,7 +330,7 @@ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) ->
gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
spawn_opt(?MODULE, do_setup,
[Driver, self(), Node, Type, MyNode, LongOrShortNames, SetupTime],
- [link, {priority, max}]).
+ dist_util:net_ticker_spawn_options()).
do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
?trace("~p~n",[{inet_tcp_dist,self(),setup,Node}]),
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 606e939041..0b760b12fe 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -154,10 +154,10 @@
{logger_sasl_compatible, false},
{net_tickintensity, 4},
{net_ticktime, 60},
- {prevent_overlapping_partitions, false},
+ {prevent_overlapping_partitions, true},
{shell_docs_ansi,auto}
]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-12.3", "stdlib-3.13", "sasl-3.0", "crypto-5.0"]}
- ]
+ {runtime_dependencies, ["erts-13.1.3", "stdlib-4.1.1", "sasl-3.0", "crypto-5.0"]}
+ ]
}.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index da8221196a..709a405244 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -19,23 +19,16 @@
%%
%% We allow upgrade from, and downgrade to all previous
%% versions from the following OTP releases:
-%% - OTP 22
%% - OTP 23
%% - OTP 24
+%% - OTP 25
%%
%% We also allow upgrade from, and downgrade to all
%% versions that have branched off from the above
%% stated previous versions.
%%
{"%VSN%",
- [{<<"^6\\.4$">>,[restart_new_emulator]},
- {<<"^6\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.5$">>,[restart_new_emulator]},
- {<<"^6\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.5\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^7\\.0$">>,[restart_new_emulator]},
+ [{<<"^7\\.0$">>,[restart_new_emulator]},
{<<"^7\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^7\\.1$">>,[restart_new_emulator]},
{<<"^7\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
@@ -58,15 +51,18 @@
{<<"^8\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^8\\.3$">>,[restart_new_emulator]},
{<<"^8\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^8\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
- [{<<"^6\\.4$">>,[restart_new_emulator]},
- {<<"^6\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.5$">>,[restart_new_emulator]},
- {<<"^6\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^6\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^6\\.5\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^7\\.0$">>,[restart_new_emulator]},
+ {<<"^8\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.3\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.4$">>,[restart_new_emulator]},
+ {<<"^8\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.5$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
+ [{<<"^7\\.0$">>,[restart_new_emulator]},
{<<"^7\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^7\\.1$">>,[restart_new_emulator]},
{<<"^7\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
@@ -89,4 +85,14 @@
{<<"^8\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^8\\.3$">>,[restart_new_emulator]},
{<<"^8\\.3\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^8\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
+ {<<"^8\\.3\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.3\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.4$">>,[restart_new_emulator]},
+ {<<"^8\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.5$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^8\\.5\\.3(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index 049db0e50d..9aec16ace7 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -140,10 +140,16 @@ init([]) ->
type => supervisor,
modules => [logger_sup]},
+ Peer = case peer:supervision_child_spec() of
+ {ok, PeerSpec} -> [PeerSpec];
+ none -> []
+ end,
+
case init:get_argument(mode) of
{ok, [["minimal"]|_]} ->
{ok, {SupFlags,
- [Code, File, StdError, User, LoggerSup, Config, RefC, SafeSup]}};
+ [Code, File, StdError] ++ Peer ++
+ [User, LoggerSup, Config, RefC, SafeSup]}};
_ ->
DistChildren =
case application:get_env(kernel, start_distribution) of
@@ -170,7 +176,8 @@ init([]) ->
{ok, {SupFlags,
[Code, InetDb | DistChildren] ++
- [File, SigSrv, StdError, User, Config, RefC, SafeSup, LoggerSup] ++
+ [File, SigSrv, StdError] ++ Peer ++
+ [User, Config, RefC, SafeSup, LoggerSup] ++
Timer ++ CompileServer}}
end;
init(safe) ->
diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
index 1f8e300dd9..73a86dd3ca 100644
--- a/lib/kernel/src/logger.erl
+++ b/lib/kernel/src/logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -997,7 +997,7 @@ get_primary_metadata() ->
{ok, Meta} ->
throw({logger_metadata, Meta});
undefined ->
- %% This case is here to keep bug compatability. Can be removed in OTP 25.
+ %% This case is here to keep bug compatibility. Can be removed in OTP 25.
case application:get_env(kernel,logger_default_metadata,#{}) of
Meta when is_map(Meta) ->
Meta;
@@ -1156,12 +1156,13 @@ log_fun_allowed(Location, Level, FunRes, Meta, FunCall) ->
Meta)
end.
-do_log_allowed(Level,{Format,Args}=Msg,Meta,Tid,Config)
+do_log_allowed(Level,{Format,Args},Meta,Tid,Config)
when ?IS_LEVEL(Level),
?IS_FORMAT(Format),
is_list(Args),
is_map(Meta) ->
- logger_backend:log_allowed(#{level=>Level,msg=>Msg,meta=>Meta},Tid,Config);
+ logger_backend:log_allowed(#{level=>Level,msg=>{deatomize(Format),Args},meta=>Meta},
+ Tid,Config);
do_log_allowed(Level,Report,Meta,Tid,Config)
when ?IS_LEVEL(Level),
?IS_REPORT(Report),
@@ -1177,6 +1178,9 @@ do_log_allowed(Level,String,Meta,Tid,Config)
tid() ->
ets:whereis(?LOGGER_TABLE).
+deatomize(Atom) when is_atom(Atom) -> atom_to_list(Atom);
+deatomize(Other) -> Other.
+
log_remote(Node,Level,{Format,Args},Meta) ->
log_remote(Node,{log,Level,Format,Args,Meta});
log_remote(Node,Level,Msg,Meta) ->
@@ -1209,7 +1213,7 @@ default(pid) -> self();
default(gl) -> group_leader();
default(time) -> timestamp().
-%% Remove everything upto and including this module from the stacktrace
+%% Remove everything up to and including this module from the stacktrace
filter_stacktrace(Module,[{Module,_,_,_}|_]) ->
[];
filter_stacktrace(Module,[H|T]) ->
diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl
index 8be6b5e69c..2f386acbf3 100644
--- a/lib/kernel/src/logger_disk_log_h.erl
+++ b/lib/kernel/src/logger_disk_log_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,8 +58,8 @@ adding_handler(Config) ->
%%%-----------------------------------------------------------------
%%% Updating handler config
-changing_config(SetOrUpdate, OldConfig, NewConfig) ->
- logger_h_common:changing_config(SetOrUpdate, OldConfig, NewConfig).
+changing_config(SetOrUpdate,OldConfig,NewConfig) ->
+ logger_h_common:changing_config(SetOrUpdate,OldConfig,NewConfig).
%%%-----------------------------------------------------------------
%%% Handler being removed
@@ -68,12 +68,12 @@ removing_handler(Config) ->
%%%-----------------------------------------------------------------
%%% Log a string or report
--spec log(LogEvent, Config) -> ok when
+-spec log(LogEvent,Config) -> ok when
LogEvent :: logger:log_event(),
Config :: logger:handler_config().
-log(LogEvent, Config) ->
- logger_h_common:log(LogEvent, Config).
+log(LogEvent,Config) ->
+ logger_h_common:log(LogEvent,Config).
%%%-----------------------------------------------------------------
%%% Remove internal fields from configuration
@@ -86,19 +86,19 @@ filter_config(Config) ->
init(Name, #{file:=File,type:=Type,max_no_bytes:=MNB,max_no_files:=MNF}) ->
case open_disk_log(Name, File, Type, MNB, MNF) of
ok ->
- {ok,#{log_opts => #{file => File,
- type => Type,
- max_no_bytes => MNB,
- max_no_files => MNF},
- prev_log_result => ok,
- prev_sync_result => ok,
- prev_disk_log_info => undefined}};
+ {ok,#{log_opts=>#{file=>File,
+ type=>Type,
+ max_no_bytes=>MNB,
+ max_no_files=>MNF},
+ prev_log_result=>ok,
+ prev_sync_result=>ok,
+ prev_disk_log_info=>undefined}};
Error ->
Error
end.
check_config(Name,set,undefined,HConfig0) ->
- HConfig=merge_default_logopts(Name,maps:merge(get_default_config(),HConfig0)),
+ HConfig=merge_default_logopts(Name,HConfig0),
check_config(HConfig);
check_config(_Name,SetOrUpdate,OldHConfig,NewHConfig0) ->
WriteOnce = maps:with([type,file,max_no_files,max_no_bytes],OldHConfig),
@@ -106,7 +106,7 @@ check_config(_Name,SetOrUpdate,OldHConfig,NewHConfig0) ->
case SetOrUpdate of
set ->
%% Do not reset write-once fields to defaults
- maps:merge(get_default_config(),WriteOnce);
+ WriteOnce;
update ->
OldHConfig
end,
@@ -147,60 +147,57 @@ check_h_config([Other | _]) ->
check_h_config([]) ->
ok.
-get_default_config() ->
- #{}.
-
-merge_default_logopts(Name, HConfig) ->
- Type = maps:get(type, HConfig, wrap),
+merge_default_logopts(Name,HConfig) ->
+ Type = maps:get(type,HConfig,wrap),
{DefaultNoFiles,DefaultNoBytes} =
case Type of
halt -> {undefined,infinity};
_wrap -> {10,1048576}
end,
{ok,Dir} = file:get_cwd(),
- Defaults = #{file => filename:join(Dir,Name),
- max_no_files => DefaultNoFiles,
- max_no_bytes => DefaultNoBytes,
- type => Type},
- maps:merge(Defaults, HConfig).
+ Defaults = #{file=>filename:join(Dir,Name),
+ max_no_files=>DefaultNoFiles,
+ max_no_bytes=>DefaultNoBytes,
+ type=>Type},
+ maps:merge(Defaults,HConfig).
filesync(Name,_Mode,State) ->
Result = ?disk_log_sync(Name),
- maybe_notify_error(Name, filesync, Result, prev_sync_result, State).
+ maybe_notify_error(Name,filesync,Result,prev_sync_result,State).
-write(Name, Mode, Bin, State) ->
- Result = ?disk_log_write(Name, Mode, Bin),
- maybe_notify_error(Name, log, Result, prev_log_result, State).
+write(Name,Mode,Bin,State) ->
+ Result = ?disk_log_write(Name,Mode,Bin),
+ maybe_notify_error(Name,log,Result,prev_log_result,State).
-reset_state(_Name, State) ->
- State#{prev_log_result => ok,
- prev_sync_result => ok,
- prev_disk_log_info => undefined}.
+reset_state(_Name,State) ->
+ State#{prev_log_result=>ok,
+ prev_sync_result=>ok,
+ prev_disk_log_info=>undefined}.
%% The disk log owner must handle status messages from disk_log.
-handle_info(Name, {disk_log, _Node, Log, Info={truncated,_NoLostItems}}, State) ->
- maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
-handle_info(Name, {disk_log, _Node, Log, Info = {blocked_log,_Items}}, State) ->
- maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
-handle_info(Name, {disk_log, _Node, Log, Info = full}, State) ->
- maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
-handle_info(Name, {disk_log, _Node, Log, Info = {error_status,_Status}}, State) ->
- maybe_notify_status(Name, Log, Info, prev_disk_log_info, State);
-handle_info(_, _, State) ->
+handle_info(Name,{disk_log,_Node,Log,Info={truncated,_NoLostItems}},State) ->
+ maybe_notify_status(Name,Log,Info,prev_disk_log_info,State);
+handle_info(Name,{disk_log,_Node,Log,Info={blocked_log,_Items}},State) ->
+ maybe_notify_status(Name,Log,Info,prev_disk_log_info,State);
+handle_info(Name,{disk_log,_Node,Log,Info=full}, State) ->
+ maybe_notify_status(Name,Log,Info,prev_disk_log_info,State);
+handle_info(Name,{disk_log,_Node,Log,Info={error_status,_Status}},State) ->
+ maybe_notify_status(Name,Log,Info,prev_disk_log_info,State);
+handle_info(_,_,State) ->
State.
-terminate(Name, _Reason, _State) ->
- _ = close_disk_log(Name, normal),
+terminate(Name,_Reason,_State) ->
+ _ = close_disk_log(Name,normal),
ok.
%%%-----------------------------------------------------------------
%%% Internal functions
-open_disk_log(Name, File, Type, MaxNoBytes, MaxNoFiles) ->
+open_disk_log(Name,File,Type,MaxNoBytes,MaxNoFiles) ->
case filelib:ensure_dir(File) of
ok ->
Size =
- if Type == halt -> MaxNoBytes;
- Type == wrap -> {MaxNoBytes,MaxNoFiles}
+ if Type==halt -> MaxNoBytes;
+ Type==wrap -> {MaxNoBytes,MaxNoFiles}
end,
Opts = [{name, Name},
{file, File},
@@ -222,27 +219,27 @@ open_disk_log(Name, File, Type, MaxNoBytes, MaxNoFiles) ->
Error
end.
-close_disk_log(Name, _) ->
+close_disk_log(Name,_) ->
_ = ?disk_log_sync(Name),
_ = disk_log:close(Name),
ok.
-disk_log_write(Name, sync, Bin) ->
- disk_log:blog(Name, Bin);
-disk_log_write(Name, async, Bin) ->
- disk_log:balog(Name, Bin).
+disk_log_write(Name,sync,Bin) ->
+ disk_log:blog(Name,Bin);
+disk_log_write(Name,async,Bin) ->
+ disk_log:balog(Name,Bin).
%%%-----------------------------------------------------------------
%%% Print error messages, but don't repeat the same message
-maybe_notify_error(Name, Op, Result, Key, #{log_opts:=LogOpts}=State) ->
- {Result,error_notify_new({Name, Op, LogOpts, Result}, Result, Key, State)}.
+maybe_notify_error(Name,Op,Result,Key,#{log_opts:=LogOpts}=State) ->
+ {Result,error_notify_new({Name,Op,LogOpts,Result},Result,Key,State)}.
-maybe_notify_status(Name, Log, Info, Key, State) ->
- error_notify_new({disk_log, Name, Log, Info}, Info, Key, State).
+maybe_notify_status(Name,Log,Info,Key,State) ->
+ error_notify_new({disk_log,Name,Log,Info},Info,Key,State).
-error_notify_new(Term, What, Key, State) ->
- error_notify_new(What, maps:get(Key,State), Term),
- State#{Key => What}.
+error_notify_new(Term,What,Key,State) ->
+ error_notify_new(What,maps:get(Key,State),Term),
+ State#{Key=>What}.
error_notify_new(ok,_Prev,_Term) ->
ok;
diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl
index e96d2b28f3..f0db587af1 100644
--- a/lib/kernel/src/logger_h_common.erl
+++ b/lib/kernel/src/logger_h_common.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -260,17 +260,39 @@ handle_call(filesync, _From, State = #{id := Name,
{Result,HandlerState1} = Module:filesync(Name,sync,HandlerState),
{reply, Result, State#{handler_state=>HandlerState1, last_op=>sync}}.
+handle_cast({config_changed, CommonConfig, HConfig},
+ State = #{id := Name,
+ module := Module,
+ handler_state := HandlerState,
+ filesync_repeat_interval := OldFSyncInt}) ->
+ State1 =
+ case maps:get(filesync_repeat_interval,CommonConfig) of
+ OldFSyncInt ->
+ State;
+ FSyncInt ->
+ set_repeated_filesync(
+ cancel_repeated_filesync(
+ State#{filesync_repeat_interval=>FSyncInt}))
+ end,
+ HS = try Module:config_changed(Name, HConfig, HandlerState)
+ catch error:undef -> HandlerState
+ end,
+ {noreply, State1#{handler_state => HS}}.
+
%% If FILESYNC_REPEAT_INTERVAL is set to a millisec value, this
%% clause gets called repeatedly by the handler. In order to
%% guarantee that a filesync *always* happens after the last log
%% event, the repeat operation must be active!
-handle_cast(repeated_filesync,State = #{filesync_repeat_interval := no_repeat}) ->
+handle_info({timeout, TRef, repeated_filesync},
+ State = #{rep_sync_tref := TRef,
+ filesync_repeat_interval := no_repeat}) ->
%% This clause handles a race condition which may occur when
%% config changes filesync_repeat_interval from an integer value
%% to no_repeat.
{noreply,State};
-handle_cast(repeated_filesync,
+handle_info({timeout, TRef, repeated_filesync},
State = #{id := Name,
+ rep_sync_tref := TRef,
module := Module,
handler_state := HandlerState,
last_op := LastOp}) ->
@@ -282,25 +304,6 @@ handle_cast(repeated_filesync,
State#{handler_state => HS, last_op => sync}
end,
{noreply,set_repeated_filesync(State1)};
-handle_cast({config_changed, CommonConfig, HConfig},
- State = #{id := Name,
- module := Module,
- handler_state := HandlerState,
- filesync_repeat_interval := OldFSyncInt}) ->
- State1 =
- case maps:get(filesync_repeat_interval,CommonConfig) of
- OldFSyncInt ->
- State;
- FSyncInt ->
- set_repeated_filesync(
- cancel_repeated_filesync(
- State#{filesync_repeat_interval=>FSyncInt}))
- end,
- HS = try Module:config_changed(Name, HConfig, HandlerState)
- catch error:undef -> HandlerState
- end,
- {noreply, State1#{handler_state => HS}}.
-
handle_info(Info, #{id := Name, module := Module,
handler_state := HandlerState} = State) ->
{noreply,State#{handler_state => Module:handle_info(Name,Info,HandlerState)}}.
@@ -396,7 +399,7 @@ do_log_to_binary(Log,Config) ->
{config,FormatterConfig},
{log_event,Log},
{bad_return_value,String},
- {catched,{C2,R2,S2}}]),
+ {caught,{C2,R2,S2}}]),
<<"FORMATTER ERROR: bad return value\n">>
end.
@@ -445,8 +448,7 @@ get_default_config() ->
set_repeated_filesync(#{filesync_repeat_interval:=FSyncInt} = State)
when is_integer(FSyncInt) ->
- {ok,TRef} = timer:apply_after(FSyncInt, gen_server, cast,
- [self(),repeated_filesync]),
+ TRef = erlang:start_timer(FSyncInt, self(), repeated_filesync),
State#{rep_sync_tref=>TRef};
set_repeated_filesync(State) ->
State.
@@ -454,7 +456,15 @@ set_repeated_filesync(State) ->
cancel_repeated_filesync(State) ->
case maps:take(rep_sync_tref,State) of
{TRef,State1} ->
- _ = timer:cancel(TRef),
+ case erlang:cancel_timer(TRef) of
+ false ->
+ %% Flush the timer message
+ receive
+ {timeout, TRef, _} -> ok
+ end;
+ _ ->
+ ok
+ end,
State1;
error ->
State
diff --git a/lib/kernel/src/logger_internal.hrl b/lib/kernel/src/logger_internal.hrl
index 9f28157585..7047ca8ae9 100644
--- a/lib/kernel/src/logger_internal.hrl
+++ b/lib/kernel/src/logger_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -96,7 +96,7 @@
-define(IS_MSG(Msg),
((is_tuple(Msg) andalso tuple_size(Msg)==2)
andalso
- (is_list(element(1,Msg)) andalso is_list(element(2,Msg)))
+ (?IS_FORMAT(element(1,Msg)) andalso is_list(element(2,Msg)))
orelse
(element(1,Msg)==report andalso ?IS_REPORT(element(2,Msg)))
orelse
diff --git a/lib/kernel/src/logger_olp.erl b/lib/kernel/src/logger_olp.erl
index 068fbe447b..1379f8cf54 100644
--- a/lib/kernel/src/logger_olp.erl
+++ b/lib/kernel/src/logger_olp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -193,11 +193,13 @@ init([Name,Module,Args,Options]) ->
gen_server:enter_loop(?MODULE, [], State);
Error ->
unregister(Name),
- proc_lib:init_ack(Error)
+ proc_lib:init_ack(Error),
+ ignore %% Just to shut Dialyzer up - ignored
catch
_:Error ->
unregister(Name),
- proc_lib:init_ack(Error)
+ proc_lib:init_ack(Error),
+ ignore %% Just to shut Dialyzer up - ignored
end.
%% This is the synchronous load event.
diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl
index 942c0aac5a..377c261f2b 100644
--- a/lib/kernel/src/logger_server.erl
+++ b/lib/kernel/src/logger_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -623,7 +623,7 @@ do_internal_log(Level,Location,Log,[Report] = Data) ->
do_internal_log(Level,Location,Log,[Fmt,Args] = Data) ->
do_internal_log(Level,Location,Log,Data,{Fmt,Args}).
do_internal_log(Level,Location,Log,Data,Msg) ->
- Meta = logger:add_default_metadata(maps:merge(Location,maps:get(meta,Log,#{}))),
+ Meta = logger:add_default_metadata(Location),
%% Spawn these to avoid deadlocks
case Log of
#{ meta := #{ internal_log_event := true } } ->
diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl
index 13fe00b72d..1fe740d5ec 100644
--- a/lib/kernel/src/logger_std_h.erl
+++ b/lib/kernel/src/logger_std_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -484,20 +484,29 @@ ensure_file(#{inode:=INode0,file_name:=FileName,modes:=Modes}=State) ->
State#{last_check=>timestamp()};
_ ->
close_log_file(State),
- case file:open(FileName,Modes) of
- {ok,Fd} ->
- {ok,#file_info{inode=INode}} =
- file:read_file_info(FileName,[raw]),
- State#{fd=>Fd,inode=>INode,
- last_check=>timestamp(),
- synced=>true,sync_res=>ok};
- Error ->
- exit({could_not_reopen_file,Error})
- end
+ {ok, Fd} = ensure_open(FileName, Modes),
+ {ok,#file_info{inode=INode}} =
+ file:read_file_info(FileName,[raw]),
+ State#{fd=>Fd,inode=>INode,
+ last_check=>timestamp(),
+ synced=>true,sync_res=>ok}
end;
ensure_file(State) ->
State.
+ensure_open(Filename, Modes) ->
+ case filelib:ensure_dir(Filename) of
+ ok ->
+ case file:open(Filename, Modes) of
+ {ok, Fd} ->
+ {ok, Fd};
+ Error ->
+ exit({could_not_reopen_file,Error})
+ end;
+ Error ->
+ exit({could_not_create_dir_for_file,Error})
+ end.
+
write_to_dev(Bin,#{dev:=DevName}=State) ->
io:put_chars(DevName, Bin),
State;
@@ -574,21 +583,19 @@ rotate_file(#{file_name:=FileName,modes:=Modes,rotation:=Rotation}=State) ->
State1 = sync_dev(State),
_ = delayed_write_close(State),
rotate_files(FileName,maps:get(count,Rotation),maps:get(compress,Rotation)),
- case file:open(FileName,Modes) of
- {ok,Fd} ->
- {ok,#file_info{inode=INode}} = file:read_file_info(FileName,[raw]),
- State1#{fd=>Fd,inode=>INode,rotation=>Rotation#{curr_size=>0}};
- Error ->
- exit({could_not_reopen_file,Error})
- end.
+ {ok, Fd} = ensure_open(FileName,Modes),
+ {ok,#file_info{inode=INode}} = file:read_file_info(FileName,[raw]),
+ State1#{fd=>Fd,inode=>INode,rotation=>Rotation#{curr_size=>0}}.
rotate_files(FileName,0,_Compress) ->
_ = file:delete(FileName),
ok;
rotate_files(FileName,1,Compress) ->
FileName0 = FileName++".0",
- _ = file:rename(FileName,FileName0),
- if Compress -> compress_file(FileName0);
+ Rename = file:rename(FileName,FileName0),
+ %% Rename may fail if file has been deleted. If it has, then
+ %% we do not need to compress it...
+ if Rename =:= ok, Compress -> compress_file(FileName0);
true -> ok
end,
ok;
diff --git a/lib/kernel/src/net.erl b/lib/kernel/src/net.erl
index 9acd89fb5a..699524181b 100644
--- a/lib/kernel/src/net.erl
+++ b/lib/kernel/src/net.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,13 +20,6 @@
-module(net).
-%% We should really ifdef this module depending on if we actually built
-%% the system with esock support (socket and prim_net), but our doc-building
-%% can't handle the "variables" we need (USE_ESOCK). So instead, we just
-%% leave everything hanging...
-%% If one of the "hanging" functions is called when esock has been disabled,
-%% the function will through a 'notsup' error (erlang:error/1).
-
%% Administrative and utility functions
-export([
info/0,
@@ -49,7 +42,6 @@
cast/4,
broadcast/3,
ping/1,
- relay/1,
sleep/1]).
%% Should we define these here or refer to the prim_net module
@@ -59,6 +51,7 @@
name_info/0,
ifaddrs_flag/0,
+ ifaddrs_flags/0,
name_info_flags/0,
name_info_flag/0,
@@ -73,24 +66,26 @@
-deprecated({cast, 4, "use rpc:cast/4 instead"}).
-deprecated({broadcast, 3, "use rpc:eval_everywhere/3 instead"}).
-deprecated({ping, 1, "use net_adm:ping/1 instead"}).
--deprecated({relay, 1, "use slave:relay/1 instead"}).
+-removed({relay, 1, "use fun Relay(Pid) -> receive X -> Pid ! X end, Relay(Pid) instead"}).
-deprecated({sleep, 1, "use 'receive after T -> ok end' instead"}).
-type ifaddrs_flag() :: up | broadcast | debug | loopback | pointopoint |
- notrailers | running | noarp | promisc | master | slave |
+ notrailers | running | noarp | promisc |
+ master | slave |
multicast | portsel | automedia | dynamic.
+-type ifaddrs_flags() :: [ifaddrs_flag()].
%% Note that not all of these fields are mandatory.
%% Actually there are (error) cases when only the name will be included.
%% And broadaddr and dstaddr are mutually exclusive!
-type ifaddrs() :: #{name := string(),
- flags := [ifaddrs_flag()],
- addr := socket:sockaddr(),
- netmask := socket:sockaddr(),
- broadaddr := socket:sockaddr(),
- dstaddr := socket:sockaddr()}.
+ flags := ifaddrs_flags(),
+ addr => socket:sockaddr(),
+ netmask => socket:sockaddr(),
+ broadaddr => socket:sockaddr(),
+ dstaddr => socket:sockaddr()}.
-type ifaddrs_filter() :: all | default | inet | inet6 | packet |
ifaddrs_filter_map() |
@@ -119,6 +114,21 @@
-type network_interface_index() :: non_neg_integer().
+-define(GAA_NAMES_FLAGS(),
+ #{skip_unicast => true,
+ skip_friendly_name => false,
+ include_prefix => false}).
+-define(GAA_INDEXES_FLAGS(),
+ #{skip_unicast => true,
+ skip_friendly_name => true,
+ include_prefix => false}).
+
+%% This is just a "fake" based on what it looks like on linux...
+-define(BADDR_FOR_PHYS_ADDR,
+ <<16#FF:8,16#FF:8,16#FF:8,16#FF:8,16#FF:8,16#FF:8>>).
+
+
+
%% ===========================================================================
%%
%% D E P R E C A T E D F U N C T I O N S
@@ -130,7 +140,6 @@ cast(N,M,F,A) -> rpc:cast(N,M,F,A).
broadcast(M,F,A) -> rpc:eval_everywhere(M,F,A).
ping(Node) -> net_adm:ping(Node).
sleep(T) -> receive after T -> ok end.
-relay(X) -> slave:relay(X).
%% ===========================================================================
@@ -139,28 +148,13 @@ relay(X) -> slave:relay(X).
%%
%% ===========================================================================
--spec info() -> list().
-
--ifdef(USE_ESOCK).
+-spec info() -> map().
info() ->
prim_net:info().
--else.
-info() ->
- erlang:error(notsup).
--endif.
-
-spec command(Cmd :: term()) -> term().
-
--ifdef(USE_ESOCK).
command(Cmd) ->
prim_net:command(Cmd).
--else.
-command(_Cmd) ->
- erlang:error(notsup).
--endif.
-
-
%% ===========================================================================
%%
@@ -177,15 +171,8 @@ command(_Cmd) ->
-spec gethostname() -> {ok, HostName} | {error, Reason} when
HostName :: string(),
Reason :: term().
-
--ifdef(USE_ESOCK).
gethostname() ->
prim_net:gethostname().
--else.
-gethostname() ->
- erlang:error(notsup).
--endif.
-
%% ===========================================================================
%%
@@ -197,9 +184,6 @@ gethostname() ->
SockAddr :: socket:sockaddr(),
Info :: name_info(),
Reason :: term().
-
--dialyzer({no_return, getnameinfo/1}).
-
getnameinfo(SockAddr) ->
getnameinfo(SockAddr, undefined).
@@ -208,26 +192,11 @@ getnameinfo(SockAddr) ->
Flags :: name_info_flags() | undefined,
Info :: name_info(),
Reason :: term().
-
-
--ifdef(USE_ESOCK).
-
getnameinfo(SockAddr, Flags)
when is_map(SockAddr), is_list(Flags);
is_map(SockAddr), Flags =:= undefined ->
prim_net:getnameinfo(SockAddr, Flags).
--else.
-
--dialyzer({no_return, getnameinfo/2}).
-
-getnameinfo(SockAddr, Flags)
- when is_map(SockAddr), is_list(Flags);
- is_map(SockAddr), Flags =:= undefined ->
- erlang:error(notsup).
--endif.
-
-
%% ===========================================================================
%%
%% getaddrinfo - Network address and service translation
@@ -238,13 +207,9 @@ getnameinfo(SockAddr, Flags)
Host :: string(),
Info :: [address_info()],
Reason :: term().
-
--dialyzer({no_return, getaddrinfo/1}).
-
getaddrinfo(Host) when is_list(Host) ->
getaddrinfo(Host, undefined).
-
-spec getaddrinfo(Host, undefined) -> {ok, Info} | {error, Reason} when
Host :: string(),
Info :: [address_info()],
@@ -258,23 +223,11 @@ getaddrinfo(Host) when is_list(Host) ->
Service :: string(),
Info :: [address_info()],
Reason :: term().
-
--ifdef(USE_ESOCK).
getaddrinfo(Host, Service)
when (is_list(Host) orelse (Host =:= undefined)) andalso
(is_list(Service) orelse (Service =:= undefined)) andalso
(not ((Service =:= undefined) andalso (Host =:= undefined))) ->
prim_net:getaddrinfo(Host, Service).
--else.
-getaddrinfo(Host, Service)
- when (is_list(Host) orelse (Host =:= undefined)) andalso
- (is_list(Service) orelse (Service =:= undefined)) andalso
- (not ((Service =:= undefined) andalso (Host =:= undefined))) ->
- erlang:error(notsup).
--endif.
-
-
-
%% ===========================================================================
%%
@@ -284,15 +237,8 @@ getaddrinfo(Host, Service)
-spec getifaddrs() -> {ok, IfAddrs} | {error, Reason} when
IfAddrs :: [ifaddrs()],
Reason :: term().
-
--ifdef(USE_ESOCK).
getifaddrs() ->
getifaddrs(default).
--else.
-getifaddrs() ->
- erlang:error(notsup).
--endif.
-
-spec getifaddrs(Filter) -> {ok, IfAddrs} | {error, Reason} when
Filter :: ifaddrs_filter(),
@@ -302,33 +248,19 @@ getifaddrs() ->
Namespace :: file:filename_all(),
IfAddrs :: [ifaddrs()],
Reason :: term().
-
--ifdef(USE_ESOCK).
getifaddrs(Filter) when is_atom(Filter) orelse is_map(Filter) ->
do_getifaddrs(getifaddrs_filter_map(Filter),
fun() -> prim_net:getifaddrs(#{}) end);
getifaddrs(Filter) when is_function(Filter, 1) ->
do_getifaddrs(Filter, fun() -> prim_net:getifaddrs(#{}) end);
getifaddrs(Namespace) when is_list(Namespace) ->
- prim_net:getifaddrs(#{netns => Namespace}).
--else.
-getifaddrs(Filter) when is_atom(Filter) orelse
- is_map(Filter) orelse
- is_function(Filter) ->
- erlang:error(notsup);
-getifaddrs(Namespace) when is_list(Namespace) ->
- erlang:error(notsup).
--endif.
-
+ getifaddrs(default, Namespace).
-spec getifaddrs(Filter, Namespace) -> {ok, IfAddrs} | {error, Reason} when
Filter :: ifaddrs_filter(),
Namespace :: file:filename_all(),
IfAddrs :: [ifaddrs()],
Reason :: term().
-
--dialyzer({no_return, getifaddrs/2}).
-
getifaddrs(Filter, Namespace)
when (is_atom(Filter) orelse is_map(Filter)) andalso is_list(Namespace) ->
do_getifaddrs(getifaddrs_filter_map(Filter),
@@ -337,10 +269,9 @@ getifaddrs(Filter, Namespace)
when is_function(Filter, 1) andalso is_list(Namespace) ->
do_getifaddrs(Filter, fun() -> getifaddrs(Namespace) end).
--dialyzer({no_return, do_getifaddrs/2}).
do_getifaddrs(Filter, GetIfAddrs) ->
- case GetIfAddrs() of
+ try GetIfAddrs() of
{ok, IfAddrs0} when is_function(Filter) ->
{ok, lists:filtermap(Filter, IfAddrs0)};
{ok, IfAddrs0} when is_map(Filter) ->
@@ -348,6 +279,18 @@ do_getifaddrs(Filter, GetIfAddrs) ->
{ok, lists:filtermap(FilterFun, IfAddrs0)};
{error, _} = ERROR ->
ERROR
+ catch
+ C : E : S when (C =:= error) andalso (E =:= notsup) ->
+ %% This means we are on windows, and should
+ %% call the windows specific functions:
+ %% get_interface_info
+ %% get_ip_addr_table
+ %% get_adapters_addresses
+ try win_getifaddrs(Filter)
+ catch
+ _WC:_WE:_WS ->
+ erlang:raise(C, E, S)
+ end
end.
getifaddrs_filter_map(all) ->
@@ -412,7 +355,434 @@ getifaddrs_filter_flags(FilterFlags, Flags) ->
[] =:= (FilterFlags -- Flags).
+win_getifaddrs(Filter) ->
+ AdsAddrs = get_adapters_addresses(),
+ IpAddrTab = get_ip_address_table(AdsAddrs),
+ IpIfInfo = get_interface_info(),
+ win_getifaddrs(Filter, AdsAddrs, IpAddrTab, IpIfInfo).
+
+get_adapters_addresses() ->
+ case prim_net:get_adapters_addresses(#{}) of
+ {ok, AdaptersAddresses} ->
+ AdaptersAddresses;
+ {error, _} ->
+ []
+ end.
+
+get_ip_address_table([]) ->
+ case prim_net:get_ip_address_table(#{}) of
+ {ok, IpAddressTable} ->
+ IpAddressTable;
+ {error, _} ->
+ []
+ end;
+get_ip_address_table(_) ->
+ [].
+
+get_interface_info() ->
+ case prim_net:get_interface_info(#{}) of
+ {ok, InterfaceInfo} ->
+ InterfaceInfo;
+ {error, _} ->
+ []
+ end.
+
+
+win_getifaddrs(Filter, [], IpAddrTab, IpIfInfo) when (IpAddrTab =/= []) ->
+ win_getifaddrs_iat(Filter, IpAddrTab, IpIfInfo);
+win_getifaddrs(Filter, AdsAddrs, _IpAddrTab, IpIfInfo) when (AdsAddrs =/= []) ->
+ win_getifaddrs_aa(Filter, AdsAddrs, IpIfInfo);
+win_getifaddrs(_Filter, AdsAddrs, IpAddrTab, IpIfInfo) ->
+ throw({error, {insufficient_info, AdsAddrs, IpAddrTab, IpIfInfo}}).
+
+win_getifaddrs_iat(Filter, IpAddrTab, IpIfInfos) when is_function(Filter) ->
+ IfAddrs = win_getifaddrs_iat2(IpAddrTab, IpIfInfos),
+ {ok, lists:filtermap(Filter, IfAddrs)};
+win_getifaddrs_iat(Filter, IpAddrTab, IpIfInfos) when is_map(Filter) ->
+ IfAddrs = win_getifaddrs_iat2(IpAddrTab, IpIfInfos),
+ FilterFun = fun(Elem) -> getifaddrs_filter(Filter, Elem) end,
+ {ok, lists:filtermap(FilterFun, IfAddrs)}.
+
+win_getifaddrs_iat2(IpAddrTab, IpIfInfos) ->
+ win_getifaddrs_iat2(IpAddrTab, IpIfInfos, []).
+
+win_getifaddrs_iat2([], _IpIfInfos, Acc) ->
+ lists:reverse(Acc);
+win_getifaddrs_iat2([#{index := Idx} = IpAddr|IpAddrTab], IpIfInfos, Acc) ->
+ case prim_net:get_if_entry(#{index => Idx}) of
+ {ok, #{name := Name} = IfEntry} when (Name =/= "") ->
+ %% Note that here its (IfAddr) *not* a list!
+ {IfAddr, PktIfAddr} = win_getifaddrs_iat3(Name, IpAddr, IfEntry),
+ win_getifaddrs_iat2(IpAddrTab, IpIfInfos, [IfAddr, PktIfAddr|Acc]);
+ {ok, #{name := Name,
+ description := Desc} = IfEntry} when (Name =:= "") ->
+ case if_info_search(Idx, IpIfInfos) of
+ {value, #{name := Name2}} ->
+ %% Note that here its (IfAddr) *not* a list!
+ {IfAddr, PktIfAddr} =
+ win_getifaddrs_iat3(Name2, IpAddr, IfEntry),
+ win_getifaddrs_iat2(IpAddrTab, IpIfInfos,
+ [IfAddr, PktIfAddr|Acc]);
+ false ->
+ %% Use description
+ %% Note that here its (IfAddr) *not* a list!
+ {IfAddr, PktIfAddr} =
+ win_getifaddrs_iat3(Desc, IpAddr, IfEntry),
+ win_getifaddrs_iat2(IpAddrTab, IpIfInfos,
+ [IfAddr, PktIfAddr|Acc])
+ end;
+ {error, _} ->
+ win_getifaddrs_iat2(IpAddrTab, IpIfInfos, Acc)
+ end.
+
+win_getifaddrs_iat3(Name,
+ #{addr := Addr,
+ mask := Mask,
+ %% Why do we skip this and "make" our own?
+ bcast_addr := _BCastAddr} = _IpAddr,
+ #{type := Type,
+ admin_status := AStatus,
+ internal_oper_status := _OStatus,
+ phys_addr := PhysAddr,
+ index := Idx} = _IfEntry) ->
+ Flags1 = case Type of
+ ethernet_csmacd ->
+ [broadcast,multicast];
+ software_loopback ->
+ [loopback];
+ _ ->
+ []
+ end,
+ Flags2 = case AStatus of
+ non_operational ->
+ [];
+ connecting ->
+ [up, pointtopoint];
+ connected ->
+ [up, runnning, pointtopoint];
+ operational ->
+ [up, running];
+ _ ->
+ [up]
+ end,
+ Flags = lists:sort(Flags1 ++ Flags2),
+ HaType = type2hatype(Type),
+ PktSockAddr = #{addr => process_phys_addr(HaType, PhysAddr),
+ family => packet,
+ hatype => HaType,
+ ifindex => Idx,
+ pkttype => host,
+ protocol => 0},
+ PktIfAddr =
+ case HaType of
+ loopback ->
+ #{name => Name,
+ addr => PktSockAddr,
+ flags => Flags};
+ _ ->
+ #{name => Name,
+ addr => PktSockAddr,
+ broadaddr => ?BADDR_FOR_PHYS_ADDR,
+ flags => Flags}
+ end,
+ IfAddr = #{name => Name,
+ flags => Flags,
+ addr => mk_sockaddr_in(Addr),
+ netmask => mk_sockaddr_in(Mask),
+ %% And fake the broadcast address...
+ broadaddr => mk_sockaddr_in(iat_broadaddr(Addr, Mask))},
+ {IfAddr, PktIfAddr}.
+
+mk_sockaddr_in(Addr) ->
+ #{addr => Addr, family => inet, port => 0}.
+
+win_getifaddrs_aa(Filter, AdsAddrs, IpIfInfo) when is_function(Filter) ->
+ IfAddrs = win_getifaddrs_aa2(AdsAddrs, IpIfInfo),
+ {ok, lists:filtermap(Filter, IfAddrs)};
+win_getifaddrs_aa(Filter, AdsAddrs, IpIfInfo) when is_map(Filter) ->
+ IfAddrs = win_getifaddrs_aa2(AdsAddrs, IpIfInfo),
+ FilterFun = fun(Elem) -> getifaddrs_filter(Filter, Elem) end,
+ {ok, lists:filtermap(FilterFun, IfAddrs)}.
+
+win_getifaddrs_aa2(AdsAddrs, IpIfInfo) ->
+ win_getifaddrs_aa2(AdsAddrs, IpIfInfo, []).
+
+win_getifaddrs_aa2([], _IpIfInfo, Acc) ->
+ lists:reverse(lists:flatten(Acc));
+win_getifaddrs_aa2([#{index := Idx} = AdAddrs|AdsAddrs], IpIfInfos, Acc) ->
+ case prim_net:get_if_entry(#{index => Idx}) of
+ {ok, #{name := Name} = IfEntry} when (Name =/= "") ->
+ {IfAddrs, PktIfAddr} = win_getifaddrs_aa3(Name, AdAddrs, IfEntry),
+ win_getifaddrs_aa2(AdsAddrs, IpIfInfos, [IfAddrs,PktIfAddr|Acc]);
+ {ok, #{name := Name,
+ description := Desc} = IfEntry} when (Name =:= "") ->
+ case if_info_search(Idx, IpIfInfos) of
+ {value, #{name := Name2}} ->
+ {IfAddrs, PktIfAddr} =
+ win_getifaddrs_aa3(Name2, AdAddrs, IfEntry),
+ win_getifaddrs_aa2(AdsAddrs, IpIfInfos,
+ [IfAddrs, PktIfAddr|Acc]);
+ false ->
+ %% Use description
+ {IfAddrs, PktIfAddr} =
+ win_getifaddrs_aa3(Desc, AdAddrs, IfEntry),
+ win_getifaddrs_aa2(AdsAddrs, IpIfInfos,
+ [IfAddrs, PktIfAddr|Acc])
+ end;
+ {error, _} ->
+ win_getifaddrs_aa2(AdsAddrs, IpIfInfos, Acc)
+ end.
+
+win_getifaddrs_aa3(Name,
+ #{flags := #{no_multicast := NoMC},
+ unicast_addrs := UCastAddrs,
+ prefixes := Prefixes} = _AdAddrs,
+ #{type := Type,
+ admin_status := AStatus,
+ internal_oper_status := _OStatus,
+ phys_addr := PhysAddr,
+ index := Idx} = _IfEntry) ->
+ Flags1 =
+ if (NoMC =:= false) ->
+ [multicast];
+ true ->
+ []
+ end,
+ Flags2 = case Type of
+ ethernet_csmacd ->
+ [broadcast];
+ software_loopback ->
+ [loopback];
+ _ ->
+ []
+ end,
+ Flags3 = case AStatus of
+ non_operational ->
+ [];
+ connecting ->
+ [up, pointtopoint];
+ connected ->
+ [up, runnning, pointtopoint];
+ operational ->
+ [up, running];
+ _ ->
+ [up]
+ end,
+ Flags = lists:sort(Flags1 ++ Flags2 ++ Flags3),
+ HaType = type2hatype(Type),
+ PktSockAddr = #{addr => process_phys_addr(HaType, PhysAddr),
+ family => packet,
+ hatype => HaType,
+ ifindex => Idx,
+ pkttype => host,
+ protocol => 0},
+ PktIfAddr =
+ case HaType of
+ loopback ->
+ #{name => Name,
+ addr => PktSockAddr,
+ flags => Flags};
+ _ ->
+ #{name => Name,
+ addr => PktSockAddr,
+ broadaddr => ?BADDR_FOR_PHYS_ADDR,
+ flags => Flags}
+ end,
+ IfAddrs = [win_getifaddrs_aa4(Name,
+ Flags,
+ Prefixes,
+ UCastAddr) || UCastAddr <- UCastAddrs],
+ {IfAddrs, PktIfAddr}.
+
+type2hatype(ethernet_csmacd) ->
+ ether;
+type2hatype(software_loopback) ->
+ loopback;
+type2hatype(Other) ->
+ Other.
+
+process_phys_addr(loopback, <<>>) ->
+ <<0:8,0:8,0:8,0:8,0:8,0:8>>;
+process_phys_addr(_, Bin) when is_binary(Bin) ->
+ Bin.
+
+
+
+win_getifaddrs_aa4(Name, Flags, Prefixes,
+ #{addr := #{family := Fam} = Addr} = UCAddr) ->
+ SPrefix = shortest_matching_prefix(UCAddr, Prefixes),
+ Mask = win_getifaddrs_mask(SPrefix),
+ case lists:member(broadcast, Flags) of
+ true when (Fam =:= inet) ->
+ BroadAddr = win_getifaddrs_broadaddr(Mask, SPrefix),
+ #{name => Name,
+ flags => Flags,
+ addr => Addr,
+ netmask => Mask,
+ broadaddr => BroadAddr};
+ _ ->
+ #{name => Name,
+ flags => Flags,
+ addr => Addr,
+ netmask => Mask}
+ end.
+
+shortest_matching_prefix(#{addr := Addr} = UCAddr, Prefixes) ->
+ SPrefix = #{addr => Addr, length => undefined},
+ shortest_matching_prefix(UCAddr, Prefixes, SPrefix).
+
+shortest_matching_prefix(#{addr := #{family := inet,
+ addr := {A, _, _, _}} = Addr}, [],
+ #{length := undefined}) ->
+ %% Fall back to old classfull network addresses
+ Shortest =
+ if
+ (A < 128) ->
+ %% Class A: 1-127
+ 8;
+ (A < 192) ->
+ %% Class B: 128-191
+ 16;
+ (A < 224) ->
+ %% Class C: 192-223
+ 24;
+ true ->
+ %% Class D: 224-239
+ 32
+ end,
+ #{addr => Addr, length => Shortest};
+shortest_matching_prefix(#{addr := #{family := inet6} = Addr}, [],
+ #{length := undefined}) ->
+ %% Just play it safe
+ #{addr => Addr, length => 128};
+shortest_matching_prefix(_UCAddr, [], SPrefix) ->
+ SPrefix;
+shortest_matching_prefix(
+ #{addr := #{family := Fam, addr := Addr}} = UCAddr,
+ [#{addr := #{family := Fam, addr := PAddr},
+ length := PLen} = Prefix|Prefixes],
+ #{length := SPLen} = SPrefix)
+ when (Fam =:= inet) ->
+ Mask = <<(16#FFFFFFFF bsl (32 - PLen)):32>>,
+ case masked_eq(Mask, ipv4_to_bin(Addr), ipv4_to_bin(PAddr)) of
+ true ->
+ if
+ (SPLen =:= undefined) ->
+ shortest_matching_prefix(UCAddr, Prefixes, Prefix);
+ (PLen < SPLen) ->
+ shortest_matching_prefix(UCAddr, Prefixes, Prefix);
+ true ->
+ shortest_matching_prefix(UCAddr, Prefixes, SPrefix)
+ end;
+ false ->
+ shortest_matching_prefix(UCAddr, Prefixes, SPrefix)
+ end;
+shortest_matching_prefix(
+ #{addr := #{family := Fam, addr := Addr}} = UCAddr,
+ [#{addr := #{family := Fam, addr := PAddr},
+ length := PLen} = Prefix|Prefixes],
+ #{length := SPLen} = SPrefix) when (Fam =:= inet6) ->
+ Mask = <<(16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF bsl (128 - PLen)):128>>,
+ case masked_eq(Mask, ipv6_to_bin(Addr), ipv6_to_bin(PAddr)) of
+ true ->
+ if
+ (SPLen =:= undefined) ->
+ shortest_matching_prefix(UCAddr, Prefixes, Prefix);
+ (PLen < SPLen) ->
+ shortest_matching_prefix(UCAddr, Prefixes, Prefix);
+ true ->
+ shortest_matching_prefix(UCAddr, Prefixes, SPrefix)
+ end;
+ false ->
+ shortest_matching_prefix(UCAddr, Prefixes, SPrefix)
+ end;
+shortest_matching_prefix(UCAddr, [_Prefix|Prefixes], SPrefix) ->
+ shortest_matching_prefix(UCAddr, Prefixes, SPrefix).
+
+masked_eq(<<M:32>>,
+ <<A:32>>,
+ <<PA:32>>) ->
+ (A band M) =:= (PA band M);
+masked_eq(<<M01:8, M02:8, M03:8, M04:8,
+ M05:8, M06:8, M07:8, M08:8,
+ M09:8, M10:8, M11:8, M12:8,
+ M13:8, M14:8, M15:8, M16:8>>,
+ <<A01:8, A02:8, A03:8, A04:8,
+ A05:8, A06:8, A07:8, A08:8,
+ A09:8, A10:8, A11:8, A12:8,
+ A13:8, A14:8, A15:8, A16:8>>,
+ <<PA01:8, PA02:8, PA03:8, PA04:8,
+ PA05:8, PA06:8, PA07:8, PA08:8,
+ PA09:8, PA10:8, PA11:8, PA12:8,
+ PA13:8, PA14:8, PA15:8, PA16:8>>) ->
+ ((A01 band M01) =:= (PA01 band M01)) andalso
+ ((A02 band M02) =:= (PA02 band M02)) andalso
+ ((A03 band M03) =:= (PA03 band M03)) andalso
+ ((A04 band M04) =:= (PA04 band M04)) andalso
+ ((A05 band M05) =:= (PA05 band M05)) andalso
+ ((A06 band M06) =:= (PA06 band M06)) andalso
+ ((A07 band M07) =:= (PA07 band M07)) andalso
+ ((A08 band M08) =:= (PA08 band M08)) andalso
+ ((A09 band M09) =:= (PA09 band M09)) andalso
+ ((A10 band M10) =:= (PA10 band M10)) andalso
+ ((A11 band M11) =:= (PA11 band M11)) andalso
+ ((A12 band M12) =:= (PA12 band M12)) andalso
+ ((A13 band M13) =:= (PA13 band M13)) andalso
+ ((A14 band M14) =:= (PA14 band M14)) andalso
+ ((A15 band M15) =:= (PA15 band M15)) andalso
+ ((A16 band M16) =:= (PA16 band M16)).
+
+ipv4_to_bin({A1, A2, A3, A4}) ->
+ <<A1:8, A2:8, A3:8, A4:8>>.
+
+ipv6_to_bin({A1, A2, A3, A4, A5, A6, A7, A8}) ->
+ <<A1:16, A2:16, A3:16, A4:16, A5:16, A6:16, A7:16, A8:16>>.
+
+if_info_search(_Idx, []) ->
+ false;
+if_info_search(Idx, [#{index := Idx} = IfInfo|_IfInfos]) ->
+ {value, IfInfo};
+if_info_search(Idx, [_|IfInfos]) ->
+ if_info_search(Idx, IfInfos).
+
+
+win_getifaddrs_mask(#{addr := #{addr := _Addr, family := inet = Fam},
+ length := Len}) ->
+ <<M1:8, M2:8, M3:8, M4:8>> = <<(16#FFFFFFFF bsl (32 - Len)):32>>,
+ #{addr => {M1, M2, M3, M4},
+ family => Fam,
+ port => 0};
+win_getifaddrs_mask(#{addr := #{addr := _Addr, family := inet6 = Fam},
+ length := Len}) ->
+ <<M1:16, M2:16, M3:16, M4:16, M5:16, M6:16, M7:16, M8:16>> =
+ <<(16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF bsl (128 - Len)):128>>,
+ #{addr => {M1, M2, M3, M4, M5, M6, M7, M8},
+ family => Fam,
+ flowinfo => 0,
+ port => 0,
+ scope_id => 0}.
+
+win_getifaddrs_broadaddr(
+ #{addr := {M1, M2, M3, M4}, family := Fam} = _Mask,
+ #{addr := #{addr := {PA1, PA2, PA3, PA4}}} = _Prefix) ->
+ BA1 = 16#FF band (PA1 bor (bnot M1)),
+ BA2 = 16#FF band (PA2 bor (bnot M2)),
+ BA3 = 16#FF band (PA3 bor (bnot M3)),
+ BA4 = 16#FF band (PA4 bor (bnot M4)),
+ #{family => Fam,
+ addr => {BA1, BA2, BA3, BA4},
+ port => 0}.
+
+iat_broadaddr({A1, A2, A3, A4}, {M1, M2, M3, M4}) ->
+ BA1 = 16#FF band (A1 bor (bnot M1)),
+ BA2 = 16#FF band (A2 bor (bnot M2)),
+ BA3 = 16#FF band (A3 bor (bnot M3)),
+ BA4 = 16#FF band (A4 bor (bnot M4)),
+ #{family => inet,
+ addr => {BA1, BA2, BA3, BA4},
+ port => 0}.
+
%% ===========================================================================
%%
%% if_name2index - Mappings between network interface names and indexes:
@@ -424,16 +794,20 @@ getifaddrs_filter_flags(FilterFlags, Flags) ->
Name :: network_interface_name(),
Idx :: network_interface_index(),
Reason :: term().
-
--ifdef(USE_ESOCK).
-if_name2index(If) when is_list(If) ->
- prim_net:if_name2index(If).
--else.
-if_name2index(If) when is_list(If) ->
- erlang:error(notsup).
--endif.
-
-
+if_name2index(Name) when is_list(Name) ->
+ try prim_net:if_name2index(Name) of
+ Result ->
+ Result
+ catch
+ C : E : S when (C =:= error) andalso (E =:= notsup) ->
+ %% This is *most likely* Windows, so try that.
+ %% If not (another catch), raise the original catched error.
+ try win_name2index(Name)
+ catch
+ _:_:_ ->
+ erlang:raise(C, E, S)
+ end
+ end.
%% ===========================================================================
%%
@@ -446,16 +820,20 @@ if_name2index(If) when is_list(If) ->
Idx :: network_interface_index(),
Name :: network_interface_name(),
Reason :: term().
-
--ifdef(USE_ESOCK).
-if_index2name(Idx) when is_integer(Idx) ->
- prim_net:if_index2name(Idx).
--else.
if_index2name(Idx) when is_integer(Idx) ->
- erlang:error(notsup).
--endif.
-
-
+ try prim_net:if_index2name(Idx) of
+ Result ->
+ Result
+ catch
+ C : E : S when (C =:= error) andalso (E =:= notsup) ->
+ %% This is *most likely* Windows, so try that.
+ %% If not (another catch), raise the original catched error.
+ try win_index2name(Idx)
+ catch
+ _:_:_ ->
+ erlang:raise(C, E, S)
+ end
+ end.
%% ===========================================================================
%%
@@ -463,18 +841,82 @@ if_index2name(Idx) when is_integer(Idx) ->
%%
%%
--spec if_names() -> Names | {error, Reason} when
+-spec if_names() -> {ok, Names} | {error, Reason} when
Names :: [{Idx, If}],
Idx :: network_interface_index(),
If :: network_interface_name(),
Reason :: term().
-
--ifdef(USE_ESOCK).
-if_names() ->
- prim_net:if_names().
--else.
if_names() ->
- erlang:error(notsup).
--endif.
+ try prim_net:if_names() of
+ Result ->
+ Result
+ catch
+ C : E : S when (C =:= error) andalso (E =:= notsup) ->
+ %% This is *most likely* Windows, so try that.
+ %% If not (another catch), raise the original catched error.
+ try {ok, win_names()}
+ catch
+ _:_:_ ->
+ erlang:raise(C, E, S)
+ end
+ end.
+
+%% ===========================================================================
+%%
+%% -- Windows specific functions:
+%%
+
+win_names() ->
+ [{Idx, win_name(Idx)} || Idx <- win_indexes()].
+
+win_indexes() ->
+ case prim_net:get_adapters_addresses(#{flags => ?GAA_INDEXES_FLAGS()}) of
+ {ok, AA} ->
+ Indexes = [Idx || #{index := Idx} <- AA],
+ lists:sort(Indexes);
+ {error, _} ->
+ case prim_net:get_ip_address_table(#{}) of
+ {ok, Tab} ->
+ Indexes = [Idx || #{index := Idx} <- Tab],
+ lists:sort(Indexes);
+ {error, _} ->
+ throw({error, no_index})
+ end
+ end.
+
+win_name(Idx) ->
+ case prim_net:get_if_entry(#{index => Idx}) of
+ {ok, #{name := Name}} ->
+ Name;
+ {error, _} ->
+ throw({error, no_entry})
+ end.
+
+
+win_index2name(Idx) ->
+ case lists:keysearch(Idx, 1, win_names()) of
+ {value, {Idx, Name}} ->
+ {ok, Name};
+ false ->
+ {error, enxio} % This is to be "compatible" with unix
+ end.
+
+win_name2index(Name) ->
+ case lists:keysearch(Name, 2, win_names()) of
+ {value, {Idx, Name}} ->
+ {ok, Idx};
+ false ->
+ {error, enodev} % This is to be "compatible" with unix
+ end.
+
+%% ===========================================================================
+%%
+%% Misc utility functions
+%%
+%% ===========================================================================
+%% d(F) ->
+%% d(F, []).
+%% d(F, A) ->
+%% io:format("~w:" ++ F ++ "~n", [?MODULE|A]).
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 40abf24f57..2123e3e1bf 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -71,9 +71,9 @@
nodename/0,
protocol_childspecs/0,
epmd_module/0,
- dist_listen/0]).
+ get_state/0]).
--export([disconnect/1, passive_cnct/1]).
+-export([disconnect/1, async_disconnect/1, passive_cnct/1]).
-export([hidden_connect_node/1]).
-export([set_net_ticktime/1, set_net_ticktime/2, get_net_ticktime/0]).
@@ -81,7 +81,7 @@
connecttime/0,
i/0, i/1, verbose/1]).
--export([publish_on_node/1, update_publish_nodes/1]).
+-export([publish_on_node/1]).
%% Internal exports for spawning processes.
@@ -112,9 +112,9 @@
listen, %% list of #listen
allowed, %% list of allowed nodes in a restricted system
verbose = 0, %% level of verboseness
- publish_on_nodes = undefined,
dyn_name_pool = #{}, %% Reusable remote node names: #{Host => [{Name,Creation}]}
- supervisor %% Our supervisor (net_sup | net_sup_dynamic | {restart,Restarter})
+ supervisor, %% Our supervisor (net_sup | net_sup_dynamic | {restart,Restarter})
+ req_map = #{} %% Map for outstanding async requests
}).
-record(listen, {
@@ -195,6 +195,23 @@ longnames() -> request(longnames).
nodename() -> request(nodename).
+-spec get_state() -> #{started => no | static | dynamic,
+ name => atom(),
+ name_type => static | dynamic,
+ name_domain => shortnames | longnames}.
+get_state() ->
+ case whereis(net_kernel) of
+ undefined ->
+ case retry_request_maybe(get_state) of
+ ignored ->
+ #{started => no};
+ Reply ->
+ Reply
+ end;
+ _ ->
+ request(get_state)
+ end.
+
-spec stop() -> ok | {error, Reason} when
Reason :: not_allowed | not_found.
stop() ->
@@ -272,15 +289,41 @@ monitor_nodes(Flag) ->
-spec monitor_nodes(Flag, Options) -> ok | Error when
Flag :: boolean(),
- Options :: [Option],
- Option :: {node_type, NodeType}
- | nodedown_reason,
+ Options :: OptionsList | OptionsMap,
+ OptionsList :: [ListOption],
+ ListOption :: connection_id
+ | {node_type, NodeType}
+ | nodedown_reason,
+ OptionsMap :: #{connection_id => boolean(),
+ node_type => NodeType,
+ nodedown_reason => boolean()},
NodeType :: visible | hidden | all,
Error :: error | {error, term()}.
monitor_nodes(Flag, Opts) ->
- case catch process_flag({monitor_nodes, Opts}, Flag) of
- N when is_integer(N) -> ok;
- _ -> mk_monitor_nodes_error(Flag, Opts)
+ try
+ MapOpts = if is_map(Opts) ->
+ error = maps:find(list, Opts),
+ Opts;
+ is_list(Opts) ->
+ lists:foldl(fun (nodedown_reason, Acc) ->
+ Acc#{nodedown_reason => true};
+ (connection_id, Acc) ->
+ Acc#{connection_id => true};
+ ({node_type, Val}, Acc) ->
+ case maps:find(node_type, Acc) of
+ error -> ok;
+ {ok, Val} -> ok
+ end,
+ Acc#{node_type => Val}
+ end,
+ #{list => true},
+ Opts)
+ end,
+ true = is_integer(process_flag({monitor_nodes, MapOpts}, Flag)),
+ ok
+ catch
+ _:_ ->
+ mk_monitor_nodes_error(Flag, Opts)
end.
%% ...
@@ -300,13 +343,14 @@ passive_cnct(Node) ->
disconnect(Node) -> request({disconnect, Node}).
+async_disconnect(Node) ->
+ gen_server:cast(net_kernel, {async_disconnect, Node}).
+
%% Should this node publish itself on Node?
publish_on_node(Node) when is_atom(Node) ->
- request({publish_on_node, Node}).
-
-%% Update publication list
-update_publish_nodes(Ns) ->
- request({update_publish_nodes, Ns}).
+ global_group:publish(persistent_term:get({?MODULE, publish_type},
+ hidden),
+ Node).
-spec connect_node(Node) -> boolean() | ignored when
Node :: node().
@@ -351,15 +395,15 @@ request(Req) ->
end.
retry_request_maybe(Req) ->
- case persistent_term:get(net_kernel, undefined) of
- dynamic_node_name ->
+ case erts_internal:dynamic_node_name() of
+ true ->
%% net_kernel must be restarting due to lost connection
%% toward the node that named us.
%% We want reconnection attempts to succeed so we wait and retry.
receive after 100 -> ok end,
request(Req);
- _ ->
+ false ->
ignored
end.
@@ -370,7 +414,9 @@ retry_request_maybe(Req) ->
-spec start(Name, Options) -> {ok, pid()} | {error, Reason} when
Options :: #{name_domain => NameDomain,
net_ticktime => NetTickTime,
- net_tickintensity => NetTickIntensity},
+ net_tickintensity => NetTickIntensity,
+ dist_listen => boolean(),
+ hidden => boolean()},
Name :: atom(),
NameDomain :: shortnames | longnames,
NetTickTime :: pos_integer(),
@@ -389,6 +435,10 @@ start(Name, Options) when is_atom(Name), is_map(Options) ->
4 =< Val,
Val =< 1000 ->
ok;
+ (dist_listen, Val) when is_boolean(Val) ->
+ ok;
+ (hidden, Val) when is_boolean(Val) ->
+ ok;
(Opt, Val) ->
error({invalid_option, Opt, Val})
end, Options)
@@ -475,7 +525,7 @@ make_init_opts(Opts) ->
NTT = if NTT1 rem NTI =:= 0 -> NTT1;
true -> ((NTT1 div NTI) + 1) * NTI
end,
-
+
ND = case maps:find(name_domain, Opts) of
{ok, ND0} ->
ND0;
@@ -483,16 +533,56 @@ make_init_opts(Opts) ->
longnames
end,
- Opts#{net_ticktime => NTT, net_tickintensity => NTI, name_domain => ND}.
+ DL = case split_node(maps:get(name, Opts)) of
+ {"undefined", _} ->
+ %% dynamic node name implies dist_listen=false
+ false;
+ _ ->
+ case maps:find(dist_listen, Opts) of
+ error ->
+ dist_listen_argument();
+ {ok, false} ->
+ false;
+ _ ->
+ true
+ end
+ end,
+
+ H = case DL of
+ false ->
+ %% dist_listen=false implies hidden=true
+ true;
+ true ->
+ case maps:find(hidden, Opts) of
+ error ->
+ hidden_argument();
+ {ok, true} ->
+ true;
+ _ ->
+ false
+ end
+ end,
+
+ Opts#{net_ticktime => NTT,
+ net_tickintensity => NTI,
+ name_domain => ND,
+ dist_listen => DL,
+ hidden => H}.
init(#{name := Name,
name_domain := NameDomain,
net_ticktime := NetTicktime,
net_tickintensity := NetTickIntensity,
clean_halt := CleanHalt,
- supervisor := Supervisor}) ->
+ supervisor := Supervisor,
+ dist_listen := DistListen,
+ hidden := Hidden}) ->
process_flag(trap_exit,true),
- case init_node(Name, NameDomain, CleanHalt) of
+ persistent_term:put({?MODULE, publish_type},
+ if Hidden -> hidden;
+ true -> normal
+ end),
+ case init_node(Name, NameDomain, CleanHalt, DistListen) of
{ok, Node, Listeners} ->
process_flag(priority, max),
TickInterval = NetTicktime div NetTickIntensity,
@@ -513,6 +603,8 @@ init(#{name := Name,
supervisor = Supervisor
}};
Error ->
+ _ = persistent_term:erase({?MODULE, publish_type}),
+ erts_internal:dynamic_node_name(false),
{stop, Error}
end.
@@ -561,7 +653,7 @@ do_auto_connect_2(Node, ConnId, From, State, ConnLookup) ->
{reply, false, State};
%% This might happen due to connection close
- %% not beeing propagated to user space yet.
+ %% not being propagated to user space yet.
%% Save the day by just not connecting...
{ok, once} when ConnLookup =/= [],
(hd(ConnLookup))#connection.state =:= up ->
@@ -655,7 +747,7 @@ handle_call({disconnect, Node}, From, State) when Node =:= node() ->
async_reply({reply, false, State}, From);
handle_call({disconnect, Node}, From, State) ->
verbose({disconnect, Node}, 1, State),
- {Reply, State1} = do_disconnect(Node, State),
+ {Reply, State1} = do_disconnect(Node, State, false),
async_reply({reply, Reply, State1}, From);
%%
@@ -715,25 +807,6 @@ handle_call(longnames, From, State) ->
handle_call(nodename, From, State) ->
async_reply({reply, State#state.node, State}, From);
-handle_call({update_publish_nodes, Ns}, From, State) ->
- async_reply({reply, ok, State#state{publish_on_nodes = Ns}}, From);
-
-handle_call({publish_on_node, Node}, From, State) ->
- NewState = case State#state.publish_on_nodes of
- undefined ->
- State#state{publish_on_nodes =
- global_group:publish_on_nodes()};
- _ ->
- State
- end,
- Publish = case NewState#state.publish_on_nodes of
- all ->
- true;
- Nodes ->
- lists:member(Node, Nodes)
- end,
- async_reply({reply, Publish, NewState}, From);
-
handle_call({verbose, Level}, From, State) ->
async_reply({reply, State#state.verbose, State#state{verbose = Level}},
From);
@@ -802,35 +875,36 @@ handle_call({new_ticktime,_T,_TP},
async_reply({reply, {ongoing_change_to, T}, State}, From);
handle_call({setopts, new, Opts}, From, State) ->
- Ret = setopts_new(Opts, State),
- async_reply({reply, Ret, State}, From);
+ setopts_new(Opts, From, State);
handle_call({setopts, Node, Opts}, From, State) ->
- Return =
- case ets:lookup(sys_dist, Node) of
- [Conn] when Conn#connection.state =:= up ->
- case call_owner(Conn#connection.owner, {setopts, Opts}) of
- {ok, Ret} -> Ret;
- _ -> {error, noconnection}
- end;
-
- _ ->
- {error, noconnection}
- end,
- async_reply({reply, Return, State}, From);
+ opts_node(setopts, Node, Opts, From, State);
handle_call({getopts, Node, Opts}, From, State) ->
- Return =
- case ets:lookup(sys_dist, Node) of
- [Conn] when Conn#connection.state =:= up ->
- case call_owner(Conn#connection.owner, {getopts, Opts}) of
- {ok, Ret} -> Ret;
- _ -> {error, noconnection}
- end;
-
- _ ->
- {error, noconnection}
- end,
+ opts_node(getopts, Node, Opts, From, State);
+
+
+handle_call(get_state, From, State) ->
+ Started = case State#state.supervisor of
+ net_sup -> static;
+ _ -> dynamic
+ end,
+ {NameType,Name} = case {erts_internal:dynamic_node_name(), node()} of
+ {false, Node} ->
+ {static, Node};
+ {true, nonode@nohost} ->
+ {dynamic, undefined};
+ {true, Node} ->
+ {dynamic, Node}
+ end,
+ NameDomain = case get(longnames) of
+ true -> longnames;
+ false -> shortnames
+ end,
+ Return = #{started => Started,
+ name_type => NameType,
+ name => Name,
+ name_domain => NameDomain},
async_reply({reply, Return, State}, From);
handle_call(_Msg, _From, State) ->
@@ -840,6 +914,13 @@ handle_call(_Msg, _From, State) ->
%% handle_cast.
%% ------------------------------------------------------------
+handle_cast({async_disconnect, Node}, State) when Node =:= node() ->
+ {noreply, State};
+handle_cast({async_disconnect, Node}, State) ->
+ verbose({async_disconnect, Node}, 1, State),
+ {_Reply, State1} = do_disconnect(Node, State, true),
+ {noreply, State1};
+
handle_cast(_, State) ->
{noreply,State}.
@@ -859,10 +940,8 @@ terminate(Reason, State) ->
#state{supervisor = {restart, _}} ->
ok;
_ ->
- case persistent_term:get(net_kernel, undefined) of
- undefined -> ok;
- _ -> persistent_term:erase(net_kernel)
- end
+ _ = persistent_term:erase({?MODULE, publish_type}),
+ erts_internal:dynamic_node_name(false)
end,
case Reason of
@@ -1065,6 +1144,16 @@ handle_info({AcceptPid, {wait_pending, Node}}, State) ->
{noreply, State};
%%
+%% Responses to asynchronous requests we've made...
+%%
+handle_info({ReqId, Reply},
+ #state{req_map = ReqMap} = S) when is_map_key(ReqId, ReqMap) ->
+ handle_async_response(reply, ReqId, Reply, S);
+handle_info({'DOWN', ReqId, process, _Pid, Reason},
+ #state{req_map = ReqMap} = S) when is_map_key(ReqId, ReqMap) ->
+ handle_async_response(down, ReqId, Reason, S);
+
+%%
%% Handle different types of process terminations.
%%
handle_info({'EXIT', From, Reason}, State) ->
@@ -1083,7 +1172,7 @@ handle_info({From,registered_send,To,Mess},State) ->
handle_info({From,badcookie,_To,_Mess}, State) ->
error_logger:error_msg("~n** Got OLD cookie from ~w~n",
[getnode(From)]),
- {_Reply, State1} = do_disconnect(getnode(From), State),
+ {_Reply, State1} = do_disconnect(getnode(From), State, false),
{noreply,State1};
%%
@@ -1495,8 +1584,45 @@ check_options(Opts) when is_list(Opts) ->
_ ->
{error, {unknown_options, RestOpts2}}
end;
+check_options(Opts) when is_map(Opts) ->
+ BadMap0 = case maps:find(connection_id, Opts) of
+ error ->
+ Opts;
+ {ok, CIdBool} when is_boolean(CIdBool) ->
+ maps:remove(connection_id, Opts);
+ {ok, BadCIdVal} ->
+ throw({error,
+ {bad_option_value,
+ #{connection_id => BadCIdVal}}})
+ end,
+ BadMap1 = case maps:find(nodedown_reason, BadMap0) of
+ error ->
+ BadMap0;
+ {ok, NRBool} when is_boolean(NRBool) ->
+ maps:remove(nodedown_reason, BadMap0);
+ {ok, BadNRVal} ->
+ throw({error,
+ {bad_option_value,
+ #{nodedown_reason => BadNRVal}}})
+ end,
+ BadMap2 = case maps:find(node_type, BadMap1) of
+ error ->
+ BadMap1;
+ {ok, NTVal} when NTVal == visible; NTVal == hidden; NTVal == all ->
+ maps:remove(node_type, BadMap1);
+ {ok, BadNTVal} ->
+ throw({error,
+ {bad_option_value,
+ #{node_type => BadNTVal}}})
+ end,
+ if map_size(BadMap2) == 0 ->
+ {error, internal_error};
+ true ->
+ throw({error, {unknown_options, BadMap2}})
+ end;
check_options(Opts) ->
- {error, {options_not_a_list, Opts}}.
+ {error, {invalid_options, Opts}}.
+
mk_monitor_nodes_error(Flag, _Opts) when Flag =/= true, Flag =/= false ->
error;
@@ -1510,23 +1636,30 @@ mk_monitor_nodes_error(_Flag, Opts) ->
% -------------------------------------------------------------
-do_disconnect(Node, State) ->
+do_disconnect(Node, State, Async) ->
case ets:lookup(sys_dist, Node) of
[Conn] when Conn#connection.state =:= up ->
- disconnect_ctrlr(Conn#connection.ctrlr, State);
+ disconnect_ctrlr(Conn#connection.ctrlr, State, Async);
[Conn] when Conn#connection.state =:= up_pending ->
- disconnect_ctrlr(Conn#connection.ctrlr, State);
+ disconnect_ctrlr(Conn#connection.ctrlr, State, Async);
_ ->
{false, State}
end.
-disconnect_ctrlr(Ctrlr, State) ->
+disconnect_ctrlr(Ctrlr, S0, Async) ->
exit(Ctrlr, disconnect),
- receive
- {'EXIT',Ctrlr,Reason} ->
- {_,State1} = handle_exit(Ctrlr, Reason, State),
- {true, State1}
- end.
+ S2 = case Async of
+ true ->
+ S0;
+ false ->
+ receive
+ {'EXIT',Ctrlr,Reason} ->
+ {_,S1} = handle_exit(Ctrlr, Reason, S0),
+ S1
+ end
+ end,
+ {true, S2}.
+
%%
%%
@@ -1710,10 +1843,10 @@ get_proto_mod(_Family, _Protocol, []) ->
%% -------- Initialisation functions ------------------------
-init_node(Name, LongOrShortNames, CleanHalt) ->
+init_node(Name, LongOrShortNames, CleanHalt, Listen) ->
case create_name(Name, LongOrShortNames, 1) of
{ok,Node} ->
- case start_protos(Node, CleanHalt) of
+ case start_protos(Node, CleanHalt, Listen) of
{ok, Ls} ->
{ok, Node, Ls};
Error ->
@@ -1828,47 +1961,57 @@ protocol_childspecs([H|T]) ->
end.
%%
-%% epmd_module() -> module_name of erl_epmd or similar gen_server_module.
+%% epmd_module argument -> module_name of erl_epmd or similar gen_server_module.
%%
epmd_module() ->
case init:get_argument(epmd_module) of
- {ok,[[Module]]} ->
+ {ok,[[Module | _] | _]} ->
list_to_atom(Module);
_ ->
erl_epmd
end.
%%
-%% dist_listen() -> whether the erlang distribution should listen for connections
+%% -dist_listen argument -> whether the erlang distribution should listen for connections
%%
-dist_listen() ->
- case persistent_term:get(net_kernel, undefined) of
- dynamic_node_name ->
+
+dist_listen_argument() ->
+ case init:get_argument(dist_listen) of
+ {ok,[["false" | _] | _]} ->
false;
_ ->
- case init:get_argument(dist_listen) of
- {ok,[[DoListen]]} ->
- list_to_atom(DoListen) =/= false;
- _ ->
- true
- end
+ true
+ end.
+
+%%%
+%%% -hidden command line argument
+%%%
+
+hidden_argument() ->
+ case init:get_argument(hidden) of
+ {ok,[[] | _]} ->
+ true;
+ {ok,[["true" | _] | _]} ->
+ true;
+ _ ->
+ false
end.
%%
%% Start all protocols
%%
-start_protos(Node, CleanHalt) ->
+start_protos(Node, CleanHalt, Listen) ->
case init:get_argument(proto_dist) of
{ok, [Protos]} ->
- start_protos(Node, Protos, CleanHalt);
+ start_protos(Node, Protos, CleanHalt, Listen);
_ ->
- start_protos(Node, ["inet_tcp"], CleanHalt)
+ start_protos(Node, ["inet_tcp"], CleanHalt, Listen)
end.
-start_protos(Node, Ps, CleanHalt) ->
- Listeners = case dist_listen() of
+start_protos(Node, Ps, CleanHalt, Listen) ->
+ Listeners = case Listen of
false -> start_protos_no_listen(Node, Ps, [], CleanHalt);
_ -> start_protos_listen(Node, Ps, CleanHalt)
end,
@@ -1886,7 +2029,7 @@ start_protos_no_listen(Node, [Proto | Ps], Ls, CleanHalt) ->
{Name, "@"++_Host} = split_node(Node),
Ok = case Name of
"undefined" ->
- persistent_term:put(net_kernel,dynamic_node_name),
+ erts_internal:dynamic_node_name(true),
true;
_ ->
(set_node(Node, create_creation()) =:= ok)
@@ -1931,7 +2074,7 @@ wrap_creation(Cr) ->
start_protos_listen(Node, Ps, CleanHalt) ->
case split_node(Node) of
{"undefined", _} ->
- start_protos_no_listen(Node, Ps, [], CleanHalt);
+ error({internal_error, "Dynamic node name and dist listen both enabled"});
{Name, "@"++Host} ->
start_protos_listen(list_to_atom(Name), Host, Node, Ps, [], CleanHalt)
end.
@@ -2230,17 +2373,40 @@ async_gen_server_reply(From, Msg) ->
_:_ -> ok
end.
-call_owner(Owner, Msg) ->
- Mref = monitor(process, Owner),
- Owner ! {self(), Mref, Msg},
- receive
- {Mref, Reply} ->
- erlang:demonitor(Mref, [flush]),
- {ok, Reply};
- {'DOWN', Mref, _, _, _} ->
- error
+handle_async_response(ResponseType, ReqId, Result, #state{req_map = ReqMap0} = S0) ->
+ if ResponseType == down -> ok;
+ true -> _ = erlang:demonitor(ReqId, [flush]), ok
+ end,
+ case maps:take(ReqId, ReqMap0) of
+
+ {{SetGetOpts, From}, ReqMap1} when SetGetOpts == setopts;
+ SetGetOpts == getopts ->
+ Reply = case ResponseType of
+ reply -> Result;
+ down -> {error, noconnection}
+ end,
+ S1 = S0#state{req_map = ReqMap1},
+ async_reply({reply, Reply, S1}, From);
+
+ {{setopts_new, Op}, ReqMap1} ->
+ case maps:get(Op, ReqMap1) of
+ {setopts_new, From, 1} ->
+ %% Last response for this operation...
+ ReqMap2 = maps:remove(Op, ReqMap1),
+ S1 = S0#state{req_map = ReqMap2},
+ async_reply({reply, ok, S1}, From);
+ {setopts_new, From, N} ->
+ ReqMap2 = ReqMap1#{Op => {setopts_new, From, N-1}},
+ S1 = S0#state{req_map = ReqMap2},
+ {noreply, S1}
+ end
end.
+send_owner_request(ReqOpMap, Label, Owner, Msg) ->
+ ReqId = monitor(process, Owner),
+ Owner ! {self(), ReqId, Msg},
+ ReqOpMap#{ReqId => Label}.
+
-spec setopts(Node, Options) -> ok | {error, Reason} | ignored when
Node :: node() | new,
Options :: [inet:socket_setopt()],
@@ -2249,15 +2415,16 @@ call_owner(Owner, Msg) ->
setopts(Node, Opts) when is_atom(Node), is_list(Opts) ->
request({setopts, Node, Opts}).
-setopts_new(Opts, State) ->
+setopts_new(Opts, From, State) ->
%% First try setopts on listening socket(s)
%% Bail out on failure.
%% If successful, we are pretty sure Opts are ok
%% and we continue with config params and pending connections.
case setopts_on_listen(Opts, State#state.listen) of
ok ->
- setopts_new_1(Opts);
- Fail -> Fail
+ setopts_new_1(Opts, From, State);
+ Fail ->
+ async_reply({reply, Fail, State}, From)
end.
setopts_on_listen(_, []) -> ok;
@@ -2270,7 +2437,7 @@ setopts_on_listen(Opts, [#listen {listen = LSocket, module = Mod} | T]) ->
error:undef -> {error, enotsup}
end.
-setopts_new_1(Opts) ->
+setopts_new_1(Opts, From, #state{req_map = ReqMap0} = State) ->
ConnectOpts = case application:get_env(kernel, inet_dist_connect_options) of
{ok, CO} -> CO;
_ -> []
@@ -2293,13 +2460,36 @@ setopts_new_1(Opts) ->
PendingConns = ets:select(sys_dist, [{'_',
[{'=/=',{element,#connection.state,'$_'},up}],
['$_']}]),
- lists:foreach(fun(#connection{state = pending, owner = Owner}) ->
- call_owner(Owner, {setopts, Opts});
- (#connection{state = up_pending, pending_owner = Owner}) ->
- call_owner(Owner, {setopts, Opts});
- (_) -> ignore
- end, PendingConns),
- ok.
+
+ Op = make_ref(),
+ SendReq = fun (ReqMap, N, Owner) ->
+ {send_owner_request(ReqMap, {setopts_new, Op},
+ Owner,
+ {setopts, Opts}),
+ N+1}
+ end,
+ {ReqMap1, NoReqs} = lists:foldl(fun(#connection{state = pending,
+ owner = Owner},
+ {ReqMap, N}) ->
+ SendReq(ReqMap, N, Owner);
+ (#connection{state = up_pending,
+ pending_owner = Owner},
+ {ReqMap, N}) ->
+ SendReq(ReqMap, N, Owner);
+ (_, Acc) ->
+ Acc
+ end,
+ {ReqMap0, 0},
+ PendingConns),
+ if NoReqs == 0 ->
+ async_reply({reply, ok, State}, From);
+ true ->
+ %% Reply made later from handle_async_response() when
+ %% we've got responses from all owners that we've
+ %% made requests to...
+ ReqMap2 = ReqMap1#{Op => {setopts_new, From, NoReqs}},
+ {noreply, State#state{req_map = ReqMap2}}
+ end.
merge_opts([], B) ->
B;
@@ -2317,3 +2507,20 @@ merge_opts([H|T], B0) ->
getopts(Node, Opts) when is_atom(Node), is_list(Opts) ->
request({getopts, Node, Opts}).
+
+opts_node(Op, Node, Opts, From, #state{req_map = ReqMap0} = S0) ->
+ case ets:lookup(sys_dist, Node) of
+ [Conn] when Conn#connection.state =:= up ->
+ ReqMap1 = send_owner_request(ReqMap0,
+ {Op, From},
+ Conn#connection.owner,
+ {Op, Opts}),
+ %% Reply made later from handle_async_response() when
+ %% we get a response from the owner that we made the
+ %% request to...
+ S1 = S0#state{req_map = ReqMap1},
+ {noreply, S1};
+ _ ->
+ async_reply({reply, {error, noconnection}, S0}, From)
+ end.
+
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index 6395d37c5d..d97e6bb473 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -258,9 +258,11 @@ extensions() ->
Command :: os_command().
cmd(Cmd) ->
try
- cmd(Cmd, #{ })
+ do_cmd(Cmd, #{ })
catch
- error:_ ->
+ throw:{open_port, Reason} ->
+ badarg_with_cause([Cmd], {open_port, Reason});
+ throw:badarg ->
badarg_with_info([Cmd])
end.
@@ -273,15 +275,20 @@ cmd(Cmd, Opts) ->
catch
throw:badopt ->
badarg_with_cause([Cmd, Opts], badopt);
- error:_ ->
+ throw:{open_port, Reason} ->
+ badarg_with_cause([Cmd, Opts], {open_port, Reason});
+ throw:badarg ->
badarg_with_info([Cmd, Opts])
end.
do_cmd(Cmd, Opts) ->
MaxSize = get_option(max_size, Opts, infinity),
{SpawnCmd, SpawnOpts, SpawnInput, Eot} = mk_cmd(os:type(), validate(Cmd)),
- Port = open_port({spawn, SpawnCmd}, [binary, stderr_to_stdout,
- stream, in, hide | SpawnOpts]),
+ Port = try open_port({spawn, SpawnCmd}, [binary, stderr_to_stdout,
+ stream, in, hide | SpawnOpts])
+ catch error:Reason ->
+ throw({open_port, Reason})
+ end,
MonRef = erlang:monitor(port, Port),
true = port_command(Port, SpawnInput),
Bytes = get_data(Port, MonRef, Eot, [], 0, MaxSize),
@@ -313,7 +320,22 @@ mk_cmd(_,Cmd) ->
%% We use an absolute path here because we do not want the path to be
%% searched in case a stale NFS handle is somewhere in the path before
%% the sh command.
- {"/bin/sh -s unix:cmd", [out],
+ %%
+ %% Check if the default shell is located in /bin/sh as expected usually
+ %% or in /system/bin/sh as implemented on Android. The raw option is
+ %% used to bypass the file server and speed up the file access.
+ Shell = case file:read_file_info("/bin/sh",[raw]) of
+ {ok,#file_info{type=regular}} ->
+ "/bin/sh";
+ _ ->
+ case file:read_file_info("/system/bin/sh",[raw]) of
+ {ok,#file_info{type=regular}} ->
+ "/system/bin/sh";
+ _ ->
+ "/bin/sh"
+ end
+ end,
+ {Shell ++ " -s unix:cmd", [out],
%% We insert a new line after the command, in case the command
%% contains a comment character.
%%
@@ -331,34 +353,39 @@ mk_cmd(_,Cmd) ->
["(", unicode:characters_to_binary(Cmd), "\n) </dev/null; echo \"\^D\"\n"],
<<$\^D>>}.
-validate(Atom) when is_atom(Atom) ->
- validate(atom_to_list(Atom));
-validate(List) when is_list(List) ->
- case validate1(List) of
+validate(Term) ->
+ try validate1(Term)
+ catch error:_ -> throw(badarg)
+ end.
+
+validate1(Atom) when is_atom(Atom) ->
+ validate1(atom_to_list(Atom));
+validate1(List) when is_list(List) ->
+ case validate2(List) of
false ->
List;
- true ->
+ true ->
%% Had zeros at end; remove them...
string:trim(List, trailing, [0])
end.
-validate1([0|Rest]) ->
+validate2([0|Rest]) ->
+ validate3(Rest);
+validate2([C|Rest]) when is_integer(C), C > 0 ->
validate2(Rest);
-validate1([C|Rest]) when is_integer(C), C > 0 ->
- validate1(Rest);
-validate1([List|Rest]) when is_list(List) ->
- validate1(List) or validate1(Rest);
-validate1([]) ->
+validate2([List|Rest]) when is_list(List) ->
+ validate2(List) or validate2(Rest);
+validate2([]) ->
false.
%% Ensure that the rest is zero only...
-validate2([]) ->
+validate3([]) ->
true;
-validate2([0|Rest]) ->
- validate2(Rest);
-validate2([List|Rest]) when is_list(List) ->
- validate2(List),
- validate2(Rest).
+validate3([0|Rest]) ->
+ validate3(Rest);
+validate3([List|Rest]) when is_list(List) ->
+ validate3(List),
+ validate3(Rest).
get_data(Port, MonRef, Eot, Sofar, Size, Max) ->
receive
diff --git a/lib/kernel/src/pg.erl b/lib/kernel/src/pg.erl
index 573d2e6953..017b1942b4 100644
--- a/lib/kernel/src/pg.erl
+++ b/lib/kernel/src/pg.erl
@@ -60,6 +60,12 @@
join/2,
leave/2,
+ monitor_scope/0,
+ monitor_scope/1,
+ monitor/1,
+ monitor/2,
+ demonitor/1,
+ demonitor/2,
get_members/1,
get_local_members/1,
which_groups/0,
@@ -144,6 +150,52 @@ leave(Scope, Group, PidOrPids) when is_pid(PidOrPids); is_list(PidOrPids) ->
%%--------------------------------------------------------------------
%% @doc
+%% Returns currently known groups, and begins monitoring
+%% all group changes. Calling process will receive {Ref, join, Group, Pids}
+%% message when new Pids join the Group, and {Ref, leave, Group, Pids} when
+%% Pids leave the group.
+-spec monitor_scope() -> {reference(), #{group() => [pid()]}}.
+monitor_scope() ->
+ monitor_scope(?DEFAULT_SCOPE).
+
+-spec monitor_scope(Scope :: atom()) -> {reference(), #{group() => [pid()]}}.
+monitor_scope(Scope) ->
+ gen_server:call(Scope, monitor, infinity).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Returns list of processes in the requested group, and begins monitoring
+%% group changes. Calling process will receive {Ref, join, Group, Pids}
+%% message when new Pids join the Group, and {Ref, leave, Group, Pids} when
+%% Pids leave the group.
+-spec monitor(Group :: group()) -> {reference(), [pid()]}.
+monitor(Group) ->
+ ?MODULE:monitor(?DEFAULT_SCOPE, Group).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Returns list of processes in the requested group, and begins monitoring
+%% group changes. Calling process will receive {Ref, join, Group, Pids}
+%% message when new Pids join the Group, and {Ref, leave, Group, Pids} when
+%% Pids leave the group.
+-spec monitor(Scope :: atom(), Group :: group()) -> {reference(), [pid()]}.
+monitor(Scope, Group) ->
+ gen_server:call(Scope, {monitor, Group}, infinity).
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Stops monitoring Scope for groups changes. Flushes all
+%% {Ref, join|leave, Group, Pids} messages from the calling process queue.
+-spec demonitor(Ref :: reference()) -> ok | false.
+demonitor(Ref) ->
+ pg:demonitor(?DEFAULT_SCOPE, Ref).
+
+-spec demonitor(Scope :: atom(), Ref :: reference()) -> ok | false.
+demonitor(Scope, Ref) ->
+ gen_server:call(Scope, {demonitor, Ref}, infinity) =:= ok andalso flush(Ref).
+
+%%--------------------------------------------------------------------
+%% @doc
%% Returns all processes in a group
-spec get_members(Group :: group()) -> [pid()].
get_members(Group) ->
@@ -204,9 +256,14 @@ which_local_groups(Scope) when is_atom(Scope) ->
%% ETS table name, and also the registered process name (self())
scope :: atom(),
%% monitored local processes and groups they joined
- monitors = #{} :: #{pid() => {MRef :: reference(), Groups :: [group()]}},
+ local = #{} :: #{pid() => {MRef :: reference(), Groups :: [group()]}},
%% remote node: scope process monitor and map of groups to pids for fast sync routine
- nodes = #{} :: #{pid() => {reference(), #{group() => [pid()]}}}
+ remote = #{} :: #{pid() => {reference(), #{group() => [pid()]}}},
+ %% processes monitoring group membership
+ scope_monitors = #{} :: #{reference() => pid()},
+ %% processes monitoring specific groups (forward and reverse map)
+ group_monitors = #{} :: #{reference() => group()},
+ monitored_groups = #{} :: #{group() => [{pid(), reference()}]}
}).
-type state() :: #state{}.
@@ -214,44 +271,86 @@ which_local_groups(Scope) when is_atom(Scope) ->
-spec init([Scope :: atom()]) -> {ok, state()}.
init([Scope]) ->
ok = net_kernel:monitor_nodes(true),
- %% discover all nodes in the cluster
+ %% discover all nodes running this scope in the cluster
broadcast([{Scope, Node} || Node <- nodes()], {discover, self()}),
Scope = ets:new(Scope, [set, protected, named_table, {read_concurrency, true}]),
{ok, #state{scope = Scope}}.
-spec handle_call(Call :: {join_local, Group :: group(), Pid :: pid()}
- | {leave_local, Group :: group(), Pid :: pid()},
- From :: {pid(),Tag :: any()},
- State :: state()) -> {reply, ok | not_joined, state()}.
-
-handle_call({join_local, Group, PidOrPids}, _From, #state{scope = Scope, monitors = Monitors, nodes = Nodes} = State) ->
- NewMons = join_monitors(PidOrPids, Group, Monitors),
- join_local_group(Scope, Group, PidOrPids),
- broadcast(maps:keys(Nodes), {join, self(), Group, PidOrPids}),
- {reply, ok, State#state{monitors = NewMons}};
-
-handle_call({leave_local, Group, PidOrPids}, _From, #state{scope = Scope, monitors = Monitors, nodes = Nodes} = State) ->
- case leave_monitors(PidOrPids, Group, Monitors) of
- Monitors ->
+ | {leave_local, Group :: group(), Pid :: pid()}
+ | monitor
+ | {monitor, Group :: group()}
+ | {demonitor, Ref :: reference()},
+ From :: {pid(), Tag :: any()},
+ State :: state()) ->
+ {reply, ok | not_joined | {reference(), #{group() => [pid()]}} | false, state()}.
+
+handle_call({join_local, Group, PidOrPids}, _From, #state{scope = Scope, local = Local,
+ remote = Remote, scope_monitors = ScopeMon, monitored_groups = MG} = State) ->
+ NewLocal = join_local(PidOrPids, Group, Local),
+ join_local_update_ets(Scope, ScopeMon, MG, Group, PidOrPids),
+ broadcast(maps:keys(Remote), {join, self(), Group, PidOrPids}),
+ {reply, ok, State#state{local = NewLocal}};
+
+handle_call({leave_local, Group, PidOrPids}, _From, #state{scope = Scope, local = Local,
+ remote = Remote, scope_monitors = ScopeMon, monitored_groups = MG} = State) ->
+ case leave_local(PidOrPids, Group, Local) of
+ Local ->
{reply, not_joined, State};
- NewMons ->
- leave_local_group(Scope, Group, PidOrPids),
- broadcast(maps:keys(Nodes), {leave, self(), PidOrPids, [Group]}),
- {reply, ok, State#state{monitors = NewMons}}
+ NewLocal ->
+ leave_local_update_ets(Scope, ScopeMon, MG, Group, PidOrPids),
+ broadcast(maps:keys(Remote), {leave, self(), PidOrPids, [Group]}),
+ {reply, ok, State#state{local = NewLocal}}
+ end;
+
+handle_call(monitor, {Pid, _Tag}, #state{scope = Scope, scope_monitors = ScopeMon} = State) ->
+ %% next line could also be done with iterating over process state, but it appears to be slower
+ Local = maps:from_list([{G,P} || [G,P] <- ets:match(Scope, {'$1', '$2', '_'})]),
+ MRef = erlang:monitor(process, Pid), %% monitor the monitor, to discard it upon termination, and generate MRef
+ {reply, {MRef, Local}, State#state{scope_monitors = ScopeMon#{MRef => Pid}}};
+
+handle_call({monitor, Group}, {Pid, _Tag}, #state{scope = Scope, group_monitors = GM, monitored_groups = MG} = State) ->
+ %% ETS cache is writable only from this process - so get_members is safe to use
+ Members = get_members(Scope, Group),
+ MRef = erlang:monitor(process, Pid),
+ NewMG = maps:update_with(Group, fun (Ex) -> [{Pid, MRef} | Ex] end, [{Pid, MRef}], MG),
+ {reply, {MRef, Members}, State#state{group_monitors = GM#{MRef => {Pid, Group}}, monitored_groups = NewMG}};
+
+handle_call({demonitor, Ref}, _From, #state{scope_monitors = ScopeMon, group_monitors = GM,
+ monitored_groups = MG} = State) ->
+ %% not using maybe_drop_monitor here as it does not demonitor, and can not return 'false'
+ case maps:take(Ref, ScopeMon) of
+ {_, NewMons} ->
+ erlang:demonitor(Ref),
+ {reply, ok, State#state{scope_monitors = NewMons}};
+ error ->
+ %% group monitor
+ case maps:take(Ref, GM) of
+ {{Pid, Group}, NewGM} ->
+ erlang:demonitor(Ref),
+ {reply, ok, State#state{group_monitors = NewGM,
+ monitored_groups = demonitor_group({Pid, Ref}, Group, MG)}};
+ error ->
+ {reply, false, State}
+ end
end;
handle_call(_Request, _From, _S) ->
- error(badarg).
+ erlang:error(badarg).
-spec handle_cast(
- {sync, Peer :: pid(), Groups :: [{group(), [pid()]}]},
+ {sync, Peer :: pid(), Groups :: [{group(), [pid()]}]} |
+ {discover, Peer :: pid()} |
+ {join, Peer :: pid(), group(), pid() | [pid()]} |
+ {leave, Peer :: pid(), pid() | [pid()], [group()]},
State :: state()) -> {noreply, state()}.
-handle_cast({sync, Peer, Groups}, #state{scope = Scope, nodes = Nodes} = State) ->
- {noreply, State#state{nodes = handle_sync(Scope, Peer, Nodes, Groups)}};
+handle_cast({sync, Peer, Groups}, #state{scope = Scope, remote = Remote, scope_monitors = ScopeMon,
+ monitored_groups = MG} = State) ->
+ {noreply, State#state{remote = handle_sync(Scope, ScopeMon, MG, Peer, Remote, Groups)}};
handle_cast(_, _State) ->
- error(badarg).
+ erlang:error(badarg).
-spec handle_info(
{discover, Peer :: pid()} |
@@ -261,13 +360,14 @@ handle_cast(_, _State) ->
{nodedown, node()} | {nodeup, node()}, State :: state()) -> {noreply, state()}.
%% remote pid or several pids joining the group
-handle_info({join, Peer, Group, PidOrPids}, #state{scope = Scope, nodes = Nodes} = State) ->
- case maps:get(Peer, Nodes, []) of
+handle_info({join, Peer, Group, PidOrPids}, #state{scope = Scope, remote = Remote, scope_monitors = ScopeMon,
+ monitored_groups = MG} = State) ->
+ case maps:get(Peer, Remote, []) of
{MRef, RemoteGroups} ->
- join_remote(Scope, Group, PidOrPids),
+ join_remote_update_ets(Scope, ScopeMon, MG, Group, PidOrPids),
%% store remote group => pids map for fast sync operation
- NewRemoteGroups = join_remote_map(Group, PidOrPids, RemoteGroups),
- {noreply, State#state{nodes = Nodes#{Peer => {MRef, NewRemoteGroups}}}};
+ NewRemoteGroups = join_remote(Group, PidOrPids, RemoteGroups),
+ {noreply, State#state{remote = Remote#{Peer => {MRef, NewRemoteGroups}}}};
[] ->
%% handle possible race condition, when remote node is flickering up/down,
%% and remote join can happen after the node left overlay network
@@ -277,12 +377,13 @@ handle_info({join, Peer, Group, PidOrPids}, #state{scope = Scope, nodes = Nodes}
end;
%% remote pid leaving (multiple groups at once)
-handle_info({leave, Peer, PidOrPids, Groups}, #state{scope = Scope, nodes = Nodes} = State) ->
- case maps:get(Peer, Nodes, []) of
+handle_info({leave, Peer, PidOrPids, Groups}, #state{scope = Scope, remote = Remote, scope_monitors = ScopeMon,
+ monitored_groups = MG} = State) ->
+ case maps:get(Peer, Remote, []) of
{MRef, RemoteMap} ->
- _ = leave_remote(Scope, PidOrPids, Groups),
- NewRemoteMap = leave_update_remote_map(PidOrPids, RemoteMap, Groups),
- {noreply, State#state{nodes = Nodes#{Peer => {MRef, NewRemoteMap}}}};
+ _ = leave_remote_update_ets(Scope, ScopeMon, MG, PidOrPids, Groups),
+ NewRemoteMap = leave_remote(PidOrPids, RemoteMap, Groups),
+ {noreply, State#state{remote = Remote#{Peer => {MRef, NewRemoteMap}}}};
[] ->
%% Handle race condition: remote node disconnected, but scope process
%% of the remote node was just about to send 'leave' message. In this
@@ -294,36 +395,42 @@ handle_info({leave, Peer, PidOrPids, Groups}, #state{scope = Scope, nodes = Node
end;
%% we're being discovered, let's exchange!
-handle_info({discover, Peer}, #state{nodes = Nodes, monitors = Monitors} = State) ->
- gen_server:cast(Peer, {sync, self(), all_local_pids(Monitors)}),
+handle_info({discover, Peer}, #state{remote = Remote, local = Local} = State) ->
+ gen_server:cast(Peer, {sync, self(), all_local_pids(Local)}),
%% do we know who is looking for us?
- case maps:is_key(Peer, Nodes) of
+ case maps:is_key(Peer, Remote) of
true ->
{noreply, State};
false ->
- MRef = monitor(process, Peer),
+ MRef = erlang:monitor(process, Peer),
erlang:send(Peer, {discover, self()}, [noconnect]),
- {noreply, State#state{nodes = Nodes#{Peer => {MRef, #{}}}}}
+ {noreply, State#state{remote = Remote#{Peer => {MRef, #{}}}}}
end;
-%% handle local process exit
-handle_info({'DOWN', MRef, process, Pid, _Info}, #state{scope = Scope, monitors = Monitors, nodes = Nodes} = State) when node(Pid) =:= node() ->
- case maps:take(Pid, Monitors) of
+%% handle local process exit, or a local monitor exit
+handle_info({'DOWN', MRef, process, Pid, _Info}, #state{scope = Scope, local = Local,
+ remote = Remote, scope_monitors = ScopeMon, monitored_groups = MG} = State) when node(Pid) =:= node() ->
+ case maps:take(Pid, Local) of
error ->
- %% this can only happen when leave request and 'DOWN' are in pg queue
- {noreply, State};
- {{MRef, Groups}, NewMons} ->
- [leave_local_group(Scope, Group, Pid) || Group <- Groups],
- %% send update to all nodes
- broadcast(maps:keys(Nodes), {leave, self(), Pid, Groups}),
- {noreply, State#state{monitors = NewMons}}
+ {noreply, maybe_drop_monitor(MRef, State)};
+ {{MRef, Groups}, NewLocal} ->
+ [leave_local_update_ets(Scope, ScopeMon, MG, Group, Pid) || Group <- Groups],
+ %% send update to all remote peers
+ broadcast(maps:keys(Remote), {leave, self(), Pid, Groups}),
+ {noreply, State#state{local = NewLocal}}
end;
-%% handle remote node down or leaving overlay network
-handle_info({'DOWN', MRef, process, Pid, _Info}, #state{scope = Scope, nodes = Nodes} = State) ->
- {{MRef, RemoteMap}, NewNodes} = maps:take(Pid, Nodes),
- maps:foreach(fun (Group, Pids) -> leave_remote(Scope, Pids, [Group]) end, RemoteMap),
- {noreply, State#state{nodes = NewNodes}};
+%% handle remote node down or scope leaving overlay network, or a monitor from the remote node went down
+handle_info({'DOWN', MRef, process, Pid, _Info}, #state{scope = Scope, remote = Remote,
+ scope_monitors = ScopeMon, monitored_groups = MG} = State) ->
+ case maps:take(Pid, Remote) of
+ {{MRef, RemoteMap}, NewRemote} ->
+ maps:foreach(fun (Group, Pids) ->
+ leave_remote_update_ets(Scope, ScopeMon, MG, Pids, [Group]) end, RemoteMap),
+ {noreply, State#state{remote = NewRemote}};
+ error ->
+ {noreply, maybe_drop_monitor(MRef, State)}
+ end;
%% nodedown: ignore, and wait for 'DOWN' signal for monitored process
handle_info({nodedown, _Node}, State) ->
@@ -337,7 +444,7 @@ handle_info({nodeup, Node}, #state{scope = Scope} = State) ->
{noreply, State};
handle_info(_Info, _State) ->
- error(badarg).
+ erlang:error(badarg).
-spec terminate(Reason :: any(), State :: state()) -> true.
terminate(_Reason, #state{scope = Scope}) ->
@@ -355,125 +462,131 @@ ensure_local(Pids) when is_list(Pids) ->
(Pid) when is_pid(Pid), node(Pid) =:= node() ->
ok;
(Bad) ->
- error({nolocal, Bad})
+ erlang:error({nolocal, Bad})
end, Pids);
ensure_local(Bad) ->
- error({nolocal, Bad}).
+ erlang:error({nolocal, Bad}).
%% Override all knowledge of the remote node with information it sends
%% to local node. Current implementation must do the full table scan
%% to remove stale pids (just as for 'nodedown').
-handle_sync(Scope, Peer, Nodes, Groups) ->
+handle_sync(Scope, ScopeMon, MG, Peer, Remote, Groups) ->
%% can't use maps:get() because it evaluates 'default' value first,
%% and in this case monitor() call has side effect.
{MRef, RemoteGroups} =
- case maps:find(Peer, Nodes) of
+ case maps:find(Peer, Remote) of
error ->
- {monitor(process, Peer), #{}};
+ {erlang:monitor(process, Peer), #{}};
{ok, MRef0} ->
MRef0
end,
%% sync RemoteMap and transform ETS table
- _ = sync_groups(Scope, RemoteGroups, Groups),
- Nodes#{Peer => {MRef, maps:from_list(Groups)}}.
+ _ = sync_groups(Scope, ScopeMon, MG, RemoteGroups, Groups),
+ Remote#{Peer => {MRef, maps:from_list(Groups)}}.
-sync_groups(Scope, RemoteGroups, []) ->
+sync_groups(Scope, ScopeMon, MG, RemoteGroups, []) ->
%% leave all missing groups
- [leave_remote(Scope, Pids, [Group]) || {Group, Pids} <- maps:to_list(RemoteGroups)];
-sync_groups(Scope, RemoteGroups, [{Group, Pids} | Tail]) ->
+ [leave_remote_update_ets(Scope, ScopeMon, MG, Pids, [Group]) || {Group, Pids} <- maps:to_list(RemoteGroups)];
+sync_groups(Scope, ScopeMon, MG, RemoteGroups, [{Group, Pids} | Tail]) ->
case maps:take(Group, RemoteGroups) of
{Pids, NewRemoteGroups} ->
- sync_groups(Scope, NewRemoteGroups, Tail);
+ sync_groups(Scope, ScopeMon, MG, NewRemoteGroups, Tail);
{OldPids, NewRemoteGroups} ->
[{Group, AllOldPids, LocalPids}] = ets:lookup(Scope, Group),
%% should be really rare...
AllNewPids = Pids ++ AllOldPids -- OldPids,
true = ets:insert(Scope, {Group, AllNewPids, LocalPids}),
- sync_groups(Scope, NewRemoteGroups, Tail);
+ sync_groups(Scope, ScopeMon, MG, NewRemoteGroups, Tail);
error ->
- join_remote(Scope, Group, Pids),
- sync_groups(Scope, RemoteGroups, Tail)
+ join_remote_update_ets(Scope, ScopeMon, MG, Group, Pids),
+ sync_groups(Scope, ScopeMon, MG, RemoteGroups, Tail)
end.
-join_monitors(Pid, Group, Monitors) when is_pid(Pid) ->
- case maps:find(Pid, Monitors) of
+join_local(Pid, Group, Local) when is_pid(Pid) ->
+ case maps:find(Pid, Local) of
{ok, {MRef, Groups}} ->
- maps:put(Pid, {MRef, [Group | Groups]}, Monitors);
+ maps:put(Pid, {MRef, [Group | Groups]}, Local);
error ->
MRef = erlang:monitor(process, Pid),
- Monitors#{Pid => {MRef, [Group]}}
+ Local#{Pid => {MRef, [Group]}}
end;
-join_monitors([], _Group, Monitors) ->
- Monitors;
-join_monitors([Pid | Tail], Group, Monitors) ->
- join_monitors(Tail, Group, join_monitors(Pid, Group, Monitors)).
+join_local([], _Group, Local) ->
+ Local;
+join_local([Pid | Tail], Group, Local) ->
+ join_local(Tail, Group, join_local(Pid, Group, Local)).
-join_local_group(Scope, Group, Pid) when is_pid(Pid) ->
+join_local_update_ets(Scope, ScopeMon, MG, Group, Pid) when is_pid(Pid) ->
case ets:lookup(Scope, Group) of
[{Group, All, Local}] ->
ets:insert(Scope, {Group, [Pid | All], [Pid | Local]});
[] ->
ets:insert(Scope, {Group, [Pid], [Pid]})
- end;
-join_local_group(Scope, Group, Pids) ->
+ end,
+ notify_group(ScopeMon, MG, join, Group, [Pid]);
+join_local_update_ets(Scope, ScopeMon, MG, Group, Pids) ->
case ets:lookup(Scope, Group) of
[{Group, All, Local}] ->
ets:insert(Scope, {Group, Pids ++ All, Pids ++ Local});
[] ->
ets:insert(Scope, {Group, Pids, Pids})
- end.
+ end,
+ notify_group(ScopeMon, MG, join, Group, Pids).
-join_remote(Scope, Group, Pid) when is_pid(Pid) ->
+join_remote_update_ets(Scope, ScopeMon, MG, Group, Pid) when is_pid(Pid) ->
case ets:lookup(Scope, Group) of
[{Group, All, Local}] ->
ets:insert(Scope, {Group, [Pid | All], Local});
[] ->
ets:insert(Scope, {Group, [Pid], []})
- end;
-join_remote(Scope, Group, Pids) ->
+ end,
+ notify_group(ScopeMon, MG, join, Group, [Pid]);
+join_remote_update_ets(Scope, ScopeMon, MG, Group, Pids) ->
case ets:lookup(Scope, Group) of
[{Group, All, Local}] ->
ets:insert(Scope, {Group, Pids ++ All, Local});
[] ->
ets:insert(Scope, {Group, Pids, []})
- end.
+ end,
+ notify_group(ScopeMon, MG, join, Group, Pids).
-join_remote_map(Group, Pid, RemoteGroups) when is_pid(Pid) ->
+join_remote(Group, Pid, RemoteGroups) when is_pid(Pid) ->
maps:update_with(Group, fun (List) -> [Pid | List] end, [Pid], RemoteGroups);
-join_remote_map(Group, Pids, RemoteGroups) ->
+join_remote(Group, Pids, RemoteGroups) ->
maps:update_with(Group, fun (List) -> Pids ++ List end, Pids, RemoteGroups).
-leave_monitors(Pid, Group, Monitors) when is_pid(Pid) ->
- case maps:find(Pid, Monitors) of
+leave_local(Pid, Group, Local) when is_pid(Pid) ->
+ case maps:find(Pid, Local) of
{ok, {MRef, [Group]}} ->
erlang:demonitor(MRef),
- maps:remove(Pid, Monitors);
+ maps:remove(Pid, Local);
{ok, {MRef, Groups}} ->
case lists:member(Group, Groups) of
true ->
- maps:put(Pid, {MRef, lists:delete(Group, Groups)}, Monitors);
+ maps:put(Pid, {MRef, lists:delete(Group, Groups)}, Local);
false ->
- Monitors
+ Local
end;
_ ->
- Monitors
+ Local
end;
-leave_monitors([], _Group, Monitors) ->
- Monitors;
-leave_monitors([Pid | Tail], Group, Monitors) ->
- leave_monitors(Tail, Group, leave_monitors(Pid, Group, Monitors)).
+leave_local([], _Group, Local) ->
+ Local;
+leave_local([Pid | Tail], Group, Local) ->
+ leave_local(Tail, Group, leave_local(Pid, Group, Local)).
-leave_local_group(Scope, Group, Pid) when is_pid(Pid) ->
+leave_local_update_ets(Scope, ScopeMon, MG, Group, Pid) when is_pid(Pid) ->
case ets:lookup(Scope, Group) of
[{Group, [Pid], [Pid]}] ->
- ets:delete(Scope, Group);
+ ets:delete(Scope, Group),
+ notify_group(ScopeMon, MG, leave, Group, [Pid]);
[{Group, All, Local}] ->
- ets:insert(Scope, {Group, lists:delete(Pid, All), lists:delete(Pid, Local)});
+ ets:insert(Scope, {Group, lists:delete(Pid, All), lists:delete(Pid, Local)}),
+ notify_group(ScopeMon, MG, leave, Group, [Pid]);
[] ->
%% rare race condition when 'DOWN' from monitor stays in msg queue while process is leave-ing.
true
end;
-leave_local_group(Scope, Group, Pids) ->
+leave_local_update_ets(Scope, ScopeMon, MG, Group, Pids) ->
case ets:lookup(Scope, Group) of
[{Group, All, Local}] ->
case All -- Pids of
@@ -481,23 +594,26 @@ leave_local_group(Scope, Group, Pids) ->
ets:delete(Scope, Group);
NewAll ->
ets:insert(Scope, {Group, NewAll, Local -- Pids})
- end;
+ end,
+ notify_group(ScopeMon, MG, leave, Group, Pids);
[] ->
true
end.
-leave_remote(Scope, Pid, Groups) when is_pid(Pid) ->
+leave_remote_update_ets(Scope, ScopeMon, MG, Pid, Groups) when is_pid(Pid) ->
_ = [
case ets:lookup(Scope, Group) of
[{Group, [Pid], []}] ->
- ets:delete(Scope, Group);
+ ets:delete(Scope, Group),
+ notify_group(ScopeMon, MG, leave, Group, [Pid]);
[{Group, All, Local}] ->
- ets:insert(Scope, {Group, lists:delete(Pid, All), Local});
+ ets:insert(Scope, {Group, lists:delete(Pid, All), Local}),
+ notify_group(ScopeMon, MG, leave, Group, [Pid]);
[] ->
true
end ||
Group <- Groups];
-leave_remote(Scope, Pids, Groups) ->
+leave_remote_update_ets(Scope, ScopeMon, MG, Pids, Groups) ->
_ = [
case ets:lookup(Scope, Group) of
[{Group, All, Local}] ->
@@ -506,15 +622,16 @@ leave_remote(Scope, Pids, Groups) ->
ets:delete(Scope, Group);
NewAll ->
ets:insert(Scope, {Group, NewAll, Local})
- end;
+ end,
+ notify_group(ScopeMon, MG, leave, Group, Pids);
[] ->
true
end ||
Group <- Groups].
-leave_update_remote_map(Pid, RemoteMap, Groups) when is_pid(Pid) ->
- leave_update_remote_map([Pid], RemoteMap, Groups);
-leave_update_remote_map(Pids, RemoteMap, Groups) ->
+leave_remote(Pid, RemoteMap, Groups) when is_pid(Pid) ->
+ leave_remote([Pid], RemoteMap, Groups);
+leave_remote(Pids, RemoteMap, Groups) ->
lists:foldl(
fun (Group, Acc) ->
case maps:get(Group, Acc) -- Pids of
@@ -525,20 +642,14 @@ leave_update_remote_map(Pids, RemoteMap, Groups) ->
end
end, RemoteMap, Groups).
-all_local_pids(Monitors) ->
+all_local_pids(Local) ->
maps:to_list(maps:fold(
fun(Pid, {_Ref, Groups}, Acc) ->
lists:foldl(
fun(Group, Acc1) ->
Acc1#{Group => [Pid | maps:get(Group, Acc1, [])]}
- end,
- Acc,
- Groups
- )
- end,
- #{},
- Monitors
- )).
+ end, Acc, Groups)
+ end, #{}, Local)).
%% Works as gen_server:abcast(), but accepts a list of processes
%% instead of nodes list.
@@ -549,3 +660,51 @@ broadcast([Dest | Tail], Msg) ->
%% join/leave messages when dist buffer is full
erlang:send(Dest, Msg, [noconnect]),
broadcast(Tail, Msg).
+
+%% drops a monitor if DOWN was received
+maybe_drop_monitor(MRef, #state{scope_monitors = ScopeMon, group_monitors = GMs, monitored_groups = MG} = State) ->
+ %% could be a local monitor going DOWN. Since it's a rare event, check should
+ %% not stay in front of any other, more frequent events
+ case maps:take(MRef, ScopeMon) of
+ error ->
+ case maps:take(MRef, GMs) of
+ error ->
+ State;
+ {{Pid, Group}, NewGM} ->
+ %% clean up the inverse map
+ State#state{group_monitors = NewGM, monitored_groups = demonitor_group({Pid, MRef}, Group, MG)}
+ end;
+ {_Pid, NewScopeMon} ->
+ State#state{scope_monitors = NewScopeMon}
+ end.
+
+demonitor_group(Tag, Group, MG) ->
+ case maps:find(Group, MG) of
+ {ok, [Tag]} ->
+ maps:remove(Group, MG);
+ {ok, Tags} ->
+ maps:put(Group, Tags -- [Tag], MG)
+ end.
+
+%% notify all monitors about an Action in Groups for Pids
+notify_group(ScopeMonitors, MG, Action, Group, Pids) ->
+ maps:foreach(
+ fun (Ref, Pid) ->
+ erlang:send(Pid, {Ref, Action, Group, Pids}, [noconnect])
+ end, ScopeMonitors),
+ case maps:find(Group, MG) of
+ error ->
+ ok;
+ {ok, Monitors} ->
+ [erlang:send(Pid, {Ref, Action, Group, Pids}, [noconnect]) || {Pid, Ref} <- Monitors],
+ ok
+ end.
+
+%% remove all messages that were send to monitor groups
+flush(Ref) ->
+ receive
+ {Ref, Verb, _Group, _Pids} when Verb =:= join; Verb =:= leave ->
+ flush(Ref)
+ after 0 ->
+ ok
+ end.
diff --git a/lib/kernel/src/ram_file.erl b/lib/kernel/src/ram_file.erl
index e7b5e1eedb..ae0784b770 100644
--- a/lib/kernel/src/ram_file.erl
+++ b/lib/kernel/src/ram_file.erl
@@ -41,7 +41,7 @@
%% --------------------------------------------------------------------------
%% These operation codes were once identical between efile_drv.c
-%% and ram_file_drv.c, but now these drivers are not depeding on each other.
+%% and ram_file_drv.c, but now these drivers are not depending on each other.
%% So, the codes could be changed to more logical values now, but why indeed?
%% Defined "file" functions
@@ -394,7 +394,7 @@ ll_close(Port) ->
%%% Utility functions.
%% Converts a list of mode atoms into an mode word for the driver.
-%% Returns {Mode, Opts} wher Opts is a list of options for
+%% Returns {Mode, Opts} where Opts is a list of options for
%% erlang:open_port/2, or {error, einval} upon failure.
open_mode(List) when is_list(List) ->
diff --git a/lib/kernel/src/raw_file_io.erl b/lib/kernel/src/raw_file_io.erl
index a153adeff0..ac60c3089b 100644
--- a/lib/kernel/src/raw_file_io.erl
+++ b/lib/kernel/src/raw_file_io.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,6 +56,7 @@ match_list(list) -> true;
match_list(_Other) -> false.
match_compressed(compressed) -> true;
+match_compressed(compressed_one) -> true;
match_compressed(_Other) -> false.
match_delayed({delayed_write, _Size, _Timeout}) -> true;
diff --git a/lib/kernel/src/raw_file_io_inflate.erl b/lib/kernel/src/raw_file_io_inflate.erl
index a0c32b1b5e..277749299e 100644
--- a/lib/kernel/src/raw_file_io_inflate.erl
+++ b/lib/kernel/src/raw_file_io_inflate.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,12 +32,19 @@
callback_mode() -> state_functions.
init({Owner, Secret, [compressed]}) ->
- Monitor = monitor(process, Owner),
- %% We're using the undocumented inflateInit/3 to open the stream in
%% 'reset mode', which resets the inflate state at the end of every stream,
%% allowing us to read concatenated gzip files.
+ init(Owner, Secret, reset);
+init({Owner, Secret, [compressed_one]}) ->
+ %% 'cut mode', which stops the inflate after one member
+ %% allowing us to read gzipped tar files
+ init(Owner, Secret, cut).
+
+init(Owner, Secret, Mode) ->
+ Monitor = monitor(process, Owner),
+ %% We're using the undocumented inflateInit/3 to set the mode
Z = zlib:open(),
- ok = zlib:inflateInit(Z, ?GZIP_WBITS, reset),
+ ok = zlib:inflateInit(Z, ?GZIP_WBITS, Mode),
Data =
#{ owner => Owner,
monitor => Monitor,
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index a799095e87..c3b4b8f1b1 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,11 +20,7 @@
-module(rpc).
%%
-%% Implementations inside '-ifdef(SERVER_SIDE_ERPC_IS_MANDATORY).'
-%% below require 'erpc' support to be mandatory on server side.
-%% 'erpc' was introduced in OTP 23, so it should be possible to
-%% enable this as of OTP 25:
-%% -define(SERVER_SIDE_ERPC_IS_MANDATORY, yes).
+%% As of OTP 25 the rpc module require server side support for erpc.
%%
%% General rpc, broadcast,multicall, promise and parallel evaluator
@@ -123,10 +119,13 @@ init([]) ->
process_flag(trap_exit, true),
{ok, #{nodes_observer => start_nodes_observer()}}.
--spec handle_call(term(), term(), state()) ->
- {'noreply', state()} |
- {'reply', term(), state()} |
- {'stop', 'normal', 'stopped', state()}.
+-spec handle_call(
+ term(),
+ gen_server:from() | {?NAME,term()},
+ state()) ->
+ {'noreply', state()} |
+ {'reply', term(), state()} |
+ {'stop', 'normal', 'stopped', state()}.
handle_call({call, Mod, Fun, Args, Gleader}, To, S) ->
%% Spawn not to block the rex server.
@@ -146,7 +145,7 @@ handle_call({call, Mod, Fun, Args, Gleader}, To, S) ->
Ref -> ok
end;
_ ->
- gen_server:reply(To, Reply)
+ reply(To, Reply)
end
end,
try
@@ -194,7 +193,7 @@ handle_info({'DOWN', M, process, _, Reason}, S) ->
undefined ->
{noreply, S};
{_, _} = To ->
- gen_server:reply(To, {badrpc, {'EXIT', Reason}}),
+ reply(To, {badrpc, {'EXIT', Reason}}),
{noreply, maps:remove(M, S)}
end;
handle_info({From, {sbcast, Name, Msg}}, S) ->
@@ -215,7 +214,7 @@ handle_info({From, {send, Name, Msg}}, S) ->
{noreply, S};
handle_info({From, {call, Mod, Fun, Args, Gleader}}, S) ->
%% Special for hidden C node's, uugh ...
- To = {From, ?NAME},
+ To = {?NAME, From},
NewGleader =
case Gleader of
send_stdout_to_caller ->
@@ -228,7 +227,7 @@ handle_info({From, {call, Mod, Fun, Args, Gleader}}, S) ->
{noreply, _NewS} = Return ->
Return;
{reply, Reply, NewS} ->
- gen_server:reply(To, Reply),
+ reply(To, Reply),
{noreply, NewS}
end;
handle_info({From, features_request}, S) ->
@@ -250,6 +249,13 @@ code_change(_, S, _) ->
%% RPC aid functions ....
+reply({?NAME, From}, Reply) ->
+ From ! {?NAME, Reply},
+ ok;
+reply({From, _} = To, Reply) when is_pid(From) ->
+ gen_server:reply(To, Reply).
+
+
execute_call(Mod, Fun, Args) ->
try
{return, Return} = erpc:execute_call(Mod, Fun, Args),
@@ -355,32 +361,6 @@ nodes_observer_loop(Tab) ->
end,
nodes_observer_loop(Tab).
--ifdef(SERVER_SIDE_ERPC_IS_MANDATORY).
-
-%% Currently node_has_feature() is only needed if
-%% it is unknown if 'erpc' is supported by server
-%% side or not...
-
--else. %% ! define SERVER_SIDE_ERPC_IS_MANDATORY
-
--dialyzer([{nowarn_function, node_has_feature/2}, no_match]).
-
--spec node_has_feature(Node :: atom(), Feature :: term()) -> boolean().
-
-node_has_feature(N, erpc) when N == node() ->
- true;
-node_has_feature(N, erpc) ->
- try
- Tab = persistent_term:get(?TAB_NAME),
- ets:lookup_element(Tab, N, 2)
- catch
- _:_ -> false
- end;
-node_has_feature(_N, _Feature) ->
- false.
-
--endif.
-
%% THE rpc client interface
%% Call
@@ -417,34 +397,9 @@ call(N,M,F,A) ->
Reason :: term(),
Timeout :: ?TIMEOUT_TYPE.
--ifdef(SERVER_SIDE_ERPC_IS_MANDATORY).
-
call(N,M,F,A,T) ->
?RPCIFY(erpc:call(N, M, F, A, T)).
--else. %% ! defined SERVER_SIDE_ERPC_IS_MANDATORY
-
-call(N,M,F,A,T) ->
- DL = try
- deadline(T)
- catch
- error:_ ->
- error(badarg)
- end,
- case ?RPCIFY(erpc:call(N, M, F, A, T)) of
- {badrpc, notsup} ->
- case time_left(DL) of
- 0 ->
- {badrpc, timeout};
- Timeout ->
- do_srv_call(N, {call,M,F,A,group_leader()}, Timeout)
- end;
- Res ->
- Res
- end.
-
--endif. %% ! defined SERVER_SIDE_ERPC_IS_MANDATORY
-
-spec block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when
Node :: node(),
Module :: module(),
@@ -573,8 +528,6 @@ server_call(Node, Name, ReplyWrapper, Msg)
Function :: atom(),
Args :: [term()].
--ifdef(SERVER_SIDE_ERPC_IS_MANDATORY).
-
cast(Node, Mod, Fun, Args) ->
try
ok = erpc:cast(Node, Mod, Fun, Args)
@@ -584,32 +537,6 @@ cast(Node, Mod, Fun, Args) ->
end,
true.
--else.
-
-cast(Node, Mod, Fun, Args) when is_atom(Node),
- is_atom(Mod),
- is_atom(Fun),
- is_list(Args) ->
- _ = case node_has_feature(Node, erpc) of
- false ->
- gen_server:cast({?NAME,Node},
- {cast,Mod,Fun,Args,group_leader()});
- true ->
- try
- ok = erpc:cast(Node, Mod, Fun, Args)
- catch
- error:{erpc, badarg} ->
- error(badarg)
- end
- end,
- true;
-cast(_, _, _, _) ->
- error(badarg).
-
-
--endif.
-
-
%% Asynchronous broadcast, returns nothing, it's just send 'n' pray
-spec abcast(Name, Msg) -> abcast when
Name :: atom(),
@@ -630,9 +557,9 @@ abcast([Node|Tail], Name, Mess) ->
abcast([], _,_) -> abcast.
-%% Syncronous broadcast, returns a list of the nodes which had Name
+%% Synchronous broadcast, returns a list of the nodes which had Name
%% as a registered server. Returns {Goodnodes, Badnodes}.
-%% Syncronous in the sense that we know that all servers have received the
+%% Synchronous in the sense that we know that all servers have received the
%% message when we return from the call, we can't know that they have
%% processed the message though.
@@ -741,21 +668,14 @@ multicall(M, F, A, Timeout) ->
ResL :: [Res :: term() | {'badrpc', Reason :: term()}],
BadNodes :: [node()].
--ifdef(SERVER_SIDE_ERPC_IS_MANDATORY).
-
-%%
-%% Use this more efficient implementation of multicall()
-%% when 'erpc' support can be made mandatory for server
-%% side.
-%%
multicall(Nodes, M, F, A, Timeout) ->
%%
%% We want to use erpc:multicall() and then convert the result
%% instead of using erpc:send_request()/erpc:receive_response()
- %% directly. This since it is expected that erpc:multicall()
- %% will be able to utilize a future message queue optimization
- %% that erpc:send_request()/erpc:receive_response() most likely
- %% wont be able to (only the future will tell...).
+ %% directly. This since erpc:multicall() is able to utilize the
+ %% selective receive optimization when all clauses match on the
+ %% same reference. erpc:send_request()/erpc:receive_response()
+ %% is not able to utilize such optimizations.
%%
ERpcRes = try
erpc:multicall(Nodes, M, F, A, Timeout)
@@ -778,256 +698,6 @@ rpcmulticallify([N|Ns], [{error, {erpc, Reason}}|Rlts], Ok, Err)
rpcmulticallify([_N|Ns], [{Class, Reason}|Rlts], Ok, Err) ->
rpcmulticallify(Ns, Rlts, [rpcify_exception(Class, Reason)|Ok], Err).
--else. %% ! defined SERVER_SIDE_ERPC_IS_MANDATORY
-
-%%
-%% Currently used implementation for multicall(). When
-%% 'erpc' support can be required for server side,
-%% replace with the implementation above...
-%%
-
-multicall(Nodes, M, F, A, Timeout) ->
- try
- true = is_atom(M),
- true = is_atom(F),
- true = is_list(A),
- Deadline = deadline(Timeout),
- Res = make_ref(),
- MFA = {M, F, A},
- {NRs, ReqMap0} = mc_requests(Res, Nodes, M, F, A, [], #{}),
- ReqMap1 = mc_spawn_replies(Res, maps:size(ReqMap0), ReqMap0,
- MFA, Deadline),
- mc_results(Res, NRs, [], [], ReqMap1, MFA, Deadline)
- catch
- error:NotIError when NotIError /= internal_error ->
- error(badarg)
- end.
-
-mc_requests(_Res, [], _M, _F, _A, NRs, ReqMap) ->
- {NRs, ReqMap};
-mc_requests(Res, [N|Ns], M, F, A, NRs, ReqMap) ->
- ReqId = try
- spawn_request(N, erpc, execute_call,
- [Res, M, F, A],
- [{reply_tag, {spawn_reply, Res, N}},
- monitor])
- catch
- _:_ ->
- mc_fail_requests(Res, NRs)
- end,
- NR = {N, ReqId},
- mc_requests(Res, Ns, M, F, A, [NR|NRs], ReqMap#{ReqId => spawn_request});
-mc_requests(Res, _Error, _M, _F, _A, NRs, _ReqMap) ->
- mc_fail_requests(Res, NRs).
-
-%% Abandon any requests sent then fail...
-mc_fail_requests(_Res, []) ->
- error(badarg);
-mc_fail_requests(Res, [{Node, ReqId} | NRs]) ->
- case spawn_request_abandon(ReqId) of
- true ->
- ok;
- false ->
- receive
- {{spawn_reply, Res, Node}, ReqId, error, _} ->
- ok;
- {{spawn_reply, Res, Node}, ReqId, ok, Pid} ->
- case erlang:demonitor(ReqId, [info]) of
- true ->
- ok;
- false ->
- receive
- {'DOWN', ReqId, process, Pid, _} ->
- ok
- after
- 0 ->
- error(internal_error)
- end
- end
- after
- 0 ->
- error(internal_error)
- end
- end,
- mc_fail_requests(Res, NRs).
-
-mc_spawn_replies(_Res, 0, ReqMap, _MFA, _Deadline) ->
- ReqMap;
-mc_spawn_replies(Res, Outstanding, ReqMap, MFA, Deadline) ->
- Timeout = time_left(Deadline),
- receive
- {{spawn_reply, Res, _}, _, _, _} = Reply ->
- NewReqMap = mc_handle_spawn_reply(Reply, ReqMap, MFA, Deadline),
- mc_spawn_replies(Res, Outstanding-1, NewReqMap, MFA, Deadline)
- after
- Timeout ->
- ReqMap
- end.
-
-mc_handle_spawn_reply({{spawn_reply, _Res, _Node}, ReqId, ok, Pid},
- ReqMap, _MFA, _Deadline) ->
- ReqMap#{ReqId => {spawn, Pid}};
-mc_handle_spawn_reply({{spawn_reply, _Res, Node}, ReqId, error, notsup},
- ReqMap, MFA, infinity) ->
- {M, F, A} = MFA,
- SrvReqId = gen_server:send_request({?NAME, Node},
- {call, M,F,A,
- group_leader()}),
- ReqMap#{ReqId => {server, SrvReqId}};
-mc_handle_spawn_reply({{spawn_reply, Res, Node}, ReqId, error, notsup},
- ReqMap, MFA, Deadline) ->
- {M, F, A} = MFA,
- try
- {Pid, Mon} = spawn_monitor(fun () ->
- process_flag(trap_exit, true),
- Request = {call, M,F,A,
- group_leader()},
- Timeout = time_left(Deadline),
- Result = gen_server:call({?NAME,
- Node},
- Request,
- Timeout),
- exit({Res, Result})
- end),
- ReqMap#{ReqId => {spawn_server, Mon, Pid}}
- catch
- error:system_limit ->
- ReqMap#{ReqId => {error, {badrpc, {'EXIT', system_limit}}}}
- end;
-mc_handle_spawn_reply({{spawn_reply, _Res, _Node}, ReqId, error, noconnection},
- ReqMap, _MFA, _Deadline) ->
- ReqMap#{ReqId => {error, badnode}};
-mc_handle_spawn_reply({{spawn_reply, _Res, _Node}, ReqId, error, Reason},
- ReqMap, _MFA, _Deadline) ->
- ReqMap#{ReqId => {error, {badrpc, {'EXIT', Reason}}}}.
-
-mc_results(_Res, [], OkAcc, ErrAcc, _ReqMap, _MFA, _Deadline) ->
- {OkAcc, ErrAcc};
-mc_results(Res, [{N,ReqId}|NRs] = OrigNRs, OkAcc, ErrAcc,
- ReqMap, MFA, Deadline) ->
- case maps:get(ReqId, ReqMap) of
- {error, badnode} ->
- mc_results(Res, NRs, OkAcc, [N|ErrAcc], ReqMap, MFA, Deadline);
- {error, BadRpc} ->
- mc_results(Res, NRs, [BadRpc|OkAcc], ErrAcc, ReqMap,
- MFA, Deadline);
- spawn_request ->
- %% We timed out waiting for spawn replies...
- case spawn_request_abandon(ReqId) of
- true ->
- %% Timed out request...
- mc_results(Res, NRs, OkAcc, [N|ErrAcc], ReqMap,
- MFA, Deadline);
- false ->
- %% Reply has been delivered now; handle it...
- receive
- {{spawn_reply, Res, _}, ReqId, _, _} = Reply ->
- NewReqMap = mc_handle_spawn_reply(Reply, ReqMap,
- MFA, Deadline),
- mc_results(Res, OrigNRs, OkAcc, ErrAcc,
- NewReqMap, MFA, Deadline)
- after 0 ->
- error(internal_error)
- end
- end;
- {spawn, Pid} ->
- Timeout = time_left(Deadline),
- receive
- {'DOWN', ReqId, process, Pid, Reason} ->
- case ?RPCIFY(erpc:call_result(down, ReqId, Res, Reason)) of
- {badrpc, nodedown} ->
- mc_results(Res, NRs, OkAcc, [N|ErrAcc],
- ReqMap, MFA, Deadline);
- CallRes ->
- mc_results(Res, NRs, [CallRes|OkAcc],
- ErrAcc, ReqMap, MFA, Deadline)
- end
- after
- Timeout ->
- case erlang:demonitor(ReqId, [info]) of
- true ->
- mc_results(Res, NRs, OkAcc, [N|ErrAcc],
- ReqMap, MFA, Deadline);
- false ->
- receive
- {'DOWN', ReqId, process, Pid, Reason} ->
- case ?RPCIFY(erpc:call_result(down,
- ReqId,
- Res,
- Reason)) of
- {badrpc, nodedown} ->
- mc_results(Res, NRs, OkAcc,
- [N|ErrAcc], ReqMap,
- MFA, Deadline);
- CallRes ->
- mc_results(Res, NRs,
- [CallRes|OkAcc],
- ErrAcc, ReqMap,
- MFA, Deadline)
- end
- after 0 ->
- error(internal_error)
- end
- end
- end;
- {spawn_server, Mon, Pid} ->
- %% Old node with timeout on the call...
- Result = receive
- {'DOWN', Mon, process, Pid, {Res, CallRes}} ->
- rpc_check(CallRes);
- {'DOWN', Mon, process, Pid, Reason} ->
- rpc_check_t({'EXIT',Reason})
- end,
- case Result of
- {badrpc, BadRpcReason} when BadRpcReason == timeout;
- BadRpcReason == nodedown ->
- mc_results(Res, NRs, OkAcc, [N|ErrAcc],
- ReqMap, MFA, Deadline);
- _ ->
- mc_results(Res, NRs, [Result|OkAcc], ErrAcc, ReqMap,
- MFA, Deadline)
- end;
- {server, SrvReqId} ->
- %% Old node without timeout on the call...
- case gen_server:wait_response(SrvReqId, infinity) of
- {reply, Reply} ->
- Result = rpc_check(Reply),
- mc_results(Res, NRs, [Result|OkAcc], ErrAcc,
- ReqMap, MFA, Deadline);
- {error, {noconnection, _}} ->
- mc_results(Res, NRs, OkAcc, [N|ErrAcc],
- ReqMap, MFA, Deadline);
- {error, {Reason, _}} ->
- BadRpc = {badrpc, {'EXIT', Reason}},
- mc_results(Res, NRs, [BadRpc|OkAcc], ErrAcc,
- ReqMap, MFA, Deadline)
- end
- end.
-
-deadline(infinity) ->
- infinity;
-deadline(?MAX_INT_TIMEOUT) ->
- erlang:convert_time_unit(erlang:monotonic_time(millisecond)
- + ?MAX_INT_TIMEOUT,
- millisecond,
- native);
-deadline(T) when ?IS_VALID_TMO_INT(T) ->
- Now = erlang:monotonic_time(),
- NativeTmo = erlang:convert_time_unit(T, millisecond, native),
- Now + NativeTmo.
-
-time_left(infinity) ->
- infinity;
-time_left(Deadline) ->
- case Deadline - erlang:monotonic_time() of
- TimeLeft when TimeLeft =< 0 ->
- 0;
- TimeLeft ->
- erlang:convert_time_unit(TimeLeft-1, native, millisecond) + 1
- end.
-
--endif. %% ! defined SERVER_SIDE_ERPC_IS_MANDATORY
-
%% Send Msg to Name on all nodes, and collect the answers.
%% Return {Replies, Badnodes} where Badnodes is a list of the nodes
%% that failed during the timespan of the call.
@@ -1081,18 +751,10 @@ rec_nodes(Name, [{N,R} | Tail], Badnodes, Replies) ->
end.
%% Now for an asynchronous rpc.
-%% An asyncronous version of rpc that is faster for series of
+%% An asynchronous version of rpc that is faster for series of
%% rpc's towards the same node. I.e. it returns immediately and
%% it returns a Key that can be used in a subsequent yield(Key).
--ifdef(SERVER_SIDE_ERPC_IS_MANDATORY).
-
-%%
-%% Use this more efficient implementation of async_call()
-%% when 'erpc' support can be made mandatory for server
-%% side.
-%%
-
-opaque key() :: erpc:request_id().
-spec async_call(Node, Module, Function, Args) -> Key when
@@ -1124,17 +786,16 @@ yield(Key) ->
Val :: (Res :: term()) | {badrpc, Reason :: term()}.
nb_yield(Key, Tmo) ->
- case ?RPCIFY(erpc:wait_response(Key, Tmo)) of
+ try erpc:wait_response(Key, Tmo) of
no_response ->
timeout;
{response, {'EXIT', _} = BadRpc} ->
- %% RPCIFY() cannot handle this case...
{value, {badrpc, BadRpc}};
{response, R} ->
- {value, R};
- BadRpc ->
- %% An exception converted by RPCIFY()...
- {value, BadRpc}
+ {value, R}
+ catch
+ Class:Reason ->
+ {value, rpcify_exception(Class, Reason)}
end.
-spec nb_yield(Key) -> {value, Val} | timeout when
@@ -1144,78 +805,6 @@ nb_yield(Key, Tmo) ->
nb_yield(Key) ->
nb_yield(Key, 0).
--else. %% ! defined SERVER_SIDE_ERPC_IS_MANDATORY
-
-%%
-%% Currently used implementation for async_call(). When
-%% 'erpc' support can be required for server side,
-%% replace with the implementation above...
-%%
-
--opaque key() :: {pid(), reference()}.
-
--spec async_call(Node, Module, Function, Args) -> Key when
- Node :: node(),
- Module :: module(),
- Function :: atom(),
- Args :: [term()],
- Key :: key().
-
-async_call(Node, Mod, Fun, Args) ->
- try
- true = is_atom(Node),
- true = is_atom(Mod),
- true = is_atom(Fun),
- true = is_integer(length(Args))
- catch
- _:_ ->
- error(badarg)
- end,
- Caller = self(),
- spawn_monitor(fun() ->
- process_flag(trap_exit, true),
- R = call(Node, Mod, Fun, Args),
- exit({async_call_result, Caller, R})
- end).
-
--spec yield(Key) -> Res | {badrpc, Reason} when
- Key :: key(),
- Res :: term(),
- Reason :: term().
-
-yield({Pid, Ref} = Key) when is_pid(Pid),
- is_reference(Ref) ->
- {value,R} = nb_yield(Key, infinity),
- R.
-
--spec nb_yield(Key) -> {value, Val} | timeout when
- Key :: key(),
- Val :: (Res :: term()) | {badrpc, Reason :: term()}.
-
-nb_yield({Pid, Ref} = Key) when is_pid(Pid),
- is_reference(Ref) ->
- nb_yield(Key, 0).
-
--spec nb_yield(Key, Timeout) -> {value, Val} | timeout when
- Key :: key(),
- Timeout :: ?TIMEOUT_TYPE,
- Val :: (Res :: term()) | {badrpc, Reason :: term()}.
-
-nb_yield({Proxy, Mon}, Tmo) when is_pid(Proxy),
- is_reference(Mon),
- ?IS_VALID_TMO(Tmo) ->
- Me = self(),
- receive
- {'DOWN', Mon, process, Proxy, {async_call_result, Me, R}} ->
- {value,R};
- {'DOWN', Mon, process, Proxy, Reason} ->
- {value, {badrpc, {'EXIT', Reason}}}
- after Tmo ->
- timeout
- end.
-
--endif. %% ! defined SERVER_SIDE_ERPC_IS_MANDATORY
-
%% A parallel network evaluator
%% ArgL === [{M,F,Args},........]
%% Returns a lists of the evaluations in the same order as
@@ -1315,7 +904,7 @@ cnode_call_group_leader_loop(State) ->
From ! {io_reply, ReplyAs, Reply},
cnode_call_group_leader_loop(NewState);
{stop, StopRequesterPid, Ref, To, Reply} ->
- gen_server:reply(To, Reply),
+ reply(To, Reply),
StopRequesterPid ! Ref,
ok;
_Unknown ->
diff --git a/lib/kernel/src/socket.erl b/lib/kernel/src/socket.erl
index c188f516a1..ccacb84293 100644
--- a/lib/kernel/src/socket.erl
+++ b/lib/kernel/src/socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -104,6 +104,8 @@
sockaddr_in6/0,
sockaddr_un/0,
sockaddr_ll/0,
+ sockaddr_dl/0,
+ sockaddr_unspec/0,
sockaddr_native/0,
msg_flag/0,
@@ -317,6 +319,13 @@
outgoing | loopback | user | kernel | fastroute |
non_neg_integer().
+-type hatype() :: netrom | eether | ether | ax25 | pronet | chaos |
+ ieee802 | arcnet | appletlk | dlci | atm | metricom |
+ ieee1394 | eui64 | infiniband |
+ tunnel | tunnel6 | loopback | localtlk |
+ none | void |
+ non_neg_integer().
+
-type sockaddr_un() ::
#{family := 'local',
path := binary() | string()}.
@@ -336,8 +345,16 @@
protocol := non_neg_integer(),
ifindex := integer(),
pkttype := packet_type(),
- hatype := non_neg_integer(),
+ hatype := hatype(),
addr := binary()}.
+-type sockaddr_dl() ::
+ #{family := 'link',
+ index := non_neg_integer(),
+ type := non_neg_integer(),
+ nlen := non_neg_integer(),
+ alen := non_neg_integer(),
+ slen := non_neg_integer(),
+ data := binary()}.
-type sockaddr_unspec() ::
#{family := 'unspec', addr := binary()}.
-type sockaddr_native() ::
@@ -347,6 +364,7 @@
sockaddr_in6() |
sockaddr_un() |
sockaddr_ll() |
+ sockaddr_dl() |
sockaddr_unspec() |
sockaddr_native().
@@ -619,7 +637,7 @@
%% Even if we are able to decode both level and type, we may not be
%% able to decode the data. The data is always delivered as a binary()
%% and a decoded value is delivered in the 'value' field, if decoding
-%% is succesful.
+%% is successful.
-type cmsg() :: cmsg_recv() | cmsg_send().
@@ -806,7 +824,7 @@ number_of() ->
%% *** which_sockets/0,1 ***
%%
%% Interface function to the socket registry
-%% Returns a list of all the sockets, accoring to the filter rule.
+%% Returns a list of all the sockets, according to the filter rule.
%%
-spec which_sockets() -> [socket()].
@@ -976,7 +994,7 @@ use_registry(D) when is_boolean(D) ->
%%
%% This produces a list of "all" the sockets, and some info about each one.
%% This function is intended as a utility and debug function.
-%% The sockets can be selected from domain, type or porotocol.
+%% The sockets can be selected from domain, type or protocol.
%% The sockets are not sorted.
%%
%% ===========================================================================
@@ -1206,8 +1224,18 @@ fmt_port(N, Proto) ->
-spec info() -> info().
%%
info() ->
- prim_socket:info().
-
+ try
+ prim_socket:info()
+ catch error:undef:ST ->
+ case ST of
+ %% We rewrite errors coming from prim_socket not existing
+ %% to enotsup.
+ [{prim_socket,info,[],_}|_] ->
+ erlang:raise(error,notsup,ST);
+ _ ->
+ erlang:raise(error,undef,ST)
+ end
+ end.
-spec info(Socket) -> socket_info() when
Socket :: socket().
@@ -1277,7 +1305,7 @@ cancel_monitor(MRef) ->
%%
%% supports - get information about what the platform "supports".
%%
-%% Generates a list of various info about what the plaform can support.
+%% Generates a list of various info about what the platform can support.
%% The most obvious case is 'options'.
%%
%% Each item in a 'supports'-list will appear only *one* time.
@@ -1338,7 +1366,7 @@ is_supported(options, Level, Opt) when is_atom(Level), is_atom(Opt) ->
%% The nif sets up a monitor to this process, and if it dies the socket
%% is closed. It is also used if someone wants to monitor the socket.
%%
-%% We may therefor need monitor function(s):
+%% We may therefore need monitor function(s):
%%
%% socket:monitor(Socket)
%% socket:demonitor(Socket)
@@ -3945,7 +3973,7 @@ setopt_native(Socket, SocketOption, Value) ->
%% If its an "invalid" option, we should not crash but return some
%% useful error...
%%
-%% When specifying level as an integer, and therefor using "native mode",
+%% When specifying level as an integer, and therefore using "native mode",
%% we should make it possible to specify common types instead of the
%% value size. Example: int | bool | {string, pos_integer()} | non_neg_integer()
%%
diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile
index 62909d324d..f7776f44fe 100644
--- a/lib/kernel/test/Makefile
+++ b/lib/kernel/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -70,7 +70,6 @@ MODULES= \
erl_prim_loader_SUITE \
erl_uds_dist \
error_handler_SUITE \
- error_info_lib \
error_logger_SUITE \
error_logger_warn_SUITE \
file_SUITE \
@@ -113,7 +112,6 @@ MODULES= \
cleanup \
ignore_cores \
zlib_SUITE \
- loose_node \
sendfile_SUITE \
standard_error_SUITE \
multi_load_SUITE \
@@ -132,13 +130,21 @@ APP_FILES = \
topApp2.app \
topApp3.app
-ERL_FILES= $(MODULES:%=%.erl) code_a_test.erl
+SASL_MODULES= otp_vsns
+STDLIB_MODULES= error_info_lib
+
+ERL_FILES= $(MODULES:%=%.erl) code_a_test.erl \
+ $(SASL_MODULES:%=$(ERL_TOP)/lib/sasl/test/%.erl) \
+ $(STDLIB_MODULES:%=$(ERL_TOP)/lib/stdlib/test/%.erl)
+
HRL_FILES= \
kernel_test_lib.hrl \
socket_test_evaluator.hrl \
socket_test_ttest.hrl \
socket_test_ttest_client.hrl
+EXTRA_FILES= $(ERL_TOP)/otp_versions.table
+
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
INSTALL_PROGS= $(TARGET_FILES)
@@ -156,6 +162,7 @@ RELSYSDIR = $(RELEASE_PATH)/kernel_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -176,10 +183,11 @@ erl_uds_dist.erl: ../examples/erl_uds_dist/src/erl_uds_dist.erl
make_emakefile: $(ERL_FILES)
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
> $(EMAKEFILE)
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
+ $(MODULES) $(SASL_MODULES) $(STDLIB_MODULES) \
>> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
@@ -203,11 +211,12 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(APP_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(APP_FILES) $(EXTRA_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) \
kernel.spec kernel_smoke.spec kernel_bench.spec logger.spec \
$(EMAKEFILE) $(COVERFILE) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ $(INSTALL_DATA) $(ERL_TOP)/make/otp_version_tickets "$(RELSYSDIR)/kernel_SUITE_data"
release_docs_spec:
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl
index 3584b90378..0668c28692 100644
--- a/lib/kernel/test/application_SUITE.erl
+++ b/lib/kernel/test/application_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -225,7 +225,7 @@ failover(Conf) when is_list(Conf) ->
%%-----------------------------------------------------------------
%% Tests failover and takeover for distributed applications. Tests
%% start, load etc implicitly. The applications do not use start_phases
-%% i.e. the failover should be transfered to normal start type.
+%% i.e. the failover should be transferred to normal start type.
failover_comp(Conf) when is_list(Conf) ->
%% start a help process to check the start type
StPid = spawn_link(?MODULE, start_type, []),
@@ -371,7 +371,7 @@ permissions(Conf) when is_list(Conf) ->
false = is_started(app1, Cp3),
true = is_started(app1, Cp2),
- %% Start app3, make sure noone starts it
+ %% Start app3, make sure no one starts it
{[ok,ok,ok],[]} =
rpc:multicall(Cps, application, load, [app3()]),
?UNTIL(is_loaded(app3, Cps)),
@@ -744,7 +744,7 @@ permit_false_start_local(Conf) when is_list(Conf) ->
true = is_started(app1, Cp2),
false = is_started(app1, Cp3),
- %% Unpermit it agin
+ %% Unpermit it again
ok = rpc:call(Cp1, application, permit, [app1, false]),
ct:sleep(1000),
false = is_started(app1, Cp1),
@@ -1225,7 +1225,7 @@ otp_2718(Conf) when is_list(Conf) ->
%% Ticket: OTP-2973
%% Slogan: application:start does not test if an appl is already starting...
%%-----------------------------------------------------------------
-%% Test of two processes simultanously starting the same application.
+%% Test of two processes simultaneously starting the same application.
otp_2973(Conf) when is_list(Conf) ->
%% Write a .app file
{ok, Fd} = file:open("app0.app", [write]),
@@ -2188,10 +2188,9 @@ do_configfd_test_bash() ->
"3> /dev/null ")),
%% Check that file descriptor with a huge amount of data fails
case application:start(os_mon) of
- ok -> case proplists:get_value(system_total_memory,
- memsup:get_system_memory_data()) of
+ ok -> case total_memory() of
Memory when is_integer(Memory),
- Memory > 16*1024*1024*1024 ->
+ Memory > 16 ->
application:stop(os_mon),
true =
("magic42" =/=
@@ -2210,6 +2209,22 @@ do_configfd_test_bash() ->
end,
ok.
+total_memory() ->
+ %% Total memory in GB.
+ try
+ SMD = memsup:get_system_memory_data(),
+ TM = proplists:get_value(
+ available_memory, SMD,
+ proplists:get_value(
+ total_memory, SMD,
+ proplists:get_value(
+ system_total_memory, SMD))),
+ TM div (1024*1024*1024)
+ catch
+ _ : _ ->
+ undefined
+ end.
+
%% Test that one can get configuration from file descriptor with the
%% -configfd option
configfd_bash(Conf) when is_list(Conf) ->
diff --git a/lib/kernel/test/bif_SUITE.erl b/lib/kernel/test/bif_SUITE.erl
index 2369dd8b71..14ab4519a1 100644
--- a/lib/kernel/test/bif_SUITE.erl
+++ b/lib/kernel/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@ spawn1(Config) when is_list(Config) ->
%% Test spawn/2.
spawn2(Config) when is_list(Config) ->
- {ok, Node} = start_node(spawn2),
+ {ok, Peer, Node} = ?CT_PEER(),
Parent = self(),
{_, _, FA, _} = fetch_proc_vals(self()),
@@ -105,7 +105,7 @@ spawn2(Config) when is_list(Config) ->
check_proc_vals(false, normal, FA, 0, PV)
end,
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
@@ -131,7 +131,7 @@ spawn3(Config) when is_list(Config) ->
%% Test spawn/4.
spawn4(Config) when is_list(Config) ->
- {ok, Node} = start_node(spawn4),
+ {ok, Peer, Node} = ?CT_PEER(),
Parent = self(),
{_, _, FA, _} = fetch_proc_vals(self()),
@@ -149,7 +149,7 @@ spawn4(Config) when is_list(Config) ->
check_proc_vals(false, normal, FA, 0, PV)
end,
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
@@ -171,7 +171,7 @@ spawn_link1(Config) when is_list(Config) ->
%% Test spawn_link/2.
spawn_link2(Config) when is_list(Config) ->
- {ok, Node} = start_node(spawn_link2),
+ {ok, Peer, Node} = ?CT_PEER(),
Parent = self(),
{_, _, FA, _} = fetch_proc_vals(self()),
@@ -185,7 +185,7 @@ spawn_link2(Config) when is_list(Config) ->
check_proc_vals(true, normal, FA, 0, PV)
end,
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
%% Test spawn_link/3.
@@ -210,7 +210,7 @@ spawn_link3(Config) when is_list(Config) ->
%% Test spawn_link/4.
spawn_link4(Config) when is_list(Config) ->
- {ok, Node} = start_node(spawn_link4),
+ {ok, Peer, Node} = ?CT_PEER(),
Parent = self(),
{_, _, FA, _} = fetch_proc_vals(self()),
@@ -228,7 +228,7 @@ spawn_link4(Config) when is_list(Config) ->
check_proc_vals(true, normal, FA, 0, PV)
end,
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
@@ -259,7 +259,7 @@ spawn_opt2(Config) when is_list(Config) ->
%% Test spawn_opt/3.
spawn_opt3(Config) when is_list(Config) ->
- {ok, Node} = start_node(spawn_opt3),
+ {ok, Peer, Node} = ?CT_PEER(),
Parent = self(),
{_, _, FA, _} = fetch_proc_vals(self()),
P1 = spawn_opt(Node,
@@ -281,7 +281,7 @@ spawn_opt3(Config) when is_list(Config) ->
Node = node(P2),
check_proc_vals(false, normal, FA, 10, PV2)
end,
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
%% Test spawn_opt/4.
@@ -316,7 +316,7 @@ spawn_opt4(Config) when is_list(Config) ->
%% Test spawn_opt/5.
spawn_opt5(Config) when is_list(Config) ->
- {ok, Node} = start_node(spawn_opt5),
+ {ok, Peer, Node} = ?CT_PEER(),
Parent = self(),
{_, _, FA, _} = fetch_proc_vals(self()),
P1 = spawn_opt(Node,
@@ -344,13 +344,13 @@ spawn_opt5(Config) when is_list(Config) ->
Node = node(P2),
check_proc_vals(false, normal, FA, 10, PV2)
end,
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
%% Test failure behavior of spawn bifs.
spawn_failures(Config) when is_list(Config) ->
ThisNode = node(),
- {ok, Node} = start_node(spawn_remote_failure),
+ {ok, Peer, Node} = ?CT_PEER(),
%% unknown nodes
io:format("Testing unknown nodes~n", []),
@@ -466,7 +466,7 @@ spawn_failures(Config) when is_list(Config) ->
{'EXIT', {badarg, _}} = (catch spawn_opt(erlang,nodes,[],[a|b])),
- true = stop_node(Node),
+ peer:stop(Peer),
ok.
check_proc_vals(Link, Priority, FullsweepAfter, MinHeapSize, {Ls, P, FA, HS}) ->
@@ -518,15 +518,7 @@ wilderness(Config) when is_list(Config) ->
run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) ->
Self = self(),
Ref = make_ref(),
- SuiteDir = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(allocator_test,
- slave,
- [{args,
- " -pa "
- ++ SuiteDir
- ++" +MYtt "++to_string(Set_tt)
- ++" +MYtp "++to_string(Set_tp)},
- {linked, false}]),
+ {ok, Peer, Node} = ?CT_PEER(["+MYtt", to_string(Set_tt), "+MYtp", to_string(Set_tp)]),
spawn(Node, fun () ->
Self ! {Ref, erlang:system_info(allocator)}
end),
@@ -541,7 +533,7 @@ run_wilderness_test({Set_tt, Set_tp}, {Exp_tt, Exp_tp}) ->
{value, {tt, Ett}} = lists:keysearch(tt, 1, SA_Opts),
{value, {tp, Etp}} = lists:keysearch(tp, 1, SA_Opts)
end,
- stop_node(Node).
+ peer:stop(Peer).
to_string(X) when is_integer(X) ->
integer_to_list(X);
@@ -550,30 +542,5 @@ to_string(X) when is_atom(X) ->
to_string(X) when is_list(X) ->
X.
-get_nodenames(N, T) ->
- get_nodenames(N, T, []).
-
-get_nodenames(0, _, Acc) ->
- Acc;
-get_nodenames(N, T, Acc) ->
- {A, B, C} = now(),
- get_nodenames(N-1, T, [list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(T)
- ++ "-"
- ++ integer_to_list(A)
- ++ "-"
- ++ integer_to_list(B)
- ++ "-"
- ++ integer_to_list(C)) | Acc]).
-
-start_node(TestCase) ->
- [Name] = get_nodenames(1, TestCase),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
-
-stop_node(Node) ->
- true = test_server:stop_node(Node).
-
run_fun(Fun) ->
Fun().
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index a6dd3b3f54..7059d477d9 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -303,7 +303,7 @@ replace_path(Config) when is_list(Config) ->
true = code:set_path(P), %Reset path
ok = file:del_dir("./kernel-2.11"),
- %% Add a completly new application.
+ %% Add a completely new application.
NewAppName = 'blurf_blarfer',
NewAppDir = filename:join(Cwd, atom_to_list(NewAppName) ++ "-6.33.1"),
@@ -657,8 +657,7 @@ set_path_file(Config) when is_list(Config) ->
%% 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) ->
- Pa = filename:dirname(code:which(?MODULE)),
- {ok,Node} = test_server:start_node(sticky_dir, slave, [{args,"-pa "++Pa}]),
+ {ok, Peer, Node} = ?CT_PEER(),
Mods = [code,lists,erlang,init],
OutDir = filename:join(proplists:get_value(priv_dir, Config), sticky_dir),
_ = file:make_dir(OutDir),
@@ -671,7 +670,7 @@ sticky_dir(Config) when is_list(Config) ->
io:format("~p\n", [Other]),
ct:fail(failed)
end,
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
sticky_compiler(Files, PrivDir) ->
@@ -709,22 +708,17 @@ pa_pz_option(Config) when is_list(Config) ->
DDir = proplists:get_value(data_dir,Config),
PaDir = filename:join(DDir,"pa"),
PzDir = filename:join(DDir,"pz"),
- {ok, Node}=test_server:start_node(pa_pz1, slave,
- [{args,
- "-pa " ++ PaDir
- ++ " -pz " ++ PzDir}]),
+ {ok, Peer, Node} = ?CT_PEER(["-pa", PaDir, "-pz", PzDir]),
Ret=rpc:call(Node, code, get_path, []),
[PaDir|Paths] = Ret,
[PzDir|_] = lists:reverse(Paths),
- test_server:stop_node(Node),
- {ok, Node2}=test_server:start_node(pa_pz2, slave,
- [{args,
- "-mode embedded " ++ "-pa "
- ++ PaDir ++ " -pz " ++ PzDir}]),
+ peer:stop(Peer),
+ {ok, Peer2, Node2} = ?CT_PEER(["-mode", "embedded", "-pa",
+ PaDir, "-pz", PzDir]),
Ret2=rpc:call(Node2, code, get_path, []),
[PaDir|Paths2] = Ret2,
[PzDir|_] = lists:reverse(Paths2),
- test_server:stop_node(Node2).
+ peer:stop(Peer2).
%% add_path, del_path should not cause priv_dir(App) to fail.
add_del_path(Config) when is_list(Config) ->
@@ -776,7 +770,7 @@ clash(Config) when is_list(Config) ->
true = code:add_path(TmpEzFile++"/foobar-0.1/ebin"),
case os:type() of
{win32,_} ->
- %% The file wont be deleted on windows until it's closed, why we
+ %% The file won't be deleted on windows until it's closed, why we
%% need to rename instead.
ok = file:rename(TmpEzFile,TmpEzFile++".moved");
_ ->
@@ -878,13 +872,15 @@ check_funs({'$M_EXPR','$F_EXPR',_},
[{code_server,do_mod_call,4},
{code_server,handle_call,3}|_]) -> 0;
check_funs({'$M_EXPR','$F_EXPR',_},
- [{lists,flatmap,2},
+ [{lists,flatmap_1,2},
+ {lists,flatmap,2},
{lists,concat,1},
{code_server,load_abs,4},
{code_server,handle_call,3},
{code_server,loop,1}|_]) -> 0;
check_funs({'$M_EXPR','$F_EXPR',_},
- [{lists,foreach,2},
+ [{lists,foreach_1,2},
+ {lists,foreach,2},
{code_server,stick_dir,3},
{code_server,handle_call,3},
{code_server,loop,1}|_]) -> 0;
@@ -901,6 +897,19 @@ check_funs({'$M_EXPR','$F_EXPR',1},
{code_server,init,3},
{code_server,start_link,1}]) -> 0;
check_funs({'$M_EXPR','$F_EXPR',1},
+ [{lists,all_1,2},
+ {lists,all,2},
+ {code_server,is_numstr,1},
+ {code_server,is_vsn,1},
+ {code_server,vsn_to_num,1},
+ {code_server,create_bundle,2},
+ {code_server,choose_bundles,1},
+ {code_server,make_path,2},
+ {code_server,get_user_lib_dirs_1,1},
+ {code_server,get_user_lib_dirs,0},
+ {code_server,init,3},
+ {code_server,start_link,1}]) -> 0;
+check_funs({'$M_EXPR','$F_EXPR',1},
[{lists,filter,2},
{code_server,try_archive_subdirs,3}|_]) -> 0;
check_funs({'$M_EXPR','$F_EXPR',_},
@@ -991,16 +1000,16 @@ mult_lib_roots(Config) when is_list(Config) ->
mult_lib_compile(DataDir,
"my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
- %% Set up ERL_LIBS and start a slave node.
+ %% Set up ERL_LIBS and start a peer node.
ErlLibs = filename:join(DataDir, "first_root") ++ mult_lib_sep() ++
filename:join(DataDir, "second_root"),
- {ok,Node} =
- test_server:start_node(mult_lib_roots, slave,
- [{args,"-env ERL_LIBS "++ErlLibs}]),
+ {ok, Peer, Node} = ?CT_PEER(["-env", "ERL_LIBS", ErlLibs]),
Path0 = rpc:call(Node, code, get_path, []),
- ["."|Path1] = Path0,
+ %% ?CT_PEER adds extra path to this module folder
+ PathToSelf = filename:dirname(code:which(?MODULE)),
+ [PathToSelf, "."|Path1] = Path0,
[Kernel|Path2] = Path1,
[Stdlib|Path3] = Path2,
mult_lib_verify_lib(Kernel, "kernel"),
@@ -1018,6 +1027,7 @@ mult_lib_roots(Config) when is_list(Config) ->
io:format("~p\n", [Path]),
true = rpc:call(Node, code_SUITE_mult_root_module, works_fine, []),
+ peer:stop(Peer),
ok.
@@ -1050,16 +1060,13 @@ bad_erl_libs(Config) when is_list(Config) ->
false -> BadLibs0;
Libs -> BadLibs0 ++ ":" ++ Libs
end,
- {ok,Node} =
- test_server:start_node(bad_erl_libs, slave, []),
+ {ok, Peer, Node} = ?CT_PEER(),
Code = rpc:call(Node,code,get_path,[]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
- {ok,Node2} =
- test_server:start_node(bad_erl_libs, slave,
- [{args,"-env ERL_LIBS " ++ BadLibs}]),
- Code2 = rpc:call(Node,code,get_path,[]),
- test_server:stop_node(Node2),
+ {ok, Peer2, Node2} = ?CT_PEER(["-env", "ERL_LIBS", BadLibs]),
+ Code2 = rpc:call(Node2,code,get_path,[]),
+ peer:stop(Peer2),
%% Test that code path is not affected by the faulty ERL_LIBS
Code = Code2,
@@ -1117,10 +1124,8 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) ->
filelib:ensure_dir(OtherFile),
ok = file:write_file(OtherFile, OtherContents),
- %% Set up ERL_LIBS and start a slave node.
- {ok, Node} =
- test_server:start_node(code_archive, slave,
- [{args,"-env ERL_LIBS " ++ RootDir}]),
+ %% Set up ERL_LIBS and start a peer node.
+ {ok, Peer, Node} = ?CT_PEER(["-env", "ERL_LIBS", RootDir]),
CodePath = rpc:call(Node, code, get_path, []),
AppEbin = filename:join([Archive, Base, "ebin"]),
io:format("AppEbin: ~p\n", [AppEbin]),
@@ -1162,7 +1167,7 @@ do_code_archive(Config, Root, StripVsn) when is_list(Config) ->
error = rpc:call(Node, App, find, [Tab, Key]),
ok = rpc:call(Node, App, erase, [Tab]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
compile_app(TopDir, AppName) ->
@@ -1192,12 +1197,11 @@ compile_files([], _, _) ->
%% embeddedd system.
big_boot_embedded(Config) when is_list(Config) ->
{BootArg,AppsInBoot} = create_big_boot(Config),
- {ok, Node} =
- test_server:start_node(big_boot_embedded, slave,
- [{args,"-boot "++BootArg++" -mode embedded"}]),
+ {ok, Peer, Node} = ?CT_PEER(["-boot", BootArg, "-mode", "embedded"]),
RemoteNodeApps =
[ {X,Y} || {X,_,Y} <-
rpc:call(Node,application,loaded_applications,[]) ],
+ peer:stop(Peer),
true = lists:sort(AppsInBoot) =:= lists:sort(RemoteNodeApps),
ok.
@@ -1343,12 +1347,11 @@ on_load_embedded_1(Config) ->
true = code:del_path(OnLoadAppEbin),
%% Start the node and check that the on_load function was run.
- {ok,Node} = start_node(on_load_embedded,
- "-mode embedded -boot " ++ BootScript),
+ {ok, Peer, Node} = ?CT_PEER(["-mode", "embedded", "-boot", BootScript]),
ok = rpc:call(Node, on_load_embedded, status, []),
%% Clean up.
- stop_node(Node).
+ peer:stop(Peer).
del_link(LinkName) ->
case file:delete(LinkName) of
@@ -1824,23 +1827,23 @@ do_normalized_paths([]) ->
%% Make sure that the extra -mode flags are ignored
mult_embedded_flags(_Config) ->
- Modes = [{" -mode embedded", embedded},
- {" -mode interactive", interactive},
- {" -mode invalid", interactive}],
+ Modes = [{["-mode", "embedded"], embedded},
+ {["-mode", "interactive"], interactive},
+ {["-mode", "invalid"], interactive}],
[ begin
{ArgMode, ExpectedMode} = Mode,
- {ok, Node} = start_node(mode_test, ArgMode),
+ {ok, Peer, Node} = ?CT_PEER(ArgMode),
ExpectedMode = rpc:call(Node, code, get_mode, []),
- true = stop_node(Node)
+ peer:stop(Peer)
end || Mode <- Modes],
[ begin
{ArgIgnoredMode, _} = IgnoredMode,
{ArgRelevantMode, ExpectedMode} = RelevantMode,
- {ok, Node} = start_node(mode_test, ArgRelevantMode ++ ArgIgnoredMode),
+ {ok, Peer, Node} = ?CT_PEER(ArgRelevantMode ++ ArgIgnoredMode),
ExpectedMode = rpc:call(Node, code, get_mode, []),
- true = stop_node(Node)
+ peer:stop(Peer)
end || IgnoredMode <- Modes, RelevantMode <- Modes],
ok.
@@ -2035,9 +2038,3 @@ run_purge_test(Test, Config) ->
after
TestLowOSRL = erlang:system_flag(outstanding_system_requests_limit, OSRL)
end.
-
-start_node(Name, Param) ->
- test_server:start_node(Name, slave, [{args, Param}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl
index 1c3c2def53..6b9a6875f3 100644
--- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl
+++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl
@@ -11,59 +11,59 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) ->
Tracer = start_tracing(),
- ?line 1 = upgradee:exp1(),
- ?line 1 = upgradee:exp1exp2(),
- ?line 1 = upgradee:exp1loc2(),
+ 1 = upgradee:exp1(),
+ 1 = upgradee:exp1exp2(),
+ 1 = upgradee:exp1loc2(),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1exp2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1exp2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
P = spawn_link(upgradee,dispatch_loop,[]),
- ?line 1 = proxy_call(P, local, exp1),
- ?line 1 = proxy_call(P, local, loc1),
- ?line 1 = proxy_call(P, local, exp1exp2),
- ?line 1 = proxy_call(P, local, exp1loc2),
- ?line 1 = proxy_call(P, local, loc1exp2),
- ?line 1 = proxy_call(P, local, loc1loc2),
- ?line 1 = proxy_call(P, external, exp1),
- ?line 1 = proxy_call(P, external, exp1exp2),
- ?line 1 = proxy_call(P, external, exp1loc2),
-
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
- ?line {cannot_compile,1} = proxy_call(P, local, exp2),
- ?line {cannot_compile,1} = proxy_call(P, local, loc2),
-
- ?line {'EXIT',{undef,_}} = (catch other:exp1()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1()),
- ?line {'EXIT',{undef,_}} = (catch other:exp1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:exp1exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc11exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc2()),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
+ 1 = proxy_call(P, local, exp1),
+ 1 = proxy_call(P, local, loc1),
+ 1 = proxy_call(P, local, exp1exp2),
+ 1 = proxy_call(P, local, exp1loc2),
+ 1 = proxy_call(P, local, loc1exp2),
+ 1 = proxy_call(P, local, loc1loc2),
+ 1 = proxy_call(P, external, exp1),
+ 1 = proxy_call(P, external, exp1exp2),
+ 1 = proxy_call(P, external, exp1loc2),
+
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
+ {cannot_compile,1} = proxy_call(P, local, exp2),
+ {cannot_compile,1} = proxy_call(P, local, loc2),
+
+ {'EXIT',{undef,_}} = (catch other:exp1()),
+ {'EXIT',{undef,_}} = (catch other:loc1()),
+ {'EXIT',{undef,_}} = (catch other:exp1loc2()),
+ {'EXIT',{undef,_}} = (catch other:exp1exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc11exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch other:exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc2()),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
Env1 = "Env1",
put(loc1_fun, upgradee:get_local_fun(Env1)),
- ?line {1,Env1} = (get(loc1_fun))(),
+ {1,Env1} = (get(loc1_fun))(),
put(exp1exp2_fun, upgradee:get_exp1exp2_fun()),
- ?line 1 = (get(exp1exp2_fun))(),
+ 1 = (get(exp1exp2_fun))(),
ok = check_tracing(Tracer, 13),
@@ -71,23 +71,23 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) ->
%% Load version 1 of other
%%
code_SUITE:compile_load(other, Dir, 1, Other1),
- ?line 1 = other:exp1(),
- ?line 1 = other:exp1loc2(),
- ?line 1 = other:exp1exp2(),
- ?line {'EXIT',{undef,_}} = (catch other:loc1()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc2()),
-
- ?line 1 = proxy_call(P, other, exp1),
- ?line 1 = proxy_call(P, other, exp1loc2),
- ?line 1 = proxy_call(P, other, exp1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
+ 1 = other:exp1(),
+ 1 = other:exp1loc2(),
+ 1 = other:exp1exp2(),
+ {'EXIT',{undef,_}} = (catch other:loc1()),
+ {'EXIT',{undef,_}} = (catch other:loc1exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch other:exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc2()),
+
+ 1 = proxy_call(P, other, exp1),
+ 1 = proxy_call(P, other, exp1loc2),
+ 1 = proxy_call(P, other, exp1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
ok = check_tracing(Tracer, 5),
@@ -96,59 +96,59 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) ->
%%
code_SUITE:compile_load(upgradee, Dir, 2, Upgradee2),
- ?line 2 = upgradee:exp2(),
- ?line 2 = upgradee:exp1exp2(),
- ?line 2 = upgradee:loc1exp2(),
+ 2 = upgradee:exp2(),
+ 2 = upgradee:exp1exp2(),
+ 2 = upgradee:loc1exp2(),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()),
-
- ?line 1 = proxy_call(P, local, exp1),
- ?line 1 = proxy_call(P, local, loc1),
- ?line 1 = proxy_call(P, local, exp1exp2),
- ?line 1 = proxy_call(P, local, exp1loc2),
- ?line 1 = proxy_call(P, local, loc1exp2),
- ?line 1 = proxy_call(P, local, loc1loc2),
- ?line {cannot_compile,1} = proxy_call(P, local, exp2),
- ?line {cannot_compile,1} = proxy_call(P, local, loc2),
-
- ?line 2 = proxy_call(P, external, exp1exp2),
- ?line 2 = proxy_call(P, external, loc1exp2),
- ?line 2 = proxy_call(P, external, exp2),
-
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
-
- ?line 1 = other:exp1(),
- ?line 1 = other:exp1loc2(),
- ?line 1 = other:exp1exp2(),
- ?line {'EXIT',{undef,_}} = (catch other:loc1()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:exp2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc2()),
-
- ?line 1 = proxy_call(P, other, exp1),
- ?line 1 = proxy_call(P, other, exp1loc2),
- ?line 1 = proxy_call(P, other, exp1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
-
- ?line {1,Env1} = (get(loc1_fun))(),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc2()),
+
+ 1 = proxy_call(P, local, exp1),
+ 1 = proxy_call(P, local, loc1),
+ 1 = proxy_call(P, local, exp1exp2),
+ 1 = proxy_call(P, local, exp1loc2),
+ 1 = proxy_call(P, local, loc1exp2),
+ 1 = proxy_call(P, local, loc1loc2),
+ {cannot_compile,1} = proxy_call(P, local, exp2),
+ {cannot_compile,1} = proxy_call(P, local, loc2),
+
+ 2 = proxy_call(P, external, exp1exp2),
+ 2 = proxy_call(P, external, loc1exp2),
+ 2 = proxy_call(P, external, exp2),
+
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
+
+ 1 = other:exp1(),
+ 1 = other:exp1loc2(),
+ 1 = other:exp1exp2(),
+ {'EXIT',{undef,_}} = (catch other:loc1()),
+ {'EXIT',{undef,_}} = (catch other:loc1exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch other:exp2()),
+ {'EXIT',{undef,_}} = (catch other:loc2()),
+
+ 1 = proxy_call(P, other, exp1),
+ 1 = proxy_call(P, other, exp1loc2),
+ 1 = proxy_call(P, other, exp1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
+
+ {1,Env1} = (get(loc1_fun))(),
Env2 = "Env2",
put(loc2_fun, upgradee:get_local_fun(Env2)),
- ?line {2,Env2} = (get(loc2_fun))(),
+ {2,Env2} = (get(loc2_fun))(),
- ?line 2 = (get(exp1exp2_fun))(),
+ 2 = (get(exp1exp2_fun))(),
ok = check_tracing(Tracer, 10),
@@ -157,56 +157,56 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) ->
%%
code_SUITE:compile_load(other, Dir, 2, Other2),
- ?line 2 = upgradee:exp2(),
- ?line 2 = upgradee:exp1exp2(),
- ?line 2 = upgradee:loc1exp2(),
+ 2 = upgradee:exp2(),
+ 2 = upgradee:exp1exp2(),
+ 2 = upgradee:loc1exp2(),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()),
-
- ?line 1 = proxy_call(P, local, exp1),
- ?line 1 = proxy_call(P, local, loc1),
- ?line 1 = proxy_call(P, local, exp1exp2),
- ?line 1 = proxy_call(P, local, exp1loc2),
- ?line 1 = proxy_call(P, local, loc1exp2),
- ?line 1 = proxy_call(P, local, loc1loc2),
- ?line {cannot_compile,1} = proxy_call(P, local, exp2),
- ?line {cannot_compile,1} = proxy_call(P, local, loc2),
-
- ?line 2 = proxy_call(P, external, exp1exp2),
- ?line 2 = proxy_call(P, external, loc1exp2),
- ?line 2 = proxy_call(P, external, exp2),
-
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
-
- ?line 2 = other:exp2(),
- ?line 2 = other:loc1exp2(),
- ?line 2 = other:exp1exp2(),
- ?line {'EXIT',{undef,_}} = (catch other:exp1()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1()),
- ?line {'EXIT',{undef,_}} = (catch other:exp1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc2()),
-
- ?line 2 = proxy_call(P, other, exp2),
- ?line 2 = proxy_call(P, other, loc1exp2),
- ?line 2 = proxy_call(P, other, exp1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
-
- ?line {1,Env1} = (get(loc1_fun))(),
- ?line {2,Env2} = (get(loc2_fun))(),
- ?line 2 = (get(exp1exp2_fun))(),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc2()),
+
+ 1 = proxy_call(P, local, exp1),
+ 1 = proxy_call(P, local, loc1),
+ 1 = proxy_call(P, local, exp1exp2),
+ 1 = proxy_call(P, local, exp1loc2),
+ 1 = proxy_call(P, local, loc1exp2),
+ 1 = proxy_call(P, local, loc1loc2),
+ {cannot_compile,1} = proxy_call(P, local, exp2),
+ {cannot_compile,1} = proxy_call(P, local, loc2),
+
+ 2 = proxy_call(P, external, exp1exp2),
+ 2 = proxy_call(P, external, loc1exp2),
+ 2 = proxy_call(P, external, exp2),
+
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
+
+ 2 = other:exp2(),
+ 2 = other:loc1exp2(),
+ 2 = other:exp1exp2(),
+ {'EXIT',{undef,_}} = (catch other:exp1()),
+ {'EXIT',{undef,_}} = (catch other:loc1()),
+ {'EXIT',{undef,_}} = (catch other:exp1loc2()),
+ {'EXIT',{undef,_}} = (catch other:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch other:loc2()),
+
+ 2 = proxy_call(P, other, exp2),
+ 2 = proxy_call(P, other, loc1exp2),
+ 2 = proxy_call(P, other, exp1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
+
+ {1,Env1} = (get(loc1_fun))(),
+ {2,Env2} = (get(loc2_fun))(),
+ 2 = (get(exp1exp2_fun))(),
ok = check_tracing(Tracer, 10),
@@ -226,52 +226,52 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) ->
%%
code:delete(upgradee),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1exp2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1exp2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch upgradee:loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp2()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1exp2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1exp2()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1()),
+ {'EXIT',{undef,_}} = (catch upgradee:exp1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch upgradee:loc2()),
- ?line 2 = proxy_call(P, local, exp2),
- ?line 2 = proxy_call(P, local, loc2),
- ?line 2 = proxy_call(P, local, exp1exp2),
- ?line 2 = proxy_call(P, local, exp1loc2),
- ?line 2 = proxy_call(P, local, loc1exp2),
- ?line 2 = proxy_call(P, local, loc1loc2),
- ?line {cannot_compile,2} = proxy_call(P, local, exp1),
- ?line {cannot_compile,2} = proxy_call(P, local, loc1),
+ 2 = proxy_call(P, local, exp2),
+ 2 = proxy_call(P, local, loc2),
+ 2 = proxy_call(P, local, exp1exp2),
+ 2 = proxy_call(P, local, exp1loc2),
+ 2 = proxy_call(P, local, loc1exp2),
+ 2 = proxy_call(P, local, loc1loc2),
+ {cannot_compile,2} = proxy_call(P, local, exp1),
+ {cannot_compile,2} = proxy_call(P, local, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, external, exp1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, external, loc2),
- ?line 2 = other:exp2(),
- ?line 2 = other:loc1exp2(),
- ?line 2 = other:exp1exp2(),
- ?line {'EXIT',{undef,_}} = (catch other:exp1()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1()),
- ?line {'EXIT',{undef,_}} = (catch other:exp1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc1loc2()),
- ?line {'EXIT',{undef,_}} = (catch other:loc2()),
+ 2 = other:exp2(),
+ 2 = other:loc1exp2(),
+ 2 = other:exp1exp2(),
+ {'EXIT',{undef,_}} = (catch other:exp1()),
+ {'EXIT',{undef,_}} = (catch other:loc1()),
+ {'EXIT',{undef,_}} = (catch other:exp1loc2()),
+ {'EXIT',{undef,_}} = (catch other:loc1loc2()),
+ {'EXIT',{undef,_}} = (catch other:loc2()),
- ?line 2 = proxy_call(P, other, exp2),
- ?line 2 = proxy_call(P, other, loc1exp2),
- ?line 2 = proxy_call(P, other, exp1exp2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
- ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
-
- ?line {'EXIT',{undef,_}} = (catch (get(exp1exp2_fun))()),
+ 2 = proxy_call(P, other, exp2),
+ 2 = proxy_call(P, other, loc1exp2),
+ 2 = proxy_call(P, other, exp1exp2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1),
+ {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2),
+ {'EXIT',{undef,_}} = proxy_call(P, other, loc2),
+
+ {'EXIT',{undef,_}} = (catch (get(exp1exp2_fun))()),
ok = check_tracing(Tracer, 14),
@@ -300,9 +300,9 @@ proxy_call(Pid, CallType, Func) ->
start_tracing() ->
Self = self(),
{Tracer,_} = spawn_opt(fun() -> tracer_loop(Self) end, [link,monitor]),
- ?line 1 = erlang:trace_pattern({error_handler,undefined_function,3},
+ 1 = erlang:trace_pattern({error_handler,undefined_function,3},
true, [global]),
- ?line 1 = erlang:trace(Self, true, [call,{tracer,Tracer}]),
+ 1 = erlang:trace(Self, true, [call,{tracer,Tracer}]),
Tracer.
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 9dd008d978..2be791a571 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -120,14 +120,6 @@
open_change_size, change_attribute, otp_6278, otp_10131,
otp_16768, otp_16809]).
-%% These tests should be skipped if the VxWorks card is configured *with*
-%% nfs cache.
--define(SKIP_LARGE_CACHE,[inc_wrap_file, halt_ext, wrap_ext, read_mode,
- head, wrap_notif, open_size, error_log,
- error_index, chunk,
- change_size_before, change_size_during,
- change_size_after, default_size]).
-
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -1045,7 +1037,7 @@ m() ->
one_line("halt,int.inf. (10,1000)", W5, R5, Rep5, C5),
io:format("\n"),
io:format("\tWrap log time depends on how often the log wraps, as this\n"),
- io:format("\tinvolves opening of new files, which costs alot."),
+ io:format("\tinvolves opening of new files, which costs a lot."),
io:format("\n").
one_line(Txt, W, R, Rep, C) ->
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 40670e45d2..dc6f9072a2 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -21,6 +21,8 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/dist.hrl").
+-include_lib("stdlib/include/assert.hrl").
+-include_lib("kernel/include/file.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
@@ -34,6 +36,7 @@
setopts/1,
table_waste/1, net_setuptime/1,
inet_dist_options_options/1,
+ net_ticker_spawn_options/1,
monitor_nodes_nodedown_reason/1,
monitor_nodes_complex_nodedown_reason/1,
@@ -50,16 +53,19 @@
erl_uds_dist_smoke_test/1,
erl_1424/1, net_kernel_start/1, differing_cookies/1,
cmdline_setcookie_2/1, connection_cookie/1,
- dyn_differing_cookies/1]).
+ dyn_differing_cookies/1,
+ xdg_cookie/1]).
%% Performs the test at another node.
-export([get_socket_priorities/0,
+ get_net_ticker_fullsweep_option/1,
tick_cli_test/3, tick_cli_test1/3,
tick_serv_test/2, tick_serv_test1/1,
run_remote_test/1,
dyn_node_name_do/2,
epmd_reconnect_do/2,
setopts_do/2,
+ setopts_deadlock_test/2,
keep_conn/1, time_ping/1,
ddc_remote_run/2]).
@@ -97,6 +103,7 @@ all() ->
epmd_reconnect,
hidden_node, setopts,
table_waste, net_setuptime, inet_dist_options_options,
+ net_ticker_spawn_options,
{group, monitor_nodes},
erl_uds_dist_smoke_test,
erl_1424, net_kernel_start,
@@ -115,7 +122,8 @@ groups() ->
[differing_cookies,
cmdline_setcookie_2,
connection_cookie,
- dyn_differing_cookies]}].
+ dyn_differing_cookies,
+ xdg_cookie]}].
init_per_suite(Config) ->
start_gen_tcp_dist_test_type_server(),
@@ -213,14 +221,14 @@ tick_test(DCfg, _Config, CheckIntensityArg) ->
"-kernel net_ticktime 100 -connect_all false"),
rpc:call(ServNode, erl_distribution_SUITE, tick_serv_test, [Node, node()]),
- %% We set min/max half a second lower/higher than expected since it
- %% takes time for termination dist controller, delivery of messages
- %% scheduling of process receiving nodedown, etc...
+ %% We set min/max a second lower/higher than expected since it takes
+ %% time for termination of the dist controller, delivery of messages,
+ %% scheduling of the process receiving nodedown, etc...
{IArg, Min, Max} = case CheckIntensityArg of
false ->
- {"", 7500, 16500};
+ {"", 7000, 17000};
true ->
- {" -kernel net_tickintensity 24", 11000, 13000}
+ {" -kernel net_tickintensity 24", 10500, 13500}
end,
{ok, Node} = start_node(DCfg, Name1,
@@ -334,14 +342,14 @@ illegal(Name) ->
test_node(Name) ->
test_node(Name, false).
-test_node(Name, Illigal) ->
- test_node(Name, Illigal, "").
-test_node(Name, Illigal, ExtraArgs) ->
+test_node(Name, Illegal) ->
+ test_node(Name, Illegal, "").
+test_node(Name, Illegal, ExtraArgs) ->
ProgName = ct:get_progname(),
Command = ProgName ++ " -noinput " ++
long_or_short() ++ Name ++ ExtraArgs ++
" -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++
- case Illigal of
+ case Illegal of
true ->
" -eval \"timer:sleep(10000),init:stop().\"";
false ->
@@ -570,54 +578,84 @@ wait_for_names(Names, N, Wait) when N > 0 ->
dyn_node_name(Config) when is_list(Config) ->
- %%run_dist_configs(fun dyn_node_name/2, Config).
- dyn_node_name("", Config).
+ run_dist_configs(fun dyn_node_name/2, Config).
dyn_node_name(DCfg, _Config) ->
- {_N1F,Port1} = start_node_unconnected(DCfg ++ " -dist_listen false",
+ NameDomain = case net_kernel:get_state() of
+ #{name_domain := shortnames} -> "shortnames";
+ #{name_domain := longnames} -> "longnames"
+ end,
+ {_N1F,Port1} = start_node_unconnected(DCfg,
undefined, ?MODULE, run_remote_test,
- ["dyn_node_name_do", atom_to_list(node())]),
+ ["dyn_node_name_do", atom_to_list(node()),
+ NameDomain]),
0 = wait_for_port_exit(Port1),
ok.
-dyn_node_name_do(TestNode, _Args) ->
+dyn_node_name_do(TestNode, [NameDomainStr]) ->
nonode@nohost = node(),
[] = nodes(),
[] = nodes(hidden),
+ NameDomain = list_to_atom(NameDomainStr),
+ #{started := static, name_type := dynamic, name := undefined,
+ name_domain := NameDomain} = net_kernel:get_state(),
net_kernel:monitor_nodes(true, [{node_type,all}]),
net_kernel:connect_node(TestNode),
[] = nodes(),
[TestNode] = nodes(hidden),
MyName = node(),
+ false = (MyName =:= undefined),
+ false = (MyName =:= nonode@nohost),
+ #{started := static, name_type := dynamic, name := MyName,
+ name_domain := NameDomain} = net_kernel:get_state(),
check([MyName], rpc:call(TestNode, erlang, nodes, [hidden])),
- {nodeup, MyName, [{node_type, visible}]} = receive_any(0),
- {nodeup, TestNode, [{node_type, hidden}]} = receive_any(0),
+ {nodeup, MyName, [{node_type, visible}]} = receive_any(),
+ {nodeup, TestNode, [{node_type, hidden}]} = receive_any(),
true = net_kernel:disconnect(TestNode),
- {nodedown, TestNode, [{node_type, hidden}]} = receive_any(0),
- [] = nodes(hidden),
- {nodedown, MyName, [{node_type, visible}]} = receive_any(1000),
+ %% We don't know the order of these nodedown messages. Often
+ %% nodedown from the connection comes first, but not always...
+
+ NodedownMsgsA = lists:sort([{nodedown, TestNode, [{node_type, hidden}]},
+ {nodedown, MyName, [{node_type, visible}]}]),
+ NodedownMsgA1 = receive_any(),
+ NodedownMsgA2 = receive_any(),
+ NodedownMsgsA = lists:sort([NodedownMsgA1, NodedownMsgA2]),
+ [] = nodes(hidden),
nonode@nohost = node(),
+ #{started := static, name_type := dynamic, name := undefined,
+ name_domain := NameDomain} = net_kernel:get_state(),
net_kernel:connect_node(TestNode),
[] = nodes(),
[TestNode] = nodes(hidden),
MyName = node(),
+ #{started := static, name_type := dynamic, name := MyName,
+ name_domain := NameDomain} = net_kernel:get_state(),
+
check([MyName], rpc:call(TestNode, erlang, nodes, [hidden])),
- {nodeup, MyName, [{node_type, visible}]} = receive_any(0),
- {nodeup, TestNode, [{node_type, hidden}]} = receive_any(0),
+ {nodeup, MyName, [{node_type, visible}]} = receive_any(),
+ {nodeup, TestNode, [{node_type, hidden}]} = receive_any(),
true = rpc:cast(TestNode, net_kernel, disconnect, [MyName]),
- {nodedown, TestNode, [{node_type, hidden}]} = receive_any(1000),
+ %% We don't know the order of these nodedown messages. Often
+ %% nodedown from the connection comes first, but not always...
+
+ NodedownMsgsB = lists:sort([{nodedown, TestNode, [{node_type, hidden}]},
+ {nodedown, MyName, [{node_type, visible}]}]),
+ NodedownMsgB1 = receive_any(),
+ NodedownMsgB2 = receive_any(),
+ NodedownMsgsB = lists:sort([NodedownMsgB1, NodedownMsgB2]),
+
[] = nodes(hidden),
- {nodedown, MyName, [{node_type, visible}]} = receive_any(1000),
nonode@nohost = node(),
-
+ #{started := static, name_type := dynamic, name := undefined,
+ name_domain := NameDomain} = net_kernel:get_state(),
ok.
check(X, X) -> ok.
@@ -627,7 +665,7 @@ setopts(Config) when is_list(Config) ->
setopts(DCfg, _Config) ->
register(setopts_regname, self()),
- [N1,N2,N3,N4] = get_nodenames(4, setopts),
+ [N1,N2,N3,N4,N5] = get_nodenames(5, setopts),
{_N1F,Port1} = start_node_unconnected(DCfg, N1, ?MODULE, run_remote_test,
["setopts_do", atom_to_list(node()), "1", "ping"]),
@@ -652,6 +690,32 @@ setopts(DCfg, _Config) ->
wait_and_connect(LSock, N4F, Port4),
0 = wait_for_port_exit(Port4),
+ %% net_kernel:setopts(new, _) used to be able to produce a deadlock
+ %% in net_kernel. GH-6129/OTP-18198
+ {N5F,Port5} = start_node_unconnected(DCfg, N5, ?MODULE, run_remote_test,
+ ["setopts_deadlock_test", atom_to_list(node()),
+ integer_to_list(LTcpPort)]),
+ wait_and_connect(LSock, N5F, Port5),
+ repeat(fun () ->
+ receive after 10 -> ok end,
+ erlang:disconnect_node(N5F),
+ WD = spawn_link(fun () ->
+ receive after 2000 -> ok end,
+ exit({net_kernel_probably_deadlocked, N5F})
+ end),
+ pong = net_adm:ping(N5F),
+ unlink(WD),
+ exit(WD, kill),
+ false = is_process_alive(WD)
+ end,
+ 200),
+ try
+ erpc:call(N5F, erlang, halt, [])
+ catch
+ error:{erpc,noconnection} -> ok
+ end,
+ 0 = wait_for_port_exit(Port5),
+
unregister(setopts_regname),
ok.
@@ -740,6 +804,19 @@ setopts_do(TestNode, [OptNr, ConnectData]) ->
ok.
+setopts_deadlock_test(_TestNode, [TcpPort]) ->
+ {ok, Sock} = gen_tcp:connect("localhost", list_to_integer(TcpPort),
+ [{active,false},{packet,2}]),
+ ok = gen_tcp:send(Sock, "Connect please"),
+ {ok, "Connect done"} = gen_tcp:recv(Sock, 0),
+ gen_tcp:close(Sock),
+ setopts_new_loop().
+
+setopts_new_loop() ->
+ ok = net_kernel:setopts(new, [{nodelay, true}]),
+ receive after 10 -> ok end,
+ setopts_new_loop().
+
opt_from_nr("1") -> {nodelay, true};
opt_from_nr("2") -> {nodelay, false}.
@@ -978,8 +1055,14 @@ run_tick_change_test(DCfg, B, C, PrevTT, TT) ->
hidden_node(Config) when is_list(Config) ->
run_dist_configs(fun hidden_node/2, Config).
-hidden_node(DCfg, _Config) ->
- HArgs = "-hidden",
+hidden_node(DCfg, Config) ->
+ hidden_node(DCfg, "-hidden", Config),
+ hidden_node(DCfg, "-hidden -hidden", Config),
+ hidden_node(DCfg, "-hidden true -hidden true", Config),
+ ok.
+
+hidden_node(DCfg, HArgs, _Config) ->
+ ct:pal("--- Hidden argument(s): ~s~n", [HArgs]),
{ok, V} = start_node(DCfg, visible_node),
VMN = start_monitor_nodes_proc(V),
{ok, H} = start_node(DCfg, hidden_node, HArgs),
@@ -1121,6 +1204,75 @@ get_socket_priorities() ->
+%% check net_ticker_spawn_options
+net_ticker_spawn_options(Config) when is_list(Config) ->
+ run_dist_configs(fun net_ticker_spawn_options/2, Config).
+
+net_ticker_spawn_options(DCfg, Config) when is_list(Config) ->
+ FullsweepString0 = "[{fullsweep_after,0}]",
+ FullsweepString =
+ case os:cmd("echo [{a,1}]") of
+ "[{a,1}]"++_ ->
+ FullsweepString0;
+ _ ->
+ %% Some shells need quoting of [{}]
+ "'"++FullsweepString0++"'"
+ end,
+ InetDistOptions =
+ "-hidden "
+ "-kernel net_ticker_spawn_options "++FullsweepString,
+ {ok,Node1} =
+ start_node(DCfg, net_ticker_spawn_options_1, InetDistOptions),
+ {ok,Node2} =
+ start_node(DCfg, net_ticker_spawn_options_2, InetDistOptions),
+ %%
+ pong =
+ erpc:call(Node1, net_adm, ping, [Node2]),
+ FullsweepOptionNode1 =
+ erpc:call(Node1, ?MODULE, get_net_ticker_fullsweep_option, [Node2]),
+ FullsweepOptionNode2 =
+ erpc:call(Node2, ?MODULE, get_net_ticker_fullsweep_option, [Node1]),
+ io:format("FullsweepOptionNode1 = ~p", [FullsweepOptionNode1]),
+ io:format("FullsweepOptionNode2 = ~p", [FullsweepOptionNode2]),
+ 0 = FullsweepOptionNode1,
+ 0 = FullsweepOptionNode2,
+ %%
+ stop_node(Node2),
+ stop_node(Node1),
+ ok.
+
+get_net_ticker_fullsweep_option(Node) ->
+ Links = case proplists:get_value(Node, erlang:system_info(dist_ctrl)) of
+ DistCtrl when is_port(DistCtrl) ->
+ {links, Ls} = erlang:port_info(DistCtrl, links),
+ Ls;
+ DistCtrl when is_pid(DistCtrl) ->
+ {links, Ls} = process_info(DistCtrl, links),
+ Ls
+ end,
+ Ticker = try
+ lists:foreach(
+ fun (Pid) when is_pid(Pid) ->
+ {current_stacktrace, Stk}
+ = process_info(Pid, current_stacktrace),
+ lists:foreach(
+ fun ({dist_util, con_loop, _, _}) ->
+ throw(Pid);
+ (_) ->
+ ok
+ end, Stk);
+ (_) ->
+ ok
+ end, Links),
+ error(no_ticker_found)
+ catch
+ throw:Pid when is_pid(Pid) -> Pid
+ end,
+ {garbage_collection, GCOpts} = erlang:process_info(Ticker, garbage_collection),
+ proplists:get_value(fullsweep_after, GCOpts).
+
+
+
%%
%% Testcase:
%% monitor_nodes_nodedown_reason
@@ -1137,9 +1289,9 @@ monitor_nodes_nodedown_reason(DCfg, _Config) ->
Names = get_numbered_nodenames(5, node),
[NN1, NN2, NN3, NN4, NN5] = Names,
- {ok, N1} = start_node(DCfg, NN1),
- {ok, N2} = start_node(DCfg, NN2),
- {ok, N3} = start_node(DCfg, NN3),
+ {ok, N1} = start_node(DCfg, NN1, "-connect_all false"),
+ {ok, N2} = start_node(DCfg, NN2, "-connect_all false"),
+ {ok, N3} = start_node(DCfg, NN3, "-connect_all false"),
{ok, N4} = start_node(DCfg, NN4, "-hidden"),
receive {nodeup, N1} -> ok end,
@@ -1315,7 +1467,9 @@ monitor_nodes_misc(DCfg, _Config) ->
MonNodeState = monitor_node_state(),
ok = net_kernel:monitor_nodes(true),
ok = net_kernel:monitor_nodes(true, [{node_type, all}, nodedown_reason]),
- ok = net_kernel:monitor_nodes(true, [nodedown_reason, {node_type, all}]),
+ ok = net_kernel:monitor_nodes(true, [nodedown_reason, {node_type, all}, connection_id]),
+ ok = net_kernel:monitor_nodes(true, #{node_type => all, nodedown_reason => true}),
+ ok = net_kernel:monitor_nodes(true, #{node_type => all, nodedown_reason => true, connection_id => true}),
Names = get_numbered_nodenames(3, node),
[NN1, NN2, NN3] = Names,
@@ -1324,27 +1478,90 @@ monitor_nodes_misc(DCfg, _Config) ->
receive {nodeup, N1} -> ok end,
+ receive {nodeup, N1, #{node_type := visible}} -> ok end,
+ receive {nodeup, N2, #{node_type := hidden}} -> ok end,
receive {nodeup, N1, [{node_type, visible}]} -> ok end,
- receive {nodeup, N1, [{node_type, visible}]} -> ok end,
- receive {nodeup, N2, [{node_type, hidden}]} -> ok end,
receive {nodeup, N2, [{node_type, hidden}]} -> ok end,
+ NodesInfo = erlang:nodes(connected, #{connection_id => true}),
+
+ {N1, #{connection_id := N1CId}} = lists:keyfind(N1, 1, NodesInfo),
+ {N2, #{connection_id := N2CId}} = lists:keyfind(N2, 1, NodesInfo),
+
+ ct:pal("N1: ~p ~p~n", [N1, N1CId]),
+ ct:pal("N2: ~p ~p~n", [N2, N2CId]),
+
+ receive {nodeup, N1, #{node_type := visible, connection_id := N1CId}} -> ok end,
+ receive {nodeup, N2, #{node_type := hidden, connection_id := N2CId}} -> ok end,
+
+ N1UpInfoSorted = lists:sort([{node_type, visible},{connection_id, N1CId}]),
+ N2UpInfoSorted = lists:sort([{node_type, hidden},{connection_id, N2CId}]),
+
+ receive {nodeup, N1, UpN1Info} -> N1UpInfoSorted = lists:sort(UpN1Info) end,
+ receive {nodeup, N2, UpN2Info} -> N2UpInfoSorted = lists:sort(UpN2Info) end,
+
stop_node(N1),
stop_node(N2),
- VisbleDownInfo = lists:sort([{node_type, visible},
- {nodedown_reason, connection_closed}]),
- HiddenDownInfo = lists:sort([{node_type, hidden},
- {nodedown_reason, connection_closed}]),
-
receive {nodedown, N1} -> ok end,
- receive {nodedown, N1, Info1A} -> VisbleDownInfo = lists:sort(Info1A) end,
- receive {nodedown, N1, Info1B} -> VisbleDownInfo = lists:sort(Info1B) end,
- receive {nodedown, N2, Info2A} -> HiddenDownInfo = lists:sort(Info2A) end,
- receive {nodedown, N2, Info2B} -> HiddenDownInfo = lists:sort(Info2B) end,
+ receive {nodedown, N1, #{node_type := visible,
+ nodedown_reason := connection_closed}} -> ok end,
+ receive {nodedown, N1, #{node_type := visible,
+ nodedown_reason := connection_closed,
+ connection_id := N1CId}} -> ok end,
+ receive {nodedown, N2, #{node_type := hidden,
+ nodedown_reason := connection_closed}} -> ok end,
+ receive {nodedown, N2, #{node_type := hidden,
+ nodedown_reason := connection_closed,
+ connection_id := N2CId}} -> ok end,
+
+ N1ADownInfoSorted = lists:sort([{node_type, visible},
+ {nodedown_reason, connection_closed}]),
+ N1BDownInfoSorted = lists:sort([{node_type, visible},
+ {nodedown_reason, connection_closed},
+ {connection_id, N1CId}]),
+ N2ADownInfoSorted = lists:sort([{node_type, hidden},
+ {nodedown_reason, connection_closed}]),
+ N2BDownInfoSorted = lists:sort([{node_type, hidden},
+ {nodedown_reason, connection_closed},
+ {connection_id, N2CId}]),
+
+ receive
+ {nodedown, N1, N1Info1} ->
+ case lists:sort(N1Info1) of
+ N1ADownInfoSorted ->
+ receive
+ {nodedown, N1, N1Info2} ->
+ N1BDownInfoSorted = lists:sort(N1Info2)
+ end;
+ N1BDownInfoSorted ->
+ receive
+ {nodedown, N1, N1Info2} ->
+ N1ADownInfoSorted = lists:sort(N1Info2)
+ end
+ end
+ end,
+ receive
+ {nodedown, N2, N2Info1} ->
+ case lists:sort(N2Info1) of
+ N2ADownInfoSorted ->
+ receive
+ {nodedown, N2, N2Info2} ->
+ N2BDownInfoSorted = lists:sort(N2Info2)
+ end;
+ N2BDownInfoSorted ->
+ receive
+ {nodedown, N2, N2Info2} ->
+ N2ADownInfoSorted = lists:sort(N2Info2)
+ end
+ end
+ end,
ok = net_kernel:monitor_nodes(false, [{node_type, all}, nodedown_reason]),
+ ok = net_kernel:monitor_nodes(false, [nodedown_reason, {node_type, all}, connection_id]),
+ ok = net_kernel:monitor_nodes(false, #{node_type => all, nodedown_reason => true}),
+ ok = net_kernel:monitor_nodes(false, #{node_type => all, nodedown_reason => true, connection_id => true}),
{ok, N3} = start_node(DCfg, NN3),
receive {nodeup, N3} -> ok end,
@@ -1480,7 +1697,11 @@ monitor_nodes_errors(Config) when is_list(Config) ->
[gurka]}} = net_kernel:monitor_nodes(true,
[gurka]),
{error,
- {options_not_a_list,
+ {unknown_options,
+ #{gurka := true}}} = net_kernel:monitor_nodes(true,
+ #{gurka => true}),
+ {error,
+ {invalid_options,
gurka}} = net_kernel:monitor_nodes(true,
gurka),
{error,
@@ -1502,6 +1723,10 @@ monitor_nodes_errors(Config) when is_list(Config) ->
{node_type,
blaha}}}
= net_kernel:monitor_nodes(true, [{node_type, blaha}]),
+ {error,
+ {bad_option_value,
+ #{node_type := blaha}}}
+ = net_kernel:monitor_nodes(true, #{node_type => blaha}),
MonNodeState = monitor_node_state(),
ok.
@@ -1676,14 +1901,10 @@ monitor_nodes_many(DCfg, _Config) ->
%% Test order of messages nodedown and nodeup.
monitor_nodes_down_up(Config) when is_list(Config) ->
- [An] = get_nodenames(1, monitor_nodeup),
- {ok, A} = ct_slave:start(An),
-
- try
- monitor_nodes_yoyo(A)
- after
- catch ct_slave:stop(A)
- end.
+ {ok, Peer, Node} = ?CT_PEER(#{connection => 0}),
+ true = net_kernel:connect_node(Node),
+ monitor_nodes_yoyo(Node),
+ peer:stop(Peer).
monitor_nodes_yoyo(A) ->
net_kernel:monitor_nodes(true),
@@ -2044,21 +2265,34 @@ erl_1424(Config) when is_list(Config) ->
net_kernel_start(Config) when is_list(Config) ->
MyName = net_kernel_start_tester,
register(MyName, self()),
- net_kernel_start_test(MyName, 120, 8),
- net_kernel_start_test(MyName, undefined, undefined).
+ net_kernel_start_test(MyName, 120, 8, true, false),
+ net_kernel_start_test(MyName, 120, 8, false, false),
+ net_kernel_start_test(MyName, 120, 8, true, true),
+ net_kernel_start_test(MyName, undefined, undefined, undefined, undefined).
-net_kernel_start_test(MyName, NetTickTime, NetTickIntesity) ->
+net_kernel_start_test(MyName, NetTickTime, NetTickIntesity, DistListen, Hidden) ->
TestNameStr = "net_kernel_start_test_node-"
++ integer_to_list(erlang:system_time(seconds))
++ "-" ++ integer_to_list(erlang:unique_integer([monotonic,positive])),
TestNode = list_to_atom(TestNameStr ++ "@" ++ atom_to_list(gethostname())),
CmdLine = net_kernel_start_cmdline(MyName, list_to_atom(TestNameStr),
- NetTickTime, NetTickIntesity),
+ NetTickTime, NetTickIntesity, DistListen, Hidden),
io:format("Starting test node ~p: ~s~n", [TestNode, CmdLine]),
case open_port({spawn, CmdLine}, []) of
Port when is_port(Port) ->
+ case DistListen == false of
+ false ->
+ ok;
+ true ->
+ receive after 1500 -> ok end,
+ pang = net_adm:ping(TestNode),
+ ok
+ end,
receive
{i_am_alive, Pid, Node, NTT} = Msg ->
+ IsHidden = lists:member(TestNode, nodes(hidden)),
+ IsVisible = lists:member(TestNode, nodes(visible)),
+ io:format("IsVisible = ~p~nIsHidden = ~p~n", [IsVisible, IsHidden]),
io:format("Response from ~p: ~p~n", [Node, Msg]),
rpc:cast(Node, erlang, halt, []),
catch erlang:port_close(Port),
@@ -2070,6 +2304,14 @@ net_kernel_start_test(MyName, NetTickTime, NetTickIntesity) ->
DefNTT = NTT;
false ->
NetTickTime = NTT
+ end,
+ case DistListen == false orelse Hidden == true of
+ true ->
+ true = IsHidden,
+ false = IsVisible;
+ false ->
+ false = IsHidden,
+ true = IsVisible
end
end,
ok;
@@ -2077,7 +2319,7 @@ net_kernel_start_test(MyName, NetTickTime, NetTickIntesity) ->
error({open_port_failed, TestNode, Error})
end.
-net_kernel_start_cmdline(TestName, Name, NetTickTime, NetTickIntensity) ->
+net_kernel_start_cmdline(TestName, Name, NetTickTime, NetTickIntensity, DistListen, Hidden) ->
Pa = filename:dirname(code:which(?MODULE)),
Prog = case catch init:get_argument(progname) of
{ok, [[Prg]]} -> Prg;
@@ -2101,21 +2343,36 @@ net_kernel_start_cmdline(TestName, Name, NetTickTime, NetTickIntensity) ->
false ->
" " ++ integer_to_list(NetTickTime) ++
" " ++ integer_to_list(NetTickIntensity)
+ end
+ ++ case DistListen == undefined of
+ true -> "";
+ false -> " " ++ atom_to_list(DistListen)
+ end
+ ++ case Hidden == undefined of
+ true -> "";
+ false -> " " ++ atom_to_list(Hidden)
end.
net_kernel_start_do_test([TestName, TestNode, Name, NameDomain]) ->
net_kernel_start_do_test(TestName, TestNode, list_to_atom(Name),
#{name_domain => list_to_atom(NameDomain)});
-net_kernel_start_do_test([TestName, TestNode, Name, NameDomain, NetTickTime, NetTickIntensity]) ->
+net_kernel_start_do_test([TestName, TestNode, Name, NameDomain, NetTickTime, NetTickIntensity,
+ DistListen, Hidden]) ->
net_kernel_start_do_test(TestName, TestNode, list_to_atom(Name),
#{net_ticktime => list_to_integer(NetTickTime),
name_domain => list_to_atom(NameDomain),
- net_tickintensity => list_to_integer(NetTickIntensity)}).
+ net_tickintensity => list_to_integer(NetTickIntensity),
+ dist_listen => list_to_atom(DistListen),
+ hidden => list_to_atom(Hidden)}).
net_kernel_start_do_test(TestName, TestNode, Name, Options) ->
case net_kernel:start(Name, Options) of
{ok, _Pid} ->
+ case maps:get(dist_listen, Options, true) of
+ false -> receive after 3000 -> ok end;
+ true -> ok
+ end,
Tester = {list_to_atom(TestName), list_to_atom(TestNode)},
Tester ! {i_am_alive, self(), node(), net_kernel:get_net_ticktime()},
receive after 60000 -> ok end,
@@ -2410,6 +2667,59 @@ ddc_remote_run(MotherNode, [SetCookie, MotherNodeCookieL]) ->
error({unexpected, Other})
end.
+xdg_cookie(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ TestHome = filename:join(PrivDir, ?FUNCTION_NAME),
+ ok = file:make_dir(TestHome),
+
+ HomeEnv = case os:type() of
+ {win32, _} ->
+ [Drive | Path] = filename:split(TestHome),
+ [{"APPDATA", filename:join(TestHome,"AppData")},
+ {"HOMEDRIVE", Drive}, {"HOMEPATH", filename:join(Path)}];
+ _ ->
+ [{"HOME", TestHome}]
+ end,
+
+ NodeOpts = #{ env => HomeEnv ++
+ [{"ERL_CRASH_DUMP", filename:join([TestHome,"erl_crash.dump"])}],
+ connection => 0 },
+
+ %% Test that a default .erlang.cookie file is created
+ {ok, CreatorPeer, _} = peer:start_link(NodeOpts#{ name => peer:random_name(?FUNCTION_NAME) }),
+ UserConfig = peer:call(CreatorPeer, filename, basedir, [user_config,"erlang"]),
+ ?assert(peer:call(CreatorPeer, filelib, is_regular,
+ [filename:join(TestHome, ".erlang.cookie")])),
+ OrigCookie = peer:call(CreatorPeer, erlang, get_cookie, []),
+ peer:stop(CreatorPeer),
+
+ %% Test that the $HOME/.erlang.cookie file takes precedence over XDG
+ XDGCookie = filename:join([UserConfig, ".erlang.cookie"]),
+ ok = filelib:ensure_dir(XDGCookie),
+ ok = file:write_file(XDGCookie, "Me want cookie!"),
+ {ok, XDGFI} = file:read_file_info(XDGCookie),
+ ok = file:write_file_info(XDGCookie, XDGFI#file_info{ mode = 8#600 }),
+
+ {ok, Peer, _} = peer:start_link(NodeOpts#{ name => peer:random_name(?FUNCTION_NAME) }),
+
+ ?assertEqual(OrigCookie, peer:call(Peer, erlang, get_cookie, [])),
+
+ peer:stop(Peer),
+
+ %% Check that XDG cookie works after we delete the $HOME cookie
+ HomeCookie = filename:join(TestHome, ".erlang.cookie"),
+ {ok, HomeFI} = file:read_file_info(HomeCookie),
+ ok = file:write_file_info(HomeCookie, HomeFI#file_info{ mode = 8#777 }),
+ ok = file:delete(HomeCookie),
+ {ok, Peer2, _} = peer:start_link(NodeOpts#{ name => peer:random_name(?FUNCTION_NAME) }),
+ ?assertEqual('Me want cookie!', peer:call(Peer2, erlang, get_cookie, [])),
+
+ peer:stop(Peer2),
+
+ ok.
+
+
%% Misc. functions
diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl
index 3f45860a7e..6ca804b5bf 100644
--- a/lib/kernel/test/erl_distribution_wb_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2, whitebox/1,
- switch_options/1, missing_compulsory_dflags/1]).
+ switch_options/1, missing_compulsory_dflags/1,
+ dflag_mandatory_25/1]).
-define(to_port(Socket, Data),
@@ -41,29 +42,40 @@
-define(DIST_VER_HIGH, 6).
-define(DIST_VER_LOW, 5).
--define(DFLAG_PUBLISHED,1).
--define(DFLAG_ATOM_CACHE,2).
--define(DFLAG_EXTENDED_REFERENCES,4).
--define(DFLAG_DIST_MONITOR,8).
--define(DFLAG_FUN_TAGS,16#10).
--define(DFLAG_DIST_MONITOR_NAME,16#20).
--define(DFLAG_HIDDEN_ATOM_CACHE,16#40).
--define(DFLAG_NEW_FUN_TAGS,16#80).
--define(DFLAG_EXTENDED_PIDS_PORTS,16#100).
--define(DFLAG_UTF8_ATOMS, 16#10000).
--define(DFLAG_BIG_CREATION, 16#40000).
--define(DFLAG_HANDSHAKE_23, 16#01000000).
-
-%% From R9 and forward extended references is compulsory
-%% From R10 and forward extended pids and ports are compulsory
-%% From R20 and forward UTF8 atoms are compulsory
-%% From R21 and forward NEW_FUN_TAGS is compulsory (no more tuple fallback {fun, ...})
-%% From R23 and forward BIG_CREATION is compulsory
--define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor
- ?DFLAG_EXTENDED_PIDS_PORTS bor
- ?DFLAG_UTF8_ATOMS bor
- ?DFLAG_NEW_FUN_TAGS bor
- ?DFLAG_BIG_CREATION)).
+-define(DFLAG_PUBLISHED, 16#01).
+-define(DFLAG_ATOM_CACHE, 16#02).
+-define(DFLAG_EXTENDED_REFERENCES, 16#04).
+-define(DFLAG_DIST_MONITOR, 16#08).
+-define(DFLAG_FUN_TAGS, 16#10).
+-define(DFLAG_NEW_FUN_TAGS, 16#80).
+-define(DFLAG_EXTENDED_PIDS_PORTS, 16#100).
+-define(DFLAG_EXPORT_PTR_TAG, 16#200).
+-define(DFLAG_BIT_BINARIES, 16#400).
+-define(DFLAG_NEW_FLOATS, 16#800).
+-define(DFLAG_UTF8_ATOMS, 16#10000).
+-define(DFLAG_MAP_TAG, 16#20000).
+-define(DFLAG_BIG_CREATION, 16#40000).
+-define(DFLAG_HANDSHAKE_23, 16#1000000).
+-define(DFLAG_MANDATORY_25_DIGEST, 16#4000000).
+
+%% From OTP R9 extended references are compulsory.
+%% From OTP R10 extended pids and ports are compulsory.
+%% From OTP 20 UTF8 atoms are compulsory.
+%% From OTP 21 NEW_FUN_TAGS is compulsory (no more tuple fallback {fun, ...}).
+%% From OTP 23 BIG_CREATION is compulsory.
+%% From OTP 25 HANDSHAKE_23, NEW_FLOATS, MAP_TAG, EXPORT_PTR_TAG, and BIT_BINARIES are compulsory.
+-define(COMPULSORY_DFLAGS,
+ (?DFLAG_EXTENDED_REFERENCES bor
+ ?DFLAG_FUN_TAGS bor
+ ?DFLAG_EXTENDED_PIDS_PORTS bor
+ ?DFLAG_UTF8_ATOMS bor
+ ?DFLAG_NEW_FUN_TAGS bor
+ ?DFLAG_BIG_CREATION bor
+ ?DFLAG_HANDSHAKE_23 bor
+ ?DFLAG_NEW_FLOATS bor
+ ?DFLAG_MAP_TAG bor
+ ?DFLAG_EXPORT_PTR_TAG bor
+ ?DFLAG_BIT_BINARIES)).
-define(PASS_THROUGH, $p).
@@ -89,7 +101,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [whitebox, switch_options, missing_compulsory_dflags].
+ [whitebox, switch_options, missing_compulsory_dflags, dflag_mandatory_25].
groups() ->
[].
@@ -126,22 +138,17 @@ switch_options(Config) when is_list(Config) ->
%% Whitebox testing of distribution handshakes.
whitebox(Config) when is_list(Config) ->
- {ok, Node} = start_node(?MODULE,""),
+ {ok, Peer, Node} = ?CT_PEER(),
Cookie = erlang:get_cookie(),
{_,Host} = split(node()),
[begin
- io:format("Test OurVersion=~p and TrustEpmd=~p\n",
- [OurVersion, TrustEpmd]),
- ok = pending_up_md5(Node, join(ccc,Host), OurVersion,
- TrustEpmd, Cookie),
- ok = simultaneous_md5(Node, join('A',Host), OurVersion,
- TrustEpmd, Cookie),
- ok = simultaneous_md5(Node, join(zzzzzzzzzzzzzz,Host),
- OurVersion, TrustEpmd, Cookie)
+ io:format("Test TrustEpmd=~p\n", [TrustEpmd]),
+ ok = pending_up_md5(Node, join(ccc,Host), TrustEpmd, Cookie),
+ ok = simultaneous_md5(Node, join('A',Host), TrustEpmd, Cookie),
+ ok = simultaneous_md5(Node, join(zzzzzzzzzz,Host), TrustEpmd, Cookie)
end
- || OurVersion <- lists:seq(?DIST_VER_LOW, ?DIST_VER_HIGH),
- TrustEpmd <- [true, false]],
- stop_node(Node),
+ || TrustEpmd <- [true, false]],
+ peer:stop(Peer),
ok.
%%
@@ -209,7 +216,7 @@ test_switch_active_and_packet() ->
%%
%% Handshake tests
%%
-pending_up_md5(Node,OurName,OurVersion,TrustEpmd,Cookie) ->
+pending_up_md5(Node,OurName,TrustEpmd,Cookie) ->
{NA,NB} = split(Node),
{port,PortNo,EpmdSaysVersion} = erl_epmd:port_please(NA,NB),
{ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
@@ -219,12 +226,12 @@ pending_up_md5(Node,OurName,OurVersion,TrustEpmd,Cookie) ->
true -> EpmdSaysVersion;
false -> ?DIST_VER_LOW
end,
- SentNameMsg = send_name(SocketA,OurName, OurVersion, AssumedVersion),
+ SentNameMsg = send_name(SocketA,OurName,AssumedVersion),
ok = recv_status(SocketA),
- {Node,ChallengeMsg,HisChallengeA} = recv_challenge(SocketA,OurVersion),
+ {Node,HisChallengeA} = recv_challenge(SocketA),
OurChallengeA = gen_challenge(),
OurDigestA = gen_digest(HisChallengeA, Cookie),
- send_complement(SocketA, SentNameMsg, ChallengeMsg, OurVersion),
+ send_complement(SocketA, SentNameMsg),
send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie),
%%%
@@ -236,14 +243,14 @@ pending_up_md5(Node,OurName,OurVersion,TrustEpmd,Cookie) ->
{ok, SocketB} = gen_tcp:connect(atom_to_list(NB),PortNo,
[{active,false},
{packet,2}]),
- SentNameMsg = send_name(SocketB,OurName, OurVersion, AssumedVersion),
+ SentNameMsg = send_name(SocketB,OurName,AssumedVersion),
alive = recv_status(SocketB),
send_status(SocketB, true),
gen_tcp:close(SocketA),
- {Node,ChallengeMsg,HisChallengeB} = recv_challenge(SocketB,OurVersion),
+ {Node,HisChallengeB} = recv_challenge(SocketB),
OurChallengeB = gen_challenge(),
OurDigestB = gen_digest(HisChallengeB, Cookie),
- send_complement(SocketB, SentNameMsg, ChallengeMsg, OurVersion),
+ send_complement(SocketB, SentNameMsg),
send_challenge_reply(SocketB, OurChallengeB, OurDigestB),
ok = recv_challenge_ack(SocketB, OurChallengeB, Cookie),
%%%
@@ -259,7 +266,7 @@ pending_up_md5(Node,OurName,OurVersion,TrustEpmd,Cookie) ->
gen_tcp:close(SocketB),
ok.
-simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName < Node ->
+simultaneous_md5(Node, OurName, TrustEpmd, Cookie) when OurName < Node ->
pong = net_adm:ping(Node),
LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
{ok, Socket} ->
@@ -267,7 +274,7 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName < No
Else ->
exit(Else)
end,
- EpmdSocket = register_node(OurName, LSocket, ?DIST_VER_LOW, ?DIST_VER_LOW),
+ EpmdSocket = register_node(OurName, LSocket),
{NA, NB} = split(Node),
rpc:cast(Node, net_adm, ping, [OurName]),
receive after 1000 -> ok end,
@@ -279,7 +286,7 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName < No
true -> EpmdSaysVersion;
false -> ?DIST_VER_LOW
end,
- send_name(SocketA,OurName, OurVersion, AssumedVersion),
+ send_name(SocketA, OurName, AssumedVersion),
%% We are still not marked up on the other side, as our first message
%% is not sent.
SocketB = case gen_tcp:accept(LSocket) of
@@ -292,12 +299,11 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName < No
%% Now we are expected to close A
gen_tcp:close(SocketA),
%% But still Socket B will continue
- {Node,GotNameMsg,GotFlags} = recv_name(SocketB),
+ {Node,GotFlags} = recv_name(SocketB),
true = (GotFlags band ?DFLAG_HANDSHAKE_23) =/= 0,
send_status(SocketB, ok_simultaneous),
MyChallengeB = gen_challenge(),
- send_challenge(SocketB, OurName, MyChallengeB, OurVersion, GotFlags),
- recv_complement(SocketB, GotNameMsg, OurVersion),
+ send_challenge(SocketB, OurName, MyChallengeB, GotFlags),
{ok,HisChallengeB} = recv_challenge_reply(SocketB, MyChallengeB, Cookie),
DigestB = gen_digest(HisChallengeB,Cookie),
send_challenge_ack(SocketB, DigestB),
@@ -312,7 +318,7 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName < No
gen_tcp:close(EpmdSocket),
ok;
-simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName > Node ->
+simultaneous_md5(Node, OurName, TrustEpmd, Cookie) when OurName > Node ->
pong = net_adm:ping(Node),
LSocket = case gen_tcp:listen(0, [{active, false}, {packet,2}]) of
{ok, Socket} ->
@@ -320,8 +326,7 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName > No
Else ->
exit(Else)
end,
- EpmdSocket = register_node(OurName, LSocket,
- ?DIST_VER_LOW, ?DIST_VER_LOW),
+ EpmdSocket = register_node(OurName, LSocket),
{NA, NB} = split(Node),
rpc:cast(Node, net_adm, ping, [OurName]),
receive after 1000 -> ok end,
@@ -339,17 +344,15 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName > No
true -> EpmdSaysVersion;
false -> ?DIST_VER_LOW
end,
- SentNameMsg = send_name(SocketA,OurName, OurVersion, AssumedVersion),
+ SentNameMsg = send_name(SocketA,OurName, AssumedVersion),
ok_simultaneous = recv_status(SocketA),
%% Socket B should die during this
case catch begin
- {Node,GotNameMsg,GotFlagsB} = recv_name(SocketB),
+ {Node, GotFlagsB} = recv_name(SocketB),
true = (GotFlagsB band ?DFLAG_HANDSHAKE_23) =/= 0,
send_status(SocketB, ok_simultaneous),
MyChallengeB = gen_challenge(),
- send_challenge(SocketB, OurName, MyChallengeB,
- OurVersion, GotFlagsB),
- recv_complement(SocketB, GotNameMsg, OurVersion),
+ send_challenge(SocketB, OurName, MyChallengeB, GotFlagsB),
{ok,HisChallengeB} = recv_challenge_reply(
SocketB,
MyChallengeB,
@@ -372,10 +375,10 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName > No
end,
gen_tcp:close(SocketB),
%% But still Socket A will continue
- {Node,ChallengeMsg,HisChallengeA} = recv_challenge(SocketA,OurVersion),
+ {Node,HisChallengeA} = recv_challenge(SocketA),
OurChallengeA = gen_challenge(),
OurDigestA = gen_digest(HisChallengeA, Cookie),
- send_complement(SocketA, SentNameMsg, ChallengeMsg, OurVersion),
+ send_complement(SocketA, SentNameMsg),
send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
ok = recv_challenge_ack(SocketA, OurChallengeA, Cookie),
@@ -391,21 +394,61 @@ simultaneous_md5(Node, OurName, OurVersion, TrustEpmd, Cookie) when OurName > No
ok.
missing_compulsory_dflags(Config) when is_list(Config) ->
- [Name1, Name2] = get_nodenames(2, missing_compulsory_dflags),
- {ok, Node} = start_node(Name1,""),
+ Cookie = erlang:get_cookie(),
+ {ok, Peer, Node} = ?CT_PEER(),
{NA,NB} = split(Node),
{port,PortNo,_} = erl_epmd:port_please(NA,NB),
[begin
+ io:format("Assumed version ~p, Missing flags ~.16B\n",
+ [Version, MissingFlags]),
{ok, SocketA} = gen_tcp:connect(atom_to_list(NB),PortNo,
[{active,false},
{packet,2}]),
- BadNode = list_to_atom(atom_to_list(Name2)++"@"++atom_to_list(NB)),
- send_name(SocketA,BadNode, Version, Version, 0),
- not_allowed = recv_status(SocketA),
+ BadNode = list_to_atom(?CT_PEER_NAME()++"@"++atom_to_list(NB)),
+ Flags = ?COMPULSORY_DFLAGS band (bnot MissingFlags),
+ SentNameMsg = send_name(SocketA, BadNode, Version, Flags),
+ case {Version, MissingFlags bsr 32} of
+ {?DIST_VER_LOW, HighFlags} when HighFlags =/= 0 ->
+ %% Missing flag in high word, peer will not detect that
+ %% until we send complement.
+ ok = recv_status(SocketA),
+ {Node,HisChallengeA} = recv_challenge(SocketA),
+ OurChallengeA = gen_challenge(),
+ OurDigestA = gen_digest(HisChallengeA, Cookie),
+ send_complement(SocketA, SentNameMsg, Flags),
+ send_challenge_reply(SocketA, OurChallengeA, OurDigestA),
+
+ %% Would normally expect recv_challenge_ack but dist_util
+ %% reacts to missing flags with a status message instead.
+ not_allowed = recv_status(SocketA);
+
+ _ ->
+ not_allowed = recv_status(SocketA)
+ end,
gen_tcp:close(SocketA)
end
- || Version <- lists:seq(?DIST_VER_LOW, ?DIST_VER_HIGH)],
- stop_node(Node),
+ || Version <- lists:seq(?DIST_VER_LOW, ?DIST_VER_HIGH),
+ MissingFlags <- [?DFLAG_BIT_BINARIES,
+ ?DFLAG_HANDSHAKE_23]],
+
+ peer:stop(Peer),
+ ok.
+
+%% Test that instead of passing all compulsory flags, we can instead
+%% pass only ?DFLAG_MANDATORY_25_DIGEST to ensure that we will be able to communicate
+%% with a future release where ?DFLAG_MANDATORY_25_DIGEST is mandatory.
+dflag_mandatory_25(_Config) ->
+ {ok, Peer, Node} = ?CT_PEER(),
+ {NA,NB} = split(Node),
+ {port,PortNo,_} = erl_epmd:port_please(NA, NB),
+ {ok, SocketA} = gen_tcp:connect(atom_to_list(NB),
+ PortNo,
+ [{active,false},{packet,2}]),
+ OtherNode = list_to_atom(?CT_PEER_NAME()++"@"++atom_to_list(NB)),
+ send_name(SocketA, OtherNode, ?DIST_VER_HIGH, ?DFLAG_MANDATORY_25_DIGEST),
+ ok = recv_status(SocketA),
+ gen_tcp:close(SocketA),
+ peer:stop(Peer),
ok.
%%
@@ -496,7 +539,7 @@ gen_digest(Challenge, Cookie) when is_integer(Challenge), is_atom(Cookie) ->
%%
-%% The differrent stages of the MD5 handshake
+%% The different stages of the MD5 handshake
%%
send_status(Socket, Stat) ->
@@ -516,14 +559,11 @@ recv_status(Socket) ->
exit(Bad)
end.
-send_challenge(Socket, Node, Challenge, Version, GotFlags) ->
- send_challenge(Socket, Node, Challenge, Version, GotFlags, ?COMPULSORY_DFLAGS).
+send_challenge(Socket, Node, Challenge, GotFlags) ->
+ Flags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
+ send_challenge(Socket, Node, Challenge, GotFlags, Flags).
-send_challenge(Socket, Node, Challenge, ?DIST_VER_LOW, _GotFlags, Flags) ->
- {ok, {{_Ip1,_Ip2,_Ip3,_Ip4}, _}} = inet:sockname(Socket),
- ?to_port(Socket, [$n,<<?DIST_VER_LOW:16>>,<<Flags:32>>,
- <<Challenge:32>>, atom_to_list(Node)]);
-send_challenge(Socket, Node, Challenge, ?DIST_VER_HIGH, GotFlags, Flags) ->
+send_challenge(Socket, Node, Challenge, GotFlags, Flags) ->
true = (GotFlags band ?DFLAG_HANDSHAKE_23) =/= 0,
{ok, {{_Ip1,_Ip2,_Ip3,_Ip4}, _}} = inet:sockname(Socket),
NodeName = atom_to_list(Node),
@@ -534,58 +574,51 @@ send_challenge(Socket, Node, Challenge, ?DIST_VER_HIGH, GotFlags, Flags) ->
<<Nlen:16>>, NodeName
]).
-recv_challenge(Socket, OurVersion) ->
+recv_challenge(Socket) ->
{ok, Msg} = gen_tcp:recv(Socket, 0),
%%io:format("recv_challenge Msg=~p\n", [Msg]),
- case {OurVersion, Msg} of
- {?DIST_VER_LOW,
- [$n,V1,V0,Fl1,Fl2,Fl3,Fl4,CA3,CA2,CA1,CA0 | Ns]} ->
- Flags = ?u32(Fl1,Fl2,Fl3,Fl4),
- true = (Flags band ?COMPULSORY_DFLAGS) =:= ?COMPULSORY_DFLAGS,
- Node =list_to_atom(Ns),
- ?DIST_VER_LOW = ?u16(V1,V0),
- Challenge = ?u32(CA3,CA2,CA1,CA0),
- {Node,$n,Challenge};
-
- {?DIST_VER_HIGH,
- [$N, F7,F6,F5,F4,F3,F2,F1,F0, CA3,CA2,CA1,CA0,
- Cr3,Cr2,Cr1,Cr0, NL1,NL0 | Ns]} ->
+ case Msg of
+ [$N, F7,F6,F5,F4,F3,F2,F1,F0, CA3,CA2,CA1,CA0,
+ Cr3,Cr2,Cr1,Cr0, NL1,NL0 | Ns] ->
<<Flags:64>> = <<F7,F6,F5,F4,F3,F2,F1,F0>>,
- true = (Flags band ?COMPULSORY_DFLAGS) =:= ?COMPULSORY_DFLAGS,
+ verify_flags(Flags),
<<Creation:32>> = <<Cr3,Cr2,Cr1,Cr0>>,
true = (Creation =/= 0),
<<NameLen:16>> = <<NL1,NL0>>,
NameLen = length(Ns),
Node = list_to_atom(Ns),
Challenge = ?u32(CA3,CA2,CA1,CA0),
- {Node,$N,Challenge};
+ {Node, Challenge};
_ ->
?shutdown(no_node)
end.
-send_complement(Socket, SentNameMsg, ChallengeMsg, OurVersion) ->
- case {SentNameMsg,ChallengeMsg} of
- {$n,$N} ->
- FlagsHigh = our_flags(?COMPULSORY_DFLAGS, OurVersion) bsr 32,
+verify_flags(Flags) ->
+ RequiredFlags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
+ if
+ Flags band RequiredFlags =:= RequiredFlags ->
+ ok;
+ true ->
+ io:format("Given flags: ~.16.0B\n", [Flags]),
+ io:format("Required flags: ~.16.0B\n", [RequiredFlags]),
+ ct:fail(missing_dflags)
+ end.
+
+send_complement(Socket, SentNameMsg) ->
+ send_complement(Socket, SentNameMsg, ?COMPULSORY_DFLAGS).
+
+send_complement(Socket, SentNameMsg, Flags) ->
+ case SentNameMsg of
+ $n ->
+ FlagsHigh = Flags bsr 32,
?to_port(Socket, [$c,
<<FlagsHigh:32>>,
?int32(erts_internal:get_creation())]);
- {Same,Same} ->
+ $N ->
ok
end.
-recv_complement(Socket, $n, OurVersion) when OurVersion > ?DIST_VER_LOW ->
- case gen_tcp:recv(Socket, 0) of
- {ok,[$c,Cr3,Cr2,Cr1,Cr0]} ->
- Creation = ?u32(Cr3,Cr2,Cr1,Cr0),
- true = (Creation =/= 0);
- Err ->
- {error,Err}
- end;
-recv_complement(_, _ , _) ->
- ok.
-
send_challenge_reply(Socket, Challenge, Digest) ->
?to_port(Socket, [$r,?int32(Challenge),Digest]).
@@ -617,31 +650,24 @@ recv_challenge_ack(Socket, ChallengeB, CookieA) ->
end
end.
-send_name(Socket, MyNode0, OurVersion, AssumedVersion) ->
- send_name(Socket, MyNode0, OurVersion, AssumedVersion, ?COMPULSORY_DFLAGS).
+send_name(Socket, MyNode0, AssumedVersion) ->
+ Flags = ?COMPULSORY_DFLAGS bor ?DFLAG_MANDATORY_25_DIGEST,
+ send_name(Socket, MyNode0, AssumedVersion, Flags).
-send_name(Socket, MyNode0, OurVersion, AssumedVersion, Flags) ->
+send_name(Socket, MyNode0, AssumedVersion, Flags) ->
MyNode = atom_to_list(MyNode0),
- if (OurVersion =:= ?DIST_VER_LOW) or
- (AssumedVersion =:= ?DIST_VER_LOW) ->
- OurFlags = our_flags(Flags,OurVersion),
- ok = ?to_port(Socket, [<<$n,OurVersion:16,OurFlags:32>>|MyNode]),
+ if (AssumedVersion =:= ?DIST_VER_LOW) ->
+ ok = ?to_port(Socket, [<<$n,?DIST_VER_HIGH:16,Flags:32>>|MyNode]),
$n;
- (OurVersion > ?DIST_VER_LOW) and
(AssumedVersion > ?DIST_VER_LOW) ->
Creation = erts_internal:get_creation(),
NameLen = length(MyNode),
- ok = ?to_port(Socket, [<<$N, (Flags bor ?DFLAG_HANDSHAKE_23):64,
+ ok = ?to_port(Socket, [<<$N, Flags:64,
Creation:32,NameLen:16>>|MyNode]),
$N
end.
-our_flags(Flags, ?DIST_VER_LOW) ->
- Flags;
-our_flags(Flags, OurVersion) when OurVersion > ?DIST_VER_LOW ->
- Flags bor ?DFLAG_HANDSHAKE_23.
-
recv_name(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok,Data} ->
@@ -650,18 +676,13 @@ recv_name(Socket) ->
?shutdown({no_node,Res})
end.
-get_name([$n, V1,V0, F3,F2,F1,F0 | OtherNode]) ->
- <<Version:16>> = <<V1,V0>>,
- 5 = Version,
- <<Flags:32>> = <<F3,F2,F1,F0>>,
- {list_to_atom(OtherNode), $n, Flags};
get_name([$N, F7,F6,F5,F4,F3,F2,F1,F0,
_C3,_C2,_C1,_C0, NLen1,NLen2 | OtherNode]) ->
<<Flags:64>> = <<F7,F6,F5,F4,F3,F2,F1,F0>>,
true = (Flags band ?DFLAG_HANDSHAKE_23) =/= 0,
<<NameLen:16>> = <<NLen1,NLen2>>,
NameLen = length(OtherNode),
- {list_to_atom(OtherNode), $N, Flags};
+ {list_to_atom(OtherNode), Flags};
get_name(Data) ->
?shutdown(Data).
@@ -676,7 +697,7 @@ get_epmd_port() ->
4369 % Default epmd port
end.
-do_register_node(NodeName, TcpPort, VLow, VHigh) ->
+do_register_node(NodeName, TcpPort) ->
case gen_tcp:connect({127,0,0,1}, get_epmd_port(), []) of
{ok, Socket} ->
{N0,_} = split(NodeName),
@@ -688,8 +709,8 @@ do_register_node(NodeName, TcpPort, VLow, VHigh) ->
?int16(TcpPort),
$M,
0,
- ?int16(VHigh),
- ?int16(VLow),
+ ?int16(?DIST_VER_HIGH),
+ ?int16(?DIST_VER_LOW),
?int16(length(Name)),
Name,
?int16(Elen),
@@ -735,9 +756,9 @@ wait_for_reg_reply(Socket, SoFar) ->
end.
-register_node(NodeName, ListenSocket, VLow, VHigh) ->
+register_node(NodeName, ListenSocket) ->
{ok,{_,TcpPort}} = inet:sockname(ListenSocket),
- case do_register_node(NodeName, TcpPort, VLow, VHigh) of
+ case do_register_node(NodeName, TcpPort) of
{alive, Socket, _Creation} ->
Socket;
Other ->
@@ -761,13 +782,13 @@ split(Atom) ->
%% Build a distribution message that will make rex answer
build_rex_message(Cookie,OurName) ->
- [$?,term_to_binary({6,self(),Cookie,rex}),
+ [?PASS_THROUGH,term_to_binary({6,self(),Cookie,rex}),
term_to_binary({'$gen_cast',
{cast,
- rpc,
- cast,
- [OurName, hello, world, []],
- self()} })].
+ erlang,
+ send,
+ [{regname, OurName}, "hello world"],
+ self()}})].
%% Receive a distribution message
recv_message(Socket) ->
@@ -793,24 +814,3 @@ recv_message(Socket) ->
%% Build a nodename
join(Name,Host) ->
list_to_atom(atom_to_list(Name) ++ "@" ++ atom_to_list(Host)).
-
-%% start/stop slave.
-start_node(Name, Param) ->
- test_server:start_node(Name, slave, [{args, Param}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-
-get_nodenames(N, T) ->
- get_nodenames(N, T, []).
-
-get_nodenames(0, _, Acc) ->
- Acc;
-get_nodenames(N, T, Acc) ->
- U = erlang:unique_integer([positive]),
- get_nodenames(N-1, T, [list_to_atom(?MODULE_STRING
- ++ "-"
- ++ atom_to_list(T)
- ++ "-"
- ++ integer_to_list(U)) | Acc]).
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 907a000787..eaeca5ac58 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -140,8 +140,7 @@ do_get_modules(Config) ->
%% Test that an 'enotdir' error can be handled.
{ok,{SuccExp,FailExp}} = get_modules_sorted(Ms, Process, [NotADir|Path]),
- Name = inet_get_modules,
- {ok, Node, BootPid} = complete_start_node(Name),
+ {ok, Peer, Node, BootPid} = complete_start_node(),
ThisDir = filename:dirname(code:which(?MODULE)),
true = rpc:call(Node, code, add_patha, [ThisDir]),
_ = rpc:call(Node, code, ensure_loaded, [?MODULE]),
@@ -149,7 +148,7 @@ do_get_modules(Config) ->
get_modules, [Ms,Process,Path]),
SuccExp = lists:sort(InetSucc),
- stop_node(Node),
+ peer:stop(Peer),
unlink(BootPid),
exit(BootPid, kill),
@@ -186,11 +185,10 @@ test_normalize_and_backslash(Config) ->
%% Start a node using the 'inet' loading method,
%% from an already started boot server.
inet_existing(Config) when is_list(Config) ->
- Name = erl_prim_test_inet_existing,
BootPid = start_boot_server(),
- Node = start_node_using_inet(Name),
+ {ok, Peer, Node} = ?CT_PEER(start_node_using_inet_args()),
{ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
- stop_node(Node),
+ peer:stop(Peer),
unlink(BootPid),
exit(BootPid, kill),
ok.
@@ -198,37 +196,35 @@ inet_existing(Config) when is_list(Config) ->
%% Start a node using the 'inet' loading method,
%% but start the boot server afterwards.
inet_coming_up(Config) when is_list(Config) ->
- Name = erl_prim_test_inet_coming_up,
- Node = start_node_using_inet(Name, [{wait,false}]),
+ {ok, Peer} = ?CT_PEER(#{wait_boot => false, connection => standard_io,
+ args => start_node_using_inet_args()}),
%% Wait a while, then start boot server, and wait for node to start.
ct:sleep({seconds,6}),
BootPid = start_boot_server(),
- wait_really_started(Node, 25),
+ Node = wait_really_started(Peer, 25),
%% Check loader argument, then cleanup.
{ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
- stop_node(Node),
+ peer:stop(Peer),
unlink(BootPid),
exit(BootPid, kill),
ok.
-wait_really_started(Node, 0) ->
- ct:fail({not_booted,Node});
-wait_really_started(Node, N) ->
- case rpc:call(Node, init, get_status, []) of
- {started, _} ->
- ok;
- _ ->
- ct:sleep(1000),
- wait_really_started(Node, N - 1)
+wait_really_started(Peer, 0) ->
+ ct:fail({not_booted,Peer});
+wait_really_started(Peer, N) ->
+ case (catch peer:call(Peer, init, get_status, [])) of
+ {started, _} ->
+ peer:call(Peer, erlang, node, []);
+ _ ->
+ ct:sleep(1000),
+ wait_really_started(Peer, N - 1)
end.
%% Start a node using the 'inet' loading method,
%% then lose the connection.
inet_disconnects(Config) when is_list(Config) ->
- Name = erl_prim_test_inet_disconnects,
-
BootPid = start_boot_server(),
unlink(BootPid),
Self = self(),
@@ -240,7 +236,8 @@ inet_disconnects(Config) when is_list(Config) ->
end,
%% Let the loading begin...
- Node = start_node_using_inet(Name, [{wait,false}]),
+ {ok,Peer} = ?CT_PEER(#{wait_boot => false, connection => 0,
+ args => start_node_using_inet_args()}),
%% When the stopper is ready, the slave node should be
%% looking for a boot server again.
@@ -255,9 +252,9 @@ inet_disconnects(Config) when is_list(Config) ->
%% Start new boot server to see that loading is continued.
BootPid2 = start_boot_server(),
- wait_really_started(Node, 25),
+ Node = wait_really_started(Peer, 25),
{ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
- stop_node(Node),
+ peer:stop(Peer),
unlink(BootPid2),
exit(BootPid2, kill),
ok.
@@ -290,22 +287,11 @@ get_calls(Count, Pid) ->
%% Start nodes in parallel, all using the 'inet' loading method;
%% verify that the boot server manages.
multiple_slaves(Config) when is_list(Config) ->
- Name = erl_prim_test_multiple_slaves,
- Host = host(),
- IpStr = ip_str(Host),
- Args = " -loader inet -hosts " ++ IpStr,
+ Args = start_node_using_inet_args(),
NoOfNodes = 10, % no of slave nodes to be started
- NamesAndNodes =
- lists:map(fun(N) ->
- NameN = atom_to_list(Name) ++
- integer_to_list(N),
- NodeN = NameN ++ "@" ++ Host,
- {list_to_atom(NameN),list_to_atom(NodeN)}
- end, lists:seq(1, NoOfNodes)),
-
- Nodes = start_multiple_nodes(NamesAndNodes, Args, []),
+ Peers = [?CT_PEER(#{wait_boot => {self(), tag}, args => Args}) || _ <- lists:seq(1, NoOfNodes)],
%% "queue up" the nodes to wait for the boot server to respond
%% (note: test_server supervises each node start by accept()
@@ -317,31 +303,25 @@ multiple_slaves(Config) when is_list(Config) ->
%% give the nodes a chance to boot up before attempting to stop them
ct:sleep({seconds,10}),
- wait_and_shutdown(lists:reverse(Nodes), 30),
+ %% wait for all nodes to complete boot process, get their names:
+ [
+ receive
+ {tag, {started, Node, Peer}} ->
+ {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader])
+ end
+ || {ok, Peer} <- Peers
+ ],
+ [peer:stop(Peer) || {ok, Peer} <- Peers],
unlink(BootPid),
exit(BootPid, kill),
ok.
-start_multiple_nodes([{Name,Node} | NNs], Args, Started) ->
- {ok,Node} = start_node(Name, Args, [{wait, false}]),
- start_multiple_nodes(NNs, Args, [Node | Started]);
-start_multiple_nodes([], _, Nodes) ->
- Nodes.
-
-wait_and_shutdown([Node | Nodes], Tries) ->
- wait_really_started(Node, Tries),
- {ok,[["inet"]]} = rpc:call(Node, init, get_argument, [loader]),
- stop_node(Node),
- wait_and_shutdown(Nodes, Tries);
-wait_and_shutdown([], _) ->
- ok.
-
%% Start a node using the 'inet' loading method,
%% verify that the boot server responds to file requests.
file_requests(Config) when is_list(Config) ->
- {ok, Node, BootPid} = complete_start_node(erl_prim_test_file_req),
+ {ok, Peer, Node, BootPid} = complete_start_node(),
%% compare with results from file server calls (the
%% boot server uses the same file sys and cwd)
@@ -384,7 +364,7 @@ file_requests(Config) when is_list(Config) ->
{ok,DCwd} = rpc:call(Node, erl_prim_loader, get_cwd, ["C:"])
end,
- stop_node(Node),
+ peer:stop(Peer),
unlink(BootPid),
exit(BootPid, kill),
ok.
@@ -414,13 +394,13 @@ remote_archive(Config) when is_list(Config) ->
file:delete(Archive),
{ok, Archive} = create_archive(Archive, [KernelDir]),
- {ok, Node, BootPid} = complete_start_node(remote_archive),
+ {ok, Peer, Node, BootPid} = complete_start_node(),
BeamName = "inet.beam",
ok = test_archive(Node, Archive, KernelDir, BeamName),
%% Cleanup
- stop_node(Node),
+ peer:stop(Peer),
unlink(BootPid),
exit(BootPid, kill),
ok.
@@ -449,10 +429,7 @@ primary_archive(Config) when is_list(Config) ->
[memory, {compress, []}, {cwd, TopDir}]),
%% Use temporary node to simplify cleanup
- Cookie = atom_to_list(erlang:get_cookie()),
- Args = " -setcookie " ++ Cookie,
- {ok,Node} = start_node(primary_archive, Args),
- wait_really_started(Node, 25),
+ {ok,Peer,Node} = ?CT_PEER(),
{_,_,_} = rpc:call(Node, erlang, date, []),
%% Set primary archive
@@ -473,7 +450,7 @@ primary_archive(Config) when is_list(Config) ->
{ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive,
[undefined, undefined, undefined,
fun escript:parse_file/1]),
- stop_node(Node),
+ peer:stop(Peer),
ok = file:delete(Archive),
ok.
@@ -559,11 +536,10 @@ virtual_dir_in_archive(Config) when is_list(Config) ->
%%% Helper functions.
%%%
-complete_start_node(Name) ->
+complete_start_node() ->
BootPid = start_boot_server(),
- Node = start_node_using_inet(Name),
- wait_really_started(Node, 25),
- {ok, Node, BootPid}.
+ {ok, Peer, Node} = ?CT_PEER(start_node_using_inet_args()),
+ {ok, Peer, Node, BootPid}.
start_boot_server() ->
%% Many linux systems define:
@@ -576,15 +552,9 @@ start_boot_server() ->
{ok,BootPid} = erl_boot_server:start_link(Hosts),
BootPid.
-start_node_using_inet(Name) ->
- start_node_using_inet(Name, []).
-
-start_node_using_inet(Name, Opts) ->
- Host = host(),
- IpStr = ip_str(Host),
- Args = " -loader inet -hosts " ++ IpStr,
- {ok,Node} = start_node(Name, Args, Opts),
- Node.
+start_node_using_inet_args() ->
+ IpStr = ip_str(host()),
+ ["-loader", "inet", "-hosts", IpStr].
ip_str({A, B, C, D}) ->
@@ -593,24 +563,10 @@ ip_str(Host) ->
{ok,Ip} = inet:getaddr(Host, inet),
ip_str(Ip).
-start_node(Name, Args) ->
- start_node(Name, Args, []).
-
-start_node(Name, Args, Opts) ->
- Opts2 = [{args, Args}|Opts],
- io:format("test_server:start_node(~p, peer, ~p).\n",
- [Name, Opts2]),
- Res = test_server:start_node(Name, peer, Opts2),
- io:format("start_node -> ~p\n", [Res]),
- Res.
-
host() ->
{ok,Host} = inet:gethostname(),
Host.
-stop_node(Node) ->
- test_server:stop_node(Node).
-
compile_app(TopDir, AppName) ->
AppDir = filename:join([TopDir, AppName]),
SrcDir = filename:join([AppDir, "src"]),
diff --git a/lib/kernel/test/erpc_SUITE.erl b/lib/kernel/test/erpc_SUITE.erl
index cd145259c3..ea749b54e8 100644
--- a/lib/kernel/test/erpc_SUITE.erl
+++ b/lib/kernel/test/erpc_SUITE.erl
@@ -21,12 +21,17 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([call/1, call_reqtmo/1, call_against_old_node/1, cast/1,
+-export([call/1, call_against_old_node/1,
+ call_from_old_node/1,
+ call_reqtmo/1, call_against_ei_node/1, cast/1,
send_request/1, send_request_fun/1,
send_request_receive_reqtmo/1,
send_request_wait_reqtmo/1,
send_request_check_reqtmo/1,
- send_request_against_old_node/1,
+ send_request_against_ei_node/1,
+ send_request_receive_reqid_collection/1,
+ send_request_wait_reqid_collection/1,
+ send_request_check_reqid_collection/1,
multicall/1, multicall_reqtmo/1,
multicall_recv_opt/1,
multicall_recv_opt2/1,
@@ -35,27 +40,41 @@
timeout_limit/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
+-export([call_test/4]).
+
-export([call_func1/1, call_func2/1, call_func4/4]).
-export([f/0, f2/0]).
-include_lib("common_test/include/ct.hrl").
+-ifndef(CT_PEER).
+%% This module needs to compile on old nodes...
+-define(CT_PEER(), {ok, undefined, undefined}).
+-define(CT_PEER(Opts), {ok, undefined, undefined}).
+-define(CT_PEER_REL(Opts, Release, PrivDir), {ok, undefined, undefined}).
+-endif.
+
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,2}}].
-all() ->
+all() ->
[call,
- call_reqtmo,
call_against_old_node,
+ call_from_old_node,
+ call_reqtmo,
+ call_against_ei_node,
cast,
send_request,
send_request_fun,
send_request_receive_reqtmo,
send_request_wait_reqtmo,
send_request_check_reqtmo,
- send_request_against_old_node,
+ send_request_against_ei_node,
+ send_request_receive_reqid_collection,
+ send_request_wait_reqid_collection,
+ send_request_check_reqid_collection,
multicall,
multicall_reqtmo,
multicall_recv_opt,
@@ -86,28 +105,61 @@ end_per_group(_GroupName, Config) ->
Config.
call(Config) when is_list(Config) ->
- call_test(Config).
-
-call_test(Config) ->
- call_test(node(), 10000),
- call_test(node(), infinity),
- try
- erpc:call(node(), timer, sleep, [100], 10),
- ct:fail(unexpected)
- catch
- error:{erpc, timeout} ->
+ {ok, Peer, Node} = ?CT_PEER(),
+ call_test(Peer, Node, true, false).
+
+call_against_old_node(Config) when is_list(Config) ->
+ {OldRelName, OldRel} = old_release(),
+ case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {skipped, "Not able to start an OTP "++OldRel++" node"};
+ {ok, Peer, Node} ->
+ compile_and_load_on_node(Node),
+ call_test(Peer, Node, false, false),
ok
- end,
- try
- erpc:call(node(), fun () -> timer:sleep(100) end, 10),
- ct:fail(unexpected)
- catch
- error:{erpc, timeout} ->
+ end.
+
+call_from_old_node(Config) when is_list(Config) ->
+ {OldRelName, OldRel} = old_release(),
+ case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {skipped, "Not able to start an OTP "++OldRel++" node"};
+ {ok, Peer, Node} ->
+ try
+ compile_and_load_on_node(Node),
+ ok = erpc:call(Node, ?MODULE, call_test, [undefined, node(), false, true])
+ after
+ peer:stop(Peer)
+ end
+ end.
+
+call_test(Peer, Node, NodesOfSameRelease, ToTestServer) ->
+ if NodesOfSameRelease ->
+ call_test(Peer, node(), 10000, NodesOfSameRelease, ToTestServer),
+ call_test(Peer, node(), infinity, NodesOfSameRelease, ToTestServer),
+ try
+ erpc:call(node(), timer, sleep, [100], 10),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, timeout} ->
+ ok
+ end,
+ try
+ erpc:call(node(), fun () -> timer:sleep(100) end, 10),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, timeout} ->
+ ok
+ end;
+ true ->
ok
end,
- {ok, Node} = start_node(Config),
- call_test(Node, 10000),
- call_test(Node, infinity),
+ call_test(Peer, Node, 10000, NodesOfSameRelease, ToTestServer),
+ call_test(Peer, Node, infinity, NodesOfSameRelease, ToTestServer),
try
erpc:call(Node, timer, sleep, [100], 10),
ct:fail(unexpected)
@@ -115,32 +167,44 @@ call_test(Config) ->
error:{erpc, timeout} ->
ok
end,
- try
- erpc:call(Node, fun () -> timer:sleep(100) end, 10),
- ct:fail(unexpected)
- catch
- error:{erpc, timeout} ->
- ok
- end,
- try
- erpc:call(Node, erlang, halt, []),
- ct:fail(unexpected)
- catch
- error:{erpc, noconnection} ->
- ok
- end,
- try
- erpc:call(Node, fun () -> erlang:node() end),
- ct:fail(unexpected)
- catch
- error:{erpc, noconnection} ->
+ if NodesOfSameRelease ->
+ try
+ erpc:call(Node, fun () -> timer:sleep(100) end, 10),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, timeout} ->
+ ok
+ end;
+ true ->
ok
end,
- try
- erpc:call(Node, erlang, node, []),
- ct:fail(unexpected)
- catch
- error:{erpc, noconnection} ->
+ if not ToTestServer ->
+ try
+ erpc:call(Node, erlang, halt, []),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, noconnection} ->
+ ok
+ end,
+ if NodesOfSameRelease ->
+ try
+ erpc:call(Node, fun () -> erlang:node() end),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, noconnection} ->
+ ok
+ end;
+ true ->
+ ok
+ end,
+ try
+ erpc:call(Node, erlang, node, []),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, noconnection} ->
+ ok
+ end;
+ true ->
ok
end,
try
@@ -155,8 +219,9 @@ call_test(Config) ->
[] = flush([]),
ok.
-call_test(Node, Timeout) ->
- io:format("call_test(~p, ~p)~n", [Node, Timeout]),
+call_test(Peer, Node, Timeout, NodesOfSameRelease, ToTestServer) ->
+ io:format("call_test(~p, ~p, ~p, ~p, ~p)~n",
+ [Peer, Node, Timeout, NodesOfSameRelease, ToTestServer]),
Node = erpc:call(Node, erlang, node, [], Timeout),
try
erpc:call(Node, erlang, error, [oops|invalid], Timeout),
@@ -179,11 +244,15 @@ call_test(Node, Timeout) ->
exit:{exception, oops} ->
ok
end,
- try
- erpc:call(Node, fun () -> erlang:exit(oops) end, Timeout),
- ct:fail(unexpected)
- catch
- exit:{exception, oops} ->
+ if NodesOfSameRelease ->
+ try
+ erpc:call(Node, fun () -> erlang:exit(oops) end, Timeout),
+ ct:fail(unexpected)
+ catch
+ exit:{exception, oops} ->
+ ok
+ end;
+ true ->
ok
end,
try
@@ -193,38 +262,42 @@ call_test(Node, Timeout) ->
throw:oops ->
ok
end,
- try
- erpc:call(Node, fun () -> erlang:throw(oops) end, Timeout),
- ct:fail(unexpected)
- catch
- throw:oops ->
- ok
- end,
- case {node() == Node, Timeout == infinity} of
- {true, true} ->
- %% This would kill the test since local calls
- %% without timeout is optimized to execute in
- %% calling process itself...
- ok;
- _ ->
- ExitSignal = fun () ->
- exit(self(), oops),
- receive after infinity -> ok end
- end,
+ if NodesOfSameRelease ->
try
- erpc:call(Node, ExitSignal, Timeout),
+ erpc:call(Node, fun () -> erlang:throw(oops) end, Timeout),
ct:fail(unexpected)
catch
- exit:{signal, oops} ->
+ throw:oops ->
ok
end,
- try
- erpc:call(Node, erlang, apply, [ExitSignal, []], Timeout),
- ct:fail(unexpected)
- catch
- exit:{signal, oops} ->
- ok
- end
+ case {node() == Node, Timeout == infinity} of
+ {true, true} ->
+ %% This would kill the test since local calls
+ %% without timeout is optimized to execute in
+ %% calling process itself...
+ ok;
+ _ ->
+ ExitSignal = fun () ->
+ exit(self(), oops),
+ receive after infinity -> ok end
+ end,
+ try
+ erpc:call(Node, ExitSignal, Timeout),
+ ct:fail(unexpected)
+ catch
+ exit:{signal, oops} ->
+ ok
+ end,
+ try
+ erpc:call(Node, erlang, apply, [ExitSignal, []], Timeout),
+ ct:fail(unexpected)
+ catch
+ exit:{signal, oops} ->
+ ok
+ end
+ end;
+ true ->
+ ok
end,
try
erpc:call(Node, ?MODULE, call_func1, [boom], Timeout),
@@ -243,22 +316,26 @@ call_test(Node, Timeout) ->
orelse (A2 == [boom])) ->
ok
end,
- try
- erpc:call(Node, fun () -> ?MODULE:call_func1(boom) end, Timeout),
- ct:fail(unexpected)
- catch
- error:{exception,
- {exception,
- boom,
- [{?MODULE, call_func3, A4, _},
- {?MODULE, call_func2, 1, _}]},
- [{erpc, call, A3, _},
- {?MODULE, call_func1, 1, _},
- {erlang, apply, 2, _}]}
- when ((A3 == 5)
- orelse (A3 == [Node, ?MODULE, call_func2, [boom]]))
- andalso ((A4 == 1)
- orelse (A4 == [boom])) ->
+ if NodesOfSameRelease ->
+ try
+ erpc:call(Node, fun () -> ?MODULE:call_func1(boom) end, Timeout),
+ ct:fail(unexpected)
+ catch
+ error:{exception,
+ {exception,
+ boom,
+ [{?MODULE, call_func3, A4, _},
+ {?MODULE, call_func2, 1, _}]},
+ [{erpc, call, A3, _},
+ {?MODULE, call_func1, 1, _},
+ {erlang, apply, 2, _}]}
+ when ((A3 == 5)
+ orelse (A3 == [Node, ?MODULE, call_func2, [boom]]))
+ andalso ((A4 == 1)
+ orelse (A4 == [boom])) ->
+ ok
+ end;
+ true ->
ok
end,
try
@@ -314,21 +391,27 @@ call_func5(A, B, N, T) when N >= 0 ->
call_func5(_A, _B, _N, _T) ->
erlang:error(badarg).
-call_against_old_node(Config) ->
- case start_22_node(Config) of
- {ok, Node22} ->
- try
- erpc:call(Node22, erlang, node, []),
- ct:fail(unexpected)
- catch
- error:{erpc, notsup} ->
- ok
- end,
- stop_node(Node22),
- ok;
- _ ->
- {skipped, "No OTP 22 available"}
- end.
+call_against_ei_node(Config) when is_list(Config) ->
+ {ok, Node} = start_ei_node(Config),
+ %% Once when erpc:call() brings up the connection
+ %% and once when the connection is up...
+ disconnect(Node),
+ try
+ erpc:call(Node, erlang, node, []),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+ true = lists:member(Node, nodes(hidden)),
+ try
+ erpc:call(Node, erlang, node, []),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+ ok = stop_ei_node(Node).
call_reqtmo(Config) when is_list(Config) ->
Fun = fun (Node, SendMe, Timeout) ->
@@ -340,9 +423,9 @@ call_reqtmo(Config) when is_list(Config) ->
error:{erpc, timeout} -> ok
end
end,
- reqtmo_test(Config, Fun).
+ reqtmo_test(Fun).
-reqtmo_test(Config, Test) ->
+reqtmo_test(Test) ->
%% Tests that we time out in time also when the request itself
%% does not get through. A typical issue we have had
%% in the past, is that the timeout has not triggered until
@@ -352,7 +435,7 @@ reqtmo_test(Config, Test) ->
WaitBlock = 100,
BlockTime = 1000,
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
erpc:call(Node, erts_debug, set_internal_state, [available_internal_state,
true]),
@@ -378,7 +461,7 @@ reqtmo_test(Config, Test) ->
after 0 -> ok
end,
- stop_node(Node),
+ peer:stop(Peer),
{comment,
"Timeout = " ++ integer_to_list(Timeout)
@@ -425,7 +508,7 @@ cast(Config) when is_list(Config) ->
receive
{a_fun, Ok1} -> ok
end,
- {ok, Node} = start_node(Config),
+ {ok, _Peer, Node} = ?CT_PEER(),
Ok2 = make_ref(),
ok = erpc:cast(Node, erlang, send, [Me, {mfa, Ok2}]),
receive
@@ -446,28 +529,52 @@ cast(Config) when is_list(Config) ->
receive after 1000 -> ok end,
[] = flush([]),
- case start_22_node(Config) of
- {ok, Node22} ->
- ok = erpc:cast(Node, erlang, send, [Me, wont_reach_me]),
- ok = erpc:cast(Node, fun () -> Me ! wont_reach_me end),
+ {ok, EiNode} = start_ei_node(Config),
+ %% Both when erpc:cast() brings up the connection
+ %% and when the connection is up...
+ disconnect(EiNode),
+
+ ok = erpc:cast(EiNode, erlang, send, [Me, wont_reach_me]),
+ ok = erpc:cast(EiNode, fun () -> Me ! wont_reach_me end),
+
+ wait_until(fun () -> lists:member(EiNode, nodes(hidden)) end),
+
+ ok = erpc:cast(EiNode, erlang, send, [Me, wont_reach_me]),
+ ok = erpc:cast(EiNode, fun () -> Me ! wont_reach_me end),
+
+ receive
+ Msg -> ct:fail({unexpected_message, Msg})
+ after
+ 2000 -> ok
+ end,
+ ok = stop_ei_node(EiNode),
+
+ {OldRelName, OldRel} = old_release(),
+ case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {comment, "Not tested against OTP "++OldRel++" node"};
+ {ok, _OldPeer, OldNode} ->
+ Ok3 = make_ref(),
+ ok = erpc:cast(OldNode, erlang, send, [Me, {mfa, Ok3}]),
receive
- Msg -> ct:fail({unexpected_message, Msg})
- after
- 2000 -> ok
+ {mfa, Ok3} -> ok
end,
- stop_node(Node22),
- {comment, "Tested against OTP 22 as well"};
- _ ->
- {comment, "No tested against OTP 22"}
+ ok = erpc:cast(OldNode, erlang, halt, []),
+
+ ok = erpc:cast(OldNode, erlang, send, [Me, wont_reach_me]),
+
+ receive after 1000 -> ok end,
+ [] = flush([]),
+ {comment, "Also tested against OTP "++OldRel++" node"}
end.
send_request(Config) when is_list(Config) ->
%% Note: First part of nodename sets response delay in seconds.
- PA = filename:dirname(code:which(?MODULE)),
- NodeArgs = [{args,"-pa "++ PA}],
- {ok,Node1} = test_server:start_node('1_erpc_SUITE_call', slave, NodeArgs),
- {ok,Node2} = test_server:start_node('10_erpc_SUITE_call', slave, NodeArgs),
- {ok,Node3} = test_server:start_node('20_erpc_SUITE_call', slave, NodeArgs),
+ {ok, _Peer1, Node1} = ?CT_PEER(["-erpc_test_delay", "1"]),
+ {ok, _Peer2, Node2} = ?CT_PEER(["-erpc_test_delay", "10"]),
+ {ok, _Peer3, Node3} = ?CT_PEER(["-erpc_test_delay", "20"]),
ReqId1 = erpc:send_request(Node1, ?MODULE, f, []),
ReqId2 = erpc:send_request(Node2, ?MODULE, f, []),
ReqId3 = erpc:send_request(Node3, ?MODULE, f, []),
@@ -512,13 +619,9 @@ send_request(Config) when is_list(Config) ->
after 0 -> ok
end,
- stop_node(Node1),
- stop_node(Node2),
- stop_node(Node3),
-
[] = flush([]),
- {ok, Node4} = start_node(Config),
+ {ok, _Peer4, Node4} = ?CT_PEER(),
ReqId6 = erpc:send_request(Node4, erlang, node, []),
@@ -551,32 +654,83 @@ send_request(Config) when is_list(Config) ->
[] = flush([]),
- case start_22_node(Config) of
- {ok, Node5} ->
- ReqId9 = erpc:send_request(Node5, erlang, node, []),
+ {ok, Node5} = start_ei_node(Config),
+ %% Once when erpc:send_request() brings up the connection
+ %% and once when the connection is up...
+ disconnect(Node5),
+ ReqId14 = erpc:send_request(Node5, erlang, node, []),
+ try
+ erpc:receive_response(ReqId14),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} -> ok
+ end,
+ true = lists:member(Node5, nodes(hidden)),
+ ReqId15 = erpc:send_request(Node5, erlang, node, []),
+ try
+ erpc:receive_response(ReqId15),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} -> ok
+ end,
+
+ ok = stop_ei_node(Node5),
+
+ [] = flush([]),
+
+ {OldRelName, OldRel} = old_release(),
+ case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {comment, "Not tested against OTP "++OldRel++" node"};
+ {ok, _OldPeer, OldNode} ->
+
+ ReqId9 = erpc:send_request(OldNode, erlang, node, []),
+
+ no_response = erpc:check_response({response, OldNode}, ReqId9),
+ no_response = erpc:check_response(ReqId6, ReqId9),
+ receive
+ Msg3 ->
+ {response, OldNode} = erpc:check_response(Msg3, ReqId9)
+ end,
+
+ ReqId10 = erpc:send_request(OldNode, erlang, node, []),
+
+ OldNode = erpc:receive_response(ReqId10),
+
+ ReqId11 = erpc:send_request(OldNode, erlang, node, []),
+ {response, OldNode} = erpc:wait_response(ReqId11, infinity),
+
+ ReqId12 = erpc:send_request(OldNode, erlang, halt, []),
try
- erpc:receive_response(ReqId9),
+ erpc:receive_response(ReqId12),
ct:fail(unexpected)
catch
- error:{erpc, notsup} -> ok
+ error:{erpc, noconnection} -> ok
end,
- stop_node(Node5),
+ ReqId13 = erpc:send_request(OldNode, erlang, node, []),
+ receive
+ Msg4 ->
+ try
+ erpc:check_response(Msg4, ReqId13),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, noconnection} ->
+ ok
+ end
+ end,
[] = flush([]),
-
- ok;
- _ ->
- {comment, "No test against OTP 22 node performed"}
+ {comment, "Also tested against OTP "++OldRel++" node"}
end.
send_request_fun(Config) when is_list(Config) ->
%% Note: First part of nodename sets response delay in seconds.
- PA = filename:dirname(code:which(?MODULE)),
- NodeArgs = [{args,"-pa "++ PA}],
- {ok,Node1} = test_server:start_node('1_erpc_SUITE_call', slave, NodeArgs),
- {ok,Node2} = test_server:start_node('10_erpc_SUITE_call', slave, NodeArgs),
- {ok,Node3} = test_server:start_node('20_erpc_SUITE_call', slave, NodeArgs),
+ {ok, _Peer1, Node1} = ?CT_PEER(["-erpc_test_delay", "1"]),
+ {ok, _Peer2, Node2} = ?CT_PEER(["-erpc_test_delay", "10"]),
+ {ok, _Peer3, Node3} = ?CT_PEER(["-erpc_test_delay", "20"]),
ReqId1 = erpc:send_request(Node1, fun () -> ?MODULE:f() end),
ReqId2 = erpc:send_request(Node2, fun () -> ?MODULE:f() end),
ReqId3 = erpc:send_request(Node3, fun () -> ?MODULE:f() end),
@@ -622,11 +776,7 @@ send_request_fun(Config) when is_list(Config) ->
after 0 -> ok
end,
- stop_node(Node1),
- stop_node(Node2),
- stop_node(Node3),
-
- {ok, Node4} = start_node(Config),
+ {ok, _Peer4, Node4} = ?CT_PEER(),
ReqId6 = erpc:send_request(Node4, fun () -> erlang:node() end),
@@ -659,24 +809,27 @@ send_request_fun(Config) when is_list(Config) ->
[] = flush([]),
- case start_22_node(Config) of
- {ok, Node5} ->
- ReqId9 = erpc:send_request(Node5, fun () -> erlang:node() end),
- try
- erpc:receive_response(ReqId9),
- ct:fail(unexpected)
- catch
- error:{erpc, notsup} -> ok
- end,
-
- stop_node(Node5),
-
- [] = flush([]),
+ {ok, Node5} = start_ei_node(Config),
+ %% Once when erpc:send_request() brings up the connection
+ %% and once when the connection is up...
+ disconnect(Node5),
+ ReqId9 = erpc:send_request(Node5, fun () -> erlang:node() end),
+ try
+ erpc:receive_response(ReqId9),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} -> ok
+ end,
+ true = lists:member(Node5, nodes(hidden)),
+ ReqId10 = erpc:send_request(Node5, fun () -> erlang:node() end),
+ try
+ erpc:receive_response(ReqId10),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} -> ok
+ end,
- ok;
- _ ->
- {comment, "No test against OTP 22 node performed"}
- end.
+ ok = stop_ei_node(Node5).
send_request_receive_reqtmo(Config) when is_list(Config) ->
@@ -690,7 +843,7 @@ send_request_receive_reqtmo(Config) when is_list(Config) ->
error:{erpc, timeout} -> ok
end
end,
- reqtmo_test(Config, Fun).
+ reqtmo_test(Fun).
send_request_wait_reqtmo(Config) when is_list(Config) ->
Fun = fun (Node, SendMe, Timeout) ->
@@ -706,7 +859,7 @@ send_request_wait_reqtmo(Config) when is_list(Config) ->
error:{erpc, timeout} -> ok
end
end,
- reqtmo_test(Config, Fun).
+ reqtmo_test(Fun).
send_request_check_reqtmo(Config) when is_list(Config) ->
Fun = fun (Node, SendMe, Timeout) ->
@@ -723,60 +876,417 @@ send_request_check_reqtmo(Config) when is_list(Config) ->
error:{erpc, timeout} -> ok
end
end,
- reqtmo_test(Config, Fun).
-
-send_request_against_old_node(Config) when is_list(Config) ->
- case start_22_node(Config) of
- {ok, Node22} ->
- RID1 = erpc:send_request(Node22, erlang, node, []),
- RID2 = erpc:send_request(Node22, erlang, node, []),
- RID3 = erpc:send_request(Node22, erlang, node, []),
- try
- erpc:receive_response(RID1),
+ reqtmo_test(Fun).
+
+send_request_against_ei_node(Config) when is_list(Config) ->
+ {ok, EiNode} = start_ei_node(Config),
+ %% Once when erpc:send_request() brings up the connection
+ %% and once when the connection is up...
+ disconnect(EiNode),
+ RID1 = erpc:send_request(EiNode, erlang, node, []),
+ RID2 = erpc:send_request(EiNode, erlang, node, []),
+ RID3 = erpc:send_request(EiNode, erlang, node, []),
+ try
+ erpc:receive_response(RID1),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+ try
+ erpc:wait_response(RID2, infinity),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+ try
+ receive
+ Msg ->
+ erpc:check_response(Msg, RID3),
ct:fail(unexpected)
- catch
- error:{erpc, notsup} ->
- ok
- end,
- try
- erpc:wait_response(RID2, infinity),
+ end
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+
+ true = lists:member(EiNode, nodes(hidden)),
+
+ RID1u = erpc:send_request(EiNode, erlang, node, []),
+ RID2u = erpc:send_request(EiNode, erlang, node, []),
+ RID3u = erpc:send_request(EiNode, erlang, node, []),
+ try
+ erpc:receive_response(RID1u),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+ try
+ erpc:wait_response(RID2u, infinity),
+ ct:fail(unexpected)
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+ try
+ receive
+ Msgu ->
+ erpc:check_response(Msgu, RID3u),
ct:fail(unexpected)
- catch
- error:{erpc, notsup} ->
- ok
- end,
- try
- receive
- Msg ->
- erpc:check_response(Msg, RID3),
- ct:fail(unexpected)
- end
- catch
- error:{erpc, notsup} ->
- ok
- end,
- stop_node(Node22),
- ok;
- _ ->
- {skipped, "No OTP 22 available"}
- end.
+ end
+ catch
+ error:{erpc, notsup} ->
+ ok
+ end,
+
+ ok = stop_ei_node(EiNode).
+
+send_request_receive_reqid_collection(Config) when is_list(Config) ->
+ {ok, _P, N} = ?CT_PEER(#{connection => 0}),
+ send_request_receive_reqid_collection_success(N),
+ send_request_receive_reqid_collection_timeout(N),
+ send_request_receive_reqid_collection_error(N),
+ ok.
+
+send_request_receive_reqid_collection_success(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 400 -> 400 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = erpc:reqids_size(ReqIdC1),
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 1 -> 1 end end, req2, ReqIdC1),
+ 2 = erpc:reqids_size(ReqIdC2),
+
+ ReqIdC3 = erpc:send_request(N, fun () -> receive after 200 -> 200 end end, req3, ReqIdC2),
+ 3 = erpc:reqids_size(ReqIdC3),
+
+ {1, req2, ReqIdC4} = erpc:receive_response(ReqIdC3, infinity, true),
+ 2 = erpc:reqids_size(ReqIdC4),
+
+ {200, req3, ReqIdC5} = erpc:receive_response(ReqIdC4, 7654, true),
+ 1 = erpc:reqids_size(ReqIdC5),
+
+ {400, req1, ReqIdC6} = erpc:receive_response(ReqIdC5, 5000, true),
+ 0 = erpc:reqids_size(ReqIdC6),
+
+ no_request = erpc:receive_response(ReqIdC6, 5000, true),
+
+ 0 = erpc:receive_response(ReqId0),
+
+ ok.
+
+send_request_receive_reqid_collection_timeout(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 1000 -> 1000 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 1 -> 1 end end, req2, ReqIdC1),
+
+ ReqId3 = erpc:send_request(N, fun () -> receive after 500 -> 500 end end),
+ ReqIdC3 = erpc:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {1, req2, ReqIdC4} = erpc:receive_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = erpc:reqids_size(ReqIdC4),
+
+ try not_valid = erpc:receive_response(ReqIdC4, {abs, Deadline}, true)
+ catch error:{erpc, timeout} -> ok
+ end,
+
+ Abandoned = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Abandoned = lists:sort(erpc:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were abandoned...
+ try not_valid = erpc:receive_response(ReqIdC4, {abs, Deadline+1000}, false)
+ catch error:{erpc, timeout} -> ok
+ end,
+
+ 0 = erpc:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_error(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 600 -> 600 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = erpc:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:{erpc, badarg} -> ok
+ end,
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 800 -> erlang:halt() end end, req2, ReqIdC1),
+ ReqIdC3 = erpc:send_request(N, fun () -> receive after 200 -> error(errored) end end, req3, ReqIdC2),
+ ReqIdC4 = erpc:send_request(N, fun () -> exit(exited) end, req4, ReqIdC3),
+ ReqIdC5 = erpc:send_request(N, fun () -> receive after 400 -> throw(thrown) end end, req5, ReqIdC4),
+
+ 5 = erpc:reqids_size(ReqIdC5),
+
+ ReqIdC6 = try not_valid = erpc:receive_response(ReqIdC5, infinity, true)
+ catch exit:{{exception, exited}, req4, RIC6} -> RIC6
+ end,
+
+ 4 = erpc:reqids_size(ReqIdC6),
+
+ try not_valid = erpc:receive_response(ReqIdC6, 2000, false)
+ catch error:{{exception, errored, _Stk}, req3, _} -> ok
+ end,
+
+ try not_valid = erpc:receive_response(ReqIdC6, infinity, false)
+ catch throw:{thrown, req5, _} -> ok
+ end,
+
+ {600, req1, ReqIdC6} = erpc:receive_response(ReqIdC6, infinity, false),
+
+ try not_valid = erpc:receive_response(ReqIdC6, 5000, false)
+ catch error:{{erpc, noconnection}, req2, ReqIdC6} -> ok
+ end,
+
+ 0 = erpc:receive_response(ReqId0),
+
+ ok.
+
+send_request_wait_reqid_collection(Config) when is_list(Config) ->
+ {ok, _P, N} = ?CT_PEER(#{connection => 0}),
+ send_request_wait_reqid_collection_success(N),
+ send_request_wait_reqid_collection_timeout(N),
+ send_request_wait_reqid_collection_error(N),
+ ok.
+
+send_request_wait_reqid_collection_success(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 400 -> 400 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = erpc:reqids_size(ReqIdC1),
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 1 -> 1 end end, req2, ReqIdC1),
+ 2 = erpc:reqids_size(ReqIdC2),
+
+ ReqIdC3 = erpc:send_request(N, fun () -> receive after 200 -> 200 end end, req3, ReqIdC2),
+ 3 = erpc:reqids_size(ReqIdC3),
+
+ {{response, 1}, req2, ReqIdC4} = erpc:wait_response(ReqIdC3, infinity, true),
+ 2 = erpc:reqids_size(ReqIdC4),
+
+ {{response, 200}, req3, ReqIdC5} = erpc:wait_response(ReqIdC4, 7654, true),
+ 1 = erpc:reqids_size(ReqIdC5),
+
+ {{response, 400}, req1, ReqIdC6} = erpc:wait_response(ReqIdC5, 5000, true),
+ 0 = erpc:reqids_size(ReqIdC6),
+
+ no_request = erpc:wait_response(ReqIdC6, 5000, true),
+
+ {response, 0} = erpc:wait_response(ReqId0),
+
+ ok.
+
+send_request_wait_reqid_collection_timeout(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 1000 -> 1000 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 1 -> 1 end end, req2, ReqIdC1),
+
+ ReqId3 = erpc:send_request(N, fun () -> receive after 500 -> 500 end end),
+ ReqIdC3 = erpc:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{response, 1}, req2, ReqIdC4} = erpc:wait_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = erpc:reqids_size(ReqIdC4),
+
+ no_response = erpc:wait_response(ReqIdC4, {abs, Deadline}, true),
+
+ Unhandled = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Unhandled = lists:sort(erpc:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were not abandoned...
+ {{response, 500}, req3, ReqIdC4} = erpc:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+ {{response, 1000}, req1, ReqIdC4} = erpc:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+
+ {response, 0} = erpc:wait_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection_error(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 600 -> 600 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = erpc:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:{erpc, badarg} -> ok
+ end,
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 800 -> erlang:halt() end end, req2, ReqIdC1),
+ ReqIdC3 = erpc:send_request(N, fun () -> receive after 200 -> error(errored) end end, req3, ReqIdC2),
+ ReqIdC4 = erpc:send_request(N, fun () -> exit(exited) end, req4, ReqIdC3),
+ ReqIdC5 = erpc:send_request(N, fun () -> receive after 400 -> throw(thrown) end end, req5, ReqIdC4),
+
+ 5 = erpc:reqids_size(ReqIdC5),
+
+ ReqIdC6 = try not_valid = erpc:wait_response(ReqIdC5, infinity, true)
+ catch exit:{{exception, exited}, req4, RIC6} -> RIC6
+ end,
+
+ 4 = erpc:reqids_size(ReqIdC6),
+
+ try not_valid = erpc:wait_response(ReqIdC6, 2000, false)
+ catch error:{{exception, errored, _Stk}, req3, _} -> ok
+ end,
+
+ try not_valid = erpc:wait_response(ReqIdC6, infinity, false)
+ catch throw:{thrown, req5, _} -> ok
+ end,
+
+ {{response, 600}, req1, ReqIdC6} = erpc:wait_response(ReqIdC6, infinity, false),
+
+ try not_valid = erpc:wait_response(ReqIdC6, 5000, false)
+ catch error:{{erpc, noconnection}, req2, ReqIdC6} -> ok
+ end,
+
+ {response, 0} = erpc:wait_response(ReqId0),
+
+ ok.
+
+send_request_check_reqid_collection(Config) when is_list(Config) ->
+ {ok, _P, N} = ?CT_PEER(#{connection => 0}),
+ send_request_check_reqid_collection_success(N),
+ send_request_check_reqid_collection_error(N),
+ ok.
+
+send_request_check_reqid_collection_success(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqIdC1 = erpc:send_request(N, fun () -> receive after 600 -> 600 end end, req1, ReqIdC0),
+ 1 = erpc:reqids_size(ReqIdC1),
+
+ ReqId2 = erpc:send_request(N, fun () -> receive after 200 -> 200 end end),
+ ReqIdC2 = erpc:reqids_add(ReqId2, req2, ReqIdC1),
+ 2 = erpc:reqids_size(ReqIdC2),
+
+ ReqIdC3 = erpc:send_request(N, fun () -> receive after 400 -> 400 end end, req3, ReqIdC2),
+ 3 = erpc:reqids_size(ReqIdC3),
+
+ Msg0 = next_msg(),
+
+ no_response = erpc:check_response(Msg0, ReqIdC3, true),
+
+ {{response, 200}, req2, ReqIdC4} = erpc:check_response(next_msg(), ReqIdC3, true),
+ 2 = erpc:reqids_size(ReqIdC4),
+
+ {{response, 400}, req3, ReqIdC5} = erpc:check_response(next_msg(), ReqIdC4, true),
+ 1 = erpc:reqids_size(ReqIdC5),
+
+ {{response, 600}, req1, ReqIdC6} = erpc:check_response(next_msg(), ReqIdC5, true),
+ 0 = erpc:reqids_size(ReqIdC6),
+
+ no_request = erpc:check_response(Msg0, ReqIdC6, true),
+
+ {response, 0} = erpc:check_response(Msg0, ReqId0),
+
+ ok.
+
+send_request_check_reqid_collection_error(N) ->
+
+ ReqId0 = erpc:send_request(N, fun () -> 0 end),
+
+ ReqIdC0 = erpc:reqids_new(),
+
+ ReqId1 = erpc:send_request(N, fun () -> receive after 600 -> 600 end end),
+ ReqIdC1 = erpc:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = erpc:send_request(N, fun () -> receive after 800 -> erlang:halt() end end, req2, ReqIdC1),
+
+ ReqIdC3 = erpc:send_request(N, fun () -> receive after 200 -> error(errored) end end, req3, ReqIdC2),
+
+ ReqIdC4 = erpc:send_request(N, fun () -> exit(exited) end, req4, ReqIdC3),
+
+ ReqIdC5 = erpc:send_request(N, fun () -> receive after 400 -> throw(thrown) end end, req5, ReqIdC4),
+
+ 5 = erpc:reqids_size(ReqIdC5),
+
+ Msg0 = next_msg(),
+
+ no_response = erpc:check_response(Msg0, ReqIdC5, true),
+
+ ReqIdC6 = try not_valid = erpc:check_response(next_msg(), ReqIdC5, true)
+ catch exit:{{exception, exited}, req4, RIC6} -> RIC6
+ end,
+
+ try not_valid = erpc:check_response(next_msg(), ReqIdC6, false)
+ catch error:{{exception, errored, _Stk}, req3, ReqIdC6} -> ok
+ end,
+
+ try not_valid = erpc:check_response(next_msg(), ReqIdC6, false)
+ catch throw:{thrown, req5, ReqIdC6} -> ok
+ end,
+
+ {{response, 600}, req1, ReqIdC6} = erpc:check_response(next_msg(), ReqIdC6, false),
+
+ try not_valid = erpc:check_response(next_msg(), ReqIdC6, false)
+ catch error:{{erpc, noconnection}, req2, ReqIdC6} -> ok
+ end,
+
+ {response, 0} = erpc:check_response(Msg0, ReqId0),
+
+ ok.
multicall(Config) ->
- {ok, Node1} = start_peer_node(Config),
- {ok, Node2} = start_peer_node(Config),
- {Node3, Node3Res} = case start_22_node(Config) of
- {ok, N3} ->
- {N3, {error, {erpc, notsup}}};
- _ ->
- {ok, N3} = start_peer_node(Config),
- stop_node(N3),
- {N3, {error, {erpc, noconnection}}}
- end,
- {ok, Node4} = start_peer_node(Config),
- {ok, Node5} = start_peer_node(Config),
- stop_node(Node2),
- io:format("Node1=~p~nNode2=~p~nNode3=~p~nNode4=~p~nNode5=~p~n",
- [Node1, Node2, Node3, Node4, Node5]),
+ {ok, _Peer1, Node1} = ?CT_PEER(#{connection => 0}),
+ {ok, Peer2, Node2} = ?CT_PEER(#{connection => 0}),
+ {ok, Node3} = start_ei_node(Config),
+ %% Test once when erpc:multicall() brings up the connection...
+ disconnect(Node3),
+ Node3Res = {error, {erpc, notsup}},
+ {ok, _Peer4, Node4} = ?CT_PEER(#{connection => 0}),
+ {ok, _Peer5, Node5} = ?CT_PEER(#{connection => 0}),
+ {OldRelName, OldRel} = old_release(),
+ {OldTested, {ok, _Peer6, Node6}}
+ = case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {false, ?CT_PEER(#{connection => 0})};
+ {ok, _OldPeer, OldNode} = OldNodeRes ->
+ compile_and_load_on_node(OldNode),
+ {true, OldNodeRes}
+ end,
+ peer:stop(Peer2),
+ io:format("Node1=~p~nNode2=~p~nNode3=~p~nNode4=~p~nNode5=~p~nNode6=~p~n",
+ [Node1, Node2, Node3, Node4, Node5, Node6]),
ThisNode = node(),
Nodes = [ThisNode, Node1, Node2, Node3, Node4, Node5],
@@ -787,8 +1297,9 @@ multicall(Config) ->
Node3Res,
{ok, Node4},
{ok, Node5},
- {error, {erpc, noconnection}}]
- = erpc:multicall(Nodes ++ [badnodename], erlang, node, []),
+ {error, {erpc, noconnection}},
+ {ok, Node6}]
+ = erpc:multicall(Nodes ++ [badnodename] ++ [Node6], erlang, node, []),
[{ok, ThisNode},
{ok, Node1},
@@ -837,16 +1348,18 @@ multicall(Config) ->
{error, {erpc, noconnection}},
Node3Res,
{ok, Node4},
- {ok, Node5}]
- = erpc:multicall(Nodes, erlang, node, []),
+ {ok, Node5},
+ {ok, Node6}]
+ = erpc:multicall(Nodes ++ [Node6], erlang, node, []),
[{ok, ThisNode},
{ok, Node1},
{error, {erpc, noconnection}},
Node3Res,
{ok, Node4},
- {ok, Node5}]
- = erpc:multicall(Nodes, erlang, node, [], 60000),
+ {ok, Node5},
+ {ok, Node6}]
+ = erpc:multicall(Nodes ++ [Node6], erlang, node, [], 60000),
[{throw, ThisNode},
{throw, Node1},
@@ -872,12 +1385,15 @@ multicall(Config) ->
{error, {erpc, timeout}},
{error, {erpc, timeout}},
{error, {erpc, timeout}},
+
+ {error, {erpc, timeout}},
{error, {erpc, timeout}},
{error, {erpc, noconnection}},
Node3Res,
{error, {erpc, timeout}},
+ {error, {erpc, timeout}},
{error, {erpc, timeout}}]
- = erpc:multicall(Nodes++Nodes, timer, sleep, [2000], 500),
+ = erpc:multicall(Nodes++[Node6]++Nodes++[Node6], timer, sleep, [2000], 500),
E0 = erlang:monotonic_time(millisecond),
T0 = E0 - S0,
io:format("T0=~p~n", [T0]),
@@ -891,12 +1407,15 @@ multicall(Config) ->
{ok, ok},
{ok, ok},
{ok, ok},
+
+ {ok, ok},
{ok, ok},
{error, {erpc, noconnection}},
Node3Res,
{ok, ok},
+ {ok, ok},
{ok, ok}]
- = erpc:multicall(Nodes++Nodes, timer, sleep, [2000]),
+ = erpc:multicall(Nodes++[Node6]++Nodes++[Node6], timer, sleep, [2000]),
E1 = erlang:monotonic_time(millisecond),
T1 = E1 - S1,
io:format("T1=~p~n", [T1]),
@@ -910,12 +1429,15 @@ multicall(Config) ->
{ok, ok},
{ok, ok},
{ok, ok},
+
+ {ok, ok},
{ok, ok},
{error, {erpc, noconnection}},
Node3Res,
{ok, ok},
+ {ok, ok},
{ok, ok}]
- = erpc:multicall(Nodes++Nodes, timer, sleep, [2000], 3000),
+ = erpc:multicall(Nodes++[Node6]++Nodes++[Node6], timer, sleep, [2000], 3000),
E2 = erlang:monotonic_time(millisecond),
T2 = E2 - S2,
io:format("T2=~p~n", [T2]),
@@ -927,13 +1449,16 @@ multicall(Config) ->
Node3Res,
{ok, Node4},
{ok, Node5},
+ {ok, Node6},
+
{ok, ThisNode},
{ok, Node1},
{error, {erpc, noconnection}},
Node3Res,
{ok, Node4},
- {ok, Node5}]
- = erpc:multicall(Nodes++Nodes, erlang, node, []),
+ {ok, Node5},
+ {ok, Node6}]
+ = erpc:multicall(Nodes++[Node6]++Nodes++[Node6], erlang, node, []),
[{ok, ThisNode},
{ok, Node1},
@@ -941,13 +1466,16 @@ multicall(Config) ->
Node3Res,
{ok, Node4},
{ok, Node5},
+ {ok, Node6},
+
{ok, ThisNode},
{ok, Node1},
{error, {erpc, noconnection}},
Node3Res,
{ok, Node4},
- {ok, Node5}]
- = erpc:multicall(Nodes++Nodes, erlang, node, [], 60000),
+ {ok, Node5},
+ {ok, Node6}]
+ = erpc:multicall(Nodes++[Node6]++Nodes++[Node6], erlang, node, [], 60000),
[{ok, ThisNode},
{ok, Node1},
@@ -962,16 +1490,18 @@ multicall(Config) ->
{error, {erpc, noconnection}},
Node3Res,
BlingError,
- BlingError]
- = erpc:multicall(Nodes, ?MODULE, call_func2, [bling]),
+ BlingError,
+ OldBlingError]
+ = erpc:multicall(Nodes++[Node6], ?MODULE, call_func2, [bling]),
[BlingError,
BlingError,
{error, {erpc, noconnection}},
Node3Res,
BlingError,
- BlingError]
- = erpc:multicall(Nodes, ?MODULE, call_func2, [bling], 60000),
+ BlingError,
+ OldBlingError]
+ = erpc:multicall(Nodes++[Node6], ?MODULE, call_func2, [bling], 60000),
{error, {exception,
bling,
@@ -979,21 +1509,29 @@ multicall(Config) ->
{?MODULE, call_func2, 1, _}]}} = BlingError,
true = (A == 1) orelse (A == [bling]),
+ {error, {exception,
+ bling,
+ [{?MODULE, call_func3, OldA, _},
+ {?MODULE, call_func2, 1, _}]}} = OldBlingError,
+ true = (OldA == 1) orelse (OldA == [bling]),
+
[{error, {exception, blong, [{erlang, error, [blong], _}]}},
{error, {exception, blong, [{erlang, error, [blong], _}]}},
{error, {erpc, noconnection}},
Node3Res,
{error, {exception, blong, [{erlang, error, [blong], _}]}},
+ {error, {exception, blong, [{erlang, error, [blong], _}]}},
{error, {exception, blong, [{erlang, error, [blong], _}]}}]
- = erpc:multicall(Nodes, erlang, error, [blong]),
+ = erpc:multicall(Nodes++[Node6], erlang, error, [blong]),
[{error, {exception, blong, [{erlang, error, [blong], _}]}},
{error, {exception, blong, [{erlang, error, [blong], _}]}},
{error, {erpc, noconnection}},
Node3Res,
{error, {exception, blong, [{erlang, error, [blong], _}]}},
+ {error, {exception, blong, [{erlang, error, [blong], _}]}},
{error, {exception, blong, [{erlang, error, [blong], _}]}}]
- = erpc:multicall(Nodes, erlang, error, [blong], 60000),
+ = erpc:multicall(Nodes++[Node6], erlang, error, [blong], 60000),
SlowNode4 = fun () ->
case node() of
@@ -1060,22 +1598,23 @@ multicall(Config) ->
[{error, {erpc, noconnection}},
Node3Res,
{error, {erpc, noconnection}},
+ {error, {erpc, noconnection}},
{error, {erpc, noconnection}}]
- = erpc:multicall([Node2, Node3, Node4, Node5], erlang, halt, []),
+ = erpc:multicall([Node2, Node3, Node4, Node5, Node6], erlang, halt, []),
[] = flush([]),
- stop_node(Node3),
- case Node3Res of
- {error, {erpc, notsup}} ->
- {comment, "Tested against an OTP 22 node as well"};
- _ ->
- {comment, "No OTP 22 node available; i.e., only testing against current release"}
+ ok = stop_ei_node(Node3),
+ case OldTested of
+ false ->
+ {comment, "Not tested against OTP "++OldRel++" node"};
+ true ->
+ {comment, "Also tested against OTP "++OldRel++" node"}
end.
multicall_reqtmo(Config) when is_list(Config) ->
- {ok, QuickNode1} = start_node(Config),
- {ok, QuickNode2} = start_node(Config),
+ {ok, Peer1, QuickNode1} = ?CT_PEER(),
+ {ok, Peer2, QuickNode2} = ?CT_PEER(),
Fun = fun (Node, SendMe, Timeout) ->
Me = self(),
SlowSend = fun () ->
@@ -1091,17 +1630,17 @@ multicall_reqtmo(Config) when is_list(Config) ->
erlang, apply, [SlowSend, []],
Timeout)
end,
- Res = reqtmo_test(Config, Fun),
- stop_node(QuickNode1),
- stop_node(QuickNode2),
+ Res = reqtmo_test(Fun),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
Res.
multicall_recv_opt(Config) when is_list(Config) ->
Loops = 1000,
HugeMsgQ = 500000,
process_flag(message_queue_data, off_heap),
- {ok, Node1} = start_node(Config),
- {ok, Node2} = start_node(Config),
+ {ok, Peer1, Node1} = ?CT_PEER(),
+ {ok, Peer2, Node2} = ?CT_PEER(),
ExpRes = [{ok, node()}, {ok, Node1}, {ok, Node2}],
Nodes = [node(), Node1, Node2],
Fun = fun () -> erlang:node() end,
@@ -1113,8 +1652,8 @@ multicall_recv_opt(Config) when is_list(Config) ->
Huge = time_multicall(ExpRes, Nodes, Fun, infinity, Loops),
io:format("Time with huge message queue: ~p microsecond~n",
[erlang:convert_time_unit(Huge, native, microsecond)]),
- stop_node(Node1),
- stop_node(Node2),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
Q = Huge / Empty,
HugeMsgQ = flush_msgq(),
case Q > 10 of
@@ -1128,9 +1667,9 @@ multicall_recv_opt2(Config) when is_list(Config) ->
Loops = 1000,
HugeMsgQ = 500000,
process_flag(message_queue_data, off_heap),
- {ok, Node1} = start_node(Config),
- stop_node(Node1),
- {ok, Node2} = start_node(Config),
+ {ok, Peer1, Node1} = ?CT_PEER(),
+ peer:stop(Peer1),
+ {ok, Peer2, Node2} = ?CT_PEER(),
ExpRes = [{ok, node()}, {error, {erpc, noconnection}}, {ok, Node2}],
Nodes = [node(), Node1, Node2],
Fun = fun () -> erlang:node() end,
@@ -1142,7 +1681,7 @@ multicall_recv_opt2(Config) when is_list(Config) ->
Huge = time_multicall(ExpRes, Nodes, Fun, infinity, Loops),
io:format("Time with huge message queue: ~p microsecond~n",
[erlang:convert_time_unit(Huge, native, microsecond)]),
- stop_node(Node2),
+ peer:stop(Peer2),
Q = Huge / Empty,
HugeMsgQ = flush_msgq(),
case Q > 10 of
@@ -1156,9 +1695,9 @@ multicall_recv_opt3(Config) when is_list(Config) ->
Loops = 1000,
HugeMsgQ = 500000,
process_flag(message_queue_data, off_heap),
- {ok, Node1} = start_node(Config),
- stop_node(Node1),
- {ok, Node2} = start_node(Config),
+ {ok, Peer1, Node1} = ?CT_PEER(),
+ peer:stop(Peer1),
+ {ok, Peer2, Node2} = ?CT_PEER(),
Nodes = [node(), Node1, Node2],
Fun = fun () -> erlang:node() end,
_Warmup = time_multicall(undefined, Nodes, Fun, infinity, Loops div 10),
@@ -1169,7 +1708,7 @@ multicall_recv_opt3(Config) when is_list(Config) ->
Huge = time_multicall(undefined, Nodes, Fun, 0, Loops),
io:format("Time with huge message queue: ~p microsecond~n",
[erlang:convert_time_unit(Huge, native, microsecond)]),
- stop_node(Node2),
+ peer:stop(Peer2),
Q = Huge / Empty,
HugeMsgQ = flush_msgq(),
case Q > 10 of
@@ -1194,10 +1733,20 @@ do_time_multicall(Expect, Nodes, Fun, Tmo, N) ->
do_time_multicall(Expect, Nodes, Fun, Tmo, N-1).
multicast(Config) when is_list(Config) ->
- {ok, Node} = start_node(Config),
+ {ok, _Peer, Node} = ?CT_PEER(),
+ {OldRelName, OldRel} = old_release(),
+ {OldTested, {ok, _OldPeer, OldNode}}
+ = case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {false, ?CT_PEER()};
+ {ok, _, _} = OldNodeRes ->
+ {true, OldNodeRes}
+ end,
Nodes = [node(), Node],
try
- erpc:multicast(Nodes, erlang, send, hej),
+ erpc:multicast(Nodes++[OldNode], erlang, send, hej),
ct:fail(unexpected)
catch
error:{erpc, badarg} -> ok
@@ -1234,7 +1783,10 @@ multicast(Config) when is_list(Config) ->
Me = self(),
Ok1 = make_ref(),
- ok = erpc:multicast(Nodes, erlang, send, [Me, {mfa, Ok1}]),
+ ok = erpc:multicast(Nodes++[OldNode], erlang, send, [Me, {mfa, Ok1}]),
+ receive
+ {mfa, Ok1} -> ok
+ end,
receive
{mfa, Ok1} -> ok
end,
@@ -1249,31 +1801,47 @@ multicast(Config) when is_list(Config) ->
{a_fun, Ok1} -> ok
end,
- ok = erpc:multicast([Node], erlang, halt, []),
+ ok = erpc:multicast([Node, OldNode], erlang, halt, []),
monitor_node(Node, true),
receive {nodedown, Node} -> ok end,
+ monitor_node(OldNode, true),
+ receive {nodedown, OldNode} -> ok end,
- ok = erpc:multicast([Node], erlang, send, [Me, wont_reach_me]),
+ ok = erpc:multicast([Node, OldNode], erlang, send, [Me, wont_reach_me]),
receive after 1000 -> ok end,
[] = flush([]),
- case start_22_node(Config) of
- {ok, Node22} ->
- ok = erpc:multicast([Node], erlang, send, [Me, wont_reach_me]),
- ok = erpc:multicast([Node], fun () -> Me ! wont_reach_me end),
- receive
- Msg -> ct:fail({unexpected_message, Msg})
- after
- 2000 -> ok
- end,
- stop_node(Node22),
- {comment, "Tested against OTP 22 as well"};
- _ ->
- {comment, "No tested against OTP 22"}
+
+ {ok, EiNode} = start_ei_node(Config),
+ %% Test once when erpc:multicast() brings up the connection
+ %% and once when the connection is up...
+ disconnect(EiNode),
+
+ ok = erpc:multicast([EiNode], erlang, send, [Me, wont_reach_me]),
+ ok = erpc:multicast([EiNode], fun () -> Me ! wont_reach_me end),
+
+ wait_until(fun () -> lists:member(EiNode, nodes(hidden)) end),
+
+ ok = erpc:multicast([EiNode], erlang, send, [Me, wont_reach_me]),
+ ok = erpc:multicast([EiNode], fun () -> Me ! wont_reach_me end),
+
+ receive
+ Msg -> ct:fail({unexpected_message, Msg})
+ after
+ 2000 -> ok
+ end,
+ ok = stop_ei_node(EiNode),
+
+ case OldTested of
+ false ->
+ {comment, "Not tested against OTP "++OldRel++" node"};
+ true ->
+ {comment, "Also tested against OTP "++OldRel++" node"}
end.
+
timeout_limit(Config) when is_list(Config) ->
Node = node(),
MaxTmo = (1 bsl 32) - 1,
@@ -1335,42 +1903,136 @@ timeout_limit(Config) when is_list(Config) ->
%%% Utility functions.
%%%
-start_node(Config) ->
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
-
-start_peer_node(Config) ->
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, peer, [{args, "-pa " ++ Pa}]).
-
-start_22_node(Config) ->
- Rel = "22_latest",
- case test_server:is_release_available(Rel) of
- false ->
- notsup;
+wait_until(Fun) ->
+ case (catch Fun()) of
true ->
- Cookie = atom_to_list(erlang:get_cookie()),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name,
- peer,
- [{args, "-pa " ++ Pa ++ " -setcookie "++Cookie},
- {erl, [{release, Rel}]}])
+ ok;
+ _ ->
+ receive after 100 -> ok end,
+ wait_until(Fun)
+ end.
+
+old_release() ->
+ OldRel = integer_to_list(list_to_integer(erlang:system_info(otp_release))-2),
+ {OldRel++"_latest", OldRel}.
+
+compile_and_load_on_node(Node) ->
+ %% Recompile erpc_SUITE on the old node and load it...
+ SrcFile = filename:rootname(code:which(?MODULE)) ++ ".erl",
+ {ok, ?MODULE, BeamCode} = erpc:call(Node, compile, file,
+ [SrcFile, [binary]]),
+ {module, ?MODULE} = erpc:call(Node, code, load_binary,
+ [?MODULE, SrcFile, BeamCode]).
+
+start_ei_node(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ Suffix = case os:type() of
+ {win32, _} -> ".exe";
+ _ -> ""
+ end,
+ FwdNodeExe = filename:join(DataDir, "fwd_node"++Suffix),
+ Name = atom_to_list(?MODULE)
+ ++ "-" ++ "ei_node"
+ ++ "-" ++ integer_to_list(erlang:system_time(second))
+ ++ "-" ++ integer_to_list(erlang:unique_integer([positive])),
+ Cookie = atom_to_list(erlang:get_cookie()),
+ HostName = get_hostname(),
+ Node = list_to_atom(Name++"@"++HostName),
+ Creation = integer_to_list(rand:uniform((1 bsl 15) - 4) + 3),
+ Parent = self(),
+ Pid = spawn_link(fun () ->
+ register(cnode_forward_receiver, self()),
+ process_flag(trap_exit, true),
+ Args = ["-sname", Name,
+ "-cookie", Cookie,
+ "-creation", Creation],
+ io:format("Starting ei_node: ~p ~p~n",
+ [FwdNodeExe, Args]),
+ Port = erlang:open_port({spawn_executable, FwdNodeExe},
+ [use_stdio, {args, Args}]),
+ receive
+ {Port, {data, "accepting"}} -> ok
+ end,
+ ei_node_handler_loop(Node, Parent, Port)
+ end),
+ put({ei_node_handler, Node}, Pid),
+ case check_ei_node(Node) of
+ ok -> {ok, Node};
+ Error -> Error
+ end.
+
+check_ei_node(Node) ->
+ Key = {ei_node_handler, Node},
+ case get(Key) of
+ undefined ->
+ {error, no_handler};
+ Pid when is_pid(Pid) ->
+ Pid ! {check_node, self()},
+ receive
+ {check_node, Pid, Res} ->
+ Res
+ after 3000 ->
+ {error, no_handler_response}
+ end
end.
-stop_node(Node) ->
- test_server:stop_node(Node).
+stop_ei_node(Node) ->
+ case check_ei_node(Node) of
+ ok ->
+ Key = {ei_node_handler, Node},
+ case get(Key) of
+ undefined ->
+ {error, no_handler};
+ Pid when is_pid(Pid) ->
+ Pid ! {stop_node, self()},
+ receive
+ {stop_node, Pid} ->
+ put(Key, undefined),
+ ok
+ after 2000 ->
+ {error, no_handler_response}
+ end
+ end;
+ Error ->
+ Error
+ end.
+
+ei_node_handler_loop(Node, Parent, Port) ->
+ receive
+ {'EXIT', Parent, Reason} ->
+ erlang:disconnect_node(Node),
+ (catch port_close(Port)),
+ exit(Reason);
+ {stop_node, Parent} ->
+ erlang:disconnect_node(Node),
+ (catch port_close(Port)),
+ Parent ! {stop_node, self()},
+ exit(normal);
+ {check_node, Parent} ->
+ Ref = make_ref(),
+ {a_name, Node} ! Ref,
+ receive
+ Ref ->
+ Parent ! {check_node, self(), ok}
+ after
+ 2000 ->
+ Parent ! {check_node, self(), {error, no_node_response}}
+ end;
+ Msg ->
+ Msgs = fetch_all_messages([Msg]),
+ erlang:disconnect_node(Node),
+ (catch port_close(Port)),
+ exit({ei_node_handler, Node, unexpected_messages, Msgs})
+ end,
+ ei_node_handler_loop(Node, Parent, Port).
+
+get_hostname() ->
+ get_hostname(atom_to_list(node())).
+
+get_hostname([$@ | HostName]) ->
+ HostName;
+get_hostname([_ | Rest]) ->
+ get_hostname(Rest).
flush(L) ->
receive
@@ -1380,9 +2042,24 @@ flush(L) ->
L
end.
+disconnect(Node) ->
+ case lists:member(Node, nodes([visible, hidden])) of
+ false ->
+ ok;
+ true ->
+ monitor_node(Node, true),
+ true = erlang:disconnect_node(Node),
+ receive {nodedown, Node} -> ok end,
+ false = lists:member(Node, nodes([visible, hidden])),
+ ok
+ end.
+
t() ->
- [N | _] = string:tokens(atom_to_list(node()), "_"),
- 1000*list_to_integer(N).
+ Delay = case init:get_argument(erpc_test_delay) of
+ {ok,[[D]]} -> list_to_integer(D);
+ _ -> 0
+ end,
+ 1000*Delay.
f() ->
timer:sleep(T=t()),
@@ -1393,6 +2070,9 @@ f2() ->
timer:sleep(500),
halt().
+next_msg() ->
+ receive M -> M end.
+
flush_msgq() ->
flush_msgq(0).
flush_msgq(N) ->
@@ -1402,3 +2082,12 @@ flush_msgq(N) ->
after 0 ->
N
end.
+
+fetch_all_messages(Msgs) ->
+ receive
+ Msg ->
+ fetch_all_messages([Msg|Msgs])
+ after
+ 0 ->
+ Msgs
+ end.
diff --git a/lib/kernel/test/erpc_SUITE_data/Makefile.src b/lib/kernel/test/erpc_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..0f59ee0b05
--- /dev/null
+++ b/lib/kernel/test/erpc_SUITE_data/Makefile.src
@@ -0,0 +1,39 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2021. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+
+include @erl_interface_mk_include@
+
+CC = @CC@
+LD = @LD@
+
+CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@
+
+LIBEI = @erl_interface_eilib@
+LIBFLAGS = $(LIBEI) @LIBS@ @erl_interface_sock_libs@ @erl_interface_threadlib@
+
+all: fwd_node@exe@
+
+fwd_node@exe@: fwd_node@obj@ $(LIBEI)
+ $(LD) @CROSSLDFLAGS@ -o $@ fwd_node@obj@ $(LIBFLAGS)
+
+clean:
+ $(RM) fwd_node@obj@
+ $(RM) fwd_node@exe@
+
diff --git a/lib/kernel/test/erpc_SUITE_data/fwd_node.c b/lib/kernel/test/erpc_SUITE_data/fwd_node.c
new file mode 100644
index 0000000000..da26fd4224
--- /dev/null
+++ b/lib/kernel/test/erpc_SUITE_data/fwd_node.c
@@ -0,0 +1,221 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2021. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __WIN32__
+# include <io.h>
+#else
+# include <unistd.h>
+# include <errno.h>
+# include <pthread.h>
+#endif
+#include "ei.h"
+
+static void usage1(char *what);
+static void usage2(char *what, char *val);
+static void fail1(char *what);
+
+char *progname;
+ei_cnode cnode;
+char *node_name = NULL;
+char *cookie = NULL;
+short creation = -1;
+
+#ifdef __WIN32__
+static unsigned __stdcall ei_node_executor(LPVOID unused)
+#else
+static void *ei_node_executor(void *unused)
+#endif
+{
+ int lfd, pfd, res, port;
+
+ ei_init();
+ res = ei_connect_init(&cnode, node_name, cookie, creation);
+ if (res < 0)
+ fail1("ei_connect_init");
+ port = 0;
+ lfd = ei_listen(&cnode, &port, 5);
+ if (lfd < 0)
+ fail1("ei_listen");
+ pfd = ei_publish(&cnode, port);
+ if (pfd < 0)
+ fail1("ei_publish");
+
+ printf("accepting");
+ fflush(stdout);
+
+ while (!0) {
+ ErlConnect conn;
+ int afd = ei_accept(&cnode, lfd, &conn);
+ if (afd < 0)
+ fail1("ei_accept");
+
+ while (!0) {
+ ei_x_buff x;
+ erlang_msg msg;
+ ei_x_new(&x);
+ do {
+ res = ei_xreceive_msg(afd, &msg, &x);
+ } while (res == ERL_TICK);
+ if (res != ERL_MSG) {
+ /* connection closed... */
+ ei_close_connection(afd);
+ break;
+ }
+
+ switch (msg.msgtype) {
+ case ERL_SEND:
+ case ERL_REG_SEND:
+ ei_send_reg_encoded(afd, &cnode.self, "cnode_forward_receiver",
+ x.buff, x.index);
+ break;
+ case ERL_LINK:
+ fail1("received link");
+ break;
+ case ERL_UNLINK:
+ fail1("received unlink");
+ break;
+ case ERL_EXIT:
+ fail1("received exit");
+ break;
+ default:
+ fail1("received invalid signal");
+ break;
+ }
+ ei_x_free(&x);
+ }
+ }
+
+#ifdef __WIN32__
+ return 0;
+#else
+ return NULL;
+#endif
+}
+
+int
+main(int argc, char *argv[])
+{
+#ifdef __WIN32__
+ unsigned tid;
+ HANDLE thndl;
+#else
+ pthread_t tid;
+#endif
+ int i;
+
+ progname = argv[0];
+ i = 1;
+ while (i < argc) {
+ if (strcmp(argv[i], "-sname") == 0) {
+ i++;
+ if (i == argc)
+ usage1("Missing -sname value");
+ node_name = argv[i];
+ }
+ else if (strcmp(argv[i], "-cookie") == 0) {
+ i++;
+ if (i == argc)
+ usage1("Missing -cookie value");
+ cookie = argv[i];
+ }
+ else if (strcmp(argv[i], "-creation") == 0) {
+ char *endp;
+ long int val;
+ i++;
+ if (i == argc)
+ usage1("Missing -creation value");
+ val = strtol(argv[i], &endp, 10);
+ creation = (short) val;
+ if (*endp != '\0' || creation < 4)
+ usage2("Invalid creation", argv[i]);
+ }
+ else {
+ usage2("Unknown parameter", argv[i]);
+ }
+ i++;
+ }
+
+ if (!node_name)
+ usage1("Missing -sname parameter");
+ if (!cookie)
+ usage1("Missing -cookie parameter");
+ if (creation < 0)
+ usage1("Missing -creation parameter");
+
+#ifdef __WIN32__
+ thndl = (HANDLE) _beginthreadex(NULL, 0, ei_node_executor,
+ NULL, 0, &tid);
+ if (thndl == (HANDLE) 0)
+ fail1("_beginthreadex() failed");
+#else
+ if (pthread_create(&tid, NULL, ei_node_executor, NULL) != 0)
+ fail1("pthread_create() failed");
+#endif
+
+ /* Wait until stdin is closed. Terminate when that happens... */
+ while (!0) {
+ char buf[128];
+#ifdef __WIN32__
+ int res = _read(0, (void *) &buf[0], sizeof(buf));
+#else
+ ssize_t res = read(0, (void *) &buf[0], sizeof(buf));
+#endif
+ if (res == 0)
+ exit(0); /* erlang port closed... */
+ if (res < 0 && errno != EINTR) {
+ fail1("read() failed");
+ }
+ }
+
+ return 0;
+}
+
+static void
+usage1(char *what)
+{
+ fprintf(stderr,
+ "ERROR: %s\n\n"
+ " Usage:\n"
+ " %s -sname <node name> -cookie <cookie> -creation <creation>\n",
+ what, progname);
+ exit(1);
+}
+
+static void
+usage2(char *what, char *val)
+{
+ fprintf(stderr,
+ "ERROR: %s: %s\n\n"
+ " Usage:\n"
+ " %s -sname <node name> -cookie <cookie> -creation <creation>\n",
+ what, val, progname);
+ exit(1);
+}
+
+static void
+fail1(char *what)
+{
+ fprintf(stderr, "%s FAILED: %s; %d\n",
+ cnode.thisalivename, what, erl_errno);
+ exit(1);
+}
diff --git a/lib/kernel/test/error_info_lib.erl b/lib/kernel/test/error_info_lib.erl
deleted file mode 100644
index d1afaf4589..0000000000
--- a/lib/kernel/test/error_info_lib.erl
+++ /dev/null
@@ -1,115 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(error_info_lib).
--export([test_error_info/2, test_error_info/3]).
-
-test_error_info(Module, List) ->
- test_error_info(Module, List, []).
-
-test_error_info(Module, L0, Options) ->
- L1 = lists:foldl(fun({_,A}, Acc) when is_integer(A) -> Acc;
- ({F,A}, Acc) -> [{F,A,[]}|Acc];
- ({F,A,Opts}, Acc) -> [{F,A,Opts}|Acc]
- end, [], L0),
- Tests = ordsets:from_list([{F,length(A)} || {F,A,_} <- L1] ++
- [{F,A} || {F,A} <- L0, is_integer(A)]),
- Bifs0 = get_bifs(Module, Options),
- Bifs = ordsets:from_list(Bifs0),
- NYI = [{F,lists:duplicate(A, '*'),nyi} || {F,A} <- Bifs -- Tests],
- L = lists:sort(NYI ++ L1),
- do_error_info(L, Module, []).
-
-get_bifs(Module, Options) ->
- case lists:member(snifs_only, Options) of
- true ->
- [{F,A} || {M,F,A} <- erlang:system_info(snifs),
- M =:= Module,
- A =/= 0];
- false ->
- [{F,A} || {F,A} <- Module:module_info(exports),
- A =/= 0,
- F =/= module_info]
- end.
-
-do_error_info([{_,Args,nyi}=H|T], Module, Errors) ->
- case lists:all(fun(A) -> A =:= '*' end, Args) of
- true ->
- do_error_info(T, Module, [{nyi,H}|Errors]);
- false ->
- do_error_info(T, Module, [{bad_nyi,H}|Errors])
- end;
-do_error_info([{F,Args,Opts}|T], Module, Errors) ->
- eval_bif_error(F, Args, Opts, T, Module, Errors);
-do_error_info([], _Module, Errors0) ->
- case lists:sort(Errors0) of
- [] ->
- ok;
- [_|_]=Errors ->
- io:format("\n~p\n", [Errors]),
- ct:fail({length(Errors),errors})
- end.
-
-eval_bif_error(F, Args, Opts, T, Module, Errors0) ->
- try apply(Module, F, Args) of
- Result ->
- case lists:member(no_fail, Opts) of
- true ->
- do_error_info(T, Module, Errors0);
- false ->
- do_error_info(T, Module, [{should_fail,{F,Args},Result}|Errors0])
- end
- catch
- error:Reason:Stk ->
- SF = fun(Mod, _, _) -> Mod =:= test_server end,
- Str = erl_error:format_exception(error, Reason, Stk, #{stack_trim_fun => SF}),
- BinStr = iolist_to_binary(Str),
- ArgStr = lists:join(", ", [io_lib:format("~p", [A]) || A <- Args]),
- io:format("\n~p:~p(~s)\n~ts", [Module,F,ArgStr,BinStr]),
-
- case Stk of
- [{Module,ActualF,ActualArgs,Info}|_] ->
- RE = <<"[*][*][*] argument \\d+:">>,
- Errors1 = case re:run(BinStr, RE, [{capture, none}]) of
- match ->
- Errors0;
- nomatch when Reason =:= system_limit ->
- Errors0;
- nomatch ->
- case lists:member(unexplained, Opts) of
- true ->
- Errors0;
- false ->
- [{no_explanation,{F,Args},Info}|Errors0]
- end
- end,
-
- Errors = case {ActualF,ActualArgs} of
- {F,Args} ->
- Errors1;
- _ ->
- [{renamed,{F,length(Args)},{ActualF,ActualArgs}}|Errors1]
- end,
-
- do_error_info(T, Module, Errors);
- _ ->
- Errors = [{renamed,{F,length(Args)},hd(Stk)}|Errors0],
- do_error_info(T, Module, Errors)
- end
- end.
diff --git a/lib/kernel/test/error_logger_SUITE.erl b/lib/kernel/test/error_logger_SUITE.erl
index eab72e58a7..5050ed1af8 100644
--- a/lib/kernel/test/error_logger_SUITE.erl
+++ b/lib/kernel/test/error_logger_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -235,7 +235,7 @@ generate_error(Error, Stack) ->
via_logger_process(Config) ->
case os:type() of
{win32,_} ->
- {skip,"Skip on windows - cant change file mode"};
+ {skip,"Skip on windows - can't change file mode"};
_ ->
error_logger:add_report_handler(?MODULE, self()),
Dir = filename:join(?config(priv_dir,Config),"dummydir"),
@@ -255,12 +255,12 @@ via_logger_process(Config) ->
other_node(_Config) ->
error_logger:add_report_handler(?MODULE, self()),
- {ok,Node} = test_server:start_node(?FUNCTION_NAME,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
ok = rpc:call(Node,logger,add_handler,[error_logger,error_logger,
#{level=>info,filter_default=>log}]),
rpc:call(Node,error_logger,error_report,[hi_from_remote]),
reported(error_report,std_error,hi_from_remote),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 60aa60bf9f..b791a577f0 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -809,10 +809,12 @@ list_dir_1(TestDir, Cnt, Sorted0) ->
untranslatable_names(Config) ->
case no_untranslatable_names() of
- true ->
- {skip,"Not a problem on this OS"};
false ->
- untranslatable_names_1(Config)
+ untranslatable_names_1(Config);
+ os ->
+ {skip,"Not a problem on this OS"};
+ fs ->
+ {skip,"Not a problem on this FS"}
end.
untranslatable_names_1(Config) ->
@@ -820,7 +822,7 @@ untranslatable_names_1(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "untranslatable_names"),
ok = file:make_dir(Dir),
- Node = start_node(untranslatable_names, "+fnu"),
+ {ok, Peer, Node} = ?CT_PEER(["+fnu"]),
try
ok = file:set_cwd(Dir),
[ok = file:write_file(F, F) || {_,F} <- untranslatable_names()],
@@ -841,7 +843,7 @@ untranslatable_names_1(Config) ->
io:format("ExpectedListDirAll: ~p\n", [ExpectedListDirAll]),
ExpectedListDirAll = call_and_sort(Node, file, list_dir_all, [Dir])
after
- catch test_server:stop_node(Node),
+ catch peer:stop(Peer),
file:set_cwd(OldCwd),
[file:delete(F) || {_,F} <- untranslatable_names()],
file:del_dir(Dir)
@@ -850,10 +852,12 @@ untranslatable_names_1(Config) ->
untranslatable_names_error(Config) ->
case no_untranslatable_names() of
- true ->
- {skip,"Not a problem on this OS"};
false ->
- untranslatable_names_error_1(Config)
+ untranslatable_names_error_1(Config);
+ os ->
+ {skip,"Not a problem on this OS"};
+ fs ->
+ {skip,"Not a problem on this FS"}
end.
untranslatable_names_error_1(Config) ->
@@ -861,7 +865,7 @@ untranslatable_names_error_1(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, "untranslatable_names_error"),
ok = file:make_dir(Dir),
- Node = start_node(untranslatable_names, "+fnue"),
+ {ok, Peer, Node} = ?CT_PEER(["+fnue"]),
try
ok = file:set_cwd(Dir),
[ok = file:write_file(F, F) || {_,F} <- untranslatable_names()],
@@ -875,7 +879,7 @@ untranslatable_names_error_1(Config) ->
true = lists:keymember(BadFile, 2, untranslatable_names())
after
- catch test_server:stop_node(Node),
+ catch peer:stop(Peer),
file:set_cwd(OldCwd),
[file:delete(F) || {_,F} <- untranslatable_names()],
file:del_dir(Dir)
@@ -896,23 +900,23 @@ call_and_sort(Node, M, F, A) ->
no_untranslatable_names() ->
case os:type() of
- {unix,darwin} -> true;
- {win32,_} -> true;
- _ -> false
- end.
-
-start_node(Name, Args) ->
- [_,Host] = string:lexemes(atom_to_list(node()), "@"),
- ct:log("Trying to start ~w@~s~n", [Name,Host]),
- case test_server:start_node(Name, peer, [{args,Args}]) of
- {error,Reason} ->
- ct:fail(Reason);
- {ok,Node} ->
- ct:log("Node ~p started~n", [Node]),
- Node
+ {unix,darwin} -> os;
+ {win32,_} -> os;
+ _ ->
+ %% If we are using utf8only on zfs then we cannot create latin1 characters.
+ case os:find_executable("zfs") of
+ false ->
+ false;
+ _Zfs ->
+ case os:cmd("zfs get utf8only `pwd` | grep utf8only | awk '{print $3}'") of
+ "on" ++ _ ->
+ fs;
+ _ ->
+ false
+ end
+ end
end.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1089,7 +1093,7 @@ close(Config) when is_list(Config) ->
{ok,Fd1} = ?FILE_MODULE:open(Name,read_write),
%% Just closing it is no fun, we did that a million times already
%% This is a common error, for code written before Erlang 4.3
- %% bacause then ?FILE_MODULE:open just returned a Pid, and not everyone
+ %% because then ?FILE_MODULE:open just returned a Pid, and not everyone
%% really checked what they got.
{'EXIT',_Msg} = (catch ok = ?FILE_MODULE:close({ok,Fd1})),
ok = ?FILE_MODULE:close(Fd1),
@@ -1253,7 +1257,7 @@ append(Config) when is_list(Config) ->
ok = ?FILE_MODULE:make_dir(NewDir),
First = "First line\n",
- Second = "Seond lines comes here\n",
+ Second = "Second lines comes here\n",
Third = "And here is the third line\n",
%% Write a small text file.
@@ -1415,8 +1419,8 @@ file_info_basic_file(Config) when is_list(Config) ->
%% Create a short file.
Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_basic_test.fil"),
+ atom_to_list(?MODULE) ++ "_" ++
+ atom_to_list(?FUNCTION_NAME) ++ ".fil"),
{ok,Fd1} = ?FILE_MODULE:open(Name, write),
io:put_chars(Fd1, "foo bar"),
ok = ?FILE_MODULE:close(Fd1),
@@ -1521,8 +1525,8 @@ file_info_int(Config) ->
io:format("RootDir = ~p", [RootDir]),
Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_file_info.fil"),
+ atom_to_list(?MODULE) ++ "_" ++
+ atom_to_list(?FUNCTION_NAME) ++ ".fil"),
{ok,Fd1} = ?FILE_MODULE:open(Name,write),
io:put_chars(Fd1,"foo"),
@@ -1600,8 +1604,8 @@ file_handle_info_basic_file(Config) when is_list(Config) ->
%% Create a short file.
Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_basic_test.fil"),
+ atom_to_list(?MODULE) ++ "_" ++
+ atom_to_list(?FUNCTION_NAME) ++ ".fil"),
{ok,Fd1} = ?FILE_MODULE:open(Name, write),
io:put_chars(Fd1, "foo bar"),
ok = ?FILE_MODULE:close(Fd1),
@@ -1696,8 +1700,8 @@ file_handle_info_int(Config) ->
io:format("RootDir = ~p", [RootDir]),
Name = filename:join(RootDir,
- atom_to_list(?MODULE)
- ++"_file_info.fil"),
+ atom_to_list(?MODULE) ++ "_" ++
+ atom_to_list(?FUNCTION_NAME) ++ ".fil"),
{ok,Fd1} = ?FILE_MODULE:open(Name, write),
io:put_chars(Fd1,"foo"),
{ok,FileInfo1} = ?FILE_MODULE:read_file_info(Fd1),
@@ -2238,7 +2242,7 @@ allocate(Config) when is_list(Config) ->
allocate_and_assert(Fd, Offset, Length) ->
%% Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
- %% any other negative side effect. We can't really asssert against a
+ %% any other negative side effect. We can't really assert against a
%% specific return value, because support for file space pre-allocation
%% depends on the OS, OS version and underlying filesystem.
%%
@@ -2603,7 +2607,7 @@ e_rename(Config) when is_list(Config) ->
ok ->
{ok, {comment,
"Moving between filesystems "
- "suceeded, files are probably "
+ "succeeded, files are probably "
"in the same filesystem!"}};
{error, eperm} ->
{ok, {comment, "SBS! You don't "
@@ -4003,7 +4007,15 @@ ok.
%% OTP-10852. +fnu and latin1 filenames.
otp_10852(Config) when is_list(Config) ->
- Node = start_node(erl_pp_helper, "+fnu"),
+ case no_untranslatable_names() of
+ fs ->
+ {skip,"Not a problem on this FS"};
+ _ ->
+ otp_10852_1(Config)
+ end.
+
+otp_10852_1(Config) ->
+ {ok, Peer, Node} = ?CT_PEER(["+fnu"]),
Dir = proplists:get_value(priv_dir, Config),
B = filename:join(Dir, <<"\xE4">>),
ok = rpc_call(Node, get_cwd, [B]),
@@ -4046,7 +4058,7 @@ otp_10852(Config) when is_list(Config) ->
{ok, Fd2, B} = rpc_call(Node, path_open, [["."], B, [read]]),
ok = rpc_call(Node, close, [Fd2])
end,
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
rpc_call(N, F, As) ->
@@ -4104,6 +4116,21 @@ do_large_file(Name) ->
{ok,R} = ?FILE_MODULE:read(F1, L+1),
ok = ?FILE_MODULE:close(F1),
+ %% Reopen the file try to read all of it; used to fail on macOS
+ %% We open with binary in order to not get a memory explosion.
+ {ok, F2} = ?FILE_MODULE:open(Name, [raw,read,binary]),
+ IsWindows = element(1,os:type()) =:= win32,
+ case {?FILE_MODULE:read(F2, P), erlang:system_info(wordsize)} of
+ {{ok, B}, 8} ->
+ P = byte_size(B);
+ {eof, 8} when IsWindows ->
+ ok;
+ {eof, 4} ->
+ %% Cannot read such large files on 32-bit
+ ok
+ end,
+ ok = ?FILE_MODULE:close(F2),
+
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -4131,6 +4158,10 @@ do_large_write(Name) ->
Bin = <<0:Size/unit:8>>,
ok = file:write_file(Name, Bin),
{ok,#file_info{size=Size}} = file:read_file_info(Name),
+
+ %% Even multiples of MAX_SYSIOVEC_IOVLEN would cause a crash
+ ok = file:write_file(Name, binary:part(Bin, 0, 1 bsl 31)),
+ {ok,#file_info{size=1 bsl 31}} = file:read_file_info(Name),
ok
end.
@@ -4809,28 +4840,37 @@ do_run_large_file_test(Config, Run, Name0) ->
Name = filename:join(proplists:get_value(priv_dir, Config),
?MODULE_STRING ++ Name0),
+ %% We run the test in a peer node in case the OOM killer
+ {ok, Peer, Node} = ?CT_PEER(),
+
+ erpc:call(Node, application, ensure_all_started, [os_mon]),
+
%% 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),
+ 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),
+ try
+ Res = erpc:call(Node, fun() -> Run(Name) end),
- %% Delete file and finish deleter process.
- Mref = erlang:monitor(process, Deleter),
- Deleter ! {Tester,done},
- receive {'DOWN',Mref,_,_,_} -> ok end,
+ %% Delete file and finish deleter process.
+ Mref = erlang:monitor(process, Deleter),
+ Deleter ! {Tester,done},
+ receive {'DOWN',Mref,_,_,_} -> ok end,
- Res.
+ Res
+ after
+ peer:stop(Peer)
+ end.
disc_free(Path) ->
Data = disksup:get_disk_data(),
@@ -4848,5 +4888,10 @@ disc_free(Path) ->
end.
memsize() ->
- {Tot,_Used,_} = memsup:get_memory_data(),
- Tot.
+ case proplists:get_value(available_memory, memsup:get_system_memory_data()) of
+ undefined ->
+ {Tot,_Used,_} = memsup:get_memory_data(),
+ Tot;
+ Available ->
+ Available
+ end.
diff --git a/lib/kernel/test/file_SUITE_data/realmen.html b/lib/kernel/test/file_SUITE_data/realmen.html
index 92e13f23b8..eaaa65523a 100644
--- a/lib/kernel/test/file_SUITE_data/realmen.html
+++ b/lib/kernel/test/file_SUITE_data/realmen.html
@@ -121,7 +121,7 @@ based on data structures, instead of the other way around. As all Real
Programmers know, the only useful data structure is the
array. Strings, lists, structures, sets -- these are all special cases
of arrays and and can be treated that way just as easily without
-messing up your programing language with all sorts of
+messing up your programming language with all sorts of
complications. The worst thing about fancy data types is that you have
to declare them, and Real Programming Languages, as we all know, have
implicit typing based on the first letter of the (six character)
@@ -318,7 +318,7 @@ thing slightly more trivial than the destruction of life as we know
it, providing there's enough money in it. There are several Real
Programmers building video games at Atari, for example. (But not
playing them. A Real Programmer knows how to beat the machine every
-time: no challange in that.) Everyone working at LucasFilm is a Real
+time: no challenge in that.) Everyone working at LucasFilm is a Real
Programmer. (It would be crazy to turn down the money of 50 million
Star Wars fans.) The proportion of Real Programmers in Computer
Graphics is somewhat lower than the norm, mostly because nobody has
@@ -384,7 +384,7 @@ coffee. In some cases, the cups will contain Orange Crush.
and the Principles of Operation open to some particularly interesting
pages.
-<LI> Taped to the wall is a line-printer Snoopy calender for the year
+<LI> Taped to the wall is a line-printer Snoopy calendar for the year
1969.
<LI> Strewn about the floor are several wrappers for peanut butter
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index 7166064558..6efc542897 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -203,9 +203,9 @@ normal(Config) when is_list(Config) ->
%% Check file operations on normal file names regardless of unicode mode.
icky(Config) when is_list(Config) ->
- case hopeless_darwin() of
+ case hopeless_icky() of
true ->
- {skipped,"This version of darwin does not support icky names at all."};
+ {skipped,"This OS/FS does not support icky names at all."};
false ->
{ok,Dir} = file:get_cwd(),
try
@@ -222,9 +222,9 @@ icky(Config) when is_list(Config) ->
end.
%% Check file operations on normal file names regardless of unicode mode.
very_icky(Config) when is_list(Config) ->
- case hopeless_darwin() of
+ case hopeless_icky() of
true ->
- {skipped,"This version of darwin does not support icky names at all."};
+ {skipped,"This OS/FS does not support icky names at all."};
false ->
{ok,Dir} = file:get_cwd(),
try
@@ -630,17 +630,34 @@ make_icky_dir(Mod, IckyDirName) ->
ok = Mod:set_cwd(IckyDirName),
make_dir_contents(Icky, Mod).
+hopeless_icky() ->
+ hopeless_darwin() orelse hopeless_zfs().
+
hopeless_darwin() ->
case {os:type(),os:version()} of
{{unix,darwin},{Major,_,_}} ->
%% icky file names worked between 10 and 17, but started returning
- %% EILSEQ in 18. The check against 18..19 is exact in case newer
+ %% EILSEQ in 18. The check against 18..21 is exact in case newer
%% versions of Darwin support them again.
- Major < 9 orelse (Major >= 18 andalso Major =< 19);
+ Major < 9 orelse (Major >= 18 andalso Major =< 21);
_ ->
false
end.
+hopeless_zfs() ->
+ %% If we are using utf8only on zfs then we cannot create latin1 characters.
+ case os:find_executable("zfs") of
+ false ->
+ false;
+ _Zfs ->
+ case os:cmd("zfs get utf8only `pwd` | grep utf8only | awk '{print $3}'") of
+ "on" ++ _ ->
+ true;
+ _ ->
+ false
+ end
+ end.
+
make_very_icky_dir(Mod, DirName) ->
Desc = [{regular,"fil1","fil1"},
{regular,[956,965,963,954,959,49],"åäö2"},
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 321f6abf2e..297c824965 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -32,7 +32,7 @@
-export([
skip_old_solaris/1,
basic/1,
- api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
+ api_open_close/1,api_listen/1,api_connect_init/1,api_connectx_init/1,api_opts/1,
xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
open_multihoming_ipv4_socket/1,
open_unihoming_ipv6_socket/1,
@@ -48,7 +48,8 @@
t_simple_local_sockaddr_in_send_recv/1,
t_simple_link_local_sockaddr_in_send_recv/1,
t_simple_local_sockaddr_in6_send_recv/1,
- t_simple_link_local_sockaddr_in6_send_recv/1
+ t_simple_link_local_sockaddr_in6_send_recv/1,
+ t_simple_local_sockaddr_in_connectx_init/1
]).
suite() ->
@@ -87,7 +88,7 @@ old_solaris_cases() ->
extensive_cases() ->
[
- api_open_close, api_listen, api_connect_init,
+ api_open_close, api_listen, api_connect_init, api_connectx_init,
api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
open_multihoming_ipv4_socket,
open_unihoming_ipv6_socket,
@@ -105,7 +106,8 @@ sockaddr_cases() ->
t_simple_local_sockaddr_in_send_recv,
t_simple_link_local_sockaddr_in_send_recv,
t_simple_local_sockaddr_in6_send_recv,
- t_simple_link_local_sockaddr_in6_send_recv
+ t_simple_link_local_sockaddr_in6_send_recv,
+ t_simple_local_sockaddr_in_connectx_init
].
@@ -178,7 +180,14 @@ end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(_Case, Config) ->
+init_per_testcase(api_connectx_init=Case, Config) ->
+ check_sctp_connectx(Case, Config);
+init_per_testcase(t_simple_local_sockaddr_in_connectx_init=Case, Config) ->
+ check_sctp_connectx(Case, Config);
+init_per_testcase(Case, Config) ->
+ init_per_testcase_common(Case, Config).
+
+init_per_testcase_common(_Case, Config) ->
?P("init_per_testcase -> entry with"
"~n Config: ~p"
@@ -215,6 +224,21 @@ end_per_testcase(_Case, Config) ->
-define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end).
+-define(no_return(Expr), error({unexpected, Expr})).
+
+check_sctp_connectx(Case, Config) ->
+ {ok,S} = gen_sctp:open([]),
+ try
+ {ok,Pb} = inet:port(S),
+ case gen_sctp:connectx_init(S, [{127,0,0,1}], Pb, []) of
+ {error, enotsup} ->
+ {skip, "sctp_connectx unsupported"};
+ _ ->
+ init_per_testcase_common(Case, Config)
+ end
+ after
+ gen_sctp:close(S)
+ end.
is_old_solaris() ->
os:type() =:= {unix,sunos} andalso os:version() < {5,12,0}.
@@ -666,6 +690,9 @@ flush() ->
%% Test the API function open/1,2 and close/1.
api_open_close(Config) when is_list(Config) ->
+ ?TC_TRY(?FUNCTION_NAME, fun() -> do_api_open_close() end).
+
+do_api_open_close() ->
{ok,S1} = gen_sctp:open(0),
{ok,P} = inet:port(S1),
ok = gen_sctp:close(S1),
@@ -682,7 +709,7 @@ api_open_close(Config) when is_list(Config) ->
{ok,P} = inet:port(S4),
ok = gen_sctp:close(S4),
- {ok,S5} = gen_sctp:open(P, [{ifaddr,any}]),
+ {ok,S5} = gen_sctp:open(P, [{debug, false}, {ifaddr,any}, {debug, true}]),
{ok,P} = inet:port(S5),
ok = gen_sctp:close(S5),
@@ -798,6 +825,40 @@ api_connect_init(Config) when is_list(Config) ->
ok = gen_sctp:close(Sb),
ok.
+%% Test the API function connectx_init/4.
+api_connectx_init(Config) when is_list(Config) ->
+ Localhost = {127,0,0,1},
+
+ {ok,S} = gen_sctp:open(),
+ {ok,Pb} = inet:port(S),
+ try ?no_return(gen_sctp:connectx_init(S, Localhost, 12345, []))
+ catch error:badarg -> ok
+ end,
+ {error, einval} = gen_sctp:connectx_init(S, [Localhost], not_allowed_for_port, []),
+ %% try ?no_return(gen_sctp:connectx_init(S, [Localhost], not_allowed_for_port, []))
+ %% catch error:badarg -> ok
+ %% end,
+ try ?no_return(gen_sctp:connectx_init(S, [Localhost], 12345, not_allowed_for_opts))
+ catch error:badarg -> ok
+ end,
+ ok = gen_sctp:close(S),
+ {error,closed} = gen_sctp:connectx_init(S, [Localhost], 12345, []),
+
+ {ok,Sb} = gen_sctp:open(Pb),
+ {ok,Sa} = gen_sctp:open(),
+ {ok, A1} = gen_sctp:connectx_init(Sa, [localhost], Pb, []),
+ true = (A1 =/= 0),
+ {Localhost,Pb,#sctp_assoc_change{state=cant_assoc, assoc_id = A1}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
+ ok = gen_sctp:listen(Sb, true),
+ {ok, A2} = gen_sctp:connectx_init(Sa, [localhost], Pb, []),
+ true = (A2 =/= 0),
+ {Localhost,Pb,#sctp_assoc_change{state=comm_up, assoc_id = A2}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
+ ok = gen_sctp:close(Sa),
+ ok = gen_sctp:close(Sb),
+ ok.
+
recv_event({Addr, Port, [], #sctp_assoc_change{} = AssocChange}) ->
{Addr, Port, AssocChange};
recv_event({Addr,Port,
@@ -862,7 +923,7 @@ do_implicit_inet6(_Config) ->
{error, nxdomain = Reason_getaddr} ->
?SKIPT(Reason_getaddr);
{error, Reason_getaddr} ->
- ?line ct:fail({unexpected, Reason_getaddr})
+ ct:fail({unexpected, Reason_getaddr})
end,
S2 = case gen_sctp:open(0, [{ip, Localhost}]) of
{ok, S} ->
@@ -870,7 +931,7 @@ do_implicit_inet6(_Config) ->
{error, nxdomain = Reason_open} ->
?SKIPT(Reason_open);
{error, Reason_open} ->
- ?line ct:fail({unexpected, Reason_open})
+ ct:fail({unexpected, Reason_open})
end,
?P("*** ~s: ~p ***", ["localhost", Localhost]),
@@ -1920,7 +1981,7 @@ recv_close(Config) when is_list(Config) ->
"~n ~p", [PreReason]),
(catch gen_sctp:close(S)),
(catch gen_sctp:close(C)),
- ?line ct:fail("Unexpected pre close from reader (~p): ~p",
+ ct:fail("Unexpected pre close from reader (~p): ~p",
[Pid, PreReason]);
{Pid, ready} ->
?P("reader ready"),
@@ -1932,7 +1993,7 @@ recv_close(Config) when is_list(Config) ->
?P("reader ready timeout"),
(catch gen_sctp:close(S)),
(catch gen_sctp:close(C)),
- ?line ct:fail("Unexpected pre close timeout (~p)", [Pid])
+ ct:fail("Unexpected pre close timeout (~p)", [Pid])
end,
?P("\"ensure\" reader reading..."),
@@ -1942,7 +2003,7 @@ recv_close(Config) when is_list(Config) ->
"~n ~p", [Any]),
(catch gen_sctp:close(S)),
(catch gen_sctp:close(C)),
- ?line ct:fail("Unexpected message: ~p", [Any])
+ ct:fail("Unexpected message: ~p", [Any])
after 5000 ->
ok
end,
@@ -1959,14 +2020,14 @@ recv_close(Config) when is_list(Config) ->
?P("unexpected reader termination: "
"~n ~p", [PostReason]),
(catch gen_sctp:close(C)),
- ?line ct:fail("Unexpected post close from reader (~p): ~p",
+ ct:fail("Unexpected post close from reader (~p): ~p",
[Pid, PostReason])
after 5000 ->
?P("unexpected reader termination timeout"),
demonitor(MRef, [flush]),
(catch gen_sctp:close(C)),
exit(Pid, kill),
- ?line ct:fail("Reader (~p) termination timeout", [Pid])
+ ct:fail("Reader (~p) termination timeout", [Pid])
end,
?P("close client socket"),
(catch gen_sctp:close(C)),
@@ -2339,6 +2400,32 @@ do_simple_sockaddr_send_recv(#{family := _Fam} = SockAddr, _) ->
ok.
+%% Test the sockaddr version of connectx_init/4.
+t_simple_local_sockaddr_in_connectx_init(Config) when is_list(Config) ->
+ Localhost = {127,0,0,1},
+ {ok,Sb} = gen_sctp:open(),
+ {ok,Pb} = inet:port(Sb),
+ {ok,Sa} = gen_sctp:open(),
+ SockAddr = #{family => inet,
+ addr => Localhost,
+ port => Pb},
+ case gen_sctp:connectx_init(Sa, [SockAddr], []) of
+ {ok, A1} ->
+ true = (A1 =/= 0),
+ {Localhost,Pb,#sctp_assoc_change{state=cant_assoc, assoc_id = A1}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
+ ok = gen_sctp:listen(Sb, true),
+ {ok, A2} = gen_sctp:connectx_init(Sa, [SockAddr], []),
+ true = (A2 =/= 0),
+ {Localhost,Pb,#sctp_assoc_change{state=comm_up, assoc_id = A2}} =
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
+ ok = gen_sctp:close(Sa),
+ ok = gen_sctp:close(Sb);
+ {error, enotsup} ->
+ ok
+ end,
+ ok.
+
%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% socket gen_server ultra light
@@ -2627,10 +2714,10 @@ ok({ok, X}) ->
X;
ok({error, X}) ->
?P("ERROR: ~p", [X]),
- ?line ct:fail({unexpected_error, X});
+ ct:fail({unexpected_error, X});
ok(X) ->
?P("UNEXPECTED: ~p", [X]),
- ?line ct:fail({unexpected, X}).
+ ct:fail({unexpected, X}).
log(X) ->
diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl
index 1488731e9a..593a784bcc 100644
--- a/lib/kernel/test/gen_tcp_api_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_api_SUITE.erl
@@ -63,7 +63,7 @@ suite() ->
].
all() ->
- %% This is a temporary messure to ensure that we can
+ %% This is a temporary measure to ensure that we can
%% test the socket backend without effecting *all*
%% applications on *all* machines.
%% This flag is set only for *one* host.
@@ -244,14 +244,11 @@ init_per_group(t_local = _GroupName, Config) ->
{skip, "AF_LOCAL not supported"}
end;
init_per_group(sockaddr = _GroupName, Config) ->
- try socket:info() of
- _ ->
- Config
- catch
- error : notsup ->
- {skip, "esock not supported"};
- error : undef ->
- {skip, "esock not configured"}
+ case is_socket_supported() of
+ ok ->
+ Config;
+ {skip, _} = SKIP ->
+ SKIP
end;
init_per_group(_GroupName, Config) ->
Config.
@@ -424,9 +421,9 @@ do_recv_delim(Config) ->
ok = gen_tcp:send(A, "abcXefgX"),
?P("await the first chunk"),
- receive {tcp, Client, "abcX"} -> ?P("received first chunck") end,
+ receive {tcp, Client, "abcX"} -> ?P("received first chunk") end,
?P("await the second chunk"),
- receive {tcp, Client, "efgX"} -> ?P("received second chunck") end,
+ receive {tcp, Client, "efgX"} -> ?P("received second chunk") end,
?P("cleanup"),
ok = gen_tcp:close(Client),
@@ -591,9 +588,23 @@ t_fdopen(Config) when is_list(Config) ->
t_fdconnect(Config) when is_list(Config) ->
- ?TC_TRY(t_fdconnect, fun() -> do_t_fdconnect(Config) end).
+ Cond = fun() ->
+ ?P("Try verify if IPv4 is supported"),
+ ?HAS_SUPPORT_IPV4()
+ end,
+ Pre = fun() ->
+ {ok, Addr} = ?WHICH_LOCAL_ADDR(inet),
+ ?P("Use (local) address: ~p", [Addr]),
+ #{local_addr => Addr}
+ end,
+ Case = fun(#{local_addr := Addr}) ->
+ do_t_fdconnect(Addr, Config)
+ end,
+ Post = fun(_) -> ok end,
+ ?TC_TRY(?FUNCTION_NAME,
+ Cond, Pre, Case, Post).
-do_t_fdconnect(Config) ->
+do_t_fdconnect(Addr, Config) ->
Question = "Aaaa... Long time ago in a small town in Germany,",
Question1 = list_to_binary(Question),
Question2 = [<<"Aaaa">>, "... ", $L, <<>>, $o, "ng time ago ",
@@ -616,7 +627,7 @@ do_t_fdconnect(Config) ->
?SKIPT("failed loading util nif lib")
end,
?P("try create listen socket"),
- LOpts = ?INET_BACKEND_OPTS(Config) ++ [{active, false}],
+ LOpts = ?INET_BACKEND_OPTS(Config) ++ [{ifaddr, Addr}, {active, false}],
L = try gen_tcp:listen(0, LOpts) of
{ok, LSock} ->
LSock;
@@ -629,7 +640,7 @@ do_t_fdconnect(Config) ->
ct:fail({unexpected_listen_error, LReason, LOpts})
catch
LC : LE : LS ->
- ?P("UNEXPECTED ERROR - catched listen: "
+ ?P("UNEXPECTED ERROR - caught listen: "
"~n LOpts: ~p"
"~n C: ~p"
"~n E: ~p"
@@ -640,9 +651,13 @@ do_t_fdconnect(Config) ->
?P("try create file descriptor"),
FD = gen_tcp_api_SUITE:getsockfd(),
?P("try connect (to port ~w) using file descriptor ~w", [LPort, FD]),
- COpts = ?INET_BACKEND_OPTS(Config) ++ [{fd, FD}, {active, false}],
- Client = try gen_tcp:connect(localhost, LPort, COpts) of
+ COpts = ?INET_BACKEND_OPTS(Config) ++ [{fd, FD},
+ {ifaddr, Addr},
+ {active, false}],
+ %% The debug is just to "see" that it (debug) "works"...
+ Client = try gen_tcp:connect(Addr, LPort, COpts ++ [{debug, true}]) of
{ok, CSock} ->
+ ok = inet:setopts(CSock, [{debug, false}]),
CSock;
{error, eaddrnotavail = CReason} ->
gen_tcp:close(L),
@@ -655,7 +670,7 @@ do_t_fdconnect(Config) ->
ct:fail({unexpected_connect_error, CReason, COpts})
catch
CC : CE : CS ->
- ?P("UNEXPECTED ERROR - catched connect: "
+ ?P("UNEXPECTED ERROR - caught connect: "
"~n COpts: ~p"
"~n C: ~p"
"~n E: ~p"
@@ -677,7 +692,7 @@ do_t_fdconnect(Config) ->
ct:fail({unexpected_accept_error, AReason})
catch
AC : AE : AS ->
- ?P("UNEXPECTED ERROR - catched accept: "
+ ?P("UNEXPECTED ERROR - caught accept: "
"~n C: ~p"
"~n E: ~p"
"~n S: ~p", [AC, AE, AS]),
@@ -893,6 +908,7 @@ do_local_fdopen(Config) ->
?P("listen socket created: ~p"
"~n => try connect ~p", [L, ConnectOpts]),
C0 = ok(gen_tcp:connect(SAddr, 0, ConnectOpts)),
+ ok = inet:setopts(C0, [{debug, true}]),
?P("connected: ~p"
"~n => get fd", [C0]),
Fd = if
@@ -1336,35 +1352,37 @@ do_simple_sockaddr_send_recv(SockAddr, _) ->
%% we have to skip on that platform.
s_accept_with_explicit_socket_backend(Config) when is_list(Config) ->
?TC_TRY(s_accept_with_explicit_socket_backend,
- fun() ->
- is_not_windows(),
- is_socket_supported()
- end,
+ fun() -> is_socket_supported() end,
fun() -> do_s_accept_with_explicit_socket_backend() end).
do_s_accept_with_explicit_socket_backend() ->
+ ?P("try create listen socket"),
{ok, S} = gen_tcp:listen(0, [{inet_backend, socket}]),
+ ?P("try get port number (via sockname)"),
{ok, {_, Port}} = inet:sockname(S),
ClientF = fun() ->
+ ?P("[client] try connect (tp ~p)", [Port]),
{ok, _} = gen_tcp:connect("localhost", Port, []),
- receive die -> exit(normal) after infinity -> ok end
+ ?P("[client] connected - wait for termination command"),
+ receive
+ die ->
+ ?P("[client] termination command received"),
+ exit(normal)
+ after infinity -> ok
+ end
end,
+ ?P("create client"),
Client = spawn_link(ClientF),
+ ?P("try accept"),
{ok, _} = gen_tcp:accept(S),
+ ?P("accepted - command client to terminate"),
Client ! die,
+ ?P("done"),
ok.
%%% Utilities
-is_not_windows() ->
- case os:type() of
- {win32, _} ->
- {skip, "Windows not supported"};
- _ ->
- ok
- end.
-
is_socket_supported() ->
try socket:info() of
_ ->
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 1e32f1b3cd..7ccab1892c 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,7 +56,13 @@
killing_multi_acceptors/1,
killing_multi_acceptors2/1,
several_accepts_in_one_go/1, accept_system_limit/1,
- active_once_closed/1, send_timeout/1, send_timeout_active/1,
+ active_once_closed/1,
+ send_timeout_basic_wo_autoclose/1,
+ send_timeout_basic_w_autoclose/1,
+ send_timeout_check_length/1,
+ send_timeout_para_wo_autoclose/1,
+ send_timeout_para_w_autoclose/1,
+ send_timeout_active/1,
send_timeout_resume/1,
otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1,
@@ -68,7 +74,8 @@
socket_monitor2/1,
socket_monitor2_manys/1,
socket_monitor2_manyc/1,
- otp_17492/1
+ otp_17492/1,
+ otp_18357/1
]).
%% Internal exports.
@@ -88,14 +95,14 @@ init_per_testcase(_Func, Config) ->
"~n Nodes: ~p"
"~n Links: ~p"
"~n Monitors: ~p",
- [Config, erlang:nodes(), pi(links), pi(monitors)]),
+ [Config, erlang:nodes(), links(), monitors()]),
kernel_test_global_sys_monitor:reset_events(),
?P("init_per_testcase -> done when"
"~n Nodes: ~p"
"~n Links: ~p"
- "~n Monitors: ~p", [erlang:nodes(), pi(links), pi(monitors)]),
+ "~n Monitors: ~p", [erlang:nodes(), links(), monitors()]),
Config.
end_per_testcase(_Func, Config) ->
@@ -104,7 +111,7 @@ end_per_testcase(_Func, Config) ->
"~n Nodes: ~p"
"~n Links: ~p"
"~n Monitors: ~p",
- [Config, erlang:nodes(), pi(links), pi(monitors)]),
+ [Config, erlang:nodes(), links(), monitors()]),
SysEvs = kernel_test_global_sys_monitor:events(),
@@ -122,7 +129,7 @@ suite() ->
{timetrap,{minutes,4}}].
all() ->
- %% This is a temporary messure to ensure that we can
+ %% This is a temporary measure to ensure that we can
%% test the socket backend without effecting *all*
%% applications on *all* machines.
%% This flag is set only for *one* host.
@@ -131,11 +138,13 @@ all() ->
[
{group, inet_backend_default},
{group, inet_backend_inet},
- {group, inet_backend_socket}
+ {group, inet_backend_socket},
+ {group, tickets}
];
_ ->
[
- {group, inet_backend_default}
+ {group, inet_backend_default},
+ {group, tickets}
]
end.
@@ -145,6 +154,8 @@ groups() ->
{inet_backend_inet, [], inet_backend_inet_cases()},
{inet_backend_socket, [], inet_backend_socket_cases()},
+ {tickets, [], ticket_cases()},
+
{ctrl_proc, [], ctrl_proc_cases()},
{close, [], close_cases()},
{active, [], active_cases()},
@@ -160,15 +171,15 @@ groups() ->
].
inet_backend_default_cases() ->
- all_cases().
+ all_std_cases().
inet_backend_inet_cases() ->
- all_cases().
+ all_std_cases().
inet_backend_socket_cases() ->
- all_cases().
+ all_std_cases().
-all_cases() ->
+all_std_cases() ->
[
{group, ctrl_proc},
iter_max_socks,
@@ -196,6 +207,11 @@ all_cases() ->
otp_17492
].
+ticket_cases() ->
+ [
+ otp_18357
+ ].
+
close_cases() ->
[
no_accept,
@@ -287,7 +303,11 @@ accept_cases() ->
send_timeout_cases() ->
[
- send_timeout,
+ send_timeout_basic_wo_autoclose,
+ send_timeout_basic_w_autoclose,
+ send_timeout_check_length,
+ send_timeout_para_wo_autoclose,
+ send_timeout_para_w_autoclose,
send_timeout_active,
send_timeout_resume
].
@@ -427,7 +447,7 @@ do_default_options(Config) ->
"-kernel inet_default_listen_options "
"\"{delay_send,true}\"",
fun() -> do_delay_send_2(Config) end),
- %% Active is to dangerous and is supressed
+ %% Active is to dangerous and is suppressed
{true,true,true} =
do_delay_on_other_node("-kernel inet_default_connect_options "
"\"{active,false}\" "
@@ -618,16 +638,25 @@ controlling_process_self(Config) when is_list(Config) ->
%% without doing any accept. The connected socket should receive
%% a tcp_closed message.
no_accept(Config) when is_list(Config) ->
- {ok, L} = ?LISTEN(Config, 0, []),
+ ?P("create listen socket"),
+ %% LOpts = [{debug, true}],
+ LOpts = [],
+ {ok, L} = ?LISTEN(Config, 0, LOpts),
{ok, {_, Port}} = inet:sockname(L),
- {ok, Client} = ?CONNECT(Config, localhost, Port, []),
+ ?P("create connection socket"),
+ %% COpts = [{debug, true}],
+ COpts = [],
+ {ok, Client} = ?CONNECT(Config, localhost, Port, COpts),
+ ?P("close listen socket"),
ok = gen_tcp:close(L),
+ ?P("await connection socket closed"),
receive
{tcp_closed, Client} ->
+ ?P("connection socket closed message received => OK"),
ok
after 5000 ->
- ct:fail(never_closed)
-
+ ?P("connection socket closed message *not* received => FAIL"),
+ ct:fail(never_closed)
end.
%% Send several packets to a socket and close it. All packets should
@@ -685,6 +714,7 @@ do_close_with_pending_output(Node, Config) ->
?P("~w -> sender spawned - accept connection", [?FUNCTION_NAME]),
{ok, A} = gen_tcp:accept(L),
?P("~w -> connection accepted - recv ~w data", [?FUNCTION_NAME, Total]),
+ %% ok = inet:setopts(A, [{debug, true}]),
case gen_tcp:recv(A, Total) of
{ok, Bin} when byte_size(Bin) == Total ->
?P("~w -> [OK] received expected ~w bytes of data - "
@@ -737,7 +767,11 @@ do_active_n(Config) ->
N = 3,
LS = ok(?LISTEN(Config, 0, [{active,N}])),
[{active,N}] = ok(inet:getopts(LS, [active])),
- ok = inet:setopts(LS, [{active,-N}]),
+ %% ok = inet:setopts(LS, [{active,-N}]),
+ %% The point of this is to "demonstrate" that its possible to
+ %% enable and then later disable debug in one (setopts) call!
+ %% Note the order! Its reversed!!
+ ok = inet:setopts(LS, [{debug, false}, {active,-N}, {debug, true}]),
receive
{tcp_passive, LS} -> ok
after
@@ -842,7 +876,8 @@ do_active_n(Config) ->
ok = gen_tcp:close(LS),
ok.
--define(OTP_3924_MAX_DELAY, 100).
+-define(OTP_3924_MAX_DELAY, 100).
+-define(OTP_3924_MIN_FACTOR, 4).
%% Taken out of the blue, but on intra host connections
%% I expect propagation of a close to be quite fast
%% so 100 ms seems reasonable.
@@ -852,6 +887,20 @@ otp_3924(Config) when is_list(Config) ->
?P("~w -> entry with"
"~n Config: ~p"
"~n Nodes: ~p", [?FUNCTION_NAME, Config, nodes()]),
+ Cond = fun() ->
+ case lists:keysearch(kernel_factor, 1, Config) of
+ %% Only run this on machines that are "fast enough"...
+ {value, {kernel_factor, Factor}}
+ when (Factor =< ?OTP_3924_MIN_FACTOR) ->
+ ?P("~w:condition -> "
+ "*fast* enough (~w)", [?FUNCTION_NAME, Factor]),
+ ok;
+ _ ->
+ ?P("~w:condition -> "
+ "*not* fast enough", [?FUNCTION_NAME]),
+ {skip, "Too slow for this test"}
+ end
+ end,
Pre = fun() ->
?P("~w:pre -> calculate max delay", [?FUNCTION_NAME]),
MaxDelay = (case has_superfluous_schedulers() of
@@ -881,7 +930,7 @@ otp_3924(Config) when is_list(Config) ->
?P("~w:post -> try stop node ~p", [?FUNCTION_NAME, Node]),
?STOP_NODE(Node)
end,
- ?TC_TRY(?FUNCTION_NAME, Pre, TC, Post).
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, TC, Post).
do_otp_3924(Config, Node, MaxDelay) ->
DataLen = 100*1024,
@@ -949,8 +998,8 @@ otp_3924_receive_data(Sock, TimeoutRef, MaxDelay, Len, Acc, AccLen) ->
if
NewAccLen == Len ->
{ok, TRef} = timer:exit_after(MaxDelay,
- self(),
- TimeoutRef),
+ self(),
+ TimeoutRef),
{error, closed} = gen_tcp:recv(Sock, 0),
timer:cancel(TRef),
lists:flatten([Acc, Data]);
@@ -1046,83 +1095,169 @@ iter_max_socks() ->
%% Open as many sockets as possible. Do this several times and check
%% that we get the same number of sockets every time.
+%% Guess: This is "supposed to" test for socket leakage
+%% This works badly with the socket inet_backend, so make some "checks"
iter_max_socks(Config) when is_list(Config) ->
- %% This is not *nearly* enough
- %% We have some crap machines, which we need to "handle with care"...
- Tries =
- case os:type() of
- {win32, _} ->
- 10;
- {unix, darwin} ->
- 10;
- _ ->
- 20
- end,
- %% Run on a different node in order to limit the effect if this test fails.
- Dir = filename:dirname(code:which(?MODULE)),
- {ok, Node} = ?START_NODE(test_iter_max_socks, "+Q 2048 -pa " ++ Dir),
- %% L = rpc:call(Node,?MODULE,do_iter_max_socks,[N, initalize]),
- L = iter_max_socks_run(Node,
- fun() ->
- exit(do_iter_max_socks(Config, Tries, initalize))
- end),
- ?STOP_NODE(Node),
+ Cond = fun() -> iter_max_socks_condition(Config) end,
+ Pre = fun() ->
+ %% This is not *nearly* enough
+ %% We have some crap machines,
+ %% which we need to "handle with care"...
+ Tries =
+ case os:type() of
+ {win32, _} ->
+ 10;
+ {unix, darwin} ->
+ 10;
+ _ ->
+ 20
+ end,
+ %% Run on a different node in order to
+ %% limit the effect if this test fails.
+ Dir = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = ?START_NODE(test_iter_max_socks,
+ "+Q 2048 -pa " ++ Dir),
+ #{tries => Tries,
+ node => Node}
+ end,
+ Case = fun(#{tries := Tries,
+ node := Node}) ->
+ do_iter_max_socks(Config, Tries, Node)
+ end,
+ Post = fun(#{node := Node}) ->
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+-define(IMS_MAX_ULIMIT, 4096).
- io:format("Result: ~p", [L]),
+iter_max_socks_condition(Config) ->
+ case ?IS_SOCKET_BACKEND(Config) of
+ true ->
+ case os:type() of
+ {unix, _} ->
+ MaxNumOpenFilesStr =
+ string:trim(os:cmd("ulimit -n")),
+ try list_to_integer(MaxNumOpenFilesStr) of
+ MaxNumOpenFile when
+ (MaxNumOpenFile =< ?IMS_MAX_ULIMIT) ->
+ ok;
+ MaxNumOpenFile ->
+ {skip, ?F("ulimit -n: ~w (> ~w)",
+ [MaxNumOpenFile, ?IMS_MAX_ULIMIT])}
+ catch
+ _:_:_ ->
+ %% Skip just to be on the safe side
+ {skip, "Works badly with the socket inet_backend"}
+ end;
+ _ ->
+ ok
+ end;
+ false ->
+ ok
+ end.
+
+
+do_iter_max_socks(Config, Tries, Node) ->
+ Self = self(),
+ L = iter_max_socks_run(
+ Node,
+ fun() ->
+ exit(iter_max_socks_runner(Config, Self, Tries, initialize))
+ end),
+ ?P("Result: "
+ "~n ~p", [L]),
all_equal(L),
{comment, "Max sockets: " ++ integer_to_list(hd(L))}.
iter_max_socks_run(Node, F) ->
try erlang:spawn_opt(Node, F, [monitor]) of
{Pid, MRef} when is_pid(Pid) andalso is_reference(MRef) ->
- receive
- {'DOWN', MRef, process, Pid, Res} ->
- Res
- end;
+ iter_max_socks_await_runner(Node, Pid, MRef);
_Any ->
?P("Unexpected process start result: "
"~n ~p", [_Any]),
- {skip, "Failed starting iterator (slave) process"}
+ {skip, "Failed starting iterator (remote) process"}
catch
C:E:S ->
- ?P("Failed starting iterator (slave) process: "
+ ?P("Failed starting iterator (remote) process: "
"~n Class: ~p"
"~n Error: ~p"
"~n Stack: ~p", [C, E, S]),
- {skip, "Failed starting iterator (slave) process"}
+ {skip, "Failed starting iterator (remote) process"}
end.
-
+
+iter_max_socks_await_runner(Node, Pid, MRef) ->
+ erlang:monitor_node(Node, true),
+ Start = millis(),
+ iter_max_socks_await_runner2(Node, Pid, MRef, Start, Start).
+
+iter_max_socks_await_runner2(Node, Pid, MRef, Start, Timestamp) ->
+ receive
+ {'DOWN', MRef, process, Pid, Res} ->
+ T = millis(),
+ ?P("received runner result after ~w ms "
+ "(~w ms since last status)", [T - Start, T - Timestamp]),
+ erlang:monitor_node(Node, false),
+ Res;
+
+ {nodedown, Node} = NODEDOWN ->
+ ?P("Received unexpected ~p 'nodedown'", [Node]),
+ NODEDOWN;
+
+ {status, Action, Info} ->
+ T = millis(),
+ ?P("Received status message (after ~w ms) from the runner ~p: "
+ "~n ~p => ~p", [T - Timestamp, Pid, Action, Info]),
+ iter_max_socks_await_runner2(Node, Pid, MRef, Start, T);
+
+ Any ->
+ ?P("Received unexpected message while waiting for the runner ~p: "
+ "~n ~p", [Pid, Any]),
+ iter_max_socks_await_runner2(Node, Pid, MRef, Start, Timestamp)
+
+ after 5000 ->
+ ?P("timeout while waiting for the runner ~p", [Pid]),
+ iter_max_socks_await_runner2(Node, Pid, MRef, Start, Timestamp)
+ end.
+
-do_iter_max_socks(_Config, 0, _) ->
- ?P("do_iter_max_socks(0,-) -> done"),
+iter_max_socks_runner(_Config, _Parent, 0, _) ->
+ ?P("iter_max_socks_runner(0,-) -> done"),
[];
-do_iter_max_socks(Config, N, initalize = First) ->
- ?P("do_iter_max_socks(~w,~w) -> entry", [N, First]),
+iter_max_socks_runner(Config, Parent, N, initialize = First) ->
+ ?P("iter_max_socks_runner(~w,~w) -> entry", [N, First]),
+ Parent ! {status, start_socks_counting, First},
MS = max_socks(Config),
- [MS|do_iter_max_socks(Config, N-1, MS)];
-do_iter_max_socks(Config, N, failed = First) ->
- ?P("do_iter_max_socks(~w,~w) -> entry", [N, First]),
+ [MS|iter_max_socks_runner(Config, Parent, N-1, MS)];
+iter_max_socks_runner(Config, Parent, N, failed = First) ->
+ ?P("iter_max_socks_runner(~w,~w) -> entry", [N, First]),
+ Parent ! {status, start_socks_counting, First},
MS = max_socks(Config),
- [MS|do_iter_max_socks(Config, N-1, failed)];
-do_iter_max_socks(Config, N, First) when is_integer(First) ->
- ?P("do_iter_max_socks(~w,~w) -> entry", [N, First]),
+ [MS|iter_max_socks_runner(Config, Parent, N-1, First)];
+iter_max_socks_runner(Config, Parent, N, First) when is_integer(First) ->
+ ?P("iter_max_socks_runner(~w,~w) -> entry", [N, First]),
+ Parent ! {status, start_socks_counting, First},
MS = max_socks(Config),
if
(MS =:= First) ->
- [MS|do_iter_max_socks(Config, N-1, First)];
+ [MS|iter_max_socks_runner(Config, Parent, N-1, First)];
true ->
?P("~w =/= ~w => sleeping for ~p seconds...",
[MS, First, ?RETRY_SLEEP/1000]),
ct:sleep(?RETRY_SLEEP),
- ?P("Trying again...", []),
+ ?P("iter_max_socks_runner(~w,~w) -> trying again", [N, First]),
+ Parent ! {status, retry_socks_counting, {First, MS}},
RetryMS = max_socks(Config),
if RetryMS == First ->
- [RetryMS|do_iter_max_socks(Config, N-1, First)];
+ [RetryMS|iter_max_socks_runner(Config, Parent, N-1, First)];
true ->
- [RetryMS|do_iter_max_socks(Config, N-1, failed)]
- end
+ [RetryMS|iter_max_socks_runner(Config, Parent, N-1, failed)]
+ end
end.
+all_equal({skip, _} = SKIP) ->
+ throw(SKIP);
all_equal([]) ->
ok;
all_equal([Rule | T]) ->
@@ -1139,9 +1274,12 @@ all_equal(_Rule, []) ->
ok.
max_socks(Config) ->
+ put(state, open),
Socks = open_socks(Config),
N = length(Socks),
+ put(state, close),
lists:foreach(fun(S) -> ok = gen_tcp:close(S) end, Socks),
+ put(state, ready),
?P("Got ~p sockets", [N]),
N.
@@ -1344,6 +1482,7 @@ do_sort(Config, P, List0) ->
{error, eaddrnotavail = Reason} ->
?SKIPT(connect_failed_str(Reason))
end,
+ ok = inet:setopts(S, [{debug, true}]),
send_lines(S, List),
ok = gen_tcp:shutdown(S, write),
Lines = collect_lines(S, true),
@@ -1496,7 +1635,7 @@ a_server2(L) ->
%%
show_econnreset_active(Config) when is_list(Config) ->
- ?TC_TRY(show_econnreset_active,
+ ?TC_TRY(?FUNCTION_NAME,
fun() -> do_show_econnreset_active(Config) end).
do_show_econnreset_active(Config) ->
@@ -1563,7 +1702,7 @@ do_show_econnreset_active(Config) ->
end.
show_econnreset_active_once(Config) when is_list(Config) ->
- ?TC_TRY(show_econnreset_active_once,
+ ?TC_TRY(?FUNCTION_NAME,
fun() -> do_show_econnreset_active_once(Config) end).
do_show_econnreset_active_once(Config) ->
@@ -1602,7 +1741,7 @@ do_show_econnreset_active_once(Config) ->
end.
show_econnreset_passive(Config) when is_list(Config) ->
- ?TC_TRY(show_econnreset_passive,
+ ?TC_TRY(?FUNCTION_NAME,
fun() -> do_show_econnreset_passive(Config) end).
do_show_econnreset_passive(Config) ->
@@ -1638,10 +1777,12 @@ do_show_econnreset_passive(Config) ->
ok = inet:setopts(S1, [{linger, {true, 0}}]),
ok = gen_tcp:close(S1),
ok = ct:sleep(1),
- {error, econnreset} = gen_tcp:recv(Client1, 0).
+ {error, econnreset} = gen_tcp:recv(Client1, 0),
+ ?P("done"),
+ ok.
econnreset_after_sync_send(Config) when is_list(Config) ->
- ?TC_TRY(econnreset_after_sync_send,
+ ?TC_TRY(?FUNCTION_NAME,
fun() -> do_econnreset_after_sync_send(Config) end).
do_econnreset_after_sync_send(Config) ->
@@ -1679,10 +1820,12 @@ do_econnreset_after_sync_send(Config) ->
ok = inet:setopts(S1, [{linger, {true, 0}}]),
ok = gen_tcp:close(S1),
ok = ct:sleep(20),
- {error, econnreset} = gen_tcp:send(Client1, "Whatever").
+ {error, econnreset} = gen_tcp:send(Client1, "Whatever"),
+ ?P("done"),
+ ok.
econnreset_after_async_send_active(Config) when is_list(Config) ->
- ?TC_TRY(econnreset_after_async_send_active,
+ ?TC_TRY(?FUNCTION_NAME,
fun() -> do_econnreset_after_async_send_active(Config) end).
do_econnreset_after_async_send_active(Config) ->
@@ -2100,7 +2243,7 @@ do_econnreset_after_async_send_passive(Config) ->
ok = ct:sleep(20),
?P("verify 1 (default)"),
- ?line ok = craasp_verify(Client1, default, SPayload),
+ ok = craasp_verify(Client1, default, SPayload),
?P("cleanup 1 (default)"),
craasp_cleanup(Client1, Sender1),
@@ -2120,7 +2263,7 @@ do_econnreset_after_async_send_passive(Config) ->
ok = ct:sleep(20),
?P("verify 2 (default)"),
- ?line ok = craasp_verify(Client2, true, SPayload),
+ ok = craasp_verify(Client2, true, SPayload),
?P("cleanup 2 (default)"),
craasp_cleanup(Client2, Sender2),
@@ -2388,11 +2531,11 @@ lz_ensure_non_empty_queue(Sock, Payload, OS, N) ->
?P("try verify client socket queue size"),
case erlang:port_info(Sock, queue_size) of
{queue_size, QSz} when QSz > 0 ->
- ?P("queue size verification *successfull* (~p) - port info: "
+ ?P("queue size verification *successful* (~p) - port info: "
"~n ~p", [QSz, erlang:port_info(Sock)]),
ok;
{queue_size, 0} when OS =:= win32 ->
- ?P("queue size verification *successfull* - port info: "
+ ?P("queue size verification *successful* - port info: "
"~n ~p", [erlang:port_info(Sock)]),
ok;
{queue_size, 0} ->
@@ -3349,7 +3492,7 @@ test_prio_accept_async(Config) ->
{Ref,{ok,[{priority,4},{tos,Tos1}]}} ->
ok;
{Ref,Error} ->
- ct:fail({missmatch,Error})
+ ct:fail({mismatch,Error})
after 5000 -> ct:fail({error,"helper process timeout"})
end,
?P("test_prio_accept_async -> await prio and tos for accepted socket"),
@@ -3357,7 +3500,7 @@ test_prio_accept_async(Config) ->
{Ref,{ok,[{priority,4},{tos,Tos1}]}} ->
ok;
{Ref,Error2} ->
- ct:fail({missmatch,Error2})
+ ct:fail({mismatch,Error2})
after 5000 -> ct:fail({error,"helper process timeout"})
end,
@@ -3406,7 +3549,7 @@ test_prio_udp() ->
so_priority(Config) when is_list(Config) ->
?TC_TRY(so_priority,
%% Normally we should have the condition funm here,
- %% but since we are (currently) not platform independant,
+ %% but since we are (currently) not platform independent,
%% we can't...check in the test case instead.
fun() -> do_so_priority(Config) end).
@@ -3831,16 +3974,16 @@ sets_eq(L1, L2) ->
millis() ->
erlang:monotonic_time(millisecond).
-collect_accepts(0,_) -> [];
-collect_accepts(N,Tmo) ->
+collect_accepts(0, _) -> [];
+collect_accepts(N, Tmo) ->
A = millis(),
receive
{accepted, P, {error, eaddrnotavail = Reason}} ->
?P("~p Failed accept: ~p", [P, Reason]),
?SKIPT(accept_failed_str(Reason));
- {accepted,P,Msg} ->
- ?P("received accepted from ~p: "
+ {accepted, P, Msg} ->
+ ?P("received 'accepted' from ~p: "
"~n ~p", [P, Msg]),
NextN = if N =:= infinity -> N; true -> N - 1 end,
[{P,Msg}] ++ collect_accepts(NextN, Tmo - (millis()-A))
@@ -3849,14 +3992,14 @@ collect_accepts(N,Tmo) ->
?P("accept timeout (~w)", [Tmo]),
[]
end.
-
+
-define(EXPECT_ACCEPTS(Pattern,N,Timeout),
(fun() ->
case collect_accepts((N), (Timeout)) of
Pattern ->
ok;
Other__ ->
- {error,{unexpected,{Other__,process_info(self(),messages)}}}
+ {error, {unexpected, {Other__, messages()}}}
end
end)()).
@@ -3887,7 +4030,13 @@ collect_connects(Tmo) ->
end)()).
mktmofun(Tmo,Parent,LS) ->
- fun() -> Parent ! {accepted,self(), catch gen_tcp:accept(LS,Tmo)} end.
+ fun() ->
+ ?P("[acceptor] mktmofun:fun -> try accept"),
+ AcceptResult = catch gen_tcp:accept(LS, Tmo),
+ ?P("[acceptor] mktmofun:fun -> accepted: "
+ "~n ~p", [AcceptResult]),
+ Parent ! {accepted,self(), AcceptResult}
+ end.
%% Accept tests
%% Test singular accept.
@@ -4101,26 +4250,47 @@ do_accept_timeouts_in_order5(Config) ->
%% Check that multi-accept timeouts happen in the correct order after
%% mixing millsec and sec timeouts (even more).
accept_timeouts_in_order6(Config) when is_list(Config) ->
- try do_accept_timeouts_in_order6(Config)
- catch
- throw:{skip, _} = SKIP ->
- SKIP
- end.
+ ?TC_TRY(?FUNCTION_NAME,
+ fun() ->
+ ?P("try create listen socket"),
+ case ?LISTEN(Config, 0,[]) of
+ {ok, LSocket} ->
+ #{socket => LSocket};
+ {error, eaddrnotavail = Reason} ->
+ ?P("failed creating socket: ~p", [Reason]),
+ {skip, listen_failed_str(Reason)}
+ end
+ end,
+ fun(I) -> do_accept_timeouts_in_order6(I) end,
+ fun(#{socket := LSock}) ->
+ gen_tcp:close(LSock)
+ end).
-do_accept_timeouts_in_order6(Config) ->
- LS = case ?LISTEN(Config, 0,[]) of
- {ok, LSocket} ->
- LSocket;
- {error, eaddrnotavail = Reason} ->
- ?SKIPT(listen_failed_str(Reason))
- end,
+do_accept_timeouts_in_order6(#{socket := LS}) ->
Parent = self(),
+
+ ?P("create acceptor 1 with timeout 1000"),
P1 = spawn(mktmofun(1000,Parent,LS)),
+
+ ?P("create acceptor 2 with timeout 400"),
P2 = spawn(mktmofun(400,Parent,LS)),
+
+ ?P("create acceptor 3 with timeout 600"),
P3 = spawn(mktmofun(600,Parent,LS)),
+
+ ?P("create acceptor 4 with timeout 200"),
P4 = spawn(mktmofun(200,Parent,LS)),
- ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P2,{error,timeout}},
- {P3,{error,timeout}},{P1,{error,timeout}}],infinity,2000).
+
+ ?P("await accept timeouts from (in order): "
+ "~n Acceptor 4: ~p"
+ "~n Acceptor 2: ~p"
+ "~n Acceptor 3: ~p"
+ "~n Acceptor 1: ~p", [P4, P2, P3, P1]),
+ ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},
+ {P2,{error,timeout}},
+ {P3,{error,timeout}},
+ {P1,{error,timeout}}],
+ infinity, 2000).
%% Check that multi-accept timeouts happen in the correct order after
%% mixing millsec and sec timeouts (even more++).
@@ -4311,7 +4481,7 @@ validate_acceptor_state(LS, ExpStates, ExpNotStates) when is_port(LS) ->
case inet:info(LS) of
#{states := States} ->
- ?P("try validate state when: "
+ ?P("try validate (listen socket) state when: "
"~n Exp States: ~p"
"~n Exp Not States: ~p"
"~n States: ~p", [ExpStates, ExpNotStates, States]),
@@ -4403,7 +4573,7 @@ validate_acceptor_state(LS, ExpNumAcc, ExpState, ExpNotState) ->
%% Check that multi acceptors behaves as expected when killed.
killing_multi_acceptors(Config) when is_list(Config) ->
- ?TC_TRY(killing_multi_acceptors,
+ ?TC_TRY(?FUNCTION_NAME,
fun() -> do_killing_multi_acceptors(Config) end).
do_killing_multi_acceptors(Config) ->
@@ -4424,32 +4594,32 @@ do_killing_multi_acceptors_inet(LS) ->
validate_acceptor_state(LS, [listen], []),
Parent = self(),
- F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS)} end,
- F2 = mktmofun(1000,Parent,LS),
+ F1 = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS)} end,
+ Tmo = 1000,
+ F2 = mktmofun(1000,Parent,LS),
?P("create first acceptor"),
- Pid = spawn(F),
+ Pid1 = spawn(F1),
?P("create second acceptor - with timeout"),
Pid2 = spawn(F2),
?P("sleep some"),
- receive after 100 -> ok
- end,
+ receive after 100 -> ok end,
?P("validate state - accepting"),
validate_acceptor_state(LS, [accepting], []),
?P("kill first acceptor"),
- exit(Pid, kill),
+ exit(Pid1, kill),
?P("sleep some"),
- receive after 100 -> ok
- end,
+ receive after 100 -> ok end,
?P("validate state - still accepting"),
validate_acceptor_state(LS, [accepting], []),
- ?P("await second acceptor exit - timeout"),
- case ?EXPECT_ACCEPTS([{Pid2, {error,timeout}}], 1, 1000) of
+ ?P("await second acceptor exit (timeout)"),
+ %% In order to avoid race condition, double the time
+ case ?EXPECT_ACCEPTS([{Pid2, {error,timeout}}], 1, 2 * Tmo) of
ok ->
?P("second acceptor - expected result"),
ok;
@@ -4748,7 +4918,7 @@ accept_system_limit(Config) when is_list(Config) ->
Cond = fun() ->
case ?IS_SOCKET_BACKEND(Config) of
true ->
- {skip, "Not complient with socket"};
+ {skip, "Not compliant with socket"};
false ->
ok
end
@@ -5045,31 +5215,126 @@ anc_await_closed_and_down(S, Pid, MRef, Size, Closed, Down) ->
anc_await_closed_and_down(S, Pid, MRef, Size, Closed, Down)
end.
-%% Test the send_timeout socket option.
-send_timeout(Config) when is_list(Config) ->
- ?TC_TRY(send_timeout, fun() -> do_send_timeout(Config) end).
-do_send_timeout(Config) ->
- ?P("begin"),
- Dir = filename:dirname(code:which(?MODULE)),
- ?P("create (slave) node"),
- {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+send_timeout_cfg(Config) ->
+ send_timeout_cfg(Config, default).
- {TslTimeout, SndTimeout, BinData, SndBuf} =
- case ?IS_SOCKET_BACKEND(Config) of
- true ->
- {100, 3000, binary:copy(<<$a:8>>, 10*1024), 5*1024};
- false ->
- {1, 1000, binary:copy(<<$a:8>>, 1*1024), 16*1024}
- end,
+send_timeout_cfg(Config, Case) ->
+ case ?IS_SOCKET_BACKEND(Config) of
+ true when (Case =:= send_timeout_check_length) ->
+ {100, 3000, binary:copy(<<$a:8>>, 1*1024), 5*1024};
+ true ->
+ {100, 3000, binary:copy(<<$a:8>>, 10*1024), 5*1024};
+ false ->
+ {1, 1000, binary:copy(<<$a:8>>, 1*1024), 16*1024}
+ end.
- %% Basic
- ?P("basic check wo autoclose"),
+%% Test the send_timeout socket option.
+send_timeout_basic_wo_autoclose(Config) when is_list(Config) ->
+ Pre = fun() ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ ?P("create node"),
+ {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+ RNode
+ end,
+ Case = fun(Node) ->
+ do_send_timeout_basic_wo_autoclose(Config, Node)
+ end,
+ Post = fun(Node) ->
+ ?P("stop node ~p", [Node]),
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Pre, Case, Post).
+
+do_send_timeout_basic_wo_autoclose(Config, RNode) ->
+ ?P("begin"),
+ {TslTimeout, SndTimeout, BinData, SndBuf} = send_timeout_cfg(Config),
send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
false, RNode),
- ?P("basic check w autoclose"),
+ ?P("done"),
+ ok.
+
+%% Test the send_timeout socket option.
+send_timeout_basic_w_autoclose(Config) when is_list(Config) ->
+ Pre = fun() ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ ?P("create node"),
+ {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+ RNode
+ end,
+ Case = fun(Node) ->
+ do_send_timeout_basic_w_autoclose(Config, Node)
+ end,
+ Post = fun(Node) ->
+ ?P("stop node ~p", [Node]),
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Pre, Case, Post).
+
+do_send_timeout_basic_w_autoclose(Config, RNode) ->
+ ?P("begin"),
+ {TslTimeout, SndTimeout, BinData, SndBuf} =
+ send_timeout_cfg(Config, send_timeout_basic_w_autoclose),
send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
true, RNode),
+ ?P("done"),
+ ok.
+
+send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
+ AutoClose, RNode) ->
+ ?P("[basic] sink"),
+ {A, Pid} = setup_timeout_sink(Config, RNode, SndTimeout,
+ AutoClose, SndBuf),
+ Send = fun() -> gen_tcp:send(A, BinData) end,
+ {{error, timeout}, _} = timeout_sink_loop(Send, TslTimeout),
+
+ %% Check that the socket is not busy/closed...
+ ?P("[basic] verify socket not busy/closed"),
+ case gen_tcp:send(A, BinData) of
+ {error, Reason} ->
+ ?P("[basic] (expected) send failure"),
+ after_send_timeout(AutoClose, Reason),
+ (catch gen_tcp:close(A)),
+ exit(Pid, kill),
+ ok;
+ ok ->
+ %% Note that there is no active reader on the other end,
+ %% so a 'channel' has been filled, should remain filled.
+ ?P("[basic] UNEXPECTED send success"),
+ (catch gen_tcp:close(A)),
+ exit(Pid, kill),
+ ct:fail("Unexpected send success")
+ end.
+
+
+%% Test the send_timeout socket option.
+send_timeout_check_length(Config) when is_list(Config) ->
+ Cond = fun() ->
+ Key = kernel_factor,
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, Factor}} when (Factor > 6) ->
+ {skip, ?F("Too slow (factor = ~w)", [Factor])};
+ _ ->
+ ok
+ end
+ end,
+ Pre = fun() ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ ?P("create node"),
+ {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+ RNode
+ end,
+ Case = fun(Node) -> do_send_timeout_check_length(Config, Node) end,
+ Post = fun(Node) ->
+ ?P("stop node ~p", [Node]),
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_send_timeout_check_length(Config, RNode) ->
+ ?P("begin"),
+ {TslTimeout, SndTimeout, BinData, SndBuf} =
+ send_timeout_cfg(Config, send_timeout_check_length),
%% Check timeout length.
?P("spawn sink process (check timeout length)"),
@@ -5077,17 +5342,29 @@ do_send_timeout(Config) ->
{Pid, Mon} = spawn_monitor(
fun() ->
{A, _} = setup_timeout_sink(Config,
- RNode, SndTimeout,
- true, SndBuf),
+ RNode, SndTimeout,
+ true, SndBuf),
Send = fun() ->
+ %% <TMP>
+ %% snmp:enable_trace(),
+ %% snmp:set_trace([{gen_tcp_socket,
+ %% [{scope, send}]},
+ %% {socket, [{scope,getopt}]},
+ %% {socket, [{scope,send}]}],
+ %% [{timestamp, true},
+ %% {return_trace, true}]),
+ %% inet:setopts(A, [{debug, true}]),
Res = gen_tcp:send(A, BinData),
+ %% inet:setopts(A, [{debug, false}]),
+ %% snmp:disable_trace(),
+ %% </TMP>
Self ! Res,
Res
end,
{{error, timeout}, _} =
timeout_sink_loop(Send, TslTimeout)
end),
- Diff = get_max_diff(),
+ Diff = get_max_diff(Pid),
?P("Max time for send: ~p", [Diff]),
true = (Diff > (SndTimeout - 500)) and (Diff < (SndTimeout + 500)),
@@ -5095,45 +5372,90 @@ do_send_timeout(Config) ->
?P("await (timeout checker) process death"),
receive {'DOWN', Mon, process, Pid, _} -> ok end,
- %% Check that parallell writers do not hang forever
- ?P("check parallell writers wo autoclose"),
+ ?P("done"),
+ ok.
+
+%% Test the send_timeout socket option.
+send_timeout_para_wo_autoclose(Config) when is_list(Config) ->
+ Cond = fun() ->
+ Key = kernel_factor,
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, Factor}} when (Factor > 6) ->
+ {skip, ?F("Too slow (factor = ~w)", [Factor])};
+ _ ->
+ ok
+ end
+ end,
+ Pre = fun() ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ ?P("create node"),
+ {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+ RNode
+ end,
+ Case = fun(Node) -> do_send_timeout_para_wo_autoclose(Config, Node) end,
+ Post = fun(Node) ->
+ ?P("stop node ~p", [Node]),
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_send_timeout_para_wo_autoclose(Config, RNode) ->
+ ?P("begin"),
+ {TslTimeout, SndTimeout, BinData, SndBuf} = send_timeout_cfg(Config),
+
+ %% Check that parallel writers do not hang forever
+ ?P("check parallel writers wo autoclose"),
send_timeout_para(Config, BinData, SndBuf, TslTimeout, SndTimeout,
false, RNode),
- ?P("check parallell writers w autoclose"),
- send_timeout_para(Config, BinData, SndBuf, TslTimeout, SndTimeout,
- true, RNode),
-
- ?P("stop (slave) node"),
- ?STOP_NODE(RNode),
?P("done"),
ok.
-send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
- AutoClose, RNode) ->
- ?P("[basic] sink"),
- {A, Pid} = setup_timeout_sink(Config, RNode, SndTimeout,
- AutoClose, SndBuf),
- Send = fun() -> gen_tcp:send(A, BinData) end,
- {{error, timeout}, _} = timeout_sink_loop(Send, TslTimeout),
+%% Test the send_timeout socket option.
+%% send_timeout/send_timeout_close behaves differently on
+%% inet_backend 'socket' (compared to inet), so we skip
+%% this test case (until we can re-write).
+send_timeout_para_w_autoclose(Config) when is_list(Config) ->
+ Cond = fun() ->
+ case ?IS_SOCKET_BACKEND(Config) of
+ true ->
+ {skip, "Unstable with 'socket' backend"};
+ false ->
+ Key = kernel_factor,
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, Factor}} when (Factor > 6) ->
+ {skip,
+ ?F("Too slow (factor = ~w)", [Factor])};
+ _ ->
+ ok
+ end
+ end
+ end,
+ Pre = fun() ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ ?P("create node"),
+ {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+ RNode
+ end,
+ Case = fun(Node) -> do_send_timeout_para_w_autoclose(Config, Node) end,
+ Post = fun(Node) ->
+ ?P("stop node ~p", [Node]),
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, Case, Post).
- %% Check that the socket is not busy/closed...
- ?P("[basic] verify socket not busy/closed"),
- case gen_tcp:send(A, BinData) of
- {error, Reason} ->
- ?P("[basic] (expected) send failure"),
- after_send_timeout(AutoClose, Reason),
- (catch gen_tcp:close(A)),
- exit(Pid, kill),
- ok;
- ok ->
- %% Note that there is no active reader on the other end,
- %% so a 'channel' has been filled, should remain filled.
- ?P("[basic] UNEXPECTED send success"),
- (catch gen_tcp:close(A)),
- exit(Pid, kill),
- ct:fail("Unexpected send success")
- end.
+do_send_timeout_para_w_autoclose(Config, RNode) ->
+ ?P("begin"),
+ {TslTimeout, SndTimeout, BinData, SndBuf} =
+ send_timeout_cfg(Config, send_timeout_para_w_autoclose),
+
+ %% Check that parallel writers do not hang forever
+ ?P("check parallel writers wo autoclose"),
+ send_timeout_para(Config, BinData, SndBuf, TslTimeout, SndTimeout,
+ true, RNode),
+
+ ?P("done"),
+ ok.
send_timeout_para(Config, BinData, BufSz, TslTimeout, SndTimeout,
AutoClose, RNode) ->
@@ -5146,13 +5468,13 @@ send_timeout_para(Config, BinData, BufSz, TslTimeout, SndTimeout,
{A, Pid} = setup_timeout_sink(Config, RNode, SndTimeout, AutoClose, BufSz),
Self = self(),
SenderFun = fun() ->
- ?P("[para:sender] start"),
+ ?P("[para:sender] starting"),
Send = fun() -> gen_tcp:send(A, BinData) end,
Self ! {self(), timeout_sink_loop(Send, TslTimeout)}
end,
- ?P("[para] spawn process 1 with sender fun"),
+ ?P("[para] spawn sender process 1"),
Snd1 = spawn_link(SenderFun),
- ?P("[para] spawn process 2 with sender fun"),
+ ?P("[para] spawn sender process 2"),
Snd2 = spawn_link(SenderFun),
SockInfo = fun() -> (catch inet:info(A)) end,
@@ -5166,7 +5488,7 @@ send_timeout_para(Config, BinData, BufSz, TslTimeout, SndTimeout,
?F("UNKNOWN: ~p", [X2])
catch
C2:E2:S2 ->
- ?F("CATCHED: ~p, ~p, ~p", [C2, E2, S2])
+ ?F("CAUGHT: ~p, ~p, ~p", [C2, E2, S2])
end
end,
@@ -5289,12 +5611,34 @@ send_timeout_para(Config, BinData, BufSz, TslTimeout, SndTimeout,
?P("[para] cleanup - await sender terminations"),
st_await_sender_termination(Snd1, Snd2),
?P("[para] cleanup - close socket"),
- (catch gen_tcp:close(A)),
+ send_timeout_close(A),
?P("[para] cleanup - kill sink"),
exit(Pid, kill),
?P("[para] done"),
ok.
+%% Spawn a closer process, transfer "ownership" of the socket
+%% to it and then send it the socket (to close) at its leisure.
+send_timeout_close(Sock) ->
+ F = fun() ->
+ receive
+ {close, S} ->
+ (catch gen_tcp:close(S)),
+ exit(normal)
+ end
+ end,
+ Pid = spawn_link(F),
+ case gen_tcp:controlling_process(Sock, Pid) of
+ ok ->
+ Pid ! {close, Sock},
+ ok;
+ {error, Reason} ->
+ ?P("failed transfering ownership to closer process: "
+ "~n ~p", [Reason]),
+ exit(Pid, kill),
+ (catch gen_tcp:close(Sock))
+ end.
+
st_await_sender_termination(undefined, undefined) ->
ok;
st_await_sender_termination(Sender1, Sender2) ->
@@ -5309,15 +5653,18 @@ st_await_sender_termination(Sender1, Sender2) ->
st_await_sender_termination(Sender1, undefined)
end.
-get_max_diff() ->
+get_max_diff(Pid) when is_pid(Pid) ->
receive
ok ->
- get_max_diff(0)
+ get_max_diff2(0)
after 10000 ->
+ ?P("timeout awaiting first send result (ok) from sender ~p:"
+ "~n Sender process info: ~p",
+ [Pid, pi(Pid)]),
exit(timeout)
end.
-get_max_diff(Max) ->
+get_max_diff2(Max) ->
T1 = millis(),
receive
ok ->
@@ -5325,11 +5672,11 @@ get_max_diff(Max) ->
if
Diff > Max ->
?P("new max send time: ~w", [Diff]),
- get_max_diff(Diff);
+ get_max_diff2(Diff);
true ->
- get_max_diff(Max)
+ get_max_diff2(Max)
end;
- {error,timeout} ->
+ {error, timeout} ->
Diff = millis() - T1,
if
Diff > Max ->
@@ -5460,12 +5807,12 @@ flush() ->
setup_closed_ao(Config) ->
Dir = filename:dirname(code:which(?MODULE)),
- ?P("[setup] start slave node"),
+ ?P("[setup] start node"),
R = case ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir) of
- {ok, Slave} ->
- Slave;
+ {ok, Node} ->
+ Node;
{error, Reason} ->
- ?SKIPT(?F("failed starting slave node: ~p", [Reason]))
+ ?SKIPT(?F("failed starting node: ~p", [Reason]))
end,
Host = get_hostname(node()),
?P("[setup] create listen socket"),
@@ -5527,54 +5874,92 @@ setup_closed_ao(Config) ->
end
end,
Loop = fun(Match2,F3) -> Loop2(Loop2,Match2,F3,10) end,
- ?P("[setup] stop slave node"),
+ ?P("[setup] stop node"),
?STOP_NODE(R),
?P("[setup] done"),
{Loop,A}.
setup_timeout_sink(Config, RNode, Timeout, AutoClose, BufSz) ->
- Host = get_hostname(node()),
- ?P("[sink] create listen socket"),
- {ok, L} = ?LISTEN(Config, 0, [{active, false},
+ ?P("[sink setup] create listen socket"),
+ {ok, Addr} = ?LIB:which_local_addr(inet),
+
+ ?P("[sink setup] create listen socket"),
+ {ok, L} = ?LISTEN(Config, 0, [{ifaddr, Addr},
+ {active, false},
{packet, 4},
{sndbuf, BufSz},
{send_timeout, Timeout},
{send_timeout_close, AutoClose}]),
- Fun = fun(F) ->
+
+ ?P("listen socket created with: "
+ "~n Send Timeout Opts: ~p",
+ [oki(inet:getopts(L, [send_timeout, send_timeout_close]))]),
+ Fun = fun(N, F) ->
receive
{From,X} when is_function(X) ->
- From ! {self(),X()}, F(F);
- die -> ok
+ From ! {self(),X()}, F(N+1,F);
+ {From, iterations} ->
+ From ! {self(), N}, F(N, F);
+ die ->
+ ok
end
end,
- ?P("[sink] start remote runner process (on ~p)", [RNode]),
- Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]),
+ ?P("[sink setup] start remote runner process (on ~p)", [RNode]),
+ Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(0,Fun) end]),
{ok, Port} = inet:port(L),
Remote = fun(Fu) ->
Pid ! {self(), Fu},
- receive {Pid,X} -> X
+ receive
+ {Pid,X} -> X
end
end,
- ?P("[sink] connect from remote node (~p)", [RNode]),
+ ?P("[sink setup] connect from remote node (~p)", [RNode]),
{ok, C} = Remote(fun() ->
- ?CONNECT(Config, Host,Port,
- [{active, false},
+ ?CONNECT(Config, Addr, Port,
+ [{ifaddr, Addr},
+ {active, false},
{packet, 4},
+ {recbuf, BufSz div 2},
{sndbuf, BufSz div 2}])
end),
- ?P("[sink] accept"),
+ ?P("[sink setup] accept"),
{ok, A} = gen_tcp:accept(L),
- ?P("[sink] accepted - send test message"),
+ ?P("[sink setup] accepted with options: "
+ "~n Send Timeout Opts: ~p"
+ "~n => send 'test' message",
+ [oki(inet:getopts(A, [send_timeout, send_timeout_close]))]),
gen_tcp:send(A, "Hello"),
- ?P("[sink] message sent - "
- "recv 'check' message on remote node (~p)", [RNode]),
+ ?P("[sink setup] 'test' message sent - "
+ "recv 'test' message on remote node (~p)", [RNode]),
{ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end),
- ?P("[sink] cleanup - close listen socket"),
+ ?P("[sink setup] cleanup - close listen socket"),
(catch gen_tcp:close(L)),
- ?P("[sink] done with socket: "
- "~n ~p", [A]),
+
+ ?P("[sink setup] done when: "
+ "~n Accepted socket: ~p"
+ "~n Buffer Info: ~p"
+ "~n SockName: ~p"
+ "~n PeerName: ~p"
+ "~n Connected socket: ~p"
+ "~n Buffer Info: ~p"
+ "~n SockName: ~p"
+ "~n PeerName: ~p",
+ [A,
+ oki(inet:getopts(A, [buffer, recbuf, sndbuf])),
+ oki(inet:sockname(A)),
+ oki(inet:peername(A)),
+ C,
+ oki(Remote(fun() -> inet:getopts(C, [buffer, recbuf, sndbuf]) end)),
+ oki(Remote(fun() -> inet:sockname(C) end)),
+ oki(Remote(fun() -> inet:peername(C) end))]),
+
+ ?P("[sink setup] done"),
+
{A, Pid}.
+oki({ok, V}) -> V;
+oki(E) -> E.
+
setup_active_timeout_sink(Config, RNode, Timeout, AutoClose) ->
Host = get_hostname(node()),
ListenOpts = [binary,
@@ -5612,9 +5997,11 @@ setup_active_timeout_sink(Config, RNode, Timeout, AutoClose) ->
%% timeout_sink_loop(Action, 1).
timeout_sink_loop(Action, To) ->
- put(action, nothing),
- put(sent, 0),
- put(elapsed, 0),
+ put(action, nothing),
+ put(sent, 0),
+ put(elapsed, 0),
+ put(send_max, 0),
+ put(lsendts, "-"), % Last Send TS (time stamp)
timeout_sink_loop(Action, To, 0).
timeout_sink_loop(Action, To, N) ->
@@ -5622,9 +6009,16 @@ timeout_sink_loop(Action, To, N) ->
Start = erlang:monotonic_time(),
Ret = Action(),
Stop = erlang:monotonic_time(),
+ LSendTS = ?FTS(),
+ SendT = Stop - Start,
Elapsed = get(elapsed),
- put(elapsed, Elapsed + (Stop - Start)),
+ put(elapsed, Elapsed + SendT),
+ SendMax = get(send_max),
+ if (SendT > SendMax) -> put(send_max, SendT);
+ true -> ok
+ end,
put(action, sent),
+ put(lsendts, LSendTS),
N2 = N + 1,
put(sent, N2),
case Ret of
@@ -5642,7 +6036,7 @@ timeout_sink_loop(Action, To, N) ->
?P("[sink-loop] action result: "
"~n Number of actions: ~p"
"~n Elapsed time: ~p msec"
- "~n Result: timeout with ~w of rest data",
+ "~n Result: timeout with ~w bytes of rest data",
[N2,
erlang:convert_time_unit(get(elapsed), native, millisecond),
byte_size(RestData)]),
@@ -5659,42 +6053,58 @@ timeout_sink_loop(Action, To, N) ->
end.
+%% =========================================================================
send_timeout_resume(Config) when is_list(Config) ->
ct:timetrap(?SECS(16)),
- ?TC_TRY(
- send_timeout_resume,
- fun () -> do_send_timeout_resume(Config) end).
-
-do_send_timeout_resume(Config) ->
- Dir = filename:dirname(code:which(?MODULE)),
- {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
- try
- do_send_timeout_resume(Config, RNode, 12)
- after
- ?STOP_NODE(RNode)
- end.
+ Cond = fun() ->
+ case ?IS_SOCKET_BACKEND(Config) of
+ true ->
+ {skip, "Unstable with 'socket' backend"};
+ false ->
+ Key = kernel_factor,
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, Factor}} when (Factor > 6) ->
+ {skip,
+ ?F("Too slow (factor = ~w)", [Factor])};
+ _ ->
+ ok
+ end
+ end
+ end,
+ Pre = fun() ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ ?P("create node"),
+ {ok, RNode} = ?START_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
+ RNode
+ end,
+ Case = fun(Node) -> do_send_timeout_resume(Config, Node, 13) end,
+ Post = fun(Node) ->
+ ?P("stop node ~p", [Node]),
+ ?STOP_NODE(Node)
+ end,
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, Case, Post).
do_send_timeout_resume(Config, RNode, BlockPow) ->
BlockSize = 1 bsl BlockPow,
- 1 = rand:uniform(1),
- Seed = rand:export_seed(),
+ 1 = rand:uniform(1),
+ Seed = rand:export_seed(),
ListenOpts =
[inet,
binary,
{backlog, 2},
- {active, false}],
+ {active, false}],
ConnectOpts =
[inet,
{send_timeout, 0},
- {active, false},
+ {active, false},
binary],
StreamOpts =
[{high_watermark, BlockSize},
- {low_watermark, BlockSize bsr 1},
- {sndbuf, BlockSize},
- {recbuf, BlockSize},
- {buffer, BlockSize bsl 1}],
+ {low_watermark, BlockSize bsr 1},
+ {sndbuf, BlockSize},
+ {recbuf, BlockSize},
+ {buffer, BlockSize bsl 1}],
Client = self(),
Tag = make_ref(),
{Server, Mref} =
@@ -5724,12 +6134,18 @@ do_send_timeout_resume(Config, RNode, BlockPow) ->
{'DOWN', Mref, _, _, Error2} ->
ct:fail(Error2)
end,
+ RetryTimeout = str_which_retry_timeout(),
+ ?P("send"),
{N, Timeouts} =
- do_send_timeout_resume_send(C, Server, Tag, 0, BlockSize),
+ do_send_timeout_resume_send(C, Server, Tag,
+ RetryTimeout, BlockSize),
+ ?P("await server (~p) reply (DOWN)", [Server]),
receive
{'DOWN', Mref, _, _, Result} ->
- ?P("N = ~p, Timeouts = ~p, Result=~p~n",
- [N, Timeouts, Result]),
+ ?P("received DOWN message from server:"
+ "~n N: ~p"
+ "~n Timeouts: ~p"
+ "~n Result: ~p", [N, Timeouts, Result]),
case Result of
{Tag, ok, Count}
when Count =:= N * BlockSize,
@@ -5739,49 +6155,122 @@ do_send_timeout_resume(Config, RNode, BlockPow) ->
%% send buffer with send_timeout = 0,
%% so that did not work
1 < Timeouts ->
+ ?P("count checked out"),
ok;
+ {Tag, ok, Count} when Count =:= N * BlockSize ->
+ ?P("Unexpected number of timeouts: ~w", [Timeouts]),
+ ct:fail(Result);
+ {Tag, ok, Count} ->
+ ?P("Unexpected counts: "
+ "~n Got: ~p"
+ "~n Expected: ~p", [Count, N*BlockSize]),
+ ct:fail(Result);
+ {Tag, Res, _Count} ->
+ ?P("Unexpected res: "
+ "~n Res: ~p", [Res]),
+ ct:fail(Result);
_ ->
ct:fail(Result)
end
end
after
+ ?P("after: kill (failsafe) server"),
exit(Server, failsafe),
- gen_tcp:close(C)
+ ?P("after: close socket"),
+ gen_tcp:close(C),
+ ?P("after: done"),
+ ok
end.
optnames(Opts) ->
[Name || {Name, _} <- Opts].
+str_which_retry_timeout() ->
+ case os:type() of
+ {unix, darwin} ->
+ %% This is really sketchy, but it seems to "work"...
+ %% Don't know if its the processor (M1) or if its the
+ %% OS/darwin version (darwin 21.x).
+ %% But since we don't have any intel macs running 21...
+ case os:version() of
+ {Major, _, _} when (Major >= 20) ->
+ 25;
+ _ ->
+ 100
+ end;
+ {unix, freebsd} ->
+ %% Has seen this on FreeBSD 12.2 and later.
+ case os:version() of
+ {Major, _, _} when (Major >= 13) ->
+ 25;
+ {Major, Minor, _} when (Major =:= 12) andalso
+ (Minor >= 2) ->
+ 25;
+ _ ->
+ 100
+ end;
+ _ ->
+ 100
+ end.
+
%% Fill buffers
-do_send_timeout_resume_send(S, Server, Tag, N, BlockSize) ->
+do_send_timeout_resume_send(S, Server, Tag, RetryTimeout, BlockSize) ->
+ ?P("try send-timeout-resume with"
+ "~n RetryTimeout: ~w ms"
+ "~n BlockSize: ~w", [RetryTimeout, BlockSize]),
+ do_send_timeout_resume_send(S, Server, Tag, 0, RetryTimeout, BlockSize).
+
+do_send_timeout_resume_send(S, Server, Tag, N, RetryTimeout, BlockSize) ->
Bin = random_data(BlockSize),
- case send_timeout_repeat(S, Server, Tag, N, Bin, 0) of
+ case send_timeout_repeat(S, Server, Tag, N, Bin, RetryTimeout, 0) of
0 ->
- do_send_timeout_resume_send(S, Server, Tag, N + 1, BlockSize);
+ do_send_timeout_resume_send(S, Server, Tag,
+ N + 1, RetryTimeout, BlockSize);
Timeouts ->
ok = gen_tcp:close(S),
{N + 1, Timeouts}
end.
-send_timeout_repeat(S, Server, Tag, N, Bin, Timeouts) ->
+send_timeout_repeat(S, Server, Tag, N, Bin, RetryTimeout, Timeouts) ->
case gen_tcp:send(S, Bin) of
ok ->
+ ?P("send_timeout_repeat -> success => done when"
+ "~n N: ~p"
+ "~n Timeouts: ~p"
+ "~n Socket Info: ~p", [N, Timeouts, (catch inet:info(S))]),
Timeouts;
{error, Reason} ->
case Reason of
timeout ->
+ ?P("send_timeout_repeat -> timeout:"
+ "~n S: ~p"
+ "~n N: ~p"
+ "~n Timeouts: ~p"
+ "~n Socket Info: ~p",
+ [S, N, Timeouts, (catch inet:info(S))]),
Server ! {Tag, rec},
- ?P("timeout ~p, ~p~n", [S, N]),
- receive after 100 -> ok end,
+ receive after RetryTimeout -> ok end,
send_timeout_repeat(
- S, Server, Tag, N, <<>>, Timeouts + 1);
+ S, Server, Tag, N, <<>>, RetryTimeout, Timeouts + 1);
{timeout, RestData} ->
+ ?P("send_timeout_repeat -> timeout with RestData: "
+ "~n S: ~p"
+ "~n N: ~p"
+ "~n Timeouts: ~p"
+ "~n Socket Info: ~p",
+ [S, N, Timeouts, (catch inet:info(S))]),
Server ! {Tag, rec},
- ?P("timeout, RestData ~p, ~p~n", [S, N]),
- receive after 100 -> ok end,
+ receive after RetryTimeout -> ok end,
send_timeout_repeat(
- S, Server, Tag, N, RestData, Timeouts + 1);
+ S, Server, Tag, N, RestData, RetryTimeout, Timeouts + 1);
_ ->
+ ?P("send_timeout_repeat -> unexpected send failure: "
+ "~n Reason: ~p"
+ "~n when"
+ "~n N: ~p"
+ "~n Timeouts: ~p"
+ "~n Socket Info: ~p",
+ [Reason, N, Timeouts, (catch inet:info(S))]),
error({Reason, N, Timeouts})
end
end.
@@ -5804,22 +6293,23 @@ compare_data(<<Byte, Bin/binary>>, Count) ->
send_timeout_resume_srv(Config, Seed, Client, Tag, ListenOpts, StreamOpts) ->
rand:seed(Seed),
{ok, L} = ?LISTEN(Config, 0, ListenOpts),
- ?P("get listen StreamOpts -> ~p",
+ ?P("[server] get listen StreamOpts -> ~p",
[inet:getopts(L, optnames(StreamOpts))]),
{ok, P} = inet:port(L),
Client ! {Tag, port, P},
%%
{ok, A} = gen_tcp:accept(L, 2000),
- ?P("accept success ~p~n", [A]),
+ ?P("[server] accept success ~p", [A]),
ok = inet:setopts(A, StreamOpts),
- ?P("get accept StreamOpts -> ~p",
+ ?P("[server] get accept StreamOpts -> ~p",
[inet:getopts(A, optnames(StreamOpts))]),
Client ! {Tag, send},
%%
receive
{Tag, rec} ->
- receive after 1000 -> ok end,
- ?P("receiving ~p~n", [A]),
+ ?P("[server] received recv command - now wait some time"),
+ receive after 5000 -> ok end,
+ ?P("[server] begin receiving (on ~p)", [A]),
exit({Tag, ok, send_timeout_resume_srv(A, 0)})
end.
@@ -6079,11 +6569,15 @@ do_otp_7816(Config) ->
[otp_7816_ctrl(Socket, 18, BinSize, Server) ||
BinSize <- lists:seq(1000, 2000, 123)],
- ?P("[ctrl] sending complete..."),
+ ?P("[ctrl] sending complete - close socket"),
ok = gen_tcp:close(Socket),
+ ?P("[ctrl] stop server"),
Server ! {self(), closed},
- {Server, closed} = receive M -> M end.
+ ?P("[ctrl] await server stopped"),
+ {Server, closed} = receive M -> M end,
+ ?P("[ctrl] done"),
+ ok.
otp_7816_ctrl(Socket, BinNr, BinSize, Server) ->
@@ -6615,7 +7109,7 @@ otp_12242(Config) when is_list(Config) ->
%% Even if we set sndbuf and recbuf to small sizes
%% Windows either happily accepts to send GBytes of
%% data in no time, so the second send below that
- %% is supposed to time out just succedes, or the
+ %% is supposed to time out just succeeds, or the
%% first send that is supposed to fill the inet_drv
%% I/O queue and start waiting for when more data
%% can be sent instead sends all data but suffers
@@ -6624,7 +7118,7 @@ otp_12242(Config) when is_list(Config) ->
_ ->
case ?IS_SOCKET_BACKEND(Config) of
true ->
- {skip, "Not complient with socket"};
+ {skip, "Not compliant with socket"};
false ->
ok
end
@@ -6797,7 +7291,7 @@ otp_12242_closer(C) ->
ok = Result
catch
Class:Reason:Stacktrace ->
- ?P("[closer] catched gen_tcp:close(C):"
+ ?P("[closer] caught gen_tcp:close(C):"
"~n Error Class: ~p"
"~n Error: ~p"
"~n Stack trace: ~p",
@@ -6870,7 +7364,7 @@ delay_send_error2(Sock) ->
delay_send_error2(Sock, 0) ->
gen_tcp:close(Sock),
- ct:fail("Unxpected send success");
+ ct:fail("Unexpected send success");
delay_send_error2(Sock, N) ->
%% Sleep in order for delay_send to have time to trigger
%% This used to result in a double free
@@ -6891,123 +7385,229 @@ delay_send_error2(Sock, N) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--define(ACTIVE_N, 20).
+-define(MAX_WORKERS, 30).
%% 30-second test for gen_tcp in {active, N} mode,
%% ensuring it does not get stuck.
%% Verifies that erl_check_io properly handles extra EPOLLIN signals.
bidirectional_traffic(Config) when is_list(Config) ->
- ?TC_TRY(bidirectional_traffic,
- fun() -> do_bidirectional_traffic(Config) end).
+ Pre = fun() ->
+ NumOnlineScheds = erlang:system_info(schedulers_online),
+ NumWorkers0 = NumOnlineScheds * 2,
+ {NumWorkers, ActiveN} =
+ if
+ (NumWorkers0 =< 10) ->
+ {NumWorkers0, 20};
+ (NumWorkers0 =< 20) ->
+ {NumWorkers0, 18};
+ (NumWorkers0 =< ?MAX_WORKERS) ->
+ {NumWorkers0, 15};
+ true ->
+ {?MAX_WORKERS, 15}
+ end,
+ ?P("pre ->"
+ "~n Number Of Online Schedulers: ~w"
+ "~n =>"
+ "~n Use workers: ~w"
+ "~n ActiveN: ~w",
+ [NumOnlineScheds, NumWorkers, ActiveN]),
+ Payload = crypto:strong_rand_bytes(32),
+ {ok, LSock} = ?LISTEN(Config,
+ 0,
+ [binary,
+ {packet, 0},
+ {active, false},
+ {reuseaddr, true}]),
+ %% get all sockets to know failing ends
+ ?P("pre -> listen socket created: "
+ "~n ~p", [LSock]),
+ #{lsock => LSock,
+ num_workers => NumWorkers,
+ payload => Payload,
+ %% The point of this is to make it "easy" to
+ %% "configure" this value...
+ active_n => ActiveN}
+ end,
+ Case = fun(Info) -> do_bidirectional_traffic(Config, Info) end,
+ Post = fun(#{lsock := LSock}) ->
+ ?P("post -> close listen socket"),
+ (catch gen_tcp:close(LSock))
+ end,
+ ?TC_TRY(?FUNCTION_NAME,
+ Pre, Case, Post).
-do_bidirectional_traffic(Config) ->
- ?P("begin"),
- Workers = erlang:system_info(schedulers_online) * 2,
- ?P("Use ~w workers", [Workers]),
- Payload = crypto:strong_rand_bytes(32),
- {ok, LSock} = ?LISTEN(Config,
- 0,
- [binary,
- {packet, 0},
- {active, false},
- {reuseaddr, true}]),
- %% get all sockets to know failing ends
- ?P("listen socket created: "
- "~n ~p", [LSock]),
+do_bidirectional_traffic(Config, #{lsock := LSock,
+ num_workers := NumWorkers} = Info) ->
+ ?P("case -> begin"),
{ok, Port} = inet:port(LSock),
- ?P("listen socket port number ~w", [Port]),
+ ?P("case -> listen socket port number ~w", [Port]),
Control = self(),
- ?P("create ~w receivers", [Workers]),
+ ?P("case -> create ~w receivers", [NumWorkers]),
Receivers = [spawn_link(fun () ->
- exchange(Config, LSock, Port, Payload, Control)
- end) || _ <- lists:seq(1, Workers)],
- ?P("await the result"),
+ exchange(Config,
+ Info#{port => Port,
+ ctrl => Control})
+ end) || _ <- lists:seq(1, NumWorkers)],
+ ?P("case -> await the result"),
+ %% Should we not collect as many as possible?
+ %% To see how many as issues?
Result =
%% If any of the receivers report, we have an error
receive
{timeout, Socket, Total} ->
- ?P("timeout msg for ~p: ~w", [Socket, Total]),
+ ?P("case -> timeout msg for ~p: received ~w", [Socket, Total]),
{fail, {timeout, Socket, Total}};
{error, Socket, Reason} ->
- ?P("error msg for ~p: ~p", [Socket, Reason]),
+ ?P("case -> error msg for ~p: ~p", [Socket, Reason]),
{fail, {error, Socket, Reason}}
after 30000 ->
%% if it does not fail in 30 seconds, it most likely works
- ?P("timeout => success"),
+ ?P("case -> timeout => success"),
ok
end,
- ?P("ensure all receivers terminated"),
- [begin unlink(Rec), exit(Rec, kill) end || Rec <- Receivers],
- ?P("close listen socket"),
- (catch gen_tcp:close(LSock)),
- ?P("done"),
+ ?P("case -> ensure all receivers terminated"),
+ %% [begin unlink(Rec), exit(Rec, kill) end || Rec <- Receivers],
+ bt_terminate_receivers(Receivers),
+ ?P("case -> done"),
Result.
+%% The point of this (function) is so that the 'receivers' should
+%% get a chance to "tell us" what they are up to...
+bt_terminate_receivers(Recvs) ->
+ bt_terminate_receivers_nice(Recvs),
+ ?SLEEP(?SECS(1)),
+ bt_terminate_receivers_force(Recvs).
+
+bt_terminate_receivers_nice(Recvs) ->
+ [begin
+ unlink(Recv),
+ Recv ! terminate
+ end || Recv <- Recvs].
+
+bt_terminate_receivers_force(Recvs) ->
+ [exit(Recv, kill) || Recv <- Recvs].
-exchange(Config, LSock, Port, Payload, Control) ->
+exchange(Config, #{lsock := LSock,
+ port := Port,
+ payload := Payload,
+ ctrl := Control,
+ active_n := ActiveN}) ->
%% spin up client
_ClntRcv = spawn_link(
fun () ->
- ?P("connect"),
+ ?P("exchange:client -> connect"),
{ok, Client} =
?CONNECT(Config,
"localhost",
Port,
- [binary, {packet, 0}, {active, ?ACTIVE_N}]),
- ?P("connected: ~p", [Client]),
- send_recv_loop(Client, Payload, Control)
+ [binary, {packet, 0}, {active, ActiveN}]),
+ ?P("exchange:client -> connected: ~p"
+ "~n PeerName: ~p"
+ "~n SockName: ~p",
+ [Client,
+ oki(inet:peername(Client)), oki(inet:sockname(Client))]),
+ put(role, connected),
+ send_recv_loop(Client, Payload, Control, ActiveN)
end),
- ?P("accept"),
+ ?P("exchange -> accept"),
{ok, Socket} = gen_tcp:accept(LSock),
- ?P("accepted: ~p", [Socket]),
+ ?P("exchange -> accepted: ~p"
+ "~n PeerName: ~p"
+ "~n SockName: ~p",
+ [Socket, oki(inet:peername(Socket)), oki(inet:sockname(Socket))]),
%% sending process
- send_recv_loop(Socket, Payload, Control).
+ put(role, accepted),
+ send_recv_loop(Socket, Payload, Control, ActiveN).
-send_recv_loop(Socket, Payload, Control) ->
+send_recv_loop(Socket, Payload, Control, ActiveN) ->
%% {active, N} must be set to active > 12 to trigger the issue
%% {active, 30} seems to trigger it quite often & reliably
- ?P("set (initial) active: ~p", [?ACTIVE_N]),
- inet:setopts(Socket, [{active, ?ACTIVE_N}]),
- ?P("spawn sender"),
+ Role = get(role),
+ ?P("[~w] set (initial) active: ~p", [Role, ActiveN]),
+ inet:setopts(Socket, [{active, ActiveN}]),
+ ?P("[~w] spawn sender", [Role]),
_Snd = spawn_link(
fun Sender() ->
case gen_tcp:send(Socket, Payload) of
ok ->
Sender();
+ {error, closed} ->
+ ?P("[~w,sender] Socket closed", [Role]),
+ exit(normal);
{error, Reason} ->
- ?P("Send failed: "
- "~n ~p", [Reason]),
+ ?P("[~w,sender] Send failed: "
+ "~n ~p", [Role, Reason]),
exit({send_failed, Reason})
end
end),
- ?P("begin recv"),
- recv(Socket, 0, Control).
+ ?P("[~w] begin recv", [Role]),
+ recv(Socket, 0, 0, 0, Control, ActiveN).
-recv(Socket, Total, Control) ->
+recv(Socket, Total, TotIter, TotAct, Control, ActiveN) ->
receive
+ terminate ->
+ ?P("[~w,recv] received terminate message when"
+ "~n Total received: ~w"
+ "~n Total iterations: ~w"
+ "~n Total activations: ~w"
+ "~n Socket: ~p"
+ "~n Socket Info: ~p",
+ [get(role),
+ Total, TotIter, TotAct,
+ Socket, (catch inet:info(Socket))]),
+ (catch gen_tcp:close(Socket)),
+ exit(normal);
+
{tcp, Socket, Data} ->
- recv(Socket, Total + byte_size(Data), Control);
+ recv(Socket,
+ Total + byte_size(Data), TotIter + 1, TotAct,
+ Control, ActiveN);
{tcp_passive, Socket} ->
- inet:setopts(Socket, [{active, ?ACTIVE_N}]),
- recv(Socket, Total, Control);
+ inet:setopts(Socket, [{active, ActiveN}]),
+ recv(Socket, Total, TotIter, TotAct + 1, Control, ActiveN);
{tcp_closed, Socket} ->
- ?P("[recv] closed when total received: ~w"
- "~n Socket Info: ~p",
- [Total, (catch inet:info(Socket))]),
+ ?P("[~w,recv] closed when"
+ "~n Total received: ~w"
+ "~n Total iterations: ~w"
+ "~n Total activations: ~w"
+ "~n Socket Info: ~p",
+ [get(role), Total, TotIter, TotAct, (catch inet:info(Socket))]),
ok;
+
Other ->
- ?P("[recv] received unexpected when total received: ~w"
- "~n ~p"
- "~n Socket: ~p"
- "~n Socket Info: ~p",
- [Total, Other, Socket, (catch inet:info(Socket))]),
+ ?P("[~w,recv] received unexpected message"
+ "~n Msg: ~p"
+ "~n when:"
+ "~n Total received: ~w"
+ "~n Total iterations: ~w"
+ "~n Total activations: ~w"
+ "~n Socket: ~p"
+ "~n PeerName: ~p"
+ "~n SockName: ~p"
+ "~n Socket Info: ~p",
+ [get(role),
+ Other,
+ Total, TotIter, TotAct,
+ Socket, oki(inet:peername(Socket)), oki(inet:sockname(Socket)),
+ (catch inet:info(Socket))]),
+ (catch gen_tcp:close(Socket)),
Control ! {error, Socket, Other}
+
after 2000 ->
%% no data received in 2 seconds => test failed
- ?P("[recv] received nothing when total received: ~w"
- "~n Socket: ~p"
- "~n Socket Info: ~p",
- [Total, Socket, (catch inet:info(Socket))]),
+ ?P("[~w,recv timeout] received nothing when:"
+ "~n Total received: ~w"
+ "~n Total iterations: ~w"
+ "~n Total activations: ~w"
+ "~n Socket: ~p"
+ "~n PeerName: ~p"
+ "~n SockName: ~p"
+ "~n Socket Info: ~p",
+ [get(role),
+ Total, TotIter, TotAct,
+ Socket, oki(inet:peername(Socket)), oki(inet:sockname(Socket)),
+ (catch inet:info(Socket))]),
+ (catch gen_tcp:close(Socket)),
Control ! {timeout, Socket, Total}
end.
@@ -7527,10 +8127,117 @@ do_otp_17492(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Check that we can connect with the option 'bind_to_device'
+%% and the inet_backend option set to socket.
+%% The value types *where* mutually exclusive:
+%% prim_inet: binary()
+%% socket: string()
+otp_18357(Config) when is_list(Config) ->
+ ct:timetrap(?SECS(30)),
+ Cond = fun() ->
+ is_socket_supported(),
+ has_support_sock_bindtodevice()
+ end,
+ Pre = fun() ->
+ case ?LIB:which_local_host_info(inet) of
+ {ok, [#{name := Name, addr := Addr}|_]} ->
+ ?P("~w:pre -> local host info:"
+ "~n (IF) Name: ~p"
+ "~n (IF) Addr: ~p",
+ [?FUNCTION_NAME, Name, Addr]),
+ #{name => Name, addr => Addr};
+ {error, Reason} ->
+ {skip, ?F("Failed get local address: ~p", [Reason])}
+ end
+ end,
+ Case = fun(State) -> do_otp_18357(State) end,
+ Post = fun(_) -> ok end,
+ ?TC_TRY(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_otp_18357(#{name := Name, addr := Addr}) ->
+ ?P("try create listen socket"),
+ {ok, L} = gen_tcp:listen(0, [{ifaddr, Addr}]),
+ {ok, PortNo} = inet:port(L),
+
+ ?P("try connect (with bind-to-device)"),
+ C = case gen_tcp:connect(Addr, PortNo,
+ [{inet_backend, socket},
+ {bind_to_device, list_to_binary(Name)}]) of
+ {ok, CSock} ->
+ CSock;
+ {error, eperm = Reason} ->
+ ?P("Failed connecting, ~p, skipping", [Reason]),
+ (catch gen_tcp:close(L)),
+ skip(Reason)
+ end,
+
+ ?P("try accept"),
+ {ok, A} = gen_tcp:accept(L),
+
+ ?P("cleanup"),
+ (catch gen_tcp:close(C)),
+ (catch gen_tcp:close(A)),
+ (catch gen_tcp:close(L)),
+
+ ?P("done"),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+is_socket_supported() ->
+ try socket:info() of
+ #{} ->
+ ok
+ catch
+ error : notsup ->
+ skip("esock not supported");
+ error : undef ->
+ skip("esock not configured")
+ end.
+
+has_support_sock_bindtodevice() ->
+ has_support_socket_option_sock(bindtodevice).
+
+has_support_socket_option_sock(Opt) ->
+ has_support_socket_option(socket, Opt).
+
+has_support_socket_option(Level, Option) ->
+ case socket:is_supported(options, Level, Option) of
+ true ->
+ ok;
+ false ->
+ skip(?F("Not Supported: ~w option ~w", [Level, Option]))
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+skip(Reason) ->
+ throw({skip, Reason}).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+messages() ->
+ pi(messages).
+
+links() ->
+ pi(links).
+
+monitors() ->
+ pi(monitors).
+
+pi(Pid) when is_pid(Pid) ->
+ process_info(Pid);
+
pi(Item) ->
- {Item, Val} = process_info(self(), Item),
- Val.
-
+ pi(self(), Item).
+
+pi(Pid, Item) ->
+ {Item, Val} = process_info(Pid, Item),
+ Val.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index bc2a7cb25b..4419999036 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -58,9 +58,14 @@
t_simple_local_sockaddr_in_send_recv/1,
t_simple_link_local_sockaddr_in_send_recv/1,
t_simple_local_sockaddr_in6_send_recv/1,
- t_simple_link_local_sockaddr_in6_send_recv/1
+ t_simple_link_local_sockaddr_in6_send_recv/1,
+
+ otp_18323_opts_processing/1,
+ otp_18323_open/1
+
]).
+-include_lib("kernel/src/inet_int.hrl").
-define(TRY_TC(F), try_tc(F)).
@@ -69,7 +74,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- %% This is a temporary messure to ensure that we can
+ %% This is a temporary measure to ensure that we can
%% test the socket backend without effecting *all*
%% applications on *all* machines.
%% This flag is set only for *one* host.
@@ -93,10 +98,12 @@ groups() ->
{inet_backend_inet, [], inet_backend_inet_cases()},
{inet_backend_socket, [], inet_backend_socket_cases()},
+ {recv_and_send_opts, [], recv_and_send_opts_cases()},
{local, [], local_cases()},
{socket_monitor, [], socket_monitor_cases()},
- {sockaddr, [], sockaddr_cases()}
+ {sockaddr, [], sockaddr_cases()},
+ {otp18323, [], otp18323_cases()}
].
inet_backend_default_cases() ->
@@ -122,13 +129,19 @@ all_cases() ->
reconnect,
implicit_inet6,
active_n,
- recvtos, recvtosttl, recvttl, recvtclass,
- sendtos, sendtosttl, sendttl, sendtclass,
+ {group, recv_and_send_opts},
{group, local},
recv_close,
{group, socket_monitor},
otp_17492,
- {group, sockaddr}
+ {group, sockaddr},
+ {group, otp18323}
+ ].
+
+recv_and_send_opts_cases() ->
+ [
+ recvtos, recvtosttl, recvttl, recvtclass,
+ sendtos, sendtosttl, sendttl, sendtclass
].
local_cases() ->
@@ -159,6 +172,12 @@ sockaddr_cases() ->
t_simple_link_local_sockaddr_in6_send_recv
].
+otp18323_cases() ->
+ [
+ otp_18323_opts_processing,
+ otp_18323_open
+ ].
+
init_per_suite(Config0) ->
@@ -242,6 +261,14 @@ init_per_group(sockaddr = _GroupName, Config) ->
?P("init_per_group(sockaddr) -> 'socket' not configured"),
{skip, "esock not configured"}
end;
+init_per_group(otp18323 = _GroupName, Config) ->
+ ?P("init_per_group(otp18323) -> inet-drv specific bug(s)"),
+ case ?IS_SOCKET_BACKEND(Config) of
+ true ->
+ {skip, "Inet Drv specific bugs"};
+ false ->
+ ok
+ end;
init_per_group(_GroupName, Config) ->
Config.
@@ -561,7 +588,8 @@ do_binary_passive_recv(Config) when is_list(Config) ->
D2 = iolist_to_binary(D3),
B = D2,
?P("open receive socket"),
- {ok, R} = ?OPEN(Config, 0, [binary, {active, false}]),
+ {ok, R} = ?OPEN(Config, 0, [binary, {active, false}, {debug, true}]),
+ ok = inet:setopts(R, [{debug, false}]),
{ok, RP} = inet:port(R),
?P("open send socket"),
{ok, S} = ?OPEN(Config, 0),
@@ -630,7 +658,7 @@ do_bad_address(Config) when is_list(Config) ->
%%-------------------------------------------------------------
%% OTP-6249 UDP option for number of packet reads
%%
-%% Starts a slave node that on command sends a bunch of messages
+%% Starts a node that on command sends a bunch of messages
%% to our UDP port. The receiving process just receives and
%% ignores the incoming messages.
%% A tracing process traces the receiving port for
@@ -645,39 +673,28 @@ read_packets(Config) when is_list(Config) ->
true ->
%% We have not (yet) implemented support for
%% this option. We accept it but do not use it.
- {skip, "Not complient with socket"};
+ {skip, "Not compliant with socket"};
false ->
ok
end
end,
- Pre = fun() ->
- ?P("~w:pre -> try create node", [?FUNCTION_NAME]),
- {ok, Node} = start_node(gen_udp_SUITE_read_packets),
- ?P("~w:pre -> node created", [?FUNCTION_NAME]),
- Node
- end,
- TC = fun(Node) ->
+ TC = fun() ->
?P("~w:tc -> begin", [?FUNCTION_NAME]),
- Res = do_read_packets(Config, Node),
+ Res = do_read_packets(Config),
?P("~w:tc -> done", [?FUNCTION_NAME]),
Res
end,
- Post = fun(Node) ->
- ?P("~w:post -> try stop node ~p", [?FUNCTION_NAME, Node]),
- stop_node(Node),
- ?P("~w:post -> done", [?FUNCTION_NAME]),
- ok
- end,
- ?TC_TRY(?FUNCTION_NAME, Cond, Pre, TC, Post).
+ ?TC_TRY(?FUNCTION_NAME, Cond, TC).
-do_read_packets(Config, Node) when is_list(Config) ->
+do_read_packets(Config) when is_list(Config) ->
N1 = 5,
N2 = 1,
Msgs = 30000,
?P("open socket (with read-packets: ~p)", [N1]),
{ok, R} = ?OPEN(Config, 0, [{read_packets,N1}]),
{ok, RP} = inet:port(R),
-
+ ?P("create slave node"),
+ {ok,Peer,Node} = ?CT_PEER(),
%%
?P("perform read-packets test"),
{V1, Trace1} = read_packets_test(Config, R, RP, Msgs, Node),
@@ -691,7 +708,8 @@ do_read_packets(Config, Node) when is_list(Config) ->
?P("verify read-packets (to ~w)", [N2]),
{ok, [{read_packets,N2}]} = inet:getopts(R, [read_packets]),
%%
-
+ ?P("stop slave node"),
+ peer:stop(Peer),
?P("dump trace 1"),
dump_terms(Config, "trace1.terms", Trace1),
?P("dump trace 2"),
@@ -1142,7 +1160,7 @@ recvtclass(Config) ->
sendtos(Config) ->
- ?TC_TRY(sendtos, fun() -> do_sendtos(Config) end).
+ ?TC_TRY(?FUNCTION_NAME, fun() -> do_sendtos(Config) end).
do_sendtos(Config) ->
test_recv_opts(
@@ -1151,7 +1169,7 @@ do_sendtos(Config) ->
fun sendtos_ok/2).
sendtosttl(Config) ->
- ?TC_TRY(sendtosttl, fun() -> do_sendtosttl(Config) end).
+ ?TC_TRY(?FUNCTION_NAME, fun() -> do_sendtosttl(Config) end).
do_sendtosttl(Config) ->
test_recv_opts(
@@ -1171,7 +1189,7 @@ do_sendttl(Config) ->
fun sendttl_ok/2).
sendtclass(Config) ->
- ?TC_TRY(sendtclass, fun() -> do_sendtclass(Config) end).
+ ?TC_TRY(?FUNCTION_NAME, fun() -> do_sendtclass(Config) end).
do_sendtclass(Config) ->
{ok,IFs} = inet:getifaddrs(),
@@ -1345,6 +1363,8 @@ test_recv_opts(Config, Family, Spec, TestSend, _OSType, _OSVer) ->
%%
?P("send/3: S2 -> S1"),
ok = gen_udp:send(S2, {Addr,P1}, <<"abcde">>),
+ ?SLEEP(100),
+
?P("send/4: S1 -> S2"),
ok = gen_udp:send(S1, Addr, P2, <<"fghij">>),
TestSend andalso
@@ -1353,6 +1373,7 @@ test_recv_opts(Config, Family, Spec, TestSend, _OSType, _OSVer) ->
"~n ~p", [OptsVals]),
case gen_udp:send(S2, Addr, P1, OptsVals, <<"ABCDE">>) of
ok ->
+ ?SLEEP(100),
ok;
{error, enoprotoopt = Reason1} ->
?SKIPT(?F("send (1) failed: ~p", [Reason1]))
@@ -1361,6 +1382,7 @@ test_recv_opts(Config, Family, Spec, TestSend, _OSType, _OSVer) ->
"~n ~p", [OptsVals]),
case gen_udp:send(S2, {Addr,P1}, OptsVals, <<"12345">>) of
ok ->
+ ?SLEEP(100),
ok;
{error, enoprotoopt = Reason2} ->
?SKIPT(?F("send (2) failed: ~p", [Reason2]))
@@ -1370,6 +1392,8 @@ test_recv_opts(Config, Family, Spec, TestSend, _OSType, _OSVer) ->
{ok,{_,P2,OptsVals3, <<"abcde">>}} = gen_udp:recv(S1, 0, Timeout),
?P("S1 recv: "
"~n OptsVals3: ~p", [OptsVals3]),
+ ?SLEEP(100),
+
verify_sets_eq(OptsVals3, OptsVals2),
TestSend andalso
begin
@@ -1377,10 +1401,13 @@ test_recv_opts(Config, Family, Spec, TestSend, _OSType, _OSVer) ->
{ok,{_,P2,OptsVals0,<<"ABCDE">>}} = gen_udp:recv(S1, 0, Timeout),
?P("S1 recv: "
"~n OptsVals0: ~p", [OptsVals0]),
+ ?SLEEP(100),
+
?P("try S1 recv"),
{ok,{_,P2,OptsVals1,<<"12345">>}} = gen_udp:recv(S1, 0, Timeout),
?P("S1 recv: "
"~n OptsVals1: ~p", [OptsVals1]),
+ ?SLEEP(100),
verify_sets_eq(OptsVals0, OptsVals),
verify_sets_eq(OptsVals1, OptsVals)
end,
@@ -1410,14 +1437,21 @@ test_recv_opts(Config, Family, Spec, TestSend, _OSType, _OSVer) ->
%%
?P("send/4: S2 -> S1"),
ok = gen_udp:send(S2, {Addr,P1}, [], <<"klmno">>),
+ ?SLEEP(100),
+
?P("send/3: S1 -> S2"),
ok = gen_udp:send(S1, {Family,{loopback,P2}}, <<"pqrst">>),
+ ?SLEEP(100),
+
TestSend andalso
begin
?P("send/4: S1 -> S2"
"~n ~p", [OptsVals]),
- ok = gen_udp:send(S1, {Family,{loopback,P2}}, OptsVals2, <<"PQRST">>)
+ ok = gen_udp:send(S1,
+ {Family,{loopback,P2}}, OptsVals2, <<"PQRST">>),
+ ?SLEEP(100)
end,
+
?P("try recv data on S1"),
{ok,{_,P2,<<"klmno">>}} = gen_udp:recv(S1, 0, Timeout),
?P("await message on S2"),
@@ -1660,7 +1694,7 @@ recv_close(Config) when is_list(Config) ->
receive
{'DOWN', MRef, process, Pid, PreReason} ->
%% Make sure id does not die for some other reason...
- ?line ct:fail("Unexpected pre close from reader (~p): ~p",
+ ct:fail("Unexpected pre close from reader (~p): ~p",
[Pid, PreReason])
after 5000 -> % Just in case...
ok
@@ -1674,13 +1708,13 @@ recv_close(Config) when is_list(Config) ->
ok;
{'DOWN', MRef, process, Pid, PostReason} ->
?P("unexpected reader termination: ~p", [PostReason]),
- ?line ct:fail("Unexpected post close from reader (~p): ~p",
+ ct:fail("Unexpected post close from reader (~p): ~p",
[Pid, PostReason])
after 5000 ->
?P("unexpected reader termination timeout"),
demonitor(MRef, [flush]),
exit(Pid, kill),
- ?line ct:fail("Reader (~p) termination timeout", [Pid])
+ ct:fail("Reader (~p) termination timeout", [Pid])
end,
?P("done"),
ok.
@@ -1705,15 +1739,20 @@ do_connect(Config) when is_list(Config) ->
ok = inet:setopts(S2, [{active, false}]),
?P("try close first socket"),
ok = gen_udp:close(S1),
+
+ %% Test if this helps...
+ ?P("sleep some"),
+ ct:sleep({seconds, 5}),
+
?P("try connect second socket to: ~p, ~p", [Addr, P1]),
ok = gen_udp:connect(S2, Addr, P1),
?P("try send on second socket"),
ok = gen_udp:send(S2, <<16#deadbeef:32>>),
- ?P("try recv on second socket - expect failure: "
- "~n ~p", [inet:info(S2)]),
+ ?P("try recv on second socket - expect failure when"
+ "~n Socket Info: ~p", [inet:info(S2)]),
ok = case gen_udp:recv(S2, 0, 500) of
- {error, econnrefused} -> ok;
- {error, econnreset} -> ok;
+ {error, econnrefused = R} -> ?P("expected failure: ~w", [R]), ok;
+ {error, econnreset = R} -> ?P("expected failure: ~w", [R]), ok;
Other ->
?P("UNEXPECTED failure: ~p:"
"~n ~p", [Other, inet:info(S2)]),
@@ -1801,9 +1840,9 @@ do_implicit_inet6(Config) ->
end.
implicit_inet6(Config, Host, Addr) ->
- Active = {active,false},
+ Active = {active,false},
Loopback = {0,0,0,0,0,0,0,1},
- ?P("try 1 with explit inet6 on loopback"),
+ ?P("try 1 with explicit inet6 on loopback"),
S1 = case ?OPEN(Config, 0, [inet6, Active, {ip, Loopback}]) of
{ok, Sock1} ->
Sock1;
@@ -1814,6 +1853,7 @@ implicit_inet6(Config, Host, Addr) ->
end,
implicit_inet6(Config, S1, Active, Loopback),
ok = gen_udp:close(S1),
+
%%
Localaddr = ok(get_localaddr()),
?P("try 2 on local addr (~p)", [Localaddr]),
@@ -1825,6 +1865,7 @@ implicit_inet6(Config, Host, Addr) ->
end,
implicit_inet6(Config, S2, Active, Localaddr),
ok = gen_udp:close(S2),
+
%%
?P("try 3 on addr ~p (~p)", [Addr, Host]),
S3 = case ?OPEN(Config, 0, [{ifaddr, Addr}, Active]) of
@@ -1862,16 +1903,43 @@ implicit_inet6(Config, S1, Active, Addr) ->
?P("sockname of \"remote\" socket"),
{Addr,P2} = ok(inet:sockname(S2)),
?P("send ping on \"local\" socket (to ~p:~p)", [Addr, P2]),
- ok = gen_udp:send(S1, Addr, P2, "ping"),
- ?P("recv ping on \"remote\" socket (from ~p:~p)", [Addr, P1]),
- {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
- ?P("send pong on \"remote\" socket (to ~p:~p)", [Addr, P1]),
- ok = gen_udp:send(S2, Addr, P1, "pong"),
- ?P("recv ping on \"local\" socket (from ~p:~p)", [Addr, P2]),
- {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
- ?P("close \"remote\" socket"),
- ok = gen_udp:close(S2),
- ok.
+ %% On some platforms its allowed to specify address and port
+ %% (that is; when useing sendto) *even* if the socket is connected
+ %% (assuming the send destination is the same as connected destination).
+ %% But on other platforms, e.g. FreeBSD, this is *not* allowed!
+ %% Linux:
+ %% EISCONN
+ %% The connection-mode socket was connected already but a recipient
+ %% was specified. (Now either this error is returned, or the re-
+ %% cipient specification is ignored.)
+ %% FreeBSD:
+ %% [EISCONN] A destination address was specified and the socket is
+ %% already connected.
+ case gen_udp:send(S1, Addr, P2, "ping") of
+ ok ->
+ ?P("recv ping on \"remote\" socket (from ~p:~p)", [Addr, P1]),
+ {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
+ ?P("send pong on \"remote\" socket (to ~p:~p)", [Addr, P1]),
+ ok = gen_udp:send(S2, Addr, P1, "pong"),
+ ?P("recv ping on \"local\" socket (from ~p:~p)", [Addr, P2]),
+ {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
+ ?P("close \"remote\" socket"),
+ ok = gen_udp:close(S2),
+ ok;
+ {error, eisconn} ->
+ ?P("socket is connect => *not* allowed to use sendto"),
+ ok = gen_udp:send(S1, "ping"),
+ %% Not allowed to specify address *at all* for a connected socket
+ ?P("recv ping on \"remote\" socket (from ~p:~p)", [Addr, P1]),
+ {Addr,P1,"ping"} = ok(gen_udp:recv(S2, 1024, 1000)),
+ ?P("send pong on \"remote\" socket (to ~p:~p)", [Addr, P1]),
+ ok = gen_udp:send(S2, "pong"),
+ ?P("recv ping on \"local\" socket (from ~p:~p)", [Addr, P2]),
+ {Addr,P2,"pong"} = ok(gen_udp:recv(S1, 1024)),
+ ?P("close \"remote\" socket"),
+ ok = gen_udp:close(S2),
+ ok
+ end.
@@ -2793,6 +2861,97 @@ do_simple_sockaddr_send_recv(#{family := _Fam} = SockAddr, _) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Verify that the options [add|drop]_membership do not mess up
+%% the options (including 'ip' which could not be added *after*).
+%% This just attempts to very that the option processing is ok.
+otp_18323_opts_processing(Config) when is_list(Config) ->
+ ct:timetrap(?MINS(1)),
+ ?TC_TRY(?FUNCTION_NAME, fun() -> do_otp_18323_opts_processing(Config) end).
+
+do_otp_18323_opts_processing(_Config) ->
+ ?P("begin"),
+
+ do_otp_18323_opts_processing_verify(
+ {add_membership, {{239,1,2,3},{0,0,0,0}}}),
+
+ do_otp_18323_opts_processing_verify(
+ {drop_membership, {{239,1,2,3},{0,0,0,0}}}),
+
+ ?P("done"),
+ ok.
+
+do_otp_18323_opts_processing_verify(MembershipOpt) ->
+ Port = 4321,
+ RecBuf = 123456,
+ Active = 10,
+ IP = {1,2,3,4},
+ Opts = [binary, MembershipOpt, {ip, IP}, {active, Active}],
+
+ case inet:udp_options([{port, Port}, {recbuf, RecBuf} | Opts], inet_udp) of
+ {ok, #udp_opts{ifaddr = IP,
+ port = Port,
+ opts = SockOpts}} ->
+ ?P("Processed Socket Options: "
+ "~n IfAddr: ~p"
+ "~n Port: ~p"
+ "~n Sock Opts: ~p", [IP, Port, SockOpts]),
+ %% Check that the recbuf and mode options are as expected
+ %% The option 'binary' is shorthand for {mode, binary}
+ {value, {recbuf, RecBuf}} = lists:keysearch(recbuf, 1, SockOpts),
+ {value, {mode, binary}} = lists:keysearch(mode, 1, SockOpts),
+ {value, {active, Active}} = lists:keysearch(active, 1, SockOpts),
+ ok;
+ {error, Reason} ->
+ exit(?F("Failed processing options: ~p", [Reason]))
+ end.
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Verify that the options [add|drop]_membership do not mess up
+%% the options (including 'ip' which could not be added *after*).
+otp_18323_open(Config) when is_list(Config) ->
+ ct:timetrap(?MINS(1)),
+ Pre = fun() ->
+ {ok, Addr} = ?LIB:which_local_addr(inet),
+ #{local_addr => Addr}
+ end,
+ Case = fun(State) -> do_otp_18323_open(State) end,
+ Post = fun(_) -> ok end,
+ ?TC_TRY(?FUNCTION_NAME, Pre, Case, Post).
+
+do_otp_18323_open(#{local_addr := Addr}) ->
+ ?P("begin"),
+
+ ROpts = [binary,
+ {add_membership, {Addr,{0,0,0,0}}},
+ {ip, Addr},
+ {active,false},
+ {debug, true}],
+ SOpts = [{reuseaddr, true}, binary],
+
+ ?P("create received socket"),
+ {ok, R} = gen_udp:open(0, ROpts),
+ ?P("extract received socket port"),
+ {ok, RPort} = inet:port(R),
+
+ ?P("create sender socket"),
+ {ok, S} = gen_udp:open(0, SOpts),
+
+ ?P("send to receiver (at port ~w)", [RPort]),
+ ok = gen_udp:send(S, Addr, RPort, <<"aaaaa">>),
+
+ ?P("attempt to receive data on specified format binary)"),
+ {ok, {_,_,<<"aaaaa">>}} = gen_udp:recv(R, 0, 200),
+
+ ?P("done"),
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
ok({ok,V}) -> V;
ok(NotOk) ->
try throw(not_ok)
@@ -2897,14 +3056,5 @@ pi(Item) ->
%% Utils
%%
-start_node(Name) ->
- ?START_NODE(Name, []).
-
-stop_node(Node) ->
- ?STOP_NODE(Node).
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
open_failed_str(Reason) ->
?F("Open failed: ~w", [Reason]).
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 7b31b7462a..9a367ca5fa 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -33,7 +33,7 @@
ring/1, simple_ring/1, line/1, simple_line/1,
global_lost_nodes/1, otp_1849/1,
otp_3162/1, otp_5640/1, otp_5737/1,
- otp_6931/1,
+ connect_all_false/1,
simple_disconnect/1,
simple_resolve/1, simple_resolve2/1, simple_resolve3/1,
leftover_name/1, re_register_name/1, name_exit/1, external_nodes/1,
@@ -45,8 +45,10 @@
mass_death/1,
garbage_messages/1,
ring_line/1,
+ flaw1/1,
lost_connection/1,
- lost_connection2/1
+ lost_connection2/1,
+ global_disconnect/1
]).
%% Not used
@@ -130,12 +132,12 @@ all() ->
advanced_partition, basic_name_partition,
stress_partition, simple_ring, simple_line, ring, line,
global_lost_nodes, otp_1849, otp_3162, otp_5640,
- otp_5737, otp_6931, simple_disconnect, simple_resolve,
+ otp_5737, connect_all_false, simple_disconnect, simple_resolve,
simple_resolve2, simple_resolve3, leftover_name,
re_register_name, name_exit, external_nodes, many_nodes,
sync_0, global_groups_change, register_1, both_known_1,
- lost_unregister, mass_death, garbage_messages,
- lost_connection, lost_connection2
+ lost_unregister, mass_death, garbage_messages, flaw1,
+ lost_connection, lost_connection2, global_disconnect
]
end.
@@ -164,6 +166,8 @@ end_per_suite(_Config) ->
-define(registered, proplists:get_value(registered, Config)).
init_per_testcase(Case, Config0) when is_atom(Case) andalso is_list(Config0) ->
+ start_node_tracker(Config0),
+
?P("init_per_testcase -> entry with"
"~n Config: ~p"
"~n Nodes: ~p"
@@ -175,11 +179,6 @@ init_per_testcase(Case, Config0) when is_atom(Case) andalso is_list(Config0) ->
high_level_trace_start,
infinity),
- %% Make sure that everything is dead and done. Otherwise there are problems
- %% on platforms on which it takes a long time to shut down a node.
- stop_nodes(nodes()),
- timer:sleep(1000),
-
Config1 = [{?TESTCASE, Case}, {registered, registered()} | Config0],
?P("init_per_testcase -> done when"
@@ -216,7 +215,7 @@ end_per_testcase(_Case, Config) ->
"~n Monitors: ~p",
[erlang:nodes(), pi(links), pi(monitors)]),
- ok.
+ stop_node_tracker(Config). %% Needs to be last and produce return value...
%%% General comments:
%%% One source of problems with failing tests can be that the nodes from the
@@ -613,8 +612,9 @@ write_high_level_trace(Nodes, Config) ->
Node <- Nodes],
Dir = proplists:get_value(priv_dir, Config),
DataFile = filename:join([Dir, lists:concat(["global_", ?testcase])]),
- ?P("High-level trace on:"
- "~n ~p", [DataFile]),
+ io:format("\n\nAnalyze high level trace like this:\n"),
+ io:format("global_trace:dd(~p, [{show_state, 0, 10}]). % 10 seconds\n",
+ [DataFile]),
file:write_file(DataFile, term_to_binary({high_level_trace, When, Data})).
lock_global2(Id, Parent) ->
@@ -885,7 +885,7 @@ locks(Config) when is_list(Config) ->
Pid = start_proc(),
Pid2 = rpc:call(Cp1, ?MODULE, start_proc, []),
- %% set a lock, and make sure noone else can set the same lock
+ %% set a lock, and make sure no one else can set the same lock
true = global:set_lock({test_lock, self()}, ?NODES, 1),
false = req(Pid, {set_lock, test_lock, self()}),
false = req(Pid2, {set_lock, test_lock, self()}),
@@ -1662,7 +1662,7 @@ stress_partition(Config) when is_list(Config) ->
ok.
-%% Use this one to test alot of connection tests
+%% Use this one to test a lot of connection tests
%% erl -sname ts -ring_line 10000 -s test_server run_test global_SUITE
ring_line(Config) when is_list(Config) ->
@@ -2192,16 +2192,25 @@ otp_5737(Config) when is_list(Config) ->
init_condition(Config),
ok.
-%% OTP-6931. Ignore nodeup when connect_all=false.
-otp_6931(Config) when is_list(Config) ->
+connect_all_false(Config) when is_list(Config) ->
+ %% OTP-6931. Ignore nodeup when connect_all=false.
+ connect_all_false_test("-connect_all false", Config),
+ %% OTP-17934: multipl -connect_all false and kernel parameter connect_all
+ connect_all_false_test("-connect_all false -connect_all false", Config),
+ connect_all_false_test("-kernel connect_all false", Config),
+ ok.
+
+connect_all_false_test(CAArg, Config) ->
Me = self(),
{ok, CAf} = start_non_connecting_node(ca_false, Config),
+ {ok, false} = rpc:call(CAf, application, get_env, [kernel, connect_all]),
ok = rpc:call(CAf, error_logger, add_report_handler, [?MODULE, Me]),
info = rpc:call(CAf, error_logger, warning_map, []),
- {global_name_server,CAf} ! {nodeup, fake_node},
+ {global_name_server,CAf} ! {nodeup, fake_node, #{connection_id => 4711}},
timer:sleep(100),
stop_node(CAf),
- receive {nodeup,fake_node} -> ct:fail({info_report, was, sent})
+ receive {nodeup,fake_node, _} ->
+ ct:fail({info_report, was, sent})
after 1000 -> ok
end,
ok.
@@ -2679,7 +2688,7 @@ mon_by_servers(Proc) ->
-define(REGNAME, contact_a_2).
-%% OTP-5563. Bug: nodedown while synching.
+%% OTP-5563. Bug: nodedown while syncing.
leftover_name(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
@@ -3045,7 +3054,7 @@ many_nodes(Config) when is_list(Config) ->
OrigNames = global:registered_names(),
{Rels, N_cps} =
- case test_server:os_type() of
+ case os:type() of
{unix, Osname} when Osname =:= linux;
Osname =:= openbsd;
Osname =:= darwin ->
@@ -3160,7 +3169,7 @@ sync_0(Config) when is_list(Config) ->
init_condition(Config),
N_cps =
- case test_server:os_type() of
+ case os:type() of
{unix, Osname} when Osname =:= linux;
Osname =:= openbsd;
Osname =:= darwin ->
@@ -3326,8 +3335,9 @@ global_groups_change(Config) ->
Config2 = filename:join(Dir, "sys2"),
{ok, CpC} = start_node_boot(NcpC, Config2, dc),
- sync_and_wait(CpA),
- sync_and_wait(CpD),
+ gg_sync_and_wait(Cp1, [Cp2], [], [mk_node(Ncp5, M)]),
+ gg_sync_and_wait(CpA, [CpB], [], []),
+ gg_sync_and_wait(CpD, [CpC, CpE], [], []),
pong = rpc:call(CpA, net_adm, ping, [CpC]),
pong = rpc:call(CpC, net_adm, ping, [CpB]),
@@ -3467,6 +3477,9 @@ global_groups_change(Config) ->
Info1ok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [Info1ok, Info1]),
ct:fail({{"could not change the global groups"
" in node", Cp1}, {Info1, Info1ok}})
end,
@@ -3475,6 +3488,9 @@ global_groups_change(Config) ->
Info2ok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [Info2ok, Info2]),
ct:fail({{"could not change the global groups"
" in node", Cp2}, {Info2, Info2ok}})
end,
@@ -3483,6 +3499,9 @@ global_groups_change(Config) ->
Info3ok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [Info3ok, Info3]),
ct:fail({{"could not change the global groups"
" in node", Cp3}, {Info3, Info3ok}})
end,
@@ -3491,6 +3510,9 @@ global_groups_change(Config) ->
InfoAok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [InfoAok, InfoA]),
ct:fail({{"could not change the global groups"
" in node", CpA}, {InfoA, InfoAok}})
end,
@@ -3499,6 +3521,9 @@ global_groups_change(Config) ->
InfoBok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [InfoBok, InfoB]),
ct:fail({{"could not change the global groups"
" in node", CpB}, {InfoB, InfoBok}})
end,
@@ -3508,6 +3533,9 @@ global_groups_change(Config) ->
InfoCok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [InfoCok, InfoC]),
ct:fail({{"could not change the global groups"
" in node", CpC}, {InfoC, InfoCok}})
end,
@@ -3516,6 +3544,9 @@ global_groups_change(Config) ->
InfoDok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [InfoDok, InfoD]),
ct:fail({{"could not change the global groups"
" in node", CpD}, {InfoD, InfoDok}})
end,
@@ -3524,6 +3555,9 @@ global_groups_change(Config) ->
InfoEok ->
ok;
_ ->
+ ct:pal("Expected: ~p~n"
+ "Got : ~p~n",
+ [InfoEok, InfoE]),
ct:fail({{"could not change the global groups"
" in node", CpE}, {InfoE, InfoEok}})
end,
@@ -3541,27 +3575,30 @@ global_groups_change(Config) ->
init_condition(Config),
ok.
-sync_and_wait(Node) ->
- Ref = make_ref(),
- Self = self(),
- spawn(Node, fun () ->
- global_group:sync(),
- case whereis(global_group_check) of
- P when is_pid(P) ->
- Self ! {Ref, P};
- _ ->
- Self ! {Ref, done}
- end
- end),
- receive
- {Ref, P} when is_pid(P) ->
- MonRef = erlang:monitor(process, P),
- receive
- {'DOWN',MonRef,process,P,_} ->
- ok
- end;
- {Ref, _} ->
- ok
+gg_sync_and_wait(Node, Synced, SyncError, NoContact) ->
+ ok = rpc:call(Node, global_group, sync, []),
+ gg_wait(Node, Synced, SyncError, NoContact).
+
+gg_wait(Node, Synced, SyncError, NoContact) ->
+ receive after 100 -> ok end,
+ try
+ GGInfo = rpc:call(Node, global_group, info, []),
+ ct:pal("GG info: ~p~n", [GGInfo]),
+ case proplists:lookup(synced_nodes, GGInfo) of
+ {synced_nodes, Synced} -> ok;
+ _ -> throw(wait)
+ end,
+ case proplists:lookup(sync_error, GGInfo) of
+ {sync_error, SyncError} -> ok;
+ _ -> throw(wait)
+ end,
+ case proplists:lookup(no_contact, GGInfo) of
+ {no_contact, NoContact} -> ok;
+ _ -> throw(wait)
+ end
+ catch
+ throw:wait ->
+ gg_wait(Node, Synced, SyncError, NoContact)
end.
%%% Copied from init_SUITE.erl.
@@ -3941,6 +3978,7 @@ start_node_rel(Name0, Rel, Config) ->
record_started_node(Res).
record_started_node({ok, Node}) ->
+ node_started(Node),
case erase(?nodes_tag) of
undefined -> ok;
Nodes -> put(?nodes_tag, [Node | Nodes])
@@ -3965,12 +4003,15 @@ stop_nodes(Nodes) ->
lists:foreach(fun(Node) -> stop_node(Node) end, Nodes).
stop_node(Node) ->
- test_server:stop_node(Node).
+ Res = test_server:stop_node(Node),
+ node_stopped(Node),
+ Res.
stop() ->
lists:foreach(fun(Node) ->
- test_server:stop_node(Node)
+ test_server:stop_node(Node),
+ node_stopped(Node)
end, nodes()).
%% Tests that locally loaded nodes do not loose contact with other nodes.
@@ -4285,6 +4326,204 @@ garbage_messages(Config) when is_list(Config) ->
init_condition(Config),
ok.
+%% This is scenario outlined in
+%% https://erlang.org/pipermail/erlang-questions/2020-October/100034.html.
+%% It illustrates that the algorithm of Global is flawed.
+%%
+%% This has been worked around by global actively disconnecting nodes
+%% to prevent overlapping partitions (OTP-17843).
+flaw1(Config) ->
+ case prevent_overlapping_partitions() of
+ true ->
+ flaw1_test(Config);
+ false ->
+ {skipped, "Prevent overlapping partitions disabled"}
+ end.
+
+flaw1_test(Config) ->
+ Timeout = 360,
+ ct:timetrap({seconds,Timeout}),
+ init_high_level_trace(Timeout),
+ init_condition(Config),
+ OrigNames = global:registered_names(),
+
+ PartCtrlr = start_partition_controller(Config),
+
+ [A, B, C, D] = OtherNodes = start_nodes([a, b, c, d], peer, Config),
+ Nodes = lists:sort([node() | OtherNodes]),
+ wait_for_ready_net(Config),
+
+ F1 =
+ fun(S0) ->
+ ct:sleep(100),
+ Str = "************",
+ S = Str ++ " " ++ lists:flatten(S0) ++ " " ++ Str,
+ io:format("~s\n", [S]),
+ erpc:call(
+ PartCtrlr,
+ fun () ->
+ [begin
+ RNs = erpc:call(N, global, registered_names, []),
+ W = erpc:call(N, global, whereis_name, [x]),
+ io:format(" === ~w ===\n", [N]),
+ io:format(" registered names: ~p", [RNs]),
+ io:format(" where is x: ~p", [W])
+ end || N <- OtherNodes]
+ end)
+ end,
+ F1("start"),
+
+ disconnect_nodes(PartCtrlr, A, C),
+ F1("after disconnecting c from a"),
+
+ Me = self(),
+ IdleFun = fun () ->
+ Mon = erlang:monitor(process, Me),
+ receive
+ {'DOWN', Mon, process, Me, _} ->
+ exit(normal)
+ end
+ end,
+ Pid = spawn(IdleFun),
+ yes = rpc:call(A, global, register_name, [x, Pid]),
+ F1(io_lib:format("after registering x as ~p on a", [Pid])),
+
+ disconnect_nodes(PartCtrlr, B, D),
+ F1("after disconnecting d from b"),
+
+ Pid2 = spawn(IdleFun),
+ yes = rpc:call(B, global, re_register_name, [x, Pid2]),
+ F1(io_lib:format("after re_register_name x as ~p on b", [Pid2])),
+
+ pong = rpc:call(A, net_adm, ping, [C]),
+ F1("finished after ping c from a"),
+
+ pong = rpc:call(B, net_adm, ping, [D]),
+ F1("finished after ping d from b"),
+
+ timer:sleep(1000),
+
+ check_everywhere(Nodes, x, Config),
+ F1("After check everywhere"),
+
+ assert_pid(global:whereis_name(x)),
+
+ lists:foreach(fun(N) ->
+ rpc:call(N, ?MODULE, stop_tracer, [])
+ end, Nodes),
+ _ = rpc:call(A, global, unregister_name, [x]),
+
+ F1("after unregistering x on node a"),
+
+ %% _ = rpc:call(B, global, unregister_name, [y]),
+ %% F1("after unregistering y on node b"),
+
+ ct:sleep(100),
+ OrigNames = global:registered_names(),
+ write_high_level_trace(Config),
+ stop_nodes(OtherNodes),
+ stop_partition_controller(PartCtrlr),
+ init_condition(Config),
+ ok.
+
+global_disconnect(Config) when is_list(Config) ->
+ Timeout = 30,
+ ct:timetrap({seconds,Timeout}),
+
+ [] = nodes(connected),
+
+ {ok, H1} = start_hidden_node(h1, Config),
+ {ok, H2} = start_hidden_node(h2, Config),
+ {ok, Cp1} = start_node(cp1, peer, Config),
+ {ok, Cp2} = start_node(cp2, peer, Config),
+ {ok, Cp3} = start_node(cp3, peer, Config),
+
+ ThisNode = node(),
+ HNodes = lists:sort([H1, H2]),
+ OtherGNodes = lists:sort([Cp1, Cp2, Cp3]),
+ AllGNodes = lists:sort([ThisNode|OtherGNodes]),
+
+ lists:foreach(fun (Node) -> pong = net_adm:ping(Node) end, OtherGNodes),
+
+ wait_for_ready_net(Config),
+
+ ok = erpc:call(
+ H2,
+ fun () ->
+ lists:foreach(fun (Node) ->
+ pong = net_adm:ping(Node)
+ end, OtherGNodes)
+ end),
+
+ lists:foreach(
+ fun (Node) ->
+ AllGNodes = erpc:call(
+ H1,
+ fun () ->
+ erpc:call(
+ Node,
+ fun () ->
+ lists:sort([node()|nodes()])
+ end)
+ end),
+ HNodes = erpc:call(
+ H1,
+ fun () ->
+ erpc:call(
+ Node,
+ fun () ->
+ lists:sort(nodes(hidden))
+ end)
+ end)
+ end, AllGNodes),
+
+ OtherGNodes = lists:sort(global:disconnect()),
+
+ GNodesAfterDisconnect = nodes(),
+
+ HNodes = lists:sort(nodes(hidden)),
+
+ lists:foreach(fun (Node) ->
+ false = lists:member(Node, GNodesAfterDisconnect)
+ end,
+ OtherGNodes),
+
+ %% Wait a while giving the other nodes time to react to the disconnects
+ %% before we check that everything is as expected...
+ receive after 2000 -> ok end,
+
+ lists:foreach(
+ fun (Node) ->
+ OtherGNodes = erpc:call(
+ H1,
+ fun () ->
+ erpc:call(
+ Node,
+ fun () ->
+ lists:sort([node()|nodes()])
+ end)
+ end),
+ HNodes = erpc:call(
+ H1,
+ fun () ->
+ erpc:call(
+ Node,
+ fun () ->
+ lists:sort(nodes(hidden))
+ end)
+ end)
+ end, OtherGNodes),
+
+ stop_node(Cp1),
+ stop_node(Cp2),
+ stop_node(Cp3),
+ stop_node(H1),
+ stop_node(H2),
+
+ ok.
+
+%% ---
+
wait_for_ready_net(Config) ->
{Pid, MRef} = spawn_monitor(fun() ->
wait_for_ready_net(?NODES, Config)
@@ -4304,7 +4543,7 @@ wait_for_ready_net_loop(Pid, MRef) ->
"~n Waiter: ~p"
"~n Current Location: ~p"
"~n Dictionary: ~p"
- "~n Mesages: ~p",
+ "~n Messages: ~p",
[ParentPid, Pid,
pi(Pid, current_location),
pi(Pid, dictionary),
@@ -4497,10 +4736,10 @@ stop_partition_controller(PartCtrlr) ->
prevent_overlapping_partitions() ->
case application:get_env(kernel, prevent_overlapping_partitions) of
- {ok, true} ->
- true;
+ {ok, false} ->
+ false;
_ ->
- false
+ true
end.
cast_line([]) ->
@@ -4608,7 +4847,7 @@ pi(Pid, Item) ->
init(Tester) ->
{ok, Tester}.
-handle_event({_, _GL, {_Pid,_String,[{nodeup,fake_node}=Msg]}}, Tester) ->
+handle_event({_, _GL, {_Pid,_String,[{nodeup,fake_node,_}=Msg]}}, Tester) ->
Tester ! Msg,
{ok, Tester};
handle_event(_Event, State) ->
@@ -4622,3 +4861,117 @@ handle_call(_Query, State) -> {ok, {error, bad_query}, State}.
terminate(_Reason, State) ->
State.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%
+%%% Keep track of started nodes so we can kill them if test
+%%% cases fail to stop them. This typically happens on test case
+%%% failure with peer nodes, and if left might mess up following
+%%% test-cases.
+%%%
+%%% This can be removed when the suite is converted to use CT_PEER.
+%%% This can however at earliest be made in OTP 25.
+%%%
+
+node_started(Node) ->
+ _ = global_SUITE_node_tracker ! {node_started, Node},
+ ok.
+
+node_stopped(Node) ->
+ _ = global_SUITE_node_tracker ! {node_stopped, Node},
+ ok.
+
+start_node_tracker(Config) ->
+ case whereis(global_SUITE_node_tracker) of
+ undefined ->
+ ok;
+ _ ->
+ try
+ stop_node_tracker(Config),
+ ok
+ catch
+ _:_ ->
+ ok
+ end
+ end,
+ _ = spawn(fun () ->
+ _ = register(global_SUITE_node_tracker, self()),
+ node_tracker_loop(#{})
+ end),
+ ok.
+
+node_tracker_loop(Nodes) ->
+ receive
+ {node_started, Node} ->
+ node_tracker_loop(Nodes#{Node => alive});
+ {node_stopped, Node} ->
+ node_tracker_loop(Nodes#{Node => stopped});
+ stop ->
+ Fact = try
+ test_server:timetrap_scale_factor()
+ catch _:_ -> 1
+ end,
+ Tmo = 1000*Fact,
+ lists:foreach(
+ fun (N) ->
+ case maps:get(N, Nodes) of
+ stopped ->
+ ok;
+ alive ->
+ ct:pal("WARNING: The node ~p was not "
+ "stopped by the test case!", [N])
+ end,
+ %% We try to kill every node, even those reported as
+ %% stopped since they might have failed at stopping...
+ case rpc:call(N, erlang, halt, [], Tmo) of
+ {badrpc,nodedown} ->
+ ok;
+ {badrpc,timeout} ->
+ ct:pal("WARNING: Failed to kill node: ~p~n"
+ " Disconnecting it, but it may "
+ "still be alive!", [N]),
+ erlang:disconnect_node(N),
+ ok;
+ Unexpected ->
+ ct:pal("WARNING: Failed to kill node: ~p~n"
+ " Got response: ~p~n"
+ " Disconnecting it, but it may "
+ "still be alive!", [N, Unexpected]),
+ erlang:disconnect_node(N),
+ ok
+ end
+ end, maps:keys(Nodes))
+ end.
+
+stop_node_tracker(Config) ->
+ NTRes = case whereis(global_SUITE_node_tracker) of
+ undefined ->
+ {fail, missing_node_tracker};
+ NT when is_port(NT) ->
+ NTMon = erlang:monitor(port, NT),
+ exit(NT, kill),
+ receive {'DOWN', NT, port, NT, _} -> ok end,
+ {fail, {port_node_tracker, NT}};
+ NT when is_pid(NT) ->
+ NTMon = erlang:monitor(process, NT),
+ NT ! stop,
+ receive
+ {'DOWN', NTMon, process, NT, normal} ->
+ ok;
+ {'DOWN', NTMon, process, NT, Reason} ->
+ {fail, {node_tracker_failed, Reason}}
+ end
+ end,
+ case NTRes of
+ ok ->
+ ok;
+ NTFailure ->
+ case proplists:get_value(tc_status, Config) of
+ ok ->
+ %% Fail test case with info about node tracker...
+ NTFailure;
+ _ ->
+ %% Don't fail due to node tracker...
+ ct:pal("WARNING: Node tracker failure: ~p", [NTFailure]),
+ ok
+ end
+ end.
diff --git a/lib/kernel/test/global_SUITE_data/global_trace.erl b/lib/kernel/test/global_SUITE_data/global_trace.erl
index b4af4ed76e..923bf53454 100644
--- a/lib/kernel/test/global_SUITE_data/global_trace.erl
+++ b/lib/kernel/test/global_SUITE_data/global_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -73,42 +73,17 @@ logdir() ->
%%% For one thing, the trace from all nodes are written onto the file
%%% as one single term. One term per node would be better. &c.
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
-record(state, {connect_all, known = [], synced = [],
resolvers = [], syncers = [], node_name = node(),
- the_locker, the_deleter, the_registrar, trace = [],
+ the_locker, the_registrar, trace = [],
global_lock_down
}).
%% Compatible with different versions.
state(#state{}=S) ->
- S;
-state({state, ConnectAll, Known, Synced, LockersResolvers, Syncers,
- NodeName, TheLocker, TheDeleter}) ->
- %% r10b: Lockers, r10b_patched, r11b: Resolvers
- #state{connect_all = ConnectAll, known = Known, synced = Synced,
- resolvers = LockersResolvers, syncers = Syncers,
- node_name = NodeName, the_locker = TheLocker,
- the_deleter = TheDeleter, the_registrar = undefined, trace = []};
-state({state, ConnectAll, Known, Synced, Resolvers, Syncers,
- NodeName, TheLocker, TheDeleter, Trace}) ->
- %% r11b, some time before r11b-3
- #state{connect_all = ConnectAll, known = Known, synced = Synced,
- resolvers = Resolvers, syncers = Syncers,
- node_name = NodeName, the_locker = TheLocker,
- the_deleter = TheDeleter, the_registrar = undefined,
- trace = Trace};
-state({state, ConnectAll, Known, Synced, Resolvers, Syncers,
- NodeName, TheLocker, TheDeleter, TheRegistrar, Trace}) ->
- %% r11b, some time after r11b-3
- #state{connect_all = ConnectAll, known = Known, synced = Synced,
- resolvers = Resolvers, syncers = Syncers,
- node_name = NodeName, the_locker = TheLocker,
- the_deleter = TheDeleter, the_registrar = TheRegistrar,
- trace = Trace, global_lock_down = false};
-state(Else) ->
- Else.
+ S.
%%% Trace tuples look like {Node, Now, Message, Nodes, Extra}.
%%% Nodes is the list as returned by nodes().
@@ -123,12 +98,11 @@ state(Else) ->
%%% {ops,Ops}]
%%% NewKnown = Known ++ AddedNodes
%%% AddedNodes = NewNodes -- Known
-%%% NewNodes är här den man förhandlat med plus de noder den känner till.
+%%% NewNodes is the other node and the nodes known to that node.
%%% {added, AddedNodes}, Extra = [{ops,Ops}]
%%% NewKnown = Known ++ AddedNodes
-%%% Den (passiva) noden får Nodes som är NewNodes
-%%% hos den förhandlande. Sedan: AddedNodes = (Nodes -- Known) -- [node()].
-%%% Det är som hos förhandlaren.
+%%% The (passive) node gets Nodes which is NewNodes on the other node.
+%%% Then: AddedNodes = (Nodes -- Known) -- [node()].
%%% {nodes_changed, {New,Old}}
%%% Every now and then the list [node() | nodes()] is checked for updates.
%%% New are the nodes that global does not know of (yet).
@@ -187,7 +161,7 @@ t(File) ->
%% {show_state, From, To}
%% From = To = integer() | {integer(), integer()}
%% Examples: {7, 8} (show states between seconds 7.0 and 8.0);
-%% {{1,431234},{2,432}} (between 1.431234 and 2.000432)
+%% {{1,431234},{2,432}} (between 1.431234 and 2.432)
%% The state of a node includes locks, names, nodes, known, ...
%% Default is {{0,0}, {0,0}}, that is, do not show state.
%% show_state
@@ -226,7 +200,7 @@ t(File, Options) ->
{high_level_trace, ET, D3} ->
{D3, ET};
_ ->
- {D1, now()}
+ {D1, erlang:timestamp()}
end,
D = adjust_nodes(D2),
{NodeNodeTrace, _NodeTrace, Trace, Base} = get_trace(D, End),
@@ -320,13 +294,12 @@ adjust_times(Ts, Base) ->
[setelement(2, adj_tag(T, Base), adjust_time(element(2, T), Base)) ||
T <- Ts].
-adj_tag({Node, Time, {M, Node2}, Nodes, Extra}=T, Base) ->
+adj_tag({Node, Time, {M, Node2}, Nodes, Extra}=T, _Base) ->
if
M =:= new_resolver;
M =:= kill_resolver;
M =:= exit_resolver ->
- {Node, Time, {M, Node2}, Nodes,
- [adjust_time(hd(Extra), Base) | tl(Extra)]};
+ {Node, Time, {M, Node2}, Nodes, Extra};
true ->
T
end.
@@ -356,10 +329,16 @@ adjust_node(Node) ->
z_2;
"z_" ++ _ ->
z;
- "b_" ++ _ ->
- b;
"c_external_nodes" ++ _ ->
c_external_nodes;
+ "a_" ++ _ ->
+ a;
+ "b_" ++ _ ->
+ b;
+ "c_" ++ _ ->
+ c;
+ "d_" ++ _ ->
+ d;
_ ->
Node
end.
@@ -381,7 +360,7 @@ eval([T | Ts], Time0, S0, Fun) ->
end,
case time_diff(Time1, Time0) > 0 of
true ->
- display_nodes("PAUS", Time1, S0#w.nodes, T);
+ display_nodes("PAUSE", Time1, S0#w.nodes, T);
false ->
ok
end,
@@ -800,9 +779,9 @@ ms(syncers) ->
no_info(D) ->
[{Node,no_info} || {Node, no_info} <- D].
-resolvers(D, Base, End) ->
+resolvers(D, _Base, End) ->
[{Node,
- [{N,adjust_time(T, Base),P} || {N, T, P} <- Rs, T < End]} ||
+ [{N,T,P} || {N, T, P} <- Rs, T < End]} ||
{Node, {info,State}} <- D,
is_record(State, state),
[] =/= (Rs = (state(State))#state.resolvers)].
@@ -834,16 +813,21 @@ negotiations(Trace) ->
{Node,T,Added,[{new_nodes,[Other|_]=NewNodes},_Abcast,_Ops]} <- Ns],
Act ++ Pass.
-show_spurious(NodeTrace, Spurious) ->
- Pairs = [{Node,ActionNode} || {{Node,ActionNode}, _Time} <- Spurious],
- S = sofs:restriction(sofs:relation(NodeTrace), sofs:set(Pairs)),
+show_spurious(NodeTraceL, SpuriousL) ->
+ TraceDomL = [{Node,ActionNode} ||
+ {{Node,ActionNode}, _Ts} <- NodeTraceL],
+ SpuriousDomL = [{Node,ActionNode} ||
+ {{Node,ActionNode}, _Times} <- SpuriousL],
+ S = sofs:restriction(sofs:relation(NodeTraceL), sofs:set(SpuriousDomL)),
+ %% Some spurious lost:
+ Spurious = sofs:restriction(sofs:relation(SpuriousL), sofs:set(TraceDomL)),
[foo ||
{{{Node,ANode},Times},
- {{Node,ANode},Ts}} <- lists:zip(family(Spurious),
+ {{Node,ANode},Ts}} <- lists:zip(family(sofs:to_external(Spurious)),
sofs:to_external(S)),
- show_spurious(Node, ANode, Times, lists:keysort(2, Ts))].
+ show_spurious2(Node, ANode, Times, lists:keysort(2, Ts))].
-show_spurious(Node, ActionNode, Times, Ts) ->
+show_spurious2(Node, ActionNode, Times, Ts) ->
io:format("** Actions for ~p on node ~p **~n", [ActionNode, Node]),
lists:map(fun(T) -> spurious(Node, T, Times) end, Ts),
io:format("-- End of actions for ~p on node ~p --~n", [ActionNode, Node]),
diff --git a/lib/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl
index 594ee6b537..df6c6b517e 100644
--- a/lib/kernel/test/global_group_SUITE.erl
+++ b/lib/kernel/test/global_group_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,8 @@
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2,
init_per_suite/1, end_per_suite/1]).
-export([start_gg_proc/1, no_gg_proc/1, no_gg_proc_sync/1, compatible/1,
- one_grp/1, one_grp_x/1, two_grp/1, hidden_groups/1, test_exit/1]).
+ one_grp/1, one_grp_x/1, two_grp/1, hidden_groups/1, test_exit/1,
+ global_disconnect/1]).
-export([init/1, init/2, init2/2, start_proc/1, start_proc_rereg/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -42,7 +43,8 @@ suite() ->
all() ->
[start_gg_proc, no_gg_proc, no_gg_proc_sync, compatible,
- one_grp, one_grp_x, two_grp, test_exit, hidden_groups].
+ one_grp, one_grp_x, two_grp, test_exit, hidden_groups,
+ global_disconnect].
groups() ->
[].
@@ -55,7 +57,6 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) ->
-
%% Copied from test_server_ctrl ln 647, we have to do this here as
%% the test_server only does this when run without common_test
global:sync(),
@@ -81,10 +82,10 @@ end_per_suite(_Config) ->
-define(TESTCASE, testcase_name).
-define(testcase, proplists:get_value(?TESTCASE, Config)).
-init_per_testcase(Case, Config) ->
+init_per_testcase(_Case, Config) ->
Config.
-end_per_testcase(_Func, _Config) ->
+end_per_testcase(_Case, _Config) ->
ok.
%%-----------------------------------------------------------------
@@ -99,25 +100,23 @@ start_gg_proc(Config) when is_list(Config) ->
Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, "global_group.config"),
{ok, Fd}=file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
+ [Ncp1,Ncp2,Ncp3] = [?CT_PEER_NAME() || _ <- [cp1, cp2, cp3]],
config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
- Cp1nn = node_at(Ncp1),
- Cp2nn = node_at(Ncp2),
- Cp3nn = node_at(Ncp3),
+ Args = ["-config", filename:join(Dir, "global_group")],
- {ok, Cp1} = start_node(Ncp1, Config),
- {ok, Cp2} = start_node(Ncp2, Config),
- {ok, Cp3} = start_node(Ncp3, Config),
+ {ok, Peer1, Cp1} = ?CT_PEER(#{name => Ncp1, args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{name => Ncp2, args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{name => Ncp3, args => Args}),
- [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
+ [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1}]),
+ [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2}]),
+ [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3}]),
%% stop the nodes, and make sure names are released.
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
?UNTIL(undefined =:= global:whereis_name(test)),
ok.
@@ -132,36 +131,29 @@ no_gg_proc(Config) when is_list(Config) ->
{ok, Fd} = file:open(File, [write]),
config_no(Fd),
- NN = node_name(atom_to_list(node())),
- Cp1nn = list_to_atom("cp1@" ++ NN),
- Cp2nn = list_to_atom("cp2@" ++ NN),
- Cp3nn = list_to_atom("cp3@" ++ NN),
- Cpxnn = list_to_atom("cpx@" ++ NN),
- Cpynn = list_to_atom("cpy@" ++ NN),
- Cpznn = list_to_atom("cpz@" ++ NN),
-
- {ok, Cp1} = start_node_no(cp1, Config),
- {ok, Cp2} = start_node_no(cp2, Config),
- {ok, Cp3} = start_node_no(cp3, Config),
- {ok, Cpx} = start_node_no(cpx, Config),
- {ok, Cpy} = start_node_no(cpy, Config),
- {ok, Cpz} = start_node_no(cpz, Config),
+ Args = ["-config", filename:join(Dir, "no_global_group")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{args => Args}),
+ {ok, Peerx, Cpx} = ?CT_PEER(#{args => Args}),
+ {ok, Peery, Cpy} = ?CT_PEER(#{args => Args}),
+ {ok, Peerz, Cpz} = ?CT_PEER(#{args => Args}),
%% let the nodes know of each other
- pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
- pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
- pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
- pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpx]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpy]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cpz]),
wait_for_ready_net(),
- [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
- [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
- [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpx}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpy}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpz}]),
%% start a proc and register it
@@ -171,28 +163,28 @@ no_gg_proc(Config) when is_list(Config) ->
RegNames =
lists:sort(
- rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])),
+ rpc:call(Cp1, global_group, registered_names, [{node, Cp1}])),
RegNames =
lists:sort(
- rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])),
+ rpc:call(Cp2, global_group, registered_names, [{node, Cp2}])),
RegNames =
lists:sort(
- rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])),
+ rpc:call(Cp3, global_group, registered_names, [{node, Cp3}])),
RegNames =
lists:sort(
- rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])),
+ rpc:call(Cp1, global_group, registered_names, [{node, Cpx}])),
RegNames =
lists:sort(
- rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])),
+ rpc:call(Cp2, global_group, registered_names, [{node, Cpy}])),
RegNames =
lists:sort(
- rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])),
+ rpc:call(Cp3, global_group, registered_names, [{node, Cpz}])),
undefined = rpc:call(Cp3, global_group, global_groups, []),
- Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
- Cpxnn, Cpynn, Cpznn],
+ Own_nodes_should = [node(), Cp1, Cp2, Cp3,
+ Cpx, Cpy, Cpz],
Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
[] = (Own_nodes -- Own_nodes_should),
[] = (Own_nodes_should -- Own_nodes),
@@ -224,67 +216,67 @@ no_gg_proc(Config) when is_list(Config) ->
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2}, test2, monitor]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test, monitor]),
%% Kill node Cp1
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodedown, Cp1}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodedown, Cp1}]),
ct:sleep(100),
- stop_node(Cp1),
+ peer:stop(Peer1),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Kill node Cpz
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodedown, Cpz}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodedown, Cpz}]),
ct:sleep(100),
- stop_node(Cpz),
+ peer:stop(Peerz),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Restart node Cp1
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodeup, Cp1}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]),
- {ok, Cp1} = start_node_no(cp1, Config),
- pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodeup, Cp1}]),
+ {ok, Peer11, Cp1} = ?CT_PEER(#{name => Cp1, args => Args}),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cp1]),
wait_for_ready_net(),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Restart node Cpz
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodeup, Cpz}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]),
- {ok, Cpz} = start_node_no(cpz, Config),
- pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodeup, Cpz}]),
+ {ok, Peer1z, Cpz} = ?CT_PEER(#{name => Cpz, args => Args}),
+ pong = rpc:call(Cp2, net_adm, ping, [Cpz]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpz]),
wait_for_ready_net(),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% stop the nodes, and make sure names are released.
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
- stop_node(Cpx),
- stop_node(Cpy),
- stop_node(Cpz),
+ peer:stop(Peer11),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
+ peer:stop(Peerx),
+ peer:stop(Peery),
+ peer:stop(Peer1z),
?UNTIL(undefined =:= global:whereis_name(test)),
ok.
@@ -299,39 +291,33 @@ no_gg_proc_sync(Config) when is_list(Config) ->
File = filename:join(Dir, "no_global_group_sync.config"),
{ok, Fd} = file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
- node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
+ [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = [?CT_PEER_NAME() ||
+ _ <- [cp1,cp2,cp3,cpx,cpy,cpz]],
config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
- Cp1nn = node_at(Ncp1),
- Cp2nn = node_at(Ncp2),
- Cp3nn = node_at(Ncp3),
- Cpxnn = node_at(Ncpx),
- Cpynn = node_at(Ncpy),
- Cpznn = node_at(Ncpz),
-
- {ok, Cp1} = start_node_no2(Ncp1, Config),
- {ok, Cp2} = start_node_no2(Ncp2, Config),
- {ok, Cp3} = start_node_no2(Ncp3, Config),
- {ok, Cpx} = start_node_no2(Ncpx, Config),
- {ok, Cpy} = start_node_no2(Ncpy, Config),
- {ok, Cpz} = start_node_no2(Ncpz, Config),
+ Args = ["-config", filename:join(Dir, "no_global_group_sync")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{name => Ncp1, args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{name => Ncp2, args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{name => Ncp3, args => Args}),
+ {ok, Peerx, Cpx} = ?CT_PEER(#{name => Ncpx, args => Args}),
+ {ok, Peery, Cpy} = ?CT_PEER(#{name => Ncpy, args => Args}),
+ {ok, Peerz, Cpz} = ?CT_PEER(#{name => Ncpz, args => Args}),
%% let the nodes know of each other
- pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
- pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
- pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
- pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpx]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpy]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cpz]),
wait_for_ready_net(),
- [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
- [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
- [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpx}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpy}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpz}]),
%% start a proc and register it
@@ -341,28 +327,28 @@ no_gg_proc_sync(Config) when is_list(Config) ->
RegNames =
lists:sort(
- rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])),
+ rpc:call(Cp1, global_group, registered_names, [{node, Cp1}])),
RegNames =
lists:sort(
- rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])),
+ rpc:call(Cp2, global_group, registered_names, [{node, Cp2}])),
RegNames =
lists:sort(
- rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])),
+ rpc:call(Cp3, global_group, registered_names, [{node, Cp3}])),
RegNames =
lists:sort(
- rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])),
+ rpc:call(Cp1, global_group, registered_names, [{node, Cpx}])),
RegNames =
lists:sort(
- rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])),
+ rpc:call(Cp2, global_group, registered_names, [{node, Cpy}])),
RegNames =
lists:sort(
- rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])),
+ rpc:call(Cp3, global_group, registered_names, [{node, Cpz}])),
undefined = rpc:call(Cp3, global_group, global_groups, []),
- Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
- Cpxnn, Cpynn, Cpznn],
+ Own_nodes_should = [node(), Cp1, Cp2, Cp3,
+ Cpx, Cpy, Cpz],
Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
[] = (Own_nodes -- Own_nodes_should),
[] = (Own_nodes_should -- Own_nodes),
@@ -394,67 +380,67 @@ no_gg_proc_sync(Config) when is_list(Config) ->
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2}, test2, monitor]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test, monitor]),
%% Kill node Cp1
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodedown, Cp1}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodedown, Cp1}]),
ct:sleep(100),
- stop_node(Cp1),
+ peer:stop(Peer1),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Kill node Cpz
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodedown, Cpz}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodedown, Cpz}]),
ct:sleep(100),
- stop_node(Cpz),
+ peer:stop(Peerz),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Restart node Cp1
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodeup, Cp1}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]),
- {ok, Cp1} = start_node_no2(Ncp1, Config),
- pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodeup, Cp1}]),
+ {ok, Peer11, Cp1} = ?CT_PEER(#{name => Cp1, args => Args}),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cp1]),
wait_for_ready_net(),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Restart node Cpz
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodeup, Cpz}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]),
- {ok, Cpz} = start_node_no2(Ncpz, Config),
- pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodeup, Cpz}]),
+ {ok, Peerz1, Cpz} = ?CT_PEER(#{name => Cpz, args => Args}),
+ pong = rpc:call(Cp2, net_adm, ping, [Cpz]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpz]),
wait_for_ready_net(),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% stop the nodes, and make sure names are released.
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
- stop_node(Cpx),
- stop_node(Cpy),
- stop_node(Cpz),
+ peer:stop(Peer11),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
+ peer:stop(Peerx),
+ peer:stop(Peery),
+ peer:stop(Peerz1),
?UNTIL(undefined =:= global:whereis_name(test)),
ok.
@@ -468,39 +454,33 @@ compatible(Config) when is_list(Config) ->
File = filename:join(Dir, "global_group_comp.config"),
{ok, Fd} = file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] =
- node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config),
- config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
-
- Cp1nn = node_at(Ncp1),
- Cp2nn = node_at(Ncp2),
- Cp3nn = node_at(Ncp3),
- Cpxnn = node_at(Ncpx),
- Cpynn = node_at(Ncpy),
- Cpznn = node_at(Ncpz),
+ [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = [?CT_PEER_NAME() ||
+ _ <- [cp1,cp2,cp3,cpx,cpy,cpz]],
+ config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz),
- {ok, Cp1} = start_node_comp(Ncp1, Config),
- {ok, Cp2} = start_node_comp(Ncp2, Config),
- {ok, Cp3} = start_node_comp(Ncp3, Config),
- {ok, Cpx} = start_node_comp(Ncpx, Config),
- {ok, Cpy} = start_node_comp(Ncpy, Config),
- {ok, Cpz} = start_node_comp(Ncpz, Config),
+ Args = ["-config", filename:join(Dir, "global_group_comp")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{args => Args}),
+ {ok, Peerx, Cpx} = ?CT_PEER(#{args => Args}),
+ {ok, Peery, Cpy} = ?CT_PEER(#{args => Args}),
+ {ok, Peerz, Cpz} = ?CT_PEER(#{args => Args}),
%% let the nodes know of each other
- pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]),
- pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]),
- pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cpynn]),
- pong = rpc:call(Cpy, net_adm, ping, [Cpznn]),
+ pong = rpc:call(Cp1, net_adm, ping, [Cp2]),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp3]),
+ pong = rpc:call(Cp3, net_adm, ping, [Cpx]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpy]),
+ pong = rpc:call(Cpy, net_adm, ping, [Cpz]),
wait_for_ready_net(),
- [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
- [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]),
- [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]),
- [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]),
- [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]),
- [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3}]),
+ [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpx}]),
+ [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpy}]),
+ [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpz}]),
%% start a proc and register it
@@ -510,28 +490,28 @@ compatible(Config) when is_list(Config) ->
RegNames =
lists:sort(
- rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])),
+ rpc:call(Cp1, global_group, registered_names, [{node, Cp1}])),
RegNames =
lists:sort(
- rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])),
+ rpc:call(Cp2, global_group, registered_names, [{node, Cp2}])),
RegNames =
lists:sort(
- rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])),
+ rpc:call(Cp3, global_group, registered_names, [{node, Cp3}])),
RegNames =
lists:sort(
- rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])),
+ rpc:call(Cp1, global_group, registered_names, [{node, Cpx}])),
RegNames =
lists:sort(
- rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])),
+ rpc:call(Cp2, global_group, registered_names, [{node, Cpy}])),
RegNames =
lists:sort(
- rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])),
+ rpc:call(Cp3, global_group, registered_names, [{node, Cpz}])),
undefined = rpc:call(Cp3, global_group, global_groups, []),
- Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn,
- Cpxnn, Cpynn, Cpznn],
+ Own_nodes_should = [node(), Cp1, Cp2, Cp3,
+ Cpx, Cpy, Cpz],
Own_nodes = rpc:call(Cp3, global_group, own_nodes, []),
[] = (Own_nodes -- Own_nodes_should),
[] = (Own_nodes_should -- Own_nodes),
@@ -563,67 +543,67 @@ compatible(Config) when is_list(Config) ->
%%------------------------------------
%% Test monitor nodes
%%------------------------------------
- Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2}, test2, monitor]),
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test, monitor]),
%% Kill node Cp1
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodedown, Cp1}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodedown, Cp1}]),
ct:sleep(100),
- stop_node(Cp1),
+ peer:stop(Peer1),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Kill node Cpz
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodedown, Cpz}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodedown, Cpz}]),
ct:sleep(100),
- stop_node(Cpz),
+ peer:stop(Peerz),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Restart node Cp1
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodeup, Cp1}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]),
- {ok, Cp1} = start_node_comp(Ncp1, Config),
- pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodeup, Cp1}]),
+ {ok, Peer11, Cp1} = ?CT_PEER(#{name => Cp1, args => Args}),
+ pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cp1]),
wait_for_ready_net(),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% Restart node Cpz
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, {wait_nodeup, Cpz}]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]),
- {ok, Cpz} = start_node_comp(Ncpz, Config),
- pong = rpc:call(Cp2, net_adm, ping, [Cpznn]),
- pong = rpc:call(Cpx, net_adm, ping, [Cpznn]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, {wait_nodeup, Cpz}]),
+ {ok, Peer1z, Cpz} = ?CT_PEER(#{name => Cpz, args => Args}),
+ pong = rpc:call(Cp2, net_adm, ping, [Cpz]),
+ pong = rpc:call(Cpx, net_adm, ping, [Cpz]),
wait_for_ready_net(),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
%% stop the nodes, and make sure names are released.
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
- stop_node(Cpx),
- stop_node(Cpy),
- stop_node(Cpz),
+ peer:stop(Peer11),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
+ peer:stop(Peerx),
+ peer:stop(Peery),
+ peer:stop(Peer1z),
?UNTIL(undefined =:= global:whereis_name(test)),
ok.
@@ -636,12 +616,13 @@ one_grp(Config) when is_list(Config) ->
Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, "global_group.config"),
{ok, Fd} = file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
+ [Ncp1,Ncp2,Ncp3] = [?CT_PEER_NAME() || _ <- [cp1, cp2, cp3]],
config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
- {ok, Cp1} = start_node(Ncp1, Config),
- {ok, Cp2} = start_node(Ncp2, Config),
- {ok, Cp3} = start_node(Ncp3, Config),
+ Args = ["-config", filename:join(Dir, "global_group")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{name => Ncp1, args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{name => Ncp2, args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{name => Ncp3, args => Args}),
%% sleep a while to make the global_group to sync...
ct:sleep(1000),
@@ -698,13 +679,13 @@ one_grp(Config) when is_list(Config) ->
{_, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]),
%% stop the nodes, and make sure names are released.
- stop_node(Cp3),
+ peer:stop(Peer3),
?UNTIL(undefined =:= rpc:call(Cp1, global, whereis_name, [test])),
Pid2 ! die,
- stop_node(Cp1),
- stop_node(Cp2),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
ok.
@@ -718,17 +699,18 @@ one_grp_x(Config) when is_list(Config) ->
Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, "global_group.config"),
{ok, Fd} = file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config),
+ [Ncp1,Ncp2,Ncp3] = [?CT_PEER_NAME() || _ <- [cp1, cp2, cp3]],
config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"),
- {ok, Cp1} = start_node(Ncp1, Config),
+ Args = ["-config", filename:join(Dir, "global_group")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{name => Ncp1, args => Args}),
%% sleep a while to make the global_group to sync...
ct:sleep(1000),
%% start a proc and register it
{Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]),
- {ok, Cp2} = start_node(Ncp2, Config),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{name => Ncp2, args => Args}),
%% sleep a while to make the global_group to sync...
ct:sleep(1000),
@@ -736,7 +718,7 @@ one_grp_x(Config) when is_list(Config) ->
Pid = rpc:call(Cp1, global, whereis_name, [test]),
Pid = rpc:call(Cp2, global, whereis_name, [test]),
- {ok, Cp3} = start_node(Ncp3, Config),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{name => Ncp3, args => Args}),
%% sleep a while to make the global_group to sync...
ct:sleep(1000),
@@ -759,9 +741,9 @@ one_grp_x(Config) when is_list(Config) ->
Pid2 ! die,
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
ok.
@@ -776,23 +758,17 @@ two_grp(Config) when is_list(Config) ->
File = filename:join(Dir, "global_group.config"),
{ok, Fd} = file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
- node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
+ [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = [?CT_PEER_NAME() ||
+ _ <- [cp1,cp2,cp3,cpx,cpy,cpz,cpq]],
config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq),
- Cp1nn = node_at(Ncp1),
- Cp2nn = node_at(Ncp2),
- Cp3nn = node_at(Ncp3),
- Cpxnn = node_at(Ncpx),
- Cpynn = node_at(Ncpy),
- Cpznn = node_at(Ncpz),
-
- {ok, Cp1} = start_node(Ncp1, Config),
- {ok, Cp2} = start_node(Ncp2, Config),
- {ok, Cp3} = start_node(Ncp3, Config),
- {ok, Cpx} = start_node(Ncpx, Config),
- {ok, Cpy} = start_node(Ncpy, Config),
- {ok, Cpz} = start_node(Ncpz, Config),
+ Args = ["-config", filename:join(Dir, "global_group")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{name => Ncp1, args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{name => Ncp2, args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{name => Ncp3, args => Args}),
+ {ok, Peerx, Cpx} = ?CT_PEER(#{name => Ncpx, args => Args}),
+ {ok, Peery, Cpy} = ?CT_PEER(#{name => Ncpy, args => Args}),
+ {ok, Peerz, Cpz} = ?CT_PEER(#{name => Ncpz, args => Args}),
%% The groups (cpq not started):
%% [{nc1, [cp1,cp2,cp3]}, {nc2, [cpx,cpy,cpz]}, {nc3, [cpq]}]
@@ -809,12 +785,14 @@ two_grp(Config) when is_list(Config) ->
{nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []),
%% check the global group nodes
- [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp1, global_group, own_nodes, []),
- [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []),
- [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp3, global_group, own_nodes, []),
- [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpx, global_group, own_nodes, []),
- [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpy, global_group, own_nodes, []),
- [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpz, global_group, own_nodes, []),
+ Nodes1 = lists:sort([Cp1, Cp2, Cp3]),
+ Nodes2 = lists:sort([Cpx, Cpy, Cpz]),
+ Nodes1 = rpc:call(Cp1, global_group, own_nodes, []),
+ Nodes1 = rpc:call(Cp2, global_group, own_nodes, []),
+ Nodes1 = rpc:call(Cp3, global_group, own_nodes, []),
+ Nodes2 = rpc:call(Cpx, global_group, own_nodes, []),
+ Nodes2 = rpc:call(Cpy, global_group, own_nodes, []),
+ Nodes2 = rpc:call(Cpz, global_group, own_nodes, []),
%% start a proc and register it
@@ -825,10 +803,10 @@ two_grp(Config) when is_list(Config) ->
Pid1 = rpc:call(Cp1, global_group, send, [{group,nc1}, test,
{io, from_cp1}]),
[test] =
- rpc:call(Cpx, global_group, registered_names, [{node, Cp1nn}]),
+ rpc:call(Cpx, global_group, registered_names, [{node, Cp1}]),
[test] =
rpc:call(Cpx, global_group, registered_names, [{group, nc1}]),
- [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpxnn}]),
+ [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpx}]),
[] = rpc:call(Cpx, global_group, registered_names, [{group, nc2}]),
Pid1 = rpc:call(Cpx, global_group, send, [{group,nc1}, test,
{io, from_cp1}]),
@@ -924,21 +902,21 @@ two_grp(Config) when is_list(Config) ->
2000 -> ct:fail(timeout2)
end,
- Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1nn}, test2,
+ Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1}, test2,
{ping, self()}]),
receive
{pong, Cp2} -> ok
after
2000 -> ct:fail(timeout2)
end,
- Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2nn}, test2,
+ Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2}, test2,
{ping, self()}]),
receive
{pong, Cp2} -> ok
after
2000 -> ct:fail(timeout2)
end,
- Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3nn}, test2,
+ Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3}, test2,
{ping, self()}]),
receive
{pong, Cp2} -> ok
@@ -946,21 +924,21 @@ two_grp(Config) when is_list(Config) ->
2000 -> ct:fail(timeout2)
end,
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpznn}, test,
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpz}, test,
{ping, self()}]),
receive
{pong, Cpx} -> ok
after
2000 -> ct:fail(timeout2)
end,
- PidX = rpc:call(Cpy, global_group, send, [{node, Cpxnn}, test,
+ PidX = rpc:call(Cpy, global_group, send, [{node, Cpx}, test,
{ping, self()}]),
receive
{pong, Cpx} -> ok
after
2000 -> ct:fail(timeout2)
end,
- PidX = rpc:call(Cpz, global_group, send, [{node, Cpynn}, test,
+ PidX = rpc:call(Cpz, global_group, send, [{node, Cpy}, test,
{ping, self()}]),
receive
{pong, Cpx} -> ok
@@ -987,79 +965,79 @@ two_grp(Config) when is_list(Config) ->
%% Test monitor nodes
%%------------------------------------
Pid2 =
- rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]),
+ rpc:call(Cp1, global_group, send, [{node, Cp2}, test2, monitor]),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, monitor]),
%% Kill node Cp1
- Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2}, test2,
{wait_nodedown, Cp1}]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test,
{wait_nodedown, Cp1}]),
ct:sleep(100),
- stop_node(Cp1),
+ peer:stop(Peer1),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodedown),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop_nodedown),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, to_loop]),
%% Kill node Cpz
- Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2}, test2,
{wait_nodedown, Cpz}]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test,
{wait_nodedown, Cpz}]),
ct:sleep(100),
- stop_node(Cpz),
+ peer:stop(Peerz),
ct:sleep(1000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodedown),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop_nodedown),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, to_loop]),
%% Restart node Cp1
- [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []),
- Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ Nodes1 = rpc:call(Cp2, global_group, own_nodes, []),
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2}, test2,
{wait_nodeup, Cp1}]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test,
{wait_nodeup, Cp1}]),
ct:sleep(100),
- {ok, Cp1} = start_node(Ncp1, Config),
+ {ok, Peer11, Cp1} = ?CT_PEER(#{name => Cp1, args => Args}),
ct:sleep(5000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodeup),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop_nodeup),
PidX =
- rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]),
+ rpc:call(Cpx, global_group, send, [{node, Cpx}, test, to_loop]),
%% Restart node Cpz
- Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2,
+ Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2}, test2,
{wait_nodeup, Cpz}]),
- PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test,
+ PidX = rpc:call(Cpx, global_group, send, [{node, Cpx}, test,
{wait_nodeup, Cpz}]),
ct:sleep(100),
- {ok, Cpz} = start_node(Ncpz, Config),
+ {ok, Peer1z, Cpz} = ?CT_PEER(#{name => Cpz, args => Args}),
ct:sleep(5000),
- ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodeup),
- ok = assert_loop(Cpx, Cpxnn, test, PidX, loop),
+ ok = assert_loop(Cp2, Cp2, test2, Pid2, loop_nodeup),
+ ok = assert_loop(Cpx, Cpx, test, PidX, loop),
Pid2 =
- rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]),
+ rpc:call(Cp2, global_group, send, [{node, Cp2}, test2, to_loop]),
Pid2 ! die,
PidX ! die,
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
- stop_node(Cpx),
- stop_node(Cpy),
- stop_node(Cpz),
+ peer:stop(Peer11),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
+ peer:stop(Peerx),
+ peer:stop(Peery),
+ peer:stop(Peer1z),
ok.
@@ -1068,20 +1046,21 @@ two_grp(Config) when is_list(Config) ->
%% Test hidden global groups.
hidden_groups(Config) when is_list(Config) ->
Dir = proplists:get_value(priv_dir, Config),
- File = filename:join(Dir, "global_group.config"),
+ File = filename:join(Dir, "hidden_groups.config"),
{ok, Fd} = file:open(File, [write]),
- [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] =
- node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config),
+ [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = [?CT_PEER_NAME() ||
+ _ <- [cp1,cp2,cp3,cpx,cpy,cpz,cpq]],
config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq),
- {ok, Cp1} = start_node(Ncp1, Config),
- {ok, Cp2} = start_node(Ncp2, Config),
- {ok, Cp3} = start_node(Ncp3, Config),
- {ok, Cpx} = start_node(Ncpx, Config),
- {ok, Cpy} = start_node(Ncpy, Config),
- {ok, Cpz} = start_node(Ncpz, Config),
- {ok, Cpq} = start_node(Ncpq, Config),
+ Args = ["-config", filename:join(Dir, "hidden_groups")],
+ {ok, Peer1, Cp1} = ?CT_PEER(#{name => Ncp1, args => Args}),
+ {ok, Peer2, Cp2} = ?CT_PEER(#{name => Ncp2, args => Args}),
+ {ok, Peer3, Cp3} = ?CT_PEER(#{name => Ncp3, args => Args}),
+ {ok, Peerx, Cpx} = ?CT_PEER(#{name => Ncpx, args => Args}),
+ {ok, Peery, Cpy} = ?CT_PEER(#{name => Ncpy, args => Args}),
+ {ok, Peerz, Cpz} = ?CT_PEER(#{name => Ncpz, args => Args}),
+ {ok, Peerq, Cpq} = ?CT_PEER(#{name => Ncpq, args => Args}),
%% sleep a while to make the global_groups to sync...
ct:sleep(1000),
@@ -1095,12 +1074,14 @@ hidden_groups(Config) when is_list(Config) ->
{nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []),
%% check the global group nodes
- [Cp1, Cp2, Cp3] = rpc:call(Cp1, global_group, own_nodes, []),
- [Cp1, Cp2, Cp3] = rpc:call(Cp2, global_group, own_nodes, []),
- [Cp1, Cp2, Cp3] = rpc:call(Cp3, global_group, own_nodes, []),
- [Cpx, Cpy, Cpz] = rpc:call(Cpx, global_group, own_nodes, []),
- [Cpx, Cpy, Cpz] = rpc:call(Cpy, global_group, own_nodes, []),
- [Cpx, Cpy, Cpz] = rpc:call(Cpz, global_group, own_nodes, []),
+ Nodes1 = lists:sort([Cp1, Cp2, Cp3]),
+ Nodes2 = lists:sort([Cpx, Cpy, Cpz]),
+ Nodes1 = rpc:call(Cp1, global_group, own_nodes, []),
+ Nodes1 = rpc:call(Cp2, global_group, own_nodes, []),
+ Nodes1 = rpc:call(Cp3, global_group, own_nodes, []),
+ Nodes2 = rpc:call(Cpx, global_group, own_nodes, []),
+ Nodes2 = rpc:call(Cpy, global_group, own_nodes, []),
+ Nodes2 = rpc:call(Cpz, global_group, own_nodes, []),
[Cpq] = rpc:call(Cpq, global_group, own_nodes, []),
%% Make some inter group connections
@@ -1112,107 +1093,237 @@ hidden_groups(Config) when is_list(Config) ->
pong = rpc:call(Cpz, net_adm, ping, [Cpq]),
%% Check that no inter group connections are visible
- NC1Nodes = lists:sort([Cp1, Cp2, Cp3]),
- NC2Nodes = lists:sort([Cpx, Cpy, Cpz]),
- NC1Nodes = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]),
- NC1Nodes = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]),
- NC1Nodes = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]),
- NC2Nodes = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]),
- NC2Nodes = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]),
- NC2Nodes = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]),
- NC12Nodes = lists:append(NC1Nodes, NC2Nodes),
+ Nodes1 = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]),
+ Nodes1 = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]),
+ Nodes1 = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]),
+ Nodes2 = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]),
+ Nodes2 = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]),
+ Nodes2 = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]),
+ NC12Nodes = lists:append(Nodes1, Nodes2),
false = lists:any(fun(N) -> lists:member(N, NC12Nodes) end,
rpc:call(Cpq, erlang, nodes, [])),
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
- stop_node(Cpx),
- stop_node(Cpy),
- stop_node(Cpz),
- stop_node(Cpq),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
+ peer:stop(Peerx),
+ peer:stop(Peery),
+ peer:stop(Peerz),
+ peer:stop(Peerq),
ok.
%% Checks when the search process exits. .
test_exit(Config) when is_list(Config) ->
- NN = node_name(atom_to_list(node())),
- Cp1nn = list_to_atom("cp1@" ++ NN),
+ Dir=proplists:get_value(priv_dir, Config),
+ Args = ["-config", filename:join(Dir, "global_group")],
- {ok, Cp1} = start_node(cp1, Config),
- {ok, Cp2} = start_node(cp2, Config),
- {ok, Cp3} = start_node(cp3, Config),
+ {ok, Peer1, Cp1} = ?CT_PEER(Args),
+ {ok, Peer2, _Cp2} = ?CT_PEER(Args),
+ {ok, Peer3, _Cp3} = ?CT_PEER(Args),
ct:sleep(1000),
{error, illegal_function_call} =
- rpc:call(Cp1, global_group, registered_names_test, [{node, Cp1nn}]),
+ rpc:call(Cp1, global_group, registered_names_test, [{node, Cp1}]),
{badarg,_} =
rpc:call(Cp1, global_group, send, [king, "The message"]),
undefined = rpc:call(Cp1, global_group, whereis_name, [king]),
% make sure the search process really exits after every global_group operations
ProcessCount0 = rpc:call(Cp1, erlang, system_info, [process_count]),
- _ = rpc:call(Cp1, global_group, whereis_name, [{node, Cp1nn}, whatever_pid_name]),
+ _ = rpc:call(Cp1, global_group, whereis_name, [{node, Cp1}, whatever_pid_name]),
ProcessCount1 = rpc:call(Cp1, erlang, system_info, [process_count]),
- _ = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]),
+ _ = rpc:call(Cp1, global_group, registered_names, [{node, Cp1}]),
ProcessCount2 = rpc:call(Cp1, erlang, system_info, [process_count]),
- _ = rpc:call(Cp1, global_group, send, [{node, Cp1nn}, whatever_pid_name, msg]),
+ _ = rpc:call(Cp1, global_group, send, [{node, Cp1}, whatever_pid_name, msg]),
ProcessCount3 = rpc:call(Cp1, erlang, system_info, [process_count]),
ProcessCount0 = ProcessCount1 = ProcessCount2 = ProcessCount3,
%% stop the nodes, and make sure names are released.
- stop_node(Cp1),
- stop_node(Cp2),
- stop_node(Cp3),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
+ peer:stop(Peer3),
%% sleep to let the nodes die
ct:sleep(1000),
ok.
+global_disconnect(Config) when is_list(Config) ->
+ Dir = proplists:get_value(priv_dir, Config),
-start_node(Name, Config) ->
- Pa=filename:dirname(code:which(?MODULE)),
- Dir=proplists:get_value(priv_dir, Config),
- ConfFile = " -config " ++ filename:join(Dir, "global_group"),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
+ [NProxy,Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Nh]
+ = [?CT_PEER_NAME(atom_to_list(?FUNCTION_NAME)++"-"++atom_to_list(NN))
+ || NN <- [proxy,cp1,cp2,cp3,cpx,cpy,cpz,h]],
+
+ Host = from($@, atom_to_list(node())),
+
+ WriteConf = fun (File,
+ [S1, S2, S3],
+ [NC11, NC12, NC13],
+ [NC21, NC22, NC23]) ->
+ {ok, Fd} = file:open(filename:join(Dir, File), [write]),
+ io:format(Fd,
+ "[{kernel,~n"
+ " [~n"
+ " {sync_nodes_optional, ['~s@~s','~s@~s','~s@~s']},~n"
+ " {sync_nodes_timeout, 1000},~n"
+ " {global_groups,~n"
+ " [{nc1, ['~s@~s','~s@~s','~s@~s']},~n"
+ " {nc2, ['~s@~s','~s@~s','~s@~s']}]}~n"
+ " ]~n"
+ " }].~n",
+ [S1, Host, S2, Host, S3, Host,
+ NC11, Host, NC12, Host, NC13, Host,
+ NC21, Host, NC22, Host, NC23, Host]),
+ file:close(Fd)
+ end,
+
+ WriteConf("nc1.config", [Ncp1,Ncp2,Ncp3], [Ncp1,Ncp2,Ncp3], [Ncpx,Ncpy,Ncpz]),
+ WriteConf("nc2.config", [Ncpx,Ncpy,Ncpz], [Ncp1,Ncp2,Ncp3], [Ncpx,Ncpy,Ncpz]),
+
+ NC1Args = ["-config", filename:join(Dir, "nc1")],
+ NC2Args = ["-config", filename:join(Dir, "nc2")],
+
+ PeerNodes = lists:map(fun ({Name, Args}) ->
+ ?CT_PEER(#{name => Name,
+ args => Args,
+ connection => 0})
+ end,
+ [{Ncp1, NC1Args},
+ {Ncp2, NC1Args},
+ {Ncp3, NC1Args},
+ {Ncpx, NC2Args},
+ {Ncpy, NC2Args},
+ {Ncpz, NC2Args},
+ {Nh, ["-hidden"]},
+ {NProxy, ["-hidden"]}]),
+
+ [{ok, _, Cp1}, {ok, _, Cp2}, {ok, _, Cp3},
+ {ok, _, Cpx}, {ok, _, Cpy}, {ok, _, Cpz},
+ {ok, _, H}, {ok, _, P}] = PeerNodes,
+
+ %% RPC() - An rpc via a hidden proxy node...
+ RPC = fun (N, M, F, A) ->
+ erpc:call(P, erpc, call, [N, M, F, A])
+ end,
+
+ %% The groups
+ NC1Nodes = lists:sort([Cp1, Cp2, Cp3]),
+ NC2Nodes = lists:sort([Cpx, Cpy, Cpz]),
-start_node_no(Name, Config) ->
- Pa=filename:dirname(code:which(?MODULE)),
- Dir=proplists:get_value(priv_dir, Config),
- ConfFile = " -config " ++ filename:join(Dir, "no_global_group"),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
+ %% Wait with disconnect from group nodes a while, so we
+ %% don't have any ongoing communication that brings up
+ %% the connections again...
+ receive after 500 -> ok end,
-start_node_no2(Name, Config) ->
- Pa=filename:dirname(code:which(?MODULE)),
- Dir=proplists:get_value(priv_dir, Config),
- ConfFile = " -config " ++ filename:join(Dir, "no_global_group_sync"),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
+ %% Disconnect test_server from the global group nodes...
+ lists:foreach(fun (N) -> erlang:disconnect_node(N) end, NC1Nodes++NC2Nodes),
-start_node_comp(Name, Config) ->
- Pa=filename:dirname(code:which(?MODULE)),
- Dir=proplists:get_value(priv_dir, Config),
- ConfFile = " -config " ++ filename:join(Dir, "global_group_comp"),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]).
+ %% wait some more to ensure that global group nodes have synced...
+ receive after 500 -> ok end,
-node_names(Names, Config) ->
- [node_name(Name, Config) || Name <- Names].
+ %% check the global group names
+ {nc1, [nc2]} = RPC(Cp1, global_group, global_groups, []),
+ {nc1, [nc2]} = RPC(Cp2, global_group, global_groups, []),
+ {nc1, [nc2]} = RPC(Cp3, global_group, global_groups, []),
+ {nc2, [nc1]} = RPC(Cpx, global_group, global_groups, []),
+ {nc2, [nc1]} = RPC(Cpy, global_group, global_groups, []),
+ {nc2, [nc1]} = RPC(Cpz, global_group, global_groups, []),
-node_name(Name, Config) ->
- U = "_",
- Pid = os:getpid(),
- {{Y,M,D}, {H,Min,S}} = calendar:now_to_local_time(now()),
- Date = io_lib:format("~4w_~2..0w_~2..0w__~2..0w_~2..0w_~2..0w",
- [Y,M,D, H,Min,S]),
- L = lists:flatten(Date),
- lists:concat([Name,U,?testcase,U,Pid,U,U,L]).
+ %% check the global group nodes
+ NC1Nodes = lists:sort(RPC(Cp1, global_group, own_nodes, [])),
+ NC1Nodes = lists:sort(RPC(Cp2, global_group, own_nodes, [])),
+ NC1Nodes = lists:sort(RPC(Cp3, global_group, own_nodes, [])),
+ NC2Nodes = lists:sort(RPC(Cpx, global_group, own_nodes, [])),
+ NC2Nodes = lists:sort(RPC(Cpy, global_group, own_nodes, [])),
+ NC2Nodes = lists:sort(RPC(Cpz, global_group, own_nodes, [])),
+
+ %% Set up connections that should *not* be affected
+ %% by our global:disconnect() call made later (this since
+ %% these connections are not internal in the group). One
+ %% hidden and one visible connection. We don't use the
+ %% proxy node for the hidden connection since it will be
+ %% brought up by our erpc calls if it should have been
+ %% taken down.
+ pong = RPC(H, net_adm, ping, [Cp1]),
+ pong = RPC(Cpx, net_adm, ping, [Cp1]),
+
+ %% Verify that the connections have been set up as
+ %% expected...
+ HiddenNodes = lists:sort([P, H]),
+
+ Cp1ConnectedNodes = lists:sort([P, H, Cpx, Cp2, Cp3]),
+ Cp1VisibleNodes = Cp1ConnectedNodes -- HiddenNodes,
+ Cp2ConnectedNodes = lists:sort([P, Cp1, Cp3]),
+ Cp2VisibleNodes = Cp2ConnectedNodes -- HiddenNodes,
+ Cp3ConnectedNodes = lists:sort([P, Cp1, Cp2]),
+ Cp3VisibleNodes = Cp3ConnectedNodes -- HiddenNodes,
+
+ CpxConnectedNodes = lists:sort([P, Cp1, Cpy, Cpz]),
+ CpxVisibleNodes = CpxConnectedNodes -- HiddenNodes,
+ CpyConnectedNodes = lists:sort([P, Cpx, Cpz]),
+ CpyVisibleNodes = CpyConnectedNodes -- HiddenNodes,
+ CpzConnectedNodes = lists:sort([P, Cpx, Cpy]),
+ CpzVisibleNodes = CpzConnectedNodes -- HiddenNodes,
+
+ Cp1ConnectedNodes = lists:sort(RPC(Cp1, erlang, nodes, [connected])),
+ Cp1VisibleNodes = lists:sort(RPC(Cp1, erlang, nodes, [])),
+ Cp2ConnectedNodes = lists:sort(RPC(Cp2, erlang, nodes, [connected])),
+ Cp2VisibleNodes = lists:sort(RPC(Cp2, erlang, nodes, [])),
+ Cp3ConnectedNodes = lists:sort(RPC(Cp3, erlang, nodes, [connected])),
+ Cp3VisibleNodes = lists:sort(RPC(Cp3, erlang, nodes, [])),
+
+ CpxConnectedNodes = lists:sort(RPC(Cpx, erlang, nodes, [connected])),
+ CpxVisibleNodes = lists:sort(RPC(Cpx, erlang, nodes, [])),
+ CpyConnectedNodes = lists:sort(RPC(Cpy, erlang, nodes, [connected])),
+ CpyVisibleNodes = lists:sort(RPC(Cpy, erlang, nodes, [])),
+ CpzConnectedNodes = lists:sort(RPC(Cpz, erlang, nodes, [connected])),
+ CpzVisibleNodes = lists:sort(RPC(Cpz, erlang, nodes, [])),
+
+ %% Expected disconnects made by global on Cp1...
+ Cp1DisconnectNodes = lists:sort([Cp2, Cp3]),
+
+ %% Perform the global:disconnect() on Cp1...
+ Cp1DisconnectNodes = lists:sort(RPC(Cp1, global, disconnect, [])),
+
+ %% Wait a while giving the other nodes time to react to the disconnects
+ %% before we check that everything is as expected...
+ receive after 2000 -> ok end,
+
+ %% Verify that only the connections Cp1-Cp2 and Cp1-Cp3 were
+ %% taken down...
+ Cp1PostConnectedNodes = Cp1ConnectedNodes -- Cp1DisconnectNodes,
+ Cp1PostVisibleNodes = Cp1PostConnectedNodes -- HiddenNodes,
+ Cp2PostConnectedNodes = Cp2ConnectedNodes -- [Cp1],
+ Cp2PostVisibleNodes = Cp2PostConnectedNodes -- HiddenNodes,
+ Cp3PostConnectedNodes = Cp3ConnectedNodes -- [Cp1],
+ Cp3PostVisibleNodes = Cp3PostConnectedNodes -- HiddenNodes,
+
+ Cp1PostConnectedNodes = lists:sort(RPC(Cp1, erlang, nodes, [connected])),
+ Cp1PostVisibleNodes = lists:sort(RPC(Cp1, erlang, nodes, [])),
+ Cp2PostConnectedNodes = lists:sort(RPC(Cp2, erlang, nodes, [connected])),
+ Cp2PostVisibleNodes = lists:sort(RPC(Cp2, erlang, nodes, [])),
+ Cp3PostConnectedNodes = lists:sort(RPC(Cp3, erlang, nodes, [connected])),
+ Cp3PostVisibleNodes = lists:sort(RPC(Cp3, erlang, nodes, [])),
+
+ CpxConnectedNodes = lists:sort(RPC(Cpx, erlang, nodes, [connected])),
+ CpxVisibleNodes = lists:sort(RPC(Cpx, erlang, nodes, [])),
+ CpyConnectedNodes = lists:sort(RPC(Cpy, erlang, nodes, [connected])),
+ CpyVisibleNodes = lists:sort(RPC(Cpy, erlang, nodes, [])),
+ CpzConnectedNodes = lists:sort(RPC(Cpz, erlang, nodes, [connected])),
+ CpzVisibleNodes = lists:sort(RPC(Cpz, erlang, nodes, [])),
+
+ lists:foreach(fun ({ok, Peer, _Node}) ->
+ peer:stop(Peer)
+ end, PeerNodes),
-stop_node(Node) ->
- test_server:stop_node(Node).
+ ok.
+%%%%% End of test-cases %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wait_for_ready_net() ->
Nodes = lists:sort(?NODES),
@@ -1236,10 +1347,10 @@ config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) ->
"{global_groups, [{nc1, hidden, ['~s@~s','~s@~s','~s@~s']}, "
"{nc2, hidden, ['~s@~s','~s@~s','~s@~s']}, "
"{nc3, normal, ['~s@~s']}]} ] }]. ~n",
- [Ncp1, M, Ncp2, M, Ncp3, M,
- Ncpx, M, Ncpy, M, Ncpz, M,
- Ncp1, M, Ncp2, M, Ncp3, M,
- Ncpx, M, Ncpy, M, Ncpz, M,
+ [Ncp1, M, Ncp2, M, Ncp3, M,
+ Ncpx, M, Ncpy, M, Ncpz, M,
+ Ncp1, M, Ncp2, M, Ncp3, M,
+ Ncpx, M, Ncpy, M, Ncpz, M,
Ncpq, M]).
config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) ->
@@ -1250,10 +1361,10 @@ config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) ->
"{global_groups, [{nc1, ['~s@~s','~s@~s','~s@~s']}, "
" {nc2, ['~s@~s','~s@~s','~s@~s']}, "
"{nc3, ['~s@~s']}]} ] }]. ~n",
- [Ncp1, M, Ncp2, M, Ncp3, M,
- Ncpx, M, Ncpy, M, Ncpz, M,
- Ncp1, M, Ncp2, M, Ncp3, M,
- Ncpx, M, Ncpy, M, Ncpz, M,
+ [Ncp1, M, Ncp2, M, Ncp3, M,
+ Ncpx, M, Ncpy, M, Ncpz, M,
+ Ncp1, M, Ncp2, M, Ncp3, M,
+ Ncpx, M, Ncpy, M, Ncpz, M,
Ncpq, M]).
config_no(Fd) ->
@@ -1265,7 +1376,7 @@ config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) ->
" '~s@~s','~s@~s','~s@~s']},"
"{sync_nodes_timeout, 1000},"
"{global_groups, []} ] }] .~n",
- [Ncp1, M, Ncp2, M, Ncp3, M,
+ [Ncp1, M, Ncp2, M, Ncp3, M,
Ncpx, M, Ncpy, M, Ncpz, M]).
@@ -1274,16 +1385,9 @@ config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) ->
io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', "
" '~s@~s','~s@~s','~s@~s']},"
"{sync_nodes_timeout, 1000} ] }] .~n",
- [Ncp1, M, Ncp2, M, Ncp3, M,
+ [Ncp1, M, Ncp2, M, Ncp3, M,
Ncpx, M, Ncpy, M, Ncpz, M]).
-node_at(N) ->
- NN = node_name(atom_to_list(node())),
- list_to_atom(lists:concat([N, "@", NN])).
-
-node_name(L) ->
- from($@, L).
-
from(H, [H | T]) -> T;
from(H, [_ | T]) -> from(H, T);
from(_, []) -> [].
@@ -1418,4 +1522,3 @@ loop_until_true(Fun) ->
_ ->
loop_until_true(Fun)
end.
-
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index f5ca6d0e1d..01a57947b1 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,159 +21,126 @@
-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2, start/1, restart/1,
- reboot/1,
- node_start_immediately_after_crash/1,
- node_start_soon_after_crash/1,
- set_cmd/1, clear_cmd/1, get_cmd/1,
- callback_api/1,
- options_api/1,
- dont_drop/1, kill_pid/1, heart_no_kill/1]).
-
--export([init_per_testcase/2, end_per_testcase/2]).
-
--export([start_heart_stress/1, mangle/1, suicide_by_heart/0, non_suicide_by_heart/0]).
-
--define(DEFAULT_TIMEOUT_SECS, 120).
-
--define(UNIQ_NODE_NAME,
- list_to_atom(?MODULE_STRING ++ "__" ++
- atom_to_list(?FUNCTION_NAME) ++ "_" ++
- integer_to_list(erlang:unique_integer([positive])))).
-
-init_per_testcase(_Func, Config) ->
- Config.
-
-end_per_testcase(_Func, _Config) ->
- Nodes = nodes(),
- lists:foreach(fun(X) ->
- NNam = list_to_atom(hd(string:tokens(atom_to_list(X),"@"))),
- case NNam of
- heart_test ->
- ct:pal(?HI_VERBOSITY, "WARNING: Killed ~p~n", [X]),
- rpc:cast(X, erlang, halt, []);
- _ ->
- ok
- end
- end, Nodes).
+%% Test suite exports
+-export([
+ all/0, suite/0,
+ init_per_suite/1, end_per_suite/1
+]).
+
+%% Test case exports
+-export([
+ start/0, start/1,
+ restart/0, restart/1,
+ reboot/0, reboot/1,
+ node_start_immediately_after_crash/1,
+ node_start_soon_after_crash/1,
+ set_cmd/1, clear_cmd/1, get_cmd/1,
+ callback_api/1, options_api/1, dont_drop/1,
+ kill_pid/0, kill_pid/1,
+ heart_no_kill/0, heart_no_kill/1
+]).
+
+%% Internal exports used by peer nodes
+-export([
+ start_heart_stress/1, mangle/1,
+ suicide_by_heart/0, non_suicide_by_heart/0,
+ exhaust_atoms/0
+]).
%%-----------------------------------------------------------------
-%% Test suite for heart.
-%% Should be started in a CC view with:
-%% erl -sname master -rsh ctrsh
-%%-----------------------------------------------------------------
+%% Test suite for heart
suite() ->
- [{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,2}}].
-
-all() -> [
- start, restart, reboot,
- node_start_immediately_after_crash,
- node_start_soon_after_crash,
- set_cmd, clear_cmd, get_cmd,
- callback_api,
- options_api,
- kill_pid,
- heart_no_kill
- ].
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
+ [{ct_hooks, [ts_install_cth]}, {timetrap, {minutes,2}}].
+all() ->
+ [
+ start, restart, reboot,
+ node_start_immediately_after_crash,
+ node_start_soon_after_crash,
+ set_cmd, clear_cmd, get_cmd, callback_api,
+ options_api, kill_pid, heart_no_kill].
init_per_suite(Config) when is_list(Config) ->
case os:type() of
- {win32, windows} ->
- {skipped, "No use to run on Windows 95/98"};
- _ ->
- ignore_cores:init(Config)
+ {win32, windows} ->
+ {skipped, "No use to run on Windows 95/98"};
+ _ ->
+ ignore_cores:init(Config)
end.
+
end_per_suite(Config) when is_list(Config) ->
ignore_cores:fini(Config).
+%%-----------------------------------------------------------------
+%% Test suite for heart
-start_check(Type, Name) ->
- start_check(Type, Name, []).
-start_check(Type, Name, Envs) ->
- Args = case test_server:os_type() of
- {win32,_} ->
- "+t50000 -heart " ++ env_encode([{"HEART_COMMAND", no_reboot}|Envs]);
- _ ->
- "+t50000 -heart " ++ env_encode(Envs)
- end,
- {ok, Node} = case Type of
- loose ->
- loose_node:start(Name, Args, ?DEFAULT_TIMEOUT_SECS);
- _ ->
- test_server:start_node(Name, Type, [{args, Args}])
- end,
+heart_args() ->
+ Common = ["-heart"],
+ case os:type() of
+ {win32, _} ->
+ Common ++ ["-env", "HEART_COMMAND", "no_reboot"];
+ _ ->
+ Common
+ end.
+
+heart_monitor(Node) ->
erlang:monitor_node(Node, true),
- case rpc:call(Node, erlang, whereis, [heart]) of
- Pid when is_pid(Pid) ->
- ok;
- _ ->
- ct:fail(heart_not_started)
- end,
- {ok, Node}.
+ %% assert that peer node has a heart
+ is_pid(rpc:call(Node, erlang, whereis, [heart])) orelse
+ ct:fail(heart_not_started),
+ ok.
+
+start() ->
+ [{doc, "Test that node is down after init:reboot"}].
start(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
- rpc:call(Node, init, reboot, []),
+ {ok, _Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
+ ok = rpc:call(Node, init, reboot, []),
receive
- {nodedown, Node} -> ok
- after 2000 -> ct:fail(node_not_closed)
+ {nodedown, Node} ->
+ ok
+ after
+ 2000 -> ct:fail(node_not_closed)
end,
timer:sleep(5000),
- case net_adm:ping(Node) of
- pang ->
- ok;
- _ ->
- ct:fail(node_rebooted)
- end,
- test_server:stop_node(Node).
+ net_adm:ping(Node) =:= pang orelse
+ ct:fail(node_rebooted).
+
+restart() ->
+ [{doc, "Check that a node is up and running after a init:restart/0"}].
%% Also test fixed bug in R1B (it was not possible to
%% do init:stop/0 on a restarted system before)
%% Slave executes erlang:halt() on master nodedown.
%% Therefore the slave process has to be killed
%% before restart.
-
-%% restart
-%% Purpose:
-%% Check that a node is up and running after a init:restart/0
restart(Config) when is_list(Config) ->
- {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME),
- rpc:call(Node, init, restart, []),
+ {ok, Peer, Node} = ?CT_PEER(#{connection => standard_io, args => heart_args()}),
+ heart_monitor(Node),
+ ok = rpc:call(Node, init, restart, []),
receive
- {nodedown, Node} ->
- ok
+ {nodedown, Node} ->
+ ok
after 5000 ->
ct:fail(node_not_closed)
end,
timer:sleep(5000),
node_check_up_down(Node, 2000),
- loose_node:stop(Node).
+ peer:stop(Peer).
-%% reboot
-%% Purpose:
-%% Check that a node is up and running after a init:reboot/0
-reboot(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
+reboot() ->
+ [{doc, "Check that a node is up and running after a init:reboot/0"}].
+reboot(Config) when is_list(Config) ->
+ {ok, _Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
ok = rpc:call(Node, heart, set_cmd,
- [ct:get_progname() ++
- " -noshell -heart " ++ name(Node) ++ "&"]),
- rpc:call(Node, init, reboot, []),
+ [ct:get_progname() ++ " -noshell -heart " ++ name(Node) ++ "&"]),
+ ok = rpc:call(Node, init, reboot, []),
receive
- {nodedown, Node} ->
- ok
+ {nodedown, Node} ->
+ ok
after 2000 ->
ct:fail(node_not_closed)
end,
@@ -187,50 +154,40 @@ reboot(Config) when is_list(Config) ->
%% This test exhausts the atom table on the remote node.
%% ERL_CRASH_DUMP_SECONDS=0 will force beam not to dump an erl_crash.dump.
%% May currently dump core in beam debug build due to lock-order violation
-%% This should be removed when a non-lockad information retriever is implemented
+%% This should be removed when a non-locked information retriever is implemented
%% for crash dumps
node_start_immediately_after_crash(Config) when is_list(Config) ->
- Config2 = ignore_cores:setup(?MODULE, node_start_immediately_after_crash, Config, true),
+ Config2 = ignore_cores:setup(?MODULE, ?FUNCTION_NAME, Config, true),
try
- node_start_immediately_after_crash_test(Config2)
+ node_start_immediately_after_crash_test(Config2)
after
- ignore_cores:restore(Config2)
+ ignore_cores:restore(Config2)
end.
-
node_start_immediately_after_crash_test(Config) when is_list(Config) ->
- {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME,
- [{"ERL_CRASH_DUMP_SECONDS", "0"}]),
+ {ok, _Peer, Node} = ?CT_PEER(#{connection => standard_io,
+ args => heart_args() ++ ["-env", "ERL_CRASH_DUMP_SECONDS", "0"]}),
+ heart_monitor(Node),
ok = rpc:call(Node, heart, set_cmd,
- [ct:get_progname() ++
- " -noshell -heart " ++ name(Node) ++ "&"]),
-
- Mod = exhaust_atoms,
-
- Code = generate(Mod, [], [
- "do() -> "
- " Set = lists:seq($a,$z), "
- " [ list_to_atom([A,B,C,D,E]) || "
- " A <- Set, B <- Set, C <- Set, E <- Set, D <- Set ]."
- ]),
+ [ct:get_progname() ++ " -noshell -heart " ++ name(Node) ++ "&"]),
%% crash it with atom exhaustion
- rpc:call(Node, erlang, load_module, [Mod, Code]),
- rpc:cast(Node, Mod, do, []),
+ rpc:cast(Node, ?MODULE, exhaust_atoms, []),
- T0 = now(),
-
- receive {nodedown, Node} ->
- io:format("Took ~.2f s. for node to go down~n", [timer:now_diff(now(), T0)/1000000]),
- ok
+ T0 = erlang:monotonic_time(),
+ receive
+ {nodedown, Node} ->
+ Msec = erlang:convert_time_unit(erlang:monotonic_time() - T0, native, millisecond),
+ io:format("Took ~.2f s. for node to go down~n", [Msec / 1000]),
+ ok
%% timeout is very liberal here. nodedown is received in about 1 s. on linux (palantir)
%% and in about 10 s. on solaris (carcharoth)
- after (15000*test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed)
+ after (15000 * test_server:timetrap_scale_factor()) ->
+ ct:fail(node_not_closed)
end,
timer:sleep(3000),
- node_check_up_down(Node, 2000),
- loose_node:stop(Node).
+ node_check_up_down(Node, 2000).
%% node_start_soon_after_crash
%% Purpose:
@@ -238,63 +195,49 @@ node_start_immediately_after_crash_test(Config) when is_list(Config) ->
%% This test exhausts the atom table on the remote node.
%% ERL_CRASH_DUMP_SECONDS=10 will force beam
%% to only dump an erl_crash.dump for 10 seconds.
-%% May currently dump core in beam debug build due to lock-order violation
-%% This should be removed when a non-lockad information retriever is implemented
-%% for crash dumps
node_start_soon_after_crash(Config) when is_list(Config) ->
- Config2 = ignore_cores:setup(?MODULE, node_start_soon_after_crash, Config, true),
+ Config2 = ignore_cores:setup(?MODULE, ?FUNCTION_NAME, Config, true),
try
- node_start_soon_after_crash_test(Config2)
+ node_start_soon_after_crash_test(Config2)
after
- ignore_cores:restore(Config2)
+ ignore_cores:restore(Config2)
end.
-
+
node_start_soon_after_crash_test(Config) when is_list(Config) ->
- {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME,
- [{"ERL_CRASH_DUMP_SECONDS", "10"}]),
+ {ok, _Peer, Node} = ?CT_PEER(#{connection => standard_io,
+ args => heart_args() ++ ["-env", "ERL_CRASH_DUMP_SECONDS", "10"]}),
+ heart_monitor(Node),
ok = rpc:call(Node, heart, set_cmd,
- [ct:get_progname() ++
- " -noshell -heart " ++ name(Node) ++ "&"]),
+ [ct:get_progname() ++ " -noshell -heart " ++ name(Node) ++ "&"]),
- Mod = exhaust_atoms,
-
- Code = generate(Mod, [], [
- "do() -> "
- " Set = lists:seq($a,$z), "
- " [ list_to_atom([A,B,C,D,E]) || "
- " A <- Set, B <- Set, C <- Set, E <- Set, D <- Set ]."
- ]),
-
- %% crash it with atom exhaustion
- rpc:call(Node, erlang, load_module, [Mod, Code]),
- rpc:cast(Node, Mod, do, []),
+ rpc:cast(Node, ?MODULE, exhaust_atoms, []),
receive {nodedown, Node} -> ok
- after (15000*test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed)
+ after (15000 * test_server:timetrap_scale_factor()) -> ct:fail(node_not_closed)
end,
timer:sleep(20000),
- node_check_up_down(Node, 15000),
- loose_node:stop(Node).
+ node_check_up_down(Node, 15000).
node_check_up_down(Node, Tmo) ->
case net_adm:ping(Node) of
- pong ->
- erlang:monitor_node(Node, true),
- rpc:call(Node, init, reboot, []),
- receive
- {nodedown, Node} -> ok
- after Tmo ->
- ct:fail(node_not_closed2)
- end;
- _ ->
- ct:fail(node_not_rebooted)
+ pong ->
+ erlang:monitor_node(Node, true),
+ rpc:call(Node, init, reboot, []),
+ receive
+ {nodedown, Node} -> ok
+ after Tmo ->
+ ct:fail(node_not_closed2)
+ end;
+ _ ->
+ ct:fail(node_not_rebooted)
end.
%% Only tests bad command, correct behaviour is tested in reboot/1.
set_cmd(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
+ {ok, Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
Cmd = wrong_atom,
{error, {bad_cmd, Cmd}} = rpc:call(Node, heart, set_cmd, [Cmd]),
Cmd1 = lists:duplicate(2047, $a),
@@ -303,49 +246,51 @@ set_cmd(Config) when is_list(Config) ->
ok = rpc:call(Node, heart, set_cmd, [Cmd2]),
Cmd3 = lists:duplicate(2000, $a),
ok = rpc:call(Node, heart, set_cmd, [Cmd3]),
- stop_node(Node),
+ peer:stop(Peer),
ok.
clear_cmd(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
+ {ok, _Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
ok = rpc:call(Node, heart, set_cmd,
- [ct:get_progname() ++
- " -noshell -heart " ++ name(Node) ++ "&"]),
+ [ct:get_progname() ++
+ " -noshell -heart " ++ name(Node) ++ "&"]),
rpc:call(Node, init, reboot, []),
receive
- {nodedown, Node} ->
- ok
+ {nodedown, Node} ->
+ ok
after 2000 ->
- ct:fail(node_not_closed)
+ ct:fail(node_not_closed)
end,
timer:sleep(5000),
case net_adm:ping(Node) of
- pong ->
- erlang:monitor_node(Node, true);
- _ ->
- ct:fail(node_not_rebooted)
+ pong ->
+ erlang:monitor_node(Node, true);
+ _ ->
+ ct:fail(node_not_rebooted)
end,
ok = rpc:call(Node, heart, set_cmd,
- ["erl -noshell -heart " ++ name(Node) ++ "&"]),
+ ["erl -noshell -heart " ++ name(Node) ++ "&"]),
ok = rpc:call(Node, heart, clear_cmd, []),
rpc:call(Node, init, reboot, []),
receive
- {nodedown, Node} ->
- ok
+ {nodedown, Node} ->
+ ok
after 2000 ->
- ct:fail(node_not_closed)
+ ct:fail(node_not_closed)
end,
timer:sleep(5000),
case net_adm:ping(Node) of
- pang ->
- ok;
- _ ->
- ct:fail(node_rebooted)
+ pang ->
+ ok;
+ _ ->
+ ct:fail(node_rebooted)
end,
ok.
get_cmd(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
+ {ok, Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
ShortCmd = "test",
ok = rpc:call(Node, heart, set_cmd, [ShortCmd]),
@@ -356,11 +301,12 @@ get_cmd(Config) when is_list(Config) ->
ok = rpc:call(Node, heart, set_cmd, [LongCmd]),
{ok, LongCmd} = rpc:call(Node, heart, get_cmd, []),
- stop_node(Node),
+ peer:stop(Peer),
ok.
callback_api(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
+ {ok, _Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
none = rpc:call(Node, heart, get_callback, []),
M0 = self(),
F0 = ok,
@@ -390,11 +336,11 @@ callback_api(Config) when is_list(Config) ->
receive {nodedown, Node} -> ok
after 5000 -> ct:fail(node_not_killed)
end,
- stop_node(Node),
ok.
options_api(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
+ {ok, Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
none = rpc:call(Node, heart, get_options, []),
M0 = self(),
F0 = ok,
@@ -418,7 +364,7 @@ options_api(Config) when is_list(Config) ->
ok = rpc:call(Node, heart, set_options, [[]]),
none = rpc:call(Node, heart, get_options, []),
- stop_node(Node),
+ peer:stop(Peer),
ok.
@@ -447,11 +393,14 @@ do_dont_drop(Config,N) ->
FirstCmd = erl() ++ name(NN2 ++ "@" ++ Host),
%% Separated the parameters to start_node_run for clarity...
Name = list_to_atom(NN1),
- Env = [{"HEART_COMMAND", FirstCmd}],
- Func = "start_heart_stress",
- Arg = NN3 ++ "@" ++ Host ++ " " ++
- filename:join(proplists:get_value(data_dir, Config), "simple_echo"),
- start_node_run(Name,Env,Func,Arg),
+ EchoPath = filename:join(proplists:get_value(data_dir, Config), "simple_echo"),
+ Peer3Name = list_to_atom(NN3 ++ "@" ++ Host),
+ %%
+ PA = filename:dirname(code:which(?MODULE)),
+ Params = ["-heart", "-pa", PA, "-env", "HEART_COMMAND", FirstCmd],
+ {ok, Peer, _Node} = ?CT_PEER(#{name => Name, args => Params}),
+ peer:call(Peer, ?MODULE, start_heart_stress, [Peer3Name, EchoPath]),
+ %%
case wait_for_any_of(list_to_atom(NN2 ++ "@" ++ Host),
list_to_atom(NN3 ++ "@" ++ Host)) of
2 ->
@@ -483,53 +432,32 @@ wait_for_any_of(N1,N2,Times) ->
end.
-%% Tests that heart kills the old erlang node before executing
-%% heart command.
-kill_pid(Config) when is_list(Config) ->
- ok = do_kill_pid(Config).
+kill_pid() ->
+ [{doc, "Tests that heart kills the old erlang node before executing heart command."}].
-do_kill_pid(_Config) ->
- Name = ?UNIQ_NODE_NAME,
- Env = [{"HEART_COMMAND", "nickeNyfikenFarEttJobb"}],
- {ok,Node} = start_node_run(Name,Env,suicide_by_heart,[]),
- ok = wait_for_node(Node,15),
+kill_pid(Config) when is_list(Config) ->
+ {ok, _Peer, Node} = ?CT_PEER(heart_args() ++ ["-env", "HEART_COMMAND", "nickeNyfikenFarEttJobb"]),
+ heart_monitor(Node),
+ true = rpc:cast(Node, ?MODULE, suicide_by_heart, []),
erlang:monitor_node(Node, true),
- receive {nodedown,Node} -> ok
+ receive {nodedown, Node} -> ok
after 30000 ->
- false
+ ct:fail(heart_did_not_kill_old_node)
end.
-heart_no_kill(suite) ->
- [];
-heart_no_kill(doc) ->
- ["Tests that heart doesn't kill the old erlang node when ",
- "HEART_NO_KILL is set."];
+heart_no_kill() ->
+ [{doc, "Tests that heart doesn't kill the old erlang node when HEART_NO_KILL is set."}].
+
heart_no_kill(Config) when is_list(Config) ->
- ok = do_no_kill(Config).
-
-do_no_kill(_Config) ->
- Name = heart_test,
- {ok,Node} = start_node_run(Name,[],non_suicide_by_heart,[]),
- io:format("Node is ~p~n", [Node]),
- ok = wait_for_node(Node,15),
- io:format("wait_for_node is ~p~n", [ok]),
- erlang:monitor_node(Node, true),
- receive {nodedown,Node} -> false
+ {ok, Peer, Node} = ?CT_PEER(heart_args()),
+ heart_monitor(Node),
+ true = rpc:cast(Node, ?MODULE, non_suicide_by_heart, []),
+ receive
+ {nodedown, Node} ->
+ ct:fail(heart_killed_old_node)
after 30000 ->
- io:format("Node didn't die..\n"),
- rpc:call(Node,init,stop,[]),
- io:format("done init:stop..\n"),
- ok
- end.
-
-wait_for_node(_,0) ->
- false;
-wait_for_node(Node,N) ->
- receive after 1000 -> ok end,
- case net_adm:ping(Node) of
- pong -> ok;
- pang -> wait_for_node(Node,N-1)
+ peer:stop(Peer)
end.
erl() ->
@@ -537,133 +465,105 @@ erl() ->
{win32,_} -> "werl ";
_ -> "erl "
end.
-
-name(Node) when is_list(Node) -> name(Node,[]);
-name(Node) when is_atom(Node) -> name(atom_to_list(Node),[]).
-name([$@|Node], Name) ->
+name(Node) when is_list(Node) -> name(Node, []);
+name(Node) when is_atom(Node) -> name(atom_to_list(Node), []).
+
+name([$@ | Node], Name) ->
case lists:member($., Node) of
- true ->
- "-name " ++ lists:reverse(Name);
- _ ->
- "-sname " ++ lists:reverse(Name)
+ true ->
+ "-name " ++ lists:reverse(Name);
+ _ ->
+ "-sname " ++ lists:reverse(Name)
end;
-name([H|T], Name) ->
- name(T, [H|Name]).
-
-
-enc(A) when is_atom(A) -> atom_to_list(A);
-enc(A) when is_binary(A) -> binary_to_list(A);
-enc(A) when is_list(A) -> A.
-
-env_encode([]) -> [];
-env_encode([{X,Y}|T]) ->
- "-env " ++ enc(X) ++ " \"" ++ enc(Y) ++ "\" " ++ env_encode(T).
-
-%%%
-%%% Starts a node and runs a function in this
-%%% module.
-%%% Name is the node name as either atom or string,
-%%% Env is a list of Tuples containing name-value pairs.
-%%% Function is the function to run in this module
-%%% Argument is the argument(s) to send through erl -s
-%%%
-start_node_run(Name, Env, Function, Argument) ->
- PA = filename:dirname(code:which(?MODULE)),
- Params = "-heart " ++ env_encode(Env) ++ " -pa " ++ PA ++
- " -s " ++
- enc(?MODULE) ++ " " ++ enc(Function) ++ " " ++
- enc(Argument),
- start_node(Name, Params).
-
-start_node(Name, Param) ->
- test_server:start_node(Name, slave, [{args, Param}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
+name([H | T], Name) ->
+ name(T, [H | Name]).
-%%% This code is run in a slave node to ensure that
-%%% A heart command really gets set syncronously
+%%% This code is run in a peer node to ensure that
+%%% A heart command really gets set synchronously
%%% and cannot get "dropped".
-send_to(_,_,0) ->
+send_to(_, _, 0) ->
ok;
-send_to(Port,D,N) ->
- Port ! {self(),{command,D}},
- send_to(Port,D,N-1).
+send_to(Port, D, N) ->
+ Port ! {self(), {command, D}},
+ send_to(Port, D, N - 1).
-receive_from(_,_,0) ->
+receive_from(_, _, 0) ->
ok;
-receive_from(Port,D,N) ->
+receive_from(Port, D, N) ->
receive
- {Port, {data,{eol,_Data}}} ->
- receive_from(Port,D,N-1);
- X ->
- io:format("Got garbage ~p~n",[X])
+ {Port, {data, {eol, _Data}}} ->
+ receive_from(Port, D, N - 1);
+ X ->
+ io:format("Got garbage ~p~n", [X])
end.
mangle(PP) when is_list(PP) ->
- Port = open_port({spawn,PP},[{line,100}]),
+ Port = open_port({spawn, PP}, [{line, 100}]),
mangle(Port);
mangle(Port) ->
- send_to(Port, "ABCDEFGHIJ" ++ io_lib:nl(),1),
- receive_from(Port,"ABCDEFGHIJ",1),
+ send_to(Port, "ABCDEFGHIJ" ++ io_lib:nl(), 1),
+ receive_from(Port, "ABCDEFGHIJ", 1),
mangle(Port).
-explode(0,_) ->
+explode(0, _) ->
ok;
-explode(N,PP) ->
- spawn(?MODULE,mangle,[PP]),
- explode(N-1,PP).
+explode(N, PP) ->
+ spawn(?MODULE, mangle, [PP]),
+ explode(N - 1, PP).
-start_heart_stress([NewName,PortProgram]) ->
- explode(10,atom_to_list(PortProgram)),
- NewCmd = erl() ++ name(NewName),
+start_heart_stress([NewName, PortProgram]) ->
+ explode(10, atom_to_list(PortProgram)),
+ NewCmd = erl() ++ name(NewName),
%%io:format("~p~n",[NewCmd]),
receive
after 10000 ->
- heart:set_cmd(NewCmd),
- halt()
+ heart:set_cmd(NewCmd),
+ halt()
end.
suicide_by_heart() ->
%%io:format("Suicide starting...~n"),
- open_port({spawn,"heart -ht 11 -pid "++os:getpid()},[{packet,2}]),
+ open_port({spawn, "heart -ht 11 -pid " ++ os:getpid()}, [{packet, 2}]),
receive X -> X end,
%% Just hang and wait for heart to timeout
receive
- {makaronipudding} ->
- sallad
+ {makaronipudding} ->
+ sallad
end.
non_suicide_by_heart() ->
- P = open_port({spawn,"heart -ht 11 -pid "++os:getpid()},
- [exit_status, {env, [{"HEART_NO_KILL", "TRUE"}]},
- {packet,2}]),
+ P = open_port({spawn, "heart -ht 11 -pid " ++ os:getpid()},
+ [exit_status, {env, [{"HEART_NO_KILL", "TRUE"}]},
+ {packet, 2}]),
receive X -> X end,
%% Just hang and wait for heart to timeout
receive
- {P,{exit_status,_}} ->
- ok
+ {P, {exit_status, _}} ->
+ ok
after
- 20000 ->
- exit(timeout)
+ 20000 ->
+ exit(timeout)
end.
+exhaust_atoms() ->
+ Set = lists:seq($a,$z),
+ [list_to_atom([A,B,C,D,E]) || A <- Set, B <- Set, C <- Set, E <- Set, D <- Set].
%% generate a module from binary
generate(Module, Attributes, FunStrings) ->
FunForms = function_forms(FunStrings),
- Forms = [
- {attribute,a(1),module,Module},
- {attribute,a(2),export,[FA || {FA,_} <- FunForms]}
- ] ++ [{attribute, a(3), A, V}|| {A, V} <- Attributes] ++
- [ Function || {_, Function} <- FunForms],
+ Forms = [
+ {attribute, a(1), module, Module},
+ {attribute, a(2), export, [FA || {FA, _} <- FunForms]}
+ ] ++ [{attribute, a(3), A, V} || {A, V} <- Attributes] ++
+ [Function || {_, Function} <- FunForms],
{ok, Module, Bin} = compile:forms(Forms),
Bin.
@@ -671,9 +571,9 @@ a(L) ->
erl_anno:new(L).
function_forms([]) -> [];
-function_forms([S|Ss]) ->
- {ok, Ts,_} = erl_scan:string(S),
+function_forms([S | Ss]) ->
+ {ok, Ts, _} = erl_scan:string(S),
{ok, Form} = erl_parse:parse_form(Ts),
- Fun = element(3, Form),
+ Fun = element(3, Form),
Arity = element(4, Form),
- [{{Fun,Arity}, Form}|function_forms(Ss)].
+ [{{Fun, Arity}, Form} | function_forms(Ss)].
diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl
index fde65bf5c4..1f223df914 100644
--- a/lib/kernel/test/ignore_cores.erl
+++ b/lib/kernel/test/ignore_cores.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,7 +94,7 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
end,
ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>),
%% cores are dumped in /cores on MacOS X
- CoresDir = case {test_server:os_type(), filelib:is_dir("/cores")} of
+ CoresDir = case {os:type(), filelib:is_dir("/cores")} of
{{unix,darwin}, true} ->
filelib:fold_files("/cores",
"^core.*$",
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index cf3ff47325..6298130a09 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@
lookup_bad_search_option/1,
getif/1,
getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1,
+ is_ip_address/1,
parse_strict_address/1, ipv4_mapped_ipv6_address/1, ntoa/1,
simple_netns/1, simple_netns_open/1,
add_del_host/1, add_del_host_v6/1,
@@ -71,7 +72,7 @@ all() ->
[
t_gethostbyaddr, t_gethostbyname, t_getaddr,
t_gethostbyaddr_v6, t_gethostbyname_v6, t_getaddr_v6,
- ipv4_to_ipv6, host_and_addr, {group, parse},
+ ipv4_to_ipv6, host_and_addr, is_ip_address, {group, parse},
t_gethostnative, gethostnative_parallell, cname_loop,
missing_hosts_reload, hosts_file_quirks,
gethostnative_debug_level, gethostnative_soft_restart,
@@ -103,7 +104,7 @@ socknames_cases() ->
socknames_udp
].
-%% Required configuaration
+%% Required configuration
required(v4) ->
[{require, test_host_ipv4_only},
{require, test_dummy_host}];
@@ -521,7 +522,7 @@ ipv4_to_ipv6(Config) when is_list(Config) ->
%% Test looking up hosts and addresses. Use 'ypcat hosts'
-%% or the local eqivalent to find all hosts.
+%% or the local equivalent to find all hosts.
host_and_addr() ->
?P("host_and_addr -> entry"),
@@ -795,18 +796,18 @@ parse_address(Config) when is_list(Config) ->
t_parse_address(Func, _Reversable, []) ->
io:format("~p done.~n", [Func]),
ok;
-t_parse_address(Func, Reversable, [{Addr,String}|L]) ->
+t_parse_address(Func, Reversible, [{Addr,String}|L]) ->
io:format("~p = ~p.~n", [Addr,String]),
{ok,Addr} = inet:Func(String),
- case Reversable of
+ case Reversible of
true ->String = inet:ntoa(Addr);
false -> ok
end,
- t_parse_address(Func, Reversable, L);
-t_parse_address(Func, Reversable, [String|L]) ->
+ t_parse_address(Func, Reversible, L);
+t_parse_address(Func, Reversible, [String|L]) ->
io:format("~p.~n", [String]),
{error,einval} = inet:Func(String),
- t_parse_address(Func, Reversable, L).
+ t_parse_address(Func, Reversible, L).
parse_strict_address(Config) when is_list(Config) ->
{ok, {127,0,0,1}} =
@@ -816,6 +817,63 @@ parse_strict_address(Config) when is_list(Config) ->
{ok, {3089,3106,23603,50240,0,0,119,136}} =
inet:parse_strict_address("c11:0c22:5c33:c440::077:0088").
+is_ip_address(Config) when is_list(Config) ->
+ IPv4Addresses = [
+ {0, 0, 0, 0},
+ {255, 255, 255, 255}
+ ],
+ IPv6Addresses = [
+ {0, 0, 0, 0, 0, 0, 0, 0},
+ {16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff}
+ ],
+ NonIPAddresses = [
+ foo,
+ "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, 0, 0, 0, 0, 0},
+ {0, 0, 0, foo},
+ {0, 0, 0, 0, 0, 0, 0, foo},
+ {0, 0, 0, 256},
+ {0, 0, 256, 0},
+ {0, 256, 0, 0},
+ {256, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 16#10000},
+ {0, 0, 0, 0, 0, 0, 16#10000, 0},
+ {0, 0, 0, 0, 0, 16#10000, 0, 0},
+ {0, 0, 0, 0, 16#10000, 0, 0, 0},
+ {0, 0, 0, 16#10000, 0, 0, 0, 0},
+ {0, 0, 16#10000, 0, 0, 0, 0, 0},
+ {0, 16#10000, 0, 0, 0, 0, 0, 0},
+ {16#10000, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, -1},
+ {0, 0, -1, 0},
+ {0, -1, 0, 0},
+ {-1, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, -1},
+ {0, 0, 0, 0, 0, 0, -1, 0},
+ {0, 0, 0, 0, 0, -1, 0, 0},
+ {0, 0, 0, 0, -1, 0, 0, 0},
+ {0, 0, 0, -1, 0, 0, 0, 0},
+ {0, 0, -1, 0, 0, 0, 0, 0},
+ {0, -1, 0, 0, 0, 0, 0, 0},
+ {-1, 0, 0, 0, 0, 0, 0, 0}
+ ],
+
+ true = lists:all(fun inet:is_ipv4_address/1, IPv4Addresses),
+ false = lists:any(fun inet:is_ipv4_address/1, IPv6Addresses ++ NonIPAddresses),
+
+ true = lists:all(fun inet:is_ipv6_address/1, IPv6Addresses),
+ false = lists:any(fun inet:is_ipv6_address/1, IPv4Addresses ++ NonIPAddresses),
+
+ true = lists:all(fun inet:is_ip_address/1, IPv6Addresses ++ IPv4Addresses),
+ false = lists:any(fun inet:is_ip_address/1, NonIPAddresses).
+
ipv4_mapped_ipv6_address(Config) when is_list(Config) ->
{D1,D2,D3,D4} = IPv4Address =
{rand:uniform(256) - 1,
@@ -907,13 +965,11 @@ gethostnative_parallell(Config) when is_list(Config) ->
end.
do_gethostnative_parallell() ->
- PA = filename:dirname(code:which(?MODULE)),
- {ok,Node} = test_server:start_node(gethost_parallell, slave,
- [{args, "-pa " ++ PA}]),
+ {ok,Peer,Node} = ?CT_PEER(),
ok = rpc:call(Node, ?MODULE, parallell_gethost, []),
receive after 10000 -> ok end,
pong = net_adm:ping(Node),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
parallell_gethost() ->
@@ -1044,9 +1100,7 @@ missing_hosts_reload(Config) when is_list(Config) ->
ok = file:write_file(InetRc, "{hosts_file, \"" ++ HostsFile ++ "\"}.\n"),
{error, enoent} = file:read_file_info(HostsFile),
% start a node
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, TestNode} = test_server:start_node(?MODULE, slave,
- [{args, "-pa " ++ Pa ++ " -kernel inetrc '\"" ++ InetRc ++ "\"'"}]),
+ {ok, Peer, TestNode} = ?CT_PEER(["-kernel", "inetrc", "\"" ++ InetRc ++ "\""]),
% ensure it has our RC
Rc = rpc:call(TestNode, inet_db, get_rc, []),
{hosts_file, HostsFile} = lists:keyfind(hosts_file, 1, Rc),
@@ -1060,7 +1114,7 @@ missing_hosts_reload(Config) when is_list(Config) ->
{ok,{hostent,"somehost",[],inet,4,[{1,2,3,4}]}} =
rpc:call(TestNode, inet_hosts, gethostbyname, ["somehost"]),
% cleanup
- true = test_server:stop_node(TestNode).
+ peer:stop(Peer).
%% The /etc/hosts file format and limitations is quite undocumented.
@@ -1138,9 +1192,7 @@ hosts_file_quirks(Config) when is_list(Config) ->
ok = file:write_file(InetRc, "{hosts_file, \"" ++ HostsFile ++ "\"}.\n"),
%%
%% start a node
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, TestNode} = test_server:start_node(?MODULE, slave,
- [{args, "-pa " ++ Pa ++ " -kernel inetrc '\"" ++ InetRc ++ "\"'"}]),
+ {ok, Peer, TestNode} = ?CT_PEER(["-kernel", "inetrc", "\"" ++ InetRc ++ "\""]),
%% ensure it has our RC
Rc = rpc:call(TestNode, inet_db, get_rc, []),
{hosts_file, HostsFile} = lists:keyfind(hosts_file, 1, Rc),
@@ -1187,7 +1239,7 @@ hosts_file_quirks(Config) when is_list(Config) ->
hosts_file_quirks_verify(TestNode, V1),
%%
%% cleanup
- true = test_server:stop_node(TestNode).
+ peer:stop(Peer).
hosts_file_quirks_verify(_TestNode, Vs) ->
hosts_file_quirks_verify(_TestNode, Vs, true).
@@ -1302,7 +1354,7 @@ gethostnative_control(Config, Opts) ->
{skipped, "Not running native gethostbyname"}
end;
_ ->
- {skipped, "Native not only lookup metod"}
+ {skipped, "Native not only lookup method"}
end.
gethostnative_control_1(
@@ -1916,9 +1968,14 @@ do_socknames_tcp0(_Config) ->
?P("Test socknames for 'new' socket (=socket nif)"),
do_socknames_tcp1([{inet_backend, socket}])
catch
- error : notsup ->
+ error:notsup ->
?P("Skip test of socknames for 'new' socket (=socket nif)"),
- ok
+ ok;
+ error:undef:ST ->
+ case ST of
+ [{prim_socket,info,[],_}|_] ->
+ ?P("Skip test of socknames for 'new' socket (=socket nif)")
+ end
end.
@@ -1995,7 +2052,12 @@ do_socknames_udp0(_Config) ->
catch
error : notsup ->
?P("Skip test of socknames for 'new' socket (=socket nif)"),
- ok
+ ok;
+ error:undef:ST ->
+ case ST of
+ [{prim_socket,info,[],_}|_] ->
+ ?P("Skip test of socknames for 'new' socket (=socket nif)")
+ end
end.
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index 5ac88f2e4a..5adce7156e 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,11 +27,12 @@
-include("kernel_test_lib.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([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1,
+ init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2
]).
--export([basic/1, resolve/1, edns0/1, txt_record/1, files_monitor/1,
+-export([basic/1, name_addr_and_cached/1, resolve/1,
+ edns0/1, txt_record/1, files_monitor/1,
nxdomain_reply/1, last_ms_answer/1, intermediate_error/1,
servfail_retry_timeout_default/1, servfail_retry_timeout_1000/1,
label_compression_limit/1
@@ -71,7 +72,8 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [basic, resolve, edns0, txt_record, files_monitor,
+ [basic, resolve, name_addr_and_cached,
+ edns0, txt_record, files_monitor,
nxdomain_reply, last_ms_answer,
intermediate_error,
servfail_retry_timeout_default, servfail_retry_timeout_1000,
@@ -123,13 +125,14 @@ end_per_group(_GroupName, Config) ->
zone_dir(TC) ->
case TC of
- basic -> otptest;
- resolve -> otptest;
- edns0 -> otptest;
- files_monitor -> otptest;
- nxdomain_reply -> otptest;
- last_ms_answer -> otptest;
- intermediate_error ->
+ basic -> otptest;
+ name_addr_and_cached -> otptest;
+ resolve -> otptest;
+ edns0 -> otptest;
+ files_monitor -> otptest;
+ nxdomain_reply -> otptest;
+ last_ms_answer -> otptest;
+ intermediate_error ->
{internal,
#{rcode => ?REFUSED}};
servfail_retry_timeout_default ->
@@ -171,7 +174,7 @@ init_per_testcase(Func, Config) ->
[{nameserver, NsSpec}, {res_lookup, Lookup} | Config]
catch
SkipReason ->
- ?P("init_per_testcase -> catched:"
+ ?P("init_per_testcase -> caught:"
"~n SkipReason: ~p", [SkipReason]),
{skip, SkipReason}
end.
@@ -511,68 +514,355 @@ basic(Config) when is_list(Config) ->
NS = ns(Config),
Name = "ns.otptest",
NameC = caseflip(Name),
- IP = {127,0,0,254},
+ NameD = NameC ++ ".",
+ IP1 = {127,0,0,253},
+ IP2 = {127,0,0,254},
%%
%% nslookup
{ok,Msg1} = inet_res:nslookup(Name, in, a, [NS]),
?P("nslookup with ~p: ~n ~p", [Name, Msg1]),
- [RR1] = inet_dns:msg(Msg1, anlist),
- IP = inet_dns:rr(RR1, data),
+ [RR1, RR2] = lists:sort(inet_dns:msg(Msg1, anlist)),
+ IP1 = inet_dns:rr(RR1, data),
+ IP2 = inet_dns:rr(RR2, data),
Bin1 = inet_dns:encode(Msg1),
%%io:format("Bin1 = ~w~n", [Bin1]),
{ok,Msg1} = inet_dns:decode(Bin1),
%% Now with scrambled case
{ok,Msg1b} = inet_res:nslookup(NameC, in, a, [NS]),
?P("nslookup with ~p: ~n ~p", [NameC, Msg1b]),
- [RR1b] = inet_dns:msg(Msg1b, anlist),
- IP = inet_dns:rr(RR1b, data),
+ [RR1b, RR2b] = lists:sort(inet_dns:msg(Msg1b, anlist)),
+ IP1 = inet_dns:rr(RR1b, data),
+ IP2 = inet_dns:rr(RR2b, data),
Bin1b = inet_dns:encode(Msg1b),
%%io:format("Bin1b = ~w~n", [Bin1b]),
{ok,Msg1b} = inet_dns:decode(Bin1b),
true =
(tolower(inet_dns:rr(RR1, domain))
=:= tolower(inet_dns:rr(RR1b, domain))),
+ true =
+ (tolower(inet_dns:rr(RR2, domain))
+ =:= tolower(inet_dns:rr(RR2b, domain))),
%%
%% resolve
{ok,Msg2} = inet_res:resolve(Name, in, a, [{nameservers,[NS]},verbose]),
?P("resolve with ~p: ~n ~p", [Name, Msg2]),
- [RR2] = inet_dns:msg(Msg2, anlist),
- IP = inet_dns:rr(RR2, data),
+ [RR1c, RR2c] = lists:sort(inet_dns:msg(Msg2, anlist)),
+ IP1 = inet_dns:rr(RR1c, data),
+ IP2 = inet_dns:rr(RR2c, data),
Bin2 = inet_dns:encode(Msg2),
%%io:format("Bin2 = ~w~n", [Bin2]),
{ok,Msg2} = inet_dns:decode(Bin2),
%% Now with scrambled case
{ok,Msg2b} = inet_res:resolve(NameC, in, a, [{nameservers,[NS]},verbose]),
?P("resolve with ~p: ~n ~p", [NameC, Msg2b]),
- [RR2b] = inet_dns:msg(Msg2b, anlist),
- IP = inet_dns:rr(RR2b, data),
+ [RR1d, RR2d] = lists:sort(inet_dns:msg(Msg2b, anlist)),
+ IP1 = inet_dns:rr(RR1d, data),
+ IP2 = inet_dns:rr(RR2d, data),
Bin2b = inet_dns:encode(Msg2b),
%%io:format("Bin2b = ~w~n", [Bin2b]),
{ok,Msg2b} = inet_dns:decode(Bin2b),
true =
- (tolower(inet_dns:rr(RR2, domain))
- =:= tolower(inet_dns:rr(RR2b, domain))),
+ (tolower(inet_dns:rr(RR1c, domain))
+ =:= tolower(inet_dns:rr(RR1d, domain))),
+ true =
+ (tolower(inet_dns:rr(RR2c, domain))
+ =:= tolower(inet_dns:rr(RR2d, domain))),
+ ?P("resolve \"127.0.0.1\"~n", []),
+ {ok, Msg3} =
+ inet_res:resolve("127.0.0.1", in, a, [{nameservers,[NS]},verbose]),
+ [] = inet_dns:msg(Msg3, anlist),
+ {ok, Msg4} =
+ inet_res:resolve("127.0.0.1", in, ptr, [{nameservers,[NS]},verbose]),
+ [RR4] = inet_dns:msg(Msg4, anlist),
+ "1.0.0.127.in-addr.arpa" = inet_dns:rr(RR4, domain),
+ "test1-78901234567890123456789012345678.otptest" =
+ inet_dns:rr(RR4, data),
%%
%% lookup
?P("lookup"),
- [IP] = inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose]),
- [IP] = inet_res:lookup(NameC, in, a, [{nameservers,[NS]},verbose]),
+ [IP1, IP2] =
+ lists:sort(
+ inet_res:lookup(Name, in, a, [{nameservers,[NS]},verbose])),
+ [IP1, IP2] =
+ lists:sort(
+ inet_res:lookup(NameC, in, a, [{nameservers,[NS]},verbose])),
+ [IP1, IP2] =
+ lists:sort(
+ inet_res:lookup(NameD, in, a, [{nameservers,[NS]},verbose])),
%%
%% gethostbyname
?P("gethostbyname"),
- {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(Name),
- {ok,#hostent{h_addr_list=[IP]}} = inet_res:gethostbyname(NameC),
+ {ok,#hostent{h_addr_list=IPs1}} = inet_res:gethostbyname(Name),
+ [IP1, IP2] = lists:sort(IPs1),
+ {ok,#hostent{h_addr_list=IPs2}} = inet_res:gethostbyname(NameC),
+ [IP1, IP2] = lists:sort(IPs2),
%%
%% getbyname
?P("getbyname"),
- {ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(Name, a),
- {ok,#hostent{h_addr_list=[IP]}} = inet_res:getbyname(NameC, a),
+ {ok,#hostent{h_addr_list=IPs3}} = inet_res:getbyname(Name, a),
+ [IP1, IP2] = lists:sort(IPs3),
+ {ok,#hostent{h_addr_list=IPs4}} = inet_res:getbyname(NameC, a),
+ [IP1, IP2] = lists:sort(IPs4),
?P("end"),
ok.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Check that lookup of names and addresses works the same
+%% also when cached, by simply repeating the lookups
+
+name_addr_and_cached(Config) when is_list(Config) ->
+ ?P("begin"),
+
+%%% dbg:tracer(),
+%%% dbg:p(all, c),
+%%% dbg:tpl(inet_res, do_query, cx),
+
+ NS = ns(Config),
+ Domain = "otptest",
+ Options =
+ [{lookup, [dns]},
+ {resolv_conf, []},
+ {hosts_file, []},
+ {domain, Domain},
+ {nameservers, [NS]},
+ {search, [Domain]},
+ {alt_nameservers, []},
+ {inet6, false},
+ {usevc, false},
+ {edns, 0}],
+ SavedOptions =
+ [{Option, inet_db:res_option(Option)}
+ || {Option, _Value} <- Options],
+ [inet_db:res_option(Option, Value)
+ || {Option, Value} <- Options],
+ try
+ ?P("first pass"),
+ %% Flip character case randomly
+ name_addr(Domain, fun caseflip/1),
+ %%
+ ?P("second pass"),
+ %% Use only character upper case,
+ %% should get identical results from the cache
+ name_addr(Domain, fun toupper/1)
+ after
+ [ok = inet_db:res_option(Option, Value)
+ || {Option, Value} <- SavedOptions]
+ end,
+ ?P("done"),
+ ok.
+
+name_addr(Domain, CFlip) ->
+%% RDomain4 = "0.0.127.in-addr.arpa",
+%% RDomain6 = "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
+ H4 =
+ #hostent{
+ h_addrtype = inet,
+ h_length = 4},
+ H6 =
+ #hostent{
+ h_addrtype = inet6,
+ h_length = 16},
+ H_mx = CFlip("mx"),
+ H_mx_ = CFlip("mx."),
+ IP4_mx = {127,0,0,10},
+ %%
+ H_resolve = CFlip("resolve"),
+ H_resolve_ = CFlip("resolve."),
+ H_cname_resolve = CFlip("cname.resolve"),
+ H_cname_resolve_ = CFlip("cname.resolve."),
+ %%
+ IP4_resolve = {127,0,0,28},
+ IP6_resolve = {0,0,0,0,0,0,127 bsl 8,28},
+ IP64_resolve = {0,0,0,0,0,16#ffff,127 bsl 8,28},
+ %%
+ H_ns = CFlip("ns"),
+ H_ns_ = CFlip("ns."),
+ IP4_ns_1 = {127,0,0,253},
+ IP4_ns_2 = {127,0,0,254},
+ IP6_ns_1 = {0,0,0,0,0,0,127 bsl 8,253},
+ IP6_ns_2 = {0,0,0,0,0,0,127 bsl 8,254},
+ IP64_ns_1 = {0,0,0,0,0,16#ffff,127 bsl 8,253},
+ IP64_ns_2 = {0,0,0,0,0,16#ffff,127 bsl 8,254},
+ Lookups =
+ %% The search list is [Domain] so a lookup of a short
+ %% name should return the fully qualified name with
+ %% Domain appended.
+ %%
+ %% Lookup results should have the same character case
+ %% as the query. Both for short (search) lookups and
+ %% for full name lookups.
+ %%
+ %% Lookup via a CNAME record should return the
+ %% result as stored in DNS but the CNAME should be
+ %% returned as an alias with the query character case
+ %% preserved.
+ %%
+ %% Address lookups (reverse/PTR lookups) can only
+ %% return the one address we looked up and the
+ %% fully qualified name as in DNS, and no aliases.
+ %%
+ %% IPv6 address lookups in ::ffff.A.B.C.D
+ %% (IPv4-compatible IPv6 addresses) should be
+ %% internally done as IPv4 lookups by the client,
+ %% without the caller noticing.
+ %%
+ [{{H_mx, inet}, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = H_mx++[$.|Domain],
+ h_addr_list = [IP4_mx]}},
+ {{H_mx_++Domain, inet}, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = H_mx_++Domain,
+ h_addr_list = [IP4_mx]}},
+ {{H_resolve, inet}, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = H_resolve++[$.|Domain],
+ h_addr_list = [IP4_resolve]}},
+ {{H_resolve_++Domain, inet}, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = H_resolve_++Domain,
+ h_addr_list = [IP4_resolve]}},
+ {{H_cname_resolve, inet}, fun lower_h_name/1, ?LINE,
+ H4#hostent{
+ h_name = "resolve."++Domain,
+ h_aliases = [H_cname_resolve++[$.|Domain]],
+ h_addr_list = [IP4_resolve]}},
+ {{H_cname_resolve_++Domain, inet}, fun lower_h_name/1, ?LINE,
+ H4#hostent{
+ h_name = "resolve."++Domain,
+ h_aliases = [H_cname_resolve_++Domain],
+ h_addr_list = [IP4_resolve]}},
+ %%
+ {{H_ns, inet}, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = H_ns++[$.|Domain],
+ h_addr_list = [IP4_ns_1,IP4_ns_2]}},
+ {{H_ns_++Domain, inet}, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = H_ns_++Domain,
+ h_addr_list = [IP4_ns_1,IP4_ns_2]}},
+ %%
+ {IP4_ns_2, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = "ns."++Domain,
+ h_addr_list = [IP4_ns_2]}},
+ {IP4_ns_1, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = "ns."++Domain,
+ h_addr_list = [IP4_ns_1]}},
+ {IP4_mx, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = "mx."++Domain,
+ h_addr_list = [IP4_mx]}},
+ {IP4_mx, fun norm/1, ?LINE,
+ H4#hostent{
+ h_name = "mx."++Domain,
+ h_addr_list = [IP4_mx]}},
+ %%
+ %%
+ %%
+ {{H_resolve_++Domain, inet6}, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = H_resolve_++Domain,
+ h_addr_list = [IP6_resolve]}},
+ {{H_resolve, inet6}, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = H_resolve++[$.|Domain],
+ h_addr_list = [IP6_resolve]}},
+ {{H_cname_resolve, inet6}, fun lower_h_name/1, ?LINE,
+ H6#hostent{
+ h_name = "resolve."++Domain,
+ h_aliases = [H_cname_resolve++[$.|Domain]],
+ h_addr_list = [IP6_resolve]}},
+ {{H_cname_resolve_++Domain, inet6}, fun lower_h_name/1, ?LINE,
+ H6#hostent{
+ h_name = "resolve."++Domain,
+ h_aliases = [H_cname_resolve_++Domain],
+ h_addr_list = [IP6_resolve]}},
+ {IP6_resolve, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = "resolve."++Domain,
+ h_addr_list = [IP6_resolve]}},
+ {IP64_resolve, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = "resolve."++Domain,
+ h_addr_list = [IP64_resolve]}},
+ %%
+ {{H_ns, inet6}, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = H_ns++[$.|Domain],
+ h_addr_list =
+ [IP6_ns_1,
+ IP6_ns_2]}},
+ {{H_ns_++Domain, inet6}, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = H_ns_++Domain,
+ h_addr_list =
+ [IP6_ns_1,
+ IP6_ns_2]}},
+ {IP6_ns_1, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = "ns."++Domain,
+ h_addr_list = [IP6_ns_1]}},
+ {IP6_ns_2, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = "ns."++Domain,
+ h_addr_list = [IP6_ns_2]}},
+ {IP64_ns_1, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = "ns."++Domain,
+ h_addr_list = [IP64_ns_1]}},
+ {IP64_ns_2, fun norm/1, ?LINE,
+ H6#hostent{
+ h_name = "ns."++Domain,
+ h_addr_list = [IP64_ns_2]}}
+ %%
+ %%
+ %%
+ ],
+ Results =
+ [case Target of
+ {H, T} ->
+ inet_res:gethostbyname(H, T);
+ Addr ->
+ inet_res:gethostbyaddr(Addr)
+ end || {Target, _TFun, _Line, _HE} <- Lookups],
+ ?P("inet_cache: ~p~n", [ets:tab2list(inet_cache)]),
+ [] = merge_results(Lookups, Results),
+ ok.
+
+lower_h_name(#hostent{h_name = HName} = HE) ->
+ norm(HE#hostent{h_name = tolower(HName)}).
+
+%%%lower_h_aliases(#hostent{h_aliases = HAliases} = HE) ->
+%%% HE#hostent{
+%%% h_aliases = [tolower(HAlias) || HAlias <- HAliases]}.
+
+norm(#hostent{h_addr_list = Addrs} = HE) ->
+ HE#hostent{h_addr_list = lists:sort(Addrs)}.
+
+merge_results([], []) ->
+ [];
+merge_results([{H_T, TFun, Line, HE} | Lookups], [Result | Results]) ->
+ case
+ case Result of
+ {ok, ResultHE} ->
+ {ok, TFun(ResultHE)};
+ _ ->
+ Result
+ end
+ of
+ {ok, HE} ->
+ merge_results(Lookups, Results);
+ Other ->
+ [{{Line, H_T, HE}, Other} | merge_results(Lookups, Results)]
+ end.
+
+
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Lookup different records using resolve/2..4.
resolve(Config) when is_list(Config) ->
?P("begin"),
@@ -965,7 +1255,7 @@ last_ms_answer(Config) when is_list(Config) ->
PSpec = proxy_start(last_ms_answer, NS),
ProxyNS = proxy_ns(PSpec),
%%
- %% resolve; whith short timeout to trigger Timeout =:= 0 in inet_res
+ %% resolve; with short timeout to trigger Timeout =:= 0 in inet_res
{error,timeout} =
inet_res:resolve(
Name, in, a, [{nameservers,[ProxyNS]},verbose], Time + 10),
@@ -1128,42 +1418,53 @@ timestamp() ->
erlang:monotonic_time(milli_seconds).
-%% Case flip helper
+%% Case flip helper, randomly flips the case of about every second [a-zA-Z]
+
+-compile({inline, [caseflip/3]}).
-caseflip([C|Cs]) when is_integer(C), $a =< C, C =< $z ->
- [(C - $a + $A)|caseflip_skip(Cs)];
-caseflip([C|Cs]) when is_integer(C), $A =< C, C =< $Z ->
- [(C - $A + $a)|caseflip_skip(Cs)];
-caseflip([C|Cs]) ->
- [C|caseflip(Cs)];
+caseflip([C | Cs]) when is_integer(C), $a =< C, C =< $z ->
+ caseflip(Cs, C, $a - $A);
+caseflip([C | Cs]) when is_integer(C), $A =< C, C =< $Z ->
+ caseflip(Cs, C, $A - $a);
+caseflip([C | Cs]) ->
+ [C | caseflip(Cs)];
caseflip([]) ->
[].
+%%
+caseflip(Cs, C, Diff) ->
+ [case 0.5 =< rand:uniform() of
+ true ->
+ C - Diff;
+ false ->
+ C
+ end | caseflip(Cs)].
-caseflip_skip([C|Cs]) when is_integer(C), $a =< C, C =< $z ->
- [C|caseflip(Cs)];
-caseflip_skip([C|Cs]) when is_integer(C), $A =< C, C =< $Z ->
- [C|caseflip(Cs)];
-caseflip_skip([C|Cs]) ->
- [C|caseflip_skip(Cs)];
-caseflip_skip([]) ->
- [].
-tolower_email([$.|Cs]) ->
- [$.|tolower(Cs)];
-tolower_email([C|Cs]) ->
- [C|tolower_email(Cs)].
+tolower_email([$. | Cs]) ->
+ [$. | tolower(Cs)];
+tolower_email([C | Cs]) ->
+ [C | tolower_email(Cs)].
-%% Case fold to lower case according to RFC 4343
+%% Case fold according to RFC 4343
%%
-tolower([C|Cs]) when is_integer(C) ->
+tolower([C | Cs]) when is_integer(C) ->
if $A =< C, C =< $Z ->
- [(C - $A + $a)|tolower(Cs)];
+ [(C - $A + $a) | tolower(Cs)];
true ->
- [C|tolower(Cs)]
+ [C | tolower(Cs)]
end;
tolower([]) ->
[].
+toupper([C | Cs]) when is_integer(C) ->
+ if $a =< C, C =< $z ->
+ [(C - $a + $A) | toupper(Cs)];
+ true ->
+ [C | toupper(Cs)]
+ end;
+toupper([]) ->
+ [].
+
-compile({inline,[ok/1]}).
ok(ok) -> ok;
ok({ok,X}) -> X;
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone
index 81e14217ba..73812abda9 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone
@@ -10,3 +10,5 @@ $TTL 3600
IN MX 10 mx.otptest.
c.1 IN PTR resolve.otptest.
+d.f IN CNAME e.f
+e.f IN PTR ns.otptest.
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.127.in-addr.arpa.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.127.in-addr.arpa.zone
index bae50a9eec..7a09e4bff8 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.127.in-addr.arpa.zone
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/0.0.127.in-addr.arpa.zone
@@ -24,4 +24,5 @@ $TTL 3600
28 IN PTR resolve.otptest.
+253 IN CNAME 254
254 IN PTR ns.otptest.
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone
index 51268f49ae..9e4a3513f8 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone
@@ -32,6 +32,9 @@ mx6-5678901234567890123456789012345678 IN A 127.0.0.26
mx7-5678901234567890123456789012345678 IN A 127.0.0.27
ns IN A 127.0.0.254
+ns IN AAAA ::127.0.0.254
+ns IN A 127.0.0.253
+ns IN AAAA ::127.0.0.253
resolve IN A 127.0.0.28
resolve IN AAAA ::127.0.0.28
cname.resolve IN CNAME resolve
diff --git a/lib/kernel/test/inet_res_SUITE_data/run-ns b/lib/kernel/test/inet_res_SUITE_data/run-ns
index 36855216f8..2ed7e50f85 100755
--- a/lib/kernel/test/inet_res_SUITE_data/run-ns
+++ b/lib/kernel/test/inet_res_SUITE_data/run-ns
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2009-2020. All Rights Reserved.
+## Copyright Ericsson AB 2009-2022. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
@@ -26,8 +26,7 @@
## $0 IPAddress PortNum SubDir
##
## Helper script to run a very local name server for this test suite,
-## on a given port number, with a configuration
-## customized for the test suite.
+## on a given port number, with a test specific configuration.
##
## * Create a work directory ./SubDir, create a $CONF_FILE there
## that includes $INC_FILE that refers to the zone files.
@@ -35,7 +34,7 @@
## * Zopy zone files and $INC_FILE from `dirname $0`/SubDir to ./SubDir.
## * Start name server in ./SubDir with logging to $LOG_FILE there.
## * Wait for "quit" on stdin.
-## * Terminate named and wait for it.
+## * Terminate name server and wait for it.
##
## Prints status lines starting with tag and colon (think mail header):
## Error: have given up, no name server started
@@ -77,10 +76,8 @@ test -d "$SRCDIR" || \
test -f "$SRCDIR/$INC_FILE" || \
error "Missing file: $SRCDIR/$INC_FILE !"
-# 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.
-NS=named
+# Locate nsd and check version.
+NS=nsd
for n in /usr/sbin/nsd /usr/bin/nsd /usr/local/sbin/nsd /usr/local/bin/nsd
do
test -x "$n" && NS="$n" && break
@@ -109,10 +106,10 @@ cat >"$CONF_FILE" <<CONF_FILE
server:
zonesdir: "$DIR"
port: $2
- database: ""
+ database: "nsd.db"
zonelistfile: "zone.list"
pidfile: "nsd.pid"
- xfrdfile: ""
+ xfrdfile: "xfrd.state"
xfrdir: "$DIR"
username: "$LOGNAME"
verbosity: 2
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 34db4d8080..bc3882b862 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
-module(init_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
@@ -28,15 +29,12 @@
many_restarts/0, many_restarts/1, restart_with_mode/1,
get_plain_arguments/1,
reboot/1, stop_status/1, stop/1, get_status/1, script_id/1,
+ dot_erlang/1,
find_system_processes/0]).
-export([boot1/1, boot2/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
--export([init/1, fini/1]).
-
--define(DEFAULT_TIMEOUT_SEC, 100).
-
%%-----------------------------------------------------------------
%% Test suite for init. (Most code is run during system start/stop.
%% Should be started in a CC view with:
@@ -50,7 +48,7 @@ all() ->
[get_arguments, get_argument, boot_var,
many_restarts, restart_with_mode,
get_plain_arguments, restart, stop_status, get_status, script_id,
- {group, boot}].
+ dot_erlang, {group, boot}].
groups() ->
[{boot, [], [boot1, boot2]}].
@@ -74,27 +72,18 @@ init_per_testcase(_Func, Config) ->
end_per_testcase(_Func, _Config) ->
ok.
-init(Config) when is_list(Config) ->
- Config.
-
-fini(Config) when is_list(Config) ->
- Host = list_to_atom(from($@, atom_to_list(node()))),
- Node = list_to_atom(lists:concat([init_test, "@", Host])),
- stop_node(Node),
- Config.
-
get_arguments(Config) when is_list(Config) ->
Args = args(),
- {ok, Node} = start_node(init_test, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
case rpc:call(Node, init, get_arguments, []) of
Arguments when is_list(Arguments) ->
- stop_node(Node),
+ peer:stop(Peer),
check_a(Arguments),
check_b(Arguments),
check_c(Arguments),
check_d(Arguments);
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail(get_arguments)
end,
ok.
@@ -169,43 +158,43 @@ check_d(Args) ->
get_argument(Config) when is_list(Config) ->
Args = args(),
- {ok, Node} = start_node(init_test, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
case rpc:call(Node, init, get_argument, [b]) of
{ok, [["hej", "hopp"],["san", "sa"]]} ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail({get_argument, b})
end,
case rpc:call(Node, init, get_argument, [a]) of
{ok, [["kalle"]]} ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail({get_argument, a})
end,
case rpc:call(Node, init, get_argument, [c]) of
{ok, [["4", "5", "6"], ["7", "8", "9"]]} ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail({get_argument, c})
end,
case rpc:call(Node, init, get_argument, [d]) of
{ok, [[]]} ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail({get_argument, d})
end,
case rpc:call(Node, init, get_argument, [e]) of
error ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail({get_argument, e})
end,
- stop_node(Node),
+ peer:stop(Peer),
ok.
get_plain_arguments(Config) when is_list(Config) ->
@@ -221,15 +210,15 @@ get_plain_arguments(Config) when is_list(Config) ->
"fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2fjdkfjdkfjfdaa2",
true = (length(Longstring) > 255),
Args = long_args(Longstring),
- {ok, Node} = start_node(init_test, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
case rpc:call(Node, init, get_plain_arguments, []) of
["a", "b", "c", Longstring] ->
ok;
As ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail({get_argument, As})
end,
- stop_node(Node),
+ peer:stop(Peer),
ok.
@@ -241,18 +230,20 @@ boot_var(Config) when is_list(Config) ->
{BootScript, TEST_VAR, KernelVsn, StdlibVsn} = create_boot(Config),
%% Should fail as we have not given -boot_var TEST_VAR
- {error, timeout} =
- start_node(init_test, "-boot " ++ BootScript),
+ try
+ ?CT_PEER(#{args => ["-boot", BootScript], connection => standard_io}),
+ ct:fail({boot_var, "Should not start without TEST_VAR"})
+ catch
+ exit:{boot_failed,{exit_status,1}} ->
+ ok
+ end,
+
case is_real_system(KernelVsn, StdlibVsn) of
true ->
%% Now it should work !!
- {ok, Node} =
- start_node(init_test,
- "-boot " ++ BootScript ++
- " -boot_var TEST_VAR \"" ++
- TEST_VAR ++ "\""),
- stop_node(Node),
+ {ok, Peer, _} = ?CT_PEER(["-boot", BootScript, "-boot_var", "TEST_VAR", TEST_VAR]),
+ peer:stop(Peer),
Res = ok;
_ ->
%% What we need is not so much version numbers on the directories, but
@@ -298,30 +289,30 @@ many_restarts() ->
[{timetrap,{minutes,16}}].
many_restarts(Config) when is_list(Config) ->
- {ok, Node} = loose_node:start(init_test, "", ?DEFAULT_TIMEOUT_SEC),
- loop_restart(50,Node,rpc:call(Node,erlang,whereis,[logger])),
- loose_node:stop(Node),
+ {ok, Peer, Node} = ?CT_PEER(#{connection => standard_io}),
+ loop_restart(50,Peer,Node,rpc:call(Node,erlang,whereis,[logger])),
+ peer:stop(Peer),
ok.
-loop_restart(0,_,_) ->
+loop_restart(0,_,_,_) ->
ok;
-loop_restart(N,Node,EHPid) ->
+loop_restart(N,Peer,Node,EHPid) ->
erlang:monitor_node(Node, true),
ok = rpc:call(Node, init, restart, []),
receive
{nodedown, Node} ->
ok
after 10000 ->
- loose_node:stop(Node),
+ peer:stop(Peer),
ct:fail(not_stopping)
end,
- ok = wait_for(60, Node, EHPid),
- loop_restart(N-1,Node,rpc:call(Node,erlang,whereis,[logger])).
+ ok = wait_for(60, Peer, Node, EHPid),
+ loop_restart(N-1,Peer,Node,rpc:call(Node,erlang,whereis,[logger])).
-wait_for(0,Node,_) ->
- loose_node:stop(Node),
+wait_for(0,Peer,_Node,_) ->
+ peer:stop(Peer),
error;
-wait_for(N,Node,EHPid) ->
+wait_for(N,Peer,Node,EHPid) ->
case rpc:call(Node, erlang, whereis, [logger]) of
Pid when is_pid(Pid), Pid =/= EHPid ->
%% erlang:display(ok),
@@ -345,7 +336,7 @@ wait_for(N,Node,EHPid) ->
after 100 ->
ok
end,
- wait_for(N-1,Node,EHPid)
+ wait_for(N-1,Peer,Node,EHPid)
end.
restart_with_mode(Config) when is_list(Config) ->
@@ -377,13 +368,7 @@ restart_with_mode(Config) when is_list(Config) ->
%% ------------------------------------------------
restart(Config) when is_list(Config) ->
Args = args(),
-
- Pa = " -pa " ++ filename:dirname(code:which(?MODULE)),
-
- %% Currently test_server:start_node cannot be used. The restarted
- %% node immediately halts due to the implementation of
- %% test_server:start_node.
- {ok, Node} = loose_node:start(init_test, Args ++ Pa, ?DEFAULT_TIMEOUT_SEC),
+ {ok, Peer, Node} = ?CT_PEER(#{args => Args, connection => standard_io}),
%% Ok, the node is up, now the real test test begins.
erlang:monitor_node(Node, true),
SysProcs0 = rpc:call(Node, ?MODULE, find_system_processes, []),
@@ -395,14 +380,14 @@ restart(Config) when is_list(Config) ->
InitPid = rpc:call(Node, erlang, whereis, [init]),
PurgerPid = rpc:call(Node, erlang, whereis, [erts_code_purger]),
Procs = rpc:call(Node, erlang, processes, []),
- MsgFlags = lists:sort(rpc:call(Node, socket, supports, [msg_flags])),
+ MsgFlags = fetch_socket_msg_flags(Node),
MaxPid = lists:last(Procs),
ok = rpc:call(Node, init, restart, []),
receive
{nodedown, Node} ->
ok
after 10000 ->
- loose_node:stop(Node),
+ peer:stop(Peer),
ct:fail(not_stopping)
end,
ok = wait_restart(30, Node),
@@ -443,8 +428,13 @@ restart(Config) when is_list(Config) ->
PrimFileP = pid_to_list(PrimFilePid1),
%% and same socket_registry helper process!
- ESockRegP = pid_to_list(ESockRegPid),
- ESockRegP = pid_to_list(ESockRegPid1),
+ if ESockRegPid =:= undefined, ESockRegPid1 =:= undefined ->
+ %% No socket registry on either node
+ ok;
+ true ->
+ ESockRegP = pid_to_list(ESockRegPid),
+ ESockRegP = pid_to_list(ESockRegPid1)
+ end,
NewProcs0 = rpc:call(Node, erlang, processes, []),
NewProcs = NewProcs0 -- SysProcs1,
@@ -452,22 +442,22 @@ restart(Config) when is_list(Config) ->
true ->
ok;
_ ->
- loose_node:stop(Node),
+ peer:stop(Peer),
ct:fail(processes_not_greater)
end,
%% Check that socket tables has been re-initialized; check one
- MsgFlags = lists:sort(rpc:call(Node, socket, supports, [msg_flags])),
+ MsgFlags = fetch_socket_msg_flags(Node),
%% Test that, for instance, the same argument still exists.
case rpc:call(Node, init, get_argument, [c]) of
{ok, [["4", "5", "6"], ["7", "8", "9"]]} ->
ok;
_ ->
- loose_node:stop(Node),
+ peer:stop(Peer),
ct:fail({get_argument, restart_fail})
end,
- loose_node:stop(Node),
+ peer:stop(Peer),
ok.
-record(sys_procs, {init,
@@ -553,6 +543,14 @@ apid(Pid) ->
[N,P,I] = string:tokens(pid_to_list(Pid),"<>."),
[list_to_integer(N),list_to_integer(P),list_to_integer(I)].
+fetch_socket_msg_flags(Node) ->
+ case code:is_loaded(prim_socket) of
+ {file,preloaded} ->
+ lists:sort(rpc:call(Node, socket, supports, [msg_flags]));
+ _ ->
+ ok
+ end.
+
%% ------------------------------------------------
%% Just test that the system is halted here.
%% The reboot facility using heart is tested
@@ -560,14 +558,14 @@ apid(Pid) ->
%% ------------------------------------------------
reboot(Config) when is_list(Config) ->
Args = args(),
- {ok, Node} = start_node(init_test, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
erlang:monitor_node(Node, true),
ok = rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} ->
ok
after 10000 ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail(not_stopping)
end,
ct:sleep(5000),
@@ -575,7 +573,7 @@ reboot(Config) when is_list(Config) ->
pang ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail(system_rebooted)
end,
ok.
@@ -599,14 +597,14 @@ catch_stop(Status) ->
%% ------------------------------------------------
stop(Config) when is_list(Config) ->
Args = args(),
- {ok, Node} = start_node(init_test, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
erlang:monitor_node(Node, true),
ok = rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} ->
ok
after 10000 ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail(not_stopping)
end,
ct:sleep(5000),
@@ -614,7 +612,7 @@ stop(Config) when is_list(Config) ->
pang ->
ok;
_ ->
- stop_node(Node),
+ peer:stop(Peer),
ct:fail(system_rebooted)
end,
ok.
@@ -649,27 +647,74 @@ script_id(Config) when is_list(Config) ->
ok.
%% ------------------------------------------------
+%% Test that .erlang file works as it should
+%% ------------------------------------------------
+dot_erlang(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ TestHome = filename:join(PrivDir, ?FUNCTION_NAME),
+ ok = file:make_dir(TestHome),
+
+ HomeEnv = case os:type() of
+ {win32, _} ->
+ [Drive | Path] = filename:split(TestHome),
+ [{"APPDATA", filename:join(TestHome,"AppData")},
+ {"HOMEDRIVE", Drive}, {"HOMEPATH", filename:join(Path)}];
+ _ ->
+ [{"HOME", TestHome}]
+ end,
+
+ NodeOpts = #{ env => HomeEnv },
+
+ %% Get basedir of peer node
+ {ok, CreatorPeer, CreatorNode} = ?CT_PEER(NodeOpts),
+ UserConfig = erpc:call(CreatorNode, filename, basedir, [user_config,"erlang"]),
+ peer:stop(CreatorPeer),
+
+ XDGErlang = filename:join([UserConfig, ".erlang"]),
+ ok = filelib:ensure_dir(XDGErlang),
+ ok = file:write_file(XDGErlang, "application:set_env(kernel,test,xdg)."),
+
+ {ok, Peer, Node} = ?CT_PEER(NodeOpts),
+
+ ?assertEqual({ok, xdg}, erpc:call(Node, application, get_env, [kernel, test])),
+ peer:stop(Peer),
+
+ HomeErlang = filename:join([TestHome, ".erlang"]),
+ ok = file:write_file(HomeErlang, "application:set_env(kernel,test,home)."),
+ {ok, Peer2, Node2} = ?CT_PEER(NodeOpts),
+
+ ?assertEqual({ok, home}, erpc:call(Node2, application, get_env, [kernel, test])),
+ peer:stop(Peer2),
+
+ ok.
+
+%% ------------------------------------------------
%% Start the slave system with -boot flag.
%% ------------------------------------------------
boot1(Config) when is_list(Config) ->
- Args = args() ++ " -boot start_sasl",
- {ok, Node} = start_node(init_test, Args),
- stop_node(Node),
+ Args = args() ++ ["-boot", "start_sasl"],
+ {ok, Peer, _Node} = ?CT_PEER(Args),
+ peer:stop(Peer),
%% Try to start with non existing boot file.
- Args1 = args() ++ " -boot dummy_script",
- {error, timeout} = start_node(init_test, Args1),
-
- ok.
+ Args1 = args() ++ ["-boot", "dummy_script"],
+ try
+ ?CT_PEER(#{args => Args1, connection => standard_io}),
+ ct:fail({boot1, "started with non existing boot file"})
+ catch
+ exit:{boot_failed, {exit_status, 1}} ->
+ ok
+ end.
boot2(Config) when is_list(Config) ->
%% Absolute boot file name
Boot = filename:join([code:root_dir(), "bin", "start_sasl"]),
- Args = args() ++ " -boot \"" ++ Boot++"\"",
- {ok, Node} = start_node(init_test, Args),
- stop_node(Node),
+ Args = args() ++ ["-boot", Boot],
+ {ok, Peer, _Node} = ?CT_PEER(Args),
+ peer:stop(Peer),
case os:type() of
{win32, _} ->
@@ -679,9 +724,9 @@ boot2(Config) when is_list(Config) ->
($/) -> $\\;
(C) -> C
end, Boot),
- Args2 = args() ++ " -boot \"" ++ Win_boot ++ "\"",
- {ok, Node2} = start_node(init_test, Args2),
- stop_node(Node2);
+ Args2 = args() ++ ["-boot", Win_boot],
+ {ok, Peer2, _Node2} = ?CT_PEER(Args2),
+ peer:stop(Peer2);
_ ->
ok
end,
@@ -690,24 +735,13 @@ boot2(Config) when is_list(Config) ->
%% Misc. functions
-start_node(Name, Param) ->
- test_server:start_node(Name, slave, [{args, Param}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-from(H, [H | T]) -> T;
-from(H, [_ | T]) -> from(H, T);
-from(_, []) -> [].
-
args() ->
- "-a kalle -- a b -d -b hej hopp -- c d -b san sa -c 4 5 6 -c 7 8 9".
+ ["-a", "kalle", "--", "a", "b", "-d", "-b", "hej", "hopp",
+ "--", "c", "d", "-b", "san", "sa", "-c", "4", "5", "6", "-c", "7", "8", "9"].
long_args(A) ->
- lists:flatten(
- io_lib:format("-a kalle -- a b -d -b hej hopp -- c "
- "~s -b san sa -c 4 5 6 -c 7 8 9",
- [A])).
+ ["-a", "kalle", "--", "a", "b", "-d", "-b", "hej", "hopp", "--", "c", A,
+ "-b", "san", "sa", "-c", "4", "5", "6", "-c", "7", "8", "9"].
create_script(Config) ->
PrivDir = proplists:get_value(priv_dir,Config),
diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl
index 2dede6ea03..ec3887df1d 100644
--- a/lib/kernel/test/interactive_shell_SUITE.erl
+++ b/lib/kernel/test/interactive_shell_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,44 +18,39 @@
%% %CopyrightEnd%
%%
-module(interactive_shell_SUITE).
--include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- get_columns_and_rows/1, exit_initial/1, job_control_local/1,
- job_control_remote/1,stop_during_init/1,
+
+-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,
+ get_columns_and_rows/1, exit_initial/1, job_control_local/1,
+ job_control_remote/1,stop_during_init/1,wrap/1,
shell_history/1, shell_history_resize/1, shell_history_eaccess/1,
shell_history_repair/1, shell_history_repair_corrupt/1,
shell_history_corrupt/1,
shell_history_custom/1, shell_history_custom_errors/1,
job_control_remote_noshell/1,ctrl_keys/1,
get_columns_and_rows_escript/1,
- remsh/1, remsh_longnames/1, remsh_no_epmd/1]).
+ remsh_basic/1, remsh_longnames/1, remsh_no_epmd/1]).
--export([init_per_testcase/2, end_per_testcase/2]).
%% For spawn
-export([toerl_server/3]).
%% Exports for custom shell history module
-export([load/0, add/1]).
-init_per_testcase(_Func, Config) ->
- Config.
-
-end_per_testcase(_Func, _Config) ->
- ok.
-
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,3}}].
-all() ->
+all() ->
[get_columns_and_rows_escript,get_columns_and_rows,
exit_initial, job_control_local,
job_control_remote, job_control_remote_noshell,
- ctrl_keys, stop_during_init, {group, shell_history},
- remsh, remsh_longnames, remsh_no_epmd].
+ ctrl_keys, stop_during_init, wrap,
+ {group, shell_history},
+ {group, remsh}].
-groups() ->
+groups() ->
[{shell_history, [],
[shell_history,
shell_history_resize,
@@ -63,32 +58,77 @@ groups() ->
shell_history_repair,
shell_history_repair_corrupt,
shell_history_corrupt,
- shell_history_custom,
- shell_history_custom_errors
- ]}].
+ {group, sh_custom}
+ ]},
+ {sh_custom, [],
+ [shell_history_custom,
+ shell_history_custom_errors]},
+ {remsh, [],
+ [remsh_basic,
+ remsh_longnames,
+ remsh_no_epmd]}
+ ].
init_per_suite(Config) ->
- Term = os:getenv("TERM", "dumb"),
- os:putenv("TERM","vt100"),
- DefShell = get_default_shell(),
- [{default_shell,DefShell},{term,Term}|Config].
+ case get_progs() of
+ {error, Error} ->
+ {skip, Error};
+ _ ->
+ Term = os:getenv("TERM", "dumb"),
+ os:putenv("TERM", "vt100"),
+ DefShell = get_default_shell(),
+ [{default_shell,DefShell},{term,Term}|Config]
+ end.
end_per_suite(Config) ->
Term = proplists:get_value(term,Config),
os:putenv("TERM",Term),
ok.
+init_per_group(remsh, Config) ->
+ case proplists:get_value(default_shell, Config) of
+ old -> {skip, "Not supported in old shell"};
+ new -> Config
+ end;
init_per_group(shell_history, Config) ->
case proplists:get_value(default_shell, Config) of
old -> {skip, "Not supported in old shell"};
new -> Config
end;
+init_per_group(sh_custom, Config) ->
+ %% Ensure that ERL_AFLAGS will not override the value of the
+ %% shell_history variable.
+ Name = interactive_shell_sh_custom,
+ Args = "-noshell -kernel shell_history not_overridden",
+ {ok, Node} = test_server:start_node(Name, slave, [{args,Args}]),
+ try erpc:call(Node, application, get_env, [kernel, shell_history], timeout(normal)) of
+ {ok, not_overridden} ->
+ Config;
+ _ ->
+ SkipText = "shell_history variable is overridden (probably by ERL_AFLAGS)",
+ {skip, SkipText}
+ catch
+ C:R:Stk ->
+ io:format("~p\n~p\n~p\n", [C,R,Stk]),
+ {skip, "Unexpected error"}
+ after
+ test_server:stop_node(Node)
+ end;
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(_Func, Config) ->
+ Config.
+
+end_per_testcase(_Case, _Config) ->
+ %% Terminate any connected nodes. They may disturb test cases that follow.
+ lists:foreach(fun(Node) ->
+ catch erpc:call(Node, erlang, halt, [])
+ end, nodes()),
+ ok.
%%-define(DEBUG,1).
-ifdef(DEBUG).
@@ -153,98 +193,139 @@ get_columns_and_rows_escript(Config) when is_list(Config) ->
%% Test that the shell can access columns and rows.
get_columns_and_rows(Config) when is_list(Config) ->
- case proplists:get_value(default_shell,Config) of
+ case proplists:get_value(default_shell, Config) of
old ->
- %% Old shell tests
- ?dbg(old_shell),
- rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline_re,".*{error,enotsup}"},
- {putline,"io:rows()."},
- {getline_re,".*{error,enotsup}"}
-
- ],[]),
- rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline_re,".*{ok,90}"},
- {putline,"io:rows()."},
- {getline_re,".*{ok,40}"}],
- [],
- "stty rows 40; stty columns 90; ");
+ test_columns_and_rows(old, []);
new ->
- %% New shell tests
- ?dbg(new_shell),
- rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- %% Behaviour change in R12B-5, returns 80
- %% {getline,"{error,enotsup}"},
- {getline,"{ok,80}"},
- {putline,"io:rows()."},
- %% Behaviour change in R12B-5, returns 24
- %% {getline,"{error,enotsup}"}
- {getline,"{ok,24}"}
- ],[]),
- rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"io:columns()."},
- {getline,"{ok,90}"},
- {putline,"io:rows()."},
- {getline,"{ok,40}"}],
- [],
- "stty rows 40; stty columns 90; ")
- end.
-
+ test_columns_and_rows(old, ["-oldshell"]),
+ test_columns_and_rows(new, [])
+ end,
+ ok.
+test_columns_and_rows(old, Args) ->
+ rtnode([{putline, ""},
+ {putline, "2."},
+ {expect, "2\r\n"},
+ {putline, "io:columns()."},
+ {expect, "{error,enotsup}\r\n"},
+ {putline, "io:rows()."},
+ {expect, "{error,enotsup}\r\n"}
+ ], [], [], Args),
+
+ rtnode([{putline, ""},
+ {putline, "2."},
+ {expect, "2\r\n"},
+ {putline, "io:columns()."},
+ {expect, "{ok,90}\r\n"},
+ {putline,"io:rows()."},
+ {expect, "{ok,40}\r\n"}],
+ [],
+ "stty rows 40; stty columns 90; ",
+ Args);
+test_columns_and_rows(new, _Args) ->
+ rtnode([{putline, ""},
+ {expect, "1> $"},
+ {putline, "2."},
+ {expect, "\r\n2\r\n"},
+ {expect, "> $"},
+ {putline, "io:columns()."},
+ {expect, "{ok,80}\r\n"},
+ {expect, "> $"},
+ {putline, "io:rows()."},
+ {expect, "\r\n{ok,24}\r\n"}
+ ]),
+
+ rtnode([{putline, ""},
+ {expect, "1> $"},
+ {putline, "2."},
+ {expect, "\r\n2\r\n"},
+ {expect, "> $"},
+ {putline, "io:columns()."},
+ {expect, "\r\n{ok,90}\r\n"},
+ {expect, "> $"},
+ {putline, "io:rows()."},
+ {expect, "\r\n{ok,40}\r\n"}],
+ [],
+ "stty rows 40; stty columns 90; ").
%% Tests that exit of initial shell restarts shell.
exit_initial(Config) when is_list(Config) ->
- case proplists:get_value(default_shell,Config) of
+ case proplists:get_value(default_shell, Config) of
old ->
- rtnode([{putline,""},
- {putline, "2."},
- {getline_re, ".*2"},
- {putline,"exit()."},
- {getline,""},
- {getline,"Eshell"},
- {putline,""},
- {putline,"35."},
- {getline_re,".*35"}],[]);
- new ->
- rtnode([{putline,""},
- {putline, "2."},
- {getline, "2"},
- {putline,"exit()."},
- {getline,""},
- {getline,"Eshell"},
- {putline,""},
- {putline,"35."},
- {getline_re,"35"}],[])
- end.
+ test_exit_initial(old);
+ new ->
+ test_exit_initial(old),
+ test_exit_initial(new)
+ end,
+ ok.
+
+test_exit_initial(old) ->
+ rtnode([{putline, ""},
+ {putline, "2."},
+ {expect, "2\r\n"},
+ {putline, "exit()."},
+ {expect, "Eshell"},
+ {putline, ""},
+ {putline, "35."},
+ {expect, "35\r\n"}],
+ [], [], ["-oldshell"]);
+test_exit_initial(new) ->
+ rtnode([{putline, ""},
+ {expect, "1> $"},
+ {putline, "2."},
+ {expect, "2"},
+ {putline,"exit()."},
+ {expect, "Eshell"},
+ {expect, "1> $"},
+ {putline, "35."},
+ {expect, "35\r\n"}]).
stop_during_init(Config) when is_list(Config) ->
- case get_progs() of
- {error,_Reason} ->
- {skip,"No runerl present"};
- {RunErl,_ToErl,Erl} ->
- case create_tempdir() of
- {error, Reason2} ->
- {skip, Reason2};
- Tempdir ->
- XArg = " -kernel shell_history enabled -s init stop",
- start_runerl_command(RunErl, Tempdir, "\\\""++Erl++"\\\""++XArg),
- Logs = rtnode_read_logs(Tempdir),
- rtnode_dump_logs(Logs),
- nomatch = binary:match(maps:get("erlang.log.1",Logs),
- <<"*** ERROR: Shell process terminated! ***">>)
- end
- end.
+ {RunErl,_ToErl,Erl} = get_progs(),
+ case create_tempdir() of
+ {error, Reason} ->
+ {skip, Reason};
+ Tempdir ->
+ XArg = " -kernel shell_history enabled -s init stop",
+ start_runerl_command(RunErl, Tempdir, "\\\""++Erl++"\\\""++XArg),
+ Logs = rtnode_read_logs(Tempdir),
+ rtnode_dump_logs(Logs),
+ nomatch = binary:match(map_get("erlang.log.1", Logs),
+ <<"*** ERROR: Shell process terminated! ***">>),
+ ok
+ end.
+
+%% This testcase tests that the correct wrapping characters are added
+%% When a terminal has the xn flag set, it means that wrapping may not
+%% work as expected and historically the ttysl driver has always inserted
+%% a " \b" (i.e. space + backspace) when an output string ends on that line
+%% in order for the cursor to be at col 0 on the next line instead of col max
+%% on the current line.
+%%
+%% This caused problems when a string was `columns` long and then ended in "\r\n"
+%% as it would first wrap due to " \b" and then output "\r\n" that cause a double
+%% newline to happen.
+%%
+%% This testcase tests that we get a " \b" when we should and we get a "\r\n" when
+%% we should.
+wrap(Config) when is_list(Config) ->
+ case proplists:get_value(default_shell, Config) of
+ new ->
+ As = lists:duplicate(20,"a"),
+ rtnode([{putline, "io:columns()."},
+ {expect, "{ok,20}\r\n"},
+ {putline, ["io:format(\"~s\",[lists:duplicate(20,\"a\")])."]},
+ {expect, As ++ " \b"},
+ {putline, ["io:format(\"~s~n~s\",[lists:duplicate(20,\"a\"),lists:duplicate(20,\"a\")])."]},
+ {expect, As ++ "\r\n" ++ As ++ " \b"}
+ ],
+ [],
+ "stty rows 40; stty columns 20; ",
+ [""]);
+ _ ->
+ ok
+ end,
+ ok.
%% This testcase tests that shell_history works as it should.
%% We use Ctrl + P = Cp=[$\^p] in order to navigate up
@@ -257,50 +338,52 @@ shell_history(Config) when is_list(Config) ->
Path = shell_history_path(Config, "basic"),
rtnode([
{putline, "echo1."},
- {getline, "echo1"},
+ {expect, "echo1\r\n"},
{putline, "echo2."},
- {getline, "echo2"},
+ {expect, "echo2\r\n"},
{putline, "echo3."},
- {getline, "echo3"},
+ {expect, "echo3\r\n"},
{putline, "echo4."},
- {getline, "echo4"},
+ {expect, "echo4\r\n"},
{putline, "echo5."},
- {getline, "echo5"}
+ {expect, "echo5\r\n"}
], [], [], " -kernel shell_history enabled " ++
"-kernel shell_history_drop '[\\\"init:stop().\\\"]' " ++
mk_sh_param(Path)),
+ receive after 1000 -> ok end,
rtnode([
{putline, ""},
%% the init:stop that stopped the node is dropped
- {putdata, [$\^p]}, {getdata, "echo5."},
+ {putdata, [$\^p]}, {expect, "echo5[.]$"},
{putdata, [$\n]},
- {getline, "echo5"},
- {putdata, [$\^p]}, {getdata,"echo5."},
- {putdata, [$\^p]}, {getdata,"echo4."},
- {putdata, [$\^p]}, {getdata,"echo3."},
- {putdata, [$\^p]}, {getdata,"echo2."},
- {putdata, [$\^n]}, {getdata,"echo3."},
- {putdata, [$\^n]}, {getdata,"echo4."},
+ {expect, "echo5\r\n"},
+ {putdata, [$\^p]}, {expect, "echo5[.]$"},
+ {putdata, [$\^p]}, {expect, "echo4[.]$"},
+ {putdata, [$\^p]}, {expect, "echo3[.]$"},
+ {putdata, [$\^p]}, {expect, "echo2[.]$"},
+ {putdata, [$\^n]}, {expect, "echo3[.]$"},
+ {putdata, [$\^n]}, {expect, "echo4[.]$"},
{putdata, [$\^b]}, {sleep,50}, %% the echo4. (cursor moved one left)
- {putline, ["echo"]},
- {getline, "echo4echo"}
- ], [], [], " -kernel shell_history enabled " ++ mk_sh_param(Path)).
+ {putline, ["ECHO"]},
+ {expect, "echo4ECHO\r\n"}
+ ], [], [], " -kernel shell_history enabled " ++ mk_sh_param(Path)),
+ ok.
shell_history_resize(Config) ->
Path = shell_history_path(Config, "resize"),
rtnode([
{putline, "echo."},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], " -kernel shell_history_file_bytes 123456 " ++
"-kernel shell_history enabled " ++ mk_sh_param(Path)),
{ok, Logs} =
rtnode([
{putline, ""},
- {putdata, [$\^p]}, {getdata,"init:stop()."},
- {putdata, [$\^p]}, {getdata,"echo."},
+ {putdata, [$\^p]}, {expect, "init:stop\\(\\)[.]$"},
+ {putdata, [$\^p]}, {expect, "echo[.]$"},
{putdata, [$\n]},
- {getline, "echo"}
+ {expect, "echo"}
], [], [], " -kernel shell_history_file_bytes 654321 " ++
"-kernel shell_history enabled " ++ mk_sh_param(Path)),
@@ -324,7 +407,7 @@ shell_history_eaccess(Config) ->
{ok, Logs1} =
rtnode([
{putline, "echo."},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)),
rtnode_check_logs("erlang.log.1", "Error handling file", Logs1),
@@ -332,10 +415,10 @@ shell_history_eaccess(Config) ->
%% shell_docs recursively creates the folder to store the
%% logs. This test checks that erlang still starts if we
%% cannot create the folders to the path.
- {ok, Logs2} =
+ {ok, Logs2} =
rtnode([
{putline, "echo."},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], "-kernel shell_history enabled " ++
mk_sh_param(filename:join(Path,"logs"))),
@@ -343,34 +426,25 @@ shell_history_eaccess(Config) ->
after
file:write_file_info(Path, Info)
- end.
+ end,
+ ok.
shell_history_repair(Config) ->
Path = shell_history_path(Config, "repair"),
%% We stop a node without closing the log
- try rtnode([
- {putline, "echo."},
- {getline, "echo"},
- {sleep, 2500}, %% disk_log internal cache timer is 2000 ms
- {putline, "erlang:halt(0)."}
- ], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)) of
- _ ->
- ok
- catch _:_ ->
- ok
- end,
+ shell_history_halt(Path),
{ok, Logs} =
rtnode([
{putline, ""},
- {putdata, [$\^p]}, {getdata,"echo."},
+ {putdata, [$\^p]}, {expect, "echo[.]$"},
{putdata, [$\n]},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)),
%% The regexp below checks that he string is NOT part of the log
- rtnode_check_logs("erlang.log.1",
+ rtnode_check_logs("erlang.log.1",
"The shell history log file was corrupted and was repaired",
false,
Logs),
@@ -380,17 +454,7 @@ shell_history_repair_corrupt(Config) ->
Path = shell_history_path(Config, "repair_corrupt"),
%% We stop a node without closing the log
- try rtnode([
- {putline, "echo."},
- {getline, "echo"},
- {sleep, 2500}, %% disk_log internal cache timer is 2000 ms
- {putline, "erlang:halt(0)."}
- ], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)) of
- _ ->
- ok
- catch _:_ ->
- ok
- end,
+ shell_history_halt(Path),
%% We corrupt the disklog
{ok, D} = file:open(filename:join(Path,"erlang-shell-log.1"), [read,append]),
@@ -400,12 +464,12 @@ shell_history_repair_corrupt(Config) ->
{ok, Logs} =
rtnode([
{putline, ""},
- {putdata, [$\^p]}, {getdata,"echo."},
+ {putdata, [$\^p]}, {expect, "echo[.]$"},
{putdata, [$\n]},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)),
- rtnode_check_logs("erlang.log.1",
+ rtnode_check_logs("erlang.log.1",
"The shell history log file was corrupted and was repaired.",
Logs),
ok.
@@ -413,18 +477,12 @@ shell_history_repair_corrupt(Config) ->
shell_history_corrupt(Config) ->
Path = shell_history_path(Config, "corrupt"),
- %% We stop a node without closing the log
- try rtnode([
- {putline, "echo."},
- {getline, "echo"}
- ], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)) of
- _ ->
- ok
- catch _:_ ->
- ok
- end,
+ %% We initialize the shell history log with a known value.
+ rtnode([{putline, "echo."},
+ {expect, "echo\r\n"}
+ ], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)),
- %% We corrupt the disklog
+ %% We corrupt the disklog.
{ok, D} = file:open(filename:join(Path,"erlang-shell-log.1"), [read, append]),
ok = file:write(D, [10, 10]),
ok = file:close(D),
@@ -432,16 +490,29 @@ shell_history_corrupt(Config) ->
{ok, Logs} =
rtnode([
{putline, ""},
- {putdata, [$\^p]}, {getdata,"init:stop()."},
- {putdata, [$\^p]}, {getdata,"echo."},
+ {putdata, [$\^p]}, {expect, "init:stop\\(\\)[.]$"},
+ {putdata, [$\^p]}, {expect, "echo[.]$"},
{putdata, [$\n]},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path)),
- rtnode_check_logs("erlang.log.1", "Invalid chunk in the file", Logs),
+ rtnode_check_logs("erlang.log.1", "Invalid chunk in the file", Logs),
ok.
-
+%% Stop the node without closing the log.
+shell_history_halt(Path) ->
+ try
+ rtnode([
+ {putline, "echo."},
+ {expect, "echo\r\n"},
+ {sleep, 2500}, % disk_log internal cache timer is 2000 ms
+ {putline, "halt(0)."}
+ ], [], [], "-kernel shell_history enabled " ++ mk_sh_param(Path))
+ catch
+ _:_ ->
+ ok
+ end.
+
shell_history_path(Config, TestCase) ->
filename:join([proplists:get_value(priv_dir, Config),
"shell_history", TestCase]).
@@ -451,63 +522,66 @@ mk_sh_param(Path) ->
shell_history_custom(_Config) ->
%% Up key: Ctrl + P = Cp=[$\^p]
- rtnode([
- {putline, ""},
- {putdata, [$\^p]}, {getdata,"0."},
+ rtnode([{expect, "1> $"},
+ %% {putline, ""},
+ {putdata, [$\^p]}, {expect, "0[.]"},
{putdata, [$\n]},
- {getline, "0"},
+ {expect, "0\r\n"},
{putline, "echo."},
- {getline, "!echo"} %% exclamation sign is printed by custom history module
+ {expect, "!echo\r\n"} % exclamation mark is printed by custom history module
], [], [], " -kernel shell_history " ++ atom_to_list(?MODULE) ++
- " -pz " ++ filename:dirname(code:which(?MODULE))).
+ " -pz " ++ filename:dirname(code:which(?MODULE))),
+ ok.
shell_history_custom_errors(_Config) ->
%% Check that we can start with a node with an undefined
%% provider module.
- rtnode([
+ rtnode([{expect, "1> $"},
{putline, "echo."},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], " -kernel shell_history very_broken " ++
" -pz " ++ filename:dirname(code:which(?MODULE))),
%% Check that we can start with a node with a provider module
- %% that crashes in load/0
+ %% that crashes in load/0.
rtnode([
{putline, "echo."},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], " -kernel shell_history " ++ atom_to_list(?MODULE) ++
" -kernel provider_load crash" ++
" -pz " ++ filename:dirname(code:which(?MODULE))),
%% Check that we can start with a node with a provider module
- %% that return incorrect in load/0
+ %% that return incorrect in load/0.
rtnode([
{putline, "echo."},
- {getline, "echo"}
+ {expect, "echo\r\n"}
], [], [], " -kernel shell_history " ++ atom_to_list(?MODULE) ++
" -kernel provider_load badreturn" ++
" -pz " ++ filename:dirname(code:which(?MODULE))),
%% Check that we can start with a node with a provider module
- %% that crashes in load/0
+ %% that crashes in load/0.
rtnode([
{putline, "echo."},
- {getline, "Disabling shell history logging."},
- {getline, "echo"}
+ {expect, "Disabling shell history logging.\r\n"},
+ {expect, "echo\r\n"}
], [], [], " -kernel shell_history " ++ atom_to_list(?MODULE) ++
" -kernel provider_add crash" ++
" -pz " ++ filename:dirname(code:which(?MODULE))),
%% Check that we can start with a node with a provider module
- %% that return incorrect in load/0
+ %% that return incorrect in load/0.
rtnode([
{putline, "echo."},
- {getline, "It returned {error,badreturn}."},
- {getline, "echo"}
+ {expect, "It returned {error,badreturn}.\r\n"},
+ {expect, "echo\r\n"}
], [], [], " -kernel shell_history " ++ atom_to_list(?MODULE) ++
" -kernel provider_add badreturn" ++
- " -pz " ++ filename:dirname(code:which(?MODULE))).
+ " -pz " ++ filename:dirname(code:which(?MODULE))),
+
+ ok.
load() ->
case application:get_env(kernel,provider_load) of
@@ -533,298 +607,276 @@ add(_Line) ->
%% Tests that local shell can be started by means of job control.
job_control_local(Config) when is_list(Config) ->
- case proplists:get_value(default_shell,Config) of
+ case proplists:get_value(default_shell, Config) of
old ->
%% Old shell tests
{skip,"No new shell found"};
new ->
%% New shell tests
- rtnode([{putline,""},
+ rtnode([{putline, ""},
+ {expect, "1> $"},
{putline, "2."},
- {getline, "2"},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"s"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {putline_raw,""},
- {getline,"1>"},
- {putline,"35."},
- {getline,"35"}],[])
+ {expect, "\r\n2\r\n"},
+ {putline, "\^g"},
+ {expect, ["--> $"]},
+ {putline, "s"},
+ {expect, ["--> $"]},
+ {putline, "c"},
+ {expect, ["\r\nEshell"]},
+ {expect, ["1> $"]},
+ {putline, "35."},
+ {expect, "\r\n35\r\n2> $"}],
+ []),
+ ok
end.
-job_control_remote(doc) -> [ "Tests that remote shell can be "
- "started by means of job control" ];
+%% Tests that remote shell can be started by means of job control.
job_control_remote(Config) when is_list(Config) ->
- case {node(),proplists:get_value(default_shell,Config)} of
- {nonode@nohost,_} ->
- exit(not_distributed);
- {_,old} ->
+ case proplists:get_value(default_shell, Config) of
+ old ->
{skip,"No new shell found"};
_ ->
- RNode = create_nodename(),
- MyNode = atom2list(node()),
- Pid = spawn_link(fun() ->
- receive die ->
- ok
- end
- end),
- PidStr = pid_to_list(Pid),
- register(kalaskula,Pid),
- CookieString = lists:flatten(
- io_lib:format("~w",
- [erlang:get_cookie()])),
- Res = rtnode([{putline,""},
- {putline, "erlang:get_cookie()."},
- {getline, CookieString},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"r '"++MyNode++"'"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++MyNode++")1>"},
- {putline,"whereis(kalaskula)."},
- {getline,PidStr},
- {sleep,timeout(short)}, % Race, known bug.
- {putline_raw,"exit()."},
- {getline,"***"},
- {putline,[7]},
- {putline,""},
- {getline," -->"},
- {putline,"c 1"},
- {putline,""},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++RNode++")"}],RNode),
- Pid ! die,
- Res
+ NSNode = start_node(?FUNCTION_NAME, []),
+ try
+ test_remote_job_control(NSNode)
+ after
+ test_server:stop_node(NSNode)
+ end
end.
-%% Tests that remote shell can be
-%% started by means of job control to -noshell node.
+%% Tests that remote shell can be started by means of job control to
+%% -noshell node.
job_control_remote_noshell(Config) when is_list(Config) ->
- case {node(),proplists:get_value(default_shell,Config)} of
- {nonode@nohost,_} ->
- exit(not_distributed);
- {_,old} ->
+ case proplists:get_value(default_shell, Config) of
+ old ->
{skip,"No new shell found"};
_ ->
- RNode = create_nodename(),
- NSNode = start_noshell_node(interactive_shell_noshell),
- Pid = spawn_link(NSNode, fun() ->
- receive die ->
- ok
- end
- end),
- PidStr = rpc:call(NSNode,erlang,pid_to_list,[Pid]),
- true = rpc:call(NSNode,erlang,register,[kalaskula,Pid]),
- NSNodeStr = atom2list(NSNode),
- CookieString = lists:flatten(
- io_lib:format("~w",
- [erlang:get_cookie()])),
- Res = rtnode([{putline,""},
- {putline, "erlang:get_cookie()."},
- {getline, CookieString},
- {putline,[7]},
- {sleep,timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"r '"++NSNodeStr++"'"},
- {putline,"c"},
- {putline_raw,""},
- {getline,"Eshell"},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++NSNodeStr++")1>"},
- {putline,"whereis(kalaskula)."},
- {getline,PidStr},
- {sleep,timeout(short)}, % Race, known bug.
- {putline_raw,"exit()."},
- {getline,"***"},
- {putline,[7]},
- {putline,""},
- {getline," -->"},
- {putline,"c 1"},
- {putline,""},
- {sleep,timeout(short)},
- {putline_raw,""},
- {getline,"("++RNode++")"}],RNode),
- Pid ! die,
- stop_noshell_node(NSNode),
- Res
+ NSNode = start_node(?FUNCTION_NAME, ["-noshell"]),
+ try
+ test_remote_job_control(NSNode)
+ after
+ test_server:stop_node(NSNode)
+ end
end.
+test_remote_job_control(Node) ->
+ RemNode = create_nodename(),
+ Pid = spawn_link(Node, fun() ->
+ receive die ->
+ ok
+ end
+ end),
+ PidStr = erpc:call(Node, erlang, pid_to_list, [Pid]),
+ true = erpc:call(Node, erlang, register, [kalaskula,Pid]),
+ PrintedNode = printed_atom(Node),
+ CookieString = printed_atom(erlang:get_cookie()),
+
+ rtnode([{putline, ""},
+ {putline, "erlang:get_cookie()."},
+ {expect, "\r\n\\Q" ++ CookieString ++ "\\E"},
+ {putdata, "\^g"},
+ {expect, " --> $"},
+ {putline, "r " ++ PrintedNode},
+ {expect, "\r\n"},
+ {putline, "c"},
+ {expect, "\r\n"},
+ {expect, "Eshell"},
+ {expect, "\\Q(" ++ atom_to_list(Node) ++")1> \\E$"},
+ {putline, "whereis(kalaskula)."},
+ {expect, PidStr},
+ {putline, "exit()."},
+ {expect, "[*][*][*] Shell process terminated!"},
+ {putdata, "\^g"},
+ {expect, " --> $"},
+ {putline, "c 1"},
+ {expect, "\r\n"},
+ {putline, ""},
+ {expect, "\\Q("++RemNode++")\\E[12]> $"}
+ ], RemNode),
+ Pid ! die,
+ ok.
+
%% Tests various control keys.
-ctrl_keys(_Conf) when is_list(_Conf) ->
- Cu=[$\^u],
- Cw=[$\^w],
- Cy=[$\^y],
- Home=[27,$O,$H],
- End=[27,$O,$F],
+ctrl_keys(_Config) ->
+ Cu = [$\^u],
+ Cw = [$\^w],
+ Cy = [$\^y],
+ Home = [27,$O,$H],
+ End = [27,$O,$F],
rtnode([{putline,""},
{putline,"2."},
- {getline,"2"},
+ {expect,"2"},
{putline,"\"hello "++Cw++"world\"."}, % test <CTRL>+W
- {getline,"\"world\""},
+ {expect,"\"world\""},
{putline,"\"hello "++Cu++"\"world\"."}, % test <CTRL>+U
- {getline,"\"world\""},
+ {expect,"\"world\""},
{putline,"world\"."++Home++"\"hello "}, % test <HOME>
- {getline,"\"hello world\""},
+ {expect,"\"hello world\""},
{putline,"world"++Home++"\"hello "++End++"\"."}, % test <END>
- {getline,"\"hello world\""},
+ {expect,"\"hello world\""},
{putline,"\"hello world\""++Cu++Cy++"."},
- {getline,"\"hello world\""}]
- ++wordLeft()++wordRight(),[]).
-
+ {expect,"\"hello world\""}] ++
+ wordLeft() ++ wordRight(), []),
+ ok.
wordLeft() ->
- L1=[27,27,$[,$D],
- L2=[27]++"[5D",
- L3=[27]++"[1;5D",
- wordLeft(L1)++wordLeft(L2)++wordLeft(L3).
+ L1 = "\e\e[D",
+ L2 = "\e[5D",
+ L3 = "\e[1;5D",
+ wordLeft(L1) ++ wordLeft(L2) ++ wordLeft(L3).
wordLeft(Chars) ->
- End=[27,$O,$F],
+ End = "\eOF",
[{putline,"\"world\""++Chars++"hello "++End++"."},
- {getline,"\"hello world\""}].
+ {expect,"\"hello world\""}].
wordRight() ->
- R1=[27,27,$[,$C],
- R2=[27]++"[5C",
- R3=[27]++"[1;5C",
- wordRight(R1)++wordRight(R2)++wordRight(R3).
+ R1 = "\e\e[C",
+ R2 = "\e[5C",
+ R3 = "\e[1;5C",
+ wordRight(R1) ++ wordRight(R2) ++ wordRight(R3).
wordRight(Chars) ->
- Home=[27,$O,$H],
+ Home = "\eOH",
[{putline,"world"++Home++"\"hello "++Chars++"\"."},
- {getline,"\"hello world\""}].
+ {expect,"\"hello world\""}].
%% Test that -remsh works
-remsh(Config) when is_list(Config) ->
- case proplists:get_value(default_shell,Config) of
- old -> {skip,"Not supported in old shell"};
- new ->
- NodeStr = lists:flatten(io_lib:format("~p",[node()])),
- [_Name,Host] = string:split(atom_to_list(node()),"@"),
- Cmds = [{kill_emulator_command,sigint},
- {putline,""},
- {putline,"node()."},
- {getline,NodeStr}],
+remsh_basic(Config) when is_list(Config) ->
+ TargetNode = start_node(?FUNCTION_NAME, []),
+ TargetNodeStr = printed_atom(TargetNode),
+ [_Name,Host] = string:split(atom_to_list(node()), "@"),
- %% Test that remsh works with explicit -sname
- rtnode(Cmds ++ [{putline,"nodes()."},
- {getline,"['Remshtest@"++Host++"']"}],
- "Remshtest", [], "-remsh " ++ NodeStr),
+ PreCmds = [{putline,""},
+ {putline,"node()."},
+ {expect, "\\Q" ++ TargetNodeStr ++ "\\E\r\n"}],
- %% Test that remsh works without -sname
- rtnode(Cmds, [], [], " -remsh " ++ NodeStr)
+ PostCmds = quit_hosting_node(),
+ %% Test that remsh works with explicit -sname.
+ HostNode = atom_to_list(?FUNCTION_NAME) ++ "_host",
+ HostNodeStr = printed_atom(list_to_atom(HostNode ++ "@" ++ Host)),
+ rtnode(PreCmds ++
+ [{putline,"nodes()."},
+ {expect, "\\Q" ++ HostNodeStr ++ "\\E"}] ++
+ PostCmds,
+ HostNode, [], "-remsh " ++ TargetNodeStr),
- end.
+ %% Test that remsh works without -sname.
+ rtnode(PreCmds ++ PostCmds, [], [], " -remsh " ++ TargetNodeStr),
-%% Test that -remsh works with long names
-remsh_longnames(Config) when is_list(Config) ->
+ test_server:stop_node(TargetNode),
- case proplists:get_value(default_shell,Config) of
- old -> {skip,"Not supported in old shell"};
- new ->
- %% If we cannot resolve the domain, we need to add localhost to the longname
- Domain =
- case inet_db:res_option(domain) of
- [] ->
- "@127.0.0.1";
- _ -> ""
- end,
- case rtstart(" -name " ++ atom_to_list(?FUNCTION_NAME)++Domain) of
- {ok, _SRPid, _STPid, SState} ->
- {ok, _CRPid, CTPid, CState} =
- rtstart("-name undefined" ++ Domain ++
- " -remsh " ++ atom_to_list(?FUNCTION_NAME)),
- try
- ok = get_and_put(
- CTPid,
- [{kill_emulator_command,sigint},
- {putline,""},
- {putline,"node()."},
- {getline_re,atom_to_list(?FUNCTION_NAME)}], 1)
- after
- rtstop(CState), %% Stop client before server
- rtstop(SState)
- end;
- Else ->
- Else
- end
+ ok.
+
+quit_hosting_node() ->
+ %% Command sequence for entering a shell on the hosting node.
+ [{putdata, "\^g"},
+ {expect, "--> $"},
+ {putline, "s"},
+ {expect, "--> $"},
+ {putline, "c"},
+ {expect, ["Eshell"]},
+ {expect, ["1> $"]}].
+
+%% Test that -remsh works with long names.
+remsh_longnames(Config) when is_list(Config) ->
+ %% If we cannot resolve the domain, we need to add localhost to the longname
+ Domain =
+ case inet_db:res_option(domain) of
+ [] ->
+ "@127.0.0.1";
+ _ -> ""
+ end,
+ case rtstart(" -name " ++ atom_to_list(?FUNCTION_NAME)++Domain) of
+ {ok, _SRPid, STPid, SState} ->
+ try
+ {ok, _CRPid, CTPid, CState} =
+ rtstart("-name undefined" ++ Domain ++
+ " -remsh " ++ atom_to_list(?FUNCTION_NAME)),
+ try
+ ok = send_commands(
+ STPid,
+ [{putline, ""},
+ {putline, "node()."},
+ {expect, "\\Q" ++ atom_to_list(?FUNCTION_NAME) ++ "\\E"}], 1),
+ ok = send_commands(
+ CTPid,
+ [{putline, ""},
+ {putline, "node()."},
+ {expect, "\\Q" ++ atom_to_list(?FUNCTION_NAME) ++ "\\E"} | quit_hosting_node()], 1)
+ after
+ rtnode_dump_logs(rtstop(CState))
+ end
+ after
+ rtnode_dump_logs(rtstop(SState))
+ end;
+ Else ->
+ Else
end.
-%% Test that -remsh works without epmd
+%% Test that -remsh works without epmd.
remsh_no_epmd(Config) when is_list(Config) ->
-
- case proplists:get_value(default_shell,Config) of
- old -> {skip,"Not supported in old shell"};
- new ->
- EPMD_ARGS = "-start_epmd false -erl_epmd_port 12345 ",
- case rtstart([],"ERL_EPMD_PORT=12345 ",
- EPMD_ARGS ++ " -sname " ++ atom_to_list(?FUNCTION_NAME)) of
- {ok, _SRPid, STPid, SState} ->
- try
- ok = get_and_put(
- STPid,
- [{putline,""},
- {putline,"node()."},
- {getline_re,atom_to_list(?FUNCTION_NAME)}], 1),
- {ok, _CRPid, CTPid, CState} =
- rtstart([],"ERL_EPMD_PORT=12345 ",
- EPMD_ARGS ++ " -remsh "++atom_to_list(?FUNCTION_NAME)),
- try
- ok = get_and_put(
- CTPid,
- [{kill_emulator_command,sigint},
- {putline,""},
- {putline,"node()."},
- {getline_re,atom_to_list(?FUNCTION_NAME)}], 1)
- after
- rtstop(CState)
- end
- after
- rtstop(SState)
- end;
- Else ->
- Else
- end
+ EPMD_ARGS = "-start_epmd false -erl_epmd_port 12345 ",
+ case rtstart([],"ERL_EPMD_PORT=12345 ",
+ EPMD_ARGS ++ " -sname " ++ atom_to_list(?FUNCTION_NAME)) of
+ {ok, _SRPid, STPid, SState} ->
+ try
+ ok = send_commands(
+ STPid,
+ [{putline, ""},
+ {putline, "node()."},
+ {expect, "\\Q" ++ atom_to_list(?FUNCTION_NAME) ++ "\\E"}], 1),
+ {ok, _CRPid, CTPid, CState} =
+ rtstart([],"ERL_EPMD_PORT=12345 ",
+ EPMD_ARGS ++ " -remsh "++atom_to_list(?FUNCTION_NAME)),
+ try
+ ok = send_commands(
+ CTPid,
+ [{putline, ""},
+ {putline, "node()."},
+ {expect, "\\Q" ++ atom_to_list(?FUNCTION_NAME) ++ "\\E"} | quit_hosting_node()], 1)
+ after
+ rtstop(CState)
+ end
+ after
+ rtstop(SState)
+ end;
+ Else ->
+ Else
end.
-rtnode(C,N) ->
- rtnode(C,N,[]).
-rtnode(Commands,Nodename,ErlPrefix) ->
- rtnode(Commands,Nodename,ErlPrefix,[]).
-rtnode(Commands,Nodename,ErlPrefix,Args) ->
- case rtstart(Nodename,ErlPrefix,Args) of
+rtnode(C) ->
+ rtnode(C, []).
+
+rtnode(C, N) ->
+ rtnode(C, N, []).
+
+rtnode(Commands, Nodename, ErlPrefix) ->
+ rtnode(Commands, Nodename, ErlPrefix, []).
+
+rtnode(Commands, Nodename, ErlPrefix, Args) ->
+ case rtstart(Nodename, ErlPrefix, Args) of
{ok, _SPid, CPid, RTState} ->
- erase(getline_skipped),
- Res = (catch get_and_put(CPid, Commands, 1)),
+ Res = catch send_commands(CPid, Commands, 1),
Logs = rtstop(RTState),
case Res of
ok ->
- {Res, Logs};
- _Else ->
+ rtnode_dump_logs(Logs),
+ ok;
+ _ ->
rtnode_dump_logs(Logs),
ok = Res
- end;
+ end,
+ {ok, Logs};
Skip ->
Skip
end.
rtstart(Args) ->
- rtstart([],[],Args).
-rtstart(Nodename,ErlPrefix,Args) ->
+ rtstart([], [], Args).
+
+rtstart(Nodename, ErlPrefix, Args) ->
case get_progs() of
{error,_Reason} ->
{skip,"No runerl present"};
@@ -844,20 +896,7 @@ rtstart(Nodename,ErlPrefix,Args) ->
rtstop({CPid, SPid, ToErl, Tempdir}) ->
case stop_runerl_node(CPid) of
{error,_} ->
- CPid2 =
- start_toerl_server(ToErl,Tempdir),
- erase(getline_skipped),
- ok = get_and_put
- (CPid2,
- [{putline,[7]},
- {sleep,
- timeout(short)},
- {putline,""},
- {getline," -->"},
- {putline,"s"},
- {putline,"c"},
- {putline,""}],1),
- stop_runerl_node(CPid2);
+ catch rtstop_try_harder(ToErl, Tempdir);
_ ->
ok
end,
@@ -866,6 +905,18 @@ rtstop({CPid, SPid, ToErl, Tempdir}) ->
file:del_dir_r(Tempdir),
Logs.
+rtstop_try_harder(ToErl, Tempdir) ->
+ CPid = start_toerl_server(ToErl, Tempdir),
+ ok = send_commands(CPid,
+ [{putline,[7]},
+ {expect, " --> $"},
+ {putline, "s"},
+ {putline, "c"},
+ {putline, ""}], 1),
+ stop_runerl_node(CPid).
+
+timeout(longest) ->
+ timeout(long) + timeout(normal);
timeout(long) ->
2 * timeout(normal);
timeout(short) ->
@@ -873,154 +924,72 @@ timeout(short) ->
timeout(normal) ->
10000 * test_server:timetrap_scale_factor().
-
-start_noshell_node(Name) ->
- PADir = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(Name,slave,[{args," -noshell -pa "++
- PADir++" "}]),
+start_node(Name, Args0) ->
+ PaDir = filename:dirname(code:which(?MODULE)),
+ Args1 = ["-pa",PaDir|Args0],
+ Args = lists:append(lists:join(" ", Args1)),
+ {ok, Node} = test_server:start_node(Name, slave, [{args,Args}]),
Node.
-stop_noshell_node(Node) ->
- test_server:stop_node(Node).
-get_and_put(_CPid,[],_) ->
- ok;
-get_and_put(CPid, [{sleep, X}|T],N) ->
+send_commands(CPid, [{sleep, X}|T], N) ->
?dbg({sleep, X}),
receive
after X ->
- get_and_put(CPid,T,N+1)
- end;
-get_and_put(CPid, [{kill_emulator_command, Cmd}|T],N) ->
- ?dbg({kill_emulator_command, Cmd}),
- CPid ! {self(), {kill_emulator_command, Cmd}},
- receive
- {kill_emulator_command,_Res} ->
- get_and_put(CPid,T,N)
- end;
-get_and_put(CPid, [{getline, Match}|T],N) ->
- ?dbg({getline, Match}),
- CPid ! {self(), {get_line, timeout(normal)}},
- receive
- {get_line, timeout} ->
- error_logger:error_msg("~p: getline timeout waiting for \"~s\" "
- "(command number ~p, skipped: ~p)~n",
- [?MODULE, Match,N,get(getline_skipped)]),
- {error, timeout};
- {get_line, Data} ->
- ?dbg({data,Data}),
- case lists:prefix(Match, Data) of
- true ->
- erase(getline_skipped),
- get_and_put(CPid, T,N+1);
- false ->
- case get(getline_skipped) of
- undefined ->
- put(getline_skipped,[Data]);
- List ->
- put(getline_skipped,List ++ [Data])
- end,
- get_and_put(CPid, [{getline, Match}|T],N)
- end
+ send_commands(CPid, T, N+1)
end;
-
-%% Hey ho copy paste from stdlib/io_proto_SUITE
-get_and_put(CPid, [{getline_re, Match}|T],N) ->
- ?dbg({getline_re, Match}),
- CPid ! {self(), {get_line, timeout(normal)}},
- receive
- {get_line, timeout} ->
- error_logger:error_msg("~p: getline_re timeout waiting for \"~s\" "
- "(command number ~p, skipped: ~p)~n",
- [?MODULE, Match,N,get(getline_skipped)]),
- {error, timeout};
- {get_line, Data} ->
- ?dbg({data,Data}),
- case re:run(Data, Match,[{capture,none}]) of
- match ->
- erase(getline_skipped),
- get_and_put(CPid, T,N+1);
- _ ->
- case get(getline_skipped) of
- undefined ->
- put(getline_skipped,[Data]);
- List ->
- put(getline_skipped,List ++ [Data])
- end,
- get_and_put(CPid, [{getline_re, Match}|T],N)
- end
- end;
-
-get_and_put(CPid, [{getdata, Match}|T],N) ->
- ?dbg({getdata, Match}),
- CPid ! {self(), {get_data, timeout(normal), Match}},
- receive
- {get_data, timeout} ->
- error_logger:error_msg("~p: getdata timeout waiting for \"~s\" "
- "(command number ~p, skipped: ~p)~n",
- [?MODULE, Match,N,get(getline_skipped)]),
- {error, timeout};
- {get_data, _Data} ->
- ?dbg({CPid,data,_Data}),
- get_and_put(CPid, T, N+1)
+send_commands(CPid, [{expect, Expect}|T], N) when is_list(Expect) ->
+ ?dbg(Exp),
+ case command(CPid, {expect, [Expect], timeout(normal)}) of
+ ok ->
+ send_commands(CPid, T, N + 1);
+ {expect_timeout, Got} ->
+ ct:pal("expect timed out waiting for ~p\ngot: ~p\n", [Expect,Got]),
+ {error, timeout};
+ Other ->
+ Other
end;
-
-get_and_put(CPid, [{putline_raw, Line}|T],N) ->
- ?dbg({putline_raw, Line}),
- CPid ! {self(), {send_line, Line}},
- Timeout = timeout(normal),
- receive
- {send_line, ok} ->
- get_and_put(CPid, T,N+1)
- after Timeout ->
- error_logger:error_msg("~p: putline_raw timeout (~p) sending "
- "\"~s\" (command number ~p)~n",
- [?MODULE, Timeout, Line, N]),
- {error, timeout}
+send_commands(CPid, [{putline, Line}|T], N) ->
+ send_commands(CPid, [{putdata, Line ++ "\n"}|T], N);
+send_commands(CPid, [{putdata, Data}|T], N) ->
+ ?dbg({putdata, Data}),
+ case command(CPid, {send_data, Data}) of
+ ok ->
+ send_commands(CPid, T, N+1);
+ Error ->
+ Error
end;
+send_commands(_CPid, [], _) ->
+ ok.
-get_and_put(CPid, [{putline, Line}|T],N) ->
- ?dbg({putline, Line}),
- CPid ! {self(), {send_line, Line}},
- Timeout = timeout(normal),
- receive
- {send_line, ok} ->
- get_and_put(CPid, [{getline, []}|T],N)
- after Timeout ->
- error_logger:error_msg("~p: putline timeout (~p) sending "
- "\"~s\" (command number ~p)~n[~p]~n",
- [?MODULE, Timeout, Line, N,get()]),
- {error, timeout}
- end;
-get_and_put(CPid, [{putdata, Data}|T],N) ->
- ?dbg({putdata, Data}),
- CPid ! {self(), {send_data, Data}},
- Timeout = timeout(normal),
+command(Pid, Req) ->
+ Timeout = timeout(longest),
+ Ref = erlang:monitor(process, Pid),
+ Pid ! {self(), Ref, Req},
receive
- {send_data, ok} ->
- get_and_put(CPid, T,N+1)
+ {Ref, Reply} ->
+ erlang:demonitor(Ref, [flush]),
+ Reply;
+ {'DOWN', Ref, _, _, Reason} ->
+ {error, Reason}
after Timeout ->
- error_logger:error_msg("~p: putline_raw timeout (~p) sending "
- "\"~s\" (command number ~p)~n",
- [?MODULE, Timeout, Data, N]),
- {error, timeout}
+ io:format("timeout while executing ~p\n", [Req]),
+ {error, timeout}
end.
wait_for_runerl_server(SPid) ->
- Ref = erlang:monitor(process, SPid),
+ Ref = erlang:monitor(process, SPid),
Timeout = timeout(long),
receive
- {'DOWN', Ref, process, SPid, _} ->
+ {'DOWN', Ref, process, SPid, _Reason} ->
ok
after Timeout ->
- {error, timeout}
+ {error, runerl_server_timeout}
end.
-
-
stop_runerl_node(CPid) ->
Ref = erlang:monitor(process, CPid),
CPid ! {self(), kill_emulator},
- Timeout = timeout(long),
+ Timeout = timeout(longest),
receive
{'DOWN', Ref, process, CPid, noproc} ->
ok;
@@ -1029,34 +998,38 @@ stop_runerl_node(CPid) ->
{'DOWN', Ref, process, CPid, {error, Reason}} ->
{error, Reason}
after Timeout ->
- {error, timeout}
+ {error, toerl_server_timeout}
end.
get_progs() ->
+ try
+ do_get_progs()
+ catch
+ throw:Thrown ->
+ {error, Thrown}
+ end.
+
+do_get_progs() ->
case os:type() of
{unix,freebsd} ->
- {error,"cant use run_erl on freebsd"};
+ throw("Can't use run_erl on FreeBSD");
{unix,openbsd} ->
- {error,"cant use run_erl on openbsd"};
+ throw("Can't use run_erl on OpenBSD");
{unix,_} ->
- case os:find_executable("run_erl") of
- RE when is_list(RE) ->
- case os:find_executable("to_erl") of
- TE when is_list(TE) ->
- case os:find_executable("erl") of
- E when is_list(E) ->
- {RE,TE,E};
- _ ->
- {error, "Could not find erl command"}
- end;
- _ ->
- {error, "Could not find to_erl command"}
- end;
- _ ->
- {error, "Could not find run_erl command"}
- end;
+ RunErl = find_executable("run_erl"),
+ ToErl = find_executable("to_erl"),
+ Erl = find_executable("erl"),
+ {RunErl, ToErl, Erl};
_ ->
- {error, "Not a unix OS"}
+ throw("Not a Unix OS")
+ end.
+
+find_executable(Name) ->
+ case os:find_executable(Name) of
+ Prog when is_list(Prog) ->
+ Prog;
+ false ->
+ throw("Could not find " ++ Name)
end.
create_tempdir() ->
@@ -1143,8 +1116,8 @@ try_to_erl(Command, N) ->
Port
end.
-toerl_server(Parent,ToErl,Tempdir) ->
- Port = try_to_erl("\""++ToErl++"\" "++Tempdir++"/ 2>/dev/null", 8),
+toerl_server(Parent, ToErl, TempDir) ->
+ Port = try_to_erl("\""++ToErl++"\" "++TempDir++"/ 2>/dev/null", 8),
case Port of
P when is_port(P) ->
Parent ! {self(),started};
@@ -1152,7 +1125,9 @@ toerl_server(Parent,ToErl,Tempdir) ->
Parent ! {self(),error,Other},
exit(Other)
end,
- case toerl_loop(#{ port => Port}) of
+
+ State = #{port => Port, acc => [], kill_emulator_command => init_stop},
+ case toerl_loop(State) of
normal ->
ok;
{error, Reason} ->
@@ -1161,100 +1136,133 @@ toerl_server(Parent,ToErl,Tempdir) ->
exit(Reason)
end.
-toerl_loop(#{ port := Port } = State0) ->
- ?dbg({toerl_loop, Port, maps:get(acc,State0,[]),
- maps:get(match,State0,nomatch)}),
+toerl_loop(#{port := Port} = State0) ->
+ ?dbg({toerl_loop, Port, map_get(acc, State0),
+ maps:get(match, State0, nomatch)}),
- State = handle_match(State0),
+ State = handle_expect(State0),
receive
{Port,{data,Data}} when is_port(Port) ->
?dbg({?LINE,Port,{data,Data}}),
- toerl_loop(State#{ acc => lists:flatten([maps:get(acc,State,[]),Data])});
- {Pid, {get_data, Timeout, Match}} ->
- toerl_loop(
- State#{ get =>
- #{ match => Match,
- timer => erlang:start_timer(Timeout, self(), timeout),
- tag => get_data,
- from => Pid }
- });
- {Pid, {get_line, Timeout}} ->
- toerl_loop(
- State#{ get =>
- #{ match => "\r\n",
- timer => erlang:start_timer(Timeout, self(), timeout),
- tag => get_line,
- from => Pid }
- });
- {Pid, {send_line, Data7}} ->
- Port ! {self(),{command, Data7++"\n"}},
- Pid ! {send_line, ok},
- toerl_loop(State);
- {Pid, {send_data, Data}} ->
- Port ! {self(),{command, Data}},
- Pid ! {send_data, ok},
- toerl_loop(State);
- {Pid, {kill_emulator_command, Cmd}} ->
- put(kill_emulator_command, Cmd),
- Pid ! {kill_emulator_command, ok},
+ toerl_loop(State#{acc => map_get(acc, State) ++ Data});
+ {Pid, Ref, {expect, Expect, Timeout}} ->
+ toerl_loop(init_expect(Pid, Ref, Expect, Timeout, State));
+ {Pid, Ref, {send_data, Data}} ->
+ Port ! {self(), {command, Data}},
+ Pid ! {Ref, ok},
toerl_loop(State);
{_Pid, kill_emulator} ->
- case get(kill_emulator_command) of
- undefined ->
- Port ! {self(),{command, "init:stop().\n"}};
- sigint ->
- ?dbg({putdata,[$\^c]}),
- Port ! {self(),{command, [$\^c]}},
- receive
- {Port,{data,_Data}} ->
- ?dbg({exit_data, _Data}),
- ok
- after 2000 ->
- ok
- end,
- ?dbg({putdata,"a\n"}),
- Port ! {self(),{command, "a\n"}}
- end,
- Timeout1 = timeout(long),
- receive
- {Port,eof} ->
- normal
- after Timeout1 ->
- {error, kill_timeout}
- end;
- {timeout,Timer,timeout} ->
- #{ get := #{ tag := Tag, from := Pid, timer := Timer } } = State,
- Pid ! {Tag, timeout},
- toerl_loop(maps:remove(get, State));
+ kill_emulator(State);
+ {timeout,Timer,expect_timeout} ->
+ toerl_loop(handle_expect_timeout(Timer, State));
{Port, eof} ->
{error, unexpected_eof};
Other ->
{error, {unexpected, Other}}
end.
-handle_match(#{ acc := Acc, get := #{ tag := Tag,
- match := Match,
- from := From,
- timer := Timer}} = State) ->
- case string:split(Acc, Match) of
- [Pre,Post] ->
- ?dbg({match,Pre}),
- From ! {Tag, Pre},
- erlang:cancel_timer(Timer),
- receive
- {timeout,Timer,timeout} ->
- ok
- after 0 ->
- ok
- end,
- maps:put(acc, Post, maps:remove(get, State));
- [Acc] ->
- State
+kill_emulator(#{port := Port}) ->
+ %% If the line happens to end in a ".", issuing "init:stop()."
+ %% will result in a syntax error. To avoid that, issue a "\n"
+ %% before "init:stop().".
+ Port ! {self(),{command, "\ninit:stop().\n"}},
+ wait_for_eof(Port).
+
+wait_for_eof(Port) ->
+ receive
+ {Port,eof} ->
+ normal;
+ _Other ->
+ wait_for_eof(Port)
+ after
+ timeout(long) ->
+ {error, kill_timeout}
+ end.
+
+init_expect(Pid, Ref, ExpectList, Timeout, State) ->
+ try compile_expect(ExpectList) of
+ Expect ->
+ Exp = #{expect => Expect,
+ ref => Ref,
+ source => ExpectList,
+ timer => erlang:start_timer(Timeout, self(), expect_timeout),
+ from => Pid},
+ State#{expect => Exp}
+ catch
+ Class:Reason:Stk ->
+ io:put_chars("Compilation of expect pattern failed:"),
+ io:format("~p\n", [ExpectList]),
+ io:put_chars(erl_error:format_exception(Class, Reason, Stk)),
+ exit(expect_pattern_error)
+ end.
+
+handle_expect(#{acc := Acc, expect := Exp} = State) ->
+ #{expect := Expect, from := Pid, ref := Ref} = Exp,
+ case Expect(Acc) of
+ nomatch ->
+ State;
+ {matched, Eaten, Result} ->
+ Pid ! {Ref, Result},
+ finish_expect(Eaten, State)
end;
-handle_match(State) ->
+handle_expect(State) ->
State.
+handle_expect_timeout(Timer, State) ->
+ #{acc := Acc, expect := Exp} = State,
+ #{expect := Expect, timer := Timer, from := Pid, ref := Ref} = Exp,
+ case Expect({timeout, Acc}) of
+ nomatch ->
+ Result = {expect_timeout, Acc},
+ Pid ! {Ref, Result},
+ finish_expect(0, State);
+ {matched, Eaten, Result} ->
+ Pid ! {Ref, Result},
+ finish_expect(Eaten, State)
+ end.
+
+finish_expect(Eaten, #{acc := Acc0,
+ expect := #{timer := Timer}}=State) ->
+ erlang:cancel_timer(Timer),
+ receive
+ {timeout,Timer,timeout} ->
+ ok
+ after 0 ->
+ ok
+ end,
+ Acc = lists:nthtail(Eaten, Acc0),
+ maps:remove(expect, State#{acc := Acc}).
+
+compile_expect([{timeout,Action}|T]) when is_function(Action, 1) ->
+ Next = compile_expect(T),
+ fun({timeout, _}=Tm) ->
+ {matched, 0, Action(Tm)};
+ (Subject) ->
+ Next(Subject)
+ end;
+compile_expect([{{re,RE0},Action}|T]) when is_binary(RE0), is_function(Action, 1) ->
+ {ok, RE} = re:compile(RE0),
+ Next = compile_expect(T),
+ fun({timeout, _}=Subject) ->
+ Next(Subject);
+ (Subject) ->
+ case re:run(Subject, RE, [{capture,first,index}]) of
+ nomatch ->
+ Next(Subject);
+ {match, [{Pos,Len}]} ->
+ Matched = binary:part(list_to_binary(Subject), Pos, Len),
+ {matched, Pos+Len, Action(Matched)}
+ end
+ end;
+compile_expect([RE|T]) when is_list(RE) ->
+ Ok = fun(_) -> ok end,
+ compile_expect([{{re,list_to_binary(RE)},Ok}|T]);
+compile_expect([]) ->
+ fun(_) ->
+ nomatch
+ end.
+
rtnode_check_logs(Logname, Pattern, Logs) ->
rtnode_check_logs(Logname, Pattern, true, Logs).
rtnode_check_logs(Logname, Pattern, Match, Logs) ->
@@ -1275,7 +1283,15 @@ rtnode_dump_logs(Logs) ->
end, Logs).
rtnode_read_logs(Tempdir) ->
- {ok, LogFiles} = file:list_dir(Tempdir),
+ {ok, LogFiles0} = file:list_dir(Tempdir),
+
+ %% Make sure that we only read log files and not any named pipes.
+ LogFiles = [F || F <- LogFiles0,
+ case F of
+ "erlang.log" ++ _ -> true;
+ _ -> false
+ end],
+
lists:foldl(
fun(File, Acc) ->
case file:read_file(filename:join(Tempdir, File)) of
@@ -1289,13 +1305,13 @@ rtnode_read_logs(Tempdir) ->
get_default_shell() ->
try
rtnode([{putline,""},
- {putline, "whereis(user_drv)."},
- {getline, "undefined"}],[]),
- old
+ {putline, "is_pid(whereis(user_drv))."},
+ {expect, "true\r\n"}], []),
+ new
catch _E:_R ->
?dbg({_E,_R}),
- new
+ old
end.
-atom2list(A) ->
- lists:flatten(io_lib:format("~s", [A])).
+printed_atom(A) ->
+ lists:flatten(io_lib:format("~w", [A])).
diff --git a/lib/kernel/test/kernel.spec b/lib/kernel/test/kernel.spec
index eaa17f3a59..fdf90c8ce2 100644
--- a/lib/kernel/test/kernel.spec
+++ b/lib/kernel/test/kernel.spec
@@ -1,5 +1,2 @@
-{config, "../test_server/ts.config"}.
-{config, "../test_server/ts.unix.config"}.
-
{suites,"../kernel_test", all}.
{skip_suites,"../kernel_test",[logger_stress_SUITE],"Benchmarks only"}.
diff --git a/lib/kernel/test/kernel_SUITE.erl b/lib/kernel/test/kernel_SUITE.erl
index a70aa1fa30..48e4db2ad3 100644
--- a/lib/kernel/test/kernel_SUITE.erl
+++ b/lib/kernel/test/kernel_SUITE.erl
@@ -23,7 +23,7 @@
-module(kernel_SUITE).
-include_lib("common_test/include/ct.hrl").
--compile(r21).
+-compile(r22).
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
@@ -55,7 +55,19 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
+init_per_testcase(appup_test, Config) ->
+ %% We check if the test results were released using a version
+ %% of Erlang/OTP that was a tagged version or not. On a non-tagged
+ %% version this testcase most likely will fail.
+ case file:read_file(
+ filename:join(
+ proplists:get_value(data_dir,Config), "otp_version_tickets")) of
+ {ok,<<"DEVELOPMENT",_/binary>>} ->
+ {skip, "This is a development version, test might fail "
+ "because of incorrect version numbers"};
+ {ok,_NotDev} ->
+ Config
+ end;
init_per_testcase(_Case, Config) ->
Config.
end_per_testcase(_Case, _Config) ->
@@ -75,8 +87,6 @@ app_test(Config) when is_list(Config) ->
appup_test(_Config) ->
appup_tests(kernel,create_test_vsns(kernel)).
-appup_tests(_App,{[],[]}) ->
- {skip,"no previous releases available"};
appup_tests(App,{OkVsns0,NokVsns}) ->
application:load(App),
{_,_,Vsn} = lists:keyfind(App,1,application:loaded_applications()),
@@ -89,8 +99,7 @@ appup_tests(App,{OkVsns0,NokVsns}) ->
OkVsns0 ->
OkVsns0;
Ok ->
- ct:log("Current version, ~p, is same as in previous release.~n"
- "Removing this from the list of ok versions.",
+ ct:log("Removed current version ~p from the list of ok versions to test.",
[Vsn]),
Ok
end,
@@ -105,57 +114,46 @@ appup_tests(App,{OkVsns0,NokVsns}) ->
ok.
create_test_vsns(App) ->
- ThisMajor = erlang:system_info(otp_release),
- FirstMajor = previous_major(ThisMajor),
- SecondMajor = previous_major(previous_major(FirstMajor)),
- Ok = app_vsn(App,[ThisMajor,FirstMajor]),
- Nok0 = app_vsn(App,[SecondMajor]),
+ S = otp_vsns:read_state(),
+ Rel = list_to_integer(erlang:system_info(otp_release)),
+ AppStr = atom_to_list(App),
+ Ok = ok_app_vsns(S, Rel, AppStr),
+ Nok0 = nok_app_vsns(S, Rel, AppStr, hd(Ok)),
Nok = case Ok of
- [Ok1|_] ->
- [Ok1 ++ ",1" | Nok0]; % illegal
- _ ->
- Nok0
- end,
- {Ok,Nok}.
-
-previous_major("17") ->
- "r16b";
-previous_major("r16b") ->
- "r15b";
-previous_major(Rel) ->
- integer_to_list(list_to_integer(Rel)-1).
-
-app_vsn(App,[R|Rs]) ->
- OldRel =
- case test_server:is_release_available(R) of
- true ->
- {release,R};
- false ->
- case ct:get_config({otp_releases,list_to_atom(R)}) of
- undefined ->
- false;
- Prog0 ->
- case os:find_executable(Prog0) of
- false ->
- false;
- Prog ->
- {prog,Prog}
- end
- end
- end,
- case OldRel of
- false ->
- app_vsn(App,Rs);
- _ ->
- {ok,N} = test_server:start_node(prevrel,peer,[{erl,[OldRel]}]),
- _ = rpc:call(N,application,load,[App]),
- As = rpc:call(N,application,loaded_applications,[]),
- {_,_,V} = lists:keyfind(App,1,As),
- test_server:stop_node(N),
- [V|app_vsn(App,Rs)]
- end;
-app_vsn(_App,[]) ->
- [].
+ [Ok1|_] ->
+ [Ok1 ++ ",1" | Nok0]; % illegal
+ _ ->
+ Nok0
+ end,
+ {Ok, Nok}.
+
+ok_app_vsns(S, Rel, AppStr) ->
+ AppVsns0 = get_rel_app_vsns(S, Rel-2, AppStr),
+ AppVsns1 = get_rel_app_vsns(S, Rel-1, AppStr),
+ AppVsns2 = try
+ get_rel_app_vsns(S, Rel, AppStr)
+ catch
+ _:_ -> []
+ end,
+ lists:usort(AppVsns2 ++ AppVsns1 ++ AppVsns0).
+
+nok_app_vsns(S, Rel, AppStr, EarliestOkVsn) ->
+ AppVsns0 = get_rel_app_vsns(S, Rel-4, AppStr),
+ AppVsns1 = get_rel_app_vsns(S, Rel-3, AppStr),
+ %% Earliest OK version may exist in not OK versions
+ %% as well if there were no application version bump
+ %% between two releases, so we need to remove it
+ %% if that is the case...
+ lists:usort(AppVsns1 ++ AppVsns0) -- EarliestOkVsn.
+
+get_rel_app_vsns(S, Rel, App) ->
+ RelStr = integer_to_list(Rel),
+ OtpVsns = otp_vsns:branch_vsns(S, "maint-"++RelStr),
+ lists:map(fun (OtpVsn) ->
+ AppVsn = otp_vsns:app_vsn(S, OtpVsn, App),
+ [_, Vsn] = string:lexemes(AppVsn, "-"),
+ Vsn
+ end, OtpVsns).
check_appup([Vsn|Vsns],Instrs,Expected) ->
case systools_relup:appup_search_for_version(Vsn, Instrs) of
diff --git a/lib/kernel/test/kernel_smoke.spec b/lib/kernel/test/kernel_smoke.spec
index e5d8273c56..84be0a97bc 100644
--- a/lib/kernel/test/kernel_smoke.spec
+++ b/lib/kernel/test/kernel_smoke.spec
@@ -1,6 +1,3 @@
-{config, "../test_server/ts.config"}.
-{config, "../test_server/ts.unix.config"}.
-
{cases,"../kernel_test", inet_SUITE,[t_gethostbyaddr,t_gethostbyname,
t_gethostbyaddr_v6,t_gethostbyname_v6,t_gethostnative,getifaddrs]}.
{cases,"../kernel_test", inet_res_SUITE,[gethostbyaddr,gethostbyname,
diff --git a/lib/kernel/test/kernel_test_global_sys_monitor.erl b/lib/kernel/test/kernel_test_global_sys_monitor.erl
index 216e872bf4..4334d405f3 100644
--- a/lib/kernel/test/kernel_test_global_sys_monitor.erl
+++ b/lib/kernel/test/kernel_test_global_sys_monitor.erl
@@ -221,7 +221,7 @@ cast(Msg) ->
ok
catch
C:E:_ ->
- {error, {catched, C, E}}
+ {error, {caught, C, E}}
end.
@@ -234,10 +234,10 @@ call(Req, Timeout) when is_integer(Timeout) andalso (Timeout > 1000) ->
call(Req, Timeout) when is_integer(Timeout) ->
call(Req, Timeout, Timeout div 2).
-%% This peace of wierdness is because on some machines this call has
+%% This peace of weirdness is because on some machines this call has
%% hung (in a call during end_per_testcase, which had a 1 min timeout,
%% or if that was the total time for the test case).
-%% But because it hung there, we don't really know what where it git stuck.
+%% But because it hung there, we don't really know where it got stuck.
%% So, by making the call in a tmp process, that we supervise, we can
%% keep control. Also, we change the default timeout from infinity to an
%% actual time (16 seconds).
@@ -250,11 +250,11 @@ call(Req, Timeout1, Timeout2) ->
{?MODULE, Ref, Rep} ->
exit(Rep)
after Timeout2 ->
- {error, timeout}
+ exit({error, timeout})
end
catch
- C:E:_ ->
- {error, {catched, C, E}}
+ C:E:S ->
+ exit({error, {caught, C, E, S}})
end
end,
{Pid, Mon} = spawn_monitor(F),
diff --git a/lib/kernel/test/kernel_test_lib.erl b/lib/kernel/test/kernel_test_lib.erl
index a25c06376d..3b00780c49 100644
--- a/lib/kernel/test/kernel_test_lib.erl
+++ b/lib/kernel/test/kernel_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,8 @@
-export([start_node/2, start_node/3,
stop_node/1]).
-export([f/2,
- print/1, print/2]).
+ print/1, print/2,
+ formated_timestamp/0]).
-export([good_hosts/1,
lookup/3]).
-export([os_cmd/1, os_cmd/2]).
@@ -44,6 +45,7 @@
proxy_call/3,
%% Generic 'has support' test function(s)
+ has_support_ipv4/0,
has_support_ipv6/0,
which_local_host_info/1, which_local_host_info/2,
@@ -54,6 +56,8 @@
skip/1
]).
+%% Convenient exports...
+-export([analyze_and_print_host_info/0]).
-include("kernel_test_lib.hrl").
@@ -91,7 +95,12 @@ init_per_suite(AllowSkip, Config) when is_boolean(AllowSkip) ->
case kernel_test_global_sys_monitor:start() of
{ok, _} ->
print("(global) system monitor started"),
- [{kernel_factor, Factor} | Config];
+ case lists:keysearch(label, 1, HostInfo) of
+ {value, Label} ->
+ [{kernel_factor, Factor}, Label | Config];
+ false ->
+ [{kernel_factor, Factor} | Config]
+ end;
{error, Reason} ->
print("Failed start (global) system monitor:"
"~n ~p", [Reason]),
@@ -150,48 +159,372 @@ analyze_and_print_host_info() ->
end.
linux_which_distro(Version) ->
+ try do_linux_which_distro(Version)
+ catch
+ throw:{distro, DistroAndLabel} ->
+ DistroAndLabel
+ end.
+
+do_linux_which_distro(Version) ->
+ Label = ts_extra_platform_label(),
+
+ %% Many (linux) distro's use the /etc/issue file, so try that first.
+ %% Then we just keep going until we are "done".
+ DistroStr = do_linux_which_distro_issue(Version, Label),
+
+ %% Still not sure; try fedora
+ _ = do_linux_which_distro_fedora(Version, Label),
+
+ %% Still not sure; try suse
+ _ = do_linux_which_distro_suse(Version, Label),
+
+ %% Still not sure; try os-release
+ _ = do_linux_which_distro_os_release(Version, Label),
+
+ %% And the fallback
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)}.
+
+do_linux_which_distro_issue(Version, Label) ->
case file:read_file_info("/etc/issue") of
{ok, _} ->
case [string:trim(S) ||
S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
- [DistroStr|_] ->
- io:format("Linux: ~s"
- "~n ~s"
- "~n",
- [Version, DistroStr]),
+ [DistroStr | _] ->
case DistroStr of
"Wind River Linux" ++ _ ->
- wind_river;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {wind_river, simplify_label(Label)}});
"MontaVista" ++ _ ->
- montavista;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {montavista, simplify_label(Label)}});
"Yellow Dog" ++ _ ->
- yellow_dog;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {yellow_dog, simplify_label(Label)}});
+ "Ubuntu" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {ubuntu, simplify_label(Label)}});
+ "Linux Mint" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_mint, simplify_label(Label)}});
_ ->
- other
+ DistroStr
end;
X ->
+ X
+ end;
+ _ ->
+ "Unknown"
+ end.
+
+do_linux_which_distro_fedora(Version, Label) ->
+ %% Check if fedora
+ case file:read_file_info("/etc/fedora-release") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/fedora-release"),
+ [$\n])] of
+ [DistroStr | _] ->
io:format("Linux: ~s"
- "~n ~p"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
"~n",
- [Version, X]),
- other
+ [Version, DistroStr, Label,
+ linux_product_name()]);
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Fedora", Label,
+ linux_product_name()])
+ end,
+ throw({distro, {fedora, simplify_label(Label)}});
+ _ ->
+ ignore
+ end.
+
+do_linux_which_distro_suse(Version, Label) ->
+ %% Check if its a SuSE
+ case file:read_file_info("/etc/SUSE-brand") of
+ {ok, _} ->
+ case file:read_file_info("/etc/SuSE-release") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/SuSE-release"),
+ [$\n])] of
+ ["SUSE Linux Enterprise Server" ++ _ = DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {sles, simplify_label(Label)}});
+ [DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "SuSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ case string:tokens(os:cmd("cat /etc/SUSE-brand"), [$\n]) of
+ ["SLE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}})
+ end;
+ ["openSUSE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Unknown SUSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end
end;
_ ->
- io:format("Linux: ~s"
- "~n", [Version]),
- other
+ ignore
end.
-
+
+do_linux_which_distro_os_release(Version, Label) ->
+ case file:read_file_info("/etc/os-release") of
+ {ok, _} ->
+ %% We want to 'catch' if our processing is wrong,
+ %% that's why we catch and re-throw the distro.
+ %% Actual errors will be returned as 'ignore'.
+ try
+ begin
+ Info = linux_process_os_release(),
+ {value, {_, DistroStr}} = lists:keysearch(name, 1, Info),
+ {value, {_, VersionNo}} = lists:keysearch(version, 1, Info),
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, VersionNo, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_distro_str_to_distro_id(DistroStr),
+ simplify_label(Label)}})
+ end
+ catch
+ throw:{distro, _} = DISTRO ->
+ throw(DISTRO);
+ _:_ ->
+ ignore
+ end;
+ _ ->
+ ignore
+ end.
+
+linux_process_os_release() ->
+ %% Read the "raw" file
+ Raw = os:cmd("cat /etc/os-release"),
+ %% Split it into lines
+ Lines1 = string:tokens(Raw, [$\n]),
+ %% Just in case, skip any lines starting with '#'.
+ Lines2 = linux_process_os_release1(Lines1),
+ %% Each (remaining) line *should* be: <TAG>=<VALUE>
+ %% Both sides will be strings, the value side will be a quoted string...
+ %% Convert those into a 2-tuple list: [{Tag, Value}]
+ linux_process_os_release2(Lines2).
+
+linux_process_os_release1(Lines) ->
+ linux_process_os_release1(Lines, []).
+
+linux_process_os_release1([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release1([H|T], Acc) ->
+ case H of
+ "#" ++ _ ->
+ linux_process_os_release1(T, Acc);
+ _ ->
+ linux_process_os_release1(T, [H|Acc])
+ end.
+
+linux_process_os_release2(Lines) ->
+ linux_process_os_release2(Lines, []).
+
+linux_process_os_release2([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release2([H|T], Acc) ->
+ case linux_process_os_release3(H) of
+ {value, Value} ->
+ linux_process_os_release2(T, [Value|Acc]);
+ false ->
+ linux_process_os_release2(T, Acc)
+ end.
+
+linux_process_os_release3(H) ->
+ case [string:strip(S) || S <- string:tokens(H, [$=])] of
+ [Tag, Value] ->
+ Tag2 = list_to_atom(string:to_lower(Tag)),
+ Value2 = string:strip(Value, both, $"),
+ linux_process_os_release4(Tag2, Value2);
+ _ ->
+ false
+ end.
+
+linux_process_os_release4(name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version_id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(pretty_name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(_Tag, _Value) ->
+ false.
+
+linux_distro_str_to_distro_id("Debian" ++ _) ->
+ debian;
+linux_distro_str_to_distro_id("Fedora" ++ _) ->
+ fedora;
+linux_distro_str_to_distro_id("Linux Mint" ++ _) ->
+ linux_mint;
+linux_distro_str_to_distro_id("MontaVista" ++ _) ->
+ montavista;
+linux_distro_str_to_distro_id("openSUSE" ++ _) ->
+ suse;
+linux_distro_str_to_distro_id("SLES" ++ _) ->
+ sles;
+linux_distro_str_to_distro_id("Ubuntu" ++ _) ->
+ ubuntu;
+linux_distro_str_to_distro_id("Wind River Linux" ++ _) ->
+ wind_river;
+linux_distro_str_to_distro_id("Yellow Dog" ++ _) ->
+ yellow_dog;
+linux_distro_str_to_distro_id(X) ->
+ X.
+
+
analyze_and_print_linux_host_info(Version) ->
- Distro =
+ {Distro, Label} =
case file:read_file_info("/etc/issue") of
{ok, _} ->
linux_which_distro(Version);
_ ->
+ L = ts_extra_platform_label(),
io:format("Linux: ~s"
- "~n", [Version]),
- other
+ "~n TS Extra Platform Label: ~s"
+ "~n", [Version, L]),
+ {other, simplify_label(L)}
end,
+ %% 'VirtFactor' will be 0 unless virtual
+ VirtFactor = linux_virt_factor(),
Factor =
case (catch linux_which_cpuinfo(Distro)) of
{ok, {CPU, BogoMIPS}} ->
@@ -201,43 +534,112 @@ analyze_and_print_linux_host_info(Version) ->
"~n Num Online Schedulers: ~s"
"~n", [CPU, BogoMIPS, str_num_schedulers()]),
if
- (BogoMIPS > 20000) ->
+ (BogoMIPS > 50000) ->
1;
- (BogoMIPS > 10000) ->
+ (BogoMIPS > 40000) ->
2;
- (BogoMIPS > 5000) ->
+ (BogoMIPS > 30000) ->
3;
- (BogoMIPS > 2000) ->
+ (BogoMIPS > 20000) ->
+ 4;
+ (BogoMIPS > 10000) ->
5;
- (BogoMIPS > 1000) ->
+ (BogoMIPS > 5000) ->
8;
+ (BogoMIPS > 3000) ->
+ 12;
true ->
10
end;
+ {ok, "POWER9" ++ _ = CPU} ->
+ %% For some reason this host is really slow
+ %% Consider the CPU, it really should not be...
+ %% But, to not fail a bunch of test cases, we add 5
+ case linux_cpuinfo_clock() of
+ Clock when is_integer(Clock) andalso (Clock > 0) ->
+ io:format("CPU: "
+ "~n Model: ~s"
+ "~n CPU Speed: ~w"
+ "~n Num Online Schedulers: ~s"
+ "~n", [CPU, Clock, str_num_schedulers()]),
+ if
+ (Clock > 2000) ->
+ 5 + num_schedulers_to_factor();
+ true ->
+ 10 + num_schedulers_to_factor()
+ end;
+ _ ->
+ num_schedulers_to_factor()
+ end;
{ok, CPU} ->
io:format("CPU: "
"~n Model: ~s"
"~n Num Online Schedulers: ~s"
"~n", [CPU, str_num_schedulers()]),
- NumChed = erlang:system_info(schedulers),
- if
- (NumChed > 2) ->
- 2;
- true ->
- 5
- end;
+ num_schedulers_to_factor();
_ ->
5
end,
+ AddLabelFactor = label2factor(Label),
%% Check if we need to adjust the factor because of the memory
- try linux_which_meminfo() of
- AddFactor ->
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
- {Factor + AddFactor, []}
- catch
- _:_:_ ->
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
- {Factor, []}
+ AddMemFactor = try linux_which_meminfo()
+ catch _:_:_ -> 0
+ end,
+ TSScaleFactor = case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
+ _ ->
+ 0
+ end,
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n Virtual Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n", [Factor, AddLabelFactor, AddMemFactor, VirtFactor,
+ TSScaleFactor]),
+ {Factor + AddLabelFactor + AddMemFactor + VirtFactor + TSScaleFactor,
+ [{label, Label}]}.
+
+linux_virt_factor() ->
+ linux_virt_factor(linux_product_name()).
+
+linux_virt_factor("VMware" ++ _) ->
+ 2;
+linux_virt_factor("VirtualBox" ++ _) ->
+ 4;
+linux_virt_factor(_) ->
+ 0.
+
+
+linux_cpuinfo_clock() ->
+ %% This is written as: "3783.000000MHz"
+ %% So, check unit MHz (handle nothing else).
+ %% Also, check for both float and integer
+ %% Also, the freq is per core, and can vary...
+ case linux_cpuinfo_lookup("clock") of
+ [C|_] when is_list(C) ->
+ case lists:reverse(string:to_lower(C)) of
+ "zhm" ++ CRev ->
+ try trunc(list_to_float(lists:reverse(CRev))) of
+ I ->
+ I
+ catch
+ _:_:_ ->
+ try list_to_integer(lists:reverse(CRev)) of
+ I ->
+ I
+ catch
+ _:_:_ ->
+ 0
+ end
+ end;
+ _ ->
+ 0
+ end;
+ _ ->
+ 0
end.
linux_cpuinfo_lookup(Key) when is_list(Key) ->
@@ -247,6 +649,8 @@ linux_cpuinfo_cpu() ->
case linux_cpuinfo_lookup("cpu") of
[Model] ->
Model;
+ ["POWER9" ++ _ = CPU|_] ->
+ CPU;
_ ->
"-"
end.
@@ -261,8 +665,11 @@ linux_cpuinfo_motherboard() ->
linux_cpuinfo_bogomips() ->
case linux_cpuinfo_lookup("bogomips") of
+ [] ->
+ "-";
BMips when is_list(BMips) ->
- try lists:sum([bogomips_to_int(BM) || BM <- BMips])
+ BMScale = 1.0,
+ try round(BMScale * lists:sum([bogomips_to_int(BM) || BM <- BMips]))
catch
_:_:_ ->
"-"
@@ -330,6 +737,14 @@ linux_cpuinfo_processor() ->
"-"
end.
+linux_cpuinfo_machine() ->
+ case linux_cpuinfo_lookup("machine") of
+ [M] ->
+ M;
+ _ ->
+ "-"
+ end.
+
linux_which_cpuinfo(montavista) ->
CPU =
case linux_cpuinfo_cpu() of
@@ -386,24 +801,43 @@ linux_which_cpuinfo(wind_river) ->
end;
%% Check for x86 (Intel or AMD)
-linux_which_cpuinfo(other) ->
+linux_which_cpuinfo(Other) when (Other =:= debian) orelse
+ (Other =:= fedora) orelse
+ (Other =:= ubuntu) orelse
+ (Other =:= linux_mint) orelse
+ (Other =:= sles) orelse
+ (Other =:= suse) orelse
+ (Other =:= other) ->
CPU =
case linux_cpuinfo_model_name() of
"-" ->
- %% ARM (at least some distros...)
- case linux_cpuinfo_processor() of
- "-" ->
- case linux_cpuinfo_model() of
+ %% This is for POWER9
+ case linux_cpuinfo_cpu() of
+ "POWER9" ++ _ = PowerCPU ->
+ Machine =
+ case linux_cpuinfo_machine() of
+ "-" ->
+ "";
+ M ->
+ " (" ++ M ++ ")"
+ end,
+ PowerCPU ++ Machine;
+ _X ->
+ %% ARM (at least some distros...)
+ case linux_cpuinfo_processor() of
"-" ->
- %% Ok, we give up
- throw(noinfo);
- Model ->
- Model
- end;
- Proc ->
- Proc
- end;
- ModelName ->
+ case linux_cpuinfo_model() of
+ "-" ->
+ %% Ok, we give up
+ throw(noinfo);
+ Model ->
+ Model
+ end;
+ Proc ->
+ Proc
+ end
+ end;
+ ModelName ->
ModelName
end,
case linux_cpuinfo_bogomips() of
@@ -464,8 +898,10 @@ linux_which_meminfo() ->
%% Just to be clear: This is ***not*** scientific...
analyze_and_print_openbsd_host_info(Version) ->
+ Label = ts_extra_platform_label(),
+ AddLabelFactor = label2factor(simplify_label(Label)),
io:format("OpenBSD:"
- "~n Version: ~p"
+ "~n Version: ~s"
"~n", [Version]),
Extract =
fun(Key) ->
@@ -508,55 +944,115 @@ analyze_and_print_openbsd_host_info(Version) ->
"~nMemory:"
"~n ~w KB"
"~n", [CPU, CPUSpeed, NCPU, Memory]),
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
CPUFactor =
if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
+ (CPUSpeed >= 3000) ->
if
- (NCPU >= 4) ->
+ (NCPU >= 8) ->
1;
+ (NCPU >= 6) ->
+ 2;
+ (NCPU >= 4) ->
+ 3;
(NCPU >= 2) ->
+ 4;
+ true ->
+ 10
+ end;
+ (CPUSpeed >= 2000) ->
+ if
+ (NCPU >= 8) ->
2;
+ (NCPU >= 6) ->
+ 3;
+ (NCPU >= 4) ->
+ 4;
+ (NCPU >= 2) ->
+ 5;
true ->
- 3
+ 12
+ end;
+ (CPUSpeed >= 1000) ->
+ if
+ (NCPU >= 8) ->
+ 3;
+ (NCPU >= 6) ->
+ 4;
+ (NCPU >= 4) ->
+ 5;
+ (NCPU >= 2) ->
+ 6;
+ true ->
+ 14
end;
true ->
if
+ (NCPU >= 8) ->
+ 4;
+ (NCPU >= 6) ->
+ 6;
(NCPU >= 4) ->
- 2;
+ 8;
(NCPU >= 2) ->
- 3;
+ 10;
true ->
- 4
+ 20
end
end,
MemAddFactor =
if
- (Memory =:= -1) ->
+ (Memory >= 16777216) ->
0;
(Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
1;
+ (Memory >= 4194304) ->
+ 3;
(Memory >= 2097152) ->
- 2;
+ 5;
true ->
- 3
+ 10
end,
- {CPUFactor + MemAddFactor, []}
+ io:format("TS Scale Factor: ~w~n"
+ "TS Extra Platform Label: ~s~n",
+ [timetrap_scale_factor(), Label]),
+ {CPUFactor + MemAddFactor + AddLabelFactor, []}
end
catch
_:_:_ ->
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
- {2, []}
+ io:format("TS Scale Factor: ~w~n"
+ "TS Extra Platform Label: ~s~n",
+ [timetrap_scale_factor(), Label]),
+ {2 + AddLabelFactor, []}
end.
+which_freebsd_version() ->
+ case string:trim(os:cmd("which freebsd-version")) of
+ [] ->
+ "-";
+ FreeBSDVersion ->
+ case string:trim(os:cmd(FreeBSDVersion)) of
+ [] ->
+ undefined;
+ V ->
+ V
+ end
+ end.
+
analyze_and_print_freebsd_host_info(Version) ->
- io:format("FreeBSD:"
- "~n Version: ~p"
- "~n", [Version]),
+ Label = ts_extra_platform_label(),
+ AddLabelFactor = label2factor(simplify_label(Label)),
+ FreeBSDVersion = which_freebsd_version(),
+ case FreeBSDVersion of
+ undefined ->
+ io:format("FreeBSD:"
+ "~n Version: ~s"
+ "~n", [Version]),
+ "";
+ _ ->
+ io:format("FreeBSD:"
+ "~n Version: ~s (~s)"
+ "~n", [Version, FreeBSDVersion])
+ end,
%% This test require that the program 'sysctl' is in the path.
%% First test with 'which sysctl', if that does not work
%% try with 'which /sbin/sysctl'. If that does not work either,
@@ -593,30 +1089,57 @@ analyze_and_print_freebsd_host_info(Version) ->
"~n ~w KB"
"~n",
[CPU, CPUSpeed, NCPU, str_num_schedulers(), Memory]),
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
+ io:format("TS Scale Factor: ~w~n"
+ "TS Extra Platform Label: ~s~n",
+ [timetrap_scale_factor(), Label]),
CPUFactor =
if
(CPUSpeed =:= -1) ->
1;
- (CPUSpeed >= 2000) ->
+ (CPUSpeed >= 3000) ->
if
- (NCPU >= 4) ->
+ (NCPU >= 8) ->
1;
+ (NCPU >= 6) ->
+ 2;
+ (NCPU >= 4) ->
+ 3;
(NCPU >= 2) ->
+ 4;
+ true ->
+ 5
+ end;
+ (CPUSpeed >= 2000) ->
+ if
+ (NCPU >= 12) ->
+ 1;
+ (NCPU >= 8) ->
2;
+ (NCPU >= 6) ->
+ 4;
+ (NCPU >= 4) ->
+ 6;
+ (NCPU >= 2) ->
+ 8;
true ->
- 3
+ 10
end;
true ->
if
(NCPU =:= -1) ->
- 1;
- (NCPU >= 4) ->
2;
- (NCPU >= 2) ->
+ (NCPU >= 12) ->
+ 2;
+ (NCPU >= 8) ->
3;
+ (NCPU >= 6) ->
+ 5;
+ (NCPU >= 4) ->
+ 7;
+ (NCPU >= 2) ->
+ 9;
true ->
- 4
+ 12
end
end,
MemAddFactor =
@@ -639,16 +1162,10 @@ analyze_and_print_freebsd_host_info(Version) ->
io:format("CPU:"
"~n Num Online Schedulers: ~s"
"~n", [str_num_schedulers()]),
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
- Factor = case erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- _ ->
- 2
- end,
- {Factor, []}
+ io:format("TS Scale Factor: ~w~n"
+ "TS Extra Platform Label: ~s~n",
+ [timetrap_scale_factor(), Label]),
+ {num_schedulers_to_factor() ++ AddLabelFactor, []}
end.
@@ -689,8 +1206,10 @@ analyze_freebsd_item(Extract, Key, Process, Default) ->
end.
analyze_and_print_netbsd_host_info(Version) ->
+ Label = ts_extra_platform_label(),
+ AddLabelFactor = label2factor(simplify_label(Label)),
io:format("NetBSD:"
- "~n Version: ~p"
+ "~n Version: ~s"
"~n", [Version]),
%% This test require that the program 'sysctl' is in the path.
%% First test with 'which sysctl', if that does not work
@@ -733,6 +1252,9 @@ analyze_and_print_netbsd_host_info(Version) ->
"~n",
[CPU, Machine, Arch, CPUSpeed, NCPU,
erlang:system_info(schedulers), Memory]),
+ io:format("TS Scale Factor: ~w~n"
+ "TS Extra Platform Label: ~s~n",
+ [timetrap_scale_factor(), Label]),
CPUFactor =
if
(CPUSpeed =:= -1) ->
@@ -771,22 +1293,18 @@ analyze_and_print_netbsd_host_info(Version) ->
true ->
3
end,
- {CPUFactor + MemAddFactor, []}
+ {CPUFactor + MemAddFactor + AddLabelFactor, []}
end
catch
_:_:_ ->
io:format("CPU:"
"~n Num Schedulers: ~w"
"~n", [erlang:system_info(schedulers)]),
- Factor = case erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- _ ->
- 2
- end,
- {Factor, []}
+ io:format("TS Scale Factor: ~w~n"
+ "TS Extra Platform Label: ~s~n",
+ [timetrap_scale_factor(), Label]),
+ Factor = num_schedulers_to_factor(),
+ {Factor + AddLabelFactor, []}
end.
analyze_netbsd_cpu(Extract) ->
@@ -823,7 +1341,7 @@ analyze_netbsd_memory(Extract) ->
analyze_netbsd_item(Extract, Key, Process, Default) ->
analyze_freebsd_item(Extract, Key, Process, Default).
-%% Model Identifier: Macmini7,1
+%% Model Identifier: Macmini7,1
%% Processor Name: Intel Core i5
%% Processor Speed: 2,6 GHz
%% Number of Processors: 1
@@ -833,53 +1351,83 @@ analyze_netbsd_item(Extract, Key, Process, Default) ->
%% Hyper-Threading Technology: Enabled
%% Memory: 16 GB
+%% Hardware:
+%%
+%% Hardware Overview:
+%%
+%% Model Name: MacBook Pro
+%% Model Identifier: MacBookPro18,1
+%% Chip: Apple M1 Pro
+%% Total Number of Cores: 10 (8 performance and 2 efficiency)
+%% Memory: 32 GB
+%% System Firmware Version: 7459.101.2
+%% OS Loader Version: 7459.101.2
+%% Serial Number (system): THF4W05C97
+%% Hardware UUID: 7C9AB2E1-73B1-5AD6-9BC8-7229DE7A748C
+%% Provisioning UDID: 00006000-000259042662801E
+%% Activation Lock Status: Enabled
+
+
analyze_and_print_darwin_host_info(Version) ->
+ Label = ts_extra_platform_label(),
+ AddLabelFactor = label2factor(simplify_label(Label)),
%% This stuff is for macOS.
%% If we ever tested on a pure darwin machine,
%% we need to find some other way to find some info...
%% Also, I suppose its possible that we for some other
%% reason *fail* to get the info...
- case analyze_darwin_software_info() of
- [] ->
- io:format("Darwin:"
- "~n Version: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [Version, str_num_schedulers()]),
- {num_schedulers_to_factor(), []};
- SwInfo when is_list(SwInfo) ->
- SystemVersion = analyze_darwin_sw_system_version(SwInfo),
- KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
- HwInfo = analyze_darwin_hardware_info(),
- ModelName = analyze_darwin_hw_model_name(HwInfo),
- ModelId = analyze_darwin_hw_model_identifier(HwInfo),
- ProcName = analyze_darwin_hw_processor_name(HwInfo),
- ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
- NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
- NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
- Memory = analyze_darwin_hw_memory(HwInfo),
- io:format("Darwin:"
- "~n System Version: ~s"
- "~n Kernel Version: ~s"
- "~n Model: ~s (~s)"
- "~n Processor: ~s (~s, ~s, ~s)"
- "~n Memory: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [SystemVersion, KernelVersion,
- ModelName, ModelId,
- ProcName, ProcSpeed, NumProc, NumCores,
- Memory,
- str_num_schedulers()]),
- CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
- ProcSpeed,
- NumProc,
- NumCores),
- MemFactor = analyze_darwin_memory_to_factor(Memory),
- if (MemFactor =:= 1) ->
- {CPUFactor, []};
- true ->
- {CPUFactor + MemFactor, []}
- end
- end.
+ Label = ts_extra_platform_label(),
+ {BaseFactor, MemFactor} =
+ case analyze_darwin_software_info() of
+ [] ->
+ io:format("Darwin:"
+ "~n Version: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n", [Version, str_num_schedulers(), Label]),
+ {num_schedulers_to_factor(), 1};
+ SwInfo when is_list(SwInfo) ->
+ SystemVersion = analyze_darwin_sw_system_version(SwInfo),
+ KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
+ HwInfo = analyze_darwin_hardware_info(),
+ ModelName = analyze_darwin_hw_model_name(HwInfo),
+ ModelId = analyze_darwin_hw_model_identifier(HwInfo),
+ {Processor, CPUFactor} = analyze_darwin_hw_processor(HwInfo),
+ Memory = analyze_darwin_hw_memory(HwInfo),
+ Memory = analyze_darwin_hw_memory(HwInfo),
+ io:format("Darwin:"
+ "~n System Version: ~s"
+ "~n Kernel Version: ~s"
+ "~n Model: ~s (~s)"
+ "~n Processor: ~s"
+ "~n Memory: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n~n",
+ [SystemVersion, KernelVersion,
+ ModelName, ModelId,
+ Processor,
+ Memory,
+ str_num_schedulers(), Label]),
+ {CPUFactor, analyze_darwin_memory_to_factor(Memory)}
+ end,
+ AddLabelFactor = label2factor(simplify_label(Label)),
+ AddMemFactor = if
+ (MemFactor > 0) ->
+ MemFactor - 1;
+ true ->
+ 0
+ end,
+ TSScaleFactor = ts_scale_factor(),
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n~n",
+ [BaseFactor, AddLabelFactor, AddMemFactor, TSScaleFactor]),
+ {BaseFactor + AddLabelFactor + AddMemFactor + TSScaleFactor,
+ [{label, Label}]}.
analyze_darwin_sw_system_version(SwInfo) ->
proplists:get_value("system version", SwInfo, "-").
@@ -890,12 +1438,38 @@ analyze_darwin_sw_kernel_version(SwInfo) ->
analyze_darwin_software_info() ->
analyze_darwin_system_profiler("SPSoftwareDataType").
+analyze_darwin_hw_chip(HwInfo) ->
+ proplists:get_value("chip", HwInfo, "-").
+
analyze_darwin_hw_model_name(HwInfo) ->
proplists:get_value("model name", HwInfo, "-").
analyze_darwin_hw_model_identifier(HwInfo) ->
proplists:get_value("model identifier", HwInfo, "-").
+analyze_darwin_hw_processor(HwInfo) ->
+ case analyze_darwin_hw_processor_name(HwInfo) of
+ "-" -> % Maybe Apple Chip
+ case analyze_darwin_hw_chip(HwInfo) of
+ "-" ->
+ "-";
+ Chip ->
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(Chip, NumCores),
+ {f("~s [~s]", [Chip, NumCores]), CPUFactor}
+ end;
+ ProcName ->
+ ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
+ NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
+ ProcSpeed,
+ NumProc,
+ NumCores),
+ {f("~s [~s, ~s, ~s]",
+ [ProcName, ProcSpeed, NumProc, NumCores]), CPUFactor}
+ end.
+
analyze_darwin_hw_processor_name(HwInfo) ->
proplists:get_value("processor name", HwInfo, "-").
@@ -919,18 +1493,29 @@ analyze_darwin_hardware_info() ->
%% "Something:" (which we ignore)
%% "Key: Value1:Value2"
analyze_darwin_system_profiler(DataType) ->
- %% First, make sure the program actually exist:
- case os:cmd("which system_profiler") of
+ %% First, make sure the program actually exist (with the current PATH):
+ Prog0 = "system_profiler",
+ case os:cmd("which " ++ Prog0) of
[] ->
- [];
+ %% Ok, as a last resource, check if is /usr/sbin/system_profiler?
+ Prog1 = "/usr/sbin/system_profiler",
+ case os:cmd("which " ++ Prog1) of
+ [] ->
+ [];
+ _ ->
+ analyze_darwin_system_profiler(Prog1, DataType)
+ end;
_ ->
- D0 = os:cmd("system_profiler " ++ DataType),
- D1 = string:tokens(D0, [$\n]),
- D2 = [string:trim(S1) || S1 <- D1],
- D3 = [string:tokens(S2, [$:]) || S2 <- D2],
- analyze_darwin_system_profiler2(D3)
+ analyze_darwin_system_profiler(Prog0, DataType)
end.
+analyze_darwin_system_profiler(Prog, DataType) ->
+ D0 = os:cmd(Prog ++ " " ++ DataType),
+ D1 = string:tokens(D0, [$\n]),
+ D2 = [string:trim(S1) || S1 <- D1],
+ D3 = [string:tokens(S2, [$:]) || S2 <- D2],
+ analyze_darwin_system_profiler2(D3).
+
analyze_darwin_system_profiler2(L) ->
analyze_darwin_system_profiler2(L, []).
@@ -978,10 +1563,16 @@ analyze_darwin_memory_to_factor(Mem) ->
20
end.
-%% The speed is a string: "<speed> <unit>"
+%% This is for the M1 family of chips
+%% We don't actually know *how* fast it is, only that its fast.
%% the speed may be a float, which we transforms into an integer of MHz.
-%% To calculate a factor based on processor speed, number of procs
-%% and number of cores is ... not an exact ... science ...
+%% To calculate a factor based on processor "class" and number of cores
+%% is ... not an exact ... science ...
+analyze_darwin_cpu_to_factor("Apple M" ++ _ = _Chip, _NumCoresStr) ->
+ %% We know that pretty much every M processor is *fast*,
+ %% so there is no real need to "calculate" anything...
+ 1.
+
analyze_darwin_cpu_to_factor(_ProcName,
ProcSpeedStr, NumProcStr, NumCoresStr) ->
Speed =
@@ -1104,6 +1695,9 @@ analyze_darwin_cpu_to_factor(_ProcName,
end.
analyze_and_print_solaris_host_info(Version) ->
+ Label = ts_extra_platform_label(),
+ AddLabelFactor = label2factor(simplify_label(Label)),
+
Release =
case file:read_file_info("/etc/release") of
{ok, _} ->
@@ -1191,33 +1785,36 @@ analyze_and_print_solaris_host_info(Version) ->
NumPhysCPU, NumVCPU,
SysConf, MemSz,
str_num_schedulers()]),
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
- MemFactor =
+ AddMemFactor =
try string:tokens(MemSz, [$ ]) of
[SzStr, "Mega" ++ _] ->
try list_to_integer(SzStr) of
- Sz when Sz > 8192 ->
+ Sz when Sz > 16384 ->
0;
- Sz when Sz > 4096 ->
+ Sz when Sz > 8192 ->
1;
+ Sz when Sz > 4096 ->
+ 4;
Sz when Sz > 2048 ->
- 2;
+ 8;
_ ->
- 5
+ 12
catch
_:_:_ ->
10
end;
[SzStr, "Giga" ++ _] ->
try list_to_integer(SzStr) of
- Sz when Sz > 8 ->
+ Sz when Sz > 16 ->
0;
- Sz when Sz > 4 ->
+ Sz when Sz > 8 ->
1;
+ Sz when Sz > 4 ->
+ 4;
Sz when Sz > 2 ->
- 2;
+ 8;
_ ->
- 5
+ 12
catch
_:_:_ ->
10
@@ -1228,79 +1825,143 @@ analyze_and_print_solaris_host_info(Version) ->
_:_:_ ->
10
end,
- {try erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- N when (N =< 6) ->
- 2;
- _ ->
- 1
- catch
- _:_:_ ->
- 10
- end + MemFactor, []}.
+ %% We don't really have enough info about the CPU to calculate the
+ %% base factor based on that, so we just use the number of schedulers.
+ BaseFactor =
+ try erlang:system_info(schedulers) of
+ 1 ->
+ 12;
+ 2 ->
+ 8;
+ N when (N =:= 3) orelse (N =:= 4) ->
+ 4;
+ N when (N =< 6) ->
+ 3;
+ _ ->
+ 2
+ catch
+ _:_:_ ->
+ 12
+ end,
+ TSScaleFactor = ts_scale_factor(),
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n TS Extra Platform Label: ~s"
+ "~n~n",
+ [BaseFactor, AddLabelFactor, AddMemFactor,
+ TSScaleFactor, Label]),
+ {BaseFactor + AddMemFactor + AddLabelFactor + TSScaleFactor,
+ [{label, Label}]}.
analyze_and_print_win_host_info(Version) ->
+ Label = ts_extra_platform_label(),
+ AddLabelFactor = label2factor(simplify_label(Label)),
+
SysInfo = which_win_system_info(),
OsName = win_sys_info_lookup(os_name, SysInfo),
OsVersion = win_sys_info_lookup(os_version, SysInfo),
SysMan = win_sys_info_lookup(system_manufacturer, SysInfo),
SysMod = win_sys_info_lookup(system_model, SysInfo),
+ SysType = win_sys_info_lookup(system_type, SysInfo),
NumProcs = win_sys_info_lookup(num_processors, SysInfo),
TotPhysMem = win_sys_info_lookup(total_phys_memory, SysInfo),
io:format("Windows: ~s"
"~n OS Version: ~s (~p)"
"~n System Manufacturer: ~s"
"~n System Model: ~s"
+ "~n System Type: ~s"
"~n Number of Processor(s): ~s"
"~n Total Physical Memory: ~s"
+ "~n (Erlang) WordSize: ~w"
"~n Num Online Schedulers: ~s"
"~n~n", [OsName, OsVersion, Version,
- SysMan, SysMod, NumProcs, TotPhysMem,
+ SysMan, SysMod, SysType,
+ NumProcs, TotPhysMem,
+ erlang:system_info(wordsize),
str_num_schedulers()]),
- io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
+ io:format("TS: "
+ "~n TimeTrap Factor: ~w"
+ "~n Extra Platform Label: ~s"
+ "~n~n",
+ [timetrap_scale_factor(), Label]),
+ %% 'VirtFactor' will be 0 unless virtual
+ VirtFactor = win_virt_factor(SysMod),
+
+ %% On some machines this is a badly formated string
+ %% (contains a char of 255), so we need to do some nasty stuff...
MemFactor =
try
begin
- [MStr, MUnit|_] =
- string:tokens(lists:delete($,, TotPhysMem), [$\ ]),
+ %% "Normally" this looks like this: "16,123 MB"
+ %% But sometimes the "," is replaced by a 255 char
+ %% which I assume must be some unicode screwup...
+ %% Anyway, filter out both of them!
+ TotPhysMem1 = lists:delete($,, TotPhysMem),
+ TotPhysMem2 = lists:delete(255, TotPhysMem1),
+ [MStr, MUnit|_] = string:tokens(TotPhysMem2, [$\ ]),
case string:to_lower(MUnit) of
"gb" ->
try list_to_integer(MStr) of
- M when M > 8 ->
+ M when M >= 16 ->
0;
- M when M > 4 ->
+ M when M >= 8 ->
1;
- M when M > 2 ->
- 2;
+ M when M >= 4 ->
+ 3;
+ M when M >= 2 ->
+ 6;
_ ->
- 5
+ 10
catch
_:_:_ ->
+ %% For some reason the string contains
+ %% "unusual" characters...
+ %% ...so print the string as a list...
+ io:format("Bad memory string: "
+ "~n [gb] ~w"
+ "~n", [MStr]),
10
end;
"mb" ->
try list_to_integer(MStr) of
- M when M > 8192 ->
+ M when M >= 16384 ->
0;
- M when M > 4096 ->
+ M when M >= 8192 ->
1;
- M when M > 2048 ->
- 2;
+ M when M >= 4096 ->
+ 3;
+ M when M >= 2048 ->
+ 6;
_ ->
- 5
+ 10
catch
_:_:_ ->
+ %% For some reason the string contains
+ %% "unusual" characters...
+ %% ...so print the string as a list...
+ io:format("Bad memory string: "
+ "~n [mb] ~w"
+ "~n", [MStr]),
10
end;
_ ->
+ io:format("Bad memory string: "
+ "~n ~w"
+ "~n", [MStr]),
10
end
end
catch
_:_:_ ->
+ %% For some reason the string contains
+ %% "unusual" characters...
+ %% ...so print the string as a list...
+ io:format("Bad memory string: "
+ "~n (y) ~w"
+ "~n", [TotPhysMem]),
10
end,
CPUFactor =
@@ -1312,7 +1973,20 @@ analyze_and_print_win_host_info(Version) ->
_ ->
2
end,
- {CPUFactor + MemFactor, SysInfo}.
+ io:format("Factor calc:"
+ "~n CPU Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Virtual Factor: ~w"
+ "~n~n",
+ [CPUFactor, MemFactor, AddLabelFactor, VirtFactor]),
+ {CPUFactor + MemFactor + AddLabelFactor + VirtFactor, SysInfo}.
+
+win_virt_factor("VMware" ++ _) ->
+ 2;
+win_virt_factor(_) ->
+ 0.
+
win_sys_info_lookup(Key, SysInfo) ->
win_sys_info_lookup(Key, SysInfo, "-").
@@ -1364,6 +2038,9 @@ process_win_system_info([H|T], Acc) ->
"system model" ->
process_win_system_info(T,
[{system_model, string:trim(Value)}|Acc]);
+ "system type" ->
+ process_win_system_info(T,
+ [{system_type, string:trim(Value)}|Acc]);
"processor(s)" ->
[NumProcStr|_] = string:tokens(Value, [$\ ]),
T2 = lists:nthtail(list_to_integer(NumProcStr), T),
@@ -1391,8 +2068,12 @@ num_schedulers_to_factor() ->
1 ->
10;
2 ->
- 5;
- N when (N =< 6) ->
+ 8;
+ 3 ->
+ 6;
+ 4 ->
+ 4;
+ N when (N =< 5) ->
2;
_ ->
1
@@ -1402,6 +2083,43 @@ num_schedulers_to_factor() ->
end.
+ts_extra_platform_label() ->
+ case os:getenv("TS_EXTRA_PLATFORM_LABEL") of
+ false -> "-";
+ Val -> Val
+ end.
+
+ts_scale_factor() ->
+ case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
+ _ ->
+ 0
+ end.
+
+simplify_label("Systemtap" ++ _) ->
+ {host, systemtap};
+simplify_label("Meamax" ++ _) ->
+ {host, meamax};
+simplify_label("Cover" ++ _) ->
+ {host, cover};
+simplify_label(Label) ->
+ case string:find(string:to_lower(Label), "docker") of
+ "docker" ++ _ ->
+ docker;
+ _ ->
+ {host, undefined}
+ end.
+
+label2factor(docker) ->
+ 4;
+label2factor({host, meamax}) ->
+ 2;
+label2factor({host, cover}) ->
+ 6;
+label2factor({host, _}) ->
+ 0.
+
linux_info_lookup(Key, File) ->
LKey = string:to_lower(Key),
try [string:trim(S) || S <- string:tokens(os:cmd("grep -i " ++ "\"" ++ LKey ++ "\"" ++ " " ++ File), [$:,$\n])] of
@@ -1426,6 +2144,22 @@ linux_info_lookup_collect(Key1, [Key2, Value|Rest], Values) ->
linux_info_lookup_collect(_, _, Values) ->
lists:reverse(Values).
+
+linux_product_name() ->
+ ProductNameFile = "/sys/devices/virtual/dmi/id/product_name",
+ case file:read_file_info(ProductNameFile) of
+ {ok, _} ->
+ case os:cmd("cat " ++ ProductNameFile) of
+ false ->
+ "-";
+ Info ->
+ string:trim(Info)
+ end;
+ _ ->
+ "-"
+ end.
+
+
maybe_skip(_HostInfo) ->
%% We have some crap machines that causes random test case failures
@@ -1667,11 +2401,12 @@ tc_try(Case, TCCond, Pre, TC, Post)
tc_print("pre done: try test case"),
try
begin
- TC(State),
+ TCRes = TC(State),
?SLEEP(?SECS(1)),
tc_print("test case done: try post"),
(catch Post(State)),
- tc_end("ok")
+ tc_end("ok"),
+ TCRes
end
catch
C:{skip, _} = SKIP when (C =:= throw) orelse
@@ -1681,10 +2416,32 @@ tc_try(Case, TCCond, Pre, TC, Post)
tc_end( f("skipping(catched,~w,tc)", [C]) ),
SKIP;
C:E:S ->
- tc_print("test case failed: try post"),
- (catch Post(State)),
- tc_end( f("failed(catched,~w,tc)", [C]) ),
- erlang:raise(C, E, S)
+ %% We always check the system events
+ %% before we accept a failure.
+ %% We do *not* run the Post here because it might
+ %% generate sys events itself...
+ case kernel_test_global_sys_monitor:events() of
+ [] ->
+ tc_print("test case failed: try post"),
+ (catch Post(State)),
+ tc_end( f("failed(caught,~w,tc)", [C]) ),
+ erlang:raise(C, E, S);
+ SysEvs ->
+ tc_print(
+ "System Events received during tc: "
+ "~n ~p"
+ "~nwhen tc failed:"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [SysEvs, C, E, S]),
+ (catch Post(State)),
+ tc_end( f("skipping(catched-sysevs,~w,tc)",
+ [C]) ),
+ SKIP = {skip,
+ "TC failure with system events"},
+ SKIP
+ end
end
catch
C:{skip, _} = SKIP when (C =:= throw) orelse
@@ -1692,14 +2449,31 @@ tc_try(Case, TCCond, Pre, TC, Post)
tc_end( f("skipping(catched,~w,tc-pre)", [C]) ),
SKIP;
C:E:S ->
- tc_print("tc-pre failed: auto-skip"
- "~n C: ~p"
- "~n E: ~p"
- "~n S: ~p",
- [C, E, S]),
- tc_end( f("auto-skip(catched,~w,tc-pre)", [C]) ),
- SKIP = {skip, f("TC-Pre failure (~w)", [C])},
- SKIP
+ %% We always check the system events
+ %% before we accept a failure
+ case kernel_test_global_sys_monitor:events() of
+ [] ->
+ tc_print("tc-pre failed: auto-skip"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [C, E, S]),
+ tc_end( f("auto-skip(caught,~w,tc-pre)", [C]) ),
+ SKIP = {skip, f("TC-Pre failure (~w)", [C])},
+ SKIP;
+ SysEvs ->
+ tc_print("System Events received: "
+ "~n ~p"
+ "~nwhen tc-pre failed:"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [SysEvs, C, E, S], "", ""),
+ tc_end( f("skipping(catched-sysevs,~w,tc-pre)",
+ [C]) ),
+ SKIP = {skip, "TC-Pre failure with system events"},
+ SKIP
+ end
end;
{skip, _} = SKIP ->
tc_end("skipping(cond)"),
@@ -1892,6 +2666,14 @@ proxy_call(F, Timeout, Default)
%% This is an extremely simple check...
+has_support_ipv4() ->
+ case which_local_addr(inet) of
+ {ok, _Addr} ->
+ ok;
+ {error, _R1} ->
+ skip("IPv4 Not Supported")
+ end.
+
has_support_ipv6() ->
case which_local_addr(inet6) of
{ok, _Addr} ->
diff --git a/lib/kernel/test/kernel_test_lib.hrl b/lib/kernel/test/kernel_test_lib.hrl
index 41fc2a2cfa..891eb6d262 100644
--- a/lib/kernel/test/kernel_test_lib.hrl
+++ b/lib/kernel/test/kernel_test_lib.hrl
@@ -56,6 +56,10 @@
-define(WHICH_INET_BACKEND(C), ?LIB:which_inet_backend(C)).
-define(IS_SOCKET_BACKEND(C), ?LIB:is_socket_backend(C)).
+-define(HAS_SUPPORT_IPV4(), ?LIB:has_support_ipv4()).
+-define(HAS_SUPPORT_IPV6(), ?LIB:has_support_ipv6()).
+-define(WHICH_LOCAL_ADDR(__D__), ?LIB:which_local_addr(__D__)).
+
-define(START_NODE(__N__, __A__),
?LIB:start_node(__N__, __A__)).
-define(START_NODE(__N__, __A__, __O__),
@@ -66,6 +70,7 @@
-define(F(FORMAT, ARGS), ?LIB:f(FORMAT, ARGS)).
-define(P(F), ?LIB:print(F)).
-define(P(F,A), ?LIB:print(F, A)).
+-define(FTS(), ?LIB:formated_timestamp()).
-define(SECS(I), timer:seconds(I)).
-define(MINS(I), timer:minutes(I)).
diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl
index f9ae51ae40..ef1bef9df3 100644
--- a/lib/kernel/test/logger_SUITE.erl
+++ b/lib/kernel/test/logger_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,8 +38,7 @@
suite() ->
- [{timetrap,{seconds,30}},
- {ct_hooks,[logger_test_lib]}].
+ [{timetrap,{seconds,30}}].
init_per_suite(Config) ->
case logger:get_handler_config(?STANDARD_HANDLER) of
@@ -77,7 +76,7 @@ end_per_testcase(Case, Config) ->
groups() ->
[].
-all() ->
+all() ->
[start_stop,
add_remove_handler,
multiple_handlers,
@@ -92,6 +91,7 @@ all() ->
set_application_level,
cache_module_level,
format_report,
+ filter_successful,
filter_failed,
handler_failed,
config_sanity_check,
@@ -103,7 +103,9 @@ all() ->
process_metadata,
app_config,
kernel_config,
- pretty_print].
+ pretty_print,
+ pathological,
+ internal_log].
start_stop(_Config) ->
S = whereis(logger),
@@ -524,6 +526,58 @@ format_report(_Config) ->
ok.
+filter_successful(_Config) ->
+ ok = logger:add_handler(h1,?MODULE,#{level=>all,filter_default=>log}),
+ HF = {fun(#{meta:=#{filter:={set_msg,Msg}}} = Log,_) ->
+ Log#{msg:=Msg};
+ (#{meta:=#{filter:={return,Ret}}},_) ->
+ Ret
+ end,
+ []},
+ ok = logger:add_handler_filter(h1,hf,HF),
+
+ ?LOG_NOTICE("hello",#{filter=>{return,stop}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_no_log(),
+
+ ?LOG_NOTICE("hello",#{filter=>{return,ignore}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,"hello",?MY_LOC(2)),
+
+ ?LOG_NOTICE("",#{filter=>{set_msg,{'hello',[]}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,'hello',[],?MY_LOC(2)),
+
+ ?LOG_NOTICE("",#{filter=>{set_msg,{"hello",[]}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,"hello",[],?MY_LOC(2)),
+
+ ?LOG_NOTICE("",#{filter=>{set_msg,{<<"hello">>,[]}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,<<"hello">>,[],?MY_LOC(2)),
+
+ ?LOG_NOTICE("",#{filter=>{set_msg,{string,"hello"}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,"hello",?MY_LOC(2)),
+
+ ?LOG_NOTICE("",#{filter=>{set_msg,{string,<<"hello">>}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,<<"hello">>,?MY_LOC(2)),
+
+ logger:notice("",#{filter=>{set_msg,{report,M1=?map_rep}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,M1,#{}),
+
+ logger:notice("",#{filter=>{set_msg,{report,M2=?keyval_rep}}}),
+ {ok,#{filters:=[_]}} = logger:get_handler_config(h1),
+ ok = check_logged(notice,M2,#{}),
+
+ ok.
+
+filter_successful(cleanup,_Config) ->
+ logger:remove_handler(h1),
+ ok.
+
filter_failed(_Config) ->
ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log}),
@@ -849,7 +903,7 @@ via_logger_process(Config) ->
case os:type() of
{win32,_} ->
- %% Skip this part on windows - cant change file mode"
+ %% Skip this part on windows - can't change file mode"
ok;
_ ->
%% This should trigger the same thing from erl_prim_loader
@@ -877,14 +931,13 @@ via_logger_process(cleanup, Config) ->
other_node(_Config) ->
ok = logger:add_handler(h1,?MODULE,#{level=>notice,filter_default=>log,
tc_proc=>self()}),
- {ok,Node} = test_server:start_node(?FUNCTION_NAME,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
rpc:call(Node,logger,error,[Msg=?str,#{}]),
check_logged(error,Msg,#{}),
+ peer:stop(Peer),
ok.
other_node(cleanup,_Config) ->
- Nodes = nodes(),
- [test_server:stop_node(Node) || Node <- Nodes],
logger:remove_handler(h1),
ok.
@@ -956,7 +1009,7 @@ process_metadata(cleanup,_Config) ->
app_config(Config) ->
%% Start a node with default configuration
- {ok,_,Node} = logger_test_lib:setup(Config,[]),
+ {ok, _, Peer, Node} = logger_test_lib:setup(Config,[]),
App1Name = app1,
App1 = {application, App1Name,
@@ -978,35 +1031,35 @@ app_config(Config) ->
{ok,#{filters:=DF}} = rpc:call(Node,logger,get_handler_config,[default]),
{ok,#{filters:=[]}} = rpc:call(Node,logger,get_handler_config,[myh]),
- true = test_server:stop_node(Node),
+ ok = peer:stop(Peer),
%% Start a node with no default handler, then add an own default handler
- {ok,#{handlers:=[#{id:=simple}]},Node} =
- logger_test_lib:setup(Config,[{logger,[{handler,default,undefined}]}]),
+ {ok, #{handlers := [#{id := simple}]}, Peer2, Node2} =
+ logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
- ok = rpc:call(Node,application,load,[App1]),
- ok = rpc:call(Node,application,set_env,
+ ok = rpc:call(Node2,application,load,[App1]),
+ ok = rpc:call(Node2,application,set_env,
[App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
- ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+ ok = rpc:call(Node2,logger,add_handlers,[App1Name]),
#{handlers:=[#{id:=default,filters:=DF}]} =
- rpc:call(Node,logger,get_config,[]),
+ rpc:call(Node2,logger,get_config,[]),
- true = test_server:stop_node(Node),
+ ok = peer:stop(Peer2),
%% Start a silent node, then add an own default handler
- {ok,#{handlers:=[]},Node} =
+ {ok,#{handlers:=[]}, Peer3, Node3} =
logger_test_lib:setup(Config,[{error_logger,silent}]),
{error,{bad_config,{handler,[{some,bad,config}]}}} =
- rpc:call(Node,logger,add_handlers,[[{some,bad,config}]]),
- ok = rpc:call(Node,logger,add_handlers,
+ rpc:call(Node3,logger,add_handlers,[[{some,bad,config}]]),
+ ok = rpc:call(Node3,logger,add_handlers,
[[{handler,default,logger_std_h,#{}}]]),
#{handlers:=[#{id:=default,filters:=DF}]} =
- rpc:call(Node,logger,get_config,[]),
+ rpc:call(Node3,logger,get_config,[]),
- ok.
+ ok = peer:stop(Peer3).
%% This test case is mainly to see code coverage. Note that
%% logger_env_var_SUITE tests a lot of the same, and checks the
@@ -1017,7 +1070,7 @@ kernel_config(Config) ->
%% start by calling logger:reconfigure(). This is to test all
%% variants of kernel config, including bad config, and see
%% the code coverage.
- {ok,#{handlers:=[#{id:=simple,filters:=DF}]}=LC,Node} =
+ {ok,#{handlers:=[#{id:=simple,filters:=DF}]}=LC, Peer, Node} =
logger_test_lib:setup(Config,[{error_logger,false}]),
%% Same once more, to get coverage
@@ -1151,7 +1204,7 @@ kernel_config(Config) ->
{error,{bad_config,{kernel,{invalid_level,bad}}}} =
rpc:call(Node,logger,reconfigure,[]),
- ok.
+ ok = peer:stop(Peer).
pretty_print(_Config) ->
ok = logger:add_handler(?FUNCTION_NAME,logger_std_h,#{}),
@@ -1208,6 +1261,45 @@ pretty_print(_Config) ->
IHs = ["Handler configuration: \n"|IHs2],
ok.
+pathological(cleanup,_Config) ->
+ logger:remove_handler(p1),
+ logger:set_primary_config(level,notice),
+ logger:unset_module_level(?MODULE),
+ ok.
+
+pathological(_Config) ->
+ ok = logger:set_primary_config(level,all),
+ ok = logger:add_handler(p1,?MODULE,#{level=>all,filter_default=>log}),
+ logger:notice(string, []),
+ check_logged(notice,"string",[],#{}),
+ logger:notice(report, []),
+ check_logged(notice,"report",[],#{}),
+ ok.
+
+internal_log(_Config) ->
+ register(callback_receiver, self()),
+ {error, {not_found, h1}} = logger:get_handler_config(h1),
+ ok = logger:add_handler(h1, ?MODULE, #{tc_proc => self()}),
+ OriginalMeta = #{
+ mfa => {orig_mod, orig_func, 0},
+ line => 0,
+ file => "path/to/orig_mod.beam",
+ pid => self(),
+ time => logger:timestamp(),
+ gl => group_leader()
+ },
+ OriginalLog = #{
+ level => notice,
+ msg => "Original log",
+ meta => OriginalMeta
+ },
+ Report = [{testing, internal_log}],
+
+ ?LOG_INTERNAL(notice, OriginalLog, Report),
+ ok = check_logged(notice, Report, ?MY_LOC(1)),
+
+ ok.
+
%%%-----------------------------------------------------------------
%%% Internal
check_logged(Level,Format,Args,Meta) ->
@@ -1288,7 +1380,7 @@ test_api(Level) ->
logger:Level("~w: ~w",[Level,fa]),
ok = check_logged(Level,"~w: ~w",[Level,fa],#{}),
logger:Level('~w: ~w',[Level,fa]),
- ok = check_logged(Level,'~w: ~w',[Level,fa],#{}),
+ ok = check_logged(Level,"~w: ~w",[Level,fa],#{}),
logger:Level(<<"~w: ~w">>,[Level,fa]),
ok = check_logged(Level,<<"~w: ~w">>,[Level,fa],#{}),
logger:Level("~w: ~w ~w",[Level,fa,meta],#{my=>meta}),
@@ -1301,7 +1393,7 @@ test_api(Level) ->
ok = check_logged(Level,<<"~w: ~w ~w">>,[Level,fun_to_fa,meta],#{my=>meta}),
logger:Level(fun(x) -> {'~w: ~w ~w',[Level,fun_to_fa,meta]} end,x,
#{my=>meta}),
- ok = check_logged(Level,'~w: ~w ~w',[Level,fun_to_fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],#{my=>meta}),
logger:Level(fun(x) -> #{Level=>fun_to_r,meta=>true} end,x,
#{my=>meta}),
ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},#{my=>meta}),
@@ -1332,7 +1424,7 @@ test_log_function(Level) ->
ok = check_logged(Level,<<"~w: ~w ~w">>,[Level,fun_to_fa,meta],#{my=>meta}),
logger:log(Level,fun(x) -> {'~w: ~w ~w',[Level,fun_to_fa,meta]} end,
x, #{my=>meta}),
- ok = check_logged(Level,'~w: ~w ~w',[Level,fun_to_fa,meta],#{my=>meta}),
+ ok = check_logged(Level,"~w: ~w ~w",[Level,fun_to_fa,meta],#{my=>meta}),
logger:log(Level,fun(x) -> #{Level=>fun_to_r,meta=>true} end,
x, #{my=>meta}),
ok = check_logged(Level,#{Level=>fun_to_r,meta=>true},#{my=>meta}),
diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl
index 7bfcd2a397..08908b8b7a 100644
--- a/lib/kernel/test/logger_disk_log_h_SUITE.erl
+++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,8 +47,7 @@
-define(domain,#{domain=>[?MODULE]}).
suite() ->
- [{timetrap,{seconds,30}},
- {ct_hooks,[logger_test_lib]}].
+ [{timetrap,{seconds,30}}].
init_per_suite(Config) ->
timer:start(), % to avoid progress report
@@ -348,7 +347,7 @@ errors(Config) ->
config,
#{file=>"newfilename"}),
- %% Read-only fields may (accidentially) be included in the change,
+ %% Read-only fields may (accidentally) be included in the change,
%% but it won't take effect
{ok,C} = logger:get_handler_config(Name1),
ok = logger:set_handler_config(Name1,config,#{olp=>dummyvalue}),
@@ -647,25 +646,26 @@ sync(Config) ->
{disk_log,sync}]),
logger:notice("second", ?domain),
- timer:sleep(?IDLE_DETECT_TIME*2),
+ timer:sleep(?IDLE_DETECT_TIME*2), %% wait for automatic disk_log_sync
logger:notice("third", ?domain),
- %% wait for automatic disk_log_sync
- check_tracer(?IDLE_DETECT_TIME*2),
+ timer:sleep(?IDLE_DETECT_TIME*2), %% wait for automatic disk_log_sync
+
+ check_tracer(1000),
try_read_file(Log, {ok,<<"first\nsecond\nthird\n">>}, 1000),
-
+
%% switch repeated filesync on and verify that the looping works
SyncInt = 1000,
WaitT = 4500,
- OneSync = {logger_h_common,handle_cast,repeated_filesync},
+ OneSync = {logger_h_common,handle_info,{timeout,repeated_filesync}},
%% receive 1 repeated_filesync per sec
- start_tracer([{{logger_h_common,handle_cast,2},
- [{[repeated_filesync,'_'],[],[{message,{caller}}]}]}],
+ start_tracer([{{logger_h_common,handle_info,2},
+ [{[{timeout,'_',repeated_filesync},'_'],[],[{message,{caller}}]}]}],
[OneSync || _ <- lists:seq(1, trunc(WaitT/SyncInt))]),
HConfig2 = HConfig#{filesync_repeat_interval => SyncInt},
ok = logger:update_handler_config(?MODULE, config, HConfig2),
-
+
SyncInt = maps:get(filesync_repeat_interval,
maps:get(cb_state,logger_olp:info(h_proc_name()))),
timer:sleep(WaitT),
@@ -1611,13 +1611,16 @@ tpl([{{M,F,A},MS}|Trace]) ->
tpl([]) ->
ok.
-tracer({trace,_,call,{logger_h_common,handle_cast,[Op|_]},Caller},
+tracer({trace,_,call,{logger_h_common = Mod,handle_cast = Func,[Op|_]},Caller},
{Pid,[{Mod,Func,Op}|Expected]}) ->
maybe_tracer_done(Pid,Expected,{Mod,Func,Op},Caller);
tracer({trace,_,call,{Mod=logger_disk_log_h,Func=disk_log_write,[_,_,Data]},Caller}, {Pid,[{Mod,Func,Data}|Expected]}) ->
maybe_tracer_done(Pid,Expected,{Mod,Func,Data},Caller);
tracer({trace,_,call,{Mod,Func,_},Caller}, {Pid,[{Mod,Func}|Expected]}) ->
maybe_tracer_done(Pid,Expected,{Mod,Func},Caller);
+tracer({trace,_,call,{logger_h_common = Mod,handle_info = Func,[{timeout,_,Op},_S]},Caller},
+ {Pid,[{Mod,Func,{timeout,Op}}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func},Caller);
tracer({trace,_,call,Call,Caller}, {Pid,Expected}) ->
ct:log("Tracer got unexpected: ~p~nCaller: ~p~nExpected: ~p~n",[Call,Caller,Expected]),
Pid ! {tracer_got_unexpected,Call,Expected},
diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl
index 270403e83a..8ac40e9e70 100644
--- a/lib/kernel/test/logger_env_var_SUITE.erl
+++ b/lib/kernel/test/logger_env_var_SUITE.erl
@@ -27,8 +27,7 @@
-import(logger_test_lib,[setup/2,log/3,sync_and_read/3]).
suite() ->
- [{timetrap,{seconds,60}},
- {ct_hooks,[logger_test_lib]}].
+ [{timetrap, {seconds, 60}}].
init_per_suite(Config) ->
Config.
@@ -80,7 +79,7 @@ all() ->
].
default(Config) ->
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} = setup(Config,[]),
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, _Node} = setup(Config, []),
notice = maps:get(level,P),
true = #{} == maps:get(metadata,P),
#{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
@@ -90,11 +89,11 @@ default(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
default_sasl_compatible(Config) ->
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} =
- setup(Config,[{logger_sasl_compatible,true}]),
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, _Node} =
+ setup(Config, [{logger_sasl_compatible, true}]),
info = maps:get(level,P),
#{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
all = maps:get(level,StdC),
@@ -103,11 +102,11 @@ default_sasl_compatible(Config) ->
false = exists(simple,Hs),
true = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
error_logger_tty(Config) ->
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} =
- setup(Config,[{error_logger,tty}]),
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, _Node} =
+ setup(Config, [{error_logger, tty}]),
notice = maps:get(level,P),
#{module:=logger_std_h} = StdC = find(?STANDARD_HANDLER,Hs),
all = maps:get(level,StdC),
@@ -116,10 +115,10 @@ error_logger_tty(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
error_logger_tty_sasl_compatible(Config) ->
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},_Node} =
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, _Node} =
setup(Config,
[{error_logger,tty},
{logger_sasl_compatible,true}]),
@@ -131,10 +130,10 @@ error_logger_tty_sasl_compatible(Config) ->
false = exists(simple,Hs),
true = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
error_logger_false(Config) ->
- {ok,#{handlers:=Hs,primary:=P,module_levels:=ML},_Node} =
+ {ok, #{handlers := Hs, primary := P, module_levels := ML}, Peer, _Node} =
setup(Config,
[{error_logger,false},
{logger_level,notice}]),
@@ -146,10 +145,10 @@ error_logger_false(Config) ->
{domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters),
false = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
error_logger_false_progress(Config) ->
- {ok,#{handlers:=Hs,primary:=P,module_levels:=ML},_Node} =
+ {ok, #{handlers := Hs, primary := P, module_levels := ML}, Peer, _Node} =
setup(Config,
[{error_logger,false},
{logger_level,notice}]),
@@ -161,10 +160,10 @@ error_logger_false_progress(Config) ->
{domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters),
false = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
error_logger_false_sasl_compatible(Config) ->
- {ok,#{handlers:=Hs,primary:=P,module_levels:=ML},_Node} =
+ {ok, #{handlers := Hs, primary := P, module_levels := ML}, Peer, _Node} =
setup(Config,
[{error_logger,false},
{logger_level,notice},
@@ -177,39 +176,39 @@ error_logger_false_sasl_compatible(Config) ->
{domain,{_,{log,super,[otp]}}} = lists:keyfind(domain,1,SimpleFilters),
true = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
error_logger_silent(Config) ->
- {ok,#{handlers:=Hs},_Node} = setup(Config,
- [{error_logger,silent}]),
+ {ok, #{handlers := Hs}, Peer, _Node} = setup(Config,
+ [{error_logger, silent}]),
false = exists(?STANDARD_HANDLER,Hs),
false = exists(simple,Hs),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
error_logger_silent_sasl_compatible(Config) ->
- {ok,#{handlers:=Hs},_Node} = setup(Config,
+ {ok, #{handlers := Hs}, Peer, _Node} = setup(Config,
[{error_logger,silent},
{logger_sasl_compatible,true}]),
false = exists(?STANDARD_HANDLER,Hs),
false = exists(simple,Hs),
true = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
error_logger_file(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,_,Node} = setup(Config,
+ {ok, _, Peer, Node} = setup(Config,
[{error_logger,{file,Log}}]),
check_default_log(Node,Log,
file,% dest
0),% progress in std logger
- ok.
+ ok = peer:stop(Peer).
logger_file(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},Node}
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, Node}
= setup(Config,
[{logger,
[{handler,?STANDARD_HANDLER,logger_std_h,
@@ -226,11 +225,11 @@ logger_file(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
logger_file_sasl_compatible(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},Node}
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, Node}
= setup(Config,
[{logger_sasl_compatible,true},
{logger,
@@ -248,11 +247,11 @@ logger_file_sasl_compatible(Config) ->
false = exists(simple,Hs),
true = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
logger_file_log_progress(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{primary:=P,handlers:=Hs,module_levels:=ML},Node}
+ {ok, #{primary := P, handlers := Hs, module_levels := ML}, Peer, Node}
= setup(Config,
[{logger_level,info},
{logger,
@@ -271,11 +270,11 @@ logger_file_log_progress(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
[] = ML,
- ok.
+ ok = peer:stop(Peer).
logger_file_no_filter(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs},Node}
+ {ok, #{handlers := Hs}, Peer, Node}
= setup(Config,
[{logger,
[{handler,?STANDARD_HANDLER,logger_std_h,
@@ -291,11 +290,11 @@ logger_file_no_filter(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
logger_file_no_filter_level(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs},Node}
+ {ok, #{handlers := Hs}, Peer, Node}
= setup(Config,
[{logger,
[{handler,?STANDARD_HANDLER,logger_std_h,
@@ -312,11 +311,11 @@ logger_file_no_filter_level(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
logger_file_formatter(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs},Node}
+ {ok, #{handlers := Hs}, Peer, Node}
= setup(Config,
[{logger,
[{handler,?STANDARD_HANDLER,logger_std_h,
@@ -333,11 +332,11 @@ logger_file_formatter(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
logger_filters(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs,primary:=P},Node}
+ {ok, #{handlers := Hs, primary := P}, Peer, Node}
= setup(Config,
[{logger_level,info},
{logger,
@@ -359,11 +358,11 @@ logger_filters(Config) ->
LoggerFilters = maps:get(filters,P),
true = lists:keymember(stop_progress,1,LoggerFilters),
- ok.
+ ok = peer:stop(Peer).
logger_filters_stop(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs,primary:=P},Node}
+ {ok, #{handlers := Hs, primary := P}, Peer, Node}
= setup(Config,
[{logger_level,info},
{logger,
@@ -385,11 +384,11 @@ logger_filters_stop(Config) ->
LoggerFilters = maps:get(filters,P),
true = lists:keymember(log_error,1,LoggerFilters),
- ok.
+ ok = peer:stop(Peer).
logger_module_level(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs,module_levels:=ModuleLevels},Node}
+ {ok, #{handlers := Hs, module_levels := ModuleLevels}, Peer, Node}
= setup(Config,
[{logger_level,info},
{logger,
@@ -409,11 +408,11 @@ logger_module_level(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
[{supervisor,error}] = ModuleLevels,
- ok.
+ ok = peer:stop(Peer).
logger_disk_log(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs},Node}
+ {ok, #{handlers := Hs}, Peer, Node}
= setup(Config,
[{logger,
[{handler,?STANDARD_HANDLER,logger_disk_log_h,
@@ -429,11 +428,11 @@ logger_disk_log(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
logger_disk_log_formatter(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,#{handlers:=Hs},Node}
+ {ok, #{handlers := Hs}, Peer, Node}
= setup(Config,
[{logger,
[{handler,?STANDARD_HANDLER,logger_disk_log_h,
@@ -450,10 +449,10 @@ logger_disk_log_formatter(Config) ->
false = exists(simple,Hs),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
logger_undefined(Config) ->
- {ok,#{handlers:=Hs,primary:=P},_Node} =
+ {ok, #{handlers := Hs, primary := P}, Peer, _Node} =
setup(Config,[{logger,[{handler,?STANDARD_HANDLER,undefined}]}]),
false = exists(?STANDARD_HANDLER,Hs),
#{module:=logger_simple_h} = SimpleC = find(simple,Hs),
@@ -462,7 +461,7 @@ logger_undefined(Config) ->
SimpleFilters = maps:get(filters,SimpleC),
{domain,{_,{log,super,[otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters),
false = exists(sasl,Hs),
- ok.
+ ok = peer:stop(Peer).
%% Test that we can add multiple handlers with the default first
@@ -530,7 +529,7 @@ logger_many_handlers_default_last_broken_filter(Config) ->
{logger_level,info}], LogErr, LogInfo, 7).
logger_many_handlers(Config, Env, LogErr, LogInfo, NumProgress) ->
- {ok,_,Node} = setup(Config,Env),
+ {ok, _, Peer, Node} = setup(Config, Env),
check_single_log(Node,LogErr,
file,% dest
0,% progress in std logger
@@ -542,12 +541,12 @@ logger_many_handlers(Config, Env, LogErr, LogInfo, NumProgress) ->
match(Bin,<<"notice:">>,1,notice,info),
match(Bin,<<"alert:">>,0,alert,info),
- ok.
+ peer:stop(Peer).
logger_proxy(Config) ->
%% assume current node runs with default settings
DefOpts = logger_olp:get_opts(logger_proxy),
- {ok,_,Node} = setup(Config,
+ {ok, _, Peer, Node} = setup(Config,
[{logger,[{proxy,#{sync_mode_qlen=>0,
drop_mode_qlen=>2}}]}]),
Expected = DefOpts#{sync_mode_qlen:=0,
@@ -555,17 +554,17 @@ logger_proxy(Config) ->
Expected = rpc:call(Node,logger_olp,get_opts,[logger_proxy]),
Expected = rpc:call(Node,logger,get_proxy_config,[]),
- ok.
+ peer:stop(Peer).
logger_metadata(Config) ->
- {ok,#{ primary := #{ metadata := #{ test := test } } }, _}
+ {ok,#{ primary := #{ metadata := #{ test := test } } }, Peer, _}
= setup(Config, [{logger_metadata,#{ test => test }}]),
- ok.
+ peer:stop(Peer).
sasl_compatible_false(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,_,Node} = setup(Config,
+ {ok, _, Peer, Node} = setup(Config,
[{error_logger,{file,Log}},
{logger_sasl_compatible,false},
{logger_level,info}]), % to get progress
@@ -573,27 +572,27 @@ sasl_compatible_false(Config) ->
file,% dest
6,% progress in std logger
info),
- ok.
+ peer:stop(Peer).
sasl_compatible_false_no_progress(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,_,Node} = setup(Config,
+ {ok, _, Peer, Node} = setup(Config,
[{error_logger,{file,Log}},
{logger_sasl_compatible,false}]),
check_default_log(Node,Log,
file,% dest
0),% progress in std logger
- ok.
+ peer:stop(Peer).
sasl_compatible(Config) ->
Log = file(Config,?FUNCTION_NAME),
- {ok,_,Node} = setup(Config,
+ {ok, _, Peer, Node} = setup(Config,
[{error_logger,{file,Log}},
{sasl_compatible,true}]),
check_default_log(Node,Log,
file,% dest
0),% progress in std logger
- ok.
+ peer:stop(Peer).
all_logger_level(Config) ->
[all_logger_level(Config,Level) || Level <- [none,
@@ -609,9 +608,8 @@ all_logger_level(Config) ->
ok.
all_logger_level(Config,Level) ->
- {ok,#{primary:=#{level:=Level}},Node} = setup(Config,[{logger_level,Level}]),
- true = test_server:stop_node(Node),
- ok.
+ {ok, #{primary := #{level := Level}}, Peer, _Node} = setup(Config, [{logger_level, Level}]),
+ peer:stop(Peer).
bad_error_logger(Config) ->
error = setup(Config,[{error_logger,baddest}]).
diff --git a/lib/kernel/test/logger_proxy_SUITE.erl b/lib/kernel/test/logger_proxy_SUITE.erl
index 2151dc11f3..cf0deccc88 100644
--- a/lib/kernel/test/logger_proxy_SUITE.erl
+++ b/lib/kernel/test/logger_proxy_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,8 +41,7 @@
-define(ENSURE_TIME,5000).
suite() ->
- [{timetrap,{seconds,30}},
- {ct_hooks,[logger_test_lib]}].
+ [{timetrap,{seconds,30}}].
init_per_suite(Config) ->
Config.
@@ -109,18 +108,18 @@ emulator(cleanup,_Config) ->
ok = logger:remove_handler(?HNAME).
remote(Config) ->
- {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
+ {ok,_,Peer,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
L1 = ?LOC, spawn(Node,fun() -> logger:notice("Log from ~p; ~p",[?FUNCTION_NAME,?LINE],L1) end),
ok = ensure(L1),
L2 = ?LOC, spawn(Node,fun() -> logger:notice([{test_case,?FUNCTION_NAME},{line,?LINE}],L2) end),
ok = ensure(L2),
- ok.
+ ok = peer:stop(Peer).
remote(cleanup,_Config) ->
ok = logger:remove_handler(?HNAME).
remote_disconnect(Config) ->
- {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
+ {ok,_,Peer,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
RemoteGL = rpc:call(Node, erlang, whereis, [user]),
net_kernel:disconnect(Node),
@@ -128,16 +127,16 @@ remote_disconnect(Config) ->
ok = ensure(L1),
L2 = ?LOC#{ gl => RemoteGL }, logger:notice([{test_case,?FUNCTION_NAME},{line,?LINE}],L2),
ok = ensure(L2),
- ok.
+ ok = peer:stop(Peer).
remote_disconnect(cleanup,_Config) ->
ok = logger:remove_handler(?HNAME).
remote_emulator(Config) ->
- {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
+ {ok,_,Peer,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
Pid = spawn(Node,fun() -> erlang:error(some_reason) end),
ok = ensure(#{pid=>Pid}),
- ok.
+ ok = peer:stop(Peer).
remote_emulator(cleanup,_Config) ->
ok = logger:remove_handler(?HNAME).
diff --git a/lib/kernel/test/logger_simple_h_SUITE.erl b/lib/kernel/test/logger_simple_h_SUITE.erl
index e0ad792bdb..8ac52e54c7 100644
--- a/lib/kernel/test/logger_simple_h_SUITE.erl
+++ b/lib/kernel/test/logger_simple_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,8 +44,7 @@
-define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]).
suite() ->
- [{timetrap,{seconds,30}},
- {ct_hooks, [logger_test_lib]}].
+ [{timetrap,{seconds,30}}].
init_per_suite(Config) ->
Hs0 = logger:get_handler_config(),
@@ -106,7 +105,7 @@ start_stop(cleanup,_Config) ->
%% to stdout which we cannot read from in a detached slave.
replace_default(Config) ->
- {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+ {ok, _, Peer, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
log(Node, emergency, [?str]),
log(Node, alert, [?str,[]]),
log(Node, error, [?map_rep]),
@@ -119,11 +118,11 @@ replace_default(Config) ->
ok = rpc:call(Node, logger, add_handlers, [kernel]),
- ok.
+ ok = peer:stop(Peer).
replace_file(Config) ->
- {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+ {ok, _, Peer, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
log(Node, emergency, [M1=?str]),
log(Node, alert, [M2=?str,[]]),
log(Node, error, [?map_rep]),
@@ -163,11 +162,11 @@ replace_file(Config) ->
"=NOTICE REPORT===="++_,
_
] = Lines,
- ok.
+ ok = peer:stop(Peer).
replace_disk_log(Config) ->
- {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+ {ok, _, Peer, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
log(Node, emergency, [M1=?str]),
log(Node, alert, [M2=?str,[]]),
log(Node, error, [?map_rep]),
@@ -206,4 +205,4 @@ replace_disk_log(Config) ->
"=NOTICE REPORT===="++_,
_
] = Lines,
- ok.
+ ok = peer:stop(Peer).
diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl
index aa31993b9a..ead4418d0d 100644
--- a/lib/kernel/test/logger_std_h_SUITE.erl
+++ b/lib/kernel/test/logger_std_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,8 +51,7 @@
-define(domain,#{domain=>[?MODULE]}).
suite() ->
- [{timetrap,{seconds,30}},
- {ct_hooks,[logger_test_lib]}].
+ [{timetrap,{seconds,30}}].
init_per_suite(Config) ->
timer:start(), % to avoid progress report
@@ -405,7 +404,7 @@ config_fail(_Config) ->
logger:set_handler_config(?MODULE, config,
#{filesync_rep_int => 2000}),
- %% Read-only fields may (accidentially) be included in the change,
+ %% Read-only fields may (accidentally) be included in the change,
%% but it won't take effect
{ok,C} = logger:get_handler_config(?MODULE),
ok = logger:set_handler_config(?MODULE,config,#{olp=>dummyvalue}),
@@ -813,15 +812,17 @@ sync(Config) ->
timer:sleep(?IDLE_DETECT_TIME*2),
logger:notice("fourth", ?domain),
%% wait for automatic filesync
- check_tracer(?IDLE_DETECT_TIME*2),
+ timer:sleep(?IDLE_DETECT_TIME*2),
+
+ check_tracer(1000),
%% switch repeated filesync on and verify that the looping works
SyncInt = 1000,
WaitT = 4500,
- OneSync = {logger_h_common,handle_cast,repeated_filesync},
+ OneSync = {logger_h_common,handle_info,{timeout,repeated_filesync}},
%% receive 1 repeated_filesync per sec
- start_tracer([{{logger_h_common,handle_cast,2},
- [{[repeated_filesync,'_'],[],[]}]}],
+ start_tracer([{{logger_h_common,handle_info,2},
+ [{[{timeout,'_',repeated_filesync},'_'],[],[]}]}],
[OneSync || _ <- lists:seq(1, trunc(WaitT/SyncInt))]),
ok = logger:update_handler_config(?MODULE, config,
@@ -841,7 +842,7 @@ write_failure(Config) ->
Dir = ?config(priv_dir, Config),
File = lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"]),
Log = filename:join(Dir, File),
- Node = start_std_h_on_new_node(Config, Log),
+ {Peer, Node} = start_std_h_on_new_node(Config, Log),
false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
@@ -869,16 +870,13 @@ write_failure(Config) ->
rpc:call(Node, logger_std_h, filesync, [?STANDARD_HANDLER]),
?check_no_log,
try_read_file(Log, {ok,<<"Logged1\nLogged2\n">>}, filesync_rep_int()),
- ok.
-write_failure(cleanup, _Config) ->
- Nodes = nodes(),
- [test_server:stop_node(Node) || Node <- Nodes].
+ peer:stop(Peer).
sync_failure(Config) ->
Dir = ?config(priv_dir, Config),
File = lists:concat([?MODULE,"_",?FUNCTION_NAME,".log"]),
Log = filename:join(Dir, File),
- Node = start_std_h_on_new_node(Config, Log),
+ {Peer, Node} = start_std_h_on_new_node(Config, Log),
false = (undefined == rpc:call(Node, ets, whereis, [?TEST_HOOKS_TAB])),
rpc:call(Node, ets, insert, [?TEST_HOOKS_TAB,{tester,self()}]),
rpc:call(Node, ?MODULE, set_internal_log, [?MODULE,internal_log]),
@@ -907,20 +905,17 @@ sync_failure(Config) ->
rpc:call(Node, ?MODULE, set_result, [file_datasync,ok]),
ok = log_on_remote_node(Node, "Logged2"),
?check_no_log,
- ok.
-sync_failure(cleanup, _Config) ->
- Nodes = nodes(),
- [test_server:stop_node(Node) || Node <- Nodes].
+ peer:stop(Peer).
start_std_h_on_new_node(Config, Log) ->
- {ok,_,Node} =
+ {ok,_,Peer,Node} =
logger_test_lib:setup(
Config,
[{logger,[{handler,default,logger_std_h,
#{ config => #{ type => {file,Log}}}}]}]),
ok = rpc:call(Node,logger,set_handler_config,[?STANDARD_HANDLER,formatter,
{?MODULE,nl}]),
- Node.
+ {Peer, Node}.
%% functions for test hook macros to be called by rpc
set_internal_log(_Mod, _Func) ->
@@ -1386,6 +1381,10 @@ handler_requests_under_load(cleanup, _Config) ->
recreate_deleted_log(Config) ->
{Log,_HConfig,_StdHConfig} =
start_handler(?MODULE, ?FUNCTION_NAME, Config),
+
+ %% Make sure that if we delete the directory it is created
+ [ok = file:del_dir_r(filename:dirname(Log)) || element(1,os:type()) =/= win32],
+
logger:notice("first",?domain),
logger_std_h:filesync(?MODULE),
ok = file:rename(Log,Log++".old"),
@@ -1393,6 +1392,7 @@ recreate_deleted_log(Config) ->
logger_std_h:filesync(?MODULE),
{ok,<<"first\n">>} = file:read_file(Log++".old"),
{ok,<<"second\n">>} = file:read_file(Log),
+
ok.
recreate_deleted_log(cleanup, _Config) ->
ok = stop_handler(?MODULE).
@@ -1507,6 +1507,48 @@ rotate_size_compressed(Config) ->
{error,enoent} = file:read_file_info(Log++".2"),
{error,enoent} = file:read_file_info(Log++".2.gz"),
+ case os:type() of
+ {unix,_} ->
+ %% Test that logging does not break when directory is deleted at rotation
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,50)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=1000}} = file:read_file_info(Log),
+ ok = file:del_dir_r(filename:dirname(Log)),
+ {error,enoent} = file:read_file_info(Log),
+ logger:notice("bbbb",?domain),
+ logger:notice("bbbb",?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=5}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {ok,#file_info{size=25}} = file:read_file_info(Log++".0.gz"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+ {error,enoent} = file:read_file_info(Log++".1.gz"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+ {error,enoent} = file:read_file_info(Log++".2.gz"),
+
+ %% Test that logging without sync does not break
+ %% when directory is deleted at rotation
+ ok = logger:update_handler_config(?MODULE, #{config=>#{ file_check => 10000 } }),
+ [logger:notice(Str,?domain) || _ <- lists:seq(1,49)],
+ [logger:notice("bbbb",?domain) || _ <- lists:seq(1,3)],
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=1000}} = file:read_file_info(Log),
+ ok = file:del_dir_r(filename:dirname(Log)),
+ {error,enoent} = file:read_file_info(Log),
+ logger:notice("bbbb",?domain),
+ logger:notice("bbbb",?domain),
+ logger_std_h:filesync(?MODULE),
+ {ok,#file_info{size=5}} = file:read_file_info(Log),
+ {error,enoent} = file:read_file_info(Log++".0"),
+ {error,enoent} = file:read_file_info(Log++".0.gz"),
+ {error,enoent} = file:read_file_info(Log++".1"),
+ {error,enoent} = file:read_file_info(Log++".1.gz"),
+ {error,enoent} = file:read_file_info(Log++".2"),
+ {error,enoent} = file:read_file_info(Log++".2.gz");
+ {win32,_} ->
+ ok
+ end,
+
ok.
rotate_size_compressed(cleanup,_Config) ->
ok = stop_handler(?MODULE).
@@ -1747,7 +1789,7 @@ rotation_opts_restart_handler(Config) ->
{ok,#file_info{size=260}} = file:read_file_info(Log),
[] = filelib:wildcard(Log++".*"),
- %% Stop/start handler and trun on rotation. Check that file is rotated.
+ %% Stop/start handler and turn on rotation. Check that file is rotated.
{ok,#{config:=StdHConfig2}=HConfig2} = logger:get_handler_config(?MODULE),
ok = logger:remove_handler(?MODULE),
ok = logger:add_handler(
@@ -1780,7 +1822,7 @@ rotation_opts_restart_handler(Config) ->
{ok,#file_info{size=29}} = file:read_file_info(Log++".0.gz"),
[_] = filelib:wildcard(Log++".*"),
- %% Stop/start handler and turn off compression. Check that achives
+ %% Stop/start handler and turn off compression. Check that archives
%% are decompressed.
{ok,#{config:=StdHConfig4}=HConfig4} = logger:get_handler_config(?MODULE),
ok = logger:remove_handler(?MODULE),
@@ -1837,8 +1879,9 @@ start_handler(Name, FuncName, Config) ->
{Log,HConfig,StdHConfig}.
get_handler_log_name(FuncName, Config) ->
- Dir = ?config(priv_dir,Config),
- filename:join(Dir, lists:concat([FuncName,".log"])).
+ filename:join([?config(priv_dir,Config),
+ FuncName,
+ lists:concat([FuncName,".log"])]).
filter_only_this_domain(Name) ->
[{remote_gl,{fun logger_filters:remote_gl/2,stop}},
@@ -2189,6 +2232,9 @@ tracer({trace,_,call,{Mod=logger_std_h,Func=write_to_dev,[Data,_]}},
maybe_tracer_done(Pid,Expected,{Mod,Func,Data});
tracer({trace,_,call,{Mod,Func,_}}, {Pid,[{Mod,Func}|Expected]}) ->
maybe_tracer_done(Pid,Expected,{Mod,Func});
+tracer({trace,_,call,{logger_h_common = Mod,handle_info = Func,[{timeout,_,Op},_S]}},
+ {Pid,[{Mod,Func,{timeout,Op}}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func});
tracer({trace,_,call,Call}, {Pid,Expected}) ->
ct:log("Tracer got unexpected: ~p~nExpected: ~p~n",[Call,Expected]),
Pid ! {tracer_got_unexpected,Call,Expected},
diff --git a/lib/kernel/test/logger_test_lib.erl b/lib/kernel/test/logger_test_lib.erl
index be4bc427fb..3bc23de422 100644
--- a/lib/kernel/test/logger_test_lib.erl
+++ b/lib/kernel/test/logger_test_lib.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,34 +20,29 @@
-module(logger_test_lib).
-include_lib("kernel/src/logger_internal.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([setup/2, log/3, sync_and_read/3]).
--export([init/2,
- pre_init_per_suite/3, pre_init_per_testcase/4,
- post_end_per_testcase/5, post_end_per_suite/3]).
-
setup(Config,Vars) ->
Postfix = case proplists:get_value(postfix, Config) of
undefined -> "";
P -> ["_",P]
end,
- FuncStr = lists:concat([proplists:get_value(suite, Config), "_",
- proplists:get_value(tc, Config)|
- Postfix]),
+ TestCase = proplists:get_value(tc, Config),
+ FuncStr = lists:concat([proplists:get_value(suite, Config), "_", TestCase | Postfix]),
ConfigFileName = filename:join(proplists:get_value(priv_dir, Config), FuncStr),
file:write_file(ConfigFileName ++ ".config", io_lib:format("[{kernel, ~p}].",[Vars])),
- Sname = lists:concat([proplists:get_value(tc,Config)|Postfix]),
- case test_server:start_node(Sname, slave,
- [{args, ["-pa ",filename:dirname(code:which(?MODULE)),
- " -boot start_sasl -kernel start_timer true "
- "-config ",ConfigFileName]}]) of
- {ok, Node} ->
- L = rpc:call(Node, logger, get_config, []),
- ct:log("~p",[L]),
- {ok, L, Node};
- {error, Reason} ->
- ct:log("Failed to start node: ~p",[Reason]),
+ Args = ["-boot", "start_sasl", "-kernel", "start_timer", "true", "-config", ConfigFileName],
+ try
+ {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(TestCase),
+ args => Args, connection => standard_io}),
+ L = rpc:call(Node, logger, get_config, []),
+ ct:log("~p",[L]),
+ {ok, L, Peer, Node}
+ catch
+ exit:{boot_failed, Reason} ->
+ ct:log("Failed to start node: ~p", [Reason]),
error
end.
@@ -63,26 +58,3 @@ sync_and_read(Node,disk_log,Log) ->
sync_and_read(Node, file,Log) ->
ok = rpc:call(Node,logger_std_h,filesync,[?STANDARD_HANDLER]),
file:read_file(Log).
-
-
-init(_, _) ->
- {ok, []}.
-
-pre_init_per_suite(_Suite, Config, State) ->
- {[{nodes, nodes()} | Config], State}.
-
-pre_init_per_testcase(Suite, TC, Config, State) ->
- cleanup(Config),
- {[{suite, Suite}, {tc, TC} | Config], State}.
-
-post_end_per_testcase(_, _TC, Config, Res, State) ->
- cleanup(Config),
- {Res, State}.
-
-post_end_per_suite(_, Config, State) ->
- cleanup(Config),
- {Config, State}.
-
-cleanup(Config) ->
- [test_server:stop_node(N) || N <- nodes(),
- not lists:member(N, proplists:get_value(nodes, Config))].
diff --git a/lib/kernel/test/loose_node.erl b/lib/kernel/test/loose_node.erl
deleted file mode 100644
index cc3f9bbea0..0000000000
--- a/lib/kernel/test/loose_node.erl
+++ /dev/null
@@ -1,202 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%%-------------------------------------------------------------------
-%%% File : loose_node.erl
-%%% Author : Rickard Green <rickard.s.green@ericsson.com>
-%%% Description : Creation of nodes which are not supervised by
-%%% the test_server. Currently needed by init_SUITE
-%%% and heart_SUITE (until the test_server can
-%%% handle node restart).
-%%%
-%%% Created : 22 Sep 2004 by Rickard Green <rickard.s.green@ericsson.com>
-%%%-------------------------------------------------------------------
--module(loose_node).
--author('rickard.s.green@ericsson.com').
-
-%%
-%% Exports
-%%
--export([start/3, start/2, stop/1]).
-
-%%
-%% Internal exports
-%%
--export([loose_node_started/1]).
-
-%%
-%% Exported functions for internal use.
-%%
-
-%%
-%% Defines
-%%
--define(L2A, list_to_atom).
--define(A2L, atom_to_list).
--define(I2L, integer_to_list).
-
-%%
-%% Exported functions.
-%%
-
-stop(Node) when is_atom(Node) ->
- erlang:monitor_node(Node, true),
- rpc:cast(Node, erlang, halt, []),
- receive
- {nodedown, Node} ->
- io:format("Stopped loose node ~p~n", [Node]),
- ok
- after 10000 ->
- io:format("Failed to stop loose node: ~p~n", [Node]),
- {error, node_not_stopped}
- end.
-
-start(Name, Args) ->
- start(Name, Args, -1).
-
-start(Name, Args, TimeOut) when is_atom(Name) ->
- start(atom_to_list(Name), Args, TimeOut);
-start(Name, Args, TimeOut)
- when is_list(Name), is_list(Args), is_integer(TimeOut) ->
- Parent = self(),
- Ref = make_ref(),
- Starter
- = fun () ->
- Erl = case init:get_argument(progname) of
- {ok,[[Prog]]} ->
- Prog;
- _ ->
- "erl"
- end,
- RegName = until_success(fun () ->
- {A, B, C} = now(),
- Reg =
- ?L2A(?A2L(?MODULE)
- ++ "-" ++ ?I2L(A)
- ++ "-" ++ ?I2L(B)
- ++ "-" ++ ?I2L(C)),
- true = register(Reg, self()),
- Reg
- end),
- NameCmd = case net_kernel:longnames() of
- true -> " -name " ++ Name;
- false -> " -sname " ++ Name
- end,
- Cookie = " -setcookie " ++ atom_to_list(auth:get_cookie()),
- Pa = " -pa " ++ filename:dirname(code:which(?MODULE)),
- ThisNode = node(),
- NodeStarted
- = " -run "
- ++ atom_to_list(?MODULE)
- ++ " loose_node_started "
- ++ atom_to_list(RegName)
- ++ " "
- ++ atom_to_list(ThisNode)
- ++ " "
- ++ integer_to_list(TimeOut),
- CrashDump =
- " -env ERL_CRASH_DUMP"
- ++ " erl_crash.dump.loose_node."
- ++ Name,
- Cmd =
- Erl
- ++ " -detached"
- ++ NameCmd
- ++ Cookie
- ++ Pa
- ++ NodeStarted
- ++ CrashDump
- ++ " "
- ++ Args,
- io:format("Trying to start loose node...~n"
- " --> ~p~n", [Cmd]),
- Res = case open_port({spawn, Cmd}, []) of
- P when is_port(P) ->
- receive
- {loose_node_started,
- Node,
- {RegName, ThisNode}} ->
- io:format("Loose node ~p started.~n",
- [Node]),
- {ok, Node}
- after 10000 ->
- io:format("Start of loose node ~p "
- "timed out.", [Name]),
- {error, timeout}
- end;
- _ ->
- io:format("Start of loose node ~p failed.",
- [Name]),
- {error, open_port_failed}
- end,
- Parent ! {Ref, Res}
- end,
- spawn_opt(Starter, [link, {priority, max}]),
- receive
- {Ref, Result} ->
- Result
- end.
-
-
-%%
-%% Exported functions for internal use.
-%%
-
-loose_node_started([Name, Node, TimeOutSecs]) when is_list(Name),
- is_list(Node),
- is_list(TimeOutSecs) ->
- spawn_opt(fun () ->
- process_flag(trap_exit, true),
- Proc = {list_to_atom(Name), list_to_atom(Node)},
- Timeout = case catch list_to_integer(TimeOutSecs) of
- I when is_integer(I), I >= 0 -> I*1000;
- _ -> infinity
- end,
- wait_until(fun () -> is_alive() end),
- Proc ! {loose_node_started, node(), Proc},
- receive
- after Timeout ->
- timeout
- end,
- erlang:halt("Loose node timeout")
- end,
- [{priority, max}]),
- ok.
-
-%%
-%% Internal functions.
-%%
-
-until_success(Fun) ->
- case catch Fun() of
- {'EXIT', _} -> until_success(Fun);
- Res -> Res
- end.
-
-wait_until(Fun) ->
- case Fun() of
- true -> true;
- _ ->
- receive
- after 100 ->
- wait_until(Fun)
- end
- end.
-
diff --git a/lib/kernel/test/net_SUITE.erl b/lib/kernel/test/net_SUITE.erl
index 5e6ee054f7..9c18b3f261 100644
--- a/lib/kernel/test/net_SUITE.erl
+++ b/lib/kernel/test/net_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
+-include("kernel_test_lib.hrl").
%% Suite exports
-export([suite/0, all/0, groups/0]).
@@ -51,30 +52,28 @@
api_b_getifaddrs/1,
api_b_name_and_addr_info/1,
- api_b_name_and_index/1
+ api_b_name_and_index/1,
- %% Tickets
- ]).
+ %% *** API Misc ***
+ api_m_getaddrinfo_v4/0,
+ api_m_getaddrinfo_v4/1,
+ api_m_getaddrinfo_v6/0,
+ api_m_getaddrinfo_v6/1,
+ api_m_getnameinfo_v4/0,
+ api_m_getnameinfo_v4/1,
+ api_m_getnameinfo_v6/0,
+ api_m_getnameinfo_v6/1
-%% -include("socket_test_evaluator.hrl").
-
-%% Internal exports
-%% -export([]).
+ %% Tickets
+ ]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--define(SLEEP(T), receive after T -> ok end).
-
-define(FAIL(R), exit(R)).
-define(SKIP(R), throw({skip, R})).
--define(MINS(M), timer:minutes(M)).
--define(SECS(S), timer:seconds(S)).
-
--define(TT(T), ct:timetrap(T)).
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -106,14 +105,16 @@ use_group(Group, Env, Default) ->
groups() ->
[{api, [], api_cases()},
- {api_basic, [], api_basic_cases()}
+ {api_basic, [], api_basic_cases()},
+ {api_misc, [], api_misc_cases()}
%% {tickets, [], ticket_cases()}
].
api_cases() ->
[
- {group, api_basic}
+ {group, api_basic},
+ {group, api_misc}
].
api_basic_cases() ->
@@ -124,6 +125,14 @@ api_basic_cases() ->
api_b_name_and_index
].
+api_misc_cases() ->
+ [
+ api_m_getaddrinfo_v4,
+ api_m_getaddrinfo_v6,
+ api_m_getnameinfo_v4,
+ api_m_getnameinfo_v6
+ ].
+
%% ticket_cases() ->
%% [].
@@ -131,19 +140,50 @@ api_basic_cases() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init_per_suite(Config) ->
+init_per_suite(Config0) ->
+
+ ?P("init_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n Nodes: ~p", [Config0, erlang:nodes()]),
+
try net:info() of
#{} ->
- %% ?LOGGER:start(),
- Config
+
+ case ?LIB:init_per_suite(Config0) of
+ {skip, _} = SKIP ->
+ SKIP;
+
+ Config1 when is_list(Config1) ->
+
+ ?P("init_per_suite -> end when "
+ "~n Config: ~p", [Config1]),
+
+ %% We need a monitor on this node also
+ kernel_test_sys_monitor:start(),
+
+ Config1
+ end
+
catch
error : notsup ->
- {skip, "esock not supported"}
+ {skip, "net not supported"}
end.
-end_per_suite(_) ->
- %% ?LOGGER:stop(),
- ok.
+end_per_suite(Config0) ->
+
+ ?P("end_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n Nodes: ~p", [Config0, erlang:nodes()]),
+
+ %% Stop the local monitor
+ kernel_test_sys_monitor:stop(),
+
+ Config1 = ?LIB:end_per_suite(Config0),
+
+ ?P("end_per_suite -> "
+ "~n Nodes: ~p", [erlang:nodes()]),
+
+ Config1.
init_per_group(_Group, Config) ->
Config.
@@ -188,6 +228,9 @@ api_b_gethostname() ->
{ok, Hostname} ->
i("hostname: ~s", [Hostname]),
ok;
+ {error, enotsup = Reason} ->
+ i("gethostname not supported - skipping"),
+ skip(Reason);
{error, Reason} ->
?FAIL(Reason)
end.
@@ -210,7 +253,7 @@ api_b_getifaddrs(_Config) when is_list(_Config) ->
api_b_getifaddrs() ->
- case net:getifaddrs() of
+ try net:getifaddrs() of
{ok, IfAddrs} ->
i("IfAddrs: "
"~n ~p", [IfAddrs]),
@@ -220,9 +263,73 @@ api_b_getifaddrs() ->
skip(Reason);
{error, Reason} ->
?FAIL(Reason)
+ catch
+ error : notsup = CReason ->
+ Fun = fun(F) when is_function(F, 0) ->
+ try F()
+ catch C:E:S -> {catched, {C, E, S}}
+ end
+ end,
+ Res2Str = fun({ok, Res}) -> ?F("ok: ~p", [Res]);
+ ({error, Reason}) -> ?F("error: ~p", [Reason]);
+ ({catched, {C, E}}) -> ?F("catched: ~w, ~p", [C, E])
+ end,
+ IIRes = Fun(fun() -> prim_net:get_interface_info(#{}) end),
+ ATRes = Fun(fun() -> prim_net:get_ip_address_table(#{}) end),
+ AARes = Fun(fun() -> prim_net:get_adapters_addresses(#{}) end),
+ IIResStr = Res2Str(IIRes),
+ ATResStr = Res2Str(ATRes),
+ IFERes = win_getifaddrs_ife(IIRes, ATRes),
+ AAResStr = Res2Str(AARes),
+ %% Note that the prim_net module is *not* intended to
+ %% be called directly. This is just a temporary thing.
+ i("~w => skipping"
+ "~n Interface Info: "
+ "~n ~s"
+ "~n IP Address Table: "
+ "~n ~s"
+ "~n MIB If Table: "
+ "~n ~p"
+ "~n Adapters Addresses: "
+ "~n ~p",
+ [CReason, IIResStr, ATResStr, IFERes, AAResStr]),
+ skip(CReason)
end.
+win_getifaddrs_ife({ok, II}, {ok, AT}) ->
+ IDX1 = [IDX || #{index := IDX} <- II],
+ IDX2 = [IDX || #{index := IDX} <- AT],
+ MergedIDX = merge(IDX1, IDX2),
+ MibIfTable =
+ [try prim_net:get_if_entry(#{index => IDX}) of
+ {ok, Entry} ->
+ Entry;
+ {error, _} = ERROR ->
+ {IDX, ERROR}
+ catch
+ %% This is *very* unlikely since we got here because of
+ %% a previous 'notsup'. But just in case...
+ error : notsup = CReason ->
+ {IDX, CReason};
+ C:E ->
+ {IDX, {C, E}}
+ end || IDX <- MergedIDX],
+ MibIfTable;
+win_getifaddrs_ife(_, _) ->
+ undefined.
+
+merge([], L) ->
+ lists:sort(L);
+merge([H|T], L) ->
+ case lists:member(H, L) of
+ true ->
+ merge(T, L);
+ false ->
+ merge(T, [H|L])
+ end.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Get name and address info.
@@ -242,33 +349,45 @@ api_b_name_and_addr_info() ->
Domain = inet,
Addr = which_local_addr(Domain),
SA = #{family => Domain, addr => Addr},
- Hostname =
- case net:getnameinfo(SA) of
- {ok, #{host := Name, service := Service} = NameInfo}
- when is_list(Name) andalso is_list(Service) ->
- i("getnameinfo: "
- "~n ~p", [NameInfo]),
- Name;
- {ok, BadNameInfo} ->
- ?FAIL({getnameinfo, SA, BadNameInfo});
- {error, enotsup = ReasonNI} ->
- i("getnameinfo not supported - skipping"),
- ?SKIP({getnameinfo, ReasonNI});
- {error, Reason1} ->
- ?FAIL({getnameinfo, SA, Reason1})
- end,
- case net:getaddrinfo(Hostname) of
- {ok, AddrInfos} when is_list(AddrInfos) ->
- i("getaddrinfo: "
- "~n ~p", [AddrInfos]),
- verify_addr_info(AddrInfos, Domain);
- {ok, BadAddrInfo} ->
- ?FAIL({getaddrinfo, Hostname, BadAddrInfo});
- {error, enotsup = ReasonAI} ->
- i("getaddrinfo not supported - skipping"),
- ?SKIP({getaddrinfo, ReasonAI});
- {error, Reason2} ->
- ?FAIL({getaddrinfo, Hostname, Reason2})
+ try
+ begin
+ i("try getnameinfo for"
+ "~n ~p", [SA]),
+ Hostname =
+ case net:getnameinfo(SA) of
+ {ok, #{host := Name, service := Service} = NameInfo}
+ when is_list(Name) andalso is_list(Service) ->
+ i("getnameinfo: "
+ "~n ~p", [NameInfo]),
+ Name;
+ {ok, BadNameInfo} ->
+ ?FAIL({getnameinfo, SA, BadNameInfo});
+ {error, enotsup = ReasonNI} ->
+ i("getnameinfo not supported - skipping"),
+ ?SKIP({getnameinfo, ReasonNI});
+ {error, Reason1} ->
+ ?FAIL({getnameinfo, SA, Reason1})
+ end,
+ i("try getaddrinfo for"
+ "~n ~p", [Hostname]),
+ case net:getaddrinfo(Hostname) of
+ {ok, AddrInfos} when is_list(AddrInfos) ->
+ i("getaddrinfo: "
+ "~n ~p", [AddrInfos]),
+ verify_addr_info(AddrInfos, Domain);
+ {ok, BadAddrInfo} ->
+ ?FAIL({getaddrinfo, Hostname, BadAddrInfo});
+ {error, enotsup = ReasonAI} ->
+ i("getaddrinfo not supported - skipping"),
+ ?SKIP({getaddrinfo, ReasonAI});
+ {error, Reason2} ->
+ ?FAIL({getaddrinfo, Hostname, Reason2})
+ end
+ end
+ catch
+ error : notsup = Reason ->
+ i("~w => skipping", [Reason]),
+ skip(Reason)
end.
@@ -315,17 +434,26 @@ api_b_name_and_index(_Config) when is_list(_Config) ->
api_b_name_and_index() ->
- Names =
- case net:if_names() of
- {ok, N} when is_list(N) andalso (N =/= []) ->
- N;
- {error, enotsup = Reason} ->
- i("if_names not supported - skipping"),
- ?SKIP({if_names, Reason});
- {error, Reason} ->
- ?FAIL({if_names, Reason})
- end,
- verify_if_names(Names).
+ try
+ begin
+ Names =
+ case net:if_names() of
+ {ok, N} when is_list(N) andalso (N =/= []) ->
+ N;
+ {error, enotsup = Reason} ->
+ i("if_names not supported - skipping"),
+ ?SKIP({if_names, Reason});
+ {error, Reason} ->
+ ?FAIL({if_names, Reason})
+ end,
+ verify_if_names(Names)
+ end
+ catch
+ error : notsup = CReason ->
+ i("~w => skipping", [CReason]),
+ skip(CReason)
+ end.
+
verify_if_names([]) ->
ok;
@@ -355,68 +483,269 @@ verify_if_names([{Index, Name}|T]) ->
verify_if_names(T).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+api_m_getaddrinfo_v4() ->
+ required(v4).
+
+api_m_getaddrinfo_v4(suite) ->
+ [];
+api_m_getaddrinfo_v4(doc) ->
+ [];
+api_m_getaddrinfo_v4(Config) when is_list(Config) ->
+ ?TT(?SECS(5)),
+ Pre = fun() ->
+ {Name, FullName, IPStr, IP, Aliases,_,_} =
+ ct:get_config(test_host_ipv4_only),
+ #{name => Name,
+ full_name => FullName,
+ ip_string => IPStr,
+ ip => IP,
+ aliases => Aliases,
+ family => inet}
+ end,
+ Case = fun(Info) ->
+ ok = api_m_getaddrinfo(Info)
+ end,
+ Post = fun(_) -> ok end,
+ tc_try(?FUNCTION_NAME,
+ Pre, Case, Post).
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This gets the local address (not 127.0...)
-%% We should really implement this using the (new) net module,
-%% but until that gets the necessary functionality...
-which_local_addr(Domain) ->
- case inet:getifaddrs() of
- {ok, IFL} ->
- which_addr(Domain, IFL);
+api_m_getaddrinfo_v6() ->
+ required(v6).
+
+api_m_getaddrinfo_v6(suite) ->
+ [];
+api_m_getaddrinfo_v6(doc) ->
+ [];
+api_m_getaddrinfo_v6(Config) when is_list(Config) ->
+ ?TT(?SECS(5)),
+ Pre = fun() ->
+ {Name, FullName, IPStr, IP, Aliases} =
+ ct:get_config(test_host_ipv6_only),
+ #{name => Name,
+ full_name => FullName,
+ ip_string => IPStr,
+ ip => IP,
+ aliases => Aliases,
+ family => inet6}
+ end,
+ Case = fun(Info) ->
+ ok = api_m_getaddrinfo(Info)
+ end,
+ Post = fun(_) -> ok end,
+ tc_try(?FUNCTION_NAME,
+ Pre, Case, Post).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+api_m_getaddrinfo(#{name := Name,
+ family := Domain,
+ ip := IP}) ->
+ i("Check address info for ~p with"
+ "~n Domain: ~p"
+ "~n IP: ~p", [Name, Domain, IP]),
+ try net:getaddrinfo(Name) of
+ {ok, AddrInfos} ->
+ %% Check that we can actually find this IP in the list
+ api_m_getaddrinfo_verify(AddrInfos, Name, Domain, IP);
+ {error, enotsup = ReasonAI} ->
+ i("getaddrinfo not supported - skipping"),
+ ?SKIP({getaddrinfo, ReasonAI});
{error, Reason} ->
- ?FAIL({inet, getifaddrs, Reason})
+ ?FAIL({gethaddrinfo, Name, Reason})
+ catch
+ error : notsup = Reason ->
+ i("~w => skipping", [Reason]),
+ skip(Reason)
end.
-which_addr(_Domain, []) ->
- skip(no_address);
-which_addr(Domain, [{"lo" ++ _, _}|IFL]) ->
- which_addr(Domain, IFL);
-which_addr(Domain, [{_Name, IFO}|IFL]) ->
- case which_addr2(Domain, IFO) of
- {ok, Addr} ->
- Addr;
- {error, no_address} ->
- which_addr(Domain, IFL)
- end;
-which_addr(Domain, [_|IFL]) ->
- which_addr(Domain, IFL).
-which_addr2(_Domain, []) ->
- {error, no_address};
-which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 4) ->
- {ok, Addr};
-which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 8) ->
- {ok, Addr};
-which_addr2(Domain, [_|IFO]) ->
- which_addr2(Domain, IFO).
+%% First we filter out the address info of the correct domain (family), then:
+%% 1) If there is no address info left: SKIP
+%% 2) If there are address info, check for the selected address
+
+api_m_getaddrinfo_verify(AddrInfos, Name, Domain, IP) ->
+ i("Attempt to verify from ~w address-infos", [length(AddrInfos)]),
+ AddrInfos2 = [AI || #{family := D} = AI <- AddrInfos, D =:= Domain],
+ case AddrInfos2 of
+ [] ->
+ i("No address info of correct domain (~w) available", [Domain]),
+ ?SKIP({no_ai_of_domain, Domain});
+ _ ->
+ api_m_getaddrinfo_verify2(AddrInfos, Name, Domain, IP)
+ end.
+api_m_getaddrinfo_verify2([], Name, Domain, IP) ->
+ i("No match found for ~p: "
+ "~n Domain: ~p"
+ "~n IP: ~p", [Name, Domain, IP]),
+ ?FAIL({not_found, Name, Domain, IP});
+api_m_getaddrinfo_verify2([#{family := Domain,
+ addr := #{addr := IP,
+ family := Domain} = _SockAddr} =
+ AddrInfo|_],
+ Name, Domain, IP) ->
+ i("Found match for ~p: "
+ "~n AddrInfo: ~p"
+ "~n Domain: ~p"
+ "~n IP: ~p", [Name, AddrInfo, Domain, IP]),
+ ok;
+api_m_getaddrinfo_verify2([AddrInfo|AddrInfos], Name, Domain, IP) ->
+ i("No match: "
+ "~n AddrInfo: ~p"
+ "~n Domain: ~p"
+ "~n IP: ~p", [AddrInfo, Domain, IP]),
+ api_m_getaddrinfo_verify2(AddrInfos, Name, Domain, IP).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-not_yet_implemented() ->
- skip("not yet implemented").
+api_m_getnameinfo_v4() ->
+ required(v4).
+
+api_m_getnameinfo_v4(suite) ->
+ [];
+api_m_getnameinfo_v4(doc) ->
+ [];
+api_m_getnameinfo_v4(Config) when is_list(Config) ->
+ ?TT(?SECS(5)),
+ Pre = fun() ->
+ {Name, FullName, IPStr, IP, Aliases,_,_} =
+ ct:get_config(test_host_ipv4_only),
+ #{name => Name,
+ full_name => FullName,
+ ip_string => IPStr,
+ ip => IP,
+ aliases => Aliases,
+ family => inet}
+ end,
+ Case = fun(Info) ->
+ ok = api_m_getnameinfo(Info)
+ end,
+ Post = fun(_) -> ok end,
+ tc_try(?FUNCTION_NAME,
+ Pre, Case, Post).
-skip(Reason) ->
- throw({skip, Reason}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% t() ->
-%% os:timestamp().
+api_m_getnameinfo_v6() ->
+ required(v6).
+api_m_getnameinfo_v6(suite) ->
+ [];
+api_m_getnameinfo_v6(doc) ->
+ [];
+api_m_getnameinfo_v6(Config) when is_list(Config) ->
+ ?TT(?SECS(5)),
+ Pre = fun() ->
+ {Name, FullName, IPStr, IP, Aliases} =
+ ct:get_config(test_host_ipv6_only),
+ #{name => Name,
+ full_name => FullName,
+ ip_string => IPStr,
+ ip => IP,
+ aliases => Aliases,
+ family => inet6}
+ end,
+ Case = fun(Info) ->
+ ok = api_m_getnameinfo(Info)
+ end,
+ Post = fun(_) -> ok end,
+ tc_try(?FUNCTION_NAME,
+ Pre, Case, Post).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% tdiff({A1, B1, C1} = _T1x, {A2, B2, C2} = _T2x) ->
-%% T1 = A1*1000000000+B1*1000+(C1 div 1000),
-%% T2 = A2*1000000000+B2*1000+(C2 div 1000),
-%% T2 - T1.
+api_m_getnameinfo(#{name := Name,
+ full_name := FName,
+ family := Domain,
+ ip := IP}) ->
+ i("Check name info for ~p with"
+ "~n Domain: ~p"
+ "~n IP: ~p", [Name, Domain, IP]),
+ SA = #{family => Domain,
+ addr => IP},
+ try net:getnameinfo(SA) of
+ {ok, NameInfo} ->
+ %% Check that we can actually find this IP in the list
+ api_m_getnameinfo_verify(NameInfo, Name, FName, IP);
+ {error, enotsup = ReasonAI} ->
+ i("getaddrinfo not supported - skipping"),
+ ?SKIP({getnameinfo, ReasonAI});
+ {error, Reason} ->
+ ?FAIL({getnameinfo, Name, Reason})
+ catch
+ error : notsup = Reason ->
+ i("~w => skipping", [Reason]),
+ skip(Reason)
+ end.
+
+
+api_m_getnameinfo_verify(#{host := Name} = NameInfo, Name, _FName, _IP) ->
+ i("Found (name) match for ~p: "
+ "~n NameInfo: ~p", [Name, NameInfo]),
+ ok;
+api_m_getnameinfo_verify(#{host := FName} = NameInfo, _Name, FName, _IP) ->
+ i("Found (full name) match for ~p: "
+ "~n NameInfo: ~p", [FName, NameInfo]),
+ ok;
+api_m_getnameinfo_verify(#{host := IPStr} = NameInfo, Name, FName, IP)
+ when (size(IP) =:= 8) ->
+ %% On some hosts we get back the IPv6 address as a string.
+ %% Exampole:
+ %% {65216,0,0,0,2560,8447,65202,46249} -> "fec0::a00:20ff:feb2:b4a9"
+ %% This is possibly because of bad config of the host.
+ case inet_parse:ipv6_address(IPStr) of
+ {ok, IP} ->
+ i("Found (IP string) \"match\" for ~p: "
+ "~n NameInfo: ~p", [IP, NameInfo]),
+ ok;
+ _ ->
+ ?FAIL({not_found, NameInfo, Name, FName})
+ end;
+api_m_getnameinfo_verify(NameInfo, Name, FName, _IP) ->
+ i("No match found for ~p (~p): "
+ "~n NameInfo: ~p", [Name, FName, NameInfo]),
+ ?FAIL({not_found, NameInfo, Name, FName}).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% This gets the local address (not 127.0...)
+%% We should really implement this using the (new) net module,
+%% but until that gets the necessary functionality...
+which_local_addr(Domain) ->
+ case ?LIB:which_local_addr(Domain) of
+ {ok, Addr} ->
+ Addr;
+ {error, _} = ERROR ->
+ skip(ERROR)
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% not_yet_implemented() ->
+%% skip("not yet implemented").
+
+skip(Reason) ->
+ throw({skip, Reason}).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
formated_timestamp() ->
format_timestamp(os:timestamp()).
@@ -433,66 +762,22 @@ format_timestamp({_N1, _N2, _N3} = TS) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-set_tc_name(N) when is_atom(N) ->
- set_tc_name(atom_to_list(N));
-set_tc_name(N) when is_list(N) ->
- put(tc_name, N).
+tc_try(Case, TC) ->
+ ?TC_TRY(Case, TC).
-%% get_tc_name() ->
-%% get(tc_name).
+tc_try(Case, Pre, TC, Post) ->
+ ?TC_TRY(Case, Pre, TC, Post).
-tc_begin(TC) ->
- set_tc_name(TC),
- tc_print("begin ***",
- "~n----------------------------------------------------~n", "").
-
-tc_end(Result) when is_list(Result) ->
- tc_print("done: ~s", [Result],
- "", "----------------------------------------------------~n~n"),
- ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-tc_try(Case, Fun) when is_atom(Case) andalso is_function(Fun, 0) ->
- tc_begin(Case),
- try
- begin
- Fun(),
- ?SLEEP(?SECS(1)),
- tc_end("ok")
- end
- catch
- throw:{skip, _} = SKIP ->
- tc_end("skipping"),
- SKIP;
- Class:Error:Stack ->
- tc_end("failed"),
- erlang:raise(Class, Error, Stack)
- end.
+%% Required configuration
+required(v4) ->
+ [{require, test_host_ipv4_only}];
+required(v6) ->
+ [{require, test_host_ipv6_only}].
-tc_print(F, Before, After) ->
- tc_print(F, [], Before, After).
-
-tc_print(F, A, Before, After) ->
- Name = tc_which_name(),
- FStr = f("*** [~s][~s][~p] " ++ F ++ "~n",
- [formated_timestamp(),Name,self()|A]),
- io:format(user, Before ++ FStr ++ After, []).
-
-tc_which_name() ->
- case get(tc_name) of
- undefined ->
- case get(sname) of
- undefined ->
- "";
- SName when is_list(SName) ->
- SName
- end;
- Name when is_list(Name) ->
- Name
- end.
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% l2a(S) when is_list(S) ->
diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl
index a84acf3b34..01b76d83df 100644
--- a/lib/kernel/test/os_SUITE.erl
+++ b/lib/kernel/test/os_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -337,7 +337,7 @@ close_stdin(Config) ->
DataDir = proplists:get_value(data_dir, Config),
Fds = filename:join(DataDir, "my_fds"),
- "-1" = os:cmd(Fds).
+ "0" = os:cmd(Fds).
max_size_command(_Config) ->
WSL = case os:getenv("WSLENV") of
@@ -396,10 +396,48 @@ do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters) ->
do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters-1)
end.
-error_info(_Config) ->
- L = [{cmd, [{no,string}]},
+error_info(Config) ->
+
+
+ ExhaustFDs =
+ fun(M,F,A) ->
+ case os:type() of
+ {unix, _} ->
+ {ok, Peer, Node} = ?CT_PEER(),
+ FN = filename:join(
+ proplists:get_value(priv_dir, Config),
+ "error_info"),
+ try
+ erpc:call(
+ Node,
+ fun() ->
+ io:format("Starting to open files..."),
+ (fun FDs(N) ->
+ case file:open(FN, [write]) of
+ {ok, _ } -> FDs(N+1);
+ {error, _} ->
+ io:format("Opened ~p files",[N])
+ end
+ end)(0),
+ apply(M,F,A)
+ end)
+ catch error:{exception, ErrorReason, StackTrace} ->
+ erlang:raise(error, ErrorReason, StackTrace)
+ after
+ peer:stop(Peer)
+ end;
+ _ ->
+ apply(M,F,A)
+ end
+ end,
+
+ L = [{cmd, [{no, string}]},
+ {cmd, [["echo 1",0,0,0,1]]},
{cmd, [{no, string}, #{}]},
{cmd, [{no, string}, no_map]},
+ {cmd, ["echo 1"], [{general, "too many open files \\(emfile\\)"},
+ {wrapper, ExhaustFDs}] ++
+ [no_fail || win32 =:= element(1, os:type())]},
{find_executable, 1}, %Not a BIF.
{find_executable, 2}, %Not a BIF.
@@ -416,7 +454,7 @@ error_info(_Config) ->
{perf_counter,[bad_time_unit]},
- {putenv, [<<"bad_key">>, <<"bad_value">>]},
+ {putenv, [<<"bad_key">>, <<"bad_value">>],[{1,".*"},{2,".*"}]},
{putenv, ["key", <<"bad_value">>]},
{putenv, [<<"bad_key">>, "value"]},
{putenv, ["abc=", "xyz"]},
@@ -424,7 +462,7 @@ error_info(_Config) ->
{set_signal, [{bad,signal}, ignore]},
{set_signal, [{bad,signal}, ignore]},
{set_signal, [bad_signal, bad_handling]},
- {set_signal, [{bad,signal}, bad_handling]},
+ {set_signal, [{bad,signal}, bad_handling],[{1,".*"},{2,".*"}]},
{system_time, [bad_time_unit]},
{unsetenv, [{bad,key}]}
diff --git a/lib/kernel/test/os_SUITE_data/my_fds.c b/lib/kernel/test/os_SUITE_data/my_fds.c
index 8b1ce13822..dedb113c70 100644
--- a/lib/kernel/test/os_SUITE_data/my_fds.c
+++ b/lib/kernel/test/os_SUITE_data/my_fds.c
@@ -7,7 +7,12 @@
int
main(int argc, char** argv)
{
+#if defined (__WIN32__)
+ printf("Windows");
+#else
char buff[1];
- int res = read(stdin, buff, 1);
+ int res = read(STDIN_FILENO, buff, 1);
printf("%d", res);
+#endif
+ return 0;
}
diff --git a/lib/kernel/test/pg_SUITE.erl b/lib/kernel/test/pg_SUITE.erl
index 9c84e51c43..d563209267 100644
--- a/lib/kernel/test/pg_SUITE.erl
+++ b/lib/kernel/test/pg_SUITE.erl
@@ -25,10 +25,10 @@
suite/0,
all/0,
groups/0,
- init_per_suite/1,
- end_per_suite/1,
init_per_testcase/2,
end_per_testcase/2,
+ init_per_group/2,
+ end_per_group/2,
stop_proc/1,
ensure_peers_info/2
]).
@@ -56,12 +56,10 @@
missing_scope_join/1,
disconnected_start/1,
forced_sync/0, forced_sync/1,
- group_leave/1
-]).
-
--export([
- control/1,
- controller/3
+ group_leave/1,
+ monitor_nonempty_scope/0, monitor_nonempty_scope/1,
+ monitor_scope/0, monitor_scope/1,
+ monitor/1
]).
-include_lib("common_test/include/ct.hrl").
@@ -70,42 +68,50 @@
suite() ->
[{timetrap, {seconds, 60}}].
-init_per_suite(Config) ->
- case erlang:is_alive() of
- false ->
- %% verify epmd running (otherwise next call fails)
- (erl_epmd:names("localhost") =:= {error, address}) andalso ([] = os:cmd("epmd -daemon")),
- %% start a random node name
- NodeName = list_to_atom(lists:concat([atom_to_list(?MODULE), "_", os:getpid()])),
- {ok, Pid} = net_kernel:start([NodeName, shortnames]),
- [{distribution, Pid} | Config];
- true ->
- Config
- end.
-
-end_per_suite(Config) ->
- is_pid(proplists:get_value(distribution, Config)) andalso net_kernel:stop().
-
init_per_testcase(TestCase, Config) ->
- {ok, _Pid} = pg:start_link(TestCase),
- Config.
+ {ok, Pid} = pg:start_link(TestCase),
+ trace_start(TestCase, Config, Pid).
-end_per_testcase(TestCase, _Config) ->
+end_per_testcase(TestCase, Config) ->
gen_server:stop(TestCase),
+ trace_end(Config),
ok.
all() ->
- [dyn_distribution, {group, basic}, {group, cluster}, {group, performance}].
+ [dyn_distribution,
+ {group, basic},
+ {group, cluster},
+ {group, performance},
+ {group, monitor},
+ {group, old_release}].
groups() ->
[
{basic, [parallel], [errors, pg, leave_exit_race, single, overlay_missing]},
- {performance, [sequential], [thundering_herd]},
+ {performance, [], [thundering_herd]},
{cluster, [parallel], [process_owner_check, two, initial, netsplit, trisplit, foursplit,
exchange, nolocal, double, scope_restart, missing_scope_join, empty_group_by_remote_leave,
- disconnected_start, forced_sync, group_leave]}
+ disconnected_start, forced_sync, group_leave]},
+ {monitor, [parallel], [monitor_nonempty_scope, monitor_scope, monitor]},
+ {old_release, [parallel], [process_owner_check, two, overlay_missing,
+ empty_group_by_remote_leave, initial, netsplit,
+ nolocal]}
].
+init_per_group(old_release, Config) ->
+ PrevRel = integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 1),
+ case test_server:is_release_available(PrevRel) of
+ true ->
+ [{otp_release, PrevRel} | Config];
+ false ->
+ {skip, "No OTP "++PrevRel++" release found"}
+ end;
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_,_) -> ok.
+
+
%%--------------------------------------------------------------------
%% TEST CASES
@@ -132,7 +138,7 @@ errors(_Config) ->
?assertException(error, badarg, pg:handle_cast(garbage, garbage)),
%% kill with call
{ok, _Pid} = pg:start(second),
- ?assertException(exit, {{badarg, _}, _}, gen_server:call(second, garbage, 100)).
+ ?assertException(exit, {{badarg, _}, _}, gen_server:call(second, garbage, infinity)).
leave_exit_race() ->
[{doc, "Tests that pg correctly handles situation when leave and 'DOWN' messages are both in pg queue"}].
@@ -196,10 +202,10 @@ process_owner_check() ->
[{doc, "Tests that process owner is local node"}].
process_owner_check(Config) when is_list(Config) ->
- {TwoPeer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
%% spawn remote process
LocalPid = erlang:spawn(forever()),
- RemotePid = erlang:spawn(TwoPeer, forever()),
+ RemotePid = spawn_sleeper_at(Node),
%% check they can't be joined locally
?assertException(error, {nolocal, _}, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid)),
?assertException(error, {nolocal, _}, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, [RemotePid, RemotePid])),
@@ -208,19 +214,19 @@ process_owner_check(Config) when is_list(Config) ->
?assertException(error, function_clause, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, undefined)),
?assertException(error, {nolocal, _}, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, [undefined])),
%% stop the peer
- stop_node(TwoPeer, Socket),
+ peer:stop(Peer),
ok.
overlay_missing() ->
[{doc, "Tests that scope process that is not a part of overlay network does not change state"}].
-overlay_missing(_Config) ->
- {TwoPeer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
+overlay_missing(Config) ->
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
%% join self (sanity check)
?assertEqual(ok, pg:join(?FUNCTION_NAME, group, self())),
%% remember pid from remote
- PgPid = rpc:call(TwoPeer, erlang, whereis, [?FUNCTION_NAME]),
- RemotePid = erlang:spawn(TwoPeer, forever()),
+ PgPid = rpc:call(Node, erlang, whereis, [?FUNCTION_NAME]),
+ RemotePid = spawn_sleeper_at(Node),
%% stop remote scope
gen_server:stop(PgPid),
%% craft white-box request: ensure it's rejected
@@ -241,34 +247,37 @@ overlay_missing(_Config) ->
%?assertException(error, function_clause, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, undefined)),
%?assertException(error, {nolocal, _}, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, [undefined])),
%% stop the peer
- stop_node(TwoPeer, Socket).
+ peer:stop(Peer).
two(Config) when is_list(Config) ->
- {TwoPeer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
Pid = erlang:spawn(forever()),
?assertEqual(ok, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, Pid)),
?assertEqual([Pid], pg:get_local_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- %% first RPC must be serialised
- sync({?FUNCTION_NAME, TwoPeer}),
- ?assertEqual([Pid], rpc:call(TwoPeer, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
- ?assertEqual([], rpc:call(TwoPeer, pg, get_local_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ %% first RPC must be serialised 3 times
+ sync({?FUNCTION_NAME, Node}),
+ sync(?FUNCTION_NAME),
+ sync({?FUNCTION_NAME, Node}),
+ ?assertEqual([Pid], rpc:call(Node, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ ?assertEqual([], rpc:call(Node, pg, get_local_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
stop_proc(Pid),
%% again, must be serialised
sync(?FUNCTION_NAME),
+ sync({?FUNCTION_NAME, Node}),
?assertEqual([], pg:get_local_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- ?assertEqual([], rpc:call(TwoPeer, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ ?assertEqual([], rpc:call(Node, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
- Pid2 = erlang:spawn(TwoPeer, forever()),
- Pid3 = erlang:spawn(TwoPeer, forever()),
- ?assertEqual(ok, rpc:call(TwoPeer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pid2])),
- ?assertEqual(ok, rpc:call(TwoPeer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pid3])),
+ Pid2 = spawn_sleeper_at(Node),
+ Pid3 = spawn_sleeper_at(Node),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pid2])),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pid3])),
%% serialise through the *other* node
- sync({?FUNCTION_NAME, TwoPeer}),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
?assertEqual(lists:sort([Pid2, Pid3]),
lists:sort(pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
%% stop the peer
- stop_node(TwoPeer, Socket),
+ peer:stop(Peer),
%% hope that 'nodedown' comes before we route our request
sync(?FUNCTION_NAME),
ok.
@@ -277,35 +286,35 @@ empty_group_by_remote_leave() ->
[{doc, "Empty group should be deleted from nodes."}].
empty_group_by_remote_leave(Config) when is_list(Config) ->
- {TwoPeer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- RemoteNode = rpc:call(TwoPeer, erlang, whereis, [?FUNCTION_NAME]),
- RemotePid = erlang:spawn(TwoPeer, forever()),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ RemoteNode = rpc:call(Node, erlang, whereis, [?FUNCTION_NAME]),
+ RemotePid = spawn_sleeper_at(Node),
% remote join
- ?assertEqual(ok, rpc:call(TwoPeer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
- sync({?FUNCTION_NAME, TwoPeer}),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
?assertEqual([RemotePid], pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
% inspecting internal state is not best practice, but there's no other way to check if the state is correct.
- {state, _, _, #{RemoteNode := {_, RemoteMap}}} = sys:get_state(?FUNCTION_NAME),
+ {_, RemoteMap} = maps:get(RemoteNode, element(4, sys:get_state(?FUNCTION_NAME))),
?assertEqual(#{?FUNCTION_NAME => [RemotePid]}, RemoteMap),
% remote leave
- ?assertEqual(ok, rpc:call(TwoPeer, pg, leave, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
- sync({?FUNCTION_NAME, TwoPeer}),
+ ?assertEqual(ok, rpc:call(Node, pg, leave, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
?assertEqual([], pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- {state, _, _, #{RemoteNode := {_, NewRemoteMap}}} = sys:get_state(?FUNCTION_NAME),
+ {_, NewRemoteMap} = maps:get(RemoteNode, element(4, sys:get_state(?FUNCTION_NAME))),
% empty group should be deleted.
?assertEqual(#{}, NewRemoteMap),
%% another variant of emptying a group remotely: join([Pi1, Pid2]) and leave ([Pid2, Pid1])
- RemotePid2 = erlang:spawn(TwoPeer, forever()),
- ?assertEqual(ok, rpc:call(TwoPeer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, [RemotePid, RemotePid2]])),
- sync({?FUNCTION_NAME, TwoPeer}),
+ RemotePid2 = spawn_sleeper_at(Node),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, [RemotePid, RemotePid2]])),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
?assertEqual([RemotePid, RemotePid2], pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
%% now leave
- ?assertEqual(ok, rpc:call(TwoPeer, pg, leave, [?FUNCTION_NAME, ?FUNCTION_NAME, [RemotePid2, RemotePid]])),
- sync({?FUNCTION_NAME, TwoPeer}),
+ ?assertEqual(ok, rpc:call(Node, pg, leave, [?FUNCTION_NAME, ?FUNCTION_NAME, [RemotePid2, RemotePid]])),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
?assertEqual([], pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- {state, _, _, #{RemoteNode := {_, NewRemoteMap}}} = sys:get_state(?FUNCTION_NAME),
- stop_node(TwoPeer, Socket),
+ {_, NewRemoteMap} = maps:get(RemoteNode, element(4, sys:get_state(?FUNCTION_NAME))),
+ peer:stop(Peer),
ok.
thundering_herd() ->
@@ -317,229 +326,257 @@ thundering_herd(Config) when is_list(Config) ->
%% make up a large amount of groups
[pg:join(?FUNCTION_NAME, {group, Seq}, self()) || Seq <- lists:seq(1, GroupCount)],
%% initiate a few syncs - and those are really slow...
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- PeerPid = erlang:spawn(Peer, forever()),
- PeerPg = rpc:call(Peer, erlang, whereis, [?FUNCTION_NAME], 1000),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ PeerPid = erlang:spawn(Node, forever()),
+ PeerPg = rpc:call(Node, erlang, whereis, [?FUNCTION_NAME], 1000),
%% WARNING: code below acts for white-box! %% WARNING
FakeSync = [{{group, 1}, [PeerPid, PeerPid]}],
[gen_server:cast(?FUNCTION_NAME, {sync, PeerPg, FakeSync}) || _ <- lists:seq(1, SyncCount)],
%% next call must not timetrap, otherwise test fails
pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, self()),
- stop_node(Peer, Socket).
+ peer:stop(Peer).
initial(Config) when is_list(Config) ->
Pid = erlang:spawn(forever()),
?assertEqual(ok, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, Pid)),
?assertEqual([Pid], pg:get_local_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- %% first RPC must be serialised
- sync({?FUNCTION_NAME, Peer}),
- ?assertEqual([Pid], rpc:call(Peer, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ %% first sync makes the peer node to process 'nodeup' (and send discover)
+ sync({?FUNCTION_NAME, Node}),
+ %% second sync makes origin node pg to reply to discover'
+ sync(?FUNCTION_NAME),
+ %% third sync makes peer node to finish processing 'exchange'
+ sync({?FUNCTION_NAME, Node}),
+ ?assertEqual([Pid], rpc:call(Node, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
- ?assertEqual([], rpc:call(Peer, pg, get_local_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ ?assertEqual([], rpc:call(Node, pg, get_local_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
stop_proc(Pid),
- sync({?FUNCTION_NAME, Peer}),
- ?assertEqual([], rpc:call(Peer, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
- stop_node(Peer, Socket),
+ sync({?FUNCTION_NAME, Node}),
+ ?assertEqual([], rpc:call(Node, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ peer:stop(Peer),
ok.
netsplit(Config) when is_list(Config) ->
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- ?assertEqual(Peer, rpc(Socket, erlang, node, [])), %% just to test RPC
- RemoteOldPid = erlang:spawn(Peer, forever()),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, '$invisible', RemoteOldPid])),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ ?assertEqual(Node, peer:call(Peer, erlang, node, [])), %% just to test RPC
+ RemoteOldPid = spawn_sleeper_at(Node),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, '$invisible', RemoteOldPid])),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
+ ?assertEqual([RemoteOldPid], pg:get_members(?FUNCTION_NAME, '$invisible')),
+
%% hohoho, partition!
- disconnect_nodes([Peer]),
- ?assertEqual(Peer, rpc(Socket, erlang, node, [])), %% just to ensure RPC still works
- RemotePid = rpc(Socket, erlang, spawn, [forever()]),
- ?assertEqual([], rpc(Socket, erlang, nodes, [])),
- ?assertNot(lists:member(Peer, nodes())), %% should be no nodes in the cluster
- ?assertEqual(ok, rpc(Socket, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])), %% join - in a partition!
-
- ?assertEqual(ok, rpc(Socket, pg, leave, [?FUNCTION_NAME, '$invisible', RemoteOldPid])),
- ?assertEqual(ok, rpc(Socket, pg, join, [?FUNCTION_NAME, '$visible', RemoteOldPid])),
- ?assertEqual([RemoteOldPid], rpc(Socket, pg, get_local_members, [?FUNCTION_NAME, '$visible'])),
+ disconnect_nodes([Node]),
+ ?assertEqual(Node, peer:call(Peer, erlang, node, [])), %% just to ensure RPC still works
+ RemotePid = peer:call(Peer, erlang, spawn, sleeper_mfa()),
+ ?assertEqual([], peer:call(Peer, erlang, nodes, [])),
+ ?assertNot(lists:member(Node, nodes())), %% should be no nodes in the cluster
+ ?assertEqual(ok, peer:call(Peer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])), %% join - in a partition!
+
+ ?assertEqual(ok, peer:call(Peer, pg, leave, [?FUNCTION_NAME, '$invisible', RemoteOldPid])),
+ ?assertEqual(ok, peer:call(Peer, pg, join, [?FUNCTION_NAME, '$visible', RemoteOldPid])),
+ ?assertEqual([RemoteOldPid], peer:call(Peer, pg, get_local_members, [?FUNCTION_NAME, '$visible'])),
%% join locally too
LocalPid = erlang:spawn(forever()),
?assertEqual(ok, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, LocalPid)),
- ?assertNot(lists:member(Peer, nodes())), %% should be no nodes in the cluster
+ ?assertNot(lists:member(Node, nodes())), %% should be no nodes in the cluster
+
+ PgPid = whereis(?FUNCTION_NAME),
+ 1 = erlang:trace(PgPid, true, ['receive']),
+ pong = net_adm:ping(Node),
+ receive
+ {trace, PgPid, 'receive', {nodeup, Node}} -> ok
+ end,
+ 1 = erlang:trace(PgPid, false, ['receive']),
- pong = net_adm:ping(Peer),
%% now ensure sync happened
- Pids = lists:sort([RemotePid, LocalPid]),
- sync({?FUNCTION_NAME, Peer}),
- ?assertEqual(Pids, lists:sort(rpc:call(Peer, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME]))),
+ sync_via(?FUNCTION_NAME, {?FUNCTION_NAME, Node}),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
+ ?assertEqual(lists:sort([RemotePid, LocalPid]),
+ lists:sort(rpc:call(Node, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME]))),
?assertEqual([RemoteOldPid], pg:get_members(?FUNCTION_NAME, '$visible')),
- stop_node(Peer, Socket),
+ peer:stop(Peer),
ok.
trisplit(Config) when is_list(Config) ->
- {Peer, Socket1} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- _PeerPid1 = erlang:spawn(Peer, forever()),
- PeerPid2 = erlang:spawn(Peer, forever()),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, three, PeerPid2])),
- disconnect_nodes([Peer]),
- ?assertEqual(true, net_kernel:connect_node(Peer)),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, one, PeerPid2])),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ _PeerPid1 = spawn_sleeper_at(Node),
+ PeerPid2 = spawn_sleeper_at(Node),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, three, PeerPid2])),
+ disconnect_nodes([Node]),
+ ?assertEqual(true, net_kernel:connect_node(Node)),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, one, PeerPid2])),
%% now ensure sync happened
- {Peer2, Socket2} = spawn_node(?FUNCTION_NAME, trisplit_second),
- ?assertEqual(true, rpc:call(Peer2, net_kernel, connect_node, [Peer])),
- ?assertEqual(lists:sort([node(), Peer]), lists:sort(rpc:call(Peer2, erlang, nodes, []))),
- ok = rpc:call(Peer2, ?MODULE, ensure_peers_info, [?FUNCTION_NAME, [node(), Peer]]),
- ?assertEqual([PeerPid2], rpc:call(Peer2, pg, get_members, [?FUNCTION_NAME, one])),
- stop_node(Peer, Socket1),
- stop_node(Peer2, Socket2),
+ {Peer2, Node2} = spawn_node(?FUNCTION_NAME, Config),
+ ?assertEqual(true, rpc:call(Node2, net_kernel, connect_node, [Node])),
+ ?assertEqual(lists:sort([node(), Node]), lists:sort(rpc:call(Node2, erlang, nodes, []))),
+ ok = rpc:call(Node2, ?MODULE, ensure_peers_info, [?FUNCTION_NAME, [node(), Node]]),
+ ?assertEqual([PeerPid2], rpc:call(Node2, pg, get_members, [?FUNCTION_NAME, one])),
+ peer:stop(Peer),
+ peer:stop(Peer2),
ok.
foursplit(Config) when is_list(Config) ->
Pid = erlang:spawn(forever()),
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
?assertEqual(ok, pg:join(?FUNCTION_NAME, one, Pid)),
?assertEqual(ok, pg:join(?FUNCTION_NAME, two, Pid)),
- PeerPid1 = spawn(Peer, forever()),
+ PeerPid1 = erlang:spawn(Node, forever()),
?assertEqual(ok, pg:leave(?FUNCTION_NAME, one, Pid)),
?assertEqual(not_joined, pg:leave(?FUNCTION_NAME, three, Pid)),
- disconnect_nodes([Peer]),
- ?assertEqual(ok, rpc(Socket, ?MODULE, stop_proc, [PeerPid1])),
+ disconnect_nodes([Node]),
+ ?assertEqual(ok, peer:call(Peer, ?MODULE, stop_proc, [PeerPid1])),
?assertEqual(not_joined, pg:leave(?FUNCTION_NAME, three, Pid)),
- ?assertEqual(true, net_kernel:connect_node(Peer)),
+ ?assertEqual(true, net_kernel:connect_node(Node)),
?assertEqual([], pg:get_members(?FUNCTION_NAME, one)),
- ?assertEqual([], rpc(Socket, pg, get_members, [?FUNCTION_NAME, one])),
- stop_node(Peer, Socket),
+ ?assertEqual([], peer:call(Peer, pg, get_members, [?FUNCTION_NAME, one])),
+ peer:stop(Peer),
ok.
exchange(Config) when is_list(Config) ->
- {Peer1, Socket1} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- {Peer2, Socket2} = spawn_node(?FUNCTION_NAME, exchange_second),
- Pids10 = [rpc(Socket1, erlang, spawn, [forever()]) || _ <- lists:seq(1, 10)],
- Pids2 = [rpc(Socket2, erlang, spawn, [forever()]) || _ <- lists:seq(1, 10)],
- Pids11 = [rpc(Socket1, erlang, spawn, [forever()]) || _ <- lists:seq(1, 10)],
+ {Peer1, Node1} = spawn_node(?FUNCTION_NAME, Config),
+ {Peer2, Node2} = spawn_node(?FUNCTION_NAME, Config),
+ Pids10 = [peer:call(Peer1, erlang, spawn, [forever()]) || _ <- lists:seq(1, 10)],
+ Pids2 = [peer:call(Peer2, erlang, spawn, [forever()]) || _ <- lists:seq(1, 10)],
+ Pids11 = [peer:call(Peer1, erlang, spawn, [forever()]) || _ <- lists:seq(1, 10)],
%% kill first 3 pids from node1
{PidsToKill, Pids1} = lists:split(3, Pids10),
- ?assertEqual(ok, rpc(Socket1, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pids10])),
- sync({?FUNCTION_NAME, Peer1}), %% Join broadcast have reached local
+ ?assertEqual(ok, peer:call(Peer1, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pids10])),
+ sync({?FUNCTION_NAME, Node1}), %% Join broadcast have reached local
sync(?FUNCTION_NAME), %% Join broadcast has been processed by local
?assertEqual(lists:sort(Pids10), lists:sort(pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
- [rpc(Socket1, ?MODULE, stop_proc, [Pid]) || Pid <- PidsToKill],
+ [peer:call(Peer1, ?MODULE, stop_proc, [Pid]) || Pid <- PidsToKill],
sync(?FUNCTION_NAME),
- sync({?FUNCTION_NAME, Peer1}),
+ sync({?FUNCTION_NAME, Node1}),
Pids = lists:sort(Pids1 ++ Pids2 ++ Pids11),
?assert(lists:all(fun erlang:is_pid/1, Pids)),
- disconnect_nodes([Peer1, Peer2]),
+ disconnect_nodes([Node1, Node2]),
sync(?FUNCTION_NAME), %% Processed nodedowns...
?assertEqual([], lists:sort(pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
- [?assertEqual(ok, rpc(Socket2, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pid])) || Pid <- Pids2],
- [?assertEqual(ok, rpc(Socket1, pg, join, [?FUNCTION_NAME, second, Pid])) || Pid <- Pids11],
- ?assertEqual(ok, rpc(Socket1, pg, join, [?FUNCTION_NAME, third, Pids11])),
+ [?assertEqual(ok, peer:call(Peer2, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, Pid])) || Pid <- Pids2],
+ [?assertEqual(ok, peer:call(Peer1, pg, join, [?FUNCTION_NAME, second, Pid])) || Pid <- Pids11],
+ ?assertEqual(ok, peer:call(Peer1, pg, join, [?FUNCTION_NAME, third, Pids11])),
%% rejoin
- ?assertEqual(true, net_kernel:connect_node(Peer1)),
- ?assertEqual(true, net_kernel:connect_node(Peer2)),
+ ?assertEqual(true, net_kernel:connect_node(Node1)),
+ ?assertEqual(true, net_kernel:connect_node(Node2)),
%% need to sleep longer to ensure both nodes made the exchange
- ensure_peers_info(?FUNCTION_NAME, [Peer1, Peer2]),
+ ensure_peers_info(?FUNCTION_NAME, [Node1, Node2]),
?assertEqual(Pids, lists:sort(pg:get_members(?FUNCTION_NAME, second) ++ pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
?assertEqual(lists:sort(Pids11), lists:sort(pg:get_members(?FUNCTION_NAME, third))),
{Left, Stay} = lists:split(3, Pids11),
- ?assertEqual(ok, rpc(Socket1, pg, leave, [?FUNCTION_NAME, third, Left])),
- sync({?FUNCTION_NAME, Peer1}),
+ ?assertEqual(ok, peer:call(Peer1, pg, leave, [?FUNCTION_NAME, third, Left])),
+ sync({?FUNCTION_NAME, Node1}),
sync(?FUNCTION_NAME),
?assertEqual(lists:sort(Stay), lists:sort(pg:get_members(?FUNCTION_NAME, third))),
- ?assertEqual(not_joined, rpc(Socket1, pg, leave, [?FUNCTION_NAME, left, Stay])),
- ?assertEqual(ok, rpc(Socket1, pg, leave, [?FUNCTION_NAME, third, Stay])),
- sync({?FUNCTION_NAME, Peer1}),
+ ?assertEqual(not_joined, peer:call(Peer1, pg, leave, [?FUNCTION_NAME, left, Stay])),
+ ?assertEqual(ok, peer:call(Peer1, pg, leave, [?FUNCTION_NAME, third, Stay])),
+ sync({?FUNCTION_NAME, Node1}),
sync(?FUNCTION_NAME),
?assertEqual([], lists:sort(pg:get_members(?FUNCTION_NAME, third))),
- sync({?FUNCTION_NAME, Peer1}),
+ sync({?FUNCTION_NAME, Node1}),
sync(?FUNCTION_NAME),
- stop_node(Peer1, Socket1),
- stop_node(Peer2, Socket2),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
ok.
nolocal(Config) when is_list(Config) ->
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- RemotePid = spawn(Peer, forever()),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ RemotePid = spawn_sleeper_at(Node),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
?assertEqual([], pg:get_local_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- stop_node(Peer, Socket),
+ peer:stop(Peer),
ok.
double(Config) when is_list(Config) ->
Pid = erlang:spawn(forever()),
?assertEqual(ok, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, Pid)),
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
?assertEqual(ok, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, [Pid])),
?assertEqual([Pid, Pid], pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- sync(?FUNCTION_NAME),
- sync({?FUNCTION_NAME, Peer}),
- ?assertEqual([Pid, Pid], rpc:call(Peer, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
- stop_node(Peer, Socket),
+ sync({?FUNCTION_NAME, Node}),
+ sync_via(?FUNCTION_NAME, {?FUNCTION_NAME, Node}),
+ ?assertEqual([Pid, Pid], rpc:call(Node, pg, get_members, [?FUNCTION_NAME, ?FUNCTION_NAME])),
+ peer:stop(Peer),
ok.
scope_restart(Config) when is_list(Config) ->
Pid = erlang:spawn(forever()),
?assertEqual(ok, pg:join(?FUNCTION_NAME, ?FUNCTION_NAME, [Pid, Pid])),
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- RemotePid = spawn(Peer, forever()),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
- sync({?FUNCTION_NAME, Peer}),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ RemotePid = erlang:spawn(Node, forever()),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
?assertEqual(lists:sort([RemotePid, Pid, Pid]), lists:sort(pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
%% stop scope locally, and restart
gen_server:stop(?FUNCTION_NAME),
pg:start(?FUNCTION_NAME),
%% ensure remote pids joined, local are missing
sync(?FUNCTION_NAME),
- sync({?FUNCTION_NAME, Peer}),
+ sync({?FUNCTION_NAME, Node}),
sync(?FUNCTION_NAME),
?assertEqual([RemotePid], pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME)),
- stop_node(Peer, Socket),
+ peer:stop(Peer),
ok.
missing_scope_join(Config) when is_list(Config) ->
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- ?assertEqual(ok, rpc:call(Peer, gen_server, stop, [?FUNCTION_NAME])),
- RemotePid = spawn(Peer, forever()),
- ?assertMatch({badrpc, {'EXIT', {noproc, _}}}, rpc:call(Peer, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
- ?assertMatch({badrpc, {'EXIT', {noproc, _}}}, rpc:call(Peer, pg, leave, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
- stop_node(Peer, Socket),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ ?assertEqual(ok, rpc:call(Node, gen_server, stop, [?FUNCTION_NAME])),
+ RemotePid = erlang:spawn(Node, forever()),
+ ?assertMatch({badrpc, {'EXIT', {noproc, _}}}, rpc:call(Node, pg, join, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ ?assertMatch({badrpc, {'EXIT', {noproc, _}}}, rpc:call(Node, pg, leave, [?FUNCTION_NAME, ?FUNCTION_NAME, RemotePid])),
+ peer:stop(Peer),
ok.
disconnected_start(Config) when is_list(Config) ->
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- disconnect_nodes([Peer]),
- ?assertEqual(ok, rpc(Socket, gen_server, stop, [?FUNCTION_NAME])),
- ?assertMatch({ok, _Pid}, rpc(Socket, pg, start,[?FUNCTION_NAME])),
- ?assertEqual(ok, rpc(Socket, gen_server, stop, [?FUNCTION_NAME])),
- RemotePid = rpc(Socket, erlang, spawn, [forever()]),
+ case test_server:is_cover() of
+ true ->
+ {skip, "Cover is running"};
+ false ->
+ disconnected_start_test(Config)
+ end.
+
+disconnected_start_test(Config) when is_list(Config) ->
+ {Peer, Node} = spawn_disconnected_node(?FUNCTION_NAME, ?FUNCTION_NAME, Config),
+ ?assertNot(lists:member(Node, nodes())),
+ ?assertEqual(ok, peer:call(Peer, gen_server, stop, [?FUNCTION_NAME])),
+ ?assertMatch({ok, _Pid}, peer:call(Peer, pg, start,[?FUNCTION_NAME])),
+ ?assertEqual(ok, peer:call(Peer, gen_server, stop, [?FUNCTION_NAME])),
+ RemotePid = peer:call(Peer, erlang, spawn, [forever()]),
?assert(is_pid(RemotePid)),
- stop_node(Peer, Socket),
+ peer:stop(Peer),
ok.
forced_sync() ->
[{doc, "This test was added when lookup_element was erroneously used instead of lookup, crashing pg with badmatch, and it tests rare out-of-order sync operations"}].
forced_sync(Config) when is_list(Config) ->
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
Pid = erlang:spawn(forever()),
- RemotePid = spawn(Peer, forever()),
+ RemotePid = erlang:spawn(Node, forever()),
Expected = lists:sort([Pid, RemotePid]),
pg:join(?FUNCTION_NAME, one, Pid),
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, one, RemotePid])),
- RemoteScopePid = rpc:call(Peer, erlang, whereis, [?FUNCTION_NAME]),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, one, RemotePid])),
+ RemoteScopePid = rpc:call(Node, erlang, whereis, [?FUNCTION_NAME]),
?assert(is_pid(RemoteScopePid)),
%% hohoho, partition!
- disconnect_nodes([Peer]),
- ?assertEqual(true, net_kernel:connect_node(Peer)),
- ensure_peers_info(?FUNCTION_NAME, [Peer]),
+ disconnect_nodes([Node]),
+ ?assertEqual(true, net_kernel:connect_node(Node)),
+ ensure_peers_info(?FUNCTION_NAME, [Node]),
?assertEqual(Expected, lists:sort(pg:get_members(?FUNCTION_NAME, one))),
+
+ %% Do extra sync to make sure any redundant sync message has arrived
+ %% before we send our fake sync message below.
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
+
%% WARNING: this code uses pg as white-box, exploiting internals,
%% only to simulate broken 'sync'
%% Fake Groups: one should disappear, one should be replaced, one stays
@@ -551,43 +588,197 @@ forced_sync(Config) when is_list(Config) ->
?assertEqual(lists:sort([RemotePid, RemotePid]), lists:sort(pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
?assertEqual(lists:sort([RemotePid, RemotePid, Pid]), lists:sort(pg:get_members(?FUNCTION_NAME, one))),
%% simulate force-sync via 'discover' - ask peer to send sync to us
- {?FUNCTION_NAME, Peer} ! {discover, whereis(?FUNCTION_NAME)},
- sync({?FUNCTION_NAME, Peer}),
+ {?FUNCTION_NAME, Node} ! {discover, whereis(?FUNCTION_NAME)},
+ sync({?FUNCTION_NAME, Node}),
sync(?FUNCTION_NAME),
?assertEqual(Expected, lists:sort(pg:get_members(?FUNCTION_NAME, one))),
?assertEqual([], lists:sort(pg:get_members(?FUNCTION_NAME, ?FUNCTION_NAME))),
%% and simulate extra sync
- sync({?FUNCTION_NAME, Peer}),
+ sync({?FUNCTION_NAME, Node}),
sync(?FUNCTION_NAME),
?assertEqual(Expected, lists:sort(pg:get_members(?FUNCTION_NAME, one))),
- stop_node(Peer, Socket),
+ peer:stop(Peer),
ok.
group_leave(Config) when is_list(Config) ->
- {Peer, Socket} = spawn_node(?FUNCTION_NAME, ?FUNCTION_NAME),
- RemotePid = erlang:spawn(Peer, forever()),
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ RemotePid = erlang:spawn(Node, forever()),
Total = lists:duplicate(16, RemotePid),
{Left, Remain} = lists:split(4, Total),
%% join 16 times!
- ?assertEqual(ok, rpc:call(Peer, pg, join, [?FUNCTION_NAME, two, Total])),
- ?assertEqual(ok, rpc:call(Peer, pg, leave, [?FUNCTION_NAME, two, Left])),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, two, Total])),
+ ?assertEqual(ok, rpc:call(Node, pg, leave, [?FUNCTION_NAME, two, Left])),
- sync({?FUNCTION_NAME, Peer}),
+ sync({?FUNCTION_NAME, Node}),
sync(?FUNCTION_NAME),
?assertEqual(Remain, pg:get_members(?FUNCTION_NAME, two)),
- stop_node(Peer, Socket),
+
+ PgPid = whereis(?FUNCTION_NAME),
+ 1 = erlang:trace(PgPid, true, ['receive']),
+ peer:stop(Peer),
+ receive
+ {trace, PgPid, 'receive', {nodedown, Node}} -> ok
+ end,
+ 1 = erlang:trace(PgPid, false, ['receive']),
sync(?FUNCTION_NAME),
?assertEqual([], pg:get_members(?FUNCTION_NAME, two)),
ok.
+monitor_nonempty_scope() ->
+ [{doc, "Ensure that monitor_scope returns full map of groups in the scope"}].
+
+monitor_nonempty_scope(Config) when is_list(Config) ->
+ {Peer, Node} = spawn_node(?FUNCTION_NAME, Config),
+ Pid = erlang:spawn_link(forever()),
+ RemotePid = erlang:spawn(Node, forever()),
+ Expected = lists:sort([Pid, RemotePid]),
+ pg:join(?FUNCTION_NAME, one, Pid),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [?FUNCTION_NAME, one, RemotePid])),
+ %% Ensure that initial monitoring request returns current map of groups to pids
+ {Ref, #{one := Actual} = FullScope} = pg:monitor_scope(?FUNCTION_NAME),
+ ?assertEqual(Expected, Actual),
+ %% just in case - check there are no extra groups in that scope
+ ?assertEqual(1, map_size(FullScope)),
+ pg:demonitor(?FUNCTION_NAME, Ref),
+ %% re-check
+ {_Ref, FullScope} = pg:monitor_scope(?FUNCTION_NAME),
+ peer:stop(Peer),
+ exit(Pid, normal).
+
+monitor_scope() ->
+ [{doc, "Tests monitor_scope/1 and demonitor/2"}].
+
+monitor_scope(Config) when is_list(Config) ->
+ %% ensure that demonitoring returns 'false' when monitor is not installed
+ ?assertEqual(false, pg:demonitor(?FUNCTION_NAME, erlang:make_ref())),
+ InitialMonitor = fun (Scope) -> {Ref, #{}} = pg:monitor_scope(Scope), Ref end,
+ SecondMonitor = fun (Scope, Group, Control) -> {Ref, #{Group := [Control]}} = pg:monitor_scope(Scope), Ref end,
+ %% WHITE BOX: knowing pg state internals - only the original monitor should stay
+ DownMonitor = fun (Scope, Ref, Self) ->
+ {state, _, _, _, ScopeMonitors, _, _} = sys:get_state(Scope),
+ ?assertEqual(#{Ref => Self}, ScopeMonitors, "pg did not remove DOWNed scope monitor")
+ end,
+ monitor_test_impl(Config, ?FUNCTION_NAME, ?FUNCTION_ARITY, InitialMonitor,
+ SecondMonitor, DownMonitor).
+
+monitor(Config) when is_list(Config) ->
+ ExpectedGroup = {?FUNCTION_NAME, ?FUNCTION_ARITY},
+ InitialMonitor = fun (Scope) -> {Ref, []} = pg:monitor(Scope, ExpectedGroup), Ref end,
+ SecondMonitor = fun (Scope, Group, Control) ->
+ {Ref, [Control]} = pg:monitor(Scope, Group), Ref end,
+ DownMonitor = fun (Scope, Ref, Self) ->
+ {state, _, _, _, _, GM, MG} = sys:get_state(Scope),
+ ?assertEqual(#{Ref => {Self, ExpectedGroup}}, GM, "pg did not remove DOWNed group monitor"),
+ ?assertEqual(#{ExpectedGroup => [{Self, Ref}]}, MG, "pg did not remove DOWNed group")
+ end,
+ monitor_test_impl(Config, ?FUNCTION_NAME, ExpectedGroup, InitialMonitor,
+ SecondMonitor, DownMonitor).
+
+monitor_test_impl(Config, Scope, Group, InitialMonitor, SecondMonitor, DownMonitor) ->
+ Self = self(),
+ Ref = InitialMonitor(Scope),
+ %% local join
+ ?assertEqual(ok, pg:join(Scope, Group, Self)),
+ wait_message(Ref, join, Group, [Self], "Local"),
+ %% start second monitor (which has 1 local pid at the start)
+ ExtraMonitor = spawn_link(fun() -> second_monitor(Scope, Group, Self, SecondMonitor) end),
+ Ref2 = receive {ExtraMonitor, SecondRef} -> SecondRef end,
+ %% start a remote node, and a remote monitor
+ {Peer, Node} = spawn_node(Scope, Config),
+ ScopePid = whereis(Scope),
+ %% do not care about the remote monitor, it is started only to check DOWN handling
+ ThirdMonitor = spawn_link(Node, fun() -> second_monitor(ScopePid, Group, Self, SecondMonitor) end),
+ Ref3 = receive {ThirdMonitor, ThirdRef} -> ThirdRef end,
+ %% remote join
+ RemotePid = erlang:spawn(Node, forever()),
+ ?assertEqual(ok, rpc:call(Node, pg, join, [Scope, Group, [RemotePid, RemotePid]])),
+ wait_message(Ref, join, Group, [RemotePid, RemotePid], "Remote"),
+ %% verify leave event
+ ?assertEqual([Self], pg:get_local_members(Scope, Group)),
+ ?assertEqual(ok, pg:leave(Scope, Group, self())),
+ wait_message(Ref, leave, Group, [Self], "Local"),
+ %% remote leave
+ ?assertEqual(ok, rpc:call(Node, pg, leave, [Scope, Group, RemotePid])),
+ %% flush the local pg scope via remote pg (to ensure local pg finished sending notifications)
+ sync_via({?FUNCTION_NAME, Node}, ?FUNCTION_NAME),
+ wait_message(Ref, leave, Group, [RemotePid], "Remote"),
+ %% drop the ExtraMonitor - this keeps original and remote monitors
+ SecondMonMsgs = gen_server:call(ExtraMonitor, flush),
+ %% inspect the queue, it should contain double remote join, then single local and single remove leave
+ ExpectedLocalMessages = [
+ {Ref2, join, Group, [RemotePid, RemotePid]},
+ {Ref2, leave, Group, [Self]},
+ {Ref2, leave, Group, [RemotePid]}],
+ ?assertEqual(ExpectedLocalMessages, SecondMonMsgs, "Local monitor failed"),
+ %% inspect remote monitor queue
+ ThirdMonMsgs = gen_server:call(ThirdMonitor, flush),
+ ExpectedRemoteMessages = [
+ {Ref3, join, Group, [RemotePid, RemotePid]},
+ {Ref3, leave, Group, [Self]},
+ {Ref3, leave, Group, [RemotePid]}],
+ ?assertEqual(ExpectedRemoteMessages, ThirdMonMsgs, "Remote monitor failed"),
+ %% remote leave via stop (causes remote monitor to go DOWN)
+ ok = peer:stop(Peer),
+ wait_message(Ref, leave, Group, [RemotePid], "Remote stop"),
+ DownMonitor(Scope, Ref, Self),
+ %% demonitor
+ ?assertEqual(ok, pg:demonitor(Scope, Ref)),
+ ?assertEqual(false, pg:demonitor(Scope, Ref)),
+ %% ensure messages don't come
+ ?assertEqual(ok, pg:join(Scope, Group, Self)),
+ sync(Scope),
+ %% join should not be here
+ receive {Ref, Action, Group, [Self]} -> ?assert(false, lists:concat(["Unexpected ", Action, "event"]))
+ after 0 -> ok end.
+
+wait_message(Ref, Action, Group, Pids, Msg) ->
+ receive
+ {Ref, Action, Group, Pids} ->
+ ok
+ after 1000 ->
+ {messages, Msgs} = process_info(self(), messages),
+ ct:pal("Message queue: ~0p", [Msgs]),
+ ?assert(false, lists:flatten(io_lib:format("Expected ~s ~s for ~p", [Msg, Action, Group])))
+ end.
+
+second_monitor(Scope, Group, Control, SecondMonitor) ->
+ Ref = SecondMonitor(Scope, Group, Control),
+ Control ! {self(), Ref},
+ second_monitor([]).
+
+second_monitor(Msgs) ->
+ receive
+ {'$gen_call', Reply, flush} ->
+ gen:reply(Reply, lists:reverse(Msgs));
+ Msg ->
+ second_monitor([Msg | Msgs])
+ end.
+
%%--------------------------------------------------------------------
%% Test Helpers - start/stop additional Erlang nodes
+%% flushes GS (GenServer) queue, ensuring that all prior
+%% messages have been processed
sync(GS) ->
_ = sys:log(GS, get).
-ensure_peers_info(Scope, Peers) ->
+%% flushes GS queue from the point of view of a registered process RegName
+%% running on the Node.
+sync_via({RegName, Node}, GS) ->
+ MyNode = node(),
+ rpc:call(Node, sys, replace_state,
+ [RegName, fun (S) -> (catch sys:get_state({GS, MyNode})), S end]);
+
+%% flush remote GS queue from local process RegName
+sync_via(RegName, {GS, Node}) ->
+ sys:replace_state(RegName,
+ fun (S) -> _R = (catch sys:get_state({GS, Node})),
+ %%io:format("sync_via: ~p -> R = ~p\n", [{GS, Node},_R]),
+ S
+ end).
+
+ensure_peers_info(Scope, Nodes) ->
%% Ensures that pg server on local node has gotten info from
%% pg servers on all Peer nodes passed as argument (assuming
%% no connection failures).
@@ -600,9 +791,9 @@ ensure_peers_info(Scope, Peers) ->
%%
sync(Scope),
- %% Known: nodup handled and discover sent to Peer
+ %% Known: nodeup handled and discover sent to Peer
- lists:foreach(fun (Peer) -> sync({Scope, Peer}) end, Peers),
+ lists:foreach(fun (Node) -> sync({Scope, Node}) end, Nodes),
%% Known: nodeup handled by Peers and discover sent to local
%% Known: discover received/handled by Peers and sync sent to local
%% Known: discover received from Peer
@@ -615,7 +806,7 @@ ensure_peers_info(Scope, Peers) ->
-ifdef(CURRENTLY_UNUSED_BUT_SERVES_AS_DOC).
-ensure_synced(Scope, Peers) ->
+ensure_synced(Scope, Nodes) ->
%% Ensures that the pg server on local node have synced
%% with pg servers on all Peer nodes (assuming no connection
%% failures).
@@ -626,10 +817,10 @@ ensure_synced(Scope, Peers) ->
%% Note that this relies on current ERTS implementation; not
%% language guarantees.
%%
- ensure_peer_info(Scope, Peer),
+ ensure_peer_info(Scope, Node),
%% Known: local has gotten info from all Peers
%% Known: discover from Peers handled and sync sent to Peers
- lists:foreach(fun (Peer) -> sync({Scope, Peer}) end, Peers),
+ lists:foreach(fun (Node) -> sync({Scope, Node}) end, Nodes),
%% Known: sync from local handled by Peers
ok.
@@ -637,7 +828,7 @@ ensure_synced(Scope, Peers) ->
disconnect_nodes(Nodes) ->
%% The following is not a language guarantee, but internal
- %% knowledged about current implementation of ERTS and pg.
+ %% knowledge about current implementation of ERTS and pg.
%%
%% The pg server reacts on 'DOWN's via process monitors of
%% its peers. These are delivered before 'nodedown's from
@@ -662,12 +853,10 @@ disconnect_nodes(Nodes) ->
{Pid, Mon} = spawn_monitor(F),
receive
{'DOWN', Mon, process, Pid, Reason} ->
- normal = Reason
+ ?assertEqual(normal, Reason)
end,
ok.
--define (LOCALHOST, {127, 0, 0, 1}).
-
%% @doc Kills process Pid and waits for it to exit using monitor,
%% and yields after (for 1 ms).
-spec stop_proc(pid()) -> ok.
@@ -679,125 +868,95 @@ stop_proc(Pid) ->
timer:sleep(1)
end.
-%% @doc Executes remote call on the node via TCP socket
-%% Used when dist connection is not available, or
-%% when it's undesirable to use one.
--spec rpc(gen_tcp:socket(), module(), atom(), [term()]) -> term().
-rpc(Sock, M, F, A) ->
- ok = gen_tcp:send(Sock, term_to_binary({call, M, F, A})),
- inet:setopts(Sock, [{active, once}]),
- receive
- {tcp, Sock, Data} ->
- case binary_to_term(Data) of
- {ok, Val} ->
- Val;
- {error, Error} ->
- {badrpc, Error}
- end;
- {tcp_closed, Sock} ->
- error(closed)
- end.
-
-%% @doc starts peer node on this host.
-%% Returns spawned node name, and a gen_tcp socket to talk to it using ?MODULE:rpc.
--spec spawn_node(Scope :: atom(), Node :: atom()) -> {node(), gen_tcp:socket()}.
-spawn_node(Scope, Name) ->
- Self = self(),
- Controller = erlang:spawn(?MODULE, controller, [Name, Scope, Self]),
- receive
- {'$node_started', Node, Port} ->
- {ok, Socket} = gen_tcp:connect(?LOCALHOST, Port, [{active, false}, {mode, binary}, {packet, 4}]),
- Controller ! {socket, Socket},
- {Node, Socket};
- Other ->
- error({start_node, Name, Other})
- after 60000 ->
- error({start_node, Name, timeout})
- end.
-
-%% @private
--spec controller(atom(), atom(), pid()) -> ok.
-controller(Name, Scope, Self) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Pa2 = filename:dirname(code:which(pg)),
- Args = lists:concat(["-setcookie ", erlang:get_cookie(),
- " -connect_all false -kernel dist_auto_connect never -noshell -pa ", Pa, " -pa ", Pa2]),
- {ok, Node} = test_server:start_node(Name, peer, [{args, Args}]),
- case rpc:call(Node, ?MODULE, control, [Scope], 5000) of
- {badrpc, nodedown} ->
- Self ! {badrpc, Node},
- ok;
- {Port, _PgPid} ->
- Self ! {'$node_started', Node, Port},
- controller_wait()
+forever() ->
+ Parent = self(),
+ fun() ->
+ %% forever() is used both locally and on a remote node,
+ %% if used locally, we want to terminate when the
+ %% parent terminates in order to not leak process to
+ %% later test cases
+ Ref = monitor(process,Parent),
+ receive
+ {'DOWN',Ref,_,_,_} when node() =:= node(Parent) ->
+ ok
+ end
end.
-controller_wait() ->
- Port =
- receive
- {socket, Port0} ->
- Port0
+%% Spawn a sleeping process on remote node.
+%% Works on older nodes also without having to run any specially compiled code.
+spawn_sleeper_at(Node) when Node =/= node() ->
+ spawn(Node, erlang, hibernate, [?MODULE,dummy,[]]).
+
+sleeper_mfa() ->
+ [erlang, hibernate, [?MODULE,dummy,[]]].
+
+spawn_node(TestCase, Config) ->
+ {Peer, Node} = spawn_disconnected_node(TestCase, TestCase, Config),
+ true = net_kernel:connect_node(Node),
+ {Peer, Node}.
+
+spawn_disconnected_node(Scope, TestCase, Config) ->
+ Opts = #{name => ?CT_PEER_NAME(TestCase),
+ connection => 0,
+ args => ["-connect_all", "false",
+ "-kernel", "dist_auto_connect", "never"]},
+ {ok, Peer, Node} =
+ case proplists:get_value(otp_release, Config) of
+ undefined ->
+ ?CT_PEER(Opts);
+ Release ->
+ TcPrivDir = filename:join(proplists:get_value(priv_dir, Config),
+ TestCase),
+ ok = ensure_dir(TcPrivDir),
+ ?CT_PEER_REL(Opts, Release, TcPrivDir)
end,
- MRef = monitor(port, Port),
- receive
- {'DOWN', MRef, port, Port, _Info} ->
- ok
+ {ok, _Pid} = peer:call(Peer, pg, start, [Scope]),
+ {Peer, Node}.
+
+ensure_dir(Dir) ->
+ case file:make_dir(Dir) of
+ ok -> ok;
+ {error, eexist} -> ok;
+ E -> E
end.
-%% @doc Stops the node previously started with spawn_node,
-%% and also closes the RPC socket.
--spec stop_node(node(), gen_tcp:socket()) -> true.
-stop_node(Node, Socket) when Node =/= node() ->
- true = test_server:stop_node(Node),
- Socket =/= undefined andalso gen_tcp:close(Socket),
- true.
-forever() ->
- fun() -> receive after infinity -> ok end end.
+%%--------------------------------------------------------------------
+%% Debug Helpers
+%% Add test cases here to enable 'receive' trace of the local pg process
+traced_testcases() -> [].
--spec control(Scope :: atom()) -> {Port :: integer(), pid()}.
-control(Scope) ->
- Control = self(),
- erlang:spawn(fun () -> server(Control, Scope) end),
- receive
- {port, Port, PgPid} ->
- {Port, PgPid};
- Other ->
- error({error, Other})
+trace_start(TestCase, Config, Tracee) ->
+ case lists:member(TestCase, traced_testcases()) of
+ true ->
+ Tracer = spawn_link(fun() -> tracer() end),
+ 1 = erlang:trace(Tracee, true, ['receive', {tracer, Tracer}, timestamp]),
+ [{tracer, Tracer} | Config];
+ false ->
+ Config
end.
-server(Control, Scope) ->
- try
- {ok, Pid} = if Scope =:= undefined -> {ok, undefined}; true -> pg:start(Scope) end,
- {ok, Listen} = gen_tcp:listen(0, [{mode, binary}, {packet, 4}, {ip, ?LOCALHOST}]),
- {ok, Port} = inet:port(Listen),
- Control ! {port, Port, Pid},
- {ok, Sock} = gen_tcp:accept(Listen),
- server_loop(Sock)
- catch
- Class:Reason:Stack ->
- Control ! {error, {Class, Reason, Stack}}
+trace_end(Config) ->
+ case proplists:get_value(tracer, Config) of
+ undefined -> ok;
+ Tracer ->
+ Mon = erlang:monitor(process, Tracer),
+ Tracer ! flush,
+ normal = receive
+ {'DOWN', Mon, process, Tracer, R} -> R
+ end
end.
-server_loop(Sock) ->
- inet:setopts(Sock, [{active, once}]),
- receive
- {tcp, Sock, Data} ->
- {call, M, F, A} = binary_to_term(Data),
- Ret =
- try
- erlang:apply(M, F, A) of
- Res ->
- {ok, Res}
- catch
- exit:Reason ->
- {error, {'EXIT', Reason}};
- error:Reason ->
- {error, {'EXIT', Reason}}
- end,
- ok = gen_tcp:send(Sock, term_to_binary(Ret)),
- server_loop(Sock);
- {tcp_closed, Sock} ->
- erlang:halt(1)
+tracer() ->
+ receive flush -> ok end,
+ io:format("Flush trace messages:\n"),
+ tracer_flush().
+
+tracer_flush() ->
+ receive M ->
+ io:format("~p\n", [M]),
+ tracer_flush()
+ after 0 ->
+ io:format("Flush done.\n")
end.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index bfdcdec836..086e54ce7f 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -435,7 +435,7 @@ close(Config) when is_list(Config) ->
{ok,Fd1} = ?PRIM_FILE:open(Name, [read, write]),
%% Just closing it is no fun, we did that a million times already
%% This is a common error, for code written before Erlang 4.3
- %% bacause then ?PRIM_FILE:open just returned a Pid, and not everyone
+ %% because then ?PRIM_FILE:open just returned a Pid, and not everyone
%% really checked what they got.
{'EXIT',_Msg} = (catch ok = ?PRIM_FILE:close({ok,Fd1})),
ok = ?PRIM_FILE:close(Fd1),
@@ -535,7 +535,7 @@ append(Config) when is_list(Config) ->
ok = ?PRIM_FILE:make_dir(NewDir),
First = "First line\n",
- Second = "Seond lines comes here\n",
+ Second = "Second lines comes here\n",
Third = "And here is the third line\n",
%% Write a small text file.
@@ -1222,7 +1222,7 @@ allocate(Config) when is_list(Config) ->
allocate_and_assert(Fd, Offset, Length) ->
%% Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have
- %% any other negative side effect. We can't really asssert against a
+ %% any other negative side effect. We can't really assert against a
%% specific return value, because support for file space pre-allocation
%% depends on the OS, OS version and underlying filesystem.
%%
@@ -1458,7 +1458,7 @@ e_rename(Config) when is_list(Config) ->
ok ->
{ok, {comment,
"Moving between filesystems "
- "suceeded, files are probably "
+ "succeeded, files are probably "
"in the same filesystem!"}};
{error, eperm} ->
{ok, {comment, "SBS! You don't "
diff --git a/lib/kernel/test/prim_file_SUITE_data/realmen.html b/lib/kernel/test/prim_file_SUITE_data/realmen.html
index c810a5d088..eaaa65523a 100644
--- a/lib/kernel/test/prim_file_SUITE_data/realmen.html
+++ b/lib/kernel/test/prim_file_SUITE_data/realmen.html
@@ -121,7 +121,7 @@ based on data structures, instead of the other way around. As all Real
Programmers know, the only useful data structure is the
array. Strings, lists, structures, sets -- these are all special cases
of arrays and and can be treated that way just as easily without
-messing up your programing language with all sorts of
+messing up your programming language with all sorts of
complications. The worst thing about fancy data types is that you have
to declare them, and Real Programming Languages, as we all know, have
implicit typing based on the first letter of the (six character)
@@ -237,7 +237,7 @@ destroy most of the interesting uses for EQUIVALENCE, and make it
impossible to modify the operating system code with negative
subscripts. Worst of all, bounds checking is inefficient.
-<LI> Source code maintainance systems. A Real Programmer keeps his
+<LI> Source code maintenance systems. A Real Programmer keeps his
code locked up in a card file, because it implies that its owner
cannot leave his important programs unguarded [5].
@@ -318,7 +318,7 @@ thing slightly more trivial than the destruction of life as we know
it, providing there's enough money in it. There are several Real
Programmers building video games at Atari, for example. (But not
playing them. A Real Programmer knows how to beat the machine every
-time: no challange in that.) Everyone working at LucasFilm is a Real
+time: no challenge in that.) Everyone working at LucasFilm is a Real
Programmer. (It would be crazy to turn down the money of 50 million
Star Wars fans.) The proportion of Real Programmers in Computer
Graphics is somewhat lower than the norm, mostly because nobody has
@@ -384,7 +384,7 @@ coffee. In some cases, the cups will contain Orange Crush.
and the Principles of Operation open to some particularly interesting
pages.
-<LI> Taped to the wall is a line-printer Snoopy calender for the year
+<LI> Taped to the wall is a line-printer Snoopy calendar for the year
1969.
<LI> Strewn about the floor are several wrappers for peanut butter
@@ -396,7 +396,7 @@ double stuff Oreos for special occasions.
<LI> Underneath the Oreos is a flow-charting template, left there by
the previous occupant of the office. (Real Programmers write programs,
-not documentation. Leave that to the maintainence people.)
+not documentation. Leave that to the maintenance people.)
</UL> <P>
diff --git a/lib/kernel/test/ram_file_SUITE_data/realmen.html b/lib/kernel/test/ram_file_SUITE_data/realmen.html
index c810a5d088..eaaa65523a 100644
--- a/lib/kernel/test/ram_file_SUITE_data/realmen.html
+++ b/lib/kernel/test/ram_file_SUITE_data/realmen.html
@@ -121,7 +121,7 @@ based on data structures, instead of the other way around. As all Real
Programmers know, the only useful data structure is the
array. Strings, lists, structures, sets -- these are all special cases
of arrays and and can be treated that way just as easily without
-messing up your programing language with all sorts of
+messing up your programming language with all sorts of
complications. The worst thing about fancy data types is that you have
to declare them, and Real Programming Languages, as we all know, have
implicit typing based on the first letter of the (six character)
@@ -237,7 +237,7 @@ destroy most of the interesting uses for EQUIVALENCE, and make it
impossible to modify the operating system code with negative
subscripts. Worst of all, bounds checking is inefficient.
-<LI> Source code maintainance systems. A Real Programmer keeps his
+<LI> Source code maintenance systems. A Real Programmer keeps his
code locked up in a card file, because it implies that its owner
cannot leave his important programs unguarded [5].
@@ -318,7 +318,7 @@ thing slightly more trivial than the destruction of life as we know
it, providing there's enough money in it. There are several Real
Programmers building video games at Atari, for example. (But not
playing them. A Real Programmer knows how to beat the machine every
-time: no challange in that.) Everyone working at LucasFilm is a Real
+time: no challenge in that.) Everyone working at LucasFilm is a Real
Programmer. (It would be crazy to turn down the money of 50 million
Star Wars fans.) The proportion of Real Programmers in Computer
Graphics is somewhat lower than the norm, mostly because nobody has
@@ -384,7 +384,7 @@ coffee. In some cases, the cups will contain Orange Crush.
and the Principles of Operation open to some particularly interesting
pages.
-<LI> Taped to the wall is a line-printer Snoopy calender for the year
+<LI> Taped to the wall is a line-printer Snoopy calendar for the year
1969.
<LI> Strewn about the floor are several wrappers for peanut butter
@@ -396,7 +396,7 @@ double stuff Oreos for special occasions.
<LI> Underneath the Oreos is a flow-charting template, left there by
the previous occupant of the office. (Real Programmers write programs,
-not documentation. Leave that to the maintainence people.)
+not documentation. Leave that to the maintenance people.)
</UL> <P>
diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl
index 90ca4addcd..8f77a9a30e 100644
--- a/lib/kernel/test/rpc_SUITE.erl
+++ b/lib/kernel/test/rpc_SUITE.erl
@@ -44,6 +44,13 @@
-include_lib("common_test/include/ct.hrl").
+-ifndef(CT_PEER).
+%% This module needs to compile on old nodes...
+-define(CT_PEER(), {ok, undefined, undefined}).
+-define(CT_PEER(Opts), {ok, undefined, undefined}).
+-define(CT_PEER_REL(Opts, Release, PrivDir), {ok, undefined, undefined}).
+-endif.
+
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,2}}].
@@ -89,17 +96,11 @@ off_heap(_Config) ->
%% Test different rpc calls.
call(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- %% Note. First part of nodename sets response delay in seconds
- {ok, N1} = test_server:start_node('3_rpc_SUITE_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N2} = test_server:start_node('1_rcp_SUITE_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N3} = test_server:start_node('4_rcp_SUITE_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N4} = test_server:start_node('8_rcp_SUITE_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- ok = io:format("~p~n", [[N1, N2, N3]]),
+ {ok, _P1, N1} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "3"]),
+ {ok, _P2, N2} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "1"]),
+ {ok, _P3, N3} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "4"]),
+ {ok, _P4, N4} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "8"]),
+ ok = io:format("~p~n", [[N1, N2, N3, N4]]),
{hej,_,N1} = rpc:call(N1, ?MODULE, f, []),
{hej,_,N2} = rpc:call(N2, ?MODULE, f, [], 2000),
{badrpc,timeout} = rpc:call(N3, ?MODULE, f, [], 2000),
@@ -107,10 +108,6 @@ call(Config) when is_list(Config) ->
[] = flush([]),
{hej,_,N4} = rpc:call(N4, ?MODULE, f, []),
{badrpc, nodedown} = rpc:call(gurka, ?MODULE, f, []),
- test_server:stop_node(N1),
- test_server:stop_node(N2),
- test_server:stop_node(N3),
- test_server:stop_node(N4),
ok.
@@ -120,9 +117,9 @@ call_reqtmo(Config) when is_list(Config) ->
[self(), SendMe],
Timeout)
end,
- reqtmo_test(Config, Fun).
+ reqtmo_test(Fun).
-reqtmo_test(Config, Test) ->
+reqtmo_test(Test) ->
%% Tests that we time out in time also when the request itself
%% does not get through. A typical issue we have had
%% in the past, is that the timeout has not triggered until
@@ -132,7 +129,7 @@ reqtmo_test(Config, Test) ->
WaitBlock = 100,
BlockTime = 1000,
- {ok, Node} = start_node(Config),
+ {ok, Peer, Node} = ?CT_PEER(),
erpc:call(Node, erts_debug, set_internal_state, [available_internal_state,
true]),
@@ -158,7 +155,7 @@ reqtmo_test(Config, Test) ->
after 0 -> ok
end,
- stop_node(Node),
+ peer:stop(Peer),
{comment,
"Timeout = " ++ integer_to_list(Timeout)
@@ -167,16 +164,10 @@ reqtmo_test(Config, Test) ->
%% Test different rpc calls.
block_call(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- %% Note. First part of nodename sets response delay in seconds
- {ok, N1} = test_server:start_node('3_rpc_SUITE_block_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N2} = test_server:start_node('1_rcp_SUITE_block_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N3} = test_server:start_node('4_rcp_SUITE_block_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N4} = test_server:start_node('8_rcp_SUITE_block_call', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, _P1, N1} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "3"]),
+ {ok, _P2, N2} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "1"]),
+ {ok, _P3, N3} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "4"]),
+ {ok, _P4, N4} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "8"]),
ok = io:format("~p~n", [[N1, N2, N3]]),
{hej,_,N1} = rpc:block_call(N1, ?MODULE, f, []),
{hej,_,N2} = rpc:block_call(N2, ?MODULE, f, [], 2000),
@@ -184,56 +175,36 @@ block_call(Config) when is_list(Config) ->
receive after 6000 -> ok end,
[] = flush([]),
{hej,_,N4} = rpc:block_call(N4, ?MODULE, f, []),
- test_server:stop_node(N1),
- test_server:stop_node(N2),
- test_server:stop_node(N3),
- test_server:stop_node(N4),
ok.
%% OTP-3449.
multicall(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- %% Note. First part of nodename sets response delay in seconds
- {ok, N1} = test_server:start_node('3_rpc_SUITE_multicall', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N2} = test_server:start_node('1_rcp_SUITE_multicall', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, _P1, N1} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "3"]),
+ {ok, _P2, N2} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "1"]),
ok = io:format("~p~n", [[N1, N2]]),
{[{hej,_,N1},{hej,_,N2}],[]} =
rpc:multicall([N1, N2], ?MODULE, f, []),
Msgs = flush([]),
[] = Msgs,
- test_server:stop_node(N1),
- test_server:stop_node(N2),
ok.
multicall_timeout(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- %% Note. First part of nodename sets response delay in seconds
- {ok, N1} = test_server:start_node('11_rpc_SUITE_multicall', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N2} = test_server:start_node('8_rpc_SUITE_multicall', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N3} = test_server:start_node('5_rpc_SUITE_multicall', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N4} = test_server:start_node('2_rcp_SUITE_multicall', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- ok = io:format("~p~n", [[N1, N2]]),
+ {ok, _P1, N1} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "11"]),
+ {ok, _P2, N2} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "8"]),
+ {ok, _P3, N3} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "5"]),
+ {ok, _P4, N4} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "2"]),
+ ok = io:format("~p~n", [[N1, N2, N3, N4]]),
{[{hej,_,N3},{hej,_,N4}],[N1, N2]} =
rpc:multicall([N3, N1, N2, N4], ?MODULE, f, [], 6000),
ct:sleep({seconds,8}), %Wait for late answers
Msgs = flush([]),
[] = Msgs,
- test_server:stop_node(N1),
- test_server:stop_node(N2),
- test_server:stop_node(N3),
- test_server:stop_node(N4),
ok.
multicall_reqtmo(Config) when is_list(Config) ->
- {ok, QuickNode1} = start_node(Config),
- {ok, QuickNode2} = start_node(Config),
+ {ok, Peer1, QuickNode1} = ?CT_PEER(),
+ {ok, Peer2, QuickNode2} = ?CT_PEER(),
Fun = fun (Node, SendMe, Timeout) ->
Me = self(),
SlowSend = fun () ->
@@ -249,18 +220,15 @@ multicall_reqtmo(Config) when is_list(Config) ->
erlang, apply, [SlowSend, []],
Timeout)
end,
- Res = reqtmo_test(Config, Fun),
- stop_node(QuickNode1),
- stop_node(QuickNode2),
+ Res = reqtmo_test(Fun),
+ peer:stop(Peer1),
+ peer:stop(Peer2),
Res.
multicall_dies(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- {ok, N1} = test_server:start_node('rpc_SUITE_multicall_dies_1', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N2} = test_server:start_node('rcp_SUITE_multicall_dies_2', slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, P1, N1} = ?CT_PEER(["-connect_all", "false"]),
+ {ok, P2, N2} = ?CT_PEER(["-connect_all", "false"]),
Nodes = [N1, N2],
%%
{[{badrpc, {'EXIT', normal}}, {badrpc, {'EXIT', normal}}], []} =
@@ -290,8 +258,8 @@ multicall_dies(Config) when is_list(Config) ->
{[{badrpc, {'EXIT', killed}}, {badrpc, {'EXIT', killed}}], []} =
do_multicall(Nodes, ?MODULE, suicide, [exit, kill]),
%%
- test_server:stop_node(N1),
- test_server:stop_node(N2),
+ peer:stop(P1),
+ peer:stop(P2),
ok.
do_multicall(Nodes, Mod, Func, Args) ->
@@ -311,11 +279,8 @@ multicall_node_dies(Config) when is_list(Config) ->
do_multicall_2_nodes_dies(Mod, Func, Args) ->
ok = io:format("~p:~p~p~n", [Mod, Func, Args]),
- PA = filename:dirname(code:which(?MODULE)),
- {ok, N1} = test_server:start_node('rpc_SUITE_multicall_node_dies_1', peer,
- [{args, "-connect_all false -pa " ++ PA}]),
- {ok, N2} = test_server:start_node('rcp_SUITE_multicall_node_dies_2', peer,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, _P1, N1} = ?CT_PEER(#{connection => 0, args => ["-connect_all", "false"]}),
+ {ok, _P2, N2} = ?CT_PEER(#{connection => 0, args => ["-connect_all", "false"]}),
Nodes = [N1, N2],
case {Mod, Func, rpc:multicall(Nodes, Mod, Func, Args)} of
{_, _, {[], Nodes}} ->
@@ -336,9 +301,7 @@ do_multicall_2_nodes_dies(Mod, Func, Args) ->
%% OTP-3766.
called_dies(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- {ok, N} = test_server:start_node(rpc_SUITE_called_dies, slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, P, N} = ?CT_PEER(["-connect_all", "false"]),
%%
rep(fun (Tag, Call, Args) ->
{Tag,{badrpc,{'EXIT',normal}}} =
@@ -425,7 +388,7 @@ called_dies(Config) when is_list(Config) ->
end, N, ?MODULE, suicide, [exit,kill]),
%%
[] = flush([]),
- test_server:stop_node(N),
+ peer:stop(P),
ok.
rep(Fun, N, M, F, A) ->
@@ -470,27 +433,22 @@ suicide(Mod, Func, Args) ->
called_node_dies(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
-
node_rep(
fun (Call, Args) ->
{badrpc,nodedown} = apply(rpc, Call, Args)
- end, "rpc_SUITE_called_node_dies_1",
- PA, ?MODULE, suicide, [erlang,halt,[]]),
+ end, ?MODULE, suicide, [erlang,halt,[]]),
node_rep(
fun (Call, Args) ->
{badrpc,nodedown} = apply(rpc, Call, Args)
- end, "rpc_SUITE_called_node_dies_2",
- PA, ?MODULE, suicide, [init,stop,[]]),
+ end, ?MODULE, suicide, [init,stop,[]]),
node_rep(
fun (block_call, Args=[_|_]) ->
{badrpc,{'EXIT',{killed,_}}} = apply(rpc, block_call, Args);
(call, Args=[_|_]) ->
{badrpc,nodedown} = apply(rpc, call, Args)
- end, "rpc_SUITE_called_node_dies_3",
- PA, ?MODULE, suicide, [erlang,exit,[rex,kill]]),
+ end, ?MODULE, suicide, [erlang,exit,[rex,kill]]),
node_rep(
fun (block_call, _Args) ->
@@ -498,31 +456,24 @@ called_node_dies(Config) when is_list(Config) ->
ok;
(Call, Args=[_|_]) ->
{badrpc,nodedown} = apply(rpc, Call, Args)
- end, "rpc_SUITE_called_node_dies_4",
- PA, ?MODULE, suicide, [rpc,stop,[]]),
+ end, ?MODULE, suicide, [rpc,stop,[]]),
ok.
-node_rep(Fun, Name, PA, M, F, A) ->
- node_rep_call(a, call, [M,F,A], Fun, Name, PA),
- node_rep_call(b, call, [M,F,A,infinity], Fun, Name, PA),
- node_rep_call(c, block_call, [M,F,A], Fun, Name, PA),
- node_rep_call(d, block_call, [M,F,A,infinity], Fun, Name, PA).
+node_rep(Fun, M, F, A) ->
+ node_rep_call(call, [M,F,A], Fun),
+ node_rep_call(call, [M,F,A,infinity], Fun),
+ node_rep_call(block_call, [M,F,A], Fun),
+ node_rep_call(block_call, [M,F,A,infinity], Fun).
-node_rep_call(Tag, Call, Args, Fun, Name0, PA) ->
- Name = list_to_atom(Name0 ++ "_" ++ atom_to_list(Tag)),
- {ok, N} = test_server:start_node(Name, slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+node_rep_call(Call, Args, Fun) ->
+ {ok, _P, N} = ?CT_PEER(#{connection => 0, args => ["-connect_all", "false"]}),
Fun(Call, [N|Args]),
- catch test_server:stop_node(N),
ok.
%% OTP-3766.
called_throws(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- %%
- {ok, N} = test_server:start_node(rpc_SUITE_called_throws, slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, P, N} = ?CT_PEER(["-connect_all", "false"]),
%%
rep(fun (Tag, Call, Args) ->
{Tag,up} =
@@ -533,21 +484,19 @@ called_throws(Config) when is_list(Config) ->
{Tag,apply(rpc, Call, Args)}
end, N, erlang, throw, [{'EXIT',reason}]),
%%
- test_server:stop_node(N),
+ peer:stop(P),
ok.
call_benchmark(Config) when is_list(Config) ->
- PA = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(rpc_SUITE_call_benchmark, slave,
- [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, Peer, Node} = ?CT_PEER(["-connect_all", "false"]),
Iter = case erlang:system_info(modified_timing_level) of
undefined -> 10000;
_ -> 500 %Modified timing - spawn is slower
end,
Res = do_call_benchmark(Node, Iter),
- test_server:stop_node(Node),
+ peer:stop(Peer),
Res.
do_call_benchmark(Node, M) when is_integer(M), M > 0 ->
@@ -567,12 +516,10 @@ do_call_benchmark(Node, I, M) ->
do_call_benchmark(Node, I+1, M).
async_call(Config) when is_list(Config) ->
+ {ok, _Peer1, Node1} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "1"]),
+ {ok, _Peer2, Node2} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "10"]),
+ {ok, _Peer3, Node3} = ?CT_PEER(["-connect_all", "false", "-rpc_test_delay", "20"]),
%% Note: First part of nodename sets response delay in seconds.
- PA = filename:dirname(code:which(?MODULE)),
- NodeArgs = [{args,"-connect_all false -pa "++ PA}],
- {ok,Node1} = test_server:start_node('1_rpc_SUITE_call', slave, NodeArgs),
- {ok,Node2} = test_server:start_node('10_rpc_SUITE_call', slave, NodeArgs),
- {ok,Node3} = test_server:start_node('20_rpc_SUITE_call', slave, NodeArgs),
Promise1 = rpc:async_call(Node1, ?MODULE, f, []),
Promise2 = rpc:async_call(Node2, ?MODULE, f, []),
Promise3 = rpc:async_call(Node3, ?MODULE, f, []),
@@ -588,32 +535,37 @@ async_call(Config) when is_list(Config) ->
%% Wait for the Node2 and Node3.
{value,{hej,_,Node2}} = rpc:nb_yield(Promise2, infinity),
{hej,_,Node3} = rpc:yield(Promise3),
-
ok.
call_against_old_node(Config) ->
- case start_22_node(Config) of
- {ok, Node22} ->
- Node22 = rpc:call(Node22, erlang, node, []),
- stop_node(Node22),
- ok;
- _ ->
- {skipped, "No OTP 22 available"}
+ {OldRelName, OldRel} = old_release(),
+ case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ {skipped, "No OTP "++OldRel++" available"};
+ {ok, PeerOld, NodeOld} ->
+ NodeOld = rpc:call(NodeOld, erlang, node, []),
+ peer:stop(PeerOld),
+ ok
end.
multicall_mix(Config) ->
- {ok, Node1} = start_peer_node(Config),
- {ok, Node2} = start_peer_node(Config),
- {Node3, OldNodeTest} = case start_22_node(Config) of
- {ok, N3} ->
- {N3, true};
- _ ->
- {ok, N3} = start_peer_node(Config),
- {N3, false}
- end,
- {ok, Node4} = start_peer_node(Config),
- {ok, Node5} = start_peer_node(Config),
- stop_node(Node2),
+ {ok, _Peer1, Node1} = ?CT_PEER(#{connection => 0}),
+ {ok, Peer2, Node2} = ?CT_PEER(#{connection => 0}),
+ {OldRelName, OldRel} = old_release(),
+ {{ok, _Peer3, Node3}, OldNodeTest}
+ = case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ {ok, _, _} = OldNRes ->
+ {OldNRes, true};
+ not_available ->
+ {?CT_PEER(#{connection => 0}), false}
+ end,
+ {ok, _Peer4, Node4} = ?CT_PEER(#{connection => 0}),
+ {ok, _Peer5, Node5} = ?CT_PEER(#{connection => 0}),
+ peer:stop(Peer2),
[] = flush([]),
@@ -711,8 +663,8 @@ multicall_mix(Config) ->
[] = flush([]),
case OldNodeTest of
- true -> {comment, "Test with OTP 22 node as well"};
- false -> {comment, "Test without OTP 22"}
+ true -> {comment, "Test with OTP "++OldRel++" node as well"};
+ false -> {comment, "Test without OTP "++OldRel}
end.
call_func1(X) ->
@@ -768,51 +720,51 @@ timeout_limit(Config) when is_list(Config) ->
call_old_against_new(Config) ->
- case test_server:is_release_available("22_latest") of
- false ->
- {skipped, "No OTP 22 available"};
- true ->
- test_on_22_node(Config, call_old_against_new_test, 1, 1)
+ try
+ test_on_old_node(Config, call_old_against_new_test, 1, 1)
+ catch
+ throw:{skipped, _} = Skipped ->
+ Skipped
end.
-call_old_against_new_test([Node22], [NodeCurr]) ->
- %% Excecuted on an OTP 22 node
+call_old_against_new_test([NodeOld], [NodeCurr]) ->
+ %% Executed on an OTP old node
- Node22 = rpc:call(Node22, erlang, node, []),
+ NodeOld = rpc:call(NodeOld, erlang, node, []),
NodeCurr = rpc:call(NodeCurr, erlang, node, []),
- {badrpc, {'EXIT', bang}} = rpc:call(Node22, erlang, exit, [bang]),
+ {badrpc, {'EXIT', bang}} = rpc:call(NodeOld, erlang, exit, [bang]),
{badrpc, {'EXIT', bang}} = rpc:call(NodeCurr, erlang, exit, [bang]),
- {badrpc, {'EXIT', {blong, _}}} = rpc:call(Node22, erlang, error, [blong]),
+ {badrpc, {'EXIT', {blong, _}}} = rpc:call(NodeOld, erlang, error, [blong]),
{badrpc, {'EXIT', {blong, _}}} = rpc:call(NodeCurr, erlang, error, [blong]),
- bling = rpc:call(Node22, erlang, throw, [bling]),
+ bling = rpc:call(NodeOld, erlang, throw, [bling]),
bling = rpc:call(NodeCurr, erlang, throw, [bling]),
- {badrpc, timeout} = rpc:call(Node22, timer, sleep, [1000], 100),
+ {badrpc, timeout} = rpc:call(NodeOld, timer, sleep, [1000], 100),
{badrpc, timeout} = rpc:call(NodeCurr, timer, sleep, [1000], 100),
- {badrpc, nodedown} = rpc:call(Node22, erlang, halt, []),
+ {badrpc, nodedown} = rpc:call(NodeOld, erlang, halt, []),
{badrpc, nodedown} = rpc:call(NodeCurr, erlang, halt, []),
- {badrpc, nodedown} = rpc:call(Node22, erlang, node, []),
+ {badrpc, nodedown} = rpc:call(NodeOld, erlang, node, []),
{badrpc, nodedown} = rpc:call(NodeCurr, erlang, node, []),
ok.
multicall_old_against_new(Config) ->
- case test_server:is_release_available("22_latest") of
- false ->
- {skipped, "No OTP 22 available"};
- true ->
- test_on_22_node(Config, multicall_old_against_new_test, 2, 2)
+ try
+ test_on_old_node(Config, multicall_old_against_new_test, 2, 2)
+ catch
+ throw:{skipped, _} = Skipped ->
+ Skipped
end.
-multicall_old_against_new_test([Node22A, Node22B], [NodeCurrA, NodeCurrB]) ->
- %% Excecuted on an OTP 22 node
+multicall_old_against_new_test([NodeOldA, NodeOldB], [NodeCurrA, NodeCurrB]) ->
+ %% Executed on an OTP old node
- AllNodes = [NodeCurrA, Node22A, NodeCurrB, Node22B],
+ AllNodes = [NodeCurrA, NodeOldA, NodeCurrB, NodeOldB],
NoNodes = length(AllNodes),
{AllNodes, []} = rpc:multicall(AllNodes, erlang, node, []),
@@ -839,32 +791,32 @@ multicall_old_against_new_test([Node22A, Node22B], [NodeCurrA, NodeCurrB]) ->
ok.
cast_old_against_new(Config) ->
- case test_server:is_release_available("22_latest") of
- false ->
- {skipped, "No OTP 22 available"};
- true ->
- test_on_22_node(Config, cast_old_against_new_test, 1, 1)
+ try
+ test_on_old_node(Config, cast_old_against_new_test, 1, 1)
+ catch
+ throw:{skipped, _} = Skipped ->
+ Skipped
end.
-cast_old_against_new_test([Node22], [NodeCurr]) ->
- %% Excecuted on an OTP 22 node
+cast_old_against_new_test([NodeOld], [NodeCurr]) ->
+ %% Executed on an OTP old node
Me = self(),
Ref = make_ref(),
- true = rpc:cast(Node22, erlang, send, [Me, {Ref, 1}]),
+ true = rpc:cast(NodeOld, erlang, send, [Me, {Ref, 1}]),
receive {Ref, 1} -> ok end,
true = rpc:cast(NodeCurr, erlang, send, [Me, {Ref, 2}]),
receive {Ref, 2} -> ok end,
- true = rpc:cast(Node22, erlang, halt, []),
+ true = rpc:cast(NodeOld, erlang, halt, []),
true = rpc:cast(NodeCurr, erlang, halt, []),
- monitor_node(Node22, true),
- receive {nodedown, Node22} -> ok end,
+ monitor_node(NodeOld, true),
+ receive {nodedown, NodeOld} -> ok end,
monitor_node(NodeCurr, true),
receive {nodedown, NodeCurr} -> ok end,
- true = rpc:cast(Node22, erlang, send, [Me, {Ref, 3}]),
+ true = rpc:cast(NodeOld, erlang, send, [Me, {Ref, 3}]),
true = rpc:cast(NodeCurr, erlang, send, [Me, {Ref, 4}]),
receive Msg -> error({unexcpected_message, Msg})
@@ -875,42 +827,9 @@ cast_old_against_new_test([Node22], [NodeCurr]) ->
%%% Utility functions.
%%%
-start_peer_node(Config) ->
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, peer, [{args, "-pa " ++ Pa}]).
-
-start_node(Config) ->
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, "-pa " ++ Pa}]).
-
-start_22_node(Config) ->
- Rel = "22_latest",
- case test_server:is_release_available(Rel) of
- false ->
- notsup;
- true ->
- Cookie = atom_to_list(erlang:get_cookie()),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(erlang:system_time(second))
- ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))),
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name,
- peer,
- [{args, "-pa " ++ Pa ++ " -setcookie "++Cookie},
- {erl, [{release, Rel}]}])
- end.
-
-stop_node(Node) ->
- test_server:stop_node(Node).
+old_release() ->
+ OldRel = integer_to_list(list_to_integer(erlang:system_info(otp_release))-2),
+ {OldRel++"_latest", OldRel}.
flush(L) ->
receive
@@ -921,8 +840,11 @@ flush(L) ->
end.
t() ->
- [N | _] = string:tokens(atom_to_list(node()), "_"),
- 1000*list_to_integer(N).
+ Delay = case init:get_argument(rpc_test_delay) of
+ {ok,[[D]]} -> list_to_integer(D);
+ _ -> 0
+ end,
+ 1000*Delay.
f() ->
timer:sleep(T=t()),
@@ -933,33 +855,37 @@ f2() ->
timer:sleep(500),
halt().
-test_on_22_node(Config, Test, No22, NoCurr) ->
- Nodes22 = lists:map(fun (_) ->
- {ok, N} = start_22_node(Config),
- N
- end,
- lists:seq(1, No22+1)),
- NodesCurr = lists:map(fun (_) ->
- {ok, N} = start_node(Config),
- N
- end,
- lists:seq(1, NoCurr)),
-
- %% Recompile rpc_SUITE on OTP 22 node and load it on all OTP 22 nodes...
+test_on_old_node(Config, Test, NoOld, NoCurr) ->
+ {OldRelName, OldRel} = old_release(),
+ NodesOldRes = lists:map(fun (_) ->
+ case ?CT_PEER_REL(#{connection => 0},
+ OldRelName,
+ proplists:get_value(priv_dir, Config)) of
+ not_available ->
+ throw({skipped, "No OTP "++OldRel++" available"});
+ {ok, _, _} = Ok ->
+ Ok
+ end
+ end,
+ lists:seq(1, NoOld+1)),
+ NodesCurrRes = lists:map(fun (_) ->
+ {ok, _, _} = ?CT_PEER()
+ end,
+ lists:seq(1, NoCurr)),
+ NFun = fun ({ok, _Peer, Node}) -> Node end,
+ NodesOld = lists:map(NFun, NodesOldRes),
+ NodesCurr = lists:map(NFun, NodesCurrRes),
+
+ %% Recompile rpc_SUITE on old node and load it on all old nodes...
SrcFile = filename:rootname(code:which(?MODULE)) ++ ".erl",
- {ok, ?MODULE, BeamCode} = rpc:call(hd(Nodes22), compile, file, [SrcFile, [binary]]),
- LoadResult = lists:duplicate(length(Nodes22), {module, ?MODULE}),
- {LoadResult, []} = rpc:multicall(Nodes22, code, load_binary, [?MODULE, SrcFile, BeamCode]),
- try
- %% Excecute test on first OTP 22 node...
- Pid = spawn_link(hd(Nodes22), ?MODULE, Test, [tl(Nodes22), NodesCurr]),
- Mon = erlang:monitor(process, Pid),
- receive
- {'DOWN', Mon, process, Pid, Reason} when Reason == normal; Reason == noproc ->
- ok
- end
- after
- lists:foreach(fun (N) -> stop_node(N) end, Nodes22),
- lists:foreach(fun (N) -> stop_node(N) end, NodesCurr)
+ {ok, ?MODULE, BeamCode} = rpc:call(hd(NodesOld), compile, file, [SrcFile, [binary]]),
+ LoadResult = lists:duplicate(length(NodesOld), {module, ?MODULE}),
+ {LoadResult, []} = rpc:multicall(NodesOld, code, load_binary, [?MODULE, SrcFile, BeamCode]),
+ %% Execute test on first old node...
+ Pid = spawn_link(hd(NodesOld), ?MODULE, Test, [tl(NodesOld), NodesCurr]),
+ Mon = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', Mon, process, Pid, Reason} when Reason == normal; Reason == noproc ->
+ ok
end,
ok.
diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl
index e7bed56510..af409e33db 100644
--- a/lib/kernel/test/sendfile_SUITE.erl
+++ b/lib/kernel/test/sendfile_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -350,7 +350,9 @@ t_sendfile_recvduring(Config) ->
{ok, #file_info{size = Size}} =
file:read_file_info(Filename),
spawn_link(fun() ->
- timer:sleep(1),
+ %% We sleep to allow file:sendfile to be
+ %% called before this send.
+ timer:sleep(10),
ok = gen_tcp:send(Sock, <<1>>),
{ok,<<1>>} = gen_tcp:recv(Sock, 1)
end),
@@ -488,10 +490,9 @@ sendfile_send(Host, Send, Orig, SockOpts) ->
Opts = [binary,{packet,0}|SockOpts],
io:format("connect with opts = ~p\n", [Opts]),
{ok, Sock} = gen_tcp:connect(Host, Port, Opts),
- Data = case proplists:get_value(arity,erlang:fun_info(Send)) of
- 1 ->
+ Data = if is_function(Send, 1) ->
Send(Sock);
- 2 ->
+ is_function(Send, 2) ->
Send(Sock, SFServer)
end,
ok = gen_tcp:close(Sock),
diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl
index f6140d16ed..6e3cb08af3 100644
--- a/lib/kernel/test/seq_trace_SUITE.erl
+++ b/lib/kernel/test/seq_trace_SUITE.erl
@@ -19,9 +19,6 @@
%%
-module(seq_trace_SUITE).
-%% label_capability_mismatch needs to run a part of the test on an OTP 20 node.
--compile(r20).
-
-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]).
@@ -30,7 +27,7 @@
send/1, distributed_send/1, recv/1, distributed_recv/1,
trace_exit/1, distributed_exit/1, call/1, port/1,
port_clean_token/1,
- match_set_seq_token/1, gc_seq_token/1, label_capability_mismatch/1,
+ match_set_seq_token/1, gc_seq_token/1,
send_literal/1,inherit_on_spawn/1,inherit_on_dist_spawn/1,
dist_spawn_error/1]).
@@ -57,7 +54,7 @@ all() ->
old_heap_token, mature_heap_token,
distributed_exit, call, port, match_set_seq_token,
port_clean_token,
- gc_seq_token, label_capability_mismatch,
+ gc_seq_token,
inherit_on_spawn, inherit_on_dist_spawn, dist_spawn_error].
groups() ->
@@ -249,10 +246,7 @@ distributed_send(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_send/1, ?TIMESTAMP_MODES).
do_distributed_send(TsType) ->
- {ok,Node} = start_node(seq_trace_other,[]),
- {_,Dir} = code:is_loaded(?MODULE),
- Mdir = filename:dirname(Dir),
- true = rpc:call(Node,code,add_patha,[Mdir]),
+ {ok, Peer, Node} = ?CT_PEER(),
seq_trace:reset_trace(),
start_tracer(),
Tester = self(),
@@ -276,7 +270,7 @@ do_distributed_send(TsType) ->
Self = self(),
seq_trace:reset_trace(),
- stop_node(Node),
+ peer:stop(Peer),
[{Label,{send,_,Self,Receiver,send}, Ts1},
{Label,{send,_,Self,{n_time_receiver,Node}, "dsend"}, Ts2},
{Label,{send,_,Self,Alias,"alias_dsend"}, Ts3}
@@ -317,10 +311,7 @@ distributed_recv(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_recv/1, ?TIMESTAMP_MODES).
do_distributed_recv(TsType) ->
- {ok,Node} = start_node(seq_trace_other,[]),
- {_,Dir} = code:is_loaded(?MODULE),
- Mdir = filename:dirname(Dir),
- true = rpc:call(Node,code,add_patha,[Mdir]),
+ {ok, Peer, Node} = ?CT_PEER(),
seq_trace:reset_trace(),
rpc:call(Node,?MODULE,start_tracer,[]),
Tester = self(),
@@ -346,7 +337,7 @@ do_distributed_recv(TsType) ->
Self = self(),
seq_trace:reset_trace(),
Result = rpc:call(Node,?MODULE,stop_tracer,[2]),
- stop_node(Node),
+ peer:stop(Peer),
ok = io:format("~p~n",[Result]),
[{Label,{'receive',_,Self,Receiver,'alias_receive'}, Ts1},
{Label,{'receive',_,Self,Receiver,'receive'}, Ts2}] = Result,
@@ -390,10 +381,7 @@ distributed_exit(Config) when is_list(Config) ->
lists:foreach(fun do_distributed_exit/1, ?TIMESTAMP_MODES).
do_distributed_exit(TsType) ->
- {ok, Node} = start_node(seq_trace_other, []),
- {_, Dir} = code:is_loaded(?MODULE),
- Mdir = filename:dirname(Dir),
- true = rpc:call(Node, code, add_patha, [Mdir]),
+ {ok, Peer, Node} = ?CT_PEER(),
seq_trace:reset_trace(),
rpc:call(Node, ?MODULE, start_tracer,[]),
Receiver = spawn_link(Node, ?MODULE, one_time_receiver, [exit]),
@@ -411,81 +399,14 @@ do_distributed_exit(TsType) ->
Self = self(),
Result = rpc:call(Node, ?MODULE, stop_tracer, [1]),
seq_trace:reset_trace(),
- stop_node(Node),
+ process_flag(trap_exit, false),
+ peer:stop(Peer),
ok = io:format("~p~n", [Result]),
[{0, {send, {1, 2}, Receiver, Self,
{'EXIT', Receiver, {exit, {before, exit}}}}, Ts}] = Result,
check_ts(TsType, Ts).
-label_capability_mismatch(Config) when is_list(Config) ->
- Releases = ["20_latest"],
- Available = [Rel || Rel <- Releases, test_server:is_release_available(Rel)],
- case Available of
- [] -> {skipped, "No incompatible releases available"};
- _ ->
- lists:foreach(fun do_incompatible_labels/1, Available),
- lists:foreach(fun do_compatible_labels/1, Available),
- ok
- end.
-
-do_incompatible_labels(Rel) ->
- Cookie = atom_to_list(erlang:get_cookie()),
- {ok, Node} = test_server:start_node(
- list_to_atom(atom_to_list(?MODULE)++"_"++Rel), peer,
- [{args, " -setcookie "++Cookie}, {erl, [{release, Rel}]}]),
-
- {_,Dir} = code:is_loaded(?MODULE),
- Mdir = filename:dirname(Dir),
- true = rpc:call(Node,code,add_patha,[Mdir]),
- seq_trace:reset_trace(),
- true = is_pid(rpc:call(Node,?MODULE,start_tracer,[])),
- Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
-
- %% This node does not support arbitrary labels, so it must fail with a
- %% timeout as the token is dropped silently.
- seq_trace:set_token(label,make_ref()),
- seq_trace:set_token('receive',true),
-
- Receiver ! 'receive',
- %% let the other process receive the message:
- receive after 10 -> ok end,
- seq_trace:reset_trace(),
-
- {error,timeout} = rpc:call(Node,?MODULE,stop_tracer,[1]),
- stop_node(Node),
- ok.
-
-do_compatible_labels(Rel) ->
- Cookie = atom_to_list(erlang:get_cookie()),
- {ok, Node} = test_server:start_node(
- list_to_atom(atom_to_list(?MODULE)++"_"++Rel), peer,
- [{args, " -setcookie "++Cookie}, {erl, [{release, Rel}]}]),
-
- {_,Dir} = code:is_loaded(?MODULE),
- Mdir = filename:dirname(Dir),
- true = rpc:call(Node,code,add_patha,[Mdir]),
- seq_trace:reset_trace(),
- true = is_pid(rpc:call(Node,?MODULE,start_tracer,[])),
- Receiver = spawn(Node,?MODULE,one_time_receiver,[]),
-
- %% This node does not support arbitrary labels, but small integers should
- %% still work.
- Label = 1234,
- seq_trace:set_token(label,Label),
- seq_trace:set_token('receive',true),
-
- Receiver ! 'receive',
- %% let the other process receive the message:
- receive after 10 -> ok end,
- Self = self(),
- seq_trace:reset_trace(),
- Result = rpc:call(Node,?MODULE,stop_tracer,[1]),
- stop_node(Node),
- ok = io:format("~p~n",[Result]),
- [{Label,{'receive',_,Self,Receiver,'receive'}, _}] = Result,
- ok.
-
-call(doc) ->
+call(doc) ->
"Tests special forms {is_seq_trace} and {get_seq_token} "
"in trace match specs.";
call(Config) when is_list(Config) ->
@@ -734,8 +655,7 @@ inherit_on_dist_spawn(Config) when is_list(Config) ->
inherit_on_dist_spawn_test(Spawn) ->
io:format("Testing ~p()~n", [Spawn]),
- Pa = "-pa "++filename:dirname(code:which(?MODULE)),
- {ok, Node} = start_node(seq_trace_dist_spawn, Pa),
+ {ok, Peer, Node} = ?CT_PEER(),
%% ensure module is loaded on remote node...
_ = rpc:call(Node, ?MODULE, module_info, []),
@@ -865,13 +785,12 @@ inherit_on_dist_spawn_test(Spawn) ->
unlink(Other),
- stop_node(Node),
+ peer:stop(Peer),
ok.
dist_spawn_error(Config) when is_list(Config) ->
- Pa = "-pa "++filename:dirname(code:which(?MODULE)),
- {ok, Node} = start_node(seq_trace_dist_spawn, Pa),
+ {ok, Peer, Node} = ?CT_PEER(),
%% ensure module is loaded on remote node...
_ = rpc:call(Node, ?MODULE, module_info, []),
@@ -957,7 +876,7 @@ dist_spawn_error(Config) when is_list(Config) ->
{spawn_reply, ReqId, error, badopt}},
_} = StSpawnReplyNode,
- stop_node(Node),
+ peer:stop(Peer),
ok.
@@ -1079,7 +998,7 @@ match_set_seq_token(Config) when is_list(Config) ->
%% All the timeout stuff is here to get decent accuracy of the error
%% return value, instead of just 'timeout'.
%%
- {ok, Sandbox} = start_node(seq_trace_other, []),
+ {ok, Peer, Sandbox} = ?CT_PEER(),
true = rpc:call(Sandbox, code, add_patha,
[filename:dirname(code:which(?MODULE))]),
Lbl = 4711,
@@ -1124,7 +1043,7 @@ match_set_seq_token(Config) when is_list(Config) ->
ok = check_match_set_seq_token_log(Lbl, SortedLog),
%%
- stop_node(Sandbox),
+ peer:stop(Peer),
ok.
%% OTP-4222 Match spec 'set_seq_token' corrupts heap
@@ -1230,7 +1149,7 @@ gc_seq_token(Config) when is_list(Config) ->
%% All the timeout stuff is here to get decent accuracy of the error
%% return value, instead of just 'timeout'.
%%
- {ok, Sandbox} = start_node(seq_trace_other, []),
+ {ok, Peer, Sandbox} = ?CT_PEER(),
true = rpc:call(Sandbox, code, add_patha,
[filename:dirname(code:which(?MODULE))]),
Label = 4711,
@@ -1268,7 +1187,7 @@ gc_seq_token(Config) when is_list(Config) ->
{error, "Test node hung"}
end,
%%
- stop_node(Sandbox),
+ peer:stop(Peer),
ok.
do_gc_seq_token(Label) ->
@@ -1554,12 +1473,6 @@ check_ts(strict_monotonic_timestamp, Ts) ->
end,
ok.
-start_node(Name, Param) ->
- test_server:start_node(Name, peer, [{args, Param}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
load_tracer(Config) ->
Path = proplists:get_value(data_dir, Config),
ok = erl_ddll:load_driver(Path, echo_drv),
diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl
index 03ee74ef29..673c905ddf 100644
--- a/lib/kernel/test/socket_SUITE.erl
+++ b/lib/kernel/test/socket_SUITE.erl
@@ -24,9 +24,13 @@
%% Variable that controls which 'groups' are to run (with default values)
%%
%% ESOCK_TEST_API: include
+%% ESOCK_TEST_REG: include
+%% ESOCK_TEST_MON: include
+%% ESOCK_TEST_IOCTL: include
%% ESOCK_TEST_SOCK_CLOSE: include
%% ESOCK_TEST_TRAFFIC: include
-%% ESOCK_TEST_TTEST: exclude
+%% ESOCK_TEST_TICKETS: include
+%% ESOCK_TEST_TTEST: include
%%
%% Variable that controls "verbosity" of the test case(s):
%%
@@ -37,13 +41,23 @@
%% the actual time it takes for the test case to complete
%% will be longer; setup, completion, ...)
%%
-%% ESOCK_TEST_TTEST_RUNTIME: 10 seconds
+%% ESOCK_TEST_TTEST_RUNTIME: 1 second
%% Format of values: <integer>[<unit>]
%% Where unit is: ms | s | m
%% ms - milli seconds
%% s - seconds (default)
%% m - minutes
%%
+%% The ttest takes a long time to run, even when the runtime is small,
+%% because there are such a large number of test cases.
+%% So, by default only the 'small' test cases are included in a test run.
+%% The following environment variables control which are included and
+%% excluded.
+%%
+%% ESOCK_TEST_TTEST_SMALL: included
+%% ESOCK_TEST_TTEST_MEDIUM: excluded
+%% ESOCK_TEST_TTEST_LARGE: excluded
+%%
%% Run the entire test suite:
%% ts:run(emulator, socket_SUITE, [batch]).
@@ -197,7 +211,7 @@
api_opt_sock_sndtimeo_udp4/1,
api_opt_sock_timestamp_udp4/1,
api_opt_sock_timestamp_tcp4/1,
- api_opt_ip_add_drop_membership/1,
+ api_opt_ip_add_drop_membership/0, api_opt_ip_add_drop_membership/1,
api_opt_ip_pktinfo_udp4/1,
api_opt_ip_recvopts_udp4/1,
api_opt_ip_recvorigdstaddr_udp4/1,
@@ -477,10 +491,10 @@
ttest_sgent_cgent_small_tcp4/1,
ttest_sgent_cgent_small_tcp6/1,
- ttest_sgent_cgent_medium_tcp4/1,
- ttest_sgent_cgent_medium_tcp6/1,
- ttest_sgent_cgent_large_tcp4/1,
- ttest_sgent_cgent_large_tcp6/1,
+ ttest_sgent_cgent_medium_tcp4/0, ttest_sgent_cgent_medium_tcp4/1,
+ ttest_sgent_cgent_medium_tcp6/0, ttest_sgent_cgent_medium_tcp6/1,
+ ttest_sgent_cgent_large_tcp4/0, ttest_sgent_cgent_large_tcp4/1,
+ ttest_sgent_cgent_large_tcp6/0, ttest_sgent_cgent_large_tcp6/1,
%% Server: transport = gen_tcp, active = true
%% Client: transport = socket(tcp)
@@ -673,7 +687,9 @@
%% Tickets
otp16359_maccept_tcp4/1,
otp16359_maccept_tcp6/1,
- otp16359_maccept_tcpL/1
+ otp16359_maccept_tcpL/1,
+ otp18240_accept_mon_leak_tcp4/1,
+ otp18240_accept_mon_leak_tcp6/1
]).
@@ -684,6 +700,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(LIB, socket_test_lib).
+-define(KLIB, kernel_test_lib).
-define(TTEST_LIB, socket_test_ttest_lib).
-define(LOGGER, socket_test_logger).
@@ -712,9 +729,29 @@
-define(TPP_SMALL_NUM, 5000).
-define(TPP_MEDIUM_NUM, 500).
-define(TPP_LARGE_NUM, 50).
--define(TPP_NUM(Config, Base), (Base) div lookup(esock_factor, 1, Config)).
+-define(TPP_NUM(Config, Base), (Base) div lookup(kernel_factor, 1, Config)).
+
+-define(TTEST_RUNTIME, ?SECS(1)).
+-define(TTEST_MIN_FACTOR, 3).
+-define(TTEST_DEFAULT_SMALL_MAX_OUTSTANDING, 50).
+-define(TTEST_DEFAULT_MEDIUM_MAX_OUTSTANDING,
+ ?TTEST_MK_DEFAULT_MAX_OUTSTANDING(
+ ?TTEST_DEFAULT_SMALL_MAX_OUTSTANDING)).
+-define(TTEST_DEFAULT_LARGE_MAX_OUTSTANDING,
+ ?TTEST_MK_DEFAULT_MAX_OUTSTANDING(
+ ?TTEST_DEFAULT_MEDIUM_MAX_OUTSTANDING)).
--define(TTEST_RUNTIME, ?SECS(10)).
+-define(TTEST_MK_DEFAULT_MAX_OUTSTANDING(__X__),
+ if ((__X__) >= 5) ->
+ (__X__) div 5;
+ true ->
+ 1
+ end).
+
+-define(START_NODE(NamePre),
+ ?START_NODE(NamePre, 5000)).
+-define(START_NODE(NamePre, Timeout),
+ start_node(?CT_PEER_NAME(NamePre), Timeout)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -725,12 +762,12 @@ suite() ->
all() ->
Groups = [{api, "ESOCK_TEST_API", include},
- {reg, undefined, include},
- {monitor, undefined, include},
- {ioctl, undefined, include},
+ {reg, "ESOCK_TEST_REG", include},
+ {monitor, "ESOCK_TEST_MON", include},
+ {ioctl, "ESOCK_TEST_IOCTL", include},
{socket_close, "ESOCK_TEST_SOCK_CLOSE", include},
{traffic, "ESOCK_TEST_TRAFFIC", include},
- {ttest, "ESOCK_TEST_TTEST", exclude},
+ {ttest, "ESOCK_TEST_TTEST", include},
{tickets, "ESOCK_TEST_TICKETS", include}],
[use_group(Group, Env, Default) || {Group, Env, Default} <- Groups].
@@ -856,7 +893,8 @@ groups() ->
%% Ticket groups
{tickets, [], tickets_cases()},
- {otp16359, [], otp16359_cases()}
+ {otp16359, [], otp16359_cases()},
+ {otp18240, [], otp18240_cases()}
].
api_cases() ->
@@ -1344,7 +1382,77 @@ traffic_pp_sendmsg_recvmsg_cases() ->
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6,
traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL
].
-
+
+%% Condition for running the ttest cases.
+%% No point in running these cases unless the machine is
+%% reasonably fast.
+ttest_condition(Config) ->
+ case ?config(kernel_factor, Config) of
+ Factor when is_integer(Factor) andalso (Factor =< ?TTEST_MIN_FACTOR) ->
+ ok;
+ Factor when is_integer(Factor) ->
+ {skip, ?F("Too slow for TTest (~w)", [Factor])};
+ _ ->
+ {skip, "Too slow for TTest (undef)"}
+ end.
+
+ttest_small_max_outstanding(Config) ->
+ EnvKey = "ESOCK_TEST_TTEST_SMALL_MAX_OUTSTANDING",
+ Default = ?TTEST_DEFAULT_SMALL_MAX_OUTSTANDING,
+ DefaultMaxOutstanding = ttest_max_outstanding(Config, EnvKey, Default),
+ ttest_max_outstanding(Config, DefaultMaxOutstanding).
+
+ttest_medium_max_outstanding(Config) ->
+ SmallMaxOutstanding = ttest_small_max_outstanding(Config),
+ EnvKey = "ESOCK_TEST_TTEST_MEDIUM_MAX_OUTSTANDING",
+ Default = ?TTEST_MK_DEFAULT_MAX_OUTSTANDING(
+ SmallMaxOutstanding),
+ DefaultMaxOutstanding = ttest_max_outstanding(Config, EnvKey, Default),
+ ttest_max_outstanding(Config, DefaultMaxOutstanding).
+
+ttest_large_max_outstanding(Config) ->
+ MediumMaxOutstanding = ttest_medium_max_outstanding(Config),
+ EnvKey = "ESOCK_TEST_TTEST_LARGE_MAX_OUTSTANDING",
+ Default = ?TTEST_MK_DEFAULT_MAX_OUTSTANDING(
+ MediumMaxOutstanding),
+ DefaultMaxOutstanding = ttest_max_outstanding(Config, EnvKey, Default),
+ ttest_max_outstanding(Config, DefaultMaxOutstanding).
+
+ttest_max_outstanding(Config, Default)
+ when is_integer(Default) andalso (Default > 1) ->
+ %% Note that we should not even get here if factor > 4
+ case ?config(kernel_factor, Config) of
+ 1 -> Default;
+ 2 when (Default >= 2) -> Default div 2;
+ 3 when (Default >= 4) -> Default div 4;
+ _ when (Default >= 8) -> Default div 8;
+ _ -> 1
+ end;
+ttest_max_outstanding(_, _) ->
+ 1.
+
+ttest_max_outstanding(Config, EnvKey, Default) ->
+ Key = list_to_atom(string:to_lower(EnvKey)),
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, MO}} when is_integer(MO) andalso (MO > 0) ->
+ MO;
+ _ ->
+ case os:getenv(EnvKey) of
+ false ->
+ Default;
+ Val ->
+ try list_to_integer(Val) of
+ MO when (MO > 0) ->
+ MO;
+ _ ->
+ 1
+ catch
+ _:_:_ ->
+ Default
+ end
+ end
+ end.
+
ttest_cases() ->
[
%% Server: transport = gen_tcp, active = false
@@ -1386,45 +1494,75 @@ ttest_sgenf_cgen_cases() ->
%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp, active = false
-ttest_sgenf_cgenf_cases() ->
- [
- ttest_sgenf_cgenf_small_tcp4,
- ttest_sgenf_cgenf_small_tcp6,
- ttest_sgenf_cgenf_medium_tcp4,
- ttest_sgenf_cgenf_medium_tcp6,
+ttest_conditional_cases(Env, Default, Cases) ->
+ case os:getenv(Env) of
+ false ->
+ Default;
+ Val ->
+ case list_to_atom(string:to_lower(Val)) of
+ Use when (Use =:= include) orelse
+ (Use =:= enable) orelse
+ (Use =:= true) ->
+ Cases;
+ _ -> % Assumed to be explicitly *disabled*
+ []
+ end
+ end.
+
+ttest_small_conditional_cases(Cases) ->
+ ttest_conditional_cases("ESOCK_TEST_TTEST_SMALL", Cases, Cases).
- ttest_sgenf_cgenf_large_tcp4,
- ttest_sgenf_cgenf_large_tcp6
- ].
+ttest_medium_conditional_cases(Cases) ->
+ ttest_conditional_cases("ESOCK_TEST_TTEST_MEDIUM", [], Cases).
+
+ttest_large_conditional_cases(Cases) ->
+ ttest_conditional_cases("ESOCK_TEST_TTEST_LARGE", [], Cases).
+
+ttest_select_conditional_cases(Small, Medium, Large) ->
+ ttest_small_conditional_cases(Small) ++
+ ttest_medium_conditional_cases(Medium) ++
+ ttest_large_conditional_cases(Large).
+
+ttest_sgenf_cgenf_cases() ->
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgenf_cgenf_small_tcp4,
+ ttest_sgenf_cgenf_small_tcp6],
+ %% Medium
+ [ttest_sgenf_cgenf_medium_tcp4,
+ ttest_sgenf_cgenf_medium_tcp6],
+ %% Large
+ [ttest_sgenf_cgenf_large_tcp4,
+ ttest_sgenf_cgenf_large_tcp6]).
%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp, active = once
ttest_sgenf_cgeno_cases() ->
- [
- ttest_sgenf_cgeno_small_tcp4,
- ttest_sgenf_cgeno_small_tcp6,
-
- ttest_sgenf_cgeno_medium_tcp4,
- ttest_sgenf_cgeno_medium_tcp6,
-
- ttest_sgenf_cgeno_large_tcp4,
- ttest_sgenf_cgeno_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgenf_cgeno_small_tcp4,
+ ttest_sgenf_cgeno_small_tcp6],
+ %% Medium
+ [ttest_sgenf_cgeno_medium_tcp4,
+ ttest_sgenf_cgeno_medium_tcp6],
+ %% Large
+ [ttest_sgenf_cgeno_large_tcp4,
+ ttest_sgenf_cgeno_large_tcp6]).
%% Server: transport = gen_tcp, active = false
%% Client: transport = gen_tcp, active = true
ttest_sgenf_cgent_cases() ->
- [
- ttest_sgenf_cgent_small_tcp4,
- ttest_sgenf_cgent_small_tcp6,
-
- ttest_sgenf_cgent_medium_tcp4,
- ttest_sgenf_cgent_medium_tcp6,
-
- ttest_sgenf_cgent_large_tcp4,
- ttest_sgenf_cgent_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgenf_cgent_small_tcp4,
+ ttest_sgenf_cgent_small_tcp6],
+ %% Medium
+ [ttest_sgenf_cgent_medium_tcp4,
+ ttest_sgenf_cgent_medium_tcp6],
+ %% Large
+ [ttest_sgenf_cgent_large_tcp4,
+ ttest_sgenf_cgent_large_tcp6]).
%% Server: transport = gen_tcp, active = false
%% Client: transport = socket(tcp)
@@ -1436,40 +1574,40 @@ ttest_sgenf_csock_cases() ->
].
ttest_sgenf_csockf_cases() ->
- [
- ttest_sgenf_csockf_small_tcp4,
- ttest_sgenf_csockf_small_tcp6,
-
- ttest_sgenf_csockf_medium_tcp4,
- ttest_sgenf_csockf_medium_tcp6,
-
- ttest_sgenf_csockf_large_tcp4,
- ttest_sgenf_csockf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgenf_csockf_small_tcp4,
+ ttest_sgenf_csockf_small_tcp6],
+ %% Medium
+ [ttest_sgenf_csockf_medium_tcp4,
+ ttest_sgenf_csockf_medium_tcp6],
+ %% Large
+ [ttest_sgenf_csockf_large_tcp4,
+ ttest_sgenf_csockf_large_tcp6]).
ttest_sgenf_csocko_cases() ->
- [
- ttest_sgenf_csocko_small_tcp4,
- ttest_sgenf_csocko_small_tcp6,
-
- ttest_sgenf_csocko_medium_tcp4,
- ttest_sgenf_csocko_medium_tcp6,
-
- ttest_sgenf_csocko_large_tcp4,
- ttest_sgenf_csocko_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgenf_csocko_small_tcp4,
+ ttest_sgenf_csocko_small_tcp6],
+ %% Medium
+ [ttest_sgenf_csocko_medium_tcp4,
+ ttest_sgenf_csocko_medium_tcp6],
+ %% Large
+ [ttest_sgenf_csocko_large_tcp4,
+ ttest_sgenf_csocko_large_tcp6]).
ttest_sgenf_csockt_cases() ->
- [
- ttest_sgenf_csockt_small_tcp4,
- ttest_sgenf_csockt_small_tcp6,
-
- ttest_sgenf_csockt_medium_tcp4,
- ttest_sgenf_csockt_medium_tcp6,
-
- ttest_sgenf_csockt_large_tcp4,
- ttest_sgenf_csockt_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgenf_csockt_small_tcp4,
+ ttest_sgenf_csockt_small_tcp6],
+ %% Medium
+ [ttest_sgenf_csockt_medium_tcp4,
+ ttest_sgenf_csockt_medium_tcp6],
+ %% Large
+ [ttest_sgenf_csockt_large_tcp4,
+ ttest_sgenf_csockt_large_tcp6]).
%% Server: transport = gen_tcp, active = once
ttest_sgeno_cases() ->
@@ -1490,44 +1628,44 @@ ttest_sgeno_cgen_cases() ->
%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp, active = false
ttest_sgeno_cgenf_cases() ->
- [
- ttest_sgeno_cgenf_small_tcp4,
- ttest_sgeno_cgenf_small_tcp6,
-
- ttest_sgeno_cgenf_medium_tcp4,
- ttest_sgeno_cgenf_medium_tcp6,
-
- ttest_sgeno_cgenf_large_tcp4,
- ttest_sgeno_cgenf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgeno_cgenf_small_tcp4,
+ ttest_sgeno_cgenf_small_tcp6],
+ %% Medium
+ [ttest_sgeno_cgenf_medium_tcp4,
+ ttest_sgeno_cgenf_medium_tcp6],
+ %% Large
+ [ttest_sgeno_cgenf_large_tcp4,
+ ttest_sgeno_cgenf_large_tcp6]).
%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp, active = once
ttest_sgeno_cgeno_cases() ->
- [
- ttest_sgeno_cgeno_small_tcp4,
- ttest_sgeno_cgeno_small_tcp6,
-
- ttest_sgeno_cgeno_medium_tcp4,
- ttest_sgeno_cgeno_medium_tcp6,
-
- ttest_sgeno_cgeno_large_tcp4,
- ttest_sgeno_cgeno_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgeno_cgeno_small_tcp4,
+ ttest_sgeno_cgeno_small_tcp6],
+ %% Medium
+ [ttest_sgeno_cgeno_medium_tcp4,
+ ttest_sgeno_cgeno_medium_tcp6],
+ %% Large
+ [ttest_sgeno_cgeno_large_tcp4,
+ ttest_sgeno_cgeno_large_tcp6]).
%% Server: transport = gen_tcp, active = once
%% Client: transport = gen_tcp, active = true
ttest_sgeno_cgent_cases() ->
- [
- ttest_sgeno_cgent_small_tcp4,
- ttest_sgeno_cgent_small_tcp6,
-
- ttest_sgeno_cgent_medium_tcp4,
- ttest_sgeno_cgent_medium_tcp6,
-
- ttest_sgeno_cgent_large_tcp4,
- ttest_sgeno_cgent_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgeno_cgent_small_tcp4,
+ ttest_sgeno_cgent_small_tcp6],
+ %% Medium
+ [ttest_sgeno_cgent_medium_tcp4,
+ ttest_sgeno_cgent_medium_tcp6],
+ %% Large
+ [ttest_sgeno_cgent_large_tcp4,
+ ttest_sgeno_cgent_large_tcp6]).
%% Server: transport = gen_tcp, active = once
%% Client: transport = socket(tcp)
@@ -1539,40 +1677,40 @@ ttest_sgeno_csock_cases() ->
].
ttest_sgeno_csockf_cases() ->
- [
- ttest_sgeno_csockf_small_tcp4,
- ttest_sgeno_csockf_small_tcp6,
-
- ttest_sgeno_csockf_medium_tcp4,
- ttest_sgeno_csockf_medium_tcp6,
-
- ttest_sgeno_csockf_large_tcp4,
- ttest_sgeno_csockf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgeno_csockf_small_tcp4,
+ ttest_sgeno_csockf_small_tcp6],
+ %% Medium
+ [ttest_sgeno_csockf_medium_tcp4,
+ ttest_sgeno_csockf_medium_tcp6],
+ %% Large
+ [ttest_sgeno_csockf_large_tcp4,
+ ttest_sgeno_csockf_large_tcp6]).
ttest_sgeno_csocko_cases() ->
- [
- ttest_sgeno_csocko_small_tcp4,
- ttest_sgeno_csocko_small_tcp6,
-
- ttest_sgeno_csocko_medium_tcp4,
- ttest_sgeno_csocko_medium_tcp6,
-
- ttest_sgeno_csocko_large_tcp4,
- ttest_sgeno_csocko_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgeno_csocko_small_tcp4,
+ ttest_sgeno_csocko_small_tcp6],
+ %% Medium
+ [ttest_sgeno_csocko_medium_tcp4,
+ ttest_sgeno_csocko_medium_tcp6],
+ %% Large
+ [ttest_sgeno_csocko_large_tcp4,
+ ttest_sgeno_csocko_large_tcp6]).
ttest_sgeno_csockt_cases() ->
- [
- ttest_sgeno_csockt_small_tcp4,
- ttest_sgeno_csockt_small_tcp6,
-
- ttest_sgeno_csockt_medium_tcp4,
- ttest_sgeno_csockt_medium_tcp6,
-
- ttest_sgeno_csockt_large_tcp4,
- ttest_sgeno_csockt_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgeno_csockt_small_tcp4,
+ ttest_sgeno_csockt_small_tcp6],
+ %% Medium
+ [ttest_sgeno_csockt_medium_tcp4,
+ ttest_sgeno_csockt_medium_tcp6],
+ %% Large
+ [ttest_sgeno_csockt_large_tcp4,
+ ttest_sgeno_csockt_large_tcp6]).
%% Server: transport = gen_tcp, active = true
ttest_sgent_cases() ->
@@ -1593,44 +1731,44 @@ ttest_sgent_cgen_cases() ->
%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp, active = false
ttest_sgent_cgenf_cases() ->
- [
- ttest_sgent_cgenf_small_tcp4,
- ttest_sgent_cgenf_small_tcp6,
-
- ttest_sgent_cgenf_medium_tcp4,
- ttest_sgent_cgenf_medium_tcp6,
-
- ttest_sgent_cgenf_large_tcp4,
- ttest_sgent_cgenf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgent_cgenf_small_tcp4,
+ ttest_sgent_cgenf_small_tcp6],
+ %% Medium
+ [ttest_sgent_cgenf_medium_tcp4,
+ ttest_sgent_cgenf_medium_tcp6],
+ %% Large
+ [ttest_sgent_cgenf_large_tcp4,
+ ttest_sgent_cgenf_large_tcp6]).
%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp, active = once
ttest_sgent_cgeno_cases() ->
- [
- ttest_sgent_cgeno_small_tcp4,
- ttest_sgent_cgeno_small_tcp6,
-
- ttest_sgent_cgeno_medium_tcp4,
- ttest_sgent_cgeno_medium_tcp6,
-
- ttest_sgent_cgeno_large_tcp4,
- ttest_sgent_cgeno_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgent_cgeno_small_tcp4,
+ ttest_sgent_cgeno_small_tcp6],
+ %% Medium
+ [ttest_sgent_cgeno_medium_tcp4,
+ ttest_sgent_cgeno_medium_tcp6],
+ %% Large
+ [ttest_sgent_cgeno_large_tcp4,
+ ttest_sgent_cgeno_large_tcp6]).
%% Server: transport = gen_tcp, active = true
%% Client: transport = gen_tcp, active = true
ttest_sgent_cgent_cases() ->
- [
- ttest_sgent_cgent_small_tcp4,
- ttest_sgent_cgent_small_tcp6,
-
- ttest_sgent_cgent_medium_tcp4,
- ttest_sgent_cgent_medium_tcp6,
-
- ttest_sgent_cgent_large_tcp4,
- ttest_sgent_cgent_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgent_cgent_small_tcp4,
+ ttest_sgent_cgent_small_tcp6],
+ %% Medium
+ [ttest_sgent_cgent_medium_tcp4,
+ ttest_sgent_cgent_medium_tcp6],
+ %% Large
+ [ttest_sgent_cgent_large_tcp4,
+ ttest_sgent_cgent_large_tcp6]).
%% Server: transport = gen_tcp, active = true
%% Client: transport = socket(tcp)
@@ -1642,40 +1780,40 @@ ttest_sgent_csock_cases() ->
].
ttest_sgent_csockf_cases() ->
- [
- ttest_sgent_csockf_small_tcp4,
- ttest_sgent_csockf_small_tcp6,
-
- ttest_sgent_csockf_medium_tcp4,
- ttest_sgent_csockf_medium_tcp6,
-
- ttest_sgent_csockf_large_tcp4,
- ttest_sgent_csockf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgent_csockf_small_tcp4,
+ ttest_sgent_csockf_small_tcp6],
+ %% Medium
+ [ttest_sgent_csockf_medium_tcp4,
+ ttest_sgent_csockf_medium_tcp6],
+ %% Large
+ [ttest_sgent_csockf_large_tcp4,
+ ttest_sgent_csockf_large_tcp6]).
ttest_sgent_csocko_cases() ->
- [
- ttest_sgent_csocko_small_tcp4,
- ttest_sgent_csocko_small_tcp6,
-
- ttest_sgent_csocko_medium_tcp4,
- ttest_sgent_csocko_medium_tcp6,
-
- ttest_sgent_csocko_large_tcp4,
- ttest_sgent_csocko_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgent_csocko_small_tcp4,
+ ttest_sgent_csocko_small_tcp6],
+ %% Medium
+ [ttest_sgent_csocko_medium_tcp4,
+ ttest_sgent_csocko_medium_tcp6],
+ %% Large
+ [ttest_sgent_csocko_large_tcp4,
+ ttest_sgent_csocko_large_tcp6]).
ttest_sgent_csockt_cases() ->
- [
- ttest_sgent_csockt_small_tcp4,
- ttest_sgent_csockt_small_tcp6,
-
- ttest_sgent_csockt_medium_tcp4,
- ttest_sgent_csockt_medium_tcp6,
-
- ttest_sgent_csockt_large_tcp4,
- ttest_sgent_csockt_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_sgent_csockt_small_tcp4,
+ ttest_sgent_csockt_small_tcp6],
+ %% Medium
+ [ttest_sgent_csockt_medium_tcp4,
+ ttest_sgent_csockt_medium_tcp6],
+ %% Large
+ [ttest_sgent_csockt_large_tcp4,
+ ttest_sgent_csockt_large_tcp6]).
%% Server: transport = socket(tcp), active = false
ttest_ssockf_cases() ->
@@ -1696,44 +1834,44 @@ ttest_ssockf_cgen_cases() ->
%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp, active = false
ttest_ssockf_cgenf_cases() ->
- [
- ttest_ssockf_cgenf_small_tcp4,
- ttest_ssockf_cgenf_small_tcp6,
-
- ttest_ssockf_cgenf_medium_tcp4,
- ttest_ssockf_cgenf_medium_tcp6,
-
- ttest_ssockf_cgenf_large_tcp4,
- ttest_ssockf_cgenf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockf_cgenf_small_tcp4,
+ ttest_ssockf_cgenf_small_tcp6],
+ %% Medium
+ [ttest_ssockf_cgenf_medium_tcp4,
+ ttest_ssockf_cgenf_medium_tcp6],
+ %% Large
+ [ttest_ssockf_cgenf_large_tcp4,
+ ttest_ssockf_cgenf_large_tcp6]).
%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp, active = once
ttest_ssockf_cgeno_cases() ->
- [
- ttest_ssockf_cgeno_small_tcp4,
- ttest_ssockf_cgeno_small_tcp6,
-
- ttest_ssockf_cgeno_medium_tcp4,
- ttest_ssockf_cgeno_medium_tcp6,
-
- ttest_ssockf_cgeno_large_tcp4,
- ttest_ssockf_cgeno_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockf_cgeno_small_tcp4,
+ ttest_ssockf_cgeno_small_tcp6],
+ %% Medium
+ [ttest_ssockf_cgeno_medium_tcp4,
+ ttest_ssockf_cgeno_medium_tcp6],
+ %% Large
+ [ttest_ssockf_cgeno_large_tcp4,
+ ttest_ssockf_cgeno_large_tcp6]).
%% Server: transport = socket(tcp), active = false
%% Client: transport = gen_tcp, active = true
ttest_ssockf_cgent_cases() ->
- [
- ttest_ssockf_cgent_small_tcp4,
- ttest_ssockf_cgent_small_tcp6,
-
- ttest_ssockf_cgent_medium_tcp4,
- ttest_ssockf_cgent_medium_tcp6,
-
- ttest_ssockf_cgent_large_tcp4,
- ttest_ssockf_cgent_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockf_cgent_small_tcp4,
+ ttest_ssockf_cgent_small_tcp6],
+ %% Medium
+ [ttest_ssockf_cgent_medium_tcp4,
+ ttest_ssockf_cgent_medium_tcp6],
+ %% Large
+ [ttest_ssockf_cgent_large_tcp4,
+ ttest_ssockf_cgent_large_tcp6]).
%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp)
@@ -1747,53 +1885,53 @@ ttest_ssockf_csock_cases() ->
%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp), active = false
ttest_ssockf_csockf_cases() ->
- [
- ttest_ssockf_csockf_small_tcp4,
- ttest_ssockf_csockf_small_tcp6,
- ttest_ssockf_csockf_small_tcpL,
-
- ttest_ssockf_csockf_medium_tcp4,
- ttest_ssockf_csockf_medium_tcp6,
- ttest_ssockf_csockf_medium_tcpL,
-
- ttest_ssockf_csockf_large_tcp4,
- ttest_ssockf_csockf_large_tcp6,
- ttest_ssockf_csockf_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockf_csockf_small_tcp4,
+ ttest_ssockf_csockf_small_tcp6,
+ ttest_ssockf_csockf_small_tcpL],
+ %% Medium
+ [ttest_ssockf_csockf_medium_tcp4,
+ ttest_ssockf_csockf_medium_tcp6,
+ ttest_ssockf_csockf_medium_tcpL],
+ %% Large
+ [ttest_ssockf_csockf_large_tcp4,
+ ttest_ssockf_csockf_large_tcp6,
+ ttest_ssockf_csockf_large_tcpL]).
%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp), active = once
ttest_ssockf_csocko_cases() ->
- [
- ttest_ssockf_csocko_small_tcp4,
- ttest_ssockf_csocko_small_tcp6,
- ttest_ssockf_csocko_small_tcpL,
-
- ttest_ssockf_csocko_medium_tcp4,
- ttest_ssockf_csocko_medium_tcp6,
- ttest_ssockf_csocko_medium_tcpL,
-
- ttest_ssockf_csocko_large_tcp4,
- ttest_ssockf_csocko_large_tcp6,
- ttest_ssockf_csocko_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockf_csocko_small_tcp4,
+ ttest_ssockf_csocko_small_tcp6,
+ ttest_ssockf_csocko_small_tcpL],
+ %% Medium
+ [ttest_ssockf_csocko_medium_tcp4,
+ ttest_ssockf_csocko_medium_tcp6,
+ ttest_ssockf_csocko_medium_tcpL],
+ %% Large
+ [ttest_ssockf_csocko_large_tcp4,
+ ttest_ssockf_csocko_large_tcp6,
+ ttest_ssockf_csocko_large_tcpL]).
%% Server: transport = socket(tcp), active = false
%% Client: transport = socket(tcp), active = true
ttest_ssockf_csockt_cases() ->
- [
- ttest_ssockf_csockt_small_tcp4,
- ttest_ssockf_csockt_small_tcp6,
- ttest_ssockf_csockt_small_tcpL,
-
- ttest_ssockf_csockt_medium_tcp4,
- ttest_ssockf_csockt_medium_tcp6,
- ttest_ssockf_csockt_medium_tcpL,
-
- ttest_ssockf_csockt_large_tcp4,
- ttest_ssockf_csockt_large_tcp6,
- ttest_ssockf_csockt_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockf_csockt_small_tcp4,
+ ttest_ssockf_csockt_small_tcp6,
+ ttest_ssockf_csockt_small_tcpL],
+ %% Medium
+ [ttest_ssockf_csockt_medium_tcp4,
+ ttest_ssockf_csockt_medium_tcp6,
+ ttest_ssockf_csockt_medium_tcpL],
+ %% Large
+ [ttest_ssockf_csockt_large_tcp4,
+ ttest_ssockf_csockt_large_tcp6,
+ ttest_ssockf_csockt_large_tcpL]).
%% Server: transport = socket(tcp), active = once
ttest_ssocko_cases() ->
@@ -1814,44 +1952,44 @@ ttest_ssocko_cgen_cases() ->
%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp, active = false
ttest_ssocko_cgenf_cases() ->
- [
- ttest_ssocko_cgenf_small_tcp4,
- ttest_ssocko_cgenf_small_tcp6,
-
- ttest_ssocko_cgenf_medium_tcp4,
- ttest_ssocko_cgenf_medium_tcp6,
-
- ttest_ssocko_cgenf_large_tcp4,
- ttest_ssocko_cgenf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssocko_cgenf_small_tcp4,
+ ttest_ssocko_cgenf_small_tcp6],
+ %% Medium
+ [ttest_ssocko_cgenf_medium_tcp4,
+ ttest_ssocko_cgenf_medium_tcp6],
+ %% Large
+ [ttest_ssocko_cgenf_large_tcp4,
+ ttest_ssocko_cgenf_large_tcp6]).
%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp, active = once
ttest_ssocko_cgeno_cases() ->
- [
- ttest_ssocko_cgeno_small_tcp4,
- ttest_ssocko_cgeno_small_tcp6,
-
- ttest_ssocko_cgeno_medium_tcp4,
- ttest_ssocko_cgeno_medium_tcp6,
-
- ttest_ssocko_cgeno_large_tcp4,
- ttest_ssocko_cgeno_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssocko_cgeno_small_tcp4,
+ ttest_ssocko_cgeno_small_tcp6],
+ %% Medium
+ [ttest_ssocko_cgeno_medium_tcp4,
+ ttest_ssocko_cgeno_medium_tcp6],
+ %% Large
+ [ttest_ssocko_cgeno_large_tcp4,
+ ttest_ssocko_cgeno_large_tcp6]).
%% Server: transport = socket(tcp), active = once
%% Client: transport = gen_tcp, active = true
ttest_ssocko_cgent_cases() ->
- [
- ttest_ssocko_cgent_small_tcp4,
- ttest_ssocko_cgent_small_tcp6,
-
- ttest_ssocko_cgent_medium_tcp4,
- ttest_ssocko_cgent_medium_tcp6,
-
- ttest_ssocko_cgent_large_tcp4,
- ttest_ssocko_cgent_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssocko_cgent_small_tcp4,
+ ttest_ssocko_cgent_small_tcp6],
+ %% Medium
+ [ttest_ssocko_cgent_medium_tcp4,
+ ttest_ssocko_cgent_medium_tcp6],
+ %% Large
+ [ttest_ssocko_cgent_large_tcp4,
+ ttest_ssocko_cgent_large_tcp6]).
%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp)
@@ -1865,53 +2003,53 @@ ttest_ssocko_csock_cases() ->
%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp), active = false
ttest_ssocko_csockf_cases() ->
- [
- ttest_ssocko_csockf_small_tcp4,
- ttest_ssocko_csockf_small_tcp6,
- ttest_ssocko_csockf_small_tcpL,
-
- ttest_ssocko_csockf_medium_tcp4,
- ttest_ssocko_csockf_medium_tcp6,
- ttest_ssocko_csockf_medium_tcpL,
-
- ttest_ssocko_csockf_large_tcp4,
- ttest_ssocko_csockf_large_tcp6,
- ttest_ssocko_csockf_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssocko_csockf_small_tcp4,
+ ttest_ssocko_csockf_small_tcp6,
+ ttest_ssocko_csockf_small_tcpL],
+ %% Medium
+ [ttest_ssocko_csockf_medium_tcp4,
+ ttest_ssocko_csockf_medium_tcp6,
+ ttest_ssocko_csockf_medium_tcpL],
+ %% Large
+ [ttest_ssocko_csockf_large_tcp4,
+ ttest_ssocko_csockf_large_tcp6,
+ ttest_ssocko_csockf_large_tcpL]).
%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp), active = once
ttest_ssocko_csocko_cases() ->
- [
- ttest_ssocko_csocko_small_tcp4,
- ttest_ssocko_csocko_small_tcp6,
- ttest_ssocko_csocko_small_tcpL,
-
- ttest_ssocko_csocko_medium_tcp4,
- ttest_ssocko_csocko_medium_tcp6,
- ttest_ssocko_csocko_medium_tcpL,
-
- ttest_ssocko_csocko_large_tcp4,
- ttest_ssocko_csocko_large_tcp6,
- ttest_ssocko_csocko_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssocko_csocko_small_tcp4,
+ ttest_ssocko_csocko_small_tcp6,
+ ttest_ssocko_csocko_small_tcpL],
+ %% Medium
+ [ttest_ssocko_csocko_medium_tcp4,
+ ttest_ssocko_csocko_medium_tcp6,
+ ttest_ssocko_csocko_medium_tcpL],
+ %% Large
+ [ttest_ssocko_csocko_large_tcp4,
+ ttest_ssocko_csocko_large_tcp6,
+ ttest_ssocko_csocko_large_tcpL]).
%% Server: transport = socket(tcp), active = once
%% Client: transport = socket(tcp), active = true
ttest_ssocko_csockt_cases() ->
- [
- ttest_ssocko_csockt_small_tcp4,
- ttest_ssocko_csockt_small_tcp6,
- ttest_ssocko_csockt_small_tcpL,
-
- ttest_ssocko_csockt_medium_tcp4,
- ttest_ssocko_csockt_medium_tcp6,
- ttest_ssocko_csockt_medium_tcpL,
-
- ttest_ssocko_csockt_large_tcp4,
- ttest_ssocko_csockt_large_tcp6,
- ttest_ssocko_csockt_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssocko_csockt_small_tcp4,
+ ttest_ssocko_csockt_small_tcp6,
+ ttest_ssocko_csockt_small_tcpL],
+ %% Medium
+ [ttest_ssocko_csockt_medium_tcp4,
+ ttest_ssocko_csockt_medium_tcp6,
+ ttest_ssocko_csockt_medium_tcpL],
+ %% Large
+ [ttest_ssocko_csockt_large_tcp4,
+ ttest_ssocko_csockt_large_tcp6,
+ ttest_ssocko_csockt_large_tcpL]).
%% Server: transport = socket(tcp), active = true
ttest_ssockt_cases() ->
@@ -1932,44 +2070,44 @@ ttest_ssockt_cgen_cases() ->
%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp, active = false
ttest_ssockt_cgenf_cases() ->
- [
- ttest_ssockt_cgenf_small_tcp4,
- ttest_ssockt_cgenf_small_tcp6,
-
- ttest_ssockt_cgenf_medium_tcp4,
- ttest_ssockt_cgenf_medium_tcp6,
-
- ttest_ssockt_cgenf_large_tcp4,
- ttest_ssockt_cgenf_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockt_cgenf_small_tcp4,
+ ttest_ssockt_cgenf_small_tcp6],
+ %% Medium
+ [ttest_ssockt_cgenf_medium_tcp4,
+ ttest_ssockt_cgenf_medium_tcp6],
+ %% Large
+ [ttest_ssockt_cgenf_large_tcp4,
+ ttest_ssockt_cgenf_large_tcp6]).
%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp, active = once
ttest_ssockt_cgeno_cases() ->
- [
- ttest_ssockt_cgeno_small_tcp4,
- ttest_ssockt_cgeno_small_tcp6,
-
- ttest_ssockt_cgeno_medium_tcp4,
- ttest_ssockt_cgeno_medium_tcp6,
-
- ttest_ssockt_cgeno_large_tcp4,
- ttest_ssockt_cgeno_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockt_cgeno_small_tcp4,
+ ttest_ssockt_cgeno_small_tcp6],
+ %% Medium
+ [ttest_ssockt_cgeno_medium_tcp4,
+ ttest_ssockt_cgeno_medium_tcp6],
+ %% Large
+ [ttest_ssockt_cgeno_large_tcp4,
+ ttest_ssockt_cgeno_large_tcp6]).
%% Server: transport = socket(tcp), active = true
%% Client: transport = gen_tcp, active = true
ttest_ssockt_cgent_cases() ->
- [
- ttest_ssockt_cgent_small_tcp4,
- ttest_ssockt_cgent_small_tcp6,
-
- ttest_ssockt_cgent_medium_tcp4,
- ttest_ssockt_cgent_medium_tcp6,
-
- ttest_ssockt_cgent_large_tcp4,
- ttest_ssockt_cgent_large_tcp6
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockt_cgent_small_tcp4,
+ ttest_ssockt_cgent_small_tcp6],
+ %% Medium
+ [ttest_ssockt_cgent_medium_tcp4,
+ ttest_ssockt_cgent_medium_tcp6],
+ %% Large
+ [ttest_ssockt_cgent_large_tcp4,
+ ttest_ssockt_cgent_large_tcp6]).
%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp)
@@ -1983,57 +2121,58 @@ ttest_ssockt_csock_cases() ->
%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp), active = false
ttest_ssockt_csockf_cases() ->
- [
- ttest_ssockt_csockf_small_tcp4,
- ttest_ssockt_csockf_small_tcp6,
- ttest_ssockt_csockf_small_tcpL,
-
- ttest_ssockt_csockf_medium_tcp4,
- ttest_ssockt_csockf_medium_tcp6,
- ttest_ssockt_csockf_medium_tcpL,
-
- ttest_ssockt_csockf_large_tcp4,
- ttest_ssockt_csockf_large_tcp6,
- ttest_ssockt_csockf_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockt_csockf_small_tcp4,
+ ttest_ssockt_csockf_small_tcp6,
+ ttest_ssockt_csockf_small_tcpL],
+ %% Medium
+ [ttest_ssockt_csockf_medium_tcp4,
+ ttest_ssockt_csockf_medium_tcp6,
+ ttest_ssockt_csockf_medium_tcpL],
+ %% Large
+ [ttest_ssockt_csockf_large_tcp4,
+ ttest_ssockt_csockf_large_tcp6,
+ ttest_ssockt_csockf_large_tcpL]).
%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp), active = once
ttest_ssockt_csocko_cases() ->
- [
- ttest_ssockt_csocko_small_tcp4,
- ttest_ssockt_csocko_small_tcp6,
- ttest_ssockt_csocko_small_tcpL,
-
- ttest_ssockt_csocko_medium_tcp4,
- ttest_ssockt_csocko_medium_tcp6,
- ttest_ssockt_csocko_medium_tcpL,
-
- ttest_ssockt_csocko_large_tcp4,
- ttest_ssockt_csocko_large_tcp6,
- ttest_ssockt_csocko_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockt_csocko_small_tcp4,
+ ttest_ssockt_csocko_small_tcp6,
+ ttest_ssockt_csocko_small_tcpL],
+ %% Medium
+ [ttest_ssockt_csocko_medium_tcp4,
+ ttest_ssockt_csocko_medium_tcp6,
+ ttest_ssockt_csocko_medium_tcpL],
+ %% Large
+ [ttest_ssockt_csocko_large_tcp4,
+ ttest_ssockt_csocko_large_tcp6,
+ ttest_ssockt_csocko_large_tcpL]).
%% Server: transport = socket(tcp), active = true
%% Client: transport = socket(tcp), active = true
ttest_ssockt_csockt_cases() ->
- [
- ttest_ssockt_csockt_small_tcp4,
- ttest_ssockt_csockt_small_tcp6,
- ttest_ssockt_csockt_small_tcpL,
-
- ttest_ssockt_csockt_medium_tcp4,
- ttest_ssockt_csockt_medium_tcp6,
- ttest_ssockt_csockt_medium_tcpL,
-
- ttest_ssockt_csockt_large_tcp4,
- ttest_ssockt_csockt_large_tcp6,
- ttest_ssockt_csockt_large_tcpL
- ].
+ ttest_select_conditional_cases(
+ %% Small
+ [ttest_ssockt_csockt_small_tcp4,
+ ttest_ssockt_csockt_small_tcp6,
+ ttest_ssockt_csockt_small_tcpL],
+ %% Medium
+ [ttest_ssockt_csockt_medium_tcp4,
+ ttest_ssockt_csockt_medium_tcp6,
+ ttest_ssockt_csockt_medium_tcpL],
+ %% Large
+ [ttest_ssockt_csockt_large_tcp4,
+ ttest_ssockt_csockt_large_tcp6,
+ ttest_ssockt_csockt_large_tcpL]).
tickets_cases() ->
[
- {group, otp16359}
+ {group, otp16359},
+ {group, otp18240}
].
otp16359_cases() ->
@@ -2044,38 +2183,58 @@ otp16359_cases() ->
].
+otp18240_cases() ->
+ [
+ otp18240_accept_mon_leak_tcp4,
+ otp18240_accept_mon_leak_tcp6
+ ].
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-init_per_suite(Config) ->
- io:format("init_per_suite -> entry with"
- "~n Config: ~p"
- "~n", [Config]),
- ct:timetrap(?MINS(2)),
- Factor = analyze_and_print_host_info(),
+init_per_suite(Config0) ->
+ ?P("init_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n Nodes: ~p", [Config0, erlang:nodes()]),
+
try socket:info() of
#{} ->
- socket:use_registry(false),
- case quiet_mode(Config) of
- default ->
- case ?LOGGER:start() of
- ok ->
- [{esock_factor, Factor} | Config];
- {error, Reason} ->
- io:format("init_per_suite -> Failed starting logger"
- "~n Reason: ~p"
- "~n", [Reason]),
- {skip, "Failed starting logger"}
- end;
- Quiet ->
- case ?LOGGER:start(Quiet) of
- ok ->
- [{esock_factor, Factor},
- {esock_test_quiet, Quiet} | Config];
- {error, Reason} ->
- io:format("init_per_suite -> Failed starting logger"
- "~n Reason: ~p"
- "~n", [Reason]),
- {skip, "Failed starting logger"}
+ case ?KLIB:init_per_suite(Config0) of
+ {skip, _} = SKIP ->
+ SKIP;
+
+ Config1 when is_list(Config1) ->
+
+ ?P("init_per_suite -> end when "
+ "~n Config: ~p", [Config1]),
+
+ %% We need a monitor on this node also
+ kernel_test_sys_monitor:start(),
+
+ socket:use_registry(false),
+ case quiet_mode(Config1) of
+ default ->
+ case ?LOGGER:start() of
+ ok ->
+ Config1;
+ {error, Reason} ->
+ ?P("init_per_suite -> "
+ "Failed starting logger"
+ "~n Reason: ~p"
+ "~n", [Reason]),
+ {skip, "Failed starting logger"}
+ end;
+ Quiet ->
+ case ?LOGGER:start(Quiet) of
+ ok ->
+ [{esock_test_quiet, Quiet} | Config1];
+ {error, Reason} ->
+ ?P("init_per_suite -> "
+ "Failed starting logger"
+ "~n Reason: ~p"
+ "~n", [Reason]),
+ {skip, "Failed starting logger"}
+ end
end
end
catch
@@ -2085,9 +2244,23 @@ init_per_suite(Config) ->
{skip, "esock not configured"}
end.
-end_per_suite(_) ->
+end_per_suite(Config0) ->
+
+ ?P("end_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n Nodes: ~p", [Config0, erlang:nodes()]),
+
+ %% Stop the local monitor
+ kernel_test_sys_monitor:stop(),
+
(catch ?LOGGER:stop()),
- ok.
+
+ Config1 = ?KLIB:end_per_suite(Config0),
+
+ ?P("end_per_suite -> "
+ "~n Nodes: ~p", [erlang:nodes()]),
+
+ Config1.
init_per_group(api_sendfile = GroupName, Config) ->
@@ -2124,7 +2297,7 @@ init_per_group(GroupName, Config)
"~n", [GroupName, Config]),
%% Maybe we should skip the entire suite for this platform,
%% but for now we just skip these groups, which seem to
- %% have problems (slave node start).
+ %% have problems (node start).
%% As stated elsewhere, its not really Fedora 16, but
%% the *really* slow VM that is the issue.
try is_old_fedora16() of
@@ -2138,12 +2311,18 @@ init_per_group(ttest = _GroupName, Config) ->
io:format("init_per_group(~w) -> entry with"
"~n Config: ~p"
"~n", [_GroupName, Config]),
- ttest_manager_start(),
- case lists:keysearch(esock_test_ttest_runtime, 1, Config) of
- {value, _} ->
- Config;
- false ->
- [{esock_test_ttest_runtime, which_ttest_runtime_env()} | Config]
+ case ttest_condition(Config) of
+ ok ->
+ ttest_manager_start(),
+ case lists:keysearch(esock_test_ttest_runtime, 1, Config) of
+ {value, _} ->
+ Config;
+ false ->
+ [{esock_test_ttest_runtime, which_ttest_runtime_env()} |
+ Config]
+ end;
+ {skip, _} = SKIP ->
+ SKIP
end;
init_per_group(api_async_ref, Config) ->
[{select_handle, true} | Config];
@@ -2211,10 +2390,6 @@ double_data(N, Data) ->
%% that we can call the "global" info function and that it returns
%% a non-empty map...
-api_m_info(suite) ->
- [];
-api_m_info(doc) ->
- [];
api_m_info(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_m_info,
@@ -2244,10 +2419,6 @@ api_m_info() ->
%% At the same time, it will test the info function (since it uses it
%% for verification).
-api_m_debug(suite) ->
- [];
-api_m_debug(doc) ->
- [];
api_m_debug(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_m_debug,
@@ -2412,10 +2583,6 @@ api_m_error_bind(Config) when is_list(Config) ->
%% Basically open (create) and info of an IPv4 UDP (dgram) socket.
%% With some extra checks...
-api_b_open_and_info_udp4(suite) ->
- [];
-api_b_open_and_info_udp4(doc) ->
- [];
api_b_open_and_info_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_info_udp4,
@@ -2432,10 +2599,6 @@ api_b_open_and_info_udp4(_Config) when is_list(_Config) ->
%% Basically open (create) and info of an IPv6 UDP (dgram) socket.
%% With some extra checks...
-api_b_open_and_info_udp6(suite) ->
- [];
-api_b_open_and_info_udp6(doc) ->
- [];
api_b_open_and_info_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_info_udp6,
@@ -2453,10 +2616,6 @@ api_b_open_and_info_udp6(_Config) when is_list(_Config) ->
%% Basically open (create) and info of an IPv4 TCP (stream) socket.
%% With some extra checks...
-api_b_open_and_info_tcp4(suite) ->
- [];
-api_b_open_and_info_tcp4(doc) ->
- [];
api_b_open_and_info_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_info_tcp4,
@@ -2473,10 +2632,6 @@ api_b_open_and_info_tcp4(_Config) when is_list(_Config) ->
%% Basically open (create) and info of an IPv6 TCP (stream) socket.
%% With some extra checks...
-api_b_open_and_info_tcp6(suite) ->
- [];
-api_b_open_and_info_tcp6(doc) ->
- [];
api_b_open_and_info_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_info_tcp6,
@@ -2554,10 +2709,6 @@ api_b_open_and_info(InitState) ->
%% Basically open (create) and close an IPv4 UDP (dgram) socket.
%% With some extra checks...
-api_b_open_and_close_udp4(suite) ->
- [];
-api_b_open_and_close_udp4(doc) ->
- [];
api_b_open_and_close_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_udp4,
@@ -2573,10 +2724,6 @@ api_b_open_and_close_udp4(_Config) when is_list(_Config) ->
%% Basically open (create) and close an IPv6 UDP (dgram) socket.
%% With some extra checks...
-api_b_open_and_close_udp6(suite) ->
- [];
-api_b_open_and_close_udp6(doc) ->
- [];
api_b_open_and_close_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_udp6,
@@ -2593,10 +2740,6 @@ api_b_open_and_close_udp6(_Config) when is_list(_Config) ->
%% Basically open (create) and close an IPv4 TCP (stream) socket.
%% With some extra checks...
-api_b_open_and_close_tcp4(suite) ->
- [];
-api_b_open_and_close_tcp4(doc) ->
- [];
api_b_open_and_close_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_tcp4,
@@ -2612,10 +2755,6 @@ api_b_open_and_close_tcp4(_Config) when is_list(_Config) ->
%% Basically open (create) and close an IPv6 TCP (stream) socket.
%% With some extra checks...
-api_b_open_and_close_tcp6(suite) ->
- [];
-api_b_open_and_close_tcp6(doc) ->
- [];
api_b_open_and_close_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_tcp6,
@@ -2632,10 +2771,6 @@ api_b_open_and_close_tcp6(_Config) when is_list(_Config) ->
%% Basically open (create) and close an Unix Domain dgram (UDP) socket.
%% With some extra checks...
-api_b_open_and_close_udpL(suite) ->
- [];
-api_b_open_and_close_udpL(doc) ->
- [];
api_b_open_and_close_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_udpL,
@@ -2652,10 +2787,6 @@ api_b_open_and_close_udpL(_Config) when is_list(_Config) ->
%% Basically open (create) and close an Unix Domain stream (TCP) socket.
%% With some extra checks...
-api_b_open_and_close_tcpL(suite) ->
- [];
-api_b_open_and_close_tcpL(doc) ->
- [];
api_b_open_and_close_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_tcpL,
@@ -2672,10 +2803,6 @@ api_b_open_and_close_tcpL(_Config) when is_list(_Config) ->
%% Basically open (create) and close an Unix Domain dgram (UDP) socket.
%% With some extra checks...
-api_b_open_and_close_seqpL(suite) ->
- [];
-api_b_open_and_close_seqpL(doc) ->
- [];
api_b_open_and_close_seqpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -2692,10 +2819,6 @@ api_b_open_and_close_seqpL(_Config) when is_list(_Config) ->
%% Basically open (create) and close an IPv4 SCTP (seqpacket) socket.
%% With some extra checks...
-api_b_open_and_close_sctp4(suite) ->
- [];
-api_b_open_and_close_sctp4(doc) ->
- [];
api_b_open_and_close_sctp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_close_sctp4,
@@ -2783,7 +2906,7 @@ api_b_open_and_close(InitState) ->
protocol := ExpProtocol}, {ok, Protocol}}) ->
%% On OpenBSD (at least 6.6) something screwy happens
%% when domain = local.
- %% It will report a completly different protocol (icmp)
+ %% It will report a completely different protocol (icmp)
%% but everything still works. So we skip if this happens
%% on OpenBSD...
case os:type() of
@@ -2847,10 +2970,6 @@ api_b_open_and_close(InitState) ->
%% Basically open (create) and (maybe) close an RAW socket.
-api_b_open_and_maybe_close_raw(suite) ->
- [];
-api_b_open_and_maybe_close_raw(doc) ->
- [];
api_b_open_and_maybe_close_raw(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_open_and_maybe_close_raw,
@@ -2913,13 +3032,10 @@ do_api_b_open_and_maybe_close_raw(InitState) ->
%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom..
-api_b_sendto_and_recvfrom_udp4(suite) ->
- [];
-api_b_sendto_and_recvfrom_udp4(doc) ->
- [];
api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_sendto_and_recvfrom_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data, Dest) ->
socket:sendto(Sock, Data, Dest)
@@ -2939,10 +3055,6 @@ api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) ->
%% Basically send and receive on an IPv4 UDP (dgram) socket using
%% sendto and recvfrom.
-api_b_sendto_and_recvfrom_udpL(suite) ->
- [];
-api_b_sendto_and_recvfrom_udpL(doc) ->
- [];
api_b_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_sendto_and_recvfrom_udpL,
@@ -2969,13 +3081,10 @@ api_b_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) ->
%% Basically send and receive on an IPv4 UDP (dgram) socket
%% using sendmsg and recvmsg.
-api_b_sendmsg_and_recvmsg_udp4(suite) ->
- [];
-api_b_sendmsg_and_recvmsg_udp4(doc) ->
- [];
api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_sendmsg_and_recvmsg_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data, Dest) ->
%% We need tests for this,
@@ -3013,10 +3122,6 @@ api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) ->
%% Basically send and receive on an IPv4 UDP (dgram) socket
%% using sendmsg and recvmsg.
-api_b_sendmsg_and_recvmsg_udpL(suite) ->
- [];
-api_b_sendmsg_and_recvmsg_udpL(doc) ->
- [];
api_b_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_sendmsg_and_recvmsg_udpL,
@@ -3201,13 +3306,10 @@ api_b_send_and_recv_udp(InitState) ->
%% Basically send and receive using the "common" functions (send and recv)
%% on an IPv4 TCP (stream) socket.
-api_b_send_and_recv_tcp4(suite) ->
- [];
-api_b_send_and_recv_tcp4(doc) ->
- [];
api_b_send_and_recv_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_b_send_and_recv_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data) ->
socket:send(Sock, Data)
@@ -3228,10 +3330,6 @@ api_b_send_and_recv_tcp4(_Config) when is_list(_Config) ->
%% Basically send and receive using the "common" functions (send and recv)
%% on an Unix Domain (stream) socket (TCP).
-api_b_send_and_recv_tcpL(suite) ->
- [];
-api_b_send_and_recv_tcpL(doc) ->
- [];
api_b_send_and_recv_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_b_send_and_recv_tcpL,
@@ -3256,10 +3354,6 @@ api_b_send_and_recv_tcpL(_Config) when is_list(_Config) ->
%% Basically send and receive using the "common" functions (send and recv)
%% on an Unix Domain seqpacket socket.
-api_b_send_and_recv_seqpL(suite) ->
- [];
-api_b_send_and_recv_seqpL(doc) ->
- [];
api_b_send_and_recv_seqpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(?FUNCTION_NAME,
@@ -3284,13 +3378,10 @@ api_b_send_and_recv_seqpL(_Config) when is_list(_Config) ->
%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an IPv4 TCP (stream) socket.
-api_b_sendmsg_and_recvmsg_tcp4(suite) ->
- [];
-api_b_sendmsg_and_recvmsg_tcp4(doc) ->
- [];
api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_b_sendmsg_and_recvmsg_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data) ->
Msg = #{iov => [Data]},
@@ -3321,10 +3412,6 @@ api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) ->
%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an Unix Domain (stream) socket (TCP).
-api_b_sendmsg_and_recvmsg_tcpL(suite) ->
- [];
-api_b_sendmsg_and_recvmsg_tcpL(doc) ->
- [];
api_b_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_b_sendmsg_and_recvmsg_tcpL,
@@ -3374,10 +3461,6 @@ api_b_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) ->
%% Basically send and receive using the msg functions (sendmsg and recvmsg)
%% on an Unix Domain (stream) socket (TCP).
-api_b_sendmsg_and_recvmsg_seqpL(suite) ->
- [];
-api_b_sendmsg_and_recvmsg_seqpL(doc) ->
- [];
api_b_sendmsg_and_recvmsg_seqpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(?FUNCTION_NAME,
@@ -3842,10 +3925,6 @@ api_b_send_and_recv_conn(InitState) ->
%% Basically send and receive on an IPv4 SCTP (seqpacket) socket
%% using sendmsg and recvmsg.
-api_b_sendmsg_and_recvmsg_sctp4(suite) ->
- [];
-api_b_sendmsg_and_recvmsg_sctp4(doc) ->
- [];
api_b_sendmsg_and_recvmsg_sctp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_b_sendmsg_and_recvmsg_sctp4,
@@ -4384,6 +4463,7 @@ api_b_send_and_recv_sctp(_InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
api_b_sendmsg_iov_dgram_inet(Config) when is_list(Config) ->
+ has_support_ipv4(),
api_b_sendmsg_iov_dgram(inet).
%%
api_b_sendmsg_iov_dgram_inet6(Config) when is_list(Config) ->
@@ -4395,6 +4475,7 @@ api_b_sendmsg_iov_dgram_local(Config) when is_list(Config) ->
api_b_sendmsg_iov_dgram(local).
api_b_sendmsg_iov_stream_inet(Config) when is_list(Config) ->
+ has_support_ipv4(),
api_b_sendmsg_iov_stream(inet).
%%
api_b_sendmsg_iov_stream_inet6(Config) when is_list(Config) ->
@@ -4489,6 +4570,7 @@ api_b_sendmsg_iov_stream(Domain) ->
api_sendfile_inet(Config) when is_list(Config) ->
has_support_sendfile(),
+ has_support_ipv4(),
api_sendfile(inet, Config, fun socket:sendfile/2).
api_sendfile_inet6(Config) when is_list(Config) ->
@@ -4505,6 +4587,7 @@ api_sendfile_local(Config) when is_list(Config) ->
api_sendfile_loop_inet(Config) when is_list(Config) ->
has_support_sendfile(),
+ has_support_ipv4(),
api_sendfile(inet, Config, fun sendfile_loop/2).
api_sendfile_loop_inet6(Config) when is_list(Config) ->
@@ -4650,13 +4733,10 @@ api_sendfile_verify_block(S, Data, M, Block, N) ->
%% With some extra checks...
%% IPv4
%% Without dup
-api_ffd_open_wod_and_info_udp4(suite) ->
- [];
-api_ffd_open_wod_and_info_udp4(doc) ->
- [];
api_ffd_open_wod_and_info_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_wod_and_info_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => dgram,
@@ -4673,10 +4753,6 @@ api_ffd_open_wod_and_info_udp4(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv6
%% Without dup
-api_ffd_open_wod_and_info_udp6(suite) ->
- [];
-api_ffd_open_wod_and_info_udp6(doc) ->
- [];
api_ffd_open_wod_and_info_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_wod_and_info_udp6,
@@ -4697,13 +4773,10 @@ api_ffd_open_wod_and_info_udp6(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv4
%% With dup
-api_ffd_open_wd_and_info_udp4(suite) ->
- [];
-api_ffd_open_wd_and_info_udp4(doc) ->
- [];
api_ffd_open_wd_and_info_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_wd_open_and_info_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => dgram,
@@ -4720,10 +4793,6 @@ api_ffd_open_wd_and_info_udp4(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv6
%% With dup
-api_ffd_open_wd_and_info_udp6(suite) ->
- [];
-api_ffd_open_wd_and_info_udp6(doc) ->
- [];
api_ffd_open_wd_and_info_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_wd_open_and_info_udp6,
@@ -4744,13 +4813,10 @@ api_ffd_open_wd_and_info_udp6(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv6
%% Without dup
-api_ffd_open_wod_and_info_tcp4(suite) ->
- [];
-api_ffd_open_wod_and_info_tcp4(doc) ->
- [];
api_ffd_open_wod_and_info_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_wod_and_info_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => stream,
@@ -4767,10 +4833,6 @@ api_ffd_open_wod_and_info_tcp4(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv6
%% Without dup
-api_ffd_open_wod_and_info_tcp6(suite) ->
- [];
-api_ffd_open_wod_and_info_tcp6(doc) ->
- [];
api_ffd_open_wod_and_info_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_wod_and_info_tcp6,
@@ -4791,13 +4853,10 @@ api_ffd_open_wod_and_info_tcp6(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv6
%% With dup
-api_ffd_open_wd_and_info_tcp4(suite) ->
- [];
-api_ffd_open_wd_and_info_tcp4(doc) ->
- [];
api_ffd_open_wd_and_info_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_wd_and_info_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => stream,
@@ -4814,10 +4873,6 @@ api_ffd_open_wd_and_info_tcp4(_Config) when is_list(_Config) ->
%% With some extra checks...
%% IPv6
%% With dup
-api_ffd_open_wd_and_info_tcp6(suite) ->
- [];
-api_ffd_open_wd_and_info_tcp6(doc) ->
- [];
api_ffd_open_wd_and_info_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_wd_and_info_tcp6,
@@ -5025,7 +5080,7 @@ api_ffd_open_and_info(InitState) ->
%% Basically open a socket (1) and then create another socket (2) from
%% its file descriptor *without* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv4 UDP (dgram) socket.
@@ -5039,13 +5094,10 @@ api_ffd_open_and_info(InitState) ->
%%
%% </WARNING>
%%
-api_ffd_open_and_open_wod_and_send_udp4(suite) ->
- [];
-api_ffd_open_and_open_wod_and_send_udp4(doc) ->
- [];
api_ffd_open_and_open_wod_and_send_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_and_open_wod_and_send_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => dgram,
@@ -5060,7 +5112,7 @@ api_ffd_open_and_open_wod_and_send_udp4(_Config) when is_list(_Config) ->
%% Basically open a socket (1) and then create another socket (2) from
%% its file descriptor *without* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv6 UDP (dgram) socket.
@@ -5074,10 +5126,6 @@ api_ffd_open_and_open_wod_and_send_udp4(_Config) when is_list(_Config) ->
%%
%% </WARNING>
%%
-api_ffd_open_and_open_wod_and_send_udp6(suite) ->
- [];
-api_ffd_open_and_open_wod_and_send_udp6(doc) ->
- [];
api_ffd_open_and_open_wod_and_send_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_and_open_wod_and_send_udp6,
@@ -5096,18 +5144,15 @@ api_ffd_open_and_open_wod_and_send_udp6(_Config) when is_list(_Config) ->
%% Basically open a socket (1) and then create another socket (2) from
%% its file descriptor *with* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv4 UDP (dgram) socket.
%%
-api_ffd_open_and_open_wd_and_send_udp4(suite) ->
- [];
-api_ffd_open_and_open_wd_and_send_udp4(doc) ->
- [];
api_ffd_open_and_open_wd_and_send_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_and_open_wd_and_send_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => dgram,
@@ -5122,15 +5167,11 @@ api_ffd_open_and_open_wd_and_send_udp4(_Config) when is_list(_Config) ->
%% Basically open a socket (1) and then create another socket (2) from
%% its file descriptor *with* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv6 UDP (dgram) socket.
%%
-api_ffd_open_and_open_wd_and_send_udp6(suite) ->
- [];
-api_ffd_open_and_open_wd_and_send_udp6(doc) ->
- [];
api_ffd_open_and_open_wd_and_send_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_and_open_wd_and_send_udp6,
@@ -5748,7 +5789,7 @@ api_ffd_open_and_open_and_send_udp2(InitState) ->
%% Basically open a socket (1), connect to a server and then create
%% another socket (2) from its file descriptor *without* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv4 TCP (stream) socket.
@@ -5762,10 +5803,6 @@ api_ffd_open_and_open_and_send_udp2(InitState) ->
%%
%% </WARNING>
%%
-api_ffd_open_connect_and_open_wod_and_send_tcp4(suite) ->
- [];
-api_ffd_open_connect_and_open_wod_and_send_tcp4(doc) ->
- [];
api_ffd_open_connect_and_open_wod_and_send_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_connect_and_open_wod_and_send_tcp4,
@@ -5783,7 +5820,7 @@ api_ffd_open_connect_and_open_wod_and_send_tcp4(_Config) when is_list(_Config) -
%% Basically open a socket (1), connect to a server and then create
%% another socket (2) from its file descriptor *without* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv6 TCP (stream) socket.
@@ -5797,10 +5834,6 @@ api_ffd_open_connect_and_open_wod_and_send_tcp4(_Config) when is_list(_Config) -
%%
%% </WARNING>
%%
-api_ffd_open_connect_and_open_wod_and_send_tcp6(suite) ->
- [];
-api_ffd_open_connect_and_open_wod_and_send_tcp6(doc) ->
- [];
api_ffd_open_connect_and_open_wod_and_send_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_connect_and_open_wod_and_send_tcp6,
@@ -5819,14 +5852,10 @@ api_ffd_open_connect_and_open_wod_and_send_tcp6(_Config) when is_list(_Config) -
%% Basically open a socket (1), connect to a server and then create
%% another socket (2) from its file descriptor *with* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv4 TCP (stream) socket.
-api_ffd_open_connect_and_open_wd_and_send_tcp4(suite) ->
- [];
-api_ffd_open_connect_and_open_wd_and_send_tcp4(doc) ->
- [];
api_ffd_open_connect_and_open_wd_and_send_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_connect_and_open_wd_and_send_tcp4,
@@ -5845,14 +5874,10 @@ api_ffd_open_connect_and_open_wd_and_send_tcp4(_Config) when is_list(_Config) ->
%% Basically open a socket (1), connect to a server and then create
%% another socket (2) from its file descriptor *with* dup.
-%% Exchange som data from via both "client" sockets.
+%% Exchange some data from via both "client" sockets.
%% Finally close the second socket. Ensure that the original socket
%% has not been closed (test by sending some data).
%% IPv6 TCP (stream) socket.
-api_ffd_open_connect_and_open_wd_and_send_tcp6(suite) ->
- [];
-api_ffd_open_connect_and_open_wd_and_send_tcp6(doc) ->
- [];
api_ffd_open_connect_and_open_wd_and_send_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_ffd_open_connect_and_open_wd_and_send_tcp6,
@@ -6524,14 +6549,10 @@ api_ffd_open_connect_and_open_and_send_tcp2(InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Basically establish a TCP connection via an async connect. IPv4.
-
-api_a_connect_tcp4(suite) ->
- [];
-api_a_connect_tcp4(doc) ->
- [];
api_a_connect_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
tc_try(api_a_connect_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
ok = api_a_connect_tcpD(inet, nowait(Config))
end).
@@ -6540,11 +6561,6 @@ api_a_connect_tcp4(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Basically establish a TCP connection via an async connect. IPv6.
-
-api_a_connect_tcp6(suite) ->
- [];
-api_a_connect_tcp6(doc) ->
- [];
api_a_connect_tcp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
tc_try(api_a_connect_tcp6,
@@ -7061,14 +7077,11 @@ api_a_connect_tcp(InitState) ->
%% select message). Note that we only do this for the recvfrom,
%% since its much more difficult to "arrange" for sendto.
%%
-api_a_sendto_and_recvfrom_udp4(suite) ->
- [];
-api_a_sendto_and_recvfrom_udp4(doc) ->
- [];
api_a_sendto_and_recvfrom_udp4(Config) when is_list(Config) ->
?TT(?SECS(5)),
Nowait = nowait(Config),
tc_try(api_a_sendto_and_recvfrom_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data, Dest) ->
socket:sendto(Sock, Data, Dest)
@@ -7093,10 +7106,6 @@ api_a_sendto_and_recvfrom_udp4(Config) when is_list(Config) ->
%% select message). Note that we only do this for the recvfrom,
%% since its much more difficult to "arrange" for sendto.
%%
-api_a_sendto_and_recvfrom_udp6(suite) ->
- [];
-api_a_sendto_and_recvfrom_udp6(doc) ->
- [];
api_a_sendto_and_recvfrom_udp6(Config) when is_list(Config) ->
?TT(?SECS(5)),
Nowait = nowait(Config),
@@ -7126,14 +7135,11 @@ api_a_sendto_and_recvfrom_udp6(Config) when is_list(Config) ->
%% select message). Note that we only do this for the recvmsg,
%% since its much more difficult to "arrange" for sendmsg.
%%
-api_a_sendmsg_and_recvmsg_udp4(suite) ->
- [];
-api_a_sendmsg_and_recvmsg_udp4(doc) ->
- [];
api_a_sendmsg_and_recvmsg_udp4(Config) when is_list(Config) ->
?TT(?SECS(5)),
Nowait = nowait(Config),
tc_try(api_a_sendmsg_and_recvmsg_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data, Dest) ->
Msg = #{addr => Dest,
@@ -7171,10 +7177,6 @@ api_a_sendmsg_and_recvmsg_udp4(Config) when is_list(Config) ->
%% select message). Note that we only do this for the recvmsg,
%% since its much more difficult to "arrange" for sendmsg.
%%
-api_a_sendmsg_and_recvmsg_udp6(suite) ->
- [];
-api_a_sendmsg_and_recvmsg_udp6(doc) ->
- [];
api_a_sendmsg_and_recvmsg_udp6(Config) when is_list(Config) ->
?TT(?SECS(5)),
Nowait = nowait(Config),
@@ -7652,14 +7654,11 @@ api_a_send_and_recv_udp(InitState) ->
%% select message). Note that we only do this for the recv,
%% since its much more difficult to "arrange" for send.
%% We *also* test async for accept.
-api_a_send_and_recv_tcp4(suite) ->
- [];
-api_a_send_and_recv_tcp4(doc) ->
- [];
api_a_send_and_recv_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_send_and_recv_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data) ->
socket:send(Sock, Data)
@@ -7684,10 +7683,6 @@ api_a_send_and_recv_tcp4(Config) when is_list(Config) ->
%% select message). Note that we only do this for the recv,
%% since its much more difficult to "arrange" for send.
%% We *also* test async for accept.
-api_a_send_and_recv_tcp6(suite) ->
- [];
-api_a_send_and_recv_tcp6(doc) ->
- [];
api_a_send_and_recv_tcp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -7717,14 +7712,11 @@ api_a_send_and_recv_tcp6(Config) when is_list(Config) ->
%% select message). Note that we only do this for the recvmsg,
%% since its much more difficult to "arrange" for sendmsg.
%% We *also* test async for accept.
-api_a_sendmsg_and_recvmsg_tcp4(suite) ->
- [];
-api_a_sendmsg_and_recvmsg_tcp4(doc) ->
- [];
api_a_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_sendmsg_and_recvmsg_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Send = fun(Sock, Data) ->
Msg = #{iov => [Data]},
@@ -7757,10 +7749,6 @@ api_a_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
%% select message). Note that we only do this for the recvmsg,
%% since its much more difficult to "arrange" for sendmsg.
%% We *also* test async for accept.
-api_a_sendmsg_and_recvmsg_tcp6(suite) ->
- [];
-api_a_sendmsg_and_recvmsg_tcp6(doc) ->
- [];
api_a_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -8320,14 +8308,11 @@ api_a_send_and_recv_tcp(Config, InitState) ->
%% Basically we make an async (Timeout = nowait) call to recvfrom,
%% wait some time and then cancel. IPv4
%%
-api_a_recvfrom_cancel_udp4(suite) ->
- [];
-api_a_recvfrom_cancel_udp4(doc) ->
- [];
api_a_recvfrom_cancel_udp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_recvfrom_cancel_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
case socket:recvfrom(Sock, 0, Nowait) of
@@ -8352,10 +8337,6 @@ api_a_recvfrom_cancel_udp4(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to recvfrom,
%% wait some time and then cancel. IPv6
%%
-api_a_recvfrom_cancel_udp6(suite) ->
- [];
-api_a_recvfrom_cancel_udp6(doc) ->
- [];
api_a_recvfrom_cancel_udp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -8385,14 +8366,11 @@ api_a_recvfrom_cancel_udp6(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel. IPv4
%%
-api_a_recvmsg_cancel_udp4(suite) ->
- [];
-api_a_recvmsg_cancel_udp4(doc) ->
- [];
api_a_recvmsg_cancel_udp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_recvmsg_cancel_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
case socket:recvmsg(Sock, Nowait) of
@@ -8417,10 +8395,6 @@ api_a_recvmsg_cancel_udp4(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel. IPv6
%%
-api_a_recvmsg_cancel_udp6(suite) ->
- [];
-api_a_recvmsg_cancel_udp6(doc) ->
- [];
api_a_recvmsg_cancel_udp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -8661,14 +8635,11 @@ api_a_recv_cancel_udp(InitState) ->
%% Basically we make an async (Timeout = nowait) call to accept,
%% wait some time and then cancel. IPv4
%%
-api_a_accept_cancel_tcp4(suite) ->
- [];
-api_a_accept_cancel_tcp4(doc) ->
- [];
api_a_accept_cancel_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_accept_cancel_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Accept = fun(Sock) ->
case socket:accept(Sock, Nowait) of
@@ -8694,10 +8665,6 @@ api_a_accept_cancel_tcp4(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to accept,
%% wait some time and then cancel. IPv6
%%
-api_a_accept_cancel_tcp6(suite) ->
- [];
-api_a_accept_cancel_tcp6(doc) ->
- [];
api_a_accept_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -8941,14 +8908,11 @@ api_a_accept_cancel_tcp(InitState) ->
%% Basically we make an async (Timeout = nowait) call to recv,
%% wait some time and then cancel. IPv4
%%
-api_a_recv_cancel_tcp4(suite) ->
- [];
-api_a_recv_cancel_tcp4(doc) ->
- [];
api_a_recv_cancel_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_recv_cancel_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
socket:recv(Sock, 0, Nowait)
@@ -8966,10 +8930,6 @@ api_a_recv_cancel_tcp4(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to recv,
%% wait some time and then cancel. IPv6
%%
-api_a_recv_cancel_tcp6(suite) ->
- [];
-api_a_recv_cancel_tcp6(doc) ->
- [];
api_a_recv_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -8992,14 +8952,11 @@ api_a_recv_cancel_tcp6(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel. IPv4
%%
-api_a_recvmsg_cancel_tcp4(suite) ->
- [];
-api_a_recvmsg_cancel_tcp4(doc) ->
- [];
api_a_recvmsg_cancel_tcp4(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
tc_try(api_a_recvmsg_cancel_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
socket:recvmsg(Sock, Nowait)
@@ -9017,10 +8974,6 @@ api_a_recvmsg_cancel_tcp4(Config) when is_list(Config) ->
%% Basically we make an async (Timeout = nowait) call to recvmsg,
%% wait some time and then cancel. IPv6
%%
-api_a_recvmsg_cancel_tcp6(suite) ->
- [];
-api_a_recvmsg_cancel_tcp6(doc) ->
- [];
api_a_recvmsg_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(10)),
Nowait = nowait(Config),
@@ -9407,14 +9360,11 @@ api_a_recv_cancel_tcp(InitState) ->
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes. IPv4
%%
-api_a_mrecvfrom_cancel_udp4(suite) ->
- [];
-api_a_mrecvfrom_cancel_udp4(doc) ->
- [];
api_a_mrecvfrom_cancel_udp4(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
tc_try(api_a_mrecvfrom_cancel_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
case socket:recvfrom(Sock, 0, Nowait) of
@@ -9440,10 +9390,6 @@ api_a_mrecvfrom_cancel_udp4(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes. IPv6
%%
-api_a_mrecvfrom_cancel_udp6(suite) ->
- [];
-api_a_mrecvfrom_cancel_udp6(doc) ->
- [];
api_a_mrecvfrom_cancel_udp6(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
@@ -9474,14 +9420,11 @@ api_a_mrecvfrom_cancel_udp6(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes. IPv4
%%
-api_a_mrecvmsg_cancel_udp4(suite) ->
- [];
-api_a_mrecvmsg_cancel_udp4(doc) ->
- [];
api_a_mrecvmsg_cancel_udp4(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
tc_try(api_a_mrecvmsg_cancel_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
case socket:recvmsg(Sock, Nowait) of
@@ -9507,10 +9450,6 @@ api_a_mrecvmsg_cancel_udp4(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel.
%% This should result in abort messages to the 'other' processes. IPv6
%%
-api_a_mrecvmsg_cancel_udp6(suite) ->
- [];
-api_a_mrecvmsg_cancel_udp6(doc) ->
- [];
api_a_mrecvmsg_cancel_udp6(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
@@ -9928,14 +9867,11 @@ api_a_mrecv_cancel_udp(InitState) ->
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv4
%%
-api_a_maccept_cancel_tcp4(suite) ->
- [];
-api_a_maccept_cancel_tcp4(doc) ->
- [];
api_a_maccept_cancel_tcp4(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
tc_try(api_a_maccept_cancel_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Accept = fun(Sock) ->
case socket:accept(Sock, Nowait) of
@@ -9962,10 +9898,6 @@ api_a_maccept_cancel_tcp4(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv6
%%
-api_a_maccept_cancel_tcp6(suite) ->
- [];
-api_a_maccept_cancel_tcp6(doc) ->
- [];
api_a_maccept_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
@@ -10387,14 +10319,11 @@ api_a_maccept_cancel_tcp(InitState) ->
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv4
%%
-api_a_mrecv_cancel_tcp4(suite) ->
- [];
-api_a_mrecv_cancel_tcp4(doc) ->
- [];
api_a_mrecv_cancel_tcp4(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
tc_try(api_a_mrecv_cancel_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
socket:recv(Sock, 0, Nowait)
@@ -10413,10 +10342,6 @@ api_a_mrecv_cancel_tcp4(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv6
%%
-api_a_mrecv_cancel_tcp6(suite) ->
- [];
-api_a_mrecv_cancel_tcp6(doc) ->
- [];
api_a_mrecv_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
@@ -10440,14 +10365,11 @@ api_a_mrecv_cancel_tcp6(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv4
%%
-api_a_mrecvmsg_cancel_tcp4(suite) ->
- [];
-api_a_mrecvmsg_cancel_tcp4(doc) ->
- [];
api_a_mrecvmsg_cancel_tcp4(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
tc_try(api_a_mrecvmsg_cancel_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) ->
socket:recvmsg(Sock, Nowait)
@@ -10466,10 +10388,6 @@ api_a_mrecvmsg_cancel_tcp4(Config) when is_list(Config) ->
%% (from *several* processes), wait some time and then cancel,
%% This should result in abort messages to the 'other' processes. IPv6
%%
-api_a_mrecvmsg_cancel_tcp6(suite) ->
- [];
-api_a_mrecvmsg_cancel_tcp6(doc) ->
- [];
api_a_mrecvmsg_cancel_tcp6(Config) when is_list(Config) ->
?TT(?SECS(20)),
Nowait = nowait(Config),
@@ -11037,10 +10955,6 @@ api_a_mrecv_cancel_tcp(InitState) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Perform some simple getopt and setopt with the level = otp options
-api_opt_simple_otp_options(suite) ->
- [];
-api_opt_simple_otp_options(doc) ->
- [];
api_opt_simple_otp_options(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_simple_otp_options,
@@ -11304,7 +11218,8 @@ api_opt_simple_otp_options() ->
%% *** We are done ***
#{desc => "finish",
- cmd => fun(_) ->
+ cmd => fun(#{ dummy := Dummy }) ->
+ Dummy ! die,
{ok, normal}
end}
],
@@ -11324,10 +11239,6 @@ api_opt_simple_otp_options() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Perform some simple getopt and setopt otp meta option
-api_opt_simple_otp_meta_option(suite) ->
- [];
-api_opt_simple_otp_meta_option(doc) ->
- [];
api_opt_simple_otp_meta_option(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_simple_otp_meta_option,
@@ -11504,10 +11415,6 @@ api_opt_simple_otp_meta_option() ->
%% Perform some simple operations with the rcvbuf otp option
%% The operations we test here are only for type = stream and
%% protocol = tcp.
-api_opt_simple_otp_rcvbuf_option(suite) ->
- [];
-api_opt_simple_otp_rcvbuf_option(doc) ->
- [];
api_opt_simple_otp_rcvbuf_option(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(api_opt_simple_otp_rcvbuf_option,
@@ -12150,7 +12057,7 @@ api_opt_simple_otp_rcvbuf_option() ->
%% Create a data binary of 6*1024 bytes
Data = list_to_binary(lists:duplicate(6*4, lists:seq(0, 255))),
- InitState = #{domain => inet,
+ InitState = #{domain => inet_or_inet6(),
data => Data},
i("create server evaluator"),
@@ -12175,10 +12082,6 @@ api_opt_simple_otp_rcvbuf_option() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Perform some simple getopt and setopt with the level = otp options
-api_opt_simple_otp_controlling_process(suite) ->
- [];
-api_opt_simple_otp_controlling_process(doc) ->
- [];
api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_simple_otp_controlling_process,
@@ -12399,7 +12302,7 @@ api_opt_simple_otp_controlling_process() ->
Client1 = ?SEV_START("tcp-client", ClientSeq, ClientInitState1),
i("start tcp (stream) tester evaluator"),
- TesterInitState1 = #{domain => inet,
+ TesterInitState1 = #{domain => inet,
type => stream,
protocol => tcp,
client => Client1#ev.pid},
@@ -12413,7 +12316,7 @@ api_opt_simple_otp_controlling_process() ->
Client2 = ?SEV_START("udp-client", ClientSeq, ClientInitState2),
i("start udp (dgram) tester evaluator"),
- TesterInitState2 = #{domain => inet,
+ TesterInitState2 = #{domain => inet,
type => dgram,
protocol => udp,
client => Client2#ev.pid},
@@ -12429,10 +12332,6 @@ api_opt_simple_otp_controlling_process() ->
%% Tests the socket option acceptconn for UDP.
%% This should be possible to get but not set.
-api_opt_sock_acceptconn_udp(suite) ->
- [];
-api_opt_sock_acceptconn_udp(doc) ->
- [];
api_opt_sock_acceptconn_udp(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_sock_acceptconn_udp,
@@ -12561,7 +12460,7 @@ api_opt_sock_acceptconn_udp() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -12577,10 +12476,6 @@ api_opt_sock_acceptconn_udp() ->
%% Tests the socket option acceptconn for TCP.
%% This should be possible to get but not set.
-api_opt_sock_acceptconn_tcp(suite) ->
- [];
-api_opt_sock_acceptconn_tcp(doc) ->
- [];
api_opt_sock_acceptconn_tcp(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_sock_acceptconn_tcp,
@@ -12917,7 +12812,7 @@ api_opt_sock_acceptconn_tcp() ->
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -12932,10 +12827,6 @@ api_opt_sock_acceptconn_tcp() ->
%% Tests the socket option acceptfilter. PLACEHOLDER!
-api_opt_sock_acceptfilter(suite) ->
- [];
-api_opt_sock_acceptfilter(doc) ->
- [];
api_opt_sock_acceptfilter(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_sock_acceptfilter,
@@ -12948,12 +12839,8 @@ api_opt_sock_acceptfilter(_Config) when is_list(_Config) ->
%% Tests the socket option bindtodevice.
%% It has not always been possible to 'get' this option
-%% (atleast on linux).
+%% (at least on linux).
-api_opt_sock_bindtodevice(suite) ->
- [];
-api_opt_sock_bindtodevice(doc) ->
- [];
api_opt_sock_bindtodevice(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_sock_bindtodevice,
@@ -13221,7 +13108,7 @@ api_opt_sock_bindtodevice() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -13238,10 +13125,6 @@ api_opt_sock_bindtodevice() ->
%% Make it possible for datagram sockets to send packets to a broadcast
%% address (IPv4 only).
-api_opt_sock_broadcast(suite) ->
- [];
-api_opt_sock_broadcast(doc) ->
- [];
api_opt_sock_broadcast(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_sock_broadcast,
@@ -13468,7 +13351,7 @@ api_opt_sock_broadcast() ->
(#{sock3 := Sock,
sa1 := Dest} = _State) ->
Data = list_to_binary("hejsan"),
- ?SEV_IPRINT("try send to bradcast address: "
+ ?SEV_IPRINT("try send to broadcast address: "
"~n ~p", [Dest]),
case socket:sendto(Sock, Data, Dest) of
ok ->
@@ -13514,7 +13397,7 @@ api_opt_sock_broadcast() ->
cmd => fun(#{sock3 := Sock,
sa2 := Dest} = _State) ->
Data = list_to_binary("hejsan"),
- ?SEV_IPRINT("try send to bradcast address: "
+ ?SEV_IPRINT("try send to broadcast address: "
"~n ~p", [Dest]),
case socket:sendto(Sock, Data, Dest) of
ok ->
@@ -13572,7 +13455,7 @@ api_opt_sock_broadcast() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -13588,13 +13471,9 @@ api_opt_sock_broadcast() ->
%% Tests the socket option debug.
%% On linux, this test requires that the user running the test to have
%% CAP_NET_ADMIN capabilities or be root (effective user ID of 0),
-%% therefor we explicitly test for the result eacces when attempting to
+%% therefore we explicitly test for the result eacces when attempting to
%% set, and skip if we get it.
-api_opt_sock_debug(suite) ->
- [];
-api_opt_sock_debug(doc) ->
- [];
api_opt_sock_debug(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_debug,
@@ -13617,19 +13496,14 @@ api_opt_sock_debug() ->
cmd => fun(#{domain := Domain} = State) ->
case ?LIB:which_local_host_info(Domain) of
{ok, #{name := Name,
- addr := Addr,
- broadaddr := BAddr}} ->
+ addr := Addr}} ->
?SEV_IPRINT("local host info: "
"~n Name: ~p"
- "~n Addr: ~p"
- "~n Broadcast Addr: ~p",
- [Name, Addr, BAddr]),
+ "~n Addr: ~p",
+ [Name, Addr]),
LSA = #{family => Domain,
addr => Addr},
- BSA = #{family => Domain,
- addr => BAddr},
- {ok, State#{lsa => LSA,
- bsa => BSA}};
+ {ok, State#{lsa => LSA}};
{error, _} = ERROR ->
ERROR
end
@@ -13697,7 +13571,7 @@ api_opt_sock_debug() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -13713,10 +13587,6 @@ api_opt_sock_debug() ->
%% Tests the socket option domain.
%% This is a read only option. Also not available on all platforms.
-api_opt_sock_domain(suite) ->
- [];
-api_opt_sock_domain(doc) ->
- [];
api_opt_sock_domain(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_domain,
@@ -13736,19 +13606,14 @@ api_opt_sock_domain() ->
cmd => fun(#{domain := Domain} = State) ->
case ?LIB:which_local_host_info(Domain) of
{ok, #{name := Name,
- addr := Addr,
- broadaddr := BAddr}} ->
+ addr := Addr}} ->
?SEV_IPRINT("local host info: "
"~n Name: ~p"
- "~n Addr: ~p"
- "~n Broadcast Addr: ~p",
- [Name, Addr, BAddr]),
+ "~n Addr: ~p",
+ [Name, Addr]),
LSA = #{family => Domain,
addr => Addr},
- BSA = #{family => Domain,
- addr => BAddr},
- {ok, State#{lsa => LSA,
- bsa => BSA}};
+ {ok, State#{lsa => LSA}};
{error, _} = ERROR ->
ERROR
end
@@ -13815,7 +13680,7 @@ api_opt_sock_domain() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -13838,10 +13703,6 @@ api_opt_sock_domain() ->
%% other side"), we only test if we can set and get the value.
%% Better then nothing.
-api_opt_sock_dontroute(suite) ->
- [];
-api_opt_sock_dontroute(doc) ->
- [];
api_opt_sock_dontroute(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_dontroute,
@@ -13864,19 +13725,14 @@ api_opt_sock_dontroute() ->
cmd => fun(#{domain := Domain} = State) ->
case ?LIB:which_local_host_info(Domain) of
{ok, #{name := Name,
- addr := Addr,
- broadaddr := BAddr}} ->
+ addr := Addr}} ->
?SEV_IPRINT("local host info: "
"~n Name: ~p"
- "~n Addr: ~p"
- "~n Broadcast Addr: ~p",
- [Name, Addr, BAddr]),
+ "~n Addr: ~p",
+ [Name, Addr]),
LSA = #{family => Domain,
addr => Addr},
- BSA = #{family => Domain,
- addr => BAddr},
- {ok, State#{lsa => LSA,
- bsa => BSA}};
+ {ok, State#{lsa => LSA}};
{error, _} = ERROR ->
ERROR
end
@@ -13946,7 +13802,7 @@ api_opt_sock_dontroute() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -13961,10 +13817,6 @@ api_opt_sock_dontroute() ->
%% Tests the socket option error. PLACEHOLDER!
-api_opt_sock_error(suite) ->
- [];
-api_opt_sock_error(doc) ->
- [];
api_opt_sock_error(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_error,
@@ -13980,10 +13832,6 @@ api_opt_sock_error(_Config) when is_list(_Config) ->
%% the underlying TCP timeouts. So, for now, we just test that we can
%% change the value.
-api_opt_sock_keepalive(suite) ->
- [];
-api_opt_sock_keepalive(doc) ->
- [];
api_opt_sock_keepalive(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_keepalive,
@@ -14006,19 +13854,14 @@ api_opt_sock_keepalive() ->
cmd => fun(#{domain := Domain} = State) ->
case ?LIB:which_local_host_info(Domain) of
{ok, #{name := Name,
- addr := Addr,
- broadaddr := BAddr}} ->
+ addr := Addr}} ->
?SEV_IPRINT("local host info: "
"~n Name: ~p"
- "~n Addr: ~p"
- "~n Broadcast Addr: ~p",
- [Name, Addr, BAddr]),
+ "~n Addr: ~p",
+ [Name, Addr]),
LSA = #{family => Domain,
addr => Addr},
- BSA = #{family => Domain,
- addr => BAddr},
- {ok, State#{lsa => LSA,
- bsa => BSA}};
+ {ok, State#{lsa => LSA}};
{error, _} = ERROR ->
ERROR
end
@@ -14090,7 +13933,7 @@ api_opt_sock_keepalive() ->
?SEV_FINISH_NORMAL
],
- Domain = inet,
+ Domain = inet_or_inet6(),
i("start tester evaluator"),
InitState = #{domain => Domain},
@@ -14105,10 +13948,6 @@ api_opt_sock_keepalive() ->
%% Tests the socket option linger. PLACEHOLDER!
-api_opt_sock_linger(suite) ->
- [];
-api_opt_sock_linger(doc) ->
- [];
api_opt_sock_linger(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_linger,
@@ -14121,10 +13960,6 @@ api_opt_sock_linger(_Config) when is_list(_Config) ->
%% Tests the socket option mark. PLACEHOLDER!
-api_opt_sock_mark(suite) ->
- [];
-api_opt_sock_mark(doc) ->
- [];
api_opt_sock_mark(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_opt_sock_mark,
@@ -14141,7 +13976,7 @@ api_opt_sock_mark(_Config) when is_list(_Config) ->
%%
%% socket:setopt(Sock, socket, oobinline, boolean()).
%%
-%% This works on linux of some version (atleast linux kernel 4.15.0),
+%% This works on linux of some version (at least linux kernel 4.15.0),
%% but not on FreeBSD (12) for some reason. Until we have figured out
%% exctly why, we skip a bunch of OSs...
%%
@@ -14150,10 +13985,6 @@ api_opt_sock_mark(_Config) when is_list(_Config) ->
%% linux but maybe not in, say, FreeBSD).
%%
-api_opt_sock_oobinline(suite) ->
- [];
-api_opt_sock_oobinline(doc) ->
- [];
api_opt_sock_oobinline(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_ooinline,
@@ -14179,7 +14010,7 @@ api_opt_sock_oobinline(_Config) when is_list(_Config) ->
(Sock, false) ->
socket:recv(Sock)
end,
- InitState = #{domain => inet,
+ InitState = #{domain => inet_or_inet6(),
proto => tcp,
send => Send,
recv => Recv,
@@ -14783,10 +14614,6 @@ do_api_opt_sock_oobinline(InitState) ->
%% As it is now, the client does *not* get any credentials!
%% Until this has been done, this case is skipped!.
-api_opt_sock_passcred_tcp4(suite) ->
- [];
-api_opt_sock_passcred_tcp4(doc) ->
- [];
api_opt_sock_passcred_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_passcred_tcp4,
@@ -15574,10 +15401,6 @@ api_opt_sock_passcred_tcp(InitState) ->
%%
%%
-api_opt_sock_peek_off_tcpL(suite) ->
- [];
-api_opt_sock_peek_off_tcpL(doc) ->
- [];
api_opt_sock_peek_off_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_peek_off_tcpL,
@@ -16125,7 +15948,7 @@ api_opt_sock_peek_off(InitState) ->
%% There is no way to be sure that the data has actually arrived,
%% and with no data on the server side, the peek will fail.
- %% Hopfully a sleep will take care of this...
+ %% Hopefully a sleep will take care of this...
?SEV_SLEEP(?SECS(1)),
%% 1) peek
@@ -16288,7 +16111,7 @@ api_opt_sock_peek_off(InitState) ->
%% Tests that we get the peer credentials for a connected unix domain
%% TCP (stream) socket.
-%% That is, all we need to do is to create a slave node, and have
+%% That is, all we need to do is to create a node, and have
%% process connect from that to a local (unix domain socket) socket.
%%
%% THIS IS A PLACEHOLDER!!
@@ -16297,10 +16120,6 @@ api_opt_sock_peek_off(InitState) ->
%% and decode it...
%%
-api_opt_sock_peercred_tcpL(suite) ->
- [];
-api_opt_sock_peercred_tcpL(doc) ->
- [];
api_opt_sock_peercred_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_peercred_tcpL,
@@ -16477,11 +16296,11 @@ api_opt_sock_peercred_tcp(_InitState) ->
%% #{desc => "create node",
%% cmd => fun(#{host := Host} = State) ->
%% ?SEV_IPRINT("try create node on ~p", [Host]),
- %% case start_node(Host, client) of
- %% {ok, Node} ->
+ %% case ?CT_PEER() of
+ %% {ok, Peer, Node} ->
%% ?SEV_IPRINT("client node ~p started",
%% [Node]),
- %% {ok, State#{node => Node}};
+ %% {ok, State#{node => Node, peer => Peer}};
%% {error, Reason} ->
%% {skip, Reason}
%% end
@@ -16590,8 +16409,8 @@ api_opt_sock_peercred_tcp(_InitState) ->
%% {ok, State1}
%% end},
%% #{desc => "stop client node",
- %% cmd => fun(#{node := Node} = _State) ->
- %% stop_node(Node)
+ %% cmd => fun(#{peer := Peer} = _State) ->
+ %% peer:stop(Peer)
%% end},
%% #{desc => "await client node termination",
%% cmd => fun(#{node := Node} = State) ->
@@ -16836,14 +16655,10 @@ api_opt_sock_peercred_tcp(_InitState) ->
%%
%%
-api_opt_sock_priority_udp4(suite) ->
- [];
-api_opt_sock_priority_udp4(doc) ->
- [];
api_opt_sock_priority_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_priority_udp4,
- fun() -> has_support_sock_priority() end,
+ fun() -> has_support_ipv4(), has_support_sock_priority() end,
fun() ->
Set = fun(Sock, Value) ->
socket:setopt(Sock, socket, priority, Value)
@@ -16869,14 +16684,10 @@ api_opt_sock_priority_udp4(_Config) when is_list(_Config) ->
%%
%%
-api_opt_sock_priority_tcp4(suite) ->
- [];
-api_opt_sock_priority_tcp4(doc) ->
- [];
api_opt_sock_priority_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_priority_tcp4,
- fun() -> has_support_sock_priority() end,
+ fun() -> has_support_ipv4(), has_support_sock_priority() end,
fun() ->
Set = fun(Sock, Value) ->
socket:setopt(Sock, socket, priority, Value)
@@ -17010,14 +16821,10 @@ api_opt_sock_priority(InitState) ->
%%
%%
-api_opt_sock_rcvbuf_udp4(suite) ->
- [];
-api_opt_sock_rcvbuf_udp4(doc) ->
- [];
api_opt_sock_rcvbuf_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_rcvbuf_udp4,
- fun() -> has_support_sock_rcvbuf() end,
+ fun() -> has_support_ipv4(), has_support_sock_rcvbuf() end,
fun() ->
ok = api_opt_sock_buf_udp4(rcvbuf)
end).
@@ -17031,14 +16838,10 @@ api_opt_sock_rcvbuf_udp4(_Config) when is_list(_Config) ->
%%
%%
-api_opt_sock_sndbuf_udp4(suite) ->
- [];
-api_opt_sock_sndbuf_udp4(doc) ->
- [];
api_opt_sock_sndbuf_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_sndbuf_udp4,
- fun() -> has_support_sock_sndbuf() end,
+ fun() -> has_support_ipv4(), has_support_sock_sndbuf() end,
fun() ->
ok = api_opt_sock_buf_udp4(sndbuf)
end).
@@ -17167,14 +16970,10 @@ api_opt_sock_buf(InitState) ->
%% but we don't (we just set the value and read it back...)
%%
-api_opt_sock_rcvtimeo_udp4(suite) ->
- [];
-api_opt_sock_rcvtimeo_udp4(doc) ->
- [];
api_opt_sock_rcvtimeo_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_rcvtimeo_udp4,
- fun() -> has_support_sock_rcvtimeo() end,
+ fun() -> has_support_ipv4(), has_support_sock_rcvtimeo() end,
fun() ->
ok = api_opt_sock_timeo_udp4(rcvtimeo)
end).
@@ -17188,14 +16987,10 @@ api_opt_sock_rcvtimeo_udp4(_Config) when is_list(_Config) ->
%%
%%
-api_opt_sock_sndtimeo_udp4(suite) ->
- [];
-api_opt_sock_sndtimeo_udp4(doc) ->
- [];
api_opt_sock_sndtimeo_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_sndtimeo_udp4,
- fun() -> has_support_sock_sndtimeo() end,
+ fun() -> has_support_ipv4(), has_support_sock_sndtimeo() end,
fun() ->
ok = api_opt_sock_timeo_udp4(sndtimeo)
end).
@@ -17291,7 +17086,7 @@ api_opt_sock_timeo(InitState) ->
ok;
{ok, #{sec := Sec}} when (ExpSec =:= Sec) ->
%% For some reason OpenBSD "adjusts" the timeout,
- %% so that usec does not (allways match)
+ %% so that usec does not (always match)
?SEV_IPRINT("timeout (approx) validated"),
ok;
{ok, TO} ->
@@ -17338,14 +17133,10 @@ api_opt_sock_timeo(InitState) ->
%%
%%
-api_opt_sock_rcvlowat_udp4(suite) ->
- [];
-api_opt_sock_rcvlowat_udp4(doc) ->
- [];
api_opt_sock_rcvlowat_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_rcvlowat_udp4,
- fun() -> has_support_sock_rcvlowat() end,
+ fun() -> has_support_ipv4(), has_support_sock_rcvlowat() end,
fun() ->
ok = api_opt_sock_lowat_udp4(rcvlowat)
end).
@@ -17361,14 +17152,10 @@ api_opt_sock_rcvlowat_udp4(_Config) when is_list(_Config) ->
%% so we skip if we get ENOPROTOOPT when attempting a change.
%%
-api_opt_sock_sndlowat_udp4(suite) ->
- [];
-api_opt_sock_sndlowat_udp4(doc) ->
- [];
api_opt_sock_sndlowat_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_sndlowat_udp4,
- fun() -> has_support_sock_sndlowat() end,
+ fun() -> has_support_ipv4(), has_support_sock_sndlowat() end,
fun() ->
ok = api_opt_sock_lowat_udp4(sndlowat)
end).
@@ -17505,14 +17292,10 @@ api_opt_sock_lowat(InitState) ->
%% All subsequent *received* messages will be timestamped.
%%
-api_opt_sock_timestamp_udp4(suite) ->
- [];
-api_opt_sock_timestamp_udp4(doc) ->
- [];
api_opt_sock_timestamp_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_timestamp_udp4,
- fun() -> has_support_sock_timestamp() end,
+ fun() -> has_support_ipv4(), has_support_sock_timestamp() end,
fun() ->
Set = fun(Sock, Value) ->
socket:setopt(Sock, socket, timestamp, Value)
@@ -17891,14 +17674,11 @@ api_opt_sock_timestamp_udp(InitState) ->
%% Don't actually know if its the distro or the (kernel) version...
%%
-api_opt_sock_timestamp_tcp4(suite) ->
- [];
-api_opt_sock_timestamp_tcp4(doc) ->
- [];
api_opt_sock_timestamp_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_sock_timestamp_tcp4,
fun() ->
+ has_support_ipv4(),
has_support_sock_timestamp(),
is_good_enough_linux({4,4,120}),
is_not_freebsd(),
@@ -18311,7 +18091,7 @@ api_opt_sock_timestamp_tcp(InitState) ->
ERROR
end
end},
- %% Linux pecularity observed here...
+ %% Linux peculiarity observed here...
%% Detected on Kernel 4.15.0-72 x96_64.
%% The option set to enable receiving timestamps just above
%% has failed to be effective down in "await recv reply 2
@@ -18696,10 +18476,9 @@ api_opt_sock_timestamp_tcp(InitState) ->
%% When sending, the dest will be the multicast address
%% and port of the receiving socket.
%% Receiving socket: Bound to the multicast address and port.
-api_opt_ip_add_drop_membership(suite) ->
- [];
-api_opt_ip_add_drop_membership(doc) ->
- ["OTP-15908 (ERL-980)"];
+api_opt_ip_add_drop_membership() ->
+ [{doc, "OTP-15908 (ERL-980)"}].
+
api_opt_ip_add_drop_membership(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(api_opt_ip_add_drop_membership,
@@ -18708,10 +18487,10 @@ api_opt_ip_add_drop_membership(_Config) when is_list(_Config) ->
has_support_ip_drop_membership(),
has_support_ip_multicast()
end,
- fun() -> api_opt_ip_add_drop_membership() end).
+ fun() -> api_opt_ip_add_drop_membership_do() end).
-api_opt_ip_add_drop_membership() ->
+api_opt_ip_add_drop_membership_do() ->
Set = fun(S, Key, Val) ->
socket:setopt(S, ip, Key, Val)
end,
@@ -19038,14 +18817,10 @@ which_local_host_ifname(Domain) ->
%% we do not test!!
%%
-api_opt_ip_pktinfo_udp4(suite) ->
- [];
-api_opt_ip_pktinfo_udp4(doc) ->
- [];
api_opt_ip_pktinfo_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_pktinfo_udp4,
- fun() -> has_support_ip_pktinfo() end,
+ fun() -> has_support_ipv4(), has_support_ip_pktinfo() end,
fun() ->
Set = fun(Sock, Value) ->
socket:setopt(Sock, ip, pktinfo, Value)
@@ -19394,14 +19169,11 @@ api_opt_ip_pktinfo_udp(InitState) ->
%% </NOTE>
%%
-api_opt_ip_recvopts_udp4(suite) ->
- [];
-api_opt_ip_recvopts_udp4(doc) ->
- [];
api_opt_ip_recvopts_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_recvopts_udp4,
fun() ->
+ has_support_ipv4(),
has_support_ip_recvopts(),
%% We also use the recvtos and timestamp options
%% in this test, so at least one of them must
@@ -19853,14 +19625,10 @@ api_opt_ip_recvopts_udp(InitState) ->
%%
%%
-api_opt_ip_recvorigdstaddr_udp4(suite) ->
- [];
-api_opt_ip_recvorigdstaddr_udp4(doc) ->
- [];
api_opt_ip_recvorigdstaddr_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_recvorigdstaddr_udp4,
- fun() -> has_support_ip_recvorigdstaddr() end,
+ fun() -> has_support_ipv4(), has_support_ip_recvorigdstaddr() end,
fun() ->
Set = fun(Sock, Value) ->
socket:setopt(Sock, ip, recvorigdstaddr, Value)
@@ -20109,14 +19877,11 @@ api_opt_ip_recvorigdstaddr_udp(InitState) ->
%% that method. Instead, set tos (true) on the sending socket.
%%
-api_opt_ip_recvtos_udp4(suite) ->
- [];
-api_opt_ip_recvtos_udp4(doc) ->
- [];
api_opt_ip_recvtos_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_recvtos_udp4,
fun() ->
+ has_support_ipv4(),
has_support_ip_recvtos(),
has_support_ip_tos() % Used in the test
end,
@@ -20486,14 +20251,11 @@ api_opt_ip_recvtos_udp(InitState) ->
%% skip darwin and OpenBSD.
%%
-api_opt_ip_recvttl_udp4(suite) ->
- [];
-api_opt_ip_recvttl_udp4(doc) ->
- [];
api_opt_ip_recvttl_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_recvttl_udp4,
fun() ->
+ has_support_ipv4(),
has_support_ip_recvttl(),
is_not_openbsd(),
is_not_darwin()
@@ -20872,14 +20634,10 @@ api_opt_ip_recvttl_udp(InitState) ->
%% Default value is supposed to be '0'.
%%
-api_opt_ip_tos_udp4(suite) ->
- [];
-api_opt_ip_tos_udp4(doc) ->
- [];
api_opt_ip_tos_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_tos_udp4,
- fun() -> has_support_ip_tos() end,
+ fun() -> has_support_ipv4(), has_support_ip_tos() end,
fun() ->
Set = fun(Sock, Value) ->
socket:setopt(Sock, ip, tos, Value)
@@ -20900,7 +20658,7 @@ api_opt_ip_tos_udp(InitState) ->
process_flag(trap_exit, true),
%% mincost is not supported on all platforms.
%% For instance, Solaris 10, does not have that constant.
- %% Instead it has two others with, what appers to be,
+ %% Instead it has two others with, what appears to be,
%% completely different meanings...
%% So, avoid the complication by not using this value...
%% TOS1 = mincost, TOS1Str = atom_to_list(TOS1),
@@ -21118,14 +20876,11 @@ api_opt_ip_tos_udp(InitState) ->
%% queue can be read.
%%
-api_opt_ip_recverr_udp4(suite) ->
- [];
-api_opt_ip_recverr_udp4(doc) ->
- [];
api_opt_ip_recverr_udp4(Config) when is_list(Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_recverr_udp4,
fun() ->
+ has_support_ipv4(),
has_support_ip_recverr()
end,
fun() ->
@@ -21157,10 +20912,6 @@ api_opt_ip_recverr_udp4(Config) when is_list(Config) ->
%% queue can be read.
%%
-api_opt_ipv6_recverr_udp6(suite) ->
- [];
-api_opt_ipv6_recverr_udp6(doc) ->
- [];
api_opt_ipv6_recverr_udp6(Config) when is_list(Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ipv6_recverr_udp6,
@@ -21249,7 +21000,7 @@ api_opt_recverr_udp(Config, InitState) ->
"~n ~p", [SelectInfo]),
{ok, State#{rselect => SelectInfo}};
{ok, _} ->
- ?SEV_EPRINT("unexpected successs"),
+ ?SEV_EPRINT("unexpected success"),
{error, unexpected_success};
{error, Reason} = ERROR ->
?SEV_EPRINT("unexpected error: ~p", [Reason]),
@@ -21310,7 +21061,7 @@ api_opt_recverr_udp(Config, InitState) ->
?SEV_IPRINT("expected failure: ~p", [Reason]),
ok;
{ok, _} ->
- ?SEV_EPRINT("unexpected successs"),
+ ?SEV_EPRINT("unexpected success"),
{error, unexpected_success};
{select, SelectInfo} ->
?SEV_EPRINT("unexpected select: ~p",
@@ -21448,14 +21199,11 @@ api_opt_recverr_udp(Config, InitState) ->
%% the test (since its a IPv4 test case).
%%
-api_opt_ip_mopts_udp4(suite) ->
- [];
-api_opt_ip_mopts_udp4(doc) ->
- [];
api_opt_ip_mopts_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ip_mopts_udp4,
fun() ->
+ has_support_ipv4(),
case is_any_options_supported(
[{ip, pktinfo},
{ip, recvorigdstaddr},
@@ -21789,10 +21537,6 @@ api_opt_ip_mopts_udp(InitState) ->
%% although we only test this with dgram.
%%
-api_opt_ipv6_recvpktinfo_udp6(suite) ->
- [];
-api_opt_ipv6_recvpktinfo_udp6(doc) ->
- [];
api_opt_ipv6_recvpktinfo_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ipv6_recvpktinfo_udp6,
@@ -22052,14 +21796,10 @@ api_opt_ipv6_recvpktinfo_udp(InitState) ->
%% There seem to be some weirdness with the definition of this
%% option, so its defined in an include file we don't include
%% (directly or indirectly). And since some of the defines
-%% are occure in a file we *do* include (via netinet/in.h), we
+%% occur in a file we *do* include (via netinet/in.h), we
%% leave it as is for now...
%%
-api_opt_ipv6_flowinfo_udp6(suite) ->
- [];
-api_opt_ipv6_flowinfo_udp6(doc) ->
- [];
api_opt_ipv6_flowinfo_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ipv6_flowinfo_udp6,
@@ -22315,10 +22055,6 @@ api_opt_ipv6_flowinfo_udp(InitState) ->
%% </Note>
%%
-api_opt_ipv6_hoplimit_udp6(suite) ->
- [];
-api_opt_ipv6_hoplimit_udp6(doc) ->
- [];
api_opt_ipv6_hoplimit_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ipv6_hoplimit_udp6,
@@ -22606,10 +22342,6 @@ api_opt_ipv6_hoplimit_udp(InitState) ->
%% </Note>
%%
-api_opt_ipv6_tclass_udp6(suite) ->
- [];
-api_opt_ipv6_tclass_udp6(doc) ->
- [];
api_opt_ipv6_tclass_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ipv6_tclass_udp6,
@@ -22963,10 +22695,6 @@ api_opt_ipv6_tclass_udp(InitState) ->
%% the test (since its a IPv6 test case).
%%
-api_opt_ipv6_mopts_udp6(suite) ->
- [];
-api_opt_ipv6_mopts_udp6(doc) ->
- [];
api_opt_ipv6_mopts_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_ipv6_mopts_udp6,
@@ -23254,18 +22982,14 @@ api_opt_ipv6_mopts_udp(InitState) ->
%% According to the man page (on linux) for this option it *should* be
%% possible to both get and set *allowed* algorithms. But when we attempt
%% to set, we get 'enoent'.
-%% Accoring to /proc/sys/net/ipv4/tcp_allowed_congestion_control that
+%% According to /proc/sys/net/ipv4/tcp_allowed_congestion_control that
%% allgorithm was allowed, so...
%% For now, we only test that we can get (it could be a bug in our code)
-api_opt_tcp_congestion_tcp4(suite) ->
- [];
-api_opt_tcp_congestion_tcp4(doc) ->
- [];
api_opt_tcp_congestion_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_tcp_congestion_tcp4,
- fun() -> has_support_tcp_congestion() end,
+ fun() -> has_support_ipv4(), has_support_tcp_congestion() end,
fun() ->
Set = fun(Sock, Value) when is_list(Value) ->
socket:setopt(Sock, tcp, congestion, Value)
@@ -23449,14 +23173,10 @@ api_opt_tcp_congestion_tcp(InitState) ->
%% Reading the man page it seems like (on linux) that the
%% value resets itself after some (short) time...
-api_opt_tcp_cork_tcp4(suite) ->
- [];
-api_opt_tcp_cork_tcp4(doc) ->
- [];
api_opt_tcp_cork_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_tcp_cork_tcp4,
- fun() -> has_support_tcp_cork() end,
+ fun() -> has_support_ipv4(), has_support_tcp_cork() end,
fun() ->
Set = fun(Sock, Value) when is_boolean(Value) ->
socket:setopt(Sock, tcp, cork, Value)
@@ -23568,17 +23288,13 @@ api_opt_tcp_cork_tcp(InitState) ->
%%
%% Note that there is no point in reading this value back,
%% since the kernel imposes its own rules with regard
-%% to what is an acceptible value.
+%% to what is an acceptable value.
%%
-api_opt_tcp_maxseg_tcp4(suite) ->
- [];
-api_opt_tcp_maxseg_tcp4(doc) ->
- [];
api_opt_tcp_maxseg_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_tcp_maxseg_tcp4,
- fun() -> has_support_tcp_maxseg() end,
+ fun() -> has_support_ipv4(), has_support_tcp_maxseg() end,
fun() ->
Set = fun(Sock, Value) when is_integer(Value) ->
socket:setopt(Sock, tcp, maxseg, Value)
@@ -23644,7 +23360,7 @@ api_opt_tcp_maxseg_tcp(InitState) ->
%% Note that there is no point in reading this value back,
%% since the kernel imposes its own rules with regard
- %% to what is an acceptible value.
+ %% to what is an acceptable value.
%% So, even if the set operation is a success, the value
%% still might not have changed.
%%
@@ -23698,14 +23414,10 @@ api_opt_tcp_maxseg_tcp(InitState) ->
%% This is a very simple test. We simple set and get the value.
%% To test that it has an effect is just "to much work"...
-api_opt_tcp_nodelay_tcp4(suite) ->
- [];
-api_opt_tcp_nodelay_tcp4(doc) ->
- [];
api_opt_tcp_nodelay_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_tcp_nodelay_tcp4,
- fun() -> has_support_tcp_nodelay() end,
+ fun() -> has_support_ipv4(), has_support_tcp_nodelay() end,
fun() ->
Set = fun(Sock, Value) when is_boolean(Value) ->
socket:setopt(Sock, tcp, nodelay, Value)
@@ -23816,14 +23528,10 @@ api_opt_tcp_nodelay_tcp(InitState) ->
%% To test that it has an effect is just "to much work"...
%%
-api_opt_udp_cork_udp4(suite) ->
- [];
-api_opt_udp_cork_udp4(doc) ->
- [];
api_opt_udp_cork_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(api_opt_udp_cork_udp4,
- fun() -> has_support_udp_cork() end,
+ fun() -> has_support_ipv4(), has_support_udp_cork() end,
fun() ->
Set = fun(Sock, Value) when is_boolean(Value) ->
socket:setopt(Sock, udp, cork, Value)
@@ -23939,13 +23647,9 @@ api_opt_udp_cork_udp(InitState) ->
%% This test case is intended to test the connect timeout option
%% on an IPv4 TCP (stream) socket.
-api_to_connect_tcp4(suite) ->
- [];
-api_to_connect_tcp4(doc) ->
- [];
api_to_connect_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
- Cond = fun() -> api_to_connect_cond() end,
+ Cond = fun() -> has_support_ipv4(), api_to_connect_cond() end,
tc_try(api_to_connect_tcp4,
Cond,
fun() ->
@@ -23961,7 +23665,7 @@ api_to_connect_cond() ->
%% I don't know exactly at which version this starts to work.
%% I know it does not work for 4.4.*, but is does for 4.15.
-%% So, just to simplify, we require atleast 4.15
+%% So, just to simplify, we require at least 4.15
api_to_connect_cond({unix, linux}, {Maj, Min, _Rev}) ->
if
(Maj > 4) ->
@@ -23998,10 +23702,6 @@ api_to_connect_cond(_, _) ->
%% This test case is intended to test the connect timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_connect_tcp6(suite) ->
- [];
-api_to_connect_tcp6(doc) ->
- [];
api_to_connect_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_connect_tcp6,
@@ -24019,7 +23719,7 @@ api_to_connect_tcp6(_Config) when is_list(_Config) ->
%% We use the backlog (listen) argument to test this.
%% Note that the behaviour of the TCP "server side" can vary when
%% a client connect to a "busy" server (full backlog).
-%% For instance, on FreeBSD (11.2) the reponse when the backlog is full
+%% For instance, on FreeBSD (11.2) the response when the backlog is full
%% is a econreset.
api_to_connect_tcp(InitState) ->
@@ -24119,16 +23819,9 @@ api_to_connect_tcp(InitState) ->
{ok, State#{local_sa => LSA}}
end},
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- ?SEV_IPRINT("try create node on ~p", [Host]),
- case start_node(Host, client) of
- {ok, Node} ->
- ?SEV_IPRINT("client node ~p started",
- [Node]),
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(#{host := _Host} = State) ->
+ {Peer, Node} = ?START_NODE("client"),
+ {ok, State#{node => Node, peer => Peer}}
end},
#{desc => "monitor client node",
cmd => fun(#{node := Node} = _State) ->
@@ -24233,9 +23926,9 @@ api_to_connect_tcp(InitState) ->
{ok, State1}
end},
#{desc => "stop client node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -24257,14 +23950,14 @@ api_to_connect_tcp(InitState) ->
receive
{nodedown, Node} ->
?SEV_IPRINT("nodedown received - cleanup"),
- State1 = maps:remove(node_id, State),
- State2 = maps:remove(node, State1),
+ State1 = maps:remove(peer, State),
+ State2 = maps:remove(node, State1),
{ok, State2}
end;
(#{node_stop := error} = State) ->
?SEV_IPRINT("Failed node stop - cleanup"),
- State1 = maps:remove(node_id, State),
- State2 = maps:remove(node, State1),
+ State1 = maps:remove(peer, State),
+ State2 = maps:remove(node, State1),
{ok, State2}
end},
@@ -24511,13 +24204,10 @@ api_to_connect_tcp_await_timeout3([Sock|Socka]) ->
%% This test case is intended to test the accept timeout option
%% on an IPv4 TCP (stream) socket.
-api_to_accept_tcp4(suite) ->
- [];
-api_to_accept_tcp4(doc) ->
- [];
api_to_accept_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_accept_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet, timeout => 5000},
ok = api_to_accept_tcp(InitState)
@@ -24528,13 +24218,9 @@ api_to_accept_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the accept timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_accept_tcp6(suite) ->
- [];
-api_to_accept_tcp6(doc) ->
- [];
api_to_accept_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
- tc_try(api_to_accept_tcp4,
+ tc_try(api_to_accept_tcp6,
fun() -> has_support_ipv6() end,
fun() ->
InitState = #{domain => inet6, timeout => 5000},
@@ -24625,13 +24311,10 @@ api_to_accept_tcp(InitState) ->
%% This test case is intended to test the multi accept timeout option
%% on an IPv4 TCP (stream) socket with multiple acceptor processes
%% (three in this case).
-api_to_maccept_tcp4(suite) ->
- [];
-api_to_maccept_tcp4(doc) ->
- [];
api_to_maccept_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(20)),
tc_try(api_to_maccept_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet, timeout => 5000},
ok = api_to_maccept_tcp(InitState)
@@ -24642,13 +24325,9 @@ api_to_maccept_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the accept timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_maccept_tcp6(suite) ->
- [];
-api_to_maccept_tcp6(doc) ->
- [];
api_to_maccept_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(20)),
- tc_try(api_to_maccept_tcp4,
+ tc_try(api_to_maccept_tcp6,
fun() -> has_support_ipv6() end,
fun() ->
InitState = #{domain => inet6, timeout => 5000},
@@ -24995,12 +24674,9 @@ api_to_maccept_tcp(InitState) ->
%% This test case is intended to test the send timeout option
%% on an IPv4 TCP (stream) socket.
-api_to_send_tcp4(suite) ->
- [];
-api_to_send_tcp4(doc) ->
- [];
api_to_send_tcp4(_Config) when is_list(_Config) ->
tc_try(api_to_send_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_send_tcp(inet)
@@ -25011,10 +24687,6 @@ api_to_send_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the send timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_send_tcp6(suite) ->
- [];
-api_to_send_tcp6(doc) ->
- [];
api_to_send_tcp6(_Config) when is_list(_Config) ->
tc_try(api_to_send_tcp6,
fun() -> has_support_ipv6() end,
@@ -25028,12 +24700,9 @@ api_to_send_tcp6(_Config) when is_list(_Config) ->
%% This test case is intended to test the sendto timeout option
%% on an IPv4 UDP (dgram) socket.
-api_to_sendto_udp4(suite) ->
- [];
-api_to_sendto_udp4(doc) ->
- [];
api_to_sendto_udp4(_Config) when is_list(_Config) ->
tc_try(api_to_sendto_udp4,
+ fun () -> has_support_ipv4() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_sendto_to_udp(inet)
@@ -25044,10 +24713,6 @@ api_to_sendto_udp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the sendto timeout option
%% on an IPv6 UDP (dgram) socket.
-api_to_sendto_udp6(suite) ->
- [];
-api_to_sendto_udp6(doc) ->
- [];
api_to_sendto_udp6(_Config) when is_list(_Config) ->
tc_try(api_to_sendto_udp6,
fun() -> has_support_ipv6() end,
@@ -25061,12 +24726,9 @@ api_to_sendto_udp6(_Config) when is_list(_Config) ->
%% This test case is intended to test the sendmsg timeout option
%% on an IPv4 TCP (stream) socket.
-api_to_sendmsg_tcp4(suite) ->
- [];
-api_to_sendmsg_tcp4(doc) ->
- [];
api_to_sendmsg_tcp4(_Config) when is_list(_Config) ->
tc_try(api_to_sendmsg_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
not_yet_implemented()%% ,
%% ok = api_to_sendmsg_tcp(inet)
@@ -25077,10 +24739,6 @@ api_to_sendmsg_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the sendmsg timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_sendmsg_tcp6(suite) ->
- [];
-api_to_sendmsg_tcp6(doc) ->
- [];
api_to_sendmsg_tcp6(_Config) when is_list(_Config) ->
tc_try(api_to_sendmsg_tcp6,
fun() -> has_support_ipv6() end,
@@ -25095,12 +24753,9 @@ api_to_sendmsg_tcp6(_Config) when is_list(_Config) ->
%% This test case is intended to test the recv timeout option
%% on an IPv4 UDP (dgram) socket. To test this we must connect
%% the socket.
-api_to_recv_udp4(suite) ->
- [];
-api_to_recv_udp4(doc) ->
- [];
api_to_recv_udp4(_Config) when is_list(_Config) ->
tc_try(api_to_recv_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
not_yet_implemented()%%,
%%ok = api_to_recv_udp(inet)
@@ -25112,10 +24767,6 @@ api_to_recv_udp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the recv timeout option
%% on an IPv6 UDP (dgram) socket. To test this we must connect
%% the socket.
-api_to_recv_udp6(suite) ->
- [];
-api_to_recv_udp6(doc) ->
- [];
api_to_recv_udp6(_Config) when is_list(_Config) ->
tc_try(api_to_recv_udp6,
fun() -> has_support_ipv6() end,
@@ -25129,13 +24780,10 @@ api_to_recv_udp6(_Config) when is_list(_Config) ->
%% This test case is intended to test the recv timeout option
%% on an IPv4 TCP (stream) socket.
-api_to_recv_tcp4(suite) ->
- [];
-api_to_recv_tcp4(doc) ->
- [];
api_to_recv_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recv_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end,
InitState = #{domain => inet,
@@ -25149,10 +24797,6 @@ api_to_recv_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the recv timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_recv_tcp6(suite) ->
- [];
-api_to_recv_tcp6(doc) ->
- [];
api_to_recv_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recv_tcp6,
@@ -25486,13 +25130,10 @@ api_to_receive_tcp(InitState) ->
%% This test case is intended to test the recvfrom timeout option
%% on an IPv4 UDP (dgram) socket.
-api_to_recvfrom_udp4(suite) ->
- [];
-api_to_recvfrom_udp4(doc) ->
- [];
api_to_recvfrom_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recvfrom_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end,
InitState = #{domain => inet,
@@ -25506,10 +25147,6 @@ api_to_recvfrom_udp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the recvfrom timeout option
%% on an IPv6 UDP (dgram) socket.
-api_to_recvfrom_udp6(suite) ->
- [];
-api_to_recvfrom_udp6(doc) ->
- [];
api_to_recvfrom_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recvfrom_udp6,
@@ -25602,13 +25239,10 @@ api_to_receive_udp(InitState) ->
%% This test case is intended to test the recvmsg timeout option
%% on an IPv4 UDP (dgram) socket.
-api_to_recvmsg_udp4(suite) ->
- [];
-api_to_recvmsg_udp4(doc) ->
- [];
api_to_recvmsg_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recvmsg_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
InitState = #{domain => inet,
@@ -25622,10 +25256,6 @@ api_to_recvmsg_udp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the recvmsg timeout option
%% on an IPv6 UDP (dgram) socket.
-api_to_recvmsg_udp6(suite) ->
- [];
-api_to_recvmsg_udp6(doc) ->
- [];
api_to_recvmsg_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recvmsg_udp6,
@@ -25643,13 +25273,10 @@ api_to_recvmsg_udp6(_Config) when is_list(_Config) ->
%% This test case is intended to test the recvmsg timeout option
%% on an IPv4 TCP (stream) socket.
-api_to_recvmsg_tcp4(suite) ->
- [];
-api_to_recvmsg_tcp4(doc) ->
- [];
api_to_recvmsg_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recvmsg_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
InitState = #{domain => inet,
@@ -25663,10 +25290,6 @@ api_to_recvmsg_tcp4(_Config) when is_list(_Config) ->
%% This test case is intended to test the recvmsg timeout option
%% on an IPv6 TCP (stream) socket.
-api_to_recvmsg_tcp6(suite) ->
- [];
-api_to_recvmsg_tcp6(doc) ->
- [];
api_to_recvmsg_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(api_to_recvmsg_tcp6,
@@ -25693,10 +25316,6 @@ api_to_recvmsg_tcp6(_Config) when is_list(_Config) ->
%% We create a bunch of different sockets and ensure that the registry
%% has the correct info.
-reg_s_single_open_and_close_and_count(suite) ->
- [];
-reg_s_single_open_and_close_and_count(doc) ->
- [];
reg_s_single_open_and_close_and_count(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(reg_s_single_open_and_close_and_count,
@@ -26086,10 +25705,6 @@ reg_sr_num2(Existing, F) ->
%% We create a bunch of different sockets and ensure that the registry
%% has the correct info.
-reg_s_optional_open_and_close_and_count(suite) ->
- [];
-reg_s_optional_open_and_close_and_count(doc) ->
- [];
reg_s_optional_open_and_close_and_count(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(reg_s_optional_open_and_close_and_count,
@@ -26198,10 +25813,6 @@ reg_s_optional_open_and_close_and_count() ->
%% Create one socket, monitor from a different process then close socket.
%% The process that did the monitor shall receive a socket DOWN.
-monitor_simple_open_and_close(suite) ->
- [];
-monitor_simple_open_and_close(doc) ->
- [];
monitor_simple_open_and_close(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_simple_open_and_close,
@@ -26458,10 +26069,6 @@ mon_simple_open_and_close(InitState) ->
%% owner process.
%% The process that did the monitor shall receive a socket DOWN.
-monitor_simple_open_and_exit(suite) ->
- [];
-monitor_simple_open_and_exit(doc) ->
- [];
monitor_simple_open_and_exit(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_simple_open_and_exit,
@@ -26653,10 +26260,6 @@ mon_simple_open_and_exit(InitState) ->
%% (demonitor) and then close socket.
%% The process that did the monitor shall *not* receive a socket DOWN.
-monitor_simple_open_and_demon_and_close(suite) ->
- [];
-monitor_simple_open_and_demon_and_close(doc) ->
- [];
monitor_simple_open_and_demon_and_close(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_simple_open_and_demon_and_close,
@@ -26848,10 +26451,6 @@ mon_simple_open_and_demon_and_close(InitState) ->
%% Create several sockets, monitor from a different process then close
%% socket. The process that did the monitor shall receive a socket DOWN.
-monitor_open_and_close_multi_socks(suite) ->
- [];
-monitor_open_and_close_multi_socks(doc) ->
- [];
monitor_open_and_close_multi_socks(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_open_and_close_multi_socks,
@@ -27293,10 +26892,6 @@ mon_open_and_close_multi_socks(InitState) ->
%% the owner process.
%% The process that did the monitor shall receive a socket DOWN.
-monitor_open_and_exit_multi_socks(suite) ->
- [];
-monitor_open_and_exit_multi_socks(doc) ->
- [];
monitor_open_and_exit_multi_socks(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_open_and_exit_multi_socks,
@@ -27614,10 +27209,6 @@ mon_open_and_exit_multi_socks(InitState) ->
%% The process that did the monitor shall receive a socket DOWN for
%% the sockets that are still monitored.
-monitor_open_and_demon_and_close_multi_socks(suite) ->
- [];
-monitor_open_and_demon_and_close_multi_socks(doc) ->
- [];
monitor_open_and_demon_and_close_multi_socks(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_open_and_demon_and_close_multi_socks,
@@ -27987,10 +27578,6 @@ mon_open_and_demon_and_close_multi_socks(InitState) ->
%% processes, then close socket (from 'owner').
%% The processes that did the monitor shall receive a socket DOWN.
-monitor_open_and_close_multi_mon(suite) ->
- [];
-monitor_open_and_close_multi_mon(doc) ->
- [];
monitor_open_and_close_multi_mon(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_open_and_close_multi_mon,
@@ -28580,10 +28167,6 @@ mon_open_and_close_multi_mon(InitState) ->
%% processes, then close socket (from 'owner').
%% The processes that did the monitor shall receive a socket DOWN.
-monitor_open_and_exit_multi_mon(suite) ->
- [];
-monitor_open_and_exit_multi_mon(doc) ->
- [];
monitor_open_and_exit_multi_mon(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_open_and_exit_multi_mon,
@@ -29138,10 +28721,6 @@ mon_open_and_exit_multi_mon(InitState) ->
%% The processes that did the monitor shall receive one socket DOWN for
%% each socket.
-monitor_open_and_close_multi_socks_and_mon(suite) ->
- [];
-monitor_open_and_close_multi_socks_and_mon(doc) ->
- [];
monitor_open_and_close_multi_socks_and_mon(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(monitor_open_and_close_multi_socks_and_mon,
@@ -30096,10 +29675,6 @@ mon_open_and_close_multi_socks_and_mon(InitState) ->
%% The processes that did the monitor shall receive one socket DOWN for
%% each socket.
-monitor_open_and_exit_multi_socks_and_mon(suite) ->
- [];
-monitor_open_and_exit_multi_socks_and_mon(doc) ->
- [];
monitor_open_and_exit_multi_socks_and_mon(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(monitor_open_and_exit_multi_socks_and_mon,
@@ -30847,10 +30422,6 @@ mon_open_and_exit_multi_socks_and_mon(InitState) ->
%% The processes that did the monitor shall receive one socket DOWN for
%% each socket.
-monitor_closed_socket(suite) ->
- [];
-monitor_closed_socket(doc) ->
- [];
monitor_closed_socket(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(monitor_closed_socket,
@@ -31146,10 +30717,6 @@ mon_closed_socket(InitState) ->
%% ("removed") when the controlling process terminates (without explicitly
%% calling the close function). For a IPv4 TCP (stream) socket.
-sc_cpe_socket_cleanup_tcp4(suite) ->
- [];
-sc_cpe_socket_cleanup_tcp4(doc) ->
- [];
sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_tcp4,
@@ -31166,10 +30733,6 @@ sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) ->
%% ("removed") when the controlling process terminates (without explicitly
%% calling the close function). For a IPv6 TCP (stream) socket.
-sc_cpe_socket_cleanup_tcp6(suite) ->
- [];
-sc_cpe_socket_cleanup_tcp6(doc) ->
- [];
sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_tcp6,
@@ -31187,10 +30750,6 @@ sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) ->
%% ("removed") when the controlling process terminates (without explicitly
%% calling the close function). For a Unix Domain (stream) socket (TCP).
-sc_cpe_socket_cleanup_tcpL(suite) ->
- [];
-sc_cpe_socket_cleanup_tcpL(doc) ->
- [];
sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_tcpL,
@@ -31208,13 +30767,10 @@ sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) ->
%% ("removed") when the controlling process terminates (without explicitly
%% calling the close function). For a IPv4 UDP (dgram) socket.
-sc_cpe_socket_cleanup_udp4(suite) ->
- [];
-sc_cpe_socket_cleanup_udp4(doc) ->
- [];
sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
type => dgram,
@@ -31229,10 +30785,6 @@ sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) ->
%% (removed) when the controlling process terminates (without explicitly
%% calling the close function). For a IPv6 UDP (dgram) socket.
-sc_cpe_socket_cleanup_udp6(suite) ->
- [];
-sc_cpe_socket_cleanup_udp6(doc) ->
- [];
sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_udp6,
@@ -31250,10 +30802,6 @@ sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) ->
%% ("removed") when the controlling process terminates (without explicitly
%% calling the close function). For a Unix Domain (dgram) socket (UDP).
-sc_cpe_socket_cleanup_udpL(suite) ->
- [];
-sc_cpe_socket_cleanup_udpL(doc) ->
- [];
sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_cpe_socket_cleanup_udpL,
@@ -31303,7 +30851,7 @@ sc_cpe_socket_cleanup(InitState) ->
end},
%% *** The actual test ***
- %% We *intentially* leave the socket "as is", no explicit close
+ %% We *intentionally* leave the socket "as is", no explicit close
#{desc => "await terminate (from tester)",
cmd => fun(#{tester := Tester} = State) ->
case ?SEV_AWAIT_TERMINATE(Tester, tester) of
@@ -31412,13 +30960,10 @@ sc_cpe_socket_cleanup(InitState) ->
%%
%% </KOLLA>
-sc_lc_recv_response_tcp4(suite) ->
- [];
-sc_lc_recv_response_tcp4(doc) ->
- [];
sc_lc_recv_response_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_recv_response_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) -> socket:recv(Sock) end,
InitState = #{domain => inet,
@@ -31433,10 +30978,6 @@ sc_lc_recv_response_tcp4(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recv function.
%% Socket is IPv6.
-sc_lc_recv_response_tcp6(suite) ->
- [];
-sc_lc_recv_response_tcp6(doc) ->
- [];
sc_lc_recv_response_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_recv_response_tcp6,
@@ -31455,10 +30996,6 @@ sc_lc_recv_response_tcp6(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recv function.
%% Socket is Unix Domain (stream) socket.
-sc_lc_recv_response_tcpL(suite) ->
- [];
-sc_lc_recv_response_tcpL(doc) ->
- [];
sc_lc_recv_response_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_recv_response_tcpL,
@@ -31647,7 +31184,7 @@ sc_lc_receive_response_tcp(InitState) ->
],
%% The point of this is to perform the recv for which
- %% we are testing the reponse.
+ %% we are testing the response.
HandlerSeq =
[
%% *** Wait for start order part ***
@@ -32099,13 +31636,10 @@ sc_lc_receive_response_tcp(InitState) ->
%% Socket is IPv4.
%%
-sc_lc_recvfrom_response_udp4(suite) ->
- [];
-sc_lc_recvfrom_response_udp4(doc) ->
- [];
sc_lc_recvfrom_response_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_lc_recvfrom_response_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end,
InitState = #{domain => inet,
@@ -32120,10 +31654,6 @@ sc_lc_recvfrom_response_udp4(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recv function.
%% Socket is IPv6.
-sc_lc_recvfrom_response_udp6(suite) ->
- [];
-sc_lc_recvfrom_response_udp6(doc) ->
- [];
sc_lc_recvfrom_response_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_lc_recvfrom_response_udp6,
@@ -32142,10 +31672,6 @@ sc_lc_recvfrom_response_udp6(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recv function.
%% Socket is Unix Domainm (dgram) socket.
-sc_lc_recvfrom_response_udpL(suite) ->
- [];
-sc_lc_recvfrom_response_udpL(doc) ->
- [];
sc_lc_recvfrom_response_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_lc_recvfrom_response_udpL,
@@ -32419,7 +31945,7 @@ sc_lc_receive_response_udp(InitState) ->
%% The actual test
- %% Make all the seondary servers continue, with an infinit recvfrom
+ %% Make all the seondary servers continue, with an infinite recvfrom
%% and then the prim-server with a timed recvfrom.
%% After the prim server notifies us (about the timeout) we order it
%% to close the socket, which should cause the all the secondary
@@ -32571,13 +32097,10 @@ sc_lc_receive_response_udp(InitState) ->
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv4.
-sc_lc_recvmsg_response_tcp4(suite) ->
- [];
-sc_lc_recvmsg_response_tcp4(doc) ->
- [];
sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_recvmsg_response_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) -> socket:recvmsg(Sock) end,
InitState = #{domain => inet,
@@ -32592,10 +32115,6 @@ sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv6.
-sc_lc_recvmsg_response_tcp6(suite) ->
- [];
-sc_lc_recvmsg_response_tcp6(doc) ->
- [];
sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_recvmsg_response_tcp6,
@@ -32614,10 +32133,6 @@ sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recvmsg function.
%% Socket is Unix Domain (stream) socket.
-sc_lc_recvmsg_response_tcpL(suite) ->
- [];
-sc_lc_recvmsg_response_tcpL(doc) ->
- [];
sc_lc_recvmsg_response_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_recvmsg_response_tcpL,
@@ -32636,12 +32151,9 @@ sc_lc_recvmsg_response_tcpL(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv4.
-sc_lc_recvmsg_response_udp4(suite) ->
- [];
-sc_lc_recvmsg_response_udp4(doc) ->
- [];
sc_lc_recvmsg_response_udp4(_Config) when is_list(_Config) ->
tc_try(sc_lc_recvmsg_response_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(10)),
Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end,
@@ -32657,10 +32169,6 @@ sc_lc_recvmsg_response_udp4(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recvmsg function.
%% Socket is IPv6.
-sc_lc_recvmsg_response_udp6(suite) ->
- [];
-sc_lc_recvmsg_response_udp6(doc) ->
- [];
sc_lc_recvmsg_response_udp6(_Config) when is_list(_Config) ->
tc_try(sc_recvmsg_response_udp6,
fun() -> has_support_ipv6() end,
@@ -32680,10 +32188,6 @@ sc_lc_recvmsg_response_udp6(_Config) when is_list(_Config) ->
%% locally closed while the process is calling the recvmsg function.
%% Socket is Unix Domain (dgram) socket.
-sc_lc_recvmsg_response_udpL(suite) ->
- [];
-sc_lc_recvmsg_response_udpL(doc) ->
- [];
sc_lc_recvmsg_response_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_recvmsg_response_udpL,
@@ -32705,13 +32209,10 @@ sc_lc_recvmsg_response_udpL(_Config) when is_list(_Config) ->
%% git the setup anyway.
%% Socket is IPv4.
-sc_lc_acceptor_response_tcp4(suite) ->
- [];
-sc_lc_acceptor_response_tcp4(doc) ->
- [];
sc_lc_acceptor_response_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_acceptor_response_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
protocol => tcp},
@@ -32726,10 +32227,6 @@ sc_lc_acceptor_response_tcp4(_Config) when is_list(_Config) ->
%% git the setup anyway.
%% Socket is IPv6.
-sc_lc_acceptor_response_tcp6(suite) ->
- [];
-sc_lc_acceptor_response_tcp6(doc) ->
- [];
sc_lc_acceptor_response_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_acceptor_response_tcp6,
@@ -32748,10 +32245,6 @@ sc_lc_acceptor_response_tcp6(_Config) when is_list(_Config) ->
%% git the setup anyway.
%% Socket is Unix Domain (stream) socket.
-sc_lc_acceptor_response_tcpL(suite) ->
- [];
-sc_lc_acceptor_response_tcpL(doc) ->
- [];
sc_lc_acceptor_response_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_lc_acceptor_response_tcpL,
@@ -33020,7 +32513,7 @@ sc_lc_acceptor_response_tcp(InitState) ->
%% The actual test
- %% Make all the seondary servers continue, with an infinit recvfrom
+ %% Make all the seondary servers continue, with an infinite recvfrom
%% and then the prim-server with a timed recvfrom.
%% After the prim server notifies us (about the timeout) we order it
%% to close the socket, which should cause the all the secondary
@@ -33176,13 +32669,10 @@ sc_lc_acceptor_response_tcp(InitState) ->
%% now, we will make do with different VMs on the same host.
%%
-sc_rc_recv_response_tcp4(suite) ->
- [];
-sc_rc_recv_response_tcp4(doc) ->
- [];
sc_rc_recv_response_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rc_recv_response_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) -> socket:recv(Sock) end,
InitState = #{domain => inet,
@@ -33197,10 +32687,6 @@ sc_rc_recv_response_tcp4(_Config) when is_list(_Config) ->
%% remotely closed while the process is calling the recv function.
%% Socket is IPv6.
-sc_rc_recv_response_tcp6(suite) ->
- [];
-sc_rc_recv_response_tcp6(doc) ->
- [];
sc_rc_recv_response_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rc_recv_response_tcp6,
@@ -33219,10 +32705,6 @@ sc_rc_recv_response_tcp6(_Config) when is_list(_Config) ->
%% remotely closed while the process is calling the recv function.
%% Socket is Unix Domain (stream) socket.
-sc_rc_recv_response_tcpL(suite) ->
- [];
-sc_rc_recv_response_tcpL(doc) ->
- [];
sc_rc_recv_response_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rc_recv_response_tcpL,
@@ -33535,19 +33017,11 @@ sc_rc_receive_response_tcp(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host, node_id := NodeID} = State) ->
- case start_node(Host,
- l2a(f("client_~w", [NodeID]))) of
- {ok, Node} ->
- ?SEV_IPRINT("client node ~p started",
- [Node]),
- {ok, State#{node => Node}};
- {error, Reason} ->
- ?SEV_EPRINT("failed starting "
- "client node ~p (=> SKIP):"
- "~n ~p", [NodeID, Reason]),
- {skip, Reason}
- end
+ cmd => fun(#{node_id := NodeID} = State) ->
+ {Peer, Node} =
+ ?START_NODE(?CT_PEER_NAME(f("client_~w",
+ [NodeID]))),
+ {ok, State#{node => Node, peer => Peer}}
end},
#{desc => "monitor client node 1",
cmd => fun(#{node := Node} = _State) ->
@@ -33665,9 +33139,9 @@ sc_rc_receive_response_tcp(InitState) ->
{ok, State1}
end},
#{desc => "stop client node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -33690,14 +33164,14 @@ sc_rc_receive_response_tcp(InitState) ->
receive
{nodedown, Node} ->
?SEV_IPRINT("nodedown received - cleanup"),
- State1 = maps:remove(node_id, State),
- State2 = maps:remove(node, State1),
+ State1 = maps:remove(peer, State),
+ State2 = maps:remove(node, State1),
{ok, State2}
end;
(#{node_stop := error} = State) ->
?SEV_IPRINT("Failed node stop - cleanup"),
- State1 = maps:remove(node_id, State),
- State2 = maps:remove(node, State1),
+ State1 = maps:remove(peer, State),
+ State2 = maps:remove(node, State1),
{ok, State2}
end},
@@ -33989,7 +33463,7 @@ sc_rc_receive_response_tcp(InitState) ->
Tester = ?SEV_START("tester", TesterSeq, TesterInitState),
i("await evaluator"),
- ?line ok = ?SEV_AWAIT_FINISH([Server,
+ ok = ?SEV_AWAIT_FINISH([Server,
Client1, Client2, Client3,
Tester]).
@@ -34161,13 +33635,10 @@ sc_rc_tcp_handler_announce_ready(Parent, Slogan, Result) ->
%% remotely closed while the process is calling the recvmsg function.
%% Socket is IPv4.
-sc_rc_recvmsg_response_tcp4(suite) ->
- [];
-sc_rc_recvmsg_response_tcp4(doc) ->
- [];
sc_rc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rc_recvmsg_response_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
Recv = fun(Sock) -> socket:recvmsg(Sock) end,
InitState = #{domain => inet,
@@ -34182,10 +33653,6 @@ sc_rc_recvmsg_response_tcp4(_Config) when is_list(_Config) ->
%% remotely closed while the process is calling the recvmsg function.
%% Socket is IPv6.
-sc_rc_recvmsg_response_tcp6(suite) ->
- [];
-sc_rc_recvmsg_response_tcp6(doc) ->
- [];
sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rc_recvmsg_response_tcp6,
@@ -34204,10 +33671,6 @@ sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) ->
%% remotely closed while the process is calling the recvmsg function.
%% Socket is Unix Domain (stream) socket.
-sc_rc_recvmsg_response_tcpL(suite) ->
- [];
-sc_rc_recvmsg_response_tcpL(doc) ->
- [];
sc_rc_recvmsg_response_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rc_recvmsg_response_tcpL,
@@ -34234,13 +33697,10 @@ sc_rc_recvmsg_response_tcpL(_Config) when is_list(_Config) ->
%% This would of course not work for Unix Domain sockets.
%%
-sc_rs_recv_send_shutdown_receive_tcp4(suite) ->
- [];
-sc_rs_recv_send_shutdown_receive_tcp4(doc) ->
- [];
sc_rs_recv_send_shutdown_receive_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(sc_rs_recv_send_shutdown_receive_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
MsgData = ?DATA,
Recv = fun(Sock) ->
@@ -34265,10 +33725,6 @@ sc_rs_recv_send_shutdown_receive_tcp4(_Config) when is_list(_Config) ->
%% reader attempts a recv.
%% Socket is IPv6.
-sc_rs_recv_send_shutdown_receive_tcp6(suite) ->
- [];
-sc_rs_recv_send_shutdown_receive_tcp6(doc) ->
- [];
sc_rs_recv_send_shutdown_receive_tcp6(_Config) when is_list(_Config) ->
tc_try(sc_rs_recv_send_shutdown_receive_tcp6,
fun() -> has_support_ipv6() end,
@@ -34297,10 +33753,6 @@ sc_rs_recv_send_shutdown_receive_tcp6(_Config) when is_list(_Config) ->
%% reader attempts a recv.
%% Socket is Unix Domain (stream) socket.
-sc_rs_recv_send_shutdown_receive_tcpL(suite) ->
- [];
-sc_rs_recv_send_shutdown_receive_tcpL(doc) ->
- [];
sc_rs_recv_send_shutdown_receive_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_rs_recv_send_shutdown_receive_tcpL,
@@ -34539,15 +33991,9 @@ sc_rs_send_shutdown_receive_tcp(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- case start_node(Host, client) of
- {ok, Node} ->
- ?SEV_IPRINT("client node ~p started",
- [Node]),
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(State) ->
+ {Peer, Node} = ?START_NODE("client"),
+ {ok, State#{peer => Peer, node => Node}}
end},
#{desc => "monitor client node",
cmd => fun(#{node := Node} = _State) ->
@@ -34712,9 +34158,9 @@ sc_rs_send_shutdown_receive_tcp(InitState) ->
{ok, State1}
end},
#{desc => "stop client node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -34736,14 +34182,14 @@ sc_rs_send_shutdown_receive_tcp(InitState) ->
receive
{nodedown, Node} ->
?SEV_IPRINT("nodedown received - cleanup"),
- State1 = maps:remove(node_id, State),
- State2 = maps:remove(node, State1),
+ State1 = maps:remove(peer, State),
+ State2 = maps:remove(node, State1),
{ok, State2}
end;
(#{node_stop := error} = State) ->
?SEV_IPRINT("Failed node stop - cleanup"),
- State1 = maps:remove(node_id, State),
- State2 = maps:remove(node, State1),
+ State1 = maps:remove(peer, State),
+ State2 = maps:remove(node, State1),
{ok, State2}
end},
@@ -35106,7 +34552,7 @@ sc_rs_tcp_handler_await(Parent, Slogan) ->
?SEV_IPRINT("await ~w", [Slogan]),
?SEV_AWAIT_CONTINUE(Parent, parent, Slogan).
-%% This hould actually work - we leave it for now
+%% This should actually work - we leave it for now
sc_rs_tcp_handler_recv(Recv, Sock, First) ->
?SEV_IPRINT("recv"),
try Recv(Sock) of
@@ -35143,12 +34589,9 @@ sc_rs_tcp_handler_announce_ready(Parent, Slogan, Result) ->
%% reader attempts a recv.
%% Socket is IPv4.
-sc_rs_recvmsg_send_shutdown_receive_tcp4(suite) ->
- [];
-sc_rs_recvmsg_send_shutdown_receive_tcp4(doc) ->
- [];
sc_rs_recvmsg_send_shutdown_receive_tcp4(_Config) when is_list(_Config) ->
tc_try(sc_rs_recvmsg_send_shutdown_receive_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(30)),
MsgData = ?DATA,
@@ -35182,10 +34625,6 @@ sc_rs_recvmsg_send_shutdown_receive_tcp4(_Config) when is_list(_Config) ->
%% reader attempts a recv.
%% Socket is IPv6.
-sc_rs_recvmsg_send_shutdown_receive_tcp6(suite) ->
- [];
-sc_rs_recvmsg_send_shutdown_receive_tcp6(doc) ->
- [];
sc_rs_recvmsg_send_shutdown_receive_tcp6(_Config) when is_list(_Config) ->
tc_try(sc_rs_recvmsg_send_shutdown_receive_tcp6,
fun() -> has_support_ipv6() end,
@@ -35222,10 +34661,6 @@ sc_rs_recvmsg_send_shutdown_receive_tcp6(_Config) when is_list(_Config) ->
%% reader attempts a recv.
%% Socket is UNix Domain (stream) socket.
-sc_rs_recvmsg_send_shutdown_receive_tcpL(suite) ->
- [];
-sc_rs_recvmsg_send_shutdown_receive_tcpL(doc) ->
- [];
sc_rs_recvmsg_send_shutdown_receive_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(sc_rs_recvmsg_send_shutdown_receive_tcpL,
@@ -35271,10 +34706,6 @@ sc_rs_recvmsg_send_shutdown_receive_tcpL(_Config) when is_list(_Config) ->
%% This test case is intended to (simply) test "some" ioctl features.
%%
-ioctl_simple1(suite) ->
- [];
-ioctl_simple1(doc) ->
- [];
ioctl_simple1(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35357,10 +34788,6 @@ do_ioctl_simple(_State) ->
%% request(s).
%%
-ioctl_get_gifname(suite) ->
- [];
-ioctl_get_gifname(doc) ->
- [];
ioctl_get_gifname(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35410,10 +34837,6 @@ do_ioctl_get_gifname(_State) ->
%% --- gifindex ---
-ioctl_get_gifindex(suite) ->
- [];
-ioctl_get_gifindex(doc) ->
- [];
ioctl_get_gifindex(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35465,10 +34888,6 @@ do_ioctl_get_gifindex(_State) ->
%% --- gifaddr ---
-ioctl_get_gifaddr(suite) ->
- [];
-ioctl_get_gifaddr(doc) ->
- [];
ioctl_get_gifaddr(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35532,10 +34951,6 @@ do_ioctl_get_gifaddr(_State) ->
%% --- gifdstaddr ---
-ioctl_get_gifdstaddr(suite) ->
- [];
-ioctl_get_gifdstaddr(doc) ->
- [];
ioctl_get_gifdstaddr(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35550,17 +34965,17 @@ ioctl_get_gifdstaddr(_Config) when is_list(_Config) ->
do_ioctl_get_gifdstaddr(_State) ->
- Domain = inet,
+ Domain = inet_or_inet6(),
LSA = which_local_socket_addr(Domain),
i("create and init listen stream:TCP socket"),
- {ok, LSock} = socket:open(inet, stream, tcp),
+ {ok, LSock} = socket:open(Domain, stream, tcp),
ok = socket:bind(LSock, LSA#{port => 0}),
ok = socket:listen(LSock),
{ok, #{port := LPort}} = socket:sockname(LSock),
i("create and init connection stream:TCP socket"),
- {ok, CSock} = socket:open(inet, stream, tcp),
+ {ok, CSock} = socket:open(Domain, stream, tcp),
i("attempt connect (nowait)"),
{ok, ASock} =
@@ -35625,16 +35040,13 @@ verify_gifdstaddr(Sock, Prefix, IfIdx, IfName) ->
"~n ~p", [Prefix, IfName, IfIdx, Crap]),
socket:close(Sock),
?FAIL({unexpected_addr, Prefix, IfName, IfIdx, Crap});
- {error, eaddrnotavail = Reason} ->
+ {error, IgnoredReason} when IgnoredReason =:= eaddrnotavail;
+ IgnoredReason =:= eperm;
+ IgnoredReason =:= enotty ->
i("[~s] got unexpected error for interface ~p (~w) => "
"SKIP interface"
- "~n Reason: ~p", [Prefix, IfName, IfIdx, Reason]),
+ "~n Reason: ~p", [Prefix, IfName, IfIdx, IgnoredReason]),
ignore;
- {error, eperm = Reason} ->
- i("[~s] got unexpected error for interface ~p (~w) => "
- "SKIP interface"
- "~n Reason: ~p", [Prefix, IfName, IfIdx, Reason]),
- ignore;
{error, einval = Reason} when (OsFam =:= unix) andalso
((OsName =:= darwin) orelse
(OsName =:= freebsd) orelse
@@ -35656,10 +35068,6 @@ verify_gifdstaddr(Sock, Prefix, IfIdx, IfName) ->
%% --- gifbrdaddr ---
-ioctl_get_gifbrdaddr(suite) ->
- [];
-ioctl_get_gifbrdaddr(doc) ->
- [];
ioctl_get_gifbrdaddr(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35674,17 +35082,17 @@ ioctl_get_gifbrdaddr(_Config) when is_list(_Config) ->
do_ioctl_get_gifbrdaddr(_State) ->
- Domain = inet,
+ Domain = inet_or_inet6(),
LSA = which_local_socket_addr(Domain),
i("create and init listen stream:TCP socket"),
- {ok, LSock} = socket:open(inet, stream, tcp),
+ {ok, LSock} = socket:open(Domain, stream, tcp),
ok = socket:bind(LSock, LSA#{port => 0}),
ok = socket:listen(LSock),
{ok, #{port := LPort}} = socket:sockname(LSock),
i("create and init connection stream:TCP socket"),
- {ok, CSock} = socket:open(inet, stream, tcp),
+ {ok, CSock} = socket:open(Domain, stream, tcp),
i("attempt connect (nowait)"),
{ok, ASock} =
@@ -35748,16 +35156,13 @@ verify_gifbrdaddr(Sock, Prefix, IfIdx, IfName) ->
"~n ~p", [Prefix, IfName, IfIdx, Crap]),
socket:close(Sock),
?FAIL({unexpected_addr, IfName, IfIdx, Crap});
- {error, eaddrnotavail = Reason} ->
+ {error, IgnoredReason} when IgnoredReason =:= eaddrnotavail;
+ IgnoredReason =:= eperm;
+ IgnoredReason =:= enotty ->
i("[~s] got unexpected error for interface ~p (~w) => "
- "SKIP interface"
- "~n Reason: ~p", [Prefix, IfName, IfIdx, Reason]),
+ "SKIP interface"
+ "~n Reason: ~p", [Prefix, IfName, IfIdx, IgnoredReason]),
ignore;
- {error, eperm = Reason} ->
- i("[~s] got unexpected error for interface ~p (~w) => "
- "SKIP interface"
- "~n Reason: ~p", [Prefix, IfName, IfIdx, Reason]),
- ignore;
{error, einval = Reason} when (OsFam =:= unix) andalso
((OsName =:= darwin) orelse
(OsName =:= freebsd) orelse
@@ -35778,10 +35183,6 @@ verify_gifbrdaddr(Sock, Prefix, IfIdx, IfName) ->
%% --- gifnetmask ---
-ioctl_get_gifnetmask(suite) ->
- [];
-ioctl_get_gifnetmask(doc) ->
- [];
ioctl_get_gifnetmask(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35844,10 +35245,6 @@ do_ioctl_get_gifnetmask(_State) ->
%% --- gifmtu ---
-ioctl_get_gifmtu(suite) ->
- [];
-ioctl_get_gifmtu(doc) ->
- [];
ioctl_get_gifmtu(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35900,10 +35297,6 @@ do_ioctl_get_gifmtu(_State) ->
%% --- gifhwaddr ---
-ioctl_get_gifhwaddr(suite) ->
- [];
-ioctl_get_gifhwaddr(doc) ->
- [];
ioctl_get_gifhwaddr(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -35929,22 +35322,8 @@ do_ioctl_get_gifhwaddr(_State) ->
%% This a *very* simple test...
%% ...just to check that we actually get an socket address
_ = [case socket:ioctl(Sock, gifhwaddr, IfName) of
- {ok, #{family := ArphdrFam,
- addr := Addr}} when is_atom(ArphdrFam) ->
- case erlang:atom_to_list(ArphdrFam) of
- "arphrd_" ++ _ ->
- i("got (expected) (HW) socket address for "
- "interface ~p (~w): "
- "~n (~w) ~p", [IfName, IfIdx, ArphdrFam, Addr]),
- ok;
- _ ->
- i("<ERROR> got unexpected family for interface ~p (~w)"
- "~n ~p", [IfName, IfIdx, ArphdrFam]),
- socket:close(Sock),
- ?FAIL({unexpected_family, IfName, IfIdx, ArphdrFam})
- end;
{ok, #{family := Fam,
- addr := Addr}} when is_integer(Fam) ->
+ addr := Addr}} when is_atom(Fam) orelse is_integer(Fam) ->
i("got (expected) socket address for interface ~p (~w): "
"~n (~w) ~p", [IfName, IfIdx, Fam, Addr]),
ok;
@@ -35971,10 +35350,6 @@ do_ioctl_get_gifhwaddr(_State) ->
%% --- giftxqlen ---
-ioctl_get_giftxqlen(suite) ->
- [];
-ioctl_get_giftxqlen(doc) ->
- [];
ioctl_get_giftxqlen(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -36027,10 +35402,6 @@ do_ioctl_get_giftxqlen(_State) ->
%% --- gifflags ---
-ioctl_get_gifflags(suite) ->
- [];
-ioctl_get_gifflags(doc) ->
- [];
ioctl_get_gifflags(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -36099,10 +35470,6 @@ do_ioctl_get_gifflags(_State) ->
%% --- gifmap ---
-ioctl_get_gifmap(suite) ->
- [];
-ioctl_get_gifmap(doc) ->
- [];
ioctl_get_gifmap(_Config) when is_list(_Config) ->
?TT(?SECS(5)),
tc_try(?FUNCTION_NAME,
@@ -36160,13 +35527,10 @@ do_ioctl_get_gifmap(_State) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv4.
-traffic_send_and_recv_counters_tcp4(suite) ->
- [];
-traffic_send_and_recv_counters_tcp4(doc) ->
- [];
traffic_send_and_recv_counters_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_send_and_recv_counters_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
proto => tcp,
@@ -36182,10 +35546,6 @@ traffic_send_and_recv_counters_tcp4(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv6.
-traffic_send_and_recv_counters_tcp6(suite) ->
- [];
-traffic_send_and_recv_counters_tcp6(doc) ->
- [];
traffic_send_and_recv_counters_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_send_and_recv_counters_tcp6,
@@ -36205,10 +35565,6 @@ traffic_send_and_recv_counters_tcp6(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use default (TCP) on local.
-traffic_send_and_recv_counters_tcpL(suite) ->
- [];
-traffic_send_and_recv_counters_tcpL(doc) ->
- [];
traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_send_and_recv_counters_tcpL,
@@ -36228,13 +35584,10 @@ traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv4.
-traffic_sendmsg_and_recvmsg_counters_tcp4(suite) ->
- [];
-traffic_sendmsg_and_recvmsg_counters_tcp4(doc) ->
- [];
traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
proto => tcp,
@@ -36260,10 +35613,6 @@ traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use TCP on IPv6.
-traffic_sendmsg_and_recvmsg_counters_tcp6(suite) ->
- [];
-traffic_sendmsg_and_recvmsg_counters_tcp6(doc) ->
- [];
traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_tcp6,
@@ -36293,10 +35642,6 @@ traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use default (TCP) on local.
-traffic_sendmsg_and_recvmsg_counters_tcpL(suite) ->
- [];
-traffic_sendmsg_and_recvmsg_counters_tcpL(doc) ->
- [];
traffic_sendmsg_and_recvmsg_counters_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_tcpL,
@@ -37365,13 +36710,10 @@ traffic_sar_counters_validation2(Counters, [{Cnt, Val}|ValidateCounters]) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv4.
-traffic_sendto_and_recvfrom_counters_udp4(suite) ->
- [];
-traffic_sendto_and_recvfrom_counters_udp4(doc) ->
- [];
traffic_sendto_and_recvfrom_counters_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendto_and_recvfrom_counters_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
proto => udp,
@@ -37391,10 +36733,6 @@ traffic_sendto_and_recvfrom_counters_udp4(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv6.
-traffic_sendto_and_recvfrom_counters_udp6(suite) ->
- [];
-traffic_sendto_and_recvfrom_counters_udp6(doc) ->
- [];
traffic_sendto_and_recvfrom_counters_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendto_and_recvfrom_counters_udp6,
@@ -37418,10 +36756,6 @@ traffic_sendto_and_recvfrom_counters_udp6(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use default (UDP) on local.
-traffic_sendto_and_recvfrom_counters_udpL(suite) ->
- [];
-traffic_sendto_and_recvfrom_counters_udpL(doc) ->
- [];
traffic_sendto_and_recvfrom_counters_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendto_and_recvfrom_counters_udp4,
@@ -37445,13 +36779,10 @@ traffic_sendto_and_recvfrom_counters_udpL(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv4.
-traffic_sendmsg_and_recvmsg_counters_udp4(suite) ->
- [];
-traffic_sendmsg_and_recvmsg_counters_udp4(doc) ->
- [];
traffic_sendmsg_and_recvmsg_counters_udp4(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
proto => udp,
@@ -37479,10 +36810,6 @@ traffic_sendmsg_and_recvmsg_counters_udp4(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use UDP on IPv6.
-traffic_sendmsg_and_recvmsg_counters_udp6(suite) ->
- [];
-traffic_sendmsg_and_recvmsg_counters_udp6(doc) ->
- [];
traffic_sendmsg_and_recvmsg_counters_udp6(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_udp6,
@@ -37514,10 +36841,6 @@ traffic_sendmsg_and_recvmsg_counters_udp6(_Config) when is_list(_Config) ->
%% So that its easy to extend, we use fun's for read and write.
%% We use default (UDP) on local.
-traffic_sendmsg_and_recvmsg_counters_udpL(suite) ->
- [];
-traffic_sendmsg_and_recvmsg_counters_udpL(doc) ->
- [];
traffic_sendmsg_and_recvmsg_counters_udpL(_Config) when is_list(_Config) ->
?TT(?SECS(15)),
tc_try(traffic_sendmsg_and_recvmsg_counters_udpL,
@@ -38377,13 +37700,10 @@ traffic_send_and_recv_udp(InitState) ->
%% Second, send in a bunch of "small" chunks, and read in one "big" chunk.
%% Socket is IPv4.
-traffic_send_and_recv_chunks_tcp4(suite) ->
- [];
-traffic_send_and_recv_chunks_tcp4(doc) ->
- [];
traffic_send_and_recv_chunks_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(traffic_send_and_recv_chunks_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
proto => tcp},
@@ -38399,10 +37719,6 @@ traffic_send_and_recv_chunks_tcp4(_Config) when is_list(_Config) ->
%% Second, send in a bunch of "small" chunks, and read in one "big" chunk.
%% Socket is IPv6.
-traffic_send_and_recv_chunks_tcp6(suite) ->
- [];
-traffic_send_and_recv_chunks_tcp6(doc) ->
- [];
traffic_send_and_recv_chunks_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(traffic_send_and_recv_chunks_tcp6,
@@ -38421,10 +37737,6 @@ traffic_send_and_recv_chunks_tcp6(_Config) when is_list(_Config) ->
%% Second, send in a bunch of "small" chunks, and read in one "big" chunk.
%% Socket is UNix Domain (Stream) socket.
-traffic_send_and_recv_chunks_tcpL(suite) ->
- [];
-traffic_send_and_recv_chunks_tcpL(doc) ->
- [];
traffic_send_and_recv_chunks_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(30)),
tc_try(traffic_send_and_recv_chunks_tcp6,
@@ -38732,15 +38044,9 @@ traffic_send_and_recv_chunks_tcp(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- case start_node(Host, client) of
- {ok, Node} ->
- ?SEV_IPRINT("(remote) client node ~p started",
- [Node]),
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(State) ->
+ {Peer, Node} = ?START_NODE("client"),
+ {ok, State#{peer => Peer, node => Node}}
end},
#{desc => "monitor client node",
cmd => fun(#{node := Node} = _State) ->
@@ -39104,9 +38410,9 @@ traffic_send_and_recv_chunks_tcp(InitState) ->
{ok, State1}
end},
#{desc => "stop client node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -39352,7 +38658,7 @@ traffic_snr_tcp_client(Parent) ->
traffic_snr_tcp_client_send_loop(Parent, Sock) ->
case ?SEV_AWAIT_CONTINUE(Parent, parent, send) of
- {ok, stop} -> % Breakes the loop
+ {ok, stop} -> % Breaks the loop
?SEV_ANNOUNCE_READY(Parent, send, ok),
ok;
{ok, Data} ->
@@ -39457,15 +38763,12 @@ traffic_snr_tcp_client_await_terminate(Parent) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.
-traffic_ping_pong_small_send_and_recv_tcp4(suite) ->
- [];
-traffic_ping_pong_small_send_and_recv_tcp4(doc) ->
- [];
traffic_ping_pong_small_send_and_recv_tcp4(Config) when is_list(Config) ->
?TT(?SECS(15)),
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
tc_try(traffic_ping_pong_small_send_and_recv_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
proto => tcp,
@@ -39485,10 +38788,6 @@ traffic_ping_pong_small_send_and_recv_tcp4(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.
-traffic_ping_pong_small_send_and_recv_tcp6(suite) ->
- [];
-traffic_ping_pong_small_send_and_recv_tcp6(doc) ->
- [];
traffic_ping_pong_small_send_and_recv_tcp6(Config) when is_list(Config) ->
?TT(?SECS(15)),
Msg = l2b(?TPP_SMALL),
@@ -39513,10 +38812,6 @@ traffic_ping_pong_small_send_and_recv_tcp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (stream) socket.
-traffic_ping_pong_small_send_and_recv_tcpL(suite) ->
- [];
-traffic_ping_pong_small_send_and_recv_tcpL(doc) ->
- [];
traffic_ping_pong_small_send_and_recv_tcpL(Config) when is_list(Config) ->
?TT(?SECS(15)),
Msg = l2b(?TPP_SMALL),
@@ -39541,14 +38836,11 @@ traffic_ping_pong_small_send_and_recv_tcpL(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.
-traffic_ping_pong_medium_send_and_recv_tcp4(suite) ->
- [];
-traffic_ping_pong_medium_send_and_recv_tcp4(doc) ->
- [];
traffic_ping_pong_medium_send_and_recv_tcp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
tc_try(traffic_ping_pong_medium_send_and_recv_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(30)),
InitState = #{domain => inet,
@@ -39568,10 +38860,6 @@ traffic_ping_pong_medium_send_and_recv_tcp4(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.
-traffic_ping_pong_medium_send_and_recv_tcp6(suite) ->
- [];
-traffic_ping_pong_medium_send_and_recv_tcp6(doc) ->
- [];
traffic_ping_pong_medium_send_and_recv_tcp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -39597,10 +38885,6 @@ traffic_ping_pong_medium_send_and_recv_tcp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (stream) socket.
-traffic_ping_pong_medium_send_and_recv_tcpL(suite) ->
- [];
-traffic_ping_pong_medium_send_and_recv_tcpL(doc) ->
- [];
traffic_ping_pong_medium_send_and_recv_tcpL(Config) when is_list(Config) ->
?TT(?SECS(30)),
Msg = l2b(?TPP_MEDIUM),
@@ -39626,16 +38910,13 @@ traffic_ping_pong_medium_send_and_recv_tcpL(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv4.
-traffic_ping_pong_large_send_and_recv_tcp4(suite) ->
- [];
-traffic_ping_pong_large_send_and_recv_tcp4(doc) ->
- [];
traffic_ping_pong_large_send_and_recv_tcp4(Config) when is_list(Config) ->
?TT(?SECS(60)),
Msg = l2b(?TPP_LARGE),
Num = ?TPP_NUM(Config, ?TPP_LARGE_NUM),
tc_try(traffic_ping_pong_large_send_and_recv_tcp4,
- fun() -> is_old_fedora16(),
+ fun() -> has_support_ipv4(),
+ is_old_fedora16(),
is_slow_ubuntu(Config) end,
fun() ->
InitState = #{domain => inet,
@@ -39655,10 +38936,6 @@ traffic_ping_pong_large_send_and_recv_tcp4(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv6.
-traffic_ping_pong_large_send_and_recv_tcp6(suite) ->
- [];
-traffic_ping_pong_large_send_and_recv_tcp6(doc) ->
- [];
traffic_ping_pong_large_send_and_recv_tcp6(Config) when is_list(Config) ->
?TT(?SECS(60)),
Msg = l2b(?TPP_LARGE),
@@ -39686,10 +38963,6 @@ traffic_ping_pong_large_send_and_recv_tcp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for UNix Domain (stream) socket.
-traffic_ping_pong_large_send_and_recv_tcpL(suite) ->
- [];
-traffic_ping_pong_large_send_and_recv_tcpL(doc) ->
- [];
traffic_ping_pong_large_send_and_recv_tcpL(Config) when is_list(Config) ->
?TT(?SECS(60)),
Msg = l2b(?TPP_LARGE),
@@ -39747,7 +39020,7 @@ is_old_fedora16(_) ->
%% not actually needed.
%% The host in question is a Ubuntu 20.04...
is_slow_ubuntu(Config) ->
- case lookup(esock_factor, 1, Config) of
+ case lookup(kernel_factor, 1, Config) of
F when is_integer(F) andalso (F > 1) ->
case os:type() of
{unix, linux} ->
@@ -39774,14 +39047,11 @@ is_slow_ubuntu(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.
-traffic_ping_pong_small_sendto_and_recvfrom_udp4(suite) ->
- [];
-traffic_ping_pong_small_sendto_and_recvfrom_udp4(doc) ->
- [];
traffic_ping_pong_small_sendto_and_recvfrom_udp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(45)),
InitState = #{domain => inet,
@@ -39801,10 +39071,6 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp4(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.
-traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) ->
- [];
-traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) ->
- [];
traffic_ping_pong_small_sendto_and_recvfrom_udp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
@@ -39830,10 +39096,6 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (dgram) socket.
-traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) ->
- [];
-traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) ->
- [];
traffic_ping_pong_small_sendto_and_recvfrom_udpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
@@ -39859,14 +39121,11 @@ traffic_ping_pong_small_sendto_and_recvfrom_udpL(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.
-traffic_ping_pong_medium_sendto_and_recvfrom_udp4(suite) ->
- [];
-traffic_ping_pong_medium_sendto_and_recvfrom_udp4(doc) ->
- [];
traffic_ping_pong_medium_sendto_and_recvfrom_udp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(45)),
InitState = #{domain => inet,
@@ -39886,10 +39145,6 @@ traffic_ping_pong_medium_sendto_and_recvfrom_udp4(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.
-traffic_ping_pong_medium_sendto_and_recvfrom_udp6(suite) ->
- [];
-traffic_ping_pong_medium_sendto_and_recvfrom_udp6(doc) ->
- [];
traffic_ping_pong_medium_sendto_and_recvfrom_udp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -39915,10 +39170,6 @@ traffic_ping_pong_medium_sendto_and_recvfrom_udp6(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (dgram) socket.
-traffic_ping_pong_medium_sendto_and_recvfrom_udpL(suite) ->
- [];
-traffic_ping_pong_medium_sendto_and_recvfrom_udpL(doc) ->
- [];
traffic_ping_pong_medium_sendto_and_recvfrom_udpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -39944,14 +39195,11 @@ traffic_ping_pong_medium_sendto_and_recvfrom_udpL(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.
-traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(suite) ->
- [];
-traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(doc) ->
- [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(20)),
InitState = #{domain => inet,
@@ -39971,10 +39219,6 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.
-traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(suite) ->
- [];
-traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(doc) ->
- [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
@@ -39999,10 +39243,6 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (stream) socket.
-traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(suite) ->
- [];
-traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(doc) ->
- [];
traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
@@ -40027,14 +39267,11 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.
-traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(suite) ->
- [];
-traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(doc) ->
- [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(30)),
InitState = #{domain => inet,
@@ -40054,10 +39291,6 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.
-traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(suite) ->
- [];
-traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(doc) ->
- [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -40082,10 +39315,6 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (stream) socket.
-traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(suite) ->
- [];
-traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(doc) ->
- [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -40110,15 +39339,11 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv4.
-traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(suite) ->
- [];
-traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(doc) ->
- [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_LARGE),
Num = ?TPP_NUM(Config, ?TPP_LARGE_NUM),
tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4,
- fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end,
+ fun() -> has_support_ipv4(), traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end,
fun() ->
?TT(?SECS(60)),
InitState = #{domain => inet,
@@ -40148,10 +39373,6 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_cond(_, _) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for IPv6.
-traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(suite) ->
- [];
-traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(doc) ->
- [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_LARGE),
Num = ?TPP_NUM(Config, ?TPP_LARGE_NUM),
@@ -40180,10 +39401,6 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'large' message test case, for Unix Domain (stream) socket.
-traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(suite) ->
- [];
-traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(doc) ->
- [];
traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_LARGE),
Num = ?TPP_NUM(Config, ?TPP_LARGE_NUM),
@@ -40209,14 +39426,11 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv4.
-traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(suite) ->
- [];
-traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(doc) ->
- [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(60)),
InitState = #{domain => inet,
@@ -40236,10 +39450,6 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for IPv6.
-traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(suite) ->
- [];
-traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(doc) ->
- [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
@@ -40264,10 +39474,6 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'small' message test case, for Unix Domain (dgram) socket.
-traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(suite) ->
- [];
-traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(doc) ->
- [];
traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_SMALL),
Num = ?TPP_NUM(Config, ?TPP_SMALL_NUM),
@@ -40292,14 +39498,11 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(Config) when is_list(Config) ->
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv4.
-traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(suite) ->
- [];
-traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(doc) ->
- [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4,
+ fun() -> has_support_ipv4() end,
fun() ->
?TT(?SECS(60)),
InitState = #{domain => inet,
@@ -40319,10 +39522,6 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for IPv6.
-traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(suite) ->
- [];
-traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(doc) ->
- [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -40348,10 +39547,6 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(Config) when is_list(Config) -
%% repeated a set number of times (more times the small the message).
%% This is the 'medium' message test case, for Unix Domain (dgram) socket.
-traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(suite) ->
- [];
-traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(doc) ->
- [];
traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(Config) when is_list(Config) ->
Msg = l2b(?TPP_MEDIUM),
Num = ?TPP_NUM(Config, ?TPP_MEDIUM_NUM),
@@ -40431,7 +39626,7 @@ traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState) ->
traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) ->
Fun = fun(Sock) ->
{ok, RcvSz} = socket:getopt(Sock, socket, rcvbuf),
- ?SEV_IPRINT("RcvBuf is ~p (needs atleast ~p)",
+ ?SEV_IPRINT("RcvBuf is ~p (needs at least ~p)",
[RcvSz, 16+size(Msg)]),
if (RcvSz < size(Msg)) ->
NewRcvSz = 1024+size(Msg),
@@ -40449,7 +39644,7 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) ->
ok
end,
{ok, SndSz} = socket:getopt(Sock, socket, sndbuf),
- ?SEV_IPRINT("SndBuf is ~p (needs atleast ~p)",
+ ?SEV_IPRINT("SndBuf is ~p (needs at least ~p)",
[SndSz, 16+size(Msg)]),
if (SndSz < size(Msg)) ->
NewSndSz = 1024+size(Msg),
@@ -40681,15 +39876,9 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- case start_node(Host, client) of
- {ok, Node} ->
- ?SEV_IPRINT("(remote) client node ~p started",
- [Node]),
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(State) ->
+ {Peer, Node} = ?START_NODE("client"),
+ {ok, State#{peer => Peer, node => Node}}
end},
#{desc => "monitor client node",
cmd => fun(#{node := Node} = _State) ->
@@ -40834,9 +40023,9 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) ->
{ok, State1}
end},
#{desc => "stop client node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -40991,7 +40180,7 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) ->
CTime = tdiff(CStart, CStop),
%% Note that the sizes we are counting is only
%% the "data" part of the messages. There is also
- %% fixed header for each message, which of cource
+ %% fixed header for each message, which of course
%% is small for the large messages, but comparatively
%% big for the small messages!
?SEV_IPRINT("Results: ~w messages exchanged"
@@ -41674,15 +40863,9 @@ traffic_ping_pong_send_and_receive_udp2(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- case start_node(Host, client) of
- {ok, Node} ->
- ?SEV_IPRINT("(remote) client node ~p started",
- [Node]),
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(State) ->
+ {Peer, Node} = ?START_NODE("client"),
+ {ok, State#{peer => Peer, node => Node}}
end},
#{desc => "monitor client node",
cmd => fun(#{node := Node} = _State) ->
@@ -41783,9 +40966,9 @@ traffic_ping_pong_send_and_receive_udp2(InitState) ->
{ok, State1}
end},
#{desc => "stop client node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -41917,7 +41100,7 @@ traffic_ping_pong_send_and_receive_udp2(InitState) ->
CTime = tdiff(CStart, CStop),
%% Note that the sizes we are counting is only
%% the "data" part of the messages. There is also
- %% fixed header for each message, which of cource
+ %% fixed header for each message, which of course
%% is small for the large messages, but comparatively
%% big for the small messages!
?SEV_IPRINT("Results: ~w messages exchanged"
@@ -42194,7 +41377,7 @@ tpp_udp_recv(Sock, Recv, Tag) ->
ERROR
catch
C:E:S ->
- {error, {catched, C, E, S}}
+ {error, {caught, C, E, S}}
end.
tpp_udp_send_req(Sock, Send, Data, Dest) ->
@@ -42306,18 +41489,14 @@ tpp_udp_sock_close(Sock, Path) ->
%% Domain: inet
%%
-ttest_sgenf_cgenf_small_tcp4(suite) ->
- [];
-ttest_sgenf_cgenf_small_tcp4(doc) ->
- [];
ttest_sgenf_cgenf_small_tcp4(Config) when is_list(Config) ->
- Runtime = which_ttest_runtime(Config),
+ Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgenf_small_tcp4,
Runtime,
inet,
gen, false,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42330,10 +41509,6 @@ ttest_sgenf_cgenf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgenf_small_tcp6(suite) ->
- [];
-ttest_sgenf_cgenf_small_tcp6(doc) ->
- [];
ttest_sgenf_cgenf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgenf_small_tcp6,
@@ -42341,7 +41516,7 @@ ttest_sgenf_cgenf_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42354,10 +41529,6 @@ ttest_sgenf_cgenf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgenf_medium_tcp4(suite) ->
- [];
-ttest_sgenf_cgenf_medium_tcp4(doc) ->
- [];
ttest_sgenf_cgenf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgenf_medium_tcp4,
@@ -42365,7 +41536,7 @@ ttest_sgenf_cgenf_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42378,10 +41549,6 @@ ttest_sgenf_cgenf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgenf_medium_tcp6(suite) ->
- [];
-ttest_sgenf_cgenf_medium_tcp6(doc) ->
- [];
ttest_sgenf_cgenf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgenf_medium_tcp6,
@@ -42389,7 +41556,7 @@ ttest_sgenf_cgenf_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42402,10 +41569,6 @@ ttest_sgenf_cgenf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgenf_large_tcp4(suite) ->
- [];
-ttest_sgenf_cgenf_large_tcp4(doc) ->
- [];
ttest_sgenf_cgenf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgenf_large_tcp4,
@@ -42413,7 +41576,7 @@ ttest_sgenf_cgenf_large_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42426,10 +41589,6 @@ ttest_sgenf_cgenf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgenf_large_tcp6(suite) ->
- [];
-ttest_sgenf_cgenf_large_tcp6(doc) ->
- [];
ttest_sgenf_cgenf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgenf_large_tcp6,
@@ -42437,7 +41596,7 @@ ttest_sgenf_cgenf_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42450,10 +41609,6 @@ ttest_sgenf_cgenf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgeno_small_tcp4(suite) ->
- [];
-ttest_sgenf_cgeno_small_tcp4(doc) ->
- [];
ttest_sgenf_cgeno_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_small_tcp4,
@@ -42461,7 +41616,7 @@ ttest_sgenf_cgeno_small_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42474,10 +41629,6 @@ ttest_sgenf_cgeno_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgeno_small_tcp6(suite) ->
- [];
-ttest_sgenf_cgeno_small_tcp6(doc) ->
- [];
ttest_sgenf_cgeno_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_small_tcp6,
@@ -42485,7 +41636,7 @@ ttest_sgenf_cgeno_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42498,10 +41649,6 @@ ttest_sgenf_cgeno_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgeno_medium_tcp4(suite) ->
- [];
-ttest_sgenf_cgeno_medium_tcp4(doc) ->
- [];
ttest_sgenf_cgeno_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_medium_tcp4,
@@ -42509,7 +41656,7 @@ ttest_sgenf_cgeno_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42522,10 +41669,6 @@ ttest_sgenf_cgeno_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgeno_medium_tcp6(suite) ->
- [];
-ttest_sgenf_cgeno_medium_tcp6(doc) ->
- [];
ttest_sgenf_cgeno_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_medium_tcp6,
@@ -42533,7 +41676,7 @@ ttest_sgenf_cgeno_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42546,10 +41689,6 @@ ttest_sgenf_cgeno_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgeno_large_tcp4(suite) ->
- [];
-ttest_sgenf_cgeno_large_tcp4(doc) ->
- [];
ttest_sgenf_cgeno_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_large_tcp4,
@@ -42557,7 +41696,7 @@ ttest_sgenf_cgeno_large_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42570,10 +41709,6 @@ ttest_sgenf_cgeno_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgeno_large_tcp6(suite) ->
- [];
-ttest_sgenf_cgeno_large_tcp6(doc) ->
- [];
ttest_sgenf_cgeno_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_large_tcp6,
@@ -42581,7 +41716,7 @@ ttest_sgenf_cgeno_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42594,10 +41729,6 @@ ttest_sgenf_cgeno_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgent_small_tcp4(suite) ->
- [];
-ttest_sgenf_cgent_small_tcp4(doc) ->
- [];
ttest_sgenf_cgent_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgent_small_tcp4,
@@ -42605,7 +41736,7 @@ ttest_sgenf_cgent_small_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42618,10 +41749,6 @@ ttest_sgenf_cgent_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgent_small_tcp6(suite) ->
- [];
-ttest_sgenf_cgent_small_tcp6(doc) ->
- [];
ttest_sgenf_cgent_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgeno_small_tcp6,
@@ -42629,7 +41756,7 @@ ttest_sgenf_cgent_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42642,10 +41769,6 @@ ttest_sgenf_cgent_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgent_medium_tcp4(suite) ->
- [];
-ttest_sgenf_cgent_medium_tcp4(doc) ->
- [];
ttest_sgenf_cgent_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgent_medium_tcp4,
@@ -42653,7 +41776,7 @@ ttest_sgenf_cgent_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42666,10 +41789,6 @@ ttest_sgenf_cgent_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgent_medium_tcp6(suite) ->
- [];
-ttest_sgenf_cgent_medium_tcp6(doc) ->
- [];
ttest_sgenf_cgent_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgent_medium_tcp6,
@@ -42677,7 +41796,7 @@ ttest_sgenf_cgent_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42690,10 +41809,6 @@ ttest_sgenf_cgent_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_cgent_large_tcp4(suite) ->
- [];
-ttest_sgenf_cgent_large_tcp4(doc) ->
- [];
ttest_sgenf_cgent_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgent_large_tcp4,
@@ -42701,7 +41816,7 @@ ttest_sgenf_cgent_large_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42714,10 +41829,6 @@ ttest_sgenf_cgent_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_cgent_large_tcp6(suite) ->
- [];
-ttest_sgenf_cgent_large_tcp6(doc) ->
- [];
ttest_sgenf_cgent_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_cgent_large_tcp6,
@@ -42725,7 +41836,7 @@ ttest_sgenf_cgent_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42738,10 +41849,6 @@ ttest_sgenf_cgent_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csockf_small_tcp4(suite) ->
- [];
-ttest_sgenf_csockf_small_tcp4(doc) ->
- [];
ttest_sgenf_csockf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockf_small_tcp4,
@@ -42749,7 +41856,7 @@ ttest_sgenf_csockf_small_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42762,10 +41869,6 @@ ttest_sgenf_csockf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csockf_small_tcp6(suite) ->
- [];
-ttest_sgenf_csockf_small_tcp6(doc) ->
- [];
ttest_sgenf_csockf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockf_small_tcp6,
@@ -42773,7 +41876,7 @@ ttest_sgenf_csockf_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42786,10 +41889,6 @@ ttest_sgenf_csockf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csockf_medium_tcp4(suite) ->
- [];
-ttest_sgenf_csockf_medium_tcp4(doc) ->
- [];
ttest_sgenf_csockf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockf_medium_tcp4,
@@ -42797,7 +41896,7 @@ ttest_sgenf_csockf_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42810,10 +41909,6 @@ ttest_sgenf_csockf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csockf_medium_tcp6(suite) ->
- [];
-ttest_sgenf_csockf_medium_tcp6(doc) ->
- [];
ttest_sgenf_csockf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockf_medium_tcp6,
@@ -42821,7 +41916,7 @@ ttest_sgenf_csockf_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42834,10 +41929,6 @@ ttest_sgenf_csockf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csockf_large_tcp4(suite) ->
- [];
-ttest_sgenf_csockf_large_tcp4(doc) ->
- [];
ttest_sgenf_csockf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockf_large_tcp4,
@@ -42845,7 +41936,7 @@ ttest_sgenf_csockf_large_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42858,10 +41949,6 @@ ttest_sgenf_csockf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csockf_large_tcp6(suite) ->
- [];
-ttest_sgenf_csockf_large_tcp6(doc) ->
- [];
ttest_sgenf_csockf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockf_large_tcp6,
@@ -42869,7 +41956,7 @@ ttest_sgenf_csockf_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -42882,10 +41969,6 @@ ttest_sgenf_csockf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csocko_small_tcp4(suite) ->
- [];
-ttest_sgenf_csocko_small_tcp4(doc) ->
- [];
ttest_sgenf_csocko_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_small_tcp4,
@@ -42893,7 +41976,7 @@ ttest_sgenf_csocko_small_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42906,10 +41989,6 @@ ttest_sgenf_csocko_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csocko_small_tcp6(suite) ->
- [];
-ttest_sgenf_csocko_small_tcp6(doc) ->
- [];
ttest_sgenf_csocko_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_small_tcp6,
@@ -42917,7 +41996,7 @@ ttest_sgenf_csocko_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -42930,10 +42009,6 @@ ttest_sgenf_csocko_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csocko_medium_tcp4(suite) ->
- [];
-ttest_sgenf_csocko_medium_tcp4(doc) ->
- [];
ttest_sgenf_csocko_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_medium_tcp4,
@@ -42941,7 +42016,7 @@ ttest_sgenf_csocko_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42954,10 +42029,6 @@ ttest_sgenf_csocko_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csocko_medium_tcp6(suite) ->
- [];
-ttest_sgenf_csocko_medium_tcp6(doc) ->
- [];
ttest_sgenf_csocko_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_medium_tcp6,
@@ -42965,7 +42036,7 @@ ttest_sgenf_csocko_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -42978,10 +42049,6 @@ ttest_sgenf_csocko_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csocko_large_tcp4(suite) ->
- [];
-ttest_sgenf_csocko_large_tcp4(doc) ->
- [];
ttest_sgenf_csocko_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_large_tcp4,
@@ -42989,7 +42056,7 @@ ttest_sgenf_csocko_large_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43002,10 +42069,6 @@ ttest_sgenf_csocko_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csocko_large_tcp6(suite) ->
- [];
-ttest_sgenf_csocko_large_tcp6(doc) ->
- [];
ttest_sgenf_csocko_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_large_tcp6,
@@ -43013,7 +42076,7 @@ ttest_sgenf_csocko_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43026,10 +42089,6 @@ ttest_sgenf_csocko_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csockt_small_tcp4(suite) ->
- [];
-ttest_sgenf_csockt_small_tcp4(doc) ->
- [];
ttest_sgenf_csockt_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockt_small_tcp4,
@@ -43037,7 +42096,7 @@ ttest_sgenf_csockt_small_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43050,10 +42109,6 @@ ttest_sgenf_csockt_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csockt_small_tcp6(suite) ->
- [];
-ttest_sgenf_csockt_small_tcp6(doc) ->
- [];
ttest_sgenf_csockt_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csocko_small_tcp6,
@@ -43061,7 +42116,7 @@ ttest_sgenf_csockt_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43074,10 +42129,6 @@ ttest_sgenf_csockt_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csockt_medium_tcp4(suite) ->
- [];
-ttest_sgenf_csockt_medium_tcp4(doc) ->
- [];
ttest_sgenf_csockt_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockt_medium_tcp4,
@@ -43085,7 +42136,7 @@ ttest_sgenf_csockt_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43098,10 +42149,6 @@ ttest_sgenf_csockt_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csockt_medium_tcp6(suite) ->
- [];
-ttest_sgenf_csockt_medium_tcp6(doc) ->
- [];
ttest_sgenf_csockt_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockt_medium_tcp6,
@@ -43109,7 +42156,7 @@ ttest_sgenf_csockt_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43122,10 +42169,6 @@ ttest_sgenf_csockt_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgenf_csockt_large_tcp4(suite) ->
- [];
-ttest_sgenf_csockt_large_tcp4(doc) ->
- [];
ttest_sgenf_csockt_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockt_large_tcp4,
@@ -43133,7 +42176,7 @@ ttest_sgenf_csockt_large_tcp4(Config) when is_list(Config) ->
inet,
gen, false,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43146,10 +42189,6 @@ ttest_sgenf_csockt_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgenf_csockt_large_tcp6(suite) ->
- [];
-ttest_sgenf_csockt_large_tcp6(doc) ->
- [];
ttest_sgenf_csockt_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgenf_csockt_large_tcp6,
@@ -43157,7 +42196,7 @@ ttest_sgenf_csockt_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, false,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43170,10 +42209,6 @@ ttest_sgenf_csockt_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgenf_small_tcp4(suite) ->
- [];
-ttest_sgeno_cgenf_small_tcp4(doc) ->
- [];
ttest_sgeno_cgenf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgenf_small_tcp4,
@@ -43181,7 +42216,7 @@ ttest_sgeno_cgenf_small_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43194,10 +42229,6 @@ ttest_sgeno_cgenf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgenf_small_tcp6(suite) ->
- [];
-ttest_sgeno_cgenf_small_tcp6(doc) ->
- [];
ttest_sgeno_cgenf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgenf_small_tcp6,
@@ -43205,7 +42236,7 @@ ttest_sgeno_cgenf_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43218,10 +42249,6 @@ ttest_sgeno_cgenf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgenf_medium_tcp4(suite) ->
- [];
-ttest_sgeno_cgenf_medium_tcp4(doc) ->
- [];
ttest_sgeno_cgenf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgenf_medium_tcp4,
@@ -43229,7 +42256,7 @@ ttest_sgeno_cgenf_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43242,10 +42269,6 @@ ttest_sgeno_cgenf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgenf_medium_tcp6(suite) ->
- [];
-ttest_sgeno_cgenf_medium_tcp6(doc) ->
- [];
ttest_sgeno_cgenf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgenf_medium_tcp6,
@@ -43253,7 +42276,7 @@ ttest_sgeno_cgenf_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43266,10 +42289,6 @@ ttest_sgeno_cgenf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgenf_large_tcp4(suite) ->
- [];
-ttest_sgeno_cgenf_large_tcp4(doc) ->
- [];
ttest_sgeno_cgenf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgenf_large_tcp4,
@@ -43277,7 +42296,7 @@ ttest_sgeno_cgenf_large_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43290,10 +42309,6 @@ ttest_sgeno_cgenf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgenf_large_tcp6(suite) ->
- [];
-ttest_sgeno_cgenf_large_tcp6(doc) ->
- [];
ttest_sgeno_cgenf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgenf_large_tcp6,
@@ -43301,7 +42316,7 @@ ttest_sgeno_cgenf_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43314,10 +42329,6 @@ ttest_sgeno_cgenf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgeno_small_tcp4(suite) ->
- [];
-ttest_sgeno_cgeno_small_tcp4(doc) ->
- [];
ttest_sgeno_cgeno_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_small_tcp4,
@@ -43325,7 +42336,7 @@ ttest_sgeno_cgeno_small_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43338,10 +42349,6 @@ ttest_sgeno_cgeno_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgeno_small_tcp6(suite) ->
- [];
-ttest_sgeno_cgeno_small_tcp6(doc) ->
- [];
ttest_sgeno_cgeno_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_small_tcp6,
@@ -43349,7 +42356,7 @@ ttest_sgeno_cgeno_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43362,10 +42369,6 @@ ttest_sgeno_cgeno_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgeno_medium_tcp4(suite) ->
- [];
-ttest_sgeno_cgeno_medium_tcp4(doc) ->
- [];
ttest_sgeno_cgeno_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_medium_tcp4,
@@ -43373,7 +42376,7 @@ ttest_sgeno_cgeno_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43386,10 +42389,6 @@ ttest_sgeno_cgeno_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgeno_medium_tcp6(suite) ->
- [];
-ttest_sgeno_cgeno_medium_tcp6(doc) ->
- [];
ttest_sgeno_cgeno_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_medium_tcp6,
@@ -43397,7 +42396,7 @@ ttest_sgeno_cgeno_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43410,10 +42409,6 @@ ttest_sgeno_cgeno_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgeno_large_tcp4(suite) ->
- [];
-ttest_sgeno_cgeno_large_tcp4(doc) ->
- [];
ttest_sgeno_cgeno_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_large_tcp4,
@@ -43421,7 +42416,7 @@ ttest_sgeno_cgeno_large_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43434,10 +42429,6 @@ ttest_sgeno_cgeno_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgeno_large_tcp6(suite) ->
- [];
-ttest_sgeno_cgeno_large_tcp6(doc) ->
- [];
ttest_sgeno_cgeno_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_large_tcp6,
@@ -43445,7 +42436,7 @@ ttest_sgeno_cgeno_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43458,10 +42449,6 @@ ttest_sgeno_cgeno_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgent_small_tcp4(suite) ->
- [];
-ttest_sgeno_cgent_small_tcp4(doc) ->
- [];
ttest_sgeno_cgent_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgent_small_tcp4,
@@ -43469,7 +42456,7 @@ ttest_sgeno_cgent_small_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43482,10 +42469,6 @@ ttest_sgeno_cgent_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgent_small_tcp6(suite) ->
- [];
-ttest_sgeno_cgent_small_tcp6(doc) ->
- [];
ttest_sgeno_cgent_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgeno_small_tcp6,
@@ -43493,7 +42476,7 @@ ttest_sgeno_cgent_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43506,10 +42489,6 @@ ttest_sgeno_cgent_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgent_medium_tcp4(suite) ->
- [];
-ttest_sgeno_cgent_medium_tcp4(doc) ->
- [];
ttest_sgeno_cgent_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgent_medium_tcp4,
@@ -43517,7 +42496,7 @@ ttest_sgeno_cgent_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43530,10 +42509,6 @@ ttest_sgeno_cgent_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgent_medium_tcp6(suite) ->
- [];
-ttest_sgeno_cgent_medium_tcp6(doc) ->
- [];
ttest_sgeno_cgent_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgent_medium_tcp6,
@@ -43541,7 +42516,7 @@ ttest_sgeno_cgent_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43554,10 +42529,6 @@ ttest_sgeno_cgent_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_cgent_large_tcp4(suite) ->
- [];
-ttest_sgeno_cgent_large_tcp4(doc) ->
- [];
ttest_sgeno_cgent_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgent_large_tcp4,
@@ -43565,7 +42536,7 @@ ttest_sgeno_cgent_large_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43578,10 +42549,6 @@ ttest_sgeno_cgent_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_cgent_large_tcp6(suite) ->
- [];
-ttest_sgeno_cgent_large_tcp6(doc) ->
- [];
ttest_sgeno_cgent_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_cgent_large_tcp6,
@@ -43589,7 +42556,7 @@ ttest_sgeno_cgent_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43602,10 +42569,6 @@ ttest_sgeno_cgent_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csockf_small_tcp4(suite) ->
- [];
-ttest_sgeno_csockf_small_tcp4(doc) ->
- [];
ttest_sgeno_csockf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockf_small_tcp4,
@@ -43613,7 +42576,7 @@ ttest_sgeno_csockf_small_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43626,10 +42589,6 @@ ttest_sgeno_csockf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csockf_small_tcp6(suite) ->
- [];
-ttest_sgeno_csockf_small_tcp6(doc) ->
- [];
ttest_sgeno_csockf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockf_small_tcp6,
@@ -43637,7 +42596,7 @@ ttest_sgeno_csockf_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43650,10 +42609,6 @@ ttest_sgeno_csockf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csockf_medium_tcp4(suite) ->
- [];
-ttest_sgeno_csockf_medium_tcp4(doc) ->
- [];
ttest_sgeno_csockf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockf_medium_tcp4,
@@ -43661,7 +42616,7 @@ ttest_sgeno_csockf_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43674,10 +42629,6 @@ ttest_sgeno_csockf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csockf_medium_tcp6(suite) ->
- [];
-ttest_sgeno_csockf_medium_tcp6(doc) ->
- [];
ttest_sgeno_csockf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockf_medium_tcp6,
@@ -43685,7 +42636,7 @@ ttest_sgeno_csockf_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43698,10 +42649,6 @@ ttest_sgeno_csockf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csockf_large_tcp4(suite) ->
- [];
-ttest_sgeno_csockf_large_tcp4(doc) ->
- [];
ttest_sgeno_csockf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockf_large_tcp4,
@@ -43709,7 +42656,7 @@ ttest_sgeno_csockf_large_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43722,10 +42669,6 @@ ttest_sgeno_csockf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csockf_large_tcp6(suite) ->
- [];
-ttest_sgeno_csockf_large_tcp6(doc) ->
- [];
ttest_sgeno_csockf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockf_large_tcp6,
@@ -43733,7 +42676,7 @@ ttest_sgeno_csockf_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43746,10 +42689,6 @@ ttest_sgeno_csockf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csocko_small_tcp4(suite) ->
- [];
-ttest_sgeno_csocko_small_tcp4(doc) ->
- [];
ttest_sgeno_csocko_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_small_tcp4,
@@ -43757,7 +42696,7 @@ ttest_sgeno_csocko_small_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43770,10 +42709,6 @@ ttest_sgeno_csocko_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csocko_small_tcp6(suite) ->
- [];
-ttest_sgeno_csocko_small_tcp6(doc) ->
- [];
ttest_sgeno_csocko_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_small_tcp6,
@@ -43781,7 +42716,7 @@ ttest_sgeno_csocko_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43794,10 +42729,6 @@ ttest_sgeno_csocko_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csocko_medium_tcp4(suite) ->
- [];
-ttest_sgeno_csocko_medium_tcp4(doc) ->
- [];
ttest_sgeno_csocko_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_medium_tcp4,
@@ -43805,7 +42736,7 @@ ttest_sgeno_csocko_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43818,10 +42749,6 @@ ttest_sgeno_csocko_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csocko_medium_tcp6(suite) ->
- [];
-ttest_sgeno_csocko_medium_tcp6(doc) ->
- [];
ttest_sgeno_csocko_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_medium_tcp6,
@@ -43829,7 +42756,7 @@ ttest_sgeno_csocko_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43842,10 +42769,6 @@ ttest_sgeno_csocko_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csocko_large_tcp4(suite) ->
- [];
-ttest_sgeno_csocko_large_tcp4(doc) ->
- [];
ttest_sgeno_csocko_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_large_tcp4,
@@ -43853,7 +42776,7 @@ ttest_sgeno_csocko_large_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43866,10 +42789,6 @@ ttest_sgeno_csocko_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csocko_large_tcp6(suite) ->
- [];
-ttest_sgeno_csocko_large_tcp6(doc) ->
- [];
ttest_sgeno_csocko_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_large_tcp6,
@@ -43877,7 +42796,7 @@ ttest_sgeno_csocko_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -43890,10 +42809,6 @@ ttest_sgeno_csocko_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csockt_small_tcp4(suite) ->
- [];
-ttest_sgeno_csockt_small_tcp4(doc) ->
- [];
ttest_sgeno_csockt_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockt_small_tcp4,
@@ -43901,7 +42816,7 @@ ttest_sgeno_csockt_small_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43914,10 +42829,6 @@ ttest_sgeno_csockt_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csockt_small_tcp6(suite) ->
- [];
-ttest_sgeno_csockt_small_tcp6(doc) ->
- [];
ttest_sgeno_csockt_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csocko_small_tcp6,
@@ -43925,7 +42836,7 @@ ttest_sgeno_csockt_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -43938,10 +42849,6 @@ ttest_sgeno_csockt_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csockt_medium_tcp4(suite) ->
- [];
-ttest_sgeno_csockt_medium_tcp4(doc) ->
- [];
ttest_sgeno_csockt_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockt_medium_tcp4,
@@ -43949,7 +42856,7 @@ ttest_sgeno_csockt_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43962,10 +42869,6 @@ ttest_sgeno_csockt_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csockt_medium_tcp6(suite) ->
- [];
-ttest_sgeno_csockt_medium_tcp6(doc) ->
- [];
ttest_sgeno_csockt_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockt_medium_tcp6,
@@ -43973,7 +42876,7 @@ ttest_sgeno_csockt_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -43986,10 +42889,6 @@ ttest_sgeno_csockt_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgeno_csockt_large_tcp4(suite) ->
- [];
-ttest_sgeno_csockt_large_tcp4(doc) ->
- [];
ttest_sgeno_csockt_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockt_large_tcp4,
@@ -43997,7 +42896,7 @@ ttest_sgeno_csockt_large_tcp4(Config) when is_list(Config) ->
inet,
gen, once,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44010,10 +42909,6 @@ ttest_sgeno_csockt_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgeno_csockt_large_tcp6(suite) ->
- [];
-ttest_sgeno_csockt_large_tcp6(doc) ->
- [];
ttest_sgeno_csockt_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgeno_csockt_large_tcp6,
@@ -44021,7 +42916,7 @@ ttest_sgeno_csockt_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, once,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44034,10 +42929,6 @@ ttest_sgeno_csockt_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgenf_small_tcp4(suite) ->
- [];
-ttest_sgent_cgenf_small_tcp4(doc) ->
- [];
ttest_sgent_cgenf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgenf_small_tcp4,
@@ -44045,7 +42936,7 @@ ttest_sgent_cgenf_small_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44058,10 +42949,6 @@ ttest_sgent_cgenf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgenf_small_tcp6(suite) ->
- [];
-ttest_sgent_cgenf_small_tcp6(doc) ->
- [];
ttest_sgent_cgenf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgenf_small_tcp6,
@@ -44069,7 +42956,7 @@ ttest_sgent_cgenf_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44082,10 +42969,6 @@ ttest_sgent_cgenf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgenf_medium_tcp4(suite) ->
- [];
-ttest_sgent_cgenf_medium_tcp4(doc) ->
- [];
ttest_sgent_cgenf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgenf_medium_tcp4,
@@ -44093,7 +42976,7 @@ ttest_sgent_cgenf_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44106,10 +42989,6 @@ ttest_sgent_cgenf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgenf_medium_tcp6(suite) ->
- [];
-ttest_sgent_cgenf_medium_tcp6(doc) ->
- [];
ttest_sgent_cgenf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgenf_medium_tcp6,
@@ -44117,7 +42996,7 @@ ttest_sgent_cgenf_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44130,10 +43009,6 @@ ttest_sgent_cgenf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgenf_large_tcp4(suite) ->
- [];
-ttest_sgent_cgenf_large_tcp4(doc) ->
- [];
ttest_sgent_cgenf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgenf_large_tcp4,
@@ -44141,7 +43016,7 @@ ttest_sgent_cgenf_large_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44154,10 +43029,6 @@ ttest_sgent_cgenf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgenf_large_tcp6(suite) ->
- [];
-ttest_sgent_cgenf_large_tcp6(doc) ->
- [];
ttest_sgent_cgenf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgenf_large_tcp6,
@@ -44165,7 +43036,7 @@ ttest_sgent_cgenf_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44178,10 +43049,6 @@ ttest_sgent_cgenf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgeno_small_tcp4(suite) ->
- [];
-ttest_sgent_cgeno_small_tcp4(doc) ->
- [];
ttest_sgent_cgeno_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_small_tcp4,
@@ -44189,7 +43056,7 @@ ttest_sgent_cgeno_small_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44202,10 +43069,6 @@ ttest_sgent_cgeno_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgeno_small_tcp6(suite) ->
- [];
-ttest_sgent_cgeno_small_tcp6(doc) ->
- [];
ttest_sgent_cgeno_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_small_tcp6,
@@ -44213,7 +43076,7 @@ ttest_sgent_cgeno_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44226,10 +43089,6 @@ ttest_sgent_cgeno_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgeno_medium_tcp4(suite) ->
- [];
-ttest_sgent_cgeno_medium_tcp4(doc) ->
- [];
ttest_sgent_cgeno_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_medium_tcp4,
@@ -44237,7 +43096,7 @@ ttest_sgent_cgeno_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44250,10 +43109,6 @@ ttest_sgent_cgeno_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgeno_medium_tcp6(suite) ->
- [];
-ttest_sgent_cgeno_medium_tcp6(doc) ->
- [];
ttest_sgent_cgeno_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_medium_tcp6,
@@ -44261,7 +43116,7 @@ ttest_sgent_cgeno_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44274,10 +43129,6 @@ ttest_sgent_cgeno_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgeno_large_tcp4(suite) ->
- [];
-ttest_sgent_cgeno_large_tcp4(doc) ->
- [];
ttest_sgent_cgeno_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_large_tcp4,
@@ -44285,7 +43136,7 @@ ttest_sgent_cgeno_large_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44298,10 +43149,6 @@ ttest_sgent_cgeno_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgeno_large_tcp6(suite) ->
- [];
-ttest_sgent_cgeno_large_tcp6(doc) ->
- [];
ttest_sgent_cgeno_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_large_tcp6,
@@ -44309,7 +43156,7 @@ ttest_sgent_cgeno_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44322,10 +43169,6 @@ ttest_sgent_cgeno_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgent_small_tcp4(suite) ->
- [];
-ttest_sgent_cgent_small_tcp4(doc) ->
- [];
ttest_sgent_cgent_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgent_small_tcp4,
@@ -44333,7 +43176,7 @@ ttest_sgent_cgent_small_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44346,10 +43189,6 @@ ttest_sgent_cgent_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgent_small_tcp6(suite) ->
- [];
-ttest_sgent_cgent_small_tcp6(doc) ->
- [];
ttest_sgent_cgent_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgeno_small_tcp6,
@@ -44357,7 +43196,7 @@ ttest_sgent_cgent_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44370,10 +43209,9 @@ ttest_sgent_cgent_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgent_medium_tcp4(suite) ->
- [];
-ttest_sgent_cgent_medium_tcp4(doc) ->
- ["Server(gen,true), Client(gen,true), Domain=inet, msg=medium"];
+ttest_sgent_cgent_medium_tcp4() ->
+ [{doc, "Server(gen,true), Client(gen,true), Domain=inet, msg=medium"}].
+
ttest_sgent_cgent_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgent_medium_tcp4,
@@ -44381,7 +43219,7 @@ ttest_sgent_cgent_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44393,11 +43231,9 @@ ttest_sgent_cgent_medium_tcp4(Config) when is_list(Config) ->
%% Message Size: medium (=2)
%% Domain: inet6
%%
+ttest_sgent_cgent_medium_tcp6() ->
+ [{doc, "Server(gen,true), Client(gen,true), Domain=inet6, msg=medium"}].
-ttest_sgent_cgent_medium_tcp6(suite) ->
- [];
-ttest_sgent_cgent_medium_tcp6(doc) ->
- ["Server(gen,true), Client(gen,true), Domain=inet6, msg=medium"];
ttest_sgent_cgent_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgent_medium_tcp6,
@@ -44405,7 +43241,7 @@ ttest_sgent_cgent_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44418,10 +43254,9 @@ ttest_sgent_cgent_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_cgent_large_tcp4(suite) ->
- [];
-ttest_sgent_cgent_large_tcp4(doc) ->
- ["Server(gen,true), Client(gen,true), Domain=inet, msg=large"];
+ttest_sgent_cgent_large_tcp4() ->
+ [{doc, "Server(gen,true), Client(gen,true), Domain=inet, msg=large"}].
+
ttest_sgent_cgent_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgent_large_tcp4,
@@ -44429,7 +43264,7 @@ ttest_sgent_cgent_large_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44442,10 +43277,9 @@ ttest_sgent_cgent_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_cgent_large_tcp6(suite) ->
- [];
-ttest_sgent_cgent_large_tcp6(doc) ->
- ["Server(gen,true), Client(gen,true), Domain=inet6, msg=large"];
+ttest_sgent_cgent_large_tcp6() ->
+ [{doc, "Server(gen,true), Client(gen,true), Domain=inet6, msg=large"}].
+
ttest_sgent_cgent_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_cgent_large_tcp6,
@@ -44453,7 +43287,7 @@ ttest_sgent_cgent_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44466,10 +43300,7 @@ ttest_sgent_cgent_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csockf_small_tcp4(suite) ->
- [];
-ttest_sgent_csockf_small_tcp4(doc) ->
- [];
+
ttest_sgent_csockf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockf_small_tcp4,
@@ -44477,7 +43308,7 @@ ttest_sgent_csockf_small_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44490,10 +43321,6 @@ ttest_sgent_csockf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csockf_small_tcp6(suite) ->
- [];
-ttest_sgent_csockf_small_tcp6(doc) ->
- [];
ttest_sgent_csockf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockf_small_tcp6,
@@ -44501,7 +43328,7 @@ ttest_sgent_csockf_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44514,10 +43341,6 @@ ttest_sgent_csockf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csockf_medium_tcp4(suite) ->
- [];
-ttest_sgent_csockf_medium_tcp4(doc) ->
- [];
ttest_sgent_csockf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockf_medium_tcp4,
@@ -44525,7 +43348,7 @@ ttest_sgent_csockf_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44538,10 +43361,6 @@ ttest_sgent_csockf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csockf_medium_tcp6(suite) ->
- [];
-ttest_sgent_csockf_medium_tcp6(doc) ->
- [];
ttest_sgent_csockf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockf_medium_tcp6,
@@ -44549,7 +43368,7 @@ ttest_sgent_csockf_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44562,10 +43381,6 @@ ttest_sgent_csockf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csockf_large_tcp4(suite) ->
- [];
-ttest_sgent_csockf_large_tcp4(doc) ->
- [];
ttest_sgent_csockf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockf_large_tcp4,
@@ -44573,7 +43388,7 @@ ttest_sgent_csockf_large_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44586,10 +43401,6 @@ ttest_sgent_csockf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csockf_large_tcp6(suite) ->
- [];
-ttest_sgent_csockf_large_tcp6(doc) ->
- [];
ttest_sgent_csockf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockf_large_tcp6,
@@ -44597,7 +43408,7 @@ ttest_sgent_csockf_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44610,10 +43421,6 @@ ttest_sgent_csockf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csocko_small_tcp4(suite) ->
- [];
-ttest_sgent_csocko_small_tcp4(doc) ->
- [];
ttest_sgent_csocko_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_small_tcp4,
@@ -44621,7 +43428,7 @@ ttest_sgent_csocko_small_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44634,10 +43441,6 @@ ttest_sgent_csocko_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csocko_small_tcp6(suite) ->
- [];
-ttest_sgent_csocko_small_tcp6(doc) ->
- [];
ttest_sgent_csocko_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_small_tcp6,
@@ -44645,7 +43448,7 @@ ttest_sgent_csocko_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44658,10 +43461,6 @@ ttest_sgent_csocko_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csocko_medium_tcp4(suite) ->
- [];
-ttest_sgent_csocko_medium_tcp4(doc) ->
- [];
ttest_sgent_csocko_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_medium_tcp4,
@@ -44669,7 +43468,7 @@ ttest_sgent_csocko_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44682,10 +43481,6 @@ ttest_sgent_csocko_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csocko_medium_tcp6(suite) ->
- [];
-ttest_sgent_csocko_medium_tcp6(doc) ->
- [];
ttest_sgent_csocko_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_medium_tcp6,
@@ -44693,7 +43488,7 @@ ttest_sgent_csocko_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44706,10 +43501,6 @@ ttest_sgent_csocko_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csocko_large_tcp4(suite) ->
- [];
-ttest_sgent_csocko_large_tcp4(doc) ->
- [];
ttest_sgent_csocko_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_large_tcp4,
@@ -44717,7 +43508,7 @@ ttest_sgent_csocko_large_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44730,10 +43521,6 @@ ttest_sgent_csocko_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csocko_large_tcp6(suite) ->
- [];
-ttest_sgent_csocko_large_tcp6(doc) ->
- [];
ttest_sgent_csocko_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_large_tcp6,
@@ -44741,7 +43528,7 @@ ttest_sgent_csocko_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44754,10 +43541,6 @@ ttest_sgent_csocko_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csockt_small_tcp4(suite) ->
- [];
-ttest_sgent_csockt_small_tcp4(doc) ->
- [];
ttest_sgent_csockt_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockt_small_tcp4,
@@ -44765,7 +43548,7 @@ ttest_sgent_csockt_small_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44778,10 +43561,6 @@ ttest_sgent_csockt_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csockt_small_tcp6(suite) ->
- [];
-ttest_sgent_csockt_small_tcp6(doc) ->
- [];
ttest_sgent_csockt_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csocko_small_tcp6,
@@ -44789,7 +43568,7 @@ ttest_sgent_csockt_small_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44802,10 +43581,6 @@ ttest_sgent_csockt_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csockt_medium_tcp4(suite) ->
- [];
-ttest_sgent_csockt_medium_tcp4(doc) ->
- [];
ttest_sgent_csockt_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockt_medium_tcp4,
@@ -44813,7 +43588,7 @@ ttest_sgent_csockt_medium_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44826,10 +43601,6 @@ ttest_sgent_csockt_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csockt_medium_tcp6(suite) ->
- [];
-ttest_sgent_csockt_medium_tcp6(doc) ->
- [];
ttest_sgent_csockt_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockt_medium_tcp6,
@@ -44837,7 +43608,7 @@ ttest_sgent_csockt_medium_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44850,10 +43621,6 @@ ttest_sgent_csockt_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_sgent_csockt_large_tcp4(suite) ->
- [];
-ttest_sgent_csockt_large_tcp4(doc) ->
- [];
ttest_sgent_csockt_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockt_large_tcp4,
@@ -44861,7 +43628,7 @@ ttest_sgent_csockt_large_tcp4(Config) when is_list(Config) ->
inet,
gen, true,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44874,10 +43641,6 @@ ttest_sgent_csockt_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_sgent_csockt_large_tcp6(suite) ->
- [];
-ttest_sgent_csockt_large_tcp6(doc) ->
- [];
ttest_sgent_csockt_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_sgent_csockt_large_tcp6,
@@ -44885,7 +43648,7 @@ ttest_sgent_csockt_large_tcp6(Config) when is_list(Config) ->
inet6,
gen, true,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -44898,10 +43661,6 @@ ttest_sgent_csockt_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgenf_small_tcp4(suite) ->
- [];
-ttest_ssockf_cgenf_small_tcp4(doc) ->
- [];
ttest_ssockf_cgenf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgenf_small_tcp4,
@@ -44909,7 +43668,7 @@ ttest_ssockf_cgenf_small_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44922,10 +43681,6 @@ ttest_ssockf_cgenf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgenf_small_tcp6(suite) ->
- [];
-ttest_ssockf_cgenf_small_tcp6(doc) ->
- [];
ttest_ssockf_cgenf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgenf_small_tcp6,
@@ -44933,7 +43688,7 @@ ttest_ssockf_cgenf_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -44946,10 +43701,6 @@ ttest_ssockf_cgenf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgenf_medium_tcp4(suite) ->
- [];
-ttest_ssockf_cgenf_medium_tcp4(doc) ->
- [];
ttest_ssockf_cgenf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgenf_medium_tcp4,
@@ -44957,7 +43708,7 @@ ttest_ssockf_cgenf_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44970,10 +43721,6 @@ ttest_ssockf_cgenf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgenf_medium_tcp6(suite) ->
- [];
-ttest_ssockf_cgenf_medium_tcp6(doc) ->
- [];
ttest_ssockf_cgenf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgenf_medium_tcp6,
@@ -44981,7 +43728,7 @@ ttest_ssockf_cgenf_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -44994,10 +43741,6 @@ ttest_ssockf_cgenf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgenf_large_tcp4(suite) ->
- [];
-ttest_ssockf_cgenf_large_tcp4(doc) ->
- [];
ttest_ssockf_cgenf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgenf_large_tcp4,
@@ -45005,7 +43748,7 @@ ttest_ssockf_cgenf_large_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45018,10 +43761,6 @@ ttest_ssockf_cgenf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgenf_large_tcp6(suite) ->
- [];
-ttest_ssockf_cgenf_large_tcp6(doc) ->
- [];
ttest_ssockf_cgenf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgenf_large_tcp6,
@@ -45029,7 +43768,7 @@ ttest_ssockf_cgenf_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45042,10 +43781,6 @@ ttest_ssockf_cgenf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgeno_small_tcp4(suite) ->
- [];
-ttest_ssockf_cgeno_small_tcp4(doc) ->
- [];
ttest_ssockf_cgeno_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_small_tcp4,
@@ -45053,7 +43788,7 @@ ttest_ssockf_cgeno_small_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45066,10 +43801,6 @@ ttest_ssockf_cgeno_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgeno_small_tcp6(suite) ->
- [];
-ttest_ssockf_cgeno_small_tcp6(doc) ->
- [];
ttest_ssockf_cgeno_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_small_tcp6,
@@ -45077,7 +43808,7 @@ ttest_ssockf_cgeno_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45090,10 +43821,6 @@ ttest_ssockf_cgeno_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgeno_medium_tcp4(suite) ->
- [];
-ttest_ssockf_cgeno_medium_tcp4(doc) ->
- [];
ttest_ssockf_cgeno_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_medium_tcp4,
@@ -45101,7 +43828,7 @@ ttest_ssockf_cgeno_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45114,10 +43841,6 @@ ttest_ssockf_cgeno_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgeno_medium_tcp6(suite) ->
- [];
-ttest_ssockf_cgeno_medium_tcp6(doc) ->
- [];
ttest_ssockf_cgeno_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_medium_tcp6,
@@ -45125,7 +43848,7 @@ ttest_ssockf_cgeno_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45138,10 +43861,6 @@ ttest_ssockf_cgeno_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgeno_large_tcp4(suite) ->
- [];
-ttest_ssockf_cgeno_large_tcp4(doc) ->
- [];
ttest_ssockf_cgeno_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_large_tcp4,
@@ -45149,7 +43868,7 @@ ttest_ssockf_cgeno_large_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45162,10 +43881,6 @@ ttest_ssockf_cgeno_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgeno_large_tcp6(suite) ->
- [];
-ttest_ssockf_cgeno_large_tcp6(doc) ->
- [];
ttest_ssockf_cgeno_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_large_tcp6,
@@ -45173,7 +43888,7 @@ ttest_ssockf_cgeno_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45186,10 +43901,6 @@ ttest_ssockf_cgeno_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgent_small_tcp4(suite) ->
- [];
-ttest_ssockf_cgent_small_tcp4(doc) ->
- [];
ttest_ssockf_cgent_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgent_small_tcp4,
@@ -45197,7 +43908,7 @@ ttest_ssockf_cgent_small_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45210,10 +43921,6 @@ ttest_ssockf_cgent_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgent_small_tcp6(suite) ->
- [];
-ttest_ssockf_cgent_small_tcp6(doc) ->
- [];
ttest_ssockf_cgent_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgeno_small_tcp6,
@@ -45221,7 +43928,7 @@ ttest_ssockf_cgent_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45234,10 +43941,6 @@ ttest_ssockf_cgent_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgent_medium_tcp4(suite) ->
- [];
-ttest_ssockf_cgent_medium_tcp4(doc) ->
- [];
ttest_ssockf_cgent_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgent_medium_tcp4,
@@ -45245,7 +43948,7 @@ ttest_ssockf_cgent_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45258,10 +43961,6 @@ ttest_ssockf_cgent_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgent_medium_tcp6(suite) ->
- [];
-ttest_ssockf_cgent_medium_tcp6(doc) ->
- [];
ttest_ssockf_cgent_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgent_medium_tcp6,
@@ -45269,7 +43968,7 @@ ttest_ssockf_cgent_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45282,10 +43981,6 @@ ttest_ssockf_cgent_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_cgent_large_tcp4(suite) ->
- [];
-ttest_ssockf_cgent_large_tcp4(doc) ->
- [];
ttest_ssockf_cgent_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgent_large_tcp4,
@@ -45293,7 +43988,7 @@ ttest_ssockf_cgent_large_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45306,10 +44001,6 @@ ttest_ssockf_cgent_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_cgent_large_tcp6(suite) ->
- [];
-ttest_ssockf_cgent_large_tcp6(doc) ->
- [];
ttest_ssockf_cgent_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_cgent_large_tcp6,
@@ -45317,7 +44008,7 @@ ttest_ssockf_cgent_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45330,10 +44021,6 @@ ttest_ssockf_cgent_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csockf_small_tcp4(suite) ->
- [];
-ttest_ssockf_csockf_small_tcp4(doc) ->
- [];
ttest_ssockf_csockf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_small_tcp4,
@@ -45341,7 +44028,7 @@ ttest_ssockf_csockf_small_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45354,10 +44041,6 @@ ttest_ssockf_csockf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csockf_small_tcp6(suite) ->
- [];
-ttest_ssockf_csockf_small_tcp6(doc) ->
- [];
ttest_ssockf_csockf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_small_tcp6,
@@ -45365,7 +44048,7 @@ ttest_ssockf_csockf_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45378,10 +44061,6 @@ ttest_ssockf_csockf_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csockf_small_tcpL(suite) ->
- [];
-ttest_ssockf_csockf_small_tcpL(doc) ->
- [];
ttest_ssockf_csockf_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_small_tcpL,
@@ -45389,7 +44068,7 @@ ttest_ssockf_csockf_small_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45402,10 +44081,6 @@ ttest_ssockf_csockf_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csockf_medium_tcp4(suite) ->
- [];
-ttest_ssockf_csockf_medium_tcp4(doc) ->
- [];
ttest_ssockf_csockf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_medium_tcp4,
@@ -45413,7 +44088,7 @@ ttest_ssockf_csockf_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45426,10 +44101,6 @@ ttest_ssockf_csockf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csockf_medium_tcp6(suite) ->
- [];
-ttest_ssockf_csockf_medium_tcp6(doc) ->
- [];
ttest_ssockf_csockf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_medium_tcp6,
@@ -45437,7 +44108,7 @@ ttest_ssockf_csockf_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45450,10 +44121,6 @@ ttest_ssockf_csockf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csockf_medium_tcpL(suite) ->
- [];
-ttest_ssockf_csockf_medium_tcpL(doc) ->
- [];
ttest_ssockf_csockf_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_medium_tcpL,
@@ -45461,7 +44128,7 @@ ttest_ssockf_csockf_medium_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45474,10 +44141,6 @@ ttest_ssockf_csockf_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csockf_large_tcp4(suite) ->
- [];
-ttest_ssockf_csockf_large_tcp4(doc) ->
- [];
ttest_ssockf_csockf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_large_tcp4,
@@ -45485,7 +44148,7 @@ ttest_ssockf_csockf_large_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45498,10 +44161,6 @@ ttest_ssockf_csockf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csockf_large_tcp6(suite) ->
- [];
-ttest_ssockf_csockf_large_tcp6(doc) ->
- [];
ttest_ssockf_csockf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_large_tcp6,
@@ -45509,7 +44168,7 @@ ttest_ssockf_csockf_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45522,10 +44181,6 @@ ttest_ssockf_csockf_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csockf_large_tcpL(suite) ->
- [];
-ttest_ssockf_csockf_large_tcpL(doc) ->
- [];
ttest_ssockf_csockf_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockf_large_tcpL,
@@ -45533,7 +44188,7 @@ ttest_ssockf_csockf_large_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45546,10 +44201,6 @@ ttest_ssockf_csockf_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csocko_small_tcp4(suite) ->
- [];
-ttest_ssockf_csocko_small_tcp4(doc) ->
- [];
ttest_ssockf_csocko_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_small_tcp4,
@@ -45557,7 +44208,7 @@ ttest_ssockf_csocko_small_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45570,10 +44221,6 @@ ttest_ssockf_csocko_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csocko_small_tcp6(suite) ->
- [];
-ttest_ssockf_csocko_small_tcp6(doc) ->
- [];
ttest_ssockf_csocko_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_small_tcp6,
@@ -45581,7 +44228,7 @@ ttest_ssockf_csocko_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45594,10 +44241,6 @@ ttest_ssockf_csocko_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csocko_small_tcpL(suite) ->
- [];
-ttest_ssockf_csocko_small_tcpL(doc) ->
- [];
ttest_ssockf_csocko_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_small_tcpL,
@@ -45605,7 +44248,7 @@ ttest_ssockf_csocko_small_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45618,10 +44261,6 @@ ttest_ssockf_csocko_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csocko_medium_tcp4(suite) ->
- [];
-ttest_ssockf_csocko_medium_tcp4(doc) ->
- [];
ttest_ssockf_csocko_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_medium_tcp4,
@@ -45629,7 +44268,7 @@ ttest_ssockf_csocko_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45642,10 +44281,6 @@ ttest_ssockf_csocko_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csocko_medium_tcp6(suite) ->
- [];
-ttest_ssockf_csocko_medium_tcp6(doc) ->
- [];
ttest_ssockf_csocko_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_medium_tcp6,
@@ -45653,7 +44288,7 @@ ttest_ssockf_csocko_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45666,10 +44301,6 @@ ttest_ssockf_csocko_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csocko_medium_tcpL(suite) ->
- [];
-ttest_ssockf_csocko_medium_tcpL(doc) ->
- [];
ttest_ssockf_csocko_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_medium_tcpL,
@@ -45677,7 +44308,7 @@ ttest_ssockf_csocko_medium_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45690,10 +44321,6 @@ ttest_ssockf_csocko_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csocko_large_tcp4(suite) ->
- [];
-ttest_ssockf_csocko_large_tcp4(doc) ->
- [];
ttest_ssockf_csocko_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_large_tcp4,
@@ -45701,7 +44328,7 @@ ttest_ssockf_csocko_large_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45714,10 +44341,6 @@ ttest_ssockf_csocko_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csocko_large_tcp6(suite) ->
- [];
-ttest_ssockf_csocko_large_tcp6(doc) ->
- [];
ttest_ssockf_csocko_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_large_tcp6,
@@ -45725,7 +44348,7 @@ ttest_ssockf_csocko_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45738,10 +44361,6 @@ ttest_ssockf_csocko_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csocko_large_tcpL(suite) ->
- [];
-ttest_ssockf_csocko_large_tcpL(doc) ->
- [];
ttest_ssockf_csocko_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_large_tcpL,
@@ -45749,7 +44368,7 @@ ttest_ssockf_csocko_large_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45762,10 +44381,6 @@ ttest_ssockf_csocko_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csockt_small_tcp4(suite) ->
- [];
-ttest_ssockf_csockt_small_tcp4(doc) ->
- [];
ttest_ssockf_csockt_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_small_tcp4,
@@ -45773,7 +44388,7 @@ ttest_ssockf_csockt_small_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45786,10 +44401,6 @@ ttest_ssockf_csockt_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csockt_small_tcp6(suite) ->
- [];
-ttest_ssockf_csockt_small_tcp6(doc) ->
- [];
ttest_ssockf_csockt_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_small_tcp6,
@@ -45797,7 +44408,7 @@ ttest_ssockf_csockt_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45810,10 +44421,6 @@ ttest_ssockf_csockt_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csockt_small_tcpL(suite) ->
- [];
-ttest_ssockf_csockt_small_tcpL(doc) ->
- [];
ttest_ssockf_csockt_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csocko_small_tcpL,
@@ -45821,7 +44428,7 @@ ttest_ssockf_csockt_small_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -45834,10 +44441,6 @@ ttest_ssockf_csockt_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csockt_medium_tcp4(suite) ->
- [];
-ttest_ssockf_csockt_medium_tcp4(doc) ->
- [];
ttest_ssockf_csockt_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_medium_tcp4,
@@ -45845,7 +44448,7 @@ ttest_ssockf_csockt_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45858,10 +44461,6 @@ ttest_ssockf_csockt_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csockt_medium_tcp6(suite) ->
- [];
-ttest_ssockf_csockt_medium_tcp6(doc) ->
- [];
ttest_ssockf_csockt_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_medium_tcp6,
@@ -45869,7 +44468,7 @@ ttest_ssockf_csockt_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45882,10 +44481,6 @@ ttest_ssockf_csockt_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csockt_medium_tcpL(suite) ->
- [];
-ttest_ssockf_csockt_medium_tcpL(doc) ->
- [];
ttest_ssockf_csockt_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_medium_tcpL,
@@ -45893,7 +44488,7 @@ ttest_ssockf_csockt_medium_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -45906,10 +44501,6 @@ ttest_ssockf_csockt_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockf_csockt_large_tcp4(suite) ->
- [];
-ttest_ssockf_csockt_large_tcp4(doc) ->
- [];
ttest_ssockf_csockt_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_large_tcp4,
@@ -45917,7 +44508,7 @@ ttest_ssockf_csockt_large_tcp4(Config) when is_list(Config) ->
inet,
sock, false,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45930,10 +44521,6 @@ ttest_ssockf_csockt_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockf_csockt_large_tcp6(suite) ->
- [];
-ttest_ssockf_csockt_large_tcp6(doc) ->
- [];
ttest_ssockf_csockt_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_large_tcp6,
@@ -45941,7 +44528,7 @@ ttest_ssockf_csockt_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, false,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45954,10 +44541,6 @@ ttest_ssockf_csockt_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockf_csockt_large_tcpL(suite) ->
- [];
-ttest_ssockf_csockt_large_tcpL(doc) ->
- [];
ttest_ssockf_csockt_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockf_csockt_large_tcpL,
@@ -45965,7 +44548,7 @@ ttest_ssockf_csockt_large_tcpL(Config) when is_list(Config) ->
local,
sock, false,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -45978,10 +44561,6 @@ ttest_ssockf_csockt_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgenf_small_tcp4(suite) ->
- [];
-ttest_ssocko_cgenf_small_tcp4(doc) ->
- [];
ttest_ssocko_cgenf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgenf_small_tcp4,
@@ -45989,7 +44568,7 @@ ttest_ssocko_cgenf_small_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46002,10 +44581,6 @@ ttest_ssocko_cgenf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgenf_small_tcp6(suite) ->
- [];
-ttest_ssocko_cgenf_small_tcp6(doc) ->
- [];
ttest_ssocko_cgenf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgenf_small_tcp6,
@@ -46013,7 +44588,7 @@ ttest_ssocko_cgenf_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46026,10 +44601,6 @@ ttest_ssocko_cgenf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgenf_medium_tcp4(suite) ->
- [];
-ttest_ssocko_cgenf_medium_tcp4(doc) ->
- [];
ttest_ssocko_cgenf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgenf_medium_tcp4,
@@ -46037,7 +44608,7 @@ ttest_ssocko_cgenf_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46050,10 +44621,6 @@ ttest_ssocko_cgenf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgenf_medium_tcp6(suite) ->
- [];
-ttest_ssocko_cgenf_medium_tcp6(doc) ->
- [];
ttest_ssocko_cgenf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgenf_medium_tcp6,
@@ -46061,7 +44628,7 @@ ttest_ssocko_cgenf_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46074,10 +44641,6 @@ ttest_ssocko_cgenf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgenf_large_tcp4(suite) ->
- [];
-ttest_ssocko_cgenf_large_tcp4(doc) ->
- [];
ttest_ssocko_cgenf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgenf_large_tcp4,
@@ -46085,7 +44648,7 @@ ttest_ssocko_cgenf_large_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46098,10 +44661,6 @@ ttest_ssocko_cgenf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgenf_large_tcp6(suite) ->
- [];
-ttest_ssocko_cgenf_large_tcp6(doc) ->
- [];
ttest_ssocko_cgenf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgenf_large_tcp6,
@@ -46109,7 +44668,7 @@ ttest_ssocko_cgenf_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46122,10 +44681,6 @@ ttest_ssocko_cgenf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgeno_small_tcp4(suite) ->
- [];
-ttest_ssocko_cgeno_small_tcp4(doc) ->
- [];
ttest_ssocko_cgeno_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgeno_small_tcp4,
@@ -46133,7 +44688,7 @@ ttest_ssocko_cgeno_small_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46146,10 +44701,6 @@ ttest_ssocko_cgeno_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgeno_small_tcp6(suite) ->
- [];
-ttest_ssocko_cgeno_small_tcp6(doc) ->
- [];
ttest_ssocko_cgeno_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgeno_small_tcp6,
@@ -46157,7 +44708,7 @@ ttest_ssocko_cgeno_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46170,10 +44721,6 @@ ttest_ssocko_cgeno_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgeno_medium_tcp4(suite) ->
- [];
-ttest_ssocko_cgeno_medium_tcp4(doc) ->
- [];
ttest_ssocko_cgeno_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgeno_medium_tcp4,
@@ -46181,7 +44728,7 @@ ttest_ssocko_cgeno_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46194,10 +44741,6 @@ ttest_ssocko_cgeno_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgeno_medium_tcp6(suite) ->
- [];
-ttest_ssocko_cgeno_medium_tcp6(doc) ->
- [];
ttest_ssocko_cgeno_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgeno_medium_tcp6,
@@ -46205,7 +44748,7 @@ ttest_ssocko_cgeno_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46218,10 +44761,6 @@ ttest_ssocko_cgeno_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgeno_large_tcp4(suite) ->
- [];
-ttest_ssocko_cgeno_large_tcp4(doc) ->
- [];
ttest_ssocko_cgeno_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgeno_large_tcp4,
@@ -46229,7 +44768,7 @@ ttest_ssocko_cgeno_large_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46242,10 +44781,6 @@ ttest_ssocko_cgeno_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgeno_large_tcp6(suite) ->
- [];
-ttest_ssocko_cgeno_large_tcp6(doc) ->
- [];
ttest_ssocko_cgeno_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgeno_large_tcp6,
@@ -46253,7 +44788,7 @@ ttest_ssocko_cgeno_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46266,10 +44801,6 @@ ttest_ssocko_cgeno_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgent_small_tcp4(suite) ->
- [];
-ttest_ssocko_cgent_small_tcp4(doc) ->
- [];
ttest_ssocko_cgent_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgent_small_tcp4,
@@ -46277,7 +44808,7 @@ ttest_ssocko_cgent_small_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46290,10 +44821,6 @@ ttest_ssocko_cgent_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgent_small_tcp6(suite) ->
- [];
-ttest_ssocko_cgent_small_tcp6(doc) ->
- [];
ttest_ssocko_cgent_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgent_small_tcp6,
@@ -46301,7 +44828,7 @@ ttest_ssocko_cgent_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46314,10 +44841,6 @@ ttest_ssocko_cgent_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgent_medium_tcp4(suite) ->
- [];
-ttest_ssocko_cgent_medium_tcp4(doc) ->
- [];
ttest_ssocko_cgent_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgent_medium_tcp4,
@@ -46325,7 +44848,7 @@ ttest_ssocko_cgent_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46338,10 +44861,6 @@ ttest_ssocko_cgent_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgent_medium_tcp6(suite) ->
- [];
-ttest_ssocko_cgent_medium_tcp6(doc) ->
- [];
ttest_ssocko_cgent_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgent_medium_tcp6,
@@ -46349,7 +44868,7 @@ ttest_ssocko_cgent_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46362,10 +44881,6 @@ ttest_ssocko_cgent_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_cgent_large_tcp4(suite) ->
- [];
-ttest_ssocko_cgent_large_tcp4(doc) ->
- [];
ttest_ssocko_cgent_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgent_large_tcp4,
@@ -46373,7 +44888,7 @@ ttest_ssocko_cgent_large_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46386,10 +44901,6 @@ ttest_ssocko_cgent_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_cgent_large_tcp6(suite) ->
- [];
-ttest_ssocko_cgent_large_tcp6(doc) ->
- [];
ttest_ssocko_cgent_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_cgent_large_tcp6,
@@ -46397,7 +44908,7 @@ ttest_ssocko_cgent_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46410,10 +44921,6 @@ ttest_ssocko_cgent_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csockf_small_tcp4(suite) ->
- [];
-ttest_ssocko_csockf_small_tcp4(doc) ->
- [];
ttest_ssocko_csockf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_small_tcp4,
@@ -46421,7 +44928,7 @@ ttest_ssocko_csockf_small_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46434,10 +44941,6 @@ ttest_ssocko_csockf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csockf_small_tcp6(suite) ->
- [];
-ttest_ssocko_csockf_small_tcp6(doc) ->
- [];
ttest_ssocko_csockf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_small_tcp6,
@@ -46445,7 +44948,7 @@ ttest_ssocko_csockf_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46458,10 +44961,6 @@ ttest_ssocko_csockf_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csockf_small_tcpL(suite) ->
- [];
-ttest_ssocko_csockf_small_tcpL(doc) ->
- [];
ttest_ssocko_csockf_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_small_tcpL,
@@ -46469,7 +44968,7 @@ ttest_ssocko_csockf_small_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46482,10 +44981,6 @@ ttest_ssocko_csockf_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csockf_medium_tcp4(suite) ->
- [];
-ttest_ssocko_csockf_medium_tcp4(doc) ->
- [];
ttest_ssocko_csockf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_medium_tcp4,
@@ -46493,7 +44988,7 @@ ttest_ssocko_csockf_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46506,10 +45001,6 @@ ttest_ssocko_csockf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csockf_medium_tcp6(suite) ->
- [];
-ttest_ssocko_csockf_medium_tcp6(doc) ->
- [];
ttest_ssocko_csockf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_medium_tcp6,
@@ -46517,7 +45008,7 @@ ttest_ssocko_csockf_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46530,10 +45021,6 @@ ttest_ssocko_csockf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csockf_medium_tcpL(suite) ->
- [];
-ttest_ssocko_csockf_medium_tcpL(doc) ->
- [];
ttest_ssocko_csockf_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_medium_tcpL,
@@ -46541,7 +45028,7 @@ ttest_ssocko_csockf_medium_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46554,10 +45041,6 @@ ttest_ssocko_csockf_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csockf_large_tcp4(suite) ->
- [];
-ttest_ssocko_csockf_large_tcp4(doc) ->
- [];
ttest_ssocko_csockf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_large_tcp4,
@@ -46565,7 +45048,7 @@ ttest_ssocko_csockf_large_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46578,10 +45061,6 @@ ttest_ssocko_csockf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csockf_large_tcp6(suite) ->
- [];
-ttest_ssocko_csockf_large_tcp6(doc) ->
- [];
ttest_ssocko_csockf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_large_tcp6,
@@ -46589,7 +45068,7 @@ ttest_ssocko_csockf_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46602,10 +45081,6 @@ ttest_ssocko_csockf_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csockf_large_tcpL(suite) ->
- [];
-ttest_ssocko_csockf_large_tcpL(doc) ->
- [];
ttest_ssocko_csockf_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockf_large_tcpL,
@@ -46613,7 +45088,7 @@ ttest_ssocko_csockf_large_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46626,10 +45101,6 @@ ttest_ssocko_csockf_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csocko_small_tcp4(suite) ->
- [];
-ttest_ssocko_csocko_small_tcp4(doc) ->
- [];
ttest_ssocko_csocko_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_small_tcp4,
@@ -46637,7 +45108,7 @@ ttest_ssocko_csocko_small_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46650,10 +45121,6 @@ ttest_ssocko_csocko_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csocko_small_tcp6(suite) ->
- [];
-ttest_ssocko_csocko_small_tcp6(doc) ->
- [];
ttest_ssocko_csocko_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_small_tcp6,
@@ -46661,7 +45128,7 @@ ttest_ssocko_csocko_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46674,10 +45141,6 @@ ttest_ssocko_csocko_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csocko_small_tcpL(suite) ->
- [];
-ttest_ssocko_csocko_small_tcpL(doc) ->
- [];
ttest_ssocko_csocko_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_small_tcpL,
@@ -46685,7 +45148,7 @@ ttest_ssocko_csocko_small_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46698,10 +45161,6 @@ ttest_ssocko_csocko_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csocko_medium_tcp4(suite) ->
- [];
-ttest_ssocko_csocko_medium_tcp4(doc) ->
- [];
ttest_ssocko_csocko_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_medium_tcp4,
@@ -46709,7 +45168,7 @@ ttest_ssocko_csocko_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46722,10 +45181,6 @@ ttest_ssocko_csocko_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csocko_medium_tcp6(suite) ->
- [];
-ttest_ssocko_csocko_medium_tcp6(doc) ->
- [];
ttest_ssocko_csocko_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_medium_tcp6,
@@ -46733,7 +45188,7 @@ ttest_ssocko_csocko_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46746,10 +45201,6 @@ ttest_ssocko_csocko_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csocko_medium_tcpL(suite) ->
- [];
-ttest_ssocko_csocko_medium_tcpL(doc) ->
- [];
ttest_ssocko_csocko_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_medium_tcpL,
@@ -46757,7 +45208,7 @@ ttest_ssocko_csocko_medium_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46770,10 +45221,6 @@ ttest_ssocko_csocko_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csocko_large_tcp4(suite) ->
- [];
-ttest_ssocko_csocko_large_tcp4(doc) ->
- [];
ttest_ssocko_csocko_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_large_tcp4,
@@ -46781,7 +45228,7 @@ ttest_ssocko_csocko_large_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46794,10 +45241,6 @@ ttest_ssocko_csocko_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csocko_large_tcp6(suite) ->
- [];
-ttest_ssocko_csocko_large_tcp6(doc) ->
- [];
ttest_ssocko_csocko_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_large_tcp6,
@@ -46805,7 +45248,7 @@ ttest_ssocko_csocko_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46818,10 +45261,6 @@ ttest_ssocko_csocko_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csocko_large_tcpL(suite) ->
- [];
-ttest_ssocko_csocko_large_tcpL(doc) ->
- [];
ttest_ssocko_csocko_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_large_tcpL,
@@ -46829,7 +45268,7 @@ ttest_ssocko_csocko_large_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -46842,10 +45281,6 @@ ttest_ssocko_csocko_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csockt_small_tcp4(suite) ->
- [];
-ttest_ssocko_csockt_small_tcp4(doc) ->
- [];
ttest_ssocko_csockt_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_small_tcp4,
@@ -46853,7 +45288,7 @@ ttest_ssocko_csockt_small_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46866,10 +45301,6 @@ ttest_ssocko_csockt_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csockt_small_tcp6(suite) ->
- [];
-ttest_ssocko_csockt_small_tcp6(doc) ->
- [];
ttest_ssocko_csockt_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_small_tcp6,
@@ -46877,7 +45308,7 @@ ttest_ssocko_csockt_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46890,10 +45321,6 @@ ttest_ssocko_csockt_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csockt_small_tcpL(suite) ->
- [];
-ttest_ssocko_csockt_small_tcpL(doc) ->
- [];
ttest_ssocko_csockt_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csocko_small_tcpL,
@@ -46901,7 +45328,7 @@ ttest_ssocko_csockt_small_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -46914,10 +45341,6 @@ ttest_ssocko_csockt_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csockt_medium_tcp4(suite) ->
- [];
-ttest_ssocko_csockt_medium_tcp4(doc) ->
- [];
ttest_ssocko_csockt_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_medium_tcp4,
@@ -46925,7 +45348,7 @@ ttest_ssocko_csockt_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46938,10 +45361,6 @@ ttest_ssocko_csockt_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csockt_medium_tcp6(suite) ->
- [];
-ttest_ssocko_csockt_medium_tcp6(doc) ->
- [];
ttest_ssocko_csockt_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_medium_tcp6,
@@ -46949,7 +45368,7 @@ ttest_ssocko_csockt_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46962,10 +45381,6 @@ ttest_ssocko_csockt_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csockt_medium_tcpL(suite) ->
- [];
-ttest_ssocko_csockt_medium_tcpL(doc) ->
- [];
ttest_ssocko_csockt_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_medium_tcpL,
@@ -46973,7 +45388,7 @@ ttest_ssocko_csockt_medium_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -46986,10 +45401,6 @@ ttest_ssocko_csockt_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssocko_csockt_large_tcp4(suite) ->
- [];
-ttest_ssocko_csockt_large_tcp4(doc) ->
- [];
ttest_ssocko_csockt_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_large_tcp4,
@@ -46997,7 +45408,7 @@ ttest_ssocko_csockt_large_tcp4(Config) when is_list(Config) ->
inet,
sock, once,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47010,10 +45421,6 @@ ttest_ssocko_csockt_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssocko_csockt_large_tcp6(suite) ->
- [];
-ttest_ssocko_csockt_large_tcp6(doc) ->
- [];
ttest_ssocko_csockt_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_large_tcp6,
@@ -47021,7 +45428,7 @@ ttest_ssocko_csockt_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, once,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47034,10 +45441,6 @@ ttest_ssocko_csockt_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssocko_csockt_large_tcpL(suite) ->
- [];
-ttest_ssocko_csockt_large_tcpL(doc) ->
- [];
ttest_ssocko_csockt_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssocko_csockt_large_tcpL,
@@ -47045,7 +45448,7 @@ ttest_ssocko_csockt_large_tcpL(Config) when is_list(Config) ->
local,
sock, once,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47058,10 +45461,6 @@ ttest_ssocko_csockt_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgenf_small_tcp4(suite) ->
- [];
-ttest_ssockt_cgenf_small_tcp4(doc) ->
- [];
ttest_ssockt_cgenf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgenf_small_tcp4,
@@ -47069,7 +45468,7 @@ ttest_ssockt_cgenf_small_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47082,10 +45481,6 @@ ttest_ssockt_cgenf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgenf_small_tcp6(suite) ->
- [];
-ttest_ssockt_cgenf_small_tcp6(doc) ->
- [];
ttest_ssockt_cgenf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgenf_small_tcp6,
@@ -47093,7 +45488,7 @@ ttest_ssockt_cgenf_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47106,10 +45501,6 @@ ttest_ssockt_cgenf_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgenf_medium_tcp4(suite) ->
- [];
-ttest_ssockt_cgenf_medium_tcp4(doc) ->
- [];
ttest_ssockt_cgenf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgenf_medium_tcp4,
@@ -47117,7 +45508,7 @@ ttest_ssockt_cgenf_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47130,10 +45521,6 @@ ttest_ssockt_cgenf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgenf_medium_tcp6(suite) ->
- [];
-ttest_ssockt_cgenf_medium_tcp6(doc) ->
- [];
ttest_ssockt_cgenf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgenf_medium_tcp6,
@@ -47141,7 +45528,7 @@ ttest_ssockt_cgenf_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47154,10 +45541,6 @@ ttest_ssockt_cgenf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgenf_large_tcp4(suite) ->
- [];
-ttest_ssockt_cgenf_large_tcp4(doc) ->
- [];
ttest_ssockt_cgenf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgenf_large_tcp4,
@@ -47165,7 +45548,7 @@ ttest_ssockt_cgenf_large_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47178,10 +45561,6 @@ ttest_ssockt_cgenf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgenf_large_tcp6(suite) ->
- [];
-ttest_ssockt_cgenf_large_tcp6(doc) ->
- [];
ttest_ssockt_cgenf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgenf_large_tcp6,
@@ -47189,7 +45568,7 @@ ttest_ssockt_cgenf_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47202,10 +45581,6 @@ ttest_ssockt_cgenf_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgeno_small_tcp4(suite) ->
- [];
-ttest_ssockt_cgeno_small_tcp4(doc) ->
- [];
ttest_ssockt_cgeno_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgeno_small_tcp4,
@@ -47213,7 +45588,7 @@ ttest_ssockt_cgeno_small_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47226,10 +45601,6 @@ ttest_ssockt_cgeno_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgeno_small_tcp6(suite) ->
- [];
-ttest_ssockt_cgeno_small_tcp6(doc) ->
- [];
ttest_ssockt_cgeno_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgeno_small_tcp6,
@@ -47237,7 +45608,7 @@ ttest_ssockt_cgeno_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47250,10 +45621,6 @@ ttest_ssockt_cgeno_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgeno_medium_tcp4(suite) ->
- [];
-ttest_ssockt_cgeno_medium_tcp4(doc) ->
- [];
ttest_ssockt_cgeno_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgeno_medium_tcp4,
@@ -47261,7 +45628,7 @@ ttest_ssockt_cgeno_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47274,10 +45641,6 @@ ttest_ssockt_cgeno_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgeno_medium_tcp6(suite) ->
- [];
-ttest_ssockt_cgeno_medium_tcp6(doc) ->
- [];
ttest_ssockt_cgeno_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgeno_medium_tcp6,
@@ -47285,7 +45648,7 @@ ttest_ssockt_cgeno_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47298,10 +45661,6 @@ ttest_ssockt_cgeno_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgeno_large_tcp4(suite) ->
- [];
-ttest_ssockt_cgeno_large_tcp4(doc) ->
- [];
ttest_ssockt_cgeno_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgeno_large_tcp4,
@@ -47309,7 +45668,7 @@ ttest_ssockt_cgeno_large_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47322,10 +45681,6 @@ ttest_ssockt_cgeno_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgeno_large_tcp6(suite) ->
- [];
-ttest_ssockt_cgeno_large_tcp6(doc) ->
- [];
ttest_ssockt_cgeno_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgeno_large_tcp6,
@@ -47333,7 +45688,7 @@ ttest_ssockt_cgeno_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47346,10 +45701,6 @@ ttest_ssockt_cgeno_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgent_small_tcp4(suite) ->
- [];
-ttest_ssockt_cgent_small_tcp4(doc) ->
- [];
ttest_ssockt_cgent_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgent_small_tcp4,
@@ -47357,7 +45708,7 @@ ttest_ssockt_cgent_small_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47370,10 +45721,6 @@ ttest_ssockt_cgent_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgent_small_tcp6(suite) ->
- [];
-ttest_ssockt_cgent_small_tcp6(doc) ->
- [];
ttest_ssockt_cgent_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgent_small_tcp6,
@@ -47381,7 +45728,7 @@ ttest_ssockt_cgent_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47394,10 +45741,6 @@ ttest_ssockt_cgent_small_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgent_medium_tcp4(suite) ->
- [];
-ttest_ssockt_cgent_medium_tcp4(doc) ->
- [];
ttest_ssockt_cgent_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgent_medium_tcp4,
@@ -47405,7 +45748,7 @@ ttest_ssockt_cgent_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47418,10 +45761,6 @@ ttest_ssockt_cgent_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgent_medium_tcp6(suite) ->
- [];
-ttest_ssockt_cgent_medium_tcp6(doc) ->
- [];
ttest_ssockt_cgent_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgent_medium_tcp6,
@@ -47429,7 +45768,7 @@ ttest_ssockt_cgent_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47442,10 +45781,6 @@ ttest_ssockt_cgent_medium_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_cgent_large_tcp4(suite) ->
- [];
-ttest_ssockt_cgent_large_tcp4(doc) ->
- [];
ttest_ssockt_cgent_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgent_large_tcp4,
@@ -47453,7 +45788,7 @@ ttest_ssockt_cgent_large_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47466,10 +45801,6 @@ ttest_ssockt_cgent_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_cgent_large_tcp6(suite) ->
- [];
-ttest_ssockt_cgent_large_tcp6(doc) ->
- [];
ttest_ssockt_cgent_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_cgent_large_tcp6,
@@ -47477,7 +45808,7 @@ ttest_ssockt_cgent_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
gen, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47490,10 +45821,6 @@ ttest_ssockt_cgent_large_tcp6(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csockf_small_tcp4(suite) ->
- [];
-ttest_ssockt_csockf_small_tcp4(doc) ->
- [];
ttest_ssockt_csockf_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_small_tcp4,
@@ -47501,7 +45828,7 @@ ttest_ssockt_csockf_small_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47514,10 +45841,6 @@ ttest_ssockt_csockf_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csockf_small_tcp6(suite) ->
- [];
-ttest_ssockt_csockf_small_tcp6(doc) ->
- [];
ttest_ssockt_csockf_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_small_tcp6,
@@ -47525,7 +45848,7 @@ ttest_ssockt_csockf_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47538,10 +45861,6 @@ ttest_ssockt_csockf_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csockf_small_tcpL(suite) ->
- [];
-ttest_ssockt_csockf_small_tcpL(doc) ->
- [];
ttest_ssockt_csockf_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_small_tcpL,
@@ -47549,7 +45868,7 @@ ttest_ssockt_csockf_small_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, false,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47562,10 +45881,6 @@ ttest_ssockt_csockf_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csockf_medium_tcp4(suite) ->
- [];
-ttest_ssockt_csockf_medium_tcp4(doc) ->
- [];
ttest_ssockt_csockf_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_medium_tcp4,
@@ -47573,7 +45888,7 @@ ttest_ssockt_csockf_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47586,10 +45901,6 @@ ttest_ssockt_csockf_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csockf_medium_tcp6(suite) ->
- [];
-ttest_ssockt_csockf_medium_tcp6(doc) ->
- [];
ttest_ssockt_csockf_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_medium_tcp6,
@@ -47597,7 +45908,7 @@ ttest_ssockt_csockf_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47610,10 +45921,6 @@ ttest_ssockt_csockf_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csockf_medium_tcpL(suite) ->
- [];
-ttest_ssockt_csockf_medium_tcpL(doc) ->
- [];
ttest_ssockt_csockf_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_medium_tcpL,
@@ -47621,7 +45928,7 @@ ttest_ssockt_csockf_medium_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, false,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47634,10 +45941,6 @@ ttest_ssockt_csockf_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csockf_large_tcp4(suite) ->
- [];
-ttest_ssockt_csockf_large_tcp4(doc) ->
- [];
ttest_ssockt_csockf_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_large_tcp4,
@@ -47645,7 +45948,7 @@ ttest_ssockt_csockf_large_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47658,10 +45961,6 @@ ttest_ssockt_csockf_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csockf_large_tcp6(suite) ->
- [];
-ttest_ssockt_csockf_large_tcp6(doc) ->
- [];
ttest_ssockt_csockf_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_large_tcp6,
@@ -47669,7 +45968,7 @@ ttest_ssockt_csockf_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47682,10 +45981,6 @@ ttest_ssockt_csockf_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csockf_large_tcpL(suite) ->
- [];
-ttest_ssockt_csockf_large_tcpL(doc) ->
- [];
ttest_ssockt_csockf_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockf_large_tcpL,
@@ -47693,7 +45988,7 @@ ttest_ssockt_csockf_large_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, false,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47706,10 +46001,6 @@ ttest_ssockt_csockf_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csocko_small_tcp4(suite) ->
- [];
-ttest_ssockt_csocko_small_tcp4(doc) ->
- [];
ttest_ssockt_csocko_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_small_tcp4,
@@ -47717,7 +46008,7 @@ ttest_ssockt_csocko_small_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47730,10 +46021,6 @@ ttest_ssockt_csocko_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csocko_small_tcp6(suite) ->
- [];
-ttest_ssockt_csocko_small_tcp6(doc) ->
- [];
ttest_ssockt_csocko_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_small_tcp6,
@@ -47741,7 +46028,7 @@ ttest_ssockt_csocko_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47754,10 +46041,6 @@ ttest_ssockt_csocko_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csocko_small_tcpL(suite) ->
- [];
-ttest_ssockt_csocko_small_tcpL(doc) ->
- [];
ttest_ssockt_csocko_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_small_tcpL,
@@ -47765,7 +46048,7 @@ ttest_ssockt_csocko_small_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, once,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47778,10 +46061,6 @@ ttest_ssockt_csocko_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csocko_medium_tcp4(suite) ->
- [];
-ttest_ssockt_csocko_medium_tcp4(doc) ->
- [];
ttest_ssockt_csocko_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_medium_tcp4,
@@ -47789,7 +46068,7 @@ ttest_ssockt_csocko_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47802,10 +46081,6 @@ ttest_ssockt_csocko_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csocko_medium_tcp6(suite) ->
- [];
-ttest_ssockt_csocko_medium_tcp6(doc) ->
- [];
ttest_ssockt_csocko_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_medium_tcp6,
@@ -47813,7 +46088,7 @@ ttest_ssockt_csocko_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47826,10 +46101,6 @@ ttest_ssockt_csocko_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csocko_medium_tcpL(suite) ->
- [];
-ttest_ssockt_csocko_medium_tcpL(doc) ->
- [];
ttest_ssockt_csocko_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_medium_tcpL,
@@ -47837,7 +46108,7 @@ ttest_ssockt_csocko_medium_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, once,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -47850,10 +46121,6 @@ ttest_ssockt_csocko_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csocko_large_tcp4(suite) ->
- [];
-ttest_ssockt_csocko_large_tcp4(doc) ->
- [];
ttest_ssockt_csocko_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_large_tcp4,
@@ -47861,7 +46128,7 @@ ttest_ssockt_csocko_large_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47874,10 +46141,6 @@ ttest_ssockt_csocko_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csocko_large_tcp6(suite) ->
- [];
-ttest_ssockt_csocko_large_tcp6(doc) ->
- [];
ttest_ssockt_csocko_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_large_tcp6,
@@ -47885,7 +46148,7 @@ ttest_ssockt_csocko_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47898,10 +46161,6 @@ ttest_ssockt_csocko_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csocko_large_tcpL(suite) ->
- [];
-ttest_ssockt_csocko_large_tcpL(doc) ->
- [];
ttest_ssockt_csocko_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_large_tcpL,
@@ -47909,7 +46168,7 @@ ttest_ssockt_csocko_large_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, once,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -47922,10 +46181,6 @@ ttest_ssockt_csocko_large_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csockt_small_tcp4(suite) ->
- [];
-ttest_ssockt_csockt_small_tcp4(doc) ->
- [];
ttest_ssockt_csockt_small_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_small_tcp4,
@@ -47933,7 +46188,7 @@ ttest_ssockt_csockt_small_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47946,10 +46201,6 @@ ttest_ssockt_csockt_small_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csockt_small_tcp6(suite) ->
- [];
-ttest_ssockt_csockt_small_tcp6(doc) ->
- [];
ttest_ssockt_csockt_small_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_small_tcp6,
@@ -47957,7 +46208,7 @@ ttest_ssockt_csockt_small_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47970,10 +46221,6 @@ ttest_ssockt_csockt_small_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csockt_small_tcpL(suite) ->
- [];
-ttest_ssockt_csockt_small_tcpL(doc) ->
- [];
ttest_ssockt_csockt_small_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csocko_small_tcpL,
@@ -47981,7 +46228,7 @@ ttest_ssockt_csockt_small_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, true,
- 1, 200).
+ 1, ttest_small_max_outstanding(Config)).
@@ -47994,10 +46241,6 @@ ttest_ssockt_csockt_small_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csockt_medium_tcp4(suite) ->
- [];
-ttest_ssockt_csockt_medium_tcp4(doc) ->
- [];
ttest_ssockt_csockt_medium_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_medium_tcp4,
@@ -48005,7 +46248,7 @@ ttest_ssockt_csockt_medium_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -48018,10 +46261,6 @@ ttest_ssockt_csockt_medium_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csockt_medium_tcp6(suite) ->
- [];
-ttest_ssockt_csockt_medium_tcp6(doc) ->
- [];
ttest_ssockt_csockt_medium_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_medium_tcp6,
@@ -48029,7 +46268,7 @@ ttest_ssockt_csockt_medium_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -48042,10 +46281,6 @@ ttest_ssockt_csockt_medium_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csockt_medium_tcpL(suite) ->
- [];
-ttest_ssockt_csockt_medium_tcpL(doc) ->
- [];
ttest_ssockt_csockt_medium_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_medium_tcpL,
@@ -48053,7 +46288,7 @@ ttest_ssockt_csockt_medium_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, true,
- 2, 20).
+ 2, ttest_medium_max_outstanding(Config)).
@@ -48066,10 +46301,6 @@ ttest_ssockt_csockt_medium_tcpL(Config) when is_list(Config) ->
%% Domain: inet
%%
-ttest_ssockt_csockt_large_tcp4(suite) ->
- [];
-ttest_ssockt_csockt_large_tcp4(doc) ->
- [];
ttest_ssockt_csockt_large_tcp4(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_large_tcp4,
@@ -48077,7 +46308,7 @@ ttest_ssockt_csockt_large_tcp4(Config) when is_list(Config) ->
inet,
sock, true,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -48090,10 +46321,6 @@ ttest_ssockt_csockt_large_tcp4(Config) when is_list(Config) ->
%% Domain: inet6
%%
-ttest_ssockt_csockt_large_tcp6(suite) ->
- [];
-ttest_ssockt_csockt_large_tcp6(doc) ->
- [];
ttest_ssockt_csockt_large_tcp6(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_large_tcp6,
@@ -48101,7 +46328,7 @@ ttest_ssockt_csockt_large_tcp6(Config) when is_list(Config) ->
inet6,
sock, true,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -48114,10 +46341,6 @@ ttest_ssockt_csockt_large_tcp6(Config) when is_list(Config) ->
%% Domain: local
%%
-ttest_ssockt_csockt_large_tcpL(suite) ->
- [];
-ttest_ssockt_csockt_large_tcpL(doc) ->
- [];
ttest_ssockt_csockt_large_tcpL(Config) when is_list(Config) ->
Runtime = which_ttest_runtime(Config),
ttest_tcp(ttest_ssockt_csockt_large_tcpL,
@@ -48125,7 +46348,7 @@ ttest_ssockt_csockt_large_tcpL(Config) when is_list(Config) ->
local,
sock, true,
sock, true,
- 3, 2).
+ 3, ttest_large_max_outstanding(Config)).
@@ -48195,10 +46418,12 @@ ttest_tcp(TC,
%% On darwin we seem to hit the system limit(s)
%% much earlier.
%% The tests "mostly" work, but random cases fail
- %% (even on reasonably powerfull machines),
+ %% (even on reasonably powerful machines),
%% so its much simpler to just skip on darwin...
has_support_unix_domain_socket(),
- is_not_darwin();
+ is_not_darwin();
+ (Domain =:= inet) ->
+ has_support_ipv4();
(Domain =:= inet6) ->
has_support_ipv6();
true -> ok
@@ -48208,6 +46433,17 @@ ttest_tcp(TC,
%% This may be overkill, depending on the runtime,
%% but better safe then sorry...
?TT(Runtime + ?SECS(60)),
+ ?P("Parameters: "
+ "~n Domain: ~p"
+ "~n Message ID: ~p"
+ "~n Max Outstanding: ~p"
+ "~n Running Time: ~p"
+ "~n Server Module: ~p"
+ "~n Server Active: ~p"
+ "~n Client Module: ~p"
+ "~n Client Active: ~p",
+ [Domain, MsgID, MaxOutstanding, Runtime,
+ ServerMod, ServerActive, ClientMod, ClientActive]),
InitState = #{domain => Domain,
msg_id => MsgID,
max_outstanding => MaxOutstanding,
@@ -48240,13 +46476,9 @@ ttest_tcp(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- case start_node(Host, server) of
- {ok, Node} ->
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(State) ->
+ {Peer, Node} = ?START_NODE("server"),
+ {ok, State#{peer => Peer, node => Node}}
end},
#{desc => "monitor server node",
cmd => fun(#{node := Node} = _State) ->
@@ -48261,6 +46493,9 @@ ttest_tcp(InitState) ->
case ttest_tcp_server_start(Node,
Domain, Mod, Active) of
{ok, {{Pid, _}, Path}} ->
+ ?SEV_IPRINT("server started: "
+ "~n Pid: ~p"
+ "~n Path: ~p", [Pid, Path]),
{ok, State#{rserver => Pid,
path => Path}};
{error, _} = ERROR ->
@@ -48273,6 +46508,11 @@ ttest_tcp(InitState) ->
case ttest_tcp_server_start(Node,
Domain, Mod, Active) of
{ok, {{Pid, _}, {Addr, Port}}} ->
+ ?SEV_IPRINT("server started: "
+ "~n Pid: ~p"
+ "~n Addr: ~p"
+ "~n Port: ~p",
+ [Pid, Addr, Port]),
{ok, State#{rserver => Pid,
addr => Addr,
port => Port}};
@@ -48301,8 +46541,11 @@ ttest_tcp(InitState) ->
case ?SEV_AWAIT_TERMINATE(Tester, tester,
[{rserver, RServer}]) of
ok ->
+ ?SEV_IPRINT("received termination request"),
{ok, maps:remove(tester, State)};
- {error, _} = ERROR ->
+ {error, Reason} = ERROR ->
+ ?SEV_EPRINT("received unexpected error: "
+ "~n ~p", [Reason]),
ERROR
end
end},
@@ -48321,9 +46564,9 @@ ttest_tcp(InitState) ->
{ok, State1}
end},
#{desc => "stop (server) node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -48366,11 +46609,17 @@ ttest_tcp(InitState) ->
cmd => fun(#{domain := local} = State) ->
{Tester, ServerPath} =
?SEV_AWAIT_START(),
+ ?SEV_IPRINT("started with server info: "
+ "~n Path: ~p", [ServerPath]),
{ok, State#{tester => Tester,
server_path => ServerPath}};
(State) ->
{Tester, {ServerAddr, ServerPort}} =
?SEV_AWAIT_START(),
+ ?SEV_IPRINT("started with server info: "
+ "~n Addr: ~p"
+ "~n Port: ~p",
+ [ServerAddr, ServerPort]),
{ok, State#{tester => Tester,
server_addr => ServerAddr,
server_port => ServerPort}}
@@ -48384,13 +46633,13 @@ ttest_tcp(InitState) ->
%% *** Init part ***
#{desc => "create node",
- cmd => fun(#{host := Host} = State) ->
- case start_node(Host, client) of
- {ok, Node} ->
- {ok, State#{node => Node}};
- {error, Reason} ->
- {skip, Reason}
- end
+ cmd => fun(#{host := _Host} = State) ->
+ %% Because peer does not accept a host argument,
+ %% we can no longer start "remote" nodes...
+ %% Not that we actually did that. We always
+ %% used local-host.
+ {Peer, Node} = ?START_NODE("client"),
+ {ok, State#{peer => Peer, node => Node}}
end},
#{desc => "monitor client node",
cmd => fun(#{node := Node} = _State) ->
@@ -48497,9 +46746,9 @@ ttest_tcp(InitState) ->
end
end},
#{desc => "stop (client) node",
- cmd => fun(#{node := Node} = State) ->
+ cmd => fun(#{peer := Peer} = State) ->
{ok,
- try stop_node(Node) of
+ try peer:stop(Peer) of
ok ->
State#{node_stop => ok};
{error, Reason} ->
@@ -48831,7 +47080,7 @@ ttest_report(Domain,
bytes = NumBytes,
msgs = NumMsgs},
%% If we run just one test case, the group init has never been run
- %% and therefor the ttest manager is not running (we also don't actually
+ %% and therefore the ttest manager is not running (we also don't actually
%% care about collecting reports in that case).
(catch global:send(?TTEST_MANAGER, Report)),
ok.
@@ -48978,13 +47227,10 @@ which_ttest_reports(Domain, MsgID) ->
%% Create several acceptor processes (processes that calls socket:accept/1)
%% and then a couple of clients connects to them without any problems.
%% TCP, IPv4.
-otp16359_maccept_tcp4(suite) ->
- [];
-otp16359_maccept_tcp4(doc) ->
- [];
otp16359_maccept_tcp4(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(otp16359_maccept_tcp4,
+ fun() -> has_support_ipv4() end,
fun() ->
InitState = #{domain => inet,
protocol => tcp},
@@ -48997,10 +47243,6 @@ otp16359_maccept_tcp4(_Config) when is_list(_Config) ->
%% Create several acceptor processes (processes that calls socket:accept/1)
%% and then a couple of clients connects to them without any problems.
%% TCP, IPv6.
-otp16359_maccept_tcp6(suite) ->
- [];
-otp16359_maccept_tcp6(doc) ->
- [];
otp16359_maccept_tcp6(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(otp16359_maccept_tcp6,
@@ -49017,10 +47259,6 @@ otp16359_maccept_tcp6(_Config) when is_list(_Config) ->
%% Create several acceptor processes (processes that calls socket:accept/1)
%% and then a couple of clients connects to them without any problems.
%% TCP, UNix Domain Sockets.
-otp16359_maccept_tcpL(suite) ->
- [];
-otp16359_maccept_tcpL(doc) ->
- [];
otp16359_maccept_tcpL(_Config) when is_list(_Config) ->
?TT(?SECS(10)),
tc_try(otp16359_maccept_tcpL,
@@ -49635,66 +47873,165 @@ otp16359_maccept_tcp(InitState) ->
Tester]).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% This test case is to verify that we do not leak monitors.
+otp18240_accept_mon_leak_tcp4(Config) when is_list(Config) ->
+ ?TT(?SECS(10)),
+ tc_try(?FUNCTION_NAME,
+ fun() -> has_support_ipv4() end,
+ fun() ->
+ InitState = #{domain => inet,
+ protocol => tcp,
+ num_socks => 10},
+ ok = otp18240_accept_tcp(InitState)
+ end).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% This mechanism has only one purpose: So that we are able to kill
-%% the node-starter process if it takes to long. The node-starter
-%% runs on the local node.
-%% This crapola is hopefully temporary, but we have seen that on
-%% some platforms the ct_slave:start simply hangs.
--define(NODE_START_TIMEOUT, 10000).
-start_node(Host, NodeName) ->
- start_node(Host, NodeName, ?NODE_START_TIMEOUT).
+%% This test case is to verify that we do not leak monitors.
+otp18240_accept_mon_leak_tcp6(Config) when is_list(Config) ->
+ ?TT(?SECS(10)),
+ tc_try(?FUNCTION_NAME,
+ fun() -> has_support_ipv6() end,
+ fun() ->
+ InitState = #{domain => inet6,
+ protocol => tcp,
+ num_socks => 10},
+ ok = otp18240_accept_tcp(InitState)
+ end).
+
-start_node(Host, NodeName, Timeout) ->
- {NodeStarter, _} =
- spawn_monitor(fun() -> exit(start_unique_node(Host, NodeName)) end),
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+otp18240_accept_tcp(#{domain := Domain,
+ protocol := Proto,
+ num_socks := NumSocks}) ->
+ Self = self(),
+ {Pid, Mon} = spawn_monitor(fun() ->
+ otp18240_acceptor(Self,
+ Domain, Proto,
+ NumSocks)
+ end),
+ otp18240_await_acceptor(Pid, Mon).
+
+otp18240_await_acceptor(Pid, Mon) ->
receive
- {'DOWN', _, process, NodeStarter, Result} ->
- %% i("Node Starter (~p) reported: ~p", [NodeStarter, Result]),
- Result
- after Timeout ->
- exit(NodeStarter, kill),
- {error, {failed_starting_node, NodeName, timeout}}
+ {'DOWN', Mon, process, Pid, Info} ->
+ i("acceptor terminated: "
+ "~n ~p", [Info])
+ after 5000 ->
+ i("acceptor info"
+ "~n Refs: ~p"
+ "~n Info: ~p",
+ [monitored_by(Pid), erlang:process_info(Pid)]),
+ otp18240_await_acceptor(Pid, Mon)
end.
-start_unique_node(Host, NodeName) ->
- UniqueNodeName = f("~w_~w", [NodeName, erlang:system_time(millisecond)]),
- case do_start_node(Host, UniqueNodeName) of
- {ok, _} = OK ->
- global:sync(),
- %% i("Node ~p started: "
- %% "~n Nodes: ~p"
- %% "~n Logger: ~p"
- %% "~n Global Names: ~p",
- %% [NodeName, nodes(),
- %% global:whereis_name(socket_test_logger),
- %% global:registered_names()]),
- OK;
- {error, Reason, _} ->
- {error, Reason}
+otp18240_acceptor(Parent, Domain, Proto, NumSocks) ->
+ i("[acceptor] begin with: "
+ "~n Domain: ~p"
+ "~n Protocol: ~p", [Domain, Proto]),
+ MonitoredBy0 = monitored_by(),
+ {ok, LSock} = socket:open(Domain, stream, Proto,
+ #{use_registry => false}),
+ ok = socket:bind(LSock, #{family => Domain, port => 0, addr => any}),
+ ok = socket:listen(LSock, NumSocks),
+ MonitoredBy1 = monitored_by(),
+ [LSockMon] = MonitoredBy1 -- MonitoredBy0,
+ i("[acceptor]: listen socket created"
+ "~n Montored By before listen socket: ~p"
+ "~n Montored By after listen socket: ~p"
+ "~n Listen Socket Monitor: ~p"
+ "~n Listen Socket info: ~p",
+ [MonitoredBy0, MonitoredBy1, LSockMon, socket:info(LSock)]),
+
+ {ok, #{port := Port}} = socket:sockname(LSock),
+
+ i("[acceptor] create ~w clients (connectors)", [NumSocks]),
+ _Clients = [spawn_link(fun() ->
+ otp18240_client(CID,
+ Domain, Proto,
+ Port)
+ end) || CID <- lists:seq(1, NumSocks)],
+
+ i("[acceptor] accept ~w connections", [NumSocks]),
+ ServSocks = [otp18240_do_accept(AID, LSock) ||
+ AID <- lists:seq(1, NumSocks)],
+
+ i("[acceptor] close accepted connections when: "
+ "~n Listen Socket info: ~p", [socket:info(LSock)]),
+ _ = [otp18240_do_close(S) || S <- ServSocks],
+
+ %% at this point in time there should be no monitors from NIFs,
+ %% because we're not accepting anything
+ i("[acceptor] check monitor status"),
+ MonitoredBy2 = monitored_by(),
+ MonitoredBy3 = MonitoredBy2 -- [Parent, LSockMon],
+ i("[acceptor] monitor status: "
+ "~n UnRefs: ~p"
+ "~n MonitoredBy2: ~p"
+ "~n MonitoredBy3: ~p",
+ [[Parent, LSockMon], MonitoredBy2, MonitoredBy3]),
+ if
+ ([] =:= MonitoredBy3) ->
+ i("[acceptor] done"),
+ socket:close(LSock),
+ exit(ok);
+ true ->
+ socket:close(LSock),
+ i("[acceptor] Unexpected monitors: "
+ "~n ~p", [MonitoredBy2]),
+ exit({unexpected_monitors, MonitoredBy2})
end.
-do_start_node(Host, NodeName) when is_list(NodeName) ->
- do_start_node(Host, list_to_atom(NodeName));
-do_start_node(Host, NodeName) when is_atom(NodeName) ->
- Dir = filename:dirname(code:which(?MODULE)),
- Flags = "-pa " ++ Dir,
- Opts = [{monitor_master, true}, {erl_flags, Flags}],
- ct_slave:start(Host, NodeName, Opts).
+
+otp18240_client(ID, Domain, Proto, PortNo) ->
+ i("[connector ~w] try create connector socket", [ID]),
+ {ok, Sock} = socket:open(Domain, stream, Proto, #{use_registry => false}),
+ ok = socket:bind(Sock, #{family => Domain, port => 0, addr => any}),
+ %% ok = socket:setopt(Sock, otp, debug, true),
+ i("[connector ~w] try connect", [ID]),
+ ok = socket:connect(Sock, #{family => Domain, addr => any, port => PortNo}),
+ i("[connector ~w] connected - now try recv", [ID]),
+ case socket:recv(Sock) of
+ {ok, Data} ->
+ i("[connector ~w] received unexpected data: "
+ "~n ~p", [ID, Data]),
+ (catch socket:close(Sock)),
+ exit('unexpected data');
+ {error, closed} ->
+ i("[connector ~w] expected socket close", [ID]);
+ {error, Reason} ->
+ i("[connector ~w] unexpected error when reading: "
+ "~n ~p", [ID, Reason]),
+ (catch socket:close(Sock))
+ end,
+ i("[connector ~w] done", [ID]),
+ ok.
-stop_node(Node) ->
- case ct_slave:stop(Node) of
- {ok, _} ->
- ok;
- {error, _} = ERROR ->
- ERROR
+otp18240_do_accept(ID, LSock) ->
+ i("[acceptor ~w] try accept", [ID]),
+ {ok, Sock} = socket:accept(LSock),
+ i("[acceptor ~w] accepted: ~p", [ID, Sock]),
+ {ID, Sock}.
+
+
+otp18240_do_close({ID, Sock}) ->
+ i("[acceptor ~w] try close ~p", [ID, Sock]),
+ case socket:close(Sock) of
+ ok ->
+ i("[acceptor ~w] socket closed", [ID]),
+ ok;
+ {error, Reason} ->
+ i("[acceptor ~w] failed close socket: "
+ "~n ~p", [ID, Reason]),
+ error
end.
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -49789,7 +48126,7 @@ ensure_unique_path(Path) ->
ensure_unique_path(Path, 1);
{error, _} ->
%% We assume this means it does not exist yet...
- %% If we have several process in paralell trying to create
+ %% If we have several process in parallel trying to create
%% (unique) path's, then we are in trouble. To *really* be
%% on the safe side we should have a (central) path registry...
encode_path(Path)
@@ -49837,6 +48174,14 @@ which_local_addr(Domain) ->
?LIB:which_local_addr(Domain).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+monitored_by() ->
+ monitored_by(self()).
+monitored_by(Pid) ->
+ {monitored_by, Refs} = erlang:process_info(Pid, monitored_by),
+ Refs.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -49878,6 +48223,7 @@ has_support_sock_bindtodevice() ->
has_support_socket_option_sock(bindtodevice).
has_support_sock_broadcast() ->
+ has_support_ipv4(),
has_support_socket_option_sock(broadcast),
case ?LIB:which_local_host_info(inet) of
{ok, #{flags := Flags}} ->
@@ -50180,11 +48526,24 @@ has_support_sctp() ->
%% The idea is that this function shall test if the test host has
-%% support for IPv6. If not, there is no point in running IPv6 tests.
+%% support for IPv4 or IPv6. If not, there is no point in running corresponding tests.
%% Currently we just skip.
+has_support_ipv4() ->
+ ?LIB:has_support_ipv4().
+
has_support_ipv6() ->
?LIB:has_support_ipv6().
+inet_or_inet6() ->
+ try
+ has_support_ipv4(),
+ inet
+ catch
+ throw:{skip, _Reason} ->
+ has_support_ipv6(),
+ inet6
+ end.
+
has_support_sendfile() ->
try socket:is_supported(sendfile) of
true ->
@@ -50409,19 +48768,19 @@ tc_try(Case, TCCondFun, TCFun)
end
catch
C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
- %% i("catched[tc] (skip): "
+ %% i("caught[tc] (skip): "
%% "~n C: ~p"
%% "~n SKIP: ~p"
%% "~n", [C, SKIP]),
- tc_end( f("skipping(catched,~w,tc)", [C]) ),
+ tc_end( f("skipping(caught,~w,tc)", [C]) ),
SKIP;
C:E:S ->
- %% i("catched[tc]: "
+ %% i("caught[tc]: "
%% "~n C: ~p"
%% "~n E: ~p"
%% "~n S: ~p"
%% "~n", [C, E, S]),
- tc_end( f("failed(catched,~w,tc)", [C]) ),
+ tc_end( f("failed(caught,~w,tc)", [C]) ),
erlang:raise(C, E, S)
end;
{skip, _} = SKIP ->
@@ -50432,19 +48791,19 @@ tc_try(Case, TCCondFun, TCFun)
exit({tc_cond_failed, Reason})
catch
C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
- %% i("catched[cond] (skip): "
+ %% i("caught[cond] (skip): "
%% "~n C: ~p"
%% "~n SKIP: ~p"
%% "~n", [C, SKIP]),
- tc_end( f("skipping(catched,~w,cond)", [C]) ),
+ tc_end( f("skipping(caught,~w,cond)", [C]) ),
SKIP;
C:E:S ->
- %% i("catched[cond]: "
+ %% i("caught[cond]: "
%% "~n C: ~p"
%% "~n E: ~p"
%% "~n S: ~p"
%% "~n", [C, E, S]),
- tc_end( f("failed(catched,~w,cond)", [C]) ),
+ tc_end( f("failed(caught,~w,cond)", [C]) ),
erlang:raise(C, E, S)
end.
@@ -50472,1020 +48831,32 @@ tc_which_name() ->
end.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% This function prints various host info, which might be usefull
-%% when analyzing the test suite (results).
-%% It also returns a "factor" that can be used when deciding
-%% the load for some test cases (traffic). Such as run time or
-%% number of iterations. This only works for some OSes (linux).
-%% Also, mostly it just returns the factor 1.
-%% At this time we just look at BogoMIPS!
-analyze_and_print_host_info() ->
- {OsFam, OsName} = os:type(),
- Version =
- case os:version() of
- {Maj, Min, Rel} ->
- f("~w.~w.~w", [Maj, Min, Rel]);
- VStr ->
- VStr
- end,
- case {OsFam, OsName} of
- {unix, linux} ->
- analyze_and_print_linux_host_info(Version);
- {unix, openbsd} ->
- analyze_and_print_openbsd_host_info(Version);
- {unix, freebsd} ->
- analyze_and_print_freebsd_host_info(Version);
- {unix, netbsd} ->
- analyze_and_print_netbsd_host_info(Version);
- {unix, sunos} ->
- analyze_and_print_solaris_host_info(Version);
- {win32, nt} ->
- analyze_and_print_win_host_info(Version);
- _ ->
- io:format("OS Family: ~p"
- "~n OS Type: ~p"
- "~n Version: ~p"
- "~n Num Schedulers: ~s"
- "~n", [OsFam, OsName, Version, str_num_schedulers()]),
- num_schedulers_to_factor()
- end.
-
-str_num_schedulers() ->
- try erlang:system_info(schedulers) of
- N -> f("~w", [N])
- catch
- _:_:_ -> "-"
- end.
-
-num_schedulers_to_factor() ->
- try erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- N when (N =< 6) ->
- 2;
- _ ->
- 1
- catch
- _:_:_ ->
- 10
- end.
-
-
-
-%% --- Linux ---
-
-linux_which_distro(Version) ->
- case file:read_file_info("/etc/issue") of
- {ok, _} ->
- case [string:trim(S) ||
- S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
- [DistroStr|_] ->
- io:format("Linux: ~s"
- "~n ~s"
- "~n",
- [Version, DistroStr]),
- case DistroStr of
- "Wind River Linux" ++ _ ->
- wind_river;
- "MontaVista" ++ _ ->
- montavista;
- "Yellow Dog" ++ _ ->
- yellow_dog;
- _ ->
- other
- end;
- X ->
- io:format("Linux: ~s"
- "~n ~p"
- "~n",
- [Version, X]),
- other
- end;
- _ ->
- io:format("Linux: ~s"
- "~n", [Version]),
- other
- end.
-
-
-analyze_and_print_linux_host_info(Version) ->
- Distro = linux_which_distro(Version),
- Factor =
- case (catch linux_which_cpuinfo(Distro)) of
- {ok, {CPU, BogoMIPS}} ->
- io:format("CPU: "
- "~n Model: ~s"
- "~n BogoMIPS: ~w"
- "~n Num Schedulers: ~s"
- "~n", [CPU, BogoMIPS, str_num_schedulers()]),
- if
- (BogoMIPS > 20000) ->
- 1;
- (BogoMIPS > 10000) ->
- 2;
- (BogoMIPS > 5000) ->
- 3;
- (BogoMIPS > 2000) ->
- 5;
- (BogoMIPS > 1000) ->
- 8;
- true ->
- 10
- end;
- {ok, CPU} ->
- io:format("CPU: "
- "~n Model: ~s"
- "~n Num Schedulers: ~s"
- "~n", [CPU, str_num_schedulers()]),
- num_schedulers_to_factor();
- _ ->
- 5
- end,
- %% Check if we need to adjust the factor because of the memory
- try linux_which_meminfo() of
- AddFactor ->
- Factor + AddFactor
- catch
- _:_:_ ->
- Factor
- end.
-
-
-linux_cpuinfo_lookup(Key) when is_list(Key) ->
- linux_info_lookup(Key, "/proc/cpuinfo").
-
-linux_cpuinfo_cpu() ->
- case linux_cpuinfo_lookup("cpu") of
- [Model] ->
- Model;
- _ ->
- "-"
- end.
-
-linux_cpuinfo_motherboard() ->
- case linux_cpuinfo_lookup("motherboard") of
- [MB] ->
- MB;
- _ ->
- "-"
- end.
-
-linux_cpuinfo_bogomips() ->
- case linux_cpuinfo_lookup("bogomips") of
- BMips when is_list(BMips) ->
- try lists:sum([bogomips_to_int(BM) || BM <- BMips])
- catch
- _:_:_ ->
- "-"
- end;
- _ ->
- "-"
- end.
-
-linux_cpuinfo_total_bogomips() ->
- case linux_cpuinfo_lookup("total bogomips") of
- [TBM] ->
- try bogomips_to_int(TBM)
- catch
- _:_:_ ->
- "-"
- end;
- _ ->
- "-"
- end.
-
-bogomips_to_int(BM) ->
- try list_to_float(BM) of
- F ->
- floor(F)
- catch
- _:_:_ ->
- try list_to_integer(BM) of
- I ->
- I
- catch
- _:_:_ ->
- throw(noinfo)
- end
- end.
-
-linux_cpuinfo_model() ->
- case linux_cpuinfo_lookup("model") of
- [M] ->
- M;
- _ ->
- "-"
- end.
-
-linux_cpuinfo_platform() ->
- case linux_cpuinfo_lookup("platform") of
- [P] ->
- P;
- _ ->
- "-"
- end.
-
-linux_cpuinfo_model_name() ->
- case linux_cpuinfo_lookup("model name") of
- [P|_] ->
- P;
- _X ->
- "-"
- end.
-
-linux_cpuinfo_processor() ->
- case linux_cpuinfo_lookup("Processor") of
- [P] ->
- P;
- _ ->
- "-"
- end.
-
-linux_which_cpuinfo(montavista) ->
- CPU =
- case linux_cpuinfo_cpu() of
- "-" ->
- throw(noinfo);
- Model ->
- case linux_cpuinfo_motherboard() of
- "-" ->
- Model;
- MB ->
- Model ++ " (" ++ MB ++ ")"
- end
- end,
- case linux_cpuinfo_bogomips() of
- "-" ->
- {ok, CPU};
- BMips ->
- {ok, {CPU, BMips}}
- end;
-
-linux_which_cpuinfo(yellow_dog) ->
- CPU =
- case linux_cpuinfo_cpu() of
- "-" ->
- throw(noinfo);
- Model ->
- case linux_cpuinfo_motherboard() of
- "-" ->
- Model;
- MB ->
- Model ++ " (" ++ MB ++ ")"
- end
- end,
- {ok, CPU};
-
-linux_which_cpuinfo(wind_river) ->
- CPU =
- case linux_cpuinfo_model() of
- "-" ->
- throw(noinfo);
- Model ->
- case linux_cpuinfo_platform() of
- "-" ->
- Model;
- Platform ->
- Model ++ " (" ++ Platform ++ ")"
- end
- end,
- case linux_cpuinfo_total_bogomips() of
- "-" ->
- {ok, CPU};
- BMips ->
- {ok, {CPU, BMips}}
- end;
-
-linux_which_cpuinfo(other) ->
- %% Check for x86 (Intel or AMD)
- CPU =
- case linux_cpuinfo_model_name() of
- "-" ->
- %% ARM (at least some distros...)
- case linux_cpuinfo_processor() of
- "-" ->
- %% Ok, we give up
- throw(noinfo);
- Proc ->
- Proc
- end;
- ModelName ->
- ModelName
- end,
- case linux_cpuinfo_bogomips() of
- "-" ->
- {ok, CPU};
- BMips ->
- {ok, {CPU, BMips}}
- end.
-
-linux_meminfo_lookup(Key) when is_list(Key) ->
- linux_info_lookup(Key, "/proc/meminfo").
-
-linux_meminfo_memtotal() ->
- case linux_meminfo_lookup("MemTotal") of
- [X] ->
- X;
- _ ->
- "-"
- end.
-
-%% We *add* the value this return to the Factor.
-linux_which_meminfo() ->
- case linux_meminfo_memtotal() of
- "-" ->
- 0;
- MemTotal ->
- io:format("Memory:"
- "~n ~s"
- "~n", [MemTotal]),
- case string:tokens(MemTotal, [$ ]) of
- [MemSzStr, MemUnit] ->
- MemSz2 = list_to_integer(MemSzStr),
- MemSz3 =
- case string:to_lower(MemUnit) of
- "kb" ->
- MemSz2;
- "mb" ->
- MemSz2*1024;
- "gb" ->
- MemSz2*1024*1024;
- _ ->
- throw(noinfo)
- end,
- if
- (MemSz3 >= 8388608) ->
- 0;
- (MemSz3 >= 4194304) ->
- 1;
- (MemSz3 >= 2097152) ->
- 3;
- true ->
- 5
- end;
- _X ->
- 0
- end
- end.
-
-
-linux_info_lookup(Key, File) ->
- try [string:trim(S) || S <- string:tokens(os:cmd("grep " ++ "\"" ++ Key ++ "\"" ++ " " ++ File), [$:,$\n])] of
- Info ->
- linux_info_lookup_collect(Key, Info, [])
- catch
- _:_:_ ->
- "-"
- end.
-
-linux_info_lookup_collect(_Key, [], Values) ->
- lists:reverse(Values);
-linux_info_lookup_collect(Key, [Key, Value|Rest], Values) ->
- linux_info_lookup_collect(Key, Rest, [Value|Values]);
-linux_info_lookup_collect(_, _, Values) ->
- lists:reverse(Values).
-
-
-%% --- OpenBSD ---
-
-%% Just to be clear: This is ***not*** scientific...
-analyze_and_print_openbsd_host_info(Version) ->
- io:format("OpenBSD:"
- "~n Version: ~p"
- "~n", [Version]),
- Extract =
- fun(Key) ->
- string:tokens(string:trim(os:cmd("sysctl " ++ Key)), [$=])
- end,
- try
- begin
- CPU =
- case Extract("hw.model") of
- ["hw.model", Model] ->
- string:trim(Model);
- _ ->
- "-"
- end,
- CPUSpeed =
- case Extract("hw.cpuspeed") of
- ["hw.cpuspeed", Speed] ->
- list_to_integer(Speed);
- _ ->
- -1
- end,
- NCPU =
- case Extract("hw.ncpufound") of
- ["hw.ncpufound", N] ->
- list_to_integer(N);
- _ ->
- -1
- end,
- Memory =
- case Extract("hw.physmem") of
- ["hw.physmem", PhysMem] ->
- list_to_integer(PhysMem) div 1024;
- _ ->
- -1
- end,
- io:format("CPU:"
- "~n Model: ~s"
- "~n Speed: ~w"
- "~n N: ~w"
- "~nMemory:"
- "~n ~w KB"
- "~n", [CPU, CPUSpeed, NCPU, Memory]),
- CPUFactor =
- if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
- if
- (NCPU >= 4) ->
- 1;
- (NCPU >= 2) ->
- 2;
- true ->
- 3
- end;
- true ->
- if
- (NCPU >= 4) ->
- 2;
- (NCPU >= 2) ->
- 3;
- true ->
- 4
- end
- end,
- MemAddFactor =
- if
- (Memory =:= -1) ->
- 0;
- (Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
- 1;
- (Memory >= 2097152) ->
- 2;
- true ->
- 3
- end,
- CPUFactor + MemAddFactor
- end
- catch
- _:_:_ ->
- 1
- end.
-
-
-%% --- FreeBSD ---
-
-analyze_and_print_freebsd_host_info(Version) ->
- io:format("FreeBSD:"
- "~n Version: ~p"
- "~n", [Version]),
- %% This test require that the program 'sysctl' is in the path.
- %% First test with 'which sysctl', if that does not work
- %% try with 'which /sbin/sysctl'. If that does not work either,
- %% we skip the test...
- try
- begin
- SysCtl =
- case string:trim(os:cmd("which sysctl")) of
- [] ->
- case string:trim(os:cmd("which /sbin/sysctl")) of
- [] ->
- throw(sysctl);
- SC2 ->
- SC2
- end;
- SC1 ->
- SC1
- end,
- Extract =
- fun(Key) ->
- string:tokens(string:trim(os:cmd(SysCtl ++ " " ++ Key)),
- [$:])
- end,
- CPU = analyze_freebsd_cpu(Extract),
- CPUSpeed = analyze_freebsd_cpu_speed(Extract),
- NCPU = analyze_freebsd_ncpu(Extract),
- Memory = analyze_freebsd_memory(Extract),
- io:format("CPU:"
- "~n Model: ~s"
- "~n Speed: ~w"
- "~n N: ~w"
- "~n Num Schedulers: ~w"
- "~nMemory:"
- "~n ~w KB"
- "~n",
- [CPU, CPUSpeed, NCPU,
- erlang:system_info(schedulers), Memory]),
- CPUFactor =
- if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
- if
- (NCPU >= 4) ->
- 1;
- (NCPU >= 2) ->
- 2;
- true ->
- 3
- end;
- true ->
- if
- (NCPU =:= -1) ->
- 1;
- (NCPU >= 4) ->
- 2;
- (NCPU >= 2) ->
- 3;
- true ->
- 4
- end
- end,
- MemAddFactor =
- if
- (Memory =:= -1) ->
- 0;
- (Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
- 1;
- (Memory >= 2097152) ->
- 2;
- true ->
- 3
- end,
- CPUFactor + MemAddFactor
- end
- catch
- _:_:_ ->
- io:format("CPU:"
- "~n Num Schedulers: ~w"
- "~n", [erlang:system_info(schedulers)]),
- case erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- _ ->
- 2
- end
- end.
-
-analyze_freebsd_cpu(Extract) ->
- analyze_freebsd_item(Extract, "hw.model", fun(X) -> X end, "-").
-
-analyze_freebsd_cpu_speed(Extract) ->
- analyze_freebsd_item(Extract,
- "hw.clockrate",
- fun(X) -> list_to_integer(X) end,
- -1).
-
-analyze_freebsd_ncpu(Extract) ->
- analyze_freebsd_item(Extract,
- "hw.ncpu",
- fun(X) -> list_to_integer(X) end,
- -1).
-
-analyze_freebsd_memory(Extract) ->
- analyze_freebsd_item(Extract,
- "hw.physmem",
- fun(X) -> list_to_integer(X) div 1024 end,
- -1).
-
-analyze_freebsd_item(Extract, Key, Process, Default) ->
- try
- begin
- case Extract(Key) of
- [Key, Model] ->
- Process(string:trim(Model));
- _ ->
- Default
- end
- end
- catch
- _:_:_ ->
- Default
- end.
-
-
-%% --- NetBSD ---
-
-analyze_and_print_netbsd_host_info(Version) ->
- io:format("NetBSD:"
- "~n Version: ~p"
- "~n", [Version]),
- %% This test require that the program 'sysctl' is in the path.
- %% First test with 'which sysctl', if that does not work
- %% try with 'which /sbin/sysctl'. If that does not work either,
- %% we skip the test...
- try
- begin
- SysCtl =
- case string:trim(os:cmd("which sysctl")) of
- [] ->
- case string:trim(os:cmd("which /sbin/sysctl")) of
- [] ->
- throw(sysctl);
- SC2 ->
- SC2
- end;
- SC1 ->
- SC1
- end,
- Extract =
- fun(Key) ->
- [string:trim(S) ||
- S <-
- string:tokens(string:trim(os:cmd(SysCtl ++ " " ++ Key)),
- [$=])]
- end,
- CPU = analyze_netbsd_cpu(Extract),
- Machine = analyze_netbsd_machine(Extract),
- Arch = analyze_netbsd_machine_arch(Extract),
- CPUSpeed = analyze_netbsd_cpu_speed(Extract),
- NCPU = analyze_netbsd_ncpu(Extract),
- Memory = analyze_netbsd_memory(Extract),
- io:format("CPU:"
- "~n Model: ~s (~s, ~s)"
- "~n Speed: ~w MHz"
- "~n N: ~w"
- "~n Num Schedulers: ~w"
- "~nMemory:"
- "~n ~w KB"
- "~n",
- [CPU, Machine, Arch, CPUSpeed, NCPU,
- erlang:system_info(schedulers), Memory]),
- CPUFactor =
- if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
- if
- (NCPU >= 4) ->
- 1;
- (NCPU >= 2) ->
- 2;
- true ->
- 3
- end;
- true ->
- if
- (NCPU =:= -1) ->
- 1;
- (NCPU >= 4) ->
- 2;
- (NCPU >= 2) ->
- 3;
- true ->
- 4
- end
- end,
- MemAddFactor =
- if
- (Memory =:= -1) ->
- 0;
- (Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
- 1;
- (Memory >= 2097152) ->
- 2;
- true ->
- 3
- end,
- CPUFactor + MemAddFactor
- end
- catch
- _:_:_ ->
- io:format("CPU:"
- "~n Num Schedulers: ~w"
- "~n", [erlang:system_info(schedulers)]),
- case erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- _ ->
- 2
- end
- end.
-
-analyze_netbsd_cpu(Extract) ->
- analyze_netbsd_item(Extract, "hw.model", fun(X) -> X end, "-").
-
-analyze_netbsd_machine(Extract) ->
- analyze_netbsd_item(Extract, "hw.machine", fun(X) -> X end, "-").
-
-analyze_netbsd_machine_arch(Extract) ->
- analyze_netbsd_item(Extract, "hw.machine_arch", fun(X) -> X end, "-").
-
-analyze_netbsd_cpu_speed(Extract) ->
- analyze_netbsd_item(Extract, "machdep.dmi.processor-frequency",
- fun(X) -> case string:tokens(X, [$\ ]) of
- [MHz, "MHz"] ->
- list_to_integer(MHz);
- _ ->
- -1
- end
- end, "-").
-
-analyze_netbsd_ncpu(Extract) ->
- analyze_netbsd_item(Extract,
- "hw.ncpu",
- fun(X) -> list_to_integer(X) end,
- -1).
-
-analyze_netbsd_memory(Extract) ->
- analyze_netbsd_item(Extract,
- "hw.physmem64",
- fun(X) -> list_to_integer(X) div 1024 end,
- -1).
-
-analyze_netbsd_item(Extract, Key, Process, Default) ->
- analyze_freebsd_item(Extract, Key, Process, Default).
-
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% --- Solaris ---
+%% start_node(Name) ->
+%% start_node(Name, 5000).
-analyze_and_print_solaris_host_info(Version) ->
- Release =
- case file:read_file_info("/etc/release") of
- {ok, _} ->
- case [string:trim(S) || S <- string:tokens(os:cmd("cat /etc/release"), [$\n])] of
- [Rel | _] ->
- Rel;
- _ ->
- "-"
- end;
- _ ->
- "-"
- end,
- %% Display the firmware device tree root properties (prtconf -b)
- Props = [list_to_tuple([string:trim(PS) || PS <- Prop]) ||
- Prop <- [string:tokens(S, [$:]) ||
- S <- string:tokens(os:cmd("prtconf -b"), [$\n])]],
- BannerName = case lists:keysearch("banner-name", 1, Props) of
- {value, {_, BN}} ->
- string:trim(BN);
- _ ->
- "-"
- end,
- InstructionSet =
- case string:trim(os:cmd("isainfo -k")) of
- "Pseudo-terminal will not" ++ _ ->
- "-";
- IS ->
- IS
- end,
- PtrConf = [list_to_tuple([string:trim(S) || S <- Items]) || Items <- [string:tokens(S, [$:]) || S <- string:tokens(os:cmd("prtconf"), [$\n])], length(Items) > 1],
- SysConf =
- case lists:keysearch("System Configuration", 1, PtrConf) of
- {value, {_, SC}} ->
- SC;
- _ ->
- "-"
- end,
- NumPhysProc =
- begin
- NPPStr = string:trim(os:cmd("psrinfo -p")),
- try list_to_integer(NPPStr) of
- _ ->
- NPPStr
- catch
- _:_:_ ->
- "-"
- end
- end,
- NumProc = try integer_to_list(length(string:tokens(os:cmd("psrinfo"), [$\n]))) of
- NPStr ->
- NPStr
- catch
- _:_:_ ->
- "-"
- end,
- MemSz =
- case lists:keysearch("Memory size", 1, PtrConf) of
- {value, {_, MS}} ->
- MS;
- _ ->
- "-"
- end,
- io:format("Solaris: ~s"
- "~n Release: ~s"
- "~n Banner Name: ~s"
- "~n Instruction Set: ~s"
- "~n CPUs: ~s (~s)"
- "~n System Config: ~s"
- "~n Memory Size: ~s"
- "~n Num Schedulers: ~s"
- "~n~n", [Version, Release, BannerName, InstructionSet,
- NumPhysProc, NumProc,
- SysConf, MemSz,
- str_num_schedulers()]),
- MemFactor =
- try string:tokens(MemSz, [$ ]) of
- [SzStr, "Mega" ++ _] ->
- try list_to_integer(SzStr) of
- Sz when Sz > 8192 ->
- 0;
- Sz when Sz > 4096 ->
- 1;
- Sz when Sz > 2048 ->
- 2;
- _ ->
- 5
- catch
- _:_:_ ->
- 10
- end;
- [SzStr, "Giga" ++ _] ->
- try list_to_integer(SzStr) of
- Sz when Sz > 8 ->
- 0;
- Sz when Sz > 4 ->
- 1;
- Sz when Sz > 2 ->
- 2;
- _ ->
- 5
- catch
- _:_:_ ->
- 10
- end;
- _ ->
- 10
- catch
- _:_:_ ->
- 10
- end,
- try erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- N when (N =< 6) ->
- 2;
- _ ->
- 1
+start_node(Name, Timeout) when is_integer(Timeout) andalso (Timeout > 0) ->
+ try ?CT_PEER(#{name => Name, wait_boot => Timeout}) of
+ {ok, Peer, Node} ->
+ ?SEV_IPRINT("Started node ~p", [Name]),
+ {Peer, Node};
+ {error, Reason} ->
+ ?SEV_EPRINT("failed starting node ~p (=> SKIP):"
+ "~n ~p", [Name, Reason]),
+ skip(Reason)
catch
- _:_:_ ->
- 10
- end + MemFactor.
-
-
-%% --- Windows ---
-
-analyze_and_print_win_host_info(Version) ->
- SysInfo = which_win_system_info(),
- OsName = win_sys_info_lookup(os_name, SysInfo),
- OsVersion = win_sys_info_lookup(os_version, SysInfo),
- SysMan = win_sys_info_lookup(system_manufacturer, SysInfo),
- SysMod = win_sys_info_lookup(system_model, SysInfo),
- NumProcs = win_sys_info_lookup(num_processors, SysInfo),
- TotPhysMem = win_sys_info_lookup(total_phys_memory, SysInfo),
- io:format("Windows: ~s"
- "~n OS Version: ~s (~p)"
- "~n System Manufacturer: ~s"
- "~n System Model: ~s"
- "~n Number of Processor(s): ~s"
- "~n Total Physical Memory: ~s"
- "~n Num Schedulers: ~s"
- "~n", [OsName, OsVersion, Version,
- SysMan, SysMod, NumProcs, TotPhysMem,
- str_num_schedulers()]),
- MemFactor =
- try
- begin
- [MStr, MUnit|_] =
- string:tokens(lists:delete($,, TotPhysMem), [$\ ]),
- case string:to_lower(MUnit) of
- "gb" ->
- try list_to_integer(MStr) of
- M when M > 8 ->
- 0;
- M when M > 4 ->
- 1;
- M when M > 2 ->
- 2;
- _ ->
- 5
- catch
- _:_:_ ->
- 10
- end;
- "mb" ->
- try list_to_integer(MStr) of
- M when M > 8192 ->
- 0;
- M when M > 4096 ->
- 1;
- M when M > 2048 ->
- 2;
- _ ->
- 5
- catch
- _:_:_ ->
- 10
- end;
- _ ->
- 10
- end
- end
- catch
- _:_:_ ->
- 10
- end,
- CPUFactor =
- case erlang:system_info(schedulers) of
- 1 ->
- 10;
- 2 ->
- 5;
- _ ->
- 2
- end,
- CPUFactor + MemFactor.
-
-win_sys_info_lookup(Key, SysInfo) ->
- win_sys_info_lookup(Key, SysInfo, "-").
-
-win_sys_info_lookup(Key, SysInfo, Def) ->
- case lists:keysearch(Key, 1, SysInfo) of
- {value, {Key, Value}} ->
- Value;
- false ->
- Def
+ Class:Reason:Stack ->
+ ?SEV_EPRINT("Failed starting node: "
+ "~n Class: ~p"
+ "~n Reason: ~p"
+ "~n Stack: ~p",
+ [Class, Reason, Stack]),
+ skip({node_start, Class, Reason})
end.
-%% This function only extracts the prop(s) we actually care about!
-%% On some hosts this (systeminfo) takes a *long time* (several minutes).
-%% And since there is no way to provide a timeout to the os command call,
-%% we have to wrap it in a process.
-which_win_system_info() ->
- F = fun() ->
- try
- begin
- SysInfo = os:cmd("systeminfo"),
- process_win_system_info(
- string:tokens(SysInfo, [$\r, $\n]), [])
- end
- catch
- C:E:S ->
- io:format("Failed get or process System info: "
- " Error Class: ~p"
- " Error: ~p"
- " Stack: ~p"
- "~n", [C, E, S]),
- []
- end
- end,
- ?LIB:pcall(F, ?MINS(1), []).
-
-process_win_system_info([], Acc) ->
- Acc;
-process_win_system_info([H|T], Acc) ->
- case string:tokens(H, [$:]) of
- [Key, Value] ->
- case string:to_lower(Key) of
- "os name" ->
- process_win_system_info(T,
- [{os_name, string:trim(Value)}|Acc]);
- "os version" ->
- process_win_system_info(T,
- [{os_version, string:trim(Value)}|Acc]);
- "system manufacturer" ->
- process_win_system_info(T,
- [{system_manufacturer, string:trim(Value)}|Acc]);
- "system model" ->
- process_win_system_info(T,
- [{system_model, string:trim(Value)}|Acc]);
- "processor(s)" ->
- [NumProcStr|_] = string:tokens(Value, [$\ ]),
- T2 = lists:nthtail(list_to_integer(NumProcStr), T),
- process_win_system_info(T2,
- [{num_processors, NumProcStr}|Acc]);
- "total physical memory" ->
- process_win_system_info(T,
- [{total_phys_memory, string:trim(Value)}|Acc]);
- _ ->
- process_win_system_info(T, Acc)
- end;
- _ ->
- process_win_system_info(T, Acc)
- end.
-
-
-
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nowait(Config) ->
@@ -51502,9 +48873,6 @@ sock_port(S) ->
{ok, #{}} -> undefined
end.
-l2a(S) when is_list(S) ->
- list_to_atom(S).
-
l2b(L) when is_list(L) ->
list_to_binary(L).
diff --git a/lib/kernel/test/socket_test_evaluator.erl b/lib/kernel/test/socket_test_evaluator.erl
index 70ab63bbc7..c2bd9d44b8 100644
--- a/lib/kernel/test/socket_test_evaluator.erl
+++ b/lib/kernel/test/socket_test_evaluator.erl
@@ -26,7 +26,7 @@
await_finish/1
]).
-%% Functions used by evaluators to interact with eachother
+%% Functions used by evaluators to interact with each other
-export([
%% Announce functions
%% (Send an announcement from one evaluator to another)
@@ -138,7 +138,7 @@ loop(ID, [#{desc := Desc,
%% Secondary skip
exit(E);
C:{skip, R} = E:_ when ((C =:= throw) orelse (C =:= exit)) ->
- ?SEV_IPRINT("command ~w skip catched(~w): "
+ ?SEV_IPRINT("command ~w skip caught(~w): "
"~n Reason: ~p", [ID, C, R]),
exit(E);
C:E:S ->
@@ -166,7 +166,7 @@ await_finish([], _OK, Fails) ->
Fails;
await_finish(Evs, OK, Fails) ->
receive
- %% Successfull termination of evaluator
+ %% Successful termination of evaluator
{'DOWN', _MRef, process, Pid, normal} ->
{Evs2, OK2, Fails2} = await_finish_normal(Pid, Evs, OK, Fails),
await_finish(Evs2, OK2, Fails2);
diff --git a/lib/kernel/test/socket_test_lib.erl b/lib/kernel/test/socket_test_lib.erl
index 56da2997e7..e7028dab3b 100644
--- a/lib/kernel/test/socket_test_lib.erl
+++ b/lib/kernel/test/socket_test_lib.erl
@@ -41,6 +41,7 @@
print/1, print/2,
%% Generic 'has support' test function(s)
+ has_support_ipv4/0,
has_support_ipv6/0,
which_local_host_info/1,
@@ -123,6 +124,14 @@ print(F, A) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+has_support_ipv4() ->
+ case which_local_addr(inet) of
+ {ok, _Addr} ->
+ ok;
+ {error, R1} ->
+ skip(f("Local Address eval failed: ~p", [R1]))
+ end.
+
has_support_ipv6() ->
case socket:is_supported(ipv6) of
true ->
diff --git a/lib/kernel/test/socket_test_ttest_tcp_client.erl b/lib/kernel/test/socket_test_ttest_tcp_client.erl
index ec9d75495f..7c115b32c0 100644
--- a/lib/kernel/test/socket_test_ttest_tcp_client.erl
+++ b/lib/kernel/test/socket_test_ttest_tcp_client.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -178,7 +178,7 @@ do_start(Quiet,
is_function(Notify) andalso
(is_atom(Transport) orelse is_tuple(Transport)) andalso
(is_boolean(Active) orelse (Active =:= once)) andalso
- (is_tuple(ServerInfo) orelse is_list(ServerInfo)) andalso
+ (is_tuple(ServerInfo) orelse is_list(ServerInfo) orelse is_binary(ServerInfo)) andalso
(is_integer(MsgID) andalso (MsgID >= 1) andalso (MsgID =< 3)) andalso
(is_integer(MaxOutstanding) andalso (MaxOutstanding > 0)) andalso
(is_integer(RunTime) andalso (RunTime > 0)) ->
@@ -206,7 +206,13 @@ do_start(Quiet,
%% We should not normally stop this (it terminates when its done).
stop(Pid) when is_pid(Pid) ->
- req(Pid, stop).
+ case req(Pid, stop, 2 * ?RECV_TIMEOUT) of
+ {error, timeout} ->
+ exit(Pid, kill),
+ ok;
+ Else ->
+ Else
+ end.
%% ==========================================================================
@@ -617,7 +623,11 @@ maybe_activate(_, _, _) ->
%% ==========================================================================
-req(Pid, Req) ->
+%% req(Pid, Req) ->
+%% req(Pid, Req, infinity).
+
+req(Pid, Req, Timeout) when (Timeout =:= infinity) orelse
+ (is_integer(Timeout) andalso (Timeout >= 0)) ->
Ref = make_ref(),
Pid ! {?MODULE, Ref, Pid, Req},
receive
@@ -625,6 +635,8 @@ req(Pid, Req) ->
{error, {exit, Reason}};
{?MODULE, Ref, Reply} ->
Reply
+ after Timeout ->
+ {error, timeout}
end.
reply(Pid, Ref, Reply) ->
diff --git a/lib/kernel/test/socket_test_ttest_tcp_server.erl b/lib/kernel/test/socket_test_ttest_tcp_server.erl
index d8cacd750c..1d471ebc63 100644
--- a/lib/kernel/test/socket_test_ttest_tcp_server.erl
+++ b/lib/kernel/test/socket_test_ttest_tcp_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
%%
%% There are three ways to run the server: active, passive or active-once.
%%
-%% The server does only two things; accept connnections and then reply
+%% The server does only two things; accept connections and then reply
%% to requests (actually the handler(s) does that). No timing or counting.
%% That is all done by the clients.
%%
@@ -116,7 +116,13 @@ do_start(Parent, Transport, Active)
stop(Pid) when is_pid(Pid) ->
- req(Pid, stop).
+ case req(Pid, stop, 2 * ?ACC_TIMEOUT) of
+ {error, timeout} ->
+ exit(Pid, kill),
+ ok;
+ Else ->
+ Else
+ end.
%% ==========================================================================
@@ -146,7 +152,7 @@ server_init(Starter, Parent, Transport, Active) ->
{error, SNReason} ->
exit({sockname, SNReason})
end;
- is_list(PortOrPath) ->
+ is_list(PortOrPath) orelse is_binary(PortOrPath) ->
?I("listening on:"
"~n Path: ~s"
"~n", [PortOrPath]),
@@ -248,7 +254,9 @@ format_peername({Addr, Port}) ->
?F("~p, ~p", [Addr, Port])
end;
format_peername(Path) when is_list(Path) ->
- Path.
+ Path;
+format_peername(Path) when is_binary(Path) ->
+ binary_to_list(Path).
maybe_start_stats_timer(#{active := Active, stats_interval := Time}, Handler)
when (Active =/= false) andalso (is_integer(Time) andalso (Time > 0)) ->
@@ -274,9 +282,16 @@ server_handle_message(#{mod := Mod,
State;
{?MODULE, Ref, Parent, stop} ->
+ ?I("received stop from parent ~p", [Parent]),
reply(Parent, Ref, ok),
- lists:foreach(fun(P) -> handler_stop(P) end, H),
+ ?I("try stop ~w handler(s)", [length(H)]),
+ lists:foreach(fun(P) ->
+ ?I("try stop handler ~p", [P]),
+ handler_stop(P)
+ end, H),
+ ?I("try close listen socket"),
(catch Mod:close(LSock)),
+ ?I("stopped"),
exit(normal);
{'DOWN', _MRef, process, Pid, Reason} ->
@@ -299,10 +314,12 @@ server_handle_stats(ProcStr, Pid) ->
server_handle_down(Pid, Reason, #{handlers := Handlers} = State) ->
case lists:delete(Pid, Handlers) of
Handlers ->
- ?I("unknown process ~p died", [Pid]),
+ ?I("unknown process ~p died: "
+ "~n ~p", [Pid, Reason]),
State;
Handlers2 ->
- server_handle_handler_down(Pid, Reason, State#{handlers => Handlers2})
+ server_handle_handler_down(Pid, Reason,
+ State#{handlers => Handlers2})
end.
@@ -341,7 +358,7 @@ server_handle_handler_down(Pid,
bcnt => AccBCnt2,
hcnt => AccHCnt2};
server_handle_handler_down(Pid, Reason, State) ->
- ?I("handler ~p terminated: "
+ ?E("handler ~p terminated: "
"~n ~p", [Pid, Reason]),
State.
@@ -358,7 +375,14 @@ handler_continue(Pid, Mod, Sock, Active) ->
req(Pid, {continue, Mod, Sock, Active}).
handler_stop(Pid) ->
- req(Pid, stop).
+ case req(Pid, stop, 2 * ?RECV_TIMEOUT) of
+ {error, timeout} ->
+ ?E("timeout attempting to stop handler ~p => try kill", [Pid]),
+ exit(Pid, kill),
+ ok;
+ Else ->
+ Else
+ end.
handler_init(Parent) ->
?I("starting"),
@@ -415,7 +439,7 @@ handler_recv_message(#{mod := Mod,
%% When "active" (once or true), we receive one data "message", which may
%% contain any number of requests or only part of a request. Then we
%% process this data together with whatever we had "accumulated" from
-%% prevous messages. Each request will be extracted and replied to. If
+%% previous messages. Each request will be extracted and replied to. If
%% there is some data left, not enough for a complete request, we store
%% this in 'acc' (accumulate it).
handler_recv_message(#{mod := Mod,
@@ -551,9 +575,19 @@ handler_done(#{start := Start,
exit({done, ?TDIFF(Start, Stop), MCnt, BCnt}).
-handler_handle_message(#{parent := Parent} = State) ->
+handler_handle_message(#{mod := Mod, sock := Sock, parent := Parent} = State) ->
receive
+ {?MODULE, Ref, Parent, stop} ->
+ ?I("handler: received stop from parent ~p", [Parent]),
+ reply(Parent, Ref, ok),
+ (catch Mod:close(Sock)),
+ ?I("handler: stopped"),
+ exit(normal);
+
{'EXIT', Parent, Reason} ->
+ ?E("handler: parent ~p exit: "
+ "~n ~p", [Parent, Reason]),
+ (catch Mod:close(Sock)),
exit({parent_exit, Reason})
after 0 ->
State
@@ -625,6 +659,10 @@ handler_maybe_activate(_, _, _) ->
%% ==========================================================================
req(Pid, Req) ->
+ req(Pid, Req, infinity).
+
+req(Pid, Req, Timeout) when (Timeout =:= infinity) orelse
+ (is_integer(Timeout) andalso (Timeout >= 0)) ->
Ref = make_ref(),
Pid ! {?MODULE, Ref, self(), Req},
receive
@@ -632,6 +670,8 @@ req(Pid, Req) ->
{error, {exit, Reason}};
{?MODULE, Ref, Reply} ->
Reply
+ after Timeout ->
+ {error, timeout}
end.
reply(Pid, Ref, Reply) ->
diff --git a/lib/kernel/test/socket_test_ttest_tcp_socket.erl b/lib/kernel/test/socket_test_ttest_tcp_socket.erl
index d949e51da1..07be4740e6 100644
--- a/lib/kernel/test/socket_test_ttest_tcp_socket.erl
+++ b/lib/kernel/test/socket_test_ttest_tcp_socket.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -84,7 +84,7 @@ accept(#{sock := LSock, opts := #{async := Async,
ERROR
end.
-%% If a timeout has been explictly specified, then we do not use
+%% If a timeout has been explicitly specified, then we do not use
%% async here. We will pass it on to the reader process.
accept(#{sock := LSock, opts := #{async := Async,
method := Method} = Opts}, Timeout) ->
@@ -120,7 +120,7 @@ close(#{sock := Sock, reader := Pid}) ->
Res.
%% Create a socket and connect it to a peer
-connect(ServerPath) when is_list(ServerPath) ->
+connect(ServerPath) when is_list(ServerPath) orelse is_binary(ServerPath) ->
Domain = local,
ClientPath = mk_unique_path(),
LocalSA = #{family => Domain,
@@ -145,7 +145,7 @@ connect(Addr, Port) when is_tuple(Addr) andalso is_integer(Port) ->
do_connect(LocalSA, ServerSA, Cleanup, Opts);
connect(ServerPath,
#{domain := local = Domain} = Opts)
- when is_list(ServerPath) ->
+ when is_list(ServerPath) orelse is_binary(ServerPath) ->
ClientPath = mk_unique_path(),
LocalSA = #{family => Domain,
path => ClientPath},
@@ -233,13 +233,14 @@ listen() ->
listen(Port) when is_integer(Port) ->
listen(Port, #{domain => inet, async => false, method => plain});
-listen(Path) when is_list(Path) ->
+listen(Path) when is_list(Path) orelse is_binary(Path) ->
listen(Path, #{domain => local, async => false, method => plain}).
listen(0, #{domain := local} = Opts) ->
listen(mk_unique_path(), Opts);
listen(Path, #{domain := local = Domain} = Opts)
- when is_list(Path) andalso (Path =/= []) ->
+ when (is_list(Path) andalso (Path =/= [])) orelse
+ (is_binary(Path) andalso (Path =/= <<"">>)) ->
SA = #{family => Domain,
path => Path},
Cleanup = fun() -> os:cmd("unlink " ++ Path), ok end,
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 5528c87124..12a1996eb5 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 8.3.2
+KERNEL_VSN = 8.5.4
diff --git a/lib/megaco/Makefile b/lib/megaco/Makefile
index ebddcec5e7..0250167791 100644
--- a/lib/megaco/Makefile
+++ b/lib/megaco/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2021. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -98,7 +98,13 @@ else
FLEX_SCANNER_REENTRANT_ENABLER = --enable-megaco-reentrant-flex-scanner
endif
-CONFIGURE_OPTS = $(FLEX_SCANNER_LINENO_ENABLER) $(FLEX_SCANNER_REENTRANT_ENABLER)
+ifeq ($(ERL_DETERMINISTIC),yes)
+ ERL_DETERMINISTIC_ENABLER = --enable-deterministic-build
+else
+ ERL_DETERMINISTIC_ENABLER = --disable-deterministic-build
+endif
+
+CONFIGURE_OPTS = $(FLEX_SCANNER_LINENO_ENABLER) $(FLEX_SCANNER_REENTRANT_ENABLER) $(ERL_DETERMINISTIC_ENABLER)
DIA_PLT = ./priv/plt/$(APPLICATION).plt
@@ -115,7 +121,7 @@ include $(ERL_TOP)/make/otp_subdir.mk
reconf:
(cd $(ERL_TOP) && \
- ./otp_build configure && \
+ ./otp_build configure $(ERL_DETERMINISTIC_ENABLER) && \
cd $(ERL_TOP)/../libraries/megaco)
conf: do_configure
@@ -203,5 +209,6 @@ $(APP_TAR_FILE): $(APP_DIR)
(cd "$(APP_RELEASE_DIR)"; gtar zcf "$(subst $(space),\ ,$@)" $(DIR_NAME))
DIA_PLT_APPS=asn1 runtime_tools et debugger
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/megaco/configure b/lib/megaco/configure
index fac90552ce..1ca72e94d3 100755
--- a/lib/megaco/configure
+++ b/lib/megaco/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,35 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +438,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +467,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +511,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +525,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +542,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,50 +614,46 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
ac_unique_file="vsn.mk"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
PERL
@@ -638,9 +673,6 @@ DED_GCC
DED_CC
DED_LD
DED_THR_DEFS
-EGREP
-GREP
-CPP
GETCONF
OTP_EXTRA_FLAGS
ERLANG_OSTYPE
@@ -659,6 +691,10 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -720,8 +756,7 @@ CC
CFLAGS
LDFLAGS
LIBS
-CPPFLAGS
-CPP'
+CPPFLAGS'
# Initialize some variables set by options.
@@ -790,8 +825,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -832,9 +865,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -858,9 +891,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1071,9 +1104,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1087,9 +1120,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1133,9 +1166,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1151,7 +1184,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1215,7 +1248,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1333,6 +1366,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1359,7 +1393,6 @@ Some influential environment variables:
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1380,9 +1413,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1410,7 +1443,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1418,7 +1452,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1428,9 +1462,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1447,14 +1481,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1462,14 +1496,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1485,14 +1520,14 @@ fi
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1500,17 +1535,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1531,11 +1567,12 @@ fi
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -1543,16 +1580,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -1570,156 +1600,66 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-} # ac_fn_c_check_header_mongrel
+} # ac_fn_c_check_header_compile
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
@@ -1729,25 +1669,26 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
@@ -1758,37 +1699,6 @@ fi
} # ac_fn_c_try_run
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
-
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@@ -1803,7 +1713,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -1813,14 +1723,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1830,9 +1741,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -1840,14 +1752,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -1857,14 +1769,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -1874,9 +1787,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -1884,14 +1798,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -1899,7 +1813,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1909,12 +1823,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -1924,12 +1839,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -1957,9 +1872,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -1971,14 +1887,34 @@ rm -f conftest.val
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2011,8 +1947,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2047,7 +1987,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2082,11 +2022,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2097,8 +2039,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2122,7 +2064,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2130,14 +2072,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2145,15 +2087,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2161,8 +2103,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2176,63 +2118,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2242,19 +2169,434 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2265,12 +2607,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2279,24 +2621,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2306,11 +2648,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2324,57 +2667,125 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in ${ERL_TOP}/erts/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in ${ERL_TOP}/erts/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2393,21 +2804,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2426,11 +2838,118 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
fi
+
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2439,11 +2958,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2451,11 +2971,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2466,11 +2990,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2479,11 +3003,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2491,11 +3016,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2506,11 +3035,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2518,8 +3047,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2532,11 +3061,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2544,11 +3074,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2559,11 +3093,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2572,11 +3106,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2585,15 +3120,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2609,18 +3148,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2631,11 +3170,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2643,11 +3183,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2658,11 +3202,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2675,11 +3219,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2687,11 +3232,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2702,11 +3251,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2718,8 +3267,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2727,25 +3276,129 @@ esac
fi
fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -2755,7 +3408,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -2763,7 +3416,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2775,9 +3428,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -2798,11 +3451,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -2819,7 +3473,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -2835,44 +3489,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -2886,15 +3542,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -2903,7 +3559,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -2915,8 +3571,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -2924,10 +3580,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -2935,39 +3591,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2981,11 +3638,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -2994,31 +3652,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3028,29 +3687,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3059,57 +3722,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3124,94 +3790,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3232,111 +3948,111 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -3346,13 +4062,14 @@ fi
# Check whether --enable-megaco_reentrant_flex_scanner was given.
-if test "${enable_megaco_reentrant_flex_scanner+set}" = set; then :
+if test ${enable_megaco_reentrant_flex_scanner+y}
+then :
enableval=$enable_megaco_reentrant_flex_scanner; if test x${enable_megaco_reentrant_flex_scanner} = xno ; then
ENABLE_REENTRANT_MEGACO_FLEX_SCANNER=false
else
ENABLE_REENTRANT_MEGACO_FLEX_SCANNER=true
fi
-else
+else $as_nop
ENABLE_REENTRANT_MEGACO_FLEX_SCANNER=true
fi
@@ -3364,11 +4081,12 @@ for ac_prog in flex lex
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LEX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LEX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$LEX"; then
ac_cv_prog_LEX="$LEX" # Let the user override the test.
else
@@ -3376,11 +4094,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LEX="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3391,11 +4113,11 @@ fi
fi
LEX=$ac_cv_prog_LEX
if test -n "$LEX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
-$as_echo "$LEX" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+printf "%s\n" "$LEX" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3403,15 +4125,26 @@ fi
done
test -n "$LEX" || LEX=":"
-if test "x$LEX" != "x:"; then
- cat >conftest.l <<_ACEOF
+ if test "x$LEX" != "x:"; then
+ cat >conftest.l <<_ACEOF
+%{
+#ifdef __cplusplus
+extern "C"
+#endif
+int yywrap(void);
+%}
%%
a { ECHO; }
b { REJECT; }
c { yymore (); }
d { yyless (1); }
e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */
- yyless ((input () != 0)); }
+#ifdef __cplusplus
+ yyless ((yyinput () != 0));
+#else
+ yyless ((input () != 0));
+#endif
+ }
f { unput (yytext[0]); }
. { BEGIN INITIAL; }
%%
@@ -3419,101 +4152,144 @@ f { unput (yytext[0]); }
extern char *yytext;
#endif
int
+yywrap (void)
+{
+ return 1;
+}
+int
main (void)
{
- return ! yylex () + ! yywrap ();
+ return ! yylex ();
}
_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for lex output file root" >&5
+printf %s "checking for lex output file root... " >&6; }
+if test ${ac_cv_prog_lex_root+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ac_cv_prog_lex_root=unknown
{ { ac_try="$LEX conftest.l"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$LEX conftest.l") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
-$as_echo_n "checking lex output file root... " >&6; }
-if ${ac_cv_prog_lex_root+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } &&
if test -f lex.yy.c; then
ac_cv_prog_lex_root=lex.yy
elif test -f lexyy.c; then
ac_cv_prog_lex_root=lexyy
-else
- as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
-$as_echo "$ac_cv_prog_lex_root" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+printf "%s\n" "$ac_cv_prog_lex_root" >&6; }
+if test "$ac_cv_prog_lex_root" = unknown
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cannot find output from $LEX; giving up on $LEX" >&5
+printf "%s\n" "$as_me: WARNING: cannot find output from $LEX; giving up on $LEX" >&2;}
+ LEX=: LEXLIB=
+fi
LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
-if test -z "${LEXLIB+set}"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
-$as_echo_n "checking lex library... " >&6; }
-if ${ac_cv_lib_lex+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test ${LEXLIB+y}
+then :
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for lex library" >&5
+printf %s "checking for lex library... " >&6; }
+if test ${ac_cv_lib_lex+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ ac_save_LIBS="$LIBS"
+ ac_found=false
+ for ac_cv_lib_lex in 'none needed' -lfl -ll 'not found'; do
+ case $ac_cv_lib_lex in #(
+ 'none needed') :
+ ;; #(
+ 'not found') :
+ break ;; #(
+ *) :
+ LIBS="$ac_cv_lib_lex $ac_save_LIBS" ;; #(
+ *) :
+ ;;
+esac
- ac_save_LIBS=$LIBS
- ac_cv_lib_lex='none needed'
- for ac_lib in '' -lfl -ll; do
- LIBS="$ac_lib $ac_save_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
`cat $LEX_OUTPUT_ROOT.c`
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_lex=$ac_lib
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_found=:
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
- test "$ac_cv_lib_lex" != 'none needed' && break
+ if $ac_found; then
+ break
+ fi
done
- LIBS=$ac_save_LIBS
+ LIBS="$ac_save_LIBS"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
-$as_echo "$ac_cv_lib_lex" >&6; }
- test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+printf "%s\n" "$ac_cv_lib_lex" >&6; }
+ if test "$ac_cv_lib_lex" = 'not found'
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: required lex library not found; giving up on $LEX" >&5
+printf "%s\n" "$as_me: WARNING: required lex library not found; giving up on $LEX" >&2;}
+ LEX=: LEXLIB=
+elif test "$ac_cv_lib_lex" = 'none needed'
+then :
+ LEXLIB=''
+else $as_nop
+ LEXLIB=$ac_cv_lib_lex
fi
+fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
-$as_echo_n "checking whether yytext is a pointer... " >&6; }
-if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+if test "$LEX" != :
+then :
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+printf %s "checking whether yytext is a pointer... " >&6; }
+if test ${ac_cv_prog_lex_yytext_pointer+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
# POSIX says lex can declare yytext either as a pointer or an array; the
# default is implementation-dependent. Figure out which it is, since
# not all implementations provide the %pointer and %array declarations.
ac_cv_prog_lex_yytext_pointer=no
-ac_save_LIBS=$LIBS
-LIBS="$LEXLIB $ac_save_LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define YYTEXT_POINTER 1
`cat $LEX_OUTPUT_ROOT.c`
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_lex_yytext_pointer=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_save_LIBS
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
-$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+printf "%s\n" "$ac_cv_prog_lex_yytext_pointer" >&6; }
if test $ac_cv_prog_lex_yytext_pointer = yes; then
-$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h
+printf "%s\n" "#define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
fi
rm -f conftest.l $LEX_OUTPUT_ROOT.c
@@ -3553,25 +4329,25 @@ int main ( int argc, char * argv[] )
return 0;
}
EOF
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reentrant capable flex" >&5
-$as_echo_n "checking for reentrant capable flex... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for reentrant capable flex" >&5
+printf %s "checking for reentrant capable flex... " >&6; }
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$flex_compile\""; } >&5
(eval $flex_compile) 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && test -s conftest.c; then
ENABLE_REENTRANT_MEGACO_FLEX_SCANNER=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
echo "configure: failed program was:" 1>&5
cat conftest.flex 1>&5
echo "configure: PATH was $PATH" 1>&5
ENABLE_REENTRANT_MEGACO_FLEX_SCANNER=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -3582,13 +4358,14 @@ fi
# Check whether --enable-megaco_flex_scanner_lineno was given.
-if test "${enable_megaco_flex_scanner_lineno+set}" = set; then :
+if test ${enable_megaco_flex_scanner_lineno+y}
+then :
enableval=$enable_megaco_flex_scanner_lineno; if test x${enable_megaco_flex_scanner_lineno} = xno ; then
ENABLE_MEGACO_FLEX_SCANNER_LINENO=false
else
ENABLE_MEGACO_FLEX_SCANNER_LINENO=true
fi
-else
+else $as_nop
ENABLE_MEGACO_FLEX_SCANNER_LINENO=true
fi
@@ -3613,43 +4390,50 @@ fi
if test "x$GCC" = xyes; then
# Treat certain GCC warnings as errors
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="-Werror=return-type $CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
fi
# Check whether --enable-sanitizers was given.
-if test "${enable_sanitizers+set}" = set; then :
+if test ${enable_sanitizers+y}
+then :
enableval=$enable_sanitizers;
case "$enableval" in
no) sanitizers= ;;
@@ -3662,432 +4446,69 @@ LDFLAGS="$LDFLAGS $sanitizers"
fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
+done
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-done
-
-
-
NEED_NPTL_PTHREAD_H=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
-$as_echo_n "checking for native win32 threads... " >&6; }
-if test "X$host_os" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
+printf %s "checking for native win32 threads... " >&6; }
+if test "X$host_os" = "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
THR_LIB_TYPE=posix_unknown
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4096,40 +4517,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pthread_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_pthread_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
THR_LIBS="-lpthread"
fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
-$as_echo_n "checking for pthread_create in -lc_r... " >&6; }
-if ${ac_cv_lib_c_r_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
+printf %s "checking for pthread_create in -lc_r... " >&6; }
+if test ${ac_cv_lib_c_r_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4138,96 +4561,112 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_c_r_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_c_r_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
-$as_echo "$ac_cv_lib_c_r_pthread_create" >&6; }
-if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_c_r_pthread_create" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_create" = xyes
+then :
THR_LIBS="-lc_r"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
-if test "x$ac_cv_func_pthread_create" = xyes; then :
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes
+then :
THR_LIBS="none_needed"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
-$as_echo_n "checking if the '-pthread' switch can be used... " >&6; }
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
+printf %s "checking if the '-pthread' switch can be used... " >&6; }
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -pthread"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_create((void*)0,(void*)0,(void*)0,(void*)0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
THR_DEFS="-pthread"
THR_LIBS="-pthread"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_cflags
if test "x$THR_LIBS" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- fi
- if test "x$THR_LIBS" != "x"; then
+fi
+
+ if test "x$THR_LIBS" != "x"
+then :
+
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ case $host_os in #(
+ solaris*) :
+
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ;; #(
+ linux*) :
+
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
-if test "$cross_compiling" != "yes"; then
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -4235,11 +4674,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4251,23 +4694,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -4275,11 +4721,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4291,25 +4741,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -4320,11 +4773,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4336,11 +4793,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4349,11 +4806,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -4364,11 +4822,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4380,11 +4842,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -4392,8 +4854,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -4402,11 +4864,13 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
+fi
+
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
-$as_echo_n "checking for Native POSIX Thread Library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
+printf %s "checking for Native POSIX Thread Library... " >&6; }
libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
if test $? -eq 0; then
case "$libpthr_vsn" in
@@ -4422,24 +4886,28 @@ $as_echo_n "checking for Native POSIX Thread Library... " >&6; }
else
nptl=no
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
-$as_echo "$nptl" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
+printf "%s\n" "$nptl" >&6; }
if test $nptl = cross; then
nptl=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
- if test $nptl = yes; then
+ if test $nptl = yes
+then :
+
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- ac_fn_c_check_header_mongrel "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_nptl_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_nptl_pthread_h" = xyes
+then :
need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes
fi
+ if test $need_nptl_incldir = yes
+then :
- if test $need_nptl_incldir = yes; then
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -4460,13 +4928,13 @@ fi
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
nptl_incldir=$dir/nptl
fi
-
if test "x$nptl_incldir" != "x"; then
THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
break
@@ -4475,38 +4943,43 @@ fi
if test "x$nptl_incldir" = "x"; then
as_fn_error $? "Failed to locate nptl system include directory" "$LINENO" 5
fi
- fi
- fi
- ;;
- *) ;;
- esac
+
+fi
+
+fi
+ ;; #(
+ *) :
+ ;;
+esac
saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $THR_DEFS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
-$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
CPPFLAGS=$saved_cppflags
- fi
+
+fi
+
fi
@@ -4550,181 +5023,253 @@ case "$host_cpu" in
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WARN_FLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=return-type $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=implicit $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=implicit $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=undef $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=undef $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$DED_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
DED_INCLUDE=$DED_SYS_INCLUDE
DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Use -fno-common for gcc, that is link error if multiple definitions of
# global variables are encountered. This is ISO C compliant.
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-common $DED_CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_CFLAGS="-fno-common $DED_CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)... " >&6; }
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="-fno-strict-aliasing $DED_CFLAGS";
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ can_enable_flag=true
+else $as_nop
+ can_enable_flag=false
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$saved_CFLAGS;
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ DED_CFLAGS="-fno-strict-aliasing $DED_CFLAGS"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_STATIC_CFLAGS="$DED_CFLAGS"
DED_CFLAGS="$DED_CFLAGS -fPIC"
# Remove -fPIE and -fno-PIE
DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
+
fi
DED_EXT=so
@@ -4811,17 +5356,19 @@ case $host_os in
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4830,14 +5377,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
case "$ac_cv_sizeof_void_p" in
@@ -4904,11 +5449,12 @@ test "$DED_LDFLAGS_CONFTEST" != "" || DED_LDFLAGS_CONFTEST="$DED_LDFLAGS"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$DED_LD"; then
ac_cv_prog_DED_LD="$DED_LD" # Let the user override the test.
else
@@ -4916,11 +5462,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DED_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4931,11 +5481,11 @@ fi
fi
DED_LD=$ac_cv_prog_DED_LD
if test -n "$DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4944,11 +5494,12 @@ if test -z "$ac_cv_prog_DED_LD"; then
ac_ct_DED_LD=$DED_LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_DED_LD"; then
ac_cv_prog_ac_ct_DED_LD="$ac_ct_DED_LD" # Let the user override the test.
else
@@ -4956,11 +5507,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DED_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4971,11 +5526,11 @@ fi
fi
ac_ct_DED_LD=$ac_cv_prog_ac_ct_DED_LD
if test -n "$ac_ct_DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
-$as_echo "$ac_ct_DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
+printf "%s\n" "$ac_ct_DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DED_LD" = x; then
@@ -4983,8 +5538,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DED_LD=$ac_ct_DED_LD
@@ -4995,37 +5550,37 @@ fi
test "$DED_LD" != "false" || as_fn_error $? "No linker found" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
-$as_echo_n "checking for static compiler flags... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
+printf %s "checking for static compiler flags... " >&6; }
DED_STATIC_CFLAGS="$DED_WERRORFLAGS $DED_WFLAGS $DED_THR_DEFS $DED_STATIC_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
-$as_echo "$DED_STATIC_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
-$as_echo_n "checking for basic compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
+printf "%s\n" "$DED_STATIC_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
+printf %s "checking for basic compiler flags for loadable drivers... " >&6; }
DED_BASIC_CFLAGS=$DED_CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
-$as_echo_n "checking for compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
+printf %s "checking for compiler flags for loadable drivers... " >&6; }
DED_CFLAGS="$DED_WERRORFLAGS $DED_WARN_FLAGS $DED_THR_DEFS $DED_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
-$as_echo_n "checking for linker for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
-$as_echo_n "checking for linker flags for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
-$as_echo "$DED_LDFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
-$as_echo_n "checking for 'runtime library path' linker flag... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
+printf %s "checking for linker for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
+printf %s "checking for linker flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
+printf "%s\n" "$DED_LDFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
+printf %s "checking for 'runtime library path' linker flag... " >&6; }
if test "x$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
-$as_echo "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
+printf "%s\n" "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
fi
@@ -5050,11 +5605,12 @@ fi
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_PERL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_PERL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$PERL"; then
ac_cv_prog_PERL="$PERL" # Let the user override the test.
else
@@ -5062,11 +5618,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_PERL="perl"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5078,11 +5638,11 @@ fi
fi
PERL=$ac_cv_prog_PERL
if test -n "$PERL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
-$as_echo "$PERL" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
+printf "%s\n" "$PERL" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5119,8 +5679,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -5150,15 +5710,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -5172,8 +5732,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -5226,7 +5786,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -5242,8 +5802,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -5266,14 +5826,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -5283,46 +5845,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -5331,13 +5893,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -5346,8 +5901,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -5359,30 +5918,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -5395,13 +5934,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -5428,18 +5968,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -5451,12 +5993,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -5487,7 +6030,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -5509,6 +6052,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -5522,6 +6069,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -5563,7 +6116,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -5572,7 +6125,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -5635,7 +6188,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -5684,14 +6237,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -5728,21 +6283,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -5770,7 +6325,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -5784,7 +6339,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -5809,7 +6364,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -6037,7 +6592,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -6045,17 +6600,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -6072,7 +6627,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6096,9 +6651,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -6151,8 +6706,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -6194,9 +6749,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -6243,8 +6798,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
ac_config_files="$ac_config_files src/flex/$host/Makefile:src/flex/Makefile.in"
@@ -6276,8 +6831,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -6307,15 +6862,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -6329,8 +6884,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -6383,7 +6938,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -6399,8 +6954,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -6423,14 +6978,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -6440,46 +6997,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -6488,13 +7045,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -6503,8 +7053,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -6516,30 +7070,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -6552,13 +7086,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -6585,18 +7120,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -6608,12 +7145,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -6644,7 +7182,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -6666,6 +7204,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -6679,6 +7221,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -6720,7 +7268,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -6729,7 +7277,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6792,7 +7340,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -6841,14 +7389,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -6885,21 +7435,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -6927,7 +7477,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -6941,7 +7491,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -6967,7 +7517,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -7195,7 +7745,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -7203,17 +7753,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -7230,7 +7780,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -7254,9 +7804,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -7309,8 +7859,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -7352,9 +7902,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -7401,8 +7951,9 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/megaco/configure.in b/lib/megaco/configure.ac
index 789fbbed04..ce65e54a85 100644
--- a/lib/megaco/configure.in
+++ b/lib/megaco/configure.ac
@@ -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-2020. All Rights Reserved.
+dnl Copyright Ericsson AB 2001-2021. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
@@ -23,15 +23,15 @@ dnl define([AC_CACHE_LOAD], )dnl
dnl define([AC_CACHE_SAVE], )dnl
-AC_INIT(vsn.mk)
+AC_INIT
+AC_CONFIG_SRCDIR([vsn.mk])
+AC_PREREQ([2.71])
-AC_CONFIG_AUX_DIRS(${ERL_TOP}/erts/autoconf)
+m4_include([otp.m4])
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
+
+ERL_CANONICAL_SYSTEM_TYPE
dnl ----------------------------------------------------------------------
dnl Checks for programs.
@@ -42,7 +42,7 @@ AC_PROG_CC
LM_WINDOWS_ENVIRONMENT
AC_DEFUN(ERL_REENTRANT_FLEX,
-[flex_compile='$LEX -R -Pconftest -oconftest.c conftest.flex 1>&AC_FD_CC'
+[flex_compile='$LEX -R -Pconftest -oconftest.c conftest.flex 1>&AS_MESSAGE_LOG_FD'
changequote(253, 273)dnl
cat > conftest.flex <<EOF
/*
@@ -79,9 +79,9 @@ if AC_TRY_EVAL(flex_compile) && test -s conftest.c; then
$1])
AC_MSG_RESULT([yes])
else
- echo "configure: failed program was:" 1>&AC_FD_CC
- cat conftest.flex 1>&AC_FD_CC
- echo "configure: PATH was $PATH" 1>&AC_FD_CC
+ echo "configure: failed program was:" 1>&AS_MESSAGE_LOG_FD
+ cat conftest.flex 1>&AS_MESSAGE_LOG_FD
+ echo "configure: PATH was $PATH" 1>&AS_MESSAGE_LOG_FD
ifelse([$2], , , [
$2
])dnl
@@ -108,7 +108,7 @@ dnl
dnl flex is needed by megaco. lex wont do!
dnl
-AC_PROG_LEX
+AC_PROG_LEX([noyywrap])
if test "$LEX" != flex; then
ENABLE_MEGACO_FLEX_SCANNER=false
else
@@ -189,6 +189,8 @@ 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)
+AC_CONFIG_FILES([examples/meas/Makefile:examples/meas/Makefile.in])
+AC_OUTPUT
+AC_CONFIG_FILES([src/flex/$host/Makefile:src/flex/Makefile.in])
+AC_OUTPUT
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 8787d63375..9e181c589c 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -37,7 +37,111 @@
section is the version number of Megaco.</p>
- <section><title>Megaco 4.3</title>
+ <section><title>Megaco 4.4.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 4.4.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A very minor improvement to the measurement tool.</p>
+ <p>
+ Own Id: OTP-18298</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 4.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed various dialyzer related issues in the examples and
+ the application proper.</p>
+ <p>
+ Own Id: OTP-18179 Aux Id: ERIERL-836 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 4.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>
+ Megaco test suite(s) use the new peer module for node
+ starts.</p>
+ <p>
+ Own Id: OTP-17910</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/megaco/examples/meas/Makefile.in b/lib/megaco/examples/meas/Makefile.in
index 4ff5cd2703..216f03fc04 100644
--- a/lib/megaco/examples/meas/Makefile.in
+++ b/lib/megaco/examples/meas/Makefile.in
@@ -86,6 +86,21 @@ ERL_COMPILE_FLAGS += \
-pa $(ERL_TOP)/lib/megaco/ebin \
-I../include
+DIA_PLT = megaco_example_meas.plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+ifeq ($(DIAW_EH),true)
+DIA_WARNINGS += -Werror_handling
+endif
+ifeq ($(DIAW_US),true)
+DIA_WARNINGS += -Wunderspecs
+endif
+ifeq ($(DIAW_UR),true)
+DIA_WARNINGS += -Wunmatched_returns
+endif
+DIA_PLT_APPS = \
+ erts et asn1 kernel stdlib compiler debugger \
+ runtime_tools crypto mnesia wx
+
# ----------------------------------------------------
# Special Build Targets
@@ -95,8 +110,8 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
@@ -104,13 +119,17 @@ script_skeletons: $(SCRIPT_SKELETONS)
info:
@echo "MODULES = $(MODULES)"
- @echo "ERL_FILED = $(ERL_FILES)"
+ @echo "ERL_FILES = $(ERL_FILES)"
@echo ""
@echo "SCRIPT_SKELETON_SRC = $(SCRIPT_SKELETON_SRC)"
@echo "SCRIPT_SKELETONS = $(SCRIPT_SKELETONS)"
@echo ""
@echo "TARGET_FILES = $(TARGET_FILES)"
@echo ""
+ @echo "DIA_PLT = $(DIA_PLT)"
+ @echo "DIA_ANALYSIS = $(DIA_ANALYSIS)"
+ @echo "DIA_PLT_APPS = $(DIA_PLT_APPS)"
+ @echo ""
clean:
rm -f $(TARGET_FILES)
@@ -140,6 +159,28 @@ release_spec: opt
release_docs_spec:
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT): $(ERL_FILES)
+ @echo "Building $(basename $(DIA_PLT)) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ --apps --apps $(sort $(APPLICATION) $(DIA_PLT_APPS)) \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on megaco example meas"
+ @dialyzer --plt $< \
+ $(ERL_TOP)/lib/megaco/examples/meas \
+ $(DIA_WARNINGS) \
+ --verbose
+
+
# ----------------------------------------------------
# Include dependencies
# ----------------------------------------------------
diff --git a/lib/megaco/examples/meas/megaco_codec_meas.erl b/lib/megaco/examples/meas/megaco_codec_meas.erl
index ae28fa43a0..ceeaa35504 100644
--- a/lib/megaco/examples/meas/megaco_codec_meas.erl
+++ b/lib/megaco/examples/meas/megaco_codec_meas.erl
@@ -46,11 +46,11 @@
%% API
%% Avoid warning for local function error/2 clashing with autoimported BIF.
-compile({no_auto_import,[error/2]}).
--export([start/0, start/1]).
+-export([start/0, start/1, start/2]).
-export([start1/0]).
%% Internal exports
--export([do_measure_codec/8, do_measure_codec_loop/7]).
+-export([do_measure_codec/7, do_measure_codec_loop/7]).
-export([flex_scanner_handler/1]).
@@ -74,6 +74,8 @@
-define(DEFAULT_MESSAGE_PACKAGE, megaco_codec_transform:default_message_package()).
+-define(DEFAULT_OPTS, #{verbose => true}).
+
-define(FTS(), formated_timestamp()).
@@ -87,18 +89,22 @@ start1() ->
start().
start() ->
- meas_init(1, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
+ meas_init(1, ?DEFAULT_OPTS, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
start([MessagePackage]) ->
- do_start(1, MessagePackage, ?MEASURE_CODECS);
+ do_start(1, ?DEFAULT_OPTS, MessagePackage, ?MEASURE_CODECS);
start(Factor) when is_integer(Factor) andalso (Factor > 0) ->
- do_start(Factor, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS);
+ do_start(Factor, ?DEFAULT_OPTS, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS);
start(MessagePackage) ->
- do_start(1, MessagePackage, ?MEASURE_CODECS).
+ do_start(1, ?DEFAULT_OPTS, MessagePackage, ?MEASURE_CODECS).
+
+start(Factor, Opts) when is_integer(Factor) andalso (Factor > 0) andalso
+ is_map(Opts) ->
+ do_start(Factor, Opts, ?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
-do_start(Factor, MessagePackageRaw, Codecs) ->
+do_start(Factor, Opts, MessagePackageRaw, Codecs) ->
MessagePackage = parse_message_package(MessagePackageRaw),
- meas_init(Factor, MessagePackage, Codecs).
+ meas_init(Factor, Opts, MessagePackage, Codecs).
parse_message_package(MessagePackageRaw) when is_list(MessagePackageRaw) ->
list_to_atom(MessagePackageRaw);
@@ -118,7 +124,7 @@ parse_message_package(BadMessagePackage) ->
%% pretty | compact | ber | per | erlang
%%
-meas_init(Factor, MessagePackage, Codecs) ->
+meas_init(Factor, Opts, MessagePackage, Codecs) ->
%% process_flag(trap_exit, true),
io:format("~nRun meas on message package: ~p~n~n", [MessagePackage]),
display_os_info(),
@@ -129,7 +135,7 @@ meas_init(Factor, MessagePackage, Codecs) ->
case megaco_codec_transform:messages(MessagePackage) of
Messages when is_list(Messages) ->
ExpandedMessages = expand_messages(Codecs, Messages),
- Results = t1(Factor, ExpandedMessages, []),
+ Results = t1(Factor, Opts, ExpandedMessages, []),
display_time(Started, os:timestamp()),
store_results(Results);
Error ->
@@ -144,12 +150,8 @@ display_os_info() ->
Str ->
Str
end,
- case os:type() of
- {OsFam, OsName} ->
- io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]);
- OsFam ->
- io:format("OS: ~p: ~s~n", [OsFam, V])
- end.
+ {OsFam, OsName} = os:type(),
+ io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]).
display_system_info() ->
SysArch = string:strip(erlang:system_info(system_architecture),right,$\n),
@@ -163,6 +165,16 @@ display_app_info() ->
display_megaco_info(),
display_asn1_info().
+%% The instruction, nowarn_function, is because I can't figure out
+%% how to suppress the warnings about
+%% megaco_flex_scanner:is_enabled/0 and
+%% megaco_flex_scanner:is_reentrant_enabled/0:
+%%
+%% "The pattern 'false' can never match the type 'true'"
+%%
+%% This is because the result of calling these function(s) is
+%% basically decided at compile time (true or false).
+-dialyzer({nowarn_function, display_megaco_info/0}).
display_megaco_info() ->
MI = megaco:module_info(),
{value, {attributes, Attr}} = lists:keysearch(attributes, 1, MI),
@@ -236,26 +248,26 @@ format_diff(Start, Fin) ->
-t1(_Factor, [], Results) ->
+t1(_Factor, _Opts, [], Results) ->
lists:reverse(Results);
-t1(Factor, [{Id, Codec, Conf, _, _} = ECodec|EMsgs], Results) ->
- case (catch measure(Factor, ECodec)) of
+t1(Factor, Opts, [{Id, Codec, Conf, _, _} = ECodec|EMsgs], Results) ->
+ case (catch measure(Factor, Opts, ECodec)) of
{'EXIT', Reason} ->
error("measure of codec ~p exited: ~n~p", [Codec, Reason]),
- t1(Factor, EMsgs, Results);
+ t1(Factor, Opts, EMsgs, Results);
{error, Reason} ->
error("skipping codec ~p: ~n~p", [Codec, Reason]),
- t1(Factor, EMsgs, Results);
+ t1(Factor, Opts, EMsgs, Results);
{ok, Res} ->
- t1(Factor, EMsgs, [{Id, Conf, Res}| Results])
+ t1(Factor, Opts, EMsgs, [{Id, Conf, Res}| Results])
end.
-measure(Factor, {Id, Codec, Conf, Count, Msgs}) ->
+measure(Factor, Opts, {Id, Codec, Conf, Count, Msgs}) ->
io:format("[~s] measure using codec ~p ~p~n ", [?FTS(), Codec, Conf]),
{Init, Conf1} = measure_init(Conf),
Conf2 = [{version3,?V3}|Conf1],
- Res = measure(Factor, Id, Codec, Conf2, Msgs, [], Count),
+ Res = measure(Factor, Opts, Id, Codec, Conf2, Msgs, [], Count),
measure_fin(Init),
Res.
@@ -303,9 +315,7 @@ expand_codec(Codec) ->
{Codec, megaco_erl_dist_encoder, [compressed], 400},
{Codec, megaco_erl_dist_encoder, [megaco_compressed], 10000},
{Codec, megaco_erl_dist_encoder, [], 10000}
- ];
- Else ->
- exit({error, {invalid_codec, Else}})
+ ]
end.
@@ -322,10 +332,10 @@ measure_fin(_) ->
ok.
-measure(_Factor, _Dir, _Codec, _Conf, [], [], _MCount) ->
+measure(_Factor, _Opts, _Dir, _Codec, _Conf, [], [], _MCount) ->
{error, no_messages};
-measure(_Factor, _Dir, _Codec, _Conf, [], Res, _MCount) ->
+measure(_Factor, _Opts, _Dir, _Codec, _Conf, [], Res, _MCount) ->
Eavg = avg([Etime/Ecnt || #stat{ecount = Ecnt, etime = Etime} <- Res]),
Davg = avg([Dtime/Dcnt || #stat{dcount = Dcnt, dtime = Dtime} <- Res]),
@@ -340,33 +350,41 @@ measure(_Factor, _Dir, _Codec, _Conf, [], Res, _MCount) ->
{ok, lists:reverse(Res)};
-measure(Factor, Dir, Codec, Conf, [{Name, Bin}|Msgs], Results, MCount) ->
- io:format(" ~p", [Name]),
- case (catch do_measure(Factor, Dir, Codec, Conf, Name, Bin, MCount)) of
+measure(Factor, #{verbose := Verbose} = Opts,
+ Dir, Codec, Conf, [{Name, Bin}|Msgs], Results, MCount) ->
+ vprint(Verbose, " ~p", [Name]),
+ case (catch do_measure(Factor, Opts,
+ Dir, Codec, Conf, Name, Bin, MCount)) of
{ok, Stat} ->
- measure(Factor, Dir, Codec, Conf, Msgs, [Stat | Results], MCount);
+ measure(Factor, Opts,
+ Dir, Codec, Conf, Msgs, [Stat | Results], MCount);
{error, S} ->
- io:format("~n[~s] ~s failed: ~n", [?FTS(), Name]),
+ if
+ (Verbose =:= true) ->
+ io:format("~n[~s] ~s failed: ~n", [?FTS(), Name]);
+ true ->
+ io:format("[~s] ~s failed: ~n", [?FTS(), Name])
+ end,
error(S,[]),
- measure(Factor, Dir, Codec, Conf, Msgs, Results, MCount);
+ measure(Factor, Opts, Dir, Codec, Conf, Msgs, Results, MCount);
{info, S} ->
- case get(verbose) of
+ vprint(Verbose, "~n"),
+ case Verbose orelse get(verbose) of
true ->
- io:format("~n", []),
info(S,[]);
_ ->
- io:format("~n~s skipped~n", [Name])
+ io:format("~s skipped~n", [Name])
end,
- measure(Factor, Dir, Codec, Conf, Msgs, Results, MCount)
+ measure(Factor, Opts, Dir, Codec, Conf, Msgs, Results, MCount)
end.
-do_measure(Factor, _Id, Codec, Conf, Name, BinMsg, MCount) ->
+do_measure(Factor, Opts, _Id, Codec, Conf, Name, BinMsg, MCount) ->
%% io:format("~n~s~n", [binary_to_list(BinMsg)]),
- {Version, NewBin} = detect_version(Codec, Conf, BinMsg),
+ {Version, NewBin} = detect_version(Opts, Codec, Conf, BinMsg),
{Msg, Dcnt, Dtime} =
measure_decode(Factor, Codec, Conf, Version, NewBin, MCount),
{_, Ecnt, Etime} =
@@ -377,16 +395,21 @@ do_measure(Factor, _Id, Codec, Conf, Name, BinMsg, MCount) ->
dcount = Dcnt, dtime = Dtime,
size = size(NewBin)}}.
-detect_version(Codec, Conf, Bin) ->
+detect_version(#{verbose := Verbose} = _Opts, Codec, Conf, Bin) ->
case (catch Codec:version_of(Conf, Bin)) of
{ok, V} ->
- io:format("[~w]", [V]),
- {ok, M} = Codec:decode_message(Conf, V, Bin),
+ vprint(Verbose, "[~w]", [V]),
+ {ok, M} = Codec:decode_message(Conf, V, Bin),
{ok, NewBin} = Codec:encode_message(Conf, V, M),
- io:format("[~w]", [size(NewBin)]),
+ vprint(Verbose, "[~w]", [size(NewBin)]),
{V, NewBin};
Error ->
- io:format("~nversion detection failed:~n~p", [Error]),
+ if
+ (Verbose =:= true) ->
+ io:format("~nversion detection failed:~n~p", [Error]);
+ true ->
+ io:format("version detection failed:~n~p", [Error])
+ end,
Error
end.
@@ -416,20 +439,21 @@ measure_codec(Factor, Codec, Func, Conf, Version, Bin, MCount)
is_atom(Func) andalso
is_list(Conf) andalso
is_integer(MCount) andalso (MCount > 0) ->
- Self = self(),
- Pid = spawn_link(?MODULE, do_measure_codec,
- [Factor, Self, Codec, Func, Conf, Version, Bin, MCount]),
+ {Pid, MRef} =
+ spawn_monitor(?MODULE, do_measure_codec,
+ [Factor, Codec, Func, Conf, Version, Bin, MCount]),
receive
- {measure_result, Pid, Func, Res} ->
+ {'DOWN', MRef, process, Pid, {measure_result, Res}} ->
{ok, Res};
- {error, Pid, Error} ->
+ {'DOWN', MRef, process, Pid, {error, Error}} ->
{error, Error};
- Else ->
+ {'DOWN', MRef, process, Pid, Else} ->
{error, {unexpected_result, Else}}
after ?MEASURE_TIMEOUT ->
Info =
case (catch process_info(Pid)) of
I when is_list(I) ->
+ erlang:demonitor(MRef),
exit(Pid, kill),
I;
_ ->
@@ -439,23 +463,17 @@ measure_codec(Factor, Codec, Func, Conf, Version, Bin, MCount)
end.
-do_measure_codec(Factor, Parent, Codec, Func, Conf, Version, Bin, MCount) ->
+do_measure_codec(Factor, Codec, Func, Conf, Version, Bin, MCount) ->
{ok, Count} = measure_warmup(Codec, Func, Conf, Version, Bin, MCount),
Count2 = Count div Factor,
- %% io:format("do_measure_codec(~w, ~w) -> warmed up:"
- %% "~n MCount: ~w"
- %% "~n Count: ~w"
- %% "~n Count2: ~w", [Codec, Func, MCount, Count, Count2]),
Res = timer:tc(?MODULE, do_measure_codec_loop,
[Codec, Func, Conf, Version, Bin, Count2, dummy]),
case Res of
{Time, {ok, M}} ->
- %% io:format("~w ", [Time]),
- Parent ! {measure_result, self(), Func, {M, Count2, Time}};
+ exit({measure_result, {M, Count2, Time}});
{_Time, Error} ->
- Parent ! {error, self(), Error}
- end,
- unlink(Parent). % Make sure Parent don't get our exit signal
+ exit({error, Error})
+ end.
%% This function does more or less what the real measure function
@@ -467,11 +485,17 @@ measure_warmup(Codec, Func, Conf, Version, M, MCount) ->
Res = timer:tc(?MODULE, do_measure_codec_loop,
[Codec, Func, Conf, Version, M, MCount, dummy]),
case Res of
- {Time, {ok, _}} when is_integer(Time) ->
+ {Time, {ok, _}} when is_integer(Time) andalso (Time > 0) ->
%% OK so far, now calculate the count:
- Count = round(?MEASURE_COUNT_TIME/(Time/MCount)),
- %% io:format("~w ", [Count]),
- {ok, Count};
+ %% For some reason we get a 'badarith' on some platforms
+ %% here. Since this is just the warmup we can try-catch.
+ try round(?MEASURE_COUNT_TIME/(Time/MCount)) of
+ Count ->
+ {ok, Count}
+ catch
+ _:_:_ ->
+ {error, {failed_calculated_count, Time, MCount}}
+ end;
{Time, Error} ->
{error, {warmup_failed, Time, Error}}
end.
@@ -666,6 +690,17 @@ flex_scanner_handler(Pid, PortOrPorts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+vprint(Verbose, F) ->
+ vprint(Verbose, F, []).
+
+vprint(true, F, A) ->
+ io:format(F, A);
+vprint(_, _, _) ->
+ ok.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
info(F, A) ->
io:format(F ++ "~n", A).
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone1.erl b/lib/megaco/examples/meas/megaco_codec_mstone1.erl
index 0d3615e7a3..9ed253dd0f 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone1.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone1.erl
@@ -229,7 +229,7 @@ do_mstone(MessagePackage, RunTime, Factor, Codecs, DrvInclude) ->
?LIB:display_system_info(),
?LIB:display_app_info(),
io:format("~n", []),
- case ?LIB:start_flex_scanner() of
+ try ?LIB:start_flex_scanner() of
{Pid, Conf} when is_pid(Pid) ->
put(flex_scanner_conf, Conf),
EMessages = ?LIB:expanded_messages(MessagePackage, Codecs, DrvInclude),
@@ -238,8 +238,9 @@ do_mstone(MessagePackage, RunTime, Factor, Codecs, DrvInclude) ->
?LIB:stop_flex_scanner(Pid),
io:format("~n", []),
io:format("MStone: ~p~n", [MStone]),
- done;
- {error, Reason} = ERROR ->
+ done
+ catch
+ throw:{error, Reason} = ERROR ->
io:format("<ERROR> Failed starting flex scanner: "
"~n ~p", [Reason]),
ERROR
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone2.erl b/lib/megaco/examples/meas/megaco_codec_mstone2.erl
index 3a8c1e6916..0368ecc38e 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone2.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone2.erl
@@ -113,7 +113,7 @@ start([RunTimeAtom, Mode, MessagePackage])
?LIB:parse_runtime(RunTimeAtom), Mode, MessagePackage);
start(RunTime) when is_integer(RunTime) andalso (RunTime > 0) ->
do_start(?DEFAULT_FACTOR,
- time:minutes(RunTime), ?DEFAULT_MODE, ?DEFAULT_MESSAGE_PACKAGE);
+ timer:minutes(RunTime), ?DEFAULT_MODE, ?DEFAULT_MESSAGE_PACKAGE);
start(MessagePackage) ->
do_start(?DEFAULT_FACTOR,
?DEFAULT_RUN_TIME, ?DEFAULT_MODE, MessagePackage).
@@ -304,30 +304,26 @@ loader(Factor, RunTime, Mode, Codecs, MessagePackage) ->
case (catch init(Factor, RunTime, Mode, Codecs, MessagePackage)) of
{ok, State} ->
loader_loop(running, State);
- Error ->
+ {error, Reason} = Error ->
+ io:format("<ERROR> Failed starting loader: "
+ "~n ~p", [Reason]),
exit(Error)
end.
init(Factor, RunTime, Mode, Codecs, MessagePackage) ->
ets:new(mstone, [set, private, named_table, {keypos, 1}]),
ets:insert(mstone, {worker_cnt, 0}),
- case ?LIB:start_flex_scanner() of
- {Pid, FlexConf} when is_pid(Pid) ->
- io:format("prepare messages", []),
- EMessages = ?LIB:expanded_messages(MessagePackage, Codecs, Mode),
- io:format("~ninit codec data", []),
- CodecData = init_codec_data(Factor, EMessages, FlexConf),
- Timer = erlang:send_after(RunTime, self(), mstone_finished),
- io:format(" => ~w concurrent workers~n", [length(CodecData)]),
- {ok, #state{timer = Timer,
- idle = CodecData,
- flex_handler = Pid,
- flex_conf = FlexConf}};
- {error, Reason} = ERROR ->
- io:format("<ERROR> Failed starting flex scanner: "
- "~n ~p", [Reason]),
- ERROR
- end.
+ {Pid, FlexConf} = ?LIB:start_flex_scanner(),
+ io:format("prepare messages", []),
+ EMessages = ?LIB:expanded_messages(MessagePackage, Codecs, Mode),
+ io:format("~ninit codec data", []),
+ CodecData = init_codec_data(Factor, EMessages, FlexConf),
+ Timer = erlang:send_after(RunTime, self(), mstone_finished),
+ io:format(" => ~w concurrent workers~n", [length(CodecData)]),
+ {ok, #state{timer = Timer,
+ idle = CodecData,
+ flex_handler = Pid,
+ flex_conf = FlexConf}}.
init_codec_data(Factor, EMsgs, FlexConf) ->
init_codec_data_expand(Factor, init_codec_data(EMsgs, FlexConf)).
@@ -345,7 +341,7 @@ init_codec_data(Codec, Mod, Conf0, Msgs0, FlexConf)
when is_atom(Codec) andalso
is_atom(Mod) andalso
is_list(Conf0) andalso
- is_list(Msgs0) ->
+ is_list(Msgs0) ->
io:format(".", []),
Conf = [{version3,?VERSION3}|init_codec_conf(FlexConf, Conf0)],
Msgs = [?LIB:detect_version(Mod, Conf, Bin) || {_, Bin} <- Msgs0],
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
index 4ab230c65b..7044a17430 100644
--- a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
+++ b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
@@ -83,12 +83,8 @@ display_os_info() ->
Str ->
Str
end,
- case os:type() of
- {OsFam, OsName} ->
- io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]);
- OsFam ->
- io:format("OS: ~p: ~s~n", [OsFam, V])
- end.
+ {OsFam, OsName} = os:type(),
+ io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]).
%%----------------------------------------------------------------------
@@ -191,12 +187,8 @@ display_alloc_info([{Alloc, Mem}|AllocInfo]) ->
display_alloc_info(AllocInfo).
alloc_info() ->
- case erlang:system_info(allocator) of
- {_Allocator, _Version, Features, _Settings} ->
- alloc_info(Features);
- _ ->
- []
- end.
+ {_Allocator, _Version, Features, _Settings} = erlang:system_info(allocator),
+ alloc_info(Features).
alloc_info(Allocators) ->
Allocs = [temp_alloc, sl_alloc, std_alloc, ll_alloc, eheap_alloc,
diff --git a/lib/megaco/examples/simple/Makefile b/lib/megaco/examples/simple/Makefile
index 00c0b7e65e..8f1ca41433 100644
--- a/lib/megaco/examples/simple/Makefile
+++ b/lib/megaco/examples/simple/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2016. All Rights Reserved.
+# Copyright Ericsson AB 2001-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -100,13 +100,29 @@ MGC_START_ARGS += "{debug,false}"
endif
+DIA_PLT = megaco_example_simple.plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+ifeq ($(DIAW_EH),true)
+DIA_WARNINGS += -Werror_handling
+endif
+ifeq ($(DIAW_US),true)
+DIA_WARNINGS += -Wunderspecs
+endif
+ifeq ($(DIAW_UR),true)
+DIA_WARNINGS += -Wunmatched_returns
+endif
+DIA_PLT_APPS = \
+ erts asn1 et kernel stdlib compiler debugger \
+ runtime_tools crypto mnesia wx
+
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
opt: $(TARGET_FILES)
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
clean:
rm -f $(TARGET_FILES)
@@ -114,8 +130,36 @@ clean:
docs:
-info:
+info:
@echo "MEGACO_ROOT_DIR = $(MEGACO_ROOT_DIR)"
+ @echo ""
+ @echo "DIA_PLT = $(DIA_PLT)"
+ @echo "DIA_ANALYSIS = $(DIA_ANALYSIS)"
+ @echo "DIA_PLT_APPS = $(DIA_PLT_APPS)"
+ @echo ""
+
+
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT): $(ERL_FILES)
+ @echo "Building $(basename $(DIA_PLT)) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ --apps --apps $(sort $(APPLICATION) $(DIA_PLT_APPS)) \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on megaco example simple"
+ @dialyzer --plt $< \
+ -r ../../ebin \
+ $(DIA_WARNINGS) \
+ --verbose
+
# ----------------------------------------------------
# Special Build Targets
diff --git a/lib/megaco/examples/simple/megaco_simple_mg.erl b/lib/megaco/examples/simple/megaco_simple_mg.erl
index 83293b810d..b71cf3c628 100644
--- a/lib/megaco/examples/simple/megaco_simple_mg.erl
+++ b/lib/megaco/examples/simple/megaco_simple_mg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -108,6 +108,13 @@ get_arg(Key, Args) ->
{value, {Key, Val}} = lists:keysearch(Key, 1, Args),
Val.
+
+-spec init_batch(ReplyTo :: pid(),
+ MgcHost :: term(),
+ Trace :: term(),
+ Debug :: term()) ->
+ no_return().
+
init_batch(ReplyTo, MgcHost, Trace, Debug) ->
register(?MODULE, self()),
Res = start(MgcHost, Trace, Debug),
diff --git a/lib/megaco/examples/simple/megaco_simple_mgc.erl b/lib/megaco/examples/simple/megaco_simple_mgc.erl
index 8a78262b86..40a27955f4 100644
--- a/lib/megaco/examples/simple/megaco_simple_mgc.erl
+++ b/lib/megaco/examples/simple/megaco_simple_mgc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -406,7 +406,13 @@ start_batch(Args0) ->
io:format("~p(~p): ~p~n", [?MODULE, ?LINE, Res]),
Res
end.
+
+-spec init_batch(ReplyTo :: pid(),
+ Trace :: term(),
+ Debug :: term()) ->
+ no_return().
+
init_batch(ReplyTo, Trace, Debug) ->
register(?MODULE, self()),
Res = start(Trace, Debug),
diff --git a/lib/megaco/src/app/Makefile b/lib/megaco/src/app/Makefile
index ab45548099..c681b88428 100644
--- a/lib/megaco/src/app/Makefile
+++ b/lib/megaco/src/app/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2007-2016. All Rights Reserved.
+# Copyright Ericsson AB 2007-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -74,8 +74,8 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/megaco/src/app/megaco.erl b/lib/megaco/src/app/megaco.erl
index de6caaae3b..d0816b1dd0 100644
--- a/lib/megaco/src/app/megaco.erl
+++ b/lib/megaco/src/app/megaco.erl
@@ -721,10 +721,10 @@ nc() ->
nc(Mods).
nc(all) ->
- application:load(?APPLICATION),
+ _ = application:load(?APPLICATION),
case application:get_key(?APPLICATION, modules) of
{ok, Mods} ->
- application:unload(?APPLICATION),
+ _ = application:unload(?APPLICATION),
nc(Mods);
_ ->
{error, not_found}
@@ -741,10 +741,10 @@ ni() ->
end.
ni(all) ->
- application:load(?APPLICATION),
+ _ = application:load(?APPLICATION),
case application:get_key(?APPLICATION, modules) of
{ok, Mods} ->
- application:unload(?APPLICATION),
+ _ = application:unload(?APPLICATION),
ni(Mods);
_ ->
{error, not_found}
diff --git a/lib/megaco/src/app/megaco.mk b/lib/megaco/src/app/megaco.mk
index a887dd42bc..ce2b265ffc 100644
--- a/lib/megaco/src/app/megaco.mk
+++ b/lib/megaco/src/app/megaco.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2007-2021. All Rights Reserved.
+# Copyright Ericsson AB 2007-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,6 +42,12 @@ ifeq ($(WARN_UNUSED_WARS), true)
ERL_COMPILE_FLAGS += +warn_unused_vars
endif
+ifeq ($(ERL_DETERMINISTIC),yes)
+ERL_COMPILE_FLAGS += +deterministic
+YRL_FLAGS += +deterministic
+XRL_FLAGS += +deterministic
+endif
+
MEGACO_APP_VSN_COMPILE_FLAGS = \
+'{parse_transform,sys_pre_attributes}' \
+'{attribute,insert,app_vsn,$(APP_VSN)}'
diff --git a/lib/megaco/src/binary/Makefile b/lib/megaco/src/binary/Makefile
index 9e33fe3ae5..9ecb649f0c 100644
--- a/lib/megaco/src/binary/Makefile
+++ b/lib/megaco/src/binary/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2020. All Rights Reserved.
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -100,8 +100,8 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: prebuild $(TARGET_FILES)
diff --git a/lib/megaco/src/binary/depend.mk b/lib/megaco/src/binary/depend.mk
index ca2872975c..c03f557e24 100644
--- a/lib/megaco/src/binary/depend.mk
+++ b/lib/megaco/src/binary/depend.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2020. All Rights Reserved.
+# Copyright Ericsson AB 2001-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -35,6 +35,10 @@ ifeq ($(MEGACO_INLINE_ASN1_RT),true)
ASN1_CT_OPTS += +inline
endif
+ifeq ($(ERL_DETERMINISTIC),yes)
+ASN1_CT_OPTS += +deterministic
+endif
+
BER_V1_FLAGS = $(ASN1_CT_OPTS) +asn1config
BER_V2_FLAGS = $(ASN1_CT_OPTS) +asn1config
BER_V3_FLAGS = $(ASN1_CT_OPTS) +asn1config
diff --git a/lib/megaco/src/engine/Makefile b/lib/megaco/src/engine/Makefile
index 869b516b05..cc4974e09d 100644
--- a/lib/megaco/src/engine/Makefile
+++ b/lib/megaco/src/engine/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -74,8 +74,8 @@ ERL_COMPILE_FLAGS += \
$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/megaco/src/engine/megaco_config.erl b/lib/megaco/src/engine/megaco_config.erl
index 0805acab9b..1b019fd535 100644
--- a/lib/megaco/src/engine/megaco_config.erl
+++ b/lib/megaco/src/engine/megaco_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -899,9 +899,9 @@ init([Parent]) ->
do_init() ->
?megaco_test_init(),
- ets:new(megaco_config, [public, named_table, {keypos, 1}]),
- ets:new(megaco_local_conn, [public, named_table, {keypos, 2}]),
- ets:new(megaco_remote_conn, [public, named_table, {keypos, 2}, bag]),
+ _ = ets:new(megaco_config, [public, named_table, {keypos, 1}]),
+ _ = ets:new(megaco_local_conn, [public, named_table, {keypos, 2}]),
+ _ = ets:new(megaco_remote_conn, [public, named_table, {keypos, 2}, bag]),
megaco_stats:init(megaco_stats, global_snmp_counters()),
init_scanner(),
init_user_defaults(),
@@ -1467,7 +1467,7 @@ handle_start_user(Mid, Config) ->
case catch user_info(Mid, mid) of
{'EXIT', _} ->
DefaultConfig = user_info(default, all),
- do_handle_start_user(Mid, DefaultConfig),
+ _ = do_handle_start_user(Mid, DefaultConfig),
do_handle_start_user(Mid, Config);
_LocalMid ->
{error, {user_already_exists, Mid}}
@@ -1482,7 +1482,7 @@ do_handle_start_user(UserMid, [{Item, Val} | Rest]) ->
{error, Reason}
end;
do_handle_start_user(UserMid, []) ->
- do_update_user(UserMid, mid, UserMid),
+ _ = do_update_user(UserMid, mid, UserMid),
ok;
do_handle_start_user(UserMid, BadConfig) ->
ets:match_delete(megaco_config, {{UserMid, '_'}, '_'}),
@@ -1715,7 +1715,7 @@ update_auto_ack(#conn_data{trans_timer = To,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{auto_ack = true, trans_sender = Pid};
@@ -1746,7 +1746,7 @@ update_trans_ack(#conn_data{trans_timer = To,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{trans_ack = true, trans_sender = Pid};
@@ -1775,7 +1775,7 @@ update_trans_req(#conn_data{trans_timer = To,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{trans_req = true, trans_sender = Pid};
@@ -1799,7 +1799,7 @@ update_trans_timer(#conn_data{auto_ack = true,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{trans_timer = To, trans_sender = Pid};
@@ -1817,7 +1817,7 @@ update_trans_timer(#conn_data{trans_req = true,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{trans_timer = To, trans_sender = Pid};
@@ -1968,7 +1968,7 @@ trans_sender_start(#conn_data{conn_handle = CH,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{trans_sender = Pid};
@@ -1997,7 +1997,7 @@ trans_sender_start(#conn_data{conn_handle = CH,
%% sender goes down.
%% Do we need to store the ref? Will we ever need to
%% cancel this (apply_at_exit)?
- megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
+ _ = megaco_monitor:apply_at_exit(?MODULE, trans_sender_exit, [CH], Pid),
CD#conn_data{trans_sender = Pid};
@@ -2150,7 +2150,7 @@ update_snmp_counters(CH, PrelCH, [Counter|Counters]) ->
PrelKey = {PrelCH, Counter},
Key = {CH, Counter},
[{PrelKey,PrelVal}] = ets:lookup(megaco_stats, PrelKey),
- ets:update_counter(megaco_stats, Key, PrelVal),
+ _ = ets:update_counter(megaco_stats, Key, PrelVal),
ets:delete(megaco_stats, PrelKey),
update_snmp_counters(CH, PrelCH, Counters).
diff --git a/lib/megaco/src/engine/megaco_digit_map.erl b/lib/megaco/src/engine/megaco_digit_map.erl
index 5b8b1f3b8f..820cb2179e 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -842,7 +842,7 @@ cast(Pid, Event) ->
test(DigitMap, Events) ->
Self = self(),
Pid = spawn_link(?MODULE, test_eval, [DigitMap, Self]),
- report(Pid, Events),
+ _ = report(Pid, Events),
receive
{Self, Pid, Res} ->
Res;
diff --git a/lib/megaco/src/engine/megaco_filter.erl b/lib/megaco/src/engine/megaco_filter.erl
index 4bd3bd518b..74326a0ced 100644
--- a/lib/megaco/src/engine/megaco_filter.erl
+++ b/lib/megaco/src/engine/megaco_filter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -300,10 +300,10 @@ do_filter_contents([H | T], E, ConnData, Contents) ->
E2 =
case E#event.label of
[$s, $e, $n, $d, $ , $b, $y, $t, $e, $s | Tail] ->
- L = lists:concat(["send ", size(Bin), " bytes", Tail]),
+ L = lists:concat(["send ", byte_size(Bin), " bytes", Tail]),
E#event{label = L};
[$r, $e, $c, $e, $i, $v, $e, $ , $b, $y, $t, $e, $s | Tail] ->
- L = lists:concat(["receive ", size(Bin), " bytes", Tail]),
+ L = lists:concat(["receive ", byte_size(Bin), " bytes", Tail]),
E#event{label = L};
_ ->
E
diff --git a/lib/megaco/src/engine/megaco_messenger.erl b/lib/megaco/src/engine/megaco_messenger.erl
index 2a9ecee2a7..dfb10dc869 100644
--- a/lib/megaco/src/engine/megaco_messenger.erl
+++ b/lib/megaco/src/engine/megaco_messenger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -545,7 +545,7 @@ disconnect(ConnHandle, DiscoReason)
case megaco_config:disconnect(ConnHandle) of
{ok, ConnData, RemoteConnData} ->
ControlRef = ConnData#conn_data.monitor_ref,
- cancel_apply_at_exit(ControlRef),
+ _ = cancel_apply_at_exit(ControlRef),
handle_disconnect_callback(ConnData, DiscoReason),
ControlNode = node_of_control_pid(ConnData#conn_data.control_pid),
case ControlNode =:= node() of
@@ -554,7 +554,7 @@ disconnect(ConnHandle, DiscoReason)
CancelFun =
fun(RCD) ->
UserRef = RCD#remote_conn_data.monitor_ref,
- cancel_apply_at_exit(UserRef),
+ _ = cancel_apply_at_exit(UserRef),
RCD#remote_conn_data.user_node
end,
Nodes = lists:map(CancelFun, RemoteConnData),
@@ -602,7 +602,7 @@ disconnect_remote(_Reason, ConnHandle, UserNode) ->
case megaco_config:disconnect_remote(ConnHandle, UserNode) of
[RCD] ->
Ref = RCD#remote_conn_data.monitor_ref,
- cancel_apply_at_exit(Ref),
+ _ = cancel_apply_at_exit(Ref),
ok;
[] ->
{error, {no_connection, ConnHandle}}
@@ -619,9 +619,10 @@ receive_message(ReceiveHandle, ControlPid, SendHandle, Bin) ->
receive_message(ReceiveHandle, ControlPid, SendHandle, Bin, Extra) ->
Opts = [link , {min_heap_size, 5000}],
- spawn_opt(?MODULE,
- process_received_message,
- [ReceiveHandle, ControlPid, SendHandle, Bin, self(), Extra], Opts),
+ _ = spawn_opt(?MODULE,
+ process_received_message,
+ [ReceiveHandle,
+ ControlPid, SendHandle, Bin, self(), Extra], Opts),
ok.
%% This function is called via the spawn_opt function with the link
@@ -1131,20 +1132,20 @@ prepare_autoconnecting_trans(ConnData, [Trans | Rest], AckList, ReqList, Extra)
Limit = ConnData#conn_data.sent_pending_limit,
TransId = to_remote_trans_id(ConnData2),
- case check_and_maybe_incr_pending_limit(Limit, sent, TransId) of
- ok ->
- send_pending(ConnData2);
- error ->
- %% Pending limit:
- %% In this (granted, highly hypothetical case)
- %% we would make the user very confused if we
- %% called the abort callback function, since
- %% the request callback function has not yet
- %% been called. Alas, we skip this call here.
- send_pending_limit_error(ConnData);
- aborted ->
- ignore
- end,
+ _ = case check_and_maybe_incr_pending_limit(Limit, sent, TransId) of
+ ok ->
+ send_pending(ConnData2);
+ error ->
+ %% Pending limit:
+ %% In this (granted, highly hypothetical case)
+ %% we would make the user very confused if we
+ %% called the abort callback function, since
+ %% the request callback function has not yet
+ %% been called. Alas, we skip this call here.
+ send_pending_limit_error(ConnData);
+ aborted ->
+ ignore
+ end,
prepare_autoconnecting_trans(ConnData2, Rest, AckList, ReqList,
Extra);
_ ->
@@ -1251,8 +1252,8 @@ prepare_request(ConnData, T, Rest, AckList, ReqList, Extra) ->
?report_debug(ConnData,
"prepare request: conflicting requests",
[TransId]),
- send_pending(ConnData),
- megaco_monitor:cancel_apply_after(PendingRef),
+ _ = send_pending(ConnData),
+ _ = megaco_monitor:cancel_apply_after(PendingRef),
prepare_normal_trans(ConnData, Rest, AckList, ReqList,
Extra)
end;
@@ -1294,7 +1295,7 @@ prepare_request(ConnData, T, Rest, AckList, ReqList, Extra) ->
%%
%% ------------------------------------------
- send_pending(ConnData),
+ _ = send_pending(ConnData),
prepare_normal_trans(ConnData, Rest, AckList, ReqList,
Extra);
@@ -1330,8 +1331,8 @@ prepare_request(ConnData, T, Rest, AckList, ReqList, Extra) ->
%% State == prepare:
%% The user does not know about this request
%% so we can safely perform cleanup.
- %%
- megaco_monitor:cancel_apply_after(Ref),
+ %%
+ _ = megaco_monitor:cancel_apply_after(Ref),
send_pending_limit_error(ConnData),
if
State == eval_request ->
@@ -1682,7 +1683,7 @@ do_handle_request(AckAction, {ok, Bin}, ConnData, TransId)
%% - Delete the pending counter
%%
- megaco_monitor:cancel_apply_after(PendingRef),
+ _ = megaco_monitor:cancel_apply_after(PendingRef),
megaco_config:del_pending_counter(sent, TransId),
Method = timer_method(AckAction),
@@ -1725,7 +1726,7 @@ do_handle_request(AckAction, {ok, {Sent, NotSent}}, ConnData, TransId)
%% - Delete the pending counter
%%
- megaco_monitor:cancel_apply_after(PendingRef),
+ _ = megaco_monitor:cancel_apply_after(PendingRef),
megaco_config:del_pending_counter(sent, TransId),
Method = timer_method(AckAction),
@@ -2178,7 +2179,7 @@ handle_recv_pending(#conn_data{long_request_resend = LRR,
%% We can now drop the "bytes", since we will
%% not resend from now on.
- megaco_monitor:cancel_apply_after(Ref),
+ _ = megaco_monitor:cancel_apply_after(Ref),
{WaitFor, CurrTimer} = megaco_timer:init(InitTimer),
ConnHandle = ConnData#conn_data.conn_handle,
M = ?MODULE,
@@ -2234,7 +2235,7 @@ handle_recv_pending(#conn_data{conn_handle = ConnHandle} = ConnData, TransId,
%% We just need to recalculate the timer, i.e.
%% increment the timer (one "slot" has been consumed).
- megaco_monitor:cancel_apply_after(Ref),
+ _ = megaco_monitor:cancel_apply_after(Ref),
{WaitFor, Timer2} = megaco_timer:restart(CurrTimer),
ConnHandle = ConnData#conn_data.conn_handle,
M = ?MODULE,
@@ -2256,12 +2257,12 @@ handle_recv_pending_error(ConnData, TransId, Req, T, Extra) ->
megaco_monitor:delete_request(TransId),
%% 2) Possibly cancel the timer
- case Req#request.timer_ref of
- {_, Ref} ->
- megaco_monitor:cancel_apply_after(Ref);
- _ ->
- ok
- end,
+ _ = case Req#request.timer_ref of
+ {_, Ref} ->
+ megaco_monitor:cancel_apply_after(Ref);
+ _ ->
+ ok
+ end,
%% 3) Delete the (receive) pending counter
megaco_config:del_pending_counter(recv, TransId),
@@ -2310,10 +2311,10 @@ handle_reply(
[T]),
%% Stop the request timer
- megaco_monitor:cancel_apply_after(Ref), %% OTP-4843
+ _ = megaco_monitor:cancel_apply_after(Ref), %% OTP-4843
%% Acknowledge the segment
- send_segment_reply(ConnData, SN),
+ _ = send_segment_reply(ConnData, SN),
%% First segment for this reply
NewFields =
@@ -2353,7 +2354,7 @@ handle_reply(
[T]),
%% Acknowledge the segment
- send_segment_reply(ConnData, SN),
+ _ = send_segment_reply(ConnData, SN),
%% Updated/handle received segment
case lists:member(SN, Segs) of
@@ -2400,7 +2401,7 @@ handle_reply(
[T]),
%% Acknowledge the segment
- send_segment_reply(ConnData, SN),
+ _ = send_segment_reply(ConnData, SN),
%% Updated received segments
case lists:member(SN, Segs) of
@@ -2413,9 +2414,9 @@ handle_reply(
Last =
case is_all_segments([SN | Segs]) of
{true, _Sorted} ->
- megaco_monitor:cancel_apply_after(SegRef),
+ _ = megaco_monitor:cancel_apply_after(SegRef),
megaco_monitor:delete_request(TransId),
- send_ack(ConnData),
+ _ = send_ack(ConnData),
true;
{false, Sorted} ->
megaco_monitor:update_request_field(TransId,
@@ -2477,10 +2478,10 @@ handle_reply(
"first/complete seg", [T]),
%% Stop the request timer
- megaco_monitor:cancel_apply_after(Ref), %% OTP-4843
+ _ = megaco_monitor:cancel_apply_after(Ref), %% OTP-4843
%% Acknowledge the ("last") segment
- send_segment_reply_complete(ConnData, SN),
+ _ = send_segment_reply_complete(ConnData, SN),
%% It is ofcourse pointless to split
%% a transaction into just one segment,
@@ -2508,7 +2509,7 @@ handle_reply(
true ->
%% Just one segment!
megaco_monitor:delete_request(TransId),
- send_ack(ConnData),
+ _ = send_ack(ConnData),
true
end,
@@ -2537,7 +2538,7 @@ handle_reply(
[T]),
%% Acknowledge the ("last") segment
- send_segment_reply_complete(ConnData, SN),
+ _ = send_segment_reply_complete(ConnData, SN),
%% Updated received segments
%% This is _probably_ the last segment, but some of
@@ -2555,7 +2556,7 @@ handle_reply(
"[segmented] trans reply - "
"complete set", [T]),
megaco_monitor:delete_request(TransId),
- send_ack(ConnData),
+ _ = send_ack(ConnData),
true;
{false, Sorted} ->
ConnHandle = ConnData#conn_data.conn_handle,
@@ -2736,11 +2737,11 @@ do_handle_reply(CD,
%% This is the first reply (maybe of many)
megaco_monitor:delete_request(TransId),
megaco_monitor:request_lockcnt_del(TransId),
- megaco_monitor:cancel_apply_after(Ref), % OTP-4843
+ _ = megaco_monitor:cancel_apply_after(Ref), % OTP-4843
megaco_config:del_pending_counter(recv, TransId), % OTP-7189
%% Send acknowledgement
- maybe_send_ack(T#megaco_transaction_reply.immAckRequired, CD),
+ _ = maybe_send_ack(T#megaco_transaction_reply.immAckRequired, CD),
UserReply =
case T#megaco_transaction_reply.transactionResult of
@@ -2778,7 +2779,7 @@ do_handle_reply(CD,
%% This *is* the first reply!!
%% 1) Stop resend timer
{_Type, Ref} = Req#request.timer_ref, % OTP-4843
- megaco_monitor:cancel_apply_after(Ref), % OTP-4843
+ _ = megaco_monitor:cancel_apply_after(Ref), % OTP-4843
%% 2) Delete pending counter
megaco_config:del_pending_counter(recv, TransId), % OTP-7189
@@ -2793,7 +2794,7 @@ do_handle_reply(CD,
RKAWaitFor),
%% 4) Maybe send acknowledgement (three-way-handshake)
- maybe_send_ack(T#megaco_transaction_reply.immAckRequired, CD),
+ _ = maybe_send_ack(T#megaco_transaction_reply.immAckRequired, CD),
%% 5) And finally store the updated request record
Req2 = Req#request{keep_alive_ref = RKARef},
@@ -2869,11 +2870,11 @@ handle_segment_reply(CD,
handle_segment_reply_callback(CD, TransId, SN, SC, Extra),
case lists:keysearch(SN, 1, Sent) of
{value, {SN, _Bin, SegTmr}} ->
- megaco_monitor:cancel_apply_after(SegTmr), %% BMK BMK
+ _ = megaco_monitor:cancel_apply_after(SegTmr), %% BMK BMK
case lists:keydelete(SN, 1, Sent) of
[] -> %% We are done
Ref = Rep#reply.timer_ref,
- megaco_monitor:cancel_apply_after(Ref),
+ _ = megaco_monitor:cancel_apply_after(Ref),
megaco_monitor:update_reply_field(TransId2,
#reply.bytes,
[]),
@@ -2896,7 +2897,7 @@ handle_segment_reply(CD,
handle_segment_reply_callback(CD, TransId, SN, SC, Extra),
case lists:keysearch(SN, 1, Sent) of
{value, {SN, _Bin, SegTmr}} ->
- megaco_monitor:cancel_apply_after(SegTmr), %% BMK BMK
+ _ = megaco_monitor:cancel_apply_after(SegTmr), %% BMK BMK
NewSent = lists:keydelete(SN, 1, Sent),
[{SN2, Bin2}|NewNotSent] = NotSent,
case send_reply_segment(CD, "send trans reply segment",
@@ -3026,14 +3027,14 @@ handle_ack(ConnData, OrigAckStatus,
handle_ack_callback(ConnData, AckStatus, AckAction, T, Extra).
handle_ack_cleanup(TransId, ReplyRef, PendingRef) ->
- megaco_monitor:cancel_apply_after(ReplyRef),
- megaco_monitor:cancel_apply_after(PendingRef),
+ _ = megaco_monitor:cancel_apply_after(ReplyRef),
+ _ = megaco_monitor:cancel_apply_after(PendingRef),
megaco_monitor:delete_reply(TransId),
megaco_config:del_pending_counter(sent, TransId). %% BMK: Still existing?
cancel_segment_timers(SegSent) when is_list(SegSent) ->
Cancel = fun({_, _, Ref}) ->
- megaco_monitor:cancel_apply_after(Ref)
+ megaco_monitor:cancel_apply_after(Ref)
end,
lists:foreach(Cancel, SegSent);
cancel_segment_timers(_) ->
@@ -4033,7 +4034,7 @@ send_reply(#conn_data{serial = Serial,
{ok, Bin} when is_binary(Bin) andalso (TransReq =:= true) ->
?rt2("send_reply - pass it on to the transaction sender",
[size(Bin)]),
- megaco_trans_sender:send_reply(TransSnd, Bin),
+ _ = megaco_trans_sender:send_reply(TransSnd, Bin),
{ok, Bin};
{ok, Bin} when is_binary(Bin) ->
@@ -4070,7 +4071,7 @@ send_reply(#conn_data{serial = Serial,
error_msg("failed encoding transaction reply body: ~s",
[format_encode_error_reason(Reason)]),
Body = {transactions, [{transactionReply, TR3}]},
- megaco_messenger_misc:send_body(CD, TraceLabel, Body),
+ _ = megaco_messenger_misc:send_body(CD, TraceLabel, Body),
Error
end.
@@ -4457,7 +4458,7 @@ do_receive_reply_remote(ConnData, TransId,
UserReply, Extra) ->
megaco_monitor:delete_request(TransId),
megaco_monitor:request_lockcnt_del(TransId),
- megaco_monitor:cancel_apply_after(Ref), % OTP-4843
+ _ = megaco_monitor:cancel_apply_after(Ref), % OTP-4843
megaco_config:del_pending_counter(recv, TransId), % OTP-7189
ConnData2 = ConnData#conn_data{user_mod = UserMod,
@@ -4471,7 +4472,7 @@ cancel_reply(ConnData, #reply{state = waiting_for_ack,
user_mod = UserMod,
user_args = UserArgs} = Rep, Reason) ->
?report_trace(ignore, "cancel reply [waiting_for_ack]", [Rep]),
- megaco_monitor:cancel_apply_after(Rep#reply.pending_timer_ref),
+ _ = megaco_monitor:cancel_apply_after(Rep#reply.pending_timer_ref),
Serial = (Rep#reply.trans_id)#trans_id.serial,
ConnData2 = ConnData#conn_data{serial = Serial,
user_mod = UserMod,
@@ -4486,8 +4487,8 @@ cancel_reply(_ConnData, #reply{state = aborted} = Rep, _Reason) ->
timer_ref = ReplyRef,
pending_timer_ref = PendingRef} = Rep,
megaco_monitor:delete_reply(TransId),
- megaco_monitor:cancel_apply_after(ReplyRef),
- megaco_monitor:cancel_apply_after(PendingRef), % Still running?
+ _ = megaco_monitor:cancel_apply_after(ReplyRef),
+ _ = megaco_monitor:cancel_apply_after(PendingRef), % Still running?
megaco_config:del_pending_counter(sent, TransId), % Still existing?
ok;
@@ -4497,8 +4498,8 @@ cancel_reply(_ConnData, Rep, ignore) ->
timer_ref = ReplyRef,
pending_timer_ref = PendingRef} = Rep,
megaco_monitor:delete_reply(TransId),
- megaco_monitor:cancel_apply_after(ReplyRef),
- megaco_monitor:cancel_apply_after(PendingRef), % Still running?
+ _ = megaco_monitor:cancel_apply_after(ReplyRef),
+ _ = megaco_monitor:cancel_apply_after(PendingRef), % Still running?
megaco_config:del_pending_counter(sent, TransId), % Still existing?
ok;
@@ -4508,7 +4509,7 @@ cancel_reply(_CD, _Rep, _Reason) ->
request_keep_alive_timeout(ConnHandle, TransId) ->
megaco_config:del_pending_counter(ConnHandle, TransId),
- megaco_monitor:lookup_request(TransId),
+ _ = megaco_monitor:lookup_request(TransId),
ok.
@@ -4853,7 +4854,7 @@ handle_reply_timer_timeout(ConnHandle, TransId) ->
{_Converted,
#reply{pending_timer_ref = Ref, % aborted?
bytes = SegSent}} -> % may be a binary
- megaco_monitor:cancel_apply_after(Ref),
+ _ = megaco_monitor:cancel_apply_after(Ref),
cancel_segment_timers(SegSent),
megaco_monitor:delete_reply(TransId),
megaco_config:del_pending_counter(sent, TransId);
@@ -4979,7 +4980,7 @@ handle_pending_timeout(CD, TransId, Timer) ->
%%
%% ---------------------------------------------
- send_pending(CD),
+ _ = send_pending(CD),
case Timer of
timeout ->
%% We are done
diff --git a/lib/megaco/src/engine/megaco_messenger_misc.erl b/lib/megaco/src/engine/megaco_messenger_misc.erl
index 091f64e5b4..d671bcafad 100644
--- a/lib/megaco/src/engine/megaco_messenger_misc.erl
+++ b/lib/megaco/src/engine/megaco_messenger_misc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -217,7 +217,7 @@ encode_action_replies(#conn_data{protocol_version = V,
[AR|ARs], Size, Acc) ->
case (catch Mod:encode_action_reply(Conf, V, AR)) of
{ok, Bin} when is_binary(Bin) ->
- encode_action_replies(CD, ARs, Size + size(Bin), [Bin|Acc]);
+ encode_action_replies(CD, ARs, Size + byte_size(Bin), [Bin|Acc]);
{'EXIT', {undef, _}} ->
throw({error, not_implemented});
{error, not_implemented} = Error1 ->
diff --git a/lib/megaco/src/engine/megaco_monitor.erl b/lib/megaco/src/engine/megaco_monitor.erl
index efda4d3716..34bd3a6706 100644
--- a/lib/megaco/src/engine/megaco_monitor.erl
+++ b/lib/megaco/src/engine/megaco_monitor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -232,8 +232,8 @@ cast(Msg) ->
init([Parent]) ->
?d("init -> entry", []),
process_flag(trap_exit, true),
- ets:new(megaco_requests, [public, named_table, {keypos, 2}]),
- ets:new(megaco_replies, [public, named_table, {keypos, 2}]),
+ _ = ets:new(megaco_requests, [public, named_table, {keypos, 2}]),
+ _ = ets:new(megaco_replies, [public, named_table, {keypos, 2}]),
?d("init -> done", []),
{ok, #state{parent_pid = Parent}}.
diff --git a/lib/megaco/src/engine/megaco_stats.erl b/lib/megaco/src/engine/megaco_stats.erl
index 1ca9faedb4..bf9d790074 100644
--- a/lib/megaco/src/engine/megaco_stats.erl
+++ b/lib/megaco/src/engine/megaco_stats.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ init(Name) ->
init(Name, []).
init(Name, GlobalCounters) ->
- ets:new(Name, [public, named_table, {keypos, 1}]),
+ _ = ets:new(Name, [public, named_table, {keypos, 1}]),
ets:insert(Name, {global_counters, GlobalCounters}),
create_global_snmp_counters(Name, GlobalCounters).
diff --git a/lib/megaco/src/engine/megaco_trans_sender.erl b/lib/megaco/src/engine/megaco_trans_sender.erl
index 871a074171..84a72e82f5 100644
--- a/lib/megaco/src/engine/megaco_trans_sender.erl
+++ b/lib/megaco/src/engine/megaco_trans_sender.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -162,17 +162,17 @@ loop(#state{reqs = [], acks = [], timeout = Timeout} = S, _) ->
{send_ack_now, Serial} ->
?d("loop(empty) -> received send_ack_now [~w] request", [Serial]),
- send_msg(S#state.conn_handle, [], [Serial]),
+ _ = send_msg(S#state.conn_handle, [], [Serial]),
loop(S, Timeout);
- {send_req, Tid, Req} when size(Req) >= S#state.req_maxsize ->
+ {send_req, Tid, Req} when is_binary(Req), byte_size(Req) >= S#state.req_maxsize ->
?d("loop(empty) -> received (big) send_req request ~w", [Tid]),
- send_msg(S#state.conn_handle, [{Tid, Req}], []),
+ _ = send_msg(S#state.conn_handle, [{Tid, Req}], []),
loop(S, Timeout);
- {send_req, Tid, Req} ->
+ {send_req, Tid, Req} when is_binary(Req) ->
?d("loop(empty) -> received send_req request ~w", [Tid]),
- loop(S#state{req_sz = size(Req), reqs = [{Tid,Req}]}, Timeout);
+ loop(S#state{req_sz = byte_size(Req), reqs = [{Tid,Req}]}, Timeout);
{send_reqs, Tids, Reqs} ->
?d("loop(empty) -> received send_reqs request: ~w", [Tids]),
@@ -381,7 +381,7 @@ loop(#state{reqs = Reqs, acks = Acks, timeout = Timeout} = S, _To) ->
handle_send_req(Tid, Req,
#state{conn_handle = CH,
req_maxsize = MaxSz, reqs = Reqs, acks = Acks} = S)
- when size(Req) >= MaxSz ->
+ when is_binary(Req), byte_size(Req) >= MaxSz ->
?d("handle_send_req -> request bigger then maxsize ~w", [MaxSz]),
handle_send_result( send_msg(CH, Reqs, Acks) ),
handle_send_result( send_msg(CH, [{Tid, Req}], []) ),
@@ -407,7 +407,7 @@ handle_send_req(Tid, Req,
),
{S#state{req_sz = 0, reqs = [], acks = []}, true};
- false when size(Req) + ReqSz >= MaxSz ->
+ false when is_binary(Req), byte_size(Req) + ReqSz >= MaxSz ->
%% We finally passed the req-maxsize limit
?d("handle_send_req -> maxsize ~w passed", [MaxSz]),
handle_send_result(
@@ -415,10 +415,10 @@ handle_send_req(Tid, Req,
),
{S#state{req_sz = 0, reqs = [], acks = []}, true};
- false ->
+ false when is_binary(Req) ->
%% Still not time to send
?d("handle_send_req -> nothing to be sent",[]),
- {S#state{req_sz = ReqSz + size(Req), reqs = [{Tid, Req}|Reqs]},
+ {S#state{req_sz = ReqSz + byte_size(Req), reqs = [{Tid, Req}|Reqs]},
false}
end.
@@ -494,33 +494,33 @@ maybe_send_reqs(_CH, [], _Acks, Acc, AccSz, _MaxSz, Sent) ->
"~n length(Acc): ~w", [Sent, AccSz, length(Acc)]),
{Acc, AccSz, Sent};
maybe_send_reqs(CH, [{Tid, Req}|Reqs], Acks, Acc, _AccSz, MaxSz, _Sent)
- when size(Req) >= MaxSz ->
+ when is_binary(Req), byte_size(Req) >= MaxSz ->
%% The request was above the maxsize limit, so first send
%% what's in store and the the big request.
?d("maybe_send_reqs -> entry when request [~w] size (~w) > max size"
"~n Acks: ~w"
- "~n length(Acc): ~w", [Tid, size(Req), Acks, length(Acc)]),
+ "~n length(Acc): ~w", [Tid, byte_size(Req), Acks, length(Acc)]),
handle_send_result( send_msg(CH, Acc, Acks) ),
handle_send_result( send_msg(CH, [{Tid, Req}], []) ),
maybe_send_reqs(CH, Reqs, [], [], 0, MaxSz, true);
maybe_send_reqs(CH, [{Tid, Req}|Reqs], Acks, Acc, AccSz, MaxSz, _Sent)
- when AccSz + size(Req) >= MaxSz ->
+ when is_binary(Req), AccSz + byte_size(Req) >= MaxSz ->
%% We _did_ pass the maxsize limit with this request, so send
?d("maybe_send_reqs -> entry when sum of requests (~w) > max size"
"~n Tid: ~w"
"~n Acks: ~w"
- "~n length(Acc): ~w", [Tid, size(Req) + AccSz, Acks, length(Acc)]),
+ "~n length(Acc): ~w", [Tid, byte_size(Req) + AccSz, Acks, length(Acc)]),
handle_send_result( send_msg(CH, [{Tid, Req}|Acc], Acks) ),
maybe_send_reqs(CH, Reqs, [], [], 0, MaxSz, true);
-maybe_send_reqs(CH, [{Tid, Req}|Reqs], Acks, Acc, AccSz, MaxSz, Sent) ->
+maybe_send_reqs(CH, [{Tid, Req}|Reqs], Acks, Acc, AccSz, MaxSz, Sent) when is_binary(Req) ->
?d("maybe_send_reqs -> entry when"
"~n Tid: ~w"
"~n size(Req): ~w"
"~n Acks: ~w"
"~n length(Acc): ~w"
- "~n AccSz: ~w", [Tid, size(Req), Acks, length(Acc), AccSz]),
+ "~n AccSz: ~w", [Tid, byte_size(Req), Acks, length(Acc), AccSz]),
NewAcc = [{Tid,Req}|Acc],
- NewAccSz = AccSz + size(Req),
+ NewAccSz = AccSz + byte_size(Req),
maybe_send_reqs(CH, Reqs, Acks, NewAcc, NewAccSz, MaxSz, Sent).
@@ -548,7 +548,7 @@ send_reply(CH, Reply, MaxSz, _ReqSz, Reqs, Acks) ->
"~n length(Reqs): ~w"
"~n length(Acks): ~w", [length(Reqs), length(Acks)]),
case megaco_config:lookup_local_conn(CH) of
- [CD] when size(Reply) > MaxSz ->
+ [CD] when is_binary(Reply), byte_size(Reply) > MaxSz ->
handle_send_result( send_msg(CD, lists:reverse(Reqs), Acks) ),
Rep = {transactionReply, Reply},
do_send_msg(CD, Rep, [], []);
@@ -691,7 +691,7 @@ system_continue(_Parent, _Dbg, {S,To}) ->
system_terminate(Reason, _Parent, _Dbg, {S, _}) ->
#state{conn_handle = CH, reqs = Reqs, acks = Acks} = S,
- send_msg(CH, Reqs, Acks),
+ _ = send_msg(CH, Reqs, Acks),
exit(Reason).
system_code_change(S, _Module, _OLdVsn, _Extra) ->
diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in
index cd409fa54f..3649e2c392 100644
--- a/lib/megaco/src/flex/Makefile.in
+++ b/lib/megaco/src/flex/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2020. All Rights Reserved.
+# Copyright Ericsson AB 2001-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -187,9 +187,9 @@ endif
# ----------------------------------------------------
ifeq ($(ENABLE_MEGACO_FLEX_SCANNER),true)
-debug opt: $(TARGET_FILES) $(C_TARGETS) solibs
+$(TYPES): $(TARGET_FILES) $(C_TARGETS) solibs
else
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
endif
clean:
diff --git a/lib/megaco/src/flex/megaco_flex_scanner.erl b/lib/megaco/src/flex/megaco_flex_scanner.erl
index 174d430fb2..bcc58b7e8d 100644
--- a/lib/megaco/src/flex/megaco_flex_scanner.erl
+++ b/lib/megaco/src/flex/megaco_flex_scanner.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,10 +32,12 @@
-define(SMP_SUPPORT_DEFAULT(), erlang:system_info(smp_support)).
-dialyzer({nowarn_function, is_enabled/0}).
+-spec is_enabled() -> boolean().
is_enabled() ->
(true =:= ?ENABLE_MEGACO_FLEX_SCANNER).
-dialyzer({nowarn_function, is_reentrant_enabled/0}).
+-spec is_reentrant_enabled() -> boolean().
is_reentrant_enabled() ->
(true =:= ?MEGACO_REENTRANT_FLEX_SCANNER).
@@ -46,8 +48,8 @@ is_scanner_port(Port, Ports) when is_tuple(Ports) ->
is_scanner_port(_, _) ->
false.
-is_own_port(Port, Ports) ->
- is_own_port(Port, size(Ports), Ports).
+is_own_port(Port, Ports) when is_tuple(Ports)->
+ is_own_port(Port, tuple_size(Ports), Ports).
is_own_port(_Port, 0, _Ports) ->
false;
@@ -72,7 +74,7 @@ start(SMP) when ((SMP =:= true) orelse (SMP =:= false)) ->
do_start(SMP) ->
Path = lib_dir(),
- erl_ddll:start(),
+ _ = erl_ddll:start(),
load_driver(Path),
PortOrPorts = open_drv_port(SMP),
{ok, PortOrPorts}.
@@ -117,7 +119,7 @@ open_drv_port() ->
Port when is_port(Port) ->
Port;
{'EXIT', Reason} ->
- erl_ddll:unload_driver(drv_name()),
+ _ = erl_ddll:unload_driver(drv_name()),
throw({error, {open_port, Reason}})
end.
@@ -136,13 +138,13 @@ drv_name() ->
stop(Port) when is_port(Port) ->
erlang:port_close(Port),
- erl_ddll:unload_driver(drv_name()),
+ _ = erl_ddll:unload_driver(drv_name()),
stopped;
stop(Ports) when is_tuple(Ports) ->
stop(tuple_to_list(Ports));
stop(Ports) when is_list(Ports) ->
lists:foreach(fun(Port) -> erlang:port_close(Port) end, Ports),
- erl_ddll:unload_driver(drv_name()),
+ _ = erl_ddll:unload_driver(drv_name()),
stopped.
diff --git a/lib/megaco/src/tcp/Makefile b/lib/megaco/src/tcp/Makefile
index d07db3fa4b..ef4232244a 100644
--- a/lib/megaco/src/tcp/Makefile
+++ b/lib/megaco/src/tcp/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -67,8 +67,8 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/megaco/src/tcp/megaco_tcp.erl b/lib/megaco/src/tcp/megaco_tcp.erl
index 6ff8e5793f..51abc99d6c 100644
--- a/lib/megaco/src/tcp/megaco_tcp.erl
+++ b/lib/megaco/src/tcp/megaco_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -205,7 +205,7 @@ connect(SupPid, Parameters) ->
{ok, Pid} ->
?d1("connect -> connection started: "
"~n Pid: ~p", [Pid]),
- gen_tcp:controlling_process(Socket, Pid),
+ _ = gen_tcp:controlling_process(Socket, Pid),
?d2("connect -> control transferred"),
{ok, Socket, Pid};
{error, Reason} ->
@@ -249,18 +249,18 @@ send_message(Socket, Data) ->
"~n size(Data): ~p", [Socket, sz(Data)]),
{Size, NewData} = add_tpkt_header(Data),
Res = gen_tcp:send(Socket, NewData),
- case Res of
- ok ->
- incNumOutMessages(Socket),
- incNumOutOctets(Socket, Size);
- _ ->
- ok
- end,
+ _ = case Res of
+ ok ->
+ incNumOutMessages(Socket),
+ incNumOutOctets(Socket, Size);
+ _ ->
+ ok
+ end,
Res.
-ifdef(megaco_debug).
sz(Bin) when is_binary(Bin) ->
- size(Bin);
+ byte_size(Bin);
sz(List) when is_list(List) ->
length(List).
-endif.
@@ -633,11 +633,11 @@ create_acceptor(Pid, Rec, TopSup, Listen) ->
%% Description: Function is used to add the TPKT header
%%-----------------------------------------------------------------
add_tpkt_header(Data) when is_binary(Data) ->
- L = size(Data) + 4,
+ L = byte_size(Data) + 4,
{L, [3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff ,Data]};
add_tpkt_header(IOList) when is_list(IOList) ->
Binary = list_to_binary(IOList),
- L = size(Binary) + 4,
+ L = byte_size(Binary) + 4,
{L, [3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff , Binary]}.
%%-----------------------------------------------------------------
diff --git a/lib/megaco/src/tcp/megaco_tcp_connection.erl b/lib/megaco/src/tcp/megaco_tcp_connection.erl
index 136bfda2e5..fa31f7a510 100644
--- a/lib/megaco/src/tcp/megaco_tcp_connection.erl
+++ b/lib/megaco/src/tcp/megaco_tcp_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -141,28 +141,28 @@ handle_info({tcp_error, _Socket}, TcpRec) ->
{stop, shutdown, TcpRec};
handle_info({tcp, Socket, <<3:8, _X:8, Length:16, Msg/binary>>},
#megaco_tcp{socket = Socket, serialize = false} = TcpRec)
- when Length < ?GC_MSG_LIMIT ->
+ when is_binary(Msg), Length < ?GC_MSG_LIMIT ->
#megaco_tcp{module = Mod, receive_handle = RH} = TcpRec,
incNumInMessages(Socket),
- incNumInOctets(Socket, 4+size(Msg)),
+ incNumInOctets(Socket, 4+byte_size(Msg)),
apply(Mod, receive_message, [RH, self(), Socket, Msg]),
- inet:setopts(Socket, [{active, once}]),
+ _ = inet:setopts(Socket, [{active, once}]),
{noreply, TcpRec};
handle_info({tcp, Socket, <<3:8, _X:8, Length:16, Msg/binary>>},
- #megaco_tcp{socket = Socket, serialize = false} = TcpRec) ->
+ #megaco_tcp{socket = Socket, serialize = false} = TcpRec) when is_binary(Msg)->
#megaco_tcp{module = Mod, receive_handle = RH} = TcpRec,
incNumInMessages(Socket),
- incNumInOctets(Socket, 4+size(Msg)),
+ incNumInOctets(Socket, 4+byte_size(Msg)),
receive_message(Mod, RH, Socket, Length, Msg),
- inet:setopts(Socket, [{active, once}]),
+ _ = inet:setopts(Socket, [{active, once}]),
{noreply, TcpRec};
handle_info({tcp, Socket, <<3:8, _X:8, _Length:16, Msg/binary>>},
- #megaco_tcp{socket = Socket, serialize = true} = TcpRec) ->
+ #megaco_tcp{socket = Socket, serialize = true} = TcpRec) when is_binary(Msg) ->
#megaco_tcp{module = Mod, receive_handle = RH} = TcpRec,
incNumInMessages(Socket),
- incNumInOctets(Socket, 4+size(Msg)),
+ incNumInOctets(Socket, 4+byte_size(Msg)),
process_received_message(Mod, RH, Socket, Msg),
- inet:setopts(Socket, [{active, once}]),
+ _ = inet:setopts(Socket, [{active, once}]),
{noreply, TcpRec};
handle_info({tcp, Socket, Msg}, TcpRec) ->
incNumErrors(Socket),
@@ -188,8 +188,8 @@ process_received_message(Mod, RH, SH, Msg) ->
receive_message(Mod, RH, SendHandle, Length, Msg) ->
Opts = [link , {min_heap_size, ?HEAP_SIZE(Length)}],
- spawn_opt(?MODULE, handle_received_message,
- [Mod, RH, self(), SendHandle, Msg], Opts),
+ _ = spawn_opt(?MODULE, handle_received_message,
+ [Mod, RH, self(), SendHandle, Msg], Opts),
ok.
diff --git a/lib/megaco/src/text/Makefile b/lib/megaco/src/text/Makefile
index bb5f80403b..6872b0ec04 100644
--- a/lib/megaco/src/text/Makefile
+++ b/lib/megaco/src/text/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2020. All Rights Reserved.
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -81,8 +81,8 @@ endif
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/megaco/src/udp/Makefile b/lib/megaco/src/udp/Makefile
index 028a63e98e..5699c3e952 100644
--- a/lib/megaco/src/udp/Makefile
+++ b/lib/megaco/src/udp/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2016. All Rights Reserved.
+# Copyright Ericsson AB 2000-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -66,8 +66,8 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/megaco/src/udp/megaco_udp.erl b/lib/megaco/src/udp/megaco_udp.erl
index 099f4b7455..e3825e9625 100644
--- a/lib/megaco/src/udp/megaco_udp.erl
+++ b/lib/megaco/src/udp/megaco_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -129,7 +129,7 @@ open(SupPid, Options) ->
NewUdpRec = UdpRec#megaco_udp{socket = Socket},
case start_udp_server(SupPid, NewUdpRec) of
{ok, ControlPid} ->
- gen_udp:controlling_process(Socket, ControlPid),
+ _ = gen_udp:controlling_process(Socket, ControlPid),
{ok, Socket, ControlPid};
{error, Reason} ->
Error = {error, {could_not_start_udp_server, Reason}},
@@ -220,13 +220,13 @@ create_snmp_counters(SH, [Counter|Counters]) ->
send_message(SH, Data) when is_record(SH, send_handle) ->
#send_handle{socket = Socket, addr = Addr, port = Port} = SH,
Res = gen_udp:send(Socket, Addr, Port, Data),
- case Res of
- ok ->
- incNumOutMessages(SH),
- incNumOutOctets(SH, size(Data));
- _ ->
- ok
- end,
+ _ = case Res of
+ ok ->
+ incNumOutMessages(SH),
+ incNumOutOctets(SH, byte_size(Data));
+ _ ->
+ ok
+ end,
Res;
send_message(SH, _Data) ->
{error, {bad_send_handle, SH}}.
diff --git a/lib/megaco/src/udp/megaco_udp_server.erl b/lib/megaco/src/udp/megaco_udp_server.erl
index 5abb4165ae..68a495d8bb 100644
--- a/lib/megaco/src/udp/megaco_udp_server.erl
+++ b/lib/megaco/src/udp/megaco_udp_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -150,10 +150,10 @@ handle_cast(Msg, UdpRec) ->
%% from the socket and exit codes.
%%-----------------------------------------------------------------
handle_info({udp, _Socket, Ip, Port, Msg},
- #megaco_udp{serialize = false} = UdpRec) ->
+ #megaco_udp{serialize = false} = UdpRec) when is_binary(Msg) ->
#megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec,
SH = megaco_udp:create_send_handle(Socket, Ip, Port),
- MsgSize = size(Msg),
+ MsgSize = byte_size(Msg),
incNumInMessages(SH),
incNumInOctets(SH, MsgSize),
case MsgSize of
@@ -162,17 +162,17 @@ handle_info({udp, _Socket, Ip, Port, Msg},
Sz ->
receive_message(Mod, RH, SH, Sz, Msg)
end,
- activate(Socket),
+ _ = activate(Socket),
{noreply, UdpRec};
handle_info({udp, _Socket, Ip, Port, Msg},
- #megaco_udp{serialize = true} = UdpRec) ->
+ #megaco_udp{serialize = true} = UdpRec) when is_binary(Msg) ->
#megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec,
SH = megaco_udp:create_send_handle(Socket, Ip, Port),
- MsgSize = size(Msg),
+ MsgSize = byte_size(Msg),
incNumInMessages(SH),
incNumInOctets(SH, MsgSize),
process_received_message(Mod, RH, SH, Msg),
- activate(Socket),
+ _ = activate(Socket),
{noreply, UdpRec};
handle_info(Info, UdpRec) ->
warning_msg("received unexpected info: "
diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile
index 0ea33883db..eced232a47 100644
--- a/lib/megaco/test/Makefile
+++ b/lib/megaco/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2020. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -90,6 +90,8 @@ ERL_COMPILE_FLAGS += $(MEGACO_ERL_COMPILE_FLAGS)
# We have a behaviour in the test catalog (megaco_test_generator)
ERL_COMPILE_FLAGS += -pa ../../megaco/test
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
+
ERL_PATH = -pa ../../megaco/examples/simple \
-pa ../../megaco/ebin \
-pa ../../et/ebin
@@ -128,7 +130,7 @@ endif
# Targets
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
diff --git a/lib/megaco/test/megaco_actions_SUITE.erl b/lib/megaco/test/megaco_actions_SUITE.erl
index c4d245a504..ac634988a7 100644
--- a/lib/megaco/test/megaco_actions_SUITE.erl
+++ b/lib/megaco/test/megaco_actions_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -191,19 +191,32 @@ end_per_testcase(Case, Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+mgc_start(Node, ET) ->
+ ?MGC_START(Node, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY).
+
+mgc_stop(Mgc) ->
+ ?MGC_STOP(Mgc).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
pretty_text(suite) ->
[];
pretty_text(doc) ->
[];
pretty_text(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- i("pretty_text -> starting"),
+ Pre = fun req_and_rep_pre/0,
+ Case = fun(Nodes) -> do_pretty_text(Nodes, Config) end,
+ Post = fun req_and_rep_post/1,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
- Codec = pretty_text,
- Version = 1,
+do_pretty_text(Nodes, Config) ->
+ Codec = pretty_text,
+ Version = 1,
EncodingConfig = [],
- req_and_rep(Config, Codec, Version, EncodingConfig).
+ req_and_rep(Nodes, Config, Codec, Version, EncodingConfig).
flex_pretty_text(suite) ->
@@ -219,14 +232,16 @@ compact_text(suite) ->
compact_text(doc) ->
[];
compact_text(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- i("compact_text -> starting"),
-
- Codec = compact_text,
- Version = 1,
+ Pre = fun req_and_rep_pre/0,
+ Case = fun(Nodes) -> do_compact_text(Nodes, Config) end,
+ Post = fun req_and_rep_post/1,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+do_compact_text(Nodes, Config) ->
+ Codec = compact_text,
+ Version = 1,
EncodingConfig = [],
- req_and_rep(Config, Codec, Version, EncodingConfig).
+ req_and_rep(Nodes, Config, Codec, Version, EncodingConfig).
flex_compact_text(suite) ->
@@ -242,14 +257,16 @@ erl_dist(suite) ->
erl_dist(doc) ->
[];
erl_dist(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- i("erl_dist -> starting"),
-
- Codec = erl_dist,
- Version = 1,
+ Pre = fun req_and_rep_pre/0,
+ Case = fun(Nodes) -> do_erl_dist(Nodes, Config) end,
+ Post = fun req_and_rep_post/1,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+do_erl_dist(Nodes, Config) ->
+ Codec = erl_dist,
+ Version = 1,
EncodingConfig = [],
- req_and_rep(Config, Codec, Version, EncodingConfig).
+ req_and_rep(Nodes, Config, Codec, Version, EncodingConfig).
erl_dist_mc(suite) ->
@@ -257,37 +274,45 @@ erl_dist_mc(suite) ->
erl_dist_mc(doc) ->
[];
erl_dist_mc(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- i("erl_dist_mc -> starting"),
-
- Codec = erl_dist,
- Version = 1,
+ Pre = fun req_and_rep_pre/0,
+ Case = fun(Nodes) -> do_erl_dist_mc(Nodes, Config) end,
+ Post = fun req_and_rep_post/1,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+do_erl_dist_mc(Nodes, Config) ->
+ Codec = erl_dist,
+ Version = 1,
EncodingConfig = [megaco_compressed],
- req_and_rep(Config, Codec, Version, EncodingConfig).
+ req_and_rep(Nodes, Config, Codec, Version, EncodingConfig).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-req_and_rep(Config, Codec, _Version, EC) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- i("req_and_rep -> starting"),
+req_and_rep_pre() ->
MgcNode = make_node_name(mgc),
Mg1Node = make_node_name(mg1),
Mg2Node = make_node_name(mg2),
- d("req_and_rep -> Nodes: "
- "~n MgcNode: ~p"
- "~n Mg1Node: ~p"
- "~n Mg2Node: ~p",
+ d("req_and_rep_pre -> start nodes: "
+ "~n MgcNode: ~p"
+ "~n Mg1Node: ~p"
+ "~n Mg2Node: ~p",
[MgcNode, Mg1Node, Mg2Node]),
- ok = ?START_NODES([MgcNode, Mg1Node, Mg2Node]),
+ Nodes = [MgcNode, Mg1Node, Mg2Node],
+ ok = ?START_NODES(Nodes, true),
+ Nodes.
+
+req_and_rep_post(Nodes) ->
+ d("req_and_rep_post -> stop nodes"),
+ ?STOP_NODES(lists:reverse(Nodes)).
+
+
+req_and_rep([MgcNode, Mg1Node, Mg2Node],
+ Config, Codec, _Version, EC) when is_list(Config) ->
%% Start the MGC and MGs
i("req_and_rep -> start the MGC"),
ET = [{Codec, EC, tcp}, {Codec, EC, udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
+ {ok, Mgc} = mgc_start(MgcNode, ET),
i("req_and_rep -> start and connect the MGs"),
MgConf0 = [{Mg1Node, "mg1", Codec, EC, tcp, ?MG_VERBOSITY},
@@ -363,7 +388,7 @@ req_and_rep(Config, Codec, _Version, EC) when is_list(Config) ->
%% Tell Mgc to stop
i("req_and_rep -> stop the MGC"),
- ?MGC_STOP(Mgc),
+ mgc_stop(Mgc),
i("req_and_rep -> done", []),
ok.
@@ -462,6 +487,16 @@ sleep(X) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+try_tc(TCName, Pre, Case, Post) ->
+ try_tc(TCName, "TEST", ?TEST_VERBOSITY, Pre, Case, Post).
+
+try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
+ ?TRY_TC(TCName, Name, Verbosity, Pre, Case, Post).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
i(F) ->
i(F, []).
@@ -469,8 +504,8 @@ i(F, A) ->
print(info, get(verbosity), "", F, A).
-%% d(F) ->
-%% d(F, []).
+d(F) ->
+ d(F, []).
d(F, A) ->
print(debug, get(verbosity), "DBG: ", F, A).
diff --git a/lib/megaco/test/megaco_codec_v1_SUITE.erl b/lib/megaco/test/megaco_codec_v1_SUITE.erl
index c458e0b579..0f88dd8d9a 100644
--- a/lib/megaco/test/megaco_codec_v1_SUITE.erl
+++ b/lib/megaco/test/megaco_codec_v1_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -508,6 +508,8 @@ end_per_suite(suite) -> [];
end_per_suite(doc) -> [];
end_per_suite(Config0) when is_list(Config0) ->
+ ?ANNOUNCE_SUITE_END(),
+
p("end_per_suite -> entry with"
"~n Config: ~p"
"~n Nodes: ~p", [Config0, erlang:nodes()]),
@@ -541,15 +543,20 @@ init_per_group(Group, Config) ->
?ANNOUNCE_GROUP_INIT(Group),
Config.
-end_per_group(flex_pretty_tickets, Config) ->
+end_per_group(flex_pretty_tickets = Group, Config) ->
+ ?ANNOUNCE_GROUP_END(Group),
flex_pretty_finish(Config);
-end_per_group(flex_compact_tickets, Config) ->
+end_per_group(flex_compact_tickets = Group, Config) ->
+ ?ANNOUNCE_GROUP_END(Group),
flex_compact_finish(Config);
-end_per_group(flex_compact, Config) ->
+end_per_group(flex_compact = Group, Config) ->
+ ?ANNOUNCE_GROUP_END(Group),
flex_compact_finish(Config);
-end_per_group(flex_pretty, Config) ->
+end_per_group(flex_pretty = Group, Config) ->
+ ?ANNOUNCE_GROUP_END(Group),
flex_pretty_finish(Config);
-end_per_group(_GroupName, Config) ->
+end_per_group(Group, Config) ->
+ ?ANNOUNCE_GROUP_END(Group),
Config.
diff --git a/lib/megaco/test/megaco_examples_SUITE.erl b/lib/megaco/test/megaco_examples_SUITE.erl
index dc3dfb7967..084749ce60 100644
--- a/lib/megaco/test/megaco_examples_SUITE.erl
+++ b/lib/megaco/test/megaco_examples_SUITE.erl
@@ -45,6 +45,8 @@
-include_lib("megaco/include/megaco.hrl").
-include_lib("megaco/include/megaco_message_v1.hrl").
+-define(TEST_VERBOSITY, debug).
+
%%======================================================================
%% Common Test interface functions
@@ -341,14 +343,32 @@ purge_example(Mods) ->
simple(suite) ->
[];
simple(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- d("simple -> create node name(s)"),
- [_Local, MGC, MG] = ?LIB:mk_nodes(3), %% Grrr
- Nodes = [MGC, MG],
-
- d("simple -> start nodes"),
- ok = ?LIB:start_nodes(Nodes, ?MODULE, ?LINE),
-
+ Pre = fun() ->
+ d("simple -> "
+ "create (3) node name(s) (includes the own node)"),
+ %% We actually need two *new* nodes,
+ %% but the function includes the own node,
+ %% so we need to ask for one more.
+ [_Local, MGC, MG] = ?MK_NODES(3),
+ Nodes = [MGC, MG],
+
+ d("simple -> start nodes: "
+ "~n ~p", [Nodes]),
+ ok = ?START_NODES(Nodes, true),
+ Nodes
+ end,
+ Case = fun(Nodes) ->
+ do_simple(Config, Nodes)
+ end,
+ Post = fun(Nodes) ->
+ d("simple -> stop nodes"
+ "~n ~p", [Nodes]),
+ ?STOP_NODES(Nodes)
+ end,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+
+do_simple(_Config, [MGC, MG]) ->
MGCId = "MGC",
MGId = "MG",
@@ -472,12 +492,6 @@ simple(Config) when is_list(Config) ->
ok
end,
- d("simple -> stop ~p", [MGC]),
- slave:stop(MGC),
-
- d("simple -> stop ~p", [MG]),
- slave:stop(MG),
-
d("simple -> done", []),
ok.
@@ -597,32 +611,40 @@ users(Proxy) ->
meas(suite) ->
[];
meas(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- MFactor = ?config(megaco_factor, Config),
- {Time, Factor} =
- if
- (MFactor =:= 1) ->
- {3, 100};
- (MFactor =:= 2) ->
- {4, 100};
- (MFactor =:= 3) ->
- {4, 200};
- (MFactor =:= 4) ->
- {5, 200};
- (MFactor =:= 5) ->
- {5, 400};
- true ->
- {6, 400}
- end,
- p("Run with: "
- "~n Timetrap: ~p mins"
- "~n Factor: ~p", [Time, Factor]),
- ct:timetrap(?MINS(Time)),
- WorkerNode = ?config(worker_node, Config),
- do_meas(?FUNCTION_NAME, WorkerNode, megaco_codec_meas, start, [Factor]).
-
-do_meas(SName, Node, Mod, Func, Args) ->
- put(sname, SName),
+ Pre = fun() ->
+ MFactor = ?config(megaco_factor, Config),
+ {Time, Factor} =
+ if
+ (MFactor =:= 1) ->
+ {3, 100};
+ (MFactor =:= 2) ->
+ {4, 100};
+ (MFactor =:= 3) ->
+ {4, 200};
+ (MFactor =:= 4) ->
+ {5, 300};
+ (MFactor =:= 5) ->
+ {5, 400};
+ (MFactor =:= 6) ->
+ {6, 500};
+ true ->
+ {10, 600}
+ end,
+ p("Run with: "
+ "~n Timetrap: ~p mins"
+ "~n Factor: ~p", [Time, Factor]),
+ ct:timetrap(?MINS(Time)),
+ WorkerNode = ?config(worker_node, Config),
+ {Factor, WorkerNode}
+ end,
+ Opts = #{verbose => false},
+ Case = fun({Factor, WorkerNode}) ->
+ do_meas(WorkerNode, megaco_codec_meas, start, [Factor, Opts])
+ end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+do_meas(Node, Mod, Func, Args) ->
F = fun() ->
exit( rpc:call(Node, Mod, Func, Args) )
end,
@@ -646,11 +668,19 @@ do_meas(SName, Node, Mod, Func, Args) ->
{'DOWN', MRef, process, Pid, Reason} ->
p("worker process terminated: "
"~n ~p", [Reason]),
- ok
+ ok;
+
+ {'EXIT', TCPid, {timetrap_timeout = R, TCTimeout, TCSTack}} ->
+ p("received timetrap timeout (~w ms) from ~p => "
+ "Kill executor process"
+ "~n TC Stack: ~p", [TCTimeout, TCPid, TCSTack]),
+ exit(Pid, kill),
+ ?SKIP(R)
end,
ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% ------------------ meas:mstone1 ------------------------
@@ -658,23 +688,30 @@ do_meas(SName, Node, Mod, Func, Args) ->
mstone1(suite) ->
[];
mstone1(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- WorkerNode = ?config(worker_node, Config),
- %% The point of this is
- %% to make sure we utilize as much of the host as possible...
- RunTime = 1, % Minute
- NumSched = try erlang:system_info(schedulers_online) of N -> N
- catch _:_:_ -> 1
- end,
- Factor = 1 + (NumSched div 12),
- Mod = megaco_codec_mstone1,
- Func = start,
- Args = [RunTime, Factor],
- p("Run with: "
- "~n Run Time: ~p min(s)"
- "~n Factor: ~p", [RunTime, Factor]),
- ct:timetrap(?MINS(RunTime + 1)),
- do_meas(?FUNCTION_NAME, WorkerNode, Mod, Func, Args).
+ Pre = fun() ->
+ %% The point of this is to make sure we
+ %% utilize as much of the host as possible...
+ RunTime = 1, % Minute
+ NumSched =
+ try erlang:system_info(schedulers_online) of N -> N
+ catch _:_:_ -> 1
+ end,
+ Factor = 1 + (NumSched div 12),
+ ct:timetrap(?MINS(RunTime + 1)),
+ {RunTime, Factor, ?config(worker_node, Config)}
+ end,
+ Case = fun({RunTime, Factor, WorkerNode}) ->
+ Mod = megaco_codec_mstone1,
+ Func = start,
+ Args = [RunTime, Factor],
+ p("Run with: "
+ "~n Run Time: ~p min(s)"
+ "~n Factor: ~p", [RunTime, Factor]),
+ do_meas(WorkerNode, Mod, Func, Args)
+ end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -684,23 +721,29 @@ mstone1(Config) when is_list(Config) ->
mstone2(suite) ->
[];
mstone2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- WorkerNode = ?config(worker_node, Config),
- RunTime = 1, % Minutes
- NumSched = try erlang:system_info(schedulers_online) of N -> N
- catch _:_:_ -> 1
- end,
- Factor = 1 + (NumSched div 12),
- Mode = standard,
- Mod = megaco_codec_mstone2,
- Func = start,
- Args = [Factor, RunTime, Mode],
- p("Run with: "
- "~n Factor: ~p"
- "~n Run Time: ~p min(s)"
- "~n Mode: ~p", [Factor, RunTime, Mode]),
- ct:timetrap(?MINS(RunTime + 1)),
- do_meas(?FUNCTION_NAME, WorkerNode, Mod, Func, Args).
+ Pre = fun() ->
+ RunTime = 1, % Minutes
+ NumSched =
+ try erlang:system_info(schedulers_online) of N -> N
+ catch _:_:_ -> 1
+ end,
+ Factor = 1 + (NumSched div 12),
+ ct:timetrap(?MINS(RunTime + 1)),
+ {Factor, RunTime, ?config(worker_node, Config)}
+ end,
+ Case = fun({Factor, RunTime, WorkerNode}) ->
+ Mode = standard,
+ Mod = megaco_codec_mstone2,
+ Func = start,
+ Args = [Factor, RunTime, Mode],
+ p("Run with: "
+ "~n Factor: ~p"
+ "~n Run Time: ~p min(s)"
+ "~n Mode: ~p", [Factor, RunTime, Mode]),
+ do_meas(WorkerNode, Mod, Func, Args)
+ end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -731,6 +774,16 @@ unique_node_name(Pre) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+try_tc(TCName, Pre, Case, Post) ->
+ try_tc(TCName, "EX-TESTER", ?TEST_VERBOSITY, Pre, Case, Post).
+
+try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
+ ?TRY_TC(TCName, Name, Verbosity, Pre, Case, Post).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
p(F) ->
p(F, []).
diff --git a/lib/megaco/test/megaco_load_SUITE.erl b/lib/megaco/test/megaco_load_SUITE.erl
index 42e1a122a4..9d671450e8 100644
--- a/lib/megaco/test/megaco_load_SUITE.erl
+++ b/lib/megaco/test/megaco_load_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -613,7 +613,6 @@ multi_load(MGs, Conf, NumLoaders, NumReqs) ->
"~n Conf: ~p"
"~n NumLoaders: ~p"
"~n NumReqs: ~p", [MGs, Conf, NumLoaders, NumReqs]),
-
Pids = multi_load_collector_start(MGs, Conf, NumLoaders, NumReqs, []),
case timer:tc(?MODULE, do_multi_load, [Pids, NumLoaders, NumReqs]) of
{Time, {ok, OKs, []}} ->
@@ -652,8 +651,8 @@ get_env(Key, Env) ->
multi_load_collector(Parent, Node, Mid, Conf, NumLoaders, NumReqs, Env) ->
put(verbosity, get_env(verbosity, Env)),
- put(tc, get_env(tc, Env)),
- put(sname, get_env(sname, Env) ++ "-loader"),
+ put(tc, get_env(tc, Env)),
+ put(sname, get_env(sname, Env) ++ "-loader"),
case ?MG_START(Node, Mid, text, tcp, Conf, ?MG_VERBOSITY) of
{ok, Pid} ->
d("MG ~p user info: ~n~p", [Mid, ?MG_USER_INFO(Pid, all)]),
diff --git a/lib/megaco/test/megaco_mess_SUITE.erl b/lib/megaco/test/megaco_mess_SUITE.erl
index 9ff3ac1468..c895592812 100644
--- a/lib/megaco/test/megaco_mess_SUITE.erl
+++ b/lib/megaco/test/megaco_mess_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -9891,6 +9891,9 @@ otp_6442_resend_request1(suite) ->
[];
otp_6442_resend_request1(Config) when is_list(Config) ->
Pre = fun() ->
+ put(verbosity, debug),
+ put(tc, ?FUNCTION_NAME),
+
MgNode = make_node_name(mg),
d("start (MG) node: ~p", [MgNode]),
Nodes = [MgNode],
@@ -10262,6 +10265,9 @@ otp_6442_resend_request2(suite) ->
[];
otp_6442_resend_request2(Config) when is_list(Config) ->
Pre = fun() ->
+ put(verbosity, debug),
+ put(tc, ?FUNCTION_NAME),
+
MgNode = make_node_name(mg),
d("start (MG) node: ~p", [MgNode]),
Nodes = [MgNode],
@@ -10571,6 +10577,9 @@ otp_6442_resend_reply1(suite) ->
otp_6442_resend_reply1(Config) when is_list(Config) ->
Factor = ?config(megaco_factor, Config),
Pre = fun() ->
+ put(verbosity, debug),
+ put(tc, ?FUNCTION_NAME),
+
MgNode = make_node_name(mg),
d("start (MG) node: ~p", [MgNode]),
Nodes = [MgNode],
@@ -11353,12 +11362,13 @@ otp_6442_resend_reply2_err_desc(T) ->
otp_6865_request_and_reply_plain_extra1(suite) ->
[];
otp_6865_request_and_reply_plain_extra1(Config) when is_list(Config) ->
- ?ACQUIRE_NODES(1, Config),
+ Pre = fun() -> undefined end,
+ Case = fun(X) -> do_otp_6865_request_and_reply_plain_extra1(X, Config) end,
+ Post = fun(_) -> ok end,
+ try_tc(otp6865e1, Pre, Case, Post).
- put(sname, "TEST"),
- put(verbosity, debug),
- put(tc, otp6865e1),
- i("starting"),
+do_otp_6865_request_and_reply_plain_extra1(_, Config) ->
+ ?ACQUIRE_NODES(1, Config),
d("start test case controller",[]),
ok = megaco_tc_controller:start_link(),
@@ -11453,11 +11463,25 @@ otp_6865_request_and_reply_plain_extra2(suite) ->
otp_6865_request_and_reply_plain_extra2(doc) ->
[];
otp_6865_request_and_reply_plain_extra2(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, otp6865e2),
- i("starting"),
+ Pre = fun() ->
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ Nodes
+ end,
+ Case = fun do_otp_6865_request_and_reply_plain_extra2/1,
+ Post = fun(Nodes) ->
+ d("stop nodes"),
+ ?STOP_NODES(lists:reverse(Nodes))
+ end,
+ try_tc(otp6865e2, Pre, Case, Post).
+do_otp_6865_request_and_reply_plain_extra2([MgcNode, MgNode]) ->
d("start tc controller"),
ok = megaco_tc_controller:start_link(),
@@ -11466,16 +11490,6 @@ otp_6865_request_and_reply_plain_extra2(Config) when is_list(Config) ->
ExtraInfo = otp6865e2_extra_info,
ok = megaco_tc_controller:insert(extra_transport_info, ExtraInfo),
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- Nodes = [MgcNode, MgNode],
- ok = ?START_NODES(Nodes, true),
-
-
d("[MGC] start the simulator "),
{ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode),
@@ -11521,10 +11535,6 @@ otp_6865_request_and_reply_plain_extra2(Config) when is_list(Config) ->
i("stop tc controller"),
ok = megaco_tc_controller:stop(),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES(lists:reverse(Nodes)),
-
i("done", []),
ok.
diff --git a/lib/megaco/test/megaco_mib_SUITE.erl b/lib/megaco/test/megaco_mib_SUITE.erl
index 965e368f73..c5b3f7f198 100644
--- a/lib/megaco/test/megaco_mib_SUITE.erl
+++ b/lib/megaco/test/megaco_mib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -675,11 +675,15 @@ traffic_verify_counter(Name, Counter, Counters, Expected) ->
{value, {Counter, Val}} ->
i("counter ~w *not* verified for ~p: "
"~n Expected: ~w"
- "~n Actual: ~w", [Counter, Name, Expected, Val]),
- exit({illegal_counter_value, Counter, Val, Expected, Name});
+ "~n Actual: ~w"
+ "~n Counters: ~w",
+ [Counter, Name, Expected, Val, Counters]),
+ exit({illegal_counter_value, Name, Counter, Expected, Val,
+ Counters});
false ->
- i("counter ~w *not* found for ~p", [Counter, Name]),
- exit({not_found, Counter, Counters, Name, Expected})
+ i("counter ~w *not* found for ~p: "
+ "~n Counters: ~p", [Counter, Name, Counters]),
+ exit({not_found, Name, Counter, Counters, Expected})
end.
@@ -1200,7 +1204,7 @@ start_mg(Node, Mid, Encoding, Transport, Verbosity) ->
mg(Parent, Verbosity, Config) ->
process_flag(trap_exit, true),
put(verbosity, Verbosity),
- put(sname, "MG"),
+ put(sname, get_mg_sname(Config)),
i("mg -> starting"),
{Mid, ConnHandle} = mg_init(Config),
notify_started(Parent),
@@ -1208,6 +1212,14 @@ mg(Parent, Verbosity, Config) ->
i("mg -> started"),
mg_loop(S).
+get_mg_sname(Config) ->
+ case get_conf(local_mid, Config) of
+ {deviceName, Name} ->
+ Name;
+ _ ->
+ "MG"
+end.
+
mg_init(Config) ->
d("mg_init -> entry"),
Mid = get_conf(local_mid, Config),
diff --git a/lib/megaco/test/megaco_pending_limit_SUITE.erl b/lib/megaco/test/megaco_pending_limit_SUITE.erl
index d5db6e6bc0..dfe52535c9 100644
--- a/lib/megaco/test/megaco_pending_limit_SUITE.erl
+++ b/lib/megaco/test/megaco_pending_limit_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,31 +46,6 @@
]).
--ifdef(megaco_hipe_special).
--export([
- %% Case: recv_limit_exceeded1
- rle1_mgc_verify_service_change_req_msg/2,
- rle1_mgc_verify_notify_req_msg/1,
- rle1_mg_verify_handle_connect/1,
- rle1_mg_verify_service_change_rep/1,
- rle1_mg_verify_trans_rep/1,
-
- %% Case: otp_4956
- otp_4956_mgc_verify_handle_connect/1,
- otp_4956_mgc_verify_service_change_req/2,
- otp_4956_mgc_verify_notify_req1/1,
- otp_4956_mgc_verify_notify_req2/1,
- otp_4956_mgc_verify_handle_trans_req_abort/1,
- otp_4956_mgc_verify_handle_disconnect/1,
- otp_4956_mg_verify_service_change_rep_msg/1,
- otp_4956_mg_verify_pending_msg/1,
- otp_4956_mg_verify_pending_limit_msg/1,
-
- %% Utility
- encode_msg/3,
- decode_msg/3
- ]).
--endif.
-include_lib("megaco/include/megaco.hrl").
-include_lib("megaco/include/megaco_message_v1.hrl").
@@ -89,6 +64,10 @@
-define(MGC_START(Pid, Mid, ET, Conf, Verb),
megaco_test_mgc:start(Pid, Mid, ET, Conf, Verb)).
+-define(MGC_START(Pid, ET, Conf),
+ ?MGC_START(Pid, {deviceName, "ctrl"}, ET, Conf, ?MGC_VERBOSITY)).
+-define(MGC_START(Pid, ET),
+ ?MGC_START(Pid, ET, [])).
-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)).
-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)).
-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)).
@@ -110,6 +89,10 @@
-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb),
megaco_test_mg:start(Pid, Mid, Enc, Transp, Conf, Verb)).
+-define(MG_START(Pid, Enc, Transp, Conf),
+ ?MG_START(Pid, {deviceName, "mg"}, Enc, Transp, Conf, ?MG_VERBOSITY)).
+-define(MG_START(Pid, Enc, Transp),
+ ?MG_START(Pid, Enc, Transp, [])).
-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)).
-define(MG_GET_STATS(Pid, No), megaco_test_mg:get_stats(Pid, No)).
-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)).
@@ -278,30 +261,39 @@ sent_timer_late_reply(suite) ->
sent_timer_late_reply(doc) ->
"...";
sent_timer_late_reply(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, sent_timer_late_reply),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_stlr_mgc),
+ MgNode = make_node_name(pl_stlr_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_sent_timer_late_reply(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_sent_timer_late_reply(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
MgcConf = [{megaco_trace, false}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, MgcConf, ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET, MgcConf),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConf = [{megaco_trace, io}],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConf, ?MG_VERBOSITY),
+ MgConf = [{megaco_trace, io}],
+ {ok, Mg} = ?MG_START(MgNode, text, tcp, MgConf),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -342,11 +334,7 @@ sent_timer_late_reply(Config) when is_list(Config) ->
i("[MGC] stop"),
?MGC_STOP(Mgc),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
@@ -357,29 +345,37 @@ sent_timer_exceeded(suite) ->
sent_timer_exceeded(doc) ->
"...";
sent_timer_exceeded(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, sent_timer_exceeded),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_ste_mgc),
+ MgNode = make_node_name(pl_ste_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_sent_timer_exceeded(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_sent_timer_exceeded(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
- i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ i("[MG] start"),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -419,11 +415,7 @@ sent_timer_exceeded(Config) when is_list(Config) ->
i("[MGC] stop"),
?MGC_STOP(Mgc),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
@@ -434,29 +426,37 @@ sent_timer_exceeded_long(suite) ->
sent_timer_exceeded_long(doc) ->
"...";
sent_timer_exceeded_long(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, sent_timer_exceeded_long),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_stel_mgc),
+ MgNode = make_node_name(pl_stel_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_sent_timer_exceeded_long(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_sent_timer_exceeded_long(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -494,11 +494,7 @@ sent_timer_exceeded_long(Config) when is_list(Config) ->
i("[MGC] stop"),
?MGC_STOP(Mgc),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
@@ -508,35 +504,42 @@ sent_timer_exceeded_long(Config) when is_list(Config) ->
%% This test case can only be run with the stack compiled with
%% the MEGACO_TEST_CODE flag. Therefor there is no point in
%% including this test case in the usual test suite
--ifdef(MEGACO_TEST_CODE).
sent_resend_late_reply(suite) ->
[];
sent_resend_late_reply(doc) ->
"...";
sent_resend_late_reply(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, sent_resend_late_reply),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun megaco_test_code/0,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_srlr_mgc),
+ MgNode = make_node_name(pl_srlr_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_sent_resend_late_reply(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_sent_resend_late_reply(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -594,53 +597,48 @@ sent_resend_late_reply(Config) when is_list(Config) ->
i("done", []),
ok.
--else.
-
-sent_resend_late_reply(suite) ->
- [];
-sent_resend_late_reply(doc) ->
- "...";
-sent_resend_late_reply(Config) when is_list(Config) ->
- ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true").
-
--endif.
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case can only be run with the stack compiled with
%% the MEGACO_TEST_CODE flag. Therefor there is no point in
%% including this test case in the usual test suite
--ifdef(MEGACO_TEST_CODE).
sent_resend_exceeded(suite) ->
[];
sent_resend_exceeded(doc) ->
"...";
sent_resend_exceeded(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, sent_resend_exceeded),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun megaco_test_code/0,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_sre_mgc),
+ MgNode = make_node_name(pl_sre_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_sent_resend_exceeded(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_sent_resend_exceeded(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -686,60 +684,51 @@ sent_resend_exceeded(Config) when is_list(Config) ->
i("[MGC] stop"),
?MGC_STOP(Mgc),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
--else.
-
-sent_resend_exceeded(suite) ->
- [];
-sent_resend_exceeded(doc) ->
- "...";
-sent_resend_exceeded(Config) when is_list(Config) ->
- ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true").
-
--endif.
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This test case can only be run with the stack compiled with
%% the MEGACO_TEST_CODE flag. Therefor there is no point in
%% including this test case in the usual test suite
--ifdef(MEGACO_TEST_CODE).
sent_resend_exceeded_long(suite) ->
[];
sent_resend_exceeded_long(doc) ->
"...";
sent_resend_exceeded_long(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, sent_resend_exceeded_long),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun megaco_test_code/0,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_srel_mgc),
+ MgNode = make_node_name(pl_srel_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_sent_resend_exceeded_long(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_sent_resend_exceeded_long(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -786,26 +775,10 @@ sent_resend_exceeded_long(Config) when is_list(Config) ->
i("[MGC] stop"),
?MGC_STOP(Mgc),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
--else.
-
-sent_resend_exceeded_long(suite) ->
- [];
-sent_resend_exceeded_long(doc) ->
- "...";
-sent_resend_exceeded_long(Config) when is_list(Config) ->
- ?SKIP("included only if compiled with USE_MEGACO_TEST_CODE=true").
-
--endif.
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% %%%
%%% Received peinding test cases %%%
@@ -817,19 +790,30 @@ recv_limit_exceeded1(suite) ->
recv_limit_exceeded1(doc) ->
"Received pending limit exceeded (exactly)";
recv_limit_exceeded1(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, rle1),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_rle_mgc),
+ MgNode = make_node_name(pl_rle_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_recv_limit_exceeded1(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_recv_limit_exceeded1(#{nodes := [MgcNode, MgNode]}) ->
d("[MGC] start the simulator "),
{ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
@@ -868,27 +852,13 @@ recv_limit_exceeded1(Config) when is_list(Config) ->
i("[MG] stop generator"),
megaco_test_megaco_generator:stop(Mg),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
%%
%% MGC generator stuff
%%
--ifdef(megaco_hipe_special).
--define(rle1_mgc_decode_msg_fun(Mod, Conf),
- {?MODULE, decode_msg, [Mod, Conf]}).
--define(rle1_mgc_encode_msg_fun(Mod, Conf),
- {?MODULE, encode_msg, [Mod, Conf]}).
--define(rle1_mgc_verify_service_change_req_msg_fun(Mid),
- {?MODULE, rle1_mgc_verify_service_change_req_msg, [Mid]}).
--define(rle1_mgc_verify_notify_req_msg_fun(),
- {?MODULE, rle1_mgc_verify_notify_req_msg, []}).
--else.
-define(rle1_mgc_decode_msg_fun(Mod, Conf),
rle1_mgc_decode_msg_fun(Mod, Conf)).
-define(rle1_mgc_encode_msg_fun(Mod, Conf),
@@ -897,7 +867,6 @@ recv_limit_exceeded1(Config) when is_list(Config) ->
rle1_mgc_verify_service_change_req_msg_fun(Mid)).
-define(rle1_mgc_verify_notify_req_msg_fun(),
rle1_mgc_verify_notify_req_msg_fun()).
--endif.
rle1_mgc_event_sequence(text, tcp) ->
Mid = {deviceName,"ctrl"},
@@ -942,17 +911,15 @@ rle1_mgc_event_sequence2(Mid, EM, EC) ->
],
EvSeq.
--ifndef(megaco_hipe_special).
rle1_mgc_encode_msg_fun(Mod, Conf) ->
fun(M) ->
encode_msg(M, Mod, Conf)
end.
rle1_mgc_decode_msg_fun(Mod, Conf) ->
- fun(M) ->
+ fun(M) ->
decode_msg(M, Mod, Conf)
end.
--endif.
rle1_mgc_service_change_reply_msg(Mid, TransId, Cid) ->
SCRP = #'ServiceChangeResParm'{serviceChangeMgcId = Mid},
@@ -983,12 +950,10 @@ rle1_mgc_pending_msg(Mid, TransId) ->
messageBody = Body},
#'MegacoMessage'{mess = Mess}.
--ifndef(megaco_hipe_special).
rle1_mgc_verify_service_change_req_msg_fun(Mid) ->
fun(M) ->
rle1_mgc_verify_service_change_req_msg(M, Mid)
end.
--endif.
rle1_mgc_verify_service_change_req_msg(#'MegacoMessage'{mess = Mess} = M,
_Mid1) ->
@@ -1018,12 +983,10 @@ rle1_mgc_verify_service_change_req_msg(#'MegacoMessage'{mess = Mess} = M,
rle1_mgc_verify_service_change_req_msg(M, _Mid) ->
{error, {invalid_message, M}}.
--ifndef(megaco_hipe_special).
rle1_mgc_verify_notify_req_msg_fun() ->
fun(M) ->
rle1_mgc_verify_notify_req_msg(M)
end.
--endif.
rle1_mgc_verify_notify_req_msg(#'MegacoMessage'{mess = Mess} = M) ->
io:format("rle1_mgc_verify_notify_req_msg -> entry with"
@@ -1054,21 +1017,12 @@ rle1_mgc_verify_notify_req_msg(M) ->
%%
%% MG generator stuff
%%
--ifdef(megaco_hipe_special).
--define(rle1_mg_verify_handle_connect_fun(),
- {?MODULE, rle1_mg_verify_handle_connect, []}).
--define(rle1_mg_verify_service_change_rep_fun(),
- {?MODULE, rle1_mg_verify_service_change_rep, []}).
--define(rle1_mg_verify_trans_rep_fun(),
- {?MODULE, rle1_mg_verify_trans_rep, []}).
--else.
-define(rle1_mg_verify_handle_connect_fun(),
fun rle1_mg_verify_handle_connect/1).
-define(rle1_mg_verify_service_change_rep_fun(),
fun rle1_mg_verify_service_change_rep/1).
-define(rle1_mg_verify_trans_rep_fun(),
fun rle1_mg_verify_trans_rep/1).
--endif.
rle1_mg_event_sequence(text, tcp) ->
Mid = {deviceName,"mg"},
@@ -1222,23 +1176,34 @@ recv_limit_exceeded2(Config) when is_list(Config) ->
otp_4956(suite) ->
[];
otp_4956(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, otp_4956),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
- d("[MGC] start the simulator "),
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_4956_mgc),
+ MgNode = make_node_name(pl_4956_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_otp_4956(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_otp_4956(#{nodes := [MgcNode, MgNode]}) ->
+ i("[MGC] start the simulator "),
{ok, Mgc} = megaco_test_megaco_generator:start_link("MGC", MgcNode),
- d("[MGC] create the event sequence"),
+ i("[MGC] create the event sequence"),
MgcEvSeq = otp_4956_mgc_event_sequence(text, tcp),
i("wait some time before starting the MGC simulation"),
@@ -1273,10 +1238,6 @@ otp_4956(Config) when is_list(Config) ->
i("[MG] stop generator"),
megaco_test_tcp_generator:stop(Mg),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
i("done", []),
ok.
@@ -1284,20 +1245,6 @@ otp_4956(Config) when is_list(Config) ->
%%
%% MGC generator stuff
%%
--ifdef(megaco_hipe_special).
--define(otp_4956_mgc_verify_handle_connect_fun(),
- {?MODULE, otp_4956_mgc_verify_handle_connect, []}).
--define(otp_4956_mgc_verify_service_change_req_fun(Mid),
- {?MODULE, otp_4956_mgc_verify_service_change_req, [Mid]}).
--define(otp_4956_mgc_verify_notify_req1_fun(),
- {?MODULE, otp_4956_mgc_verify_notify_req1, []}).
--define(otp_4956_mgc_verify_notify_req2_fun(),
- {?MODULE, otp_4956_mgc_verify_notify_req2, []}).
--define(otp_4956_mgc_verify_handle_trans_req_abort_fun(),
- {?MODULE, otp_4956_mgc_verify_handle_trans_req_abort, []}).
--define(otp_4956_mgc_verify_handle_disconnect_fun(),
- {?MODULE, otp_4956_mgc_verify_handle_disconnect, []}).
--else.
-define(otp_4956_mgc_verify_handle_connect_fun(),
otp_4956_mgc_verify_handle_connect_fun()).
-define(otp_4956_mgc_verify_service_change_req_fun(Mid),
@@ -1310,7 +1257,6 @@ otp_4956(Config) when is_list(Config) ->
otp_4956_mgc_verify_handle_trans_req_abort_fun()).
-define(otp_4956_mgc_verify_handle_disconnect_fun(),
fun otp_4956_mgc_verify_handle_disconnect/1).
--endif.
otp_4956_mgc_event_sequence(text, tcp) ->
Mid = {deviceName,"ctrl"},
@@ -1355,24 +1301,20 @@ otp_4956_mgc_event_sequence(text, tcp) ->
EvSeq.
--ifndef(megaco_hipe_special).
otp_4956_mgc_verify_handle_connect_fun() ->
fun(M) ->
otp_4956_mgc_verify_handle_connect(M)
end.
--endif.
otp_4956_mgc_verify_handle_connect({handle_connect, CH, ?VERSION}) ->
{ok, CH, ok};
otp_4956_mgc_verify_handle_connect(Else) ->
{error, Else, ok}.
--ifndef(megaco_hipe_special).
otp_4956_mgc_verify_service_change_req_fun(Mid) ->
fun(Req) ->
otp_4956_mgc_verify_service_change_req(Req, Mid)
end.
--endif.
otp_4956_mgc_verify_service_change_req(
{handle_trans_request, _, ?VERSION, [AR]}, Mid) ->
@@ -1434,12 +1376,10 @@ otp_4956_mgc_verify_service_change_req(Else, _Mid) ->
ErrReply = {discard_ack, ED},
{error, Else, ErrReply}.
--ifndef(megaco_hipe_special).
otp_4956_mgc_verify_notify_req1_fun() ->
fun(Req) ->
otp_4956_mgc_verify_notify_req1(Req)
end.
--endif.
otp_4956_mgc_verify_notify_req1({handle_trans_request, _, ?VERSION, [AR]}) ->
io:format("otp_4956_mgc_verify_notify_req1 -> entry with"
@@ -1470,12 +1410,10 @@ otp_4956_mgc_verify_notify_req1(Else) ->
ErrReply = {discard_ack, ED},
{error, Else, ErrReply}.
--ifndef(megaco_hipe_special).
otp_4956_mgc_verify_notify_req2_fun() ->
fun(Ev) ->
otp_4956_mgc_verify_notify_req2(Ev)
end.
--endif.
otp_4956_mgc_verify_notify_req2({handle_trans_request, _, ?VERSION, [AR]}) ->
case AR of
@@ -1500,12 +1438,10 @@ otp_4956_mgc_verify_notify_req2(Else) ->
ErrReply = {discard_ack, ED},
{error, Else, ErrReply}.
--ifndef(megaco_hipe_special).
otp_4956_mgc_verify_handle_trans_req_abort_fun() ->
fun(Req) ->
otp_4956_mgc_verify_handle_trans_req_abort(Req)
end.
--endif.
otp_4956_mgc_verify_handle_trans_req_abort({handle_trans_request_abort,
CH, ?VERSION, 2, Pid}) ->
@@ -1574,18 +1510,6 @@ otp_4956_mgc_notify_reply_ar(Cid, TermId) ->
%%
%% MG generator stuff
%%
--ifdef(megaco_hipe_special).
--define(otp_4956_mg_decode_msg_fun(Mod, Conf),
- {?MODULE, decode_msg, [Mod, Conf]}).
--define(otp_4956_mg_encode_msg_fun(Mod, Conf),
- {?MODULE, encode_msg, [Mod, Conf]}).
--define(otp_4956_mg_verify_service_change_rep_msg_fun(),
- {?MODULE, otp_4956_mg_verify_service_change_rep_msg, []}).
--define(otp_4956_mg_verify_pending_msg_fun(),
- {?MODULE, otp_4956_mg_verify_pending_msg, []}).
--define(otp_4956_mg_verify_pending_limit_msg_fun(),
- {?MODULE, otp_4956_mg_verify_pending_limit_msg, []}).
--else.
-define(otp_4956_mg_decode_msg_fun(Mod, Conf),
otp_4956_mg_decode_msg_fun(Mod, Conf)).
-define(otp_4956_mg_encode_msg_fun(Mod, Conf),
@@ -1596,7 +1520,6 @@ otp_4956_mgc_notify_reply_ar(Cid, TermId) ->
otp_4956_mg_verify_pending_msg_fun()).
-define(otp_4956_mg_verify_pending_limit_msg_fun(),
otp_4956_mg_verify_pending_limit_msg_fun()).
--endif.
otp_4956_mg_event_sequence(text, tcp) ->
DecodeFun = ?otp_4956_mg_decode_msg_fun(megaco_pretty_text_encoder, []),
@@ -1642,7 +1565,6 @@ otp_4956_mg_event_sequence(text, tcp) ->
],
EvSeq.
--ifndef(megaco_hipe_special).
otp_4956_mg_encode_msg_fun(Mod, Conf) ->
fun(M) ->
encode_msg(M, Mod, Conf)
@@ -1652,14 +1574,11 @@ otp_4956_mg_decode_msg_fun(Mod, Conf) ->
fun(M) ->
decode_msg(M, Mod, Conf)
end.
--endif.
--ifndef(megaco_hipe_special).
otp_4956_mg_verify_service_change_rep_msg_fun() ->
fun(M) ->
otp_4956_mg_verify_service_change_rep_msg(M)
end.
--endif.
otp_4956_mg_verify_service_change_rep_msg(
#'MegacoMessage'{mess = Mess} = M) ->
@@ -1687,12 +1606,10 @@ otp_4956_mg_verify_service_change_rep_msg(
otp_4956_mg_verify_service_change_rep_msg(M) ->
{error, {invalid_message, M}}.
--ifndef(megaco_hipe_special).
otp_4956_mg_verify_pending_msg_fun() ->
fun(M) ->
otp_4956_mg_verify_pending_msg(M)
end.
--endif.
otp_4956_mg_verify_pending_msg(#'MegacoMessage'{mess = Mess} = M) ->
io:format("otp_4956_mg_verify_pending_msg -> entry with"
@@ -1710,12 +1627,10 @@ otp_4956_mg_verify_pending_msg(M) ->
"~n", [M]),
{error, {invalid_message, M}}.
--ifndef(megaco_hipe_special).
otp_4956_mg_verify_pending_limit_msg_fun() ->
fun(M) ->
otp_4956_mg_verify_pending_limit_msg(M)
end.
--endif.
otp_4956_mg_verify_pending_limit_msg(#'MegacoMessage'{mess = Mess} = M) ->
io:format("otp_4956_mg_verify_pending_limit_msg -> entry with"
@@ -1784,29 +1699,37 @@ otp_5310(suite) ->
otp_5310(doc) ->
"...";
otp_5310(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, otp_5310),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_5310_mgc),
+ MgNode = make_node_name(pl_5310_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_otp_5310(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_otp_5310(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
- {ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -1897,18 +1820,6 @@ otp_5310(Config) when is_list(Config) ->
UserReps3 = ?MGC_USER_INFO(Mgc, replies),
d("[MGC] UserReps3: ~p", [UserReps3]),
- %% Tell MG to stop
- i("[MG] stop"),
- ?MG_STOP(Mg),
-
- %% Tell Mgc to stop
- i("[MGC] stop"),
- ?MGC_STOP(Mgc),
-
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
i("done", []),
ok.
@@ -1951,29 +1862,37 @@ otp_5619(suite) ->
otp_5619(doc) ->
"...";
otp_5619(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(sname, "TEST"),
- put(tc, otp_5619),
- i("starting"),
-
- MgcNode = make_node_name(mgc),
- MgNode = make_node_name(mg),
- d("start nodes: "
- "~n MgcNode: ~p"
- "~n MgNode: ~p",
- [MgcNode, MgNode]),
- ok = ?START_NODES([MgcNode, MgNode], true),
-
+ Cond = fun() -> ok end,
+ Pre = fun() ->
+ put(tc, ?FUNCTION_NAME),
+ MgcNode = make_node_name(pl_5619_mgc),
+ MgNode = make_node_name(pl_5619_mg),
+ i("try start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ Nodes = [MgcNode, MgNode],
+ ok = ?START_NODES(Nodes, true),
+ #{nodes => Nodes}
+ end,
+ Case = fun(State) ->
+ do_otp_5619(State)
+ end,
+ Post = fun(#{nodes := Nodes}) ->
+ i("stop nodes"),
+ ?STOP_NODES(Nodes),
+ ok
+ end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_otp_5619(#{nodes := [MgcNode, MgNode]}) ->
%% Start the MGC and MGs
i("[MGC] start"),
- MgcMid = {deviceName, "ctrl"},
ET = [{text, tcp}, {text, udp}, {binary, tcp}, {binary, udp}],
- {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, [], ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, ET),
i("[MG] start"),
- MgMid = {deviceName, "mg"},
- MgConfig = [],
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, text, tcp),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
d("MG conn info: ~p", [?MG_CONN_INFO(Mg, all)]),
@@ -2027,11 +1946,7 @@ otp_5619(Config) when is_list(Config) ->
i("[MGC] stop~n"),
?MGC_STOP(Mgc),
- %% Cleanup
- d("stop nodes"),
- ?STOP_NODES([MgcNode, MgNode]),
-
- i("done", []),
+ i("done"),
ok.
@@ -2160,14 +2075,12 @@ cre_megacoMessage(Mess) ->
%% having received the first pending (which
%% indicates that the other side _IS_
%% working on the request).
--ifdef(MEGACO_TEST_CODE).
init_request_timer({short, Ref}) ->
{long, Ref};
init_request_timer(O) ->
O.
--endif.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2187,12 +2100,6 @@ decode_msg(M, Mod, Conf) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% tim() ->
-%% {A,B,C} = erlang:now(),
-%% A*1000000000+B*1000+(C div 1000).
-
-
make_node_name(Name) ->
case string:tokens(atom_to_list(node()), [$@]) of
[_,Host] ->
@@ -2218,11 +2125,31 @@ await_completion(Ids) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+try_tc(TCName, Cond, Pre, Case, Post) ->
+ try_tc(TCName, "TEST", ?TEST_VERBOSITY, Cond, Pre, Case, Post).
+
+try_tc(TCName, Name, Verbosity, Cond, Pre, Case, Post) ->
+ ?TRY_TC(TCName, Name, Verbosity, Cond, Pre, Case, Post).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
sleep(X) -> receive after X -> ok end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-ifdef(MEGACO_TEST_CODE).
+megaco_test_code() ->
+ ok.
+-else.
+megaco_test_code() ->
+ exit({skip, "Included only if compiled with USE_MEGACO_TEST_CODE=true"}).
+-endif.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
p(F, A) ->
io:format("*** [~s] ~p ***"
"~n " ++ F ++ "~n",
diff --git a/lib/megaco/test/megaco_tcp_SUITE.erl b/lib/megaco/test/megaco_tcp_SUITE.erl
index 43ecb335be..300772e564 100644
--- a/lib/megaco/test/megaco_tcp_SUITE.erl
+++ b/lib/megaco/test/megaco_tcp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -318,10 +318,10 @@ start_and_stop(doc) ->
start_and_stop(Config) when is_list(Config) ->
Pre = fun() ->
p("create nodes"),
- ServerNode = make_node_name(server),
- ClientNode = make_node_name(client),
+ ServerNode = make_node_name(t_sas_server),
+ ClientNode = make_node_name(t_sas_client),
Nodes = [ServerNode, ClientNode],
- ok = ?START_NODES(Nodes),
+ ok = ?START_NODES(Nodes, true),
Nodes
end,
Case = fun(X) -> do_start_and_stop(Config, X) end,
@@ -461,10 +461,10 @@ sendreceive(suite) ->
sendreceive(Config) when is_list(Config) ->
Pre = fun() ->
p("create nodes"),
- ServerNode = make_node_name(server),
- ClientNode = make_node_name(client),
+ ServerNode = make_node_name(t_sr_server),
+ ClientNode = make_node_name(t_sr_client),
Nodes = [ServerNode, ClientNode],
- ok = ?START_NODES(Nodes),
+ ok = ?START_NODES(Nodes, true),
Nodes
end,
Case = fun(X) -> do_sendreceive(Config, X) end,
@@ -673,10 +673,10 @@ block_unblock(suite) ->
block_unblock(Config) when is_list(Config) ->
Pre = fun() ->
p("create nodes"),
- ServerNode = make_node_name(server),
- ClientNode = make_node_name(client),
+ ServerNode = make_node_name(t_bb_server),
+ ClientNode = make_node_name(t_bb_client),
Nodes = [ServerNode, ClientNode],
- ok = ?START_NODES(Nodes),
+ ok = ?START_NODES(Nodes, true),
Nodes
end,
Case = fun(X) -> do_block_unblock(Config, X) end,
@@ -1054,14 +1054,22 @@ process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg)
await_server_listening(Server, Client) ->
receive
{listening, Server} ->
- p("received listening message from server [~p] => "
+ p("[await-server-listening] "
+ "received listening message from server [~p] => "
"send continue to client [~p]"
"~n", [Server, Client]),
Client ! {continue, self()},
ok;
{'EXIT', Server, SReason} ->
+ p("[await-server-listening] unexpected server (~p) exit: "
+ "~n ~p"
+ "~n", [Server, SReason]),
exit({server_crash, SReason});
{'EXIT', Client, CReason} ->
+ p("[await-server-listening] "
+ "unexpected client (~p) exit: "
+ "~n ~p"
+ "~n", [Client, CReason]),
exit({client_crash, CReason})
after 5000 ->
%% There is no normal reason why this should take any time.
@@ -1076,13 +1084,22 @@ await_server_listening(Server, Client) ->
await_client_blocked(Server, Client) ->
receive
{blocked, Client} ->
- p("received blocked message from client [~p] => "
+ p("[await-client-blocked] "
+ "received blocked message from client [~p] => "
"send continue to server [~p]~n", [Client, Server]),
Server ! {continue, self()},
ok;
{'EXIT', Client, CReason} ->
+ p("[await-client-blocked] "
+ "unexpected client (~p) exit: "
+ "~n ~p"
+ "~n", [Client, CReason]),
exit({client_crash, CReason});
{'EXIT', Server, SReason} ->
+ p("[await-client-blocked] "
+ "unexpected server (~p) exit: "
+ "~n ~p"
+ "~n", [Server, SReason]),
exit({server_crash, SReason})
after 5000 ->
%% There is no normal reason why this should take any time.
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 8e7c3bec68..1eab21ef5a 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -50,7 +50,7 @@
display_system_info/1, display_system_info/2, display_system_info/3,
executor/1, executor/2,
- try_tc/6,
+ try_tc/6, try_tc/7,
prepare_test_case/5,
@@ -62,6 +62,7 @@
stop_nodes/3,
stop_node/3,
+ ping/1, ping/2,
is_socket_backend/1,
inet_backend_opts/1,
@@ -75,9 +76,12 @@
-export([proxy_init/2]).
+%% Convenient exports...
+-export([analyze_and_print_host_info/0]).
+
-include("megaco_test_lib.hrl").
--record('REASON', {mod, line, desc}).
+%% -record('REASON', {mod, line, desc}).
%% ----------------------------------------------------------------
@@ -363,19 +367,11 @@ display_system_info(WhenStr, ModFuncStr) ->
%% Stores the result in the process dictionary if mismatch
error(Actual, Mod, Line) ->
- global:send(megaco_global_logger, {failed, Mod, Line}),
log("<ERROR> Bad result: ~p~n", [Actual], Mod, Line),
Label = lists:concat([Mod, "(", Line, ") unexpected result"]),
megaco:report_event(60, Mod, Mod, Label,
[{line, Mod, Line}, {error, Actual}]),
- case global:whereis_name(megaco_test_case_sup) of
- undefined ->
- ignore;
- Pid ->
- Fail = #'REASON'{mod = Mod, line = Line, desc = Actual},
- Pid ! {fail, self(), Fail}
- end,
- Actual.
+ exit(Actual).
log(Format, Args, Mod, Line) ->
case global:whereis_name(megaco_global_logger) of
@@ -717,43 +713,421 @@ num_schedulers_to_factor() ->
end.
-
+ts_extra_platform_label() ->
+ case os:getenv("TS_EXTRA_PLATFORM_LABEL") of
+ false -> "-";
+ Val -> Val
+ end.
+
+ts_scale_factor() ->
+ case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
+ _ ->
+ 0
+ end.
+
+simplify_label("Systemtap" ++ _) ->
+ {host, systemtap};
+simplify_label("Meamax" ++ _) ->
+ {host, meamax};
+simplify_label("Cover" ++ _) ->
+ {host, cover};
+simplify_label(Label) ->
+ case string:find(string:to_lower(Label), "docker") of
+ "docker" ++ _ ->
+ docker;
+ _ ->
+ {host, undefined}
+ end.
+
+label2factor(docker) ->
+ 4;
+label2factor({host, meamax}) ->
+ 2;
+label2factor({host, cover}) ->
+ 6;
+label2factor({host, _}) ->
+ 0.
+
linux_which_distro(Version) ->
- case file:read_file_info("/etc/issue") of
+ Label = ts_extra_platform_label(),
+ Checks =
+ [fun() -> do_linux_which_distro_os_release(Version, Label) end,
+ fun() -> do_linux_which_distro_suse_release(Version, Label) end,
+ fun() -> do_linux_which_distro_fedora_release(Version, Label) end,
+ fun() -> do_linux_which_distro_issue(Version, Label) end],
+ try linux_which_distro("", Version, Label, Checks)
+ catch
+ throw:{distro, Distro} ->
+ Distro
+ end.
+
+linux_which_distro("", Version, Label, []) ->
+ io:format("Linux: ~s"
+ "~n Label: ~s"
+ "~n Product Name: ~s"
+ "~n", [Version, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)};
+linux_which_distro(DestroStr, Version, Label, []) ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Label: ~s"
+ "~n Product Name: ~s"
+ "~n", [Version, DestroStr, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)};
+linux_which_distro(Default, Version, Label, [Check|Checks]) ->
+ try Check() of
+ DistroStr when is_list(DistroStr) ->
+ linux_which_distro(DistroStr, Version, Label, Checks);
+ retry ->
+ linux_which_distro(Default, Version, Label, Checks);
+ {error, _Reason} ->
+ linux_which_distro(Default, Version, Label, Checks)
+ catch
+ throw:{error, _Reason} ->
+ linux_which_distro(Default, Version, Label, Checks)
+ end.
+
+
+do_linux_which_distro_os_release(Version, Label) ->
+ case file:read_file_info("/etc/os-release") of
+ {ok, _} ->
+ %% We want to 'catch' if our processing is wrong,
+ %% that's why we catch and re-throw the distro.
+ %% Actual errors will be returned as 'ignore'.
+ try
+ begin
+ Info = linux_process_os_release(),
+ {value, {_, DistroStr}} = lists:keysearch(name, 1, Info),
+ {value, {_, VersionNo}} = lists:keysearch(version, 1, Info),
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, VersionNo, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_distro_str_to_distro_id(DistroStr),
+ simplify_label(Label)}})
+ end
+ catch
+ throw:{distro, _} = DISTRO ->
+ throw(DISTRO);
+ _:_ ->
+ retry
+ end;
+ _ ->
+ retry
+ end.
+
+
+linux_process_os_release() ->
+ %% Read the "raw" file
+ Raw = os:cmd("cat /etc/os-release"),
+ %% Split it into lines
+ Lines1 = string:tokens(Raw, [$\n]),
+ %% Just in case, skip any lines starting with '#'.
+ Lines2 = linux_process_os_release1(Lines1),
+ %% Each (remaining) line *should* be: <TAG>=<VALUE>
+ %% Both sides will be strings, the value side will be a quoted string...
+ %% Convert those into a 2-tuple list: [{Tag, Value}]
+ linux_process_os_release2(Lines2).
+
+linux_process_os_release1(Lines) ->
+ linux_process_os_release1(Lines, []).
+
+linux_process_os_release1([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release1([H|T], Acc) ->
+ case H of
+ "#" ++ _ ->
+ linux_process_os_release1(T, Acc);
+ _ ->
+ linux_process_os_release1(T, [H|Acc])
+ end.
+
+linux_process_os_release2(Lines) ->
+ linux_process_os_release2(Lines, []).
+
+linux_process_os_release2([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release2([H|T], Acc) ->
+ case linux_process_os_release3(H) of
+ {value, Value} ->
+ linux_process_os_release2(T, [Value|Acc]);
+ false ->
+ linux_process_os_release2(T, Acc)
+ end.
+
+linux_process_os_release3(H) ->
+ case [string:strip(S) || S <- string:tokens(H, [$=])] of
+ [Tag, Value] ->
+ Tag2 = list_to_atom(string:to_lower(Tag)),
+ Value2 = string:strip(Value, both, $"),
+ linux_process_os_release4(Tag2, Value2);
+ _ ->
+ false
+ end.
+
+linux_process_os_release4(name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version_id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(pretty_name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(_Tag, _Value) ->
+ false.
+
+linux_distro_str_to_distro_id("Debian" ++ _) ->
+ debian;
+linux_distro_str_to_distro_id("Fedora" ++ _) ->
+ fedora;
+linux_distro_str_to_distro_id("Linux Mint" ++ _) ->
+ linux_mint;
+linux_distro_str_to_distro_id("MontaVista" ++ _) ->
+ montavista;
+linux_distro_str_to_distro_id("openSUSE" ++ _) ->
+ suse;
+linux_distro_str_to_distro_id("SLES" ++ _) ->
+ sles;
+linux_distro_str_to_distro_id("Ubuntu" ++ _) ->
+ ubuntu;
+linux_distro_str_to_distro_id("Wind River Linux" ++ _) ->
+ wind_river;
+linux_distro_str_to_distro_id("Yellow Dog" ++ _) ->
+ yellow_dog;
+linux_distro_str_to_distro_id(X) ->
+ X.
+
+
+do_linux_which_distro_fedora_release(Version, Label) ->
+ %% Check if fedora
+ case file:read_file_info("/etc/fedora-release") of
{ok, _} ->
case [string:trim(S) ||
- S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
- [DistroStr|_] ->
+ S <- string:tokens(os:cmd("cat /etc/fedora-release"),
+ [$\n])] of
+ [DistroStr | _] ->
io:format("Linux: ~s"
- "~n ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
"~n",
- [Version, DistroStr]),
+ [Version, DistroStr, Label,
+ linux_product_name()]);
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Fedora", Label,
+ linux_product_name()])
+ end,
+ throw({distro, {fedora, simplify_label(Label)}});
+ _ ->
+ throw({error, not_found})
+ end.
+
+do_linux_which_distro_suse_release(Version, Label) ->
+ %% Check if its a SuSE
+ case file:read_file_info("/etc/SUSE-brand") of
+ {ok, _} ->
+ case file:read_file_info("/etc/SuSE-release") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/SuSE-release"),
+ [$\n])] of
+ ["SUSE Linux Enterprise Server" ++ _ = DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {sles, simplify_label(Label)}});
+ [DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "SuSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ case string:tokens(os:cmd("cat /etc/SUSE-brand"), [$\n]) of
+ ["SLE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}})
+ end;
+ ["openSUSE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Unknown SUSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end
+ end;
+ _ ->
+ throw({error, not_found})
+ end.
+
+do_linux_which_distro_issue(Version, Label) ->
+ case file:read_file_info("/etc/issue") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
+ [DistroStr | _] ->
case DistroStr of
"Wind River Linux" ++ _ ->
- wind_river;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {wind_river, simplify_label(Label)}});
"MontaVista" ++ _ ->
- montavista;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {montavista, simplify_label(Label)}});
"Yellow Dog" ++ _ ->
- yellow_dog;
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {yellow_dog, simplify_label(Label)}});
+ "Ubuntu" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {ubuntu, simplify_label(Label)}});
+ "Linux Mint" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_mint, simplify_label(Label)}});
+ "Debian" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {debian, simplify_label(Label)}});
_ ->
- other
+ DistroStr
end;
X ->
- io:format("Linux: ~s"
- "~n ~p"
- "~n",
- [Version, X]),
- other
+ X
end;
_ ->
- io:format("Linux: ~s"
- "~n", [Version]),
- other
+ throw({error, not_found})
end.
+
-
analyze_and_print_linux_host_info(Version) ->
- Distro = linux_which_distro(Version),
+ {Distro, Label} = linux_which_distro(Version),
+ %% 'VirtFactor' will be 0 unless virtual
+ VirtFactor = linux_virt_factor(),
Factor =
case (catch linux_which_cpuinfo(Distro)) of
{ok, {CPU, BogoMIPS}} ->
@@ -765,14 +1139,18 @@ analyze_and_print_linux_host_info(Version) ->
if
(BogoMIPS > 50000) ->
1;
- (BogoMIPS > 30000) ->
+ (BogoMIPS > 40000) ->
2;
- (BogoMIPS > 10000) ->
+ (BogoMIPS > 30000) ->
3;
- (BogoMIPS > 5000) ->
+ (BogoMIPS > 20000) ->
+ 4;
+ (BogoMIPS > 10000) ->
5;
- (BogoMIPS > 3000) ->
+ (BogoMIPS > 5000) ->
8;
+ (BogoMIPS > 3000) ->
+ 12;
true ->
10
end;
@@ -805,21 +1183,53 @@ analyze_and_print_linux_host_info(Version) ->
_ ->
5
end,
+ AddLabelFactor = label2factor(Label),
%% Check if we need to adjust the factor because of the memory
- try linux_which_meminfo() of
- AddFactor ->
- {Factor + AddFactor, []}
- catch
- _:_:_ ->
- {Factor, []}
- end.
+ AddMemFactor = try linux_which_meminfo()
+ catch _:_:_ -> 0
+ end,
+ TSScaleFactor = case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
+ _ ->
+ 0
+ end,
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n Virtual Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n", [Factor, AddLabelFactor, AddMemFactor, VirtFactor,
+ TSScaleFactor]),
+ {Factor + AddLabelFactor + AddMemFactor + VirtFactor + TSScaleFactor,
+ [{label, Label}]}.
+
+
+linux_virt_factor() ->
+ linux_virt_factor(linux_product_name()).
+
+linux_virt_factor("VMware" ++ _) ->
+ 2;
+linux_virt_factor("VirtualBox" ++ _) ->
+ 4;
+linux_virt_factor(_) ->
+ 0.
linux_cpuinfo_lookup(Key) when is_list(Key) ->
linux_info_lookup(Key, "/proc/cpuinfo").
linux_cpuinfo_bogomips() ->
- case linux_cpuinfo_lookup("bogomips") of
+ case linux_cpuinfo_bogomips("bogomips") of
+ "-" ->
+ linux_cpuinfo_bogomips("BogoMIPS");
+ Res ->
+ Res
+ end.
+
+linux_cpuinfo_bogomips(Key) ->
+ case linux_cpuinfo_lookup(Key) of
[] ->
"-";
BMips when is_list(BMips) ->
@@ -864,7 +1274,14 @@ linux_cpuinfo_model() ->
[M] ->
M;
_ ->
- "-"
+ %% Note that some distros/platforms,
+ %% the first char is Capital, that is: Model...
+ case linux_cpuinfo_lookup("Model") of
+ [M] ->
+ M;
+ _ ->
+ "-"
+ end
end.
linux_cpuinfo_platform() ->
@@ -907,6 +1324,14 @@ linux_cpuinfo_processor() ->
"-"
end.
+linux_cpuinfo_machine() ->
+ case linux_cpuinfo_lookup("machine") of
+ [M] ->
+ M;
+ _ ->
+ "-"
+ end.
+
linux_cpuinfo_clock() ->
%% This is written as: "3783.000000MHz"
%% So, check unit MHz (handle nothing else).
@@ -991,6 +1416,52 @@ linux_which_cpuinfo(wind_river) ->
{ok, {CPU, BMips}}
end;
+linux_which_cpuinfo(Distro) when (Distro =:= debian) orelse
+ (Distro =:= fedora) orelse
+ (Distro =:= linux_mint) orelse
+ (Distro =:= sles) orelse
+ (Distro =:= suse) orelse
+ (Distro =:= ubuntu) orelse
+ (Distro =:= other) ->
+ CPU =
+ case linux_cpuinfo_model_name() of
+ "-" ->
+ %% This is for POWER9
+ case linux_cpuinfo_cpu() of
+ "POWER9" ++ _ = PowerCPU ->
+ Machine =
+ case linux_cpuinfo_machine() of
+ "-" ->
+ "";
+ M ->
+ " (" ++ M ++ ")"
+ end,
+ PowerCPU ++ Machine;
+ _X ->
+ %% ARM (at least some distros...)
+ case linux_cpuinfo_processor() of
+ "-" ->
+ case linux_cpuinfo_model() of
+ "-" ->
+ %% Ok, we give up
+ throw(noinfo);
+ Model ->
+ Model
+ end;
+ Proc ->
+ Proc
+ end
+ end;
+ ModelName ->
+ ModelName
+ end,
+ case linux_cpuinfo_bogomips() of
+ "-" ->
+ {ok, CPU};
+ BMips ->
+ {ok, {CPU, BMips}}
+ end;
+
linux_which_cpuinfo(other) ->
%% Check for x86 (Intel or AMD or Power)
CPU =
@@ -1072,6 +1543,22 @@ linux_which_meminfo() ->
end.
+linux_product_name() ->
+ ProductNameFile = "/sys/devices/virtual/dmi/id/product_name",
+ case file:read_file_info(ProductNameFile) of
+ {ok, _} ->
+ case os:cmd("cat " ++ ProductNameFile) of
+ false ->
+ "-";
+ Info ->
+ string:trim(Info)
+ end;
+ _ ->
+ "-"
+ end.
+
+
+
%% Just to be clear: This is ***not*** scientific...
analyze_and_print_openbsd_host_info(Version) ->
io:format("OpenBSD:"
@@ -1120,45 +1607,78 @@ analyze_and_print_openbsd_host_info(Version) ->
"~n", [CPU, CPUSpeed, NCPU, Memory]),
CPUFactor =
if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
+ (CPUSpeed >= 3000) ->
if
- (NCPU >= 4) ->
+ (NCPU >= 8) ->
1;
+ (NCPU >= 6) ->
+ 2;
+ (NCPU >= 4) ->
+ 3;
(NCPU >= 2) ->
+ 4;
+ true ->
+ 10
+ end;
+ (CPUSpeed >= 2000) ->
+ if
+ (NCPU >= 8) ->
2;
+ (NCPU >= 6) ->
+ 3;
+ (NCPU >= 4) ->
+ 4;
+ (NCPU >= 2) ->
+ 5;
true ->
- 3
+ 12
+ end;
+ (CPUSpeed >= 1000) ->
+ if
+ (NCPU >= 8) ->
+ 3;
+ (NCPU >= 6) ->
+ 4;
+ (NCPU >= 4) ->
+ 5;
+ (NCPU >= 2) ->
+ 6;
+ true ->
+ 14
end;
true ->
if
+ (NCPU >= 8) ->
+ 4;
+ (NCPU >= 6) ->
+ 6;
(NCPU >= 4) ->
- 2;
+ 8;
(NCPU >= 2) ->
- 3;
+ 10;
true ->
- 4
+ 20
end
end,
MemAddFactor =
if
- (Memory =:= -1) ->
+ (Memory >= 16777216) ->
0;
(Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
1;
+ (Memory >= 4194304) ->
+ 3;
(Memory >= 2097152) ->
- 2;
+ 5;
true ->
- 3
+ 10
end,
{CPUFactor + MemAddFactor, []}
end
catch
_:_:_ ->
- {5, []}
+ io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
+ {10, []}
end.
@@ -1449,47 +1969,57 @@ analyze_and_print_darwin_host_info(Version) ->
%% we need to find some other way to find some info...
%% Also, I suppose its possible that we for some other
%% reason *fail* to get the info...
- case analyze_darwin_software_info() of
- [] ->
- io:format("Darwin:"
- "~n Version: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [Version, str_num_schedulers()]),
- {num_schedulers_to_factor(), []};
- SwInfo when is_list(SwInfo) ->
- SystemVersion = analyze_darwin_sw_system_version(SwInfo),
- KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
- HwInfo = analyze_darwin_hardware_info(),
- ModelName = analyze_darwin_hw_model_name(HwInfo),
- ModelId = analyze_darwin_hw_model_identifier(HwInfo),
- ProcName = analyze_darwin_hw_processor_name(HwInfo),
- ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
- NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
- NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
- Memory = analyze_darwin_hw_memory(HwInfo),
- io:format("Darwin:"
- "~n System Version: ~s"
- "~n Kernel Version: ~s"
- "~n Model: ~s (~s)"
- "~n Processor: ~s (~s, ~s, ~s)"
- "~n Memory: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [SystemVersion, KernelVersion,
- ModelName, ModelId,
- ProcName, ProcSpeed, NumProc, NumCores,
- Memory,
- str_num_schedulers()]),
- CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
- ProcSpeed,
- NumProc,
- NumCores),
- MemFactor = analyze_darwin_memory_to_factor(Memory),
- if (MemFactor =:= 1) ->
- {CPUFactor, []};
- true ->
- {CPUFactor + MemFactor, []}
- end
- end.
+ Label = ts_extra_platform_label(),
+ {BaseFactor, MemFactor} =
+ case analyze_darwin_software_info() of
+ [] ->
+ io:format("Darwin:"
+ "~n Version: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n", [Version, str_num_schedulers(), Label]),
+ {num_schedulers_to_factor(), 1};
+ SwInfo when is_list(SwInfo) ->
+ SystemVersion = analyze_darwin_sw_system_version(SwInfo),
+ KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
+ HwInfo = analyze_darwin_hardware_info(),
+ ModelName = analyze_darwin_hw_model_name(HwInfo),
+ ModelId = analyze_darwin_hw_model_identifier(HwInfo),
+ {Processor, CPUFactor} = analyze_darwin_hw_processor(HwInfo),
+ Memory = analyze_darwin_hw_memory(HwInfo),
+ io:format("Darwin:"
+ "~n System Version: ~s"
+ "~n Kernel Version: ~s"
+ "~n Model: ~s (~s)"
+ "~n Processor: ~s"
+ "~n Memory: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n~n",
+ [SystemVersion, KernelVersion,
+ ModelName, ModelId,
+ Processor,
+ Memory,
+ str_num_schedulers(), Label]),
+ {CPUFactor, analyze_darwin_memory_to_factor(Memory)}
+ end,
+ AddLabelFactor = label2factor(simplify_label(Label)),
+ AddMemFactor = if
+ (MemFactor > 0) ->
+ MemFactor - 1;
+ true ->
+ 0
+ end,
+ TSScaleFactor = ts_scale_factor(),
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n~n",
+ [BaseFactor, AddLabelFactor, AddMemFactor, TSScaleFactor]),
+ {BaseFactor + AddLabelFactor + AddMemFactor + TSScaleFactor,
+ [{label, Label}]}.
analyze_darwin_sw_system_version(SwInfo) ->
proplists:get_value("system version", SwInfo, "-").
@@ -1500,12 +2030,38 @@ analyze_darwin_sw_kernel_version(SwInfo) ->
analyze_darwin_software_info() ->
analyze_darwin_system_profiler("SPSoftwareDataType").
+analyze_darwin_hw_chip(HwInfo) ->
+ proplists:get_value("chip", HwInfo, "-").
+
analyze_darwin_hw_model_name(HwInfo) ->
proplists:get_value("model name", HwInfo, "-").
analyze_darwin_hw_model_identifier(HwInfo) ->
proplists:get_value("model identifier", HwInfo, "-").
+analyze_darwin_hw_processor(HwInfo) ->
+ case analyze_darwin_hw_processor_name(HwInfo) of
+ "-" -> % Maybe Apple Chip
+ case analyze_darwin_hw_chip(HwInfo) of
+ "-" ->
+ "-";
+ Chip ->
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(Chip, NumCores),
+ {f("~s [~s]", [Chip, NumCores]), CPUFactor}
+ end;
+ ProcName ->
+ ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
+ NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
+ ProcSpeed,
+ NumProc,
+ NumCores),
+ {f("~s [~s, ~s, ~s]",
+ [ProcName, ProcSpeed, NumProc, NumCores]), CPUFactor}
+ end.
+
analyze_darwin_hw_processor_name(HwInfo) ->
case proplists:get_value("processor name", HwInfo, "-") of
"-" ->
@@ -1540,17 +2096,25 @@ analyze_darwin_hardware_info() ->
%% "Key: Value1:Value2"
analyze_darwin_system_profiler(DataType) ->
%% First, make sure the program actually exist:
- case os:cmd("which system_profiler") of
+ case string:trim(os:cmd("which system_profiler")) of
[] ->
- [];
- _ ->
- D0 = os:cmd("system_profiler " ++ DataType),
- D1 = string:tokens(D0, [$\n]),
- D2 = [string:trim(S1) || S1 <- D1],
- D3 = [string:tokens(S2, [$:]) || S2 <- D2],
- analyze_darwin_system_profiler2(D3)
+ case string:trim(os:cmd("which /usr/sbin/system_profiler")) of
+ [] ->
+ [];
+ Cmd1 ->
+ analyze_darwin_system_profiler(Cmd1, DataType)
+ end;
+ Cmd2 ->
+ analyze_darwin_system_profiler(Cmd2, DataType)
end.
+analyze_darwin_system_profiler(Cmd, DataType) ->
+ D0 = os:cmd(Cmd ++ " " ++ DataType),
+ D1 = string:tokens(D0, [$\n]),
+ D2 = [string:trim(S1) || S1 <- D1],
+ D3 = [string:tokens(S2, [$:]) || S2 <- D2],
+ analyze_darwin_system_profiler2(D3).
+
analyze_darwin_system_profiler2(L) ->
analyze_darwin_system_profiler2(L, []).
@@ -1600,6 +2164,12 @@ analyze_darwin_memory_to_factor(Mem) ->
end.
+analyze_darwin_cpu_to_factor("Apple" ++ _ = _Chip, _NumCores) ->
+ 1;
+analyze_darwin_cpu_to_factor(_Chip, _NumCores) ->
+ 8.
+
+
%% The speed is a string: "<speed> <unit>"
%% the speed may be a float, which we transforms into an integer of MHz.
%% To calculate a factor based on processor speed, number of procs
@@ -2133,68 +2703,199 @@ executor(Fun, Timeout)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-try_tc(TCName, Name, Verbosity, Pre, Case, Post)
- when is_function(Pre, 0) andalso
+try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
+ Cond = fun() -> ok end,
+ try_tc(TCName, Name, Verbosity, Cond, Pre, Case, Post).
+
+try_tc(TCName, Name, Verbosity, Cond, Pre, Case, Post)
+ when is_function(Cond, 0) andalso
+ is_function(Pre, 0) andalso
is_function(Case, 1) andalso
is_function(Post, 1) ->
- process_flag(trap_exit, true),
- put(verbosity, Verbosity),
- put(sname, Name),
- put(tc, TCName),
- p("try_tc -> starting: try pre"),
- try Pre() of
- State ->
- p("try_tc -> pre done: try test case"),
- try Case(State) of
- Res ->
- p("try_tc -> test case done: try post"),
- _ = executor(fun() -> Post(State) end),
- p("try_tc -> done"),
- Res
+ tc_begin(TCName, Name, Verbosity),
+ try Cond() of
+ ok ->
+ tc_print("starting: try pre"),
+ try Pre() of
+ State ->
+ tc_print("pre done: try test case"),
+ try
+ begin
+ Res = Case(State),
+ sleep(seconds(1)),
+ tc_print("test case done: try post"),
+ _ = executor(fun() ->
+ put(verbosity, Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end("ok"),
+ Res
+ end
+ catch
+ C:{skip, _} = SKIP:_ when (C =:= throw) orelse
+ (C =:= exit) ->
+ tc_print("test case (~w) skip: try post", [C]),
+ _ = executor(fun() ->
+ put(verbosity, Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end( f("skipping(caught,~w,tc)", [C]) ),
+ SKIP;
+ C:E:S ->
+ %% We always check the system events
+ %% before we accept a failure.
+ %% We do *not* run the Post here because it might
+ %% generate sys events itself...
+ p("try_tc -> test case failed: try post"),
+ _ = executor(fun() -> Post(State) end),
+ case megaco_test_global_sys_monitor:events() of
+ [] ->
+ tc_print("test case failed: try post"),
+ _ = executor(fun() ->
+ put(verbosity,
+ Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end( f("failed(caught,~w,tc)", [C]) ),
+ erlang:raise(C, E, S);
+ SysEvs ->
+ tc_print("System Events "
+ "received during tc: "
+ "~n ~p"
+ "~nwhen tc failed:"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [SysEvs, C, E, S]),
+ _ = executor(fun() ->
+ put(verbosity,
+ Verbosity),
+ put(sname, Name),
+ put(tc, TCName),
+ Post(State)
+ end),
+ tc_end( f("skipping(catched-sysevs,~w,tc)",
+ [C]) ),
+ SKIP =
+ {skip, "TC failure with system events"},
+ SKIP
+ end
+ end
catch
- throw:{skip, _} = SKIP:_ ->
- p("try_tc -> test case (throw) skip: try post"),
- _ = executor(fun() -> Post(State) end),
- p("try_tc -> test case (throw) skip: done"),
- SKIP;
- exit:{skip, _} = SKIP:_ ->
- p("try_tc -> test case (exit) skip: try post"),
- _ = executor(fun() -> Post(State) end),
- p("try_tc -> test case (exit) skip: done"),
+ C:{skip, _} = SKIP:_ when (C =:= throw) orelse
+ (C =:= exit) ->
+ tc_end( f("skipping(caught,~w,tc-pre)", [C]) ),
SKIP;
C:E:S ->
- p("try_tc -> test case failed: try post"),
- _ = executor(fun() -> Post(State) end),
case megaco_test_global_sys_monitor:events() of
[] ->
- p("try_tc -> test case failed: done"),
- exit({case_catched, C, E, S});
+ tc_print("tc-pre failed: auto-skip"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [C, E, S]),
+ tc_end( f("auto-skip(caught,~w,tc-pre)", [C]) ),
+ SKIP = {skip, f("TC-Pre failure (~w)", [C])},
+ SKIP;
SysEvs ->
- p("try_tc -> test case failed with system event(s): "
- "~n ~p", [SysEvs]),
- {skip, "TC failure with system events"}
+ tc_print("System Events received: "
+ "~n ~p"
+ "~nwhen tc-pre failed:"
+ "~n C: ~p"
+ "~n E: ~p"
+ "~n S: ~p",
+ [SysEvs, C, E, S], "", ""),
+ tc_end( f("skipping(catched-sysevs,~w,tc-pre)",
+ [C]) ),
+ SKIP = {skip, "TC-Pre failure with system events"},
+ SKIP
end
- end
- catch
- throw:{skip, _} = SKIP:_ ->
- p("try_tc -> pre (throw) skip"),
+ end;
+ {skip, _} = SKIP ->
+ tc_end("skipping(cond)"),
SKIP;
- exit:{skip, _} = SKIP:_ ->
- p("try_tc -> pre (exit) skip"),
+ {error, Reason} ->
+ tc_end("failed(cond)"),
+ exit({tc_cond_failed, Reason})
+ catch
+ C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
+ tc_end( f("skipping(caught,~w,cond)", [C]) ),
SKIP;
C:E:S ->
+ %% We always check the system events before we accept a failure
case megaco_test_global_sys_monitor:events() of
[] ->
- p("try_tc -> pre failed: done"),
- exit({pre_catched, C, E, S});
+ tc_end( f("failed(caught,~w,cond)", [C]) ),
+ erlang:raise(C, E, S);
SysEvs ->
- p("try_tc -> pre failed with system event(s): "
- "~n ~p", [SysEvs]),
- {skip, "TC pre failure with system events"}
+ tc_print("System Events received: "
+ "~n ~p", [SysEvs], "", ""),
+ tc_end( f("skipping(catched-sysevs,~w,cond)", [C]) ),
+ SKIP = {skip, "TC cond failure with system events"},
+ SKIP
end
end.
+tc_set_name(N) when is_atom(N) ->
+ tc_set_name(atom_to_list(N));
+tc_set_name(N) when is_list(N) ->
+ put(tc_name, N).
+
+tc_get_name() ->
+ get(tc_name).
+
+tc_begin(TC, Name, Verbosity) ->
+ OldVal = process_flag(trap_exit, true),
+ put(old_trap_exit, OldVal),
+ tc_set_name(TC),
+ put(sname, Name),
+ put(verbosity, Verbosity),
+ tc_print("begin ***",
+ "~n----------------------------------------------------~n", "").
+
+tc_end(Result) when is_list(Result) ->
+ OldVal = erase(old_trap_exit),
+ process_flag(trap_exit, OldVal),
+ tc_print("done: ~s", [Result],
+ "", "----------------------------------------------------~n~n"),
+ ok.
+
+tc_print(F) ->
+ tc_print(F, [], "", "").
+
+tc_print(F, A) ->
+ tc_print(F, A, "", "").
+
+tc_print(F, Before, After) ->
+ tc_print(F, [], Before, After).
+
+tc_print(F, A, Before, After) ->
+ Name = tc_which_name(),
+ FStr = f("*** [~s][~s][~p] " ++ F ++ "~n",
+ [formated_timestamp(), Name, self() | A]),
+ io:format(user, Before ++ FStr ++ After, []),
+ io:format(standard_io, Before ++ FStr ++ After, []).
+
+tc_which_name() ->
+ case tc_get_name() of
+ undefined ->
+ case get(sname) of
+ undefined ->
+ "";
+ SName when is_list(SName) ->
+ SName
+ end;
+ Name when is_list(Name) ->
+ Name
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2234,20 +2935,24 @@ lookup_config(Key,Config) ->
[]
end.
-mk_nodes(N) when (N > 0) ->
- mk_nodes(N, []).
-mk_nodes(0, Nodes) ->
+mk_nodes(1 = _N) ->
+ [node()];
+mk_nodes(N) when is_integer(N) andalso (N > 1) ->
+ OwnNode = node(),
+ [Name0, Host] = node_to_name_and_host(OwnNode),
+ Uniq = erlang:unique_integer([positive]),
+ Name =
+ list_to_atom(lists:concat([Name0, "_", integer_to_list(Uniq)])),
+ [OwnNode | mk_nodes(N-1, Name, Host, [])].
+
+mk_nodes(0, _BaseName, _Host, Nodes) ->
Nodes;
-mk_nodes(N, []) ->
- mk_nodes(N - 1, [node()]);
-mk_nodes(N, Nodes) when N > 0 ->
- Head = hd(Nodes),
- [Name, Host] = node_to_name_and_host(Head),
- Nodes ++ [mk_node(I, Name, Host) || I <- lists:seq(1, N)].
-
-mk_node(N, Name, Host) ->
- list_to_atom(lists:concat([Name ++ integer_to_list(N) ++ "@" ++ Host])).
+mk_nodes(N, BaseName, Host, Nodes) ->
+ mk_nodes(N-1, BaseName, Host, [mk_node(N, BaseName, Host)|Nodes]).
+
+mk_node(N, BaseName, Host) ->
+ list_to_atom(lists:concat([BaseName, "_", integer_to_list(N), "@", Host])).
%% Returns [Name, Host]
node_to_name_and_host(Node) ->
@@ -2284,10 +2989,11 @@ start_node(Node, Force, File, Line)
start_node(Node, Force, false, File, Line).
start_node(Node, Force, Retry, File, Line) ->
- case net_adm:ping(Node) of
+ p("start_node -> check if node ~p already running", [Node]),
+ case ping(Node, ?SECS(5)) of
%% Do not require a *new* node
pong when (Force =:= false) ->
- p("node ~p already running", [Node]),
+ p("start_node -> node ~p already running", [Node]),
ok;
%% Do require a *new* node, so kill this one and try again
@@ -2308,26 +3014,40 @@ start_node(Node, Force, Retry, File, Line) ->
% Not (yet) running
pang ->
+ p("start_node -> node ~p not running - create args", [Node]),
[Name, Host] = node_to_name_and_host(Node),
Pa = filename:dirname(code:which(?MODULE)),
- Args = " -pa " ++ Pa ++
+ Args0 = " -pa " ++ Pa ++
" -s " ++ atom_to_list(megaco_test_sys_monitor) ++ " start" ++
" -s global sync",
- p("try start node ~p", [Node]),
- case slave:start_link(Host, Name, Args) of
- {ok, NewNode} when NewNode =:= Node ->
+ Args = string:tokens(Args0, [$\ ]),
+ p("start_node -> try start node ~p", [Node]),
+ PeerOpts = #{name => Name,
+ host => Host,
+ args => Args},
+ case peer:start(PeerOpts) of
+ {ok, _Peer, NewNode} when NewNode =:= Node ->
p("node ~p started - now set path, cwd and sync", [Node]),
- Path = code:get_path(),
+ Path = code:get_path(),
{ok, Cwd} = file:get_cwd(),
- true = rpc:call(Node, code, set_path, [Path]),
- ok = rpc:call(Node, file, set_cwd, [Cwd]),
- true = rpc:call(Node, code, set_path, [Path]),
- {_, []} = rpc:multicall(global, sync, []),
+ true = rpc:call(Node, code, set_path, [Path]),
+ ok = rpc:call(Node, file, set_cwd, [Cwd]),
+ true = rpc:call(Node, code, set_path, [Path]),
+ {_, []} = rpc:multicall(global, sync, []),
ok;
+ {ok, _Peer, NewNode} ->
+ e("wrong node started: "
+ "~n Expected: ~p"
+ "~n Got: ~p", [Node, NewNode]),
+ stop_node(NewNode),
+ fatal_skip({invalid_node_start, NewNode, Node}, File, Line);
Other ->
e("failed starting node ~p: ~p", [Node, Other]),
- fatal_skip({cannot_start_node, Node, Other}, File, Line)
- end
+ fatal_skip({cannot_start_node, Node, Other}, File, Line)
+ end;
+
+ timeout ->
+ fatal_skip({ping_timeout, Node}, File, Line)
end.
@@ -2379,12 +3099,24 @@ stop_node(Node) ->
end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+timetrap_scale_factor() ->
+ case (catch test_server:timetrap_scale_factor()) of
+ {'EXIT', _} ->
+ 1;
+ N ->
+ N
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f(F, A) ->
lists:flatten(io_lib:format(F, A)).
+e(F) ->
+ e(F, []).
e(F, A) ->
print("ERROR", F, A).
@@ -2470,3 +3202,49 @@ connect(Config, Ref, Opts)
InetBackendOpts = inet_backend_opts(Config),
megaco_tcp:connect(Ref, InetBackendOpts ++ Opts).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% The point of this cludge is to make it possible to specify a
+%% timeout for the ping, since it can actually hang.
+ping(Node) ->
+ ping(Node, infinity).
+
+ping(Node, Timeout)
+ when is_atom(Node) andalso
+ ((is_integer(Timeout) andalso (Timeout > 0)) orelse
+ (Timeout =:= infinity)) ->
+ {Pid, Mon} = erlang:spawn_monitor(fun() -> exit(net_adm:ping(Node)) end),
+ receive
+ {'DOWN', Mon, process, Pid, Info} when (Info =:= pong) orelse
+ (Info =:= pang) ->
+ Info;
+ {'DOWN', Mon, process, Pid, Info} ->
+ e("unexpected ping result: "
+ "~n ~p", [Info]),
+ exit({unexpected_ping_result, Info});
+ {'EXIT', TCPid, {timetrap_timeout, TCTimeout, TCSTack}} ->
+ p("received timetrap timeout (~w ms) from ~p => Kill ping process"
+ "~n TC Stack: ~p", [TCTimeout, TCPid, TCSTack]),
+ kill_and_wait(Pid, Mon, "ping"),
+ timeout
+ after Timeout ->
+ e("unexpected ping timeout"),
+ kill_and_wait(Pid, Mon, "ping"),
+ timeout
+ end.
+
+
+kill_and_wait(Pid, MRef, PStr) ->
+ exit(Pid, kill),
+ %% We do this in case we get some info about 'where'
+ %% the process is hanging...
+ receive
+ {'DOWN', MRef, process, Pid, Info} ->
+ p("~s process terminated (forced) with"
+ "~n ~p", [PStr, Info]),
+ ok
+ after 100 -> % Give it a second...
+ ok
+ end.
+
diff --git a/lib/megaco/test/megaco_test_lib.hrl b/lib/megaco/test/megaco_test_lib.hrl
index 43a1bfd0f8..5f5a26adf9 100644
--- a/lib/megaco/test/megaco_test_lib.hrl
+++ b/lib/megaco/test/megaco_test_lib.hrl
@@ -90,11 +90,14 @@
-define(TRY_TC(TCN, N, V, PRE, CASE, POST),
?LIB:try_tc(TCN, N, V, PRE, CASE, POST)).
+-define(TRY_TC(TCN, N, V, COND, PRE, CASE, POST),
+ ?LIB:try_tc(TCN, N, V, COND, PRE, CASE, POST)).
-define(ACQUIRE_NODES(N, Config),
?LIB:prepare_test_case([init, {stop_app, megaco}],
N, Config, ?FILE, ?LINE)).
+-define(MK_NODES(N), ?LIB:mk_nodes(N)).
-define(START_NODE(Node, Force), ?LIB:start_node(Node, Force, ?FILE, ?LINE)).
-define(START_NODE(Node), ?START_NODE(Node, false)).
-define(START_NODES(Nodes, Force), ?LIB:start_nodes(Nodes, Force, ?FILE, ?LINE)).
@@ -124,12 +127,20 @@
-define(ANNOUNCE_SUITE_INIT(),
io:format(user, "~n*** ~s *** suite ~w init~n~n", [?FTS(), ?MODULE])).
+-define(ANNOUNCE_SUITE_END(),
+ io:format(user, "~n*** ~s *** suite ~w end~n~n", [?FTS(), ?MODULE])).
-define(ANNOUNCE_GROUP_INIT(GR),
io:format(user, "~n*** ~s *** group ~w:~w init~n~n",
[?FTS(), ?MODULE, GR])).
+-define(ANNOUNCE_GROUP_END(GR),
+ io:format(user, "~n*** ~s *** group ~w:~w end~n~n",
+ [?FTS(), ?MODULE, GR])).
-define(ANNOUNCE_CASE_INIT(C),
io:format(user, "~n*** ~s *** case ~w:~w init~n~n",
[?FTS(), ?MODULE, C])).
+-define(ANNOUNCE_CASE_END(C),
+ io:format(user, "~n*** ~s *** case ~w:~w end~n~n",
+ [?FTS(), ?MODULE, C])).
-define(UNIQUE(__PreName__),
list_to_atom(
diff --git a/lib/megaco/test/megaco_timer_SUITE.erl b/lib/megaco/test/megaco_timer_SUITE.erl
index c150dad897..2cdd83481b 100644
--- a/lib/megaco/test/megaco_timer_SUITE.erl
+++ b/lib/megaco/test/megaco_timer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -143,9 +143,6 @@ end_per_group(_GroupName, Config) ->
%% -----
%%
-%% init_per_testcase(multi_user_extreme_load = Case, Config) ->
-%% C = lists:keydelete(tc_timeout, 1, Config),
-%% do_init_per_testcase(Case, [{tc_timeout, min(20)}|C]);
init_per_testcase(Case, Config) ->
do_init_per_testcase(Case, Config).
@@ -183,6 +180,12 @@ simple_init(suite) ->
simple_init(doc) ->
[];
simple_init(Config) when is_list(Config) ->
+ Pre = fun() -> #{} end,
+ Case = fun(_) -> do_simple_init() end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+do_simple_init() ->
put(verbosity, ?TEST_VERBOSITY),
put(tc, si),
put(sname, "TEST"),
@@ -297,6 +300,12 @@ simple_usage(suite) ->
simple_usage(doc) ->
[];
simple_usage(Config) when is_list(Config) ->
+ Pre = fun() -> #{} end,
+ Case = fun(_) -> do_simple_usage() end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Pre, Case, Post).
+
+do_simple_usage() ->
put(verbosity, ?TEST_VERBOSITY),
put(tc, su),
put(sname, "TEST"),
@@ -389,23 +398,34 @@ integer_timer_start_and_expire(suite) ->
integer_timer_start_and_expire(doc) ->
[];
integer_timer_start_and_expire(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(tc, itsae),
- put(sname, "TEST"),
- i("starting"),
-
+ Cond = fun() ->
+ Key = megaco_factor,
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, F}} when (F > 5) ->
+ {skip, ?F("Megaco Factor (~w) > 5", [F])};
+ _ ->
+ ok
+ end
+ end,
+ Pre = fun() -> #{} end,
+ Case = fun(_) -> do_integer_timer_start_and_expire() end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_integer_timer_start_and_expire() ->
Timeout = 5000,
+ i("start timer"),
Ref = tmr_start(Timeout),
+ i("await timer expire"),
receive
- {timeout, Timeout} ->
- ok
+ {timeout, Timeout} ->
+ i("received expected timer expire message"),
+ ok
after Timeout + 500 ->
- tmr_stop(Ref),
- no_timeout()
- end,
-
- i("done", []),
- ok.
+ i("timeout-message timeout"),
+ tmr_stop(Ref),
+ no_timeout()
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -415,9 +435,21 @@ integer_timer_start_and_stop(suite) ->
integer_timer_start_and_stop(doc) ->
[];
integer_timer_start_and_stop(Config) when is_list(Config) ->
- put(verbosity, ?TEST_VERBOSITY),
- put(tc, itsas),
- put(sname, "TEST"),
+ Cond = fun() ->
+ Key = megaco_factor,
+ case lists:keysearch(Key, 1, Config) of
+ {value, {Key, F}} when (F > 5) ->
+ {skip, ?F("Megaco Factor (~w) > 5", [F])};
+ _ ->
+ ok
+ end
+ end,
+ Pre = fun() -> #{} end,
+ Case = fun(_) -> do_integer_timer_start_and_stop() end,
+ Post = fun(_) -> ok end,
+ try_tc(?FUNCTION_NAME, Cond, Pre, Case, Post).
+
+do_integer_timer_start_and_stop() ->
i("starting"),
Timeout = 5000,
@@ -475,6 +507,16 @@ timeout(Pid, Timeout, Tc) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+try_tc(Name, Pre, Case, Post) ->
+ Cond = fun() -> ok end,
+ try_tc(Name, Cond, Pre, Case, Post).
+
+try_tc(Name, Cond, Pre, Case, Post) ->
+ ?TRY_TC(Name, "TEST", ?TEST_VERBOSITY, Cond, Pre, Case, Post).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
unexpected_result(A, B) ->
error({unexpected_result, A, B}).
diff --git a/lib/megaco/test/megaco_trans_SUITE.erl b/lib/megaco/test/megaco_trans_SUITE.erl
index 0fe90a8524..0d98cb3895 100644
--- a/lib/megaco/test/megaco_trans_SUITE.erl
+++ b/lib/megaco/test/megaco_trans_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -381,13 +381,23 @@ multi_ack_timeout(suite) ->
multi_ack_timeout(doc) ->
[];
multi_ack_timeout(Config) when is_list(Config) ->
+ Cond = fun() ->
+ %% Regardless of other criteria,
+ %% if the factor is to high => SKIP
+ case lists:keysearch(megaco_factor, 1, Config) of
+ {value, {megaco_factor, MF}} when (MF >= 10) ->
+ ?SKIP({factor_too_high, MF});
+ {value, _} ->
+ ok;
+ false ->
+ ?SKIP(factor_undefined)
+ end,
+
+ Skippable = [win32, {unix, [darwin, sunos]}],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition)
+ end,
Pre = fun() ->
- %% <CONDITIONAL-SKIP>
- Skippable = [win32, {unix, [darwin, linux, sunos]}],
- Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
MgcNode = make_node_name(mgc),
MgNode = make_node_name(mg),
d("start nodes: "
@@ -396,18 +406,39 @@ multi_ack_timeout(Config) when is_list(Config) ->
[MgcNode, MgNode]),
Nodes = [MgcNode, MgNode],
ok = ?START_NODES(Nodes),
- Nodes
+ Factor = case lists:keysearch(megaco_factor, 1, Config) of
+ {value, {megaco_factor, MF}} ->
+ MF;
+ false ->
+ ?SKIP(factor_undefined)
+ end,
+ MaxCount =
+ if
+ (Factor =:= 1) ->
+ 20;
+ (Factor =:= 2) ->
+ 15;
+ (Factor < 5) ->
+ 10;
+ true ->
+ 5
+ end,
+ #{nodes => Nodes,
+ max_count => MaxCount,
+ ttimeout => ?SECS(10),
+ timeout => ?SECS(60)}
end,
Case = fun do_multi_ack_timeout/1,
- Post = fun(Nodes) ->
+ Post = fun(#{nodes := Nodes}) ->
d("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
- try_tc(multi_ack_timeout, Pre, Case, Post).
+ try_tc(multi_ack_timeout, Cond, Pre, Case, Post).
-do_multi_ack_timeout([MgcNode, MgNode]) ->
-
- MaxCount = 20,
+do_multi_ack_timeout(#{nodes := [MgcNode, MgNode],
+ max_count := MaxCount,
+ ttimeout := TTimeout,
+ timeout := Timeout}) ->
%% Start the MGC and MGs
i("[MGC] start"),
@@ -419,7 +450,7 @@ do_multi_ack_timeout([MgcNode, MgNode]) ->
MgMid = {deviceName, "mg"},
MgConfig = [{auto_ack, true},
{trans_ack, true},
- {trans_timer, 10000},
+ {trans_timer, TTimeout},
{trans_ack_maxcount, MaxCount + 10}],
Mg = ?MG_START(MgNode, MgMid, text, tcp, MgConfig, ?MG_VERBOSITY),
@@ -446,7 +477,7 @@ do_multi_ack_timeout([MgcNode, MgNode]) ->
?MG_NOTIF_RAR(Mg),
d("await the ack(s)"),
- await_ack(Mgc, MaxCount, 60000, ok),
+ await_ack(Mgc, MaxCount, Timeout, ok),
i("wait some time before closing down"),
sleep(5000),
@@ -9537,12 +9568,13 @@ await_ack(User, N, Timeout, Expected)
{ack_received, User, UnExpected} ->
e("await_ack -> received unexpected ack result: ~p"
"~n when"
+ "~n User: ~p"
"~n N: ~p"
"~n Remaining: ~p",
- [UnExpected, N, Timeout - (tim() - T)]),
- exit({unexpected_ack_result, UnExpected, Expected})
+ [UnExpected, User, N, Timeout - (tim() - T)]),
+ exit({unexpected_ack_result, User, UnExpected, Expected})
after Timeout ->
- exit({await_ack_timeout, N})
+ exit({await_ack_timeout, N, User})
end;
await_ack(User, N, infinity, Expected) when N > 0 ->
d("await_ack -> entry with N: ~p", [N]),
@@ -9553,8 +9585,9 @@ await_ack(User, N, infinity, Expected) when N > 0 ->
{ack_received, User, UnExpected} ->
e("await_ack -> unexpected ack result: ~p"
"~n when"
- "~n N: ~p", [UnExpected, N]),
- exit({unexpected_ack_result, UnExpected, Expected})
+ "~n User: ~p"
+ "~n N: ~p", [UnExpected, User, N]),
+ exit({unexpected_ack_result, User, UnExpected, Expected})
end.
@@ -9640,12 +9673,25 @@ mg_start(Pid, Mid, Enc, Transp, Conf, Verb) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-try_tc(TCName, Pre, Case, Post) ->
+try_tc(TCName, Pre, Case, Post) when is_atom(TCName) andalso
+ is_function(Pre, 0) andalso
+ is_function(Case, 1) andalso
+ is_function(Post, 1) ->
try_tc(TCName, "TEST", ?TEST_VERBOSITY, Pre, Case, Post).
+try_tc(TCName, Cond, Pre, Case, Post) when is_atom(TCName) andalso
+ is_function(Cond, 0) andalso
+ is_function(Pre, 0) andalso
+ is_function(Case, 1) andalso
+ is_function(Post, 1) ->
+ try_tc(TCName, "TEST", ?TEST_VERBOSITY, Cond, Pre, Case, Post).
+
try_tc(TCName, Name, Verbosity, Pre, Case, Post) ->
?TRY_TC(TCName, Name, Verbosity, Pre, Case, Post).
+try_tc(TCName, Name, Verbosity, Cond, Pre, Case, Post) ->
+ ?TRY_TC(TCName, Name, Verbosity, Cond, Pre, Case, Post).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index d1fd7c372a..dad5cd8bea 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 4.3
+MEGACO_VSN = 4.4.3
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/Mnesia_chap3.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap3.xmlsrc
index 41c85d97f1..eb25f57787 100644
--- a/lib/mnesia/doc/src/Mnesia_chap3.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap3.xmlsrc
@@ -177,7 +177,7 @@ Transformer =
which identifies the particular record in that table. The
combination of the table name and a key is an arity two tuple
<c>{Tab, Key}</c> called the OID. For more information about
- the relationship beween the record name and the table name, see
+ the relationship between the record name and the table name, see
<seeguide marker="Mnesia_chap4#recordnames_tablenames">Record Names versus Table Names</seeguide>.
</p>
<p>What makes the <c>Mnesia</c> data model an extended relational model
diff --git a/lib/mnesia/doc/src/Mnesia_chap4.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap4.xmlsrc
index fd9bea8323..937caf10f0 100644
--- a/lib/mnesia/doc/src/Mnesia_chap4.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap4.xmlsrc
@@ -520,10 +520,10 @@
<list type="ordered">
<item>It is much more efficient.
</item>
- <item>The funcion
+ <item>The function
<seemfa marker="mnesia#dirty_update_counter/2">dirty_update_counter/2</seemfa>
is performed as an atomic operation although it is not protected
- by a transaction. Therfore no table update is lost if two
+ by a transaction. Therefore no table update is lost if two
processes simultaneously execute the function
<c>dirty_update_counter/2</c>.
</item>
diff --git a/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
index ef5e136446..3ef8d08220 100644
--- a/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
+++ b/lib/mnesia/doc/src/Mnesia_chap7.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2020</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -720,7 +720,7 @@ dets:close(N).</pre>
</item>
<item><c>Source</c> and <c>Target</c> are opaque data used
exclusively by the modules <c>SourceMod</c> and
- <c>TargetMod</c> for initializing the backup medias.
+ <c>TargetMod</c> for initializing the backup media.
</item>
<item><c>Acc</c> is an initial accumulator value.
</item>
diff --git a/lib/mnesia/doc/src/mnesia.xml b/lib/mnesia/doc/src/mnesia.xml
index 9791a57610..8e285d78ce 100644
--- a/lib/mnesia/doc/src/mnesia.xml
+++ b/lib/mnesia/doc/src/mnesia.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -772,7 +772,7 @@ mnesia:change_table_copy_type(person, node(), disc_copies)</code>
table is aborted, unless a majority of the table
replicas are available for the commit. When used on a
fragmented table, all fragments are given the same
- the same majority setting.</p>
+ majority setting.</p>
</item>
<item>
<p><c>{ram_copies, Nodelist}</c>, where
@@ -1153,7 +1153,7 @@ mnesia:create_table(person,
or negative number. However, counters can never become less
than zero. There are two significant differences between
this function and the action of first reading the record,
- performing the arithmetics, and then writing the record:</p>
+ performing the arithmetic, and then writing the record:</p>
<list type="bulleted">
<item>It is much more efficient.
</item>
@@ -2609,6 +2609,7 @@ mnesia:create_table(employee,
</list>
</desc>
</func>
+
<func>
<name name="transaction" arity="1" since=""/>
<name name="transaction" arity="2" clause_i="1" since=""/>
@@ -2674,13 +2675,20 @@ raise(Name, Amount) ->
several processes running on different nodes can concurrently
execute the function <c>raise/2</c> without interfering
with each other.</p>
- <p>Since Mnesia detects deadlocks, a transaction can be
- restarted any number of times. This function attempts a
- restart as specified in <c>Retries</c>. <c>Retries</c> must
- be an integer greater than 0 or the atom <c>infinity</c>.
- Default is <c>infinity</c>.</p>
+ <p>
+ Since Mnesia detects deadlocks, a transaction can be
+ restarted any number of times and therefore the <c>Fun</c> shall not
+ have any side effects such as waiting for specific messages.
+ This function attempts a restart as many times as specified in <c>Retries</c>.
+ <c>Retries</c> must be an integer greater than 0 or the atom <c>infinity</c>,
+ default is <c>infinity</c>.
+ Mnesia uses <c>exit</c> exceptions to signal that a transaction needs to be
+ restarted, thus a <c>Fun</c> must not catch <c>exit</c> exceptions with reason
+ <c>{aborted, term()}</c>.
+ </p>
</desc>
</func>
+
<func>
<name name="transform_table" arity="4" since=""/>
<fsummary>Changes format on all records in table <c>Tab</c>.</fsummary>
@@ -2955,7 +2963,7 @@ raise(Name, Amount) ->
<p><c>-mnesia dump_log_write_threshold Max</c>.
<c>Max</c> is an integer that specifies the maximum
number of writes allowed to the transaction log before
- a new dump of the log is performed. Default is <c>100</c>
+ a new dump of the log is performed. Default is <c>1000</c>
log writes.</p>
</item>
<item>
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 0ce4a959ed..16c844dc4b 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,7 +39,161 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.20.4</title>
+ <section><title>Mnesia 4.21.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved consistency for dirty writes when a table was
+ added with <c>add_table_copy/3</c>.</p>
+ <p>
+ Fixed a problem with sticky write, which could lead to
+ inconsistent data.</p>
+ <p>
+ Own Id: OTP-18412</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.21.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed crash which could happen during startup if too many
+ decisions where sent from remote nodes.</p>
+ <p>
+ Own Id: OTP-18319 Aux Id: ERIERL-875 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.21.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Don't fill the logs if mnesia can't connect to all nodes,
+ due to partitioned network.</p>
+ <p>
+ Own Id: OTP-18288 Aux Id: ERIERL-868 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.21.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed <c>add_table_copy</c> which could leave a table
+ lock if the receiving node went down during the
+ operation.</p>
+ <p>
+ Own Id: OTP-18128 Aux Id: PR-6013 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.21</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Documentation fixes.</p>
+ <p>
+ Own Id: OTP-17930</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Mnesia 4.20.4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Don't fill the logs if mnesia can't connect to all nodes,
+ due to partitioned network.</p>
+ <p>
+ Own Id: OTP-18288 Aux Id: ERIERL-868 </p>
+ </item>
+ <item>
+ <p>
+ Fixed crash which could happen during startup if too many
+ decisions where sent from remote nodes.</p>
+ <p>
+ Own Id: OTP-18319 Aux Id: ERIERL-875 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Mnesia 4.20.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed <c>add_table_copy</c> which could leave a table
+ lock if the receiving node went down during the
+ operation.</p>
+ <p>
+ Own Id: OTP-18128 Aux Id: PR-6013 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.20.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/mnesia/examples/Makefile b/lib/mnesia/examples/Makefile
index 5580f0bdcb..e5eb2de940 100644
--- a/lib/mnesia/examples/Makefile
+++ b/lib/mnesia/examples/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ EBIN = .
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES) *~
diff --git a/lib/mnesia/examples/bench/README b/lib/mnesia/examples/bench/README
index b8209b19b8..52225c5f7d 100644
--- a/lib/mnesia/examples/bench/README
+++ b/lib/mnesia/examples/bench/README
@@ -45,7 +45,7 @@ In order to be able to automatically start remote Erlang nodes,
you need to:
- put the $ERL_TOP/bin directory in your path on all nodes
- - bind IP adresses to hostnames (e.g via DNS or /etc/hosts)
+ - bind IP addresses to hostnames (e.g via DNS or /etc/hosts)
- enable usage of ssh so it does not prompt for password
If you cannot achieve this, it is possible to run the benchmark
@@ -79,11 +79,11 @@ Given some arguments such as
Args = ['YourConfigFile', {statistics_detail, debug}].
-the invokation of
+the invocation of
bench:run(Args).
-is equivivalent with:
+is equivalent with:
SlaveNodes = bench:start_all(Args).
bench:populate(Args).
diff --git a/lib/mnesia/examples/mnesia_tpcb.erl b/lib/mnesia/examples/mnesia_tpcb.erl
index fb39ee321d..6a78d4f1d0 100644
--- a/lib/mnesia/examples/mnesia_tpcb.erl
+++ b/lib/mnesia/examples/mnesia_tpcb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
%% a database system.
%%
%% The definition of the TPC-B states lots of detailed rules and
-%% conditions that must be fullfilled, e.g. how the ACID (atomicity,
+%% conditions that must be fulfilled, e.g. how the ACID (atomicity,
%% consistency, isolation and durability) properties are verified,
%% how the random numbers must be distributed, minimum sizes of
%% the different types of records, minimum duration of the benchmark,
diff --git a/lib/mnesia/include/Makefile b/lib/mnesia/include/Makefile
index 6eed4d716f..1c96482d87 100644
--- a/lib/mnesia/include/Makefile
+++ b/lib/mnesia/include/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2016. All Rights Reserved.
+# Copyright Ericsson AB 1998-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ INCLUDE_FILES =
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/mnesia/src/Makefile b/lib/mnesia/src/Makefile
index dce7a359d3..72aa054fb3 100644
--- a/lib/mnesia/src/Makefile
+++ b/lib/mnesia/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -106,8 +106,8 @@ ERL_COMPILE_FLAGS += \
opt: $(TARGET_FILES)
-debug:
- @${MAKE} TYPE=debug
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl
index 35e2d8dd10..bb5858b3f8 100644
--- a/lib/mnesia/src/mnesia.erl
+++ b/lib/mnesia/src/mnesia.erl
@@ -513,7 +513,7 @@ wrap_trans(State, Fun, Args, Retries, Mod, Kind) ->
%% read lock is only set on the first node
%% Nodes may either be a list of nodes or one node as an atom
%% Mnesia on all Nodes must be connected to each other, but
-%% it is not neccessary that they are up and running.
+%% it is not necessary that they are up and running.
-spec lock(LockItem, LockKind) -> list() | tuple() | no_return() when
LockItem :: {'record', table(), Key::term()} |
{'table', table()} |
diff --git a/lib/mnesia/src/mnesia_backup.erl b/lib/mnesia/src/mnesia_backup.erl
index 719e010c17..2cbf164b9f 100644
--- a/lib/mnesia/src/mnesia_backup.erl
+++ b/lib/mnesia/src/mnesia_backup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
%% write an own module the same interface as mnesia_backup and
%% configure Mnesia so the alternate module performs the actual
%% accesses to the backup media. This means that the user may put
-%% the backup on medias that Mnesia does not know about, possibly
+%% the backup on media that Mnesia does not know about, possibly
%% on hosts where Erlang is not running.
%%
%% The OpaqueData argument is never interpreted by other parts of
diff --git a/lib/mnesia/src/mnesia_bup.erl b/lib/mnesia/src/mnesia_bup.erl
index 4b4be695d2..1fe7f4ae26 100644
--- a/lib/mnesia/src/mnesia_bup.erl
+++ b/lib/mnesia/src/mnesia_bup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -809,7 +809,7 @@ restore_tables(Recs, Header, Schema, Ext, {start, LocalTabs}) ->
restore_tables([], _Header, _Schema, _Ext, State) ->
State.
-%% Creates all neccessary dat files and inserts
+%% Creates all necessary dat files and inserts
%% the table definitions in the schema table
%%
%% Returns a list of local_tab tuples for all local tables
diff --git a/lib/mnesia/src/mnesia_checkpoint.erl b/lib/mnesia/src/mnesia_checkpoint.erl
index c67c740036..fce588444b 100644
--- a/lib/mnesia/src/mnesia_checkpoint.erl
+++ b/lib/mnesia/src/mnesia_checkpoint.erl
@@ -306,7 +306,7 @@ really_retain(Name, Tab) ->
%%
%% {min, MinTabs}
%% Minimize redundancy and only keep checkpoint info together with
-%% one replica, preferrably at the local node. If any node involved
+%% one replica, preferably at the local node. If any node involved
%% the checkpoint goes down, the checkpoint is deactivated.
%%
%% {max, MaxTabs}
@@ -319,7 +319,7 @@ really_retain(Name, Tab) ->
%% {ram_overrides_dump, Tabs}
%% Only applicable for ram_copies. Bool controls which versions of
%% the records that should be included in the checkpoint state.
-%% true means that the latest comitted records in ram (i.e. the
+%% true means that the latest committed records in ram (i.e. the
%% records that the application accesses) should be included
%% in the checkpoint. false means that the records dumped to
%% dat-files (the records that will be loaded at startup) should
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index f19960360f..02d873040b 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -342,7 +342,7 @@ get_network_copy(Tid, Tab, Cs) ->
ok ->
Reason = {dumper,{add_table_copy, Tid}},
Work = #net_load{table = Tab,reason = Reason,cstruct = Cs},
- %% I'll need this cause it's linked trough the subscriber
+ %% I'll need this cause it's linked through the subscriber
%% might be solved by using monitor in subscr instead.
process_flag(trap_exit, true),
Load = load_table_fun(Work),
@@ -375,7 +375,7 @@ get_network_copy(Tid, Tab, Cs) ->
%% no need for sync, since mnesia_controller not started yet
%% schema_trans ->
%% already synced with mnesia_controller since the dumper
-%% is syncronously started from mnesia_controller
+%% is synchronously started from mnesia_controller
create_table(Tab) ->
Cs = val({Tab, cstruct}),
@@ -1019,7 +1019,7 @@ handle_cast(Msg, State) when State#state.schema_is_merged /= true ->
%% This must be done after schema_is_merged otherwise adopt_orphan
%% might trigger a table load from wrong nodes as a result of that we don't
-%% know which tables we can load safly first.
+%% know which tables we can load safely first.
handle_cast({im_running, Node, NewFriends}, State) ->
LocalTabs = mnesia_lib:local_active_tables() -- [schema],
RemoveLocalOnly = fun(Tab) -> not val({Tab, local_content}) end,
@@ -1449,7 +1449,7 @@ orphan_tables([Tab | Tabs], Node, Ns, Local, Remote) ->
case lists:member(Node, DiscCopyHolders) of
_ when BeingCreated == true ->
orphan_tables(Tabs, Node, Ns, Local, Remote);
- _ when Read == node() -> %% Allready loaded
+ _ when Read == node() -> %% Already loaded
orphan_tables(Tabs, Node, Ns, Local, Remote);
true when Active == [] ->
case DiscCopyHolders -- Ns of
@@ -2171,7 +2171,7 @@ load_and_reply(ReplyTo, Worker) ->
spawn_link(SendAndReply).
%% Now it is time to load the table
-%% but first we must check if it still is neccessary
+%% but first we must check if it still is necessary
load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=ReplyTo}) ->
LocalC = val({Tab, local_content}),
AccessMode = val({Tab, access_mode}),
diff --git a/lib/mnesia/src/mnesia_dumper.erl b/lib/mnesia/src/mnesia_dumper.erl
index 1264efeb68..e6b02b501a 100644
--- a/lib/mnesia/src/mnesia_dumper.erl
+++ b/lib/mnesia/src/mnesia_dumper.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -86,7 +86,7 @@ adjust_log_writes(DoCast) ->
false ->
ignore;
true ->
- mnesia_controller:async_dump_log(write_threshold)
+ ?CATCH(mnesia_controller:async_dump_log(write_threshold))
end,
Max = mnesia_monitor:get_env(dump_log_write_threshold),
Left = mnesia_lib:read_counter(trans_log_writes_left),
@@ -526,8 +526,8 @@ disc_delete_table(Tab, Storage) ->
disc_delete_indecies(Tab, Cs, Storage) ->
case storage_semantics(Storage) of
disc_only_copies ->
- Indecies = Cs#cstruct.index,
- mnesia_index:del_transient(Tab, Indecies, Storage);
+ Indices = Cs#cstruct.index,
+ mnesia_index:del_transient(Tab, Indices, Storage);
_ ->
ok
end.
@@ -815,7 +815,7 @@ insert_op(Tid, _, {op, create_table, TabDef}, InPlace, InitBy) ->
ram_copies ->
ignore;
_ ->
- %% Indecies are still created by loader
+ %% Indices are still created by loader
disc_delete_indecies(Tab, Cs, Storage)
%% disc_delete_table(Tab, Storage)
end,
@@ -1433,10 +1433,10 @@ chunk_from_log(eof, _, _, _) ->
%%
%% 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
+%% costly BIF invocations 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
+%% not steal all computation power in the Erlang Emulator and make
%% other processes starve. Hopefully this is a temporary solution.
start_regulator() ->
diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl
index 8f7dd321b0..1b4b55e071 100644
--- a/lib/mnesia/src/mnesia_frag.erl
+++ b/lib/mnesia/src/mnesia_frag.erl
@@ -1,7 +1,7 @@
%%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1103,7 +1103,7 @@ make_add_node(Tab, Node) ->
mnesia:abort({bad_type, Tab, Node}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Delet a node from the node pool of a fragmented table
+%% Delete a node from the node pool of a fragmented table
make_multi_del_node(Tab, Node) ->
verify_multi(Tab),
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index d9f7da8eda..fbfca91421 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -332,7 +332,7 @@ init_disc_index(Tab, disc_only_copies, [{Pos,_Pref} | Tail]) ->
Storage = disc_only_copies,
Key = mnesia_lib:db_first(Storage, Tab),
Recs = mnesia_lib:db_get(Storage, Tab, Key),
- BinSize = size(term_to_binary(Recs)),
+ BinSize = byte_size(term_to_binary(Recs)),
KeysPerChunk = (4000 div BinSize) + 1,
Init = {start, KeysPerChunk},
mnesia_lib:db_fixtable(Storage, Tab, true),
diff --git a/lib/mnesia/src/mnesia_lib.erl b/lib/mnesia/src/mnesia_lib.erl
index 4dce5cefc0..84750835d9 100644
--- a/lib/mnesia/src/mnesia_lib.erl
+++ b/lib/mnesia/src/mnesia_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -568,10 +568,10 @@ set_remote_where_to_read(Tab, Ignore) ->
end,
Available = mnesia_lib:intersect(val({current, db_nodes}), Valid -- Ignore),
DiscOnlyC = val({Tab, disc_only_copies}),
- Prefered = Available -- DiscOnlyC,
+ Preferred = Available -- DiscOnlyC,
if
- Prefered /= [] ->
- set({Tab, where_to_read}, hd(Prefered));
+ Preferred /= [] ->
+ set({Tab, where_to_read}, hd(Preferred));
Available /= [] ->
set({Tab, where_to_read}, hd(Available));
true ->
@@ -936,7 +936,7 @@ error_desc(mnesia_down) -> "A transaction involving objects at some remote "
"node which died while transaction was executing"
"*and* object(s) are no longer available elsewhere"
"in the network";
-error_desc(not_a_db_node) -> "A node which is non existant in "
+error_desc(not_a_db_node) -> "A node which is non existent in "
"the schema was mentioned";
error_desc(bad_type) -> "Bad type on some provided arguments";
error_desc(node_not_running) -> "Node not running";
@@ -950,7 +950,7 @@ error_desc({error, Reason}) ->
error_desc(Reason);
error_desc({aborted, Reason}) ->
error_desc(Reason);
-error_desc(Reason) when is_tuple(Reason), size(Reason) > 0 ->
+error_desc(Reason) when tuple_size(Reason) > 0 ->
setelement(1, Reason, error_desc(element(1, Reason)));
error_desc(Reason) ->
Reason.
diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl
index fc42c9e13a..9c039652bd 100644
--- a/lib/mnesia/src/mnesia_loader.erl
+++ b/lib/mnesia/src/mnesia_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -222,7 +222,6 @@ do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
ok ->
set({Tab, load_node}, Node),
set({Tab, load_reason}, Reason),
- mnesia_controller:i_have_tab(Tab, Cs),
dbg_out("Table ~tp copied from ~p to ~p~n", [Tab, Node, node()]),
{loaded, ok};
Err = {error, _} when element(1, Reason) == dumper ->
@@ -267,7 +266,7 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
end,
%% Check that table still exists
Active = val({Tab, active_replicas}),
- %% Check that we havn't loaded it already
+ %% Check that we haven't loaded it already
case val({Tab,where_to_read}) == node() of
true -> ok;
_ ->
@@ -291,7 +290,11 @@ init_receiver(Node, Tab,Storage,Cs,Reason) ->
{atomic, {error,Result}} ->
fatal("Cannot create table ~tp: ~tp~n",
[[Tab, Storage], Result]);
- {atomic, Result} -> Result;
+ {atomic, ok} ->
+ mnesia_controller:i_have_tab(Tab, Cs),
+ ok;
+ {atomic, Result} ->
+ Result;
{aborted, nomore} -> restart;
{aborted, _Reas} ->
verbose("Receiver failed on ~tp from ~p:~nReason: ~tp~n",
@@ -334,7 +337,7 @@ table_init_fun(SenderPid, Storage) ->
ok
end.
-%% Add_table_copy get's it's own locks.
+%% Add_table_copy gets it's own locks.
start_receiver(Tab,Storage,Cs,SenderPid,TabSize,DetsData,{dumper,{add_table_copy,_}}) ->
Init = table_init_fun(SenderPid, Storage),
case do_init_table(Tab,Storage,Cs,SenderPid,TabSize,DetsData,self(), Init) of
@@ -555,14 +558,17 @@ init_table(Tab, _, Fun, _DetsInfo,_) ->
finish_copy(Storage,Tab,Cs,SenderPid,DatBin,OrigTabRec) ->
TabRef = {Storage, Tab},
- subscr_postprocess(TabRef, Cs#cstruct.record_name),
case handle_last(TabRef, Cs#cstruct.type, DatBin) of
ok ->
- mnesia_index:init_index(Tab, Storage),
- snmpify(Tab, Storage),
+ subscr_postprocess(TabRef, Cs#cstruct.record_name),
%% OrigTabRec must not be the spawned tab-receiver
%% due to old protocol.
SenderPid ! {OrigTabRec, no_more},
+ Ref = monitor(process, SenderPid),
+ %% and all remaining events
+ subscr_receiver(TabRef, Cs#cstruct.record_name, Ref),
+ mnesia_index:init_index(Tab, Storage),
+ snmpify(Tab, Storage),
mnesia_tm:unblock_tab(Tab),
ok;
{error, Reason} ->
@@ -582,22 +588,21 @@ subscr_postprocess(TabRef, RecName) ->
handle_subscr_event(Event, TabRef, RecName)
end, ok, SubscrCache),
ets:delete(SubscrCache)
- end,
- % and all remaining events
- subscr_receiver(TabRef, RecName).
+ end.
-subscr_receiver(TabRef = {_, Tab}, RecName) ->
+subscr_receiver(TabRef = {_, Tab}, RecName, Ref) ->
receive
{mnesia_table_event, {_Op, Val, _Tid}} = Event
when element(1, Val) =:= Tab; element(1, Val) =:= schema ->
handle_subscr_event(Event, TabRef, RecName),
- subscr_receiver(TabRef, RecName);
+ subscr_receiver(TabRef, RecName, Ref);
{'EXIT', Pid, Reason} ->
handle_exit(Pid, Reason),
- subscr_receiver(TabRef, RecName)
- after 0 ->
- ok
+ subscr_receiver(TabRef, RecName, Ref);
+
+ {'DOWN', Ref, process, _, _} ->
+ ok
end.
handle_subscr_event(Event, TabRef = {_, Tab}, RecName) ->
@@ -760,7 +765,7 @@ calc_nokeys(Storage, Tab) ->
%% Calculate #keys per transfer
Key = mnesia_lib:db_first(Storage, Tab),
Recs = mnesia_lib:db_get(Storage, Tab, Key),
- BinSize = size(term_to_binary(Recs)),
+ BinSize = byte_size(term_to_binary(Recs)),
(max_transfer_size() div BinSize) + 1.
send_table(Pid, Tab, RemoteS, Reason) ->
@@ -1014,15 +1019,18 @@ finish_copy(Pid, Tab, Storage, RemoteS, NeedLock) ->
mnesia_checkpoint:tm_add_copy(Tab, RecNode),
DatBin = dat2bin(Tab, ?catch_val({Tab, storage_type}), RemoteS),
Pid ! {self(), {no_more, DatBin}},
- cleanup_tab_copier(Pid, Storage, Tab)
- end,
- receive
- {Pid, no_more} -> % Dont bother about the spurious 'more' message
- no_more;
- {copier_done, Node} ->
- verbose("Tab receiver ~tp crashed (more): ~p~n", [Tab, Node]),
- receiver_died
- end
+ receive
+ {Pid, no_more} -> % Dont bother about the spurious 'more' message
+ %% Sync mnesia_tm (before unsubscribing)
+ mnesia_tm:sync(),
+ cleanup_tab_copier(Pid, Storage, Tab),
+ no_more;
+ {copier_done, Node} ->
+ verbose("Tab receiver ~tp crashed (more): ~p~n", [Tab, Node]),
+ cleanup_tab_copier(Pid, Storage, Tab),
+ receiver_died
+ end
+ end
end,
mnesia:transaction(Trans).
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index 671dea2a14..aa7f94ee9f 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -201,14 +201,14 @@ loop(State) ->
end;
%% If test_set_sticky fails, we send this to all nodes
- %% after aquiring a real write lock on Oid
+ %% after acquiring a real write lock on Oid
{stick, {Tab, _}, N} ->
?ets_insert(mnesia_sticky_locks, {Tab, N}),
loop(State);
%% The caller which sends this message, must have first
- %% aquired a write lock on the entire table
+ %% acquired a write lock on the entire table
{unstick, Tab} ->
?ets_delete(mnesia_sticky_locks, Tab),
loop(State);
@@ -649,7 +649,7 @@ ix_read_res(Tab,IxKey,Pos) ->
%% ********************* end server code ********************
%% The following code executes at the client side of a transactions
-%% Aquire a write lock, but do a read, used by
+%% Acquire a write lock, but do a read, used by
%% mnesia:wread/1
rwlock(Tid, Store, Oid) ->
@@ -712,7 +712,7 @@ check_majority(Tab, HaveNs) ->
ok
end.
-%% aquire a sticky wlock, a sticky lock is a lock
+%% acquire a sticky wlock, a sticky lock is a lock
%% which remains at this node after the termination of the
%% transaction.
@@ -761,12 +761,14 @@ do_sticky_lock(Tid, Store, {Tab, Key} = Oid, Lock) ->
exit({aborted, Reason});
{?MODULE, N, not_stuck} ->
not_stuck(Tid, Store, Tab, Key, Oid, Lock, N),
+ ?ets_insert(Store, {sticky, true}),
dirty_sticky_lock(Tab, Key, [N], Lock);
{mnesia_down, Node} ->
EMsg = {aborted, {node_not_running, Node}},
flush_remaining([N], Node, EMsg);
{?MODULE, N, {stuck_elsewhere, _N2}} ->
stuck_elsewhere(Tid, Store, Tab, Key, Oid, Lock),
+ ?ets_insert(Store, {sticky, true}),
dirty_sticky_lock(Tab, Key, [N], Lock)
end.
@@ -809,11 +811,11 @@ dirty_sticky_lock(Tab, Key, Nodes, Lock) ->
sticky_wlock_table(Tid, Store, Tab) ->
sticky_lock(Tid, Store, {Tab, ?ALL}, write).
-%% aquire a wlock on Oid
+%% acquire a wlock on Oid
%% We store a {Tabname, write, Tid} in all locktables
%% on all nodes containing a copy of Tabname
%% We also store an item {{locks, Tab, Key}, write} in the
-%% local store when we have aquired the lock.
+%% local store when we have acquired the lock.
%%
wlock(Tid, Store, Oid) ->
wlock(Tid, Store, Oid, _CheckMajority = true).
@@ -882,7 +884,7 @@ 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 succeeded cont with the rest
get_wlocks_on_nodes(Tail, Store, Request),
receive_wlocks(Tail, Orig, Store, Oid)
end;
@@ -996,7 +998,7 @@ return_granted_or_nodes(_ , _Nodes) -> granted.
%% locks table on the node where we actually do pick up the object
%% and we also store an item {lock, Oid, read} in our local store
%% so that we can release any locks we hold when we commit.
-%% This function not only aquires a read lock, but also reads the object
+%% This function not only acquires a read lock, but also reads the object
%% Oid's are always {Tab, Key} tuples
rlock(Tid, Store, Oid) ->
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 03411ace41..b1514bfbe6 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@
%% with the same interface as mnesia_backup and configure
%% Mnesia so the alternate module performs the actual accesses
%% to the backup media. This means that the user may put the
-%% backup on medias that Mnesia does not know about possibly on
+%% backup on media that Mnesia does not know about possibly on
%% hosts where Erlang is not running.
%%
%% All these logs have to some extent a common structure.
@@ -93,7 +93,7 @@
%% The log file structure for the mnesia_down log is as follows.
%%
%% After the mnesia log section follows a mnesia_down section
-%% containg lists with yoyo records as single element.
+%% containing lists with yoyo records as single element.
%%
%% +-----------------+
%% | mnesia log head |
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index aee84887dc..dbd4a9c42f 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -136,7 +136,7 @@ unsafe_create_external(Tab, Alias, Mod, Cs) ->
disconnect(Node) ->
cast({disconnect, Node}).
-%% Returns GoodNoodes
+%% Returns GoodNodes
%% Creates a link to each compatible monitor and
%% protocol_version to agreed version upon success
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index 36b4a29fc2..820e142994 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -130,7 +130,7 @@ allow_garb() ->
cast(allow_garb).
-%% The transaction log has either been swiched (latest -> previous) or
+%% The transaction log has either been switched (latest -> previous) or
%% there is nothing to be dumped. This means that the previous
%% transaction log only may contain commit records which refers to
%% transactions noted in the last two of the 'Prev' tables. All other
@@ -428,7 +428,7 @@ check_what_happened([H | T], Aborts, Commits) ->
check_what_happened([], Aborts, Commits) ->
if
Aborts == 0, Commits == 0 -> aborted; % None of the active nodes knows
- Aborts > 0 -> aborted; % Someody has aborted
+ Aborts > 0 -> aborted; % Somebody has aborted
Aborts == 0, Commits > 0 -> committed % All has committed
end.
@@ -674,7 +674,7 @@ handle_call({connect_nodes, Ns}, From, State) ->
erlang:send_after(2, self(), {connect_nodes,Ns,From}),
{noreply, State};
[] ->
- %% No good noodes to connect to!
+ %% No good nodes to connect to!
%% We can't use reply here because this function can be
%% called from handle_info
gen_server:reply(From, {[], AlreadyConnected}),
@@ -1083,7 +1083,7 @@ merge_decisions(Node, D, NewD0) ->
NewD#decision.outcome == aborted ->
%% Interesting! We have already committed,
%% but someone else has aborted. Now we
- %% have a nice little inconcistency. The
+ %% have a nice little inconsistency. The
%% other guy (or some one else) has
%% enforced a recovery decision when
%% max_wait_for_decision was exceeded.
@@ -1096,11 +1096,11 @@ merge_decisions(Node, D, NewD0) ->
OldD#decision{outcome = aborted};
OldD#decision.outcome == aborted ->
- %% aborted overrrides anything
+ %% aborted overrides anything
OldD#decision{outcome = aborted};
NewD#decision.outcome == aborted ->
- %% aborted overrrides anything
+ %% aborted overrides anything
OldD#decision{outcome = aborted};
OldD#decision.outcome == committed,
@@ -1236,7 +1236,7 @@ arrange([To | ToNodes], D, Acc, ForceSend) when is_record(D, decision) ->
arrange([To | ToNodes], {trans_tid, serial, Serial}, Acc, ForceSend) ->
%% Do the lamport thing plus release the others
- %% from uncertainity.
+ %% from uncertainty.
Acc2 = add_decision(To, {trans_tid, serial, Serial}, Acc),
arrange(ToNodes, {trans_tid, serial, Serial}, Acc2, ForceSend);
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index e0f561937e..ed4f7a8784 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -957,13 +957,13 @@ get_ext_types_disc_() ->
[]
end.
-%% Convert attribute name to integer if neccessary
+%% Convert attribute name to integer if necessary
attr_tab_to_pos(_Tab, Pos) when is_integer(Pos) ->
Pos;
attr_tab_to_pos(Tab, Attr) ->
attr_to_pos(Attr, val({Tab, attributes})).
-%% Convert attribute name to integer if neccessary
+%% Convert attribute name to integer if necessary
attr_to_pos({_} = P, _) -> P;
attr_to_pos(Pos, _Attrs) when is_integer(Pos) ->
Pos;
@@ -1024,14 +1024,14 @@ verify_cstruct(#cstruct{} = Cs) ->
expand_index_attrs(#cstruct{index = Ix, attributes = Attrs,
name = Tab} = Cs) ->
- Prefered = prefered_index_types(Cs),
- expand_index_attrs(Ix, Tab, Attrs, Prefered).
+ Preferred = prefered_index_types(Cs),
+ expand_index_attrs(Ix, Tab, Attrs, Preferred).
-expand_index_attrs(Ix, Tab, Attrs, Prefered) ->
+expand_index_attrs(Ix, Tab, Attrs, Preferred) ->
lists:map(fun(P) when is_integer(P); is_atom(P) ->
- {attr_to_pos(P, Attrs), Prefered};
+ {attr_to_pos(P, Attrs), Preferred};
({A} = P) when is_atom(A) ->
- {P, Prefered};
+ {P, Preferred};
({P, Type}) ->
{attr_to_pos(P, Attrs), Type};
(_Other) ->
@@ -1186,7 +1186,7 @@ assert_correct_cstruct(Cs) when is_record(Cs, cstruct) ->
verify(true, mnesia_snmp_hook:check_ustruct(Snmp),
{badarg, Tab, {snmp, Snmp}}),
- CheckProp = fun(Prop) when is_tuple(Prop), size(Prop) >= 1 -> ok;
+ CheckProp = fun(Prop) when tuple_size(Prop) >= 1 -> ok;
(Prop) ->
mnesia:abort({bad_type, Tab,
{user_properties, [Prop]}})
@@ -1352,7 +1352,7 @@ check_active([], _Expl, _Tab) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Function for definining an external backend type
+%% Function for defining an external backend type
add_backend_type(Name, Module) ->
case schema_transaction(fun() -> do_add_backend_type(Name, Module) end) of
@@ -2126,7 +2126,7 @@ make_change_table_majority(Tab, Majority) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-write_table_property(Tab, Prop) when is_tuple(Prop), size(Prop) >= 1 ->
+write_table_property(Tab, Prop) when tuple_size(Prop) >= 1 ->
schema_transaction(fun() -> do_write_table_property(Tab, Prop) end);
write_table_property(Tab, Prop) ->
{aborted, {bad_type, Tab, Prop}}.
@@ -2472,6 +2472,7 @@ prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) ->
{loaded, ok} ->
%% Tables are created by mnesia_loader get_network code
insert_cstruct(Tid, Cs, true),
+ mnesia_controller:i_have_tab(Tab, Cs),
{true, optional};
{not_loaded, ErrReason} ->
Reason = {system_limit, Tab, {Node, ErrReason}},
@@ -2809,7 +2810,7 @@ transform_objs(Fun, Tab, RecName, Key, A, Storage, Type, Acc) ->
transform_obj(Tab, RecName, Key, Fun, [Obj|Rest], NewArity, Type, Ws, Ds) ->
NewObj = Fun(Obj),
if
- size(NewObj) /= NewArity ->
+ tuple_size(NewObj) /= NewArity ->
exit({"Bad arity", Obj, NewObj});
NewObj == Obj ->
transform_obj(Tab, RecName, Key, Fun, Rest, NewArity, Type, Ws, Ds);
@@ -3095,7 +3096,7 @@ ext_real_suffixes(Ext) ->
[M || {_,M} <- Ext])
catch
error:E ->
- verbose("Cant find real ext suffixes (~tp)~n", [E]),
+ verbose("Can't find real ext suffixes (~tp)~n", [E]),
[]
end.
@@ -3104,7 +3105,7 @@ ext_tmp_suffixes(Ext) ->
[M || {_,M} <- Ext])
catch
error:E ->
- verbose("Cant find tmp ext suffixes (~tp)~n", [E]),
+ verbose("Can't find tmp ext suffixes (~tp)~n", [E]),
[]
end.
@@ -3398,8 +3399,7 @@ do_merge_schema(LockTabs0) ->
RemoteRunning = mnesia_lib:intersect(New ++ Old, RemoteRunning1),
if
RemoteRunning /= RemoteRunning1 ->
- mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
- [node(), RemoteRunning1 -- RemoteRunning]),
+ warn_user_connect_failed(RemoteRunning1 -- RemoteRunning),
mnesia:abort({node_not_running, RemoteRunning1 -- RemoteRunning});
true -> ok
end,
@@ -3440,6 +3440,22 @@ do_merge_schema(LockTabs0) ->
not_merged
end.
+warn_user_connect_failed(Missing) ->
+ Tag = {user_warned, do_schema_merge},
+ case ?catch_val(Tag) of
+ {'EXIT', _} ->
+ mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
+ [node(), Missing]),
+ mnesia_lib:set(Tag, 1);
+ N when N rem 2000 =:= 0 -> %% ~10 min
+ mnesia_lib:error("Mnesia on ~p could not connect to node(s) ~p~n",
+ [node(), Missing]),
+ mnesia_lib:set(Tag, N+1);
+ N ->
+ mnesia_lib:set(Tag, N+1)
+ end.
+
+
fetch_cstructs(Node) ->
rpc:call(Node, mnesia_controller, get_remote_cstructs, []).
diff --git a/lib/mnesia/src/mnesia_snmp_hook.erl b/lib/mnesia/src/mnesia_snmp_hook.erl
index 58a20c6051..ff89770eaf 100644
--- a/lib/mnesia/src/mnesia_snmp_hook.erl
+++ b/lib/mnesia/src/mnesia_snmp_hook.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -124,7 +124,7 @@ key_to_oid(Tab, Key, [{key, Types}]) ->
key_to_oid_i(Key, integer) when is_integer(Key) -> [Key];
key_to_oid_i(Key, fix_string) when is_list(Key) -> Key;
key_to_oid_i(Key, string) when is_list(Key) -> [length(Key) | Key];
-key_to_oid_i(Key, Types) -> keys_to_oid(size(Key), Key, [], Types).
+key_to_oid_i(Key, Types) when is_tuple(Key) -> keys_to_oid(tuple_size(Key), Key, [], Types).
keys_to_oid(0, _Key, Oid, _Types) -> Oid;
keys_to_oid(N, Key, Oid, Types) ->
@@ -134,7 +134,7 @@ keys_to_oid(N, Key, Oid, Types) ->
%%--------------------------------------------------
%% The reverse of the above, i.e. snmp oid to mnesia key.
%% This can be lookup up in tree but that might be on a remote node.
-%% It's probably faster to look it up, but use when it migth be remote
+%% It's probably faster to look it up, but use when it might be remote
oid_to_key(Oid, Tab) ->
[{key, Types}] = mnesia_lib:val({Tab,snmp}),
oid_to_key_1(Types, Oid).
@@ -144,7 +144,7 @@ oid_to_key_1(fix_string, Key) -> Key;
oid_to_key_1(string, [_|Key]) -> Key;
oid_to_key_1(Tuple, Oid) ->
try
- List = oid_to_key_2(1, size(Tuple), Tuple, Oid),
+ List = oid_to_key_2(1, tuple_size(Tuple), Tuple, Oid),
list_to_tuple(List)
catch
_:_ -> unknown
@@ -208,7 +208,7 @@ get_next_index(Name, RowIndex) ->
%% Purpose: Get the mnesia key corresponding to the RowIndex.
%% Args: Name is the name of the table (atom)
%% RowIndex is an Oid
-%% Returns: {ok, Key} | undefiend
+%% Returns: {ok, Key} | undefined
%%-----------------------------------------------------------------
get_mnesia_key(Name, RowIndex) ->
Tree = mnesia_lib:val({Name, {index, snmp}}),
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index 21a308cfb6..d0c298e425 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -148,7 +148,7 @@ report_table_event(Tab, Tid, Obj, Op) ->
end
end.
-%% Backwards compatible for the moment when mnesia_tm get's updated!
+%% Backwards compatible for the moment when mnesia_tm gets updated!
report_table_event(Subscr, Tab, Tid, Obj, Op) ->
report_table_event(Subscr, Tab, Tid, Obj, Op, undefined).
@@ -173,7 +173,7 @@ report_table_event({subscribers, S1, S2}, Tab, Tid, Obj, Op, Old) ->
Extended = what(Tab, Tid, Obj, Op, Old),
deliver(S2, Extended);
-%% Backwards compatible for the moment when mnesia_tm get's updated!
+%% Backwards compatible for the moment when mnesia_tm gets updated!
report_table_event({subscribers, Subscr}, Tab, Tid, Obj, Op, Old) ->
report_table_event({subscribers, Subscr, []}, Tab, Tid, Obj, Op, Old).
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index 5a070cf0cd..9827ef97ad 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@
put_activity_id/2,
block_tab/1,
unblock_tab/1,
+ sync/0,
fixtable/3,
new_cr_format/1
]).
@@ -181,7 +182,7 @@ tmpid(Pid) ->
%% Returns a list of participant transaction Tid's
mnesia_down(Node) ->
- %% Syncronously call needed in order to avoid
+ %% Synchronously call needed in order to avoid
%% race with mnesia_tm's coordinator processes
%% that may restart and acquire new locks.
%% mnesia_monitor takes care of the sync
@@ -205,6 +206,17 @@ block_tab(Tab) ->
unblock_tab(Tab) ->
req({unblock_tab, Tab}).
+fixtable(Tab, Lock, Me) ->
+ case req({fixtable, [Tab,Lock,Me]}) of
+ error ->
+ exit({no_exists, Tab});
+ Else ->
+ Else
+ end.
+
+sync() ->
+ req(sync).
+
doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=Sup}=State) ->
receive
{_From, {async_dirty, Tid, Commit, Tab}} ->
@@ -250,25 +262,30 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
[{tid, Tid}, {prot, Protocol}]),
mnesia_checkpoint:tm_enter_pending(Tid, DiscNs, RamNs),
Commit = new_cr_format(Commit0),
- Pid =
- if
- node(Tid#tid.pid) =:= node() ->
- error({internal_error, local_node});
- Protocol =:= asym_trans orelse Protocol =:= sync_asym_trans ->
- Args = [Protocol, tmpid(From), Tid, Commit, DiscNs, RamNs],
- spawn_link(?MODULE, commit_participant, Args);
- true -> %% *_sym_trans
- reply(From, {vote_yes, Tid}),
- nopid
- end,
- P = #participant{tid = Tid,
- pid = Pid,
- commit = Commit,
- disc_nodes = DiscNs,
- ram_nodes = RamNs,
- protocol = Protocol},
- State2 = State#state{participants = gb_trees:insert(Tid,P,Participants)},
- doit_loop(State2);
+ case is_blocked(State#state.blocked_tabs, Commit) of
+ false ->
+ Pid =
+ if
+ node(Tid#tid.pid) =:= node() ->
+ error({internal_error, local_node});
+ Protocol =:= asym_trans orelse Protocol =:= sync_asym_trans ->
+ Args = [Protocol, tmpid(From), Tid, Commit, DiscNs, RamNs],
+ spawn_link(?MODULE, commit_participant, Args);
+ true -> %% *_sym_trans
+ reply(From, {vote_yes, Tid}),
+ nopid
+ end,
+ P = #participant{tid = Tid,
+ pid = Pid,
+ commit = Commit,
+ disc_nodes = DiscNs,
+ ram_nodes = RamNs,
+ protocol = Protocol},
+ State2 = State#state{participants = gb_trees:insert(Tid,P,Participants)},
+ doit_loop(State2);
+ true ->
+ reply(From, {vote_no, Tid, {bad_commit, node()}}, State)
+ end;
{Tid, do_commit} ->
case gb_trees:lookup(Tid, Participants) of
@@ -449,6 +466,9 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
reply(From, ok, State2)
end;
+ {From, sync} ->
+ reply(From, ok, State);
+
{From, {prepare_checkpoint, Cp}} ->
Res = mnesia_checkpoint:tm_prepare(Cp),
case Res of
@@ -478,6 +498,28 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
doit_loop(State)
end.
+is_blocked([], _Commit) ->
+ false;
+is_blocked([Tab|Tabs], #commit{ram_copies=RCs, disc_copies=DCs,
+ disc_only_copies=DOs, ext=Exts} = Commit) ->
+ is_blocked_tab(RCs, Tab) orelse
+ is_blocked_tab(DCs, Tab) orelse
+ is_blocked_tab(DOs, Tab) orelse
+ is_blocked_ext_tab(Exts, Tab) orelse
+ is_blocked(Tabs, Commit).
+
+is_blocked_tab([{{Tab,_},_,_}|_Ops], Tab) -> true;
+is_blocked_tab([_|Ops], Tab) -> is_blocked_tab(Ops, Tab);
+is_blocked_tab([],_) -> false.
+
+is_blocked_ext_tab([], _Tab) ->
+ false;
+is_blocked_ext_tab(Exts, Tab) ->
+ case lists:keyfind(ext_copies, 1, Exts) of
+ false -> false;
+ {_, ExtOps} -> is_blocked_tab([Op || {_, Op} <- ExtOps], Tab)
+ end.
+
do_sync_dirty(From, Tid, Commit, _Tab) ->
?eval_debug_fun({?MODULE, sync_dirty, pre}, [{tid, Tid}]),
Res = do_dirty(Tid, Commit),
@@ -598,7 +640,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 haven't been copied to
ok %% to the new nested trans store.
end
catch _:Reason:Stacktrace ->
@@ -881,7 +923,7 @@ try_again(_) -> no.
%% We can only restart toplevel transactions.
%% If a deadlock situation occurs in a nested transaction
%% The whole thing including all nested transactions need to be
-%% restarted. The stack is thus popped by a consequtive series of
+%% restarted. The stack is thus popped by a consecutive series of
%% exit({aborted, #cyclic{}}) calls
restart(Mod, Tid, Ts, Fun, Args, Factor0, Retries0, Type, Why) ->
@@ -1070,7 +1112,7 @@ 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.
+ %% Preferably, the local node if possible.
ReadNode = val({Tab, where_to_read}),
{WaitFor, FirstRes} = async_send_dirty(Tid, CR, Tab, ReadNode),
@@ -1088,7 +1130,7 @@ dirty(Protocol, Item) ->
%% This is the commit function, The first thing it does,
%% is to find out which nodes that have been participating
%% in this particular transaction, all of the mnesia_locker:lock*
-%% functions insert the names of the nodes where it aquires locks
+%% functions insert the names of the nodes where it acquires locks
%% into the local shadow Store
%% This function exacutes in the context of the user process
t_commit(Type) ->
@@ -1379,7 +1421,7 @@ multi_commit(read_only, _Maj = [], Tid, CR, _Store) ->
multi_commit(sym_trans, _Maj = [], Tid, CR, Store) ->
%% This lightweight commit protocol is used when all
- %% the involved tables are replicated symetrically.
+ %% the involved tables are replicated symmetrically.
%% Their storage types must match on each node.
%%
%% 1 Ask the other involved nodes if they want to commit
@@ -1431,7 +1473,7 @@ multi_commit(sym_trans, _Maj = [], Tid, CR, Store) ->
multi_commit(sync_sym_trans, _Maj = [], Tid, CR, Store) ->
%% This protocol is the same as sym_trans except that it
- %% uses syncronized calls to disk_log and syncronized commits
+ %% uses synchronized calls to disk_log and synchronized commits
%% when several nodes are involved.
{DiscNs, RamNs} = commit_nodes(CR, [], []),
@@ -1754,7 +1796,7 @@ commit_participant(Protocol, Coord, Tid, Bin, C0, DiscNs, _RamNs) ->
do_abort(Tid, Bin) when is_binary(Bin) ->
%% Possible optimization:
- %% If we want we could pass arround a flag
+ %% If we want we could pass around a flag
%% that tells us whether the binary contains
%% schema ops or not. Only if the binary
%% contains schema ops there are meningful
@@ -2326,14 +2368,6 @@ do_stop(#state{coordinators = Coordinators}) ->
mnesia_log:stop(),
exit(shutdown).
-fixtable(Tab, Lock, Me) ->
- case req({fixtable, [Tab,Lock,Me]}) of
- error ->
- exit({no_exists, Tab});
- Else ->
- Else
- end.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% System upgrade
diff --git a/lib/mnesia/test/Makefile b/lib/mnesia/test/Makefile
index b77be46e7a..c3fbad88ca 100644
--- a/lib/mnesia/test/Makefile
+++ b/lib/mnesia/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -91,6 +91,7 @@ RELSYSDIR = $(RELEASE_PATH)/mnesia_test
# FLAGS
# ----------------------------------------------------
#ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -98,7 +99,7 @@ EBIN = .
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
$(TARGET_FILES): $(HRL_FILES)
diff --git a/lib/mnesia/test/mnesia_SUITE.erl b/lib/mnesia/test/mnesia_SUITE.erl
index 5e95e1dce7..123d16023f 100644
--- a/lib/mnesia/test/mnesia_SUITE.erl
+++ b/lib/mnesia/test/mnesia_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
%% Verify that Mnesia really is a distributed real-time DBMS.
%% This is the test suite of the Mnesia DBMS. The test suite
-%% covers many aspects of usage and is indended to be developed
+%% covers many aspects of usage and is intended to be developed
%% incrementally. The test suite is divided into a hierarchy of test
%% suites where the leafs actually implements the test cases.
%% The intention of each test case and sub test suite can be
@@ -162,8 +162,8 @@ clean_up_suite(suite) ->
[];
clean_up_suite(Config) when is_list(Config)->
mnesia:kill(),
- Slaves = mnesia_test_lib:lookup_config(nodenames, Config),
- Nodes = lists:delete(node(), Slaves),
+ NodeNames = mnesia_test_lib:lookup_config(nodenames, Config),
+ Nodes = lists:delete(node(), NodeNames),
rpc:multicall(Nodes, erlang, halt, []),
ok.
diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl
index 4764f9e7c0..e079100a4c 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-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -111,7 +111,7 @@ explicit_abort_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a transaction on one node
{success, [A]} = ?start_activities([Node1]),
- %% store an object in the Tab - first tranaction
+ %% store an object in the Tab - first transaction
?start_transactions([A]),
A ! fun() ->
mnesia:write(Rec1A) % returns ok when successful
@@ -136,7 +136,7 @@ explicit_abort_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a second transactionprocess, after the first failed
{success, [B]} = ?start_activities([Node1]),
- %% check, whether the interupted transaction had no influence on the db
+ %% check, whether the interrupted transaction had no influence on the db
?start_transactions([B]),
B ! fun() ->
?match([Rec1A], mnesia:read({Tab, 1})),
@@ -163,7 +163,7 @@ runtime_error_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a transaction on one node
{success, [A]} = ?start_activities([Node1]),
- %% store an object in the Tab - first tranaction
+ %% store an object in the Tab - first transaction
?start_transactions([A]),
A ! fun() ->
mnesia:write(Rec1A) % returns ok when successful
@@ -188,7 +188,7 @@ runtime_error_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a second transactionprocess, after the first failed
{success, [B]} = ?start_activities([Node1]),
- %% check, whether the interupted transaction had no influence on the db
+ %% check, whether the interrupted transaction had no influence on the db
?start_transactions([B]),
B ! fun() ->
?match([Rec1A], mnesia:read({Tab, 1})),
@@ -215,7 +215,7 @@ kill_self_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a transaction on one node
{success, [A]} = ?start_activities([Node1]),
- %% store an object in the Tab - first tranaction
+ %% store an object in the Tab - first transaction
?start_transactions([A]),
A ! fun() ->
mnesia:write(Rec1A) % returns ok when successful
@@ -244,7 +244,7 @@ kill_self_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a second transactionprocess, after the first failed
{success, [B]} = ?start_activities([Node1]),
- %% check, whether the interupted transaction had no influence on the db
+ %% check, whether the interrupted transaction had no influence on the db
?start_transactions([B]),
B ! fun() ->
?match([Rec1A], mnesia:read({Tab, 1})),
@@ -271,7 +271,7 @@ throw_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a transaction on one node
{success, [A]} = ?start_activities([Node1]),
- %% store an object in the Tab - first tranaction
+ %% store an object in the Tab - first transaction
?start_transactions([A]),
A ! fun() ->
mnesia:write(Rec1A) % returns ok when successful
@@ -297,7 +297,7 @@ throw_in_middle_of_trans(Config) when is_list(Config) ->
%% Start a second transactionprocess, after the first failed
{success, [B]} = ?start_activities([Node1]),
- %% check, whether the interupted transaction had no influence on the db
+ %% check, whether the interrupted transaction had no influence on the db
?start_transactions([B]),
B ! fun() ->
?match([Rec1A], mnesia:read({Tab, 1})),
@@ -542,7 +542,7 @@ start_lock_waiter(BlockOpA, BlockOpB, Config) ->
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("Queues ~p~n",
[[{N,rpc:call(N, mnesia, system_info, [lock_queue])} || N <- Nodes]]),
KillNode = node(B),
@@ -743,7 +743,7 @@ start_restart_check(RestartOp, ReplicaNeed, Config) ->
Wait(Wait),
A ! go_ahead,
- %% the sticky write doesnt work on remote nodes !!!
+ %% the sticky write doesn't work on remote nodes !!!
ExpectedMsg =
case RestartOp of
sw when ReplicaNeed == two ->
@@ -765,7 +765,7 @@ start_restart_check(RestartOp, ReplicaNeed, Config) ->
%% the expected result depends on the transaction of
- %% fun A - when that doesnt change the object in the
+ %% 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
diff --git a/lib/mnesia/test/mnesia_config_backup.erl b/lib/mnesia/test/mnesia_config_backup.erl
index 239101ca92..a39e41f63d 100644
--- a/lib/mnesia/test/mnesia_config_backup.erl
+++ b/lib/mnesia/test/mnesia_config_backup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@
%% write an own module the same interface as mnesia_backup and
%% configure Mnesia so the alternate module performs the actual
%% accesses to the backup media. This means that the user may put
-%% the backup on medias that Mnesia does not know about, possibly
+%% the backup on media that Mnesia does not know about, possibly
%% on hosts where Erlang is not running.
%%
%% The OpaqueData argument is never interpreted by other parts of
diff --git a/lib/mnesia/test/mnesia_config_test.erl b/lib/mnesia/test/mnesia_config_test.erl
index 7f584e35f9..4ba560e25d 100644
--- a/lib/mnesia/test/mnesia_config_test.erl
+++ b/lib/mnesia/test/mnesia_config_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -106,7 +106,7 @@ all() ->
dump_log_load_regulation, {group, dump_log_thresholds},
dump_log_update_in_place,
event_module, backend_plugin_registration,
- inconsistent_database, max_wait_for_decision,
+ inconsistent_database, %% max_wait_for_decision,
send_compressed, app_test, {group, schema_config},
unknown_config].
@@ -937,7 +937,7 @@ start_first_one_disc_less_then_two_more_disc_less(Config) when is_list(Config) -
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
schema_location_and_extra_db_nodes_combinations(doc)->
- ["Test schema loaction and extra_db_nodes combinations."];
+ ["Test schema location and extra_db_nodes combinations."];
schema_location_and_extra_db_nodes_combinations(suite) -> [];
schema_location_and_extra_db_nodes_combinations(Config) when is_list(Config) ->
[N1, N2] = Nodes = ?init(2, Config),
diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl
index 46bafaf65c..73093b9227 100644
--- a/lib/mnesia/test/mnesia_consistency_test.erl
+++ b/lib/mnesia/test/mnesia_consistency_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
all/0, groups/0]).
-export([consistency_after_change_table_copy_type/1,
- consistency_after_rename_of_node/1,
consistency_after_restart_1_ram/1,
consistency_after_restart_1_disc/1,
consistency_after_restart_1_disc_only/1,
@@ -110,9 +109,8 @@ all() ->
{group, consistency_after_del_replica},
{group, consistency_after_move_replica},
{group, consistency_after_transform_table},
- consistency_after_change_table_copy_type,
+ %% consistency_after_change_table_copy_type,
{group, consistency_after_restore},
- consistency_after_rename_of_node,
{group, checkpoint_retainer_consistency},
{group, backup_consistency}].
@@ -341,7 +339,7 @@ receive_messages(ListOfMsgs) ->
?verbose("I (~p) got msg ~p from ~p ~n", [self(),Msg, Pid]),
[{Pid, Msg} | receive_messages(ListOfMsgs -- [Msg])]
end;
- Else -> ?warning("Recevied unexpected Msg~n ~p ~n", [Else])
+ Else -> ?warning("Received unexpected Msg~n ~p ~n", [Else])
after timer:minutes(3) ->
?error("Timeout in receive msgs while waiting for ~p~n",
[ListOfMsgs])
@@ -381,7 +379,7 @@ consistency_after_restart(ReplicaType, NodeConfig, Config) ->
TpcbConfig = tpcb_config(ReplicaType, NodeConfig, Nodes, [Node1]),
mnesia_tpcb:init(TpcbConfig),
A ! fun () -> mnesia_tpcb:run(TpcbConfig) end,
- timer:sleep(timer:seconds(10)),
+ timer:sleep(timer:seconds(3)),
mnesia_test_lib:kill_mnesia([Node1]),
%% Start and wait for tables to be loaded on all nodes
timer:sleep(timer:seconds(3)),
@@ -408,7 +406,7 @@ consistency_after_dump_tables(ReplicaType, NodeConfig, Config) ->
TpcbConfig = tpcb_config(ReplicaType, NodeConfig, Nodes, []),
mnesia_tpcb:init(TpcbConfig),
A ! fun() -> mnesia_tpcb:run(TpcbConfig) end,
- timer:sleep(timer:seconds(10)),
+ timer:sleep(timer:seconds(3)),
?match({atomic, ok}, rpc:call(Node1, mnesia, dump_tables,
[[branch, teller, account, history]])),
mnesia_tpcb:stop(),
@@ -459,7 +457,7 @@ consistency_after_add_replica(ReplicaType, NodeConfig, Config) ->
TpcbConfig = tpcb_config(ReplicaType, NodeConfig, Nodes, []),
mnesia_tpcb:init(TpcbConfig),
A ! fun () -> mnesia_tpcb:run(TpcbConfig) end,
- timer:sleep(timer:seconds(10)),
+ timer:sleep(timer:seconds(2)),
?match({atomic, ok}, mnesia:add_table_copy(account, AddNode, ReplicaType)),
mnesia_tpcb:stop(),
?match(ok, mnesia_tpcb:verify_tabs()),
@@ -501,7 +499,7 @@ consistency_after_del_replica(ReplicaType, NodeConfig, Config) ->
TpcbConfig = tpcb_config(ReplicaType, NodeConfig, Nodes, []),
mnesia_tpcb:init(TpcbConfig),
A ! fun () -> mnesia_tpcb:run(TpcbConfig) end,
- timer:sleep(timer:seconds(10)),
+ timer:sleep(timer:seconds(3)),
?match({atomic, ok}, mnesia:del_table_copy(account, Node2)),
mnesia_tpcb:stop(),
?match(ok, mnesia_tpcb:verify_tabs()),
@@ -543,7 +541,7 @@ consistency_after_move_replica(ReplicaType, NodeConfig, Config) ->
TpcbConfig = tpcb_config(ReplicaType, NodeConfig, Nodes -- [Node2], []),
mnesia_tpcb:init(TpcbConfig),
A ! fun () -> mnesia_tpcb:run(TpcbConfig) end,
- timer:sleep(timer:seconds(10)),
+ timer:sleep(timer:seconds(3)),
?match({atomic, ok}, mnesia:move_table_copy(account, Node1, Node2)),
?log("First move completed from node ~p to ~p ~n", [Node1, Node2]),
?match({atomic, ok}, mnesia:move_table_copy(account, Node2, Node1)),
@@ -585,8 +583,8 @@ consistency_after_transform_table(Type, Config) ->
[k,a,n]) || Tab <- Tabs]),
[?match([k,a,n], mnesia:table_info(Tab, attributes)) || Tab <- Tabs],
- Filter = fun(Tab) -> mnesia:foldl(fun(A, Acc) when size(A) == 3 -> [A|Acc];
- (A, Acc) when size(A) == 4 -> Acc
+ Filter = fun(Tab) -> mnesia:foldl(fun(A, Acc) when tuple_size(A) == 3 -> [A|Acc];
+ (A, Acc) when tuple_size(A) == 4 -> Acc
end, [], Tab)
end,
@@ -638,7 +636,7 @@ consistency_after_fallback_3_disc_only(Config) when is_list(Config) ->
consistency_after_fallback(ReplicaType, NodeConfig, Config) ->
put(mnesia_test_verbose, true),
%%?verbose("Starting consistency_after_fallback2 at ~p~n", [self()]),
- Delay = 5,
+ Delay = 3,
Nodes = ?acquire_nodes(NodeConfig, [{tc_timeout, timer:minutes(10)} | Config]),
Node1 = hd(Nodes),
%%?verbose("Mnesia info: ~p~n", [mnesia:info()]),
@@ -821,11 +819,6 @@ restore_verify_tabs([Tab | R]) ->
restore_verify_tabs([]) ->
ok.
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-consistency_after_rename_of_node(doc) ->
- ["Skipped because it is an unimportant case."].
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -867,7 +860,7 @@ updates_during_checkpoint_activation_3_disc_only(Config) when is_list(Config) ->
updates_during_checkpoint_activation(ReplicaType,NodeConfig,Config) ->
%%?verbose("updates_during_checkpoint_activation2 at ~p~n", [self()]),
- Delay = 5,
+ Delay = 2,
Nodes = ?acquire_nodes(NodeConfig, Config),
Node1 = hd(Nodes),
%%?verbose("Mnesia info: ~p~n", [mnesia:info()]),
@@ -922,7 +915,7 @@ updates_during_checkpoint_iteration_2_disc_only(Config) when is_list(Config) ->
updates_during_checkpoint_iteration(ReplicaType,NodeConfig,Config) ->
%?verbose("updates_during_checkpoint_iteration2 at ~p~n", [self()]),
- Delay = 5,
+ Delay = 2,
Nodes = ?acquire_nodes(NodeConfig, Config),
Node1 = hd(Nodes),
%?verbose("Mnesia info: ~p~n", [mnesia:info()]),
diff --git a/lib/mnesia/test/mnesia_dbn_meters.erl b/lib/mnesia/test/mnesia_dbn_meters.erl
index 407d7c65b8..d66da2fb6b 100644
--- a/lib/mnesia/test/mnesia_dbn_meters.erl
+++ b/lib/mnesia/test/mnesia_dbn_meters.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,12 +64,12 @@ start(Config,Nodes,Meters) ->
config(one_ram_only,[Single|_]) ->
[{ram_copies,[Single]}];
-config(ram_and_ram,[Master|[Slave|_]]) ->
- [{ram_copies,[Master,Slave]}];
+config(ram_and_ram,[N1,N2|_]) ->
+ [{ram_copies,[N1,N2]}];
config(one_disc_only,[Single|_]) ->
[{disc_copies,[Single]}];
-config(disc_and_disc,[Master|[Slave|_]]) ->
- [{disc_copies,[Master,Slave]}];
+config(disc_and_disc,[N1,N2|_]) ->
+ [{disc_copies,[N1,N2]}];
config(Config,Nodes) ->
io:format("<ERROR> Config ~p not supported or too few nodes ~p given~n",[Config,Nodes]).
diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl
index e883931e36..e684faf7b0 100644
--- a/lib/mnesia/test/mnesia_dirty_access_test.erl
+++ b/lib/mnesia/test/mnesia_dirty_access_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -844,12 +844,12 @@ del_table(CallFrom, DelNode, [Node1, Node2, Node3]) ->
Pid3 = spawn_link(Node3, ?MODULE, update_trans, [Tab, 3, 0]),
- dbg:tracer(process, {fun(Msg,_) -> tracer(Msg) end, void}),
+ %% dbg:tracer(process, {fun(Msg,_) -> tracer(Msg) end, void}),
%% dbg:n(Node2),
%% dbg:n(Node3),
%% dbg:tp('_', []),
%% dbg:tpl(dets, [timestamp]),
- dbg:p(Pid1, [m,c,timestamp]),
+ %% dbg:p(Pid1, [m,c,timestamp]),
?match({atomic, ok},
rpc:call(CallFrom, mnesia, del_table_copy, [Tab, DelNode])),
@@ -872,17 +872,6 @@ del_table(CallFrom, DelNode, [Node1, Node2, Node3]) ->
verify_oids(Tab, Node1, Node2, Node3, R1, R2, R3),
?verify_mnesia([Node1, Node2, Node3], []).
-tracer({trace_ts, _, send, Msg, Pid, {_,S,Ms}}) ->
- io:format("~p:~p ~p >> ~w ~n",[S,Ms,Pid,Msg]);
-tracer({trace_ts, _, 'receive', Msg, {_,S,Ms}}) ->
- io:format("~p:~p << ~w ~n",[S,Ms,Msg]);
-
-
-tracer(Msg) ->
- io:format("UMsg ~p ~n",[Msg]),
- ok.
-
-
add_table_copy_1(suite) -> [];
add_table_copy_1(Config) when is_list(Config) ->
@@ -929,6 +918,22 @@ add_table(CallFrom, AddNode, [Node1, Node2, Node3], Def) ->
verify_oids(Tab, Node1, Node2, Node3, R1, R2, R3),
?verify_mnesia([Node1, Node2, Node3], []).
+
+tracer({trace_ts, From, send, Msg, To, {_,S,Ms}}) ->
+ io:format("~p:~p ~p(~p) >>~p ~w ~n",[S,Ms,From,node(From),To,Msg]);
+tracer({trace_ts, Pid, 'receive', Msg, {_,S,Ms}}) ->
+ io:format("~p:~p ~p(~p) << ~w ~n",[S,Ms,Pid,node(Pid),Msg]);
+
+tracer({trace_ts, Pid, call, MFA, ST, {_,S,Ms}}) ->
+ io:format("~p:~p ~p(~p) ~w ~w ~n",[S,Ms,Pid,node(Pid),MFA, ST]);
+tracer({trace_ts, Pid, return_from, MFA, Ret, {_,S,Ms}}) ->
+ io:format("~p:~p ~p(~p) ~w => ~w ~n",[S,Ms,Pid,node(Pid),MFA,Ret]);
+
+tracer(Msg) ->
+ io:format("UMsg ~p ~n",[Msg]),
+ ok.
+
+
move_table_copy_1(suite) -> [];
move_table_copy_1(Config) when is_list(Config) ->
[Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config),
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl
index ccbfdc9738..986d0efcb5 100644
--- a/lib/mnesia/test/mnesia_durability_test.erl
+++ b/lib/mnesia/test/mnesia_durability_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -503,7 +503,7 @@ load_when_down_from_all_other_replica_nodes(Config) when is_list(Config) ->
?match([], mnesia_test_lib:kill_mnesia([N2])),
?match({atomic,ok},rpc:call(N3,mnesia,transaction,[Write_one,[33,33]])),
?match([], mnesia_test_lib:kill_mnesia([N3])),
- ?verbose("Mnesia stoped on all three nodes.~n",[]),
+ ?verbose("Mnesia stopped on all three nodes.~n",[]),
%%Start Mnesia on N3; wait for 'test_rec' table to load
?match(ok, rpc:call(N3, mnesia, start, [])),
@@ -528,7 +528,7 @@ load_when_down_from_all_other_replica_nodes(Config) when is_list(Config) ->
late_load_transforms_into_disc_load(doc) ->
["Difficult case that needs instrumentation of Mnesia.",
"A table is force loaded, and Mnesia decides to load it from another ",
- "Mnesia node because it is avaliable there. The other Mnesia node then ",
+ "Mnesia node because it is available there. The other Mnesia node then ",
"dies in mid copy which shall make the first Mnesia node to really ",
"force load from disc.",
"Check this by starting N1 and N2 and replicating a table between ",
@@ -1028,7 +1028,7 @@ master_nodes(Config) when is_list(Config) ->
?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 2000])),
%% Test 6: Force load on table that couldn't be loaded due to master
- %% table setttings, loads other active replicas i.e. from C
+ %% table settings, loads other active replicas i.e. from C
?match(yes, rpc:call(A, mnesia, force_load_table, [Tab])),
?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])),
@@ -1041,7 +1041,7 @@ master_nodes(Config) when is_list(Config) ->
?match([{Tab, 1, update_2}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])),
%% Test 7: Master [B] and B is down the table should not be loaded,
- %% force_load when there are no active replicas availible
+ %% force_load when there are no active replicas available
%% should generate a load of a local table
?match(ok, rpc:call(A, mnesia, set_master_nodes, [Tab, [B]])),
@@ -1138,7 +1138,7 @@ master_on_non_local_tables(Config) when is_list(Config) ->
remote_force_load_with_local_master_node(doc) ->
["Force load a table on a remote node while the ",
"local node is down. Start the local node and ",
- "verfify that the tables is loaded from disc locally "
+ "verify that the tables is loaded from disc locally "
"if the local node has itself as master node and ",
"the remote node has both the local and remote node ",
"as master nodes"];
@@ -1345,13 +1345,13 @@ dump_ram_copies(Config) when is_list(Config) ->
%% start Mnesia only on node 3
?verbose("starting mnesia on Node3~n",[]),
- %% test_lib:mnesia_start doesnt work, because it waits
+ %% test_lib:mnesia_start doesn't work, because it waits
%% for the schema on all nodes ... ???
?match(ok,rpc:call(Node3,mnesia,start,[]) ),
?match(ok,rpc:call(Node3,mnesia,wait_for_tables,
[[Tab],timer:seconds(30)] ) ),
- %% node3 shall have the conents of the dump
+ %% node3 shall have the contents of the dump
cross_check_tables([C],Tab,{[{Tab,1,4711}],[{Tab,2,42}],[{Tab,3,256}]}),
%% start Mnesia on the other 2 nodes, too
@@ -1569,7 +1569,7 @@ receive_messages(ListOfMsgs) ->
[{Pid, Msg} | receive_messages(ListOfMsgs -- [Msg])]
end;
- Else -> ?warning("Recevied unexpected Msg~n ~p ~n", [Else])
+ Else -> ?warning("Received unexpected Msg~n ~p ~n", [Else])
after timer:seconds(40) ->
?error("Timeout in receive msgs while waiting for ~p~n",
[ListOfMsgs])
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 1c84774e6f..3a697ba16d 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@
-export([system_info/1, table_info/1, error_description/1,
db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1,
checkpoint/1, table_lifecycle/1, storage_options/1,
- add_copy_conflict/1, add_copy_when_going_down/1,
+ add_copy_conflict/1, add_copy_when_going_down/1, add_copy_when_dst_going_down/1,
add_copy_with_down/1,
replica_management/1, clear_table_during_load/1,
schema_availability/1, local_content/1,
@@ -66,7 +66,8 @@ all() ->
db_node_lifecycle, evil_delete_db_node, start_and_stop,
checkpoint, table_lifecycle, storage_options,
add_copy_conflict,
- add_copy_when_going_down, add_copy_with_down, replica_management,
+ add_copy_when_going_down, add_copy_when_dst_going_down, add_copy_with_down,
+ replica_management,
clear_table_during_load,
schema_availability, local_content,
{group, table_access_modifications}, replica_location,
@@ -696,7 +697,7 @@ verify_ll_queue(N) ->
?match(granted,mnesia_controller:block_controller()),
case mnesia_controller:get_info(1000) of
{info,{state,_,true,[],_Loader,[],[],[],_,_,_,_,_,_}} ->
- %% Very slow SMP machines havn't loaded it yet..
+ %% Very slow SMP machines haven't loaded it yet..
mnesia_controller:unblock_controller(),
timer:sleep(10),
verify_ll_queue(N-1);
@@ -735,6 +736,54 @@ add_copy_when_going_down(Config) ->
?match_receive({test,{aborted,_}}),
?verify_mnesia([Node2], []).
+add_copy_when_dst_going_down(suite) -> [];
+add_copy_when_dst_going_down(doc) ->
+ ["Table copy destination node goes down. Verify that the issue fixed in erlang/otp#6013 doesn't happen again, whitebox testing."];
+add_copy_when_dst_going_down(Config) ->
+ [Node1, Node2] = ?acquire_nodes(2, Config),
+ ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node1]}])),
+ lists:foreach(fun(I) ->
+ ok = mnesia:sync_dirty(fun() -> mnesia:write({a, I, I}) end)
+ end,
+ lists:seq(1, 100000)),
+ ?match({ok, _}, mnesia:change_config(extra_db_nodes, [Node2])),
+
+ %% Start table copy
+ Tester = self(),
+ spawn_link(fun() ->
+ mnesia:add_table_copy(a, Node2, ram_copies),
+ Tester ! add_table_copy_finished
+ end),
+ timer:sleep(10), % Wait for `mnesia_loader:send_more/6` has started
+
+ %% Grab a write lock
+ spawn_link(fun() ->
+ Fun = fun() ->
+ ok = mnesia:write_lock_table(a),
+ Tester ! {write_lock_acquired, self()},
+ receive node2_mnesia_killed -> ok
+ end,
+ Tester ! write_lock_released,
+ ok
+ end,
+ mnesia:transaction(Fun)
+ end),
+ receive {write_lock_acquired, Locker} -> ok
+ end,
+ timer:sleep(200), % Wait for `mnesia_loader:send_more/6` has finished
+ ?match([], mnesia_test_lib:kill_mnesia([Node2])),
+ Locker ! node2_mnesia_killed,
+
+ receive write_lock_released -> ok
+ end,
+ receive add_table_copy_finished -> ok
+ end,
+ timer:sleep(1000), % Wait for `mnesia_loader:finish_copy/5` has acquired the read lock
+
+ %% Grab a write lock
+ ?match({atomic, ok}, mnesia:transaction(fun() -> mnesia:write_lock_table(a) end, 10)),
+ ?verify_mnesia([Node1], []).
+
add_copy_with_down(suite) -> [];
add_copy_with_down(Config) ->
%% Allow add_table_copy() with ram_copies even all other replicas are down
@@ -1295,7 +1344,7 @@ offline_set_master_nodes(Config) when is_list(Config) ->
?verify_mnesia(Nodes, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Syncronize table with log or disc
+%% Synchronize table with log or disc
%%
%% Dump ram tables on disc
@@ -2091,7 +2140,7 @@ test_ext_sub(Tab1, Tab2, Tab3) ->
subscribe_standard(doc) ->
- ["Tests system events and the orignal table events"];
+ ["Tests system events and the original table events"];
subscribe_standard(suite) -> [];
subscribe_standard(Config) when is_list(Config)->
[N1, N2]=?acquire_nodes(2, Config),
diff --git a/lib/mnesia/test/mnesia_examples_test.erl b/lib/mnesia/test/mnesia_examples_test.erl
index 3bbb6e4d77..53062ca3eb 100644
--- a/lib/mnesia/test/mnesia_examples_test.erl
+++ b/lib/mnesia/test/mnesia_examples_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,7 +44,8 @@ end_per_testcase(Func, Conf) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
- [bup, company, meter, {group, tpcb}].
+ [bup, %% company,
+ meter, {group, tpcb}].
groups() ->
[{tpcb, [],
diff --git a/lib/mnesia/test/mnesia_frag_test.erl b/lib/mnesia/test/mnesia_frag_test.erl
index 7b37fcb684..c390ae3508 100644
--- a/lib/mnesia/test/mnesia_frag_test.erl
+++ b/lib/mnesia/test/mnesia_frag_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -185,7 +185,7 @@ nice_multi(Config) when is_list(Config) ->
?match([{Node2, 2}, {Node1, 2}], frag_dist(Tab)),
%% And connect another table to it, via a foreign key
- TabF = frag_slave,
+ TabF = frag_node,
PropsF = [{foreign_key, {Tab, foreign_id}}],
DefF = [{frag_properties, PropsF},
{attributes, [id, foreign_id]}],
@@ -322,7 +322,7 @@ nice_access(Config) when is_list(Config) ->
[frag_write(Tab, {Tab, Id, Id}) || Id <- lists:seq(1, 400)],
%% And connect another table to it, via a foreign key
- TabF = frag_access_slave,
+ TabF = frag_access_extra,
PropsF = [{foreign_key, {Tab, val}}],
DefF = [{frag_properties, PropsF},
{index, [val]}],
diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl
index 601f46e45f..759735a7ea 100644
--- a/lib/mnesia/test/mnesia_isolation_test.erl
+++ b/lib/mnesia/test/mnesia_isolation_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -608,7 +608,7 @@ sticky_sync(Config) when is_list(Config) ->
%% In first transaction we initialise {dc, I} record with value 0
First = fun() ->
%% Do a lot of writes into ram copies table
- %% which on the Slave in do_commit will be
+ %% which on the N2 in do_commit will be
%% processed first
lists:foreach(fun(J) -> ok = mnesia:write(ec, {ec, J, 0}, write) end,
lists:seq(1, 750)),
@@ -630,11 +630,6 @@ sticky_sync(Config) when is_list(Config) ->
%% Fill 1000 dc records. At the end all dc records should have value 1.
{Time, ok} = timer:tc(fun() -> lists:foreach(TestFun, lists:seq(1,200)) end),
- io:format("200 trans done in ~p ~n",[Time div (1000000)]),
- case (Time div (1000000)) < 20 of
- true -> lists:foreach(TestFun, lists:seq(201,1000));
- false -> ignore %% Some virtual test machines are really slow..
- end,
io:format("Written, check content~n",[]),
All = fun() -> mnesia:select(dc, [ {{dc, '_', 0}, [] ,['$_']} ]) end,
?match({atomic, []}, rpc:call(N1, mnesia, sync_transaction, [All])),
@@ -967,7 +962,7 @@ snmp_open_table(Config) when is_list(Config) ->
A ! end_trans, %% Kill A, locks should be released
?match_receive({A,{atomic,end_trans}}),
- %% Locks released! op should be exec. Can take a while (thats the timeout)
+ %% Locks released! op should be exec. Can take a while (that's the timeout)
receive
Msg -> ?match({Pid, {atomic, ok}}, Msg)
after
@@ -999,7 +994,7 @@ snmp_close_table(Config) when is_list(Config) ->
A ! end_trans, %% Kill A, locks should be released
?match_receive({A,{atomic,end_trans}}),
- %% Locks released! op should be exec. Can take a while (thats the timeout)
+ %% Locks released! op should be exec. Can take a while (that's the timeout)
receive
Msg -> ?match({Pid, {atomic, ok}}, Msg)
after
@@ -1729,7 +1724,7 @@ write_shadows(Config) when is_list(Config) ->
?match({atomic, ok}, mnesia:transaction(Fun1)),
Fun2 = fun() ->
- %% write shadow old write - is the confirmed value visable
+ %% write shadow old write - is the confirmed value visible
%% in the shadow ?
?match([RecA1], mnesia:read({Tab, a})),
?match([RecA1], mnesia:wread({Tab, a})),
@@ -1738,14 +1733,14 @@ write_shadows(Config) when is_list(Config) ->
?match([RecA1], mnesia:index_match_object(PatA1, ValPos)),
?match([RecA1], mnesia:index_read(Tab, 1, ValPos)),
- %% write shadow new write - is a new value visable instead
+ %% write shadow new write - is a new value visible instead
%% of the old value ?
?match(ok, mnesia:write(RecA2)),
?match([RecA2], mnesia:read({Tab, a})),
?match([RecA2], mnesia:wread({Tab, a})),
?match([], mnesia:match_object(PatA1)), %% delete shadow old but not new write
- ?match([RecA2], mnesia:match_object(PatA2)), %% is the new value visable
+ ?match([RecA2], mnesia:match_object(PatA2)), %% is the new value visible
?match([a], mnesia:all_keys(Tab)),
?match([RecA2], mnesia:index_match_object(PatA2, ValPos)),
@@ -1798,7 +1793,7 @@ delete_shadows(Config) when is_list(Config) ->
?match([], mnesia:index_match_object(PatA1, ValPos)),
?match([], mnesia:index_read(Tab, 1, ValPos)),
- %% delete shadow old but not new write - is the new value visable
+ %% delete shadow old but not new write - is the new value visible
%% when the old one was deleted ?
?match(ok, mnesia:write(RecA2)),
@@ -1883,7 +1878,7 @@ write_delete_shadows_bag(Config) when is_list(Config) ->
?match([], mnesia:index_match_object(PatA1, ValPos)),
?match([], mnesia:index_read(Tab, 1, ValPos)),
- %% delete shadow old but not new write - are both new value visable
+ %% delete shadow old but not new write - are both new value visible
%% when the old one was deleted ?
?match(ok, mnesia:write(RecA2)),
?match(ok, mnesia:write(RecA3)),
@@ -2143,7 +2138,7 @@ removed_resources([_N1,N2,N3], DeleteRes) ->
nasty(suite) -> [];
nasty(doc) ->
- ["Tries to fullfill a rather nasty locking scenario, where we have had "
+ ["Tries to fulfill a rather nasty locking scenario, where we have had "
"bugs, the testcase tries a combination of locks in locker queue"];
%% This testcase no longer works as it was intended to show errors when
diff --git a/lib/mnesia/test/mnesia_recovery_test.erl b/lib/mnesia/test/mnesia_recovery_test.erl
index b5749408f8..498550c8ec 100644
--- a/lib/mnesia/test/mnesia_recovery_test.erl
+++ b/lib/mnesia/test/mnesia_recovery_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
-export([coord_dies/1, after_full_disc_partition/1,
disc_less/1, garb_decision/1,
- system_upgrade/1,
delete_during_start/1,
no_master_2/1, no_master_3/1, one_master_2/1, one_master_3/1,
two_master_2/1, two_master_3/1, all_master_2/1,
@@ -120,9 +119,9 @@ all() ->
[{group, mnesia_down}, {group, explicit_stop},
coord_dies, {group, schema_trans}, {group, async_dirty},
{group, sync_dirty}, {group, sym_trans},
- {group, asym_trans}, after_full_disc_partition,
- {group, after_corrupt_files}, disc_less, garb_decision,
- system_upgrade].
+ {group, asym_trans}, %% after_full_disc_partition,
+ {group, after_corrupt_files}, disc_less, garb_decision
+ ].
groups() ->
[{schema_trans, [],
@@ -1341,7 +1340,7 @@ garb_of_decisions(Kill, Nodes, Tid_list, Trans_res) ->
case length(Tid_list) of
1 ->
%% If there was only one transaction, it should be logged as
- %% comitted on every node!
+ %% committed on every node!
[Tid1] = Tid_list,
verify_garb_transient_logs(Nodes, [Tid1], committed);
2 ->
@@ -1455,7 +1454,7 @@ receive_messages(ListOfMsgs, File, Line) ->
[{Pid, Msg} | receive_messages(ListOfMsgs -- [Msg], File, Line)]
end;
Else -> mnesia_test_lib:log("<>WARNING<>~n"
- "Recevied unexpected or bad formatted msg~n ~p ~n"
+ "Received unexpected or bad formatted msg~n ~p ~n"
"While waiting for ~p~n",
[Else, ListOfMsgs], File, Line),
receive_messages(ListOfMsgs, File, Line)
@@ -1645,9 +1644,6 @@ disc_less(Config) when is_list(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-system_upgrade(doc) ->
- ["Test on-line and off-line upgrade of the Mnesia application"].
-
garb_decision(doc) ->
["Test that decisions are garbed correctly."];
garb_decision(suite) -> [];
diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl
index 9794915026..6bf44295b3 100644
--- a/lib/mnesia/test/mnesia_test_lib.erl
+++ b/lib/mnesia/test/mnesia_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@
%%% specified in the Config, the test case is skipped. If there
%%% was enough node names in the Config, X of them are selected
%%% and if some of them happens to be down they are restarted
-%%% via the slave module. When all nodes are up and running a
+%%% via the peer module. When all nodes are up and running a
%%% disk resident schema is created on all nodes and Mnesia is
%%% started a on all nodes. This means that all test cases may
%%% assume that Mnesia is up and running on all acquired nodes.
@@ -62,7 +62,7 @@
%%% test(TestCases)
%%%
%%% Run parts of the test suite. Uses test/2.
-%%% Reads Config from mnesia_test.config and starts them if neccessary.
+%%% Reads Config from mnesia_test.config and starts them if necessary.
%%% Kills Mnesia and wipes out the Mnesia directories as a starter.
%%%
%%% test(TestCases, Config)
@@ -97,9 +97,7 @@
select_nodes/4,
init_nodes/3,
error/4,
- slave_start_link/0,
- slave_start_link/1,
- slave_sup/0,
+ node_sup/0,
start_mnesia/1,
start_mnesia/2,
@@ -236,26 +234,14 @@ 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()).
+node_start_link(Host, Name) ->
+ node_start_link(Host, Name, 10).
-slave_start_link(Node) ->
- [Local, Host] = node_to_name_and_host(Node),
- Count = erlang:unique_integer([positive]),
- List = [Local, "_", Count],
- Name = list_to_atom(lists:concat(List)),
- slave_start_link(list_to_atom(Host), Name).
-
-slave_start_link(Host, Name) ->
- slave_start_link(Host, Name, 10).
-
-slave_start_link(Host, Name, Retries) ->
+node_start_link(Host, Name, Retries) ->
Debug = atom_to_list(mnesia:system_info(debug)),
- Args = "-mnesia debug " ++ Debug ++
- " -pa " ++
- filename:dirname(code:which(?MODULE)) ++
- " -pa " ++
- filename:dirname(code:which(mnesia)),
+ Args = ["-mnesia", "debug", Debug,
+ "-pa", filename:dirname(code:which(?MODULE)),
+ "-pa", filename:dirname(code:which(mnesia))],
case starter(Host, Name, Args) of
{ok, NewNode} ->
?match(pong, net_adm:ping(NewNode)),
@@ -264,22 +250,23 @@ slave_start_link(Host, Name, Retries) ->
ok = rpc:call(NewNode, file, set_cwd, [Cwd]),
true = rpc:call(NewNode, code, set_path, [Path]),
ok = rpc:call(NewNode, error_logger, tty, [false]),
- spawn_link(NewNode, ?MODULE, slave_sup, []),
+ spawn_link(NewNode, ?MODULE, node_sup, []),
rpc:multicall([node() | nodes()], global, sync, []),
{ok, NewNode};
{error, Reason} when Retries == 0->
{error, Reason};
{error, Reason} ->
- io:format("Could not start slavenode ~p ~p retrying~n",
+ io:format("Could not start node ~p ~p retrying~n",
[{Host, Name, Args}, Reason]),
timer:sleep(500),
- slave_start_link(Host, Name, Retries - 1)
+ node_start_link(Host, Name, Retries - 1)
end.
starter(Host, Name, Args) ->
- slave:start(Host, Name, Args).
+ {ok, _, Node} = peer:start(#{host => Host, name => Name, args => Args}),
+ {ok, Node}.
-slave_sup() ->
+node_sup() ->
process_flag(trap_exit, true),
receive
{'EXIT', _, _} ->
@@ -722,7 +709,7 @@ kill_tc(Pid, Time) ->
"in ~p min~n", [Time div (1000*60)]),
Files = mnesia_lib:dist_coredump(),
?log("Cores dumped to:~n ~p~n", [Files]),
- %% Genarate erlang crashdumps.
+ %% Generate erlang crashdumps.
%% GenDump = fun(Node) ->
%% File = "CRASH_" ++ atom_to_list(Node) ++ ".dump",
%% rpc:call(Node, os, putenv, ["ERL_CRASH_DUMP", File]),
@@ -759,7 +746,7 @@ init_nodes([Node | Nodes], File, Line) ->
[Node | init_nodes(Nodes, File, Line)];
pang ->
[Name, Host] = node_to_name_and_host(Node),
- case slave_start_link(Host, Name) of
+ case node_start_link(Host, Name) of
{ok, Node1} ->
Path = code:get_path(),
true = rpc:call(Node1, code, set_path, [Path]),
diff --git a/lib/mnesia/test/mnesia_tpcb.erl b/lib/mnesia/test/mnesia_tpcb.erl
index fb39ee321d..6a78d4f1d0 100644
--- a/lib/mnesia/test/mnesia_tpcb.erl
+++ b/lib/mnesia/test/mnesia_tpcb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
%% a database system.
%%
%% The definition of the TPC-B states lots of detailed rules and
-%% conditions that must be fullfilled, e.g. how the ACID (atomicity,
+%% conditions that must be fulfilled, e.g. how the ACID (atomicity,
%% consistency, isolation and durability) properties are verified,
%% how the random numbers must be distributed, minimum sizes of
%% the different types of records, minimum duration of the benchmark,
diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl
index 65206a85af..b33b807bfc 100644
--- a/lib/mnesia/test/mnesia_trans_access_test.erl
+++ b/lib/mnesia/test/mnesia_trans_access_test.erl
@@ -722,7 +722,7 @@ nested_transactions(Config, Child, Father) ->
{[{Tab, father, not_updated}], [{Tab, child, not_updated}]}
end,
- %% Syncronize things!!
+ %% Synchronize things!!
?match({atomic, ok}, mnesia:sync_transaction(fun() -> mnesia:write({Tab, sync, sync}) end)),
?match(ChildRes, rpc:call(Node1, mnesia, dirty_read, [{Tab, child}])),
@@ -1196,7 +1196,7 @@ index_delete_object(Config) when is_list(Config) ->
?verify_mnesia(Nodes, []).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Add and drop indecies
+%% Add and drop indices
add_table_index_ram(suite) -> [];
diff --git a/lib/mnesia/test/mt.erl b/lib/mnesia/test/mt.erl
index c1859bef3f..b5eea30690 100644
--- a/lib/mnesia/test/mt.erl
+++ b/lib/mnesia/test/mt.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -235,7 +235,7 @@ ping() ->
Nodes = mnesia_test_lib:select_nodes(all, Config, ?FILE, ?LINE),
[{N, net_adm:ping(N)} || N <- Nodes].
-%% Slave start all nodes in config spec
+%% Start all nodes in config spec
start_nodes() ->
Config = read_config(),
Nodes = mnesia_test_lib:select_nodes(all, Config, ?FILE, ?LINE),
@@ -245,30 +245,32 @@ start_nodes() ->
%% loop one testcase /suite until it fails
loop(Case) ->
- loop_1(Case,-1,read_config()).
+ loop_1(Case,1,infinity,read_config()).
loop(M,F) when is_atom(F) ->
- loop_1({M,F},-1,read_config());
+ loop_1({M,F},1, infinity, read_config());
loop(Case,N) when is_integer(N) ->
- loop_1(Case, N,read_config()).
+ loop_1(Case, 1, N,read_config()).
loop(M,F,N) when is_integer(N) ->
- loop_1({M,F},N,read_config()).
+ loop_1({M,F},1, N,read_config()).
+
+loop_1(Case,N,Max,Config) when N < Max ->
+ io:format("~nLoop test ~p ~n", [abs(N)]),
-loop_1(Case,N,Config) when N /= 0 ->
- io:format("Loop test ~p ~n", [abs(N)]),
case ok_result(Res = t(Case,Config)) of
true ->
- loop_1(Case,N-1,Config);
+ loop_1(Case,N+1,Max,Config);
error ->
+ io:format("Failed after ~p~n", [N]),
Res
end;
-loop_1(_,_,_) ->
+loop_1(_,_,_,_) ->
ok.
-
+
ok_result([{_T,{ok,_,_}}|R]) ->
ok_result(R);
-ok_result([{_T,{TC,List}}|R]) when is_tuple(TC), is_list(List) ->
+ok_result([{_T,{TC,List}}|R]) when is_tuple(TC), is_list(List) ->
ok_result(List) andalso ok_result(R);
ok_result([]) -> true;
ok_result(_) -> error.
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index 8f04eb60fe..ca16e64482 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.20.4
+MNESIA_VSN = 4.21.4
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index ef95459d1e..a32302ee95 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -32,6 +32,91 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 2.14</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A WX event race could causes a crash in when handling
+ socket or port info.</p>
+ <p>
+ Own Id: OTP-18339</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improve the nodes menu to include more nodes.</p>
+ <p>
+ Own Id: OTP-18269 Aux Id: PR-6030 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fixed units in gui.</p>
+ <p>
+ Own Id: OTP-18151 Aux Id: PR-6063 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Observer 2.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed default handling of Mac specific menus.</p>
+ <p>
+ Own Id: OTP-17996 Aux Id: PR-5795 </p>
+ </item>
+ <item>
+ <p>
+ Reading port socket options on macOS and Windows "skips"
+ invalid options.</p>
+ <p>
+ Own Id: OTP-18012 Aux Id: #5798 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The configuration files <seecom
+ marker="erts:erl"><c>.erlang</c></seecom>, <seeguide
+ marker="system/reference_manual:distributed"><c>.erlang.cookie</c></seeguide>
+ and <seeerl
+ marker="stdlib:beam_lib#.erlang.crypt"><c>.erlang.crypt</c></seeerl>
+ can now be located in the XDG Config Home directory.</p>
+ <p>
+ See the documentation for each file and
+ <c>filename:basedir/2</c> for more details.</p>
+ <p>
+ Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 2.11.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/observer/doc/src/observer_ug.xml b/lib/observer/doc/src/observer_ug.xml
index b0e8ef5872..348e613c85 100644
--- a/lib/observer/doc/src/observer_ug.xml
+++ b/lib/observer/doc/src/observer_ug.xml
@@ -252,7 +252,7 @@
<section>
<title>Sockets Tab</title>
- <p>Tab <em>Sockets</em> is devided into two parts.
+ <p>Tab <em>Sockets</em> is divided into two parts.
The first part contains general
<seeerl marker="kernel:socket"><c>socket</c></seeerl>
information and the second part
@@ -314,7 +314,7 @@
<title>Table Viewer Tab</title>
<p>Tab <em>Table Viewer</em> lists tables. By default, ETS tables
are displayed whereas unreadable private ETS tables and tables created by OTP
- applications are not diplayed. Use menu <em>View</em> to view "system"
+ applications are not displayed. Use menu <em>View</em> to view "system"
ETS tables, unreadable ETS tables, or Mnesia tables.
</p>
<p>Double-click to view the table content, or right-click and
@@ -360,7 +360,7 @@
the <em>Ports</em> tab. A special <em>new</em> identifier,
meaning all processes, or ports, started after trace start, can
be added with buttons <em>Add 'new' Processes</em> and <em>Add
- 'new' Ports</em>, respecively.
+ 'new' Ports</em>, respectively.
</p>
<p>
When adding processes or ports, a window with trace options is
diff --git a/lib/observer/doc/src/ttb_ug.xml b/lib/observer/doc/src/ttb_ug.xml
index be24db1aac..0411694c4e 100644
--- a/lib/observer/doc/src/ttb_ug.xml
+++ b/lib/observer/doc/src/ttb_ug.xml
@@ -394,7 +394,7 @@ check(stop) ->
this way is then merged with all other traces.</p>
<p>The autostart feature requires more data to be stored on
traced nodes. By default, the data is stored automatically
- to the file named "ttb_autostart.bin" in the currect working directory
+ to the file named "ttb_autostart.bin" in the current working directory
(cwd) of the traced node.
Users can change this behaviour (that is, on diskless
nodes) by specifying their own module to handle autostart data
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index 4280557d45..2edb2ceb3e 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2002-2021. All Rights Reserved.
+# Copyright Ericsson AB 2002-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -128,7 +128,7 @@ ERL_COMPILE_FLAGS += \
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-opt debug: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/observer/src/cdv_proc_cb.erl b/lib/observer/src/cdv_proc_cb.erl
index 11830065b7..dafd8ab5d2 100644
--- a/lib/observer/src/cdv_proc_cb.erl
+++ b/lib/observer/src/cdv_proc_cb.erl
@@ -153,7 +153,7 @@ info_fields() ->
{"Old Binary vheap", old_bin_vheap},
{"Binary vheap unused", bin_vheap_unused},
{"Old Binary vheap unused", old_bin_vheap_unused},
- {"Number of Heap Fragements", num_heap_frag},
+ {"Number of Heap Fragments", num_heap_frag},
{"Heap Fragment Data",heap_frag_data},
{"New Heap Start", new_heap_start},
{"New Heap Top", new_heap_top},
diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl
index b876ce2945..a2f88986af 100644
--- a/lib/observer/src/crashdump_viewer.erl
+++ b/lib/observer/src/crashdump_viewer.erl
@@ -1652,7 +1652,7 @@ read_heap_lines_1(Fd, Acc) ->
%% Reduce the memory consumption by converting the
%% line to a binary. Measurements show that it may also
- %% be benefical for performance, too, because it makes the
+ %% be beneficial for performance, too, because it makes the
%% garbage collections cheaper.
Line = list_to_binary(Line1),
@@ -3357,7 +3357,7 @@ collect(Pids,Acc) ->
collect(lists:delete(Pid,Pids),[Result|Acc]);
{'DOWN', _Ref, process, Pid, _Error} ->
Warning =
- "WARNING: an error occured while parsing data.\n" ++
+ "WARNING: an error occurred while parsing data.\n" ++
case get(truncated) of
true -> "This might be because the dump is truncated.\n";
false -> ""
diff --git a/lib/observer/src/crashdump_viewer.hrl b/lib/observer/src/crashdump_viewer.hrl
index 856e558e6c..b6362f6d9d 100644
--- a/lib/observer/src/crashdump_viewer.hrl
+++ b/lib/observer/src/crashdump_viewer.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@
}).
-record(proc,
- %% Initial data according to the follwoing:
+ %% Initial data according to the following:
%%
%% msg_q_len, reds, memory and stack_heap are integers because it must
%% be possible to sort on them. All other fields are strings
diff --git a/lib/observer/src/etop.erl b/lib/observer/src/etop.erl
index f0990f1f25..78ffe658e4 100644
--- a/lib/observer/src/etop.erl
+++ b/lib/observer/src/etop.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ help() ->
"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"
- " will hang if the port is not avaiable~n"
+ " will hang if the port is not available~n"
" accumulate boolean If true execution time is accumulated ~n"
" lines integer Number of displayed processes~n"
" interval integer Display update interval in secs~n"
diff --git a/lib/observer/src/observer.app.src b/lib/observer/src/observer.app.src
index 09f959dabf..a2f012ebd5 100644
--- a/lib/observer/src/observer.app.src
+++ b/lib/observer/src/observer.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -67,7 +67,5 @@
{registered, []},
{applications, [kernel, stdlib]},
{env, []},
- {runtime_dependencies, ["wx-1.2","stdlib-3.13","runtime_tools-1.17",
+ {runtime_dependencies, ["wx-1.2","stdlib-3.13","runtime_tools-1.19",
"kernel-8.1","et-1.5","erts-11.0"]}]}.
-
-
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index b4c2663d0d..438fa80ce2 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -299,13 +299,13 @@ to_str({Unit, X}) when (Unit==bytes orelse Unit==time_ms) andalso is_list(X) ->
catch error:badarg -> X
end;
to_str({bytes, B}) ->
- KB = B div 1024,
- MB = KB div 1024,
- GB = MB div 1024,
+ KiB = B div 1024,
+ MiB = KiB div 1024,
+ GiB = MiB div 1024,
if
- GB > 10 -> integer_to_list(GB) ++ " GB";
- MB > 10 -> integer_to_list(MB) ++ " MB";
- KB > 0 -> integer_to_list(KB) ++ " kB";
+ GiB > 10 -> integer_to_list(GiB) ++ " GiB";
+ MiB > 10 -> integer_to_list(MiB) ++ " MiB";
+ KiB > 0 -> integer_to_list(KiB) ++ " KiB";
true -> integer_to_list(B) ++ " B"
end;
to_str({{words,WSz}, Sz}) ->
diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl
index a11ae4175a..4e16319d2b 100644
--- a/lib/observer/src/observer_port_wx.erl
+++ b/lib/observer/src/observer_port_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -147,12 +147,19 @@ 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_activated,
- itemIndex=Index}},
- State=#state{grid=Grid, ports=Ports, open_wins=Opened}) ->
- Port = lists:nth(Index+1, Ports),
- NewOpened = display_port_info(Grid, Port, Opened),
- {noreply, State#state{open_wins=NewOpened}};
+handle_event(#wx{event = #wxList{type = command_list_item_activated,
+ itemIndex = Index}},
+ State = #state{grid = Grid,
+ ports = Ports,
+ open_wins = Opened}) ->
+ if
+ length(Ports) >= (Index+1) ->
+ Port = lists:nth(Index+1, Ports),
+ NewOpened = display_port_info(Grid, Port, Opened),
+ {noreply, State#state{open_wins=NewOpened}};
+ true -> % Race - should we do somthing here?
+ {noreply, State}
+ end;
handle_event(#wx{event=#wxList{type=command_list_item_right_click,
itemIndex=Index}},
diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl
index 7ffdba262a..a22f76a4c7 100644
--- a/lib/observer/src/observer_procinfo.erl
+++ b/lib/observer/src/observer_procinfo.erl
@@ -339,7 +339,7 @@ fetch_state_info2(Pid, M) ->
%% Formatted status ?
case lists:keyfind(format_status, 1, rpc:call(node(Pid), M, module_info, [exports])) of
false -> Opt = {"Format", unknown};
- _ -> Opt = {"Format", overriden}
+ _ -> Opt = {"Format", overridden}
end,
[{"Behaviour", B}, Opt, {"State",OtherFormat}];
{badrpc,{'EXIT',{timeout, _}}} -> []
diff --git a/lib/observer/src/observer_sock_wx.erl b/lib/observer/src/observer_sock_wx.erl
index 3ab8f0d27a..4b936f6f3a 100644
--- a/lib/observer/src/observer_sock_wx.erl
+++ b/lib/observer/src/observer_sock_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2021-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -241,9 +241,14 @@ handle_event(#wx{event = #wxList{type = command_list_item_activated,
State = #state{grid = Grid,
sockets = Sockets,
open_wins = Opened}) ->
- Socket = lists:nth(Index+1, Sockets),
- NewOpened = display_socket_info(Grid, Socket, Opened),
- {noreply, State#state{open_wins = NewOpened}};
+ if
+ length(Sockets) >= (Index+1) ->
+ Socket = lists:nth(Index+1, Sockets),
+ NewOpened = display_socket_info(Grid, Socket, Opened),
+ {noreply, State#state{open_wins = NewOpened}};
+ true -> % Race - should we do somthing here?
+ {noreply, State}
+ end;
handle_event(#wx{event = #wxList{type = command_list_item_right_click,
itemIndex = Index}},
diff --git a/lib/observer/src/observer_sys_wx.erl b/lib/observer/src/observer_sys_wx.erl
index 8c2ffd77b4..25086b10b7 100644
--- a/lib/observer/src/observer_sys_wx.erl
+++ b/lib/observer/src/observer_sys_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -138,10 +138,10 @@ info_fields() ->
{"Async thread pool size", thread_pool_size}
]}],
- Cpu = [{"CPU's and Threads",
- [{"Logical CPU's", logical_processors},
- {"Online Logical CPU's", logical_processors_online},
- {"Available Logical CPU's", logical_processors_available},
+ Cpu = [{"CPUs and Threads",
+ [{"Logical CPUs", logical_processors},
+ {"Online Logical CPUs", logical_processors_online},
+ {"Available Logical CPUs", logical_processors_available},
{"Schedulers", schedulers},
{"Online schedulers", schedulers_online},
{"Available schedulers", schedulers_available}
diff --git a/lib/observer/src/observer_trace_wx.erl b/lib/observer/src/observer_trace_wx.erl
index 5b8d4f5568..5b4e98a909 100644
--- a/lib/observer/src/observer_trace_wx.erl
+++ b/lib/observer/src/observer_trace_wx.erl
@@ -361,7 +361,7 @@ handle_event(#wx{event = #wxCommand{type = command_togglebutton_clicked, command
(TProcs == []) andalso (TPorts == []) andalso throw({error, "No processes or ports traced"}),
(Nodes == []) andalso throw({error, "No nodes traced"}),
HaveCallTrace = fun(#titem{opts=Os}) -> lists:member(functions,Os) end,
- WStr = "Call trace actived but no trace patterns used",
+ WStr = "Call trace activated but no trace patterns used",
(TPs == []) andalso lists:any(HaveCallTrace, TProcs) andalso
observer_wx:create_txt_dialog(Panel, WStr, "Warning", ?wxICON_WARNING),
@@ -763,7 +763,7 @@ do_add_patterns({Module, NewPs}, State=#state{tpatterns=TPs0, m_view=Mview, f_vi
{Old, [], []} ->
State;
{MPatterns, _New, _Changed} ->
- %% if dynamicly updates update New and Changed
+ %% if dynamically 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),
@@ -1048,7 +1048,7 @@ textformat(Trace) when element(1, Trace) == trace_ts, tuple_size(Trace) >= 4 ->
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", []);
+ io_lib:format("*** Seq trace not implemented.~n", []);
textformat(_) ->
"".
diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl
index 07e2fb1b29..321f189fc9 100644
--- a/lib/observer/src/observer_wx.erl
+++ b/lib/observer/src/observer_wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
%% Includes
-include_lib("wx/include/wx.hrl").
+-include_lib("kernel/include/file.hrl").
-include("observer_defs.hrl").
@@ -157,7 +158,7 @@ setup(#state{frame = Frame} = State) ->
wxNotebook:connect(Notebook, command_notebook_page_changed,
[{skip, true}, {id, ?ID_NOTEBOOK}]),
wxFrame:connect(Frame, close_window, []),
- wxMenu:connect(Frame, command_menu_selected),
+ wxMenu:connect(Frame, command_menu_selected, [{skip, true}]),
wxFrame:show(Frame),
%% Freeze and thaw is buggy currently
@@ -390,6 +391,10 @@ handle_event(#wx{id = Id, event = #wxCommand{type = command_menu_selected}},
end,
{noreply, change_node_view(Node, LState)};
+handle_event(#wx{id = Id, event = #wxCommand{type = command_menu_selected}}, State)
+ when Id >= ?wxID_OSX_MENU_FIRST, Id =< ?wxID_OSX_MENU_LAST ->
+ {noreply, State};
+
handle_event(Event, #state{active_tab=Pid} = State) ->
Pid ! Event,
{noreply, State}.
@@ -558,7 +563,7 @@ try_rpc(Node, Mod, Func, Args) ->
return_to_localnode(Frame, Node) ->
case node() =/= Node of
true ->
- create_txt_dialog(Frame, "Error occured on remote node",
+ create_txt_dialog(Frame, "Error occurred on remote node",
"Error", ?wxICON_ERROR),
disconnect_node(Node);
false ->
@@ -658,14 +663,16 @@ create_connect_dialog(connect, #state{frame = Frame}) ->
wxWindow:setSizerAndFit(Dialog, VSizer),
wxSizer:setSizeHints(VSizer, Dialog),
{ok,[[HomeDir]]} = init:get_argument(home),
- CookiePath = filename:join(HomeDir, ".erlang.cookie"),
- DefaultCookie = case filelib:is_file(CookiePath) of
- true ->
- {ok, Bin} = file:read_file(CookiePath),
- binary_to_list(Bin);
- false ->
- ""
- end,
+ XDGHome = filename:basedir(user_config,"erlang"),
+ DefaultCookie =
+ case file:path_open([HomeDir,XDGHome], ".erlang.cookie", [read]) of
+ {ok, File, _} ->
+ {ok, #file_info{ size = Sz }} = file:read_file_info(File),
+ {ok, Data} = file:read(File, Sz),
+ Data;
+ _ ->
+ ""
+ end,
wxTextCtrl:setValue(CookieCtrl, DefaultCookie),
case wxDialog:showModal(Dialog) of
?wxID_OK ->
@@ -740,21 +747,45 @@ get_nodes() ->
Nodes0 = case erlang:is_alive() of
false -> [];
true ->
- case net_adm:names() of
- {error, _} -> nodes();
- {ok, Names} ->
- epmd_nodes(Names) ++ nodes()
- end
+ case net_adm:names() of
+ {error, _} -> [];
+ {ok, Names} -> epmd_nodes(Names)
+ end
+ ++
+ [node() | nodes(connected)]
end,
Nodes = lists:usort(Nodes0),
+ WarningText = "WARNING: connecting to non-erlang nodes may crash them",
{_, 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]}
+ text=atom_to_list(Node),
+ help=WarningText} | Acc]}
end, {1, []}, Nodes),
{Nodes, lists:reverse(Menues)}.
-epmd_nodes(Names) ->
+%% see erl_epmd:(listen_)port_please/2
+erl_dist_port() ->
+ try
+ erl_epmd = net_kernel:epmd_module(),
+ {ok, [[StringPort]]} = init:get_argument(erl_epmd_port),
+ list_to_integer(StringPort)
+ catch
+ _:_ ->
+ undefined
+ end.
+
+%% If the default epmd module erl_epmd is used and erl_epmd_port is
+%% set to `DistPort' then it is only possible to connect to the node
+%% listening on DistPort (if any), so exclude other nodes registered
+%% in EPMD
+epmd_nodes(Names0) ->
+ Names = case erl_dist_port() of
+ undefined ->
+ Names0;
+ DistPort ->
+ [NP || NP = {_, Port} <- Names0, Port =:= DistPort]
+ end,
[_, Host] = string:lexemes(atom_to_list(node()),"@"),
[list_to_atom(Name ++ [$@|Host]) || {Name, _} <- Names].
@@ -833,7 +864,7 @@ is_rb_compatible(Node) ->
is_rb_server_running(Node, LogState) ->
%% If already started, somebody else may use it.
- %% We cannot use it too, as far log file would be overriden. Not fair.
+ %% We cannot use it too, as far log file would be overridden. Not fair.
case rpc:block_call(Node, erlang, whereis, [rb_server]) of
Pid when is_pid(Pid), (LogState == false) ->
throw("Error: rb_server is already started and maybe used by someone.");
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index 29a572d7fe..c4161f4e2a 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1199,7 +1199,7 @@ start_client(FileOrWrap,Traci) ->
{fun handler/2, dict:to_list(Traci)}).
handler(Trace,Traci) ->
- %%We return our own Traci so that it not necesarry to look it up
+ %%We return our own Traci so that it not necessary to look it up
%%This may take time if something huge has been written to it
receive
{get,Collector} -> Collector ! {self(),{Trace,Traci}};
diff --git a/lib/observer/src/ttb_et.erl b/lib/observer/src/ttb_et.erl
index f90a7f6dcf..39c4c2180c 100644
--- a/lib/observer/src/ttb_et.erl
+++ b/lib/observer/src/ttb_et.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ collector(Trace) ->
%% all events backwards and collect call/return information:
%%
%% MFA collected from return_to events is added to call and
-%% return_from events as {caller,MFA} and {return_to,MFA} respecively.
+%% return_from events as {caller,MFA} and {return_to,MFA} respectively.
%% MFA collected from call events is added to return_to events as
%% {return_from,MFA}
%%
diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile
index 1dc7a7e11b..114f77400f 100644
--- a/lib/observer/test/Makefile
+++ b/lib/observer/test/Makefile
@@ -52,6 +52,7 @@ RELSYSDIR = $(RELEASE_PATH)/observer_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += +warnings_as_errors +nowarn_export_all
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -68,7 +69,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
$(MODULES) > $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl
index 83455def93..8a5dd1011c 100644
--- a/lib/observer/test/crashdump_helper.erl
+++ b/lib/observer/test/crashdump_helper.erl
@@ -25,7 +25,7 @@
dump_persistent_terms/0,
create_persistent_terms/0,
dump_global_literals/0]).
--compile(r20).
+-compile(r22).
-include_lib("common_test/include/ct.hrl").
n1_proc(N2,Creator) ->
diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl
index 230ab6ceed..2777e5f995 100644
--- a/lib/observer/test/crashdump_viewer_SUITE.erl
+++ b/lib/observer/test/crashdump_viewer_SUITE.erl
@@ -187,7 +187,7 @@ start_stop(Config) when is_list(Config) ->
ok.
recv_downs([]) ->
- ct:log("'DOWN' received from all registered proceses~n", []),
+ ct:log("'DOWN' received from all registered processes~n", []),
ok;
recv_downs(Regs) ->
receive
diff --git a/lib/observer/test/etop_SUITE.erl b/lib/observer/test/etop_SUITE.erl
index e324c9bbb1..8b112cba37 100644
--- a/lib/observer/test/etop_SUITE.erl
+++ b/lib/observer/test/etop_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
-define(default_timeout, test_server:minutes(1)).
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) ->
try apply(?MODULE,Case,[cleanup,Config])
@@ -64,23 +64,23 @@ end_per_group(_GroupName, Config) ->
%% Start etop with text presentation
text(_) ->
- ?line {ok,Node} = test_server:start_node(node2,peer,[]),
+ {ok,Node} = test_server:start_node(node2,peer,[]),
%% Must spawn this process, else the test case will never end.
- ?line spawn_link(etop,start,[[{node,Node},{output,text},{interval,3}]]),
- ?line timer:sleep(4000),
- ?line etop:config(interval,2),
- ?line timer:sleep(3000),
- ?line etop:config(lines,5),
- ?line timer:sleep(3000),
- ?line etop:config(accumulate,true),
- ?line timer:sleep(3000),
- ?line etop:config(sort,reductions),
- ?line timer:sleep(3000),
- ?line etop:config(sort,memory),
- ?line timer:sleep(3000),
- ?line etop:config(sort,msg_q),
- ?line timer:sleep(3000),
+ spawn_link(etop,start,[[{node,Node},{output,text},{interval,3}]]),
+ timer:sleep(4000),
+ etop:config(interval,2),
+ timer:sleep(3000),
+ etop:config(lines,5),
+ timer:sleep(3000),
+ etop:config(accumulate,true),
+ timer:sleep(3000),
+ etop:config(sort,reductions),
+ timer:sleep(3000),
+ etop:config(sort,memory),
+ timer:sleep(3000),
+ etop:config(sort,msg_q),
+ timer:sleep(3000),
ok.
text(cleanup,_Config) ->
etop:stop(),
@@ -93,26 +93,26 @@ text_tracing_off(suite) ->
text_tracing_off(doc) ->
["Start etop with text presentation, and tracing turned off"];
text_tracing_off(Config) when is_list(Config) ->
- ?line {ok,Node} = test_server:start_node(node2,peer,[]),
+ {ok,Node} = test_server:start_node(node2,peer,[]),
%% Must spawn this process, else the test case will never end.
- ?line spawn_link(etop,start,[[{node,Node},
+ spawn_link(etop,start,[[{node,Node},
{output,text},
{interval,3},
{tracing,off}]]),
- ?line timer:sleep(4000),
- ?line etop:config(interval,2),
- ?line timer:sleep(3000),
- ?line etop:config(lines,5),
- ?line timer:sleep(3000),
- ?line etop:config(accumulate,true),
- ?line timer:sleep(3000),
- ?line etop:config(sort,memory),
- ?line timer:sleep(3000),
- ?line etop:config(sort,msg_q),
- ?line timer:sleep(3000),
- ?line etop:config(sort,runtime), % this should not crash, but has no effect
- ?line timer:sleep(3000),
+ timer:sleep(4000),
+ etop:config(interval,2),
+ timer:sleep(3000),
+ etop:config(lines,5),
+ timer:sleep(3000),
+ etop:config(accumulate,true),
+ timer:sleep(3000),
+ etop:config(sort,memory),
+ timer:sleep(3000),
+ etop:config(sort,msg_q),
+ timer:sleep(3000),
+ etop:config(sort,runtime), % this should not crash, but has no effect
+ timer:sleep(3000),
ok.
text_tracing_off(cleanup,_Config) ->
etop:stop(),
diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl
index 575f63b956..1a1dca0fe0 100644
--- a/lib/observer/test/observer_SUITE.erl
+++ b/lib/observer/test/observer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,17 +74,47 @@ end_per_suite(Config) ->
ok.
+%% init_per_testcase(basic = Case, Config) ->
+%% ?P("init_per_testcase(~w) -> entry with"
+%% "~n Config: ~p", [Case, Config]),
+%% {ok, Host} = inet:gethostname(),
+%% {ok, IFL} = inet:getifaddrs(),
+%% init_per_testcase2(Case, [{host, Host}, {ifl, IFL} | Config]);
init_per_testcase(Case, Config) ->
?P("init_per_testcase(~w) -> entry with"
"~n Config: ~p", [Case, Config]),
+ init_per_testcase2(Case, Config).
+
+init_per_testcase2(Case, Config) ->
+ ?P("init_per_testcase(~w) -> entry", [Case]),
Dog = test_server:timetrap(?default_timeout),
[{watchdog, Dog} | Config].
+%% end_per_testcase(basic = Case, Config) ->
+%% ?P("end_per_testcase(~w) -> entry with"
+%% "~n Config: ~p", [Case, Config]),
+%% case lists:keysearch(tc_status, 1, Config) of
+%% {value, {tc_status, ok}} ->
+%% ?P("end_per_testcase(~w) -> successful", [Case]),
+%% ok;
+%% {value, _} ->
+%% ?P("end_per_testcase(~w) -> try ensure observer stopped", [Case]),
+%% ensure_observer_stopped();
+%% _ ->
+%% ?P("end_per_testcase(~w) -> nop status", [Case]),
+%% ok
+%% end,
+%% end_per_testcase2(Case, Config);
end_per_testcase(Case, Config) ->
?P("end_per_testcase(~w) -> entry with"
"~n Config: ~p", [Case, Config]),
+ end_per_testcase2(Case, Config).
+
+end_per_testcase2(Case, Config) ->
+ ?P("end_per_testcase2(~w) -> entry - try cancel watchdog", [Case]),
Dog = ?config(watchdog, Config),
test_server:timetrap_cancel(Dog),
+ ?P("end_per_testcase2(~w) -> done", [Case]),
ok.
@@ -139,14 +169,14 @@ app_file(suite) ->
app_file(doc) ->
["Testing .app file"];
app_file(Config) when is_list(Config) ->
- ?line ok = test_server:app_test(observer),
+ ok = test_server:app_test(observer),
ok.
+
%% Testing .appup file
appup_file(Config) when is_list(Config) ->
ok = test_server:appup_test(observer).
--define(DBG(Foo), io:format("~p: ~p~n",[?LINE, catch Foo])).
basic(suite) -> [];
basic(doc) -> [""];
@@ -159,10 +189,19 @@ basic(Config) when is_list(Config) ->
wx:new(),
?P("basic -> try wx destroy"),
wx:destroy(),
- timer:send_after(100, "foobar"),
+ timer:start(),
?P("basic -> try start distribution"),
{foo, node@machine} ! dummy_msg, %% start distribution stuff
%% Otherwise ever lasting servers gets added to procs
+
+ %% It takes some time for all the procs to start,
+ %% so give it some time.
+ %% Note that this is a problem *only* if this test suite
+ %% is run *on its own*. If all the observer suite(s) are run
+ %% (ex: ts:run(observer, [batch]), then this problem does
+ %% not occcur.
+ timer:sleep(5000),
+
?P("basic -> procs before"),
ProcsBefore = processes(),
ProcInfoBefore = [{P,process_info(P)} || P <- ProcsBefore],
@@ -179,6 +218,7 @@ basic(Config) when is_list(Config) ->
?P("basic -> check selection (=0)"),
0 = wxNotebook:getSelection(Notebook),
?P("basic -> wait some time..."),
+
timer:sleep(500),
Check = fun(N, TestMore) ->
TestMore andalso
@@ -198,7 +238,7 @@ basic(Config) when is_list(Config) ->
?P("basic -> try verify that we resized"),
[_|_] = [Check(N, true) || N <- lists:seq(0, Count-1)],
- ?P("basic -> try stop observer (async)"),
+ ?P("basic -> try stop observer"),
ok = observer:stop(),
timer:sleep(2000), %% stop is async
?P("basic -> try verify observer stopped"),
@@ -206,15 +246,16 @@ basic(Config) when is_list(Config) ->
NumProcsAfter = length(ProcsAfter),
if NumProcsAfter =/= NumProcsBefore ->
BeforeNotAfter = ProcsBefore -- ProcsAfter,
+ AfterNotBefore = ProcsAfter -- ProcsBefore,
?P("basic -> *not* fully stopped:"
"~n Number of Procs before: ~p"
"~n Number of Procs after: ~p",
- [NumProcsAfter, NumProcsBefore]),
+ [NumProcsBefore, NumProcsAfter]),
ct:log("Before but not after:~n~p~n",
[[{P,I} || {P,I} <- ProcInfoBefore,
lists:member(P,BeforeNotAfter)]]),
ct:log("After but not before:~n~p~n",
- [[{P,process_info(P)} || P <- ProcsAfter -- ProcsBefore]]),
+ [[{P,process_info(P)} || P <- AfterNotBefore]]),
ensure_observer_stopped(),
ct:fail("leaking processes");
true ->
diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl
index ab02cdabb4..d44f89d92c 100644
--- a/lib/observer/test/ttb_SUITE.erl
+++ b/lib/observer/test/ttb_SUITE.erl
@@ -2,7 +2,7 @@
%% %CopyrightBegin%
%%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@
-define(DIRNAME, "ddtemp").
init_per_testcase(Case, Config) ->
- ?line Dog=test_server:timetrap(?default_timeout),
+ Dog=test_server:timetrap(?default_timeout),
ttb:stop(),
rm(?OUTPUT),
[rm(Upload) || Upload<-filelib:wildcard("ttb_upload*")],
@@ -115,74 +115,74 @@ file(suite) ->
file(doc) ->
["Start tracing on multiple nodes, single file"];
file(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"file"),
- ?line {ok,[Node]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"file"),
+ {ok,[Node]} =
ttb:tracer(Node,[{file, File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{S,[{matched,Node,_}]}]} = ttb:p(S,call),
- ?line {ok,[OtherNode]} =
+ {ok,[{S,[{matched,Node,_}]}]} = ttb:p(S,call),
+ {ok,[OtherNode]} =
ttb:tracer([Node,OtherNode],[{file, File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[]} = ttb:tracer([Node,OtherNode],
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[]} = ttb:tracer([Node,OtherNode],
[{file, File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
- ?line ok = ttb:format(filename:join(Privdir,
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
+ ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-file")),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace,
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
file(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
file_no_pi(suite) ->
[];
file_no_pi(doc) ->
["Start tracing on multiple nodes, single file, no process information"];
file_no_pi(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"file"),
- ?line {ok,[_,_]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"file"),
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
{handler,{fun myhandler/4, S}},
{process_info,false}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
- ?line ok = ttb:format(filename:join(Privdir,
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(filename:join(Privdir,atom_to_list(Node)++"-file")),
+ ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-file")),
- ?line [{trace_ts,LocalProc,call,{?MODULE,foo,[]}, {_,_,_}},
+ [{trace_ts,LocalProc,call,{?MODULE,foo,[]}, {_,_,_}},
end_of_trace,
{trace_ts,RemoteProc,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
- ?line true = is_pid(LocalProc),
- ?line true = is_pid(RemoteProc),
+ true = is_pid(LocalProc),
+ true = is_pid(RemoteProc),
ok.
file_no_pi(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
file_fetch(suite) ->
@@ -190,67 +190,67 @@ file_fetch(suite) ->
file_fetch(doc) ->
["stop with the fetch option, i.e. collect all files when ttb is stopped"];
file_fetch(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line ThisDir = filename:join(Privdir,this),
- ?line ok = file:make_dir(ThisDir),
- ?line OtherDir = filename:join(Privdir,other),
- ?line ok = file:make_dir(OtherDir),
- ?line ThisFile = filename:join(ThisDir,"file_fetch"),
- ?line OtherFile = filename:join(OtherDir,"file_fetch"),
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ ThisDir = filename:join(Privdir,this),
+ ok = file:make_dir(ThisDir),
+ OtherDir = filename:join(Privdir,other),
+ ok = file:make_dir(OtherDir),
+ ThisFile = filename:join(ThisDir,"file_fetch"),
+ OtherFile = filename:join(OtherDir,"file_fetch"),
%% I'm setting priv_dir as cwd, so ttb_upload directory is created there
%% and not in any other strange place!
- ?line {ok,Cwd} = file:get_cwd(),
- ?line ok = file:set_cwd(Privdir),
+ {ok,Cwd} = file:get_cwd(),
+ ok = file:set_cwd(Privdir),
- ?line {ok,[Node]} =
+ {ok,[Node]} =
ttb:tracer(Node,[{file, ThisFile},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[OtherNode]} =
+ {ok,[OtherNode]} =
ttb:tracer([OtherNode],[{file, OtherFile},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line test_server:capture_start(),
- ?line ttb:stop([return_fetch_dir]),
- ?line test_server:capture_stop(),
- ?line [StoreString] = test_server:capture_get(),
- ?line UploadDir =
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ test_server:capture_start(),
+ ttb:stop([return_fetch_dir]),
+ test_server:capture_stop(),
+ [StoreString] = test_server:capture_get(),
+ UploadDir =
lists:last(string:lexemes(lists:flatten(StoreString),"$ \n")),
%% check that files are no longer in original directories...
- ?line ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch"),
- ?line ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch.ti"),
-% ?line false = lists:member(TrcLog,ThisList),
-% ?line false = lists:member(TIFile,ThisList),
+ ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch"),
+ ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch.ti"),
+% false = lists:member(TrcLog,ThisList),
+% false = lists:member(TIFile,ThisList),
- ?line {ok,OtherList} = file:list_dir(OtherDir),
- ?line false = lists:member(atom_to_list(OtherNode)++"-file_fetch",OtherList),
- ?line false = lists:member(atom_to_list(OtherNode)++"-file_fetch.ti",
+ {ok,OtherList} = file:list_dir(OtherDir),
+ false = lists:member(atom_to_list(OtherNode)++"-file_fetch",OtherList),
+ false = lists:member(atom_to_list(OtherNode)++"-file_fetch.ti",
OtherList),
%% but instead in ttb_upload directory, where they can be formatted
- ?line ok = ttb:format(filename:join(UploadDir,
+ ok = ttb:format(filename:join(UploadDir,
atom_to_list(Node)++"-file_fetch")),
- ?line ok = ttb:format(filename:join(UploadDir,
+ ok = ttb:format(filename:join(UploadDir,
atom_to_list(OtherNode)++"-file_fetch")),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace,
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
- ?line ok = file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
ok.
file_fetch(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
wrap(suite) ->
@@ -258,44 +258,44 @@ wrap(suite) ->
wrap(doc) ->
["Start tracing on multiple nodes, wrap files"];
wrap(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"wrap"),
- ?line {ok,[_,_]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"wrap"),
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(filename:join(Privdir,
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp")),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
- ?line ok = ttb:format(filename:join(Privdir,
+ ok = ttb:format(filename:join(Privdir,
atom_to_list(OtherNode)++"-wrap.*.wrp")),
- ?line [{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
%% Check that merge does not crash even if the timestamp flag is not on.
- ?line ok = ttb:format(
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-wrap.*.wrp"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-wrap.*.wrp")],[{disable_sort,true}]),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},
@@ -305,37 +305,37 @@ wrap(Config) when is_list(Config) ->
ok.
wrap(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
wrap_merge(suite) ->
[];
wrap_merge(doc) ->
["Start tracing on multiple nodes, wrap files, merge logs from both nodes"];
wrap_merge(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"wrap_merge"),
- ?line {ok,[_,_]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"wrap_merge"),
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]}=ttb:p(all,[call,timestamp]),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]}=ttb:p(all,[call,timestamp]),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-wrap_merge.*.wrp"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-wrap_merge.*.wrp")]),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,_,call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,_,call,{?MODULE,foo,[]},_},
@@ -345,7 +345,7 @@ wrap_merge(Config) when is_list(Config) ->
ok.
wrap_merge(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
wrap_merge_fetch_format(suite) ->
@@ -353,31 +353,31 @@ wrap_merge_fetch_format(suite) ->
wrap_merge_fetch_format(doc) ->
["Start tracing on multiple nodes, wrap files, fetch and format at stop"];
wrap_merge_fetch_format(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"wrap_merge_fetch_format"),
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"wrap_merge_fetch_format"),
%% I'm setting priv_dir as cwd, so ttb_upload directory is created there
%% and not in any other strange place!
- ?line {ok,Cwd} = file:get_cwd(),
- ?line ok = file:set_cwd(Privdir),
+ {ok,Cwd} = file:get_cwd(),
+ ok = file:set_cwd(Privdir),
- ?line {ok,[_,_]} =
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, {wrap,File,200,3}},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]}=ttb:p(all,[call,timestamp]),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([format]),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]}=ttb:p(all,[call,timestamp]),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([format]),
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},_},
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
@@ -385,55 +385,55 @@ wrap_merge_fetch_format(Config) when is_list(Config) ->
{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},_},
end_of_trace] = flush(),
- ?line ok = file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
ok.
wrap_merge_fetch_format(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
write_config1(suite) ->
[];
write_config1(doc) ->
["Write config given commands"];
write_config1(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
-
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"write_config1"),
- ?line ok = ttb:write_config(File,
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"write_config1"),
+ ok = ttb:write_config(File,
[{ttb,tracer,[[Node,OtherNode],
[{file, File},
{handler,{fun myhandler/4,S}}]]},
{ttb,p,[all,call]},
{ttb,tp,[?MODULE,foo,[]]}]),
- ?line [_,_,_] = ttb:list_config(File),
- ?line ok = ttb:run_config(File),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ [_,_,_] = ttb:list_config(File),
+ ok = ttb:run_config(File),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config1"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config1")]),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config1.ti") of
{error,Reason} ->
timer:sleep(5000),
- ?line ok = ttb:format(
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config1"),
filename:join(Privdir,
atom_to_list(OtherNode)++
"-write_config1")]),
- ?line io:format("\nTrying again: ~p\n",[flush()]),
- ?line ct:fail(Reason);
+ io:format("\nTrying again: ~p\n",[flush()]),
+ ct:fail(Reason);
ok ->
ok
end,
@@ -441,58 +441,58 @@ write_config1(Config) when is_list(Config) ->
write_config1(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
write_config2(suite) ->
[];
write_config2(doc) ->
["Write config from history (all)"];
write_config2(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"write_config2"),
- ?line {ok,[_,_]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"write_config2"),
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ok = ttb:write_config(File,all),
- ?line ttb:stop(),
- ?line [_,_,_] = ttb:list_config(File),
- ?line ok = ttb:run_config(File),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ok = ttb:write_config(File,all),
+ ttb:stop(),
+ [_,_,_] = ttb:list_config(File),
+ ok = ttb:run_config(File),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config2"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config2")]),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config2.ti") of
{error,Reason} ->
timer:sleep(5000),
- ?line ok = ttb:format(
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config2"),
filename:join(Privdir,
atom_to_list(OtherNode)++
"-write_config2")]),
- ?line io:format("\nTrying again: ~p\n",[flush()]),
- ?line ct:fail(Reason);
+ io:format("\nTrying again: ~p\n",[flush()]),
+ ct:fail(Reason);
ok ->
ok
end,
ok.
write_config2(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
write_config3(suite) ->
@@ -500,65 +500,65 @@ write_config3(suite) ->
write_config3(doc) ->
["Write config from history (selected and append)"];
write_config3(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"write_config3"),
- ?line {ok,[_,_]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"write_config3"),
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ok = ttb:write_config(File,[1,2]),
- ?line ttb:stop([nofetch]),
- ?line [_,_] = ttb:list_config(File),
- ?line ok = ttb:run_config(File),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ok = ttb:write_config(File,[1,2]),
+ ttb:stop([nofetch]),
+ [_,_] = ttb:list_config(File),
+ ok = ttb:run_config(File),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config3")]),
- ?line [end_of_trace] = flush(), %foo is not traced
+ [end_of_trace] = flush(), %foo is not traced
- ?line ok = ttb:write_config(File,[{ttb,tp,[?MODULE,foo,[]]}],
+ ok = ttb:write_config(File,[{ttb,tp,[?MODULE,foo,[]]}],
[append]),
- ?line [_,_,_] = ttb:list_config(File),
- ?line ok = ttb:run_config(File),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ [_,_,_] = ttb:list_config(File),
+ ok = ttb:run_config(File),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_config3")]),
- ?line [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
{trace_ts,Other,call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
case metatest(Other,OtherNode,Privdir,"-write_config3.ti") of
{error,Reason} ->
timer:sleep(5000),
- ?line ok = ttb:format(
+ ok = ttb:format(
[filename:join(Privdir,
atom_to_list(Node)++"-write_config3"),
filename:join(Privdir,
atom_to_list(OtherNode)++
"-write_config3")]),
- ?line io:format("\nTrying again: ~p\n",[flush()]),
- ?line ct:fail(Reason);
+ io:format("\nTrying again: ~p\n",[flush()]),
+ ct:fail(Reason);
ok ->
ok
end,
ok.
write_config3(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
@@ -567,39 +567,39 @@ history(suite) ->
history(doc) ->
["List history and execute entry from history"];
history(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
-
- ?line Nodes = [Node,OtherNode],
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"history"),
- ?line StartOpts = [{file, File},
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+
+ Nodes = [Node,OtherNode],
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"history"),
+ StartOpts = [{file, File},
{handler,{fun myhandler/4, S}}],
- ?line {ok,[_,_]} = ttb:tracer(Nodes,StartOpts),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:ctp(?MODULE,foo),
- ?line [{1,{ttb,tracer,[Nodes,StartOpts]}},
+ {ok,[_,_]} = ttb:tracer(Nodes,StartOpts),
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:ctp(?MODULE,foo),
+ [{1,{ttb,tracer,[Nodes,StartOpts]}},
{2,{ttb,p,[all,call]}},
{3,{ttb,tp,[?MODULE,foo,[]]}},
{4,{ttb,ctp,[?MODULE,foo]}}] = ttb:list_history(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ok = ttb:run_history(3),
- ?line ?MODULE:foo(),
- ?line ok = ttb:run_history([3,4]),
- ?line ?MODULE:foo(),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ok = ttb:run_history(3),
+ ?MODULE:foo(),
+ ok = ttb:run_history([3,4]),
+ ?MODULE:foo(),
+ ttb:stop([nofetch]),
+ 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,[]},{_,_,_}},
+ [{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
history(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
write_trace_info(suite) ->
@@ -607,34 +607,34 @@ write_trace_info(suite) ->
write_trace_info(doc) ->
["Write trace info and give handler explicitly in format command"];
write_trace_info(Config) when is_list(Config) ->
- ?line Node = node(),
- ?line {ok,OtherNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"write_trace_info"),
- ?line {ok,[_,_]} =
+ Node = node(),
+ {ok,OtherNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"write_trace_info"),
+ {ok,[_,_]} =
ttb:tracer([Node,OtherNode],[{file, File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line ok = ttb:write_trace_info(mytraceinfo,fun() -> node() end),
- ?line ?MODULE:foo(),
- ?line rpc:call(OtherNode,?MODULE,foo,[]),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ {ok,[{all,[{matched,_,_},{matched,_,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,_,1},{matched,_,1}]} = ttb:tp(?MODULE,foo,[]),
+ ok = ttb:write_trace_info(mytraceinfo,fun() -> node() end),
+ ?MODULE:foo(),
+ rpc:call(OtherNode,?MODULE,foo,[]),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-write_trace_info"),
filename:join(Privdir,
atom_to_list(OtherNode)++"-write_trace_info")],
[{handler,{fun otherhandler/4,S}}]),
- ?line [{{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},[Node]},
+ [{{trace_ts,{S,_,Node},call,{?MODULE,foo,[]},{_,_,_}},[Node]},
{{trace_ts,{_,_,OtherNode},call,{?MODULE,foo,[]},{_,_,_}},[OtherNode]},
end_of_trace] = flush(),
ok.
write_trace_info(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
seq_trace(suite) ->
@@ -642,22 +642,22 @@ seq_trace(suite) ->
seq_trace(doc) ->
["Test sequential tracing"];
seq_trace(Config) when is_list(Config) ->
- ?line S = self(),
+ S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"seq_trace"),
- ?line {ok,[Node]} = ttb:tracer(node(),[{file,File},
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"seq_trace"),
+ {ok,[Node]} = ttb:tracer(node(),[{file,File},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{new,[{matched,Node,0}]}]} = ttb:p(new,call),
- ?line {ok,[{matched,Node,1},{saved,1}]} =
+ {ok,[{new,[{matched,Node,0}]}]} = ttb:p(new,call),
+ {ok,[{matched,Node,1},{saved,1}]} =
ttb:tpl(?MODULE,seq,0,ttb:seq_trigger_ms(send)),
- ?line Start = spawn(fun() -> seq() end),
- ?line timer:sleep(300),
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(
+ Start = spawn(fun() -> seq() end),
+ timer:sleep(300),
+ ttb:stop([nofetch]),
+ ok = ttb:format(
[filename:join(Privdir,atom_to_list(Node)++"-seq_trace")]),
- ?line [{trace_ts,StartProc,call,{?MODULE,seq,[]},{_,_,_}},
+ [{trace_ts,StartProc,call,{?MODULE,seq,[]},{_,_,_}},
{seq_trace,0,{send,{First, Seq0},StartProc,P1Proc,SpawnRequest1}},
{seq_trace,0,{send,{Seq0, Seq1},P1Proc,StartProc,SpawnReply1}},
{seq_trace,0,{send,{Seq2, Seq3},StartProc,P2Proc,SpawnRequest2}},
@@ -726,68 +726,68 @@ diskless(suite) ->
diskless(doc) ->
["Start tracing on diskless remote node"];
diskless(Config) when is_list(Config) ->
- ?line {ok,RemoteNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"diskless"),
- ?line {ok,[RemoteNode]} =
+ {ok,RemoteNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"diskless"),
+ {ok,[RemoteNode]} =
ttb:tracer([RemoteNode],[{file, {local, File}},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,RemoteNode,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,RemoteNode,1}]} = ttb:tp(?MODULE,foo,[]),
+ {ok,[{all,[{matched,RemoteNode,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,RemoteNode,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line rpc:call(RemoteNode,?MODULE,foo,[]),
- ?line timer:sleep(5000), % needed for the IP port to flush
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(filename:join(Privdir,
+ rpc:call(RemoteNode,?MODULE,foo,[]),
+ timer:sleep(5000), % needed for the IP port to flush
+ ttb:stop([nofetch]),
+ ok = ttb:format(filename:join(Privdir,
atom_to_list(RemoteNode)++"-diskless")),
- ?line [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
diskless(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
diskless_wrap(suite) ->
[];
diskless_wrap(doc) ->
["Start tracing on diskless remote node, save to local wrapped file"];
diskless_wrap(Config) when is_list(Config) ->
- ?line {ok,RemoteNode} = test_server:start_node(node2,slave,[]),
- ?line c:nl(?MODULE),
- ?line S = self(),
- ?line Privdir=priv_dir(Config),
- ?line File = filename:join(Privdir,"diskless"),
- ?line {ok,[RemoteNode]} =
+ {ok,RemoteNode} = test_server:start_node(node2,slave,[]),
+ c:nl(?MODULE),
+ S = self(),
+ Privdir=priv_dir(Config),
+ File = filename:join(Privdir,"diskless"),
+ {ok,[RemoteNode]} =
ttb:tracer([RemoteNode],[{file, {local, {wrap,File,200,3}}},
{handler,{fun myhandler/4, S}}]),
- ?line {ok,[{all,[{matched,RemoteNode,_}]}]} = ttb:p(all,call),
- ?line {ok,[{matched,RemoteNode,1}]} = ttb:tp(?MODULE,foo,[]),
+ {ok,[{all,[{matched,RemoteNode,_}]}]} = ttb:p(all,call),
+ {ok,[{matched,RemoteNode,1}]} = ttb:tp(?MODULE,foo,[]),
- ?line rpc:call(RemoteNode,?MODULE,foo,[]),
- ?line timer:sleep(5000), % needed for the IP port to flush
- ?line ttb:stop([nofetch]),
- ?line ok = ttb:format(filename:join(Privdir,
+ rpc:call(RemoteNode,?MODULE,foo,[]),
+ timer:sleep(5000), % needed for the IP port to flush
+ ttb:stop([nofetch]),
+ ok = ttb:format(filename:join(Privdir,
atom_to_list(RemoteNode)++"-diskless.*.wrp")),
- ?line [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
+ [{trace_ts,{_,_,RemoteNode},call,{?MODULE,foo,[]},{_,_,_}},
end_of_trace] = flush(),
ok.
diskless_wrap(cleanup,_Config) ->
- ?line test_server:stop_node(ttb_helper:get_node(node2)).
+ test_server:stop_node(ttb_helper:get_node(node2)).
otp_4967_1(suite) ->
[];
otp_4967_1(doc) ->
["OTP-4967: clear flag"];
otp_4967_1(Config) when is_list(Config) ->
- ?line {ok,[Node]} = ttb:tracer(),
- ?line {ok,[{all,[{matched,Node,_}]}]} = ttb:p(all,call),
- ?line {ok,[{all,[{matched,Node,_}]}]} = ttb:p(all,clear),
- ?line stopped = ttb:stop(),
+ {ok,[Node]} = ttb:tracer(),
+ {ok,[{all,[{matched,Node,_}]}]} = ttb:p(all,call),
+ {ok,[{all,[{matched,Node,_}]}]} = ttb:p(all,clear),
+ stopped = ttb:stop(),
ok.
@@ -797,37 +797,37 @@ otp_4967_2(doc) ->
["OTP-4967: Trace message sent to {Name, Node}"];
otp_4967_2(Config) when is_list(Config) ->
io:format("1: ~p",[erlang:timestamp()]),
- ?line Privdir = priv_dir(Config),
+ Privdir = priv_dir(Config),
io:format("2: ~p",[erlang:timestamp()]),
- ?line File = filename:join(Privdir,"otp_4967"),
+ File = filename:join(Privdir,"otp_4967"),
io:format("3: ~p",[erlang:timestamp()]),
- ?line S = self(),
+ S = self(),
io:format("4: ~p",[erlang:timestamp()]),
- ?line {ok,[Node]} =
+ {ok,[Node]} =
ttb:tracer(node(),[{file, File},
{handler,{fun myhandler/4, S}}]),
io:format("5: ~p",[erlang:timestamp()]),
%% Test that delayed registration of a process works.
receive after 200 -> ok end,
- ?line register(otp_4967,self()),
+ register(otp_4967,self()),
io:format("6: ~p",[erlang:timestamp()]),
- ?line {ok,[{S,[{matched,Node,1}]}]} = ttb:p(self(),s),
+ {ok,[{S,[{matched,Node,1}]}]} = ttb:p(self(),s),
io:format("7: ~p",[erlang:timestamp()]),
- ?line {otp_4967,node()} ! heihopp,
+ {otp_4967,node()} ! heihopp,
io:format("8: ~p",[erlang:timestamp()]),
- ?line stopped = ttb:stop([format]),
+ stopped = ttb:stop([format]),
io:format("9: ~p",[erlang:timestamp()]),
- ?line Msgs = flush(),
+ Msgs = flush(),
io:format("10: ~p",[erlang:timestamp()]),
- ?line io:format("Messages received: \n~p\n",[Msgs]),
+ io:format("Messages received: \n~p\n",[Msgs]),
io:format("11: ~p",[erlang:timestamp()]),
- ?line true = lists:member(heihopp,Msgs), % the heihopp message itself
+ true = lists:member(heihopp,Msgs), % the heihopp message itself
io:format("13: ~p",[erlang:timestamp()]),
- ?line {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} =
+ {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} =
lists:keysearch(heihopp,4,Msgs), % trace trace of the heihopp message
io:format("14: ~p",[erlang:timestamp()]),
- ?line end_of_trace = lists:last(Msgs), % end of the trace
+ end_of_trace = lists:last(Msgs), % end of the trace
ok.
@@ -876,7 +876,7 @@ flush(Acc) ->
end.
foo() ->
- %% Sync between nodes is not always exact, so here is a litle timeout to
+ %% Sync between nodes is not always exact, so here is a little timeout to
%% make sure traces come i correct sequence when merging.
%% In the real world there is no way to avoid this kind of trouble
timer:sleep(100),
@@ -909,8 +909,8 @@ metatest(Proc,Node,Privdir,Filename) ->
end.
check_gone(Dir,File) ->
- ?line {ok,List} = file:list_dir(Dir),
- ?line case lists:member(File,List) of
+ {ok,List} = file:list_dir(Dir),
+ case lists:member(File,List) of
true ->
timer:sleep(2000),
{ok,NewList} = file:list_dir(Dir),
@@ -928,11 +928,11 @@ check_gone(Dir,File) ->
end.
start_client_and_server() ->
- ?line {ok,ClientNode} = test_server:start_node(client,slave,[]),
- ?line ok = ttb_helper:c(code, add_paths, [code:get_path()]),
- ?line {ok,ServerNode} = test_server:start_node(server,slave,[]),
- ?line ok = ttb_helper:s(code, add_paths, [code:get_path()]),
- ?line ttb_helper:clear(),
+ {ok,ClientNode} = test_server:start_node(client,slave,[]),
+ ok = ttb_helper:c(code, add_paths, [code:get_path()]),
+ {ok,ServerNode} = test_server:start_node(server,slave,[]),
+ ok = ttb_helper:s(code, add_paths, [code:get_path()]),
+ ttb_helper:clear(),
{ServerNode, ClientNode}.
stop_client_and_server() ->
@@ -940,8 +940,8 @@ stop_client_and_server() ->
ServerNode = ttb_helper:get_node(server),
erlang:monitor_node(ClientNode,true),
erlang:monitor_node(ServerNode,true),
- ?line test_server:stop_node(ClientNode),
- ?line test_server:stop_node(ServerNode),
+ test_server:stop_node(ClientNode),
+ test_server:stop_node(ServerNode),
wait_for_client_and_server_stop(ClientNode,ServerNode).
wait_for_client_and_server_stop(undefined,undefined) ->
@@ -957,20 +957,20 @@ wait_for_client_and_server_stop(ClientNode,ServerNode) ->
end.
begin_trace(ServerNode, ClientNode, Dest) ->
- ?line {ok, _} =
+ {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
- ?line ttb:p(all, call),
- ?line ttb:tp(server, received, []),
- ?line ttb:tp(client, put, []),
- ?line ttb:tp(client, get, []).
+ ttb:p(all, call),
+ ttb:tp(server, received, []),
+ ttb:tp(client, put, []),
+ ttb:tp(client, get, []).
begin_trace_local(ServerNode, ClientNode, Dest) ->
- ?line {ok, _} =
+ {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, Dest}]),
- ?line ttb:p(all, call),
- ?line ttb:tpl(server, received, []),
- ?line ttb:tpl(client, put, []),
- ?line ttb:tpl(client, get, []).
+ ttb:p(all, call),
+ ttb:tpl(server, received, []),
+ ttb:tpl(client, put, []),
+ ttb:tpl(client, get, []).
check_size(N, Dest, Output, ServerNode, ClientNode) ->
begin_trace(ServerNode, ClientNode, Dest),
@@ -997,16 +997,16 @@ fetch_when_no_option_given(suite) ->
fetch_when_no_option_given(doc) ->
["Fetch when no option given"];
fetch_when_no_option_given(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line {ok, Privdir} = file:get_cwd(),
- ?line [] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ {ok, Privdir} = file:get_cwd(),
+ [] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")),
begin_trace(ServerNode, ClientNode, ?FNAME),
- ?line ttb_helper:msgs(4),
- ?line stopped = ttb:stop(),
- ?line [_] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")).
+ ttb_helper:msgs(4),
+ stopped = ttb:stop(),
+ [_] = filelib:wildcard(filename:join(Privdir,"ttb_upload_temptest*")).
fetch_when_no_option_given(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
basic_ttb_run_ip_port(suite) ->
@@ -1014,123 +1014,123 @@ basic_ttb_run_ip_port(suite) ->
basic_ttb_run_ip_port(doc) ->
["Basic ttb run ip port"];
basic_ttb_run_ip_port(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line check_size(1, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
- ?line check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
- ?line check_size(10, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ check_size(1, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ check_size(10, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode).
basic_ttb_run_ip_port(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
basic_ttb_run_file_port(suite) ->
[];
basic_ttb_run_file_port(doc) ->
["Basic ttb run file port"];
basic_ttb_run_file_port(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line check_size(1, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
- ?line check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
- ?line check_size(10, ?FNAME, ?OUTPUT, ServerNode, ClientNode).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ check_size(1, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ check_size(10, ?FNAME, ?OUTPUT, ServerNode, ClientNode).
basic_ttb_run_file_port(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
return_fetch_dir_implies_fetch(suite) ->
[];
return_fetch_dir_implies_fetch(doc) ->
["Return_fetch_dir implies fetch"];
return_fetch_dir_implies_fetch(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace(ServerNode, ClientNode, ?FNAME),
- ?line ttb_helper:msgs(2),
- ?line {_,_} = ttb:stop([return_fetch_dir]).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace(ServerNode, ClientNode, ?FNAME),
+ ttb_helper:msgs(2),
+ {_,_} = ttb:stop([return_fetch_dir]).
return_fetch_dir_implies_fetch(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
logfile_name_in_fetch_dir(suite) ->
[];
logfile_name_in_fetch_dir(doc) ->
["Logfile name in fetch dir"];
logfile_name_in_fetch_dir(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
- ?line {_,Dir} = ttb:stop([return_fetch_dir]),
- ?line P1 = lists:nth(3, string:lexemes(filename:basename(Dir), "_")),
- ?line P2 = hd(string:lexemes(P1, "-")),
- ?line _File = P2.
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ {_,Dir} = ttb:stop([return_fetch_dir]),
+ P1 = lists:nth(3, string:lexemes(filename:basename(Dir), "_")),
+ P2 = hd(string:lexemes(P1, "-")),
+ _File = P2.
logfile_name_in_fetch_dir(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
upload_to_my_logdir(suite) ->
[];
upload_to_my_logdir(doc) ->
["Upload to my logdir"];
upload_to_my_logdir(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line {ok, _} =
+ {ServerNode, ClientNode} = start_client_and_server(),
+ {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
- ?line {stopped,_} = ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}]),
- ?line true = filelib:is_file(?DIRNAME),
- ?line [] = filelib:wildcard("ttb_upload_"++?FNAME).
+ {stopped,_} = ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}]),
+ true = filelib:is_file(?DIRNAME),
+ [] = filelib:wildcard("ttb_upload_"++?FNAME).
upload_to_my_logdir(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
upload_to_my_existing_logdir(suite) ->
[];
upload_to_my_existing_logdir(doc) ->
["Upload to my existing logdir"];
upload_to_my_existing_logdir(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line ok = file:make_dir(?DIRNAME),
- ?line {ok, _} =
+ {ServerNode, ClientNode} = start_client_and_server(),
+ ok = file:make_dir(?DIRNAME),
+ {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).
+ {error,_,_} = (catch ttb:stop([return_fetch_dir, {fetch_dir, ?DIRNAME}])),
+ {stopped,_} = ttb:stop(return_fetch_dir).
upload_to_my_existing_logdir(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
fetch_with_options_not_as_list(suite) ->
[];
fetch_with_options_not_as_list(doc) ->
["Fetch with options not as list"];
fetch_with_options_not_as_list(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line {ok, _} =
+ {ServerNode, ClientNode} = start_client_and_server(),
+ {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
- ?line {stopped, D} = ttb:stop(return_fetch_dir),
- ?line false = filelib:is_file(?OUTPUT),
- ?line ttb:format(D, {out, ?OUTPUT}),
- ?line true = filelib:is_file(?OUTPUT).
+ {stopped, D} = ttb:stop(return_fetch_dir),
+ false = filelib:is_file(?OUTPUT),
+ ttb:format(D, {out, ?OUTPUT}),
+ true = filelib:is_file(?OUTPUT).
fetch_with_options_not_as_list(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
error_when_formatting_multiple_files_4393(suite) ->
[];
error_when_formatting_multiple_files_4393(doc) ->
["Error when formatting multiple files"];
error_when_formatting_multiple_files_4393(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace(ServerNode, ClientNode, ?FNAME),
- ?line ttb_helper:msgs(2),
- ?line {_, Dir} = ttb:stop(return_fetch_dir),
- ?line Files = [filename:join(Dir, atom_to_list(ServerNode) ++ "-" ++ ?FNAME),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace(ServerNode, ClientNode, ?FNAME),
+ ttb_helper:msgs(2),
+ {_, Dir} = ttb:stop(return_fetch_dir),
+ Files = [filename:join(Dir, atom_to_list(ServerNode) ++ "-" ++ ?FNAME),
filename:join(Dir, atom_to_list(ClientNode) ++ "-" ++ ?FNAME)],
- ?line ok = ttb:format(Files).
+ ok = ttb:format(Files).
error_when_formatting_multiple_files_4393(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
format_on_trace_stop(suite) ->
[];
format_on_trace_stop(doc) ->
["Format on trace stop"];
format_on_trace_stop(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
- ?line ttb_helper:msgs_ip(2),
- ?line file:delete("HANDLER_OK"),
- ?line {_,_} = ttb:stop([fetch, return_fetch_dir, {format, {handler, marking_call_handler()}}]),
- ?line true = filelib:is_file("HANDLER_OK"),
- ?line ok = file:delete("HANDLER_OK").
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace(ServerNode, ClientNode, {local, ?FNAME}),
+ ttb_helper:msgs_ip(2),
+ file:delete("HANDLER_OK"),
+ {_,_} = ttb:stop([fetch, return_fetch_dir, {format, {handler, marking_call_handler()}}]),
+ true = filelib:is_file("HANDLER_OK"),
+ ok = file:delete("HANDLER_OK").
format_on_trace_stop(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
%% The following three tests are for the issue "fixes fetch fail when nodes on the same host
%% have different cwd"
@@ -1139,41 +1139,41 @@ trace_to_remote_files_on_localhost_with_different_pwd(suite) ->
trace_to_remote_files_on_localhost_with_different_pwd(doc) ->
["Trace to remote files on localhost with different pwd"];
trace_to_remote_files_on_localhost_with_different_pwd(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line ok = file:set_cwd(".."),
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
- ?line ok = file:set_cwd(OldDir).
+ {ok, OldDir} = file:get_cwd(),
+ ok = file:set_cwd(".."),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ check_size(2, ?FNAME, ?OUTPUT, ServerNode, ClientNode),
+ ok = file:set_cwd(OldDir).
trace_to_remote_files_on_localhost_with_different_pwd(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
trace_to_local_files_on_localhost_with_different_pwd(suite) ->
[];
trace_to_local_files_on_localhost_with_different_pwd(doc) ->
["Trace to local files on localhost with different pwd"];
trace_to_local_files_on_localhost_with_different_pwd(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line ok = file:set_cwd(".."),
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
- ?line ok = file:set_cwd(OldDir).
+ {ok, OldDir} = file:get_cwd(),
+ ok = file:set_cwd(".."),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ check_size(2, {local, ?FNAME}, ?OUTPUT, ServerNode, ClientNode),
+ ok = file:set_cwd(OldDir).
trace_to_local_files_on_localhost_with_different_pwd(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
trace_to_remote_files_on_localhost_with_different_pwd_abs(suite) ->
[];
trace_to_remote_files_on_localhost_with_different_pwd_abs(doc) ->
["Trace to remote files on localhost with different pwd abs"];
trace_to_remote_files_on_localhost_with_different_pwd_abs(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line ok = file:set_cwd(".."),
- ?line {ok, Path} = file:get_cwd(),
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line File = filename:join(Path, ?FNAME),
- ?line check_size(2, File, ?OUTPUT, ServerNode, ClientNode),
- ?line ok = file:set_cwd(OldDir).
+ {ok, OldDir} = file:get_cwd(),
+ ok = file:set_cwd(".."),
+ {ok, Path} = file:get_cwd(),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ File = filename:join(Path, ?FNAME),
+ check_size(2, File, ?OUTPUT, ServerNode, ClientNode),
+ ok = file:set_cwd(OldDir).
trace_to_remote_files_on_localhost_with_different_pwd_abs(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
%% Trace is not affected by changes of cwd on control node or remote nodes during tracing
%% (three tests)
@@ -1182,20 +1182,20 @@ changing_cwd_on_control_node(suite) ->
changing_cwd_on_control_node(doc) ->
["Changing cwd on control node during tracing is safe"];
changing_cwd_on_control_node(Config) when is_list(Config) ->
- ?line {ok, OldDir} = file:get_cwd(),
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace(ServerNode, ClientNode, ?FNAME),
- ?line NumMsgs = 3,
- ?line ttb_helper:msgs(NumMsgs),
- ?line ok = file:set_cwd(".."),
- ?line ttb_helper:msgs(NumMsgs),
- ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
- ?line {ok, Ret} = file:consult(?OUTPUT),
+ {ok, OldDir} = file:get_cwd(),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace(ServerNode, ClientNode, ?FNAME),
+ NumMsgs = 3,
+ ttb_helper:msgs(NumMsgs),
+ ok = file:set_cwd(".."),
+ ttb_helper:msgs(NumMsgs),
+ {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ {ok, Ret} = file:consult(?OUTPUT),
check_output(2*(NumMsgs + 1),Ret),
ok = file:set_cwd(OldDir).
changing_cwd_on_control_node(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
changing_cwd_on_control_node_with_local_trace(suite) ->
[];
@@ -1216,156 +1216,156 @@ changing_cwd_on_control_node_with_local_trace(Config) when is_list(Config) ->
check_output(Expected, Ret),
ok = file:set_cwd(OldDir).
changing_cwd_on_control_node_with_local_trace(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
changing_cwd_on_remote_node(suite) ->
[];
changing_cwd_on_remote_node(doc) ->
["Changing cwd on remote node during tracing is safe"];
changing_cwd_on_remote_node(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace(ServerNode, ClientNode, ?FNAME),
- ?line NumMsgs = 2,
- ?line ttb_helper:msgs(NumMsgs),
- ?line ok = rpc:call(ClientNode, file, set_cwd, [".."]),
- ?line ttb_helper:msgs(NumMsgs),
- ?line {_, D} = ttb:stop([fetch, return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
- ?line {ok, Ret} = file:consult(?OUTPUT),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace(ServerNode, ClientNode, ?FNAME),
+ NumMsgs = 2,
+ ttb_helper:msgs(NumMsgs),
+ ok = rpc:call(ClientNode, file, set_cwd, [".."]),
+ ttb_helper:msgs(NumMsgs),
+ {_, D} = ttb:stop([fetch, return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ {ok, Ret} = file:consult(?OUTPUT),
check_output(2*(NumMsgs + 1),Ret).
changing_cwd_on_remote_node(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
one_command_trace_setup(suite) ->
[];
one_command_trace_setup(doc) ->
["One command trace setup"];
one_command_trace_setup(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line ttb:start_trace([ClientNode, ServerNode],
+ {ServerNode, ClientNode} = start_client_and_server(),
+ 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 ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
- ?line {ok, Ret} = file:consult(?OUTPUT),
- ?line 5 = length(Ret).
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop(return_fetch_dir),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, simple_call_handler()}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ 5 = length(Ret).
one_command_trace_setup(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
dbg_style_fetch(suite) ->
[];
dbg_style_fetch(doc) ->
["Dbg style fetch"];
dbg_style_fetch(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line DirSize = length(element(2, file:list_dir("."))),
- ?line ttb:start_trace([ClientNode, ServerNode],
+ {ServerNode, ClientNode} = start_client_and_server(),
+ DirSize = length(element(2, file:list_dir("."))),
+ 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("."))),
- ?line stopped, ttb:stop(format),
+ DirSize = length(element(2, file:list_dir("."))),
+ ttb_helper:msgs(2),
+ DirSize = length(element(2, file:list_dir("."))),
+ stopped, ttb:stop(format),
%%+1 -> ttb_last_trace
- ?line true = (DirSize + 1 == length(element(2, file:list_dir(".")))),
- ?line {ok,[{all, [{matched,_,_}, {matched,_,_}]}]} =
+ true = (DirSize + 1 == length(element(2, file:list_dir(".")))),
+ {ok,[{all, [{matched,_,_}, {matched,_,_}]}]} =
ttb:start_trace([ClientNode, ServerNode],
[{server, received, '_', []},
{client, put, 1, []},
{client, get, '_', []}],
{all, call},
[{shell, only}]),
- ?line ttb:stop().
+ ttb:stop().
dbg_style_fetch(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
shell_tracing_init(suite) ->
[];
shell_tracing_init(doc) ->
["Shell tracing init"];
shell_tracing_init(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line ttb:tracer([ClientNode, ServerNode], shell),
- ?line ttb:stop(),
- ?line ttb:tracer([ClientNode, ServerNode],
+ {ServerNode, ClientNode} = start_client_and_server(),
+ ttb:tracer([ClientNode, ServerNode], shell),
+ ttb:stop(),
+ ttb:tracer([ClientNode, ServerNode],
[{file, {local, ?FNAME}}, shell]),
- ?line ttb:stop(),
- ?line local_client_required_on_shell_tracing =
+ ttb:stop(),
+ 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().
+ stop_client_and_server().
only_one_state_for_format_handler(suite) ->
[];
only_one_state_for_format_handler(doc) ->
["Only one state for format handler"];
only_one_state_for_format_handler(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_local(ServerNode, ClientNode, ?FNAME),
- ?line ttb_helper:msgs(2),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, counter_call_handler()}]),
- ?line {ok, Ret} = file:consult(?OUTPUT),
- ?line [5] = Ret.
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_local(ServerNode, ClientNode, ?FNAME),
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop([return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, counter_call_handler()}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ [5] = Ret.
only_one_state_for_format_handler(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
only_one_state_with_default_format_handler(suite) ->
[];
only_one_state_with_default_format_handler(doc) ->
["Only one state with default format handler"];
only_one_state_with_default_format_handler(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_local(ServerNode, ClientNode, ?FNAME),
- ?line ttb_helper:msgs(2),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}]),
- ?line true = filelib:is_file(?OUTPUT).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_local(ServerNode, ClientNode, ?FNAME),
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop([return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}]),
+ true = filelib:is_file(?OUTPUT).
only_one_state_with_default_format_handler(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
only_one_state_with_initial_format_handler(suite) ->
[];
only_one_state_with_initial_format_handler(doc) ->
["Only one state with initial format handler"];
only_one_state_with_initial_format_handler(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line {ok, _} =
+ {ServerNode, ClientNode} = start_client_and_server(),
+ {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}, {handler, counter_call_handler()}]),
- ?line ttb:p(all, call),
- ?line ttb:tpl(server, received, []),
- ?line ttb:tpl(client, put, []),
- ?line ttb:tpl(client, get, []),
- ?line ttb_helper:msgs(2),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}]),
- ?line {ok, Ret} = file:consult(?OUTPUT),
- ?line [5] = Ret.
+ ttb:p(all, call),
+ ttb:tpl(server, received, []),
+ ttb:tpl(client, put, []),
+ ttb:tpl(client, get, []),
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop([return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}]),
+ {ok, Ret} = file:consult(?OUTPUT),
+ [5] = Ret.
only_one_state_with_initial_format_handler(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
run_trace_with_shortcut(Shortcut, Ret, F) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line {ok, _} =
+ {ServerNode, ClientNode} = start_client_and_server(),
+ {ok, _} =
ttb:tracer([ServerNode,ClientNode],[{file, ?FNAME}]),
- ?line ttb:p(all, call),
- ?line ttb:F(client, put, Shortcut),
- ?line ttb_helper:msgs(2),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler()}]),
- ?line {ok, Ret} =file:consult(?OUTPUT),
- ?line stop_client_and_server().
+ ttb:p(all, call),
+ ttb:F(client, put, Shortcut),
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop([return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler()}]),
+ {ok, Ret} =file:consult(?OUTPUT),
+ stop_client_and_server().
fun_for(return) ->
{codestr, "fun(_) -> return_trace() end"};
@@ -1377,48 +1377,48 @@ run_trace_with_shortcut1(suite) ->
run_trace_with_shortcut1(doc) ->
["Run trace with shortcut 1"];
run_trace_with_shortcut1(Config) when is_list(Config) ->
- ?line run_trace_with_shortcut(caller, [ok,ok], tp),
- ?line run_trace_with_shortcut(caller, [ok,ok], tpl).
+ run_trace_with_shortcut(caller, [ok,ok], tp),
+ run_trace_with_shortcut(caller, [ok,ok], tpl).
run_trace_with_shortcut1(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
run_trace_with_shortcut2(suite) ->
[];
run_trace_with_shortcut2(doc) ->
["Run trace with shortcut 2"];
run_trace_with_shortcut2(Config) when is_list(Config) ->
- ?line run_trace_with_shortcut(return, [ok,ok], tp),
- ?line run_trace_with_shortcut(return, [ok,ok], tpl).
+ run_trace_with_shortcut(return, [ok,ok], tp),
+ run_trace_with_shortcut(return, [ok,ok], tpl).
run_trace_with_shortcut2(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
run_trace_with_shortcut3(suite) ->
[];
run_trace_with_shortcut3(doc) ->
["Run trace with shortcut 3"];
run_trace_with_shortcut3(Config) when is_list(Config) ->
- ?line run_trace_with_shortcut(fun_for(return), [ok,ok], tp),
- ?line run_trace_with_shortcut(fun_for(return), [ok,ok], tpl).
+ run_trace_with_shortcut(fun_for(return), [ok,ok], tp),
+ run_trace_with_shortcut(fun_for(return), [ok,ok], tpl).
run_trace_with_shortcut3(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
run_trace_with_shortcut4(suite) ->
[];
run_trace_with_shortcut4(doc) ->
["Run trace with shortcut 4"];
run_trace_with_shortcut4(Config) when is_list(Config) ->
- ?line run_trace_with_shortcut(fun_for(msg_false), [], tp),
- ?line run_trace_with_shortcut(fun_for(msg_false), [], tpl).
+ run_trace_with_shortcut(fun_for(msg_false), [], tp),
+ run_trace_with_shortcut(fun_for(msg_false), [], tpl).
run_trace_with_shortcut4(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
cant_specify_local_and_flush(suite) ->
[];
cant_specify_local_and_flush(doc) ->
["Can't specify local and flush"];
cant_specify_local_and_flush(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line flush_unsupported_with_ip_trace_port =
+ {ServerNode, ClientNode} = start_client_and_server(),
+ flush_unsupported_with_ip_trace_port =
try ttb:tracer([ServerNode, ClientNode],
[{flush, 1000}, {file, {local, ?FNAME}}])
catch
@@ -1426,37 +1426,37 @@ cant_specify_local_and_flush(Config) when is_list(Config) ->
flush_unsupported_with_ip_trace_port
end.
cant_specify_local_and_flush(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
trace_sorted_by_default(suite) ->
[];
trace_sorted_by_default(doc) ->
["Trace sorted by default"];
trace_sorted_by_default(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_local(ServerNode, ClientNode, ?FILE),
- ?line ttb_helper:msgs(2),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, false}]),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_local(ServerNode, ClientNode, ?FILE),
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop([return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, false}]),
{ok, Ret} = file:consult(?OUTPUT),
- ?line [ClientNode,ServerNode,ClientNode,ServerNode,ServerNode] = Ret.
+ [ClientNode,ServerNode,ClientNode,ServerNode,ServerNode] = Ret.
trace_sorted_by_default(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
disable_sorting(suite) ->
[];
disable_sorting(doc) ->
["Disable sorting"];
disable_sorting(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_local(ServerNode, ClientNode, ?FILE),
- ?line ttb_helper:msgs(2),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, true}]),
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_local(ServerNode, ClientNode, ?FILE),
+ ttb_helper:msgs(2),
+ {_, D} = ttb:stop([return_fetch_dir]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, node_call_handler()}, {disable_sort, true}]),
{ok, Ret} = file:consult(?OUTPUT),
- ?line [ClientNode,ClientNode,ServerNode,ServerNode,ServerNode] = Ret.
+ [ClientNode,ClientNode,ServerNode,ServerNode,ServerNode] = Ret.
disable_sorting(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
%% -----------------------------------------------------------------------------
%% tests for autoresume of tracing
@@ -1467,71 +1467,71 @@ trace_resumed_after_node_restart(suite) ->
trace_resumed_after_node_restart(doc) ->
["Test trace resumed after node restart, trace to files on remote node."];
trace_resumed_after_node_restart(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_with_resume(ServerNode, ClientNode, ?FNAME),
- ?line logic(2,6,file).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_with_resume(ServerNode, ClientNode, ?FNAME),
+ logic(2,6,file).
trace_resumed_after_node_restart(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
trace_resumed_after_node_restart_ip(suite) ->
[];
trace_resumed_after_node_restart_ip(doc) ->
["Test trace resumed after node restart, trace via tcp/ip to local node."];
trace_resumed_after_node_restart_ip(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_with_resume(ServerNode, ClientNode, {local, ?FNAME}),
- ?line logic(2,6,local).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_with_resume(ServerNode, ClientNode, {local, ?FNAME}),
+ logic(2,6,local).
trace_resumed_after_node_restart_ip(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
trace_resumed_after_node_restart_wrap(suite) ->
[];
trace_resumed_after_node_restart_wrap(doc) ->
["Test trace resumed after node restart, wrap option."];
trace_resumed_after_node_restart_wrap(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
- ?line logic(1,4,file).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
+ logic(1,4,file).
trace_resumed_after_node_restart_wrap(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
trace_resumed_after_node_restart_wrap_mult(suite) ->
[];
trace_resumed_after_node_restart_wrap_mult(doc) ->
["Test trace resumed after node restart, wrap option, multiple files."];
trace_resumed_after_node_restart_wrap_mult(Config) when is_list(Config) ->
- ?line {ServerNode, ClientNode} = start_client_and_server(),
- ?line begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
- ?line logic(20,8,file).
+ {ServerNode, ClientNode} = start_client_and_server(),
+ begin_trace_with_resume(ServerNode, ClientNode, {wrap, ?FNAME, 10, 4}),
+ logic(20,8,file).
trace_resumed_after_node_restart_wrap_mult(cleanup,_Config) ->
- ?line stop_client_and_server().
+ stop_client_and_server().
logic(N, M, TracingType) ->
helper_msgs(N, TracingType),
test_server:stop_node(ttb_helper:get_node(client)),
timer:sleep(2500),
- ?line {ok,_ClientNode} = test_server:start_node(client,slave,[]),
+ {ok,_ClientNode} = test_server:start_node(client,slave,[]),
ct:log("client started",[]),
- ?line ok = ttb_helper:c(code, add_paths, [code:get_path()]),
+ ok = ttb_helper:c(code, add_paths, [code:get_path()]),
ct:log("paths added",[]),
- ?line ttb_helper:c(client, init, []),
+ ttb_helper:c(client, init, []),
ct:log("client initiated",[]),
- ?line helper_msgs(N, TracingType),
+ helper_msgs(N, TracingType),
ct:log("helper msgs sent and flushed",[]),
- ?line {_, D} = ttb:stop([return_fetch_dir]),
+ {_, D} = ttb:stop([return_fetch_dir]),
ct:log("stopped ~p",[D]),
- ?line ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler2()}]),
+ ttb:format(D, [{out, ?OUTPUT}, {handler, ret_caller_call_handler2()}]),
ct:log("formatted ~p",[{D,?OUTPUT}]),
- ?line {ok, Ret} = file:consult(?OUTPUT),
+ {ok, Ret} = file:consult(?OUTPUT),
ct:log("consulted: ~p",[Ret]),
check_output(M,Ret).
begin_trace_with_resume(ServerNode, ClientNode, Dest) ->
- ?line {ok, _} = ttb:tracer([ServerNode,ClientNode], [{file, Dest}, resume]),
- ?line ttb:p(all, [call, timestamp]),
- ?line ttb:tp(server, received, []),
- ?line ttb:tp(client, put, []),
- ?line ttb:tp(client, get, []).
+ {ok, _} = ttb:tracer([ServerNode,ClientNode], [{file, Dest}, resume]),
+ ttb:p(all, [call, timestamp]),
+ ttb:tp(server, received, []),
+ ttb:tp(client, put, []),
+ ttb:tp(client, get, []).
ret_caller_call_handler2() ->
{fun(A, {trace_ts, _, call, _, _} ,_,_) -> io:format(A, "ok.~n", []);
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 5ea7b062fc..2a308d0c55 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 2.11.1
+OBSERVER_VSN = 2.14
diff --git a/lib/odbc/configure b/lib/odbc/configure
index a167f1b0ec..e429e5a946 100755
--- a/lib/odbc/configure
+++ b/lib/odbc/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +430,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +459,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +503,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +517,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +534,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,50 +606,46 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
ac_unique_file="c_src/odbcserver.c"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
ODBC_INCLUDE
@@ -629,7 +656,6 @@ THR_DEFS
GETCONF
EGREP
GREP
-CPP
RM
LD
SET_MAKE
@@ -642,6 +668,10 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -702,8 +732,7 @@ CC
CFLAGS
LDFLAGS
LIBS
-CPPFLAGS
-CPP'
+CPPFLAGS'
# Initialize some variables set by options.
@@ -772,8 +801,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -814,9 +841,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -840,9 +867,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1053,9 +1080,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1069,9 +1096,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1115,9 +1142,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1133,7 +1160,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1197,7 +1224,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1315,6 +1342,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1344,7 +1372,6 @@ Some influential environment variables:
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1365,9 +1392,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1395,7 +1422,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1403,7 +1431,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1413,9 +1441,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1432,14 +1460,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1447,14 +1475,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1470,14 +1499,14 @@ fi
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1485,17 +1514,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1516,11 +1546,12 @@ fi
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -1528,16 +1559,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -1555,194 +1579,29 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
-ac_fn_c_try_run ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
- { { case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
- ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=$ac_status
-fi
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_run
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
@@ -1750,26 +1609,28 @@ fi
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
@@ -1781,17 +1642,18 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof ($2))
return 0;
@@ -1799,12 +1661,13 @@ if (sizeof ($2))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof (($2)))
return 0;
@@ -1812,18 +1675,19 @@ if (sizeof (($2)))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
eval "$3=yes"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
@@ -1835,16 +1699,17 @@ $as_echo "$ac_res" >&6; }
ac_fn_c_check_member ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
-$as_echo_n "checking for $2.$3... " >&6; }
-if eval \${$4+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+printf %s "checking for $2.$3... " >&6; }
+if eval test \${$4+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
-main ()
+main (void)
{
static $2 ac_aggr;
if (ac_aggr.$3)
@@ -1853,14 +1718,15 @@ return 0;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$4=yes"
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
-main ()
+main (void)
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
@@ -1869,22 +1735,66 @@ return 0;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$4=yes"
-else
+else $as_nop
eval "$4=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$4
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_member
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@@ -1899,7 +1809,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -1909,14 +1819,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1926,9 +1837,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -1936,14 +1848,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -1953,14 +1865,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -1970,9 +1883,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -1980,14 +1894,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -1995,7 +1909,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2005,12 +1919,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -2020,12 +1935,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -2053,9 +1968,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -2067,14 +1983,34 @@ rm -f conftest.val
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2107,8 +2043,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2143,7 +2083,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2178,11 +2118,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2193,8 +2135,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2218,7 +2160,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2226,14 +2168,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2241,15 +2183,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2257,8 +2199,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2272,63 +2214,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2338,19 +2265,434 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2361,12 +2703,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2375,24 +2717,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2402,11 +2744,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2420,57 +2763,125 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in ${ERL_TOP}/erts/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in ${ERL_TOP}/erts/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2489,21 +2900,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2522,22 +2934,116 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
-# Check whether --with-odbc was given.
-if test "${with_odbc+set}" = set; then :
- withval=$with_odbc;
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
fi
-if test "$with_odbc" = "no"; then
- rm -f "$ERL_TOP/lib/odbc/SKIP"
+# Check whether --with-odbc was given.
+if test ${with_odbc+y}
+then :
+ withval=$with_odbc;
+fi
+
-else
erl_xcomp_without_sysroot=no
if test "$cross_compiling" = "yes"; then
@@ -2549,6 +3055,15 @@ else
fi
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2557,11 +3072,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2569,11 +3085,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2584,11 +3104,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2597,11 +3117,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2609,11 +3130,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2624,11 +3149,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2636,8 +3161,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2650,11 +3175,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2662,11 +3188,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2677,11 +3207,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2690,11 +3220,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2703,15 +3234,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2727,18 +3262,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2749,11 +3284,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2761,11 +3297,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2776,11 +3316,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2793,11 +3333,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2805,11 +3346,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2820,11 +3365,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2836,8 +3381,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2845,25 +3390,129 @@ esac
fi
fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -2873,7 +3522,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -2881,7 +3530,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2893,9 +3542,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -2916,11 +3565,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -2937,7 +3587,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -2953,44 +3603,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -3004,15 +3656,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -3021,7 +3673,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3033,8 +3685,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -3042,10 +3694,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -3053,39 +3705,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3099,11 +3752,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -3112,31 +3766,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3146,29 +3801,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3177,57 +3836,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3242,94 +3904,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3350,123 +4062,124 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
-$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
set x ${MAKE-make}
-ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
-if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval test \${ac_cv_prog_make_${ac_make}_set+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat >conftest.make <<\_ACEOF
SHELL = /bin/sh
all:
@@ -3482,12 +4195,12 @@ esac
rm -f conftest.make
fi
if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
SET_MAKE=
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
SET_MAKE="MAKE=${MAKE-make}"
fi
@@ -3496,11 +4209,12 @@ for ac_prog in ld.sh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$LD"; then
ac_cv_prog_LD="$LD" # Let the user override the test.
else
@@ -3508,11 +4222,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LD="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3523,11 +4241,11 @@ fi
fi
LD=$ac_cv_prog_LD
if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3537,11 +4255,12 @@ done
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$LD"; then
ac_cv_prog_LD="$LD" # Let the user override the test.
else
@@ -3549,11 +4268,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3564,11 +4287,11 @@ fi
fi
LD=$ac_cv_prog_LD
if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3577,11 +4300,12 @@ if test -z "$ac_cv_prog_LD"; then
ac_ct_LD=$LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_LD"; then
ac_cv_prog_ac_ct_LD="$ac_ct_LD" # Let the user override the test.
else
@@ -3589,11 +4313,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3604,11 +4332,11 @@ fi
fi
ac_ct_LD=$ac_cv_prog_ac_ct_LD
if test -n "$ac_ct_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5
-$as_echo "$ac_ct_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5
+printf "%s\n" "$ac_ct_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_LD" = x; then
@@ -3616,8 +4344,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
LD=$ac_ct_LD
@@ -3633,11 +4361,12 @@ _search_path=/bin:/usr/bin:/usr/local/bin:$PATH
# Extract the first word of "rm", so it can be a program name with args.
set dummy rm; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_RM+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_RM+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $RM in
[\\/]* | ?:[\\/]*)
ac_cv_path_RM="$RM" # Let the user override the test with a path.
@@ -3647,11 +4376,15 @@ else
for as_dir in $_search_path
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_RM="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3664,11 +4397,11 @@ esac
fi
RM=$ac_cv_path_RM
if test -n "$RM"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5
-$as_echo "$RM" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RM" >&5
+printf "%s\n" "$RM" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3679,6 +4412,115 @@ fi
_search_path=
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
+do
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
+ fi
+done
+
+
+
+
+
+
+
+
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
+
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+if test "$with_odbc" = "no"
+then :
+
+
+ rm -f "$ERL_TOP/lib/odbc/SKIP"
+
+
+else $as_nop
+
+
+
# Sockets
#--------------------------------------------------------------------
# Check for the existence of the -lsocket and -lnsl libraries.
@@ -3698,20 +4540,23 @@ _search_path=
# if -lsocket doesn't work by itself.
#--------------------------------------------------------------------
erl_checkBoth=0
-
ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
-if test "x$ac_cv_func_connect" = xyes; then :
+if test "x$ac_cv_func_connect" = xyes
+then :
erl_checkSocket=0
-else
+else $as_nop
erl_checkSocket=1
fi
-if test "$erl_checkSocket" = 1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
-$as_echo_n "checking for socket in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_socket+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "$erl_checkSocket" = 1
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
+printf %s "checking for socket in -lsocket... " >&6; }
+if test ${ac_cv_lib_socket_socket+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3720,56 +4565,62 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char socket ();
int
-main ()
+main (void)
{
return socket ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_socket_socket=yes
-else
+else $as_nop
ac_cv_lib_socket_socket=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
-$as_echo "$ac_cv_lib_socket_socket" >&6; }
-if test "x$ac_cv_lib_socket_socket" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
+printf "%s\n" "$ac_cv_lib_socket_socket" >&6; }
+if test "x$ac_cv_lib_socket_socket" = xyes
+then :
LIBS="$LIBS -lsocket"
-else
+else $as_nop
erl_checkBoth=1
fi
+
fi
-if test "$erl_checkBoth" = 1; then
+if test "$erl_checkBoth" = 1
+then :
+
tk_oldLibs=$LIBS
LIBS="$LIBS -lsocket -lnsl"
ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
-if test "x$ac_cv_func_accept" = xyes; then :
+if test "x$ac_cv_func_accept" = xyes
+then :
odbc_erl_checkNsl=0
-else
+else $as_nop
LIBS=$tk_oldLibs
fi
+
fi
ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
-if test "x$ac_cv_func_gethostbyname" = xyes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
-$as_echo_n "checking for main in -lnsl... " >&6; }
-if ${ac_cv_lib_nsl_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test "x$ac_cv_func_gethostbyname" = xyes
+then :
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
+printf %s "checking for main in -lnsl... " >&6; }
+if test ${ac_cv_lib_nsl_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lnsl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3777,37 +4628,41 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_nsl_main=yes
-else
+else $as_nop
ac_cv_lib_nsl_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
-$as_echo "$ac_cv_lib_nsl_main" >&6; }
-if test "x$ac_cv_lib_nsl_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
+printf "%s\n" "$ac_cv_lib_nsl_main" >&6; }
+if test "x$ac_cv_lib_nsl_main" = xyes
+then :
LIBS="$LIBS -lnsl"
fi
fi
-case "$host_os" in
- haiku*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5
-$as_echo_n "checking for socket in -lnetwork... " >&6; }
-if ${ac_cv_lib_network_socket+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+case "$host_os" in #(
+ haiku*) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5
+printf %s "checking for socket in -lnetwork... " >&6; }
+if test ${ac_cv_lib_network_socket+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lnetwork $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -3816,247 +4671,47 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char socket ();
int
-main ()
+main (void)
{
return socket ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_network_socket=yes
-else
+else $as_nop
ac_cv_lib_network_socket=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5
-$as_echo "$ac_cv_lib_network_socket" >&6; }
-if test "x$ac_cv_lib_network_socket" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNETWORK 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5
+printf "%s\n" "$ac_cv_lib_network_socket" >&6; }
+if test "x$ac_cv_lib_network_socket" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBNETWORK 1" >>confdefs.h
LIBS="-lnetwork $LIBS"
fi
- ;;
-esac
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+ ;; #(
+ *) :
+ ;;
esac
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
then ac_cv_path_EGREP="$GREP -E"
else
@@ -4067,10 +4722,15 @@ else
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
@@ -4079,13 +4739,13 @@ case `"$ac_path_EGREP" --version 2>&1` in
ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
*)
ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
+ printf %s 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
"$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
@@ -4114,195 +4774,87 @@ fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
EGREP="$ac_cv_path_EGREP"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-int
-main ()
-{
+ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcntl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default"
+if test "x$ac_cv_header_netdb_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
fi
-rm -f conftest*
+ac_fn_c_check_header_compile "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_STDLIB_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
+if test "x$ac_cv_header_string_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
fi
-rm -f conftest*
+ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_socket_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h
fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-for ac_header in fcntl.h netdb.h stdlib.h string.h sys/socket.h winsock2.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default"
+if test "x$ac_cv_header_winsock2_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_WINSOCK2_H 1" >>confdefs.h
fi
-done
-
-for ac_header in windows.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default"
-if test "x$ac_cv_header_windows_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_WINDOWS_H 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default"
+if test "x$ac_cv_header_windows_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h
fi
-done
-
-for ac_header in sql.h sqlext.h
+ for ac_header in sql.h sqlext.h
do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
odbc_required_headers=yes
-else
+else $as_nop
odbc_required_headers=no
fi
done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
-$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
-if ${ac_cv_c_const+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+printf %s "checking for an ANSI C-conforming const... " >&6; }
+if test ${ac_cv_c_const+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __cplusplus
@@ -4315,7 +4867,7 @@ main ()
/* NEC SVR4.0.2 mips cc rejects this. */
struct point {int x, y;};
static struct point const zero = {0,0};
- /* AIX XL C 1.02.0.0 rejects this.
+ /* IBM XL C 1.02.0.0 rejects this.
It does not let you subtract one const X* pointer from another in
an arm of an if-expression whose if-part is not a constant
expression */
@@ -4343,7 +4895,7 @@ main ()
iptr p = 0;
++p;
}
- { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
+ { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying
"k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
struct s { int j; const int *ap[3]; } bx;
struct s *b = &bx; b->j = 5;
@@ -4359,29 +4911,29 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_c_const=yes
-else
+else $as_nop
ac_cv_c_const=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
-$as_echo "$ac_cv_c_const" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+printf "%s\n" "$ac_cv_c_const" >&6; }
if test $ac_cv_c_const = no; then
-$as_echo "#define const /**/" >>confdefs.h
+printf "%s\n" "#define const /**/" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
-if test "x$ac_cv_type_size_t" = xyes; then :
+if test "x$ac_cv_type_size_t" = xyes
+then :
-else
+else $as_nop
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
-_ACEOF
+printf "%s\n" "#define size_t unsigned int" >>confdefs.h
fi
@@ -4392,27 +4944,27 @@ ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_addr" "ac_cv_member_s
#include <netinet/in.h>
#endif
"
-if test "x$ac_cv_member_struct_sockaddr_in6_sin6_addr" = xyes; then :
+if test "x$ac_cv_member_struct_sockaddr_in6_sin6_addr" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_ADDR 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_ADDR 1" >>confdefs.h
fi
-for ac_func in memset socket
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset"
+if test "x$ac_cv_func_memset" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMSET 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket"
+if test "x$ac_cv_func_socket" = xyes
+then :
+ printf "%s\n" "#define HAVE_SOCKET 1" >>confdefs.h
fi
-done
# ODBC
@@ -4422,29 +4974,34 @@ $RM -f "$ERL_TOP/lib/odbc/SKIP"
NEED_NPTL_PTHREAD_H=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
-$as_echo_n "checking for native win32 threads... " >&6; }
-if test "X$host_os" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
+printf %s "checking for native win32 threads... " >&6; }
+if test "X$host_os" = "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
THR_LIB_TYPE=posix_unknown
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4453,40 +5010,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pthread_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_pthread_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
THR_LIBS="-lpthread"
fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
-$as_echo_n "checking for pthread_create in -lc_r... " >&6; }
-if ${ac_cv_lib_c_r_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
+printf %s "checking for pthread_create in -lc_r... " >&6; }
+if test ${ac_cv_lib_c_r_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4495,96 +5054,112 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_c_r_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_c_r_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
-$as_echo "$ac_cv_lib_c_r_pthread_create" >&6; }
-if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_c_r_pthread_create" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_create" = xyes
+then :
THR_LIBS="-lc_r"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
-if test "x$ac_cv_func_pthread_create" = xyes; then :
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes
+then :
THR_LIBS="none_needed"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
-$as_echo_n "checking if the '-pthread' switch can be used... " >&6; }
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
+printf %s "checking if the '-pthread' switch can be used... " >&6; }
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -pthread"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_create((void*)0,(void*)0,(void*)0,(void*)0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
THR_DEFS="-pthread"
THR_LIBS="-pthread"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_cflags
if test "x$THR_LIBS" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- fi
- if test "x$THR_LIBS" != "x"; then
+fi
+
+ if test "x$THR_LIBS" != "x"
+then :
+
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ case $host_os in #(
+ solaris*) :
+
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ;; #(
+ linux*) :
+
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
-if test "$cross_compiling" != "yes"; then
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -4592,11 +5167,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4608,23 +5187,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -4632,11 +5214,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4648,25 +5234,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -4677,11 +5266,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4693,11 +5286,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4706,11 +5299,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -4721,11 +5315,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4737,11 +5335,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -4749,8 +5347,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -4759,11 +5357,13 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
-$as_echo_n "checking for Native POSIX Thread Library... " >&6; }
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
+printf %s "checking for Native POSIX Thread Library... " >&6; }
libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
if test $? -eq 0; then
case "$libpthr_vsn" in
@@ -4779,24 +5379,28 @@ $as_echo_n "checking for Native POSIX Thread Library... " >&6; }
else
nptl=no
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
-$as_echo "$nptl" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
+printf "%s\n" "$nptl" >&6; }
if test $nptl = cross; then
nptl=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
- if test $nptl = yes; then
+ if test $nptl = yes
+then :
+
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- ac_fn_c_check_header_mongrel "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_nptl_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_nptl_pthread_h" = xyes
+then :
need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes
fi
+ if test $need_nptl_incldir = yes
+then :
- if test $need_nptl_incldir = yes; then
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -4817,13 +5421,13 @@ fi
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
nptl_incldir=$dir/nptl
fi
-
if test "x$nptl_incldir" != "x"; then
THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
break
@@ -4832,38 +5436,43 @@ fi
if test "x$nptl_incldir" = "x"; then
as_fn_error $? "Failed to locate nptl system include directory" "$LINENO" 5
fi
- fi
- fi
- ;;
- *) ;;
- esac
+
+fi
+
+fi
+ ;; #(
+ *) :
+ ;;
+esac
saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $THR_DEFS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
-$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
CPPFLAGS=$saved_cppflags
- fi
+
+fi
+
fi
@@ -4872,8 +5481,9 @@ fi
odbc_lib_link_success=no
- case $host_os in
- darwin1[0-9].*)
+case $host_os in #(
+ darwin1[0-9].*) :
+
TARGET_FLAGS="-DUNIX"
if test ! -d "$with_odbc" || test "$with_odbc" = "yes"; then
ODBC_LIB= -L"/usr/local/lib"
@@ -4883,11 +5493,12 @@ odbc_lib_link_success=no
ODBC_INCLUDE="-I$with_odbc/include"
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -liodbc" >&5
-$as_echo_n "checking for SQLAllocHandle in -liodbc... " >&6; }
-if ${ac_cv_lib_iodbc_SQLAllocHandle+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -liodbc" >&5
+printf %s "checking for SQLAllocHandle in -liodbc... " >&6; }
+if test ${ac_cv_lib_iodbc_SQLAllocHandle+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-liodbc $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4896,43 +5507,44 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char SQLAllocHandle ();
int
-main ()
+main (void)
{
return SQLAllocHandle ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_iodbc_SQLAllocHandle=yes
-else
+else $as_nop
ac_cv_lib_iodbc_SQLAllocHandle=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iodbc_SQLAllocHandle" >&5
-$as_echo "$ac_cv_lib_iodbc_SQLAllocHandle" >&6; }
-if test "x$ac_cv_lib_iodbc_SQLAllocHandle" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iodbc_SQLAllocHandle" >&5
+printf "%s\n" "$ac_cv_lib_iodbc_SQLAllocHandle" >&6; }
+if test "x$ac_cv_lib_iodbc_SQLAllocHandle" = xyes
+then :
ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes
fi
- ;;
- haiku*)
+ ;; #(
+ haiku*) :
+
TARGET_FLAGS="-DUNIX"
ODBC_LIB= -L"/system/lib"
ODBC_INCLUDE="-I/system/develop/headers"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -lodbc" >&5
-$as_echo_n "checking for SQLAllocHandle in -lodbc... " >&6; }
-if ${ac_cv_lib_odbc_SQLAllocHandle+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -lodbc" >&5
+printf %s "checking for SQLAllocHandle in -lodbc... " >&6; }
+if test ${ac_cv_lib_odbc_SQLAllocHandle+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lodbc $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4941,41 +5553,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char SQLAllocHandle ();
int
-main ()
+main (void)
{
return SQLAllocHandle ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_odbc_SQLAllocHandle=yes
-else
+else $as_nop
ac_cv_lib_odbc_SQLAllocHandle=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLAllocHandle" >&5
-$as_echo "$ac_cv_lib_odbc_SQLAllocHandle" >&6; }
-if test "x$ac_cv_lib_odbc_SQLAllocHandle" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLAllocHandle" >&5
+printf "%s\n" "$ac_cv_lib_odbc_SQLAllocHandle" >&6; }
+if test "x$ac_cv_lib_odbc_SQLAllocHandle" = xyes
+then :
ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes
fi
- ;;
- win32|cygwin)
+ ;; #(
+ win32|cygwin) :
+
TARGET_FLAGS="-DWIN32"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lws2_32" >&5
-$as_echo_n "checking for main in -lws2_32... " >&6; }
-if ${ac_cv_lib_ws2_32_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lws2_32" >&5
+printf %s "checking for main in -lws2_32... " >&6; }
+if test ${ac_cv_lib_ws2_32_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lws2_32 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -4983,28 +5596,28 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_ws2_32_main=yes
-else
+else $as_nop
ac_cv_lib_ws2_32_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ws2_32_main" >&5
-$as_echo "$ac_cv_lib_ws2_32_main" >&6; }
-if test "x$ac_cv_lib_ws2_32_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBWS2_32 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ws2_32_main" >&5
+printf "%s\n" "$ac_cv_lib_ws2_32_main" >&6; }
+if test "x$ac_cv_lib_ws2_32_main" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBWS2_32 1" >>confdefs.h
LIBS="-lws2_32 $LIBS"
@@ -5017,11 +5630,12 @@ fi
ODBC_LIB=-L"$with_odbc/lib"
ODBC_INCLUDE="-I$with_odbc/include"
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lodbc32" >&5
-$as_echo_n "checking for main in -lodbc32... " >&6; }
-if ${ac_cv_lib_odbc32_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lodbc32" >&5
+printf %s "checking for main in -lodbc32... " >&6; }
+if test ${ac_cv_lib_odbc32_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lodbc32 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5029,55 +5643,62 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_odbc32_main=yes
-else
+else $as_nop
ac_cv_lib_odbc32_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc32_main" >&5
-$as_echo "$ac_cv_lib_odbc32_main" >&6; }
-if test "x$ac_cv_lib_odbc32_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc32_main" >&5
+printf "%s\n" "$ac_cv_lib_odbc32_main" >&6; }
+if test "x$ac_cv_lib_odbc32_main" = xyes
+then :
ODBC_LIB="$ODBC_LIB -lodbc32"; odbc_lib_link_success=yes
fi
- ;;
- *)
+ ;; #(
+ *) :
+
TARGET_FLAGS="-DUNIX"
- case "$erl_xcomp_without_sysroot-$with_odbc" in
- yes-yes | yes- )
+ case "$erl_xcomp_without_sysroot-$with_odbc" in #(
+ yes-yes | yes-) :
+
msg="Dont know where to search for odbc (setting erl_xcomp_sysroot will help)"
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $msg" >&5
-$as_echo "$as_me: WARNING: $msg" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $msg" >&5
+printf "%s\n" "$as_me: WARNING: $msg" >&2;}
echo "$msg" > "$ERL_TOP/lib/odbc/SKIP"
odbc_lib_link_success=wont_try
- ;;
- no-yes | no- )
+ ;; #(
+ no-yes | no-) :
+
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -5086,18 +5707,16 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for odbc in standard locations" >&5
-$as_echo_n "checking for odbc in standard locations... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for odbc in standard locations" >&5
+printf %s "checking for odbc in standard locations... " >&6; }
for rdir in /usr/local/odbc /usr/local /usr/odbc \
/usr /opt/local/pgm/odbc /usr/local/pgm/odbc \
"$with_odbc"; do
@@ -5116,19 +5735,20 @@ $as_echo_n "checking for odbc in standard locations... " >&6; }
break
done
if test "x$is_odbc_std_location" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No odbc library found skipping odbc" >&5
-$as_echo "$as_me: WARNING: No odbc library found skipping odbc" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No odbc library found skipping odbc" >&5
+printf "%s\n" "$as_me: WARNING: No odbc library found skipping odbc" >&2;}
echo "No odbc library found" > "$ERL_TOP/lib/odbc/SKIP"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ODBC_LIB" >&5
-$as_echo "$ODBC_LIB" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -lodbc" >&5
-$as_echo_n "checking for SQLAllocHandle in -lodbc... " >&6; }
-if ${ac_cv_lib_odbc_SQLAllocHandle+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ODBC_LIB" >&5
+printf "%s\n" "$ODBC_LIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -lodbc" >&5
+printf %s "checking for SQLAllocHandle in -lodbc... " >&6; }
+if test ${ac_cv_lib_odbc_SQLAllocHandle+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lodbc $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5137,44 +5757,44 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char SQLAllocHandle ();
int
-main ()
+main (void)
{
return SQLAllocHandle ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_odbc_SQLAllocHandle=yes
-else
+else $as_nop
ac_cv_lib_odbc_SQLAllocHandle=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLAllocHandle" >&5
-$as_echo "$ac_cv_lib_odbc_SQLAllocHandle" >&6; }
-if test "x$ac_cv_lib_odbc_SQLAllocHandle" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLAllocHandle" >&5
+printf "%s\n" "$ac_cv_lib_odbc_SQLAllocHandle" >&6; }
+if test "x$ac_cv_lib_odbc_SQLAllocHandle" = xyes
+then :
ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes
fi
fi
- ;;
+ ;; #(
+ *) :
- *)
ODBC_LIB=-L"$with_odbc/lib"
ODBC_INCLUDE="-I$with_odbc/include"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -lodbc" >&5
-$as_echo_n "checking for SQLAllocHandle in -lodbc... " >&6; }
-if ${ac_cv_lib_odbc_SQLAllocHandle+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SQLAllocHandle in -lodbc" >&5
+printf %s "checking for SQLAllocHandle in -lodbc... " >&6; }
+if test ${ac_cv_lib_odbc_SQLAllocHandle+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lodbc $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5183,93 +5803,103 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char SQLAllocHandle ();
int
-main ()
+main (void)
{
return SQLAllocHandle ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_odbc_SQLAllocHandle=yes
-else
+else $as_nop
ac_cv_lib_odbc_SQLAllocHandle=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLAllocHandle" >&5
-$as_echo "$ac_cv_lib_odbc_SQLAllocHandle" >&6; }
-if test "x$ac_cv_lib_odbc_SQLAllocHandle" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odbc_SQLAllocHandle" >&5
+printf "%s\n" "$ac_cv_lib_odbc_SQLAllocHandle" >&6; }
+if test "x$ac_cv_lib_odbc_SQLAllocHandle" = xyes
+then :
ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes
fi
- ;;
- esac
- ;;
+ ;;
+esac
+ ;;
esac
if test $odbc_required_headers = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"ODBC library - header check failed\"" >&5
-$as_echo "$as_me: WARNING: \"ODBC library - header check failed\"" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: \"ODBC library - header check failed\"" >&5
+printf "%s\n" "$as_me: WARNING: \"ODBC library - header check failed\"" >&2;}
echo "ODBC library - header check failed" > $ERL_TOP/lib/odbc/SKIP
fi
if test $odbc_lib_link_success = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"ODBC library - link check failed\"" >&5
-$as_echo "$as_me: WARNING: \"ODBC library - link check failed\"" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: \"ODBC library - link check failed\"" >&5
+printf "%s\n" "$as_me: WARNING: \"ODBC library - link check failed\"" >&2;}
echo "ODBC library - link check failed" > $ERL_TOP/lib/odbc/SKIP
fi
+
fi
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Treat certain GCC warnings as errors
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="-Werror=return-type $CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
fi
# Check whether --enable-sanitizers was given.
-if test "${enable_sanitizers+set}" = set; then :
+if test ${enable_sanitizers+y}
+then :
enableval=$enable_sanitizers;
case "$enableval" in
no) sanitizers= ;;
@@ -5311,8 +5941,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -5342,15 +5972,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -5364,8 +5994,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -5418,7 +6048,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -5434,8 +6064,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -5458,14 +6088,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -5475,46 +6107,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -5523,13 +6155,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -5538,8 +6163,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -5551,30 +6180,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -5587,13 +6196,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -5620,18 +6230,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -5643,12 +6255,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -5679,7 +6292,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -5701,6 +6314,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -5714,6 +6331,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -5755,7 +6378,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -5764,7 +6387,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -5827,7 +6450,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -5876,14 +6499,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -5920,21 +6545,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -5962,7 +6587,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -5976,7 +6601,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -6001,7 +6626,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -6229,7 +6854,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -6237,17 +6862,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -6264,7 +6889,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6288,9 +6913,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -6343,8 +6968,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -6386,9 +7011,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -6435,7 +7060,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/odbc/configure.in b/lib/odbc/configure.ac
index f11eb70796..dfc3a6ec04 100644
--- a/lib/odbc/configure.in
+++ b/lib/odbc/configure.ac
@@ -23,27 +23,21 @@ dnl define([AC_CACHE_SAVE], )dnl
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(c_src/odbcserver.c)
+AC_INIT
+AC_CONFIG_SRCDIR([c_src/odbcserver.c])
+AC_PREREQ([2.71])
-AC_CONFIG_AUX_DIRS(${ERL_TOP}/erts/autoconf)
+m4_include([otp.m4])
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
+
+ERL_CANONICAL_SYSTEM_TYPE
AC_ARG_WITH(odbc,
[ --with-odbc=PATH specify location of ODBC include and lib
--with-odbc use ODBC (default)
--without-odbc don't use ODBC])
-if test "$with_odbc" = "no"; then
-
- rm -f "$ERL_TOP/lib/odbc/SKIP"
-
-else dnl "$with_odbc" != "no"
-
ERL_XCOMP_SYSROOT_INIT
dnl Checks for programs.
@@ -70,6 +64,15 @@ fi
_search_path=
+AS_IF([test "$with_odbc" = "no"],
+ [
+
+ rm -f "$ERL_TOP/lib/odbc/SKIP"
+
+ ],
+ [
+ dnl "$with_odbc" != "no"
+
# Sockets
#--------------------------------------------------------------------
@@ -91,23 +94,27 @@ _search_path=
#--------------------------------------------------------------------
erl_checkBoth=0
AC_CHECK_FUNC(connect, erl_checkSocket=0, erl_checkSocket=1)
-if test "$erl_checkSocket" = 1; then
+AS_IF([test "$erl_checkSocket" = 1],
+ [
AC_CHECK_LIB(socket, socket, LIBS="$LIBS -lsocket", erl_checkBoth=1)
-fi
-if test "$erl_checkBoth" = 1; then
+ ])
+AS_IF([test "$erl_checkBoth" = 1],
+ [
tk_oldLibs=$LIBS
LIBS="$LIBS -lsocket -lnsl"
AC_CHECK_FUNC(accept, odbc_erl_checkNsl=0, [LIBS=$tk_oldLibs])
-fi
+ ])
AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"]))
-case "$host_os" in
- haiku*)
+AS_CASE(["$host_os"],
+ [haiku*],
+ [
AC_CHECK_LIB(network, socket)
- ;;
-esac
+ ])
dnl Checks for header files.
-AC_HEADER_STDC
+AC_CHECK_INCLUDES_DEFAULT
+AC_PROG_EGREP
+
AC_CHECK_HEADERS([fcntl.h netdb.h stdlib.h string.h sys/socket.h winsock2.h])
AC_CHECK_HEADERS([windows.h])
AC_CHECK_HEADERS([sql.h sqlext.h], [odbc_required_headers=yes], [odbc_required_headers=no],
@@ -139,8 +146,10 @@ AC_SUBST(THR_LIBS)
odbc_lib_link_success=no
AC_SUBST(TARGET_FLAGS)
- case $host_os in
- darwin1[[0-9]].*)
+AS_CASE([$host_os],
+
+ [darwin1[[0-9]].*],
+ [
TARGET_FLAGS="-DUNIX"
if test ! -d "$with_odbc" || test "$with_odbc" = "yes"; then
ODBC_LIB= -L"/usr/local/lib"
@@ -151,15 +160,19 @@ AC_SUBST(TARGET_FLAGS)
fi
AC_CHECK_LIB(iodbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
- ;;
- haiku*)
+ ],
+
+ [haiku*],
+ [
TARGET_FLAGS="-DUNIX"
ODBC_LIB= -L"/system/lib"
ODBC_INCLUDE="-I/system/develop/headers"
dnl Haiku's package manager will deal with this for us
AC_CHECK_LIB(odbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
- ;;
- win32|cygwin)
+ ],
+
+ [win32|cygwin],
+ [
TARGET_FLAGS="-DWIN32"
AC_CHECK_LIB(ws2_32, main)
if test ! -d "$with_odbc" || test "$with_odbc" = "yes"; then
@@ -170,17 +183,22 @@ AC_SUBST(TARGET_FLAGS)
ODBC_INCLUDE="-I$with_odbc/include"
fi
AC_CHECK_LIB(odbc32, main, [ODBC_LIB="$ODBC_LIB -lodbc32"; odbc_lib_link_success=yes])
- ;;
- *)
+ ],
+
+ [
TARGET_FLAGS="-DUNIX"
- case "$erl_xcomp_without_sysroot-$with_odbc" in
- yes-yes | yes- )
+ AS_CASE(["$erl_xcomp_without_sysroot-$with_odbc"],
+
+ [yes-yes | yes-],
+ [
msg="Dont know where to search for odbc (setting erl_xcomp_sysroot will help)"
AC_MSG_WARN([$msg])
echo "$msg" > "$ERL_TOP/lib/odbc/SKIP"
odbc_lib_link_success=wont_try
- ;;
- no-yes | no- )
+ ],
+
+ [no-yes | no-],
+ [
AC_CHECK_SIZEOF(void *)
AC_MSG_CHECKING([for odbc in standard locations])
for rdir in /usr/local/odbc /usr/local /usr/odbc \
@@ -209,16 +227,14 @@ AC_SUBST(TARGET_FLAGS)
AC_MSG_RESULT($ODBC_LIB)
AC_CHECK_LIB(odbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
fi
- ;;
+ ],
- *)
+ [
ODBC_LIB=-L"$with_odbc/lib"
ODBC_INCLUDE="-I$with_odbc/include"
AC_CHECK_LIB(odbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
- ;;
- esac
- ;;
-esac
+ ])
+ ])
if test $odbc_required_headers = no; then
AC_MSG_WARN(["ODBC library - header check failed"])
@@ -232,12 +248,13 @@ fi
AC_SUBST(ODBC_LIB)
AC_SUBST(ODBC_INCLUDE)
-fi dnl "$with_odbc" != "no"
+ ]) dnl "$with_odbc" != "no"
-if test "x$GCC" = xyes; then
+AS_IF([test "x$GCC" = xyes],
+ [
# Treat certain GCC warnings as errors
LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS])
-fi
+ ])
dnl ----------------------------------------------------------------------
dnl Enable -fsanitize= flags.
@@ -259,4 +276,5 @@ CFLAGS="$CFLAGS $sanitizers"
LDFLAGS="$LDFLAGS $sanitizers"
])
-AC_OUTPUT(c_src/$host/Makefile:c_src/Makefile.in)
+AC_CONFIG_FILES([c_src/$host/Makefile:c_src/Makefile.in])
+AC_OUTPUT
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index 33b232fc84..8526a5b383 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -32,7 +32,23 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.13.5</title>
+ <section><title>ODBC 2.14</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.13.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/src/Makefile b/lib/odbc/src/Makefile
index 7ca59495ed..e18628e94d 100644
--- a/lib/odbc/src/Makefile
+++ b/lib/odbc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@ ERL_COMPILE_FLAGS += -I$(INCLUDE) \
#debug:
# @${MAKE} TYPE=debug opt
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/odbc/test/Makefile b/lib/odbc/test/Makefile
index c90f76a83d..ab184ac06b 100644
--- a/lib/odbc/test/Makefile
+++ b/lib/odbc/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -72,11 +72,13 @@ RELSYSDIR = $(RELEASE_PATH)/odbc_test
ERL_COMPILE_FLAGS += $(INCLUDES) \
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
diff --git a/lib/odbc/test/mysql.erl b/lib/odbc/test/mysql.erl
index 69b136e743..1bba1482c9 100644
--- a/lib/odbc/test/mysql.erl
+++ b/lib/odbc/test/mysql.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
%-------------------------------------------------------------------------
connection_string() ->
- case test_server:os_type() of
+ case os:type() of
{unix, linux} ->
"DSN=MySQL;Database=odbctest;Uid=odbctest;Pwd=gurka;CHARSET=utf8;SSTMT=SET NAMES 'utf8';";
{unix, sunos} ->
diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl
index 7c45e48899..717d42a505 100644
--- a/lib/odbc/test/postgres.erl
+++ b/lib/odbc/test/postgres.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
%-------------------------------------------------------------------------
connection_string() ->
- case test_server:os_type() of
+ case os:type() of
{unix, sunos} ->
"DSN=Postgres;UID=odbctest";
{unix, linux} ->
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 04aea9d2a4..7856175267 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.13.5
+ODBC_VSN = 2.14
diff --git a/lib/os_mon/c_src/memsup.c b/lib/os_mon/c_src/memsup.c
index 7ea7456003..96f662da19 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@
* This program communicates with Erlang through the standard
* input and output file descriptors (0 and 1). These descriptors
* (and the standard error descriptor 2) must NOT be closed
- * explicitely by this program at termination (in UNIX it is
+ * explicitly by this program at termination (in UNIX it is
* taken care of by the operating system itself; in VxWorks
* it is taken care of by the spawn driver part of the Emulator).
*
@@ -176,7 +176,7 @@ static void print_error(const char *,...);
* PageTables: 9368 kB 2.5.41+
* VmallocTotal: 34359738367 kB ?? total size of vmalloc memory area
* VmallocUsed: 57376 kB ?? amount of vmalloc area which is used
- * VmallocChunk: 34359677947 kB ?? largest contigious block of vmalloc area which is free
+ * VmallocChunk: 34359677947 kB ?? largest contiguous block of vmalloc area which is free
* ReverseMaps: 5738 2.5.41+ number of rmap pte chains
* SwapCached: 0 kB 2.5.??+
* HugePages_Total: 0 2.5.??+
@@ -609,6 +609,8 @@ message_loop(int erlin_fd)
case SHOW_SYSTEM_MEM:
extended_show_mem();
break;
+ case EXIT:
+ return;
default: /* ignore all other messages */
break;
}
diff --git a/lib/os_mon/c_src/memsup.h b/lib/os_mon/c_src/memsup.h
index fa65db784a..ae53ec6101 100644
--- a/lib/os_mon/c_src/memsup.h
+++ b/lib/os_mon/c_src/memsup.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2021. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2023. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@
/* Extended memory statistics */
/*IG*/ #define SHOW_SYSTEM_MEM 2
+#define EXIT 3
+
/* Tags for the extended statistics */
/*IG*/ #define SHOW_SYSTEM_MEM_END 0
/*IG*/ #define MEM_SYSTEM_TOTAL 1
diff --git a/lib/os_mon/c_src/nteventlog/elog_format.h b/lib/os_mon/c_src/nteventlog/elog_format.h
index d92e2a81c3..e753100001 100644
--- a/lib/os_mon/c_src/nteventlog/elog_format.h
+++ b/lib/os_mon/c_src/nteventlog/elog_format.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ char *format_message(MessageFiles mf, DWORD id,
* Formats an eventlog message with the messagefiles
* in mf, the ID id, the stringarray strings,
* containing numstrings strings into buff.
- * if bufflen is to small or anything else failes,
+ * if bufflen is to small or anything else fails,
* the return value is NULL.
*/
diff --git a/lib/os_mon/c_src/nteventlog/elog_main.c b/lib/os_mon/c_src/nteventlog/elog_main.c
index a7b59e516b..bed558f80f 100644
--- a/lib/os_mon/c_src/nteventlog/elog_main.c
+++ b/lib/os_mon/c_src/nteventlog/elog_main.c
@@ -285,7 +285,7 @@ BOOL output_record(char *category, EVENTLOGRECORD *event){
* number and timestamp, and sends them to
* stdout. If timestamp does
* not correspond with record number, the
- * log is concidered wrapped around
+ * log is considered wrapped around
* and is reread from the beginning.
* time is ignored if 0.
* If record_number is 0, the whole log is read (if there is one).
diff --git a/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.c b/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.c
index 1920268af9..96a2625e73 100644
--- a/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.c
+++ b/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ static char *stdin_buff = NULL;
static int stdin_siz = 0;
static int stdin_len = 0;
static int stdin_eof = 0;
-/* end syncronized objects */
+/* end synchronized objects */
static int stdin_is_console = 0;
static HANDLE stdin_event;
diff --git a/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.h b/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.h
index b8f08bb412..4677477753 100644
--- a/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.h
+++ b/lib/os_mon/c_src/nteventlog/elog_pipe_stdin.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1998-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1998-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,11 +22,11 @@
/*
* Module: elog_pipe_stdin
* Purpouse: Read data from stdin when stdin is a pipe
- * and deliver events only when data is really availabel or
+ * and deliver events only when data is really available or
* end of file is reached.
* If we would wait on an ordinary pipe handle, we
* would return immediately as it's always "signaled".
- * some kind of asyncronous I/O in the win32 way is
+ * some kind of asynchronous I/O in the win32 way is
* not possible as it's not supported on anonymous pipes
* (besides we have not opened the file ourselves so we
* cannot specify that we want async I/O...).
@@ -66,7 +66,7 @@ BOOL setup_pipe_stdin(void);
/*
* Initializes the module, returns TRUE if OK.
* If stdin is a console, no thread is created
- * and the event objet returned by get_Stdin_event
+ * and the event object returned by get_Stdin_event
* will be the console handle.
* Check if stdin was a console with the console_stdin()
* function.
diff --git a/lib/os_mon/c_src/win32sysinfo.c b/lib/os_mon/c_src/win32sysinfo.c
index 67b3f74910..1c9590fb8b 100644
--- a/lib/os_mon/c_src/win32sysinfo.c
+++ b/lib/os_mon/c_src/win32sysinfo.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1997-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1997-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@
* get_disk_info 'd'Driveroot (where Driveroot is a string like this "A:\\"
* (request info of specific drive)
- * The result is returned with the same format as above exept that
+ * The result is returned with the same format as above except that
* Type will be DRIVE_NOT_EXIST if the drive does not exist.
*
* get_mem_info 'm' (request info about memory)
diff --git a/lib/os_mon/doc/src/disksup.xml b/lib/os_mon/doc/src/disksup.xml
index 47eff80ff5..59ba7eaf9e 100644
--- a/lib/os_mon/doc/src/disksup.xml
+++ b/lib/os_mon/doc/src/disksup.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -57,15 +57,42 @@
longer valid.</p>
</description>
+ <datatypes>
+ <datatype>
+ <name>time()</name>
+ <desc>
+ <p>Supported units:</p>
+ <taglist>
+ <tag><c>integer() >= 1</c></tag>
+ <item>
+ <p>The time interval in minutes.</p>
+ </item>
+ <tag><c>{TimeUnit, Time}</c></tag>
+ <item>
+ <p>
+ The time interval <c>Time</c> in a time unit specified by <c>TimeUnit</c> where
+ <c>TimeUnit</c> is of the type
+ <seetype marker="erts:erlang#time_unit"><c>erlang:time_unit()</c></seetype>
+ and <c>Time</c> is a positive integer. The time interval needs to be at least one
+ millisecond long.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ </datatypes>
+
<section>
<marker id="config"></marker>
<title>Configuration</title>
<p>The following configuration parameters can be used to change
the default values for time interval and threshold:</p>
<taglist>
- <tag><c>disk_space_check_interval = int()>0</c></tag>
+ <tag>
+ <c>disk_space_check_interval = </c><seetype marker="#time"><c>time()</c></seetype>
+ </tag>
<item>
- <p>The time interval, in minutes, for the periodic disk space
+ <p>The time interval for the periodic disk space
check. The default is 30 minutes.</p>
</item>
<tag><c>disk_almost_full_threshold = float()</c></tag>
@@ -123,13 +150,13 @@
</desc>
</func>
<func>
- <name since="">set_check_interval(Minutes) -> ok</name>
- <fsummary>Set time interval, in minutes, for the periodic disk space check</fsummary>
+ <name since="">set_check_interval(Time) -> ok</name>
+ <fsummary>Set time interval for the periodic disk space check</fsummary>
<type>
- <v>Minutes = int()>=1</v>
+ <v>Time = <seetype marker="#time">time()</seetype></v>
</type>
<desc>
- <p>Changes the time interval, given in minutes, for the periodic
+ <p>Changes the time interval for the periodic
disk space check.</p>
<p>The change will take effect after the next disk space check
and is non-persist. That is, in case of a process restart,
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index f510329619..1fac53d330 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -31,6 +31,41 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The port programs used by <c>cpu_sup</c> and
+ <c>memsup</c> are now gracefully shut down when
+ <c>cpu_sup</c> and <c>memsup</c> are shut down.</p>
+ <p>
+ Own Id: OTP-18469 Aux Id: PR-6689 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Os_Mon 2.8</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The <seeerl
+ marker="os_mon:disksup#config"><c>disk_space_check_interval</c></seeerl>
+ configuration parameter of <c>disksup</c> can now be set
+ to values smaller than a minute.</p>
+ <p>
+ Own Id: OTP-18304 Aux Id: PR-6385 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.7.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -698,7 +733,7 @@
<list>
<item>
<p>
- Memsup did not read memory correctly on MaxOSX
+ Memsup did not read memory correctly on macOS X
Snowleopard. This has now been corrected. (Thanks to Joel
Reymont)</p>
<p>
diff --git a/lib/os_mon/include/memsup.hrl b/lib/os_mon/include/memsup.hrl
index 2f76cfe9b3..df2278aaf6 100644
--- a/lib/os_mon/include/memsup.hrl
+++ b/lib/os_mon/include/memsup.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
-define( SHOW_MEM , 1 ).
-define( SHOW_SYSTEM_MEM , 2 ).
+-define( EXIT , 3 ).
-define( SHOW_SYSTEM_MEM_END , 8#0 ).
%% tags for extended statistics
-define( MEM_SYSTEM_TOTAL , 1 ).
diff --git a/lib/os_mon/src/Makefile b/lib/os_mon/src/Makefile
index 48a896265b..e28fb12548 100644
--- a/lib/os_mon/src/Makefile
+++ b/lib/os_mon/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ ERL_COMPILE_FLAGS += -I$(INCLUDE) -Werror
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl
index b4283bb436..be917021e7 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -495,9 +495,6 @@ measurement_server_init() ->
measurement_server_loop(State) ->
receive
- {_, quit} ->
- State#internal.port ! {self(), ?quit},
- ok;
{'DOWN',Monitor,process,_,_} ->
measurement_server_loop(State#internal{ util = lists:keydelete(
Monitor,
@@ -528,6 +525,14 @@ measurement_server_loop(State) ->
{'EXIT', OldPid, _n} when State#internal.port == OldPid ->
{ok, NewPid} = port_server_start_link(),
measurement_server_loop(State#internal{port = NewPid});
+ {'EXIT', _, normal} ->
+ case State#internal.port of
+ not_used ->
+ ok;
+ Srv ->
+ Srv ! {self(), ?quit},
+ ok
+ end;
_Other ->
measurement_server_loop(State)
end.
diff --git a/lib/os_mon/src/disksup.erl b/lib/os_mon/src/disksup.erl
index 80f833bb49..ecf3928d89 100644
--- a/lib/os_mon/src/disksup.erl
+++ b/lib/os_mon/src/disksup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,12 +48,12 @@ get_disk_data() ->
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}, infinity);
- false ->
- erlang:error(badarg)
+set_check_interval(Value) ->
+ case param_type(disk_space_check_interval, Value) of
+ true ->
+ os_mon:call(disksup, {set_check_interval, Value}, infinity);
+ false ->
+ erlang:error(badarg)
end.
get_almost_full_threshold() ->
@@ -69,7 +69,12 @@ set_almost_full_threshold(Float) ->
dummy_reply(get_disk_data) ->
[{"none", 0, 0}];
dummy_reply(get_check_interval) ->
- minutes_to_ms(os_mon:get_env(disksup, disk_space_check_interval));
+ case os_mon:get_env(disksup, disk_space_check_interval) of
+ {TimeUnit, Time} ->
+ erlang:convert_time_unit(Time, TimeUnit, millisecond);
+ Minute ->
+ minutes_to_ms(Minute)
+ end;
dummy_reply({set_check_interval, _}) ->
ok;
dummy_reply(get_almost_full_threshold) ->
@@ -77,6 +82,13 @@ dummy_reply(get_almost_full_threshold) ->
dummy_reply({set_almost_full_threshold, _}) ->
ok.
+param_type(disk_space_check_interval, {TimeUnit, Time}) ->
+ try erlang:convert_time_unit(Time, TimeUnit, millisecond) of
+ MsTime when MsTime > 0 -> true;
+ _ -> false
+ catch
+ _:_ -> false
+ end;
param_type(disk_space_check_interval, Val) when is_integer(Val),
Val>=1 -> true;
param_type(disk_almost_full_threshold, Val) when is_number(Val),
@@ -120,20 +132,28 @@ init([]) ->
%% Read the values of some configuration parameters
Threshold = os_mon:get_env(disksup, disk_almost_full_threshold),
- Timeout = os_mon:get_env(disksup, disk_space_check_interval),
+ Timeout = case os_mon:get_env(disksup, disk_space_check_interval) of
+ {TimeUnit, Time} ->
+ erlang:convert_time_unit(Time, TimeUnit, millisecond);
+ Minutes ->
+ minutes_to_ms(Minutes)
+ end,
%% Initiation first disk check
self() ! timeout,
{ok, #state{port=Port, os=OS,
threshold=round(Threshold*100),
- timeout=minutes_to_ms(Timeout)}}.
+ timeout=Timeout}}.
handle_call(get_disk_data, _From, State) ->
{reply, State#state.diskdata, State};
handle_call(get_check_interval, _From, State) ->
{reply, State#state.timeout, State};
+handle_call({set_check_interval, {TimeUnit, Time}}, _From, State) ->
+ Timeout = erlang:convert_time_unit(Time, TimeUnit, millisecond),
+ {reply, ok, State#state{timeout=Timeout}};
handle_call({set_check_interval, Minutes}, _From, State) ->
Timeout = minutes_to_ms(Minutes),
{reply, ok, State#state{timeout=Timeout}};
diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl
index e4f60b9972..1c93bfbae4 100644
--- a/lib/os_mon/src/memsup.erl
+++ b/lib/os_mon/src/memsup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -651,6 +651,10 @@ port_init() ->
start_portprogram() ->
os_mon:open_port("memsup",[{packet,1}]).
+port_shutdown(Port) ->
+ Port ! {self(), {command, [?EXIT]}},
+ port_close(Port).
+
%% The connected process loops are a bit awkward (several different
%% functions doing almost the same thing) as
%% a) strategies for receiving regular memory data and extensive
@@ -674,13 +678,13 @@ port_idle(Port) ->
%% Received after reply already has been delivered...
port_idle(Port);
close ->
- port_close(Port);
+ port_shutdown(Port);
{Port, {data, Data}} ->
exit({port_error, Data});
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
get_memory_usage(Port, Alloc, Memsup) ->
@@ -694,11 +698,11 @@ get_memory_usage(Port, Alloc, Memsup) ->
cancel ->
get_memory_usage_cancelled(Port, Alloc);
close ->
- port_close(Port);
+ port_shutdown(Port);
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
get_memory_usage_cancelled(Port, Alloc) ->
receive
@@ -707,11 +711,11 @@ get_memory_usage_cancelled(Port, Alloc) ->
{Port, {data, _Data}} ->
port_idle(Port);
close ->
- port_close(Port);
+ port_shutdown(Port);
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
tag2atag(Port, Tag) ->
@@ -734,11 +738,11 @@ get_ext_memory_usage(Port, Accum, Memsup) ->
ext_cancel ->
get_ext_memory_usage_cancelled(Port);
close ->
- port_close(Port);
+ port_shutdown(Port);
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
get_ext_memory_usage_cancelled(Port) ->
receive
@@ -748,11 +752,11 @@ get_ext_memory_usage_cancelled(Port) ->
get_ext_memory_usage_cancelled(tag2atag(Port, Tag),
Port);
close ->
- port_close(Port);
+ port_shutdown(Port);
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
get_ext_memory_usage(ATag, Port, Accum0, Memsup) ->
@@ -769,22 +773,22 @@ get_ext_memory_usage(ATag, Port, Accum0, Memsup) ->
cancel ->
get_ext_memory_usage_cancelled(ATag, Port);
close ->
- port_close(Port);
+ port_shutdown(Port);
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
get_ext_memory_usage_cancelled(_ATag, Port) ->
receive
{Port, {data, _Data}} ->
get_ext_memory_usage_cancelled(Port);
close ->
- port_close(Port);
+ port_shutdown(Port);
{'EXIT', Port, Reason} ->
exit({port_died, Reason});
{'EXIT', _Memsup, _Reason} ->
- port_close(Port)
+ port_shutdown(Port)
end.
%%--Collect process data------------------------------------------------
diff --git a/lib/os_mon/src/os_mon.app.src b/lib/os_mon/src/os_mon.app.src
index 2b1f7dc85b..76d056de04 100644
--- a/lib/os_mon/src/os_mon.app.src
+++ b/lib/os_mon/src/os_mon.app.src
@@ -31,4 +31,4 @@
{start_memsup, true},
{start_os_sup, false}]},
{mod, {os_mon, []}},
- {runtime_dependencies, ["stdlib-2.0","sasl-2.4","kernel-3.0","erts-6.0"]}]}.
+ {runtime_dependencies, ["stdlib-3.4","sasl-2.4","kernel-3.0","erts-6.0"]}]}.
diff --git a/lib/os_mon/test/Makefile b/lib/os_mon/test/Makefile
index 73618e5fae..df7b606c06 100644
--- a/lib/os_mon/test/Makefile
+++ b/lib/os_mon/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@ RELSYSDIR = $(RELEASE_PATH)/os_mon_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/snmp/include
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
@@ -64,7 +65,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl
index 03aa6cd355..e719963ea9 100644
--- a/lib/os_mon/test/cpu_sup_SUITE.erl
+++ b/lib/os_mon/test/cpu_sup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- case test_server:os_type() of
+ case os:type() of
{unix, sunos} ->
[load_api, util_api, util_values, port, unavailable];
{unix, linux} ->
@@ -65,6 +65,7 @@ all() ->
[load_api, util_api, util_values, port, unavailable];
{unix, darwin} ->
[load_api, util_api, util_values, port, unavailable];
+ {unix, netbsd} -> [unavailable];
{unix, _OSname} -> [load_api];
_OS -> [unavailable]
end.
diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl
index fe27ea9046..1590b1a735 100644
--- a/lib/os_mon/test/disksup_SUITE.erl
+++ b/lib/os_mon/test/disksup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -61,7 +61,7 @@ all() ->
Bugs = [otp_5910],
Always = [api, config, alarm, port, posix_only, unavailable,
parse_df_output_posix, parse_df_output_susv3] ++ Bugs,
- case test_server:os_type() of
+ case os:type() of
{unix, _OSname} -> Always;
{win32, _OSname} -> Always;
_OS -> [unavailable]
@@ -83,6 +83,15 @@ api(Config) when is_list(Config) ->
1200000 = disksup:get_check_interval(),
ok = disksup:set_check_interval(30),
+ %% set_check_interval({TimeUnit, Time})
+ ok = disksup:set_check_interval({second, 1}),
+ 1000 = disksup:get_check_interval(),
+ {'EXIT',{badarg,_}} = (catch disksup:set_check_interval({second, 0.5})),
+ {'EXIT',{badarg,_}} = (catch disksup:set_check_interval({badarg, 1})),
+ {'EXIT',{badarg,_}} = (catch disksup:set_check_interval({nanosecond, 1})),
+ 1000 = disksup:get_check_interval(),
+ ok = disksup:set_check_interval(30),
+
%% get_almost_full_threshold()
80 = disksup:get_almost_full_threshold(),
@@ -110,6 +119,13 @@ config(Config) when is_list(Config) ->
1740000 = disksup:get_check_interval(),
81 = disksup:get_almost_full_threshold(),
+ ok = application:set_env(os_mon, disk_space_check_interval, {second, 2}),
+
+ ok = supervisor:terminate_child(os_mon_sup, disksup),
+ {ok, _Child2} = supervisor:restart_child(os_mon_sup, disksup),
+
+ 2000 = disksup:get_check_interval(),
+
%% Also try this with bad parameter values, should be ignored
ok =
application:set_env(os_mon, disk_space_check_interval, 0.5),
@@ -117,11 +133,32 @@ config(Config) when is_list(Config) ->
application:set_env(os_mon, disk_almost_full_threshold, -0.81),
ok = supervisor:terminate_child(os_mon_sup, disksup),
- {ok, _Child2} = supervisor:restart_child(os_mon_sup, disksup),
+ {ok, _Child3} = supervisor:restart_child(os_mon_sup, disksup),
1800000 = disksup:get_check_interval(),
80 = disksup:get_almost_full_threshold(),
+ ok = application:set_env(os_mon, disk_space_check_interval, {second, 0.5}),
+
+ ok = supervisor:terminate_child(os_mon_sup, disksup),
+ {ok, _Child4} = supervisor:restart_child(os_mon_sup, disksup),
+
+ 1800000 = disksup:get_check_interval(),
+
+ ok = application:set_env(os_mon, disk_space_check_interval, {badarg, 1}),
+
+ ok = supervisor:terminate_child(os_mon_sup, disksup),
+ {ok, _Child5} = supervisor:restart_child(os_mon_sup, disksup),
+
+ 1800000 = disksup:get_check_interval(),
+
+ ok = application:set_env(os_mon, disk_space_check_interval, {nanosecond, 1}),
+
+ ok = supervisor:terminate_child(os_mon_sup, disksup),
+ {ok, _Child6} = supervisor:restart_child(os_mon_sup, disksup),
+
+ 1800000 = disksup:get_check_interval(),
+
%% Reset configuration parameters
ok = application:set_env(os_mon, disk_space_check_interval, 30),
ok = application:set_env(os_mon, disk_almost_full_threshold, 0.80),
@@ -332,8 +369,8 @@ otp_5910(Config) when is_list(Config) ->
0 ->
[{_Id,_Kbyte,Cap}|_] = Data,
io:format("Data ~p Threshold ~p ~n",[Data, Cap-1]),
- ok = disksup:set_almost_full_threshold((Cap-1)/100),
- Cap-1;
+ ok = disksup:set_almost_full_threshold((max(0, Cap-1))/100),
+ max(0, Cap-1);
_N -> Threshold0
end,
ok = application:set_env(os_mon, disk_almost_full_threshold, Threshold/100),
@@ -404,7 +441,7 @@ check_get_disk_data() ->
% filter get_disk_data and remove entriew with zero capacity
% "non-normal" filesystems report zero capacity
-% - Perhaps errorneous 'df -k -l'?
+% - Perhaps erroneous 'df -k -l'?
% - Always list filesystems by type '-t ufs,zfs,..' instead?
% It is unclear what the intention was from the beginning.
get_disk_data() ->
diff --git a/lib/os_mon/test/memsup_SUITE.erl b/lib/os_mon/test/memsup_SUITE.erl
index b2944e2804..1f66ea0afa 100644
--- a/lib/os_mon/test/memsup_SUITE.erl
+++ b/lib/os_mon/test/memsup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- All = case test_server:os_type() of
+ All = case os:type() of
{unix, sunos} ->
[api, alarm1, alarm2, process, config, timeout,
unavailable, port];
@@ -551,7 +551,7 @@ timeout(Config) when is_list(Config) ->
%% Linux should be handled the same way as solaris.
- % TimeoutMsg = case test_server:os_type() of
+ % TimeoutMsg = case os:type() of
% {unix, sunos} -> ext_collection_timeout;
% {unix, linux} -> reg_collection_timeout
% end,
@@ -722,14 +722,14 @@ otp_5910(Config) when is_list(Config) ->
ok = application:start(os_mon),
ok.
-improved_system_memory_data(Config) ->
- {ok, Node} = start_node(Config),
+improved_system_memory_data(Config) when is_list(Config) ->
+ {ok, Peer, Node} = ?CT_PEER(),
ok = rpc:call(Node, application, start, [sasl]),
ok = rpc:call(Node, application, start, [os_mon]),
ExtMemData = rpc:call(Node, memsup, get_system_memory_data, []),
- stop_node(Node),
+ peer:stop(Peer),
Tags = ?SYSTEM_MEMORY_DATA_TAGS,
AvailableMemoryPresent
@@ -785,7 +785,7 @@ force_collection(TimerRef) ->
erlang:trace(whereis(memsup), false, ['receive']),
flush(),
collection_timeout;
- timout ->
+ timeout ->
erlang:trace(whereis(memsup), false, ['receive']),
flush(),
timeout;
@@ -802,20 +802,3 @@ flush() ->
after 0 ->
ok
end.
-
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) when is_list(Config) ->
- Pa = filename:dirname(code:which(?MODULE)),
- Name = list_to_atom(atom_to_list(?MODULE)
- ++ "-"
- ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-"
- ++ integer_to_list(erlang:system_time(second))
- ++ "-"
- ++ integer_to_list(erlang:unique_integer([positive]))),
- test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]).
-
-stop_node(Node) ->
- test_server:stop_node(Node).
diff --git a/lib/os_mon/test/os_mon_SUITE.erl b/lib/os_mon/test/os_mon_SUITE.erl
index c373b5d851..7eec6d0eaf 100644
--- a/lib/os_mon/test/os_mon_SUITE.erl
+++ b/lib/os_mon/test/os_mon_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- case test_server:os_type() of
+ case os:type() of
{unix, sunos} -> [app_file, appup_file, config];
_OS -> [app_file, appup_file]
end.
diff --git a/lib/os_mon/test/os_sup_SUITE.erl b/lib/os_mon/test/os_sup_SUITE.erl
index febd3b5f12..75bcfdd075 100644
--- a/lib/os_mon/test/os_sup_SUITE.erl
+++ b/lib/os_mon/test/os_sup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- case test_server:os_type() of
+ case os:type() of
{unix, sunos} -> [message, config, port];
{win32, _OSname} -> [message];
OS ->
@@ -76,7 +76,7 @@ message(Config) when is_list(Config) ->
%% Check with message_receptor that it has been received
ct:sleep({seconds,1}),
Msg =
- case test_server:os_type() of
+ case os:type() of
{unix, sunos} ->
{?TAG, Data};
{win32, _} ->
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index a85ec42981..9e64a83612 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.7.1
+OS_MON_VSN = 2.8.1
diff --git a/lib/parsetools/doc/src/leex.xml b/lib/parsetools/doc/src/leex.xml
index 153374e16a..d802e46b59 100644
--- a/lib/parsetools/doc/src/leex.xml
+++ b/lib/parsetools/doc/src/leex.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2020</year>
+ <year>2009</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -110,6 +110,11 @@
<item>
<p>Causes warnings to be treated as errors.</p>
</item>
+ <tag><c>{deterministic, boolean()}</c></tag>
+ <item>
+ <p>Causes generated -file() attributes to only include
+ the basename of the file path.</p>
+ </item>
</taglist>
<p>Any of the Boolean options can be set to <c>true</c> by
stating the name of the option. For example, <c>verbose</c>
@@ -222,13 +227,13 @@ io:request(InFile, {get_until,unicode,Prompt,Module,token,[Line]})
<c>[]</c>.</p>
<p>This functions differs from <c>token</c> in that it will
- continue to scan tokens upto and including an
+ continue to scan tokens up to and including an
<c>{end_token,Token}</c> has been scanned (see next
section). It will then return all the tokens. This is
typically used for scanning grammars like Erlang where there
is an explicit end token, <c>'.'</c>. If no end token is
found then the whole file will be scanned and returned. If
- an error occurs then all tokens upto and including the next
+ an error occurs then all tokens up to and including the next
end token will be skipped.</p>
<p>It is not designed to be called directly by an application
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 32a95f51a8..6d79b4ce49 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>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,41 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.4.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Parsetools 2.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>In the generated code, <c>yecc</c> will now quote all
+ atoms coming from terminals in the grammar, in order to
+ avoid conflicts with future reserved words.</p>
+ <p>
+ Own Id: OTP-17755</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.3.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -456,7 +491,7 @@
<section><title>Improvements and New Features</title>
<list>
<item>
- <p> The formating of Yecc's error messages has been
+ <p> The formatting of Yecc's error messages has been
improved. (Thanks to Joe Armstrong.) </p>
<p>
Own Id: OTP-8919</p>
diff --git a/lib/parsetools/doc/src/yecc.xml b/lib/parsetools/doc/src/yecc.xml
index 60c1bdb8f0..4d639d1f21 100644
--- a/lib/parsetools/doc/src/yecc.xml
+++ b/lib/parsetools/doc/src/yecc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -134,6 +134,11 @@
is <c>column</c>, the location includes a line number and
a column number. Default is <c>column</c>.
</item>
+ <tag><c>{deterministic, boolean()}</c></tag>
+ <item>
+ <p>Causes generated -file() attributes to only include the
+ basename of the file path.</p>
+ </item>
</taglist>
<p>Any of the Boolean options can be set to <c>true</c> by
stating the name of the option. For example, <c>verbose</c>
@@ -361,7 +366,7 @@ element -> list : '$1'. </code>
<c>(a b c).</c>. This still assumes that this was the first
input line that the scanner tokenized:</p>
<code type="none">
-{cons, {atom, 1, a,} {cons, {atom, 1, b},
+{cons, {atom, 1, a}, {cons, {atom, 1, b},
{cons, {atom, 1, c}, nil}}} </code>
<p>The associated code contains <c>pseudo variables</c> <c>'$1'</c>, <c>'$2'</c>, <c>'$3'</c>, etc. which refer to (are
bound to) the values associated previously by the parser with
diff --git a/lib/parsetools/include/leexinc.hrl b/lib/parsetools/include/leexinc.hrl
index 2a74c252ff..8dfc42f479 100644
--- a/lib/parsetools/include/leexinc.hrl
+++ b/lib/parsetools/include/leexinc.hrl
@@ -32,7 +32,7 @@ string(Ics0, L0, Tcs, Ts) ->
case yystate(yystate(), Ics0, L0, 0, reject, 0) of
{A,Alen,Ics1,L1} -> % Accepting end state
string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L0), Ts);
- {A,Alen,Ics1,L1,_S1} -> % Accepting transistion state
+ {A,Alen,Ics1,L1,_S1} -> % Accepting transition state
string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L0), Ts);
{reject,_Alen,Tlen,_Ics1,L1,_S1} -> % After a non-accepting state
{error,{L0,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1};
diff --git a/lib/parsetools/src/Makefile b/lib/parsetools/src/Makefile
index ba206904ec..c7971750a7 100644
--- a/lib/parsetools/src/Makefile
+++ b/lib/parsetools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -66,7 +66,7 @@ ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/stdlib/include \
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl
index 37f3fb7114..b764678516 100644
--- a/lib/parsetools/src/leex.erl
+++ b/lib/parsetools/src/leex.erl
@@ -78,9 +78,10 @@ compile(Input0, Output0,
Output = assure_extension(shorten_filename(Output0), ".erl"),
Includefile = lists:sublist(Includes, 1),
Werror = proplists:get_bool(warnings_as_errors, Specific),
+ Deterministic = proplists:get_bool(deterministic, Specific),
Opts = [{scannerfile,Output},{includefile,Includefile},{verbose,Verbose},
{report_errors,true},{report_warnings,WarnLevel > 0},
- {warnings_as_errors, Werror}],
+ {warnings_as_errors, Werror}, {deterministic, Deterministic}],
case file(Input, Opts) of
{ok, _} ->
ok;
@@ -117,6 +118,7 @@ file(File) -> file(File, []).
| {'scannerfile', Scannerfile :: file:filename()}
| {'verbose', boolean()}
| {'warnings_as_errors', boolean()}
+ | {'deterministic', boolean()}
| 'dfa_graph'
| 'report_errors' | 'report_warnings' | 'report'
| 'return_errors' | 'return_warnings' | 'return'
@@ -287,7 +289,7 @@ check_options(_Options, _, _L) ->
all_options() ->
[dfa_graph,includefile,report_errors,report_warnings,
return_errors,return_warnings,scannerfile,verbose,
- warnings_as_errors].
+ warnings_as_errors, deterministic].
default_option(dfa_graph) -> false;
default_option(includefile) -> [];
@@ -297,7 +299,8 @@ default_option(return_errors) -> false;
default_option(return_warnings) -> false;
default_option(scannerfile) -> [];
default_option(verbose) -> false;
-default_option(warnings_as_errors) -> false.
+default_option(warnings_as_errors) -> false;
+default_option(deterministic) -> false.
atom_option(dfa_graph) -> {dfa_graph,true};
atom_option(report_errors) -> {report_errors,true};
@@ -306,6 +309,7 @@ atom_option(warnings_as_errors) -> {warnings_as_errors,true};
atom_option(return_errors) -> {return_errors,true};
atom_option(verbose) -> {verbose,true};
atom_option(return_warnings) -> {return_warnings,true};
+atom_option(deterministic) -> {deterministic,true};
atom_option(Key) -> Key.
is_filename(T) ->
@@ -575,7 +579,7 @@ collect_action(Ifile, Chars, L0, Cont0) ->
%% parse_rule(RegExpString, RegExpLine, ActionTokens, Macros, Counter, State) ->
%% {ok,{RE,Action},ActionData,State}.
-%% Parse one regexp after performing macro substition.
+%% Parse one regexp after performing macro substitution.
parse_rule(S, Line, [{dot,_}], Ms, N, St) ->
case parse_rule_regexp(S, Ms, St) of
@@ -1126,7 +1130,7 @@ comp_crs([], Last) -> [{Last,maxchar}].
%% build_dfa(NFA, NfaFirstState) -> {DFA,DfaFirstState}.
%% Build a DFA from an NFA using "subset construction". The major
%% difference from the book is that we keep the marked and unmarked
-%% DFA states in seperate lists. New DFA states are added to the
+%% DFA states in separate lists. New DFA states are added to the
%% unmarked list and states are marked by moving them to the marked
%% list. We assume that the NFA accepting state numbers are in
%% ascending order for the rules and use ordsets to keep this order.
@@ -1264,7 +1268,7 @@ accept([], _) -> noaccept.
%% minimise_dfa(DFA, DfaFirst) -> {DFA,DfaFirst}.
%% Minimise the DFA by removing equivalent states. We consider a
%% state if both the transitions and the their accept state is the
-%% same. First repeatedly run throught the DFA state list removing
+%% same. First repeatedly run through the DFA state list removing
%% equivalent states and updating remaining transitions with
%% remaining equivalent state numbers. When no more reductions are
%% possible then pack the remaining state numbers to get consecutive
@@ -1362,7 +1366,8 @@ out_file(St0, DFA, DF, Actions, Code) ->
set_encoding(St0, Ofile),
try
output_encoding_comment(Ofile, St0),
- output_file_directive(Ofile, St0#leex.ifile, 0),
+ Deterministic = proplists:get_bool(deterministic, St0#leex.opts),
+ output_file_directive(Ofile, St0#leex.ifile, Deterministic, 0),
out_file(Ifile, Ofile, St0, DFA, DF, Actions,
Code, 1),
verbose_print(St0, "ok~n", []),
@@ -1400,15 +1405,18 @@ inc_file_name(Filename) ->
%% characters.
out_file(Ifile, Ofile, St, DFA, DF, Actions, Code, L) ->
+ Deterministic = proplists:get_bool(deterministic, St#leex.opts),
case io:get_line(Ifile, leex) of
- eof -> output_file_directive(Ofile, St#leex.ifile, L);
- {error, _} -> add_error(St#leex.ifile, {L, leex, cannot_parse}, St);
+ eof ->
+ output_file_directive(Ofile, St#leex.ifile, Deterministic, L);
+ {error, _} ->
+ add_error(St#leex.ifile, {L, leex, cannot_parse}, St);
Line ->
case string:slice(Line, 0, 5) of
"##mod" -> out_module(Ofile, St);
"##cod" -> out_erlang_code(Ofile, St, Code, L);
"##dfa" -> out_dfa(Ofile, St, DFA, Code, DF, L);
- "##act" -> out_actions(Ofile, St#leex.xfile, Actions);
+ "##act" -> out_actions(Ofile, St#leex.xfile, Deterministic, Actions);
_ -> io:put_chars(Ofile, Line)
end,
out_file(Ifile, Ofile, St, DFA, DF, Actions, Code, L+1)
@@ -1419,7 +1427,8 @@ out_module(File, St) ->
out_erlang_code(File, St, Code, L) ->
{CodeL,CodePos,_NCodeLines} = Code,
- output_file_directive(File, St#leex.xfile, CodeL),
+ Deterministic = proplists:get_bool(deterministic, St#leex.opts),
+ output_file_directive(File, St#leex.xfile, Deterministic, CodeL),
{ok,Xfile} = file:open(St#leex.xfile, [read]),
try
set_encoding(St, Xfile),
@@ -1429,7 +1438,7 @@ out_erlang_code(File, St, Code, L) ->
ok = file:close(Xfile)
end,
io:nl(File),
- output_file_directive(File, St#leex.ifile, L).
+ output_file_directive(File, St#leex.ifile, Deterministic, L).
file_copy(From, To) ->
case io:get_line(From, leex) of
@@ -1441,8 +1450,9 @@ file_copy(From, To) ->
out_dfa(File, St, DFA, Code, DF, L) ->
{_CodeL,_CodePos,NCodeLines} = Code,
+ Deterministic = proplists:get_bool(deterministic, St#leex.opts),
%% Three file attributes before this one...
- output_file_directive(File, St#leex.efile, L+(NCodeLines-1)+3),
+ output_file_directive(File, St#leex.efile, Deterministic, L+(NCodeLines-1)+3),
io:fwrite(File, "yystate() -> ~w.~n~n", [DF]),
foreach(fun (S) -> out_trans(File, S) end, DFA),
io:fwrite(File, "yystate(S, Ics, Line, Tlen, Action, Alen) ->~n", []),
@@ -1565,14 +1575,14 @@ pack_trans([Tr|Trs], Pt) -> % The default uninteresting case
pack_trans(Trs, Pt ++ [Tr]);
pack_trans([], Pt) -> Pt.
-%% out_actions(File, XrlFile, ActionList) -> ok.
+%% out_actions(File, XrlFile, Deterministic, ActionList) -> ok.
%% Write out the action table.
-out_actions(File, XrlFile, As) ->
+out_actions(File, XrlFile, Deterministic, As) ->
As1 = prep_out_actions(As),
foreach(fun (A) -> out_action(File, A) end, As1),
io:fwrite(File, "yyaction(_, _, _, _) -> error.~n", []),
- foreach(fun (A) -> out_action_code(File, XrlFile, A) end, As1).
+ foreach(fun (A) -> out_action_code(File, XrlFile, Deterministic, A) end, As1).
prep_out_actions(As) ->
map(fun ({A,empty_action}) ->
@@ -1603,14 +1613,14 @@ out_action(File, {A,_Code,Vars,Name,_Args,ArgsChars}) ->
end,
io:fwrite(File, " ~s(~s);~n", [Name, ArgsChars]).
-out_action_code(_File, _XrlFile, {_A,empty_action}) ->
+out_action_code(_File, _XrlFile, _Deterministic, {_A,empty_action}) ->
ok;
-out_action_code(File, XrlFile, {_A,Code,_Vars,Name,Args,ArgsChars}) ->
+out_action_code(File, XrlFile, Deterministic, {_A,Code,_Vars,Name,Args,ArgsChars}) ->
%% Should set the file to the .erl file, but instead assumes that
%% ?LEEXINC is syntactically correct.
io:fwrite(File, "\n-compile({inline,~w/~w}).\n", [Name, length(Args)]),
L = erl_scan:line(hd(Code)),
- output_file_directive(File, XrlFile, L-2),
+ output_file_directive(File, XrlFile, Deterministic, L-2),
io:fwrite(File, "~s(~s) ->~n", [Name, ArgsChars]),
io:fwrite(File, " ~ts\n", [pp_tokens(Code, L, File)]).
@@ -1710,12 +1720,18 @@ output_encoding_comment(_File, #leex{encoding = none}) ->
output_encoding_comment(File, #leex{encoding = Encoding}) ->
io:fwrite(File, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
-output_file_directive(File, Filename, Line) ->
+output_file_directive(File, Filename, Deterministic, Line) ->
io:fwrite(File, <<"-file(~ts, ~w).\n">>,
- [format_filename(Filename, File), Line]).
-
-format_filename(Filename0, File) ->
- Filename = filename:flatten(Filename0),
+ [format_filename(Filename, File, Deterministic), Line]).
+
+format_filename(Filename0, File, Deterministic) ->
+ Filename =
+ case Deterministic of
+ true ->
+ filename:basename(filename:flatten(Filename0));
+ false ->
+ filename:flatten(Filename0)
+ end,
case enc(File) of
unicode -> io_lib:write_string(Filename);
latin1 -> io_lib:write_string_as_latin1(Filename)
diff --git a/lib/parsetools/src/parsetools.app.src b/lib/parsetools/src/parsetools.app.src
index a7b258820a..e67e3e38f2 100644
--- a/lib/parsetools/src/parsetools.app.src
+++ b/lib/parsetools/src/parsetools.app.src
@@ -12,7 +12,7 @@
{env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]}
]
},
- {runtime_dependencies, ["stdlib-2.5","kernel-3.0","erts-6.0"]}
+ {runtime_dependencies, ["stdlib-3.4","kernel-3.0","erts-6.0"]}
]
}.
diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl
index 0e5b5d4388..ffd04a1631 100644
--- a/lib/parsetools/src/yecc.erl
+++ b/lib/parsetools/src/yecc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@
%% when debugging).
%% Non-terminals are also given integer codes, starting with -1. The
-%% absolut value of the code is used for indexing a tuple of lists of
+%% absolute value of the code is used for indexing a tuple of lists of
%% rules.
-define(SYMBOLS_AS_CODES, true).
@@ -141,9 +141,10 @@ compile(Input0, Output0,
Output = shorten_filename(Output0),
Includefile = lists:sublist(Includes, 1),
Werror = proplists:get_bool(warnings_as_errors, Specific),
+ Deterministic = proplists:get_bool(deterministic, Specific),
Opts = [{parserfile,Output}, {includefile,Includefile}, {verbose,Verbose},
{report_errors, true}, {report_warnings, WarnLevel > 0},
- {warnings_as_errors, Werror}],
+ {warnings_as_errors, Werror}, {deterministic, Deterministic}],
case file(Input, Opts) of
{ok, _OutFile} ->
ok;
@@ -265,6 +266,7 @@ file(GrammarFile) ->
| {'parserfile', Parserfile :: file:filename()}
| {'verbose', boolean()}
| {'warnings_as_errors', boolean()}
+ | {'deterministic', boolean()}
| 'report_errors' | 'report_warnings' | 'report'
| 'return_errors' | 'return_warnings' | 'return'
| 'verbose' | 'warnings_as_errors'.
@@ -407,7 +409,7 @@ check_options(_Options, _, _L) ->
all_options() ->
[error_location, file_attributes, includefile, parserfile,
report_errors, report_warnings, return_errors, return_warnings,
- time, verbose, warnings_as_errors].
+ time, verbose, warnings_as_errors, deterministic].
default_option(error_location) -> column;
default_option(file_attributes) -> true;
@@ -419,7 +421,8 @@ default_option(return_errors) -> false;
default_option(return_warnings) -> false;
default_option(time) -> false;
default_option(verbose) -> false;
-default_option(warnings_as_errors) -> false.
+default_option(warnings_as_errors) -> false;
+default_option(deterministic) -> false.
atom_option(file_attributes) -> {file_attributes, true};
atom_option(report_errors) -> {report_errors, true};
@@ -429,6 +432,7 @@ atom_option(return_warnings) -> {return_warnings, true};
atom_option(time) -> {time, true};
atom_option(verbose) -> {verbose, true};
atom_option(warnings_as_errors) -> {warnings_as_errors, true};
+atom_option(deterministic) -> {deterministic, true};
atom_option(Key) -> Key.
is_filename(T) ->
@@ -1317,7 +1321,7 @@ compute_state(Seed, Tables) ->
Closure = keysort(1, erase()),
state_items(Closure, [], [], Tables#tabs.rp_rhs).
-%% Collects a uniqe id for the state (all rule pointers).
+%% Collects a unique id for the state (all rule pointers).
state_items([{RP, LA} | L], Is, Id, RpRhs) ->
I = #item{rule_pointer = RP, look_ahead = LA, rhs = element(RP, RpRhs)},
state_items(L, [I | Is], [RP | Id], RpRhs);
@@ -1911,13 +1915,13 @@ report_conflict(Conflict, St, ActionName, How) ->
if
St#yecc.verbose ->
io:fwrite(<<"~s\n">>, [format_conflict(Conflict)]),
- Formated = format_symbol(ActionName),
+ Formatted = format_symbol(ActionName),
case How of
prec ->
- io:fwrite(<<"Resolved in favor of ~ts.\n\n">>, [Formated]);
+ io:fwrite(<<"Resolved in favor of ~ts.\n\n">>, [Formatted]);
default ->
io:fwrite(<<"Conflict resolved in favor of ~ts.\n\n">>,
- [Formated])
+ [Formatted])
end;
true ->
ok
@@ -2130,7 +2134,7 @@ output_goto_fini(F, NT, #yecc{includefile_version = {1,1}}=St0) ->
[F]),
fwrite(St,
?YECC_BUG(<<"{~ts, State, missing_in_goto_table}">>,
- [quoted_atom(St0, NT)]),
+ [quoted_atom(NT)]),
[]);
output_goto_fini(_F, _NT, St) ->
fwrite(St, <<".\n\n">>, []).
@@ -2255,13 +2259,13 @@ output_action(St, State, Terminal, #reduce{}=Action, IsFirst, SI) ->
output_action(St0, State, Terminal, #shift{state = NewState}, IsFirst, _SI) ->
St10 = delim(St0, IsFirst),
St = fwrite(St10, <<"yeccpars2_~w(S, ~ts, Ss, Stack, T, Ts, Tzr) ->\n">>,
- [State, quoted_atom(St10, Terminal)]),
+ [State, quoted_atom(Terminal)]),
output_call_to_includefile(NewState, St);
output_action(St0, State, Terminal, accept, IsFirst, _SI) ->
St10 = delim(St0, IsFirst),
St = fwrite(St10,
<<"yeccpars2_~w(_S, ~ts, _Ss, Stack, _T, _Ts, _Tzr) ->\n">>,
- [State, quoted_atom(St10, Terminal)]),
+ [State, quoted_atom(Terminal)]),
fwrite(St, <<" {ok, hd(Stack)}">>, []);
output_action(St, _State, _Terminal, nonassoc, _IsFirst, _SI) ->
St.
@@ -2287,7 +2291,7 @@ output_reduce(St0, State, Terminal,
IsFirst, StateInfo) ->
St10 = delim(St0, IsFirst),
QuotedTerminal = if
- is_atom(Terminal) -> quoted_atom(St10, Terminal);
+ is_atom(Terminal) -> quoted_atom(Terminal);
true -> Terminal
end,
St20 = fwrite(St10,
@@ -2341,11 +2345,13 @@ delim(St, true) ->
delim(St, false) ->
fwrite(St, <<";\n">>, []).
-quoted_atom(#yecc{encoding = latin1}, Atom) when is_atom(Atom) ->
- io_lib:write_atom_as_latin1(Atom);
-quoted_atom(_St, Atomic) ->
- io_lib:write(Atomic).
-
+%% Always quote atoms to ensure compatibility with future reserved words.
+quoted_atom(Atom) when is_atom(Atom) ->
+ case lists:flatten(io_lib:write_atom_as_latin1(Atom)) of
+ "'" ++ _ = Quoted -> Quoted;
+ NotQuoted -> ["'", NotQuoted, "'"]
+ end.
+
output_inlined(St, UserCodeActions, Infile) ->
foldl(fun(#user_code{funname = InlinedFunctionName,
action = Action}, St_0) ->
@@ -2407,13 +2413,23 @@ output_nowarn(St, Function, Suffix, Arity) ->
inlined_function_name(St, State, Terminal) ->
End = case Terminal of
"Cat" -> [];
- _ -> [quoted_atom(St, Terminal)]
+ _ -> [safe_atom_chars(St, Terminal)]
end,
list_to_atom(concat([yeccpars2_, State, '_'] ++ End)).
-compile({nowarn_unused_function,function_name/3}).
function_name(St, Name, Suf) ->
- list_to_atom(concat([Name, '_'] ++ [quoted_atom(St, Suf)])).
+ list_to_atom(concat([Name, '_', safe_atom_chars(St, Suf)])).
+
+safe_atom_chars(St, Atom) when is_atom(Atom) ->
+ case St of
+ #yecc{encoding = latin1} ->
+ io_lib:write_atom_as_latin1(Atom);
+ #yecc{} ->
+ atom_to_list(Atom)
+ end;
+safe_atom_chars(_St, Atomic) ->
+ io_lib:write(Atomic).
rule(RulePointer, St) ->
#rule{n = N, location = Location, symbols = Symbols} =
@@ -2683,7 +2699,12 @@ nl(#yecc{outport = Outport, line = Line}=St) ->
St#yecc{line = Line + 1}.
format_filename(Filename0, St) ->
- Filename = filename:flatten(Filename0),
+ Deterministic = proplists:get_bool(deterministic, St#yecc.options),
+ Filename =
+ case Deterministic of
+ true -> filename:basename(filename:flatten(Filename0));
+ false -> filename:flatten(Filename0)
+ end,
case lists:keyfind(encoding, 1, io:getopts(St#yecc.outport)) of
{encoding, unicode} -> io_lib:write_string(Filename);
_ -> io_lib:write_string_as_latin1(Filename)
diff --git a/lib/parsetools/test/Makefile b/lib/parsetools/test/Makefile
index 046b29067b..23cb9709e1 100644
--- a/lib/parsetools/test/Makefile
+++ b/lib/parsetools/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2016. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ RELSYSDIR = $(RELEASE_PATH)/parsetools_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -54,7 +55,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/parsetools/test/leex_SUITE.erl b/lib/parsetools/test/leex_SUITE.erl
index 1518c5d91e..ae7a907a60 100644
--- a/lib/parsetools/test/leex_SUITE.erl
+++ b/lib/parsetools/test/leex_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
%-define(debug, true).
-include_lib("stdlib/include/erl_compile.hrl").
+-include_lib("stdlib/include/assert.hrl").
-include_lib("kernel/include/file.hrl").
-ifdef(debug).
@@ -39,7 +40,7 @@
init_per_testcase/2, end_per_testcase/2]).
-export([
- file/1, compile/1, syntax/1,
+ file/1, compile/1, syntax/1, deterministic/1,
pt/1, man/1, ex/1, ex2/1, not_yet/1,
line_wrap/1,
@@ -64,7 +65,7 @@ all() ->
[{group, checks}, {group, examples}, {group, tickets}, {group, bugs}].
groups() ->
- [{checks, [], [file, compile, syntax]},
+ [{checks, [], [file, compile, syntax, deterministic]},
{examples, [], [pt, man, ex, ex2, not_yet, unicode]},
{tickets, [], [otp_10302, otp_11286, otp_13916, otp_14285, otp_17023,
compiler_warnings]},
@@ -368,6 +369,42 @@ syntax(Config) when is_list(Config) ->
leex:file(Filename, Ret),
ok.
+deterministic(doc) ->
+ "Check leex respects the +deterministic flag.";
+deterministic(suite) -> [];
+deterministic(Config) when is_list(Config) ->
+ Dir = ?privdir,
+ Filename = filename:join(Dir, "file.xrl"),
+ Scannerfile = filename:join(Dir, "file.erl"),
+ Mini = <<"Definitions.\n"
+ "D = [0-9]\n"
+ "Rules.\n"
+ "{L}+ : {token,{word,TokenLine,TokenChars}}.\n"
+ "Erlang code.\n">>,
+ ok = file:write_file(Filename, Mini),
+
+ %% Generated leex scanners include the leexinc.hrl header file by default,
+ %% so we'll get a -file attribute corresponding to that include. In
+ %% deterministic mode, that include should only use the basename,
+ %% "leexinc.hrl", but otherwise, it should contain the full path.
+
+ %% Matches when OTP is not installed (e.g. /lib/parsetools/include/leexinc.hrl)
+ %% and when it is (e.g. /lib/parsetools-2.3.2/include/leexinc.hrl)
+ AbsolutePathSuffix = ".*/lib/parsetools.*/include/leexinc\.hrl",
+
+ ok = leex:compile(Filename, Scannerfile, #options{specific=[deterministic]}),
+ {ok, FormsDet} = epp:parse_file(Scannerfile,[]),
+ ?assertMatch(false, search_for_file_attr(AbsolutePathSuffix, FormsDet)),
+ ?assertMatch({value, _}, search_for_file_attr("leexinc\.hrl", FormsDet)),
+ file:delete(Scannerfile),
+
+ ok = leex:compile(Filename, Scannerfile, #options{}),
+ {ok, Forms} = epp:parse_file(Scannerfile,[]),
+ ?assertMatch({value, _}, search_for_file_attr(AbsolutePathSuffix, Forms)),
+ file:delete(Scannerfile),
+
+ file:delete(Filename),
+ ok.
pt(doc) ->
"Pushing back characters.";
@@ -1043,7 +1080,7 @@ otp_11286(doc) ->
"OTP-11286. A Unicode filename bug; both Leex and Yecc.";
otp_11286(suite) -> [];
otp_11286(Config) when is_list(Config) ->
- Node = start_node(otp_11286, "+fnu"),
+ {ok, Peer, Node} = ?CT_PEER(["+fnu"]),
Dir = ?privdir,
UName = [1024] ++ "u",
UDir = filename:join(Dir, UName),
@@ -1087,7 +1124,7 @@ otp_11286(Config) when is_list(Config) ->
{ok,_,_} = rpc:call(Node, compile, file,
[Scannerfile,[basic_validation,return]]),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
otp_13916(doc) ->
@@ -1127,8 +1164,6 @@ otp_13916(Config) when is_list(Config) ->
ok.
otp_14285(Config) ->
- Dir = ?privdir,
-
Ts = [{otp_14285_1,
<<"%% encoding: latin-1\n"
"Definitions.\n"
@@ -1210,17 +1245,6 @@ erlang:display({erlfile,ErlFile}),
{ok, compiler_warnings, []} = compile:file(ErlFile, [return]),
ok.
-start_node(Name, Args) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
- ct:log("Trying to start ~w@~s~n", [Name,Host]),
- case test_server:start_node(Name, peer, [{args,Args}]) of
- {error,Reason} ->
- ct:fail(Reason);
- {ok,Node} ->
- ct:log("Node ~p started~n", [Node]),
- Node
- end.
-
unwritable(Fname) ->
{ok, Info} = file:read_file_info(Fname),
Mode = Info#file_info.mode - 8#00200,
@@ -1285,3 +1309,13 @@ extract(File, {error, Es, Ws}) ->
{errors, extract(File, Es), extract(File, Ws)};
extract(File, Ts) ->
lists:append([T || {F, T} <- Ts, F =:= File]).
+
+search_for_file_attr(PartialFilePathRegex, Forms) ->
+ lists:search(fun
+ ({attribute, _, file, {FileAttr, _}}) ->
+ case re:run(FileAttr, PartialFilePathRegex) of
+ nomatch -> false;
+ _ -> true
+ end;
+ (_) -> false end,
+ Forms).
diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl
index 5162315076..e76b98f0f5 100644
--- a/lib/parsetools/test/yecc_SUITE.erl
+++ b/lib/parsetools/test/yecc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
%-define(debug, true).
-include_lib("stdlib/include/erl_compile.hrl").
+-include_lib("stdlib/include/assert.hrl").
-ifdef(debug).
-define(config(X,Y), foo).
@@ -40,7 +41,7 @@
-export([app_test/1,
file/1, syntax/1, compile/1, rules/1, expect/1,
- conflicts/1,
+ conflicts/1, deterministic/1,
empty/1, prec/1, yeccpre/1, lalr/1, old_yecc/1,
other_examples/1,
@@ -70,7 +71,7 @@ all() ->
groups() ->
[{checks, [],
- [file, syntax, compile, rules, expect, conflicts]},
+ [file, syntax, compile, rules, expect, conflicts, deterministic]},
{examples, [],
[empty, prec, yeccpre, lalr, old_yecc, other_examples]},
{bugs, [],
@@ -269,7 +270,7 @@ syntax(Config) when is_list(Config) ->
nt -> t.">>),
{ok,_,[{_,[{{2,13},yecc,bad_declaration}]}]} =
yecc:file(Filename, Ret),
- ?line {ok,_,[{_,[{2,yecc,bad_declaration}]}]} =
+ {ok,_,[{_,[{2,yecc,bad_declaration}]}]} =
yecc:file(Filename, [{error_location, line} | Ret]),
%% Syntax error found by yeccparser.
@@ -926,6 +927,43 @@ conflicts(Config) when is_list(Config) ->
file:delete(Filename),
ok.
+deterministic(doc) ->
+ "Check yecc respects the +deterministic flag.";
+deterministic(suite) -> [];
+deterministic(Config) when is_list(Config) ->
+ Dir = ?privdir,
+ Filename = filename:join(Dir, "file.yrl"),
+ Parserfile = filename:join(Dir, "file.erl"),
+ ok = file:write_file(Filename,
+ <<"Nonterminals nt.
+ Terminals t.
+ Rootsymbol nt.
+ nt -> t.">>),
+
+ %% Generated yecc parsers need to include the yeccpre.hrl
+ %% header file, so we'll get a -file attribute corresponding
+ %% to that include. In deterministic mode, that include should
+ %% only use the basename, "yeccpre.hrl", but otherwise, it should
+ %% contain the full path.
+
+ %% Matches when OTP is not installed (e.g. /lib/parsetools/include/yeccpre.hrl)
+ %% and when it is (e.g. /lib/parsetools-2.3.2/include/yeccpre.hrl)
+ AbsolutePathSuffix = "/lib/parsetools.*/include/yeccpre\.hrl",
+
+ ok = yecc:compile(Filename, Parserfile, #options{specific=[deterministic]}),
+ {ok, FormsDet} = epp:parse_file(Parserfile,[]),
+ ?assertMatch(false, search_for_file_attr(AbsolutePathSuffix, FormsDet)),
+ ?assertMatch({value, _}, search_for_file_attr("yeccpre\.hrl", FormsDet)),
+ file:delete(Parserfile),
+
+ ok = yecc:compile(Filename, Parserfile, #options{}),
+ {ok, Forms} = epp:parse_file(Parserfile,[]),
+ ?assertMatch({value, _}, search_for_file_attr(AbsolutePathSuffix, Forms)),
+ file:delete(Parserfile),
+
+ file:delete(Filename),
+ ok.
+
empty(doc) ->
"'$empty'.";
empty(suite) -> [];
@@ -1851,7 +1889,7 @@ otp_7969(Config) when is_list(Config) ->
ok.
otp_8919(doc) ->
- "OTP-8919. Improve formating of Yecc error messages.";
+ "OTP-8919. Improve formatting of Yecc error messages.";
otp_8919(suite) -> [];
otp_8919(Config) when is_list(Config) ->
A1 = erl_anno:new(1),
@@ -2042,7 +2080,7 @@ otp_11286(doc) ->
"OTP-11286. A Unicode filename bug; both Leex and Yecc.";
otp_11286(suite) -> [];
otp_11286(Config) when is_list(Config) ->
- Node = start_node(otp_11286, "+fnu"),
+ {ok, Peer, Node} = ?CT_PEER(["+fnu"]),
Dir = ?privdir,
UName = [1024] ++ "u",
UDir = filename:join(Dir, UName),
@@ -2082,7 +2120,7 @@ otp_11286(Config) when is_list(Config) ->
Opts = [return, warn_unused_vars,{outdir,Dir}],
{ok,_,_} = rpc:call(Node, compile, file, [ErlFile, Opts]),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
otp_14285(Config) ->
@@ -2214,17 +2252,6 @@ otp_17535(Config) when is_list(Config) ->
{ok, _, []} = compile:file(ErlFile, [return]),
ok.
-start_node(Name, Args) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
- ct:log("Trying to start ~w@~s~n", [Name,Host]),
- case test_server:start_node(Name, peer, [{args,Args}]) of
- {error,Reason} ->
- ct:fail(Reason);
- {ok,Node} ->
- ct:log("Node ~p started~n", [Node]),
- Node
- end.
-
yeccpre_size() ->
yeccpre_size(default_yeccpre()).
@@ -2295,3 +2322,13 @@ process_list() ->
safe_second_element({_,Info}) -> Info;
safe_second_element(Other) -> Other.
+
+search_for_file_attr(PartialFilePathRegex, Forms) ->
+ lists:search(fun
+ ({attribute, _, file, {FileAttr, _}}) ->
+ case re:run(FileAttr, PartialFilePathRegex) of
+ nomatch -> false;
+ _ -> true
+ end;
+ (_) -> false end,
+ Forms).
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index d68af7fd01..f903e0274d 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.3.2
+PARSETOOLS_VSN = 2.4.1
diff --git a/lib/public_key/.gitignore b/lib/public_key/.gitignore
index d30fe62c9d..8d0ebe018f 100644
--- a/lib/public_key/.gitignore
+++ b/lib/public_key/.gitignore
@@ -1,7 +1,9 @@
# public_key
-asn1/*.asn1db
-asn1/*.erl
-asn1/*.hrl
+src/*.asn1db
+src/OTP-PUB-KEY.erl
+src/OTP-PUB-KEY.hrl
+src/PKCS-FRAME.erl
+src/PKCS-FRAME.hrl
include/OTP-PUB-KEY.hrl
include/PKCS-FRAME.hrl
diff --git a/lib/public_key/Makefile b/lib/public_key/Makefile
index c033d4bfcd..a476140365 100644
--- a/lib/public_key/Makefile
+++ b/lib/public_key/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2021. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
# ----------------------------------------------------
-SUB_DIRECTORIES = asn1 src doc/src
+SUB_DIRECTORIES = asn1 src c_src doc/src
include vsn.mk
VSN = $(PUBLIC_KEY_VSN)
diff --git a/lib/public_key/asn1/ECPrivateKey.asn1 b/lib/public_key/asn1/ECPrivateKey.asn1
index e0f4c3a011..926afe5b29 100644
--- a/lib/public_key/asn1/ECPrivateKey.asn1
+++ b/lib/public_key/asn1/ECPrivateKey.asn1
@@ -19,7 +19,7 @@ ECPrivateKey ::= SEQUENCE {
privateKey CurvePrivateKey,
parameters [0] EcpkParameters OPTIONAL,
publicKey [1] CurvePublicKey OPTIONAL,
- -- Should be PKCS-8 Attributes but problem at the moment with PKCS-8 beeing part
+ -- Should be PKCS-8 Attributes but problem at the moment with PKCS-8 being part
-- of PCKS-FRAME and PKIX1Algorithms88 is part of OTP-PUB-KEY. Procrastinate
-- the solution as it mostly not used anyway
attributes ANY OPTIONAL
diff --git a/lib/public_key/asn1/Makefile b/lib/public_key/asn1/Makefile
index 1fef168463..c1adf58ed4 100644
--- a/lib/public_key/asn1/Makefile
+++ b/lib/public_key/asn1/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2020. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,6 +18,9 @@
# %CopyrightEnd%
#
+EGEN = ../src
+ESRC = ../src
+
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
@@ -39,28 +42,26 @@ RELSYSDIR = $(RELEASE_PATH)/lib/public_key-$(VSN)
.SUFFIXES: .asn1
.PRECIOUS: %.erl
+INCLUDE = ../include
+EBIN = ../ebin
+
ASN_TOP = OTP-PUB-KEY PKCS-FRAME
ASN_MODULES = PKIX1Explicit88 PKIX1Implicit88 PKIX1Algorithms88 \
PKIXAttributeCertificate PKCS-1 PKCS-3 PKCS-7 PKCS-8 PKCS-10 PKCS5v2-0 OTP-PKIX \
InformationFramework RFC5639 CMSAesRsaesOaep
ASN_ASNS = $(ASN_MODULES:%=%.asn1)
-ASN_ERLS = $(ASN_TOP:%=%.erl)
+ASN_ERLS = $(ASN_TOP:%=$(ESRC)/%.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)
-GEN_MODULES =
-GEN_ERLS = $(GEN_MODULES:%=%.erl)
ERL_MODULES = $(ASN_TOP) $(GEN_MODULES)
TARGET_FILES= $(ERL_MODULES:%=$(EBIN)/%.$(EMULATOR))
HRL_FILES = $(ASN_HRLS:%=$(INCLUDE)/%)
-INCLUDE = ../include
-EBIN = ../ebin
-
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -69,22 +70,26 @@ ERL_COMPILE_FLAGS += $(EXTRA_ERLC_FLAGS)
ASN_FLAGS = -bber +der +noobj +asn1config
+ifeq ($(ERL_DETERMINISTIC),yes)
+ ASN_FLAGS += +deterministic
+endif
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(HRL_FILES)
+$(TYPES): $(TARGET_FILES) $(HRL_FILES)
clean:
- -rm -f $(ASN_ERLS) $(GEN_ERLS) $(ASN_HRLS) $(HRL_FILES) $(ASN_DBS) \
+ -rm -f $(ASN_ERLS) $(ASN_HRLS) $(HRL_FILES) $(ASN_DBS) \
$(ASN_TABLES) $(TARGET_FILES) *.beam *~
docs:
-%.erl %.hrl: %.set.asn
- $(asn_verbose)erlc $(ASN_FLAGS) $<
+$(ESRC)/%.erl $(ESRC)/%.hrl: %.set.asn
+ $(asn_verbose)erlc $(ASN_FLAGS) -o $(ESRC) $<
-$(INCLUDE)/%.hrl: %.hrl
+$(INCLUDE)/%.hrl: $(ESRC)/%.hrl
$(gen_verbose)cp -p $< $@
# ----------------------------------------------------
@@ -96,8 +101,10 @@ release_spec: opt
$(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_DATA) $(ASN_ASNS) $(ASN_CONFIGS) \
+ "$(RELSYSDIR)/asn1"
+ $(INSTALL_DIR) "$(RELSYSDIR)/src"
+ $(INSTALL_DATA) $(ASN_ERLS) "$(RELSYSDIR)/src"
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
$(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
@@ -106,7 +113,7 @@ release_docs_spec:
#
# Dependencies
-$(EBIN)/OTP-PUB-KEY.beam: OTP-PUB-KEY.erl OTP-PUB-KEY.hrl
+$(EBIN)/OTP-PUB-KEY.beam: $(ESRC)/OTP-PUB-KEY.erl $(INCLUDE)/OTP-PUB-KEY.hrl
OTP-PUB-KEY.erl OTP-PUB-KEY.hrl: OTP-PUB-KEY.asn1db
OTP-PUB-KEY.asn1db: PKIX1Algorithms88.asn1 \
PKIX1Explicit88.asn1 \
@@ -120,7 +127,7 @@ OTP-PUB-KEY.asn1db: PKIX1Algorithms88.asn1 \
OTP-PKIX.asn1 \
RFC5639.asn1
-$(EBIN)/PKCS-FRAME.beam: PKCS-FRAME.erl PKCS-FRAME.hrl
+$(EBIN)/PKCS-FRAME.beam: $(ESRC)/PKCS-FRAME.erl $(INCLUDE)/PKCS-FRAME.hrl
PKCS-FRAME.erl PKCS-FRAME.hrl: PKCS-FRAME.asn1db
PKCS-FRAME.asn1db: PKCS5v2-0.asn1\
PKCS-8.asn1\
diff --git a/lib/public_key/c_src/Makefile b/lib/public_key/c_src/Makefile
new file mode 100644
index 0000000000..535d6c9218
--- /dev/null
+++ b/lib/public_key/c_src/Makefile
@@ -0,0 +1,127 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2022. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# %CopyrightEnd%
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(PUBLIC_KEY_VSN)
+
+# ----------------------------------------------------
+# The following variables differ on different systems, we set
+# reasonable defaults, if something different is needed it should
+# be set for that system only.
+# ----------------------------------------------------
+CC = $(DED_CC)
+CFLAGS = $(DED_CFLAGS) -I./
+LD = $(DED_LD)
+SHELL = /bin/sh
+#LIBS = $(DED_LIBS) @LIBS@
+LIBS = $(DED_LIBS)
+LDFLAGS += $(DED_LDFLAGS)
+
+PUBKEY_LIBNAME = public_key
+
+SYSINCLUDE = $(DED_SYS_INCLUDE)
+
+PUBKEY_INCLUDES = $(SYSINCLUDE)
+
+ifeq ($(TYPE),debug)
+TYPEMARKER = .debug
+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 = $(CFLAGS)
+endif
+endif
+
+#DEFS = @DEFS@
+#CONFIG_H_DIR = @ERTS_CONFIG_H_IDIR@
+
+ALL_CFLAGS = $(DEFS) $(CONFIG_H_DIR) $(TYPE_FLAGS) $(PUBKEY_INCLUDES) \
+ -I$(OBJDIR) -I$(ERL_TOP)/erts/emulator/$(TARGET)
+
+ROOTDIR = $(ERL_TOP)/lib
+PRIVDIR = ../priv
+LIBDIR = $(PRIVDIR)/lib/$(TARGET)
+OBJDIR = $(PRIVDIR)/obj/$(TARGET)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/public_key-$(VSN)
+
+# ----------------------------------------------------
+# Misc Macros
+# ----------------------------------------------------
+
+ifeq ($(TARGET),win32)
+PUBKEY_LIB = $(LIBDIR)/$(PUBKEY_LIBNAME)$(TYPEMARKER).$(DED_EXT)
+DIRS = $(OBJDIR) $(LIBDIR)
+endif
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
+
+debug opt valgrind: $(DIRS) $(PUBKEY_LIB)
+
+$(OBJDIR):
+ -@mkdir -p $(OBJDIR)
+
+$(LIBDIR):
+ -@mkdir -p $(LIBDIR)
+
+$(OBJDIR)/%$(TYPEMARKER).o: %.c
+ $(V_CC) -c -o $@ $(ALL_CFLAGS) $<
+
+$(LIBDIR)/%$(TYPEMARKER).$(DED_EXT): $(OBJDIR)/%$(TYPEMARKER).o
+ $(V_LD) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+clean:
+ rm -f $(PUBKEY_LIB)
+ rm -f core *~
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+ifeq ($(TARGET),win32)
+release_spec: opt
+ $(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
+ $(INSTALL_PROGRAM) $(PUBKEY_LIB) "$(RELSYSDIR)/priv/lib"
+else
+release_spec: opt
+
+endif
+release_docs_spec:
diff --git a/lib/public_key/c_src/public_key.c b/lib/public_key/c_src/public_key.c
new file mode 100644
index 0000000000..fb6fc2b3b3
--- /dev/null
+++ b/lib/public_key/c_src/public_key.c
@@ -0,0 +1,107 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2022. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Purpose: CaCert fetcher
+ */
+
+#include <erl_nif.h>
+
+#ifdef WINVER /* Windows */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <Wincrypt.h>
+#pragma comment(lib, "crypt32.lib")
+#endif
+
+ERL_NIF_TERM ATOM_PKCS_7_ASN_ENCODING;
+ERL_NIF_TERM ATOM_X509_ASN_ENCODING;
+ERL_NIF_TERM ATOM_UNKNOWN;
+
+ERL_NIF_TERM ATOM_OPEN_ERROR;
+
+static ERL_NIF_TERM os_cacerts(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ ATOM_UNKNOWN = enif_make_atom(env,"unknown");
+ ATOM_OPEN_ERROR = enif_make_atom(env, "internal_error");
+ ATOM_PKCS_7_ASN_ENCODING = enif_make_atom(env,"pkcs_7_asn_encoding");
+ ATOM_X509_ASN_ENCODING = enif_make_atom(env,"x509_asn_encoding");
+
+ return 0;
+}
+
+static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
+ ERL_NIF_TERM load_info)
+{
+ return 0;
+}
+
+static void unload(ErlNifEnv* env, void* priv_data)
+{
+}
+
+static ErlNifFunc nif_funcs[] =
+ {
+ {"os_cacerts", 0, os_cacerts, 0},
+ };
+
+ERL_NIF_INIT(pubkey_os_cacerts, nif_funcs, load, NULL, upgrade, unload)
+
+
+#ifdef WINVER
+ERL_NIF_TERM os_cacerts(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ HANDLE hStoreHandle = NULL;
+ PCCERT_CONTEXT pCertContext = NULL;
+ ERL_NIF_TERM head, tail, der, enc;
+ unsigned char * data;
+
+ hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0,
+ // CERT_SYSTEM_STORE_LOCAL_MACHINE,
+ CERT_SYSTEM_STORE_CURRENT_USER,
+ L"ROOT");
+ if (!hStoreHandle) {
+ return ATOM_OPEN_ERROR;
+ }
+
+ tail = enif_make_list(env, 0);
+ while((pCertContext = CertEnumCertificatesInStore(hStoreHandle,pCertContext))) {
+ switch (pCertContext->dwCertEncodingType) {
+ case X509_ASN_ENCODING:
+ enc = ATOM_X509_ASN_ENCODING;
+ break;
+ case PKCS_7_ASN_ENCODING:
+ enc = ATOM_PKCS_7_ASN_ENCODING;
+ break;
+ default:
+ enc = ATOM_UNKNOWN;
+ }
+ data = enif_make_new_binary(env, pCertContext->cbCertEncoded, &der);
+ memcpy(data, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
+ head = enif_make_tuple2(env, enc, der);
+ tail = enif_make_list_cell(env, head, tail);
+ }
+
+ CertCloseStore(hStoreHandle, 0);
+ return tail;
+}
+#endif
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index b31f51491b..70e1c819f3 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2021</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -35,6 +35,172 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.13.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ As different solutions of verifying certificate
+ revocation exists move the decode of
+ 'CRLDistributionPoints' so that it will only be decode.
+ When it is actually used in the verification process.
+ This would enable interoperability with systems that use
+ certificates with an invalid empty CRLDistributionPoints
+ extension that they want to ignore and make verification
+ by other means.</p>
+ <p>
+ Own Id: OTP-18316 Aux Id: GH-6402, PR-6883 </p>
+ </item>
+ <item>
+ <p>
+ public_key:pkix_path_validation validates certificates
+ expiring after 2050</p>
+ <p>
+ Own Id: OTP-18356 Aux Id: GH-6403 </p>
+ </item>
+ <item>
+ <p>
+ Do not leave exit message in message queue after calling
+ <c>cacerts_load()</c> on MacOS.</p>
+ <p>
+ Own Id: OTP-18392 Aux Id: GH-6656 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.13.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Disregard LDAP URIs when HTTP URIs are expected.</p>
+ <p>
+ Own Id: OTP-18333 Aux Id: GH-6363 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.13.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Support more Linux distributions in cacerts_load/0.</p>
+ <p>
+ Own Id: OTP-18154 Aux Id: PR-6002 </p>
+ </item>
+ <item>
+ <p>
+ Correct asn1 typenames available in type pki_asn1_type()</p>
+ <p>
+ Own Id: OTP-18189 Aux Id: ERIERL-829 </p>
+ </item>
+ <item>
+ <p>
+ Sign/verify does now behave as in OTP-24 and earlier for
+ eddsa.</p>
+ <p>
+ Own Id: OTP-18205 Aux Id: GH-6219 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added functions to retrieve OS provided CA-certs.</p>
+ <p>
+ Own Id: OTP-17798 Aux Id: GH-5760 </p>
+ </item>
+ <item>
+ <p>
+ Allow key file passwords to be input as a single binary,
+ that is we change the data type to be the more for the
+ purpose logical data type iodata() instead of string().</p>
+ <p>
+ Own Id: OTP-17890</p>
+ </item>
+ <item>
+ <p>
+ The deprecated public_key functions ssh_decode/2,
+ ssh_encode/2, ssh_hostkey_fingerprint/1 and
+ ssh_hostkey_fingerprint/2 are removed.</p>
+ <p>
+ They are replaced by ssh_file:decode/2,
+ ssh_file:encode/2, ssh:hostkey_fingerprint/1 and
+ ssh:hostkey_fingerprint/2 respectively.</p>
+ <p>
+ Note that the decode/2 and encode/2 are not exact
+ replacement functions, some minor changes may be needed.
+ Se the manual for more information.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17921</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Public_Key 1.12.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct asn1 typenames available in type pki_asn1_type()</p>
+ <p>
+ Own Id: OTP-18189 Aux Id: ERIERL-829 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.12</title>
<section><title>Improvements and New Features</title>
@@ -426,7 +592,7 @@
<list>
<item>
<p>
- Support Pasword based encryption with AES</p>
+ Support Password based encryption with AES</p>
<p>
Own Id: OTP-15870 Aux Id: ERL-952 </p>
</item>
@@ -597,7 +763,7 @@
</item>
<item>
<p>
- Compleate PKCS-8 encoding support and enhance the
+ Complete PKCS-8 encoding support and enhance the
decoding of 'PrivateKeyInfo' to conform to the rest of
Erlang public_key API.</p>
<p>
@@ -694,7 +860,7 @@
saltlength setting<br/> * X9.31 RSA padding.<br/> * sha,
sha224, sha256, sha384, and sha512 for dss signatures as
mentioned in NIST SP 800-57 Part 1.<br/> * ripemd160 to
- be used for rsa signatures.</p>
+ be used for RSA signatures.</p>
<p>
This is a manual merge of half of the pull request 838 by
potatosalad from Sept 2015.</p>
@@ -705,7 +871,7 @@
<p>
Add API function pkix_test_data/1 for facilitating
automated testing. This is useful for applications that
- preform X509-certifcate path validation of so called
+ perform X509-certifcate path validation of so called
certificate chains, such as TLS.</p>
<p>
Own Id: OTP-14181</p>
@@ -889,7 +1055,7 @@
</item>
<item>
<p>
- Add different upper bounds for diffrent string types as
+ Add different upper bounds for different string types as
suggested by comment in PKIX1Explicit88.</p>
<p>
Own Id: OTP-13132</p>
@@ -1093,7 +1259,7 @@
<item>
<p>
Add support for ISO oids 1.3.14.3.2.29 and 1.3.14.3.2.27
- that are somtimes used instead of the PKCS defined oids
+ that are sometimes used instead of the PKCS defined oids
1.2.840.113549.1.1.5 and 1.2.840.10040.4.3. Add function
pkix_sign_types:/1 that translates oids to to algorithm
atoms ex:</p>
@@ -1186,7 +1352,7 @@
<item>
<p>
ssh_decode now handles comments, at the end of the line,
- containing withe spaces correctly</p>
+ containing with spaces correctly</p>
<p>
Own Id: OTP-9361</p>
</item>
@@ -1204,7 +1370,7 @@
<list>
<item>
<p>
- public_key now supports PKCS-10 and includes exprimental
+ public_key now supports PKCS-10 and includes experimental
support for PKCS-7</p>
<p>
Own Id: OTP-10509 Aux Id: kunagi-291 [202] </p>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 76179ceb6f..501b7be954 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -122,10 +122,7 @@
<datatype>
<name name="ed_public_key"/>
- <name name="ed_legacy_pubkey"/>
<desc>
- <warning><p>The tagged ed_pub format will not be returned from any public_key
- functions but can be used as input, should be considered deprecated.</p></warning>
</desc>
</datatype>
@@ -145,10 +142,7 @@
<datatype>
<name name="ed_private_key"/>
- <name name="ed_legacy_privkey"/>
<desc>
- <warning><p>The tagged ed_pri format will not be returned from any public_key
- functions but can be used as input, should be considered deprecated.</p></warning>
</desc>
</datatype>
@@ -271,18 +265,47 @@
</desc>
</datatype>
- <datatype>
- <name name="ssh_file"/>
- <desc>
- </desc>
- </datatype>
+ </datatypes>
+<funcs>
- </datatypes>
+ <func>
+ <name name="cacerts_clear" arity="0" since="OTP 25.0"/>
+ <fsummary>Clears any loaded CA certificates.</fsummary>
+ <desc>
+ <p>Clears any loaded CA certificates, returns true if any was loaded.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="cacerts_get" arity="0" since="OTP 25.0"/>
+ <fsummary>Returns CA certificates.</fsummary>
+ <desc>
+ <p>Returns the trusted CA certificates if any are loaded, otherwise
+ uses <seemfa marker="#cacerts_load/0">cacerts_load/0</seemfa> to load them.
+ The function fails if no <c>cacerts</c> could be loaded.</p>
+ </desc>
+ </func>
-<funcs>
+ <func>
+ <name name="cacerts_load" arity="0" since="OTP 25.0"/>
+ <fsummary>Loads OS specific CA certificates.</fsummary>
+ <desc>
+ <p>Loads the OS supplied trusted CA certificates.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="cacerts_load" arity="1" since="OTP 25.0"/>
+ <fsummary>Loads CA certificates.</fsummary>
+ <desc>
+ <p>Loads the trusted CA certificates from a file.
+ </p>
+ </desc>
+ </func>
<func>
<name name="compute_key" arity="2" since="OTP R16B01"/>
@@ -801,7 +824,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
critical = false}]
</code>
<p>Hostname is the result of calling net_adm:localhost() in the Erlang node
- where this funcion is called.
+ where this function is called.
</p></item>
</taglist>
@@ -953,106 +976,6 @@ end
</func>
<func>
- <name name="ssh_decode" arity="2" since="OTP R14B03"/>
- <fsummary>Decodes an SSH file-binary.</fsummary>
- <desc>
- <note>
- <p>This function is deprecated and should not be used in new programs. Use
- <seemfa marker="ssh:ssh_file#decode/2">ssh_file:decode/2</seemfa>
- instead.
- </p>
- </note>
- <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
- <c>auth_keys</c>, the binary can include one or more lines of the
- file. Returns a list of public keys and their attributes, possible
- attribute values depends on the file type represented by the
- binary.
- </p>
- <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the result will be
- <c>Decoded_ssh2_pubkey</c>. Otherwise it will be <c>Decoded_OtherType</c>.
- </p>
- <taglist>
- <tag>RFC4716 attributes - see RFC 4716.</tag>
- <item><p>{headers, [{string(), utf8_string()}]}</p></item>
- <tag>auth_key attributes - see manual page for sshd.</tag>
- <item>{comment, string()}</item>
- <item>{options, [string()]}</item>
- <item><p>{bits, integer()} - In SSH version 1 files.</p></item>
- <tag>known_host attributes - see manual page for sshd.</tag>
- <item>{hostnames, [string()]}</item>
- <item>{comment, string()}</item>
- <item><p>{bits, integer()} - In SSH version 1 files.</p></item>
- </taglist>
- <p>Example: <c>{ok, SshBin} = file:read_file("known_hosts")</c>.
- </p>
- <p>If <c>Type</c> is <c>public_key</c> the binary can be either
- an RFC4716 public key or an OpenSSH public key.</p>
- </desc>
- </func>
-
- <func>
- <name name="ssh_encode" arity="2" since="OTP R14B03"/>
- <fsummary>Encodes a list of SSH file entries to a binary.</fsummary>
- <desc>
- <note>
- <p>This function is deprecated and should not be used in new programs. Use
- <seemfa marker="ssh:ssh_file#encode/2">ssh_file:encode/2</seemfa>
- instead.
- </p>
- </note>
- <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
- attributes depend on the file type, see
- <seemfa marker="#ssh_decode/2"> ssh_decode/2 </seemfa>.
- </p>
- <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the <c>InData</c> shall be
- <c>InData_ssh2_pubkey</c>. Otherwise it shall be <c>OtherInData</c>.
- </p>
- </desc>
- </func>
-
- <func>
- <name since="OTP 19.2">ssh_hostkey_fingerprint(HostKey) -> string()</name>
- <name since="OTP 19.2">ssh_hostkey_fingerprint(DigestType, HostKey) -> string()</name>
- <name since="OTP 19.2">ssh_hostkey_fingerprint([DigestType], HostKey) -> [string()]</name>
- <fsummary>Calculates a ssh fingerprint for a hostkey.</fsummary>
- <type>
- <v>HostKey = <seetype marker="#public_key">public_key()</seetype></v>
- <v>DigestType = <seetype marker="#digest_type">digest_type()</seetype></v>
- </type>
- <desc>
- <p>Calculates a ssh fingerprint from a public host key as openssh does.</p>
- <note>
- <p>This function is deprecated and should not be used in new programs. Use
- <seemfa marker="ssh:ssh#hostkey_fingerprint/1">ssh:hostkey_fingerprint/1</seemfa> or
- <seemfa marker="ssh:ssh#hostkey_fingerprint/2">ssh:hostkey_fingerprint/2</seemfa>
- instead.
- </p>
- </note>
- <p>The algorithm in <c>ssh_hostkey_fingerprint/1</c> is md5 to be compatible with older
- ssh-keygen commands. The string from the second variant is prepended by the algorithm name
- in uppercase as in newer ssh-keygen commands.</p>
- <p>Examples:</p>
- <code>
- 2> public_key:ssh_hostkey_fingerprint(Key).
- "f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
-
- 3> public_key:ssh_hostkey_fingerprint(md5,Key).
- "MD5:f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
-
- 4> public_key:ssh_hostkey_fingerprint(sha,Key).
- "SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY"
-
- 5> public_key:ssh_hostkey_fingerprint(sha256,Key).
- "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"
-
- 6> public_key:ssh_hostkey_fingerprint([sha,sha256],Key).
- ["SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY",
- "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"]
- </code>
- </desc>
- </func>
-
- <func>
<name name="verify" arity="4" since="OTP R14B"/>
<name name="verify" arity="5" since="OTP 20.1"/>
<fsummary>Verifies a digital signature.</fsummary>
diff --git a/lib/public_key/doc/src/using_public_key.xml b/lib/public_key/doc/src/using_public_key.xml
index b783785347..2a8203121d 100644
--- a/lib/public_key/doc/src/using_public_key.xml
+++ b/lib/public_key/doc/src/using_public_key.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2011</year><year>2021</year>
+ <year>2011</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -87,7 +87,7 @@
<p>An RSA private key encrypted with a password can look as follows:</p>
<code>1> {ok, PemBin} = file:read_file("rsa.pem").
-{ok,&lt;&lt;"Bag Attribut"...&gt;&gt;}</code>
+{ok,&lt;&lt;"Bag Attribute"...&gt;&gt;}</code>
<p>The following PEM file has only one entry, a private RSA key:</p>
<code>2>[RSAEntry] = public_key:pem_decode(PemBin).
@@ -382,7 +382,7 @@ Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),</code>
Msg = public_key:decrypt_private(RsaEncrypted, PrivateKey),</code>
<note><p>You normally do only one of the encrypt or decrypt operations,
- and the peer does the other. This normaly used in legacy applications
+ and the peer does the other. This normally used in legacy applications
as a primitive digital signature.
</p></note>
@@ -426,12 +426,12 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
checks that the certificate is not revoked, not forged or not out-of-date.
</p>
<p>There are however attacks that are not detected by those checks. Suppose a bad guy has
- succeded with a DNS infection. Then the client could belive it is connecting to one host but
+ succeeded with a DNS infection. Then the client could believe it is connecting to one host but
ends up at another but evil one. Though it is evil, it could have a perfectly legal
certificate! The certificate has a valid signature, it is not revoked, the certificate chain
is not faked and has a trusted root and so on.
</p>
- <p>To detect that the server is not the intended one, the client must additionaly perform
+ <p>To detect that the server is not the intended one, the client must additionally perform
a <i>hostname verification</i>. This procedure is described in
<url href="https://tools.ietf.org/html/rfc6125">RFC 6125</url>. The idea is that the certificate
lists the hostnames it could be fetched from. This is checked by the certificate issuer when
@@ -447,13 +447,13 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
It is possible for a client to hook in modified rules using the options list.
</p>
<p>Some terminology is needed: the certificate presents hostname(s) on which it is valid.
- Those are called <i>Presented IDs</i>. The hostname(s) the client belives it connects to
+ Those are called <i>Presented IDs</i>. The hostname(s) the client believes it connects to
are called <i>Reference IDs</i>. The matching rules aims to verify that there is at least
one of the Reference IDs that matches one of the Presented IDs. If not, the verification fails.
</p>
<p>The IDs contains normal fully qualified domain names like e.g <c>foo.example.com</c>,
but IP addresses are not recommended. The rfc describes why this is not recommended as well
- as security considerations about how to aquire the Reference IDs.
+ as security considerations about how to acquire the Reference IDs.
</p>
<p>Internationalized domain names are not supported.
</p>
@@ -525,7 +525,7 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
field, the <c>Subject</c> field MUST NOT be used for host name checking, even if it contains
valid CN names.
Therefore only <c>kb.example.org</c> and <c>https://www.example.org</c> matches. The match fails
- both for <c>example.com</c> and <c>foo.example.com</c> becuase they are in the <c>Subject</c>
+ both for <c>example.com</c> and <c>foo.example.com</c> because they are in the <c>Subject</c>
field which is not checked because the <c>Subject Alternate Name</c> field is present.
</p>
</section>
@@ -599,7 +599,7 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
<marker id="redefining_match_op"></marker>
<title>Re-defining the match operation</title>
<p>The default matching handles dns_id and uri_id. In an uri_id the value is tested for
- equality with a value from the <c>Subject Alternate Name</c>. If som other kind of matching
+ equality with a value from the <c>Subject Alternate Name</c>. If some other kind of matching
is needed, use the <c>match_fun</c> option.
</p>
<p>The <c>match_fun</c> takes two arguments and returns either <c>true</c>,
@@ -626,8 +626,8 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
field and from the <c>Subject Alternate Name</c> field.
</p>
<p>The default matching transformes the ascii values in strings to lowercase before comparing.
- The <c>match_fun</c> is however called without any transfomation applied to the strings. The
- reason is to enable the user to do unforseen handling of the strings where the original format
+ The <c>match_fun</c> is however called without any transformation applied to the strings. The
+ reason is to enable the user to do unforeseen handling of the strings where the original format
is needed.
</p>
</section>
@@ -672,99 +672,4 @@ true = public_key:verify(Digest, none, Signature, PublicKey),</code>
</section>
</section>
- <section>
- <title>SSH Files</title>
-
- <p>SSH typically uses PEM files for private keys but has its
- own file format for storing public keys. The <c>public_key</c>
- application can be used to parse the content of SSH public-key files.</p>
-
- <section>
- <title>RFC 4716 SSH Public-Key Files</title>
-
- <p>RFC 4716 SSH files looks confusingly like PEM files,
- but there are some differences:</p>
- <code>1> {ok, SshBin} = file:read_file("ssh2_rsa_pub").
-{ok, &lt;&lt;"---- BEGIN SSH2 PUBLIC KEY ----\nAAAA"...&gt;&gt;}</code>
-
- <p>This is equivalent to calling <c>public_key:ssh_decode(SshBin, rfc4716_public_key)</c>:
- </p>
- <code>2> public_key:ssh_decode(SshBin, public_key).
-[{#'RSAPublicKey'{modulus = 794430685...91663,
- publicExponent = 35}, []}]</code>
-
- </section>
-
- <section>
- <title>OpenSSH Public-Key Format</title>
- <p>OpenSSH public-key format looks as follows:</p>
- <code>1> {ok, SshBin} = file:read_file("openssh_dsa_pub").
-{ok,&lt;&lt;"ssh-dss AAAAB3Nza"...&gt;&gt;}</code>
-
- <p>This is equivalent to calling <c>public_key:ssh_decode(SshBin, openssh_public_key)</c>:
- </p>
- <code>2> public_key:ssh_decode(SshBin, public_key).
-[{{15642692...694280725,
- #'Dss-Parms'{p = 17291273936...696123221,
- q = 1255626590179665817295475654204371833735706001853,
- g = 10454211196...480338645}},
- [{comment,"dhopson@VMUbuntu-DSH"}]}]</code>
- </section>
-
- <section>
- <title>Known Hosts - OpenSSH Format</title>
- <p>Known hosts - OpenSSH format looks as follows:</p>
- <code>1> {ok, SshBin} = file:read_file("known_hosts").
-{ok,&lt;&lt;"hostname.domain.com,192.168.0.1 ssh-rsa AAAAB...&gt;&gt;}</code>
-
- <p>Returns a list of public keys and their related attributes.
- Each pair of key and attribute corresponds to one entry in
- the known hosts file:</p>
-
- <code>2> public_key:ssh_decode(SshBin, known_hosts).
-[{#'RSAPublicKey'{modulus = 1498979460408...72721699,
- publicExponent = 35},
- [{hostnames,["hostname.domain.com","192.168.0.1"]}]},
- {#'RSAPublicKey'{modulus = 14989794604088...2721699,
- publicExponent = 35},
- [{comment,"foo@bar.com"},
- {hostnames,["|1|BWO5qDxk/cFH0wa05JLdHn+j6xQ=|rXQvIxh5cDD3C43k5DPDamawVNA="]}]}]</code>
- </section>
-
- <section>
- <title>Authorized Keys - OpenSSH Format</title>
- <p>Authorized keys - OpenSSH format looks as follows:</p>
-
- <code>1> {ok, SshBin} = file:read_file("auth_keys").
-{ok, &lt;&lt;"command=\"dump /home\",no-pty,no-port-forwarding ssh-rsa AAA...&gt;&gt;}</code>
-
- <p>Returns a list of public keys and their related attributes.
- Each pair of key and attribute corresponds to one entry in
- the authorized key file:</p>
-
- <code>2> public_key:ssh_decode(SshBin, auth_keys).
-[{#'RSAPublicKey'{modulus = 794430685...691663,
- publicExponent = 35},
- [{comment,"dhopson@VMUbuntu-DSH"},
- {options,["command=\"dump/home\"","no-pty",
- "no-port-forwarding"]}]},
- {{1564269258491...607694280725,
- #'Dss-Parms'{p = 17291273936185...763696123221,
- q = 1255626590179665817295475654204371833735706001853,
- g = 10454211195705...60511039590076780999046480338645}},
- [{comment,"dhopson@VMUbuntu-DSH"}]}]</code>
- </section>
-
- <section>
- <title>Creating an SSH File from Public-Key Data</title>
-
- <p>If you got a public key <c>PubKey</c> and a related list of
- attributes <c>Attributes</c> as returned
- by <c>ssh_decode/2</c>, you can create a new SSH file, for example:</p>
- <code>N> SshBin = public_key:ssh_encode([{PubKey, Attributes}], openssh_public_key),
-&lt;&lt;"ssh-rsa "...&gt;&gt;
-N+1> file:write_file("id_rsa.pub", SshBin).
-ok</code>
- </section>
- </section>
</chapter>
diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile
index e27f02eea9..9b2b442794 100644
--- a/lib/public_key/src/Makefile
+++ b/lib/public_key/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2021. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -47,7 +47,8 @@ MODULES = \
pubkey_cert \
pubkey_cert_records \
pubkey_crl\
- pubkey_ocsp
+ pubkey_ocsp \
+ pubkey_os_cacerts
HRL_FILES = $(INCLUDE)/public_key.hrl
@@ -85,7 +86,7 @@ ERL_COMPILE_FLAGS += $(PUB_KEY_ERL_FLAGS) \
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(HRL_FILES)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(HRL_FILES)
$(EBIN)/pubkey_ssh.$(EMULATOR): pubkey_moduli.hrl
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index abe69d9ae2..4d448fd42c 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,7 +72,7 @@ verify_data(DerCert) ->
-spec init_validation_state(#'OTPCertificate'{}, integer(), list()) ->
#path_validation_state{}.
%%
-%% Description: Creates inital version of path_validation_state for
+%% Description: Creates initial version of path_validation_state for
%% basic path validation of x509 certificates.
%%--------------------------------------------------------------------
init_validation_state(#'OTPCertificate'{} = OtpCert, DefaultPathLen,
@@ -134,7 +134,7 @@ prepare_for_next_cert(OtpCert, ValidationState = #path_validation_state{
}.
%%--------------------------------------------------------------------
--spec validate_time(#'OTPCertificate'{}, term(), fun()) -> term().
+-spec validate_time(#'OTPCertificate'{}, term(), fun()) -> term() | no_return().
%%
%% Description: Check that the certificate validity period includes the
%% current time.
@@ -144,8 +144,8 @@ validate_time(OtpCert, UserState, VerifyFun) ->
{'Validity', NotBeforeStr, NotAfterStr}
= TBSCert#'OTPTBSCertificate'.validity,
Now = calendar:datetime_to_gregorian_seconds(calendar:universal_time()),
- NotBefore = time_str_2_gregorian_sec(NotBeforeStr),
- NotAfter = time_str_2_gregorian_sec(NotAfterStr),
+ NotBefore = time_str_2_gregorian_sec(notBefore, NotBeforeStr),
+ NotAfter = time_str_2_gregorian_sec(notAfter, NotAfterStr),
case ((NotBefore =< Now) and (Now =< NotAfter)) of
true ->
@@ -154,7 +154,7 @@ validate_time(OtpCert, UserState, VerifyFun) ->
verify_fun(OtpCert, {bad_cert, cert_expired}, UserState, VerifyFun)
end.
%%--------------------------------------------------------------------
--spec validate_issuer(#'OTPCertificate'{}, term(), term(), fun()) -> term().
+-spec validate_issuer(#'OTPCertificate'{}, term(), term(), fun()) -> term() | no_return().
%%
%% Description: Check that the certificate issuer name is the working_issuer_name
%% in path_validation_state.
@@ -169,7 +169,7 @@ validate_issuer(OtpCert, Issuer, UserState, VerifyFun) ->
end.
%%--------------------------------------------------------------------
-spec validate_signature(#'OTPCertificate'{}, DER::binary(),
- term(),term(), term(), fun()) -> term().
+ term(),term(), term(), fun()) -> term() | no_return().
%%
%% Description: Check that the signature on the certificate can be verified using
@@ -187,7 +187,7 @@ validate_signature(OtpCert, DerCert, Key, KeyParams,
end.
%%--------------------------------------------------------------------
-spec validate_names(#'OTPCertificate'{}, no_constraints | list(), list(),
- term(), term(), fun())-> term().
+ term(), term(), fun())-> term() | no_return().
%%
%% Description: Validate Subject Alternative Name.
%%--------------------------------------------------------------------
@@ -247,7 +247,7 @@ validate_extensions(OtpCert, ValidationState, UserState, VerifyFun) ->
-spec normalize_general_name({rdnSequence, term()}| binary()) -> {rdnSequence, term()}.
%%
%% Description: Normalizes a general name so that it can be easily
-%% compared to another genral name.
+%% compared to another general name.
%%--------------------------------------------------------------------
normalize_general_name({rdnSequence, Issuer}) ->
NormIssuer = do_normalize_general_name(Issuer),
@@ -333,7 +333,7 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
%%--------------------------------------------------------------------
-spec verify_fun(#'OTPCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}|
- valid | valid_peer, term(), fun()) -> term().
+ valid | valid_peer, term(), fun()) -> term() | no_return().
%%
%% Description: Gives the user application the opportunity handle path
%% validation errors and unknown extensions and optional do other
@@ -370,6 +370,9 @@ select_extension(_, asn1_NOVALUE) ->
undefined;
select_extension(_, []) ->
undefined;
+select_extension(Id, [#'Extension'{extnID = ?'id-ce-cRLDistributionPoints' = Id,
+ extnValue = Value} = Extension | _]) when is_binary(Value) ->
+ Extension#'Extension'{extnValue = public_key:der_decode('CRLDistributionPoints', Value)};
select_extension(Id, [#'Extension'{extnID = Id} = Extension | _]) ->
Extension;
select_extension(Id, [_ | Extensions]) ->
@@ -633,19 +636,44 @@ public_key_info(PublicKeyInfo,
end,
{Algorithm, PublicKey, NewPublicKeyParams}.
-time_str_2_gregorian_sec({utcTime, [Y1,Y2,M1,M2,D1,D2,H1,H2,M3,M4,S1,S2,Z]}) ->
- case list_to_integer([Y1,Y2]) of
- N when N >= 50 ->
- time_str_2_gregorian_sec({generalTime,
- [$1,$9,Y1,Y2,M1,M2,D1,D2,
- H1,H2,M3,M4,S1,S2,Z]});
- _ ->
- time_str_2_gregorian_sec({generalTime,
- [$2,$0,Y1,Y2,M1,M2,D1,D2,
- H1,H2,M3,M4,S1,S2,Z]})
- end;
-
-time_str_2_gregorian_sec({_,[Y1,Y2,Y3,Y4,M1,M2,D1,D2,H1,H2,M3,M4,S1,S2,$Z]}) ->
+%% time_str_2_gregorian_sec/2 is a wrapper (decorator pattern) over
+%% time_str_2_gregorian_sec/1. the decorator deals with notBefore and notAfter
+%% property differently when we pass utcTime because the data format is
+%% ambiguous YYMMDD. on generalTime the year ambiguity cannot happen because
+%% years are expressed in a 4-digit format, i.e., YYYYMMDD.
+-spec time_str_2_gregorian_sec(PeriodOfTime, Time) -> Seconds :: non_neg_integer() when
+ PeriodOfTime :: notBefore | notAfter,
+ Time :: {utcTime | generalTime, [non_neg_integer() | char()]}.
+time_str_2_gregorian_sec(notBefore, {utcTime, [FirstDigitYear | _]=UtcTime}) ->
+ %% To be compliant with PKITS Certification Path Validation,
+ %% we must accept certificates with notBefore = 50, meaning 1950.
+ %% Once the PKITS certification path validation is updated,
+ %% we must update this function body and test case
+ %% {"4.2.3", "Valid pre2000 UTC notBefore Date Test3 EE"}
+ %% in pkits_SUITE.erl
+ Y1 = erlang:list_to_integer([FirstDigitYear]),
+ YearPrefix = case (Y1 > 4 andalso Y1 =< 9) of
+ true -> [$1, $9];
+ false ->
+ {Y, _M, _D} = erlang:date(),
+ integer_to_list(Y div 100)
+ end,
+ time_str_2_gregorian_sec({generalTime, YearPrefix ++ UtcTime});
+
+time_str_2_gregorian_sec(notAfter, {utcTime, UtcTime}) ->
+ SlidingDate = sliding_year_window(UtcTime),
+ time_str_2_gregorian_sec({generalTime, SlidingDate});
+
+time_str_2_gregorian_sec(_, {generalTime, _Time}=GeneralTime) ->
+ time_str_2_gregorian_sec(GeneralTime).
+
+%% converts 'Time' as a string into gregorian time in seconds.
+-spec time_str_2_gregorian_sec(Time) -> Seconds :: non_neg_integer() when
+ Time :: {generalTime | utcTime, string()}.
+time_str_2_gregorian_sec({utcTime, UtcTime}) ->
+ time_str_2_gregorian_sec(notAfter, {utcTime, UtcTime});
+
+time_str_2_gregorian_sec({generalTime,[Y1,Y2,Y3,Y4,M1,M2,D1,D2,H1,H2,M3,M4,S1,S2,$Z]}) ->
Year = list_to_integer([Y1, Y2, Y3, Y4]),
Month = list_to_integer([M1, M2]),
Day = list_to_integer([D1, D2]),
@@ -655,6 +683,28 @@ time_str_2_gregorian_sec({_,[Y1,Y2,Y3,Y4,M1,M2,D1,D2,H1,H2,M3,M4,S1,S2,$Z]}) ->
calendar:datetime_to_gregorian_seconds({{Year, Month, Day},
{Hour, Min, Sec}}).
+%% Sliding window algorithm to calculate the time.
+%% The value is set as taking {Y1, Y2} from the first two digits of
+%% current_date - 50 or current_date - 49.
+sliding_year_window([Y1,Y2,M1,M2,D1,D2,H1,H2,M3,M4,S1,S2,Z]) ->
+ {{CurrentYear,_, _}, _} = calendar:universal_time(),
+ LastTwoDigitYear = CurrentYear rem 100,
+ MinYear = mod(LastTwoDigitYear - 50, 100),
+ YearWindow = case list_to_integer([Y1,Y2]) of
+ N when N < MinYear -> CurrentYear + 50;
+ N when N >= MinYear -> CurrentYear - 49
+ end,
+ [Year1, Year2] = integer_to_list(YearWindow div 100),
+ [Year1,Year2,Y1,Y2,M1,M2,D1,D2,H1,H2,M3,M4,S1,S2,Z].
+
+
+%% Helper function to perform modulo calculation for integer
+-spec mod(A :: integer(), B :: non_neg_integer()) -> non_neg_integer().
+mod(A, B) when A > 0 -> A rem B;
+mod(A, B) when A < 0 -> mod(A+B, B);
+mod(0, _) -> 0.
+
+
is_dir_name([], [], _Exact) -> true;
is_dir_name([H|R1],[H|R2], Exact) -> is_dir_name(R1,R2, Exact);
is_dir_name([[{'AttributeTypeAndValue', Type, What1}]|Rest1],
@@ -1027,6 +1077,8 @@ is_permitted_ip([CandidatIp | CandidatIpRest],
mask_cmp(Canditate, Permitted, Mask) ->
(Canditate band Mask) == Permitted.
+is_valid_host_or_domain([], _) ->
+ false; %% Can happen if URI was not a HTTP URI
is_valid_host_or_domain(Canditate, [$.|_] = Permitted) ->
is_suffix(Permitted, Canditate);
is_valid_host_or_domain(Canditate, Permitted) ->
@@ -1301,7 +1353,7 @@ cert_chain(Role, IssuerCert, IssuerKey, [PeerOpts], _, Acc) ->
cert_chain(Role, IssuerCert, IssuerKey, [CAOpts | Rest], N, Acc) ->
Key = gen_key(proplists:get_value(key, CAOpts, default_key_gen())),
Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin",
- " Intermidiate CA " ++ integer_to_list(N), CAOpts, ca),
+ " Intermediate CA " ++ integer_to_list(N), CAOpts, ca),
cert_chain(Role, Cert, Key, Rest, N+1, [{IssuerCert, encode_key(IssuerKey)} | Acc]).
cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer}},
diff --git a/lib/public_key/src/pubkey_cert_records.erl b/lib/public_key/src/pubkey_cert_records.erl
index 592bd4c938..0bcbe84f87 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ decode_cert(DerCert) ->
%%--------------------------------------------------------------------
-spec transform(term(), encode | decode) ->term().
%%
-%% Description: Transforms between encoded and decode otp formated
+%% Description: Transforms between encoded and decode otp formatted
%% certificate parts.
%%--------------------------------------------------------------------
@@ -262,21 +262,20 @@ extension_id(?'id-ce-keyUsage') -> 'KeyUsage';
extension_id(?'id-ce-privateKeyUsagePeriod') -> 'PrivateKeyUsagePeriod';
extension_id(?'id-ce-certificatePolicies') -> 'CertificatePolicies';
extension_id(?'id-ce-policyMappings') -> 'PolicyMappings';
-extension_id(?'id-ce-subjectAltName') -> 'SubjectAltName';
-extension_id(?'id-ce-issuerAltName') -> 'IssuerAltName';
+extension_id(?'id-ce-subjectAltName') -> 'SubjectAltName';
+extension_id(?'id-ce-issuerAltName') -> 'IssuerAltName';
extension_id(?'id-ce-subjectDirectoryAttributes') -> 'SubjectDirectoryAttributes';
-extension_id(?'id-ce-basicConstraints' ) -> 'BasicConstraints';
-extension_id(?'id-ce-nameConstraints') -> 'NameConstraints';
-extension_id(?'id-ce-policyConstraints') -> 'PolicyConstraints';
-extension_id(?'id-ce-cRLDistributionPoints') -> 'CRLDistributionPoints';
-extension_id(?'id-ce-extKeyUsage') -> 'ExtKeyUsageSyntax';
-extension_id(?'id-ce-inhibitAnyPolicy') -> 'InhibitAnyPolicy';
+extension_id(?'id-ce-basicConstraints' ) -> 'BasicConstraints';
+extension_id(?'id-ce-nameConstraints') -> 'NameConstraints';
+extension_id(?'id-ce-policyConstraints') -> 'PolicyConstraints';
+extension_id(?'id-ce-extKeyUsage') -> 'ExtKeyUsageSyntax';
+extension_id(?'id-ce-inhibitAnyPolicy') -> 'InhibitAnyPolicy';
extension_id(?'id-ce-freshestCRL') -> 'FreshestCRL';
-%% Missing in public_key doc
+extension_id(?'id-ce-issuingDistributionPoint') -> 'IssuingDistributionPoint';
+%% Missing in public_key doc
extension_id(?'id-pe-authorityInfoAccess') -> 'AuthorityInfoAccessSyntax';
extension_id(?'id-pe-subjectInfoAccess') -> 'SubjectInfoAccessSyntax';
extension_id(?'id-ce-cRLNumber') -> 'CRLNumber';
-extension_id(?'id-ce-issuingDistributionPoint') -> 'IssuingDistributionPoint';
extension_id(?'id-ce-deltaCRLIndicator') -> 'BaseCRLNumber';
extension_id(?'id-ce-cRLReasons') -> 'CRLReason';
extension_id(?'id-ce-certificateIssuer') -> 'CertificateIssuer';
diff --git a/lib/public_key/src/pubkey_crl.erl b/lib/public_key/src/pubkey_crl.erl
index 7115424863..5bbc34ba53 100644
--- a/lib/public_key/src/pubkey_crl.erl
+++ b/lib/public_key/src/pubkey_crl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -298,7 +298,7 @@ is_all_reasons(Mask, AllReasonsFun) ->
%% As the "uspecified" reason should not
%% be explicitly used according to RFC 3280
%% and the conformance tests have test cases
- %% that should succed, and that does not specify
+ %% that should succeed, and that does not specify
%% "unspecified", we tolorate that it is not included.
sets:is_subset(sets:del_element(unspecified, AllReasons), Mask)
end.
diff --git a/lib/public_key/src/pubkey_os_cacerts.erl b/lib/public_key/src/pubkey_os_cacerts.erl
new file mode 100644
index 0000000000..1970c8b3d3
--- /dev/null
+++ b/lib/public_key/src/pubkey_os_cacerts.erl
@@ -0,0 +1,215 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(pubkey_os_cacerts).
+
+-include("public_key.hrl").
+-export([load/0, load/1, get/0, clear/0]).
+
+-on_load(on_load/0).
+-nifs([os_cacerts/0]).
+
+%% API
+
+%% Return cacerts
+-spec get() -> [public_key:combined_cert()].
+get() ->
+ case persistent_term:get(?MODULE, not_loaded) of
+ not_loaded ->
+ ok = load(),
+ persistent_term:get(?MODULE);
+ CaCerts ->
+ CaCerts
+ end.
+
+%% (Re)Load default os cacerts and cache result.
+-spec load() -> ok | {error, Reason::term()}.
+load() ->
+ case os:type() of
+ {unix, linux} ->
+ load_from_file(linux_paths());
+ {unix, openbsd} ->
+ load_from_file(bsd_paths());
+ {unix, freebsd} ->
+ load_from_file(bsd_paths());
+ {unix, netbsd} ->
+ load_from_file(bsd_paths());
+ {unix, sunos} ->
+ load_from_files(sunos_path());
+ {win32, _} ->
+ load_win32();
+ {unix, darwin} ->
+ load_darwin();
+ Os ->
+ {error, {enotsup, Os}}
+ end.
+
+%% (Re)Load cacerts from file and cache result.
+%% The file-paths will be tried in order.
+%% Can be used when load/0 doesn't work for an unsupported os type.
+-spec load([file:filename_all()]) -> ok | {error, Reason::term()}.
+load(Paths) ->
+ load_from_file(Paths).
+
+
+%% cleanup persistent_key
+-spec clear() -> boolean().
+clear() ->
+ persistent_term:erase(?MODULE).
+
+%% Implementation
+load_from_file([Path|Paths]) when is_list(Path); is_binary(Path) ->
+ try
+ {ok, Binary} = file:read_file(Path),
+ ok = decode_result(Binary)
+ catch _:_Reason ->
+ load_from_file(Paths)
+ end;
+load_from_file([]) ->
+ {error, enoent}.
+
+decode_result(Binary) ->
+ try
+ MakeCert = fun({'Certificate', Der, not_encrypted}, Acc) ->
+ try
+ Decoded = public_key:pkix_decode_cert(Der, otp),
+ [#cert{der=Der, otp=Decoded}|Acc]
+ catch _:_ ->
+ Acc
+ end
+ end,
+ Certs = lists:foldl(MakeCert, [], pubkey_pem:decode(Binary)),
+ store(Certs)
+ catch _:Reason ->
+ {error, Reason}
+ end.
+
+
+load_from_files(Path) ->
+ MakeCert = fun(FileName, Acc) ->
+ try
+ {ok, Bin} = file:read_file(FileName),
+ [#cert{der=Der, otp=public_key:pkix_decode_cert(Der, otp)}
+ || {'Certificate', Der, not_encrypted} <- pubkey_pem:decode(Bin)]
+ ++ Acc
+ catch _:_ ->
+ Acc
+ end
+ end,
+ Certs = filelib:fold_files(Path, ".*\.pem", false, MakeCert, []),
+ store(Certs).
+
+
+load_win32() ->
+ Dec = fun({_Enc, Der}, Acc) ->
+ try
+ Decoded = public_key:pkix_decode_cert(Der, otp),
+ [#cert{der=Der, otp=Decoded}|Acc]
+ catch _:_ ->
+ Acc
+ end
+ end,
+ store(lists:foldl(Dec, [], os_cacerts())).
+
+load_darwin() ->
+ %% Could/should probably be re-written to use Keychain Access API
+ KeyChainFile = "/System/Library/Keychains/SystemRootCertificates.keychain",
+ Args = ["export", "-t", "certs", "-f", "pemseq", "-k", KeyChainFile],
+ try run_cmd("/usr/bin/security", Args) of
+ {ok, Bin} -> decode_result(Bin);
+ Err -> Err
+ catch error:Reason ->
+ {error, {eopnotsupp, Reason}}
+ end.
+
+store([]) ->
+ {error, no_cacerts_found};
+store(CaCerts) ->
+ persistent_term:put(?MODULE, CaCerts).
+
+linux_paths() ->
+ ["/etc/ssl/certs/ca-certificates.crt", %% Debian, Ubuntu, Gentoo
+ "/etc/pki/tls/certs/ca-bundle.crt", %% Fedora, RHEL 6, Amazon Linux
+ "/etc/ssl/ca-bundle.pem", %% OpenSUSE
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", %% CentOS, RHEL 7
+ "/etc/ssl/cert.pem" %% Alpine Linux
+ ].
+
+bsd_paths() ->
+ ["/usr/local/share/certs/ca-root-nss.crt",
+ "/etc/ssl/cert.pem",
+ "/etc/openssl/certs/cacert.pem", %% netbsd (if installed)
+ "/etc/openssl/certs/ca-certificates.crt"
+ ].
+
+sunos_path() ->
+ "/etc/certs/CA/".
+
+run_cmd(Cmd, Args) ->
+ Opts = [binary, exit_status, stderr_to_stdout],
+ Port = open_port({spawn_executable, Cmd}, [{args, Args}|Opts]),
+ unlink(Port),
+ cmd_data(Port, <<>>).
+
+cmd_data(Port, Acc) ->
+ receive
+ {Port, {data, Bin}} ->
+ cmd_data(Port, <<Acc/binary, Bin/binary>>);
+ {Port, {exit_status, 0}} ->
+ {ok, Acc};
+ {Port, {exit_status, Status}} ->
+ {error, {eopnotsupp, Status, Acc}}
+ end.
+
+%%%
+%%% NIF placeholders
+%%%
+
+-spec os_cacerts() -> [{Encoding::atom(), Cert::binary()}].
+
+os_cacerts() ->
+ erlang:nif_error(nif_not_loaded).
+
+on_load() ->
+ case os:type() of
+ {win32, _} -> load_nif();
+ _ -> ok
+ end.
+
+load_nif() ->
+ PrivDir = code:priv_dir(public_key),
+ LibName = "public_key",
+ Lib = filename:join([PrivDir, "lib", LibName]),
+ case erlang:load_nif(Lib, 0) of
+ ok -> ok;
+ {error, {load_failed, _}}=Error1 ->
+ Arch = erlang:system_info(system_architecture),
+ ArchLibDir = filename:join([PrivDir, "lib", Arch]),
+ 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.
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
index dc327567e4..27c21129b4 100644
--- a/lib/public_key/src/pubkey_pbe.erl
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@
%%====================================================================
%%--------------------------------------------------------------------
--spec encode(binary(), string(), string(), term()) -> binary().
+-spec encode(binary(), iodata(), string(), term()) -> binary().
%%
%% Description: Performs password based encoding
%%--------------------------------------------------------------------
@@ -57,7 +57,7 @@ encode(Data, Password, "AES-256-CBC"= Cipher, KeyDevParams) ->
crypto:crypto_one_time(aes_256_cbc, Key, IV, pbe_pad(Data, block_size(aes_256_cbc)), true).
%%--------------------------------------------------------------------
--spec decode(binary(), string(), string(), term()) -> binary().
+-spec decode(binary(), iodata(), string(), term()) -> binary().
%%
%% Description: Performs password based decoding
%%--------------------------------------------------------------------
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index 4aa965e14f..e28fd4019c 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -72,7 +72,7 @@ encode(PemEntries) ->
-spec decipher({public_key:pki_asn1_type(), DerEncrypted::binary(),
{Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}
| {#'PBEParameter'{}, atom()}}},
- string()) -> Der::binary().
+ iodata()) -> Der::binary().
%%
%% Description: Deciphers a decrypted pem entry.
%%--------------------------------------------------------------------
@@ -82,7 +82,7 @@ decipher({_, DecryptDer, {Cipher, KeyDevParams}}, Password) ->
%%--------------------------------------------------------------------
-spec cipher(Der::binary(), {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}
| {#'PBEParameter'{}, atom()}},
- string()) -> binary().
+ iodata()) -> binary().
%%
%% Description: Ciphers a PEM entry
%%--------------------------------------------------------------------
diff --git a/lib/public_key/src/pubkey_ssh.erl b/lib/public_key/src/pubkey_ssh.erl
index 9a9505f558..36c3ebf558 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,71 +19,17 @@
%%
-module(pubkey_ssh).
--include("public_key.hrl").
-include("pubkey_moduli.hrl").
-
--export([decode/2, encode/2,
- dh_gex_group/4,
- dh_gex_group_sizes/0,
-pad/2, new_openssh_encode/1, new_openssh_decode/1 % For test and experiments
+-export([dh_gex_group/4,
+ dh_gex_group_sizes/0
]).
--define(UINT32(X), X:32/unsigned-big-integer).
--define(STRING(X), ?UINT32((byte_size(X))), (X)/binary).
-
--define(DEC_BIN(X,Len), ?UINT32(Len), X:Len/binary ).
--define(DEC_MPINT(I,Len), ?DEC_INT(I,Len) ).
--define(DEC_INT(I,Len), ?UINT32(Len), I:Len/big-signed-integer-unit:8 ).
-
--define(Empint(X), (mpint(X))/binary ).
--define(Estring(X), (string(X))/binary ).
-
--define(b64enc(X), base64:encode(iolist_to_binary(X)) ).
--define(b64mime_dec(X), base64:mime_decode(iolist_to_binary(X)) ).
-
-%% Max encoded line length is 72, but conformance examples use 68
-%% Comment from rfc 4716: "The following are some examples of public
-%% key files that are compliant (note that the examples all wrap
-%% before 72 bytes to meet IETF document requirements; however, they
-%% are still compliant.)" So we choose to use 68 also.
--define(ENCODED_LINE_LENGTH, 68).
-
-
%%====================================================================
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
-%% Description: Decodes a ssh file-binary.
-%%--------------------------------------------------------------------
-decode(Bin, public_key)->
- PKtype =
- case binary:match(Bin, begin_marker()) of
- nomatch -> openssh_public_key;
- _ -> rfc4716_public_key
- end,
- decode(Bin, PKtype);
-decode(Bin, rfc4716_public_key) ->
- rfc4716_decode(Bin);
-decode(Bin, ssh2_pubkey) ->
- ssh2_pubkey_decode(Bin);
-decode(Bin, new_openssh) ->
- new_openssh_decode(Bin);
-decode(Bin, Type) ->
- openssh_decode(Bin, Type).
-
-%%--------------------------------------------------------------------
-%% Description: Encodes a list of ssh file entries.
-%%--------------------------------------------------------------------
-encode(Bin, ssh2_pubkey) ->
- ssh2_pubkey_encode(Bin);
-encode(Entries, Type) ->
- iolist_to_binary(lists:map(fun({Key, Attributes}) ->
- do_encode(Type, Key, Attributes)
- end, Entries)).
-
-%%--------------------------------------------------------------------
%% Description: Returns Generator and Modulus given MinSize, WantedSize
%% and MaxSize
%%--------------------------------------------------------------------
@@ -102,6 +48,11 @@ dh_gex_group(Min, N, Max, Groups) ->
dh_gex_group_sizes()->
[KeyLen || {KeyLen,_} <- ?dh_default_groups].
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
%% Select the one with K closest to N but within the interval [Min,Max]
select_by_keylen(Min, N, Max, [{K,_Gs}|Groups]) when K < Min ->
@@ -123,533 +74,3 @@ select_by_keylen(Min, N, Max, [{K,Gs}|Groups], {Kprev,GsPrev}) ->
select_by_keylen(_Min, _N, _Max, [],GPprev) ->
%% is between Min and Max
GPprev.
-
-
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
-begin_marker() ->
- <<"---- BEGIN SSH2 PUBLIC KEY ----">>.
-end_marker() ->
- <<"---- END SSH2 PUBLIC KEY ----">>.
-
-rfc4716_decode(Bin) ->
- Lines = binary:split(Bin, <<"\n">>, [global]),
- do_rfc4716_decode(Lines, []).
-
-do_rfc4716_decode([<<"---- BEGIN SSH2 PUBLIC KEY ----", _/binary>> | Lines], Acc) ->
- do_rfc4716_decode(Lines, Acc);
-%% Ignore empty lines before or after begin/end - markers.
-do_rfc4716_decode([<<>> | Lines], Acc) ->
- do_rfc4716_decode(Lines, Acc);
-do_rfc4716_decode([], Acc) ->
- lists:reverse(Acc);
-do_rfc4716_decode(Lines, Acc) ->
- {Headers, PubKey, Rest} = rfc4716_decode_lines(Lines, []),
- case Headers of
- [_|_] ->
- do_rfc4716_decode(Rest, [{PubKey, [{headers, Headers}]} | Acc]);
- _ ->
- do_rfc4716_decode(Rest, [{PubKey, []} | Acc])
- end.
-
-rfc4716_decode_lines([Line | Lines], Acc) ->
- case binary:last(Line) of
- $\\ ->
- NewLine = binary:replace(Line,<<"\\">>, hd(Lines), []),
- rfc4716_decode_lines([NewLine | tl(Lines)], Acc);
- _ ->
- rfc4716_decode_line(Line, Lines, Acc)
- end.
-
-rfc4716_decode_line(Line, Lines, Acc) ->
- case binary:split(Line, <<":">>) of
- [Tag, Value] ->
- rfc4716_decode_lines(Lines, [{string_decode(Tag), unicode_decode(Value)} | Acc]);
- _ ->
- {Body, Rest} = join_entry([Line | Lines], []),
- {lists:reverse(Acc), rfc4716_pubkey_decode(?b64mime_dec(Body)), Rest}
- end.
-
-join_entry([<<"---- END SSH2 PUBLIC KEY ----", _/binary>>| Lines], Entry) ->
- {lists:reverse(Entry), Lines};
-join_entry([Line | Lines], Entry) ->
- join_entry(Lines, [Line | Entry]).
-
-
-rfc4716_pubkey_decode(BinKey) -> ssh2_pubkey_decode(BinKey).
-
-
-%% From https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
-new_openssh_decode(<<"openssh-key-v1",0,
- ?DEC_BIN(CipherName, _L1),
- ?DEC_BIN(KdfName, _L2),
- ?DEC_BIN(KdfOptions, _L3),
- ?UINT32(N), % number of keys
- ?DEC_BIN(PublicKey, _L4),
- ?DEC_BIN(Encrypted, _L5),
- _Rest/binary
- >>) ->
- %%io:format("CipherName = ~p~nKdfName = ~p~nKdfOptions = ~p~nPublicKey = ~p~nN = ~p~nEncrypted = ~p~nRest = ~p~n", [CipherName, KdfName, KdfOptions, PublicKey, N, Encrypted, _Rest]),
- new_openssh_decode(CipherName, KdfName, KdfOptions, PublicKey, N, Encrypted).
-
-new_openssh_decode(<<"none">>, <<"none">>, <<"">>, _PublicKey, 1,
- <<?UINT32(CheckInt),
- ?UINT32(CheckInt),
- ?DEC_BIN(Type, _Lt),
- ?DEC_BIN(PubKey, _Lpu),
- ?DEC_BIN(PrivPubKey, _Lpripub),
- ?DEC_BIN(_Comment, _C1),
- _Pad/binary>>) ->
- case {Type,PrivPubKey} of
- {<<"ssh-ed25519">>,
- <<PrivKey:32/binary, PubKey:32/binary>>} ->
- {ed_pri, ed25519, PubKey, PrivKey};
-
- {<<"ssh-ed448">>,
- <<PrivKey:57/binary, PubKey/binary>>} -> % "Intelligent" guess from
- % https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-ed448
- {ed_pri, ed448, PubKey, PrivKey}
- end.
-
-
-new_openssh_encode({ed_pri,_,PubKey,PrivKey}=Key) ->
- Type = key_type(Key),
- CheckInt = 17*256+17, %crypto:strong_rand_bytes(4),
- Comment = <<>>,
- PublicKey = <<?STRING(Type),?STRING(PubKey)>>,
- CipherName = <<"none">>,
- KdfName = <<"none">>,
- KdfOptions = <<>>,
- BlockSize = 8, % Crypto dependent
- NumKeys = 1,
- Encrypted0 = <<?UINT32(CheckInt),
- ?UINT32(CheckInt),
- ?STRING(Type),
- ?STRING(PubKey),
- ?STRING(<<PrivKey/binary,PubKey/binary>>),
- ?STRING(Comment)
- >>,
- Pad = pad(size(Encrypted0), BlockSize),
- Encrypted = <<Encrypted0/binary, Pad/binary>>,
- <<"openssh-key-v1",0,
- ?STRING(CipherName),
- ?STRING(KdfName),
- ?STRING(KdfOptions),
- ?UINT32(NumKeys),
- ?STRING(PublicKey),
- ?STRING(Encrypted)>>.
-
-pad(N, BlockSize) when N>BlockSize -> pad(N rem BlockSize, BlockSize);
-pad(N, BlockSize) -> list_to_binary(lists:seq(1,BlockSize-N)).
-
-
-openssh_decode(Bin, FileType) ->
- Lines = binary:split(Bin, <<"\n">>, [global]),
- do_openssh_decode(FileType, Lines, []).
-
-do_openssh_decode(_, [], Acc) ->
- lists:reverse(Acc);
-%% Ignore empty lines
-do_openssh_decode(FileType, [<<>> | Lines], Acc) ->
- do_openssh_decode(FileType, Lines, Acc);
-%% Ignore lines that start with #
-do_openssh_decode(FileType,[<<"#", _/binary>> | Lines], Acc) ->
- do_openssh_decode(FileType, Lines, Acc);
-do_openssh_decode(auth_keys = FileType, [Line | Lines], Acc) ->
- case decode_auth_keys(Line) of
- {ssh2, {options, [Options, KeyType, Base64Enc| Comment]}} ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- decode_comment(Comment) ++ [{options, comma_list_decode(Options)}]} | Acc]);
- {ssh2, {no_options, [KeyType, Base64Enc| Comment]}} ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- decode_comment(Comment)} | Acc]);
- {ssh1, {options, [Options, Bits, Exponent, Modulus | Comment]}} ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- decode_comment(Comment) ++ [{options, comma_list_decode(Options)},
- {bits, integer_decode(Bits)}]
- } | Acc]);
- {ssh1, {no_options, [Bits, Exponent, Modulus | Comment]}} ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- decode_comment(Comment) ++ [{bits, integer_decode(Bits)}]
- } | Acc])
- end;
-
-do_openssh_decode(known_hosts = FileType, [Line | Lines], Acc) ->
- case decode_known_hosts(Line) of
- {ssh2, [HostNames, KeyType, Base64Enc| Comment]} ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- decode_comment(Comment) ++
- [{hostnames, comma_list_decode(HostNames)}]}| Acc]);
- {ssh1, [HostNames, Bits, Exponent, Modulus | Comment]} ->
- do_openssh_decode(FileType, Lines,
- [{ssh1_rsa_pubkey_decode(Modulus, Exponent),
- decode_comment(Comment) ++
- [{hostnames, comma_list_decode(HostNames)},
- {bits, integer_decode(Bits)}]}
- | Acc])
- end;
-
-do_openssh_decode(openssh_public_key = FileType, [Line | Lines], Acc) ->
- [KeyType, Base64Enc | Comment0] = split_n(2, Line, []),
- KnownKeyType =
- case KeyType of
- <<"ssh-rsa">> -> true;
- <<"ssh-dss">> -> true;
- <<"ecdsa-sha2-",Curve/binary>> -> is_ssh_curvename(Curve);
- <<"ssh-ed25519">> -> true;
- <<"ssh-ed448">> -> true;
- _ -> false
- end,
-
- case Comment0 of
- [] when KnownKeyType==true ->
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- []} | Acc]);
- _ when KnownKeyType==true ->
- Comment = string:strip(string_decode(iolist_to_binary(Comment0)), right, $\n),
- do_openssh_decode(FileType, Lines,
- [{openssh_pubkey_decode(KeyType, Base64Enc),
- [{comment, Comment}]} | Acc]);
- _ when KnownKeyType==false ->
- do_openssh_decode(FileType, Lines, Acc)
- end.
-
-
-decode_comment([]) ->
- [];
-decode_comment(Comment) ->
- [{comment, string_decode(iolist_to_binary(Comment))}].
-
-
-openssh_pubkey_decode(Type, Base64Enc) ->
- try
- <<?DEC_BIN(Type,_TL), Bin/binary>> = ?b64mime_dec(Base64Enc),
- ssh2_pubkey_decode(Type, Bin)
- catch
- _:_ ->
- {Type, ?b64mime_dec(Base64Enc)}
- end.
-
-
-ssh1_rsa_pubkey_decode(MBin, EBin) ->
- #'RSAPublicKey'{modulus = integer_decode(MBin),
- publicExponent = integer_decode(EBin)}.
-
-integer_decode(BinStr) ->
- list_to_integer(binary_to_list(BinStr)).
-
-string_decode(BinStr) ->
- unicode_decode(BinStr).
-
-unicode_decode(BinStr) ->
- unicode:characters_to_list(BinStr).
-
-comma_list_decode(BinOpts) ->
- CommaList = binary:split(BinOpts, <<",">>, [global]),
- lists:map(fun(Item) ->
- binary_to_list(Item)
- end, CommaList).
-
-do_encode(rfc4716_public_key, Key, Attributes) ->
- rfc4716_encode(Key, proplists:get_value(headers, Attributes, []), []);
-
-do_encode(Type, Key, Attributes) ->
- openssh_encode(Type, Key, Attributes).
-
-rfc4716_encode(Key, [],[]) ->
- iolist_to_binary([begin_marker(),"\n",
- split_lines(?b64enc(ssh2_pubkey_encode(Key))),
- "\n", end_marker(), "\n"]);
-rfc4716_encode(Key, [], [_|_] = Acc) ->
- iolist_to_binary([begin_marker(), "\n",
- lists:reverse(Acc),
- split_lines(?b64enc(ssh2_pubkey_encode(Key))),
- "\n", end_marker(), "\n"]);
-rfc4716_encode(Key, [ Header | Headers], Acc) ->
- LinesStr = rfc4716_encode_header(Header),
- rfc4716_encode(Key, Headers, [LinesStr | Acc]).
-
-rfc4716_encode_header({Tag, Value}) ->
- TagLen = length(Tag),
- ValueLen = length(Value),
- case TagLen + 1 + ValueLen of
- N when N > ?ENCODED_LINE_LENGTH ->
- NumOfChars = ?ENCODED_LINE_LENGTH - (TagLen + 1),
- {First, Rest} = lists:split(NumOfChars, Value),
- [Tag,":" , First, [$\\], "\n", rfc4716_encode_value(Rest) , "\n"];
- _ ->
- [Tag, ":", Value, "\n"]
- end.
-
-rfc4716_encode_value(Value) ->
- case length(Value) of
- N when N > ?ENCODED_LINE_LENGTH ->
- {First, Rest} = lists:split(?ENCODED_LINE_LENGTH, Value),
- [First, [$\\], "\n", rfc4716_encode_value(Rest)];
- _ ->
- Value
- end.
-
-openssh_encode(openssh_public_key, Key, Attributes) ->
- Comment = proplists:get_value(comment, Attributes, ""),
- Enc = ?b64enc(ssh2_pubkey_encode(Key)),
- iolist_to_binary([key_type(Key), " ", Enc, " ", Comment, "\n"]);
-
-openssh_encode(auth_keys, Key, Attributes) ->
- Comment = proplists:get_value(comment, Attributes, ""),
- Options = proplists:get_value(options, Attributes, undefined),
- Bits = proplists:get_value(bits, Attributes, undefined),
- case Bits of
- undefined ->
- openssh_ssh2_auth_keys_encode(Options, Key, Comment);
- _ ->
- openssh_ssh1_auth_keys_encode(Options, Bits, Key, Comment)
- end;
-openssh_encode(known_hosts, Key, Attributes) ->
- Comment = proplists:get_value(comment, Attributes, ""),
- Hostnames = proplists:get_value(hostnames, Attributes),
- Bits = proplists:get_value(bits, Attributes, undefined),
- case Bits of
- undefined ->
- openssh_ssh2_know_hosts_encode(Hostnames, Key, Comment);
- _ ->
- openssh_ssh1_known_hosts_encode(Hostnames, Bits, Key, Comment)
- end.
-
-openssh_ssh2_auth_keys_encode(undefined, Key, Comment) ->
- iolist_to_binary([key_type(Key)," ", ?b64enc(ssh2_pubkey_encode(Key)), line_end(Comment)]);
-openssh_ssh2_auth_keys_encode(Options, Key, Comment) ->
- iolist_to_binary([comma_list_encode(Options, []), " ",
- key_type(Key)," ", ?b64enc(ssh2_pubkey_encode(Key)), line_end(Comment)]).
-
-openssh_ssh1_auth_keys_encode(undefined, Bits,
- #'RSAPublicKey'{modulus = N, publicExponent = E},
- Comment) ->
- iolist_to_binary([integer_to_list(Bits), " ", integer_to_list(E), " ", integer_to_list(N),
- line_end(Comment)]);
-openssh_ssh1_auth_keys_encode(Options, Bits,
- #'RSAPublicKey'{modulus = N, publicExponent = E},
- Comment) ->
- iolist_to_binary([comma_list_encode(Options, []), " ", integer_to_list(Bits),
- " ", integer_to_list(E), " ", integer_to_list(N), line_end(Comment)]).
-
-openssh_ssh2_know_hosts_encode(Hostnames, Key, Comment) ->
- iolist_to_binary([comma_list_encode(Hostnames, []), " ",
- key_type(Key)," ", ?b64enc(ssh2_pubkey_encode(Key)), line_end(Comment)]).
-
-openssh_ssh1_known_hosts_encode(Hostnames, Bits,
- #'RSAPublicKey'{modulus = N, publicExponent = E},
- Comment) ->
- iolist_to_binary([comma_list_encode(Hostnames, [])," ", integer_to_list(Bits)," ",
- integer_to_list(E)," ", integer_to_list(N), line_end(Comment)]).
-
-line_end("") ->
- "\n";
-line_end(Comment) ->
- [" ", Comment, "\n"].
-
-key_type(#'RSAPublicKey'{}) -> <<"ssh-rsa">>;
-key_type({_, #'Dss-Parms'{}}) -> <<"ssh-dss">>;
-key_type({ed_pub,ed25519,_}) -> <<"ssh-ed25519">>;
-key_type({ed_pub,ed448,_}) -> <<"ssh-ed448">>;
-key_type({ed_pri,ed25519,_,_}) -> <<"ssh-ed25519">>;
-key_type({ed_pri,ed448,_,_}) -> <<"ssh-ed448">>;
-key_type({#'ECPoint'{}, {namedCurve,Curve}}) -> <<"ecdsa-sha2-", (public_key:oid2ssh_curvename(Curve))/binary>>.
-
-comma_list_encode([Option], []) ->
- Option;
-comma_list_encode([Option], Acc) ->
- Acc ++ "," ++ Option;
-comma_list_encode([Option | Rest], []) ->
- comma_list_encode(Rest, Option);
-comma_list_encode([Option | Rest], Acc) ->
- comma_list_encode(Rest, Acc ++ "," ++ Option).
-
-
-ssh2_pubkey_encode(#'RSAPublicKey'{modulus = N, publicExponent = E}) ->
- <<?STRING(<<"ssh-rsa">>), ?Empint(E), ?Empint(N)>>;
-ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) ->
- <<?STRING(<<"ssh-dss">>), ?Empint(P), ?Empint(Q), ?Empint(G), ?Empint(Y)>>;
-ssh2_pubkey_encode(Key={#'ECPoint'{point = Q}, {namedCurve,OID}}) ->
- Curve = public_key:oid2ssh_curvename(OID),
- <<?STRING(key_type(Key)), ?Estring(Curve), ?Estring(Q)>>;
-ssh2_pubkey_encode({ed_pub, ed25519, Key}) ->
- <<?STRING(<<"ssh-ed25519">>), ?Estring(Key)>>;
-ssh2_pubkey_encode({ed_pub, ed448, Key}) ->
- <<?STRING(<<"ssh-ed448">>), ?Estring(Key)>>.
-
-
-
-ssh2_pubkey_decode(<<?DEC_BIN(Type,_TL), Bin/binary>>) ->
- ssh2_pubkey_decode(Type, Bin).
-
-%% ssh2_pubkey_decode(<<"rsa-sha2-256">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin);
-%% ssh2_pubkey_decode(<<"rsa-sha2-512">>, Bin) -> ssh2_pubkey_decode(<<"ssh-rsa">>, Bin);
-ssh2_pubkey_decode(<<"ssh-rsa">>,
- <<?DEC_INT(E, _EL),
- ?DEC_INT(N, _NL)>>) ->
- #'RSAPublicKey'{modulus = N,
- publicExponent = E};
-
-ssh2_pubkey_decode(<<"ssh-dss">>,
- <<?DEC_INT(P, _PL),
- ?DEC_INT(Q, _QL),
- ?DEC_INT(G, _GL),
- ?DEC_INT(Y, _YL)>>) ->
- {Y, #'Dss-Parms'{p = P,
- q = Q,
- g = G}};
-
-ssh2_pubkey_decode(<<"ecdsa-sha2-",Id/binary>>,
- <<?DEC_BIN(Id, _IL),
- ?DEC_BIN(Q, _QL)>>) ->
- {#'ECPoint'{point = Q}, {namedCurve,public_key:ssh_curvename2oid(Id)}};
-
-ssh2_pubkey_decode(<<"ssh-ed25519">>,
- <<?DEC_BIN(Key, _L)>>) ->
- {ed_pub, ed25519, Key};
-
-ssh2_pubkey_decode(<<"ssh-ed448">>,
- <<?DEC_BIN(Key, _L)>>) ->
- {ed_pub, ed448, Key}.
-
-
-
-
-is_key_field(<<"ssh-dss">>) -> true;
-is_key_field(<<"ssh-rsa">>) -> true;
-is_key_field(<<"ssh-ed25519">>) -> true;
-is_key_field(<<"ssh-ed448">>) -> true;
-is_key_field(<<"ecdsa-sha2-",Id/binary>>) -> is_ssh_curvename(Id);
-is_key_field(_) -> false.
-
-is_bits_field(Part) ->
- try list_to_integer(binary_to_list(Part)) of
- _ ->
- true
- catch _:_ ->
- false
- end.
-
-split_lines(<<Text:?ENCODED_LINE_LENGTH/binary>>) ->
- [Text];
-split_lines(<<Text:?ENCODED_LINE_LENGTH/binary, Rest/binary>>) ->
- [Text, $\n | split_lines(Rest)];
-split_lines(Bin) ->
- [Bin].
-
-decode_auth_keys(Line) ->
- [First, Rest] = binary:split(Line, <<" ">>, []),
- case is_key_field(First) of
- true ->
- {ssh2, decode_auth_keys_ssh2(First, Rest)};
- false ->
- case is_bits_field(First) of
- true ->
- {ssh1, decode_auth_keys_ssh1(First, Rest)};
- false ->
- decode_auth_keys(First, Rest)
- end
- end.
-
-decode_auth_keys(First, Line) ->
- [Second, Rest] = binary:split(Line, <<" ">>, []),
- case is_key_field(Second) of
- true ->
- {ssh2, decode_auth_keys_ssh2(First, Second, Rest)};
- false ->
- case is_bits_field(Second) of
- true ->
- {ssh1, decode_auth_keys_ssh1(First, Second, Rest)};
- false ->
- decode_auth_keys(<<First/binary, Second/binary>>, Rest)
- end
- end.
-
-decode_auth_keys_ssh2(KeyType, Rest) ->
- {no_options, [KeyType | split_n(1, Rest, [])]}.
-
-decode_auth_keys_ssh2(Options, Next, Rest) ->
- {options, [Options, Next | split_n(1, Rest, [])]}.
-
-decode_auth_keys_ssh1(Options, Next, Rest) ->
- {options, [Options, Next | split_n(2, Rest, [])]}.
-
-decode_auth_keys_ssh1(First, Rest) ->
- {no_options, [First | split_n(2, Rest, [])]}.
-
-decode_known_hosts(Line) ->
- [First, Rest] = binary:split(Line, <<" ">>, []),
- [Second, Rest1] = binary:split(Rest, <<" ">>, []),
-
- case is_bits_field(Second) of
- true ->
- {ssh1, decode_known_hosts_ssh1(First, Second, Rest1)};
- false ->
- {ssh2, decode_known_hosts_ssh2(First, Second, Rest1)}
- end.
-
-decode_known_hosts_ssh1(Hostnames, Bits, Rest) ->
- [Hostnames, Bits | split_n(2, Rest, [])].
-
-decode_known_hosts_ssh2(Hostnames, KeyType, Rest) ->
- [Hostnames, KeyType | split_n(1, Rest, [])].
-
-split_n(0, <<>>, Acc) ->
- lists:reverse(Acc);
-split_n(0, Bin, Acc) ->
- lists:reverse([Bin | Acc]);
-split_n(N, Bin, Acc) ->
- case binary:split(Bin, <<" ">>, []) of
- [First, Rest] ->
- split_n(N-1, Rest, [First | Acc]);
- [Last] ->
- split_n(0, <<>>, [Last | Acc])
- end.
-%% large integer in a binary with 32bit length
-%% MP representaion (SSH2)
-mpint(X) when X < 0 -> mpint_neg(X);
-mpint(X) -> mpint_pos(X).
-
-mpint_neg(X) ->
- Bin = int_to_bin_neg(X, []),
- <<?STRING(Bin)>>.
-
-mpint_pos(X) ->
- Bin = int_to_bin_pos(X, []),
- <<MSB,_/binary>> = Bin,
- if MSB band 16#80 == 16#80 ->
- B = << 0, Bin/binary>>,
- <<?STRING(B)>>;
- true ->
- <<?STRING(Bin)>>
- end.
-
-int_to_bin_pos(0,Ds=[_|_]) ->
- list_to_binary(Ds);
-int_to_bin_pos(X,Ds) ->
- int_to_bin_pos(X bsr 8, [(X band 255)|Ds]).
-
-int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
- list_to_binary(Ds);
-int_to_bin_neg(X,Ds) ->
- int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
-
-
-string(X) when is_binary(X) ->
- << ?STRING(X) >>;
-string(X) ->
- B = list_to_binary(X),
- << ?STRING(B) >>.
-
-is_ssh_curvename(Id) -> try public_key:ssh_curvename2oid(Id) of _ -> true
- catch _:_ -> false
- end.
-
diff --git a/lib/public_key/src/public_key.app.src b/lib/public_key/src/public_key.app.src
index 6be7cd3bc4..5d8f936e33 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -9,13 +9,14 @@
pubkey_cert_records,
pubkey_crl,
pubkey_ocsp,
+ pubkey_os_cacerts,
'OTP-PUB-KEY',
'PKCS-FRAME'
]},
{applications, [asn1, crypto, kernel, stdlib]},
{registered, []},
{env, []},
- {runtime_dependencies, ["stdlib-3.5","kernel-3.0","erts-6.0","crypto-3.8",
+ {runtime_dependencies, ["stdlib-3.5","kernel-3.0","erts-6.0","crypto-4.6",
"asn1-3.0"]}
]
}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 276be6bb87..3cb9fea632 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,6 @@
pkix_path_validation/3,
pkix_verify_hostname/2, pkix_verify_hostname/3,
pkix_verify_hostname_match_fun/1,
- ssh_curvename2oid/1, oid2ssh_curvename/1,
pkix_crls_validate/3,
pkix_dist_point/1,
pkix_dist_points/1,
@@ -64,27 +63,22 @@
pkix_test_root_cert/2,
pkix_ocsp_validate/5,
ocsp_responder_id/1,
- ocsp_extensions/1
+ ocsp_extensions/1,
+ cacerts_get/0,
+ cacerts_load/0,
+ cacerts_load/1,
+ cacerts_clear/0
]).
%%----------------
-%% To be moved to ssh and deprecated:
--export([ssh_decode/2, ssh_encode/2,
- ssh_hostkey_fingerprint/1, ssh_hostkey_fingerprint/2
- ]).
-
--deprecated([{ssh_decode,2, "use ssh_file:decode/2 instead"},
- {ssh_encode,2, "use ssh_file:encode/2 instead"},
- {ssh_hostkey_fingerprint,1, "use ssh:hostkey_fingerprint/1 instead"},
- {ssh_hostkey_fingerprint,2, "use ssh:hostkey_fingerprint/2 instead"}
- ]).
-
--compile([{nowarn_deprecated_function,
- [{public_key,ssh_decode,2},
- {public_key,ssh_encode,2}
- ]}
+%% Moved to ssh
+-removed([{ssh_decode,2, "use ssh_file:decode/2 instead"},
+ {ssh_encode,2, "use ssh_file:encode/2 instead"},
+ {ssh_hostkey_fingerprint,1, "use ssh:hostkey_fingerprint/1 instead"},
+ {ssh_hostkey_fingerprint,2, "use ssh:hostkey_fingerprint/2 instead"}
]).
+-export([ssh_curvename2oid/1, oid2ssh_curvename/1]).
%% When removing for OTP-25.0, remember to also remove
%% - most of pubkey_ssh.erl except
%% + dh_gex_group/4
@@ -100,7 +94,6 @@
pem_entry/0,
pki_asn1_type/0,
asn1_type/0,
- ssh_file/0,
der_encoded/0,
key_params/0,
digest_type/0,
@@ -131,19 +124,17 @@
-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}.
-type ec_private_key() :: #'ECPrivateKey'{}.
-type ed_public_key() :: {#'ECPoint'{}, ed_params()}.
--type ed_legacy_pubkey() :: {ed_pub, ed25519|ed448, Key::binary()}.
-type ed_private_key() :: #'ECPrivateKey'{parameters :: ed_params()}.
--type ed_legacy_privkey() :: {ed_pri, ed25519|ed448, Pub::binary(), Priv::binary()}.
-type ed_oid_name() :: 'id-Ed25519' | 'id-Ed448'.
-type ed_params() :: {namedCurve, ed_oid_name()}.
-type key_params() :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} |
{rsa, Size::integer(), PubExp::integer()}.
-type der_encoded() :: binary().
-type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey'
- | 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter'
- | 'SubjectPublicKeyInfo' | 'PrivateKeyInfo' |
- 'CertificationRequest' | 'CertificateList' |
- 'ECPrivateKey' | 'EcpkParameters'.
+ | 'SubjectPublicKeyInfo' | 'DSAPrivateKey'
+ | 'DHParameter' | 'PrivateKeyInfo' |
+ 'CertificationRequest' | 'ContentInfo' | 'CertificateList' |
+ 'ECPrivateKey' | 'OneAsymmetricKey'| 'EcpkParameters'.
-type pem_entry() :: {pki_asn1_type(),
der_or_encrypted_der(),
not_encrypted | cipher_info()
@@ -158,8 +149,6 @@
-type salt() :: binary(). % crypto:strong_rand_bytes(8)
-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl
--type ssh_file() :: openssh_public_key | rfc4716_public_key | known_hosts |
- auth_keys.
-type digest_type() :: none % None is for backwards compatibility
| sha1 % Backwards compatibility
| crypto:rsa_digest_type()
@@ -235,15 +224,13 @@ pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
ECCParams = der_decode('EcpkParameters', Params),
{#'ECPoint'{point = Key0}, ECCParams}
end;
-pem_entry_decode({{no_asn1,new_openssh}, Special, not_encrypted}) ->
- ssh_decode(Special, new_openssh);
pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der).
-spec pem_entry_decode(PemEntry, Password) -> term() when
PemEntry :: pem_entry(),
- Password :: string() | fun(() -> string()).
+ Password :: iodata() | fun(() -> iodata()).
pem_entry_decode(PemEntry, PasswordFun) when is_function(PasswordFun) ->
pem_entry_decode(PemEntry, PasswordFun());
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
@@ -313,7 +300,7 @@ pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Entity :: term(),
InfoPwd :: {CipherInfo,Password},
CipherInfo :: cipher_info(),
- Password :: string() .
+ Password :: iodata() .
pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
Password}) when is_atom(Asn1Type) andalso
is_list(Password) andalso
@@ -827,7 +814,7 @@ pkix_hash_type('id-md5') ->
-spec sign(Msg, DigestType, Key) ->
Signature when Msg :: binary() | {digest,binary()},
DigestType :: digest_type(),
- Key :: private_key() | ed_legacy_privkey(),
+ Key :: private_key(),
Signature :: binary() .
sign(DigestOrPlainText, DigestType, Key) ->
sign(DigestOrPlainText, DigestType, Key, []).
@@ -835,7 +822,7 @@ sign(DigestOrPlainText, DigestType, Key) ->
-spec sign(Msg, DigestType, Key, Options) ->
Signature when Msg :: binary() | {digest,binary()},
DigestType :: digest_type(),
- Key :: private_key() | ed_legacy_privkey(),
+ Key :: private_key(),
Options :: crypto:pk_sign_verify_opts(),
Signature :: binary() .
sign(Digest, none, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
@@ -846,7 +833,12 @@ sign(DigestOrPlainText, DigestType, Key, Options) ->
badarg ->
erlang:error(badarg, [DigestOrPlainText, DigestType, Key, Options]);
{Algorithm, CryptoKey} ->
- crypto:sign(Algorithm, DigestType, DigestOrPlainText, CryptoKey, Options)
+ try crypto:sign(Algorithm, DigestType, DigestOrPlainText, CryptoKey, Options)
+ catch %% Compatible with old error schema
+ error:{notsup,_,_} -> error(notsup);
+ error:{error,_,_} -> error(error);
+ error:{badarg,_,_} -> error(badarg)
+ end
end.
%%--------------------------------------------------------------------
@@ -856,7 +848,7 @@ sign(DigestOrPlainText, DigestType, Key, Options) ->
boolean() when Msg :: binary() | {digest, binary()},
DigestType :: digest_type(),
Signature :: binary(),
- Key :: public_key() | ed_legacy_pubkey().
+ Key :: public_key().
verify(DigestOrPlainText, DigestType, Signature, Key) ->
verify(DigestOrPlainText, DigestType, Signature, Key, []).
@@ -865,7 +857,7 @@ verify(DigestOrPlainText, DigestType, Signature, Key) ->
boolean() when Msg :: binary() | {digest, binary()},
DigestType :: digest_type(),
Signature :: binary(),
- Key :: public_key() | ed_legacy_pubkey(),
+ Key :: public_key(),
Options :: crypto:pk_sign_verify_opts().
verify(Digest, none, Signature, Key = {_, #'Dss-Parms'{}}, Options) when is_binary(Digest) ->
@@ -876,7 +868,12 @@ verify(DigestOrPlainText, DigestType, Signature, Key, Options) when is_binary(Si
badarg ->
erlang:error(badarg, [DigestOrPlainText, DigestType, Signature, Key, Options]);
{Algorithm, CryptoKey} ->
- crypto:verify(Algorithm, DigestType, DigestOrPlainText, Signature, CryptoKey, Options)
+ try crypto:verify(Algorithm, DigestType, DigestOrPlainText, Signature, CryptoKey, Options)
+ catch %% Compatible with old error schema
+ error:{notsup,_,_} -> error(notsup);
+ error:{error,_,_} -> error(error);
+ error:{badarg,_,_} -> error(badarg)
+ end
end;
verify(_,_,_,_,_) ->
%% If Signature is a bitstring and not a binary we know already at this
@@ -1301,58 +1298,6 @@ pkix_verify_hostname_match_fun(https) ->
end.
%%--------------------------------------------------------------------
--spec ssh_decode(SshBin, Type) ->
- Decoded
- when SshBin :: binary(),
- Type :: ssh2_pubkey | OtherType | InternalType,
- OtherType :: public_key | ssh_file(),
- InternalType :: new_openssh,
- Decoded :: Decoded_ssh2_pubkey
- | Decoded_OtherType,
- Decoded_ssh2_pubkey :: public_key() | ed_legacy_pubkey(),
- Decoded_OtherType :: [{public_key() | ed_legacy_pubkey(), Attributes}],
- Attributes :: [{atom(),term()}] .
-%%
-%% Description: Decodes a ssh file-binary. In the case of know_hosts
-%% or auth_keys the binary may include one or more lines of the
-%% file. Returns a list of public keys and their attributes, possible
-%% attribute values depends on the file type represented by the
-%% binary.
-%%--------------------------------------------------------------------
-ssh_decode(SshBin, Type) when is_binary(SshBin),
- Type == public_key;
- Type == rfc4716_public_key;
- Type == openssh_public_key;
- Type == auth_keys;
- Type == known_hosts;
- Type == ssh2_pubkey;
- Type == new_openssh ->
- pubkey_ssh:decode(SshBin, Type).
-
-%%--------------------------------------------------------------------
--spec ssh_encode(InData, Type) ->
- binary()
- when Type :: ssh2_pubkey | OtherType,
- OtherType :: public_key | ssh_file(),
- InData :: InData_ssh2_pubkey | OtherInData,
- InData_ssh2_pubkey :: public_key() | ed_legacy_pubkey(),
- OtherInData :: [{Key,Attributes}],
- Key :: public_key() | ed_legacy_pubkey(),
- Attributes :: [{atom(),term()}] .
-%%
-%% Description: Encodes a list of ssh file entries (public keys and
-%% attributes) to a binary. Possible attributes depends on the file
-%% type.
-%%--------------------------------------------------------------------
-ssh_encode(Entries, Type) when is_list(Entries),
- Type == rfc4716_public_key;
- Type == openssh_public_key;
- Type == auth_keys;
- Type == known_hosts;
- Type == ssh2_pubkey ->
- pubkey_ssh:encode(Entries, Type).
-
-%%--------------------------------------------------------------------
-spec ssh_curvename2oid(binary()) -> oid().
%% Description: Converts from the ssh name of elliptic curves to
@@ -1371,51 +1316,6 @@ oid2ssh_curvename(?'secp256r1') -> <<"nistp256">>;
oid2ssh_curvename(?'secp384r1') -> <<"nistp384">>;
oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>.
-%%--------------------------------------------------------------------
--spec ssh_hostkey_fingerprint(public_key()) -> string().
-
-ssh_hostkey_fingerprint(Key) ->
- sshfp_string(md5, public_key:ssh_encode(Key,ssh2_pubkey) ).
-
-
--spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
- ; ([digest_type()], public_key()) -> [string()]
- .
-ssh_hostkey_fingerprint(HashAlgs, Key) when is_list(HashAlgs) ->
- EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
- [sshfp_full_string(HashAlg,EncKey) || HashAlg <- HashAlgs];
-ssh_hostkey_fingerprint(HashAlg, Key) when is_atom(HashAlg) ->
- EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
- sshfp_full_string(HashAlg, EncKey).
-
-
-sshfp_string(HashAlg, EncodedKey) ->
- %% Other HashAlgs than md5 will be printed with
- %% other formats than hextstr by
- %% ssh-keygen -E <alg> -lf <file>
- fp_fmt(sshfp_fmt(HashAlg), crypto:hash(HashAlg, EncodedKey)).
-
-sshfp_full_string(HashAlg, EncKey) ->
- lists:concat([sshfp_alg_name(HashAlg),
- [$: | sshfp_string(HashAlg, EncKey)]
- ]).
-
-sshfp_alg_name(sha) -> "SHA1";
-sshfp_alg_name(Alg) -> string:to_upper(atom_to_list(Alg)).
-
-sshfp_fmt(md5) -> hexstr;
-sshfp_fmt(_) -> b64.
-
-fp_fmt(hexstr, Bin) ->
- lists:flatten(string:join([io_lib:format("~2.16.0b",[C1]) || <<C1>> <= Bin], ":"));
-fp_fmt(b64, Bin) ->
- %% This function clause *seems* to be
- %% [C || C<-base64:encode_to_string(Bin), C =/= $=]
- %% but I am not sure. Must be checked.
- B64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
- BitsInLast = 8*size(Bin) rem 6,
- Padding = (6-BitsInLast) rem 6, % Want BitsInLast = [1:5] to map to padding [5:1] and 0 -> 0
- [lists:nth(C+1,B64Chars) || <<C:6>> <= <<Bin/binary,0:Padding>> ].
%%--------------------------------------------------------------------
-spec short_name_hash(Name) -> string() when Name :: issuer_name() .
@@ -1503,6 +1403,39 @@ ocsp_responder_id(Cert) ->
pubkey_ocsp:get_ocsp_responder_id(Cert).
%%--------------------------------------------------------------------
+-spec cacerts_get() -> [combined_cert()].
+%%
+%% Description: Get loaded cacerts, if none are loaded it will try to
+%% load OS provided cacerts
+%%--------------------------------------------------------------------
+cacerts_get() ->
+ pubkey_os_cacerts:get().
+
+%%--------------------------------------------------------------------
+-spec cacerts_load() -> ok | {error, Reason::term()}.
+%%
+%% Description: (Re)Load OS provided cacerts
+%%--------------------------------------------------------------------
+cacerts_load() ->
+ pubkey_os_cacerts:load().
+
+%%--------------------------------------------------------------------
+-spec cacerts_load(File::file:filename_all()) -> ok | {error, Reason::term()}.
+%%
+%% Description: (Re)Load cacerts from a file
+%%--------------------------------------------------------------------
+cacerts_load(File) ->
+ pubkey_os_cacerts:load([File]).
+
+%%--------------------------------------------------------------------
+-spec cacerts_clear() -> boolean().
+%%
+%% Description: Clears loaded cacerts, returns true if any was loaded.
+%%--------------------------------------------------------------------
+cacerts_clear() ->
+ pubkey_os_cacerts:clear().
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
default_options([]) ->
@@ -2001,7 +1934,7 @@ verify_hostname_match_default0({ip,R}, {iPAddress,P}) when length(P) == 4 ->
%% IPv4
try
list_to_tuple(P)
- == if is_tuple(R), size(R)==4 -> R;
+ == if tuple_size(R)==4 -> R;
is_list(R) -> ok(inet:parse_ipv4strict_address(R))
end
catch
@@ -2013,7 +1946,7 @@ verify_hostname_match_default0({ip,R}, {iPAddress,P}) when length(P) == 16 ->
%% IPv6. The length 16 is due to the certificate specification.
try
l16_to_tup(P)
- == if is_tuple(R), size(R)==8 -> R;
+ == if tuple_size(R)==8 -> R;
is_list(R) -> ok(inet:parse_ipv6strict_address(R))
end
catch
@@ -2049,8 +1982,8 @@ match_wild(_, _) -> false.
%% Match the parts after the only wildcard by comparing them from the end
match_wild_suffixes(A, B) -> match_wild_sfx(lists:reverse(A), lists:reverse(B)).
-match_wild_sfx([$*|_], _) -> false; % Bad name (no wildcards alowed)
-match_wild_sfx(_, [$*|_]) -> false; % Bad pattern (no more wildcards alowed)
+match_wild_sfx([$*|_], _) -> false; % Bad name (no wildcards allowed)
+match_wild_sfx(_, [$*|_]) -> false; % Bad pattern (no more wildcards allowed)
match_wild_sfx([A|Ar], [A|Br]) -> match_wild_sfx(Ar, Br);
match_wild_sfx(Ar, []) -> not lists:member($*, Ar); % Chk for bad name (= wildcards)
match_wild_sfx(_, _) -> false.
diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile
index 89e82a5f34..57879c20e6 100644
--- a/lib/public_key/test/Makefile
+++ b/lib/public_key/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2020. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ MODULES= \
public_key_SUITE \
pbe_SUITE \
pkits_SUITE \
- pubkey_ssh_SUITE
+ pubkey_cert_SUITE
ERL_FILES= $(MODULES:%=%.erl)
@@ -56,6 +56,7 @@ RELSYSDIR = $(RELEASE_PATH)/public_key_test
# FLAGS
# ----------------------------------------------------
ERL_COMPILE_FLAGS += $(INCLUDES)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -63,7 +64,7 @@ EBIN = .
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
clean:
diff --git a/lib/public_key/test/erl_make_certs.erl b/lib/public_key/test/erl_make_certs.erl
index e2a94dd886..a56c8e3691 100644
--- a/lib/public_key/test/erl_make_certs.erl
+++ b/lib/public_key/test/erl_make_certs.erl
@@ -47,7 +47,7 @@
%% {title, Title}
%% {dnQualifer, DnQ}
%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
-%% (obs IssuerKey migth be {Key, Password}
+%% (obs IssuerKey might be {Key, Password}
%% key = KeyFile|KeyBin|rsa|dsa|ec Subject PublicKey rsa, dsa or ec generates key
%%
%%
@@ -368,7 +368,7 @@ make_key(ec, _Opts) ->
gen_rsa2(Size) ->
try
- %% The numbers 2048,17 is choosen to not cause the cryptolib on
+ %% The numbers 2048,17 is chosen to not cause the cryptolib on
%% FIPS-enabled test machines be mad at us.
public_key:generate_key({rsa, 2048, 17})
catch
diff --git a/lib/public_key/test/pbe_SUITE.erl b/lib/public_key/test/pbe_SUITE.erl
index 4745698293..f3ed9f9b1d 100644
--- a/lib/public_key/test/pbe_SUITE.erl
+++ b/lib/public_key/test/pbe_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -219,12 +219,24 @@ pbdkdf2(Config) when is_list(Config) ->
pbes1() ->
[{doc,"Tests encode/decode EncryptedPrivateKeyInfo encrypted with different ciphers using PBES1"}].
pbes1(Config) when is_list(Config) ->
- decode_encode_key_file("pbes1_des_cbc_md5_enc_key.pem", "password", "DES-CBC", Config).
+ case lists:member(des_cbc, crypto:supports(ciphers))
+ andalso lists:member(md5, crypto:supports(hashs))
+ of
+ true ->
+ decode_encode_key_file("pbes1_des_cbc_md5_enc_key.pem", "password", "DES-CBC", Config);
+ false ->
+ {skip, alg_not_supported}
+ end.
pbes2() ->
[{doc,"Tests encode/decode EncryptedPrivateKeyInfo encrypted with different ciphers using PBES2"}].
pbes2(Config) when is_list(Config) ->
- decode_encode_key_file("pbes2_des_cbc_enc_key.pem", "password", "DES-CBC", Config),
+ case lists:member(des_cbc, crypto:supports(ciphers)) of
+ true ->
+ decode_encode_key_file("pbes2_des_cbc_enc_key.pem", "password", "DES-CBC", Config);
+ false ->
+ ok
+ end,
decode_encode_key_file("pbes2_des_ede3_cbc_enc_key.pem", "password", "DES-EDE3-CBC", Config),
decode_encode_key_file("pbes2_aes_128_enc_key.pem", "password", "AES-128-CBC", Config),
decode_encode_key_file("pbes2_aes_192_enc_key.pem", "password", "AES-192-CBC", Config),
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index ba3efdba09..ca722919a9 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
%%
-%% Se specification here:
+%% See specification here:
%% http://csrc.nist.gov/groups/ST/crypto_apps_infra/pki/pkitesting.html
-module(pkits_SUITE).
@@ -300,24 +300,24 @@ end_per_testcase(_Func, Config) ->
%%--------------------------- signature_verification--------------------------------------------------
valid_rsa_signature() ->
- [{doc, "Test rsa signatur verification"}].
+ [{doc, "Test rsa signature verification"}].
valid_rsa_signature(Config) when is_list(Config) ->
run([{ "4.1.1", "Valid Certificate Path Test1 EE", ok}]).
invalid_rsa_signature() ->
- [{doc,"Test rsa signatur verification"}].
+ [{doc,"Test rsa signature verification"}].
invalid_rsa_signature(Config) when is_list(Config) ->
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"}].
+ [{doc,"Test dsa signature verification"}].
valid_dsa_signature(Config) when is_list(Config) ->
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"}].
+ [{doc,"Test dsa signature verification"}].
invalid_dsa_signature(Config) when is_list(Config) ->
run([{ "4.1.6", "Invalid DSA Signature Test6 EE",{bad_cert,invalid_signature}}]).
@@ -332,7 +332,7 @@ not_before_valid() ->
[{doc,"Test valid periods"}].
not_before_valid(Config) when is_list(Config) ->
run([{ "4.2.3", "Valid pre2000 UTC notBefore Date Test3 EE", ok},
- { "4.2.4", "Valid GeneralizedTime notBefore Date Test4 EE", ok}]).
+ { "4.2.4", "Valid GeneralizedTime notBefore Date Test4 EE", ok}]).
not_after_invalid() ->
[{doc,"Test valid periods"}].
@@ -805,7 +805,7 @@ invalid_crl_issuer(Config) when is_list(Config) ->
]).
%% Although this test is valid it has a circular dependency. As a result
-%% an attempt is made to reursively checks a CRL path and rejected due to
+%% an attempt is made to recursively checks a CRL path and rejected due to
%% a CRL path validation error. PKITS notes suggest this test does not
%% need to be run due to this issue.
%% { "4.14.30", "Valid cRLIssuer Test30", 54 }
@@ -828,13 +828,24 @@ unknown_not_critical_extension(Config) when is_list(Config) ->
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
+-spec run([tuple()]) -> ok.
run(Tests) ->
[TA] = read_certs("Trust Anchor Root Certificate"),
run(Tests, TA).
+-spec run([Entry] | Entry, TA) -> ok when
+ TA :: public_key:pem_entry(),
+ Entry :: {CA, Test, Result} | {CA, Test, Result, CertificateBodies},
+ CA :: public_key:pem_entry(),
+ Test :: string(),
+ Result :: atom(),
+ CertificateBodies :: [binary()].
run({Chap, Test, Result}, TA) ->
- CertChain = cas(Chap) ++ read_certs(Test),
- Options = path_validation_options(TA, Chap,Test),
+ run({Chap, Test, Result, read_certs(Test)}, TA);
+
+run({Chap, Test, Result, CertsBody}, TA) ->
+ CertChain = cas(Chap) ++ CertsBody,
+ Options = path_validation_options(Chap),
try public_key:pkix_path_validation(TA, CertChain, Options) of
{Result, _} -> ok;
{error,Result} when Result =/= ok ->
@@ -851,15 +862,14 @@ run({Chap, Test, Result}, TA) ->
exit(crash)
end;
-run([Test|Rest],TA) ->
- run(Test,TA),
- run(Rest,TA);
-run([],_) -> ok.
+run(Tests,TA) when is_list(Tests) ->
+ lists:foreach(fun (T) -> run(T, TA) end, Tests),
+ ok.
-path_validation_options(TA, Chap, Test) ->
+path_validation_options(Chap) ->
case needs_crl_options(Chap) of
true ->
- crl_options(TA, Chap, Test);
+ crl_options(Chap);
false ->
Fun =
fun(_,{bad_cert, _} = Reason, _) ->
@@ -873,9 +883,14 @@ path_validation_options(TA, Chap, Test) ->
[{verify_fun, {Fun, []}}]
end.
+-spec read_certs(TestCase :: string()) -> [CertificateContent :: binary()].
read_certs(Test) ->
File = cert_file(Test),
Ders = erl_make_certs:pem_to_der(File),
+ extract_certificate(Ders).
+
+-spec extract_certificate(Certificates :: [public_key:pem_entry()]) -> CertificateContent :: binary().
+extract_certificate(Ders) ->
[Cert || {'Certificate', Cert, not_encrypted} <- Ders].
read_crls(Test) ->
@@ -883,13 +898,15 @@ read_crls(Test) ->
Ders = erl_make_certs:pem_to_der(File),
[CRL || {'CertificateList', CRL, not_encrypted} <- Ders].
+-spec cert_file(TestCase :: string()) -> FilenamePath :: string().
cert_file(Test) ->
file(?CONV, lists:append(string:tokens(Test, " -")) ++ ".pem").
+-spec crl_file(TestCase :: string()) -> FilenamePath :: string().
crl_file(Test) ->
file(?CRL, lists:append(string:tokens(Test, " -")) ++ ".pem").
-
+-spec file(Subdir :: string(), Filename :: string()) -> FilenamePath :: string().
file(Sub,File) ->
TestDir = case get(datadir) of
undefined -> "./pkits_SUITE_data";
@@ -939,7 +956,7 @@ needs_crl_options("4.15" ++ _) ->
needs_crl_options(_) ->
false.
-crl_options(_TA, Chap, _Test) ->
+crl_options(Chap) ->
CRLNames = crl_names(Chap),
CRLs = crls(CRLNames),
Paths = lists:map(fun(CRLName) -> crl_path(CRLName) end, CRLNames),
@@ -966,16 +983,12 @@ crl_options(_TA, Chap, _Test) ->
CRLInfo = lists:reverse(CRLInfo0),
PathDb = crl_path_db(lists:reverse(Crls), Paths, []),
- Fun = fun(DP, CRLtoValidate, Id, PathDb0) ->
- trusted_cert_and_path(DP, CRLtoValidate, Id, PathDb0)
- end,
-
case CRLInfo of
[] ->
{valid, UserState};
[_|_] ->
case public_key:pkix_crls_validate(OtpCert, CRLInfo,
- [{issuer_fun,{Fun, PathDb}}]) of
+ [{issuer_fun,{fun trusted_cert_and_path/4, PathDb}}]) of
valid ->
{valid, UserState};
Reason ->
@@ -1089,6 +1102,7 @@ dp_crlissuer_to_issuer(DPCRLIssuer) ->
%%%%%%%%%%%%%%% CA mappings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-spec cas(Chap :: string()) -> [Certificates :: public_key:pem_entry()].
cas(Chap) ->
CAS = intermidiate_cas(Chap),
lists:foldl(fun([], Acc) ->
@@ -1097,7 +1111,8 @@ cas(Chap) ->
[CACert] = read_certs(CA),
[CACert | Acc]
end, [], CAS).
-
+
+-spec intermidiate_cas(Chap :: string()) -> [CACert :: string()].
intermidiate_cas(Chap) when Chap == "4.1.1";
Chap == "4.1.3";
Chap == "4.2.2";
diff --git a/lib/public_key/test/pubkey_cert_SUITE.erl b/lib/public_key/test/pubkey_cert_SUITE.erl
new file mode 100644
index 0000000000..7d51d5afda
--- /dev/null
+++ b/lib/public_key/test/pubkey_cert_SUITE.erl
@@ -0,0 +1,178 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2023. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(pubkey_cert_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+%% -include_lib("public_key/include/public_key.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [{group, time_str_2_gregorian_sec}].
+
+groups() ->
+ [{time_str_2_gregorian_sec, [], time_str_two_gregorian()}].
+
+time_str_two_gregorian() ->
+ [ time_str_2_gregorian_utc_post2000
+ , time_str_2_gregorian_utc_limit_50_years_before_current_time
+ , time_str_2_gregorian_utc_limit_51_years_before_current_time
+ , time_str_2_gregorian_utc_limit_50_years_from_current_time
+ , time_str_2_gregorian_utc_limit_49_years_from_current_time
+ , time_str_2_gregorian_generaltime_50_years_before_current_time
+ , time_str_2_gregorian_generaltime_50_years_from_current_time
+ ].
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+time_str_2_gregorian_utc_post2000() ->
+ [{doc, "Tests a valid gregorian Utc time"}].
+time_str_2_gregorian_utc_post2000(_) ->
+ YYMMDD = "450101",
+ HHMMSSZ = "000000Z",
+ ExpectedYear = 2045,
+ UtcTime = {utcTime, YYMMDD ++ HHMMSSZ},
+ {ExpectedDate, _} = convert_to_datetime_format(UtcTime, ExpectedYear),
+
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ {ExpectedDate, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+
+time_str_2_gregorian_utc_limit_50_years_before_current_time() ->
+ [{doc, "Tests limit of gregorian Utc time 50 years before current time"}].
+time_str_2_gregorian_utc_limit_50_years_before_current_time(_) ->
+ {ExpectedDate, UtcTime} = get_date(utcTime, -50),
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ {ExpectedDate, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+time_str_2_gregorian_utc_limit_51_years_before_current_time() ->
+ [{doc, "Tests limit of gregorian Utc time 51 years before current time"}].
+time_str_2_gregorian_utc_limit_51_years_before_current_time(_) ->
+ {{Y, M, D}, UtcTime} = get_date(utcTime, -51),
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ %% the sliding window method from pubkey_cert reaches its limit and
+ %% reverses the year from 19XX to 20XX. Because of this, the expected
+ %% year is current_year + 50, or ExpectedYear + 100 (they are equivalent)
+ ExpectedYear = Y + 100,
+ {{ExpectedYear, M, D}, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+time_str_2_gregorian_utc_limit_50_years_from_current_time() ->
+ [{doc, "Tests a valid gregorian Utc time 50 years from now"}].
+time_str_2_gregorian_utc_limit_50_years_from_current_time(_) ->
+ {{Y, M, D}, UtcTime} = get_date(utcTime, 50),
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ %% the sliding window method from pubkey_cert reaches its limit and
+ %% reverses the year from 20XX to 19XX. Because of this, the expected
+ %% year is current_year - 50, or ExpectedYear - 100 (they are equivalent)
+ ExpectedYear = Y - 100,
+ {{ExpectedYear, M, D}, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+time_str_2_gregorian_utc_limit_49_years_from_current_time() ->
+ [{doc, "Tests a valid gregorian Utc time 49 years from now"}].
+time_str_2_gregorian_utc_limit_49_years_from_current_time(_) ->
+ {ExpectedDate, UtcTime} = get_date(utcTime, 49),
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ {ExpectedDate, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+
+time_str_2_gregorian_generaltime_50_years_before_current_time() ->
+ [{doc, "Tests a valid general time 50 years before current time"}].
+time_str_2_gregorian_generaltime_50_years_before_current_time(_) ->
+ {ExpectedDate, UtcTime} = get_date(generalTime, -50),
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ {ExpectedDate, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+
+time_str_2_gregorian_generaltime_50_years_from_current_time() ->
+ [{doc, "Tests a valid general time 50 years from now"}].
+time_str_2_gregorian_generaltime_50_years_from_current_time(_) ->
+ {ExpectedDate, UtcTime} = get_date(generalTime, 50),
+ Result = pubkey_cert:time_str_2_gregorian_sec(UtcTime),
+ {ExpectedDate, _} = calendar:gregorian_seconds_to_datetime(Result).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Helper functions
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-spec convert_to_datetime_format({Format, Date}, ExpectedYear) -> Result when
+ Format :: generalTime | utcTime,
+ Date :: YYMMDDHHMMSS | YYYYMMDDHHMMSS,
+ YYMMDDHHMMSS :: string(),
+ YYYYMMDDHHMMSS :: string(),
+ ExpectedYear :: non_neg_integer(),
+ Result :: {{non_neg_integer(), 1..12, 1..31}, {0, 0, 0}}.
+convert_to_datetime_format({Format, Date}, ExpectedYear) ->
+ YYMMDD = group_year(Format, Date),
+ [Y, M, D] = lists:map(fun (Str) -> erlang:list_to_integer(Str) end, YYMMDD),
+ %% assertions to test that the result is the expected one
+ case Format of
+ utcTime -> (ExpectedYear rem 100) =:= Y;
+ generalTime -> ExpectedYear =:= Y
+ end,
+ {{ExpectedYear, M, D}, {0, 0, 0}}.
+
+-spec get_date(Format, YearsFromNow) -> {{Year, Month, Day}, UtcDate} when
+ Format :: utcTime | generalTime,
+ YearsFromNow :: integer(),
+ Year :: non_neg_integer(),
+ Month :: 1..12,
+ Day :: 1..31,
+ UtcDate :: string().
+get_date(Format, Years) ->
+ {YYYY, MM0, DD0} = date(),
+ MM = io_lib:format("~2..0w", [MM0]),
+ DD = io_lib:format("~2..0w", [DD0]),
+ ExpectedYear = YYYY + Years,
+ YYMMDD = format_year(Format, ExpectedYear, {MM, DD}),
+ HHMMSSZ = "000000Z",
+ FormattedTime = {Format, YYMMDD ++ HHMMSSZ},
+ {ExpectedDate, _} = convert_to_datetime_format(FormattedTime, ExpectedYear),
+ {ExpectedDate, FormattedTime}.
+
+-spec format_year(Format, ExpectedYear, {Month, Day}) -> YYMMDD | YYYYMMDD when
+ Format :: utcTime | generalTime,
+ ExpectedYear :: non_neg_integer(),
+ Month :: string(),
+ Day :: string(),
+ YYMMDD :: string(),
+ YYYYMMDD :: string().
+format_year(utcTime, ExpectedYear, {MM, DD}) ->
+ YY = erlang:integer_to_list((ExpectedYear) rem 100),
+ lists:flatten(YY++MM++DD);
+format_year(generalTime, ExpectedYear, {MM, DD}) ->
+ YY = erlang:integer_to_list(ExpectedYear),
+ lists:flatten(YY++MM++DD).
+
+-spec group_year(Format, Date) -> [list()] when
+ Format :: utcTime | generalTime,
+ Date :: [non_neg_integer()].
+group_year(utcTime, [Y1, Y2, M1, M2, D1, D2 | _]) ->
+ [[Y1, Y2], [M1, M2], [D1, D2]];
+group_year(generalTime, [Y1, Y2, Y3, Y4, M1, M2, D1, D2 | _]) ->
+ [[Y1, Y2, Y3, Y4], [M1, M2], [D1, D2]].
diff --git a/lib/public_key/test/pubkey_ssh_SUITE.erl b/lib/public_key/test/pubkey_ssh_SUITE.erl
deleted file mode 100644
index 4b7c2082ba..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE.erl
+++ /dev/null
@@ -1,457 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
--module(pubkey_ssh_SUITE).
-
-%% This test suite tests thoose functions until they are removed
--compile([{nowarn_deprecated_function,
- [{public_key,ssh_decode,2},
- {public_key,ssh_encode,2},
- {public_key,ssh_hostkey_fingerprint,1},
- {public_key,ssh_hostkey_fingerprint,2}
- ]}
- ]).
-
--include_lib("common_test/include/ct.hrl").
--include_lib("public_key/include/public_key.hrl").
-
--export([
- suite/0,
- 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,
-
- ssh_rsa_public_key/1,
- ssh_dsa_public_key/1,
- ssh_ecdsa_public_key/1,
- ssh_rfc4716_rsa_comment/1,
- ssh_rfc4716_dsa_comment/1,
- ssh_rfc4716_rsa_subject/1,
- ssh_known_hosts/1,
- ssh1_known_hosts/1,
- ssh_auth_keys/1,
- ssh1_auth_keys/1,
- ssh_openssh_public_key_with_comment/1,
- ssh_openssh_public_key_long_header/1,
-
- ssh_hostkey_fingerprint_md5_implicit/1,
- ssh_hostkey_fingerprint_md5/1,
- ssh_hostkey_fingerprint_sha/1,
- ssh_hostkey_fingerprint_sha256/1,
- ssh_hostkey_fingerprint_sha384/1,
- ssh_hostkey_fingerprint_sha512/1,
- ssh_hostkey_fingerprint_list/1
- ]).
-
-
--define(TIMEOUT, 120000). % 2 min
-
-
-%%--------------------------------------------------------------------
-%% Common Test interface functions -----------------------------------
-%%--------------------------------------------------------------------
-
-suite() ->
- [].
-
-all() ->
- [{group, ssh_public_key_decode_encode},
- {group, ssh_hostkey_fingerprint}
- ].
-
-groups() ->
- [{ssh_public_key_decode_encode, [],
- [ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key,
- ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment,
- ssh_rfc4716_rsa_subject,
- ssh_known_hosts,
- ssh_auth_keys, ssh1_known_hosts, ssh1_auth_keys, ssh_openssh_public_key_with_comment,
- ssh_openssh_public_key_long_header]},
-
- {ssh_hostkey_fingerprint, [],
- [ssh_hostkey_fingerprint_md5_implicit,
- ssh_hostkey_fingerprint_md5,
- ssh_hostkey_fingerprint_sha,
- ssh_hostkey_fingerprint_sha256,
- ssh_hostkey_fingerprint_sha384,
- ssh_hostkey_fingerprint_sha512,
- ssh_hostkey_fingerprint_list]}
- ].
-%%-------------------------------------------------------------------
-init_per_suite(Config) ->
- application:stop(crypto),
- try crypto:start() of
- ok ->
- application:start(asn1),
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(_Config) ->
- application:stop(asn1),
- application:stop(crypto).
-
-%%-------------------------------------------------------------------
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-%%-------------------------------------------------------------------
-init_per_testcase(ssh_hostkey_fingerprint_md5_implicit, Config) ->
- init_fingerprint_testcase([md5], Config);
-
-init_per_testcase(ssh_hostkey_fingerprint_md5, Config) ->
- init_fingerprint_testcase([md5], Config);
-
-init_per_testcase(ssh_hostkey_fingerprint_sha, Config) ->
- init_fingerprint_testcase([sha], Config);
-
-init_per_testcase(ssh_hostkey_fingerprint_sha256, Config) ->
- init_fingerprint_testcase([sha256], Config);
-
-init_per_testcase(ssh_hostkey_fingerprint_sha384, Config) ->
- init_fingerprint_testcase([sha384], Config);
-
-init_per_testcase(ssh_hostkey_fingerprint_sha512, Config) ->
- init_fingerprint_testcase([sha512], Config);
-
-init_per_testcase(ssh_hostkey_fingerprint_list , Config) ->
- init_fingerprint_testcase([sha,md5], Config);
-
-init_per_testcase(_, Config) ->
- init_common_per_testcase(Config).
-
-
-init_fingerprint_testcase(Algs, Config) ->
- Hashs = proplists:get_value(hashs, crypto:supports(), []),
- case Algs -- Hashs of
- [] -> init_common_per_testcase(Config);
- UnsupportedAlgs -> {skip,{UnsupportedAlgs,not_supported}}
- end.
-
-init_common_per_testcase(Config0) ->
- Config = lists:keydelete(watchdog, 1, Config0),
- Dog = ct:timetrap(?TIMEOUT),
- [{watchdog, Dog} | Config].
-
-
-end_per_testcase(_TestCase, _Config) ->
- ok.
-
-%%--------------------------------------------------------------------
-%% Test Cases --------------------------------------------------------
-%%--------------------------------------------------------------------
-ssh_rsa_public_key(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, RSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_rsa_pub")),
- [{PubKey, Attributes1}] = public_key:ssh_decode(RSARawSsh2, public_key),
- [{PubKey, Attributes1}] = public_key:ssh_decode(RSARawSsh2, rfc4716_public_key),
-
- {ok, RSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_rsa_pub")),
- [{PubKey, Attributes2}] = public_key:ssh_decode(RSARawOpenSsh, public_key),
- [{PubKey, Attributes2}] = public_key:ssh_decode(RSARawOpenSsh, openssh_public_key),
-
- %% Can not check EncodedSSh == RSARawSsh2 and EncodedOpenSsh
- %% = RSARawOpenSsh as line breakpoints may differ
-
- EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key),
- EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key),
-
- [{PubKey, Attributes1}] =
- public_key:ssh_decode(EncodedSSh, public_key),
- [{PubKey, Attributes2}] =
- public_key:ssh_decode(EncodedOpenSsh, public_key).
-
-%%--------------------------------------------------------------------
-ssh_dsa_public_key(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, DSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_dsa_pub")),
- [{PubKey, Attributes1}] = public_key:ssh_decode(DSARawSsh2, public_key),
- [{PubKey, Attributes1}] = public_key:ssh_decode(DSARawSsh2, rfc4716_public_key),
-
- {ok, DSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_dsa_pub")),
- [{PubKey, Attributes2}] = public_key:ssh_decode(DSARawOpenSsh, public_key),
- [{PubKey, Attributes2}] = public_key:ssh_decode(DSARawOpenSsh, openssh_public_key),
-
- %% Can not check EncodedSSh == DSARawSsh2 and EncodedOpenSsh
- %% = DSARawOpenSsh as line breakpoints may differ
-
- EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key),
- EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key),
-
- [{PubKey, Attributes1}] =
- public_key:ssh_decode(EncodedSSh, public_key),
- [{PubKey, Attributes2}] =
- public_key:ssh_decode(EncodedOpenSsh, public_key).
-
-%%--------------------------------------------------------------------
-ssh_ecdsa_public_key(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, ECDSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_ecdsa_pub")),
- [{PubKey, Attributes1}] = public_key:ssh_decode(ECDSARawSsh2, public_key),
- [{PubKey, Attributes1}] = public_key:ssh_decode(ECDSARawSsh2, rfc4716_public_key),
-
- {ok, ECDSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_ecdsa_pub")),
- [{PubKey, Attributes2}] = public_key:ssh_decode(ECDSARawOpenSsh, public_key),
- [{PubKey, Attributes2}] = public_key:ssh_decode(ECDSARawOpenSsh, openssh_public_key),
-
- %% Can not check EncodedSSh == ECDSARawSsh2 and EncodedOpenSsh
- %% = ECDSARawOpenSsh as line breakpoints may differ
-
- EncodedSSh = public_key:ssh_encode([{PubKey, Attributes1}], rfc4716_public_key),
- EncodedOpenSsh = public_key:ssh_encode([{PubKey, Attributes2}], openssh_public_key),
-
- [{PubKey, Attributes1}] =
- public_key:ssh_decode(EncodedSSh, public_key),
- [{PubKey, Attributes2}] =
- public_key:ssh_decode(EncodedOpenSsh, public_key).
-
-%%--------------------------------------------------------------------
-ssh_rfc4716_rsa_comment(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, RSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_rsa_comment_pub")),
- [{#'RSAPublicKey'{} = PubKey, Attributes}] =
- public_key:ssh_decode(RSARawSsh2, public_key),
-
- Headers = proplists:get_value(headers, Attributes),
-
- Value = proplists:get_value("Comment", Headers, undefined),
- true = Value =/= undefined,
- RSARawSsh2 = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key).
-
-%%--------------------------------------------------------------------
-ssh_rfc4716_dsa_comment(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, DSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_dsa_comment_pub")),
- [{{_, #'Dss-Parms'{}} = PubKey, Attributes}] =
- public_key:ssh_decode(DSARawSsh2, public_key),
-
- Headers = proplists:get_value(headers, Attributes),
-
- Value = proplists:get_value("Comment", Headers, undefined),
- true = Value =/= undefined,
-
- %% Can not check Encoded == DSARawSsh2 as line continuation breakpoints may differ
- Encoded = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key),
- [{PubKey, Attributes}] =
- public_key:ssh_decode(Encoded, public_key).
-
-%%--------------------------------------------------------------------
-ssh_rfc4716_rsa_subject(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, RSARawSsh2} = file:read_file(filename:join(Datadir, "ssh2_subject_pub")),
- [{#'RSAPublicKey'{} = PubKey, Attributes}] =
- public_key:ssh_decode(RSARawSsh2, public_key),
-
- Headers = proplists:get_value(headers, Attributes),
-
- Value = proplists:get_value("Subject", Headers, undefined),
- true = Value =/= undefined,
-
- %% Can not check Encoded == RSARawSsh2 as line continuation breakpoints may differ
- Encoded = public_key:ssh_encode([{PubKey, Attributes}], rfc4716_public_key),
- [{PubKey, Attributes}] =
- public_key:ssh_decode(Encoded, public_key).
-
-%%--------------------------------------------------------------------
-ssh_known_hosts(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, SshKnownHosts} = file:read_file(filename:join(Datadir, "known_hosts")),
- [{#'RSAPublicKey'{}, Attributes1}, {#'RSAPublicKey'{}, Attributes2},
- {#'RSAPublicKey'{}, Attributes3}, {#'RSAPublicKey'{}, Attributes4}] = Decoded =
- public_key:ssh_decode(SshKnownHosts, known_hosts),
-
- Comment1 = undefined,
- Comment2 = "foo@bar.com",
- Comment3 = "Comment with whitespaces",
- Comment4 = "foo@bar.com Comment with whitespaces",
-
- Comment1 = proplists:get_value(comment, Attributes1, undefined),
- Comment2 = proplists:get_value(comment, Attributes2),
- Comment3 = proplists:get_value(comment, Attributes3),
- Comment4 = proplists:get_value(comment, Attributes4),
-
- Value1 = proplists:get_value(hostnames, Attributes1, undefined),
- Value2 = proplists:get_value(hostnames, Attributes2, undefined),
- true = (Value1 =/= undefined) and (Value2 =/= undefined),
-
- Encoded = public_key:ssh_encode(Decoded, known_hosts),
- Decoded = public_key:ssh_decode(Encoded, known_hosts).
-
-%%--------------------------------------------------------------------
-ssh1_known_hosts(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, SshKnownHosts} = file:read_file(filename:join(Datadir, "ssh1_known_hosts")),
- [{#'RSAPublicKey'{}, Attributes1}, {#'RSAPublicKey'{}, Attributes2},{#'RSAPublicKey'{}, Attributes3}]
- = Decoded = public_key:ssh_decode(SshKnownHosts, known_hosts),
-
- Value1 = proplists:get_value(hostnames, Attributes1, undefined),
- Value2 = proplists:get_value(hostnames, Attributes2, undefined),
- true = (Value1 =/= undefined) and (Value2 =/= undefined),
-
- Comment ="dhopson@VMUbuntu-DSH comment with whitespaces",
- Comment = proplists:get_value(comment, Attributes3),
-
- Encoded = public_key:ssh_encode(Decoded, known_hosts),
- Decoded = public_key:ssh_decode(Encoded, known_hosts).
-
-%%--------------------------------------------------------------------
-ssh_auth_keys(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, SshAuthKeys} = file:read_file(filename:join(Datadir, "auth_keys")),
- [{#'RSAPublicKey'{}, Attributes1}, {{_, #'Dss-Parms'{}}, Attributes2},
- {#'RSAPublicKey'{}, Attributes3}, {{_, #'Dss-Parms'{}}, Attributes4}
- ] = Decoded =
- public_key:ssh_decode(SshAuthKeys, auth_keys),
-
- Value1 = proplists:get_value(options, Attributes1, undefined),
- true = Value1 =/= undefined,
-
- Comment1 = Comment2 = "dhopson@VMUbuntu-DSH",
- Comment3 = Comment4 ="dhopson@VMUbuntu-DSH comment with whitespaces",
-
- Comment1 = proplists:get_value(comment, Attributes1),
- Comment2 = proplists:get_value(comment, Attributes2),
- Comment3 = proplists:get_value(comment, Attributes3),
- Comment4 = proplists:get_value(comment, Attributes4),
-
- Encoded = public_key:ssh_encode(Decoded, auth_keys),
- Decoded = public_key:ssh_decode(Encoded, auth_keys).
-
-%%--------------------------------------------------------------------
-ssh1_auth_keys(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, SshAuthKeys} = file:read_file(filename:join(Datadir, "ssh1_auth_keys")),
- [{#'RSAPublicKey'{}, Attributes1},
- {#'RSAPublicKey'{}, Attributes2}, {#'RSAPublicKey'{}, Attributes3},
- {#'RSAPublicKey'{}, Attributes4}, {#'RSAPublicKey'{}, Attributes5}] = Decoded =
- public_key:ssh_decode(SshAuthKeys, auth_keys),
-
- Value1 = proplists:get_value(bits, Attributes2, undefined),
- Value2 = proplists:get_value(bits, Attributes3, undefined),
- true = (Value1 =/= undefined) and (Value2 =/= undefined),
-
- Comment2 = Comment3 = "dhopson@VMUbuntu-DSH",
- Comment4 = Comment5 ="dhopson@VMUbuntu-DSH comment with whitespaces",
-
- undefined = proplists:get_value(comment, Attributes1, undefined),
- Comment2 = proplists:get_value(comment, Attributes2),
- Comment3 = proplists:get_value(comment, Attributes3),
- Comment4 = proplists:get_value(comment, Attributes4),
- Comment5 = proplists:get_value(comment, Attributes5),
-
- Encoded = public_key:ssh_encode(Decoded, auth_keys),
- Decoded = public_key:ssh_decode(Encoded, auth_keys).
-
-%%--------------------------------------------------------------------
-ssh_openssh_public_key_with_comment(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok, DSARawOpenSsh} = file:read_file(filename:join(Datadir, "openssh_dsa_with_comment_pub")),
- [{{_, #'Dss-Parms'{}}, _}] = public_key:ssh_decode(DSARawOpenSsh, openssh_public_key).
-
-%%--------------------------------------------------------------------
-ssh_openssh_public_key_long_header(Config) when is_list(Config) ->
- Datadir = proplists:get_value(data_dir, Config),
-
- {ok,RSARawOpenSsh} = file:read_file(filename:join(Datadir, "ssh_rsa_long_header_pub")),
- [{#'RSAPublicKey'{}, _}] = Decoded = public_key:ssh_decode(RSARawOpenSsh, public_key),
-
- Encoded = public_key:ssh_encode(Decoded, rfc4716_public_key),
- Decoded = public_key:ssh_decode(Encoded, rfc4716_public_key).
-
-%%--------------------------------------------------------------------
-%% Check of different host keys left to later
-ssh_hostkey_fingerprint_md5_implicit(_Config) ->
- Expected = "4b:0b:63:de:0f:a7:3a:ab:2c:cc:2d:d1:21:37:1d:3a",
- Expected = public_key:ssh_hostkey_fingerprint(ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Check of different host keys left to later
-ssh_hostkey_fingerprint_md5(_Config) ->
- Expected = "MD5:4b:0b:63:de:0f:a7:3a:ab:2c:cc:2d:d1:21:37:1d:3a",
- Expected = public_key:ssh_hostkey_fingerprint(md5, ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Since this kind of fingerprint is not available yet on standard
-%% distros, we do like this instead. The Expected is generated with:
-%% $ openssh-7.3p1/ssh-keygen -E sha1 -lf <file>
-%% 2048 SHA1:Soammnaqg06jrm2jivMSnzQGlmk none@example.org (RSA)
-ssh_hostkey_fingerprint_sha(_Config) ->
- Expected = "SHA1:Soammnaqg06jrm2jivMSnzQGlmk",
- Expected = public_key:ssh_hostkey_fingerprint(sha, ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Since this kind of fingerprint is not available yet on standard
-%% distros, we do like this instead.
-ssh_hostkey_fingerprint_sha256(_Config) ->
- Expected = "SHA256:T7F1BahkJWR7iJO8+rpzWOPbp7LZP4MlNrDExdNYOvY",
- Expected = public_key:ssh_hostkey_fingerprint(sha256, ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Since this kind of fingerprint is not available yet on standard
-%% distros, we do like this instead.
-ssh_hostkey_fingerprint_sha384(_Config) ->
- Expected = "SHA384:QhkLoGNI4KXdPvC//HxxSCP3uTQVADqxdajbgm+Gkx9zqz8N94HyP1JmH8C4/aEl",
- Expected = public_key:ssh_hostkey_fingerprint(sha384, ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Since this kind of fingerprint is not available yet on standard
-%% distros, we do like this instead.
-ssh_hostkey_fingerprint_sha512(_Config) ->
- Expected = "SHA512:ezUismvm3ADQQb6Nm0c1DwQ6ydInlJNfsnSQejFkXNmABg1Aenk9oi45CXeBOoTnlfTsGG8nFDm0smP10PBEeA",
- Expected = public_key:ssh_hostkey_fingerprint(sha512, ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Since this kind of fingerprint is not available yet on standard
-%% distros, we do like this instead.
-ssh_hostkey_fingerprint_list(_Config) ->
- Expected = ["SHA1:Soammnaqg06jrm2jivMSnzQGlmk",
- "MD5:4b:0b:63:de:0f:a7:3a:ab:2c:cc:2d:d1:21:37:1d:3a"],
- Expected = public_key:ssh_hostkey_fingerprint([sha,md5], ssh_hostkey(rsa)).
-
-%%--------------------------------------------------------------------
-%% Internal functions ------------------------------------------------
-%%--------------------------------------------------------------------
-ssh_hostkey(rsa) ->
- [{PKdecoded,_}] =
- public_key:ssh_decode(
- <<"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYXcYmsyJBstl4EfFYzfQJmSiUE162zvSGSoMYybShYOI6rnnyvvihfw8Aml+2gZ716F2tqG48FQ/yPZEGWNPMrCejPpJctaPWhpNdNMJ8KFXSEgr5bY2mEpa19DHmuDeXKzeJJ+X7s3fVdYc4FMk5731KIW6Huf019ZnTxbx0VKG6b1KAJBg3vpNsDxEMwQ4LFMB0JHVklOTzbxmpaeULuIxvl65A+eGeFVeo2Q+YI9UnwY1vSgmc9Azwy8Ie9Z0HpQBN5I7Uc5xnknT8V6xDhgNfXEfzsgsRdDfZLECt1WO/1gP9wkosvAGZWt5oG8pbNQWiQdFq536ck8WQD9WD none@example.org">>,
- public_key),
- PKdecoded.
-
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/auth_keys b/lib/public_key/test/pubkey_ssh_SUITE_data/auth_keys
deleted file mode 100644
index 8be7357a06..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/auth_keys
+++ /dev/null
@@ -1,7 +0,0 @@
-command="dump /home",no-pty,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAwrr66r8n6B8Y0zMF3dOpXEapIQD9DiYQ6D6/zwor9o39jSkHNiMMER/GETBbzP83LOcekm02aRjo55ArO7gPPVvCXbrirJu9pkm4AC4BBre5xSLS7soyzwbigFruM8G63jSXqpHqJ/ooi168sKMC2b0Ncsi+JlTfNYlDXJVLKEeZgZOInQyMmtisaDTUQWTIv1snAizf4iIYENuAkGYGNCL77u5Y5VOu5eQipvFajTnps9QvUx/zdSFYn9e2sulWM3Bxc/S4IJ67JWHVRpfJxGi3hinRBH8WQdXuUwdJJTiJHKPyYrrM7Q6Xq4TOMFtcRuLDC6u3BXM1L0gBvHPNOnD5l2Lp5EjUkQ9CBf2j4A4gfH+iWQZyk08esAG/iwArAVxkl368+dkbMWOXL8BN4x5zYgdzoeypQZZ2RKH780MCTSo4WQ19DP8pw+9q3bSFC9H3xYAxrKAJNWjeTUJOTrTe+mWXXU770gYyQTxa2ycnYrlZucn1S3vsvn6eq7NZZ8NRbyv1n15Ocg+nHK4fuKOrwPhU3NbKQwtjb0Wsxx1gAmQqIOLTpAdsrAauPxC7TPYA5qQVCphvimKuhQM/1gMV225JrnjspVlthCzuFYUjXOKC3wxz6FFEtwnXu3uC5bVVkmkNadJmD21gD23yk4BraGXVYpRMIB+X+OTUUI8= dhopson@VMUbuntu-DSH
-
-ssh-dss AAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbETW6ToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdHYI14Om1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5cvwHWTZDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGfJ0/RHd+NjB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAAvioUPkmdMc0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACBAN7CY+KKv1gHpRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HSn24VYtYtsMu74qXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5sY29ouezv4Xz2PuMch5VGPP+CDqzCM4loWgV dhopson@VMUbuntu-DSH
-
-command="dump /home",no-pty,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAwrr66r8n6B8Y0zMF3dOpXEapIQD9DiYQ6D6/zwor9o39jSkHNiMMER/GETBbzP83LOcekm02aRjo55ArO7gPPVvCXbrirJu9pkm4AC4BBre5xSLS7soyzwbigFruM8G63jSXqpHqJ/ooi168sKMC2b0Ncsi+JlTfNYlDXJVLKEeZgZOInQyMmtisaDTUQWTIv1snAizf4iIYENuAkGYGNCL77u5Y5VOu5eQipvFajTnps9QvUx/zdSFYn9e2sulWM3Bxc/S4IJ67JWHVRpfJxGi3hinRBH8WQdXuUwdJJTiJHKPyYrrM7Q6Xq4TOMFtcRuLDC6u3BXM1L0gBvHPNOnD5l2Lp5EjUkQ9CBf2j4A4gfH+iWQZyk08esAG/iwArAVxkl368+dkbMWOXL8BN4x5zYgdzoeypQZZ2RKH780MCTSo4WQ19DP8pw+9q3bSFC9H3xYAxrKAJNWjeTUJOTrTe+mWXXU770gYyQTxa2ycnYrlZucn1S3vsvn6eq7NZZ8NRbyv1n15Ocg+nHK4fuKOrwPhU3NbKQwtjb0Wsxx1gAmQqIOLTpAdsrAauPxC7TPYA5qQVCphvimKuhQM/1gMV225JrnjspVlthCzuFYUjXOKC3wxz6FFEtwnXu3uC5bVVkmkNadJmD21gD23yk4BraGXVYpRMIB+X+OTUUI8= dhopson@VMUbuntu-DSH comment with whitespaces
-
-ssh-dss AAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbETW6ToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdHYI14Om1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5cvwHWTZDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGfJ0/RHd+NjB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAAvioUPkmdMc0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACBAN7CY+KKv1gHpRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HSn24VYtYtsMu74qXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5sY29ouezv4Xz2PuMch5VGPP+CDqzCM4loWgV dhopson@VMUbuntu-DSH comment with whitespaces
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/known_hosts b/lib/public_key/test/pubkey_ssh_SUITE_data/known_hosts
deleted file mode 100644
index 3c3af68178..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/known_hosts
+++ /dev/null
@@ -1,8 +0,0 @@
-hostname.domain.com,192.168.0.1 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1XY18+zA8VNK2YkzygOkMqUxHSTfxT1Xxx8CgDZgcQH8HUhPssW5ttvG8nKetlPQZAVk1C4WkWS1y5b3ekBhZTIxocp9Joc6V1+f2EOfO2mSLRwB16RGrdw6q7msrBXTC/dl+hF45kMMzVNzqxnSMVOa0sEPK2zK6Sg3Vi9fCSM=
-
-|1|BWO5qDxk/cFH0wa05JLdHn+j6xQ=|rXQvIxh5cDD3C43k5DPDamawVNA= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1XY18+zA8VNK2YkzygOkMqUxHSTfxT1Xxx8CgDZgcQH8HUhPssW5ttvG8nKetlPQZAVk1C4WkWS1y5b3ekBhZTIxocp9Joc6V1+f2EOfO2mSLRwB16RGrdw6q7msrBXTC/dl+hF45kMMzVNzqxnSMVOa0sEPK2zK6Sg3Vi9fCSM= foo@bar.com
-
-hostname.domain.com,192.168.0.1 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1XY18+zA8VNK2YkzygOkMqUxHSTfxT1Xxx8CgDZgcQH8HUhPssW5ttvG8nKetlPQZAVk1C4WkWS1y5b3ekBhZTIxocp9Joc6V1+f2EOfO2mSLRwB16RGrdw6q7msrBXTC/dl+hF45kMMzVNzqxnSMVOa0sEPK2zK6Sg3Vi9fCSM= Comment with whitespaces
-
-|1|BWO5qDxk/cFH0wa05JLdHn+j6xQ=|rXQvIxh5cDD3C43k5DPDamawVNA= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1XY18+zA8VNK2YkzygOkMqUxHSTfxT1Xxx8CgDZgcQH8HUhPssW5ttvG8nKetlPQZAVk1C4WkWS1y5b3ekBhZTIxocp9Joc6V1+f2EOfO2mSLRwB16RGrdw6q7msrBXTC/dl+hF45kMMzVNzqxnSMVOa0sEPK2zK6Sg3Vi9fCSM= foo@bar.com Comment with whitespaces
-
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_pub
deleted file mode 100644
index a765ba8189..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-dss AAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbETW6ToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdHYI14Om1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5cvwHWTZDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGfJ0/RHd+NjB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAAvioUPkmdMc0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACBAN7CY+KKv1gHpRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HSn24VYtYtsMu74qXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5sY29ouezv4Xz2PuMch5VGPP+CDqzCM4loWgV dhopson@VMUbuntu-DSH
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_with_comment_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_with_comment_pub
deleted file mode 100644
index d5a34a3f78..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_dsa_with_comment_pub
+++ /dev/null
@@ -1,3 +0,0 @@
-#This should be ignored!!
-
-ssh-dss AAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbETW6ToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdHYI14Om1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5cvwHWTZDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGfJ0/RHd+NjB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAAvioUPkmdMc0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACBAN7CY+KKv1gHpRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HSn24VYtYtsMu74qXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5sY29ouezv4Xz2PuMch5VGPP+CDqzCM4loWgV dhopson@VMUbuntu-DSH
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_ecdsa_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_ecdsa_pub
deleted file mode 100644
index a49b4264b8..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_ecdsa_pub
+++ /dev/null
@@ -1 +0,0 @@
-ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJrVlKYIT+MlxxRx5BFXisHHkcGMAAKv2dguUeOsutsYyzs9JAczvl6c+Sypra5+qOi2LHPXw6GGluuXcOssOM= uabhnil@elxadlj3q32
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_rsa_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_rsa_pub
deleted file mode 100644
index 0a0838db40..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/openssh_rsa_pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEAwrr66r8n6B8Y0zMF3dOpXEapIQD9DiYQ6D6/zwor9o39jSkHNiMMER/GETBbzP83LOcekm02aRjo55ArO7gPPVvCXbrirJu9pkm4AC4BBre5xSLS7soyzwbigFruM8G63jSXqpHqJ/ooi168sKMC2b0Ncsi+JlTfNYlDXJVLKEeZgZOInQyMmtisaDTUQWTIv1snAizf4iIYENuAkGYGNCL77u5Y5VOu5eQipvFajTnps9QvUx/zdSFYn9e2sulWM3Bxc/S4IJ67JWHVRpfJxGi3hinRBH8WQdXuUwdJJTiJHKPyYrrM7Q6Xq4TOMFtcRuLDC6u3BXM1L0gBvHPNOnD5l2Lp5EjUkQ9CBf2j4A4gfH+iWQZyk08esAG/iwArAVxkl368+dkbMWOXL8BN4x5zYgdzoeypQZZ2RKH780MCTSo4WQ19DP8pw+9q3bSFC9H3xYAxrKAJNWjeTUJOTrTe+mWXXU770gYyQTxa2ycnYrlZucn1S3vsvn6eq7NZZ8NRbyv1n15Ocg+nHK4fuKOrwPhU3NbKQwtjb0Wsxx1gAmQqIOLTpAdsrAauPxC7TPYA5qQVCphvimKuhQM/1gMV225JrnjspVlthCzuFYUjXOKC3wxz6FFEtwnXu3uC5bVVkmkNadJmD21gD23yk4BraGXVYpRMIB+X+OTUUI8= dhopson@VMUbuntu-DSH
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_auth_keys b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_auth_keys
deleted file mode 100644
index ac3d61b4c7..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_auth_keys
+++ /dev/null
@@ -1,9 +0,0 @@
-1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663
-
-1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663 dhopson@VMUbuntu-DSH
-
-command="dump /home",no-pty,no-port-forwarding 1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663 dhopson@VMUbuntu-DSH
-
-1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663 dhopson@VMUbuntu-DSH comment with whitespaces
-
-command="dump /home",no-pty,no-port-forwarding 1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663 dhopson@VMUbuntu-DSH comment with whitespaces
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_known_hosts b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_known_hosts
deleted file mode 100644
index 835b16ab67..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh1_known_hosts
+++ /dev/null
@@ -1,3 +0,0 @@
-hostname.domain.com,192.168.0.1 1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663 dhopson@VMUbuntu-DSH
-hostname2.domain.com,192.168.0.2 1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663
-hostname3.domain.com,192.168.0.3 1024 35 794430685278501116412873221867658581245241426828503388129294124540165981586596106773643485704743298698207838825035605868404742682423919455523383721081589378970796492944950066480951790660582889972423189943567111507801410254720228911513553205592856585541922662924268445466959576882300405064708497308004255650466014242855505233634626075778108365396568863197935915425650388910408127232583533503834009244199384570662092164277923946411149853110048365318587554141774139652307149492021035538341281427025252592933784473453522113124752189378715431529801894015739903371171585194505182320772654217490509848165365152457990491089951560694728469571221819385402117009544812199223715540348068497710535492913376699508575875577554607325905000745578091554027803374110357015655416894607641289462159580964951182385869168785183135763253784745647466464331174922663455073627501620274348748413309761116542324505123795743603781806636788810617169341018091186028310551725315297135354426735951943325476221811539822892501042385411792050504283745898099390893596941969752683246939665141002098430129617772928840718016009187577151479855846883928332010147501182201528575840364152774917950524127063432334646746291719251739989499132767590205934821590545762802261107691663 dhopson@VMUbuntu-DSH comment with whitespaces
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_comment_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_comment_pub
deleted file mode 100644
index ca5089dbd7..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_comment_pub
+++ /dev/null
@@ -1,13 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Comment: This is my public key for use on \
-servers which I don't like.
-AAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbET
-W6ToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdH
-YI14Om1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5c
-vwHWTZDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGf
-J0/RHd+NjB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAA
-vioUPkmdMc0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACB
-AN7CY+KKv1gHpRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HS
-n24VYtYtsMu74qXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5
-sY29ouezv4Xz2PuMch5VGPP+CDqzCM4loWgV
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_pub
deleted file mode 100644
index a5e38be81a..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_dsa_pub
+++ /dev/null
@@ -1,12 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Comment: DSA Public Key for use with MyIsp
-AAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbET
-W6ToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdH
-YI14Om1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5c
-vwHWTZDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGf
-J0/RHd+NjB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAA
-vioUPkmdMc0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACB
-AN7CY+KKv1gHpRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HS
-n24VYtYtsMu74qXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5
-sY29ouezv4Xz2PuMch5VGPP+CDqzCM4loWgV
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_ecdsa_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_ecdsa_pub
deleted file mode 100644
index 702e5c4fde..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_ecdsa_pub
+++ /dev/null
@@ -1,6 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Comment: "256-bit ECDSA, converted by uabhnil@elxadlj3q32 from OpenSSH"
-AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIJrVlKYIT+MlxxRx5
-BFXisHHkcGMAAKv2dguUeOsutsYyzs9JAczvl6c+Sypra5+qOi2LHPXw6GGluuXcOssOM=
-
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_comment_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_comment_pub
deleted file mode 100644
index e4d446147c..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_comment_pub
+++ /dev/null
@@ -1,7 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Comment: "1024-bit RSA, converted from OpenSSH by me@example.com"
-x-command: /home/me/bin/lock-in-guest.sh
-AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
-YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
-5TT4SfsUu/iKy9lUcCfXzwre4WWZSXXcPff+EHtWshahu3WzBdnGxm5Xoi89zcE=
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_pub
deleted file mode 100644
index 761088b517..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_rsa_pub
+++ /dev/null
@@ -1,13 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-AAAAB3NzaC1yc2EAAAABIwAAAgEAwrr66r8n6B8Y0zMF3dOpXEapIQD9DiYQ6D6/zwor9o
-39jSkHNiMMER/GETBbzP83LOcekm02aRjo55ArO7gPPVvCXbrirJu9pkm4AC4BBre5xSLS
-7soyzwbigFruM8G63jSXqpHqJ/ooi168sKMC2b0Ncsi+JlTfNYlDXJVLKEeZgZOInQyMmt
-isaDTUQWTIv1snAizf4iIYENuAkGYGNCL77u5Y5VOu5eQipvFajTnps9QvUx/zdSFYn9e2
-sulWM3Bxc/S4IJ67JWHVRpfJxGi3hinRBH8WQdXuUwdJJTiJHKPyYrrM7Q6Xq4TOMFtcRu
-LDC6u3BXM1L0gBvHPNOnD5l2Lp5EjUkQ9CBf2j4A4gfH+iWQZyk08esAG/iwArAVxkl368
-+dkbMWOXL8BN4x5zYgdzoeypQZZ2RKH780MCTSo4WQ19DP8pw+9q3bSFC9H3xYAxrKAJNW
-jeTUJOTrTe+mWXXU770gYyQTxa2ycnYrlZucn1S3vsvn6eq7NZZ8NRbyv1n15Ocg+nHK4f
-uKOrwPhU3NbKQwtjb0Wsxx1gAmQqIOLTpAdsrAauPxC7TPYA5qQVCphvimKuhQM/1gMV22
-5JrnjspVlthCzuFYUjXOKC3wxz6FFEtwnXu3uC5bVVkmkNadJmD21gD23yk4BraGXVYpRM
-IB+X+OTUUI8=
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_subject_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_subject_pub
deleted file mode 100644
index 8b8ccda8ba..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh2_subject_pub
+++ /dev/null
@@ -1,8 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Subject: me
-Comment: 1024-bit rsa, created by me@example.com Mon Jan 15 \
-08:31:24 2001
-AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
-596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
-soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_comment_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_comment_pub
deleted file mode 100644
index 7b42ced93e..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_comment_pub
+++ /dev/null
@@ -1,9 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Comment: This is an example of a very very very very looooooooooooo\
-ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\
-commment
-x-command: /home/me/bin/lock-in-guest.sh
-AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
-YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
-5TT4SfsUu/iKy9lUcCfXzwre4WWZSXXcPff+EHtWshahu3WzBdnGxm5Xoi89zcE=
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_header_pub b/lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_header_pub
deleted file mode 100644
index 7b42ced93e..0000000000
--- a/lib/public_key/test/pubkey_ssh_SUITE_data/ssh_rsa_long_header_pub
+++ /dev/null
@@ -1,9 +0,0 @@
----- BEGIN SSH2 PUBLIC KEY ----
-Comment: This is an example of a very very very very looooooooooooo\
-ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\
-commment
-x-command: /home/me/bin/lock-in-guest.sh
-AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
-YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
-5TT4SfsUu/iKy9lUcCfXzwre4WWZSXXcPff+EHtWshahu3WzBdnGxm5Xoi89zcE=
----- END SSH2 PUBLIC KEY ----
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 80c76827c6..1a779e03bd 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,6 +59,7 @@
eddsa_priv_pkcs8/1,
eddsa_priv_rfc5958/0,
eddsa_priv_rfc5958/1,
+ eddsa_sign_verify_24_compat/1,
init_ec_pem_encode_generated/1,
ec_pem_encode_generated/0,
ec_pem_encode_generated/1,
@@ -88,6 +89,8 @@
pkix_countryname/1,
pkix_emailaddress/0,
pkix_emailaddress/1,
+ pkix_decode_cert/0,
+ pkix_decode_cert/1,
pkix_path_validation/0,
pkix_path_validation/1,
pkix_path_validation_root_expired/0,
@@ -96,6 +99,8 @@
pkix_verify_hostname_subjAltName/1,
pkix_verify_hostname_options/1,
pkix_verify_hostname_subjAltName_IP/1,
+ pkix_dist_point_uri/0,
+ pkix_dist_point_uri/1,
pkix_iso_rsa_oid/0,
pkix_iso_rsa_oid/1,
pkix_iso_dsa_oid/0,
@@ -119,9 +124,13 @@
gen_ec_param_prime_field/0,
gen_ec_param_prime_field/1,
gen_ec_param_char_2_field/0,
- gen_ec_param_char_2_field/1
+ gen_ec_param_char_2_field/1,
+ cacerts_load/0, cacerts_load/1
]).
+-export([list_cacerts/0]). % debug exports
+
+
-define(TIMEOUT, 120000). % 2 min
-define(PASSWORD1, "1234abcd").
-define(PASSWORD2, "4567efgh").
@@ -142,6 +151,7 @@ all() ->
pkix,
pkix_countryname,
pkix_emailaddress,
+ pkix_decode_cert,
pkix_path_validation,
pkix_path_validation_root_expired,
pkix_iso_rsa_oid,
@@ -154,10 +164,12 @@ all() ->
pkix_verify_hostname_subjAltName,
pkix_verify_hostname_subjAltName_IP,
pkix_verify_hostname_options,
+ pkix_dist_point_uri,
pkix_test_data_all_default,
pkix_test_data,
short_cert_issuer_hash,
- short_crl_issuer_hash
+ short_crl_issuer_hash,
+ cacerts_load
].
groups() ->
@@ -168,7 +180,8 @@ groups() ->
eddsa_priv_pkcs8, eddsa_priv_rfc5958,
ec_pem_encode_generated, gen_ec_param_prime_field,
gen_ec_param_char_2_field]},
- {sign_verify, [], [rsa_sign_verify, rsa_pss_sign_verify, dsa_sign_verify]}
+ {sign_verify, [], [rsa_sign_verify, rsa_pss_sign_verify, dsa_sign_verify,
+ eddsa_sign_verify_24_compat]}
].
%%-------------------------------------------------------------------
init_per_suite(Config) ->
@@ -219,6 +232,15 @@ init_per_testcase(rsa_pss_sign_verify, Config) ->
false ->
{skip, not_supported_by_crypto}
end;
+
+init_per_testcase(eddsa_sign_verify_24_compat, Config) ->
+ case lists:member(eddsa, crypto:supports(public_keys)) of
+ true ->
+ Config;
+ false ->
+ {skip, eddsa_not_supported_by_crypto}
+ end;
+
init_per_testcase(TestCase, Config) ->
case TestCase of
ec_pem_encode_generated ->
@@ -435,6 +457,61 @@ eddsa_priv_rfc5958(Config) when is_list(Config) ->
ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem),
ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([PrivEntry0])).
+eddsa_sign_verify_24_compat(_Config) ->
+ Key =
+ {'ECPrivateKey',1,
+ <<15,192,10,239,169,93,9,105,143,13,221,71,191,255,201,
+ 60,8,80,43,234,82,68,151,219,233,144,174,41,227,241,
+ 229,232>>,
+ {namedCurve,{1,3,101,112}},
+ <<209,208,142,135,125,251,57,203,2,49,232,74,238,214,170,
+ 181,23,107,221,39,187,225,106,19,34,133,117,198,138,
+ 180,16,70>>,
+ asn1_NOVALUE},
+ Body =
+ <<83,83,72,83,73,71,0,0,0,4,116,101,120,116,0,0,0,0,0,0,0,6,115,104,97,
+ 53,49,50,0,0,0,64,119,199,206,154,93,134,187,56,109,68,59,185,99,144,
+ 250,161,32,99,49,88,105,156,136,68,195,11,19,171,11,249,39,96,183,228,
+ 65,106,234,57,125,185,27,74,192,229,221,86,184,239,126,75,6,97,98,171,
+ 31,220,8,131,25,206,109,239,200,118>>,
+ ExpectedSignature =
+ <<203,148,171,54,165,4,216,251,189,124,35,227,88,183,187,225,142,10,132,163,98,
+ 48,167,195,67,12,49,148,85,146,41,14,58,0,198,68,103,114,90,61,31,38,200,198,
+ 64,179,135,138,31,172,236,105,0,71,50,195,168,247,216,110,210,61,159,5>>,
+ lists:foreach(
+ fun(Sha) ->
+ ct:log("Try Sha = ~p", [Sha]),
+ try
+ case public_key:sign(Body, Sha, Key) of
+ ExpectedSignature ->
+ ct:log("sign Sha ~p ok", [Sha]),
+ ExpectedSignature;
+ Others ->
+ ct:log("Sha: ~p~nGot: ~p~nExpect: ~p", [Sha,Others,ExpectedSignature]),
+ ct:fail("Bad sign result")
+ end
+ of
+ Sig ->
+ try
+ case public_key:verify(Body, Sha, Sig, Key) of
+ true ->
+ ct:log("verify Sha ~p ok", [Sha]);
+ false ->
+ ct:fail("Bad verify result for ~p",[Sha])
+ end
+ catch
+ C:E ->
+ ct:log("Verify: ~p:~p Sha = ~p", [C,E,Sha]),
+ ct:fail("Bad verify",[])
+ end
+ catch
+ C:E ->
+ ct:log("Sign: ~p:~p Sha = ~p", [C,E,Sha]),
+ ct:fail("Bad sign",[])
+ end
+ end, [undefined, none | crypto:supports(hashs)]).
+
+
init_ec_pem_encode_generated(Config) ->
case catch true = lists:member('secp384r1', crypto:ec_curves()) of
{'EXIT', _} -> {skip, {'secp384r1', not_supported}};
@@ -466,32 +543,46 @@ encrypted_pem_pwdfun(Config) when is_list(Config) ->
encrypted_pem(Config, Password1, Password2) ->
Datadir = proplists:get_value(data_dir, Config),
-
[{'RSAPrivateKey', DerRSAKey, not_encrypted}] =
erl_make_certs:pem_to_der(filename:join(Datadir, "client_key.pem")),
-
RSAKey = public_key:der_decode('RSAPrivateKey', DerRSAKey),
-
- Salt0 = crypto:strong_rand_bytes(8),
- Entry0 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey,
- {{"DES-EDE3-CBC", Salt0}, ?PASSWORD1}),
- RSAKey = public_key:pem_entry_decode(Entry0, Password1),
+ SupportedCiphers = crypto:supports(ciphers),
+ SupportedECB = lists:member(des_ecb, SupportedCiphers),
+ SupportedDES = lists:member(des_cbc, SupportedCiphers),
+ case SupportedECB of
+ true ->
+ encrypted_pem_des_ede(Datadir, RSAKey, Password1);
+ false ->
+ ct:comment("DES-EDE3-CBC not supported")
+ end,
+ case SupportedDES of
+ true ->
+ encrypted_pem_des_cbc(Datadir, RSAKey, Password2);
+ false ->
+ ct:comment("DES-CBC not supported")
+ end.
+encrypted_pem_des_ede(Datadir, RSAKey, Password) ->
+ Salt = crypto:strong_rand_bytes(8),
+ Entry = public_key:pem_entry_encode('RSAPrivateKey', RSAKey,
+ {{"DES-EDE3-CBC", Salt}, ?PASSWORD1}),
+ RSAKey = public_key:pem_entry_decode(Entry, Password),
Des3KeyFile = filename:join(Datadir, "des3_client_key.pem"),
- erl_make_certs:der_to_pem(Des3KeyFile, [Entry0]),
- [{'RSAPrivateKey', _, {"DES-EDE3-CBC", Salt0}}] =
- erl_make_certs:pem_to_der(Des3KeyFile),
-
- Salt1 = crypto:strong_rand_bytes(8),
- Entry1 = public_key:pem_entry_encode('RSAPrivateKey', RSAKey,
- {{"DES-CBC", Salt1}, ?PASSWORD2}),
+ erl_make_certs:der_to_pem(Des3KeyFile, [Entry]),
+ [{'RSAPrivateKey', _, {"DES-EDE3-CBC", Salt}}] =
+ erl_make_certs:pem_to_der(Des3KeyFile).
+
+encrypted_pem_des_cbc(Datadir, RSAKey, Password) ->
+ Salt = crypto:strong_rand_bytes(8),
+ Entry = public_key:pem_entry_encode('RSAPrivateKey', RSAKey,
+ {{"DES-CBC", Salt}, ?PASSWORD2}),
DesKeyFile = filename:join(Datadir, "des_client_key.pem"),
- erl_make_certs:der_to_pem(DesKeyFile, [Entry1]),
- [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} = Entry2] =
+ erl_make_certs:der_to_pem(DesKeyFile, [Entry]),
+ [{'RSAPrivateKey', _, {"DES-CBC", Salt}} = Entry] =
erl_make_certs:pem_to_der(DesKeyFile),
{ok, Pem} = file:read_file(DesKeyFile),
check_encapsulated_header(Pem),
- true = check_entry_type(public_key:pem_entry_decode(Entry2, Password2),
- 'RSAPrivateKey').
+ true = check_entry_type(public_key:pem_entry_decode(Entry, Password),
+ 'RSAPrivateKey').
%%--------------------------------------------------------------------
@@ -673,7 +764,7 @@ pkix(Config) when is_list(Config) ->
true = lists:member(IssuerId, CaIds),
- %% Should be normalized allready
+ %% Should be normalized already
TestStr = {rdnSequence,
[[{'AttributeTypeAndValue', {2,5,4,3},{printableString,"ERLANGCA"}}],
[{'AttributeTypeAndValue', {2,5,4,3},{printableString," erlang ca "}}]]},
@@ -707,6 +798,17 @@ pkix_emailaddress(Config) when is_list(Config) ->
check_emailaddress(Issuer),
check_emailaddress(Subj).
+
+%%--------------------------------------------------------------------
+pkix_decode_cert() ->
+ [{doc, "Test that extension IssuerDistributionPoint is not decoded in 'otp' decoding mode. We want to leave it for later "
+ "to increase interopability for sites that does not use this extension and will not care if it is properly encoded"}].
+pkix_decode_cert(Config) when is_list(Config) ->
+ Der = base64:decode(
+ <<"MIICXDCCAgKgAwIBAgIBATAKBggqhkjOPQQDAjApMRkwFwYDVQQFExBjOTY4NDI4OTMyNzUwOGRiMQwwCgYDVQQMDANURUUwHhcNMjIxMDI5MTczMTA3WhcNMjkwNDE2MjAzNDUzWjAfMR0wGwYDVQQDExRBbmRyb2lkIEtleXN0b3JlIEtleTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFmIQDus/jIZ0cPnRCITCzUUuCjQBw8MetO6154mmTL8O/fFlGgYkZ6C8jSSntKC/lMwaZHxAgW1AGgoCrPuX5ejggEjMIIBHzALBgNVHQ8EBAMCB4AwCAYDVR0fBAEAMIIBBAYKKwYBBAHWeQIBEQSB9TCB8gIBAgoBAQIBAwoBAQQgyvsSa116xqleaXs6xA84wqpAPWFgaaTjCWBnZpHslmoEADBEv4VFQAQ+MDwxFjAUBAxjb20ud2hhdHNhcHACBA0+oAQxIgQgOYfQQ9EK769ahxCzZxQY/lfg4ZtlPJ34JVj+tf/OXUQweqEFMQMCAQKiAwIBA6MEAgIBAKUIMQYCAQYCAQSqAwIBAb+DdwIFAL+FPQgCBgGEJMweob+FPgMCAQC/hUAqMCgEIFNB5rJkaXmnDldlMAeh8xAWlCHsm92fGlZI91reAFrxAQH/CgEAv4VBBQIDAV+Qv4VCBQIDAxUYMAoGCCqGSM49BAMCA0gAMEUCIF0BwvRQipVoaz5SIhsYbIeK+FHbAjWPgOxWgQ6Juq64AiEA83ZLsK37DjZ/tZNRi271VHQqIU8mdqUIMboVUiy3DaM=">>),
+
+ #'OTPCertificate'{} = public_key:pkix_decode_cert(Der, otp).
+
%%--------------------------------------------------------------------
pkix_path_validation() ->
[{doc, "Test PKIX path validation"}].
@@ -887,19 +989,19 @@ pkix_verify_hostname_subjAltName(Config) ->
true = public_key:pkix_verify_hostname(Cert, [{dns_id,"kb.example.org"}]),
true = public_key:pkix_verify_hostname(Cert, [{dns_id,"KB.EXAMPLE.ORG"}]),
- %% Check that a dns_id does not match a DNS subjAltName wiht wildcard
+ %% Check that a dns_id does not match a DNS subjAltName with wildcard
false = public_key:pkix_verify_hostname(Cert, [{dns_id,"other.example.org"}]),
- %% Check that a dns_id does match a DNS subjAltName wiht wildcard with matchfun
+ %% Check that a dns_id does match a DNS subjAltName with wildcard with matchfun
MatchFun = {match_fun, public_key:pkix_verify_hostname_match_fun(https)},
true = public_key:pkix_verify_hostname(Cert, [{dns_id,"other.example.org"}], [MatchFun]),
true = public_key:pkix_verify_hostname(Cert, [{dns_id,"OTHER.EXAMPLE.ORG"}], [MatchFun]),
- %% Check that a uri_id does not match a DNS subjAltName wiht wildcard
+ %% Check that a uri_id does not match a DNS subjAltName with wildcard
false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://other.example.org"}]),
false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://OTHER.EXAMPLE.ORG"}]),
- %% Check that a dns_id does match a DNS subjAltName wiht wildcard with matchfun
+ %% Check that a dns_id does match a DNS subjAltName with wildcard with matchfun
true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://other.example.org"}], [MatchFun]),
true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://OTHER.EXAMPLE.ORG"}], [MatchFun]),
true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://OTHER.example.org"}], [MatchFun]),
@@ -995,7 +1097,27 @@ pkix_verify_hostname_subjAltName_IP(Config) ->
true = public_key:pkix_verify_hostname(Cert, [{ip, {10,67,16,75}}]),
false = public_key:pkix_verify_hostname(Cert, [{ip, {1,2,3,4}}]),
false = public_key:pkix_verify_hostname(Cert, [{ip, {10,11,12,13}}]).
+
+
%%--------------------------------------------------------------------
+
+pkix_dist_point_uri() ->
+ [{doc, "Disregard ldap URIs in code path handling HTTP URIs"}].
+pkix_dist_point_uri(Config) when is_list(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ {ok, PemCert} = file:read_file(filename:join(Datadir, "ldap_uri_cert.pem")),
+ [{_, Cert, _}] = public_key:pem_decode(PemCert),
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
+
+ Extensions = pubkey_cert:extensions_list(TBSCert#'OTPTBSCertificate'.extensions),
+ DpExt = pubkey_cert:select_extension(?'id-ce-cRLDistributionPoints', Extensions),
+ #'Extension'{extnValue = DPs} = DpExt,
+ [#'DistributionPoint'{distributionPoint = {fullName, DPNames}}|_] = DPs,
+ ct:pal("~p", [DPNames]),
+ true = pubkey_crl:match_one(DPNames, [{uniformResourceIdentifier, "http://ca.eait.uq.edu.au/crl/labs-LILY-CA"}]).
+
+%%--------------------------------------------------------------------
+
pkix_iso_rsa_oid() ->
[{doc, "Test workaround for supporting certs that use ISO oids"
" 1.3.14.3.2.29 instead of PKIX/PKCS oid"}].
@@ -1217,6 +1339,105 @@ gen_ec_param_char_2_field(Config) when is_list(Config) ->
do_gen_ec_param(filename:join(Datadir, "ec_key_param1.pem")).
%%--------------------------------------------------------------------
+cacerts_load() ->
+ [{doc, "Basic tests of cacerts functionality"}].
+cacerts_load(Config) ->
+ Datadir = proplists:get_value(data_dir, Config),
+ {error, enoent} = public_key:cacerts_load("/dummy.file"),
+ %% Load default OS certs
+ %% there is no default installed OS certs on netbsd
+ %% can be installed with 'pkgin install mozilla-rootcerts'
+ IsNetBsd = element(2, os:type()) =:= netbsd,
+ OsCerts = try
+ Certs = public_key:cacerts_get(),
+ true = public_key:cacerts_clear(),
+ Certs
+ catch _:{badmatch, {error, enoent}} when IsNetBsd -> netbsd
+ end,
+
+ false = public_key:cacerts_clear(),
+
+ %% Reload from file
+ ok = public_key:cacerts_load(filename:join(Datadir, "cacerts.pem")),
+ [_TestCert1, _TestCert2] = public_key:cacerts_get(),
+
+ %% Re-Load default OS certs
+ try
+ process_flag(trap_exit, true),
+ flush(),
+ ok = public_key:cacerts_load(),
+ [] = flush(),
+ ct:log("~p: ~p~n", [os:type(), length(OsCerts)]),
+ OsCerts = public_key:cacerts_get(),
+ Ids = cert_info(OsCerts),
+ Check = fun(ShouldBeThere) ->
+ lists:any(fun(#{id:=Id}) -> lists:prefix(ShouldBeThere, Id) end, Ids)
+ end,
+ case lists:partition(Check, ["digicert", "globalsign"]) of
+ {_, []} -> ok;
+ {_, Fail} ->
+ cert_info(OsCerts),
+ [] = Fail
+ end,
+ ok
+ catch _:{badmatch, {error, enoent}} when IsNetBsd ->
+ ok
+ end.
+
+flush() ->
+ receive Msg -> [Msg|flush()]
+ after 500 -> []
+ end.
+
+cert_info([#cert{der=Der, otp=#'OTPCertificate'{tbsCertificate = C0}=Cert}|Rest]) when is_binary(Der) ->
+ #'OTPTBSCertificate'{subject = Subject, serialNumber = _Nr, issuer = Issuer0} = C0,
+ C = case public_key:pkix_is_self_signed(Cert) of
+ true -> #{id => subject(Subject), ss => true};
+ false ->
+ case public_key:pkix_issuer_id(Cert, other) of
+ {ok, {_IsNr, Issuer}} ->
+ #{id => subject(Subject), ss => false, issuer => subject(Issuer)};
+ {error, _} ->
+ #{id => subject(Subject), ss => false, issuer => subject(Issuer0)}
+ end
+ end,
+ [C|cert_info(Rest)];
+cert_info([]) ->
+ [].
+
+
+subject(S) ->
+ string:lowercase(subject(public_key:pkix_normalize_name(S), "unknown")).
+
+subject({rdnSequence, Seq}, Def) ->
+ subject(Seq, Def);
+subject([[{'AttributeTypeAndValue', ?'id-at-commonName', Name0}]|_], _Def) ->
+ case Name0 of
+ {printableString, Name} -> Name;
+ {utf8String, Name} -> unicode:characters_to_list(Name);
+ Name -> Name
+ end;
+subject([[{'AttributeTypeAndValue', ?'id-at-organizationName', Name0}]|Rest], _Def) ->
+ Name = case Name0 of
+ {printableString, Name1} -> Name1;
+ {utf8String, Name1} -> unicode:characters_to_list(Name1);
+ Name1 -> Name1
+ end,
+ subject(Rest, Name);
+subject([_|R], Def) ->
+ subject(R, Def);
+subject([], Def) ->
+ Def.
+
+list_cacerts() ->
+ Certs = public_key:cacerts_get(),
+ %% io:format("~P~n",[Certs, 20]),
+ IO = fun(C, N) -> io:format("~.3w:~0p~n", [N,C]), N+1 end,
+ lists:foldl(IO, 0, lists:sort(cert_info(Certs))),
+ ok.
+
+
+%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
asn1_encode_decode({Asn1Type, Der, not_encrypted} = Entry) ->
@@ -1323,7 +1544,8 @@ crypto_supported_curve(Curve, _Curves) ->
catch
_:_-> false
end.
-
+
+
incorrect_countryname_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>>.
@@ -1367,7 +1589,7 @@ hardcode_rsa_key(3) ->
exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
otherPrimeInfos = asn1_NOVALUE};
-hardcode_rsa_key(4) ->
+hardcode_rsa_key(4) ->
#'RSAPrivateKey'{
version ='two-prime',
modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
@@ -1388,4 +1610,3 @@ pss_params(sha256) ->
},
saltLength = 32,
trailerField = 1}.
-
diff --git a/lib/public_key/test/public_key_SUITE_data/ldap_uri_cert.pem b/lib/public_key/test/public_key_SUITE_data/ldap_uri_cert.pem
new file mode 100644
index 0000000000..2c6dbad9fa
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/ldap_uri_cert.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGIjCCBQqgAwIBAgITWwAAByiISJBWTJahTQAAAAAHKDANBgkqhkiG9w0BAQsF
+ADCBgDESMBAGCgmSJomT8ixkARkWAmF1MRMwEQYKCZImiZPyLGQBGRYDZWR1MRIw
+EAYKCZImiZPyLGQBGRYCdXExFDASBgoJkiaJk/IsZAEZFgRlYWl0MRQwEgYKCZIm
+iZPyLGQBGRYEbGFiczEVMBMGA1UEAwwMbGFicy1MSUxZLUNBMB4XDTIyMTAxMjIz
+MjgwNVoXDTIyMTEwOTIzMjgwNVowKTEnMCUGA1UEAxMeZ3M0MzItODEyNS5sYWJz
+LmVhaXQudXEuZWR1LmF1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+wuWgx3RlNrtapvbXc5RBroyCbXGu1Zefmq70PUiHrxHQIhmExjN4sdBd7Q5biKY4
+lr++4I49Z8FbOLw+MypmK0SG6BqYtrL+1Y/GMqAmeox6RbWVkIfLTJHqxdvmTjEX
+Kr9KbL7/5JOMSyDLv9ygqE5GS3IAjaDvwP6BeU3yJDkeSPotiCK2Pxm0Owo9g0a7
+C4UACCn2wzdo5g1xIeWoSejNC2ZMec8Ug1NWiuUq7FVw5+UzUkf4mqajndO6xJVi
+EGOaW59197iqj/vz3Rl58Gr7pKQHyE3TtZI8Jt+PrRuUD68JEnpR7ZX3HEERnczD
+2fejPM0v4AX725vuwCtkPQIDAQABo4IC6TCCAuUwHQYJKwYBBAGCNxQCBBAeDgBN
+AGEAYwBoAGkAbgBlMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAOBgNV
+HQ8BAf8EBAMCBaAwHQYDVR0OBBYEFNh+7KXQHE7Sxaze06Wna9IHRWIWMB8GA1Ud
+IwQYMBaAFOoq6NmbC3CwMRapHGF6uqpJiKzvMIIBAwYDVR0fBIH7MIH4MIH1oIHy
+oIHvhoHBbGRhcDovLy9DTj1sYWJzLUxJTFktQ0EsQ049bGlseSxDTj1DRFAsQ049
+UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJh
+dGlvbixEQz1sYWJzLERDPWVhaXQsREM9dXEsREM9ZWR1LERDPWF1P2NlcnRpZmlj
+YXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRp
+b25Qb2ludIYpaHR0cDovL2NhLmVhaXQudXEuZWR1LmF1L2NybC9sYWJzLUxJTFkt
+Q0Ewgc8GCCsGAQUFBwEBBIHCMIG/MIG8BggrBgEFBQcwAoaBr2xkYXA6Ly8vQ049
+bGFicy1MSUxZLUNBLENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxD
+Tj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWxhYnMsREM9ZWFpdCxEQz11
+cSxEQz1lZHUsREM9YXU/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNl
+cnRpZmljYXRpb25BdXRob3JpdHkwKQYDVR0RBCIwIIIeZ3M0MzItODEyNS5sYWJz
+LmVhaXQudXEuZWR1LmF1MFEGCSsGAQQBgjcZAgREMEKgQAYKKwYBBAGCNxkCAaAy
+BDBTLTEtNS0yMS0xOTc2MTAwMzA2LTE3MzE1MDIwOTctMzk0MjQwMTc2Ni0xMjMy
+MDcwDQYJKoZIhvcNAQELBQADggEBAMDVF3QK4Tgz2cu+UNbEnIQVDK9mx07kNDMO
+X0SUD8SNEP5LWhpLZoltInJ0s3ID8T7Rjf0bFw+eykp4/prVqENuDNj6lYxY/2ho
+WgJ7FKSqCNvkFzR2Bln20p6HFq8Jgz1R3uO3bVZ0RGUebUoT3PvF5t0d+xUg1Es9
+kYNxTRvNsFDvwpHg583R3bgO6Bqsi6ohTEW0/Xc3+d99dA+1F8So3DgXFnrb1wyT
+/D+xxIqq/BTAO771oxiujzlBYUewkjf2+JMQTc/mCJHHwCZxC4kgxqS9T2vuk2Hv
+CBsqnxGzixobGISmglAKAJvfckzWcF4iYwGPK9sSBkXSIAT5OOU=
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 9d4f2c4f6a..850e86ef69 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.12
+PUBLIC_KEY_VSN = 1.13.3
diff --git a/lib/reltool/Makefile b/lib/reltool/Makefile
index 94534ee2b7..50ac3b443e 100644
--- a/lib/reltool/Makefile
+++ b/lib/reltool/Makefile
@@ -37,5 +37,6 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=wx sasl
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index d469c8d9a9..346a80ef54 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -38,7 +38,21 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.9</title>
+ <section><title>Reltool 0.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that would cause analysis to crash.</p>
+ <p>
+ Own Id: OTP-18372 Aux Id: GH-6580 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.9</title>
<section><title>Improvements and New Features</title>
<list>
@@ -404,7 +418,7 @@
reltool config does not contain all applications that are
listed as <c>{applications,Applications}</c> in a
<c>.app</c> file, then these applications are
- autmatically added when creating the <c>.rel</c> file.
+ automatically added when creating the <c>.rel</c> file.
For 'included_applications', the behaviour was not the
same. I.e. if a <c>rel</c> spec in the reltool config did
not contain all applications that are listed as
@@ -508,7 +522,7 @@
<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
+ of dependencies column in app and mod window is changed
from "Modules used by others" to "Modules using this".
</item> </list>
<p>
@@ -668,7 +682,7 @@
<p>
Allow the same module name in multiple applications
visible to reltool, as long as all but one of the
- applications/modules are explicitely excluded. (Thanks to
+ applications/modules are explicitly excluded. (Thanks to
Andrew Gopienko and Jay Nelson)</p>
<p>
Own Id: OTP-9229</p>
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 136ec2ed69..49c5424969 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>2018</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -386,7 +386,7 @@
will be chosen.</p>
<p>Note that in order for reltool to sort application versions
and thereby be able to select the latest, it is required that
- the version id for the application consits of integers and
+ the version id for the application consists of integers and
dots only, for example <c>1</c>, <c>2.0</c> or
<c>3.17.1</c>.</p>
</item>
@@ -402,7 +402,7 @@
will be chosen.</p>
<p>Note that in order for reltool to sort application versions
and thereby be able to select the latest, it is required that
- the version id for the application consits of integers and
+ the version id for the application consists of integers and
dots only, for example <c>1</c>, <c>2.0</c> or
<c>3.17.1</c>.</p>
</item>
diff --git a/lib/reltool/doc/src/reltool_examples.xml b/lib/reltool/doc/src/reltool_examples.xml
index b77217dbf7..76db47a760 100644
--- a/lib/reltool/doc/src/reltool_examples.xml
+++ b/lib/reltool/doc/src/reltool_examples.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2021</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -432,16 +432,13 @@ Eshell V10.0 (abort with ^G)
[{copy_file,"makewhatis"},{copy_file,"format_man_pages"}]},
{create_dir,"usr",
[{create_dir,"lib",
- [{copy_file,"liberts.a"},
- {copy_file,"liberl_interface_st.a"},
- {copy_file,"liberts_r.a"},
+ [{copy_file,"liberl_interface_st.a"},
{copy_file,"libic.a"},
{copy_file,"liberl_interface.a"},
{copy_file,"libei_st.a"},
{copy_file,"libei.a"}]},
{create_dir,"include",
- [{copy_file,"erl_memory_trace_parser.h"},
- {copy_file,"driver_int.h"},
+ [{copy_file,"driver_int.h"},
{copy_file,"ei_connect.h"},
{copy_file,"ei.h"},
{copy_file,"erl_nif_api_funcs.h"},
@@ -476,8 +473,7 @@ Eshell V10.0 (abort with ^G)
{copy_file,"liberts_internal_r.a"},
{copy_file,"libethread.a"},
{copy_file,"README"}]},
- {copy_file,"liberts.a"},
- {copy_file,"liberts_r.a"}]},
+ ]},
{create_dir,"src",[{copy_file,"setuid_socket_wrap.c"}]},
{create_dir,"doc",[]},
{create_dir,"man",[]},
@@ -488,7 +484,6 @@ Eshell V10.0 (abort with ^G)
{copy_file,[...]},
{copy_file,...},
{...}|...]},
- {copy_file,"erl_memory_trace_parser.h"},
{copy_file,"driver_int.h"},
{copy_file,"erl_nif_api_funcs.h"},
{copy_file,"erl_fixed_size_int_types.h"},
diff --git a/lib/reltool/doc/src/reltool_usage.xml b/lib/reltool/doc/src/reltool_usage.xml
index 743d5fa366..c30684907a 100644
--- a/lib/reltool/doc/src/reltool_usage.xml
+++ b/lib/reltool/doc/src/reltool_usage.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2016</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -261,7 +261,7 @@
<p>Note that in order for reltool to sort application versions and
thereby be able to select the latest, it is required that the
- version id for the application consits of integers and dots only,
+ version id for the application consists of integers and dots only,
for example <c>1</c>, <c>2.0</c> or <c>3.17.1</c>.</p>
<p>By default the <c>Application inclusion policy</c> on system
diff --git a/lib/reltool/examples/Makefile b/lib/reltool/examples/Makefile
index cc29c88ba3..b2e424b91a 100644
--- a/lib/reltool/examples/Makefile
+++ b/lib/reltool/examples/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ EBIN = .
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES) *~
diff --git a/lib/reltool/src/Makefile b/lib/reltool/src/Makefile
index 4bddee4664..173a557d58 100644
--- a/lib/reltool/src/Makefile
+++ b/lib/reltool/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -65,8 +65,8 @@ ERL_COMPILE_FLAGS += +'{parse_transform,sys_pre_attributes}' \
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/reltool/src/reltool_app_win.erl b/lib/reltool/src/reltool_app_win.erl
index c84c1562ee..7d6e062463 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-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -98,6 +98,7 @@ open_mod(Pid, ModName) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Server
+-spec init(term(), term(), term(), term(), term()) -> no_return().
init(Parent, WxEnv, Xref, C, AppName) ->
try
do_init(Parent, WxEnv, Xref, C, AppName)
diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl
index 43e9d50b18..de7d73bf37 100644
--- a/lib/reltool/src/reltool_server.erl
+++ b/lib/reltool/src/reltool_server.erl
@@ -1012,7 +1012,7 @@ mod_recap_dependencies(S, A, [#mod{name = ModName}=M1 | Mods], Acc, IsIncl) ->
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
+ %% App is explicitly excluded so it is ok that the module
%% record does not exist for this module in this
%% application.
mod_recap_dependencies(S, A, Mods, [M1 | Acc], IsIncl);
diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl
index 773e752ad4..1a0f868be8 100644
--- a/lib/reltool/src/reltool_target.erl
+++ b/lib/reltool/src/reltool_target.erl
@@ -677,7 +677,7 @@ del_apps([], Apps) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Create the load path used in the generated script.
%% If PathFlag is true a script intended to be used as a complete
-%% system (e.g. in an embbeded system), i.e. all applications are
+%% system (e.g. in an embedded system), i.e. all applications are
%% located under $ROOT/lib.
%% Otherwise all paths are set according to dir per application.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/reltool/test/Makefile b/lib/reltool/test/Makefile
index 838e9a34f6..245c9c9f00 100644
--- a/lib/reltool/test/Makefile
+++ b/lib/reltool/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -51,6 +51,7 @@ RELSYSDIR = $(RELEASE_PATH)/reltool_test
# FLAGS
# ----------------------------------------------------
ERL_COMPILE_FLAGS += -pa $(ERL_TOP)/lib/reltool/ebin/
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -58,7 +59,7 @@ EBIN = .
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGET_FILES)
+tests $(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl
index c775aa1225..11ae6d6da2 100644
--- a/lib/reltool/test/reltool_server_SUITE.erl
+++ b/lib/reltool/test/reltool_server_SUITE.erl
@@ -2722,7 +2722,7 @@ os_cmd(Cmd) when is_list(Cmd) ->
[]->
{99, []};
Return->
- %% Find the position of the status code wich is last in the string
+ %% Find the position of the status code which is last in the string
%% prepended with #
case string:split(Return, "$#", trailing) of
[_] -> %% This happens only if the sh command pipe is somehow interrupted
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index 1bee6b4581..2fa512829c 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.9
+RELTOOL_VSN = 0.9.1
diff --git a/lib/runtime_tools/Makefile b/lib/runtime_tools/Makefile
index a76637dfeb..c85d81922b 100644
--- a/lib/runtime_tools/Makefile
+++ b/lib/runtime_tools/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2021. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,5 +37,6 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=mnesia
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c
index e7fd5968c1..37a8149777 100644
--- a/lib/runtime_tools/c_src/trace_file_drv.c
+++ b/lib/runtime_tools/c_src/trace_file_drv.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@
** 0 = binary, 1 = drop
** If Op is 1, then Size reflects the number of dropped messages. The
** op 1 is never used in this driver.
-** Size, a 32 bit interger in network byte order:
+** Size, a 32 bit integer in network byte order:
** Either the size of the binary term, or the number of packet's dropped.
** Term, an array of bytes:
** An erlang term in the external format or simply empty if Op == 1, the
diff --git a/lib/runtime_tools/c_src/trace_ip_drv.c b/lib/runtime_tools/c_src/trace_ip_drv.c
index 195558f958..c6f42b3b52 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-2016. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -68,7 +68,7 @@
** The number of messages to que up before dropping.
** Fl, ascii string representing a flag byte:
** 0x1 -> Drop oldest when que is full (instead of last arrived)
-** 0x2 -> Fill the que even if noone is listening.
+** 0x2 -> Fill the que even if no one is listening.
**
** The package sent over the network looks like this:
** +--+--------+-----------------------------------+
@@ -77,7 +77,7 @@
** Op, a char:
** 0 = binary, 1 = drop
** If Op is 1, then Size reflects the number of dropped messages.
-** Size, a 32 bit interger in network byte order:
+** Size, a 32 bit integer in network byte order:
** Either the size of the binary term, or the number of packet's dropped.
** Term, an array of bytes:
** An erlang term in the external format or simply empty if Op == 1, the
@@ -86,7 +86,7 @@
/*
** SO, most of the differences between WinDoze and Posixish OS'es
-** is handeled here, but the multiplexing (driver_select) is also quite
+** is handled here, but the multiplexing (driver_select) is also quite
** interesting, see my_driver_select further down in the file...
*/
@@ -677,7 +677,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...
+** The FLAG_DROP_OLDEST is currently ignored...
*/
static void enque_message(TraceIpData *data, char *buff, int bufflen,
int byteswritten)
diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml
index 7567d4ba43..00e1537176 100644
--- a/lib/runtime_tools/doc/src/LTTng.xml
+++ b/lib/runtime_tools/doc/src/LTTng.xml
@@ -521,7 +521,7 @@ Eshell V8.0 (abort with ^G)
<pre>1> <input>l(dyntrace).</input>
{module,dyntrace}</pre>
- <p>All tracepoints via dyntrace are now visibile and can be listed through <c>lttng list -u</c>.</p>
+ <p>All tracepoints via dyntrace are now visible and can be listed through <c>lttng list -u</c>.</p>
<p>Enable the process_register LTTng tracepoint for Erlang.</p>
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
index 7532ec692d..ba7641ffa9 100644
--- a/lib/runtime_tools/doc/src/dbg.xml
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1156,20 +1156,12 @@ hello</pre>
</func>
<func>
<name since="">stop() -> ok</name>
- <fsummary>Stop the <c>dbg</c>server and the tracing of all processes.</fsummary>
- <desc>
- <p>Stops the <c>dbg</c> server and clears all trace flags for
- all processes and all local trace patterns for all functions. Also
- shuts down all trace clients and closes all trace ports.</p>
- <p>Note that no global trace patterns are affected by this
- function.</p>
- </desc>
- </func>
- <func>
- <name since="">stop_clear() -> ok</name>
<fsummary>Stop the <c>dbg</c>server and the tracing of all processes, and clears trace patterns.</fsummary>
<desc>
- <p>Same as stop/0, but also clears all trace patterns on global functions calls.</p>
+ <p>Stops the <c>dbg</c> server, clears all trace flags for
+ all processes, clears all trace patterns for all functions,
+ clears trace patterns for send/receive, shuts down all trace clients,
+ and closes all trace ports.</p>
</desc>
</func>
</funcs>
diff --git a/lib/runtime_tools/doc/src/dyntrace.xml b/lib/runtime_tools/doc/src/dyntrace.xml
index d3b348e850..5971740b87 100644
--- a/lib/runtime_tools/doc/src/dyntrace.xml
+++ b/lib/runtime_tools/doc/src/dyntrace.xml
@@ -171,7 +171,7 @@
<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 <seeerl marker="kernel:file">file</seeerl> 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 <seeerl marker="kernel:file">file</seeerl> module already spread's tags, so there is no 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 <seeerl marker="stdlib:io">io</seeerl> module to communicate with an I/O-server for a regular file, like in the following example:</p>
<pre>
f() ->
diff --git a/lib/runtime_tools/doc/src/erts_alloc_config.xml b/lib/runtime_tools/doc/src/erts_alloc_config.xml
index fb5d08be9d..af41d64881 100644
--- a/lib/runtime_tools/doc/src/erts_alloc_config.xml
+++ b/lib/runtime_tools/doc/src/erts_alloc_config.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2021</year>
+ <year>2007</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,11 +32,11 @@
<module since="">erts_alloc_config</module>
<modulesummary>Configuration tool for erts_alloc</modulesummary>
<description>
- <note>
- <p><c>erts_alloc_config</c> is currently an experimental
- tool and might be subject to backward incompatible
- changes.</p>
- </note>
+ <warning>
+ <p>This (experimental) tool no longer produces good configurations and
+ cannot be fixed in a reasonably backwards compatible manner. It has
+ therefore been scheduled for removal in <c>OTP 26.0</c>.</p>
+ </warning>
<p><seecref marker="erts:erts_alloc">erts_alloc(3)</seecref> is an
Erlang Run-Time System internal memory allocator library.
<c>erts_alloc_config</c> is intended to be used to aid creation
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 03e6a9af8c..56c77be0a4 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -32,6 +32,43 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.19</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Reading port socket options on macOS and Windows "skips"
+ invalid options.</p>
+ <p>
+ Own Id: OTP-18012 Aux Id: #5798 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p><c>dbg:stop/0</c> now behaves like
+ <c>dbg:stop_clear/0</c>, clearing all global trace
+ patterns for all functions.</p>
+ <p>
+ Own Id: OTP-17909 Aux Id: ERIERL-760 </p>
+ </item>
+ <item>
+ <p><c>erts_alloc_config</c> has been scheduled for
+ removal in OTP 26. It has not produced good
+ configurations for a very long time, and unfortunately it
+ cannot be fixed in a backwards compatible manner.</p>
+ <p>
+ Own Id: OTP-17939</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.18</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/runtime_tools/doc/src/system_information.xml b/lib/runtime_tools/doc/src/system_information.xml
index f52f461ddb..b8ccc73418 100644
--- a/lib/runtime_tools/doc/src/system_information.xml
+++ b/lib/runtime_tools/doc/src/system_information.xml
@@ -74,7 +74,7 @@
versions</seeguide> of the same application installed in the
system, but you do not use a
<seeguide marker="system/system_principles:system_principles#BOOTSCRIPT">boot
- script</seeguide> identifing the correct application version.</p>
+ script</seeguide> identifying the correct application version.</p>
</item>
</taglist>
<p>Currently the sanity check is limited to verifying
diff --git a/lib/runtime_tools/src/Makefile b/lib/runtime_tools/src/Makefile
index 76286c5499..8e8c4074f5 100644
--- a/lib/runtime_tools/src/Makefile
+++ b/lib/runtime_tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2018. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -79,7 +79,7 @@ ERL_COMPILE_FLAGS += \
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/runtime_tools/src/appmon_info.erl b/lib/runtime_tools/src/appmon_info.erl
index ebff52664d..ad08a6c66f 100644
--- a/lib/runtime_tools/src/appmon_info.erl
+++ b/lib/runtime_tools/src/appmon_info.erl
@@ -40,11 +40,11 @@
%% have a nice public interface function which should handle task
%% administration. Tasks are identified by a "key" consisting of
%% three items, the requesting pid, the name of the task and the
-%% task auxillary parameter. The requesting pid is the pid of the
+%% task auxiliary parameter. The requesting pid is the pid of the
%% callee (in the appmon case it can be the node window for
%% instance), the task name is whatever name the task is given
%% (in the appmon case it can be app, app_ctrl or load). The task
-%% name can be seen as the type of the task. The task auxillary
+%% name can be seen as the type of the task. The task auxiliary
%% parameter is an all purpose parameter that have a different
%% meaning for each type of task so in appmon the Aux for app
%% contains the root pid of the monitored application and in
@@ -136,7 +136,7 @@
%%----------------------------------------------------------------------
%% Public interface
%%
-%% The Aux parameter is an auxillary parameter that can be used
+%% The Aux parameter is an auxiliary parameter that can be used
%% freely by the requesting process, it is included in the work
%% task key. appmon uses it for storing the node name when
%% requesting load and app_ctrl tasks, and appmon_a uses it for
@@ -149,7 +149,7 @@
%% Do not use gen_server:start_link because we do not want the
%% appmon_info to die when initiating process dies unless special
%% conditions apply.
-%% Uhu, we don't??? Made a fix so that this proces DOES indeed die
+%% Uhu, we don't??? Made a fix so that this process DOES indeed die
%% if it's starter dies. /Gunilla
start_link(Node, Client, Opts) ->
rpc:call(Node, ?MODULE, start_link2, [self(), Client, Opts]).
@@ -473,7 +473,7 @@ get_pid(X) when is_tuple(X) -> element(2, X).
%----------------------------------------------------------------------
%%---------------------------------------------------------------------
-%% Handling process trees of processses that are linked to each other
+%% Handling process trees of processes that are linked to each other
do_find_proc(Mode, DB, GL, Avoid) ->
case get_next(DB) of
diff --git a/lib/runtime_tools/src/dbg.erl b/lib/runtime_tools/src/dbg.erl
index 7dd3c452e5..d5be9ac6a9 100644
--- a/lib/runtime_tools/src/dbg.erl
+++ b/lib/runtime_tools/src/dbg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -595,17 +595,23 @@ c(Parent, M, F, A, Flags) ->
Parent ! {self(), Res}.
stop() ->
+ {ok, _} = ctp(),
+ {ok, _} = ctpe('receive'),
+ {ok, _} = ctpe('send'),
+
Mref = erlang:monitor(process, dbg),
catch dbg ! {self(),stop},
+
receive
- {'DOWN',Mref,_,_,_} ->
- ok
+ {'DOWN',Mref,_,_,_} -> ok
end.
+%% This is a vestigial function that used to be documented as a variant of
+%% `stop/0` that also clears global function traces. Since `stop/0` now clears
+%% all tracing as the user would expect it to, we've removed this from the
+%% documentation but keep it around for backwards compatibility, much like
+%% `queue:lait`.
stop_clear() ->
- {ok, _} = ctp(),
- {ok, _} = ctpe('receive'),
- {ok, _} = ctpe('send'),
stop().
%%% Calling the server.
diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl
index 5fe62a46f6..d0861669e7 100644
--- a/lib/runtime_tools/src/dyntrace.erl
+++ b/lib/runtime_tools/src/dyntrace.erl
@@ -62,6 +62,18 @@
enabled/3]).
-export([user_trace_i4s4/9]). % Know what you're doing!
+
+-nifs([available/0, user_trace_s1/1, user_trace_i4s4/9, user_trace_n/10,
+
+ trace_procs/5, trace_ports/5, trace_running_procs/5,
+ trace_running_ports/5, trace_call/5, trace_send/5,
+ trace_receive/5, trace_garbage_collection/5, enabled_procs/3,
+ enabled_ports/3, enabled_running_procs/3, enabled_running_ports/3,
+ enabled_call/3, enabled_send/3, enabled_receive/3,
+ enabled_garbage_collection/3,
+
+ enabled/3, trace/5]).
+
-compile(no_native).
-on_load(on_load/0).
diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl
index ed36fe0589..18587b0475 100644
--- a/lib/runtime_tools/src/erts_alloc_config.erl
+++ b/lib/runtime_tools/src/erts_alloc_config.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,9 @@
-module(erts_alloc_config).
+-deprecated({'_','_', "this module will be removed in OTP 26.0. See the "
+ "documentation for details"}).
+
-record(state, {have_scenario = false,
alloc}).
@@ -265,13 +268,13 @@ strategy_str(aoff) ->
strategy_str(aoffcbf) ->
"Address order first fit carrier best fit";
strategy_str(aoffcaobf) ->
- "Address order first fit carrier adress order best fit";
+ "Address order first fit carrier address order best fit";
strategy_str(ageffcaoff) ->
"Age order first fit carrier address order first fit";
strategy_str(ageffcbf) ->
"Age order first fit carrier best fit";
strategy_str(ageffcaobf) ->
- "Age order first fit carrier adress order best fit".
+ "Age order first fit carrier address order best fit".
default_acul(A, S) ->
case carrier_migration_support(S) of
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index ecbba3d0d8..ccd2240a99 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ vsn() ->
socket_info() ->
Info0 = socket:info(),
{Counters, Info1} = maps:take(counters, Info0),
- IovMax = maps:get(iov_max , Info1),
+ IovMax = maps:get(iov_max, Info1),
NumMons = socket:number_of_monitors(),
[{iov_max, IovMax}, {num_monitors, NumMons} | maps:to_list(Counters)].
@@ -205,22 +205,53 @@ inet_port_extra({_,Type},Port) when Type =:= "udp_inet";
[{local_address,LAddr}];
{error, _} -> []
end ++
- case inet:getopts(Port,
- [active, broadcast, buffer, bind_to_device,
- delay_send, deliver, dontroute, exit_on_close,
- header, high_msgq_watermark, high_watermark,
- ipv6_v6only, keepalive, linger, low_msgq_watermark,
- low_watermark, mode, netns, nodelay, packet,
- packet_size, priority, read_packets, recbuf,
- reuseaddr, send_timeout, send_timeout_close,
- show_econnreset, sndbuf, tos, tclass]) of
- {ok, Opts} -> [{options, Opts}];
- {error, _} -> []
- end,
+ [{options, get_sock_opts(Port)}],
[{inet,Data}];
inet_port_extra(_,_) ->
[].
+sock_opts() ->
+ [active, broadcast, buffer, bind_to_device,
+ delay_send, deliver, dontroute, exit_on_close,
+ header, high_msgq_watermark, high_watermark,
+ ipv6_v6only, keepalive, linger, low_msgq_watermark,
+ low_watermark, mode, netns, nodelay, packet,
+ packet_size, priority, read_packets, recbuf,
+ reuseaddr, send_timeout, send_timeout_close,
+ show_econnreset, sndbuf, tos, tclass].
+
+get_sock_opts(Port) ->
+ get_sock_opts(Port, sock_opts()).
+
+get_sock_opts(Port, Opts) ->
+ get_sock_opts(Port, Opts, []).
+
+%% The reason we are doing it this way, is because if there
+%% is an issue with one of the options, we should just skip
+%% that option and continue with the next.
+%% Better to have some options then none.
+get_sock_opts(_Port, [], Acc) ->
+ lists:reverse(Acc);
+get_sock_opts(Port, [Opt|Opts], Acc) ->
+ case inet:getopts(Port, [Opt]) of
+ {ok, [Res]} ->
+ get_sock_opts(Port, Opts, [Res|Acc]);
+ {ok, []} -> % No value?
+ Res = {Opt, "-"},
+ get_sock_opts(Port, Opts, [Res|Acc]);
+ {error, einval} ->
+ Res = {Opt, "Not Supported"},
+ get_sock_opts(Port, Opts, [Res|Acc]);
+
+ %% If the option is "invalid", the reason would be 'einval',
+ %% so this error must be something else.
+ %% But if the option just vanish, we don't know what is
+ %% going on. So, do something similar to socket (see below).
+ {error, Reason} ->
+ Res = {Opt, f("error:~p", [Reason])},
+ get_sock_opts(Port, Opts, [Res|Acc])
+ end.
+
get_socket_list() ->
GetOpt = fun(_Sock, {Opt, false}) ->
diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl
index 9bbb87dfb4..507071fa2f 100644
--- a/lib/runtime_tools/src/system_information.erl
+++ b/lib/runtime_tools/src/system_information.erl
@@ -387,7 +387,6 @@ os_getenv_erts_specific() ->
os_getenv_erts_specific([
"BINDIR",
"DIALYZER_EMULATOR",
- "CERL_DETACHED_PROG",
"EMU",
"ERL_CONSOLE_MODE",
"ERL_CRASH_DUMP",
@@ -849,7 +848,7 @@ get_apps([Path|Paths], Apps) ->
[AppFile] ->
get_apps(Paths, [app_file_to_app(AppFile) | Apps]);
[_AppFile| _] = AppFiles ->
- %% Strange with multple .app files... Lets put them
+ %% Strange with multiple .app files... Lets put them
%% all in the list and see what we get...
lists:map(fun (AF) ->
app_file_to_app(AF)
diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile
index e5a087f3ad..c9578d376e 100644
--- a/lib/runtime_tools/test/Makefile
+++ b/lib/runtime_tools/test/Makefile
@@ -31,6 +31,7 @@ RELSYSDIR = $(RELEASE_PATH)/runtime_tools_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += -Werror
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -42,7 +43,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
@@ -65,5 +66,6 @@ release_tests_spec: make_emakefile
$(INSTALL_DATA) $(EMAKEFILE) runtime_tools.cover "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ $(INSTALL_DATA) $(ERL_TOP)/make/otp_version_tickets "$(RELSYSDIR)/system_information_SUITE_data"
release_docs_spec:
diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl
index 44e9b7d00d..209af7be19 100644
--- a/lib/runtime_tools/test/dbg_SUITE.erl
+++ b/lib/runtime_tools/test/dbg_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -161,9 +161,9 @@ message(Config) when is_list(Config) ->
send(Config) when is_list(Config) ->
{ok, _} = start(),
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
rpc:call(Node, code, add_patha,
- [filename:join(proplists:get_value(data_dir, Config), "..")]),
+ [filename:dirname(proplists:get_value(data_dir, Config))]),
try
Echo = fun F() ->
receive {From, M} ->
@@ -172,7 +172,7 @@ send(Config) when is_list(Config) ->
end
end,
Rcvr = spawn_link(Echo),
- RemoteRcvr = spawn_link(Node, Echo),
+ RemoteRcvr = spawn(Node, Echo),
{ok, [{matched, _, 1}]} = dbg:p(Rcvr, send),
@@ -222,7 +222,7 @@ send(Config) when is_list(Config) ->
%% Test that distributed dbg works
dbg:tracer(Node, process, {fun myhandler/2, self()}),
Rcvr2 = spawn_link(Echo),
- RemoteRcvr2 = spawn_link(Node, Echo),
+ RemoteRcvr2 = spawn(Node, Echo),
dbg:p(Rcvr2, [send]),
dbg:p(RemoteRcvr2, [send]),
dbg:tpe(send, [{['_', hej],[],[]}]),
@@ -235,7 +235,8 @@ send(Config) when is_list(Config) ->
ok
after
- dbg:stop_clear()
+ dbg:stop_clear(),
+ peer:stop(Peer)
end.
send_test(Pid, Pattern, Msg, TraceEvent) ->
@@ -270,7 +271,7 @@ send_test_rcv(Pid, Msg, S, TraceEvent) ->
recv(Config) when is_list(Config) ->
{ok, _} = start(),
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
rpc:call(Node, code, add_patha,
[filename:join(proplists:get_value(data_dir, Config), "..")]),
try
@@ -281,7 +282,7 @@ recv(Config) when is_list(Config) ->
end
end,
Rcvr = spawn_link(Echo),
- RemoteRcvr = spawn_link(Node, Echo),
+ RemoteRcvr = spawn(Node, Echo),
{ok, [{matched, _, 1}]} = dbg:p(Rcvr, 'receive'),
@@ -333,7 +334,7 @@ recv(Config) when is_list(Config) ->
%% Test that distributed dbg works
dbg:tracer(Node, process, {fun myhandler/2, self()}),
Rcvr2 = spawn_link(Echo),
- RemoteRcvr2 = spawn_link(Node, Echo),
+ RemoteRcvr2 = spawn(Node, Echo),
dbg:p(Rcvr2, ['receive']),
dbg:p(RemoteRcvr2, ['receive']),
dbg:tpe('receive', [{[node(), '_', '$1'],[{'==',{element,2,'$1'}, hej}],[]}]),
@@ -346,7 +347,8 @@ recv(Config) when is_list(Config) ->
ok
after
- dbg:stop_clear()
+ dbg:stop_clear(),
+ peer:stop(Peer)
end.
recv_test(Pid, Pattern, Msg, TraceEvent) ->
@@ -382,7 +384,7 @@ recv_test_rcv(Pid, Msg, TraceEvent) ->
%% Simple test of distributed tracing
distributed(Config) when is_list(Config) ->
{ok, _} = start(),
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
try
RexPid = rpc:call(Node, erlang, whereis, [rex]),
RexPidList = pid_to_list(RexPid),
@@ -411,7 +413,7 @@ distributed(Config) when is_list(Config) ->
stop()
after
dbg:stop_clear(),
- stop_slave(Node)
+ peer:stop(Peer)
end,
ok.
@@ -870,7 +872,7 @@ distributed_erl_tracer(Config) ->
ok = load_nif(Config),
LNode = node(),
- RNode = start_slave(),
+ {ok, Peer, RNode} = ?CT_PEER(),
true = rpc:call(RNode, code, add_patha, [filename:join(proplists:get_value(data_dir, Config), "..")]),
ok = rpc:call(RNode, ?MODULE, load_nif, [Config]),
@@ -899,7 +901,7 @@ distributed_erl_tracer(Config) ->
RCall = spawn_link(RNode, fun() -> ?MODULE:dummy() end),
[{RCall, call, RNifProxy, RCall, {?MODULE, dummy, []}, #{}}] = flush(),
-
+ peer:stop(Peer),
ok.
load_nif(Config) ->
@@ -922,29 +924,6 @@ trace(_, _, _, _, _) ->
%% Support functions
%%
-start_slave() ->
- Name = "asdkxlkmd" ++ integer_to_list(erlang:unique_integer([positive])),
- {ok, Node} = test_server:start_node(Name,slave,[]),
- ok = wait_node(Node, 15),
- Node.
-
-stop_slave(Node) ->
- test_server:stop_node(Node).
-
-wait_node(_,0) ->
- no;
-wait_node(Node, N) ->
- case net_adm:ping(Node) of
- pong ->
- ok;
- pang ->
- receive
- after 1000 ->
- ok
- end,
- wait_node(Node, N - 1)
- end.
-
myhandler(Message, {wait_for_go,Pid}) ->
receive
{go,Pid} ->
diff --git a/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl
index 68ece5936e..3e7c39f8ab 100644
--- a/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl
+++ b/lib/runtime_tools/test/dbg_SUITE_data/dbg_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,10 +23,10 @@
%%% This module implements a priority queue as defined in
%%% "Priority Queues and the STL" by Mark Nelson in Dr.Dobb's Journal, Jan 1996
%%% see http://web2.airmail.net/markn/articles/pq_stl/priority.htm for more
-%%% information. (A heap implementation is planned aswell)
+%%% information. (A heap implementation is planned as well)
%%%----------------------------------------------------------------------
%%% The items of the queue is kept priority sorted, and because of that,
-%%% a push() operation costs more than a pop() operation (wich only
+%%% a push() operation costs more than a pop() operation (which only
%%% needs to return the top item of the queue(read: list)).
%%%----------------------------------------------------------------------
%%% The priority queue can be deceptively nice to use when creating for
diff --git a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
index ed24cce0bf..10a9560b73 100644
--- a/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
+++ b/lib/runtime_tools/test/erts_alloc_config_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -76,9 +76,9 @@ basic(Config) when is_list(Config) ->
os:putenv("ERL_ZFLAGS", ZFlgs ++ SbctMod),
- {ok, Node1} = start_node(Config),
+ {ok, Peer1, Node1} = ?CT_PEER(),
ok = rpc:call(Node1, ?MODULE, make_basic_config, [ErtsAllocConfig]),
- stop_node(Node1),
+ peer:stop(Peer1),
display_file(ErtsAllocConfig),
@@ -90,13 +90,12 @@ basic(Config) when is_list(Config) ->
os:putenv("ERL_ZFLAGS", ZFlgs),
- {ok, Node2} = start_node(Config,
- "-args_file " ++ ErtsAllocConfig
- ++ " -args_file " ++ ManualConfig),
+ {ok, Peer2, Node2} = ?CT_PEER(["-args_file", ErtsAllocConfig,
+ "-args_file", ManualConfig]),
{_, _, _, Cfg} = rpc:call(Node2, erlang, system_info, [allocator]),
- stop_node(Node2),
+ peer:stop(Peer2),
{value,{binary_alloc, BCfg}} = lists:keysearch(binary_alloc, 1, Cfg),
{value,{sbct, 2097152}} = lists:keysearch(sbct, 1, BCfg),
@@ -160,26 +159,6 @@ display_file(FileName) ->
io:format("eof: ~s~n", [FileName]),
ok.
-mk_name(Config) when is_list(Config) ->
- {A, B, C} = erlang:timestamp(),
- list_to_atom(atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ "-" ++ integer_to_list(A)
- ++ "-" ++ integer_to_list(B)
- ++ "-" ++ integer_to_list(C)).
-
-start_node(Config) ->
- start_node(Config, "").
-
-start_node(Config, Args) ->
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(mk_name(Config),
- slave,
- [{args, "-pa " ++ Pa ++ " " ++ Args}]).
-
-stop_node(Node) ->
- true = test_server:stop_node(Node).
-
privfile(Name, Config) ->
filename:join([proplists:get_value(priv_dir, Config),
atom_to_list(proplists:get_value(testcase, Config)) ++ "." ++ Name]).
diff --git a/lib/runtime_tools/test/system_information_SUITE.erl b/lib/runtime_tools/test/system_information_SUITE.erl
index a5a025a1cf..b8a8ca9a39 100644
--- a/lib/runtime_tools/test/system_information_SUITE.erl
+++ b/lib/runtime_tools/test/system_information_SUITE.erl
@@ -182,6 +182,19 @@ end_per_group(_GroupName, _Config) ->
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
+init_per_testcase(sanity_check, Config) ->
+ %% We check if the test results were released using a version
+ %% of Erlang/OTP that was a tagged version or not. On a non-tagged
+ %% version this testcase most likely will fail.
+ case file:read_file(
+ filename:join(
+ proplists:get_value(data_dir,Config), "otp_version_tickets")) of
+ {ok,<<"DEVELOPMENT",_/binary>>} ->
+ {skip, "This is a development version, test might fail "
+ "because of incorrect version numbers"};
+ {ok,_S} ->
+ Config
+ end;
init_per_testcase(_TestCase, Config) ->
Config.
diff --git a/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat b/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat
index 94120c0dc7..3c8f582086 100644
--- a/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat
+++ b/lib/runtime_tools/test/system_information_SUITE_data/information_test_report.dat
@@ -9729,7 +9729,6 @@
[{"BINDIR",
"/ldisk/daily_build/r16b02_opu_c_Muacul100.2013-07-10_20/otp/erts-5.10.3/bin"},
{"DIALYZER_EMULATOR",false},
- {"CERL_DETACHED_PROG",false},
{"EMU","beam"},
{"ERL_CONSOLE_MODE",false},
{"ERL_CRASH_DUMP",false},
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 3e7545b8c5..15ef680b67 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.18
+RUNTIME_TOOLS_VSN = 1.19
diff --git a/lib/sasl/Makefile b/lib/sasl/Makefile
index 4f32f0ec0c..4b04c1aee4 100644
--- a/lib/sasl/Makefile
+++ b/lib/sasl/Makefile
@@ -37,5 +37,6 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=tools
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index f9162b67e7..78de4f2f39 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -31,6 +31,40 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix systools:make* to recursively search for source code
+ when doing a <c>src_tests</c>.</p>
+ <p>
+ Own Id: OTP-17752 Aux Id: PR-5302 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ An Erlang installation directory is now relocatable on
+ the file system given that the paths in the
+ installation's <c>RELEASES</c> file are paths that are
+ relative to the installations root directory. The
+ <c>`release_handler:create_RELEASES/4</c> function can
+ generate a <c>RELEASES</c> file with relative paths if
+ its <c>RootDir</c> parameter is set to the empty string.</p>
+ <p>
+ Own Id: OTP-17304</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 4.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/sasl/doc/src/release_handler.xml b/lib/sasl/doc/src/release_handler.xml
index 55ec4cdb0f..f5eb0ccbd1 100644
--- a/lib/sasl/doc/src/release_handler.xml
+++ b/lib/sasl/doc/src/release_handler.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -202,6 +202,7 @@
</func>
<func>
+ <name since="OTP 25.0">create_RELEASES(RelDir, RelFile, AppDirs) -> ok | {error, Reason}</name>
<name since="">create_RELEASES(Root, RelDir, RelFile, AppDirs) -> ok | {error, Reason}</name>
<fsummary>Creates an initial <c>RELEASES</c> file.</fsummary>
<type>
@@ -215,12 +216,19 @@
<p>Creates an initial <c>RELEASES</c> file to be used by the
release handler. This file must exist to install new
releases.</p>
- <p><c>Root</c> is the root of the installation (<c>$ROOT</c>) as
- described earlier. <c>RelDir</c> is the directory where
- the <c>RELEASES</c> file is to be created (normally
- <c>$ROOT/releases</c>). <c>RelFile</c> is the name
- of the <c>.rel</c> file that describes the initial release,
- including the extension <c>.rel</c>.</p>
+ <p><c>Root</c> is the root of the installation (<c>$ROOT</c>)
+ as described earlier. <c>RelDir</c> is the directory where the
+ <c>RELEASES</c> file is to be created (normally
+ <c>$ROOT/releases</c>). <c>RelFile</c> is the name of the
+ <c>.rel</c> file that describes the initial release, including
+ the extension <c>.rel</c>. If <c>Root</c> is not given,
+ the <c>RELEASES</c> file will be location independent (i.e, it
+ will not contain absolute paths unless there are absolute
+ paths in <c>AppDirs</c>). A <c>RELEASES</c> file should be
+ made location independent if the installation's <c>$ROOT</c>
+ is unknown. The <c>release_handler</c> module will interpret
+ relative paths in a running system's <c>RELEASES</c> file as
+ being relative to <c>$ROOT</c>.</p>
<p><c>AppDirs</c> can be used to specify from where the modules
for the specified applications are to be loaded. <c>App</c> is
the name of an application, <c>Vsn</c> is the version, and
diff --git a/lib/sasl/examples/src/Makefile b/lib/sasl/examples/src/Makefile
index e8b903f252..6b6f872221 100644
--- a/lib/sasl/examples/src/Makefile
+++ b/lib/sasl/examples/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -fr $(TARGET_FILES) *~ *.beam
diff --git a/lib/sasl/examples/src/target_system.erl b/lib/sasl/examples/src/target_system.erl
index b3d6748306..8a68dd379d 100644
--- a/lib/sasl/examples/src/target_system.erl
+++ b/lib/sasl/examples/src/target_system.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,9 +35,9 @@ create(RelFileName,SystoolsOpts) ->
Dir = filename:dirname(RelFileName),
PlainRelFileName = filename:join(Dir,"plain"),
PlainRelFile = PlainRelFileName ++ ".rel",
- io:fwrite("Reading file: ~tp ...~n", [RelFile]),
+ io:fwrite("Reading file: ~ts ...~n", [RelFile]),
{ok, [RelSpec]} = file:consult(RelFile),
- io:fwrite("Creating file: ~tp from ~tp ...~n",
+ io:fwrite("Creating file: ~ts from ~ts ...~n",
[PlainRelFile, RelFile]),
{release,
{RelName, RelVsn},
@@ -67,32 +67,32 @@ create(RelFileName,SystoolsOpts) ->
make_script(RelFileName,SystoolsOpts),
TarFileName = RelFileName ++ ".tar.gz",
- io:fwrite("Creating tar file ~tp ...~n", [TarFileName]),
+ io:fwrite("Creating tar file ~ts ...~n", [TarFileName]),
make_tar(RelFileName,SystoolsOpts),
TmpDir = filename:join(Dir,"tmp"),
io:fwrite("Creating directory ~tp ...~n",[TmpDir]),
file:make_dir(TmpDir),
- io:fwrite("Extracting ~tp into directory ~tp ...~n", [TarFileName,TmpDir]),
+ io:fwrite("Extracting ~ts into directory ~ts ...~n", [TarFileName,TmpDir]),
extract_tar(TarFileName, TmpDir),
TmpBinDir = filename:join([TmpDir, "bin"]),
ErtsBinDir = filename:join([TmpDir, "erts-" ++ ErtsVsn, "bin"]),
- io:fwrite("Deleting \"erl\" and \"start\" in directory ~tp ...~n",
+ io:fwrite("Deleting \"erl\" and \"start\" in directory ~ts ...~n",
[ErtsBinDir]),
file:delete(filename:join([ErtsBinDir, "erl"])),
file:delete(filename:join([ErtsBinDir, "start"])),
- io:fwrite("Creating temporary directory ~tp ...~n", [TmpBinDir]),
+ io:fwrite("Creating temporary directory ~ts ...~n", [TmpBinDir]),
file:make_dir(TmpBinDir),
- io:fwrite("Copying file \"~ts.boot\" to ~tp ...~n",
+ io:fwrite("Copying file \"~ts.boot\" to ~ts ...~n",
[PlainRelFileName, filename:join([TmpBinDir, "start.boot"])]),
copy_file(PlainRelFileName++".boot",filename:join([TmpBinDir, "start.boot"])),
io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n"
- "~tp to ~tp ...~n",
+ "~ts to ~ts ...~n",
[ErtsBinDir, TmpBinDir]),
copy_file(filename:join([ErtsBinDir, "epmd"]),
filename:join([TmpBinDir, "epmd"]), [preserve]),
@@ -104,15 +104,15 @@ create(RelFileName,SystoolsOpts) ->
%% This is needed if 'start' script created from 'start.src' shall
%% be used as it points out this directory as log dir for 'run_erl'
TmpLogDir = filename:join([TmpDir, "log"]),
- io:fwrite("Creating temporary directory ~tp ...~n", [TmpLogDir]),
+ io:fwrite("Creating temporary directory ~ts ...~n", [TmpLogDir]),
ok = file:make_dir(TmpLogDir),
StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]),
- io:fwrite("Creating ~tp ...~n", [StartErlDataFile]),
+ io:fwrite("Creating ~ts ...~n", [StartErlDataFile]),
StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]),
write_file(StartErlDataFile, StartErlData),
- io:fwrite("Recreating tar file ~tp from contents in directory ~tp ...~n",
+ io:fwrite("Recreating tar file ~ts from contents in directory ~ts ...~n",
[TarFileName,TmpDir]),
{ok, Tar} = erl_tar:open(TarFileName, [write, compressed]),
%% {ok, Cwd} = file:get_cwd(),
@@ -125,14 +125,14 @@ create(RelFileName,SystoolsOpts) ->
erl_tar:add(Tar, filename:join(TmpDir,"log"), "log", []),
erl_tar:close(Tar),
%% file:set_cwd(Cwd),
- io:fwrite("Removing directory ~tp ...~n",[TmpDir]),
+ io:fwrite("Removing directory ~ts ...~n",[TmpDir]),
remove_dir_tree(TmpDir),
ok.
install(RelFileName, RootDir) ->
TarFile = RelFileName ++ ".tar.gz",
- io:fwrite("Extracting ~tp ...~n", [TarFile]),
+ io:fwrite("Extracting ~ts ...~n", [TarFile]),
extract_tar(TarFile, RootDir),
StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]),
{ok, StartErlData} = read_txt_file(StartErlDataFile),
diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile
index 16a42caf11..490e03595d 100644
--- a/lib/sasl/src/Makefile
+++ b/lib/sasl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2020. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@ ERL_COMPILE_FLAGS += -I../../stdlib/include -Werror
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl
index 48feac1a21..7635b1ef78 100644
--- a/lib/sasl/src/release_handler.erl
+++ b/lib/sasl/src/release_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
%% External exports
-export([start_link/0,
- create_RELEASES/1, create_RELEASES/2, create_RELEASES/4,
+ create_RELEASES/1, create_RELEASES/2, create_RELEASES/3, create_RELEASES/4,
unpack_release/1,
check_install_release/1, check_install_release/2,
install_release/1, install_release/2, new_emulator_upgrade/2,
@@ -43,7 +43,13 @@
-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,
remove_file/1, do_write_file/2, do_write_file/3,
- do_ensure_RELEASES/1]).
+ do_ensure_RELEASES/1,
+ consult/2,
+ root_dir_relative_read_file_info/1,
+ root_dir_relative_read_file/1,
+ root_dir_relative_rename_file/2,
+ root_dir_relative_make_dir/1,
+ root_dir_relative_ensure_dir/1]).
-record(state, {unpurged = [],
root,
@@ -134,9 +140,9 @@
%%
%% It is configurable where the start file is located, and what it
%% is called.
-%% The paramater is {sasl, start_prg} = File
+%% The parameter is {sasl, start_prg} = File
%% It is also configurable where the releases directory is located.
-%% Default is $ROOT/releases. $RELDIR overrids, and
+%% Default is $ROOT/releases. $RELDIR overrides, and
%% {sasl, releases_dir} overrides both.
%%-----------------------------------------------------------------
start_link() ->
@@ -162,7 +168,7 @@ unpack_release(ReleaseName) ->
%% Purpose: Checks the relup script for the specified version.
%% The release must be unpacked.
%% Options = [purge] - all old code that can be soft purged
-%% will be purged if all checks succeeds. This can be usefull
+%% will be purged if all checks succeeds. This can be useful
%% in order to reduce time needed in the following call to
%% install_release.
%% Returns: {ok, FromVsn, Descr} | {error, Reason}
@@ -298,7 +304,7 @@ remove_release(Vsn) ->
%% .rel.
%% The release dir will be created. The necessary files can
%% be installed by calling install_file/2.
-%% The release_handler remebers where all libs are located.
+%% The release_handler remembers where all libs are located.
%% If remove_release is called later,
%% those libs are removed as well (if no other releases uses
%% them).
@@ -378,6 +384,8 @@ create_RELEASES([Root, RelFile | LibDirs]) ->
create_RELEASES(Root, RelFile) ->
create_RELEASES(Root, filename:join(Root, "releases"), RelFile, []).
+create_RELEASES(RelDir, RelFile, LibDirs) ->
+ create_RELEASES("", RelDir, RelFile, LibDirs).
create_RELEASES(Root, RelDir, RelFile, LibDirs) ->
case catch check_rel(Root, RelFile, LibDirs, false) of
{error, Reason } ->
@@ -397,7 +405,8 @@ create_RELEASES(Root, RelDir, RelFile, LibDirs) ->
%% located under Dir/ebin
%% Purpose: Upgrade to the version in Dir according to an appup file
%%-----------------------------------------------------------------
-upgrade_app(App, NewDir) ->
+upgrade_app(App, NewDir1) ->
+ NewDir = root_dir_relative_path(NewDir1),
try upgrade_script(App, NewDir) of
{ok, NewVsn, Script} ->
eval_appup_script(App, NewVsn, NewDir, Script)
@@ -435,7 +444,8 @@ downgrade_app(App, OldVsn, OldDir) ->
{error, Reason}
end.
-upgrade_script(App, NewDir) ->
+upgrade_script(App, NewDir1) ->
+ NewDir = root_dir_relative_path(NewDir1),
OldVsn = ensure_running(App),
OldDir = code:lib_dir(App),
{NewVsn, Script} = find_script(App, NewDir, OldVsn, up),
@@ -489,7 +499,8 @@ ensure_running(App) ->
end.
find_script(App, Dir, OldVsn, UpOrDown) ->
- Appup = filename:join([Dir, "ebin", atom_to_list(App)++".appup"]),
+ Appup1 = filename:join([Dir, "ebin", atom_to_list(App)++".appup"]),
+ Appup = root_dir_relative_path(Appup1),
case file:consult(Appup) of
{ok, [{NewVsn, UpFromScripts, DownToScripts}]} ->
Scripts = case UpOrDown of
@@ -522,7 +533,7 @@ read_app(App, Vsn, Dir) ->
read_appspec(App, Dir) ->
AppS = atom_to_list(App),
- Path = [filename:join(Dir, "ebin")],
+ Path = [root_dir_relative_path(filename:join(Dir, "ebin"))],
case file:path_consult(Path, AppS++".app") of
{ok, AppSpecL, _File} ->
AppSpecL;
@@ -833,7 +844,9 @@ do_unpack_release(Root, RelDir, ReleaseName, Releases) ->
Rel = ReleaseName ++ ".rel",
_ = extract_rel_file(filename:join("releases", Rel), Tar, Root),
RelFile = filename:join(RelDir, Rel),
- Release = check_rel(Root, RelFile, false),
+ %% Send an empty string as Root as the library locations should
+ %% appear as paths relative to the root
+ Release = check_rel("", RelFile, false),
#release{vsn = Vsn} = Release,
case lists:keysearch(Vsn, #release.vsn, Releases) of
{value, _} -> throw({error, {existing_release, Vsn}});
@@ -850,8 +863,8 @@ do_unpack_release(Root, RelDir, ReleaseName, Releases) ->
copy_file(RelFile, Dir, false),
%% Clean release
- _ = file:delete(Tar),
- _ = file:delete(RelFile),
+ _ = root_dir_relative_file_delete(Tar),
+ _ = root_dir_relative_file_delete(RelFile),
{ok, NewReleases, Vsn}.
@@ -883,7 +896,19 @@ check_rel_data({release, {Name, Vsn}, {erts, EVsn}, Libs}, Root, LibDirs,
check_path(Path, Masters),
Path;
_ ->
- filename:join([Root, "lib", LibName])
+ %% If Root is an empty string,
+ %% we assume that the path is
+ %% relative to code:root_dir()
+ %% and save a relative
+ %% path. This is done to make it
+ %% easy to create a relocatable
+ %% RELEASES file.
+ case string:length(Root) of
+ 0 ->
+ filename:join("lib", LibName);
+ _ ->
+ filename:join([Root, "lib", LibName])
+ end
end,
{Lib, LibVsn, LibDir}
end,
@@ -894,7 +919,7 @@ check_rel_data(RelData, _Root, _LibDirs, _Masters) ->
throw({error, {bad_rel_data, RelData}}).
check_path(Path) ->
- check_path_response(Path, file:read_file_info(Path)).
+ check_path_response(Path, root_dir_relative_read_file_info(Path)).
check_path(Path, false) -> check_path(Path);
check_path(Path, Masters) -> check_path_master(Masters, Path).
@@ -904,7 +929,7 @@ check_path(Path, Masters) -> check_path_master(Masters, Path).
%% at one node it should not exist at any other node either.
%%-----------------------------------------------------------------
check_path_master([Master|Ms], Path) ->
- case rpc:call(Master, file, read_file_info, [Path]) of
+ case rpc:call(Master, ?MODULE, root_dir_relative_read_file_info, [Path]) of
{badrpc, _} -> consult_master(Ms, Path);
Res -> check_path_response(Path, Res)
end;
@@ -1168,7 +1193,7 @@ new_emulator_rm_tmp_release(?tmp_vsn(_)=TmpVsn,EVsn,NewVsn,
new_emulator_rm_tmp_release(_,_,_,_,Releases,_) ->
Releases.
-%% Rename the tempoarary service (for erts ugprade) to the real ToVsn
+%% Rename the temporary service (for erts ugprade) to the real ToVsn
rename_tmp_service(EVsn,TmpVsn,NewVsn) ->
FromName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ TmpVsn,
ToName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ NewVsn,
@@ -1573,14 +1598,14 @@ memlib(_Lib, []) -> false.
%% recursively remove file or directory
remove_file(File) ->
- case file:read_link_info(File) of
+ case root_dir_relative_read_link_info(File) of
{ok, Info} when Info#file_info.type==directory ->
- case file:list_dir(File) of
+ case root_dir_relative_list_dir(File) of
{ok, Files} ->
lists:foreach(fun(File2) ->
remove_file(filename:join(File,File2))
end, Files),
- case file:del_dir(File) of
+ case root_dir_relative_dir_delete(File) of
ok -> ok;
{error, Reason} -> throw({error, Reason})
end;
@@ -1588,7 +1613,7 @@ remove_file(File) ->
throw({error, Reason})
end;
{ok, _Info} ->
- case file:delete(File) of
+ case root_dir_relative_file_delete(File) of
ok -> ok;
{error, Reason} -> throw({error, Reason})
end;
@@ -1599,7 +1624,8 @@ remove_file(File) ->
do_write_file(File, Str) ->
do_write_file(File, Str, []).
-do_write_file(File, Str, FileOpts) ->
+do_write_file(File1, Str, FileOpts) ->
+ File = root_dir_relative_path(File1),
case file:open(File, [write | FileOpts]) of
{ok, Fd} ->
io:put_chars(Fd, Str),
@@ -1822,13 +1848,13 @@ check_file_masters(_FileName, _Type, []) ->
%% Type == regular | directory
do_check_file(FileName, Type) ->
- case file:read_file_info(FileName) of
+ case root_dir_relative_read_file_info(FileName) of
{ok, Info} when Info#file_info.type==Type -> ok;
{error, _Reason} -> throw({error, {no_such_file, FileName}})
end.
do_check_file(Master, FileName, Type) ->
- case rpc:call(Master, file, read_file_info, [FileName]) of
+ case rpc:call(Master, ?MODULE, root_dir_relative_read_file_info, [FileName]) of
{ok, Info} when Info#file_info.type==Type -> ok;
_ -> throw({error, {no_such_file, {Master, FileName}}})
end.
@@ -1871,7 +1897,8 @@ write_releases_1(Dir, NewReleases, Masters) ->
write_releases_m(Dir, NewReleases, Masters).
do_write_release(Dir, RELEASES, NewReleases) ->
- case file:open(filename:join(Dir, RELEASES), [write,{encoding,utf8}]) of
+ ReleasesFile = root_dir_relative_path(filename:join(Dir, RELEASES)),
+ case file:open(ReleasesFile, [write,{encoding,utf8}]) of
{ok, Fd} ->
ok = io:format(Fd, "%% ~s~n~tp.~n",
[epp:encoding_to_string(utf8),NewReleases]),
@@ -1908,7 +1935,8 @@ write_releases_m(Dir, NewReleases, Masters) ->
remove_files(all, [Backup, Change], Masters),
ok;
{error, {Master, R}} ->
- takewhile(Master, Masters, file, rename,
+ takewhile(Master, Masters, ?MODULE,
+ root_dir_relative_rename_file,
[Backup, RelFile]),
remove_files(all, [Backup, Change], Masters),
throw({error, {Master, R, move_releases}})
@@ -1959,9 +1987,9 @@ do_copy_file(File, Dir) ->
do_copy_file1(File, File2).
do_copy_file1(File, File2) ->
- case file:read_file(File) of
+ case root_dir_relative_read_file(File) of
{ok, Bin} ->
- case file:write_file(File2, Bin) of
+ case root_dir_relative_write_file(File2, Bin) of
ok -> ok;
{error, Reason} ->
{error, {Reason, File2}}
@@ -1995,7 +2023,9 @@ do_copy_files([]) ->
%%-----------------------------------------------------------------
%% Rename each Src file to Dest file in the list of files.
%%-----------------------------------------------------------------
-do_rename_files([{Src, Dest}|Files]) ->
+do_rename_files([{Src1, Dest1}|Files]) ->
+ Src = root_dir_relative_path(Src1),
+ Dest = root_dir_relative_path(Dest1),
case file:rename(Src, Dest) of
ok -> do_rename_files(Files);
Error -> Error
@@ -2007,7 +2037,7 @@ do_rename_files([]) ->
%% Remove a list of files. Ignore failure.
%%-----------------------------------------------------------------
do_remove_files([File|Files]) ->
- _ = file:delete(File),
+ _ = root_dir_relative_file_delete(File),
do_remove_files(Files);
do_remove_files([]) ->
ok.
@@ -2018,7 +2048,7 @@ do_remove_files([]) ->
%% If not create an empty RELEASES file.
%%-----------------------------------------------------------------
do_ensure_RELEASES(RelFile) ->
- case file:read_file_info(RelFile) of
+ case root_dir_relative_read_file_info(RelFile) of
{ok, _} -> ok;
_ -> do_write_file(RelFile, "[]. ")
end.
@@ -2026,11 +2056,16 @@ do_ensure_RELEASES(RelFile) ->
%%-----------------------------------------------------------------
%% Make a directory, ignore failures (captured later).
%%-----------------------------------------------------------------
-make_dir(Dir, false) ->
+make_dir(Dir1, false) ->
+ Dir = root_dir_relative_path(Dir1),
_ = file:make_dir(Dir),
ok;
make_dir(Dir, Masters) ->
- lists:foreach(fun(Master) -> rpc:call(Master, file, make_dir, [Dir]) end,
+ lists:foreach(fun(Master) -> rpc:call(Master,
+ ?MODULE,
+ root_dir_relative_make_dir,
+ [Dir])
+ end,
Masters).
%%-----------------------------------------------------------------
@@ -2068,7 +2103,7 @@ takewhile(Master, Masters, M, F, A) ->
end, Masters),
ok.
-consult(File, false) -> file:consult(File);
+consult(File, false) -> file:consult(root_dir_relative_path(File));
consult(File, Masters) -> consult_master(Masters, File).
%%-----------------------------------------------------------------
@@ -2077,7 +2112,7 @@ consult(File, Masters) -> consult_master(Masters, File).
%% not exist at any other node either.
%%-----------------------------------------------------------------
consult_master([Master|Ms], File) ->
- case rpc:call(Master, file, consult, [File]) of
+ case rpc:call(Master, ?MODULE, consult, [File, false]) of
{badrpc, _} -> consult_master(Ms, File);
Res -> Res
end;
@@ -2085,12 +2120,12 @@ consult_master([], _File) ->
{error, no_master}.
read_file(File, false) ->
- file:read_file(File);
+ root_dir_relative_read_file(File);
read_file(File, Masters) ->
read_master(Masters, File).
write_file(File, Data, false) ->
- case file:write_file(File, Data) of
+ case root_dir_relative_write_file(File, Data) of
ok -> ok;
Error -> throw(Error)
end;
@@ -2101,12 +2136,12 @@ write_file(File, Data, Masters) ->
end.
ensure_dir(File, false) ->
- case filelib:ensure_dir(File) of
+ case root_dir_relative_ensure_dir(File) of
ok -> ok;
Error -> throw(Error)
end;
ensure_dir(File, Masters) ->
- case at_all_masters(Masters,filelib,ensure_dir,[File]) of
+ case at_all_masters(Masters,?MODULE,root_dir_relative_ensure_dir,[File]) of
ok -> ok;
Error -> throw(Error)
end.
@@ -2130,7 +2165,7 @@ remove_files(Master, Files, Masters) ->
%% not exist at any other node either.
%%-----------------------------------------------------------------
read_master([Master|Ms], File) ->
- case rpc:call(Master, file, read_file, [File]) of
+ case rpc:call(Master, ?MODULE, root_dir_relative_read_file, [File]) of
{badrpc, _} -> read_master(Ms, File);
Res -> Res
end;
@@ -2275,7 +2310,7 @@ safe_write_file_m(File, Data, FileOpts, Masters) ->
%%
%% A different situation is when the same application version is used
%% in old and new release, but the path has changed. This is not
-%% handled here - instead it must be explicitely indicated by the
+%% handled here - instead it must be explicitly indicated by the
%% 'update_paths' option to release_handler:install_release/2 if the
%% code path shall be updated then.
%% -----------------------------------------------------------------
@@ -2299,3 +2334,47 @@ get_releases_with_status([ {_, _, _, ReleaseStatus } = Head | Tail],
get_releases_with_status(Tail, Status, [Head | Acc]);
get_releases_with_status([_ | Tail], Status, Acc) ->
get_releases_with_status(Tail, Status, Acc).
+
+root_dir_relative_read_link_info(File) ->
+ file:read_link_info(root_dir_relative_path(File)).
+
+root_dir_relative_list_dir(File) ->
+ file:list_dir(root_dir_relative_path(File)).
+
+root_dir_relative_file_delete(File) ->
+ file:delete(root_dir_relative_path(File)).
+
+root_dir_relative_dir_delete(File) ->
+ file:del_dir(root_dir_relative_path(File)).
+
+root_dir_relative_path(Pathname) ->
+ case filename:pathtype(Pathname) of
+ relative ->
+ filename:join(code:root_dir(), Pathname);
+ _ ->
+ Pathname
+ end.
+
+root_dir_relative_write_file(File, Bin) ->
+ file:write_file(root_dir_relative_path(File), Bin).
+
+%% The root_dir_relative* functions below are exported so that they
+%% can be called on other nodes with rpc
+
+root_dir_relative_read_file_info(Path) ->
+ file:read_file_info(root_dir_relative_path(Path)).
+
+root_dir_relative_read_file(File) ->
+ file:read_file(root_dir_relative_path(File)).
+
+root_dir_relative_rename_file(Source1, Destination1) ->
+ Source = root_dir_relative_path(Source1),
+ Destination = root_dir_relative_path(Destination1),
+ file:rename(Source, Destination).
+
+root_dir_relative_make_dir(Dir) ->
+ file:make_dir(root_dir_relative_path(Dir)).
+
+root_dir_relative_ensure_dir(Dir) ->
+ filelib:ensure_dir(root_dir_relative_path(Dir)).
+
diff --git a/lib/sasl/src/release_handler_1.erl b/lib/sasl/src/release_handler_1.erl
index ede7df186b..3a5883dfb9 100644
--- a/lib/sasl/src/release_handler_1.erl
+++ b/lib/sasl/src/release_handler_1.erl
@@ -248,7 +248,7 @@ syntax_check_script([]) ->
%% {load_object_code, [Mod1, Mod2]},
%% % delete old version
%% {remove, {Mod1, brutal_purge}}, {remove, {Mod2, brutal_purge}},
-%% % now, some procs migth be running prev current (now old) version
+%% % now, some procs might be running prev current (now old) version
%% % kill them, and load new version
%% {load, {Mod1, brutal_purge}}, {load, {Mod2, brutal_purge}}
%% % now, there is one version of the code (new, current)
@@ -279,7 +279,7 @@ syntax_check_script([]) ->
%% If a process doesn't repsond - never mind. It will be killed
%% later on (if a purge is performed).
%% Hmm, we must do something smart here... we should probably kill it,
-%% but we cant, because its supervisor will restart it directly! Maybe
+%% but we can't, because its supervisor will restart it directly! Maybe
%% we should keep a list of those, call supervisor:terminate_child()
%% when all others are suspended, and call sup:restart_child() when the
%% others are resumed.
@@ -313,7 +313,7 @@ eval({load_object_code, {Lib, LibVsn, Modules}}, EvalState) ->
{NewBins, NewVsns} =
lists:foldl(fun(Mod, {Bins, Vsns}) ->
File = lists:concat([Mod, Ext]),
- FName = filename:join([LibDir, "ebin", File]),
+ FName = root_dir_relative_path(filename:join([LibDir, "ebin", File])),
case erl_prim_loader:get_file(FName) of
{ok, Bin, FName2} ->
NVsns = add_vsns(Mod, Bin, Vsns),
@@ -340,14 +340,15 @@ eval(point_of_no_return, EvalState) ->
EvalState#eval_state.libdirs
end,
lists:foreach(fun({Lib, _LibVsn, LibDir}) ->
- Ebin = filename:join(LibDir,"ebin"),
+ Ebin = root_dir_relative_path(filename:join(LibDir,"ebin")),
code:replace_path(Lib, Ebin)
end,
Libs),
EvalState;
eval({load, {Mod, _PrePurgeMethod, PostPurgeMethod}}, EvalState) ->
Bins = EvalState#eval_state.bins,
- {value, {_Mod, Bin, File}} = lists:keysearch(Mod, 1, Bins),
+ {value, {_Mod, Bin, File1}} = lists:keysearch(Mod, 1, Bins),
+ File = root_dir_relative_path(File1),
% load_binary kills all procs running old code
% if soft_purge, we know that there are no such procs now
{module,_} = code:load_binary(Mod, File, Bin),
@@ -804,3 +805,12 @@ get_vsn(Bin) ->
Vsn
end
end.
+
+root_dir_relative_path(Pathname) ->
+ case filename:pathtype(Pathname) of
+ relative ->
+ filename:join(code:root_dir(), Pathname);
+ _ ->
+ Pathname
+ end.
+
diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src
index 293af504df..8fc41ca506 100644
--- a/lib/sasl/src/sasl.app.src
+++ b/lib/sasl/src/sasl.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,6 +42,6 @@
{applications, [kernel, stdlib]},
{env, []},
{mod, {sasl, []}},
- {runtime_dependencies, ["tools-2.6.14","stdlib-3.4","kernel-5.3",
+ {runtime_dependencies, ["tools-2.6.14","stdlib-3.4","kernel-6.0",
"erts-10.2"]}]}.
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index e2fc3e5b7f..3752c085e2 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -19,34 +19,28 @@
%%
%% We allow upgrade from, and downgrade to all previous
%% versions from the following OTP releases:
-%% - OTP 22
%% - OTP 23
%% - OTP 24
+%% - OTP 25
%%
%% We also allow upgrade from, and downgrade to all
%% versions that have branched off from the above
%% stated previous versions.
%%
{"%VSN%",
- [{<<"^3\\.4$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^4\\.0$">>,[restart_new_emulator]},
+ [{<<"^4\\.0$">>,[restart_new_emulator]},
{<<"^4\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^4\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^4\\.0\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^4\\.1$">>,[restart_new_emulator]},
{<<"^4\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
- [{<<"^3\\.4$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.4\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^4\\.0$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
+ [{<<"^4\\.0$">>,[restart_new_emulator]},
{<<"^4\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^4\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^4\\.0\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^4\\.1$">>,[restart_new_emulator]},
{<<"^4\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
+ {<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
diff --git a/lib/sasl/src/systools.erl b/lib/sasl/src/systools.erl
index a97db3a20e..889cf924a3 100644
--- a/lib/sasl/src/systools.erl
+++ b/lib/sasl/src/systools.erl
@@ -43,7 +43,7 @@
%%-----------------------------------------------------------------
%% Options is a list of {path, Path} | silent | local where path sets
-%% the search path, silent supresses error message printing on console,
+%% the search path, silent suppresses error message printing on console,
%% local generates a script with references to the directories there
%% the applications are found.
%%-----------------------------------------------------------------
@@ -57,7 +57,7 @@ make_script(RelName, Opt) ->
%%-----------------------------------------------------------------
%% Options is a list of {path, Path} | silent |
%% {dirs, [src,include,examples,..]} | {erts, ErtsDir} where path
-%% sets the search path, silent supresses error message printing on console,
+%% sets the search path, silent suppresses error message printing on console,
%% dirs includes the specified directories (per application) in the
%% release package and erts specifies that the erts-Vsn/bin directory
%% should be included in the release package and there it can be found.
@@ -116,8 +116,8 @@ script2boot(File, Output0, _Opt) ->
%%-----------------------------------------------------------------
%% Options is a list of {path, Path} | silent | noexec where path sets
-%% search path, silent supresses error message printing on console,
-%% noexec supresses writing the output "relup" file
+%% search path, silent suppresses error message printing on console,
+%% noexec suppresses writing the output "relup" file
%%-----------------------------------------------------------------
make_relup(ReleaseName, UpNameList, DownNameList) ->
systools_relup:mk_relup(ReleaseName, UpNameList, DownNameList, []).
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index ca4fb4300a..b875c445c6 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -45,18 +45,13 @@
-compile({inline,[{badarg,2}]}).
--ifdef(USE_ESOCK).
-define(ESOCK_MODS, [prim_net,prim_socket,socket_registry]).
--else.
--define(ESOCK_MODS, []).
--endif.
-
%%-----------------------------------------------------------------
%% Create a boot script from a release file.
%% Options is a list of {path, Path} | silent | local
%% | warnings_as_errors
-%% where path sets the search path, silent supresses error message
+%% where path sets the search path, silent suppresses error message
%% printing on console, local generates a script with references
%% to the directories there the applications are found,
%% and warnings_as_errors treats warnings as errors.
@@ -195,7 +190,7 @@ do_make_hybrid_boot(TmpVsn, OldBoot, NewBoot, Args) ->
{script,{_RelName1,_RelVsn1},OldScript} = binary_to_term(OldBoot),
{script,{NewRelName,_RelVsn2},NewScript} = binary_to_term(NewBoot),
- %% Everyting upto kernel_load_completed must come from the new script
+ %% Everything up to kernel_load_completed must come from the new script
Fun1 = fun({progress,kernel_load_completed}) -> false;
(_) -> true
end,
@@ -345,7 +340,7 @@ add_apply_upgrade(Script,Args) ->
%% Create a release package from a release file.
%% Options is a list of {path, Path} | silent |
%% {dirs, [src,include,examples,..]} | {erts, ErtsDir} where path
-%% sets the search path, silent supresses error message printing,
+%% sets the search path, silent suppresses error message printing,
%% dirs includes the specified directories (per application) in the
%% release package and erts specifies that the erts-Vsn/bin directory
%% should be included in the release package and there it can be found.
@@ -674,7 +669,7 @@ parse_application({application, Name, Dict}, File, Vsn, Incls)
parse_application(Other, _, _, _) ->
{error, {badly_formatted_application, Other}}.
-%% Test if all included applications specifed in the .rel file
+%% Test if all included applications specified in the .rel file
%% exists in the {included_applications,Incs} specified in the
%% .app file.
override_include(Name, Incs, Incls) ->
@@ -1162,12 +1157,36 @@ smart_guess(Dir,IncPath) ->
D1 = reverse(D),
Dirs = [filename:join(D1 ++ ["src"]),
filename:join(D1 ++ ["src", "e_src"])],
- {Dirs,Dirs ++ IncPath};
+ RecurseDirs = add_subdirs(Dirs),
+ {RecurseDirs,RecurseDirs ++ IncPath};
_ ->
{[Dir],[Dir] ++ IncPath}
end.
%%______________________________________________________________________
+%% add_subdirs([Dirs]) -> [Dirs]
+%% Take the directories that were used for a guess, and search them
+%% recursively. This is required for applications relying on varying
+%% nested directories. One example within OTP is the `wx' application,
+%% which has auto-generated modules in `src/gen/' and then fail any
+%% systools check.
+
+add_subdirs([]) ->
+ [];
+add_subdirs([Dir|Dirs]) ->
+ case filelib:is_dir(Dir) of
+ false ->
+ %% Keep the bad guess, but put it last in the search order
+ %% since we won't find anything there. Handling of errors
+ %% for unfound file is done in `locate_src/2'
+ add_subdirs(Dirs) ++ [Dir];
+ true ->
+ SubDirs = [File || File <- filelib:wildcard(filename:join(Dir, "**")),
+ filelib:is_dir(File)],
+ [Dir|SubDirs] ++ add_subdirs(Dirs)
+ end.
+
+%%______________________________________________________________________
%% generate_script(#release,
%% [{{Name,Vsn},#application}], Flags) ->
%% ok | {error, Error}
@@ -1346,7 +1365,7 @@ find_all(CheckingApp, [Name|T], L, Visited, Found, NotFound) ->
case find_app(Name, L) of
{value, App} ->
{_A,R} = App,
- %% It is OK to have a dependecy like
+ %% It is OK to have a dependency like
%% X includes Y, Y uses X.
case lists:member(CheckingApp, R#application.includes) of
true ->
@@ -1386,7 +1405,7 @@ del_apps([], L) ->
%%______________________________________________________________________
%% Create the load path used in the generated script.
%% If PathFlag is true a script intended to be used as a complete
-%% system (e.g. in an embbeded system), i.e. all applications are
+%% system (e.g. in an embedded system), i.e. all applications are
%% located under $ROOT/lib.
%% Otherwise all paths are set according to dir per application.
@@ -1755,7 +1774,7 @@ add_system_files(Tar, RelName, Release, Path1) ->
%% (well, actually the boot file was looked for in the same
%% directory as RelName, which is not necessarily the same as cwd)
%% --
- %% but also in the path specfied as an option to systools:make_tar
+ %% but also in the path specified as an option to systools:make_tar
%% (but make sure to search the RelName directory and cwd first)
Path = case filename:dirname(RelName) of
"." ->
diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile
index 2a782bcf61..adc5a927ac 100644
--- a/lib/sasl/test/Makefile
+++ b/lib/sasl/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2011-2016. All Rights Reserved.
+# Copyright Ericsson AB 2011-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -35,10 +35,13 @@ MODULES= \
systools_rc_SUITE \
rb_SUITE \
rh_test_lib \
+ otp_vsns
ERL_FILES= $(MODULES:%=%.erl)
-HRL_FILES= test_lib.hrl
+EXTRA_FILES= $(ERL_TOP)/otp_versions.table
+
+HRL_FILES=
TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
INSTALL_PROGS= $(TARGET_FILES)
@@ -55,6 +58,7 @@ RELSYSDIR = $(RELEASE_PATH)/sasl_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/sasl/src
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -68,7 +72,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
>> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
@@ -87,9 +91,10 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) "$(RELSYSDIR)"
- $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) "$(RELSYSDIR)"
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(EXTRA_FILES) "$(RELSYSDIR)"
$(INSTALL_DATA) sasl.spec sasl.cover $(EMAKEFILE) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cfh - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ $(INSTALL_DATA) $(ERL_TOP)/make/otp_version_tickets "$(RELSYSDIR)/sasl_SUITE_data"
release_docs_spec:
diff --git a/lib/sasl/test/installer.erl b/lib/sasl/test/installer.erl
index 2c5c9d725a..05b0156574 100644
--- a/lib/sasl/test/installer.erl
+++ b/lib/sasl/test/installer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
-module(installer).
--include("test_lib.hrl").
-
%%-compile(export_all).
-export([install_1/2]).
-export([install_2/1]).
@@ -330,7 +328,7 @@ install_11(TestNode) ->
true = lists:member("a-1.0", Libs),
false = lists:member("a-1.1", Libs),
{ok, Dirs} = file:list_dir(code:root_dir()),
- ErtsDir = "erts-"++?ertsvsn,
+ ErtsDir = "erts-"++rh_test_lib:old_app_vsn(erts),
[ErtsDir] = lists:filter(fun(Dir) -> lists:prefix("erts-",Dir) end, Dirs),
?print(["install_11 file checks ok"]),
ok.
@@ -383,7 +381,7 @@ install_14(TestNode) ->
%%%-----------------------------------------------------------------
-%%% Ths test checks that an upgrade which both upgrades to a new
+%%% The 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.)
@@ -413,7 +411,7 @@ upgrade_restart_2(TestNode) ->
{"SASL-test","P2B"} ->
upgrade_restart_2a(TestNode);
{"SASL-test","__new_emulator__P1G"} ->
- %% catched the node too early - give it another try
+ %% caught the node too early - give it another try
{wait,whereis(init)}
end.
@@ -918,7 +916,9 @@ 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-"++?ertsvsn,"bin"]),
+ ErtsBinDir = filename:join([RootDir,
+ "erts-"++rh_test_lib:old_app_vsn(erts),
+ "bin"]),
{ClientArgs,RelClientDir} = rh_test_lib:get_client_args(Client,ClientSname,
RootDir),
diff --git a/lib/sasl/test/otp_vsns.erl b/lib/sasl/test/otp_vsns.erl
new file mode 100644
index 0000000000..d88fb8a815
--- /dev/null
+++ b/lib/sasl/test/otp_vsns.erl
@@ -0,0 +1,160 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(otp_vsns).
+
+-export([read_state/0, read_state/1, branch_latest/2, branch_vsns/2, app_vsn/3]).
+
+read_state() ->
+ File = "otp_versions.table",
+ Dir = filename:dirname(code:which(?MODULE)),
+ Alt0 = filename:join([Dir, File]),
+ case file:read_file_info(Alt0) of
+ {ok, _} ->
+ read_state(Alt0);
+ _ ->
+ Alt1 = filename:join([Dir, "..", "priv", File]),
+ case file:read_file_info(Alt1) of
+ {ok, _} ->
+ read_state(Alt1);
+ _ ->
+ error(no_otp_versions_table)
+ end
+ end.
+
+read_state(OtpVsnsTabFile) ->
+ {ok, OtpVsnsTabData} = file:read_file(OtpVsnsTabFile),
+ lists:foldl(fun (OtpAppVsnsBin, Acc0) ->
+ [OtpVsnBin
+ | AppVsnBins] = binary:split(OtpAppVsnsBin,
+ [<<" ">>,
+ <<":">>,
+ <<"#">>],
+ [global, trim_all]),
+ OtpVsn = mk_vsn(OtpVsnBin),
+ AppList = lists:map(fun (AppVsnBin) ->
+ AppVsn = mk_vsn(AppVsnBin),
+ {App, _} = AppVsn,
+ {App, AppVsn}
+ end,
+ AppVsnBins),
+ AppMap = maps:from_list(AppList),
+ Acc1 = maps:put(OtpVsn, AppMap, Acc0),
+ Acc2 = update_branch(OtpVsn, Acc1),
+ update_branch_versions(OtpVsn, Acc2)
+ end,
+ #{},
+ binary:split(OtpVsnsTabData, <<"\n">>, [global, trim_all])).
+
+branch_latest(State, "maint-" ++ RelStr) ->
+ mk_vsn_str(maps:get({maint, list_to_integer(RelStr)}, State)).
+
+branch_vsns(State, "maint-" ++ RelStr) ->
+ Rel = list_to_integer(RelStr),
+ NrmlVsns = lists:map(fun (V) -> mk_vsn_str(V) end,
+ maps:get({normal_maint_vsns, Rel}, State)),
+ case maps:get({maint, Rel}, State) of
+ {'OTP', [_, _]} ->
+ NrmlVsns;
+ {'OTP', [_, _, _]} ->
+ NrmlVsns;
+ {'OTP', [_, _, _, _]} = Vsn ->
+ add_branched_vsns(1, Vsn, NrmlVsns)
+ end.
+
+add_branched_vsns(MinorPatch,
+ {'OTP', [_Major, _Minor, _Patch, MinorPatch]} = Vsn,
+ VsnStrs) ->
+ [mk_vsn_str(Vsn) | VsnStrs];
+add_branched_vsns(N,
+ {'OTP', [Major, Minor, Patch, _MinorPatch]} = Vsn,
+ VsnStrs) ->
+ VsnStr = mk_vsn_str({'OTP', [Major, Minor, Patch, N]}),
+ add_branched_vsns(N+1, Vsn, [VsnStr | VsnStrs]).
+
+app_vsn(State, "OTP-"++OtpVsn, App) ->
+ AppMap = maps:get({'OTP', vsnstr2vsnlist(OtpVsn)}, State),
+ mk_vsn_str(maps:get(list_to_atom(App), AppMap)).
+
+mk_vsn_str({App, Vsn}) ->
+ VsnStr = lists:flatten(lists:join($., lists:map(fun (V) ->
+ integer_to_list(V)
+ end, Vsn))),
+ atom_to_list(App) ++ "-" ++ VsnStr.
+
+mk_vsn(AppVsnBin) ->
+ [AppBin, VsnBin] = binary:split(AppVsnBin, <<"-">>),
+ {binary_to_atom(AppBin), vsnstr2vsnlist(VsnBin)}.
+
+vsnstr2vsnlist(VsnStr) ->
+ lists:map(fun (SV) when is_list(SV) ->
+ list_to_integer(SV);
+ (BV) when is_binary(BV) ->
+ binary_to_integer(BV)
+ end, string:lexemes(VsnStr, ".")).
+
+update_branch({'OTP', [Major, Minor | _] = Vsn} = OtpVsn,
+ VsnMap) when length(Vsn) =< 4 ->
+ Branch = {maint, Major},
+ case maps:get(Branch, VsnMap, undefined) of
+ undefined ->
+ maps:put(Branch, OtpVsn, VsnMap);
+ {'OTP', [Major, OldMinor | _] = OldVsn} ->
+ if OldMinor < Minor ->
+ maps:put(Branch, OtpVsn, VsnMap);
+ OldMinor > Minor ->
+ VsnMap;
+ true ->
+ {Patch, MinorPatch} = get_patch_vsns(Vsn),
+ {OldPatch, OldMinorPatch} = get_patch_vsns(OldVsn),
+ if OldPatch < Patch ->
+ maps:put(Branch, OtpVsn, VsnMap);
+ OldPatch > Patch ->
+ VsnMap;
+ OldMinorPatch < MinorPatch ->
+ maps:put(Branch, OtpVsn, VsnMap);
+ true ->
+ VsnMap
+ end
+ end
+ end;
+update_branch({'OTP', [_Major, _Minor | _]}, VsnMap) ->
+ VsnMap.
+
+update_branch_versions({'OTP', [Rel | _] = Vsn} = OtpVsn,
+ VsnMap) when length(Vsn) =< 3 ->
+ %% Save normal versions. Branched versions are added on request
+ %% since we do not know the right branch until all versions has
+ %% been parsed.
+ BranchVsnsKey = {normal_maint_vsns, Rel},
+ OtherOtpVsns = case maps:get(BranchVsnsKey, VsnMap, undefined) of
+ undefined -> [];
+ Vsns -> Vsns
+ end,
+ maps:put(BranchVsnsKey, [OtpVsn|OtherOtpVsns], VsnMap);
+update_branch_versions({'OTP', _}, VsnMap) ->
+ VsnMap.
+
+get_patch_vsns([_Major, _Minor]) ->
+ {0, 0};
+get_patch_vsns([_Major, _Minor, Patch]) ->
+ {Patch, 0};
+get_patch_vsns([_, _, Patch, MinorPatch | _]) ->
+ {Patch, MinorPatch}.
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index f545590247..570e1bc1fe 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@
-module(release_handler_SUITE).
-include_lib("common_test/include/ct.hrl").
--include("test_lib.hrl").
+-include_lib("stdlib/include/assert.hrl").
+-include_lib("kernel/include/file.hrl").
-compile([export_all, nowarn_export_all]).
-export([scheduler_wall_time/0, garbage_collect/0]). %% rpc'ed
@@ -60,17 +61,16 @@ win32_cases() ->
%% Cases that can be run on all platforms
cases() ->
- [otp_2740, otp_2760, otp_5761, otp_9402, otp_9417,
- otp_9395_check_old_code, otp_9395_check_and_purge,
- otp_9395_update_many_mods, otp_9395_rm_many_mods,
+ [otp_9395_check_old_code,
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,
- otp_10463_upgrade_script_regexp, no_dot_erlang, unicode_upgrade].
+ install_release_syntax_check,
+ otp_10463_upgrade_script_regexp, no_dot_erlang, move_system,
+ {group, absolute}, {group, relative}].
groups() ->
- [{release,[],
+ [{absolute,[],root_dir_cases()},
+ {relative,[],root_dir_cases()},
+ {release,[],
[
{group,release_single},
{group,release_gg}
@@ -87,6 +87,22 @@ groups() ->
upgrade_gg
]}].
+%% Testcases that are to be run with and without an absolute root dir
+root_dir_cases() ->
+ [supervisor_which_children_timeout,
+ release_handler_which_releases,
+ otp_2760,
+ otp_5761,
+ otp_9402,
+ otp_9417,
+ otp_9395_check_and_purge,
+ otp_9395_update_many_mods,
+ otp_9395_rm_many_mods,
+ otp_9864,
+ upgrade_supervisor,
+ upgrade_supervisor_fail,
+ unicode_upgrade].
+
%% {group,release}
%% Top group for all cases using run_erl
init_per_group(release, Config) ->
@@ -161,8 +177,10 @@ init_per_group(release_gg, Config0) ->
Snames),
test_server:timetrap_cancel(Dog),
- [{snames,Snames}|Config].
-
+ [{snames,Snames}|Config];
+init_per_group(Group, Config) when Group =:= absolute;
+ Group =:= relative ->
+ [{root_dir, Group}|Config].
end_per_group(release, Config) ->
Dog = test_server:timetrap(?default_timeout),
@@ -244,6 +262,252 @@ gg_node_snames(Config) ->
%%%-----------------------------------------------------------------
%%% TEST CASES
+%% Test that a release can be location independent (i.e., if all
+%% paths related to the release are relative to the ROOTDIR of the
+%% release, then one can move the release to a different directory and
+%% it should still work).
+move_system(Conf) when is_list(Conf) ->
+
+ DataDir = ?config(data_dir, Conf),
+ TestRootDir = filename:join(priv_dir(Conf), ?FUNCTION_NAME),
+ ErtsBinDir = filename:join("erts-" ++ find_vsn_app(erts), "bin"),
+
+ %% Remove old test data
+ file:del_dir_r(filename:join(TestRootDir,"system")),
+ file:del_dir_r(filename:join(TestRootDir,"system_moved")),
+ file:del_dir_r(filename:join(TestRootDir,"system_moved_again")),
+
+ %% Create TAR file for release A
+ ReleaseATarFile = create_release_package(DataDir, "hello_server", "A"),
+ SystemPath = filename:join(TestRootDir, "system"),
+ ok = erl_tar:extract(ReleaseATarFile, [{cwd, SystemPath}, compressed]),
+ RelDir = filename:join(SystemPath, "releases"),
+ SystemRelFile = filename:join(RelDir, "hello_server-A.rel"),
+
+ %% Create a location independent RELEASES file. Library paths in the releases
+ %% file are assumed to be relative to the RootDir.
+ ok = release_handler:create_RELEASES(RelDir, SystemRelFile, []),
+
+ %% Create the bin directory with links (or copies on windows) to the erts directory
+ file:make_dir(filename:join(SystemPath,"bin")),
+ case os:type() of
+ {win32, _} ->
+ {ok,_} = file:copy(
+ filelib:wildcard(filename:join([SystemPath,ErtsBinDir,"erl.exe"])),
+ filename:join([SystemPath,"bin","erl.exe"]));
+ _ ->
+ ok = file:make_symlink(
+ filename:join(["..",ErtsBinDir,"erl"]),
+ filename:join([SystemPath,"bin","erl"]))
+ end,
+
+ %% Test that the location independent system can start and run
+ {ok, Peer, Node} = start_remote_node(SystemPath, "A"),
+ hello = erpc:call(Node, app_callback_module, get_response, []),
+ peer:stop(Peer),
+
+ %% Should still work after copying the system and corrupting the source
+ NewSystemPath = filename:join(TestRootDir, "system_moved"),
+ copy_r(SystemPath, NewSystemPath),
+ [file:del_dir_r(F) || F <- filelib:wildcard(filename:join([SystemPath,"lib","stdlib*"]))],
+ file:del_dir_r(filename:join(SystemPath,"releases")),
+ {ok, MovedPeer, MovedNode} = start_remote_node(NewSystemPath, "A"),
+ hello = erpc:call(MovedNode, app_callback_module, get_response, []),
+ peer:stop(MovedPeer),
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Let us now try if a system upgrade also works with a location independent system %
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ ReleaseBTarFile = create_release_package(DataDir, "hello_server_new", "B"),
+
+ BPackDest = filename:join([NewSystemPath, "releases", filename:basename(ReleaseBTarFile)]),
+ {ok, _ } = file:copy(ReleaseBTarFile, BPackDest),
+ BTarFileName = filename:basename(ReleaseBTarFile),
+ NameToUnpack = filename:rootname(BTarFileName, ".tar.gz"),
+ %% Start remote node with release A
+ {ok, PeerA, NodeA} = start_remote_node(NewSystemPath, "A"),
+
+ %% Set current working directory to something irrelevant as the
+ %% current working directory should not affect if a system is
+ %% location independent or not
+ ok = erpc:call(NodeA, file, set_cwd, ["/"]),
+ %% Let us check our app
+ hello = erpc:call(NodeA, app_callback_module, get_response, []),
+ %% Install the next release
+ {ok, "B"} = erpc:call(NodeA, release_handler, unpack_release, [NameToUnpack]),
+ %% We can now create relup file
+ AppUpSrc = filename:join([DataDir, "relocatable_release", "hello_server_new",
+ "ebin", "hello_server.appup"]),
+ AppUpDest = filename:join([NewSystemPath, "lib", "hello_server-B", "ebin", "hello_server.appup"]),
+ {ok, _} = file:copy(AppUpSrc, AppUpDest),
+ %% Run command to create the relup file
+ ok = systools:make_relup(
+ filename:join([NewSystemPath, "releases", "B", "hello_server-B"]),
+ [filename:join([NewSystemPath, "releases", "A", "hello_server-A"])],
+ [filename:join([NewSystemPath, "releases", "A", "hello_server-A"])],
+ [{outdir,filename:join([NewSystemPath, "releases","B"])},
+ {path,[NewSystemPath ++ "/lib/hello_server-A/ebin/",
+ NewSystemPath ++ "/lib/hello_server-B/ebin/"]}]
+ ),
+ %% Install the B version
+ {ok, "A", _} = erpc:call(NodeA, release_handler, install_release, ["B"]),
+ %% Check that the releases info looks ok
+ true = lists:any(fun({"hello_server", "B", _, current}) ->
+ true;
+ (_) ->
+ false
+ end,
+ erpc:call(NodeA, release_handler, which_releases, [])),
+ %% Make sure the old module gets replaced
+ ok = erpc:call(NodeA, app_callback_module, update, []),
+ %% Check that the upgrade worked
+ hej = erpc:call(NodeA, app_callback_module, get_response, []),
+
+ case os:type() of
+ {win32, _} ->
+ %% We cannot make release permanent on windows due to
+ %% not having permissions to edit services.
+ %% And symlinks to do not on windows, so we don't test
+ %% anything more there.
+ peer:stop(PeerA);
+ _ ->
+ move_system_unix(NodeA, PeerA, TestRootDir, ErtsBinDir, NewSystemPath)
+
+ end.
+
+move_system_unix(NodeA, PeerA, TestRootDir, ErtsBinDir, NewSystemPath) ->
+ %% Make the upgrade permanent
+ ok = erpc:call(NodeA, release_handler, make_permanent, ["B"]),
+ %% Check that it still works
+ hej = erpc:call(NodeA, app_callback_module, get_response, []),
+ true = lists:any(fun({"hello_server", "B", _, permanent}) ->
+ true;
+ (_) ->
+ false
+ end,
+ erpc:call(NodeA, release_handler, which_releases, [])),
+ ok = peer:stop(PeerA),
+
+ %% We will now move the install and check that everything still seems to be working fine
+ NewSystemPath2 = filename:join(TestRootDir, "system_moved_again"),
+ ok = file:rename(NewSystemPath, NewSystemPath2),
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Create a symlink to moved system and test that if we set the path to
+ %% contain the symlink it will work.
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ ok = file:make_symlink(
+ filename:join([NewSystemPath2, ErtsBinDir, "erl"]),
+ filename:join(TestRootDir, "erl")),
+
+ Name = peer:random_name(),
+ LinkNode = list_to_atom(Name++"@"++lists:last(string:split(atom_to_list(node()),"@"))),
+
+ %% We cannot use ?CT_PEER here because it uses spawn_executable and that
+ %% does not search the PATH for which program to run.
+ Port = open_port(
+ {spawn,"erl -sname " ++ Name ++ " -boot " ++
+ filename:join([NewSystemPath2, "releases", "B", "start"])},
+ [{env,[{"PATH",TestRootDir ++ ":" ++ os:getenv("PATH")}]}]),
+
+ %% Wait for node to start
+ receive _ -> ok end,
+
+ hej = erpc:call(LinkNode, app_callback_module, get_response, []),
+
+ true = catch port_close(Port),
+ ct:log("~p",[(fun F() -> receive M -> [M | F()] after 0 -> [] end end)()]),
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Test that we can do a downgrade of the moved system
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ {ok, PeerB, NodeB} = start_remote_node(NewSystemPath2, "B"),
+
+ %% Change current working directory to something irrelevant
+ ok = erpc:call(NodeB, file, set_cwd, ["/"]),
+ {ok, "/"} = erpc:call(NodeB, file, get_cwd, []),
+ %% Check that we are using version B
+ hej = erpc:call(NodeB, app_callback_module, get_response, []),
+ %% Downgrade to version A
+ {ok, "A", _} = erpc:call(NodeB, release_handler, install_release, ["A"]),
+ true = lists:any(fun({"hello_server", "A", _, current}) ->
+ true;
+ (_) ->
+ false
+ end,
+ erpc:call(NodeB, release_handler, which_releases, [])),
+ %% Make sure that the module is reloaded
+ ok = erpc:call(NodeB, app_callback_module, update, []),
+ %% Make sure that we are on version A
+ hello = erpc:call(NodeB, app_callback_module, get_response, []),
+ %% Make the downgrade permanent
+ ok = erpc:call(NodeB, release_handler, make_permanent, ["A"]),
+ %% Test that remove release works
+ ok = erpc:call(NodeB, release_handler, remove_release, ["B"]),
+ %% B should not exist anymore
+ false = lists:any(fun({"hello_server", "B", _, _}) ->
+ true;
+ (_) ->
+ false
+ end,
+ erpc:call(NodeB, release_handler, which_releases, [])),
+ ok = erpc:call(NodeB, app_callback_module, update, []),
+ %% We should still get hello
+ hello = erpc:call(NodeB, app_callback_module, get_response, []),
+ ok = peer:stop(PeerB),
+
+ ok.
+
+start_remote_node(SystemPath, RelVsn) ->
+ SystemErlPath = filename:join([SystemPath, "bin", "erl"]),
+ ?CT_PEER(#{ exec => SystemErlPath,
+ args => ["-boot",filename:join([SystemPath,"releases", RelVsn, "start"])]}).
+
+create_release_package(DataDir, SourceDir, RelVsn) ->
+ ReleaseSource = filename:join(DataDir, "relocatable_release"),
+ AppSrc = filename:join(ReleaseSource, SourceDir),
+ OldCWD = file:get_cwd(),
+ file:set_cwd(AppSrc),
+ os:cmd("erl -make"),
+ file:set_cwd(OldCWD),
+ RelFileScr = filename:join(ReleaseSource, "hello_server-"++ RelVsn ++".rel.src"),
+ RelFileDst = filename:join(ReleaseSource, "hello_server-"++ RelVsn ++".rel"),
+ {ok, RelFileTxt1} = file:read_file(RelFileScr),
+ RelFileTxt = fix_rel_file_vsns(["erts", "kernel", "stdlib", "sasl"],
+ RelFileTxt1),
+ ok = file:write_file(RelFileDst, RelFileTxt),
+ AppPath = filename:join([ReleaseSource, SourceDir, "ebin"]),
+ RelFileWithoutEnding = filename:join(ReleaseSource, "hello_server-" ++ RelVsn),
+ ok = systools:make_script(RelFileWithoutEnding, [local, {path, [AppPath]}]),
+ ok = systools:make_tar(RelFileWithoutEnding, [{erts, code:root_dir()}, {path, [AppPath]}]),
+ SystemPath = filename:join(ReleaseSource, "system"),
+ file:make_dir(SystemPath),
+ InitialTarPath = filename:join(ReleaseSource, "hello_server-"++ RelVsn ++".tar.gz"),
+ InitialTarPath.
+
+fix_rel_file_vsns(Apps, Txt) ->
+ Res =
+ lists:foldl(
+ fun(App, TxtAcc) ->
+ string:replace(TxtAcc,
+ "%" ++ App ++ "_VSN" ++ "%" ,
+ find_vsn_app(erlang:list_to_atom(App)))
+ end,
+ Txt,
+ Apps),
+ erlang:iolist_to_binary(lists:flatten(Res)).
+
+find_vsn_app(erts) ->
+ Str = erlang:system_info(system_version),
+ {match, [{Start, Len} | _]} = re:run(Str, "erts-(\\d\\.?)+"),
+ ErtsStr = string:substr(Str, Start+1, Len),
+ [_, Vsn] = string:split(ErtsStr, "-"),
+ Vsn;
+find_vsn_app(App) ->
+ Apps = application:which_applications(),
+ [Vsn] = [Vsn || {AppX, _, Vsn} <- Apps, AppX =:= App],
+ Vsn.
+
%% Executed instead of release group when no run_erl program exists
no_run_erl(Config) when is_list(Config) ->
@@ -390,7 +654,7 @@ upgrade_restart(Conf) when is_list(Conf) ->
ok ->
ok;
{wait,TestNodeInit2a} ->
- %% We catched the node too early - it was supposed to
+ %% We caught 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, [])
@@ -618,7 +882,7 @@ supervisor_which_children_timeout(Conf) ->
DataDir = ?config(data_dir,Conf),
LibDir = filename:join([DataDir,release_handler_timeouts]),
- Rel1 = create_and_install_fake_first_release(Dir,[{dummy,"0.1",LibDir}]),
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,[{dummy,"0.1",LibDir}]),
{ok, Node} = t_start_node(supervisor_which_children_timeout, Rel1, []),
Proc = rpc:call(Node, erlang, whereis, [dummy_sup_2]),
@@ -657,7 +921,7 @@ release_handler_which_releases(Conf) ->
DataDir = ?config(data_dir,Conf),
LibDir = filename:join([DataDir,release_handler_timeouts]),
- Rel1 = create_and_install_fake_first_release(Dir,[{dummy,"0.1",LibDir}]),
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,[{dummy,"0.1",LibDir}]),
{ok, Node} = t_start_node(release_handler_which_releases, Rel1, []),
Releases0 = rpc:call(Node, release_handler, which_releases, []),
@@ -713,7 +977,7 @@ otp_2760(Conf) ->
DataDir = ?config(data_dir,Conf),
LibDir = filename:join([DataDir,app1_app2,lib1]),
- Rel1 = create_and_install_fake_first_release(Dir,[{app1,"1.0",LibDir}]),
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,[{app1,"1.0",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,"after",[],{[Rel1],[Rel1],[LibDir]}),
Rel2Dir = filename:dirname(Rel2),
@@ -751,7 +1015,7 @@ otp_5761(Conf) when is_list(Conf) ->
LibDir2 = filename:join(RelDir, "lib2"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{app1,"1.0",LibDir1},
{app2,"1.0",LibDir1}]),
Rel2 = create_fake_upgrade_release(Dir,
@@ -830,7 +1094,7 @@ otp_9402(Conf) when is_list(Conf) ->
LibDir = filename:join(?config(data_dir, Conf), "lib"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{a,"1.1",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,
"2",
@@ -897,7 +1161,7 @@ otp_9417(Conf) when is_list(Conf) ->
LibDir = filename:join(?config(data_dir, Conf), "lib"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{b,"1.0",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,
"2",
@@ -1010,7 +1274,7 @@ otp_9395_check_and_purge(Conf) when is_list(Conf) ->
LibDir = filename:join(?config(data_dir, Conf), "lib"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{b,"1.0",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,
"2",
@@ -1076,7 +1340,7 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
LibDir = filename:join(?config(data_dir, Conf), "lib"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{many_mods,"1.0",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,
"2",
@@ -1191,7 +1455,7 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
LibDir = filename:join(?config(data_dir, Conf), "lib"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{many_mods,"1.0",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,
"2",
@@ -1303,7 +1567,7 @@ do_otp_9864(Conf) ->
LibDir2 = filename:join(Dir, "lib2"),
%% Create the releases
- Rel1 = create_and_install_fake_first_release(Dir,
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,
[{app1,"1.0",LibDir1},
{app2,"1.0",LibDir1}]),
Rel2 = create_fake_upgrade_release(Dir,
@@ -1359,7 +1623,7 @@ upgrade_supervisor(Conf) when is_list(Conf) ->
%% Create the releases
Lib1 = [{a,"1.0",LibDir}],
Lib2 = [{a,"9.0",LibDir}],
- Rel1 = create_and_install_fake_first_release(Dir,Lib1),
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,Lib1),
Rel2 = create_fake_upgrade_release(Dir,"2",Lib2,{[Rel1],[Rel1],[LibDir]}),
Rel1Dir = filename:dirname(Rel1),
Rel2Dir = filename:dirname(Rel2),
@@ -1416,7 +1680,7 @@ upgrade_supervisor_fail(Conf) when is_list(Conf) ->
%% Create the releases
Lib1 = [{a,"1.0",LibDir}],
Lib2 = [{a,"9.1",LibDir}],
- Rel1 = create_and_install_fake_first_release(Dir,Lib1),
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,Lib1),
Rel2 = create_fake_upgrade_release(Dir,"2",Lib2,{[Rel1],[Rel1],[LibDir]}),
Rel1Dir = filename:dirname(Rel1),
Rel2Dir = filename:dirname(Rel2),
@@ -1814,15 +2078,34 @@ upgrade_gg(Conf) ->
%% start gg2 and gg6
[Gg2,Gg6] = start_nodes(Conf,[Gg2Sname,Gg6Sname],"upgrade_gg start gg2/gg6"),
+ %% Watch dog pulling out some more information in case we hang...
+ Nodes3 = [Gg1,Gg2,Gg4,Gg5,Gg6],
+ Tester = self(),
+ WD = spawn_link(fun () ->
+ receive after 7*60*1000 -> ok end,
+ ct:pal("7 minutes passed...~n", []),
+ erlang:suspend_process(Tester),
+ load_suite(Nodes3),
+ dump_info([node()|Nodes3]),
+ exit(operation_hang)
+ end),
+
%% reg proc on each of the nodes
ok = rpc:call(Gg2, installer, reg_proc, [reg2]),
ok = rpc:call(Gg6, installer, reg_proc, [reg6]),
- are_names_reg_gg(Gg1, [reg1, reg2, reg4, reg5, reg6]),
%% Check global group info
- Nodes3 = [Gg1,Gg2,Gg4,Gg5,Gg6],
[check_gg_info(Node,Nodes3,[],Nodes3--[Node]) || Node <- Nodes3],
+ OkList = lists:map(fun (_) -> ok end, Nodes3),
+ {OkList,[]} = rpc:multicall(Nodes3, global, sync, []),
+
+ are_names_reg_gg(Gg1, [reg1, reg2, reg4, reg5, reg6]),
+
+ unlink(WD),
+ exit(WD, kill),
+ false = is_process_alive(WD),
+
ok.
upgrade_gg(cleanup,Config) ->
@@ -1830,6 +2113,53 @@ upgrade_gg(cleanup,Config) ->
NodeNames = [node_name(Sname) || Sname <- Snames],
ok = stop_nodes(NodeNames).
+load_suite(Nodes) ->
+ {ok,Bin}=file:read_file(code:which(?MODULE)),
+ _ = rpc:multicall(Nodes, erlang, load_module, [?MODULE, Bin]),
+ ok.
+
+dump_info(Nodes) ->
+ GetLockerState = fun (TheLocker) ->
+ Mon = erlang:monitor(process, TheLocker),
+ TheLocker ! {get_state, self(), Mon},
+ receive
+ Msg when element(1, Msg) =:= Mon ->
+ erlang:demonitor(Mon, [flush]),
+ RList = tl(erlang:tuple_to_list(Msg)),
+ erlang:list_to_tuple([state | RList]);
+ {'DOWN', Mon, process, TheLocker, Reason} ->
+ {error, Reason}
+ after 60*1000 ->
+ erlang:demonitor(Mon, [flush]),
+ {error, timeout}
+ end
+ end,
+ GI = rpc:multicall(Nodes,
+ erlang,
+ apply,
+ [fun () ->
+ GlobalLocker = global:get_locker(),
+ {node(),
+ #{global_state => global:info(),
+ global_dict => process_info(whereis(global_name_server), dictionary),
+ global_locks_tab => ets:tab2list(global_locks),
+ global_names_tab => ets:tab2list(global_names),
+ global_names_ext_tab => ets:tab2list(global_names_ext),
+ global_pid_names_tab => ets:tab2list(global_pid_names),
+ global_pid_ids_tab => ets:tab2list(global_pid_ids),
+ global_lost_connections_tab => ets:tab2list(global_lost_connections),
+ global_node_resources_tag => ets:tab2list(global_node_resources),
+ global_locker_state => GetLockerState(GlobalLocker),
+ global_locker_info => process_info(GlobalLocker,
+ [status,
+ current_stacktrace,
+ messages,
+ dictionary]),
+ global_group_info => global_group:info()}}
+ end,
+ []],
+ 2*60*1000),
+ ct:pal("GI: ~p~n", [GI]).
%%%-----------------------------------------------------------------
%%% OTP-10463, Bug - release_handler could not handle regexp in appup
@@ -1926,7 +2256,7 @@ unicode_upgrade(Conf) ->
%% Create the releases
RelName = "unicode_rel_αβ",
- Rel1 = create_and_install_fake_first_release(Dir,{RelName,"1"},
+ Rel1 = create_and_install_fake_first_release(Conf,Dir,{RelName,"1"},
[{u,"1.0",LibDir}]),
Rel2 = create_fake_upgrade_release(Dir,
{RelName,"2"},
@@ -2241,7 +2571,7 @@ copy_tree(Conf, Src, NewName, DestDir) ->
TempTarName = filename:join(PrivDir, "temp_tar_file.tar"),
%% Not compressing tar file here since that would increase test
%% suite time by almost 100%, and the tar file is deleted
- %% imediately anyway.
+ %% immediately anyway.
{ok,Tar} = erl_tar:open(TempTarName, [write]),
ok = erl_tar:add(Tar, Src, NewName, []),
ok = erl_tar:close(Tar),
@@ -2405,6 +2735,17 @@ create_p1g(Conf,TargetDir) ->
filename:join([DataDir,lib,"installer-1.0",ebin])),
copy_file(filename:join(DataDir, "../rh_test_lib.beam"),
filename:join([DataDir,lib,"installer-1.0",ebin])),
+ copy_file(filename:join(DataDir, "../otp_vsns.beam"),
+ filename:join([DataDir,lib,"installer-1.0",ebin])),
+
+ InstPrivDir = filename:join([DataDir,lib,"installer-1.0","priv"]),
+ case file:read_file_info(InstPrivDir) of
+ {ok, _} ->
+ ok;
+ _ ->
+ ok = file:make_dir(InstPrivDir)
+ end,
+ copy_file(filename:join(DataDir, "../otp_versions.table"), InstPrivDir),
%% Create .rel, .script and .boot files
RelName = "rel0",
@@ -2583,48 +2924,31 @@ check_gg_info(Node,OtherAlive,OtherDead,Synced) ->
check_gg_info(Node,OtherAlive,OtherDead,Synced,N) ->
GGI = rpc:call(Node, global_group, info, []),
- GI = rpc:call(Node, global, info,[]),
- try do_check_gg_info(OtherAlive,OtherDead,Synced,GGI,GI)
- catch _:E:Stacktrace when N==0 ->
+ try do_check_gg_info(OtherAlive,OtherDead,Synced,GGI)
+ catch _:E:Stacktrace ->
test_server:format("~nERROR: check_gg_info failed for ~p:~n~p~n"
- "when GGI was: ~p~nand GI was: ~p~n",
- [Node,{E,Stacktrace},GGI,GI]),
- ct:fail("check_gg_info failed");
- _:E:Stacktrace ->
- test_server:format("~nWARNING: check_gg_info failed for ~p:~n~p~n"
- "when GGI was: ~p~nand GI was: ~p~n",
- [Node,{E,Stacktrace},GGI,GI]),
- timer:sleep(1000),
- check_gg_info(Node,OtherAlive,OtherDead,Synced,N-1)
+ "when GGI was: ~p~n",
+ [Node,{E,Stacktrace},GGI]),
+ if N == 0 ->
+ ct:fail("check_gg_info failed");
+ true ->
+ ok = rpc:call(Node, global_group, sync, []),
+ timer:sleep(1000),
+ check_gg_info(Node,OtherAlive,OtherDead,Synced,N-1)
+ end
end.
-do_check_gg_info(OtherAlive,OtherDead,Synced,GGI,GI) ->
+do_check_gg_info(OtherAlive,OtherDead,Synced,GGI) ->
{_,gg1} = lists:keyfind(own_group_name,1,GGI),
{_,synced} = lists:keyfind(state,1,GGI),
{_,AllNodes} = lists:keyfind(own_group_nodes,1,GGI),
true = lists:sort(AllNodes) =:= lists:sort(OtherAlive++OtherDead),
{_,[]} = lists:keyfind(sync_error,1,GGI),
{_,[{gg2,[_,_]}]} = lists:keyfind(other_groups,1,GGI),
-
- %% There is a known bug in global_group (OTP-9177) which causes
- %% the following to fail every now and then:
- %% {_,SyncedNodes} = lists:keyfind(synced_nodes,1,GGI),
- %% true = lists:sort(SyncedNodes) =:= lists:sort(Synced),
- %% {_,NoContact} = lists:keyfind(no_contact,1,GGI),
- %% true = lists:sort(NoContact) =:= lists:sort(OtherDead),
-
- %% Therefore we use global:info instead for this part
- {state,_,_,SyncedNodes,_,_,_,_,_,_,_} = GI,
+ {_,SyncedNodes} = lists:keyfind(synced_nodes,1,GGI),
true = lists:sort(SyncedNodes) =:= lists:sort(Synced),
-
- %% .. and we only check that all OtherDead are listed as
- %% no_contact (due to th bug there might be more nodes in this
- %% list)
{_,NoContact} = lists:keyfind(no_contact,1,GGI),
- true =
- lists:sort(OtherDead) =:=
- lists:sort([NC || NC <- NoContact,lists:member(NC,OtherDead)]),
-
+ true = lists:sort(NoContact) =:= lists:sort(OtherDead),
ok.
%% Return the configuration (to be inserted in sys.config) for global group tests
@@ -2650,7 +2974,7 @@ permanent_p1h(Node) ->
ok = rpc_inst(Node, permanent_p1h, []).
%% For each node in ToNodes, create a target installation which is
-%% indentical to the target installation for FromNode.
+%% identical to the target installation for FromNode.
copy_installed(Conf,FromNode,ToNodes) ->
PrivDir = priv_dir(Conf),
DataDir = ?config(data_dir,Conf),
@@ -2832,9 +3156,9 @@ cover_fun(Node,Func) ->
%% current running OTP release. It includes kernel, stdlib and sasl,
%% and possibly other applications if they are listed in AppDirs =
%% [{App,Vsn,LibDir}]
-create_and_install_fake_first_release(Dir,AppDirs) ->
- create_and_install_fake_first_release(Dir,init:script_id(),AppDirs).
-create_and_install_fake_first_release(Dir,{RelName,RelVsn},AppDirs) ->
+create_and_install_fake_first_release(Conf,Dir,AppDirs) ->
+ create_and_install_fake_first_release(Conf,Dir,init:script_id(),AppDirs).
+create_and_install_fake_first_release(Conf,Dir,{RelName,RelVsn},AppDirs) ->
{Rel,_} = create_fake_release(Dir,RelName,RelVsn,AppDirs),
ReleasesDir = filename:join(Dir, "releases"),
RelDir = filename:dirname(Rel),
@@ -2847,13 +3171,21 @@ create_and_install_fake_first_release(Dir,{RelName,RelVsn},AppDirs) ->
ok = copy_file(Rel++".boot",filename:join(RelVsnDir, "start.boot")),
ok = copy_file(filename:join(RelDir,"sys.config"),RelVsnDir),
- ok = release_handler:create_RELEASES(code:root_dir(),
- ReleasesDir,
- Rel++".rel",
- AppDirs),
-
+ case proplists:get_value(root_dir, Conf, relative) of
+ relative ->
+ ok = release_handler:create_RELEASES(
+ ReleasesDir,
+ Rel++".rel",
+ AppDirs);
+ absolute ->
+ ok = release_handler:create_RELEASES(
+ code:root_dir(),
+ ReleasesDir,
+ Rel++".rel",
+ AppDirs)
+ end,
Rel.
-
+
%% This function create a new release, including a relup file. It can
%% be upgraded to from the release created by
%% create_and_install_fake_first_release/2. Unpack first by calls to
@@ -2940,9 +3272,7 @@ modify_tar_win32(Conf, TarFileName) ->
app_dir(App,Vsn) ->
atom_to_list(App) ++ "-" ++ vsn(App,Vsn).
-vsn(erts,old) -> ?ertsvsn;
-vsn(kernel,old) -> ?kernelvsn;
-vsn(stdlib,old) -> ?stdlibvsn;
+vsn(App,old) -> rh_test_lib:old_app_vsn(App);
vsn(erts,current) -> erlang:system_info(version);
vsn(App,current) ->
{ok,Vsn} = application:get_key(App,vsn),
@@ -2950,3 +3280,20 @@ vsn(App,current) ->
system_lib(PrivDir) ->
filename:join(PrivDir,"system_lib").
+
+copy_r(Src, Dst) ->
+ {ok,S} = file:read_file_info(Src),
+ case S#file_info.type of
+ directory ->
+ {ok,Names} = file:list_dir(Src),
+ ok = filelib:ensure_dir(Dst),
+ ok = file:make_dir(Dst),
+ lists:foreach(
+ fun(Name) ->
+ copy_r(filename:join(Src, Name),
+ filename:join(Dst, Name))
+ end, Names);
+ _ ->
+ {ok,_NumBytesCopied} = file:copy(Src, Dst),
+ ok = file:write_file_info(Dst, S)
+ end.
diff --git a/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
index e1391c0605..b1622307bb 100644
--- a/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
+++ b/lib/sasl/test/release_handler_SUITE_data/lib/installer-1.0/ebin/installer.app
@@ -1,6 +1,6 @@
{application, installer,
[{description, "Installer application"},
{vsn, "1.0"},
- {modules, [installer,rh_test_lib]},
+ {modules, [installer,rh_test_lib,otp_vsns]},
{registered, []},
{applications, [kernel, stdlib, sasl]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-A.rel.src b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-A.rel.src
new file mode 100644
index 0000000000..8b8ec2eff6
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-A.rel.src
@@ -0,0 +1,8 @@
+{release,
+ {"hello_server", "A"},
+ {erts, "%erts_VSN%"},
+ [{kernel, "%kernel_VSN%"},
+ {stdlib, "%stdlib_VSN%"},
+ {sasl, "%sasl_VSN%"},
+ {hello_server, "A"}]
+}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-B.rel.src b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-B.rel.src
new file mode 100644
index 0000000000..c966ad48ec
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server-B.rel.src
@@ -0,0 +1,8 @@
+{release,
+ {"hello_server", "B"},
+ {erts, "%erts_VSN%"},
+ [{kernel, "%kernel_VSN%"},
+ {stdlib, "%stdlib_VSN%"},
+ {sasl, "%sasl_VSN%"},
+ {hello_server, "B"}]
+}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/Emakefile b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/Emakefile
new file mode 100644
index 0000000000..8e1f951aee
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/Emakefile
@@ -0,0 +1,2 @@
+{"src/*", [debug_info, {i,"include/"}, {outdir, "ebin/"}]}.
+{"test/*", [debug_info, {i,"include/"}, {outdir, "ebin/"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/.gitignore b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/.gitignore
new file mode 100644
index 0000000000..1ef2775ff8
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/.gitignore
@@ -0,0 +1 @@
+*.beam \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/hello_server.app b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/hello_server.app
new file mode 100644
index 0000000000..697bd7add4
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/ebin/hello_server.app
@@ -0,0 +1,7 @@
+{application, hello_server,
+ [{description, "Simple server that sends back hello"},
+ {vsn, "A"},
+ {modules, [app_callback_module, hello_server]},
+ {registered, [hello_server]},
+ {applications, [kernel, stdlib, sasl]},
+ {mod, {app_callback_module,[]}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/app_callback_module.erl b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/app_callback_module.erl
new file mode 100644
index 0000000000..0d988ab8f6
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/app_callback_module.erl
@@ -0,0 +1,26 @@
+-module(app_callback_module).
+
+-behaviour(application).
+
+-export([start/2, stop/1, get_response/0, update/0]).
+
+start(_Type, _Args) ->
+ Pid = hello_server:start_server(),
+ global:register_name(hello_server, Pid),
+ {ok, Pid}.
+
+update() ->
+ global:whereis_name(hello_server) ! update,
+ ok.
+
+get_response() ->
+ global:whereis_name(hello_server) ! self(),
+ receive
+ A ->
+ A
+ end.
+
+stop(_State) ->
+ Pid = global:whereis_name(hello_server),
+ hello_server:stop(Pid),
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/hello_server.erl b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/hello_server.erl
new file mode 100644
index 0000000000..1008e1f4e2
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server/src/hello_server.erl
@@ -0,0 +1,20 @@
+-module(hello_server).
+
+-export([start_server/0, stop/1, loop/0]).
+
+start_server() ->
+ erlang:spawn_link(?MODULE, loop, []).
+
+stop(Pid) ->
+ Pid ! stop.
+
+loop() ->
+ receive
+ stop ->
+ ok;
+ update ->
+ ?MODULE:loop();
+ Sender ->
+ Sender ! hello,
+ loop()
+ end.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/Emakefile b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/Emakefile
new file mode 100644
index 0000000000..8e1f951aee
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/Emakefile
@@ -0,0 +1,2 @@
+{"src/*", [debug_info, {i,"include/"}, {outdir, "ebin/"}]}.
+{"test/*", [debug_info, {i,"include/"}, {outdir, "ebin/"}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/.gitignore b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/.gitignore
new file mode 100644
index 0000000000..1ef2775ff8
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/.gitignore
@@ -0,0 +1 @@
+*.beam \ No newline at end of file
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.app b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.app
new file mode 100644
index 0000000000..1e1426344b
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.app
@@ -0,0 +1,7 @@
+{application, hello_server,
+ [{description, "Simple server that sends back hej"},
+ {vsn, "B"},
+ {modules, [app_callback_module, hello_server]},
+ {registered, [hello_server]},
+ {applications, [kernel, stdlib, sasl]},
+ {mod, {app_callback_module,[]}}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.appup b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.appup
new file mode 100644
index 0000000000..1aa16cd39c
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/ebin/hello_server.appup
@@ -0,0 +1,3 @@
+{"B",
+ [{"A", [{load_module, hello_server}]}],
+ [{"A", [{load_module, hello_server}]}]}.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/app_callback_module.erl b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/app_callback_module.erl
new file mode 100644
index 0000000000..0d988ab8f6
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/app_callback_module.erl
@@ -0,0 +1,26 @@
+-module(app_callback_module).
+
+-behaviour(application).
+
+-export([start/2, stop/1, get_response/0, update/0]).
+
+start(_Type, _Args) ->
+ Pid = hello_server:start_server(),
+ global:register_name(hello_server, Pid),
+ {ok, Pid}.
+
+update() ->
+ global:whereis_name(hello_server) ! update,
+ ok.
+
+get_response() ->
+ global:whereis_name(hello_server) ! self(),
+ receive
+ A ->
+ A
+ end.
+
+stop(_State) ->
+ Pid = global:whereis_name(hello_server),
+ hello_server:stop(Pid),
+ ok.
diff --git a/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/hello_server.erl b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/hello_server.erl
new file mode 100644
index 0000000000..d40309457a
--- /dev/null
+++ b/lib/sasl/test/release_handler_SUITE_data/relocatable_release/hello_server_new/src/hello_server.erl
@@ -0,0 +1,20 @@
+-module(hello_server).
+
+-export([start_server/0, stop/1, loop/0]).
+
+start_server() ->
+ erlang:spawn_link(?MODULE, loop, []).
+
+stop(Pid) ->
+ Pid ! stop.
+
+loop() ->
+ receive
+ stop ->
+ ok;
+ update ->
+ ?MODULE:loop();
+ Sender ->
+ Sender ! hej,
+ loop()
+ end.
diff --git a/lib/sasl/test/rh_test_lib.erl b/lib/sasl/test/rh_test_lib.erl
index 6425fce7a7..dba45bece6 100644
--- a/lib/sasl/test/rh_test_lib.erl
+++ b/lib/sasl/test/rh_test_lib.erl
@@ -12,13 +12,15 @@
-export([clean_dir/1,
clean_dir/2]).
+-export([old_app_vsn/1]).
+
-include_lib("kernel/include/file.hrl").
cmd(Cmd,Args,Env) ->
case open_port({spawn_executable, Cmd}, [{args,Args},{env,Env}]) of
Port when is_port(Port) ->
unlink(Port),
- catch erlang:port_close(Port), % migth already be closed, so catching
+ catch erlang:port_close(Port), % might already be closed, so catching
ok;
Error ->
Error
@@ -160,3 +162,23 @@ rm_rf([File|Files],Save) ->
end;
rm_rf([],_) ->
ok.
+
+old_app_vsn(App) ->
+ %% Get oldest application version (erts, kernel, sasl,
+ %% stdlib) we support upgrade from, i.e., the first
+ %% application version in the release two releases
+ %% prior to current release...
+ State = case get('__otp_vsns_state__') of
+ undefined ->
+ S = otp_vsns:read_state(),
+ put('__otp_vsns_state__', S),
+ S;
+ S ->
+ S
+ end,
+ Rel = integer_to_list(list_to_integer(erlang:system_info(otp_release))-2),
+ AppVsn = otp_vsns:app_vsn(State, "OTP-"++Rel++".0", atom_to_list(App)),
+ [_, Vsn] = string:lexemes(AppVsn, "-"),
+ Vsn.
+
+
diff --git a/lib/sasl/test/sasl_SUITE.erl b/lib/sasl/test/sasl_SUITE.erl
index 1b377db903..bbebce83ae 100644
--- a/lib/sasl/test/sasl_SUITE.erl
+++ b/lib/sasl/test/sasl_SUITE.erl
@@ -32,7 +32,7 @@
log_file/1,
utc_log/1]).
--compile(r21).
+-compile(r22).
all() ->
[log_mf_h_env, log_file, app_test, appup_test, utc_log].
@@ -60,6 +60,19 @@ end_per_group(_GroupName, Config) ->
Config.
+init_per_testcase(appup_test, Config) ->
+ %% We check if the test results were released using a version
+ %% of Erlang/OTP that was a tagged version or not. On a non-tagged
+ %% version this testcase most likely will fail.
+ case file:read_file(
+ filename:join(
+ proplists:get_value(data_dir,Config), "otp_version_tickets")) of
+ {ok,<<"DEVELOPMENT",_/binary>>} ->
+ {skip, "This is a development version, test might fail "
+ "because of incorrect version numbers"};
+ {ok,S} ->
+ Config
+ end;
init_per_testcase(_Case, Config) ->
Config.
end_per_testcase(_Case, _Config) ->
@@ -74,8 +87,6 @@ app_test(Config) when is_list(Config) ->
appup_test(_Config) ->
appup_tests(sasl,create_test_vsns(sasl)).
-appup_tests(_App,{[],[]}) ->
- {skip,"no previous releases available"};
appup_tests(App,{OkVsns0,NokVsns}) ->
application:load(App),
{_,_,Vsn} = lists:keyfind(App,1,application:loaded_applications()),
@@ -88,8 +99,7 @@ appup_tests(App,{OkVsns0,NokVsns}) ->
OkVsns0 ->
OkVsns0;
Ok ->
- ct:log("Current version, ~p, is same as in previous release.~n"
- "Removing this from the list of ok versions.",
+ ct:log("Removed current version ~p from the list of ok versions to test.",
[Vsn]),
Ok
end,
@@ -104,57 +114,46 @@ appup_tests(App,{OkVsns0,NokVsns}) ->
ok.
create_test_vsns(App) ->
- ThisMajor = erlang:system_info(otp_release),
- FirstMajor = previous_major(ThisMajor),
- SecondMajor = previous_major(previous_major(FirstMajor)),
- Ok = app_vsn(App,[ThisMajor,FirstMajor]),
- Nok0 = app_vsn(App,[SecondMajor]),
+ S = otp_vsns:read_state(),
+ Rel = list_to_integer(erlang:system_info(otp_release)),
+ AppStr = atom_to_list(App),
+ Ok = ok_app_vsns(S, Rel, AppStr),
+ Nok0 = nok_app_vsns(S, Rel, AppStr, hd(Ok)),
Nok = case Ok of
- [Ok1|_] ->
- [Ok1 ++ ",1" | Nok0]; % illegal
- _ ->
- Nok0
- end,
- {Ok,Nok}.
-
-previous_major("17") ->
- "r16b";
-previous_major("r16b") ->
- "r15b";
-previous_major(Rel) ->
- integer_to_list(list_to_integer(Rel)-1).
-
-app_vsn(App,[R|Rs]) ->
- OldRel =
- case test_server:is_release_available(R) of
- true ->
- {release,R};
- false ->
- case ct:get_config({otp_releases,list_to_atom(R)}) of
- undefined ->
- false;
- Prog0 ->
- case os:find_executable(Prog0) of
- false ->
- false;
- Prog ->
- {prog,Prog}
- end
- end
- end,
- case OldRel of
- false ->
- app_vsn(App,Rs);
- _ ->
- {ok,N} = test_server:start_node(prevrel,peer,[{erl,[OldRel]}]),
- _ = rpc:call(N,application,load,[App]),
- As = rpc:call(N,application,loaded_applications,[]),
- {_,_,V} = lists:keyfind(App,1,As),
- test_server:stop_node(N),
- [V|app_vsn(App,Rs)]
- end;
-app_vsn(_App,[]) ->
- [].
+ [Ok1|_] ->
+ [Ok1 ++ ",1" | Nok0]; % illegal
+ _ ->
+ Nok0
+ end,
+ {Ok, Nok}.
+
+ok_app_vsns(S, Rel, AppStr) ->
+ AppVsns0 = get_rel_app_vsns(S, Rel-2, AppStr),
+ AppVsns1 = get_rel_app_vsns(S, Rel-1, AppStr),
+ AppVsns2 = try
+ get_rel_app_vsns(S, Rel, AppStr)
+ catch
+ _:_ -> []
+ end,
+ lists:usort(AppVsns2 ++ AppVsns1 ++ AppVsns0).
+
+nok_app_vsns(S, Rel, AppStr, EarliestOkVsn) ->
+ AppVsns0 = get_rel_app_vsns(S, Rel-4, AppStr),
+ AppVsns1 = get_rel_app_vsns(S, Rel-3, AppStr),
+ %% Earliest OK version may exist in not OK versions
+ %% as well if there were no application version bump
+ %% between two releases, so we need to remove it
+ %% if that is the case...
+ lists:usort(AppVsns1 ++ AppVsns0) -- EarliestOkVsn.
+
+get_rel_app_vsns(S, Rel, App) ->
+ RelStr = integer_to_list(Rel),
+ OtpVsns = otp_vsns:branch_vsns(S, "maint-"++RelStr),
+ lists:map(fun (OtpVsn) ->
+ AppVsn = otp_vsns:app_vsn(S, OtpVsn, App),
+ [_, Vsn] = string:lexemes(AppVsn, "-"),
+ Vsn
+ end, OtpVsns).
check_appup([Vsn|Vsns],Instrs,Expected) ->
case systools_relup:appup_search_for_version(Vsn, Instrs) of
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index 42672358c0..fb607d02ca 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -95,12 +95,8 @@ gen_server_crash(Config, Encoding, FormatterOpts, Min, Max) ->
ok = file:write_file(ConfigFileName ++ ".config",
io_lib:format("[{kernel, ~p},~n{sasl, ~p}].",
[KernelConfig,SaslConfig])),
- {ok,Node} =
- test_server:start_node(
- TC, peer,
- [{args, ["-pa ",filename:dirname(code:which(?MODULE)),
- " -boot start_sasl -kernel start_timer true "
- "-config ",ConfigFileName]}]),
+ {ok,Peer,Node} = ?CT_PEER(["-boot", "start_sasl", "-kernel", "start_timer", "true",
+ "-config", ConfigFileName]),
%% Set depth or chars_limit.
ok = rpc:call(Node,logger,update_formatter_config,[default,FormatterOpts]),
@@ -126,7 +122,7 @@ gen_server_crash(Config, Encoding, FormatterOpts, Min, Max) ->
ok = rpc:call(Node,logger_std_h,filesync,[default]),
ok = rpc:call(Node,logger_std_h,filesync,[sasl]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok = logger:remove_primary_filter(no_remote),
check_file(KernelLog, utf8, Min, Max),
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index ef863581a5..801660ddac 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -106,6 +106,9 @@ init_per_suite(Config) when is_list(Config) ->
%% Compile source files in the copy directory.
Sources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*.erl'])),
lists:foreach(fun compile_source/1, Sources),
+ %% Deal with subdirectories, if any
+ SubSources = filelib:wildcard(fname([CopyDir,'*','*','*','*','*','*.erl'])),
+ lists:foreach(fun compile_subsource/1, SubSources),
[{copy_dir, CopyDir}, {cwd,Cwd}, {path,Path} | Config].
@@ -122,6 +125,16 @@ compile_source(File) ->
ok = file:write_file(OutFileTemp, Code),
file:rename(OutFileTemp, OutFile).
+compile_subsource(File) ->
+ %% Same as compile_source/1 but works a subdirectory lower
+ U = filename:dirname(filename:dirname(filename:dirname(File))),
+ Base = filename:rootname(filename:basename(File)),
+ OutFile = filename:join([U,"ebin",Base++".beam"]),
+ OutFileTemp = OutFile ++ "#",
+ {ok,_,Code} = compile:file(File, [binary]),
+ ok = file:write_file(OutFileTemp, Code),
+ file:rename(OutFileTemp, OutFile).
+
end_per_suite(Config) when is_list(Config) ->
rh_test_lib:clean_dir(?privdir),
Config.
@@ -278,9 +291,7 @@ unicode_script(Config) when is_list(Config) ->
%% Need to do this on a separate node to make sure it has unicode
%% filename mode (+fnu*)
- {ok,HostStr} = inet:gethostname(),
- Host = list_to_atom(HostStr),
- {ok,Node} = ct_slave:start(Host,unicode_script_node,[{erl_flags,"+fnui"}]),
+ {ok,Peer,Node} = ?CT_PEER(["+fnui"]),
ok = rpc:call(Node,erl_tar,extract,
[TarFile, [{cwd,UnicodeLibDir},compressed]]),
@@ -313,10 +324,11 @@ unicode_script(Config) when is_list(Config) ->
rpc:call(Node,code,add_pathz,[filename:dirname(code:which(?MODULE))]),
rpc:call(Node,?MODULE,delete_tree,[UnicodeLibDir]),
+ peer:stop(Peer),
+
ok.
unicode_script(cleanup,Config) ->
- _ = ct_slave:stop(unicode_script_node),
file:delete(fname(?privdir, "unicode_app.tgz")),
ok.
@@ -1386,7 +1398,7 @@ src_tests_tar(Config) when is_list(Config) ->
%% 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.
+%% Test the {var_tar, include | ownfile | omit} option.
var_tar(Config) when is_list(Config) ->
{ok, OldDir} = file:get_cwd(),
PSAVE = code:get_path(), % Save path
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
index a1025c306a..28d0f80d34 100644
--- a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/ebin/db.app
@@ -1,7 +1,7 @@
{application, db,
[{description, "ERICSSON NR FOR DB"},
{vsn, "2.1"},
- {modules, [db1, db2]},
+ {modules, [db1, db2, db3]},
{registered, []},
{applications, []},
{env, []},
diff --git a/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl
new file mode 100644
index 0000000000..010249638f
--- /dev/null
+++ b/lib/sasl/test/systools_SUITE_data/d_missing_src/lib/db-2.1/src/sub/db3.erl
@@ -0,0 +1,3 @@
+-module(db3).
+-vsn("1.0").
+
diff --git a/lib/sasl/test/test_lib.hrl b/lib/sasl/test/test_lib.hrl
deleted file mode 100644
index 6f02666b87..0000000000
--- a/lib/sasl/test/test_lib.hrl
+++ /dev/null
@@ -1,3 +0,0 @@
--define(ertsvsn,"10.4").
--define(kernelvsn,"6.4").
--define(stdlibvsn,"3.9").
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index c38e64d0a9..0fbf91bf53 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 4.1.2
+SASL_VSN = 4.2
diff --git a/lib/snmp/.gitignore b/lib/snmp/.gitignore
index aef73491a4..9f3a9a2331 100644
--- a/lib/snmp/.gitignore
+++ b/lib/snmp/.gitignore
@@ -6,3 +6,7 @@
doc/index.html
mibs/.index
+
+# Agent
+src/agent/Makefile
+
diff --git a/lib/snmp/bin/snmp-v2tov1.pl b/lib/snmp/bin/snmp-v2tov1.pl
index f9ecfc9dd8..6f1e73087d 100644
--- a/lib/snmp/bin/snmp-v2tov1.pl
+++ b/lib/snmp/bin/snmp-v2tov1.pl
@@ -64,7 +64,7 @@ line: while (<>) {
next line;
}
- # Translate TEXTUAL-CONVENTION into an ordinary type assignement.
+ # Translate TEXTUAL-CONVENTION into an ordinary type assignment.
# Place comments around body.
if (/TEXTUAL-CONVENTION/ && ($str == 0)) {
$textual = 1;
diff --git a/lib/snmp/configure b/lib/snmp/configure
index 65d95918cc..a907ba26b2 100755
--- a/lib/snmp/configure
+++ b/lib/snmp/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,41 +167,52 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -227,14 +220,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -252,18 +252,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -290,6 +291,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -307,6 +309,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -321,7 +331,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -330,7 +340,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -369,12 +379,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -386,18 +397,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -409,9 +429,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -438,7 +458,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -482,7 +502,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -496,6 +516,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -509,6 +533,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -574,17 +605,22 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
-
-ac_unique_file="vsn.mk"
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="src/app/snmp.app.src"
ac_subst_vars='LTLIBOBJS
LIBOBJS
+SNMP_EMPTY_PDU_SIZE_DEFAULT
PERL
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -635,6 +671,7 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+with_snmp_empty_pdu_size
'
ac_precious_vars='build_alias
host_alias
@@ -707,8 +744,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -749,9 +784,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -775,9 +810,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -988,9 +1023,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1004,9 +1039,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1050,9 +1085,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1068,7 +1103,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1132,7 +1167,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1250,6 +1285,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1257,6 +1293,13 @@ if test -n "$ac_init_help"; then
cat <<\_ACEOF
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-snmp-empty-pdu-size=SZ
+ Empty pdu size, in number of bytes >= 21; default is
+ 21
+
Report bugs to the package provider.
_ACEOF
ac_status=$?
@@ -1273,9 +1316,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1303,7 +1346,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1311,7 +1355,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1321,9 +1365,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1333,14 +1377,34 @@ fi
## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -1373,8 +1437,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -1409,7 +1477,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -1444,11 +1512,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -1459,8 +1529,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -1484,7 +1554,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -1492,14 +1562,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -1507,15 +1577,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -1523,8 +1593,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -1538,69 +1608,152 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
done
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -1611,12 +1764,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -1625,24 +1778,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -1652,11 +1805,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -1670,57 +1824,126 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in ${ERL_TOP}/erts/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in ${ERL_TOP}/erts/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -1739,21 +1962,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -1772,20 +1996,116 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
+fi
+
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_PERL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_PERL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$PERL"; then
ac_cv_prog_PERL="$PERL" # Let the user override the test.
else
@@ -1793,11 +2113,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_PERL="perl"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -1809,11 +2133,11 @@ fi
fi
PERL=$ac_cv_prog_PERL
if test -n "$PERL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
-$as_echo "$PERL" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
+printf "%s\n" "$PERL" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -1822,8 +2146,34 @@ if test "$PERL" = no_perl; then
fi
+
+
+
+# Check whether --with-snmp-empty-pdu-size was given.
+if test ${with_snmp_empty_pdu_size+y}
+then :
+ withval=$with_snmp_empty_pdu_size;
+else $as_nop
+ with_snmp_empty_pdu_size=21
+fi
+
+
+if test $with_snmp_empty_pdu_size -lt 21; then
+ SNMP_EMPTY_PDU_SIZE_DEFAULT=21
+ as_fn_error $? "Minimum size of 'empty pdu size' is 21" "$LINENO" 5
+else
+ SNMP_EMPTY_PDU_SIZE_DEFAULT=$with_snmp_empty_pdu_size
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Default (snmp) empty pdu size set to $with_snmp_empty_pdu_size" >&5
+printf "%s\n" "$as_me: Default (snmp) empty pdu size set to $with_snmp_empty_pdu_size" >&6;}
+fi
+
+
+
+
ac_config_files="$ac_config_files mibs/Makefile:mibs/Makefile.in"
+ac_config_files="$ac_config_files src/agent/Makefile:src/agent/Makefile.in"
+
test "x$prefix" = xNONE && prefix=$ac_default_prefix
@@ -1874,7 +2224,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -1890,8 +2240,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -1914,14 +2264,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -1931,46 +2283,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -1979,13 +2331,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -1994,8 +2339,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -2007,30 +2356,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -2043,13 +2372,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -2076,18 +2406,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -2099,12 +2431,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -2135,7 +2468,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -2157,6 +2490,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -2170,6 +2507,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -2211,7 +2554,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -2220,7 +2563,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -2283,7 +2626,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -2332,14 +2675,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -2376,21 +2721,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -2418,7 +2763,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -2432,7 +2777,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -2446,6 +2791,7 @@ for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"mibs/Makefile") CONFIG_FILES="$CONFIG_FILES mibs/Makefile:mibs/Makefile.in" ;;
+ "src/agent/Makefile") CONFIG_FILES="$CONFIG_FILES src/agent/Makefile:src/agent/Makefile.in" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
@@ -2457,7 +2803,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -2685,7 +3031,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -2693,17 +3039,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -2720,7 +3066,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -2744,9 +3090,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -2799,8 +3145,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -2842,9 +3188,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -2891,8 +3237,9 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/lib/snmp/configure.ac b/lib/snmp/configure.ac
new file mode 100644
index 0000000000..8f4c1fd833
--- /dev/null
+++ b/lib/snmp/configure.ac
@@ -0,0 +1,71 @@
+dnl Process this file with autoconf to produce a configure script. -*-m4-*-
+dnl
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 2021-2022. All Rights Reserved.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+dnl
+dnl %CopyrightEnd%
+dnl
+
+
+define([AC_CACHE_LOAD], )dnl
+define([AC_CACHE_SAVE], )dnl
+
+AC_INIT
+AC_CONFIG_SRCDIR([src/app/snmp.app.src])
+AC_PREREQ([2.71])
+
+m4_include([otp.m4])
+
+AC_CONFIG_AUX_DIRS([${ERL_TOP}/make/autoconf])
+
+dnl ----------------------------------------------------------------------
+dnl Checks for programs.
+dnl ----------------------------------------------------------------------
+
+ERL_CANONICAL_SYSTEM_TYPE
+
+AC_CHECK_PROG(PERL, perl, perl, no_perl)
+if test "$PERL" = no_perl; then
+ AC_MSG_ERROR([Perl is required to generate v2 to v1 mib converter script])
+fi
+
+
+dnl ----------------------------------------------------------------------
+
+dnl *** SNMP_EMPTY_PDU_SIZE ***
+
+AC_ARG_WITH(snmp-empty-pdu-size,
+AS_HELP_STRING([--with-snmp-empty-pdu-size=SZ],
+ [Empty pdu size, in number of bytes >= 21; default is 21]),
+[],
+[with_snmp_empty_pdu_size=21])
+
+if test $with_snmp_empty_pdu_size -lt 21; then
+ SNMP_EMPTY_PDU_SIZE_DEFAULT=21
+ AC_MSG_ERROR([Minimum size of 'empty pdu size' is 21])
+else
+ SNMP_EMPTY_PDU_SIZE_DEFAULT=$with_snmp_empty_pdu_size
+ AC_MSG_NOTICE([Default (snmp) empty pdu size set to $with_snmp_empty_pdu_size])
+fi
+
+
+dnl ----------------------------------------------------------------------
+
+AC_SUBST(SNMP_EMPTY_PDU_SIZE_DEFAULT)
+AC_CONFIG_FILES([mibs/Makefile:mibs/Makefile.in])
+AC_CONFIG_FILES([src/agent/Makefile:src/agent/Makefile.in])
+AC_OUTPUT
+
diff --git a/lib/snmp/configure.in b/lib/snmp/configure.in
deleted file mode 100644
index bac042ccca..0000000000
--- a/lib/snmp/configure.in
+++ /dev/null
@@ -1,28 +0,0 @@
-
-define([AC_CACHE_LOAD], )dnl
-define([AC_CACHE_SAVE], )dnl
-
-AC_INIT(vsn.mk)
-
-AC_CONFIG_AUX_DIRS(${ERL_TOP}/erts/autoconf)
-
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
-
-
-dnl ----------------------------------------------------------------------
-dnl Checks for programs.
-dnl ----------------------------------------------------------------------
-
-
-AC_CHECK_PROG(PERL, perl, perl, no_perl)
-if test "$PERL" = no_perl; then
- AC_MSG_ERROR([Perl is required to generate v2 to v1 mib converter script])
-fi
-
-
-AC_OUTPUT(mibs/Makefile:mibs/Makefile.in)
-
diff --git a/lib/snmp/doc/src/files.mk b/lib/snmp/doc/src/files.mk
index 44db07230b..9670dfdca8 100644
--- a/lib/snmp/doc/src/files.mk
+++ b/lib/snmp/doc/src/files.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2001-2021. All Rights Reserved.
+# Copyright Ericsson AB 2001-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -101,6 +101,7 @@ XML_CHAPTER_FILES = \
snmp_advanced_agent.xml \
snmp_app_a.xml \
snmp_app_b.xml \
+ snmp_app_c.xml \
notes.xml
BOOK_FILES = book.xml
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index a37e57e1f3..e692ca99bb 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>2021</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,7 +34,168 @@
</header>
- <section><title>SNMP 5.12</title>
+ <section><title>SNMP 5.13.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.13.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Single threaded agent crash when vacm table not properly
+ initiated.</p>
+ <p>
+ Own Id: OTP-18379 Aux Id: ERIERL-904 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.13.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Explicitly close the socket(s) when terminating
+ (default-) net-if process.</p>
+ <p>
+ Own Id: OTP-18352 Aux Id: ERIERL-881 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>SNMP 5.13.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Single threaded agent crash when vacm table not properly
+ initiated.</p>
+ <p>
+ Own Id: OTP-18379 Aux Id: ERIERL-904 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.13.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved the get-bulk response max size calculation. Its
+ now possible to configure 'empty pdu size', see appendix
+ c for more info.</p>
+ <p>
+ Own Id: OTP-17115 Aux Id: ERIERL-456 </p>
+ </item>
+ <item>
+ <p>
+ Fix various example dialyzer issues</p>
+ <p>
+ Own Id: OTP-18180 Aux Id: ERIERL-837 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.13</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>
+ Removed deprecated functions slated for removal in
+ OTP-25. Also removed "dead" code, kept for backward
+ compatibility reasons.</p>
+ <p>
+ Own Id: OTP-17612</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>SNMP 5.12.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Single threaded agent crash when vacm table not properly
+ initiated.</p>
+ <p>
+ Own Id: OTP-18379 Aux Id: ERIERL-904 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>SNMP 5.12.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Explicitly close the socket(s) when terminating
+ (default-) net-if process.</p>
+ <p>
+ Own Id: OTP-18352 Aux Id: ERIERL-881 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.12</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -214,7 +375,7 @@
<p>
[manager] In a function handling snmp errors, an unused
result (_Error) could result in matching issues and
- therefor case clause runtime errors (crash). Note that
+ therefore case clause runtime errors (crash). Note that
this would only happen in *very* unusual error cases.</p>
<p>
Own Id: OTP-17161</p>
@@ -1074,7 +1235,7 @@
<list>
<item>
<p>
- Improved cryptocraphic capability.</p>
+ Improved cryptographic capability.</p>
<p>
Own Id: OTP-12452</p>
</item>
@@ -1330,7 +1491,7 @@
<p>Add (atl) log conversion block option. </p>
<p>It is now possible to request that the Audit Trail Log should
be blocked during conversion (<c>log_to_txt</c> or <c>log_to_io</c>).
- This could be usefull when coverting an entire large log (when
+ This could be useful when converting an entire large log (when
there is a chance it may otherwise wrap during conversion). </p>
<p>See
agent
@@ -1801,7 +1962,7 @@
<list type="bulleted">
<item>
- <p>[agent] Sematic fixes to SNMP-USER-BASED-SM-MIB.
+ <p>[agent] Semantic 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.
@@ -1910,7 +2071,7 @@
<item>
<p>[manager] Introduced a new transport module,
<c>snmpm_net_if_mt</c>,
- which handles all incomming and outgoing
+ which handles all incoming and outgoing
traffic in newly created processes. The message/request is
processed and then the process exits. </p>
<p>Own Id: OTP-9876</p>
@@ -1924,7 +2085,7 @@
<item>
<p>[agent] Improve error handling while reading agent config files.
- Some files contain mandatory information and is therefor themself
+ Some files contain mandatory information and is therefore themself
mandatory. </p>
<p>Own Id: OTP-9943</p>
</item>
@@ -2111,8 +2272,8 @@
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
+ processes in rapid succession, the dumping could fail because the
+ different processes was simultaneously 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>
@@ -2575,7 +2736,7 @@
<p>See
<seeerl marker="snmpa#send_notification2">
snmpa:send_notification2/3</seeerl> for more info.
- See also the incomming net-if messages when sending a
+ See also the incoming net-if messages when sending a
<seeguide marker="snmp_agent_netif#im_send_pdu">trap</seeguide>
(send_pdu message) and
<seeguide marker="snmp_agent_netif#im_send_pdu_req">
diff --git a/lib/snmp/doc/src/notes_history.xml b/lib/snmp/doc/src/notes_history.xml
index ed71a86e83..cd65aec57d 100644
--- a/lib/snmp/doc/src/notes_history.xml
+++ b/lib/snmp/doc/src/notes_history.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2020</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -438,7 +438,7 @@
<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>
+ unnecessary confusion.</p>
<p>Own Id: OTP-8116</p>
<p>Aux Id: Seq 11312</p>
</item>
@@ -490,7 +490,7 @@
<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>
+ as this was interpreted 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>
@@ -514,7 +514,7 @@
<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>
+ unnecessary confusion.</p>
<p>Own Id: OTP-8116</p>
<p>Aux Id: Seq 11312</p>
</item>
@@ -1397,7 +1397,7 @@
<item>
<p>[agent] Uninstalling MEs when unloading mibs incorrect and
- therefor never done. </p>
+ therefore never done. </p>
<p>Own Id: OTP-7153</p>
</item>
@@ -2175,7 +2175,7 @@
<item>
<p>[manager] Improve handling of empty messages. Today
when receiving an empty (size = 0) udp message, this
- will result in a decode failure (a catched function
+ will result in a decode failure (a caught function
clause), which in turn will be passed on to the user,
via a call to the
<seeerl marker="snmpm_user#handle_error">handle_error</seeerl>
diff --git a/lib/snmp/doc/src/part.xml b/lib/snmp/doc/src/part.xml
index 5ac6dc3917..4e5a33b6b2 100644
--- a/lib/snmp/doc/src/part.xml
+++ b/lib/snmp/doc/src/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -51,5 +51,6 @@
<xi:include href="snmp_advanced_agent.xml"/>
<xi:include href="snmp_app_a.xml"/>
<xi:include href="snmp_app_b.xml"/>
+ <xi:include href="snmp_app_c.xml"/>
</part>
diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml
index 9a4e123cb2..cc866b9f99 100644
--- a/lib/snmp/doc/src/snmp.xml
+++ b/lib/snmp/doc/src/snmp.xml
@@ -381,7 +381,7 @@
<c>Stop</c> is the stop (last) date and time to which log
events will be converted.
The <c>Block</c> argument indicates if the log should be blocked
- during conversion. This could be usefull when converting large
+ during conversion. This could be useful when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>.
</p>
diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml
index 87002e8189..1400e7bf32 100644
--- a/lib/snmp/doc/src/snmp_app.xml
+++ b/lib/snmp/doc/src/snmp_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1997</year><year>2021</year>
+ <year>1997</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -224,7 +224,7 @@ in the snmp_config file!
<note>
<p>Even with multi-threaded set to <c>extended</c>
there is still a risk for 'reorder' when sending inform-requsts,
- which require a response (and may therefor require resending). </p>
+ which require a response (and may therefore require resending). </p>
<p>Also, there is of course no way to guarantee order once the
package is on the network. </p>
</note>
@@ -295,14 +295,15 @@ in the snmp_config file!
<c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() =
- {bind_to, bind_to()} |
- {sndbuf, sndbuf()} |
- {recbuf, recbuf()} |
- {no_reuse, no_reuse()} |
- {req_limit, req_limit()} |
- {filter, agent_net_if_filter_options()} |
- {extra_sock_opts, extra_socket_options()} |
- {inet_backend, inet | socket}</c></p>
+ {bind_to, bind_to()} |
+ {sndbuf, sndbuf()} |
+ {recbuf, recbuf()} |
+ {no_reuse, no_reuse()} |
+ {req_limit, req_limit()} |
+ {filter, agent_net_if_filter_options()} |
+ {open_err_filters, agent_net_if_open_err_filters()} |
+ {extra_sock_opts, extra_socket_options()} |
+ {inet_backend, inet | socket}</c></p>
<p>These options are actually specific to the used module.
The ones shown here are applicable to the default
<c>agent_net_if_module()</c>.</p>
@@ -343,6 +344,25 @@ in the snmp_config file!
<p>Default is <c>snmpa_net_if_filter</c>.</p>
</item>
+ <tag><marker id="agent_ni_open_err_filters"></marker>
+ <c><![CDATA[agent_net_if_open_err_filters() = [agent_net_if_open_err_filter()] <optional>]]></c></tag>
+ <item>
+ <p><c>agent_net_if_open_err_filter() = atom()</c></p>
+ <p>During agent initiation, the transports UDP sockets are opened.
+ If this operation fails, the net-if (and the agent) fails to start
+ (crash). This (filter) list contains error (reasons) that will
+ make net-if fail "nicely".
+ This (filter) list, is supposed to contain errors that can be
+ returned by
+ <seemfa marker="kernel:gen_udp#open/1">gen_udp:open/1,2</seemfa>.
+ The effect is that any error returned by
+ <seemfa marker="kernel:gen_udp#open/1">gen_udp:open</seemfa>
+ which *are* in this list, will be considered
+ "non-fatal" and will only result in an info message, rather than
+ an error message. Net If, and the agent, will still crash,
+ but will produce a less obnoxious message. </p>
+ </item>
+
<tag><marker id="agent_mibs"></marker>
<c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
<item>
@@ -376,7 +396,7 @@ in the snmp_config file!
behaviour. </p>
<p>Several entities (<c>mib-server</c> via the its data module and
the <c>symbolic-store</c>) of the snmp agent uses this for storage
- of miscelaneous mib related data retrieved while loading a mib. </p>
+ of miscellaneous mib related data retrieved while loading a mib. </p>
<p>There are several implementations provided with the agent:
<c>snmpa_mib_storage_ets</c>, <c>snmpa_mib_storage_dets</c> and
<c>snmpa_mib_storage_mnesia</c>. </p>
@@ -386,7 +406,7 @@ in the snmp_config file!
<tag><marker id="agent_mst_options"></marker>
<c><![CDATA[mib_storage_options() = list() <optional>]]></c></tag>
<item>
- <p>This is implementattion depended. That is, it depends on the
+ <p>This is implementation depended. That is, it depends on the
module. For each module a specific set of options are valid.
For the module provided with the app, these options are supported: </p>
<list type="bulleted">
diff --git a/lib/snmp/doc/src/snmp_app_c.xml b/lib/snmp/doc/src/snmp_app_c.xml
new file mode 100644
index 0000000000..8bf71800e5
--- /dev/null
+++ b/lib/snmp/doc/src/snmp_app_c.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2022</year><year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>SNMP Appendix C</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ <file>snmp_app_c.xml</file>
+ </header>
+
+ <section>
+ <title>Appendix C</title>
+
+ <section>
+ <title>Compile time configuration</title>
+ <p>There is one compile/configure time option:
+ Defining the size of an "empty" PDU. This is used when processing
+ get-bulk requests. The default value for this is <em>21</em>,
+ but can be <em>increased</em> in two ways: </p>
+ <list type="bulleted">
+ <item>configure: <c>--with-snmp-empty-pdu-size=SIZE</c></item>
+ <item>compile time: <c> environment variable: SNMP_EMPTY_PDU_SIZE=SIZE"</c></item>
+ </list>
+ <p>Where <c>SIZE</c> is a value greater or equal to 21.</p>
+ </section>
+ </section>
+</chapter>
+
diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml
index 4f3dcb6f02..99324ed400 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>2021</year>
+ <year>1997</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -209,7 +209,7 @@
<note>
<p>Even with multi-threaded set to <c>extended</c>
there is still a risk for 'reorder' when sending inform-requsts,
- which require a response (and may therefor require resending). </p>
+ which require a response (and may therefore require resending). </p>
<p>Also, there is of course no way to guarantee order once the
package is on the network. </p>
</note>
@@ -281,14 +281,15 @@
<c><![CDATA[agent_net_if_options() = [agent_net_if_option()] <optional>]]></c></tag>
<item>
<p><c>agent_net_if_option() =
- {bind_to, bind_to()} |
- {sndbuf, sndbuf()} |
- {recbuf, recbuf()} |
- {no_reuse, no_reuse()} |
- {req_limit, req_limit()} |
- {filter, agent_net_if_filter_options()} |
- {extra_sock_opts, extra_socket_options()} |
- {inet_backend, inet | socket}</c></p>
+ {bind_to, bind_to()} |
+ {sndbuf, sndbuf()} |
+ {recbuf, recbuf()} |
+ {no_reuse, no_reuse()} |
+ {req_limit, req_limit()} |
+ {filter, agent_net_if_filter_options()} |
+ {extra_sock_opts, extra_socket_options()} |
+ {open_err_filters, agent_net_if_open_err_filters()} |
+ {inet_backend, inet | socket}</c></p>
<p>These options are actually specific to the used module.
The ones shown here are applicable to the default
<c>agent_net_if_module()</c>.</p>
@@ -329,6 +330,25 @@
<p>Default is <c>snmpa_net_if_filter</c>.</p>
</item>
+ <tag><marker id="agent_ni_open_err_filters"></marker>
+ <c><![CDATA[agent_net_if_open_err_filters() = [agent_net_if_open_err_filter()] <optional>]]></c></tag>
+ <item>
+ <p><c>agent_net_if_open_err_filter() = atom()</c></p>
+ <p>During agent initiation, the transports UDP sockets are opened.
+ If this operation fails, the net-if (and the agent) fails to start
+ (crash). This (filter) list contains error (reasons) that will
+ make net-if fail "nicely".
+ This (filter) list, is supposed to contain errors that can be
+ returned by
+ <seemfa marker="kernel:gen_udp#open/1">gen_udp:open/1,2</seemfa>.
+ The effect is that any error returned by
+ <seemfa marker="kernel:gen_udp#open/1">gen_udp:open</seemfa>
+ which *are* in this list, will be considered
+ "non-fatal" and will only result in an info message, rather than
+ an error message. Net If, and the agent, will still crash,
+ but will produce a less obnoxious message. </p>
+ </item>
+
<tag><marker id="agent_mibs"></marker>
<c><![CDATA[agent_mibs() = [string()] <optional>]]></c></tag>
<item>
diff --git a/lib/snmp/doc/src/snmp_def_instr_functions.xml b/lib/snmp/doc/src/snmp_def_instr_functions.xml
index 5fbcfaf2db..5a59f1bae5 100644
--- a/lib/snmp/doc/src/snmp_def_instr_functions.xml
+++ b/lib/snmp/doc/src/snmp_def_instr_functions.xml
@@ -99,7 +99,7 @@
</item>
<item><c>genErr</c>. Used if an error occurred. Note,
this should be an internal processing error, e.g. a caused
- by a programing fault somewhere. If the variable does not
+ by a programming fault somewhere. If the variable does not
exist, use <c>{noValue, noSuchName}</c> or
<c>{noValue, noSuchInstance}</c>.
</item>
@@ -275,7 +275,7 @@
</item>
<item><c>genErr</c>. Used if an error occurred. Note that
this should be an internal processing error, e.g. a caused
- by a programing fault somewhere. If some column does not
+ by a programming fault somewhere. If some column does not
exist, use <c>{noValue, noSuchName}</c> or
<c>{noValue, noSuchInstance}</c>.
</item>
@@ -322,7 +322,7 @@
<item><c>{NextOid, NextValue}</c>, where <c>NextOid</c>
is the lexicographic next OBJECT IDENTIFIER for the
corresponding column. This should be specified as the
- OBJECT IDENTIFER part following the table entry. This
+ OBJECT IDENTIFIER part following the table entry. This
means that the first integer is the column number and
the rest is a specification of the keys.
<c>NextValue</c> is the value of this element.
@@ -336,7 +336,7 @@
the column that caused the error. <c>Column</c> must be
one of the columns in the <c>Cols</c> list. Note that
this should be an internal processing error, e.g. a caused
- by a programing fault somewhere. If some column does not
+ by a programming fault somewhere. If some column does not
exist, you must return the next accessible element (or
<c>endOfTable</c>).
</item>
diff --git a/lib/snmp/doc/src/snmp_index.xml b/lib/snmp/doc/src/snmp_index.xml
index 9c8e6b8b33..108266e608 100644
--- a/lib/snmp/doc/src/snmp_index.xml
+++ b/lib/snmp/doc/src/snmp_index.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2020</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -123,7 +123,7 @@ get_next_pid(Oid, SnmpIndex) ->
</p>
<p>For example, if the SNMP table has two INDEX columns, the first
one an OCTET STRING with size 2, and the second one an OBJECT
- IDENTIFER, the corresponding <c>key_types</c> parameter would be
+ IDENTIFIER, the corresponding <c>key_types</c> parameter would be
<c>{fix_string, string}</c>.
</p>
<p>The <c>key()</c> type correlates to the <c>key_types()</c>
diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml
index f6c9e642cf..a790a7e7f3 100644
--- a/lib/snmp/doc/src/snmp_manager_netif.xml
+++ b/lib/snmp/doc/src/snmp_manager_netif.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2020</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -63,8 +63,8 @@
The (supervising) process simply sends a
<seeguide marker="#im_ping">ping</seeguide> message and expects a
<seeguide marker="#om_pong">pong</seeguide> message response
- (withing a specific time).
- The interval between each <c>ping/pong</c> exhange is user configurable.
+ (within a specific time).
+ The interval between each <c>ping/pong</c> exchange is user configurable.
As is the time that is allowed for the
<seeguide marker="#om_pong">pong</seeguide>
message to arrive.
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index fb341f8f79..c7ddd10d67 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -587,7 +587,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<c>LogName</c> defaults to "snmpa_log".
<c>LogFile</c> defaults to "snmpa.log". </p>
<p>The <c>Block</c> option indicates if the log should be blocked
- during conversion. This could be usefull when converting large
+ during conversion. This could be useful when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
<p>See <seeerl marker="snmp#log_to_txt">snmp:log_to_txt</seeerl>
@@ -628,7 +628,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<c>LogName</c> defaults to "snmpa_log".
<c>LogFile</c> defaults to "snmpa.log".</p>
<p>The <c>Block</c> option indicates if the log should be blocked
- during conversion. This could be usefull when converting large
+ during conversion. This could be useful when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
<p>See <seeerl marker="snmp#log_to_io">snmp:log_to_io</seeerl>
@@ -772,7 +772,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>Agent = pid() | atom()</v>
</type>
<desc>
- <p>Retreive the size of the mib server cache. </p>
+ <p>Retrieve the size of the mib server cache. </p>
<marker id="gc_mibs_cache"></marker>
</desc>
@@ -1104,7 +1104,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
</list>
<p>The 'process oid' "tag" that can be provided with the
- variable name / oids is indended to be used for oid post
+ variable name / oids is intended to be used for oid post
processing. The value '<c>keep</c>', which is the default, leaves
the oid as is. The value '<c>truncate</c>', will cause the oid
to be "truncated". That is, any trailing ".0" will be removed. </p>
@@ -1126,8 +1126,8 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2).
of this data, with one exception:
Any tuple containing the atom
<c>snmpa_default_notification_extra_info</c>
- may be used by the agent and is therefor <em>reserved</em>. </p>
- <p>See the net-if incomming messages for sending a
+ may be used by the agent and is therefore <em>reserved</em>. </p>
+ <p>See the net-if incoming messages for sending a
<seeguide marker="snmp_agent_netif#im_send_pdu">
trap</seeguide> and
<seeguide marker="snmp_agent_netif#im_send_pdu_req">
diff --git a/lib/snmp/doc/src/snmpa_mib_data.xml b/lib/snmp/doc/src/snmpa_mib_data.xml
index 1937e0f780..3dcfdc5865 100644
--- a/lib/snmp/doc/src/snmpa_mib_data.xml
+++ b/lib/snmp/doc/src/snmpa_mib_data.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2013</year><year>2020</year>
+ <year>2013</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -363,7 +363,7 @@
</type>
<desc>
<p>Perform a backup of the mib-server data. </p>
- <p>Note that its implementation dependant (and also
+ <p>Note that its implementation dependent (and also
dependent on mib-storage is used) if a backup is possible. </p>
<marker id="code_change"></marker>
diff --git a/lib/snmp/doc/src/snmpa_mpd.xml b/lib/snmp/doc/src/snmpa_mpd.xml
index e9294430bd..3235352608 100644
--- a/lib/snmp/doc/src/snmpa_mpd.xml
+++ b/lib/snmp/doc/src/snmpa_mpd.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2020</year>
+ <year>1999</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -170,7 +170,7 @@
<c>To</c> is a list of destination addresses and
their corresponding security parameters. This value is
received in the same message from the agent and then transformed
- trough <seeerl marker="#process_taddrs"><c>process_taddrs</c></seeerl>
+ through <seeerl marker="#process_taddrs"><c>process_taddrs</c></seeerl>
before passed to this function.</p>
<note>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index bb0826f2ce..8807851518 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -130,7 +130,7 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv
<item>
<p>During the start of a system, when a client application
<em>could</em> start prior to the SNMP manager but is dependent
- upon it, and therefor has to wait for it to start.</p>
+ upon it, and therefore has to wait for it to start.</p>
</item>
<item>
<p>When the SNMP manager has crashed, the dependent client
@@ -558,59 +558,10 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>For <c>SnmpInfo</c>, see the user callback function
<seeerl marker="snmpm_user#handle_report">handle_report</seeerl>.</p>
- <!-- <marker id="sync_get"></marker> -->
<marker id="async_get2"></marker>
</desc>
</func>
- <!-- DEPRECATED
- <func>
- <name since="">sync_get(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get(UserId, TargetName, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get(UserId, TargetName, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <fsummary>Synchronous <c>get-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>ContextName = string()</v>
- <v>Oids = [oid()]</v>
- <v>Timeout = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>SnmpReply = snmp_reply()</v>
- <v>Remaining = integer()</v>
- <v>Reason = {send_failed, ReqId, R} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
- <v>R = term()</v>
- <v>SecInfo = [sec_info()]</v>
- <v>sec_info() = {sec_tag(), ExpectedValue, ReceivedValue}</v>
- <v>sec_tag() = atom()</v>
- <v>ExpectedValue = ReceivedValue = term()</v>
- <v>SnmpInfo = term()</v>
- </type>
- <desc>
- <p>Synchronous <c>get-request</c>. </p>
- <p><c>Remaining</c> is the remaining time of the given or
- default timeout time.</p>
- <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
- <p>For <c>SnmpInfo</c>, see the user callback function
- <seeerl marker="snmpm_user#handle_report">handle_report</seeerl>.</p>
-
- <marker id="async_get2"></marker>
- </desc>
- </func>
- -->
-
<func>
<name since="OTP R14B03">async_get2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
<name since="OTP R14B03">async_get2(UserId, TargetName, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
@@ -649,49 +600,10 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
for <em>this</em> request, they override any configuration done
when the agent was registered. </p>
- <!-- <marker id="async_get"></marker> -->
<marker id="sync_get_next2"></marker>
</desc>
</func>
- <!-- DEPRECATED
- <func>
- <name since="">async_get(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get(UserId, TargetName, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get(UserId, TargetName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get(UserId, TargetName, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get(UserId, TargetName, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
- <fsummary>Asynchronous <c>get-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>ContextName = string()</v>
- <v>Oids = [oid()]</v>
- <v>Expire = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>ReqId = term()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Asynchronous <c>get-request</c>.</p>
- <p>The reply, if it arrives, will be delivered to the user
- through a call to the snmpm_user callback function
- <c>handle_pdu</c>.</p>
- <p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
- <marker id="sync_get_next2"></marker>
- </desc>
- </func>
- -->
-
<func>
<name since="OTP R14B03">sync_get_next2(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<name since="OTP R14B03">sync_get_next2(UserId, TargetName, Oids, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
@@ -742,50 +654,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>For <c>SnmpInfo</c>, see the user callback function
<seeerl marker="snmpm_user#handle_report">handle_report</seeerl>.</p>
- <!-- <marker id="sync_get_next"></marker> -->
- <marker id="async_get_next2"></marker>
- </desc>
- </func>
-
- <!-- DEPRECATED
- <func>
- <name since="">sync_get_next(UserId, TargetName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_next(UserId, TargetName, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_next(UserId, TargetName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_next(UserId, TargetName, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_next(UserId, TargetName, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <fsummary>Synchronous <c>get-next-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>ContextName = string()</v>
- <v>Oids = [oid()]</v>
- <v>Timeout = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>SnmpReply = snmp_reply()</v>
- <v>Remaining = integer()</v>
- <v>Reason = {send_failed, ReqId, R} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
- <v>R = term()</v>
- </type>
- <desc>
- <p>Synchronous <c>get-next-request</c>. </p>
- <p><c>Remaining</c> time of the given or default timeout time.</p>
- <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
<marker id="async_get_next2"></marker>
</desc>
</func>
- -->
<func>
<name since="OTP R14B03">async_get_next2(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
@@ -822,48 +693,10 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
for <em>this</em> request, they override any configuration done
when the agent was registered. </p>
- <!-- <marker id="async_get_next"></marker> -->
<marker id="sync_set2"></marker>
</desc>
</func>
- <!-- DEPRECATED
- <func>
- <name since="">async_get_next(UserId, TargetName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_next(UserId, TargetName, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_next(UserId, TargetName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_next(UserId, TargetName, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_next(UserId, TargetName, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
- <fsummary>Asynchronous <c>get-next-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>ContextName = string()</v>
- <v>Oids = [oid()]</v>
- <v>Expire = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>ReqId = integer()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Asynchronous <c>get-next-request</c>. </p>
- <p>The reply will be delivered to the user through a call
- to the snmpm_user callback function <c>handle_pdu</c>.</p>
- <p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
- <marker id="sync_set2"></marker>
- </desc>
- </func>
- -->
-
<func>
<name since="OTP R14B03">sync_set2(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
<name since="OTP R14B03">sync_set2(UserId, TargetName, VarsAndVals, SendOpts) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
@@ -917,52 +750,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>For <c>SnmpInfo</c>, see the user callback function
<seeerl marker="snmpm_user#handle_report">handle_report</seeerl>.</p>
- <!-- <marker id="sync_set"></marker> -->
- <marker id="async_set2"></marker>
- </desc>
- </func>
-
- <!-- DEPRECATED
- <func>
- <name since="">sync_set(UserId, TargetName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_set(UserId, TargetName, ContextName, VarsAndVals) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_set(UserId, TargetName, VarsAndVals, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_set(UserId, TargetName, ContextName, VarsAndVals, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_set(UserId, TargetName, ContextName, VarsAndVals, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <fsummary>Synchronous <c>set-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>ContextName = string()</v>
- <v>VarsAndVals = vars_and_vals()</v>
- <v>Timeout = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>SnmpReply = snmp_reply()</v>
- <v>Remaining = integer()</v>
- <v>Reason = {send_failed, ReqId, ActualReason} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
- <v>ActualReason = term()</v>
- </type>
- <desc>
- <p>Synchronous <c>set-request</c>. </p>
- <p><c>Remaining</c> time of the given or default timeout time.</p>
- <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
- manager makes an educated guess based on the loaded mibs. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
<marker id="async_set2"></marker>
</desc>
</func>
- -->
<func>
<name since="OTP R14B03">async_set2(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
@@ -1004,48 +794,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
for <em>this</em> request, they override any configuration done
when the agent was registered. </p>
- <!-- <marker id="async_set"></marker> -->
- <marker id="sync_get_bulk2"></marker>
- </desc>
- </func>
-
- <!-- DEPRECATED
- <func>
- <name since="">async_set(UserId, TargetName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_set(UserId, TargetName, ContextName, VarsAndVals) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_set(UserId, TargetName, VarsAndVals, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_set(UserId, TargetName, ContextName, VarsAndVals, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_set(UserId, TargetName, ContextName, VarsAndVals, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
- <fsummary>Asynchronous <c>set-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>VarsAndVals = vars_and_vals()</v>
- <v>Expire = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>ReqId = term()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Asynchronous <c>set-request</c>. </p>
- <p>The reply will be delivered to the user through a call
- to the snmpm_user callback function <c>handle_pdu</c>.</p>
- <p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
- <p>When <em>var_and_val()</em> is <em>{oid(), value()}</em>, the
- manager makes an educated guess based on the loaded mibs. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
<marker id="sync_get_bulk2"></marker>
</desc>
</func>
- -->
<func>
<name since="OTP R14B03">sync_get_bulk2(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
@@ -1099,52 +850,10 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<p>For <c>SnmpInfo</c>, see the user callback function
<seeerl marker="snmpm_user#handle_report">handle_report</seeerl>.</p>
- <!-- <marker id="sync_get_bulk"></marker> -->
<marker id="async_get_bulk2"></marker>
</desc>
</func>
- <!-- DEPRECATED
- <func>
- <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids, Timeout) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <name since="">sync_get_bulk(UserId, TragetName, NonRep, MaxRep, ContextName, Oids, Timeout, ExtraInfo) -> {ok, SnmpReply, Remaining} | {error, Reason}</name>
- <fsummary>Synchronous <c>get-bulk-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>NonRep = integer()</v>
- <v>MaxRep = integer()</v>
- <v>ContextName = string()</v>
- <v>Oids = [oid()]</v>
- <v>Timeout = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>SnmpReply = snmp_reply()</v>
- <v>Remaining = integer()</v>
- <v>Reason = {send_failed, ReqId, R} | {invalid_sec_info, SecInfo, SnmpInfo} | term()</v>
- </type>
- <desc>
- <p>Synchronous <c>get-bulk-request</c> (See RFC1905).</p>
- <p><c>Remaining</c> time of the given or default timeout time.</p>
- <p>When <em>Reason</em> is <em>{send_failed, ...}</em> it means that
- the net_if process failed to send the message. This could happen
- because of any number of reasons, i.e. encoding error. <em>R</em>
- is the actual reason in this case. </p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
- <marker id="async_get_bulk2"></marker>
- </desc>
- </func>
- -->
-
<func>
<name since="OTP R14B03">async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
<name since="OTP R14B03">async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts) -> {ok, ReqId} | {error, Reason}</name>
@@ -1182,49 +891,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
for <em>this</em> request, they override any configuration done
when the agent was registered. </p>
- <!-- <marker id="async_get_bulk"></marker> -->
- <marker id="cancel_async_request"></marker>
- </desc>
- </func>
-
- <!-- DEPRECATED
- <func>
- <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids, Expire) -> {ok, ReqId} | {error, Reason}</name>
- <name since="">async_get_bulk(UserId, TargetName, NonRep, MaxRep, ContextName, Oids, Expire, ExtraInfo) -> {ok, ReqId} | {error, Reason}</name>
- <fsummary>Asynchronous <c>get-bulk-request</c></fsummary>
- <type>
- <v>UserId = term()</v>
- <v>TargetName = target_name()</v>
- <v>NonRep = integer()</v>
- <v>MaxRep = integer()</v>
- <v>ContextName = string()</v>
- <v>Oids = [oid()]</v>
- <v>Expire = integer()</v>
- <v>ExtraInfo = term()</v>
- <v>ReqId = integer()</v>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Asynchronous <c>get-bulk-request</c> (See RFC1905).</p>
- <p>The reply will be delivered to the user through a call
- to the snmpm_user callback function <c>handle_pdu</c>.</p>
- <p>The <c>Expire</c> time indicates for how long the request is
- valid (after which the manager is free to delete it).</p>
- <p><c>ExtraInfo</c> is an opaque data structure passed on to
- the net-if process. The net-if process included in this
- application makes, with one exception, no use of this info,
- so the only use for it in such a configuration (when using the
- built in net-if) would be tracing. The one usage exception is:
- <em>Any</em> tuple with <c>snmpm_extra_info_tag</c> as its first
- element is reserved for internal use. </p>
-
<marker id="cancel_async_request"></marker>
</desc>
</func>
- -->
<func>
<name since="">cancel_async_request(UserId, ReqId) -> ok | {error, Reason}</name>
@@ -1274,7 +943,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<c>LogName</c> defaults to "snmpm_log".
<c>LogFile</c> defaults to "snmpm.log".</p>
<p>The <c>Block</c> argument indicates if the log should be blocked
- during conversion. This could be usefull when converting large
+ during conversion. This could be useful when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
<p>See <seeerl marker="snmp#log_to_txt">snmp:log_to_txt</seeerl>
@@ -1316,7 +985,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<c>LogName</c> defaults to "snmpm_log".
<c>LogFile</c> defaults to "snmpm.log".</p>
<p>The <c>Block</c> argument indicates if the log should be blocked
- during conversion. This could be usefull when converting large
+ during conversion. This could be useful when converting large
logs (when otherwise the log could wrap during conversion).
Defaults to <c>true</c>. </p>
<p>See <seeerl marker="snmp#log_to_io">snmp:log_to_io</seeerl>
@@ -1465,7 +1134,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>Reason = term()</v>
</type>
<desc>
- <p>Retreive the type (asn1 bertype) of an oid.</p>
+ <p>Retrieve the type (asn1 bertype) of an oid.</p>
<marker id="backup"></marker>
</desc>
@@ -1527,7 +1196,7 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</type>
<desc>
<p>Restart the indicated process (<c>Ref</c>). Note that its not
- without risk to restart a process, and should therefor be used
+ without risk to restart a process, and should therefore be used
with care. </p>
<marker id="format_reason"></marker>
@@ -1558,9 +1227,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<seeerl marker="snmpm_user#handle_error">handle_error</seeerl> user callback function.</p>
</item>
</list>
- <p><c>Prefix</c> should either be an indention string
+ <p><c>Prefix</c> should either be an indentation string
(e.g. a list of spaces) or a positive integer (which will be used
- to create the indention string of that length).</p>
+ to create the indentation string of that length).</p>
</desc>
</func>
</funcs>
diff --git a/lib/snmp/doc/src/structure.fig b/lib/snmp/doc/src/structure.fig
index c7feff6f47..c50a5b74b3 100644
--- a/lib/snmp/doc/src/structure.fig
+++ b/lib/snmp/doc/src/structure.fig
@@ -30,7 +30,7 @@ Inches
2400 900 8625 900 8625 6000 2400 6000 2400 900
2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5
8625 6000 8625 6000 8625 6000 8625 6000 8625 6000
-4 0 -1 0 0 0 12 0.0000 4 135 1230 3525 3000 Assosiacition file\001
+4 0 -1 0 0 0 12 0.0000 4 135 1230 3525 3000 Association file\001
4 0 -1 0 0 0 12 0.0000 4 180 990 3750 1575 SNMP Agent\001
4 0 -1 0 0 0 12 0.0000 4 135 345 4050 1950 MIB\001
4 0 -1 0 0 0 12 0.0000 4 180 1080 3075 4275 snmp_local_db\001
diff --git a/lib/snmp/examples/ex1/Makefile b/lib/snmp/examples/ex1/Makefile
index a3d02ea778..b4e7c7f2dd 100644
--- a/lib/snmp/examples/ex1/Makefile
+++ b/lib/snmp/examples/ex1/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@ TARGET_FILES= \
# Targets
# ----------------------------------------------------
-debug opt: build
+$(TYPES): build
clean:
rm -f $(TARGET_FILES)
diff --git a/lib/snmp/examples/ex2/Makefile b/lib/snmp/examples/ex2/Makefile
index 624a1df2ee..f0f652af74 100644
--- a/lib/snmp/examples/ex2/Makefile
+++ b/lib/snmp/examples/ex2/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2016. All Rights Reserved.
+# Copyright Ericsson AB 2006-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -65,11 +65,25 @@ TARGET_FILES= \
$(ERL_FILES:%.erl=%.$(EMULATOR))
+DIA_PLT = snmp_example_ex2.plt
+DIA_ANALYSIS = $(basename $(DIA_PLT)).dialyzer_analysis
+ifeq ($(DIAW_EH),true)
+DIA_WARNINGS += -Werror_handling
+endif
+ifeq ($(DIAW_US),true)
+DIA_WARNINGS += -Wunderspecs
+endif
+ifeq ($(DIAW_UR),true)
+DIA_WARNINGS += -Wunmatched_returns
+endif
+DIA_PLT_APPS = erts kernel stdlib crypto mnesia runtime_tools compiler
+
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: build
+$(TYPES): build
clean:
rm -f $(TARGET_FILES)
@@ -80,6 +94,28 @@ docs:
build: $(TARGET_FILES)
+dclean:
+ rm -f $(DIA_PLT)
+ rm -f $(DIA_ANALYSIS)
+
+dialyzer_plt: $(DIA_PLT)
+
+$(DIA_PLT): $(ERL_FILES)
+ @echo "Building ($(basename $(DIA_PLT))) plt file"
+ @dialyzer --build_plt \
+ --output_plt $@ \
+ --apps $(sort snmp $(DIA_PLT_APPS)) \
+ --output $(DIA_ANALYSIS) \
+ --verbose
+
+dialyzer: $(DIA_PLT)
+ @echo "Running dialyzer on snmp example ex2"
+ @dialyzer --plt $< \
+ $(ERL_TOP)/lib/snmp/examples/ex2 \
+ $(DIA_WARNINGS) \
+ --verbose
+
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
diff --git a/lib/snmp/examples/ex2/snmp_ex2_manager.erl b/lib/snmp/examples/ex2/snmp_ex2_manager.erl
index b3faa54a15..43f585f026 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -133,12 +133,7 @@ write_config(Dir, Conf) ->
end.
start_manager(Opts) ->
- case snmpm:start_link(Opts) of
- ok ->
- ok;
- Error ->
- error({failed_starting_manager, Error})
- end.
+ ok = snmpm:start_link(Opts).
register_user() ->
case snmpm:register_user(?USER, ?USER_MOD, self()) of
@@ -397,16 +392,16 @@ handle_pdu(TargetName, ReqId, SnmpResponse, Server) when is_pid(Server) ->
handle_trap(TargetName, SnmpTrap, Server) when is_pid(Server) ->
report_callback(Server, handle_trap, {TargetName, SnmpTrap}),
- ok.
+ ignore.
handle_inform(TargetName, SnmpInform, Server) when is_pid(Server) ->
report_callback(Server, handle_inform, {TargetName, SnmpInform}),
- ok.
+ ignore.
handle_report(TargetName, SnmpReport, Server) when is_pid(Server) ->
report_callback(Server, handle_inform, {TargetName, SnmpReport}),
- ok.
+ ignore.
handle_invalid_result(In, Out, Server) when is_pid(Server) ->
report_callback(Server, handle_invalid_result, {In, Out}),
diff --git a/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl b/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl
index e8f748c337..181a789529 100644
--- a/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl
+++ b/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -246,34 +246,32 @@ verify_vbs([Vb|T], NameAndTypes, Acc) ->
Acc2 = lists:flatten(io_lib:format("~s~n ~s", [Acc, Val])),
verify_vbs(T, NameAndTypes, Acc2).
-verify_vb(#varbind{oid = Oid, variabletype = Type, value = Val} = Vb,
- NameAndTypes) ->
+verify_vb(#varbind{oid = Oid} = Vb, NameAndTypes) ->
case lists:reverse(Oid) of
[0|RevOid] ->
- case snmp_ex2_manager:oid_to_name(lists:reverse(RevOid)) of
- {ok, Name} ->
- case lists:keysearch(Name, 1, NameAndTypes) of
- {value, {Name, Type}} ->
- Val;
- {value, {Name, WrongType}} ->
- error({wrong_type, {WrongType, Vb}});
- false ->
- error({unexpected_name, {Name, Vb}})
- end;
- {error, Reason} ->
- error({unexpected_oid, {Reason, Vb}})
- end;
+ verify_vb_value(lists:reverse(RevOid), Vb, NameAndTypes);
_ ->
- case lists:keysearch(Oid, 1, NameAndTypes) of
- {value, {Oid, Type}} ->
- Val;
- {value, {Oid, WrongType}} ->
- error({wrong_type, {WrongType, Vb}});
- false ->
- error({unexpected_oid, Vb})
- end
+ verify_vb_value(Oid, Vb, NameAndTypes)
end.
+verify_vb_value(Oid,
+ #varbind{variabletype = Type, value = Val} = Vb,
+ NameAndTypes) ->
+ case snmp_ex2_manager:oid_to_name(Oid) of
+ {ok, Name} ->
+ case lists:keysearch(Name, 1, NameAndTypes) of
+ {value, {Name, Type}} ->
+ Val;
+ {value, {Name, WrongType}} ->
+ error({wrong_type, {WrongType, Vb}});
+ false ->
+ error({unexpected_name, {Name, Vb}})
+ end;
+ {error, Reason} ->
+ error({unexpected_oid, {Reason, Vb}})
+ end.
+
+
std_mib(MibName) ->
j(std_dir(), MibName).
diff --git a/lib/snmp/mibs/Makefile.in b/lib/snmp/mibs/Makefile.in
index 6419009a6a..428587617f 100644
--- a/lib/snmp/mibs/Makefile.in
+++ b/lib/snmp/mibs/Makefile.in
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -127,7 +127,7 @@ endif
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
$(ERL_TOP)/lib/snmp/bin/snmp-v2tov1: $(ERL_TOP)/lib/snmp/bin/snmp-v2tov1.src
$(gen_verbose)$(PERL) -p -e 's?%PERL%?$(PERL)? ' < $< > $@
diff --git a/lib/snmp/priv/conf/agent/Makefile b/lib/snmp/priv/conf/agent/Makefile
index e905f55999..7e8f4ef6c6 100644
--- a/lib/snmp/priv/conf/agent/Makefile
+++ b/lib/snmp/priv/conf/agent/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ include files.mk
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/snmp/priv/conf/manager/Makefile b/lib/snmp/priv/conf/manager/Makefile
index 27024c171f..0659b900eb 100644
--- a/lib/snmp/priv/conf/manager/Makefile
+++ b/lib/snmp/priv/conf/manager/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2016. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,7 +44,7 @@ include files.mk
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/snmp/src/agent/Makefile b/lib/snmp/src/agent/Makefile.in
index 1da0f33c9d..6ab9ed437a 100644
--- a/lib/snmp/src/agent/Makefile
+++ b/lib/snmp/src/agent/Makefile.in
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -76,6 +76,16 @@ ifeq ($(SNMP_EXT_VERBOSITY),true)
SNMP_FLAGS += -Dsnmp_extended_verbosity
endif
+SNMP_EMPTY_PDU_SIZE_DEFAULT = @SNMP_EMPTY_PDU_SIZE_DEFAULT@
+
+# SNMP_EMPTY_PDU_SIZE=42
+ifneq ($(SNMP_EMPTY_PDU_SIZE),)
+ SNMP_FLAGS += -Dempty_pdu_size=$(SNMP_EMPTY_PDU_SIZE)
+else
+ SNMP_FLAGS += -Dempty_pdu_size=$(SNMP_EMPTY_PDU_SIZE_DEFAULT)
+endif
+
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -110,8 +120,8 @@ ERL_COMPILE_FLAGS += -I../../include \
# Targets
# ----------------------------------------------------
-debug:
- @$(MAKE) TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt:
@$(MAKE) behaviour_targets
diff --git a/lib/snmp/src/agent/modules.mk b/lib/snmp/src/agent/modules.mk
index 39c9aca1cd..32df6a9a9b 100644
--- a/lib/snmp/src/agent/modules.mk
+++ b/lib/snmp/src/agent/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2019. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -41,9 +41,9 @@ MIB_MODULES = \
snmp_view_based_acm_mib
# snmpa is "plain" interface module but also defines some agent specific types
-# and therefor must be compiled before the modules that use them, including
+# and therefore must be compiled before the modules that use them, including
# the behaviour modules...
-# Some of the MIB modules also define types used elsewhere and therefor
+# Some of the MIB modules also define types used elsewhere and therefore
# has to be built before the other mods.
# snmpa_mib_data_ttln
MODULES = \
diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl
index 5db686d29b..3f2179c11e 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -474,7 +474,7 @@ delete_context(Key) ->
%%-----------------------------------------------------------------
%% Instrumentation functions
-%% Retreive functions are also used internally by the agent, so
+%% Retrieve functions are also used internally by the agent, so
%% don't change the interface without changing those functions.
%% Note that if these functions implementations are changed,
%% an error can make the agent crash, as no error detection is
diff --git a/lib/snmp/src/agent/snmp_generic.erl b/lib/snmp/src/agent/snmp_generic.erl
index 429f78abd0..6419503322 100644
--- a/lib/snmp/src/agent/snmp_generic.erl
+++ b/lib/snmp/src/agent/snmp_generic.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -134,7 +134,7 @@ table_max_col(NameDb, Col) -> % ret largest element in Col
%%------------------------------------------------------------------
-%% Theses functions could be in the MIB for simple
+%% These functions could be in the MIB for simple
%% variables or tables, i.e. vars without complex
%% set-operations. If there are complex set op, an
%% extra layer-function should be added, and that
@@ -566,7 +566,7 @@ table_create_rest(Col, Max, StatusCol, Status, Cols, NoAccs) when Col =< Max->
%% Defs is a list of {Col, DefVal}, in Column order.
%% Returns a new row (a list of values) with the same values as
%% InitRow, except if InitRow has value noinit in a column, and
-%% the corresponing Col has a DefVal in Defs, then the DefVal
+%% the corresponding Col has a DefVal in Defs, then the DefVal
%% will be the new value.
%%------------------------------------------------------------------
table_defaults(InitRow, Defs) -> table_defaults(InitRow, 1, Defs).
diff --git a/lib/snmp/src/agent/snmp_generic_mnesia.erl b/lib/snmp/src/agent/snmp_generic_mnesia.erl
index 131b9b0368..37bf23a5b6 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
%%%-----------------------------------------------------------------
%%------------------------------------------------------------------
-%% Theses functions could be in the MIB for simple
+%% These functions could be in the MIB for simple
%% variables or tables, i.e. vars without complex
%% set-operations. If there are complex set op, an
%% extra layer-function should be added, and that
@@ -185,8 +185,8 @@ make_row2(RowList, 1) -> RowList;
make_row2([_OtherIndex | RowList], N) ->
make_row2(RowList, N-1).
-make_row_list(Row) ->
- make_row_list(size(Row), Row, []).
+make_row_list(Row) when is_tuple(Row) ->
+ make_row_list(tuple_size(Row), Row, []).
make_row_list(N, Row, Acc) when N > 2 ->
make_row_list(N-1, Row, [element(N, Row) | Acc]);
make_row_list(2, Row, Acc) ->
diff --git a/lib/snmp/src/agent/snmp_index.erl b/lib/snmp/src/agent/snmp_index.erl
index 38b39a9b7e..fd2f1c8415 100644
--- a/lib/snmp/src/agent/snmp_index.erl
+++ b/lib/snmp/src/agent/snmp_index.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -155,7 +155,7 @@ is_snmp_type(_) -> false.
key_to_oid_i(Key, _Type) when is_integer(Key) -> [Key];
key_to_oid_i(Key, fix_string) -> Key;
key_to_oid_i(Key, _Type) when is_list(Key) -> [length(Key) | Key];
-key_to_oid_i(Key, Types) -> keys_to_oid(size(Key), Key, [], Types).
+key_to_oid_i(Key, Types) when is_tuple(Key) -> keys_to_oid(tuple_size(Key), Key, [], Types).
keys_to_oid(0, _Key, Oid, _Types) -> Oid;
keys_to_oid(N, Key, Oid, Types) ->
diff --git a/lib/snmp/src/agent/snmp_shadow_table.erl b/lib/snmp/src/agent/snmp_shadow_table.erl
index f9181f70a7..12aa659213 100644
--- a/lib/snmp/src/agent/snmp_shadow_table.erl
+++ b/lib/snmp/src/agent/snmp_shadow_table.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -93,9 +93,9 @@ update(Name, UpdateFunc, Interval) ->
%% Args: Extra = {Name, SnmpKey, Attributes, Interval, UpdateFunc}
%% Purpose: Instrumentation function for the table.
%% Name is the name of the table
-%% SnmpKey is the snmpkey as it should be specifed in order
+%% SnmpKey is the snmpkey as it should be specified in order
%% to create the Mnesia table as an SNMP table
-%% Attributes is the attributes as it should be specifed in order
+%% Attributes is the attributes as it should be specified in order
%% to create the Mnesia table as an SNMP table
%% Interval is the minimum time in milliseconds between two
%% updates of the table
diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl
index 22fd3acb84..30a3f08749 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-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -595,7 +595,7 @@ get_target_addr({Tab, mnesia}, Key) ->
snmpTargetAddrRowStatus = ?'RowStatus_active'}} ->
case get_target_params(Params) of
undefined ->
- config_err("Failed retreiving target params [~p]"
+ config_err("Failed retrieving target params [~p]"
"~n for ~p [~p]", [Params, Key, TAddress]),
{error, {not_found, {target_params, Key, Params}}};
TargetParams ->
@@ -612,7 +612,7 @@ get_target_addr(TabDb, Key) ->
_Storage, ?'RowStatus_active', _TargetEngineId,_TMask,_MMS} ->
case get_target_params(Params) of
undefined ->
- config_err("Failed retreiving target params [~p]"
+ config_err("Failed retrieving target params [~p]"
"~n for target ~p [~p]",
[Params, Key, TAddress]),
{error, {not_found, {target_params, Key, Params}}};
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 0b94f4604a..e75cb7c5ce 100644
--- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
+++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
@@ -830,7 +830,7 @@ validate_set(Error, _RowIndex, _Cols) ->
%%-----------------------------------------------------------------
%% Here's the alg: If this is the first time the CloneFrom is written,
%% we must check that the CloneFrom row exists, so we can invoke the
-%% clone process in the set phase. Otherwise, the set succed, with
+%% clone process in the set phase. Otherwise, the set succeed, with
%% no further checks.
%%-----------------------------------------------------------------
validate_clone_from(RowIndex, Cols) ->
@@ -902,7 +902,7 @@ validate_auth_protocol(RowIndex, Cols) ->
%% now; set is ok if new protocol is usmNoAuthProtocol
case AuthProtocol of
?usmNoAuthProtocol ->
- %% Check that the Priv protocl is noPriv
+ %% Check that the Priv protocol is noPriv
case get_priv_proto(RowIndex, Cols) of
?usmNoPrivProtocol -> ok;
_ -> inconsistentValue(?usmUserAuthProtocol)
@@ -928,7 +928,7 @@ validate_auth_protocol(RowIndex, Cols) ->
%% hash function.
case AuthProtocol of
?usmNoAuthProtocol ->
- %% Check that the Priv protocl is noPriv
+ %% Check that the Priv protocol is noPriv
case get_priv_proto(RowIndex, Cols) of
?usmNoPrivProtocol -> ok;
_ -> inconsistentValue(?usmUserAuthProtocol)
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 a5a65d9326..6fcd92bf03 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-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -285,7 +285,7 @@ delete_sec2group(Key) ->
{error, delete_failed}
end.
-%% NOTE: This function must be used in conjuction with
+%% NOTE: This function must be used in conjunction with
%% snmpa_vacm:dump_table.
%% That is, when all access has been added, call
%% snmpa_vacm:dump_table/0
@@ -357,7 +357,7 @@ init_vacm_mnesia() ->
%% The 5 is intentional: It is a trick to get a tuple with the
%% columns needed by the vacm ets-table (corresponding to the
- %% tuple read from the config files). Therefor, 5 since it it
+ %% tuple read from the config files). Therefore, 5 since it it
%% is not a real foi...
snmp_generic:table_foreach({vacmAccessTable, mnesia}, F, 5).
@@ -1048,7 +1048,7 @@ imask2emask(IMask) ->
imask2emask([], EMask) ->
lists:reverse(EMask);
imask2emask(IMask, EMask) ->
- %% Make sure we have atleast 8 bits
+ %% Make sure we have at least 8 bits
%% (maybe extend with 1's)
IMask2 =
case length(IMask) of
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl
index 995e6d627d..74205e5716 100644
--- a/lib/snmp/src/agent/snmpa.erl
+++ b/lib/snmp/src/agent/snmpa.erl
@@ -149,6 +149,11 @@
%% Options specific to the above module
-type mib_storage_options() :: list().
+-type mib_module() :: atom().
+-type table_name() :: atom().
+-type variable_name() :: atom().
+-type mib_info() :: {mib_module(), [table_name()], [variable_name()]}.
+
%%-----------------------------------------------------------------
%% This utility function is used to convert an old SNMP application
@@ -340,11 +345,11 @@ unload_mib(Agent, Mib) ->
end.
unload_mibs(Mibs) ->
- unload_mibs(snmp_master_agent, Mibs, false).
+ unload_mibs(snmp_master_agent, Mibs).
unload_mibs(Agent, Mibs) when is_list(Mibs) ->
- snmpa_agent:unload_mibs(Agent, Mibs);
+ unload_mibs(Agent, Mibs, false);
unload_mibs(Mibs, Force)
- when is_list(Mibs) andalso ((Force =:= true) orelse (Force =:= false)) ->
+ when is_list(Mibs) andalso is_boolean(Force) ->
unload_mibs(snmp_master_agent, Mibs, Force).
-spec unload_mibs(Agent :: pid() | atom(),
@@ -353,7 +358,7 @@ unload_mibs(Mibs, Force)
ok | {error, {'unload aborted at', MibName :: string(), InternalReason :: not_loaded | term()}}.
unload_mibs(Agent, Mibs, Force)
- when is_list(Mibs) andalso ((Force =:= true) orelse (Force =:= false)) ->
+ when is_list(Mibs) andalso is_boolean(Force) ->
snmpa_agent:unload_mibs(Agent, Mibs, Force).
@@ -369,6 +374,8 @@ whereis_mib(Agent, Mib) when is_atom(Mib) ->
%% -
+-spec mibs_info() -> [mib_info()].
+
mibs_info() ->
[
{snmp_standard_mib,
diff --git a/lib/snmp/src/agent/snmpa_acm.erl b/lib/snmp/src/agent/snmpa_acm.erl
index de67df8a06..74efae4ad5 100644
--- a/lib/snmp/src/agent/snmpa_acm.erl
+++ b/lib/snmp/src/agent/snmpa_acm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -234,7 +234,7 @@ invalidate_ca_cache() ->
%%-----------------------------------------------------------------
%% NOTE: The do_get MUST be executed in the Master agents's
-%% context. Therefor, force master-agent to do a GET to
+%% context. Therefore, force master-agent to do a GET to
%% retrieve the value for snmpEnableAuthenTraps.
%% A user may have another impl. than default for this
%% variable.
diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl
index 5039b08391..8c24440efc 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,18 +65,11 @@
-export([increment_counter/3]).
-export([restart_worker/1, restart_set_worker/1, restart_notif_worker/1]).
-%% For backward compatibillity
--export([send_trap/6, send_trap/7]).
-
%% Internal exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3, tr_var/2, tr_varbind/1,
handle_pdu/8, worker/4, worker_loop/2,
do_send_trap/7, do_send_trap/8]).
-%% <BACKWARD-COMPAT>
--export([handle_pdu/7,
- load_mibs/2, unload_mibs/2]).
-%% </BACKWARD-COMPAT>
-include("snmpa_internal.hrl").
@@ -84,8 +77,6 @@
-define(default_verbosity,silence).
-endif.
--define(empty_pdu_size, 21).
-
-ifdef(snmp_extended_verbosity).
-define(vt(F,A), ?vtrace(F, A)).
-else.
@@ -349,10 +340,16 @@ init([Prio, Parent, Ref, Options]) ->
"~n Options: ~p", [Prio, Parent, Ref, Options]),
case (catch do_init(Prio, Parent, Ref, Options)) of
{ok, State} ->
- ?vdebug("started",[]),
+ ?vdebug("started"),
{ok, State};
+ {error, {net_if, info, Reason}} ->
+ info_msg("Failed starting agent: "
+ "~n Net If error: ~p", [Reason]),
+ %% {shutdown, Reason};
+ exit(Reason);
{error, Reason} ->
- config_err("failed starting agent: ~n~p", [Reason]),
+ config_err("Failed starting agent: "
+ "~n ~p", [Reason]),
{stop, Reason}
end.
@@ -419,15 +416,18 @@ start_note_store(Prio, Ref, Options) ->
{ok, Pid} ->
?vdebug("start_note_store -> Pid: ~p", [Pid]),
Pid;
- {error, Reason} ->
- ?vinfo("error starting note store: ~n~p",[Reason]),
- throw({error, {note_store_error, Reason}});
- {'EXIT', Reason} ->
- ?vinfo("exit starting note store: ~n~p",[Reason]),
- throw({error, {note_store_exit, Reason}});
+ {error, {Reason, _ChildSpec}} ->
+ ?vinfo("error starting note store: "
+ "~n ~p", [Reason]),
+ throw({error, {note_store, error, Reason}});
+ {'EXIT', {Reason, _ChildSpec}} ->
+ ?vinfo("exit starting note store: "
+ "~n ~p", [Reason]),
+ throw({error, {note_store, exit, Reason}});
Error ->
- ?vinfo("failed starting note store: ~n~p",[Error]),
- throw({error, {note_store_failed, Error}})
+ ?vinfo("failed starting note store: "
+ "~n ~p", [Error]),
+ throw({error, {note_store, failed, Error}})
end.
@@ -446,18 +446,25 @@ start_net_if(none, Prio, Ref, Vsns, NoteStore, Options) ->
case (catch snmpa_misc_sup:start_net_if(Prio, NoteStore, Ref, self(),
Mod, NiOpts)) of
- {ok, Pid} ->
+ {ok, Pid} ->
?vdebug("start_net_if -> Pid: ~p", [Pid]),
{master_agent, Pid, Mod};
- {error, Reason} ->
- ?vinfo("error starting net if: ~n~p",[Reason]),
- throw({error, {net_if_error, Reason}});
+ {error, {{Class, udp_open, PortNo, Reason}, _ChildSpec}} ->
+ ?vinfo("error starting net if: "
+ "~n ~p", [Reason]),
+ throw({error, {net_if, Class, {udp_open, PortNo, Reason}}});
+ {error, {Reason, _ChildSpec}} ->
+ ?vinfo("error starting net if: "
+ "~n ~p", [Reason]),
+ throw({error, {net_if, error, Reason}});
{'EXIT', Reason} ->
- ?vinfo("exit starting net if: ~n~p",[Reason]),
- throw({error, {net_if_exit, Reason}});
+ ?vinfo("exit starting net if: "
+ "~n ~p", [Reason]),
+ throw({error, {net_if, exit, Reason}});
Error ->
- ?vinfo("failed starting net if: ~n~p",[Error]),
- throw({error, {net_if_failed, Error}})
+ ?vinfo("failed starting net if: "
+ "~n ~p", [Error]),
+ throw({error, {net_if, failed, Error}})
end;
start_net_if(Parent, _Prio, _Ref, _Vsns, _NoteStore, _Options)
when is_pid(Parent) ->
@@ -479,41 +486,21 @@ start_mib_server(Prio, Ref, Mibs, Options) ->
{ok, Pid} ->
?vdebug("start_mib_server -> Pid: ~p", [Pid]),
Pid;
- {error, Reason} ->
- ?vinfo("error starting mib server: ~n~p",[Reason]),
- throw({error, {mib_server_error, Reason}});
+ {error, {Reason, _ChildSpec}} ->
+ ?vinfo("error starting mib server: "
+ "~n ~p", [Reason]),
+ throw({error, {mib_server, error, Reason}});
{'EXIT', Reason} ->
- ?vinfo("exit starting mib server: ~n~p",[Reason]),
- throw({error, {mib_server_exit, Reason}});
+ ?vinfo("exit starting mib server: "
+ "~n ~p", [Reason]),
+ throw({error, {mib_server, exit, Reason}});
Error ->
- ?vinfo("failed starting mib server: ~n~p",[Error]),
- throw({error, {mib_server_failed, Error}})
+ ?vinfo("failed starting mib server: "
+ "~n ~p", [Error]),
+ throw({error, {mib_server, failed, Error}})
end.
-%%-----------------------------------------------------------------
-%% Purpose: We must calculate the length of an empty Pdu. This
-%% length is used to calculate the max pdu size allowed
-%% for each get-bulk-request. This size is
-%% dependent on the varbinds. It is calculated
-%% as EmptySize + 8. 8 comes from the fact that the
-%% maximum pdu size needs 31 bits which needs 5 * 7 bits to be
-%% expressed. One 7bit octet is already present in the
-%% empty pdu, leaving 4 more 7bit octets. The length is
-%% repeated twice, once for the varbinds, and once for the
-%% entire pdu; 2 * 4 = 8.
-%% Actually, this function is not used, we use a constant instead.
-%%-----------------------------------------------------------------
-%% Ret: 21
-%% empty_pdu() ->
-%% Pdu = #pdu{type = 'get-response',
-%% request_id = 1,
-%% error_status = noError,
-%% error_index = 0,
-%% varbinds = []},
-%% length(snmp_pdus:enc_pdu(Pdu)) + 8.
-
-
%%%--------------------------------------------------
%%% 1. Interface
%%%--------------------------------------------------
@@ -559,21 +546,9 @@ subagent_set(SubAgent, Arguments) ->
call(SubAgent, {subagent_set, Arguments, PduData}).
-%% Called by administrator (not agent; deadlock would occur)
-%% <BACKWARD-COMPAT>
-load_mibs(Agent, Mibs) ->
- load_mibs(Agent, Mibs, false).
-%% </BACKWARD-COMPAT>
-
load_mibs(Agent, Mibs, Force) ->
call(Agent, {load_mibs, Mibs, Force}).
-%% Called by administrator (not agent; deadlock would occur)
-%% <BACKWARD-COMPAT>
-unload_mibs(Agent, Mibs) ->
- unload_mibs(Agent, Mibs, false).
-%% </BACKWARD-COMPAT>
-
unload_mibs(Agent, Mibs, Force) ->
call(Agent, {unload_mibs, Mibs, Force}).
@@ -622,51 +597,6 @@ send_notification(Agent, Notification, SendOpts) ->
Msg = {send_notif, Notification, SendOpts},
maybe_call(Agent, Msg).
-%% <BACKWARD-COMPAT>
-send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) ->
- ?d("send_trap -> entry with"
- "~n self(): ~p"
- "~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]),
- SendOpts = [
- {receiver, Recv},
- {varbinds, Varbinds},
- {name, NotifyName},
- {context, CtxName},
- {extra, ?DEFAULT_NOTIF_EXTRA_INFO}
- ],
- send_notification(Agent, Trap, SendOpts).
-
-send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, 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]),
- SendOpts = [
- {receiver, Recv},
- {varbinds, Varbinds},
- {name, NotifyName},
- {context, CtxName},
- {extra, ?DEFAULT_NOTIF_EXTRA_INFO},
- {local_engine_id, LocalEngineID}
- ],
- send_notification(Agent, Trap, SendOpts).
-
-%% </BACKWARD-COMPAT>
-
%% -- Discovery functions --
@@ -863,51 +793,6 @@ handle_info({send_notif, Notification, SendOpts}, S) ->
{noreply, S}
end;
-%% <BACKWARD-COMPAT>
-handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) ->
- ?vlog("[handle_info] send trap request:"
- "~n Trap: ~p"
- "~n NotifyName: ~p"
- "~n ContextName: ~p"
- "~n Recv: ~p"
- "~n Varbinds: ~p",
- [Trap, NotifyName, ContextName, Recv, Varbinds]),
- 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} ->
- {noreply, NewS};
- {'EXIT', R} ->
- ?vinfo("Trap not sent:~n ~p", [R]),
- {noreply, S};
- _ ->
- {noreply, S}
- end;
-
-handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds,
- LocalEngineID}, S) ->
- ?vlog("[handle_info] send trap request:"
- "~n Trap: ~p"
- "~n NotifyName: ~p"
- "~n ContextName: ~p"
- "~n Recv: ~p"
- "~n Varbinds: ~p"
- "~n LocalEngineID: ~p",
- [Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]),
- ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
- case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID, ExtraInfo)) of
- {ok, NewS} ->
- {noreply, NewS};
- {'EXIT', R} ->
- ?vinfo("Trap not sent:~n ~p", [R]),
- {noreply, S};
- _ ->
- {noreply, S}
- end;
-%% </BACKWARD-COMPAT>
-
handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
Recv, Varbinds, ExtraInfo}, S) ->
?vlog("[handle_info] forward trap request:"
@@ -929,30 +814,6 @@ handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
{noreply, S}
end;
-%% <BACKWARD-COMPAT>
-handle_info({forward_trap, TrapRecord, NotifyName, ContextName,
- Recv, Varbinds}, S) ->
- ?vlog("[handle_info] forward trap request:"
- "~n TrapRecord: ~p"
- "~n NotifyName: ~p"
- "~n ContextName: ~p"
- "~n Recv: ~p"
- "~n Varbinds: ~p",
- [TrapRecord, NotifyName, ContextName, Recv, Varbinds]),
- ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
- LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID,
- case (catch maybe_send_trap(S, TrapRecord, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID, ExtraInfo)) of
- {ok, NewS} ->
- {noreply, NewS};
- {'EXIT', R} ->
- ?vinfo("Trap not sent:~n ~p", [R]),
- {noreply, S};
- _ ->
- {noreply, S}
- end;
-%% </BACKWARD-COMPAT>
-
handle_info({backup_done, Reply}, #state{backup = {_, From}} = S) ->
?vlog("[handle_info] backup done:"
"~n Reply: ~p", [Reply]),
@@ -1075,55 +936,6 @@ handle_call({send_notif, Notification, SendOpts}, _From, S) ->
{reply, {error, send_failed}, S}
end;
-%% <BACKWARD-COMPAT>
-handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds},
- _From, S) ->
- ?vlog("[handle_call] send trap request:"
- "~n Trap: ~p"
- "~n NotifyName: ~p"
- "~n ContextName: ~p"
- "~n Recv: ~p"
- "~n Varbinds: ~p",
- [Trap, NotifyName, ContextName, Recv, Varbinds]),
- 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} ->
- {reply, ok, NewS};
- {'EXIT', Reason} ->
- ?vinfo("Trap not sent:~n ~p", [Reason]),
- {reply, {error, {send_failed, Reason}}, S};
- _ ->
- ?vinfo("Trap not sent", []),
- {reply, {error, send_failed}, S}
- end;
-
-handle_call({send_trap, Trap, NotifyName,
- ContextName, Recv, Varbinds, LocalEngineID},
- _From, S) ->
- ?vlog("[handle_call] send trap request:"
- "~n Trap: ~p"
- "~n NotifyName: ~p"
- "~n ContextName: ~p"
- "~n Recv: ~p"
- "~n Varbinds: ~p"
- "~n LocalEngineID: ~p",
- [Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]),
- ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
- case (catch handle_send_trap(S, Trap, NotifyName, ContextName,
- Recv, Varbinds, LocalEngineID, ExtraInfo)) of
- {ok, NewS} ->
- {reply, ok, NewS};
- {'EXIT', Reason} ->
- ?vinfo("Trap not sent:~n ~p", [Reason]),
- {reply, {error, {send_failed, Reason}}, S};
- _ ->
- ?vinfo("Trap not sent", []),
- {reply, {error, send_failed}, S}
- end;
-%% </BACKWARD-COMPAT>
-
handle_call({discovery,
TargetName, Notification, ContextName, Vbs, DiscoHandler,
ExtraInfo},
@@ -1262,22 +1074,10 @@ handle_call({unregister_subagent, SubTreeOid}, _From, S) ->
end,
{reply, Reply, S};
-%% <BACKWARD-COMPAT>
-handle_call({load_mibs, Mibs}, _From, S) ->
- ?vlog("load mibs ~p", [Mibs]),
- {reply, snmpa_mib:load_mibs(get(mibserver), Mibs), S};
-%% </BACKWARD-COMPAT>
-
handle_call({load_mibs, Mibs, Force}, _From, S) ->
?vlog("[~w] load mibs ~p", [Force, Mibs]),
{reply, snmpa_mib:load_mibs(get(mibserver), Mibs, Force), S};
-%% <BACKWARD-COMPAT>
-handle_call({unload_mibs, Mibs}, _From, S) ->
- ?vlog("unload mibs ~p", [Mibs]),
- {reply, snmpa_mib:unload_mibs(get(mibserver), Mibs), S};
-%% </BACKWARD-COMPAT>
-
handle_call({unload_mibs, Mibs, Force}, _From, S) ->
?vlog("[~w] unload mibs ~p", [Force, Mibs]),
{reply, snmpa_mib:unload_mibs(get(mibserver), Mibs, Force), S};
@@ -1876,46 +1676,6 @@ worker_loop(Master, Report) ->
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
@@ -1972,12 +1732,6 @@ 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))),
@@ -1987,7 +1741,7 @@ handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra, Dict) ->
handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) ->
%% OTP-3324
AuthMod = get(auth_module),
- case AuthMod:init_check_access(Pdu, ACMData) of
+ try AuthMod:init_check_access(Pdu, ACMData) of
{ok, MibView, ContextName} ->
?vlog("handle_pdu -> ok:"
"~n MibView: ~p"
@@ -2005,6 +1759,13 @@ handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) ->
"~n Reason: ~p", [Variable, Reason]),
get(net_if) ! {discarded_pdu, Vsn, Pdu#pdu.request_id,
ACMData, Variable, Extra}
+ catch
+ Class:Error:Stack ->
+ ?vinfo("handle_pdu -> crash:"
+ "~n Class: ~p"
+ "~n Error: ~p"
+ "~n Stack: ~p", [Class, Error, Stack]),
+ handle_acm_error(Vsn, Error, Pdu, ACMData, Address, Extra)
end.
do_handle_pdu(MibView, Vsn, Pdu, PduMS,
@@ -2373,7 +2134,7 @@ handle_discovery_response(#state{disco = #disco{target = TargetName,
"~n ManagerEngineId: ~p", [TargetName, ManagerEngineId]),
%% This is end of stage 1.
%% So, first we need to update the database with the EngineId of the
- %% manager and then deside if we should continue with stage 2. E.g.
+ %% manager and then decide if we should continue with stage 2. E.g.
%% establish authenticated communication.
case snmp_target_mib:set_target_engine_id(TargetName, ManagerEngineId) of
true when Disco#disco.sec_level =:= ?'SnmpSecurityLevel_noAuthNoPriv' ->
@@ -2766,7 +2527,7 @@ validate_next_v1_2([], _MibView, Res) ->
%% column, we'll try to find the next instance. This will be the
%% next row in the table, which is a Counter64 value as well. This
%% means that we will loop through the entire table, until we find
-%% a column that isn't a Counter64 column. We can optimze this by
+%% a column that isn't a Counter64 column. We can optimize this by
%% adding 1 to the column-no in the oid of this instance.
%% If the table is implemented by a subagent this does not help,
%% we'll call that subagent many times. But it shouldn't be any
@@ -3462,8 +3223,8 @@ get_stats_counters([Counter|Counters], Acc) ->
%% ---------------------------------------------------------------------
-%% info_msg(F, A) ->
-%% ?snmpa_info(F, A).
+info_msg(F, A) ->
+ ?snmpa_info(F, A).
warning_msg(F, A) ->
?snmpa_warning(F, A).
diff --git a/lib/snmp/src/agent/snmpa_agent_sup.erl b/lib/snmp/src/agent/snmpa_agent_sup.erl
index 0a5116b2d0..b1eeaba988 100644
--- a/lib/snmp/src/agent/snmpa_agent_sup.erl
+++ b/lib/snmp/src/agent/snmpa_agent_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,7 +24,9 @@
-behaviour(supervisor).
%% External exports
--export([start_link/0, start_link/1, start_subagent/3, stop_subagent/1]).
+-export([start_link/0, start_link/1,
+ start_master_agent/1,
+ start_subagent/3, stop_subagent/1]).
%% Internal exports
-export([init/1]).
@@ -40,8 +42,7 @@
%%%-----------------------------------------------------------------
-%%% This is a supervisor for the mib processes. Each agent has one
-%%% mib process.
+%%% This is a supervisor for the agent processes (master and sub).
%%%-----------------------------------------------------------------
start_link() ->
?d("start_link -> entry", []),
@@ -52,6 +53,9 @@ start_link(AgentSpec) ->
"~n AgentSpec: ~p", [AgentSpec]),
supervisor:start_link({local, ?SERVER}, ?MODULE, [[AgentSpec]]).
+start_master_agent(MasterAgentSpec) ->
+ supervisor:start_child(snmpa_agent_sup, MasterAgentSpec).
+
start_subagent(ParentAgent, Subtree, Mibs) ->
?d("start_subagent -> entry with"
"~n ParentAgent: ~p"
diff --git a/lib/snmp/src/agent/snmpa_general_db.erl b/lib/snmp/src/agent/snmpa_general_db.erl
index a1e91b2b3c..306bb79769 100644
--- a/lib/snmp/src/agent/snmpa_general_db.erl
+++ b/lib/snmp/src/agent/snmpa_general_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@
%% Open or create a database table. In the mnesia/dets case,
%% where the table is stored on disc, it could be of interest
%% to clear the table. This is controlled by the Action parameter.
-%% An empty node list ([]), is traslated into a list containing
+%% An empty node list ([]), is translated into a list containing
%% only the own node.
%% ---------------------------------------------------------------
open({mnesia,Nodes,clear}, Name, RecName, Attr, Type) when is_list(Nodes) ->
diff --git a/lib/snmp/src/agent/snmpa_get.erl b/lib/snmp/src/agent/snmpa_get.erl
index c4f4f44095..dab90ff14e 100644
--- a/lib/snmp/src/agent/snmpa_get.erl
+++ b/lib/snmp/src/agent/snmpa_get.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,13 @@
do_get_bulk/7
]).
+%% Debugging
+-export([
+ empty_pdu/0, empty_pdu/1,
+ empty_scoped_pdu/0, empty_scoped_pdu/1,
+ empty_pdu_size/0, empty_scoped_pdu_size/0
+ ]).
+
-define(VMODULE,"GET").
-include("snmpa_internal.hrl").
-include("snmp_types.hrl").
@@ -43,7 +50,9 @@
-define(default_verbosity,silence).
-endif.
--define(empty_pdu_size, 21).
+-ifndef(empty_pdu_size).
+-define(empty_pdu_size, 21). % See below!
+-endif.
-ifdef(snmp_extended_verbosity).
-define(vt(F,A), ?vtrace(F, A)).
@@ -57,6 +66,80 @@
+%%-----------------------------------------------------------------
+%% Purpose: We must calculate the length of an empty Pdu. This
+%% length is used to calculate the max pdu size allowed
+%% for each get-bulk-request.
+%% This size is dependent on the varbinds.
+%% It is calculated as EmptySize + 8. 8 comes from the
+%% fact that the maximum pdu size needs 31 bits which needs
+%% 5 * 7 bits to be expressed. One 7bit octet is already
+%% present in the empty pdu, leaving 4 more 7bit octets.
+%% The length is repeated twice, once for the varbinds,
+%% and once for the entire pdu; 2 * 4 = 8.
+%%
+%% Actually, this function is not used, we use a constant instead.
+%%
+%%-----------------------------------------------------------------
+%%
+%% Some wierdness is going on since this seems to be insufficient,
+%% atleast on version 3.
+%% One of the issues is that the constant (21) is only correct if
+%% request-id < 128 (as is the case in the example below).
+%% But adding 8 to this solves the problem => 29 (atleast for the
+%% customer reporting the issue).
+%% Since it is version 3, should we use the scopedPDU for the
+%% calculation?
+%%
+%%-----------------------------------------------------------------
+%% Ret: 21 (see above)
+%% empty_pdu_size() ->
+%% Pdu = #pdu{type = 'get-response',
+%% request_id = 1,
+%% error_status = noError,
+%% error_index = 0,
+%% varbinds = []},
+%% length(snmp_pdus:enc_pdu(Pdu)) + 8.
+
+empty_pdu() ->
+ empty_pdu(1).
+empty_pdu(RequestId) when is_integer(RequestId) andalso (RequestId > 0) ->
+ #pdu{type = 'get-response',
+ request_id = RequestId,
+ error_status = noError,
+ error_index = 0,
+ varbinds = []}.
+
+%% empty_pdu_size() ->
+%% empty_pdu_size(1).
+%% empty_pdu_size(RequestId) ->
+%% length(snmp_pdus:enc_pdu(empty_pdu(RequestId))) + 8.
+
+empty_pdu_size() ->
+ ?empty_pdu_size.
+
+
+%% This is used when calculating how many VBs to include in a pdu.
+%% For "some reason" we need to add 8 to the size for version 3.
+%% Could be the context EngineID and Name, which is actuall part
+%% of the scoped PDU?
+
+empty_scoped_pdu() ->
+ empty_scoped_pdu(1).
+empty_scoped_pdu(RequestId) ->
+ #scopedPdu{contextEngineID = "",
+ contextName = "",
+ data = empty_pdu(RequestId)}.
+
+%% empty_scoped_pdu_size() ->
+%% empty_scoped_pdu_size(1).
+%% empty_scoped_pdu_size(RequestId) ->
+%% length(snmp_pdus:enc_scoped_pdu(empty_scoped_pdu(RequestId))) + 8.
+
+empty_scoped_pdu_size() ->
+ ?empty_pdu_size + 6.
+
+
%%%-----------------------------------------------------------------
%%% 3. GET REQUEST
%%% --------------
@@ -143,7 +226,7 @@ do_get_local([], Res, _IsNotification) ->
%%-----------------------------------------------------------------
%% Func: do_get_subagents/2
%% Purpose: Loop the list of varbinds for different subagents.
-%% For each of them, call sub_agent_get to retreive
+%% For each of them, call sub_agent_get to retrieve
%% the values for them.
%% Returns: {noError, 0, ListOfNewVarbinds} |
%% {ErrorStatus, ErrorIndex, []}
@@ -928,7 +1011,7 @@ validate_tab_next_res(TooMany, [], Mfa, _Res, _, _, I) ->
%%-----------------------------------------------------------------
%% Func: get_next_sa/4
%% Purpose: Loop the list of varbinds for the subagent.
-%% Call subagent_get_next to retreive
+%% Call subagent_get_next to retrieve
%% the next varbinds.
%% Returns: {ok, ListOfNewVbs, ListOfEndOfMibViewsVbs} |
%% {ErrorStatus, ErrorIndex}
diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl
index c9093fcdb9..2b6588b412 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-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -663,7 +663,7 @@ code_change(_Vsn, State, _Extra) ->
%%----------------------------------------------------------
handle_backup(D, BackupDir) ->
- %% First check that we do not wrote to the corrent db-dir...
+ %% First check that we do not wrote to the current db-dir...
?vtrace("handle_backup -> entry with"
"~n D: ~p"
"~n BackupDir: ~p", [D, BackupDir]),
@@ -1031,7 +1031,7 @@ table_get_elements(NameDb, RowIndex, Cols, _FirstOwnIndex) ->
get_elements(_Cols, undefined) ->
undefined;
-get_elements([Col | Cols], Row) when is_tuple(Row) and (size(Row) >= Col) ->
+get_elements([Col | Cols], Row) when tuple_size(Row) >= Col ->
[element(Col, Row) | get_elements(Cols, Row)];
get_elements([], _Row) ->
[];
@@ -1215,7 +1215,7 @@ cast(Msg) ->
%% ----------------------------------------------------------------
%% DETS wrapper functions
-%% The purpose of these fuctions is basically to hide the shadow
+%% The purpose of these functions is basically to hide the shadow
%% table.
%% Changes are made both in dets and in the shadow table.
%% Reads are made from the shadow table.
diff --git a/lib/snmp/src/agent/snmpa_mib.erl b/lib/snmp/src/agent/snmpa_mib.erl
index fe98fc2585..23d5468897 100644
--- a/lib/snmp/src/agent/snmpa_mib.erl
+++ b/lib/snmp/src/agent/snmpa_mib.erl
@@ -47,11 +47,6 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
code_change/3]).
-%% <BACKWARD-COMPAT>
--export([load_mibs/2, unload_mibs/2]).
-%% </BACKWARD-COMPAT>
-
-
-include_lib("kernel/include/file.hrl").
-include("snmpa_internal.hrl").
-include("snmp_types.hrl").
@@ -204,11 +199,6 @@ next(MibServer, Oid, MibView) ->
%% Returns: ok | {error, Reason}
%%----------------------------------------------------------------------
-%% <BACKWARD-COMPAT>
-load_mibs(MibServer, Mibs) ->
- load_mibs(MibServer, Mibs, false).
-%% </BACKWARD-COMPAT>
-
load_mibs(MibServer, Mibs, Force) ->
call(MibServer, {load_mibs, Mibs, Force}).
@@ -219,10 +209,6 @@ load_mibs(MibServer, Mibs, Force) ->
%% Force is a boolean
%% Returns: ok | {error, Reason}
%%----------------------------------------------------------------------
-%% <BACKWARD-COMPAT>
-unload_mibs(MibServer, Mibs) ->
- unload_mibs(MibServer, Mibs, false).
-%% </BACKWARD-COMPAT>
unload_mibs(MibServer, Mibs, Force) ->
call(MibServer, {unload_mibs, Mibs, Force}).
@@ -514,11 +500,6 @@ handle_call({next, Oid, MibView}, _From,
?vdebug("next -> Reply: ~p", [Reply]),
{reply, Reply, NewState};
-%% <BACKWARD-COMPAT>
-handle_call({load_mibs, Mibs}, From, State) ->
- handle_call({load_mibs, Mibs, false}, From, State);
-%% </BACKWARD-COMPAT>
-
handle_call({load_mibs, Mibs, Force}, _From,
#state{data = Data,
teo = TeOverride,
@@ -540,11 +521,6 @@ handle_call({load_mibs, Mibs, Force}, _From,
Mod:sync(NData),
{reply, Reply, State#state{data = NData, cache = NewCache}};
-%% <BACKWARD-COMPAT>
-handle_call({unload_mibs, Mibs}, From, State) ->
- handle_call({unload_mibs, Mibs, false}, From, State);
-%% </BACKWARD-COMPAT>
-
handle_call({unload_mibs, Mibs, Force}, _From,
#state{data = Data,
teo = TeOverride,
diff --git a/lib/snmp/src/agent/snmpa_mib_data_ttln.erl b/lib/snmp/src/agent/snmpa_mib_data_ttln.erl
index 959230b1dd..2b4493d527 100644
--- a/lib/snmp/src/agent/snmpa_mib_data_ttln.erl
+++ b/lib/snmp/src/agent/snmpa_mib_data_ttln.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -753,7 +753,7 @@ find_node(_D, Node, _RestOfOid, _RevOid) ->
%% {subagent, SubAgentPid, SAOid} |
%% {variable, MibEntry, VarOid} |
%% {table, TableOid, TableRestOid, MibEntry}
-%% If a variable is returnes, it is in the MibView.
+%% If a variable is returns, it is in the MibView.
%% If a table or subagent is returned, it *may* be in the MibView.
%%-----------------------------------------------------------------
next(#mib_data{tree = T} = D, Oid, MibView) ->
@@ -777,10 +777,10 @@ next_node(_D, undefined_node, _Oid, _RevOidSoFar, _MibView) ->
next_node(_D, {tree, Tree, {table_entry, _Id}}, [Int | _Oid],
_RevOidSoFar, _MibView)
- when Int+1 > size(Tree) ->
- ?vtrace("next_node(tree,table_entry) -> entry when not found whith"
+ when Int+1 > tuple_size(Tree) ->
+ ?vtrace("next_node(tree,table_entry) -> entry when not found within"
"~n Int: ~p"
- "~n size(Tree): ~p", [Int, size(Tree)]),
+ "~n size(Tree): ~p", [Int, tuple_size(Tree)]),
false;
next_node(D, {tree, Tree, {table_entry, _MibName}},
Oid, RevOidSoFar, MibView) ->
@@ -788,7 +788,7 @@ next_node(D, {tree, Tree, {table_entry, _MibName}},
"~n size(Tree): ~p"
"~n Oid: ~p"
"~n RevOidSoFar: ~p"
- "~n MibView: ~p", [size(Tree), Oid, RevOidSoFar, MibView]),
+ "~n MibView: ~p", [tuple_size(Tree), Oid, RevOidSoFar, MibView]),
OidSoFar = lists:reverse(RevOidSoFar),
case snmpa_acm:is_definitely_not_in_mib_view(OidSoFar, MibView) of
true ->
@@ -809,14 +809,14 @@ next_node(D, {tree, Tree, {table_entry, _MibName}},
end;
next_node(D, {tree, Tree, _Info}, [Int | RestOfOid], RevOidSoFar, MibView)
- when (Int < size(Tree)) andalso (Int >= 0) ->
+ when (Int < tuple_size(Tree)) andalso (Int >= 0) ->
?vtrace("next_node(tree) -> entry when"
"~n size(Tree): ~p"
"~n Int: ~p"
"~n RestOfOid: ~p"
"~n RevOidSoFar: ~p"
"~n MibView: ~p",
- [size(Tree), Int, RestOfOid, RevOidSoFar, MibView]),
+ [tuple_size(Tree), Int, RestOfOid, RevOidSoFar, MibView]),
case next_node(D, element(Int+1,Tree),
RestOfOid, [Int|RevOidSoFar], MibView) of
false ->
@@ -830,11 +830,11 @@ next_node(D, {tree, Tree, _Info}, [], RevOidSoFar, MibView) ->
"~n size(Tree): ~p"
"~n RevOidSoFar: ~p"
"~n MibView: ~p",
- [size(Tree), RevOidSoFar, MibView]),
+ [tuple_size(Tree), RevOidSoFar, MibView]),
find_next(D, {tree, Tree, _Info}, 0, RevOidSoFar, MibView);
next_node(_D, {tree, Tree, _Info}, _RestOfOid, _RevOidSoFar, _MibView) ->
?vtrace("next_node(tree) -> entry when"
- "~n size(Tree): ~p", [size(Tree)]),
+ "~n size(Tree): ~p", [tuple_size(Tree)]),
false;
next_node(D, {node, subagent}, Oid, RevOidSoFar, MibView) ->
@@ -896,7 +896,7 @@ next_node(_D, {node, {variable, _MibName}}, _Oid, _RevOidSoFar, _MibView) ->
%% node.
%%-----------------------------------------------------------------
find_next(D, {tree, Tree, internal}, Idx, RevOidSoFar, MibView)
- when Idx < size(Tree) ->
+ when Idx < tuple_size(Tree) ->
case find_next(D, element(Idx+1, Tree), 0, [Idx| RevOidSoFar], MibView) of
false ->
find_next(D, {tree, Tree, internal}, Idx+1, RevOidSoFar, MibView);
diff --git a/lib/snmp/src/agent/snmpa_mib_data_tttn.erl b/lib/snmp/src/agent/snmpa_mib_data_tttn.erl
index 9b4493a03f..39ed23809e 100644
--- a/lib/snmp/src/agent/snmpa_mib_data_tttn.erl
+++ b/lib/snmp/src/agent/snmpa_mib_data_tttn.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -780,7 +780,7 @@ find_node(_D, Node, _RestOfOid, _RevOid) ->
%% {subagent, SubAgentPid, SAOid} |
%% {variable, MibEntry, VarOid} |
%% {table, TableOid, TableRestOid, MibEntry}
-%% If a variable is returnes, it is in the MibView.
+%% If a variable is returns, it is in the MibView.
%% If a table or subagent is returned, it *may* be in the MibView.
%%-----------------------------------------------------------------
next(#mib_data{tree = T} = D, Oid, MibView) ->
@@ -804,10 +804,10 @@ next_node(_D, undefined_node, _Oid, _RevOidSoFar, _MibView) ->
next_node(_D, {tree, Tree, {table_entry, _Id}}, [Int | _Oid],
_RevOidSoFar, _MibView)
- when Int+1 > size(Tree) ->
- ?vtrace("next_node(tree,table_entry) -> entry when not found whith"
+ when Int+1 > tuple_size(Tree) ->
+ ?vtrace("next_node(tree,table_entry) -> entry when not found within"
"~n Int: ~p"
- "~n size(Tree): ~p", [Int, size(Tree)]),
+ "~n size(Tree): ~p", [Int, tuple_size(Tree)]),
false;
next_node(D, {tree, Tree, {table_entry, _MibName}},
Oid, RevOidSoFar, MibView) ->
@@ -815,7 +815,7 @@ next_node(D, {tree, Tree, {table_entry, _MibName}},
"~n size(Tree): ~p"
"~n Oid: ~p"
"~n RevOidSoFar: ~p"
- "~n MibView: ~p", [size(Tree), Oid, RevOidSoFar, MibView]),
+ "~n MibView: ~p", [tuple_size(Tree), Oid, RevOidSoFar, MibView]),
OidSoFar = lists:reverse(RevOidSoFar),
case snmpa_acm:is_definitely_not_in_mib_view(OidSoFar, MibView) of
true ->
@@ -836,14 +836,14 @@ next_node(D, {tree, Tree, {table_entry, _MibName}},
end;
next_node(D, {tree, Tree, _Info}, [Int | RestOfOid], RevOidSoFar, MibView)
- when (Int < size(Tree)) andalso (Int >= 0) ->
+ when (Int < tuple_size(Tree)) andalso (Int >= 0) ->
?vtrace("next_node(tree) -> entry when"
"~n size(Tree): ~p"
"~n Int: ~p"
"~n RestOfOid: ~p"
"~n RevOidSoFar: ~p"
"~n MibView: ~p",
- [size(Tree), Int, RestOfOid, RevOidSoFar, MibView]),
+ [tuple_size(Tree), Int, RestOfOid, RevOidSoFar, MibView]),
case next_node(D, element(Int+1,Tree),
RestOfOid, [Int|RevOidSoFar], MibView) of
false ->
@@ -857,11 +857,11 @@ next_node(D, {tree, Tree, _Info}, [], RevOidSoFar, MibView) ->
"~n size(Tree): ~p"
"~n RevOidSoFar: ~p"
"~n MibView: ~p",
- [size(Tree), RevOidSoFar, MibView]),
+ [tuple_size(Tree), RevOidSoFar, MibView]),
find_next(D, {tree, Tree, _Info}, 0, RevOidSoFar, MibView);
next_node(_D, {tree, Tree, _Info}, _RestOfOid, _RevOidSoFar, _MibView) ->
?vtrace("next_node(tree) -> entry when"
- "~n size(Tree): ~p", [size(Tree)]),
+ "~n size(Tree): ~p", [tuple_size(Tree)]),
false;
next_node(D, {node, subagent}, Oid, RevOidSoFar, MibView) ->
@@ -924,7 +924,7 @@ next_node(_D, {node, {variable, _MibName}}, _Oid, _RevOidSoFar, _MibView) ->
%% node.
%%-----------------------------------------------------------------
find_next(D, {tree, Tree, internal}, Idx, RevOidSoFar, MibView)
- when Idx < size(Tree) ->
+ when Idx < tuple_size(Tree) ->
case find_next(D, element(Idx+1, Tree), 0, [Idx| RevOidSoFar], MibView) of
false ->
find_next(D, {tree, Tree, internal}, Idx+1, RevOidSoFar, MibView);
diff --git a/lib/snmp/src/agent/snmpa_mib_lib.erl b/lib/snmp/src/agent/snmpa_mib_lib.erl
index ecdf968458..ad2840a33f 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ table_del_row({Tab, Db} = TabDb, Key) ->
%%%-----------------------------------------------------------------
-%%% Retreives the entire table. Used for debugging
+%%% Retrieves the entire table. Used for debugging
%%%-----------------------------------------------------------------
get_table(NameDb, FOI) ->
diff --git a/lib/snmp/src/agent/snmpa_mib_storage.erl b/lib/snmp/src/agent/snmpa_mib_storage.erl
index d46dab0be0..508af51f18 100644
--- a/lib/snmp/src/agent/snmpa_mib_storage.erl
+++ b/lib/snmp/src/agent/snmpa_mib_storage.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@
%% (of the behaviour), this is done using the *Options* argument.
%% ---------------------------------------------------------------
-%% Options is callback module dependant
+%% Options is callback module dependent
-callback open(Name :: atom(),
RecName :: atom(),
diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl
index 0d40840d35..9c520a7071 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,6 +28,13 @@
process_taddrs/1,
generate_req_id/0]).
+%% This is just for debugging and testing
+-export([
+ empty_msg/0,
+ empty_msg_size/0
+ ]).
+
+
-define(SNMP_USE_V3, true).
-include("snmp_types.hrl").
-include("SNMP-MPD-MIB.hrl").
@@ -39,7 +46,11 @@
-include("snmp_verbosity.hrl").
-include("snmpa_internal.hrl").
+-ifdef(empty_pdu_size).
+-define(empty_msg_size, ?empty_pdu_size + 3).
+-else.
-define(empty_msg_size, 24).
+-endif.
-record(state, {v1 = false, v2c = false, v3 = false}).
-record(note, {sec_engine_id,
@@ -51,9 +62,9 @@
disco = false,
req_id}).
-
+
%%%-----------------------------------------------------------------
-%%% This module implemets the Message Processing and Dispatch part of
+%%% This module implements the Message Processing and Dispatch part of
%%% the multi-lingual SNMP agent.
%%%
%%% The MPD is responsible for:
@@ -70,7 +81,7 @@
%%% the counters only, it does not provide instrumentation functions
%%% for the counters.
%%%
-%%% With the terms defined in rfc2271, this module implememts part
+%%% With the terms defined in rfc2271, this module implements part
%%% of the Dispatcher and the Message Processing functionality.
%%%-----------------------------------------------------------------
init(Vsns) ->
@@ -88,14 +99,13 @@ reset() ->
ok.
-%%-----------------------------------------------------------------
-%% Purpose: We must calculate the length of a
-%% message with an empty Pdu, and zero-length community
-%% string. This length is used to calculate the max
-%% pdu size allowed for each request. This size is
-%% dependent on two dynamic fields, the community string
-%% and the pdu (varbinds actually). It is calculated
-%% as EmptySize + length(CommunityString) + 4.
+%%--------------------------------------------------------------------------
+%% Purpose: We must calculate the length of a message with an empty Pdu
+%% and zero-length community string.
+%% This length is used to calculate the max pdu size allowed for
+%% each request. This size is dependent on two dynamic fields;
+%% the community string and the pdu (varbinds actually).
+%% It is calculated as EmptySize + length(CommunityString) + 4.
%% We assume that the length of the CommunityString is
%% less than 128 (thus requiring just one octet for the
%% length field (the same as the zero-length community
@@ -104,13 +114,28 @@ reset() ->
%% expressed. One 7bit octet is already present in the
%% empty msg, leaving 4 more 7bit octets.
%% Actually, this function is not used, we use a constant instead.
-%%-----------------------------------------------------------------
+%%--------------------------------------------------------------------------
%% Ret: 24
-%empty_msg() ->
-% M = #message{version = 'version-1', community = "", data =
-% #pdu{type = 'get-response', request_id = 1,
-% error_status = noError, error_index = 0, varbinds = []}},
-% length(snmp_pdus:enc_message(M)) + 4.
+%%empty_msg() ->
+%% M = #message{version = 'version-1', community = "", data =
+%% #pdu{type = 'get-response', request_id = 1,
+%% error_status = noError, error_index = 0, varbinds = []}},
+%% length(snmp_pdus:enc_message(M)) + 4.
+
+-ifdef(SNMP_USE_V3).
+empty_msg() ->
+ {message, 'version-1', "", snmpa_get:empty_pdu()}.
+-else.
+empty_msg() ->
+ #message{version = 'version-1',
+ community = "",
+ data = snmpa_get:empty_pdu()}.
+-endif.
+
+empty_msg_size() ->
+ ?empty_msg_size.
+
+
%%-----------------------------------------------------------------
%% Func: process_packet(Packet, Domain, Address, State, Log) ->
@@ -648,7 +673,7 @@ generate_response_msg(Vsn, RePdu, Type,
{discarded, Reason};
Packet ->
MMS = get_engine_max_message_size(LocalEngineID),
- case size(Packet) of
+ case byte_size(Packet) of
Len when Len =< MMS ->
Log(Type, Packet),
inc_snmp_cnt_vars(Type, RePdu),
@@ -717,7 +742,7 @@ generate_response_msg(Vsn, RePdu, Type,
%% because of the calculation we do when we
%% receive the bulk-request.
Packet = list_to_binary(OutMsg),
- case size(Packet) of
+ case byte_size(Packet) of
Len when Len =< AgentMS ->
if
SecLevel =:= 3 ->
@@ -907,7 +932,7 @@ generate_msg(Vsn, _NoteStore, Pdu, {community, Community}, LocalEngineID, To) ->
{discarded, Reason};
Packet ->
AgentMax = get_engine_max_message_size(LocalEngineID),
- case size(Packet) of
+ case byte_size(Packet) of
Len when Len =< AgentMax ->
{ok, mk_v1_v2_packet_list(To, Packet, Len, Pdu)};
Len ->
@@ -1296,7 +1321,7 @@ mk_v3_packet_entry(NoteStore, Domain, Addr,
%% Store in cache for 150 sec.
Packet = list_to_binary(OutMsg),
?vdebug("mk_v3_packet_entry -> generated: ~w bytes",
- [size(Packet)]),
+ [byte_size(Packet)]),
Data =
if
SecLevel =:= 3 ->
@@ -1535,3 +1560,4 @@ user_err(F, A) ->
config_err(F, A) ->
snmpa_error:config_err(F, A).
+
diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl
index bd19a32159..72e3ac3e41 100644
--- a/lib/snmp/src/agent/snmpa_net_if.erl
+++ b/lib/snmp/src/agent/snmpa_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@
%% Also, the request-reponder and trap-sender transport(s),
%% has different needs.
%% The trap-sender transport will send more data then it will receive.
-%% Therefor, we should be able to specify;
+%% Therefore, we should be able to specify;
%% bind_to, no_reuse_address, recbuf and sndbuf individually:
%% {intAgentTransports,
%% [{transportDomainUdpIpv4, {{141,213,11,24}, PortInfo},
@@ -122,7 +122,7 @@
%% Note that since informs require confirmation,
%% an ephemeral socket cannot be removed immediately
%% when it has been "used up".
-%% We need to keep it for some time to receive responces
+%% We need to keep it for some time to receive responses
%% and in case a resend is needed!.
%% </EPHEMERAL-FOR-FUTUR-USE>
@@ -235,11 +235,21 @@ init(Prio, NoteStore, MasterAgent, Parent, Opts) ->
end,
erlang:raise(C, E, S)
end;
- {error, Reason} ->
- config_err("failed starting net-if: ~n~p", [Reason]),
- proc_lib:init_ack({error, Reason});
+ {error, {udp_open, {open, PortNo, Reason}}} ->
+ OEFilters = get_open_err_filters(Opts),
+ Class =
+ case lists:member(Reason, OEFilters) of
+ false ->
+ error;
+ true ->
+ info
+ end,
+ proc_lib:init_ack({error, {Class, udp_open, PortNo, Reason}});
+ {error, Reason} ->
+ %% config_err("failed starting net-if: ~n~p", [Reason]),
+ proc_lib:init_ack({error, Reason});
Error ->
- config_err("failed starting net-if: ~n~p", [Error]),
+ %% config_err("failed starting net-if: ~n~p", [Error]),
proc_lib:init_ack({error, Error})
end.
@@ -256,7 +266,7 @@ do_init(Prio, NoteStore, MasterAgent, Parent, Opts) ->
Vsns = get_vsns(Opts),
?vdebug("vsns: ~w",[Vsns]),
- %% Flow control --
+ %% -- Flow control --
Limit = get_req_limit(Opts),
?vdebug("Limit: ~w", [Limit]),
FilterOpts = get_filter_opts(Opts),
@@ -475,7 +485,7 @@ gen_udp_open(system, Opts) ->
throw({udp_open, {port, PReason}})
end;
{error, OReason} ->
- throw({udp_open, {open, OReason}})
+ throw({udp_open, {open, 0, OReason}})
end;
%% This is for "future compat" since we cannot actually config '0'...
gen_udp_open(IpPort, Opts) when (IpPort =:= 0) ->
@@ -533,7 +543,7 @@ gen_udp_range_open(Min, Max, Opts) ->
gen_udp_range_open(Min+1, Max, Opts);
{error, Reason} ->
?vdebug("gen_udp_range_open(~w,~w) -> ~w", [Reason]),
- throw({udp_open, {open, Reason}})
+ throw({udp_open, {open, Min, Reason}})
catch
C:E:S ->
?vinfo("gen_udp_range_open(~w,~w) -> failed open socket: "
@@ -573,7 +583,7 @@ loop(#state{transports = Transports,
?vdebug("loop(~p)", [S]),
receive
{udp, Socket, IpAddr, IpPort, Packet} = Msg ->
- ?vlog("got paket from ~w:~w on ~w", [IpAddr, IpPort, Socket]),
+ ?vlog("got packet from ~w:~w on ~w", [IpAddr, IpPort, Socket]),
case lists:keyfind(Socket, #transport.socket, Transports) of
#transport{socket = Socket, domain = Domain} = Transport ->
From =
@@ -679,18 +689,6 @@ loop(#state{transports = Transports,
loop(NewS);
%% Discovery Inform
- %% <BACKWARD-COMPAT>
- {send_discovery, Pdu, MsgData, To, From} ->
- ?vdebug("received send discovery request: "
- "~n Pdu: ~p"
- "~n To: ~p"
- "~n From: ~p",
- [Pdu, To, toname(From)]),
- NewS = handle_send_discovery(S, Pdu, MsgData, To, From),
- loop(NewS);
- %% </BACKWARD-COMPAT>
-
- %% Discovery Inform
{send_discovery, Pdu, MsgData, To, From, ExtraInfo} ->
?vdebug("received send discovery request: "
"~n Pdu: ~p"
@@ -1668,7 +1666,7 @@ udp_send(Socket, To, B) ->
ok;
ok ->
%% For future use! Ephemeral ports!
- {ok, size(B)}
+ {ok, byte_size(B)}
catch
error:ExitReason:StackTrace ->
error_msg("[exit] cannot send message "
@@ -1677,7 +1675,7 @@ udp_send(Socket, To, B) ->
end.
sz(L) when is_list(L) -> length(L);
-sz(B) when is_binary(B) -> size(B);
+sz(B) when is_binary(B) -> byte_size(B);
sz(_) -> undefined.
@@ -1900,9 +1898,18 @@ handle_set_request_limit(State, BadLimit) ->
system_continue(_Parent, _Dbg, S) ->
loop(S).
-system_terminate(Reason, _Parent, _Dbg, #state{log = Log}) ->
+system_terminate(Reason, _Parent, _Dbg, #state{log = Log,
+ transports = Transports}) ->
?vlog("system-terminate -> entry with"
"~n Reason: ~p", [Reason]),
+ %% Close all transports
+ Close =
+ fun(S) ->
+ ?vlog("try close socket ~p", [S]),
+ (catch gen_udp:close(S))
+ end,
+ _ = [Close(Socket) || #transport{socket = Socket} <- Transports],
+ %% Close logs
do_close_log(Log),
exit(Reason).
@@ -2104,6 +2111,16 @@ get_filter_opts(O) ->
get_filter_module(O) ->
snmp_misc:get_option(module, O, ?DEFAULT_FILTER_MODULE).
+get_open_err_filters(O) ->
+ case snmp_misc:get_option(open_err_filters, O, []) of
+ Filters when is_list(Filters) ->
+ Filters;
+ Filter when is_atom(Filter) ->
+ [Filter];
+ _ ->
+ []
+ end.
+
get_recbuf(Opts, DefaultOpts) ->
get_socket_opt(recbuf, Opts, DefaultOpts, use_default).
@@ -2123,7 +2140,7 @@ get_inet_backend(Opts, DefaultOpts) ->
get_socket_opt(inet_backend, Opts, DefaultOpts, use_default).
%% <EPHEMERAL-FOR-FUTUR-USE>
-%% This is not realy a socket option, but rather socket 'meta'
+%% This is not really a socket option, but rather socket 'meta'
%% information. Its still put together with the actual socket
%% options.
%% get_ephemeral(SocketOpts) ->
@@ -2156,8 +2173,8 @@ info_msg(F,A) ->
user_err(F, A) ->
snmpa_error:user_err(F, A).
-config_err(F, A) ->
- snmpa_error:config_err(F, A).
+%% config_err(F, A) ->
+%% snmpa_error:config_err(F, A).
%% ----------------------------------------------------------------
diff --git a/lib/snmp/src/agent/snmpa_network_interface_filter.erl b/lib/snmp/src/agent/snmpa_network_interface_filter.erl
index 1524a6447b..d67d945b8a 100644
--- a/lib/snmp/src/agent/snmpa_network_interface_filter.erl
+++ b/lib/snmp/src/agent/snmpa_network_interface_filter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ behaviour_info(_) ->
%% accept_recv({domain(), address()}) -> boolean()
-%% Called at the receiption of a message
+%% Called at the reception of a message
%% (before *any* processing has been done).
%%
%% accept_send({domain(), address()}) -> boolean()
diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl
index 89580ad8e1..5943b850bf 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@
%% Input is a sorted Varbinds list.
%% Output is either ok or {ErrIndex, ErrCode}.
%%* 1) IF the variable is outside the mib view THEN noAccess.
-%%* 2a) IF the varaible doesn't exist THEN notWritable.
+%%* 2a) IF the variable doesn't exist THEN notWritable.
%% 2b) IF mib isn't able to create instances of the variable (for
%% example in a table) THEN noCreation.
%%* 3) IF the new value provided is of the wrong ASN.1 type THEN wrongType.
@@ -59,7 +59,7 @@
%%
%% SNMPv1 (see rfc1157:4.1.5)
%%* 1) IF variable not available for set in the mibview THEN noSuchName.
-%%* 2) IF variable exists, but doesn't permit writeing THEN readOnly.
+%%* 2) IF variable exists, but doesn't permit writing THEN readOnly.
%%* 3) IF provided value doesn't match ASN.1 type THEN badValue.
%% 4) IF any other error THEN genErr.
%% 5) Otherwise ok!
diff --git a/lib/snmp/src/agent/snmpa_supervisor.erl b/lib/snmp/src/agent/snmpa_supervisor.erl
index 7d5c6da2c8..26c61579d5 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-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
%% Internal exports
-export([init/1, config/2]).
+-compile({no_auto_import,[erase/1]}).
-define(SERVER, ?MODULE).
@@ -41,6 +42,10 @@
%% Process structure
%% =================
%%
+%% "application"
+%% |
+%% app-sup
+%% |
%% ___________________ supervisor __________________
%% / | | \ \
%% ___misc_sup___ target_cache symbolic_store local_db agent_sup
@@ -176,7 +181,23 @@ start_master_sup(Opts) ->
do_start_master_sup(Opts) ->
verify_mandatory([db_dir], Opts),
- supervisor:start_link({local, ?SERVER}, ?MODULE, [master, Opts]).
+ case supervisor:start_link({local, ?SERVER}, ?MODULE, [master, Opts]) of
+ {ok, Pid} = OK ->
+ %% <HACKETI-HACK-HACK>
+ Key = master_agent_child_spec,
+ MasterAgentSpec = lookup(Key),
+ case snmpa_agent_sup:start_master_agent(MasterAgentSpec) of
+ {ok, MPid} when is_pid(MPid) ->
+ erase(Key),
+ OK;
+ {error, {Reason, _ChildSpec}} ->
+ stop(Pid, 0),
+ {error, Reason}
+ end;
+ %% </HACKETI-HACK-HACK>
+ Else ->
+ Else
+ end.
verify_mandatory([], _) ->
ok;
@@ -259,7 +280,7 @@ init([AgentType, Opts]) ->
%% -- mib storage --
%% MibStorage has only one mandatory part: module
- %% Everything else is module dependent and therefor
+ %% Everything else is module dependent and therefore
%% put in a special option: options
MibStorage =
case get_opt(mib_storage, Opts, [{module, snmpa_mib_storage_ets}]) of
@@ -503,9 +524,18 @@ init([AgentType, Opts]) ->
worker_spec(snmpa_agent,
[Prio, snmp_master_agent, none, Ref, AgentOpts],
Restart, 15000),
+ %% <HACKETI-HACK-HACK>
+ %% The point is to make start failure more quiet
+ %% Often the failure happens in the master agent,
+ %% so we move the start of that out of this function
+ %% and into the 'do_start_master_sup' function.
+ %% At some point we should rewrite this. Maybe start all
+ %% children the same way (explicitly).
+ store(master_agent_child_spec, AgentSpec),
AgentSupSpec =
- sup_spec(snmpa_agent_sup, [AgentSpec],
+ sup_spec(snmpa_agent_sup, [],
Restart, infinity),
+ %% </HACKETI-HACK-HACK>
[ConfigSpec, AgentSupSpec];
_ ->
?vdebug("[sub agent] spec for the agent supervisor",[]),
@@ -521,6 +551,13 @@ init([AgentType, Opts]) ->
store(Key, Value) ->
ets:insert(snmp_agent_table, {Key, Value}).
+lookup(Key) ->
+ [{Key, Value}] = ets:lookup(snmp_agent_table, Key),
+ Value.
+
+erase(Key) ->
+ ets:delete(snmp_agent_table, Key).
+
get_mibs(Mibs, Vsns) ->
MibDir = filename:join(code:priv_dir(snmp), "mibs"),
StdMib =
diff --git a/lib/snmp/src/agent/snmpa_svbl.erl b/lib/snmp/src/agent/snmpa_svbl.erl
index 8955bed0f2..a42d16de3a 100644
--- a/lib/snmp/src/agent/snmpa_svbl.erl
+++ b/lib/snmp/src/agent/snmpa_svbl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -91,7 +91,7 @@ insert_key(Key, Value, []) ->
[{Key, [Value]}].
%%-----------------------------------------------------------------
-%% Tranforms a list of {Oid, Vb} to a 2-tuple with all
+%% Transforms a list of {Oid, Vb} to a 2-tuple with all
%% Oids and all Vbs. These lists will be reversed.
%%-----------------------------------------------------------------
sa_split(Vbs) -> sa_split(Vbs, [], []).
@@ -137,7 +137,7 @@ unpack(Rest, [Row | Rows], []) ->
%% OrgIndex should not be present when we call the is_set_ok/set/undo
%% table functions. They just see the list of cols, and if an error
-%% occurs, they return the column nunber.
+%% occurs, they return the column number.
%% Also, delete duplicate columns. If a SET is performed with duplicate
%% columns, it is undefined which column to use. We just pick one.
delete_org_index([{RowIndex, Cols} | Rows]) ->
diff --git a/lib/snmp/src/agent/snmpa_target_cache.erl b/lib/snmp/src/agent/snmpa_target_cache.erl
index 72caf72b33..dab6eacddc 100644
--- a/lib/snmp/src/agent/snmpa_target_cache.erl
+++ b/lib/snmp/src/agent/snmpa_target_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -200,7 +200,7 @@ do_init(Prio, Opts) ->
%%
%% (1) As long as there are no _waiting_ or active write locks,
-%% read-locks will allways be granted
+%% read-locks will always be granted
%% (2) When there are no active readers, write-locks will be
%% granted.
%% (3) When there are active readers (clients with read-locks),
@@ -490,7 +490,7 @@ handle_cast({unlock, Pid},
writer = Writer,
waiting = StillWaiting}};
- %% If we have no active lockers, this may be a bug and therefor
+ %% If we have no active lockers, this may be a bug and therefore
%% see if we can activate some of the waiting
_ when (State#state.active_count == 0) ->
?vdebug("unlock -> could not find locker", []),
@@ -661,7 +661,7 @@ handle_maybe_active_or_waiting_down(Pid,
[#locker{state = active, type = read}] when (Cnt == 1) ->
%% 1) This means that the writer must be waiting
%% 2) The last reader terminated,
- %% time to activate the wating writer
+ %% time to activate the waiting writer
%% If this was the last one, then we must
%% activate the waiting writer.
ets:delete(?LOCKER_TAB, Pid),
diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl
index 9ee854b67d..be1a2a2a85 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,11 +34,6 @@
send_inform/6]).
-export([init_discovery_inform/13, send_discovery_inform/5]).
-%% <BACKWARD-COMPAT>
--export([send_discovery/5,
- init_discovery_inform/12]).
-%% </BACKWARD-COMPAT>
-
-include_lib("snmp/include/snmp_types.hrl").
-include_lib("snmp/src/agent/snmpa_internal.hrl").
-include_lib("snmp/include/SNMPv2-MIB.hrl").
@@ -74,9 +69,9 @@
%% operation, and so on, until eventually the MA will receive the
%% info. The MA then fills in the gaps, and at this point all
%% oids and types must be known, otherwise an error is signalled,
-%% and the opertaion is aborted. For the unknown values for some
+%% and the operation is aborted. For the unknown values for some
%% oids, a get-operation is performed by the MA. This will
-%% retreive the missing values.
+%% retrieve the missing values.
%% At this point, all oid, types and values are known, so the MA
%% can distribute the traps according to the information in the
%% internal tables.
@@ -128,7 +123,7 @@
%% Initialize as many variables as possible.
%% Returns: {ok, TrapRecord, <list of Var>} | error
%% where Var is returned from initiate_vars.
-%% NOTE: Executed at the inital SA
+%% NOTE: Executed at the initial SA
%%-----------------------------------------------------------------
construct_trap(Trap, Varbinds) ->
?vdebug("construct_trap -> entry with"
@@ -218,7 +213,7 @@ alias2oid(Alias, Append) ->
%% {{Process, VariableOid}, Value} |
%% {{Process, VariableAtom}, Value} |
%% {TableColAtom, RowIndex, Value}
-%% NOTE: Executed at the inital SA
+%% NOTE: Executed at the initial SA
%%-----------------------------------------------------------------
initiate_vars([{Oid, Asn1Type} | T], Varbinds) ->
case delete_oid_from_varbinds(Oid, Varbinds) of
@@ -410,7 +405,7 @@ send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, ExtraInfo, NetIf) ->
LocalEngineID, ExtraInfo, NetIf).
%% The agent normally does not care about the result,
-%% but since it can be usefull when debugging, add
+%% but since it can be useful when debugging, add
%% some info when we fail to send the trap(s).
send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID,
ExtraInfo, NetIf) ->
@@ -438,9 +433,6 @@ do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs,
send_trap_pdus(Dests, ContextName, {TrapRec, VarbindList}, [], [], [],
Recv, LocalEngineID, ExtraInfo, NetIf).
-send_discovery(TargetName, Record, ContextName, Vbs, NetIf) ->
- ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
- send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo).
send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo) ->
case find_dest(TargetName) of
{ok, Dest} ->
@@ -718,16 +710,6 @@ send_discovery_pdu(Record, Dest, Vbs,
init_discovery_inform(Parent,
Dest,
SecModel, SecName, SecLevel, TargetName,
- ContextName, Timeout, Retry, Vbs, NetIf, Verbosity) ->
- ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO,
- init_discovery_inform(Parent,
- Dest,
- SecModel, SecName, SecLevel, TargetName,
- ContextName, Timeout, Retry, Vbs, NetIf,
- Verbosity, ExtraInfo).
-init_discovery_inform(Parent,
- Dest,
- SecModel, SecName, SecLevel, TargetName,
ContextName, Timeout, Retry, Vbs, NetIf,
Verbosity, ExtraInfo) ->
put(verbosity, Verbosity),
diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl
index c65fcf2f8c..3417bb1aa9 100644
--- a/lib/snmp/src/agent/snmpa_usm.erl
+++ b/lib/snmp/src/agent/snmpa_usm.erl
@@ -62,7 +62,7 @@
%% Func: process_incoming_msg(Packet, Data, SecParams, SecLevel) ->
%% {ok, {SecEngineID, SecName, ScopedPDUBytes, SecData}} |
%% {error, Reason} | {error, Reason, ErrorInfo}
-%% Return value may be throwed.
+%% Return value may be thrown.
%% Types: Reason -> term()
%% Purpose:
%%-----------------------------------------------------------------
@@ -373,7 +373,7 @@ is_auth(AuthProtocol, AuthKey, AuthParams, Packet, SecName,
(TermDiscoStage2 =:= plain)) -> %% 3.2.7a
?vtrace("is_auth -> terminating discovery stage 2 - plain",[]),
%% This will *always* result in the manager *not*
- %% beeing in timewindow
+ %% being in timewindow
authoritative(SecName,
MsgAuthEngineBoots, MsgAuthEngineTime,
LocalEngineID);
diff --git a/lib/snmp/src/agent/snmpa_vacm.erl b/lib/snmp/src/agent/snmpa_vacm.erl
index d7d588c30d..a04d8bbdd8 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -142,12 +142,16 @@ split_prefix(_, _) -> false.
%% ViewName is including length from now on
loop_mib_view(ViewName, Subtree, Indexes, MibView) ->
- [{value, Mask}, {value, Type}, {value, Status}] =
- snmp_view_based_acm_mib:vacmViewTreeFamilyTable(
- get, Indexes,
- [?vacmViewTreeFamilyMask,
- ?vacmViewTreeFamilyType,
- ?vacmViewTreeFamilyStatus]),
+ {Mask, Type, Status} =
+ case loop_mib_view_get(Indexes) of
+ [{value, M}, {value, T}, {value, S}] ->
+ {M, T, S};
+ Else ->
+ ?vinfo("Failed vacmViewTreeFamilyTable lookup:"
+ "~n Indexes: ~p"
+ "~n Result: ~p", [Indexes, Else]),
+ exit(noSuchView)
+ end,
NextMibView =
case Status of
?'RowStatus_active' ->
@@ -169,6 +173,13 @@ loop_mib_view(ViewName, Subtree, Indexes, MibView) ->
end
end.
+loop_mib_view_get(Indexes) ->
+ Cols = [?vacmViewTreeFamilyMask,
+ ?vacmViewTreeFamilyType,
+ ?vacmViewTreeFamilyStatus],
+ snmp_view_based_acm_mib:vacmViewTreeFamilyTable(get, Indexes, Cols).
+
+
%%%-----------------------------------------------------------------
%%% 1b. The ordered ets table that implements vacmAccessTable
%%%-----------------------------------------------------------------
@@ -306,7 +317,7 @@ dump_table() ->
%% time dumping the table.
unique_table_name(Pre) ->
%% We want something that is guaranteed to be unique,
- %% therefor we use erlang:timestamp() instead of os:timestamp()
+ %% therefore we use erlang:timestamp() instead of os:timestamp()
unique_table_name(Pre, erlang:timestamp()).
unique_table_name(Pre, {_A, _B, C} = Now) ->
@@ -378,7 +389,7 @@ get_access_row(Key, GroupKey, ContextName, SecModel, SecLevel, Score, Found) ->
{ok, NScore} when NScore > Score ->
get_access_row(NextKey, GroupKey, ContextName,
SecModel, SecLevel, NScore, Row);
- {ok, _} -> % e.g. a throwed {ok, 0}
+ {ok, _} -> % e.g. a thrown {ok, 0}
get_access_row(NextKey, GroupKey, ContextName,
SecModel, SecLevel, Score, Found);
false ->
diff --git a/lib/snmp/src/app/Makefile b/lib/snmp/src/app/Makefile
index 02800462a4..f5a74aa78e 100644
--- a/lib/snmp/src/app/Makefile
+++ b/lib/snmp/src/app/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2021. All Rights Reserved.
+# Copyright Ericsson AB 2003-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -109,8 +109,8 @@ ERL_COMPILE_FLAGS += -I../misc \
# Targets
# ----------------------------------------------------
-debug:
- @$(MAKE) TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/snmp/src/app/snmp.app.src b/lib/snmp/src/app/snmp.app.src
index 2159fb5b4b..a18ea083fd 100644
--- a/lib/snmp/src/app/snmp.app.src
+++ b/lib/snmp/src/app/snmp.app.src
@@ -142,4 +142,4 @@
{applications, [kernel, stdlib]},
{mod, {snmp_app, []}},
{runtime_dependencies, ["stdlib-2.5","runtime_tools-1.8.14","mnesia-4.12",
- "kernel-8.0","erts-12.0","crypto-3.3"]}]}.
+ "kernel-8.0","erts-12.0","crypto-4.6"]}]}.
diff --git a/lib/snmp/src/app/snmp.config b/lib/snmp/src/app/snmp.config
index f35a636157..f5222245f1 100644
--- a/lib/snmp/src/app/snmp.config
+++ b/lib/snmp/src/app/snmp.config
@@ -36,8 +36,8 @@
%% {verbosity, verbosity()} |
%% {options, net_if_options()}
%% net_if_options() -> [net_if_option()]
-%% net_if_option() -> Note that these are basically dependant on which net-if
-%% module is beeing used, but the options described here
+%% net_if_option() -> Note that these are basically dependent on which net-if
+%% module is being used, but the options described here
%% are the ones that snmp_net_if (the default value for
%% the module option) handles:
%% {bind_to, bool()} |
@@ -77,8 +77,8 @@
%% {verbosity, verbosity()} |
%% {options, mgr_net_if_options()}
%% mgr_net_if_options() -> [mgr_net_if_option()]
-%% mgr_net_if_option() -> Note that these are basically dependant on which
-%% net-if module is beeing used, but the options
+%% mgr_net_if_option() -> Note that these are basically dependent on which
+%% net-if module is being used, but the options
%% described here are the ones of the snmpm_net_if
%% (the default value for the module option):
%% {recbuf, integer()} |
diff --git a/lib/snmp/src/app/snmp.erl b/lib/snmp/src/app/snmp.erl
index bc6a803eaa..c1f1c12acd 100644
--- a/lib/snmp/src/app/snmp.erl
+++ b/lib/snmp/src/app/snmp.erl
@@ -264,7 +264,7 @@ set_module_trace(Module, Opts) ->
{value, {return_trace, false}} ->
[];
_ ->
- %% Default is allways to include return values
+ %% Default is always to include return values
[{return_trace}]
end,
TraceRes =
@@ -665,7 +665,7 @@ short_time({{Y,M,D},{H,Mi,S}}) ->
[y1(Y), y2(Y), M, D, H, Mi, S, 0].
%% This function will only be called if there has been some
-%% validation error, and as it is strict, it allways returns
+%% validation error, and as it is strict, it always returns
%% false.
strict_validation(_What, _Data) ->
false.
diff --git a/lib/snmp/src/app/snmp_app.erl b/lib/snmp/src/app/snmp_app.erl
index 486b276383..7ba3c659f0 100644
--- a/lib/snmp/src/app/snmp_app.erl
+++ b/lib/snmp/src/app/snmp_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,8 +38,13 @@ start(Type, []) ->
%% First start the (new) central supervisor,
{ok, Pid} = snmp_app_sup:start_link(),
Entities = entities(),
- ok = start_entities(Type, Entities),
- {ok, Pid}.
+ case start_entities(Type, Entities) of
+ ok ->
+ {ok, Pid};
+ Error ->
+ snmp_app_sup:stop(),
+ Error
+ end.
entities() ->
entities([agent, manager], []).
diff --git a/lib/snmp/src/app/snmp_app_sup.erl b/lib/snmp/src/app/snmp_app_sup.erl
index eb89cc5b6d..bb6faa18cb 100644
--- a/lib/snmp/src/app/snmp_app_sup.erl
+++ b/lib/snmp/src/app/snmp_app_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,7 +64,12 @@ start_agent(Type, Opts) ->
"~n Type: ~p"
"~n Opts: ~p", [Type, Opts]),
Restart = get_restart(Opts, permanent),
- start_sup_child(snmpa_supervisor, Restart, [Type, Opts]).
+ case start_sup_child(snmpa_supervisor, Restart, [Type, Opts]) of
+ {ok, Pid} = OK when is_pid(Pid) ->
+ OK;
+ {error, {Reason, _ChildSpec}} ->
+ {error, Reason}
+ end.
start_manager(Type, Opts) ->
@@ -72,7 +77,12 @@ start_manager(Type, Opts) ->
"~n Type: ~p"
"~n Opts: ~p", [Type, Opts]),
Restart = get_restart(Opts, transient),
- start_sup_child(snmpm_supervisor, Restart, [Type, Opts]).
+ case start_sup_child(snmpm_supervisor, Restart, [Type, Opts]) of
+ {ok, Pid} = OK when is_pid(Pid) ->
+ OK;
+ {error, {Reason, _ChildSpec}} ->
+ {error, Reason}
+ end.
%%%-------------------------------------------------------------------
diff --git a/lib/snmp/src/compile/Makefile b/lib/snmp/src/compile/Makefile
index bbd7f99378..f255237a04 100644
--- a/lib/snmp/src/compile/Makefile
+++ b/lib/snmp/src/compile/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -85,13 +85,17 @@ ERL_COMPILE_FLAGS += -I../../include \
YRL_FLAGS = -o .
+ifeq ($(ERL_DETERMINISTIC),yes)
+ YRL_FLAGS += +deterministic
+endif
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug:
- @${MAKE} TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 4249799195..4fcc6e2342 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1322,7 +1322,7 @@ define_cols([{#mc_object_type{name = NameOfCol,
entrytype = table_column,
access = NewAccess,
description = Description,
- units = Units, %% Propably not usefull
+ units = Units, %% Probably not useful
assocList = [{table_name,TableName} | Defval]}),
define_cols(Rest,SubIndex+1,Fields,NameOfEntry,TableName,
[ColumnME|ColMEs]);
diff --git a/lib/snmp/src/compile/snmpc.src b/lib/snmp/src/compile/snmpc.src
index e64b6607c4..0f6831cc17 100644
--- a/lib/snmp/src/compile/snmpc.src
+++ b/lib/snmp/src/compile/snmpc.src
@@ -3,7 +3,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -355,7 +355,7 @@ usage() ->
"~n For example snmp/mibs/ "
"~n The current workin dir and the "
"~n <snmp-home>/priv/mibs "
- "~n are always listed last the includ path. "
+ "~n are always listed last the include path. "
"~n --db <DB> - Database to used for the default instrumentation."
"~n Defaults to volatile."
"~n --sgc - This option (skip group check), if present, "
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index 0cff8c5456..b04ab3af84 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -903,7 +903,7 @@ test_index_positions(Line, Indexes, ColMEs) ->
TLI = lists:filter(IsTLI, Indexes),
test_index_positions_impl(Line, TLI, ColMEs).
-%% An table that augments another cannot conatin any index,
+%% An table that augments another cannot contain any index,
%% so the first non-index column is always the first column.
augments_first_non_index_column([]) ->
none;
diff --git a/lib/snmp/src/compile/snmpc_mib_gram.yrl b/lib/snmp/src/compile/snmpc_mib_gram.yrl
index 14a668127e..1a970b97ea 100644
--- a/lib/snmp/src/compile/snmpc_mib_gram.yrl
+++ b/lib/snmp/src/compile/snmpc_mib_gram.yrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -453,7 +453,7 @@ variables -> objectname : ['$1'].
variables -> variables ',' objectname : ['$3' | '$1'].
implies -> '::=' : '$1'.
-implies -> ':' ':' '=' : w("Sloppy asignment on line ~p", [line_of('$1')]), '$1'.
+implies -> ':' ':' '=' : w("Sloppy assignment on line ~p", [line_of('$1')]), '$1'.
descriptionfield -> string : lreverse(descriptionfield, val('$1')).
descriptionfield -> '$empty' : undefined.
description -> 'DESCRIPTION' string : lreverse(description, val('$2')).
@@ -1071,7 +1071,7 @@ bits_to_bytes([], 1, _Byte) -> % empty bitstring
[];
bits_to_bytes([], 256, _Byte) -> % correct; multiple of 8
[];
-% If we are to support arbitrary length of bitstrings. This migth
+% If we are to support arbitrary length of bitstrings. This might
% be needed in the new SMI.
%bits_to_bytes([], N, Byte) ->
% [Byte];
diff --git a/lib/snmp/src/compile/snmpc_mib_to_hrl.erl b/lib/snmp/src/compile/snmpc_mib_to_hrl.erl
index c214bca93c..b041a6414b 100644
--- a/lib/snmp/src/compile/snmpc_mib_to_hrl.erl
+++ b/lib/snmp/src/compile/snmpc_mib_to_hrl.erl
@@ -33,7 +33,7 @@
%% Args: MibName = string() without extension.
%% Purpose: Produce a .hrl file with oid for tables and variables,
%% column numbers for columns and values for enums.
-%% Writes only the first occurence of a name. Prints a
+%% Writes only the first occurrence of a name. Prints a
%% warning if a duplicate name is found.
%% Returns: ok | {error, Reason}
%% Note: The Mib must be compiled.
diff --git a/lib/snmp/src/compile/snmpc_tok.erl b/lib/snmp/src/compile/snmpc_tok.erl
index 9114cc90de..fa40dd3237 100644
--- a/lib/snmp/src/compile/snmpc_tok.erl
+++ b/lib/snmp/src/compile/snmpc_tok.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -273,7 +273,7 @@ tokenise([10| T]) -> tokenise(T);
tokenise([13| T]) -> tokenise(T);
tokenise([32| T]) -> tokenise(T);
-%% Handle singe characters like { } [ ] + = ...
+%% Handle single characters like { } [ ] + = ...
tokenise([Ch | T]) ->
Atm = list_to_atom([Ch]),
{{Atm, get(line)}, T};
diff --git a/lib/snmp/src/manager/Makefile b/lib/snmp/src/manager/Makefile
index 6f5f5d01f9..693ef75469 100644
--- a/lib/snmp/src/manager/Makefile
+++ b/lib/snmp/src/manager/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2021. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -100,8 +100,8 @@ ERL_COMPILE_FLAGS += -I../../include \
# Targets
# ----------------------------------------------------
-debug:
- @$(MAKE) TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt:
@$(MAKE) behaviour_targets
diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl
index ffa6b0012c..6c6a22e1f1 100644
--- a/lib/snmp/src/manager/snmpm.erl
+++ b/lib/snmp/src/manager/snmpm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -96,18 +96,6 @@
-export([format_reason/1, format_reason/2]).
-%% Backward compatibility exports (API version "2")
--export([
- sync_get/3, sync_get/4, sync_get/5, sync_get/6,
- async_get/3, async_get/4, async_get/5, async_get/6,
- sync_get_next/3, sync_get_next/4, sync_get_next/5, sync_get_next/6,
- async_get_next/3, async_get_next/4, async_get_next/5, async_get_next/6,
- sync_set/3, sync_set/4, sync_set/5, sync_set/6,
- async_set/3, async_set/4, async_set/5, async_set/6,
- sync_get_bulk/5, sync_get_bulk/6, sync_get_bulk/7, sync_get_bulk/8,
- async_get_bulk/5, async_get_bulk/6, async_get_bulk/7, async_get_bulk/8
- ]).
-
%% Application internal export
-export([start_link/3, snmpm_start_verify/2, snmpm_start_verify/3]).
-export([target_name/1, target_name/2]).
@@ -119,49 +107,6 @@
]).
--deprecated(
- [
- {sync_get, 3, "use snmpm:sync_get2/3 instead."},
- {sync_get, 4, "use snmpm:sync_get2/4 instead."},
- {sync_get, 5, "use snmpm:sync_get2/4 instead."},
- {sync_get, 6, "use snmpm:sync_get2/4 instead."},
-
- {async_get, 3, "use snmpm:async_get2/3 instead."},
- {async_get, 4, "use snmpm:async_get2/4 instead."},
- {async_get, 5, "use snmpm:async_get2/4 instead."},
- {async_get, 6, "use snmpm:async_get2/4 instead."},
-
- {sync_get_next, 3, "use snmpm:sync_get_next2/3 instead."},
- {sync_get_next, 4, "use snmpm:sync_get_next2/4 instead."},
- {sync_get_next, 5, "use snmpm:sync_get_next2/4 instead."},
- {sync_get_next, 6, "use snmpm:sync_get_next2/4 instead."},
-
- {async_get_next, 3, "use snmpm:async_get_next2/3 instead."},
- {async_get_next, 4, "use snmpm:async_get_next2/4 instead."},
- {async_get_next, 5, "use snmpm:async_get_next2/4 instead."},
- {async_get_next, 6, "use snmpm:async_get_next2/4 instead."},
-
- {sync_set, 3, "use snmpm:sync_set2/3 instead."},
- {sync_set, 4, "use snmpm:sync_set2/4 instead."},
- {sync_set, 5, "use snmpm:sync_set2/4 instead."},
- {sync_set, 6, "use snmpm:sync_set2/4 instead."},
-
- {async_set, 3, "use snmpm:async_set2/3 instead."},
- {async_set, 4, "use snmpm:async_set2/4 instead."},
- {async_set, 5, "use snmpm:async_set2/4 instead."},
- {async_set, 6, "use snmpm:async_set2/4 instead."},
-
- {sync_get_bulk, 5, "use snmpm:sync_get_bulk2/5 instead."},
- {sync_get_bulk, 6, "use snmpm:sync_get_bulk2/6 instead."},
- {sync_get_bulk, 7, "use snmpm:sync_get_bulk2/6 instead."},
- {sync_get_bulk, 8, "use snmpm:sync_get_bulk2/6 instead."},
-
- {async_get_bulk, 5, "use snmpm:async_get_bulk2/5 instead."},
- {async_get_bulk, 6, "use snmpm:async_get_bulk2/6 instead."},
- {async_get_bulk, 7, "use snmpm:async_get_bulk2/6 instead."},
- {async_get_bulk, 8, "use snmpm:async_get_bulk2/6 instead."}
- ]).
-
-include_lib("snmp/src/misc/snmp_debug.hrl").
-include_lib("snmp/include/snmp_types.hrl").
-include("snmpm_atl.hrl").
@@ -206,14 +151,14 @@ simple_conf() ->
{ok, _} ->
ok;
_ ->
- ok = snmp_config:write_manager_config(Cwd, "",
+ ok = snmp_config:write_manager_config(Cwd, "",
[{port, 5000},
{engine_id, "mgrEngine"},
{max_message_size, 484}])
end,
Conf = [{dir, Cwd}, {db_dir, Cwd}],
[{versions, Vsns}, {config, Conf}].
-
+
%% Simple start. Start a manager with default values.
start_link() ->
start_link(simple_conf()).
@@ -379,7 +324,7 @@ restart(net_if = What) ->
%% The manager entity responsible for a specific agent.
%% Module is the callback module (snmpm_user behaviour) which
%% will be called whenever something happens (detected
-%% agent, incomming reply or incomming trap/notification).
+%% agent, incoming reply or incoming trap/notification).
%% Note that this could have already been done as a
%% consequence of the node config.
register_user(Id, Module, Data) ->
@@ -549,7 +494,7 @@ which_usm_users(EngineID) when is_list(EngineID) ->
%% -- Requests --
-%% --- synchroneous get-request ---
+%% --- synchronous get-request ---
%%
sync_get2(UserId, TargetName, Oids) ->
@@ -559,29 +504,6 @@ sync_get2(UserId, TargetName, Oids, SendOpts)
when is_list(Oids) andalso is_list(SendOpts) ->
snmpm_server:sync_get(UserId, TargetName, Oids, SendOpts).
-%% <BACKWARD-COMPAT>
-sync_get(UserId, TargetName, Oids) ->
- sync_get2(UserId, TargetName, Oids).
-
-sync_get(UserId, TargetName, Oids, Timeout)
- when is_list(Oids) andalso is_integer(Timeout) ->
- SendOpts = [{timeout, Timeout}],
- sync_get2(UserId, TargetName, Oids, SendOpts);
-sync_get(UserId, TargetName, Context, [OH|_] = Oids)
- when is_list(Context) andalso is_list(OH) ->
- SendOpts = [{context, Context}],
- sync_get2(UserId, TargetName, Oids, SendOpts).
-
-sync_get(UserId, TargetName, Context, Oids, Timeout) ->
- SendOpts = [{context, Context}, {timeout, Timeout}],
- sync_get2(UserId, TargetName, Oids, SendOpts).
-
-sync_get(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
- SendOpts = [{context, Context}, {timeout, Timeout}, {extra, ExtraInfo}],
- sync_get2(UserId, TargetName, Oids, SendOpts).
-%% </BACKWARD-COMPAT>
-
-
%% --- asynchronous get-request ---
%%
@@ -596,29 +518,8 @@ async_get2(UserId, TargetName, Oids, SendOpts)
when is_list(Oids) andalso is_list(SendOpts) ->
snmpm_server:async_get(UserId, TargetName, Oids, SendOpts).
-%% <BACKWARD-COMPAT>
-async_get(UserId, TargetName, Oids) ->
- async_get2(UserId, TargetName, Oids).
-
-async_get(UserId, TargetName, Oids, Expire) when is_integer(Expire) ->
- SendOpts = [{timeout, Expire}],
- async_get2(UserId, TargetName, Oids, SendOpts);
-async_get(UserId, TargetName, Context, Oids)
- when is_list(Context) andalso is_list(Oids) ->
- SendOpts = [{context, Context}],
- async_get2(UserId, TargetName, Oids, SendOpts).
-
-async_get(UserId, TargetName, Context, Oids, Expire) ->
- SendOpts = [{timeout, Expire}, {context, Context}],
- async_get2(UserId, TargetName, Oids, SendOpts).
-async_get(UserId, TargetName, Context, Oids, Expire, ExtraInfo) ->
- SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
- async_get2(UserId, TargetName, Oids, SendOpts).
-%% </BACKWARD-COMPAT>
-
-
-%% --- synchroneous get_next-request ---
+%% --- synchronous get_next-request ---
%%
sync_get_next2(UserId, TargetName, Oids) ->
@@ -628,28 +529,6 @@ sync_get_next2(UserId, TargetName, Oids, SendOpts)
when is_list(Oids) andalso is_list(SendOpts) ->
snmpm_server:sync_get_next(UserId, TargetName, Oids, SendOpts).
-%% <BACKWARD-COMPAT>
-sync_get_next(UserId, TargetName, Oids) ->
- sync_get_next2(UserId, TargetName, Oids).
-
-sync_get_next(UserId, TargetName, Oids, Timeout)
- when is_list(Oids) andalso is_integer(Timeout) ->
- SendOpts = [{timeout, Timeout}],
- sync_get_next2(UserId, TargetName, Oids, SendOpts);
-sync_get_next(UserId, TargetName, Context, Oids)
- when is_list(Context) andalso is_list(Oids) ->
- SendOpts = [{context, Context}],
- sync_get_next2(UserId, TargetName, Oids, SendOpts).
-
-sync_get_next(UserId, TargetName, Context, Oids, Timeout) ->
- SendOpts = [{timeout, Timeout}, {context, Context}],
- sync_get_next2(UserId, TargetName, Oids, SendOpts).
-
-sync_get_next(UserId, TargetName, Context, Oids, Timeout, ExtraInfo) ->
- SendOpts = [{timeout, Timeout}, {context, Context}, {extra, ExtraInfo}],
- sync_get_next2(UserId, TargetName, Oids, SendOpts).
-%% </BACKWARD-COMPAT>
-
%% --- asynchronous get_next-request ---
%%
@@ -661,30 +540,8 @@ async_get_next2(UserId, TargetName, Oids, SendOpts)
when is_list(Oids) andalso is_list(SendOpts) ->
snmpm_server:async_get_next(UserId, TargetName, Oids, SendOpts).
-%% <BACKWARD-COMPAT>
-async_get_next(UserId, TargetName, Oids) ->
- async_get_next2(UserId, TargetName, Oids).
-async_get_next(UserId, TargetName, Oids, Expire)
- when is_list(Oids) andalso is_integer(Expire) ->
- SendOpts = [{timeout, Expire}],
- async_get_next2(UserId, TargetName, Oids, SendOpts);
-async_get_next(UserId, TargetName, Context, Oids)
- when is_list(Context) andalso is_list(Oids) ->
- SendOpts = [{context, Context}],
- async_get_next2(UserId, TargetName, Oids, SendOpts).
-
-async_get_next(UserId, TargetName, Context, Oids, Expire) ->
- SendOpts = [{timeout, Expire}, {context, Context}],
- async_get_next2(UserId, TargetName, Oids, SendOpts).
-
-async_get_next(UserId, TargetName, Context, Oids, Expire, ExtraInfo) ->
- SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
- async_get_next2(UserId, TargetName, Oids, SendOpts).
-%% </BACKWARD-COMPAT>
-
-
-%% --- synchroneous set-request ---
+%% --- synchronous set-request ---
%%
sync_set2(UserId, TargetName, VarsAndVals) ->
@@ -694,28 +551,6 @@ sync_set2(UserId, TargetName, VarsAndVals, SendOpts)
when is_list(VarsAndVals) andalso is_list(SendOpts) ->
snmpm_server:sync_set(UserId, TargetName, VarsAndVals, SendOpts).
-%% <BACKWARD-COMPAT>
-sync_set(UserId, TargetName, VarsAndVals) ->
- sync_set2(UserId, TargetName, VarsAndVals).
-
-sync_set(UserId, TargetName, VarsAndVals, Timeout)
- when is_list(VarsAndVals) andalso is_integer(Timeout) ->
- SendOpts = [{timeout, Timeout}],
- sync_set2(UserId, TargetName, VarsAndVals, SendOpts);
-sync_set(UserId, TargetName, Context, VarsAndVals)
- when is_list(Context) andalso is_list(VarsAndVals) ->
- SendOpts = [{context, Context}],
- sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
-
-sync_set(UserId, TargetName, Context, VarsAndVals, Timeout) ->
- SendOpts = [{timeout, Timeout}, {context, Context}],
- sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
-
-sync_set(UserId, TargetName, Context, VarsAndVals, Timeout, ExtraInfo) ->
- SendOpts = [{timeout, Timeout}, {context, Context}, {extra, ExtraInfo}],
- sync_set2(UserId, TargetName, VarsAndVals, SendOpts).
-%% </BACKWARD-COMPAT>
-
%% --- asynchronous set-request ---
%%
@@ -727,30 +562,8 @@ async_set2(UserId, TargetName, VarsAndVals, SendOpts)
when is_list(VarsAndVals) andalso is_list(SendOpts) ->
snmpm_server:async_set(UserId, TargetName, VarsAndVals, SendOpts).
-%% <BACKWARD-COMPAT>
-async_set(UserId, TargetName, VarsAndVals) ->
- async_set2(UserId, TargetName, VarsAndVals).
-
-async_set(UserId, TargetName, VarsAndVals, Expire)
- when is_list(VarsAndVals) andalso is_integer(Expire) ->
- SendOpts = [{timeout, Expire}],
- async_set2(UserId, TargetName, VarsAndVals, SendOpts);
-async_set(UserId, TargetName, Context, VarsAndVals)
- when is_list(Context) andalso is_list(VarsAndVals) ->
- SendOpts = [{context, Context}],
- async_set2(UserId, TargetName, VarsAndVals, SendOpts).
-
-async_set(UserId, TargetName, Context, VarsAndVals, Expire) ->
- SendOpts = [{timeout, Expire}, {context, Context}],
- async_set2(UserId, TargetName, VarsAndVals, SendOpts).
-
-async_set(UserId, TargetName, Context, VarsAndVals, Expire, ExtraInfo) ->
- SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
- async_set2(UserId, TargetName, VarsAndVals, SendOpts).
-%% </BACKWARD-COMPAT>
-
-%% --- synchroneous get-bulk ---
+%% --- synchronous get-bulk ---
%%
sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids) ->
@@ -764,35 +577,6 @@ sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts)
snmpm_server:sync_get_bulk(UserId, TargetName,
NonRep, MaxRep, Oids, SendOpts).
-%% <BACKWARD-COMPAT>
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) ->
- sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids).
-
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Timeout)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) andalso
- is_integer(Timeout) ->
- SendOpts = [{timeout, Timeout}],
- sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts);
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Context) andalso
- is_list(Oids) ->
- SendOpts = [{context, Context}],
- sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
-
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Timeout) ->
- SendOpts = [{timeout, Timeout}, {context, Context}],
- sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
-
-sync_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Timeout,
- ExtraInfo) ->
- SendOpts = [{timeout, Timeout}, {context, Context}, {extra, ExtraInfo}],
- sync_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
-%% </BACKWARD-COMPAT>
-
%% --- asynchronous get-bulk ---
%%
@@ -808,35 +592,6 @@ async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts)
snmpm_server:async_get_bulk(UserId, TargetName,
NonRep, MaxRep, Oids, SendOpts).
-%% <BACKWARD-COMPAT>
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids) ->
- async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids).
-
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Oids, Expire)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Oids) andalso
- is_integer(Expire) ->
- SendOpts = [{timeout, Expire}],
- async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts);
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids)
- when is_integer(NonRep) andalso
- is_integer(MaxRep) andalso
- is_list(Context) andalso
- is_list(Oids) ->
- SendOpts = [{context, Context}],
- async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
-
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Expire) ->
- SendOpts = [{timeout, Expire}, {context, Context}],
- async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
-
-async_get_bulk(UserId, TargetName, NonRep, MaxRep, Context, Oids, Expire,
- ExtraInfo) ->
- SendOpts = [{timeout, Expire}, {context, Context}, {extra, ExtraInfo}],
- async_get_bulk2(UserId, TargetName, NonRep, MaxRep, Oids, SendOpts).
-%% </BACKWARD-COMPAT>
-
cancel_async_request(UserId, ReqId) ->
@@ -1081,7 +836,7 @@ sys_up_time() ->
%%% printable string of the error reason received from either:
%%%
%%% * If any of the sync/async get/get-next/set/get-bulk
-%%% returnes {error, Reason}
+%%% returns {error, Reason}
%%% * The Reason parameter in the handle_error user callback
%%% function
%%%
diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl
index 8e3dc3be6e..d5394d4298 100644
--- a/lib/snmp/src/manager/snmpm_config.erl
+++ b/lib/snmp/src/manager/snmpm_config.erl
@@ -38,7 +38,7 @@
register_agent/3, unregister_agent/2,
agent_info/0, agent_info/2, agent_info/3,
- update_agent_info/3, update_agent_info/4,
+ update_agent_info/3,
which_agents/0, which_agents/1,
is_known_engine_id/2,
@@ -94,9 +94,7 @@
%% Backward compatibillity exports
-export([
- register_user/3,
unregister_agent/3,
- update_agent_info/5,
is_known_engine_id/3,
get_agent_engine_id/2,
get_agent_engine_max_message_size/2,
@@ -109,12 +107,15 @@
check_manager_config/2,
check_user_config/1,
check_agent_config/1,
- check_usm_user_config/1]).
+ check_usm_user_config/1
+ ]).
%% gen_server callbacks
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- code_change/3, terminate/2]).
+-export([
+ init/1, handle_call/3, handle_cast/2, handle_info/2,
+ code_change/3, terminate/2
+ ]).
%% Includes:
@@ -192,10 +193,6 @@ is_started() ->
backup(BackupDir) when is_list(BackupDir) ->
call({backup, BackupDir}).
-%% Backward compatibillity
-register_user(UserId, UserMod, UserData) ->
- register_user(UserId, UserMod, UserData, []).
-
register_user(UserId, UserMod, UserData, DefaultAgentConfig)
when (UserId =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) ->
case (catch verify_user_behaviour(UserMod)) of
@@ -215,20 +212,6 @@ register_user(UserId, _UserMod, _UserData, DefaultAgentConfig)
register_user(UserId, _, _, _) ->
{error, {bad_user_id, UserId}}.
-%% default_agent_config(DefaultAgentConfig) ->
-%% {ok, SystemDefaultAgentConfig} = agent_info(),
-%% default_agent_config(SystemDefaultAgentConfig, DefaultAgentConfig).
-
-%% default_agent_config([], DefaultAgentConfig) ->
-%% DefaultAgentConfig;
-%% default_agent_config([{Key, _} = Entry|T], DefaultAgentConfig) ->
-%% case lists:keymember(Key, 1, DefaultAgentConfig) of
-%% true ->
-%% default_agent_config(T, DefaultAgentConfig);
-%% false ->
-%% default_agent_config(T, [Entry|DefaultAgentConfig])
-%% end.
-
verify_user_behaviour(UserMod) ->
case snmp_misc:verify_behaviour(snmpm_user, UserMod) of
@@ -547,23 +530,6 @@ which_agents(UserId) ->
update_agent_info(UserId, TargetName, Info) ->
call({update_agent_info, UserId, TargetName, Info}).
-%% <BACKWARD-COMPAT-2>
-%% This is wrapped in the interface module, so this function is
-%% only here to catch code-upgrade problems.
-update_agent_info(UserId, TargetName, Item, Val) ->
- update_agent_info(UserId, TargetName, [{Item, Val}]).
-%% </BACKWARD-COMPAT-2>
-
-%% <BACKWARD-COMPAT-1>
-update_agent_info(UserId, Addr, Port, Item, Val) ->
- case agent_info(Addr, Port, target_name) of
- {ok, TargetName} ->
- update_agent_info(UserId, TargetName, Item, Val);
- Error ->
- Error
- end.
-%% </BACKWARD-COMPAT-1>
-
is_known_engine_id(EngineID, TargetName) ->
case agent_info(TargetName, engine_id) of
{ok, EngineID} ->
@@ -2531,18 +2497,6 @@ handle_call({update_agent_info, UserId, TargetName, Info},
Reply = handle_update_agent_info(UserId, TargetName, Info),
{reply, Reply, State};
-%% <BACKWARD-COMPAT>
-handle_call({update_agent_info, UserId, TargetName, Item, Val},
- _From, State) ->
- ?vlog("received update_agent_info request: "
- "~n UserId: ~p"
- "~n TargetName: ~p"
- "~n Item: ~p"
- "~n Val: ~p", [UserId, TargetName, Item, Val]),
- Reply = handle_update_agent_info(UserId, TargetName, Item, Val),
- {reply, Reply, State};
-%% </BACKWARD-COMPAT>
-
handle_call({register_usm_user, User}, _From, State) ->
?vlog("received register_usm_user request: "
"~n User: ~p", [User]),
@@ -2793,7 +2747,7 @@ stop_backup_server({Pid, _}) when is_pid(Pid) ->
%%----------------------------------------------------------
handle_backup(D, BackupDir) ->
- %% First check that we do not wrote to the corrent db-dir...
+ %% First check that we do not wrote to the current db-dir...
?vtrace("handle_backup -> entry with"
"~n D: ~p"
"~n BackupDir: ~p", [D, BackupDir]),
@@ -2915,6 +2869,7 @@ handle_register_agent(UserId, TargetName, Config) ->
" FixedConfig: ~p", [FixedConfig]),
do_handle_register_agent(
TargetName, [{user_id, UserId}|FixedConfig]),
+
%% <DIRTY-BACKWARD-COMPATIBILLITY>
%% And now for some (backward compatibillity)
%% dirty crossref stuff
@@ -2928,25 +2883,6 @@ handle_register_agent(UserId, TargetName, Config) ->
{{Domain, Address, target_name}, TargetName}),
%% </DIRTY-BACKWARD-COMPATIBILLITY>
-%% %% First, insert this users default config
-%% ?vtrace("handle_register_agent -> store default config", []),
-%% do_handle_register_agent(TargetName, DefConfig),
-%% %% Second, insert the config for this agent
-%% ?vtrace("handle_register_agent -> store config", []),
-%% do_handle_register_agent(TargetName,
-%% [{user_id, UserId}|Config]),
-%% %% <DIRTY-BACKWARD-COMPATIBILLITY>
-%% %% And now for some (backward compatibillity)
-%% %% dirty crossref stuff
-%% ?vtrace("handle_register_agent -> lookup taddress", []),
-%% {ok, {Addr, Port} = TAddress} =
-%% agent_info(TargetName, taddress),
-%% ?vtrace("handle_register_agent -> taddress: ~p",
-%% [TAddress]),
-%% ?vtrace("handle_register_agent -> register cross-ref fix", []),
-%% ets:insert(snmpm_agent_table,
-%% {{Addr, Port, target_name}, TargetName}),
-%% %% </DIRTY-BACKWARD-COMPATIBILLITY>
ok;
_ ->
{error, {not_found, UserId}}
@@ -3051,14 +2987,6 @@ handle_update_agent_info(TargetName, Info) ->
{error, {failed_info_verification, Info, T, E}}
end.
-handle_update_agent_info(UserId, TargetName, Item, Val) ->
- ?vdebug("handle_update_agent_info -> entry with"
- "~n UserId: ~p"
- "~n TargetName: ~p"
- "~n Item: ~p"
- "~n Val: ~p", [UserId, TargetName, Item, Val]),
- handle_update_agent_info(TargetName, [{Item, Val}]).
-
do_update_agent_info(TargetName, Info) ->
?vtrace("do_update_agent_info -> entry with~n"
" TargetName: ~p~n"
diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl
index 85821ccb94..4d3733b2fd 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@
%%%-----------------------------------------------------------------
-%%% This module implemets the Message Processing and Dispatch part of
+%%% This module implements the Message Processing and Dispatch part of
%%% the multi-lingual SNMP agent.
%%%
%%% The MPD is responsible for:
@@ -63,7 +63,7 @@
%%% the counters only, it does not provide instrumentation functions
%%% for the counters.
%%%
-%%% With the terms defined in rfc2271, this module implememts part
+%%% With the terms defined in rfc2271, this module implements part
%%% of the Dispatcher and the Message Processing functionality.
%%%-----------------------------------------------------------------
init(Vsns) ->
@@ -324,7 +324,7 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Address, Log) ->
CtxEngineID, CtxName, PDU#pdu.request_id},
Err = sec_error(Note, Recv),
ACM = {invalid_sec_info, Err},
- ReqId = element(size(Note), Note),
+ ReqId = element(tuple_size(Note), Note),
{ok, 'version-3', PDU, PduMMS, {error, ReqId, ACM}};
_NoFound ->
?vtrace("process_v3_msg -> _NoFound: "
@@ -412,10 +412,10 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Address, Log) ->
sec_error(T1, T2)
- when is_tuple(T1) andalso is_tuple(T2) andalso (size(T1) =:= size(T2)) ->
+ when tuple_size(T1) =:= tuple_size(T2) ->
Tags = {sec_engine_id, msg_sec_model, sec_name, sec_level,
ctx_engine_id, ctx_name, request_id},
- sec_error(size(T1), T1, T2, Tags, []);
+ sec_error(tuple_size(T1), T1, T2, Tags, []);
sec_error(T1, T2) ->
[{internal_error, T1, T2}].
@@ -585,7 +585,7 @@ sec_module(?SEC_USM) ->
%% securityEngineID is set to the value of the target entity's
%% snmpEngineID.
%%
-%% As we never send traps, the SecEngineID is allways the
+%% As we never send traps, the SecEngineID is always the
%% snmpEngineID of the target entity!
sec_engine_id(TargetName) ->
case get_agent_engine_id(TargetName) of
@@ -600,7 +600,7 @@ sec_engine_id(TargetName) ->
%% BMK BMK BMK
-%% This one looks very similar to lik generate_v1_v2c_response_msg!
+%% This one looks very similar to link generate_v1_v2c_response_msg!
%% Common/shared? Should there be differences?
%%
generate_v1_v2c_msg(Vsn, Pdu, Community, Log) ->
@@ -622,7 +622,7 @@ generate_v1_v2c_msg(Vsn, Pdu, Community, Log) ->
"(pdu: ~w, community: ~w): ~n~w",
[Pdu, Community, Reason]),
{discarded, Reason};
- {ok, Packet} when size(Packet) =< MMS ->
+ {ok, Packet} when byte_size(Packet) =< MMS ->
Log(Packet),
inc_snmp_out(Pdu),
{ok, Packet};
@@ -630,7 +630,7 @@ generate_v1_v2c_msg(Vsn, Pdu, Community, Log) ->
?vlog("packet max size exceeded: "
"~n MMS: ~p"
"~n Len: ~p",
- [MMS, size(Packet)]),
+ [MMS, byte_size(Packet)]),
{discarded, tooBig}
end
end.
@@ -683,7 +683,7 @@ generate_v3_response_msg(#pdu{type = Type} = Pdu, MsgID,
%% if it's larger than the agent can handle -
%% it will be dropped. Just check against the
%% internal size.
- {ok, Packet} when size(Packet) =< MMS ->
+ {ok, Packet} when byte_size(Packet) =< MMS ->
if
SecLevel == 3 ->
%% encrypted - log decrypted pdu
@@ -760,13 +760,13 @@ generate_v1_v2c_response_msg(Vsn, Pdu, Comm, Log) ->
[Pdu, Comm, Reason]),
{discarded, Reason};
- {ok, Packet} when size(Packet) =< MMS ->
+ {ok, Packet} when byte_size(Packet) =< MMS ->
Log(Packet),
inc_snmp_out(Pdu),
{ok, Packet};
{ok, Packet} -> %% Too big
- too_big(Vsn, Pdu, Comm, MMS, size(Packet), Log)
+ too_big(Vsn, Pdu, Comm, MMS, byte_size(Packet), Log)
end
end.
@@ -870,7 +870,7 @@ get_max_message_size() ->
{ok, MMS} ->
MMS;
E ->
- user_err("failed retreiving engine max message size: ~w", [E]),
+ user_err("failed retrieving engine max message size: ~w", [E]),
484
end.
diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl
index af78308147..96a8d7cab2 100644
--- a/lib/snmp/src/manager/snmpm_net_if.erl
+++ b/lib/snmp/src/manager/snmpm_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -750,8 +750,18 @@ handle_info_down(Info, State) ->
%% Purpose: Shutdown the server
%% Returns: any (ignored by gen_server)
%%--------------------------------------------------------------------
-terminate(Reason, #state{log = Log, irgc = IrGcRef}) ->
+terminate(Reason, #state{log = Log,
+ irgc = IrGcRef,
+ transports = Transports}) ->
?vdebug("terminate: ~p", [Reason]),
+ %% Close all transports:
+ Close =
+ fun(S) ->
+ ?vlog("try close socket ~p", [S]),
+ (catch gen_udp:close(S))
+ end,
+ _ = [Close(Socket) || #transport{socket = Socket} <- Transports],
+ %% Stop IR GC timer
irgc_stop(IrGcRef),
%% Close logs
do_close_log(Log),
@@ -782,7 +792,7 @@ maybe_handle_recv_msg(Domain, Addr, Bytes, State) ->
fun (Pid, Class, Reason, Stacktrace) ->
warning_msg(
"Worker process (~p) terminated "
- "while processing (incomming) message from %s:~n"
+ "while processing (incoming) message from %s:~n"
"~w:~w at ~p",
[Pid, snmp_conf:mk_addr_string({Domain, Addr}),
Class, Reason, Stacktrace])
@@ -804,7 +814,7 @@ maybe_handle_recv_msg_mt(
handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid})
- when is_binary(Bytes) andalso (size(Bytes) =:= 0) ->
+ when is_binary(Bytes) andalso (byte_size(Bytes) =:= 0) ->
Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr};
%%
handle_recv_msg(
diff --git a/lib/snmp/src/manager/snmpm_network_interface_filter.erl b/lib/snmp/src/manager/snmpm_network_interface_filter.erl
index 35bec4e7e7..54fa8645df 100644
--- a/lib/snmp/src/manager/snmpm_network_interface_filter.erl
+++ b/lib/snmp/src/manager/snmpm_network_interface_filter.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ behaviour_info(_) ->
%% accept_recv(address(), port()) -> boolean()
-%% Called at the receiption of a message
+%% Called at the reception of a message
%% (before *any* processing has been done).
%%
%% accept_send(address(), port()) -> boolean()
diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl
index ca18637b8d..0da35c9bb3 100644
--- a/lib/snmp/src/manager/snmpm_server.erl
+++ b/lib/snmp/src/manager/snmpm_server.erl
@@ -571,24 +571,6 @@ handle_call({sync_get, Pid, UserId, TargetName, Oids, SendOpts},
{reply, Error, State}
end;
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({sync_get,
- Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo},
- From, State) ->
- ?vlog("[~p,~p,~p] received sync_get request for: "
- "~n ~p", [UserId, TargetName, CtxName, Oids]),
- case (catch handle_sync_get(Pid,
- UserId, TargetName, CtxName, Oids,
- Timeout, ExtraInfo, From, State)) of
- ok ->
- {noreply, State};
- Error ->
- {reply, Error, State}
- end;
-%% </BACKWARD-COMPAT>
-
-
handle_call({sync_get_next, Pid, UserId, TargetName, Oids, SendOpts},
From, State) ->
?vlog("[~p,~p] received sync_get_next request for: "
@@ -603,24 +585,6 @@ handle_call({sync_get_next, Pid, UserId, TargetName, Oids, SendOpts},
end;
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({sync_get_next,
- Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo},
- From, State) ->
- ?vlog("[~p,~p,~p] received sync_get_next request for"
- "~n ~p", [UserId, TargetName, CtxName, Oids]),
- case (catch handle_sync_get_next(Pid,
- UserId, TargetName, CtxName, Oids,
- Timeout, ExtraInfo, From, State)) of
- ok ->
- {noreply, State};
- Error ->
- {reply, Error, State}
- end;
-%% </BACKWARD-COMPAT>
-
-
%% Check agent version? This op not in v1
handle_call({sync_get_bulk,
Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts},
@@ -636,24 +600,6 @@ handle_call({sync_get_bulk,
{reply, Error, State}
end;
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({sync_get_bulk, Pid, UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Timeout, ExtraInfo},
- From, State) ->
- ?vlog("[~p,~p] received sync_get_bulk request for: ~p"
- "~n ~p", [UserId, TargetName, CtxName, Oids]),
- case (catch handle_sync_get_bulk(Pid,
- UserId, TargetName, CtxName,
- NonRep, MaxRep, Oids,
- Timeout, ExtraInfo, From, State)) of
- ok ->
- {noreply, State};
- Error ->
- {reply, Error, State}
- end;
-%% </BACKWARD-COMPAT>
-
handle_call({sync_set,
Pid, UserId, TargetName, VarsAndVals, SendOpts},
@@ -670,24 +616,6 @@ handle_call({sync_set,
end;
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({sync_set, Pid, UserId, TargetName,
- CtxName, VarsAndVals, Timeout, ExtraInfo},
- From, State) ->
- ?vlog("[~p,~p,~p] received sync_set request for: "
- "~n ~p", [UserId, TargetName, CtxName, VarsAndVals]),
- case (catch handle_sync_set(Pid,
- UserId, TargetName, CtxName, VarsAndVals,
- Timeout, ExtraInfo, From, State)) of
- ok ->
- {noreply, State};
- Error ->
- {reply, Error, State}
- end;
-%% </BACKWARD-COMPAT>
-
-
handle_call({async_get, Pid, UserId, TargetName, Oids, SendOpts},
_From, State) ->
?vlog("[~p,~p] received async_get request for: "
@@ -698,19 +626,6 @@ handle_call({async_get, Pid, UserId, TargetName, Oids, SendOpts},
{reply, Reply, State};
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({async_get, Pid, UserId, TargetName,
- CtxName, Oids, Expire, ExtraInfo},
- _From, State) ->
- ?vlog("[~p,~p,~p] received async_get request for: "
- "~n ~p", [UserId, TargetName, CtxName, Oids]),
- Reply = (catch handle_async_get(Pid, UserId, TargetName, CtxName, Oids,
- Expire, ExtraInfo, State)),
- {reply, Reply, State};
-%% </BACKWARD-COMPAT>
-
-
handle_call({async_get_next, Pid, UserId, TargetName, Oids, SendOpts},
_From, State) ->
?vlog("[~p,~p] received async_get_next request for: "
@@ -721,19 +636,6 @@ handle_call({async_get_next, Pid, UserId, TargetName, Oids, SendOpts},
{reply, Reply, State};
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({async_get_next, Pid, UserId, TargetName,
- CtxName, Oids, Expire, ExtraInfo},
- _From, State) ->
- ?vlog("[~p,~p,~p] received async_get_next request for: ",
- [UserId, TargetName, CtxName, Oids]),
- Reply = (catch handle_async_get_next(Pid, UserId, TargetName, CtxName,
- Oids, Expire, ExtraInfo, State)),
- {reply, Reply, State};
-%% </BACKWARD-COMPAT>
-
-
%% Check agent version? This op not in v1
handle_call({async_get_bulk,
Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts},
@@ -747,21 +649,6 @@ handle_call({async_get_bulk,
{reply, Reply, State};
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({async_get_bulk, Pid, UserId, TargetName,
- NonRep, MaxRep, CtxName, Oids, Expire, ExtraInfo},
- _From, State) ->
- ?vlog("[~p,~p,~p] received async_get_bulk request for: "
- "~n ~p", [UserId, TargetName, CtxName, Oids]),
- Reply = (catch handle_async_get_bulk(Pid,
- UserId, TargetName, CtxName,
- NonRep, MaxRep, Oids,
- Expire, ExtraInfo, State)),
- {reply, Reply, State};
-%% </BACKWARD-COMPAT>
-
-
handle_call({async_set,
Pid, UserId, TargetName, VarsAndVals, SendOpts},
_From, State) ->
@@ -773,19 +660,6 @@ handle_call({async_set,
{reply, Reply, State};
-%% <BACKWARD-COMPAT>
-%% The only case where this would be called is during code upgrade
-handle_call({async_set, Pid, UserId, TargetName,
- CtxName, VarsAndVals, Expire, ExtraInfo},
- _From, State) ->
- ?vlog("[~p,~p,~p] received async_set request for: "
- "~n ~p", [UserId, TargetName, CtxName, VarsAndVals]),
- Reply = (catch handle_async_set(Pid, UserId, TargetName, CtxName,
- VarsAndVals, Expire, ExtraInfo, State)),
- {reply, Reply, State};
-%% </BACKWARD-COMPAT>
-
-
handle_call({cancel_async_request, UserId, ReqId}, _From, State) ->
?vlog("received cancel_async_request request", []),
Reply = (catch handle_cancel_async_request(UserId, ReqId, State)),
@@ -1024,16 +898,6 @@ terminate(Reason, #state{nis_pid = NIS, gct = GCT, cbproxy = CBP}) ->
%%
%%----------------------------------------------------------------------
-handle_sync_get(Pid, UserId, TargetName, CtxName, Oids, Timeout, ExtraInfo,
- From, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Timeout},
- {extra, ExtraInfo}
- ],
- handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State).
-
handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) ->
?vtrace("handle_sync_get -> entry with"
"~n Pid: ~p"
@@ -1076,16 +940,6 @@ handle_sync_get(Pid, UserId, TargetName, Oids, SendOpts, From, State) ->
Error
end.
-handle_sync_get_next(Pid, UserId, TargetName, CtxName, Oids, Timeout,
- ExtraInfo, From, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Timeout},
- {extra, ExtraInfo}
- ],
- handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts, From, State).
-
handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts,
From, State) ->
?vtrace("handle_sync_get_next -> entry with"
@@ -1131,18 +985,6 @@ handle_sync_get_next(Pid, UserId, TargetName, Oids, SendOpts,
end.
-handle_sync_get_bulk(Pid, UserId, TargetName, CtxName,
- NonRep, MaxRep, Oids, Timeout,
- ExtraInfo, From, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Timeout},
- {extra, ExtraInfo}
- ],
- handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids,
- SendOpts, From, State).
-
handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
From, State) ->
?vtrace("handle_sync_get_bulk -> entry with"
@@ -1190,17 +1032,6 @@ handle_sync_get_bulk(Pid, UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
end.
-handle_sync_set(Pid, UserId, TargetName, CtxName, VarsAndVals, Timeout,
- ExtraInfo, From, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Timeout},
- {extra, ExtraInfo}
- ],
- handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts,
- From, State).
-
handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) ->
?vtrace("handle_sync_set -> entry with"
"~n Pid: ~p"
@@ -1245,16 +1076,6 @@ handle_sync_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, From, State) ->
end.
-handle_async_get(Pid, UserId, TargetName, CtxName, Oids, Expire, ExtraInfo,
- State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Expire},
- {extra, ExtraInfo}
- ],
- handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State).
-
handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) ->
?vtrace("handle_async_get -> entry with"
"~n Pid: ~p"
@@ -1294,16 +1115,6 @@ handle_async_get(Pid, UserId, TargetName, Oids, SendOpts, State) ->
end.
-handle_async_get_next(Pid, UserId, TargetName, CtxName, Oids, Expire,
- ExtraInfo, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Expire},
- {extra, ExtraInfo}
- ],
- handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State).
-
handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State) ->
?vtrace("handle_async_get_next -> entry with"
"~n Pid: ~p"
@@ -1343,19 +1154,6 @@ handle_async_get_next(Pid, UserId, TargetName, Oids, SendOpts, State) ->
end.
-handle_async_get_bulk(Pid, UserId, TargetName, CtxName,
- NonRep, MaxRep, Oids, Expire,
- ExtraInfo, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Expire},
- {extra, ExtraInfo}
- ],
- handle_async_get_bulk(Pid,
- UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
- State).
-
handle_async_get_bulk(Pid,
UserId, TargetName, NonRep, MaxRep, Oids, SendOpts,
State) ->
@@ -1398,16 +1196,6 @@ handle_async_get_bulk(Pid,
end.
-handle_async_set(Pid, UserId, TargetName, CtxName, VarsAndVals, Expire,
- ExtraInfo, State) ->
- SendOpts =
- [
- {context, CtxName},
- {timeout, Expire},
- {extra, ExtraInfo}
- ],
- handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State).
-
handle_async_set(Pid, UserId, TargetName, VarsAndVals, SendOpts, State) ->
?vtrace("handle_async_set -> entry with"
"~n Pid: ~p"
@@ -1549,14 +1337,14 @@ handle_snmp_error(#pdu{request_id = ReqId} = Pdu, Reason, State) ->
_ ->
%% reply to outstanding request, for which there is no
%% longer any owner (the user has unregistered).
- %% Therefor send it to the default user
+ %% Therefore send it to the default user
case snmpm_config:user_info() of
{ok, DefUserId, DefMod, DefData} ->
handle_error(DefUserId, DefMod, Reason, ReqId,
DefData, State),
maybe_delete(Disco, ReqId);
_ ->
- error_msg("failed retreiving the default user "
+ error_msg("failed retrieving the default user "
"info handling error [~w]: "
"~n~w", [ReqId, Reason])
end
@@ -1604,7 +1392,7 @@ handle_snmp_error(#pdu{request_id = ReqId} = Pdu, Reason, State) ->
handle_error(DefUserId, DefMod, Reason,
ReqId, DefData, State);
_ ->
- error_msg("failed retreiving the default "
+ error_msg("failed retrieving the default "
"user info handling error [~w]: "
"~n~w",[ReqId, Reason])
end
@@ -1636,7 +1424,7 @@ handle_snmp_error(Domain, Addr, ReqId, Reason, State) ->
handle_error(DefUserId, DefMod, Reason,
ReqId, DefData, State);
_Error2 ->
- error_msg("failed retreiving the default user "
+ error_msg("failed retrieving the default user "
"info handling snmp error "
"<~p,~p>: ~n~w~n~w",
[Domain, Addr, ReqId, Reason])
@@ -1648,7 +1436,7 @@ handle_snmp_error(Domain, Addr, ReqId, Reason, State) ->
handle_error(DefUserId, DefMod, Reason,
ReqId, DefData, State);
_Error4 ->
- error_msg("failed retreiving the default user "
+ error_msg("failed retrieving the default user "
"info handling snmp error "
"<~p,~p>: ~n~w~n~w",
[Domain, Addr, ReqId, Reason])
@@ -1721,7 +1509,7 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu,
_Error ->
%% reply to outstanding request, for which there is no
%% longer any owner (the user has unregistered).
- %% Therefor send it to the default user
+ %% Therefore send it to the default user
case snmpm_config:user_info() of
{ok, DefUserId, DefMod, DefData} ->
handle_pdu(
@@ -1730,7 +1518,7 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu,
ReqId, SnmpResponse, DefData, State),
maybe_delete(Disco, ReqId);
Error ->
- error_msg("failed retreiving the default user "
+ error_msg("failed retrieving the default user "
"info handling pdu from "
"~p <~p,~p>: ~n~w~n~w",
[Target, Domain, Addr, Error, Pdu])
@@ -1808,7 +1596,7 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu,
handle_error(DefUserId, DefMod, Reason,
ReqId, DefData, State);
Error ->
- error_msg("failed retreiving the default "
+ error_msg("failed retrieving the default "
"user info handling (old) "
"pdu from "
"<~p,~p>: ~n~w~n~w",
@@ -1835,7 +1623,7 @@ handle_snmp_pdu(#pdu{type = 'get-response', request_id = ReqId} = Pdu,
pdu, ignore,
SnmpInfo, DefData, State);
Error ->
- error_msg("failed retreiving the default user "
+ error_msg("failed retrieving the default user "
"info handling (old) pdu when no user "
"found from "
"<~p,~p>: ~n~w~n~w",
@@ -2105,7 +1893,7 @@ do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State) ->
Error1 ->
%% User no longer exists, unregister agent
- ?vlog("[trap] failed retreiving user info for "
+ ?vlog("[trap] failed retrieving user info for "
"user ~p: "
"~n ~p", [UserId, Error1]),
case snmpm_config:unregister_agent(UserId, Target) of
@@ -2120,7 +1908,7 @@ do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State) ->
SnmpTrapInfo, DefData, State);
Error2 ->
error_msg(
- "failed retreiving the default "
+ "failed retrieving the default "
"user info handling report from "
"~p <~p,~p>: ~n~w~n~w",
[Target, Domain, Addr,
@@ -2142,7 +1930,7 @@ do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State) ->
Error4 ->
%% Unknown agent, pass it on to the default user
- ?vlog("[trap] failed retreiving user id for agent <~p,~p>: "
+ ?vlog("[trap] failed retrieving user id for agent <~p,~p>: "
"~n Error: ~p"
"~n when"
"~n Users: ~p"
@@ -2159,7 +1947,7 @@ do_handle_snmp_trap(SnmpTrapInfo, Domain, Addr, State) ->
SnmpTrapInfo, DefData, State);
Error5 ->
error_msg(
- "failed retreiving "
+ "failed retrieving "
"the default user info, handling trap from <~p,~p>:"
"~n Error: ~p"
"~n Trap Info: ~p",
@@ -2290,7 +2078,7 @@ handle_snmp_inform(
case snmpm_config:unregister_agent(UserId, Target) of
ok ->
%% Try use the default user
- ?vlog("[inform] failed retreiving user "
+ ?vlog("[inform] failed retrieving user "
"info for user ~p:"
"~n ~p", [UserId, Error1]),
case snmpm_config:user_info() of
@@ -2301,7 +2089,7 @@ handle_snmp_inform(
inform, Ref,
SnmpInform, DefData, State);
Error2 ->
- error_msg("failed retreiving the default "
+ error_msg("failed retrieving the default "
"user info handling inform from "
"~p <~p,~p>: ~n~w~n~w",
[Target, Domain, Addr,
@@ -2322,7 +2110,7 @@ handle_snmp_inform(
Error4 ->
%% Unknown agent, pass it on to the default user
- ?vlog("[inform] failed retreiving user id for agent <~p,~p>: "
+ ?vlog("[inform] failed retrieving user id for agent <~p,~p>: "
"~n ~p", [Domain, Addr, Error4]),
case snmpm_config:user_info() of
{ok, DefUserId, DefMod, DefData} ->
@@ -2332,7 +2120,7 @@ handle_snmp_inform(
inform, Ref,
SnmpInform, DefData, State);
Error5 ->
- error_msg("failed retreiving "
+ error_msg("failed retrieving "
"the default user info handling inform from "
"<~p,~p>: ~n~w~n~w",
[Domain, Addr, Error5, Pdu])
@@ -2492,7 +2280,7 @@ handle_snmp_report(
SnmpReport, Data, State);
Error1 ->
%% User no longer exists, unregister agent
- ?vlog("[report] failed retreiving user info "
+ ?vlog("[report] failed retrieving user info "
"for user ~p:"
" ~n ~p", [UserId, Error1]),
case snmpm_config:unregister_agent(UserId, Target) of
@@ -2506,7 +2294,7 @@ handle_snmp_report(
SnmpReport, DefData, State);
Error2 ->
- error_msg("failed retreiving the default "
+ error_msg("failed retrieving the default "
"user info handling report from "
"~p <~p,~p>: ~n~w~n~w",
[Target, Domain, Addr,
@@ -2527,7 +2315,7 @@ handle_snmp_report(
Error4 ->
%% Unknown agent, pass it on to the default user
- ?vlog("[report] failed retreiving user id for agent <~p,~p>: "
+ ?vlog("[report] failed retrieving user id for agent <~p,~p>: "
"~n ~p", [Domain, Addr, Error4]),
case snmpm_config:user_info() of
{ok, DefUserId, DefMod, DefData} ->
@@ -2536,7 +2324,7 @@ handle_snmp_report(
report, ignore,
SnmpReport, DefData, State);
Error5 ->
- error_msg("failed retreiving "
+ error_msg("failed retrieving "
"the default user info handling report from "
"<~p,~p>: ~n~w~n~w",
[Domain, Addr, Error5, Pdu])
@@ -2551,7 +2339,7 @@ handle_snmp_report(CrapReport, Domain, Addr, _State) ->
%% This could be from a failed get-request, so we might have a user
%% waiting for a reply here. If there is, we handle this as an failed
-%% get-response (except for tha data which is different). Otherwise,
+%% get-response (except for the data which is different). Otherwise,
%% we handle it as an error (reported via the handle_error callback
%% function).
handle_snmp_report(
@@ -2624,7 +2412,7 @@ handle_snmp_report(
Data, State);
Error ->
%% Oh crap, use the default user
- ?vlog("[report] failed retreiving user info for "
+ ?vlog("[report] failed retrieving user info for "
"user ~p:"
" ~n ~p", [UserId, Error]),
case snmpm_config:user_info() of
@@ -2632,7 +2420,7 @@ handle_snmp_report(
handle_error(DefUserId, DefMod, Reason,
ReqId, DefData, State);
Error ->
- error_msg("failed retreiving the "
+ error_msg("failed retrieving the "
"default user "
"info handling report from "
"<~p,~p>: ~n~w~n~w~n~w",
@@ -2642,7 +2430,7 @@ handle_snmp_report(
end;
Error ->
%% Unknown agent, pass it on to the default user
- ?vlog("[report] failed retreiving user id for "
+ ?vlog("[report] failed retrieving user id for "
"agent <~p,~p>: "
"~n ~p", [Domain, Addr, Error]),
case snmpm_config:user_info() of
@@ -2650,7 +2438,7 @@ handle_snmp_report(
handle_error(DefUserId, DefMod, Reason, ReqId,
DefData, State);
Error ->
- error_msg("failed retreiving "
+ error_msg("failed retrieving "
"the default user info handling "
"report from "
"<~p,~p>: ~n~w~n~w~n~w",
diff --git a/lib/snmp/src/manager/snmpm_usm.erl b/lib/snmp/src/manager/snmpm_usm.erl
index 7ba91b86e7..08a70c6ca6 100644
--- a/lib/snmp/src/manager/snmpm_usm.erl
+++ b/lib/snmp/src/manager/snmpm_usm.erl
@@ -60,7 +60,7 @@ init() ->
%% Func: process_incoming_msg(Packet, Data, SecParams, SecLevel) ->
%% {ok, {SecEngineID, SecName, ScopedPDUBytes, SecData}} |
%% {error, Reason} | {error, Reason, ErrorInfo}
-%% Return value may be throwed.
+%% Return value may be thrown.
%% Types: Reason -> term()
%% Purpose:
%%-----------------------------------------------------------------
@@ -331,7 +331,7 @@ try_decrypt(usmAesCfb128Protocol,
%% SecData, SecLevel) ->
%% {ok, {SecEngineID, SecName, ScopedPDUBytes, SecData}} |
%% {error, Reason} | {error, Reason, ErrorInfo}
-%% Return value may be throwed.
+%% Return value may be thrown.
%% Types: Reason -> term()
%% Purpose:
%%-----------------------------------------------------------------
diff --git a/lib/snmp/src/misc/Makefile b/lib/snmp/src/misc/Makefile
index eca2d949d2..e92506e855 100644
--- a/lib/snmp/src/misc/Makefile
+++ b/lib/snmp/src/misc/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2021. All Rights Reserved.
+# Copyright Ericsson AB 2003-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -100,8 +100,8 @@ ERL_COMPILE_FLAGS += -I../../include \
# Targets
# ----------------------------------------------------
-debug:
- @$(MAKE) TYPE=debug opt
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
opt: $(TARGET_FILES)
diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl
index 39c18777c7..33db74e1e0 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -163,7 +163,7 @@ no_gen(_Dir, _R) -> [].
no_order(_, _) -> true.
no_filter(X) -> X.
-%% Order tuples on element N with Keys first in appearence order.
+%% Order tuples on element N with Keys first in appearance order.
%%
%% An ordering function (A, B) shall return true iff
%% A is less than or equal to B i.e shall return
@@ -924,7 +924,7 @@ check_transport_address(transportDomainUdpIpv4 = _Domain,
when ?is_ipv4_addr(A0, A1, A2, A3) ->
case PortInfo of
system ->
- %% The actual port number will be choosen
+ %% The actual port number will be chosen
%% by the system (create with port = 0)
%% when the socket is created.
true;
@@ -946,7 +946,7 @@ check_transport_address(transportDomainUdpIpv6 = _Domain,
when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) ->
case PortInfo of
system ->
- %% The actual port number will be choosen
+ %% The actual port number will be chosen
%% by the system (create with port = 0)
%% when the socket is created.
true;
diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl
index 928b469c06..44a9044a29 100644
--- a/lib/snmp/src/misc/snmp_config.erl
+++ b/lib/snmp/src/misc/snmp_config.erl
@@ -504,7 +504,7 @@ config_agent_transports(ID) ->
config_agent_transports(ID, []).
config_agent_transports(ID, []) ->
- i(ID ++ ". Configure atleast one transport: "),
+ i(ID ++ ". Configure at least one transport: "),
T = config_agent_transport(ID),
config_agent_transports(ID, [T]);
config_agent_transports(ID, Acc) ->
@@ -1103,7 +1103,7 @@ verify_max_message_size(MMS) ->
I when is_integer(I) andalso (I >= 484) ->
{ok, I};
I when is_integer(I) ->
- {error, "invalid max message size (must be atleast 484): " ++ MMS};
+ {error, "invalid max message size (must be at least 484): " ++ MMS};
_ ->
{error, "invalid max message size: " ++ MMS}
end.
@@ -1167,7 +1167,7 @@ verify_db_init_error(R) ->
verify_notif_type("trap") -> {ok, trap};
verify_notif_type("inform") -> {ok, inform};
-verify_notif_type(NT) -> {error, "invalid notifcation type: " ++ NT}.
+verify_notif_type(NT) -> {error, "invalid notification type: " ++ NT}.
verify_sec_type("none") -> {ok, none};
@@ -2648,7 +2648,7 @@ write_sys_config_file_agent_config_opt(Fid, {verbosity, Verb}) ->
ok = io:format(Fid, "{verbosity, ~w}", [Verb]).
-%% This is only present if there is atleast one option
+%% This is only present if there is at least one option
write_sys_config_file_agent_atl_opts(Fid, [Opt]) ->
write_sys_config_file_agent_atl_opt(Fid, Opt),
ok = io:format(Fid, "]", []),
@@ -2670,7 +2670,7 @@ write_sys_config_file_agent_atl_opt(Fid, {seqno, SeqNo}) ->
ok = io:format(Fid, "{seqno, ~w}", [SeqNo]).
-%% These options are allways there
+%% These options are always there
write_sys_config_file_agent_disco_opts(Fid, [Opt]) ->
write_sys_config_file_agent_disco_opt(Fid, Opt),
ok = io:format(Fid, "]", []),
@@ -2776,7 +2776,7 @@ write_sys_config_file_manager_config_opt(Fid, {verbosity, Verb}) ->
ok = io:format(Fid, "{verbosity, ~w}", [Verb]).
-%% This is only present if there is atleast one option
+%% This is only present if there is at least one option
write_sys_config_file_manager_atl_opts(Fid, [Opt]) ->
write_sys_config_file_manager_atl_opt(Fid, Opt),
ok = io:format(Fid, "]", []),
@@ -2807,7 +2807,7 @@ header() ->
[?MODULE, ?version, Y, Mo, D, H, Mi, S]).
-%% *If* these functions are successfull, they successfully return
+%% *If* these functions are successful, they successfully return
%% (value is ignored), but they fail preferably with
%% throw({error, Reason}). Other exceptions are also handled.
@@ -2862,7 +2862,7 @@ write_config_file(Dir, FileName, Order, Check, Write, Entries)
end
catch
throw:E:S ->
- d("File write of ~s throwed: "
+ d("File write of ~s thrown: "
"~n ~p"
"~n ~p"
"~n", [FileName, E, S]),
@@ -2881,7 +2881,7 @@ write_config_file(Dir, FileName, Write, Entries, Fd) ->
close_config_file(Dir, FileName, Fd)
catch
throw:E:S ->
- d("File write of ~s throwed: "
+ d("File write of ~s thrown: "
"~n ~p"
"~n ~p"
"~n", [FileName, E, S]),
@@ -2954,7 +2954,7 @@ append_config_file(Dir, FileName, Order, Check, Write, Entries, Fd) ->
close_config_file(Dir, FileName, Fd)
catch
throw:E:S ->
- d("File append of ~s throwed: "
+ d("File append of ~s thrown: "
"~n ~p"
"~n ~p"
"~n", [FileName, E, S]),
@@ -2997,7 +2997,7 @@ read_config_file(Dir, FileName, Order, Check)
{ok, verify_lines(SortedLines, Check, undefined, [])}
catch
throw:E:S ->
- d("File read of ~s throwed: "
+ d("File read of ~s thrown: "
"~n ~p"
"~n ~p"
"~n", [FileName, E, S]),
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index 8a4dfa621b..158883810f 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-2019. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1068,7 +1068,7 @@ log_open2(Name, File, SeqNoGen, Size, Repair, Notify) ->
end.
-%% We need to make sure we do not end up in an infinit loop
+%% We need to make sure we do not end up in an infinite loop
%% Take the number of files of the wrap log and add 2 (for
%% the index and size files).
do_log_open(Name, File, {_, N} = Size, snmp_repair = _Repair, Notify) ->
diff --git a/lib/snmp/src/misc/snmp_misc.erl b/lib/snmp/src/misc/snmp_misc.erl
index b02cf9d82e..18d5800651 100644
--- a/lib/snmp/src/misc/snmp_misc.erl
+++ b/lib/snmp/src/misc/snmp_misc.erl
@@ -492,7 +492,7 @@ format_pdu(PDU, MiniMib) when is_record(PDU, pdu) ->
(T =:= 'get-bulk-request') ->
"";
true ->
- io_lib:format("*!*!* An error occured. *!*!* ~n"
+ io_lib:format("*!*!* An error occurred. *!*!* ~n"
"Error status = ~w, index = ~w.~n",
[ES, EI])
end,
diff --git a/lib/snmp/src/misc/snmp_note_store.erl b/lib/snmp/src/misc/snmp_note_store.erl
index 606dd8ce4f..e842f3d3fa 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -156,7 +156,7 @@ handle_call({set_note, Lifetime, Key, Value}, _From,
{reply, Val, NState};
_Crap ->
?vinfo("handle_call(set_note) -> "
- "failed retreiving system start time from ~w: "
+ "failed retrieving system start time from ~w: "
"~n ~p", [Mod, _Crap]),
{reply, {error, failed_retreive_system_start_time}, State}
end;
@@ -317,13 +317,13 @@ timer(Pid, passive, Timeout) ->
?MODULE:timer(Pid, passive, Timeout);
activate ->
- ?d("timer(deactive) -> activate request, send ack",[]),
+ ?d("timer(deactivate) -> activate request, send ack",[]),
Pid ! activated,
- ?d("timer(deactive) -> activate",[]),
+ ?d("timer(deactivate) -> activate",[]),
?MODULE:timer(Pid, active, Timeout) % code replacement
after
Timeout ->
- ?d("timer(deactive) -> timeout",[]),
+ ?d("timer(deactivate) -> timeout",[]),
?MODULE:timer(Pid, passive, Timeout)
end;
timer(Pid, active, Timeout) ->
diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl
index 93f06749fd..1967c7078d 100644
--- a/lib/snmp/src/misc/snmp_pdus.erl
+++ b/lib/snmp/src/misc/snmp_pdus.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -828,8 +828,8 @@ enint(N, Acc) ->
enc_oct_str_tag(OStr) when is_list(OStr) ->
lists:append([4|elength(length(OStr))],OStr);
-enc_oct_str_tag(OBin) ->
- [4 | elength(size(OBin))] ++ binary_to_list(OBin).
+enc_oct_str_tag(OBin) when is_binary(OBin) ->
+ [4 | elength(byte_size(OBin))] ++ binary_to_list(OBin).
enc_oct_str_notag(OStr) -> OStr.
diff --git a/lib/snmp/src/misc/snmp_usm.erl b/lib/snmp/src/misc/snmp_usm.erl
index 9652e3a3ff..9c05c7d616 100644
--- a/lib/snmp/src/misc/snmp_usm.erl
+++ b/lib/snmp/src/misc/snmp_usm.erl
@@ -411,7 +411,7 @@ des_decrypt(PrivKey, MsgPrivParams, EncData)
DesKey = [A,B,C,D,E,F,G,H],
Salt = MsgPrivParams,
IV = list_to_binary(snmp_misc:str_xor(PreIV, Salt)),
- %% Whatabout errors here??? E.g. not a mulitple of 8!
+ %% Whatabout errors here??? E.g. not a multiple of 8!
Data = binary_to_list(crypto:crypto_one_time(?BLOCK_CIPHER_DES,
DesKey, IV, EncData, false)),
Data2 = snmp_pdus:strip_encrypted_scoped_pdu_data(Data),
@@ -438,7 +438,7 @@ aes_decrypt(PrivKey, MsgPrivParams, EncData, EngineBoots, EngineTime)
AesKey = PrivKey,
Salt = MsgPrivParams,
IV = list_to_binary([?i32(EngineBoots), ?i32(EngineTime) | Salt]),
- %% Whatabout errors here??? E.g. not a mulitple of 8!
+ %% Whatabout errors here??? E.g. not a multiple of 8!
Data = binary_to_list(crypto:crypto_one_time(?BLOCK_CIPHER_AES(AesKey),
AesKey, IV, EncData, false)),
Data2 = snmp_pdus:strip_encrypted_scoped_pdu_data(Data),
diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile
index e9bd50f6d8..8de1b1e80d 100644
--- a/lib/snmp/test/Makefile
+++ b/lib/snmp/test/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2020. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -161,6 +161,7 @@ ERL_COMPILE_FLAGS += -I../../snmp/src/app \
+'{parse_transform,sys_pre_attributes}' \
+'{attribute,insert,app_vsn,$(APP_VSN)}' \
$(SNMP_FLAGS)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
ERL_SNMP_FLAGS = $(SNMP_MIB_FLAGS) \
-I../priv/mibs
@@ -176,7 +177,7 @@ $(SNMP_BIN_TARGET_DIR)/%.hrl: $(SNMP_BIN_TARGET_DIR)/%.bin
# Targets
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
.PHONY: emakebuild
diff --git a/lib/snmp/test/exp/.gitignore b/lib/snmp/test/exp/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/snmp/test/exp/.gitignore
+++ /dev/null
diff --git a/lib/snmp/test/exp/snmp_agent_bl_test.erl b/lib/snmp/test/exp/snmp_agent_bl_test.erl
deleted file mode 100644
index 943426d8c2..0000000000
--- a/lib/snmp/test/exp/snmp_agent_bl_test.erl
+++ /dev/null
@@ -1,5634 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %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 = test_server:timetrap(test_server:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- [
- app_info,
- test_v1, test_v2, test_v1_v2, test_v3,
- test_multi_threaded,
- mib_storage,
- tickets
- ].
-
-
-%%%-----------------------------------------------------------------
-%%% 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 ?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,
- 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 = ?CRYPTO_START(),
- ?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
deleted file mode 100644
index 7c8967d302..0000000000
--- a/lib/snmp/test/exp/snmp_agent_ms_test.erl
+++ /dev/null
@@ -1,5636 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %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("common_test/include/ct.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 = test_server:timetrap(test_server:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- [
- app_info,
- {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}
- ].
-
-
-%%%-----------------------------------------------------------------
-%%% 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 ?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,
- 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 = ?CRYPTO_START(),
- ?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
deleted file mode 100644
index bd9162fa65..0000000000
--- a/lib/snmp/test/exp/snmp_agent_mt_test.erl
+++ /dev/null
@@ -1,5636 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %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("common_test/include/ct.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 = test_server:timetrap(test_server:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- [
- app_info,
- {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}
- ].
-
-
-%%%-----------------------------------------------------------------
-%%% 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 ?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,
- 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 = ?CRYPTO_START(),
- ?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
deleted file mode 100644
index f3b49f3bfd..0000000000
--- a/lib/snmp/test/exp/snmp_agent_v1_test.erl
+++ /dev/null
@@ -1,2674 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(snmp_agent_v1_test).
-
-%% TODO
-%% * Test fault-tolerance (kill master etc)
-%%
-
--export([]).
-
--define(application, snmp).
-
--include_lib("kernel/include/file.hrl").
--include_lib("common_test/include/ct.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 = test_server:timetrap(test_server:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- test_server: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
deleted file mode 100644
index 07ff1ed422..0000000000
--- a/lib/snmp/test/exp/snmp_agent_v2_test.erl
+++ /dev/null
@@ -1,5636 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %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("common_test/include/ct.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 = test_server:timetrap(test_server:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- [
- app_info,
- {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}
- ].
-
-
-%%%-----------------------------------------------------------------
-%%% 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 ?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,
- 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 = ?CRYPTO_START(),
- ?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
deleted file mode 100644
index 49f98b5178..0000000000
--- a/lib/snmp/test/exp/snmp_agent_v3_test.erl
+++ /dev/null
@@ -1,5635 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %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("common_test/include/ct.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 = test_server:timetrap(test_server:minutes(6)),
- [{watchdog, Dog}|Config].
-
-end_per_testcase(_Case, Config) when list(Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- Config.
-
-cases() ->
- [
- app_info, {group, test_v1}, {group, test_v2},
- {group, test_v1_v2}, {group, test_v3},
- {group, test_multi_threaded}, {group, mib_storage},
- {group, tickets}
- ].
-
-
-%%%-----------------------------------------------------------------
-%%% 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 ?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,
- 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 = ?CRYPTO_START(),
- ?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/klas3.erl b/lib/snmp/test/klas3.erl
index 9a5c388170..40002e8413 100644
--- a/lib/snmp/test/klas3.erl
+++ b/lib/snmp/test/klas3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -131,7 +131,7 @@ ftab2(set, [2], _Cols) ->
ftab2(set, _, _Cols) ->
{noError, 0};
-%% Unfortunatly we can't force the undo - we don't know which var
+%% Unfortunately we can't force the undo - we don't know which var
%% is tried first.
%ftab2(undo, [3], Cols) ->
% % bad column - In: col 2 & 3
diff --git a/lib/snmp/test/snmp_agent_SUITE.erl b/lib/snmp/test/snmp_agent_SUITE.erl
index bf942715cd..36c47f00f1 100644
--- a/lib/snmp/test/snmp_agent_SUITE.erl
+++ b/lib/snmp/test/snmp_agent_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -524,10 +524,11 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
- %% This is a temporary messure to ensure that we can
+ %% This is a temporary measure to ensure that we can
%% test the socket backend without effecting *all*
%% applications on *all* machines.
%% This flag is set only for *one* host.
+ %% case ?TEST_INET_BACKENDS() of
case ?TEST_INET_BACKENDS() of
true ->
[
@@ -679,8 +680,8 @@ otp16649_gen_cases() ->
init_per_suite(Config0) when is_list(Config0) ->
?IPRINT("init_per_suite -> entry with"
- "~n Config: ~p"
- "~n Nodes: ~p"
+ "~n Config: ~p"
+ "~n Nodes: ~p"
"~n explicit inet backend: ~p"
"~n test inet backends: ~p",
[Config0, erlang:nodes(),
@@ -709,7 +710,7 @@ init_per_suite(Config0) when is_list(Config0) ->
?IPRINT("init_per_suite -> end when"
"~n Config: ~p"
"~n Nodes: ~p", [Config4, erlang:nodes()]),
-
+
Config4
end.
@@ -721,7 +722,7 @@ end_per_suite(Config0) when is_list(Config0) ->
case snmp_test_mgr_counter_server:stop() of
{ok, Counters} ->
- ?IPRINT("end_per_suite -> sucessfully stopped counter server"
+ ?IPRINT("end_per_suite -> successfully stopped counter server"
"~n Counters: ~p", [Counters]);
{error, Reason} ->
@@ -761,25 +762,56 @@ init_per_group(GroupName, Config0) ->
Config1.
-init_per_group2(inet_backend_default = _GroupName, Config) ->
- snmp_test_lib:init_group_top_dir(default, [{socket_create_opts, []} | Config]);
-init_per_group2(inet_backend_inet = _GroupName, Config) ->
+init_per_group2(inet_backend_default = _GroupName, Config0) ->
+ Config1 = [{socket_create_opts, []} | Config0],
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ ?LIB:init_group_top_dir(default, Config1);
+ false ->
+ %% For a "standard" test (that is if we do not run the "extended"
+ %% inet backends test) then we should always run this group!
+ %% So, if we have an extended test, *then* (and only then)
+ %% check the factor.
+ case ?TEST_INET_BACKENDS() of
+ true ->
+ case lists:keysearch(snmp_factor, 1, Config0) of
+ {value, {snmp_factor, Factor}} when (Factor < 3) ->
+ ?LIB:init_group_top_dir(default, Config1);
+ _ ->
+ {skip, "Machine too slow"}
+ end;
+ _ ->
+ ?LIB:init_group_top_dir(default, Config1)
+ end
+ end;
+init_per_group2(inet_backend_inet = _GroupName, Config0) ->
case ?EXPLICIT_INET_BACKEND() of
true ->
%% The environment trumps us,
%% so only the default group should be run!
{skip, "explicit inet backend"};
false ->
- snmp_test_lib:init_group_top_dir(inet, [{socket_create_opts, [{inet_backend, inet}]} | Config])
+ case lists:keysearch(snmp_factor, 1, Config0) of
+ {value, {snmp_factor, Factor}} when (Factor < 5) ->
+ Config1 = [{socket_create_opts, [{inet_backend, inet}]} |
+ Config0],
+ ?LIB:init_group_top_dir(inet, Config1);
+ _ ->
+ {skip, "Machine too slow"}
+ end
end;
-init_per_group2(inet_backend_socket = _GroupName, Config) ->
+init_per_group2(inet_backend_socket = _GroupName, Config0) ->
case ?EXPLICIT_INET_BACKEND() of
true ->
%% The environment trumps us,
- %% so only the default group should be run!
+ %% so only the *default* group should be run!
{skip, "explicit inet backend"};
false ->
- snmp_test_lib:init_group_top_dir(socket, [{socket_create_opts, [{inet_backend, socket}]} | Config])
+ %% Always run this unless a backend has been explicitly
+ %% configured (since this is really what we want to test).
+ Config1 = [{socket_create_opts, [{inet_backend, socket}]} |
+ Config0],
+ ?LIB:init_group_top_dir(socket, Config1)
end;
init_per_group2(major_tcs = GroupName, Config) ->
init_all(snmp_test_lib:init_group_top_dir(GroupName, Config));
@@ -873,7 +905,7 @@ init_per_group2(GroupName, Config) ->
init_per_group_ipv6(GroupName, Config, Init) ->
%% <OS-CONDITIONAL-SKIP>
- %% This is a higly questionable test.
+ %% This is a highly questionable test.
%% But until we have time to figure out what IPv6 issues
%% are actually causing the failures...
OSSkipable = [{unix,
@@ -1330,7 +1362,7 @@ stop_agent(Config) ->
create_tables(SaNode) ->
- %% ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2},
+ %% {atomic, ok} = mnesia:create_table([{name, friendsTable2},
%% {ram_copies, [SaNode]},
%% {snmp, [{key, integer}]},
%% {attributes, [a1,a2,a3]}]),
@@ -1338,7 +1370,7 @@ create_tables(SaNode) ->
{ram_copies, [SaNode]},
{snmp, [{key, integer}]},
{attributes, [a1,a2,a3]}]),
- %% ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2},
+ %% {atomic, ok} = mnesia:create_table([{name, kompissTable2},
%% {ram_copies, [SaNode]},
%% {snmp, [{key, integer}]},
%% {attributes, [a1,a2,a3]}]),
@@ -1346,7 +1378,7 @@ create_tables(SaNode) ->
{ram_copies, [SaNode]},
{snmp, [{key, integer}]},
{attributes, [a1,a2,a3]}]),
- %% ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables},
+ %% {atomic, ok} = mnesia:create_table([{name, snmp_variables},
%% {attributes, [a1,a2]}]),
mnesia_create_table_or_fail([{name, snmp_variables},
{attributes, [a1,a2]}]),
@@ -1526,14 +1558,14 @@ init_mib_storage_ets(Config) when is_list(Config) ->
init_mib_storage_dets(Config) when is_list(Config) ->
?IPRINT("init_mib_storage_dets -> entry"),
- ?line AgentDbDir = ?GCONF(agent_db_dir, Config),
+ AgentDbDir = ?GCONF(agent_db_dir, Config),
MibStorage = {mib_storage, [{module, snmpa_mib_storage_dets},
{options, [{dir, AgentDbDir}]}]},
init_ms(Config, [MibStorage]).
init_mib_storage_mnesia(Config) when is_list(Config) ->
?IPRINT("init_mib_storage_mnesia -> entry"),
- ?line AgentNode = ?GCONF(snmp_master, Config),
+ AgentNode = ?GCONF(snmp_master, Config),
MibStorage = {mib_storage, [{module, snmpa_mib_storage_mnesia},
{options, [{nodes, [AgentNode]}]}]},
init_ms(Config, [MibStorage]).
@@ -1542,12 +1574,12 @@ init_ms(Config, Opts) when is_list(Config) ->
?IPRINT("init_ms -> entry with"
"~n Config: ~p"
"~n Opts: ~p", [Config, Opts]),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentConfDir = ?GCONF(agent_conf_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentConfDir,
+ SaNode = ?GCONF(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ config([v1], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
MasterAgentVerbosity = {agent_verbosity, trace},
MibsVerbosity = {mib_server, [{verbosity, trace}]},
@@ -1566,7 +1598,7 @@ init_ms(Config, Opts) when is_list(Config) ->
%% init_size_check_ms(Config, [MibStorage]).
init_size_check_msm(Config) when is_list(Config) ->
- ?line AgentNode = ?GCONF(snmp_master, Config),
+ AgentNode = ?GCONF(snmp_master, Config),
MibStorage = {mib_storage, [{module, snmpa_mib_storage_mnesia},
{options, [{nodes, [AgentNode]}]}]},
init_size_check_ms(Config, [MibStorage]).
@@ -1594,19 +1626,19 @@ init_size_check_ms(Config, Opts) when is_list(Config) ->
AgentConfDir = ?GCONF(agent_conf_dir, Config),
MgrDir = ?GCONF(mgr_dir, Config),
Ip = ?GCONF(ip, Config),
- ?line ok = config([v3], MgrDir, AgentConfDir,
+ 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) ->
?IPRINT("init_varm_mib_storage_dets -> entry"),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?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,
+ SaNode = ?GCONF(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentDbDir = ?GCONF(agent_db_dir, Config),
+ AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ config([v1], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
MibStorage = {mib_storage, [{module, snmpa_mib_storage_dets},
{options, [{dir, AgentDbDir}]}]},
@@ -1621,14 +1653,14 @@ init_varm_mib_storage_dets(Config) when is_list(Config) ->
init_varm_mib_storage_mnesia(Config) when is_list(Config) ->
?IPRINT("init_varm_mib_storage_mnesia -> entry"),
- ?line SaNode = ?GCONF(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentConfDir = ?GCONF(agent_conf_dir, Config),
- ?line MgrDir = ?GCONF(mgr_dir, Config),
- ?line Ip = ?GCONF(ip, Config),
- ?line config([v1], MgrDir, AgentConfDir,
+ SaNode = ?GCONF(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentConfDir = ?GCONF(agent_conf_dir, Config),
+ MgrDir = ?GCONF(mgr_dir, Config),
+ Ip = ?GCONF(ip, Config),
+ config([v1], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
- ?line AgentNode = ?GCONF(snmp_master, Config),
+ AgentNode = ?GCONF(snmp_master, Config),
MibStorage = {mib_storage, [{module, snmpa_mib_storage_mnesia},
{options, [{nodes, [AgentNode]}]}]},
MasterAgentVerbosity = {agent_verbosity, trace},
@@ -1803,49 +1835,47 @@ msm_varm_mib_start(X) ->
?P(msm_varm_mib_start),
varm_mib_start(X).
-ms_size_check(suite) -> [];
ms_size_check(Config) when is_list(Config) ->
?P(ms_size_check),
init_case(Config),
?IPRINT("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"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
+ load_master_std("OTP-SNMPEA-MIB"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-MPD-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-USER-BASED-SM-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ load_master_std("SNMPv2-MIB"),
+ load_master_std("SNMPv2-TM"),
?SLEEP(2000),
- ?line display_memory_usage(),
+ 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"),
+ unload_master("OTP-SNMPEA-MIB"),
+ unload_master("SNMP-COMMUNITY-MIB"),
+ unload_master("SNMP-FRAMEWORK-MIB"),
+ unload_master("SNMP-MPD-MIB"),
+ unload_master("SNMP-NOTIFICATION-MIB"),
+ unload_master("SNMP-TARGET-MIB"),
+ unload_master("SNMP-USER-BASED-SM-MIB"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ unload_master("SNMPv2-MIB"),
+ unload_master("SNMPv2-TM"),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
ok.
-varm_mib_start(suite) -> [];
varm_mib_start(Config) when is_list(Config) ->
?P(varm_mib_start),
?IPRINT("varm_mib_start -> entry"),
@@ -1862,16 +1892,16 @@ varm_mib_start(Config) when is_list(Config) ->
%% 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"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
+ 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
+ unload_mibs(HardwiredMibs), %% unload hardwired
?DBG("varm_mib_start -> sleep some (before stopping agent)", []),
?SLEEP(1000),
@@ -1908,51 +1938,50 @@ varm_mib_start(Config) when is_list(Config) ->
-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 is_list(Config) ->
?P(ms_me_of),
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"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
+ load_master_std("OTP-SNMPEA-MIB"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-MPD-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
?SLEEP(2000),
- ?line display_memory_usage(),
+ display_memory_usage(),
?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB",
[?snmpTrapCommunity_instance]),
- ?line ok = me_of(?snmpTrapCommunity_instance),
+ 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),
+ 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),
+ {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"),
+ unload_master("OTP-SNMPEA-MIB"),
+ unload_master("SNMP-COMMUNITY-MIB"),
+ unload_master("SNMP-FRAMEWORK-MIB"),
+ unload_master("SNMP-MPD-MIB"),
+ unload_master("SNMP-NOTIFICATION-MIB"),
+ unload_master("SNMP-TARGET-MIB"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
ok.
@@ -1979,52 +2008,51 @@ me_of(Oid) ->
end.
-ms_mib_of(suite) -> [];
ms_mib_of(Config) when is_list(Config) ->
?P(ms_mib_of),
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"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
+ load_master_std("OTP-SNMPEA-MIB"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-MPD-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
?SLEEP(2000),
- ?line display_memory_usage(),
+ display_memory_usage(),
?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB",
[?snmpTrapCommunity_instance]),
- ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'),
+ 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'),
+ 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,
+ {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"),
+ unload_master("OTP-SNMPEA-MIB"),
+ unload_master("SNMP-COMMUNITY-MIB"),
+ unload_master("SNMP-FRAMEWORK-MIB"),
+ unload_master("SNMP-MPD-MIB"),
+ unload_master("SNMP-NOTIFICATION-MIB"),
+ unload_master("SNMP-TARGET-MIB"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB"),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
ok.
@@ -2062,7 +2090,6 @@ misc_cases() ->
create_local_db_dir
].
-app_info(suite) -> [];
app_info(Config) when is_list(Config) ->
?P(app_info),
SnmpDir = app_dir(snmp),
@@ -2100,8 +2127,6 @@ create_local_db_dir(Config) when is_list(Config) ->
erlang:unique_integer([positive])},
[As,Bs,Cs] = [integer_to_list(I) || I <- tuple_to_list(T)],
DbDir = filename:join([DataDir, As, Bs, Cs]),
- Name = list_to_atom(atom_to_list(create_local_db_dir)
- ++"_"++As++"_"++Bs++"_"++Cs),
?IPRINT("try ensuring db-dir does not exist"),
try del_dir(DbDir, 3) of
ok ->
@@ -2114,20 +2139,13 @@ create_local_db_dir(Config) when is_list(Config) ->
"~n Stack: ~p", [C, E, S]),
throw({skip, "Failed pre db-dir cleanup"})
end,
- ?IPRINT("try start node ~p", [Name]),
- case ?ALIB:start_node(Name) of
- {ok, Node} ->
- {DbDir, Node};
- {error, Reason} ->
- ?WPRINT("Failed starting node ~p:"
- "~n ~p", [Reason]),
- throw({skip, ?F("Failed starting node ~p", [Name])})
- end
+ {ok, Peer, Node} = ?START_PEER(""),
+ {DbDir, Peer, Node}
end,
Case = fun do_create_local_db_dir/1,
- Post = fun({DbDir, Node}) ->
+ Post = fun({DbDir, Peer, Node}) ->
?IPRINT("try stop node ~p", [Node]),
- ?ALIB:stop_node(Node),
+ peer:stop(Peer),
?IPRINT("try delete db-dir"),
try del_dir(DbDir, 3)
catch
@@ -2142,7 +2160,7 @@ create_local_db_dir(Config) when is_list(Config) ->
end,
?TC_TRY(create_local_db_dir, Pre, Case, Post).
-do_create_local_db_dir({DbDir, Node}) ->
+do_create_local_db_dir({DbDir, _Peer, Node}) ->
?P(create_local_db_dir),
%% first start with a nonexisting DbDir
Fun1 = fun() ->
@@ -2254,13 +2272,13 @@ v1_cases_ipv6() ->
].
init_v1(Config) when is_list(Config) ->
- ?line SaNode = ?config(snmp_sa, Config),
- ?line create_tables(SaNode),
- ?line AgentConfDir = ?config(agent_conf_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line IpFamily = config_ipfamily(Config),
- ?line config(
+ SaNode = ?config(snmp_sa, Config),
+ create_tables(SaNode),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ IpFamily = config_ipfamily(Config),
+ config(
[v1], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip), IpFamily),
[{vsn, v1} | start_v1_agent(Config)].
@@ -2462,7 +2480,7 @@ init_v3(Config) when is_list(Config) ->
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
IpFamily = config_ipfamily(Config),
- ?line ok =
+ ok =
config(
[v3], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip), IpFamily),
@@ -2495,7 +2513,7 @@ init_mt(Config, MT) when is_list(Config) ->
AgentConfDir = ?config(agent_conf_dir, Config),
MgrDir = ?config(mgr_dir, Config),
Ip = ?config(ip, Config),
- ?line ok = config([v2], MgrDir, AgentConfDir,
+ ok = config([v2], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
[{vsn, v2} | start_multi_threaded_agent(Config, MT)].
@@ -2574,7 +2592,6 @@ init_old() ->
-simple(suite) -> [];
simple(Config) when is_list(Config) ->
?P(simple),
init_case(Config),
@@ -2586,7 +2603,6 @@ simple(Config) when is_list(Config) ->
simple_2(X) -> ?P(simple_2), simple(X).
-simple_bi(suite) -> [];
simple_bi(Config) when is_list(Config) ->
?P(simple_bi),
init_case(Config),
@@ -2600,7 +2616,6 @@ simple_bi(Config) when is_list(Config) ->
simple_3(X) ->
?P(simple_3), simple(X).
-big(suite) -> [];
big(Config) when is_list(Config) ->
?P(big),
%% put(sname, {?MODULE, big}),
@@ -2609,12 +2624,12 @@ big(Config) when is_list(Config) ->
{SaNode, _MgrNode, _MibDir} = init_case(Config),
?NPRINT("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
+ pong = net_adm:ping(SaNode),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
?DBG("big -> SA: ~p", [SA]),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
snmpa:dump_mibs(),
snmpa:dump_mibs("dumped_mibs.txt"),
@@ -2622,15 +2637,14 @@ big(Config) when is_list(Config) ->
try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB").
+ stop_subagent(SA),
+ unload_master("OLD-SNMPEA-MIB").
big_2(X) -> ?P(big_2), big(X).
big_3(X) -> ?P(big_3), big(X).
-big2(suite) -> [];
big2(Config) when is_list(Config) ->
?P(big2),
%% This is exactly the same tests as 'big', but with the
@@ -2638,110 +2652,102 @@ big2(Config) when is_list(Config) ->
{SaNode, _MgrNode, _MibDir} = init_case(Config),
?NPRINT("Starting subagent..."),
- ?line pong = net_adm:ping(SaNode),
+ pong = net_adm:ping(SaNode),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
- ?line load_master("OLD-SNMPEA-MIB-v2"),
- ?line init_old(),
+ {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"),
+ load_master("OLD-SNMPEA-MIB-v2"),
+ init_old(),
try_test(big_test),
- ?line stop_subagent(SA),
- ?line unload_master("OLD-SNMPEA-MIB-v2").
+ stop_subagent(SA),
+ unload_master("OLD-SNMPEA-MIB-v2").
big2_2(X) -> ?P(big2_2), big2(X).
big2_3(X) -> ?P(big2_3), big2(X).
-multi_threaded(suite) -> [];
multi_threaded(Config) when is_list(Config) ->
?P(multi_threaded),
init_case(Config),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(multi_threaded_test),
- ?line unload_master("Test1").
+ unload_master("Test1").
-mt_trap(suite) -> [];
mt_trap(Config) when is_list(Config) ->
?P(mt_trap),
init_case(Config),
MA = whereis(snmp_master_agent),
MT = ?config(multi_threaded, Config),
- ?line load_master("Test1"),
- ?line load_master("TestTrapv2"),
+ load_master("Test1"),
+ load_master("TestTrapv2"),
try_test(mt_trap_test, [MA, MT]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("Test1"),
+ unload_master("TestTrapv2"),
+ unload_master("Test1"),
ok.
-v2_types(suite) -> [];
v2_types(Config) when is_list(Config) ->
?P(v2_types),
init_case(Config),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(types_v2_test),
- ?line unload_master("Test1").
+ unload_master("Test1").
v2_types_3(X) -> ?P(v2_types_3), v2_types(X).
-implied(suite) -> [];
implied(Config) when is_list(Config) ->
?P(implied),
init_case(Config),
MA = whereis(snmp_master_agent),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(implied_test,[MA]),
- ?line unload_master("Test1").
+ unload_master("Test1").
implied_3(X) -> ?P(implied_3), implied(X).
-sparse_table(suite) -> [];
sparse_table(Config) when is_list(Config) ->
?P(sparse_table),
init_case(Config),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(sparse_table_test),
- ?line unload_master("Test1").
+ unload_master("Test1").
sparse_table_2(X) -> ?P(sparse_table_2), sparse_table(X).
sparse_table_3(X) -> ?P(sparse_table_3), sparse_table(X).
-cnt_64(suite) -> [];
cnt_64(Config) when is_list(Config) ->
?P(cnt_64),
init_case(Config),
MA = whereis(snmp_master_agent),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(cnt_64_test, [MA]),
- ?line unload_master("Test1").
+ unload_master("Test1").
cnt_64_2(X) -> ?P(cnt_64_2), cnt_64(X).
cnt_64_3(X) -> ?P(cnt_64_3), cnt_64(X).
-opaque(suite) -> [];
opaque(Config) when is_list(Config) ->
?P(opaque),
init_case(Config),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(opaque_test),
- ?line unload_master("Test1").
+ unload_master("Test1").
opaque_2(X) -> ?P(opaque_2), opaque(X).
opaque_3(X) -> ?P(opaque_2), opaque(X).
-change_target_addr_config(suite) -> [];
change_target_addr_config(Config) when is_list(Config) ->
?P(change_target_addr_config),
?IPRINT("change_target_addr_config -> entry"),
@@ -2753,27 +2759,27 @@ change_target_addr_config(Config) when is_list(Config) ->
MA = whereis(snmp_master_agent),
?IPRINT("change_target_addr_config -> load TestTrap"),
- ?line load_master("TestTrap"),
+ load_master("TestTrap"),
?IPRINT("change_target_addr_config -> set trace verbosity for local_db"),
- ?line snmpa:verbosity(local_db,trace),
+ snmpa:verbosity(local_db,trace),
- %% First send some traps that will arive att the original manager
+ %% First send some traps that will arrive att the original manager
?IPRINT("change_target_addr_config -> send trap"),
try_test(ma_trap1, [MA]),
?IPRINT("change_target_addr_config -> set silence verbosity for local_db"),
- ?line snmpa:verbosity(local_db, silence),
+ snmpa:verbosity(local_db, silence),
%% Start new dummy listener
?IPRINT("change_target_addr_config -> start dummy manager"),
- ?line {ok,Pid,NewPort} = dummy_manager_start(MA),
+ {ok,Pid,NewPort} = dummy_manager_start(MA),
%% Reconfigure
?IPRINT("change_target_addr_config -> reconfigure"),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_addr_conf(AgentConfDir, NewPort),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_addr_conf(AgentConfDir, NewPort),
+ snmp_target_mib:reconfigure(AgentConfDir),
%% Send the trap again
?IPRINT("change_target_addr_config -> send trap again"),
@@ -2783,13 +2789,13 @@ change_target_addr_config(Config) when is_list(Config) ->
catch dummy_manager_await_trap2_ack(),
?IPRINT("change_target_addr_config -> stop dummy manager"),
- ?line ok = dummy_manager_stop(Pid),
+ ok = dummy_manager_stop(Pid),
?IPRINT("change_target_addr_config -> reset target address config"),
- ?line reset_target_addr_conf(AgentConfDir),
+ reset_target_addr_conf(AgentConfDir),
?IPRINT("change_target_addr_config -> unload TestTrap"),
- ?line unload_master("TestTrap").
+ unload_master("TestTrap").
dummy_manager_start(MA) ->
@@ -2838,7 +2844,7 @@ dummy_manager_await_trap2_ack() ->
{received_trap, _Trap} ->
?IPRINT("dummy_manager_await_trap2 -> received trap: ~p", [_Trap]),
%% Note:
- %% Without this sleep the v2_inform_i testcase failes! There
+ %% Without this sleep the v2_inform_i testcase fails! There
%% is no relation between these two test cases as far as I
%% able to figure out...
?SLEEP(60000),
@@ -2892,7 +2898,7 @@ dummy_manager_loop(P,S,MA) ->
%% -ifdef(snmp_log).
dummy_manager_message_sz(B) when is_binary(B) ->
- size(B);
+ byte_size(B);
dummy_manager_message_sz(L) when is_list(L) ->
length(L);
dummy_manager_message_sz(_) ->
@@ -2913,49 +2919,57 @@ dummy_manager_handle_message(Bytes) ->
end.
-api(suite) -> [];
api(Config) when is_list(Config) ->
?P(api),
init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(api_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
+ unload_master("OLD-SNMPEA-MIB").
api_2(X) -> ?P(api_2), api(X).
api_3(X) -> ?P(api_3), api(X).
-subagent(suite) -> [];
subagent(Config) when is_list(Config) ->
?P(subagent),
{SaNode, _MgrNode, MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?NPRINT("try start subagent..."),
+ {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ ?NPRINT("try test case load_test_sa..."),
try_test(load_test_sa),
?NPRINT("Testing unregister subagent..."),
MA = whereis(snmp_master_agent),
rpc:call(SaNode, snmpa, unregister_subagent, [MA, SA]),
+ ?NPRINT("try test case unreg_test..."),
try_test(unreg_test),
?NPRINT("Loading previous subagent mib in master and testing..."),
- ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas1")),
+ ok = snmpa:load_mib(MA, join(MibDir, "Klas1")),
+ ?NPRINT("try test case load_test..."),
try_test(load_test),
?NPRINT("Unloading previous subagent mib in master and testing..."),
- ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas1")),
+ ok = snmpa:unload_mib(MA, join(MibDir, "Klas1")),
+ ?NPRINT("try test case unreg_test..."),
try_test(unreg_test),
?NPRINT("Testing register subagent..."),
- rpc:call(SaNode, snmpa, register_subagent,
- [MA, ?klas1, SA]),
+ rpc:call(SaNode, snmpa, register_subagent, [MA, ?klas1, SA]),
+ ?NPRINT("try test case load_test_sa..."),
try_test(load_test_sa),
- ?line stop_subagent(SA),
- try_test(unreg_test).
+ ?NPRINT("try stop subagent..."),
+ stop_subagent(SA),
+ ?NPRINT("try test case unreg_test..."),
+ try_test(unreg_test),
+
+ ?NPRINT("done"),
+ ok.
subagent_2(X) -> ?P(subagent_2), subagent(X).
@@ -2970,15 +2984,14 @@ subagent_3(X) ->
subagent(X).
-mnesia(suite) -> [];
mnesia(Config) when is_list(Config) ->
?P(mnesia),
{SaNode, _MgrNode, _MibDir} = init_case(Config),
?NPRINT("Starting subagent with mnesia impl..."),
{ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(big_test_2),
@@ -2986,8 +2999,8 @@ mnesia(Config) when is_list(Config) ->
MA = whereis(snmp_master_agent),
rpc:call(SaNode, snmpa, unregister_subagent, [MA, SA]),
try_test(unreg_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA).
+ unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA).
mnesia_2(X) -> ?P(mnesia_2), mnesia(X).
@@ -3030,9 +3043,9 @@ mul_cases_3() ->
init_mul(Config) when is_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(),
+ {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
[{mul_sub, SA} | Config].
finish_mul(Config) when is_list(Config) ->
@@ -3040,11 +3053,10 @@ finish_mul(Config) when is_list(Config) ->
SA = ?config(mul_sub, Config),
- ?line unload_master("OLD-SNMPEA-MIB"),
- ?line stop_subagent(SA),
+ unload_master("OLD-SNMPEA-MIB"),
+ stop_subagent(SA),
lists:keydelete(mul_sub, 1, Config).
-mul_get(suite) -> [];
mul_get(Config) when is_list(Config) ->
?P(mul_get),
init_case(Config),
@@ -3057,7 +3069,6 @@ mul_get_2(X) -> ?P(mul_get_2), mul_get(X).
mul_get_3(X) -> ?P(mul_get_3), mul_get(X).
-mul_get_err(suite) -> [];
mul_get_err(Config) when is_list(Config) ->
?P(mul_get_err),
init_case(Config),
@@ -3070,7 +3081,6 @@ mul_get_err_2(X) -> ?P(mul_get_err_2), mul_get_err(X).
mul_get_err_3(X) -> ?P(mul_get_err_3), mul_get_err(X).
-mul_next(suite) -> [];
mul_next(Config) when is_list(Config) ->
?P(mul_next),
init_case(Config),
@@ -3083,7 +3093,6 @@ mul_next_2(X) -> ?P(mul_next_2), mul_next(X).
mul_next_3(X) -> ?P(mul_next_3), mul_next(X).
-mul_next_err(suite) -> [];
mul_next_err(Config) when is_list(Config) ->
?P(mul_next_err),
init_case(Config),
@@ -3096,7 +3105,6 @@ mul_next_err_2(X) -> ?P(mul_next_err_2), mul_next_err(X).
mul_next_err_3(X) -> ?P(mul_next_err_3), mul_next_err(X).
-mul_set(suite) -> [];
mul_set(Config) when is_list(Config) ->
?P(mul_set),
init_case(Config),
@@ -3109,7 +3117,6 @@ mul_set_2(X) -> ?P(mul_set_2), mul_set(X).
mul_set_3(X) -> ?P(mul_set_3), mul_set(X).
-mul_set_err(suite) -> [];
mul_set_err(Config) when is_list(Config) ->
?P(mul_set_err),
init_case(Config),
@@ -3122,14 +3129,13 @@ mul_set_err_2(X) -> ?P(mul_set_err_2), mul_set_err(X).
mul_set_err_3(X) -> ?P(mul_set_err_3), mul_set_err(X).
-sa_register(suite) -> [];
sa_register(Config) when is_list(Config) ->
?P(sa_register),
{SaNode, _MgrNode, MibDir} = init_case(Config),
?DBG("sa_register -> start subagent", []),
?NPRINT("start subagent..."),
- ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
+ {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"),
?DBG("sa_register -> unregister subagent", []),
?NPRINT("Testing unregister subagent (2)..."),
@@ -3153,14 +3159,13 @@ sa_register(Config) when is_list(Config) ->
?NPRINT("stop subagent..."),
?DBG("sa_register -> stop subagent", []),
- ?line stop_subagent(SA).
+ stop_subagent(SA).
sa_register_2(X) -> ?P(sa_register_2), sa_register(X).
sa_register_3(X) -> ?P(sa_register_3), sa_register(X).
-v1_trap(suite) -> [];
v1_trap(Config) when is_list(Config) ->
?P(v1_trap),
trap1(Config).
@@ -3169,14 +3174,14 @@ trap1(Config) ->
{SaNode, _MgrNode, _MibDir} = init_case(Config),
?NPRINT("start subagent..."),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?NPRINT("Testing trap sending from master agent..."),
MA = whereis(snmp_master_agent),
?NPRINT("load TestTrap & TestTrapv2..."),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
?NPRINT("Testing trap sending from master-agent..."),
try_test(ma_trap1, [MA]),
@@ -3190,13 +3195,12 @@ trap1(Config) ->
try_test(sa_trap3, [SA]),
?NPRINT("unload TestTrap & TestTrapv2..."),
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("TestTrapv2"),
?NPRINT("stop subagent..."),
- ?line stop_subagent(SA).
+ stop_subagent(SA).
-v2_trap(suite) -> [];
v2_trap(Config) when is_list(Config) ->
?P(v2_trap),
trap2(Config).
@@ -3205,14 +3209,14 @@ trap2(Config) ->
{SaNode, _MgrNode, _MibDir} = init_case(Config),
?NPRINT("start subagent..."),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?NPRINT("Testing trap sending from master agent..."),
MA = whereis(snmp_master_agent),
?NPRINT("load TestTrap & TestTrapv2..."),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
?NPRINT("Testing trap sending from master-agent..."),
try_test(ma_v2_trap1, [MA]),
@@ -3228,13 +3232,12 @@ trap2(Config) ->
try_test(sa_v1_2_v2_trap3, [SA]),
?NPRINT("unload TestTrap & TestTrapv2..."),
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("TestTrapv2"),
?NPRINT("stop subagent..."),
- ?line stop_subagent(SA).
+ stop_subagent(SA).
-v3_trap(suite) -> [];
v3_trap(Config) when is_list(Config) ->
%% <CONDITIONAL-SKIP>
Skippable = [{unix, [darwin]}],
@@ -3273,7 +3276,6 @@ v2_inform_cases() ->
v2_inform_i
].
-v2_inform_i(suite) -> [];
v2_inform_i(Config) when is_list(Config) ->
?P(v2_inform_i),
inform_i(Config).
@@ -3284,19 +3286,19 @@ inform_i(Config) ->
MA = whereis(snmp_master_agent),
?NPRINT("load TestTrap & TestTrapv2..."),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
?NPRINT("Testing inform sending from master agent... "
- "~nNOTE! This test takes a few minutes (10) to complete."),
+ "~n NOTE! This test takes a few minutes (10) to complete."),
try_test(ma_v2_inform1, [MA]),
try_test(ma_v2_inform2, [MA]),
try_test(ma_v2_inform3, [MA]),
?NPRINT("unload TestTrap & TestTrapv2..."),
- ?line unload_master("TestTrap"),
- ?line unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("TestTrapv2"),
ok.
v3_inform_i(X) ->
@@ -3310,17 +3312,16 @@ v3_inform_i(X) ->
inform_i(X).
-sa_error(suite) -> [];
sa_error(Config) when is_list(Config) ->
?P(sa_error),
{SaNode, _MgrNode, _MibDir} = init_case(Config),
?NPRINT("load OLD-SNMPEA-MIB..."),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
?NPRINT("start subagent..."),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?NPRINT("Testing sa bad value (is_set_ok)..."),
try_test(sa_errs_bad_value),
@@ -3332,7 +3333,7 @@ sa_error(Config) when is_list(Config) ->
try_test(sa_too_big),
?NPRINT("unload OLD-SNMPEA-MIB..."),
- ?line unload_master("OLD-SNMPEA-MIB"),
+ unload_master("OLD-SNMPEA-MIB"),
?NPRINT("stop subagent..."),
stop_subagent(SA).
@@ -3352,17 +3353,16 @@ sa_error_3(X) ->
sa_error(X).
-next_across_sa(suite) -> [];
next_across_sa(Config) when is_list(Config) ->
?P(next_across_sa),
{SaNode, _MgrNode, MibDir} = init_case(Config),
MA = whereis(snmp_master_agent),
?NPRINT("start subagent (1)..."),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?NPRINT("Loading another subagent mib (Klas1)..."),
- ?line ok = snmpa:load_mib(SA, MibDir ++ "Klas1"),
+ ok = snmpa:load_mib(SA, MibDir ++ "Klas1"),
?NPRINT("register subagent..."),
rpc:call(SaNode, snmpa, register_subagent, [MA, ?klas1, SA]),
@@ -3379,7 +3379,7 @@ next_across_sa(Config) when is_list(Config) ->
try_test(unreg_test),
?NPRINT("Starting another subagent (2) "),
- ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
+ {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"),
?NPRINT("Testing next across subagent (wrong prefix from SA)..."),
try_test(next_across_sa_test),
@@ -3404,7 +3404,6 @@ next_across_sa_3(X) ->
next_across_sa(X).
-undo(suite) -> [];
undo(Config) when is_list(Config) ->
?P(undo),
{SaNode, _MgrNode, MibDir} = init_case(Config),
@@ -3412,30 +3411,30 @@ undo(Config) when is_list(Config) ->
MA = whereis(snmp_master_agent),
?NPRINT("start subagent (1)..."),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
?NPRINT("Load Klas3 & Klas4..."),
- ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas3")),
- ?line ok = snmpa:load_mib(MA, join(MibDir, "Klas4")),
+ ok = snmpa:load_mib(MA, join(MibDir, "Klas3")),
+ ok = snmpa:load_mib(MA, join(MibDir, "Klas4")),
?NPRINT("Testing undo phase at master agent..."),
try_test(undo_test),
try_test(api_test2),
?NPRINT("Unload Klas3..."),
- ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas3")),
+ ok = snmpa:unload_mib(MA, join(MibDir, "Klas3")),
?NPRINT("Testing bad return values from instrum. funcs..."),
try_test(bad_return),
?NPRINT("Unload Klas4..."),
- ?line ok = snmpa:unload_mib(MA, join(MibDir, "Klas4")),
+ ok = snmpa:unload_mib(MA, join(MibDir, "Klas4")),
?NPRINT("Testing undo phase at subagent..."),
- ?line ok = snmpa:load_mib(SA, join(MibDir, "Klas3")),
- ?line ok = snmpa:load_mib(SA, join(MibDir, "Klas4")),
- ?line ok = snmpa:register_subagent(MA, ?klas3, SA),
- ?line ok = snmpa:register_subagent(MA, ?klas4, SA),
+ ok = snmpa:load_mib(SA, join(MibDir, "Klas3")),
+ ok = snmpa:load_mib(SA, join(MibDir, "Klas4")),
+ ok = snmpa:register_subagent(MA, ?klas3, SA),
+ ok = snmpa:register_subagent(MA, ?klas4, SA),
try_test(undo_test),
try_test(api_test3),
@@ -3461,47 +3460,44 @@ undo_3(X) ->
undo(X).
%% Req. Test2
-v1_processing(suite) -> [];
v1_processing(Config) when is_list(Config) ->
?P(v1_processing),
?DBG("v1_processing -> entry", []),
init_case(Config),
?NPRINT("Load Test2..."),
- ?line load_master("Test2"),
+ load_master("Test2"),
try_test(v1_proc),
?NPRINT("Unload Test2..."),
- ?line unload_master("Test2").
+ unload_master("Test2").
%% Req. Test2
-v2_processing(suite) -> [];
v2_processing(Config) when is_list(Config) ->
?P(v2_processing),
init_case(Config),
?NPRINT("Load Test2..."),
- ?line load_master("Test2"),
+ load_master("Test2"),
try_test(v2_proc),
?NPRINT("Unload Test2..."),
- ?line unload_master("Test2").
+ unload_master("Test2").
%% Req. Test2
-v3_processing(suite) -> [];
v3_processing(Config) when is_list(Config) ->
?P(v3_processing),
init_case(Config),
?NPRINT("Load Test2..."),
- ?line load_master("Test2"),
+ load_master("Test2"),
try_test(v2_proc), % same as v2!
?NPRINT("Unload Test2..."),
- ?line unload_master("Test2").
+ unload_master("Test2").
%% We'll try get/set/trap and inform for all the auth & priv protocols.
@@ -3523,31 +3519,30 @@ v3_security_cases() ->
].
-v3_crypto_basic(suite) -> [];
v3_crypto_basic(_Config) ->
?P(v3_crypto_basic),
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,
+ KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID),
+ [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,
+ KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID),
+ [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,
+ KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID),
+ [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,
+ KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID),
+ [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,
@@ -3556,7 +3551,7 @@ v3_crypto_basic(_Config) ->
[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#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] =
@@ -3564,15 +3559,14 @@ v3_crypto_basic(_Config) ->
[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),
+ Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2),
+ KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1),
+ Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2),
+ KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2),
ok.
-v3_md5_auth(suite) -> [];
v3_md5_auth(Config) when is_list(Config) ->
?P(v3_md5_auth),
init_case(Config),
@@ -3580,26 +3574,25 @@ v3_md5_auth(Config) when is_list(Config) ->
?NPRINT("Testing MD5 authentication...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "authMD5", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "authMD5", authNoPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ 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(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
-v3_sha_auth(suite) -> [];
v3_sha_auth(Config) when is_list(Config) ->
?P(v3_sha_auth),
init_case(Config),
@@ -3607,28 +3600,27 @@ v3_sha_auth(Config) when is_list(Config) ->
?NPRINT("Testing SHA authentication...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "authSHA", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "authSHA", authNoPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
snmp_user_based_sm_mib:usmUserTable(print),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ 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(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
-v3_sha224_auth(suite) -> [];
v3_sha224_auth(Config) when is_list(Config) ->
?P(v3_sha224_auth),
init_case(Config),
@@ -3636,28 +3628,27 @@ v3_sha224_auth(Config) when is_list(Config) ->
?NPRINT("Testing SHA224 authentication...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "authSHA224", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "authSHA224", authNoPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
snmp_user_based_sm_mib:usmUserTable(print),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
{ma_v2_trap1, [MA]},
{v3_inform_sync, [MA]}]],
[{sec_level, authNoPriv}, {user, "authSHA224"}]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
-v3_sha256_auth(suite) -> [];
v3_sha256_auth(Config) when is_list(Config) ->
?P(v3_sha256_auth),
init_case(Config),
@@ -3665,28 +3656,27 @@ v3_sha256_auth(Config) when is_list(Config) ->
?NPRINT("Testing SHA256 authentication...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "authSHA256", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "authSHA256", authNoPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
snmp_user_based_sm_mib:usmUserTable(print),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
{ma_v2_trap1, [MA]},
{v3_inform_sync, [MA]}]],
[{sec_level, authNoPriv}, {user, "authSHA256"}]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
-v3_sha384_auth(suite) -> [];
v3_sha384_auth(Config) when is_list(Config) ->
?P(v3_sha384_auth),
init_case(Config),
@@ -3694,28 +3684,27 @@ v3_sha384_auth(Config) when is_list(Config) ->
?NPRINT("Testing SHA authentication...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "authSHA384", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "authSHA384", authNoPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
snmp_user_based_sm_mib:usmUserTable(print),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
{ma_v2_trap1, [MA]},
{v3_inform_sync, [MA]}]],
[{sec_level, authNoPriv}, {user, "authSHA384"}]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
-v3_sha512_auth(suite) -> [];
v3_sha512_auth(Config) when is_list(Config) ->
?P(v3_sha512_auth),
init_case(Config),
@@ -3723,28 +3712,27 @@ v3_sha512_auth(Config) when is_list(Config) ->
?NPRINT("Testing SHA512 authentication...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "authSHA512", authNoPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "authSHA512", authNoPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
snmp_user_based_sm_mib:usmUserTable(print),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ load_master("TestTrapv2"),
try_test(v3_sync, [[{v2_proc, []},
{ma_v2_trap1, [MA]},
{v3_inform_sync, [MA]}]],
[{sec_level, authNoPriv}, {user, "authSHA512"}]),
- ?line unload_master("TestTrapv2"),
- ?line unload_master("TestTrap"),
- ?line unload_master("Test2"),
- ?line reset_target_params_conf(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
-v3_des_priv(suite) -> [];
v3_des_priv(Config) when is_list(Config) ->
?P(v3_des_priv),
init_case(Config),
@@ -3752,26 +3740,26 @@ v3_des_priv(Config) when is_list(Config) ->
?NPRINT("Testing DES encryption...takes a few seconds..."),
AgentConfDir = ?config(agent_conf_dir, Config),
- ?line rewrite_target_params_conf(AgentConfDir, "privDES", authPriv),
- ?line snmp_target_mib:reconfigure(AgentConfDir),
+ rewrite_target_params_conf(AgentConfDir, "privDES", authPriv),
+ snmp_target_mib:reconfigure(AgentConfDir),
MA = whereis(snmp_master_agent),
snmp_user_based_sm_mib:usmUserTable(print),
- ?line load_master("Test2"),
- ?line load_master("TestTrap"),
- ?line load_master("TestTrapv2"),
+ load_master("Test2"),
+ load_master("TestTrap"),
+ 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(AgentConfDir).
+ unload_master("TestTrapv2"),
+ unload_master("TestTrap"),
+ unload_master("Test2"),
+ reset_target_params_conf(AgentConfDir).
%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]).
@@ -3786,18 +3774,17 @@ v3_sync(Funcs) ->
v3_inform_sync(MA) ->
?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]),
- ?line snmpa:send_notification(MA, testTrapv22, no_receiver,
+ 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 ?expect2({inform, true},
+ ?expect2({inform, true},
[{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?system ++ [0,1]}]).
-v2_caps(suite) -> [];
v2_caps(Config) when is_list(Config) ->
?P(v2_caps),
init_case(Config),
@@ -3808,13 +3795,13 @@ v2_caps_3(X) -> ?P(v2_caps_3), v2_caps(X).
v2_caps_i(Node) ->
- ?line Idx = rpc:call(Node, snmpa, add_agent_caps, [[1,2,3,4,5], "test cap"]),
+ Idx = rpc:call(Node, snmpa, add_agent_caps, [[1,2,3,4,5], "test cap"]),
g([[sysORID, Idx], [sysORDescr, Idx]]),
- ?line ?expect1([{[sysORID, Idx], [1,2,3,4,5]},
+ ?expect1([{[sysORID, Idx], [1,2,3,4,5]},
{[sysORDescr, Idx], "test cap"}]),
- ?line rpc:call(Node, snmpa, del_agent_caps, [Idx]),
+ rpc:call(Node, snmpa, del_agent_caps, [Idx]),
g([[sysORID, Idx]]),
- ?line ?expect1([{[sysORID, Idx], noSuchInstance}]).
+ ?expect1([{[sysORID, Idx], noSuchInstance}]).
%% Req. Test2
@@ -3830,85 +3817,85 @@ v1_proc() ->
v1_get_p() ->
%% 4.1.2:1
g([[test2]]),
- ?line ?expect3(noSuchName, 1, [{[test2], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[test2], 'NULL'}]),
g([[tDescr]]),
- ?line ?expect3(noSuchName, 1, [{[tDescr], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[tDescr], 'NULL'}]),
g([[tDescr2,0]]),
- ?line ?expect3(noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[tDescr2,0], 'NULL'}]),
g([[tDescr3,0]]),
- ?line ?expect3(noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[tDescr3,0], 'NULL'}]),
g([[tDescr4,0]]),
- ?line ?expect3(noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[tDescr4,0], 'NULL'}]),
g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line ?expect3(noSuchName, 2, [{[sysDescr, 0], 'NULL'},
+ ?expect3(noSuchName, 2, [{[sysDescr, 0], 'NULL'},
{[tDescr,0], 'NULL'}]),
g([[sysDescr,3]]),
- ?line ?expect3(noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[sysDescr, 3], 'NULL'}]),
%% 4.1.2:2
g([[tTable]]),
- ?line ?expect3(noSuchName, 1, [{[tTable], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[tTable], 'NULL'}]),
g([[tEntry]]),
- ?line ?expect3(noSuchName, 1, [{[tEntry], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[tEntry], 'NULL'}]),
%% 4.1.2:3
g([[tTooBig, 0]]),
- ?line ?expect3(tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+ ?expect3(tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
%% 4.1.2:4
g([[tGenErr1, 0]]),
- ?line ?expect3(genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ ?expect3(genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
g([[tGenErr2, 0]]),
- ?line ?expect3(genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ ?expect3(genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line ?expect3(genErr, 2, [{[sysDescr, 0], 'NULL'},
+ ?expect3(genErr, 2, [{[sysDescr, 0], 'NULL'},
{[tGenErr3, 0], 'NULL'}]).
v1_get_next_p() ->
%% 4.1.3:1
gn([[1,3,7,1]]),
- ?line ?expect3(noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
+ ?expect3(noSuchName, 1, [{[1,3,7,1], 'NULL'}]),
gn([[tDescr2]]),
- ?line ?expect3(tooBig, 0, any),
+ ?expect3(tooBig, 0, any),
%% 4.1.3:2
gn([[tTooBig]]),
io:format("We currently don't handle tooBig correct!!!\n"),
- ?line ?expect3(tooBig, 0, any),
+ ?expect3(tooBig, 0, any),
%% 4.1.3:3
gn([[tGenErr1]]),
- ?line ?expect3(genErr, 1, any),
+ ?expect3(genErr, 1, any),
gn([[tGenErr2]]),
- ?line ?expect3(genErr, 1, any),
+ ?expect3(genErr, 1, any),
gn([[sysDescr], [tGenErr3]]),
- ?line ?expect3(genErr, 2, any).
+ ?expect3(genErr, 2, any).
v1_set_p() ->
%% 4.1.5:1
s([{[1,3,7,0], i, 4}]),
- ?line ?expect3(noSuchName, 1, [{[1,3,7,0], 4}]),
+ ?expect3(noSuchName, 1, [{[1,3,7,0], 4}]),
s([{[tDescr,0], s, "outside mibview"}]),
- ?line ?expect3(noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
+ ?expect3(noSuchName, 1, [{[tDescr,0], "outside mibview"}]),
s([{[tDescr3,0], s, "read-only"}]),
- ?line ?expect3(noSuchName, 1, [{[tDescr3,0], "read-only"}]),
+ ?expect3(noSuchName, 1, [{[tDescr3,0], "read-only"}]),
s([{[tDescr3], s, "noSuchObject"}]),
- ?line ?expect3(noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
+ ?expect3(noSuchName, 1, [{[tDescr3], "noSuchObject"}]),
s([{[tDescr3,1], s, "noSuchInstance"}]),
- ?line ?expect3(noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
+ ?expect3(noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]),
s([{[tDescr2,0], s, "inconsistentName"}]),
- ?line ?expect3(noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
+ ?expect3(noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]),
%% 4.1.5:2
s([{[tDescr2, 0], i, 4}]),
- ?line ?expect3(badValue, 1, [{[tDescr2, 0], 4}]),
+ ?expect3(badValue, 1, [{[tDescr2, 0], 4}]),
s([{[tDescr2, 0], s, "badValue"}]),
- ?line ?expect3(badValue, 1, [{[tDescr2, 0], "badValue"}]),
+ ?expect3(badValue, 1, [{[tDescr2, 0], "badValue"}]),
%% 4.1.5:3
%% The standard is quite incorrect here. The resp pdu was too big. In
@@ -3918,14 +3905,14 @@ v1_set_p() ->
%% of the std-like original value.
s([{[tTooBig, 0], s, ?tooBigStr}]),
%% according to std:
-% ?line ?expect3(tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
- ?line ?expect3(tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
+% ?expect3(tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]),
+ ?expect3(tooBig, 0, [{[tTooBig, 0], 'NULL'}]),
%% 4.1.5:4
s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line ?expect3(genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
+ ?expect3(genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]),
s([{[tDescr2, 0], s, "commit_fail"}]),
- ?line ?expect3(genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
+ ?expect3(genErr, 1, [{[tDescr2, 0], "commit_fail"}]).
%% Req. Test2
v2_proc() ->
@@ -3941,94 +3928,94 @@ v2_get_p() ->
%% 4.2.1:2
?DBG("v2_get_p -> entry",[]),
g([[test2]]),
- ?line ?expect1([{[test2], noSuchObject}]),
+ ?expect1([{[test2], noSuchObject}]),
g([[tDescr]]),
- ?line ?expect1([{[tDescr], noSuchObject}]),
+ ?expect1([{[tDescr], noSuchObject}]),
g([[tDescr4,0]]),
- ?line ?expect1([{[tDescr4,0], noSuchObject}]),
+ ?expect1([{[tDescr4,0], noSuchObject}]),
g([[sysDescr, 0], [tDescr,0]]), % Outside mibview
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{[tDescr,0], noSuchObject}]),
g([[tTable]]),
- ?line ?expect1([{[tTable], noSuchObject}]),
+ ?expect1([{[tTable], noSuchObject}]),
g([[tEntry]]),
- ?line ?expect1([{[tEntry], noSuchObject}]),
+ ?expect1([{[tEntry], noSuchObject}]),
%% 4.2.1:3
g([[tDescr2,0]]), %% instrum ret noSuchName!!!
- ?line ?expect1([{[tDescr2,0], noSuchInstance}]),
+ ?expect1([{[tDescr2,0], noSuchInstance}]),
g([[tDescr3,0]]),
- ?line ?expect1([{[tDescr3,0], noSuchInstance}]),
+ ?expect1([{[tDescr3,0], noSuchInstance}]),
g([[sysDescr,3]]),
- ?line ?expect1([{[sysDescr, 3], noSuchInstance}]),
+ ?expect1([{[sysDescr, 3], noSuchInstance}]),
g([[tIndex,1]]),
- ?line ?expect1([{[tIndex, 1], noSuchInstance}]),
+ ?expect1([{[tIndex, 1], noSuchInstance}]),
%% 4.2.1 - any other error: genErr
g([[tGenErr1, 0]]),
- ?line ?expect3(genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
+ ?expect3(genErr, 1, [{[tGenErr1, 0], 'NULL'}]),
g([[tGenErr2, 0]]),
- ?line ?expect3(genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
+ ?expect3(genErr, 1, [{[tGenErr2, 0], 'NULL'}]),
g([[sysDescr, 0], [tGenErr3, 0]]),
- ?line ?expect3(genErr, 2, [{[sysDescr, 0], 'NULL'},
+ ?expect3(genErr, 2, [{[sysDescr, 0], 'NULL'},
{[tGenErr3, 0], 'NULL'}]),
%% 4.2.1 - tooBig
g([[tTooBig, 0]]),
- ?line ?expect3(tooBig, 0, []).
+ ?expect3(tooBig, 0, []).
v2_get_next_p() ->
%% 4.2.2:2
?DBG("v2_get_next_p -> entry",[]),
gn([[1,3,7,1]]),
- ?line ?expect1([{[1,3,7,1], endOfMibView}]),
+ ?expect1([{[1,3,7,1], endOfMibView}]),
gn([[sysDescr], [1,3,7,1]]),
- ?line ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
{[1,3,7,1], endOfMibView}]),
gn([[tCnt2, 1]]),
- ?line ?expect1([{[tCnt2,2], 100}]),
+ ?expect1([{[tCnt2,2], 100}]),
gn([[tCnt2, 2]]),
- ?line ?expect1([{[tCnt2,2], endOfMibView}]),
+ ?expect1([{[tCnt2,2], endOfMibView}]),
%% 4.2.2 - any other error: genErr
gn([[tGenErr1]]),
- ?line ?expect3(genErr, 1, [{[tGenErr1], 'NULL'}]),
+ ?expect3(genErr, 1, [{[tGenErr1], 'NULL'}]),
gn([[tGenErr2]]),
- ?line ?expect3(genErr, 1, [{[tGenErr2], 'NULL'}]),
+ ?expect3(genErr, 1, [{[tGenErr2], 'NULL'}]),
gn([[sysDescr], [tGenErr3]]),
- ?line ?expect3(genErr, 2, [{[sysDescr], 'NULL'},
+ ?expect3(genErr, 2, [{[sysDescr], 'NULL'},
{[tGenErr3], 'NULL'}]),
%% 4.2.2 - tooBig
gn([[tTooBig]]),
- ?line ?expect3(tooBig, 0, []).
+ ?expect3(tooBig, 0, []).
v2_get_bulk_p() ->
%% 4.2.3
?DBG("v2_get_bulk_p -> entry",[]),
gb(1, 1, []),
- ?line ?expect1([]),
+ ?expect1([]),
gb(-1, 1, []),
- ?line ?expect1([]),
+ ?expect1([]),
gb(-1, -1, []),
- ?line ?expect1([]),
+ ?expect1([]),
gb(-1, -1, []),
- ?line ?expect1([]),
+ ?expect1([]),
gb(2, 0, [[sysDescr], [1,3,7,1]]),
- ?line ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
{[1,3,7,1], endOfMibView}]),
gb(1, 2, [[sysDescr], [1,3,7,1]]),
- ?line ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
{[1,3,7,1], endOfMibView}]),
gb(0, 2, [[sysDescr], [1,3,7,1]]),
- ?line ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
+ ?expect1([{[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 ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
{[1,3,7,1], endOfMibView},
{[sysDescr, 0], "Erlang SNMP agent"},
{[1,3,7,1], endOfMibView},
@@ -4036,19 +4023,19 @@ v2_get_bulk_p() ->
{[1,3,7,1], endOfMibView}]),
gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]),
- ?line ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr, 0], "Erlang SNMP agent"},
{[sysDescr, 0], "Erlang SNMP agent"}]),
gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig.
- ?line ?expect1([]),
+ ?expect1([]),
gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]),
- ?line ?expect3(genErr, 3, [{[sysDescr], 'NULL'},
+ ?expect3(genErr, 3, [{[sysDescr], 'NULL'},
{[sysObjectID], 'NULL'},
{[tGenErr1], 'NULL'},
{[sysDescr], 'NULL'}]),
gb(0, 2, [[tCnt2, 1]]),
- ?line ?expect1([{[tCnt2,2], 100},
+ ?expect1([{[tCnt2,2], 100},
{[tCnt2,2], endOfMibView}]).
@@ -4056,68 +4043,68 @@ v2_set_p() ->
%% 4.2.5:1
?DBG("v2_set_p -> entry",[]),
s([{[1,3,7,0], i, 4}]),
- ?line ?expect3(noAccess, 1, [{[1,3,7,0], 4}]),
+ ?expect3(noAccess, 1, [{[1,3,7,0], 4}]),
s([{[tDescr,0], s, "outside mibview"}]),
- ?line ?expect3(noAccess, 1, [{[tDescr,0], "outside mibview"}]),
+ ?expect3(noAccess, 1, [{[tDescr,0], "outside mibview"}]),
%% 4.2.5:2
s([{[1,3,6,1,0], s, "noSuchObject"}]),
- ?line ?expect3(notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
+ ?expect3(notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]),
%% 4.2.5:3
s([{[tDescr2, 0], i, 4}]),
- ?line ?expect3(wrongType, 1, [{[tDescr2, 0], 4}]),
+ ?expect3(wrongType, 1, [{[tDescr2, 0], 4}]),
s([{[tDescr2, 0], s, "badValue"}]),
- ?line ?expect3(badValue, 1, [{[tDescr2, 0], "badValue"}]),
+ ?expect3(badValue, 1, [{[tDescr2, 0], "badValue"}]),
%% 4.2.5:4
s([{[tStr, 0], s, ""}]),
- ?line ?expect3(wrongLength, 1, [{[tStr, 0], ""}]),
+ ?expect3(wrongLength, 1, [{[tStr, 0], ""}]),
s([{[tStr, 0], s, "12345"}]),
- ?line ?expect3(wrongLength, 1, [{[tStr, 0], "12345"}]),
+ ?expect3(wrongLength, 1, [{[tStr, 0], "12345"}]),
%% 4.2.5:5 - N/A
%% 4.2.5:6
s([{[tInt1, 0], i, 0}]),
- ?line ?expect3(wrongValue, 1, [{[tInt1, 0], 0}]),
+ ?expect3(wrongValue, 1, [{[tInt1, 0], 0}]),
s([{[tInt1, 0], i, 5}]),
- ?line ?expect3(wrongValue, 1, [{[tInt1, 0], 5}]),
+ ?expect3(wrongValue, 1, [{[tInt1, 0], 5}]),
s([{[tInt2, 0], i, 0}]),
- ?line ?expect3(wrongValue, 1, [{[tInt2, 0], 0}]),
+ ?expect3(wrongValue, 1, [{[tInt2, 0], 0}]),
s([{[tInt2, 0], i, 5}]),
- ?line ?expect3(wrongValue, 1, [{[tInt2, 0], 5}]),
+ ?expect3(wrongValue, 1, [{[tInt2, 0], 5}]),
s([{[tInt3, 0], i, 5}]),
- ?line ?expect3(wrongValue, 1, [{[tInt3, 0], 5}]),
+ ?expect3(wrongValue, 1, [{[tInt3, 0], 5}]),
%% 4.2.5:7
s([{[tDescrX, 1, 1], s, "noCreation"}]),
- ?line ?expect3(noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
+ ?expect3(noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]),
%% 4.2.5:8
s([{[tDescrX, 1, 2], s, "inconsistentName"}]),
- ?line ?expect3(inconsistentName, 1,
+ ?expect3(inconsistentName, 1,
[{[tDescrX, 1, 2], "inconsistentName"}]),
%% 4.2.5:9
s([{[tCnt, 1, 2], i, 5}]),
- ?line ?expect3(notWritable, 1, [{[tCnt, 1, 2], 5}]),
+ ?expect3(notWritable, 1, [{[tCnt, 1, 2], 5}]),
s([{[tDescr3,0], s, "read-only"}]),
- ?line ?expect3(notWritable, 1, [{[tDescr3,0], "read-only"}]),
+ ?expect3(notWritable, 1, [{[tDescr3,0], "read-only"}]),
%% 4.2.5:10
s([{[tDescr2,0], s, "inconsistentValue"}]),
- ?line ?expect3(inconsistentValue, 1,
+ ?expect3(inconsistentValue, 1,
[{[tDescr2,0], "inconsistentValue"}]),
%% 4.2.5:11
s([{[tDescr2,0], s, "resourceUnavailable"}]),
- ?line ?expect3(resourceUnavailable, 1,
+ ?expect3(resourceUnavailable, 1,
[{[tDescr2,0],"resourceUnavailable"}]),
%% 4.2.5:12
s([{[tDescr2, 0], s, "is_set_ok_fail"}]),
- ?line ?expect3(genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
+ ?expect3(genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]).
%% commitFailed and undoFailed is tested by the 'undo' case.
@@ -4131,26 +4118,26 @@ table_test() ->
Key1c4 = [intCommunityAccess,get(mip),is("public")],
EndKey = [intCommunityEntry,[9],get(mip),is("public")],
gn([[intCommunityEntry]]),
- ?line ?expect1([{Key1c3, 2}]),
+ ?expect1([{Key1c3, 2}]),
gn([[intCommunityTable]]),
- ?line ?expect1([{Key1c3, 2}]),
+ ?expect1([{Key1c3, 2}]),
gn([[community]]),
- ?line ?expect1([{Key1c3, 2}]),
+ ?expect1([{Key1c3, 2}]),
gn([[otpSnmpeaMIB]]),
- ?line ?expect1([{Key1c3, 2}]),
+ ?expect1([{Key1c3, 2}]),
gn([[ericsson]]),
- ?line ?expect1([{Key1c3, 2}]),
+ ?expect1([{Key1c3, 2}]),
gn([Key1c3]),
- ?line ?expect1([{Key2c3, 2}]),
+ ?expect1([{Key2c3, 2}]),
gn([Key2c3]),
- ?line ?expect1([{Key1c4, 2}]),
+ ?expect1([{Key1c4, 2}]),
gn([EndKey]),
AgentIp = [intAgentIpAddress,0],
- ?line ?expect1([{AgentIp, any}]),
+ ?expect1([{AgentIp, any}]),
g([Key1c3]),
- ?line ?expect1([{Key1c3, 2}]),
+ ?expect1([{Key1c3, 2}]),
g([EndKey]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{EndKey, noSuchObject}])),
io:format("Testing row creation/deletion on communityTable...~n"),
@@ -4158,33 +4145,33 @@ table_test() ->
NewKeyc4 = [intCommunityAccess,get(mip),is("test")],
NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
s([{NewKeyc5, ?createAndGo}]),
- ?line ?expect3(?v1_2(badValue, inconsistentValue), 1, any),
+ ?expect3(?v1_2(badValue, inconsistentValue), 1, any),
s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]),
- ?line ?expect1([{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
+ ?expect1([{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]),
g([NewKeyc4]),
- ?line ?expect1([{NewKeyc4, 2}]),
+ ?expect1([{NewKeyc4, 2}]),
s([{NewKeyc5, ?destroy}]),
- ?line ?expect1([{NewKeyc5, ?destroy}]),
+ ?expect1([{NewKeyc5, ?destroy}]),
s([{NewKeyc4, 2}]),
- ?line ?expect3(?v1_2(noSuchName, inconsistentName), 1, [{NewKeyc4, 2}]),
+ ?expect3(?v1_2(noSuchName, inconsistentName), 1, [{NewKeyc4, 2}]),
s([{NewKeyc5, ?createAndWait}]),
- ?line ?expect1([{NewKeyc5, ?createAndWait}]),
+ ?expect1([{NewKeyc5, ?createAndWait}]),
g([NewKeyc5]),
- ?line ?expect1([{NewKeyc5, ?notReady}]),
+ ?expect1([{NewKeyc5, ?notReady}]),
s([{NewKeyc4, 2}]),
- ?line ?expect1([{NewKeyc4, 2}]),
+ ?expect1([{NewKeyc4, 2}]),
g([NewKeyc5]),
- ?line ?expect1([{NewKeyc5, ?notReady}]),
+ ?expect1([{NewKeyc5, ?notReady}]),
s([{NewKeyc3, 2}]),
- ?line ?expect1([{NewKeyc3, 2}]),
+ ?expect1([{NewKeyc3, 2}]),
g([NewKeyc5]),
- ?line ?expect1([{NewKeyc5, ?notInService}]),
+ ?expect1([{NewKeyc5, ?notInService}]),
s([{NewKeyc5, ?active}]),
- ?line ?expect1([{NewKeyc5, ?active}]),
+ ?expect1([{NewKeyc5, ?active}]),
s([{NewKeyc5, ?destroy}]),
- ?line ?expect1([{NewKeyc5, ?destroy}]),
+ ?expect1([{NewKeyc5, ?destroy}]),
s([{NewKeyc3, 3}]),
- ?line ?expect3(?v1_2(noSuchName, inconsistentName), 1, [{NewKeyc3, 3}]),
+ ?expect3(?v1_2(noSuchName, inconsistentName), 1, [{NewKeyc3, 3}]),
otp_1128_test(),
ok.
@@ -4192,46 +4179,45 @@ table_test() ->
simple_standard_test() ->
?DBG("simple_standard_test -> entry",[]),
gn([[1,1]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[1,3]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[1,3,6]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[1,3,6,1]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[1,3,6,1,2]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[1,3,6,1,2,1]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[1,3,6,1,2,1,1]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
gn([[sysDescr]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
g([[sysDescr,0]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"}]),
g([[sysDescr]]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{[sysDescr], noSuchObject}])),
g([[1,6,7,0]]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{[1,6,7,0], noSuchObject}])),
gn([[1,13]]),
- ?line ?v1_2(?expect3(noSuchName,1, any),
+ ?v1_2(?expect3(noSuchName,1, any),
?expect1([{[1,13], endOfMibView}])),
s([{[sysLocation, 0], "new_value"}]),
- ?line ?expect1([{[sysLocation, 0], "new_value"}]),
+ ?expect1([{[sysLocation, 0], "new_value"}]),
g([[sysLocation, 0]]),
- ?line ?expect1([{[sysLocation, 0], "new_value"}]),
+ ?expect1([{[sysLocation, 0], "new_value"}]),
io:format("Testing noSuchName and badValue...~n"),
s([{[sysServices,0], 3}]),
- ?line ?expect3(?v1_2(noSuchName, notWritable), 1, any),
+ ?expect3(?v1_2(noSuchName, notWritable), 1, any),
s([{[sysLocation, 0], i, 3}]),
- ?line ?expect3(?v1_2(badValue, wrongType), 1, any),
+ ?expect3(?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 is_list(Config) ->
?P(db_notify_client),
{_SaNode, _MgrNode, _MibDir} = init_case(Config),
@@ -4280,11 +4266,11 @@ db_notify_client(Config) when is_list(Config) ->
db_notify_client_test() ->
?DBG("set first new sysLocation",[]),
s([{[sysLocation, 0], "new_value"}]),
- ?line ?expect1([{[sysLocation, 0], "new_value"}]),
+ ?expect1([{[sysLocation, 0], "new_value"}]),
?DBG("set second new sysLocation",[]),
s([{[sysLocation, 0], "new_value"}]),
- ?line ?expect1([{[sysLocation, 0], "new_value"}]).
+ ?expect1([{[sysLocation, 0], "new_value"}]).
%% Callback function
notify(Pid, What) ->
@@ -4300,23 +4286,23 @@ big_test() ->
?DBG("big_test -> testing simple next/get/set @ subagent...",[]),
gn([[klas1]]),
- ?line ?expect1([{[fname,0], ""}]),
+ ?expect1([{[fname,0], ""}]),
g([[fname,0]]),
- ?line ?expect1([{[fname,0], ""}]),
+ ?expect1([{[fname,0], ""}]),
s([{[fname,0], s, "test set"}]),
- ?line ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
g([[fname,0]]),
- ?line ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
?DBG("big_test -> "
"testing next from last instance in master to subagent...",[]),
gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
gn([[1,1], [?v1_2(sysServices, sysORLastChange),0]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{[fname,0], "test set"}]),
s([{[fname,0], s, ""}]),
- ?line ?expect1([{[fname,0], ""}]),
+ ?expect1([{[fname,0], ""}]),
table_test(),
@@ -4324,14 +4310,14 @@ big_test() ->
_FTab = [friendsEntry],
s([{[friendsEntry, [2, 3]], s, "kompis3"},
{[friendsEntry, [3, 3]], i, ?createAndGo}]),
- ?line ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
+ ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
{[friendsEntry, [3, 3]], ?createAndGo}]),
g([[friendsEntry, [2, 3]],
[friendsEntry, [3, 3]]]),
- ?line ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
+ ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
{[friendsEntry, [3, 3]], ?active}]),
s([{[friendsEntry, [3, 3]], i, ?destroy}]),
- ?line ?expect1([{[friendsEntry, [3, 3]], ?destroy}]),
+ ?expect1([{[friendsEntry, [3, 3]], ?destroy}]),
otp_1131_test(),
@@ -4339,28 +4325,28 @@ big_test() ->
[]),
s([{[kompissEntry, [1, 3]], s, "kompis3"},
{[kompissEntry, [2, 3]], i, ?createAndGo}]),
- ?line ?expect1([{[kompissEntry, [1, 3]], "kompis3"},
+ ?expect1([{[kompissEntry, [1, 3]], "kompis3"},
{[kompissEntry, [2, 3]], ?createAndGo}]),
g([[kompissEntry, [1, 3]],
[kompissEntry, [2, 3]]]),
- ?line ?expect1([{[kompissEntry, [1, 3]], "kompis3"},
+ ?expect1([{[kompissEntry, [1, 3]], "kompis3"},
{[kompissEntry, [2, 3]], ?active}]),
gn([[kompissEntry, [1]],
[kompissEntry, [2]]]),
- ?line ?expect1([{[kompissEntry, [1, 3]], "kompis3"},
+ ?expect1([{[kompissEntry, [1, 3]], "kompis3"},
{[kompissEntry, [2, 3]], ?active}]),
s([{[kompissEntry, [1, 2]], s, "kompis3"},
{[kompissEntry, [2, 2]], i, ?createAndGo}]),
- ?line ?expect1([{[kompissEntry, [1, 2]], "kompis3"},
+ ?expect1([{[kompissEntry, [1, 2]], "kompis3"},
{[kompissEntry, [2, 2]], ?createAndGo}]),
gn([[kompissEntry, [1, 1]],
[kompissEntry, [2, 1]]]),
- ?line ?expect1([{[kompissEntry, [1, 2]], "kompis3"},
+ ?expect1([{[kompissEntry, [1, 2]], "kompis3"},
{[kompissEntry, [2, 2]], ?active}]),
s([{[kompissEntry, [2, 3]], i, ?destroy}]),
- ?line ?expect1([{[kompissEntry, [2, 3]], ?destroy}]),
+ ?expect1([{[kompissEntry, [2, 3]], ?destroy}]),
s([{[kompissEntry, [2, 2]], i, ?destroy}]),
- ?line ?expect1([{[kompissEntry, [2, 2]], ?destroy}]),
+ ?expect1([{[kompissEntry, [2, 2]], ?destroy}]),
?DBG("big_test -> done",[]),
ok.
@@ -4371,21 +4357,21 @@ big_test_2() ->
?NPRINT("Testing simple next/get/set @ subagent (2)..."),
gn([[klas2]]),
- ?line ?expect1([{[fname2,0], ""}]),
+ ?expect1([{[fname2,0], ""}]),
g([[fname2,0]]),
- ?line ?expect1([{[fname2,0], ""}]),
+ ?expect1([{[fname2,0], ""}]),
s([{[fname2,0], s, "test set"}]),
- ?line ?expect1([{[fname2,0], "test set"}]),
+ ?expect1([{[fname2,0], "test set"}]),
g([[fname2,0]]),
- ?line ?expect1([{[fname2,0], "test set"}]),
+ ?expect1([{[fname2,0], "test set"}]),
otp_1298_test(),
?NPRINT("Testing next from last object in master to subagent (2)..."),
gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line ?expect1([{[fname2,0], "test set"}]),
+ ?expect1([{[fname2,0], "test set"}]),
gn([[1,1], [?v1_2(sysServices, sysORLastChange),0]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{[fname2,0], "test set"}]),
table_test(),
@@ -4394,40 +4380,40 @@ big_test_2() ->
_FTab = [friendsEntry2],
s([{[friendsEntry2, [2, 3]], s, "kompis3"},
{[friendsEntry2, [3, 3]], i, ?createAndGo}]),
- ?line ?expect1([{[friendsEntry2, [2, 3]], "kompis3"},
+ ?expect1([{[friendsEntry2, [2, 3]], "kompis3"},
{[friendsEntry2, [3, 3]], ?createAndGo}]),
g([[friendsEntry2, [2, 3]],
[friendsEntry2, [3, 3]]]),
- ?line ?expect1([{[friendsEntry2, [2, 3]], "kompis3"},
+ ?expect1([{[friendsEntry2, [2, 3]], "kompis3"},
{[friendsEntry2, [3, 3]], ?active}]),
s([{[friendsEntry2, [3, 3]], i, ?destroy}]),
- ?line ?expect1([{[friendsEntry2, [3, 3]], ?destroy}]),
+ ?expect1([{[friendsEntry2, [3, 3]], ?destroy}]),
?NPRINT("Adding two rows in subagent table with special INDEX (2)"),
s([{[kompissEntry2, [1, 3]], s, "kompis3"},
{[kompissEntry2, [2, 3]], i, ?createAndGo}]),
- ?line ?expect1([{[kompissEntry2, [1, 3]], "kompis3"},
+ ?expect1([{[kompissEntry2, [1, 3]], "kompis3"},
{[kompissEntry2, [2, 3]], ?createAndGo}]),
g([[kompissEntry2, [1, 3]],
[kompissEntry2, [2, 3]]]),
- ?line ?expect1([{[kompissEntry2, [1, 3]], "kompis3"},
+ ?expect1([{[kompissEntry2, [1, 3]], "kompis3"},
{[kompissEntry2, [2, 3]], ?active}]),
gn([[kompissEntry2, [1]],
[kompissEntry2, [2]]]),
- ?line ?expect1([{[kompissEntry2, [1, 3]], "kompis3"},
+ ?expect1([{[kompissEntry2, [1, 3]], "kompis3"},
{[kompissEntry2, [2, 3]], ?active}]),
s([{[kompissEntry2, [1, 2]], s, "kompis3"},
{[kompissEntry2, [2, 2]], i, ?createAndGo}]),
- ?line ?expect1([{[kompissEntry2, [1, 2]], "kompis3"},
+ ?expect1([{[kompissEntry2, [1, 2]], "kompis3"},
{[kompissEntry2, [2, 2]], ?createAndGo}]),
gn([[kompissEntry2, [1, 1]],
[kompissEntry2, [2, 1]]]),
- ?line ?expect1([{[kompissEntry2, [1, 2]], "kompis3"},
+ ?expect1([{[kompissEntry2, [1, 2]], "kompis3"},
{[kompissEntry2, [2, 2]], ?active}]),
s([{[kompissEntry2, [2, 3]], i, ?destroy}]),
- ?line ?expect1([{[kompissEntry2, [2, 3]], ?destroy}]),
+ ?expect1([{[kompissEntry2, [2, 3]], ?destroy}]),
s([{[kompissEntry2, [2, 2]], i, ?destroy}]),
- ?line ?expect1([{[kompissEntry2, [2, 2]], ?destroy}]),
+ ?expect1([{[kompissEntry2, [2, 2]], ?destroy}]),
ok.
%% Req. Test1
@@ -4436,26 +4422,26 @@ multi_threaded_test() ->
g([[multiStr,0]]),
Pid = get_multi_pid(),
g([[sysUpTime,0]]),
- ?line ?expect1([{[sysUpTime,0], any}]),
+ ?expect1([{[sysUpTime,0], any}]),
s([{[sysLocation, 0], s, "pelle"}]),
- ?line ?expect1([{[sysLocation, 0], "pelle"}]),
+ ?expect1([{[sysLocation, 0], "pelle"}]),
Pid ! continue,
- ?line ?expect1([{[multiStr,0], "ok"}]),
+ ?expect1([{[multiStr,0], "ok"}]),
s([{[multiStr, 0], s, "block"}]),
Pid2 = get_multi_pid(),
g([[sysUpTime,0]]),
- ?line ?expect1([{[sysUpTime,0], any}]),
+ ?expect1([{[sysUpTime,0], any}]),
g([[multiStr,0]]),
Pid3 = get_multi_pid(),
g([[sysUpTime,0]]),
- ?line ?expect1([{[sysUpTime,0], any}]),
+ ?expect1([{[sysUpTime,0], any}]),
s([{[sysLocation, 0], s, "kalle"}]),
Pid3 ! continue,
- ?line ?expect1([{[multiStr,0], "ok"}]),
+ ?expect1([{[multiStr,0], "ok"}]),
Pid2 ! continue,
- ?line ?expect1([{[multiStr,0], "block"}]),
- ?line ?expect1([{[sysLocation,0], "kalle"}]).
+ ?expect1([{[multiStr,0], "block"}]),
+ ?expect1([{[sysLocation,0], "kalle"}]).
%% Req. Test1, TestTrapv2
mt_trap_test(MA, MT) ->
@@ -4463,12 +4449,12 @@ mt_trap_test(MA, MT) ->
?IPRINT("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []),
snmpa:send_trap(MA, testTrapv22, "standard trap"),
?IPRINT("mt_trap_test(02) -> await v2trap", []),
- ?line ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?system ++ [0,1]}]),
%% multi-threaded = true
%% This will *lock* the 'main thread' of a multi-threaded agent,
- %% the worker state will be 'busy'. Therefor when a new request
+ %% the worker state will be 'busy'. Therefore when a new request
%% arrives a new *temporary* worker will be spawned.
?IPRINT("mt_trap_test(03) -> issue mtTrap (standard trap)", []),
snmpa:send_trap(MA, mtTrap, "standard trap"),
@@ -4477,7 +4463,7 @@ mt_trap_test(MA, MT) ->
g([[sysUpTime,0]]),
?IPRINT("mt_trap_test(06) -> await sysUpTime", []),
- ?line ?expect1([{[sysUpTime,0], any}]),
+ ?expect1([{[sysUpTime,0], any}]),
%% This will *only* work if multi-threaded is 'true', not 'extended'
%% since in the latter case all notifications are serialized through
@@ -4488,7 +4474,7 @@ mt_trap_test(MA, MT) ->
?IPRINT("mt_trap_test(07) -> issue testTrapv22 (standard trap)", []),
snmpa:send_trap(MA, testTrapv22, "standard trap"),
?IPRINT("mt_trap_test(08) -> await v2trap", []),
- ?line ?expect2(v2trap,
+ ?expect2(v2trap,
[{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?system ++ [0,1]}]);
true ->
@@ -4499,7 +4485,7 @@ mt_trap_test(MA, MT) ->
Pid ! continue,
?IPRINT("mt_trap_test(10) -> await v2trap", []),
- ?line ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?testTrap ++ [2]},
{[multiStr,0], "ok"}]),
?IPRINT("mt_trap_test(11) -> done", []),
@@ -4509,7 +4495,7 @@ mt_trap_test(MA, MT) ->
get_multi_pid() ->
get_multi_pid(10).
get_multi_pid(0) ->
- ?line ?FAIL(no_global_name);
+ ?FAIL(no_global_name);
get_multi_pid(N) ->
?SLEEP(1000),
case global:whereis_name(snmp_multi_tester) of
@@ -4522,26 +4508,26 @@ types_v2_test() ->
?NPRINT("Testing v2 types..."),
s([{[bits1,0], 2#10}]),
- ?line ?expect1([{[bits1,0], ?str(2#10)}]),
+ ?expect1([{[bits1,0], ?str(2#10)}]),
g([[bits1,0]]),
- ?line ?expect1([{[bits1,0], ?str(2#101)}]),
+ ?expect1([{[bits1,0], ?str(2#101)}]),
s([{[bits2,0], 2#11000000110}]),
- ?line ?expect1([{[bits2,0], ?str(2#11000000110)}]),
+ ?expect1([{[bits2,0], ?str(2#11000000110)}]),
g([[bits2,0]]),
- ?line ?expect1([{[bits2,0], ?str(2#11000000110)}]),
+ ?expect1([{[bits2,0], ?str(2#11000000110)}]),
g([[bits3,0]]),
- ?line ?expect3(genErr, 1, any),
+ ?expect3(genErr, 1, any),
g([[bits4,0]]),
- ?line ?expect3(genErr, 1, any),
+ ?expect3(genErr, 1, any),
s([{[bits1,0], s, [2#10]}]),
- ?line ?expect3(?v1_2(badValue, wrongValue), 1, any),
+ ?expect3(?v1_2(badValue, wrongValue), 1, any),
s([{[bits2,0], 2#11001001101010011}]),
- ?line ?expect3(?v1_2(badValue, wrongValue), 1, any).
+ ?expect3(?v1_2(badValue, wrongValue), 1, any).
%% Req. Test1
@@ -4557,52 +4543,52 @@ implied_test(MA) ->
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 ?expect1([{[testStatus, Idx1], ?createAndGo},
+ ?expect1([{[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 ?expect1([{[testStatus, Idx2], ?createAndGo},
+ ?expect1([{[testStatus, Idx2], ?createAndGo},
{[testDescr, Idx2], "row 2"}]),
?DBG("implied_test -> get-next(testDescr)",[]),
gn([[testDescr]]),
- ?line ?expect1([{[testDescr,Idx1], "row 1"}]),
+ ?expect1([{[testDescr,Idx1], "row 1"}]),
?DBG("implied_test -> get-next(testDescr) of row 1",[]),
gn([[testDescr,Idx1]]),
- ?line ?expect1([{[testDescr,Idx2], "row 2"}]),
+ ?expect1([{[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 ?expect1([{[testStatus, Idx1], ?destroy}]),
+ ?expect1([{[testStatus, Idx1], ?destroy}]),
?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]),
s([{[testStatus, Idx2], i, ?destroy}]),
- ?line ?expect1([{[testStatus, Idx2], ?destroy}]),
+ ?expect1([{[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 ?expect1([{[testStatus2, Idx3], ?createAndGo},
+ ?expect1([{[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 ?expect1([{[testStatus2, Idx4], ?createAndGo},
+ ?expect1([{[testStatus2, Idx4], ?createAndGo},
{[testDescr2, Idx4], "row 2"}]),
?DBG("implied_test -> get-next(testDescr2)",[]),
gn([[testDescr2]]),
- ?line ?expect1([{[testDescr2,Idx3], "row 1"}]),
+ ?expect1([{[testDescr2,Idx3], "row 1"}]),
?DBG("implied_test -> get-next(testDescr2) of row 1",[]),
gn([[testDescr2,Idx3]]),
- ?line ?expect1([{[testDescr2,Idx4], "row 2"}]),
+ ?expect1([{[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 ?expect1([{[testStatus2, Idx3], ?destroy}]),
+ ?expect1([{[testStatus2, Idx3], ?destroy}]),
?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]),
s([{[testStatus2, Idx4], i, ?destroy}]),
- ?line ?expect1([{[testStatus2, Idx4], ?destroy}]),
+ ?expect1([{[testStatus2, Idx4], ?destroy}]),
snmpa:verbosity(MA, log),
@@ -4620,25 +4606,25 @@ sparse_table_test() ->
Idx2 = 2,
s([{[sparseStatus, Idx1], i, ?createAndGo},
{[sparseDescr, Idx1], s, "row 1"}]),
- ?line ?expect1([{[sparseStatus, Idx1], ?createAndGo},
+ ?expect1([{[sparseStatus, Idx1], ?createAndGo},
{[sparseDescr, Idx1], "row 1"}]),
s([{[sparseStatus, Idx2], i, ?createAndGo},
{[sparseDescr, Idx2], s, "row 2"}]),
- ?line ?expect1([{[sparseStatus, Idx2], ?createAndGo},
+ ?expect1([{[sparseStatus, Idx2], ?createAndGo},
{[sparseDescr, Idx2], "row 2"}]),
?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2],
[sparseStatus,Idx1], [sparseStatus,Idx2]]),
gb(0,5,[[sparseIndex]])),
- ?line ?expect1([{[sparseDescr,Idx1], "row 1"},
+ ?expect1([{[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 ?expect1([{[sparseStatus, Idx1], ?destroy}]),
+ ?expect1([{[sparseStatus, Idx1], ?destroy}]),
s([{[sparseStatus, Idx2], i, ?destroy}]),
- ?line ?expect1([{[sparseStatus, Idx2], ?destroy}]).
+ ?expect1([{[sparseStatus, Idx2], ?destroy}]).
%% Req. Test1
@@ -4653,12 +4639,12 @@ cnt_64_test(MA) ->
?DBG("get cnt64",[]),
g([[cnt64,0]]),
?DBG("await response",[]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{[cnt64,0],18446744073709551615}])),
?DBG("get-next cnt64",[]),
gn([[cnt64]]),
?DBG("await response",[]),
- ?line ?v1_2(?expect1([{[cnt64Str,0], "after cnt64"}]),
+ ?v1_2(?expect1([{[cnt64Str,0], "after cnt64"}]),
?expect1([{[cnt64,0],18446744073709551615}])),
?DBG("send cntTrap",[]),
snmpa:send_trap(MA,cntTrap,"standard trap",[
@@ -4667,7 +4653,7 @@ cnt_64_test(MA) ->
{sysLocation, "here"}
]),
?DBG("await response",[]),
- ?line ?v1_2(?expect5(trap, [test], 6, 1, [{[sysContact,0], "pelle"},
+ ?v1_2(?expect5(trap, [test], 6, 1, [{[sysContact,0], "pelle"},
{[sysLocation,0], "here"}]),
?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?testTrap ++ [1]},
@@ -4681,26 +4667,26 @@ cnt_64_test(MA) ->
?DBG("create row (cntStatus): ~p",[Idx1]),
s([{[cntStatus, Idx1], i, ?createAndGo}]),
?DBG("await response",[]),
- ?line ?expect1([{[cntStatus, Idx1], ?createAndGo}]),
+ ?expect1([{[cntStatus, Idx1], ?createAndGo}]),
?DBG("create row (cntStatus): ~p",[Idx2]),
s([{[cntStatus, Idx2], i, ?createAndGo}]),
?DBG("await response",[]),
- ?line ?expect1([{[cntStatus, Idx2], ?createAndGo}]),
+ ?expect1([{[cntStatus, Idx2], ?createAndGo}]),
?DBG("get-next (cntIndex)",[]),
gn([[cntIndex]]),
?DBG("await response",[]),
- ?line ?v1_2(?expect1([{[cntStatus,Idx1], ?active}]),
+ ?v1_2(?expect1([{[cntStatus,Idx1], ?active}]),
?expect1([{[cntCnt,Idx1], 0}])),
% Delete the rows
?DBG("delete row (cntStatus): ~p",[Idx1]),
s([{[cntStatus, Idx1], i, ?destroy}]),
?DBG("await response",[]),
- ?line ?expect1([{[cntStatus, Idx1], ?destroy}]),
+ ?expect1([{[cntStatus, Idx1], ?destroy}]),
?DBG("delete row (cntStatus): ~p",[Idx2]),
s([{[cntStatus, Idx2], i, ?destroy}]),
?DBG("await response",[]),
- ?line ?expect1([{[cntStatus, Idx2], ?destroy}]),
+ ?expect1([{[cntStatus, Idx2], ?destroy}]),
catch snmpa:verbosity(MA, log),
?DBG("done",[]),
ok.
@@ -4709,40 +4695,40 @@ cnt_64_test(MA) ->
opaque_test() ->
?NPRINT("Testing Opaque datatype..."),
g([[opaqueObj,0]]),
- ?line ?expect1([{[opaqueObj,0], "opaque-data"}]).
+ ?expect1([{[opaqueObj,0], "opaque-data"}]).
%% Req. OLD-SNMPEA-MIB
api_test(MaNode) ->
- ?line {value, OID} = rpc:call(MaNode, snmpa, name_to_oid,
+ {value, OID} = rpc:call(MaNode, snmpa, name_to_oid,
[intAgentIpAddress]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmpa,
+ {value, intAgentIpAddress} = rpc:call(MaNode, snmpa,
oid_to_name, [OID]),
- ?line false = rpc:call(MaNode, snmpa, name_to_oid, [intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmpa, oid_to_name,
+ false = rpc:call(MaNode, snmpa, name_to_oid, [intAgentIpAddres]),
+ false = rpc:call(MaNode, snmpa, oid_to_name,
[[1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmpa, enum_to_int,
+ {value, 2} = rpc:call(MaNode, snmpa, enum_to_int,
[intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmpa, int_to_enum,
+ {value, excluded} = rpc:call(MaNode, snmpa, int_to_enum,
[intViewType, 2]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int, [intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int, [intViewType, exclude]),
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, [intViewType, 3]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, [intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, [intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmpa,
+ false = rpc:call(MaNode, snmpa, int_to_enum, [intViewType, 3]),
+ false = rpc:call(MaNode, snmpa, int_to_enum, [intAgentIpAddress, 2]),
+ false = rpc:call(MaNode, snmpa, int_to_enum, [intAgentIpAddre, 2]),
+ {value, active} = rpc:call(MaNode, snmpa,
int_to_enum, ['RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmpa,
+ {value, ?destroy} = rpc:call(MaNode, snmpa,
enum_to_int, ['RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmpa,
+ false = rpc:call(MaNode, snmpa,
enum_to_int, ['RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmpa,
+ false = rpc:call(MaNode, snmpa,
enum_to_int, ['xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, ['RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, ['xxRowStatus', 1]),
- ?line case snmp:date_and_time() of
+ false = rpc:call(MaNode, snmpa, int_to_enum, ['RowStatus', 25]),
+ false = rpc:call(MaNode, snmpa, int_to_enum, ['xxRowStatus', 1]),
+ case snmp:date_and_time() of
List when is_list(List), length(List) == 8 -> ok;
List when is_list(List), length(List) == 11 -> ok
end.
@@ -4750,42 +4736,42 @@ api_test(MaNode) ->
%% Req. Klas3
api_test2() ->
g([[fname3,0]]),
- ?line ?expect1([{[fname3,0], "ok"}]),
+ ?expect1([{[fname3,0], "ok"}]),
g([[fname4,0]]),
- ?line ?expect1([{[fname4,0], 1}]).
+ ?expect1([{[fname4,0], 1}]).
api_test3() ->
g([[fname3,0]]),
- ?line ?expect1([{[fname3,0], "ok"}]).
+ ?expect1([{[fname3,0], "ok"}]).
unreg_test() ->
gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line ?expect1([{[snmpInPkts, 0], any}]).
+ ?expect1([{[snmpInPkts, 0], any}]).
load_test() ->
gn([[?v1_2(sysServices, sysORLastChange),0]]),
- ?line ?expect1([{[fname,0], ""}]).
+ ?expect1([{[fname,0], ""}]).
%% Req. Klas1
load_test_sa() ->
gn([[?v1_2(sysServices,sysORLastChange), 0]]),
- ?line ?expect1([{[fname,0], any}]).
+ ?expect1([{[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 ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
g([[sysDescr,0], Key1c4, [fname,0],Key1c3,[sysName,0]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
+ ?expect1([{[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(?expect3(noSuchName, [1,4], any),
+ ?v1_2(?expect3(noSuchName, [1,4], any),
?expect1([{[1,3,7,1], noSuchObject},
{Key1c4, 2},
{[sysDescr,0], "Erlang SNMP agent"},
@@ -4798,16 +4784,16 @@ 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 ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]),
- ?line ?v1_2(?expect3(noSuchName, 5, any),
+ ?v1_2(?expect3(noSuchName, 5, any),
?expect1([{[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(?expect3(noSuchName, [3,5], any),
+ ?v1_2(?expect3(noSuchName, [3,5], any),
?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{Key1c4, 2},
{[fname3,0], noSuchObject},
@@ -4822,9 +4808,9 @@ do_mul_next() ->
Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
s([{[fname,0], s, "test set"}]),
- ?line ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{Key1c4, 2}, {[fname,0], "test set"},
{Key1c3, 2}, {[sysName,0], "test"}]).
@@ -4835,9 +4821,9 @@ do_mul_next_err() ->
Key1c3 = [intCommunityEntry,[3],get(mip),is("public")],
Key1c4 = [intCommunityEntry,[4],get(mip),is("public")],
s([{[fname,0], s, "test set"}]),
- ?line ?expect1([{[fname,0], "test set"}]),
+ ?expect1([{[fname,0], "test set"}]),
gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]),
- ?line ?v1_2(?expect3(noSuchName, [3,5], any),
+ ?v1_2(?expect3(noSuchName, [3,5], any),
?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{Key1c4, 2},
{[1,3,6,999], endOfMibView},
@@ -4859,7 +4845,7 @@ do_mul_set() ->
{NewKeyc5, ?createAndGo},
{NewKeyc4, 2},
{[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
+ ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
{NewKeyc3, 2},
{[sysLocation,0], "new_value"},
{NewKeyc5, ?createAndGo},
@@ -4868,14 +4854,14 @@ do_mul_set() ->
g([[friendsEntry, [2, 3]],
[sysLocation,0],
[friendsEntry, [3, 3]]]),
- ?line ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
+ ?expect1([{[friendsEntry, [2, 3]], "kompis3"},
{[sysLocation,0], "new_value"},
{[friendsEntry, [3, 3]], ?active}]),
g([NewKeyc4]),
- ?line ?expect1([{NewKeyc4, 2}]),
+ ?expect1([{NewKeyc4, 2}]),
s([{[friendsEntry, [3, 3]], ?destroy},
{NewKeyc5, ?destroy}]),
- ?line ?expect1([{[friendsEntry, [3, 3]], ?destroy},
+ ?expect1([{[friendsEntry, [3, 3]], ?destroy},
{NewKeyc5, ?destroy}]).
%% Req. system group, Klas1, OLD-SNMPEA-MIB
@@ -4890,46 +4876,46 @@ do_mul_set_err() ->
{NewKeyc5, ?createAndGo},
{NewKeyc4, 2},
{[friendsEntry, [3, 3]], ?createAndGo}]),
- ?line ?expect3(?v1_2(noSuchName, notWritable), 3, any),
+ ?expect3(?v1_2(noSuchName, notWritable), 3, any),
g([[friendsEntry, [2, 3]]]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{[friendsEntry, [2,3]], noSuchInstance}])),
g([NewKeyc4]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{NewKeyc4, noSuchInstance}])).
%% Req. SA-MIB
sa_mib() ->
g([[sa, [2,0]]]),
- ?line ?expect1([{[sa, [2,0]], 3}]),
+ ?expect1([{[sa, [2,0]], 3}]),
s([{[sa, [1,0]], s, "sa_test"}]),
- ?line ?expect1([{[sa, [1,0]], "sa_test"}]),
+ ?expect1([{[sa, [1,0]], "sa_test"}]),
ok.
ma_trap1(MA) ->
ok = snmpa:send_trap(MA, testTrap2, "standard trap"),
- ?line ?expect5(trap, [system], 6, 1, [{[system, [4,0]],
+ ?expect5(trap, [system], 6, 1, [{[system, [4,0]],
"{mbj,eklas}@erlang.ericsson.se"}]),
ok = snmpa:send_trap(MA, testTrap1, "standard trap"),
- ?line ?expect5(trap, [1,2,3] , 1, 0, [{[system, [4,0]],
+ ?expect5(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 ?expect5(trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]),
+ ?expect5(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 ?expect5(trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]),
+ ?expect5(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 ?expect5(trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
+ ?expect5(trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1},
{[ifAdminStatus, 1], 1},
{[ifOperStatus, 1], 2}]),
ok.
@@ -4949,7 +4935,7 @@ sa_trap1(SA) ->
%% io:format("sa_trap1 -> SA trap send: "
%% "~n TSRes: ~p"
%% "~n", [TSRes]),
- ?line ?expect5(trap, [ericsson], 6, 1, [{[system, [4,0]],
+ ?expect5(trap, [ericsson], 6, 1, [{[system, [4,0]],
"{mbj,eklas}@erlang.ericsson.se"},
{[sa, [1,0]], "sa_test"}]),
snmpa:verbosity(SA, {subagents, silence}),
@@ -4957,14 +4943,14 @@ sa_trap1(SA) ->
sa_trap2(SA) ->
snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line ?expect5(trap, [ericsson], 6, 1, [{[system, [4,0]], "pelle"},
+ ?expect5(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 ?expect5(trap, [ericsson], 6, 2, [{[system, [4,0]],
+ ?expect5(trap, [ericsson], 6, 2, [{[system, [4,0]],
"{mbj,eklas}@erlang.ericsson.se"},
{[sa, [1,0]], "sa_test"},
{[intViewSubtree,4],[1,2,3,4]}]),
@@ -4974,25 +4960,23 @@ 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 ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(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 ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?snmp ++ [1]}]),
ok.
ma_v2_trap2(MA) ->
snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]),
- ?line ?expect2(v2trap, [{[sysUpTime, 0], any},
- {[snmpTrapOID, 0], ?system ++ [0,1]},
- {[system, [4,0]], "pelle"}]).
+ ?expect2(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_inform1 -> entry with"
- "~n MA = ~p => "
- "~n send notification: testTrapv22", [MA]),
+ ?IPRINT("begin ma_v2_inform1 (MA: ~p)", [MA]),
CmdExpectInform =
fun(_No, Response) ->
@@ -5145,9 +5129,7 @@ ma_v2_inform1(MA) ->
%% Note: This test case takes a while... actually a couple of minutes.
ma_v2_inform2(MA) ->
- ?DBG("ma_v2_inform2 -> entry with"
- "~n MA = ~p => "
- "~n send notification: testTrapv22", [MA]),
+ ?IPRINT("begin ma_v2_inform2 (MA: ~p)", [MA]),
CmdExpectInform =
fun(_No, Response) ->
@@ -5244,9 +5226,7 @@ ma_v2_inform2(MA) ->
%% Note: This test case takes a while... actually a couple of minutes.
ma_v2_inform3(MA) ->
- ?DBG("ma_v2_inform3 -> entry with"
- "~n MA = ~p => "
- "~n send notification: testTrapv22", [MA]),
+ ?IPRINT("begin ma_v2_inform3 (MA: ~p)", [MA]),
CmdExpectInform =
fun(_No, Response) ->
@@ -5389,10 +5369,10 @@ command_handler([{_No, _Desc, Cmd}|Rest]) ->
%% command_handler(Rest);
%% {error, Reason} ->
%% ?EPRINT("command_handler -> ~w error: ~n~p", [_No, Reason]),
- %% ?line ?FAIL(Reason);
+ %% ?FAIL(Reason);
%% Error ->
%% ?EPRINT("command_handler -> ~w unexpected: ~n~p", [_No, Error]),
- %% ?line ?FAIL({unexpected_command_result, Error})
+ %% ?FAIL({unexpected_command_result, Error})
%% end.
try Cmd() of
ok ->
@@ -5404,7 +5384,7 @@ command_handler([{_No, _Desc, Cmd}|Rest]) ->
if
(SysEvs =:= []) ->
?EPRINT("command_handler -> ~w error: ~n~p", [_No, Reason]),
- ?line ?FAIL(Reason);
+ ?FAIL(Reason);
true ->
?WPRINT("command_handler -> "
"failed when we got system events: "
@@ -5420,7 +5400,7 @@ command_handler([{_No, _Desc, Cmd}|Rest]) ->
(SysEvs =:= []) ->
?EPRINT("command_handler -> "
"~w unexpected: ~n~p", [_No, Error]),
- ?line ?FAIL({unexpected_command_result, Error});
+ ?FAIL({unexpected_command_result, Error});
true ->
?WPRINT("command_handler -> "
"unexpected when we got system events: "
@@ -5431,32 +5411,32 @@ command_handler([{_No, _Desc, Cmd}|Rest]) ->
end
catch
C:E:S ->
- ?IPRINT("command_handler -> command ~w catched", [_No]),
+ ?IPRINT("command_handler -> command ~w caught", [_No]),
SysEvs = snmp_test_global_sys_monitor:events(),
if
(SysEvs =:= []) ->
- ?EPRINT("command_handler -> ~w catched: "
+ ?EPRINT("command_handler -> ~w caught: "
"~n Class: ~p"
"~n Error: ~p"
"~n Stack: ~p", [_No, C, E, S]),
- ?line ?FAIL({catched_command_result, {C, E, S}});
+ ?FAIL({catched_command_result, {C, E, S}});
true ->
?WPRINT("command_handler -> "
- "catched when we got system events: "
- "~n Catched: "
+ "caught when we got system events: "
+ "~n Caught: "
"~n Class: ~p"
"~n Error: ~p"
"~n Stack: ~p"
"~n Sys Events: ~p"
"~n", [C, E, S, SysEvs]),
- ?SKIP([{catched, {C, E, S}}, {system_events, SysEvs}])
+ ?SKIP([{caught, {C, E, S}}, {system_events, SysEvs}])
end
end.
ma_v1_2_v2_trap(MA) ->
snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]),
- ?line ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?snmpTraps ++ [3]},
{[ifIndex, 1], 1},
{[snmpTrapEnterprise, 0], [1,2,3]}]).
@@ -5464,7 +5444,7 @@ ma_v1_2_v2_trap(MA) ->
ma_v1_2_v2_trap2(MA) ->
snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]),
- ?line ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?system ++ [0,1]},
{[system, [4,0]], "pelle"},
{[snmpTrapEnterprise, 0], ?system}]).
@@ -5473,7 +5453,7 @@ 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 ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
{[system, [4,0]],
"{mbj,eklas}@erlang.ericsson.se"},
@@ -5485,7 +5465,7 @@ sa_v1_2_v2_trap1(SA) ->
sa_v1_2_v2_trap2(SA) ->
snmpa:verbosity(SA, {subagents, trace}),
snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]),
- ?line ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?ericsson ++ [0, 1]},
{[system, [4,0]], "pelle"},
{[sa, [1,0]], "sa_test"},
@@ -5498,7 +5478,7 @@ 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 ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], ?ericsson ++ [0, 2]},
{[system, [4,0]],
"{mbj,eklas}@erlang.ericsson.se"},
@@ -5518,14 +5498,14 @@ sa_errs_bad_value() ->
{[sa, [2,0]], 5}, % badValue (i is_set_ok)
{NewKeyc5, ?createAndGo},
{NewKeyc4, 2}]),
- ?line ?expect3(badValue, 2, any),
+ ?expect3(badValue, 2, any),
s([{NewKeyc3, 2},
{[sa, [2,0]], 6}, % wrongValue (i is_set_ok)
{NewKeyc5, ?createAndGo},
{NewKeyc4, 2}]),
- ?line ?expect3(?v1_2(badValue, wrongValue), 2, any),
+ ?expect3(?v1_2(badValue, wrongValue), 2, any),
g([NewKeyc4]),
- ?line ?v1_2(?expect3(noSuchName, 1, any),
+ ?v1_2(?expect3(noSuchName, 1, any),
?expect1([{NewKeyc4, noSuchInstance}])).
%% Req. SA-MIB, OLD-SNMPEA-MIB
@@ -5535,22 +5515,22 @@ sa_errs_gen_err() ->
NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")],
s([{NewKeyc3, 2},{NewKeyc4, 2},
{NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]),
- ?line ?expect3(genErr, 4, any),
+ ?expect3(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 ?expect1([{NewKeyc5, ?destroy}]).
+ ?expect1([{NewKeyc5, ?destroy}]).
%% Req. SA-MIB, OLD-SNMPEA-MIB
sa_too_big() ->
g([[sa, [4,0]]]),
- ?line ?expect1(tooBig).
+ ?expect1(tooBig).
%% Req. Klas1, system group, snmp group (v1/v2)
next_across_sa_test() ->
gn([[sysDescr],[klas1,5]]),
- ?line ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
+ ?expect1([{[sysDescr,0], "Erlang SNMP agent"},
{[snmpInPkts, 0], any}]).
%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError
@@ -5562,40 +5542,40 @@ next_across_sa_test() ->
%% Req. Klas3, Klas4
undo_test() ->
s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
- ?line ?expect1([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
+ ?expect1([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]),
s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]),
- ?line ?expect3(?v1_2(badValue, inconsistentValue), 2, any),
+ ?expect3(?v1_2(badValue, inconsistentValue), 2, any),
s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]),
- ?line ?expect3(?v1_2(genErr, undoFailed), 1, any),
+ ?expect3(?v1_2(genErr, undoFailed), 1, any),
s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]),
- ?line ?expect3(?v1_2(genErr, commitFailed), 1, any),
-% unfortunatly we don't know if we'll get undoFailed or commitFailed.
+ ?expect3(?v1_2(genErr, commitFailed), 1, any),
+% unfortunately 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),
+% expect(5, ?v1_2(genErr, undoFailed), 1, any),
s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]),
- ?line ?expect3(genErr, 2, any).
+ ?expect3(genErr, 2, any).
%% Req. Klas3, Klas4
bad_return() ->
g([[fStatus4,4],
[fName4,4]]),
- ?line ?expect3(genErr, 2, any),
+ ?expect3(genErr, 2, any),
g([[fStatus4,5],
[fName4,5]]),
- ?line ?expect3(genErr, 1, any),
+ ?expect3(genErr, 1, any),
g([[fStatus4,6],
[fName4,6]]),
- ?line ?expect3(genErr, 2, any),
+ ?expect3(genErr, 2, any),
gn([[fStatus4,7],
[fName4,7]]),
- ?line ?expect3(genErr, 2, any),
+ ?expect3(genErr, 2, any),
gn([[fStatus4,8],
[fName4,8]]),
- ?line ?expect3(genErr, 1, any),
+ ?expect3(genErr, 1, any),
gn([[fStatus4,9],
[fName4,9]]),
- ?line ?expect3(genErr, 2, any).
+ ?expect3(genErr, 2, any).
%%%-----------------------------------------------------------------
@@ -5630,7 +5610,6 @@ standard_mibs_cases_ipv6() ->
%% 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 is_list(Config) ->
?P(snmp_standard_mib),
init_case(Config),
@@ -5671,9 +5650,9 @@ snmp_standard_mib(Config) when is_list(Config) ->
%% 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,
+ [OutPkts] = get_req(2, [[snmpOutPkts,0]]),
+ [OutPkts2] = get_req(3, [[snmpOutPkts,0]]),
+ 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.
@@ -5683,27 +5662,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 ?expect1([{[snmpEnableAuthenTraps, 0], 2}]).
+ ?expect1([{[snmpEnableAuthenTraps, 0], 2}]).
%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
std_mib_finish() ->
%% enable again
s([{[snmpEnableAuthenTraps,0], 1}]),
- ?line ?expect1([{[snmpEnableAuthenTraps, 0], 1}]).
+ ?expect1([{[snmpEnableAuthenTraps, 0], 1}]).
%% Req. SNMP-STANDARD-MIB
standard_mib_test_finish() ->
%% force a authenticationFailure (should result in a trap)
std_mib_write(),
%% check that we got a trap
- ?line ?expect5(trap, [1,2,3], 4, 0, []).
+ ?expect5(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 ?expect1(timeout). % make sure we don't get a trap!
+ ?expect1(timeout). % make sure we don't get a trap!
%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
@@ -5731,7 +5710,6 @@ standard_mibs2_cases() ->
%% 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 is_list(Config) ->
?P(snmpv2_mib_2),
?IPRINT("snmpv2_mib_2 -> start"),
@@ -5763,7 +5741,7 @@ snmpv2_mib_2(Config) when is_list(Config) ->
?DBG("snmpv2_mib_2 -> check counters",[]),
try_test(std_mib_c, [Bad]),
- ?DBG("snmpv2_mib_2 -> get som counters",[]),
+ ?DBG("snmpv2_mib_2 -> get some counters",[]),
try_test(snmpv2_mib_a),
?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]),
@@ -5790,7 +5768,6 @@ standard_mibs3_cases() ->
%% Req. SNMPv2-MIB
-snmpv2_mib_3(suite) -> [];
snmpv2_mib_3(Config) when is_list(Config) ->
%% <CONDITIONAL-SKIP>
Skippable = [{unix, [darwin]}],
@@ -5820,31 +5797,31 @@ snmpv2_mib_test_finish() ->
%% check that we got a trap
?DBG("ma_v2_inform -> await trap",[]),
- ?line ?expect2(v2trap, [{[sysUpTime,0], any},
+ ?expect2(v2trap, [{[sysUpTime,0], any},
{[snmpTrapOID,0], ?authenticationFailure}]),
%% and the the inform
?DBG("ma_v2_inform -> await inform",[]),
- ?line ?expect2({inform,true}, [{[sysUpTime,0], any},
+ ?expect2({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,
+ [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ InPkts2 = InPkts + 1,
- ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]),
+ [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] =
+ [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]),
+ InBadVsns2 = InBadVsns + 1,
+ [InPkts] = get_req(2, [[snmpInPkts,0]]),
+ [InPkts2] = get_req(3, [[snmpInPkts,0]]),
+ InPkts2 = InPkts + 1,
+ [InBadCommunityNames, InBadCommunityUses, InASNErrs] =
get_req(4, [[snmpInBadCommunityNames,0],
[snmpInBadCommunityUses,0],
[snmpInASNParseErrs, 0]]),
@@ -5852,25 +5829,25 @@ std_mib_b(InBadVsns) ->
%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB
std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) ->
- ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
+ [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] =
get_req(1, [[snmpInBadCommunityNames,0],
[snmpInBadCommunityUses,0],
[snmpInASNParseErrs, 0]]),
- ?line InBadCommunityNames2 = InBadCommunityNames + 1,
- ?line InBadCommunityUses2 = InBadCommunityUses + 1,
- ?line InASNErrs2 = InASNErrs + 1.
+ InBadCommunityNames2 = InBadCommunityNames + 1,
+ InBadCommunityUses2 = InBadCommunityUses + 1,
+ InASNErrs2 = InASNErrs + 1.
%% Req. SNMPv2-MIB
snmpv2_mib_a() ->
- ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
+ [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]),
s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]),
- ?line ?expect1([{[snmpSetSerialNo,0], SetSerial},
+ ?expect1([{[snmpSetSerialNo,0], SetSerial},
{[sysLocation, 0], "val2"}]),
s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]),
- ?line ?expect3(inconsistentValue, 2,
+ ?expect3(inconsistentValue, 2,
[{[sysLocation, 0], "val3"},
{[snmpSetSerialNo,0], SetSerial}]),
- ?line ["val2"] = get_req(5, [[sysLocation,0]]),
+ ["val2"] = get_req(5, [[sysLocation,0]]),
ok.
@@ -5879,13 +5856,12 @@ snmpv2_mib_a() ->
%% in SNMPv2-MIB and STANDARD-MIB.
%% o Test add/deletion of rows.
%%-----------------------------------------------------------------
-snmp_community_mib(suite) -> [];
snmp_community_mib(Config) when is_list(Config) ->
?P(snmp_community_mib),
init_case(Config),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
try_test(snmp_community_mib_test),
- ?line unload_master("SNMP-COMMUNITY-MIB").
+ unload_master("SNMP-COMMUNITY-MIB").
snmp_community_mib_2(X) -> ?P(snmp_community_mib_2), snmp_community_mib(X).
@@ -5898,17 +5874,15 @@ snmp_community_mib_test() ->
%%-----------------------------------------------------------------
%% o Test engine boots / time
%%-----------------------------------------------------------------
-snmp_framework_mib(suite) -> [];
snmp_framework_mib(Config) when is_list(Config) ->
?P(snmp_framework_mib),
init_case(Config),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
try_test(snmp_framework_mib_test),
- ?line unload_master("SNMP-FRAMEWORK-MIB").
+ unload_master("SNMP-FRAMEWORK-MIB").
snmp_framework_mib_2(X) -> ?P(snmp_framework_mib_2), snmp_framework_mib(X).
-snmp_framework_mib_3(suite) -> [];
snmp_framework_mib_3(Config) when is_list(Config) ->
?P(snmp_framework_mib_3),
init_case(Config),
@@ -5921,7 +5895,7 @@ snmp_framework_mib_3(Config) when is_list(Config) ->
%% the same as the number of seconds we sleep (5 in this case).
%% But because, on some (slow or/and high loaded) hosts, the actual
%% time we sleep could be a lot larger (due to, for instance, scheduling).
-%% Therefor we must take that into account when we check if the
+%% Therefore we must take that into account when we check if the
%% Engine Time diff (between the two checks) is acceptably.
snmp_framework_mib_test() ->
@@ -5935,13 +5909,13 @@ snmp_framework_mib_test() ->
]),
Sleep = 5,
- ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
+ ["agentEngine"] = get_req(1, [[snmpEngineID,0]]),
T1 = snmp_misc:now(ms),
- ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
+ [EngineTime] = get_req(2, [[snmpEngineTime,0]]),
T2 = snmp_misc:now(ms),
?SLEEP(?SECS(Sleep)),
T3 = snmp_misc:now(ms),
- ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
+ [EngineTime2] = get_req(3, [[snmpEngineTime,0]]),
T4 = snmp_misc:now(ms),
%% Ok, we tried to sleep 5 seconds, but how long did we actually sleep
@@ -5988,18 +5962,18 @@ snmp_framework_mib_test() ->
?EPRINT("snmp_framework_mib -> (High) Engine Time diff (~w) too large: "
"~n ~w < ~w",
[EngineTimeDiff, HighEngineTime, EngineTime2]),
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ ?FAIL({too_large_diff, EngineTime, EngineTime2});
(LowEngineTime > EngineTime2) ->
?EPRINT("snmp_framework_mib -> (Low) Engine Time diff (~w) too large: "
"~n ~w > ~w",
[EngineTimeDiff, LowEngineTime, EngineTime2]),
- ?line ?FAIL({too_large_diff, EngineTime, EngineTime2});
+ ?FAIL({too_large_diff, EngineTime, EngineTime2});
true ->
ok
end,
T5 = snmp_misc:now(ms),
- ?line case get_req(4, [[snmpEngineBoots,0]]) of
+ case get_req(4, [[snmpEngineBoots,0]]) of
[Boots] when is_integer(Boots) ->
T6 = snmp_misc:now(ms),
?IPRINT("snmp_framework_mib -> "
@@ -6016,7 +5990,6 @@ snmp_framework_mib_test() ->
%%-----------------------------------------------------------------
%% o Test the counters
%%-----------------------------------------------------------------
-snmp_mpd_mib_3(suite) -> [];
snmp_mpd_mib_3(Config) when is_list(Config) ->
%% <CONDITIONAL-SKIP>
Skippable = [{unix, [darwin]}],
@@ -6033,7 +6006,7 @@ snmp_mpd_mib_3(Config) when is_list(Config) ->
%% Req. SNMP-MPD-MIB
snmp_mpd_mib_a() ->
- ?line [UnknownSecs, InvalidMsgs] =
+ [UnknownSecs, InvalidMsgs] =
get_req(1, [[snmpUnknownSecurityModels,0],
[snmpInvalidMsgs,0]]),
Pdu = #pdu{type = 'get-request',
@@ -6044,7 +6017,7 @@ snmp_mpd_mib_a() ->
SPdu = #scopedPdu{contextEngineID = "agentEngine",
contextName = "",
data = Pdu},
- ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
+ SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu),
V3Hdr1 = #v3_hdr{msgID = 21,
msgMaxSize = 484,
msgFlags = [7],
@@ -6059,38 +6032,37 @@ snmp_mpd_mib_a() ->
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),
+ MsgBytes1 = snmp_pdus:enc_message_only(Message1),
+ MsgBytes2 = snmp_pdus:enc_message_only(Message2),
snmp_test_mgr:send_bytes(MsgBytes1),
snmp_test_mgr:send_bytes(MsgBytes2),
- ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
+ [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] =
get_req(1, [[snmpUnknownSecurityModels,0],
[snmpInvalidMsgs,0],
[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownSecs2 = UnknownSecs + 1,
- ?line InvalidMsgs2 = InvalidMsgs + 1,
+ UnknownSecs2 = UnknownSecs + 1,
+ 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 ?expect2(report, [{?snmpUnknownPDUHandlers_instance, any}]).
+ ?expect2(report, [{?snmpUnknownPDUHandlers_instance, any}]).
snmp_mpd_mib_c(UnknownPDUHs) ->
- ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
- ?line UnknownPDUHs2 = UnknownPDUHs + 1,
+ [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]),
+ UnknownPDUHs2 = UnknownPDUHs + 1,
ok.
-snmp_target_mib(suite) -> [];
snmp_target_mib(Config) when is_list(Config) ->
?P(snmp_target_mib),
init_case(Config),
- ?line load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
try_test(snmp_target_mib_test),
- ?line unload_master("SNMP-TARGET-MIB").
+ unload_master("SNMP-TARGET-MIB").
snmp_target_mib_2(X) -> ?P(snmp_target_mib_2), snmp_target_mib(X).
@@ -6100,13 +6072,12 @@ snmp_target_mib_test() ->
?NPRINT("NOT YET IMPLEMENTED"),
nyi.
-snmp_notification_mib(suite) -> [];
snmp_notification_mib(Config) when is_list(Config) ->
?P(snmp_notification_mib),
init_case(Config),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
try_test(snmp_notification_mib_test),
- ?line unload_master("SNMP-NOTIFICATION-MIB").
+ unload_master("SNMP-NOTIFICATION-MIB").
snmp_notification_mib_2(X) -> ?P(snmp_notification_mib_2),
snmp_notification_mib(X).
@@ -6123,16 +6094,15 @@ snmp_notification_mib_test() ->
%% o add/delete views and try them
%% o try boundaries
%%-----------------------------------------------------------------
-snmp_view_based_acm_mib(suite) -> [];
snmp_view_based_acm_mib(Config) when is_list(Config) ->
?P(snmp_view_based_acm_mib),
init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
- ?line load_master("Test2"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ load_master("Test2"),
snmp_view_based_acm_mib(),
- ?line unload_master("Test2"),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+ unload_master("Test2"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB").
snmp_view_based_acm_mib_2(X) ->
?P(snmp_view_based_acm_mib_2),
@@ -6167,7 +6137,7 @@ snmp_view_based_acm_mib() ->
v3 -> {?SEC_USM, ?SEC_V1}
end,
?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
+ try_test(use_no_rights, [], Opts),
%% Now, add a mapping from "no-rights" -> "no-rights-group"
GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]],
@@ -6175,25 +6145,25 @@ snmp_view_based_acm_mib() ->
[{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"},
{GRow1Status, ?createAndGo}],
?DBG("set '~p'",[GRow1]),
- ?line try_test(do_set, [GRow1]),
+ try_test(do_set, [GRow1]),
?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
+ try_test(use_no_rights, [], Opts),
- %% Create a mapping for another sec model, and make sure it dosn't
+ %% Create a mapping for another sec model, and make sure it doesn'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]),
+ try_test(do_set, [GRow2]),
?DBG("assign rights for 'no-rights'",[]),
- ?line try_test(use_no_rights, [], Opts),
+ try_test(use_no_rights, [], Opts),
%% Delete that row
- ?line try_test(del_row, [GRow2Status]),
+ try_test(del_row, [GRow2Status]),
RVName = "rv_name",
WVName = "wv_name",
@@ -6206,7 +6176,7 @@ snmp_view_based_acm_mib() ->
{[vacmAccessWriteViewName, ARow1Idx], WVName},
{ARow1Status, ?createAndGo}],
- %% This access row would give acces, if InvSecMod was valid.
+ %% This access row would give access, if InvSecMod was valid.
ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1],
ARow2Status = [vacmAccessStatus, ARow2Idx],
ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1},
@@ -6214,18 +6184,18 @@ snmp_view_based_acm_mib() ->
{[vacmAccessWriteViewName, ARow2Idx], "internet"},
{ARow2Status, ?createAndGo}],
- ?line try_test(do_set, [ARow2]),
+ try_test(do_set, [ARow2]),
- ?line try_test(use_no_rights, [], Opts),
+ try_test(use_no_rights, [], Opts),
%% Delete that row
- ?line try_test(del_row, [ARow2Status]),
+ try_test(del_row, [ARow2Status]),
%% Add valid row
- ?line try_test(do_set, [ARow1]),
+ try_test(do_set, [ARow1]),
- ?line try_test(use_no_rights, [], Opts),
+ try_test(use_no_rights, [], Opts),
%% Create the view family
VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access
@@ -6237,32 +6207,32 @@ snmp_view_based_acm_mib() ->
VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx],
VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx],
- ?line try_test(add_row, [VRow1Status]),
- ?line try_test(add_row, [VRow2Status]),
- ?line try_test(add_row, [VRow3Status]),
+ try_test(add_row, [VRow1Status]),
+ try_test(add_row, [VRow2Status]),
+ try_test(add_row, [VRow3Status]),
%% We're supposed to have access now...
- ?line try_test(use_rights, [], Opts),
+ try_test(use_rights, [], Opts),
%% Change Row3 to Row4
- ?line try_test(del_row, [VRow3Status]),
- ?line try_test(add_row, [VRow4Status]),
+ try_test(del_row, [VRow3Status]),
+ try_test(add_row, [VRow4Status]),
%% We should still have access...
- ?line try_test(use_rights, [], Opts),
+ try_test(use_rights, [], Opts),
%% Delete rows
- ?line try_test(del_row, [GRow1Status]),
+ try_test(del_row, [GRow1Status]),
- ?line try_test(use_no_rights, [], Opts),
+ 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]),
+ try_test(del_row, [ARow1Status]),
+ try_test(del_row, [VRow1Status]),
+ try_test(del_row, [VRow2Status]),
+ try_test(del_row, [VRow4Status]),
- ?line try_test(use_no_rights, [], Opts),
+ try_test(use_no_rights, [], Opts),
snmpa:verbosity(master_agent,log).
do_set(Row) ->
@@ -6318,7 +6288,6 @@ mk_ln(X) ->
%% 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 is_list(Config) ->
%% <CONDITIONAL-SKIP>
Skippable = [{unix, [darwin]}],
@@ -6330,7 +6299,7 @@ snmp_user_based_sm_mib_3(Config) when is_list(Config) ->
init_case(Config),
_AgentDir = ?config(agent_conf_dir, Config),
- ?line load_master_std("SNMP-USER-BASED-SM-MIB"),
+ load_master_std("SNMP-USER-BASED-SM-MIB"),
%% The newUser used here already has VACM access.
@@ -6339,10 +6308,10 @@ snmp_user_based_sm_mib_3(Config) when is_list(Config) ->
[{sec_level, authPriv}, {user, "privDES"}]),
%% Try to use the new user
- ?line load_master("Test2"),
+ load_master("Test2"),
try_test(v3_sync, [[{usm_use_user, []}]],
[{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
+ unload_master("Test2"),
ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"),
DesKey1 = lists:sublist(ShaKey1, 16),
@@ -6353,55 +6322,55 @@ snmp_user_based_sm_mib_3(Config) when is_list(Config) ->
%% Try to use the new keys
MgrDir = ?config(mgr_dir, Config),
- ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
- ?line load_master("Test2"),
+ rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ load_master("Test2"),
try_test(v3_sync, [[{usm_use_user, []}]],
[{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
+ 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,
+ 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, []}]],
+ rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2),
+ load_master("Test2"),
+ try_test(v3_sync, [[{usm_use_user, []}]],
[{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
+ unload_master("Test2"),
reset_usm_mgr(MgrDir),
%% Change the new user's keys - 3
- ?line try_test(v3_sync,
+ 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"),
+ rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1),
+ load_master("Test2"),
try_test(v3_sync, [[{usm_use_user, []}]],
[{sec_level, authPriv}, {user, "newUser"}]),
- ?line unload_master("Test2"),
+ unload_master("Test2"),
reset_usm_mgr(MgrDir),
%% Try some read requests
- ?line try_test(v3_sync, [[{usm_read, []}]],
+ try_test(v3_sync, [[{usm_read, []}]],
[{sec_level, authPriv}, {user, "privDES"}]),
%% Delete the new user
- ?line try_test(v3_sync, [[{usm_del_user, []}]],
+ try_test(v3_sync, [[{usm_del_user, []}]],
[{sec_level, authPriv}, {user, "privDES"}]),
%% Try some bad requests
- ?line try_test(v3_sync, [[{usm_bad, []}]],
+ try_test(v3_sync, [[{usm_bad, []}]],
[{sec_level, authPriv}, {user, "privDES"}]),
- ?line unload_master("SNMP-USER-BASED-SM-MIB").
+ unload_master("SNMP-USER-BASED-SM-MIB").
-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]).
@@ -6410,8 +6379,8 @@ usm_add_user1() ->
RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer},
{[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line ?expect1(Vbs1),
+ s(Vbs1),
+ ?expect1(Vbs1),
ok.
usm_use_user() ->
@@ -6430,7 +6399,7 @@ usm_key_change1(ShaKey, DesKey) ->
Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
{[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
s(Vbs1),
- ?line ?expect1(Vbs1).
+ ?expect1(Vbs1).
%% Change own private keys
usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
@@ -6444,7 +6413,7 @@ usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) ->
Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange},
{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
s(Vbs1),
- ?line ?expect1(Vbs1).
+ ?expect1(Vbs1).
%% Change other's public keys
usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
@@ -6457,27 +6426,27 @@ usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) ->
DesKey),
Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}],
s(Vbs1),
- ?line ?expect3(noAccess, 1, any),
+ ?expect3(noAccess, 1, any),
Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}],
s(Vbs2),
- ?line ?expect3(noAccess, 1, any),
+ ?expect3(noAccess, 1, any),
Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange},
{[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}],
s(Vbs3),
- ?line ?expect1(Vbs3),
+ ?expect1(Vbs3),
ok.
usm_read() ->
NewRowIndex = [11,"agentEngine", 7, "newUser"],
- ?line g([[usmUserSecurityName, NewRowIndex],
+ g([[usmUserSecurityName, NewRowIndex],
[usmUserCloneFrom, NewRowIndex],
[usmUserAuthKeyChange, NewRowIndex],
[usmUserOwnAuthKeyChange, NewRowIndex],
[usmUserPrivKeyChange, NewRowIndex],
[usmUserOwnPrivKeyChange, NewRowIndex]]),
- ?line ?expect1([{[usmUserSecurityName, NewRowIndex], "newUser"},
+ ?expect1([{[usmUserSecurityName, NewRowIndex], "newUser"},
{[usmUserCloneFrom, NewRowIndex], [0,0]},
{[usmUserAuthKeyChange, NewRowIndex], ""},
{[usmUserOwnAuthKeyChange, NewRowIndex], ""},
@@ -6490,8 +6459,8 @@ usm_read() ->
usm_del_user() ->
NewRowIndex = [11,"agentEngine", 7, "newUser"],
Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs1),
- ?line ?expect1(Vbs1),
+ s(Vbs1),
+ ?expect1(Vbs1),
ok.
-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]).
@@ -6511,32 +6480,32 @@ usm_bad() ->
RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"],
Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1},
{[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs1),
- ?line ?expect3(inconsistentName, 1, any),
+ s(Vbs1),
+ ?expect3(inconsistentName, 1, any),
RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"],
Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2},
{[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs2),
- ?line ?expect3(wrongValue, 1, any),
+ s(Vbs2),
+ ?expect3(wrongValue, 1, any),
RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"],
Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3},
{[usmUserStatus, NewRowIndex], ?createAndGo}],
- ?line s(Vbs3),
- ?line ?expect1(Vbs3),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
- ?line ?expect3(inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
- ?line ?expect3(inconsistentValue, 1, any),
- ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
- ?line ?expect3(wrongValue, 1, any),
- ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
- ?line ?expect3(wrongValue, 1, any),
+ s(Vbs3),
+ ?expect1(Vbs3),
+ s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]),
+ ?expect3(inconsistentValue, 1, any),
+ s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]),
+ ?expect3(inconsistentValue, 1, any),
+ s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]),
+ ?expect3(wrongValue, 1, any),
+ s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]),
+ ?expect3(wrongValue, 1, any),
Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}],
- ?line s(Vbs4),
- ?line ?expect1(Vbs4),
+ s(Vbs4),
+ ?expect1(Vbs4),
ok.
@@ -6545,7 +6514,6 @@ usm_bad() ->
%% works.
%% Load all std mibs that are not loaded by default.
%%-----------------------------------------------------------------
-loop_mib_1(suite) -> [];
loop_mib_1(Config) when is_list(Config) ->
?P(loop_mib_1),
?IPRINT("loop_mib_1 -> initiate case"),
@@ -6556,40 +6524,39 @@ loop_mib_1(Config) when is_list(Config) ->
"\tMgrNode: ~p~n"
"\tMibDir: ~p",[_SaNode, _MgrNode, _MibDir]),
?DBG("loop_mib_1 -> load mib SNMP-COMMUNITY-MIB",[]),
- ?line load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
?DBG("loop_mib_1 -> load mib SNMP-MPD-MIB",[]),
- ?line load_master_std("SNMP-MPD-MIB"),
+ load_master_std("SNMP-MPD-MIB"),
?DBG("loop_mib_1 -> load mib SNMP-TARGET-MIB",[]),
- ?line load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
?DBG("loop_mib_1 -> load mib SNMP-NOTIFICATION-MIB",[]),
- ?line load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
?DBG("loop_mib_1 -> load mib SNMP-FRAMEWORK-MIB",[]),
- ?line load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
?DBG("loop_mib_1 -> load mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
?DBG("loop_mib_1 -> try",[]),
try_test(loop_mib_1_test),
?DBG("loop_mib_1 -> unload mib SNMP-COMMUNITY-MIB",[]),
- ?line unload_master("SNMP-COMMUNITY-MIB"),
+ unload_master("SNMP-COMMUNITY-MIB"),
?DBG("loop_mib_1 -> unload mib SNMP-MPD-MIB",[]),
- ?line unload_master("SNMP-MPD-MIB"),
+ unload_master("SNMP-MPD-MIB"),
?DBG("loop_mib_1 -> unload mib SNMP-TARGET-MIB",[]),
- ?line unload_master("SNMP-TARGET-MIB"),
+ unload_master("SNMP-TARGET-MIB"),
?DBG("loop_mib_1 -> unload mib SNMP-NOTIFICATION-MIB",[]),
- ?line unload_master("SNMP-NOTIFICATION-MIB"),
+ unload_master("SNMP-NOTIFICATION-MIB"),
?DBG("loop_mib_1 -> unload mib SNMP-FRAMEWORK-MIB",[]),
- ?line unload_master("SNMP-FRAMEWORK-MIB"),
+ unload_master("SNMP-FRAMEWORK-MIB"),
?DBG("loop_mib_1 -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB"),
%% snmpa:verbosity(master_agent,log),
%% snmpa:verbosity(mib_server,silence),
?IPRINT("loop_mib_1 -> done"),
ok.
-loop_mib_2(suite) -> [];
loop_mib_2(Config) when is_list(Config) ->
?P(loop_mib_2),
?IPRINT("loop_mib_2 -> initiate case"),
@@ -6599,27 +6566,26 @@ loop_mib_2(Config) when is_list(Config) ->
"\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"),
+ load_master_std("SNMP-COMMUNITY-MIB"),
+ load_master_std("SNMP-MPD-MIB"),
+ load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-FRAMEWORK-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
try_test(loop_mib_2_test),
?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"),
+ unload_master("SNMP-COMMUNITY-MIB"),
+ unload_master("SNMP-MPD-MIB"),
+ unload_master("SNMP-TARGET-MIB"),
+ unload_master("SNMP-NOTIFICATION-MIB"),
+ unload_master("SNMP-FRAMEWORK-MIB"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB"),
?IPRINT("loop_mib_2 -> done"),
ok.
-loop_mib_3(suite) -> [];
loop_mib_3(Config) when is_list(Config) ->
?P(loop_mib_3),
?IPRINT("loop_mib_3 -> initiate case"),
@@ -6629,18 +6595,18 @@ loop_mib_3(Config) when is_list(Config) ->
"\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"),
+ load_master_std("SNMP-TARGET-MIB"),
+ load_master_std("SNMP-NOTIFICATION-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ load_master_std("SNMP-USER-BASED-SM-MIB"),
try_test(loop_mib_3_test),
?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"),
+ unload_master("SNMP-TARGET-MIB"),
+ unload_master("SNMP-NOTIFICATION-MIB"),
+ unload_master("SNMP-VIEW-BASED-ACM-MIB"),
+ unload_master("SNMP-USER-BASED-SM-MIB"),
?IPRINT("loop_mib_3 -> done"),
ok.
@@ -6649,8 +6615,8 @@ loop_mib_3(Config) when is_list(Config) ->
loop_mib_1_test() ->
?IPRINT("loop_mib_1_test -> entry"),
N = loop_it_1([1,1], 0),
- ?IPRINT("found ~w varibles", [N]),
- ?line N = if N < 100 -> 100;
+ ?IPRINT("found ~w variables", [N]),
+ N = if N < 100 -> 100;
true -> N
end.
@@ -6668,7 +6634,7 @@ loop_it_1(Oid, N) ->
"expected intermediate (get-next) result: "
"~n NOid: ~p"
"~n Value: ~p", [NOid, _Value]),
- ?line [_Value2] = get_req(1, [NOid]), % must not be same
+ [_Value2] = get_req(1, [NOid]), % must not be same
?IPRINT("loop_it_1_test -> expected intermediate (get) result: "
"~n Value2: ~p", [_Value2]),
loop_it_1(NOid, N+1);
@@ -6679,7 +6645,7 @@ loop_it_1(Oid, N) ->
varbinds = Vbs} ->
?EPRINT("loop_it_1_test -> unexpected (get-response) vbs: "
"~n Vbs: ~p", [Vbs]),
- ?line ?FAIL({unexpected_vbs,
+ ?FAIL({unexpected_vbs,
[{get_next_oid, Oid},
{counter, N},
{varbinds, Vbs}]});
@@ -6699,7 +6665,7 @@ loop_it_1(Oid, N) ->
"~n Err: ~p"
"~n Idx: ~p"
"~n Vbs: ~p", [Err, Idx, Vbs]),
- ?line ?FAIL({unexpected_pdu,
+ ?FAIL({unexpected_pdu,
[{get_next_oid, Oid},
{counter, N},
{error_status, Err},
@@ -6715,7 +6681,7 @@ loop_it_1(Oid, N) ->
"~n Err: ~p"
"~n Idx: ~p"
"~n Vbs: ~p", [Type, Err, Idx, Vbs]),
- ?line ?FAIL({unexpected_pdu,
+ ?FAIL({unexpected_pdu,
[{get_next_oid, Oid},
{counter, N},
{type, Type},
@@ -6735,7 +6701,7 @@ loop_it_1(Oid, N) ->
(SysEvs =:= []) ->
?EPRINT("loop_it_1_test -> error: "
"~n ~p", [Reason]),
- ?line ?FAIL([{get_next_oid, Oid},
+ ?FAIL([{get_next_oid, Oid},
{counter, N},
{reason, Reason}]);
@@ -6750,12 +6716,12 @@ loop_it_1(Oid, N) ->
end.
-%% Req. As many mibs all possible
+%% Req. As many mibs as possible
loop_mib_2_test() ->
?IPRINT("loop_mib_2_test -> entry"),
N = loop_it_2([1,1], 0),
- ?IPRINT("found ~w varibles", [N]),
- ?line N = if N < 100 -> 100;
+ ?IPRINT("found ~w variables", [N]),
+ N = if N < 100 -> 100;
true -> N
end.
@@ -6781,7 +6747,7 @@ loop_it_2(Oid, N) ->
"expected intermediate (get-next) result: "
"~n NOid: ~p"
"~n Value: ~p", [NOid, _Value]),
- ?line [_Value2] = get_req(1, [NOid]), % must not be same
+ [_Value2] = get_req(1, [NOid]), % must not be same
?IPRINT("loop_it_2 -> expected intermediate (get) result: "
"~n Value2: ~p", [_Value2]),
loop_it_2(NOid, N+1);
@@ -6792,7 +6758,7 @@ loop_it_2(Oid, N) ->
varbinds = Vbs} ->
?EPRINT("loop_it_2 -> unexpected (get-response) vbs: "
"~n Vbs: ~p", [Vbs]),
- ?line ?FAIL({unexpected_vbs,
+ ?FAIL({unexpected_vbs,
[{get_next_oid, Oid},
{counter, N},
{varbinds, Vbs}]});
@@ -6805,7 +6771,7 @@ loop_it_2(Oid, N) ->
"~n ES: ~p"
"~n EI: ~p"
"~n Vbs: ~p", [ES, EI, Vbs]),
- ?line ?FAIL({unexpected_pdu,
+ ?FAIL({unexpected_pdu,
[{get_next_oid, Oid},
{counter, N},
{error_status, ES},
@@ -6821,7 +6787,7 @@ loop_it_2(Oid, N) ->
"~n ES: ~p"
"~n EI: ~p"
"~n Vbs: ~p", [Type, ES, EI, Vbs]),
- ?line ?FAIL({unexpected_pdu,
+ ?FAIL({unexpected_pdu,
[{get_next_oid, Oid},
{counter, N},
{type, Type},
@@ -6839,18 +6805,22 @@ loop_it_2(Oid, N) ->
SysEvs = snmp_test_global_sys_monitor:events(),
if
(SysEvs =:= []) ->
- ?EPRINT("loop_it_2 -> error: "
- "~n ~p", [Reason]),
- ?line ?FAIL([{get_next_oid, Oid},
- {counter, N},
- {reason, Reason}]);
+ ?EPRINT("loop_it_2 -> error *without* system events: "
+ "~n Oid: ~p"
+ "~n N: ~p"
+ "~n Reason: ~p", [Oid, N,Reason]),
+ ?FAIL([{get_next_oid, Oid},
+ {counter, N},
+ {reason, Reason}]);
- true ->
+ true ->
?WPRINT("loop_it_2 -> "
- "error when we got system events: "
+ "error *with* system events: "
+ "~n Oid: ~p"
+ "~n N: ~p"
"~n Reason: ~p"
"~n Sys Events: ~p"
- "~n", [Reason, SysEvs]),
+ "~n", [Oid, N, Reason, SysEvs]),
?SKIP([{reason, Reason}, {system_events, SysEvs}])
end
end.
@@ -6922,15 +6892,14 @@ reported_bugs3_cases() ->
%% Ticket: OTP-1128
%% Slogan: Bug in handling of createAndWait set-requests.
%%-----------------------------------------------------------------
-otp_1128(suite) -> [];
otp_1128(Config) when is_list(Config) ->
?P(otp_1128),
init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(otp_1128_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
+ unload_master("OLD-SNMPEA-MIB"),
ok.
otp_1128_2(X) -> ?P(otp_1128_2), otp_1128(X).
@@ -6945,15 +6914,15 @@ otp_1128_test() ->
NewKeyc5 = [intCommunityStatus,get(mip),is("test")],
s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
- ?line ?expect1([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
+ ?expect1([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]),
g([NewKeyc5]),
- ?line ?expect1([{NewKeyc5, ?notReady}]),
+ ?expect1([{NewKeyc5, ?notReady}]),
s([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
- ?line ?expect1([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
+ ?expect1([{NewKeyc5, ?active}, {NewKeyc3, 2}]),
g([NewKeyc5]),
- ?line ?expect1([{NewKeyc5, ?active}]),
+ ?expect1([{NewKeyc5, ?active}]),
s([{NewKeyc5, ?destroy}]),
- ?line ?expect1([{NewKeyc5, ?destroy}]),
+ ?expect1([{NewKeyc5, ?destroy}]),
ok.
@@ -6961,13 +6930,12 @@ otp_1128_test() ->
%% Ticket: OTP-1129, OTP-1169
%% Slogan: snmpa:int_to_enum crashes on bad oids
%%-----------------------------------------------------------------
-otp_1129(suite) -> [];
otp_1129(Config) when is_list(Config) ->
?P(otp_1129),
init_case(Config),
- ?line load_master("Klas3"),
+ load_master("Klas3"),
try_test(otp_1129_i, [node()]),
- ?line unload_master("Klas3"),
+ unload_master("Klas3"),
ok.
otp_1129_2(X) -> ?P(otp_1129_2), otp_1129(X).
@@ -6986,14 +6954,13 @@ otp_1129_i(MaNode) ->
%% setrequest is of bad type, e.g. an INDEX {INTEGER},
%% and RowIdenx [3,2].
%%-----------------------------------------------------------------
-otp_1131(suite) -> [];
otp_1131(Config) when is_list(Config) ->
?P(otp_1131),
init_case(Config),
- ?line load_master("Klas1"),
+ load_master("Klas1"),
try_test(otp_1131_test),
- ?line unload_master("Klas1").
+ unload_master("Klas1").
otp_1131_2(X) -> ?P(otp_1131_2), otp_1131(X).
@@ -7046,7 +7013,7 @@ otp_1131_test() ->
io:format("Testing bug reported in ticket OTP-1131...~n"),
s([{[friendsEntry, [2, 3, 1]], s, "kompis3"},
{[friendsEntry, [3, 3, 1]], i, ?createAndGo}]),
- ?line ?expect3(?v1_2(noSuchName, noCreation), 2, any),
+ ?expect3(?v1_2(noSuchName, noCreation), 2, any),
ok.
@@ -7054,11 +7021,10 @@ otp_1131_test() ->
%% Ticket: OTP-1162
%% Slogan: snmp_agent can't handle wrongValue from instrum.func
%%-----------------------------------------------------------------
-otp_1162(suite) -> [];
otp_1162(Config) when is_list(Config) ->
?P(otp_1162),
{SaNode, _MgrNode, _MibDir} = init_case(Config),
- ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
+ {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"),
try_test(otp_1162_test),
stop_subagent(SA).
@@ -7068,7 +7034,7 @@ otp_1162_3(X) -> ?P(otp_1162_3), otp_1162(X).
otp_1162_test() ->
s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok)
- ?line ?expect3(?v1_2(badValue, wrongValue), 1, any),
+ ?expect3(?v1_2(badValue, wrongValue), 1, any),
ok.
@@ -7076,15 +7042,14 @@ otp_1162_test() ->
%% Ticket: OTP-1222
%% Slogan: snmp agent crash if faulty index is returned from instrum
%%-----------------------------------------------------------------
-otp_1222(suite) -> [];
otp_1222(Config) when is_list(Config) ->
?P(otp_1222),
init_case(Config),
- ?line load_master("Klas3"),
- ?line load_master("Klas4"),
+ load_master("Klas3"),
+ load_master("Klas4"),
try_test(otp_1222_test),
- ?line unload_master("Klas3"),
- ?line unload_master("Klas4"),
+ unload_master("Klas3"),
+ unload_master("Klas4"),
ok.
otp_1222_2(X) -> ?P(otp_1222_2), otp_1222(X).
@@ -7094,9 +7059,9 @@ otp_1222_3(X) -> ?P(otp_1222_3), otp_1222(X).
otp_1222_test() ->
io:format("Testing bug reported in ticket OTP-1222...~n"),
s([{[fStatus4,1], 4}, {[fName4,1], 1}]),
- ?line ?expect3(genErr, 0, any),
+ ?expect3(genErr, 0, any),
s([{[fStatus4,2], 4}, {[fName4,2], 1}]),
- ?line ?expect3(genErr, 0, any),
+ ?expect3(genErr, 0, any),
ok.
@@ -7104,14 +7069,13 @@ otp_1222_test() ->
%% Ticket: OTP-1298
%% Slogan: Negative INTEGER values are treated as positive.
%%-----------------------------------------------------------------
-otp_1298(suite) -> [];
otp_1298(Config) when is_list(Config) ->
?P(otp_1298),
init_case(Config),
- ?line load_master("Klas2"),
+ load_master("Klas2"),
try_test(otp_1298_test),
- ?line unload_master("Klas2"),
+ unload_master("Klas2"),
ok.
otp_1298_2(X) -> ?P(otp_1298_2), otp_1298(X).
@@ -7121,7 +7085,7 @@ otp_1298_3(X) -> ?P(otp_1298_3), otp_1298(X).
otp_1298_test() ->
io:format("Testing bug reported in ticket OTP-1298...~n"),
s([{[fint,0], -1}]),
- ?line ?expect1([{[fint,0], -1}]),
+ ?expect1([{[fint,0], -1}]),
ok.
@@ -7129,14 +7093,13 @@ otp_1298_test() ->
%% Ticket: OTP-1331
%% Slogan: snmp_generic should return noError when deleting non-ex row
%%-----------------------------------------------------------------
-otp_1331(suite) -> [];
otp_1331(Config) when is_list(Config) ->
?P(otp_1331),
init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(otp_1331_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
+ unload_master("OLD-SNMPEA-MIB"),
ok.
otp_1331_2(X) -> ?P(otp_1331_2), otp_1331(X).
@@ -7146,7 +7109,7 @@ otp_1331_3(X) -> ?P(otp_1331_3), otp_1331(X).
otp_1331_test() ->
NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")],
s([{NewKeyc5, ?destroy}]),
- ?line ?expect1([{NewKeyc5, ?destroy}]),
+ ?expect1([{NewKeyc5, ?destroy}]),
ok.
@@ -7154,14 +7117,13 @@ otp_1331_test() ->
%% Ticket: OTP-1338
%% Slogan: snmp bug in initialisation of default values for mnesia tabs
%%-----------------------------------------------------------------
-otp_1338(suite) -> [];
otp_1338(Config) when is_list(Config) ->
?P(otp_1338),
init_case(Config),
- ?line load_master("Klas2"),
+ load_master("Klas2"),
try_test(otp_1338_test),
- ?line unload_master("Klas2").
+ unload_master("Klas2").
otp_1338_2(X) -> ?P(otp_1338_2), otp_1338(X).
@@ -7169,9 +7131,9 @@ otp_1338_3(X) -> ?P(otp_1338_3), otp_1338(X).
otp_1338_test() ->
s([{[kStatus2, 7], i, ?createAndGo}]),
- ?line ?expect1([{[kStatus2, 7], ?createAndGo}]),
+ ?expect1([{[kStatus2, 7], ?createAndGo}]),
g([[kName2, 7]]),
- ?line ?expect1([{[kName2, 7], "JJJ"}]).
+ ?expect1([{[kName2, 7], "JJJ"}]).
%%-----------------------------------------------------------------
@@ -7179,13 +7141,12 @@ otp_1338_test() ->
%% 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 is_list(Config) ->
?P(otp_1342),
init_case(Config),
- ?line load_master("Klas4"),
+ load_master("Klas4"),
try_test(otp_1342_test),
- ?line unload_master("Klas4"),
+ unload_master("Klas4"),
ok.
otp_1342_2(X) -> ?P(otp_1342_2), otp_1342(X).
@@ -7196,7 +7157,7 @@ otp_1342_test() ->
s([{[fIndex5, 1], i, 1},
{[fName5, 1], i, 3},
{[fStatus5, 1], i, ?createAndGo}]),
- ?line ?expect3(?v1_2(noSuchName, noCreation), 3, any),
+ ?expect3(?v1_2(noSuchName, noCreation), 3, any),
ok.
@@ -7206,14 +7167,13 @@ otp_1342_test() ->
%% 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 is_list(Config) ->
?P(otp_1366),
init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(otp_1366_test),
- ?line unload_master("OLD-SNMPEA-MIB"),
+ unload_master("OLD-SNMPEA-MIB"),
ok.
otp_1366_2(X) -> ?P(otp_1366_2), otp_1366(X).
@@ -7229,7 +7189,6 @@ otp_1366_test() ->
%% Ticket: OTP-2776
%% Slogan: snmp:validate_date_and_time() fails when time is 00:00
%%-----------------------------------------------------------------
-otp_2776(suite) -> [];
otp_2776(Config) when is_list(Config) ->
?P(otp_2776),
init_case(Config),
@@ -7265,7 +7224,7 @@ otp_2776_test() ->
{10, false, Dt10_invalid},
{11, false, Dt11_invalid}],
- ?line ok = validate_dat(L).
+ ok = validate_dat(L).
validate_dat(L) -> validate_dat(L,[]).
@@ -7296,14 +7255,13 @@ validate_dat2(Id, E, Dat) ->
%% Slogan: get-next on more than 1 column in an empty table
%% returns bad response.
%%-----------------------------------------------------------------
-otp_2979(suite) -> [];
otp_2979(Config) when is_list(Config) ->
?P(otp_2979),
init_case(Config),
- ?line load_master("Test1"),
- ?line init_old(),
+ load_master("Test1"),
+ init_old(),
try_test(otp_2979_test),
- ?line unload_master("Test1").
+ unload_master("Test1").
otp_2979_2(X) -> ?P(otp_2979_2), otp_2979(X).
@@ -7311,33 +7269,32 @@ otp_2979_3(X) -> ?P(otp_2979_3), otp_2979(X).
otp_2979_test() ->
gn([[sparseDescr], [sparseStatus]]),
- ?line ?expect1([{[sparseStr,0], "slut"},
+ ?expect1([{[sparseStr,0], "slut"},
{[sparseStr,0], "slut"}]),
ok.
%%-----------------------------------------------------------------
%% Ticket: OTP-3187
-%% Slogan: get-next on vacmAccessTable for colums > 5 returns
+%% Slogan: get-next on vacmAccessTable for columns > 5 returns
%% endOfTable - should return value.
%%-----------------------------------------------------------------
-otp_3187(suite) -> [];
otp_3187(Config) when is_list(Config) ->
?P(otp_3187),
init_case(Config),
- ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
+ load_master_std("SNMP-VIEW-BASED-ACM-MIB"),
otp_3187_test(),
- ?line unload_master("SNMP-VIEW-BASED-ACM-MIB").
+ unload_master("SNMP-VIEW-BASED-ACM-MIB").
otp_3187_2(X) -> ?P(otp_3187_2), otp_3187(X).
otp_3187_3(X) -> ?P(otp_3187_3), otp_3187(X).
otp_3187_test() ->
- ?line Elements =
+ Elements =
snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]),
lists:foreach(fun(E) ->
- ?line if E == endOfTable ->
+ if E == endOfTable ->
?FAIL(endOfTable);
true -> ok
end
@@ -7347,7 +7304,6 @@ otp_3187_test() ->
%% Ticket: OTP-3542
%% Slogan:
%%-----------------------------------------------------------------
-otp_3542(suite) -> [];
otp_3542(Config) when is_list(Config) ->
?P(otp_3542),
init_case(Config),
@@ -7355,7 +7311,7 @@ otp_3542(Config) when is_list(Config) ->
otp_3542_test() ->
io:format("SNMP v3 discovery...~n"),
- ?line Res = snmp_test_mgr:d(),
+ Res = snmp_test_mgr:d(),
io:format("SNMP v3 discovery result: ~p~n",[Res]).
@@ -7363,57 +7319,56 @@ otp_3542_test() ->
%% Ticket: OTP-3725
%% Slogan: Slow response time on snmpa:int_to_enum
%%-----------------------------------------------------------------
-otp_3725(suite) -> [];
otp_3725(Config) when is_list(Config) ->
?P(otp_3725),
init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(otp_3725_test, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
+ 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, snmpa, get_symbolic_store_db, []),
+ rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]),
+ Db = rpc:call(MaNode, snmpa, get_symbolic_store_db, []),
?DBG("otp_3725_test -> Db = ~p", [Db]),
- ?line {value, OID} = rpc:call(MaNode, snmpa, name_to_oid,
+ {value, OID} = rpc:call(MaNode, snmpa, name_to_oid,
[Db, intAgentIpAddress]),
?DBG("otp_3725_test -> name_to_oid for ~p: ~p", [intAgentIpAddress,OID]),
- ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmpa, oid_to_name,
+ {value, intAgentIpAddress} = rpc:call(MaNode, snmpa, oid_to_name,
[Db,OID]),
?DBG("otp_3725_test -> oid_to_name for ~p: ~p", [OID, intAgentIpAddress]),
- ?line false = rpc:call(MaNode, snmpa, name_to_oid, [Db, intAgentIpAddres]),
- ?line false = rpc:call(MaNode, snmpa, oid_to_name,
+ false = rpc:call(MaNode, snmpa, name_to_oid, [Db, intAgentIpAddres]),
+ false = rpc:call(MaNode, snmpa, oid_to_name,
[Db, [1,5,32,3,54,3,3,34,4]]),
- ?line {value, 2} = rpc:call(MaNode, snmpa, enum_to_int,
+ {value, 2} = rpc:call(MaNode, snmpa, enum_to_int,
[Db, intViewType, excluded]),
- ?line {value, excluded} = rpc:call(MaNode, snmpa, int_to_enum,
+ {value, excluded} = rpc:call(MaNode, snmpa, int_to_enum,
[Db, intViewType, 2]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[Db, intViewType, exclude]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[Db, intAgentIpAddress, exclude]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[Db, intAgentIpAddre, exclude]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, [Db, intViewType, 3]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum,
+ false = rpc:call(MaNode, snmpa, int_to_enum, [Db, intViewType, 3]),
+ false = rpc:call(MaNode, snmpa, int_to_enum,
[Db, intAgentIpAddress, 2]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum,
+ false = rpc:call(MaNode, snmpa, int_to_enum,
[Db, intAgentIpAddre, 2]),
- ?line {value, active} = rpc:call(MaNode, snmpa, int_to_enum,
+ {value, active} = rpc:call(MaNode, snmpa, int_to_enum,
[Db, 'RowStatus', ?active]),
- ?line {value, ?destroy} = rpc:call(MaNode, snmpa, enum_to_int,
+ {value, ?destroy} = rpc:call(MaNode, snmpa, enum_to_int,
[Db, 'RowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[Db, 'RowStatus', xxxdestroy]),
- ?line false = rpc:call(MaNode, snmpa, enum_to_int,
+ false = rpc:call(MaNode, snmpa, enum_to_int,
[Db, 'xxRowStatus', destroy]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, [Db, 'RowStatus', 25]),
- ?line false = rpc:call(MaNode, snmpa, int_to_enum, [Db, 'xxRowStatus', 1]),
+ false = rpc:call(MaNode, snmpa, int_to_enum, [Db, 'RowStatus', 25]),
+ false = rpc:call(MaNode, snmpa, int_to_enum, [Db, 'xxRowStatus', 1]),
ok.
@@ -7425,10 +7380,10 @@ otp_3725_test(MaNode) ->
otp_4394_init(Config) when is_list(Config) ->
?DBG("otp_4394_init -> entry with"
"~n Config: ~p", [Config]),
- ?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),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ otp_4394_config(AgentConfDir, MgrDir, Ip),
MasterAgentVerbosity = {master_agent_verbosity, trace},
NetIfVerbosity = {net_if_verbosity, trace},
Opts = [MasterAgentVerbosity, NetIfVerbosity],
@@ -7441,21 +7396,21 @@ otp_4394_config(AgentConfDir, MgrDir, Ip0) ->
"~n Ip0: ~p", [AgentConfDir, MgrDir, Ip0]),
Vsn = [v1],
Ip = tuple_to_list(Ip0),
- ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsn, Ip,
+ snmp_config:write_agent_snmp_files(AgentConfDir, Vsn, Ip,
?TRAP_UDP, Ip, 4000,
"OTP-4394 test"),
- ?line case update_usm(Vsn, AgentConfDir) of
+ case update_usm(Vsn, AgentConfDir) of
true ->
- ?line copy_file(join(AgentConfDir, "usm.conf"),
+ copy_file(join(AgentConfDir, "usm.conf"),
join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsn, MgrDir);
+ update_usm_mgr(Vsn, MgrDir);
false ->
- ?line ok
+ ok
end,
C1 = {"a", "all-rights", "initial", "", "pc"},
C2 = {"c", "secret", "secret_name", "", "secret_tag"},
- ?line write_community_conf(AgentConfDir, [C1, C2]),
- ?line update_vacm(Vsn, AgentConfDir),
+ write_community_conf(AgentConfDir, [C1, C2]),
+ update_vacm(Vsn, AgentConfDir),
Ta1 = {"shelob v1",
[134,138,177,177], 5000, 1500, 3, %% Use Ip and modify
"pc1",
@@ -7469,9 +7424,9 @@ otp_4394_config(AgentConfDir, MgrDir, Ip0) ->
"target_v1", "",
%% [255,255,255,255,0,0],
[], 2048},
- ?line write_target_addr_conf(AgentConfDir, [Ta1, Ta2]),
- ?line write_target_params_conf(AgentConfDir, Vsn),
- ?line write_notify_conf(AgentConfDir),
+ write_target_addr_conf(AgentConfDir, [Ta1, Ta2]),
+ write_target_params_conf(AgentConfDir, Vsn),
+ write_notify_conf(AgentConfDir),
ok.
otp_4394_finish(Config) when is_list(Config) ->
@@ -7481,7 +7436,6 @@ otp_4394_finish(Config) when is_list(Config) ->
erase(mgr_node),
lists:keydelete(vsn, 1, C1).
-otp_4394(suite) -> [];
otp_4394(Config) ->
?P(otp_4394),
?DBG("otp_4394 -> entry", []),
@@ -7519,10 +7473,10 @@ otp_7157_init(Config) when is_list(Config) ->
?DBG("init_otp_7157 -> entry with"
"~n Config: ~p", [Config]),
- ?line AgentConfDir = ?config(agent_conf_dir, Config),
- ?line MgrDir = ?config(mgr_dir, Config),
- ?line Ip = ?config(ip, Config),
- ?line config([v2], MgrDir, AgentConfDir,
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ MgrDir = ?config(mgr_dir, Config),
+ Ip = ?config(ip, Config),
+ config([v2], MgrDir, AgentConfDir,
tuple_to_list(Ip), tuple_to_list(Ip)),
MasterAgentVerbosity = {master_agent_verbosity, trace},
NetIfVerbosity = {net_if_verbosity, trace},
@@ -7537,15 +7491,14 @@ otp_7157_finish(Config) when is_list(Config) ->
erase(mgr_node),
lists:keydelete(vsn, 1, C1).
-otp_7157(suite) -> [];
otp_7157(Config) ->
?P(otp_7157),
?DBG("otp_7157 -> entry", []),
init_case(Config),
MA = whereis(snmp_master_agent),
- ?line load_master("Test1"),
+ load_master("Test1"),
try_test(otp_7157_test, [MA]),
- ?line unload_master("Test1"),
+ unload_master("Test1"),
?DBG("otp_7157 -> done", []),
ok.
@@ -7562,7 +7515,7 @@ otp_7157_test(MA) ->
?DBG("await response",[]),
%% We don't really care about the values, just the vb order.
- ?line ok = ?expect2(v2trap, [{[sysUpTime, 0], any},
+ ok = ?expect2(v2trap, [{[sysUpTime, 0], any},
{[snmpTrapOID, 0], any},
{[sysContact, 0], any},
{[cnt64, 0], any},
@@ -7588,108 +7541,80 @@ otp16092_cases() ->
otp_16092_simple_start_and_stop4 % invalid content
].
-otp_16092_simple_start_and_stop1(suite) -> [];
otp_16092_simple_start_and_stop1(Config) ->
- ?P(otp_16092_simple_start_and_stop1),
- ?DBG("otp_16092_simple_start_and_stop1 -> entry", []),
-
- TC = fun() ->
- otp_16092_simple_start_and_stop(Config, default, success)
- end,
+ otp_16092_simple_start_and_stop(?FUNCTION_NAME,
+ Config, default, success).
- Result = otp_16092_try(TC),
- ?DBG("otp_16092_simple_start_and_stop1 -> done: "
- "~n ~p", [Result]),
-
- Result.
-
-
-otp_16092_simple_start_and_stop2(suite) -> [];
otp_16092_simple_start_and_stop2(Config) ->
- ?P(otp_16092_simple_start_and_stop2),
- ?DBG("otp_16092_simple_start_and_stop2 -> entry", []),
-
- TC = fun() ->
- otp_16092_simple_start_and_stop(Config, [], success)
- end,
+ otp_16092_simple_start_and_stop(?FUNCTION_NAME,
+ Config, [], success).
- Result = otp_16092_try(TC),
- ?DBG("otp_16092_simple_start_and_stop2 -> done: "
- "~n ~p", [Result]),
-
- Result.
-
-
-otp_16092_simple_start_and_stop3(suite) -> [];
otp_16092_simple_start_and_stop3(Config) ->
- ?P(otp_16092_simple_start_and_stop3),
- ?DBG("otp_16092_simple_start_and_stop3 -> entry", []),
-
- TC = fun() ->
- otp_16092_simple_start_and_stop(Config,
- 'this-should-be-ignored',
- success)
- end,
-
- Result = otp_16092_try(TC),
-
- ?DBG("otp_16092_simple_start_and_stop3 -> done: "
- "~n ~p", [Result]),
-
- Result.
+ otp_16092_simple_start_and_stop(?FUNCTION_NAME,
+ Config,
+ 'this-should-be-ignored',
+ success).
-otp_16092_simple_start_and_stop4(suite) -> [];
otp_16092_simple_start_and_stop4(Config) ->
- ?P(otp_16092_simple_start_and_stop4),
- ?DBG("otp_16092_simple_start_and_stop4 -> entry", []),
-
- TC = fun() ->
- otp_16092_simple_start_and_stop(Config,
- ['this-should-fail'],
- failure)
- end,
-
- Result = otp_16092_try(TC),
-
- ?DBG("otp_16092_simple_start_and_stop4 -> done: "
- "~n ", [Result]),
-
- Result.
-
-
-otp_16092_try(TC) ->
- try TC() of
- Any ->
- Any
- catch
- _:{skip, _} = SKIP ->
- SKIP
- end.
-
-otp_16092_simple_start_and_stop(Config, ESO, Expected) ->
- ?line ConfDir = ?config(agent_conf_dir, Config),
- ?line DbDir = ?config(agent_db_dir, Config),
-
- ?NPRINT("try start agent node"),
- {ok, Node} = ?ALIB:start_node(agent_16092),
-
- Vsns = [v1],
- IP = tuple_to_list(?config(ip, Config)),
- ManagerIP = IP,
- TrapPort = ?TRAP_UDP,
- AgentIP = IP,
- AgentPort = 4000,
- SysName = "test",
- ok = snmp_config:write_agent_snmp_files(
- ConfDir, Vsns, ManagerIP, TrapPort, AgentIP, AgentPort, SysName),
-
- ConfOpts = [{dir, ConfDir},
- {force_load, false},
- {verbosity, trace}],
- NiOpts =
+ otp_16092_simple_start_and_stop(?FUNCTION_NAME,
+ Config,
+ ['this-should-fail'],
+ failure).
+
+otp_16092_simple_start_and_stop(CaseName, Config, ESO, Expected)
+ when is_atom(CaseName) ->
+ Pre = fun() ->
+ [D|_] = lists:reverse(atom_to_list(CaseName)),
+ Digit = [D],
+
+ ?NPRINT("try start agent node"),
+ {ok, Peer, Node} = ?START_PEER(Digit ++ "-agent"),
+
+ ?NPRINT("try write config to file"),
+ ConfDir = ?config(agent_conf_dir, Config),
+ DbDir = ?config(agent_db_dir, Config),
+ Vsns = [v1],
+ IP = tuple_to_list(?config(ip, Config)),
+ ManagerIP = IP,
+ TrapPort = ?TRAP_UDP,
+ AgentIP = IP,
+ AgentPort = 4000,
+ SysName = "test",
+ ok = snmp_config:write_agent_snmp_files(ConfDir, Vsns,
+ ManagerIP, TrapPort,
+ AgentIP, AgentPort,
+ SysName),
+
+ #{eso => ESO,
+ vsns => Vsns,
+ db_dir => DbDir,
+ conf_opts => [{dir, ConfDir},
+ {force_load, false},
+ {verbosity, trace}],
+ node => Node,
+ peer => Peer,
+ expected => Expected}
+ end,
+ Case = fun(State) ->
+ do_otp_16092_simple_start_and_stop(State)
+ end,
+ Post = fun(#{node := Node,
+ peer := Peer}) ->
+ ?NPRINT("try stop agent node ~p", [Node]),
+ ?STOP_PEER(Peer)
+ end,
+ ?TC_TRY(CaseName, Pre, Case, Post).
+
+do_otp_16092_simple_start_and_stop(#{eso := ESO,
+ vsns := Vsns,
+ db_dir := DbDir,
+ conf_opts := ConfOpts,
+ node := Node,
+ expected := Expected} = _State) ->
+ NiOpts =
case ESO of
default ->
[{verbosity, trace}];
@@ -7705,15 +7630,9 @@ otp_16092_simple_start_and_stop(Config, ESO, Expected) ->
otp16092_try_start_and_stop_agent(Node, Opts, Expected),
- ?NPRINT("try stop agent node ~p", [Node]),
- ?ALIB:stop_node(Node),
-
- ?SLEEP(1000),
-
?NPRINT("done"),
ok.
-
otp16092_try_start_and_stop_agent(Node, Opts, Expected) ->
?IPRINT("try start snmp (agent) supervisor (on ~p) - expect ~p",
[Node, Expected]),
@@ -7794,9 +7713,8 @@ otp8395({init, Config}) when is_list(Config) ->
%% --
%% Start nodes
%%
- FName = ?FUNCTION_NAME,
- {ok, AgentNode} = start_node(mk_node_name(FName, agent)),
- {ok, ManagerNode} = start_node(mk_node_name(FName, manager)),
+ {ok, AgentPeer, AgentNode} = ?START_PEER("-agent"),
+ {ok, ManagerPeer, ManagerNode} = ?START_PEER("-manager"),
%% --
%% Mnesia init
@@ -7846,12 +7764,14 @@ otp8395({init, Config}) when is_list(Config) ->
Config2 = start_agent([{host, Host},
{ip, Ip},
{ipfamily, IpFamily},
+ {agent_peer, AgentPeer},
{agent_node, AgentNode},
{agent_host, AgentHost},
{agent_ip, AgentIP},
%% {sub_agent_node, SubAgentNode},
%% {sub_agent_host, SubAgentHost},
- %% {sub_agent_ip, SubAgentIP},
+ %% {sub_agent_ip, SubAgentIP},
+ {manager_peer, ManagerPeer},
{manager_node, ManagerNode},
{manager_host, ManagerHost},
{manager_ip, ManagerIP}|Config]),
@@ -7867,7 +7787,6 @@ otp8395({fin, Config}) when is_list(Config) ->
"~n Config: ~p", [Config]),
AgentNode = ?config(agent_node, Config),
- ManagerNode = ?config(manager_node, Config),
%% -
%% Stop agent (this is the nice way to do it,
@@ -7890,14 +7809,14 @@ otp8395({fin, Config}) when is_list(Config) ->
%%
?DBG("otp8395(fin) -> stop agent node", []),
- stop_node(AgentNode),
+ ?STOP_PEER(?config(agent_peer, Config)),
%% -
%% Stop the manager node
%%
?DBG("otp8395(fin) -> stop manager node", []),
- stop_node(ManagerNode),
+ ?STOP_PEER(?config(manager_peer, Config)),
wd_stop(Config);
@@ -8156,7 +8075,7 @@ otp16649(N, Config) ->
AgentNode = ?config(agent_node, Config),
ManagerNode = ?config(manager_node, Config),
- ?line AInfo = rpc:call(AgentNode, snmpa, info, []),
+ AInfo = rpc:call(AgentNode, snmpa, info, []),
?IPRINT("Agent Info: "
"~n ~p", [AInfo]),
@@ -8189,25 +8108,25 @@ otp16649(N, Config) ->
AgentTrapPortNo = otp16649_which_trap_port_no(TIs),
?IPRINT("(mgr) register user"),
- ?line ok = otp16649_mgr_reg_user(ManagerNode),
+ ok = otp16649_mgr_reg_user(ManagerNode),
?IPRINT("(mgr) register agent"),
TargetBase = "otp16649-agent-",
ReqTarget = TargetBase ++ "req",
TrapTarget = TargetBase ++ "trap",
- ?line ok = otp16649_mgr_reg_agent(ManagerNode,
+ ok = otp16649_mgr_reg_agent(ManagerNode,
?config(ipfamily, Config),
?config(tdomain, Config),
ReqTarget, AgentReqPortNo),
- ?line ok = otp16649_mgr_reg_agent(ManagerNode,
+ ok = otp16649_mgr_reg_agent(ManagerNode,
?config(ipfamily, Config),
?config(tdomain, Config),
TrapTarget, AgentTrapPortNo),
?IPRINT("(mgr) simple (sync) get request"),
Oids = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance],
- ?line ok = case otp16649_mgr_get_req(ManagerNode, Oids) of
+ ok = case otp16649_mgr_get_req(ManagerNode, Oids) of
{ok, {noError, 0, ReplyOids}, _} ->
?IPRINT("(mgr) simple (sync) successful reply: "
"~n ~p", [ReplyOids]),
@@ -8224,10 +8143,10 @@ otp16649(N, Config) ->
?IPRINT("load TestTrap..."),
MibDir = ?config(mib_dir, Config),
- ?line ok = otp16649_agent_load_mib(AgentNode, MibDir, "TestTrap"),
+ ok = otp16649_agent_load_mib(AgentNode, MibDir, "TestTrap"),
?IPRINT("(agent) send trap (testTrap2)"),
- ?line ok = otp16649_agent_send_trap(AgentNode, testTrap2),
+ ok = otp16649_agent_send_trap(AgentNode, testTrap2),
TDomain = ?config(tdomain, Config),
@@ -8245,7 +8164,7 @@ otp16649(N, Config) ->
case TDomain of
transportDomainUdpIpv4 ->
?IPRINT("TIMEOUT"),
- ?line exit(timeout);
+ exit(timeout);
transportDomainUdpIpv6 ->
?IPRINT("expected timeout - "
"v1 trap's can only be sent on IPv4 domains"),
@@ -8255,10 +8174,10 @@ otp16649(N, Config) ->
?IPRINT("load TestTrapv2..."),
- ?line ok = otp16649_agent_load_mib(AgentNode, MibDir, "TestTrapv2"),
+ ok = otp16649_agent_load_mib(AgentNode, MibDir, "TestTrapv2"),
?IPRINT("(agent) send trap (testTrapv22)"),
- ?line ok = otp16649_agent_send_trap(AgentNode, testTrapv22),
+ ok = otp16649_agent_send_trap(AgentNode, testTrapv22),
receive
{handle_trap, From_v2, TrapTarget,
@@ -8270,7 +8189,7 @@ otp16649(N, Config) ->
after 5000 ->
?IPRINT("TIMEOUT"),
- ?line exit(timeout)
+ exit(timeout)
end,
?IPRINT("done"),
@@ -8287,10 +8206,8 @@ otp16649_init(N, AgentPreTransports, Config) ->
%% Start nodes
%%
- ?IPRINT("start (agent and mansger) nodes"),
-
- {ok, AgentNode} = start_node(otp16649_mk_name(N, agent)),
- {ok, ManagerNode} = start_node(otp16649_mk_name(N, manager)),
+ {ok, AgentPeer, AgentNode} = ?START_PEER("-agent"),
+ {ok, ManagerPeer, ManagerNode} = ?START_PEER("-manager"),
%% --
%% Misc
@@ -8340,16 +8257,18 @@ otp16649_init(N, AgentPreTransports, Config) ->
AgentPreTransports2 = [F(T) || T <- AgentPreTransports],
?IPRINT("write agent config files"),
- ?line ok = snmp_config:write_agent_snmp_files(
+ ok = snmp_config:write_agent_snmp_files(
AgentConfDir, Vsns,
TransportDomain, {ManagerIP, ?MGR_PORT}, AgentPreTransports2,
"test"),
?IPRINT("start agent"),
Config2 = start_agent([{host, Host},
+ {agent_peer, AgentPeer},
{agent_node, AgentNode},
{agent_host, AgentHost},
{agent_ip, AgentIP},
+ {manager_peer, ManagerPeer},
{manager_node, ManagerNode},
{manager_host, ManagerHost},
{manager_ip, ManagerIP}|Config]),
@@ -8364,15 +8283,15 @@ otp16649_init(N, AgentPreTransports, Config) ->
MgrTopDir = ?config(manager_top_dir, Config),
MgrDbDir = filename:join(MgrTopDir, "db/"),
MgrConfDir = filename:join(MgrTopDir, "conf/"),
- ?line ok = file:make_dir(MgrConfDir),
+ ok = file:make_dir(MgrConfDir),
MgrDbDir = filename:join(MgrTopDir, "db/"),
- ?line ok = file:make_dir(MgrDbDir),
+ ok = file:make_dir(MgrDbDir),
MgrLogDir = filename:join(MgrTopDir, "log/"),
- ?line ok = file:make_dir(MgrLogDir),
+ ok = file:make_dir(MgrLogDir),
?IPRINT("write manager config files"),
MgrTransports = [{TransportDomain, {ManagerIP0, ?MGR_PORT}}],
- ?line ok = snmp_config:write_manager_snmp_files(
+ ok = snmp_config:write_manager_snmp_files(
MgrConfDir,
MgrTransports,
?MGR_MMS, ?MGR_ENGINE_ID),
@@ -8382,19 +8301,12 @@ otp16649_init(N, AgentPreTransports, Config) ->
{manager_log_dir, MgrLogDir} | Config2],
?IPRINT("start manager"),
- ?line ok = start_manager(Config3),
+ ok = start_manager(Config3),
?DBG("otp16649_init -> done when"
"~n Config2: ~p", [Config3]),
[{agent_raw_transports, AgentPreTransports} | Config3].
-mk_node_name(FName, Post) when is_atom(FName) andalso is_atom(Post) ->
- list_to_atom(?F("~w_~w", [FName, Post])).
-
-otp16649_mk_name(N, Post) when is_integer(N) andalso is_atom(Post) ->
- mk_node_name(otp16649, list_to_atom(?F("~w_~w", [N, Post]))).
-%% list_to_atom(?F("otp16649_~w_~w", [N, Post])).
-
otp16649_fin(N, Config) when is_integer(N) ->
?IPRINT("otp16649_fin -> entry with"
@@ -8402,14 +8314,13 @@ otp16649_fin(N, Config) when is_integer(N) ->
"~n Config: ~p", [N, Config]),
ManagerNode = ?config(manager_node, Config),
- AgentNode = ?config(agent_node, Config),
%% -
%% Stop agent (this is the nice way to do it,
%% so logs and files can be closed in the proper way).
%%
- ?line AgentTopSup = ?config(agent_sup, Config),
+ AgentTopSup = ?config(agent_sup, Config),
stop_standalone_agent(AgentTopSup),
@@ -8425,7 +8336,7 @@ otp16649_fin(N, Config) when is_integer(N) ->
%%
?DBG("otp16649_fin -> stop manager node", []),
- stop_node(ManagerNode),
+ peer:stop(?config(manager_peer, Config)),
%%
@@ -8433,7 +8344,7 @@ otp16649_fin(N, Config) when is_integer(N) ->
%%
?DBG("otp16649_fin -> stop agent node", []),
- stop_node(AgentNode),
+ peer:stop(?config(agent_peer, Config)),
?DBG("otp16649_fin -> done", []),
Config1 = lists:keydelete(manager_node, 1, Config),
@@ -8624,7 +8535,7 @@ start_agent(Config, Opts) ->
process_flag(trap_exit, true),
- ?line {ok, AgentTopSup} = start_standalone_agent(AgentNode, AgentConfig),
+ {ok, AgentTopSup} = start_standalone_agent(AgentNode, AgentConfig),
[{agent_sup, AgentTopSup} | Config].
@@ -8719,7 +8630,7 @@ start_manager(Config) ->
{net_if, [{verbosity, trace}]},
{note_store, [{verbosity, trace}]},
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
- ?line ok = start_standalone_manager(Node, Opts).
+ ok = start_standalone_manager(Node, Opts).
start_standalone_manager(Node, Config) ->
@@ -8756,18 +8667,17 @@ nkill(Pid, Reason, N) when N > 0 ->
%% Slogan: info test
%%-----------------------------------------------------------------
-info_test(suite) -> [];
info_test(Config) when is_list(Config) ->
?P(info_test),
init_case(Config),
- ?line load_master("OLD-SNMPEA-MIB"),
- ?line init_old(),
+ load_master("OLD-SNMPEA-MIB"),
+ init_old(),
try_test(do_info, [node()]),
- ?line unload_master("OLD-SNMPEA-MIB").
+ unload_master("OLD-SNMPEA-MIB").
do_info(MaNode) ->
- ?line Info = rpc:call(MaNode, snmpa, info, []),
+ Info = rpc:call(MaNode, snmpa, info, []),
?DBG("info_test1 -> Info: ~n~p", [Info]),
Keys = [vsns,
stats_counters,
@@ -8854,15 +8764,6 @@ get_next_req(Vars) ->
?ALIB:get_next_req(Vars).
-start_node(Name) ->
- ?ALIB:start_node(Name).
-
-stop_node(undefined) ->
- ok;
-stop_node(Node) ->
- ?ALIB:stop_node(Node).
-
-
%%%-----------------------------------------------------------------
%%% Configuration
%%%-----------------------------------------------------------------
@@ -9075,14 +8976,12 @@ lists_key1search(Key, List) when is_atom(Key) ->
init_v1_agent(Config) ->
%% --
%% Start nodes
- %%
-
- FName = ?config(fname, Config),
- {ok, AgentNode} = start_node(mk_node_name(FName, agent)),
+ %%
+ {ok, AgentPeer, AgentNode} = ?START_PEER("-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(mk_node_name(FName, manager)),
+ {ok, ManagerPeer, ManagerNode} = ?START_PEER("-manager"),
%% --
%% Mnesia init
@@ -9134,6 +9033,7 @@ init_v1_agent(Config) ->
Config2 = start_agent([{host, Host},
{ip, Ip},
+ {agent_peer, AgentPeer},
{agent_node, AgentNode},
{agent_host, AgentHost},
{agent_ip, AgentIP},
@@ -9141,6 +9041,7 @@ init_v1_agent(Config) ->
%% We need this here since without it
%% fin_v1_agent will not be able to stop!
+ {manager_peer, ManagerPeer},
{manager_node, ManagerNode}|Config]),
%% --
@@ -9151,7 +9052,6 @@ init_v1_agent(Config) ->
fin_v1_agent(Config) ->
AgentNode = ?config(agent_node, Config),
- ManagerNode = ?config(manager_node, Config),
%% -
%% Stop agent (this is the nice way to do it,
@@ -9170,7 +9070,7 @@ fin_v1_agent(Config) ->
%% -
%% Stop the agent node
%%
- stop_node(AgentNode),
+ peer:stop(?config(agent_peer, Config)),
%% SubAgentNode = ?config(sub_agent_node, Config),
@@ -9180,7 +9080,7 @@ fin_v1_agent(Config) ->
%% -
%% Stop the manager node
%%
- stop_node(ManagerNode),
+ peer:stop(?config(manager_peer, Config)),
wd_stop(Config).
diff --git a/lib/snmp/test/snmp_agent_mibs_SUITE.erl b/lib/snmp/test/snmp_agent_mibs_SUITE.erl
index f4130aed65..3fc9f55371 100644
--- a/lib/snmp/test/snmp_agent_mibs_SUITE.erl
+++ b/lib/snmp/test/snmp_agent_mibs_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -163,7 +163,7 @@ init_per_testcase(Case, Config0) when is_list(Config0) ->
Config1 = ?LIB:fix_data_dir(Config0),
CaseTopDir = ?LIB:init_testcase_top_dir(Case, Config1),
DbDir = join(CaseTopDir, "db_dir/"),
- ?line ok = file:make_dir(DbDir),
+ ok = file:make_dir(DbDir),
init_per_testcase2(Case, [{db_dir, DbDir},
{case_top_dir, CaseTopDir} | Config1]).
@@ -215,7 +215,6 @@ end_per_testcase1(_Case, Config) when is_list(Config) ->
%% Test functions
%%======================================================================
-start_and_stop(suite) -> [];
start_and_stop(Config) when is_list(Config) ->
tc_try(start_and_start,
fun() -> do_start_and_stop(Config) end).
@@ -224,20 +223,19 @@ do_start_and_stop(_Config) ->
Prio = normal,
Verbosity = trace,
- ?line sym_start(Prio, Verbosity),
- ?line MibsPid = mibs_start(Prio, Verbosity),
+ sym_start(Prio, Verbosity),
+ MibsPid = mibs_start(Prio, Verbosity),
- ?line mibs_info(MibsPid),
+ mibs_info(MibsPid),
- ?line mibs_stop(MibsPid),
- ?line sym_stop(),
+ mibs_stop(MibsPid),
+ sym_stop(),
ok.
%% ---------------------------------------------------------------------
-load_unload(suite) -> [];
load_unload(Config) when is_list(Config) ->
tc_try(load_unload,
fun() -> do_load_unload(Config) end).
@@ -250,44 +248,44 @@ do_load_unload(Config) ->
MibDir = ?config(data_dir, Config),
?DBG("load_unload -> start symbolic store", []),
- ?line sym_start(Prio, Verbosity),
+ sym_start(Prio, Verbosity),
?DBG("load_unload -> start mib server", []),
- ?line MibsPid = mibs_start(Prio, Verbosity),
+ MibsPid = mibs_start(Prio, Verbosity),
?DBG("load_unload -> load one not already loaded mib", []),
- ?line ok = verify_loaded_mibs(MibsPid, MibDir, []),
- ?line ok = load_mibs(MibsPid, MibDir, ["Test2"]),
- ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["Test2"]),
+ ok = verify_loaded_mibs(MibsPid, MibDir, []),
+ ok = load_mibs(MibsPid, MibDir, ["Test2"]),
+ ok = verify_loaded_mibs(MibsPid, MibDir, ["Test2"]),
?DBG("load_unload -> try load one *already loaded* mib", []),
EMib = join(MibDir, "Test2"),
- ?line {error, {'load aborted at', EMib, already_loaded}} =
+ {error, {'load aborted at', EMib, already_loaded}} =
load_mibs(MibsPid, MibDir, ["Test2"]),
?DBG("load_unload -> load 2 not already loaded mibs", []),
- ?line ok = load_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
- ?line ok = verify_loaded_mibs(MibsPid, MibDir,
+ ok = load_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
+ ok = verify_loaded_mibs(MibsPid, MibDir,
["Test2", "TestTrap", "TestTrapv2"]),
?DBG("load_unload -> unload one loaded mib", []),
- ?line ok = unload_mibs(MibsPid, ["Test2"]),
- ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
+ ok = unload_mibs(MibsPid, ["Test2"]),
+ ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]),
?DBG("load_unload -> try unload two loaded mibs and one not loaded", []),
- ?line {error, {'unload aborted at', "Test2", not_loaded}} =
+ {error, {'unload aborted at', "Test2", not_loaded}} =
unload_mibs(MibsPid, ["TestTrap","Test2","TestTrapv2"]),
- ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrapv2"]),
+ ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrapv2"]),
?DBG("load_unload -> unload the remaining loaded mib", []),
- ?line ok = unload_mibs(MibsPid, ["TestTrapv2"]),
- ?line ok = verify_loaded_mibs(MibsPid, MibDir, []),
+ ok = unload_mibs(MibsPid, ["TestTrapv2"]),
+ ok = verify_loaded_mibs(MibsPid, MibDir, []),
?DBG("load_unload -> stop mib server", []),
- ?line mibs_stop(MibsPid),
+ mibs_stop(MibsPid),
?DBG("load_unload -> stop symbolic store", []),
- ?line sym_stop(),
+ sym_stop(),
?DBG("load_unload -> done", []),
ok.
@@ -296,15 +294,11 @@ do_load_unload(Config) ->
%% ---------------------------------------------------------------------
-size_check_ets1(suite) ->
- [];
size_check_ets1(Config) when is_list(Config) ->
MibStorage = [{module, snmpa_mib_storage_ets}],
do_size_check(size_check_ets1,
[{mib_storage, MibStorage}|Config]).
-size_check_ets2(suite) ->
- [];
size_check_ets2(Config) when is_list(Config) ->
Dir = ?config(db_dir, Config),
MibStorage = [{module, snmpa_mib_storage_ets},
@@ -312,8 +306,6 @@ size_check_ets2(Config) when is_list(Config) ->
do_size_check(size_check_ets2,
[{mib_storage, MibStorage}|Config]).
-size_check_ets2_bad_file1(suite) ->
- [];
size_check_ets2_bad_file1(Config) when is_list(Config) ->
Dir = ?config(db_dir, Config),
%% Ensure that the bad file does not cause any problems (action = clear)
@@ -323,8 +315,6 @@ size_check_ets2_bad_file1(Config) when is_list(Config) ->
do_size_check(size_check_ets2_bad_file1,
[{mib_storage, MibStorage}|Config]).
-size_check_ets3(suite) ->
- [];
size_check_ets3(Config) when is_list(Config) ->
Dir = ?config(db_dir, Config),
MibStorage = [{module, snmpa_mib_storage_ets},
@@ -333,8 +323,6 @@ size_check_ets3(Config) when is_list(Config) ->
do_size_check(size_check_ets3,
[{mib_storage, MibStorage}|Config]).
-size_check_ets3_bad_file1(suite) ->
- [];
size_check_ets3_bad_file1(Config) when is_list(Config) ->
Dir = ?config(db_dir, Config),
%% Ensure that the bad file does not cause any problems (action = clear)
@@ -345,8 +333,6 @@ size_check_ets3_bad_file1(Config) when is_list(Config) ->
do_size_check(size_check_ets3_bad_file1,
[{mib_storage, MibStorage}|Config]).
-size_check_dets(suite) ->
- [];
size_check_dets(Config) when is_list(Config) ->
Dir = ?config(db_dir, Config),
MibStorage = [{module, snmpa_mib_storage_dets},
@@ -354,8 +340,6 @@ size_check_dets(Config) when is_list(Config) ->
do_size_check(size_check_dets,
[{mib_storage, MibStorage}|Config]).
-size_check_mnesia(suite) ->
- [];
size_check_mnesia(Config) when is_list(Config) ->
MibStorage = [{module, snmpa_mib_storage_mnesia},
{options, [{nodes, []}]}],
@@ -385,9 +369,9 @@ do_size_check(Config) ->
StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/",
?IPRINT("do_size_check -> start symbolic store", []),
- ?line sym_start(Prio, MibStorage, Verbosity),
+ sym_start(Prio, MibStorage, Verbosity),
?IPRINT("do_size_check -> start mib server", []),
- ?line MibsPid = mibs_start(Prio, MibStorage, Verbosity),
+ MibsPid = mibs_start(Prio, MibStorage, Verbosity),
Mibs = ["Test2", "TestTrap", "TestTrapv2"],
StdMibs = ["OTP-SNMPEA-MIB",
@@ -403,23 +387,23 @@ do_size_check(Config) ->
"SNMPv2-TM"],
?IPRINT("do_size_check -> load std mibs", []),
- ?line load_mibs(MibsPid, StdMibDir, StdMibs),
+ load_mibs(MibsPid, StdMibDir, StdMibs),
?IPRINT("do_size_check -> load (own) mibs", []),
- ?line load_mibs(MibsPid, MibDir, Mibs),
+ load_mibs(MibsPid, MibDir, Mibs),
?SLEEP(2000),
?IPRINT("do_size_check -> display mem usage", []),
- ?line display_memory_usage(MibsPid),
+ display_memory_usage(MibsPid),
?IPRINT("do_size_check -> unload (own) mibs", []),
- ?line unload_mibs(MibsPid, Mibs),
+ unload_mibs(MibsPid, Mibs),
?IPRINT("do_size_check -> unload std mibs", []),
- ?line unload_mibs(MibsPid, StdMibs),
+ unload_mibs(MibsPid, StdMibs),
?IPRINT("do_size_check -> stop mib server", []),
- ?line mibs_stop(MibsPid),
+ mibs_stop(MibsPid),
?IPRINT("do_size_check -> stop symbolic store", []),
- ?line sym_stop(),
+ sym_stop(),
?IPRINT("do_size_check -> done", []),
ok.
@@ -427,7 +411,6 @@ do_size_check(Config) ->
%% ---------------------------------------------------------------------
-me_lookup(suite) -> [];
me_lookup(Config) when is_list(Config) ->
tc_try(me_lookup,
fun() -> do_me_lookup(Config) end).
@@ -451,40 +434,39 @@ do_me_lookup(Config) ->
"SNMPv2-TM"],
?DBG("me_lookup -> start symbolic store", []),
- ?line sym_start(Prio, Verbosity),
+ sym_start(Prio, Verbosity),
?DBG("me_lookup -> start mib server", []),
- ?line MibsPid = mibs_start(Prio, Verbosity),
+ MibsPid = mibs_start(Prio, Verbosity),
?DBG("me_lookup -> load mibs", []),
- ?line load_mibs(MibsPid, MibDir, Mibs),
+ load_mibs(MibsPid, MibDir, Mibs),
?DBG("me_lookup -> load std mibs", []),
- ?line load_mibs(MibsPid, StdMibDir, StdMibs),
+ load_mibs(MibsPid, StdMibDir, StdMibs),
?DBG("me_lookup -> find ~w from SNMP-COMMUNITY-MIB",
[?snmpTrapCommunity_instance]),
- ?line ok = me_lookup(MibsPid, ?snmpTrapCommunity_instance),
+ ok = me_lookup(MibsPid, ?snmpTrapCommunity_instance),
?DBG("me_lookup -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
[?vacmViewSpinLock_instance]),
- ?line ok = me_lookup(MibsPid, ?vacmViewSpinLock_instance),
+ ok = me_lookup(MibsPid, ?vacmViewSpinLock_instance),
?DBG("me_lookup -> find ~w from SNMP-USER-BASED-SM-MIB",
[?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = me_lookup(MibsPid, ?usmStatsNotInTimeWindows_instance),
+ {error, _} = me_lookup(MibsPid, ?usmStatsNotInTimeWindows_instance),
?DBG("me_lookup -> stop mib server", []),
- ?line mibs_stop(MibsPid),
+ mibs_stop(MibsPid),
?DBG("me_lookup -> stop symbolic store", []),
- ?line sym_stop(),
+ sym_stop(),
ok.
%% ---------------------------------------------------------------------
-which_mib(suite) -> [];
which_mib(Config) when is_list(Config) ->
tc_try(which_mib,
fun() -> do_which_mib(Config) end).
@@ -508,43 +490,42 @@ do_which_mib(Config) ->
"SNMPv2-TM"],
?DBG("which_mib -> start symbolic store", []),
- ?line sym_start(Prio, Verbosity),
+ sym_start(Prio, Verbosity),
?DBG("which_mib -> start mib server", []),
- ?line MibsPid = mibs_start(Prio, Verbosity),
+ MibsPid = mibs_start(Prio, Verbosity),
?DBG("which_mib -> load mibs", []),
- ?line load_mibs(MibsPid, MibDir, Mibs),
+ load_mibs(MibsPid, MibDir, Mibs),
?DBG("which_mib -> load std mibs", []),
- ?line load_mibs(MibsPid, StdMibDir, StdMibs),
+ load_mibs(MibsPid, StdMibDir, StdMibs),
?DBG("which_mib -> find ~w from SNMP-COMMUNITY-MIB",
[?snmpTrapCommunity_instance]),
- ?line ok = which_mib(MibsPid, ?snmpTrapCommunity_instance,
+ ok = which_mib(MibsPid, ?snmpTrapCommunity_instance,
"SNMP-COMMUNITY-MIB"),
?DBG("which_mib -> find ~w from SNMP-VIEW-BASED-ACM-MIB",
[?vacmViewSpinLock_instance]),
- ?line ok = which_mib(MibsPid, ?vacmViewSpinLock_instance,
+ ok = which_mib(MibsPid, ?vacmViewSpinLock_instance,
"SNMP-VIEW-BASED-ACM-MIB"),
?DBG("which_mib -> find ~w from SNMP-USER-BASED-SM-MIB (not loaded)",
[?usmStatsNotInTimeWindows_instance]),
- ?line {error, _} = which_mib(MibsPid, ?usmStatsNotInTimeWindows_instance,
+ {error, _} = which_mib(MibsPid, ?usmStatsNotInTimeWindows_instance,
"SNMP-USER-BASED-SM-MIB"),
?DBG("which_mib -> stop mib server", []),
- ?line mibs_stop(MibsPid),
+ mibs_stop(MibsPid),
?DBG("which_mib -> stop symbolic store", []),
- ?line sym_stop(),
+ sym_stop(),
ok.
%% ---------------------------------------------------------------------
-cache_test(suite) -> [];
cache_test(Config) when is_list(Config) ->
tc_try(cache_test,
fun() -> do_cache_test(Config) end).
@@ -571,7 +552,7 @@ do_cache_test(Config) ->
"SNMPv2-TM"],
?IPRINT("cache_test -> start symbolic store"),
- ?line sym_start(Prio, MibStorage, silence), % Verbosity),
+ sym_start(Prio, MibStorage, silence), % Verbosity),
?IPRINT("cache_test -> start mib server"),
GcLimit = 3,
@@ -580,25 +561,25 @@ do_cache_test(Config) ->
{age, Age},
{gclimit, GcLimit},
{gcverbose, true}],
- ?line MibsPid = mibs_start(Prio, MibStorage, [], Verbosity, CacheOpts),
+ MibsPid = mibs_start(Prio, MibStorage, [], Verbosity, CacheOpts),
?NPRINT("Info before load mibs: "
"~n ~p", [snmpa_mib:info(MibsPid)]),
?IPRINT("cache_test -> load mibs"),
- ?line load_mibs(MibsPid, MibDir, Mibs),
+ load_mibs(MibsPid, MibDir, Mibs),
?NPRINT("Info before load std mibs: "
"~n ~p", [snmpa_mib:info(MibsPid)]),
?IPRINT("cache_test -> load std mibs"),
- ?line load_mibs(MibsPid, StdMibDir, StdMibs),
+ load_mibs(MibsPid, StdMibDir, StdMibs),
?NPRINT("Info (after mibs load but) before populate: "
"~n ~p", [snmpa_mib:info(MibsPid)]),
?IPRINT("cache_test -> populate the cache"),
- ?line ok = populate(MibsPid),
+ ok = populate(MibsPid),
?NPRINT("Info after populate: "
"~n ~p", [snmpa_mib:info(MibsPid)]),
@@ -625,10 +606,10 @@ do_cache_test(Config) ->
?IPRINT("cache_test -> subscribe to GC events"),
- ?line ok = snmpa_mib:subscribe_gc_events(MibsPid),
+ ok = snmpa_mib:subscribe_gc_events(MibsPid),
?IPRINT("cache_test -> enable cache autogc"),
- ?line ok = snmpa_mib:enable_cache_autogc(MibsPid),
+ ok = snmpa_mib:enable_cache_autogc(MibsPid),
?IPRINT("cache_test -> wait 65 seconds to allow gc to happen"),
?SLEEP(timer:seconds(65)),
@@ -738,10 +719,10 @@ do_cache_test(Config) ->
?IPRINT("cache_test -> stop mib server"),
- ?line mibs_stop(MibsPid),
+ mibs_stop(MibsPid),
?IPRINT("cache_test -> stop symbolic store"),
- ?line sym_stop(),
+ sym_stop(),
?IPRINT("cache_test -> end"),
ok.
@@ -873,13 +854,13 @@ mnesia_start(Opts) ->
mnesia_start(Opts, [node()]).
mnesia_start(Opts, Nodes) ->
- %% We can accept mnesia beeing loaded but *not* started.
+ %% We can accept mnesia being loaded but *not* started.
%% If its started it *may* contain data that will invalidate
%% this test case.
?IPRINT("mnesia_start -> try load mnesia when:"
"~n Loaded: ~p"
"~n Running: ~p", [apps_loaded(), apps_running()]),
- ?line ok = case application:load(mnesia) of
+ ok = case application:load(mnesia) of
ok ->
ok;
{error, {already_loaded, mnesia}} ->
@@ -890,11 +871,11 @@ mnesia_start(Opts, Nodes) ->
F = fun({Key, Val}) ->
?IPRINT("mnesia_start -> try set mnesia env: "
"~n ~p -> ~p", [Key, Val]),
- ?line application_controller:set_env(mnesia, Key, Val)
+ application_controller:set_env(mnesia, Key, Val)
end,
lists:foreach(F, Opts),
?IPRINT("mnesia_start -> create mnesia schema on ~p", [Nodes]),
- ?line case mnesia:create_schema(Nodes) of
+ case mnesia:create_schema(Nodes) of
ok ->
ok;
{error, {_, {already_exist, _}}} ->
@@ -904,7 +885,7 @@ mnesia_start(Opts, Nodes) ->
?F("Failed create mnesia schema: ~p", [SchemaReason])})
end,
?IPRINT("mnesia_start -> start mnesia", []),
- ?line case application:start(mnesia) of
+ case application:start(mnesia) of
ok ->
ok;
{error, {already_started, mnesia}} ->
@@ -988,13 +969,13 @@ mibs_info(Pid) ->
load_mibs(Pid, Dir, Mibs0) ->
Mibs = [join(Dir, Mib) || Mib <- Mibs0],
- Res = snmpa_mib:load_mibs(Pid, Mibs),
+ Res = snmpa_mib:load_mibs(Pid, Mibs, false),
%% ?DBG("load_mibs -> "
%% "~n Res: ~p", [Res]),
Res.
unload_mibs(Pid, Mibs) ->
- Res = snmpa_mib:unload_mibs(Pid, Mibs),
+ Res = snmpa_mib:unload_mibs(Pid, Mibs, false),
%% ?DBG("unload_mibs -> "
%% "~n Res: ~p", [Res]),
Res.
@@ -1093,11 +1074,11 @@ tc_try(Name, TC) ->
tc_try(Name, Init, TC)
when is_atom(Name) andalso is_function(Init, 0) andalso is_function(TC, 0) ->
Pre = fun() ->
- {ok, Node} = ?ALIB:start_node(unique(Name)),
+ {ok, Peer, Node} = ?START_PEER(atom_to_list(Name)),
ok = run_on(Node, Init),
- Node
+ {Peer, Node}
end,
- Case = fun(Node) ->
+ Case = fun({_Peer, Node}) ->
monitor_node(Node, true),
Pid = spawn_link(Node, TC),
receive
@@ -1125,7 +1106,7 @@ tc_try(Name, Init, TC)
exit(Reason)
end
end,
- Post = fun(Node) ->
+ Post = fun({Peer, Node}) ->
receive
{nodedown, Node} ->
?NPRINT("node ~p (already) stopped", [Node]),
@@ -1133,7 +1114,7 @@ tc_try(Name, Init, TC)
after 0 ->
monitor_node(Node, true),
?NPRINT("try stop node ~p", [Node]),
- ?STOP_NODE(Node),
+ peer:stop(Peer),
receive
{nodedown, Node} ->
?NPRINT("node ~p stopped", [Node]),
@@ -1156,9 +1137,6 @@ run_on(Node, F) when is_atom(Node) andalso is_function(F, 0) ->
monitor_node(Node, false),
Reason
end.
-
-unique(PreName) ->
- list_to_atom(?F("~w_~w", [PreName, erlang:system_time(millisecond)])).
%% --
diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl
index 199296593f..3877123b37 100644
--- a/lib/snmp/test/snmp_agent_test_lib.erl
+++ b/lib/snmp/test/snmp_agent_test_lib.erl
@@ -33,8 +33,6 @@
start_subagent/3, stop_subagent/1,
start_sub_sup/1, start_sub_sup/2,
- start_node/1, stop_node/1,
-
load_master/1, load_master_std/1, unload_master/1,
loaded_mibs/0, unload_mibs/1,
@@ -131,11 +129,16 @@ init_all(Config) when is_list(Config) ->
%%
?IPRINT("init_all -> start sub-agent node"),
- ?line {ok, SaNode} = start_node(snmp_sa),
+ Args = ["-s", "snmp_test_sys_monitor", "start", "-s", "global", "sync"],
+
+ {ok, SaPeer, SaNode} = ?CT_PEER(#{name => ?CT_PEER_NAME(snmp_sa), args => Args}),
+ unlink(SaPeer), %% must unlink, otherwise peer will exit before test case
?IPRINT("init_all -> start manager node"),
- ?line {ok, MgrNode} = start_node(snmp_mgr),
+ {ok, MgrPeer, MgrNode} = ?CT_PEER(#{name => ?CT_PEER_NAME(snmp_mgr), args => Args}),
+ unlink(MgrPeer), %% must unlink, otherwise peer will exit before test case
+ global:sync(),
%% --
%% Create necessary files ( and dirs )
@@ -147,37 +150,37 @@ init_all(Config) when is_list(Config) ->
?IPRINT("init_all -> create agent dir"),
AgentDir = join(GroupTopDir, "agent/"),
- ?line ok = file:make_dir(AgentDir),
+ ok = file:make_dir(AgentDir),
?DBG("init_all -> AgentDir ~p", [AgentDir]),
?IPRINT("init_all -> create agent db dir"),
AgentDbDir = join(AgentDir, "db/"),
- ?line ok = file:make_dir(AgentDbDir),
+ ok = file:make_dir(AgentDbDir),
?DBG("init_all -> AgentDbDir ~p", [AgentDbDir]),
?IPRINT("init_all -> create agent log dir"),
AgentLogDir = join(AgentDir, "log/"),
- ?line ok = file:make_dir(AgentLogDir),
+ ok = file:make_dir(AgentLogDir),
?DBG("init_all -> AgentLogDir ~p", [AgentLogDir]),
?IPRINT("init_all -> create agent config dir"),
AgentConfDir = join(AgentDir, "conf/"),
- ?line ok = file:make_dir(AgentConfDir),
+ ok = file:make_dir(AgentConfDir),
?DBG("init_all -> AgentConfDir ~p", [AgentConfDir]),
?IPRINT("init_all -> create manager dir"),
MgrDir = join(GroupTopDir, "mgr/"),
- ?line ok = file:make_dir(MgrDir),
+ ok = file:make_dir(MgrDir),
?DBG("init_all -> MgrDir ~p", [MgrDir]),
?IPRINT("init_all -> create sub-agent dir"),
SaDir = join(GroupTopDir, "sa/"),
- ?line ok = file:make_dir(SaDir),
+ ok = file:make_dir(SaDir),
?DBG("init_all -> SaDir ~p", [SaDir]),
?IPRINT("init_all -> create sub-agent db dir"),
SaDbDir = join(SaDir, "db/"),
- ?line ok = file:make_dir(SaDbDir),
+ ok = file:make_dir(SaDbDir),
?DBG("init_all -> SaDbDir ~p", [SaDbDir]),
%% MibDir = ?config(mib_dir, Config),
@@ -189,35 +192,37 @@ init_all(Config) when is_list(Config) ->
%%
?IPRINT("init_all -> load mnesia application (local)"),
- ?line ok = application:load(mnesia),
+ ok = application:load(mnesia),
?IPRINT("init_all -> load application mnesia on node ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, load, [mnesia]),
+ ok = rpc:call(SaNode, application, load, [mnesia]),
?IPRINT("init_all -> application mnesia (local): set_env dir"),
- ?line application_controller:set_env(mnesia, dir,
+ application_controller:set_env(mnesia, dir,
join(AgentDbDir, "Mnesia1")),
?IPRINT("init_all -> application mnesia: set_env dir on node ~p", [SaNode]),
- ?line rpc:call(SaNode, application_controller, set_env,
+ rpc:call(SaNode, application_controller, set_env,
[mnesia, dir, join(SaDir, "Mnesia2")]),
?IPRINT("init_all -> create mnesia schema"),
- ?line ok = mnesia:create_schema([SaNode, node()]),
+ ok = mnesia:create_schema([SaNode, node()]),
?IPRINT("init_all -> start application mnesia (local)"),
- ?line ok = application:start(mnesia),
+ ok = application:start(mnesia),
?IPRINT("init_all -> start application mnesia on ~p", [SaNode]),
- ?line ok = rpc:call(SaNode, application, start, [mnesia]),
+ ok = rpc:call(SaNode, application, start, [mnesia]),
?IPRINT("init_all -> get localhost"),
Ip = ?LOCALHOST(),
?IPRINT("init_all -> done when"
"~n Nodes: ~p", [nodes()]),
- [{snmp_sa, SaNode},
- {snmp_mgr, MgrNode},
+ [{snmp_sa, SaNode},
+ {snmp_sa_peer, SaPeer},
+ {snmp_mgr, MgrNode},
+ {snmp_mgr_peer, MgrPeer},
{snmp_master, node()},
{agent_dir, AgentDir ++ "/"},
{agent_db_dir, AgentDbDir ++ "/"},
@@ -237,14 +242,12 @@ finish_all(Config) when is_list(Config) ->
"~n Config: ~p"
"~n Nodes: ~p", [Config, nodes()]),
- SaNode = ?config(snmp_sa, Config),
- MgrNode = ?config(snmp_mgr, Config),
+ SaPeer = ?config(snmp_sa_peer, Config),
+ MgrPeer = ?config(snmp_mgr_peer, Config),
- ?IPRINT("finish_all -> stop sub-agent node ~p", [SaNode]),
- stop_node(SaNode),
+ peer:stop(SaPeer),
- ?IPRINT("finish_all -> stop manager node ~p", [MgrNode]),
- stop_node(MgrNode),
+ peer:stop(MgrPeer),
?IPRINT("finish_all -> stop mnesia application"),
application:stop(mnesia),
@@ -296,6 +299,8 @@ init_case(Config) when is_list(Config) ->
put(masterip, tuple_to_list(MasterIP)),
put(sip, tuple_to_list(SIP)),
put(ipfamily, IpFamily),
+
+ put(receive_response_timeout, receive_response_timeout(Config)),
MibDir = ?config(mib_dir, Config),
put(mib_dir, MibDir),
@@ -316,6 +321,20 @@ init_case(Config) when is_list(Config) ->
{SaNode, MgrNode, MibDir}.
+receive_response_timeout(Config) ->
+ case lists:keysearch(snmp_factor, 1, Config) of
+ {value, {snmp_factor, F}} when (F < 4) ->
+ ?SECS(5);
+ {value, {snmp_factor, F}} when (F < 6) ->
+ ?SECS(10);
+ {value, {snmp_factor, F}} when (F < 8) ->
+ ?SECS(15);
+ {value, {snmp_factor, _}} ->
+ ?SECS(20);
+ _ ->
+ ?SECS(10)
+ end.
+
%%%--------------------------------------------------
%%% Used to test the standard mib with our
%%% configuration.
@@ -579,13 +598,13 @@ tc_run(Mod, Func, Args, Opts) ->
?EPRINT("Failed starting (test) manager: "
"~n ~p", [Reason]),
(catch snmp_test_mgr:stop()),
- ?line ?FAIL({mgr_start_error, Reason});
+ ?FAIL({mgr_start_error, Reason});
Err ->
?EPRINT("Failed starting (test) manager: "
"~n ~p", [Err]),
(catch snmp_test_mgr:stop()),
- ?line ?FAIL({mgr_start_failure, Err})
+ ?FAIL({mgr_start_failure, Err})
end.
%% We have some crap machines that generate this every now and then
@@ -597,7 +616,7 @@ tc_run_skip_check(_Mod, _Func, _Args,
?SKIP([{reason, Reason}]);
%% We have hosts (mostly *very* slooow VMs) that
%% can timeout anything. Since we are basically
-%% testing communication, we therefor must check
+%% testing communication, we therefore must check
%% for system events at every failure. Grrr!
tc_run_skip_check(Mod, Func, Args, Reason, Cat) ->
SysEvs = snmp_test_global_sys_monitor:events(),
@@ -608,7 +627,7 @@ tc_run_skip_check(Mod, Func, Args, Reason, Cat) ->
"~n ~p~n", [Cat, Reason]),
?FAIL({apply_failed, {Mod, Func, Args}, Reason});
true ->
- ?WPRINT("apply (~w) catched "
+ ?WPRINT("apply (~w) caught "
"when we got system events: "
"~n Reason: ~p"
"~n Sys Events: ~p"
@@ -670,11 +689,11 @@ start_agent(Config, Vsns, Opts) ->
"~n Vsns: ~p"
"~n Opts: ~p", [node(), Config, Vsns, Opts]),
- ?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),
- ?line InetBackend = ?config(socket_create_opts, Config),
+ AgentLogDir = ?config(agent_log_dir, Config),
+ AgentConfDir = ?config(agent_conf_dir, Config),
+ AgentDbDir = ?config(agent_db_dir, Config),
+ SaNode = ?config(snmp_sa, Config),
+ InetBackend = ?config(socket_create_opts, Config),
Env = app_agent_env_init(
[{versions, Vsns},
@@ -706,26 +725,26 @@ start_agent(Config, Vsns, Opts) ->
?DBG("start_agent -> snmp app supervisor: ~p", [AppSup]),
?IPRINT("start_agent -> try start master agent",[]),
- ?line Sup = start_sup(Env),
- ?line unlink(Sup),
+ Sup = start_sup(Env),
+ unlink(Sup),
?DBG("start_agent -> snmp supervisor: ~p", [Sup]),
?IPRINT("start_agent -> try (rpc) start sub agent on ~p", [SaNode]),
- ?line SaDir = ?config(sa_dir, Config),
- ?line {ok, Sub} = start_sub_sup(SaNode, SaDir),
+ SaDir = ?config(sa_dir, Config),
+ {ok, Sub} = start_sub_sup(SaNode, SaDir),
?DBG("start_agent -> done", []),
- ?line [{snmp_app_sup, AppSup},
+ [{snmp_app_sup, AppSup},
{snmp_sup, {Sup, self()}},
{snmp_sub, Sub} | Config].
app_agent_env_init(Env0, Opts) ->
?DBG("app_agent_env_init -> unload snmp",[]),
- ?line application:unload(snmp),
+ application:unload(snmp),
?DBG("app_agent_env_init -> load snmp",[]),
- ?line application:load(snmp),
+ application:load(snmp),
?DBG("app_agent_env_init -> "
"merge or maybe replace (snmp agent) app env",[]),
@@ -1306,7 +1325,7 @@ 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' withing ~w ms with"
+ io_format_expect("'get-response' within ~w ms with"
"~n Error: ~p"
"~n Index: ~p"
"~n Varbinds: ~p", [To, Err, Idx, ExpVBs]),
@@ -1639,41 +1658,6 @@ get_next_req(Vars) ->
Response.
-%% --- start and stop nodes ---
-
-start_node(Name) ->
- ?IPRINT("start_node -> entry with"
- "~n Name: ~p"
- "~n when"
- "~n hostname of this node: ~p",
- [Name, list_to_atom(?HOSTNAME(node()))]),
-
- Pa = filename:dirname(code:which(?MODULE)),
- ?DBG("start_node -> Pa: ~p", [Pa]),
-
- A = " -pa " ++ Pa ++
- " -s " ++ atom_to_list(snmp_test_sys_monitor) ++ " start" ++
- " -s global sync",
- case ?START_NODE(Name, A) of
- {ok, Node} ->
- ?DBG("start_node -> Node: ~p", [Node]),
- global:sync(),
- {ok, Node};
- {error, Reason} ->
- ?WPRINT("start_node -> failed starting node ~p:"
- "~n Reason: ~p", [Name, Reason]),
- ?line ?SKIP({failed_start_node, Reason});
- Else ->
- ?EPRINT("start_node -> failed starting node ~p:"
- "~n ~p", [Name, Else]),
- ?line ?FAIL(Else)
- end.
-
-
-stop_node(Node) ->
- ?IPRINT("stop_node -> Node: ~p", [Node]),
- ?STOP_NODE(Node).
-
%%%-----------------------------------------------------------------
%%% Configuration
@@ -1691,13 +1675,13 @@ config(Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily) ->
"~n AIp: ~p"
"~n IpFamily: ~p",
[Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily]),
- ?line {Domain, ManagerAddr} =
+ {Domain, ManagerAddr} =
case IpFamily of
inet6 ->
TransportDomain6 = transportDomainUdpIpv6,
AgentAddr6 = {AIp, 4000},
ManagerAddr6 = {MIp, ?TRAP_UDP},
- ?line ok =
+ ok =
snmp_config:write_agent_snmp_files(
AgentConfDir, Vsns,
TransportDomain6, ManagerAddr6, AgentAddr6, "test"),
@@ -1710,32 +1694,32 @@ config(Vsns, MgrDir, AgentConfDir, MIp, AIp, IpFamily) ->
%% [#{addr => {AIp2, 4000}, kind => req_responder},
%% #{addr => {AIp2, 4001}, kind => trap_sender}],
AgentPreTransport = [#{addr => {AIp2, 4000}}],
- ?line ok =
+ ok =
snmp_config:write_agent_snmp_files(
AgentConfDir, Vsns,
TransportDomain4, ManagerAddr4, AgentPreTransport,
"test"),
{TransportDomain4, ManagerAddr4};
_ ->
- ?line ok =
+ ok =
snmp_config:write_agent_snmp_files(
AgentConfDir, Vsns, MIp, ?TRAP_UDP, AIp, 4000, "test"),
{snmpUDPDomain, {MIp, ?TRAP_UDP}}
end,
- ?line case update_usm(Vsns, AgentConfDir) of
+ case update_usm(Vsns, AgentConfDir) of
true ->
- ?line copy_file(join(AgentConfDir, "usm.conf"),
+ copy_file(join(AgentConfDir, "usm.conf"),
join(MgrDir, "usm.conf")),
- ?line update_usm_mgr(Vsns, MgrDir);
+ update_usm_mgr(Vsns, MgrDir);
false ->
- ?line ok
+ ok
end,
- ?line update_community(Vsns, AgentConfDir),
- ?line update_vacm(Vsns, AgentConfDir),
- ?line write_target_addr_conf(AgentConfDir, Domain, ManagerAddr, Vsns),
- ?line write_target_params_conf(AgentConfDir, Vsns),
- ?line write_notify_conf(AgentConfDir),
+ update_community(Vsns, AgentConfDir),
+ update_vacm(Vsns, AgentConfDir),
+ write_target_addr_conf(AgentConfDir, Domain, ManagerAddr, Vsns),
+ write_target_params_conf(AgentConfDir, Vsns),
+ write_notify_conf(AgentConfDir),
ok.
maybe_fix_addr(Addr) when is_list(Addr) ->
@@ -1843,7 +1827,7 @@ update_usm(Vsns, Dir) ->
usmHMACSHAAuthProtocol, "", "",
usmDESPrivProtocol, "", "", "",
"passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}],
- ?line ok = snmp_config:update_agent_usm_config(Dir, Conf),
+ ok = snmp_config:update_agent_usm_config(Dir, Conf),
true;
false ->
false
@@ -1862,14 +1846,14 @@ update_usm_mgr(Vsns, Dir) ->
usmDESPrivProtocol, "", "", "",
"passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}],
- ?line ok = snmp_config:update_agent_usm_config(Dir, Conf),
+ ok = snmp_config:update_agent_usm_config(Dir, Conf),
true;
false ->
false
end.
rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
- ?line ok = file:rename(join(Dir,"usm.conf"),
+ ok = file:rename(join(Dir,"usm.conf"),
join(Dir,"usm.old")),
Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero,
usmHMACSHAAuthProtocol, "", "",
@@ -1877,10 +1861,10 @@ rewrite_usm_mgr(Dir, ShaKey, DesKey) ->
{"mgrEngine", "newUser", "newUser", zeroDotZero,
usmHMACSHAAuthProtocol, "", "",
usmDESPrivProtocol, "", "", "", ShaKey, DesKey}],
- ?line ok = snmp_config:write_agent_usm_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_usm_config(Dir, "", Conf).
reset_usm_mgr(Dir) ->
- ?line ok = file:rename(join(Dir,"usm.old"),
+ ok = file:rename(join(Dir,"usm.old"),
join(Dir,"usm.conf")).
@@ -1888,7 +1872,7 @@ update_community([v3], _Dir) ->
ok;
update_community(_, Dir) ->
Conf = [{"no-rights", "no-rights", "no-rights", "", ""}],
- ?line ok = snmp_config:update_agent_community_config(Dir, Conf).
+ ok = snmp_config:update_agent_community_config(Dir, Conf).
-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]).
@@ -1903,17 +1887,17 @@ update_vacm(_Vsn, Dir) ->
{vacmSecurityToGroup, usm, "newUser", "initial"},
{vacmViewTreeFamily, "internet", ?tDescr_instance,
excluded, null}],
- ?line ok = snmp_config:update_agent_vacm_config(Dir, Conf).
+ ok = snmp_config:update_agent_vacm_config(Dir, Conf).
write_community_conf(Dir, Conf) ->
- ?line ok = snmp_config:write_agent_community_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_community_config(Dir, "", Conf).
write_target_addr_conf(Dir, Conf) ->
- ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_target_addr_config(Dir, "", Conf).
write_target_addr_conf(Dir, Ip_or_Domain, Port_or_Addr, Vsns) ->
- ?line ok =
+ ok =
snmp_config:write_agent_snmp_target_addr_conf(
Dir, Ip_or_Domain, Port_or_Addr, Vsns).
@@ -1930,7 +1914,7 @@ rewrite_target_addr_conf(Dir, NewPort) ->
ok
end,
- ?line [TrapAddr|Addrs] =
+ [TrapAddr|Addrs] =
snmp_conf:read(TAFile, fun rewrite_target_addr_conf_check/1),
?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]),
@@ -1939,10 +1923,10 @@ rewrite_target_addr_conf(Dir, NewPort) ->
?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]),
- ?line ok = file:rename(join(Dir,"target_addr.conf"),
+ ok = file:rename(join(Dir,"target_addr.conf"),
join(Dir,"target_addr.old")),
- ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", NewAddrs).
+ ok = snmp_config:write_agent_target_addr_config(Dir, "", NewAddrs).
rewrite_target_addr_conf_check(O) ->
{ok,O}.
@@ -1958,7 +1942,7 @@ rewrite_target_addr_conf2(_NewPort,O) ->
O.
reset_target_addr_conf(Dir) ->
- ?line ok = file:rename(join(Dir, "target_addr.old"),
+ ok = file:rename(join(Dir, "target_addr.old"),
join(Dir, "target_addr.conf")).
write_target_params_conf(Dir, Vsns) ->
@@ -1967,28 +1951,28 @@ write_target_params_conf(Dir, Vsns) ->
(v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv}
end,
Conf = [F(Vsn) || Vsn <- Vsns],
- ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_target_params_config(Dir, "", Conf).
rewrite_target_params_conf(Dir, SecName, SecLevel)
when is_list(SecName) andalso is_atom(SecLevel) ->
- ?line ok = file:rename(join(Dir,"target_params.conf"),
+ ok = file:rename(join(Dir,"target_params.conf"),
join(Dir,"target_params.old")),
Conf = [{"target_v3", v3, usm, SecName, SecLevel}],
- ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_target_params_config(Dir, "", Conf).
reset_target_params_conf(Dir) ->
- ?line ok = file:rename(join(Dir,"target_params.old"),
+ ok = file:rename(join(Dir,"target_params.old"),
join(Dir,"target_params.conf")).
write_notify_conf(Dir) ->
Conf = [{"standard trap", "std_trap", trap},
{"standard inform", "std_inform", inform}],
- ?line ok = snmp_config:write_agent_notify_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_notify_config(Dir, "", Conf).
write_view_conf(Dir) ->
Conf = [{2, [1,3,6], included, null},
{2, ?tDescr_instance, excluded, null}],
- ?line ok = snmp_config:write_agent_view_config(Dir, "", Conf).
+ ok = snmp_config:write_agent_view_config(Dir, "", Conf).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/snmp/test/snmp_compiler_SUITE.erl b/lib/snmp/test/snmp_compiler_SUITE.erl
index f4ba914919..9cc47397a8 100644
--- a/lib/snmp/test/snmp_compiler_SUITE.erl
+++ b/lib/snmp/test/snmp_compiler_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -197,14 +197,14 @@ description(Config) when is_list(Config) ->
Desctext = "This is a test description",
Oid = [1,3,6,1,2,1,15,1],
write_mib(MibSrcName,Desctext),
- ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir},
+ {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir},
{group_check, false},
{warnings, false},
{description, false}]),
MIB1 = read_mib(MibBinName),
%% ?IPRINT("description -> MIB1: ~n~p~n", [MIB1]),
check_mib(MIB1#mib.mes, Oid, undefined),
- ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir},
+ {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir},
{group_check, false},
{warnings, false},
{description, true}]),
@@ -228,8 +228,8 @@ oid_conflicts(Config) when is_list(Config) ->
Dir = ?config(case_top_dir, Config),
Mib = join(Dir,"TESTv2.mib"),
- ?line ok = write_oid_conflict_mib(Mib),
- ?line {error,compilation_failed} =
+ ok = write_oid_conflict_mib(Mib),
+ {error,compilation_failed} =
snmpc:compile(Mib,[{outdir, Dir},{verbosity,trace}]),
ok.
@@ -263,21 +263,21 @@ agent_capabilities(Config) when is_list(Config) ->
SnmpMibsDir = join(SnmpPrivDir, "mibs"),
Dir = ?config(mib_dir, Config),
AcMib = join(Dir,"AC-TEST-MIB.mib"),
- ?line {ok, MibFile1} = snmpc:compile(AcMib, [options,
+ {ok, MibFile1} = snmpc:compile(AcMib, [options,
version,
{i, [SnmpMibsDir]},
{outdir, Dir},
{verbosity, trace}]),
- ?line {ok, Mib1} = snmp_misc:read_mib(MibFile1),
- ?line {ok, MibFile2} = snmpc:compile(AcMib, [options,
+ {ok, Mib1} = snmp_misc:read_mib(MibFile1),
+ {ok, MibFile2} = snmpc:compile(AcMib, [options,
version,
agent_capabilities,
{i, [SnmpMibsDir]},
{outdir, Dir},
{verbosity, trace}]),
- ?line {ok, Mib2} = snmp_misc:read_mib(MibFile2),
+ {ok, Mib2} = snmp_misc:read_mib(MibFile2),
MEDiff = Mib2#mib.mes -- Mib1#mib.mes,
- %% This is a rather pathetic test, but it is somthing...
+ %% This is a rather pathetic test, but it is something...
?IPRINT("agent_capabilities -> "
"~n MEDiff: ~p"
"~n Mib1: ~p"
@@ -304,21 +304,21 @@ module_compliance(Config) when is_list(Config) ->
SnmpMibsDir = join(SnmpPrivDir, "mibs"),
Dir = ?config(mib_dir, Config),
AcMib = join(Dir,"MC-TEST-MIB.mib"),
- ?line {ok, MibFile1} = snmpc:compile(AcMib, [options,
+ {ok, MibFile1} = snmpc:compile(AcMib, [options,
version,
{i, [SnmpMibsDir]},
{outdir, Dir},
{verbosity, trace}]),
- ?line {ok, Mib1} = snmp_misc:read_mib(MibFile1),
- ?line {ok, MibFile2} = snmpc:compile(AcMib, [options,
+ {ok, Mib1} = snmp_misc:read_mib(MibFile1),
+ {ok, MibFile2} = snmpc:compile(AcMib, [options,
version,
module_compliance,
{i, [SnmpMibsDir]},
{outdir, Dir},
{verbosity, trace}]),
- ?line {ok, Mib2} = snmp_misc:read_mib(MibFile2),
+ {ok, Mib2} = snmp_misc:read_mib(MibFile2),
MEDiff = Mib2#mib.mes -- Mib1#mib.mes,
- %% This is a rather pathetic test, but it is somthing...
+ %% This is a rather pathetic test, but it is something...
?IPRINT("module_compliance -> "
"~n MEDiff: ~p"
"~n Mib1: ~p"
@@ -369,7 +369,7 @@ otp_6150(Config) when is_list(Config) ->
Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"),
- ?line {ok, Mib} =
+ {ok, Mib} =
snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
?IPRINT("otp_6150 -> Mib: "
"~n ~p", [Mib]),
@@ -422,7 +422,7 @@ otp_8595(Config) when is_list(Config) ->
Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP8595-MIB.mib"),
- ?line {ok, Mib} =
+ {ok, Mib} =
snmpc:compile(MibFile, [{outdir, Dir},
{verbosity, trace},
{group_check, false}]),
@@ -442,7 +442,7 @@ otp_10799(Config) when is_list(Config) ->
Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP10799-MIB.mib"),
- ?line {ok, Mib} =
+ {ok, Mib} =
snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
?IPRINT("Mib: "
"~n ~p", [Mib]),
@@ -461,7 +461,7 @@ otp_10808(Config) when is_list(Config) ->
Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP10808-MIB.mib"),
- ?line {ok, Mib} =
+ {ok, Mib} =
snmpc:compile(MibFile, [{outdir, Dir},
{verbosity, trace},
{group_check, false}]),
@@ -483,7 +483,7 @@ otp_14145(Config) when is_list(Config) ->
MibDir = ?config(mib_dir, Config),
MibName = "OTP14145-MIB",
MibFile = join(MibDir, MibName++".mib"),
- ?line {ok, MibBin} =
+ {ok, MibBin} =
snmpc:compile(MibFile, [{outdir, Dir},
{verbosity, trace},
{group_check, false},
@@ -509,7 +509,7 @@ otp_13014(Config) when is_list(Config) ->
MibDir = ?config(mib_dir, Config),
MibName = "Test-LLDP-MIB",
MibFile = join(MibDir, MibName++".mib"),
- ?line {ok, MibBin} =
+ {ok, MibBin} =
snmpc:compile(MibFile, [{outdir, Dir},
{verbosity, log},
{group_check, false},
@@ -544,7 +544,7 @@ otp_14196(Config) when is_list(Config) ->
Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "OTP14196-MIB.mib"),
- ?line {ok, Mib} =
+ {ok, Mib} =
snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
?IPRINT("Mib: "
"~n ~p", [Mib]),
@@ -564,13 +564,13 @@ augments_extra_info(Config) when is_list(Config) ->
MibDir = ?config(mib_dir, Config),
Test2File = join(MibDir, "Test2.mib"),
Test3File = join(MibDir, "Test3.mib"),
- ?line {ok, Test2BinFile} =
+ {ok, Test2BinFile} =
snmpc:compile(Test2File, [{outdir, Dir},
{verbosity, silence},
{group_check, false}]),
?IPRINT("Test2BinFile: "
"~n ~p", [Test2BinFile]),
- ?line {ok, Test3BinFile} =
+ {ok, Test3BinFile} =
snmpc:compile(Test3File, [{i, [MibDir]},
{outdir, Dir},
{verbosity, silence},
diff --git a/lib/snmp/test/snmp_conf_SUITE.erl b/lib/snmp/test/snmp_conf_SUITE.erl
index 698cf2d6f3..ae5cbc9c5a 100644
--- a/lib/snmp/test/snmp_conf_SUITE.erl
+++ b/lib/snmp/test/snmp_conf_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -181,7 +181,7 @@ init_per_testcase(fd_leak_check = _Case, Config) when is_list(Config) ->
%% Something strange happens when we use pfiles from within erlang,
%% so skip the test for now
- %% For some reason even though 'which' exists (atleast in
+ %% For some reason even though 'which' exists (at least in
%% a tcsh shell), it hangs when called via os:cmd/1.
%% And type produces results that is not so easy to
%% "analyze". So, we 'try it' and know that it starts
@@ -239,14 +239,14 @@ check_mandatory(Config) when is_list(Config) ->
{b, mandatory},
{d, {value, 20202}},
{e, {value, "kalle"}}],
- ?line {ok, _L1} = verify_mandatory(A1, B1),
+ {ok, _L1} = verify_mandatory(A1, B1),
?DBG("check_mandatory -> L1: ~p", [L1]),
A2 = [{a, hej}, {c, 10}, {d, 10101}, {f, 10.88}],
B2 = [{a, {value, hejsan}},
{b, mandatory},
{d, {value, 20202}},
{e, {value, "kalle"}}],
- ?line ok = verify_not_mandatory(A2, B2),
+ ok = verify_not_mandatory(A2, B2),
ok.
verify_mandatory(A, B) ->
@@ -283,16 +283,16 @@ verify_not_mandatory(A, B) ->
check_integer1(suite) -> [];
check_integer1(Config) when is_list(Config) ->
?P(check_integer1),
- ?line ok = verify_int(0),
- ?line ok = verify_int(16#FF),
- ?line ok = verify_int(16#FFFF),
- ?line ok = verify_int(16#FFFFFFFF),
- ?line ok = verify_int(-1),
- ?line ok = verify_int(-333),
+ ok = verify_int(0),
+ ok = verify_int(16#FF),
+ ok = verify_int(16#FFFF),
+ ok = verify_int(16#FFFFFFFF),
+ ok = verify_int(-1),
+ ok = verify_int(-333),
- ?line ok = verify_not_int("kalle & hobbe"),
- ?line ok = verify_not_int(kalle_och_hobbe),
- ?line ok = verify_not_int(1.5),
+ ok = verify_not_int("kalle & hobbe"),
+ ok = verify_not_int(kalle_och_hobbe),
+ ok = verify_not_int(1.5),
ok.
@@ -318,49 +318,49 @@ check_integer2(suite) -> [];
check_integer2(Config) when is_list(Config) ->
?P(check_integer2),
- ?line ok = verify_int(0, any),
- ?line ok = verify_int(-22222, any),
- ?line ok = verify_int(33333, any),
- ?line ok = verify_int(1, pos),
- ?line ok = verify_int(9999, pos),
- ?line ok = verify_int(-1, neg),
- ?line ok = verify_int(-9999, neg),
- ?line ok = verify_int(1, {gt, 0}),
- ?line ok = verify_int(88888, {gt, -255}),
- ?line ok = verify_int(88888, {gte, -255}),
- ?line ok = verify_int(88888, {gte, 88888}),
- ?line ok = verify_int(88888, {lt, 88889}),
- ?line ok = verify_int(88888, {lte, 88888}),
- ?line ok = verify_int(88888, {eq, 88888}),
- ?line ok = verify_int(88888, {range, 88887,88889}),
-
- ?line ok = verify_not_int("kalle & hobbe", any),
- ?line ok = verify_not_int(kalle_och_hobbe, any),
- ?line ok = verify_not_int(1.5, any),
-
- ?line ok = verify_not_int(0, pos),
- ?line ok = verify_not_int(-22222, pos),
- ?line ok = verify_not_int(33333, neg),
- ?line ok = verify_not_int(0, {gt, 0}),
- ?line ok = verify_not_int(33333, {gt, 99999}),
- ?line ok = verify_not_int(33333, {gt, 33333}),
- ?line ok = verify_not_int(33333, {gte, 33334}),
- ?line ok = verify_not_int(33333, {lt, 33333}),
- ?line ok = verify_not_int(33333, {lte, 33332}),
- ?line ok = verify_not_int(33333, {eq, 33332}),
- ?line ok = verify_not_int(33333, {eq, -33333}),
- ?line ok = verify_not_int(33333, {range, 33334, 33338}),
- ?line ok = verify_not_int(33339, {range, 33334, 33338}),
- ?line ok = verify_not_int(33333, {gt, kalle}),
- ?line ok = verify_not_int(33333, {gt, 1.55}),
- ?line ok = verify_not_int(33333, {gte, "hejsan"}),
- ?line ok = verify_not_int(33333, {lt, hobbe}),
- ?line ok = verify_not_int(33333, {lte, 1.7666}),
- ?line ok = verify_not_int(33333, {eq, 33333.0}),
- ?line ok = verify_not_int(33333, {eq, -33333.0}),
- ?line ok = verify_not_int(33333, {range, kalle, 33338}),
- ?line ok = verify_not_int(33339, {range, 33334, kalle}),
- ?line ok = verify_not_int(33339, {kalle, 33334, kalle}),
+ ok = verify_int(0, any),
+ ok = verify_int(-22222, any),
+ ok = verify_int(33333, any),
+ ok = verify_int(1, pos),
+ ok = verify_int(9999, pos),
+ ok = verify_int(-1, neg),
+ ok = verify_int(-9999, neg),
+ ok = verify_int(1, {gt, 0}),
+ ok = verify_int(88888, {gt, -255}),
+ ok = verify_int(88888, {gte, -255}),
+ ok = verify_int(88888, {gte, 88888}),
+ ok = verify_int(88888, {lt, 88889}),
+ ok = verify_int(88888, {lte, 88888}),
+ ok = verify_int(88888, {eq, 88888}),
+ ok = verify_int(88888, {range, 88887,88889}),
+
+ ok = verify_not_int("kalle & hobbe", any),
+ ok = verify_not_int(kalle_och_hobbe, any),
+ ok = verify_not_int(1.5, any),
+
+ ok = verify_not_int(0, pos),
+ ok = verify_not_int(-22222, pos),
+ ok = verify_not_int(33333, neg),
+ ok = verify_not_int(0, {gt, 0}),
+ ok = verify_not_int(33333, {gt, 99999}),
+ ok = verify_not_int(33333, {gt, 33333}),
+ ok = verify_not_int(33333, {gte, 33334}),
+ ok = verify_not_int(33333, {lt, 33333}),
+ ok = verify_not_int(33333, {lte, 33332}),
+ ok = verify_not_int(33333, {eq, 33332}),
+ ok = verify_not_int(33333, {eq, -33333}),
+ ok = verify_not_int(33333, {range, 33334, 33338}),
+ ok = verify_not_int(33339, {range, 33334, 33338}),
+ ok = verify_not_int(33333, {gt, kalle}),
+ ok = verify_not_int(33333, {gt, 1.55}),
+ ok = verify_not_int(33333, {gte, "hejsan"}),
+ ok = verify_not_int(33333, {lt, hobbe}),
+ ok = verify_not_int(33333, {lte, 1.7666}),
+ ok = verify_not_int(33333, {eq, 33333.0}),
+ ok = verify_not_int(33333, {eq, -33333.0}),
+ ok = verify_not_int(33333, {range, kalle, 33338}),
+ ok = verify_not_int(33339, {range, 33334, kalle}),
+ ok = verify_not_int(33339, {kalle, 33334, kalle}),
ok.
@@ -385,10 +385,10 @@ verify_not_int(Val, Cond) ->
check_string1(suite) -> [];
check_string1(Config) when is_list(Config) ->
?P(check_string1),
- ?line ok = verify_string("kalle & hobbe"),
- ?line ok = verify_not_string(kalle_hobbe),
- ?line ok = verify_not_string(1000),
- ?line ok = verify_not_string(1.0),
+ ok = verify_string("kalle & hobbe"),
+ ok = verify_not_string(kalle_hobbe),
+ ok = verify_not_string(1000),
+ ok = verify_not_string(1.0),
ok.
verify_string(Val) ->
@@ -414,21 +414,21 @@ check_string2(suite) -> [];
check_string2(Config) when is_list(Config) ->
?P(check_string2),
Str = "kalle & hobbe",
- ?line ok = verify_string(Str, any),
- ?line ok = verify_string(Str, {gt, length(Str) - 1}),
- ?line ok = verify_string(Str, {gte, length(Str)}),
- ?line ok = verify_string(Str, {lt, length(Str) + 1}),
- ?line ok = verify_string(Str, {lte, length(Str)}),
- ?line ok = verify_string(Str, length(Str)),
-
- ?line ok = verify_not_string(kalle_hobbe, any),
- ?line ok = verify_not_string(1000, any),
- ?line ok = verify_not_string(1.0, any),
- ?line ok = verify_not_string(Str, {gt, length(Str)}),
- ?line ok = verify_not_string(Str, {gte, length(Str) + 1}),
- ?line ok = verify_not_string(Str, {lt, length(Str)}),
- ?line ok = verify_not_string(Str, {lte, length(Str) - 1}),
- ?line ok = verify_not_string(Str, length(Str) + 1),
+ ok = verify_string(Str, any),
+ ok = verify_string(Str, {gt, length(Str) - 1}),
+ ok = verify_string(Str, {gte, length(Str)}),
+ ok = verify_string(Str, {lt, length(Str) + 1}),
+ ok = verify_string(Str, {lte, length(Str)}),
+ ok = verify_string(Str, length(Str)),
+
+ ok = verify_not_string(kalle_hobbe, any),
+ ok = verify_not_string(1000, any),
+ ok = verify_not_string(1.0, any),
+ ok = verify_not_string(Str, {gt, length(Str)}),
+ ok = verify_not_string(Str, {gte, length(Str) + 1}),
+ ok = verify_not_string(Str, {lt, length(Str)}),
+ ok = verify_not_string(Str, {lte, length(Str) - 1}),
+ ok = verify_not_string(Str, length(Str) + 1),
ok.
verify_string(Val, Limit) ->
@@ -454,10 +454,10 @@ check_atom(suite) -> [];
check_atom(Config) when is_list(Config) ->
?P(check_atom),
Atoms = [{kalle, "kalle"}, {hobbe, "hobbe"}, {dummy, "dummy"}],
- ?line ok = verify_atom(kalle, Atoms),
- ?line ok = verify_not_atom(anka, Atoms),
- ?line ok = verify_not_atom("kalle", Atoms),
- ?line ok = verify_not_atom(1000, Atoms),
+ ok = verify_atom(kalle, Atoms),
+ ok = verify_not_atom(anka, Atoms),
+ ok = verify_not_atom("kalle", Atoms),
+ ok = verify_not_atom(1000, Atoms),
ok.
verify_atom(Val, Atoms) ->
@@ -482,13 +482,13 @@ verify_not_atom(Val, Atoms) ->
check_ip(suite) -> [];
check_ip(Config) when is_list(Config) ->
?P(check_ip),
- ?line ok = verify_ip([1,2,3,4]),
- ?line ok = verify_not_ip([1,2,3]),
- ?line ok = verify_not_ip([1,2,3,4,5]),
- ?line ok = verify_not_ip(kalle),
- ?line ok = verify_not_ip(1000),
- ?line ok = verify_not_ip([1,2,3.0,4]),
- ?line ok = verify_not_ip([1,two,3,4]),
+ ok = verify_ip([1,2,3,4]),
+ ok = verify_not_ip([1,2,3]),
+ ok = verify_not_ip([1,2,3,4,5]),
+ ok = verify_not_ip(kalle),
+ ok = verify_not_ip(1000),
+ ok = verify_not_ip([1,2,3.0,4]),
+ ok = verify_not_ip([1,two,3,4]),
ok.
verify_ip(Val) ->
@@ -515,13 +515,13 @@ verify_not_ip(Val) ->
check_taddress(suite) -> [];
check_taddress(Config) when is_list(Config) ->
?P(check_taddress),
- ?line ok = verify_taddress([1,2,3,4,5,6]),
- ?line ok = verify_not_taddress([1,2,3,4,5]),
- ?line ok = verify_not_taddress([1,2,3,4,5,6,7]),
- ?line ok = verify_not_taddress(kalle),
- ?line ok = verify_not_taddress(1000),
- ?line ok = verify_not_taddress([1,2,3.0,4,5,6]),
- ?line ok = verify_not_taddress([1,two,3,4,5,6]),
+ ok = verify_taddress([1,2,3,4,5,6]),
+ ok = verify_not_taddress([1,2,3,4,5]),
+ ok = verify_not_taddress([1,2,3,4,5,6,7]),
+ ok = verify_not_taddress(kalle),
+ ok = verify_not_taddress(1000),
+ ok = verify_not_taddress([1,2,3.0,4,5,6]),
+ ok = verify_not_taddress([1,two,3,4,5,6]),
ok.
verify_taddress(Val) ->
@@ -548,15 +548,15 @@ check_packet_size(Config) when is_list(Config) ->
?P(check_packet_size),
Min = 484,
Max = 2147483647,
- ?line ok = verify_packet_size(Min),
- ?line ok = verify_packet_size(2*Min),
- ?line ok = verify_packet_size(Max),
- ?line ok = verify_not_packet_size(Min-1),
- ?line ok = verify_not_packet_size(Max+1),
- ?line ok = verify_not_packet_size(kalle),
- ?line ok = verify_not_packet_size("kalle"),
- ?line ok = verify_not_packet_size(1.0),
- ?line ok = verify_not_packet_size(1.0*Max),
+ ok = verify_packet_size(Min),
+ ok = verify_packet_size(2*Min),
+ ok = verify_packet_size(Max),
+ ok = verify_not_packet_size(Min-1),
+ ok = verify_not_packet_size(Max+1),
+ ok = verify_not_packet_size(kalle),
+ ok = verify_not_packet_size("kalle"),
+ ok = verify_not_packet_size(1.0),
+ ok = verify_not_packet_size(1.0*Max),
ok.
verify_packet_size(Val) ->
@@ -583,14 +583,14 @@ check_oid(Config) when is_list(Config) ->
?P(check_oid),
[_,_|Rest] = ?otpSnmpeaModule,
ErrOid = [6,16|Rest],
- ?line ok = verify_oid(?system),
- ?line ok = verify_oid(?sysDescr_instance),
- ?line ok = verify_oid(?otpSnmpeaModule),
- ?line ok = verify_not_oid(kalle),
- ?line ok = verify_not_oid("kalle"),
- ?line ok = verify_not_oid(1000),
- ?line ok = verify_not_oid(1.0),
- ?line ok = verify_not_oid(ErrOid),
+ ok = verify_oid(?system),
+ ok = verify_oid(?sysDescr_instance),
+ ok = verify_oid(?otpSnmpeaModule),
+ ok = verify_not_oid(kalle),
+ ok = verify_not_oid("kalle"),
+ ok = verify_not_oid(1000),
+ ok = verify_not_oid(1.0),
+ ok = verify_not_oid(ErrOid),
ok.
verify_oid(Val) ->
@@ -618,15 +618,15 @@ check_sec_model1(Config) when is_list(Config) ->
Exclude1 = [],
Exclude2 = [v1],
Exclude3 = [v1,usm],
- ?line ok = verify_sec_model(any, Exclude1),
- ?line ok = verify_sec_model(v1, Exclude1),
- ?line ok = verify_sec_model(v2c, Exclude1),
- ?line ok = verify_sec_model(usm, Exclude1),
- ?line ok = verify_sec_model(any, Exclude2),
- ?line ok = verify_sec_model(v2c, Exclude2),
- ?line ok = verify_not_sec_model(v1, Exclude2),
- ?line ok = verify_not_sec_model(v1, Exclude3),
- ?line ok = verify_not_sec_model(usm, Exclude3),
+ ok = verify_sec_model(any, Exclude1),
+ ok = verify_sec_model(v1, Exclude1),
+ ok = verify_sec_model(v2c, Exclude1),
+ ok = verify_sec_model(usm, Exclude1),
+ ok = verify_sec_model(any, Exclude2),
+ ok = verify_sec_model(v2c, Exclude2),
+ ok = verify_not_sec_model(v1, Exclude2),
+ ok = verify_not_sec_model(v1, Exclude3),
+ ok = verify_not_sec_model(usm, Exclude3),
ok.
verify_sec_model(Val, Exclude) ->
@@ -651,24 +651,24 @@ verify_not_sec_model(Val, Exclude) ->
check_sec_model2(suite) -> [];
check_sec_model2(Config) when is_list(Config) ->
?P(check_sec_model2),
- ?line ok = verify_sec_model(v1, v1, []),
- ?line ok = verify_sec_model(v1, v1, [v2c]),
- ?line ok = verify_sec_model(v2c, v2c, []),
- ?line ok = verify_sec_model(v2c, v2c, [v1]),
- ?line ok = verify_sec_model(v3, usm, []),
- ?line ok = verify_sec_model(v3, usm, [v2c]),
- ?line ok = verify_not_sec_model(v1, v2c, []),
- ?line ok = verify_not_sec_model(v1, v3, [v2c]),
- ?line ok = verify_not_sec_model(v1, v1, [v1]),
- ?line ok = verify_not_sec_model(v2c, v1, []),
- ?line ok = verify_not_sec_model(v2c, v3, [v3]),
- ?line ok = verify_not_sec_model(v2c, v2c, [v2c]),
- ?line ok = verify_not_sec_model(v3, v1, []),
- ?line ok = verify_not_sec_model(v3, v2c, [v1]),
- ?line ok = verify_not_sec_model(v3, v3, [v2c]),
- ?line ok = verify_not_sec_model(kalle, v3, []),
- ?line ok = verify_not_sec_model(1000, v3, []),
- ?line ok = verify_not_sec_model(1.0, v3, []),
+ ok = verify_sec_model(v1, v1, []),
+ ok = verify_sec_model(v1, v1, [v2c]),
+ ok = verify_sec_model(v2c, v2c, []),
+ ok = verify_sec_model(v2c, v2c, [v1]),
+ ok = verify_sec_model(v3, usm, []),
+ ok = verify_sec_model(v3, usm, [v2c]),
+ ok = verify_not_sec_model(v1, v2c, []),
+ ok = verify_not_sec_model(v1, v3, [v2c]),
+ ok = verify_not_sec_model(v1, v1, [v1]),
+ ok = verify_not_sec_model(v2c, v1, []),
+ ok = verify_not_sec_model(v2c, v3, [v3]),
+ ok = verify_not_sec_model(v2c, v2c, [v2c]),
+ ok = verify_not_sec_model(v3, v1, []),
+ ok = verify_not_sec_model(v3, v2c, [v1]),
+ ok = verify_not_sec_model(v3, v3, [v2c]),
+ ok = verify_not_sec_model(kalle, v3, []),
+ ok = verify_not_sec_model(1000, v3, []),
+ ok = verify_not_sec_model(1.0, v3, []),
ok.
@@ -694,13 +694,13 @@ verify_not_sec_model(M1, M2, Exclude) ->
check_sec_level(suite) -> [];
check_sec_level(Config) when is_list(Config) ->
?P(check_sec_level),
- ?line ok = verify_sec_level(noAuthNoPriv),
- ?line ok = verify_sec_level(authNoPriv),
- ?line ok = verify_sec_level(authPriv),
- ?line ok = verify_not_sec_level(kalle),
- ?line ok = verify_not_sec_level("noAuthNoPriv"),
- ?line ok = verify_not_sec_level(1000),
- ?line ok = verify_not_sec_level(1.0),
+ ok = verify_sec_level(noAuthNoPriv),
+ ok = verify_sec_level(authNoPriv),
+ ok = verify_sec_level(authPriv),
+ ok = verify_not_sec_level(kalle),
+ ok = verify_not_sec_level("noAuthNoPriv"),
+ ok = verify_not_sec_level(1000),
+ ok = verify_not_sec_level(1.0),
ok.
@@ -730,30 +730,30 @@ verify_not_sec_level(Val) ->
check_timer(suite) -> [];
check_timer(Config) when is_list(Config) ->
?P(check_timer),
- ?line ok = verify_timer(infinity),
- ?line ok = verify_timer(1),
- ?line ok = verify_timer(10),
- ?line ok = verify_timer(2147483647),
- ?line ok = verify_timer(2*2147483647),
- ?line ok = verify_timer({1,1,0,0}),
- ?line ok = verify_timer({10,10,10,10}),
- ?line ok = verify_timer({2147483647,2147483647,2147483647,2147483647}),
- ?line ok = verify_not_timer(ytinifni),
- ?line ok = verify_not_timer("ytinifni"),
- ?line ok = verify_not_timer(0),
- ?line ok = verify_not_timer(-10),
- ?line ok = verify_not_timer({0,1,0,0}),
- ?line ok = verify_not_timer({1,0,0,0}),
- ?line ok = verify_not_timer({1,1,-1,0}),
- ?line ok = verify_not_timer({1,1,0,-1}),
- ?line ok = verify_not_timer({1.0,1,0,0}),
- ?line ok = verify_not_timer({1,1.0,0,0}),
- ?line ok = verify_not_timer({1,1,1.0,0}),
- ?line ok = verify_not_timer({1,1,0,1.0}),
- ?line ok = verify_not_timer({"1",1,0,0}),
- ?line ok = verify_not_timer({1,"1",0,0}),
- ?line ok = verify_not_timer({1,1,"0",0}),
- ?line ok = verify_not_timer({1,1,0,"0"}),
+ ok = verify_timer(infinity),
+ ok = verify_timer(1),
+ ok = verify_timer(10),
+ ok = verify_timer(2147483647),
+ ok = verify_timer(2*2147483647),
+ ok = verify_timer({1,1,0,0}),
+ ok = verify_timer({10,10,10,10}),
+ ok = verify_timer({2147483647,2147483647,2147483647,2147483647}),
+ ok = verify_not_timer(ytinifni),
+ ok = verify_not_timer("ytinifni"),
+ ok = verify_not_timer(0),
+ ok = verify_not_timer(-10),
+ ok = verify_not_timer({0,1,0,0}),
+ ok = verify_not_timer({1,0,0,0}),
+ ok = verify_not_timer({1,1,-1,0}),
+ ok = verify_not_timer({1,1,0,-1}),
+ ok = verify_not_timer({1.0,1,0,0}),
+ ok = verify_not_timer({1,1.0,0,0}),
+ ok = verify_not_timer({1,1,1.0,0}),
+ ok = verify_not_timer({1,1,0,1.0}),
+ ok = verify_not_timer({"1",1,0,0}),
+ ok = verify_not_timer({1,"1",0,0}),
+ ok = verify_not_timer({1,1,"0",0}),
+ ok = verify_not_timer({1,1,0,"0"}),
ok.
verify_timer(Val) ->
diff --git a/lib/snmp/test/snmp_log_SUITE.erl b/lib/snmp/test/snmp_log_SUITE.erl
index caa7a10076..e4d8414506 100644
--- a/lib/snmp/test/snmp_log_SUITE.erl
+++ b/lib/snmp/test/snmp_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -169,7 +169,7 @@ init_per_testcase(Case, Config) when is_list(Config) ->
Error ->
?FAIL({failed_creating_subsuite_top_dir, Error})
end,
- ?line ok = file:make_dir(CaseDir),
+ ok = file:make_dir(CaseDir),
Dog = ?WD_START(?MINS(5)),
[{log_dir, CaseDir}, {watchdog, Dog}|Config].
@@ -199,11 +199,11 @@ open_and_close(Config) when is_list(Config) ->
File = join(Dir, "snmp_test.log"),
Size = {1024, 10},
Repair = true,
- ?line {ok, Log} = snmp_log:create(Name, File, Size, Repair),
- ?line ok = snmp_log:sync(Log),
- ?line {ok, Info} = snmp_log:info(Log),
+ {ok, Log} = snmp_log:create(Name, File, Size, Repair),
+ ok = snmp_log:sync(Log),
+ {ok, Info} = snmp_log:info(Log),
display_info(Info),
- ?line ok = snmp_log:close(Log).
+ ok = snmp_log:close(Log).
%%======================================================================
@@ -219,7 +219,7 @@ open_write_and_close1(Config) when is_list(Config) ->
?DBG("open_write_and_close1 -> start", []),
SeqNoGen = none,
- ?line ok = open_write_and_close(SeqNoGen, Config),
+ ok = open_write_and_close(SeqNoGen, Config),
?DBG("open_write_and_close1 -> done", []),
ok.
@@ -238,7 +238,7 @@ open_write_and_close2(Config) when is_list(Config) ->
?DBG("open_write_and_close2 -> start", []),
SeqNoGen = disabled,
- ?line ok = open_write_and_close(SeqNoGen, Config),
+ ok = open_write_and_close(SeqNoGen, Config),
?DBG("open_write_and_close2 -> done", []),
ok.
@@ -258,7 +258,7 @@ open_write_and_close3(Config) when is_list(Config) ->
seqno_init(),
SeqNoGen = {?MODULE, next_seqno, [10, 100]},
- ?line ok = open_write_and_close(SeqNoGen, Config),
+ ok = open_write_and_close(SeqNoGen, Config),
seqno_finish(),
?DBG("open_write_and_close2 -> done", []),
@@ -279,7 +279,7 @@ open_write_and_close4(Config) when is_list(Config) ->
seqno_init(),
SeqNoGen = fun() -> next_seqno(10, 100) end,
- ?line ok = open_write_and_close(SeqNoGen, Config),
+ ok = open_write_and_close(SeqNoGen, Config),
seqno_finish(),
?DBG("open_write_and_close2 -> done", []),
@@ -319,7 +319,7 @@ open_write_and_close(SeqNoGen, Config) ->
Repair = true,
?DBG("open_write_and_close -> create log", []),
- ?line {ok, Log} =
+ {ok, Log} =
case SeqNoGen of
none ->
snmp_log:create(Name, File, Size, Repair);
@@ -332,10 +332,10 @@ open_write_and_close(SeqNoGen, Config) ->
?DBG("open_write_and_close1 -> create messages to log", []),
%% A request
- ?line Req = get_next_request(Vsn, Community, [1,1], 1, 235779012),
+ Req = get_next_request(Vsn, Community, [1,1], 1, 235779012),
%% A reply
- ?line Rep = get_response(Vsn, Community,
+ Rep = get_response(Vsn, Community,
[1,3,6,1,2,1,1,1,0], 'OCTET STRING',
"Erlang SNMP agent", 1, 235779012),
@@ -348,17 +348,17 @@ open_write_and_close(SeqNoGen, Config) ->
Addr = ?LOCALHOST(),
Port = 162,
Logger = fun(Packet) ->
- ?line ok = snmp_log:log(Log, Packet, Addr, Port)
+ ok = snmp_log:log(Log, Packet, Addr, Port)
end,
lists:foreach(Logger, Msgs),
check_notify(),
?DBG("open_write_and_close1 -> display info", []),
- ?line {ok, Info} = snmp_log:info(Log),
+ {ok, Info} = snmp_log:info(Log),
display_info(Info),
?DBG("open_write_and_close1 -> close log", []),
- ?line ok = snmp_log:close(Log),
+ ok = snmp_log:close(Log),
?DBG("open_write_and_close -> done", []),
ok.
@@ -381,7 +381,7 @@ log_to_io1(Config) when is_list(Config) ->
Size = {1024, 10},
Repair = true,
?DBG("log_to_io1 -> create log", []),
- ?line {ok, Log} = snmp_log:create(Name, File, Size, Repair),
+ {ok, Log} = snmp_log:create(Name, File, Size, Repair),
?DBG("log_to_io1 -> create messages to log", []),
Msgs = messages(),
@@ -390,7 +390,7 @@ log_to_io1(Config) when is_list(Config) ->
Addr = ?LOCALHOST(),
Port = 162,
Logger = fun(Packet) ->
- ?line ok = snmp_log:log(Log, Packet, Addr, Port)
+ ok = snmp_log:log(Log, Packet, Addr, Port)
end,
BatchLogger = fun(Time) ->
lists:foreach(Logger, Msgs),
@@ -403,14 +403,14 @@ log_to_io1(Config) when is_list(Config) ->
lists:foreach(BatchLogger, To),
?DBG("log_to_io1 -> display info", []),
- ?line {ok, Info} = snmp_log:info(Log),
+ {ok, Info} = snmp_log:info(Log),
display_info(Info),
?DBG("log_to_io1 -> do the convert to io (stdout)", []),
? line ok = snmp:log_to_io(Dir, [], Name, File, false),
?DBG("log_to_io1 -> close log", []),
- ?line ok = snmp_log:close(Log),
+ ok = snmp_log:close(Log),
?DBG("log_to_io1 -> done", []),
ok.
@@ -438,20 +438,20 @@ log_to_io2(Config) when is_list(Config) ->
Repair = true,
?DBG("log_to_io2 -> create log writer process", []),
- ?line {ok, Log, Logger} =
+ {ok, Log, Logger} =
log_writer_start(Name, File, Size, Repair, Factor),
?DBG("log_to_io2 -> create log reader process", []),
- ?line {ok, Reader} = log_reader_start(),
+ {ok, Reader} = log_reader_start(),
?DBG("log_to_io2 -> wait some time", []),
?SLEEP(5000),
?DBG("log_to_io2 -> display log info", []),
- ?line log_writer_info(Logger),
+ log_writer_info(Logger),
?DBG("log_to_io2 -> instruct the log writer to sleep some", []),
- ?line ok = log_writer_sleep(Logger, 5000),
+ ok = log_writer_sleep(Logger, 5000),
?DBG("log_to_io2 -> instruct the log reader to log to io", []),
Res =
@@ -470,14 +470,14 @@ log_to_io2(Config) when is_list(Config) ->
?DBG("log_to_io2 -> log to io failed: "
"~n Error: ~p"
"~n Info: ~p", [Error, Info]),
- ?line ?FAIL({log_lo_io_failed, Error, Info})
+ ?FAIL({log_lo_io_failed, Error, Info})
end,
?DBG("log_to_io2 -> instruct the log writer to stop", []),
- ?line log_writer_stop(Logger),
+ log_writer_stop(Logger),
?DBG("log_to_io2 -> instruct the log reader to stop", []),
- ?line log_reader_stop(Reader),
+ log_reader_stop(Reader),
?DBG("log_to_io2 -> done", []),
ok.
@@ -494,7 +494,7 @@ log_to_txt1(Config) when is_list(Config) ->
Name = "snmp_test_l2t1",
SeqNoGen = disabled,
- ?line ok = log_to_txt(Name, SeqNoGen, Config),
+ ok = log_to_txt(Name, SeqNoGen, Config),
?DBG("log_to_txt1 -> done", []),
ok.
@@ -513,7 +513,7 @@ log_to_txt2(Config) when is_list(Config) ->
Name = "snmp_test_l2t2",
seqno_init(),
SeqNoGen = {?MODULE, next_seqno, [1, 100]},
- ?line ok = log_to_txt(Name, SeqNoGen, Config),
+ ok = log_to_txt(Name, SeqNoGen, Config),
seqno_finish(),
?DBG("log_to_txt2 -> done", []),
@@ -531,7 +531,7 @@ log_to_txt(Name, SeqNoGen, Config) when is_list(Config) ->
Repair = true,
?DBG("log_to_txt -> create log", []),
- ?line {ok, Log} =
+ {ok, Log} =
case SeqNoGen of
none ->
snmp_log:create(Name, File, Size, Repair);
@@ -546,7 +546,7 @@ log_to_txt(Name, SeqNoGen, Config) when is_list(Config) ->
Addr = ?LOCALHOST(),
Port = 162,
Logger = fun(Packet) ->
- ?line ok = snmp_log:log(Log, Packet, Addr, Port)
+ ok = snmp_log:log(Log, Packet, Addr, Port)
end,
BatchLogger = fun(Time) ->
lists:foreach(Logger, Msgs),
@@ -561,22 +561,22 @@ log_to_txt(Name, SeqNoGen, Config) when is_list(Config) ->
Stop = calendar:local_time(),
?DBG("log_to_txt -> display info", []),
- ?line {ok, Info} = snmp_log:info(Log),
+ {ok, Info} = snmp_log:info(Log),
display_info(Info),
Out1a = join(Dir, "snmp_text-1-unblocked.txt"),
?DBG("log_to_txt -> do the convert to a text file (~s) unblocked", [Out1a]),
- ?line ok = snmp:log_to_txt(Dir, [], Out1a, Log, File, false),
+ ok = snmp:log_to_txt(Dir, [], Out1a, Log, File, false),
- ?line {ok, #file_info{size = Size1a}} = file:read_file_info(Out1a),
+ {ok, #file_info{size = Size1a}} = file:read_file_info(Out1a),
?DBG("log_to_txt -> text file size: ~p", [Size1a]),
validate_size(Size1a),
Out1b = join(Dir, "snmp_text-1-blocked.txt"),
?DBG("log_to_txt -> do the convert to a text file (~s) blocked", [Out1b]),
- ?line ok = snmp:log_to_txt(Dir, [], Out1b, Log, File, true),
+ ok = snmp:log_to_txt(Dir, [], Out1b, Log, File, true),
- ?line {ok, #file_info{size = Size1b}} = file:read_file_info(Out1b),
+ {ok, #file_info{size = Size1b}} = file:read_file_info(Out1b),
?DBG("log_to_txt -> text file size: ~p", [Size1b]),
validate_size(Size1b, {eq, Size1a}),
@@ -585,9 +585,9 @@ log_to_txt(Name, SeqNoGen, Config) when is_list(Config) ->
"~n Start: ~p"
"~n Stop: ~p"
"~n Out2: ~p", [Start, Stop, Out2]),
- ?line ok = snmp:log_to_txt(Dir, [], Out2, Log, File, Start, Stop),
+ ok = snmp:log_to_txt(Dir, [], Out2, Log, File, Start, Stop),
- ?line {ok, #file_info{size = Size2}} = file:read_file_info(Out2),
+ {ok, #file_info{size = Size2}} = file:read_file_info(Out2),
?DBG("log_to_txt -> text file size: ~p", [Size2]),
validate_size(Size2, {le, Size1a}),
@@ -615,14 +615,14 @@ log_to_txt(Name, SeqNoGen, Config) when is_list(Config) ->
"~n Start2: ~p"
"~n Stop2: ~p"
"~n Out3: ~p", [Start2, Stop2, Out3]),
- ?line ok = snmp:log_to_txt(Dir, [], Out3, Log, File, Start2, Stop2),
+ ok = snmp:log_to_txt(Dir, [], Out3, Log, File, Start2, Stop2),
- ?line {ok, #file_info{size = Size3}} = file:read_file_info(Out3),
+ {ok, #file_info{size = Size3}} = file:read_file_info(Out3),
?DBG("log_to_txt -> text file size: ~p", [Size3]),
validate_size(Size3, {l, Size1a}),
?DBG("log_to_txt -> close log", []),
- ?line ok = snmp_log:close(Log),
+ ok = snmp_log:close(Log),
?DBG("log_to_txt -> done", []),
ok.
@@ -659,20 +659,20 @@ log_to_txt3(Config) when is_list(Config) ->
Mibs = [join(StdMibDir, "SNMPv2-MIB")],
?DBG("log_to_txt3 -> create log writer process", []),
- ?line {ok, Log, Logger} =
+ {ok, Log, Logger} =
log_writer_start(Name, LogFile, Size, Repair, Factor),
?DBG("log_to_txt3 -> create log reader process", []),
- ?line {ok, Reader} = log_reader_start(),
+ {ok, Reader} = log_reader_start(),
?DBG("log_to_txt3 -> wait some time", []),
?SLEEP(5000),
?DBG("log_to_txt3 -> display log info", []),
- ?line log_writer_info(Logger),
+ log_writer_info(Logger),
?DBG("log_to_txt3 -> instruct the log writer to sleep some", []),
- ?line ok = log_writer_sleep(Logger, 5000),
+ ok = log_writer_sleep(Logger, 5000),
?DBG("log_to_txt3 -> instruct the log reader to log to txt", []),
Res =
@@ -690,7 +690,7 @@ log_to_txt3(Config) when is_list(Config) ->
case Res of
{ok, _Info} ->
?DBG("log_to_txt3 -> ~n Info: ~p", [_Info]),
- ?line {ok, #file_info{size = FileSize}} =
+ {ok, #file_info{size = FileSize}} =
file:read_file_info(TxtFile),
?DBG("log_to_txt3 -> text file size: ~p", [FileSize]),
validate_size(FileSize);
@@ -698,14 +698,14 @@ log_to_txt3(Config) when is_list(Config) ->
?EPRINT("log to txt failed: "
"~n Error: ~p"
"~n Info: ~p", [Error, Info]),
- ?line ?FAIL({log_lo_txt_failed, Error, Info})
+ ?FAIL({log_lo_txt_failed, Error, Info})
end,
?DBG("log_to_txt3 -> instruct the log writer to stop", []),
- ?line log_writer_stop(Logger),
+ log_writer_stop(Logger),
?DBG("log_to_txt3 -> instruct the log reader to stop", []),
- ?line log_reader_stop(Reader),
+ log_reader_stop(Reader),
?IPRINT("log_to_txt3 -> done", []),
ok.
@@ -801,7 +801,7 @@ log_writer_main(Name, File, Size, Repair, P, Factor) ->
Addr = ?LOCALHOST(),
Port = 162,
Logger = fun(Packet) ->
- ?line ok = snmp_log:log(Log, Packet, Addr, Port)
+ ok = snmp_log:log(Log, Packet, Addr, Port)
end,
BatchLogger = fun(Time) ->
lists:foreach(Logger, Msgs),
diff --git a/lib/snmp/test/snmp_manager_SUITE.erl b/lib/snmp/test/snmp_manager_SUITE.erl
index fc4d73ac7f..d45a415776 100644
--- a/lib/snmp/test/snmp_manager_SUITE.erl
+++ b/lib/snmp/test/snmp_manager_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,9 +62,9 @@
register_user1/1,
- register_agent_old/1,
- register_agent2/1,
- register_agent3/1,
+ register_agent_old/0, register_agent_old/1,
+ register_agent2/0, register_agent2/1,
+ register_agent3/0, register_agent3/1,
info/1,
usm_priv_aes/1,
@@ -73,30 +73,30 @@
usm_sha384_priv_aes/1,
usm_sha512_priv_aes/1,
- simple_sync_get3/1,
- simple_async_get3/1,
+ simple_sync_get3/0, simple_sync_get3/1,
+ simple_async_get3/0, simple_async_get3/1,
- simple_sync_get_next3/1,
- simple_async_get_next3_cbp_def/1,
- simple_async_get_next3_cbp_temp/1,
- simple_async_get_next3_cbp_perm/1,
+ simple_sync_get_next3/0, simple_sync_get_next3/1,
+ simple_async_get_next3_cbp_def/0, simple_async_get_next3_cbp_def/1,
+ simple_async_get_next3_cbp_temp/0, simple_async_get_next3_cbp_temp/1,
+ simple_async_get_next3_cbp_perm/0, simple_async_get_next3_cbp_perm/1,
- simple_sync_set3/1,
- simple_async_set3_cbp_def/1,
- simple_async_set3_cbp_temp/1,
- simple_async_set3_cbp_perm/1,
+ simple_sync_set3/0, simple_sync_set3/1,
+ simple_async_set3_cbp_def/0, simple_async_set3_cbp_def/1,
+ simple_async_set3_cbp_temp/0, simple_async_set3_cbp_temp/1,
+ simple_async_set3_cbp_perm/0, simple_async_set3_cbp_perm/1,
- simple_sync_get_bulk3/1,
- simple_async_get_bulk3_cbp_def/1,
- simple_async_get_bulk3_cbp_temp/1,
- simple_async_get_bulk3_cbp_perm/1,
-
- simple_v3_exchange_md5/1,
- simple_v3_exchange_sha/1,
- simple_v3_exchange_sha224/1,
- simple_v3_exchange_sha256/1,
- simple_v3_exchange_sha384/1,
- simple_v3_exchange_sha512/1,
+ simple_sync_get_bulk3/0, simple_sync_get_bulk3/1,
+ simple_async_get_bulk3_cbp_def/0, simple_async_get_bulk3_cbp_def/1,
+ simple_async_get_bulk3_cbp_temp/0, simple_async_get_bulk3_cbp_temp/1,
+ simple_async_get_bulk3_cbp_perm/0, simple_async_get_bulk3_cbp_perm/1,
+
+ simple_v3_exchange_md5/0, simple_v3_exchange_md5/1,
+ simple_v3_exchange_sha/0, simple_v3_exchange_sha/1,
+ simple_v3_exchange_sha224/0, simple_v3_exchange_sha224/1,
+ simple_v3_exchange_sha256/0, simple_v3_exchange_sha256/1,
+ simple_v3_exchange_sha384/0, simple_v3_exchange_sha384/1,
+ simple_v3_exchange_sha512/0, simple_v3_exchange_sha512/1,
discovery/1,
@@ -113,9 +113,9 @@
report/1,
- otp8015_1/1,
+ otp8015_1/0, otp8015_1/1,
- otp8395_1/1
+ otp8395_1/0, otp8395_1/1
]).
@@ -156,7 +156,7 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
- %% This is a temporary messure to ensure that we can
+ %% This is a temporary measure to ensure that we can
%% test the socket backend without effecting *all*
%% applications on *all* machines.
%% This flag is set only for *one* host.
@@ -440,25 +440,56 @@ init_per_group(GroupName, Config0) ->
Config1.
-init_per_group2(inet_backend_default = _GroupName, Config) ->
- ?LIB:init_group_top_dir(default, [{socket_create_opts, []} | Config]);
-init_per_group2(inet_backend_inet = _GroupName, Config) ->
+init_per_group2(inet_backend_default = _GroupName, Config0) ->
+ Config1 = [{socket_create_opts, []} | Config0],
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ ?LIB:init_group_top_dir(default, Config1);
+ false ->
+ %% For a "standard" test (that is if we do not run the "extended"
+ %% inet backends test) then we should always run this group!
+ %% So, if we have an extended test, *then* (and only then)
+ %% check the factor.
+ case ?TEST_INET_BACKENDS() of
+ true ->
+ case lists:keysearch(snmp_factor, 1, Config0) of
+ {value, {snmp_factor, Factor}} when (Factor < 3) ->
+ ?LIB:init_group_top_dir(default, Config1);
+ _ ->
+ {skip, "Machine too slow"}
+ end;
+ _ ->
+ ?LIB:init_group_top_dir(default, Config1)
+ end
+ end;
+init_per_group2(inet_backend_inet = _GroupName, Config0) ->
case ?EXPLICIT_INET_BACKEND() of
true ->
%% The environment trumps us,
%% so only the default group should be run!
{skip, "explicit inet backend"};
false ->
- ?LIB:init_group_top_dir(inet, [{socket_create_opts, [{inet_backend, inet}]} | Config])
+ case lists:keysearch(snmp_factor, 1, Config0) of
+ {value, {snmp_factor, Factor}} when (Factor < 5) ->
+ Config1 = [{socket_create_opts, [{inet_backend, inet}]} |
+ Config0],
+ ?LIB:init_group_top_dir(inet, Config1);
+ _ ->
+ {skip, "Machine too slow"}
+ end
end;
-init_per_group2(inet_backend_socket = _GroupName, Config) ->
+init_per_group2(inet_backend_socket = _GroupName, Config0) ->
case ?EXPLICIT_INET_BACKEND() of
true ->
%% The environment trumps us,
%% so only the default group should be run!
{skip, "explicit inet backend"};
false ->
- ?LIB:init_group_top_dir(socket, [{socket_create_opts, [{inet_backend, socket}]} | Config])
+ %% Always run this unless a backend has been explicitly
+ %% configured (since this is really what we want to test).
+ Config1 = [{socket_create_opts, [{inet_backend, socket}]} |
+ Config0],
+ ?LIB:init_group_top_dir(socket, Config1)
end;
init_per_group2(all = GroupName, Config) ->
?LIB:init_group_top_dir(GroupName, Config);
@@ -577,7 +608,7 @@ init_per_testcase(Case, Config) when is_list(Config) ->
{skip, {Reason, Mod, Line}};
C:E:_ when ((C =:= throw) orelse
(C =:= exit)) ->
- {skip, {catched, C, E}}
+ {skip, {caught, C, E}}
end
end,
?IPRINT("init_per_testcase end when"
@@ -598,29 +629,29 @@ init_per_testcase2(Case, Config) ->
MgrTopDir = filename:join(CaseTopDir, "manager/"),
?DBG("init_per_testcase2 -> try create manager top dir: ~n~p",
[MgrTopDir]),
- ?line ok = file:make_dir(MgrTopDir),
+ ok = file:make_dir(MgrTopDir),
MgrConfDir = filename:join(MgrTopDir, "conf/"),
- ?line ok = file:make_dir(MgrConfDir),
+ ok = file:make_dir(MgrConfDir),
MgrDbDir = filename:join(MgrTopDir, "db/"),
- ?line ok = file:make_dir(MgrDbDir),
+ ok = file:make_dir(MgrDbDir),
MgrLogDir = filename:join(MgrTopDir, "log/"),
- ?line ok = file:make_dir(MgrLogDir),
+ ok = file:make_dir(MgrLogDir),
%% -- Agent dirs --
AgTopDir = filename:join(CaseTopDir, "agent/"),
- ?line ok = file:make_dir(AgTopDir),
+ ok = file:make_dir(AgTopDir),
AgConfDir = filename:join(AgTopDir, "conf/"),
- ?line ok = file:make_dir(AgConfDir),
+ ok = file:make_dir(AgConfDir),
AgDbDir = filename:join(AgTopDir, "db/"),
- ?line ok = file:make_dir(AgDbDir),
+ ok = file:make_dir(AgDbDir),
AgLogDir = filename:join(AgTopDir, "log/"),
- ?line ok = file:make_dir(AgLogDir),
+ ok = file:make_dir(AgLogDir),
Family = proplists:get_value(ipfamily, Config, inet),
@@ -654,18 +685,18 @@ init_per_testcase2(Case, Config) ->
?DBG("init [~w] Nodes [2]: ~p", [Case, erlang:nodes()]),
Conf2.
-init_per_testcase3(simple_v3_exchange_md5 = _Case, Config) ->
- init_v3_testcase([{auth_alg, md5} | Config]);
-init_per_testcase3(simple_v3_exchange_sha = _Case, Config) ->
- init_v3_testcase([{auth_alg, sha} | Config]);
-init_per_testcase3(simple_v3_exchange_sha224 = _Case, Config) ->
- init_v3_testcase([{auth_alg, sha224} | Config]);
-init_per_testcase3(simple_v3_exchange_sha256 = _Case, Config) ->
- init_v3_testcase([{auth_alg, sha256} | Config]);
-init_per_testcase3(simple_v3_exchange_sha384 = _Case, Config) ->
- init_v3_testcase([{auth_alg, sha384} | Config]);
-init_per_testcase3(simple_v3_exchange_sha512 = _Case, Config) ->
- init_v3_testcase([{auth_alg, sha512} | Config]);
+init_per_testcase3(simple_v3_exchange_md5 = Case, Config) ->
+ init_v3_testcase(Case, [{auth_alg, md5} | Config]);
+init_per_testcase3(simple_v3_exchange_sha = Case, Config) ->
+ init_v3_testcase(Case, [{auth_alg, sha} | Config]);
+init_per_testcase3(simple_v3_exchange_sha224 = Case, Config) ->
+ init_v3_testcase(Case, [{auth_alg, sha224} | Config]);
+init_per_testcase3(simple_v3_exchange_sha256 = Case, Config) ->
+ init_v3_testcase(Case, [{auth_alg, sha256} | Config]);
+init_per_testcase3(simple_v3_exchange_sha384 = Case, Config) ->
+ init_v3_testcase(Case, [{auth_alg, sha384} | Config]);
+init_per_testcase3(simple_v3_exchange_sha512 = Case, Config) ->
+ init_v3_testcase(Case, [{auth_alg, sha512} | Config]);
init_per_testcase3(Case, Config) ->
ApiCases02 =
[
@@ -744,8 +775,8 @@ init_per_testcase3(Case, Config) ->
end,
%% We don't need to try catch this (init_agent)
%% since we have a try catch "higher up"...
- Conf3 = init_agent(Conf2),
- Conf4 = try init_manager(AutoInform, Conf3)
+ Conf3 = init_agent(Case, Conf2),
+ Conf4 = try init_manager(Case, AutoInform, Conf3)
catch AC:AE:_ ->
%% Ouch we need to clean up:
%% The init_agent starts an agent node!
@@ -771,9 +802,9 @@ init_per_testcase3(Case, Config) ->
Config
end.
-init_v3_testcase(Conf) ->
- Conf2 = init_v3_agent(Conf),
- Conf3 = try init_v3_manager(Conf2)
+init_v3_testcase(Case, Conf) ->
+ Conf2 = init_v3_agent(Case, Conf),
+ Conf3 = try init_v3_manager(Case, Conf2)
catch AC:AE:AS ->
%% Ouch we need to clean up:
%% The init_agent starts an agent node!
@@ -896,7 +927,6 @@ end_per_testcase2(Case, Config) ->
%% Test functions
%%======================================================================
-simple_start_and_stop1(suite) -> [];
simple_start_and_stop1(Config) when is_list(Config) ->
?TC_TRY(simple_start_and_stop1,
fun() -> do_simple_start_and_stop1(Config) end).
@@ -930,17 +960,16 @@ do_simple_start_and_stop1(Config) ->
%%======================================================================
-simple_start_and_stop2(suite) -> [];
simple_start_and_stop2(Config) when is_list(Config) ->
Pre = fun() ->
- ManagerNode = start_manager_node(),
+ ManagerNode = start_node(simple_start_and_stop2),
[ManagerNode]
end,
Case = fun(State) -> do_simple_start_and_stop2(State, Config) end,
- Post = fun([ManagerNode]) -> stop_node(ManagerNode) end,
+ Post = fun([{ManagerPeer, _ManagerNode}]) -> peer:stop(ManagerPeer) end,
?TC_TRY(simple_start_and_stop2, Pre, Case, Post).
-do_simple_start_and_stop2([ManagerNode], Config) ->
+do_simple_start_and_stop2([{_ManagerPeer, ManagerNode}], Config) ->
?IPRINT("starting with Config: "
"~n ~p"
"~n", [Config]),
@@ -958,20 +987,20 @@ do_simple_start_and_stop2([ManagerNode], Config) ->
?IPRINT("try load snmp application"),
- ?line ok = load_snmp(ManagerNode),
+ ok = load_snmp(ManagerNode),
?IPRINT("try set manager env for the snmp application"),
- ?line ok = set_mgr_env(ManagerNode, Opts),
+ ok = set_mgr_env(ManagerNode, Opts),
?IPRINT("try starting snmp application (with only manager)"),
- ?line ok = start_snmp(ManagerNode),
+ ok = start_snmp(ManagerNode),
?IPRINT("started"),
?SLEEP(1000),
?IPRINT("try stopping snmp application (with only manager)"),
- ?line ok = stop_snmp(ManagerNode),
+ ok = stop_snmp(ManagerNode),
?SLEEP(1000),
?IPRINT("end"),
@@ -981,7 +1010,6 @@ do_simple_start_and_stop2([ManagerNode], Config) ->
%%======================================================================
-simple_start_and_stop3(suite) -> [];
simple_start_and_stop3(Config) when is_list(Config) ->
?TC_TRY(simple_start_and_stop3,
fun() -> do_simple_start_and_stop3(Config) end).
@@ -1021,7 +1049,6 @@ do_simple_start_and_stop3(Config) ->
%%======================================================================
-simple_start_and_monitor_crash1(suite) -> [];
simple_start_and_monitor_crash1(Config) when is_list(Config) ->
?TC_TRY(simple_start_and_monitor_crash1,
fun() -> do_simple_start_and_monitor_crash1(Config) end).
@@ -1085,7 +1112,6 @@ do_simple_start_and_monitor_crash1(Config) ->
%%======================================================================
-simple_start_and_monitor_crash2(suite) -> [];
simple_start_and_monitor_crash2(Config) when is_list(Config) ->
Cond = fun() -> case os:type() of
{unix, netbsd} ->
@@ -1191,7 +1217,6 @@ simulate_crash(NumKills, _) ->
%%======================================================================
-notify_started01(suite) -> [];
notify_started01(Config) when is_list(Config) ->
?TC_TRY(notify_started01,
fun() -> do_notify_started01(Config) end).
@@ -1283,7 +1308,6 @@ snmpm_starter(Opts, To) ->
%%======================================================================
-notify_started02(suite) -> [];
notify_started02(Config) when is_list(Config) ->
?TC_TRY(notify_started02,
fun() -> notify_started02_cond(Config) end,
@@ -1509,7 +1533,6 @@ ns02_ctrl_loop(Opts, N) ->
%%======================================================================
-info(suite) -> [];
info(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -1612,7 +1635,6 @@ verify_info([{Key, SubKeys}|Keys], Info) ->
%% USM privacy fails with AES in OTP 22.2.3. Test to prevent
%% regression in future releases.
%%
-usm_priv_aes(suite) -> [];
usm_priv_aes(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -1645,7 +1667,6 @@ usm_priv_aes(Config) when is_list(Config) ->
%%======================================================================
-usm_sha224_priv_aes(suite) -> [];
usm_sha224_priv_aes(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -1678,7 +1699,6 @@ usm_sha224_priv_aes(Config) when is_list(Config) ->
%%======================================================================
-usm_sha256_priv_aes(suite) -> [];
usm_sha256_priv_aes(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -1711,7 +1731,6 @@ usm_sha256_priv_aes(Config) when is_list(Config) ->
%%======================================================================
-usm_sha384_priv_aes(suite) -> [];
usm_sha384_priv_aes(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -1744,7 +1763,6 @@ usm_sha384_priv_aes(Config) when is_list(Config) ->
%%======================================================================
-usm_sha512_priv_aes(suite) -> [];
usm_sha512_priv_aes(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -1921,17 +1939,16 @@ do_usm_priv_aes(AuthAlg, Config) ->
%%======================================================================
-register_user1(suite) -> [];
register_user1(Config) when is_list(Config) ->
Pre = fun() ->
- ManagerNode = start_manager_node(),
+ ManagerNode = start_node(register_user1),
[ManagerNode]
end,
Case = fun(State) -> do_register_user1(State, Config) end,
- Post = fun([ManagerNode]) -> stop_node(ManagerNode) end,
+ Post = fun([{ManagerPeer, _ManagerNode}]) -> peer:stop(ManagerPeer) end,
?TC_TRY(register_user1, Pre, Case, Post).
-do_register_user1([ManagerNode], Config) ->
+do_register_user1([{_ManagerPeer, ManagerNode}], Config) ->
?IPRINT("starting with Config: "
"~n ~p"
"~n", [Config]),
@@ -1949,13 +1966,13 @@ do_register_user1([ManagerNode], Config) ->
?IPRINT("load snmp application"),
- ?line ok = load_snmp(ManagerNode),
+ ok = load_snmp(ManagerNode),
?IPRINT("set manager env for the snmp application"),
- ?line ok = set_mgr_env(ManagerNode, Opts),
+ ok = set_mgr_env(ManagerNode, Opts),
?IPRINT("starting snmp application (with only manager)"),
- ?line ok = start_snmp(ManagerNode),
+ ok = start_snmp(ManagerNode),
?IPRINT("started"),
@@ -1964,41 +1981,41 @@ do_register_user1([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("try register user(s)"),
- ?line ok = mgr_register_user(ManagerNode, calvin, snmpm_user_default,
+ ok = mgr_register_user(ManagerNode, calvin, snmpm_user_default,
[self(), "various misc info"]),
Users1 = mgr_which_users(ManagerNode),
?IPRINT("users: ~p~n", [Users1]),
- ?line ok = verify_users(Users1, [calvin]),
+ ok = verify_users(Users1, [calvin]),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
- ?line ok = mgr_register_user(ManagerNode, hobbe, snmpm_user_default,
+ ok = mgr_register_user(ManagerNode, hobbe, snmpm_user_default,
{"misc info", self()}),
Users2 = mgr_which_users(ManagerNode),
?IPRINT("users: ~p~n", [Users2]),
- ?line ok = verify_users(Users2, [calvin, hobbe]),
+ ok = verify_users(Users2, [calvin, hobbe]),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("try unregister user(s)"),
- ?line ok = mgr_unregister_user(ManagerNode, calvin),
+ ok = mgr_unregister_user(ManagerNode, calvin),
Users3 = mgr_which_users(ManagerNode),
?IPRINT("users: ~p~n", [Users3]),
- ?line ok = verify_users(Users3, [hobbe]),
+ ok = verify_users(Users3, [hobbe]),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
- ?line ok = mgr_unregister_user(ManagerNode, hobbe),
+ ok = mgr_unregister_user(ManagerNode, hobbe),
Users4 = mgr_which_users(ManagerNode),
?IPRINT("users: ~p~n", [Users4]),
- ?line ok = verify_users(Users4, []),
+ ok = verify_users(Users4, []),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?SLEEP(1000),
?IPRINT("stop snmp application (with only manager)"),
- ?line ok = stop_snmp(ManagerNode),
+ ok = stop_snmp(ManagerNode),
?SLEEP(1000),
@@ -2019,20 +2036,19 @@ verify_users(ActualUsers0, [User|RegUsers]) ->
%%======================================================================
-register_agent_old(doc) ->
- ["Test registration of agents with the OLD interface functions"];
-register_agent_old(suite) ->
- [];
+register_agent_old() ->
+ [{doc, "Test registration of agents with the OLD interface functions"}].
+
register_agent_old(Config) when is_list(Config) ->
Pre = fun() ->
- ManagerNode = start_manager_node(),
+ ManagerNode = start_node(register_agent_old),
[ManagerNode]
end,
Case = fun(State) -> do_register_agent_old(State, Config) end,
- Post = fun([ManagerNode]) -> stop_node(ManagerNode) end,
+ Post = fun([{ManagerPeer, _ManagerNode}]) -> peer:stop(ManagerPeer) end,
?TC_TRY(register_agent_old, Pre, Case, Post).
-do_register_agent_old([ManagerNode], Config) ->
+do_register_agent_old([{_ManagerPeer, ManagerNode}], Config) ->
?IPRINT("starting with Config: "
"~n ~p"
"~n", [Config]),
@@ -2050,13 +2066,13 @@ do_register_agent_old([ManagerNode], Config) ->
?IPRINT("load snmp application"),
- ?line ok = load_snmp(ManagerNode),
+ ok = load_snmp(ManagerNode),
?IPRINT("set manager env for the snmp application"),
- ?line ok = set_mgr_env(ManagerNode, Opts),
+ ok = set_mgr_env(ManagerNode, Opts),
?IPRINT("starting snmp application (with only manager)"),
- ?line ok = start_snmp(ManagerNode),
+ ok = start_snmp(ManagerNode),
?IPRINT("started"),
@@ -2065,15 +2081,15 @@ do_register_agent_old([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("register user(s) user_alfa & user_beta"),
- ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
- ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
+ ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
+ ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("register agent(s)"),
- ?line ok = mgr_register_agent(ManagerNode, user_alfa, 5000, []),
- ?line ok = mgr_register_agent(ManagerNode, user_alfa, 5001, []),
- ?line ok = mgr_register_agent(ManagerNode, user_beta, 5002, []),
- ?line ok = mgr_register_agent(ManagerNode, user_beta, 5003, []),
+ ok = mgr_register_agent(ManagerNode, user_alfa, 5000, []),
+ ok = mgr_register_agent(ManagerNode, user_alfa, 5001, []),
+ ok = mgr_register_agent(ManagerNode, user_beta, 5002, []),
+ ok = mgr_register_agent(ManagerNode, user_beta, 5003, []),
?IPRINT("verify all agent(s): expect 4"),
case mgr_which_agents(ManagerNode) of
@@ -2106,7 +2122,7 @@ do_register_agent_old([ManagerNode], Config) ->
"~n ~p", [mgr_info(ManagerNode)]),
?IPRINT("unregister user user_alfa"),
- ?line ok = mgr_unregister_user(ManagerNode, user_alfa),
+ ok = mgr_unregister_user(ManagerNode, user_alfa),
?IPRINT("verify all agent(s): expect 2"),
case mgr_which_agents(ManagerNode) of
@@ -2120,8 +2136,8 @@ do_register_agent_old([ManagerNode], Config) ->
"~n ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("unregister user_beta agents"),
- ?line ok = mgr_unregister_agent(ManagerNode, user_beta, 5002),
- ?line ok = mgr_unregister_agent(ManagerNode, user_beta, 5003),
+ ok = mgr_unregister_agent(ManagerNode, user_beta, 5002),
+ ok = mgr_unregister_agent(ManagerNode, user_beta, 5003),
?IPRINT("verify all agent(s): expect 0"),
case mgr_which_agents(ManagerNode) of
@@ -2136,7 +2152,7 @@ do_register_agent_old([ManagerNode], Config) ->
"~n ~p", [mgr_info(ManagerNode)]),
?IPRINT("unregister user hobbe"),
- ?line ok = mgr_unregister_user(ManagerNode, user_beta),
+ ok = mgr_unregister_user(ManagerNode, user_beta),
?IPRINT("manager info: "
"~n ~p", [mgr_info(ManagerNode)]),
@@ -2144,7 +2160,7 @@ do_register_agent_old([ManagerNode], Config) ->
?SLEEP(1000),
?IPRINT("stop snmp application (with only manager)"),
- ?line ok = stop_snmp(ManagerNode),
+ ok = stop_snmp(ManagerNode),
?SLEEP(1000),
?IPRINT("end"),
@@ -2154,20 +2170,19 @@ do_register_agent_old([ManagerNode], Config) ->
%%======================================================================
-register_agent2(doc) ->
- ["Test registration of agents with the NEW interface functions"];
-register_agent2(suite) ->
- [];
+register_agent2() ->
+ [{doc, "Test registration of agents with the NEW interface functions"}].
+
register_agent2(Config) when is_list(Config) ->
Pre = fun() ->
- ManagerNode = start_manager_node(),
+ ManagerNode = start_node(register_agent2),
[ManagerNode]
end,
Case = fun(State) -> do_register_agent2(State, Config) end,
- Post = fun([ManagerNode]) -> stop_node(ManagerNode) end,
+ Post = fun([{ManagerPeer, _ManagerNode}]) -> peer:stop(ManagerPeer) end,
?TC_TRY(register_agent2, Pre, Case, Post).
-do_register_agent2([ManagerNode], Config) ->
+do_register_agent2([{_ManagerPeer, ManagerNode}], Config) ->
?IPRINT("starting with Config: "
"~n ~p", [Config]),
@@ -2184,13 +2199,13 @@ do_register_agent2([ManagerNode], Config) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("load snmp application"),
- ?line ok = load_snmp(ManagerNode),
+ ok = load_snmp(ManagerNode),
?IPRINT("set manager env for the snmp application"),
- ?line ok = set_mgr_env(ManagerNode, Opts),
+ ok = set_mgr_env(ManagerNode, Opts),
?IPRINT("starting snmp application (with only manager)"),
- ?line ok = start_snmp(ManagerNode),
+ ok = start_snmp(ManagerNode),
?IPRINT("started"),
@@ -2199,28 +2214,28 @@ do_register_agent2([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("register user(s) user_alfa & user_beta"),
- ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
- ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
+ ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
+ ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("register agent(s)"),
TargetName1 = "agent1",
- ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1,
+ ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1,
[{address, LocalHost},
{port, 5001},
{engine_id, "agentEngineId-1"}]),
TargetName2 = "agent2",
- ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2,
+ ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2,
[{address, LocalHost},
{port, 5002},
{engine_id, "agentEngineId-2"}]),
TargetName3 = "agent3",
- ?line ok = mgr_register_agent(ManagerNode, user_beta, TargetName3,
+ ok = mgr_register_agent(ManagerNode, user_beta, TargetName3,
[{address, LocalHost},
{port, 5003},
{engine_id, "agentEngineId-3"}]),
TargetName4 = "agent4",
- ?line ok = mgr_register_agent(ManagerNode, user_beta, TargetName4,
+ ok = mgr_register_agent(ManagerNode, user_beta, TargetName4,
[{address, LocalHost},
{port, 5004},
{engine_id, "agentEngineId-4"}]),
@@ -2255,7 +2270,7 @@ do_register_agent2([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("unregister user user_alfa"),
- ?line ok = mgr_unregister_user(ManagerNode, user_alfa),
+ ok = mgr_unregister_user(ManagerNode, user_alfa),
?IPRINT("verify all agent(s): expect 2"),
case mgr_which_agents(ManagerNode) of
@@ -2268,8 +2283,8 @@ do_register_agent2([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("unregister user_beta agents"),
- ?line ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName3),
- ?line ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName4),
+ ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName3),
+ ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName4),
?IPRINT("verify all agent(s): expect 0"),
case mgr_which_agents(ManagerNode) of
@@ -2283,14 +2298,14 @@ do_register_agent2([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("unregister user user_beta"),
- ?line ok = mgr_unregister_user(ManagerNode, user_beta),
+ ok = mgr_unregister_user(ManagerNode, user_beta),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?SLEEP(1000),
?IPRINT("stop snmp application (with only manager)"),
- ?line ok = stop_snmp(ManagerNode),
+ ok = stop_snmp(ManagerNode),
?SLEEP(1000),
@@ -2299,21 +2314,20 @@ do_register_agent2([ManagerNode], Config) ->
%%======================================================================
-register_agent3(doc) ->
- ["Test registration of agents with the NEW interface functions "
- "and specifying transport domain"];
-register_agent3(suite) ->
- [];
+register_agent3() ->
+ [{doc, "Test registration of agents with the NEW interface functions "
+ "and specifying transport domain"}].
+
register_agent3(Config) when is_list(Config) ->
Pre = fun() ->
- ManagerNode = start_manager_node(),
+ ManagerNode = start_node(register_agent3),
[ManagerNode]
end,
Case = fun(State) -> do_register_agent3(State, Config) end,
- Post = fun([ManagerNode]) -> stop_node(ManagerNode) end,
+ Post = fun([{ManagerPeer, _ManagerNode}]) -> peer:stop(ManagerPeer) end,
?TC_TRY(register_agent3, Pre, Case, Post).
-do_register_agent3([ManagerNode], Config) ->
+do_register_agent3([{_ManagerPeer, ManagerNode}], Config) ->
?IPRINT("starting with Config: "
"~n ~p", [Config]),
@@ -2332,13 +2346,13 @@ do_register_agent3([ManagerNode], Config) ->
?IPRINT("load snmp application"),
- ?line ok = load_snmp(ManagerNode),
+ ok = load_snmp(ManagerNode),
?IPRINT("set manager env for the snmp application"),
- ?line ok = set_mgr_env(ManagerNode, Opts),
+ ok = set_mgr_env(ManagerNode, Opts),
?IPRINT("starting snmp application (with only manager)"),
- ?line ok = start_snmp(ManagerNode),
+ ok = start_snmp(ManagerNode),
?IPRINT("started"),
@@ -2347,25 +2361,25 @@ do_register_agent3([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("register user(s) user_alfa & user_beta"),
- ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
- ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
+ ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []),
+ ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("register agent(s)"),
TargetName1 = "agent2",
- ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1,
+ ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1,
[{tdomain, transportDomainUdpIpv4},
{address, LocalHost},
{port, 5001},
{engine_id, "agentEngineId-1"}]),
TargetName2 = "agent3",
- ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2,
+ ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2,
[{tdomain, transportDomainUdpIpv6},
{address, {0,0,0,0,0,0,0,1}},
{port, 5002},
{engine_id, "agentEngineId-2"}]),
TargetName3 = "agent4",
- ?line {error, {unsupported_domain, _} = Reason4} =
+ {error, {unsupported_domain, _} = Reason4} =
mgr_register_agent(ManagerNode, user_beta, TargetName3,
[{tdomain, transportDomainTcpIpv4},
{address, LocalHost},
@@ -2373,7 +2387,7 @@ do_register_agent3([ManagerNode], Config) ->
{engine_id, "agentEngineId-3"}]),
?IPRINT("Expected registration failure: ~p", [Reason4]),
TargetName4 = "agent5",
- ?line {error, {unknown_domain, _} = Reason5} =
+ {error, {unknown_domain, _} = Reason5} =
mgr_register_agent(ManagerNode, user_beta, TargetName4,
[{tdomain, transportDomainUdpIpv4_bad},
{address, LocalHost},
@@ -2411,7 +2425,7 @@ do_register_agent3([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("unregister user user_alfa"),
- ?line ok = mgr_unregister_user(ManagerNode, user_alfa),
+ ok = mgr_unregister_user(ManagerNode, user_alfa),
?IPRINT("verify all agent(s): expect 0"),
case mgr_which_agents(ManagerNode) of
@@ -2435,14 +2449,14 @@ do_register_agent3([ManagerNode], Config) ->
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?IPRINT("unregister user user_beta"),
- ?line ok = mgr_unregister_user(ManagerNode, user_beta),
+ ok = mgr_unregister_user(ManagerNode, user_beta),
?IPRINT("manager info: ~p~n", [mgr_info(ManagerNode)]),
?SLEEP(1000),
?IPRINT("stop snmp application (with only manager)"),
- ?line ok = stop_snmp(ManagerNode),
+ ok = stop_snmp(ManagerNode),
?SLEEP(1000),
@@ -2451,9 +2465,9 @@ do_register_agent3([ManagerNode], Config) ->
%%======================================================================
-simple_sync_get3(doc) ->
- ["Simple sync get-request - Version 3 API (TargetName and send-opts)"];
-simple_sync_get3(suite) -> [];
+simple_sync_get3() ->
+ [{doc, "Simple sync get-request - Version 3 API (TargetName and send-opts)"}].
+
simple_sync_get3(Config) when is_list(Config) ->
?TC_TRY(simple_sync_get3,
fun() -> do_simple_sync_get3(Config) end).
@@ -2493,12 +2507,12 @@ do_simple_sync_get3(Config, Get, PostVerify) ->
?IPRINT("issue get-request without loading the mib"),
Oids1 = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance],
- ?line ok = do_simple_sync_get3(Node, TargetName, Oids1, Get, PostVerify),
+ ok = do_simple_sync_get3(Node, TargetName, Oids1, Get, PostVerify),
?IPRINT("issue get-request after first loading the mibs"),
- ?line ok = mgr_user_load_mib(Node, std_mib()),
+ ok = mgr_user_load_mib(Node, std_mib()),
Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]],
- ?line ok = do_simple_sync_get3(Node, TargetName, Oids2, Get, PostVerify),
+ ok = do_simple_sync_get3(Node, TargetName, Oids2, Get, PostVerify),
ok.
do_simple_sync_get3(Node, TargetName, Oids, Get, PostVerify)
@@ -2506,7 +2520,7 @@ do_simple_sync_get3(Node, TargetName, Oids, Get, PostVerify)
?IPRINT("try get for ~p (on ~p):"
"~n Oids: ~p", [TargetName, Node, Oids]),
- ?line Reply =
+ Reply =
case Get(Node, TargetName, Oids) of
{ok, R, _Rem} ->
?IPRINT("get reply: "
@@ -2522,7 +2536,7 @@ do_simple_sync_get3(Node, TargetName, Oids, Get, PostVerify)
%% verify that the operation actually worked:
%% The order should be the same, so no need to search
- ?line ok = case Reply of
+ ok = case Reply of
{noError, 0, [#varbind{oid = ?sysObjectID_instance,
value = SysObjectID},
#varbind{oid = ?sysDescr_instance,
@@ -2582,9 +2596,9 @@ sag_verify_vbs([Vb|_], [E|_]) ->
%%======================================================================
-simple_async_get3(doc) ->
- ["Simple (async) get-request - Version 3 API (TargetName and send-opts)"];
-simple_async_get3(suite) -> [];
+simple_async_get3() ->
+ [{doc, "Simple (async) get-request - Version 3 API (TargetName and send-opts)"}].
+
simple_async_get3(Config) when is_list(Config) ->
?TC_TRY(simple_async_get3,
fun() -> do_simple_async_get3(Config) end).
@@ -2613,10 +2627,10 @@ do_simple_async_get3(Config) ->
Res.
do_simple_async_sync_get3(Config, MgrNode, AgentNode, Get, PostVerify) ->
- ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ ok = mgr_user_load_mib(MgrNode, std_mib()),
Test2Mib = test2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
do_simple_async_sync_get3(fun() -> mgr_info(MgrNode) end,
fun() -> agent_info(AgentNode) end,
Get, PostVerify).
@@ -2666,7 +2680,7 @@ do_simple_async_sync_get3(MgrInfo, AgentInfo, Get, PostVerify)
?IPRINT("agent info when starting test: "
"~n ~p", [AgentInfo()]),
- ?line ok = async_exec(Requests, []),
+ ok = async_exec(Requests, []),
?IPRINT("manager info when ending test: "
"~n ~p", [MgrInfo()]),
@@ -2715,10 +2729,10 @@ check_ssgn_vbs([Vb|_], [E|_]) ->
%%======================================================================
-simple_sync_get_next3(doc) ->
- ["Simple (sync) get_next-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_sync_get_next3(suite) -> [];
+simple_sync_get_next3() ->
+ [{doc, "Simple (sync) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_sync_get_next3(Config) when is_list(Config) ->
process_flag(trap_exit, true),
put(tname, ssgn3),
@@ -2753,32 +2767,32 @@ do_simple_sync_get_next3(Config, GetNext, PostVerify)
%% -- 1 --
Oids01 = [[1,3,7,1]],
VF01 = fun(X) -> verify_ssgn_reply1(X, [{[1,3,7,1],endOfMibView}]) end,
- ?line ok = do_simple_get_next(1,
+ ok = do_simple_get_next(1,
MgrNode, TargetName, Oids01, VF01,
GetNext, PostVerify),
- ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ ok = mgr_user_load_mib(MgrNode, std_mib()),
%% -- 2 --
Oids02 = [[sysDescr], [1,3,7,1]],
VF02 = fun(X) ->
verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView])
end,
- ?line ok = do_simple_get_next(2,
+ ok = do_simple_get_next(2,
MgrNode, TargetName, Oids02, VF02,
GetNext, PostVerify),
Test2Mib = test2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
%% -- 3 --
- ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
+ {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
Oids03 = [[TCnt2, 1]],
VF03 = fun(X) ->
verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}])
end,
- ?line ok = do_simple_get_next(3,
+ ok = do_simple_get_next(3,
MgrNode, TargetName, Oids03, VF03,
GetNext, PostVerify),
@@ -2787,48 +2801,48 @@ do_simple_sync_get_next3(Config, GetNext, PostVerify)
VF04 = fun(X) ->
verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}])
end,
- ?line ok = do_simple_get_next(4,
+ ok = do_simple_get_next(4,
MgrNode, TargetName, Oids04, VF04,
GetNext, PostVerify),
%% -- 5 --
- ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1),
+ {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1),
Oids05 = [TGenErr1],
VF05 = fun(X) ->
verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]})
end,
- ?line ok = do_simple_get_next(5,
+ ok = do_simple_get_next(5,
MgrNode, TargetName, Oids05, VF05,
GetNext, PostVerify),
%% -- 6 --
- ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2),
+ {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2),
Oids06 = [TGenErr2],
VF06 = fun(X) ->
verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]})
end,
- ?line ok = do_simple_get_next(6,
+ ok = do_simple_get_next(6,
MgrNode, TargetName, Oids06, VF06,
GetNext, PostVerify),
%% -- 7 --
- ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3),
+ {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3),
Oids07 = [[sysDescr], TGenErr3],
VF07 = fun(X) ->
verify_ssgn_reply2(X, {genErr, 2,
[?sysDescr, TGenErr3]})
end,
- ?line ok = do_simple_get_next(7,
+ ok = do_simple_get_next(7,
MgrNode, TargetName, Oids07, VF07,
GetNext, PostVerify),
%% -- 8 --
- ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig),
+ {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig),
Oids08 = [TTooBig],
VF08 = fun(X) ->
verify_ssgn_reply2(X, {tooBig, 0, []})
end,
- ?line ok = do_simple_get_next(8,
+ ok = do_simple_get_next(8,
MgrNode, TargetName, Oids08, VF08,
GetNext, PostVerify),
ok.
@@ -2850,24 +2864,24 @@ do_simple_get_next(N, Node, TargetName, Oids, Verify, GetNext, PostVerify) ->
%%======================================================================
-simple_async_get_next3_cbp_def(doc) ->
- ["Simple (async) get_next-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_async_get_next3_cbp_def(suite) -> [];
+simple_async_get_next3_cbp_def() ->
+ [{doc, "Simple (async) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_async_get_next3_cbp_def(Config) when is_list(Config) ->
simple_async_get_next3(ssgn2_cbp_def, Config).
-simple_async_get_next3_cbp_temp(doc) ->
- ["Simple (async) get_next-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_async_get_next3_cbp_temp(suite) -> [];
+simple_async_get_next3_cbp_temp() ->
+ [{doc, "Simple (async) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_async_get_next3_cbp_temp(Config) when is_list(Config) ->
simple_async_get_next3(ssgn2_cbp_temp, Config).
-simple_async_get_next3_cbp_perm(doc) ->
- ["Simple (async) get_next-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_async_get_next3_cbp_perm(suite) -> [];
+simple_async_get_next3_cbp_perm() ->
+ [{doc, "Simple (async) get_next-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_async_get_next3_cbp_perm(Config) when is_list(Config) ->
simple_async_get_next3(ssgn2_cbp_perm, Config).
@@ -2884,10 +2898,10 @@ do_simple_async_get_next3(Config) ->
AgentNode = ?config(agent_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
- ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ ok = mgr_user_load_mib(MgrNode, std_mib()),
Test2Mib = test2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
Self = self(),
Msg = simple_async_get_next3,
@@ -2911,11 +2925,11 @@ do_simple_async_get_next3(Config) ->
do_simple_async_get_next3(MgrNode, AgentNode, GetNext, PostVerify)
when is_function(GetNext, 1) andalso is_function(PostVerify, 1) ->
- ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
- ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1),
- ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2),
- ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3),
- ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig),
+ {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
+ {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1),
+ {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2),
+ {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3),
+ {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig),
Requests =
[
@@ -2983,7 +2997,7 @@ do_simple_async_get_next3(MgrNode, AgentNode, GetNext, PostVerify)
?IPRINT("agent info when starting test: "
"~n ~p", [agent_info(AgentNode)]),
- ?line ok = async_exec(Requests, []),
+ ok = async_exec(Requests, []),
?IPRINT("manager info when ending test: "
"~n ~p", [mgr_info(MgrNode)]),
@@ -3012,9 +3026,9 @@ value_of_vavs([{_Oid, Val}|VAVs], Acc) ->
%%======================================================================
-simple_sync_set3(doc) ->
- ["Simple (sync) set-request - Version 3 API (TargetName with send-opts)"];
-simple_sync_set3(suite) -> [];
+simple_sync_set3() ->
+ [{doc, "Simple (sync) set-request - Version 3 API (TargetName with send-opts)"}].
+
simple_sync_set3(Config) when is_list(Config) ->
?TC_TRY(simple_sync_set3,
fun() -> do_simple_sync_set3(Config) end).
@@ -3054,22 +3068,22 @@ do_simple_sync_set3(Config, Set, PostVerify)
{?sysName_instance, s, Val11},
{?sysLocation_instance, s, Val12}
],
- ?line ok = do_simple_set3(Node, TargetName, VAVs1, Set, PostVerify),
+ ok = do_simple_set3(Node, TargetName, VAVs1, Set, PostVerify),
?IPRINT("issue set-request after first loading the mibs"),
- ?line ok = mgr_user_load_mib(Node, std_mib()),
+ ok = mgr_user_load_mib(Node, std_mib()),
Val21 = "Sune Anka",
Val22 = "Gothenburg",
VAVs2 = [
{[sysName, 0], Val21},
{[sysLocation, 0], Val22}
],
- ?line ok = do_simple_set3(Node, TargetName, VAVs2, Set, PostVerify),
+ ok = do_simple_set3(Node, TargetName, VAVs2, Set, PostVerify),
ok.
do_simple_set3(Node, TargetName, VAVs, Set, PostVerify) ->
[SysName, SysLoc] = value_of_vavs(VAVs),
- ?line {ok, Reply, _Rem} = Set(Node, TargetName, VAVs),
+ {ok, Reply, _Rem} = Set(Node, TargetName, VAVs),
?DBG("~n Reply: ~p"
"~n Rem: ~w", [Reply, _Rem]),
@@ -3077,7 +3091,7 @@ do_simple_set3(Node, TargetName, VAVs, Set, PostVerify) ->
%% verify that the operation actually worked:
%% The order should be the same, so no need to search
%% The value we get should be exactly the same as we sent
- ?line ok = case Reply of
+ ok = case Reply of
{noError, 0, [#varbind{oid = ?sysName_instance,
value = SysName},
#varbind{oid = ?sysLocation_instance,
@@ -3127,21 +3141,21 @@ sas_verify_vbs([Vb|_], [E|_]) ->
%%======================================================================
-simple_async_set3_cbp_def(doc) ->
- ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
-simple_async_set3_cbp_def(suite) -> [];
+simple_async_set3_cbp_def() ->
+ [{doc, "Simple (async) set-request - Version 3 API (TargetName with send-opts)"}].
+
simple_async_set3_cbp_def(Config) when is_list(Config) ->
simple_async_set3(sas3_cbp_def, Config).
-simple_async_set3_cbp_temp(doc) ->
- ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
-simple_async_set3_cbp_temp(suite) -> [];
+simple_async_set3_cbp_temp() ->
+ [{doc, "Simple (async) set-request - Version 3 API (TargetName with send-opts)"}].
+
simple_async_set3_cbp_temp(Config) when is_list(Config) ->
simple_async_set3(sas3_cbp_temp, Config).
-simple_async_set3_cbp_perm(doc) ->
- ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"];
-simple_async_set3_cbp_perm(suite) -> [];
+simple_async_set3_cbp_perm() ->
+ [{doc, "Simple (async) set-request - Version 3 API (TargetName with send-opts)"}].
+
simple_async_set3_cbp_perm(Config) when is_list(Config) ->
simple_async_set3(sas3_cbp_perm, Config).
@@ -3157,10 +3171,10 @@ do_simple_async_set3(Config) ->
AgentNode = ?config(agent_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
- ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ ok = mgr_user_load_mib(MgrNode, std_mib()),
Test2Mib = test2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
Self = self(),
Msg = simple_async_set3,
@@ -3217,7 +3231,7 @@ do_simple_async_set3(MgrNode, AgentNode, Set, PostVerify) ->
?IPRINT("agent info when starting test: "
"~n ~p", [agent_info(AgentNode)]),
- ?line ok = async_exec(Requests, []),
+ ok = async_exec(Requests, []),
?IPRINT("manager info when ending test: "
"~n ~p", [mgr_info(MgrNode)]),
@@ -3270,10 +3284,10 @@ check_ssgb_vbs([R|_], [E|_]) ->
%%======================================================================
-simple_sync_get_bulk3(doc) ->
- ["Simple (sync) get_bulk-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_sync_get_bulk3(suite) -> [];
+simple_sync_get_bulk3() ->
+ [{doc, "Simple (sync) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_sync_get_bulk3(Config) when is_list(Config) ->
?TC_TRY(simple_sync_get_bulk3,
fun() -> do_simple_sync_get_bulk3(Config) end).
@@ -3310,34 +3324,34 @@ do_simple_sync_get_bulk3(Config) ->
do_simple_sync_get_bulk3(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
%% -- 1 --
- ?line ok = do_simple_get_bulk3(1,
+ ok = do_simple_get_bulk3(1,
1, 1, [],
fun verify_ssgb_reply1/1,
GetBulk, PostVerify),
%% -- 2 --
- ?line ok = do_simple_get_bulk3(2,
+ ok = do_simple_get_bulk3(2,
-1, 1, [],
fun verify_ssgb_reply1/1,
GetBulk, PostVerify),
%% -- 3 --
- ?line ok = do_simple_get_bulk3(3,
+ ok = do_simple_get_bulk3(3,
-1, -1, [],
fun verify_ssgb_reply1/1,
GetBulk, PostVerify),
- ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ ok = mgr_user_load_mib(MgrNode, std_mib()),
%% -- 4 --
VF04 = fun(X) ->
verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView])
end,
- ?line ok = do_simple_get_bulk3(4,
+ ok = do_simple_get_bulk3(4,
2, 0, [[sysDescr],[1,3,7,1]], VF04,
GetBulk, PostVerify),
%% -- 5 --
- ?line ok = do_simple_get_bulk3(5,
+ ok = do_simple_get_bulk3(5,
1, 2, [[sysDescr],[1,3,7,1]], VF04,
GetBulk, PostVerify),
@@ -3347,7 +3361,7 @@ do_simple_sync_get_bulk3(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
[?sysDescr_instance, endOfMibView,
?sysObjectID_instance, endOfMibView])
end,
- ?line ok = do_simple_get_bulk3(6,
+ ok = do_simple_get_bulk3(6,
0, 2, [[sysDescr],[1,3,7,1]], VF06,
GetBulk, PostVerify),
@@ -3358,15 +3372,15 @@ do_simple_sync_get_bulk3(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
?sysDescr_instance, endOfMibView,
?sysObjectID_instance, endOfMibView])
end,
- ?line ok = do_simple_get_bulk3(7,
+ ok = do_simple_get_bulk3(7,
2, 2,
[[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]],
VF07,
GetBulk, PostVerify),
Test2Mib = test2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
%% -- 8 --
VF08 = fun(X) ->
@@ -3374,14 +3388,14 @@ do_simple_sync_get_bulk3(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
[?sysDescr_instance,
?sysDescr_instance])
end,
- ?line ok = do_simple_get_bulk3(8,
+ ok = do_simple_get_bulk3(8,
1, 2,
[[sysDescr],[sysDescr],[tTooBig]],
VF08,
GetBulk, PostVerify),
%% -- 9 --
- ?line ok = do_simple_get_bulk3(9,
+ ok = do_simple_get_bulk3(9,
1, 12,
[[tDescr2], [sysDescr]],
fun verify_ssgb_reply1/1,
@@ -3395,7 +3409,7 @@ do_simple_sync_get_bulk3(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
{?tGenErr1, 'NULL'},
{?sysDescr, 'NULL'}])
end,
- ?line ok = do_simple_get_bulk3(10,
+ ok = do_simple_get_bulk3(10,
2, 2,
[[sysDescr],
[sysObjectID],
@@ -3405,14 +3419,14 @@ do_simple_sync_get_bulk3(Config, MgrNode, AgentNode, GetBulk, PostVerify) ->
GetBulk, PostVerify),
%% -- 11 --
- ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
+ {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
?IPRINT("TCnt2: ~p", [TCnt2]),
VF11 = fun(X) ->
verify_ssgb_reply2(X,
[{fl([TCnt2,2]), 100},
{fl([TCnt2,2]), endOfMibView}])
end,
- ?line ok = do_simple_get_bulk3(11,
+ ok = do_simple_get_bulk3(11,
0, 2,
[[TCnt2, 1]], VF11,
GetBulk, PostVerify),
@@ -3440,10 +3454,10 @@ do_simple_get_bulk3(N,
%%======================================================================
-simple_async_get_bulk3_cbp_def(doc) ->
- ["Simple (async) get_bulk-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_async_get_bulk3_cbp_def(suite) -> [];
+simple_async_get_bulk3_cbp_def() ->
+ [{doc, "Simple (async) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_async_get_bulk3_cbp_def(Config) when is_list(Config) ->
simple_async_get_bulk3(sagb3_cbp_def, Config).
@@ -3460,10 +3474,10 @@ do_simple_async_get_bulk3(Config) ->
AgentNode = ?config(agent_node, Config),
TargetName = ?config(manager_agent_target_name, Config),
- ?line ok = mgr_user_load_mib(MgrNode, std_mib()),
+ ok = mgr_user_load_mib(MgrNode, std_mib()),
Test2Mib = test2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
Self = self(),
Msg = simple_async_get_bulk3,
@@ -3519,7 +3533,7 @@ do_simple_async_get_bulk3(MgrNode, AgentNode, GetBulk, PostVerify) ->
{?tGenErr1, 'NULL'},
{?sysDescr, 'NULL'}]))
end,
- ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
+ {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2),
VF11 = fun(X) ->
PostVerify(
verify_ssgb_reply2(X,
@@ -3602,7 +3616,7 @@ do_simple_async_get_bulk3(MgrNode, AgentNode, GetBulk, PostVerify) ->
?IPRINT("agent info when starting test: "
"~n ~p", [agent_info(AgentNode)]),
- ?line ok = async_exec(Requests, []),
+ ok = async_exec(Requests, []),
?IPRINT("manager info when ending test: "
"~n ~p", [mgr_info(MgrNode)]),
@@ -3618,59 +3632,59 @@ async_gb_exec3(Node, TargetName, {NR, MR, Oids}, SendOpts) ->
%%======================================================================
-simple_async_get_bulk3_cbp_temp(doc) ->
- ["Simple (async) get_bulk-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_async_get_bulk3_cbp_temp(suite) -> [];
+simple_async_get_bulk3_cbp_temp() ->
+ [{doc, "Simple (async) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_async_get_bulk3_cbp_temp(Config) when is_list(Config) ->
simple_async_get_bulk3(sagb3_cbp_temp, Config).
%%======================================================================
-simple_async_get_bulk3_cbp_perm(doc) ->
- ["Simple (async) get_bulk-request - "
- "Version 3 API (TargetName with send-opts)"];
-simple_async_get_bulk3_cbp_perm(suite) -> [];
+simple_async_get_bulk3_cbp_perm() ->
+ [{doc, "Simple (async) get_bulk-request - "
+ "Version 3 API (TargetName with send-opts)"}].
+
simple_async_get_bulk3_cbp_perm(Config) when is_list(Config) ->
simple_async_get_bulk3(sagb3_cbp_perm, Config).
%%======================================================================
-simple_v3_exchange_md5(doc) ->
- ["Simple message exchange using v3 (MD5) messages"];
-simple_v3_exchange_md5(suite) -> [];
+simple_v3_exchange_md5() ->
+ [{doc, "Simple message exchange using v3 (MD5) messages"}].
+
simple_v3_exchange_md5(Config) when is_list(Config) ->
simple_v3_exchange(Config).
-simple_v3_exchange_sha(doc) ->
- ["Simple message exchange using v3 (SHA) messages"];
-simple_v3_exchange_sha(suite) -> [];
+simple_v3_exchange_sha() ->
+ [{doc, "Simple message exchange using v3 (SHA) messages"}].
+
simple_v3_exchange_sha(Config) when is_list(Config) ->
simple_v3_exchange(Config).
-simple_v3_exchange_sha224(doc) ->
- ["Simple message exchange using v3 (SHA224) messages"];
-simple_v3_exchange_sha224(suite) -> [];
+simple_v3_exchange_sha224() ->
+ [{doc, "Simple message exchange using v3 (SHA224) messages"}].
+
simple_v3_exchange_sha224(Config) when is_list(Config) ->
simple_v3_exchange(Config).
-simple_v3_exchange_sha256(doc) ->
- ["Simple message exchange using v3 (SHA256) messages"];
-simple_v3_exchange_sha256(suite) -> [];
+simple_v3_exchange_sha256() ->
+ [{doc, "Simple message exchange using v3 (SHA256) messages"}].
+
simple_v3_exchange_sha256(Config) when is_list(Config) ->
simple_v3_exchange(Config).
-simple_v3_exchange_sha384(doc) ->
- ["Simple message exchange using v3 (SHA384) messages"];
-simple_v3_exchange_sha384(suite) -> [];
+simple_v3_exchange_sha384() ->
+ [{doc, "Simple message exchange using v3 (SHA384) messages"}].
+
simple_v3_exchange_sha384(Config) when is_list(Config) ->
simple_v3_exchange(Config).
-simple_v3_exchange_sha512(doc) ->
- ["Simple message exchange using v3 (SHA512) messages"];
-simple_v3_exchange_sha512(suite) -> [];
+simple_v3_exchange_sha512() ->
+ [{doc, "Simple message exchange using v3 (SHA512) messages"}].
+
simple_v3_exchange_sha512(Config) when is_list(Config) ->
simple_v3_exchange(Config).
@@ -3707,7 +3721,6 @@ simple_v3_exchange(Config) when is_list(Config) ->
%%======================================================================
-discovery(suite) -> [];
discovery(Config) when is_list(Config) ->
?SKIP(not_yet_implemented).
@@ -3772,7 +3785,6 @@ verify_trap(Trap, [{Id, Verifier}|Verifiers]) ->
%%======================================================================
-trap1(suite) -> [];
trap1(Config) when is_list(Config) ->
?TC_TRY(trap1,
fun() -> do_trap1(Config) end).
@@ -3785,16 +3797,16 @@ do_trap1(Config) ->
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
%% Version 1 trap verification function:
VerifyTrap_v1 =
@@ -3933,7 +3945,6 @@ do_trap1(Config) ->
%%======================================================================
-trap2(suite) -> [];
trap2(Config) when is_list(Config) ->
?TC_TRY(trap2,
fun() -> do_trap2(Config) end).
@@ -3946,16 +3957,16 @@ do_trap2(Config) ->
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
%% Version 1 trap verification function:
VerifyTrap_v1 =
@@ -4132,7 +4143,6 @@ do_trap2(Config) ->
%%======================================================================
-inform1(suite) -> [];
inform1(Config) when is_list(Config) ->
?TC_TRY(inform1,
fun() -> do_inform1(Config) end).
@@ -4145,16 +4155,16 @@ do_inform1(Config) ->
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
Cmd1 =
@@ -4252,7 +4262,7 @@ do_inform1(Config) ->
Commands =
[
{1, "Manager and agent info at start of test", Cmd1},
- {2, "Send notifcation [no receiver] from agent", Cmd2},
+ {2, "Send notification [no receiver] from agent", Cmd2},
{3, "Await first inform to manager - do not reply", Cmd3},
{4, "Await second inform to manager - reply", Cmd4},
{5, "Sleep some time (5 sec)", Cmd5},
@@ -4266,7 +4276,6 @@ do_inform1(Config) ->
%%======================================================================
-inform2(suite) -> [];
inform2(Config) when is_list(Config) ->
?TC_TRY(inform2,
fun() -> do_inform2(Config) end).
@@ -4281,16 +4290,16 @@ do_inform2(Config) ->
%% Addr = ?config(ip, Config),
%% Port = ?AGENT_PORT,
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
Cmd1 =
fun() ->
@@ -4428,7 +4437,7 @@ do_inform2(Config) ->
Commands =
[
{1, "Manager and agent info at start of test", Cmd1},
- {2, "Send notifcation [no receiver] from agent", Cmd2},
+ {2, "Send notification [no receiver] from agent", Cmd2},
{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},
@@ -4444,7 +4453,6 @@ do_inform2(Config) ->
%%======================================================================
-inform3(suite) -> [];
inform3(Config) when is_list(Config) ->
?TC_TRY(inform3,
fun() -> do_inform3(Config) end).
@@ -4456,16 +4464,16 @@ do_inform3(Config) ->
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
Cmd1 =
fun() ->
@@ -4567,7 +4575,7 @@ do_inform3(Config) ->
Commands =
[
{1, "Manager and agent info at start of test", Cmd1},
- {2, "Send notifcation from agent", Cmd2},
+ {2, "Send notification from agent", Cmd2},
{3, "await inform-sent acknowledge from agent", Cmd3},
{4, "Await first inform to manager - do not reply", Cmd4},
{5, "Await first inform to manager - do not reply", Cmd4},
@@ -4584,7 +4592,6 @@ do_inform3(Config) ->
%%======================================================================
-inform4(suite) -> [];
inform4(Config) when is_list(Config) ->
?TC_TRY(inform4,
fun() -> do_inform4(Config) end).
@@ -4596,16 +4603,16 @@ do_inform4(Config) ->
MgrNode = ?config(manager_node, Config),
AgentNode = ?config(agent_node, Config),
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
Cmd1 =
fun() ->
@@ -4693,7 +4700,7 @@ do_inform4(Config) ->
Commands =
[
{1, "Manager and agent info at start of test", Cmd1},
- {2, "Send notifcation [no receiver] from agent", Cmd2},
+ {2, "Send notification [no receiver] from agent", Cmd2},
{3, "Await inform to manager", Cmd3},
%% {4, "Await error info (because of erroneous config)", Cmd4},
{5, "Sleep some time (1 sec)", Cmd5},
@@ -4709,15 +4716,12 @@ do_inform4(Config) ->
%%
%% Test: ts:run(snmp, snmp_manager_test, inform_swarm_cbp_def, [batch]).
-inform_swarm_cbp_def(suite) -> [];
inform_swarm_cbp_def(Config) when is_list(Config) ->
inform_swarm(is_cbp_def, 1500, Config).
-inform_swarm_cbp_temp(suite) -> [];
inform_swarm_cbp_temp(Config) when is_list(Config) ->
inform_swarm(is_cbp_temp, 1500, Config).
-inform_swarm_cbp_perm(suite) -> [];
inform_swarm_cbp_perm(Config) when is_list(Config) ->
inform_swarm(is_cbp_perm, 1800, Config).
@@ -4736,16 +4740,16 @@ do_inform_swarm(NumI, Config) ->
AgentNode = ?config(agent_node, Config),
Factor = ?config(snmp_factor, Config),
- ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
+ ok = mgr_user_load_mib(MgrNode, snmpv2_mib()),
Test2Mib = test2_mib(Config),
TestTrapMib = test_trap_mib(Config),
TestTrapv2Mib = test_trap_v2_mib(Config),
- ?line ok = mgr_user_load_mib(MgrNode, Test2Mib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib),
- ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
- ?line ok = agent_load_mib(AgentNode, Test2Mib),
- ?line ok = agent_load_mib(AgentNode, TestTrapMib),
- ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib),
+ ok = mgr_user_load_mib(MgrNode, Test2Mib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapMib),
+ ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib),
+ ok = agent_load_mib(AgentNode, Test2Mib),
+ ok = agent_load_mib(AgentNode, TestTrapMib),
+ ok = agent_load_mib(AgentNode, TestTrapv2Mib),
NumInforms = NumI div Factor,
Collector = self(),
@@ -4807,7 +4811,7 @@ do_inform_swarm(NumI, Config) ->
Commands =
[
{1, "Manager and agent info at start of test", Cmd1},
- {2, ?F("Send ~p notifcation(s) from agent", [NumInforms]), Cmd2},
+ {2, ?F("Send ~p notification(s) from agent", [NumInforms]), Cmd2},
{3, "Await send-ack(s)/inform(s)/response(s)", Cmd3},
{4, "Sleep some time (1 sec)", Cmd4},
{5, "Manager and agent info after test completion", Cmd1}
@@ -4823,7 +4827,7 @@ inform_swarm_collector(N) ->
%% Note that we need to deal with re-transmissions!
%% That is, the agent did not receive the ack in time,
-%% and therefor did a re-transmit. This means that we
+%% and therefore did a re-transmit. This means that we
%% expect to receive more inform's then we actually
%% sent. So for success we assume:
%%
@@ -4900,7 +4904,6 @@ inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, Timeout) ->
%%======================================================================
-report(suite) -> [];
report(Config) when is_list(Config) ->
?SKIP(not_yet_implemented).
@@ -4908,8 +4911,9 @@ report(Config) when is_list(Config) ->
%%======================================================================
-otp8015_1(doc) -> ["OTP-8015:1 - testing the new api-function."];
-otp8015_1(suite) -> [];
+otp8015_1() ->
+ [{doc, "OTP-8015:1 - testing the new api-function."}].
+
otp8015_1(Config) when is_list(Config) ->
Pre = fun() ->
SCO = ?config(socket_create_opts, Config),
@@ -4965,8 +4969,9 @@ do_otp8015_1(Config) ->
%%======================================================================
-otp8395_1(doc) -> ["OTP-8395:1 - simple get with ATL sequence numbering."];
-otp8395_1(suite) -> [];
+otp8395_1() ->
+ [{doc, "OTP-8395:1 - simple get with ATL sequence numbering."}].
+
otp8395_1(Config) when is_list(Config) ->
?TC_TRY(otp8395_1,
fun() -> do_otp8395_1(Config) end).
@@ -4984,7 +4989,7 @@ async_exec([], Acc) ->
async_verify(async_collector(Acc, []));
async_exec([{Id, Data, Exec, Ver}|Reqs], Acc) ->
?IPRINT("issue async request ~w", [Id]),
- ?line {ok, ReqId} = Exec(Data),
+ {ok, ReqId} = Exec(Data),
async_exec(Reqs, [{ReqId, Id, Ver}|Acc]).
async_collector([], Acc) ->
@@ -5079,17 +5084,17 @@ command_handler([{No, Desc, Cmd}|Cmds]) ->
{error, Reason} ->
?EPRINT("Command_handler -> ~w error: "
"~n ~p", [No, Reason]),
- ?line ?FAIL({command_failed, No, Reason});
+ ?FAIL({command_failed, No, Reason});
Error ->
?EPRINT("Command_handler -> ~w unexpected: "
"~n ~p", [No, Error]),
- ?line ?FAIL({unexpected_command_result, No, Error})
+ ?FAIL({unexpected_command_result, No, Error})
end.
%% -- Misc manager functions --
-init_manager(AutoInform, Config) ->
+init_manager(Case, AutoInform, Config) ->
?IPRINT("init_manager -> entry with"
"~n AutoInform: ~p"
@@ -5099,7 +5104,7 @@ init_manager(AutoInform, Config) ->
%% Start node
%%
- ?line Node = start_manager_node(),
+ {Peer, Node} = start_node(lists:concat([Case, "-mgr"])),
%% The point with this (try catch block) is to be
%% able to do some cleanup in case we fail to
@@ -5114,13 +5119,13 @@ init_manager(AutoInform, Config) ->
%% Start and initiate crypto on manager node
%%
- ?line ok = init_crypto(Node),
+ ok = init_crypto(Node),
%%
%% Write manager config
%%
- ?line ok = write_manager_config(Config),
+ ok = write_manager_config(Config),
IRB = case AutoInform of
true ->
@@ -5128,7 +5133,7 @@ init_manager(AutoInform, Config) ->
_ ->
user
end,
- Conf = [{manager_node, Node}, {irb, IRB} | Config],
+ Conf = [{manager_node, Node}, {manager_peer, Peer}, {irb, IRB} | Config],
Vsns = [v1,v2,v3],
start_manager(Node, Vsns, Conf)
end
@@ -5138,7 +5143,7 @@ init_manager(AutoInform, Config) ->
"~n Reason: ~p"
"~n StackTrace: ~p", [Reason, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
erlang:raise(C, E, S);
C:E:S ->
?EPRINT("Failure during manager start: "
@@ -5146,11 +5151,11 @@ init_manager(AutoInform, Config) ->
"~n Error: ~p"
"~n StackTrace: ~p", [C, E, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
?FAIL({failed_starting_manager, C, E, S})
end.
-init_v3_manager(Config) ->
+init_v3_manager(Case, Config) ->
?IPRINT("init_v3_manager -> entry with"
"~n Config: ~p", [Config]),
@@ -5159,8 +5164,7 @@ init_v3_manager(Config) ->
%% Start node
%%
- %% ?line Node = self(),
- ?line Node = start_unique_manager_node(),
+ {Peer, Node} = start_node(lists:concat([Case, "-v3mgr"])),
%% The point with this (try catch block) is to be
%% able to do some cleanup in case we fail to
@@ -5175,7 +5179,7 @@ init_v3_manager(Config) ->
%% Start and initiate crypto on manager node
%%
- ?line ok = init_crypto(Node),
+ ok = init_crypto(Node),
%%
%% Write manager config
@@ -5183,10 +5187,10 @@ init_v3_manager(Config) ->
%% DomainType is just a "dummy" arg to make the
%% function choose transportDomainUdpIpv4 as transport domain.
- ?line ok = write_manager_config(transport, Config),
+ ok = write_manager_config(transport, Config),
IRB = auto,
- Conf = [{manager_node, Node}, {irb, IRB} | Config],
+ Conf = [{manager_node, Node}, {manager_peer, Peer}, {irb, IRB} | Config],
Vsns = [v3],
start_manager(Node, Vsns, Conf)
end
@@ -5196,7 +5200,7 @@ init_v3_manager(Config) ->
"~n Reason: ~p"
"~n StackTrace: ~p", [Reason, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
erlang:raise(C, E, S);
C:E:S ->
?EPRINT("Failure during manager start: "
@@ -5204,7 +5208,7 @@ init_v3_manager(Config) ->
"~n Error: ~p"
"~n StackTrace: ~p", [C, E, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
?FAIL({failed_starting_manager, C, E, S})
end.
@@ -5215,7 +5219,7 @@ fin_manager(Config) ->
Node = ?config(manager_node, Config),
StopMgrRes = stop_manager(Node),
StopCryptoRes = fin_crypto(Node),
- StopNode = stop_node(Node),
+ StopNode = peer:stop(?config(manager_peer, Config)),
?IPRINT("fin_manager -> stop apps and (mgr node ~p) node results: "
"~n SNMP Mgr: ~p"
"~n Crypto: ~p"
@@ -5226,7 +5230,7 @@ fin_manager(Config) ->
%% -- Misc agent functions --
-init_agent(Config) ->
+init_agent(Case, Config) ->
?IPRINT("init_agent -> entry with"
"~n Config: ~p", [Config]),
@@ -5240,7 +5244,7 @@ init_agent(Config) ->
%% Start node
%%
- ?line Node = start_agent_node(),
+ {Peer, Node} = start_node(lists:concat([Case, "-agent"])),
%% The point with this (try catch block) is to be
%% able to do some cleanup in case we fail to
@@ -5255,14 +5259,14 @@ init_agent(Config) ->
%% Start and initiate mnesia on agent node
%%
- ?line ok = init_mnesia(Node, Dir, ?config(mnesia_debug, Config)),
+ ok = init_mnesia(Node, Dir, ?config(mnesia_debug, Config)),
%% --
%% Start and initiate crypto on agent node
%%
- ?line ok = init_crypto(Node),
+ ok = init_crypto(Node),
%%
@@ -5270,9 +5274,9 @@ init_agent(Config) ->
%%
Vsns = [v1,v2],
- ?line ok = write_agent_config(Vsns, Config),
+ ok = write_agent_config(Vsns, Config),
- Conf = [{agent_node, Node},
+ Conf = [{agent_node, Node}, {agent_peer, Peer},
{mib_dir, MibDir} | Config],
%%
@@ -5287,7 +5291,7 @@ init_agent(Config) ->
"~n Reason: ~p"
"~n StackTrace: ~p", [Reason, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
erlang:raise(C, E, S);
C:E:S ->
?EPRINT("Failure during agent start: "
@@ -5295,12 +5299,12 @@ init_agent(Config) ->
"~n Error: ~p"
"~n StackTrace: ~p", [C, E, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
?FAIL({failed_starting_agent, C, E, S})
end.
-init_v3_agent(Config) ->
+init_v3_agent(Case, Config) ->
?IPRINT("init_v3_agent -> entry with"
"~n Config: ~p", [Config]),
@@ -5315,7 +5319,7 @@ init_v3_agent(Config) ->
%%
%% ?line Node = self(),
- ?line Node = start_unique_agent_node(),
+ ?line {Peer, Node} = start_node(lists:concat([Case, "-v3agent"])),
%% The point with this (try catch block) is to be
%% able to do some cleanup in case we fail to
@@ -5330,7 +5334,7 @@ init_v3_agent(Config) ->
%% Start and initiate crypto on agent node
%%
- ?line ok = init_crypto(Node),
+ ok = init_crypto(Node),
%%
@@ -5338,9 +5342,9 @@ init_v3_agent(Config) ->
%%
Vsns = [v3],
- ?line ok = write_agent_config(Vsns, Config),
+ ok = write_agent_config(Vsns, Config),
- Conf = [{agent_node, Node},
+ Conf = [{agent_node, Node}, {agent_peer, Peer},
{mib_dir, MibDir} | Config],
%%
@@ -5355,7 +5359,7 @@ init_v3_agent(Config) ->
"~n Reason: ~p"
"~n StackTrace: ~p", [Reason, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
erlang:raise(C, E, S);
C:E:S ->
?EPRINT("Failure during agent start: "
@@ -5363,7 +5367,7 @@ init_v3_agent(Config) ->
"~n Error: ~p"
"~n StackTrace: ~p", [C, E, S]),
%% And now, *try* to cleanup
- (catch stop_node(Node)),
+ (catch peer:stop(Peer)),
?FAIL({failed_starting_agent, C, E, S})
end.
@@ -5373,7 +5377,7 @@ fin_agent(Config) ->
StopAgentRes = stop_agent(Node),
StopCryptoRes = fin_crypto(Node),
StopMnesiaRes = fin_mnesia(Node),
- StopNode = stop_node(Node),
+ StopNode = peer:stop(?config(agent_peer, Config)),
?IPRINT("fin_agent -> stop apps and (agent node ~p) node results: "
"~n SNMP Agent: ~p"
"~n Crypto: ~p"
@@ -5386,7 +5390,7 @@ fin_v3_agent(Config) ->
Node = ?config(agent_node, Config),
StopAgentRes = stop_agent(Node),
StopCryptoRes = fin_crypto(Node),
- StopNode = stop_node(Node),
+ StopNode = peer:stop(?config(agent_peer, Config)),
?IPRINT("fin_agent -> stop apps and (agent node ~p) node results: "
"~n SNMP Agent: ~p"
"~n Crypto: ~p"
@@ -5400,52 +5404,52 @@ init_mnesia(Node, Dir, MnesiaDebug)
init_mnesia(Node, Dir, ?DEFAULT_MNESIA_DEBUG);
init_mnesia(Node, Dir, MnesiaDebug) ->
?DBG("init_mnesia -> load application mnesia", []),
- ?line ok = load_mnesia(Node),
+ ok = load_mnesia(Node),
?DBG("init_mnesia -> application mnesia: set_env dir: ~n~p",[Dir]),
- ?line ok = set_mnesia_env(Node, dir, filename:join(Dir, "mnesia")),
+ ok = set_mnesia_env(Node, dir, filename:join(Dir, "mnesia")),
%% Just in case, only set (known to be) valid values for debug
if
((MnesiaDebug =:= debug) orelse (MnesiaDebug =:= trace)) ->
?DBG("init_mnesia -> application mnesia: set_env debug: ~w",
[MnesiaDebug]),
- ?line ok = set_mnesia_env(Node, debug, MnesiaDebug);
+ ok = set_mnesia_env(Node, debug, MnesiaDebug);
true ->
ok
end,
?DBG("init_mnesia -> create mnesia schema",[]),
- ?line case create_schema(Node) of
+ case create_schema(Node) of
ok ->
ok;
{error, {Node, {already_exists, Node}}} ->
- ?line ok = delete_schema(Node),
- ?line ok = create_schema(Node);
+ ok = delete_schema(Node),
+ ok = create_schema(Node);
Error ->
?FAIL({failed_creating_mnesia_schema, Error})
end,
?DBG("init_mnesia -> start application mnesia",[]),
- ?line ok = start_mnesia(Node),
+ ok = start_mnesia(Node),
?DBG("init_mnesia -> create tables",[]),
- ?line ok = create_tables(Node),
+ ok = create_tables(Node),
ok.
fin_mnesia(Node) ->
- ?line ok = delete_tables(Node),
- ?line ok = stop_mnesia(Node),
+ ok = delete_tables(Node),
+ ok = stop_mnesia(Node),
ok.
init_crypto(Node) ->
- ?line ok = load_crypto(Node),
- ?line ok = start_crypto(Node),
+ ok = load_crypto(Node),
+ ok = start_crypto(Node),
ok.
fin_crypto(Node) ->
- ?line ok = stop_crypto(Node),
+ ok = stop_crypto(Node),
ok.
@@ -5662,7 +5666,7 @@ init_mgr_user(Conf) ->
Node = ?config(manager_node, Conf),
%% UserId = ?config(user_id, Conf),
- ?line {ok, User} = mgr_user_start(Node),
+ {ok, User} = mgr_user_start(Node),
?DBG("start_mgr_user -> User: ~p", [User]),
link(User),
@@ -5675,7 +5679,7 @@ init_mgr_v3_user(Conf) ->
Node = ?config(manager_node, Conf),
%% UserId = ?config(user_id, Conf),
- ?line {ok, User} = mgr_user_start(Node),
+ {ok, User} = mgr_user_start(Node),
?IPRINT("start_mgr_v3_user -> User: ~p", [User]),
link(User),
@@ -5687,7 +5691,7 @@ init_mgr_v3_user(Conf) ->
[ {auth, select_auth_proto(AuthAlg)},
{auth_key, AuthKey}
],
- ?line ok = mgr_register_usm_user(Node, EngineID, SecName, Credentials),
+ ok = mgr_register_usm_user(Node, EngineID, SecName, Credentials),
?IPRINT("start_mgr_v3_user -> done"),
[{user_pid, User} | Conf].
@@ -5723,7 +5727,7 @@ fin_mgr_user(Conf) ->
User = ?config(user_pid, Conf),
unlink(User),
Node = ?config(manager_node, Conf),
- ?line ok = mgr_user_stop(Node),
+ ok = mgr_user_stop(Node),
Conf.
init_mgr_user_data1(Conf) ->
@@ -5732,7 +5736,7 @@ init_mgr_user_data1(Conf) ->
IpFamily = ?config(ipfamily, Conf),
Ip = ?config(ip, Conf),
Port = ?AGENT_PORT,
- ?line ok =
+ ok =
case IpFamily of
inet ->
mgr_user_register_agent(
@@ -5750,19 +5754,19 @@ init_mgr_user_data1(Conf) ->
_Agents = mgr_user_which_own_agents(Node),
?DBG("Own agents: ~p", [_Agents]),
- ?line {ok, _DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
+ {ok, _DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
?DBG("Default agent config: ~n~p", [_DefAgentConf]),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
community, "all-rights"),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
sec_name, "all-rights"),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
engine_id, "agentEngine"),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
max_message_size, 1024),
- ?line {ok, _AgentConf} = mgr_user_agent_info(Node, TargetName, all),
+ {ok, _AgentConf} = mgr_user_agent_info(Node, TargetName, all),
?DBG("Updated agent config: ~n~p", [_AgentConf]),
Conf.
@@ -5774,7 +5778,7 @@ init_mgr_user_data2(Conf) ->
IpFamily = ?config(ipfamily, Conf),
Ip = ?config(ip, Conf),
Port = ?AGENT_PORT,
- ?line ok =
+ ok =
case IpFamily of
inet ->
mgr_user_register_agent(
@@ -5792,17 +5796,17 @@ init_mgr_user_data2(Conf) ->
_Agents = mgr_user_which_own_agents(Node),
?DBG("Own agents: ~p", [_Agents]),
- ?line {ok, _DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
+ {ok, _DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
?DBG("Default agent config: ~n~p", [_DefAgentConf]),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
community, "all-rights"),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
sec_name, "all-rights"),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
max_message_size, 1024),
- ?line {ok, _AgentConf} = mgr_user_agent_info(Node, TargetName, all),
+ {ok, _AgentConf} = mgr_user_agent_info(Node, TargetName, all),
?DBG("Updated agent config: ~n~p", [_AgentConf]),
Conf.
@@ -5814,7 +5818,7 @@ init_mgr_v3_user_data(Conf) ->
IpFamily = ?config(ipfamily, Conf),
Ip = ?config(ip, Conf),
Port = ?AGENT_PORT,
- ?line ok =
+ ok =
case IpFamily of
inet ->
mgr_user_register_agent(
@@ -5834,22 +5838,22 @@ init_mgr_v3_user_data(Conf) ->
_Agents = mgr_user_which_own_agents(Node),
?IPRINT("Own agents: ~p", [_Agents]),
- ?line {ok, _DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
+ {ok, _DefAgentConf} = mgr_user_agent_info(Node, TargetName, all),
?IPRINT("Default agent config: ~n~p", [_DefAgentConf]),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
community, "all-rights"),
SecName = select_secname_from_authalg(?config(auth_alg, Conf)),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
sec_name, SecName),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
sec_level, authNoPriv),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
sec_model, usm),
- ?line ok = mgr_user_update_agent_info(Node, TargetName,
+ ok = mgr_user_update_agent_info(Node, TargetName,
max_message_size, 1024),
- ?line {ok, _AgentConf} = mgr_user_agent_info(Node, TargetName, all),
+ {ok, _AgentConf} = mgr_user_agent_info(Node, TargetName, all),
?IPRINT("Updated agent config: ~n~p", [_AgentConf]),
Conf.
@@ -5992,9 +5996,9 @@ start_manager(Node, Vsns, Conf0, _Opts) ->
{cbproxy, CBP},
{netif_sup, NIS}]},
{net_if, NetIfConf}],
- ?line ok = set_mgr_env(Node, Env),
+ ok = set_mgr_env(Node, Env),
- ?line ok = try start_snmp(Node) of
+ ok = try start_snmp(Node) of
ok ->
ok;
{error, Reason} ->
@@ -6059,9 +6063,9 @@ start_agent(Node, Vsns, Conf0, _Opts) ->
%% (which will cause problems for some test cases).
{options, [{bind_to, true}]}]},
{multi_threaded, true}],
- ?line ok = set_agent_env(Node, Env),
+ ok = set_agent_env(Node, Env),
- ?line try start_snmp(Node) of
+ try start_snmp(Node) of
ok ->
ok;
{error, Reason} ->
@@ -6100,87 +6104,12 @@ agent_info(Node) ->
%% -- Misc node operation wrapper functions --
-unique(PreName) ->
- list_to_atom(?F("~w_~w", [PreName, erlang:system_time(millisecond)])).
-
-start_agent_node() ->
- start_node(snmp_agent).
-
-start_unique_agent_node() ->
- start_unique_node(snmp_agent).
-
-start_manager_node() ->
- start_node(snmp_manager).
-
-start_unique_manager_node() ->
- start_unique_node(snmp_manager).
-
-%% Generate a "unique" (node-) name and start a node with this name.
-start_unique_node(BaseName) when is_atom(BaseName) ->
- start_node(unique(BaseName), false).
-
-start_node(Name) ->
- start_node(Name, true).
-start_node(Name, Retry) ->
-
- ?IPRINT("start_node -> entry with"
- "~n Name: ~p"
- "~n when"
- "~n hostname of this node: ~p",
- [Name, list_to_atom(?HOSTNAME(node()))]),
-
- Pa = filename:dirname(code:which(?MODULE)),
-
- A = " -pa " ++ Pa ++
- " -s " ++ atom_to_list(snmp_test_sys_monitor) ++ " start" ++
- " -s global sync",
- try ?START_NODE(Name, A) of
- {ok, Node} ->
- global:sync(),
- Node;
- {error, timeout} ->
- ?EPRINT("Failed starting node ~p: timeout", [Name]),
- ?line ?FAIL({error_starting_node, Name, timeout});
- {error, {already_running, Node}} when (Retry =:= true) ->
- %% Ouch
- %% Either we previously failed to (properly) stop the node
- %% or it was a failed start, that reported failure (for instance
- %% timeout) but actually succeeded. Regardless, we don't know
- %% the state of this node, so (try) stop it and then (re-) try
- %% start again.
- ?WPRINT("Failed starting node ~p: Already Running - try stop", [Node]),
- case ?STOP_NODE(Node) of
- true ->
- ?IPRINT("Successfully stopped old node ~p", [Node]),
- start_node(Name, false);
- false ->
- ?EPRINT("Failed stop old node ~p", [Node]),
- ?line ?FAIL({error_starting_node, Node, Retry, already_running})
- end;
- {error, {already_running, Node}} ->
- ?EPRINT("Failed starting node ~p: Already Running", [Node]),
- ?line ?FAIL({error_starting_node, Node, Retry, already_running});
- {error, Reason} ->
- ?EPRINT("Failed starting node ~p: ~p", [Name, Reason]),
- ?line ?FAIL({error_starting_node, Name, Reason})
- catch
- exit:{suite_failed, Reason} ->
- ?EPRINT("(suite) Failed starting node ~p: ~p", [Name, Reason]),
- ?line ?FAIL({failed_starting_node, Name, Reason})
- end.
-
-
-stop_node(Node) when (Node =:= self()) ->
- ok;%?line ?FAIL({stop_own_node, Node});
-stop_node(Node) ->
- case ?STOP_NODE(Node) of
- true ->
- ok;
- false ->
- ?line ?FAIL({failed_stop_node, Node})
- end.
-
-
+start_node(Case) ->
+ Args = ["-s", "snmp_test_sys_monitor", "start", "-s", "global", "sync"],
+ Name = peer:random_name(lists:concat([?MODULE, "-", Case])),
+ {ok, Peer, Node} = ?CT_PEER(#{name => Name, args => Args}),
+ global:sync(),
+ {Peer, Node}.
%% -- Misc config wrapper functions --
@@ -6224,21 +6153,21 @@ write_manager_conf(Dir, Str) ->
write_agent_config(Vsns, Conf) ->
Dir = ?config(agent_conf_dir, Conf),
- ?line Ip = tuple_to_list(?config(ip, Conf)),
- ?line Domain =
+ Ip = tuple_to_list(?config(ip, Conf)),
+ Domain =
case ?config(ipfamily, Conf) of
inet ->
transportDomainUdpIpv4;
inet6 ->
transportDomainUdpIpv6
end,
- ?line ok = write_agent_config_files(Dir, Vsns, Domain, Ip),
- ?line ok = update_agent_usm(Vsns, Dir),
- ?line ok = update_agent_community(Vsns, Dir),
- ?line ok = update_agent_vacm(Vsns, Dir),
- ?line ok = write_agent_target_addr_conf(Dir, Domain, Ip, Vsns),
- ?line ok = write_agent_target_params_conf(Dir, Vsns),
- ?line ok = write_agent_notify_conf(Dir),
+ ok = write_agent_config_files(Dir, Vsns, Domain, Ip),
+ ok = update_agent_usm(Vsns, Dir),
+ ok = update_agent_community(Vsns, Dir),
+ ok = update_agent_vacm(Vsns, Dir),
+ ok = write_agent_target_addr_conf(Dir, Domain, Ip, Vsns),
+ ok = write_agent_target_params_conf(Dir, Vsns),
+ ok = write_agent_notify_conf(Dir),
ok.
write_agent_config_files(Dir, Vsns, Domain, Ip) ->
@@ -6381,8 +6310,8 @@ write_agent_notify_conf(Dir) ->
write_conf_file(Dir, File, Str) ->
- ?line {ok, Fd} = file:open(filename:join(Dir, File), write),
- ?line ok = io:format(Fd, "~s", [Str]),
+ {ok, Fd} = file:open(filename:join(Dir, File), write),
+ ok = io:format(Fd, "~s", [Str]),
file:close(Fd).
diff --git a/lib/snmp/test/snmp_manager_config_SUITE.erl b/lib/snmp/test/snmp_manager_config_SUITE.erl
index f70f506fb0..933be4e016 100644
--- a/lib/snmp/test/snmp_manager_config_SUITE.erl
+++ b/lib/snmp/test/snmp_manager_config_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -272,22 +272,22 @@ init_per_testcase(Case, Config) when is_list(Config) ->
SuiteTopDir = ?config(snmp_suite_top_dir, Config),
CaseTopDir = filename:join(SuiteTopDir, atom_to_list(Case)),
- ?line ok = file:make_dir(CaseTopDir),
+ ok = file:make_dir(CaseTopDir),
?IPRINT("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]),
MgrTopDir = filename:join(CaseTopDir, "manager/"),
- ?line ok = file:make_dir(MgrTopDir),
+ ok = file:make_dir(MgrTopDir),
MgrConfDir = filename:join(MgrTopDir, "conf/"),
- ?line ok = file:make_dir(MgrConfDir),
+ ok = file:make_dir(MgrConfDir),
MgrDbDir = filename:join(MgrTopDir, "db/"),
case Case of
start_with_create_db_and_dir_opt ->
ok;
_ ->
- ?line ok = file:make_dir(MgrDbDir)
+ ok = file:make_dir(MgrDbDir)
end,
MgrLogDir = filename:join(MgrTopDir, "log/"),
- ?line ok = file:make_dir(MgrLogDir),
+ ok = file:make_dir(MgrLogDir),
Config1 = [{case_top_dir, CaseTopDir},
{manager_dir, MgrTopDir},
{manager_conf_dir, MgrConfDir},
@@ -308,7 +308,7 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
?IPRINT("system events during test: "
"~n ~p", [snmp_test_global_sys_monitor:events()]),
- %% The cleanup is removed due to some really discusting NFS behaviour...
+ %% The cleanup is removed due to some really disgusting NFS behaviour...
%% Also, it can always be useful to retain "all the stuff" after
%% the test case in case of debugging...
Config.
@@ -338,8 +338,8 @@ simple_start_and_stop(Conf) when is_list(Conf) ->
Opts = [{versions, [v1]},
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
- ?line {ok, _Pid} = snmpm_config:start_link(Opts),
- ?line ok = snmpm_config:stop(),
+ {ok, _Pid} = snmpm_config:start_link(Opts),
+ ok = snmpm_config:stop(),
ok.
@@ -367,7 +367,7 @@ start_without_mandatory_opts1(Conf) when is_list(Conf) ->
?IPRINT("config option, but no dir"),
Opts = [{priority, normal},
{config, [{verbosity, trace}, {db_dir, DbDir}]}, {mibs, []}],
- ?line {error, {missing_mandatory,dir}} = config_start(Opts),
+ {error, {missing_mandatory,dir}} = config_start(Opts),
?IPRINT("done"),
ok.
@@ -395,7 +395,7 @@ start_without_mandatory_opts2(Conf) when is_list(Conf) ->
?IPRINT("no config option"),
Opts = [{priority, normal},
{mibs, []}],
- ?line {error, {missing_mandatory,config,[dir, db_dir]}} =
+ {error, {missing_mandatory,config,[dir, db_dir]}} =
config_start(Opts),
?IPRINT("done"),
@@ -456,8 +456,8 @@ start_with_all_valid_opts(Conf) when is_list(Conf) ->
{priority, Prio},
{mibs, Mibs},
{versions, Vsns}],
- ?line {ok, _Pid} = config_start(Opts),
- ?line ok = config_stop(),
+ {ok, _Pid} = config_start(Opts),
+ ok = config_stop(),
?IPRINT("done"),
ok.
@@ -510,10 +510,10 @@ start_with_unknown_opts(Conf) when is_list(Conf) ->
{priority, Prio},
{mibs, Mibs},
{versions, Vsns}],
- ?line {ok, _Pid} = config_start(Opts),
+ {ok, _Pid} = config_start(Opts),
?IPRINT("(config) started - now stop"),
- ?line ok = config_stop(),
+ ok = config_stop(),
?IPRINT("done"),
ok.
@@ -544,35 +544,35 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
NetIfOpts1 = [{module, snmpm_user}], %% Behaviour check will fail
Opts01 = [{config, ConfigOpts}, {versions, [v1]},
{net_if, NetIfOpts1}],
- ?line {error, Reason01} = config_start(Opts01),
+ {error, Reason01} = config_start(Opts01),
?IPRINT("net-if (module) res: ~p", [Reason01]),
?IPRINT("net-if - incorrect verbosity"),
NetIfOpts2 = [{verbosity, invalid_verbosity}],
Opts02 = [{config, ConfigOpts}, {versions, [v1]},
{net_if, NetIfOpts2}],
- ?line {error, Reason02} = config_start(Opts02),
+ {error, Reason02} = config_start(Opts02),
?IPRINT("net-if (verbosity) res: ~p", [Reason02]),
?IPRINT("net-if - incorrect options"),
NetIfOpts3 = [{options, invalid_options}],
Opts03 = [{config, ConfigOpts}, {versions, [v1]},
{net_if, NetIfOpts3}],
- ?line {error, Reason03} = config_start(Opts03),
+ {error, Reason03} = config_start(Opts03),
?IPRINT("net-if (options) res: ~p", [Reason03]),
?IPRINT("server - incorrect timeout (1)"),
ServerOpts1 = [{timeout, invalid_timeout}],
Opts08 = [{config, ConfigOpts}, {versions, [v1]},
{server, ServerOpts1}],
- ?line {error, Reason08} = config_start(Opts08),
+ {error, Reason08} = config_start(Opts08),
?IPRINT("server (timeout) res: ~p", [Reason08]),
?IPRINT("server - incorrect timeout (2)"),
ServerOpts2 = [{timeout, 0}],
Opts09 = [{config, ConfigOpts}, {versions, [v1]},
{server, ServerOpts2}],
- ?line {error, Reason09} = config_start(Opts09),
+ {error, Reason09} = config_start(Opts09),
?IPRINT("server (timeout) res: ~p", [Reason09]),
?IPRINT("server - incorrect timeout (3)"),
@@ -580,7 +580,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts10 = [{config, ConfigOpts},
{versions, [v1]},
{server, ServerOpts3}],
- ?line {error, Reason10} = config_start(Opts10),
+ {error, Reason10} = config_start(Opts10),
?IPRINT("server (timeout) res: ~p", [Reason10]),
?IPRINT("server - incorrect verbosity"),
@@ -588,7 +588,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts11 = [{config, ConfigOpts},
{versions, [v1]},
{server, ServerOpts4}],
- ?line {error, Reason11} = config_start(Opts11),
+ {error, Reason11} = config_start(Opts11),
?IPRINT("server (verbosity) res: ~p", [Reason11]),
?IPRINT("note-store - incorrect timeout (1)"),
@@ -596,7 +596,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts12 = [{config, ConfigOpts},
{versions, [v1]},
{note_store, NoteStoreOpts1}],
- ?line {error, Reason12} = config_start(Opts12),
+ {error, Reason12} = config_start(Opts12),
?IPRINT("note-store (timeout) res: ~p", [Reason12]),
?IPRINT("note-store - incorrect timeout (2)"),
@@ -604,7 +604,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts13 = [{config, ConfigOpts},
{versions, [v1]},
{note_store, NoteStoreOpts2}],
- ?line {error, Reason13} = config_start(Opts13),
+ {error, Reason13} = config_start(Opts13),
?IPRINT("note-store (timeout) res: ~p", [Reason13]),
?IPRINT("note-store - incorrect timeout (3)"),
@@ -612,7 +612,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts14 = [{config, ConfigOpts},
{versions, [v1]},
{note_store, NoteStoreOpts3}],
- ?line {error, Reason14} = config_start(Opts14),
+ {error, Reason14} = config_start(Opts14),
?IPRINT("note-store (timeout) res: ~p", [Reason14]),
?IPRINT("note-store - incorrect verbosity"),
@@ -620,28 +620,28 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts15 = [{config, ConfigOpts},
{versions, [v1]},
{note_store, NoteStoreOpts4}],
- ?line {error, Reason15} = config_start(Opts15),
+ {error, Reason15} = config_start(Opts15),
?IPRINT("note-store (verbosity) res: ~p", [Reason15]),
?IPRINT("config - incorrect dir (1)"),
ConfigOpts1 = [{dir, invalid_dir}],
Opts16 = [{config, ConfigOpts1},
{versions, [v1]}],
- ?line {error, Reason16} = config_start(Opts16),
+ {error, Reason16} = config_start(Opts16),
?IPRINT("config (dir) res: ~p", [Reason16]),
?IPRINT("config - incorrect dir (2)"),
ConfigOpts2 = [{dir, "/invalid/dir"}],
Opts17 = [{config, ConfigOpts2},
{versions, [v1]}],
- ?line {error, Reason17} = config_start(Opts17),
+ {error, Reason17} = config_start(Opts17),
?IPRINT("config (dir) res: ~p", [Reason17]),
?IPRINT("config - incorrect verbosity"),
ConfigOpts3 = [{dir, ConfDir}, {verbosity, invalid_verbosity}],
Opts18 = [{config, ConfigOpts3},
{versions, [v1]}],
- ?line {error, Reason18} = config_start(Opts18),
+ {error, Reason18} = config_start(Opts18),
?IPRINT("config (verbosity) res: ~p", [Reason18]),
?IPRINT("mibs - incorrect mibs (1)"),
@@ -649,7 +649,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts19 = [{config, ConfigOpts},
{versions, [v1]},
{mibs, Mibs1}],
- ?line {error, Reason19} = config_start(Opts19),
+ {error, Reason19} = config_start(Opts19),
?IPRINT("mibs (mibs) res: ~p", [Reason19]),
?IPRINT("mibs - incorrect mibs (2)"),
@@ -657,7 +657,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts20 = [{config, ConfigOpts},
{versions, [v1]},
{mibs, Mibs2}],
- ?line {error, Reason20} = config_start(Opts20),
+ {error, Reason20} = config_start(Opts20),
?IPRINT("mibs (mibs) res: ~p", [Reason20]),
?IPRINT("prio - incorrect prio"),
@@ -665,7 +665,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts21 = [{config, ConfigOpts},
{versions, [v1]},
{priority, Prio1}],
- ?line {error, Reason21} = config_start(Opts21),
+ {error, Reason21} = config_start(Opts21),
?IPRINT("prio (prio) res: ~p", [Reason21]),
?IPRINT("atl - incorrect type"),
@@ -676,7 +676,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts22 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL1}],
- ?line {error, Reason22} = config_start(Opts22),
+ {error, Reason22} = config_start(Opts22),
?IPRINT("atl (type) res: ~p", [Reason22]),
?IPRINT("atl - incorrect dir (1)"),
@@ -687,7 +687,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts23 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL2}],
- ?line {error, Reason23} = config_start(Opts23),
+ {error, Reason23} = config_start(Opts23),
?IPRINT("atl (dir) res: ~p", [Reason23]),
?IPRINT("atl - incorrect dir (2)"),
@@ -698,7 +698,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts24 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL3}],
- ?line {error, Reason24} = config_start(Opts24),
+ {error, Reason24} = config_start(Opts24),
?IPRINT("atl (dir) res: ~p", [Reason24]),
?IPRINT("atl - incorrect size (1)"),
@@ -709,7 +709,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts25 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL4}],
- ?line {error, Reason25} = config_start(Opts25),
+ {error, Reason25} = config_start(Opts25),
?IPRINT("atl (size) res: ~p", [Reason25]),
?IPRINT("atl - incorrect size (2)"),
@@ -720,7 +720,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts26 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL5}],
- ?line {error, Reason26} = config_start(Opts26),
+ {error, Reason26} = config_start(Opts26),
?IPRINT("atl (size) res: ~p", [Reason26]),
?IPRINT("atl - incorrect size (3)"),
@@ -731,7 +731,7 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts27 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL6}],
- ?line {error, Reason27} = config_start(Opts27),
+ {error, Reason27} = config_start(Opts27),
?IPRINT("atl (size) res: ~p", [Reason27]),
?IPRINT("atl - incorrect repair"),
@@ -742,21 +742,21 @@ start_with_incorrect_opts(Conf) when is_list(Conf) ->
Opts28 = [{config, ConfigOpts},
{versions, [v1]},
{audit_trail_log, ATL7}],
- ?line {error, Reason28} = config_start(Opts28),
+ {error, Reason28} = config_start(Opts28),
?IPRINT("atl (repair) res: ~p", [Reason28]),
?IPRINT("version - incorrect versions (1)"),
Vsns1 = invalid_vsns,
Opts29 = [{config, ConfigOpts},
{versions, Vsns1}],
- ?line {error, Reason29} = config_start(Opts29),
+ {error, Reason29} = config_start(Opts29),
?IPRINT("versions (versions) res: ~p", [Reason29]),
?IPRINT("version - incorrect versions (2)"),
Vsns2 = [v1,v2,v3,v9],
Opts30 = [{config, ConfigOpts},
{versions, Vsns2}],
- ?line {error, Reason30} = config_start(Opts30),
+ {error, Reason30} = config_start(Opts30),
?IPRINT("versions (versions) res: ~p", [Reason30]),
?IPRINT("done"),
@@ -784,136 +784,136 @@ start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("write manager config file with invalid IP address (1)"),
write_manager_conf(ConfDir,
"arne-anka", "4001", "500", "\"bmkEngine\""),
- ?line {error, Reason11} = config_start(Opts),
+ {error, Reason11} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason11]),
- ?line {failed_reading, _, _, 1, {parse_error, _}} = Reason11,
+ {failed_reading, _, _, 1, {parse_error, _}} = Reason11,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid IP address (2)"),
write_manager_conf(ConfDir,
"arne_anka", "4001", "500", "\"bmkEngine\""),
- ?line {error, Reason12} = config_start(Opts),
+ {error, Reason12} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason12]),
- ?line {failed_check, _, _, 2, {bad_address, _}} = Reason12,
+ {failed_check, _, _, 2, {bad_address, _}} = Reason12,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid IP address (3)"),
write_manager_conf(ConfDir,
"9999", "4001", "500", "\"bmkEngine\""),
- ?line {error, Reason13} = config_start(Opts),
+ {error, Reason13} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason13]),
- ?line {failed_check, _, _, 2, {bad_address, _}} = Reason13,
+ {failed_check, _, _, 2, {bad_address, _}} = Reason13,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid port (2)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "kalle-anka", "500", "\"bmkEngine\""),
- ?line {error, Reason21} = config_start(Opts),
+ {error, Reason21} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason21]),
- ?line {failed_reading, _, _, 2, {parse_error, _}} = Reason21,
+ {failed_reading, _, _, 2, {parse_error, _}} = Reason21,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid port (1)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "-1", "500", "\"bmkEngine\""),
- ?line {error, Reason22} = config_start(Opts),
+ {error, Reason22} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason22]),
io:format("Reason22: ~p~n", [Reason22]),
- ?line {failed_check, _, _, 3, {bad_port, _}} = Reason22,
+ {failed_check, _, _, 3, {bad_port, _}} = Reason22,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid port (3)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "\"kalle-anka\"", "500", "\"bmkEngine\""),
- ?line {error, Reason23} = config_start(Opts),
+ {error, Reason23} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason23]),
- ?line {failed_check, _, _, 3, {bad_port, _}} = Reason23,
+ {failed_check, _, _, 3, {bad_port, _}} = Reason23,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid EngineID (1)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "500", "bmkEngine"),
- ?line {error, Reason31} = config_start(Opts),
+ {error, Reason31} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason31]),
- ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason31,
+ {failed_check, _, _, 5, {invalid_string, _}} = Reason31,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid EngineID (2)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "500", "{1,2,3}"),
- ?line {error, Reason32} = config_start(Opts),
+ {error, Reason32} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason32]),
- ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason32,
+ {failed_check, _, _, 5, {invalid_string, _}} = Reason32,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid EngineID (3)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "500", "10101"),
- ?line {error, Reason33} = config_start(Opts),
+ {error, Reason33} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason33]),
- ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason33,
+ {failed_check, _, _, 5, {invalid_string, _}} = Reason33,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid MMS (1)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "483", "\"bmkEngine\""),
- ?line {error, Reason41} = config_start(Opts),
+ {error, Reason41} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason41]),
- ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason41,
+ {failed_check, _, _, 4, {invalid_integer, _}} = Reason41,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid MMS (2)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "-1", "\"bmkEngine\""),
- ?line {error, Reason42} = config_start(Opts),
+ {error, Reason42} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason42]),
- ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason42,
+ {failed_check, _, _, 4, {invalid_integer, _}} = Reason42,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid MMS (3)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "\"kalle-anka\"", "\"bmkEngine\""),
- ?line {error, Reason43} = config_start(Opts),
+ {error, Reason43} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason43]),
- ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason43,
+ {failed_check, _, _, 4, {invalid_integer, _}} = Reason43,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with invalid MMS (4)"),
write_manager_conf(ConfDir,
"[134,138,177,189]", "4001", "kalle_anka", "\"bmkEngine\""),
- ?line {error, Reason44} = config_start(Opts),
+ {error, Reason44} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason44]),
- ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason44,
+ {failed_check, _, _, 4, {invalid_integer, _}} = Reason44,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with unknown option"),
write_manager_conf(ConfDir,
"{kalle, anka}."),
- ?line {error, Reason51} = config_start(Opts),
+ {error, Reason51} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason51]),
- ?line {failed_check, _, _, 1, {unknown_config, _}} = Reason51,
+ {failed_check, _, _, 1, {unknown_config, _}} = Reason51,
config_ensure_not_running(),
%% --
?IPRINT("write manager config file with unknown option"),
write_manager_conf(ConfDir,
"kalle_anka."),
- ?line {error, Reason52} = config_start(Opts),
+ {error, Reason52} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason52]),
- ?line {failed_check, _, _, 1, {unknown_config, _}} = Reason52,
+ {failed_check, _, _, 1, {unknown_config, _}} = Reason52,
config_ensure_not_running(),
?IPRINT("done"),
@@ -945,73 +945,73 @@ start_with_invalid_users_conf_file1(Conf) when is_list(Conf) ->
%% --
?IPRINT("write users config file with invalid module (1)"),
write_users_conf(ConfDir, [{"kalle", "kalle", "dummy"}]),
- ?line {error, Reason11} = config_start(Opts),
+ {error, Reason11} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason11]),
- ?line {failed_check, _, _, _, {bad_module, kalle}} = Reason11,
+ {failed_check, _, _, _, {bad_module, kalle}} = Reason11,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid module (1)"),
write_users_conf(ConfDir, [{"kalle", "snmpm", "dummy"}]),
- ?line {error, Reason12} = config_start(Opts),
+ {error, Reason12} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason12]),
- ?line {failed_check, _, _, _, {bad_module, _}} = Reason12,
+ {failed_check, _, _, _, {bad_module, _}} = Reason12,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid module (2)"),
write_users_conf(ConfDir, [{"kalle1", "10101", "dummy"}]),
- ?line {error, Reason13} = config_start(Opts),
+ {error, Reason13} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason13]),
- ?line {failed_check, _, _, _, {bad_module, _}} = Reason13,
+ {failed_check, _, _, _, {bad_module, _}} = Reason13,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid user tuple (1)"),
write_users_conf2(ConfDir, "{kalle, snmpm_user_default}."),
- ?line {error, Reason21} = config_start(Opts),
+ {error, Reason21} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason21]),
- ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason21,
+ {failed_check, _, _, _, {bad_user_config, _}} = Reason21,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid user tuple (2)"),
write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, [], olle}."),
- ?line {error, Reason22} = config_start(Opts),
+ {error, Reason22} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason22]),
- ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason22,
+ {failed_check, _, _, _, {bad_user_config, _}} = Reason22,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid user tuple (3)"),
write_users_conf2(ConfDir, "snmpm_user_default."),
- ?line {error, Reason23} = config_start(Opts),
+ {error, Reason23} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason23]),
- ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason23,
+ {failed_check, _, _, _, {bad_user_config, _}} = Reason23,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid user tuple (4)"),
write_users_conf2(ConfDir, "[kalle, snmpm_user_default, kalle]."),
- ?line {error, Reason24} = config_start(Opts),
+ {error, Reason24} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason24]),
- ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason24,
+ {failed_check, _, _, _, {bad_user_config, _}} = Reason24,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid user agent default config (1)"),
write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, olle}."),
- ?line {error, Reason31} = config_start(Opts),
+ {error, Reason31} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason31]),
- ?line {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason31,
+ {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason31,
config_ensure_not_running(),
%% --
?IPRINT("write users config file with invalid user agent default config (2)"),
write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, [olle]}."),
- ?line {error, Reason32} = config_start(Opts),
+ {error, Reason32} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason32]),
- %% ?line {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason32,
+ %% {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason32,
case Reason32 of
{failed_check, _, _, _, {bad_default_agent_config, _}} ->
ok;
@@ -1059,7 +1059,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason11} ->
?IPRINT("start failed (as expected): ~p", [Reason11]),
- ?line {failed_reading, _, _, _, {parse_error, _}} = Reason11,
+ {failed_reading, _, _, _, {parse_error, _}} = Reason11,
config_ensure_not_running();
OK_11 ->
config_ensure_not_running(),
@@ -1073,7 +1073,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason21} ->
?IPRINT("start failed (as expected): ~p", [Reason21]),
- ?line {failed_reading, _, _, _, {parse_error, _}} = Reason21,
+ {failed_reading, _, _, _, {parse_error, _}} = Reason21,
config_ensure_not_running();
OK_21 ->
config_ensure_not_running(),
@@ -1087,7 +1087,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason22} ->
?IPRINT("start failed (as expected): ~p", [Reason22]),
- ?line {failed_check, _, _, _, {invalid_string, _}} = Reason22,
+ {failed_check, _, _, _, {invalid_string, _}} = Reason22,
config_ensure_not_running();
OK_22 ->
config_ensure_not_running(),
@@ -1101,7 +1101,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason23} ->
?IPRINT("start failed (as expected): ~p", [Reason23]),
- ?line {failed_check, _, _, _, {invalid_string, _}} = Reason23,
+ {failed_check, _, _, _, {invalid_string, _}} = Reason23,
config_ensure_not_running();
OK_23 ->
config_ensure_not_running(),
@@ -1115,7 +1115,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason31} ->
?IPRINT("start failed (as expected): ~p", [Reason31]),
- ?line {failed_reading, _, _, _, {parse_error, _}} = Reason31,
+ {failed_reading, _, _, _, {parse_error, _}} = Reason31,
config_ensure_not_running();
OK_31 ->
config_ensure_not_running(),
@@ -1129,7 +1129,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason32} ->
?IPRINT("start failed (as expected): ~p", [Reason32]),
- ?line {failed_check, _, _, _, {invalid_string, _}} = Reason32,
+ {failed_check, _, _, _, {invalid_string, _}} = Reason32,
config_ensure_not_running();
OK_32 ->
config_ensure_not_running(),
@@ -1143,7 +1143,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason33} ->
?IPRINT("start failed (as expected): ~p", [Reason33]),
- ?line {failed_check, _, _, _, {invalid_string, _}} = Reason33,
+ {failed_check, _, _, _, {invalid_string, _}} = Reason33,
config_ensure_not_running();
OK_33 ->
config_ensure_not_running(),
@@ -1157,7 +1157,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason51} ->
?IPRINT("start failed (as expected): ~p", [Reason51]),
- ?line {failed_check, _, _, _, {bad_domain, _}} = Reason51,
+ {failed_check, _, _, _, {bad_domain, _}} = Reason51,
config_ensure_not_running();
OK_51 ->
config_ensure_not_running(),
@@ -1171,7 +1171,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason52} ->
?IPRINT("start failed (as expected): ~p", [Reason52]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason52,
+ {failed_check, _, _, _, {bad_address, _}} = Reason52,
config_ensure_not_running();
OK_52 ->
config_ensure_not_running(),
@@ -1185,7 +1185,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason53} ->
?IPRINT("start failed (as expected): ~p", [Reason53]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason53,
+ {failed_check, _, _, _, {bad_address, _}} = Reason53,
config_ensure_not_running();
OK_53 ->
config_ensure_not_running(),
@@ -1199,7 +1199,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, Reason54} ->
?IPRINT("start failed (as expected): ~p", [Reason54]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason54,
+ {failed_check, _, _, _, {bad_address, _}} = Reason54,
config_ensure_not_running();
OK_54 ->
config_ensure_not_running(),
@@ -1210,162 +1210,162 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 55] write agents config file with invalid ip (5)"),
Agent55 = setelement(4, Agent0, "[192,168,0,arne]"),
write_agents_conf(ConfDir, [Agent55]),
- ?line {error, Reason55} = config_start(Opts),
+ {error, Reason55} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason55]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason55,
+ {failed_check, _, _, _, {bad_address, _}} = Reason55,
config_ensure_not_running(),
%% --
?IPRINT("[test 61] write agents config file with invalid port (1)"),
Agent61 = setelement(5, Agent0, "kalle_anka"),
write_agents_conf(ConfDir, [Agent61]),
- ?line {error, Reason61} = config_start(Opts),
+ {error, Reason61} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason61]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason61,
+ {failed_check, _, _, _, {bad_address, _}} = Reason61,
config_ensure_not_running(),
%% --
?IPRINT("[test 62] write agents config file with invalid port (2)"),
Agent62 = setelement(5, Agent0, "-1"),
write_agents_conf(ConfDir, [Agent62]),
- ?line {error, Reason62} = config_start(Opts),
+ {error, Reason62} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason62]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason62,
+ {failed_check, _, _, _, {bad_address, _}} = Reason62,
config_ensure_not_running(),
%% --
?IPRINT("[test 63] write agents config file with invalid port (3)"),
Agent63 = setelement(5, Agent0, "\"100\""),
write_agents_conf(ConfDir, [Agent63]),
- ?line {error, Reason63} = config_start(Opts),
+ {error, Reason63} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason63]),
- ?line {failed_check, _, _, _, {bad_address, _}} = Reason63,
+ {failed_check, _, _, _, {bad_address, _}} = Reason63,
config_ensure_not_running(),
%% --
?IPRINT("[test 71] write agents config file with invalid engine-id (1)"),
Agent71 = setelement(6, Agent0, "kalle_anka"),
write_agents_conf(ConfDir, [Agent71]),
- ?line {error, Reason71} = config_start(Opts),
+ {error, Reason71} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason71]),
- ?line {failed_check, _, _, _, {invalid_string, _}} = Reason71,
+ {failed_check, _, _, _, {invalid_string, _}} = Reason71,
config_ensure_not_running(),
%% --
?IPRINT("[test 72] write agents config file with invalid engine-id (2)"),
Agent72 = setelement(6, Agent0, "10101"),
write_agents_conf(ConfDir, [Agent72]),
- ?line {error, Reason72} = config_start(Opts),
+ {error, Reason72} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason72]),
- ?line {failed_check, _, _, _, {invalid_string, _}} = Reason72,
+ {failed_check, _, _, _, {invalid_string, _}} = Reason72,
config_ensure_not_running(),
%% --
?IPRINT("[test 81] write agents config file with invalid timeout (1)"),
Agent81 = setelement(7, Agent0, "kalle_anka"),
write_agents_conf(ConfDir, [Agent81]),
- ?line {error, Reason81} = config_start(Opts),
+ {error, Reason81} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason81]),
- ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason81,
+ {failed_check, _, _, _, {invalid_timer, _}} = Reason81,
config_ensure_not_running(),
%% --
?IPRINT("[test 82] write agents config file with invalid timeout (2)"),
Agent82 = setelement(7, Agent0, "-1"),
write_agents_conf(ConfDir, [Agent82]),
- ?line {error, Reason82} = config_start(Opts),
+ {error, Reason82} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason82]),
- ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason82,
+ {failed_check, _, _, _, {invalid_timer, _}} = Reason82,
config_ensure_not_running(),
%% --
?IPRINT("[test 83] write agents config file with invalid timeout (3)"),
Agent83 = setelement(7, Agent0, "{1000, 1, 10, kalle}"),
write_agents_conf(ConfDir, [Agent83]),
- ?line {error, Reason83} = config_start(Opts),
+ {error, Reason83} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason83]),
- ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason83,
+ {failed_check, _, _, _, {invalid_timer, _}} = Reason83,
config_ensure_not_running(),
%% --
?IPRINT("[test 84] write agents config file with invalid timeout (4)"),
Agent84 = setelement(7, Agent0, "{1000, -1, 10, 10}"),
write_agents_conf(ConfDir, [Agent84]),
- ?line {error, Reason84} = config_start(Opts),
+ {error, Reason84} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason84]),
- ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason84,
+ {failed_check, _, _, _, {invalid_timer, _}} = Reason84,
config_ensure_not_running(),
%% --
?IPRINT("[test 85] write agents config file with invalid timeout (5)"),
Agent85 = setelement(7, Agent0, "{1000, 1, -100, 10}"),
write_agents_conf(ConfDir, [Agent85]),
- ?line {error, Reason85} = config_start(Opts),
+ {error, Reason85} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason85]),
- ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason85,
+ {failed_check, _, _, _, {invalid_timer, _}} = Reason85,
config_ensure_not_running(),
%% --
?IPRINT("[test 86] write agents config file with invalid timeout (6)"),
Agent86 = setelement(7, Agent0, "{1000, 1, 100, -1}"),
write_agents_conf(ConfDir, [Agent86]),
- ?line {error, Reason86} = config_start(Opts),
+ {error, Reason86} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason86]),
- ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason86,
+ {failed_check, _, _, _, {invalid_timer, _}} = Reason86,
config_ensure_not_running(),
%% --
?IPRINT("[test 91] write agents config file with invalid max-message-size (1)"),
Agent91 = setelement(8, Agent0, "483"),
write_agents_conf(ConfDir, [Agent91]),
- ?line {error, Reason91} = config_start(Opts),
+ {error, Reason91} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason91]),
- ?line {failed_check, _, _, _, {invalid_packet_size, _}} = Reason91,
+ {failed_check, _, _, _, {invalid_packet_size, _}} = Reason91,
config_ensure_not_running(),
%% --
?IPRINT("[test 92] write agents config file with invalid max-message-size (2)"),
Agent92 = setelement(8, Agent0, "kalle_anka"),
write_agents_conf(ConfDir, [Agent92]),
- ?line {error, Reason92} = config_start(Opts),
+ {error, Reason92} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason92]),
- ?line {failed_check, _, _, _, {invalid_packet_size, _}} = Reason92,
+ {failed_check, _, _, _, {invalid_packet_size, _}} = Reason92,
config_ensure_not_running(),
%% --
?IPRINT("[test A1] write agents config file with invalid version (1)"),
AgentA1 = setelement(9, Agent0, "1"),
write_agents_conf(ConfDir, [AgentA1]),
- ?line {error, ReasonA1} = config_start(Opts),
+ {error, ReasonA1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [ReasonA1]),
- ?line {failed_check, _, _, _, {bad_version, _}} = ReasonA1,
+ {failed_check, _, _, _, {bad_version, _}} = ReasonA1,
config_ensure_not_running(),
%% --
?IPRINT("[test A2] write agents config file with invalid version (2)"),
AgentA2 = setelement(9, Agent0, "v30"),
write_agents_conf(ConfDir, [AgentA2]),
- ?line {error, ReasonA2} = config_start(Opts),
+ {error, ReasonA2} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [ReasonA2]),
- ?line {failed_check, _, _, _, {bad_version, _}} = ReasonA2,
+ {failed_check, _, _, _, {bad_version, _}} = ReasonA2,
config_ensure_not_running(),
%% --
?IPRINT("[test B1] write agents config file with invalid sec-model (1)"),
AgentB1 = setelement(10, Agent0, "\"any\""),
write_agents_conf(ConfDir, [AgentB1]),
- ?line {error, ReasonB1} = config_start(Opts),
+ {error, ReasonB1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [ReasonB1]),
- ?line {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB1,
+ {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB1,
config_ensure_not_running(),
%% --
?IPRINT("[test B2] write agents config file with invalid sec-model (2)"),
AgentB2 = setelement(10, Agent0, "v3"),
write_agents_conf(ConfDir, [AgentB2]),
- ?line {error, ReasonB2} = config_start(Opts),
+ {error, ReasonB2} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [ReasonB2]),
- ?line {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB2,
+ {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB2,
config_ensure_not_running(),
%% --
@@ -1375,7 +1375,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, ReasonC1} ->
?IPRINT("start failed (as expected): ~p", [ReasonC1]),
- ?line {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC1,
+ {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC1,
config_ensure_not_running();
OK_C1 ->
config_ensure_not_running(),
@@ -1389,7 +1389,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, ReasonC2} ->
?IPRINT("start failed (as expected): ~p", [ReasonC2]),
- ?line {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC2,
+ {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC2,
config_ensure_not_running();
OK_C2 ->
config_ensure_not_running(),
@@ -1403,7 +1403,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, ReasonD1} ->
?IPRINT("start failed (as expected): ~p", [ReasonD1]),
- ?line {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD1,
+ {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD1,
config_ensure_not_running();
OK_D1 ->
config_ensure_not_running(),
@@ -1417,7 +1417,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, ReasonD2} ->
?IPRINT("start failed (as expected): ~p", [ReasonD2]),
- ?line {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD2,
+ {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD2,
config_ensure_not_running();
OK_D2 ->
config_ensure_not_running(),
@@ -1430,7 +1430,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) ->
case config_start(Opts) of
{error, ReasonE1} ->
?IPRINT("start failed (as expected): ~p", [ReasonE1]),
- ?line {failed_check, _, _, _, {bad_agent_config, _}} = ReasonE1,
+ {failed_check, _, _, _, {bad_agent_config, _}} = ReasonE1,
config_ensure_not_running();
OK_E1 ->
config_ensure_not_running(),
@@ -1487,146 +1487,146 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 11] write usm config file with invalid engine-id (1)"),
Usm11 = setelement(1, Usm0, "kalle-anka"),
write_usm_conf(ConfDir, [Usm11]),
- ?line {error, Reason11} = config_start(Opts),
+ {error, Reason11} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason11]),
- ?line {failed_reading, _, _, _, {parse_error, _}} = Reason11,
+ {failed_reading, _, _, _, {parse_error, _}} = Reason11,
config_ensure_not_running(),
%% --
?IPRINT("[test 12] write usm config file with invalid engine-id (2)"),
Usm12 = setelement(1, Usm0, "kalle_anka"),
write_usm_conf(ConfDir, [Usm12]),
- ?line {error, Reason12} = config_start(Opts),
+ {error, Reason12} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason12]),
- ?line {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason12,
+ {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason12,
config_ensure_not_running(),
%% --
?IPRINT("[test 13] write usm config file with invalid engine-id (3)"),
Usm13 = setelement(1, Usm1, "10101"),
write_usm_conf(ConfDir, [Usm13]),
- ?line {error, Reason13} = config_start(Opts),
+ {error, Reason13} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason13]),
- ?line {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason13,
+ {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason13,
config_ensure_not_running(),
%% --
?IPRINT("[test 21] write usm config file with invalid user-name (1)"),
Usm21 = setelement(2, Usm0, "kalle_anka"),
write_usm_conf(ConfDir, [Usm21]),
- ?line {error, Reason21} = config_start(Opts),
+ {error, Reason21} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason21]),
- ?line {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason21,
+ {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason21,
config_ensure_not_running(),
%% --
?IPRINT("[test 22] write usm config file with invalid user-name (1)"),
Usm22 = setelement(2, Usm1, "10101"),
write_usm_conf(ConfDir, [Usm22]),
- ?line {error, Reason22} = config_start(Opts),
+ {error, Reason22} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason22]),
- ?line {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason22,
+ {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason22,
config_ensure_not_running(),
%% --
?IPRINT("[test 31] write usm config file with invalid sec-name (1)"),
Usm31 = setelement(3, Usm1, "kalle_anka"),
write_usm_conf(ConfDir, [Usm31]),
- ?line {error, Reason31} = config_start(Opts),
+ {error, Reason31} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason31]),
- ?line {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason31,
+ {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason31,
config_ensure_not_running(),
%% --
?IPRINT("[test 32] write usm config file with invalid sec-name (2)"),
Usm32 = setelement(3, Usm1, "10101"),
write_usm_conf(ConfDir, [Usm32]),
- ?line {error, Reason32} = config_start(Opts),
+ {error, Reason32} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason32]),
- ?line {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason32,
+ {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason32,
config_ensure_not_running(),
%% --
?IPRINT("[test 41] write usm config file with invalid auth-protocol (1)"),
Usm41 = setelement(3, Usm0, "\"usmNoAuthProtocol\""),
write_usm_conf(ConfDir, [Usm41]),
- ?line {error, Reason41} = config_start(Opts),
+ {error, Reason41} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason41]),
- ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason41,
+ {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason41,
config_ensure_not_running(),
%% --
?IPRINT("[test 42] write usm config file with invalid auth-protocol (2)"),
Usm42 = setelement(3, Usm0, "kalle"),
write_usm_conf(ConfDir, [Usm42]),
- ?line {error, Reason42} = config_start(Opts),
+ {error, Reason42} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason42]),
- ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason42,
+ {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason42,
config_ensure_not_running(),
%% --
?IPRINT("[test 43] write usm config file with invalid auth-protocol (3)"),
Usm43 = setelement(3, Usm0, "10101"),
write_usm_conf(ConfDir, [Usm43]),
- ?line {error, Reason43} = config_start(Opts),
+ {error, Reason43} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason43]),
- ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason43,
+ {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason43,
config_ensure_not_running(),
%% --
?IPRINT("[test 51.1] write (auth md5) usm config file with invalid auth-key (1)"),
Usm51_1 = setelement(3, Usm0, "usmHMACMD5AuthProtocol"),
write_usm_conf(ConfDir, [Usm51_1]),
- ?line {error, Reason51_1} = config_start(Opts),
+ {error, Reason51_1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason51_1]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason51_1,
+ {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason51_1,
config_ensure_not_running(),
%% --
?IPRINT("[test 51.2] write (auth md5) usm config file with invalid auth-key (2)"),
Usm51_2 = setelement(4, Usm51_1, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]"),
write_usm_conf(ConfDir, [Usm51_2]),
- ?line {error, Reason51_2} = config_start(Opts),
+ {error, Reason51_2} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason51_2]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 15}} = Reason51_2,
+ {failed_check, _, _, _, {invalid_auth_key, _, 15}} = Reason51_2,
config_ensure_not_running(),
%% --
?IPRINT("[test 51.3] write (auth md5) usm config file with invalid auth-key (3)"),
Usm51_3 = setelement(4, Usm51_1, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"),
write_usm_conf(ConfDir, [Usm51_3]),
- ?line {error, Reason51_3} = config_start(Opts),
+ {error, Reason51_3} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason51_3]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 17}} = Reason51_3,
+ {failed_check, _, _, _, {invalid_auth_key, _, 17}} = Reason51_3,
config_ensure_not_running(),
%% --
?IPRINT("[test 51.4] write (auth md5) usm config file with invalid auth-key (4)"),
Usm51_4 = setelement(4, Usm51_1, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,kalle]"),
write_usm_conf(ConfDir, [Usm51_4]),
- ?line maybe_start_crypto(), %% Make sure it's started...
- ?line {error, Reason51_4} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ maybe_start_crypto(), %% Make sure it's started...
+ {error, Reason51_4} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason51_4]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason51_4,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason51_4,
config_ensure_not_running(),
%% --
?IPRINT("[test 51.5] write (auth md5) usm config file with invalid auth-key (5)"),
Usm51_5 = setelement(4, Usm51_1, "arne_anka"),
write_usm_conf(ConfDir, [Usm51_5]),
- ?line {error, Reason51_5} = config_start(Opts),
+ {error, Reason51_5} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason51_5]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason51_5,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason51_5,
config_ensure_not_running(),
%% --
?IPRINT("[test 51.6] write (auth md5) usm config file with invalid auth-key (6)"),
Usm51_6 = setelement(4, Usm51_1, "10101"),
write_usm_conf(ConfDir, [Usm51_6]),
- ?line {error, Reason51_6} = config_start(Opts),
+ {error, Reason51_6} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason51_6]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason51_6,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason51_6,
config_ensure_not_running(),
@@ -1635,29 +1635,29 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 52.1] write (auth sha) usm config file with invalid auth-key (1)"),
Usm52_1 = setelement(3, Usm0, "usmHMACSHAAuthProtocol"),
write_usm_conf(ConfDir, [Usm52_1]),
- ?line {error, Reason52_1} = config_start(Opts),
+ {error, Reason52_1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason52_1]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason52_1,
+ {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason52_1,
config_ensure_not_running(),
%% --
?IPRINT("[test 52.2] write (auth sha) usm config file with invalid auth-key (2)"),
Usm52_2 = setelement(4, Usm52_1, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]"),
write_usm_conf(ConfDir, [Usm52_2]),
- ?line {error, Reason52_2} = config_start(Opts),
+ {error, Reason52_2} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason52_2]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 16}} = Reason52_2,
+ {failed_check, _, _, _, {invalid_auth_key, _, 16}} = Reason52_2,
config_ensure_not_running(),
%% --
?IPRINT("[test 52.3] write (auth sha) usm config file with invalid auth-key (3)"),
Usm52_3 = setelement(4, Usm52_1, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,ka]"),
write_usm_conf(ConfDir, [Usm52_3]),
- ?line ok = maybe_start_crypto(),
- ?line {error, Reason52_3} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ ok = maybe_start_crypto(),
+ {error, Reason52_3} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason52_3]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason52_3,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason52_3,
config_ensure_not_running(),
@@ -1666,9 +1666,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 53.1] write (auth sha224) usm config file with invalid auth-key (1)"),
Usm53_1 = setelement(3, Usm0, "usmHMAC128SHA224AuthProtocol"),
write_usm_conf(ConfDir, [Usm53_1]),
- ?line {error, Reason53_1} = config_start(Opts),
+ {error, Reason53_1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason53_1]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason53_1,
+ {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason53_1,
config_ensure_not_running(),
%% --
@@ -1676,7 +1676,7 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm53_2 = setelement(4, Usm53_1,
"[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]"),
write_usm_conf(ConfDir, [Usm53_2]),
- ?line {ok, _} = config_start(Opts),
+ {ok, _} = config_start(Opts),
?IPRINT("expected start success"),
config_ensure_not_running(),
@@ -1685,9 +1685,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm53_3 = setelement(4, Usm53_1,
"[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]"),
write_usm_conf(ConfDir, [Usm53_3]),
- ?line {error, Reason53_3} = config_start(Opts),
+ {error, Reason53_3} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason53_3]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 27}} = Reason53_3,
+ {failed_check, _, _, _, {invalid_auth_key, _, 27}} = Reason53_3,
config_ensure_not_running(),
%% --
@@ -1695,11 +1695,11 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm53_4 = setelement(4, Usm53_1,
"[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,ka]"),
write_usm_conf(ConfDir, [Usm53_4]),
- ?line ok = maybe_start_crypto(),
- ?line {error, Reason53_4} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ ok = maybe_start_crypto(),
+ {error, Reason53_4} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason53_4]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason53_4,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason53_4,
config_ensure_not_running(),
@@ -1707,9 +1707,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 54.1] write (auth sha256) usm config file with invalid auth-key (1)"),
Usm54_1 = setelement(3, Usm0, "usmHMAC192SHA256AuthProtocol"),
write_usm_conf(ConfDir, [Usm54_1]),
- ?line {error, Reason54_1} = config_start(Opts),
+ {error, Reason54_1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason54_1]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason54_1,
+ {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason54_1,
config_ensure_not_running(),
%% --
@@ -1717,7 +1717,7 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm54_2 = setelement(4, Usm54_1,
"[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,2]"),
write_usm_conf(ConfDir, [Usm54_2]),
- ?line {ok, _} = config_start(Opts),
+ {ok, _} = config_start(Opts),
?IPRINT("expected start success"),
config_ensure_not_running(),
@@ -1726,9 +1726,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm54_3 = setelement(4, Usm54_1,
"[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]"),
write_usm_conf(ConfDir, [Usm54_3]),
- ?line {error, Reason54_3} = config_start(Opts),
+ {error, Reason54_3} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason54_3]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 31}} = Reason54_3,
+ {failed_check, _, _, _, {invalid_auth_key, _, 31}} = Reason54_3,
config_ensure_not_running(),
%% --
@@ -1736,11 +1736,11 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm54_4 = setelement(4, Usm54_1,
"[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,ka]"),
write_usm_conf(ConfDir, [Usm54_4]),
- ?line ok = maybe_start_crypto(),
- ?line {error, Reason54_4} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ ok = maybe_start_crypto(),
+ {error, Reason54_4} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason54_4]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason54_4,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason54_4,
config_ensure_not_running(),
@@ -1748,9 +1748,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 55.1] write (auth sha384) usm config file with invalid auth-key (1)"),
Usm55_1 = setelement(3, Usm0, "usmHMAC256SHA384AuthProtocol"),
write_usm_conf(ConfDir, [Usm55_1]),
- ?line {error, Reason55_1} = config_start(Opts),
+ {error, Reason55_1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason55_1]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason55_1,
+ {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason55_1,
config_ensure_not_running(),
%% --
@@ -1758,7 +1758,7 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm55_2 = setelement(4, Usm55_1,
"[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,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8]"),
write_usm_conf(ConfDir, [Usm55_2]),
- ?line {ok, _} = config_start(Opts),
+ {ok, _} = config_start(Opts),
?IPRINT("expected start success"),
config_ensure_not_running(),
@@ -1767,9 +1767,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm55_3 = setelement(4, Usm55_1,
"[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,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"),
write_usm_conf(ConfDir, [Usm55_3]),
- ?line {error, Reason55_3} = config_start(Opts),
+ {error, Reason55_3} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason55_3]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 47}} = Reason55_3,
+ {failed_check, _, _, _, {invalid_auth_key, _, 47}} = Reason55_3,
config_ensure_not_running(),
%% --
@@ -1777,11 +1777,11 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm55_4 = setelement(4, Usm55_1,
"[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,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,ka]"),
write_usm_conf(ConfDir, [Usm55_4]),
- ?line ok = maybe_start_crypto(),
- ?line {error, Reason55_4} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ ok = maybe_start_crypto(),
+ {error, Reason55_4} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason55_4]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason55_4,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason55_4,
config_ensure_not_running(),
@@ -1789,9 +1789,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 56.1] write (auth sha512) usm config file with invalid auth-key (1)"),
Usm56_1 = setelement(3, Usm0, "usmHMAC384SHA512AuthProtocol"),
write_usm_conf(ConfDir, [Usm56_1]),
- ?line {error, Reason56_1} = config_start(Opts),
+ {error, Reason56_1} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason56_1]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason56_1,
+ {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason56_1,
config_ensure_not_running(),
%% --
@@ -1799,7 +1799,7 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm56_2 = setelement(4, Usm56_1,
"[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,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,2,3,4]"),
write_usm_conf(ConfDir, [Usm56_2]),
- ?line {ok, _} = config_start(Opts),
+ {ok, _} = config_start(Opts),
?IPRINT("expected start success"),
config_ensure_not_running(),
@@ -1808,9 +1808,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm56_3 = setelement(4, Usm56_1,
"[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,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,2,3]"),
write_usm_conf(ConfDir, [Usm56_3]),
- ?line {error, Reason56_3} = config_start(Opts),
+ {error, Reason56_3} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason56_3]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _, 63}} = Reason56_3,
+ {failed_check, _, _, _, {invalid_auth_key, _, 63}} = Reason56_3,
config_ensure_not_running(),
%% --
@@ -1818,11 +1818,11 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
Usm56_4 = setelement(4, Usm56_1,
"[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,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,2,3,ka]"),
write_usm_conf(ConfDir, [Usm56_4]),
- ?line ok = maybe_start_crypto(),
- ?line {error, Reason56_4} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ ok = maybe_start_crypto(),
+ {error, Reason56_4} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason56_4]),
- ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason56_4,
+ {failed_check, _, _, _, {invalid_auth_key, _}} = Reason56_4,
config_ensure_not_running(),
@@ -1830,83 +1830,83 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
?IPRINT("[test 61] write usm config file with invalid priv-protocol (1)"),
Usm61 = setelement(5, Usm0, "\"usmNoPrivProtocol\""),
write_usm_conf(ConfDir, [Usm61]),
- ?line {error, Reason61} = config_start(Opts),
+ {error, Reason61} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason61]),
- ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason61,
+ {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason61,
config_ensure_not_running(),
%% --
?IPRINT("[test 62] write usm config file with invalid priv-protocol (2)"),
Usm62 = setelement(5, Usm0, "kalle"),
write_usm_conf(ConfDir, [Usm62]),
- ?line {error, Reason62} = config_start(Opts),
+ {error, Reason62} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason62]),
- ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason62,
+ {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason62,
config_ensure_not_running(),
%% --
?IPRINT("[test 63] write usm config file with invalid priv-protocol (3)"),
Usm63 = setelement(5, Usm0, "10101"),
write_usm_conf(ConfDir, [Usm63]),
- ?line {error, Reason63} = config_start(Opts),
+ {error, Reason63} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason63]),
- ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason63,
+ {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason63,
config_ensure_not_running(),
%% --
?IPRINT("[test 71] write usm config file with invalid priv-key (1)"),
Usm71 = setelement(5, Usm0, "usmDESPrivProtocol"),
write_usm_conf(ConfDir, [Usm71]),
- ?line {error, Reason71} = config_start(Opts),
+ {error, Reason71} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason71]),
- ?line {failed_check, _, _, _, {invalid_priv_key, _, _}} = Reason71,
+ {failed_check, _, _, _, {invalid_priv_key, _, _}} = Reason71,
config_ensure_not_running(),
%% --
?IPRINT("[test 72] write usm config file with invalid priv-key (2)"),
Usm72 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]"),
write_usm_conf(ConfDir, [Usm72]),
- ?line {error, Reason72} = config_start(Opts),
+ {error, Reason72} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason72]),
- ?line {failed_check, _, _, _, {invalid_priv_key, _, 15}} = Reason72,
+ {failed_check, _, _, _, {invalid_priv_key, _, 15}} = Reason72,
config_ensure_not_running(),
%% --
?IPRINT("[test 73] write usm config file with invalid priv-key (3)"),
Usm73 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"),
write_usm_conf(ConfDir, [Usm73]),
- ?line {error, Reason73} = config_start(Opts),
+ {error, Reason73} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason73]),
- ?line {failed_check, _, _, _, {invalid_priv_key, _, 17}} = Reason73,
+ {failed_check, _, _, _, {invalid_priv_key, _, 17}} = Reason73,
config_ensure_not_running(),
%% --
?IPRINT("[test 74] write usm config file with invalid priv-key (4)"),
Usm74 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,kalle]"),
write_usm_conf(ConfDir, [Usm74]),
- ?line ok = maybe_start_crypto(),
- ?line {error, Reason74} = config_start(Opts),
- ?line ok = maybe_stop_crypto(),
+ ok = maybe_start_crypto(),
+ {error, Reason74} = config_start(Opts),
+ ok = maybe_stop_crypto(),
?IPRINT("start failed (as expected): ~p", [Reason74]),
- ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason74,
+ {failed_check, _, _, _, {invalid_priv_key, _}} = Reason74,
config_ensure_not_running(),
%% --
?IPRINT("[test 75] write usm config file with invalid priv-key (5)"),
Usm75 = setelement(6, Usm71, "arne_anka"),
write_usm_conf(ConfDir, [Usm75]),
- ?line {error, Reason75} = config_start(Opts),
+ {error, Reason75} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason75]),
- ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason75,
+ {failed_check, _, _, _, {invalid_priv_key, _}} = Reason75,
config_ensure_not_running(),
%% --
?IPRINT("[test 76] write usm config file with invalid priv-key (6)"),
Usm76 = setelement(6, Usm71, "10101"),
write_usm_conf(ConfDir, [Usm76]),
- ?line {error, Reason76} = config_start(Opts),
+ {error, Reason76} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason76]),
- ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason76,
+ {failed_check, _, _, _, {invalid_priv_key, _}} = Reason76,
config_ensure_not_running(),
%% --
@@ -1919,9 +1919,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
"when crypto not started (7)"),
Usm77 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]"),
write_usm_conf(ConfDir, [Usm77]),
- ?line {error, Reason77} = config_start(Opts),
+ {error, Reason77} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason77]),
- ?line {failed_check, _, _, _, {unsupported_crypto, _}} = Reason77,
+ {failed_check, _, _, _, {unsupported_crypto, _}} = Reason77,
config_ensure_not_running();
_ ->
%% This function is only present in version 2.0 or greater.
@@ -1933,9 +1933,9 @@ start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) ->
%% --
?IPRINT("[test 78] write usm config file with invalid usm (1)"),
write_usm_conf2(ConfDir, "{\"bmkEngine\", \"swiusmcf\"}."),
- ?line {error, Reason81} = config_start(Opts),
+ {error, Reason81} = config_start(Opts),
?IPRINT("start failed (as expected): ~p", [Reason81]),
- ?line {failed_check, _, _, _, {bad_usm_config, _}} = Reason81,
+ {failed_check, _, _, _, {bad_usm_config, _}} = Reason81,
config_ensure_not_running(),
?IPRINT("done"),
@@ -1996,17 +1996,17 @@ simple_system_op(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("start config"),
- ?line {ok, _Pid} = config_start(Opts),
+ {ok, _Pid} = config_start(Opts),
- ?IPRINT("retreive various configs"),
- ?line {ok, _Time} = snmpm_config:system_start_time(),
- ?line {ok, _EngineId} = snmpm_config:get_engine_id(),
- ?line {ok, _MMS} = snmpm_config:get_engine_max_message_size(),
+ ?IPRINT("retrieve various configs"),
+ {ok, _Time} = snmpm_config:system_start_time(),
+ {ok, _EngineId} = snmpm_config:get_engine_id(),
+ {ok, _MMS} = snmpm_config:get_engine_max_message_size(),
- ?IPRINT("attempt to retreive nonexisting"),
- ?line {error, not_found} = snmpm_config:system_info(kalle),
+ ?IPRINT("attempt to retrieve nonexisting"),
+ {error, not_found} = snmpm_config:system_info(kalle),
- ?line ok = config_stop(),
+ ok = config_stop(),
config_ensure_not_running(),
?IPRINT("done"),
@@ -2092,7 +2092,7 @@ register_agent_using_file(Conf) when is_list(Conf) ->
Case = fun(_) -> do_register_agent_using_file(Conf) end,
Post = fun(_) ->
?IPRINT("stop config process"),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
ok
end,
@@ -2151,49 +2151,49 @@ do_register_agent_using_file(Conf) ->
%% --
?IPRINT("start the config process"),
- ?line {ok, _Pid} = config_start(Opts),
+ {ok, _Pid} = config_start(Opts),
%% --
?IPRINT("which agents"),
- ?line [_, _] = All = snmpm_config:which_agents(),
+ [_, _] = All = snmpm_config:which_agents(),
?IPRINT("all agents: ~n ~p", [All]),
- ?line [A1] = snmpm_config:which_agents(UserId1),
+ [A1] = snmpm_config:which_agents(UserId1),
?IPRINT("agents belonging to ~w: ~n ~p", [UserId1, A1]),
- ?line [A2] = snmpm_config:which_agents(UserId2),
+ [A2] = snmpm_config:which_agents(UserId2),
?IPRINT("agents belonging to ~w: ~n ~p", [UserId2, A2]),
%% --
?IPRINT("All info for agent <~w,~w>", [AgentAddr1, AgentPort1]),
- ?line {ok, AllInfo1} =
+ {ok, AllInfo1} =
snmpm_config:agent_info(AgentAddr1, AgentPort1, all),
?IPRINT("all agent info for agent: ~n ~p", [AllInfo1]),
%% --
?IPRINT("EngineID (~p) for agent <~w,~w>", [EngineID1, AgentAddr1, AgentPort1]),
- ?line {ok, EngineID1} =
+ {ok, EngineID1} =
snmpm_config:agent_info(AgentAddr1, AgentPort1, engine_id),
%% --
?IPRINT("All info for agent <~w,~w>", [AgentAddr2, AgentPort2]),
- ?line {ok, AllInfo2} =
+ {ok, AllInfo2} =
snmpm_config:agent_info(AgentAddr2, AgentPort2, all),
?IPRINT("all agent info for agent: ~n ~p", [AllInfo2]),
%% --
?IPRINT("EngineID (~p) for agent <~w,~w>", [EngineID2, AgentAddr2, AgentPort2]),
- ?line {ok, EngineID2} =
+ {ok, EngineID2} =
snmpm_config:agent_info(AgentAddr2, AgentPort2, engine_id),
%% --
- ?line {ok, MMS2} =
+ {ok, MMS2} =
snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size),
NewMMS21 = 2048,
?IPRINT("try update agent info max-message-size to ~w for agent <~w,~w>",
[NewMMS21, AgentAddr2, AgentPort2]),
- ?line ok = snmpm_config:update_agent_info(UserId2, AgentAddr2, AgentPort2,
- max_message_size, NewMMS21),
- ?line {ok, NewMMS21} =
+ ok = update_agent_info(UserId2, AgentAddr2, AgentPort2,
+ max_message_size, NewMMS21),
+ {ok, NewMMS21} =
snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size),
%% --
@@ -2201,11 +2201,11 @@ do_register_agent_using_file(Conf) ->
"for agent <~w,~w> "
"with user ~w (not owner)",
[NewMMS21, AgentAddr2, AgentPort2, UserId1]),
- ?line {error, Reason01} =
- snmpm_config:update_agent_info(UserId1, AgentAddr2, AgentPort2,
- max_message_size, NewMMS21),
+ {error, Reason01} =
+ update_agent_info(UserId1, AgentAddr2, AgentPort2,
+ max_message_size, NewMMS21),
?IPRINT("expected failure. Reason01: ~p", [Reason01]),
- ?line {ok, NewMMS21} =
+ {ok, NewMMS21} =
snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size),
%% --
@@ -2213,9 +2213,9 @@ do_register_agent_using_file(Conf) ->
?IPRINT("try (and fail) to update agent info max-message-size to ~w "
"for agent <~w,~w>",
[NewMMS22, AgentAddr2, AgentPort2]),
- ?line {error, Reason02} =
- snmpm_config:update_agent_info(UserId1, AgentAddr2, AgentPort2,
- max_message_size, NewMMS22),
+ {error, Reason02} =
+ update_agent_info(UserId1, AgentAddr2, AgentPort2,
+ max_message_size, NewMMS22),
?IPRINT("expected failure. Reason02: ~p", [Reason02]),
%% --
@@ -2245,7 +2245,7 @@ register_agent_using_function(Conf) when is_list(Conf) ->
register_agent_failed_using_function1(suite) -> [];
register_agent_failed_using_function1(doc) ->
- "Register agents failng using the API (function) with incorrect "
+ "Register agents failing using the API (function) with incorrect "
"config (1).";
register_agent_failed_using_function1(Conf) when is_list(Conf) ->
put(tname, "REG-AG-FAIL-USING-FUNC-1"),
@@ -2318,26 +2318,26 @@ register_usm_user_using_file(Conf) when is_list(Conf) ->
%% --
?IPRINT("start the config process"),
- ?line {ok, _Pid} = config_start(Opts),
+ {ok, _Pid} = config_start(Opts),
%% --
?IPRINT("lookup 1 (ok)"),
- ?line {ok, #usm_user{name = UserName1} = User1} =
+ {ok, #usm_user{name = UserName1} = User1} =
snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName1),
?IPRINT("User: ~p", [User1]),
?IPRINT("lookup 2 (ok)"),
- ?line {ok, #usm_user{name = UserName2} = User2} =
+ {ok, #usm_user{name = UserName2} = User2} =
snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName2),
?IPRINT("User: ~p", [User2]),
?IPRINT("lookup 3 (error)"),
- ?line {error, not_found} =
+ {error, not_found} =
snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName2 ++ "_1"),
%% --
?IPRINT("stop config process"),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
%% --
@@ -2386,7 +2386,7 @@ register_usm_user_using_function(Conf) when is_list(Conf) ->
%% --
?IPRINT("start the config process"),
- ?line {ok, _Pid} = config_start(Opts),
+ {ok, _Pid} = config_start(Opts),
%% --
?IPRINT("register usm user's"),
@@ -2400,9 +2400,9 @@ register_usm_user_using_function(Conf) when is_list(Conf) ->
{auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]},
{priv, usmNoPrivProtocol}],
- ?line ok = snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1),
+ ok = snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1),
?IPRINT("try register user 1 again (error)"),
- ?line {error, {already_registered, EngineID, UserName1}} =
+ {error, {already_registered, EngineID, UserName1}} =
snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1),
?IPRINT("register user 2 (ok)"),
@@ -2411,7 +2411,7 @@ register_usm_user_using_function(Conf) when is_list(Conf) ->
UsmConfig2 = [{auth, usmHMACMD5AuthProtocol},
{auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]},
{priv, usmNoPrivProtocol}],
- ?line ok = snmpm_config:register_usm_user(EngineID, UserName2, UsmConfig2),
+ ok = snmpm_config:register_usm_user(EngineID, UserName2, UsmConfig2),
?IPRINT("register user 3 (ok)"),
UserName3 = "samu3",
@@ -2420,7 +2420,7 @@ register_usm_user_using_function(Conf) when is_list(Conf) ->
{auth, usmHMACMD5AuthProtocol},
{auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]},
{priv, usmNoPrivProtocol}],
- ?line ok = snmpm_config:register_usm_user(EngineID, UserName3, UsmConfig3),
+ ok = snmpm_config:register_usm_user(EngineID, UserName3, UsmConfig3),
?IPRINT("register user 4 (ok)"),
UserName4 = "samu4",
@@ -2430,35 +2430,35 @@ register_usm_user_using_function(Conf) when is_list(Conf) ->
{auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]},
{priv, usmAesCfb128Protocol},
{priv_key, [190,54,66,227,33,171,152,0,133,223,204,155,109,111,77,44]}],
- ?line ok = snmpm_config:register_usm_user(EngineID, UserName4, UsmConfig4),
+ ok = snmpm_config:register_usm_user(EngineID, UserName4, UsmConfig4),
?IPRINT("lookup 1 (ok)"),
- ?line {ok, #usm_user{name = UserName1} = User1} =
+ {ok, #usm_user{name = UserName1} = User1} =
snmpm_config:get_usm_user_from_sec_name(EngineID, SecName1),
?IPRINT("User: ~p", [User1]),
?IPRINT("lookup 2 (ok)"),
- ?line {ok, #usm_user{name = UserName2} = User2} =
+ {ok, #usm_user{name = UserName2} = User2} =
snmpm_config:get_usm_user_from_sec_name(EngineID, SecName2),
?IPRINT("User: ~p", [User2]),
?IPRINT("lookup 3 (ok)"),
- ?line {ok, #usm_user{name = UserName3} = User3} =
+ {ok, #usm_user{name = UserName3} = User3} =
snmpm_config:get_usm_user_from_sec_name(EngineID, SecName3),
?IPRINT("User: ~p", [User3]),
?IPRINT("lookup 4 (ok)"),
- ?line {ok, #usm_user{name = UserName4} = User4} =
+ {ok, #usm_user{name = UserName4} = User4} =
snmpm_config:get_usm_user_from_sec_name(EngineID, SecName4),
?IPRINT("User: ~p", [User4]),
?IPRINT("lookup 5 (error)"),
- ?line {error, not_found} =
+ {error, not_found} =
snmpm_config:get_usm_user_from_sec_name(EngineID, SecName4 ++ "_1"),
%% --
?IPRINT("stop config process"),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
%% --
@@ -2535,7 +2535,7 @@ update_usm_user_info(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("Start config server"),
- ?line {ok, _Pid} = snmpm_config:start_link(Opts),
+ {ok, _Pid} = snmpm_config:start_link(Opts),
?IPRINT("Register usm user"),
EngineID = "engine",
@@ -2551,9 +2551,9 @@ update_usm_user_info(Conf) when is_list(Conf) ->
ok = snmpm_config:register_usm_user(EngineID, UsmUser, UsmConfig),
?IPRINT("verify user user config"),
- ?line {ok, AuthProto} = snmpm_config:usm_user_info(EngineID, UsmUser, auth),
- ?line {ok, AuthKey} = snmpm_config:usm_user_info(EngineID, UsmUser, auth_key),
- ?line {ok, PrivProto1} = snmpm_config:usm_user_info(EngineID, UsmUser, priv),
+ {ok, AuthProto} = snmpm_config:usm_user_info(EngineID, UsmUser, auth),
+ {ok, AuthKey} = snmpm_config:usm_user_info(EngineID, UsmUser, auth_key),
+ {ok, PrivProto1} = snmpm_config:usm_user_info(EngineID, UsmUser, priv),
?IPRINT("usm user update 1"),
PrivProto2 = usmAesCfb128Protocol,
@@ -2562,22 +2562,22 @@ update_usm_user_info(Conf) when is_list(Conf) ->
ok = snmpm_config:update_usm_user_info(EngineID, UsmUser, priv_key, PrivKey2),
?IPRINT("verify updated user user config after update 1"),
- ?line {ok, AuthProto} = snmpm_config:usm_user_info(EngineID, UsmUser, auth),
- ?line {ok, AuthKey} = snmpm_config:usm_user_info(EngineID, UsmUser, auth_key),
- ?line {ok, PrivProto2} = snmpm_config:usm_user_info(EngineID, UsmUser, priv),
- ?line {ok, PrivKey2} = snmpm_config:usm_user_info(EngineID, UsmUser, priv_key),
+ {ok, AuthProto} = snmpm_config:usm_user_info(EngineID, UsmUser, auth),
+ {ok, AuthKey} = snmpm_config:usm_user_info(EngineID, UsmUser, auth_key),
+ {ok, PrivProto2} = snmpm_config:usm_user_info(EngineID, UsmUser, priv),
+ {ok, PrivKey2} = snmpm_config:usm_user_info(EngineID, UsmUser, priv_key),
?IPRINT("usm user update 2"),
PrivProto3 = PrivProto1,
ok = snmpm_config:update_usm_user_info(EngineID, UsmUser, priv, PrivProto3),
?IPRINT("verify updated user user config after update 2"),
- ?line {ok, AuthProto} = snmpm_config:usm_user_info(EngineID, UsmUser, auth),
- ?line {ok, AuthKey} = snmpm_config:usm_user_info(EngineID, UsmUser, auth_key),
- ?line {ok, PrivProto3} = snmpm_config:usm_user_info(EngineID, UsmUser, priv),
+ {ok, AuthProto} = snmpm_config:usm_user_info(EngineID, UsmUser, auth),
+ {ok, AuthKey} = snmpm_config:usm_user_info(EngineID, UsmUser, auth_key),
+ {ok, PrivProto3} = snmpm_config:usm_user_info(EngineID, UsmUser, priv),
?IPRINT("Stop config server"),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
?IPRINT("done"),
ok.
@@ -2595,7 +2595,7 @@ update_usm_user_info(Conf) when is_list(Conf) ->
create_and_increment(suite) -> [];
create_and_increment(doc) ->
- "Craete and increment counters.";
+ "Create and increment counters.";
create_and_increment(Conf) when is_list(Conf) ->
put(tname, "CRE-AND-INC"),
?IPRINT("start"),
@@ -2609,7 +2609,7 @@ create_and_increment(Conf) when is_list(Conf) ->
Opts = [{versions, [v1]},
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
- ?line {ok, _Pid} = snmpm_config:start_link(Opts),
+ {ok, _Pid} = snmpm_config:start_link(Opts),
%% Random init
?SNMP_RAND_SEED(),
@@ -2618,10 +2618,10 @@ create_and_increment(Conf) when is_list(Conf) ->
IncVal = 42,
EndVal = StartVal + IncVal,
- ?line StartVal = snmpm_config:cre_counter(test_id, StartVal),
- ?line EndVal = snmpm_config:incr_counter(test_id, IncVal),
+ StartVal = snmpm_config:cre_counter(test_id, StartVal),
+ EndVal = snmpm_config:incr_counter(test_id, IncVal),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
ok.
@@ -2652,27 +2652,27 @@ stats_create_and_increment(Conf) when is_list(Conf) ->
Opts = [{versions, [v1]},
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
- ?line {ok, _Pid} = snmpm_config:start_link(Opts),
+ {ok, _Pid} = snmpm_config:start_link(Opts),
?IPRINT("stats table (1): ~p", [ets:tab2list(snmpm_stats_table)]),
- ?line 0 = snmpm_config:maybe_cre_stats_counter(stats1, 0),
+ 0 = snmpm_config:maybe_cre_stats_counter(stats1, 0),
?IPRINT("stats table (2): ~p", [ets:tab2list(snmpm_stats_table)]),
- ?line ok = snmpm_config:maybe_cre_stats_counter(stats1, 0),
+ ok = snmpm_config:maybe_cre_stats_counter(stats1, 0),
?IPRINT("stats table (3): ~p", [ets:tab2list(snmpm_stats_table)]),
- ?line 1 = snmpm_config:maybe_cre_stats_counter(stats2, 1),
+ 1 = snmpm_config:maybe_cre_stats_counter(stats2, 1),
?IPRINT("stats table (4): ~p", [ets:tab2list(snmpm_stats_table)]),
- ?line 10 = snmpm_config:cre_stats_counter(stats3, 10),
+ 10 = snmpm_config:cre_stats_counter(stats3, 10),
?IPRINT("stats table (5): ~p", [ets:tab2list(snmpm_stats_table)]),
Stats1Inc = fun() -> snmpm_config:incr_stats_counter(stats1, 1) end,
- ?line 10 = loop(10, -1, Stats1Inc),
+ 10 = loop(10, -1, Stats1Inc),
?IPRINT("stats table (6): ~p", [ets:tab2list(snmpm_stats_table)]),
- ?line ok = snmpm_config:reset_stats_counter(stats1),
+ ok = snmpm_config:reset_stats_counter(stats1),
- ?line 10 = loop(10, -1, Stats1Inc),
+ 10 = loop(10, -1, Stats1Inc),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
ok.
@@ -2710,13 +2710,13 @@ otp_7219(Config) when is_list(Config) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("start manager config"),
- ?line {ok, _Pid1} = snmpm_config:start_link(Opts1),
+ {ok, _Pid1} = snmpm_config:start_link(Opts1),
?IPRINT("get some manager config"),
{ok, {user, _}} = snmpm_config:system_info(net_if_irb),
?IPRINT("stop manager config"),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
IRB_TO = 15322,
@@ -2725,13 +2725,13 @@ otp_7219(Config) when is_list(Config) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("start manager config"),
- ?line {ok, _Pid2} = snmpm_config:start_link(Opts2),
+ {ok, _Pid2} = snmpm_config:start_link(Opts2),
?IPRINT("get some manager config"),
{ok, {user, IRB_TO}} = snmpm_config:system_info(net_if_irb),
?IPRINT("stop manager config"),
- ?line ok = snmpm_config:stop(),
+ ok = snmpm_config:stop(),
config_ensure_not_running(),
?IPRINT("done"),
@@ -2808,7 +2808,7 @@ otp8395(Conf, SeqNoVal, Expect) ->
case config_start(Opts) of
{ok, _Pid} when (Expect =:= ok) ->
- ?line ok = config_stop(),
+ ok = config_stop(),
ok;
{ok, _Pid} when (Expect =/= ok) ->
config_stop(),
@@ -2867,7 +2867,7 @@ otp_8395_4(Conf) when is_list(Conf) ->
{mibs, Mibs},
{versions, Vsns}],
- ?line {ok, _Pid} = config_start(Opts),
+ {ok, _Pid} = config_start(Opts),
Counter = otp_8395_4,
Initial = 10,
@@ -2885,7 +2885,7 @@ otp_8395_4(Conf) when is_list(Conf) ->
Val2 = Initial + Increment,
Val2 = otp8395_incr_counter(Counter, Initial, Increment, Max),
- ?line ok = config_stop(),
+ ok = config_stop(),
?IPRINT("done"),
ok.
@@ -2899,6 +2899,14 @@ otp8395_incr_counter(Counter, Initial, Increment, Max) ->
%% Internal functions
%%======================================================================
+update_agent_info(UserId, Addr, Port, Item, Val) ->
+ case snmpm_config:agent_info(Addr, Port, target_name) of
+ {ok, TargetName} ->
+ snmpm_config:update_agent_info(UserId, TargetName, [{Item, Val}]);
+ Error ->
+ Error
+ end.
+
config_start(Opts) ->
(catch snmpm_config:start_link(Opts)).
@@ -3016,7 +3024,7 @@ write_usm_conf2(Dir, Str) ->
write_conf_file(Dir, File, Str) ->
case file:open(filename:join(Dir, File), write) of
{ok, Fd} ->
- ?line ok = io:format(Fd, "~s", [Str]),
+ ok = io:format(Fd, "~s", [Str]),
file:close(Fd);
{error, Reason} ->
Info =
diff --git a/lib/snmp/test/snmp_manager_user_SUITE.erl b/lib/snmp/test/snmp_manager_user_SUITE.erl
index 04a75232b7..b4789bfe89 100644
--- a/lib/snmp/test/snmp_manager_user_SUITE.erl
+++ b/lib/snmp/test/snmp_manager_user_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -202,16 +202,16 @@ init_per_testcase(Case, Config) when is_list(Config) ->
SuiteTopDir = ?config(snmp_suite_top_dir, Config),
CaseTopDir = filename:join(SuiteTopDir, atom_to_list(Case)),
- ?line ok = file:make_dir(CaseTopDir),
+ ok = file:make_dir(CaseTopDir),
?IPRINT("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]),
MgrTopDir = filename:join(CaseTopDir, "manager/"),
- ?line ok = file:make_dir(MgrTopDir),
+ ok = file:make_dir(MgrTopDir),
MgrConfDir = filename:join(MgrTopDir, "conf/"),
- ?line ok = file:make_dir(MgrConfDir),
+ ok = file:make_dir(MgrConfDir),
MgrDbDir = filename:join(MgrTopDir, "db/"),
- ?line ok = file:make_dir(MgrDbDir),
+ ok = file:make_dir(MgrDbDir),
MgrLogDir = filename:join(MgrTopDir, "log/"),
- ?line ok = file:make_dir(MgrLogDir),
+ ok = file:make_dir(MgrLogDir),
Config1 = [{case_top_dir, CaseTopDir},
{manager_dir, MgrTopDir},
@@ -267,24 +267,24 @@ simple_register_and_unregister1(Conf) when is_list(Conf) ->
Id = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid, Id),
+ ok = register_user(Pid, Id),
- ?line [Id] = Users2 = which_users(),
+ [Id] = Users2 = which_users(),
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = unregister_user(Pid),
+ ok = unregister_user(Pid),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line stop_user(Pid),
+ stop_user(Pid),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -319,15 +319,15 @@ simple_register_and_unregister2(Conf) when is_list(Conf) ->
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid, Id1),
- ?line ok = register_user(Pid, Id2),
+ ok = register_user(Pid, Id1),
+ ok = register_user(Pid, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -338,15 +338,15 @@ simple_register_and_unregister2(Conf) when is_list(Conf) ->
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = unregister_user(Pid, Id1),
- ?line ok = unregister_user(Pid, Id2),
+ ok = unregister_user(Pid, Id1),
+ ok = unregister_user(Pid, Id2),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line stop_user(Pid),
+ stop_user(Pid),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -381,16 +381,16 @@ simple_register_and_unregister3(Conf) when is_list(Conf) ->
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid1 = start_user(),
- ?line Pid2 = start_user(),
+ Pid1 = start_user(),
+ Pid2 = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid1, Id1),
- ?line ok = register_user(Pid2, Id2),
+ ok = register_user(Pid1, Id1),
+ ok = register_user(Pid2, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -401,16 +401,16 @@ simple_register_and_unregister3(Conf) when is_list(Conf) ->
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = unregister_user(Pid1, Id1),
- ?line ok = unregister_user(Pid2, Id2),
+ ok = unregister_user(Pid1, Id1),
+ ok = unregister_user(Pid2, Id2),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line stop_user(Pid1),
- ?line stop_user(Pid2),
+ stop_user(Pid1),
+ stop_user(Pid2),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -437,29 +437,29 @@ register_and_crash1(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("try starting manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
Id = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid, Id),
+ ok = register_user(Pid, Id),
- ?line [Id] = Users2 = which_users(),
+ [Id] = Users2 = which_users(),
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = simulate_crash(Pid),
+ ok = simulate_crash(Pid),
- ?line [Id] = Users3 = which_users(),
+ [Id] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -487,22 +487,22 @@ register_and_crash2(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("try starting manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid, Id1),
- ?line ok = register_user(Pid, Id2),
+ ok = register_user(Pid, Id1),
+ ok = register_user(Pid, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -512,9 +512,9 @@ register_and_crash2(Conf) when is_list(Conf) ->
end,
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = simulate_crash(Pid),
+ ok = simulate_crash(Pid),
- ?line Users3 = case which_users() of
+ Users3 = case which_users() of
[Id1, Id2] = U3 ->
U3;
[Id2, Id1] = U4 ->
@@ -525,7 +525,7 @@ register_and_crash2(Conf) when is_list(Conf) ->
?IPRINT("Users3: ~p", [Users3]),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -614,31 +614,31 @@ simple_register_monitor_and_unregister1(Conf) when is_list(Conf) ->
Id = make_ref(),
?IPRINT("start user"),
- ?line Pid = start_user(),
+ Pid = start_user(),
?IPRINT("get users (=0)"),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
?IPRINT("register monitored user"),
- ?line ok = register_user_monitor(Pid, Id),
+ ok = register_user_monitor(Pid, Id),
?IPRINT("get users (=1)"),
- ?line [Id] = Users2 = which_users(),
+ [Id] = Users2 = which_users(),
?IPRINT("Users2: ~p", [Users2]),
?IPRINT("unregister monitored user"),
- ?line unregister_user(Pid),
+ unregister_user(Pid),
?IPRINT("get users (=0)"),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
?IPRINT("start user"),
- ?line stop_user(Pid),
+ stop_user(Pid),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -674,15 +674,15 @@ simple_register_monitor_and_unregister2(Conf) when is_list(Conf) ->
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user_monitor(Pid, Id1),
- ?line ok = register_user_monitor(Pid, Id2),
+ ok = register_user_monitor(Pid, Id1),
+ ok = register_user_monitor(Pid, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -692,15 +692,15 @@ simple_register_monitor_and_unregister2(Conf) when is_list(Conf) ->
end,
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = unregister_user(Pid, Id1),
- ?line ok = unregister_user(Pid, Id2),
+ ok = unregister_user(Pid, Id1),
+ ok = unregister_user(Pid, Id2),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line stop_user(Pid),
+ stop_user(Pid),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -737,15 +737,15 @@ simple_register_monitor_and_unregister3(Conf) when is_list(Conf) ->
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid, Id1),
- ?line ok = register_user_monitor(Pid, Id2),
+ ok = register_user(Pid, Id1),
+ ok = register_user_monitor(Pid, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -755,14 +755,14 @@ simple_register_monitor_and_unregister3(Conf) when is_list(Conf) ->
end,
?IPRINT("Users2: ~p", [Users2]),
- ?line unregister_user(Pid),
+ unregister_user(Pid),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line stop_user(Pid),
+ stop_user(Pid),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -789,31 +789,31 @@ register_monitor_and_crash1(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("try starting manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
Id = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user_monitor(Pid, Id),
+ ok = register_user_monitor(Pid, Id),
- ?line [Id] = Users2 = which_users(),
+ [Id] = Users2 = which_users(),
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = simulate_crash(Pid),
+ ok = simulate_crash(Pid),
?SLEEP(1000),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -842,22 +842,22 @@ register_monitor_and_crash2(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("try starting manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user_monitor(Pid, Id1),
- ?line ok = register_user_monitor(Pid, Id2),
+ ok = register_user_monitor(Pid, Id1),
+ ok = register_user_monitor(Pid, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -867,15 +867,15 @@ register_monitor_and_crash2(Conf) when is_list(Conf) ->
end,
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = simulate_crash(Pid),
+ ok = simulate_crash(Pid),
?SLEEP(1000),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -924,22 +924,22 @@ register_monitor_and_crash3(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("try starting manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
Id1 = make_ref(),
Id2 = make_ref(),
- ?line Pid = start_user(),
+ Pid = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user(Pid, Id1),
- ?line ok = register_user_monitor(Pid, Id2),
+ ok = register_user(Pid, Id1),
+ ok = register_user_monitor(Pid, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -949,15 +949,15 @@ register_monitor_and_crash3(Conf) when is_list(Conf) ->
end,
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = simulate_crash(Pid),
+ ok = simulate_crash(Pid),
?SLEEP(1000),
- ?line [Id1] = Users3 = which_users(),
+ [Id1] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -986,7 +986,7 @@ register_monitor_and_crash4(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("start manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
@@ -994,16 +994,16 @@ register_monitor_and_crash4(Conf) when is_list(Conf) ->
Id2 = make_ref(),
?IPRINT("start user processes"),
- ?line Pid1 = start_user(),
- ?line Pid2 = start_user(),
+ Pid1 = start_user(),
+ Pid2 = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user_monitor(Pid1, Id1),
- ?line ok = register_user_monitor(Pid2, Id2),
+ ok = register_user_monitor(Pid1, Id1),
+ ok = register_user_monitor(Pid2, Id2),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -1013,17 +1013,17 @@ register_monitor_and_crash4(Conf) when is_list(Conf) ->
end,
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = simulate_crash(Pid1),
+ ok = simulate_crash(Pid1),
?SLEEP(1000),
- ?line [Id2] = Users3 = which_users(),
+ [Id2] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line stop_user(Pid2),
+ stop_user(Pid2),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -1054,7 +1054,7 @@ register_monitor_and_crash5(Conf) when is_list(Conf) ->
{config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}],
?IPRINT("start manager"),
- ?line ok = snmpm:start_link(Opts),
+ ok = snmpm:start_link(Opts),
?SLEEP(1000),
@@ -1062,14 +1062,14 @@ register_monitor_and_crash5(Conf) when is_list(Conf) ->
Id2 = tomat, %% make_ref(),
?IPRINT("start user processes"),
- ?line Pid1 = start_user(),
- ?line Pid2 = start_user(),
+ Pid1 = start_user(),
+ Pid2 = start_user(),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = register_user_monitor(Pid1, Id1),
- ?line ok = register_user_monitor(Pid2, Id2),
+ ok = register_user_monitor(Pid1, Id1),
+ ok = register_user_monitor(Pid2, Id2),
LocalHost = snmp_test_lib:localhost(),
@@ -1083,16 +1083,16 @@ register_monitor_and_crash5(Conf) when is_list(Conf) ->
Port2 = 5002,
EngineId2 = "agentEngineId-2",
- ?line ok = register_agent(Pid1,
+ ok = register_agent(Pid1,
Id1, TargetName1, [{address, Address1},
{port, Port1},
{engine_id, EngineId1}]),
- ?line ok = register_agent(Pid2,
+ ok = register_agent(Pid2,
Id2, TargetName2, [{address, Address2},
{port, Port2},
{engine_id, EngineId2}]),
- ?line Users2 = case which_users() of
+ Users2 = case which_users() of
[Id1, Id2] = U1 ->
U1;
[Id2, Id1] = U2 ->
@@ -1103,7 +1103,7 @@ register_monitor_and_crash5(Conf) when is_list(Conf) ->
?IPRINT("Users2: ~p", [Users2]),
?IPRINT("verify all agent(s): expect 2"),
- ?line Agents1 = case which_agents() of
+ Agents1 = case which_agents() of
[TargetName1, TargetName2] = A1 ->
A1;
[TargetName2, TargetName1] = A2 ->
@@ -1113,21 +1113,21 @@ register_monitor_and_crash5(Conf) when is_list(Conf) ->
end,
?IPRINT("Agents1: ~p", [Agents1]),
- ?line ok = simulate_crash(Pid1),
+ ok = simulate_crash(Pid1),
?IPRINT("wait some time"),
?SLEEP(1000),
- ?line [Id2] = Users3 = which_users(),
+ [Id2] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line [TargetName2] = Agents2 = which_agents(),
+ [TargetName2] = Agents2 = which_agents(),
?IPRINT("Agents2: ~p", [Agents2]),
- ?line stop_user(Pid2),
+ stop_user(Pid2),
?IPRINT("stop manager"),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -1217,20 +1217,20 @@ otp7902(Conf) when is_list(Conf) ->
?SLEEP(1000),
- ?line [] = Users1 = which_users(),
+ [] = Users1 = which_users(),
?IPRINT("Users1: ~p", [Users1]),
- ?line ok = snmp_manager_user_old:start(),
+ ok = snmp_manager_user_old:start(),
- ?line [_] = Users2 = which_users(),
+ [_] = Users2 = which_users(),
?IPRINT("Users2: ~p", [Users2]),
- ?line ok = snmp_manager_user_old:stop(),
+ ok = snmp_manager_user_old:stop(),
- ?line [] = Users3 = which_users(),
+ [] = Users3 = which_users(),
?IPRINT("Users3: ~p", [Users3]),
- ?line ok = snmpm:stop(),
+ ok = snmpm:stop(),
?IPRINT("end"),
ok.
@@ -1312,7 +1312,7 @@ write_manager_conf(Dir, Str) ->
write_conf_file(Dir, File, Str) ->
- ?line {ok, Fd} = file:open(filename:join(Dir, File), write),
- ?line ok = io:format(Fd, "~s", [Str]),
+ {ok, Fd} = file:open(filename:join(Dir, File), write),
+ ok = io:format(Fd, "~s", [Str]),
file:close(Fd).
diff --git a/lib/snmp/test/snmp_note_store_SUITE.erl b/lib/snmp/test/snmp_note_store_SUITE.erl
index 3b6d9f9fcd..469178c372 100644
--- a/lib/snmp/test/snmp_note_store_SUITE.erl
+++ b/lib/snmp/test/snmp_note_store_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -239,7 +239,7 @@ do_notes({_, Pid}, _Config) ->
info(suite) ->
[];
info(doc) ->
- ["Testing that we can retreive process info."];
+ ["Testing that we can retrieve process info."];
info(Config) when is_list(Config) ->
Pre = fun() ->
?IPRINT("try start note-store"),
diff --git a/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib b/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib
index 0421e64d62..eeb2535d7d 100644
--- a/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib
+++ b/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib
@@ -684,7 +684,7 @@
Setting this object to a null string (one of zero
length) has the effect of invaliding the
corresponding entry in the atTable object. That
- is, it effectively dissasociates the interface
+ is, it effectively disassociates the interface
identified with said entry from the mapping
identified with said entry. It is an
implementation-specific matter as to whether the
@@ -1256,7 +1256,7 @@
Setting this object to the value invalid(2) has
the effect of invalidating the corresponding entry
in the ipRouteTable object. That is, it
- effectively dissasociates the destination
+ effectively disassociates the destination
identified with said entry from the route
identified with said entry. It is an
implementation-specific matter as to whether the
@@ -1475,7 +1475,7 @@
Setting this object to the value invalid(2) has
the effect of invalidating the corresponding entry
in the ipNetToMediaTable. That is, it effectively
- dissasociates the interface identified with said
+ disassociates the interface identified with said
entry from the mapping identified with said entry.
It is an implementation-specific matter as to
whether the agent removes an invalidated entry
diff --git a/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib b/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib
index e45d9d91da..995be37f80 100644
--- a/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib
+++ b/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib
@@ -221,7 +221,7 @@ sysORUpTime OBJECT-TYPE
STATUS current
DESCRIPTION
"The value of sysUpTime at the time this conceptual row was
- last instanciated."
+ last instantiated."
::= { sysOREntry 4 }
diff --git a/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib b/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib
index 40a9fc79e1..41b8057223 100644
--- a/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib
+++ b/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib
@@ -30,7 +30,7 @@ t-lldpMIB MODULE-IDENTITY
"This is the ripped out bits and pieces of LLDP-MIB
that triggered a compilation problem for Erlang/OTP's
MIB compiler due to an AUGMENTS in lldpConfigManAddrEntry
- refering to a not yet defined OBJECT-TYPE lldpLocManAddrEntry.
+ referring to a not yet defined OBJECT-TYPE lldpLocManAddrEntry.
Rip and rewrite done 2017.
Management Information Base module for LLDP configuration,
@@ -199,7 +199,7 @@ lldpLocManAddrLen OBJECT-TYPE
The management address length field is needed so that the
receiving systems that do not implement SNMP will not be
required to implement an iana family numbers/address length
- equivalency table in order to decode the management adress."
+ equivalency table in order to decode the management address."
REFERENCE
"IEEE 802.1AB-2005 9.5.9.2"
::= { lldpLocManAddrEntry 2 }
diff --git a/lib/snmp/test/snmp_test_data/TestTrapv2.mib b/lib/snmp/test/snmp_test_data/TestTrapv2.mib
index 679ddc14b0..2ba59451f5 100644
--- a/lib/snmp/test/snmp_test_data/TestTrapv2.mib
+++ b/lib/snmp/test/snmp_test_data/TestTrapv2.mib
@@ -44,14 +44,14 @@ tst OBJECT IDENTIFIER ::= { system 0 }
testTrapv21 NOTIFICATION-TYPE
STATUS current
DESCRIPTION
- "This trap is exactly the v2 correspondance of testTrap1 in
+ "This trap is exactly the v2 correspondence of testTrap1 in
TestTrap mib."
::= { snmp 1 }
testTrapv22 NOTIFICATION-TYPE
STATUS current
DESCRIPTION
- "This trap is exactly the v2 correspondance of testTrap2 in
+ "This trap is exactly the v2 correspondence of testTrap2 in
TestTrap mib."
::= { system 0 1 }
diff --git a/lib/snmp/test/snmp_test_global_sys_monitor.erl b/lib/snmp/test/snmp_test_global_sys_monitor.erl
index 1c90fff686..e3f59c05e4 100644
--- a/lib/snmp/test/snmp_test_global_sys_monitor.erl
+++ b/lib/snmp/test/snmp_test_global_sys_monitor.erl
@@ -199,7 +199,7 @@ cast(Msg) ->
ok
catch
C:E:_ ->
- {error, {catched, C, E}}
+ {error, {caught, C, E}}
end.
%% call(Req) ->
@@ -217,7 +217,7 @@ cast(Msg) ->
%% end
%% catch
%% C:E:_ ->
-%% {error, {catched, C, E}}
+%% {error, {caught, C, E}}
%% end.
call(Req, Timeout) when (Timeout =:= infinity) ->
@@ -229,7 +229,7 @@ call(Req, Timeout) when is_integer(Timeout) andalso (Timeout > 1000) ->
call(Req, Timeout) when is_integer(Timeout) ->
call(Req, Timeout, Timeout div 2).
-%% This peace of wierdness is because on some machines this call has
+%% This peace of weirdness is because on some machines this call has
%% hung (in a call during end_per_testcase, which had a 1 min timeout,
%% or if that was the total time for the test case).
%% But because it hung there, we don't really know where it got stuck.
@@ -249,7 +249,7 @@ call(Req, Timeout1, Timeout2) ->
end
catch
C:E:_ ->
- exit({error, {catched, C, E}})
+ exit({error, {caught, C, E}})
end
end,
{Pid, Mon} = spawn_monitor(F),
diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index 95aab43deb..de1216790d 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
-export([tc_try/2, tc_try/3,
tc_try/4, tc_try/5]).
-export([proxy_call/3]).
--export([hostname/0, hostname/1, localhost/0, localhost/1, os_type/0, sz/1,
+-export([hostname/0, hostname/1, localhost/0, localhost/1, sz/1,
display_suite_info/1]).
-export([non_pc_tc_maybe_skip/4,
os_based_skip/1,
@@ -41,8 +41,7 @@
-export([hours/1, minutes/1, seconds/1, sleep/1]).
-export([flush_mqueue/0, mqueue/0, mqueue/1, trap_exit/0, trap_exit/1]).
-export([ping/1, local_nodes/0, nodes_on/1]).
--export([start_node/2, stop_node/1]).
--export([is_app_running/1,
+-export([is_app_running/1,
is_crypto_running/0, is_mnesia_running/0, is_snmp_running/0,
ensure_not_running/3]).
-export([crypto_start/0, crypto_support/0]).
@@ -54,6 +53,8 @@
-export([explicit_inet_backend/0, test_inet_backends/0]).
-export([which_host_ip/2]).
+%% Convenient exports...
+-export([analyze_and_print_host_info/0]).
-define(SKIP(R), skip(R, ?MODULE, ?LINE)).
@@ -71,7 +72,7 @@
%% conditions.
%% Pre: A fun that is nominally part of the test case
%% but is an initiation that must be "undone". This is
-%% done by the Post fun (regardless if the TC is successfull
+%% done by the Post fun (regardless if the TC is successful
%% or not). Example: Starts a couple of nodes,
%% TC: The test case fun
%% Post: A fun that undo what was done by the Pre fun.
@@ -119,7 +120,7 @@ tc_try(Case, TCCond, Pre, TC, Post)
(C =:= exit) ->
tc_print("test case (~w) skip: try post", [C]),
(catch Post(State)),
- tc_end( f("skipping(catched,~w,tc)", [C]) ),
+ tc_end( f("skipping(caught,~w,tc)", [C]) ),
SKIP;
C:E:S ->
%% We always check the system events
@@ -130,7 +131,7 @@ tc_try(Case, TCCond, Pre, TC, Post)
[] ->
tc_print("test case failed: try post"),
(catch Post(State)),
- tc_end( f("failed(catched,~w,tc)", [C]) ),
+ tc_end( f("failed(caught,~w,tc)", [C]) ),
erlang:raise(C, E, S);
SysEvs ->
tc_print("System Events received during tc: "
@@ -150,7 +151,7 @@ tc_try(Case, TCCond, Pre, TC, Post)
catch
C:{skip, _} = SKIP when (C =:= throw) orelse
(C =:= exit) ->
- tc_end( f("skipping(catched,~w,tc-pre)", [C]) ),
+ tc_end( f("skipping(caught,~w,tc-pre)", [C]) ),
SKIP;
C:E:S ->
%% We always check the system events
@@ -162,7 +163,7 @@ tc_try(Case, TCCond, Pre, TC, Post)
"~n E: ~p"
"~n S: ~p",
[C, E, S]),
- tc_end( f("auto-skip(catched,~w,tc-pre)", [C]) ),
+ tc_end( f("auto-skip(caught,~w,tc-pre)", [C]) ),
SKIP = {skip, f("TC-Pre failure (~w)", [C])},
SKIP;
SysEvs ->
@@ -186,13 +187,13 @@ tc_try(Case, TCCond, Pre, TC, Post)
exit({tc_cond_failed, Reason})
catch
C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) ->
- tc_end( f("skipping(catched,~w,cond)", [C]) ),
+ tc_end( f("skipping(caught,~w,cond)", [C]) ),
SKIP;
C:E:S ->
%% We always check the system events before we accept a failure
case snmp_test_global_sys_monitor:events() of
[] ->
- tc_end( f("failed(catched,~w,cond)", [C]) ),
+ tc_end( f("failed(caught,~w,cond)", [C]) ),
erlang:raise(C, E, S);
SysEvs ->
tc_print("System Events received: "
@@ -396,10 +397,10 @@ which_addr(Family, [{_Name, IfOpts} | IfList]) ->
which_addr2(_Family, []) ->
{error, not_found};
which_addr2(Family, [{addr, Addr}|_])
- when (Family =:= inet) andalso (size(Addr) =:= 4) ->
+ when (Family =:= inet) andalso (tuple_size(Addr) =:= 4) ->
{ok, Addr};
which_addr2(Family, [{addr, Addr}|_])
- when (Family =:= inet6) andalso (size(Addr) =:= 8) ->
+ when (Family =:= inet6) andalso (tuple_size(Addr) =:= 8) ->
{ok, Addr};
which_addr2(Family, [_|IfOpts]) ->
which_addr2(Family, IfOpts).
@@ -408,20 +409,10 @@ which_addr2(Family, [_|IfOpts]) ->
sz(L) when is_list(L) ->
length(L);
sz(B) when is_binary(B) ->
- size(B);
+ byte_size(B);
sz(O) ->
{unknown_size,O}.
-
-os_type() ->
- case (catch test_server:os_type()) of
- {'EXIT', _} ->
- %% Pre-R10 test server does not have this function
- os:type();
- OsType ->
- OsType
- end.
-
display_suite_info(SUITE) when is_atom(SUITE) ->
(catch do_display_suite_info(SUITE)).
@@ -692,7 +683,7 @@ old_has_support_ipv6() ->
old_has_support_ipv6(Hostname) ->
case inet:getaddr(Hostname, inet6) of
- {ok, Addr} when (size(Addr) =:= 8) andalso
+ {ok, Addr} when (tuple_size(Addr) =:= 8) andalso
(element(1, Addr) =/= 0) andalso
(element(1, Addr) =/= 16#fe80) ->
true;
@@ -968,7 +959,7 @@ skip(Reason, Module, Line) ->
exit({skip, String}).
-%% This function prints various host info, which might be usefull
+%% This function prints various host info, which might be useful
%% when analyzing the test suite (results).
%% It also returns a "factor" that can be used when deciding
%% the load for some test cases. Such as run time or number of
@@ -1009,82 +1000,426 @@ analyze_and_print_host_info() ->
"~n Num Online Schedulers: ~s"
"~n TS Extra Platform Label: ~s"
"~n", [OsFam, OsName, Version, str_num_schedulers(),
- ts_extra_flatform_label()]),
+ ts_extra_platform_label()]),
{num_schedulers_to_factor(), []}
end.
-ts_extra_flatform_label() ->
+ts_extra_platform_label() ->
case os:getenv("TS_EXTRA_PLATFORM_LABEL") of
false -> "-";
Val -> Val
end.
-simplify_label(Label) ->
- case string:to_lower(Label) of
- "docker" ++ _ ->
- docker;
+ts_scale_factor() ->
+ case timetrap_scale_factor() of
+ N when is_integer(N) andalso (N > 0) ->
+ N - 1;
_ ->
- host
+ 0
end.
-
linux_which_distro(Version) ->
- Label = ts_extra_flatform_label(),
- case file:read_file_info("/etc/issue") of
+ Label = ts_extra_platform_label(),
+ Checks =
+ [fun() -> do_linux_which_distro_os_release(Version, Label) end,
+ fun() -> do_linux_which_distro_suse_release(Version, Label) end,
+ fun() -> do_linux_which_distro_fedora_release(Version, Label) end,
+ fun() -> do_linux_which_distro_issue(Version, Label) end],
+ try linux_which_distro("", Version, Label, Checks)
+ catch
+ throw:{distro, Distro} ->
+ Distro
+ end.
+
+linux_which_distro("", Version, Label, []) ->
+ io:format("Linux: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n", [Version, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)};
+linux_which_distro(DestroStr, Version, Label, []) ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n", [Version, DestroStr, Label,
+ linux_product_name()]),
+ {other, simplify_label(Label)};
+linux_which_distro(Default, Version, Label, [Check|Checks]) ->
+ try Check() of
+ DistroStr when is_list(DistroStr) ->
+ linux_which_distro(DistroStr, Version, Label, Checks);
+ retry ->
+ linux_which_distro(Default, Version, Label, Checks);
+ {error, _Reason} ->
+ linux_which_distro(Default, Version, Label, Checks)
+ catch
+ throw:{error, _Reason} ->
+ linux_which_distro(Default, Version, Label, Checks)
+ end.
+
+do_linux_which_distro_os_release(Version, Label) ->
+ case file:read_file_info("/etc/os-release") of
+ {ok, _} ->
+ %% We want to 'catch' if our processing is wrong,
+ %% that's why we catch and re-throw the distro.
+ %% Actual errors will be returned as 'ignore'.
+ try
+ begin
+ Info = linux_process_os_release(),
+ {value, {_, DistroStr}} = lists:keysearch(name, 1, Info),
+ {value, {_, VersionNo}} = lists:keysearch(version, 1, Info),
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, VersionNo, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_distro_str_to_distro_id(DistroStr),
+ simplify_label(Label)}})
+ end
+ catch
+ throw:{distro, _} = DISTRO ->
+ throw(DISTRO);
+ _:_ ->
+ retry
+ end;
+ _ ->
+ retry
+ end.
+
+
+linux_process_os_release() ->
+ %% Read the "raw" file
+ Raw = os:cmd("cat /etc/os-release"),
+ %% Split it into lines
+ Lines1 = string:tokens(Raw, [$\n]),
+ %% Just in case, skip any lines starting with '#'.
+ Lines2 = linux_process_os_release1(Lines1),
+ %% Each (remaining) line *should* be: <TAG>=<VALUE>
+ %% Both sides will be strings, the value side will be a quoted string...
+ %% Convert those into a 2-tuple list: [{Tag, Value}]
+ linux_process_os_release2(Lines2).
+
+linux_process_os_release1(Lines) ->
+ linux_process_os_release1(Lines, []).
+
+linux_process_os_release1([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release1([H|T], Acc) ->
+ case H of
+ "#" ++ _ ->
+ linux_process_os_release1(T, Acc);
+ _ ->
+ linux_process_os_release1(T, [H|Acc])
+ end.
+
+linux_process_os_release2(Lines) ->
+ linux_process_os_release2(Lines, []).
+
+linux_process_os_release2([], Acc) ->
+ lists:reverse(Acc);
+linux_process_os_release2([H|T], Acc) ->
+ case linux_process_os_release3(H) of
+ {value, Value} ->
+ linux_process_os_release2(T, [Value|Acc]);
+ false ->
+ linux_process_os_release2(T, Acc)
+ end.
+
+linux_process_os_release3(H) ->
+ case [string:strip(S) || S <- string:tokens(H, [$=])] of
+ [Tag, Value] ->
+ Tag2 = list_to_atom(string:to_lower(Tag)),
+ Value2 = string:strip(Value, both, $"),
+ linux_process_os_release4(Tag2, Value2);
+ _ ->
+ false
+ end.
+
+linux_process_os_release4(name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(version_id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(id = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(pretty_name = Tag, Value) ->
+ {value, {Tag, Value}};
+linux_process_os_release4(_Tag, _Value) ->
+ false.
+
+
+linux_distro_str_to_distro_id("Debian" ++ _) ->
+ debian;
+linux_distro_str_to_distro_id("Fedora" ++ _) ->
+ fedora;
+linux_distro_str_to_distro_id("Linux Mint" ++ _) ->
+ linux_mint;
+linux_distro_str_to_distro_id("MontaVista" ++ _) ->
+ montavista;
+linux_distro_str_to_distro_id("openSUSE" ++ _) ->
+ suse;
+linux_distro_str_to_distro_id("SLES" ++ _) ->
+ sles;
+linux_distro_str_to_distro_id("Ubuntu" ++ _) ->
+ ubuntu;
+linux_distro_str_to_distro_id("Wind River Linux" ++ _) ->
+ wind_river;
+linux_distro_str_to_distro_id("Yellow Dog" ++ _) ->
+ yellow_dog;
+linux_distro_str_to_distro_id(X) ->
+ X.
+
+
+do_linux_which_distro_fedora_release(Version, Label) ->
+ %% Check if fedora
+ case file:read_file_info("/etc/fedora-release") of
{ok, _} ->
case [string:trim(S) ||
- S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
- [DistroStr|_] ->
+ S <- string:tokens(os:cmd("cat /etc/fedora-release"),
+ [$\n])] of
+ [DistroStr | _] ->
io:format("Linux: ~s"
"~n Distro: ~s"
"~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
"~n",
- [Version, DistroStr, Label]),
- {case DistroStr of
- "Wind River Linux" ++ _ ->
- wind_river;
- "MontaVista" ++ _ ->
- montavista;
- "Yellow Dog" ++ _ ->
- yellow_dog;
- "Debian" ++ _ ->
- debian;
- _ ->
- other
- end,
- simplify_label(Label)};
- X ->
+ [Version, DistroStr, Label,
+ linux_product_name()]);
+ _ ->
io:format("Linux: ~s"
- "~n Distro: ~p"
+ "~n Distro: ~s"
"~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
"~n",
- [Version, X, Label]),
- {other, simplify_label(Label)}
+ [Version, "Fedora", Label,
+ linux_product_name()])
+ end,
+ throw({distro, {fedora, simplify_label(Label)}});
+ _ ->
+ throw({error, not_found})
+ end.
+
+do_linux_which_distro_suse_release(Version, Label) ->
+ %% Check if its a SuSE
+ case file:read_file_info("/etc/SUSE-brand") of
+ {ok, _} ->
+ case file:read_file_info("/etc/SuSE-release") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/SuSE-release"),
+ [$\n])] of
+ ["SUSE Linux Enterprise Server" ++ _ = DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {sles, simplify_label(Label)}});
+ [DistroStr | _] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "SuSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ case string:tokens(os:cmd("cat /etc/SUSE-brand"), [$\n]) of
+ ["SLE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {sles, simplify_label(Label)}})
+ end;
+ ["openSUSE" = DistroStr, VERSION | _] ->
+ case [string:strip(S) ||
+ S <- string:tokens(VERSION, [$=])] of
+ ["VERSION", VersionNo] ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n Distro Version: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version,
+ DistroStr, VersionNo,
+ Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}});
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {suse, simplify_label(Label)}})
+ end;
+ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, "Unknown SUSE", Label,
+ linux_product_name()]),
+ throw({distro, {suse, simplify_label(Label)}})
+ end
end;
_ ->
- io:format("Linux: ~s"
- "~n TS Extra Platform Label: ~s"
- "~n", [Version, Label]),
- {other, simplify_label(Label)}
+ throw({error, not_found})
+ end.
+
+do_linux_which_distro_issue(Version, Label) ->
+ case file:read_file_info("/etc/issue") of
+ {ok, _} ->
+ case [string:trim(S) ||
+ S <- string:tokens(os:cmd("cat /etc/issue"), [$\n])] of
+ [DistroStr | _] ->
+ case DistroStr of
+ "Wind River Linux" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {wind_river, simplify_label(Label)}});
+ "MontaVista" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {montavista, simplify_label(Label)}});
+ "Yellow Dog" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {yellow_dog, simplify_label(Label)}});
+ "Debian" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {debian, simplify_label(Label)}});
+ "Ubuntu" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {ubuntu, simplify_label(Label)}});
+ "Linux Mint" ++ _ ->
+ io:format("Linux: ~s"
+ "~n Distro: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n Product Name: ~s"
+ "~n",
+ [Version, DistroStr, Label,
+ linux_product_name()]),
+ throw({distro,
+ {linux_mint, simplify_label(Label)}});
+ _ ->
+ DistroStr
+ end;
+ X ->
+ X
+ end;
+ _ ->
+ throw({error, not_found})
+ end.
+
+
+simplify_label("Systemtap" ++ _) ->
+ {host, systemtap};
+simplify_label("Meamax" ++ _) ->
+ {host, meamax};
+simplify_label("Cover" ++ _) ->
+ {host, cover};
+simplify_label(Label) ->
+ case string:find(string:to_lower(Label), "docker") of
+ "docker" ++ _ ->
+ docker;
+ _ ->
+ {host, undefined}
end.
label2factor(docker) ->
4;
-label2factor(host) ->
+label2factor({host, meamax}) ->
+ 2;
+label2factor({host, cover}) ->
+ 6;
+label2factor({host, _}) ->
0.
+
analyze_and_print_linux_host_info(Version) ->
- {Distro, Label} =
- case file:read_file_info("/etc/issue") of
- {ok, _} ->
- linux_which_distro(Version);
- _ ->
- L = ts_extra_flatform_label(),
- io:format("Linux: ~s"
- "~n TS Extra Platform Label: ~s"
- "~n", [Version, L]),
- {other, simplify_label(L)}
- end,
+ {Distro, Label} = linux_which_distro(Version),
+ %% 'VirtFactor' will be 0 unless virtual
+ VirtFactor = linux_virt_factor(),
Factor =
case (catch linux_which_cpuinfo(Distro)) of
{ok, {CPU, BogoMIPS}} ->
@@ -1094,31 +1429,49 @@ analyze_and_print_linux_host_info(Version) ->
"~n Num Online Schedulers: ~s"
"~n", [CPU, BogoMIPS, str_num_schedulers()]),
if
- (BogoMIPS > 20000) ->
+ (BogoMIPS > 50000) ->
1;
- (BogoMIPS > 10000) ->
+ (BogoMIPS > 40000) ->
2;
- (BogoMIPS > 5000) ->
+ (BogoMIPS > 30000) ->
3;
- (BogoMIPS > 2000) ->
+ (BogoMIPS > 20000) ->
+ 4;
+ (BogoMIPS > 10000) ->
5;
- (BogoMIPS > 1000) ->
+ (BogoMIPS > 5000) ->
8;
+ (BogoMIPS > 3000) ->
+ 12;
true ->
10
end;
+ {ok, "POWER9" ++ _ = CPU} ->
+ %% For some reason this host is really slow
+ %% Consider the CPU, it really should not be...
+ %% But, to not fail a bunch of test cases, we add 5
+ case linux_cpuinfo_clock() of
+ Clock when is_integer(Clock) andalso (Clock > 0) ->
+ io:format("CPU: "
+ "~n Model: ~s"
+ "~n CPU Speed: ~w"
+ "~n Num Online Schedulers: ~s"
+ "~n", [CPU, Clock, str_num_schedulers()]),
+ if
+ (Clock > 2000) ->
+ 5 + num_schedulers_to_factor();
+ true ->
+ 10 + num_schedulers_to_factor()
+ end;
+ _ ->
+ num_schedulers_to_factor()
+ end;
{ok, CPU} ->
io:format("CPU: "
"~n Model: ~s"
"~n Num Online Schedulers: ~s"
"~n", [CPU, str_num_schedulers()]),
- NumChed = erlang:system_info(schedulers),
- if
- (NumChed > 2) ->
- 2;
- true ->
- 5
- end;
+ num_schedulers_to_factor();
_ ->
5
end,
@@ -1137,9 +1490,12 @@ analyze_and_print_linux_host_info(Version) ->
"~n Base Factor: ~w"
"~n Label Factor: ~w"
"~n Mem Factor: ~w"
+ "~n Virtual Factor: ~w"
"~n TS Scale Factor: ~w"
- "~n", [Factor, AddLabelFactor, AddMemFactor, TSScaleFactor]),
- {Factor + AddLabelFactor + AddMemFactor + TSScaleFactor, [{label, Label}]}.
+ "~n", [Factor, AddLabelFactor, AddMemFactor, VirtFactor,
+ TSScaleFactor]),
+ {Factor + AddLabelFactor + AddMemFactor + VirtFactor + TSScaleFactor,
+ [{label, Label}]}.
linux_cpuinfo_lookup(Key) when is_list(Key) ->
@@ -1162,19 +1518,17 @@ linux_cpuinfo_motherboard() ->
end.
linux_cpuinfo_bogomips() ->
- case linux_cpuinfo_lookup("bogomips") of
- BMips when is_list(BMips) ->
- try lists:sum([bogomips_to_int(BM) || BM <- BMips])
- catch
- _:_:_ ->
- "-"
- end;
- _ ->
- "-"
+ case linux_cpuinfo_bogomips("bogomips") of
+ "-" ->
+ linux_cpuinfo_bogomips("BogoMIPS");
+ Res ->
+ Res
end.
-linux_cpuinfo_BogoMIPS() ->
- case linux_cpuinfo_lookup("BogoMIPS") of
+linux_cpuinfo_bogomips(Key) ->
+ case linux_cpuinfo_lookup(Key) of
+ [] ->
+ "-";
BMips when is_list(BMips) ->
try lists:sum([bogomips_to_int(BM) || BM <- BMips])
catch
@@ -1303,7 +1657,7 @@ linux_which_cpuinfo(wind_river) ->
end,
case linux_cpuinfo_total_bogomips() of
"-" ->
- case linux_cpuinfo_BogoMIPS() of
+ case linux_cpuinfo_bogomips() of
"-" ->
{ok, CPU};
BMips ->
@@ -1313,43 +1667,44 @@ linux_which_cpuinfo(wind_river) ->
{ok, {CPU, BMips}}
end;
-%% Check for x86 (Intel, AMD, Raspberry (ARM))
-linux_which_cpuinfo(debian) ->
- CPU =
- case linux_cpuinfo_model() of
- "-" ->
- %% ARM (at least some distros...)
- case linux_cpuinfo_processor() of
- "-" ->
- %% Ok, we give up
- throw(noinfo);
- Proc ->
- Proc
- end;
- ModelName ->
- ModelName
- end,
- case linux_cpuinfo_bogomips() of
- "-" ->
- {ok, CPU};
- BMips ->
- {ok, {CPU, BMips}}
- end;
-
%% Check for x86 (Intel or AMD)
-linux_which_cpuinfo(other) ->
+linux_which_cpuinfo(Distro) when (Distro =:= debian) orelse
+ (Distro =:= fedora) orelse
+ (Distro =:= linux_mint) orelse
+ (Distro =:= sles) orelse
+ (Distro =:= suse) orelse
+ (Distro =:= ubuntu) orelse
+ (Distro =:= other) ->
CPU =
case linux_cpuinfo_model_name() of
"-" ->
- %% ARM (at least some distros...)
- case linux_cpuinfo_processor() of
- "-" ->
- %% Ok, we give up
- throw(noinfo);
- Proc ->
- Proc
- end;
- ModelName ->
+ %% This is for POWER9
+ case linux_cpuinfo_cpu() of
+ "POWER9" ++ _ = PowerCPU ->
+ Machine =
+ case linux_cpuinfo_machine() of
+ "-" ->
+ "";
+ M ->
+ " (" ++ M ++ ")"
+ end,
+ PowerCPU ++ Machine;
+ _X ->
+ %% ARM (at least some distros...)
+ case linux_cpuinfo_processor() of
+ "-" ->
+ case linux_cpuinfo_model() of
+ "-" ->
+ %% Ok, we give up
+ throw(noinfo);
+ Model ->
+ Model
+ end;
+ Proc ->
+ Proc
+ end
+ end;
+ ModelName ->
ModelName
end,
case linux_cpuinfo_bogomips() of
@@ -1409,6 +1764,87 @@ linux_which_meminfo() ->
end.
+linux_product_name() ->
+ ProductNameFile = "/sys/devices/virtual/dmi/id/product_name",
+ case file:read_file_info(ProductNameFile) of
+ {ok, _} ->
+ case os:cmd("cat " ++ ProductNameFile) of
+ false ->
+ "-";
+ Info ->
+ string:trim(Info)
+ end;
+ _ ->
+ "-"
+ end.
+
+
+linux_info_lookup(Key, File) ->
+ try [string:trim(S) || S <- string:tokens(os:cmd("grep " ++ "\"" ++ Key ++ "\"" ++ " " ++ File), [$:,$\n])] of
+ Info ->
+ linux_info_lookup_collect(Key, Info, [])
+ catch
+ _:_:_ ->
+ "-"
+ end.
+
+linux_info_lookup_collect(_Key, [], Values) ->
+ lists:reverse(Values);
+linux_info_lookup_collect(Key, [Key, Value|Rest], Values) ->
+ linux_info_lookup_collect(Key, Rest, [Value|Values]);
+linux_info_lookup_collect(_, _, Values) ->
+ lists:reverse(Values).
+
+
+linux_virt_factor() ->
+ linux_virt_factor(linux_product_name()).
+
+linux_virt_factor("VMware" ++ _) ->
+ 2;
+linux_virt_factor("VirtualBox" ++ _) ->
+ 4;
+linux_virt_factor(_) ->
+ 0.
+
+
+linux_cpuinfo_machine() ->
+ case linux_cpuinfo_lookup("machine") of
+ [M] ->
+ M;
+ _ ->
+ "-"
+ end.
+
+linux_cpuinfo_clock() ->
+ %% This is written as: "3783.000000MHz"
+ %% So, check unit MHz (handle nothing else).
+ %% Also, check for both float and integer
+ %% Also, the freq is per core, and can vary...
+ case linux_cpuinfo_lookup("clock") of
+ [C|_] when is_list(C) ->
+ case lists:reverse(string:to_lower(C)) of
+ "zhm" ++ CRev ->
+ try trunc(list_to_float(lists:reverse(CRev))) of
+ I ->
+ I
+ catch
+ _:_:_ ->
+ try list_to_integer(lists:reverse(CRev)) of
+ I ->
+ I
+ catch
+ _:_:_ ->
+ 0
+ end
+ end;
+ _ ->
+ 0
+ end;
+ _ ->
+ 0
+ end.
+
+
%% Just to be clear: This is ***not*** scientific...
analyze_and_print_openbsd_host_info(Version) ->
io:format("OpenBSD:"
@@ -1458,39 +1894,71 @@ analyze_and_print_openbsd_host_info(Version) ->
io:format("TS Scale Factor: ~w~n", [timetrap_scale_factor()]),
CPUFactor =
if
- (CPUSpeed =:= -1) ->
- 1;
- (CPUSpeed >= 2000) ->
+ (CPUSpeed >= 3000) ->
if
- (NCPU >= 4) ->
+ (NCPU >= 8) ->
1;
+ (NCPU >= 6) ->
+ 2;
+ (NCPU >= 4) ->
+ 3;
(NCPU >= 2) ->
+ 4;
+ true ->
+ 10
+ end;
+ (CPUSpeed >= 2000) ->
+ if
+ (NCPU >= 8) ->
2;
+ (NCPU >= 6) ->
+ 3;
+ (NCPU >= 4) ->
+ 4;
+ (NCPU >= 2) ->
+ 5;
true ->
- 3
+ 12
+ end;
+ (CPUSpeed >= 1000) ->
+ if
+ (NCPU >= 8) ->
+ 3;
+ (NCPU >= 6) ->
+ 4;
+ (NCPU >= 4) ->
+ 5;
+ (NCPU >= 2) ->
+ 6;
+ true ->
+ 14
end;
true ->
if
+ (NCPU >= 8) ->
+ 4;
+ (NCPU >= 6) ->
+ 6;
(NCPU >= 4) ->
- 2;
+ 8;
(NCPU >= 2) ->
- 3;
+ 10;
true ->
- 4
+ 20
end
end,
MemAddFactor =
if
- (Memory =:= -1) ->
+ (Memory >= 16777216) ->
0;
(Memory >= 8388608) ->
- 0;
- (Memory >= 4194304) ->
1;
+ (Memory >= 4194304) ->
+ 3;
(Memory >= 2097152) ->
- 2;
+ 5;
true ->
- 3
+ 10
end,
{CPUFactor + MemAddFactor, []}
end
@@ -1790,47 +2258,58 @@ analyze_and_print_darwin_host_info(Version) ->
%% we need to find some other way to find some info...
%% Also, I suppose its possible that we for some other
%% reason *fail* to get the info...
- case analyze_darwin_software_info() of
- [] ->
- io:format("Darwin:"
- "~n Version: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [Version, str_num_schedulers()]),
- {num_schedulers_to_factor(), []};
- SwInfo when is_list(SwInfo) ->
- SystemVersion = analyze_darwin_sw_system_version(SwInfo),
- KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
- HwInfo = analyze_darwin_hardware_info(),
- ModelName = analyze_darwin_hw_model_name(HwInfo),
- ModelId = analyze_darwin_hw_model_identifier(HwInfo),
- ProcName = analyze_darwin_hw_processor_name(HwInfo),
- ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
- NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
- NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
- Memory = analyze_darwin_hw_memory(HwInfo),
- io:format("Darwin:"
- "~n System Version: ~s"
- "~n Kernel Version: ~s"
- "~n Model: ~s (~s)"
- "~n Processor: ~s (~s, ~s, ~s)"
- "~n Memory: ~s"
- "~n Num Online Schedulers: ~s"
- "~n", [SystemVersion, KernelVersion,
- ModelName, ModelId,
- ProcName, ProcSpeed, NumProc, NumCores,
- Memory,
- str_num_schedulers()]),
- CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
- ProcSpeed,
- NumProc,
- NumCores),
- MemFactor = analyze_darwin_memory_to_factor(Memory),
- if (MemFactor =:= 1) ->
- {CPUFactor, []};
- true ->
- {CPUFactor + MemFactor, []}
- end
- end.
+ Label = ts_extra_platform_label(),
+ {BaseFactor, MemFactor} =
+ case analyze_darwin_software_info() of
+ [] ->
+ io:format("Darwin:"
+ "~n Version: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n", [Version, str_num_schedulers(), Label]),
+ {num_schedulers_to_factor(), 1};
+ SwInfo when is_list(SwInfo) ->
+ SystemVersion = analyze_darwin_sw_system_version(SwInfo),
+ KernelVersion = analyze_darwin_sw_kernel_version(SwInfo),
+ HwInfo = analyze_darwin_hardware_info(),
+ ModelName = analyze_darwin_hw_model_name(HwInfo),
+ ModelId = analyze_darwin_hw_model_identifier(HwInfo),
+ {Processor, CPUFactor} = analyze_darwin_hw_processor(HwInfo),
+ Memory = analyze_darwin_hw_memory(HwInfo),
+ io:format("Darwin:"
+ "~n System Version: ~s"
+ "~n Kernel Version: ~s"
+ "~n Model: ~s (~s)"
+ "~n Processor: ~s"
+ "~n Memory: ~s"
+ "~n Num Online Schedulers: ~s"
+ "~n TS Extra Platform Label: ~s"
+ "~n~n",
+ [SystemVersion, KernelVersion,
+ ModelName, ModelId,
+ Processor,
+ Memory,
+ str_num_schedulers(), Label]),
+ {CPUFactor, analyze_darwin_memory_to_factor(Memory)}
+ end,
+ AddLabelFactor = label2factor(simplify_label(Label)),
+ AddMemFactor = if
+ (MemFactor > 0) ->
+ MemFactor - 1;
+ true ->
+ 0
+ end,
+ TSScaleFactor = ts_scale_factor(),
+ io:format("Factor calc:"
+ "~n Base Factor: ~w"
+ "~n Label Factor: ~w"
+ "~n Mem Factor: ~w"
+ "~n TS Scale Factor: ~w"
+ "~n~n",
+ [BaseFactor, AddLabelFactor, AddMemFactor, TSScaleFactor]),
+ {BaseFactor + AddLabelFactor + AddMemFactor + TSScaleFactor,
+ [{label, Label}]}.
+
analyze_darwin_sw_system_version(SwInfo) ->
proplists:get_value("system version", SwInfo, "-").
@@ -1847,6 +2326,32 @@ analyze_darwin_hw_model_name(HwInfo) ->
analyze_darwin_hw_model_identifier(HwInfo) ->
proplists:get_value("model identifier", HwInfo, "-").
+analyze_darwin_hw_processor(HwInfo) ->
+ case analyze_darwin_hw_processor_name(HwInfo) of
+ "-" -> % Maybe Apple Chip
+ case analyze_darwin_hw_chip(HwInfo) of
+ "-" ->
+ "-";
+ Chip ->
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(Chip, NumCores),
+ {f("~s [~s]", [Chip, NumCores]), CPUFactor}
+ end;
+ ProcName ->
+ ProcSpeed = analyze_darwin_hw_processor_speed(HwInfo),
+ NumProc = analyze_darwin_hw_number_of_processors(HwInfo),
+ NumCores = analyze_darwin_hw_total_number_of_cores(HwInfo),
+ CPUFactor = analyze_darwin_cpu_to_factor(ProcName,
+ ProcSpeed,
+ NumProc,
+ NumCores),
+ {f("~s [~s, ~s, ~s]",
+ [ProcName, ProcSpeed, NumProc, NumCores]), CPUFactor}
+ end.
+
+analyze_darwin_hw_chip(HwInfo) ->
+ proplists:get_value("chip", HwInfo, "-").
+
analyze_darwin_hw_processor_name(HwInfo) ->
proplists:get_value("processor name", HwInfo, "-").
@@ -1871,17 +2376,25 @@ analyze_darwin_hardware_info() ->
%% "Key: Value1:Value2"
analyze_darwin_system_profiler(DataType) ->
%% First, make sure the program actually exist:
- case os:cmd("which system_profiler") of
+ case string:trim(os:cmd("which system_profiler")) of
[] ->
- [];
- _ ->
- D0 = os:cmd("system_profiler " ++ DataType),
- D1 = string:tokens(D0, [$\n]),
- D2 = [string:trim(S1) || S1 <- D1],
- D3 = [string:tokens(S2, [$:]) || S2 <- D2],
- analyze_darwin_system_profiler2(D3)
+ case string:trim(os:cmd("which /usr/sbin/system_profiler")) of
+ [] ->
+ [];
+ Cmd1 ->
+ analyze_darwin_system_profiler(Cmd1, DataType)
+ end;
+ Cmd2 ->
+ analyze_darwin_system_profiler(Cmd2, DataType)
end.
+analyze_darwin_system_profiler(Cmd, DataType) ->
+ D0 = os:cmd(Cmd ++ " " ++ DataType),
+ D1 = string:tokens(D0, [$\n]),
+ D2 = [string:trim(S1) || S1 <- D1],
+ D3 = [string:tokens(S2, [$:]) || S2 <- D2],
+ analyze_darwin_system_profiler2(D3).
+
analyze_darwin_system_profiler2(L) ->
analyze_darwin_system_profiler2(L, []).
@@ -1931,6 +2444,12 @@ analyze_darwin_memory_to_factor(Mem) ->
end.
+analyze_darwin_cpu_to_factor("Apple" ++ _ = _Chip, _NumCores) ->
+ 1;
+analyze_darwin_cpu_to_factor(_Chip, _NumCores) ->
+ 8.
+
+
%% The speed is a string: "<speed> <unit>"
%% the speed may be a float, which we transforms into an integer of MHz.
%% To calculate a factor based on processor speed, number of procs
@@ -2349,8 +2868,12 @@ num_schedulers_to_factor() ->
1 ->
10;
2 ->
- 5;
- N when (N =< 6) ->
+ 8;
+ 3 ->
+ 6;
+ 4 ->
+ 4;
+ N when (N =< 5) ->
2;
_ ->
1
@@ -2360,38 +2883,6 @@ num_schedulers_to_factor() ->
end.
-linux_info_lookup(Key, File) ->
- %% try
- %% begin
- %% GREP = os:cmd("grep " ++ "\"" ++ Key ++ "\"" ++ " " ++ File),
- %% io:format("linux_info_lookup() -> GREP: ~p~n", [GREP]),
- %% TOKENS = string:tokens(GREP, [$:,$\n]),
- %% io:format("linux_info_lookup() -> TOKENS: ~p~n", [TOKENS]),
- %% INFO = [string:trim(S) || S <- TOKENS],
- %% io:format("linux_info_lookup() -> INFO: ~p~n", [INFO]),
- %% linux_info_lookup_collect(Key, INFO, [])
- %% end
- %% catch
- %% _:_:_ ->
- %% "-"
- %% end.
- try [string:trim(S) || S <- string:tokens(os:cmd("grep " ++ "\"" ++ Key ++ "\"" ++ " " ++ File), [$:,$\n])] of
- Info ->
- linux_info_lookup_collect(Key, Info, [])
- catch
- _:_:_ ->
- "-"
- end.
-
-linux_info_lookup_collect(_Key, [], Values) ->
- lists:reverse(Values);
-linux_info_lookup_collect(Key, [Key, Value|Rest], Values) ->
- linux_info_lookup_collect(Key, Rest, [Value|Values]);
-linux_info_lookup_collect(_, _, Values) ->
- lists:reverse(Values).
-
-
-
%% ----------------------------------------------------------------
%% Time related function
%%
@@ -2468,15 +2959,6 @@ nodes_on(Host) when is_list(Host) ->
net_adm:world_list([list_to_atom(Host)]).
-start_node(Name, Args) ->
- Opts = [{cleanup, false}, {args, Args}],
- test_server:start_node(Name, peer, Opts).
-
-
-stop_node(Node) ->
- test_server:stop_node(Node).
-
-
%% ----------------------------------------------------------------
%% Application and Crypto utility functions
%%
diff --git a/lib/snmp/test/snmp_test_lib.hrl b/lib/snmp/test/snmp_test_lib.hrl
index ea7732eba8..f57f2b0e35 100644
--- a/lib/snmp/test/snmp_test_lib.hrl
+++ b/lib/snmp/test/snmp_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -103,9 +103,6 @@
-define(PING(N), ?LIB:ping(N)).
-define(LNODES(), ?LIB:local_nodes()).
-define(NODES(H), ?LIB:nodes_on(H)).
--define(START_NODE(N,A), ?LIB:start_node(N,A)).
--define(STOP_NODE(N), ?LIB:stop_node(N)).
-
%% - Application and Crypto utility macros -
@@ -158,3 +155,9 @@
-define(FTS(), snmp_misc:formated_timestamp()).
-define(FTS(TS), snmp_misc:format_timestamp(TS)).
+%% This needs to be a macro-definition to capture ?FUNCTION_NAME and ?MODULE.
+-define (START_PEER(Kind), ?CT_PEER(#{
+ name => ?CT_PEER_NAME(atom_to_list(?FUNCTION_NAME) ++ Kind),
+ args => ["-s", "snmp_test_sys_monitor", "start", "-s", "global", "sync"]
+})).
+-define(STOP_PEER(__P__), peer:stop(__P__)).
diff --git a/lib/snmp/test/snmp_test_manager.erl b/lib/snmp/test/snmp_test_manager.erl
index 38ec1d9ce3..1bd1351a76 100644
--- a/lib/snmp/test/snmp_test_manager.erl
+++ b/lib/snmp/test/snmp_test_manager.erl
@@ -155,7 +155,7 @@ parse_opts(Opts) ->
MgrDir = get_opt(dir, get_opt(config, MgrOpts, [])),
- %% Retreive the agent configuration
+ %% Retrieve the agent configuration
AgentConf = get_opt(agent_config, Opts),
AgentTarget = get_opt(agent_target, Opts),
{MgrDir, MgrConf, MgrOpts, AgentTarget, AgentConf}.
diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl
index d9caa15cdb..9621bb2e7d 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -147,7 +147,7 @@ receive_response() ->
receive_response(get_timeout()).
receive_response(Timeout) ->
- d("await response within ~w ms",[Timeout]),
+ d("await response within ~w ms", [Timeout]),
receive
{snmp_pdu, PDU} when is_record(PDU, pdu) ->
d("[await response] received PDU: "
@@ -158,7 +158,8 @@ receive_response(Timeout) ->
"~n ~p", [Reason]),
ERROR
after Timeout ->
- ?EPRINT("[await response] unexpected timeout"),
+ ?EPRINT("[await response] unexpected timeout: "
+ "~n ~p", [process_info(self(), messages)]),
{error, timeout}
end.
@@ -255,14 +256,12 @@ init({Options, CallerPid}) ->
IpFamily = get_value(ipfamily, Options, inet),
?IPRINT("init -> IpFamily: ~p", [IpFamily]),
AgIp = case snmp_misc:assq(agent, Options) of
- {value, Addr} when is_tuple(Addr) andalso
- (size(Addr) =:= 4) andalso
- (IpFamily =:= inet) ->
+ {value, Addr} when (tuple_size(Addr) =:= 4) andalso
+ (IpFamily =:= inet) ->
?IPRINT("init -> Addr: ~p", [Addr]),
Addr;
- {value, Addr} when is_tuple(Addr) andalso
- (size(Addr) =:= 8) andalso
- (IpFamily =:= inet6) ->
+ {value, Addr} when (tuple_size(Addr) =:= 8) andalso
+ (IpFamily =:= inet6) ->
?IPRINT("init -> Addr: ~p", [Addr]),
Addr;
{value, Host} when is_list(Host) ->
@@ -1303,7 +1302,7 @@ cast(Msg) ->
sizeOf(L) when is_list(L) ->
length(lists:flatten(L));
sizeOf(B) when is_binary(B) ->
- size(B).
+ byte_size(B).
d(F) -> d(F, []).
d(F, A) -> d(get(debug), F, A).
diff --git a/lib/snmp/test/snmp_test_mgr_counter_server.erl b/lib/snmp/test/snmp_test_mgr_counter_server.erl
index 697afdf799..49f273e04a 100644
--- a/lib/snmp/test/snmp_test_mgr_counter_server.erl
+++ b/lib/snmp/test/snmp_test_mgr_counter_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
%% agent test suite is implemented in such a way that the
%% agent is started once and then used for several test cases.
%% Each request is given a request id which *was* generated using
-%% random! It is therefor possible, although unlikely, that a
+%% random! It is therefore possible, although unlikely, that a
%% request may get a request id that has recently been used,
%% which will cause the agent to silently reject the request.
%% For this reason, we start this server at the start of the
diff --git a/lib/snmp/test/snmp_test_mgr_misc.erl b/lib/snmp/test/snmp_test_mgr_misc.erl
index 506ceb6a5e..ed3785d019 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -394,7 +394,7 @@ handle_v1_or_v2_message(Mgr, _UdpId, Ip, UdpPort, _AgentIp,
end.
-%% This function assumes that the agent and the manager (thats us)
+%% This function assumes that the agent and the manager (that's us)
%% has the same version.
check_discovery_result('version-3', DiscoReqMsg, DiscoRspMsg) ->
ReqMsgID = getMsgID(DiscoReqMsg),
@@ -776,7 +776,7 @@ ensure_dead_kill(Pid, MRef, Timeout) ->
display_incomming_message(M) ->
- display_message("Incomming",M).
+ display_message("Incoming",M).
display_outgoing_message(M) ->
display_message("Outgoing", M).
@@ -961,7 +961,7 @@ display_prop_hdr(S) ->
sz(L) when is_list(L) ->
iolist_size(L);
sz(B) when is_binary(B) ->
- size(B);
+ byte_size(B);
sz(O) ->
{unknown_size, O}.
diff --git a/lib/snmp/test/snmp_test_server.erl b/lib/snmp/test/snmp_test_server.erl
index ac874e47be..0eb7065b85 100644
--- a/lib/snmp/test/snmp_test_server.erl
+++ b/lib/snmp/test/snmp_test_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -322,7 +322,7 @@ display_failed(Failed) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Verify that the actual result of a test case matches the exected one
+%% Verify that the actual result of a test case matches the expected one
%% Returns the actual result
%% Stores the result in the process dictionary if mismatch
diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
index 1152c8ec49..6a659e6aed 100644
--- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
+++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
@@ -411,7 +411,7 @@ erlang_agent_netsnmp_get(Config) when is_list(Config) ->
"~n ~s", [Rest]),
throw({skip, Rest});
Any ->
- ct:pal("Received unexpected reponse: "
+ ct:pal("Received unexpected response: "
"~n ~p", [Any]),
exit({unexpected, Any})
end || Transport <- Transports],
diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib
index 679ddc14b0..2ba59451f5 100644
--- a/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib
+++ b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/TestTrapv2.mib
@@ -44,14 +44,14 @@ tst OBJECT IDENTIFIER ::= { system 0 }
testTrapv21 NOTIFICATION-TYPE
STATUS current
DESCRIPTION
- "This trap is exactly the v2 correspondance of testTrap1 in
+ "This trap is exactly the v2 correspondence of testTrap1 in
TestTrap mib."
::= { snmp 1 }
testTrapv22 NOTIFICATION-TYPE
STATUS current
DESCRIPTION
- "This trap is exactly the v2 correspondance of testTrap2 in
+ "This trap is exactly the v2 correspondence of testTrap2 in
TestTrap mib."
::= { system 0 1 }
diff --git a/lib/snmp/test/test-mibs/RFC1213-MIB.mib b/lib/snmp/test/test-mibs/RFC1213-MIB.mib
index 0421e64d62..eeb2535d7d 100644
--- a/lib/snmp/test/test-mibs/RFC1213-MIB.mib
+++ b/lib/snmp/test/test-mibs/RFC1213-MIB.mib
@@ -684,7 +684,7 @@
Setting this object to a null string (one of zero
length) has the effect of invaliding the
corresponding entry in the atTable object. That
- is, it effectively dissasociates the interface
+ is, it effectively disassociates the interface
identified with said entry from the mapping
identified with said entry. It is an
implementation-specific matter as to whether the
@@ -1256,7 +1256,7 @@
Setting this object to the value invalid(2) has
the effect of invalidating the corresponding entry
in the ipRouteTable object. That is, it
- effectively dissasociates the destination
+ effectively disassociates the destination
identified with said entry from the route
identified with said entry. It is an
implementation-specific matter as to whether the
@@ -1475,7 +1475,7 @@
Setting this object to the value invalid(2) has
the effect of invalidating the corresponding entry
in the ipNetToMediaTable. That is, it effectively
- dissasociates the interface identified with said
+ disassociates the interface identified with said
entry from the mapping identified with said entry.
It is an implementation-specific matter as to
whether the agent removes an invalidated entry
diff --git a/lib/snmp/test/test-mibs/SNMPv2-MIB.mib b/lib/snmp/test/test-mibs/SNMPv2-MIB.mib
index 0c5418b9ce..e07e5ae16b 100644
--- a/lib/snmp/test/test-mibs/SNMPv2-MIB.mib
+++ b/lib/snmp/test/test-mibs/SNMPv2-MIB.mib
@@ -221,7 +221,7 @@ sysORUpTime OBJECT-TYPE
STATUS current
DESCRIPTION
"The value of sysUpTime at the time this conceptual row was
- last instanciated."
+ last instantiated."
::= { sysOREntry 4 }
@@ -375,7 +375,7 @@ tst OBJECT IDENTIFIER ::= { system 0 }
testTrapv22 NOTIFICATION-TYPE
STATUS current
DESCRIPTION
- "This trap is exactly the v2 correspondance of testTrap2 in
+ "This trap is exactly the v2 correspondence of testTrap2 in
TestTrap mib."
::= { system 0 1 }
diff --git a/lib/snmp/test/test-mibs/SNMPv2-TC.mib b/lib/snmp/test/test-mibs/SNMPv2-TC.mib
index 1d75c4bbd8..f6051f7a71 100644
--- a/lib/snmp/test/test-mibs/SNMPv2-TC.mib
+++ b/lib/snmp/test/test-mibs/SNMPv2-TC.mib
@@ -629,7 +629,7 @@ value | | see 1| ->C| ->D
time should be long enough to allow for human response time
(including `think time') between the creation of the
conceptual row and the setting of the status to `active'.
- In the absense of such information in the DESCRIPTION
+ In the absence of such information in the DESCRIPTION
clause, it is suggested that this period be approximately 5
minutes in length. This removal action applies not only to
newly-created rows, but also to previously active rows which
diff --git a/lib/snmp/test/test-mibs/SNMPv2-test.mib b/lib/snmp/test/test-mibs/SNMPv2-test.mib
index b02be09138..f435660b2c 100644
--- a/lib/snmp/test/test-mibs/SNMPv2-test.mib
+++ b/lib/snmp/test/test-mibs/SNMPv2-test.mib
@@ -163,7 +163,7 @@ sysQ OBJECT-TYPE
MAX-ACCESS read-write
STATUS current
DESCRIPTION
- "The auxiliar the SYNTAX."
+ "The auxiliary the SYNTAX."
DEFVAL { { a, b } }
::= { system 11 }
@@ -231,7 +231,7 @@ sysORUpTime OBJECT-TYPE
STATUS current
DESCRIPTION
"The value of sysUpTime at the time this conceptual row was
- last instanciated."
+ last instantiated."
::= { sysOREntry 4 }
diff --git a/lib/snmp/test/test_config/Makefile b/lib/snmp/test/test_config/Makefile
index 1e53f51b83..af765cfa5a 100644
--- a/lib/snmp/test/test_config/Makefile
+++ b/lib/snmp/test/test_config/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@ endif
# Targets
# ----------------------------------------------------
-tests debug opt: $(TARGETS)
+tests $(TYPES): $(TARGETS)
clean:
rm -f $(CONFIG_FILES)
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index c448034840..4c11344234 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 5.12
+SNMP_VSN = 5.13.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/Makefile b/lib/ssh/doc/src/Makefile
index a4a25f8eed..3835866fcc 100644
--- a/lib/ssh/doc/src/Makefile
+++ b/lib/ssh/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2021. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@ BOOK_FILES = book.xml
XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) $(XML_REF3_FILES) $(XML_REF6_FILES)\
$(XML_PART_FILES) $(XML_CHAPTER_FILES)
-IMAGE_FILES = SSH_protocols.png
+IMAGE_FILES = SSH_protocols.png ssh_timeouts.jpg
TOP_SPECS_FILE = specs.xml
diff --git a/lib/ssh/doc/src/SSH_app.xml b/lib/ssh/doc/src/SSH_app.xml
index 8f3b5fc80b..4d12669c1e 100644
--- a/lib/ssh/doc/src/SSH_app.xml
+++ b/lib/ssh/doc/src/SSH_app.xml
@@ -282,7 +282,7 @@
</section>
<section>
<title>Unicode support</title>
- <p>Unicode filenames are supported if the emulator and the underlaying OS support it. See section DESCRIPTION in the
+ <p>Unicode filenames are supported if the emulator and the underlying OS support it. See section DESCRIPTION in the
<seeerl marker="kernel:file">file</seeerl> manual page in Kernel for information about this subject.
</p>
<p>The shell and the cli both support unicode.
diff --git a/lib/ssh/doc/src/configurations.xml b/lib/ssh/doc/src/configurations.xml
index cd55e87027..56dc84e7e0 100644
--- a/lib/ssh/doc/src/configurations.xml
+++ b/lib/ssh/doc/src/configurations.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2020</year>
+ <year>2020</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -105,7 +105,7 @@
<p>There is an ordering, which is:
</p>
<list>
- <item>Level 0: Hard-coded default values in the source code</item>
+ <item>Level 0: Hard-coded default values in the OTP SSH source code</item>
<item>Level 1: <seefile marker="kernel:config">OTP Configuration Parameters</seefile></item>
<item>Level 2: Options in the <seefile marker="kernel:config">OTP Configuration Parameters</seefile>
<c>server_options</c> or <c>client_options</c></item>
@@ -116,7 +116,7 @@
<p>The only exception is the
<seetype marker="ssh#modify_algorithms_common_option">modify_algorithms</seetype>
common option. They are all applied in ascending level order on the set of algorithms. So a
- <c>modify_algorithms</c> on level zero is applied before one of level one and so on.
+ <c>modify_algorithms</c> on level one is applied before one of level two and so on.
</p>
<p>If there is an
<seetype marker="ssh#preferred_algorithms_common_option">preferred_algorithms</seetype>
@@ -250,7 +250,7 @@ ok
]).
{ok,&gt;0.118.0>}
</code>
- <p>We check which algoritms are negotiated by the client and the server, and note that
+ <p>We check which algorithms are negotiated by the client and the server, and note that
the (only) <c>kex</c> algorithm <c>'curve25519-sha256@libssh.org'</c> was selected:
</p>
<code>
diff --git a/lib/ssh/doc/src/configure_algos.xml b/lib/ssh/doc/src/configure_algos.xml
index acc6269da5..df4ed145a6 100644
--- a/lib/ssh/doc/src/configure_algos.xml
+++ b/lib/ssh/doc/src/configure_algos.xml
@@ -75,15 +75,15 @@
<tag><c>public_key</c></tag>
<item>
<p>Server host key</p>
- <p>The asymetric encryption algorithm used in the server's private-public host key pair.
+ <p>The asymmetric encryption algorithm used in the server's private-public host key pair.
Examples include the well-known RSA <c>'ssh-rsa'</c> and elliptic curve <c>'ecdsa-sha2-nistp521'</c>.
</p>
</item>
<tag><c>cipher</c></tag>
<item>
- <p>Symetric cipher algorithm used for the payload encryption. This algorithm will use the key calculated
- in the kex phase (together with other info) to genereate the actual key used. Examples are
+ <p>Symmetric cipher algorithm used for the payload encryption. This algorithm will use the key calculated
+ in the kex phase (together with other info) to generate the actual key used. Examples are
tripple-DES <c>'3des-cbc'</c> and one of many AES variants <c>'aes192-ctr'</c>.
</p>
<p>This list is actually two - one for each direction server-to-client and client-to-server. Therefore it
@@ -110,13 +110,13 @@
<section>
<title>The SSH app's mechanism</title>
- <p>The set of algorithms that the SSH app uses by default depends on the algoritms supported by the:</p>
+ <p>The set of algorithms that the SSH app uses by default depends on the algorithms supported by the:</p>
<list>
<item><p><seeerl marker="crypto:crypto">crypto</seeerl> app,</p>
</item>
- <item><p>The cryptolib OTP is linked with, usally the one the OS uses, probably OpenSSL,</p>
+ <item><p>The cryptolib OTP is linked with, usually the one the OS uses, probably OpenSSL,</p>
</item>
- <item><p>and finaly what the SSH app implements</p>
+ <item><p>and finally what the SSH app implements</p>
</item>
</list>
<p>Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.</p>
@@ -170,7 +170,7 @@
<p>To forsee the effect of an option there is an experimental function <c>ssh:chk_algos_opts(Opts)</c>.
It mangles the options <c>preferred_algorithms</c>
- and <c>modify_algorithms</c> in the same way as <c>ssh:dameon</c>, <c>ssh:connect</c> and their friends does.</p>
+ and <c>modify_algorithms</c> in the same way as <c>ssh:daemon</c>, <c>ssh:connect</c> and their friends does.</p>
<section>
<title>Example 1</title>
@@ -322,7 +322,7 @@
<section>
<title>Example 5</title>
<p>As an example let's add the Diffie-Hellman Group1 first in the kex list. It is supported according to
- <seeapp marker="SSH_app#supported_algos">Supported algoritms</seeapp>.</p>
+ <seeapp marker="SSH_app#supported_algos">Supported algorithms</seeapp>.</p>
<code type="erl">
5> ssh:chk_algos_opts(
[{modify_algorithms,
diff --git a/lib/ssh/doc/src/hardening.xml b/lib/ssh/doc/src/hardening.xml
index c1d3f7669c..cc530ace0e 100644
--- a/lib/ssh/doc/src/hardening.xml
+++ b/lib/ssh/doc/src/hardening.xml
@@ -5,14 +5,14 @@
<header>
<copyright>
<year>2017</year>
- <year>2020</year>
+ <year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -59,43 +59,64 @@
However, some measures could be taken in the configuration of the SSH server to increase the resilence.
The options to use
are:</p>
- <taglist>
- <tag><seetype marker="ssh#hello_timeout_daemon_option">hello_timeout</seetype></tag>
- <item>
- If the client fails to send the first ssh message after a tcp connection setup
- within this time (in milliseconds), the connection is closed.
- The default value is 30 seconds. This is actualy a generous time, so it can lowered
- to make the daemon less prone to DoS attacks.
- </item>
- <tag><seetype marker="ssh#negotiation_timeout_daemon_option">negotiation_timeout</seetype></tag>
- <item>
- Maximum time in milliseconds for the authentication negotiation.
- If the client fails to log in within this time, the connection is closed.
- The default value is 2 minutes. It is quite a long time, but can lowered if the client is
- supposed to be fast like if it is a program logging in.
- </item>
- <tag><seeerl marker="ssh#hardening_daemon_options--max_sessions">max_sessions</seeerl></tag>
- <item>
- The maximum number of simultaneous sessions that are accepted at any time for this daemon.
- This includes sessions that are being authorized. The default is that an unlimited number of
- simultaneous sessions are allowed. It is a good candidate to set if the capacity of the server
- is low or a capacity margin is needed.
- </item>
- <tag><seeerl marker="ssh#hardening_daemon_options--max_channels">max_channels</seeerl></tag>
- <item>
- The maximum number of channels that are accepted for each connection. The default is unlimited.
- </item>
- <tag><seeerl marker="ssh#hardening_daemon_options--parallel_login">parallel_login</seeerl></tag>
- <item>
- If set to false (the default value), only one login is handled at a time.
- If set to true, the number of simultaneous login attempts are limited by the value of
- <seeerl marker="ssh#hardening_daemon_options--max_sessions">max_sessions</seeerl> option.
- </item>
- <tag><seetype marker="ssh#max_idle_time_common_option">idle_time<!--sic!--></seetype></tag>
- <item>
- Sets a time-out on a connection when no channels are open. Defaults to infinity.
- </item>
- </taglist>
+ <section>
+ <title>Counters and parallelism</title>
+ <taglist>
+ <tag><seeerl marker="ssh#hardening_daemon_options--max_sessions">max_sessions</seeerl></tag>
+ <item>
+ The maximum number of simultaneous sessions that are accepted at any time for this daemon.
+ This includes sessions that are being authorized. The default is that an unlimited number of
+ simultaneous sessions are allowed. It is a good candidate to set if the capacity of the server
+ is low or a capacity margin is needed.
+ </item>
+ <tag><seeerl marker="ssh#hardening_daemon_options--max_channels">max_channels</seeerl></tag>
+ <item>
+ The maximum number of channels that are accepted for each connection. The default is unlimited.
+ </item>
+ <tag><seeerl marker="ssh#hardening_daemon_options--parallel_login">parallel_login</seeerl></tag>
+ <item>
+ If set to false (the default value), only one login is handled at a time.
+ If set to true, the number of simultaneous login attempts are limited by the value of the
+ <seeerl marker="ssh#hardening_daemon_options--max_sessions">max_sessions</seeerl> option.
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <title>Timeouts</title>
+ <taglist>
+ <tag><seetype marker="ssh#hello_timeout_daemon_option">hello_timeout</seetype></tag>
+ <item>
+ If the client fails to send the first ssh message after a tcp connection setup
+ within this time (in milliseconds), the connection is closed.
+ The default value is 30 seconds. This is actually a generous time, so it can lowered
+ to make the daemon less prone to DoS attacks.
+ </item>
+ <tag><seetype marker="ssh#negotiation_timeout_daemon_option">negotiation_timeout</seetype></tag>
+ <item>
+ Maximum time in milliseconds for the authentication negotiation counted from the TCP connection establishment.
+ If the client fails to log in within this time the connection is closed.
+ The default value is 2 minutes. It is quite a long time, but can lowered if the client is
+ supposed to be fast like if it is a program logging in.
+ </item>
+ <tag><seetype marker="ssh#max_idle_time_common_option">idle_time<!--sic!--></seetype></tag>
+ <item>
+ Sets a time-out on a connection when no channels are left after closing the final one.
+ It defaults to infinity.
+ </item>
+ <tag><seetype marker="ssh#max_initial_idle_time_daemon_option">max_initial_idle_time</seetype></tag>
+ <item>
+ Sets a time-out on a connection that will expire if no channel is opened on the connection.
+ The timeout is started when the authentication phase is completed.
+ It defaults to infinity.
+ </item>
+ </taglist>
+ <p>A figure clarifies when a timeout is started and when it triggers:
+ </p>
+ <image file="ssh_timeouts.jpg">
+ <icaption>SSH server timeouts</icaption>
+ </image>
+ </section>
</section>
@@ -170,7 +191,7 @@ fun(User, Password, _PeerAddress, State) ->
end.
</code>
<p>If a public key is used for logging in, there is normally no checking of the user name. It
- could be enabled by setting the option
+ could be enabled by setting the option
<seeerl marker="ssh#option-pk_check_user"><c>pk_check_user</c></seeerl>
to <c>true</c>.
In that case the pwdfun will get the atom <c>pubkey</c> in the password argument.
@@ -251,7 +272,7 @@ end.
<code>
ssh:daemon(1234, [{id_string,"hi there"}, ... ]).
</code>
- <p>and the deamon will present itself as:</p>
+ <p>and the daemon will present itself as:</p>
<pre>SSH-2.0-hi there</pre>
<p>It is possible to replace the string with one randomly generated for each connection attempt.
See the reference manual for <seetype marker="ssh#id_string_common_option">id_string</seetype>.
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 54904de950..b445e649f8 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2022</year>
+ <year>2004</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,6 +30,242 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.15.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, PKCS8 formatted private key file is
+ properly decoded and SSH daemon with such key can be
+ started.</p>
+ <p>
+ Own Id: OTP-18446 Aux Id: GH-6475 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.15.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, ssh application does not crash when
+ formatting some of info reports for unsuccessful
+ connections.</p>
+ <p>
+ Own Id: OTP-18386 Aux Id: PR-6611 </p>
+ </item>
+ <item>
+ <p>
+ With this change, ssh does not log extensively long
+ messages.</p>
+ <p>
+ Own Id: OTP-18417 Aux Id: DAFH-1349,ERIERL-888,IA18357 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.15.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ graceful shutdown of ssh_conection_handler when
+ connection is closed by peer</p>
+ <p>
+ Own Id: OTP-18326 Aux Id: ERIERL-865 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.15</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Handling rare race condition at channel close.</p>
+ <p>
+ Own Id: OTP-18220 Aux Id: ERIERL-666, ERIERL-661 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ New ssh option <c>no_auth_needed</c> to skip the ssh
+ authentication. Use with caution!</p>
+ <p>
+ Own Id: OTP-18134 Aux Id: GH-6021 </p>
+ </item>
+ <item>
+ <p>
+ This change fixes dialyzer warnings generated for
+ inets/httpd examples (includes needed adjustment of spec
+ for ssh_sftp module).</p>
+ <p>
+ Own Id: OTP-18178 Aux Id: ERIERL-833, ERIERL-834,
+ ERIERL-835 </p>
+ </item>
+ <item>
+ <p>
+ The new function <c>ssh:daemon_replace_options/2</c>
+ makes it possible to change the <c>Options</c> in a
+ running SSH server.</p>
+ <p>
+ Established connections are not affected, only those
+ created after the call to this new function.</p>
+ <p>
+ Own Id: OTP-18196</p>
+ </item>
+ <item>
+ <p>
+ Add a timeout as option <c>max_initial_idle_time</c>. It
+ closes a connection that does not allocate a channel
+ within the timeout time.</p>
+ <p>
+ For more information about timeouts, see the <seeguide
+ marker="hardening#timeouts">Timeouts section </seeguide>
+ in the User's Guide <seeguide
+ marker="hardening">Hardening</seeguide> chapter.</p>
+ <p>
+ Own Id: OTP-18207 Aux Id: PR-6231 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.14.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Binaries can be limited in logs with the parameter
+ <c>max_log_item_len</c>. The default value is 500 bytes.</p>
+ <p>
+ Own Id: OTP-18094</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.14</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The representation of Edward curves (ed25519 and ed448)
+ inside ssh had a temporary representation (ed_pri and
+ ed_pub).</p>
+ <p>
+ That is now changed to the public_key form. See the
+ manual for more information.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17920</p>
+ </item>
+ <item>
+ <p>
+ Former internal function
+ <c>ssh_file:extract_public_key/1</c> documented publicly.</p>
+ <p>
+ Internally it was previously in ssh_transport.</p>
+ <p>
+ Own Id: OTP-18079 Aux Id: GH-5767 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.13.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, ssh application does not crash when
+ formatting some of info reports for unsuccessful
+ connections.</p>
+ <p>
+ Own Id: OTP-18386 Aux Id: PR-6611 </p>
+ </item>
+ <item>
+ <p>
+ With this change, ssh does not log extensively long
+ messages.</p>
+ <p>
+ Own Id: OTP-18417 Aux Id: DAFH-1349,ERIERL-888,IA18357 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.13.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Binaries can be limited in logs with the parameter
+ <c>max_log_item_len</c>. The default value is 500 bytes.</p>
+ <p>
+ Own Id: OTP-18094</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.13.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -340,6 +576,22 @@
</section>
+<section><title>Ssh 4.11.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Binaries can be limited in logs with the parameter
+ <c>max_log_item_len</c>. The default value is 500 bytes.</p>
+ <p>
+ Own Id: OTP-18094</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.11.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1125,7 +1377,7 @@
input/output, the I/O was erroneously handled by the
*server's* group leader, so the I/O turned up in the the
server's Erlang shell (if any). The user at the client
- side did therefor not see that I/O.</p>
+ side did therefore not see that I/O.</p>
<p>
This is corrected now, so the client - for example the
ssh OS shell command - handles the I/O. The user could
@@ -1670,7 +1922,7 @@
</item>
<item>
<p>
- The type specifications in SSH are completly reworked and
+ The type specifications in SSH are completely reworked and
the following types are renamed:</p>
<p>
<c>ssh:ssh_connection_ref()</c> is changed to
@@ -1935,7 +2187,7 @@
</item>
<item>
<p>
- Fix rare spurios shutdowns of ssh servers when receiveing
+ Fix rare spurious shutdowns of ssh servers when receiving
<c>{'EXIT',_,normal}</c> messages.</p>
<p>
Own Id: OTP-15018</p>
@@ -2386,7 +2638,7 @@
<list>
<item>
<p>
- Fix rare spurios shutdowns of ssh servers when receiveing
+ Fix rare spurious shutdowns of ssh servers when receiving
<c>{'EXIT',_,normal}</c> messages.</p>
<p>
Own Id: OTP-15018</p>
@@ -2618,7 +2870,7 @@
<item>
<p>
If a client illegaly sends an info-line and then
- immediatly closes the TCP-connection, a badmatch
+ immediately closes the TCP-connection, a badmatch
exception was raised.</p>
<p>
Own Id: OTP-13966</p>
@@ -2831,7 +3083,7 @@
<list>
<item>
<p>
- Fix rare spurios shutdowns of ssh servers when receiveing
+ Fix rare spurious shutdowns of ssh servers when receiving
<c>{'EXIT',_,normal}</c> messages.</p>
<p>
Own Id: OTP-15018</p>
@@ -3453,7 +3705,7 @@
<p>
The possible values are: <c>{id_string,string()}</c> and
<c>{id_string,random}</c>. The latter will make ssh
- generate a random nonsence id-string for each new
+ generate a random nonsense id-string for each new
connection.</p>
<p>
Own Id: OTP-12659</p>
@@ -3579,7 +3831,7 @@
<p>
The possible values are: <c>{id_string,string()}</c> and
<c>{id_string,random}</c>. The latter will make ssh
- generate a random nonsence id-string for each new
+ generate a random nonsense id-string for each new
connection.</p>
<p>
Own Id: OTP-12659</p>
@@ -4242,7 +4494,7 @@
<list>
<item>
<p>
- ssh:daemon will get feeded with an argument even if it is
+ ssh:daemon will get fed with an argument even if it is
not a valid expression.</p>
<p>
Own Id: OTP-10975</p>
@@ -4590,7 +4842,7 @@
<list>
<item>
<p>
- All keys in authorized_keys are considerd, wrongly only
+ All keys in authorized_keys are considered, wrongly only
the first one was before.</p>
<p>
Own Id: OTP-7235</p>
@@ -4964,7 +5216,7 @@
<list>
<item>
<p>
- Now clear all processes when a connnection is terminated.</p>
+ Now clear all processes when a connection is terminated.</p>
<p>
Own Id: OTP-8121 Aux Id:</p>
</item>
@@ -5062,13 +5314,13 @@
<list>
<item>
<p>
- ssh_sftp:start_channel/3 did not handle timout correctly.</p>
+ ssh_sftp:start_channel/3 did not handle timeout correctly.</p>
<p>
Own Id: OTP-8159 Aux Id: seq11386</p>
</item>
<item>
<p>
- If a progress message was not recieved after invoking ssh:connect/3
+ If a progress message was not received after invoking ssh:connect/3
the call could hang for ever. A timeout option has also been added.</p>
<p>
Own Id: OTP-8160 Aux Id: seq11386</p>
diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml
index 44188ea34c..d58166711a 100644
--- a/lib/ssh/doc/src/ssh.xml
+++ b/lib/ssh/doc/src/ssh.xml
@@ -4,14 +4,14 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -21,7 +21,7 @@
limitations under the License.
</legalnotice>
-
+
<title>ssh</title>
<prepared></prepared>
<docno></docno>
@@ -40,8 +40,8 @@
<p>With the SSH application it is possible to start <i>clients</i> and to start <i>daemons</i> (servers).
</p>
<p>Clients are started with
- <seemfa marker="#connect/2">connect/2</seemfa>,
- <seemfa marker="#connect/3">connect/3</seemfa> or
+ <seemfa marker="#connect/2">connect/2</seemfa>,
+ <seemfa marker="#connect/3">connect/3</seemfa> or
<seemfa marker="#connect/4">connect/4</seemfa>. They open an encrypted connection on top of TCP/IP.
In that encrypted connection one or more channels could be opened with
<seemfa marker="ssh_connection#session_channel/2">ssh_connection:session_channel/2,4</seemfa>.
@@ -52,32 +52,32 @@
the user is not necessarily a human but probably a system interfacing the SSH app.
</p>
<p>A server-side subssystem (channel) server is requested by the client with
- <seemfa marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seemfa>.
+ <seemfa marker="ssh_connection#subsystem/4">ssh_connection:subsystem/4</seemfa>.
</p>
- <p>A server (daemon) is started with
+ <p>A server (daemon) is started with
<seemfa marker="#daemon/2">daemon/1</seemfa>,
<seemfa marker="#daemon/2">daemon/2</seemfa> or
<seemfa marker="#daemon/2">daemon/3</seemfa>.
Possible channel handlers (subsystems) are declared with the
<seetype marker="#subsystem_daemon_option">subsystem</seetype> option when the daemon is started.
</p>
- <p>To just run a shell on a remote machine, there are functions that bundles the needed
+ <p>To just run a shell on a remote machine, there are functions that bundles the needed
three steps needed into one:
<seemfa marker="#shell/1">shell/1,2,3</seemfa>.
- Similarily, to just open an sftp (file transfer) connection to a remote machine, the simplest way is to use
+ Similarly, to just open an sftp (file transfer) connection to a remote machine, the simplest way is to use
<seemfa marker="ssh_sftp#start_channel/1">ssh_sftp:start_channel/1,2,3</seemfa>.
</p>
- <p>To write your own client channel handler, use the behaviour
- <seeerl marker="ssh_client_channel">ssh_client_channel</seeerl>. For server channel handlers use
+ <p>To write your own client channel handler, use the behaviour
+ <seeerl marker="ssh_client_channel">ssh_client_channel</seeerl>. For server channel handlers use
<seeerl marker="ssh_server_channel">ssh_server_channel</seeerl> behaviour (replaces ssh_daemon_channel).
</p>
<p>Both clients and daemons accepts options that controls the exact behaviour. Some options are common to both.
- The three sets are called
- <seetype marker="#client_options">Client Options</seetype>,
+ The three sets are called
+ <seetype marker="#client_options">Client Options</seetype>,
<seetype marker="#daemon_options">Daemon Options</seetype> and
<seetype marker="#common_options">Common Options</seetype>.
</p>
- <p>The descriptions of the options uses the
+ <p>The descriptions of the options uses the
<seeguide marker="system/reference_manual:typespec">Erlang Type Language</seeguide> with explaining text.
</p>
<note>
@@ -90,7 +90,7 @@
<section>
<title>Keys and files</title>
- <p>A number of objects must be present for the SSH application to work.
+ <p>A number of objects must be present for the SSH application to work.
Those objects are per default stored in files.
The default names, paths and file formats are the same as for
<url href="http://www.openssh.com">OpenSSH</url>. Keys could be generated with the <c>ssh-keygen</c>
@@ -102,7 +102,7 @@
<seetype marker="ssh_file#user_dir_common_option"><c>user_dir</c></seetype> and
<seetype marker="ssh_file#system_dir_daemon_option"><c>system_dir</c></seetype>.
</p>
- <p>A completly different storage could be interfaced by writing call-back modules
+ <p>A completely different storage could be interfaced by writing call-back modules
using the behaviours
<seeerl marker="ssh_client_key_api">ssh_client_key_api</seeerl> and/or
<seeerl marker="ssh_server_key_api">ssh_server_key_api</seeerl>.
@@ -122,12 +122,12 @@
<item><c>ssh_host_rsa_key</c> and <c>ssh_host_rsa_key.pub</c></item>
<item><c>ssh_host_ecdsa_key</c> and <c>ssh_host_ecdsa_key.pub</c></item>
</list>
- <p>The host keys directory could be changed with the option
+ <p>The host keys directory could be changed with the option
<seetype marker="ssh_file#system_dir_daemon_option"><c>system_dir</c></seetype>.</p>
</item>
<item>Optional: one or more <i>User's public key</i> in case of <c>publickey</c> authorization.
Default is to store them concatenated in the file <c>.ssh/authorized_keys</c> in the user's home directory.
- <p>The user keys directory could be changed with the option
+ <p>The user keys directory could be changed with the option
<seetype marker="ssh_file#user_dir_common_option"><c>user_dir</c></seetype>.</p>
</item>
</list>
@@ -137,14 +137,14 @@
<title>Clients</title>
<p>The keys and some other data are by default stored in files in the directory <c>.ssh</c>
in the user's home directory.</p>
- <p>The directory could be changed with the option
+ <p>The directory could be changed with the option
<seetype marker="ssh_file#user_dir_common_option"><c>user_dir</c></seetype>.
</p>
<list>
<item>Optional: a list of <i>Host public key(s)</i> for previously connected hosts. This list
is handled by the SSH application without any need of user assistance. The default
is to store them in the file <c>known_hosts</c>.
- <p>The
+ <p>The
<seetype marker="#host_accepting_client_options">host_accepting_client_options()</seetype>
are associated with this list of keys.
</p>
@@ -206,12 +206,12 @@
<c>silently_accept_hosts</c>
</tag>
<item>
- <p>This option guides the <c>connect</c> function on how to act when the connected server presents a Host
+ <p>This option guides the <c>connect</c> function on how to act when the connected server presents a Host
Key that the client has not seen before. The default is to ask the user with a question on stdio of whether to
accept or reject the new Host Key.
See the option <seetype marker="ssh_file#user_dir_common_option"><c>user_dir</c></seetype>
for specifying the path to the file <c>known_hosts</c> where previously accepted Host Keys are recorded.
- See also the option
+ See also the option
<seetype marker="#key_cb_common_option">key_cb</seetype>
for the general way to handle keys.
</p>
@@ -228,7 +228,7 @@
result the connection will be closed. The arguments to the fun are:
<list type="bulleted">
<item><c>PeerName</c> - a string with the name or address of the remote host.</item>
- <item><c>FingerPrint</c> - the fingerprint of the Host Key as
+ <item><c>FingerPrint</c> - the fingerprint of the Host Key as
<seemfa marker="#hostkey_fingerprint/1">hostkey_fingerprint/1</seemfa>
calculates it.
</item>
@@ -241,12 +241,12 @@
is either an atom or a list of atoms as the first argument in
<seemfa marker="#hostkey_fingerprint/2">hostkey_fingerprint/2</seemfa>.
If it is a list of hash algorithm names, the <c>FingerPrint</c> argument in the
- <c>accept_callback()</c> will be
+ <c>accept_callback()</c> will be
a list of fingerprints in the same order as the corresponding name in the <c>HashAlgoSpec</c> list.
</item>
</list>
</item>
-
+
<tag><c>user_interaction</c></tag>
<item>
<p>If <c>false</c>, disables the client to connect to the server
@@ -322,7 +322,7 @@
<name name="connect_timeout_client_option"/>
<desc>
<p>Sets a timeout on the transport layer connect time.
- For <seeerl marker="kernel:gen_tcp"><c>gen_tcp</c></seeerl> the time is in milli-seconds and the default
+ For <seeerl marker="kernel:gen_tcp"><c>gen_tcp</c></seeerl> the time is in milli-seconds and the default
value is <c>infinity</c>.
</p>
<p>See the parameter <c>Timeout</c> in <seemfa marker="#connect/4">connect/4</seemfa> for
@@ -335,7 +335,7 @@
<name name="recv_ext_info_client_option"/>
<desc>
<p>Make the client tell the server that the client accepts extension negotiation, that is,
- include <c>ext-info-c</c> in the kexinit message sent. See
+ include <c>ext-info-c</c> in the kexinit message sent. See
<url href="https://tools.ietf.org/html/rfc8308">RFC 8308</url>
for details and <seeapp marker="SSH_app#supported-ext-info">ssh(6)</seeapp>
for a list of currently implemented extensions.
@@ -370,7 +370,7 @@
</desc>
</datatype>
-
+
<datatype>
<name name="subsystem_daemon_option"/>
<name name="subsystem_specs"/>
@@ -382,7 +382,7 @@
</p>
<p>The <c>channel_callback</c> is the module that implements the
<seeerl marker="ssh_server_channel">ssh_server_channel</seeerl> (replaces ssh_daemon_channel)
- behaviour in the daemon. See the section
+ behaviour in the daemon. See the section
<seeguide marker="using_ssh#usersguide_creating_a_subsystem">Creating a Subsystem</seeguide>
in the User's Guide for more information and an example.
</p>
@@ -440,8 +440,8 @@
</p>
<p>In case of the <c>{direct, exec_fun()}</c> variant or no exec-option at all,
all reads from <c>standard_input</c> will be from the received data-events of type 0.
- Those are sent by the client. Similarily all writes to <c>standard_output</c>
- will be sent as data-events to the client. An OS shell client like the command 'ssh' will usally use
+ Those are sent by the client. Similarly all writes to <c>standard_output</c>
+ will be sent as data-events to the client. An OS shell client like the command 'ssh' will usually use
stdin and stdout for the user interface.
</p>
<p>The option cooperates with the daemon-option <seetype marker="#shell_daemon_option"><c>shell</c></seetype>
@@ -473,7 +473,7 @@
<seetype marker="#shell_daemon_option"><c>shell_spec</c></seetype>'s value.
</p>
</item>
-
+
<tag>4. If the <seetype marker="#exec_daemon_option"><c>exec-option</c></seetype> is absent, and the
<seetype marker="#shell_daemon_option"><c>shell-option</c></seetype>
is present with the default Erlang shell as the
@@ -483,7 +483,7 @@
<p>The default Erlang evaluator is used both for exec and shell requests.
The result is returned to the client.</p>
</item>
-
+
<tag>5. If the <seetype marker="#exec_daemon_option"><c>exec-option</c></seetype> is absent, and the
<seetype marker="#shell_daemon_option"><c>shell-option</c></seetype>
is present with a value that is neither the default Erlang shell nor the value <c>disabled</c>:</tag>
@@ -492,7 +492,7 @@
are executed according to the value of the
<seetype marker="#shell_daemon_option"><c>shell_spec</c></seetype>.</p>
</item>
-
+
<tag>6. If the <seetype marker="#exec_daemon_option"><c>exec-option</c></seetype> is absent, and the
<seetype marker="#shell_daemon_option"><c>shell_spec</c></seetype>'s value is <c>disabled</c>:</tag>
<item>
@@ -601,11 +601,11 @@
</warning>
</item>
- <tag><marker id="option-pwdfun"/><c>pwdfun</c> with
+ <tag><marker id="option-pwdfun"/><c>pwdfun</c> with
<seetype marker="#pwdfun_4"><c>pwdfun_4()</c></seetype>
</tag>
<item>
- <p>Provides a function for password validation. This could used for calling an external system or handeling
+ <p>Provides a function for password validation. This could used for calling an external system or handling
passwords stored as hash values.
</p>
<p>This fun can also be used to make delays in authentication tries for example by calling
@@ -618,13 +618,13 @@
</p>
<list type="bulleted">
<item><c>true</c> if the user and password is valid</item>
- <item><c>false</c> if the user or password is invalid</item>
+ <item><c>false</c> if the user or password is invalid</item>
<item><c>disconnect</c> if a SSH_MSG_DISCONNECT message should be sent immediately. It will
be followed by a close of the underlying tcp connection.</item>
<item><c>{true, NewState:any()}</c> if the user and password is valid</item>
- <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
+ <item><c>{false, NewState:any()}</c> if the user or password is invalid</item>
</list>
- <p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
+ <p>A third usage is to block login attempts from a missbehaving peer. The <c>State</c> described above
can be used for this. The return value <c>disconnect</c> is useful for this.</p>
<p>In case of the <seeerl marker="#option-pk_check_user"><c>pk_check_user</c></seeerl> is set,
the atom <c>pubkey</c> is put in the password argument when validating a public key login. The
@@ -640,7 +640,7 @@
as strings, and returns:</p>
<list type="bulleted">
<item><c>true</c> if the user and password is valid</item>
- <item><c>false</c> if the user or password is invalid</item>
+ <item><c>false</c> if the user or password is invalid</item>
</list>
<p>In case of the <seeerl marker="#option-pk_check_user"><c>pk_check_user</c></seeerl> is set,
the atom <c>pubkey</c> is put in the password argument when validating a public key login. The
@@ -648,6 +648,19 @@
</p>
<p>This variant is kept for compatibility.</p>
</item>
+
+ <tag><marker id="option-no_auth_needed"/><c>no_auth_needed</c></tag>
+ <item>
+ <p>If <c>true</c>, a client is authenticated without any need of
+ providing any password or key.
+ </p>
+ <p>This option is only intended for very special applications due
+ to the high risk of accepting any connecting client.
+ </p>
+ <p>The default value is <c>false</c>.
+ </p>
+ </item>
+
</taglist>
</desc>
</datatype>
@@ -662,7 +675,7 @@
<tag><c>dh_gex_groups</c></tag>
<item>
<p>Defines the groups the server may choose among when diffie-hellman-group-exchange is negotiated.
- See
+ See
<url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
for details. The three variants of this option are:
</p>
@@ -672,7 +685,7 @@
In such a case, the server will choose one randomly in the negotiated Size.
</item>
<tag><c>{file,filename()}</c></tag>
- <item>The file must have one or more three-tuples <c>{Size=integer(),G=integer(),P=integer()}</c>
+ <item>The file must have one or more three-tuples <c>{Size=integer(),G=integer(),P=integer()}</c>
terminated by a dot. The file is read when the daemon starts.
</item>
<tag><c>{ssh_moduli_file,filename()}</c></tag>
@@ -681,7 +694,7 @@
The file is read when the daemon starts.
</item>
</taglist>
- <p>The default list is fetched from the
+ <p>The default list is fetched from the
<seemfa marker="public_key:public_key#dh_gex_group/4">public_key</seemfa> application.
</p>
</item>
@@ -690,14 +703,14 @@
<item>
<p>Limits what a client can ask for in diffie-hellman-group-exchange.
The limits will be
- <c>{MaxUsed = min(MaxClient,Max), MinUsed = max(MinClient,Min)}</c> where <c>MaxClient</c> and
+ <c>{MaxUsed = min(MaxClient,Max), MinUsed = max(MinClient,Min)}</c> where <c>MaxClient</c> and
<c>MinClient</c> are the values proposed by a connecting client.
</p>
<p>The default value is <c>{0,infinity}</c>.
</p>
<p>If <c>MaxUsed &lt; MinUsed</c> in a key exchange, it will fail with a disconnect.
</p>
- <p>See
+ <p>See
<url href="https://tools.ietf.org/html/rfc4419">RFC 4419</url>
for the function of the Max and Min values.</p>
</item>
@@ -712,6 +725,10 @@
Defaults to 30000 ms (30 seconds). If the client fails to send the first message within this time,
the connection is closed.
</p>
+ <p>For more information about timeouts, see the
+ <seeguide marker="hardening#timeouts">Timeouts section </seeguide>
+ in the User's Guide <seeguide marker="hardening">Hardening</seeguide> chapter.
+ </p>
</desc>
</datatype>
@@ -722,12 +739,33 @@
Defaults to 120000 ms (2 minutes). If the client fails to log in within this time,
the connection is closed.
</p>
+ <p>For more information about timeouts, see the
+ <seeguide marker="hardening#timeouts">Timeouts section </seeguide>
+ in the User's Guide <seeguide marker="hardening">Hardening</seeguide> chapter.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="max_initial_idle_time_daemon_option"/>
+ <desc>
+ <p>Maximum time in milliseconds for the first channel start after
+ completion of the authentication negotiation.
+ Defaults to <c>infinity</c>.
+ </p>
+ <p>For more information about timeouts, see the
+ <seeguide marker="hardening#timeouts">Timeouts section </seeguide>
+ in the User's Guide <seeguide marker="hardening">Hardening</seeguide> chapter.
+ </p>
</desc>
</datatype>
<datatype>
<name name="hardening_daemon_options"/>
<desc>
+ <p>For more information about hardening, see the
+ <seeguide marker="hardening">Hardening</seeguide> section in the User's Guide chapter.
+ </p>
<taglist>
<tag>
<marker id="hardening_daemon_options--max_sessions"/>
@@ -751,7 +789,7 @@
<p>By default, this option is not set. This means that the number is not limited.
</p>
</item>
-
+
<tag>
<marker id="hardening_daemon_options--max_channels"/>
<c>max_channels</c>
@@ -792,11 +830,11 @@
The default value is 0.
</p>
</item>
-
+
</taglist>
</desc>
</datatype>
-
+
<datatype>
<name name="callbacks_daemon_options"/>
<desc>
@@ -880,6 +918,19 @@
<p>The timeout is not active until channels are started, so it does
not limit the time from the connection creation to the first channel opening.
</p>
+ <p>For more information about timeouts, see the
+ <seeguide marker="hardening#timeouts">Timeouts section </seeguide>
+ in the User's Guide <seeguide marker="hardening">Hardening</seeguide> chapter.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="max_log_item_len_common_option"/>
+ <desc>
+ <p>Sets a limit for the size of a logged item excluding a header.
+ The unit is bytes and the value defaults to 500.
+ </p>
</desc>
</datatype>
@@ -925,10 +976,10 @@
<code>
Module:F(..., [{key_cb_private,Opts}|UserOptions])
</code>
- <p>where <c>...</c> are arguments to <c>F</c> as in
+ <p>where <c>...</c> are arguments to <c>F</c> as in
<seeerl marker="ssh_client_key_api">ssh_client_key_api</seeerl> and/or
<seeerl marker="ssh_server_key_api">ssh_server_key_api</seeerl>.
- The <c>UserOptions</c> are the options given to
+ The <c>UserOptions</c> are the options given to
<seemfa marker="ssh:ssh#connect/3">ssh:connect</seemfa>,
<seemfa marker="ssh:ssh#shell/1">ssh:shell</seemfa> or
<seemfa marker="ssh:ssh#daemon/2">ssh:daemon</seemfa>.
@@ -973,7 +1024,7 @@
<name name="ssh_msg_debug_fun_common_option"/>
<desc>
<p>Provide a fun to implement your own logging of the SSH message SSH_MSG_DEBUG.
- The last three parameters are from the message, see
+ The last three parameters are from the message, see
<url href="https://tools.ietf.org/html/rfc4253#section-11.3">RFC 4253, section 11.3</url>.
The <seetype marker="#connection_ref"><c>connection_ref()</c></seetype> is the reference
to the connection on which the message arrived.
@@ -1018,7 +1069,7 @@
<p>If an alg_entry() is missing in the algs_list(), the default value is used for that entry.</p>
<p>Here is an example of this option:</p>
<code>
- {preferred_algorithms,
+ {preferred_algorithms,
[{public_key,['ssh-rsa','ssh-dss']},
{cipher,[{client2server,['aes128-ctr']},
{server2client,['aes128-cbc','3des-cbc']}]},
@@ -1051,7 +1102,7 @@
<desc>
<p>Modifies the list of algorithms to use in the algorithm negotiation. The modifications are
applied after the option <c>preferred_algorithms</c> (if existing) is applied.</p>
- <p>The algoritm for modifications works like this:</p>
+ <p>The algorithm for modifications works like this:</p>
<list>
<item>
<p>Input is the <c>modify_algs_list()</c> and a set of algorithms <c>A</c>
@@ -1085,7 +1136,7 @@
<p>If there are more than one modify_algorithms options, the result is undefined.</p>
<p>Here is an example of this option:</p>
<code>
- {modify_algorithms,
+ {modify_algorithms,
[{prepend, [{kex, ['diffie-hellman-group1-sha1']}],
{rm, [{compression, [none]}]}
]
@@ -1131,7 +1182,7 @@
<!--................................................................-->
<datatype_title>Other data types</datatype_title>
-
+
<datatype>
<name name="host"/>
<desc>
@@ -1149,13 +1200,13 @@
<desc>
</desc>
</datatype>
-
+
<datatype>
<name name="mod_fun_args"/>
<desc>
</desc>
</datatype>
-
+
<datatype>
<name name="open_socket"/>
<desc>
@@ -1222,7 +1273,7 @@
<p>In the <c>option</c> info tuple are only the options included that differs from the default values.
</p>
</desc>
- </datatype>
+ </datatype>
<datatype>
<name>opaque_client_options()</name>
@@ -1248,7 +1299,7 @@
<fsummary>Closes an SSH connection.</fsummary>
<desc><p>Closes an SSH connection.</p></desc>
</func>
-
+
<!-- CONNECT/2 etc -->
<func>
<name since="">connect(Host, Port, Options) -> Result </name>
@@ -1318,7 +1369,7 @@
<p>are allowed. The excluded options are reserved by the SSH application.
</p>
<warning>
- <p>This is an extremly dangerous function. You use it on your own risk.</p>
+ <p>This is an extremely dangerous function. You use it on your own risk.</p>
<p>Some options are OS and OS version dependent.
Do not use it unless you know what effect your option values will have
on an TCP stream.</p>
@@ -1340,7 +1391,7 @@
</desc>
</func>
-<!-- DEAMON/1,2,3 -->
+<!-- DAEMON/1,2,3 -->
<func>
<name since="">daemon(Port | TcpSocket) -> Result</name>
<name since="">daemon(Port | TcpSocket, Options) -> Result</name>
@@ -1374,7 +1425,7 @@
An 'ip'-option will be discarded if present.</item>
<item>if <c>HostAddress</c> is the atom <c>loopback</c>, the listening address
- is <c>loopback</c> and an loopback address will be choosen by the underlying layers.
+ is <c>loopback</c> and an loopback address will be chosen by the underlying layers.
An 'ip'-option will be discarded if present.</item>
<item>if <c>HostAddress</c> is the atom <c>any</c> and no 'ip'-option is present, the listening address is
@@ -1386,7 +1437,32 @@
</desc>
</func>
-<!-- DAEMON_INFO/1 -->
+<!-- DAEMON_REPLACE_OPTIONS/2 -->
+ <func>
+ <name name="daemon_replace_options" arity="2" since="OTP 25.1"/>
+ <fsummary>Change options in a running daemon</fsummary>
+ <desc>
+ <p>
+ Replaces the options in a running daemon with the options in
+ <c>NewUserOptions</c>. Only connections established after this call
+ are affected, already established connections are not.
+ </p>
+ <note>
+ <p>In the final phase of this function, the listening process is restarted.
+ Therfore a connection attempt to the daemon in this final phase could fail.
+ </p>
+ </note>
+ <p>
+ The handling of Erlang configurations is described in the User's Guide;
+ see chapters
+ <seeguide marker="configurations">Configuration in SSH</seeguide>
+ and
+ <seeguide marker="configure_algos">Configuring algorithms in SSH</seeguide>.
+ </p>
+ </desc>
+ </func>
+
+<!-- DAEMON_INFO/1 -->
<func>
<name name="daemon_info" arity="1" since="OTP 19.0"/>
<name name="daemon_info" arity="2" since="OTP 22.1"/>
@@ -1402,7 +1478,6 @@
</desc>
</func>
-
<!-- DEFAULT_ALGORITHMS/0 -->
<func>
<name name="default_algorithms" arity="0" since="OTP 18.0"/>
@@ -1433,7 +1508,7 @@
interactive shell on that remote host.
</p>
<p>As an alternative, an already open TCP socket could be passed to the function in <c>TcpSocket</c>.
- The SSH initiation and negotiation will be initiated on that one and finaly a shell will be started
+ The SSH initiation and negotiation will be initiated on that one and finally a shell will be started
on the host at the other end of the TCP socket.
</p>
<p>For a description of the options, see <seetype marker="#client_options">Client Options</seetype>.</p>
@@ -1464,7 +1539,7 @@
manual page in Kernel.</p>
</desc>
</func>
-
+
<func>
<name name="stop_daemon" arity="1" since=""/>
<name name="stop_daemon" arity="2" since=""/>
@@ -1506,7 +1581,7 @@
</p>
</desc>
</func>
-
+
<func>
<name name="tcpip_tunnel_to_server" arity="5" since="OTP 23.0"/>
<name name="tcpip_tunnel_to_server" arity="6" since="OTP 23.0"/>
@@ -1544,7 +1619,7 @@
in uppercase as in newer ssh-keygen commands.</p>
<p>Examples:</p>
<code>
- 2> ssh:hostkey_fingerprint(Key).
+ 2> ssh:hostkey_fingerprint(Key).
"f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
3> ssh:hostkey_fingerprint(md5,Key).
@@ -1566,5 +1641,5 @@
</funcs>
-
+
</erlref>
diff --git a/lib/ssh/doc/src/ssh_agent.xml b/lib/ssh/doc/src/ssh_agent.xml
index a6ff511f2f..ceada72371 100644
--- a/lib/ssh/doc/src/ssh_agent.xml
+++ b/lib/ssh/doc/src/ssh_agent.xml
@@ -52,7 +52,7 @@
</code>
<p>
The agent communication is established through a UNIX domain socket. By default, the socket path
- will be fetched from the <c>SSH_AUTH_SOCK</c> enviroment variable, which is the default socket path in the agent
+ will be fetched from the <c>SSH_AUTH_SOCK</c> environment variable, which is the default socket path in the agent
implementation of
<url href="http://www.openssh.com">OpenSSH</url>.
</p>
diff --git a/lib/ssh/doc/src/ssh_client_key_api.xml b/lib/ssh/doc/src/ssh_client_key_api.xml
index a81d0d3274..cb20724496 100644
--- a/lib/ssh/doc/src/ssh_client_key_api.xml
+++ b/lib/ssh/doc/src/ssh_client_key_api.xml
@@ -69,7 +69,7 @@
<v>ConnectOptions = <seetype marker="#client_key_cb_options">client_key_cb_options()</seetype></v>
</type>
<desc>
- <p>This function is retired in favour for <c>Module:add_host_key/4</c> which is the prefered API function.
+ <p>This function is retired in favour for <c>Module:add_host_key/4</c> which is the preferred API function.
The calling SSH application will still try the <c>add_host_key/3</c> if the call to <c>add_host_key/4</c> failed.
</p>
<p>Adds a host key to the set of trusted host keys.</p>
@@ -96,10 +96,10 @@
</type>
<desc>
<p>Adds a host key to the set of trusted host keys.</p>
- <p>This function is prefered to the old <c>Module:add_host_key/3</c> since it also uses
+ <p>This function is preferred to the old <c>Module:add_host_key/3</c> since it also uses
the peer host port number and may return an error message.</p>
<p>The OTP/SSH application first calls this function in the callback module, and then
- the old <c>Module:add_host_key/3</c> for compatibilty.</p>
+ the old <c>Module:add_host_key/3</c> for compatibility.</p>
</desc>
</func>
@@ -121,7 +121,7 @@
<v>Result = boolean()</v>
</type>
<desc>
- <p>This function is retired in favour for <c>Module:is_host_key/5</c> which is the prefered API function.
+ <p>This function is retired in favour for <c>Module:is_host_key/5</c> which is the preferred API function.
The calling SSH application will still try the <c>is_host_key/4</c> if the call to <c>is_host_key/5</c> failed.
</p>
<p>Checks if a host key is trusted.</p>
@@ -155,10 +155,10 @@
</type>
<desc>
<p>Checks if a host key is trusted.</p>
- <p>This function is prefered to the old <c>Module:is_host_key/4</c> since it also uses
+ <p>This function is preferred to the old <c>Module:is_host_key/4</c> since it also uses
the peer host port number and may return an error message.</p>
<p>The OTP/SSH application first calls this function in the callback module, and then
- the old <c>Module:is_host_key/4</c> for compatibilty.</p>
+ the old <c>Module:is_host_key/4</c> for compatibility.</p>
</desc>
</func>
diff --git a/lib/ssh/doc/src/ssh_connection.xml b/lib/ssh/doc/src/ssh_connection.xml
index cd4b9c0f85..899bd0c2b7 100644
--- a/lib/ssh/doc/src/ssh_connection.xml
+++ b/lib/ssh/doc/src/ssh_connection.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2020</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -85,7 +85,7 @@
<name name="req_status"/>
<desc>
<p>The status of a request.
- Coresponds to the <c>SSH_MSG_CHANNEL_SUCCESS</c> and <c>SSH_MSG_CHANNEL_FAILURE</c> values in
+ Corresponds to the <c>SSH_MSG_CHANNEL_SUCCESS</c> and <c>SSH_MSG_CHANNEL_FAILURE</c> values in
<url href="https://tools.ietf.org/html/rfc4254#section-5.4">RFC 4254, Section 5.4</url>.
</p>
</desc>
diff --git a/lib/ssh/doc/src/ssh_file.xml b/lib/ssh/doc/src/ssh_file.xml
index e97bb5b37f..29db36481a 100644
--- a/lib/ssh/doc/src/ssh_file.xml
+++ b/lib/ssh/doc/src/ssh_file.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2018</year><year>2022</year>
+ <year>2018</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -66,7 +66,7 @@
<title>Daemons</title>
<p>Daemons uses all files stored in the <seeerl marker="#SYSDIR">SYSDIR</seeerl> directory.
</p>
- <p>Optionaly, in case of <c>publickey</c> authorization, one or more of the remote user's public keys
+ <p>Optionally, in case of <c>publickey</c> authorization, one or more of the remote user's public keys
in the <seeerl marker="#USERDIR">USERDIR</seeerl> directory are used.
See the files
<seeerl marker="#FILE-authorized_keys"><c>USERDIR/authorized_keys</c></seeerl> and
@@ -223,7 +223,7 @@ key :: % encoded key from eg ssh_host_*.pub
<datatype>
<name name="key"/>
<desc>
- <p>The key representation.</p>
+ <p>The key representation</p>
</desc>
</datatype>
@@ -232,8 +232,6 @@ key :: % encoded key from eg ssh_host_*.pub
<name name="openssh_key_v1_attributes"/>
<desc>
<p>Types for the experimental implementaition of the <c>openssh_key_v1</c> format.
- The <c>#ECPoint{}</c> and <c>ECPrivateKey{}</c> are not used for Edwards curves
- (ed25519 and ed448), but will be in next major release.
</p>
</desc>
</datatype>
@@ -262,7 +260,7 @@ key :: % encoded key from eg ssh_host_*.pub
<item><seeerl marker="#FILE-ssh_host_dsa_key"><c>SYSDIR/ssh_host_dsa_key</c></seeerl></item>
<item><seeerl marker="#FILE-ssh_host_ecdsa_key"><c>SYSDIR/ssh_host_ecdsa_key</c></seeerl></item>
<item><seeerl marker="#FILE-ssh_host_ed25519_key"><c>SYSDIR/ssh_host_ed25519_key</c></seeerl></item>
- <item><seeerl marker="#FILE-ssh_host_ed448_key"><c>SYSDIR/ssh_host_ed448_key</c>c></seeerl></item>
+ <item><seeerl marker="#FILE-ssh_host_ed448_key"><c>SYSDIR/ssh_host_ed448_key</c></seeerl></item>
</list>
</desc>
</func>
@@ -285,7 +283,7 @@ key :: % encoded key from eg ssh_host_*.pub
<item><seeerl marker="#FILE-authorized_keys"><c>USERDIR/authorized_keys</c></seeerl></item>
<item><seeerl marker="#FILE-authorized_keys2"><c>USERDIR/authorized_keys2</c></seeerl></item>
</list>
- <p>This functions discards all options in the begining of the lines of thoose files when reading them.
+ <p>This functions discards all options in the beginning of the lines of thoose files when reading them.
</p>
</desc>
</func>
@@ -375,7 +373,7 @@ key :: % encoded key from eg ssh_host_*.pub
an RFC4716 public key or an OpenSSH public key.</p>
<note>
<p>The following key types have been renamed from the deprecated
- <seemfa marker="public_key:public_key#ssh_decode/2">public_key:ssh_decode/2</seemfa>:</p>
+ <c>public_key:ssh_decode/2</c>:</p>
<list>
<item>rfc4716_public_key -> rfc4716_key</item>
<item>openssh_public_key -> openssh_key</item>
@@ -391,8 +389,7 @@ key :: % encoded key from eg ssh_host_*.pub
<desc>
<p>Encodes a list of SSH file entries (public keys and attributes) to a binary.</p>
<note>
- <p>The following key types have been renamed from the deprecated
- <seemfa marker="public_key:public_key#ssh_encode/2">public_key:ssh_encode/2</seemfa>:</p>
+ <p>The following key types have been renamed from the removed <c>public_key:ssh_encode/2</c>:</p>
<list>
<item>rfc4716_public_key -> rfc4716_key</item>
<item>openssh_public_key -> openssh_key</item>
@@ -402,6 +399,15 @@ key :: % encoded key from eg ssh_host_*.pub
</desc>
</func>
+
+ <func>
+ <name since="OTP 25.0" name="extract_public_key" arity="1"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Fetches the public key from a private key.</p>
+ </desc>
+ </func>
+
</funcs>
</erlref>
diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml
index 6e30c1e20d..c035f74b3a 100644
--- a/lib/ssh/doc/src/ssh_sftp.xml
+++ b/lib/ssh/doc/src/ssh_sftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2005</year><year>2020</year>
+ <year>2005</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -96,7 +96,7 @@
<seemfa marker="crypto:crypto#crypto_init/4">crypto:crypto_init/4</seemfa>
or similar. The <c>crypto_state()</c> is the state such a function may return.
</p>
- <p>If the selected cipher needs to have the input data partioned into
+ <p>If the selected cipher needs to have the input data partitioned into
blocks of a certain size, the <c>init_fun()</c> should return the second
form of return value with the <c>chunk_size()</c> set to the block size.
If the <c>chunk_size()</c> is <c>undefined</c>, the size of the <c>PlainBin</c>s varies,
diff --git a/lib/ssh/doc/src/ssh_timeouts.jpg b/lib/ssh/doc/src/ssh_timeouts.jpg
new file mode 100644
index 0000000000..da2f0914fc
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_timeouts.jpg
Binary files differ
diff --git a/lib/ssh/doc/src/ssh_timeouts.odp b/lib/ssh/doc/src/ssh_timeouts.odp
new file mode 100644
index 0000000000..ba2d072e9f
--- /dev/null
+++ b/lib/ssh/doc/src/ssh_timeouts.odp
Binary files differ
diff --git a/lib/ssh/doc/src/terminology.xml b/lib/ssh/doc/src/terminology.xml
index 9766276192..78a24f1618 100644
--- a/lib/ssh/doc/src/terminology.xml
+++ b/lib/ssh/doc/src/terminology.xml
@@ -44,7 +44,7 @@
cause confusion.
</p>
<p>The term is used differently in <url href="http://www.openssh.com">OpenSSH</url> and SSH in Erlang/OTP.
- The reason is the different environments and use cases that are not immediatly obvious.
+ The reason is the different environments and use cases that are not immediately obvious.
</p>
<p>This chapter aims at explaining the differences and giving a rationale for why Erlang/OTP handles "user" as
it does.
@@ -95,8 +95,8 @@
</p>
</section>
<section>
- <title>The SSH server on UNIX/Linux/etc after a succesful authentication</title>
- <p>After a succesful incoming authentication, a new process runs as the just authenticated user.</p>
+ <title>The SSH server on UNIX/Linux/etc after a successful authentication</title>
+ <p>After a successful incoming authentication, a new process runs as the just authenticated user.</p>
<p>Next step is to start a service according to the ssh request. In case of a request of a shell,
a new one is started which handles the OS-commands that arrives from the client (that's "you").
</p>
@@ -166,7 +166,7 @@
</list>
</section>
<section>
- <title>The Erlang/OTP SSH server after a succesful authentication</title>
+ <title>The Erlang/OTP SSH server after a successful authentication</title>
<p>After a successful authentication an <i>Erlang process</i> is handling the service request from the remote
ssh client. The rights of that process are those of the user of the OS process running the Erlang emulator.
</p>
diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml
index a127b66607..648b59ab23 100644
--- a/lib/ssh/doc/src/using_ssh.xml
+++ b/lib/ssh/doc/src/using_ssh.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2012</year>
- <year>2020</year>
+ <year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -201,7 +201,7 @@ ok
<p>To close the connection, call the function <seemfa marker="ssh#close/1"><c>ssh:close(ConnectionRef)</c></seemfa>.
As an alternative, set the option
<seetype marker="ssh#max_idle_time_common_option"><c>{idle_time, 1}</c></seetype>
- when opening the connection. This will cause the connection to be closed automaticaly when there are
+ when opening the connection. This will cause the connection to be closed automatically when there are
no channels open for the specified time period, in this case 1 ms.
</p>
</section>
diff --git a/lib/ssh/examples/Makefile b/lib/ssh/examples/Makefile
index d7d47eb3ae..1b05d65cb5 100644
--- a/lib/ssh/examples/Makefile
+++ b/lib/ssh/examples/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2015. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ EBIN = .
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
debug: ERLC_FLAGS += -Ddebug
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index cc3cfe9e96..2fcb164301 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -159,7 +159,7 @@ $(DEP_FILE): $(ERL_FILES)
| sed 's@^sshd_@$$(EBIN)/sshd_@' \
> $(DEP_FILE)
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(DEP_FILE)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(DEP_FILE)
clean:
rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(BEHAVIOUR_TARGET_FILES)
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index c7ad417bef..2cb8d80488 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -59,8 +59,8 @@
{mod, {ssh_app, []}},
{runtime_dependencies, [
"crypto-5.0",
- "erts-9.0",
- "kernel-5.3",
+ "erts-11.0",
+ "kernel-6.0",
"public_key-1.6.1",
"stdlib-3.15",
"runtime_tools-1.15.1"
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index f655f0db45..f856d3d887 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
channel_info/3,
daemon/1, daemon/2, daemon/3,
daemon_info/1, daemon_info/2,
+ daemon_replace_options/2,
set_sock_opts/2, get_sock_opts/2,
default_algorithms/0,
chk_algos_opts/1,
@@ -108,7 +109,7 @@ start(Type) ->
{ok, _} ->
%% Clear cached default_algorithms (if exists) ...
ssh_transport:clear_default_algorithms_env(),
- %% ... and rebuld them taking configure options in account
+ %% ... and rebuild them taking configure options in account
ssh_transport:default_algorithms(),
ok;
Other ->
@@ -443,6 +444,17 @@ daemon(_, _, _) ->
{error, badarg}.
%%--------------------------------------------------------------------
+-spec daemon_replace_options(DaemonRef, NewUserOptions) -> {ok,daemon_ref()}
+ | {error,term()} when
+ DaemonRef :: daemon_ref(),
+ NewUserOptions :: daemon_options().
+
+daemon_replace_options(DaemonRef, NewUserOptions) ->
+ {ok,Os0} = ssh_system_sup:get_acceptor_options(DaemonRef),
+ Os1 = ssh_options:merge_options(server, NewUserOptions, Os0),
+ ssh_system_sup:replace_acceptor_options(DaemonRef, Os1).
+
+%%--------------------------------------------------------------------
-type daemon_info_tuple() ::
{port, inet:port_number()}
| {ip, inet:ip_address()}
@@ -836,7 +848,7 @@ fp_fmt(b64, Bin) ->
%% [C || C<-base64:encode_to_string(Bin), C =/= $=]
%% but I am not sure. Must be checked.
B64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
- BitsInLast = 8*size(Bin) rem 6,
+ BitsInLast = 8*byte_size(Bin) rem 6,
Padding = (6-BitsInLast) rem 6, % Want BitsInLast = [1:5] to map to padding [5:1] and 0 -> 0
[lists:nth(C+1,B64Chars) || <<C:6>> <= <<Bin/binary,0:Padding>> ].
@@ -931,10 +943,10 @@ is_host(X, Opts) ->
is_host1(L) when is_list(L) -> true; %% "string()"
-is_host1(T) when is_tuple(T), size(T)==4 -> lists:all(fun(I) -> 0=<I andalso I=<255 end,
- tuple_to_list(T));
-is_host1(T) when is_tuple(T), size(T)==16 -> lists:all(fun(I) -> 0=<I andalso I=<65535 end,
- tuple_to_list(T));
+is_host1(T) when tuple_size(T)==4 -> lists:all(fun(I) -> 0=<I andalso I=<255 end,
+ tuple_to_list(T));
+is_host1(T) when tuple_size(T)==16 -> lists:all(fun(I) -> 0=<I andalso I=<65535 end,
+ tuple_to_list(T));
is_host1(loopback) -> true.
%%%----------------------------------------------------------------
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 2f6e961457..aecce6c1ef 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@
-define(UINT16(X), (X):16/unsigned-big-integer).
-define(UINT32(X), (X):32/unsigned-big-integer).
-define(UINT64(X), (X):64/unsigned-big-integer).
--define(STRING(X), ?UINT32((size(X))), (X)/binary).
+-define(STRING(X), ?UINT32((byte_size(X))), (X)/binary).
-define(DEC_BIN(X,Len), ?UINT32(Len), X:Len/binary ).
-define(DEC_INT(I,Len), ?UINT32(Len), I:Len/big-signed-integer-unit:8 ).
@@ -209,6 +209,7 @@
ssh_file:user_dir_common_option()
| profile_common_option()
| max_idle_time_common_option()
+ | max_log_item_len_common_option()
| key_cb_common_option()
| disconnectfun_common_option()
| unexpectedfun_common_option()
@@ -230,6 +231,7 @@
-type rekey_limit_common_option() :: {rekey_limit, Bytes::limit_bytes() |
{Minutes::limit_time(), Bytes::limit_bytes()}
}.
+-type max_log_item_len_common_option() :: {max_log_item_len, limit_bytes()} .
-type limit_bytes() :: non_neg_integer() | infinity . % non_neg_integer due to compatibility
-type limit_time() :: pos_integer() | infinity .
@@ -320,6 +322,7 @@
| tcpip_tunnel_in_daemon_option()
| authentication_daemon_options()
| diffie_hellman_group_exchange_daemon_option()
+ | max_initial_idle_time_daemon_option()
| negotiation_timeout_daemon_option()
| hello_timeout_daemon_option()
| hardening_daemon_options()
@@ -360,7 +363,9 @@
| {user_passwords, [{UserName::string(),Pwd::string()}]}
| {pk_check_user, boolean()}
| {password, string()}
- | {pwdfun, pwdfun_2() | pwdfun_4()} .
+ | {pwdfun, pwdfun_2() | pwdfun_4()}
+ | {no_auth_needed, boolean()}
+ .
-type prompt_texts() ::
kb_int_tuple()
@@ -388,6 +393,7 @@
-type explicit_group_file() :: {file,string()} .
-type ssh_moduli_file() :: {ssh_moduli_file,string()}.
+-type max_initial_idle_time_daemon_option() :: {max_initial_idle_time, timeout()} .
-type negotiation_timeout_daemon_option() :: {negotiation_timeout, timeout()} .
-type hello_timeout_daemon_option() :: {hello_timeout, timeout()} .
diff --git a/lib/ssh/src/ssh_agent.erl b/lib/ssh/src/ssh_agent.erl
index ffb46df4ea..25e6beed0e 100644
--- a/lib/ssh/src/ssh_agent.erl
+++ b/lib/ssh/src/ssh_agent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -173,7 +173,7 @@ send(Request, Opts) ->
%% Message packing
pack(Data) ->
- <<(size(Data)):32/unsigned-big-integer, Data/binary>>.
+ <<(byte_size(Data)):32/unsigned-big-integer, Data/binary>>.
%% SSH Agent message encoding
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 818489c1d0..efd1bbbabd 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -149,7 +149,7 @@ get_public_key(SigAlg, #ssh{opts = Opts}) ->
try
%% Check the key - the KeyCb may be a buggy plugin
true = ssh_transport:valid_key_sha_alg(private, PrivKey, KeyAlg),
- Key = ssh_transport:extract_public_key(PrivKey),
+ Key = ssh_file:extract_public_key(PrivKey),
ssh_message:ssh2_pubkey_encode(Key)
of
PubKeyBlob -> {ok, {PrivKey, PubKeyBlob}}
@@ -272,11 +272,21 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
method = "none"}, _,
- #ssh{userauth_supported_methods = Methods} = Ssh) ->
- {not_authorized, {User, undefined},
- {#ssh_msg_userauth_failure{authentications = Methods,
- partial_success = false}, Ssh}
- };
+ #ssh{userauth_supported_methods = Methods,
+ opts = Opts} = Ssh) ->
+ case ?GET_OPT(no_auth_needed, Opts) of
+ false ->
+ %% The normal case
+ {not_authorized, {User, undefined},
+ {#ssh_msg_userauth_failure{authentications = Methods,
+ partial_success = false}, Ssh}
+ };
+ true ->
+ %% RFC 4252 5.2
+ {authorized, User,
+ {#ssh_msg_userauth_success{}, Ssh}
+ }
+ end;
handle_userauth_request(#ssh_msg_userauth_request{user = User,
service = "ssh-connection",
diff --git a/lib/ssh/src/ssh_auth.hrl b/lib/ssh/src/ssh_auth.hrl
index 56314ca6d9..842beb5186 100644
--- a/lib/ssh/src/ssh_auth.hrl
+++ b/lib/ssh/src/ssh_auth.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
-record(ssh_msg_userauth_passwd_changereq,
{
prompt, %% string
- languge %% string
+ language %% string
}).
-record(ssh_msg_userauth_pk_ok,
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 3ce7758447..882154c006 100644
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,20 +40,20 @@ mpint(I) when I>0 ->
<<B1,V/binary>> = binary:encode_unsigned(I),
case B1 band 16#80 of
16#80 ->
- <<(size(V)+2):32/unsigned-big-integer, 0,B1,V/binary >>;
+ <<(byte_size(V)+2):32/unsigned-big-integer, 0,B1,V/binary >>;
_ ->
- <<(size(V)+1):32/unsigned-big-integer, B1,V/binary >>
+ <<(byte_size(V)+1):32/unsigned-big-integer, B1,V/binary >>
end;
mpint(N) when N<0 ->
- Sxn = 8*size(binary:encode_unsigned(-N)),
+ Sxn = bit_size(binary:encode_unsigned(-N)),
Sxn1 = Sxn+8,
<<W:Sxn1>> = <<1, 0:Sxn>>,
<<B1,V/binary>> = binary:encode_unsigned(W+N),
case B1 band 16#80 of
16#80 ->
- <<(size(V)+1):32/unsigned-big-integer, B1,V/binary >>;
+ <<(byte_size(V)+1):32/unsigned-big-integer, B1,V/binary >>;
_ ->
- <<(size(V)+2):32/unsigned-big-integer, 255,B1,V/binary >>
+ <<(byte_size(V)+2):32/unsigned-big-integer, 255,B1,V/binary >>
end.
%%%----------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_client_channel.erl b/lib/ssh/src/ssh_client_channel.erl
index 7132e32fe5..6b6623945f 100644
--- a/lib/ssh/src/ssh_client_channel.erl
+++ b/lib/ssh/src/ssh_client_channel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -261,10 +261,9 @@ handle_info({ssh_cm, ConnectionManager, {closed, ChannelId}},
(catch ssh_connection:close(ConnectionManager, ChannelId)),
{stop, normal, State#state{close_sent = true}};
-handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
- channel_cb = Module,
- channel_state = ChannelState0} = State) ->
- case Module:handle_ssh_msg(Msg, ChannelState0) of
+handle_info({ssh_cm, _, _} = Msg, #state{channel_cb = Module,
+ channel_state = ChannelState0} = State) ->
+ try Module:handle_ssh_msg(Msg, ChannelState0) of
{ok, ChannelState} ->
adjust_window(Msg),
{noreply, State#state{channel_state = ChannelState}};
@@ -272,9 +271,10 @@ handle_info({ssh_cm, _, _} = Msg, #state{cm = ConnectionManager,
adjust_window(Msg),
{noreply, State#state{channel_state = ChannelState}, Timeout};
{stop, ChannelId, ChannelState} ->
- catch ssh_connection:close(ConnectionManager, ChannelId),
- {stop, normal, State#state{close_sent = true,
- channel_state = ChannelState}}
+ do_the_close(Msg, ChannelId, State#state{channel_state = ChannelState})
+ catch
+ error:_ ->
+ do_the_close(Msg, State#state.channel_id, State)
end;
handle_info(Msg, #state{channel_cb = Module,
@@ -288,7 +288,7 @@ handle_info(Msg, #state{channel_cb = Module,
{stop, ChannelId, ChannelState} ->
do_the_close(Msg, ChannelId, State#state{channel_state = ChannelState})
catch
- error:function_clause when size(Msg) == 3,
+ error:function_clause when tuple_size(Msg) == 3,
element(1,Msg) == 'EXIT' ->
do_the_close(Msg, State#state.channel_id, State)
end.
@@ -390,7 +390,7 @@ handle_cb_result({stop, Reason, ChannelState}, State) ->
adjust_window({ssh_cm, ConnectionManager,
{data, ChannelId, _, Data}}) ->
- ssh_connection:adjust_window(ConnectionManager, ChannelId, size(Data));
+ ssh_connection:adjust_window(ConnectionManager, ChannelId, byte_size(Data));
adjust_window(_) ->
ok.
diff --git a/lib/ssh/src/ssh_client_key_api.erl b/lib/ssh/src/ssh_client_key_api.erl
index 367d78bf22..1cc153904f 100644
--- a/lib/ssh/src/ssh_client_key_api.erl
+++ b/lib/ssh/src/ssh_client_key_api.erl
@@ -82,7 +82,7 @@
%%% in the argument Host with the port Port.
%%%
%%% Due to compatibility reasons, the OTP/SSH application first
-%%% trys add_host_key/4 and then the old add_host_key/3
+%%% tries add_host_key/4 and then the old add_host_key/3
-callback add_host_key(Host :: inet:ip_address() | inet:hostname()
| [inet:ip_address() | inet:hostname()],
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl
index f504cd5813..34e97ba6ca 100644
--- a/lib/ssh/src/ssh_connection.erl
+++ b/lib/ssh/src/ssh_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -177,7 +177,7 @@
Command :: string()
} .
-%%% This function is soley to convince all
+%%% This function is solely to convince all
%%% checks that the type event() exists...
-export([dummy/1]).
-spec dummy(event()) -> false.
@@ -404,7 +404,7 @@ ptty_alloc(ConnectionHandler, Channel, Options0, TimeOut) ->
).
%%--------------------------------------------------------------------
-%% Not yet officialy supported! The following functions are part of the
+%% Not yet officially supported! The following functions are part of the
%% initial contributed ssh application. They are untested. Do we want them?
%% Should they be documented and tested?
%%--------------------------------------------------------------------
@@ -1200,7 +1200,7 @@ get_window(#channel{send_buf = Buffer,
} = Channel, Acc0) ->
case queue:out(Buffer) of
{{value, {_, Data} = Msg}, NewBuffer} ->
- case handle_send_window(Msg, size(Data), PacketSize, WindowSize0, Acc0) of
+ case handle_send_window(Msg, byte_size(Data), PacketSize, WindowSize0, Acc0) of
{WindowSize, Acc, {_, <<>>}} ->
{lists:reverse(Acc), Channel#channel{send_window_size = WindowSize,
send_buf = NewBuffer}};
@@ -1520,7 +1520,7 @@ handle_cli_msg(C0, ChId, Reply0) ->
channel_data_reply_msg(ChannelId, Connection, DataType, Data) ->
case ssh_client_channel:cache_lookup(Connection#connection.channel_cache, ChannelId) of
#channel{recv_window_size = Size} = Channel ->
- WantedSize = Size - size(Data),
+ WantedSize = Size - byte_size(Data),
ssh_client_channel:cache_update(Connection#connection.channel_cache,
Channel#channel{recv_window_size = WantedSize}),
reply_msg(Channel, Connection, {data, ChannelId, DataType, Data});
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index b2545c4db4..4ef45516ca 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -421,11 +421,11 @@ init([Role, Socket, Opts]) when Role==client ; Role==server ->
end;
{error,Error} ->
- {stop, {error,Error}}
+ {stop, {shutdown,Error}}
end.
%%%----------------------------------------------------------------
-%%% Connection start and initalization helpers
+%%% Connection start and initialization helpers
init_connection_record(Role, Socket, Opts) ->
{WinSz, PktSz} = init_inet_buffers_window(Socket),
@@ -625,7 +625,7 @@ handle_event(internal, {version_exchange,Version}, {hello,Role}, D0) ->
{NumVsn, StrVsn} = ssh_transport:handle_hello_version(Version),
case handle_version(NumVsn, StrVsn, D0#data.ssh_params) of
{ok, Ssh1} ->
- %% Since the hello part is finnished correctly, we set the
+ %% Since the hello part is finished correctly, we set the
%% socket to the packet handling mode (including recbuf size):
inet:setopts(D0#data.socket, [{packet,0},
{mode,binary},
@@ -651,7 +651,7 @@ handle_event(state_timeout, no_hello_received, {hello,_Role}=StateName, D0 = #da
Time = ?GET_OPT(hello_timeout, Ssh0#ssh.opts),
{Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- lists:concat(["No HELLO recieved within ",ssh_lib:format_time_ms(Time)]),
+ lists:concat(["No HELLO received within ",ssh_lib:format_time_ms(Time)]),
StateName, D0),
{stop, Shutdown, D};
@@ -939,7 +939,7 @@ handle_event({call,From}, {request, ChannelPid, ChannelId, Type, Data, Timeout},
{error,Error} ->
{keep_state, D0, {reply,From,{error,Error}}};
D ->
- %% Note reply to channel will happen later when reply is recived from peer on the socket
+ %% Note reply to channel will happen later when reply is received from peer on the socket
start_channel_request_timer(ChannelId, From, Timeout),
{keep_state, D, cond_set_idle_timer(D)}
end;
@@ -950,7 +950,7 @@ handle_event({call,From}, {request, ChannelId, Type, Data, Timeout}, StateName,
{error,Error} ->
{keep_state, D0, {reply,From,{error,Error}}};
D ->
- %% Note reply to channel will happen later when reply is recived from peer on the socket
+ %% Note reply to channel will happen later when reply is received from peer on the socket
start_channel_request_timer(ChannelId, From, Timeout),
{keep_state, D, cond_set_idle_timer(D)}
end;
@@ -1091,8 +1091,10 @@ handle_event(info, {Proto, Sock, Info}, {hello,_}, #data{socket = Sock,
end;
-handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
- transport_protocol = Proto}) ->
+handle_event(info, {Proto, Sock, NewData}, StateName,
+ D0 = #data{socket = Sock,
+ transport_protocol = Proto,
+ ssh_params = SshParams}) ->
try ssh_transport:handle_packet_part(
D0#data.decrypted_data_buffer,
<<(D0#data.encrypted_data_buffer)/binary, NewData/binary>>,
@@ -1118,7 +1120,10 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
#ssh_msg_global_request{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
#ssh_msg_request_success{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
#ssh_msg_request_failure{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
- #ssh_msg_channel_open{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
+ #ssh_msg_channel_open{} = Msg -> {keep_state, D1,
+ [{{timeout, max_initial_idle_time}, cancel} |
+ ?CONNECTION_MSG(Msg)
+ ]};
#ssh_msg_channel_open_confirmation{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
#ssh_msg_channel_open_failure{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
#ssh_msg_channel_window_adjust{} = Msg -> {keep_state, D1, ?CONNECTION_MSG(Msg)};
@@ -1136,10 +1141,11 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
]}
catch
C:E:ST ->
- {Shutdown, D} =
+ MaxLogItemLen = ?GET_OPT(max_log_item_len,SshParams#ssh.opts),
+ {Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~p",
- [C,E,ST]),
+ io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~P",
+ [C,E,ST,MaxLogItemLen]),
StateName, D1),
{stop, Shutdown, D}
end;
@@ -1170,9 +1176,11 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
{stop, Shutdown, D}
catch
C:E:ST ->
- {Shutdown, D} =
+ MaxLogItemLen = ?GET_OPT(max_log_item_len,SshParams#ssh.opts),
+ {Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~p",[C,E,ST]),
+ io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~P",
+ [C,E,ST,MaxLogItemLen]),
StateName, D0),
{stop, Shutdown, D}
end;
@@ -1181,7 +1189,7 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
%%%====
handle_event(internal, prepare_next_packet, _StateName, D) ->
Enough = erlang:max(8, D#data.ssh_params#ssh.decrypt_block_size),
- case size(D#data.encrypted_data_buffer) of
+ case byte_size(D#data.encrypted_data_buffer) of
Sz when Sz >= Enough ->
self() ! {D#data.transport_protocol, D#data.socket, <<>>};
_ ->
@@ -1232,6 +1240,9 @@ handle_event({timeout,idle_time}, _Data, _StateName, D) ->
keep_state_and_data
end;
+handle_event({timeout,max_initial_idle_time}, _Data, _StateName, _D) ->
+ {stop, {shutdown, "Timeout"}};
+
%%% So that terminate will be run when supervisor is shutdown
handle_event(info, {'EXIT', _Sup, Reason}, StateName, _D) ->
Role = ?role(StateName),
@@ -1242,7 +1253,7 @@ handle_event(info, {'EXIT', _Sup, Reason}, StateName, _D) ->
{stop, {shutdown, Reason}};
Reason == normal ->
- %% An exit normal should not cause a server to crash. This has happend...
+ %% An exit normal should not cause a server to crash. This has happened...
keep_state_and_data;
true ->
@@ -1583,7 +1594,7 @@ handle_ssh_msg_ext_info(#ssh_msg_ext_info{data=Data}, D0) ->
ext_info({"server-sig-algs",SigAlgsStr},
D0 = #data{ssh_params=#ssh{role=client,
userauth_pubkeys=ClientSigAlgs}=Ssh0}) ->
- %% ClientSigAlgs are the pub_key algortithms that:
+ %% ClientSigAlgs are the pub_key algorithms that:
%% 1) is usable, that is, the user has such a public key and
%% 2) is either the default list or set by the caller
%% with the client option 'pref_public_key_algs'
@@ -1867,13 +1878,9 @@ log(Tag, D, Reason) ->
end.
-do_log(F, Reason0, #data{ssh_params = S}) ->
- Reason =
- try io_lib:format("~s",[Reason0])
- of _ -> Reason0
- catch
- _:_ -> io_lib:format("~p",[Reason0])
- end,
+do_log(F, Reason0, #data{ssh_params=S}) ->
+ Reason1 = string:chomp(assure_string(Reason0)),
+ Reason = limit_size(Reason1, ?GET_OPT(max_log_item_len,S#ssh.opts)),
case S of
#ssh{role = Role} when Role==server ;
Role==client ->
@@ -1899,6 +1906,29 @@ do_log(F, Reason0, #data{ssh_params = S}) ->
Reason])
end.
+assure_string(S) ->
+ try io_lib:format("~s",[S])
+ of Formatted -> Formatted
+ catch
+ _:_ -> io_lib:format("~p",[S])
+ end.
+
+limit_size(S, MaxLen) when is_integer(MaxLen) ->
+ limit_size(S, lists:flatlength(S), MaxLen);
+limit_size(S, _) ->
+ S.
+
+limit_size(S, Len, MaxLen) when Len =< MaxLen ->
+ S;
+limit_size(S, Len, MaxLen) when Len =< (MaxLen + 5) ->
+ %% Looks silly with e.g "... (2 bytes skipped)"
+ S;
+limit_size(S, Len, MaxLen) when Len > MaxLen ->
+ %% Cut
+ io_lib:format("~s ... (~w bytes skipped)",
+ [string:substr(lists:flatten(S), 1, MaxLen),
+ Len-MaxLen]).
+
crypto_log_info() ->
try
[{_,_,CI}] = crypto:info_lib(),
@@ -2058,7 +2088,7 @@ ssh_dbg_off(disconnect) -> dbg:ctpl(?MODULE, send_disconnect, 7);
ssh_dbg_off(terminate) -> dbg:ctpg(?MODULE, terminate, 3);
ssh_dbg_off(tcp) -> dbg:ctpg(?MODULE, handle_event, 4), % How to avoid cancelling 'connection_events' ?
dbg:ctpl(?MODULE, send_bytes, 2),
- dbg:ctpg(?MODULE, close_transport, 1);
+ dbg:ctpl(?MODULE, close_transport, 1);
ssh_dbg_off(renegotiation) -> dbg:ctpl(?MODULE, init_renegotiate_timers, 3),
dbg:ctpl(?MODULE, pause_renegotiate_timers, 3),
dbg:ctpl(?MODULE, check_data_rekeying_dbg, 2),
diff --git a/lib/ssh/src/ssh_daemon_channel.erl b/lib/ssh/src/ssh_daemon_channel.erl
index 30c4773a7a..899c99d610 100644
--- a/lib/ssh/src/ssh_daemon_channel.erl
+++ b/lib/ssh/src/ssh_daemon_channel.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
-module(ssh_daemon_channel).
-%% API to server side channel that can be pluged into the erlang ssh daemeon
+%% API to server side channel that can be plugged into the erlang ssh daemeon
-callback init(Args :: term()) ->
{ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
{stop, Reason :: term()} | ignore.
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index 54a88a479f..85b3399295 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -156,26 +156,26 @@ go_on() ->
on(IsOn).
%%%----------------------------------------------------------------
-shrink_bin(B) when is_binary(B), size(B)>256 -> {'*** SHRINKED BIN',
- size(B),
- element(1,split_binary(B,64)),
- '...',
- element(2,split_binary(B,size(B)-64))
- };
+shrink_bin(B) when is_binary(B), byte_size(B)>256 -> {'*** SHRUNK BIN',
+ byte_size(B),
+ element(1,split_binary(B,64)),
+ '...',
+ element(2,split_binary(B,byte_size(B)-64))
+ };
shrink_bin(L) when is_list(L) -> lists:map(fun shrink_bin/1, L);
shrink_bin(T) when is_tuple(T) -> list_to_tuple(shrink_bin(tuple_to_list(T)));
shrink_bin(X) -> X.
%%%----------------------------------------------------------------
-%% Replace any occurence of {Name,...}, with "#Name{}"
+%% Replace any occurrence of {Name,...}, with "#Name{}"
reduce_state(T, RecordExample) ->
Name = element(1, RecordExample),
- Arity = size(RecordExample),
+ Arity = tuple_size(RecordExample),
reduce_state(T, Name, Arity).
-%% Replace any occurence of {Name,...}, with "#Name{}"
+%% Replace any occurrence of {Name,...}, with "#Name{}"
reduce_state(T, Name, Arity) when element(1,T) == Name,
- size(T) == Arity ->
+ tuple_size(T) == Arity ->
lists:concat(['#',Name,'{}']);
reduce_state(L, Name, Arity) when is_list(L) ->
[reduce_state(E,Name,Arity) || E <- L];
@@ -353,7 +353,7 @@ trace_pid(T) when element(1,T)==trace
%% Pick last element, the Time Stamp, and format it
trace_ts(T) when element(1,T)==trace_ts ->
- ts( element(size(T), T) ).
+ ts( element(tuple_size(T), T) ).
%% Make a tuple of all elements but the 1st, 2nd and last
trace_info(T) ->
@@ -400,7 +400,7 @@ try_all_types_in_all_modules(TypesOn, Arg, WriteFun, Acc0) ->
catch
_:_ ->
%% and finally, signal for special formatting
- %% if noone else formats it
+ %% if no one else formats it
Acc
end
end
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 5a1b4def87..c44b649e87 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,6 +51,7 @@
%%%--------------------- utility exports ---------------------------
-export([decode/2, encode/2]).
+-export([extract_public_key/1]).
-define(ENCODED_LINE_LENGTH, 68).
@@ -66,10 +67,7 @@
-type optimize_key_lookup() :: {optimize, time|space} .
-type key() :: public_key:public_key() | public_key:private_key() .
--type experimental_openssh_key_v1() :: [{key()
- | {ed_pri, ed25519|ed448, Pub::binary(), Priv::binary()}
- | {ed_pub, ed25519|ed448, Key::binary()},
- openssh_key_v1_attributes()}].
+-type experimental_openssh_key_v1() :: [{key(), openssh_key_v1_attributes()}].
-type openssh_key_v1_attributes() :: [{atom(),term()}].
%%%================================================================
@@ -291,7 +289,7 @@ decode(Bin, auth_keys) when is_binary(Bin) ->
[ [[] | binary:split(L,<<" ">>,[global,trim_all])] ];
{Pos,Len} when is_integer(Pos), is_integer(Len) ->
[ [binary:split(binary:part(L,0,Pos-1), <<",">>,[global,trim_all]) |
- binary:split(binary:part(L,Pos,size(L)-Pos), <<" ">>, [global,trim_all])]
+ binary:split(binary:part(L,Pos,byte_size(L)-Pos), <<" ">>, [global,trim_all])]
]
end
];
@@ -386,6 +384,40 @@ encode(KeyAttrs, Type) when Type == known_hosts;
encode(_KeyBin, _Type) ->
error(badarg).
+%%%----------------------------------------------------------------
+
+-spec extract_public_key(PrivKey) -> PubKey
+ when PrivKey :: public_key:private_key(),
+ PubKey :: public_key:public_key().
+
+extract_public_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) ->
+ #'RSAPublicKey'{modulus = N, publicExponent = E};
+extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) ->
+ {Y, #'Dss-Parms'{p=P, q=Q, g=G}};
+extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID},
+ publicKey = Pub0, privateKey = Priv}) when
+ OID == ?'id-Ed25519' orelse
+ OID == ?'id-Ed448' ->
+ case {pubkey_cert_records:namedCurves(OID), Pub0} of
+ {Alg, asn1_NOVALUE} ->
+ %% If we're missing the public key, we can create it with
+ %% the private key.
+ {Pub, Priv} = crypto:generate_key(eddsa, Alg, Priv),
+ {#'ECPoint'{point=Pub}, {namedCurve,OID}};
+ {_Alg, Pub} ->
+ {#'ECPoint'{point=Pub}, {namedCurve,OID}}
+ end;
+extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID},
+ publicKey = Q}) when is_tuple(OID) ->
+ {#'ECPoint'{point=Q}, {namedCurve,OID}};
+extract_public_key(#{engine:=_, key_id:=_, algorithm:=Alg} = M) ->
+ case {Alg, crypto:privkey_to_pubkey(Alg, M)} of
+ {rsa, [E,N]} ->
+ #'RSAPublicKey'{modulus = N, publicExponent = E};
+ {dss, [P,Q,G,Y]} ->
+ {Y, #'Dss-Parms'{p=P, q=Q, g=G}}
+ end.
+
%%%================================================================
%%%
%%% Local functions
@@ -604,7 +636,7 @@ find_host_key(_, _, _, []) ->
revoked_key(Hosts, KeyType, EncKey, [<<"@revoked ",RestLine/binary>> | Lines]) ->
case binary:split(RestLine, <<" ">>, [global,trim_all]) of
[Patterns, KeyType, EncKey|_Comment] ->
- %% Very likeley to be a revoked key,
+ %% Very likely to be a revoked key,
%% but does any of the hosts match the pattern?
case host_match(Hosts, Patterns) of
true ->
@@ -698,12 +730,12 @@ pos_match(H, P) ->
{[Hh], [Ph,<<"*">>]} ->
%% host [host]:*
- Sz = size(Hh),
+ Sz = byte_size(Hh),
Ph == <<"[", Hh:Sz/binary, "]">>;
{[Hh], [Ph,<<"22">>]} ->
%% host [host]:22
- Sz = size(Hh),
+ Sz = byte_size(Hh),
Ph == <<"[", Hh:Sz/binary, "]">>;
_ ->
@@ -1020,6 +1052,7 @@ asn1_type(<<"RSA PUBLIC">>) -> 'RSAPublicKey';
asn1_type(<<"DSA PRIVATE">>) -> 'DSAPrivateKey';
asn1_type(<<"EC PRIVATE">>) -> 'ECPrivateKey';
asn1_type(<<"OPENSSH PRIVATE">>) -> 'openssh-key-v1';
+asn1_type(<<"PRIVATE">>) -> 'PrivateKeyInfo';
asn1_type(_) -> undefined.
%%%================================================================
@@ -1101,7 +1134,7 @@ check_padding(Bin, BlockSize) ->
end.
%%%----------------------------------------------------------------
-%% KeyPairs :: [ {Pub,Priv,Comment} | {ed_pri{_,_,_},Comment} ]
+%% KeyPairs :: [ {Pub,Priv,Comment} ]
openssh_key_v1_encode(KeyPairs) ->
CipherName = <<"none">>,
BlockSize = ?NON_CRYPT_BLOCKSIZE, % Cipher dependent
@@ -1113,7 +1146,7 @@ openssh_key_v1_encode(KeyPairs) ->
CheckInt/binary,
(openssh_key_v1_encode_priv_keys_cmnts(KeyPairs))/binary>>,
UnEncrypted = <<UnEncrypted0/binary,
- (pad(size(UnEncrypted0), BlockSize))/binary>>,
+ (pad(byte_size(UnEncrypted0), BlockSize))/binary>>,
Encrypted = encrypt_openssh_key_v1(UnEncrypted, KdfName, KdfOptions, CipherName, ignore),
<<"openssh-key-v1",0,
?STRING(CipherName),
@@ -1127,8 +1160,9 @@ openssh_key_v1_encode(KeyPairs) ->
openssh_key_v1_encode_pub_keys(KeyPairs) ->
openssh_key_v1_encode_pub_keys(KeyPairs, []).
-openssh_key_v1_encode_pub_keys([{{ed_pri,Alg,PubKey,_},_C}|Ks], Acc) ->
- Bk = ssh_message:ssh2_pubkey_encode({ed_pub,Alg,PubKey}),
+openssh_key_v1_encode_pub_keys([{Priv = #'ECPrivateKey'{}, _Cmnt} | Ks], Acc) ->
+ Pub = extract_public_key(Priv),
+ Bk = ssh_message:ssh2_pubkey_encode(Pub),
openssh_key_v1_encode_pub_keys(Ks, [<<?STRING(Bk)>>|Acc]);
openssh_key_v1_encode_pub_keys([{K,_,_C}|Ks], Acc) ->
Bk = ssh_message:ssh2_pubkey_encode(K),
@@ -1136,11 +1170,12 @@ openssh_key_v1_encode_pub_keys([{K,_,_C}|Ks], Acc) ->
openssh_key_v1_encode_pub_keys([], Acc) ->
list_to_binary(lists:reverse(Acc)).
+
%%%----
openssh_key_v1_encode_priv_keys_cmnts(KeyPairs) ->
openssh_key_v1_encode_priv_keys_cmnts(KeyPairs, []).
-openssh_key_v1_encode_priv_keys_cmnts([{K={ed_pri,_,_,_},C} | Ks], Acc) ->
+openssh_key_v1_encode_priv_keys_cmnts([{K = #'ECPrivateKey'{}, C} | Ks], Acc) ->
Bk = ssh_message:ssh2_privkey_encode(K),
openssh_key_v1_encode_priv_keys_cmnts(Ks, [<<Bk/binary,?STRING(C)>>|Acc]);
openssh_key_v1_encode_priv_keys_cmnts([{_,K,C}|Ks], Acc) ->
diff --git a/lib/ssh/src/ssh_fsm_userauth_client.erl b/lib/ssh/src/ssh_fsm_userauth_client.erl
index e24e0e2f9a..73c8446639 100644
--- a/lib/ssh/src/ssh_fsm_userauth_client.erl
+++ b/lib/ssh/src/ssh_fsm_userauth_client.erl
@@ -55,13 +55,13 @@ callback_mode() ->
%%% ######## {userauth, client} ####
-%%---- #ssh_msg_ext_info could follow after the key exchange, both the intial and the re-negotiation
+%%---- #ssh_msg_ext_info could follow after the key exchange, both the initial and the re-negotiation
handle_event(internal, #ssh_msg_ext_info{}=Msg, {userauth,client}, D0) ->
%% FIXME: need new state to receive this msg!
D = ssh_connection_handler:handle_ssh_msg_ext_info(Msg, D0),
{keep_state, D};
-%%---- recevied userauth success from the server
+%%---- received userauth success from the server
handle_event(internal, #ssh_msg_userauth_success{}, {userauth,client}, D0=#data{ssh_params = Ssh}) ->
ssh_auth:ssh_msg_userauth_result(success),
ssh_connection_handler:handshake(ssh_connected, D0),
@@ -80,7 +80,7 @@ handle_event(internal, #ssh_msg_userauth_failure{}, {userauth,client}=StateName,
handle_event(internal, #ssh_msg_userauth_failure{authentications = Methods}, StateName={userauth,client},
D0 = #data{ssh_params = Ssh0}) ->
- %% The prefered authentication method failed, try next method
+ %% The preferred authentication method failed, try next method
Ssh1 = case Ssh0#ssh.userauth_methods of
none ->
%% Server tells us which authentication methods that are allowed
diff --git a/lib/ssh/src/ssh_fsm_userauth_server.erl b/lib/ssh/src/ssh_fsm_userauth_server.erl
index 77657b4d82..fc1750ce2c 100644
--- a/lib/ssh/src/ssh_fsm_userauth_server.erl
+++ b/lib/ssh/src/ssh_fsm_userauth_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,10 +64,20 @@ handle_event(internal,
case {ServiceName, Ssh0#ssh.service, Method} of
{"ssh-connection", "ssh-connection", "none"} ->
%% Probably the very first userauth_request but we deny unauthorized login
- {not_authorized, _, {Reply,Ssh}} =
- ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0),
- D = ssh_connection_handler:send_msg(Reply, D0#data{ssh_params = Ssh}),
- {keep_state, D};
+ %% However, we *may* accept unauthorized login if instructed so
+ case ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0) of
+ {not_authorized, _, {Reply,Ssh}} ->
+ D = ssh_connection_handler:send_msg(Reply, D0#data{ssh_params = Ssh}),
+ {keep_state, D};
+ {authorized, User, {Reply, Ssh1}} ->
+ D = connected_state(Reply, Ssh1, User, Method, D0),
+ {next_state, {connected,server}, D,
+ [set_max_initial_idle_timeout(D),
+ {change_callback_module,ssh_connection_handler}
+ ]
+ }
+
+ end;
{"ssh-connection", "ssh-connection", Method} ->
%% Userauth request with a method like "password" or so
@@ -77,7 +87,10 @@ handle_event(internal,
case ssh_auth:handle_userauth_request(Msg, Ssh0#ssh.session_id, Ssh0) of
{authorized, User, {Reply, Ssh1}} ->
D = connected_state(Reply, Ssh1, User, Method, D0),
- {next_state, {connected,server}, D, {change_callback_module,ssh_connection_handler}};
+ {next_state, {connected,server}, D,
+ [set_max_initial_idle_timeout(D),
+ {change_callback_module,ssh_connection_handler}
+ ]};
{not_authorized, {User, Reason}, {Reply, Ssh}} when Method == "keyboard-interactive" ->
retry_fun(User, Reason, D0),
D = ssh_connection_handler:send_msg(Reply, D0#data{ssh_params = Ssh}),
@@ -110,7 +123,10 @@ handle_event(internal, #ssh_msg_userauth_info_response{} = Msg, {userauth_keyboa
case ssh_auth:handle_userauth_info_response(Msg, D0#data.ssh_params) of
{authorized, User, {Reply, Ssh1}} ->
D = connected_state(Reply, Ssh1, User, "keyboard-interactive", D0),
- {next_state, {connected,server}, D, {change_callback_module,ssh_connection_handler}};
+ {next_state, {connected,server}, D,
+ [set_max_initial_idle_timeout(D),
+ {change_callback_module,ssh_connection_handler}
+ ]};
{not_authorized, {User, Reason}, {Reply, Ssh}} ->
retry_fun(User, Reason, D0),
D = ssh_connection_handler:send_msg(Reply, D0#data{ssh_params = Ssh}),
@@ -125,7 +141,11 @@ handle_event(internal, #ssh_msg_userauth_info_response{} = Msg, {userauth_keyboa
{authorized, User, {Reply, Ssh1}} =
ssh_auth:handle_userauth_info_response({extra,Msg}, D0#data.ssh_params),
D = connected_state(Reply, Ssh1, User, "keyboard-interactive", D0),
- {next_state, {connected,server}, D, {change_callback_module,ssh_connection_handler}};
+ {next_state, {connected,server}, D,
+ [set_max_initial_idle_timeout(D),
+ {change_callback_module,ssh_connection_handler}
+ ]
+ };
%%% ######## UNHANDLED EVENT!
@@ -159,6 +179,9 @@ connected_state(Reply, Ssh1, User, Method, D0) ->
ssh_params = Ssh#ssh{authenticated = true}}.
+set_max_initial_idle_timeout(#data{ssh_params = #ssh{opts=Opts}}) ->
+ {{timeout,max_initial_idle_time}, ?GET_OPT(max_initial_idle_time,Opts), none}.
+
connected_fun(User, Method, #data{ssh_params = #ssh{peer = {_,Peer}}} = D) ->
?CALL_FUN(connectfun,D)(User, Peer, Method).
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index b1b4d0ea56..aa7324b588 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -20,7 +20,7 @@
%%
%%----------------------------------------------------------------------
-%% Purpose: Print some info of a running ssh aplication.
+%% Purpose: Print some info of a running ssh application.
%%----------------------------------------------------------------------
-module(ssh_info).
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 8ed662b3de..3c1ea65038 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -34,6 +34,8 @@
-export([ssh2_pubkey_decode/1,
ssh2_pubkey_encode/1,
ssh2_privkey_decode2/1,
+ oid2ssh_curvename/1,
+ ssh_curvename2oid/1,
%% experimental:
ssh2_privkey_encode/1
]).
@@ -172,7 +174,7 @@ encode(#ssh_msg_userauth_pk_ok{
<<?Ebyte(?SSH_MSG_USERAUTH_PK_OK), ?Estring(Alg), ?Ebinary(KeyBlob)>>;
encode(#ssh_msg_userauth_passwd_changereq{prompt = Prompt,
- languge = Lang
+ language = Lang
})->
<<?Ebyte(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?Estring_utf8(Prompt), ?Estring(Lang)>>;
@@ -438,7 +440,7 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_REQUEST),
decode(<<?BYTE(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?DEC_BIN(Prompt,__0), ?DEC_BIN(Lang,__1) >>) ->
#ssh_msg_userauth_passwd_changereq{
prompt = Prompt,
- languge = Lang
+ language = Lang
};
%%% Unhandled message, also masked by same 1:st byte value as ?SSH_MSG_USERAUTH_INFO_REQUEST:
@@ -571,20 +573,29 @@ decode(<<?BYTE(?SSH_MSG_DEBUG), ?BYTE(Bool), ?DEC_BIN(Msg,__0), ?DEC_BIN(Lang,__
%%%-------- public key --------
ssh2_pubkey_encode(#'RSAPublicKey'{modulus = N, publicExponent = E}) ->
<<?STRING(<<"ssh-rsa">>), ?Empint(E), ?Empint(N)>>;
+
ssh2_pubkey_encode({Y, #'Dss-Parms'{p = P, q = Q, g = G}}) ->
<<?STRING(<<"ssh-dss">>), ?Empint(P), ?Empint(Q), ?Empint(G), ?Empint(Y)>>;
+
+ssh2_pubkey_encode({#'ECPoint'{point = Q}, {namedCurve,OID}}) when OID == ?'id-Ed25519' orelse
+ OID == ?'id-Ed448' ->
+ {KeyType, _} = oid2ssh_curvename(OID),
+ <<?STRING(KeyType), ?Estring(Q)>>;
+
+ssh2_pubkey_encode(#'ECPrivateKey'{parameters = {namedCurve,OID},
+ publicKey = Key}) when OID == ?'id-Ed25519' orelse
+ OID == ?'id-Ed448' ->
+ {KeyType, _} = oid2ssh_curvename(OID),
+ <<?STRING(KeyType), ?Estring(Key)>>;
+
+ssh2_pubkey_encode(#'ECPrivateKey'{parameters = {namedCurve,OID},
+ publicKey = Key}) ->
+ {KeyType,Curve} = oid2ssh_curvename(OID),
+ <<?STRING(KeyType), ?STRING(Curve), ?Estring(Key)>>;
+
ssh2_pubkey_encode({#'ECPoint'{point = Q}, {namedCurve,OID}}) ->
- Curve = public_key:oid2ssh_curvename(OID),
- KeyType = <<"ecdsa-sha2-", Curve/binary>>,
- <<?STRING(KeyType), ?STRING(Curve), ?Estring(Q)>>;
-ssh2_pubkey_encode({ed_pub, ed25519, Key}) ->
- <<?STRING(<<"ssh-ed25519">>), ?Estring(Key)>>;
-ssh2_pubkey_encode({ed_pub, ed448, Key}) ->
- <<?STRING(<<"ssh-ed448">>), ?Estring(Key)>>;
-ssh2_pubkey_encode({ed_pri, ed25519, Key, _}) ->
- <<?STRING(<<"ssh-ed25519">>), ?Estring(Key)>>;
-ssh2_pubkey_encode({ed_pri, ed448, Key, _}) ->
- <<?STRING(<<"ssh-ed448">>), ?Estring(Key)>>.
+ {KeyType,Curve} = oid2ssh_curvename(OID),
+ <<?STRING(KeyType), ?STRING(Curve), ?Estring(Q)>>.
%%%--------
ssh2_pubkey_decode(KeyBlob) ->
@@ -608,26 +619,23 @@ ssh2_pubkey_decode2(<<?UINT32(7), "ssh-dss",
q = Q,
g = G}
}, Rest};
-ssh2_pubkey_decode2(<<?UINT32(TL), "ecdsa-sha2-",KeyRest/binary>>) ->
- Sz = TL-11,
- <<_Curve:Sz/binary,
- ?DEC_BIN(SshName, _IL),
- ?DEC_BIN(Q, _QL),
- Rest/binary>> = KeyRest,
- OID = public_key:ssh_curvename2oid(SshName),
- {{#'ECPoint'{point = Q}, {namedCurve,OID}
- }, Rest};
-ssh2_pubkey_decode2(<<?UINT32(11), "ssh-ed25519",
- ?DEC_BIN(Key, _L),
- Rest/binary>>) ->
- {{ed_pub, ed25519, Key},
- Rest};
-ssh2_pubkey_decode2(<<?UINT32(9), "ssh-ed448",
- ?DEC_BIN(Key, _L),
- Rest/binary>>) ->
- {{ed_pub, ed448, Key},
+
+ssh2_pubkey_decode2(<<?DEC_BIN(SshCurveName,SCNL), Rest0/binary>>) ->
+ {Pub, Rest} =
+ case {SshCurveName, Rest0} of
+ {<<"ecdsa-sha2-", _/binary>>,
+ <<?DEC_BIN(_Curve, _IL),
+ ?DEC_BIN(Q, _QL),
+ Rest1/binary>>} -> {Q, Rest1};
+
+ {<<"ssh-ed",_/binary>>,
+ <<?DEC_BIN(Key, _L),
+ Rest1/binary>>} -> {Key, Rest1}
+ end,
+ OID = ssh_curvename2oid(SshCurveName),
+ {{#'ECPoint'{point = Pub}, {namedCurve,OID}},
Rest}.
-
+
%%%-------- private key --------
%% dialyser... ssh2_privkey_decode(KeyBlob) ->
@@ -674,20 +682,26 @@ ssh2_privkey_encode(#'ECPrivateKey'
{version = 1,
parameters = {namedCurve,OID},
privateKey = Priv,
+ publicKey = Pub
+ }) when OID == ?'id-Ed25519' orelse
+ OID == ?'id-Ed448' ->
+ {CurveName,_} = oid2ssh_curvename(OID),
+ <<?STRING(CurveName),
+ ?STRING(Pub),
+ ?STRING(Priv)>>;
+
+ssh2_privkey_encode(#'ECPrivateKey'
+ {version = 1,
+ parameters = {namedCurve,OID},
+ privateKey = Priv,
publicKey = Q
}) ->
- CurveName = public_key:oid2ssh_curvename(OID),
- <<?STRING(<<"ecdsa-sha2-",CurveName/binary>>),
- ?STRING(<<"ecdsa-sha2-",CurveName/binary>>), % Yes
+ {CurveName,_} = oid2ssh_curvename(OID),
+ <<?STRING(CurveName),
+ ?STRING(CurveName), % SIC!
?STRING(Q),
- ?STRING(Priv)>>;
+ ?STRING(Priv)>>.
-ssh2_privkey_encode({ed_pri, Alg, Pub, Priv}) ->
- Name = atom_to_binary(Alg),
- <<?STRING(<<"ssh-",Name/binary>>),
- ?STRING(Pub),
- ?STRING(<<Priv/binary,Pub/binary>>)>>.
-
%%%--------
ssh2_privkey_decode2(<<?UINT32(7), "ssh-rsa",
?DEC_INT(N, _NL), % Yes, N and E is reversed relative pubkey format
@@ -721,34 +735,49 @@ ssh2_privkey_decode2(<<?UINT32(7), "ssh-dss",
y = Y,
x = X
}, Rest};
-ssh2_privkey_decode2(<<?UINT32(TL), "ecdsa-sha2-",KeyRest/binary>>) ->
- Sz = TL-11,
- <<_Curve:Sz/binary,
- ?DEC_BIN(CurveName, _SNN),
- ?DEC_BIN(Q, _QL),
- ?DEC_BIN(Priv, _PrivL),
- Rest/binary>> = KeyRest,
- OID = public_key:ssh_curvename2oid(CurveName),
+
+ssh2_privkey_decode2(<<?DEC_BIN(SshCurveName,SCNL), Rest0/binary>>) ->
+ {Pub, Priv, Rest} =
+ case {SshCurveName, Rest0} of
+ {<<"ecdsa-sha2-",_/binary>>,
+ <<?DEC_BIN(_Curve, _IL),
+ ?DEC_BIN(Pub1, _QL),
+ ?DEC_BIN(Priv1, _PrivL),
+ Rest1/binary>>} ->
+ {Pub1, Priv1, Rest1};
+
+ {<<"ssh-ed",_/binary>>,
+ <<?DEC_BIN(Pub1, PL),
+ ?DEC_BIN(PrivPub, PPL),
+ Rest1/binary>>} ->
+ PL = PPL div 2,
+ <<Priv1:PL/binary, _/binary>> = PrivPub,
+ {Pub1, Priv1, Rest1}
+ end,
+ OID = ssh_curvename2oid(SshCurveName),
{#'ECPrivateKey'{version = 1,
parameters = {namedCurve,OID},
privateKey = Priv,
- publicKey = Q
- }, Rest};
-ssh2_privkey_decode2(<<?UINT32(11), "ssh-ed25519",
- ?DEC_BIN(Pub,_Lpub),
- 64:32/unsigned-big-integer,
- Priv:32/binary,
- _Pub:32/binary,
- Rest/binary>>) ->
- {{ed_pri, ed25519, Pub, Priv}, Rest};
-ssh2_privkey_decode2(<<?UINT32(9), "ssh-ed448",
- ?DEC_BIN(Pub,_Lpub),
- 114:32/unsigned-big-integer,
- Priv:57/binary,
- _Pub:57/binary,
- Rest/binary>>) ->
- {{ed_pri, ed448, Pub, Priv}, Rest}.
-
+ publicKey = Pub
+ }, Rest}.
+
+
+%% Description: Converts from the ssh name of elliptic curves to
+%% the OIDs.
+%%--------------------------------------------------------------------
+ssh_curvename2oid(<<"ssh-ed25519">>) -> ?'id-Ed25519';
+ssh_curvename2oid(<<"ssh-ed448">> ) -> ?'id-Ed448';
+ssh_curvename2oid(<<"ecdsa-sha2-nistp256">>) -> ?'secp256r1';
+ssh_curvename2oid(<<"ecdsa-sha2-nistp384">>) -> ?'secp384r1';
+ssh_curvename2oid(<<"ecdsa-sha2-nistp521">>) -> ?'secp521r1'.
+
+%% Description: Converts from elliptic curve OIDs to the ssh name.
+%%--------------------------------------------------------------------
+oid2ssh_curvename(?'id-Ed25519')-> {<<"ssh-ed25519">>, 'n/a'};
+oid2ssh_curvename(?'id-Ed448') -> {<<"ssh-ed448">>, 'n/a'};
+oid2ssh_curvename(?'secp256r1') -> {<<"ecdsa-sha2-nistp256">>, <<"nistp256">>};
+oid2ssh_curvename(?'secp384r1') -> {<<"ecdsa-sha2-nistp384">>, <<"nistp384">>};
+oid2ssh_curvename(?'secp521r1') -> {<<"ecdsa-sha2-nistp521">>, <<"nistp521">>}.
%%%================================================================
%%%
@@ -810,13 +839,8 @@ encode_signature(#'RSAPublicKey'{}, SigAlg, Signature) ->
encode_signature({_, #'Dss-Parms'{}}, _SigAlg, Signature) ->
<<?Ebinary(<<"ssh-dss">>), ?Ebinary(Signature)>>;
encode_signature({#'ECPoint'{}, {namedCurve,OID}}, _SigAlg, Signature) ->
- Curve = public_key:oid2ssh_curvename(OID),
- <<?Ebinary(<<"ecdsa-sha2-",Curve/binary>>), ?Ebinary(Signature)>>;
-encode_signature({ed_pub, ed25519,_}, _SigAlg, Signature) ->
- <<?Ebinary(<<"ssh-ed25519">>), ?Ebinary(Signature)>>;
-encode_signature({ed_pub, ed448,_}, _SigAlg, Signature) ->
- <<?Ebinary(<<"ssh-ed448">>), ?Ebinary(Signature)>>.
-
+ {SshCurveName,_} = oid2ssh_curvename(OID),
+ <<?Ebinary(<<SshCurveName/binary>>), ?Ebinary(Signature)>>.
%%%################################################################
diff --git a/lib/ssh/src/ssh_options.erl b/lib/ssh/src/ssh_options.erl
index e06c2ed27c..53cc69dc86 100644
--- a/lib/ssh/src/ssh_options.erl
+++ b/lib/ssh/src/ssh_options.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,8 @@
keep_set_options/2,
no_sensitive/2,
initial_default_algorithms/2,
- check_preferred_algorithms/1
+ check_preferred_algorithms/1,
+ merge_options/3
]).
-export_type([private_options/0
@@ -153,6 +154,14 @@ delete_key(internal_options, Key, Opts, _CallerMod, _CallerLine) when is_map(Opt
%%%================================================================
%%%
+%%% Replace 0 or more options in an options map
+%%%
+merge_options(Role, NewPropList, Opts0) when is_list(NewPropList),
+ is_map(Opts0) ->
+ check_and_save(NewPropList, default(Role), Opts0).
+
+%%%================================================================
+%%%
%%% Initialize the options
%%%
@@ -167,8 +176,7 @@ handle_options(Role, PropList0) ->
handle_options(Role, OptsList0, Opts0) when is_map(Opts0),
is_list(OptsList0) ->
OptsList1 = proplists:unfold(
- lists:foldr(fun(T,Acc) when is_tuple(T),
- size(T) =/= 2-> [{special_trpt_args,T} | Acc];
+ lists:foldr(fun(T,Acc) when tuple_size(T) =/= 2 -> [{special_trpt_args,T} | Acc];
(X,Acc) -> [X|Acc]
end,
[], OptsList0)),
@@ -219,10 +227,8 @@ handle_options(Role, OptsList0, Opts0) when is_map(Opts0),
%% Enter the user's values into the map; unknown keys are
%% treated as socket options
- final_preferred_algorithms(
- lists:foldl(fun(KV, Vals) ->
- save(KV, OptionDefinitions, Vals)
- end, InitialMap, OptsList2))
+ check_and_save(OptsList2, OptionDefinitions, InitialMap)
+
catch
error:{EO, KV, Reason} when EO == eoptions ; EO == eerl_env ->
if
@@ -235,6 +241,13 @@ handle_options(Role, OptsList0, Opts0) when is_map(Opts0),
end
end.
+check_and_save(OptsList, OptionDefinitions, InitialMap) ->
+ final_preferred_algorithms(
+ lists:foldl(fun(KV, Vals) ->
+ save(KV, OptionDefinitions, Vals)
+ end, InitialMap, OptsList)).
+
+
cnf_key(server) -> server_options;
cnf_key(client) -> client_options.
@@ -295,7 +308,7 @@ save({Inet,false}, _Defs, OptMap) when Inet==inet ; Inet==inet6 -> OptMap;
save({special_trpt_args,T}, _Defs, OptMap) when is_map(OptMap) ->
OptMap#{socket_options := [T | maps:get(socket_options,OptMap)]};
-%% and finaly the 'real stuff':
+%% and finally the 'real stuff':
save({Key,Value}, Defs, OptMap) when is_map(OptMap) ->
try (check_fun(Key,Defs))(Value)
of
@@ -477,6 +490,12 @@ default(server) ->
class => user_option
},
+ no_auth_needed =>
+ #{default => false,
+ chk => fun(V) -> erlang:is_boolean(V) end,
+ class => user_option
+ },
+
pk_check_user =>
#{default => false,
chk => fun(V) -> erlang:is_boolean(V) end,
@@ -513,6 +532,12 @@ default(server) ->
class => user_option
},
+ max_initial_idle_time =>
+ #{default => infinity, %% To not break compatibility
+ chk => fun(V) -> check_timeout(V) end,
+ class => user_option
+ },
+
negotiation_timeout =>
#{default => 2*60*1000,
chk => fun(V) -> check_timeout(V) end,
@@ -771,6 +796,14 @@ default(common) ->
class => user_option
},
+ max_log_item_len =>
+ #{default => 500,
+ chk => fun(infinity) -> true;
+ (I) -> check_non_neg_integer(I)
+ end,
+ class => user_option
+ },
+
rekey_limit =>
#{default => {3600000, 1024000000}, % {1 hour, 1 GB}
chk => fun({infinity, infinity}) ->
@@ -1045,7 +1078,7 @@ check_modify_algorithms(M) when is_list(M) ->
[error_in_check(Op_KVs, "Bad modify_algorithms")
|| Op_KVs <- M,
not is_tuple(Op_KVs)
- orelse (size(Op_KVs) =/= 2)
+ orelse (tuple_size(Op_KVs) =/= 2)
orelse (not lists:member(element(1,Op_KVs), [append,prepend,rm]))],
{true, [{Op,normalize_mod_algs(KVs,false)} || {Op,KVs} <- M]};
check_modify_algorithms(_) ->
@@ -1070,11 +1103,11 @@ normalize_mod_algs([K|Ks], KVs0, Acc, UseDefaultAlgs) ->
normalize_mod_algs(Ks, KVs, [{K,Vs} | Acc], UseDefaultAlgs);
normalize_mod_algs([], [], Acc, _) ->
%% No values left in the key-value list after removing the expected entries
- %% (thats good)
+ %% (that's good)
lists:reverse(Acc);
normalize_mod_algs([], [{K,_}|_], _, _) ->
%% Some values left in the key-value list after removing the expected entries
- %% (thats bad)
+ %% (that's bad)
case ssh_transport:algo_class(K) of
true -> error_in_check(K, "Duplicate key");
false -> error_in_check(K, "Unknown key")
@@ -1157,7 +1190,7 @@ check_input_ok(Algs) ->
[error_in_check(KVs, "Bad preferred_algorithms")
|| KVs <- Algs,
not is_tuple(KVs)
- orelse (size(KVs) =/= 2)].
+ orelse (tuple_size(KVs) =/= 2)].
%%%----------------------------------------------------------------
final_preferred_algorithms(Options0) ->
diff --git a/lib/ssh/src/ssh_server_channel.erl b/lib/ssh/src/ssh_server_channel.erl
index 6339f13cad..87d32ccfb0 100644
--- a/lib/ssh/src/ssh_server_channel.erl
+++ b/lib/ssh/src/ssh_server_channel.erl
@@ -25,7 +25,7 @@
-module(ssh_server_channel).
-%% API to server side channel that can be pluged into the erlang ssh daemeon
+%% API to server side channel that can be plugged into the erlang ssh daemeon
-callback init(Args :: term()) ->
{ok, State :: term()} | {ok, State :: term(), timeout() | hibernate} |
{stop, Reason :: term()} | ignore.
diff --git a/lib/ssh/src/ssh_server_key_api.erl b/lib/ssh/src/ssh_server_key_api.erl
index addf46ef78..d668c8f61b 100644
--- a/lib/ssh/src/ssh_server_key_api.erl
+++ b/lib/ssh/src/ssh_server_key_api.erl
@@ -29,7 +29,7 @@
%%% The option key_cb_private is to pass options needed by other
%%% callback modules than the default ssh_file.erl
%%%
-%%% If ssh:deamon(n, [ {key_cb_private, {hi,{there}}} ]
+%%% If ssh:daemon(n, [ {key_cb_private, {hi,{there}}} ]
%%% is called, the term() will be {hi,{there}}
-type daemon_key_cb_options(T) :: [{key_cb_private,[T]} | ssh:daemon_option()].
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl
index c91f9d67ee..bd31119654 100644
--- a/lib/ssh/src/ssh_sftp.erl
+++ b/lib/ssh/src/ssh_sftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,9 +58,9 @@
-record(state,
{
xf,
- rep_buf = <<>>,
+ rep_buf = <<>> :: binary(),
req_id,
- req_list = [], %% {ReqId, Fun}
+ req_list = [], %% {ReqId, Fun}
inf, %% list of fileinf,
opts
}).
@@ -75,14 +75,14 @@
-record(bufinf,
{
- mode, % read | write (=from or to buffer by user)
- crypto_state,
+ mode :: read | write, % read | write (=from or to buffer by user)
+ crypto_state :: term() | undefined,
crypto_fun, % For encode or decode depending on the mode field
- size = 0, % # bytes "before" the current buffer for the postion call
+ size = 0 :: non_neg_integer() | undefined, % # bytes "before" the current buffer for the position call
- chunksize, % The size of the chunks to be sent or received
- enc_text_buf = <<>>, % Encrypted text
- plain_text_buf = <<>> % Decrypted text
+ chunksize :: non_neg_integer() | undefined, % The size of the chunks to be sent or received
+ enc_text_buf = <<>> :: binary() | undefined, % Encrypted text
+ plain_text_buf = <<>> :: binary() | undefined % Decrypted text
}).
-define(FILEOP_TIMEOUT, infinity).
@@ -121,7 +121,7 @@ start_channel(Dest) ->
%%% function clauses.
-spec start_channel(ssh:open_socket(),
- [ssh:client_options() | sftp_option()]
+ [ssh:client_option() | sftp_option()]
)
-> {ok,pid(),ssh:connection_ref()} | {error,reason()};
@@ -131,7 +131,7 @@ start_channel(Dest) ->
-> {ok,pid()} | {ok,pid(),ssh:connection_ref()} | {error,reason()};
(ssh:host(),
- [ssh:client_options() | sftp_option()]
+ [ssh:client_option() | sftp_option()]
)
-> {ok,pid(),ssh:connection_ref()} | {error,reason()} .
@@ -816,7 +816,7 @@ write_file(Pid, Name, Bin, FileOpTimeout) ->
case open(Pid, Name, [write, binary], FileOpTimeout) of
{ok, Handle} ->
{ok,{_Window,Packet}} = send_window(Pid, FileOpTimeout),
- Res = write_file_loop(Pid, Handle, 0, Bin, size(Bin), Packet,
+ Res = write_file_loop(Pid, Handle, 0, Bin, byte_size(Bin), Packet,
FileOpTimeout),
close(Pid, Handle, FileOpTimeout),
Res;
@@ -1017,7 +1017,7 @@ do_handle_call({pwrite,Async,Handle,At,Data0}, From, State) ->
{ok,Offset} ->
Data = to_bin(Data0),
ReqID = State#state.req_id,
- Size = size(Data),
+ Size = byte_size(Data),
ssh_xfer:write(?XF(State),ReqID,Handle,Offset,Data),
State1 = update_size(Handle, Offset+Size, State),
make_reply(ReqID, Async, From, State1);
@@ -1030,7 +1030,7 @@ do_handle_call({write,Async,Handle,Data0}, From, State) ->
{ok,Offset} ->
Data = to_bin(Data0),
ReqID = State#state.req_id,
- Size = size(Data),
+ Size = byte_size(Data),
ssh_xfer:write(?XF(State),ReqID,Handle,Offset,Data),
State1 = update_offset(Handle, Offset+Size, State),
make_reply(ReqID, Async, From, State1);
@@ -1224,7 +1224,7 @@ terminate(_Reason, State) ->
%% Internal functions
%%====================================================================
legacy_timeout(UserOptions) ->
- %% Make both connect_timeout and timeout defined if exaclty one of them is defined:
+ %% Make both connect_timeout and timeout defined if exactly one of them is defined:
case {proplists:get_value(connect_timeout, UserOptions),
proplists:get_value(timeout, UserOptions)} of
{undefined, undefined} ->
@@ -1582,7 +1582,7 @@ erase_handle(Handle, State) ->
State#state{inf = FI}.
%%
-%% Caluclate a integer offset
+%% Calculate a integer offset
%%
lseek_position(Handle, Pos, State) ->
case maps:find(Handle, State#state.inf) of
@@ -1640,7 +1640,7 @@ read_repeat(Pid, Handle, Len, FileOpTimeout) ->
read_rpt(Pid, Handle, WantedLen, PacketSz, FileOpTimeout, Acc) when WantedLen > 0 ->
case read(Pid, Handle, min(WantedLen,PacketSz), FileOpTimeout) of
{ok, Data} ->
- read_rpt(Pid, Handle, WantedLen-size(Data), PacketSz, FileOpTimeout, <<Acc/binary, Data/binary>>);
+ read_rpt(Pid, Handle, WantedLen-byte_size(Data), PacketSz, FileOpTimeout, <<Acc/binary, Data/binary>>);
eof ->
{ok, Acc};
Error ->
@@ -1654,7 +1654,7 @@ write_to_remote_tar(_Pid, _SftpHandle, <<>>, _FileOpTimeout) ->
ok;
write_to_remote_tar(Pid, SftpHandle, Bin, FileOpTimeout) ->
{ok,{_Window,Packet}} = send_window(Pid, FileOpTimeout),
- write_file_loop(Pid, SftpHandle, 0, Bin, size(Bin), Packet, FileOpTimeout).
+ write_file_loop(Pid, SftpHandle, 0, Bin, byte_size(Bin), Packet, FileOpTimeout).
position_buf(Pid, SftpHandle, BufHandle, Pos, FileOpTimeout) ->
{ok,#bufinf{mode = Mode,
@@ -1662,7 +1662,7 @@ position_buf(Pid, SftpHandle, BufHandle, Pos, FileOpTimeout) ->
size = Size}} = call(Pid, {get_bufinf,BufHandle}, FileOpTimeout),
case Pos of
{cur,0} when Mode==write ->
- {ok,Size+size(Buf0)};
+ {ok,Size+byte_size(Buf0)};
{cur,0} when Mode==read ->
{ok,Size};
@@ -1707,7 +1707,7 @@ read_buf(Pid, SftpHandle, BufHandle, WantedLen, FileOpTimeout) ->
do_the_read_buf(_Pid, _SftpHandle, WantedLen, _Packet, _FileOpTimeout,
B=#bufinf{plain_text_buf=PlainBuf0,
size = Size})
- when size(PlainBuf0) >= WantedLen ->
+ when byte_size(PlainBuf0) >= WantedLen ->
%% We already have the wanted number of bytes decoded and ready!
<<ResultBin:WantedLen/binary, PlainBuf/binary>> = PlainBuf0,
{ok,ResultBin,B#bufinf{plain_text_buf=PlainBuf,
@@ -1718,8 +1718,8 @@ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
enc_text_buf = EncBuf0,
chunksize = undefined
})
- when size(EncBuf0) > 0 ->
- %% We have (at least) one decodable byte waiting for decodeing.
+ when byte_size(EncBuf0) > 0 ->
+ %% We have (at least) one decodable byte waiting for decoding.
{ok,DecodedBin,B} = apply_crypto(EncBuf0, B0),
do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
B#bufinf{plain_text_buf = <<PlainBuf0/binary, DecodedBin/binary>>,
@@ -1731,8 +1731,8 @@ do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
enc_text_buf = EncBuf0,
chunksize = ChunkSize0
})
- when size(EncBuf0) >= ChunkSize0 ->
- %% We have (at least) one chunk of decodable bytes waiting for decodeing.
+ when byte_size(EncBuf0) >= ChunkSize0 ->
+ %% We have (at least) one chunk of decodable bytes waiting for decoding.
<<ToDecode:ChunkSize0/binary, EncBuf/binary>> = EncBuf0,
{ok,DecodedBin,B} = apply_crypto(ToDecode, B0),
do_the_read_buf(Pid, SftpHandle, WantedLen, Packet, FileOpTimeout,
@@ -1768,7 +1768,7 @@ write_buf(Pid, SftpHandle, BufHandle, PlainBin, FileOpTimeout) ->
do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
B=#bufinf{enc_text_buf = EncBuf0,
size = Size})
- when size(EncBuf0) >= Packet ->
+ when byte_size(EncBuf0) >= Packet ->
<<BinToWrite:Packet/binary, EncBuf/binary>> = EncBuf0,
case write(Pid, SftpHandle, BinToWrite, FileOpTimeout) of
ok ->
@@ -1783,7 +1783,7 @@ do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
B0=#bufinf{plain_text_buf = PlainBuf0,
enc_text_buf = EncBuf0,
chunksize = undefined})
- when size(PlainBuf0) > 0 ->
+ when byte_size(PlainBuf0) > 0 ->
{ok,EncodedBin,B} = apply_crypto(PlainBuf0, B0),
do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
B#bufinf{plain_text_buf = <<>>,
@@ -1794,7 +1794,7 @@ do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
enc_text_buf = EncBuf0,
chunksize = ChunkSize0
})
- when size(PlainBuf0) >= ChunkSize0 ->
+ when byte_size(PlainBuf0) >= ChunkSize0 ->
<<ToEncode:ChunkSize0/binary, PlainBuf/binary>> = PlainBuf0,
{ok,EncodedBin,B} = apply_crypto(ToEncode, B0),
do_the_write_buf(Pid, SftpHandle, Packet, FileOpTimeout,
diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 27b97716eb..c86ed2cb81 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -102,7 +102,7 @@ init(Options) ->
%% Get the root of the file system (symlinks must be followed,
%% otherwise the realpath call won't work). But since symbolic links
- %% isn't supported on all plattforms we have to use the root property
+ %% isn't supported on all platforms we have to use the root property
%% supplied by the user.
{Root, State} =
case resolve_symlinks(Root0,
diff --git a/lib/ssh/src/ssh_shell.erl b/lib/ssh/src/ssh_shell.erl
index bd11afa080..4ab11487a9 100644
--- a/lib/ssh/src/ssh_shell.erl
+++ b/lib/ssh/src/ssh_shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
-include("ssh_connect.hrl").
%%% As this is an user interactive client it behaves like a daemon
-%%% channel inspite of it being a client.
+%%% channel in spite of it being a client.
-behaviour(ssh_server_channel).
%% ssh_server_channel callbacks
diff --git a/lib/ssh/src/ssh_system_sup.erl b/lib/ssh/src/ssh_system_sup.erl
index 728a10974c..ed27dc52b2 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,9 @@
get_daemon_listen_address/1,
addresses/1,
addresses/2,
- get_options/2
+ get_options/2,
+ get_acceptor_options/1,
+ replace_acceptor_options/2
]).
%% Supervisor callback
@@ -122,7 +124,7 @@ start_subsystem(Role, Address=#address{}, Socket, Options0) ->
{error,Error};
error:timeout ->
%% The connection was started, but the takover procedure timed out,
- %% therefor it exists a subtree, but it is not quite ready and
+ %% therefore it exists a subtree, but it is not quite ready and
%% must be removed (by the supervisor above):
supervisor:terminate_child(SysPid, Id),
{error, connection_start_timeout}
@@ -151,6 +153,32 @@ addresses(Role, #address{address=Address, port=Port, profile=Profile}) ->
Port == any orelse A#address.port == Port,
Profile == any orelse A#address.profile == Profile].
+%%%----------------------------------------------------------------
+%% SysPid is the DaemonRef
+
+get_acceptor_options(SysPid) ->
+ case get_daemon_listen_address(SysPid) of
+ {ok,Address} ->
+ get_options(SysPid, Address);
+ {error,Error} ->
+ {error,Error}
+ end.
+
+replace_acceptor_options(SysPid, NewOpts) ->
+ case get_daemon_listen_address(SysPid) of
+ {ok,Address} ->
+ try stop_listener(SysPid)
+ of
+ ok ->
+ restart_acceptor(SysPid, Address, NewOpts)
+ catch
+ error:_ ->
+ restart_acceptor(SysPid, Address, NewOpts)
+ end;
+ {error,Error} ->
+ {error,Error}
+ end.
+
%%%=========================================================================
%%% Supervisor callback
%%%=========================================================================
@@ -219,7 +247,7 @@ find_system_sup(Role, Address0) ->
case addresses(Role, Address0) of
[{SysSupPid,Address}] -> {ok,{SysSupPid,Address}};
[] -> {error,not_found};
- [_,_|_] -> {error,ambigous}
+ [_,_|_] -> {error,ambiguous}
end.
sup(client) -> sshc_sup;
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index e43c345130..c0b46b338b 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,7 +49,6 @@
handle_kex_ecdh_init/2,
handle_kex_ecdh_reply/2,
parallell_gen_key/1,
- extract_public_key/1,
ssh_packet/2, pack/2,
valid_key_sha_alg/3,
sign/3, sign/4,
@@ -62,6 +61,8 @@
-behaviour(ssh_dbg).
-export([ssh_dbg_trace_points/0, ssh_dbg_flags/1, ssh_dbg_on/1, ssh_dbg_off/1, ssh_dbg_format/2]).
+-define(MIN_DH_KEY_SIZE, 400).
+
%%% For test suites
-export([pack/3, adjust_algs_for_peer_version/2]).
@@ -432,7 +433,12 @@ kexinit_error(Class, Error, Role, Own, CounterPart) ->
_ ->
{"Kexinit failed in ~p: ~p:~p", [Role,Class,Error]}
end,
- io_lib:format(Fmt, Args).
+ try io_lib:format(Fmt, Args) of
+ R -> R
+ catch
+ _:_ ->
+ io_lib:format("Kexinit failed in ~p: ~p:~p", [Role, Class, Error])
+ end.
alg_info(client, Alg) ->
alg_info(Alg);
@@ -553,7 +559,7 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E},
{Public, Private} = generate_key(dh, [P,G,2*Sz]),
K = compute_key(dh, E, Private, [P,G]),
MyPrivHostKey = get_host_key(SignAlg, Opts),
- MyPubHostKey = extract_public_key(MyPrivHostKey),
+ MyPubHostKey = ssh_file:extract_public_key(MyPrivHostKey),
H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {E,Public,K}),
case sign(H, SignAlg, MyPrivHostKey, Ssh0) of
{ok,H_SIG} ->
@@ -705,7 +711,7 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E},
if
1<K, K<(P-1) ->
MyPrivHostKey = get_host_key(SignAlg, Opts),
- MyPubHostKey = extract_public_key(MyPrivHostKey),
+ MyPubHostKey = ssh_file:extract_public_key(MyPrivHostKey),
H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {Min,NBits,Max,P,G,E,Public,K}),
case sign(H, SignAlg, MyPrivHostKey, Ssh0) of
{ok,H_SIG} ->
@@ -788,7 +794,7 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic},
of
K ->
MyPrivHostKey = get_host_key(SignAlg, Opts),
- MyPubHostKey = extract_public_key(MyPrivHostKey),
+ MyPubHostKey = ssh_file:extract_public_key(MyPrivHostKey),
H = kex_hash(Ssh0, MyPubHostKey, sha(Curve), {PeerPublic, MyPublic, K}),
case sign(H, SignAlg, MyPrivHostKey, Ssh0) of
{ok,H_SIG} ->
@@ -926,37 +932,6 @@ call_KeyCb(F, Args, Opts) ->
UserOpts = ?GET_OPT(key_cb_options, Opts),
apply(KeyCb, F, Args ++ [[{key_cb_private,KeyCbOpts}|UserOpts]]).
-extract_public_key(#'RSAPrivateKey'{modulus = N, publicExponent = E}) ->
- #'RSAPublicKey'{modulus = N, publicExponent = E};
-extract_public_key(#'DSAPrivateKey'{y = Y, p = P, q = Q, g = G}) ->
- {Y, #'Dss-Parms'{p=P, q=Q, g=G}};
-extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID},
- publicKey = Pub0, privateKey = Priv}) when
- OID == ?'id-Ed25519'orelse
- OID == ?'id-Ed448' ->
- case {pubkey_cert_records:namedCurves(OID), Pub0} of
- {Alg, asn1_NOVALUE} ->
- %% If we're missing the public key, we can create it with
- %% the private key.
- {Pub, Priv} = crypto:generate_key(eddsa, Alg, Priv),
- {ed_pub, Alg, Pub};
- {Alg, Pub} ->
- {ed_pub, Alg, Pub}
- end;
-extract_public_key(#'ECPrivateKey'{parameters = {namedCurve,OID},
- publicKey = Q}) when is_tuple(OID) ->
- {#'ECPoint'{point=Q}, {namedCurve,OID}};
-extract_public_key({ed_pri, Alg, Pub, _Priv}) ->
- {ed_pub, Alg, Pub};
-extract_public_key(#{engine:=_, key_id:=_, algorithm:=Alg} = M) ->
- case {Alg, crypto:privkey_to_pubkey(Alg, M)} of
- {rsa, [E,N]} ->
- #'RSAPublicKey'{modulus = N, publicExponent = E};
- {dss, [P,Q,G,Y]} ->
- {Y, #'Dss-Parms'{p=P, q=Q, g=G}}
- end.
-
-
verify_host_key(#ssh{algorithms=Alg}=SSH, PublicKey, Digest, {AlgStr,Signature}) ->
case atom_to_list(Alg#alg.hkey) of
@@ -1274,8 +1249,8 @@ alg_final(rcv, SSH0) ->
select_all(CL, SL) when length(CL) + length(SL) < ?MAX_NUM_ALGORITHMS ->
- %% algortihms only used by client
- %% NOTE: an algorithm occuring more than once in CL will still be present
+ %% algorithms only used by client
+ %% NOTE: an algorithm occurring more than once in CL will still be present
%% in CLonly. This is not a problem for nice clients.
CLonly = CL -- SL,
@@ -1335,9 +1310,9 @@ pack(common, rfc4253, PlainText, DeltaLenTst,
#ssh{send_sequence = SeqNum,
send_mac = MacAlg,
send_mac_key = MacKey} = Ssh0) ->
- PadLen = padding_length(4+1+size(PlainText), Ssh0),
+ PadLen = padding_length(4+1+byte_size(PlainText), Ssh0),
Pad = ssh_bits:random(PadLen),
- TextLen = 1 + size(PlainText) + PadLen + DeltaLenTst,
+ TextLen = 1 + byte_size(PlainText) + PadLen + DeltaLenTst,
PlainPkt = <<?UINT32(TextLen),?BYTE(PadLen), PlainText/binary, Pad/binary>>,
{Ssh1, CipherPkt} = encrypt(Ssh0, PlainPkt),
MAC0 = mac(MacAlg, MacKey, SeqNum, PlainPkt),
@@ -1348,9 +1323,9 @@ pack(common, enc_then_mac, PlainText, DeltaLenTst,
#ssh{send_sequence = SeqNum,
send_mac = MacAlg,
send_mac_key = MacKey} = Ssh0) ->
- PadLen = padding_length(1+size(PlainText), Ssh0),
+ PadLen = padding_length(1+byte_size(PlainText), Ssh0),
Pad = ssh_bits:random(PadLen),
- PlainLen = 1 + size(PlainText) + PadLen + DeltaLenTst,
+ PlainLen = 1 + byte_size(PlainText) + PadLen + DeltaLenTst,
PlainPkt = <<?BYTE(PadLen), PlainText/binary, Pad/binary>>,
{Ssh1, CipherPkt} = encrypt(Ssh0, PlainPkt),
EncPacketPkt = <<?UINT32(PlainLen), CipherPkt/binary>>,
@@ -1358,9 +1333,9 @@ pack(common, enc_then_mac, PlainText, DeltaLenTst,
{<<?UINT32(PlainLen), CipherPkt/binary, MAC0/binary>>, Ssh1};
pack(aead, _, PlainText, DeltaLenTst, Ssh0) ->
- PadLen = padding_length(1+size(PlainText), Ssh0),
+ PadLen = padding_length(1+byte_size(PlainText), Ssh0),
Pad = ssh_bits:random(PadLen),
- PlainLen = 1 + size(PlainText) + PadLen + DeltaLenTst,
+ PlainLen = 1 + byte_size(PlainText) + PadLen + DeltaLenTst,
PlainPkt = <<?BYTE(PadLen), PlainText/binary, Pad/binary>>,
{Ssh1, {CipherPkt,MAC0}} = encrypt(Ssh0, <<?UINT32(PlainLen),PlainPkt/binary>>),
{<<CipherPkt/binary,MAC0/binary>>, Ssh1}.
@@ -1387,7 +1362,7 @@ handle_packet_part(<<>>, Encrypted0, AEAD0, undefined, #ssh{decrypt = CryptoAlg,
end;
handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0)
- when (size(DecryptedPfx)+size(EncryptedBuffer)) < TotalNeeded ->
+ when (byte_size(DecryptedPfx)+byte_size(EncryptedBuffer)) < TotalNeeded ->
%% need more bytes to finalize the packet
{get_more, DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0};
@@ -1406,7 +1381,7 @@ handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, #ssh{decryp
%%%----------------
unpack(common, rfc4253, DecryptedPfx, EncryptedBuffer, _AEAD, TotalNeeded,
#ssh{recv_mac_size = MacSize} = Ssh0) ->
- MoreNeeded = TotalNeeded - size(DecryptedPfx) - MacSize,
+ MoreNeeded = TotalNeeded - byte_size(DecryptedPfx) - MacSize,
<<EncryptedSfx:MoreNeeded/binary, Mac:MacSize/binary, NextPacketBytes/binary>> = EncryptedBuffer,
{Ssh1, DecryptedSfx} = decrypt(Ssh0, EncryptedSfx),
PlainPkt = <<DecryptedPfx/binary, DecryptedSfx/binary>>,
@@ -1423,7 +1398,7 @@ unpack(common, enc_then_mac, <<?UINT32(PlainLen)>>, EncryptedBuffer, _AEAD, _Tot
case is_valid_mac(MAC0, <<?UINT32(PlainLen),Payload/binary>>, Ssh0) of
true ->
{Ssh1, <<?BYTE(PaddingLen), PlainRest/binary>>} = decrypt(Ssh0, Payload),
- CompressedPlainTextLen = size(PlainRest) - PaddingLen,
+ CompressedPlainTextLen = byte_size(PlainRest) - PaddingLen,
<<CompressedPlainText:CompressedPlainTextLen/binary, _Padding/binary>> = PlainRest,
{ok, CompressedPlainText, NextPacketBytes, Ssh1};
false ->
@@ -1433,7 +1408,7 @@ unpack(common, enc_then_mac, <<?UINT32(PlainLen)>>, EncryptedBuffer, _AEAD, _Tot
unpack(aead, _, DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded,
#ssh{recv_mac_size = MacSize} = Ssh0) ->
%% enough bytes to decode the packet.
- MoreNeeded = TotalNeeded - size(DecryptedPfx) - MacSize,
+ MoreNeeded = TotalNeeded - byte_size(DecryptedPfx) - MacSize,
<<EncryptedSfx:MoreNeeded/binary, Mac:MacSize/binary, NextPacketBytes/binary>> = EncryptedBuffer,
case decrypt(Ssh0, {AEAD,EncryptedSfx,Mac}) of
{Ssh1, error} ->
@@ -1445,7 +1420,7 @@ unpack(aead, _, DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded,
%%%----------------------------------------------------------------
get_length(common, rfc4253, EncryptedBuffer, #ssh{decrypt_block_size = BlockSize} = Ssh0) ->
- case size(EncryptedBuffer) >= erlang:max(8, BlockSize) of
+ case byte_size(EncryptedBuffer) >= erlang:max(8, BlockSize) of
true ->
<<EncBlock:BlockSize/binary, EncryptedRest/binary>> = EncryptedBuffer,
{Ssh,
@@ -1465,7 +1440,7 @@ get_length(common, enc_then_mac, EncryptedBuffer, Ssh) ->
end;
get_length(aead, _, EncryptedBuffer, Ssh) ->
- case {size(EncryptedBuffer) >= 4, Ssh#ssh.decrypt} of
+ case {byte_size(EncryptedBuffer) >= 4, Ssh#ssh.decrypt} of
{true, 'chacha20-poly1305@openssh.com'} ->
<<EncryptedLen:4/binary, EncryptedRest/binary>> = EncryptedBuffer,
{Ssh1, PacketLenBin} = decrypt(Ssh, {length,EncryptedLen}),
@@ -1546,7 +1521,7 @@ do_verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key, _) ->
_ ->
false
end;
-do_verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) ->
+do_verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) when HashAlg =/= undefined ->
case Sig of
<<?UINT32(Rlen),R:Rlen/big-signed-integer-unit:8,
?UINT32(Slen),S:Slen/big-signed-integer-unit:8>> ->
@@ -2061,40 +2036,27 @@ valid_key_sha_alg(private, #'RSAPrivateKey'{}, 'ssh-rsa' ) -> true;
valid_key_sha_alg(public, {_, #'Dss-Parms'{}}, 'ssh-dss') -> true;
valid_key_sha_alg(private, #'DSAPrivateKey'{}, 'ssh-dss') -> true;
-valid_key_sha_alg(public, {ed_pub, ed25519,_}, 'ssh-ed25519') -> true;
-valid_key_sha_alg(private, {ed_pri, ed25519,_,_},'ssh-ed25519') -> true;
-valid_key_sha_alg(private, #'ECPrivateKey'{parameters = {namedCurve,OID}},'ssh-ed25519') when OID == ?'id-Ed25519' -> true;
-valid_key_sha_alg(public, {ed_pub, ed448,_}, 'ssh-ed448') -> true;
-valid_key_sha_alg(private, {ed_pri, ed448,_,_}, 'ssh-ed448') -> true;
-valid_key_sha_alg(private, #'ECPrivateKey'{parameters = {namedCurve,OID}},'ssh-ed448') when OID == ?'id-Ed448' -> true;
-
-valid_key_sha_alg(public, {#'ECPoint'{},{namedCurve,OID}}, Alg) when is_tuple(OID) ->
+valid_key_sha_alg(public, {#'ECPoint'{},{namedCurve,OID}}, Alg) ->
valid_key_sha_alg_ec(OID, Alg);
-valid_key_sha_alg(private, #'ECPrivateKey'{parameters = {namedCurve,OID}}, Alg) when is_tuple(OID) ->
+valid_key_sha_alg(private, #'ECPrivateKey'{parameters = {namedCurve,OID}}, Alg) ->
valid_key_sha_alg_ec(OID, Alg);
valid_key_sha_alg(_, _, _) -> false.
-
-valid_key_sha_alg_ec(OID, Alg) ->
- try
- Curve = public_key:oid2ssh_curvename(OID),
- Alg == list_to_existing_atom("ecdsa-sha2-" ++ binary_to_list(Curve))
- catch
- _:_ -> false
- end.
+
+
+valid_key_sha_alg_ec(OID, Alg) when is_tuple(OID) ->
+ {SshCurveType, _} = ssh_message:oid2ssh_curvename(OID),
+ Alg == binary_to_atom(SshCurveType);
+valid_key_sha_alg_ec(_, _) -> false.
+
-dialyzer({no_match, public_algo/1}).
public_algo(#'RSAPublicKey'{}) -> 'ssh-rsa'; % FIXME: Not right with draft-curdle-rsa-sha2
public_algo({_, #'Dss-Parms'{}}) -> 'ssh-dss';
-public_algo({ed_pub, ed25519,_}) -> 'ssh-ed25519';
-public_algo({ed_pub, ed448,_}) -> 'ssh-ed448';
public_algo({#'ECPoint'{},{namedCurve,OID}}) when is_tuple(OID) ->
- SshName = public_key:oid2ssh_curvename(OID),
- try list_to_existing_atom("ecdsa-sha2-" ++ binary_to_list(SshName))
- catch
- _:_ -> undefined
- end.
+ {SshCurveType, _} = ssh_message:oid2ssh_curvename(OID),
+ binary_to_atom(SshCurveType).
sha('ssh-rsa') -> sha;
@@ -2179,10 +2141,10 @@ parallell_gen_key(Ssh = #ssh{keyex_key = {x, {G, P}},
Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}.
-generate_key(ecdh = Algorithm, Args) ->
- crypto:generate_key(Algorithm, Args);
-generate_key(Algorithm, Args) ->
- {Public,Private} = crypto:generate_key(Algorithm, Args),
+generate_key(ecdh, Args) ->
+ crypto:generate_key(ecdh, Args);
+generate_key(dh, [P,G,Sz2]) ->
+ {Public,Private} = crypto:generate_key(dh, [P, G, max(Sz2,?MIN_DH_KEY_SIZE)] ),
{crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}.
diff --git a/lib/ssh/src/ssh_transport.hrl b/lib/ssh/src/ssh_transport.hrl
index f424a4ff63..009d85cb79 100644
--- a/lib/ssh/src/ssh_transport.hrl
+++ b/lib/ssh/src/ssh_transport.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
%%
%%----------------------------------------------------------------------
-%% Purpose: Record and constant defenitions for the SSH-tansport layer
+%% Purpose: Record and constant definitions for the SSH-tansport layer
%% protocol see RFC 4253
%%----------------------------------------------------------------------
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index 212798f2d7..4656ab5219 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -242,7 +242,7 @@ xf_request(XF, Op, Arg) ->
is_list(Arg) ->
?to_binary(Arg)
end,
- Size = 1+size(Data),
+ Size = 1+byte_size(Data),
ssh_connection:send(CM, Channel, [<<?UINT32(Size), Op, Data/binary>>]).
xf_send_reply(#ssh_xfer{cm = CM, channel = Channel}, Op, Arg) ->
@@ -252,7 +252,7 @@ xf_send_reply(#ssh_xfer{cm = CM, channel = Channel}, Op, Arg) ->
is_list(Arg) ->
?to_binary(Arg)
end,
- Size = 1 + size(Data),
+ Size = 1 + byte_size(Data),
ssh_connection:send(CM, Channel, [<<?UINT32(Size), Op, Data/binary>>]).
xf_send_name(XF, ReqId, Name, Attr) ->
@@ -290,7 +290,7 @@ xf_send_status(#ssh_xfer{cm = CM, channel = Channel},
LangTag = "en",
ELen = length(ErrorMsg),
TLen = 2, %% length(LangTag),
- Size = 1 + 4 + 4 + 4+ELen + 4+TLen + size(Data),
+ Size = 1 + 4 + 4 + 4+ELen + 4+TLen + byte_size(Data),
ToSend = [<<?UINT32(Size), ?SSH_FXP_STATUS, ?UINT32(ReqId),
?UINT32(ErrorCode)>>,
<<?UINT32(ELen)>>, ErrorMsg,
@@ -300,13 +300,13 @@ xf_send_status(#ssh_xfer{cm = CM, channel = Channel},
xf_send_attr(#ssh_xfer{cm = CM, channel = Channel, vsn = Vsn}, ReqId, Attr) ->
EncAttr = encode_ATTR(Vsn, Attr),
- ALen = size(EncAttr),
+ ALen = byte_size(EncAttr),
Size = 1 + 4 + ALen,
ToSend = [<<?UINT32(Size), ?SSH_FXP_ATTRS, ?UINT32(ReqId)>>, EncAttr],
ssh_connection:send(CM, Channel, ToSend).
xf_send_data(#ssh_xfer{cm = CM, channel = Channel}, ReqId, Data) ->
- DLen = size(Data),
+ DLen = byte_size(Data),
Size = 1 + 4 + 4+DLen,
ToSend = [<<?UINT32(Size), ?SSH_FXP_DATA, ?UINT32(ReqId), ?UINT32(DLen)>>,
Data],
@@ -815,21 +815,21 @@ encode_name(Vsn, {{NameUC,LongNameUC},Attr}, Len) when Vsn =< 3 ->
LongName = binary_to_list(unicode:characters_to_binary(LongNameUC)),
LNLen = length(LongName),
EncAttr = encode_ATTR(Vsn, Attr),
- ALen = size(EncAttr),
+ ALen = byte_size(EncAttr),
NewLen = Len + NLen + LNLen + 4 + 4 + ALen,
{[<<?UINT32(NLen)>>, Name, <<?UINT32(LNLen)>>, LongName, EncAttr], NewLen};
encode_name(Vsn, {NameUC,Attr}, Len) when Vsn =< 3 ->
Name = binary_to_list(unicode:characters_to_binary(NameUC)),
NLen = length(Name),
EncAttr = encode_ATTR(Vsn, Attr),
- ALen = size(EncAttr),
+ ALen = byte_size(EncAttr),
NewLen = Len + NLen*2 + 4 + 4 + ALen,
{[<<?UINT32(NLen)>>, Name, <<?UINT32(NLen)>>, Name, EncAttr], NewLen};
encode_name(Vsn, {NameUC,Attr}, Len) when Vsn >= 4 ->
Name = binary_to_list(unicode:characters_to_binary(NameUC)),
NLen = length(Name),
EncAttr = encode_ATTR(Vsn, Attr),
- ALen = size(EncAttr),
+ ALen = byte_size(EncAttr),
{[<<?UINT32(NLen)>>, Name, EncAttr],
Len + 4 + NLen + ALen}.
diff --git a/lib/ssh/src/ssh_xfer.hrl b/lib/ssh/src/ssh_xfer.hrl
index 07467c474b..bc2e1fa20c 100644
--- a/lib/ssh/src/ssh_xfer.hrl
+++ b/lib/ssh/src/ssh_xfer.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -226,7 +226,7 @@
-record(ssh_xfer_attr,
{
- type, %% regular, dirctory, symlink, ...
+ type, %% regular, directory, symlink, ...
size,
owner,
group,
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index 54d20cf8db..908312f8de 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2021. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -98,6 +98,7 @@ RELSYSDIR = $(RELEASE_PATH)/ssh_test
INCLUDES = -I$(ERL_TOP)/lib/ssh/src
ERL_COMPILE_FLAGS += $(INCLUDES) -pa ../ebin
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -105,7 +106,7 @@ EBIN = .
# Targets
# ----------------------------------------------------
-tests debug opt: emakebuild $(TARGET_FILES)
+tests $(TYPES): emakebuild $(TARGET_FILES)
.PHONY: emakebuild
diff --git a/lib/ssh/test/property_test/ssh_eqc_client_server.erl b/lib/ssh/test/property_test/ssh_eqc_client_server.erl
index 4bfc23d5ff..432fc87900 100644
--- a/lib/ssh/test/property_test/ssh_eqc_client_server.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_client_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -299,7 +299,7 @@ do(Pid, Fun, Timeout) when is_function(Fun,0) ->
%%%----------------
%%% Start a new connection
-%%% Precondition: deamon exists
+%%% Precondition: daemon exists
ssh_open_connection_pre(S) -> S#state.servers /= [].
diff --git a/lib/ssh/test/property_test/ssh_eqc_encode_decode.erl b/lib/ssh/test/property_test/ssh_eqc_encode_decode.erl
index 843a2b5a3c..b34d36dfdb 100644
--- a/lib/ssh/test/property_test/ssh_eqc_encode_decode.erl
+++ b/lib/ssh/test/property_test/ssh_eqc_encode_decode.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -250,7 +250,7 @@ msg_code(Num) -> Name
-include_lib("ssh/src/ssh_connect.hrl").
-include_lib("ssh/src/ssh_transport.hrl").
-%%% Encoding and decodeing is asymetric so out=binary in=string. Sometimes. :(
+%%% Encoding and decoding is asymmetric so out=binary in=string. Sometimes. :(
-define(fix_asym_Xdh_reply(S),
fix_asym(#S{public_host_key = Key, h_sig = {Alg,Sig}} = M) ->
M#S{public_host_key = {Key, list_to_atom(Alg)}, h_sig = Sig}
diff --git a/lib/ssh/test/ssh_agent_mock_server.erl b/lib/ssh/test/ssh_agent_mock_server.erl
index 026bc30812..f682393252 100644
--- a/lib/ssh/test/ssh_agent_mock_server.erl
+++ b/lib/ssh/test/ssh_agent_mock_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -149,7 +149,7 @@ check_mktemp(Config) ->
end.
extract_pubkey(PrivKey) ->
- PubKey = ssh_transport:extract_public_key(PrivKey),
+ PubKey = ssh_file:extract_public_key(PrivKey),
ssh_message:ssh2_pubkey_encode(PubKey).
sig_format('ssh-rsa') -> <<"ssh-rsa">>;
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 0c6bb4365f..fa88cb4bbd 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
-module(ssh_basic_SUITE).
+-include_lib("public_key/include/public_key.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/include/file.hrl").
@@ -73,6 +74,7 @@
login_bad_pwd_no_retry3/1,
login_bad_pwd_no_retry4/1,
login_bad_pwd_no_retry5/1,
+ max_initial_idle_time/1,
misc_ssh_options/1,
multi_daemon_opt_fd/1,
openssh_zlib_basic_test/1,
@@ -154,7 +156,9 @@ groups() ->
exec, exec_compressed,
exec_with_io_out, exec_with_io_in,
cli, cli_exit_normal, cli_exit_status,
- idle_time_client, idle_time_server, openssh_zlib_basic_test,
+ idle_time_client, idle_time_server,
+ max_initial_idle_time,
+ openssh_zlib_basic_test,
misc_ssh_options, inet_option, inet6_option,
shell, shell_socket, shell_ssh_conn, shell_no_unicode, shell_unicode_string,
close
@@ -251,7 +255,7 @@ appup_test(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% 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.
+%%% if they need their own test case.
misc_ssh_options(Config) when is_list(Config) ->
SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
UserDir = proplists:get_value(priv_dir, Config),
@@ -471,6 +475,25 @@ idle_time_common(DaemonExtraOpts, ClientExtraOpts, Config) ->
ssh:stop_daemon(Pid).
%%--------------------------------------------------------------------
+max_initial_idle_time(Config) ->
+ SystemDir = filename:join(proplists:get_value(priv_dir, Config), system),
+ UserDir = proplists:get_value(priv_dir, Config),
+
+ {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
+ {user_dir, UserDir},
+ {failfun, fun ssh_test_lib:failfun/2},
+ {max_initial_idle_time, 2000}
+ ]),
+ ConnectionRef =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user_dir, UserDir},
+ {user_interaction, false}
+ ]),
+ timer:sleep(8000),
+ {error, closed} = ssh_connection:session_channel(ConnectionRef, 1000),
+ ssh:stop_daemon(Pid).
+
+%%--------------------------------------------------------------------
%%% Test that ssh:shell/2 works
shell(Config) when is_list(Config) ->
process_flag(trap_exit, true),
@@ -520,7 +543,7 @@ shell_socket(Config) when is_list(Config) ->
ct:log("~p:~p udp socket failed ok", [?MODULE,?LINE]),
gen_udp:close(BadSock),
- %% And finaly test with passive mode (which should work):
+ %% And finally test with passive mode (which should work):
IO = ssh_test_lib:start_io_server(),
{ok,Sock} = gen_tcp:connect(Host, Port, [{active,false}]),
Shell = ssh_test_lib:start_shell(Sock, IO, [{user_dir,UserDir}]),
@@ -659,7 +682,7 @@ cli_exit_status(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%%% Test that get correct error message if you try to start a daemon
-%%% on an adress that already runs a daemon see also seq10667
+%%% on an address that already runs a daemon see also seq10667
daemon_already_started(Config) when is_list(Config) ->
SystemDir = proplists:get_value(data_dir, Config),
UserDir = proplists:get_value(priv_dir, Config),
@@ -783,12 +806,14 @@ ssh_file_is_host_key(Config) ->
ct:log("Dir = ~p", [Dir]),
KnownHosts = filename:join(Dir, "known_hosts"),
- Key1 = {ed_pub,ed25519,<<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,
- 214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>},
- Key2 = {ed_pub,ed448,<<95,215,68,155,89,180,97,253,44,231,135,236,97,106,212,106,29,
- 161,52,36,133,167,14,31,138,14,167,93,128,233,103,120,237,241,
- 36,118,155,70,199,6,27,214,120,61,241,229,15,108,209,250,26,
- 190,175,232,37,97,128>>},
+ Key1 = {#'ECPoint'{point = <<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,
+ 214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>},
+ {namedCurve,?'id-Ed25519'}},
+ Key2 = {#'ECPoint'{point = <<95,215,68,155,89,180,97,253,44,231,135,236,97,106,212,106,29,
+ 161,52,36,133,167,14,31,138,14,167,93,128,233,103,120,237,241,
+ 36,118,155,70,199,6,27,214,120,61,241,229,15,108,209,250,26,
+ 190,175,232,37,97,128>>},
+ {namedCurve,?'id-Ed448'}},
Key3 = {'RSAPublicKey',26565213557098441060571713941539431805641814292761836797158846333985276408616038302348064841541244792430014595960643885863857366044141899534486816837416587694213836843799730043696945690516841209754307951050689906601353687467659852190777927968674989320642319504162787468947018505175948989102544757855693228490011564030927714896252701919941617689227585365348356580525802093985552564228730275431222515673065363441446158870936027338182083252824862151536327733046243804704721201548991176621134884093279416695997338124856506800535228380202243308550318880784741179703553922258881924287662178348044420509921666661119986374777,
65537},
@@ -831,13 +856,14 @@ ssh_file_is_host_key_misc(Config) ->
ct:log("Dir = ~p", [Dir]),
KnownHosts = filename:join(Dir, "known_hosts"),
- Key1 = {ed_pub,ed25519,<<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,
- 214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>},
- Key2 = {ed_pub,ed448,<<95,215,68,155,89,180,97,253,44,231,135,236,97,106,212,106,29,
- 161,52,36,133,167,14,31,138,14,167,93,128,233,103,120,237,241,
- 36,118,155,70,199,6,27,214,120,61,241,229,15,108,209,250,26,
- 190,175,232,37,97,128>>},
-
+ Key1 = {#'ECPoint'{point = <<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,
+ 214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>},
+ {namedCurve,?'id-Ed25519'}},
+ Key2 = {#'ECPoint'{point = <<95,215,68,155,89,180,97,253,44,231,135,236,97,106,212,106,29,
+ 161,52,36,133,167,14,31,138,14,167,93,128,233,103,120,237,241,
+ 36,118,155,70,199,6,27,214,120,61,241,229,15,108,209,250,26,
+ 190,175,232,37,97,128>>},
+ {namedCurve,?'id-Ed448'}},
FileContents = <<"h11,h12,!h12 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIElI66JgZZo72XJ7wGBp+h3WTDw/pxXddvaomAIHrIl9\n",
%% Key revoked later in file:
"h22 ssh-ed448 AAAACXNzaC1lZDQ0OAAAADlf10SbWbRh/Sznh+xhatRqHaE0JIWnDh"
@@ -871,13 +897,14 @@ ssh_file_is_auth_key(Config) ->
ct:log("Dir = ~p", [Dir]),
AuthKeys = filename:join(Dir, "authorized_keys"),
- Key1 = {ed_pub,ed25519,<<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,
- 214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>},
- Key2 = {ed_pub,ed448,<<95,215,68,155,89,180,97,253,44,231,135,236,97,106,212,106,29,
- 161,52,36,133,167,14,31,138,14,167,93,128,233,103,120,237,241,
- 36,118,155,70,199,6,27,214,120,61,241,229,15,108,209,250,26,
- 190,175,232,37,97,128>>},
-
+ Key1 = {#'ECPoint'{point = <<73,72,235,162,96,101,154,59,217,114,123,192,96,105,250,29,
+ 214,76,60,63,167,21,221,118,246,168,152,2,7,172,137,125>>},
+ {namedCurve,?'id-Ed25519'}},
+ Key2 = {#'ECPoint'{point = <<95,215,68,155,89,180,97,253,44,231,135,236,97,106,212,106,29,
+ 161,52,36,133,167,14,31,138,14,167,93,128,233,103,120,237,241,
+ 36,118,155,70,199,6,27,214,120,61,241,229,15,108,209,250,26,
+ 190,175,232,37,97,128>>},
+ {namedCurve,?'id-Ed448'}},
FileContents = <<" \n",
"# A test file\n",
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIElI66JgZZo72XJ7wGBp+h3WTDw/pxXddvaomAIHrIl9 foo@example.com\n",
@@ -1204,7 +1231,7 @@ packet_size(Config) ->
rec(Server, Conn, Ch, MaxSz) ->
receive
- {ssh_cm,Conn,{data,Ch,_,M}} when size(M) =< MaxSz ->
+ {ssh_cm,Conn,{data,Ch,_,M}} when byte_size(M) =< MaxSz ->
ct:log("~p: ~p",[MaxSz,M]),
rec(Server, Conn, Ch, MaxSz);
{ssh_cm,Conn,{data,Ch,_,_}} = M ->
@@ -1393,7 +1420,7 @@ login_bad_pwd_no_retry(Config, AuthMethods) ->
{ok,Conn} ->
ssh:close(Conn),
ssh:stop_daemon(DaemonRef),
- {fail, "Connect erroneosly succeded"}
+ {fail, "Connect erroneosly succeeded"}
end
end.
@@ -1465,7 +1492,7 @@ setopts_getopts(Config) ->
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
%% Due to timing the error message may or may not be delivered to
-%% the "tcp-application" before the socket closed message is recived
+%% the "tcp-application" before the socket closed message is received
check_error("Invalid state") -> ok;
check_error("Connection closed") -> ok;
check_error("Selection of key exchange algorithm failed"++_) -> ok;
@@ -1515,7 +1542,7 @@ new_do_shell(IO, N, [new_prompt|More]) ->
new_do_shell(IO, N, Ops=[{Order,Arg}|More]) ->
Pfx = prompt_prefix(),
- PfxSize = size(Pfx),
+ PfxSize = byte_size(Pfx),
receive
_X = <<"\r\n">> ->
ct:log("Skip newline ~p",[_X]),
@@ -1582,7 +1609,7 @@ prompt_prefix() ->
new_do_shell_prompt(IO, N, type, Str, More) ->
ct:log("Matched prompt ~p to trigger sending of next line to server",[N]),
IO ! {input, self(), Str++"\r\n"},
- ct:log("Promt '~p> ', Sent ~ts",[N,Str++"\r\n"]),
+ ct:log("Prompt '~p> ', Sent ~ts",[N,Str++"\r\n"]),
new_do_shell(IO, N, More);
new_do_shell_prompt(IO, N, Op, Str, More) ->
ct:log("Matched prompt ~p",[N]),
diff --git a/lib/ssh/test/ssh_chan_behaviours_SUITE.erl b/lib/ssh/test/ssh_chan_behaviours_SUITE.erl
index df37918228..c0ab325126 100644
--- a/lib/ssh/test/ssh_chan_behaviours_SUITE.erl
+++ b/lib/ssh/test/ssh_chan_behaviours_SUITE.erl
@@ -104,7 +104,7 @@ end_per_testcase(_TC, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-%% Try start a subsystem whos name is not known by the server
+%% Try start a subsystem whose name is not known by the server
noexist_subsystem(Config) ->
C = proplists:get_value(connref, Config),
{ok, Ch} = ssh_connection:session_channel(C, infinity),
@@ -135,7 +135,7 @@ defined_subsystem(Config) ->
?EXPECT({ssh_cm, C, {closed,Ch1}}, []), % self() is instead of a proper channel handler
ok.
-%% Try to start and stop a subsystem from a ssh_client_channel behviour
+%% Try to start and stop a subsystem from a ssh_client_channel behaviour
subsystem_client(Config) ->
C = proplists:get_value(connref, Config),
diff --git a/lib/ssh/test/ssh_compat_SUITE.erl b/lib/ssh/test/ssh_compat_SUITE.erl
index 56127e98e2..0b1357ca05 100644
--- a/lib/ssh/test/ssh_compat_SUITE.erl
+++ b/lib/ssh/test/ssh_compat_SUITE.erl
@@ -80,7 +80,7 @@ groups() ->
ssh_image_versions() ->
try
%% Find all useful containers in such a way that undefined command, too low
- %% priviliges, no containers and containers found give meaningful result:
+ %% privileges, no containers and containers found give meaningful result:
L0 = ["REPOSITORY"++_|_] = string:tokens(os:cmd("docker images"), "\r\n"),
[["REPOSITORY","TAG"|_]|L1] = [string:tokens(E, " ") || E<-L0],
[list_to_atom(V) || [?DOCKER_PFX,V|_] <- L1]
@@ -151,7 +151,7 @@ init_per_group(G, Config0) ->
ct:comment("~s",[NewCmnt])
end,
AuthMethods =
- %% This should be obtained by quering the peer, but that
+ %% This should be obtained by querying the peer, but that
%% is a bit hard. It is possible with ssh_protocol_SUITE
%% techniques, but it can wait.
case Vssh of
@@ -409,7 +409,7 @@ send_recv_big_with_renegotiate_otp_is_client(Config) ->
Data = << <<X:32>> || X <- lists:seq(1, HalfSizeBytes div 4)>>,
%% Send the data. Must spawn a process to avoid deadlock. The client will block
- %% until all is sent through the send window. But the server will stop receiveing
+ %% until all is sent through the send window. But the server will stop receiving
%% when the servers send-window towards the client is full.
%% Since the client can't receive before the server has received all but 655k from the client
%% ssh_connection:send/4 is blocking...
@@ -875,7 +875,7 @@ new_dir(Config) ->
%%--------------------------------------------------------------------
%%
-%% Find the intersection of algoritms for otp ssh and the docker ssh.
+%% Find the intersection of algorithms for otp ssh and the docker ssh.
%% Returns {ok, ServerHello, Server, ClientHello, Client} where Server are the algorithms common
%% with the docker server and analogous for Client.
%%
@@ -1097,7 +1097,7 @@ receive_hello(S, Ack) ->
receive_kexinit(_S, <<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>)
- when PacketLen < 5000, % heuristic max len to stop huge attempts if packet decodeing get out of sync
+ when PacketLen < 5000, % heuristic max len to stop huge attempts if packet decoding get out of sync
size(PayloadAndPadding) >= (PacketLen-1) % Need more bytes?
->
ct:log("Has all ~p packet bytes",[PacketLen]),
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index 1e79f0a622..06d90cc036 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -209,7 +209,7 @@ end_per_suite(_Config) ->
init_per_group(openssh, Config) ->
case ssh_test_lib:gen_tcp_connect(?SSH_DEFAULT_PORT, []) of
{error,econnrefused} ->
- {skip,"No openssh deamon (econnrefused)"};
+ {skip,"No openssh daemon (econnrefused)"};
{ok, Socket} ->
gen_tcp:close(Socket),
ssh_test_lib:openssh_sanity_check(Config)
@@ -368,7 +368,7 @@ connect4_invalid_two_1(Config) ->
ssh:stop_daemon(Pid).
connect4_invalid_two_2(Config) ->
- {Pid, Host, Port, _UserDir} = daemon_start(Config),
+ {Pid, Host, _Port, _UserDir} = daemon_start(Config),
%% Actual error implementation dependent
{error, _} =
@@ -380,7 +380,7 @@ connect4_invalid_two_2(Config) ->
%% All three args incorrect
connect4_invalid_three(Config) ->
- {Pid, Host, Port, _UserDir} = daemon_start(Config),
+ {Pid, Host, _Port, _UserDir} = daemon_start(Config),
%% Actual error implementation dependent
{error, _} =
@@ -679,7 +679,7 @@ do_interrupted_send(Config, SendSize, EchoSize) ->
ct:log("~p:~p got expected data",[?MODULE,?LINE]),
ok;
Other ->
- ct:log("~p:~p unexpect: ~p", [?MODULE,?LINE,Other]),
+ ct:log("~p:~p unexpected: ~p", [?MODULE,?LINE,Other]),
{fail,"unexpected result in listener"}
catch
Class:Exception ->
@@ -1236,7 +1236,7 @@ start_shell_sock_daemon_exec_multi(Config) ->
receive
{ssh_cm, ConnectionRef, {data, _ChannelId, 0, <<"echo testing\n">>}} ->
Parent ! {answer_received,self()},
- ct:log("~p:~p: recevied result on connection ~p", [?MODULE,?LINE,ConnectionRef])
+ ct:log("~p:~p: received result on connection ~p", [?MODULE,?LINE,ConnectionRef])
after 5000 ->
ct:fail("Exec Timeout")
end
diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl
index 82c8b956c9..c02b20d6a2 100644
--- a/lib/ssh/test/ssh_options_SUITE.erl
+++ b/lib/ssh/test/ssh_options_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
auth_method_kb_interactive_data_tuple/1,
auth_method_kb_interactive_data_fun3/1,
auth_method_kb_interactive_data_fun4/1,
+ auth_none/1,
connectfun_disconnectfun_client/1,
disconnectfun_option_client/1,
disconnectfun_option_server/1,
@@ -45,6 +46,7 @@
id_string_own_string_server_trail_space/1,
id_string_random_client/1,
id_string_random_server/1,
+ max_log_item_len/1,
max_sessions_sftp_start_channel_parallel/1,
max_sessions_sftp_start_channel_sequential/1,
max_sessions_ssh_connect_parallel/1,
@@ -82,7 +84,11 @@
save_accepted_host_option/1,
raw_option/1,
config_file/1,
- config_file_modify_algorithms_order/1
+ config_file_modify_algorithms_order/1,
+ daemon_replace_options_simple/1,
+ daemon_replace_options_algs/1,
+ daemon_replace_options_algs_connect/1,
+ daemon_replace_options_algs_conf_file/1
]).
%%% Common test callbacks
@@ -92,6 +98,10 @@
init_per_testcase/2, end_per_testcase/2
]).
+%%% For test nodes
+-export([get_preferred_algorithms/2
+ ]).
+
-define(NEWLINE, <<"\r\n">>).
%%--------------------------------------------------------------------
@@ -114,6 +124,7 @@ all() ->
auth_method_kb_interactive_data_tuple,
auth_method_kb_interactive_data_fun3,
auth_method_kb_interactive_data_fun4,
+ auth_none,
{group, dir_options},
ssh_connect_timeout,
ssh_connect_arg4_timeout,
@@ -139,10 +150,15 @@ all() ->
id_string_own_string_server,
id_string_own_string_server_trail_space,
id_string_random_server,
+ max_log_item_len,
save_accepted_host_option,
raw_option,
config_file,
config_file_modify_algorithms_order,
+ daemon_replace_options_simple,
+ daemon_replace_options_algs,
+ daemon_replace_options_algs_connect,
+ daemon_replace_options_algs_conf_file,
{group, hardening_tests}
].
@@ -574,6 +590,30 @@ amkid(Config, {ExpectName,ExpectInstr,ExpectPrompts,ExpectEcho}, OptVal) ->
{"bar",2}]).
%%--------------------------------------------------------------------
+auth_none(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ SysDir = proplists:get_value(data_dir, Config),
+ {DaemonRef, Host, Port} =
+ ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {auth_methods, "password"}, % to make even more sure we don't use public-key-auth
+ {user_passwords, [{"foo","somepwd"}]}, % Not to be used
+ {no_auth_needed, true} % we test this
+ ]),
+ ClientConnRef1 =
+ ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
+ {user, "some-other-user"},
+ {password, "wrong-pwd"},
+ {user_dir, UserDir},
+ {user_interaction, false}]),
+ "some-other-user" =
+ proplists:get_value(user, ssh:connection_info(ClientConnRef1, [user])),
+ ok = ssh:close(ClientConnRef1),
+ ok = ssh:stop_daemon(DaemonRef).
+
+%%--------------------------------------------------------------------
system_dir_option(Config) ->
DirUnread = proplists:get_value(unreadable_dir,Config),
FileRead = proplists:get_value(readable_file,Config),
@@ -1352,6 +1392,67 @@ one_shell_op(IO, TimeOut) ->
end.
%%--------------------------------------------------------------------
+max_log_item_len(Config) ->
+ %% Find a supported algorithm (to be removed from the daemon):
+ {ok, {Type,Alg}} = select_alg( ssh:default_algorithms() ),
+
+ %% Start a test daemon without support for {Type,Alg}
+ SystemDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(priv_dir, Config),
+ {_Pid, Host0, Port} =
+ ssh_test_lib:daemon([
+ {system_dir, SystemDir},
+ {user_dir, UserDir},
+ {user_passwords, [{"carni", "meat"}]},
+ {modify_algorithms, [{rm, [{Type,[Alg]}]}]},
+ {max_log_item_len, 10}
+ ]),
+ Host = ssh_test_lib:mangle_connect_address(Host0),
+ ct:log("~p:~p Listen ~p:~p. Mangled Host = ~p",
+ [?MODULE,?LINE,Host0,Port,Host]),
+
+ {ok,ReportHandlerPid} = ssh_eqc_event_handler:add_report_handler(),
+
+ %% Connect to it with the {Type,Alg} to force a failure and log entry:
+ {error,_} = R =
+ ssh:connect(Host, Port,
+ [{preferred_algorithms, [{Type,[Alg]}]},
+ {max_log_item_len, 10},
+ {silently_accept_hosts, true},
+ {save_accepted_host, false},
+ {user_dir, UserDir},
+ {user_interaction, false},
+ {user, "carni"},
+ {password, "meat"}
+ ]),
+
+ {ok, Reports} = ssh_eqc_event_handler:get_reports(ReportHandlerPid),
+ ct:log("~p:~p ssh:connect -> ~p~n~p", [?MODULE,?LINE,R,Reports]),
+
+ [ok] =
+ lists:usort(
+ [check_skip_part(
+ string:tokens(
+ lists:flatten(io_lib:format(Fmt,Args)),
+ " \n"))
+ || {info_msg,_,{_,Fmt,Args}} <- Reports]
+ ).
+
+
+check_skip_part(["Disconnect","...","("++_NumSkipped, "bytes","skipped)"]) ->
+ ok;
+check_skip_part([_|T]) ->
+ check_skip_part(T);
+check_skip_part([]) ->
+ error.
+
+select_alg([{Type,[A,_|_]}|_]) when is_atom(A) -> {ok, {Type,A}};
+select_alg([{Type,[{Dir,[A,_|_]}, _]}|_]) when is_atom(A), is_atom(Dir) -> {ok, {Type,A}};
+select_alg([{Type,[_,{Dir,[A,_|_]}]}|_]) when is_atom(A), is_atom(Dir) -> {ok, {Type,A}};
+select_alg([_|Algs]) -> select_alg(Algs);
+select_alg([]) -> false.
+
+%%--------------------------------------------------------------------
max_sessions_ssh_connect_parallel(Config) ->
max_sessions(Config, true, connect_fun(ssh__connect,Config)).
max_sessions_ssh_connect_sequential(Config) ->
@@ -1412,7 +1513,7 @@ max_sessions(Config, ParallelLogin, Connect0) when is_function(Connect0,2) ->
ct:log("Connections up: ~p",[Connections]),
[_|_] = Connections,
- %% N w try one more than alowed:
+ %% N w try one more than allowed:
ct:pal("Info Report expected here (if not disabled) ...",[]),
try Connect(Host,Port)
of
@@ -1442,7 +1543,7 @@ try_to_connect(Connect, Host, Port, Pid, Tref, N) ->
of
_ConnectionRef1 ->
timer:cancel(Tref),
- ct:log("Step 3 ok: could set up one more connection after killing one. Thats good.",[]),
+ ct:log("Step 3 ok: could set up one more connection after killing one. That's good.",[]),
ssh:stop_daemon(Pid),
receive % flush.
timeout_no_connection -> ok
@@ -1611,30 +1712,24 @@ config_file(Config) ->
[{_,[Ch1|_]}|_] = proplists:get_value(cipher, CommonAlgs),
%% Make config file:
- Contents =
- [{ssh, [{preferred_algorithms,
- [{cipher, [Ch1]},
- {kex, [K1a]}
- ] ++ AdjustClient},
- {client_options,
- [{modify_algorithms,
- [{rm, [{kex, [K1a]}]},
- {append, [{kex, [K1b]}]}
+ {ok,ConfFile} =
+ make_config_file_in_privdir(
+ "c2.config", Config,
+ [{ssh, [{preferred_algorithms,
+ [{cipher, [Ch1]},
+ {kex, [K1a]}
+ ] ++ AdjustClient},
+ {client_options,
+ [{modify_algorithms,
+ [{rm, [{kex, [K1a]}]},
+ {append, [{kex, [K1b]}]}
+ ]}
]}
]}
- ]}
- ],
- %% write the file:
- PrivDir = proplists:get_value(priv_dir, Config),
- ConfFile = filename:join(PrivDir,"c2.config"),
- {ok,D} = file:open(ConfFile, [write]),
- io:format(D, "~p.~n", [Contents]),
- file:close(D),
- {ok,Cnfs} = file:read_file(ConfFile),
- ct:log("c2.config:~n~s", [Cnfs]),
+ ]),
%% Start the slave node with the configuration just made:
- {ok,Node} = start_node(random_node_name(?MODULE), ConfFile),
+ {ok, Peer, Node} = ?CT_PEER(["-config", ConfFile]),
R0 = rpc:call(Node, ssh, default_algorithms, []),
ct:log("R0 = ~p",[R0]),
@@ -1679,7 +1774,7 @@ config_file(Config) ->
{options,Os2} = rpc:call(Node, ssh, connection_info, [C2, options]),
ct:log("C2 opts:~n~p~n~nalgorithms:~n~p~n~noptions:~n~p", [C2_Opts,As2,Os2]),
- stop_node_nice(Node)
+ peer:stop(Peer)
end.
%%%----------------------------------------------------------------
@@ -1703,36 +1798,30 @@ config_file_modify_algorithms_order(Config) ->
[{_,[Ch1|_]}|_] = proplists:get_value(cipher, CommonAlgs),
%% Make config file:
- Contents =
- [{ssh, [{preferred_algorithms,
- [{cipher, [Ch1]},
- {kex, [K1]}
- ]},
- {server_options,
- [{modify_algorithms,
- [{rm, [{kex, [K1]}]},
- {append, [{kex, [K2]}]}
- ]}
- ]},
- {client_options,
- [{modify_algorithms,
- [{rm, [{kex, [K1]}]},
- {append, [{kex, [K3]}]}
+ {ok, ConfFile} =
+ make_config_file_in_privdir(
+ "c3.config", Config,
+ [{ssh, [{preferred_algorithms,
+ [{cipher, [Ch1]},
+ {kex, [K1]}
+ ]},
+ {server_options,
+ [{modify_algorithms,
+ [{rm, [{kex, [K1]}]},
+ {append, [{kex, [K2]}]}
+ ]}
+ ]},
+ {client_options,
+ [{modify_algorithms,
+ [{rm, [{kex, [K1]}]},
+ {append, [{kex, [K3]}]}
+ ]}
]}
]}
- ]}
- ],
- %% write the file:
- PrivDir = proplists:get_value(priv_dir, Config),
- ConfFile = filename:join(PrivDir,"c3.config"),
- {ok,D} = file:open(ConfFile, [write]),
- io:format(D, "~p.~n", [Contents]),
- file:close(D),
- {ok,Cnfs} = file:read_file(ConfFile),
- ct:log("c3.config:~n~s", [Cnfs]),
+ ]),
%% Start the slave node with the configuration just made:
- {ok,Node} = start_node(random_node_name(?MODULE), ConfFile),
+ {ok, Peer, Node} = ?CT_PEER(["-config", ConfFile]),
R0 = rpc:call(Node, ssh, default_algorithms, []),
ct:log("R0 = ~p",[R0]),
@@ -1769,32 +1858,184 @@ config_file_modify_algorithms_order(Config) ->
ConnOptions = proplists:get_value(options, ConnInfo),
ConnPrefAlgs = proplists:get_value(preferred_algorithms, ConnOptions),
- %% And now, are all levels appied in right order:
+ %% And now, are all levels applied in right order:
[K3,K2] = proplists:get_value(kex, ConnPrefAlgs),
- stop_node_nice(Node)
+ peer:stop(Peer)
end.
%%--------------------------------------------------------------------
-%% Internal functions ------------------------------------------------
+daemon_replace_options_simple(Config) ->
+ SysDir = proplists:get_value(data_dir, Config),
+
+ UserDir1 = proplists:get_value(user_dir, Config),
+ UserDir2 = filename:join(UserDir1, "foo"),
+ file:make_dir(UserDir2),
+
+ {Pid, _Host, _Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir1}
+ ]),
+ {ok,Opts1} = ssh:daemon_info(Pid),
+ UserDir1 = proplists:get_value(user_dir, proplists:get_value(options,Opts1,[])),
+
+ {ok, Pid} = ssh:daemon_replace_options(Pid, [{user_dir,UserDir2}]),
+ {ok,Opts2} = ssh:daemon_info(Pid),
+ case proplists:get_value(user_dir, proplists:get_value(options,Opts2,[])) of
+ UserDir2 ->
+ ok;
+ UserDir1 ->
+ ct:log("~p:~p Got old value ~p~nExpected ~p", [?MODULE,?LINE,UserDir1,UserDir2]),
+ {fail, "Not changed"};
+ Other ->
+ ct:log("~p:~p Got ~p~nExpected ~p", [?MODULE,?LINE,Other,UserDir2]),
+ {fail, "Strange value"}
+ end.
+
+%%--------------------------------------------------------------------
+daemon_replace_options_algs(Config) ->
+ SysDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(user_dir, Config),
+
+ DefaultKex =
+ ssh_transport:default_algorithms(kex),
+ NonDefaultKex =
+ ssh_transport:supported_algorithms(kex) -- DefaultKex,
+
+ case NonDefaultKex of
+ [A1|_] ->
+ [A2,A3|_] = DefaultKex,
+ {Pid, _Host, _Port} = ssh_test_lib:daemon([{system_dir, SysDir},
+ {user_dir, UserDir},
+ {preferred_algorithms,[{kex,[A1]}]}
+ ]),
+ [A1] = get_preferred_algorithms(Pid, kex),
+ {ok, Pid} =
+ ssh:daemon_replace_options(Pid, [{modify_algorithms,
+ [{prepend,[{kex,[A2]}]}]
+ }
+ ]),
+ [A2,A1] = get_preferred_algorithms(Pid, kex),
+
+ {ok, Pid} =
+ ssh:daemon_replace_options(Pid, [{preferred_algorithms,[{kex,[A3]}]
+ }
+ ]),
+ [A2,A3] = get_preferred_algorithms(Pid, kex)
+ ;
+ [] ->
+ {skip, "No non-default kex"}
+ end.
+
%%--------------------------------------------------------------------
+daemon_replace_options_algs_connect(Config) ->
+ [A1,A2|_] =
+ ssh_transport:default_algorithms(kex),
+
+ {Pid, Host, Port} =
+ ssh_test_lib:std_daemon(Config,
+ [{preferred_algorithms,[{kex,[A1]}]}
+ ]),
+ [A1] = get_preferred_algorithms(Pid, kex),
+
+ %% Open a connection with A1 as kex and test it
+ C1 =
+ ssh_test_lib:std_connect(Config, Host, Port,
+ [{preferred_algorithms,[{kex,[A1]}]}
+ ]),
+ ok = test_connection(C1),
+ ok = test_not_connect(Config, Host, Port,
+ [{preferred_algorithms,[{kex,[A2]}]}
+ ]),
+
+ %% Change kex to A2
+ {ok, Pid} =
+ ssh:daemon_replace_options(Pid,
+ [{preferred_algorithms,[{kex,[A2]}]}]),
+ [A2] = get_preferred_algorithms(Pid, kex),
+
+ %% and open the second connection with this kex, and test it
+ C2 =
+ ssh_test_lib:std_connect(Config, Host, Port,
+ [{preferred_algorithms,[{kex,[A2]}]}
+ ]),
+ ok = test_connection(C2),
+ ok = test_not_connect(Config, Host, Port,
+ [{preferred_algorithms,[{kex,[A1]}]}
+ ]),
+
+ %% Test that the first connection is still alive:
+ ok = test_connection(C1),
+
+ ssh:close(C1),
+ ssh:close(C2),
+ ssh:stop_daemon(Pid).
-start_node(Name, ConfigFile) ->
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args,
- " -pa " ++ Pa ++
- " -config " ++ ConfigFile}]).
+%%--------------------------------------------------------------------
+daemon_replace_options_algs_conf_file(Config) ->
+ SysDir = proplists:get_value(data_dir, Config),
+ UserDir = proplists:get_value(user_dir, Config),
-stop_node_nice(Node) when is_atom(Node) ->
- test_server:stop_node(Node).
+ DefaultKex =
+ ssh_transport:default_algorithms(kex),
+ NonDefaultKex =
+ ssh_transport:supported_algorithms(kex) -- DefaultKex,
-random_node_name(BaseName) ->
- L = integer_to_list(erlang:unique_integer([positive])),
- lists:concat([BaseName,"___",L]).
+ case NonDefaultKex of
+ [A0,A1|_] ->
+ %% Make config file:
+ {ok,ConfFile} =
+ make_config_file_in_privdir(
+ "c4.config", Config,
+ [{ssh, [{modify_algorithms,
+ %% Whatever happens, always put A0 first in the kex list:
+ [{prepend, [{kex, [A0]}]}
+ ]}
+ ]}
+ ]),
+
+ [A2|_] = DefaultKex,
+ ct:log("[A0, A1, A2] = ~p", [[A0, A1, A2]]),
+
+ %% Start the slave node with the configuration just made:
+ {ok, Peer, Node} = ?CT_PEER(["-config", ConfFile]),
+
+ %% Start ssh on the slave. This should apply the ConfFile:
+ rpc:call(Node, ssh, start, []),
+
+ {Pid, _Host, _Port} =
+ rpc:call(Node, ssh_test_lib, daemon,
+ [
+ [{system_dir, SysDir},
+ {user_dir, UserDir},
+ {preferred_algorithms,[{kex,[A1]}]}
+ ]
+ ]),
+
+ [A0,A1] =
+ rpc:call(Node, ?MODULE, get_preferred_algorithms, [Pid, kex]),
+ {ok, Pid} =
+ rpc:call(Node, ssh, daemon_replace_options,
+ [Pid,
+ [{modify_algorithms,
+ [{prepend,[{kex,[A2]}]}]
+ }
+ ]
+ ]),
+
+ %% Check that the precedens order is fulfilled:
+ [A2,A0,A1] =
+ rpc:call(Node, ?MODULE, get_preferred_algorithms, [Pid, kex]),
+
+ peer:stop(Peer);
+ [] ->
+ {skip, "No non-default kex"}
+ end.
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
-%%%----
-
expected_ssh_vsn(Str) ->
try
{ok,L} = application:get_all_key(ssh),
@@ -1804,7 +2045,7 @@ expected_ssh_vsn(Str) ->
"\r\n" -> true;
_ -> false
catch
- _:_ -> true %% ssh not started so we dont't know
+ _:_ -> true %% ssh not started so we don't know
end.
@@ -1831,3 +2072,42 @@ fake_daemon(_Config) ->
after
10000 -> ct:fail("timeout ~p:~p",[?MODULE,?LINE])
end.
+
+
+make_config_file_in_privdir(FileName, Config, Contents) ->
+ %% write the file:
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ConfFile = filename:join(PrivDir, FileName),
+ {ok,D} = file:open(ConfFile, [write]),
+ io:format(D, "~p.~n", [Contents]),
+ file:close(D),
+ {ok,Cnfs} = file:read_file(ConfFile),
+ ct:log("Config file ~p :~n~s", [ConfFile,Cnfs]),
+ {ok,ConfFile}.
+
+
+get_preferred_algorithms(Pid, Type) ->
+ {ok,#{preferred_algorithms:=As}} = ssh_system_sup:get_acceptor_options(Pid),
+ proplists:get_value(Type, As).
+
+test_connection(C) ->
+ {ok, Ch} = ssh_connection:session_channel(C, infinity),
+ A = rand:uniform(100),
+ B = rand:uniform(100),
+ A_plus_B = lists:concat([A,"+",B,"."]),
+ Sum = integer_to_binary(A+B),
+ success = ssh_connection:exec(C, Ch, A_plus_B, infinity),
+ expected = ssh_test_lib:receive_exec_result(
+ {ssh_cm, C, {data, Ch, 0, Sum}} ),
+ ssh_test_lib:receive_exec_end(C, Ch),
+ ok.
+
+test_not_connect(Config, Host, Port, Opts) ->
+ try
+ ssh_test_lib:std_connect(Config, Host, Port, Opts)
+ of
+ Cx when is_pid(Cx) -> {error, connected}
+ catch
+ error:{badmatch, {error,_}} -> ok
+ end.
+
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 7e94bf60c7..666ac76f63 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -717,7 +717,7 @@ client_info_line(Config) ->
%%% The server does not send the extension because
%%% the client does not tell the server to send it
no_ext_info_s1(Config) ->
- %% Start the dameon
+ %% Start the daemon
Server = {Pid,_,_} = ssh_test_lib:daemon([{send_ext_info,true},
{system_dir, system_dir(Config)}]),
{ok,AfterKexState} = connect_and_kex([{server,Server}|Config]),
@@ -732,7 +732,7 @@ no_ext_info_s1(Config) ->
%%% The server does not send the extension because
%%% the server is not configured to send it
no_ext_info_s2(Config) ->
- %% Start the dameon
+ %% Start the daemon
Server = {Pid,_,_} = ssh_test_lib:daemon([{send_ext_info,false},
{system_dir, system_dir(Config)}]),
{ok,AfterKexState} = connect_and_kex([{extra_options,[{recv_ext_info,true}]},
@@ -748,7 +748,7 @@ no_ext_info_s2(Config) ->
%%%--------------------------------------------------------------------
%%% The server sends the extension
ext_info_s(Config) ->
- %% Start the dameon
+ %% Start the daemon
Server = {Pid,_,_} = ssh_test_lib:daemon([{send_ext_info,true},
{system_dir, system_dir(Config)}]),
{ok,AfterKexState} = connect_and_kex([{extra_options,[{recv_ext_info,true}]},
@@ -903,8 +903,6 @@ modify_combo(Config) ->
%%%----------------------------------------------------------------
%%%
-client_close_after_hello() -> [{timetrap,{seconds,80}}].
-
client_close_after_hello(Config0) ->
MaxSessions = 20,
SleepSec = 15,
@@ -913,7 +911,7 @@ client_close_after_hello(Config0) ->
{negotiation_timeout,SleepSec*1000}
]),
- {Parents0, Conns0, []} = find_handshake_parent(server_port(Config)),
+ {_Parents0, Conns0, []} = find_handshake_parent(server_port(Config)),
Cs =
[ssh_trpt_test_lib:exec(
@@ -984,7 +982,7 @@ chk_pref_algs(Config,
ExpectedKex,
ExpectedCiphers,
ServerPrefOpts) ->
- %% Start the dameon
+ %% Start the daemon
case ssh_test_lib:daemon(
[{send_ext_info,false},
{recv_ext_info,false},
@@ -1103,7 +1101,7 @@ std_connect({Host,Port}, Config, Opts) ->
std_connect(Host, Port, Config, Opts) ->
{User,Pwd} = server_user_password(Config),
ssh:connect(Host, Port,
- %% Prefere User's Opts to the default opts
+ %% Prefer User's Opts to the default opts
[O || O = {Tag,_} <- [{user,User},{password,Pwd},
{silently_accept_hosts, true},
{save_accepted_host, false},
diff --git a/lib/ssh/test/ssh_pubkey_SUITE.erl b/lib/ssh/test/ssh_pubkey_SUITE.erl
index 81c32e0197..7eca2619db 100644
--- a/lib/ssh/test/ssh_pubkey_SUITE.erl
+++ b/lib/ssh/test/ssh_pubkey_SUITE.erl
@@ -85,7 +85,8 @@
ssh_hostkey_fingerprint_sha512/1,
ssh_hostkey_fingerprint_list/1,
- chk_known_hosts/1
+ chk_known_hosts/1,
+ ssh_hostkey_pkcs8/1
]).
-include_lib("common_test/include/ct.hrl").
@@ -106,6 +107,7 @@ all() ->
{group, option_space},
{group, ssh_hostkey_fingerprint},
{group, ssh_public_key_decode_encode},
+ {group, pkcs8},
chk_known_hosts
].
@@ -146,6 +148,7 @@ groups() ->
{old_format, [], [check_dsa_disabled, check_rsa_sha1_disabled | ?tests_old++[{group,passphrase}] ]},
{passphrase, [], ?tests_old},
{option_space,[], [{group,new_format}]},
+ {pkcs8, [], [ssh_hostkey_pkcs8]},
{ssh_hostkey_fingerprint, [],
[ssh_hostkey_fingerprint_md5_implicit,
@@ -192,6 +195,11 @@ init_per_group(old_format, Config) ->
[{fmt,old_format},
{key_src_dir,Dir} | Config];
+init_per_group(pkcs8, Config) ->
+ Dir = filename:join(proplists:get_value(data_dir,Config), "pkcs8"),
+ [{fmt,pkcs8},
+ {key_src_dir,Dir} | Config];
+
init_per_group(option_space, Config) ->
extend_optsL([client_opts,daemon_opts],
[{key_cb, {ssh_file, [{optimize, space}]}}],
@@ -237,6 +245,8 @@ end_per_group(_, Config) ->
Config.
%%%----------------------------------------------------------------
+init_per_testcase(ssh_hostkey_pkcs8, Config0) ->
+ setup_user_system_dir(rsa_sha2, rsa_sha2, Config0);
init_per_testcase(connect_rsa_sha2_to_rsa_sha2, Config0) ->
setup_user_system_dir(rsa_sha2, rsa_sha2, Config0);
init_per_testcase(connect_rsa_sha1_to_dsa, Config0) ->
@@ -427,6 +437,12 @@ check_rsa_sha1_disabled(Config) ->
%%%----------------------------------------------------------------
%% Check of different host keys left to later
+ssh_hostkey_pkcs8(Config) ->
+ try_connect(Config).
+
+%%%----------------------------------------------------------------
+
+%% Check of different host keys left to later
ssh_hostkey_fingerprint_md5_implicit(_Config) ->
Expected = "4b:0b:63:de:0f:a7:3a:ab:2c:cc:2d:d1:21:37:1d:3a",
Expected = ssh:hostkey_fingerprint(ssh_hostkey(rsa)).
@@ -836,8 +852,8 @@ chk_known_hosts(Config) ->
%%%----------------------------------------------------------------
-try_connect({skip,Reson}) ->
- {skip,Reson};
+try_connect({skip,Reason}) ->
+ {skip,Reason};
try_connect(Config) ->
SystemDir = proplists:get_value(system_dir, Config),
UserDir = proplists:get_value(user_dir, Config),
diff --git a/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa
new file mode 100644
index 0000000000..b0453eb4e2
--- /dev/null
+++ b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2d3XMIA8GTEQc
+UFCOm31M5jt6lGjN61ZYGnXBVBjEcyJynB7Y3C437cDpjmvbSWF1oSVVDTwMERwn
+XzixLG//7w8K7i6aJLKpHKtS91qnrQidmrUWDnQ4kx8AZxaN46nhSsf+cZ0nKp03
+ZjjR5WxeDimiDLsSUbdDmFE6ZsL2+k5OStvcqu/skUVfPe+FGTGJgIw3DyErxM7J
+72jUkLJXMiZkYbB1QD05k3g2LOiPqJ73QoJVGgj7YagTSA3Lgy3s/6U7IMHMV4ls
+aXShv1Lk/eCfIJVSaVXQRjV9KKM3wgg6PmWqwGkAO36w3eJiW1kmYKfnAM/+I5Gf
+o/TiNZTXAgMBAAECggEAeWdwfDmUZZdW9hPGFayFKSZCyuN1/BSqZYJteQ2QUR1d
+/S29JIMTSWkqovt87fGcI9ztbvKYUlsMBXJI0TGE75/KvXYOkcb7DKQjpdcofUoW
+4m4uMJe7Ym0ZAnaUviGNRXYxLS3A529mHZcpFRb2DHqV3tljmuO98P6mhRocfKCc
+3p/T4+LIGlRlov5lOP/oKkeILF1m04J/SjptTtNo81xne9/dCGTiOTXjS8QMslCc
+8Xyy0Go9Zr0d+YzsI2NYF2aFBce0fDwK0Xpptr0FEL8UxjHjeK0T2GSDqncmtKoA
+3+BnpEJcuiDqZBi20lX7LygtNe9uVPZjdz1iOeKAaQKBgQDZjj6yOwbDeXkedD0I
+25RC8lmCWhV381PDz9RdeRXVC50jq3OYwmdcDEIK23YNWU8GoUnvi7B1aljSfAUm
+yUSnixXpU+/ZOkGYA48MHpC1DxJeEVZDu+MFWHmTCXctQNUj40gAKhozJm5Lo33s
+Wnhr+Yq2CP65w6R+vXn4gXsv9QKBgQDWtd0BMEVCUug+6/dWCVTUsuBouz/erOgE
+f0PPA8/IQV1ZhBQK4wewv14R8Nkywb8Z5lsVyH8JHRHZC35mVzFxGJyGAzDfJ3Mg
+GoK8t7jjiUHPF0tYWpLmAKdKHmJqB7ZBGzT7pAP07XockRHoeYHBHoO3Ck/c3h0f
+EtclGMOuGwKBgQCXf8z9RMmS+lZz9LJEJtT6QdY/RghJPbOJWoMijJ29fJbzLgQT
+zt03ZnnfIbD13sl/bnYUUIyTV3l/KkpUFjivC9Y4Y/FUrpLbDy9gWzCeRV6fDyep
+h3+yS0huMltBsjI7CZ0sMCWKlSqdlb6tBttxJZeI6H6qUimM8NmtSk3EuQKBgAw+
+OIjt0LU0dwvHdsYQKCcswAEY1E6FO4GuJBa01+9KUuFc16u7QGACuYF6Y1gylgwL
+B5yZXy0M3EytDBsX07joN1yo5+uBm130RQovy7olxHvjjydNmtzEosVmMCRtpiXW
+QFItCxC3TeQ9HXFNJGn3rHkOfHlSrQRtlZkG7XmLAoGACVKIJSoI2Kvd913TATb4
+whzNqbdiyFCadLf9cST7sGZ+ZvtHF3CT3iU/9JpBhndu4IqgFPPk694GXhoR2LK8
+SoGR4mhRvPAUgvKjRE2dypQtytgA8gm1soofSjSdoJlSBQkaxfT8N0mwQTbsoyWN
+zUDUWl3epDaqpUsV8NOuy4E=
+-----END PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa.pub b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa.pub
new file mode 100644
index 0000000000..f7b1180aad
--- /dev/null
+++ b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/id_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2d3XMIA8GTEQcUFCOm31M5jt6lGjN61ZYGnXBVBjEcyJynB7Y3C437cDpjmvbSWF1oSVVDTwMERwnXzixLG//7w8K7i6aJLKpHKtS91qnrQidmrUWDnQ4kx8AZxaN46nhSsf+cZ0nKp03ZjjR5WxeDimiDLsSUbdDmFE6ZsL2+k5OStvcqu/skUVfPe+FGTGJgIw3DyErxM7J72jUkLJXMiZkYbB1QD05k3g2LOiPqJ73QoJVGgj7YagTSA3Lgy3s/6U7IMHMV4lsaXShv1Lk/eCfIJVSaVXQRjV9KKM3wgg6PmWqwGkAO36w3eJiW1kmYKfnAM/+I5Gfo/TiNZTX uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key
new file mode 100644
index 0000000000..0c01831fa6
--- /dev/null
+++ b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCuvOQFQAxi8Cyj
+iFHv2+Y1vE1sti3tChy6RuIJY6rb0dC+ptLOP85ITVCDoL9pNuCG92m/FtoW3dqp
+1augXQ+FVWgSwljvpsjtGyhsh73Mj9nd2RBGZbcjKMe+lUHDLzh8pnTkDwF3XSRx
+rUZ+tBeLsuQVnkVGPFqsXMyiMZV6xZxktqBOE8bRACNLDawb6iqXhigh5qBJ1/e3
+M44X7Ti9ymCoJG6CyxzDXuUjVHCrScze2FQGBJYNFuPOaRaj2Llalz1kpLXPgA0R
+P4jaEZbs8QDpcBckoLqchZ1UiJ7QY3TYL+aLjk3JM+fnYj9MkoUC0ihnx9uscR6l
+ftX8O3sNAgMBAAECggEADXIlja3fBiH7HV5ZB78BGPNzdcETCaF0knTv4c8Uj7O2
+f2Uw5YQNaIzifC57bCo33srdDUJB5+6Ma/MwMLfYgOcQihkAZPiNj4k+dBOB7GLJ
+XgPc973N+NujeyvbEpzomNbqOb5Z24iETGcL/KX5BdvvJya1p/Du/UJq0LRGD1tS
+0TycwcphU9rOffTCUd0+XpPJO0RehkIoyDY5PGu9rzTHkluhSotldfjVWpWaqqhq
+QQ7c04aWGsjMg4HzrqnLx35/rCKU3+tRwZ4wnAHxpOtg/EuQJiX08Z4wMwsBG+GM
+ybnd/pRAUOkvatjRemdqqtmpL0qtsmhNANaUyPc6IQKBgQDgUvd9trgVgbN/tP+b
+bFFILmqumvSA2fWZknmhRYaIcHCMAcLsRVZqlyOyRpztavOcgEmJXajPPFA6AjKa
+5g70tf3kbpveeuRaFVepSLIKSl0xIT9hV8CIxzdnRA3P4j9xsQ9Qpnuiwo9mbgFG
+lQ28nCPhW+3mNfBNmU+ZWak0dQKBgQDHaXGroc74attrQDODvChuedny5lm91n5C
+nGAaEfVHH3zrYoz65VisnvERSU1Nh8G12moldCcaWnOMY97OJmMnG/sCBZskDzRp
+e1Mf+gT0TQoyYZHMTZtA1HyRRkdTlLZ7S77HUNTK8qrIpJEHLFSnzCPlBkY84fgw
++8IdVkX5OQKBgCDnapARFi1paffoh7m3iLCqxlE4P3cLAYB2QMsMFLC8tXWD6KCZ
+hxR5eO30d55HmtYw5xh0GYfUU/w+SEf6SOVSMJyqMMjQg+BG0yXsmNjzkXncY5yW
+r5IgjpriG5iLmjzF+PYehXIZUcl3h05gHLS2vniW8G1dKhNn0oou4aflAoGAFTLh
+caR+8yuw7cLidxOunKf5gnf4fFTsETq8gKj+ETSIvCE66YUuGxO+ft7zB9XxwtpY
+RGkHqyaIeBk522J7UfIIiht8daXkJX6FxLV4h1wVRGvY6wYpBghQwcTd2kXJ7GuN
++XRfWr/XZgMQo9mTmk76VeOH3fsLvnFVHndIcwkCgYBLntA0osVpZm6egw26+80C
+PtnSrUmsW4sTB+eQbbyDn6i/fAgGKc+2WuvcdorqyfLSEcs+hE/59roFVFpCEPN5
+4oO7o+o0SQ2ehxY+Lv2XF+TnfUQlAc6BCBfK3tG6rROUFiznAaua1hcsoAa9x/LH
+0SgWzYqbWI0qq7pv91tBdw==
+-----END PRIVATE KEY-----
diff --git a/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key.pub b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key.pub
new file mode 100644
index 0000000000..8e62458395
--- /dev/null
+++ b/lib/ssh/test/ssh_pubkey_SUITE_data/pkcs8/ssh_host_rsa_key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuvOQFQAxi8CyjiFHv2+Y1vE1sti3tChy6RuIJY6rb0dC+ptLOP85ITVCDoL9pNuCG92m/FtoW3dqp1augXQ+FVWgSwljvpsjtGyhsh73Mj9nd2RBGZbcjKMe+lUHDLzh8pnTkDwF3XSRxrUZ+tBeLsuQVnkVGPFqsXMyiMZV6xZxktqBOE8bRACNLDawb6iqXhigh5qBJ1/e3M44X7Ti9ymCoJG6CyxzDXuUjVHCrScze2FQGBJYNFuPOaRaj2Llalz1kpLXPgA0RP4jaEZbs8QDpcBckoLqchZ1UiJ7QY3TYL+aLjk3JM+fnYj9MkoUC0ihnx9uscR6lftX8O3sN uabhnil@elxadlj3q32
diff --git a/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_comment_pub b/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_comment_pub
index 7b42ced93e..bca5a375ca 100644
--- a/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_comment_pub
+++ b/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_comment_pub
@@ -1,7 +1,7 @@
---- BEGIN SSH2 PUBLIC KEY ----
Comment: This is an example of a very very very very looooooooooooo\
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\
-commment
+comment
x-command: /home/me/bin/lock-in-guest.sh
AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
diff --git a/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_header_pub b/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_header_pub
index 7b42ced93e..bca5a375ca 100644
--- a/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_header_pub
+++ b/lib/ssh/test/ssh_pubkey_SUITE_data/public_key/ssh_rsa_long_header_pub
@@ -1,7 +1,7 @@
---- BEGIN SSH2 PUBLIC KEY ----
Comment: This is an example of a very very very very looooooooooooo\
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\
-commment
+comment
x-command: /home/me/bin/lock-in-guest.sh
AAAAB3NzaC1yc2EAAAABIwAAAIEA1on8gxCGJJWSRT4uOrR13mUaUk0hRf4RzxSZ1zRb
YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ
diff --git a/lib/ssh/test/ssh_relay.erl b/lib/ssh/test/ssh_relay.erl
index 3bb4cb2071..f7aac11c7c 100644
--- a/lib/ssh/test/ssh_relay.erl
+++ b/lib/ssh/test/ssh_relay.erl
@@ -313,7 +313,7 @@ listen(Parent, LSock) ->
do_listen(Parent, LSock).
do_listen(Parent, LSock) ->
- %% So annoying there is no select-like sematic for this
+ %% So annoying there is no select-like semantics for this
case gen_tcp:accept(LSock, ?ACCEPT_TMO) of
{ok, Sock} ->
Parent ! {accept, Sock},
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 70a0049730..42677b7613 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-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -405,7 +405,7 @@ rename_file(Config) when is_list(Config) ->
NewReqId1 = NewReqId + 1,
file:copy(FileName, NewFileName),
- %% No owerwrite
+ %% No overwrite
{ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
?UINT32(?SSH_FX_FILE_ALREADY_EXISTS), _/binary>>, _} =
rename(FileName, NewFileName, Cm, Channel, NewReqId1, 6,
@@ -685,7 +685,7 @@ access_outside_root(Config) when is_list(Config) ->
BadFilePath = filename:join([BaseDir, bad]),
ok = file:write_file(BadFilePath, <<>>),
{Cm, Channel} = proplists:get_value(sftp, Config),
- %% Try to access a file parallell to the RootDir:
+ %% Try to access a file parallel to the RootDir:
try_access("/../bad", Cm, Channel, 0),
%% Try to access the same file via the CWD which is /b relative to the RootDir:
try_access("../../bad", Cm, Channel, 1).
@@ -717,7 +717,7 @@ try_access(Path, Cm, Channel, ReqId) ->
end
end;
_ ->
- ct:fail("Completly unexpected return: ~p", [Return])
+ ct:fail("Completely unexpected return: ~p", [Return])
end.
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index acabb66a48..08c9638213 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -627,14 +627,14 @@ default_algorithms(sshc, DaemonOptions) ->
{hostport,Srvr,{_Host,Port}} ->
spawn(fun()-> os:cmd(lists:concat(["ssh -o \"StrictHostKeyChecking no\" -p ",Port," localhost"])) end)
after ?TIMEOUT ->
- ct:fail("No server respons (timeout) 1")
+ ct:fail("No server response (timeout) 1")
end,
receive
{result,Srvr,L} ->
L
after ?TIMEOUT ->
- ct:fail("No server respons (timeout) 2")
+ ct:fail("No server response (timeout) 2")
end.
run_fake_ssh({ok,InitialState}) ->
@@ -940,7 +940,7 @@ create_random_dir(Config) ->
Name;
{error,eexist} ->
%% The Name already denotes an existing file system object, try again.
- %% The likelyhood of always generating an existing file name is low
+ %% The likelihood of always generating an existing file name is low
create_random_dir(Config)
end.
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index a36b4036a5..c61907ec28 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -91,7 +91,7 @@ init_per_suite(Config) ->
?CHECK_CRYPTO(
case gen_tcp:connect("localhost", ?SSH_DEFAULT_PORT, []) of
{error,econnrefused} ->
- {skip,"No openssh deamon (econnrefused)"};
+ {skip,"No openssh daemon (econnrefused)"};
_ ->
ssh_test_lib:openssh_sanity_check(
[{ptty_supported, ssh_test_lib:ptty_supported()}
diff --git a/lib/ssh/test/ssh_trpt_test_lib.erl b/lib/ssh/test/ssh_trpt_test_lib.erl
index eea392bd35..6d3f4544ce 100644
--- a/lib/ssh/test/ssh_trpt_test_lib.erl
+++ b/lib/ssh/test/ssh_trpt_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% The 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,7 +47,7 @@
prints = [],
return_value,
- %% Packet retrival and decryption
+ %% Packet retrieval and decryption
decrypted_data_buffer = <<>>,
encrypted_data_buffer = <<>>,
aead_data = <<>>,
@@ -343,7 +343,7 @@ send(S0=#s{alg_neg={undefined,PeerMsg}}, Msg=#ssh_msg_kexinit{}) ->
S1#s{alg = Cx#ssh.algorithms}
catch
Class:Exc ->
- save_prints({"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n",
+ save_prints({"Algorithm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n",
[?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(Msg)]},
S1)
end;
@@ -361,8 +361,8 @@ send(S0, ssh_msg_kexdh_init) when ?role(S0) == client ->
try ssh_transport:handle_kexinit_msg(PeerMsg, OwnMsg, S0#s.ssh)
catch
Class:Exc ->
- fail("Algoritm negotiation failed!",
- {"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s",
+ fail("Algorithm negotiation failed!",
+ {"Algorithm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s",
[?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(OwnMsg)]},
S0)
end,
@@ -429,7 +429,7 @@ recv(S0 = #s{}) ->
%% Must see hello before binary messages
try_find_crlf(<<>>, S1);
true ->
- %% Has seen hello, therefore no more crlf-messages are alowed.
+ %% Has seen hello, therefore no more crlf-messages are allowed.
S = receive_binary_msg(S1),
case PeerMsg = S#s.return_value of
#ssh_msg_kexinit{} ->
@@ -451,7 +451,7 @@ recv(S0 = #s{}) ->
alg = C#ssh.algorithms}
catch
Class:Exc ->
- save_prints({"Algoritm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n",
+ save_prints({"Algorithm negotiation failed at line ~p:~p~n~p:~s~nPeer: ~s~n Own: ~s~n",
[?MODULE,?LINE,Class,format_msg(Exc),format_msg(PeerMsg),format_msg(OwnMsg)]},
S#s{alg_neg = {OwnMsg, PeerMsg}})
end
@@ -650,7 +650,7 @@ ok({error,E}) -> erlang:error(E).
%%%================================================================
%%%
-%%% Formating of records
+%%% Formatting of records
%%%
format_msg(M) -> format_msg(M, 0).
diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl
index 7c7c93e04b..b96fa896bb 100644
--- a/lib/ssh/test/ssh_upgrade_SUITE.erl
+++ b/lib/ssh/test/ssh_upgrade_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -98,7 +98,7 @@ minor_upgrade(Config) when is_list(Config) ->
%%%
%%%----------------------------------------------------------------
-%%% Initialyze system before upgrade test starts.
+%%% Initialize system before upgrade test starts.
%%% Called by ct_release_test:upgrade/4
upgrade_init(CTData, State) ->
{ok, AppUp={_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssh),
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 3a88e96f93..6fa9e323c5 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,4 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.13.2
+SSH_VSN = 4.15.3
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 564eb9ec9c..a36ac8d78d 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2022</year>
+ <year>1999</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -27,6 +27,611 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 10.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed that new <c>dtls</c> connections from the same
+ client ip port combination works. If there is a process
+ waiting for accept the new connection will connect to
+ that, otherwise it will try to re-connect to the old
+ server connection.</p>
+ <p>
+ Own Id: OTP-18371 Aux Id: GH-6160 </p>
+ </item>
+ <item>
+ <p>
+ When shutting down a node that uses SSL distribution
+ (<c>-proto_dist inet_tls</c>), a confusing error message
+ about an unexpected process exit was printed. This
+ particular message is no longer generated.</p>
+ <p>
+ Own Id: OTP-18443 Aux Id: PR-6810 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ fixes the type spec for ssl:format_error/1</p>
+ <p>
+ Own Id: OTP-18366 Aux Id: PR-6565, GH-6506 </p>
+ </item>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Maximize compatibility by ignoring change_cipher_spec
+ during handshake even if middle_box_mode is not
+ negotiated (mandated by client)</p>
+ <p>
+ Own Id: OTP-18433 Aux Id: GH-6772 </p>
+ </item>
+ <item>
+ <p>
+ Move assert of middlebox message after an
+ hello_retry_request to maximize interoperability. Does
+ not changes semantics of the protocol only allows
+ unexpected message delay from server.</p>
+ <p>
+ Own Id: OTP-18467 Aux Id: GH-6807 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, tls_sender process is hibernated after
+ sufficient inactivity.</p>
+ <p>
+ Own Id: OTP-18314 Aux Id: GH-6373 </p>
+ </item>
+ <item>
+ <p>
+ Correct handling of legacy schemes so that ECDSA certs
+ using sha1 may be used for some TLS-1.3 configurations.</p>
+ <p>
+ Own Id: OTP-18332 Aux Id: GH-6435, PR-6435, ERL-6435 </p>
+ </item>
+ <item>
+ <p>
+ With this change, tls_sender does not cause logger crash
+ upon key update.</p>
+ <p>
+ Own Id: OTP-18349</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Enhance warning message</p>
+ <p>
+ Own Id: OTP-18257 Aux Id: GH-6307 </p>
+ </item>
+ <item>
+ <p>
+ Provide server option to make certificate_authorities
+ extension in the TLS-1.3 servers certificate request
+ optional. This will allow clients to send incomplete
+ chains that may be reconstructable and thereby verifiable
+ by the server, but that would not adhere to the
+ certificate_authorities extension.</p>
+ <p>
+ Own Id: OTP-18267 Aux Id: PR-6228, GH-6106 </p>
+ </item>
+ <item>
+ <p>
+ If the <c>verify_fun</c> handles four arguments the DER
+ cert will be supplied as one of the arguments.</p>
+ <p>
+ Own Id: OTP-18302 Aux Id: ERIERL-867 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixes handling of symlinks in cacertfile option.</p>
+ <p>
+ Own Id: OTP-18266 Aux Id: GH-6328 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Reject unexpected application data in all relevant places
+ for all TLS versions. Also, handle TLS-1.3 middlebox
+ compatibility with more care. This will make malicious
+ connections fail early and further, mitigate possible DoS
+ attacks, that would be caught by the handshake timeout.</p>
+ <p>
+ Thanks to Aina Toky Rasoamanana and Olivier Levillain
+ from Télécom SudParis for alerting us of the issues in
+ our implementation.</p>
+ <p>
+ Own Id: OTP-18044</p>
+ </item>
+ <item>
+ <p>
+ With this change, value of cacertfile option will be
+ adjusted before loading certs from the file. Adjustments
+ include converting relative paths to absolute and
+ converting symlinks to actual file path.</p>
+ <p>
+ Thanks to Marcus Johansson</p>
+ <p>
+ Own Id: OTP-18099 Aux Id: PR-6287 </p>
+ </item>
+ <item>
+ <p>
+ In TLS-1.3, if chain certs are missing (so server auth
+ domain adherence can not be determined) send peer cert
+ and hope the server is able to recreate a chain in its
+ auth domain.</p>
+ <p>
+ Own Id: OTP-18191 Aux Id: GH-6105 </p>
+ </item>
+ <item>
+ <p>
+ Make sure periodical refresh of CA certificate files
+ repopulates cache properly.</p>
+ <p>
+ Own Id: OTP-18195</p>
+ </item>
+ <item>
+ <p>
+ Correct internal CRL cache functions to use internal
+ format consistently.</p>
+ <p>
+ Own Id: OTP-18203 Aux Id: PR-5996 </p>
+ </item>
+ <item>
+ <p>
+ Incorrect handling of client middlebox negotiation for
+ TLS-1.3 could result in that a TLS-1.3 server would not
+ use middlebox mode although the client was expecting it
+ too and failing the negotiation with unexpected message.</p>
+ <p>
+ Own Id: OTP-18219 Aux Id: GH-6241, PR-6249 </p>
+ </item>
+ <item>
+ <p>
+ If the "User" process, the process starting the TLS
+ connection, gets killed in the middle of spawning the
+ dynamic connection tree make sure we do not leave any
+ processes behind.</p>
+ <p>
+ Own Id: OTP-18233 Aux Id: GH-6244, PR-6270 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A vulnerability has been discovered and corrected. It is
+ registered as CVE-2022-37026 "Client Authentication
+ Bypass". Corrections have been released on the supported
+ tracks with patches 23.3.4.15, 24.3.4.2, and 25.0.2. The
+ vulnerability might also exist in older OTP versions. We
+ recommend that impacted users upgrade to one of these
+ versions or later on the respective tracks. OTP 25.1
+ would be an even better choice. Impacted are those who
+ are running an ssl/tls/dtls server using the ssl
+ application either directly or indirectly via other
+ applications. For example via inets (httpd), cowboy, etc.
+ Note that the vulnerability only affects servers that
+ request client certification, that is sets the option
+ {verify, verify_peer}.</p>
+ <p>
+ Own Id: OTP-18241</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The link to crypto:engine_load refered the function
+ with wrong arity. </p>
+ <p>
+ Own Id: OTP-18173</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved handling of unexpected messages during the
+ handshake, taking the right action for unexpected
+ messages.</p>
+ <p>
+ Own Id: OTP-18145</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When a TLS-1.3 enabled client tried to talk to a TLS-1.2
+ server that coalesces TLS-1.2 handshake message over one
+ TLS record, the connection could fail due to some message
+ being handled in the wrong state, this has been fixed.</p>
+ <p>
+ Own Id: OTP-18087 Aux Id: GH-5961 </p>
+ </item>
+ <item>
+ <p>
+ Correctly handles supported protocol version change from
+ default to something else by sni_fun supplied to
+ ssl:handshake/[2,3] together with a TCP-socket (so called
+ upgrade).</p>
+ <p>
+ Own Id: OTP-18100 Aux Id: GH-5985 </p>
+ </item>
+ <item>
+ <p>
+ Also, TLS-1.3 should respond with a protocol version
+ alert if previous versions, that are supported but not
+ configured, are attempted.</p>
+ <p>
+ Own Id: OTP-18129 Aux Id: GH-5950 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When a TLS-1.3 enabled client tried to talk to a TLS-1.2
+ server that coalesces TLS-1.2 handshake message over one
+ TLS record, the connection could fail due to some message
+ being handled in the wrong state, this has been fixed.</p>
+ <p>
+ Own Id: OTP-18087 Aux Id: GH-5961 </p>
+ </item>
+ <item>
+ <p>
+ Fixed tls-1.3 session ticket lifetime which was discarded
+ to quickly before.</p>
+ <p>
+ Own Id: OTP-18092 Aux Id: PR-5959 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ With this change, it is possible to provide several
+ certificates. Most appropriate will be selected based on
+ negotiated properties.</p>
+ <p>
+ Own Id: OTP-15993 Aux Id: GH-4143 </p>
+ </item>
+ <item>
+ <p>
+ Add options for users to be able to set spawn_opts for
+ TLS processes (sender and receiver) this may be useful
+ for tuning trade-offs between CPU and Memory usage.</p>
+ <p>
+ Own Id: OTP-17855 Aux Id: PR-5328 </p>
+ </item>
+ <item>
+ <p>
+ Allow key file passwords to be input as a single binary,
+ that is we change the data type to be the more for the
+ purpose logical data type iodata() instead of string().</p>
+ <p>
+ Own Id: OTP-17890</p>
+ </item>
+ <item>
+ <p>
+ Logging enhancement, add location information to the
+ warning log message.</p>
+ <p>
+ Own Id: OTP-18000 Aux Id: PR-5790 </p>
+ </item>
+ <item>
+ <p>
+ Now also accepts the signature_algs_cert option in
+ TLS-1.2 configuration.</p>
+ <p>
+ Own Id: OTP-18014</p>
+ </item>
+ <item>
+ <p>
+ Handle certificate selection correctly for server
+ fallback and certificate authorities considerations.</p>
+ <p>
+ Own Id: OTP-18045 Aux Id: ERIERL-792, OTP-15993 </p>
+ </item>
+ <item>
+ <p>
+ Enhance handling of handshake decoding errors, especially
+ for certificate authorities extension to ensure graceful
+ termination.</p>
+ <p>
+ Own Id: OTP-18085</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.7.3.6</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Maximize compatibility by ignoring change_cipher_spec
+ during handshake even if middle_box_mode is not
+ negotiated (mandated by client)</p>
+ <p>
+ Own Id: OTP-18433 Aux Id: GH-6772 </p>
+ </item>
+ <item>
+ <p>
+ Move assert of middlebox message after an
+ hello_retry_request to maximize interoperability. Does
+ not changes semantics of the protocol only allows
+ unexpected message delay from server.</p>
+ <p>
+ Own Id: OTP-18467 Aux Id: GH-6807 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.7.3.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixes handling of symlinks in cacertfile option.</p>
+ <p>
+ Own Id: OTP-18266 Aux Id: GH-6328 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.7.3.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ With this change, value of cacertfile option will be
+ adjusted before loading certs from the file. Adjustments
+ include converting relative paths to absolute and
+ converting symlinks to actual file path.</p>
+ <p>
+ Thanks to Marcus Johansson</p>
+ <p>
+ Own Id: OTP-18099 Aux Id: PR-6287 </p>
+ </item>
+ <item>
+ <p>
+ Incorrect handling of client middlebox negotiation for
+ TLS-1.3 could result in that a TLS-1.3 server would not
+ use middlebox mode although the client was expecting it
+ too and failing the negotiation with unexpected message.</p>
+ <p>
+ Own Id: OTP-18219 Aux Id: GH-6241, PR-6249 </p>
+ </item>
+ <item>
+ <p>
+ If the "User" process, the process starting the TLS
+ connection, gets killed in the middle of spawning the
+ dynamic connection tree make sure we do not leave any
+ processes behind.</p>
+ <p>
+ Own Id: OTP-18233 Aux Id: GH-6244, PR-6270 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.7.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Reject unexpected application data in all relevant places
+ for all TLS versions. Also, handle TLS-1.3 middlebox
+ compatibility with more care. This will make malicious
+ connections fail early and further, mitigate possible DoS
+ attacks, that would be caught by the handshake timeout.</p>
+ <p>
+ Thanks to Aina Toky Rasoamanana and Olivier Levillain
+ from Télécom SudParis for alerting us of the issues in
+ our implementation.</p>
+ <p>
+ Own Id: OTP-18044</p>
+ </item>
+ <item>
+ <p> The link to crypto:engine_load refered the function
+ with wrong arity. </p>
+ <p>
+ Own Id: OTP-18173</p>
+ </item>
+ <item>
+ <p>
+ Make sure periodical refresh of CA certificate files
+ repopulates cache properly.</p>
+ <p>
+ Own Id: OTP-18195</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.7.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved handling of unexpected messages during the
+ handshake, taking the right action for unexpected
+ messages.</p>
+ <p>
+ Own Id: OTP-18145</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.7.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ When a TLS-1.3 enabled client tried to talk to a TLS-1.2
+ server that coalesces TLS-1.2 handshake message over one
+ TLS record, the connection could fail due to some message
+ being handled in the wrong state, this has been fixed.</p>
+ <p>
+ Own Id: OTP-18087 Aux Id: GH-5961 </p>
+ </item>
+ <item>
+ <p>
+ Fixed tls-1.3 session ticket lifetime which was discarded
+ to quickly before.</p>
+ <p>
+ Own Id: OTP-18092 Aux Id: PR-5959 </p>
+ </item>
+ <item>
+ <p>
+ Correctly handles supported protocol version change from
+ default to something else by sni_fun supplied to
+ ssl:handshake/[2,3] together with a TCP-socket (so called
+ upgrade).</p>
+ <p>
+ Own Id: OTP-18100 Aux Id: GH-5985 </p>
+ </item>
+ <item>
+ <p>
+ Also, TLS-1.3 should respond with a protocol version
+ alert if previous versions, that are supported but not
+ configured, are attempted.</p>
+ <p>
+ Own Id: OTP-18129 Aux Id: GH-5950 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Enhance handling of handshake decoding errors, especially
+ for certificate authorities extension to ensure graceful
+ termination.</p>
+ <p>
+ Own Id: OTP-18085</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 10.7.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -559,6 +1164,56 @@
</section>
+<section><title>SSL 10.3.1.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct corner case of unexpected message handling for
+ pre TLS-1.3 versions, could cause "late failure" and make
+ the server dependent on its handshake timeout to prevent
+ possible DoS attacks.</p>
+ <p>
+ Own Id: OTP-18224</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.3.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The link to crypto:engine_load refered the function
+ with wrong arity. </p>
+ <p>
+ Own Id: OTP-18173</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 10.3.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved handling of unexpected messages during the
+ handshake, taking the right action for unexpected
+ messages.</p>
+ <p>
+ Own Id: OTP-18145</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 10.3.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -702,6 +1357,23 @@
</section>
+<section><title>SSL 10.2.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved handling of unexpected messages during the
+ handshake, taking the right action for unexpected
+ messages.</p>
+ <p>
+ Own Id: OTP-18145</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 10.2.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 8c63b1d698..803c0f789a 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -339,8 +339,8 @@
<desc>
<p>The DER-encoded user's private key or a map referring to a crypto
engine and its key reference that optionally can be password protected,
- see also <seemfa marker="crypto:crypto#engine_load/4"> crypto:engine_load/4
- </seemfa> and <seeguide marker="crypto:engine_load"> Crypto's Users Guide</seeguide>. If this option
+ see also <seemfa marker="crypto:crypto#engine_load/3"> crypto:engine_load/3
+ </seemfa> and <seeguide marker="crypto:engine_load"> Crypto's Users Guide</seeguide>. If this option
is supplied, it overrides option <c>keyfile</c>.</p>
</desc>
</datatype>
@@ -356,7 +356,7 @@
</datatype>
<datatype>
- <name name="key_password"/>
+ <name name="key_pem_password"/>
<desc>
<p>String containing the user's password or a function returning same type. Only used if the
private keyfile is password-protected.</p>
@@ -364,6 +364,46 @@
</datatype>
<datatype>
+ <name name="certs_keys"/>
+ <desc>
+ <p>A list of a certificate (or possible a certificate and its
+ chain) and the associated key of the certificate, that may be
+ used to authenticate the client or the server. The
+ certificate key pair that is considered best and matches
+ negotiated parameters for the connection will be selected.
+ Different signature algorithms are prioritized in the order
+ <c> eddsa, ecdsa, rsa_pss_pss, rsa and dsa </c>. If more than
+ one key is supplied for the same signing algorithm (which is
+ probably an unusual use case) they will prioritized by
+ strength unless it is a so called <c>engine key</c> that will
+ be favoured over other keys. As engine keys cannot be
+ inspected, supplying more than one engine key will make no
+ sense. This offers flexibility to for instance configure a
+ newer certificate that is expected to be used in most cases
+ and an older but acceptable certificate that will only be used
+ to communicate with legacy systems. Note that there is a trade
+ off between the induced overhead and the flexibility so
+ alternatives should be chosen for good reasons. If the <c>certs_keys</c> option is specified it
+ overrides all single certificate and key options. For examples see <seeguide marker="ssl:using_ssl"> the Users Guide</seeguide>
+ </p>
+
+ <note><p> <c>eddsa</c> certificates are only supported by TLS-1.3 that does not support <c>dsa</c> certificates.
+ <c>rsa_pss_pss</c> (RSA certificates using Probabilistic Signature Scheme) are supported in TLS-1.2 and TLS-1.3, but some
+ TLS-1.2 implementations may not support <c>rsa_pss_pss</c>.
+ </p></note>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="cert_key_conf"/>
+ <desc>
+ <p> A certificate (or possibly a certificate and its chain) and its associated key on one of the
+ possible formats. For the PEM file format there may also be a password associated with the file containg the key.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
<name name="cipher_suites"/>
<desc>
<p>A list of cipher suites that should be supported</p>
@@ -422,7 +462,8 @@
<p>Signature algorithms used for certificates may be overridden by the
<seetype marker="#sign_schemes">signature schemes</seetype> (algorithms) supplied by the <c>signature_algs_cert</c> option.</p>
- <p>TLS-1.2 default is</p>
+ <p>TLS-1.2 default is Default_TLS_12_Alg_Pairs interleaved with rsa_pss_schemes since ssl-11.0 (OTP-25)
+ pss_pss is prefered over pss_rsae that is prefered over rsa</p>
<p><c>Default_TLS_12_Alg_Pairs =</c></p>
<code>[
@@ -439,13 +480,21 @@
{sha, ecdsa},
{sha, rsa},
{sha, dsa}
-]
- </code>
+]</code>
- <p>Support for {md5, rsa} was removed from the the TLS-1.2 default in ssl-8.0 (OTP-22) </p>
+<p>Support for {md5, rsa} was removed from the the TLS-1.2 default in ssl-8.0 (OTP-22) </p>
+ <p><c> rsa_pss_schemes =</c></p>
+ <code>
+[rsa_pss_pss_sha512,
+rsa_pss_pss_sha384,
+rsa_pss_pss_sha256,
+rsa_pss_rsae_sha512,
+rsa_pss_rsae_sha384,
+rsa_pss_rsae_sha256]
+ </code>
- <p><c> TLS_13 _Legacy_Schemes =</c></p>
+ <p><c> TLS_13_Legacy_Schemes =</c></p>
<code> [
%% Legacy algorithms only applicable to certificate signatures
rsa_pkcs1_sha512, %% Corresponds to {sha512, rsa}
@@ -458,21 +507,20 @@ rsa_pkcs1_sha1 %% Corresponds to {sha, rsa}
<p><c> Default_TLS_13_Schemes =</c></p>
<code> [
+ %% EDDSA
+eddsa_ed25519,
+eddsa_ed448
+
%% ECDSA
ecdsa_secp521r1_sha512,
ecdsa_secp384r1_sha384,
-ecdsa_secp256r1_sha256,
+ecdsa_secp256r1_sha256] ++
+
%% RSASSA-PSS
-rsa_pss_pss_sha512,
-rsa_pss_pss_sha384,
-rsa_pss_pss_sha256,
-rsa_pss_rsae_sha512,
-rsa_pss_rsae_sha384,
-rsa_pss_rsae_sha256,
-%% EDDSA
-eddsa_ed25519,
-eddsa_ed448]
-</code>
+rsa_pss_schemes()
+ </code>
+
+ <p>EDDSA was made highest priority in ssl-11.0 (OTP-25) </p>
<p>TLS-1.3 default is</p>
<code>Default_TLS_13_Schemes ++ Legacy_TLS_13_Schemes </code>
@@ -577,11 +625,22 @@ version.
<p>The verification fun is to be defined as follows:</p>
<code>
-fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom() |
- {revoked, atom()}} |
- {extension, #'Extension'{}} | valid | valid_peer, InitialUserState :: term()) ->
+fun(OtpCert :: #'OTPCertificate'{},
+ Event, InitialUserState :: term()) ->
+ {valid, UserState :: term()} |
+ {fail, Reason :: term()} | {unknown, UserState :: term()}.
+
+fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),
+ Event, InitialUserState :: term()) ->
{valid, UserState :: term()} |
{fail, Reason :: term()} | {unknown, UserState :: term()}.
+
+Types:
+ Event = {bad_cert, Reason :: atom() |
+ {revoked, atom()}} |
+ {extension, #'Extension'{}} |
+ valid |
+ valid_peer
</code>
<p>The verification fun is called during the X509-path
@@ -591,8 +650,8 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom() |
allow access to each certificate in the path to the user
application. It differentiates between the peer certificate
and the CA certificates by using <c>valid_peer</c> or
- <c>valid</c> as second argument to the verification fun. See
- the <seeguide marker="public_key:public_key_records">public_key
+ <c>valid</c> as <c>Event</c> argument to the verification fun.
+ See the <seeguide marker="public_key:public_key_records">public_key
User's Guide</seeguide> for definition of
<c>#'OTPCertificate'{}</c> and <c>#'Extension'{}</c>.</p>
@@ -919,6 +978,18 @@ fun(srp, Username :: binary(), UserState :: term()) ->
</datatype>
<datatype>
+ <name name="spawn_opts"/>
+ <desc><p>Configures spawn options of TLS sender and receiver processes.</p>
+ <p>Setting up garbage collection options can be helpful for trade-offs between
+ CPU usage and Memory usage.
+ See <seemfa marker="erts:erlang#spawn_opt/2"><c>erlang:spawn_opt/2</c></seemfa>.</p>
+ <p>For dist connections, default sender option is <c>[...{priority, max}]</c>, this priority
+ option cannot be changed. For all connections, <c>...link</c> is added to receiver and cannot
+ be changed.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
<name name="keep_secrets"/>
<desc><p>Configures a TLS 1.3 connection for keylogging</p>
<p>In order to retrieve keylog information on a TLS 1.3 connection, it must be configured
@@ -936,9 +1007,14 @@ fun(srp, Username :: binary(), UserState :: term()) ->
<datatype>
<name name="client_verify_type"/>
- <desc><p>In mode <c>verify_none</c> the default behavior is to allow
- all x509-path validation errors. See also option <seetype marker="#custom_verify">verify_fun</seetype>.</p>
- </desc>
+ <desc>
+ <p>Defaults to <c>verify_none</c> as additional options are needed to be able to perform the certificate verification.
+ A warning will be emitted unless <c>verify_none</c> is explicitly configured. Usually the applications will want to configure
+ <c>verify_peer</c> together with an appropriate <c>cacert</c> or <c>cacertfile</c> option. For example an <c>HTTPS</c> client would normally
+ use the option <c>{cacerts, public_key:cacerts_get()}</c> (available since OTP-25) to access the CA certificates
+ provided by the OS. Using verify_none means that all x509-certificate path validation errors will be ignored.
+ See also option <seetype marker="#custom_verify">verify_fun</seetype>.</p>
+ </desc>
</datatype>
<datatype>
@@ -949,7 +1025,7 @@ fun(srp, Username :: binary(), UserState :: term()) ->
explicitly specified by its session id and associated data since OTP-22.3.
See also
<seeguide marker="ssl:using_ssl#session-reuse-pre-tls-1.3">
- SSL's Users Guide, Session Reuse pre TLS 1.3</seeguide>
+ SSL's Users Guide, Session Reuse pre TLS 1.3.</seeguide>
</p>
</desc>
</datatype>
@@ -963,17 +1039,17 @@ fun(srp, Username :: binary(), UserState :: term()) ->
and used with the client option <seetype marker="#client_reuse_session">reuse_session</seetype>
The boolean value true specifies that if possible, automated session reuse will
be performed. If a new session is created, and is unique in regard
- to previous stored sessions, it will be saved for possible later reuse. Since OTP-21.3</p>
+ to previous stored sessions, it will be saved for possible later reuse. Since OTP-21.3.</p>
</desc>
</datatype>
<datatype>
- <name name="certificate_authorities"/>
+ <name name="client_certificate_authorities"/>
<desc>
<p>If set to true, sends the certificate authorities extension in TLS-1.3 client hello.
The default is false. Note that setting it to true may result in a big overhead if you
have many trusted CA certificates.
- Since OTP-24.3</p>
+ Since OTP-24.3.</p>
</desc>
</datatype>
@@ -989,8 +1065,15 @@ fun(srp, Username :: binary(), UserState :: term()) ->
<name name="client_cafile"/>
<desc>
<p>Path to a file containing PEM-encoded CA certificates. The CA
- certificates are used during server authentication and when building the
- client certificate chain.</p>
+ certificates are used during server authentication and when building the
+ client certificate chain.</p>
+ <note><p>When PEM caching is enabled, files provided with
+ this option will be checked for updates at fixed time intervals specified by the
+ <seeapp marker="ssl:ssl_app#configuration">ssl_pem_cache_clean</seeapp> environment parameter.</p>
+ </note>
+ <note><p>Alternatively, CA certificates can be provided as a DER-encoded
+ binary with <seetype marker="#client_cacerts">client_cacerts</seetype>
+ option.</p></note>
</desc>
</datatype>
@@ -1183,6 +1266,21 @@ fun(srp, Username :: binary(), UserState :: term()) ->
is supplied it overrides option <c>cacertfile</c>.</p>
</desc>
</datatype>
+
+ <datatype>
+ <name since="OTP 25.2" name="server_certificate_authorities"/>
+ <desc>
+ <p>Determines if a TLS-1.3 server should include the authorities
+ extension in its certificate request message that will be sent if the
+ option <c>verify</c> is set to <c>verify_peer</c>. Defaults to <c>true</c>.</p>
+
+ <p>A reason to exclude the extension would be if the server wants to communicate with clients
+ incapable of sending complete certificate chains that adhere to the
+ extension, but the server still has the capability to recreate a chain that it can verify.</p>
+
+ </desc>
+
+ </datatype>
<datatype>
<name name="server_cafile"/>
@@ -1193,6 +1291,12 @@ fun(srp, Username :: binary(), UserState :: term()) ->
client when a certificate is requested. Can be omitted if
there is no need to verify the client and if there are no
intermediate CAs for the server certificate.</p>
+ <note><p>When PEM caching is enabled, files provided with
+ this option will be checked for updates at fixed time intervals specified by the
+ <seeapp marker="ssl:ssl_app#configuration">ssl_pem_cache_clean</seeapp> environment parameter.</p>
+ </note>
+ <note><p>Alternatively, CA certificates can be provided as a DER-encoded
+ binary with <seetype marker="#server_cacerts">server_cacerts</seetype> option.</p></note>
</desc>
</datatype>
@@ -1218,12 +1322,14 @@ fun(srp, Username :: binary(), UserState :: term()) ->
<datatype>
<name name="server_verify_type"/>
- <desc><p>A server only does x509-path validation in mode
- <c>verify_peer</c>, as it then sends a certificate request to
- the client (this message is not sent if the verify option is
- <c>verify_none</c>). You can then also want to specify option
- <c>fail_if_no_peer_cert</c>. </p>
- </desc>
+ <desc><p> Client certificates are an optional part of the TLS protocol.
+ A server only does x509-certificate path validation in mode
+ <c>verify_peer</c>. By default the server is in <c>verify_none</c> mode
+ an hence will not send an certificate request to the client.
+ When using <c>verify_peer</c> you may also want to specify the options
+ <seetype marker="#fail_if_no_peer_cert">fail_if_no_peer_cert</seetype> and
+ <seetype marker="#server_certificate_authorities">certificate_authorities</seetype>.</p>
+ </desc>
</datatype>
<datatype>
@@ -1242,7 +1348,7 @@ fun(srp, Username :: binary(), UserState :: term()) ->
<desc><p>The boolean value true specifies that the server will
agree to reuse sessions. Setting it to false will result in an empty
session table, that is no sessions will be reused.
- See also option <seetype marker="#server_reuse_session">reuse_session</seetype>
+ See also option <seetype marker="#server_reuse_session">reuse_session</seetype>.
</p>
</desc>
</datatype>
@@ -1544,12 +1650,13 @@ fun(srp, Username :: binary(), UserState :: term()) ->
<func>
<name name="clear_pem_cache" arity="0" since="OTP 17.5"/>
- <fsummary> Clears the pem cache</fsummary>
- <desc><p>PEM files, used by ssl API-functions, are cached. The
- cache is regularly checked to see if any cache entries should be
- invalidated, however this function provides a way to
- unconditionally clear the whole cache.
- </p>
+ <fsummary>Clears the pem cache</fsummary>
+ <desc>
+ <p>PEM files, used by ssl API-functions, are cached for
+ performance reasons. The cache is automatically checked at
+ regular intervals to see if any cache entries should be invalidated.</p>
+ <p>This function provides a way to unconditionally clear the entire
+ cache, thereby forcing a reload of previously cached PEM files.</p>
</desc>
</func>
diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml
index 0f660cc420..dbb1fc166e 100644
--- a/lib/ssl/doc/src/ssl_app.xml
+++ b/lib/ssl/doc/src/ssl_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>1999</year><year>2021</year>
+ <year>1999</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -139,9 +139,9 @@
<p>
Number of milliseconds between PEM cache validations. Defaults to 2 minutes.
</p>
+ <p>Note: The cache can be reloaded by calling
<seemfa
- marker="ssl#clear_pem_cache/0">ssl:clear_pem_cache/0</seemfa>
-
+ marker="ssl#clear_pem_cache/0">ssl:clear_pem_cache/0</seemfa>.</p>
</item>
<tag><c><![CDATA[bypass_pem_cache = boolean() <optional>]]></c></tag>
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index ae082b98db..318e367245 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -36,39 +36,60 @@
<seemfa marker="ssl:ssl#versions/0"><c>ssl:versions/0</c></seemfa>
.</p>
- <p>To see all supported cipher suites, call
- <seemfa marker="ssl:ssl#cipher_suites/2"><c>ssl:cipher_suites(all, 'tlsv1.3')</c> </seemfa>.
- The available cipher suites for a connection depend on the TLS version and pre TLS-1.3 also
- on the certificate. To see the default cipher suite list change <c>all</c> to <c>default</c>.
- Note that TLS 1.3 and previous versions does not have any cipher suites in common,
- for listing cipher suites for a specific version use
- <seemfa marker="ssl:ssl#cipher_suites/2"><c>ssl:cipher_suites(exclusive, 'tlsv1.3')</c> </seemfa>.
- Specific cipher suites that you want your connection to use can also be
- specified. Default is to use the strongest available.</p>
-
+ <p>To see all supported cipher suites, call <seemfa
+ marker="ssl:ssl#cipher_suites/2"><c>ssl:cipher_suites(all,
+ 'tlsv1.3')</c> </seemfa>. The available cipher suites for a
+ connection depend on the TLS version and pre TLS-1.3 also on the
+ certificate. To see the default cipher suite list change <c>all</c>
+ to <c>default</c>. Note that TLS 1.3 and previous versions do not
+ have any cipher suites in common, for listing cipher suites for a
+ specific version use <seemfa
+ marker="ssl:ssl#cipher_suites/2"><c>ssl:cipher_suites(exclusive,
+ 'tlsv1.3')</c> </seemfa>. Specific cipher suites that you want your
+ connection to use can also be specified. Default is to use the
+ strongest available.</p>
+
+
+ <p>The following sections shows small examples of how to set up
+ client/server connections using the Erlang shell. The returned
+ value of the <c>sslsocket</c> is abbreviated with <c>[...]</c> as
+ it can be fairly large and is opaque to the user except for the
+ purpose of pattern matching.</p>
+
+
+ <note><p>Note that client certificate verification is optional for the server and needs additional conguration
+ on both sides to work. The Certificate and keys, in the examples, are provided using the <seetype marker="ssl:ssl#certs_keys">certs_keys</seetype> option
+ introduced in OTP-25.
+ </p>
+ </note>
+
<section>
- <title>Setting up Connections</title>
-
- <p>This section shows a small example of how to set up client/server connections
- using the Erlang shell. The returned value of the <c>sslsocket</c> is abbreviated
- with <c>[...]</c> as it can be fairly large and is opaque.</p>
-
- <section>
- <title>Minimal Example</title>
-
- <note><p> The minimal setup is not the most secure setup of TLS/DTLS.</p>
- </note>
+ <title>Basic Client</title>
+ <code type="erl"> 1 > ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
+ {cacerts, public_key:cacerts_get()}]).
+ {ok,{sslsocket, [...]}}</code>
+ </section>
- <p>To set up client/server connections:</p>
+ <section>
+ <title>Basic Connection</title>
- <p><em>Step 1:</em> Start the server side:</p>
- <code type="erl">1 server> ssl:start().
+ <p><em>Step 1:</em> Start the server side:</p>
+ <code type="erl">1 server> ssl:start().
ok</code>
-
- <p><em>Step 2:</em> Create a TLS listen socket: (To run DTLS add the option {protocol, dtls})</p>
+
+ <p><em>Step 2:</em> with alternative certificates,
+ in this example the EDDSA certificate will be preferred if TLS-1.3
+ is negotiated and the RSA certificate will always be used for TLS-1.2
+ as it does not support the EDDSA algorithm: </p>
<code type="erl">2 server> {ok, ListenSocket} =
-ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]).
+ssl:listen(9999, [{certs_keys, [#{certfile => "eddsacert.pem",
+ keyfile => "eddsakey.pem"},
+ #{certfile => "rsacert.pem",
+ keyfile => "rsakey.pem",
+ password => "foobar"}
+ ]},{reuseaddr, true}]).
{ok,{sslsocket, [...]}}</code>
+
<p><em>Step 3:</em> Do a transport accept on the TLS listen socket:</p>
<code type="erl">3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
@@ -83,8 +104,10 @@ connection</p>
<p><em>Step 4:</em> Start the client side: </p>
<code type="erl">1 client> ssl:start().
ok</code>
- <p> To run DTLS add the option {protocol, dtls} to third argument.</p>
- <code type="erl">2 client> {ok, Socket} = ssl:connect("localhost", 9999, [], infinity).
+ <p> Be sure to configure trusted certificates to use for server certificate verification.</p>
+ <code type="erl">2 client> {ok, Socket} = ssl:connect("localhost", 9999,
+ [{verify, verify_peer},
+ {cacertfile, "cacerts.pem"}, {active, once}], infinity).
{ok,{sslsocket, [...]}}</code>
<p><em>Step 5:</em> Do the TLS handshake:</p>
@@ -100,79 +123,90 @@ to avoid DoS attacks. In the example the timeout defaults to infinty.</p>
ok</code>
<p><em>Step 7:</em> Flush the shell message queue to see that the message
- was sent on the server side:</p>
+ sent on the server side is recived by the client side:</p>
<code type="erl">3 client> flush().
Shell got {ssl,{sslsocket,[...]},"foo"}
ok</code>
- </section>
-
- <section>
- <title>Upgrade Example - TLS only </title>
-
- <note><p>To upgrade a TCP/IP connection to a TLS connection, the
- client and server must agree to do so. The agreement
- can be accomplished by using a protocol, for example, the one used by HTTP
- specified in RFC 2817.</p></note>
+ </section>
- <p>To upgrade to a TLS connection:</p>
-
- <p><em>Step 1:</em> Start the server side:</p>
- <code type="erl">1 server> ssl:start().
-ok</code>
-
- <p><em>Step 2:</em> Create a normal TCP listen socket:</p>
- <code type="erl">2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true}]).
-{ok, #Port&lt;0.475&gt;}</code>
-
- <p><em>Step 3:</em> Accept client connection:</p>
- <code type="erl">3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
-{ok, #Port&lt;0.476&gt;}</code>
-
- <p><em>Step 4:</em> Start the client side:</p>
- <code type="erl">1 client> ssl:start().
-ok</code>
-
- <code type="erl">2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).</code>
-
- <p><em>Step 5:</em> Ensure <c>active</c> is set to <c>false</c> before trying
- to upgrade a connection to a TLS connection, otherwise
- TLS handshake messages can be delivered to the wrong process:</p>
- <code type="erl">4 server> inet:setopts(Socket, [{active, false}]).
-ok</code>
+
+ <section>
+ <title>Upgrade Example - TLS only</title>
+
+ <p>Upgrading a a TCP/IP connection to a TLS connections is mostly
+ used when there is a desire have unencrypted communication first and
+ then later secure the communication channel by using TLS. Note that
+ the client and server need to agree to do the upgrade in the
+ protocol doing the communication. This is concept is often
+ referenced as <c>STARTLS</c> and used in many protocols such as
+ <c>SMTP</c>, <c>FTPS</c> and <c>HTTPS</c> via a proxy.
+ </p>
+
+ <warning><p>Maximum security recommendations are however moving away from such solutions.</p></warning>
- <p><em>Step 6:</em> Do the TLS handshake:</p>
- <code type="erl">5 server> {ok, TLSSocket} = ssl:handshake(Socket, [{cacertfile, "cacerts.pem"},
-{certfile, "cert.pem"}, {keyfile, "key.pem"}]).
-{ok,{sslsocket,[...]}}</code>
+ <p>To upgrade to a TLS connection:</p>
+
+ <p><em>Step 1:</em> Start the server side:</p>
+ <code type="erl">1 server> ssl:start().
+ ok</code>
+
+ <p><em>Step 2:</em> Create a normal TCP listen socket and ensure
+ <c>active</c> is set to <c>false</c> and not set to any active mode
+ otherwise TLS handshake messages can be delivered to the
+ wrong process.
+ </p>
+ <code type="erl">2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},
+ {active, false}]).
+ {ok, #Port&lt;0.475&gt;}</code>
+
+ <p><em>Step 3:</em> Accept client connection:</p>
+ <code type="erl">3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
+ {ok, #Port&lt;0.476&gt;}</code>
+
+ <p><em>Step 4:</em> Start the client side:</p>
+ <code type="erl">1 client> ssl:start().
+ ok</code>
+
+ <code type="erl">2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).</code>
+
+ <p><em>Step 5:</em> Do the TLS handshake:</p>
+ <code type="erl">4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},
+ {fail_if_no_peer_cert, true},
+ {cacertfile, "cacerts.pem"},
+ {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}]).
+ {ok,{sslsocket,[...]}}</code>
- <p><em>Step 7:</em> Upgrade to a TLS connection. The client and server
- must agree upon the upgrade. The server must call
- <c>ssl:handshake/2</c> before the client calls <c>ssl:connect/3.</c></p>
- <code type="erl">3 client>{ok, TLSSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"},
-{certfile, "cert.pem"}, {keyfile, "key.pem"}], infinity).
+ <p><em>Step 6:</em> Upgrade to a TLS connection. The client and
+ server must agree upon the upgrade. The server must be prepared to be a TLS server before the client
+ can do a successful connect.</p>
+
+ <code type="erl">3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},
+ {cacertfile, "cacerts.pem"},
+ {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}], infinity).
{ok,{sslsocket,[...]}}</code>
-
- <p><em>Step 8:</em> Send a message over TLS:</p>
+
+ <p><em>Step 7:</em> Send a message over TLS:</p>
<code type="erl">4 client> ssl:send(TLSSocket, "foo").
-ok</code>
+ ok</code>
- <p><em>Step 9:</em> Set <c>active true</c> on the TLS socket:</p>
- <code type="erl">4 server> ssl:setopts(TLSSocket, [{active, true}]).
-ok</code>
+ <p><em>Step 8:</em> Set <c>active once</c> on the TLS socket:</p>
+ <code type="erl">5 server> ssl:setopts(TLSSocket, [{active, once}]).
+ ok</code>
- <p><em>Step 10:</em> Flush the shell message queue to see that the message
- was sent on the client side:</p>
+ <p><em>Step 9:</em> Flush the shell message queue to see that
+ the message sent on the client side is recived by the server side:</p>
+
<code type="erl">5 server> flush().
-Shell got {ssl,{sslsocket,[...]},"foo"}
-ok</code>
- </section>
- </section>
+ Shell got {ssl,{sslsocket,[...]},"foo"}
+ ok</code>
+</section>
<section>
<title>Customizing cipher suites</title>
<p>Fetch default cipher suite list for a TLS/DTLS version. Change default
to all to get all possible cipher suites.</p>
+
<code type="erl">1> Default = ssl:cipher_suites(default, 'tlsv1.2').
[#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
mac => aead,prf => sha384}, ....]
@@ -183,7 +217,8 @@ ok</code>
<code type="erl">2> NoRSA =
ssl:filter_cipher_suites(Default,
[{key_exchange, fun(rsa) -> false;
- (_) -> true end}]).
+ (_) -> true
+ end}]).
[...]
</code>
@@ -191,9 +226,11 @@ ok</code>
<code type="erl"> 3> Suites =
ssl:filter_cipher_suites(Default,
[{key_exchange, fun(ecdh_ecdsa) -> true;
- (_) -> false end},
- {cipher, fun(aes_128_cbc) ->true;
- (_) ->false end}]).
+ (_) -> false
+ end},
+ {cipher, fun(aes_128_cbc) -> true;
+ (_) ->false
+ end}]).
[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
mac => sha256,prf => sha256},
#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
@@ -226,7 +263,8 @@ ok</code>
</p>
<code type="erl">2> {ok, EngineRef} =
crypto:engine_load(&lt;&lt;"dynamic">>,
- [{&lt;&lt;"SO_PATH">>, "/tmp/user/engines/MyEngine"},&lt;&lt;"LOAD">>],[]).
+[{&lt;&lt;"SO_PATH">>, "/tmp/user/engines/MyEngine"},&lt;&lt;"LOAD">>],
+[]).
{ok,#Ref&lt;0.2399045421.3028942852.173962>}
</code>
@@ -240,35 +278,34 @@ crypto:engine_load(&lt;&lt;"dynamic">>,
<code type="erl">4> {ok, SSLSocket} =
ssl:connect("localhost", 9999,
[{cacertfile, "cacerts.pem"},
- {certfile, "cert.pem"},
- {key, PrivKey}], infinity).
+ {certs_keys, [#{certfile => "cert.pem", key => PrivKey}]}
+ ], infinity).
</code>
<p>See also <seeguide marker="crypto:engine_load#engine_load"> crypto documentation</seeguide> </p>
</section>
-
<section>
<title>Session Reuse pre TLS 1.3</title>
- <p>Clients can request to reuse a session established
- by a previous full handshake between that client and server by
- sending the id of the session in the initial handshake
- message. The server may or may not agree to reuse it. If agreed
- the server will send back the id and if not it will send a new
- id. The ssl application has several options for handling session
- reuse.</p>
+
+ <p>Clients can request to reuse a session established by a
+ previous full handshake between that client and server by sending
+ the id of the session in the initial handshake message. The server
+ may or may not agree to reuse it. If agreed the server will send
+ back the id and if not it will send a new id. The ssl application
+ has several options for handling session reuse.</p>
<p>On the client side the ssl application will save session data
to try to automate session reuse on behalf of the client processes
- on the Erlang node. Note that only verified sessions will be
- saved for security reasons, that is session resumption relies on
- the certificate validation to have been run in the original
+ on the Erlang node. Note that only verified sessions will be saved
+ for security reasons, that is session resumption relies on the
+ certificate validation to have been run in the original
handshake. To minimize memory consumption only unique sessions
will be saved unless the special <c>save</c> value is specified
for the following option <c> {reuse_sessions, boolean() |
- save}</c> in which case a full handshake will be performed and that
- specific session will have been saved before the handshake
+ save}</c> in which case a full handshake will be performed and
+ that specific session will have been saved before the handshake
returns. The session id and even an opaque binary containing the
session data can be retrieved using
<c>ssl:connection_information/1</c> function. A saved session
@@ -320,7 +357,8 @@ ok
<p>Step 2- Using <c>save</c> Option </p>
<code type="erl">
-%% We want save this particular session for reuse although it has the same basis as C1
+%% We want save this particular session for
+%% reuse although it has the same basis as C1
6&gt; {ok, C3} = ssl:connect("localhost", 9999, [{verify, verify_peer},
{versions, ['tlsv1.2']},
{cacertfile, "cacerts.pem"},
@@ -365,11 +403,12 @@ ok
<code type="erl">
%% Perform a full handshake and the session will not be saved for reuse
-12&gt; {ok, C9} = ssl:connect("localhost", 9999, [{verify, verify_peer},
- {versions, ['tlsv1.2']},
- {cacertfile, "cacerts.pem"},
- {reuse_sessions, false},
- {server_name_indication, disable}]).
+12&gt; {ok, C9} =
+ssl:connect("localhost", 9999, [{verify, verify_peer},
+ {versions, ['tlsv1.2']},
+ {cacertfile, "cacerts.pem"},
+ {reuse_sessions, false},
+ {server_name_indication, disable}]).
{ok,{sslsocket,{gen_tcp,#Port&lt;0.14&gt;,tls_connection, ...}}
%% Fetch session ID and data for C9 connection
@@ -451,11 +490,10 @@ ok
<p>An example with automatic and manual session resumption:</p>
- <p><em>Step 1 (server):</em> Start the server:</p>
<code type="erl">
{ok, _} = application:ensure_all_started(ssl).
- LOpts = [{certfile, "cert.pem"},
- {keyfile, "key.pem"},
+ LOpts = [{certs_keys, [#{certfile => "cert.pem",
+ keyfile => "key.pem"}]},
{versions, ['tlsv1.2','tlsv1.3']},
{session_tickets, stateless}].
{ok, LSock} = ssl:listen(8001, LOpts).
@@ -490,8 +528,9 @@ ok
<![CDATA[<<<]]> Post-Handshake, NewSessionTicket ...
</code>
- <p>At this point the client has stored the received session tickets and ready to use them when
- establishing new connections to the same server.</p>
+ <p>At this point the client has stored the received session
+ tickets and ready to use them when establishing new connections to
+ the same server.</p>
<p><em>Step 4 (server):</em> Accept a new connection on the server:</p>
<code type="erl">
@@ -530,7 +569,7 @@ ok
<p><em>Step 8 (client):</em> Make a new connection to server:</p>
<code type="erl">
{ok, _} = application:ensure_all_started(ssl).
- COpts2 = [{cacertfile, "cert.pem"},
+ COpts2 = [{cacertfile, "cacerts.pem"},
{versions, ['tlsv1.2','tlsv1.3']},
{log_level, debug},
{session_tickets, manual}].
@@ -542,8 +581,8 @@ ok
ssl:handshake(CSock3).
</code>
- <p>After the handshake is performed, the user process receives messages with the tickets
- sent by the server.</p>
+ <p>After the handshake is performed, the user process receivess
+ messages with the tickets sent by the server.</p>
<p><em>Step 10 (client):</em> Receive a new session ticket:</p>
<code type="erl">
@@ -571,7 +610,8 @@ ok
<code type="erl">
ssl:handshake(CSock3).
</code>
- </section>
+</section>
+
<section>
<title>Early Data in TLS 1.3</title>
@@ -604,14 +644,13 @@ ok
application:load(ssl),
{ok, _} = application:ensure_all_started(ssl),
Port = 11029,
- LOpts = [{certfile, ?SERVER_CERT},
- {keyfile, ?SERVER_KEY},
- {reuseaddr, true},
- {versions, ['tlsv1.2','tlsv1.3']},
- {session_tickets, stateless},
- {early_data, enabled},
- {keep_secrets, true} %% Enable NSS key log (debug option)
- ],
+ LOpts = [{certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]},
+ {reuseaddr, true},
+ {versions, ['tlsv1.2','tlsv1.3']},
+ {session_tickets, stateless},
+ {early_data, enabled},
+ {keep_secrets, true} %% Enable NSS key log (debug option)
+ ],
{ok, LSock} = ssl:listen(Port, LOpts),
%% Accept first connection
{ok, CSock0} = ssl:transport_accept(LSock),
@@ -634,18 +673,19 @@ ok
{ok, _} = application:ensure_all_started(ssl),
Port = 11029,
Data = &lt;&lt;"HEAD / HTTP/1.1\r\nHost: \r\nConnection: close\r\n"&gt;&gt;,
- COpts0 = [{cacertfile, ?CA_CERT},
+ COpts0 = [{cacertfile, "cacerts.pem"},
{versions, ['tlsv1.2', 'tlsv1.3']},
{session_tickets, auto}],
{ok, Sock0} = ssl:connect("localhost", Port, COpts0),
%% Wait for session tickets
timer:sleep(500),
- %% Close socket if server cannot handle multiple connections e.g. openssl s_server
+ %% Close socket if server cannot handle multiple
+ %% connections e.g. openssl s_server
ssl:close(Sock0),
%% Second handshake 0-RTT
- COpts1 = [{cacertfile, ?CA_CERT},
+ COpts1 = [{cacertfile, "cacerts.pem"},
{versions, ['tlsv1.2', 'tlsv1.3']},
{session_tickets, auto},
{early_data, Data}],
@@ -660,7 +700,7 @@ ok
{ok, _} = application:ensure_all_started(ssl),
Port = 11029,
Data = &lt;&lt;"HEAD / HTTP/1.1\r\nHost: \r\nConnection: close\r\n"&gt;&gt;,
- COpts0 = [{cacertfile, ?CA_CERT},
+ COpts0 = [{cacertfile, "cacerts.pem"},
{versions, ['tlsv1.2', 'tlsv1.3']},
{session_tickets, manual}],
{ok, Sock0} = ssl:connect("localhost", Port, COpts0),
@@ -677,7 +717,7 @@ ok
ssl:close(Sock0),
%% Second handshake 0-RTT
- COpts1 = [{cacertfile, ?CA_CERT},
+ COpts1 = [{cacertfile, "cacerts.pem"},
{versions, ['tlsv1.2', 'tlsv1.3']},
{session_tickets, manual},
{use_ticket, [Ticket]},
@@ -745,4 +785,14 @@ ok
</list>
</section>
+
+ <section>
+ <title>Using DTLS</title>
+
+ <p> Using DTLS has basically the same API as TLS. You need to add the option {protocol, dtls} to the connect and listen functions. For example</p>
+
+ <code type="erl"> client> {ok, Socket} = ssl:connect("localhost", 9999, [{protocol, dtls},
+{verify, verify_peer},{cacertfile, "cacerts.pem"}], infinity).
+{ok,{sslsocket, [...]}}</code>
+ </section>
</chapter>
diff --git a/lib/ssl/examples/certs/Makefile b/lib/ssl/examples/certs/Makefile
index 5c456c6a1a..817ff2b00d 100644
--- a/lib/ssl/examples/certs/Makefile
+++ b/lib/ssl/examples/certs/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
+# Copyright Ericsson AB 2003-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@ TARGET_FILES=
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -fr $(TARGET_FILES) *~ *.beam
diff --git a/lib/ssl/examples/src/Makefile b/lib/ssl/examples/src/Makefile
index 7335bb2bb8..8b0435bfc4 100644
--- a/lib/ssl/examples/src/Makefile
+++ b/lib/ssl/examples/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
+# Copyright Ericsson AB 2003-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -fr $(TARGET_FILES) *~ *.beam
diff --git a/lib/ssl/internal_doc/pem_and_cert_cache.md b/lib/ssl/internal_doc/pem_and_cert_cache.md
new file mode 100644
index 0000000000..52fac1e6fe
--- /dev/null
+++ b/lib/ssl/internal_doc/pem_and_cert_cache.md
@@ -0,0 +1,39 @@
+# Notes on the PEM and cert caches
+## Data relations
+
+ |---------------| |------------------------|
+ | PemCache | | CertDb |
+ |---------------| * |------------------------|
+ | FilePath (PK) | +---- | {Ref, SN, Issuer} (PK) |
+ | FileContent | | | Cert (Subject) |
+ |---------------| | |------------------------|
+ |0,1 |
+ | +-----------+
+ |0,1 |1
+ |-----------------| |------------|
+ | FileMapDb | | RefDb |
+ |-----------------|1 1 |------------|
+ | CaCertFile (PK) |---------------| Ref (PK) |
+ | Ref (FK) | | Counter |
+ |-----------------| |------------|
+
+### PemCache
+1. stores a copy of file content in memory
+2. includes files from cacertfile, certfile, keyfile options
+3. content is added unless FileMapDb table contains entry with specified path
+
+### FileMapDb
+1. holds relation between specific path (PEM file with CA certificates) and a ref
+2. ref is generated when file from path is added for 1st time
+3. ref is used as path identifier in CertDb and RefDb tables
+
+### RefDb
+1. holds an active connections counter for a specific ref
+2. when counter reaches zero - related data in CertDb, FileMapDb, RefDb is deleted
+
+### CertDb
+1. holds decoded CA ceritificates (only those taken from cacertfile option)
+2. used for building certificate chains
+3. it is an ETS set table - when iterating in search of Issuer certificate,
+ processing order is not guaranted
+4. Table key is: {Ref, SerialNumber, Issuer}
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index 1e55bb497d..789bed5c3f 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -173,7 +173,7 @@ ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/src \
# Targets
# ----------------------------------------------------
-opt debug: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(DEP_FILE)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(DEP_FILE)
deps: $(DEP_FILE)
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index 65076994f9..08229d8bb5 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,7 +46,8 @@
%% ClientKeyExchange \
%% CertificateVerify* Flight 5
%% [ChangeCipherSpec] /
-%% Finished --------> /
+%% NextProtocol* /
+%% Finished --------> /
%%
%% [ChangeCipherSpec] \ Flight 6
%% <-------- Finished /
@@ -64,7 +65,8 @@
%% <-------- Finished / part 2
%%
%% [ChangeCipherSpec] \ Abbrev Flight 3
-%% Finished --------> /
+%% NextProtocol* /
+%% Finished --------> /
%%
%%
%% Message Flights for Abbbriviated Handshake
@@ -142,6 +144,7 @@
user_hello/3,
wait_ocsp_stapling/3,
certify/3,
+ wait_cert_verify/3,
cipher/3,
abbreviated/3,
connection/3]).
@@ -160,16 +163,15 @@
%%====================================================================
init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = #state{protocol_specific = Map} =
- initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ State0 = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_gen_statem:ssl_config(State0#state.ssl_options,
Role, State0),
gen_statem:enter_loop(?MODULE, [], initial_hello, State)
catch
throw:Error ->
- EState = State0#state{protocol_specific =
- Map#{error => Error}},
+ #state{protocol_specific = Map} = State0,
+ EState = State0#state{protocol_specific = Map#{error => Error}},
gen_statem:enter_loop(?MODULE, [], config_error, EState)
end.
%%====================================================================
@@ -208,13 +210,14 @@ initial_hello({call, From}, {start, Timeout},
session_cache_cb = CacheCb},
protocol_specific = PS,
handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs} = CEnv,
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts} = CEnv,
ssl_options = #{versions := Versions} = SslOpts,
session = Session0,
connection_states = ConnectionStates0
} = State0) ->
Packages = maps:get(active_n, PS),
dtls_socket:setopts(Transport, Socket, [{active,Packages}]),
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts),
Session = ssl_session:client_select_session({Host, Port, SslOpts}, Cache, CacheCb, Session0, CertKeyPairs),
Hello = dtls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
Session#session.session_id, Renegotiation),
@@ -324,14 +327,12 @@ hello(internal, #hello_verify_request{cookie = Cookie},
},
dtls_gen_connection:next_event(?FUNCTION_NAME, no_record, State, Actions);
hello(internal, #client_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #{handshake := hello},
- handshake_env = HsEnv,
+ #state{handshake_env = #handshake_env{continue_status = pause},
start_or_recv_from = From} = State0) ->
try tls_dtls_connection:handle_sni_extension(State0, Hello) of
#state{} = State ->
- {next_state, user_hello, State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{hello = Hello}},
- [{reply, From, {ok, Extensions}}]}
+ {next_state, user_hello, State#state{start_or_recv_from = undefined},
+ [{postpone, true}, {reply, From, {ok, Extensions}}]}
catch throw:#alert{} = Alert ->
alert_or_reset_connection(Alert, ?FUNCTION_NAME, State0)
end;
@@ -354,16 +355,11 @@ hello(internal, #client_hello{cookie = Cookie} = Hello, #state{static_env = #sta
hello(internal, Hello#client_hello{cookie = <<>>}, State)
end
end;
-hello(internal, #server_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #{
- handshake := hello},
- handshake_env = HsEnv,
+hello(internal, #server_hello{extensions = Extensions},
+ #state{handshake_env = #handshake_env{continue_status = pause},
start_or_recv_from = From} = State) ->
- {next_state, user_hello, State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{
- hello = Hello}},
- [{reply, From, {ok, Extensions}}]};
-
+ {next_state, user_hello, State#state{start_or_recv_from = undefined},
+ [{postpone, true},{reply, From, {ok, Extensions}}]};
hello(internal, #server_hello{} = Hello,
#state{
static_env = #static_env{role = client},
@@ -469,6 +465,24 @@ certify(state_timeout, Event, State) ->
certify(Type, Event, State) ->
gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_cert_verify(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cert_verify(enter, _Event, State0) ->
+ {State, Actions} = handle_flight_timer(State0),
+ {keep_state, State, Actions};
+wait_cert_verify(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cert_verify(state_timeout, Event, State) ->
+ handle_state_timeout(Event, ?FUNCTION_NAME, State);
+wait_cert_verify(Type, Event, State) ->
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
+
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
@@ -498,13 +512,20 @@ cipher(Type, Event, State) ->
#hello_request{} | #client_hello{}| term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-connection(enter, _, #state{connection_states = Cs0} = State0) ->
- State = case maps:is_key(previous_cs, Cs0) of
- false ->
- State0;
- true ->
- Cs = maps:remove(previous_cs, Cs0),
- State0#state{connection_states = Cs}
+connection(enter, _, #state{connection_states = Cs0,
+ static_env = Env} = State0) ->
+ State = case Env of
+ #static_env{socket = {Listener, {Client, _}}} ->
+ dtls_packet_demux:connection_setup(Listener, Client),
+ case maps:is_key(previous_cs, Cs0) of
+ false ->
+ State0;
+ true ->
+ Cs = maps:remove(previous_cs, Cs0),
+ State0#state{connection_states = Cs}
+ end;
+ _ -> %% client
+ State0
end,
{keep_state, State};
connection(info, Event, State) ->
@@ -516,13 +537,14 @@ connection(internal, #hello_request{}, #state{static_env = #static_env{host = Ho
session_cache_cb = CacheCb
},
handshake_env = #handshake_env{renegotiation = {Renegotiation, _}},
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs} = CEnv,
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts} = CEnv,
session = Session0,
ssl_options = #{versions := Versions} = SslOpts,
connection_states = ConnectionStates0,
protocol_specific = PS
} = State0) ->
#{current_cookie_secret := Cookie} = PS,
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts),
Session = ssl_session:client_select_session({Host, Port, SslOpts}, Cache, CacheCb, Session0, CertKeyPairs),
Hello = dtls_handshake:client_hello(Host, Port, Cookie, ConnectionStates0, SslOpts,
Session#session.session_id, Renegotiation, undefined),
@@ -557,14 +579,20 @@ connection(internal, #client_hello{}, #state{static_env = #static_env{role = ser
dtls_gen_connection:next_event(?FUNCTION_NAME, Record, State);
connection(internal, new_connection, #state{ssl_options=SSLOptions,
handshake_env=HsEnv,
+ static_env = #static_env{socket = {Listener, {Client, _}}},
connection_states = OldCs} = State) ->
case maps:get(previous_cs, OldCs, undefined) of
undefined ->
- BeastMitigation = maps:get(beast_mitigation, SSLOptions, disabled),
- ConnectionStates0 = dtls_record:init_connection_states(server, BeastMitigation),
- ConnectionStates = ConnectionStates0#{previous_cs => OldCs},
- {next_state, hello, State#state{handshake_env = HsEnv#handshake_env{renegotiation = {false, first}},
- connection_states = ConnectionStates}};
+ case dtls_packet_demux:new_connection(Listener, Client) of
+ true ->
+ {keep_state, State};
+ false ->
+ BeastMitigation = maps:get(beast_mitigation, SSLOptions, disabled),
+ ConnectionStates0 = dtls_record:init_connection_states(server, BeastMitigation),
+ ConnectionStates = ConnectionStates0#{previous_cs => OldCs},
+ {next_state, hello, State#state{handshake_env = HsEnv#handshake_env{renegotiation = {false, first}},
+ connection_states = ConnectionStates}}
+ end;
_ ->
%% Someone spamming new_connection, just drop them
{keep_state, State}
@@ -628,6 +656,7 @@ format_status(Type, Data) ->
initial_state(Role, Host, Port, Socket,
{#{client_renegotiation := ClientRenegotiation} = SSLOptions, SocketOptions, Trackers}, User,
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
+ put(log_level, maps:get(log_level, SSLOptions)),
BeastMitigation = maps:get(beast_mitigation, SSLOptions, disabled),
ConnectionStates = dtls_record:init_connection_states(Role, BeastMitigation),
#{session_cb := SessionCacheCb} = ssl_config:pre_1_3_session_opts(Role),
@@ -681,14 +710,14 @@ handle_client_hello(#client_hello{client_version = ClientVersion} = Hello, State
handshake_env = #handshake_env{kex_algorithm = KeyExAlg,
renegotiation = {Renegotiation, _},
negotiated_protocol = CurrentProtocol} = HsEnv,
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs} = CEnv,
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts} = CEnv,
session = Session0,
ssl_options = SslOpts} =
tls_dtls_connection:handle_sni_extension(State0, Hello),
SessionTracker = proplists:get_value(session_id_tracker, Trackers),
{Version, {Type, Session}, ConnectionStates, Protocol0, ServerHelloExt, HashSign} =
dtls_handshake:hello(Hello, SslOpts, {SessionTracker, Session0,
- ConnectionStates0, CertKeyPairs, KeyExAlg}, Renegotiation),
+ ConnectionStates0, CertKeyAlts, KeyExAlg}, Renegotiation),
Protocol = case Protocol0 of
undefined -> CurrentProtocol;
_ -> Protocol0
@@ -738,20 +767,23 @@ gen_handshake(StateName, Type, Event, State) ->
catch
throw:#alert{}=Alert ->
alert_or_reset_connection(Alert, StateName, State);
- error:_ ->
+ error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
Alert = ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data),
alert_or_reset_connection(Alert, StateName, State)
end.
gen_info(Event, connection = StateName, State) ->
try dtls_gen_connection:handle_info(Event, StateName, State)
- catch error:_ ->
+ catch error:Reason:ST ->
+ ?SSL_LOG(info, internal_error, [{error, Reason}, {stacktrace, ST}]),
Alert = ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, malformed_data),
alert_or_reset_connection(Alert, StateName, State)
end;
gen_info(Event, StateName, State) ->
try dtls_gen_connection:handle_info(Event, StateName, State)
- catch error:_ ->
+ catch error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
Alert = ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,malformed_handshake_data),
alert_or_reset_connection(Alert, StateName, State)
end.
diff --git a/lib/ssl/src/dtls_gen_connection.erl b/lib/ssl/src/dtls_gen_connection.erl
index 4964d3d21f..c075fa5879 100644
--- a/lib/ssl/src/dtls_gen_connection.erl
+++ b/lib/ssl/src/dtls_gen_connection.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -572,6 +572,12 @@ handle_info(new_cookie_secret, StateName,
{next_state, StateName, State#state{protocol_specific =
CookieInfo#{current_cookie_secret => dtls_v1:cookie_secret(),
previous_cookie_secret => Secret}}};
+handle_info({socket_reused, Client}, StateName,
+ #state{static_env = #static_env{socket = {_, {Client, _}}}} = State) ->
+ Alert = ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY, transport_closed),
+ ssl_gen_statem:handle_normal_shutdown(Alert#alert{role = server}, StateName, State),
+ {stop, {shutdown, transport_closed}, State};
+
handle_info(Msg, StateName, State) ->
ssl_gen_statem:handle_info(Msg, StateName, State).
diff --git a/lib/ssl/src/dtls_packet_demux.erl b/lib/ssl/src/dtls_packet_demux.erl
index 19f1d2359c..c4cdb2eb01 100644
--- a/lib/ssl/src/dtls_packet_demux.erl
+++ b/lib/ssl/src/dtls_packet_demux.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2023. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -33,6 +33,8 @@
sockname/1,
close/1,
new_owner/1,
+ new_connection/2,
+ connection_setup/2,
get_all_opts/1,
set_all_opts/2,
get_sock_opts/2,
@@ -55,7 +57,6 @@
dtls_options,
emulated_options,
dtls_msq_queues = kv_new(),
- clients = set_new(),
dtls_processes = kv_new(),
accepters = queue:new(),
first,
@@ -85,6 +86,12 @@ close(PacketSocket) ->
new_owner(PacketSocket) ->
call(PacketSocket, new_owner).
+new_connection(PacketSocket, Client) ->
+ call(PacketSocket, {new_connection, Client, self()}).
+
+connection_setup(PacketSocket, Client) ->
+ gen_server:cast(PacketSocket, {connection_setup, Client}).
+
get_sock_opts(PacketSocket, SplitSockOpts) ->
call(PacketSocket, {get_sock_opts, SplitSockOpts}).
get_all_opts(PacketSocket) ->
@@ -146,6 +153,18 @@ handle_call(close, _, #state{dtls_processes = Processes,
end;
handle_call(new_owner, _, State) ->
{reply, ok, State#state{close = false, first = true}};
+handle_call({new_connection, Old, _Pid}, _,
+ #state{accepters = Accepters, dtls_msq_queues = MsgQs0} = State) ->
+ case queue:is_empty(Accepters) of
+ false ->
+ OldQueue = kv_get(Old, MsgQs0),
+ MsgQs1 = kv_delete(Old, MsgQs0),
+ MsgQs = kv_insert({old,Old}, OldQueue, MsgQs1),
+ {reply, true, State#state{dtls_msq_queues = MsgQs}};
+ true ->
+ {reply, false, State}
+ end;
+
handle_call({get_sock_opts, {SocketOptNames, EmOptNames}}, _, #state{listener = Socket,
emulated_options = EmOpts} = State) ->
case get_socket_opts(Socket, SocketOptNames) of
@@ -170,7 +189,16 @@ handle_call({getstat, Options}, _, #state{listener = Socket, transport = {Tran
handle_cast({active_once, Client, Pid}, State0) ->
State = handle_active_once(Client, Pid, State0),
- {noreply, State}.
+ {noreply, State};
+handle_cast({connection_setup, Client}, #state{dtls_msq_queues = MsgQueues} = State) ->
+ case kv_lookup({old, Client}, MsgQueues) of
+ none ->
+ {noreply, State};
+ {value, {Pid, _}} ->
+ Pid ! {socket_reused, Client},
+ %% Will be deleted when handling DOWN message
+ {noreply, State}
+ end.
handle_info({Transport, Socket, IP, InPortNo, _} = Msg, #state{listener = Socket, transport = {_,Transport,_,_,_}} = State0) ->
State = handle_datagram({IP, InPortNo}, Msg, State0),
@@ -190,24 +218,40 @@ handle_info({udp_error, Socket, econnreset = Error}, #state{listener = Socket, t
?LOG_NOTICE(Report),
{noreply, State};
handle_info({ErrorTag, Socket, Error}, #state{listener = Socket, transport = {_,_,_, ErrorTag,_}} = State) ->
- Report = io_lib:format("SSL Packet muliplxer shutdown: Socket error: ~p ~n", [Error]),
+ Report = io_lib:format("SSL Packet muliplexer shutdown: Socket error: ~p ~n", [Error]),
?LOG_NOTICE(Report),
{noreply, State#state{close=true}};
-handle_info({'DOWN', _, process, Pid, _}, #state{clients = Clients,
- dtls_processes = Processes0,
- dtls_msq_queues = MsgQueues0,
- close = ListenClosed} = State) ->
+handle_info({'DOWN', _, process, Pid, _},
+ #state{dtls_processes = Processes0,
+ dtls_msq_queues = MsgQueues0,
+ close = ListenClosed} = State0) ->
Client = kv_get(Pid, Processes0),
Processes = kv_delete(Pid, Processes0),
- MsgQueues = kv_delete(Client, MsgQueues0),
+ State = case kv_lookup(Client, MsgQueues0) of
+ none ->
+ MsgQueues1 = kv_delete({old, Client}, MsgQueues0),
+ State0#state{dtls_processes = Processes, dtls_msq_queues = MsgQueues1};
+ {value, {Pid, _}} ->
+ MsgQueues1 = kv_delete(Client, MsgQueues0),
+ %% Restore old process if exists
+ case kv_lookup({old, Client}, MsgQueues1) of
+ none ->
+ State0#state{dtls_processes = Processes, dtls_msq_queues = MsgQueues1};
+ {value, Old} ->
+ MsgQueues2 = kv_delete({old, Client}, MsgQueues1),
+ MsgQueues = kv_insert(Client, Old, MsgQueues2),
+ State0#state{dtls_processes = Processes, dtls_msq_queues = MsgQueues}
+ end;
+ {value, _} -> %% Old process died (just delete its queue)
+ MsgQueues1 = kv_delete({old, Client}, MsgQueues0),
+ State0#state{dtls_processes = Processes, dtls_msq_queues = MsgQueues1}
+ end,
case ListenClosed andalso kv_empty(Processes) of
true ->
{stop, normal, State};
false ->
- {noreply, State#state{clients = set_delete(Client, Clients),
- dtls_processes = Processes,
- dtls_msq_queues = MsgQueues}}
+ {noreply, State}
end.
terminate(_Reason, _State) ->
@@ -219,55 +263,57 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
-handle_datagram(Client, Msg, #state{clients = Clients,
- accepters = AcceptorsQueue0} = State) ->
- case set_is_member(Client, Clients) of
- false ->
+handle_datagram(Client, Msg, #state{dtls_msq_queues = MsgQueues, accepters = AcceptorsQueue0} = State) ->
+ case kv_lookup(Client, MsgQueues) of
+ none ->
case queue:out(AcceptorsQueue0) of
- {{value, {UserPid, From}}, AcceptorsQueue} ->
- setup_new_connection(UserPid, From, Client, Msg,
+ {{value, {UserPid, From}}, AcceptorsQueue} ->
+ setup_new_connection(UserPid, From, Client, Msg,
State#state{accepters = AcceptorsQueue});
{empty, _} ->
%% Drop packet client will resend
State
end;
- true ->
- dispatch(Client, Msg, State)
+ {value, Queue} ->
+ dispatch(Queue, Client, Msg, State)
end.
-dispatch(Client, Msg, #state{dtls_msq_queues = MsgQueues} = State) ->
- case kv_lookup(Client, MsgQueues) of
- {value, Queue0} ->
- case queue:out(Queue0) of
- {{value, Pid}, Queue} when is_pid(Pid) ->
- Pid ! Msg,
- State#state{dtls_msq_queues =
- kv_update(Client, Queue, MsgQueues)};
- {{value, _UDP}, _Queue} ->
- State#state{dtls_msq_queues =
- kv_update(Client, queue:in(Msg, Queue0), MsgQueues)};
- {empty, Queue} ->
- State#state{dtls_msq_queues =
- kv_update(Client, queue:in(Msg, Queue), MsgQueues)}
- end
+dispatch({Pid, Queue0}, Client, Msg, #state{dtls_msq_queues = MsgQueues} = State) ->
+ case queue:out(Queue0) of
+ {{value, Pid}, Queue} when is_pid(Pid) ->
+ Pid ! Msg,
+ State#state{dtls_msq_queues =
+ kv_update(Client, {Pid, Queue}, MsgQueues)};
+ {{value, _UDP}, _Queue} ->
+ State#state{dtls_msq_queues =
+ kv_update(Client, {Pid, queue:in(Msg, Queue0)}, MsgQueues)};
+ {empty, Queue} ->
+ State#state{dtls_msq_queues =
+ kv_update(Client, {Pid, queue:in(Msg, Queue)}, MsgQueues)}
end.
+
next_datagram(Socket, N) ->
inet:setopts(Socket, [{active, N}]).
handle_active_once(Client, Pid, #state{dtls_msq_queues = MsgQueues} = State0) ->
- Queue0 = kv_get(Client, MsgQueues),
+ {Key, Queue0} = case kv_lookup(Client, MsgQueues) of
+ {value, {Pid, Q0}} -> {Client, Q0};
+ _ ->
+ OldKey = {old, Client},
+ {Pid, Q0} = kv_get(OldKey, MsgQueues),
+ {OldKey, Q0}
+ end,
case queue:out(Queue0) of
- {{value, Pid}, _} when is_pid(Pid) ->
- State0;
- {{value, Msg}, Queue} ->
- Pid ! Msg,
- State0#state{dtls_msq_queues = kv_update(Client, Queue, MsgQueues)};
- {empty, Queue0} ->
- State0#state{dtls_msq_queues = kv_update(Client, queue:in(Pid, Queue0), MsgQueues)}
+ {{value, Pid}, _} when is_pid(Pid) ->
+ State0;
+ {{value, Msg}, Queue} ->
+ Pid ! Msg,
+ State0#state{dtls_msq_queues = kv_update(Key, {Pid, Queue}, MsgQueues)};
+ {empty, Queue0} ->
+ State0#state{dtls_msq_queues = kv_update(Key, {Pid, queue:in(Pid, Queue0)}, MsgQueues)}
end.
setup_new_connection(User, From, Client, Msg, #state{dtls_processes = Processes,
- clients = Clients,
dtls_msq_queues = MsgQueues,
dtls_options = DTLSOpts,
port = Port,
@@ -281,8 +327,7 @@ setup_new_connection(User, From, Client, Msg, #state{dtls_processes = Processes,
erlang:monitor(process, Pid),
gen_server:reply(From, {ok, Pid, {Client, Socket}}),
Pid ! Msg,
- State#state{clients = set_insert(Client, Clients),
- dtls_msq_queues = kv_insert(Client, queue:new(), MsgQueues),
+ State#state{dtls_msq_queues = kv_insert(Client, {Pid, queue:new()}, MsgQueues),
dtls_processes = kv_insert(Pid, Client, Processes)};
{error, Reason} ->
gen_server:reply(From, {error, Reason}),
@@ -295,7 +340,7 @@ kv_lookup(Key, Store) ->
gb_trees:lookup(Key, Store).
kv_insert(Key, Value, Store) ->
gb_trees:insert(Key, Value, Store).
-kv_get(Key, Store) ->
+kv_get(Key, Store) ->
gb_trees:get(Key, Store).
kv_delete(Key, Store) ->
gb_trees:delete(Key, Store).
@@ -304,15 +349,6 @@ kv_new() ->
kv_empty(Store) ->
gb_trees:is_empty(Store).
-set_new() ->
- gb_sets:empty().
-set_insert(Item, Set) ->
- gb_sets:insert(Item, Set).
-set_delete(Item, Set) ->
- gb_sets:delete(Item, Set).
-set_is_member(Item, Set) ->
- gb_sets:is_member(Item, Set).
-
call(Server, Msg) ->
try
gen_server:call(Server, Msg, infinity)
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index 6efc2dc8be..dadb16d250 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -175,9 +175,9 @@ current_connection_state_epoch(#{current_write := #{epoch := Epoch}},
%% and returns it as a list of tls_compressed binaries also returns leftover
%% data
%%--------------------------------------------------------------------
-get_dtls_records(Data, Vinfo, Buffer, SslOpts) ->
+get_dtls_records(Data, Vinfo, Buffer, #{log_level := LogLevel}) ->
BinData = list_to_binary([Buffer, Data]),
- get_dtls_records_aux(Vinfo, BinData, [], SslOpts).
+ get_dtls_records_aux(Vinfo, BinData, [], LogLevel).
%%====================================================================
%% Encoding DTLS records
@@ -423,40 +423,48 @@ initial_connection_state(ConnectionEnd, BeastMitigation) ->
max_fragment_length => undefined
}.
-get_dtls_records_aux({DataTag, StateName, _, Versions} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Epoch), ?UINT48(SequenceNumber),
- ?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
- Acc, #{log_level := LogLevel} = SslOpts)
+get_dtls_records_aux({DataTag, StateName, _, Versions} = Vinfo,
+ <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Epoch), ?UINT48(SequenceNumber),
+ ?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
+ Acc0, LogLevel)
when ((StateName == hello)
orelse ((StateName == certify) andalso (DataTag == udp))
- orelse ((StateName == abbreviated) andalso (DataTag == udp))) andalso ((Type == ?HANDSHAKE)
- orelse
- (Type == ?ALERT)) ->
+ orelse ((StateName == abbreviated) andalso (DataTag == udp)))
+ andalso ((Type == ?HANDSHAKE) orelse (Type == ?ALERT)) ->
ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]),
+ Acc = [#ssl_tls{type = Type, version = {MajVer, MinVer},
+ epoch = Epoch, sequence_number = SequenceNumber,
+ fragment = Data} | Acc0],
case is_acceptable_version({MajVer, MinVer}, Versions) of
true ->
- get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type,
- version = {MajVer, MinVer},
- epoch = Epoch, sequence_number = SequenceNumber,
- fragment = Data} | Acc], SslOpts);
+ get_dtls_records_aux(Vinfo, Rest, Acc, LogLevel);
false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end;
-get_dtls_records_aux({_, _, Version, _} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
- ?UINT16(Epoch), ?UINT48(SequenceNumber),
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+get_dtls_records_aux({_, _, Version, Versions} = Vinfo,
+ <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
+ ?UINT16(Epoch), ?UINT48(SequenceNumber),
?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
- Acc, #{log_level := LogLevel} = SslOpts) when (Type == ?APPLICATION_DATA) orelse
- (Type == ?HANDSHAKE) orelse
- (Type == ?ALERT) orelse
- (Type == ?CHANGE_CIPHER_SPEC) ->
+ Acc0, LogLevel)
+ when (Type == ?APPLICATION_DATA) orelse
+ (Type == ?HANDSHAKE) orelse
+ (Type == ?ALERT) orelse
+ (Type == ?CHANGE_CIPHER_SPEC) ->
ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]),
- case {MajVer, MinVer} of
- Version ->
- get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type,
- version = {MajVer, MinVer},
- epoch = Epoch, sequence_number = SequenceNumber,
- fragment = Data} | Acc], SslOpts);
- _ ->
+ Acc = [#ssl_tls{type = Type, version = {MajVer,MinVer},
+ epoch = Epoch, sequence_number = SequenceNumber,
+ fragment = Data} | Acc0],
+ if {MajVer, MinVer} =:= Version ->
+ get_dtls_records_aux(Vinfo, Rest, Acc, LogLevel);
+ Type == ?HANDSHAKE ->
+ case is_acceptable_version({MajVer, MinVer}, Versions) of
+ true ->
+ get_dtls_records_aux(Vinfo, Rest, Acc, LogLevel);
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end;
+ true ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end;
get_dtls_records_aux(_, <<?BYTE(_), ?BYTE(_MajVer), ?BYTE(_MinVer),
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index c234bf81be..9118fb59f6 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -232,7 +232,7 @@ gen_accept(Driver, Listen) ->
%% smaller than MaxPending
accept_loop(DLK, undefined, MaxPending, Pending) when map_size(Pending) < MaxPending ->
accept_loop(DLK, spawn_accept(DLK), MaxPending, Pending);
-accept_loop(DLK, HandshakePid, MaxPending, Pending) ->
+accept_loop({_, _, NetKernelPid} = DLK, HandshakePid, MaxPending, Pending) ->
receive
{continue, HandshakePid} when is_pid(HandshakePid) ->
accept_loop(DLK, undefined, MaxPending, Pending#{HandshakePid => true});
@@ -244,6 +244,9 @@ accept_loop(DLK, HandshakePid, MaxPending, Pending) ->
%% HandshakePid crashed before turning into Pending, which means
%% error happened in accept. Need to restart the listener.
exit(Reason);
+ {'EXIT', NetKernelPid, Reason} ->
+ %% Since we're trapping exits, need to manually propagate this signal
+ exit(Reason);
Unexpected ->
?LOG_WARNING("TLS distribution: unexpected message: ~p~n" ,[Unexpected]),
accept_loop(DLK, HandshakePid, MaxPending, Pending)
@@ -440,7 +443,7 @@ gen_accept_connection(
Driver, AcceptPid, DistCtrl,
MyNode, Allowed, SetupTime, Kernel)
end,
- [link, {priority, max}])).
+ dist_util:net_ticker_spawn_options())).
do_accept(
_Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime, Kernel) ->
@@ -539,7 +542,7 @@ gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
Kernel = self(),
monitor_pid(
spawn_opt(setup_fun(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime),
- [link, {priority, max}])).
+ dist_util:net_ticker_spawn_options())).
-spec setup_fun(_,_,_,_,_,_,_) -> fun(() -> no_return()).
setup_fun(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) ->
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index a43a84f26d..b5cb6b5d91 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -2,7 +2,7 @@
[{description, "Erlang/OTP SSL application"},
{vsn, "%VSN%"},
{modules, [
- %% TLS/SSL
+ %% TLS/SSL
tls_connection,
tls_connection_1_3,
tls_handshake,
@@ -34,7 +34,7 @@
dtls_server_sup,
dtls_server_session_cache_sup,
%% API
- ssl, %% Main API
+ ssl, %% Main API
ssl_session_cache_api,
%% Both TLS/SSL and DTLS
tls_dtls_connection,
@@ -46,7 +46,7 @@
ssl_cipher_format,
ssl_srp_primes,
ssl_alert,
- ssl_listen_tracker_sup, %% may be used by DTLS over SCTP
+ ssl_listen_tracker_sup, %% may be used by DTLS over SCTP
tls_bloom_filter,
tls_client_ticket_store,
%% Erlang Distribution over SSL/TLS
@@ -55,8 +55,8 @@
ssl_dist_sup,
ssl_dist_connection_sup,
ssl_dist_admin_sup,
- tls_dist_sup,
- tls_dist_server_sup,
+ tls_dist_sup,
+ tls_dist_server_sup,
%% SSL/TLS session and cert handling
ssl_session,
ssl_client_session_cache_db,
@@ -70,7 +70,7 @@
ssl_certificate,
%% CRL handling
ssl_crl,
- ssl_crl_cache,
+ ssl_crl_cache,
ssl_crl_cache_api,
ssl_crl_hash_dir,
%% Logging
@@ -85,6 +85,6 @@
{applications, [crypto, public_key, kernel, stdlib]},
{env, []},
{mod, {ssl_app, []}},
- {runtime_dependencies, ["stdlib-3.12","public_key-1.11.3","kernel-8.0",
+ {runtime_dependencies, ["stdlib-4.1","public_key-1.11.3","kernel-8.4",
"erts-10.0","crypto-5.0", "inets-5.10.7",
"runtime_tools-1.15.1"]}]}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 2b88568927..ad5028655d 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -26,6 +26,7 @@
-module(ssl).
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
-include("ssl_internal.hrl").
-include("ssl_api.hrl").
@@ -310,7 +311,8 @@
{certfile, cert_pem()} |
{key, key()} |
{keyfile, key_pem()} |
- {password, key_password()} |
+ {password, key_pem_password()} |
+ {certs_keys, certs_keys()} |
{ciphers, cipher_suites()} |
{eccs, [named_curve()]} |
{signature_algs, signature_algs()} |
@@ -334,7 +336,8 @@
{ssl_imp, ssl_imp()} |
{session_tickets, session_tickets()} |
{key_update_at, key_update_at()} |
- {middlebox_comp_mode, middlebox_comp_mode()}.
+ {receiver_spawn_opts, spawn_opts()} |
+ {sender_spawn_opts, spawn_opts()}.
-type protocol() :: tls | dtls.
-type handshake_completion() :: hello | full.
@@ -347,8 +350,14 @@
key_id := crypto:key_id(),
password => crypto:password()}. % exported
-type key_pem() :: file:filename().
--type key_password() :: string() | fun(() -> string()).
--type cipher_suites() :: ciphers().
+-type key_pem_password() :: iodata() | fun(() -> iodata()).
+-type certs_keys() :: [cert_key_conf()].
+-type cert_key_conf() :: #{cert => cert(),
+ key => key(),
+ certfile => cert_pem(),
+ keyfile => key_pem(),
+ password => key_pem_password()}.
+-type cipher_suites() :: ciphers().
-type ciphers() :: [erl_cipher_suite()] |
string(). % (according to old API) exported
-type cipher_filters() :: list({key_exchange | cipher | mac | prf,
@@ -391,6 +400,7 @@
-type middlebox_comp_mode() :: boolean().
-type client_early_data() :: binary().
-type server_early_data() :: disabled | enabled.
+-type spawn_opts() :: [erlang:spawn_opt_option()].
%% -------------------------------------------------------------------------------------------------------
@@ -407,7 +417,8 @@
{max_fragment_length, max_fragment_length()} |
{customize_hostname_check, customize_hostname_check()} |
{fallback, fallback()} |
- {certificate_authorities, certificate_authorities()} |
+ {middlebox_comp_mode, middlebox_comp_mode()} |
+ {certificate_authorities, client_certificate_authorities()} |
{session_tickets, client_session_tickets()} |
{use_ticket, use_ticket()} |
{early_data, client_early_data()}.
@@ -418,8 +429,8 @@
-type client_verify_type() :: verify_type().
-type client_reuse_session() :: session_id() | {session_id(), SessionData::binary()}.
-type client_reuse_sessions() :: boolean() | save.
--type certificate_authorities() :: boolean().
--type client_cacerts() :: [public_key:der_encoded()].
+-type client_certificate_authorities() :: boolean().
+-type client_cacerts() :: [public_key:der_encoded()] | [public_key:combined_cert()].
-type client_cafile() :: file:filename().
-type app_level_protocol() :: binary().
-type client_alpn() :: [app_level_protocol()].
@@ -447,6 +458,7 @@
{dhfile, dh_file()} |
{verify, server_verify_type()} |
{fail_if_no_peer_cert, fail_if_no_peer_cert()} |
+ {certificate_authorities, server_certificate_authorities()} |
{reuse_sessions, server_reuse_sessions()} |
{reuse_session, server_reuse_session()} |
{alpn_preferred_protocols, server_alpn()} |
@@ -462,7 +474,7 @@
{cookie, cookie()} |
{early_data, server_early_data()}.
--type server_cacerts() :: [public_key:der_encoded()].
+-type server_cacerts() :: [public_key:der_encoded()] | [public_key:combined_cert()].
-type server_cafile() :: file:filename().
-type server_alpn() :: [app_level_protocol()].
-type server_next_protocol() :: [app_level_protocol()].
@@ -479,6 +491,7 @@
-type honor_ecc_order() :: boolean().
-type client_renegotiation() :: boolean().
-type cookie() :: boolean().
+-type server_certificate_authorities() :: boolean().
%% -------------------------------------------------------------------------------------------------------
-type prf_random() :: client_random | server_random. % exported
-type protocol_extensions() :: #{renegotiation_info => binary(),
@@ -1395,39 +1408,15 @@ clear_pem_cache() ->
ssl_pem_cache:clear().
%%---------------------------------------------------------------
--spec format_error({error, Reason}) -> string() when
+-spec format_error(Reason | {error, Reason}) -> string() when
Reason :: any().
%%
%% Description: Creates error string.
%%--------------------------------------------------------------------
format_error({error, Reason}) ->
- format_error(Reason);
-format_error(Reason) when is_list(Reason) ->
- Reason;
-format_error(closed) ->
- "TLS connection is closed";
-format_error({tls_alert, {_, Description}}) ->
- Description;
-format_error({options,{FileType, File, Reason}}) when FileType == cacertfile;
- FileType == certfile;
- FileType == keyfile;
- FileType == dhfile ->
- Error = file_error_format(Reason),
- file_desc(FileType) ++ File ++ ": " ++ Error;
-format_error({options, {socket_options, Option, Error}}) ->
- lists:flatten(io_lib:format("Invalid transport socket option ~p: ~s", [Option, format_error(Error)]));
-format_error({options, {socket_options, Option}}) ->
- lists:flatten(io_lib:format("Invalid socket option: ~p", [Option]));
-format_error({options, Options}) ->
- lists:flatten(io_lib:format("Invalid TLS option: ~p", [Options]));
-
-format_error(Error) ->
- case inet:format_error(Error) of
- "unknown POSIX" ++ _ ->
- unexpected_format(Error);
- Other ->
- Other
- end.
+ do_format_error(Reason);
+format_error(Reason) ->
+ do_format_error(Reason).
tls_version({3, _} = Version) ->
Version;
@@ -1673,11 +1662,11 @@ handle_option(fallback = Option, Value0, OptionsMap, #{role := Role}) ->
assert_role(client_only, Role, Option, Value0),
Value = validate_option(Option, Value0),
OptionsMap#{Option => Value};
-handle_option(certificate_authorities = Option, unbound, OptionsMap, #{role := Role}) ->
- Value = default_option_role(client, false, Role),
- OptionsMap#{Option => Value};
-handle_option(certificate_authorities = Option, Value0, #{versions := Versions} = OptionsMap, #{role := Role}) ->
- assert_role(client_only, Role, Option, Value0),
+handle_option(certificate_authorities = Option, unbound, OptionsMap, #{role := server}) ->
+ OptionsMap#{Option => true};
+handle_option(certificate_authorities = Option, unbound, OptionsMap, #{role := client}) ->
+ OptionsMap#{Option => false};
+handle_option(certificate_authorities = Option, Value0, #{versions := Versions} = OptionsMap, _Env) ->
assert_option_dependency(Option, versions, Versions, ['tlsv1.3']),
Value = validate_option(Option, Value0),
OptionsMap#{Option => Value};
@@ -1713,6 +1702,13 @@ handle_option(key_update_at = Option, Value0, #{versions := Versions} = OptionsM
assert_option_dependency(Option, versions, Versions, ['tlsv1.3']),
Value = validate_option(Option, Value0),
OptionsMap#{Option => Value};
+handle_option(log_level = Option, unbound, OptionsMap, _Env) ->
+ DefaultLevel = case logger:get_module_level(?MODULE) of
+ [] -> notice;
+ [{ssl,Level}] -> Level
+ end,
+ Value = validate_option(Option, DefaultLevel),
+ OptionsMap#{Option => Value};
handle_option(next_protocols_advertised = Option, unbound, OptionsMap,
#{rules := Rules}) ->
Value = validate_option(Option, default_value(Option, Rules)),
@@ -1746,6 +1742,11 @@ handle_option(password = Option, unbound, OptionsMap, #{rules := Rules}) ->
handle_option(password = Option, Value0, OptionsMap, _Env) ->
Value = validate_option(Option, Value0),
OptionsMap#{password => Value};
+handle_option(certs_keys, unbound, OptionsMap, _Env) ->
+ OptionsMap;
+handle_option(certs_keys = Option, Value0, OptionsMap, _Env) ->
+ Value = validate_option(Option, Value0),
+ OptionsMap#{certs_keys => Value};
handle_option(psk_identity = Option, unbound, OptionsMap, #{rules := Rules}) ->
Value = validate_option(Option, default_value(Option, Rules)),
OptionsMap#{Option => Value};
@@ -2086,10 +2087,10 @@ validate_option(cacertfile, undefined, _) ->
<<>>;
validate_option(cacertfile, Value, _)
when is_binary(Value) ->
- Value;
+ unambiguous_path(Value);
validate_option(cacertfile, Value, _)
when is_list(Value), Value =/= ""->
- binary_filename(Value);
+ binary_filename(unambiguous_path(Value));
validate_option(cacerts, Value, _)
when Value == undefined;
is_list(Value) ->
@@ -2293,11 +2294,13 @@ validate_option(partial_chain, Value, _)
when is_function(Value) ->
Value;
validate_option(password, Value, _)
- when is_list(Value) ->
+ when is_list(Value); is_binary(Value) ->
Value;
validate_option(password, Value, _)
when is_function(Value, 0) ->
Value;
+validate_option(certs_keys, Value, _) when is_list(Value) ->
+ Value;
validate_option(protocol, Value = tls, _) ->
Value;
validate_option(protocol, Value = dtls, _) ->
@@ -2307,6 +2310,9 @@ validate_option(psk_identity, undefined, _) ->
validate_option(psk_identity, Identity, _)
when is_list(Identity), Identity =/= "", length(Identity) =< 65535 ->
binary_filename(Identity);
+validate_option(receiver_spawn_opts, Value, _)
+ when is_list(Value) ->
+ Value;
validate_option(renegotiate_at, Value, _) when is_integer(Value) ->
erlang:min(Value, ?DEFAULT_RENEGOTIATE_AT);
validate_option(reuse_session, undefined, _) ->
@@ -2329,6 +2335,9 @@ validate_option(reuse_sessions, save = Value, _) ->
validate_option(secure_renegotiate, Value, _)
when is_boolean(Value) ->
Value;
+validate_option(sender_spawn_opts, Value, _)
+ when is_list(Value) ->
+ Value;
validate_option(server_name_indication, Value, _)
when is_list(Value) ->
%% RFC 6066, Section 3: Currently, the only server names supported are
@@ -2465,7 +2474,7 @@ handle_hashsigns_option(_, _Version) ->
undefined.
handle_signature_algorithms_option(Value, Version) when is_list(Value)
- andalso Version >= {3, 4} ->
+ andalso Version >= {3, 3} ->
case tls_v1:signature_schemes(Version, Value) of
[] ->
throw({error, {options,
@@ -2555,7 +2564,7 @@ dtls_validate_versions([Version | Rest], Versions) when Version == 'dtlsv1';
dtls_validate_versions([Ver| _], Versions) ->
throw({error, {options, {Ver, {versions, Versions}}}}).
-%% The option cacerts overrides cacertsfile
+%% The option cacerts overrides cacertfile
ca_cert_default(_,_, [_|_]) ->
undefined;
ca_cert_default(verify_none, _, _) ->
@@ -2679,6 +2688,47 @@ handle_supported_groups_option(Value, Version) when is_list(Value) ->
end.
+-spec do_format_error( string()
+ | closed
+ | {tls_alert, {_, Description :: string()}}
+ | {options, Options :: term()}
+ | {options, {socket_options, Option :: term()}}
+ | {options, {socket_options, Option :: term(), Error}}
+ | {options, {FileType, File :: string(), Error}}
+ | InetError
+ | OtherReason) -> string()
+ when
+ FileType :: cacertfile | certfile | keyfile | dhfile,
+ OtherReason :: term(),
+ InetError :: inet:posix() | system_limit.
+
+do_format_error(Reason) when is_list(Reason) ->
+ Reason;
+do_format_error(closed) ->
+ "TLS connection is closed";
+do_format_error({tls_alert, {_, Description}}) ->
+ Description;
+do_format_error({options,{FileType, File, Reason}}) when FileType == cacertfile;
+ FileType == certfile;
+ FileType == keyfile;
+ FileType == dhfile ->
+ Error = file_error_format(Reason),
+ file_desc(FileType) ++ File ++ ": " ++ Error;
+do_format_error ({options, {socket_options, Option, Error}}) ->
+ lists:flatten(io_lib:format("Invalid transport socket option ~p: ~s", [Option, do_format_error(Error)]));
+do_format_error({options, {socket_options, Option}}) ->
+ lists:flatten(io_lib:format("Invalid socket option: ~p", [Option]));
+do_format_error({options, Options}) ->
+ lists:flatten(io_lib:format("Invalid TLS option: ~p", [Options]));
+
+do_format_error(Error) ->
+ case inet:format_error(Error) of
+ "unknown POSIX" ++ _ ->
+ unexpected_format(Error);
+ Other ->
+ Other
+ end.
+
unexpected_format(Error) ->
lists:flatten(io_lib:format("Unexpected error: ~p", [Error])).
@@ -2849,8 +2899,25 @@ add_filter(Filter, Filters) ->
maybe_client_warn_no_verify(#{verify := verify_none,
warn_verify_none := true,
log_level := LogLevel}, client) ->
- ssl_logger:log(warning, LogLevel, #{description => "Authenticity is not established by certificate path validation",
- reason => "Option {verify, verify_peer} and cacertfile/cacerts is missing"}, #{});
+ ssl_logger:log(warning, LogLevel,
+ #{description => "Server authenticity is not verified since certificate path validation is not enabled",
+ reason => "The option {verify, verify_peer} and one of the options 'cacertfile' or "
+ "'cacerts' are required to enable this."}, ?LOCATION);
maybe_client_warn_no_verify(_,_) ->
%% Warning not needed. Note client certificate validation is optional in TLS
ok.
+
+unambiguous_path(Value) ->
+ AbsName = filename:absname(Value),
+ case file:read_link(AbsName) of
+ {ok, PathWithNoLink} ->
+ case filename:pathtype(PathWithNoLink) of
+ relative ->
+ Dirname = filename:dirname(AbsName),
+ filename:join([Dirname, PathWithNoLink]);
+ _ ->
+ PathWithNoLink
+ end;
+ _ ->
+ AbsName
+ end.
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index eef6aa875a..2e2b43f564 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -80,7 +80,9 @@
public_key_type/1,
foldl_db/3,
find_cross_sign_root_paths/4,
- handle_cert_auths/4
+ handle_cert_auths/4,
+ available_cert_key_pairs/1,
+ available_cert_key_pairs/2
]).
%%====================================================================
@@ -307,25 +309,60 @@ find_cross_sign_root_paths([_ | Rest] = Path, CertDbHandle, CertDbRef, Invalidat
end.
handle_cert_auths(Chain, [], _, _) ->
- %% If we have no authorities extension to check we just accept
- %% first choice
+ %% If we have no authorities extension (or corresponding
+ %% 'certificate_authorities' in the certificate request message in
+ %% TLS-1.2 is empty) to check we just accept first choice.
{ok, Chain};
handle_cert_auths([Cert], CertAuths, CertDbHandle, CertDbRef) ->
- {ok, {_, [Cert | _] = EChain}, {_, [_ | DCerts]}} = certificate_chain(Cert, CertDbHandle, CertDbRef, [], both),
- case cert_auth_member(cert_subjects(DCerts), CertAuths) of
- true ->
- {ok, EChain};
- false ->
- {error, EChain, not_in_auth_domain}
+ case certificate_chain(Cert, CertDbHandle, CertDbRef, [], both) of
+ {ok, {_, [Cert | _] = EChain}, {_, [_ | DCerts]}} ->
+ case cert_auth_member(cert_issuers(DCerts), CertAuths) of
+ true ->
+ {ok, EChain};
+ false ->
+ {error, EChain, not_in_auth_domain}
+ end;
+ _ ->
+ {ok, [Cert]}
end;
handle_cert_auths([_ | Certs] = EChain, CertAuths, _, _) ->
- case cert_auth_member(cert_subjects(Certs), CertAuths) of
+ case cert_auth_member(cert_issuers(Certs), CertAuths) of
true ->
{ok, EChain};
false ->
{error, EChain, not_in_auth_domain}
end.
+available_cert_key_pairs(CertKeyGroups) ->
+ %% To be able to find possible TLS session pre TLS-1.3
+ %% that may be reused. At this point the version is
+ %% not negotiated.
+ RevAlgos = [dsa, rsa, rsa_pss_pss, ecdsa],
+ cert_key_group_to_list(RevAlgos, CertKeyGroups, []).
+
+%% Create the prioritized list of cert key pairs that
+%% are availble for use in the negotiated version
+available_cert_key_pairs(CertKeyGroups, {3, 4}) ->
+ RevAlgos = [rsa, rsa_pss_pss, ecdsa, eddsa],
+ cert_key_group_to_list(RevAlgos, CertKeyGroups, []);
+available_cert_key_pairs(CertKeyGroups, {3, 3}) ->
+ RevAlgos = [dsa, rsa, rsa_pss_pss, ecdsa],
+ cert_key_group_to_list(RevAlgos, CertKeyGroups, []);
+available_cert_key_pairs(CertKeyGroups, {3, N}) when N < 3->
+ RevAlgos = [dsa, rsa, ecdsa],
+ cert_key_group_to_list(RevAlgos, CertKeyGroups, []).
+
+cert_key_group_to_list([], _, Acc) ->
+ final_group_list(Acc);
+cert_key_group_to_list([Algo| Rest], CertKeyGroups, Acc) ->
+ CertKeyPairs = maps:get(Algo, CertKeyGroups, []),
+ cert_key_group_to_list(Rest, CertKeyGroups, CertKeyPairs ++ Acc).
+
+final_group_list([]) ->
+ [#{certs => [[]], private_key => #{}}];
+final_group_list(List) ->
+ List.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -411,7 +448,7 @@ find_alternative_root([Cert | _], CertDbHandle, CertDbRef, InvalidatedList) ->
end.
find_issuer(#cert{der=DerCert, otp=OtpCert}, CertDbHandle, CertsDbRef, ListDb, InvalidatedList) ->
- IsIssuerFun =
+ IsIssuerFun =
fun({_Key, #cert{otp=ErlCertCandidate}}, Acc) ->
case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
true ->
@@ -431,12 +468,15 @@ find_issuer(#cert{der=DerCert, otp=OtpCert}, CertDbHandle, CertsDbRef, ListDb, I
end,
Result = case is_reference(CertsDbRef) of
- true ->
- do_find_issuer(IsIssuerFun, CertDbHandle, ListDb);
- false ->
+ true when ListDb == [] ->
+ CertEntryList = ssl_pkix_db:select_certentries_by_ref(CertsDbRef, CertDbHandle),
+ do_find_issuer(IsIssuerFun, CertDbHandle, CertEntryList);
+ false when ListDb == [] ->
{extracted, CertsData} = CertsDbRef,
- DB = [Entry || {decoded, Entry} <- CertsData],
- do_find_issuer(IsIssuerFun, CertDbHandle, DB)
+ CertEntryList = [Entry || {decoded, Entry} <- CertsData],
+ do_find_issuer(IsIssuerFun, CertDbHandle, CertEntryList);
+ _ ->
+ do_find_issuer(IsIssuerFun, CertDbHandle, ListDb)
end,
case Result of
issuer_not_found ->
@@ -445,6 +485,7 @@ find_issuer(#cert{der=DerCert, otp=OtpCert}, CertDbHandle, CertsDbRef, ListDb, I
Result
end.
+
do_find_issuer(IssuerFun, CertDbHandle, CertDb) ->
try
foldl_db(IssuerFun, CertDbHandle, CertDb)
@@ -667,18 +708,18 @@ maybe_shorten_path(Path, PartialChainHandler, Default) ->
DerCerts = [Der || #cert{der=Der} <- Path],
try PartialChainHandler(DerCerts) of
{trusted_ca, Root} ->
- new_trusteded_path(Root, Path, Default);
+ new_trusted_path(Root, Path, Default);
unknown_ca ->
Default
catch _:_ ->
Default
end.
-new_trusteded_path(DerCert, [#cert{der=DerCert}=Cert | Chain], _) ->
- {Cert, Chain};
-new_trusteded_path(DerCert, [_ | Rest], Default) ->
- new_trusteded_path(DerCert, Rest, Default);
-new_trusteded_path(_, [], Default) ->
+new_trusted_path(DerCert, [#cert{der=DerCert}=Cert | Path], _) ->
+ {Cert, Path};
+new_trusted_path(DerCert, [_ | Rest], Default) ->
+ new_trusted_path(DerCert, Rest, Default);
+new_trusted_path(_, [], Default) ->
%% User did not pick a cert present
%% in the cert chain so ignore
Default.
@@ -758,21 +799,29 @@ subject(Cert) ->
{_Serial,Subject} = public_key:pkix_subject_id(Cert),
Subject.
-cert_subjects([], Acc) ->
- Acc;
-cert_subjects([Cert | Rest], Acc) ->
- cert_subjects(Rest, [subject(Cert) | Acc]).
-
-cert_subjects(OTPCerts) ->
- cert_subjects(OTPCerts, []).
+issuer(Cert) ->
+ case public_key:pkix_is_self_signed(Cert) of
+ true ->
+ subject(Cert);
+ false ->
+ case is_binary(Cert) of
+ true ->
+ #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
+ public_key:pkix_normalize_name(TBSCert#'OTPTBSCertificate'.issuer);
+ false ->
+ #'OTPCertificate'{tbsCertificate = TBSCert} = Cert,
+ public_key:pkix_normalize_name(TBSCert#'OTPTBSCertificate'.issuer)
+ end
+ end.
-decode_cert_auths(<<>>, Acc) ->
+cert_issuers([], Acc) ->
Acc;
-decode_cert_auths(<<?UINT16(Len), Auth:Len/binary, Rest/binary>>, Acc) ->
- NormAut = public_key:pkix_normalize_name(Auth),
- decode_cert_auths(Rest, [NormAut | Acc]).
+cert_issuers([Cert | Rest], Acc) ->
+ cert_issuers(Rest, [issuer(Cert) | Acc]).
+
+cert_issuers(OTPCerts) ->
+ cert_issuers(OTPCerts, []).
-cert_auth_member(ChainSubjects, EncCertAuths) ->
- CertAuths = decode_cert_auths(EncCertAuths, []),
+cert_auth_member(ChainSubjects, CertAuths) ->
CommonAuthorities = sets:intersection(sets:from_list(ChainSubjects), sets:from_list(CertAuths)),
not sets:is_empty(CommonAuthorities).
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index f567bd6c53..87dd624306 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -183,10 +183,10 @@ cipher(?AES_CBC, CipherState, Mac, Fragment, Version) ->
end, block_size(aes_128_cbc), CipherState, Mac, Fragment, Version).
aead_encrypt(Type, Key, Nonce, Fragment, AdditionalData, TagLen) ->
- crypto:crypto_one_time_aead(aead_type(Type,size(Key)), Key, Nonce, Fragment, AdditionalData, TagLen, true).
+ crypto:crypto_one_time_aead(aead_type(Type,byte_size(Key)), Key, Nonce, Fragment, AdditionalData, TagLen, true).
aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AdditionalData) ->
- crypto:crypto_one_time_aead(aead_type(Type,size(Key)), Key, Nonce, CipherText, AdditionalData, CipherTag, false).
+ crypto:crypto_one_time_aead(aead_type(Type,byte_size(Key)), Key, Nonce, CipherText, AdditionalData, CipherTag, false).
aead_type(?AES_GCM, 16) ->
aes_128_gcm;
@@ -260,12 +260,13 @@ decipher(?RC4, HashSz, CipherState = #cipher_state{state = State}, Fragment, _,
#generic_stream_cipher{content = Content, mac = Mac} = GSC,
{Content, Mac, CipherState}
catch
- _:_ ->
+ _:Reason:ST ->
%% This is a DECRYPTION_FAILED but
%% "differentiating between bad_record_mac and decryption_failed
%% alerts may permit certain attacks against CBC mode as used in
%% TLS [CBCATT]. It is preferable to uniformly use the
%% bad_record_mac alert to hide the specific type of the error."
+ ?SSL_LOG(debug, decrypt_error, [{reason,Reason}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end;
@@ -305,12 +306,13 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
{<<16#F0, Content/binary>>, Mac, CipherState1}
end
catch
- _:_ ->
+ _:Reason:ST ->
%% This is a DECRYPTION_FAILED but
%% "differentiating between bad_record_mac and decryption_failed
%% alerts may permit certain attacks against CBC mode as used in
%% TLS [CBCATT]. It is preferable to uniformly use the
%% bad_record_mac alert to hide the specific type of the error."
+ ?SSL_LOG(debug, decrypt_error, [{reason,Reason}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end.
@@ -674,8 +676,8 @@ scheme_to_components(eddsa_ed448) -> {none, eddsa, ed448};
scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined};
scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined};
scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined};
-scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined};
-scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined};
+scheme_to_components(rsa_pkcs1_sha1) -> {sha, rsa_pkcs1, undefined};
+scheme_to_components(ecdsa_sha1) -> {sha, ecdsa, undefined};
%% Handling legacy signature algorithms
scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}.
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index 91bd03decf..46578c05a5 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -41,20 +41,162 @@
%% Internal application API
%%====================================================================
init(#{erl_dist := ErlDist,
- key := Key,
- keyfile := KeyFile,
- password := Password, %% Can be fun() or string()
dh := DH,
dhfile := DHFile} = SslOpts, Role) ->
init_manager_name(ErlDist),
+ #{pem_cache := PemCache} = Config = init_cacerts(SslOpts, Role),
+ DHParams = init_diffie_hellman(PemCache, DH, DHFile, Role),
+
+ CertKeyAlts = init_certs_keys(SslOpts, Role, PemCache),
+
+ {ok, Config#{cert_key_alts => CertKeyAlts, dh_params => DHParams}}.
- {ok, #{pem_cache := PemCache} = Config, Certs}
- = init_certificates(SslOpts, Role),
+init_certs_keys(#{certs_keys := CertsKeys}, Role, PemCache) ->
+ Pairs = lists:map(fun(CertKey) -> cert_key_pair(CertKey, Role, PemCache) end, CertsKeys),
+ CertKeyGroups = group_pairs(Pairs),
+ prioritize_groups(CertKeyGroups);
+init_certs_keys(SslOpts, Role, PemCache) ->
+ KeyPair = init_cert_key_pair(SslOpts, Role, PemCache),
+ group_pairs([KeyPair]).
+
+init_cert_key_pair(#{key := Key,
+ keyfile := KeyFile,
+ password := Password} = Opts, Role, PemCache) ->
+ {ok, Certs} = init_certificates(Opts, PemCache, Role),
PrivateKey =
init_private_key(PemCache, Key, KeyFile, Password, Role),
- DHParams = init_diffie_hellman(PemCache, DH, DHFile, Role),
- {ok, Config#{cert_key_pairs => [#{private_key => PrivateKey, certs => Certs}], dh_params => DHParams}}.
+ #{private_key => PrivateKey, certs => Certs}.
+
+cert_key_pair(CertKey, Role, PemCache) ->
+ CertKeyPairConf = cert_conf(key_conf(CertKey)),
+ init_cert_key_pair(CertKeyPairConf, Role, PemCache).
+
+
+group_pairs([#{certs := [[]]}]) ->
+ #{eddsa => [],
+ ecdsa => [],
+ rsa_pss_pss => [],
+ rsa => [],
+ dsa => []
+ };
+group_pairs(Pairs) ->
+ group_pairs(Pairs, #{eddsa => [],
+ ecdsa => [],
+ rsa_pss_pss => [],
+ rsa => [],
+ dsa => []
+ }).
+group_pairs([], Group) ->
+ Group;
+group_pairs([#{private_key := #'ECPrivateKey'{parameters = {namedCurve, ?'id-Ed25519'}}} = Pair | Rest], #{eddsa := EDDSA} = Group) ->
+ group_pairs(Rest, Group#{eddsa => [Pair | EDDSA]});
+group_pairs([#{private_key := #'ECPrivateKey'{parameters = {namedCurve, ?'id-Ed448'}}} = Pair | Rest], #{eddsa := EDDSA} = Group) ->
+ group_pairs(Rest, Group#{eddsa => [Pair | EDDSA]});
+group_pairs([#{private_key := #'ECPrivateKey'{}} = Pair | Rest], #{ecdsa := ECDSA} = Group) ->
+ group_pairs(Rest, Group#{ecdsa => [Pair | ECDSA]});
+group_pairs([#{private_key := {#'RSAPrivateKey'{}, #'RSASSA-PSS-params'{}}} = Pair | Rest], #{rsa_pss_pss := RSAPSS} = Group) ->
+ group_pairs(Rest, Group#{rsa_pss_pss => [Pair | RSAPSS]});
+group_pairs([#{private_key := #'RSAPrivateKey'{}} = Pair | Rest], #{rsa := RSA} = Group) ->
+ group_pairs(Rest, Group#{rsa => [Pair | RSA]});
+group_pairs([#{private_key := #'DSAPrivateKey'{}} = Pair | Rest], #{dsa := DSA} = Group) ->
+ group_pairs(Rest, Group#{dsa => [Pair | DSA]});
+group_pairs([#{private_key := #{algorithm := dss, engine := _}} = Pair | Rest], Group) ->
+ Pairs = maps:get(dsa, Group),
+ group_pairs(Rest, Group#{dsa => [Pair | Pairs]});
+group_pairs([#{private_key := #{algorithm := Alg, engine := _}} = Pair | Rest], Group) ->
+ Pairs = maps:get(Alg, Group),
+ group_pairs(Rest, Group#{Alg => [Pair | Pairs]}).
+
+prioritize_groups(#{eddsa := EDDSA,
+ ecdsa := ECDSA,
+ rsa_pss_pss := RSAPSS,
+ rsa := RSA,
+ dsa := DSA} = CertKeyGroups) ->
+ CertKeyGroups#{eddsa => prio_eddsa(EDDSA),
+ ecdsa => prio_ecdsa(ECDSA),
+ rsa_pss_pss => prio_rsa_pss(RSAPSS),
+ rsa => prio_rsa(RSA),
+ dsa => prio_dsa(DSA)}.
+
+prio_eddsa(EDDSA) ->
+ %% Engine not supported yet
+ using_curve({namedCurve, ?'id-Ed25519'}, EDDSA, []) ++ using_curve({namedCurve, ?'id-Ed448'}, EDDSA, []).
+
+prio_ecdsa(ECDSA) ->
+ EnginePairs = [Pair || Pair = #{private_key := #{engine := _}} <- ECDSA],
+ Curves = tls_v1:ecc_curves(all),
+ EnginePairs ++ lists:foldr(fun(Curve, AccIn) ->
+ CurveOid = pubkey_cert_records:namedCurves(Curve),
+ Pairs = using_curve({namedCurve, CurveOid}, ECDSA -- EnginePairs, []),
+ Pairs ++ AccIn
+ end, [], Curves).
+using_curve(_, [], Acc) ->
+ lists:reverse(Acc);
+using_curve(Curve, [#{private_key := #'ECPrivateKey'{parameters = Curve}} = Pair | Rest], Acc) ->
+ using_curve(Curve, Rest, [Pair | Acc]);
+using_curve(Curve, [_ | Rest], Acc) ->
+ using_curve(Curve, Rest, Acc).
+
+prio_rsa_pss(RSAPSS) ->
+ Order = fun(#{privat_key := {#'RSAPrivateKey'{modulus = N}, Params1}},
+ #{private_key := {#'RSAPrivateKey'{modulus = N}, Params2}}) ->
+ prio_params_1(Params1, Params2);
+ (#{private_key := {#'RSAPrivateKey'{modulus = N}, _}},
+ #{private_key := {#'RSAPrivateKey'{modulus = M}, _}}) when M > N ->
+ true;
+ (#{private_key := #{engine := _}}, _) ->
+ true;
+ (_,_) ->
+ false
+ end,
+ lists:sort(Order, RSAPSS).
+
+prio_params_1(#'RSASSA-PSS-params'{hashAlgorithm = #'HashAlgorithm'{algorithm = Oid1}},
+ #'RSASSA-PSS-params'{hashAlgorithm = #'HashAlgorithm'{algorithm = Oid2}}) ->
+ public_key:pkix_hash_type(Oid1) > public_key:pkix_hash_type(Oid2).
+
+prio_rsa(RSA) ->
+ Order = fun(#{key := #'RSAPrivateKey'{modulus = N}},
+ #{key := #'RSAPrivateKey'{modulus = M}}) when M > N ->
+ true;
+ (#{private_key := #{engine := _}}, _) ->
+ true;
+ (_,_) ->
+ false
+ end,
+ lists:sort(Order, RSA).
+
+prio_dsa(DSA) ->
+ Order = fun(#{key := #'DSAPrivateKey'{q = N}},
+ #{key := #'DSAPrivateKey'{q = M}}) when M > N ->
+ true;
+ (#{private_key := #{engine := _}}, _) ->
+ true;
+ (_,_) ->
+ false
+ end,
+ lists:sort(Order, DSA).
+
+key_conf(#{key := _} = Conf) ->
+ Conf#{certfile => <<>>,
+ keyfile => <<>>,
+ password => undefined};
+key_conf(#{keyfile := _} = Conf) ->
+ case maps:get(password, Conf, undefined) of
+ undefined ->
+ Conf#{key => undefined,
+ password => undefined};
+ _ ->
+ Conf#{key => undefined}
+ end.
+
+cert_conf(#{cert := Bin} = Conf) when is_binary(Bin)->
+ Conf#{cert => [Bin]};
+cert_conf(#{cert := _} = Conf) ->
+ Conf#{certfile => <<>>};
+cert_conf(#{certfile := _} = Conf) ->
+ Conf#{cert => undefined}.
pre_1_3_session_opts(Role) ->
{Cb, InitArgs} = session_cb_opts(Role),
@@ -119,12 +261,10 @@ init_manager_name(true) ->
put(ssl_manager, ssl_manager:name(dist)),
put(ssl_pem_cache, ssl_pem_cache:name(dist)).
-init_certificates(#{cacerts := CaCerts,
- cacertfile := CACertFile,
- certfile := CertFile,
- cert := OwnCerts,
- crl_cache := CRLCache
- }, Role) ->
+init_cacerts(#{cacerts := CaCerts,
+ cacertfile := CACertFile,
+ crl_cache := CRLCache
+ }, Role) ->
{ok, Config} =
try
Certs = case CaCerts of
@@ -138,31 +278,36 @@ init_certificates(#{cacerts := CaCerts,
_:Reason ->
file_error(CACertFile, {cacertfile, Reason})
end,
- init_certificates(OwnCerts, Config, CertFile, Role).
+ Config.
-init_certificates(undefined, Config, <<>>, _) ->
- {ok, Config, [[]]};
+init_certificates(#{certfile := CertFile,
+ cert := OwnCerts}, PemCache, Role) ->
+ init_certificates(OwnCerts, PemCache, CertFile, Role).
-init_certificates(undefined, #{pem_cache := PemCache} = Config, CertFile, client) ->
+init_certificates(undefined, _, <<>>, _) ->
+ {ok, [[]]};
+init_certificates(undefined, PemCache, CertFile, client) ->
try
%% OwnCert | [OwnCert | Chain]
OwnCerts = ssl_certificate:file_to_certificats(CertFile, PemCache),
- {ok, Config, OwnCerts}
+ {ok, OwnCerts}
catch _Error:_Reason ->
- {ok, Config, [[]]}
+ {ok, [[]]}
end;
-
-init_certificates(undefined, #{pem_cache := PemCache} = Config, CertFile, server) ->
+init_certificates(undefined, PemCache, CertFile, server) ->
try
%% OwnCert | [OwnCert | Chain]
OwnCerts = ssl_certificate:file_to_certificats(CertFile, PemCache),
- {ok, Config, OwnCerts}
+ {ok, OwnCerts}
catch
_:Reason ->
file_error(CertFile, {certfile, Reason})
end;
-init_certificates(OwnCerts, Config, _, _) ->
- {ok, Config, OwnCerts}.
+init_certificates(OwnCerts, _, _, _) when is_binary(OwnCerts)->
+ {ok, [OwnCerts]};
+init_certificates(OwnCerts, _, _, _) ->
+ {ok, OwnCerts}.
+
init_private_key(_, #{algorithm := Alg} = Key, _, _Password, _Client) when Alg == ecdsa;
Alg == rsa;
Alg == dss ->
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 86ee57d7fa..c8295f339f 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -55,7 +55,7 @@
-record(handshake_env, {
- client_hello_version :: ssl_record:ssl_version() | 'undefined',
+ client_hello_version :: ssl_record:ssl_version() | 'undefined', %% Legacy client hello
unprocessed_handshake_events = 0 :: integer(),
tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
| 'undefined',
@@ -67,7 +67,9 @@
early_data_accepted = false :: boolean(), %% TLS 1.3
allow_renegotiate = true ::boolean(),
%% Ext handling
- hello, %%:: #client_hello{} | #server_hello{}
+ %% continue_status reflects handling of the option handshake that is either full or
+ %% hello (will pause at hello message to allow user to act on hello extensions)
+ continue_status, %% full | pause | {pause, ClientVersionsExt} | continue
sni_hostname = undefined,
max_frag_enum :: undefined | {max_frag_enum, integer()},
expecting_next_protocol_negotiation = false ::boolean(),
@@ -97,9 +99,12 @@
socket_tls_closed = false ::boolean(),
negotiated_version :: ssl_record:ssl_version() | 'undefined',
erl_dist_handle = undefined :: erlang:dist_handle() | 'undefined',
- cert_key_pairs = undefined :: [#{private_key => public_key:private_key(),
- certs => [public_key:der_encoded()]}]
- | secret_printout() | 'undefined'
+ cert_key_alts = undefined :: #{eddsa => list(),
+ ecdsa => list(),
+ rsa_pss_pss => list(),
+ rsa => list(),
+ dsa => list()
+ } | secret_printout() | 'undefined'
}).
-record(state, {
@@ -118,7 +123,7 @@
%% need to worry about packet loss in TLS. In DTLS we
%% need to track DTLS handshake seqnr
flight_buffer = [] :: list() | map(),
- client_certificate_requested = false :: boolean(),
+ client_certificate_status = not_requested :: not_requested | requested | empty | needs_verifying | verified,
protocol_specific = #{} :: map(),
session :: #session{} | secret_printout(),
key_share,
@@ -150,8 +155,8 @@
%% session_cache_cb - not implemented
%% crl_db - not implemented
%% client_hello_version - Bleichenbacher mitigation in TLS 1.2
-%% client_certificate_requested - Built into TLS 1.3 state machine
-%% key_algorithm - not used
+%% client_certificate_status - only uses non_requested| requested
+%% key_algorithm - only uses not_requested and requested
%% diffie_hellman_params - used in TLS 1.2 ECDH key exchange
%% diffie_hellman_keys - used in TLS 1.2 ECDH key exchange
%% psk_identity - not used
diff --git a/lib/ssl/src/ssl_crl_cache.erl b/lib/ssl/src/ssl_crl_cache.erl
index 095e3e8b44..c12d829470 100644
--- a/lib/ssl/src/ssl_crl_cache.erl
+++ b/lib/ssl/src/ssl_crl_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -64,7 +64,7 @@ fresh_crl(#'DistributionPoint'{distributionPoint = {fullName, Names}}, CRL) ->
case get_crls(Names, undefined) of
not_available ->
CRL;
- [NewCRL] ->
+ NewCRL ->
NewCRL
end.
@@ -175,7 +175,7 @@ cache_lookup(URL, {{Cache, _}, _}) ->
case ssl_pkix_db:lookup(string:trim(Path, leading, "/"), Cache) of
undefined ->
[];
- CRLs ->
+ [CRLs] ->
CRLs
end.
diff --git a/lib/ssl/src/ssl_gen_statem.erl b/lib/ssl/src/ssl_gen_statem.erl
index caa6c6742d..36768ab6c7 100644
--- a/lib/ssl/src/ssl_gen_statem.erl
+++ b/lib/ssl/src/ssl_gen_statem.erl
@@ -25,8 +25,6 @@
-module(ssl_gen_statem).
--include_lib("kernel/include/logger.hrl").
-
-include("ssl_api.hrl").
-include("ssl_internal.hrl").
-include("ssl_connection.hrl").
@@ -102,24 +100,28 @@
%%% Initial Erlang process setup
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
--spec start_link(client| server, pid(), ssl:host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+-spec start_link(client| server, pid(), ssl:host(), inet:port_number(), port(), tuple(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a process which calls Module:init/1 to
%% choose appropriat gen_statem and initialize.
%%--------------------------------------------------------------------
-start_link(Role, Sender, Host, Port, Socket, Options, User, CbInfo) ->
- {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]])}.
+start_link(Role, Sender, Host, Port, Socket, {#{receiver_spawn_opts := ReceiverOpts}, _, _} = Options, User, CbInfo) ->
+ Opts = [link | proplists:delete(link, ReceiverOpts)],
+ Pid = proc_lib:spawn_opt(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]], Opts),
+ {ok, Pid}.
%%--------------------------------------------------------------------
--spec start_link(atom(), ssl:host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+-spec start_link(atom(), ssl:host(), inet:port_number(), port(), tuple(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a gen_statem process which calls Module:init/1 to
%% initialize.
%%--------------------------------------------------------------------
-start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
- {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
+start_link(Role, Host, Port, Socket, {#{receiver_spawn_opts := ReceiverOpts}, _, _} = Options, User, CbInfo) ->
+ Opts = [link | proplists:delete(link, ReceiverOpts)],
+ Pid = proc_lib:spawn_opt(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]], Opts),
+ {ok, Pid}.
%%--------------------------------------------------------------------
@@ -149,6 +151,7 @@ init([_Role, _Host, _Port, _Socket, {TLSOpts, _, _}, _User, _CbInfo] = InitArgs
-spec ssl_config(ssl_options(), client | server, #state{}) -> #state{}.
%%--------------------------------------------------------------------
ssl_config(Opts, Role, #state{static_env = InitStatEnv0,
+ ssl_options = #{handshake := Handshake},
handshake_env = HsEnv,
connection_env = CEnv} = State0) ->
{ok, #{cert_db_ref := Ref,
@@ -156,12 +159,21 @@ ssl_config(Opts, Role, #state{static_env = InitStatEnv0,
fileref_db_handle := FileRefHandle,
session_cache := CacheHandle,
crl_db_info := CRLDbHandle,
- cert_key_pairs := CertKeyPairs,
+ cert_key_alts := CertKeyAlts,
dh_params := DHParams}} =
ssl_config:init(Opts, Role),
TimeStamp = erlang:monotonic_time(),
Session = State0#state.session,
+ ContinueStatus = case Handshake of
+ hello ->
+ %% Will pause handshake after hello message to
+ %% enable user to react to hello extensions
+ pause;
+ full ->
+ Handshake
+ end,
+
State0#state{session = Session#session{time_stamp = TimeStamp},
static_env = InitStatEnv0#static_env{
file_ref_db = FileRefHandle,
@@ -170,8 +182,9 @@ ssl_config(Opts, Role, #state{static_env = InitStatEnv0,
crl_db = CRLDbHandle,
session_cache = CacheHandle
},
- handshake_env = HsEnv#handshake_env{diffie_hellman_params = DHParams},
- connection_env = CEnv#connection_env{cert_key_pairs = CertKeyPairs},
+ handshake_env = HsEnv#handshake_env{diffie_hellman_params = DHParams,
+ continue_status = ContinueStatus},
+ connection_env = CEnv#connection_env{cert_key_alts = CertKeyAlts},
ssl_options = Opts}.
%%--------------------------------------------------------------------
@@ -709,8 +722,6 @@ handle_common_event(internal, {protocol_record, TLSorDTLSRecord}, StateName,
Connection:handle_protocol_record(TLSorDTLSRecord, StateName, State);
handle_common_event(timeout, hibernate, _, _) ->
{keep_state_and_data, [hibernate]};
-handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName, State) ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), StateName, State);
handle_common_event({timeout, handshake}, close, _StateName, #state{start_or_recv_from = StartFrom} = State) ->
{stop_and_reply,
{shutdown, user_timeout},
@@ -840,10 +851,9 @@ handle_info({ErrorTag, Socket, econnaborted}, StateName,
handle_info({ErrorTag, Socket, Reason}, StateName, #state{static_env = #static_env{
role = Role,
socket = Socket,
- error_tag = ErrorTag},
- ssl_options = #{log_level := Level}} = State) ->
- ssl_logger:log(info, Level, #{description => "Socket error",
- reason => [{error_tag, ErrorTag}, {description, Reason}]}, ?LOCATION),
+ error_tag = ErrorTag}
+ } = State) ->
+ ?SSL_LOG(info, "Socket error", [{error_tag, ErrorTag}, {description, Reason}]),
Alert = ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY, {transport_error, Reason}),
handle_normal_shutdown(Alert#alert{role = Role}, StateName, State),
{stop, {shutdown,normal}, State};
@@ -870,11 +880,9 @@ handle_info({'EXIT', Socket, Reason}, _StateName, #state{static_env = #static_en
{stop,{shutdown, Reason}, State};
handle_info(allow_renegotiate, StateName, #state{handshake_env = HsEnv} = State) -> %% PRE TLS-1.3
{next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{allow_renegotiate = true}}};
-handle_info(Msg, StateName, #state{static_env = #static_env{socket = Socket, error_tag = ErrorTag},
- ssl_options = #{log_level := Level}} = State) ->
- ssl_logger:log(notice, Level, #{description => "Unexpected INFO message",
- reason => [{message, Msg}, {socket, Socket},
- {error_tag, ErrorTag}]}, ?LOCATION),
+handle_info(Msg, StateName, #state{static_env = #static_env{socket = Socket, error_tag = ErrorTag}} = State) ->
+ ?SSL_LOG(notice, "Unexpected INFO message",
+ [{message, Msg}, {socket, Socket}, {error_tag, ErrorTag}]),
{next_state, StateName, State}.
%%====================================================================
@@ -896,9 +904,25 @@ read_application_data(Data,
try read_application_dist_data(DHandle, Front, BufferSize, Rear) of
Buffer ->
{no_record, State#state{user_data_buffer = Buffer}}
- catch error:_ ->
- {stop,disconnect,
- State#state{user_data_buffer = {Front,BufferSize,Rear}}}
+ catch
+ error:notsup ->
+ %% Distribution controller has shut down
+ %% so we are no longer input handler and therefore
+ %% erlang:dist_ctrl_put_data/2 raises this exception
+ {stop, {shutdown, dist_closed},
+ %% This buffers known data, but we might have delivered
+ %% some of it to the VM, which makes buffering all
+ %% incorrect, as would be wasting all.
+ %% But we are stopping the server so
+ %% user_data_buffer is not important at all...
+ State#state{
+ user_data_buffer = {Front,BufferSize,Rear}}};
+ error:Reason:Stacktrace ->
+ %% Unforeseen exception in parsing application data
+ {stop,
+ {disconnect,{error,Reason,Stacktrace}},
+ State#state{
+ user_data_buffer = {Front,BufferSize,Rear}}}
end
end.
passive_receive(#state{user_data_buffer = {Front,BufferSize,Rear},
@@ -1151,7 +1175,7 @@ terminate(Reason, connection, #state{static_env = #static_env{
handle_trusted_certs_db(State),
Alert = terminate_alert(Reason),
%% Send the termination ALERT if possible
- catch (ok = Connection:send_alert_in_connection(Alert, State)),
+ catch Connection:send_alert_in_connection(Alert, State),
Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates);
terminate(Reason, _StateName, #state{static_env = #static_env{transport_cb = Transport,
protocol_cb = Connection,
@@ -1278,7 +1302,7 @@ handle_sni_hostname(Hostname,
fileref_db_handle := FileRefHandle,
session_cache := CacheHandle,
crl_db_info := CRLDbHandle,
- cert_key_pairs := CertKeyPairs,
+ cert_key_alts := CertKeyAlts,
dh_params := DHParams}} =
ssl_config:init(NewOptions, Role),
State0#state{
@@ -1289,7 +1313,7 @@ handle_sni_hostname(Hostname,
crl_db = CRLDbHandle,
session_cache = CacheHandle
},
- connection_env = CEnv#connection_env{cert_key_pairs = CertKeyPairs},
+ connection_env = CEnv#connection_env{cert_key_alts = CertKeyAlts},
ssl_options = NewOptions,
handshake_env = HsEnv#handshake_env{sni_hostname = Hostname,
diffie_hellman_params = DHParams}
@@ -1333,7 +1357,9 @@ filter_for_versions(['tlsv1.1'], OrigSSLOptions) ->
maps:without(Opts, OrigSSLOptions);
filter_for_versions(['tlsv1.1'| Rest], OrigSSLOptions) ->
Opts = ?'TLS-1_3_ONLY_OPTIONS' ++ ?'FROM_TLS-1_2_ONLY_OPTIONS',
- maybe_exclude_tlsv1(Rest, maps:without(Opts, OrigSSLOptions)).
+ maybe_exclude_tlsv1(Rest, maps:without(Opts, OrigSSLOptions));
+filter_for_versions(['tlsv1'], OrigSSLOptions) ->
+ OrigSSLOptions.
maybe_exclude_tlsv1(Versions, Options) ->
case lists:member('tlsv1', Versions) of
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index ee102077af..56a1ca81b9 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -358,7 +358,8 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
error:{_,{error, {asn1, Asn1Reason}}} ->
%% ASN-1 decode of certificate somehow failed
?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, {failed_to_decode_certificate, Asn1Reason});
- error:OtherReason ->
+ error:OtherReason:ST ->
+ ?SSL_LOG(info, internal_error, [{error, OtherReason}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason})
end.
%%--------------------------------------------------------------------
@@ -427,7 +428,8 @@ master_secret(Version, #session{master_secret = Mastersecret},
try master_secret(Version, Mastersecret, SecParams,
ConnectionStates, Role)
catch
- exit:_ ->
+ exit:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, key_calculation_failure)
end;
@@ -443,7 +445,8 @@ master_secret(Version, PremasterSecret, ConnectionStates, Role) ->
ClientRandom, ServerRandom),
SecParams, ConnectionStates, Role)
catch
- exit:_ ->
+ exit:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, master_secret_calculation_failure)
end.
@@ -561,25 +564,27 @@ encode_handshake(#server_key_params{params_bin = Keys, hashsign = HashSign,
encode_handshake(#certificate_request{certificate_types = CertTypes,
hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
certificate_authorities = CertAuths},
- {Major, Minor}) when Major == 3, Minor >= 3 ->
+ {3,3}) ->
HashSigns = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> ||
SignatureScheme <- HashSignAlgos >>,
+ EncCertAuths = encode_cert_auths(CertAuths),
CertTypesLen = byte_size(CertTypes),
HashSignsLen = byte_size(HashSigns),
- CertAuthsLen = byte_size(CertAuths),
+ CertAuthsLen = byte_size(EncCertAuths),
{?CERTIFICATE_REQUEST,
- <<?BYTE(CertTypesLen), CertTypes/binary,
- ?UINT16(HashSignsLen), HashSigns/binary,
- ?UINT16(CertAuthsLen), CertAuths/binary>>
+ <<?BYTE(CertTypesLen), CertTypes/binary,
+ ?UINT16(HashSignsLen), HashSigns/binary,
+ ?UINT16(CertAuthsLen), EncCertAuths/binary>>
};
encode_handshake(#certificate_request{certificate_types = CertTypes,
certificate_authorities = CertAuths},
_Version) ->
+ EncCertAuths = encode_cert_auths(CertAuths),
CertTypesLen = byte_size(CertTypes),
- CertAuthsLen = byte_size(CertAuths),
+ CertAuthsLen = byte_size(EncCertAuths),
{?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes/binary,
- ?UINT16(CertAuthsLen), CertAuths/binary>>
+ ?UINT16(CertAuthsLen), EncCertAuths/binary>>
};
encode_handshake(#server_hello_done{}, _Version) ->
{?SERVER_HELLO_DONE, <<>>};
@@ -764,10 +769,11 @@ encode_extensions([#early_data_indication_nst{indication = MaxSize} | Rest], Acc
encode_extensions(Rest, <<?UINT16(?EARLY_DATA_EXT),
?UINT16(4), ?UINT32(MaxSize), Acc/binary>>);
encode_extensions([#certificate_authorities{authorities = CertAuths}| Rest], Acc) ->
- CertAuthsLen = byte_size(CertAuths),
+ EncCertAuths = encode_cert_auths(CertAuths),
+ CertAuthsLen = byte_size(EncCertAuths),
Len = CertAuthsLen + 2,
encode_extensions(Rest, <<?UINT16(?CERTIFICATE_AUTHORITIES_EXT), ?UINT16(Len),
- ?UINT16(CertAuthsLen), CertAuths/binary, Acc/binary>>).
+ ?UINT16(CertAuthsLen), EncCertAuths/binary, Acc/binary>>).
encode_cert_status_req(
StatusType,
@@ -816,6 +822,16 @@ encode_protocols_advertised_on_server(Protocols) ->
#next_protocol_negotiation{
extension_data = lists:foldl(fun encode_protocol/2, <<>>, Protocols)}.
+encode_cert_auths(Auths) ->
+ encode_cert_auths(Auths, []).
+
+encode_cert_auths([], Acc) ->
+ list_to_binary(lists:reverse(Acc));
+encode_cert_auths([Auth | Auths], Acc) ->
+ DNEncodedBin = public_key:pkix_encode('Name', Auth, otp),
+ DNEncodedLen = byte_size(DNEncodedBin),
+ encode_cert_auths(Auths, [<<?UINT16(DNEncodedLen), DNEncodedBin/binary>> | Acc]).
+
%%====================================================================
%% Decode handshake
%%====================================================================
@@ -866,16 +882,16 @@ decode_handshake(_Version, ?SERVER_KEY_EXCHANGE, Keys) ->
decode_handshake({3, 3} = Version, ?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
?UINT16(HashSignsLen), HashSigns:HashSignsLen/binary,
- ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>) ->
+ ?UINT16(CertAuthsLen), EncCertAuths:CertAuthsLen/binary>>) ->
HashSignAlgos = decode_sign_alg(Version, HashSigns),
#certificate_request{certificate_types = CertTypes,
hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos},
- certificate_authorities = CertAuths};
+ certificate_authorities = decode_cert_auths(EncCertAuths, [])};
decode_handshake(_Version, ?CERTIFICATE_REQUEST,
<<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary,
- ?UINT16(CertAuthsLen), CertAuths:CertAuthsLen/binary>>) ->
+ ?UINT16(CertAuthsLen), EncCertAuths:CertAuthsLen/binary>>) ->
#certificate_request{certificate_types = CertTypes,
- certificate_authorities = CertAuths};
+ certificate_authorities = decode_cert_auths(EncCertAuths, [])};
decode_handshake(_Version, ?SERVER_HELLO_DONE, <<>>) ->
#server_hello_done{};
decode_handshake({Major, Minor}, ?CERTIFICATE_VERIFY,<<HashSign:2/binary, ?UINT16(SignLen),
@@ -888,8 +904,8 @@ decode_handshake(_Version, ?CLIENT_KEY_EXCHANGE, PKEPMS) ->
#client_key_exchange{exchange_keys = PKEPMS};
decode_handshake(_Version, ?FINISHED, VerifyData) ->
#finished{verify_data = VerifyData};
-decode_handshake(_, Message, _) ->
- throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, {unknown_or_malformed_handshake, Message})).
+decode_handshake(_, MessageType, _) ->
+ throw(?ALERT_REC(?FATAL, ?DECODE_ERROR, {unknown_or_malformed_handshake, MessageType})).
%%--------------------------------------------------------------------
@@ -970,6 +986,7 @@ decode_suites('2_bytes', Dec) ->
decode_suites('3_bytes', Dec) ->
from_3bytes(Dec).
+
%%====================================================================
%% Cipher suite handling
%%====================================================================
@@ -1045,7 +1062,8 @@ cipher_suites(Suites, true) ->
prf({3,_N}, PRFAlgo, Secret, Label, Seed, WantedLength) ->
{ok, tls_v1:prf(PRFAlgo, Secret, Label, Seed, WantedLength)}.
-select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, SessIdTracker, Session0, Version, SslOpts, CertKeyPairs) ->
+select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, SessIdTracker, Session0, Version, SslOpts, CertKeyAlts) ->
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts, Version),
{SessionId, Resumed} = ssl_session:server_select_session(Version, SessIdTracker, SuggestedSessionId,
SslOpts, CertKeyPairs),
case Resumed of
@@ -1063,7 +1081,7 @@ select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, SessId
new_session_parameters(SessionId, #session{ecc = ECCCurve0} = Session, CipherSuites, SslOpts,
Version, Compressions, HashSigns, CertKeyPairs) ->
Compression = select_compression(Compressions),
- {Certs, Key, {ECCCurve, CipherSuite}} = select_cert_key_pair_and_params(CipherSuites, CertKeyPairs, HashSigns,
+ {Certs, Key, {ECCCurve, CipherSuite}} = server_select_cert_key_pair_and_params(CipherSuites, CertKeyPairs, HashSigns,
ECCCurve0, SslOpts, Version),
Session#session{session_id = SessionId,
ecc = ECCCurve,
@@ -1074,30 +1092,44 @@ new_session_parameters(SessionId, #session{ecc = ECCCurve0} = Session, CipherSui
%% Possibly support part of "trusted_ca_keys" extension that corresponds to TLS-1.3 certificate_authorities?!
-select_cert_key_pair_and_params(CipherSuites, [#{private_key := NoKey, certs := [[]] = NoCerts}], HashSigns, ECCCurve0,
+server_select_cert_key_pair_and_params(CipherSuites, [#{private_key := NoKey, certs := [[]] = NoCerts}], HashSigns, ECCCurve0,
#{ciphers := UserSuites, honor_cipher_order := HonorCipherOrder}, Version) ->
%% This can happen if anonymous cipher suites are enabled
Suites = available_suites(undefined, UserSuites, Version, HashSigns, ECCCurve0),
CipherSuite0 = select_cipher_suite(CipherSuites, Suites, HonorCipherOrder),
CurveAndSuite = cert_curve(undefined, ECCCurve0, CipherSuite0),
{NoCerts, NoKey, CurveAndSuite};
-select_cert_key_pair_and_params(CipherSuites, [#{private_key := Key, certs := [Cert | _] = Certs}], HashSigns, ECCCurve0,
+server_select_cert_key_pair_and_params(CipherSuites, [#{private_key := Key, certs := [Cert | _] = Certs}], HashSigns, ECCCurve0,
#{ciphers := UserSuites, honor_cipher_order := HonorCipherOrder}, Version) ->
Suites = available_suites(Cert, UserSuites, Version, HashSigns, ECCCurve0),
CipherSuite0 = select_cipher_suite(CipherSuites, Suites, HonorCipherOrder),
CurveAndSuite = cert_curve(Cert, ECCCurve0, CipherSuite0),
{Certs, Key, CurveAndSuite};
-select_cert_key_pair_and_params(CipherSuites, [#{private_key := Key, certs := [Cert | _] = Certs} | Rest], HashSigns, ECCCurve0,
+server_select_cert_key_pair_and_params(CipherSuites, [#{private_key := Key, certs := [Cert | _] = Certs} | Rest], HashSigns, ECCCurve0,
#{ciphers := UserSuites, honor_cipher_order := HonorCipherOrder} = Opts, Version) ->
Suites = available_suites(Cert, UserSuites, Version, HashSigns, ECCCurve0),
case select_cipher_suite(CipherSuites, Suites, HonorCipherOrder) of
no_suite ->
- select_cert_key_pair_and_params(CipherSuites, Rest, HashSigns, ECCCurve0, Opts, Version);
+ server_select_cert_key_pair_and_params(CipherSuites, Rest, HashSigns, ECCCurve0, Opts, Version);
CipherSuite0 ->
- CurveAndSuite = cert_curve(Cert, ECCCurve0, CipherSuite0),
- {Certs, Key, CurveAndSuite}
+ case is_acceptable_cert(Cert, HashSigns, ssl:tls_version(Version)) of
+ true ->
+ CurveAndSuite = cert_curve(Cert, ECCCurve0, CipherSuite0),
+ {Certs, Key, CurveAndSuite};
+ false ->
+ server_select_cert_key_pair_and_params(CipherSuites, Rest, HashSigns, ECCCurve0, Opts, Version)
+ end
end.
+is_acceptable_cert(Cert, HashSigns, {Major, Minor}) when Major == 3,
+ Minor >= 3 ->
+ {SignAlgo0, Param, _, _, _} = get_cert_params(Cert),
+ SignAlgo = sign_algo(SignAlgo0, Param),
+ is_acceptable_hash_sign(SignAlgo, HashSigns);
+is_acceptable_cert(_,_,_) ->
+ %% Not negotiable pre TLS-1.2. So if cert is available for version it is acceptable
+ true.
+
supported_ecc({Major, Minor}) when ((Major == 3) and (Minor >= 1)) orelse (Major > 3) ->
Curves = tls_v1:ecc_curves(Minor),
#elliptic_curves{elliptic_curve_list = Curves};
@@ -1105,26 +1137,27 @@ supported_ecc(_) ->
#elliptic_curves{elliptic_curve_list = []}.
premaster_secret(OtherPublicDhKey, MyPrivateKey, #'DHParameter'{} = Params) ->
- try
- public_key:compute_key(OtherPublicDhKey, MyPrivateKey, Params)
- catch
- error:computation_failed ->
+ try
+ public_key:compute_key(OtherPublicDhKey, MyPrivateKey, Params)
+ catch
+ error:Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
- end;
+ end;
premaster_secret(PublicDhKey, PrivateDhKey, #server_dh_params{dh_p = Prime, dh_g = Base}) ->
- try
+ try
crypto:compute_key(dh, PublicDhKey, PrivateDhKey, [Prime, Base])
- catch
- error:computation_failed ->
+ catch
+ error:Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
premaster_secret(#client_srp_public{srp_a = ClientPublicKey}, ServerKey, #srp_user{prime = Prime,
verifier = Verifier}) ->
- try crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
- PremasterSecret ->
- PremasterSecret
+ try crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']})
catch
- error:_ ->
+ error:Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
premaster_secret(#server_srp_params{srp_n = Prime, srp_g = Generator, srp_s = Salt, srp_b = Public},
@@ -1132,14 +1165,13 @@ premaster_secret(#server_srp_params{srp_n = Prime, srp_g = Generator, srp_s = Sa
case ssl_srp_primes:check_srp_params(Generator, Prime) of
ok ->
DerivedKey = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]),
- try crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
- PremasterSecret ->
- PremasterSecret
+ try crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']})
catch
- error ->
+ error:Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
- _ ->
+ not_accepted ->
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
premaster_secret(#client_rsa_psk_identity{
@@ -1185,14 +1217,16 @@ premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
try public_key:decrypt_private(EncSecret, RSAPrivateKey,
[{rsa_pad, rsa_pkcs1_padding}])
catch
- _:_ ->
+ _:Reason:ST ->
+ ?SSL_LOG(debug, decrypt_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
end;
premaster_secret(EncSecret, #{algorithm := rsa} = Engine) ->
try crypto:private_decrypt(rsa, EncSecret, maps:remove(algorithm, Engine),
[{rsa_pad, rsa_pkcs1_padding}])
catch
- _:_ ->
+ _:Reason:ST ->
+ ?SSL_LOG(debug, decrypt_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?DECRYPT_ERROR))
end.
%%====================================================================
@@ -1923,14 +1957,10 @@ handle_ocsp_extension(false = Stapling, Extensions) ->
end.
certificate_authorities(CertDbHandle, CertDbRef) ->
- Authorities = [ Cert || #cert{otp = Cert} <- certificate_authorities_from_db(CertDbHandle, CertDbRef)],
- Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
- OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
- DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
- DNEncodedLen = byte_size(DNEncodedBin),
- <<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
- end,
- list_to_binary([Enc(Cert) || Cert <- Authorities]).
+ Auths = fun(#'OTPCertificate'{tbsCertificate = TBSCert}) ->
+ TBSCert#'OTPTBSCertificate'.subject
+ end,
+ [Auths(Cert) || #cert{otp = Cert} <- certificate_authorities_from_db(CertDbHandle, CertDbRef)].
%%--------------------------------------------------------------------
%%% Internal functions
@@ -2020,8 +2050,8 @@ validation_fun_and_state(undefined, VerifyState, CertPath, LogLevel) ->
apply_user_fun(Fun, OtpCert, VerifyResult0, UserState0, SslState, CertPath, LogLevel) when
(VerifyResult0 == valid) or (VerifyResult0 == valid_peer) ->
VerifyResult = maybe_check_hostname(OtpCert, VerifyResult0, SslState),
- case Fun(OtpCert, VerifyResult, UserState0) of
- {Valid, UserState} when (Valid == valid) or (Valid == valid_peer) ->
+ case apply_fun(Fun, OtpCert, VerifyResult, UserState0, CertPath) of
+ {Valid, UserState} when (Valid == valid) orelse (Valid == valid_peer) ->
case cert_status_check(OtpCert, SslState, VerifyResult, CertPath, LogLevel) of
valid ->
{Valid, {SslState, UserState}};
@@ -2031,9 +2061,9 @@ apply_user_fun(Fun, OtpCert, VerifyResult0, UserState0, SslState, CertPath, LogL
{fail, _} = Fail ->
Fail
end;
-apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, _CertPath, _LogLevel) ->
- case Fun(OtpCert, ExtensionOrError, UserState0) of
- {Valid, UserState} when (Valid == valid) or (Valid == valid_peer)->
+apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, CertPath, _LogLevel) ->
+ case apply_fun(Fun, OtpCert, ExtensionOrError, UserState0, CertPath) of
+ {Valid, UserState} when (Valid == valid) orelse (Valid == valid_peer)->
{Valid, {SslState, UserState}};
{fail, _} = Fail ->
Fail;
@@ -2041,6 +2071,14 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, _CertPath,
{unknown, {SslState, UserState}}
end.
+apply_fun(Fun, OtpCert, ExtensionOrError, UserState, CertPath) ->
+ if is_function(Fun, 4) ->
+ #cert{der=DerCert} = lists:keyfind(OtpCert, #cert.otp, CertPath),
+ Fun(OtpCert, DerCert, ExtensionOrError, UserState);
+ is_function(Fun, 3) ->
+ Fun(OtpCert, ExtensionOrError, UserState)
+ end.
+
maybe_check_hostname(OtpCert, valid_peer, SslState) ->
case ssl_certificate:validate(OtpCert, valid_peer, SslState) of
{valid, _} ->
@@ -2076,11 +2114,10 @@ path_validation_alert(Reason) ->
digitally_signed(Version, Msg, HashAlgo, PrivateKey, SignAlgo) ->
- try do_digitally_signed(Version, Msg, HashAlgo, PrivateKey, SignAlgo) of
- Signature ->
- Signature
+ try do_digitally_signed(Version, Msg, HashAlgo, PrivateKey, SignAlgo)
catch
- error:badkey->
+ error:Reason:ST ->
+ ?SSL_LOG(info, sign_error, [{error, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, bad_key(PrivateKey)))
end.
@@ -2263,7 +2300,8 @@ encrypted_premaster_secret(Secret, RSAPublicKey) ->
rsa_pkcs1_padding}]),
#encrypted_premaster_secret{premaster_secret = PreMasterSecret}
catch
- _:_->
+ _:Reason:ST->
+ ?SSL_LOG(debug, encrypt_error, [{reason, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, premaster_encryption_failed))
end.
@@ -3060,13 +3098,13 @@ decode_extensions(<<?UINT16(?EARLY_DATA_EXT), ?UINT16(4), ?UINT32(MaxSize),
Acc#{early_data =>
#early_data_indication_nst{indication = MaxSize}});
decode_extensions(<<?UINT16(?CERTIFICATE_AUTHORITIES_EXT), ?UINT16(Len),
- CertAuts0:Len/binary, Rest/binary>>,
+ CertAutsExt:Len/binary, Rest/binary>>,
Version, MessageType, Acc) ->
CertAutsLen = Len - 2,
- <<?UINT16(CertAutsLen), CertAuts/binary>> = CertAuts0,
+ <<?UINT16(CertAutsLen), EncCertAuts/binary>> = CertAutsExt,
decode_extensions(Rest, Version, MessageType,
Acc#{certificate_authorities =>
- #certificate_authorities{authorities = CertAuts}});
+ #certificate_authorities{authorities = decode_cert_auths(EncCertAuts, [])}});
%% Ignore data following the ClientHello (i.e.,
%% extensions) if not understood.
decode_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Version, MessageType, Acc) ->
@@ -3087,18 +3125,10 @@ decode_sign_alg({3,3}, SignSchemeList) ->
{true, {Hash, Sign}};
{Hash, rsa_pss_pss = Sign, _} ->
{true,{Hash, Sign}};
- {sha1, rsa_pkcs1, _} ->
- {true,{sha, rsa}};
{Hash, rsa_pkcs1, _} ->
{true,{Hash, rsa}};
- {sha1, ecdsa, _} ->
- {true,{sha, ecdsa}};
- {sha512,ecdsa, _} ->
- {true,{sha512, ecdsa}};
- {sha384,ecdsa, _} ->
- {true,{sha384, ecdsa}};
- {sha256,ecdsa, _}->
- {true,{sha256, ecdsa}};
+ {Hash, ecdsa, _} ->
+ {true,{Hash, ecdsa}};
_ ->
false
end;
@@ -3213,6 +3243,11 @@ decode_psk_binders(<<>>, Acc) ->
decode_psk_binders(<<?BYTE(Len), Binder:Len/binary, Rest/binary>>, Acc) ->
decode_psk_binders(Rest, [Binder|Acc]).
+decode_cert_auths(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_cert_auths(<<?UINT16(Len), Auth:Len/binary, Rest/binary>>, Acc) ->
+ decode_cert_auths(Rest, [public_key:pkix_normalize_name(Auth) | Acc]).
+
%% encode/decode stream of certificate data to/from list of certificate data
certs_to_list(ASN1Certs) ->
certs_to_list(ASN1Certs, []).
@@ -3477,21 +3512,6 @@ is_acceptable_cert_type(Sign, Types) ->
is_supported_sign(SignAlgo, _, HashSigns, []) ->
ssl_cipher:is_supported_sign(SignAlgo, HashSigns);
%% {'SignatureAlgorithm',{1,2,840,113549,1,1,11},'NULL'}
-is_supported_sign({Hash, Sign}, 'NULL', _, SignatureSchemes) ->
- Fun = fun (Scheme, Acc) ->
- {H0, S0, _} = ssl_cipher:scheme_to_components(Scheme),
- S1 = case S0 of
- rsa_pkcs1 -> rsa;
- S -> S
- end,
- H1 = case H0 of
- sha1 -> sha;
- H -> H
- end,
- Acc orelse (Sign =:= S1 andalso
- Hash =:= H1)
- end,
- lists:foldl(Fun, false, SignatureSchemes);
%% TODO: Implement validation for the curve used in the signature
%% RFC 3279 - 2.2.3 ECDSA Signature Algorithm
%% When the ecdsa-with-SHA1 algorithm identifier appears as the
@@ -3503,20 +3523,15 @@ is_supported_sign({Hash, Sign}, 'NULL', _, SignatureSchemes) ->
%% the certificate of the issuer SHALL apply to the verification of the
%% signature.
is_supported_sign({Hash, Sign}, _Param, _, SignatureSchemes) ->
- Fun = fun (Scheme, Acc) ->
- {H0, S0, _} = ssl_cipher:scheme_to_components(Scheme),
+ Fun = fun (Scheme) ->
+ {H, S0, _} = ssl_cipher:scheme_to_components(Scheme),
S1 = case S0 of
rsa_pkcs1 -> rsa;
S -> S
end,
- H1 = case H0 of
- sha1 -> sha;
- H -> H
- end,
- Acc orelse (Sign =:= S1 andalso
- Hash =:= H1)
+ (Sign =:= S1) andalso (Hash =:= H)
end,
- lists:foldl(Fun, false, SignatureSchemes).
+ lists:any(Fun, SignatureSchemes).
%% SupportedSignatureAlgorithms SIGNATURE-ALGORITHM-CLASS ::= {
@@ -3843,12 +3858,12 @@ path_validation(TrustedCert, Path, ServerName, Role, CertDbHandle, CertDbRef, CR
customize_hostname_check := CustomizeHostnameCheck,
crl_check := CrlCheck,
log_level := Level,
- signature_algs := SignAlgos,
- signature_algs_cert := SignAlgosCert,
- depth := Depth},
+ depth := Depth} = Opts,
#{cert_ext := CertExt,
ocsp_responder_certs := OcspResponderCerts,
ocsp_state := OcspState}) ->
+ SignAlgos = maps:get(signature_algs, Opts, undefined),
+ SignAlgosCert = maps:get(signature_algs_cert, Opts, undefined),
ValidationFunAndState =
validation_fun_and_state(VerifyFun, #{role => Role,
certdb => CertDbHandle,
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index 3c770f4e25..6dd47019f4 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -54,6 +54,7 @@
dh_public_value %% TLS 1.3 DH Public Value from peer
}).
+-define(EMPTY_ID, <<>>).
-define(NUM_OF_SESSION_ID_BYTES, 32). % TSL 1.1 & SSL 3
-define(NUM_OF_PREMASTERSECRET_BYTES, 48).
-define(DEFAULT_DIFFIE_HELLMAN_GENERATOR, ssl_dh_groups:modp2048_generator()).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index a611f237d0..cdb3154cb6 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -23,7 +23,8 @@
-ifndef(ssl_internal).
-define(ssl_internal, true).
--include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
+-include_lib("public_key/include/public_key.hrl").
-define(SECRET_PRINTOUT, "***").
@@ -132,6 +133,7 @@
cacerts]},
cacerts => {undefined, [versions]},
cert => {undefined, [versions]},
+ certs_keys => {undefined, [versions]},
certfile => {<<>>, [versions]},
certificate_authorities => {false, [versions]},
ciphers => {[], [versions]},
@@ -154,6 +156,7 @@
hibernate_after => {infinity, [versions]},
honor_cipher_order => {false, [versions]},
honor_ecc_order => {undefined, [versions]},
+ keep_secrets => {false, [versions]},
key => {undefined, [versions]},
keyfile => {undefined, [versions,
certfile]},
@@ -177,11 +180,12 @@
password => {"", [versions]},
protocol => {tls, []},
psk_identity => {undefined, [versions]},
+ receiver_spawn_opts => {[], [versions]},
renegotiate_at => {?DEFAULT_RENEGOTIATE_AT, [versions]},
reuse_session => {undefined, [versions]},
reuse_sessions => {true, [versions]},
secure_renegotiate => {true, [versions]},
- keep_secrets => {false, [versions]},
+ sender_spawn_opts => {[], [versions]},
server_name_indication => {undefined, [versions]},
session_tickets => {disabled, [versions]},
signature_algs => {undefined, [versions]},
@@ -217,10 +221,30 @@
versions => {[], [protocol]}
}).
--define('TLS-1_3_ONLY_OPTIONS', [anti_replay, cookie, early_data, key_update_at, middlebox_comp_mode, session_tickets, supported_groups, use_ticket]).
--define('FROM_TLS-1_2_ONLY_OPTIONS', [signature_algs, signature_algs_cert]).
--define('PRE_TLS-1_3_ONLY_OPTIONS', [client_renegotiation, secure_renegotiate]).
--define('TLS-1_0_ONLY_OPTIONS', [padding_check, beast_mitigation]).
+-define('TLS-1_3_ONLY_OPTIONS', [anti_replay,
+ certificate_authorities,
+ cookie,
+ early_data,
+ key_update_at,
+ middlebox_comp_mode,
+ session_tickets,
+ supported_groups,
+ use_ticket]).
+-define('FROM_TLS-1_2_ONLY_OPTIONS', [signature_algs,
+ signature_algs_cert]).
+-define('PRE_TLS-1_3_ONLY_OPTIONS', [client_renegotiation,
+ dh_file,
+ eccs,
+ fallback,
+ secure_renegotiate,
+ psk_identity,
+ reuse_session,
+ reuse_sessions,
+ srp_identity,
+ user_lookup_fun
+ ]).
+-define('TLS-1_0_ONLY_OPTIONS', [padding_check,
+ beast_mitigation]).
-record(socket_options,
{
@@ -247,6 +271,24 @@
{stop, any(), any()}.
-type ssl_options() :: map().
+
+-define(SSL_LOG(Level, Descr, Reason),
+ fun() ->
+ case get(log_level) of
+ undefined ->
+ %% Use debug here, i.e. log everything and let loggers
+ %% log_level decide if it should be logged
+ ssl_logger:log(Level, debug,
+ #{description => Descr, reason => Reason},
+ ?LOCATION);
+ __LogLevel__ ->
+ ssl_logger:log(Level, __LogLevel__,
+ #{description => Descr, reason => Reason},
+ ?LOCATION)
+ end
+ end()).
+
+
%% Internal ticket data record holding pre-processed ticket data.
-record(ticket_data,
{key, %% key in client ticket store
diff --git a/lib/ssl/src/ssl_logger.erl b/lib/ssl/src/ssl_logger.erl
index 9e872587e2..8777233b81 100644
--- a/lib/ssl/src/ssl_logger.erl
+++ b/lib/ssl/src/ssl_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,10 +57,10 @@ log(Level, LogLevel, ReportMap, Meta) ->
ok
end.
-debug(Level, Direction, Protocol, Message)
+debug(LogLevel, Direction, Protocol, Message)
when (Direction =:= inbound orelse Direction =:= outbound) andalso
(Protocol =:= 'record' orelse Protocol =:= 'handshake') ->
- case logger:compare_levels(Level, debug) of
+ case logger:compare_levels(LogLevel, debug) of
lt ->
?LOG_DEBUG(#{direction => Direction,
protocol => Protocol,
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index a4fb07c795..2e96624a2b 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -20,6 +20,8 @@
%%----------------------------------------------------------------------
%% Purpose: Manages ssl sessions and trusted certifacates
+%% (Note: See the document internal_doc/pem_and_cert_cache.md for additional
+%% information)
%%----------------------------------------------------------------------
-module(ssl_manager).
@@ -274,23 +276,23 @@ init([ManagerName, PemCacheName, Opts]) ->
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call({{connection_init, <<>>, Role, {CRLCb, UserCRLDb}}, _Pid}, _From,
- #state{certificate_db = [CertDb, FileRefDb, PemChace | _] = Db} = State) ->
+ #state{certificate_db = [CertDb, FileRefDb, PemCache | _] = Db} = State) ->
Ref = make_ref(),
{reply, {ok, #{cert_db_ref => Ref,
cert_db_handle => CertDb,
fileref_db_handle => FileRefDb,
- pem_cache => PemChace,
+ pem_cache => PemCache,
session_cache => session_cache(Role, State),
crl_db_info => {CRLCb, crl_db_info(Db, UserCRLDb)}}}, State};
handle_call({{connection_init, Trustedcerts, Role, {CRLCb, UserCRLDb}}, Pid}, _From,
- #state{certificate_db = [CertDb, FileRefDb, PemChace | _] = Db} = State) ->
+ #state{certificate_db = [CertDb, FileRefDb, PemCache | _] = Db} = State) ->
case add_trusted_certs(Pid, Trustedcerts, Db) of
{ok, Ref} ->
{reply, {ok, #{cert_db_ref => Ref,
cert_db_handle => CertDb,
fileref_db_handle => FileRefDb,
- pem_cache => PemChace,
+ pem_cache => PemCache,
session_cache => session_cache(Role, State),
crl_db_info => {CRLCb, crl_db_info(Db, UserCRLDb)}}}, State};
{error, _} = Error ->
@@ -310,10 +312,12 @@ handle_call({{register_session, Host, Port, Session},_}, _, State0) ->
State = client_register_session(Host, Port, Session, State0),
{reply, ok, State};
handle_call({refresh_trusted_db, _}, _, #state{certificate_db = Db} = State) ->
- ssl_pkix_db:refresh_trusted_certs(Db),
+ PemCache = get(ssl_pem_cache),
+ ssl_pkix_db:refresh_trusted_certs(Db, PemCache),
{reply, ok, State};
handle_call({{refresh_trusted_db, File}, _}, _, #state{certificate_db = Db} = State) ->
- ssl_pkix_db:refresh_trusted_certs(File, Db),
+ PemCache = get(ssl_pem_cache),
+ ssl_pkix_db:refresh_trusted_certs(File, Db, PemCache),
{reply, ok, State}.
%%--------------------------------------------------------------------
@@ -461,7 +465,7 @@ invalidate_session(Cache, CacheCb, Key, _Session,
clean_cert_db(Ref, CertDb, RefDb, FileMapDb, File) ->
case ssl_pkix_db:ref_count(Ref, RefDb, 0) of
- 0 ->
+ 0 ->
ssl_pkix_db:remove(Ref, RefDb),
ssl_pkix_db:remove(File, FileMapDb),
ssl_pkix_db:remove_trusted_certs(Ref, CertDb);
diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl
index 2c24351714..cc1c04da9a 100644
--- a/lib/ssl/src/ssl_pem_cache.erl
+++ b/lib/ssl/src/ssl_pem_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 20016-2021. All Rights Reserved.
+%% Copyright Ericsson AB 20016-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
%%----------------------------------------------------------------------
%% Purpose: Manages ssl sessions and trusted certifacates
+%% (Note: See the document internal_doc/pem_and_cert_cache.md for additional
+%% information)
%%----------------------------------------------------------------------
-module(ssl_pem_cache).
@@ -50,7 +52,6 @@
}).
-define(CLEAR_PEM_CACHE, 120000).
--define(DEFAULT_MAX_SESSION_CACHE, 1000).
%%====================================================================
%% API
diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl
index dbdae5307c..eac9e2a8b3 100644
--- a/lib/ssl/src/ssl_pkix_db.erl
+++ b/lib/ssl/src/ssl_pkix_db.erl
@@ -31,11 +31,11 @@
-export([create/1, create_pem_cache/1,
add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3,
- refresh_trusted_certs/1,
refresh_trusted_certs/2,
+ refresh_trusted_certs/3,
extract_trusted_certs/1,
remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1,
- ref_count/3, lookup_trusted_cert/4, foldl/3, select_cert_by_issuer/2,
+ ref_count/3, lookup_trusted_cert/4, foldl/3, select_certentries_by_ref/2,
decode_pem_file/1, lookup/2]).
%%====================================================================
@@ -117,7 +117,7 @@ lookup_trusted_cert(_DbHandle, {extracted,Certs}, SerialNumber, Issuer) ->
CertSerial =:= SerialNumber, CertIssuer =:= Issuer],
undefined
catch
- Cert ->
+ throw:Cert ->
{ok, Cert}
end.
@@ -132,12 +132,12 @@ lookup_trusted_cert(_DbHandle, {extracted,Certs}, SerialNumber, Issuer) ->
add_trusted_certs(_Pid, {extracted, _} = Certs, _) ->
{ok, Certs};
-add_trusted_certs(_Pid, {der, DerList}, [CertDb, _,_ | _]) ->
+add_trusted_certs(_Pid, {der, DerList}, [CertDb, _, _ | _]) ->
NewRef = make_ref(),
add_certs_from_der(DerList, NewRef, CertDb),
{ok, NewRef};
-add_trusted_certs(_Pid, File, [ _, {RefDb, FileMapDb} | _] = Db) ->
+add_trusted_certs(_Pid, File, [_, {RefDb, FileMapDb} | _] = Db) ->
case lookup(File, FileMapDb) of
[Ref] ->
ref_count(Ref, RefDb, 1),
@@ -146,18 +146,18 @@ add_trusted_certs(_Pid, File, [ _, {RefDb, FileMapDb} | _] = Db) ->
new_trusted_cert_entry(File, Db)
end.
-refresh_trusted_certs(File, [CertsDb, {_, FileMapDb} | _]) ->
+refresh_trusted_certs(File, [CertsDb, {_, FileMapDb} | _], PemCache) ->
case lookup(File, FileMapDb) of
[Ref] ->
- {ok, Content} = decode_pem_file(File),
- remove_trusted_certs(Ref, CertsDb),
- add_certs_from_pem(Content, Ref, CertsDb);
+ Certs = ssl_certificate:file_to_certificats(File, PemCache),
+ KeyList = select_certentries_by_ref(Ref,CertsDb),
+ update_certs(Ref, Certs, KeyList, CertsDb);
undefined ->
ok
end.
-refresh_trusted_certs([_, {_, FileMapDb} | _] = Db) ->
+refresh_trusted_certs([_, {_, FileMapDb} | _] = Db, PemCache) ->
Refresh = fun({File, _}, Acc) ->
- refresh_trusted_certs(File, Db),
+ refresh_trusted_certs(File, Db, PemCache),
Acc
end,
foldl(Refresh, refresh, FileMapDb).
@@ -243,9 +243,13 @@ lookup(Key, Db) ->
foldl(Fun, Acc0, Cache) ->
ets:foldl(Fun, Acc0, Cache).
-
-select_cert_by_issuer(Cache, Issuer) ->
- ets:select(Cache, [{{{'_','_', Issuer},{'_', '$1'}},[],['$$']}]).
+%%--------------------------------------------------------------------
+-spec select_certentries_by_ref(reference(), db_handle()) -> term().
+%%
+%% Description: Select certs entries originating from same source
+%%--------------------------------------------------------------------
+select_certentries_by_ref(Ref, Cache) ->
+ ets:select(Cache, [{{{Ref,'_', '_'}, '_'},[],['$_']}]).
%%--------------------------------------------------------------------
-spec ref_count(term(), db_handle(), integer()) -> integer().
@@ -297,40 +301,40 @@ remove_certs(Ref, CertsDb) ->
ok.
add_certs_from_der(DerList, Ref, CertsDb) ->
- Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end,
+ Add = fun(Cert) -> add_cert(Cert, Ref, CertsDb) end,
[Add(Cert) || Cert <- DerList],
ok.
certs_from_der(DerList) ->
Ref = make_ref(),
[Decoded || Cert <- DerList,
- Decoded <- [decode_certs(Ref, Cert)],
+ Decoded <- [decode_cert(Ref, Cert)],
Decoded =/= undefined].
add_certs_from_pem(PemEntries, Ref, CertsDb) ->
- Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end,
+ Add = fun(Cert) -> add_cert(Cert, Ref, CertsDb) end,
[Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries],
ok.
-add_certs(Cert, Ref, CertsDb) ->
+add_cert(Cert, Ref, CertsDb) ->
try
- {decoded, {Key, Val}} = decode_certs(Ref, Cert),
+ {decoded, {Key, Val}} = decode_cert(Ref, Cert),
insert(Key, Val, CertsDb)
catch
error:_ ->
ok
end.
-decode_certs(Ref, #cert{otp=ErlCert} = Cert) ->
+decode_cert(Ref, #cert{otp=ErlCert} = Cert) ->
TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
Issuer = public_key:pkix_normalize_name(
TBSCertificate#'OTPTBSCertificate'.issuer),
{decoded, {{Ref, SerialNumber, Issuer}, Cert}};
-decode_certs(Ref, Der) ->
+decode_cert(Ref, Der) ->
try public_key:pkix_decode_cert(Der, otp) of
ErlCert ->
- decode_certs(Ref, #cert{der=Der, otp=ErlCert})
+ decode_cert(Ref, #cert{der=Der, otp=ErlCert})
catch error:_ ->
?LOG_NOTICE("SSL WARNING: Ignoring a CA cert as "
"it could not be correctly decoded.~n"),
@@ -352,7 +356,7 @@ new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->
add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) ->
[add_crls(CRL, Mapping) || CRL <- CRLs];
add_crls([_,_,_, {Cache, Mapping} | _], Path, CRLs) ->
- insert(Path, CRLs, Cache),
+ insert(Path, CRLs, Cache),
[add_crls(CRL, Mapping) || CRL <- CRLs].
add_crls(CRL, Mapping) ->
@@ -365,7 +369,7 @@ remove_crls([_,_,_, {Cache, Mapping} | _], Path) ->
case lookup(Path, Cache) of
undefined ->
ok;
- CRLs ->
+ [CRLs] ->
remove(Path, Cache),
[rm_crls(CRL, Mapping) || CRL <- CRLs]
end.
@@ -378,3 +382,27 @@ crl_issuer(DerCRL) ->
TBSCRL = CRL#'CertificateList'.tbsCertList,
TBSCRL#'TBSCertList'.issuer.
+update_certs(Ref, CertList, KeyList, CertsDb) ->
+ {Insert, Delete} = insert_delete_lists(Ref, CertList, CertsDb, [], KeyList),
+ insert_cert_entries(Insert, CertsDb),
+ remove_cert_entries(Delete, CertsDb).
+
+insert_delete_lists(_, [], _, Insert, Delete) ->
+ {Insert, Delete};
+insert_delete_lists(Ref, [Cert | Rest], CertsDb, Insert, Delete) ->
+ case decode_cert(Ref, Cert) of
+ {decoded, {Key, Value} = Entry} ->
+ case lookup(Key, CertsDb) of
+ [Value] -> %% Entry already exists and is unchanged
+ insert_delete_lists(Ref, Rest, CertsDb, Insert, lists:keydelete(Key, 1, Delete));
+ _ ->
+ insert_delete_lists(Ref, Rest, CertsDb, [Entry | Insert], lists:keydelete(Key, 1, Delete))
+ end;
+ undefined ->
+ insert_delete_lists(Ref, Rest, CertsDb, Insert, Delete)
+ end.
+
+insert_cert_entries(EntryList, CertsDb) ->
+ ets:insert(CertsDb, EntryList).
+remove_cert_entries(EntryList, CertsDb) ->
+ lists:foreach(fun({Key, Value}) -> remove(Key, Value, CertsDb) end, EntryList).
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index c3c31e8767..b7b68edd82 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -447,11 +447,14 @@ decipher_aead(Type, #cipher_state{key = Key} = CipherState, AAD0, CipherFragment
case ssl_cipher:aead_decrypt(Type, Key, Nonce, CipherText, CipherTag, AAD) of
Content when is_binary(Content) ->
Content;
- _ ->
+ Reason ->
+ ?SSL_LOG(debug, decrypt_error, [{reason,Reason},
+ {stacktrace, process_info(self(), current_stacktrace)}]),
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end
catch
- _:_ ->
+ _:Reason2:ST ->
+ ?SSL_LOG(debug, decrypt_error, [{reason,Reason2}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end.
@@ -480,10 +483,10 @@ empty_connection_state(ConnectionEnd, Version,
secure_renegotiation => undefined,
client_verify_data => undefined,
server_verify_data => undefined,
- max_early_data_size => MaxEarlyDataSize,
+ pending_early_data_size => MaxEarlyDataSize,
max_fragment_length => undefined,
trial_decryption => false,
- early_data_limit => false
+ early_data_accepted => false
}.
init_security_parameters(?CLIENT, Version) ->
diff --git a/lib/ssl/src/ssl_session.erl b/lib/ssl/src/ssl_session.erl
index 2f35c54c64..3999b2fc0e 100644
--- a/lib/ssl/src/ssl_session.erl
+++ b/lib/ssl/src/ssl_session.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
+%%
%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
-%%
+%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
@@ -14,7 +14,7 @@
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -30,9 +30,13 @@
-include("ssl_api.hrl").
%% Internal application API
--export([is_new/2, client_select_session/5, server_select_session/5, valid_session/2, legacy_session_id/0]).
+-export([is_new/2,
+ client_select_session/5,
+ server_select_session/5,
+ valid_session/2,
+ legacy_session_id/1]).
--type seconds() :: integer().
+-type seconds() :: integer().
%%--------------------------------------------------------------------
-spec legacy_session_id() -> ssl:session_id().
@@ -42,51 +46,71 @@
%% If now lower versions are configured this function can be called
%% for a dummy value.
%%--------------------------------------------------------------------
-legacy_session_id() ->
- crypto:strong_rand_bytes(32).
-
+legacy_session_id(#{middlebox_comp_mode := true}) ->
+ legacy_session_id();
+legacy_session_id(_) ->
+ ?EMPTY_ID.
%%--------------------------------------------------------------------
--spec is_new(ssl:session_id(), ssl:session_id()) -> boolean().
-%%
-%% Description: Checks if the session id decided by the server is a
-%% new or resumed sesion id.
+-spec is_new(ssl:session_id() | #session{}, ssl:session_id()) -> boolean().
+ %%
+ %% Description: Checks if the session id decided by the server is a
+%% new or resumed sesion id. TLS-1.3 middlebox negotiation
+%% requies that client also needs to check "is_resumable" in
+%% its current session data when pre TLS-1.3 version is
+%% negotiated.
%%--------------------------------------------------------------------
-is_new(<<>>, _) ->
+is_new(?EMPTY_ID, _) ->
true;
is_new(SessionId, SessionId) ->
false;
+is_new(#session{session_id = ?EMPTY_ID}, _) ->
+ true;
+is_new(#session{session_id = SessionId,
+ is_resumable = true}, SessionId) ->
+ false;
is_new(_ClientSuggestion, _ServerDecision) ->
true.
%%--------------------------------------------------------------------
--spec client_select_session({ssl:host(), inet:port_number(), map()}, db_handle(), atom(),
- #session{}, list()) -> #session{}.
+-spec client_select_session({ssl:host(), inet:port_number(), map()},
+ db_handle(), atom(), #session{}, list()) -> #session{}.
%%
%% Description: Should be called by the client side to get an id
%% for the client hello message.
%%--------------------------------------------------------------------
client_select_session({_, _, #{versions := Versions,
- protocol := Protocol}} = ClientInfo,
+ protocol := Protocol} = Opts} = ClientInfo,
Cache, CacheCb, NewSession, CertKeyPairs) ->
-
+
RecordCb = record_cb(Protocol),
- Version = RecordCb:lowest_protocol_version(Versions),
-
- case Version of
- {3, N} when N >= 4 ->
- NewSession#session{session_id = legacy_session_id()};
+ LVersion = RecordCb:lowest_protocol_version(Versions),
+ HVersion = RecordCb:highest_protocol_version(Versions),
+
+ case LVersion of
+ {3, 4} ->
+ %% Session reuse is not supported, do pure legacy
+ %% middlebox comp mode negotiation, by providing either
+ %% empty session id (no middle box) or random id (middle
+ %% box mode).
+ NewSession#session{session_id = legacy_session_id(Opts)};
_ ->
- do_client_select_session(ClientInfo, Cache, CacheCb, NewSession, CertKeyPairs)
- end.
+ Session = do_client_select_session(ClientInfo, Cache, CacheCb,
+ NewSession, CertKeyPairs),
+ %% If TLS-1.3 is highest version and there was no previous
+ %% session id that could be reused, if TLS-1.3 is not
+ %% negotiated, possibly use random id for middle box mode
+ %% negotiation.
+ maybe_handle_middlebox(HVersion, Session, Opts)
+ end.
%%--------------------------------------------------------------------
--spec server_select_session(ssl_record:ssl_version(), pid(), binary(), map(),
+-spec server_select_session(ssl_record:ssl_version(), pid(), ssl:session_id(), map(),
list()) -> {binary(), #session{} | undefined}.
%%
%% Description: Should be called by the server side to get an id
%% for the client hello message.
%%--------------------------------------------------------------------
-server_select_session(_, SessIdTracker, <<>>, _SslOpts, _CertKeyPairs) ->
+server_select_session(_, SessIdTracker, ?EMPTY_ID, _SslOpts, _CertKeyPairs) ->
{ssl_server_session_cache:new_session_id(SessIdTracker), undefined};
server_select_session(_, SessIdTracker, SuggestedId, Options, CertKeyPairs) ->
case is_resumable(SuggestedId, SessIdTracker, Options, CertKeyPairs)
@@ -111,26 +135,28 @@ valid_session(#session{time_stamp = TimeStamp}, LifeTime) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-do_client_select_session({_, _, #{reuse_session := {SessionId, SessionData}}}, _, _, NewSession, _) when is_binary(SessionId) andalso
- is_binary(SessionData) ->
+do_client_select_session({_, _, #{reuse_session := {SessionId, SessionData}}},
+ _, _, NewSession, _) when is_binary(SessionId) andalso
+ is_binary(SessionData) ->
try binary_to_term(SessionData, [safe]) of
Session ->
- Session
+ Session#session{is_resumable = true}
catch
_:_ ->
- NewSession#session{session_id = <<>>}
+ NewSession#session{session_id = ?EMPTY_ID}
end;
-do_client_select_session({Host, Port, #{reuse_session := SessionId}}, Cache, CacheCb, NewSession, _) when is_binary(SessionId)->
+do_client_select_session({Host, Port, #{reuse_session := SessionId}},
+ Cache, CacheCb, NewSession, _) when is_binary(SessionId)->
case CacheCb:lookup(Cache, {{Host, Port}, SessionId}) of
undefined ->
- NewSession#session{session_id = <<>>};
+ NewSession#session{session_id = ?EMPTY_ID};
#session{} = Session->
Session
end;
do_client_select_session(ClientInfo, Cache, CacheCb, NewSession, CertKeyPairs) ->
case select_session(ClientInfo, Cache, CacheCb, CertKeyPairs) of
no_session ->
- NewSession#session{session_id = <<>>};
+ NewSession#session{session_id = ?EMPTY_ID};
Session ->
Session
end.
@@ -156,7 +182,8 @@ select_session(Sessions, #{ciphers := Ciphers}, CertKeyPairs) ->
end,
not (resumable(Session#session.is_resumable) andalso
lists:member(Session#session.cipher_suite, Ciphers)
- andalso (is_owncert(SessionOwnCert, CertKeyPairs) orelse (SessionOwnCert == undefined)))
+ andalso (is_owncert(SessionOwnCert, CertKeyPairs)
+ orelse (SessionOwnCert == undefined)))
end,
case lists:dropwhile(IsNotResumable, Sessions) of
[] -> no_session;
@@ -165,7 +192,8 @@ select_session(Sessions, #{ciphers := Ciphers}, CertKeyPairs) ->
is_resumable(_, _, #{reuse_sessions := false}, _) ->
{false, undefined};
-is_resumable(SuggestedSessionId, SessIdTracker, #{reuse_session := ReuseFun} = Options, OwnCertKeyPairs) ->
+is_resumable(SuggestedSessionId, SessIdTracker,
+ #{reuse_session := ReuseFun} = Options, OwnCertKeyPairs) ->
case ssl_server_session_cache:reuse_session(SessIdTracker, SuggestedSessionId) of
#session{cipher_suite = CipherSuite,
own_certificates = [SessionOwnCert | _],
@@ -207,3 +235,11 @@ record_cb(tls) ->
tls_record;
record_cb(dtls) ->
dtls_record.
+
+legacy_session_id() ->
+ crypto:strong_rand_bytes(32).
+
+maybe_handle_middlebox({3, 4}, #session{session_id = ?EMPTY_ID} = Session, #{middlebox_comp_mode := true})->
+ Session#session{session_id = legacy_session_id()};
+maybe_handle_middlebox(_, Session, _) ->
+ Session.
diff --git a/lib/ssl/src/tls_client_ticket_store.erl b/lib/ssl/src/tls_client_ticket_store.erl
index eb10adc9f1..146fd4c8cc 100644
--- a/lib/ssl/src/tls_client_ticket_store.erl
+++ b/lib/ssl/src/tls_client_ticket_store.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -202,8 +202,8 @@ iterate_tickets(Iter0, Pid, Ciphers, Hash, SNI, Lifetime, EarlyDataSize, Acc) ->
lock = Lock}, Iter} when Lock =:= undefined orelse
Lock =:= Pid ->
MaxEarlyData = tls_handshake_1_3:get_max_early_data(Extensions),
- Age = erlang:system_time(seconds) - Timestamp,
- if Age < Lifetime ->
+ Age = erlang:monotonic_time(millisecond) - Timestamp,
+ if Age < Lifetime * 1000 ->
case verify_ticket_sni(SNI, TicketSNI) of
match ->
case lists:member(Cipher, Ciphers) of
@@ -274,7 +274,7 @@ get_tickets(#state{db = Db} = State, Pid, [Key|T], Acc) ->
ticket = Ticket,
extensions = Extensions
} = NewSessionTicket,
- TicketAge = erlang:system_time(seconds) - Timestamp,
+ TicketAge = erlang:monotonic_time(millisecond) - Timestamp,
ObfuscatedTicketAge = obfuscate_ticket_age(TicketAge, AgeAdd),
Identity = #psk_identity{
identity = Ticket,
@@ -329,8 +329,8 @@ collect_invalid_tickets(Iter0, Lifetime, Acc) ->
case gb_trees:next(Iter0) of
{Key, #data{timestamp = Timestamp,
lock = undefined}, Iter} ->
- Age = erlang:system_time(seconds) - Timestamp,
- if Age < Lifetime ->
+ Age = erlang:monotonic_time(millisecond) - Timestamp,
+ if Age < Lifetime * 1000 ->
collect_invalid_tickets(Iter, Lifetime, Acc);
true ->
collect_invalid_tickets(Iter, Lifetime, [Key|Acc])
@@ -343,7 +343,7 @@ collect_invalid_tickets(Iter0, Lifetime, Acc) ->
store_ticket(#state{db = Db0, max = Max} = State, Ticket, CipherSuite, SNI, PSK) ->
- Timestamp = erlang:system_time(seconds),
+ Timestamp = erlang:monotonic_time(millisecond),
Size = gb_trees:size(Db0),
Db1 = if Size =:= Max ->
delete_oldest(Db0);
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 05cf5bb6c3..6cc9e21cfb 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -34,6 +34,7 @@
%% ClientKeyExchange \
%% CertificateVerify* Flight 3 part 1
%% [ChangeCipherSpec] /
+%% NextProtocol*
%% Finished --------> / Flight 3 part 2
%% [ChangeCipherSpec]
%% <-------- Finished Flight 4
@@ -48,6 +49,7 @@
%% [ChangeCipherSpec]
%% <-------- Finished Abbrev Flight 2 part 2
%% [ChangeCipherSpec]
+%% NextProtocol*
%% Finished --------> Abbrev Flight 3
%% Application Data <-------> Application Data
%%
@@ -70,13 +72,14 @@
%% |
%% New session | Resumed session
%% WAIT_OCSP_STAPELING CERTIFY <----------------------------------> ABBRIVIATED
-%%
+%% WAIT_CERT_VERIFY
%% <- Possibly Receive -- | |
-%% OCSP Stapel ------> | Flight 3 part 1 |
+%% OCSP Stapel/CertVerify -> | Flight 3 part 1 |
%% | |
%% V | Abbrev Flight 2 part 2 to Abbrev Flight 3
%% CIPHER |
%% | |
+%% | |
%% | Fligth 3 part 2 to Flight 4 |
%% | |
%% V V
@@ -111,7 +114,8 @@
%% Setup
-export([init/1]).
--export([renegotiate/2]).
+-export([renegotiate/2,
+ choose_tls_fsm/2]).
%% gen_statem state functions
-export([initial_hello/3,
@@ -121,6 +125,7 @@
user_hello/3,
wait_ocsp_stapling/3,
certify/3,
+ wait_cert_verify/3,
cipher/3,
abbreviated/3,
connection/3]).
@@ -135,17 +140,17 @@
%% Internal application API
%%====================================================================
init([Role, Sender, Host, Port, Socket, Options, User, CbInfo]) ->
- State0 = #state{protocol_specific = Map} = initial_state(Role, Sender,
- Host, Port, Socket, Options, User, CbInfo),
- try
- State1 = #state{static_env = #static_env{session_cache = Cache,
+ State0 = initial_state(Role, Sender, Host, Port, Socket, Options, User, CbInfo),
+ try
+ State1 = #state{static_env = #static_env{session_cache = Cache,
session_cache_cb = CacheCb
},
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs},
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts},
ssl_options = SslOptions,
session = Session0} = ssl_gen_statem:ssl_config(State0#state.ssl_options, Role, State0),
State = case Role of
client ->
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts),
Session = ssl_session:client_select_session({Host, Port, SslOptions}, Cache, CacheCb, Session0, CertKeyPairs),
State1#state{session = Session};
server ->
@@ -154,6 +159,7 @@ init([Role, Sender, Host, Port, Socket, Options, User, CbInfo]) ->
tls_gen_connection:initialize_tls_sender(State),
gen_statem:enter_loop(?MODULE, [], initial_hello, State)
catch throw:Error ->
+ #state{protocol_specific = Map} = State0,
EState = State0#state{protocol_specific = Map#{error => Error}},
gen_statem:enter_loop(?MODULE, [], config_error, EState)
end.
@@ -207,31 +213,26 @@ config_error(Type, Event, State) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-hello(internal, #client_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #{handshake := hello},
- static_env = #static_env{role = server},
- handshake_env = HsEnv,
+hello(internal, #client_hello{extensions = Extensions},
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{continue_status = pause},
start_or_recv_from = From} = State) ->
- {next_state, user_hello, State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{hello = Hello}},
- [{reply, From, {ok, Extensions}}]};
-hello(internal, #server_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #{handshake := hello},
+ {next_state, user_hello, State#state{start_or_recv_from = undefined},
+ [{postpone, true}, {reply, From, {ok, Extensions}}]};
+hello(internal, #server_hello{extensions = Extensions},
+ #state{handshake_env = #handshake_env{continue_status = pause},
static_env = #static_env{role = client},
- handshake_env = HsEnv,
- start_or_recv_from = From} = State) ->
+ start_or_recv_from = From} = State) ->
{next_state, user_hello,
- State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{
- hello = Hello}}, [{reply, From, {ok, Extensions}}]};
+ State#state{start_or_recv_from = undefined}, [{postpone, true}, {reply, From, {ok, Extensions}}]};
hello(internal, #client_hello{client_version = ClientVersion} = Hello,
#state{static_env = #static_env{role = server}, connection_env = CEnv} = State0) ->
try
#state{ssl_options = SslOpts} = State1 = tls_dtls_connection:handle_sni_extension(State0, Hello),
case choose_tls_fsm(SslOpts, Hello) of
tls_1_3_fsm ->
- %% Continue in TLS 1.3 'start' state
- {next_state, start, State1, [{change_callback_module, tls_connection_1_3}, {next_event, internal, Hello}]};
+ {next_state, start, State1,
+ [{change_callback_module, tls_connection_1_3}, {next_event, internal, Hello}]};
tls_1_0_to_1_2_fsm ->
{ServerHelloExt, Type, State} = handle_client_hello(Hello, State1),
{next_state, hello, State, [{next_event, internal, {common_client_hello, Type, ServerHelloExt}}]}
@@ -319,6 +320,19 @@ certify(Type, Event, State) ->
ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
end.
+
+%%--------------------------------------------------------------------
+-spec wait_cert_verify(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cert_verify(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cert_verify(Type, Event, State) ->
+ try tls_dtls_connection:gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, ?FUNCTION_NAME, State)
+ end.
+
%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
@@ -353,13 +367,14 @@ connection(internal, #hello_request{},
handshake_env = #handshake_env{
renegotiation = {Renegotiation, peer},
ocsp_stapling_state = OcspState},
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs},
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts},
session = Session0,
ssl_options = SslOpts,
protocol_specific = #{sender := Pid},
connection_states = ConnectionStates} = State0) ->
try tls_sender:peer_renegotiate(Pid) of
{ok, Write} ->
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts),
Session = ssl_session:client_select_session({Host, Port, SslOpts}, Cache, CacheCb, Session0, CertKeyPairs),
Hello = tls_handshake:client_hello(Host, Port, ConnectionStates, SslOpts,
Session#session.session_id,
@@ -371,8 +386,9 @@ connection(internal, #hello_request{},
ConnectionStates#{current_write => Write},
session = Session}),
tls_gen_connection:next_event(hello, no_record, State, Actions)
- catch
- _:_ ->
+ catch
+ _:Reason:ST ->
+ ?SSL_LOG(info, internal_error, [{error, Reason}, {stacktrace, ST}]),
{stop, {shutdown, sender_blocked}, State0}
end;
connection(internal, #hello_request{},
@@ -459,6 +475,7 @@ code_change(_OldVsn, StateName, State, _) ->
%%--------------------------------------------------------------------
initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trackers}, User,
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
+ put(log_level, maps:get(log_level, SSLOptions)),
#{erl_dist := IsErlDist,
%% Use highest supported version for client/server random nonce generation
versions := [Version|_],
@@ -513,7 +530,7 @@ handle_client_hello(#client_hello{client_version = ClientVersion} = Hello, State
renegotiation = {Renegotiation, _},
negotiated_protocol = CurrentProtocol,
sni_guided_cert_selection = SNICertSelection} = HsEnv,
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs} = CEnv,
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts} = CEnv,
session = Session0,
ssl_options = SslOpts} = State,
SessionTracker = proplists:get_value(session_id_tracker, Trackers),
@@ -522,7 +539,7 @@ handle_client_hello(#client_hello{client_version = ClientVersion} = Hello, State
tls_handshake:hello(Hello,
SslOpts,
{SessionTracker, Session0,
- ConnectionStates0, CertKeyPairs, KeyExAlg},
+ ConnectionStates0, CertKeyAlts, KeyExAlg},
Renegotiation),
Protocol = case Protocol0 of
undefined -> CurrentProtocol;
@@ -549,7 +566,8 @@ gen_info(Event, connection = StateName, State) ->
try
tls_gen_connection:handle_info(Event, StateName, State)
catch
- _:_ ->
+ _:Reason:ST ->
+ ?SSL_LOG(info, internal_error, [{error, Reason}, {stacktrace, ST}]),
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR,
malformed_data),
StateName, State)
@@ -559,7 +577,8 @@ gen_info(Event, StateName, State) ->
try
tls_gen_connection:handle_info(Event, StateName, State)
catch
- _:_ ->
+ _:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
malformed_handshake_data),
StateName, State)
diff --git a/lib/ssl/src/tls_connection_1_3.erl b/lib/ssl/src/tls_connection_1_3.erl
index 19c9a05a2f..8041e48eb0 100644
--- a/lib/ssl/src/tls_connection_1_3.erl
+++ b/lib/ssl/src/tls_connection_1_3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -125,6 +125,8 @@
config_error/3,
user_hello/3,
start/3,
+ hello_middlebox_assert/3,
+ hello_retry_middlebox_assert/3,
negotiated/3,
wait_cert/3,
wait_cv/3,
@@ -183,7 +185,7 @@ update_cipher_key(ConnStateName, CS0) ->
%% gen_statem callbacks
%%--------------------------------------------------------------------
callback_mode() ->
- state_functions.
+ [state_functions, state_enter].
init([Role, Sender, Host, Port, Socket, Options, User, CbInfo]) ->
State0 = #state{protocol_specific = Map} = initial_state(Role, Sender,
@@ -220,6 +222,8 @@ code_change(_OldVsn, StateName, State, _) ->
{start, timeout()} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
+initial_hello(enter, _, State) ->
+ {keep_state, State};
initial_hello(Type, Event, State) ->
ssl_gen_statem:?FUNCTION_NAME(Type, Event, State).
@@ -228,77 +232,126 @@ initial_hello(Type, Event, State) ->
{start, timeout()} | term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
+config_error(enter, _, State) ->
+ {keep_state, State};
config_error(Type, Event, State) ->
ssl_gen_statem:?FUNCTION_NAME(Type, Event, State).
-
+user_hello(enter, _, State) ->
+ {keep_state, State};
user_hello({call, From}, cancel, State) ->
gen_statem:reply(From, ok),
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled),
?FUNCTION_NAME, State);
user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
- #state{static_env = #static_env{role = Role},
- handshake_env = #handshake_env{hello = Hello},
+ #state{static_env = #static_env{role = client = Role},
+ handshake_env = HSEnv,
+ ssl_options = Options0} = State0) ->
+ Options = ssl:handle_options(NewOptions, Role, Options0),
+ State = ssl_gen_statem:ssl_config(Options, Role, State0),
+ {next_state, wait_sh, State#state{start_or_recv_from = From,
+ handshake_env = HSEnv#handshake_env{continue_status = continue}},
+ [{{timeout, handshake}, Timeout, close}]};
+user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
+ #state{static_env = #static_env{role = server = Role},
+ handshake_env = #handshake_env{continue_status = {pause, ClientVersions}} = HSEnv,
ssl_options = Options0} = State0) ->
- Options = ssl:handle_options(NewOptions, Role, Options0#{handshake => full}),
+ Options = #{versions := Versions} = ssl:handle_options(NewOptions, Role, Options0),
State = ssl_gen_statem:ssl_config(Options, Role, State0),
- Next = case Role of
- client ->
- wait_sh;
- server ->
- start
- end,
- {next_state, Next, State#state{start_or_recv_from = From},
- [{next_event, internal, Hello}, {{timeout, handshake}, Timeout, close}]};
+ case ssl_handshake:select_supported_version(ClientVersions, Versions) of
+ {3,4} ->
+ {next_state, start, State#state{start_or_recv_from = From,
+ handshake_env = HSEnv#handshake_env{continue_status = continue}},
+ [{{timeout, handshake}, Timeout, close}]};
+ undefined ->
+ ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION), ?FUNCTION_NAME, State);
+ _Else ->
+ {next_state, hello, State#state{start_or_recv_from = From,
+ handshake_env = HSEnv#handshake_env{continue_status = continue}},
+ [{change_callback_module, tls_connection},
+ {{timeout, handshake}, Timeout, close}]}
+ end;
user_hello(info, {'DOWN', _, _, _, _} = Event, State) ->
ssl_gen_statem:handle_info(Event, ?FUNCTION_NAME, State);
user_hello(_, _, _) ->
{keep_state_and_data, [postpone]}.
-start(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
-start(internal, #client_hello{extensions = Extensions} = Hello,
- #state{ssl_options = #{handshake := hello},
- start_or_recv_from = From,
- handshake_env = HsEnv} = State) ->
+start(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+start(internal = Type, #change_cipher_spec{} = Msg,
+ #state{static_env = #static_env{role = server},
+ handshake_env = #handshake_env{tls_handshake_history = Hist}} = State) ->
+ case ssl_handshake:init_handshake_history() of
+ Hist -> %% First message must always be client hello
+ ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State);
+ _ ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State)
+ end;
+start(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
+start(internal, #client_hello{extensions = #{client_hello_versions :=
+ #client_hello_versions{versions = ClientVersions}
+ }} = Hello,
+ #state{ssl_options = #{handshake := full}} = State) ->
+ case tls_record:is_acceptable_version({3,4}, ClientVersions) of
+ true ->
+ do_server_start(Hello, State);
+ false ->
+ ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION), ?FUNCTION_NAME, State)
+ end;
+start(internal, #client_hello{extensions = #{client_hello_versions :=
+ #client_hello_versions{versions = ClientVersions}
+ }= Extensions},
+ #state{start_or_recv_from = From,
+ handshake_env = #handshake_env{continue_status = pause} = HSEnv} = State) ->
{next_state, user_hello,
- State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{
- hello = Hello}}, [{reply, From, {ok, Extensions}}]};
-start(internal, #client_hello{} = Hello, State0) ->
- case tls_handshake_1_3:do_start(Hello, State0) of
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, start, State0);
- {State, start} ->
- {next_state, start, State, []};
- {State, negotiated} ->
- {next_state, negotiated, State, [{next_event, internal, {start_handshake, undefined}}]};
- {State, negotiated, PSK} -> %% Session Resumption with PSK
- {next_state, negotiated, State, [{next_event, internal, {start_handshake, PSK}}]}
+ State#state{start_or_recv_from = undefined, handshake_env = HSEnv#handshake_env{continue_status = {pause, ClientVersions}}},
+ [{postpone, true}, {reply, From, {ok, Extensions}}]};
+start(internal, #client_hello{} = Hello,
+ #state{handshake_env = #handshake_env{continue_status = continue}} = State) ->
+ do_server_start(Hello, State);
+start(internal, #client_hello{}, State0) -> %% Missing mandantory TLS-1.3 extensions, so it is a previous version hello.
+ ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION), ?FUNCTION_NAME, State0);
+start(internal, #server_hello{extensions = #{server_hello_selected_version :=
+ #server_hello_selected_version{selected_version = Version}}} = ServerHello,
+ #state{ssl_options = #{handshake := full,
+ versions := SupportedVersions}} = State) ->
+ case tls_record:is_acceptable_version(Version, SupportedVersions) of
+ true ->
+ do_client_start(ServerHello, State);
+ false ->
+ ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION), ?FUNCTION_NAME, State)
end;
-start(internal, #server_hello{extensions = Extensions} = ServerHello,
- #state{ssl_options = #{handshake := hello},
- handshake_env = HsEnv,
- start_or_recv_from = From}
+start(internal, #server_hello{extensions = #{server_hello_selected_version :=
+ #server_hello_selected_version{selected_version = Version}}
+ = Extensions},
+ #state{ssl_options = #{versions := SupportedVersions},
+ start_or_recv_from = From,
+ handshake_env = #handshake_env{continue_status = pause}}
= State) ->
- {next_state, user_hello,
- State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{
- hello = ServerHello}}, [{reply, From, {ok, Extensions}}]};
-start(internal, #server_hello{} = ServerHello, State0) ->
- case tls_handshake_1_3:do_start(ServerHello, State0) of
- #alert{} = Alert ->
- ssl_gen_statem:handle_own_alert(Alert, start, State0);
- {State, NextState} ->
- {next_state, NextState, State, []}
+ case tls_record:is_acceptable_version(Version, SupportedVersions) of
+ true ->
+ {next_state, user_hello,
+ State#state{start_or_recv_from = undefined}, [{postpone, true}, {reply, From, {ok, Extensions}}]};
+ false ->
+ ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION), ?FUNCTION_NAME, State)
end;
+start(internal, #server_hello{} = ServerHello,
+ #state{handshake_env = #handshake_env{continue_status = continue}} = State) ->
+ do_client_start(ServerHello, State);
+start(internal, #server_hello{}, State0) -> %% Missing mandantory TLS-1.3 extensions, so it is a previous version hello.
+ ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?PROTOCOL_VERSION), ?FUNCTION_NAME, State0);
start(info, Msg, State) ->
tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State);
start(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-negotiated(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+negotiated(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+negotiated(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
negotiated(internal, Message, State0) ->
case tls_handshake_1_3:do_negotiated(Message, State0) of
#alert{} = Alert ->
@@ -309,8 +362,11 @@ negotiated(internal, Message, State0) ->
negotiated(info, Msg, State) ->
tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State).
-wait_cert(internal, #change_cipher_spec{}, State0) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State0);
+wait_cert(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_cert(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
wait_cert(internal,
#certificate_1_3{} = Certificate, State0) ->
case tls_handshake_1_3:do_wait_cert(Certificate, State0) of
@@ -324,8 +380,11 @@ wait_cert(info, Msg, State) ->
wait_cert(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-wait_cv(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+wait_cv(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_cv(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
wait_cv(internal,
#certificate_verify_1_3{} = CertificateVerify, State0) ->
case tls_handshake_1_3:do_wait_cv(CertificateVerify, State0) of
@@ -339,8 +398,11 @@ wait_cv(info, Msg, State) ->
wait_cv(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-wait_finished(internal, #change_cipher_spec{}, State0) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State0);
+wait_finished(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_finished(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
wait_finished(internal,
#finished{} = Finished, State0) ->
case tls_handshake_1_3:do_wait_finished(Finished, State0) of
@@ -356,34 +418,71 @@ wait_finished(info, Msg, State) ->
wait_finished(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-
-wait_sh(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
-wait_sh(internal, #server_hello{extensions = Extensions} = Hello, #state{ssl_options = #{handshake := hello},
- start_or_recv_from = From,
- handshake_env = HsEnv} = State) ->
+wait_sh(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_sh(internal = Type, #change_cipher_spec{} = Msg, State)->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
+wait_sh(internal, #server_hello{extensions = Extensions},
+ #state{handshake_env = #handshake_env{continue_status = pause},
+ start_or_recv_from = From} = State) ->
{next_state, user_hello,
- State#state{start_or_recv_from = undefined,
- handshake_env = HsEnv#handshake_env{
- hello = Hello}}, [{reply, From, {ok, Extensions}}]};
-wait_sh(internal, #server_hello{} = Hello, State0) ->
+ State#state{start_or_recv_from = undefined}, [{postpone, true},{reply, From, {ok, Extensions}}]};
+wait_sh(internal, #server_hello{session_id = ?EMPTY_ID} = Hello, #state{session = #session{session_id = ?EMPTY_ID},
+ ssl_options = #{middlebox_comp_mode := false}} = State0) ->
case tls_handshake_1_3:do_wait_sh(Hello, State0) of
- #alert{} = Alert ->
+ #alert{} = Alert ->
ssl_gen_statem:handle_own_alert(Alert, wait_sh, State0);
{State1, start, ServerHello} ->
%% hello_retry_request: go to start
- {next_state, start, State1, [{next_event, internal, ServerHello}]};
+ {next_state, start, State1, [{next_event, internal, ServerHello}]};
{State1, wait_ee} ->
- tls_gen_connection:next_event(wait_ee, no_record, State1)
+ tls_gen_connection:next_event(wait_ee, no_record, State1)
+ end;
+wait_sh(internal, #server_hello{} = Hello,
+ #state{protocol_specific = PS, ssl_options = #{middlebox_comp_mode := true}} = State0) ->
+ IsRetry = maps:get(hello_retry, PS, false),
+ case tls_handshake_1_3:do_wait_sh(Hello, State0) of
+ #alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, wait_sh, State0);
+ {State1 = #state{}, start, ServerHello} ->
+ %% hello_retry_request: go to start
+ {next_state, start, State1, [{next_event, internal, ServerHello}]};
+ {State1, wait_ee} when IsRetry == true ->
+ tls_gen_connection:next_event(wait_ee, no_record, State1);
+ {State1, wait_ee} when IsRetry == false ->
+ tls_gen_connection:next_event(hello_middlebox_assert, no_record, State1)
end;
wait_sh(info, Msg, State) ->
tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State);
wait_sh(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
+hello_middlebox_assert(enter, _, State) ->
+ {keep_state, State};
+hello_middlebox_assert(internal, #change_cipher_spec{}, State) ->
+ tls_gen_connection:next_event(wait_ee, no_record, State);
+hello_middlebox_assert(info, Msg, State) ->
+ tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State);
+hello_middlebox_assert(Type, Msg, State) ->
+ ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-wait_ee(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+hello_retry_middlebox_assert(enter, _, State) ->
+ {keep_state, State};
+hello_retry_middlebox_assert(internal, #change_cipher_spec{}, State) ->
+ tls_gen_connection:next_event(wait_sh, no_record, State);
+hello_retry_middlebox_assert(internal, #server_hello{}, State) ->
+ tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State, [postpone]);
+hello_retry_middlebox_assert(info, Msg, State) ->
+ tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State);
+hello_retry_middlebox_assert(Type, Msg, State) ->
+ ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
+
+wait_ee(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_ee(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
wait_ee(internal, #encrypted_extensions{} = EE, State0) ->
case tls_handshake_1_3:do_wait_ee(EE, State0) of
#alert{} = Alert ->
@@ -396,9 +495,12 @@ wait_ee(info, Msg, State) ->
wait_ee(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-
-wait_cert_cr(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+wait_cert_cr(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_cert_cr(internal = Type, #change_cipher_spec{} = Msg,
+ State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
wait_cert_cr(internal, #certificate_1_3{} = Certificate, State0) ->
case tls_handshake_1_3:do_wait_cert_cr(Certificate, State0) of
{#alert{} = Alert, State} ->
@@ -418,8 +520,11 @@ wait_cert_cr(info, Msg, State) ->
wait_cert_cr(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-wait_eoed(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+wait_eoed(enter, _, State0) ->
+ State = handle_middlebox(State0),
+ {next_state, ?FUNCTION_NAME, State,[]};
+wait_eoed(internal = Type, #change_cipher_spec{} = Msg, State) ->
+ handle_change_cipher_spec(Type, Msg, ?FUNCTION_NAME, State);
wait_eoed(internal, #end_of_early_data{} = EOED, State0) ->
case tls_handshake_1_3:do_wait_eoed(EOED, State0) of
{#alert{} = Alert, State} ->
@@ -432,6 +537,8 @@ wait_eoed(info, Msg, State) ->
wait_eoed(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
+connection(enter, _, State) ->
+ {keep_state, State};
connection(internal, #new_session_ticket{} = NewSessionTicket, State) ->
handle_new_session_ticket(NewSessionTicket, State),
tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
@@ -455,6 +562,8 @@ connection({call, From}, negotiated_protocol,
connection(Type, Event, State) ->
ssl_gen_statem:?FUNCTION_NAME(Type, Event, State).
+downgrade(enter, _, State) ->
+ {keep_state, State};
downgrade(internal, #new_session_ticket{} = NewSessionTicket, State) ->
_ = handle_new_session_ticket(NewSessionTicket, State),
{next_state, ?FUNCTION_NAME, State};
@@ -464,8 +573,30 @@ downgrade(Type, Event, State) ->
%--------------------------------------------------------------------
%% internal functions
%%--------------------------------------------------------------------
+
+do_server_start(ClientHello, State0) ->
+ case tls_handshake_1_3:do_start(ClientHello, State0) of
+ #alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, start, State0);
+ {State, start} ->
+ {next_state, start, State, []};
+ {State, negotiated} ->
+ {next_state, negotiated, State, [{next_event, internal, {start_handshake, undefined}}]};
+ {State, negotiated, PSK} -> %% Session Resumption with PSK
+ {next_state, negotiated, State, [{next_event, internal, {start_handshake, PSK}}]}
+ end.
+
+do_client_start(ServerHello, State0) ->
+ case tls_handshake_1_3:do_start(ServerHello, State0) of
+ #alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, start, State0);
+ {State, NextState} ->
+ {next_state, NextState, State, []}
+ end.
+
initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trackers}, User,
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
+ put(log_level, maps:get(log_level, SSLOptions)),
#{erl_dist := IsErlDist,
%% Use highest supported version for client/server random nonce generation
versions := [Version|_],
@@ -500,7 +631,7 @@ initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trac
socket_options = SocketOptions,
ssl_options = SSLOptions,
session = #session{is_resumable = false,
- session_id = ssl_session:legacy_session_id()},
+ session_id = ssl_session:legacy_session_id(SSLOptions)},
connection_states = ConnectionStates,
protocol_buffers = #protocol_buffers{},
user_data_buffer = {[],0,[]},
@@ -560,7 +691,7 @@ handle_new_session_ticket(#new_session_ticket{ticket_nonce = Nonce} = NewSession
tls_client_ticket_store:store_ticket(NewSessionTicket, {Cipher, HKDF}, SNI, PSK).
send_ticket_data(User, NewSessionTicket, CipherSuite, SNI, PSK) ->
- Timestamp = erlang:system_time(seconds),
+ Timestamp = erlang:system_time(millisecond),
TicketData = #{cipher_suite => CipherSuite,
sni => SNI,
psk => PSK,
@@ -591,3 +722,19 @@ init_max_early_data_size(client) ->
init_max_early_data_size(server) ->
ssl_config:get_max_early_data_size().
+handle_middlebox(#state{protocol_specific = PS} = State0) ->
+ %% Always be prepared to ignore one change cipher spec
+ %% for maximum interopablility, even if middlebox mode
+ %% is not enabled.
+ State0#state{protocol_specific = PS#{change_cipher_spec => ignore}}.
+
+
+handle_change_cipher_spec(Type, Msg, StateName, #state{protocol_specific = PS0} = State) ->
+ case maps:get(change_cipher_spec, PS0) of
+ ignore ->
+ PS = PS0#{change_cipher_spec => fail},
+ tls_gen_connection:next_event(StateName, no_record,
+ State#state{protocol_specific = PS});
+ fail ->
+ ssl_gen_statem:handle_common_event(Type, Msg, StateName, State)
+ end.
diff --git a/lib/ssl/src/tls_dtls_connection.erl b/lib/ssl/src/tls_dtls_connection.erl
index 9f0bf8132e..6882e8af34 100644
--- a/lib/ssl/src/tls_dtls_connection.erl
+++ b/lib/ssl/src/tls_dtls_connection.erl
@@ -56,6 +56,7 @@
user_hello/3,
abbreviated/3,
certify/3,
+ wait_cert_verify/3,
wait_ocsp_stapling/3,
cipher/3,
connection/3,
@@ -107,7 +108,7 @@ prf(ConnectionPid, Secret, Label, Seed, WantedLength) ->
handle_session(#server_hello{cipher_suite = CipherSuite,
compression_method = Compression},
Version, NewId, ConnectionStates, ProtoExt, Protocol0,
- #state{session = #session{session_id = OldId},
+ #state{session = Session,
handshake_env = #handshake_env{negotiated_protocol = CurrentProtocol} = HsEnv,
connection_env = #connection_env{negotiated_version = ReqVersion} = CEnv} = State0) ->
#{key_exchange := KeyAlgorithm} =
@@ -128,7 +129,7 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
negotiated_protocol = Protocol},
connection_env = CEnv#connection_env{negotiated_version = Version}},
- case ssl_session:is_new(OldId, NewId) of
+ case ssl_session:is_new(Session, NewId) of
true ->
handle_new_session(NewId, CipherSuite, Compression,
State#state{connection_states = ConnectionStates});
@@ -168,12 +169,14 @@ user_hello({call, From}, cancel, _State) ->
throw(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled));
user_hello({call, From}, {handshake_continue, NewOptions, Timeout},
#state{static_env = #static_env{role = Role},
- handshake_env = #handshake_env{hello = Hello},
+ handshake_env = HSEnv,
ssl_options = Options0} = State0) ->
- Options = ssl:handle_options(NewOptions, Role, Options0#{handshake => full}),
+ Options = ssl:handle_options(NewOptions, Role, Options0),
State = ssl_gen_statem:ssl_config(Options, Role, State0),
- {next_state, hello, State#state{start_or_recv_from = From},
- [{next_event, internal, Hello}, {{timeout, handshake}, Timeout, close}]};
+ {next_state, hello, State#state{start_or_recv_from = From,
+ handshake_env = HSEnv#handshake_env{continue_status = continue}
+ },
+ [{{timeout, handshake}, Timeout, close}]};
user_hello(info, {'DOWN', _, _, _, _} = Event, State) ->
ssl_gen_statem:handle_info(Event, ?FUNCTION_NAME, State);
user_hello(_, _, _) ->
@@ -316,7 +319,7 @@ certify(internal, #certificate{asn1_certificates = []},
ssl_options = #{verify := verify_peer,
fail_if_no_peer_cert := false}} =
State0) ->
- Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_requested = false});
+ Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_status = empty});
certify(internal, #certificate{},
#state{static_env = #static_env{role = server},
ssl_options = #{verify := verify_none}}) ->
@@ -338,14 +341,19 @@ certify(internal, #certificate{asn1_certificates = [Peer|_]} = Cert,
ocsp_stapling_state = #{ocsp_expect := Status} = OcspState},
connection_env = #connection_env{
negotiated_version = Version},
- ssl_options = Opts} = State) when Status =/= staple ->
+ ssl_options = Opts} = State0) when Status =/= staple ->
OcspInfo = ocsp_info(OcspState, Opts, Peer),
case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef,
Opts, CRLDbInfo, Role, Host,
ensure_tls(Version), OcspInfo) of
{PeerCert, PublicKeyInfo} ->
- handle_peer_cert(Role, PeerCert, PublicKeyInfo,
- State#state{client_certificate_requested = false}, Connection, []);
+ State = case Role of
+ server ->
+ State0#state{client_certificate_status = needs_verifying};
+ client ->
+ State0
+ end,
+ handle_peer_cert(Role, PeerCert, PublicKeyInfo, State, Connection, []);
#alert{} = Alert ->
throw(Alert)
end;
@@ -409,11 +417,11 @@ certify(internal, #certificate_request{},
#state{static_env = #static_env{role = client,
protocol_cb = Connection},
session = Session0,
- connection_env = #connection_env{cert_key_pairs = [#{certs := [[]]}]}} = State) ->
+ connection_env = #connection_env{cert_key_alts = [#{certs := [[]]}]}} = State) ->
%% The client does not have a certificate and will send an empty reply, the server may fail
%% or accept the connection by its own preference. No signature algorithms needed as there is
%% no certificate to verify.
- Connection:next_event(?FUNCTION_NAME, no_record, State#state{client_certificate_requested = true,
+ Connection:next_event(?FUNCTION_NAME, no_record, State#state{client_certificate_status = requested,
session = Session0#session{own_certificates = [[]],
private_key = #{}}});
certify(internal, #certificate_request{} = CertRequest,
@@ -422,16 +430,17 @@ certify(internal, #certificate_request{} = CertRequest,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef},
connection_env = #connection_env{negotiated_version = Version,
- cert_key_pairs = CertKeyPairs
+ cert_key_alts = CertKeyAlts
},
session = Session0,
ssl_options = #{signature_algs := SupportedHashSigns}} = State) ->
TLSVersion = ssl:tls_version(Version),
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts, ssl:tls_version(Version)),
Session = select_client_cert_key_pair(Session0, CertRequest, CertKeyPairs,
SupportedHashSigns, TLSVersion,
CertDbHandle, CertDbRef),
Connection:next_event(?FUNCTION_NAME, no_record,
- State#state{client_certificate_requested = true,
+ State#state{client_certificate_status = requested,
session = Session});
%% PSK and RSA_PSK might bypass the Server-Key-Exchange
certify(internal, #server_hello_done{},
@@ -510,7 +519,7 @@ certify(internal, #server_hello_done{},
end;
certify(internal = Type, #client_key_exchange{} = Msg,
#state{static_env = #static_env{role = server},
- client_certificate_requested = true,
+ client_certificate_status = requested,
ssl_options = #{fail_if_no_peer_cert := true}}) ->
%% We expect a certificate here
throw(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, {Type, Msg}}));
@@ -531,25 +540,22 @@ certify(Type, Event, State) ->
ssl_gen_statem:handle_common_event(Type, Event, ?FUNCTION_NAME, State).
%%--------------------------------------------------------------------
--spec cipher(gen_statem:event_type(),
- #hello_request{} | #certificate_verify{} | #finished{} | term(),
+-spec wait_cert_verify(gen_statem:event_type(),
+ #hello_request{} | #certificate_verify{} | term(),
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-cipher({call, From}, Msg, State) ->
- handle_call(Msg, From, ?FUNCTION_NAME, State);
-cipher(info, Msg, State) ->
- handle_info(Msg, ?FUNCTION_NAME, State);
-cipher(internal, #certificate_verify{signature = Signature,
- hashsign_algorithm = CertHashSign},
- #state{static_env = #static_env{role = server,
- protocol_cb = Connection},
- handshake_env = #handshake_env{tls_handshake_history = Hist,
- kex_algorithm = KexAlg,
+wait_cert_verify(internal, #certificate_verify{signature = Signature,
+ hashsign_algorithm = CertHashSign},
+ #state{static_env = #static_env{role = server,
+ protocol_cb = Connection},
+ client_certificate_status = needs_verifying,
+ handshake_env = #handshake_env{tls_handshake_history = Hist,
+ kex_algorithm = KexAlg,
public_key_info = PubKeyInfo},
- connection_env = #connection_env{negotiated_version = Version},
- session = #session{master_secret = MasterSecret} = Session0
- } = State) ->
+ connection_env = #connection_env{negotiated_version = Version},
+ session = #session{master_secret = MasterSecret} = Session0
+ } = State) ->
TLSVersion = ssl:tls_version(Version),
%% Use negotiated value if TLS-1.2 otherwise return default
@@ -557,17 +563,27 @@ cipher(internal, #certificate_verify{signature = Signature,
case ssl_handshake:certificate_verify(Signature, PubKeyInfo,
TLSVersion, HashSign, MasterSecret, Hist) of
valid ->
- Connection:next_event(?FUNCTION_NAME, no_record,
- State#state{session = Session0#session{sign_alg = HashSign}});
+ Connection:next_event(cipher, no_record,
+ State#state{client_certificate_status = verified,
+ session = Session0#session{sign_alg = HashSign}});
#alert{} = Alert ->
throw(Alert)
end;
-%% client must send a next protocol message if we are expecting it
-cipher(internal, #finished{},
- #state{static_env = #static_env{role = server},
- handshake_env = #handshake_env{expecting_next_protocol_negotiation = true,
- negotiated_protocol = undefined}}) ->
- throw(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE));
+wait_cert_verify(internal, #hello_request{}, _) ->
+ keep_state_and_data;
+wait_cert_verify(Type, Event, State) ->
+ ssl_gen_statem:handle_common_event(Type, Event, ?FUNCTION_NAME, State).
+
+%%--------------------------------------------------------------------
+-spec cipher(gen_statem:event_type(),
+ #hello_request{} | #finished{} | term(),
+ #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+cipher({call, From}, Msg, State) ->
+ handle_call(Msg, From, ?FUNCTION_NAME, State);
+cipher(info, Msg, State) ->
+ handle_info(Msg, ?FUNCTION_NAME, State);
cipher(internal, #finished{verify_data = Data} = Finished,
#state{static_env = #static_env{role = Role,
host = Host,
@@ -670,7 +686,8 @@ downgrade(Type, Event, State) ->
gen_handshake(StateName, Type, Event, State) ->
try
tls_dtls_connection:StateName(Type, Event, State)
- catch error:_ ->
+ catch error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data))
end.
@@ -702,8 +719,12 @@ handle_call({prf, Secret, Label, Seed, WantedLength}, From, _,
end, [], Seed)),
ssl_handshake:prf(ssl:tls_version(Version), PRFAlgorithm, SecretToUse, Label, SeedToUse, WantedLength)
catch
- exit:_ -> {error, badarg};
- error:Reason -> {error, Reason}
+ exit:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
+ {error, badarg};
+ error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
+ {error, Reason}
end,
{keep_state_and_data, [{reply, From, Reply}]};
handle_call(Msg, From, StateName, State) ->
@@ -731,6 +752,7 @@ do_server_hello(Type, #{next_protocol_negotiation := NextProtocols} =
ServerHello =
ssl_handshake:server_hello(SessId, ssl:tls_version(Version),
ConnectionStates1, ServerHelloExt),
+
State = server_hello(ServerHello,
State1#state{handshake_env = HsEnv#handshake_env{expecting_next_protocol_negotiation =
NextProtocols =/= undefined}}, Connection),
@@ -862,18 +884,18 @@ handle_peer_cert_key(_, _, _, _, State) ->
certify_client(#state{static_env = #static_env{role = client,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef},
- client_certificate_requested = true,
+ client_certificate_status = requested,
session = #session{own_certificates = OwnCerts}}
= State, Connection) ->
Certificate = ssl_handshake:certificate(OwnCerts, CertDbHandle, CertDbRef, client),
Connection:queue_handshake(Certificate, State);
-certify_client(#state{client_certificate_requested = false} = State, _) ->
+certify_client(#state{client_certificate_status = not_requested} = State, _) ->
State.
verify_client_cert(#state{static_env = #static_env{role = client},
handshake_env = #handshake_env{tls_handshake_history = Hist},
connection_env = #connection_env{negotiated_version = Version},
- client_certificate_requested = true,
+ client_certificate_status = requested,
session = #session{sign_alg = HashSign,
master_secret = MasterSecret,
private_key = PrivateKey,
@@ -887,13 +909,13 @@ verify_client_cert(#state{static_env = #static_env{role = client},
#alert{} = Alert ->
throw(Alert)
end;
-verify_client_cert(#state{client_certificate_requested = false} = State, _) ->
+verify_client_cert(#state{client_certificate_status = not_requested} = State, _) ->
State.
client_certify_and_key_exchange(State0, Connection) ->
State1 = do_client_certify_and_key_exchange(State0, Connection),
{State2, Actions} = finalize_handshake(State1, certify, Connection),
- State = State2#state{client_certificate_requested = false}, %% Reinitialize
+ State = State2#state{client_certificate_status = not_requested}, %% Reinitialize
Connection:next_event(cipher, no_record, State, Actions).
do_client_certify_and_key_exchange(State0, Connection) ->
@@ -908,7 +930,8 @@ server_certify_and_key_exchange(State0, Connection) ->
certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS},
#state{session = #session{private_key = PrivateKey},
- handshake_env = #handshake_env{client_hello_version = {Major, Minor} = Version}}
+ handshake_env = #handshake_env{client_hello_version = {Major, Minor} = Version},
+ client_certificate_status = CCStatus}
= State, Connection) ->
FakeSecret = make_premaster_secret(Version, rsa),
%% Countermeasure for Bleichenbacher attack always provide some kind of premaster secret
@@ -928,55 +951,74 @@ certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS
#alert{description = ?DECRYPT_ERROR} ->
FakeSecret
end,
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
#state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
- kex_keys = {_, ServerDhPrivateKey}}
+ kex_keys = {_, ServerDhPrivateKey}},
+ client_certificate_status = CCStatus
} = State,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientPublicDhKey, ServerDhPrivateKey, Params),
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientPublicEcDhPoint},
- #state{handshake_env = #handshake_env{kex_keys = ECDHKey}} = State, Connection) ->
+ #state{handshake_env = #handshake_env{kex_keys = ECDHKey},
+ client_certificate_status = CCStatus
+ } = State, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(#'ECPoint'{point = ClientPublicEcDhPoint}, ECDHKey),
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_psk_identity{} = ClientKey,
#state{ssl_options =
- #{user_lookup_fun := PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup},
+ client_certificate_status = CCStatus
+ } = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PSKLookup),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
#state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
kex_keys = {_, ServerDhPrivateKey}},
ssl_options =
- #{user_lookup_fun := PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup},
+ client_certificate_status = CCStatus
+ } = State0,
Connection) ->
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerDhPrivateKey, Params, PSKLookup),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
#state{handshake_env = #handshake_env{kex_keys = ServerEcDhPrivateKey},
ssl_options =
- #{user_lookup_fun := PSKLookup}} = State,
+ #{user_lookup_fun := PSKLookup},
+ client_certificate_status = CCStatus
+ } = State,
Connection) ->
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerEcDhPrivateKey, PSKLookup),
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey,
#state{session = #session{private_key = PrivateKey},
ssl_options =
- #{user_lookup_fun := PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup},
+ client_certificate_status = CCStatus
+ } = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PrivateKey, PSKLookup),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_srp_public{} = ClientKey,
#state{handshake_env = #handshake_env{srp_params = Params,
- kex_keys = Key}
+ kex_keys = Key},
+ client_certificate_status = CCStatus
} = State0, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, Params),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher).
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus)).
+
+client_kex_next_state(needs_verifying) ->
+ wait_cert_verify;
+client_kex_next_state(empty) ->
+ cipher;
+client_kex_next_state(not_requested) ->
+ cipher.
certify_server(#state{handshake_env = #handshake_env{kex_algorithm = KexAlg}} =
State, _) when KexAlg == dh_anon;
@@ -1285,15 +1327,15 @@ request_client_cert(#state{handshake_env = #handshake_env{kex_algorithm = Alg}}
request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle,
cert_db_ref = CertDbRef},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = #{verify := verify_peer,
- signature_algs := SupportedHashSigns}} = State0, Connection) ->
+ ssl_options = #{verify := verify_peer} = Opts} = State0, Connection) ->
+ SupportedHashSigns = maps:get(signature_algs, Opts, undefined),
TLSVersion = ssl:tls_version(Version),
HashSigns = ssl_handshake:available_signature_algs(SupportedHashSigns,
TLSVersion),
Msg = ssl_handshake:certificate_request(CertDbHandle, CertDbRef,
HashSigns, TLSVersion),
State = Connection:queue_handshake(Msg, State0),
- State#state{client_certificate_requested = true};
+ State#state{client_certificate_status = requested};
request_client_cert(#state{ssl_options = #{verify := verify_none}} =
State, _) ->
@@ -1447,22 +1489,20 @@ generate_srp_server_keys(_SrpParams, 10) ->
generate_srp_server_keys(SrpParams =
#srp_user{generator = Generator, prime = Prime,
verifier = Verifier}, N) ->
- try crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
- Keys ->
- Keys
+ try crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']})
catch
- error:_ ->
+ error:Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{error, Reason}, {stacktrace, ST}]),
generate_srp_server_keys(SrpParams, N+1)
end.
generate_srp_client_keys(_Generator, _Prime, 10) ->
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
generate_srp_client_keys(Generator, Prime, N) ->
- try crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
- Keys ->
- Keys
+ try crypto:generate_key(srp, {user, [Generator, Prime, '6a']})
catch
- error:_ ->
+ error:Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{error, Reason}, {stacktrace, ST}]),
generate_srp_client_keys(Generator, Prime, N+1)
end.
@@ -1651,7 +1691,7 @@ select_client_cert_key_pair(Session0, CertRequest, CertKeyPairs, SupportedHashSi
select_client_cert_key_pair(Session0, CertRequest, CertKeyPairs, SupportedHashSigns, TLSVersion, CertDbHandle, CertDbRef, undefined).
select_client_cert_key_pair(Session0,_,[], _, _,_,_, undefined) ->
- %% No certificate compliant with signing algorithms found: empty certificate will be sent
+ %% No certificate compliant with supported algorithms: empty certificate will be sent
Session0#session{own_certificates = [[]],
private_key = #{}};
select_client_cert_key_pair(_,_,[], _, _,_,_,#session{}=Session) ->
@@ -1661,7 +1701,7 @@ select_client_cert_key_pair(Session0, #certificate_request{certificate_authoriti
[#{private_key := PrivateKey, certs := [Cert| _] = Certs} | Rest],
SupportedHashSigns, TLSVersion, CertDbHandle, CertDbRef, Default) ->
case ssl_handshake:select_hashsign(CertRequest, Cert, SupportedHashSigns, TLSVersion) of
- #alert {} ->
+ #alert{} ->
select_client_cert_key_pair(Session0, CertRequest, Rest, SupportedHashSigns, TLSVersion, CertDbHandle, CertDbRef, Default);
SelectedHashSign ->
case ssl_certificate:handle_cert_auths(Certs, CertAuths, CertDbHandle, CertDbRef) of
diff --git a/lib/ssl/src/tls_gen_connection.erl b/lib/ssl/src/tls_gen_connection.erl
index cff0abdcb3..940666f104 100644
--- a/lib/ssl/src/tls_gen_connection.erl
+++ b/lib/ssl/src/tls_gen_connection.erl
@@ -70,42 +70,70 @@
close/4,
protocol_name/0]).
--define(DIST_CNTRL_SPAWN_OPTS, [{priority, max}]).
-
%%====================================================================
%% Internal application API
-%%====================================================================
+%%====================================================================
%%====================================================================
%% Setup
%%====================================================================
-start_fsm(Role, Host, Port, Socket, {#{erl_dist := false},_, Trackers} = Opts,
- User, {CbModule, _,_, _, _} = CbInfo,
- Timeout) ->
- try
- {ok, DynSup} = tls_connection_sup:start_child([]),
- {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, []),
- {ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, [Role, Sender, Host, Port, Socket,
- Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_gen_statem:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Trackers),
- ssl_gen_statem:handshake(SslSocket, Timeout)
- catch
- error:{badmatch, {error, _} = Error} ->
- Error
- end;
+start_fsm(Role, Host, Port, Socket,
+ {#{erl_dist := ErlDist, sender_spawn_opts := SenderSpawnOpts}, _, Trackers} = Opts,
+ User, {CbModule, _, _, _, _} = CbInfo,
+ Timeout) ->
+ SenderOptions = handle_sender_options(ErlDist, SenderSpawnOpts),
+ Starter = start_connection_tree(User, ErlDist, SenderOptions,
+ Role, [Host, Port, Socket, Opts, User, CbInfo]),
+ receive
+ {Starter, SockReceiver, SockSender} ->
+ socket_control(Socket, SockReceiver, SockSender, CbModule, Trackers, Timeout);
+ {Starter, Error} ->
+ Error
+ end.
-start_fsm(Role, Host, Port, Socket, {#{erl_dist := true},_, Trackers} = Opts,
- User, {CbModule, _,_, _, _} = CbInfo,
- Timeout) ->
- try
- {ok, DynSup} = tls_connection_sup:start_child_dist([]),
- {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, [[{spawn_opt, ?DIST_CNTRL_SPAWN_OPTS}]]),
- {ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, [Role, Sender, Host, Port, Socket,
- Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_gen_statem:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Trackers),
- ssl_gen_statem:handshake(SslSocket, Timeout)
- catch
- error:{badmatch, {error, _} = Error} ->
- Error
+handle_sender_options(ErlDist, SpawnOpts) ->
+ case ErlDist of
+ true ->
+ [[{spawn_opt, [{priority, max} | proplists:delete(priority, SpawnOpts)]}]];
+ false ->
+ [[{spawn_opt, SpawnOpts}]]
+ end.
+
+start_connection_tree(User, IsErlDist, SenderOpts, Role, ReceiverOpts) ->
+ StartConnectionTree =
+ fun() ->
+ case start_dyn_connection_sup(IsErlDist) of
+ {ok, DynSup} ->
+ case tls_dyn_connection_sup:start_child(DynSup, sender, SenderOpts) of
+ {ok, Sender} ->
+ case tls_dyn_connection_sup:start_child(DynSup, receiver,
+ [Role, Sender | ReceiverOpts]) of
+ {ok, Receiver} ->
+ User ! {self(), Receiver, Sender};
+ {error, Error} ->
+ User ! {self(), Error},
+ exit(DynSup, shutdown)
+ end;
+ {error, Error} ->
+ User ! {self(), Error},
+ exit(DynSup, shutdown)
+ end;
+ {error, Error} ->
+ User ! {self(), Error}
+ end
+ end,
+ spawn(StartConnectionTree).
+
+start_dyn_connection_sup(true) ->
+ tls_connection_sup:start_child_dist([]);
+start_dyn_connection_sup(false) ->
+ tls_connection_sup:start_child([]).
+
+socket_control(Socket, SockReceiver, SockSender, CbModule, Trackers, Timeout) ->
+ case ssl_gen_statem:socket_control(?MODULE, Socket, [SockReceiver, SockSender], CbModule, Trackers) of
+ {ok, SslSocket} ->
+ ssl_gen_statem:handshake(SslSocket, Timeout);
+ Error ->
+ Error
end.
pids(#state{protocol_specific = #{sender := Sender}}) ->
@@ -118,24 +146,26 @@ initialize_tls_sender(#state{static_env = #static_env{
trackers = Trackers
},
connection_env = #connection_env{negotiated_version = Version},
- socket_options = SockOpts,
+ socket_options = SockOpts,
ssl_options = #{renegotiate_at := RenegotiateAt,
key_update_at := KeyUpdateAt,
erl_dist := ErlDist,
- log_level := LogLevel},
+ log_level := LogLevel,
+ hibernate_after := HibernateAfter},
connection_states = #{current_write := ConnectionWriteState},
protocol_specific = #{sender := Sender}}) ->
Init = #{current_write => ConnectionWriteState,
role => Role,
socket => Socket,
socket_options => SockOpts,
- erl_dist => ErlDist,
+ erl_dist => ErlDist,
trackers => Trackers,
transport_cb => Transport,
negotiated_version => Version,
renegotiate_at => RenegotiateAt,
key_update_at => KeyUpdateAt,
- log_level => LogLevel},
+ log_level => LogLevel,
+ hibernate_after => HibernateAfter},
tls_sender:initialize(Sender, Init).
%%====================================================================
@@ -355,16 +385,28 @@ handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA}, StateName,
} = State) when StateName == initial_hello;
StateName == hello;
StateName == certify;
+ StateName == wait_cert_verify;
+ StateName == wait_ocsp_stapling;
StateName == abbreviated;
StateName == cipher
->
%% Application data can not be sent before initial handshake pre TLS-1.3.
Alert = ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE, application_data_before_initial_handshake),
ssl_gen_statem:handle_own_alert(Alert, StateName, State);
-handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA}, start = StateName,
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, early_data = false}, StateName,
#state{static_env = #static_env{role = server}
- } = State) ->
- Alert = ?ALERT_REC(?FATAL, ?DECODE_ERROR, invalid_tls_13_message),
+ } = State) when StateName == start;
+ StateName == recvd_ch;
+ StateName == negotiated;
+ StateName == wait_eoed ->
+ Alert = ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE, none_early_application_data_before_handshake),
+ ssl_gen_statem:handle_own_alert(Alert, StateName, State);
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA}, StateName,
+ #state{static_env = #static_env{role = server}
+ } = State) when StateName == wait_cert;
+ StateName == wait_cv;
+ StateName == wait_finished->
+ Alert = ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE, application_data_before_handshake_or_intervened_in_post_handshake_auth),
ssl_gen_statem:handle_own_alert(Alert, StateName, State);
handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName,
#state{start_or_recv_from = From,
@@ -389,26 +431,17 @@ handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, Stat
next_event(StateName, Record, State)
end;
%%% TLS record protocol level handshake messages
-handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data},
- StateName, #state{protocol_buffers =
- #protocol_buffers{tls_handshake_buffer = Buf0} = Buffers,
- connection_env = #connection_env{negotiated_version = Version},
- static_env = #static_env{role = Role},
- ssl_options = Options} = State0) ->
+handle_protocol_record(#ssl_tls{type = ?HANDSHAKE, fragment = Data}, StateName,
+ #state{ssl_options = Options, protocol_buffers = Buffers} = State0) ->
try
- %% Calculate the effective version that should be used when decoding an incoming handshake
- %% message.
- EffectiveVersion = effective_version(Version, Options, Role, StateName),
- {Packets, Buf} = tls_handshake:get_tls_handshake(EffectiveVersion,Data,Buf0, Options),
- State =
- State0#state{protocol_buffers =
- Buffers#protocol_buffers{tls_handshake_buffer = Buf}},
- case Packets of
+ {HSPackets, NewHSBuffer, RecordRest} = get_tls_handshakes(Data, StateName, State0),
+ State = State0#state{protocol_buffers = Buffers#protocol_buffers{tls_handshake_buffer = NewHSBuffer}},
+ case HSPackets of
[] ->
- assert_buffer_sanity(Buf, Options),
+ assert_buffer_sanity(NewHSBuffer, Options),
next_event(StateName, no_record, State);
_ ->
- Events = tls_handshake_events(Packets),
+ Events = tls_handshake_events(HSPackets, RecordRest),
case StateName of
connection ->
ssl_gen_statem:hibernate_after(StateName, State, Events);
@@ -437,7 +470,8 @@ handle_protocol_record(#ssl_tls{type = ?ALERT, fragment = EncAlerts}, StateName,
#alert{} = Alert ->
ssl_gen_statem:handle_own_alert(Alert, StateName, State)
catch
- _:_ ->
+ _:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{error, Reason}, {stacktrace, ST}]),
ssl_gen_statem:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, alert_decode_error),
StateName, State)
@@ -494,7 +528,8 @@ send_sync_alert(
Alert, #state{protocol_specific = #{sender := Sender}} = State) ->
try tls_sender:send_and_ack_alert(Sender, Alert)
catch
- _:_ ->
+ _:Reason:ST ->
+ ?SSL_LOG(info, "Send failed", [{error, Reason}, {stacktrace, ST}]),
throw({stop, {shutdown, own_alert}, State})
end.
@@ -528,10 +563,30 @@ protocol_name() ->
%%====================================================================
%% Internal functions
%%====================================================================
-tls_handshake_events(Packets) ->
- lists:map(fun(Packet) ->
- {next_event, internal, {handshake, Packet}}
- end, Packets).
+get_tls_handshakes(Data, StateName, #state{protocol_buffers = #protocol_buffers{tls_handshake_buffer = HSBuffer},
+ connection_env = #connection_env{negotiated_version = Version},
+ static_env = #static_env{role = Role},
+ ssl_options = Options}) ->
+ case handle_unnegotiated_version(Version, Options, Data, HSBuffer, Role, StateName) of
+ {HSPackets, NewHSBuffer} ->
+ %% Common case
+ NoRecordRest = <<>>,
+ {HSPackets, NewHSBuffer, NoRecordRest};
+ {_Packets, _HSBuffer, _RecordRest} = Result ->
+ %% Possible coalesced TLS record data from pre TLS-1.3 server
+ Result
+ end.
+
+tls_handshake_events(HSPackets, <<>>) ->
+ lists:map(fun(HSPacket) ->
+ {next_event, internal, {handshake, HSPacket}}
+ end, HSPackets);
+
+tls_handshake_events(HSPackets, RecordRest) ->
+ %% Coalesced TLS record data to be handled after first handshake message has been handled
+ RestEvent = {next_event, internal, {protocol_record, #ssl_tls{type = ?HANDSHAKE, fragment = RecordRest}}},
+ FirstHS = tls_handshake_events(HSPackets, <<>>),
+ FirstHS ++ [RestEvent].
unprocessed_events(Events) ->
%% The first handshake event will be processed immediately
@@ -675,32 +730,29 @@ activate_socket(#state{protocol_specific = #{active_n_toggle := true, active_n :
%% Decipher next record and concatenate consecutive ?APPLICATION_DATA records into one
%%
next_record(State, CipherTexts, ConnectionStates, Check) ->
- next_record(State, CipherTexts, ConnectionStates, Check, []).
+ next_record(State, CipherTexts, ConnectionStates, Check, [], false).
%%
next_record(#state{connection_env = #connection_env{negotiated_version = {3,4} = Version}} = State,
- [CT|CipherTexts], ConnectionStates0, Check, Acc) ->
+ [CT|CipherTexts], ConnectionStates0, Check, Acc, IsEarlyData) ->
case tls_record:decode_cipher_text(Version, CT, ConnectionStates0, Check) of
- {#ssl_tls{type = ?APPLICATION_DATA, fragment = Fragment}, ConnectionStates} ->
+ {Record = #ssl_tls{type = ?APPLICATION_DATA, fragment = Fragment}, ConnectionStates} ->
case CipherTexts of
[] ->
%% End of cipher texts - build and deliver an ?APPLICATION_DATA record
%% from the accumulated fragments
next_record_done(State, [], ConnectionStates,
- #ssl_tls{type = ?APPLICATION_DATA,
- fragment = iolist_to_binary(lists:reverse(Acc, [Fragment]))});
+ Record#ssl_tls{type = ?APPLICATION_DATA,
+ fragment = iolist_to_binary(lists:reverse(Acc, [Fragment]))});
[_|_] ->
- next_record(State, CipherTexts, ConnectionStates, Check, [Fragment|Acc])
+ next_record(State, CipherTexts, ConnectionStates, Check, [Fragment|Acc], Record#ssl_tls.early_data)
end;
- {trial_decryption_failed, ConnectionStates} ->
+ {no_record, ConnectionStates} ->
case CipherTexts of
[] ->
- %% End of cipher texts - build and deliver an ?APPLICATION_DATA record
- %% from the accumulated fragments
- next_record_done(State, [], ConnectionStates,
- #ssl_tls{type = ?APPLICATION_DATA,
- fragment = iolist_to_binary(lists:reverse(Acc))});
+ Record = accumulated_app_record(Acc, IsEarlyData),
+ next_record_done(State, [], ConnectionStates, Record);
[_|_] ->
- next_record(State, CipherTexts, ConnectionStates, Check, Acc)
+ next_record(State, CipherTexts, ConnectionStates, Check, Acc, IsEarlyData)
end;
{Record, ConnectionStates} when Acc =:= [] ->
%% Singleton non-?APPLICATION_DATA record - deliver
@@ -711,33 +763,36 @@ next_record(#state{connection_env = #connection_env{negotiated_version = {3,4} =
%% and forget about decrypting this record - we'll decrypt it again next time
%% Will not work for stream ciphers
next_record_done(State, [CT|CipherTexts], ConnectionStates0,
- #ssl_tls{type = ?APPLICATION_DATA, fragment = iolist_to_binary(lists:reverse(Acc))});
+ #ssl_tls{type = ?APPLICATION_DATA,
+ early_data = IsEarlyData,
+ fragment = iolist_to_binary(lists:reverse(Acc))});
#alert{} = Alert ->
Alert
end;
next_record(#state{connection_env = #connection_env{negotiated_version = Version}} = State,
- [#ssl_tls{type = ?APPLICATION_DATA} = CT |CipherTexts], ConnectionStates0, Check, Acc) ->
+ [#ssl_tls{type = ?APPLICATION_DATA} = CT |CipherTexts], ConnectionStates0, Check, Acc, NotRelevant) ->
case tls_record:decode_cipher_text(Version, CT, ConnectionStates0, Check) of
- {#ssl_tls{type = ?APPLICATION_DATA, fragment = Fragment}, ConnectionStates} ->
+ {Record = #ssl_tls{type = ?APPLICATION_DATA, fragment = Fragment}, ConnectionStates} ->
case CipherTexts of
[] ->
%% End of cipher texts - build and deliver an ?APPLICATION_DATA record
%% from the accumulated fragments
next_record_done(State, [], ConnectionStates,
- #ssl_tls{type = ?APPLICATION_DATA,
- fragment = iolist_to_binary(lists:reverse(Acc, [Fragment]))});
+ Record#ssl_tls{type = ?APPLICATION_DATA,
+ fragment = iolist_to_binary(lists:reverse(Acc, [Fragment]))});
[_|_] ->
- next_record(State, CipherTexts, ConnectionStates, Check, [Fragment|Acc])
+ next_record(State, CipherTexts, ConnectionStates, Check, [Fragment|Acc], NotRelevant)
end;
#alert{} = Alert ->
Alert
end;
-next_record(State, CipherTexts, ConnectionStates, _, [_|_] = Acc) ->
+next_record(State, CipherTexts, ConnectionStates, _, [_|_] = Acc, IsEarlyData) ->
next_record_done(State, CipherTexts, ConnectionStates,
#ssl_tls{type = ?APPLICATION_DATA,
+ early_data = IsEarlyData,
fragment = iolist_to_binary(lists:reverse(Acc))});
next_record(#state{connection_env = #connection_env{negotiated_version = Version}} = State,
- [CT|CipherTexts], ConnectionStates0, Check, []) ->
+ [CT|CipherTexts], ConnectionStates0, Check, [], _) ->
case tls_record:decode_cipher_text(Version, CT, ConnectionStates0, Check) of
{Record, ConnectionStates} ->
%% Singleton non-?APPLICATION_DATA record - deliver
@@ -746,6 +801,13 @@ next_record(#state{connection_env = #connection_env{negotiated_version = Version
Alert
end.
+accumulated_app_record([], _) ->
+ no_record;
+accumulated_app_record([_|_] = Acc, IsEarlyData) ->
+ #ssl_tls{type = ?APPLICATION_DATA,
+ early_data = IsEarlyData,
+ fragment = iolist_to_binary(lists:reverse(Acc))}.
+
next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, ConnectionStates, Record) ->
{Record,
State#state{protocol_buffers = Buffers#protocol_buffers{tls_cipher_texts = CipherTexts},
@@ -755,21 +817,27 @@ next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, Connec
%% Pre TLS-1.3, on the client side, the connection state variable `negotiated_version` will initially be
%% the requested version. On the server side the same variable is initially undefined.
%% When the client can support TLS-1.3 and one or more prior versions and we are waiting
-%% for the server hello (with or without a RetryRequest, that is in state hello or in state wait_sh),
-%% the "initial requested version" kept in the connection state variable `negotiated_version`
+%% for the server hello the "initial requested version" kept in the connection state variable `negotiated_version`
%% (before the versions is actually negotiated) will always be the value of TLS-1.2 (which is a legacy
%% field in TLS-1.3 client hello). The versions are instead negotiated with an hello extension. When
%% decoding the server_hello messages we want to go through TLS-1.3 decode functions to be able
%% to handle TLS-1.3 extensions if TLS-1.3 will be the negotiated version.
-effective_version({3,3} , #{versions := [{3,4} = Version |_]}, client, StateName) when StateName == hello;
- StateName == wait_sh ->
- Version;
+handle_unnegotiated_version({3,3} , #{versions := [{3,4} = Version |_]} = Options, Data, Buffer, client, hello) ->
+ %% The effective version for decoding the server hello message should be the TLS-1.3. Possible coalesced TLS-1.2
+ %% server handshake messages should be decoded with the negotiated version in later state.
+ <<_:8, ?UINT24(Length), _/binary>> = Data,
+ <<FirstPacket:(Length+4)/binary, RecordRest/binary>> = Data,
+ {HSPacket, <<>> = NewHsBuffer} = tls_handshake:get_tls_handshakes(Version, FirstPacket, Buffer, Options),
+ {HSPacket, NewHsBuffer, RecordRest};
+%% TLS-1.3 RetryRequest
+handle_unnegotiated_version({3,3} , #{versions := [{3,4} = Version |_]} = Options, Data, Buffer, client, wait_sh) ->
+ tls_handshake:get_tls_handshakes(Version, Data, Buffer, Options);
%% When the `negotiated_version` variable is not yet set use the highest supported version.
-effective_version(undefined, #{versions := [Version|_]}, _, _) ->
- Version;
+handle_unnegotiated_version(undefined, #{versions := [Version|_]} = Options, Data, Buff, _, _) ->
+ tls_handshake:get_tls_handshakes(Version, Data, Buff, Options);
%% In all other cases use the version saved in the connection state variable `negotiated_version`
-effective_version(Version, _, _, _) ->
- Version.
+handle_unnegotiated_version(Version, Options, Data, Buff, _, _) ->
+ tls_handshake:get_tls_handshakes(Version, Data, Buff, Options).
assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>,
#{max_handshake_size := Max}) when
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 7a3d9712aa..7704ff7b6b 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -42,7 +42,7 @@
-export([encode_handshake/2]).
%% Handshake decoding
--export([get_tls_handshake/4, decode_handshake/3]).
+-export([get_tls_handshakes/4, decode_handshake/3]).
%% Handshake helper
-export([ocsp_nonce/2]).
@@ -245,7 +245,8 @@ hello(#client_hello{client_version = _ClientVersion,
Version = ssl_handshake:select_supported_version(ClientVersions, Versions),
do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation)
catch
- error:_ ->
+ error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{reason,Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data))
end;
@@ -260,7 +261,8 @@ hello(#client_hello{client_version = ClientVersion,
error:{case_clause,{asn1, Asn1Reason}} ->
%% ASN-1 decode of certificate somehow failed
throw(?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {failed_to_decode_own_certificate, Asn1Reason}));
- error:_ ->
+ error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{reason,Reason}, {stacktrace, ST}]),
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data))
end.
@@ -285,7 +287,7 @@ encode_handshake(Package, Version) ->
%%--------------------------------------------------------------------
%%--------------------------------------------------------------------
--spec get_tls_handshake(tls_record:tls_version(), binary(), binary() | iolist(),
+-spec get_tls_handshakes(tls_record:tls_version(), binary(), binary() | iolist(),
ssl_options()) ->
{[{tls_handshake(), binary()}], binary()}.
%%
@@ -293,10 +295,10 @@ encode_handshake(Package, Version) ->
%% and returns it as a list of handshake messages, also returns leftover
%% data.
%%--------------------------------------------------------------------
-get_tls_handshake(Version, Data, <<>>, Options) ->
- get_tls_handshake_aux(Version, Data, Options, []);
-get_tls_handshake(Version, Data, Buffer, Options) ->
- get_tls_handshake_aux(Version, list_to_binary([Buffer, Data]), Options, []).
+get_tls_handshakes(Version, Data, <<>>, Options) ->
+ get_tls_handshakes_aux(Version, Data, Options, []);
+get_tls_handshakes(Version, Data, Buffer, Options) ->
+ get_tls_handshakes_aux(Version, list_to_binary([Buffer, Data]), Options, []).
%%--------------------------------------------------------------------
%%% Handshake helper
@@ -330,8 +332,8 @@ handle_client_hello(Version,
true ->
SupportedHashSigns = maps:get(signature_algs, SslOpts, undefined),
Curves = maps:get(elliptic_curves, HelloExt, undefined),
- ClientHashSigns = maps:get(signature_algs, HelloExt, undefined),
- ClientSignatureSchemes = maps:get(signature_algs_cert, HelloExt, undefined),
+ ClientHashSigns = get_signature_ext(signature_algs, HelloExt, Version),
+ ClientSignatureSchemes = get_signature_ext(signature_algs_cert, HelloExt, Version),
AvailableHashSigns = ssl_handshake:available_signature_algs(
ClientHashSigns, SupportedHashSigns, Version),
ECCCurve = ssl_handshake:select_curve(Curves, SupportedECCs, Version, ECCOrder),
@@ -357,7 +359,7 @@ handle_client_hello(Version,
CipherSuites, HelloExt,
SslOpts, Session1,
ConnectionStates0,
- Renegotiation, HashSign)
+ Renegotiation, HashSign)
end
end;
false ->
@@ -426,19 +428,20 @@ enc_handshake(HandshakeMsg, Version) ->
ssl_handshake:encode_handshake(HandshakeMsg, Version).
%%--------------------------------------------------------------------
-get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
+get_tls_handshakes_aux(Version, <<?BYTE(Type), ?UINT24(Length),
Body:Length/binary,Rest/binary>>,
#{log_level := LogLevel} = Opts, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
try decode_handshake(Version, Type, Body) of
Handshake ->
ssl_logger:debug(LogLevel, inbound, 'handshake', Handshake),
- get_tls_handshake_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
+ get_tls_handshakes_aux(Version, Rest, Opts, [{Handshake,Raw} | Acc])
catch
- error:_ ->
- throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, handshake_decode_error))
+ error:Reason:ST ->
+ ?SSL_LOG(info, handshake_error, [{reason,Reason}, {stacktrace, ST}]),
+ throw(?ALERT_REC(?FATAL, ?DECODE_ERROR, handshake_decode_error))
end;
-get_tls_handshake_aux(_Version, Data, _, Acc) ->
+get_tls_handshakes_aux(_Version, Data, _, Acc) ->
{lists:reverse(Acc), Data}.
decode_handshake({3, N}, ?HELLO_REQUEST, <<>>) when N < 4 ->
@@ -470,3 +473,22 @@ ocsp_expect(true) ->
staple;
ocsp_expect(_) ->
no_staple.
+
+get_signature_ext(Ext, HelloExt, {3,3}) ->
+ case maps:get(Ext, HelloExt, undefined) of
+ %% Signature algorithms was not sent
+ undefined ->
+ undefined;
+ %% Can happen when connection is upgraded and sni_fun changes
+ %% the versions option from default
+ #signature_algorithms{signature_scheme_list = Schemes} ->
+ #hash_sign_algos{hash_sign_algos = ssl_cipher:signature_schemes_1_2(Schemes)};
+ #signature_algorithms_cert{} = Algos ->
+ Algos;
+ #hash_sign_algos{} = Algos ->
+ Algos
+ end;
+get_signature_ext(Ext, HelloExt, _) ->
+ maps:get(Ext, HelloExt, undefined).
+
+
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 84ee036a46..750a79887f 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,8 +58,7 @@
maybe_add_binders/4,
maybe_add_early_data_indication/3,
maybe_automatic_session_resumption/1,
- maybe_send_early_data/1,
- update_current_read/3]).
+ maybe_send_early_data/1]).
-export([get_max_early_data/1,
is_valid_binder/4,
@@ -205,18 +204,23 @@ encrypted_extensions(#state{handshake_env = HandshakeEnv}) ->
}.
-certificate_request(SignAlgs0, SignAlgsCert0, CertDbHandle, CertDbRef) ->
+certificate_request(SignAlgs0, SignAlgsCert0, CertDbHandle, CertDbRef, CertAuthBool) ->
%% Input arguments contain TLS 1.2 algorithms due to backward compatibility
%% reasons. These {Hash, Algo} tuples must be filtered before creating the
%% the extensions.
SignAlgs = filter_tls13_algs(SignAlgs0),
SignAlgsCert = filter_tls13_algs(SignAlgsCert0),
Extensions0 = add_signature_algorithms(#{}, SignAlgs),
- Extensions = add_signature_algorithms_cert(Extensions0, SignAlgsCert),
- Auths = ssl_handshake:certificate_authorities(CertDbHandle, CertDbRef),
+ Extensions1 = add_signature_algorithms_cert(Extensions0, SignAlgsCert),
+ Extensions = if CertAuthBool =:= true ->
+ Auths = ssl_handshake:certificate_authorities(CertDbHandle, CertDbRef),
+ Extensions1#{certificate_authorities => #certificate_authorities{authorities = Auths}};
+ true ->
+ Extensions1
+ end,
#certificate_request_1_3{
certificate_request_context = <<>>,
- extensions = Extensions#{certificate_authorities => #certificate_authorities{authorities = Auths}}}.
+ extensions = Extensions}.
add_signature_algorithms(Extensions, SignAlgs) ->
@@ -587,21 +591,21 @@ certificate_entry(DER) ->
%% 0101010101010101010101010101010101010101010101010101010101010101
sign(THash, Context, HashAlgo, PrivateKey, SignAlgo) ->
Content = build_content(Context, THash),
- try ssl_handshake:digitally_signed({3,4}, Content, HashAlgo, PrivateKey, SignAlgo) of
- Signature ->
- {ok, Signature}
- catch
- error:badarg ->
- {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, badarg)}
+ try
+ {ok, ssl_handshake:digitally_signed({3,4}, Content, HashAlgo, PrivateKey, SignAlgo)}
+ catch throw:Alert ->
+ {error, Alert}
end.
+
verify(THash, Context, HashAlgo, SignAlgo, Signature, PublicKeyInfo) ->
Content = build_content(Context, THash),
try ssl_handshake:verify_signature({3, 4}, Content, {HashAlgo, SignAlgo}, Signature, PublicKeyInfo) of
Result ->
{ok, Result}
catch
- error:badarg ->
+ error:Reason:ST ->
+ ?SSL_LOG(debug, handshake_error, [{reason, Reason}, {stacktrace, ST}]),
{error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, badarg)}
end.
@@ -646,13 +650,13 @@ do_start(#client_hello{cipher_suites = ClientCiphers,
maps:get(signature_algs, Extensions, undefined)),
ClientSignAlgsCert = get_signature_scheme_list(
maps:get(signature_algs_cert, Extensions, undefined)),
- CertAuths = get_certificate_authorites(maps:get(certificate_authorities, Extensions, undefined)),
+ CertAuths = get_certificate_authorities(maps:get(certificate_authorities, Extensions, undefined)),
CookieExt = maps:get(cookie, Extensions, undefined),
Cookie = get_cookie(CookieExt),
#state{connection_states = ConnectionStates0,
session = Session0,
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs}} = State1 =
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts}} = State1 =
Maybe(ssl_gen_statem:handle_sni_extension(SNI, State0)),
Maybe(validate_cookie(Cookie, State1)),
@@ -667,6 +671,7 @@ do_start(#client_hello{cipher_suites = ClientCiphers,
Cipher = Maybe(select_cipher_suite(HonorCipherOrder, ClientCiphers, ServerCiphers)),
Groups = Maybe(select_common_groups(ServerGroups, ClientGroups)),
Maybe(validate_client_key_share(ClientGroups, ClientShares)),
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts, {3,4}),
#session{own_certificates = [Cert|_]} = Session =
Maybe(select_server_cert_key_pair(Session0, CertKeyPairs, ClientSignAlgs,
ClientSignAlgsCert, CertAuths, State0,
@@ -746,6 +751,7 @@ do_start(#server_hello{cipher_suite = SelectedCipherSuite,
handshake_env = #handshake_env{renegotiation = {Renegotiation, _},
ocsp_stapling_state = OcspState},
connection_env = #connection_env{negotiated_version = NegotiatedVersion},
+ protocol_specific = PS,
ssl_options = #{ciphers := ClientCiphers,
supported_groups := ClientGroups0,
use_ticket := UseTicket,
@@ -819,8 +825,17 @@ do_start(#server_hello{cipher_suite = SelectedCipherSuite,
handshake_env = HsEnv#handshake_env{tls_handshake_history = HHistory},
key_share = ClientKeyShare},
- {State, wait_sh}
-
+ %% If it is a hello_retry and middlebox mode is
+ %% used assert the change_cipher_spec message
+ %% that the server should send next
+ case (maps:get(hello_retry, PS, false)) andalso
+ (maps:get(middlebox_comp_mode, SslOpts, true))
+ of
+ true ->
+ {State, hello_retry_middlebox_assert};
+ false ->
+ {State, wait_sh}
+ end
catch
{Ref, #alert{} = Alert} ->
Alert
@@ -864,11 +879,11 @@ do_negotiated({start_handshake, PSK0},
ssl_record:step_encryption_state_write(State3);
false ->
%% Read state is overwritten when handshake secrets are set.
- %% Trial_decryption and early_data_limit must be set here!
+ %% Trial_decryption and early_data_accepted must be set here!
update_current_read(
ssl_record:step_encryption_state(State3),
true, %% trial_decryption
- false %% early data limit
+ false %% early_data_accepted
)
end,
@@ -902,7 +917,8 @@ do_negotiated({start_handshake, PSK0},
catch
{Ref, #alert{} = Alert} ->
Alert;
- error:badarg ->
+ error:badarg=Reason:ST ->
+ ?SSL_LOG(debug, crypto_error, [{reason, Reason}, {stacktrace, ST}]),
?ALERT_REC(?ILLEGAL_PARAMETER, illegal_parameter_to_compute_key)
end.
@@ -1128,8 +1144,9 @@ do_wait_eoed(#end_of_early_data{}, State0) ->
%% Upon receiving a message with type server_hello, implementations MUST
%% first examine the Random value and, if it matches this value, process
%% it as described in Section 4.1.4).
-maybe_hello_retry_request(#server_hello{random = ?HELLO_RETRY_REQUEST_RANDOM} = ServerHello, State0) ->
- {error, {State0, start, ServerHello}};
+maybe_hello_retry_request(#server_hello{random = ?HELLO_RETRY_REQUEST_RANDOM} = ServerHello,
+ #state{protocol_specific = PS} = State0) ->
+ {error, {State0#state{protocol_specific = PS#{hello_retry => true}}, start, ServerHello}};
maybe_hello_retry_request(_, _) ->
ok.
@@ -1180,11 +1197,10 @@ maybe_queue_change_cipher_spec(#state{flight_buffer = FlightBuffer0} = State0, l
%% first ClientHello.
%% @end
maybe_prepend_change_cipher_spec(#state{
- ssl_options =
- #{middlebox_comp_mode := true},
+ session = #session{session_id = Id},
handshake_env =
#handshake_env{
- change_cipher_spec_sent = false} = HSEnv} = State, Bin) ->
+ change_cipher_spec_sent = false} = HSEnv} = State, Bin) when Id =/= ?EMPTY_ID ->
CCSBin = create_change_cipher_spec(State),
{State#state{handshake_env =
HSEnv#handshake_env{change_cipher_spec_sent = true}},
@@ -1195,11 +1211,10 @@ maybe_prepend_change_cipher_spec(State, Bin) ->
%% @doc Appends a change_cipher_spec record to the input binary
%% @end
maybe_append_change_cipher_spec(#state{
- ssl_options =
- #{middlebox_comp_mode := true},
+ session = #session{session_id = Id},
handshake_env =
#handshake_env{
- change_cipher_spec_sent = false} = HSEnv} = State, Bin) ->
+ change_cipher_spec_sent = false} = HSEnv} = State, Bin) when Id =/= ?EMPTY_ID ->
CCSBin = create_change_cipher_spec(State),
{State#state{handshake_env =
HSEnv#handshake_env{change_cipher_spec_sent = true}},
@@ -1207,7 +1222,7 @@ maybe_append_change_cipher_spec(#state{
maybe_append_change_cipher_spec(State, Bin) ->
{State, Bin}.
-maybe_queue_cert_cert_cv(#state{client_certificate_requested = false} = State) ->
+maybe_queue_cert_cert_cv(#state{client_certificate_status = not_requested} = State) ->
{ok, State};
maybe_queue_cert_cert_cv(#state{connection_states = _ConnectionStates0,
session = #session{session_id = _SessionId,
@@ -1347,8 +1362,9 @@ maybe_send_certificate_request(#state{static_env = #static_env{protocol_cb = Con
cert_db_ref = CertDbRef}} = State,
#{verify := verify_peer,
signature_algs := SignAlgs,
- signature_algs_cert := SignAlgsCert}, _) ->
- CertificateRequest = certificate_request(SignAlgs, SignAlgsCert, CertDbHandle, CertDbRef),
+ signature_algs_cert := SignAlgsCert,
+ certificate_authorities := CertAuthBool}, _) ->
+ CertificateRequest = certificate_request(SignAlgs, SignAlgsCert, CertDbHandle, CertDbRef, CertAuthBool),
{Connection:queue_handshake(CertificateRequest, State), wait_cert}.
maybe_send_certificate(State, PSK) when PSK =/= undefined ->
@@ -1431,7 +1447,8 @@ create_change_cipher_spec(#state{ssl_options = #{log_level := LogLevel}}) ->
process_certificate_request(#certificate_request_1_3{
extensions = Extensions},
#state{ssl_options = #{signature_algs := ClientSignAlgs},
- connection_env = #connection_env{cert_key_pairs = CertKeyPairs},
+ connection_env = #connection_env{cert_key_alts = CertKeyAlts,
+ negotiated_version = Version},
static_env = #static_env{cert_db = CertDbHandle, cert_db_ref = CertDbRef},
session = Session0} =
State) ->
@@ -1439,12 +1456,13 @@ process_certificate_request(#certificate_request_1_3{
maps:get(signature_algs, Extensions, undefined)),
ServerSignAlgsCert = get_signature_scheme_list(
maps:get(signature_algs_cert, Extensions, undefined)),
- CertAuths = get_certificate_authorites(maps:get(certificate_authorities, Extensions, undefined)),
+ CertAuths = get_certificate_authorities(maps:get(certificate_authorities, Extensions, undefined)),
+ CertKeyPairs = ssl_certificate:available_cert_key_pairs(CertKeyAlts, Version),
Session = select_client_cert_key_pair(Session0, CertKeyPairs,
- ServerSignAlgs, ServerSignAlgsCert, ClientSignAlgs,
- CertDbHandle, CertDbRef, CertAuths),
- {ok, {State#state{client_certificate_requested = true, session = Session}, wait_cert}}.
+ ServerSignAlgs, ServerSignAlgsCert, filter_tls13_algs(ClientSignAlgs),
+ CertDbHandle, CertDbRef, CertAuths, undefined),
+ {ok, {State#state{client_certificate_status = requested, session = Session}, wait_cert}}.
process_certificate(#certificate_1_3{
certificate_request_context = <<>>,
@@ -1649,19 +1667,16 @@ calculate_client_early_traffic_secret(
PendingRead0 = ssl_record:pending_connection_state(ConnectionStates, read),
PendingRead1 = maybe_store_early_data_secret(KeepSecrets, ClientEarlyTrafficSecret,
PendingRead0),
- PendingRead2 = update_connection_state(PendingRead1, undefined, undefined,
+ PendingRead = update_connection_state(PendingRead1, undefined, undefined,
undefined,
Key, IV, undefined),
- %% Signal start of early data. This is to prevent handshake messages to be
- %% counted in max_early_data_size.
- PendingRead = PendingRead2#{count_early_data => true},
State0#state{connection_states = ConnectionStates#{pending_read => PendingRead}}
end.
-update_current_read(#state{connection_states = CS} = State, TrialDecryption, EarlyDataLimit) ->
+update_current_read(#state{connection_states = CS} = State, TrialDecryption, EarlyDataExpected) ->
Read0 = ssl_record:current_connection_state(CS, read),
Read = Read0#{trial_decryption => TrialDecryption,
- early_data_limit => EarlyDataLimit},
+ early_data_accepted => EarlyDataExpected},
State#state{connection_states = CS#{current_read => Read}}.
maybe_store_early_data_secret(true, EarlySecret, State) ->
@@ -2064,7 +2079,7 @@ verify_signature_algorithm(#state{
static_env = #static_env{role = Role},
ssl_options = #{signature_algs := LocalSignAlgs}} = State0,
#certificate_verify_1_3{algorithm = PeerSignAlg}) ->
- case lists:member(PeerSignAlg, LocalSignAlgs) of
+ case lists:member(PeerSignAlg, filter_tls13_algs(LocalSignAlgs)) of
true ->
{ok, maybe_update_selected_sign_alg(State0, PeerSignAlg, Role)};
false ->
@@ -2312,14 +2327,14 @@ check_cert_sign_algo(SignAlgo, SignHash, _, ClientSignAlgsCert) ->
%% DSA keys are not supported by TLS 1.3
-select_sign_algo(dsa, _RSAKeySize, _PeerSignAlgs, _OwnSignAlgs, _Curve) ->
+select_sign_algo(dsa, _RSAKeySize, _CertSignAlg, _OwnSignAlgs, _Curve) ->
{error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_public_key)};
select_sign_algo(_, _RSAKeySize, [], _, _) ->
{error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)};
select_sign_algo(_, _RSAKeySize, undefined, _OwnSignAlgs, _) ->
{error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_public_key)};
-select_sign_algo(PublicKeyAlgo, RSAKeySize, [PeerSignAlg|PeerSignAlgs], OwnSignAlgs, Curve) ->
- {_, S, _} = ssl_cipher:scheme_to_components(PeerSignAlg),
+select_sign_algo(PublicKeyAlgo, RSAKeySize, [CertSignAlg|CertSignAlgs], OwnSignAlgs, Curve) ->
+ {_, S, _} = ssl_cipher:scheme_to_components(CertSignAlg),
%% RSASSA-PKCS1-v1_5 and Legacy algorithms are not defined for use in signed
%% TLS handshake messages: filter sha-1 and rsa_pkcs1.
%%
@@ -2333,36 +2348,36 @@ select_sign_algo(PublicKeyAlgo, RSAKeySize, [PeerSignAlg|PeerSignAlgs], OwnSignA
orelse (PublicKeyAlgo =:= eddsa andalso S =:= eddsa)
)
andalso
- lists:member(PeerSignAlg, OwnSignAlgs) of
+ lists:member(CertSignAlg, OwnSignAlgs) of
true ->
validate_key_compatibility(PublicKeyAlgo, RSAKeySize,
- [PeerSignAlg|PeerSignAlgs], OwnSignAlgs, Curve);
+ [CertSignAlg|CertSignAlgs], OwnSignAlgs, Curve);
false ->
- select_sign_algo(PublicKeyAlgo, RSAKeySize, PeerSignAlgs, OwnSignAlgs, Curve)
+ select_sign_algo(PublicKeyAlgo, RSAKeySize, CertSignAlgs, OwnSignAlgs, Curve)
end.
-validate_key_compatibility(PublicKeyAlgo, RSAKeySize, [PeerSignAlg|PeerSignAlgs], OwnSignAlgs, Curve)
+validate_key_compatibility(PublicKeyAlgo, RSAKeySize, [CertSignAlg|CertSignAlgs], OwnSignAlgs, Curve)
when PublicKeyAlgo =:= rsa orelse
PublicKeyAlgo =:= rsa_pss_pss ->
- {Hash, Sign, _} = ssl_cipher:scheme_to_components(PeerSignAlg),
+ {Hash, Sign, _} = ssl_cipher:scheme_to_components(CertSignAlg),
case (Sign =:= rsa_pss_rsae orelse Sign =:= rsa_pss_pss) andalso
is_rsa_key_compatible(RSAKeySize, Hash) of
true ->
- {ok, PeerSignAlg};
+ {ok, CertSignAlg};
false ->
- select_sign_algo(PublicKeyAlgo, RSAKeySize, PeerSignAlgs, OwnSignAlgs, Curve)
+ select_sign_algo(PublicKeyAlgo, RSAKeySize, CertSignAlgs, OwnSignAlgs, Curve)
end;
-validate_key_compatibility(PublicKeyAlgo, RSAKeySize, [PeerSignAlg|PeerSignAlgs], OwnSignAlgs, Curve)
+validate_key_compatibility(PublicKeyAlgo, RSAKeySize, [CertSignAlg|CertSignAlgs], OwnSignAlgs, Curve)
when PublicKeyAlgo =:= ecdsa ->
- {_ , Sign, PeerCurve} = ssl_cipher:scheme_to_components(PeerSignAlg),
+ {_ , Sign, PeerCurve} = ssl_cipher:scheme_to_components(CertSignAlg),
case Sign =:= ecdsa andalso Curve =:= PeerCurve of
true ->
- {ok, PeerSignAlg};
+ {ok, CertSignAlg};
false ->
- select_sign_algo(PublicKeyAlgo, RSAKeySize, PeerSignAlgs, OwnSignAlgs, Curve)
+ select_sign_algo(PublicKeyAlgo, RSAKeySize, CertSignAlgs, OwnSignAlgs, Curve)
end;
-validate_key_compatibility(_, _, [PeerSignAlg|_], _, _) ->
- {ok, PeerSignAlg}.
+validate_key_compatibility(_, _, [CertSignAlg|_], _, _) ->
+ {ok, CertSignAlg}.
is_rsa_key_compatible(KeySize, Hash) ->
HashSize = ssl_cipher:hash_size(Hash),
@@ -2419,18 +2434,14 @@ get_certificate_params(Cert) ->
SubjectPublicKeyAlgo = public_key_algo(SubjectPublicKeyAlgo0),
{SubjectPublicKeyAlgo, SignAlgo, SignHash, RSAKeySize, Curve}.
-oids_to_atoms(?'id-RSASSA-PSS', #'RSASSA-PSS-params'{maskGenAlgorithm =
+oids_to_atoms(?'id-RSASSA-PSS', #'RSASSA-PSS-params'{maskGenAlgorithm =
#'MaskGenAlgorithm'{algorithm = ?'id-mgf1',
parameters = #'HashAlgorithm'{algorithm = HashOid}}}) ->
Hash = public_key:pkix_hash_type(HashOid),
{Hash, rsa_pss_pss};
oids_to_atoms(SignAlgo, _) ->
- case public_key:pkix_sign_types(SignAlgo) of
- {sha, Sign} ->
- {sha1, Sign};
- {_,_} = Algs ->
- Algs
- end.
+ public_key:pkix_sign_types(SignAlgo).
+
%% Note: copied from ssl_handshake
public_key_algo(?'id-RSASSA-PSS') ->
rsa_pss_pss;
@@ -2458,9 +2469,9 @@ get_signature_scheme_list(#signature_algorithms{
lists:filter(fun (E) -> is_atom(E) andalso E =/= unassigned end,
ClientSignatureSchemes).
-get_certificate_authorites(#certificate_authorities{authorities = Auths}) ->
+get_certificate_authorities(#certificate_authorities{authorities = Auths}) ->
Auths;
-get_certificate_authorites(undefined) ->
+get_certificate_authorities(undefined) ->
[].
get_supported_groups(undefined = Groups) ->
@@ -2737,8 +2748,8 @@ maybe_send_early_data(#state{
%% Set 0-RTT traffic keys for sending early_data and EndOfEarlyData
State3 = ssl_record:step_encryption_state_write(State2),
{ok, encode_early_data(Cipher, State3)};
- {ok, {_, _, _, _MaxSize}} ->
- {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, too_much_early_data)};
+ {ok, {_, _, _, MaxSize}} ->
+ {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, {too_much_early_data, {max, MaxSize}})};
{error, Alert} ->
{error, Alert}
end;
@@ -2886,7 +2897,7 @@ process_ticket(#{cipher_suite := CipherSuite,
ticket = Ticket,
extensions = Extensions
} = NewSessionTicket,
- TicketAge = erlang:system_time(seconds) - Timestamp,
+ TicketAge = erlang:system_time(millisecond) - Timestamp,
ObfuscatedTicketAge = obfuscate_ticket_age(TicketAge, AgeAdd),
Identity = #psk_identity{
identity = Ticket,
@@ -2966,55 +2977,83 @@ supported_groups_from_extensions(Extensions) ->
{ok, undefined}
end.
-select_server_cert_key_pair(_,[], _,_,_,_, {error, _} = Return) ->
- Return;
select_server_cert_key_pair(_,[], _,_,_,_, #session{}=Session) ->
+ %% Conformant Cert-Key pair with advertised signature algorithm is
+ %% selected.
+ {ok, Session};
+select_server_cert_key_pair(_,[], _,_,_,_, {fallback, #session{}=Session}) ->
+ %% Use fallback Cert-Key pair as no conformant pair to the advertised
+ %% signature algorithms was found.
{ok, Session};
select_server_cert_key_pair(_,[], _,_,_,_, undefined) ->
- {error, ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, unable_to_send_certificate_verifiable_by_client)};
+ {error, ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, unable_to_supply_acceptable_cert)};
select_server_cert_key_pair(Session, [#{private_key := Key, certs := [Cert| _] = Certs} | Rest],
ClientSignAlgs, ClientSignAlgsCert, CertAuths,
- #state{static_env = #static_env{cert_db = CertDbHandle,
- cert_db_ref = CertDbRef} = State},
- Default) ->
+ #state{static_env = #static_env{cert_db = CertDbHandle,
+ cert_db_ref = CertDbRef} = State},
+ Default0) ->
{_, SignAlgo, SignHash, _, _} = get_certificate_params(Cert),
%% TODO: We do validate the signature algorithm and signature hash but we could also check
%% if the signing cert has a key on a curve supported by the client for ECDSA/EDDSA certs
case check_cert_sign_algo(SignAlgo, SignHash, ClientSignAlgs, ClientSignAlgsCert) of
ok ->
case ssl_certificate:handle_cert_auths(Certs, CertAuths, CertDbHandle, CertDbRef) of
- {ok, EncodeChain} ->
+ {ok, EncodeChain} -> %% Chain fullfills certificate_authorities extension
{ok, Session#session{own_certificates = EncodeChain, private_key = Key}};
{error, EncodeChain, not_in_auth_domain} ->
+ %% If this is the first chain to fulfill the signing requirement, use it as default,
+ %% if not later alternative also fulfills certificate_authorities extension
Default = Session#session{own_certificates = EncodeChain, private_key = Key},
- select_server_cert_key_pair(Session, Rest, ClientSignAlgs, ClientSignAlgsCert, CertAuths, State, Default)
+ select_server_cert_key_pair(Session, Rest, ClientSignAlgs, ClientSignAlgsCert,
+ CertAuths, State, default_or_fallback(Default0, Default))
end;
- Error ->
- select_server_cert_key_pair(Session, Rest, ClientSignAlgs, ClientSignAlgsCert, CertAuths, State,
- default_cert_key_pair_return(Default, Error))
+ _ ->
+ %% If the server cannot produce a certificate chain that is signed only
+ %% via the indicated supported algorithms, then it SHOULD continue the
+ %% handshake by sending the client a certificate chain of its choice
+ case SignHash of
+ sha ->
+ %% According to "Server Certificate Selection - RFC 8446"
+ %% Never send cert using sha1 unless client allows it
+ select_server_cert_key_pair(Session, Rest, ClientSignAlgs, ClientSignAlgsCert,
+ CertAuths, State, Default0);
+ _ ->
+ %% If there does not exist a default or fallback from previous alternatives
+ %% use this alternative as fallback.
+ Fallback = {fallback, Session#session{own_certificates = Certs, private_key = Key}},
+ select_server_cert_key_pair(Session, Rest, ClientSignAlgs, ClientSignAlgsCert,
+ CertAuths, State,
+ default_or_fallback(Default0, Fallback))
+ end
end.
+default_or_fallback(undefined, DefaultOrFallback) ->
+ DefaultOrFallback;
+default_or_fallback({fallback, _}, #session{} = Default) ->
+ Default;
+default_or_fallback(Default, _) ->
+ Default.
+
select_client_cert_key_pair(Session0,
[#{private_key := NoKey, certs := [[]] = NoCerts}],
- _,_,_,_,_,_) ->
+ _,_,_,_,_,_, _) ->
%% No certificate supplied : send empty certificate
Session0#session{own_certificates = NoCerts,
private_key = NoKey};
-select_client_cert_key_pair(Session0, CertKeyPairs, ServerSignAlgs, ServerSignAlgsCert,
- ClientSignAlgs, CertDbHandle, CertDbRef, CertAuths) ->
- select_client_cert_key_pair(Session0, CertKeyPairs, ServerSignAlgs, ServerSignAlgsCert,
- ClientSignAlgs, CertDbHandle, CertDbRef, CertAuths, undefined).
-
-select_client_cert_key_pair(Session, [],_,_,_,_,_,_, undefined = Default) ->
- %% No certificate compliant with supported algorithms : send empty certificate in state 'wait_finished'
- Session#session{own_certificates = Default,
- private_key = Default};
-select_client_cert_key_pair(_,[],_,_,_,_,_,_,#session{}=Session) ->
- %% No certificate compliant with guide lines send default
- Session;
-
+select_client_cert_key_pair(Session, [],_,_,_,_,_,_, undefined) ->
+ %% No certificate compliant with supported algorithms and
+ %% extensison : send empty certificate in state 'wait_finished'
+ Session#session{own_certificates = [[]],
+ private_key = #{}};
+select_client_cert_key_pair(_,[],_,_,_,_,_,_, #session{} = Plausible) ->
+ %% If we do not find an alternative chain with a cert signed in auth_domain,
+ %% but have a single cert without chain certs it might be verifiable by
+ %% a server that has the means to recreate the chain
+ Plausible;
select_client_cert_key_pair(Session0, [#{private_key := Key, certs := [Cert| _] = Certs} | Rest],
- ServerSignAlgs, ServerSignAlgsCert, ClientSignAlgs, CertDbHandle, CertDbRef, CertAuths, Default) ->
+ ServerSignAlgs, ServerSignAlgsCert,
+ ClientSignAlgs, CertDbHandle, CertDbRef,
+ CertAuths, Plausible0) ->
{PublicKeyAlgo, SignAlgo, SignHash, MaybeRSAKeySize, Curve} = get_certificate_params(Cert),
case select_sign_algo(PublicKeyAlgo, MaybeRSAKeySize, ServerSignAlgs, ClientSignAlgs, Curve) of
{ok, SelectedSignAlg} ->
@@ -3028,24 +3067,25 @@ select_client_cert_key_pair(Session0, [#{private_key := Key, certs := [Cert| _]
private_key = Key
};
{error, EncodedChain, not_in_auth_domain} ->
- Session = Session0#session{sign_alg = SelectedSignAlg,
- own_certificates = EncodedChain,
- private_key = Key
- },
- select_client_cert_key_pair(Session, Rest, ServerSignAlgs, ServerSignAlgsCert,
- ClientSignAlgs, CertDbHandle, CertDbRef, CertAuths,
- default_cert_key_pair_return(Default, Session))
+ Plausible = plausible_missing_chain(EncodedChain, Plausible0,
+ SelectedSignAlg, Key, Session0),
+ select_client_cert_key_pair(Session0, Rest, ServerSignAlgs, ServerSignAlgsCert,
+ ClientSignAlgs, CertDbHandle, CertDbRef, CertAuths,
+ Plausible)
end;
_ ->
select_client_cert_key_pair(Session0, Rest, ServerSignAlgs, ServerSignAlgsCert, ClientSignAlgs,
- CertDbHandle, CertDbRef, CertAuths, Default)
+ CertDbHandle, CertDbRef, CertAuths, Plausible0)
end;
{error, _} ->
select_client_cert_key_pair(Session0, Rest, ServerSignAlgsCert, ServerSignAlgsCert, ClientSignAlgs,
- CertDbHandle, CertDbRef, CertAuths, Default)
+ CertDbHandle, CertDbRef, CertAuths, Plausible0)
end.
-default_cert_key_pair_return(undefined, Session) ->
- Session;
-default_cert_key_pair_return(Default, _) ->
- Default.
+plausible_missing_chain([_] = EncodedChain, undefined, SignAlg, Key, Session0) ->
+ Session0#session{sign_alg = SignAlg,
+ own_certificates = EncodedChain,
+ private_key = Key
+ };
+plausible_missing_chain(_,Plausible,_,_,_) ->
+ Plausible.
diff --git a/lib/ssl/src/tls_handshake_1_3.hrl b/lib/ssl/src/tls_handshake_1_3.hrl
index 0c525bbb89..5af35208b9 100644
--- a/lib/ssl/src/tls_handshake_1_3.hrl
+++ b/lib/ssl/src/tls_handshake_1_3.hrl
@@ -26,10 +26,10 @@
-ifndef(tls_handshake_1_3).
-define(tls_handshake_1_3, true).
-%% Common to TLS-1.3 and previous TLS versions
-%% Some definitions may not exist in TLS-1.3 this is
+%% Common to TLS-1.3 and previous TLS versions
+%% Some definitions may not exist in TLS-1.3 this is
%% handled elsewhere
--include("tls_handshake.hrl").
+-include("tls_handshake.hrl").
%% New handshake types in TLS-1.3 RFC 8446 B.3
-define(NEW_SESSION_TICKET, 4).
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 30341f1598..ff23b2a99b 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -202,7 +202,7 @@ encode_data(Data, Version,
%%--------------------------------------------------------------------
-spec decode_cipher_text(tls_version(), #ssl_tls{}, ssl_record:connection_states(), boolean()) ->
- {#ssl_tls{} | trial_decryption_failed,
+ {#ssl_tls{} | no_record,
ssl_record:connection_states()}| #alert{}.
%%
%% Description: Decode cipher text
@@ -498,10 +498,10 @@ initial_connection_state(ConnectionEnd, BeastMitigation, MaxEarlyDataSize) ->
secure_renegotiation => undefined,
client_verify_data => undefined,
server_verify_data => undefined,
- max_early_data_size => MaxEarlyDataSize,
+ pending_early_data_size => MaxEarlyDataSize,
max_fragment_length => undefined,
trial_decryption => false,
- early_data_limit => false
+ early_data_expected => false
}.
%% Used by logging to recreate the received bytes
diff --git a/lib/ssl/src/tls_record.hrl b/lib/ssl/src/tls_record.hrl
index a483e5ba5b..e446e481a7 100644
--- a/lib/ssl/src/tls_record.hrl
+++ b/lib/ssl/src/tls_record.hrl
@@ -30,10 +30,11 @@
-include("ssl_record.hrl"). %% Common TLS and DTLS records and Constantes
%% Used to handle tls_plain_text, tls_compressed and tls_cipher_text
--record(ssl_tls, {
- type,
- version,
- fragment
- }).
+-record(ssl_tls, {
+ type,
+ version,
+ fragment,
+ early_data = false % TLS-1.3
+ }).
-endif. % -ifdef(tls_record).
diff --git a/lib/ssl/src/tls_record_1_3.erl b/lib/ssl/src/tls_record_1_3.erl
index ae375e4da1..440d9e0998 100644
--- a/lib/ssl/src/tls_record_1_3.erl
+++ b/lib/ssl/src/tls_record_1_3.erl
@@ -21,12 +21,14 @@
-include("tls_record.hrl").
-include("tls_record_1_3.hrl").
+-include("tls_handshake_1_3.hrl").
-include("ssl_internal.hrl").
-include("ssl_alert.hrl").
-include("ssl_cipher.hrl").
%% Encoding
--export([encode_handshake/2, encode_alert_record/2,
+-export([encode_handshake/2,
+ encode_alert_record/2,
encode_data/2]).
-export([encode_plain_text/3]).
@@ -43,7 +45,8 @@
%
%% Description: Encodes a handshake message to send on the tls-1.3-socket.
%%--------------------------------------------------------------------
-encode_handshake(Frag, #{current_write := #{max_fragment_length := MaxFragmentLength}} =
+encode_handshake(Frag, #{current_write :=
+ #{max_fragment_length := MaxFragmentLength}} =
ConnectionStates) ->
MaxLength = if is_integer(MaxFragmentLength) ->
MaxFragmentLength;
@@ -75,7 +78,8 @@ encode_alert_record(#alert{level = Level, description = Description},
%%
%% Description: Encodes data to send on the ssl-socket.
%%--------------------------------------------------------------------
-encode_data(Frag, #{current_write := #{max_fragment_length := MaxFragmentLength}} =
+encode_data(Frag, #{current_write :=
+ #{max_fragment_length := MaxFragmentLength}} =
ConnectionStates) ->
MaxLength = if is_integer(MaxFragmentLength) ->
MaxFragmentLength;
@@ -85,7 +89,8 @@ encode_data(Frag, #{current_write := #{max_fragment_length := MaxFragmentLength}
Data = tls_record:split_iovec(Frag, MaxLength),
encode_iolist(?APPLICATION_DATA, Data, ConnectionStates).
-encode_plain_text(Type, Data0, #{current_write := Write0} = ConnectionStates) ->
+encode_plain_text(Type, Data0, #{current_write := Write0} =
+ ConnectionStates) ->
PadLen = 0, %% TODO where to specify PadLen?
Data = inner_plaintext(Type, Data0, PadLen),
CipherFragment = encode_plain_text(Data, Write0),
@@ -107,12 +112,13 @@ encode_iolist(Type, Data, ConnectionStates0) ->
%%--------------------------------------------------------------------
-spec decode_cipher_text(#ssl_tls{}, ssl_record:connection_states()) ->
- {#ssl_tls{} | trial_decryption_failed,
+ {#ssl_tls{} | no_record,
ssl_record:connection_states()}| #alert{}.
%%
-%% Description: Decode cipher text, use legacy type ssl_tls instead of tls_cipher_text
-%% in decoding context so that we can reuse the code from earlier versions.
-%%--------------------------------------------------------------------
+%% Description: Decode cipher text, use legacy type ssl_tls instead of
+%% tls_cipher_text in decoding context so that we can reuse the code
+%% from earlier versions.
+%% --------------------------------------------------------------------
decode_cipher_text(#ssl_tls{type = ?OPAQUE_TYPE,
version = ?LEGACY_VERSION,
fragment = CipherFragment},
@@ -126,22 +132,25 @@ decode_cipher_text(#ssl_tls{type = ?OPAQUE_TYPE,
cipher_type = ?AEAD,
bulk_cipher_algorithm =
BulkCipherAlgo},
- max_early_data_size := MaxEarlyDataSize0,
+ pending_early_data_size := PendingMaxEarlyDataSize0,
trial_decryption := TrialDecryption,
- early_data_limit := EarlyDataLimit
+ early_data_accepted := EarlyDataAccepted
} = ReadState0} = ConnectionStates0) ->
case decipher_aead(CipherFragment, BulkCipherAlgo, Key, Seq, IV, TagLen) of
#alert{} when TrialDecryption =:= true andalso
- MaxEarlyDataSize0 > 0 -> %% Trial decryption
- trial_decrypt(ConnectionStates0, ReadState0, MaxEarlyDataSize0,
- BulkCipherAlgo, CipherFragment);
+ EarlyDataAccepted =:= false andalso
+ PendingMaxEarlyDataSize0 > 0 -> %% Trial decryption
+ ignore_early_data(ConnectionStates0, ReadState0,
+ PendingMaxEarlyDataSize0,
+ BulkCipherAlgo, CipherFragment);
#alert{} = Alert ->
Alert;
- PlainFragment0 when EarlyDataLimit =:= true andalso
- MaxEarlyDataSize0 > 0 ->
+ PlainFragment0 when EarlyDataAccepted =:= true andalso
+ PendingMaxEarlyDataSize0 > 0 ->
PlainFragment = remove_padding(PlainFragment0),
- process_early_data(ConnectionStates0, ReadState0, MaxEarlyDataSize0, Seq,
- BulkCipherAlgo, CipherFragment, PlainFragment);
+ process_early_data(ConnectionStates0, ReadState0,
+ PendingMaxEarlyDataSize0, Seq,
+ PlainFragment);
PlainFragment0 ->
PlainFragment = remove_padding(PlainFragment0),
ConnectionStates =
@@ -159,20 +168,20 @@ decode_cipher_text(#ssl_tls{type = ?OPAQUE_TYPE,
%% the signature algorithm of the client's certificate.)
decode_cipher_text(#ssl_tls{type = ?ALERT,
version = ?LEGACY_VERSION,
- fragment = <<2,47>>},
+ fragment = <<?FATAL,?ILLEGAL_PARAMETER>>},
ConnectionStates0) ->
{#ssl_tls{type = ?ALERT,
version = {3,4}, %% Internally use real version
- fragment = <<2,47>>}, ConnectionStates0};
+ fragment = <<?FATAL,?ILLEGAL_PARAMETER>>}, ConnectionStates0};
%% TLS 1.3 server can receive a User Cancelled Alert when handshake is
%% paused and then cancelled on the client side.
decode_cipher_text(#ssl_tls{type = ?ALERT,
version = ?LEGACY_VERSION,
- fragment = <<2,90>>},
+ fragment = <<?FATAL,?USER_CANCELED>>},
ConnectionStates0) ->
{#ssl_tls{type = ?ALERT,
version = {3,4}, %% Internally use real version
- fragment = <<2,90>>}, ConnectionStates0};
+ fragment = <<?FATAL,?USER_CANCELED>>}, ConnectionStates0};
%% RFC8446 - TLS 1.3
%% D.4. Middlebox Compatibility Mode
%% - If not offering early data, the client sends a dummy
@@ -208,48 +217,49 @@ decode_cipher_text(#ssl_tls{type = Type}, _) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-trial_decrypt(ConnectionStates0, ReadState0, MaxEarlyDataSize0,
+ignore_early_data(ConnectionStates0, ReadState0, PendingMaxEarlyDataSize0,
BulkCipherAlgo, CipherFragment) ->
- MaxEarlyDataSize = update_max_early_date_size(MaxEarlyDataSize0, BulkCipherAlgo, CipherFragment),
- ConnectionStates =
- ConnectionStates0#{current_read =>
- ReadState0#{max_early_data_size => MaxEarlyDataSize}},
- if MaxEarlyDataSize < 0 ->
- %% More early data is trial decrypted as the configured limit
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed);
- true ->
- {trial_decryption_failed, ConnectionStates}
- end.
-
-process_early_data(ConnectionStates0, ReadState0, _MaxEarlyDataSize0, Seq,
- _BulkCipherAlgo, _CipherFragment, PlainFragment)
- when PlainFragment =:= <<5,0,0,0,22>> ->
- %% struct {
- %% opaque content[TLSPlaintext.length]; <<5,0,0,0>> - 5 = EndOfEarlyData
- %% 0 = (uint24) size
- %% ContentType type; <<22>> - Handshake
- %% uint8 zeros[length_of_padding]; <<>> - no padding
- %% } TLSInnerPlaintext;
- %% EndOfEarlyData should not be counted into early data
+ PendingMaxEarlyDataSize =
+ approximate_pending_early_data_size(PendingMaxEarlyDataSize0,
+ BulkCipherAlgo, CipherFragment),
ConnectionStates =
- ConnectionStates0#{current_read =>
- ReadState0#{sequence_number => Seq + 1}},
- {decode_inner_plaintext(PlainFragment), ConnectionStates};
-process_early_data(ConnectionStates0, ReadState0, MaxEarlyDataSize0, Seq,
- BulkCipherAlgo, CipherFragment, PlainFragment) ->
+ ConnectionStates0#{current_read =>
+ ReadState0#{pending_early_data_size => PendingMaxEarlyDataSize}},
+ if PendingMaxEarlyDataSize < 0 ->
+ %% More early data is trial decrypted as the configured limit
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, {decryption_failed,
+ {max_early_data_threshold_exceeded,
+ PendingMaxEarlyDataSize}});
+ true ->
+ {no_record, ConnectionStates}
+ end.
+process_early_data(ConnectionStates0, ReadState0, PendingMaxEarlyDataSize0, Seq,
+ PlainFragment) ->
%% First packet is deciphered anyway so we must check if more early data is received
%% than the configured limit (max_early_data_size).
- MaxEarlyDataSize =
- update_max_early_date_size(MaxEarlyDataSize0, BulkCipherAlgo, CipherFragment),
- if MaxEarlyDataSize < 0 ->
- %% Too much early data received, send alert unexpected_message
- ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE, too_much_early_data);
- true ->
+ Record = decode_inner_plaintext(PlainFragment),
+ case {Record#ssl_tls.type, remove_padding(Record#ssl_tls.fragment)} of
+ {?HANDSHAKE, <<?END_OF_EARLY_DATA>>} ->
ConnectionStates =
ConnectionStates0#{current_read =>
- ReadState0#{sequence_number => Seq + 1,
- max_early_data_size => MaxEarlyDataSize}},
- {decode_inner_plaintext(PlainFragment), ConnectionStates}
+ ReadState0#{sequence_number => Seq + 1}},
+ {Record, ConnectionStates};
+ {?APPLICATION_DATA, Data} ->
+ PendingMaxEarlyDataSize =
+ pending_early_data_size(PendingMaxEarlyDataSize0, Data),
+ if PendingMaxEarlyDataSize < 0 ->
+ %% Too much early data received, send alert unexpected_message
+ ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE,
+ {too_much_early_data,
+ {max_early_data_threshold_exceeded,
+ PendingMaxEarlyDataSize}});
+ true ->
+ ConnectionStates =
+ ConnectionStates0#{current_read =>
+ ReadState0#{sequence_number => Seq + 1,
+ pending_early_data_size => PendingMaxEarlyDataSize}},
+ {Record#ssl_tls{early_data = true}, ConnectionStates}
+ end
end.
inner_plaintext(Type, Data, Length) ->
@@ -276,7 +286,8 @@ encode_plain_text(#inner_plaintext{
}) ->
PlainText = [Data, Type, Zeros],
Encoded = cipher_aead(PlainText, BulkCipherAlgo, Key, Seq, IV, TagLen),
- #tls_cipher_text{opaque_type = 23, %% 23 (application_data) for outward compatibility
+ %% 23 (application_data) for outward compatibility
+ #tls_cipher_text{opaque_type = ?OPAQUE_TYPE,
legacy_version = {3,3},
encoded_record = Encoded};
encode_plain_text(#inner_plaintext{
@@ -320,7 +331,8 @@ cipher_aead(Fragment, BulkCipherAlgo, Key, Seq, IV, TagLen) ->
encode_tls_cipher_text(#tls_cipher_text{opaque_type = Type,
legacy_version = {MajVer, MinVer},
- encoded_record = Encoded}, #{sequence_number := Seq} = Write) ->
+ encoded_record = Encoded},
+ #{sequence_number := Seq} = Write) ->
Length = erlang:iolist_size(Encoded),
{[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Encoded],
Write#{sequence_number => Seq +1}}.
@@ -333,11 +345,14 @@ decipher_aead(CipherFragment, BulkCipherAlgo, Key, Seq, IV, TagLen) ->
case ssl_cipher:aead_decrypt(BulkCipherAlgo, Key, Nonce, CipherText, CipherTag, AAD) of
Content when is_binary(Content) ->
Content;
- _ ->
+ Reason ->
+ ?SSL_LOG(debug, decrypt_error, [{reason,Reason},
+ {stacktrace, process_info(self(), current_stacktrace)}]),
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end
catch
- _:_ ->
+ _:Reason2:ST ->
+ ?SSL_LOG(debug, decrypt_error, [{reason,Reason2}, {stacktrace, ST}]),
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC, decryption_failed)
end.
@@ -379,19 +394,19 @@ remove_padding(InnerPlainText) ->
InnerPlainText
end.
-update_max_early_date_size(MaxEarlyDataSize, BulkCipherAlgo, CipherFragment) ->
- %% CipherFragment is the binary encoded form of a TLSInnerPlaintext:
- %%
- %% struct {
- %% opaque content[TLSPlaintext.length];
- %% ContentType type;
- %% uint8 zeros[length_of_padding];
- %% } TLSInnerPlaintext;
- %%
- TypeLen = 1,
- PaddingLen = 0, %% TODO Update formula when padding is implemented!
- MaxEarlyDataSize - (byte_size(CipherFragment) - TypeLen - PaddingLen -
- bca_tag_len(BulkCipherAlgo)).
+pending_early_data_size(PendingMaxEarlyDataSize, PlainFragment) ->
+ %% The maximum amount of 0-RTT data that the client is allowed to
+ %% send when using this ticket, in bytes. Only Application Data
+ %% payload (i.e., plaintext but not padding or the inner content
+ %% type byte) is counted.
+ PendingMaxEarlyDataSize - (byte_size(PlainFragment)).
+
+approximate_pending_early_data_size(PendingMaxEarlyDataSize,
+ BulkCipherAlgo, CipherFragment) ->
+ %% We can not know how much is padding!
+ InnerContTypeLen = 1,
+ PendingMaxEarlyDataSize - (byte_size(CipherFragment) -
+ InnerContTypeLen - bca_tag_len(BulkCipherAlgo)).
bca_tag_len(?AES_CCM_8) ->
8;
diff --git a/lib/ssl/src/tls_record_1_3.hrl b/lib/ssl/src/tls_record_1_3.hrl
index dbd1aafae5..c6214a5de3 100644
--- a/lib/ssl/src/tls_record_1_3.hrl
+++ b/lib/ssl/src/tls_record_1_3.hrl
@@ -27,6 +27,10 @@
-ifndef(tls_record_1_3).
-define(tls_record_1_3, true).
+%% Common to TLS-1.3 and previous TLS versions
+%% Some definitions may not exist in TLS-1.3 this is
+%% handled elsewhere
+-include("tls_record.hrl").
%% enum {
%% invalid(0),
%% %% defined in ssl_record.hrl
diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl
index 68e4eeed4e..b53a801b90 100644
--- a/lib/ssl/src/tls_sender.erl
+++ b/lib/ssl/src/tls_sender.erl
@@ -68,7 +68,8 @@
key_update_at, %% TLS 1.3
bytes_sent, %% TLS 1.3
dist_handle,
- log_level
+ log_level,
+ hibernate_after
}).
-record(data,
@@ -230,7 +231,8 @@ init({call, From}, {Pid, #{current_write := WriteState,
negotiated_version := Version,
renegotiate_at := RenegotiateAt,
key_update_at := KeyUpdateAt,
- log_level := LogLevel}},
+ log_level := LogLevel,
+ hibernate_after := HibernateAfter}},
#data{connection_states = ConnectionStates, static = Static0} = StateData0) ->
StateData =
StateData0#data{connection_states = ConnectionStates#{current_write => WriteState},
@@ -245,10 +247,11 @@ init({call, From}, {Pid, #{current_write := WriteState,
renegotiate_at = RenegotiateAt,
key_update_at = KeyUpdateAt,
bytes_sent = 0,
- log_level = LogLevel}},
+ log_level = LogLevel,
+ hibernate_after = HibernateAfter}},
{next_state, handshake, StateData, [{reply, From, ok}]};
init(info = Type, Msg, StateData) ->
- handle_common(Type, Msg, StateData);
+ handle_common(?FUNCTION_NAME, Type, Msg, StateData);
init(_, _, _) ->
%% Just in case anything else sneaks through
{keep_state_and_data, [postpone]}.
@@ -281,14 +284,14 @@ connection({call, From}, downgrade, #data{connection_states =
#{current_write := Write}} = StateData) ->
{next_state, death_row, StateData, [{reply,From, {ok, Write}}]};
connection({call, From}, {set_opts, Opts}, StateData) ->
- handle_set_opts(From, Opts, StateData);
+ handle_set_opts(?FUNCTION_NAME, From, Opts, StateData);
connection({call, From}, dist_get_tls_socket,
#data{static = #static{transport_cb = Transport,
socket = Socket,
connection_pid = Pid,
trackers = Trackers}} = StateData) ->
TLSSocket = tls_gen_connection:socket([Pid, self()], Transport, Socket, Trackers),
- {next_state, ?FUNCTION_NAME, StateData, [{reply, From, {ok, TLSSocket}}]};
+ hibernate_after(?FUNCTION_NAME, StateData, [{reply, From, {ok, TLSSocket}}]);
connection({call, From}, {dist_handshake_complete, _Node, DHandle},
#data{static = #static{connection_pid = Pid} = Static} = StateData) ->
false = erlang:dist_ctrl_set_opt(DHandle, get_size, true),
@@ -296,15 +299,20 @@ connection({call, From}, {dist_handshake_complete, _Node, DHandle},
ok = ssl_gen_statem:dist_handshake_complete(Pid, DHandle),
%% From now on we execute on normal priority
process_flag(priority, normal),
- {keep_state, StateData#data{static = Static#static{dist_handle = DHandle}},
- [{reply,From,ok}|
- case dist_data(DHandle) of
- [] ->
- [];
- Data ->
- [{next_event, internal,
- {application_packets,{self(),undefined},Data}}]
- end]};
+
+ case dist_data(DHandle) of
+ [] ->
+ hibernate_after(?FUNCTION_NAME,
+ StateData#data{
+ static = Static#static{dist_handle = DHandle}},
+ [{reply,From,ok}]);
+ Data ->
+ {keep_state,
+ StateData#data{static = Static#static{dist_handle = DHandle}},
+ [{reply,From,ok},
+ {next_event, internal,
+ {application_packets, {self(),undefined}, Data}}]}
+ end;
connection(internal, {application_packets, From, Data}, StateData) ->
send_application_data(Data, From, ?FUNCTION_NAME, StateData);
connection(internal, {post_handshake_data, From, HSData}, StateData) ->
@@ -314,20 +322,22 @@ connection(cast, #alert{} = Alert, StateData0) ->
{next_state, ?FUNCTION_NAME, StateData};
connection(cast, {new_write, WritesState, Version},
#data{connection_states = ConnectionStates, static = Static} = StateData) ->
- {next_state, connection,
- StateData#data{connection_states =
- ConnectionStates#{current_write => WritesState},
- static = Static#static{negotiated_version = Version}}};
+ hibernate_after(connection,
+ StateData#data{connection_states =
+ ConnectionStates#{current_write => WritesState},
+ static =
+ Static#static{negotiated_version = Version}}, []);
%%
-connection(info, dist_data, #data{static = #static{dist_handle = DHandle}}) ->
- {keep_state_and_data,
+connection(info, dist_data,
+ #data{static = #static{dist_handle = DHandle}} = StateData) ->
case dist_data(DHandle) of
[] ->
- [];
+ hibernate_after(?FUNCTION_NAME, StateData, []);
Data ->
- [{next_event, internal,
- {application_packets,{self(),undefined},Data}}]
- end};
+ {keep_state_and_data,
+ [{next_event, internal,
+ {application_packets, {self(),undefined}, Data}}]}
+ end;
connection(info, tick, StateData) ->
consume_ticks(),
Data = [<<0:32>>], % encode_packet(4, <<>>)
@@ -342,8 +352,10 @@ connection(info, {send, From, Ref, Data}, _StateData) ->
{keep_state_and_data,
[{next_event, {call, {self(), undefined}},
{application_data, erlang:iolist_to_iovec(Data)}}]};
+connection(timeout, hibernate, _StateData) ->
+ {keep_state_and_data, [hibernate]};
connection(Type, Msg, StateData) ->
- handle_common(Type, Msg, StateData).
+ handle_common(?FUNCTION_NAME, Type, Msg, StateData).
%%--------------------------------------------------------------------
-spec handshake(gen_statem:event_type(),
@@ -352,7 +364,7 @@ connection(Type, Msg, StateData) ->
gen_statem:event_handler_result(atom()).
%%--------------------------------------------------------------------
handshake({call, From}, {set_opts, Opts}, StateData) ->
- handle_set_opts(From, Opts, StateData);
+ handle_set_opts(?FUNCTION_NAME, From, Opts, StateData);
handshake({call, _}, _, _) ->
%% Postpone all calls to the connection state
{keep_state_and_data, [postpone]};
@@ -376,7 +388,7 @@ handshake(info, {send, _, _, _}, _) ->
%% Testing only, OTP distribution test suites...
{keep_state_and_data, [postpone]};
handshake(Type, Msg, StateData) ->
- handle_common(Type, Msg, StateData).
+ handle_common(?FUNCTION_NAME, Type, Msg, StateData).
%%--------------------------------------------------------------------
-spec death_row(gen_statem:event_type(),
@@ -384,14 +396,18 @@ handshake(Type, Msg, StateData) ->
StateData :: term()) ->
gen_statem:event_handler_result(atom()).
%%--------------------------------------------------------------------
-death_row(state_timeout, Reason, _State) ->
+death_row(state_timeout, Reason, _StateData) ->
{stop, {shutdown, Reason}};
-death_row(info = Type, Msg, State) ->
- handle_common(Type, Msg, State);
-death_row(_Type, _Msg, _State) ->
+death_row(info = Type, Msg, StateData) ->
+ handle_common(?FUNCTION_NAME, Type, Msg, StateData);
+death_row(_Type, _Msg, _StateData) ->
%% Waste all other events
keep_state_and_data.
+%% State entry function that starts shutdown state_timeout
+death_row_shutdown(Reason, StateData) ->
+ {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]}.
+
%%--------------------------------------------------------------------
-spec terminate(Reason :: term(), State :: term(), Data :: term()) ->
any().
@@ -413,36 +429,47 @@ code_change(_OldVsn, State, Data, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
-
-handle_set_opts(From, Opts, #data{static = #static{socket_options = SockOpts} = Static} = StateData) ->
- {keep_state, StateData#data{static = Static#static{socket_options = set_opts(SockOpts, Opts)}},
- [{reply, From, ok}]}.
-
-handle_common({call, From}, {set_opts, Opts},
+handle_set_opts(StateName, From, Opts,
+ #data{static = #static{socket_options = SockOpts} = Static}
+ = StateData) ->
+ hibernate_after(StateName,
+ StateData#data{
+ static =
+ Static#static{
+ socket_options = set_opts(SockOpts, Opts)}},
+ [{reply, From, ok}]).
+
+handle_common(StateName, {call, From}, {set_opts, Opts},
#data{static = #static{socket_options = SockOpts} = Static} = StateData) ->
- {keep_state, StateData#data{static = Static#static{socket_options = set_opts(SockOpts, Opts)}},
- [{reply, From, ok}]};
-handle_common(info, {'EXIT', _Sup, shutdown},
+ hibernate_after(StateName,
+ StateData#data{
+ static =
+ Static#static{
+ socket_options = set_opts(SockOpts, Opts)}},
+ [{reply, From, ok}]);
+handle_common(_StateName, info, {'EXIT', _Sup, shutdown = Reason},
#data{static = #static{erl_dist = true}} = StateData) ->
%% When the connection is on its way down operations
- %% begin to fail. We wait for 5 seconds to receive
- %% possible exit signals for one of our links to the other
- %% involved distribution parties, in which case we want to use
- %% their exit reason for the connection teardown.
- {next_state, death_row, StateData, [{state_timeout, 5000, shutdown}]};
-handle_common(info, {'EXIT', _Dist, Reason},
+ %% begin to fail. We wait to receive possible exit signals
+ %% for one of our links to the other involved distribution parties,
+ %% in which case we want to use their exit reason
+ %% for the connection teardown.
+ death_row_shutdown(Reason, StateData);
+handle_common(_StateName, info, {'EXIT', _Dist, Reason},
#data{static = #static{erl_dist = true}} = StateData) ->
{stop, {shutdown, Reason}, StateData};
-handle_common(info, {'EXIT', _Sup, shutdown}, StateData) ->
+handle_common(_StateName, info, {'EXIT', _Sup, shutdown}, StateData) ->
{stop, shutdown, StateData};
-handle_common(info, Msg, #data{static = #static{log_level = Level}}) ->
- ssl_logger:log(info, Level, #{event => "TLS sender received unexpected info",
+handle_common(StateName, info, Msg,
+ #data{static = #static{log_level = Level}} = StateData) ->
+ ssl_logger:log(info, Level, #{event => "TLS sender received unexpected info",
reason => [{message, Msg}]}, ?LOCATION),
- keep_state_and_data;
-handle_common(Type, Msg, #data{static = #static{log_level = Level}}) ->
- ssl_logger:log(error, Level, #{event => "TLS sender received unexpected event",
+ hibernate_after(StateName, StateData, []);
+handle_common(StateName, Type, Msg,
+ #data{static = #static{log_level = Level}} = StateData) ->
+ ssl_logger:log(error, Level, #{event => "TLS sender received unexpected event",
reason => [{type, Type}, {message, Msg}]}, ?LOCATION),
- keep_state_and_data.
+ hibernate_after(StateName, StateData, []).
send_tls_alert(#alert{} = Alert,
#data{static = #static{negotiated_version = Version,
@@ -471,7 +498,6 @@ send_application_data(Data, From, StateName,
key_update ->
KeyUpdate = tls_handshake_1_3:key_update(update_requested),
{keep_state_and_data, [{next_event, internal, {post_handshake_data, From, KeyUpdate}},
- {next_event, internal, {key_update, From}},
{next_event, internal, {application_packets, From, Data}}]};
renegotiate ->
tls_dtls_connection:internal_renegotiation(Pid, ConnectionStates0),
@@ -491,15 +517,15 @@ send_application_data(Data, From, StateName,
ok when DistHandle =/= undefined ->
ssl_logger:debug(LogLevel, outbound, 'record', Msgs),
StateData1 = update_bytes_sent(Version, StateData, Data),
- {next_state, StateName, StateData1, []};
+ hibernate_after(StateName, StateData1, []);
Reason when DistHandle =/= undefined ->
- {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]};
+ death_row_shutdown(Reason, StateData);
ok ->
ssl_logger:debug(LogLevel, outbound, 'record', Msgs),
StateData1 = update_bytes_sent(Version, StateData, Data),
- {next_state, StateName, StateData1, [{reply, From, ok}]};
+ hibernate_after(StateName, StateData1, [{reply, From, ok}]);
Result ->
- {next_state, StateName, StateData, [{reply, From, Result}]}
+ hibernate_after(StateName, StateData, [{reply, From, Result}])
end
end.
@@ -522,7 +548,7 @@ send_post_handshake_data(Handshake, From, StateName,
StateData = maybe_update_cipher_key(StateData1, Handshake),
{next_state, StateName, StateData, []};
Reason when DistHandle =/= undefined ->
- {next_state, death_row, StateData1, [{state_timeout, 5000, Reason}]};
+ death_row_shutdown(Reason, StateData1);
ok ->
ssl_logger:debug(LogLevel, outbound, 'record', Encoded),
StateData = maybe_update_cipher_key(StateData1, Handshake),
@@ -679,3 +705,10 @@ consume_ticks() ->
after 0 ->
ok
end.
+
+hibernate_after(connection = StateName,
+ #data{static=#static{hibernate_after = HibernateAfter}} = State,
+ Actions) ->
+ {next_state, StateName, State, [{timeout, HibernateAfter, hibernate} | Actions]};
+hibernate_after(StateName, State, Actions) ->
+ {next_state, StateName, State, Actions}.
diff --git a/lib/ssl/src/tls_server_session_ticket.erl b/lib/ssl/src/tls_server_session_ticket.erl
index b625cbcd52..f6b91404fb 100644
--- a/lib/ssl/src/tls_server_session_ticket.erl
+++ b/lib/ssl/src/tls_server_session_ticket.erl
@@ -181,7 +181,7 @@ inital_state([stateful, Lifetime, TicketStoreSize, MaxEarlyDataSize|_]) ->
}.
ticket_age_add() ->
- MaxTicketAge = 7 * 24 * 3600,
+ MaxTicketAge = 7 * 24 * 3600 * 1000,
IntMax = round(math:pow(2,32)) - 1,
MaxAgeAdd = IntMax - MaxTicketAge,
<<?UINT32(I)>> = crypto:strong_rand_bytes(4),
@@ -385,10 +385,10 @@ stateless_living_ticket(0, _, _, _, _) ->
stateless_living_ticket(ObfAge, TicketAgeAdd, Lifetime, Timestamp, Window) ->
ReportedAge = ObfAge - TicketAgeAdd,
RealAge = erlang:system_time(second) - Timestamp,
- (ReportedAge =< Lifetime)
+ (ReportedAge =< Lifetime * 1000)
andalso (RealAge =< Lifetime)
andalso (in_window(RealAge, Window)).
-
+
in_window(_, undefined) ->
true;
in_window(Age, Window) when is_integer(Window) ->
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index 80073952fc..779043f1de 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -391,10 +391,10 @@ code_change(_OldVsn, State, _Extra) ->
call(Pid, Msg) ->
gen_server:call(Pid, Msg, infinity).
-start_tls_server_connection(SslOpts, ConnectionCb, Transport, Port, Socket, EmOpts, Trackers, CbInfo) ->
+start_tls_server_connection(#{sender_spawn_opts := SenderOpts} = SslOpts, ConnectionCb, Transport, Port, Socket, EmOpts, Trackers, CbInfo) ->
try
{ok, DynSup} = tls_connection_sup:start_child([]),
- {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, []),
+ {ok, Sender} = tls_dyn_connection_sup:start_child(DynSup, sender, [[{spawn_opt, SenderOpts}]]),
ConnArgs = [server, Sender, "localhost", Port, Socket,
{SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Trackers}, self(), CbInfo],
{ok, Pid} = tls_dyn_connection_sup:start_child(DynSup, receiver, ConnArgs),
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index 75d994f18c..dd891967bc 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -869,25 +869,47 @@ signature_algs({3, 3}, HashSigns) ->
default_signature_algs([{3, 4} = Version]) ->
default_signature_schemes(Version) ++ legacy_signature_schemes(Version);
default_signature_algs([{3, 4}, {3,3} | _]) ->
- default_signature_schemes({3,4}) ++ default_signature_algs([{3,3}]);
+ default_signature_schemes({3,4}) ++ default_pre_1_3_signature_algs_only();
default_signature_algs([{3, 3} = Version |_]) ->
- Default = [%% SHA2
- {sha512, ecdsa},
- {sha512, rsa},
- {sha384, ecdsa},
- {sha384, rsa},
- {sha256, ecdsa},
- {sha256, rsa},
- {sha224, ecdsa},
- {sha224, rsa},
- %% SHA
- {sha, ecdsa},
- {sha, rsa},
- {sha, dsa}],
+ Default = [%% SHA2 ++ PSS
+ {sha512, ecdsa},
+ rsa_pss_pss_sha512,
+ rsa_pss_rsae_sha512,
+ {sha512, rsa},
+ {sha384, ecdsa},
+ rsa_pss_pss_sha384,
+ rsa_pss_rsae_sha384,
+ {sha384, rsa},
+ {sha256, ecdsa},
+ rsa_pss_pss_sha256,
+ rsa_pss_rsae_sha256,
+ {sha256, rsa},
+ {sha224, ecdsa},
+ {sha224, rsa},
+ %% SHA
+ {sha, ecdsa},
+ {sha, rsa},
+ {sha, dsa}],
signature_algs(Version, Default);
default_signature_algs(_) ->
undefined.
+default_pre_1_3_signature_algs_only() ->
+ Default = [%% SHA2
+ {sha512, ecdsa},
+ {sha512, rsa},
+ {sha384, ecdsa},
+ {sha384, rsa},
+ {sha256, ecdsa},
+ {sha256, rsa},
+ {sha224, ecdsa},
+ {sha224, rsa},
+ %% SHA
+ {sha, ecdsa},
+ {sha, rsa},
+ {sha, dsa}],
+ signature_algs({3,3}, Default).
+
signature_schemes(Version, [_|_] =SignatureSchemes) when is_tuple(Version)
andalso Version >= {3, 3} ->
@@ -898,7 +920,7 @@ signature_schemes(Version, [_|_] =SignatureSchemes) when is_tuple(Version)
RSAPSSSupported = lists:member(rsa_pkcs1_pss_padding,
proplists:get_value(rsa_opts, CryptoSupports)),
Fun = fun (Scheme, Acc) when is_atom(Scheme) ->
- {Hash0, Sign0, Curve} =
+ {Hash, Sign0, Curve} =
ssl_cipher:scheme_to_components(Scheme),
Sign = case Sign0 of
rsa_pkcs1 ->
@@ -909,11 +931,6 @@ signature_schemes(Version, [_|_] =SignatureSchemes) when is_tuple(Version)
rsa;
S -> S
end,
- Hash = case Hash0 of
- sha1 ->
- sha;
- H -> H
- end,
case proplists:get_bool(Sign, PubKeys)
andalso
(proplists:get_bool(Hash, Hashes)
@@ -957,7 +974,8 @@ signature_schemes(_, _) ->
[].
default_signature_schemes(Version) ->
- Default = [
+ Default = [eddsa_ed25519,
+ eddsa_ed448,
ecdsa_secp521r1_sha512,
ecdsa_secp384r1_sha384,
ecdsa_secp256r1_sha256,
@@ -966,9 +984,7 @@ default_signature_schemes(Version) ->
rsa_pss_pss_sha256,
rsa_pss_rsae_sha512,
rsa_pss_rsae_sha384,
- rsa_pss_rsae_sha256,
- eddsa_ed25519,
- eddsa_ed448
+ rsa_pss_rsae_sha256
],
signature_schemes(Version, Default).
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 7b7534bce8..ac1318bd14 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2021. All Rights Reserved.
+# Copyright Ericsson AB 1999-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -96,7 +96,8 @@ MODULES = \
x509_test \
inet_crypto_dist \
openssl_ocsp_SUITE \
- tls_server_session_ticket_SUITE
+ tls_server_session_ticket_SUITE \
+ tls_client_ticket_store_SUITE
ERL_FILES = $(MODULES:%=%.erl)
@@ -143,12 +144,13 @@ RELSYSDIR = $(RELEASE_PATH)/ssl_test
# running the target "targets".
# ----------------------------------------------------
ERL_COMPILE_FLAGS += $(INCLUDES)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
@@ -177,7 +179,7 @@ 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_bench.spec ssl.cover "$(RELSYSDIR)"
+ $(INSTALL_DATA) ssl.spec ssl_bench.spec ssl_gh.spec ssl.cover "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cf - *_SUITE_data property_test | (cd "$(RELSYSDIR)"; tar xf -)
diff --git a/lib/ssl/test/dtls_api_SUITE.erl b/lib/ssl/test/dtls_api_SUITE.erl
index f6dab82bd0..611c552858 100644
--- a/lib/ssl/test/dtls_api_SUITE.erl
+++ b/lib/ssl/test/dtls_api_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,8 @@
dtls_listen_two_sockets_5/1,
dtls_listen_two_sockets_6/0,
dtls_listen_two_sockets_6/1,
- client_restarts/0, client_restarts/1
+ client_restarts/0, client_restarts/1,
+ client_restarts_multiple_acceptors/1
]).
-include_lib("ssl/src/ssl_internal.hrl").
@@ -84,7 +85,8 @@ api_tests() ->
dtls_listen_two_sockets_4,
dtls_listen_two_sockets_5,
dtls_listen_two_sockets_6,
- client_restarts
+ client_restarts,
+ client_restarts_multiple_acceptors
].
init_per_suite(Config0) ->
@@ -354,59 +356,159 @@ client_restarts() ->
[{doc, "Test re-connection "}].
client_restarts(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ClientOpts = [{verify, verify_none},{reuse_sessions, save} | ClientOpts0],
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, ServerOpts}]),
+ {options, [{verify, verify_none}|ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client0 = ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
{mfa, {ssl_test_lib, no_result, []}},
{from, self()},
- {options, [{reuse_sessions, save} | ClientOpts]}]),
+ {options, ClientOpts}]),
+
+ ssl_test_lib:send(Client0, Msg1 = "from client 0"),
+ ssl_test_lib:send(Server, Msg2 = "from server to client 0"),
+
+ Server ! {active_receive, Msg1},
+ Client0 ! {active_receive, Msg2},
+
+ Msgs = lists:sort([{Server, Msg1}, {Client0, Msg2}]),
+ Msgs = lists:sort(flush()),
+
ReConnect = %% Whitebox re-connect test
fun({sslsocket, {gen_udp,_,dtls_gen_connection}, [Pid]} = Socket, ssl) ->
ct:log("~p Client Socket: ~p ~n", [self(), Socket]),
- {ok, {{Address,CPort},UDPSocket}=IntSocket} = gen_statem:call(Pid, {downgrade, self()}),
-
+ {ok, IntSocket} = gen_statem:call(Pid, {downgrade, self()}),
+ {{Address,CPort},UDPSocket}=IntSocket,
ct:log("Info: ~p~n", [inet:info(UDPSocket)]),
{ok, #config{transport_info = CbInfo, connection_cb = ConnectionCb,
- ssl = SslOpts0}} = ssl:handle_options(ClientOpts, client, Address),
+ ssl = SslOpts0}} =
+ ssl:handle_options(ClientOpts, client, Address),
SslOpts = {SslOpts0, #socket_options{}, undefined},
ct:sleep(250),
ct:log("Client second connect: ~p ~p~n", [Socket, CbInfo]),
- Res = ssl_gen_statem:connect(ConnectionCb, Address, CPort, IntSocket, SslOpts, self(), CbInfo, infinity),
- {Res, Pid}
+ {ok, NewSocket} = ssl_gen_statem:connect(ConnectionCb, Address, CPort, IntSocket,
+ SslOpts, self(), CbInfo, infinity),
+ {replace, NewSocket}
end,
Client0 ! {apply, self(), ReConnect},
receive
- {apply_res, {Res, _Prev}} ->
+ {apply_res, {replace, Res}} ->
ct:log("Apply res: ~p~n", [Res]),
ok;
- Msg ->
- ct:log("Unhandled: ~p~n", [Msg]),
- ct:fail({wrong_msg, Msg})
+ ErrMsg ->
+ ct:log("Unhandled: ~p~n", [ErrMsg]),
+ ct:fail({wrong_msg, ErrMsg})
end,
+ ssl_test_lib:send(Client0, Msg1 = "from client 0"),
+ ssl_test_lib:send(Server, Msg2 = "from server to client 0"),
+
+ Server ! {active_receive, Msg1},
+ Client0 ! {active_receive, Msg2},
+
+ Msgs = lists:sort(flush()),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client0),
+ ok.
+
+
+flush() ->
+ receive Msg -> [Msg|flush()]
+ after 500 -> []
+ end.
+
+client_restarts_multiple_acceptors(Config) ->
+ %% Can also be tested with openssl by connecting a client and hit
+ %% Ctrl-C to kill openssl process, so that the connection is not
+ %% closed.
+ %% Then do a new openssl connect with the same client port.
+
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ ClientOpts = [{verify, verify_none},{reuse_sessions, save} | ClientOpts0],
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {accepters, 2},
+ {options, [{verify, verify_none}|ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client0 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {from, self()},
+ {options, ClientOpts}]),
+
+ Server2 = receive {accepter, 2, Server2Pid} -> Server2Pid
+ after 5000 -> ct:fail(msg_timeout)
+ end,
+
+ ssl_test_lib:send(Client0, Msg1 = "from client 0"),
+ ssl_test_lib:send(Server, Msg2 = "from server to client 0"),
+
+ Server ! {active_receive, Msg1},
+ Client0 ! {active_receive, Msg2},
+
+ Msgs = lists:sort([{Server, Msg1}, {Client0, Msg2}]),
+ Msgs = lists:sort(flush()),
+
+ ReConnect = %% Whitebox re-connect test
+ fun({sslsocket, {gen_udp,_,dtls_gen_connection}, [Pid]} = Socket, ssl) ->
+ ct:log("~p Client Socket: ~p ~n", [self(), Socket]),
+ {ok, IntSocket} = gen_statem:call(Pid, {downgrade, self()}),
+ {{Address,CPort},UDPSocket}=IntSocket,
+ ct:log("Info: ~p~n", [inet:info(UDPSocket)]),
+
+ {ok, #config{transport_info = CbInfo, connection_cb = ConnectionCb,
+ ssl = SslOpts0}} =
+ ssl:handle_options(ClientOpts, client, Address),
+ SslOpts = {SslOpts0, #socket_options{}, undefined},
+
+ ct:sleep(250),
+ ct:log("Client second connect: ~p ~p~n", [Socket, CbInfo]),
+ {ok, NewSocket} = ssl_gen_statem:connect(ConnectionCb, Address, CPort, IntSocket,
+ SslOpts, self(), CbInfo, infinity),
+ {replace, NewSocket}
+ end,
+
+ Client0 ! {apply, self(), ReConnect},
receive
- Msg2 ->
- ct:log("Unhandled: ~p~n", [Msg2]),
- ct:fail({wrong_msg, Msg2})
- after 200 ->
- ct:log("Nothing received~n", [])
+ {apply_res, {replace, Res}} ->
+ ct:log("Apply res: ~p~n", [Res]),
+ ok;
+ ErrMsg ->
+ ct:log("Unhandled: ~p~n", [ErrMsg]),
+ ct:fail({wrong_msg, ErrMsg})
end,
+ ok = ssl_test_lib:send(Client0, Msg3 = "from client 2"),
+ ok = ssl_test_lib:send(Server2, Msg4 = "from server 2 to client 2"),
+ {error, closed} = ssl_test_lib:send(Server, "Should be closed"),
+
+ Msgs2 = lists:sort([{Server2, Msg3}, {Client0, Msg4}]),
+
+ Server2 ! {active_receive, Msg3},
+ Client0 ! {active_receive, Msg4},
+
+ Msgs2 = lists:sort(flush()),
+
ssl_test_lib:close(Server),
+ ssl_test_lib:close(Server2),
ssl_test_lib:close(Client0),
-
ok.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/inet_crypto_dist.erl b/lib/ssl/test/inet_crypto_dist.erl
index 58a303f48c..902bb5c252 100644
--- a/lib/ssl/test/inet_crypto_dist.erl
+++ b/lib/ssl/test/inet_crypto_dist.erl
@@ -29,7 +29,7 @@
-define(DRIVER, inet_tcp).
-define(FAMILY, inet).
--export([listen/1, accept/1, accept_connection/5,
+-export([supported/0, listen/1, accept/1, accept_connection/5,
setup/5, close/1, select/1, is_node_name/1]).
%% Generalized dist API, for sibling IPv6 module inet6_crypto_dist
@@ -51,11 +51,23 @@
%% -------------------------------------------------------------------------
+%% The curve choice greatly affects setup time,
+%% we really want an Edwards curve but that would
+%% require a very new openssl version.
+%% Twisted brainpool curves (*t1) are faster than
+%% non-twisted (*r1), 256 is much faster than 384,
+%% and so on...
+%%% -define(CURVE, brainpoolP384t1).
+%%% -define(CURVE, brainpoolP256t1).
+-define(CURVE, secp256r1).
+-define(CIPHER, aes_gcm).
+-define(HMAC, sha256).
+
-record(params,
{socket,
dist_handle,
- hmac_algorithm = sha256,
- aead_cipher = aes_gcm,
+ hmac_algorithm = ?HMAC,
+ aead_cipher = ?CIPHER,
rekey_key,
iv = 12,
key = 16,
@@ -71,20 +83,29 @@ params(Socket) ->
-record(key_pair,
{type = ecdh,
- %% The curve choice greatly affects setup time,
- %% we really want an Edwards curve but that would
- %% require a very new openssl version.
- %% Twisted brainpool curves (*t1) are faster than
- %% non-twisted (*r1), 256 is much faster than 384,
- %% and so on...
-%%% params = brainpoolP384t1,
- params = brainpoolP256t1,
+ params = ?CURVE,
public,
private,
life_time = 3600000, % 1 hour
life_count = 256 % Number of connection setups
}).
+supported() ->
+ Curve = lists:member(?CURVE, crypto:supports(curves)),
+ Cipher = lists:member(?CIPHER, crypto:supports(ciphers)),
+ Hmac =
+ lists:member(hmac, crypto:supports(macs)) andalso
+ lists:member(?HMAC, crypto:supports(hashs)),
+ if
+ not Curve ->
+ "curve " ++ atom_to_list(?CURVE);
+ not Cipher ->
+ "cipher " ++ atom_to_list(?CIPHER);
+ not Hmac ->
+ "HMAC " ++ atom_to_list(?HMAC);
+ true ->
+ ok
+ end.
%% -------------------------------------------------------------------------
%% Keep the node's public/private key pair in the process state
@@ -95,6 +116,7 @@ params(Socket) ->
start_key_pair_server() ->
monitor_dist_proc(
+ key_pair_server,
spawn_link(
fun () ->
register(?MODULE, self()),
@@ -354,6 +376,7 @@ gen_accept(Listen, Driver) ->
%% Spawn Acceptor process
%%
monitor_dist_proc(
+ acceptor,
spawn_opt(
fun () ->
start_key_pair_server(),
@@ -424,6 +447,7 @@ gen_accept_connection(
%% Spawn Controller/handshaker/ticker process
%%
monitor_dist_proc(
+ accept_controller,
spawn_opt(
fun() ->
do_accept(
@@ -466,6 +490,7 @@ gen_setup(Node, Type, MyNode, LongOrShortNames, SetupTime, Driver) ->
%% Spawn Controller/handshaker/ticker process
%%
monitor_dist_proc(
+ setup_controller,
spawn_opt(
setup_fun(
Node, Type, MyNode, LongOrShortNames, SetupTime, Driver, NetKernel),
@@ -796,6 +821,7 @@ start_dist_ctrl(Socket, Timeout) ->
Controller = self(),
Server =
monitor_dist_proc(
+ output_handler,
spawn_opt(
fun () ->
receive
@@ -937,7 +963,12 @@ init_recv(
RecvParams_1#params{iv = {IV2BSalt, IV2BNo}}}
end
catch
- error : Reason : Stacktrace->
+ Class : Reason : Stacktrace when Class =:= error ->
+ error_logger:info_report(
+ [init_recv_exception,
+ {class, Class},
+ {reason, Reason},
+ {stacktrace, Stacktrace}]),
_ = trace({Reason, Stacktrace}),
exit(connection_closed)
end.
@@ -960,8 +991,8 @@ init_msg(
MsgLen = byte_size(R1A) + TagLen + iolist_size(Plaintext),
AAD = [<<MsgLen:32>>, R1A],
{Ciphertext, Tag} =
- crypto:crypto_one_time(AeadCipher, Key1A, IV1A,
- {AAD, Plaintext, TagLen}, true),
+ crypto:crypto_one_time_aead(
+ AeadCipher, Key1A, IV1A, Plaintext, AAD, TagLen, true),
Msg = [R1A, Tag, Ciphertext],
{R2A, R3A, Msg}.
%%
@@ -982,8 +1013,8 @@ init_msg(
MsgLen = byte_size(Msg),
AAD = [<<MsgLen:32>>, R1B],
case
- crypto:crypto_one_time(
- AeadCipher, Key1B, IV1B, {AAD, Ciphertext, Tag}, false)
+ crypto:crypto_one_time_aead(
+ AeadCipher, Key1B, IV1B, Ciphertext, AAD, Tag, false)
of
<<R2B:RLen/binary, R3B:RLen/binary, PubKeyB/binary>> ->
SharedSecret = compute_shared_secret(KeyPair, PubKeyB),
@@ -1000,8 +1031,9 @@ init_msg(
StartMsgLen = TagLen + iolist_size(StartCleartext),
StartAAD = <<StartMsgLen:32>>,
{StartCiphertext, StartTag} =
- crypto:crypto_one_time(AeadCipher, Key2A, IV2A,
- {StartAAD, StartCleartext, TagLen}, true),
+ crypto:crypto_one_time_aead(
+ AeadCipher, Key2A, IV2A,
+ StartCleartext, StartAAD, TagLen, true),
StartMsg = [StartTag, StartCiphertext],
%%
{Key2B, IV2B} =
@@ -1032,8 +1064,8 @@ start_msg(
MsgLen = byte_size(Msg),
AAD = <<MsgLen:32>>,
case
- crypto:crypto_one_time(
- AeadCipher, Key2B, IV2B, {AAD, Ciphertext, Tag}, false)
+ crypto:crypto_one_time_aead(
+ AeadCipher, Key2B, IV2B, Ciphertext, AAD, Tag, false)
of
<<R2A:RLen/binary, R3A:RLen/binary, RekeyCountB:32>>
when RekeyCountA =< (RekeyCountB bsl 2),
@@ -1044,7 +1076,7 @@ start_msg(
hmac_key_iv(HmacAlgo, MacKey, Data, KeyLen, IVLen) ->
<<Key:KeyLen/binary, IV:IVLen/binary>> =
- crypto:macN(HmacAlgo, MacKey, Data, KeyLen + IVLen),
+ crypto:macN(hmac, HmacAlgo, MacKey, Data, KeyLen + IVLen),
{Key, IV}.
%% -------------------------------------------------------------------------
@@ -1063,20 +1095,14 @@ handshake(
{?MODULE, From, {handshake_complete, DistHandle}} ->
InputHandler =
monitor_dist_proc(
+ input_handler,
spawn_opt(
fun () ->
link(Controller),
receive
DistHandle ->
- ok =
- inet:setopts(
- Socket,
- [{active, ?TCP_ACTIVE},
- nodelay()]),
input_handler(
- RecvParams#params{
- dist_handle = DistHandle},
- RecvSeq, empty_q(), infinity)
+ RecvParams, RecvSeq, DistHandle)
end
end,
[link,
@@ -1085,42 +1111,40 @@ handshake(
{fullsweep_after, 0}])),
_ = monitor(process, InputHandler), % For the benchmark test
ok = gen_tcp:controlling_process(Socket, InputHandler),
+ false = erlang:dist_ctrl_set_opt(DistHandle, get_size, true),
ok = erlang:dist_ctrl_input_handler(DistHandle, InputHandler),
InputHandler ! DistHandle,
- crypto:rand_seed_alg(crypto_cache),
reply(From, ok),
process_flag(priority, normal),
- erlang:dist_ctrl_get_data_notification(DistHandle),
- output_handler(
- SendParams#params{
- dist_handle = DistHandle,
- rekey_msg = start_rekey_timer(SendParams#params.rekey_time)},
- SendSeq);
+ output_handler(SendParams, SendSeq, DistHandle);
%%
{?MODULE, From, {send, Data}} ->
- case
+ {SendParams_1, SendSeq_1, Result} =
encrypt_and_send_chunk(
- SendParams, SendSeq, [?HANDSHAKE_CHUNK, Data])
- of
- {SendParams_1, SendSeq_1, ok} ->
+ SendParams, SendSeq,
+ [?HANDSHAKE_CHUNK, Data], 1 + iolist_size(Data)),
+ if
+ Result =:= ok ->
reply(From, ok),
handshake(
SendParams_1, SendSeq_1, RecvParams, RecvSeq,
Controller);
- {_, _, Error} ->
+ true ->
reply(From, {error, closed}),
- death_row({send, trace(Error)})
+ death_row({send, trace(Result)})
end;
{?MODULE, From, recv} ->
- case recv_and_decrypt_chunk(RecvParams, RecvSeq) of
- {RecvParams_1, RecvSeq_1, {ok, _} = Reply} ->
- reply(From, Reply),
+ {RecvParams_1, RecvSeq_1, Result} =
+ recv_and_decrypt_chunk(RecvParams, RecvSeq),
+ case Result of
+ {ok, _} ->
+ reply(From, Result),
handshake(
SendParams, SendSeq, RecvParams_1, RecvSeq_1,
Controller);
- {_, _, Error} ->
- reply(From, Error),
- death_row({recv, trace(Error)})
+ {error, _} ->
+ reply(From, Result),
+ death_row({recv, trace(Result)})
end;
{?MODULE, From, peername} ->
reply(From, inet:peername(Socket)),
@@ -1136,11 +1160,17 @@ recv_and_decrypt_chunk(#params{socket = Socket} = RecvParams, RecvSeq) ->
case decrypt_chunk(RecvParams, RecvSeq, Chunk) of
<<?HANDSHAKE_CHUNK, Cleartext/binary>> ->
{RecvParams, RecvSeq + 1, {ok, Cleartext}};
- OtherChunk when is_binary(OtherChunk) ->
- {RecvParams, RecvSeq + 1, {error, decrypt_error}};
+ UnknownChunk when is_binary(UnknownChunk) ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason,unknown_chunk}]),
+ {RecvParams, RecvSeq + 1, {error, unknown_chunk}};
#params{} = RecvParams_1 ->
recv_and_decrypt_chunk(RecvParams_1, 0);
error ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason,decrypt_error}]),
{RecvParams, RecvSeq, {error, decrypt_error}}
end;
Error ->
@@ -1150,9 +1180,38 @@ recv_and_decrypt_chunk(#params{socket = Socket} = RecvParams, RecvSeq) ->
%% -------------------------------------------------------------------------
%% Output handler process
%%
-%% The game here is to flush all dist_data and dist_tick messages,
-%% prioritize dist_data over dist_tick, and to not use selective receive
+%% Await an event about what to do; fetch dist data from the VM,
+%% send a dist tick, or rekey outbound encryption parameters.
+%%
+%% In case we are overloaded and could get many accumulated
+%% dist_data or dist_tick messages; make sure to flush all of them
+%% before proceeding with what to do. But, do not use selective
+%% receive since that does not perform well when there are
+%% many messages in the process mailbox.
+
+%% Entry function
+output_handler(Params, Seq, DistHandle) ->
+ try
+ _ = crypto:rand_seed_alg(crypto_cache),
+ erlang:dist_ctrl_get_data_notification(DistHandle),
+ output_handler(
+ Params#params{
+ dist_handle = DistHandle,
+ rekey_msg = start_rekey_timer(Params#params.rekey_time)},
+ Seq)
+ catch
+ Class : Reason : Stacktrace ->
+ error_logger:info_report(
+ [output_handler_exception,
+ {class, Class},
+ {reason, Reason},
+ {stacktrace, Stacktrace}]),
+ erlang:raise(Class, Reason, Stacktrace)
+ end.
+%% Loop top
+%%
+%% State: lurking until any interesting message
output_handler(Params, Seq) ->
receive
Msg ->
@@ -1162,8 +1221,7 @@ output_handler(Params, Seq) ->
dist_tick ->
output_handler_tick(Params, Seq);
_ when Msg =:= Params#params.rekey_msg ->
- Params_1 = output_handler_rekey(Params, Seq),
- output_handler(Params_1, 0);
+ output_handler_rekey(Params, Seq);
_ ->
%% Ignore
_ = trace(Msg),
@@ -1171,6 +1229,7 @@ output_handler(Params, Seq) ->
end
end.
+%% State: we have received at least one dist_data message
output_handler_data(Params, Seq) ->
receive
Msg ->
@@ -1180,21 +1239,19 @@ output_handler_data(Params, Seq) ->
dist_tick ->
output_handler_data(Params, Seq);
_ when Msg =:= Params#params.rekey_msg ->
- Params_1 = output_handler_rekey(Params, Seq),
- output_handler_data(Params_1, 0);
+ output_handler_rekey(Params, Seq);
_ ->
%% Ignore
_ = trace(Msg),
output_handler_data(Params, Seq)
end
after 0 ->
- DistHandle = Params#params.dist_handle,
- Q = get_data(DistHandle, empty_q()),
- {Params_1, Seq_1} = output_handler_send(Params, Seq, Q),
- erlang:dist_ctrl_get_data_notification(DistHandle),
+ {Params_1, Seq_1} = output_handler_xfer(Params, Seq),
+ erlang:dist_ctrl_get_data_notification(Params#params.dist_handle),
output_handler(Params_1, Seq_1)
end.
+%% State: we have received at least one dist_tick but no dist_data message
output_handler_tick(Params, Seq) ->
receive
Msg ->
@@ -1204,8 +1261,7 @@ output_handler_tick(Params, Seq) ->
dist_tick ->
output_handler_tick(Params, Seq);
_ when Msg =:= Params#params.rekey_msg ->
- Params_1 = output_handler_rekey(Params, Seq),
- output_handler(Params_1, 0);
+ output_handler_rekey(Params, Seq);
_ ->
%% Ignore
_ = trace(Msg),
@@ -1214,185 +1270,273 @@ output_handler_tick(Params, Seq) ->
after 0 ->
TickSize = 7 + rand:uniform(56),
TickData = binary:copy(<<0>>, TickSize),
- case
- encrypt_and_send_chunk(Params, Seq, [?TICK_CHUNK, TickData])
- of
- {Params_1, Seq_1, ok} ->
+ {Params_1, Seq_1, Result} =
+ encrypt_and_send_chunk(
+ Params, Seq, [?TICK_CHUNK, TickData], 1 + TickSize),
+ if
+ Result =:= ok ->
output_handler(Params_1, Seq_1);
- {_, _, Error} ->
- _ = trace(Error),
- death_row()
+ true ->
+ death_row({send_tick, trace(Result)})
end
end.
output_handler_rekey(Params, Seq) ->
case encrypt_and_send_rekey_chunk(Params, Seq) of
#params{} = Params_1 ->
- Params_1;
+ output_handler(Params_1, 0);
SendError ->
- _ = trace(SendError),
- death_row()
+ death_row({send_rekey, trace(SendError)})
end.
-output_handler_send(Params, Seq, {_, Size, _} = Q) ->
- if
- ?CHUNK_SIZE < Size ->
- output_handler_deq_send(Params, Seq, Q, ?CHUNK_SIZE);
- true ->
- case get_data(Params#params.dist_handle, Q) of
- {_, 0, _} ->
+
+%% Get outbound data from VM; encrypt and send,
+%% until the VM has no more
+%%
+output_handler_xfer(Params, Seq) ->
+ output_handler_xfer(Params, Seq, [], 0, []).
+%%
+%% Front,Size,Rear is an Okasaki queue of binaries with total byte Size
+%%
+output_handler_xfer(Params, Seq, Front, Size, Rear)
+ when ?CHUNK_SIZE =< Size ->
+ %%
+ %% We have a full chunk or more
+ %% -> collect one chunk or less and send
+ output_handler_collect(Params, Seq, Front, Size, Rear);
+output_handler_xfer(Params, Seq, Front, Size, Rear) ->
+ %% when Size < ?CHUNK_SIZE ->
+ %%
+ %% We do not have a full chunk -> try to fetch more from VM
+ case erlang:dist_ctrl_get_data(Params#params.dist_handle) of
+ none ->
+ if
+ Size =:= 0 ->
+ %% No more data from VM, nothing buffered
+ %% -> go back to lurking
{Params, Seq};
- {_, Size, _} = Q_1 -> % Got no more
- output_handler_deq_send(Params, Seq, Q_1, Size);
- Q_1 ->
- output_handler_send(Params, Seq, Q_1)
- end
+ true ->
+ %% The VM had no more -> send what we have
+ output_handler_collect(Params, Seq, Front, Size, Rear)
+ end;
+ {Len,Iov} ->
+ output_handler_enq(
+ Params, Seq, Front, Size + 4 + Len, [<<Len:32>>|Rear], Iov)
end.
-output_handler_deq_send(Params, Seq, Q, Size) ->
- {Cleartext, Q_1} = deq_iovec(Size, Q),
- case
- encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK, Cleartext])
- of
- {Params_1, Seq_1, ok} ->
- output_handler_send(Params_1, Seq_1, Q_1);
- {_, _, Error} ->
- _ = trace(Error),
- death_row()
+%% Enqueue VM data while splitting large binaries into ?CHUNK_SIZE
+%%
+output_handler_enq(Params, Seq, Front, Size, Rear, []) ->
+ output_handler_xfer(Params, Seq, Front, Size, Rear);
+output_handler_enq(Params, Seq, Front, Size, Rear, [Bin|Iov]) ->
+ output_handler_enq(Params, Seq, Front, Size, Rear, Iov, Bin).
+%%
+output_handler_enq(Params, Seq, Front, Size, Rear, Iov, Bin) ->
+ BinSize = byte_size(Bin),
+ if
+ BinSize =< ?CHUNK_SIZE ->
+ output_handler_enq(
+ Params, Seq, Front, Size, [Bin|Rear], Iov);
+ true ->
+ <<Bin1:?CHUNK_SIZE/binary, Bin2/binary>> = Bin,
+ output_handler_enq(
+ Params, Seq, Front, Size, [Bin1|Rear], Iov, Bin2)
end.
-%% -------------------------------------------------------------------------
-%% Input handler process
+%% Collect small binaries into chunks of at most ?CHUNK_SIZE
%%
-%% Here is T = 0|infinity to steer if we should try to receive
-%% more data or not; start with infinity, and when we get some
-%% data try with 0 to see if more is waiting
-
-input_handler(#params{socket = Socket} = Params, Seq, Q, T) ->
- receive
- Msg ->
- case Msg of
- {tcp_passive, Socket} ->
- ok = inet:setopts(Socket, [{active, ?TCP_ACTIVE}]),
- Q_1 =
- case T of
- 0 ->
- deliver_data(Params#params.dist_handle, Q);
- infinity ->
- Q
- end,
- input_handler(Params, Seq, Q_1, infinity);
- {tcp, Socket, Chunk} ->
- input_chunk(Params, Seq, Q, T, Chunk);
- {tcp_closed, Socket} ->
- exit(connection_closed);
- Other ->
- %% Ignore...
- _ = trace(Other),
- input_handler(Params, Seq, Q, T)
- end
- after T ->
- Q_1 = deliver_data(Params#params.dist_handle, Q),
- input_handler(Params, Seq, Q_1, infinity)
+output_handler_collect(Params, Seq, [], Zero, []) ->
+ 0 = Zero, % Assert
+ %% No more enqueued -> try to get more form VM
+ output_handler_xfer(Params, Seq);
+output_handler_collect(Params, Seq, Front, Size, Rear) ->
+ output_handler_collect(Params, Seq, Front, Size, Rear, [], 0).
+%%
+output_handler_collect(Params, Seq, [], Zero, [], Acc, DataSize) ->
+ 0 = Zero, % Assert
+ output_handler_chunk(Params, Seq, [], Zero, [], Acc, DataSize);
+output_handler_collect(Params, Seq, [], Size, Rear, Acc, DataSize) ->
+ %% Okasaki queue transfer Rear -> Front
+ output_handler_collect(
+ Params, Seq, lists:reverse(Rear), Size, [], Acc, DataSize);
+output_handler_collect(
+ Params, Seq, [Bin|Iov] = Front, Size, Rear, Acc, DataSize) ->
+ BinSize = byte_size(Bin),
+ DataSize_1 = DataSize + BinSize,
+ if
+ ?CHUNK_SIZE < DataSize_1 ->
+ %% Bin does not fit in chunk -> send Acc
+ output_handler_chunk(
+ Params, Seq, Front, Size, Rear, Acc, DataSize);
+ DataSize_1 < ?CHUNK_SIZE ->
+ %% Chunk not full yet -> try to accumulate more
+ output_handler_collect(
+ Params, Seq, Iov, Size - BinSize, Rear, [Bin|Acc], DataSize_1);
+ true -> % DataSize_1 == ?CHUNK_SIZE ->
+ %% Optimize one iteration; Bin fits exactly -> accumulate and send
+ output_handler_chunk(
+ Params, Seq, Iov, Size - BinSize, Rear, [Bin|Acc], DataSize_1)
end.
-input_chunk(Params, Seq, Q, T, Chunk) ->
- case decrypt_chunk(Params, Seq, Chunk) of
- <<?DATA_CHUNK, Cleartext/binary>> ->
- input_handler(Params, Seq + 1, enq_binary(Cleartext, Q), 0);
- <<?TICK_CHUNK, _/binary>> ->
- input_handler(Params, Seq + 1, Q, T);
- OtherChunk when is_binary(OtherChunk) ->
- _ = trace(invalid_chunk),
- exit(connection_closed);
- #params{} = Params_1 ->
- input_handler(Params_1, 0, Q, T);
- error ->
- _ = trace(decrypt_error),
- exit(connection_closed)
+%% Encrypt and send a chunk
+%%
+output_handler_chunk(Params, Seq, Front, Size, Rear, Acc, DataSize) ->
+ Data = lists:reverse(Acc),
+ {Params_1, Seq_1, Result} =
+ encrypt_and_send_chunk(Params, Seq, [?DATA_CHUNK|Data], 1 + DataSize),
+ if
+ Result =:= ok ->
+ %% Try to collect another chunk
+ output_handler_collect(Params_1, Seq_1, Front, Size, Rear);
+ true ->
+ death_row({send_chunk, trace(Result)})
end.
%% -------------------------------------------------------------------------
-%% erlang:dist_ctrl_* helpers
+%% Input handler process
+%%
-%% Get data for sending from the VM and place it in a queue
+%% Entry function
+input_handler(#params{socket = Socket} = Params, Seq, DistHandle) ->
+ try
+ ok =
+ inet:setopts(
+ Socket, [{active, ?TCP_ACTIVE}, nodelay()]),
+ input_handler(
+ Params#params{dist_handle = DistHandle},
+ Seq)
+ catch
+ Class : Reason : Stacktrace ->
+ error_logger:info_report(
+ [input_handler_exception,
+ {class, Class},
+ {reason, Reason},
+ {stacktrace, Stacktrace}]),
+ erlang:raise(Class, Reason, Stacktrace)
+ end.
+
+%% Loop top
+input_handler(Params, Seq) ->
+ %% Shortcut into the loop
+ {Params_1, Seq_1, Data} = input_data(Params, Seq),
+ input_handler(Params_1, Seq_1, Data, [], byte_size(Data)).
%%
-get_data(DistHandle, {Front, Size, Rear}) ->
- get_data(DistHandle, Front, Size, Rear).
+input_handler(Params, Seq, First, Buffer, Size) ->
+ %% Size is size of First + Buffer
+ case First of
+ <<Packet1Size:32, Packet1:Packet1Size/binary,
+ Packet2Size:32, Packet2:Packet2Size/binary, Rest/binary>> ->
+ DistHandle = Params#params.dist_handle,
+ erlang:dist_ctrl_put_data(DistHandle, Packet1),
+ erlang:dist_ctrl_put_data(DistHandle, Packet2),
+ input_handler(
+ Params, Seq, Rest,
+ Buffer, Size - (8 + Packet1Size + Packet2Size));
+ <<PacketSize:32, Packet:PacketSize/binary, Rest/binary>> ->
+ DistHandle = Params#params.dist_handle,
+ erlang:dist_ctrl_put_data(DistHandle, Packet),
+ input_handler(
+ Params, Seq, Rest, Buffer, Size - (4 + PacketSize));
+ <<PacketSize:32, PacketStart/binary>> ->
+ %% Partial packet in First
+ input_handler(
+ Params, Seq, PacketStart, Buffer, Size - 4, PacketSize);
+ <<Bin/binary>> ->
+ %% Partial header in First
+ if
+ 4 =< Size ->
+ %% Complete header in First + Buffer
+ {First_1, Buffer_1, PacketSize} =
+ input_get_packet_size(Bin, lists:reverse(Buffer)),
+ input_handler(
+ Params, Seq, First_1, Buffer_1, Size - 4, PacketSize);
+ true ->
+ %% Incomplete header received so far
+ {Params_1, Seq_1, More} = input_data(Params, Seq),
+ input_handler(
+ Params_1, Seq_1, Bin,
+ [More|Buffer], Size + byte_size(More))
+ end
+ end.
%%
-get_data(DistHandle, Front, Size, Rear) ->
- case erlang:dist_ctrl_get_data(DistHandle) of
- none ->
- {Front, Size, Rear};
- Bin when is_binary(Bin) ->
- Len = byte_size(Bin),
- get_data(
- DistHandle, Front, Size + 4 + Len,
- [Bin, <<Len:32>>|Rear]);
- [Bin1, Bin2] ->
- Len = byte_size(Bin1) + byte_size(Bin2),
- get_data(
- DistHandle, Front, Size + 4 + Len,
- [Bin2, Bin1, <<Len:32>>|Rear]);
- Iovec ->
- Len = iolist_size(Iovec),
- get_data(
- DistHandle, Front, Size + 4 + Len,
- lists:reverse(Iovec, [<<Len:32>>|Rear]))
+input_handler(Params, Seq, PacketStart, Buffer, Size, PacketSize) ->
+ %% Size is size of PacketStart + Buffer
+ RestSize = Size - PacketSize,
+ if
+ RestSize < 0 ->
+ %% Incomplete packet received so far
+ {Params_1, Seq_1, More} = input_data(Params, Seq),
+ input_handler(
+ Params_1, Seq_1, PacketStart,
+ [More|Buffer], Size + byte_size(More), PacketSize);
+ 0 < RestSize, Buffer =:= [] ->
+ %% Rest data in PacketStart
+ <<Packet:PacketSize/binary, Rest/binary>> = PacketStart,
+ DistHandle = Params#params.dist_handle,
+ erlang:dist_ctrl_put_data(DistHandle, Packet),
+ input_handler(Params, Seq, Rest, [], RestSize);
+ Buffer =:= [] -> % RestSize == 0
+ %% No rest data
+ DistHandle = Params#params.dist_handle,
+ erlang:dist_ctrl_put_data(DistHandle, PacketStart),
+ input_handler(Params, Seq);
+ true ->
+ %% Split packet from rest data
+ LastBin = hd(Buffer),
+ <<PacketLast:(byte_size(LastBin) - RestSize)/binary,
+ Rest/binary>> = LastBin,
+ Packet = [PacketStart|lists:reverse(tl(Buffer), PacketLast)],
+ DistHandle = Params#params.dist_handle,
+ erlang:dist_ctrl_put_data(DistHandle, Packet),
+ input_handler(Params, Seq, Rest, [], RestSize)
end.
-%% De-packet and deliver received data to the VM from a queue
-%%
-deliver_data(DistHandle, Q) ->
- case Q of
- {[], Size, []} ->
- Size = 0, % Assert
- Q;
- {[], Size, Rear} ->
- [Bin|Front] = lists:reverse(Rear),
- deliver_data(DistHandle, Front, Size, [], Bin);
- {[Bin|Front], Size, Rear} ->
- deliver_data(DistHandle, Front, Size, Rear, Bin)
+input_get_packet_size(First, [Bin|Buffer]) ->
+ MissingSize = 4 - byte_size(First),
+ if
+ MissingSize =< byte_size(Bin) ->
+ <<Last:MissingSize/binary, Rest/binary>> = Bin,
+ <<PacketSize:32>> = <<First/binary, Last/binary>>,
+ {Rest, lists:reverse(Buffer), PacketSize};
+ true ->
+ input_get_packet_size(<<First/binary, Bin/binary>>, Buffer)
end.
+
+input_data(Params, Seq) ->
+ receive Msg -> input_data(Params, Seq, Msg) end.
%%
-deliver_data(DistHandle, Front, Size, Rear, Bin) ->
- case Bin of
- <<DataSizeA:32, DataA:DataSizeA/binary,
- DataSizeB:32, DataB:DataSizeB/binary, Rest/binary>> ->
- erlang:dist_ctrl_put_data(DistHandle, DataA),
- erlang:dist_ctrl_put_data(DistHandle, DataB),
- deliver_data(
- DistHandle,
- Front, Size - (4 + DataSizeA + 4 + DataSizeB), Rear,
- Rest);
- <<DataSize:32, Data:DataSize/binary, Rest/binary>> ->
- erlang:dist_ctrl_put_data(DistHandle, Data),
- deliver_data(DistHandle, Front, Size - (4 + DataSize), Rear, Rest);
- <<DataSize:32, FirstData/binary>> ->
- TotalSize = 4 + DataSize,
- if
- TotalSize =< Size ->
- BinSize = byte_size(Bin),
- {MoreData, Q} =
- deq_iovec(
- TotalSize - BinSize,
- Front, Size - BinSize, Rear),
- erlang:dist_ctrl_put_data(DistHandle, [FirstData|MoreData]),
- deliver_data(DistHandle, Q);
- true -> % Incomplete data
- {[Bin|Front], Size, Rear}
+input_data(#params{socket = Socket} = Params, Seq, Msg) ->
+ case Msg of
+ {tcp_passive, Socket} ->
+ ok = inet:setopts(Socket, [{active, ?TCP_ACTIVE}]),
+ input_data(Params, Seq);
+ {tcp, Socket, Ciphertext} ->
+ case decrypt_chunk(Params, Seq, Ciphertext) of
+ <<?DATA_CHUNK, Chunk/binary>> ->
+ {Params, Seq + 1, Chunk};
+ <<?TICK_CHUNK, _Dummy/binary>> ->
+ input_data(Params, Seq + 1);
+ <<UnknownChunk/binary>> ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason, unknown_chunk}]),
+ _ = trace(UnknownChunk),
+ exit(connection_closed);
+ #params{} = Params_1 ->
+ input_data(Params_1, 0);
+ error ->
+ _ = trace(decrypt_error),
+ exit(connection_closed)
end;
- <<_/binary>> ->
- BinSize = byte_size(Bin),
- if
- 4 =< Size -> % Fragmented header - extract a header bin
- {RestHeader, {Front_1, _Size_1, Rear_1}} =
- deq_iovec(4 - BinSize, Front, Size - BinSize, Rear),
- Header = iolist_to_binary([Bin|RestHeader]),
- deliver_data(DistHandle, Front_1, Size, Rear_1, Header);
- true -> % Incomplete header
- {[Bin|Front], Size, Rear}
- end
+ {tcp_closed = Reason, Socket} ->
+ error_logger:info_report(
+ [?FUNCTION_NAME,
+ {reason, Reason}]),
+ exit(connection_closed);
+ Other ->
+ %% Ignore...
+ _ = trace(Other),
+ input_data(Params, Seq)
end.
%% -------------------------------------------------------------------------
@@ -1400,20 +1544,23 @@ deliver_data(DistHandle, Front, Size, Rear, Bin) ->
encrypt_and_send_chunk(
#params{
- socket = Socket, rekey_count = Seq, rekey_msg = RekeyMsg} = Params,
- Seq, Cleartext) ->
+ socket = Socket, rekey_count = RekeyCount, rekey_msg = RekeyMsg} = Params,
+ Seq, Cleartext, Size) when Seq =:= RekeyCount ->
%%
cancel_rekey_timer(RekeyMsg),
case encrypt_and_send_rekey_chunk(Params, Seq) of
#params{} = Params_1 ->
Result =
- gen_tcp:send(Socket, encrypt_chunk(Params, 0, Cleartext)),
+ gen_tcp:send(
+ Socket, encrypt_chunk(Params, 0, Cleartext, Size)),
{Params_1, 1, Result};
SendError ->
{Params, Seq + 1, SendError}
end;
-encrypt_and_send_chunk(#params{socket = Socket} = Params, Seq, Cleartext) ->
- Result = gen_tcp:send(Socket, encrypt_chunk(Params, Seq, Cleartext)),
+encrypt_and_send_chunk(
+ #params{socket = Socket} = Params, Seq, Cleartext, Size) ->
+ Result =
+ gen_tcp:send(Socket, encrypt_chunk(Params, Seq, Cleartext, Size)),
{Params, Seq + 1, Result}.
encrypt_and_send_rekey_chunk(
@@ -1430,7 +1577,9 @@ encrypt_and_send_rekey_chunk(
#key_pair{public = PubKeyA} = KeyPair = get_new_key_pair(),
case
gen_tcp:send(
- Socket, encrypt_chunk(Params, Seq, [?REKEY_CHUNK, PubKeyA]))
+ Socket,
+ encrypt_chunk(
+ Params, Seq, [?REKEY_CHUNK, PubKeyA], 1 + byte_size(PubKeyA)))
of
ok ->
SharedSecret = compute_shared_secret(KeyPair, PubKeyB),
@@ -1445,18 +1594,19 @@ encrypt_and_send_rekey_chunk(
SendError ->
SendError
end.
-
+
encrypt_chunk(
#params{
aead_cipher = AeadCipher,
- iv = {IVSalt, IVNo}, key = Key, tag_len = TagLen}, Seq, Cleartext) ->
+ iv = {IVSalt, IVNo}, key = Key, tag_len = TagLen},
+ Seq, Cleartext, Size) ->
%%
- ChunkLen = iolist_size(Cleartext) + TagLen,
+ ChunkLen = Size + TagLen,
AAD = <<Seq:32, ChunkLen:32>>,
IVBin = <<IVSalt/binary, (IVNo + Seq):48>>,
{Ciphertext, CipherTag} =
- crypto:crypto_one_time(AeadCipher, Key, IVBin,
- {AAD, Cleartext, TagLen}, true),
+ crypto:crypto_one_time_aead(
+ AeadCipher, Key, IVBin, Cleartext, AAD, TagLen, true),
Chunk = [Ciphertext,CipherTag],
Chunk.
@@ -1468,31 +1618,33 @@ decrypt_chunk(
ChunkLen = byte_size(Chunk),
if
ChunkLen < TagLen ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason,short_chunk}]),
error;
true ->
AAD = <<Seq:32, ChunkLen:32>>,
IVBin = <<IVSalt/binary, (IVNo + Seq):48>>,
CiphertextLen = ChunkLen - TagLen,
- case Chunk of
- <<Ciphertext:CiphertextLen/binary,
- CipherTag:TagLen/binary>> ->
- block_decrypt(
- Params, Seq, AeadCipher, Key, IVBin,
- {AAD, Ciphertext, CipherTag});
- _ ->
- error
- end
+ <<Ciphertext:CiphertextLen/binary,
+ CipherTag:TagLen/binary>> = Chunk,
+ block_decrypt(
+ Params, Seq, AeadCipher, Key, IVBin,
+ Ciphertext, AAD, CipherTag)
end.
block_decrypt(
#params{
rekey_key = #key_pair{public = PubKeyA} = KeyPair,
rekey_count = RekeyCount} = Params,
- Seq, AeadCipher, Key, IV, Data) ->
- case crypto:crypto_one_time(AeadCipher, Key, IV, Data, false) of
- <<?REKEY_CHUNK, Rest/binary>> ->
+ Seq, AeadCipher, Key, IV, Ciphertext, AAD, CipherTag) ->
+ case
+ crypto:crypto_one_time_aead(
+ AeadCipher, Key, IV, Ciphertext, AAD, CipherTag, false)
+ of
+ <<?REKEY_CHUNK, Chunk/binary>> ->
PubKeyLen = byte_size(PubKeyA),
- case Rest of
+ case Chunk of
<<PubKeyB:PubKeyLen/binary>> ->
SharedSecret = compute_shared_secret(KeyPair, PubKeyB),
KeyLen = byte_size(Key),
@@ -1504,56 +1656,50 @@ block_decrypt(
SharedSecret, [Key, IV], KeyLen, IVLen),
Params#params{iv = {IVSalt, IVNo}, key = Key_1};
_ ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason,bad_rekey_chunk}]),
error
end;
Chunk when is_binary(Chunk) ->
case Seq of
RekeyCount ->
%% This was one chunk too many without rekeying
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason,rekey_overdue}]),
error;
_ ->
Chunk
end;
error ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason,decrypt_error}]),
error
end.
%% -------------------------------------------------------------------------
-%% Queue of binaries i.e an iovec queue
-
-empty_q() ->
- {[], 0, []}.
-enq_binary(Bin, {Front, Size, Rear}) ->
- {Front, Size + byte_size(Bin), [Bin|Rear]}.
+%% Wait for getting killed by process link,
+%% and if that does not happen - drop dead
-deq_iovec(GetSize, {Front, Size, Rear}) when GetSize =< Size ->
- deq_iovec(GetSize, Front, Size, Rear, []).
-%%
-deq_iovec(GetSize, Front, Size, Rear) ->
- deq_iovec(GetSize, Front, Size, Rear, []).
-%%
-deq_iovec(GetSize, [], Size, Rear, Acc) ->
- deq_iovec(GetSize, lists:reverse(Rear), Size, [], Acc);
-deq_iovec(GetSize, [Bin|Front], Size, Rear, Acc) ->
- BinSize = byte_size(Bin),
- if
- BinSize < GetSize ->
- deq_iovec(
- GetSize - BinSize, Front, Size - BinSize, Rear, [Bin|Acc]);
- GetSize < BinSize ->
- {Bin1,Bin2} = erlang:split_binary(Bin, GetSize),
- {lists:reverse(Acc, [Bin1]), {[Bin2|Front], Size - GetSize, Rear}};
- true ->
- {lists:reverse(Acc, [Bin]), {Front, Size - BinSize, Rear}}
+death_row(Reason) ->
+ error_logger:info_report(
+ [?FUNCTION_NAME,
+ {reason, Reason},
+ {pid, self()}]),
+ receive
+ after 5000 ->
+ death_row_timeout(Reason)
end.
-%% -------------------------------------------------------------------------
-
-death_row() -> death_row(connection_closed).
-%%
-death_row(normal) -> death_row(connection_closed);
-death_row(Reason) -> receive after 5000 -> exit(Reason) end.
+death_row_timeout(Reason) ->
+ error_logger:error_report(
+ [?FUNCTION_NAME,
+ {reason, Reason},
+ {pid, self()}]),
+ exit(Reason).
%% -------------------------------------------------------------------------
@@ -1561,23 +1707,27 @@ death_row(Reason) -> receive after 5000 -> exit(Reason) end.
trace(Term) -> Term.
%% Keep an eye on this Pid (debug)
--ifndef(undefined).
-monitor_dist_proc(Pid) ->
+-ifdef(undefined).
+monitor_dist_proc(_Tag, Pid) ->
Pid.
-else.
-monitor_dist_proc(Pid) ->
+monitor_dist_proc(Tag, Pid) ->
spawn(
fun () ->
MRef = erlang:monitor(process, Pid),
+ error_logger:info_report(
+ [?FUNCTION_NAME,
+ {type, Tag},
+ {pid, Pid}]),
receive
{'DOWN', MRef, _, _, normal} ->
error_logger:error_report(
- [dist_proc_died,
+ [?FUNCTION_NAME,
{reason, normal},
{pid, Pid}]);
{'DOWN', MRef, _, _, Reason} ->
error_logger:info_report(
- [dist_proc_died,
+ [?FUNCTION_NAME,
{reason, Reason},
{pid, Pid}])
end
diff --git a/lib/ssl/test/openssl_ECC_SUITE.erl b/lib/ssl/test/openssl_ECC_SUITE.erl
index ec84deda85..12595eeb7c 100644
--- a/lib/ssl/test/openssl_ECC_SUITE.erl
+++ b/lib/ssl/test/openssl_ECC_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2018-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2018-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -60,26 +60,22 @@ groups() ->
false ->
[{'tlsv1.2', [], [mix_sign]}]
end.
-
+
init_per_suite(Config0) ->
- end_per_suite(Config0),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
+ case ssl_test_lib:init_per_suite(Config0, openssl) of
+ {skip, _} = Skip ->
+ Skip;
+ Config ->
+ case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
true ->
- Config0;
+ Config;
false ->
{skip, "Openssl does not support ECC"}
end
- catch _:_ ->
- {skip, "Crypto did not start"}
end.
-end_per_suite(_Config) ->
- application:stop(ssl),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -90,15 +86,13 @@ end_per_group(GroupName, Config) ->
init_per_testcase(skip, Config) ->
Config;
init_per_testcase(TestCase, Config) ->
- ssl_test_lib:ct_log_supported_protocol_versions(Config),
- Version = proplists:get_value(tls_version, Config),
- ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, Version)]),
end_per_testcase(TestCase, Config),
ssl:start(),
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 30}),
Config.
-end_per_testcase(_TestCase, Config) ->
+end_per_testcase(_TestCase, Config) ->
application:stop(ssl),
Config.
diff --git a/lib/ssl/test/openssl_alpn_SUITE.erl b/lib/ssl/test/openssl_alpn_SUITE.erl
index 3a7a31d38c..2836e9a0a7 100644
--- a/lib/ssl/test/openssl_alpn_SUITE.erl
+++ b/lib/ssl/test/openssl_alpn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,7 +57,7 @@
%%--------------------------------------------------------------------
all() ->
- case ssl_test_lib:openssl_sane_dtls_alpn() of
+ case ssl_test_lib:openssl_sane_dtls_alpn() of
true ->
[
{group, 'tlsv1.3'},
@@ -76,8 +76,8 @@ all() ->
end.
groups() ->
- case ssl_test_lib:openssl_sane_dtls_alpn() of
- true ->
+ case ssl_test_lib:openssl_sane_dtls_alpn() of
+ true ->
[
{'tlsv1.3', [], alpn_tests()},
{'tlsv1.2', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()},
@@ -94,7 +94,7 @@ groups() ->
{'tlsv1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()}
]
end.
-
+
alpn_tests() ->
[erlang_client_alpn_openssl_server_alpn,
erlang_server_alpn_openssl_client_alpn,
@@ -107,7 +107,7 @@ alpn_tests() ->
alpn_npn_coexist() ->
[
erlang_client_alpn_npn_openssl_server_alpn_npn,
- erlang_server_alpn_npn_openssl_client_alpn_npn
+ erlang_server_alpn_npn_openssl_client_alpn_npn
].
rengotiation_tests() ->
[
@@ -116,30 +116,16 @@ rengotiation_tests() ->
].
init_per_suite(Config0) ->
- case os:find_executable("openssl") of
+ Config1 = ssl_test_lib:init_per_suite(Config0, openssl),
+ case check_openssl_alpn_support(Config1) of
false ->
- {skip, "Openssl not found"};
- _ ->
- case check_openssl_alpn_support(Config0) of
- {skip, _} = Skip ->
- Skip;
- _ ->
- ct:pal("Version: ~p", [os:cmd("openssl version")]),
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- ssl_test_lib:make_rsa_cert(Config0)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
- end
+ {skip, "No ALPN support"};
+ true ->
+ ssl_test_lib:make_rsa_cert(Config1)
end.
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -147,7 +133,7 @@ init_per_group(GroupName, Config) ->
end_per_group(GroupName, Config) ->
ssl_test_lib:end_per_group(GroupName, Config).
-init_per_testcase(TestCase, Config) ->
+init_per_testcase(TestCase, Config) ->
ct:timetrap({seconds, 30}),
special_init(TestCase, Config).
@@ -160,12 +146,12 @@ special_init(TestCase, Config) when TestCase == erlang_client_alpn_openssl_serve
Config ->
ssl_test_lib:openssl_allows_server_renegotiate(Config)
end;
-special_init(TestCase, Config) when TestCase == erlang_client_alpn_npn_openssl_server_alpn_npn;
+special_init(TestCase, Config) when TestCase == erlang_client_alpn_npn_openssl_server_alpn_npn;
TestCase == erlang_server_alpn_npn_openssl_client_alpn_npn ->
case ssl_test_lib:check_openssl_npn_support(Config) of
- {skip, _} = Skip ->
- Skip;
- Config ->
+ false ->
+ {skip, "npn not supported"};
+ true ->
Config
end;
special_init(_, Config) ->
@@ -182,19 +168,19 @@ erlang_client_alpn_openssl_server_alpn(Config) when is_list(Config) ->
ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
AlpnProtocol = <<"spdy/2">>,
-
+
{Server, OpenSSLPort} =
ssl_test_lib:start_server(openssl, [{alpn,"http/1.1,spdy/2"}, return_port],
[{server_opts, ServerOpts} | Config]),
Port = ssl_test_lib:inet_port(Server),
-
+
{Client, CSocket} = ssl_test_lib:start_client(erlang, [{port, Port},
- return_socket],
- [{client_opts,
+ return_socket],
+ [{client_opts,
[{alpn_advertised_protocols,
- [AlpnProtocol]} | ClientOpts]}
+ [AlpnProtocol]} | ClientOpts]}
| Config]),
-
+
case ssl:negotiated_protocol(CSocket) of
{ok, AlpnProtocol} ->
ok;
@@ -210,17 +196,17 @@ erlang_server_alpn_openssl_client_alpn(Config) when is_list(Config) ->
ClientOpts = proplists:get_value(client_rsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
Protocol = <<"spdy/2">>,
- Server = ssl_test_lib:start_server(erlang, [{from, self()}],
- [{server_opts, [{alpn_preferred_protocols,
+ Server = ssl_test_lib:start_server(erlang, [{from, self()}],
+ [{server_opts, [{alpn_preferred_protocols,
[<<"spdy/2">>]} |ServerOpts]} | Config]),
Port = ssl_test_lib:inet_port(Server),
{_Client, OpenSSLPort} =
ssl_test_lib:start_client(openssl, [{port, Port},{alpn, "spdy/2"},
{options, ClientOpts}, return_port], Config),
-
+
Server ! get_socket,
- SSocket =
- receive
+ SSocket =
+ receive
{Server, {socket, Socket}} ->
Socket
end,
@@ -239,11 +225,11 @@ erlang_client_alpn_openssl_server(Config) when is_list(Config) ->
ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
Protocol = <<"spdy/2">>,
-
+
{Server, OpenSSLPort} = ssl_test_lib:start_server(openssl, [return_port],
[{server_opts, ServerOpts} | Config]),
Port = ssl_test_lib:inet_port(Server),
-
+
{Client, CSocket} =
ssl_test_lib:start_client(erlang, [{port, Port},
return_socket],
@@ -264,15 +250,15 @@ erlang_client_alpn_openssl_server(Config) when is_list(Config) ->
erlang_client_openssl_server_alpn(Config) when is_list(Config) ->
ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
-
- {Server, OpenSSLPort} = ssl_test_lib:start_server(openssl, [{alpn,"spdy/2"}, return_port],
+
+ {Server, OpenSSLPort} = ssl_test_lib:start_server(openssl, [{alpn,"spdy/2"}, return_port],
[{server_opts, ServerOpts} | Config]),
Port = ssl_test_lib:inet_port(Server),
-
+
{Client, CSocket} = ssl_test_lib:start_client(erlang, [{port, Port},
- return_socket],
+ return_socket],
[{client_opts, ClientOpts} | Config]),
-
+
case ssl:negotiated_protocol(CSocket) of
{error, protocol_not_negotiated} ->
ok;
@@ -285,17 +271,17 @@ erlang_client_openssl_server_alpn(Config) when is_list(Config) ->
erlang_server_alpn_openssl_client(Config) when is_list(Config) ->
ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- Server = ssl_test_lib:start_server(erlang, [{from, self()}],
+ Server = ssl_test_lib:start_server(erlang, [{from, self()}],
[{server_opts, [{alpn_preferred_protocols,
[<<"spdy/2">>]} | ServerOpts]} | Config]),
Port = ssl_test_lib:inet_port(Server),
{_Client, OpenSSLPort} =
ssl_test_lib:start_client(openssl, [{port, Port},
{options, ClientOpts}, return_port], Config),
-
+
Server ! get_socket,
- SSocket =
- receive
+ SSocket =
+ receive
{Server, {socket, Socket}} ->
Socket
end,
@@ -312,16 +298,16 @@ erlang_server_alpn_openssl_client(Config) when is_list(Config) ->
erlang_server_openssl_client_alpn(Config) when is_list(Config) ->
ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- Server = ssl_test_lib:start_server(erlang, [{from, self()}],
+ Server = ssl_test_lib:start_server(erlang, [{from, self()}],
[{server_opts, [ServerOpts]} | Config]),
Port = ssl_test_lib:inet_port(Server),
{_Client, OpenSSLPort} =
ssl_test_lib:start_client(openssl, [{port, Port}, {alpn, "spdy/2"},
{options, ClientOpts}, return_port], Config),
-
+
Server ! get_socket,
- SSocket =
- receive
+ SSocket =
+ receive
{Server, {socket, Socket}} ->
Socket
end,
@@ -337,16 +323,16 @@ erlang_server_openssl_client_alpn(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
erlang_client_alpn_openssl_server_alpn_renegotiate(Config) when is_list(Config) ->
-
+
ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
AlpnProtocol = <<"spdy/2">>,
-
+
{Server, OpenSSLPort} =
ssl_test_lib:start_server(openssl, [{alpn,"http/1.1,spdy/2"}, return_port],
[{server_opts, ServerOpts} | Config]),
Port = ssl_test_lib:inet_port(Server),
-
+
{Client, CSocket} =
ssl_test_lib:start_client(erlang, [{port, Port},
return_socket],
@@ -378,17 +364,17 @@ erlang_server_alpn_openssl_client_alpn_renegotiate(Config) when is_list(Config)
ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
AlpnProtocol = <<"spdy/2">>,
- Server = ssl_test_lib:start_server(erlang, [{from, self()}],
- [{server_opts, [{alpn_preferred_protocols,
+ Server = ssl_test_lib:start_server(erlang, [{from, self()}],
+ [{server_opts, [{alpn_preferred_protocols,
[AlpnProtocol]} | ServerOpts]} | Config]),
Port = ssl_test_lib:inet_port(Server),
{_Client, OpenSSLPort} =
ssl_test_lib:start_client(openssl, [{port, Port}, {alpn, "spdy/2"},
{options, ClientOpts}, return_port], Config),
-
+
Server ! get_socket,
- SSocket =
- receive
+ SSocket =
+ receive
{Server, {socket, Socket}} ->
Socket
end,
@@ -415,20 +401,20 @@ erlang_client_alpn_npn_openssl_server_alpn_npn(Config) when is_list(Config) ->
ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
AlpnProtocol = <<"spdy/2">>,
-
+
{Server, OpenSSLPort} =
ssl_test_lib:start_server(openssl, [{alpn,"http/1.1,spdy/2"},
{np, "spdy/3"}, return_port],
[{server_opts, ServerOpts} | Config]),
Port = ssl_test_lib:inet_port(Server),
-
+
{Client, CSocket} =
ssl_test_lib:start_client(erlang, [{port, Port},
return_socket],
[{client_opts,
[{alpn_advertised_protocols, [AlpnProtocol]},
- {next_protocols_advertised,
- [<<"spdy/3">>, <<"http/1.1">>]}]} | ClientOpts] ++ Config),
+ {client_preferred_next_protocols,
+ {client, [<<"spdy/3">>, <<"http/1.1">>]}}]} | ClientOpts] ++ Config),
case ssl:negotiated_protocol(CSocket) of
{ok, AlpnProtocol} ->
ok;
@@ -443,11 +429,11 @@ erlang_server_alpn_npn_openssl_client_alpn_npn(Config) when is_list(Config) ->
ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
AlpnProtocol = <<"spdy/2">>,
- Server = ssl_test_lib:start_server(erlang,
- [{from, self()}],
- [{server_opts, [{alpn_preferred_protocols,
+ Server = ssl_test_lib:start_server(erlang,
+ [{from, self()}],
+ [{server_opts, [{alpn_preferred_protocols,
[<<"spdy/2">>]},
- {next_protocols_advertised,
+ {next_protocols_advertised,
[<<"spdy/3">>, <<"http/1.1">>]}
| ServerOpts]} | Config]),
Port = ssl_test_lib:inet_port(Server),
@@ -455,10 +441,10 @@ erlang_server_alpn_npn_openssl_client_alpn_npn(Config) when is_list(Config) ->
ssl_test_lib:start_client(openssl, [{port, Port}, {alpn, "http/1.1,spdy/2"},
{np,"spdy/3"}, {options, ClientOpts},
return_port], Config),
-
+
Server ! get_socket,
- SSocket =
- receive
+ SSocket =
+ receive
{Server, {socket, Socket}} ->
Socket
end,
@@ -475,10 +461,22 @@ erlang_server_alpn_npn_openssl_client_alpn_npn(Config) when is_list(Config) ->
%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
check_openssl_alpn_support(Config) ->
- HelpText = ssl_test_lib:portable_cmd("openssl", ["s_client --help"]),
- case string:str(HelpText, "alpn") of
- 0 ->
- {skip, "Openssl not compiled with alpn support"};
+ case proplists:get_value(openssl_version, Config) of
+ "OpenSSL 1.0." ++ _ = Str->
+ SubStr = Str -- "OpenSSL 1.0.",
+ atleast(SubStr, 2);
+ "OpenSSL 1.1" ++ _ ->
+ true;
+ "OpenSSL 3" ++ _ ->
+ true;
+ "LibreSSL 2.0" ++ _ ->
+ false;
+ "LibreSSL 2.1." ++ _ = Str ->
+ SubStr = Str -- "LibreSSL 2.1.",
+ atleast(SubStr, 3);
_ ->
- Config
+ false
end.
+
+atleast([StrNum|_], Num) ->
+ list_to_integer([StrNum]) >= Num.
diff --git a/lib/ssl/test/openssl_cipher_suite_SUITE.erl b/lib/ssl/test/openssl_cipher_suite_SUITE.erl
index 72fe666e0f..8724595724 100644
--- a/lib/ssl/test/openssl_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/openssl_cipher_suite_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
end_per_testcase/2]).
%% Testcases
--export([dhe_psk_des_cbc/1,
+-export([%%dhe_psk_des_cbc/1,
dhe_rsa_3des_ede_cbc/1,
dhe_rsa_aes_128_cbc/1,
dhe_rsa_aes_128_gcm/1,
@@ -89,19 +89,14 @@
ecdhe_ecdsa_with_aes_256_ccm_8/1
]).
--define(DEFAULT_TIMEOUT, {seconds, 10}).
+-define(DEFAULT_TIMEOUT, {seconds, 15}).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-all() ->
- case ssl_test_lib:working_openssl_client() of
- true ->
- [{group, openssl_server},
- {group, openssl_client}];
- false ->
- [{group, openssl_server}]
- end.
+all() ->
+ [{group, openssl_server},
+ {group, openssl_client}].
all_protocol_groups() ->
[
@@ -125,14 +120,14 @@ groups() ->
{'tlsv1', [], kex()},
{'dtlsv1.2', [], dtls_kex()},
{'dtlsv1', [], dtls_kex()},
- {dhe_rsa, [],[dhe_rsa_3des_ede_cbc,
+ {dhe_rsa, [],[dhe_rsa_3des_ede_cbc,
dhe_rsa_aes_128_cbc,
dhe_rsa_aes_128_gcm,
dhe_rsa_aes_256_cbc,
dhe_rsa_aes_256_gcm,
dhe_rsa_chacha20_poly1305
]},
- {ecdhe_rsa, [], [ecdhe_rsa_3des_ede_cbc,
+ {ecdhe_rsa, [], [ecdhe_rsa_3des_ede_cbc,
ecdhe_rsa_rc4_128,
ecdhe_rsa_aes_128_cbc,
ecdhe_rsa_aes_128_gcm,
@@ -141,8 +136,8 @@ groups() ->
ecdhe_rsa_chacha20_poly1305
]},
{ecdhe_1_3_rsa_cert, [], tls_1_3_cipher_suites()},
- {ecdhe_ecdsa, [],[ecdhe_ecdsa_rc4_128,
- ecdhe_ecdsa_3des_ede_cbc,
+ {ecdhe_ecdsa, [],[ecdhe_ecdsa_rc4_128,
+ ecdhe_ecdsa_3des_ede_cbc,
ecdhe_ecdsa_aes_128_cbc,
ecdhe_ecdsa_aes_128_gcm,
ecdhe_ecdsa_aes_256_cbc,
@@ -159,34 +154,34 @@ groups() ->
rsa_aes_256_cbc,
rsa_rc4_128
]},
- {dhe_dss, [], [dhe_dss_3des_ede_cbc,
+ {dhe_dss, [], [dhe_dss_3des_ede_cbc,
dhe_dss_aes_128_cbc,
dhe_dss_aes_256_cbc]},
- %% {srp_rsa, [], [srp_rsa_3des_ede_cbc,
+ %% {srp_rsa, [], [srp_rsa_3des_ede_cbc,
%% srp_rsa_aes_128_cbc,
%% srp_rsa_aes_256_cbc]},
- %% {srp_dss, [], [srp_dss_3des_ede_cbc,
+ %% {srp_dss, [], [srp_dss_3des_ede_cbc,
%% srp_dss_aes_128_cbc,
%% srp_dss_aes_256_cbc]},
- %% {rsa_psk, [], [rsa_psk_3des_ede_cbc,
+ %% {rsa_psk, [], [rsa_psk_3des_ede_cbc,
%% rsa_psk_rc4_128,
%% rsa_psk_aes_128_cbc,
%% rsa_psk_aes_256_cbc
%% ]},
{dh_anon, [], [dh_anon_rc4_128,
- dh_anon_3des_ede_cbc,
+ dh_anon_3des_ede_cbc,
dh_anon_aes_128_cbc,
dh_anon_aes_128_gcm,
dh_anon_aes_256_cbc,
dh_anon_aes_256_gcm]},
- {ecdh_anon, [], [ecdh_anon_3des_ede_cbc,
+ {ecdh_anon, [], [ecdh_anon_3des_ede_cbc,
ecdh_anon_aes_128_cbc,
ecdh_anon_aes_256_cbc
- ]}
- %% {srp_anon, [], [srp_anon_3des_ede_cbc,
+ ]}
+ %% {srp_anon, [], [srp_anon_3des_ede_cbc,
%% srp_anon_aes_128_cbc,
%% srp_anon_aes_256_cbc]},
- %% {psk, [], [psk_3des_ede_cbc,
+ %% {psk, [], [psk_3des_ede_cbc,
%% psk_rc4_128,
%% psk_aes_128_cbc,
%% psk_aes_128_ccm,
@@ -195,7 +190,7 @@ groups() ->
%% psk_aes_256_ccm,
%% psk_aes_256_ccm_8
%% ]},
- %% {dhe_psk, [], [dhe_psk_3des_ede_cbc,
+ %% {dhe_psk, [], [dhe_psk_3des_ede_cbc,
%% dhe_psk_rc4_128,
%% dhe_psk_aes_128_cbc,
%% dhe_psk_aes_128_ccm,
@@ -204,7 +199,7 @@ groups() ->
%% dhe_psk_aes_256_ccm,
%% dhe_psk_aes_256_ccm_8
%% ]},
- %% {ecdhe_psk, [], [ecdhe_psk_3des_ede_cbc,
+ %% {ecdhe_psk, [], [ecdhe_psk_3des_ede_cbc,
%% ecdhe_psk_rc4_128,
%% ecdhe_psk_aes_128_cbc,
%% ecdhe_psk_aes_128_ccm,
@@ -238,13 +233,13 @@ rsa() ->
dtls_rsa() ->
[
- {group, rsa}
+ {group, rsa}
%%,{group, rsa_psk}
].
ecdsa() ->
[{group, ecdhe_ecdsa}].
-
+
dss() ->
[{group, dhe_dss}
%%{group, srp_dss}
@@ -260,35 +255,31 @@ anonymous() ->
].
init_per_suite(Config) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
+ ssl_test_lib:init_per_suite(Config, openssl).
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
%%--------------------------------------------------------------------
init_per_group(GroupName, Config) ->
+ case ssl_test_lib:working_openssl_client(Config) of
+ false when GroupName =:= openssl_client ->
+ throw({skip, "Ignore non-working openssl_client"});
+ _ -> ok
+ end,
case ssl_test_lib:is_protocol_version(GroupName) of
true ->
ssl_test_lib:init_per_group_openssl(GroupName, Config);
false ->
do_init_per_group(GroupName, Config)
end.
-
+
do_init_per_group(openssl_client, Config0) ->
Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
[{client_type, openssl}, {server_type, erlang} | Config];
do_init_per_group(openssl_server, Config0) ->
Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
- [{client_type, erlang}, {server_type, openssl} | Config];
+ [{client_type, erlang}, {server_type, openssl} | Config];
do_init_per_group(GroupName, Config) when GroupName == ecdh_anon;
GroupName == ecdhe_rsa;
GroupName == ecdhe_psk;
@@ -318,7 +309,7 @@ do_init_per_group(dhe_dss = GroupName, Config) ->
end;
do_init_per_group(srp_dss = GroupName, Config) ->
PKAlg = proplists:get_value(public_keys, crypto:supports()),
- case lists:member(dss, PKAlg) andalso lists:member(srp, PKAlg)
+ case lists:member(dss, PKAlg) andalso lists:member(srp, PKAlg)
andalso (ssl_test_lib:openssl_dsa_suites() =/= []) of
true ->
init_certs(GroupName, Config);
@@ -386,9 +377,9 @@ init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
TestCase == ecdh_anon_3des_ede_cbc;
TestCase == ecdhe_ecdsa_3des_ede_cbc ->
SupCiphers = proplists:get_value(ciphers, crypto:supports()),
- case lists:member(des_ede3, SupCiphers) of
+ case lists:member(des_ede3_cbc, SupCiphers) of
true ->
- ct:timetrap({seconds, ?DEFAULT_TIMEOUT}),
+ ct:timetrap(?DEFAULT_TIMEOUT),
Config;
_ ->
{skip, "Missing 3DES crypto support"}
@@ -525,10 +516,10 @@ init_certs(srp_anon, Config) ->
proplists:delete(tls_config, Config)];
init_certs(rsa_psk, Config) ->
Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
- {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
[[ssl_test_lib:digest()],[ssl_test_lib:digest()],
[ssl_test_lib:digest(), {extensions, Ext}]]},
- {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
Config, "_peer_keyEncipherment"),
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
[{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}} | ServerOpts],
@@ -537,24 +528,24 @@ init_certs(rsa_psk, Config) ->
proplists:delete(tls_config, Config)];
init_certs(rsa, Config) ->
Ext = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
- {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
[[ssl_test_lib:digest()],[ssl_test_lib:digest()],
- [ssl_test_lib:digest(), {extensions, Ext}]]}
- ],
+ [ssl_test_lib:digest(), {extensions, Ext}]]}
+ ],
Config, "_peer_keyEncipherment"),
[{tls_config, #{server_config => ServerOpts,
client_config => ClientOpts}} |
proplists:delete(tls_config, Config)];
init_certs(dhe_dss, Config) ->
{ClientOpts, ServerOpts} = ssl_test_lib:make_dsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
- {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
Config, ""),
[{tls_config, #{server_config => ServerOpts,
client_config => ClientOpts}} |
proplists:delete(tls_config, Config)];
init_certs(srp_dss, Config) ->
{ClientOpts, ServerOpts} = ssl_test_lib:make_dsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
- {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
Config, ""),
[{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}} | ServerOpts],
client_config => [{srp_identity, {"Test-User", "secret"}} | ClientOpts]}} |
@@ -562,7 +553,7 @@ init_certs(srp_dss, Config) ->
init_certs(GroupName, Config) when GroupName == dhe_rsa;
GroupName == ecdhe_rsa ->
{ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
- {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
Config, ""),
[{tls_config, #{server_config => ServerOpts,
client_config => ClientOpts}} |
@@ -579,7 +570,7 @@ init_certs(ecdhe_1_3_rsa_cert, Config) ->
init_certs(GroupName, Config) when GroupName == dhe_ecdsa;
GroupName == ecdhe_ecdsa ->
{ClientOpts, ServerOpts} = ssl_test_lib:make_ecc_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
- {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
Config, ""),
[{tls_config, #{server_config => ServerOpts,
client_config => ClientOpts}} |
@@ -591,12 +582,12 @@ init_certs(GroupName, Config) when GroupName == psk;
[{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}],
client_config => [{psk_identity, "Test-User"},
{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, PskSharedSecret}}]}} |
- proplists:delete(tls_config, Config)];
-init_certs(srp, Config) ->
+ proplists:delete(tls_config, Config)];
+init_certs(srp, Config) ->
[{tls_config, #{server_config => [{user_lookup_fun, {fun ssl_test_lib:user_lookup/3, undefined}}],
client_config => [{srp_identity, {"Test-User", "secret"}}]}} |
proplists:delete(tls_config, Config)];
-init_certs(_GroupName, Config) ->
+init_certs(_GroupName, Config) ->
%% Anonymous does not need certs
[{tls_config, #{server_config => [],
client_config => []}} |
@@ -622,76 +613,76 @@ aes_128_ccm_8_sha256(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%% SRP --------------------------------------------------------
%%--------------------------------------------------------------------
-srp_rsa_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_rsa, '3des_ede_cbc', Config).
-
-srp_rsa_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_rsa, 'aes_128_cbc', Config).
+%% srp_rsa_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_rsa, '3des_ede_cbc', Config).
+
+%% srp_rsa_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_rsa, 'aes_128_cbc', Config).
-srp_rsa_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_rsa, 'aes_256_cbc', Config).
+%% srp_rsa_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_rsa, 'aes_256_cbc', Config).
-srp_dss_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_dss, '3des_ede_cbc', Config).
-
-srp_dss_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_dss, 'aes_128_cbc', Config).
+%% srp_dss_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_dss, '3des_ede_cbc', Config).
-srp_dss_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_dss, 'aes_256_cbc', Config).
+%% srp_dss_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_dss, 'aes_128_cbc', Config).
+
+%% srp_dss_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_dss, 'aes_256_cbc', Config).
%%--------------------------------------------------------------------
%% PSK --------------------------------------------------------
%%--------------------------------------------------------------------
-rsa_psk_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(rsa_psk, '3des_ede_cbc', Config).
-
-rsa_psk_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(rsa_psk, 'aes_128_cbc', Config).
-
-rsa_psk_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(rsa_psk, 'aes_256_cbc', Config).
-
-rsa_psk_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(rsa_psk, 'rc4_128', Config).
-
+%% rsa_psk_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(rsa_psk, '3des_ede_cbc', Config).
+
+%% rsa_psk_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(rsa_psk, 'aes_128_cbc', Config).
+
+%% rsa_psk_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(rsa_psk, 'aes_256_cbc', Config).
+
+%% rsa_psk_rc4_128(Config) when is_list(Config) ->
+%% run_ciphers_test(rsa_psk, 'rc4_128', Config).
+
%%--------------------------------------------------------------------
%% RSA --------------------------------------------------------
%%--------------------------------------------------------------------
rsa_des_cbc(Config) when is_list(Config) ->
- run_ciphers_test(rsa, 'des_cbc', Config).
+ run_ciphers_test(rsa, 'des_cbc', Config).
rsa_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(rsa, '3des_ede_cbc', Config).
+ run_ciphers_test(rsa, '3des_ede_cbc', Config).
rsa_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(rsa, 'aes_128_cbc', Config).
+ run_ciphers_test(rsa, 'aes_128_cbc', Config).
rsa_aes_256_cbc(Config) when is_list(Config) ->
run_ciphers_test(rsa, 'aes_256_cbc', Config).
rsa_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(rsa, 'aes_128_gcm', Config).
+ run_ciphers_test(rsa, 'aes_128_gcm', Config).
rsa_aes_256_gcm(Config) when is_list(Config) ->
run_ciphers_test(rsa, 'aes_256_gcm', Config).
rsa_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(rsa, 'rc4_128', Config).
+ run_ciphers_test(rsa, 'rc4_128', Config).
%%--------------------------------------------------------------------
%% DHE_RSA --------------------------------------------------------
%%--------------------------------------------------------------------
dhe_rsa_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_rsa, '3des_ede_cbc', Config).
+ run_ciphers_test(dhe_rsa, '3des_ede_cbc', Config).
dhe_rsa_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_rsa, 'aes_128_cbc', Config).
+ run_ciphers_test(dhe_rsa, 'aes_128_cbc', Config).
dhe_rsa_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(dhe_rsa, 'aes_128_gcm', Config).
+ run_ciphers_test(dhe_rsa, 'aes_128_gcm', Config).
dhe_rsa_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_rsa, 'aes_256_cbc', Config).
+ run_ciphers_test(dhe_rsa, 'aes_256_cbc', Config).
dhe_rsa_aes_256_gcm(Config) when is_list(Config) ->
run_ciphers_test(dhe_rsa, 'aes_256_gcm', Config).
@@ -702,22 +693,22 @@ dhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
%% ECDHE_RSA --------------------------------------------------------
%%--------------------------------------------------------------------
ecdhe_rsa_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_rsa, '3des_ede_cbc', Config).
+ run_ciphers_test(ecdhe_rsa, '3des_ede_cbc', Config).
ecdhe_rsa_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_rsa, 'aes_128_cbc', Config).
+ run_ciphers_test(ecdhe_rsa, 'aes_128_cbc', Config).
ecdhe_rsa_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_rsa, 'aes_128_gcm', Config).
+ run_ciphers_test(ecdhe_rsa, 'aes_128_gcm', Config).
ecdhe_rsa_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_rsa, 'aes_256_cbc', Config).
+ run_ciphers_test(ecdhe_rsa, 'aes_256_cbc', Config).
ecdhe_rsa_aes_256_gcm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_rsa, 'aes_256_gcm', Config).
+ run_ciphers_test(ecdhe_rsa, 'aes_256_gcm', Config).
ecdhe_rsa_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_rsa, 'rc4_128', Config).
+ run_ciphers_test(ecdhe_rsa, 'rc4_128', Config).
ecdhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
run_ciphers_test(ecdhe_rsa, 'chacha20_poly1305', Config).
@@ -726,54 +717,54 @@ ecdhe_rsa_chacha20_poly1305(Config) when is_list(Config) ->
%% ECDHE_ECDSA --------------------------------------------------------
%%--------------------------------------------------------------------
ecdhe_ecdsa_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'rc4_128', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'rc4_128', Config).
ecdhe_ecdsa_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, '3des_ede_cbc', Config).
+ run_ciphers_test(ecdhe_ecdsa, '3des_ede_cbc', Config).
ecdhe_ecdsa_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_128_cbc', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_cbc', Config).
ecdhe_ecdsa_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_128_gcm', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_gcm', Config).
ecdhe_ecdsa_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_256_cbc', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_cbc', Config).
ecdhe_ecdsa_aes_256_gcm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_256_gcm', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_gcm', Config).
ecdhe_ecdsa_chacha20_poly1305(Config) when is_list(Config) ->
run_ciphers_test(ecdhe_ecdsa, 'chacha20_poly1305', Config).
ecdhe_ecdsa_with_aes_128_ccm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_128_ccm', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_ccm', Config).
ecdhe_ecdsa_with_aes_256_ccm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_256_ccm', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_ccm', Config).
ecdhe_ecdsa_with_aes_128_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_128_ccm_8', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_128_ccm_8', Config).
ecdhe_ecdsa_with_aes_256_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_ecdsa, 'aes_256_ccm_8', Config).
+ run_ciphers_test(ecdhe_ecdsa, 'aes_256_ccm_8', Config).
%%--------------------------------------------------------------------
%% DHE_DSS --------------------------------------------------------
%%--------------------------------------------------------------------
dhe_dss_des_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_dss, 'des_cbc', Config).
+ run_ciphers_test(dhe_dss, 'des_cbc', Config).
dhe_dss_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_dss, '3des_ede_cbc', Config).
+ run_ciphers_test(dhe_dss, '3des_ede_cbc', Config).
dhe_dss_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_dss, 'aes_128_cbc', Config).
+ run_ciphers_test(dhe_dss, 'aes_128_cbc', Config).
dhe_dss_aes_256_cbc(Config) when is_list(Config) ->
run_ciphers_test(dhe_dss, 'aes_256_cbc', Config).
dhe_dss_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(dhe_dss, 'aes_128_gcm', Config).
+ run_ciphers_test(dhe_dss, 'aes_128_gcm', Config).
dhe_dss_aes_256_gcm(Config) when is_list(Config) ->
run_ciphers_test(dhe_dss, 'aes_256_gcm', Config).
@@ -782,144 +773,144 @@ dhe_dss_aes_256_gcm(Config) when is_list(Config) ->
%% Anonymous --------------------------------------------------------
%%--------------------------------------------------------------------
dh_anon_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dh_anon, '3des_ede_cbc', Config).
+ run_ciphers_test(dh_anon, '3des_ede_cbc', Config).
dh_anon_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dh_anon, 'aes_128_cbc', Config).
+ run_ciphers_test(dh_anon, 'aes_128_cbc', Config).
dh_anon_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(dh_anon, 'aes_128_gcm', Config).
+ run_ciphers_test(dh_anon, 'aes_128_gcm', Config).
dh_anon_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dh_anon, 'aes_256_cbc', Config).
+ run_ciphers_test(dh_anon, 'aes_256_cbc', Config).
dh_anon_aes_256_gcm(Config) when is_list(Config) ->
- run_ciphers_test(dh_anon, 'aes_256_gcm', Config).
+ run_ciphers_test(dh_anon, 'aes_256_gcm', Config).
dh_anon_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(dh_anon, 'rc4_128', Config).
+ run_ciphers_test(dh_anon, 'rc4_128', Config).
ecdh_anon_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdh_anon, '3des_ede_cbc', Config).
+ run_ciphers_test(ecdh_anon, '3des_ede_cbc', Config).
ecdh_anon_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdh_anon, 'aes_128_cbc', Config).
+ run_ciphers_test(ecdh_anon, 'aes_128_cbc', Config).
ecdh_anon_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdh_anon, 'aes_256_cbc', Config).
+ run_ciphers_test(ecdh_anon, 'aes_256_cbc', Config).
-srp_anon_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_anon, '3des_ede_cbc', Config).
-
-srp_anon_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_anon, 'aes_128_cbc', Config).
+%% srp_anon_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_anon, '3des_ede_cbc', Config).
-srp_anon_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(srp_anon, 'aes_256_cbc', Config).
+%% srp_anon_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_anon, 'aes_128_cbc', Config).
-dhe_psk_des_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'des_cbc', Config).
+%% srp_anon_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(srp_anon, 'aes_256_cbc', Config).
-dhe_psk_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'rc4_128', Config).
+%% dhe_psk_des_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'des_cbc', Config).
-dhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, '3des_ede_cbc', Config).
+%% dhe_psk_rc4_128(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'rc4_128', Config).
-dhe_psk_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_128_cbc', Config).
+%% dhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, '3des_ede_cbc', Config).
-dhe_psk_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_256_cbc', Config).
+%% dhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_128_cbc', Config).
-dhe_psk_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_128_gcm', Config).
+%% dhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_256_cbc', Config).
-dhe_psk_aes_256_gcm(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_256_gcm', Config).
+%% dhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_128_gcm', Config).
-dhe_psk_aes_128_ccm(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_128_ccm', Config).
+%% dhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_256_gcm', Config).
-dhe_psk_aes_256_ccm(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_256_ccm', Config).
+%% dhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_128_ccm', Config).
-dhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_128_ccm_8', Config).
+%% dhe_psk_aes_256_ccm(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_256_ccm', Config).
-dhe_psk_aes_256_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(dhe_psk, 'aes_256_ccm_8', Config).
+%% dhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_128_ccm_8', Config).
-ecdhe_psk_des_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'des_cbc', Config).
+%% dhe_psk_aes_256_ccm_8(Config) when is_list(Config) ->
+%% run_ciphers_test(dhe_psk, 'aes_256_ccm_8', Config).
-ecdhe_psk_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'rc4_128', Config).
+%% ecdhe_psk_des_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'des_cbc', Config).
-ecdhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, '3des_ede_cbc', Config).
+%% ecdhe_psk_rc4_128(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'rc4_128', Config).
-ecdhe_psk_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'aes_128_cbc', Config).
+%% ecdhe_psk_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, '3des_ede_cbc', Config).
-ecdhe_psk_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'aes_256_cbc', Config).
+%% ecdhe_psk_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'aes_128_cbc', Config).
-ecdhe_psk_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'aes_128_gcm', Config).
+%% ecdhe_psk_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'aes_256_cbc', Config).
-ecdhe_psk_aes_256_gcm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'aes_256_gcm', Config).
+%% ecdhe_psk_aes_128_gcm(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'aes_128_gcm', Config).
-ecdhe_psk_aes_128_ccm(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'aes_128_ccm', Config).
+%% ecdhe_psk_aes_256_gcm(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'aes_256_gcm', Config).
-ecdhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(ecdhe_psk, 'aes_128_ccm_8', Config).
+%% ecdhe_psk_aes_128_ccm(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'aes_128_ccm', Config).
-psk_des_cbc(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'des_cbc', Config).
+%% ecdhe_psk_aes_128_ccm_8(Config) when is_list(Config) ->
+%% run_ciphers_test(ecdhe_psk, 'aes_128_ccm_8', Config).
-psk_rc4_128(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'rc4_128', Config).
+%% psk_des_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'des_cbc', Config).
-psk_3des_ede_cbc(Config) when is_list(Config) ->
- run_ciphers_test(psk, '3des_ede_cbc', Config).
+%% psk_rc4_128(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'rc4_128', Config).
-psk_aes_128_cbc(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_128_cbc', Config).
+%% psk_3des_ede_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, '3des_ede_cbc', Config).
-psk_aes_256_cbc(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_256_cbc', Config).
+%% psk_aes_128_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_128_cbc', Config).
-psk_aes_128_gcm(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_128_gcm', Config).
+%% psk_aes_256_cbc(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_256_cbc', Config).
-psk_aes_256_gcm(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_256_gcm', Config).
+%% psk_aes_128_gcm(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_128_gcm', Config).
-psk_aes_128_ccm(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_128_ccm', Config).
+%% psk_aes_256_gcm(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_256_gcm', Config).
-psk_aes_256_ccm(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_256_ccm', Config).
+%% psk_aes_128_ccm(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_128_ccm', Config).
-psk_aes_128_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_128_ccm_8', Config).
+%% psk_aes_256_ccm(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_256_ccm', Config).
-psk_aes_256_ccm_8(Config) when is_list(Config) ->
- run_ciphers_test(psk, 'aes_256_ccm_8', Config).
+%% psk_aes_128_ccm_8(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_128_ccm_8', Config).
+
+%% psk_aes_256_ccm_8(Config) when is_list(Config) ->
+%% run_ciphers_test(psk, 'aes_256_ccm_8', Config).
%%--------------------------------------------------------------------
%% Internal functions ----------------------------------------------
%%--------------------------------------------------------------------
run_ciphers_test(Kex, Cipher, Config) ->
Version = ssl_test_lib:protocol_version(Config),
- TestCiphers = test_ciphers(Kex, Cipher, Version),
-
+ TestCiphers = test_ciphers(Kex, Cipher, Version),
+
case TestCiphers of
- [_|_] ->
- lists:foreach(fun(TestCipher) ->
+ [_|_] ->
+ lists:foreach(fun(TestCipher) ->
cipher_suite_test(TestCipher, Version, Config)
end, TestCiphers);
[] ->
@@ -936,15 +927,15 @@ cipher_suite_test(CipherSuite, Version, Config) ->
ct:log("Client Opts ~p~n", [ClientOpts]),
case proplists:get_value(server_type, Config) of
erlang ->
- ssl_test_lib:basic_test([{ciphers, ssl:cipher_suites(all, Version)} | COpts],
+ ssl_test_lib:basic_test([{ciphers, ssl:cipher_suites(all, Version)} | COpts],
[{ciphers, [CipherSuite]} | SOpts], Config);
_ ->
- ssl_test_lib:basic_test([{versions, [Version]}, {ciphers, [CipherSuite]} | COpts],
+ ssl_test_lib:basic_test([{versions, [Version]}, {ciphers, [CipherSuite]} | COpts],
[{ciphers, ssl_test_lib:openssl_ciphers()} | SOpts], Config)
end.
test_ciphers(Kex, Cipher, Version) ->
- Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, Version) ++ ssl:cipher_suites(anonymous, Version),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, Version) ++ ssl:cipher_suites(anonymous, Version),
[{key_exchange,
fun(Kex0) when (Kex0 == Kex) andalso (Version =/= 'tlsv1.3') -> true;
(Kex0) when (Kex0 == any) andalso (Version == 'tlsv1.3') -> true;
diff --git a/lib/ssl/test/openssl_client_cert_SUITE.erl b/lib/ssl/test/openssl_client_cert_SUITE.erl
index 43db4bad42..018b49e0b7 100644
--- a/lib/ssl/test/openssl_client_cert_SUITE.erl
+++ b/lib/ssl/test/openssl_client_cert_SUITE.erl
@@ -44,12 +44,10 @@
client_auth_empty_cert_accepted/1,
client_auth_empty_cert_rejected/0,
client_auth_empty_cert_rejected/1,
- client_auth_partial_chain/0,
- client_auth_partial_chain/1,
- client_auth_allow_partial_chain/0,
- client_auth_allow_partial_chain/1,
- client_auth_do_not_allow_partial_chain/0,
- client_auth_do_not_allow_partial_chain/1,
+ client_auth_use_partial_chain/0,
+ client_auth_use_partial_chain/1,
+ client_auth_do_not_use_partial_chain/0,
+ client_auth_do_not_use_partial_chain/1,
client_auth_partial_chain_fun_fail/0,
client_auth_partial_chain_fun_fail/1,
missing_root_cert_no_auth/0,
@@ -144,32 +142,21 @@ all_version_tests() ->
auth,
client_auth_empty_cert_accepted,
client_auth_empty_cert_rejected,
- client_auth_partial_chain,
- client_auth_allow_partial_chain,
- client_auth_do_not_allow_partial_chain,
+ client_auth_use_partial_chain,
+ client_auth_do_not_use_partial_chain,
client_auth_partial_chain_fun_fail,
missing_root_cert_no_auth
].
-init_per_suite(Config) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- case ssl_test_lib:working_openssl_client() of
- true ->
- ssl_test_lib:clean_start(),
- Config;
- false ->
- {skip, "Broken OpenSSL s_client"}
- end
- catch _:_ ->
- {skip, "Crypto did not start"}
+init_per_suite(Config0) ->
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ case ssl_test_lib:working_openssl_client(Config) of
+ true -> Config;
+ false -> throw({skip, "Broken OpenSSL s_client"})
end.
-end_per_suite(_Config) ->
- ssl:stop(),
- application:unload(ssl),
- application:stop(crypto).
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(openssl_client, Config) ->
[{client_type, openssl}, {server_type, erlang} | Config];
@@ -374,27 +361,87 @@ client_auth_empty_cert_rejected() ->
client_auth_empty_cert_rejected(Config) ->
ssl_cert_tests:client_auth_empty_cert_rejected(Config).
%%--------------------------------------------------------------------
-client_auth_partial_chain() ->
- ssl_cert_tests:client_auth_partial_chain().
-client_auth_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_partial_chain(Config).
-
-%%--------------------------------------------------------------------
-client_auth_allow_partial_chain() ->
- ssl_cert_tests:client_auth_allow_partial_chain().
-client_auth_allow_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_allow_partial_chain(Config).
+%% Have to use partial chain functionality on side running Erlang (we are not testing OpenSSL features)
+client_auth_use_partial_chain() ->
+ [{doc, "Server does not trust an intermediat CA and fails the connetion as ROOT has expired"}].
+client_auth_use_partial_chain(Config) when is_list(Config) ->
+ Prop = proplists:get_value(tc_group_properties, Config),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
+ {Year, Month, Day} = date(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_pem(proplists:get_value(cert_key_alg, Config),
+ [{client_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {server_chain, DefaultCertConf}],
+ Config, "use_partial_chain"),
+ ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
+ CaCertsFile = proplists:get_value(cacertfile, ClientOpts),
+ ClientCACerts = [DerCA || {'Certificate', DerCA, _} <- ssl_test_lib:pem_to_der(CaCertsFile)],
+ [_, IntermidiateCA, _] = ClientCACerts,
+ PartialChain = fun(CertChain) ->
+ case lists:member(IntermidiateCA, CertChain) of
+ true ->
+ {trusted_ca, IntermidiateCA};
+ false ->
+ unknown_ca
+ end
+ end,
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}, {partial_chain, PartialChain} |
+ ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
-client_auth_do_not_allow_partial_chain() ->
- ssl_cert_tests:client_auth_do_not_allow_partial_chain().
-client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_do_not_allow_partial_chain(Config).
+%% Have to use partial chain functionality on side running Erlang (we are not testing OpenSSL features)
+client_auth_do_not_use_partial_chain() ->
+ ssl_cert_tests:client_auth_do_not_use_partial_chain().
+client_auth_do_not_use_partial_chain(Config) when is_list(Config) ->
+ Prop = proplists:get_value(tc_group_properties, Config),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
+ {Year, Month, Day} = date(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_pem(proplists:get_value(cert_key_alg, Config),
+ [{client_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {server_chain, DefaultCertConf}], Config, "do_not_use_partial_chain"),
+ PartialChain = fun(_CertChain) ->
+ unknown_ca
+ end,
+ ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}, {partial_chain, PartialChain} |
+ ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_expired).
%%--------------------------------------------------------------------
+%% Have to use partial chain functionality on side running Erlang (we are not testing OpenSSL features)
client_auth_partial_chain_fun_fail() ->
ssl_cert_tests:client_auth_partial_chain_fun_fail().
client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_partial_chain_fun_fail(Config).
+ Prop = proplists:get_value(tc_group_properties, Config),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
+ {Year, Month, Day} = date(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_pem(proplists:get_value(cert_key_alg, Config),
+ [{client_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {server_chain, DefaultCertConf}], Config, "do_not_use_partial_chain"),
+ PartialChain = fun(_CertChain) ->
+ error(crash_on_purpose)
+ end,
+ ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}, {partial_chain, PartialChain} |
+ ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_expired).
%%--------------------------------------------------------------------
missing_root_cert_no_auth() ->
diff --git a/lib/ssl/test/openssl_key_update_SUITE.erl b/lib/ssl/test/openssl_key_update_SUITE.erl
index 55e302dd69..d24f42a297 100644
--- a/lib/ssl/test/openssl_key_update_SUITE.erl
+++ b/lib/ssl/test/openssl_key_update_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,24 +48,17 @@ tls_1_3_tests() ->
openssl_server_explicit_key_update].
init_per_suite(Config0) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of
- true ->
- ssl_test_lib:make_ecdsa_cert(Config0);
- false ->
- {skip, "Missing EC crypto support"}
- end
- catch _:_ ->
- {skip, "Crypto did not start"}
+ Config1 = ssl_test_lib:init_per_suite(Config0, openssl),
+ case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports()))
+ of
+ true ->
+ ssl_test_lib:make_ecdsa_cert(Config1);
+ false ->
+ {skip, "Missing EC crypto support"}
end.
-end_per_suite(_Config) ->
- ssl:stop(),
- application:unload(ssl),
- application:stop(crypto).
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -92,7 +85,7 @@ openssl_client_explicit_key_update() ->
openssl_client_explicit_key_update(Config) ->
Data = "123456789012345", %% 15 bytes
- Server = ssl_test_lib:start_server(erlang, [{log_level, debug}], Config),
+ Server = ssl_test_lib:start_server(erlang, [], Config),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client(openssl, [{port, Port}], Config),
@@ -120,7 +113,6 @@ openssl_server_explicit_key_update(Config) ->
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client(erlang, [{port, Port},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],Config),
ssl_test_lib:send(Server, Data),
Data = ssl_test_lib:check_active_receive(Client, Data),
diff --git a/lib/ssl/test/openssl_mfl_SUITE.erl b/lib/ssl/test/openssl_mfl_SUITE.erl
index c26934082a..54a6788966 100644
--- a/lib/ssl/test/openssl_mfl_SUITE.erl
+++ b/lib/ssl/test/openssl_mfl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -38,26 +38,21 @@
reuse_session_erlang_server/1,
reuse_session_erlang_client/1]).
+
+-export([session_id_and_data/3]).
+
-define(SLEEP, 500).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- case ssl_test_lib:openssl_dtls_maxfraglen_support() of
- true ->
- [{group, 'tlsv1.3'},
- {group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'dtlsv1.2'},
- {group, 'dtlsv1'}];
- false ->
- [{group, 'tlsv1.3'},
- {group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'}]
- end.
+ [{group, 'tlsv1.3'},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}].
groups() ->
[{'tlsv1.3', [], common_tests()},
@@ -69,25 +64,17 @@ groups() ->
].
init_per_suite(Config0) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- case ssl_test_lib:openssl_maxfraglen_support() of
- true ->
- ssl_test_lib:clean_start(),
- ssl:clear_pem_cache(),
- Config = ssl_test_lib:make_rsa_cert(Config0),
- ssl_test_lib:cert_options(Config);
- false ->
- {skip, "max_fragment_length not supported by OpenSSL"}
- end
- catch _:_ ->
- {skip, "Crypto did not start"}
+ Config1 = ssl_test_lib:init_per_suite(Config0, openssl),
+ case ssl_test_lib:openssl_maxfraglen_support() of
+ true ->
+ Config = ssl_test_lib:make_rsa_cert(Config1),
+ ssl_test_lib:cert_options(Config);
+ false ->
+ {skip, "max_fragment_length not supported by OpenSSL"}
end.
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto).
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -125,12 +112,10 @@ openssl_client(Config) when is_list(Config) ->
reuse_session_erlang_server(Config) when is_list(Config) ->
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ClientOpts = proplists:get_value(client_rsa_opts, Config),
-
+ Protocol = proplists:get_value(protocol, ServerOpts, tls),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
-
MFL = 512,
- Data = "reuse_session_erlang_server " ++ lists:duplicate(MFL, $r),
-
+ Data = max_frag_data(Protocol, MFL),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, active_recv, [length(Data)]}},
@@ -153,9 +138,9 @@ reuse_session_erlang_client(Config) when is_list(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = proplists:get_value(server_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
+ Protocol = proplists:get_value(protocol, ClientOpts0, tls),
MFL = 512,
- Data = "reuse_session_erlang_client " ++ lists:duplicate(MFL, $r),
+ Data = max_frag_data(Protocol, MFL),
ClientOpts = [{max_fragment_length, MFL} | ClientOpts0],
{Server, OpenSSLPort} = ssl_test_lib:start_server(openssl, [{maxfrag, MFL}, return_port],
@@ -175,14 +160,12 @@ reuse_session_erlang_client(Config) when is_list(Config) ->
Id0
end,
- %% quit s_server's current session so we can interact with the next client
- true = port_command(OpenSSLPort, "q\n"),
ssl_test_lib:close(Client0),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, session_id, []}},
+ {mfa, {?MODULE, session_id_and_data, [self(), length(Data)]}},
{from, self()}, {options, [{reuse_session, SID} | ClientOpts]}]),
receive
{Client1, SID} ->
@@ -191,25 +174,24 @@ reuse_session_erlang_client(Config) when is_list(Config) ->
ct:fail(session_not_reused)
end,
- ErlRecvFun = fun() ->
- Data = ssl_test_lib:check_active_receive(Client1, Data)
- end,
- max_frag_len_test(Client1, OpenSSLPort, MFL, Data, ErlRecvFun),
+ max_frag_len_test(Client1, OpenSSLPort, MFL, Data),
ssl_test_lib:close(Client1).
openssl_client(MFL, Config) ->
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ClientOpts = proplists:get_value(client_rsa_opts, Config),
+ Protocol = proplists:get_value(protocol, ServerOpts, tls),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
- Data = "mfl_openssl_server " ++ lists:duplicate(MFL, $s),
+ Data = max_frag_data(Protocol, MFL),
+
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, active_recv, [length(Data)]}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
-
+
{_Client, OpenSSLPort} = ssl_test_lib:start_client(openssl, [{port, Port},
{maxfrag, MFL},
{options, ClientOpts},
@@ -224,40 +206,49 @@ openssl_client(MFL, Config) ->
openssl_server(MFL, Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = proplists:get_value(server_rsa_opts, Config),
+ Protocol = proplists:get_value(protocol, ClientOpts, tls),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- Data = "mfl_openssl_server " ++ lists:duplicate(MFL, $s),
+
+ Data = max_frag_data(Protocol, MFL),
{Server, OpenSSLPort} = ssl_test_lib:start_server(openssl, [{maxfrag, MFL},
return_port],
[{server_opts, ServerOpts} | Config]),
Port = ssl_test_lib:inet_port(Server),
-
+
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib,
active_recv, [length(Data)]}},
{options, [{max_fragment_length, MFL} | ClientOpts]}]),
-
+
max_frag_len_test(Client, OpenSSLPort, MFL, Data).
%% ------------------------------------------------------------
max_frag_len_test(ErlProc, OpenSSL, MFL, Data) ->
- ErlRecvFun = fun() ->
- receive
- {ErlProc, Data} ->
- ok
- end
- end,
- max_frag_len_test(ErlProc, OpenSSL, MFL, Data, ErlRecvFun).
-
-max_frag_len_test(ErlProc, OpenSSL, MFL, Data, ErlRecvFun) ->
- true = port_command(OpenSSL, Data),
- ErlRecvFun(),
-
+ openssl_send(OpenSSL, Data),
+ receive
+ {ErlProc, Data} ->
+ ok
+ end,
ErlProc ! get_socket,
ErlSocket = receive
{ErlProc, {socket, ErlSocket0}} ->
ErlSocket0
end,
ssl_test_lib:assert_mfl(ErlSocket, MFL).
+
+session_id_and_data(Socket, Pid, Len) ->
+ {ok, [{session_id, ID}]} = ssl:connection_information(Socket, [session_id]),
+ Pid ! {self(), ID},
+ ssl_test_lib:active_recv(Socket, Len).
+
+max_frag_data(tls, MaxFragLen) ->
+ "Send more data than max frag length " ++ lists:duplicate(MaxFragLen, $s);
+max_frag_data(dtls, _MaxFragLen) ->
+ "Send small data as OpenSSL s_client/s_server does not create UDP packets "
+ "with appropriate fragments".
+
+openssl_send(OpenSSL, Data) ->
+ port_command(OpenSSL, Data).
diff --git a/lib/ssl/test/openssl_npn_SUITE.erl b/lib/ssl/test/openssl_npn_SUITE.erl
index dbeef3d2f8..ccfd6e45c0 100644
--- a/lib/ssl/test/openssl_npn_SUITE.erl
+++ b/lib/ssl/test/openssl_npn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -82,31 +82,16 @@ npn_renegotiate_tests() ->
].
init_per_suite(Config0) ->
- case os:find_executable("openssl") of
+ Config1 = ssl_test_lib:init_per_suite(Config0, openssl),
+ case ssl_test_lib:check_openssl_npn_support(Config1) of
+ true ->
+ ssl_test_lib:make_rsa_cert(Config1);
false ->
- {skip, "Openssl not found"};
- _ ->
- case ssl_test_lib:check_openssl_npn_support(Config0) of
- {skip, _} = Skip ->
- Skip;
- _ ->
- ct:pal("Version: ~p", [os:cmd("openssl version")]),
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- ssl:clear_pem_cache(),
- ssl_test_lib:make_rsa_cert(Config0)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
- end
+ {skip, "npn_not_supported"}
end.
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
diff --git a/lib/ssl/test/openssl_ocsp_SUITE.erl b/lib/ssl/test/openssl_ocsp_SUITE.erl
index 888a0ab3c4..800ce3ce78 100644
--- a/lib/ssl/test/openssl_ocsp_SUITE.erl
+++ b/lib/ssl/test/openssl_ocsp_SUITE.erl
@@ -70,8 +70,9 @@ ocsp_tests() ->
].
%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- case ssl_test_lib:openssl_ocsp_support() of
+init_per_suite(Config0) ->
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ case ssl_test_lib:openssl_ocsp_support(Config) of
true ->
do_init_per_suite(Config);
false ->
@@ -79,38 +80,28 @@ init_per_suite(Config) ->
end.
do_init_per_suite(Config) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- DataDir = proplists:get_value(data_dir, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
- %% Prepare certs
- {ok, _} = make_certs:all(DataDir, PrivDir),
+ %% Prepare certs
+ {ok, _} = make_certs:all(DataDir, PrivDir),
- ResponderPort = get_free_port(),
- Pid = start_ocsp_responder(ResponderPort, PrivDir),
+ ResponderPort = get_free_port(),
+ Pid = start_ocsp_responder(ResponderPort, PrivDir),
- NewConfig =
+ NewConfig =
lists:merge(
- [{responder_port, ResponderPort},
- {responder_pid, Pid}
- ], Config),
+ [{responder_port, ResponderPort},
+ {responder_pid, Pid}
+ ], Config),
- ssl_test_lib:cert_options(NewConfig)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
+ ssl_test_lib:cert_options(NewConfig).
end_per_suite(Config) ->
ResponderPid = proplists:get_value(responder_pid, Config),
ssl_test_lib:close(ResponderPid),
- ok = ssl:stop(),
- %% terminate OpenSSL processes (OCSP responder in particular)
- ssl_test_lib:kill_openssl(),
- application:stop(crypto).
+ ssl_test_lib:end_per_suite(Config).
%%--------------------------------------------------------------------
init_per_group(GroupName, Config) ->
diff --git a/lib/ssl/test/openssl_reject_SUITE.erl b/lib/ssl/test/openssl_reject_SUITE.erl
index 962ed8f831..35d165f155 100644
--- a/lib/ssl/test/openssl_reject_SUITE.erl
+++ b/lib/ssl/test/openssl_reject_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,8 +36,6 @@
%% Test cases
-export([erlang_client_bad_openssl_server/0,
erlang_client_bad_openssl_server/1,
- erlang_server_reject_sslv2/0,
- erlang_server_reject_sslv2/1,
erlang_server_reject_sslv3/0,
erlang_server_reject_sslv3/1
]).
@@ -54,7 +52,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-all() ->
+all() ->
[{group, 'tlsv1.3'},
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
@@ -72,30 +70,15 @@ groups() ->
all_versions_tests() ->
[
erlang_client_bad_openssl_server,
- erlang_server_reject_sslv2,
erlang_server_reject_sslv3
].
init_per_suite(Config0) ->
- case os:find_executable("openssl") of
- false ->
- {skip, "Openssl not found"};
- _ ->
- ct:pal("Version: ~p", [os:cmd("openssl version")]),
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- ssl_test_lib:make_rsa_cert(Config0)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
- end.
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ ssl_test_lib:make_rsa_cert(Config).
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -108,14 +91,14 @@ init_per_testcase(TestCase, Config) ->
special_init(TestCase, Config).
special_init(erlang_server_reject_sslv2, Config) ->
- case ssl_test_lib:check_sane_openssl_version(sslv2) of
+ case ssl_test_lib:check_sane_openssl_version(sslv2, Config) of
true ->
Config;
false ->
{skip, "sslv2 not supported by openssl"}
end;
special_init(erlang_server_reject_sslv3, Config) ->
- case ssl_test_lib:check_sane_openssl_version(sslv3) of
+ case ssl_test_lib:check_sane_openssl_version(sslv3, Config) of
true ->
Config;
false ->
@@ -147,11 +130,11 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
Exe = "openssl",
Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
"-cert", CertFile, "-key", KeyFile],
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
- Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {?MODULE, server_sent_garbage, []}},
@@ -183,32 +166,6 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, false).
%%--------------------------------------------------------------------
-erlang_server_reject_sslv2() ->
- [{doc,"Test that ssl v2 clients are rejected"}].
-
-erlang_server_reject_sslv2(Config) when is_list(Config) ->
- process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
- {from, self()},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
-
- Exe = "openssl",
- Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- "-ssl2", "-msg"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
- ssl_test_lib:consume_port_exit(OpenSslPort),
- ssl_test_lib:check_server_alert(Server, unexpected_message),
- process_flag(trap_exit, false).
-
-%%--------------------------------------------------------------------
erlang_server_reject_sslv3() ->
[{doc,"Test that ssl v3 clients are rejected"}].
@@ -218,18 +175,19 @@ erlang_server_reject_sslv3(Config) when is_list(Config) ->
{_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Exe = "openssl",
- Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ Args = ["s_client", "-connect", ssl_test_lib:hostname_format(Hostname) ++
+ ":" ++ integer_to_list(Port),
"-ssl3", "-msg"],
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
+ ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
ssl_test_lib:consume_port_exit(OpenSslPort),
ssl_test_lib:check_server_alert(Server, protocol_version),
process_flag(trap_exit, false).
@@ -239,8 +197,7 @@ erlang_server_reject_sslv3(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
server_sent_garbage(Socket) ->
- receive
+ receive
server_sent_garbage ->
{error, closed} == ssl:send(Socket, "data")
-
end.
diff --git a/lib/ssl/test/openssl_renegotiate_SUITE.erl b/lib/ssl/test/openssl_renegotiate_SUITE.erl
index 1b8769f2fd..01b5a7a8a9 100644
--- a/lib/ssl/test/openssl_renegotiate_SUITE.erl
+++ b/lib/ssl/test/openssl_renegotiate_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -98,28 +98,14 @@ all_versions_tests() ->
init_per_suite(Config0) ->
- case os:find_executable("openssl") of
- false ->
- {skip, "Openssl not found"};
- _ ->
- ct:pal("Version: ~p", [os:cmd("openssl version")]),
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- ssl_test_lib:make_rsa_cert(Config0)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
- end.
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ ssl_test_lib:make_rsa_cert(Config).
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
- case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ case ssl_test_lib:check_sane_openssl_version(GroupName, Config) of
true ->
case ssl_test_lib:check_sane_openssl_renegotiate(Config, GroupName) of
{skip,_} = Skip ->
diff --git a/lib/ssl/test/openssl_server_cert_SUITE.erl b/lib/ssl/test/openssl_server_cert_SUITE.erl
index 701de76461..7f7a9b739e 100644
--- a/lib/ssl/test/openssl_server_cert_SUITE.erl
+++ b/lib/ssl/test/openssl_server_cert_SUITE.erl
@@ -47,10 +47,10 @@
client_auth_empty_cert_rejected/1,
client_auth_partial_chain/0,
client_auth_partial_chain/1,
- client_auth_allow_partial_chain/0,
- client_auth_allow_partial_chain/1,
- client_auth_do_not_allow_partial_chain/0,
- client_auth_do_not_allow_partial_chain/1,
+ client_auth_use_partial_chain/0,
+ client_auth_use_partial_chain/1,
+ client_auth_do_not_use_partial_chain/0,
+ client_auth_do_not_use_partial_chain/1,
client_auth_partial_chain_fun_fail/0,
client_auth_partial_chain_fun_fail/1,
missing_root_cert_no_auth/0,
@@ -149,19 +149,10 @@ all_version_tests() ->
].
init_per_suite(Config) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- Config
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
+ ssl_test_lib:init_per_suite(Config, openssl).
-end_per_suite(_Config) ->
- ssl:stop(),
- application:unload(ssl),
- application:stop(crypto).
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(openssl_server, Config0) ->
Config = proplists:delete(server_type, proplists:delete(client_type, Config0)),
@@ -350,7 +341,17 @@ init_per_group(dsa = Group, Config0) ->
{skip, "Missing DSS crypto support"}
end;
init_per_group(GroupName, Config) ->
- ssl_test_lib:init_per_group_openssl(GroupName, Config).
+ case ssl_test_lib:is_protocol_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName, Config) of
+ true ->
+ ssl_test_lib:init_per_group_openssl(GroupName, Config);
+ false ->
+ {skip, {atom_to_list(GroupName) ++ " not supported by OpenSSL"}}
+ end;
+ false ->
+ Config
+ end.
end_per_group(GroupName, Config) ->
ssl_test_lib:end_per_group(GroupName, Config).
@@ -394,15 +395,15 @@ client_auth_partial_chain(Config) when is_list(Config) ->
ssl_cert_tests:client_auth_partial_chain(Config).
%%--------------------------------------------------------------------
-client_auth_allow_partial_chain() ->
- ssl_cert_tests:client_auth_allow_partial_chain().
-client_auth_allow_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_allow_partial_chain(Config).
+client_auth_use_partial_chain() ->
+ ssl_cert_tests:client_auth_use_partial_chain().
+client_auth_use_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_use_partial_chain(Config).
%%--------------------------------------------------------------------
-client_auth_do_not_allow_partial_chain() ->
- ssl_cert_tests:client_auth_do_not_allow_partial_chain().
-client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_do_not_allow_partial_chain(Config).
+client_auth_do_not_use_partial_chain() ->
+ ssl_cert_tests:client_auth_do_not_use_partial_chain().
+client_auth_do_not_use_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_do_not_use_partial_chain(Config).
%%--------------------------------------------------------------------
client_auth_partial_chain_fun_fail() ->
diff --git a/lib/ssl/test/openssl_session_SUITE.erl b/lib/ssl/test/openssl_session_SUITE.erl
index 92568716f3..935c98dd5d 100644
--- a/lib/ssl/test/openssl_session_SUITE.erl
+++ b/lib/ssl/test/openssl_session_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -86,29 +86,15 @@ tests() ->
init_per_suite(Config0) ->
- case os:find_executable("openssl") of
- false ->
- {skip, "Openssl not found"};
- _ ->
- ct:pal("Version: ~p", [os:cmd("openssl version")]),
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- {ClientOpts, ServerOpts} =
- ssl_test_lib:make_rsa_cert_chains([{server_chain, ssl_test_lib:default_cert_chain_conf()},
- {client_chain, ssl_test_lib:default_cert_chain_conf()}],
- Config0, "openssl_session_SUITE"),
- [{client_opts, ClientOpts}, {server_opts, ServerOpts} | Config0]
- catch _:_ ->
- {skip, "Crypto did not start"}
- end
- end.
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains(
+ [{server_chain, ssl_test_lib:default_cert_chain_conf()},
+ {client_chain, ssl_test_lib:default_cert_chain_conf()}],
+ Config, "openssl_session_SUITE"),
+ [{client_opts, ClientOpts}, {server_opts, ServerOpts} | Config].
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -124,7 +110,7 @@ init_per_testcase(reuse_session_erlang_client, Config) ->
ssl:start(),
Config;
init_per_testcase(reuse_session_erlang_server, Config) ->
- case ssl_test_lib:working_openssl_client() of
+ case ssl_test_lib:working_openssl_client(Config) of
true ->
Version = ssl_test_lib:protocol_version(Config),
case ssl_test_lib:is_dtls_version(Version) of
diff --git a/lib/ssl/test/openssl_session_ticket_SUITE.erl b/lib/ssl/test/openssl_session_ticket_SUITE.erl
index 5e6b32427d..caff7458d4 100644
--- a/lib/ssl/test/openssl_session_ticket_SUITE.erl
+++ b/lib/ssl/test/openssl_session_ticket_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -93,18 +93,11 @@ session_tests() ->
openssl_client_early_data_basic].
init_per_suite(Config0) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- ssl_test_lib:make_rsa_cert(Config0)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
-
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto).
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ ssl_test_lib:make_rsa_cert(Config).
+
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(stateful, Config) ->
[{server_ticket_mode, stateful} | proplists:delete(server_ticket_mode, Config)];
@@ -138,7 +131,7 @@ openssl_server_basic(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
Server = ssl_test_lib:start_server(openssl, [],
@@ -184,7 +177,7 @@ openssl_client_basic(Config) when is_list(Config) ->
Data = "Hello world",
%% Configure session tickets
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
+ ServerOpts = [{session_tickets, ServerTicketMode},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
@@ -231,7 +224,7 @@ openssl_server_hrr(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups,[secp256r1, x25519]}|ClientOpts0],
@@ -279,7 +272,7 @@ openssl_client_hrr(Config) when is_list(Config) ->
Data = "Hello world",
%% Configure session tickets
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
+ ServerOpts = [{session_tickets, ServerTicketMode},
{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups,[x448, x25519]}|ServerOpts0],
@@ -333,7 +326,7 @@ openssl_server_hrr_multiple_tickets(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups,[secp256r1, x25519]}|ClientOpts0],
@@ -380,7 +373,7 @@ openssl_server_early_data_basic(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
ClientOpts2 = [{early_data, <<"SampleData">>}|ClientOpts1],
@@ -422,7 +415,7 @@ openssl_server_early_data_big(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
ClientOpts2 = [{early_data, <<"SampleData">>}|ClientOpts1],
@@ -467,7 +460,7 @@ openssl_server_early_data_manual(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
ClientOpts2 = [{early_data, <<"SampleData">>}|ClientOpts1],
@@ -516,7 +509,7 @@ openssl_server_early_data_manual_big(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
ClientOpts2 = [{early_data, <<"SampleData">>}|ClientOpts1],
@@ -563,7 +556,7 @@ openssl_server_early_data_manual_2_tickets(Config) when is_list(Config) ->
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
ClientOpts2 = [{early_data, <<"SampleData">>}|ClientOpts1],
@@ -610,7 +603,7 @@ openssl_server_early_data_manual_2_chacha_tickets(Config) when is_list(Config) -
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{ciphers, ["TLS_CHACHA20_POLY1305_SHA256"]},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
ClientOpts2 = [{early_data, <<"SampleData">>}|ClientOpts1],
@@ -670,7 +663,6 @@ openssl_client_early_data_basic(Config) when is_list(Config) ->
%% Configure session tickets
ServerOpts = [{session_tickets, ServerTicketMode},
{early_data, enabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
diff --git a/lib/ssl/test/openssl_sni_SUITE.erl b/lib/ssl/test/openssl_sni_SUITE.erl
index a6d9746164..a5ebbb35c4 100644
--- a/lib/ssl/test/openssl_sni_SUITE.erl
+++ b/lib/ssl/test/openssl_sni_SUITE.erl
@@ -98,33 +98,20 @@ sni_tests() ->
sni_no_header_fun].
init_per_suite(Config0) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- case check_openssl_sni_support(Config0) of
- {skip, _} = Skip ->
- Skip;
- Config1 ->
- %% Needed by version interop test in ssl_test_lib
- Config = ssl_test_lib:make_rsa_cert(Config1),
- ssl_test_lib:clean_start(),
- Hostname = net_adm:localhost(),
- {#{server_config := ServerConf,
- client_config := ClientConf},
- #{server_config := LServerConf,
- client_config := LClientConf}} = ssl_test_lib:make_rsa_sni_configs(),
- [{client_opts, ClientConf}, {client_local_opts, LClientConf},
- {sni_server_opts, [{sni_hosts, [{Hostname, ServerConf}]} | LServerConf]} | Config]
- end
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
+ Config1 = ssl_test_lib:init_per_suite(Config0, openssl),
+ Config2 = check_openssl_sni_support(Config1),
+ Config = ssl_test_lib:make_rsa_cert(Config2),
+ Hostname = net_adm:localhost(),
+ {#{server_config := ServerConf,
+ client_config := ClientConf},
+ #{server_config := LServerConf,
+ client_config := LClientConf}} = ssl_test_lib:make_rsa_sni_configs(),
+ [{client_opts, ClientConf}, {client_local_opts, LClientConf},
+ {sni_server_opts, [{sni_hosts, [{Hostname, ServerConf}]} | LServerConf]} | Config].
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto),
- ssl_test_lib:kill_openssl().
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group_openssl(GroupName, Config).
@@ -289,7 +276,7 @@ check_openssl_sni_support(Config) ->
HelpText = ssl_test_lib:portable_cmd("openssl", ["s_client", "--help"]),
case string:str(HelpText, "-servername") of
0 ->
- {skip, "Current openssl doesn't support SNI"};
+ throw({skip, "Current openssl doesn't support SNI"});
_ ->
case string:str(HelpText, "-noservername") of
0 ->
diff --git a/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl b/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl
index 7135d96b18..9b95041064 100644
--- a/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl
+++ b/lib/ssl/test/openssl_tls_1_3_version_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -67,24 +67,17 @@ tests() ->
%%tls13_client_with_ext_tls12_server,
tls12_client_tls13_server].
-init_per_suite(Config) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- case ssl_test_lib:check_sane_openssl_version('tlsv1.3') of
- true ->
- ssl_test_lib:clean_start(),
- Config;
- false ->
- {skip, openssl_does_not_support_version}
- end
- catch _:_ ->
- {skip, "Crypto did not start"}
+init_per_suite(Config0) ->
+ Config = ssl_test_lib:init_per_suite(Config0, openssl),
+ case ssl_test_lib:check_sane_openssl_version('tlsv1.3', Config) of
+ true ->
+ Config;
+ false ->
+ {skip, openssl_does_not_support_version}
end.
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto).
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
case ssl_test_lib:is_protocol_version(GroupName) of
diff --git a/lib/ssl/test/property_test/ssl_eqc_handshake.erl b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
index b8c4133a04..6d9d84e6ae 100644
--- a/lib/ssl/test/property_test/ssl_eqc_handshake.erl
+++ b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
@@ -687,14 +687,11 @@ certificate_authorities(?'TLS_v1.3') ->
#certificate_authorities{authorities = Auths};
certificate_authorities(_) ->
#{server_config := ServerConf} = cert_conf(),
- Authorities = proplists:get_value(cacerts, ServerConf),
- Enc = fun(#'OTPCertificate'{tbsCertificate=TBSCert}) ->
- OTPSubj = TBSCert#'OTPTBSCertificate'.subject,
- DNEncodedBin = public_key:pkix_encode('Name', OTPSubj, otp),
- DNEncodedLen = byte_size(DNEncodedBin),
- <<?UINT16(DNEncodedLen), DNEncodedBin/binary>>
- end,
- list_to_binary([Enc(public_key:pkix_decode_cert(DERCert, otp)) || DERCert <- Authorities]).
+ Certs = proplists:get_value(cacerts, ServerConf),
+ Auths = fun(#'OTPCertificate'{tbsCertificate = TBSCert}) ->
+ public_key:pkix_normalize_name(TBSCert#'OTPTBSCertificate'.subject)
+ end,
+ [Auths(public_key:pkix_decode_cert(Cert, otp)) || Cert <- Certs].
digest_size()->
oneof([160,224,256,384,512]).
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 15587abecd..c6d6aa3a8b 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -1,12 +1,2 @@
% {merge_tests,false}.
-{alias,dir,"../ssl_test"}.
-
-{suites,dir,all}.
-{skip_groups,dir,ssl_bench_SUITE,setup,"Benchmarks run separately"}.
-{skip_groups,dir,ssl_bench_SUITE,payload,"Benchmarks run separately"}.
-{skip_groups,dir,ssl_bench_SUITE,pem_cache,"Benchmarks run separately"}.
-{skip_groups,dir,ssl_dist_bench_SUITE,setup,"Benchmarks run separately"}.
-{skip_groups,dir,ssl_dist_bench_SUITE,roundtrip,"Benchmarks run separately"}.
-{skip_groups,dir,ssl_dist_bench_SUITE,throughput,"Benchmarks run separately"}.
-{skip_groups,dir,ssl_dist_bench_SUITE,sched_utilization,"Benchmarks run separately"}.
-
+{suites, "../ssl_test", all}.
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index bb3bb15c97..4b43954139 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -77,7 +77,7 @@ groups() ->
{'tlsv1.1', [], test_cases()},
{'tlsv1', [], test_cases()},
{'dtlsv1.2', [], [mix_sign | test_cases()]},
- {'dtlsv1', [], test_cases()}
+ {'dtlsv1', [], test_cases()}
].
test_cases()->
@@ -99,7 +99,7 @@ ecc_negotiation() ->
client_ecdhe_rsa_server_ecdh_rsa_server_custom,
client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom,
client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom,
- client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom,
+ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom,
client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom
].
@@ -125,9 +125,9 @@ end_per_suite(_Config) ->
%%--------------------------------------------------------------------
init_per_group(GroupName, Config) ->
case ssl_test_lib:is_protocol_version(GroupName) of
- true ->
+ true ->
ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, GroupName)]),
- ssl_test_lib:init_per_group(GroupName,
+ ssl_test_lib:init_per_group(GroupName,
[{client_type, erlang},
{server_type, erlang},
{version, GroupName} | Config]);
@@ -142,14 +142,12 @@ end_per_group(GroupName, Config) ->
init_per_testcase(TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- Version = proplists:get_value(version, Config),
- ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, Version)]),
end_per_testcase(TestCase, Config),
ssl:start(),
- ct:timetrap({seconds, 15}),
+ ct:timetrap({seconds, 5}),
Config.
-end_per_testcase(_TestCase, Config) ->
+end_per_testcase(_TestCase, Config) ->
application:stop(ssl),
Config.
@@ -161,10 +159,10 @@ end_per_testcase(_TestCase, Config) ->
client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}]
, ecdhe_ecdsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ServerKeyFile = proplists:get_value(keyfile, SOpts),
{ok, PemBin} = file:read_file(ServerKeyFile),
@@ -183,11 +181,11 @@ client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
ecc_default_order(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_ecdsa, ecdhe_ecdsa,
Config, DefaultCurve),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [],
case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
@@ -198,11 +196,11 @@ ecc_default_order(Config) ->
ecc_default_order_custom_curves(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_ecdsa, ecdhe_ecdsa,
Config, DefaultCurve),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -213,11 +211,11 @@ ecc_default_order_custom_curves(Config) ->
ecc_client_order(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_ecdsa, ecdhe_ecdsa,
Config, DefaultCurve),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, false}],
case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
@@ -232,7 +230,7 @@ ecc_client_order_custom_curves(Config) ->
{client_chain, Default}],
ecdhe_ecdsa, ecdhe_ecdsa,
Config, DefaultCurve),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -244,8 +242,8 @@ ecc_unknown_curve(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
- ecdhe_ecdsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, ['123_fake_curve']}],
ssl_test_lib:ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
@@ -254,9 +252,9 @@ client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
+ {client_chain, Default}],
ecdh_rsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -267,13 +265,13 @@ client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdh_rsa, ecdhe_rsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
-
+
case ssl_test_lib:supported_eccs(ECCOpts) of
true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
false -> {skip, "unsupported named curves"}
@@ -282,10 +280,10 @@ client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_rsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -296,11 +294,11 @@ client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
ecdhe_rsa, ecdhe_rsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -312,10 +310,10 @@ client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
{COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
- {client_chain, Default}],
+ {client_chain, Default}],
ecdhe_rsa, ecdh_rsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
Expected = secp256r1, %% The certificate curve
@@ -328,10 +326,10 @@ client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
- {client_chain, Default}],
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
ecdhe_ecdsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -342,10 +340,10 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_ecdsa, ecdhe_rsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -356,10 +354,10 @@ client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_ecdsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -370,10 +368,10 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
Default = ssl_test_lib:default_cert_chain_conf(),
DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
- {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
{client_chain, Default}],
ecdhe_rsa, ecdhe_ecdsa, Config),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
case ssl_test_lib:supported_eccs(ECCOpts) of
@@ -384,23 +382,22 @@ client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
mix_sign(Config) ->
mix_sign_rsa_peer(Config),
mix_sign_ecdsa_peer(Config).
-
+
mix_sign_ecdsa_peer(Config) ->
{COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_ecc} |Config]),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECDHE_ECDSA =
- ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
[{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
-
+
mix_sign_rsa_peer(Config) ->
{COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_rsa} |Config]),
- COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ECDHE_RSA =
- ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
[{key_exchange, fun(ecdhe_rsa) -> true; (_) -> false end}]),
ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_RSA} | SOpts], Config).
-
diff --git a/lib/ssl/test/ssl_alert_SUITE.erl b/lib/ssl/test/ssl_alert_SUITE.erl
index f20df97d53..d6b132cc63 100644
--- a/lib/ssl/test/ssl_alert_SUITE.erl
+++ b/lib/ssl/test/ssl_alert_SUITE.erl
@@ -29,6 +29,8 @@
%% Common test
-export([all/0,
+ init_per_suite/1,
+ end_per_suite/1,
init_per_testcase/2,
end_per_testcase/2
]).
@@ -54,6 +56,19 @@ all() ->
bad_connect_response
].
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config0
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
init_per_testcase(_TestCase, Config) ->
ct:timetrap({seconds, 5}),
Config.
diff --git a/lib/ssl/test/ssl_api_SUITE.erl b/lib/ssl/test/ssl_api_SUITE.erl
index c686fac6d6..fc56323afd 100644
--- a/lib/ssl/test/ssl_api_SUITE.erl
+++ b/lib/ssl/test/ssl_api_SUITE.erl
@@ -25,6 +25,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("ssl/src/ssl_api.hrl").
+-include_lib("public_key/include/public_key.hrl").
%% Common test
-export([all/0,
@@ -50,6 +51,10 @@
peercert/1,
peercert_with_client_cert/0,
peercert_with_client_cert/1,
+ select_best_cert/0,
+ select_best_cert/1,
+ select_sha1_cert/0,
+ select_sha1_cert/1,
connection_information/0,
connection_information/1,
secret_connection_info/0,
@@ -66,10 +71,10 @@
dh_params/1,
prf/0,
prf/1,
- hibernate/0,
- hibernate/1,
- hibernate_right_away/0,
- hibernate_right_away/1,
+ hibernate_client/0,
+ hibernate_client/1,
+ hibernate_server/0,
+ hibernate_server/1,
listen_socket/0,
listen_socket/1,
peername/0,
@@ -205,6 +210,7 @@
log/2,
get_connection_information/3,
protocol_version_check/2,
+ check_peercert/2,
%%TODO Keep?
run_error_server/1,
run_error_server_close/1,
@@ -243,11 +249,13 @@ groups() ->
{'tlsv1', [], gen_api_tests() ++ handshake_paus_tests() ++ pre_1_3() ++ beast_mitigation_test()},
{'dtlsv1.2', [], (gen_api_tests() --
[invalid_keyfile, invalid_certfile, invalid_cacertfile,
- invalid_options, new_options_in_handshake]) ++
+ invalid_options, new_options_in_handshake,
+ hibernate_server]) ++
handshake_paus_tests() -- [handshake_continue_tls13_client] ++ pre_1_3()},
{'dtlsv1', [], (gen_api_tests() --
[invalid_keyfile, invalid_certfile, invalid_cacertfile,
- invalid_options, new_options_in_handshake]) ++
+ invalid_options, new_options_in_handshake,
+ hibernate_server]) ++
handshake_paus_tests() -- [handshake_continue_tls13_client] ++ pre_1_3()}
].
@@ -269,14 +277,16 @@ gen_api_tests() ->
[
peercert,
peercert_with_client_cert,
+ select_best_cert,
+ select_sha1_cert,
connection_information,
secret_connection_info,
keylog_connection_info,
versions,
active_n,
dh_params,
- hibernate,
- hibernate_right_away,
+ hibernate_client,
+ hibernate_server,
listen_socket,
peername,
recv_active,
@@ -427,6 +437,23 @@ init_per_testcase(check_random_nonce, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 20}),
Config;
+init_per_testcase(select_best_cert, Config) ->
+ ct:timetrap({seconds, 10}),
+ Version = ssl_test_lib:protocol_version(Config),
+ %% We need to make sure TLS-1.3 can be supported as
+ %% want to generate a TLS-1.3 specific certificate that will not
+ %% be chosen
+ case Version of
+ 'tlsv1.2' ->
+ case ssl_test_lib:sufficient_crypto_support('tlsv1.3') of
+ true ->
+ Config;
+ false ->
+ {skip, "Crypto does not support EDDSA"}
+ end;
+ _ ->
+ Config
+ end;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 10}),
@@ -509,6 +536,54 @@ peercert_with_client_cert(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+select_best_cert() ->
+ [{doc,"Basic test of the certs_keys option."}].
+
+select_best_cert(Config) when is_list(Config) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ Conf = test_config(Version, Config),
+ lists:foreach(
+ fun({#{server_config := SConfig,
+ client_config := CConfig},
+ {client_peer, CExpected},
+ {server_peer, SExpected}}) ->
+ selected_peer(CExpected, SExpected,
+ ssl_test_lib:ssl_options(CConfig, Config),
+ ssl_test_lib:ssl_options(SConfig, Config),
+ Conf)
+ end, Conf).
+
+
+
+%%--------------------------------------------------------------------
+select_sha1_cert() ->
+ [{doc,"Use cert signed with rsa and sha1"}].
+
+select_sha1_cert(Config) when is_list(Config) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ TestConfRSA = public_key:pkix_test_data(#{server_chain => #{root => [{digest, sha},{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[{digest, sha}, {key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{digest, sha}, {key, ssl_test_lib:hardcode_rsa_key(3)}]
+ },
+ client_chain => #{root => [{digest, sha},{key, ssl_test_lib:hardcode_rsa_key(3)}],
+ intermediates => [[{digest, sha},{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{digest, sha}, {key, ssl_test_lib:hardcode_rsa_key(1)}]}}),
+
+ TestConfECDSA = public_key:pkix_test_data(#{server_chain => #{root => [{digest, sha},{key, {namedCurve, secp256r1}}],
+ intermediates => [[{digest, sha}, {key,{namedCurve, secp256r1} }]],
+ peer => [{digest, sha}, {key,{namedCurve, secp256r1}}]
+ },
+ client_chain => #{root => [{digest, sha},{key, {namedCurve, secp256r1}}],
+ intermediates => [[{digest, sha},{key, {namedCurve, secp256r1}}]],
+ peer => [{digest, sha}, {key, {namedCurve, secp256r1}}]}}),
+ case (Version == 'tlsv1.3') orelse (Version == 'tlsv1.2') of
+ true ->
+ test_sha1_cert_conf(Version, TestConfRSA, TestConfECDSA, Config);
+ false ->
+ test_sha1_cert_conf(Version, TestConfRSA, undefined, Config)
+ end.
+
+%%--------------------------------------------------------------------
connection_information() ->
[{doc,"Test the API function ssl:connection_information/1"}].
connection_information(Config) when is_list(Config) ->
@@ -777,7 +852,6 @@ handshake_continue(Config) when is_list(Config) ->
{from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ssl_test_lib:ssl_options([{reuseaddr, true},
- {log_level, debug},
{verify, verify_peer},
{handshake, hello} | ServerOpts
],
@@ -820,7 +894,6 @@ handshake_continue_tls13_client(Config) when is_list(Config) ->
{from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ssl_test_lib:ssl_options([{reuseaddr, true},
- {log_level, debug},
{verify, verify_peer},
{ciphers, SCiphers},
{handshake, hello} | ServerOpts
@@ -1118,92 +1191,89 @@ active_n(Config) when is_list(Config) ->
ok = ssl:close(LS),
ok.
-hibernate() ->
- [{doc,"Check that an SSL connection that is started with option "
- "{hibernate_after, 1000} indeed hibernates after 1000ms of "
- "inactivity"}].
+hibernate_client() ->
+ [{doc,"Check that an SSL connection on client side that is started with "
+ "option hibernate_after indeed hibernates after inactivity"}].
-hibernate(Config) ->
+hibernate_client(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_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, send_recv_result_active, []}},
- {options, ServerOpts}]),
- Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=[Pid|_]}} = ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, [{hibernate_after, 1000}|ClientOpts]}]),
- {current_function, _} =
- process_info(Pid, current_function),
-
- ssl_test_lib:check_result(Server, ok, Client, ok),
-
- ct:sleep(1500),
- {current_function, {erlang, hibernate, 3}} =
- process_info(Pid, current_function),
-
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%%--------------------------------------------------------------------
-
-hibernate_right_away() ->
- [{doc,"Check that an SSL connection that is configured to hibernate "
- "after 0 or 1 milliseconds hibernates as soon as possible and not "
- "crashes"}].
-
-hibernate_right_away(Config) ->
+ StartServerOpts = [return_socket, {node, ServerNode},
+ {port, 0}, {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{hibernate_after, infinity} | ServerOpts]}],
+ StartClientOpts = [return_socket, {node, ClientNode}, {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}}],
+ [ok = hibernate_helper(?config(version, Config), false,
+ StartServerOpts, StartClientOpts,
+ ServerOpts, ClientOpts, T, infinity) ||
+ T <- [1000, 0, 1]].
+
+hibernate_server() ->
+ [{doc,"Check that an SSL connection on server side that is started with "
+ "option hibernate_after indeed hibernates after inactivity."
+ "Note: for DTLS test will not be stable, because cookie secret refresh "
+ "mechanism might disturb hibernation of a server process."}].
+hibernate_server(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
-
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- StartServerOpts = [{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, ServerOpts}],
- StartClientOpts = [return_socket,
- {node, ClientNode},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}}],
-
- Server1 = ssl_test_lib:start_server(StartServerOpts),
- Port1 = ssl_test_lib:inet_port(Server1),
- {Client1, #sslsocket{pid = [Pid1|_]}} = ssl_test_lib:start_client(StartClientOpts ++
- [{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
-
- ssl_test_lib:check_result(Server1, ok, Client1, ok),
-
- ct:sleep(1000), %% Schedule out
-
- {current_function, {erlang, hibernate, 3}} =
- process_info(Pid1, current_function),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1),
-
- Server2 = ssl_test_lib:start_server(StartServerOpts),
- Port2 = ssl_test_lib:inet_port(Server2),
- {Client2, #sslsocket{pid = [Pid2|_]}} = ssl_test_lib:start_client(StartClientOpts ++
- [{port, Port2}, {options, [{hibernate_after, 1}|ClientOpts]}]),
-
- ssl_test_lib:check_result(Server2, ok, Client2, ok),
-
- ct:sleep(1000), %% Schedule out
-
+ StartServerOpts = [return_socket, {node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}}],
+ StartClientOpts = [return_socket, {node, ClientNode}, {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}}],
+ [ok = hibernate_helper(?config(version, Config), true,
+ StartServerOpts, StartClientOpts,
+ ServerOpts, ClientOpts, infinity, T) ||
+ T <- [1000, 0, 1]].
+
+hibernate_helper(Version, CheckServer, StartServerOpts, StartClientOpts,
+ ServerOpts0, ClientOpts0,
+ ClientHibernateAfter, ServerHibernateAfter) ->
+ AllServerOpts = StartServerOpts ++
+ [{options, [{hibernate_after, ServerHibernateAfter} | ServerOpts0]}],
+ Server = ssl_test_lib:start_server(AllServerOpts),
+ Port = ssl_test_lib:inet_port(Server),
+ AllClientOpts = StartClientOpts ++
+ [{port, Port},
+ {options, [{hibernate_after, ClientHibernateAfter} | ClientOpts0]}],
+ {Client, #sslsocket{pid = [ClientReceiverPid | ClientPotentialSenderPid]}} =
+ ssl_test_lib:start_client(AllClientOpts),
+ Results = ssl_test_lib:get_result([Client, Server]),
+ {ok, ServerAcceptSocket} = proplists:get_value(Server, Results),
+ ok = proplists:get_value(Client, Results),
+ #sslsocket{pid = [ServerReceiverPid | ServerPotentialSenderPid]} =
+ ServerAcceptSocket,
+ {ReceiverPid, PotentialSenderPid, HibernateAfter} =
+ case CheckServer of
+ true -> {ServerReceiverPid, ServerPotentialSenderPid,
+ ServerHibernateAfter};
+ false -> {ClientReceiverPid, ClientPotentialSenderPid,
+ ClientHibernateAfter}
+ end,
+ SleepAmount = max(1.5*HibernateAfter, 500),
+ ct:log("HibernateAfter = ~w SleepAmount = ~w", [HibernateAfter, SleepAmount]),
+ ct:sleep(SleepAmount), %% Schedule out
{current_function, {erlang, hibernate, 3}} =
- process_info(Pid2, current_function),
-
- ssl_test_lib:close(Server2),
- ssl_test_lib:close(Client2).
+ process_info(ReceiverPid, current_function),
+ IsTls = ssl_test_lib:is_tls_version(Version),
+ case IsTls of
+ true ->
+ [SenderPid] = PotentialSenderPid,
+ {current_function, {erlang, hibernate, 3}} =
+ process_info(SenderPid, current_function);
+ _ -> %% DTLS (no sender process)
+ ok
+ end,
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client),
+ ok.
+%%--------------------------------------------------------------------
listen_socket() ->
[{doc,"Check error handling and inet compliance when calling API functions with listen sockets."}].
@@ -1832,7 +1902,36 @@ der_input(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client),
%% Using only DER input should not increase file indexed DB
- Size = ets:info(CADb, size).
+ Size = ets:info(CADb, size),
+
+ ServerOpts1 = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
+ {cert, ServerCert}, {key, ServerKey},
+ {cacerts, [ #cert{der=Der, otp=public_key:pkix_decode_cert(Der, otp)}
+ || Der <- ServerCaCerts]}],
+ ClientOpts1 = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
+ {dh, DHParams},
+ {cert, ClientCert}, {key, ClientKey},
+ {cacerts, [ #cert{der=Der, otp=public_key:pkix_decode_cert(Der, otp)}
+ || Der <- ClientCaCerts]}],
+ Server1 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts1]}]),
+ Port1 = ssl_test_lib:inet_port(Server1),
+ Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port1},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ClientOpts1]}]),
+
+ ssl_test_lib:check_result(Server1, ok, Client1, ok),
+ ssl_test_lib:close(Server1),
+ ssl_test_lib:close(Client1),
+ %% Using only DER input should not increase file indexed DB
+ Size = ets:info(CADb, size),
+
+ ok.
%%--------------------------------------------------------------------
invalid_certfile() ->
@@ -2797,6 +2896,11 @@ do_recv_close(Socket) ->
tls_close(Socket) ->
ok = ssl_test_lib:send_recv_result(Socket),
+ %% So both sides will have time to send
+ %% and recv before close is called, as this
+ %% function will be called by both client
+ %% and server in the test.
+ ct:sleep(100),
case ssl:close(Socket, 10000) of
ok ->
ok;
@@ -3169,3 +3273,233 @@ dtls_exclusive_non_default_version(DTLSVersion) ->
tls_v1:srp_exclusive(Minor) ++
tls_v1:rsa_exclusive(Minor) ++
tls_v1:des_exclusive(Minor).
+
+selected_peer(ExpectedClient,
+ ExpectedServer, ClientOpts, ServerOpts, Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, check_peercert, [ExpectedServer]}},
+ {options, ssl_test_lib:ssl_options(ServerOpts, Config)}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, check_peercert, [ExpectedClient]}},
+ {options, ssl_test_lib:ssl_options(ClientOpts, Config)}
+ ]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ %% Make sure to start next test fresh
+ ssl:stop(),
+ ssl:start().
+
+test_config('tlsv1.3', _) ->
+ #{server_config := SEDDSAOpts,
+ client_config := CEDDSAOpts} = eddsa_cert_chains(),
+ #{server_config := SECDSAOpts,
+ client_config := CECDSAOpts } = ecdsa_cert_chains(),
+
+ {SEDDSACert, SEDDSAKey, SEDDSACACerts} = get_single_options(cert, key, cacerts, SEDDSAOpts),
+ {CEDDSACert, CEDDSAKey, CEDDSACACerts} = get_single_options(cert, key, cacerts, CEDDSAOpts),
+
+ {SECDSACert, SECDSAKey, SECDSACACerts} = get_single_options(cert, key, cacerts, SECDSAOpts),
+ {CECDSACert, CECDSAKey, CECDSACACerts} = get_single_options(cert, key, cacerts, CECDSAOpts),
+
+ ServerCertKeys = [#{cert => SECDSACert, key => SECDSAKey},
+ #{cert => SEDDSACert, key => SEDDSAKey}],
+
+ ClientCertKeys = [#{cert => CECDSACert, key => CECDSAKey},
+ #{cert => CEDDSACert, key => CEDDSAKey}],
+
+ [{#{server_config => [{certs_keys,ServerCertKeys},
+ {verify, verify_peer}, {versions, ['tlsv1.3', 'tlsv1.2']},
+ {cacerts, SEDDSACACerts ++ SECDSACACerts}],
+ client_config => [{certs_keys, ClientCertKeys},
+ {verify, verify_peer}, {versions, ['tlsv1.3', 'tlsv1.2']},
+ {cacerts, CEDDSACACerts ++ CECDSACACerts}]
+ },
+ {client_peer, SEDDSACert}, {server_peer, CEDDSACert}},
+ {#{server_config => [{certs_keys, ServerCertKeys},
+ {verify, verify_peer}, {versions, ['tlsv1.2']},
+ {cacerts, SEDDSACACerts ++ SECDSACACerts}],
+ client_config => [{certs_keys, ClientCertKeys},
+ {verify, verify_peer}, {versions, ['tlsv1.2']},
+ {cacerts, CEDDSACACerts ++ CECDSACACerts}]},
+ {client_peer, SECDSACert}, {server_peer, CECDSACert}}
+ ];
+test_config('tlsv1.2', _) ->
+ #{server_config := SRSAOpts,
+ client_config := CRSAOpts} = eddsa_cert_chains(),
+ #{server_config := SDSAOpts,
+ client_config := CDSAOpts} = dsa_cert_chains(),
+
+ {SRSACert, SRSAKey, SRSACACerts} = get_single_options(cert, key, cacerts, SRSAOpts),
+ {CRSACert, CRSAKey, CRSACACerts} = get_single_options(cert, key, cacerts, CRSAOpts),
+
+ {SDSACert, SDSAKey, SDSACACerts} = get_single_options(cert, key, cacerts, SDSAOpts),
+ {CDSACert, CDSAKey, CDSACACerts} = get_single_options(cert, key, cacerts, CDSAOpts),
+
+
+ [{#{server_config => [{certs_keys, [#{cert => SDSACert, key => SDSAKey}, #{cert => SRSACert, key => SRSAKey}]},
+ {verify, verify_peer}, {versions, ['tlsv1.3', 'tlsv1.2']},
+ {cacerts, SRSACACerts ++ SDSACACerts}],
+ client_config => [{certs_keys, [#{cert => CDSACert, key => CDSAKey}, #{cert => CRSACert, key => CRSAKey}]},
+ {verify, verify_peer}, {versions, ['tlsv1.3', 'tlsv1.2']},
+ {cacerts, CRSACACerts ++ CDSACACerts}]
+ }, {client_peer, SRSACert}, {server_peer, CRSACert}},
+ {#{server_config => [{certs_keys, [#{cert => SDSACert, key => SDSAKey}, #{cert => SRSACert, key => SRSAKey}]},
+ {verify, verify_peer}, {versions, ['tlsv1.2']},
+ {cacerts, SRSACACerts ++ SDSACACerts}],
+ client_config => [{certs_keys, [#{cert => CDSACert, key => CDSAKey}, #{cert => CRSACert, key => CRSAKey}]},
+ {verify, verify_peer}, {versions, ['tlsv1.2']},
+ {cacerts, CRSACACerts ++ CDSACACerts}]
+ }, {client_peer, SDSACert}, {server_peer, CDSACert}}];
+test_config('dtlsv1.2', Config) ->
+ #{server_config := SRSAPSSOpts,
+ client_config := CRSAPSSOpts} = ssl_test_lib:make_rsa_pss_pem(rsa_pss_pss, [], Config, "dtls_pss_pss_conf"),
+ #{server_config := SRSAPSSRSAEOpts,
+ client_config := CRSAPSSRSAEOpts} = ssl_test_lib:make_rsa_pss_pem(rsa_pss_rsae, [], Config, "dtls_pss_rsae_conf"),
+
+ {SRSAPSSCert, SRSAPSSKey, SRSAPSSCACerts} = get_single_options(certfile, keyfile, cacertfile, SRSAPSSOpts),
+ {CRSAPSSCert, CRSAPSSKey, CRSAPSSCACerts} = get_single_options(certfile, keyfile, cacertfile, CRSAPSSOpts),
+
+ {SRSAPSSRSAECert, SRSAPSSRSAEKey, SRSAPSSRSAECACerts} = get_single_options(certfile, keyfile, cacertfile, SRSAPSSRSAEOpts),
+ {CRSAPSSRSAECert, CRSAPSSRSAEKey, CRSAPSSRSAECACerts} = get_single_options(certfile, keyfile, cacertfile, CRSAPSSRSAEOpts),
+
+ [{#{server_config => [{certs_keys, [#{certfile => SRSAPSSRSAECert, keyfile => SRSAPSSRSAEKey},
+ #{certfile => SRSAPSSCert, keyfile => SRSAPSSKey}]},
+ {verify, verify_peer},
+ {cacertfile, SRSAPSSCACerts}],
+ client_config => [{certs_keys, [#{certfile => CRSAPSSRSAECert, keyfile => CRSAPSSRSAEKey},
+ #{certfile => CRSAPSSCert, keyfile => CRSAPSSKey}]},
+ {verify, verify_peer},
+ {cacertfile, CRSAPSSCACerts}]
+ },
+ {client_peer, pem_to_der_cert(SRSAPSSCert)}, {server_peer, pem_to_der_cert(CRSAPSSCert)}},
+ {#{server_config => [{certs_keys, [#{certfile => SRSAPSSRSAECert, keyfile => SRSAPSSRSAEKey},
+ #{certfile => SRSAPSSCert, keyfile => SRSAPSSKey}]},
+ {verify, verify_peer},
+ {cacertfile, SRSAPSSRSAECACerts}],
+ client_config => [{certs_keys, [#{certfile => CRSAPSSRSAECert, keyfile => CRSAPSSRSAEKey}]},
+ {verify, verify_peer}, {signature_algs, [rsa_pss_rsae_sha256]},
+ {cacertfile, CRSAPSSRSAECACerts}]
+ },
+ {client_peer, pem_to_der_cert(SRSAPSSRSAECert)}, {server_peer, pem_to_der_cert(CRSAPSSRSAECert)}}
+ ];
+test_config(_, Config) ->
+ RSAConf1 = ssl_test_lib:make_rsa_cert(Config),
+ SRSA1Opts = proplists:get_value(server_rsa_opts, RSAConf1),
+ CRSA1Opts = proplists:get_value(client_rsa_opts, RSAConf1),
+
+ RSAConf2 = ssl_test_lib:make_rsa_1024_cert(Config),
+ SRSA2Opts = proplists:get_value(server_rsa_1024_opts, RSAConf2),
+ CRSA2Opts = proplists:get_value(client_rsa_1024_opts, RSAConf2),
+
+ {SRSA1Cert, SRSA1Key, _SRSA1CACerts} = get_single_options(certfile, keyfile, cacertfile, SRSA1Opts),
+ {CRSA1Cert, CRSA1Key, _CRSA1CACerts} = get_single_options(certfile, keyfile, cacertfile, CRSA1Opts),
+
+ {SRSA2Cert, SRSA2Key, SRSA2CACerts} = get_single_options(certfile, keyfile, cacertfile, SRSA2Opts),
+ {CRSA2Cert, CRSA2Key, CRSA2CACerts} = get_single_options(certfile, keyfile, cacertfile, CRSA2Opts),
+
+ [{#{server_config => [{certs_keys, [#{certfile => SRSA2Cert, keyfile => SRSA2Key},
+ #{certfile => SRSA1Cert, keyfile => SRSA1Key}]},
+ {verify, verify_peer},
+ {cacertfile, SRSA2CACerts}],
+ client_config => [{certs_keys, [#{certfile => CRSA2Cert, keyfile => CRSA2Key},
+ #{certfile => CRSA1Cert, keyfile => CRSA1Key}]},
+ {verify, verify_peer},
+ {cacertfile, CRSA2CACerts}]
+ }, {client_peer, pem_to_der_cert(SRSA2Cert)}, {server_peer, pem_to_der_cert(CRSA2Cert)}}].
+
+check_peercert(Socket, Cert) ->
+ case ssl:peercert(Socket) of
+ {ok, Cert} ->
+ ok;
+ {ok, Other} ->
+ {error, {{expected, public_key:pkix_decode_cert(Cert, otp)}, {got, public_key:pkix_decode_cert(Other, otp)}}}
+ end.
+
+
+eddsa_cert_chains() ->
+ public_key:pkix_test_data(#{server_chain => #{root => ssl_test_lib:eddsa_conf(),
+ intermediates => [ssl_test_lib:eddsa_conf()],
+ peer => ssl_test_lib:eddsa_conf()},
+ client_chain => #{root => ssl_test_lib:eddsa_conf(),
+ intermediates => [ssl_test_lib:eddsa_conf()],
+ peer => ssl_test_lib:eddsa_conf()}}).
+
+ecdsa_cert_chains() ->
+ public_key:pkix_test_data(#{server_chain => #{root => ssl_test_lib:ecdsa_conf(),
+ intermediates => [ssl_test_lib:ecdsa_conf()],
+ peer => ssl_test_lib:ecdsa_conf()},
+ client_chain => #{root => ssl_test_lib:ecdsa_conf(),
+ intermediates => [ssl_test_lib:ecdsa_conf()],
+ peer => ssl_test_lib:ecdsa_conf()}}).
+dsa_cert_chains() ->
+ public_key:pkix_test_data(#{server_chain => #{root => [{key, ssl_test_lib:hardcode_dsa_key(1)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_dsa_key(2)}]],
+ peer => [{key, ssl_test_lib:hardcode_dsa_key(3)}]
+ },
+ client_chain => #{root => [{key, ssl_test_lib:hardcode_dsa_key(3)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_dsa_key(2)}]],
+ peer => [{key, ssl_test_lib:hardcode_dsa_key(1)}]}}).
+
+get_single_options(CertOptName, KeyOptName, CaOptName, Opts) ->
+ CertOpt = proplists:get_value(CertOptName, Opts),
+ KeyOpt = proplists:get_value(KeyOptName, Opts),
+ CaOpt = proplists:get_value(CaOptName, Opts),
+ {CertOpt, KeyOpt, CaOpt}.
+
+pem_to_der_cert(Pem) ->
+ [{'Certificate', Der, _}] = ssl_test_lib:pem_to_der(Pem),
+ Der.
+
+test_sha1_cert_conf('tlsv1.3'= Version, RSA, ECDSA, Config) ->
+ run_sha1_cert_conf(Version, ECDSA, Config, ecdsa_sha1),
+ run_sha1_cert_conf(Version, RSA, Config, rsa_pkcs1_sha1);
+test_sha1_cert_conf('tlsv1.2'= Version, RSA, ECDSA, Config) ->
+ run_sha1_cert_conf(Version, RSA, Config, {sha, rsa}),
+ run_sha1_cert_conf(Version, ECDSA, Config, {sha, ecdsa});
+test_sha1_cert_conf(Version,RSA,_,Config) ->
+ run_sha1_cert_conf(Version, RSA, Config, undefined).
+
+run_sha1_cert_conf('tlsv1.3', #{client_config := ClientOpts, server_config := ServerOpts}, Config, LegacyAlg) ->
+ SigAlgs = [%% ECDSA
+ ecdsa_secp521r1_sha512,
+ ecdsa_secp384r1_sha384,
+ ecdsa_secp256r1_sha256,
+ %% RSASSA-PSS
+ rsa_pss_pss_sha512,
+ rsa_pss_pss_sha384,
+ rsa_pss_pss_sha256,
+ rsa_pss_rsae_sha512,
+ rsa_pss_rsae_sha384,
+ rsa_pss_rsae_sha256,
+ %% EDDSA
+ eddsa_ed25519,
+ eddsa_ed448
+ ],
+ IncludeLegacyAlg = SigAlgs ++ [LegacyAlg],
+ ssl_test_lib:basic_alert([{verify, verify_peer}, {signature_algs, SigAlgs} | ClientOpts],
+ [{signature_algs, IncludeLegacyAlg} | ServerOpts], Config, handshake_failure),
+ ssl_test_lib:basic_test([{verify, verify_peer}, {signature_algs, IncludeLegacyAlg} | ClientOpts],
+ [{signature_algs, IncludeLegacyAlg} | ServerOpts], Config);
+
+run_sha1_cert_conf('tlsv1.2', #{client_config := ClientOpts, server_config := ServerOpts}, Config, LegacyAlg) ->
+ SigAlgs = [%% SHA2
+ {sha512, ecdsa},
+ {sha512, rsa},
+ {sha384, ecdsa},
+ {sha384, rsa},
+ {sha256, ecdsa},
+ {sha256, rsa},
+ {sha224, ecdsa},
+ {sha224, rsa}],
+ IncludeLegacyAlg = SigAlgs ++ [LegacyAlg],
+ ssl_test_lib:basic_test( [{verify, verify_peer}, {signature_algs, IncludeLegacyAlg} | ClientOpts],
+ [{signature_algs, IncludeLegacyAlg} | ServerOpts], Config);
+run_sha1_cert_conf(_, #{client_config := ClientOpts, server_config := ServerOpts}, Config, _) ->
+ ssl_test_lib:basic_test([{verify, verify_peer} | ClientOpts], ServerOpts, Config).
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 573337e134..db306419aa 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -54,6 +54,8 @@
cipher_format/1,
tls_versions_option/0,
tls_versions_option/1,
+ spawn_opts_option/0,
+ spawn_opts_option/1,
eccs/0,
eccs/1,
cipher_suites/0,
@@ -74,8 +76,10 @@
fake_root_no_intermediate_legacy/1,
fake_intermediate_cert/0,
fake_intermediate_cert/1,
- incompleat_chain_length/0,
- incompleat_chain_length/1
+ incomplete_chain_length/0,
+ incomplete_chain_length/1,
+ user_dies/0,
+ user_dies/1
]).
%% Apply export
@@ -83,9 +87,11 @@
result_ok/1,
protocol_info_result/1,
version_info_result/1,
+ min_heap_size_info/1,
connect_dist_s/1,
connect_dist_c/1,
- dummy/1
+ dummy/1,
+ many_client_starter/4
]).
-define(TIMEOUT, 20000).
@@ -98,7 +104,7 @@
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-all() ->
+all() ->
[
{group, basic},
{group, options}
@@ -111,7 +117,7 @@ groups() ->
basic_tests() ->
[app,
- appup,
+ appup,
version_option,
connect_twice,
connect_dist,
@@ -119,15 +125,17 @@ basic_tests() ->
fallback,
cipher_format,
tls_versions_option,
+ spawn_opts_option,
eccs,
cipher_suites,
- cipher_suites_mix,
+ cipher_suites_mix,
fake_root,
fake_root_no_intermediate,
fake_root_legacy,
fake_root_no_intermediate_legacy,
fake_intermediate_cert,
- incompleat_chain_length
+ incomplete_chain_length,
+ user_dies
].
options_tests() ->
@@ -184,7 +192,7 @@ version_option() ->
version_option(Config) when is_list(Config) ->
Versions = proplists:get_value(supported, ssl:versions()),
[version_option_test(Config, Version) || Version <- Versions].
-
+
%%--------------------------------------------------------------------
connect_twice() ->
[{doc,""}].
@@ -237,7 +245,7 @@ defaults(Config) when is_list(Config)->
true = lists:member('tlsv1.1', proplists:get_value(available, Versions)),
false = lists:member('tlsv1.1', proplists:get_value(supported, Versions)),
true = lists:member('tlsv1.2', proplists:get_value(available, Versions)),
- true = lists:member('tlsv1.2', proplists:get_value(supported, Versions)),
+ true = lists:member('tlsv1.2', proplists:get_value(supported, Versions)),
true = lists:member('dtlsv1.2', proplists:get_value(available_dtls, Versions)),
true = lists:member('dtlsv1', proplists:get_value(available_dtls, Versions)),
true = lists:member('dtlsv1.2', proplists:get_value(supported_dtls, Versions)),
@@ -251,15 +259,15 @@ fallback(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Server =
- ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+
+ Server =
+ ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{options, ServerOpts}]),
-
+
Port = ssl_test_lib:inet_port(Server),
-
- Client =
+
+ Client =
ssl_test_lib:start_client_error([{node, ClientNode},
{port, Port}, {host, Hostname},
{from, self()}, {options,
@@ -267,7 +275,7 @@ fallback(Config) when is_list(Config) ->
{versions, ['tlsv1']}
| ClientOpts]}]),
ssl_test_lib:check_server_alert(Server, Client, inappropriate_fallback).
-
+
%%--------------------------------------------------------------------
cipher_format() ->
[{doc, "Test that cipher conversion from maps | tuples | strings to binarys works"}].
@@ -281,7 +289,7 @@ cipher_suites() ->
[{doc,"Test API function cipher_suites/2, filter_cipher_suites/2"
" and prepend|append_cipher_suites/2"}].
-cipher_suites(Config) when is_list(Config) ->
+cipher_suites(Config) when is_list(Config) ->
chipher_suite_checks('tlsv1.3'),
chipher_suite_checks('tlsv1.2'),
chipher_suite_checks('tlsv1.1'),
@@ -300,7 +308,7 @@ cipher_suites(Config) when is_list(Config) ->
cipher_suites_mix() ->
[{doc,"Test to have old and new cipher suites at the same time"}].
-cipher_suites_mix(Config) when is_list(Config) ->
+cipher_suites_mix(Config) when is_list(Config) ->
CipherSuites = [{dhe_rsa,aes_128_cbc,sha256,sha256}, {dhe_rsa,aes_128_cbc,sha}],
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
@@ -322,58 +330,58 @@ cipher_suites_mix(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
unordered_protocol_versions_server() ->
- [{doc,"Test that the highest protocol is selected even"
+ [{doc,"Test that the highest protocol is selected even"
" when it is not first in the versions list."}].
-unordered_protocol_versions_server(Config) when is_list(Config) ->
+unordered_protocol_versions_server(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | 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()},
+ {from, self()},
{mfa, {?MODULE, protocol_info_result, []}},
{options, ClientOpts}]),
- ServerMsg = ClientMsg = {ok,'tlsv1.2'},
+ ServerMsg = ClientMsg = {ok,'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
unordered_protocol_versions_client() ->
- [{doc,"Test that the highest protocol is selected even"
+ [{doc,"Test that the highest protocol is selected even"
" when it is not first in the versions list."}].
-unordered_protocol_versions_client(Config) when is_list(Config) ->
+unordered_protocol_versions_client(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, protocol_info_result, []}},
{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()},
+ {from, self()},
{mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
- ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
+ ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
-
+
connect_dist() ->
[{doc,"Test a simple connect as is used by distribution"}].
-connect_dist(Config) when is_list(Config) ->
+connect_dist(Config) when is_list(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{active, false}, {packet,4}|ClientOpts0],
ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
@@ -381,17 +389,17 @@ connect_dist(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, connect_dist_s, []}},
{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()},
+ {from, self()},
{mfa, {?MODULE, connect_dist_c, []}},
{options, ClientOpts}]),
-
+
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
@@ -419,31 +427,54 @@ tls_versions_option(Config) when is_list(Config) ->
Supported = proplists:get_value(supported, ssl:versions()),
Available = proplists:get_value(available, ssl:versions()),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, [{versions, Supported} | 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()},
+ {from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ClientOpts}]),
-
+
ssl_test_lib:check_result(Server, ok, Client, ok),
- Server ! listen,
+ Server ! listen,
Versions = remove_supported_versions(Available, Supported),
- ErrClient = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ ErrClient = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{options, [{versions , Versions} | ClientOpts]}]),
receive
{Server, _} ->
ok
- end,
+ end,
ssl_test_lib:check_client_alert(ErrClient, protocol_version).
+spawn_opts_option() ->
+ [{doc,"Test API spawn_opts option to sender/receiver."}].
+spawn_opts_option(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_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, min_heap_size_info, []}},
+ {options, [{sender_spawn_opts, [{min_heap_size, 1598}]},
+ {receiver_spawn_opts, [{min_heap_size, 2586}]} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, min_heap_size_info, []}},
+ {options, [{sender_spawn_opts, [{min_heap_size, 1598}]},
+ {receiver_spawn_opts, [{min_heap_size, 2586}]} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, {ok, 2586, 1598}, Client, {ok, 2586, 1598}).
+
fake_root() ->
[{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}].
fake_root(Config) when is_list(Config) ->
@@ -453,45 +484,41 @@ fake_root(Config) when is_list(Config) ->
ROOT = #{cert := Cert,
key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)},
{extensions, Ext}]),
-
FakeKey = ssl_test_lib:hardcode_rsa_key(1),
OTPCert = public_key:pkix_decode_cert(Cert, otp),
TBS = OTPCert#'OTPCertificate'.tbsCertificate,
FakeCert = public_key:pkix_sign(TBS, FakeKey),
-
AuthExt = #'AuthorityKeyIdentifier'{authorityCertIssuer = [{directoryName, TBS#'OTPTBSCertificate'.issuer}],
authorityCertSerialNumber = TBS#'OTPTBSCertificate'.serialNumber},
[AuthKeyExt] = x509_test:extensions([{?'id-ce-authorityKeyIdentifier',
AuthExt,
false}]),
-
#{server_config := ServerConf,
- client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
#{root => ROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)},
{extensions, [AuthKeyExt]}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
-
- #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
+ ),
+
+ #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
#{root => #{cert => FakeCert, key => FakeKey},
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)},
{extensions, [AuthKeyExt]}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
-
+ ),
test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, bad_certificate, bad_certificate).
-
+
fake_root_no_intermediate() ->
[{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}].
@@ -513,32 +540,30 @@ fake_root_no_intermediate(Config) when is_list(Config) ->
[AuthKeyExt] = x509_test:extensions([{?'id-ce-authorityKeyIdentifier',
AuthExt,
false}]),
-
-
#{server_config := ServerConf,
- client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
#{root => ROOT,
intermediates => [],
peer => [{key, ssl_test_lib:hardcode_rsa_key(4)},
{extensions, [AuthKeyExt]}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
-
- #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
+ ),
+
+ #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
#{root => #{cert => FakeCert, key => FakeKey},
intermediates => [],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)},
{extensions, [AuthKeyExt]}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
+ ),
test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, bad_certificate, bad_certificate).
-
+
fake_root_legacy() ->
[{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}].
fake_root_legacy(Config) when is_list(Config) ->
@@ -548,36 +573,34 @@ fake_root_legacy(Config) when is_list(Config) ->
ROOT = #{cert := Cert,
key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)},
{extensions, Ext}]),
-
FakeKey = ssl_test_lib:hardcode_rsa_key(1),
OTPCert = public_key:pkix_decode_cert(Cert, otp),
TBS = OTPCert#'OTPCertificate'.tbsCertificate,
FakeCert = public_key:pkix_sign(TBS, FakeKey),
-
#{server_config := ServerConf,
- client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
#{root => ROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
-
- #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
+ ),
+
+ #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
#{root => #{cert => FakeCert, key => FakeKey},
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
-
+ ),
+
test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, unknown_ca, unknown_ca).
-
+
fake_root_no_intermediate_legacy() ->
[{doc,"Test that we can not use a fake root signed by other key but with correct name and serial number."}].
fake_root_no_intermediate_legacy(Config) when is_list(Config) ->
@@ -592,27 +615,27 @@ fake_root_no_intermediate_legacy(Config) when is_list(Config) ->
OTPCert = public_key:pkix_decode_cert(Cert, otp),
TBS = OTPCert#'OTPCertificate'.tbsCertificate,
FakeCert = public_key:pkix_sign(TBS, FakeKey),
-
+
#{server_config := ServerConf,
- client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
#{root => ROOT,
intermediates => [],
peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
-
- #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
+ ),
+
+ #{server_config := FakeServerConf} = public_key:pkix_test_data(#{server_chain =>
#{root => #{cert => FakeCert, key => FakeKey},
intermediates => [],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
- ),
+ ),
test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, unknown_ca, unknown_ca).
fake_intermediate_cert() ->
@@ -620,34 +643,31 @@ fake_intermediate_cert() ->
fake_intermediate_cert(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]),
ROOT = #{cert := Cert,
key := _Key} = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)},
{extensions, Ext}]),
-
OtherSROOT = #{cert := OtherSCert,
key := OtherSKey} = public_key:pkix_test_root_cert("OTHER SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(3)},
{extensions, Ext}]),
OtherCROOT = #{cert := OtherCCert,
key := _OtherCKey} = public_key:pkix_test_root_cert("OTHER Client ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(1)},
{extensions, Ext}]),
-
- #{client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ #{client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
#{root => ROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
),
-
- #{server_config := OtherServerConf} = public_key:pkix_test_data(#{server_chain =>
+
+ #{server_config := OtherServerConf} = public_key:pkix_test_data(#{server_chain =>
#{root => OtherSROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]},
- client_chain =>
+ client_chain =>
#{root => OtherCROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
@@ -660,72 +680,68 @@ fake_intermediate_cert(Config) when is_list(Config) ->
[AuthKeyExt] = x509_test:extensions([{?'id-ce-authorityKeyIdentifier',
AuthExt,
false}]),
-
-
+
CAs = proplists:get_value(cacerts, OtherServerConf),
-
+
[ICA] = CAs -- [OtherSCert, OtherCCert],
-
+
OTPICACert = public_key:pkix_decode_cert(ICA, otp),
ICATBS = OTPICACert#'OTPCertificate'.tbsCertificate,
-
+
FakeICA = public_key:pkix_sign(ICATBS#'OTPTBSCertificate'{extensions = [AuthKeyExt | TBSExt]}, OtherSKey),
-
+
ServerCert = proplists:get_value(cert, OtherServerConf),
- FakeServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ FakeServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, [{cert, [ServerCert, FakeICA]} |
+ {options, [{cert, [ServerCert, FakeICA]} |
proplists:delete(cert, OtherServerConf)]
}]),
Port1 = ssl_test_lib:inet_port(FakeServer),
-
- Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port1},
+ Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port1},
{host, Hostname},
- {from, self()},
+ {from, self()},
{options, [{verify, verify_peer} | ClientConf]}]),
-
+
ssl_test_lib:check_client_alert(Client1, bad_certificate).
-incompleat_chain_length() ->
+incomplete_chain_length() ->
[{doc,"Test that attempts to reconstruct incomplete chains does not make shorter incomplete chains"}].
-incompleat_chain_length(Config) when is_list(Config)->
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+incomplete_chain_length(Config) when is_list(Config)->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]),
ROOT = public_key:pkix_test_root_cert("SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(6)},
{extensions, Ext}]),
-
+
OtherROOT = public_key:pkix_test_root_cert("OTHER SERVER ROOT CA", [{key, ssl_test_lib:hardcode_rsa_key(3)},
{extensions, Ext}]),
-
-
- #{client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
+ #{client_config := ClientConf} = public_key:pkix_test_data(#{server_chain =>
#{root => ROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
),
-
- #{server_config := ServerConf} = public_key:pkix_test_data(#{server_chain =>
+
+ #{server_config := ServerConf} = public_key:pkix_test_data(#{server_chain =>
#{root => OtherROOT,
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}],
[{key, ssl_test_lib:hardcode_rsa_key(3)}]
],
peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}
),
- VerifyFun = {fun(_,{bad_cert, unknown_ca}, UserState) ->
- %% accept this error to provoke the
+ VerifyFun = {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ %% accept this error to provoke the
%% building of an shorter incomplete chain
- %% than the one received
+ %% than the one received
{valid, UserState};
(_,{extension, _} = Extension, #{ext := N} = UserState) ->
ct:pal("~p", [Extension]),
@@ -741,20 +757,43 @@ incompleat_chain_length(Config) when is_list(Config)->
end, #{intermediates => 0,
ext => 0}},
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ServerConf}
]),
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()},
+ {from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, [{verify, verify_peer}, {verify_fun, VerifyFun} | ClientConf]}]),
ssl_test_lib:check_result(Client, ok, Server, ok).
+
+user_dies() ->
+ [{doc, "Test that we do not leak processess when user dies during startup of connection"}].
+user_dies(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Port = ssl_test_lib:inet_port(ServerNode),
+ Server = spawn_link(fun() ->
+ {ok, L} = ssl:listen(Port, ServerOpts),
+ loop(L)
+ end),
+ do_wait_tls_server(Hostname, Port),
+ {ok,_} = ssl:connect(Hostname, Port, ClientOpts),
+ check_process_count(2),
+ Pid = spawn_link(fun() -> many_client_starter(Hostname, Port, ClientOpts, Server) end),
+ receive
+ {'EXIT', Pid, _} ->
+ check_process_count(2)
+ end.
+
%%--------------------------------------------------------------------
%% callback functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -775,7 +814,11 @@ version_info_result(Socket) ->
{ok, [{version, Version}]} = ssl:connection_information(Socket, [version]),
{ok, Version}.
-
+min_heap_size_info(#sslsocket{pid = [Receiver, Sender]}) ->
+ {garbage_collection, ReceiverGc} = process_info(Receiver, garbage_collection),
+ {garbage_collection, SenderGc} = process_info(Sender, garbage_collection),
+ {ok, proplists:get_value(min_heap_size, ReceiverGc), proplists:get_value(min_heap_size, SenderGc)}.
+
connect_dist_s(S) ->
Msg = term_to_binary({erlang,term}),
ok = ssl:send(S, Msg).
@@ -796,24 +839,22 @@ version_option_test(Config, Version) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- Server =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {ssl_test_lib, send_recv_result, []}},
{options, [{active, false}, {versions, [Version]}| 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()},
+ {from, self()},
{mfa, {ssl_test_lib, send_recv_result, []}},
{options, [{active, false}, {versions, [Version]}| ClientOpts]}]),
-
+
ct:log("Testcase ~p, Client ~p Server ~p ~n",
[self(), Client, Server]),
-
ssl_test_lib:check_result(Server, ok, Client, ok),
-
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
@@ -829,56 +870,53 @@ remove_supported_versions(Available, Supported) ->
end.
-test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf, ResultRootIncluded, ResultRootExcluded) ->
- RealServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+test_fake_root(Hostname, ServerNode, ClientNode, ServerConf, ClientConf, FakeCert, FakeServerConf,
+ ResultRootIncluded, ResultRootExcluded) ->
+ RealServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ServerConf}]),
Port0 = ssl_test_lib:inet_port(RealServer),
- Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port0},
+ Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port0},
{host, Hostname},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
- {from, self()},
+ {from, self()},
{options, [{verify, verify_peer} | ClientConf]}]),
-
+
ssl_test_lib:check_result(RealServer, ok, Client0, ok),
-
+
ssl_test_lib:close(RealServer),
ssl_test_lib:close(Client0),
-
+
%% Fake server sends ROOT cert
- FakeServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ FakeServer = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {ssl_test_lib, no_result, []}},
{options, FakeServerConf}]),
Port1 = ssl_test_lib:inet_port(FakeServer),
-
- Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port1},
+
+ Client1 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port1},
{host, Hostname},
- {from, self()},
+ {from, self()},
{options, [{verify, verify_peer} | ClientConf]}]),
-
+
ssl_test_lib:check_client_alert(Client1, ResultRootIncluded),
-
-
+
%%Fake server does not send ROOT cert
CAS0 = proplists:get_value(cacerts, FakeServerConf),
CAS1 = CAS0 -- [FakeCert],
-
- FakeServer1 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
+
+ FakeServer1 = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result, []}},
{options, [{cacerts, CAS1} | proplists:delete(cacerts, FakeServerConf)]}]),
-
+
Port2 = ssl_test_lib:inet_port(FakeServer1),
-
- Client2 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port2},
+ Client2 = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port2},
{host, Hostname},
- {from, self()},
+ {from, self()},
{options, [{verify, verify_peer} | ClientConf]}]),
-
ssl_test_lib:check_client_alert(Client2, ResultRootExcluded),
-
ssl_test_lib:close(FakeServer1).
anon_chipher_suite_checks('tlsv1.3' = Version) ->
@@ -953,4 +991,58 @@ chipher_suite_checks(Version) ->
'dtlsv1.2' ->
ok
end.
-
+
+many_client_starter(Hostname, Port, ClientOpts, Server) ->
+ spawn_clients(Hostname, Port, ClientOpts, 50),
+ ct:sleep(100),
+ many_client_starter(Hostname, Port, ClientOpts, Server).
+
+spawn_clients(_, _, _, 0) ->
+ ok;
+spawn_clients(Hostname, Port, ClientOpts, N) ->
+ spawn_link(fun() ->
+ case N of
+ 20 ->
+ exit(self(), kill);
+ _ ->
+ {ok, _} = ssl:connect(Hostname, Port, ClientOpts)
+ end
+ end),
+ spawn_clients(Hostname, Port, ClientOpts, N-1).
+
+loop(L) ->
+ {ok, A} = ssl:transport_accept(L),
+ spawn(fun() ->
+ ssl:handshake(A)
+ end),
+ loop(L).
+
+check_process_count(Count) ->
+ check_process_count(Count, 5).
+
+check_process_count(Count, 0) ->
+ Count = proplists:get_value(supervisors, supervisor:count_children(tls_connection_sup));
+check_process_count(Count, Try) ->
+ case proplists:get_value(supervisors, supervisor:count_children(tls_connection_sup)) of
+ Count ->
+ ok;
+ Other ->
+ ct:pal("Not expected number of cildren ~p on try ~p", [Other, Try]),
+ ct:sleep(500), %% Wait long enough
+ check_process_count(Count, Try - 1)
+ end.
+
+do_wait_tls_server(Hostname, Port) ->
+ do_wait_tls_server(Hostname, Port, 5).
+
+do_wait_tls_server(_,_, 0)->
+ ct:fail(to_connect_to_server);
+do_wait_tls_server(Hostname, Port, Try) ->
+ case gen_tcp:connect(Hostname, Port, []) of
+ {ok, S} ->
+ gen_tcp:close(S),
+ ok;
+ _ ->
+ ct:sleep(?SLEEP),
+ do_wait_tls_server(Hostname, Port, Try-1)
+ end.
diff --git a/lib/ssl/test/ssl_bench.spec b/lib/ssl/test/ssl_bench.spec
index 217cc6fc83..38c8b35cf4 100644
--- a/lib/ssl/test/ssl_bench.spec
+++ b/lib/ssl/test/ssl_bench.spec
@@ -1,2 +1,3 @@
-{suites,"../ssl_test",[ssl_bench_SUITE, ssl_dist_bench_SUITE]}.
-{skip_groups,"../ssl_test",ssl_bench_SUITE,basic,"Benchmarks run separately"}.
+{alias, dir, "../ssl_test"}.
+{groups, dir, ssl_dist_bench_SUITE, [benchmark]}.
+{groups, dir, ssl_bench_SUITE, [benchmark]}.
diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl
index f78ac9c9cc..41970ba66b 100644
--- a/lib/ssl/test/ssl_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -60,38 +60,81 @@
test/2
]).
+
+-define(COUNT, 400).
+-define(REDUCE, 40). % (?COUNT rem ?REDUCE) should be 0
+%% (?COUNT div ?REDUCE) is the count used for a non-benchmark run
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
-all() -> [{group, setup}, {group, payload}].
+all() ->
+ %% {repeat,_} here overrides {repeat,_} in groups()
+ [{group, setup, [{repeat,1}]},
+ {group, payload, [{repeat,1}]}].
groups() ->
- [{setup, [{repeat, 3}], [setup_sequential, setup_sequential_noreuse, setup_sequential_13,
- setup_concurrent, setup_concurrent_noreuse, setup_concurrent_13]},
- {payload, [{repeat, 3}], [payload, payload_13]}
+ [{benchmark, [{group, G} || {group, G, _} <- all()]},
+ %%
+ {setup, [{repeat,3}],
+ [setup_sequential, setup_sequential_noreuse, setup_sequential_13,
+ setup_concurrent, setup_concurrent_noreuse, setup_concurrent_13]},
+ {payload, [{repeat,3}],
+ [payload, payload_13]}
].
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, _Config) ->
- ok.
+%%-------
init_per_suite(Config) ->
ct:timetrap({minutes, 1}),
- case node() of
- nonode@nohost ->
- {skipped, "Node not distributed"};
- _ ->
- ssl_test_lib:clean_start(),
- [{server_node, ssl_bench_test_lib:setup(perf_server)}|Config]
+ Skipped = make_ref(),
+ try
+ node() =/= nonode@nohost
+ orelse throw({Skipped, "Node not distributed"}),
+ %%
+ ssl_test_lib:clean_start(),
+ [{server_node, ssl_bench_test_lib:setup(perf_server)}|Config]
+ catch
+ throw : {Skipped, Reason} ->
+ {skipped, Reason};
+ Class : Reason : Stacktrace ->
+ {failed, {Class, Reason, Stacktrace}}
end.
end_per_suite(_Config) ->
ok.
+%%-------
+
+init_per_group(benchmark, Config) ->
+ [{effort,?REDUCE} | Config];
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%-------
+
+init_per_testcase(Func, Conf)
+ when Func =:= setup_sequential_13;
+ Func =:= setup_concurrent_13;
+ Func =:= payload_13 ->
+ try
+ TLSVersion = 'tlsv1.3',
+ {supported, SSLVersions} =
+ lists:keyfind(supported, 1, ssl:versions()),
+ case lists:member(TLSVersion, SSLVersions) of
+ true ->
+ Conf;
+ false ->
+ {skipped, {not_supported,TLSVersion,SSLVersions}}
+ end
+ catch Class : Reason : Stacktrace ->
+ {failed, {Class,Reason,Stacktrace}}
+ end;
init_per_testcase(_Func, Conf) ->
Conf.
@@ -103,8 +146,9 @@ end_per_testcase(_Func, _Conf) ->
%%--------------------------------------------------------------------
--define(COUNT, 400).
--define(TC(Cmd), tc(fun() -> Cmd end, ?MODULE, ?LINE)).
+%%-define(TC(Cmd), tc(fun() -> Cmd end, ?MODULE, ?LINE)).
+count(Config) ->
+ (proplists:get_value(effort, Config, 1) * ?COUNT) div ?REDUCE.
-define(FPROF_CLIENT, false).
-define(FPROF_SERVER, false).
@@ -117,7 +161,8 @@ setup_sequential(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.2'}],
- {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT * 20, 1, Server),
+ {ok, Result} =
+ do_test(ssl, {setup_connection,Cfg}, 20*count(Config), 1, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Sequential setup"}]}),
@@ -127,7 +172,8 @@ setup_sequential_noreuse(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.2'}, no_reuse],
- {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT * 20, 1, Server),
+ {ok, Result} =
+ do_test(ssl, {setup_connection,Cfg}, 20*count(Config), 1, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Seq setup 1.2 no session"}]}),
@@ -137,7 +183,8 @@ setup_sequential_13(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.3'}],
- {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT * 20, 1, Server),
+ {ok, Result} =
+ do_test(ssl, {setup_connection,Cfg}, 20*count(Config), 1, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Seq setup 1.3"}]}),
@@ -147,7 +194,8 @@ setup_concurrent(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.2'}],
- {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT, 100, Server),
+ {ok, Result} =
+ do_test(ssl, {setup_connection,Cfg}, count(Config), 100, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Concurrent setup"}]}),
@@ -157,7 +205,8 @@ setup_concurrent_noreuse(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.2'}, no_reuse],
- {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT, 100, Server),
+ {ok, Result} =
+ do_test(ssl, {setup_connection,Cfg}, count(Config), 100, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Conc setup 1.2 no session"}]}),
@@ -167,7 +216,8 @@ setup_concurrent_13(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.3'}],
- {ok, Result} = do_test(ssl, {setup_connection,Cfg}, ?COUNT, 100, Server),
+ {ok, Result} =
+ do_test(ssl, {setup_connection,Cfg}, count(Config), 100, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Conc setup 1.3"}]}),
@@ -177,7 +227,8 @@ payload(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.2'}],
- {ok, Result} = do_test(ssl, {payload, Cfg}, ?COUNT*300, 10, Server),
+ {ok, Result} =
+ do_test(ssl, {payload, Cfg}, 300*count(Config), 10, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Payload simple"}]}),
@@ -187,7 +238,8 @@ payload_13(Config) ->
Server = proplists:get_value(server_node, Config),
Server =/= undefined orelse error(no_server),
Cfg = [{version, 'tlsv1.3'}],
- {ok, Result} = do_test(ssl, {payload, Cfg}, ?COUNT*300, 10, Server),
+ {ok, Result} =
+ do_test(ssl, {payload, Cfg}, 300*count(Config), 10, Server),
ct_event:notify(#event{name = benchmark_data,
data=[{value, Result},
{suite, "ssl"}, {name, "Payload 1.3"}]}),
@@ -365,6 +417,7 @@ setup_server_init(Type, Tc, Loop, PC, Certs) ->
unlink(Pid),
Res.
+-ifdef(TC).
tc(Fun, Mod, Line) ->
case timer:tc(Fun) of
{_,{'EXIT',Reason}} ->
@@ -377,6 +430,7 @@ tc(Fun, Mod, Line) ->
io:format("~p:~p: Time: ~p\n", [Mod, Line, T]),
R
end.
+-endif.
start_profile(eprof, Procs) ->
profiling = eprof:start_profiling(Procs),
diff --git a/lib/ssl/test/ssl_bench_test_lib.erl b/lib/ssl/test/ssl_bench_test_lib.erl
index 04cda889df..648b42fb03 100644
--- a/lib/ssl/test/ssl_bench_test_lib.erl
+++ b/lib/ssl/test/ssl_bench_test_lib.erl
@@ -20,7 +20,7 @@
-module(ssl_bench_test_lib).
%% API
--export([setup/1]).
+-export([setup/1, cleanup/1]).
%% Internal exports
-export([setup_server/1]).
@@ -28,6 +28,51 @@
-define(remote_host, "NETMARKS_REMOTE_HOST").
setup(Name) ->
+ NameStr = atom_to_list(Name),
+ case os:getenv(?remote_host) of
+ false ->
+ {ok, Host} = inet:gethostname(),
+ Remote = false,
+ ok;
+ Host ->
+ Remote = true,
+ ok
+ end,
+ Node = list_to_atom(NameStr ++ "@" ++ Host),
+ case net_adm:ping(Node) of
+ pong ->
+ Node;
+ pang ->
+ PeerOptions =
+ #{name => NameStr,
+ host => Host},
+ ct:pal("PeerOptions: ~p~n", [PeerOptions]),
+ {ok, _Pid, Node} =
+ peer:start(
+ case Remote of
+ true ->
+ Ssh = find_executable("ssh"),
+ Erl = find_executable("erl"),
+ PeerOptions#{exec => {Ssh, [Host, Erl]}};
+ false ->
+ PeerOptions
+ end),
+ Path = code:get_path(),
+ true = erpc:call(Node, code, set_path, [Path]),
+ ok = erpc:call(Node, ?MODULE, setup_server, [node()]),
+ ct:pal("Client (~p) using ~ts~n",[node(), code:which(ssl)]),
+ (Node =:= node()) andalso restrict_schedulers(client),
+ Node
+ end.
+
+find_executable(Prog) ->
+ case os:find_executable(Prog) of
+ false -> Prog;
+ P -> P
+ end.
+
+-ifdef(undefined).
+setup(Name) ->
Host = case os:getenv(?remote_host) of
false ->
{ok, This} = inet:gethostname(),
@@ -61,6 +106,7 @@ setup(Name) ->
ct:pal("Client (~p) using ~ts~n",[node(), code:which(ssl)]),
(Node =:= node()) andalso restrict_schedulers(client),
Node.
+-endif.
setup_server(ClientNode) ->
(ClientNode =:= node()) andalso restrict_schedulers(server),
@@ -73,3 +119,14 @@ restrict_schedulers(Type) ->
Extra = if (Type =:= server) -> -Extra0; true -> Extra0 end,
Scheds = erlang:system_info(schedulers),
erlang:system_flag(schedulers_online, (Scheds div 2) + Extra).
+
+cleanup(Node) ->
+ try erpc:call(Node, erlang, halt, [], 5000) of
+ Result ->
+ ct:fail({unexpected_return, Result})
+ catch
+ error : {erpc,noconnection} ->
+ ok;
+ Class : Reason : Stacktrace ->
+ ct:fail({unexpected_exception, {Class,Reason,Stacktrace}})
+ end.
diff --git a/lib/ssl/test/ssl_cert_SUITE.erl b/lib/ssl/test/ssl_cert_SUITE.erl
index 6b0b6f5f4d..315c0e20b1 100644
--- a/lib/ssl/test/ssl_cert_SUITE.erl
+++ b/lib/ssl/test/ssl_cert_SUITE.erl
@@ -46,12 +46,12 @@
client_auth_empty_cert_accepted/1,
client_auth_empty_cert_rejected/0,
client_auth_empty_cert_rejected/1,
- client_auth_partial_chain/0,
- client_auth_partial_chain/1,
- client_auth_allow_partial_chain/0,
- client_auth_allow_partial_chain/1,
- client_auth_do_not_allow_partial_chain/0,
- client_auth_do_not_allow_partial_chain/1,
+ client_auth_no_suitable_chain/0,
+ client_auth_no_suitable_chain/1,
+ client_auth_use_partial_chain/0,
+ client_auth_use_partial_chain/1,
+ client_auth_do_not_use_partial_chain/0,
+ client_auth_do_not_use_partial_chain/1,
client_auth_partial_chain_fun_fail/0,
client_auth_partial_chain_fun_fail/1,
client_auth_sni/0,
@@ -72,6 +72,8 @@
verify_fun_always_run_server/1,
incomplete_chain_auth/0,
incomplete_chain_auth/1,
+ no_chain_client_auth/0,
+ no_chain_client_auth/1,
invalid_signature_client/0,
invalid_signature_client/1,
invalid_signature_server/0,
@@ -121,7 +123,9 @@
signature_algorithms_bad_curve_secp384r1/0,
signature_algorithms_bad_curve_secp384r1/1,
signature_algorithms_bad_curve_secp521r1/0,
- signature_algorithms_bad_curve_secp521r1/1
+ signature_algorithms_bad_curve_secp521r1/1,
+ server_certificate_authorities_disabled/0,
+ server_certificate_authorities_disabled/1
]).
%%--------------------------------------------------------------------
@@ -186,9 +190,11 @@ tls_1_3_tests() ->
[
hello_retry_request,
custom_groups,
+ client_auth_no_suitable_chain,
hello_retry_client_auth,
hello_retry_client_auth_empty_cert_accepted,
- hello_retry_client_auth_empty_cert_rejected
+ hello_retry_client_auth_empty_cert_rejected,
+ server_certificate_authorities_disabled
].
pre_tls_1_3_rsa_tests() ->
@@ -221,9 +227,8 @@ all_version_tests() ->
auth,
client_auth_empty_cert_accepted,
client_auth_empty_cert_rejected,
- client_auth_partial_chain,
- client_auth_allow_partial_chain,
- client_auth_do_not_allow_partial_chain,
+ client_auth_use_partial_chain,
+ client_auth_do_not_use_partial_chain,
client_auth_partial_chain_fun_fail,
client_auth_sni,
missing_root_cert_no_auth,
@@ -233,6 +238,7 @@ all_version_tests() ->
verify_fun_always_run_client,
verify_fun_always_run_server,
incomplete_chain_auth,
+ no_chain_client_auth,
invalid_signature_client,
invalid_signature_server,
critical_extension_auth,
@@ -449,21 +455,21 @@ client_auth_empty_cert_rejected() ->
client_auth_empty_cert_rejected(Config) ->
ssl_cert_tests:client_auth_empty_cert_rejected(Config).
%%--------------------------------------------------------------------
-client_auth_partial_chain() ->
- ssl_cert_tests:client_auth_partial_chain().
-client_auth_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_partial_chain(Config).
+client_auth_no_suitable_chain() ->
+ ssl_cert_tests:client_auth_no_suitable_chain().
+client_auth_no_suitable_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_no_suitable_chain(Config).
%%--------------------------------------------------------------------
-client_auth_allow_partial_chain() ->
- ssl_cert_tests:client_auth_allow_partial_chain().
-client_auth_allow_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_allow_partial_chain(Config).
+client_auth_use_partial_chain() ->
+ ssl_cert_tests:client_auth_use_partial_chain().
+client_auth_use_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_use_partial_chain(Config).
%%--------------------------------------------------------------------
-client_auth_do_not_allow_partial_chain() ->
- ssl_cert_tests:client_auth_do_not_allow_partial_chain().
-client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
- ssl_cert_tests:client_auth_do_not_allow_partial_chain(Config).
+client_auth_do_not_use_partial_chain() ->
+ ssl_cert_tests:client_auth_do_not_use_partial_chain().
+client_auth_do_not_use_partial_chain(Config) when is_list(Config) ->
+ ssl_cert_tests:client_auth_do_not_use_partial_chain(Config).
%%--------------------------------------------------------------------
client_auth_partial_chain_fun_fail() ->
@@ -573,6 +579,8 @@ missing_root_cert_auth_user_verify_fun_reject(Config) ->
ClientOpts = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
{verify_fun, FunAndState}], Config),
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+
+
%%--------------------------------------------------------------------
incomplete_chain_auth() ->
[{doc,"Test that we can verify an incompleat chain when we have the certs to rebuild it"}].
@@ -595,6 +603,31 @@ incomplete_chain_auth(Config) when is_list(Config) ->
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
+no_chain_client_auth() ->
+ [{doc,"In TLS-1.3 test that we allow sending only peer cert if chain CAs are missing and hence"
+ " we can not determine if client is in servers auth domain or not, so send and hope"
+ " that the cert chain is in the auth domain and that the server possess "
+ " intermediates to recreate the chain."}].
+no_chain_client_auth(Config) when is_list(Config) ->
+ Prop = proplists:get_value(tc_group_properties, Config),
+ Group = proplists:get_value(name, Prop),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(Group),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain, DefaultCertConf},
+ {client_chain, DefaultCertConf}]),
+ ServerCas = proplists:get_value(cacerts, ServerOpts0),
+ [ClientRoot| _] = ClientCas = proplists:get_value(cacerts, ClientOpts0),
+ ClientOpts = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
+ {cacerts, [ClientRoot]} |
+ proplists:delete(cacerts, ClientOpts0)], Config),
+ ServerOpts = ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer},
+ {fail_if_no_peer_cert, true},
+ {cacerts, ClientCas ++ ServerCas} |
+ proplists:delete(cacerts, ServerOpts0)], Config),
+ ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+%%--------------------------------------------------------------------
verify_fun_always_run_client() ->
[{doc,"Verify that user verify_fun is always run (for valid and "
"valid_peer not only unknown_extension)"}].
@@ -614,13 +647,17 @@ verify_fun_always_run_client(Config) when is_list(Config) ->
%% If user verify fun is called correctly we fail the connection.
%% otherwise we cannot tell this case apart form where we miss
%% to call users verify fun
- FunAndState = {fun(_,{extension, _}, UserState) ->
+ FunAndState = {fun(_, Der, {extension, _}, UserState) ->
+ true = is_binary(Der),
{unknown, UserState};
- (_, valid, [ChainLen]) ->
+ (_, Der, valid, [ChainLen]) ->
+ true = is_binary(Der),
{valid, [ChainLen + 1]};
- (_, valid_peer, [1]) ->
+ (_, Der, valid_peer, [1]) ->
+ true = is_binary(Der),
{fail, "verify_fun_was_always_run"};
- (_, valid_peer, UserState) ->
+ (_, Der, valid_peer, UserState) ->
+ true = is_binary(Der),
{valid, UserState}
end, [0]},
@@ -648,13 +685,17 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
%% If user verify fun is called correctly we fail the connection.
%% otherwise we cannot tell this case apart form where we miss
%% to call users verify fun
- FunAndState = {fun(_,{extension, _}, UserState) ->
+ FunAndState = {fun(_, Der, {extension, _}, UserState) ->
+ true = is_binary(Der),
{unknown, UserState};
- (_, valid, [ChainLen]) ->
+ (_, Der, valid, [ChainLen]) ->
+ true = is_binary(Der),
{valid, [ChainLen + 1]};
- (_, valid_peer, [1]) ->
+ (_, Der, valid_peer, [1]) ->
+ true = is_binary(Der),
{fail, "verify_fun_was_always_run"};
- (_, valid_peer, UserState) ->
+ (_, Der, valid_peer, UserState) ->
+ true = is_binary(Der),
{valid, UserState}
end, [0]},
@@ -859,8 +900,8 @@ cert_expired(Config) when is_list(Config) ->
#{client_config := ClientOpts0,
server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
[{server_chain,
- [[],
- [{validity, {{Year-2, Month, Day},
+ [[],
+ [{validity, {{Year-2, Month, Day},
{Year-1, Month, Day}}}],
[]
]},
@@ -1121,7 +1162,7 @@ unsupported_sign_algo_cert_client_auth(Config) ->
'tlsv1.3' ->
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required);
_ ->
- ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, insufficient_security)
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, bad_certificate)
end.
%%--------------------------------------------------------------------
@@ -1202,7 +1243,7 @@ signature_algorithms_bad_curve_secp256r1(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
%% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, {log_level, debug}|ServerOpts0],
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{signature_algs, [ecdsa_secp384r1_sha384,
ecdsa_secp521r1_sha512,
@@ -1219,7 +1260,7 @@ signature_algorithms_bad_curve_secp384r1(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
%% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, {log_level, debug}|ServerOpts0],
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{signature_algs, [ecdsa_secp256r1_sha256,
ecdsa_secp521r1_sha512,
@@ -1236,7 +1277,7 @@ signature_algorithms_bad_curve_secp521r1(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
%% Set versions
- ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, {log_level, debug}|ServerOpts0],
+ ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{signature_algs, [ecdsa_secp256r1_sha256,
ecdsa_secp384r1_sha384,
@@ -1258,6 +1299,42 @@ basic_rsa_1024(Config) ->
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
+server_certificate_authorities_disabled() ->
+ [{doc,"TLS 1.3: Disabling certificate_authorities extension on the server when verify_peer is set to true"
+ " allows the client to send a chain that could be verifiable by the server but that would not adhere to"
+ " the certificate_authorities extension as it is not part of the regular trusted certificate set"}].
+
+server_certificate_authorities_disabled(Config) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ % Strip out the ClientRoot to simulate cases where the they are manually managed and
+ % not expected to be included in certificate requests during mutual authentication.
+ {ok, CACerts0} = ssl_pkix_db:decode_pem_file(proplists:get_value(cacertfile, ServerOpts0)),
+ [_ClientRoot | ServerCACerts] = [CertDER || {_, CertDER, _} <- CACerts0],
+
+ FunAndState = {fun(_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState};
+ % Because this is a manually managed setup, we also need to manually verify
+ % an unknown_ca (ClientCert) as expected. Typically you would have custom logic
+ % here to decide if you know the cert (like looking up pinned values in a DB)
+ % but for testing purposes, we'll allow everything
+ (_, {bad_cert, unknown_ca}, UserState) ->
+ {valid, UserState};
+ (_, valid_peer, UserState) ->
+ {valid, UserState}
+ end, [0]},
+
+ ClientOpts = [{versions, ['tlsv1.3']}, {verify, verify_peer} | ClientOpts0],
+ ServerOpts = [{versions, ['tlsv1.3']}, {verify, verify_peer},
+ {fail_if_no_peer_cert, true}, {cacerts, ServerCACerts},
+ {verify_fun, FunAndState} | ServerOpts0],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required),
+ ssl_test_lib:basic_test(ClientOpts, [{certificate_authorities, false} | ServerOpts], Config).
+
+%%--------------------------------------------------------------------
%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
n_version(Version) when
diff --git a/lib/ssl/test/ssl_cert_tests.erl b/lib/ssl/test/ssl_cert_tests.erl
index c7a88e961e..b6fb9f4724 100644
--- a/lib/ssl/test/ssl_cert_tests.erl
+++ b/lib/ssl/test/ssl_cert_tests.erl
@@ -32,12 +32,12 @@
client_auth_empty_cert_accepted/1,
client_auth_empty_cert_rejected/0,
client_auth_empty_cert_rejected/1,
- client_auth_partial_chain/0,
- client_auth_partial_chain/1,
- client_auth_allow_partial_chain/0,
- client_auth_allow_partial_chain/1,
- client_auth_do_not_allow_partial_chain/0,
- client_auth_do_not_allow_partial_chain/1,
+ client_auth_no_suitable_chain/0,
+ client_auth_no_suitable_chain/1,
+ client_auth_use_partial_chain/0,
+ client_auth_use_partial_chain/1,
+ client_auth_do_not_use_partial_chain/0,
+ client_auth_do_not_use_partial_chain/1,
client_auth_partial_chain_fun_fail/0,
client_auth_partial_chain_fun_fail/1,
client_auth_sni/0,
@@ -99,8 +99,7 @@ auth(Config) ->
%%--------------------------------------------------------------------
client_auth_empty_cert_accepted() ->
- [{doc,"Test client authentication when client sends an empty certificate and "
- "fail_if_no_peer_cert is set to false."}].
+ [{doc,"Client sends empty cert chain as no cert is configured and server allows it"}].
client_auth_empty_cert_accepted(Config) ->
ClientOpts = proplists:delete(keyfile,
@@ -112,8 +111,7 @@ client_auth_empty_cert_accepted(Config) ->
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
client_auth_empty_cert_rejected() ->
- [{doc,"Test client authentication when client sends an empty certificate and "
- "fail_if_no_peer_cert is set to true."}].
+ [{doc,"Client sends empty cert chain as no cert is configured"}].
client_auth_empty_cert_rejected(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
@@ -131,30 +129,49 @@ client_auth_empty_cert_rejected(Config) ->
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, handshake_failure)
end.
%%--------------------------------------------------------------------
-client_auth_partial_chain() ->
- [{doc, "Client sends an incomplete chain, by default not acceptable."}].
-
-client_auth_partial_chain(Config) when is_list(Config) ->
+client_auth_no_suitable_chain() ->
+ [{doc, "Client sends an empty cert chain as no suitable chain is found."}].
+
+client_auth_no_suitable_chain(Config) when is_list(Config) ->
+ CRoot = public_key:pkix_test_root_cert("OTP other client test ROOT", []),
+ #{client_config := ClientOpts0} = public_key:pkix_test_data(#{server_chain => #{root => [],
+ intermediates => [[]],
+ peer => []},
+ client_chain => #{root => CRoot,
+ intermediates => [[]],
+ peer => []}}),
+ ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
| ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
- ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
- {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts0)),
- [{_,RootCA,_} | _] = public_key:pem_decode(ClientCAs),
- ClientOpts = [{cacerts, [RootCA]} |
- proplists:delete(cacertfile, ClientOpts0)],
- ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
-
-%%--------------------------------------------------------------------
-client_auth_allow_partial_chain() ->
- [{doc, "Server trusts intermediat CA and accepts a partial chain. (partial_chain option)"}].
+ Version = proplists:get_value(version, Config),
-client_auth_allow_partial_chain(Config) when is_list(Config) ->
- ServerOpts0 = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
- {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts)),
- [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ClientCAs),
+ case Version of
+ 'tlsv1.3' ->
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required);
+ _ ->
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, handshake_failure)
+ end.
+%%--------------------------------------------------------------------
+client_auth_use_partial_chain() ->
+ [{doc, "Client trusts intermediat CA and verifies the shorter chain."}].
+
+client_auth_use_partial_chain(Config) when is_list(Config) ->
+ Prop = proplists:get_value(tc_group_properties, Config),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
+ {Year, Month, Day} = date(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
+ ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
+ [_, IntermidiateCA, _] = proplists:get_value(cacerts, ServerOpts),
PartialChain = fun(CertChain) ->
case lists:member(IntermidiateCA, CertChain) of
true ->
@@ -163,52 +180,58 @@ client_auth_allow_partial_chain(Config) when is_list(Config) ->
unknown_ca
end
end,
- ServerOpts = [{cacerts, [IntermidiateCA]},
- {partial_chain, PartialChain} |
- proplists:delete(cacertfile, ServerOpts0)],
-
- ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+ ssl_test_lib:basic_test([{verify, verify_peer}, {partial_chain, PartialChain} |ClientOpts], ServerOpts, Config).
%%--------------------------------------------------------------------
-client_auth_do_not_allow_partial_chain() ->
- [{doc, "Server does not accept the chain sent by the client as ROOT CA is unknown, "
- "and we do not choose to trust the intermediate CA. (partial_chain option)"}].
-
-client_auth_do_not_allow_partial_chain(Config) when is_list(Config) ->
- ServerOpts0 = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
- {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts0)),
- [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
-
+client_auth_do_not_use_partial_chain() ->
+ [{doc, "Client does not trust an intermediat CA and fails the connetion as ROOT has expired"}].
+
+client_auth_do_not_use_partial_chain(Config) when is_list(Config) ->
+ Prop = proplists:get_value(tc_group_properties, Config),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
+ {Year, Month, Day} = date(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
PartialChain = fun(_CertChain) ->
unknown_ca
end,
- ServerOpts = [{cacerts, [IntermidiateCA]},
- {partial_chain, PartialChain} |
- proplists:delete(cacertfile, ServerOpts0)],
- ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
+ ClientOpts = [{verify, verify_peer}, {partial_chain, PartialChain} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_expired).
%%--------------------------------------------------------------------
client_auth_partial_chain_fun_fail() ->
- [{doc, "If parial_chain fun crashes, treat it as if it returned unkown_ca"}].
+ [{doc, "If partial_chain fun crashes, treat it as if it returned unkown_ca"}].
client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
- ServerOpts0 = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ Prop = proplists:get_value(tc_group_properties, Config),
+ DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
+ {Year, Month, Day} = date(),
+ #{client_config := ClientOpts0,
+ server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
- {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts0)),
- [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
PartialChain = fun(_CertChain) ->
error(crash_on_purpose)
end,
- ServerOpts = [{cacerts, [IntermidiateCA]},
- {partial_chain, PartialChain} |
- proplists:delete(cacertfile, ServerOpts0)],
+ ClientOpts = [{verify, verify_peer}, {partial_chain, PartialChain} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ServerOpts = [ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
+ ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_expired).
- ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
%%--------------------------------------------------------------------
client_auth_sni() ->
@@ -286,7 +309,7 @@ invalid_signature_client(Config) when is_list(Config) ->
NewClientDerCert = public_key:pkix_sign(ClientOTPTbsCert, Key),
ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]),
ClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts0)],
- ServerOpts = [{verify, verify_peer} | ServerOpts0],
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} | ServerOpts0],
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
index 40592870a1..def13d0860 100644
--- a/lib/ssl/test/ssl_cipher_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,9 +74,17 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_TestCase, Config) ->
ct:timetrap({seconds, 5}),
- Config.
+ _ = application:load(ssl),
+ Previous = case logger:get_module_level(ssl) of
+ [] -> notice;
+ [{ssl,P}] -> P
+ end,
+ ok = logger:set_application_level(ssl, debug),
+ [{app_log_level, Previous}|Config].
end_per_testcase(_TestCase, Config) ->
+ Previous = proplists:get_value(app_log_level, Config),
+ logger:set_application_level(ssl, Previous),
Config.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
index 22dbc3663c..0ddbf59e56 100644
--- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl
+++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -386,7 +386,7 @@ init_per_testcase(TestCase, Config) when TestCase == psk_3des_ede_cbc;
TestCase == ecdh_anon_3des_ede_cbc;
TestCase == ecdhe_ecdsa_3des_ede_cbc ->
SupCiphers = proplists:get_value(ciphers, crypto:supports()),
- case lists:member(des_ede3, SupCiphers) of
+ case lists:member(des_ede3_cbc, SupCiphers) of
true ->
ct:timetrap(?TIMEOUT),
Config;
diff --git a/lib/ssl/test/ssl_crl_SUITE.erl b/lib/ssl/test/ssl_crl_SUITE.erl
index 58b0f8cb76..6f4485d438 100644
--- a/lib/ssl/test/ssl_crl_SUITE.erl
+++ b/lib/ssl/test/ssl_crl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,8 @@
crl_hash_dir_collision/0,
crl_hash_dir_collision/1,
crl_hash_dir_expired/0,
- crl_hash_dir_expired/1]).
+ crl_hash_dir_expired/1,
+ delete_crl_with_path/1]).
-define(TIMEOUT, {seconds, 30}).
@@ -83,7 +84,7 @@ groups() ->
{group, crl_hash_dir}]},
{v2_crl, [], basic_tests()},
{v1_crl, [], basic_tests()},
- {idp_crl, [], basic_tests()},
+ {idp_crl, [], basic_tests() ++ idp_crl_tests()},
{crl_hash_dir, [], basic_tests() ++ crl_hash_dir_tests()},
{crl_verify_crldp_crlissuer, [], [crl_verify_valid]}].
@@ -94,6 +95,9 @@ basic_tests() ->
crl_verify_revoked_derCAs,
crl_verify_no_crl].
+idp_crl_tests() ->
+ [delete_crl_with_path].
+
crl_hash_dir_tests() ->
[crl_hash_dir_collision, crl_hash_dir_expired].
@@ -240,10 +244,15 @@ crl_verify_valid(Config) when is_list(Config) ->
end,
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_crl_cache:insert("http://localhost/erlangCA/crl.pem", {file, filename:join([PrivDir, "erlangCA", "crl.pem"])}),
+ ssl_crl_cache:insert("http://localhost/otpCA/crl.pem", {file, filename:join([PrivDir, "otpCA", "crl.pem"])}),
ssl_crl_cache:insert({file, filename:join([PrivDir, "erlangCA", "crl.pem"])}),
ssl_crl_cache:insert({file, filename:join([PrivDir, "otpCA", "crl.pem"])}),
-
- crl_verify_valid(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts).
+
+ crl_verify_valid(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts),
+
+ %% check that delete WITH URI works as well.
+ ssl_crl_cache:delete("http://localhost/erlangCA/crl.pem").
crl_verify_revoked() ->
[{doc,"Verify a simple CRL chain when peer cert is reveoked"}].
@@ -553,6 +562,35 @@ crl_verify_error(Hostname, ServerNode, ServerOpts, ClientNode, ClientOpts, Expec
ssl_test_lib:check_client_alert(Server, Client, ExpectedAlert).
+delete_crl_with_path(Config) ->
+ PrivDir = proplists:get_value(cert_dir, Config),
+
+ CertFilepath = filename:join([PrivDir, "server", "cert.pem"]),
+ {ok, PemCert} = file:read_file(CertFilepath),
+ [{_, DerCert, _}] = public_key:pem_decode(PemCert),
+ OTPCert = public_key:pkix_decode_cert(DerCert, otp),
+ [DP | _] = public_key:pkix_dist_points(OTPCert),
+
+ CRLFilepath = filename:join([PrivDir, "otpCA", "crl.pem"]),
+ {ok, PemBin} = file:read_file(CRLFilepath),
+ PemEntries = public_key:pem_decode(PemBin),
+ CRLs = [CRL || {'CertificateList', CRL, not_encrypted}
+ <- PemEntries],
+
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ case element(5, State) of
+ [_, _, _, {CRLCache, _}] ->
+ URI = "http://localhost/otpCA/crl.pem",
+ not_available = ssl_crl_cache:lookup(DP, issuer, {{CRLCache, unused}, unused}),
+ ok = ssl_crl_cache:insert(URI, {der, CRLs}),
+ CRLs = ssl_crl_cache:lookup(DP, issuer, {{CRLCache, unused}, unused}),
+ ok = ssl_crl_cache:delete(URI),
+ not_available = ssl_crl_cache:lookup(DP, issuer, {{CRLCache, unused}, unused}),
+ ok
+ end.
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 854c349689..c6154855e5 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -22,6 +22,7 @@
-behaviour(ct_suite).
+-include_lib("kernel/include/net_address.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("public_key/include/public_key.hrl").
-include("ssl_dist_test_lib.hrl").
@@ -54,6 +55,8 @@
listen_options/1,
connect_options/0,
connect_options/1,
+ net_ticker_spawn_options/0,
+ net_ticker_spawn_options/1,
use_interface/0,
use_interface/1,
verify_fun_fail/0,
@@ -74,6 +77,7 @@
listen_options_test/3,
do_connect_options/2,
connect_options_test/3,
+ net_ticker_spawn_options_test/3,
verify_fun_fail_test/3,
verify_fun_pass_test/3,
verify_pass_always/3,
@@ -95,7 +99,8 @@
stop_ssl_node/1]).
start_ssl_node_name(Name, Args) ->
- ssl_dist_test_lib:start_ssl_node(Name, Args).
+ Pa = filename:dirname(code:which(?MODULE)),
+ ssl_dist_test_lib:start_ssl_node(Name, "-pa " ++ Pa ++ " " ++ Args).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -111,6 +116,7 @@ all() ->
listen_port_options,
listen_options,
connect_options,
+ net_ticker_spawn_options,
use_interface,
verify_fun_fail,
verify_fun_pass,
@@ -276,56 +282,45 @@ nodelay_option(Config) ->
listen_port_options() ->
[{doc, "Test specifying listening ports"}].
listen_port_options(Config) when is_list(Config) ->
- %% Start a node, and get the port number it's listening on.
+ %% Set up the probably most supported scenario
+ %% for {reuseaddr,true}, i.e, the listening socket
+ %% is closed, but an accepted server side socket
+ %% blocks the server port, unless {reuseaddr,true}
+ %% is used.
+ %%
+ %% Set up a server socket and close the listening socket
+ {ok, L} = gen_tcp:listen(0, [{reuseaddr,true}]),
+ {ok, Port} = inet:port(L),
+ {ok, C} = gen_tcp:connect({127,0,0,1}, Port, []),
+ {ok, S} = gen_tcp:accept(L),
+ ok = gen_tcp:close(L),
+ ct:pal("Port: ~w", [Port]),
+ %%
+ %% Start a node on the server port, {reuseaddr,true}
+ %% is used per default on the listening socket
+ %% since it is a server - see inet_tcp_dist:gen_listen/3
+ PortOpts =
+ "-kernel"
+ " inet_dist_listen_min " ++ integer_to_list(Port) ++
+ " inet_dist_listen_max " ++ integer_to_list(Port),
+ %% basic_test/3 connects NH1 -> NH2 so it is NH2 that should
+ %% act as server to make use of PortOpts
NH1 = start_ssl_node(Config),
- Node1 = NH1#node_handle.nodename,
- Name1 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)),
- {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0),
- {Name1, Port1} = lists:keyfind(Name1, 1, NodesPorts),
-
- %% Now start a second node, configuring it to use the same port
- %% number.
- PortOpt1 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++
- " inet_dist_listen_max " ++ integer_to_list(Port1),
-
- try start_ssl_node([{tls_verify_opts, PortOpt1} | proplists:delete(tls_verify_opts, Config)]) of
- #node_handle{} ->
- %% If the node was able to start, it didn't take the port
- %% option into account.
- stop_ssl_node(NH1),
- exit(unexpected_success)
- catch
- exit:{accept_failed, timeout} ->
- %% The node failed to start, as expected.
- ok
- end,
-
- %% Try again, now specifying a high max port.
- PortOpt2 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++
- " inet_dist_listen_max 65535",
- NH2 = start_ssl_node([{tls_verify_opts, PortOpt2} | proplists:delete(tls_verify_opts, Config)]),
-
- try
- Node2 = NH2#node_handle.nodename,
- Name2 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node2)),
- {ok, NodesPorts2} = apply_on_ssl_node(NH2, fun net_adm:names/0),
- {Name2, Port2} = lists:keyfind(Name2, 1, NodesPorts2),
-
- %% The new port should be higher:
- if Port2 > Port1 ->
- ok;
- true ->
- error({port, Port2, not_higher_than, Port1})
- end
- catch
- _:Reason ->
- stop_ssl_node(NH2),
- stop_ssl_node(NH1),
- ct:fail(Reason)
- end,
- stop_ssl_node(NH2),
- stop_ssl_node(NH1),
- success(Config).
+ NH2 = start_ssl_node(Config, PortOpts),
+ try
+ basic_test(NH1, NH2, Config),
+ Node2 = NH2#node_handle.nodename,
+ {ok,NodeInfo2} =
+ apply_on_ssl_node(NH1, net_kernel, node_info, [Node2]),
+ {address,#net_address{address = {_,Port}, protocol = tls}} =
+ lists:keyfind(address, 1, NodeInfo2),
+ ok
+ after
+ gen_tcp:close(C),
+ gen_tcp:close(S),
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2)
+ end.
%%--------------------------------------------------------------------
listen_options() ->
@@ -339,6 +334,14 @@ connect_options() ->
connect_options(Config) when is_list(Config) ->
try_setting_priority(fun do_connect_options/2, Config).
+%%--------------------------------------------------------------------
+net_ticker_spawn_options() ->
+ [{doc, "Test net_ticker_spawn_options"}].
+net_ticker_spawn_options(Config) when is_list(Config) ->
+ FullsweepString = maybe_quote_tuple_list("[{fullsweep_after,0}]"),
+ Options = "-kernel net_ticker_spawn_options "++FullsweepString,
+ gen_dist_test(net_ticker_spawn_options_test, [{tls_only_basic_opts, Options} | Config]).
+
%%--------------------------------------------------------------------
use_interface() ->
@@ -628,16 +631,8 @@ plain_verify_options_test(NH1, NH2, _) ->
[Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end).
do_listen_options(Prio, Config) ->
- PriorityString0 = "[{priority,"++integer_to_list(Prio)++"}]",
PriorityString =
- case os:cmd("echo [{a,1}]") of
- "[{a,1}]"++_ ->
- PriorityString0;
- _ ->
- %% Some shells need quoting of [{}]
- "'"++PriorityString0++"'"
- end,
-
+ maybe_quote_tuple_list("[{priority,"++integer_to_list(Prio)++"}]"),
Options = "-kernel inet_dist_listen_options " ++ PriorityString,
gen_dist_test(listen_options_test, [{prio, Prio}, {tls_only_basic_opts, Options} | Config]).
@@ -659,16 +654,8 @@ listen_options_test(NH1, NH2, Config) ->
[_|_] = Elevated2.
do_connect_options(Prio, Config) ->
- PriorityString0 = "[{priority,"++integer_to_list(Prio)++"}]",
PriorityString =
- case os:cmd("echo [{a,1}]") of
- "[{a,1}]"++_ ->
- PriorityString0;
- _ ->
- %% Some shells need quoting of [{}]
- "'"++PriorityString0++"'"
- end,
-
+ maybe_quote_tuple_list("[{priority,"++integer_to_list(Prio)++"}]"),
Options = "-kernel inet_dist_connect_options " ++ PriorityString,
gen_dist_test(connect_options_test,
[{prio, Prio}, {tls_only_basic_opts, Options} | Config]).
@@ -693,6 +680,23 @@ connect_options_test(NH1, NH2, Config) ->
%% Node 2 will not, since it only applies to outbound connections.
[] = Elevated2.
+net_ticker_spawn_options_test(NH1, NH2, _Config) ->
+ Node1 = NH1#node_handle.nodename,
+ Node2 = NH2#node_handle.nodename,
+
+ pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
+
+ FullsweepOptionNode1 =
+ apply_on_ssl_node(NH1, fun () -> get_dist_util_fullsweep_option(Node2) end),
+ FullsweepOptionNode2 =
+ apply_on_ssl_node(NH2, fun () -> get_dist_util_fullsweep_option(Node1) end),
+
+ ct:pal("FullsweepOptionNode1: ~p~n", [FullsweepOptionNode1]),
+ ct:pal("FullsweepOptionNode2: ~p~n", [FullsweepOptionNode2]),
+
+ 0 = FullsweepOptionNode1,
+ 0 = FullsweepOptionNode2.
+
verify_fun_fail_test(NH1, NH2, _) ->
Node2 = NH2#node_handle.nodename,
@@ -734,6 +738,14 @@ get_socket_priorities() ->
{ok,[{priority,Priority}]} <-
[inet:getopts(Port, [priority]) || Port <- inet_ports()]].
+get_dist_util_fullsweep_option(Node) ->
+ SenderPid = proplists:get_value(Node, erlang:system_info(dist_ctrl)),
+ {links, Links1} = erlang:process_info(SenderPid, links),
+ {links, Links2} = erlang:process_info(whereis(net_kernel), links),
+ [DistUtilPid] = [X || X <- Links1, Y <- Links2, X =:= Y],
+ {garbage_collection, GCOpts} = erlang:process_info(DistUtilPid, garbage_collection),
+ proplists:get_value(fullsweep_after, GCOpts).
+
inet_ports() ->
[Port || Port <- erlang:ports(),
element(2, erlang:port_info(Port, name)) =:= "tcp_inet"].
@@ -789,11 +801,12 @@ setup_tls_opts(Config) ->
case proplists:get_value(tls_only_basic_opts, Config, []) of
[_|_] = BasicOpts -> %% No verify but server still need to have cert
"-proto_dist inet_tls " ++ "-ssl_dist_opt server_certfile " ++ SC ++ " "
- ++ "-ssl_dist_opt server_keyfile " ++ SK ++ " " ++ BasicOpts;
+ ++ "-ssl_dist_opt server_keyfile " ++ SK ++ " " ++ BasicOpts;
[] -> %% Verify
- case proplists:get_value(tls_verify_opts, Config, []) of
+ TlsVerifyOpts = proplists:get_value(tls_verify_opts, Config, []),
+ case TlsVerifyOpts of
[_|_] ->
- BasicVerifyOpts = "-proto_dist inet_tls "
+ "-proto_dist inet_tls "
++ "-ssl_dist_opt server_certfile " ++ SC ++ " "
++ "-ssl_dist_opt server_keyfile " ++ SK ++ " "
++ "-ssl_dist_opt server_cacertfile " ++ SCA ++ " "
@@ -802,8 +815,8 @@ setup_tls_opts(Config) ->
++ "-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 ",
- BasicVerifyOpts ++ proplists:get_value(tls_verify_opts, Config, []);
+ ++ "-ssl_dist_opt client_verify verify_peer "
+ ++ TlsVerifyOpts;
_ -> %% No verify, no extra opts
"-proto_dist inet_tls " ++ "-ssl_dist_opt server_certfile " ++ SC ++ " "
++ "-ssl_dist_opt server_keyfile " ++ SK ++ " "
@@ -956,7 +969,15 @@ rsa_peer_key(N) ->
%% As rsa keygen is not guaranteed to be fast
[{key, ssl_test_lib:hardcode_rsa_key(N)}].
-rsa_intermediate(N) ->
+rsa_intermediate(N) ->
[{key, ssl_test_lib:hardcode_rsa_key(N)}].
+maybe_quote_tuple_list(String) ->
+ case os:cmd("echo [{a,1}]") of
+ "[{a,1}]"++_ ->
+ String;
+ _ ->
+ %% Some shells need quoting of [{}]
+ "'"++String++"'"
+ end.
diff --git a/lib/ssl/test/ssl_dist_bench_SUITE.erl b/lib/ssl/test/ssl_dist_bench_SUITE.erl
index a7b6bba807..b556701869 100644
--- a/lib/ssl/test/ssl_dist_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,7 +57,9 @@ all() ->
{group, plain}].
groups() ->
- [{ssl, all_groups()},
+ [{benchmark, all()},
+ %%
+ {ssl, all_groups()},
{crypto, all_groups()},
{plain, all_groups()},
%%
@@ -85,112 +87,146 @@ init_per_suite(Config) ->
Digest = sha1,
ECCurve = secp521r1,
TLSVersion = 'tlsv1.2',
- TLSCipher = {ecdhe_ecdsa,aes_128_cbc,sha256,sha256},
+ TLSCipher =
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256},
%%
Node = node(),
+ Skipped = make_ref(),
try
Node =/= nonode@nohost orelse
- throw({skipped,"Node not distributed"}),
+ throw({Skipped,"Node not distributed"}),
verify_node_src_addr(),
{supported, SSLVersions} =
lists:keyfind(supported, 1, ssl:versions()),
lists:member(TLSVersion, SSLVersions) orelse
throw(
- {skipped,
+ {Skipped,
"SSL does not support " ++ term_to_string(TLSVersion)}),
lists:member(ECCurve, ssl:eccs(TLSVersion)) orelse
throw(
- {skipped,
+ {Skipped,
"SSL does not support " ++ term_to_string(ECCurve)}),
- lists:member(TLSCipher, ssl:cipher_suites(default, TLSVersion)) orelse
+ TLSCipherKeys = maps:keys(TLSCipher),
+ lists:any(
+ fun (Cipher) ->
+ maps:with(TLSCipherKeys, Cipher) =:= TLSCipher
+ end,
+ ssl:cipher_suites(default, TLSVersion)) orelse
throw(
- {skipped,
- "SSL does not support " ++ term_to_string(TLSCipher)})
- of
- _ ->
- PrivDir = proplists:get_value(priv_dir, Config),
- %%
- [_, HostA] = split_node(Node),
- NodeAName = ?MODULE_STRING ++ "_node_a",
- NodeAString = NodeAName ++ "@" ++ HostA,
- NodeAConfFile = filename:join(PrivDir, NodeAString ++ ".conf"),
- NodeA = list_to_atom(NodeAString),
- %%
- ServerNode = ssl_bench_test_lib:setup(dist_server),
- [_, HostB] = split_node(ServerNode),
- NodeBName = ?MODULE_STRING ++ "_node_b",
- NodeBString = NodeBName ++ "@" ++ HostB,
- NodeBConfFile = filename:join(PrivDir, NodeBString ++ ".conf"),
- NodeB = list_to_atom(NodeBString),
- %%
- CertOptions =
- [{digest, Digest},
- {key, {namedCurve, ECCurve}}],
- RootCert =
- public_key:pkix_test_root_cert(
- ?MODULE_STRING ++ " ROOT CA", CertOptions),
- SSLConf =
- [{verify, verify_peer},
- {versions, [TLSVersion]},
- {ciphers, [TLSCipher]}],
- ServerConf =
- [{fail_if_no_peer_cert, true},
- {verify_fun,
- {fun inet_tls_dist:verify_client/3,[]}}
- | SSLConf],
- ClientConf = SSLConf,
- %%
- write_node_conf(
- NodeAConfFile, NodeA, ServerConf, ClientConf,
- CertOptions, RootCert),
- write_node_conf(
- NodeBConfFile, NodeB, ServerConf, ClientConf,
- CertOptions, RootCert),
- %%
- [{node_a_name, NodeAName},
- {node_a, NodeA},
- {node_a_dist_args,
- "-proto_dist inet_tls "
- "-ssl_dist_optfile " ++ NodeAConfFile ++ " "},
- {node_b_name, NodeBName},
- {node_b, NodeB},
- {node_b_dist_args,
- "-proto_dist inet_tls "
- "-ssl_dist_optfile " ++ NodeBConfFile ++ " "},
- {server_node, ServerNode}
- |Config]
+ {Skipped,
+ "SSL does not support " ++ term_to_string(TLSCipher)}),
+ %%
+ %%
+ %%
+ PrivDir = proplists:get_value(priv_dir, Config),
+ [_, HostA] = split_node(Node),
+ NodeAName = ?MODULE_STRING ++ "_node_a",
+ NodeAString = NodeAName ++ "@" ++ HostA,
+ NodeAConfFile = filename:join(PrivDir, NodeAString ++ ".conf"),
+ NodeA = list_to_atom(NodeAString),
+ %%
+ ServerNode = ssl_bench_test_lib:setup(dist_server),
+ [_, HostB] = split_node(ServerNode),
+ NodeBName = ?MODULE_STRING ++ "_node_b",
+ NodeBString = NodeBName ++ "@" ++ HostB,
+ NodeBConfFile = filename:join(PrivDir, NodeBString ++ ".conf"),
+ NodeB = list_to_atom(NodeBString),
+ %%
+ CertOptions =
+ [{digest, Digest},
+ {key, {namedCurve, ECCurve}}],
+ RootCert =
+ public_key:pkix_test_root_cert(
+ ?MODULE_STRING ++ " ROOT CA", CertOptions),
+ SSLConf =
+ [{verify, verify_peer},
+ {versions, [TLSVersion]},
+ {ciphers, [TLSCipher]}],
+ ServerConf =
+ [{fail_if_no_peer_cert, true},
+ {verify_fun,
+ {fun inet_tls_dist:verify_client/3,[]}}
+ | SSLConf],
+ ClientConf = SSLConf,
+ %%
+ write_node_conf(
+ NodeAConfFile, NodeA, ServerConf, ClientConf,
+ CertOptions, RootCert),
+ write_node_conf(
+ NodeBConfFile, NodeB, ServerConf, ClientConf,
+ CertOptions, RootCert),
+ %%
+ [{node_a_name, NodeAName},
+ {node_a, NodeA},
+ {node_a_dist_args,
+ "-proto_dist inet_tls "
+ "-ssl_dist_optfile " ++ NodeAConfFile ++ " "},
+ {node_b_name, NodeBName},
+ {node_b, NodeB},
+ {node_b_dist_args,
+ "-proto_dist inet_tls "
+ "-ssl_dist_optfile " ++ NodeBConfFile ++ " "},
+ {server_node, ServerNode}
+ |Config]
catch
- throw:Result ->
- Result
+ throw : {Skipped, Reason} ->
+ {skipped, Reason};
+ Class : Reason : Stacktrace ->
+ {failed, {Class, Reason, Stacktrace}}
end.
end_per_suite(Config) ->
ServerNode = proplists:get_value(server_node, Config),
- slave:stop(ServerNode).
+ ssl_bench_test_lib:cleanup(ServerNode).
init_per_group(ssl, Config) ->
[{ssl_dist, true}, {ssl_dist_prefix, "SSL"}|Config];
init_per_group(crypto, Config) ->
- [{ssl_dist, false}, {ssl_dist_prefix, "Crypto"},
- {ssl_dist_args,
- "-proto_dist inet_crypto"}
- |Config];
+ try inet_crypto_dist:supported() of
+ ok ->
+ [{ssl_dist, false}, {ssl_dist_prefix, "Crypto"},
+ {ssl_dist_args,
+ "-proto_dist inet_crypto"}
+ |Config];
+ Problem ->
+ {skipped,
+ "Crypto does not support " ++ Problem}
+ catch
+ Class : Reason : Stacktrace ->
+ {failed, {Class, Reason, Stacktrace}}
+ end;
init_per_group(plain, Config) ->
[{ssl_dist, false}, {ssl_dist_prefix, "Plain"}|Config];
+init_per_group(benchmark, Config) ->
+ [{effort,10}|Config];
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, _Config) ->
ok.
-init_per_testcase(_Func, Conf) ->
- Conf.
+init_per_testcase(Func, Conf) ->
+ case proplists:is_defined(effort, Conf) of
+ false ->
+ %% Not a benchmark run
+ case atom_to_list(Func) of
+ "throughput_64" ->
+ Conf;
+ "throughput_"++_ ->
+ {skipped, "Benchmarks run separately"};
+ _ ->
+ Conf
+ end;
+ true ->
+ Conf
+ end.
end_per_testcase(_Func, _Conf) ->
ok.
--define(COUNT, 400).
-
%%%-------------------------------------------------------------------
%%% CommonTest API helpers
@@ -258,10 +294,10 @@ split_node(Node) ->
%% Connection setup speed
setup(Config) ->
- run_nodepair_test(fun setup/5, Config).
+ run_nodepair_test(fun setup/6, Config).
-setup(A, B, Prefix, HA, HB) ->
- Rounds = 50,
+setup(A, B, Prefix, Effort, HA, HB) ->
+ Rounds = 5 * Effort,
[] = ssl_apply(HA, erlang, nodes, []),
[] = ssl_apply(HB, erlang, nodes, []),
{SetupTime, CycleTime} =
@@ -316,10 +352,10 @@ setup_wait_nodedown(A, Time) ->
%% Roundtrip speed
roundtrip(Config) ->
- run_nodepair_test(fun roundtrip/5, Config).
+ run_nodepair_test(fun roundtrip/6, Config).
-roundtrip(A, B, Prefix, HA, HB) ->
- Rounds = 40000,
+roundtrip(A, B, Prefix, Effort, HA, HB) ->
+ Rounds = 4000 * Effort,
[] = ssl_apply(HA, erlang, nodes, []),
[] = ssl_apply(HB, erlang, nodes, []),
ok = ssl_apply(HA, net_kernel, allow, [[B]]),
@@ -372,20 +408,37 @@ roundtrip_client(Pid, Mon, StartTime, N) ->
sched_utilization(Config) ->
run_nodepair_test(
- fun(A, B, Prefix, HA, HB) ->
- sched_utilization(A, B, Prefix, HA, HB, proplists:get_value(ssl_dist, Config))
+ fun(A, B, Prefix, Effort, HA, HB) ->
+ sched_utilization(A, B, Prefix, Effort, HA, HB, Config)
end, Config).
-sched_utilization(A, B, Prefix, HA, HB, SSL) ->
+sched_utilization(A, B, Prefix, Effort, HA, HB, Config) ->
+ SSL = proplists:get_value(ssl_dist, Config),
[] = ssl_apply(HA, erlang, nodes, []),
[] = ssl_apply(HB, erlang, nodes, []),
- {ClientMsacc, ServerMsacc, Msgs} =
- ssl_apply(HA, fun () -> sched_util_runner(A, B, SSL) end),
+ PidA = ssl_apply(HA, os, getpid, []),
+ PidB = ssl_apply(HB, os, getpid, []),
+ ct:pal("Starting scheduler utilization run effort ~w:~n"
+ " [~s] ~w~n"
+ " [~s] ~w~n",
+ [Effort, PidA, A, PidB, B]),
+ {ClientMsacc, ServerMsacc, BusyDistPortMsgs} =
+ ssl_apply(
+ HA,
+ fun () ->
+ Result = sched_util_runner(A, B, Effort, SSL, Config),
+ fs_log(
+ Config,
+ "sched_utilization.Result", Result),
+ Result
+ end),
+ ct:log("Got ~p busy_dist_port msgs",[tail(BusyDistPortMsgs)]),
[B] = ssl_apply(HA, erlang, nodes, []),
[A] = ssl_apply(HB, erlang, nodes, []),
+ ct:log("Microstate accounting for node ~w:", [A]),
msacc:print(ClientMsacc),
+ ct:log("Microstate accounting for node ~w:", [B]),
msacc:print(ServerMsacc),
- ct:pal("Got ~p busy_dist_port msgs",[length(Msgs)]),
ct:log("Stats of B from A: ~p",
[ssl_apply(HA, net_kernel, node_info, [B])]),
ct:log("Stats of A from B: ~p",
@@ -397,10 +450,13 @@ sched_utilization(A, B, Prefix, HA, HB, SSL) ->
round(10000 * msacc:stats(system_runtime,ServerMsacc) /
msacc:stats(system_realtime,ServerMsacc)),
Verdict =
- case Msgs of
- [] ->
+ if
+ BusyDistPortMsgs =:= 0 ->
"";
- _ ->
+ is_integer(BusyDistPortMsgs) ->
+ " ?";
+ true ->
+ ct:log("Stray Msgs: ~p", [BusyDistPortMsgs]),
" ???"
end,
{comment, ClientComment} =
@@ -414,56 +470,112 @@ sched_utilization(A, B, Prefix, HA, HB, SSL) ->
%% Runs on node A and spawns a server on node B
%% We want to avoid getting busy_dist_port as it hides the true SU usage
%% of the receiver and sender.
-sched_util_runner(A, B, true) ->
- sched_util_runner(A, B, 250);
-sched_util_runner(A, B, false) ->
- sched_util_runner(A, B, 250);
-sched_util_runner(A, B, Senders) ->
+sched_util_runner(A, B, Effort, true, Config) ->
+ sched_util_runner(A, B, Effort, 250, Config);
+sched_util_runner(A, B, Effort, false, Config) ->
+ sched_util_runner(A, B, Effort, 250, Config);
+sched_util_runner(A, B, Effort, Senders, Config) ->
+ process_flag(trap_exit, true),
Payload = payload(5),
+ Time = 1000 * Effort,
[A] = rpc:call(B, erlang, nodes, []),
ServerPids =
[erlang:spawn_link(
B, fun () -> throughput_server() end)
|| _ <- lists:seq(1, Senders)],
+ Tag = make_ref(),
ServerMsacc =
- erlang:spawn(
+ erlang:spawn_link(
B,
fun() ->
receive
- {start,Pid} ->
- msacc:start(10000),
+ {start,Tag,Pid} ->
+ fs_log(
+ Config,
+ "sched_util_runner.Server.msacc.self",
+ self()),
+ msacc:start(Time),
+ fs_log(
+ Config,
+ "sched_util_runner.Server.msacc:start",
+ ok),
receive
- {done,Pid} ->
- Pid ! {self(),msacc:stats()}
+ {done,Tag,Pid} ->
+ fs_log(
+ Config,
+ "sched_util_runner.Server.msacc:stats",
+ ok),
+ ServerStats = msacc:stats(),
+ fs_log(Config,
+ "sched_util_runner.Server.msacc:stats",
+ ServerStats),
+ exit({result,Tag,ServerStats})
end
end
end),
erlang:system_monitor(self(),[busy_dist_port]),
%% We spawn 250 senders which should mean that we
- %% have a load of 250 msgs/msec
- [spawn_link(
- fun() ->
- throughput_client(Pid, Payload)
- end) || Pid <- ServerPids],
+ %% have a load of 25 msgs/msec
+ _Clients =
+ [spawn_link(
+ fun() ->
+ throughput_client(Pid, Payload)
+ end) || Pid <- ServerPids],
%%
receive after 1000 -> ok end,
- ServerMsacc ! {start,self()},
- msacc:start(10000),
+ ServerMsacc ! {start,Tag,self()},
+ fs_log(Config, "sched_util_runner.Client.self", self()),
+ msacc:start(Time),
+ fs_log(Config, "sched_util_runner.Client.msacc:start", ok),
ClientMsaccStats = msacc:stats(),
+ fs_log(Config, "sched_util_runner.Client.msacc.stats", ClientMsaccStats),
receive after 1000 -> ok end,
- ServerMsacc ! {done,self()},
- ServerMsaccStats = receive {ServerMsacc,Stats} -> Stats end,
+ ServerMsacc ! {done,Tag,self()},
+ ServerMsaccStats =
+ receive
+ {'EXIT',ServerMsacc,{result,Tag,Stats}} ->
+ Stats;
+ {'EXIT',ServerMsacc,Other} ->
+ exit({other,ServerMsacc,Other})
+ end,
+ fs_log(Config, "sched_util_runner.ServerMsaccStats", ServerMsaccStats),
%%
- {ClientMsaccStats,ServerMsaccStats, flush()}.
+ {ClientMsaccStats,ServerMsaccStats, busy_dist_port_msgs()}.
+
+fs_log(Config, Name, Term) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ DistPrefix = proplists:get_value(ssl_dist_prefix, Config),
+ _ = file:write_file(
+ filename:join(PrivDir, DistPrefix ++ "_" ++ Name),
+ io_lib:format(
+ "~p~n",
+ [{{erlang:unique_integer([positive,monotonic]),
+ os:system_time(1000000)},
+ Term}])),
+ ok.
-flush() ->
+busy_dist_port_msgs() ->
+ busy_dist_port_msgs(0).
+%%
+busy_dist_port_msgs(N) ->
receive
M ->
- [M | flush()]
+ case M of
+ {monitor, P1, busy_dist_port, P2}
+ when is_pid(P1), is_pid(P2) ->
+ busy_dist_port_msgs(N + 1);
+ Stray ->
+ [Stray | busy_dist_port_msgs(N)]
+ end
after 0 ->
- []
+ N
end.
+tail([_|Tail]) ->
+ tail(Tail);
+tail(Tail) ->
+ Tail.
+
throughput_server() ->
receive _ -> ok end,
receive _ -> ok end,
@@ -479,57 +591,57 @@ throughput_server() ->
throughput_client(Pid, Payload) ->
Pid ! Payload,
- receive after 1 -> throughput_client(Pid, Payload) end.
+ receive after 10 -> throughput_client(Pid, Payload) end.
%%-----------------
%% Throughput speed
throughput_0(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 500000, 0)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 50000 * Effort, 0)
end, Config).
throughput_64(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 500000, 64)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 50000 * Effort, 64)
end, Config).
throughput_1024(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 100000, 1024)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 10000 * Effort, 1024)
end, Config).
throughput_4096(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 50000, 4096)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 5000 * Effort, 4096)
end, Config).
throughput_16384(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 10000, 16384)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 1000 * Effort, 16384)
end, Config).
throughput_65536(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 2000, 65536)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 200 * Effort, 65536)
end, Config).
throughput_262144(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 500, 262144)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 50 * Effort, 262144)
end, Config).
throughput_1048576(Config) ->
run_nodepair_test(
- fun (A, B, Prefix, HA, HB) ->
- throughput(A, B, Prefix, HA, HB, 200, 1048576)
+ fun (A, B, Prefix, Effort, HA, HB) ->
+ throughput(A, B, Prefix, HA, HB, 20 * Effort, 1048576)
end, Config).
throughput(A, B, Prefix, HA, HB, Packets, Size) ->
@@ -617,6 +729,47 @@ throughput_runner(A, B, Rounds, Size) ->
client_prof => Prof}.
dig_dist_node_sockets() ->
+ DistCtrl2Node =
+ maps:from_list(
+ [{DistCtrl, Node}
+ || {Node, DistCtrl}
+ <- erlang:system_info(dist_ctrl), is_pid(DistCtrl)]),
+ TlsDistConnSup = whereis(tls_dist_connection_sup),
+ InetCryptoDist = whereis(inet_crypto_dist),
+ [NodeSocket
+ || {_, Socket} = NodeSocket
+ <- erlang:system_info(dist_ctrl), is_port(Socket)]
+ ++
+ if
+ TlsDistConnSup =/= undefined ->
+ [case ConnSpec of
+ {undefined, ConnSup, supervisor, _} ->
+ [{receiver, ReceiverPid, worker, _},
+ {sender, SenderPid, worker, _}] =
+ lists:sort(supervisor:which_children(ConnSup)),
+ {links,ReceiverLinks} =
+ process_info(ReceiverPid, links),
+ [Socket] = [S || S <- ReceiverLinks, is_port(S)],
+ {maps:get(SenderPid, DistCtrl2Node), Socket}
+ end
+ || ConnSpec <- supervisor:which_children(TlsDistConnSup)];
+ InetCryptoDist =/= undefined ->
+ [begin
+ {monitors,[{process,InputHandler}]} =
+ erlang:process_info(DistCtrl, monitors),
+ {links,InputHandlerLinks} =
+ erlang:process_info(InputHandler, links),
+ [Socket] =
+ [S || S <- InputHandlerLinks, is_port(S)],
+ {Node, Socket}
+ end
+ || {DistCtrl, Node} <- maps:to_list(DistCtrl2Node)];
+ true ->
+ []
+ end.
+
+-ifdef(undefined).
+dig_dist_node_sockets() ->
[case DistCtrl of
{_Node,Socket} = NodeSocket when is_port(Socket) ->
NodeSocket;
@@ -634,7 +787,7 @@ dig_dist_node_sockets() ->
{Node,Socket}
end
end || DistCtrl <- erlang:system_info(dist_ctrl)].
-
+-endif.
throughput_server(Pid, N) ->
GC_Before = get_server_gc_info(),
@@ -767,9 +920,10 @@ run_nodepair_test(TestFun, Config) ->
A = proplists:get_value(node_a, Config),
B = proplists:get_value(node_b, Config),
Prefix = proplists:get_value(ssl_dist_prefix, Config),
+ Effort = proplists:get_value(effort, Config, 1),
HA = start_ssl_node_a(Config),
HB = start_ssl_node_b(Config),
- try TestFun(A, B, Prefix, HA, HB)
+ try TestFun(A, B, Prefix, Effort, HA, HB)
after
stop_ssl_node_a(HA),
stop_ssl_node_b(HB, Config),
@@ -795,14 +949,18 @@ ssl_apply(Handle, Fun) ->
start_ssl_node_a(Config) ->
Name = proplists:get_value(node_a_name, Config),
Args = get_node_args(node_a_dist_args, Config),
- ssl_dist_test_lib:start_ssl_node(Name, Args).
+ Pa = filename:dirname(code:which(?MODULE)),
+ ssl_dist_test_lib:start_ssl_node(
+ Name, "-pa " ++ Pa ++ " " ++ Args).
start_ssl_node_b(Config) ->
Name = proplists:get_value(node_b_name, Config),
Args = get_node_args(node_b_dist_args, Config),
+ Pa = filename:dirname(code:which(?MODULE)),
ServerNode = proplists:get_value(server_node, Config),
rpc:call(
- ServerNode, ssl_dist_test_lib, start_ssl_node, [Name, Args]).
+ ServerNode, ssl_dist_test_lib, start_ssl_node,
+ [Name, "-pa " ++ Pa ++ " " ++ Args]).
stop_ssl_node_a(HA) ->
ssl_dist_test_lib:stop_ssl_node(HA).
diff --git a/lib/ssl/test/ssl_dist_test_lib.erl b/lib/ssl/test/ssl_dist_test_lib.erl
index 45da600767..90aae473e2 100644
--- a/lib/ssl/test/ssl_dist_test_lib.erl
+++ b/lib/ssl/test/ssl_dist_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -136,7 +136,6 @@ host_name() ->
mk_node_cmdline(ListenPort, Name, Args, LogPath, DumpPath) ->
Static = "-detached -noinput",
- Pa = filename:dirname(code:which(?MODULE)),
Prog = case catch init:get_argument(progname) of
{ok,[[P]]} -> P;
_ -> exit(no_progname_argument_found)
@@ -148,7 +147,6 @@ mk_node_cmdline(ListenPort, Name, Args, LogPath, DumpPath) ->
"\"" ++ Prog ++ "\" "
++ Static ++ " "
++ NameSw ++ " " ++ Name ++ " "
- ++ "-pa " ++ Pa ++ " "
++ "-run application start crypto -run application start public_key "
++ "-eval 'net_kernel:verbose(1)' "
++ "-run " ++ atom_to_list(?MODULE) ++ " cnct2tstsrvr "
diff --git a/lib/ssl/test/ssl_eqc_SUITE.erl b/lib/ssl/test/ssl_eqc_SUITE.erl
index 84ee7bf778..6db3c93482 100644
--- a/lib/ssl/test/ssl_eqc_SUITE.erl
+++ b/lib/ssl/test/ssl_eqc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% The 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,9 +66,18 @@ all() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
ct:timetrap({seconds, 20}),
- ct_property_test:init_per_suite(Config).
-end_per_suite(Config) ->
- Config.
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ ct_property_test:init_per_suite(Config)
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
init_per_testcase(_, Config0) ->
Config0.
diff --git a/lib/ssl/test/ssl_gh.spec b/lib/ssl/test/ssl_gh.spec
new file mode 100644
index 0000000000..6942caa68e
--- /dev/null
+++ b/lib/ssl/test/ssl_gh.spec
@@ -0,0 +1,15 @@
+% {merge_tests,false}.
+{alias,dir,"../ssl_test"}.
+
+{suites,dir,all}.
+{skip_suites,dir,[openssl_ocsp_SUITE],"Unstable testcases"}.
+{skip_groups,all_nodes, dir, openssl_session_ticket_SUITE, 'openssl_server',
+ {cases,[openssl_server_hrr]},"Unstable testcases"}.
+{skip_groups,dir,ssl_bench_SUITE,setup,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_bench_SUITE,payload,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_bench_SUITE,pem_cache,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_dist_bench_SUITE,setup,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_dist_bench_SUITE,roundtrip,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_dist_bench_SUITE,throughput,"Benchmarks run separately"}.
+{skip_groups,dir,ssl_dist_bench_SUITE,sched_utilization,"Benchmarks run separately"}.
+
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index ec770168a3..1bde66a80b 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -129,8 +129,8 @@ decode_hello_handshake(_Config) ->
16#70, 16#64, 16#79, 16#2f, 16#32>>,
Version = {3, 0},
- {Records, _Buffer} = tls_handshake:get_tls_handshake(Version, HelloPacket, <<>>,
- default_options_map()),
+ {Records, _Buffer} = tls_handshake:get_tls_handshakes(Version, HelloPacket, <<>>,
+ default_options_map()),
{Hello, _Data} = hd(Records),
Extensions = Hello#server_hello.extensions,
diff --git a/lib/ssl/test/ssl_key_update_SUITE.erl b/lib/ssl/test/ssl_key_update_SUITE.erl
index aba6a02ddc..baa408dbc5 100644
--- a/lib/ssl/test/ssl_key_update_SUITE.erl
+++ b/lib/ssl/test/ssl_key_update_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,12 +32,16 @@
end_per_testcase/2]).
%% Testcases
--export([key_update_at/0,
- key_update_at/1,
+-export([key_update_at_client/0,
+ key_update_at_client/1,
+ key_update_at_server/0,
+ key_update_at_server/1,
explicit_key_update/0,
explicit_key_update/1]).
-include_lib("common_test/include/ct.hrl").
+-include_lib("ssl/src/ssl_api.hrl").
+-include_lib("ssl/src/ssl_connection.hrl").
all() ->
[{group, 'tlsv1.3'}].
@@ -46,7 +50,8 @@ groups() ->
[{'tlsv1.3', [], tls_1_3_tests()}].
tls_1_3_tests() ->
- [key_update_at,
+ [key_update_at_client,
+ key_update_at_server,
explicit_key_update].
init_per_suite(Config0) ->
@@ -87,42 +92,106 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-
-key_update_at() ->
- [{doc,"Test option 'key_update_at' between erlang client and erlang server."}].
-
-key_update_at(Config) ->
- %% {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+key_update_at_client() ->
+ [{doc,"Test option 'key_update_at' between erlang client and erlang server."
+ "Client initiating the update."}].
+key_update_at_client(Config) ->
+ key_update_at(Config, client).
+
+key_update_at_server() ->
+ [{doc,"Test option 'key_update_at' between erlang client and erlang server."
+ "Server initiating the update."}].
+key_update_at_server(Config) ->
+ key_update_at(Config, server).
+
+key_update_at(Config, Role) ->
Data = "123456789012345", %% 15 bytes
-
- Server = ssl_test_lib:start_server(erlang, [{log_level, debug},
- {key_update_at, 15}], Config),
+ Server = ssl_test_lib:start_server(erlang,
+ [{options, [{key_update_at, 14}]}],
+ Config),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client(erlang, [{port, Port},
- {log_level, debug},
- {key_update_at, 15}], Config),
+ {Client,
+ #sslsocket{pid =
+ [ClientReceiverPid, ClientSenderPid]}} =
+ ssl_test_lib:start_client(erlang,
+ [return_socket, {port, Port},
+ {options, [{key_update_at, 14}]}],
+ Config),
+ Server ! get_socket,
+ #sslsocket{pid =
+ [ServerReceiverPid, ServerSenderPid]} =
+ receive
+ {Server, {socket, S}} -> S
+ end,
+ Keys0 = get_keys(ClientReceiverPid, ClientSenderPid,
+ ServerReceiverPid, ServerSenderPid),
+ {Sender, Receiver} = case Role of
+ client -> {Client, Server};
+ server -> {Server, Client}
+ end,
%% Sending bytes over limit triggers key update
- ssl_test_lib:send(Client, Data),
- Data = ssl_test_lib:check_active_receive(Server, Data),
+ ssl_test_lib:send(Sender, Data),
+ Data = ssl_test_lib:check_active_receive(Receiver, Data),
%% TODO check if key has been updated (needs debug logging of secrets)
-
+ ct:sleep(500),
+ Keys1 = get_keys(ClientReceiverPid, ClientSenderPid,
+ ServerReceiverPid, ServerSenderPid),
+ verify_key_update(Keys0, Keys1),
%% Test mechanism to prevent infinite loop of key updates
BigData = binary:copy(<<"1234567890">>, 10), %% 100 bytes
- ok = ssl_test_lib:send(Client, BigData),
-
+ ok = ssl_test_lib:send(Sender, BigData),
+ ct:sleep(500),
+ Keys2 = get_keys(ClientReceiverPid, ClientSenderPid,
+ ServerReceiverPid, ServerSenderPid),
+ verify_key_update(Keys1, Keys2),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+get_keys(ClientReceiverPid, ClientSenderPid,
+ ServerReceiverPid, ServerSenderPid) ->
+ F = fun(Pid) ->
+ {connection, D} = sys:get_state(Pid),
+ M0 = element(3, D),
+ Cr = maps:get(current_write, M0),
+ {Pid, {maps:get(security_parameters, Cr),
+ maps:get(cipher_state, Cr)}}
+ end,
+ SendersKeys = [F(P) || P <- [ClientSenderPid, ServerSenderPid]],
+
+ G = fun(Pid) ->
+ {connection, D} = sys:get_state(Pid),
+ #state{connection_states = Cs} = D,
+ Cr = maps:get(current_read, Cs),
+ {Pid, {maps:get(security_parameters,Cr),
+ maps:get(cipher_state, Cr)}}
+ end,
+ ReceiversKeys = [G(P) || P <- [ClientReceiverPid, ServerReceiverPid]],
+ maps:from_list(SendersKeys ++ ReceiversKeys).
+
+verify_key_update(Keys0, Keys1) ->
+ V = fun(Pid, CurrentKeys) ->
+ BaseKeys = maps:get(Pid, Keys0),
+ ct:log("Pid = ~p~nBaseKeys = ~p~nCurrentKeys = ~p",
+ [Pid, BaseKeys, CurrentKeys], [esc_chars]),
+ case BaseKeys == CurrentKeys of
+ true ->
+ ct:fail("Keys don't differ for ~w", [Pid]);
+ false ->
+ ok
+ end
+ end,
+ maps:foreach(V, Keys1).
+
explicit_key_update() ->
[{doc,"Test ssl:update_key/2 between erlang client and erlang server."}].
explicit_key_update(Config) ->
Data = "123456789012345", %% 15 bytes
- Server = ssl_test_lib:start_server(erlang, [{log_level, debug}], Config),
+ Server = ssl_test_lib:start_server(erlang, [], Config),
Port = ssl_test_lib:inet_port(Server),
- Client = ssl_test_lib:start_client(erlang, [{port, Port}, {log_level, debug}], Config),
+ Client = ssl_test_lib:start_client(erlang, [{port, Port}], Config),
ssl_test_lib:send_recv_result_active(Client, Server, Data),
ssl_test_lib:update_keys(Client, write),
diff --git a/lib/ssl/test/ssl_mfl_SUITE.erl b/lib/ssl/test/ssl_mfl_SUITE.erl
index 0f9aeb1c67..3ad466590f 100644
--- a/lib/ssl/test/ssl_mfl_SUITE.erl
+++ b/lib/ssl/test/ssl_mfl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,20 +72,12 @@ pre_tls_1_3() ->
[reuse_session].
init_per_suite(Config0) ->
- catch crypto:stop(),
- try crypto:start() of
- ok ->
- ssl_test_lib:clean_start(),
- ssl:clear_pem_cache(),
- Config = ssl_test_lib:make_rsa_cert(Config0),
- ssl_test_lib:cert_options(Config)
- catch _:_ ->
- {skip, "Crypto did not start"}
- end.
+ Config1 = ssl_test_lib:init_per_suite(Config0, openssl),
+ Config = ssl_test_lib:make_rsa_cert(Config1),
+ ssl_test_lib:cert_options(Config).
-end_per_suite(_Config) ->
- ssl:stop(),
- application:stop(crypto).
+end_per_suite(Config) ->
+ ssl_test_lib:end_per_suite(Config).
init_per_group(GroupName, Config) ->
ssl_test_lib:init_per_group(GroupName, Config).
diff --git a/lib/ssl/test/ssl_npn_SUITE.erl b/lib/ssl/test/ssl_npn_SUITE.erl
index 6dc889852d..26c27b88cb 100644
--- a/lib/ssl/test/ssl_npn_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -68,14 +68,18 @@
all() ->
[{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
- {group, 'tlsv1'}
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
].
groups() ->
[
{'tlsv1.2', [], next_protocol_tests()},
{'tlsv1.1', [], next_protocol_tests()},
- {'tlsv1', [], next_protocol_tests()}
+ {'tlsv1', [], next_protocol_tests()},
+ {'dtlsv1.2', [], next_protocol_tests()},
+ {'dtlsv1', [], next_protocol_tests()}
].
next_protocol_tests() ->
diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl
index dae07aae63..ee8825a724 100644
--- a/lib/ssl/test/ssl_npn_hello_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -87,7 +87,7 @@ encode_and_decode_client_hello_test(Config) ->
HandShakeData = create_client_handshake(undefined),
Version = ssl_test_lib:protocol_version(Config),
{[{DecodedHandshakeMessage, _Raw}], _} =
- tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
+ tls_handshake:get_tls_handshakes(Version, list_to_binary(HandShakeData), <<>>,
default_options_map()),
Extensions = DecodedHandshakeMessage#client_hello.extensions,
#{next_protocol_negotiation := undefined} = Extensions.
@@ -96,7 +96,7 @@ encode_and_decode_npn_client_hello_test(Config) ->
HandShakeData = create_client_handshake(#next_protocol_negotiation{extension_data = <<>>}),
Version = ssl_test_lib:protocol_version(Config),
{[{DecodedHandshakeMessage, _Raw}], _} =
- tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
+ tls_handshake:get_tls_handshakes(Version, list_to_binary(HandShakeData), <<>>,
default_options_map()),
Extensions = DecodedHandshakeMessage#client_hello.extensions,
#{next_protocol_negotiation := #next_protocol_negotiation{extension_data = <<>>}} = Extensions.
@@ -105,7 +105,7 @@ encode_and_decode_server_hello_test(Config) ->
HandShakeData = create_server_handshake(undefined),
Version = ssl_test_lib:protocol_version(Config),
{[{DecodedHandshakeMessage, _Raw}], _} =
- tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
+ tls_handshake:get_tls_handshakes(Version, list_to_binary(HandShakeData), <<>>,
default_options_map()),
Extensions = DecodedHandshakeMessage#server_hello.extensions,
#{next_protocol_negotiation := undefined} = Extensions.
@@ -115,7 +115,7 @@ encode_and_decode_npn_server_hello_test(Config) ->
HandShakeData = create_server_handshake(#next_protocol_negotiation{extension_data = <<6, "spdy/2">>}),
Version = ssl_test_lib:protocol_version(Config),
{[{DecodedHandshakeMessage, _Raw}], _} =
- tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
+ tls_handshake:get_tls_handshakes(Version, list_to_binary(HandShakeData), <<>>,
default_options_map()),
Extensions = DecodedHandshakeMessage#server_hello.extensions,
ct:log("~p ~n", [Extensions]),
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index ed74917d63..53c95c0cb7 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -17,7 +17,8 @@
%%
%% %CopyrightEnd%
%%
-
+%% (Note: See the document internal_doc/pem_and_cert_cache.md for additional
+%% information)
%%
-module(ssl_pem_cache_SUITE).
@@ -27,6 +28,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include("ssl_test_lib.hrl").
%% Callback functions
-export([all/0,
@@ -39,40 +41,66 @@
end_per_testcase/2]).
%% Testcases
--export([pem_cleanup/0,
- pem_cleanup/1,
- clear_pem_cache/0,
- clear_pem_cache/1,
+-export([pem_certfile_keyfile_periodical_cleanup/0,
+ pem_certfile_keyfile_periodical_cleanup/1,
+ pem_cacertfile_periodical_cleanup/0,
+ pem_cacertfile_periodical_cleanup/1,
+ pem_manual_cleanup/0,
+ pem_manual_cleanup/1,
invalid_insert/0,
invalid_insert/1,
- new_root_pem/0,
- new_root_pem/1,
+ new_root_pem_manual_cleanup/0,
+ new_root_pem_manual_cleanup/1,
+ new_root_pem_periodical_cleanup/0,
+ new_root_pem_periodical_cleanup/1,
+ new_root_pem_no_cleanup/0,
+ new_root_pem_no_cleanup/1,
+ new_root_pem_no_cleanup_symlink/0,
+ new_root_pem_no_cleanup_symlink/1,
+ new_root_pem_no_cleanup_hardlink/0,
+ new_root_pem_no_cleanup_hardlink/1,
+ alternative_path_hardlink/0,
+ alternative_path_hardlink/1,
+ alternative_path_symlink/0,
+ alternative_path_symlink/1,
+ alternative_path_noabspath/0,
+ alternative_path_noabspath/1,
+ alternative_path_symlink_relative/0,
+ alternative_path_symlink_relative/1,
check_cert/3
]).
-
-define(CLEANUP_INTERVAL, 5000).
+-define(BIG_CLEANUP_INTERVAL, 600000).
+-define(SLEEP_AMOUNT, 1000).
+-define(KEY(NUMBER), ssl_test_lib:hardcode_rsa_key(NUMBER)).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [
- pem_cleanup,
- clear_pem_cache,
+ [pem_certfile_keyfile_periodical_cleanup,
+ pem_cacertfile_periodical_cleanup,
+ pem_manual_cleanup,
invalid_insert,
- new_root_pem
- ].
-
-groups() ->
- [].
+ new_root_pem_manual_cleanup,
+ new_root_pem_periodical_cleanup,
+ new_root_pem_no_cleanup,
+ new_root_pem_no_cleanup_symlink,
+ new_root_pem_no_cleanup_hardlink,
+ alternative_path_noabspath,
+ alternative_path_hardlink,
+ alternative_path_symlink,
+ alternative_path_symlink_relative].
+
+groups() -> [].
init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
ssl_test_lib:clean_start(),
- %% make rsa certs
+ %% make rsa certs
ssl_test_lib:make_rsa_cert(Config0)
catch _:_ ->
{skip, "Crypto did not start"}
@@ -87,18 +115,35 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-init_per_testcase(pem_cleanup = Case, Config) ->
- application:load(ssl),
- end_per_testcase(Case, Config) ,
- application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL),
- ssl:start(),
- ct:timetrap({minutes, 1}),
+init_per_testcase(pem_certfile_keyfile_periodical_cleanup = Case, Config) ->
+ adjust_pem_periodical_cleanup_interval(Case, Config, ?CLEANUP_INTERVAL),
+ ssl:clear_pem_cache(),
+ Config;
+init_per_testcase(pem_cacertfile_periodical_cleanup = Case, Config) ->
+ adjust_pem_periodical_cleanup_interval(Case, Config, ?CLEANUP_INTERVAL),
+ ssl:clear_pem_cache(),
+ Config;
+init_per_testcase(new_root_pem_periodical_cleanup = Case, Config) ->
+ adjust_pem_periodical_cleanup_interval(Case, Config, ?CLEANUP_INTERVAL),
+ ssl:clear_pem_cache(),
+ Config;
+init_per_testcase(new_root_pem_manual_cleanup = Case, Config) ->
+ adjust_pem_periodical_cleanup_interval(Case, Config, ?BIG_CLEANUP_INTERVAL),
+ ssl:clear_pem_cache(),
Config;
-init_per_testcase(_, Config) ->
+init_per_testcase(_Case, Config) ->
ssl_test_lib:clean_start(),
- ct:timetrap({seconds, 10}),
+ ssl:clear_pem_cache(),
+ ct:timetrap({seconds, 20}),
Config.
+adjust_pem_periodical_cleanup_interval(Case, Config, Interval) ->
+ application:load(ssl),
+ end_per_testcase(Case, Config) ,
+ application:set_env(ssl, ssl_pem_cache_clean, Interval),
+ ssl:start(),
+ ct:timetrap({minutes, 1}).
+
end_per_testcase(_TestCase, Config) ->
ssl_test_lib:clean_env(),
ssl:stop(),
@@ -107,77 +152,102 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-pem_cleanup() ->
- [{doc, "Test pem cache invalidate mechanism"}].
-pem_cleanup(Config)when is_list(Config) ->
- process_flag(trap_exit, true),
- ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
- ServerOpts = proplists:get_value(server_rsa_verify_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 =
- ssl_test_lib:start_client([{node, ClientNode},
- {port, Port}, {host, Hostname},
- {mfa, {ssl_test_lib, no_result, []}},
- {from, self()}, {options, ClientOpts}]),
-
- Size = ssl_pkix_db:db_size(get_pem_cache()),
- Certfile = proplists:get_value(certfile, ServerOpts),
- {ok, FileInfo} = file:read_file_info(Certfile),
- Time = later(),
- ok = file:write_file_info(Certfile, FileInfo#file_info{mtime = Time}),
- ct:sleep(2 * ?CLEANUP_INTERVAL),
- Size1 = ssl_pkix_db:db_size(get_pem_cache()),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- false = Size == Size1.
-
-clear_pem_cache() ->
+pem_certfile_keyfile_periodical_cleanup() ->
+ [{doc, "Test PEM cache invalidate mechanism using mtime attribute "
+ "adjustment - certfile and keyfile."}].
+%% 1. establish TLS connection
+%% 2. mtime adjusted for certfile, keyfile for server
+%% 3. during cleanup:
+%% 1. 2 files removed from PEM Cache
+%% 2. Ca trust store and its references mapping tables are not affected
+%% 4. After TLS disconnect only the PEM cache is populated
+pem_certfile_keyfile_periodical_cleanup(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected => [6, 6, 2, 2],
+ cleaned => [4, 6, 2, 2], disconnected => [4, 0, 0, 0]},
+ pem_periodical_cleanup(Config, [certfile, keyfile], Expected, false).
+
+pem_cacertfile_periodical_cleanup() ->
+ [{doc, "Test pem cache invalidate mechanism using mtime attribute "
+ "adjustment - cacertfile."}].
+%% 1. establish TLS connection
+%% 2. mtime adjusted for cacertfile for server
+%% 3. during cleanup:
+%% 1. 1 file removed from PEM Cache
+%% 2. The file will however be reentered as it is a CA file that is
+%% referenced
+%% 4. After TLS disconnect only the PEM cache is populated
+pem_cacertfile_periodical_cleanup(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected => [6, 6, 2, 2],
+ cleaned => [6, 6, 2, 2], disconnected => [6, 0, 0, 0]},
+ pem_periodical_cleanup(Config, [cacertfile], Expected, true).
+
+pem_manual_cleanup() ->
[{doc,"Test that internal reference table is cleaned properly even when "
- " the PEM cache is cleared" }].
-clear_pem_cache(Config) when is_list(Config) ->
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- [_,{FilRefDb, _} |_] = element(5, State),
+ " the PEM cache is cleared" }].
+%% 1. establish 1st TLS connection
+%% 2. The server and client process will now have a reference to its CA file
+%% 3. ssl:clear_pem_cache() will empty the PEM cache but as we have
+%% references to the CAfiles they will be read back, and possible updated
+%% in the CA store. (Will not happen in this test).
+%% 4. establish 2nd TLS connection
+%% 5. Now there will be two server and two client processes in total 4 references
+%% 6. The same files are used for both connections so the total amount of file is
+%% still 6.
+%% 7. Upon disconnecting summed ref counters are reduced to 2 and 0
+%% When there is no reference to a CA file (the entries for its CA certs)
+%% will be removed from the CA store. All files will still be cached.
+%% 10. Clear the PEM cache and check that it is empty.
+pem_manual_cleanup(Config) when is_list(Config) ->
+ %% Initialy all tables are empty. First size will be nubmer of
+ %% files (PEM cache), second size will be number of CA certs (CA store),
+ %% third and forth number of CA files (used for reference counting and mapping
+ %% from filename to ref key)
+ [0, 0, 0, 0] = get_table_sizes(),
+
{Server, Client} = basic_verify_test_no_close(Config),
- CountReferencedFiles = fun({_, -1}, Acc) ->
- Acc;
- ({_, N}, Acc) ->
- N + Acc
- end,
-
- 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
- ssl:clear_pem_cache(),
- _ = sys:get_status(whereis(ssl_manager)),
+ 2 = get_total_number_of_references(),
+ %% 6 files (cacerts,cert,key x 2), 6 CA certs in 2 different CA files
+ [6, 6, 2, 2] = get_table_sizes(),
+
+ ssl:clear_pem_cache(),
+ [2, 6, 2, 2] = get_table_sizes(), %% Pemcache cleared and used CAs read back
+
{Server1, Client1} = basic_verify_test_no_close(Config),
- 4 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- ct:sleep(2000),
- _ = sys:get_status(whereis(ssl_manager)),
- 2 = ets:foldl(CountReferencedFiles, 0, FilRefDb),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client1),
- ct:sleep(2000),
- _ = sys:get_status(whereis(ssl_manager)),
- 0 = ets:foldl(CountReferencedFiles, 0, FilRefDb).
+ %% Total 4 processes reference a CA file
+ 4 = get_total_number_of_references(),
+ %% New connection causes keys end entity certs and keys to be cached again
+ [6, 6, 2, 2] = get_table_sizes(),
+
+ [ssl_test_lib:close(A) || A <- [Server, Client]],
+ [6, 6, 2, 2] = get_table_sizes(), %% All CA files are still referenced
+ %% Total 2 processes reference a CA file
+ 2 = get_total_number_of_references(),
+
+ [ssl_test_lib:close(A) || A <- [Server1, Client1]],
+ %% No processes reference a CA file
+ 0 = get_total_number_of_references(),
+ %% All files are still cached
+ [6, 0, 0, 0] = get_table_sizes(),
+
+ ssl:clear_pem_cache(),
+ [0, 0, 0, 0] = get_table_sizes().
invalid_insert() ->
[{doc, "Test that insert of invalid pem does not cause empty cache entry"}].
-invalid_insert(Config)when is_list(Config) ->
+%% 1. attempt to establish TLS connection with client passing invalid path in
+%% cacertfile option
+%% 2. verify PEM Cache table is populated with options passed by server
+%% 3. connection is not established as error happens during handshake,
+%% when client tries to open file passed in cacertfile option
+%% 4. verify Cert, CaFileRef tables are empty and the reference count is zero
+invalid_insert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
-
+ [0, 0, 0, 0] = get_table_sizes(), %% Initialy all tables are empty
ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} | proplists:delete(cacertfile, ClientOpts)],
+ BadClientOpts = [{cacertfile, "tmp/does_not_exist.pem"} |
+ proplists:delete(cacertfile, ClientOpts)],
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
@@ -187,37 +257,419 @@ invalid_insert(Config)when is_list(Config) ->
ssl_test_lib:start_client_error([{node, ClientNode},
{port, Port}, {host, Hostname},
{from, self()}, {options, BadClientOpts}]),
- ssl_test_lib:close(Server),
- 1 = ssl_pkix_db:db_size(get_fileref_db()).
+ [3, 0, 0, 0] = get_table_sizes(), %% Server options are cached and bad client options ignored
+ 0 = get_total_number_of_references(),
+ [3, 0, 0, 0] = get_table_sizes(). %% Cache is still valid
+
+new_root_pem_manual_cleanup() ->
+ [{doc, "Test that changed PEM-files on disk followed by ssl:clear_pem_cache()"
+ " invalidates trusted CA cache as well as ordinary PEM cache. "
+ "This test case recreates a PEM file, resulting with its actual content change."}].
+%% 1. ITERATE below over 2 cert chains
+%% 1. in one scenario overwritten cert chain has the same private keys - so both
+%% cert chains are 'compatible'
+%% 2. in second scenario overwrittern cert chain has a differet private key for
+%% intermediate cert - cert chains are not 'compatible'
+%% 2. create initial config in PEM files - 1st cert chain is created
+%% 3. make 1st TLS connection
+%% 4. verify cert on client side by:
+%% 1. get server Cert with ssl:peercert(Socket)
+%% 2. extract trusted certs from file - load data from disk
+%% 3. with CA certs extracted from file, attempt to build a chain for server Cert
+%% 4. verify that RootCert found is the same as one passed as argument
+%% 5. check tables are populated as expected
+%% 6. (copy server cacertfile to separate file - for checking chain with not
+%% cleanup flow)
+%% 7. overwrite config in PEM files - server cert chain is updated
+%% 8. check in-memory tables were not changed even though files on disk are updated
+%% 9. -> ssl:clear_pem_cache() / ct:sleep() -
+%% 10. check PemCache is empty CaRefCnt and CaFileRef tables are unchanged
+%% 11. check Cert table was update (certificate conntent was updated)
+%% 12. make 2nd TLS connection
+%% 13. verify server cert on client side (use NEW server root as argument)
+%% 14. check the sum of counters is 4 - 2 connections using same cert data
+%% 15. check CaFileRef table contains same data as for 1st connection
+%% 16. check Cert table was reloaded with different certs
+%% 17. check PemCache table was loaded with different file content
+%% 18. close connections in a sequence, check sum of counters value and final
+%% content of tables (connection related should be empty when last connection
+%% is terminated)
+new_root_pem_manual_cleanup(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ cleaned => [2, 6, 2, 2], connected2 => [6, 6, 2, 2],
+ disconnected1 => [6, 6, 2, 2], disconnected2 => [6,0,0,0]},
+ new_root_pem_helper(Config, manual, Expected, fun identity/1),
+ %% verify also same key sequence for initial and overwritten certs PEM files
+ new_root_pem_helper(Config, manual, Expected, fun identity/1, 5).
+
+new_root_pem_periodical_cleanup() ->
+ [{doc, "Test that changed PEM-files on disk followed by periodical cleanup"
+ " invalidates trusted CA store as well as ordinary PEM cache. "
+ "This test case recreates a PEM file, resulting with its actual content change."}].
+%% see new_root_pem_manual_cleanup for specification
+new_root_pem_periodical_cleanup(Config) when is_list(Config) ->
+ ExpectedStats = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ cleaned => [2, 6, 2, 2], connected2 => [6, 6, 2, 2],
+ disconnected1 => [6, 6, 2, 2], disconnected2 => [6,0,0,0]},
+ new_root_pem_helper(Config, periodical, ExpectedStats, fun identity/1),
+ %% verify also same key sequence for initial and overwritten certs PEM files
+ new_root_pem_helper(Config, periodical, ExpectedStats, fun identity/1, 5).
+
+new_root_pem_no_cleanup() ->
+ [{doc, "Test that changed PEM-files on disk not followed by any cleanup"
+ " will not be used for making connection."
+ "This test case recreates a PEM file, resulting with its actual content change."}].
+%% 1. for link variant, replace path in ClientConf with a link - both
+%% connection will use links on client side
+%% 2. create initial config in PEM files - 1st cert chain is created
+%% 3. make 1st TLS connection
+%% 4. verify server cert on client side by:
+%% 1. get server Cert with ssl:peercert(Socket)
+%% 2. extract trusted certs from file - load data from disk
+%% 3. with CA certs extracted from file, attempt to build a chain for server Cert
+%% 4. verify that RootCert found is the same as one passed as argument
+%% 5. check tables are populated as expected
+%% 6. (copy server cacertfile to separate file - for checking chain with not
+%% cleanup flow)
+%% 7. overwrite config in PEM files - server cert chain is updated
+%% 8. check in-memory tables were not changed even though files on disk are updated
+%% 9. make 2nd TLS connection
+%% 10. verify server cert on client side (use the same server root as argument)
+%% 11. check the sum of counters is 4 - 2 connections using same cert data
+%% 12. check PemCache and Cert tables hold the same data as for 1st connection
+%% 13. close connections in a sequence, check sum of counters value and final
+%% content of tables (connection related should be empty when last connection
+%% is terminated)
+new_root_pem_no_cleanup(Config) when is_list(Config) ->
+ ExpectedStats = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ cleaned => [6, 6, 2, 2], connected2 => [6, 6, 2, 2],
+ disconnected1 => [6, 6, 2, 2], disconnected2 => [6,0,0,0]},
+ new_root_pem_helper(Config, no_cleanup, ExpectedStats, fun identity/1).
+
+new_root_pem_no_cleanup_symlink() ->
+ [{doc, "Test that changed PEM-files on disk not followed by any cleanup"
+ " will not be used for making connection - even with symlink. "
+ "This test case recreates a PEM file, resulting with its actual content change."}].
+%% see new_root_pem_no_cleanup for specification
+new_root_pem_no_cleanup_symlink(Config) when is_list(Config) ->
+ ExpectedStats = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ cleaned => [6, 6, 2, 2], connected2 => [6, 6, 2, 2],
+ disconnected1 => [6, 6, 2, 2], disconnected2 => [6,0,0,0]},
+ new_root_pem_helper(Config, no_cleanup, ExpectedStats, fun make_symlink/1).
+
+new_root_pem_no_cleanup_hardlink() ->
+ [{doc, "Test that changed PEM-files on disk not followed by any cleanup"
+ " will not be used for making connection - even with hardlink. "
+ "This test case recreates a PEM file, resulting with its actual content change."}].
+%% see new_root_pem_no_cleanup for specification
+new_root_pem_no_cleanup_hardlink(Config) when is_list(Config) ->
+ ExpectedStats = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ cleaned => [6, 6, 2, 2], connected2 => [6, 6, 2, 2],
+ disconnected1 => [6, 6, 2, 2], disconnected2 => [6,0,0,0]},
+ new_root_pem_helper(Config, no_cleanup, ExpectedStats, fun make_hardlink/1).
+
+alternative_path_hardlink() ->
+ [{doc,"Test that internal reference table contains expected data for"
+ " absolute and hard link. "
+ "This test verifies handling of same file with an alternative reference."}].
+%% 1. copy client cacertfile to CWD
+%% 2. establish connection using client CA cert file specified with full path
+%% 3. check sum of counters is 2
+%% 4. check table sizes
+%% 5. establish connection using client CA cert file specified with alternative
+%% - hardlink, symlink or just filename instead of path
+%% 6. check sum of counters is 4
+%% 7. check table sizes
+%% 8. copy client CA cert file into sub-directory
+%% 9. change CWD to subdirectory
+%% 10. establish connection using client CA cert file specified with alternative
+%% - hardlink, symlink or just filename instead of path
+alternative_path_hardlink(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ connected2 => [7, 9, 3, 3], connected3 => [8, 12, 4, 4],
+ disconnected => [8, 0, 0, 0]},
+ alternative_path_helper(Config, fun make_hardlink/1, Expected).
+
+alternative_path_symlink() ->
+ [{doc,"Test that internal reference table contains only one instance of data "
+ "for absolute path and symbolic link pointing to same file."
+ "This test verifies handling of same file with an alternative reference."
+ "Symlink is expected to be converted to absolute file path - "
+ "as a result establishing 2nd connection should not add new data to tables."}].
+%% see alternative_path_hardlink for detailed specification
+alternative_path_symlink(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ connected2 => [6, 6, 2, 2], connected3 => [7, 9, 3, 3],
+ disconnected => [7, 0, 0, 0]},
+ alternative_path_helper(Config, fun make_symlink/1, Expected).
+
+alternative_path_noabspath() ->
+ [{doc,"Test that internal reference table contains only one instance of data "
+ "for absolute and relative paths pointing to same file. "
+ "This test verifies handling of same file with an alternative reference."
+ "Relative file path is expected to be converted to absolute file path - "
+ "as a result establishing 2nd connection should not add new data to tables."}].
+%% see alternative_path_hardlink for detailed specification
+alternative_path_noabspath(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ connected2 => [6, 6, 2, 2], connected3 => [7, 9, 3, 3],
+ disconnected => [7, 0, 0, 0]},
+ alternative_path_helper(Config, fun strip_path/1, Expected).
+
+alternative_path_symlink_relative() ->
+ [{doc,"Test that internal reference table contains separate instance of data "
+ "for absolute path and relative symbolic ink pointing to a file in subdirectory."
+ "This test verifies handling of different files."
+ "Relative path to a symlink is expected to be converted to absolute file path - "
+ "as a result establishing 2nd connection should add new data to tables."}].
+%% see alternative_path_hardlink for detailed specification
+alternative_path_symlink_relative(Config) when is_list(Config) ->
+ Expected = #{init => [0, 0, 0, 0], connected1 => [6, 6, 2, 2],
+ connected2 => [7, 9, 3, 3], connected3 => [8, 12, 4, 4],
+ disconnected => [8, 0, 0, 0]},
+ alternative_path_helper(Config, fun make_symlink_noabspath/1, Expected).
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+get_table_sizes() ->
+ ct:sleep(?SLEEP_AMOUNT),
+ DbSizes = [{Label, Db, ssl_pkix_db:db_size(Db)} ||
+ {Label, Db} <- get_table_refs()],
+ [Size || {_, _, Size} <- DbSizes].
+
+get_total_number_of_references() ->
+ CaFileRef = proplists:get_value(ca_ref_cnt, get_table_refs()),
+ CountReferencedFiles = fun({Ref, _}, Acc) ->
+ ets:update_counter(CaFileRef,Ref,0) + Acc
+ end,
+ ets:foldl(CountReferencedFiles, 0, CaFileRef).
+
+get_table_refs() ->
+ _ = sys:get_status(whereis(ssl_manager)),
+ _ = sys:get_status(whereis(ssl_pem_cache)),
+ {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = ssl_test_lib:state(Prop),
+ case element(5, State) of
+ [Cert, {CaRefCnt, CaFileRef}, PemCache| _] ->
+ [{pem_cache, PemCache},
+ {cert, Cert},
+ {ca_ref_cnt, CaRefCnt},
+ {ca_file_ref, CaFileRef}];
+ _ ->
+ undefined
+ end.
-new_root_pem() ->
- [{doc, "Test that changed PEM-files on disk followed by ssl:clear_pem_cache() invalidates"
- "trusted CA cache as well as ordinary PEM cache"}].
-new_root_pem(Config)when is_list(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- #{cert := OrgSRoot} = SRoot =
- public_key:pkix_test_root_cert("OTP test server ROOT", [{key, ssl_test_lib:hardcode_rsa_key(6)}]),
-
- DerConfig = public_key:pkix_test_data(#{server_chain => #{root => SRoot,
- intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
- intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}),
-
- ClientBase = filename:join(PrivDir, "client_test"),
- SeverBase = filename:join(PrivDir, "server_test"),
- PemConfig = x509_test:gen_pem_config_files(DerConfig, ClientBase, SeverBase),
- ClientConf = proplists:get_value(client_config, PemConfig),
- ServerConf = proplists:get_value(server_config, PemConfig),
+get_tables() ->
+ [{Id, get_table(T)} || {Id, T} <- get_table_refs()].
+
+check_tables(ExpectedTables) ->
+ ActualTables = [{Id, get_table(T)} || {Id, T} <- get_table_refs(),
+ proplists:is_defined(Id, ExpectedTables)],
+ Zipped = lists:zip(ExpectedTables, ActualTables),
+
+ CompareTables = fun({ExpectedLabel, ExpectedTable},
+ {ActualLabel, ActualTable}) ->
+ ExpectedLabel = ActualLabel,
+ ExpectedTableSorted = lists:sort(ExpectedTable),
+ ActualTableSorted = lists:sort(ActualTable),
+ case ExpectedTableSorted == ActualTableSorted of
+ true ->
+ ok;
+ _ ->
+ ?PAL("Mismatch for table ~w", [ActualLabel]),
+ ?PAL("Expected = ~w", [ExpectedTableSorted]),
+ ?PAL("Actual = ~w", [ActualTableSorted]),
+ ct:fail({data_mismatch, ActualLabel})
+ end
+ end,
+ [CompareTables(Expected, Actual) || {Expected, Actual} <- Zipped].
+
+get_table(TableRef) ->
+ get_table(TableRef, ets:first(TableRef), []).
+
+get_table(TableRef, Key, Acc) ->
+ case Key of
+ '$end_of_table' ->
+ Acc;
+ _ ->
+ get_table(TableRef, ets:next(TableRef, Key),
+ [ets:lookup(TableRef, Key) | Acc])
+ end.
- SCAFile = proplists:get_value(cacertfile, ServerConf),
+new_root_pem_helper(Config, CleanMode, ExpectedStats, TransformFun) ->
+ %% by default use different key sequence for initial and overwritten certs PEM files
+ new_root_pem_helper(Config, CleanMode, ExpectedStats, TransformFun, 6).
+new_root_pem_helper(Config, CleanMode,
+ #{init := Init, connected1 := Connected1, cleaned := Cleaned,
+ connected2 := Connected2, disconnected1 := Disconnected1,
+ disconnected2 := Disconnected2} = _ExpectedStats, TransformFun,
+ IntermediateServerKeyId) ->
+ %% ExpectedStats map passed to function contains expected sizes of tables
+ %% holding various cert, cacert, keyfile data.
+ %% Init - represents initial state
+ %% ConnectedN - state after establishing Nth connection
+ %% Cleaned - state after periodical cleanup
+ %% DisconnectedN - state after closing Nth connection
+ ?PAL(">>> IntermediateServerKeyId = ~w", [IntermediateServerKeyId]),
+ {ServerCAFile, ClientConf0, ServerConf, ServerRootCert0, ClientBase, ServerBase} =
+ create_initial_config(Config),
+
+ CACertfilePath = proplists:get_value(cacertfile, ClientConf0),
+ case TransformFun(CACertfilePath) of
+ {ok, TransformedPath} ->
+ ClientConf = [{cacertfile, TransformedPath} | proplists:delete(cacertfile, ClientConf0)],
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Init = get_table_sizes(),
+ {Client0, Server0} =
+ make_connection_check_cert(ServerRootCert0, ClientNode, ClientConf,
+ ServerNode, ServerConf, Hostname, ServerCAFile),
+ Connected1 = get_table_sizes(),
+ [{pem_cache, PemCacheData0}, {cert, CertData0},
+ {ca_ref_cnt, CaRefCntData0}, {ca_file_ref, CaFileRefData0}] = get_tables(),
+ ServerCAFile0 = ServerCAFile ++ "_original",
+ {ok, _} = file:copy(ServerCAFile, ServerCAFile0),
+ ServerRootCert =
+ overwrite_files_with_new_configuration(ServerRootCert0,
+ ClientBase, ServerBase,
+ IntermediateServerKeyId),
+ check_tables([{pem_cache, PemCacheData0}, {cert, CertData0},
+ {ca_ref_cnt, CaRefCntData0}, {ca_file_ref, CaFileRefData0}]),
+ case CleanMode of
+ manual -> ssl:clear_pem_cache();
+ periodical -> ct:sleep(round(1.5 * ?CLEANUP_INTERVAL));
+ no_cleanup -> ok
+ end,
+ Cleaned = get_table_sizes(),
+
+ [{pem_cache, PemCacheData1}, {cert, CertData1},
+ {ca_ref_cnt, CaRefCntData1}, {ca_file_ref, _}] = get_tables(),
+ {Client1, Server1} = case CleanMode of
+ no_cleanup ->
+ check_tables([{pem_cache, PemCacheData0},
+ {cert, CertData0},
+ {ca_ref_cnt, CaRefCntData0},
+ {ca_file_ref, CaFileRefData0}]),
+ make_connection_check_cert(ServerRootCert0, ClientNode, ClientConf,
+ ServerNode, ServerConf, Hostname, ServerCAFile0);
+ _ ->
+ false = (CertData1 == CertData0),
+ make_connection_check_cert(ServerRootCert, ClientNode, ClientConf,
+ ServerNode, ServerConf, Hostname, ServerCAFile)
+ end,
+
+ 4 = get_total_number_of_references(),
+ Connected2 = get_table_sizes(),
+ [{pem_cache, PemCacheData2}, {cert, CertData2},
+ {ca_ref_cnt, CaRefCntData2}, {ca_file_ref, _}] = get_tables(),
+ case CleanMode of
+ no_cleanup ->
+ check_tables([{pem_cache, PemCacheData0},
+ {cert, CertData0}]);
+ _ ->
+ check_tables([{ca_file_ref, CaFileRefData0}]),
+ false = (CertData0 == CertData2),
+ false = (PemCacheData0 == PemCacheData2)
+ end,
+ true = (CaRefCntData2 /= CaRefCntData1),
+
+ [ssl_test_lib:close(A) || A <- [Client1, Server1]],
+ 2 = get_total_number_of_references(),
+ Disconnected1 = get_table_sizes(),
+
+ case CleanMode of
+ no_cleanup ->
+ check_tables([{pem_cache, PemCacheData1}]);
+ _ ->
+ check_tables([{pem_cache, PemCacheData2}])
+ end,
+ check_tables([{cert, CertData1}, {ca_ref_cnt, CaRefCntData0},
+ {ca_file_ref, CaFileRefData0}]),
+ [ssl_test_lib:close(A) || A <- [Client0, Server0]],
+ 0 = get_total_number_of_references(),
+ Disconnected2 = get_table_sizes(),
+ case CleanMode of
+ no_cleanup ->
+ check_tables([{pem_cache, PemCacheData1}, {cert, []},
+ {ca_ref_cnt, []}, {ca_file_ref, []}]);
+ _ ->
+ check_tables([{pem_cache, PemCacheData2}, {cert, []},
+ {ca_ref_cnt, []}, {ca_file_ref, []}])
+ end,
+
+ ssl:clear_pem_cache(),
+ [0, 0, 0, 0] = get_table_sizes(),
+ ok;
+ {skip, Reason} ->
+ {skip, Reason}
+ end.
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+alternative_path_helper(Config, GetAlternative,
+ #{init := Init, connected1 := Connected1,
+ connected2 := Connected2, connected3 := Connected3,
+ disconnected := Disconnected}) ->
+ %% ExpectedStats map passed to function contains expected sizes of tables
+ %% holding various cert, cacert, keyfile data.
+ %% Init - represents initial state
+ %% ConnectedN - state after establishing Nth connection
+ %% Disconnected - state after closing connections
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
+ CACertFilePath0 = proplists:get_value(cacertfile, ClientOpts),
+ {ok, CACertFilename} = strip_path(CACertFilePath0),
+ {ok, Cwd} = file:get_cwd(),
+
+ CACertFilePath1 = filename:join([Cwd, CACertFilename]),
+ {ok, _} = file:copy(CACertFilePath0, CACertFilePath1),
+ 0 = get_total_number_of_references(),
+ Init = get_table_sizes(),
+
+ %% connect with full path
+ {Server0, Client0} = basic_verify_test_no_close(
+ replace_cacertfile(Config, CACertFilePath1)),
+ 2 = get_total_number_of_references(),
+ Connected1 = get_table_sizes(),
+
+ TestAlternative = fun(ExpectedTotalCounter, ExpectedSizes, CertPath) ->
+ case GetAlternative(CertPath) of
+ {skip, _} = R ->
+ [{skip, R}];
+ {ok, Alternative} ->
+ %% connect with filename only
+ {Server, Client} = basic_verify_test_no_close(
+ replace_cacertfile(Config, Alternative)),
+ ExpectedTotalCounter = get_total_number_of_references(),
+ ExpectedSizes = get_table_sizes(),
+ [Server, Client]
+ end
+ end,
+
+ R1 = TestAlternative(4, Connected2, CACertFilePath1),
+
+ %% check that same filenames in different folders don't collide
+ SubDirPath = make_subdirectory(Cwd, "subdir"),
+ CACertFilePath2 = filename:join([SubDirPath, CACertFilename]),
+
+ {ok, _} = file:copy(CACertFilePath0, CACertFilePath2),
+ ok = c:cd(SubDirPath),
+ R2 = TestAlternative(6, Connected3, CACertFilePath2),
+
+ ProcessesCreated = R1 ++ R2,
+ case proplists:lookup(skip, ProcessesCreated) of
+ none ->
+ [ssl_test_lib:close(Actor) || Actor <- [Server0, Client0] ++
+ ProcessesCreated],
+ ct:sleep(?SLEEP_AMOUNT),
+ _ = sys:get_status(whereis(ssl_manager)),
+ 0 = get_total_number_of_references(),
+ Disconnected = get_table_sizes(),
+ ok;
+ {skip, Reason} ->
+ {skip, Reason}
+ end.
- %% Start a connection and keep it up for a little while, so that
- %% it will be up when the second connection is started.
+make_connection_check_cert(ServerRootCert, ClientNode, ClientConf, ServerNode,
+ ServerConf, Hostname, ServerCAFile) ->
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
@@ -227,86 +679,131 @@ new_root_pem(Config)when is_list(Config) ->
Client =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
- {mfa, {?MODULE, check_cert, [OrgSRoot, SCAFile]}},
- {from, self()}, {options, [{verify, verify_peer} |ClientConf]}]),
+ {from, self()},
+ {mfa, {?MODULE, check_cert,
+ [ServerRootCert, ServerCAFile]}},
+ {options, [{verify, verify_peer} | ClientConf]}]),
ssl_test_lib:check_result(Client, ok),
+ {Client, Server}.
- %% Create new configuration
- Key = ssl_test_lib:hardcode_rsa_key(1),
- OTPCert = public_key:pkix_decode_cert(OrgSRoot, otp),
+create_initial_config(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ #{cert := ServerRootCert0} = SRoot =
+ public_key:pkix_test_root_cert("OTP test server ROOT",
+ [{key, ?KEY(6)}]),
+ DerConfig =
+ public_key:pkix_test_data(
+ #{server_chain =>
+ #{root => SRoot,
+ intermediates => [[{key, ?KEY(5)}]],
+ peer => [{key, ?KEY(4)}]},
+ client_chain =>
+ #{root => [{key, ?KEY(1)}],
+ intermediates => [[{key, ?KEY(2)}]],
+ peer => [{key, ?KEY(3)}]}}),
+ ClientBase = filename:join(PrivDir, "client_test"),
+ ServerBase = filename:join(PrivDir, "server_test"),
+ PemConfig = x509_test:gen_pem_config_files(DerConfig, ClientBase, ServerBase),
+ ClientConf = proplists:get_value(client_config, PemConfig),
+ ServerConf = proplists:get_value(server_config, PemConfig),
+ {proplists:get_value(cacertfile, ServerConf), ClientConf, ServerConf, ServerRootCert0,
+ ClientBase, ServerBase}.
+
+overwrite_files_with_new_configuration(ServerRootCert0, ClientBase,
+ ServerBase, IntermediateServerKey) ->
+ Key = ?KEY(1),
+ OTPCert = public_key:pkix_decode_cert(ServerRootCert0, otp),
TBS = OTPCert#'OTPCertificate'.tbsCertificate,
#'RSAPrivateKey'{modulus=N, publicExponent=E} = Key,
Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
SPKI = #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
subjectPublicKey = Public},
- NewCert = public_key:pkix_sign(TBS#'OTPTBSCertificate'{subjectPublicKeyInfo = SPKI}, Key),
-
- DerConfig1 = public_key:pkix_test_data(#{server_chain =>
- #{root => #{cert => NewCert, key => Key},
- intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(4)}]},
- client_chain =>
- #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
- intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}]}}),
-
+ ServerRootCert1 = public_key:pkix_sign(TBS#'OTPTBSCertificate'{subjectPublicKeyInfo = SPKI}, Key),
+ DerConfig1 =
+ public_key:pkix_test_data(
+ #{server_chain =>
+ #{root => #{cert => ServerRootCert1, key => Key},
+ intermediates => [[{key, ?KEY(IntermediateServerKey)}]],
+ peer => [{key, ?KEY(4)}]},
+ client_chain =>
+ #{root => [{key, ?KEY(1)}],
+ intermediates => [[{key, ?KEY(2)}]],
+ peer => [{key, ?KEY(3)}]}}),
%% Overwrite old config files
- _ = x509_test:gen_pem_config_files(DerConfig1, ClientBase, SeverBase),
+ _ = x509_test:gen_pem_config_files(DerConfig1, ClientBase, ServerBase),
+ ServerRootCert1.
+
+pem_periodical_cleanup(Config, FileIds,
+ #{init := Init, connected := Connected,
+ cleaned := Cleaned, disconnected := Disconnected} = _ExpectedStats, IsSame)->
+ %% ExpectedStats map passed to function contains expected sizes of tables
+ %% holding various cert, cacert, keyfile data.
+ %% Init - represents initial state
+ %% Connected - state after connection is established
+ %% Cleaned - state after periodical cleanup
+ %% Disconnected - state after disconnecting
+ process_flag(trap_exit, true),
+ %% wait so that certificate mtime is smaller the ssl_pem_cache start time
+ %% we want to avoid invalidation of all cert files - happens when server
+ %% start time and file mtime is the same number in seconds
+ %% and all files get invalidated
+ ct:sleep(4 * ?SLEEP_AMOUNT),
+ Init = get_table_sizes(),
- %% Make sure cache is cleared
- ssl:clear_pem_cache(),
-
- Server1 =
- ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib, no_result, []}},
- {options, ServerConf}]),
- Port1 = ssl_test_lib:inet_port(Server1),
-
- %% Start second connection
- Client1 = ssl_test_lib:start_client([{node, ClientNode},
- {port, Port1}, {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, check_cert, [NewCert, SCAFile]}},
- {options, [{verify, verify_peer} | ClientConf]}]),
- ssl_test_lib:check_result(Client1, ok),
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Server1),
- ssl_test_lib:close(Client),
- ssl_test_lib:close(Client1).
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
-%%--------------------------------------------------------------------
-%% Internal funcations
-%%--------------------------------------------------------------------
+ {Server, Client} = basic_verify_test_no_close(Config),
-get_pem_cache() ->
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- case element(5, State) of
- [_CertDb, _FileRefDb, PemCache| _] ->
- PemCache;
- _ ->
- undefined
+ Connected = get_table_sizes(),
+ [{pem_cache, PemCacheData0}, {cert, CertData0}, {ca_ref_cnt, CaRefCntData0},
+ {ca_file_ref, CaFileRefData0}] = get_tables(),
+
+ MakeLookingYounger =
+ fun (Type) ->
+ %% make file looking like modified recently
+ Certfile = proplists:get_value(Type, ServerOpts),
+ {ok, #file_info{mtime = OriginalTime} = FileInfo} =
+ file:read_file_info(Certfile),
+ Time = later(),
+ ok = file:write_file_info(Certfile, FileInfo#file_info{mtime = Time}),
+ {Certfile, FileInfo, OriginalTime}
+ end,
+
+ Memory = [MakeLookingYounger(F) || F <- FileIds],
+ ct:sleep(round(1.5 * ?CLEANUP_INTERVAL)),
+ _ = sys:get_status(whereis(ssl_manager)),
+ Result =
+ try
+ Cleaned = get_table_sizes(),
+ [{pem_cache, PemCacheData1}, _, _, _] = get_tables(),
+ IsSame = PemCacheData1 == PemCacheData0,
+ check_tables([{pem_cache, PemCacheData1}, {cert, CertData0}, {ca_ref_cnt, CaRefCntData0},
+ {ca_file_ref, CaFileRefData0}]),
+ [true = lists:member(Row, PemCacheData0) || Row <- PemCacheData1],
+ %% restore original mtime attributes
+ [ok = file:write_file_info(C, F#file_info{mtime = OT}) ||
+ {C, F, OT} <- Memory],
+
+ [ssl_test_lib:close(A) || A <- [Server, Client]],
+ Disconnected = get_table_sizes(),
+ ok
+ catch _:Reason ->
+ Reason
+ end,
+ case Result of
+ ok ->
+ ok;
+ _ ->
+ ct:fail(Result)
end.
-get_fileref_db() ->
- {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
- [_, _,_, _, Prop] = StatusInfo,
- State = ssl_test_lib:state(Prop),
- case element(5, State) of
- [_CertDb, {FileRefDb,_} | _] ->
- FileRefDb;
- _ ->
- undefined
- end.
later()->
- DateTime = calendar:now_to_local_time(os:timestamp()),
+ DateTime = calendar:now_to_local_time(os:timestamp()),
Gregorian = calendar:datetime_to_gregorian_seconds(DateTime),
calendar:gregorian_seconds_to_datetime(Gregorian + (2 * ?CLEANUP_INTERVAL)).
-
+
basic_verify_test_no_close(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
@@ -323,14 +820,68 @@ basic_verify_test_no_close(Config) ->
{from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ClientOpts}]),
-
ssl_test_lib:check_result(Server, ok, Client, ok),
{Server, Client}.
+replace_cacertfile(Config, CACertFile) ->
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ClientOpts = [{cacertfile, CACertFile} | proplists:delete(cacertfile, ClientOpts0)],
+ [{client_rsa_opts, ClientOpts} | proplists:delete(client_rsa_opts, Config)].
check_cert(Socket, RootCert, File) ->
{ok, Cert} = ssl:peercert(Socket),
{ok, Extracted} = ssl_pkix_db:extract_trusted_certs(File),
- {ok, RootCert, _} = ssl_certificate:certificate_chain(Cert, ets:new(foo, []), Extracted, [], encoded),
+ {ok, RootCert, _} = ssl_certificate:certificate_chain(Cert, ets:new(foo, []),
+ Extracted, [], encoded),
ok.
+strip_path(AbsPath) ->
+ {ok, lists:last(filename:split(AbsPath))}.
+
+make_hardlink(AbsPath) ->
+ LinkPath = AbsPath ++ "_hardlink",
+ case file:make_link(AbsPath, LinkPath) of
+ ok ->
+ {ok, LinkPath};
+ Reason ->
+ {skip, Reason}
+ end.
+
+make_symlink(AbsPath) ->
+ LinkPath = AbsPath ++ "_symlink",
+ case file:make_symlink(AbsPath, LinkPath) of
+ ok ->
+ {ok, LinkPath};
+ Reason ->
+ {skip, Reason}
+ end.
+
+make_symlink_noabspath(CACertFilePath1) ->
+ {ok, Cwd} = file:get_cwd(),
+ {ok, CACertFilename1} = strip_path(CACertFilePath1),
+
+ SubDir = "foo",
+ SubDirPath = make_subdirectory(Cwd, SubDir),
+ CACertFilename2 = CACertFilename1 ++ "_copy",
+ LinkName = CACertFilename2 ++ "_symlink",
+ CACertFilePath2 = filename:join([SubDirPath, CACertFilename2]),
+ {ok, _} = file:copy(CACertFilePath1, CACertFilePath2),
+ case file:make_symlink(CACertFilename2,
+ filename:join([SubDirPath, LinkName])) of
+ ok ->
+ {ok, filename:join([SubDir, LinkName])};
+ Reason ->
+ {skip, Reason}
+ end.
+
+make_subdirectory(Cwd, SubDir) ->
+ SubDirPath = filename:join([Cwd, SubDir]),
+ case file:read_file_info(SubDirPath) of
+ {error, enoent} ->
+ ok = file:make_dir(SubDirPath);
+ _ ->
+ ok
+ end,
+ SubDirPath.
+
+identity(Path) -> {ok, Path}.
diff --git a/lib/ssl/test/ssl_reject_SUITE.erl b/lib/ssl/test/ssl_reject_SUITE.erl
index 08d0321020..7221b629ac 100644
--- a/lib/ssl/test/ssl_reject_SUITE.erl
+++ b/lib/ssl/test/ssl_reject_SUITE.erl
@@ -38,7 +38,9 @@
]).
%% Test cases
--export([reject_sslv2/0,
+-export([reject_prev/0,
+ reject_prev/1,
+ reject_sslv2/0,
reject_sslv2/1,
reject_sslv3/0,
reject_sslv3/1,
@@ -65,17 +67,19 @@ all() ->
{group, 'tlsv1.3'},
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
- {group, 'tlsv1'}
- ].
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'}
+ ].
groups() ->
- [{'tlsv1.3', [], all_versions_tests()},
- {'tlsv1.2', [], all_versions_tests()},
- {'tlsv1.1', [], all_versions_tests()},
- {'tlsv1', [], all_versions_tests()}
+ [{'tlsv1.3', [], [reject_prev] ++ all_tls_version_tests()},
+ {'tlsv1.2', [], [reject_prev] ++ all_tls_version_tests()},
+ {'tlsv1.1', [], [reject_prev] ++ all_tls_version_tests()},
+ {'tlsv1', [], all_tls_version_tests()},
+ {'dtlsv1.2', [], [reject_prev]}
].
-all_versions_tests() ->
+all_tls_version_tests() ->
[
reject_sslv2,
reject_sslv3,
@@ -127,12 +131,12 @@ reject_sslv2(Config) when is_list(Config) ->
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- %% SSL-2.0 Hello
+ %% SSL-2.0 Hello
ClientHello = <<128,43,?CLIENT_HELLO, ?SSL_2_0_MAJOR, ?SSL_2_0_MINOR,
0,18,0,0,0,16,7,0,192,3,0,128,1,0,128,6,0,64,4,0,
128,2,0,128,115,245,33,148,17,175,69,226,204,214,132,216,182,
41,238,196>>,
-
+
{ok, Socket} = gen_tcp:connect(Hostname, Port, [{active, false}]),
gen_tcp:send(Socket, ClientHello),
@@ -145,7 +149,6 @@ reject_sslv3() ->
[{doc,"Test that SSL v3 clients are rejected"}].
reject_sslv3(Config) when is_list(Config) ->
- Version = proplists:get_value(version, Config),
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -156,7 +159,7 @@ reject_sslv3(Config) when is_list(Config) ->
%% SSL-3.0 Hello
ClientHello =
- <<?HANDSHAKE, ?SSL_3_0_MAJOR, ?SSL_3_0_MINOR,0,162, ?CLIENT_HELLO, 0,0,158,
+ <<?HANDSHAKE, ?SSL_3_0_MAJOR, ?SSL_3_0_MINOR,0,162, ?CLIENT_HELLO, 0,0,158,
?TLS_MAJOR, ?SSL_3_0_MINOR, 97,160,130,59,226,182,64,143,134,112,117,
64,10,57,164,101,182,215,0,199,145,232,172,194,45,242,48,176,5,153,
101,54,0,0,26,0,255,192,10,192,20,192,5,192,15,192,9,192,19,192,4,192,
@@ -168,14 +171,8 @@ reject_sslv3(Config) when is_list(Config) ->
{ok, Socket} = gen_tcp:connect(Hostname, Port, [{active, false}]),
gen_tcp:send(Socket, ClientHello),
%% v3 is not a supported protocol version (but hello record could have 3.0 for legacy interop)
- case Version of
- 'tlsv1.3' ->
- ssl_test_lib:check_server_alert(Server, illegal_parameter),
- client_rejected(Socket, illegal_parameter);
- _ ->
- ssl_test_lib:check_server_alert(Server, protocol_version),
- client_rejected(Socket, protocol_version)
- end.
+ ssl_test_lib:check_server_alert(Server, protocol_version),
+ client_rejected(Socket, protocol_version).
accept_sslv3_record_hello() ->
[{doc,"Test that ssl v3 record in clients hellos are ignored when higher version are advertised"}].
@@ -198,13 +195,42 @@ accept_sslv3_record_hello(Config) when is_list(Config) ->
{ok, Socket} = gen_tcp:connect(Hostname, Port, [{active, false}]),
gen_tcp:send(Socket, ClientHello),
case gen_tcp:recv(Socket, 3, 5000) of
- %% Minor needs to be a TLS version that is a version
- %% above SSL-3.0
+ %% Minor needs to be a TLS version that is a version
+ %% above SSL-3.0
{ok, [?HANDSHAKE, ?TLS_MAJOR, Minor]} when Minor > ?SSL_3_0_MINOR ->
ok;
- {error, timeout} ->
+ {error, timeout} ->
ct:fail(ssl3_record_not_accepted)
end.
+
+
+reject_prev() ->
+ [{doc,"Test that prev version is rejected, for all version where there"
+ "exists possible support a previous version, that is not configured"}].
+
+reject_prev(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Version = proplists:get_value(version, Config),
+ PrevVersion = prev_version(Version),
+
+ 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),
+
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ no_result, []}},
+ {options,[{versions, [PrevVersion]} | ClientOpts]}]),
+ ssl_test_lib:check_client_alert(Server, Client, protocol_version).
+
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------
%%--------------------------------------------------------------------
@@ -273,3 +299,12 @@ hello_with_3_0_record('tlsv1.3') ->
42,42,32,73,84,134,110,74,110,163,140,111,177,126,133,118,141,2,153,
156,157,205,101,69,0,10,0,10,0,8,0,29,0,30,0,23,0,24,0,11,0,2,1,0,0,
?SUPPORTED_VERSIONS_EXT,0,3,2,?TLS_MAJOR, ?TLS_1_3_MINOR>>.
+
+prev_version('tlsv1.3') ->
+ 'tlsv1.2';
+prev_version('tlsv1.2') ->
+ 'tlsv1.1';
+prev_version('tlsv1.1') ->
+ 'tlsv1';
+prev_version('dtlsv1.2') ->
+ 'dtlsv1'.
diff --git a/lib/ssl/test/ssl_session_cache_api_SUITE.erl b/lib/ssl/test/ssl_session_cache_api_SUITE.erl
index 2277e0fa66..0f775ea7ba 100644
--- a/lib/ssl/test/ssl_session_cache_api_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_api_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,9 @@
-include("tls_handshake.hrl").
%% Callback functions
--export([all/0]).
+-export([all/0,
+ init_per_suite/1,
+ end_per_suite/1]).
%% Testcases
-export([server_cb/0,
@@ -43,6 +45,21 @@
all() ->
[server_cb,
client_cb].
+
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config0
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_session_ticket_SUITE.erl b/lib/ssl/test/ssl_session_ticket_SUITE.erl
index 8056b40d72..0c981b5b83 100644
--- a/lib/ssl/test/ssl_session_ticket_SUITE.erl
+++ b/lib/ssl/test/ssl_session_ticket_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,8 +35,16 @@
%% Testcases
-export([basic/0,
basic/1,
- basic_anti_replay/0,
- basic_anti_replay/1,
+ ticketage_smaller_than_windowsize_anti_replay/0,
+ ticketage_smaller_than_windowsize_anti_replay/1,
+ ticketage_bigger_than_windowsize_anti_replay/0,
+ ticketage_bigger_than_windowsize_anti_replay/1,
+ ticketage_out_of_lifetime_anti_replay/0,
+ ticketage_out_of_lifetime_anti_replay/1,
+ ticket_reuse_anti_replay/0,
+ ticket_reuse_anti_replay/1,
+ ticket_reuse_anti_replay_server_restart/0,
+ ticket_reuse_anti_replay_server_restart/1,
basic_stateful_stateless/0,
basic_stateful_stateless/1,
basic_stateless_stateful/0,
@@ -92,7 +100,11 @@ groups() ->
{group, stateless},
{group, mixed}]},
{stateful, [], session_tests()},
- {stateless, [], session_tests() ++ [basic_anti_replay]},
+ {stateless, [], session_tests() ++
+ [ticketage_smaller_than_windowsize_anti_replay,
+ ticketage_bigger_than_windowsize_anti_replay,
+ ticketage_out_of_lifetime_anti_replay, ticket_reuse_anti_replay,
+ ticket_reuse_anti_replay_server_restart]},
{mixed, [], mixed_tests()}].
session_tests() ->
@@ -167,9 +179,9 @@ basic(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
+ ServerOpts = [{session_tickets, ServerTicketMode},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
@@ -212,73 +224,195 @@ basic(Config) when is_list(Config) ->
ssl_test_lib:close(Server0),
ssl_test_lib:close(Client1).
-basic_anti_replay() ->
- [{doc,"Test session resumption with stateless session tickets and anti_replay (erlang client - erlang server)"}].
-basic_anti_replay(Config) when is_list(Config) ->
+ticketage_smaller_than_windowsize_anti_replay() ->
+ [{doc, "Session resumption with stateless tickets and anti_replay enabled."
+ "ClientHello with DeltaAge smaller than Bloom filter window size - fresh ClientHello."
+ "DeltaAge treated as particular ClientHello adjective, calculated "
+ "as a difference between RealAge and ReportedAge of a ticket used in ClientHello."
+ "Ticket age smaller than windowsize."
+ "(Erlang client - Erlang server)"}].
+ticketage_smaller_than_windowsize_anti_replay(Config) when is_list(Config) ->
+ {Server0, Client0, Port0, ClientNode, Hostname, ClientOpts} =
+ anti_replay_helper_init(Config, auto, 10),
+ ssl_test_lib:check_result(Server0, ok, Client0, ok),
+ Client1 = anti_replay_helper_connect(Server0, Client0, Port0, ClientNode,
+ Hostname, ClientOpts, 0, true),
+ process_flag(trap_exit, false),
+ [ssl_test_lib:close(A) || A <- [Server0, Client0, Client1]].
+
+ticketage_bigger_than_windowsize_anti_replay() ->
+ [{doc, "Session resumption with stateless tickets and anti_replay enabled."
+ "Fresh ClientHellos."
+ "Ticket age bigger than windowsize. 0-RTT is expected to fail."
+ "(Erlang client - Erlang server)"}].
+ticketage_bigger_than_windowsize_anti_replay(Config) when is_list(Config) ->
+ WindowSize = 3,
+ {Server0, Client0, Port0, ClientNode, Hostname, ClientOpts} =
+ anti_replay_helper_init(Config, auto, WindowSize),
+ ssl_test_lib:check_result(Server0, ok, Client0, ok),
+ Client1 = anti_replay_helper_connect(Server0, Client0, Port0, ClientNode,
+ Hostname, ClientOpts,
+ {seconds, WindowSize + 2}, false),
+ Client2 = anti_replay_helper_connect(Server0, Client0, Port0, ClientNode,
+ Hostname, ClientOpts,
+ {seconds, 2*WindowSize + 2}, false),
+ process_flag(trap_exit, false),
+ [ssl_test_lib:close(A) || A <- [Server0, Client0, Client1, Client2]].
+
+ticketage_out_of_lifetime_anti_replay() ->
+ [{doc, "Session resumption with stateless tickets and anti_replay enabled."
+ "Fresh ClientHello."
+ "Ticket age beyond its lifetime. 0-RTT is expected to fail."
+ "(Erlang client - Erlang server)"}].
+ticketage_out_of_lifetime_anti_replay(Config) when is_list(Config) ->
+ Lifetime = 4,
+ WindowSize = 2,
+ {Server0, Client0, Port0, ClientNode, Hostname, ClientOpts} =
+ anti_replay_helper_init(Config, auto, WindowSize, Lifetime),
+ ssl_test_lib:check_result(Server0, ok, Client0, ok),
+ Client1 = anti_replay_helper_connect(Server0, Client0, Port0, ClientNode,
+ Hostname, ClientOpts,
+ {seconds, Lifetime + 2}, false),
+ process_flag(trap_exit, false),
+ [ssl_test_lib:close(A) || A <- [Server0, Client0, Client1]].
+
+ticket_reuse_anti_replay() ->
+ [{doc, "Verify that 2 connection attempts with same stateless tickets "
+ "are successful."
+ "Fresh ClientHellos."
+ "Ticket age smaller than windowsize."
+ "Anti_replay allows it because both "
+ "ClientHellos are unique, look fresh(small enough DeltaAge) "
+ "and do not look like a replay attempt."
+ "(Erlang client - Erlang server)"}].
+ticket_reuse_anti_replay(Config) when is_list(Config) ->
+ {Server0, Client0, Port0, ClientNode, Hostname, ClientOpts0} =
+ anti_replay_helper_init(Config, manual, 10),
+ [Ticket] = ssl_test_lib:check_tickets(Client0),
+ ssl_test_lib:check_result(Server0, ok),
+ ClientOpts1 = [{use_ticket, [Ticket]} | ClientOpts0],
+ Client1 = anti_replay_helper_connect(Server0, Client0, Port0, ClientNode,
+ Hostname, ClientOpts1, 0, true),
+ Client2 = anti_replay_helper_connect(Server0, Client1, Port0, ClientNode,
+ Hostname, ClientOpts1, 0, true),
+ process_flag(trap_exit, false),
+ [ssl_test_lib:close(A) || A <- [Server0, Client0, Client2]].
+
+ticket_reuse_anti_replay_server_restart() ->
+ [{doc, "Verify 2 connection attempts with same stateless tickets "
+ "and server restart between. Second attempt is expected to fail as long as "
+ "Bloom filter window overlaps with startup time."
+ "Fresh ClientHellos."
+ "(Erlang client - Erlang server)"
+
+ "RFC8446 8.2: When implementations are freshly started, they SHOULD reject "
+ "0-RTT as long as any portion of their recording window overlaps the startup "
+ "time. Otherwise, they run the risk of accepting replays which were "
+ "originally sent during that period."
+ }].
+ticket_reuse_anti_replay_server_restart(Config) when is_list(Config) ->
+ WindowSize = 10,
+ {Server0, Client0, Port0, ClientNode, Hostname, ClientOpts0} =
+ anti_replay_helper_init(Config, manual, WindowSize),
+ [Ticket] = ssl_test_lib:check_tickets(Client0),
+ ssl_test_lib:check_result(Server0, ok),
+ ClientOpts1 = [{use_ticket, [Ticket]} | ClientOpts0],
+ Client1 = anti_replay_helper_connect(Server0, Client0, Port0, ClientNode,
+ Hostname, ClientOpts1, 0, true),
+ {Server1, Port1} = anti_replay_helper_start_server(Config, WindowSize),
+ Client2 = anti_replay_helper_connect(Server1, Client1, Port1, ClientNode,
+ Hostname, ClientOpts1, 0, false, false),
+ process_flag(trap_exit, false),
+ [ssl_test_lib:close(A) || A <- [Server0, Client2, Server1]].
+
+anti_replay_helper_init(Config, Mode, WindowSize) ->
+ DefaultLifetime = ssl_config:get_ticket_lifetime(),
+ anti_replay_helper_init(Config, Mode, WindowSize, DefaultLifetime).
+
+anti_replay_helper_init(Config, Mode, WindowSize, Lifetime) ->
+ application:set_env(ssl, server_session_ticket_lifetime, Lifetime),
ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
+ {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ %% Configure session tickets
+ ClientOpts = [{session_tickets, Mode},
+ {versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0],
+
+ {Server0 , Port0} = anti_replay_helper_start_server(Config, WindowSize),
+ MFA = case Mode of
+ auto ->
+ {ssl_test_lib,
+ verify_active_session_resumption,
+ [false]};
+ manual ->
+ {ssl_test_lib,
+ verify_active_session_resumption,
+ [false, wait_reply, {tickets, 1}]}
+ end,
+
+ %% Store ticket from first connection
+ Client0 = ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port0}, {host, Hostname},
+ {mfa, MFA},
+ {from, self()}, {options, ClientOpts}]),
+ {Server0, Client0, Port0, ClientNode, Hostname, ClientOpts}.
+
+anti_replay_helper_start_server(Config, WindowSize) ->
+ {_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
- {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
-
- %% Configure session tickets
- ClientOpts = [{session_tickets, auto}, {log_level, debug},
- {versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
- {anti_replay, '10k'},
+ ServerOpts = [{session_tickets, ServerTicketMode},
+ {anti_replay, {WindowSize, 5, 72985}},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
- Server0 =
+ Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib,
verify_active_session_resumption,
[false]}},
{options, ServerOpts}]),
- Port0 = ssl_test_lib:inet_port(Server0),
-
- %% Store ticket from first connection
- Client0 = ssl_test_lib:start_client([{node, ClientNode},
- {port, Port0}, {host, Hostname},
- {mfa, {ssl_test_lib, %% Full handshake
- verify_active_session_resumption,
- [false]}},
- {from, self()}, {options, ClientOpts}]),
- ssl_test_lib:check_result(Server0, ok, Client0, ok),
-
- Server0 ! {listen, {mfa, {ssl_test_lib,
- verify_active_session_resumption,
- [true]}}},
+ Port0 = ssl_test_lib:inet_port(Server),
+ {Server, Port0}.
+
+anti_replay_helper_connect(Server, Client0, Port0, ClientNode, Hostname,
+ ClientOpts, Delay, ExpectedResumption) ->
+ anti_replay_helper_connect(Server, Client0, Port0, ClientNode, Hostname,
+ ClientOpts, Delay, ExpectedResumption, true).
+
+anti_replay_helper_connect(Server, Client0, Port0, ClientNode, Hostname,
+ ClientOpts, Delay, ExpectedResumption, SendListen) ->
+ case SendListen of
+ true ->
+ Server ! {listen, {mfa, {ssl_test_lib,
+ verify_active_session_resumption,
+ [ExpectedResumption]}}};
+ _ ->
+ ok
+ end,
%% Wait for session ticket
ct:sleep(100),
-
ssl_test_lib:close(Client0),
-
+ ct:sleep(Delay),
%% Use ticket
Client1 = ssl_test_lib:start_client([{node, ClientNode},
{port, Port0}, {host, Hostname},
{mfa, {ssl_test_lib, %% Short handshake
verify_active_session_resumption,
- [true]}},
+ [ExpectedResumption]}},
{from, self()}, {options, ClientOpts}]),
- ssl_test_lib:check_result(Server0, ok, Client1, ok),
-
- process_flag(trap_exit, false),
- ssl_test_lib:close(Server0),
- ssl_test_lib:close(Client1).
+ ssl_test_lib:check_result(Server, ok, Client1, ok),
+ Client1.
basic_stateful_stateless() ->
[{doc,"Test session resumption with session tickets (erlang client - erlang server)"}].
basic_stateful_stateless(Config) when is_list(Config) ->
do_test_mixed(Config,
[{session_tickets, auto},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateful},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateless},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}]).
basic_stateless_stateful() ->
@@ -286,13 +420,10 @@ basic_stateless_stateful() ->
basic_stateless_stateful(Config) when is_list(Config) ->
do_test_mixed(Config,
[{session_tickets, auto},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateless},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateful},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}]).
basic_stateful_stateless_anti_replay() ->
@@ -300,13 +431,10 @@ basic_stateful_stateless_anti_replay() ->
basic_stateful_stateless_anti_replay(Config) when is_list(Config) ->
do_test_mixed(Config,
[{session_tickets, auto},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateful},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateless},
- {log_level, debug},
{anti_replay, '10k'},
{versions, ['tlsv1.2','tlsv1.3']}]).
@@ -315,14 +443,11 @@ basic_stateless_stateful_anti_replay() ->
basic_stateless_stateful_anti_replay(Config) when is_list(Config) ->
do_test_mixed(Config,
[{session_tickets, auto},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateless},
- {log_level, debug},
{anti_replay, '10k'},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateful},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}]).
basic_stateful_stateless_faulty_ticket() ->
@@ -330,19 +455,15 @@ basic_stateful_stateless_faulty_ticket() ->
basic_stateful_stateless_faulty_ticket(Config) when is_list(Config) ->
do_test_mixed(Config,
[{session_tickets, auto},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, manual},
{use_ticket, [<<131,100,0,12,"faultyticket">>,
<<"faulty ticket">>]},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateless},
- {log_level, debug},
{anti_replay, '10k'},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateful},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}]).
basic_stateless_stateful_faulty_ticket() ->
@@ -350,19 +471,15 @@ basic_stateless_stateful_faulty_ticket() ->
basic_stateless_stateful_faulty_ticket(Config) when is_list(Config) ->
do_test_mixed(Config,
[{session_tickets, auto},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, manual},
{use_ticket, [<<"faulty ticket">>,
<<131,100,0,12,"faultyticket">>]},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateless},
- {log_level, debug},
{anti_replay, '10k'},
{versions, ['tlsv1.2','tlsv1.3']}],
[{session_tickets, stateful},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}]).
hello_retry_request() ->
@@ -374,10 +491,10 @@ hello_retry_request(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups,[secp256r1, x25519]}|ClientOpts0],
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
+ ServerOpts = [{session_tickets, ServerTicketMode},
{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups, [x448, x25519]}|ServerOpts0],
@@ -430,9 +547,9 @@ multiple_tickets(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
+ ServerOpts = [{session_tickets, ServerTicketMode},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
@@ -488,9 +605,9 @@ multiple_tickets_2hash(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
- ServerOpts = [{session_tickets, ServerTicketMode}, {log_level, debug},
+ ServerOpts = [{session_tickets, ServerTicketMode},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
@@ -617,7 +734,7 @@ early_data_trial_decryption(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send maximum sized early data to verify calculation of plain text size
%% in the server.
@@ -625,7 +742,6 @@ early_data_trial_decryption(Config) when is_list(Config) ->
%% Disabled early data triggers trial decryption upon receiving early data
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, disabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
@@ -677,7 +793,7 @@ early_data_client_too_much_data(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send more early data than max_early_data_size to verify calculation
%% of plain text size in the server.
@@ -685,7 +801,6 @@ early_data_client_too_much_data(Config) when is_list(Config) ->
ClientOpts2 = [{early_data, binary:copy(<<"F">>, 16384)}|ClientOpts1],
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, disabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
application:set_env(ssl, server_session_ticket_max_early_data, MaxEarlyDataSize),
@@ -739,7 +854,7 @@ early_data_trial_decryption_failure(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send more early data than max_early_data_size to verify calculation
%% of plain text size in the server.
@@ -756,7 +871,6 @@ early_data_trial_decryption_failure(Config) when is_list(Config) ->
%% in the ticket used for the 0-RTT handshake. If more data is sent the
%% client will trigger an illegal_parameter alert (too_much_early_data).
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, disabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
application:set_env(ssl, server_session_ticket_max_early_data, MaxEarlyDataSize),
@@ -792,7 +906,7 @@ early_data_trial_decryption_failure(Config) when is_list(Config) ->
ssl_test_lib:close(Client0),
%% Use ticket
- Client1 = ssl_test_lib:start_client_error([{node, ClientNode},
+ _Client1 = ssl_test_lib:start_client_error([{node, ClientNode},
{port, Port0}, {host, Hostname},
{mfa, {ssl_test_lib, %% Short handshake
verify_active_session_resumption,
@@ -812,7 +926,7 @@ early_data_decryption_failure(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, manual}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, manual},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send more early data than max_early_data_size to verify calculation
%% of plain text size in the server.
@@ -820,7 +934,6 @@ early_data_decryption_failure(Config) when is_list(Config) ->
ClientOpts2 = [{early_data, binary:copy(<<"F">>, 16385)}|ClientOpts1],
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, enabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
application:set_env(ssl, server_session_ticket_max_early_data, MaxEarlyDataSize),
@@ -856,7 +969,7 @@ early_data_decryption_failure(Config) when is_list(Config) ->
ssl_test_lib:close(Client0),
%% Use ticket
- Client1 = ssl_test_lib:start_client_error([{node, ClientNode},
+ _Client1 = ssl_test_lib:start_client_error([{node, ClientNode},
{port, Port0}, {host, Hostname},
{mfa, {ssl_test_lib, %% Short handshake
verify_active_session_resumption,
@@ -876,7 +989,7 @@ early_data_disabled_small_limit(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send maximum sized early data to verify calculation of plain text size
%% in the server.
@@ -885,7 +998,6 @@ early_data_disabled_small_limit(Config) when is_list(Config) ->
%% Disabled early data triggers trial decryption upon receiving early data
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, disabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
application:set_env(ssl, server_session_ticket_max_early_data, MaxEarlyDataSize),
Server0 =
@@ -938,7 +1050,7 @@ early_data_enabled_small_limit(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send maximum sized early data to verify calculation of plain text size
%% in the server.
@@ -947,7 +1059,6 @@ early_data_enabled_small_limit(Config) when is_list(Config) ->
%% Disabled early data triggers trial decryption upon receiving early data
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, enabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
application:set_env(ssl, server_session_ticket_max_early_data, MaxEarlyDataSize),
Server0 =
@@ -1000,7 +1111,7 @@ early_data_basic(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send maximum sized early data to verify calculation of plain text size
%% in the server.
@@ -1009,7 +1120,6 @@ early_data_basic(Config) when is_list(Config) ->
%% Disabled early data triggers trial decryption upon receiving early data
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, enabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
@@ -1061,7 +1171,7 @@ early_data_basic_auth(Config) when is_list(Config) ->
ServerTicketMode = proplists:get_value(server_ticket_mode, Config),
%% Configure session tickets
- ClientOpts1 = [{session_tickets, auto}, {log_level, debug},
+ ClientOpts1 = [{session_tickets, auto},
{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0],
%% Send maximum sized early data to verify calculation of plain text size
%% in the server.
@@ -1070,7 +1180,6 @@ early_data_basic_auth(Config) when is_list(Config) ->
%% Disabled early data triggers trial decryption upon receiving early data
ServerOpts = [{session_tickets, ServerTicketMode}, {early_data, enabled},
- {log_level, debug},
{versions, ['tlsv1.2','tlsv1.3']}|ServerOpts0],
Server0 =
diff --git a/lib/ssl/test/ssl_sni_SUITE.erl b/lib/ssl/test/ssl_sni_SUITE.erl
index a5419e8586..ab243bc6c9 100644
--- a/lib/ssl/test/ssl_sni_SUITE.erl
+++ b/lib/ssl/test/ssl_sni_SUITE.erl
@@ -379,7 +379,7 @@ sni_no_trailing_dot(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, [{log_level, debug} | ServerOpts]}]),
+ {options, [ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
@@ -387,8 +387,8 @@ sni_no_trailing_dot(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, [{log_level, debug},
- {server_name_indication, Hostname ++ "."} |ClientOpts]}]),
+ {options,
+ [{server_name_indication, Hostname ++ "."} | ClientOpts]}]),
ssl_test_lib:check_server_alert(Server, Client, unrecognized_name).
hostname_trailing_dot() ->
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 0e9e4d7490..4b0618bc86 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-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
-export([clean_start/0,
clean_start/1,
clean_env/0,
+ init_per_suite/2, end_per_suite/1,
init_per_group/2,
init_per_group_openssl/2,
end_per_group/2,
@@ -51,6 +52,7 @@
start_upgrade_server/1,
start_upgrade_server_error/1,
start_upgrade_client/1,
+ start_upgrade_client_error/1,
start_client_error/1,
start_server_error/1,
start_server_transport_abuse_socket/1,
@@ -70,6 +72,7 @@
run_upgrade_server/1,
run_upgrade_client/1,
run_upgrade_server_error/1,
+ run_upgrade_client_error/1,
run_client_error/1,
send_recv_result_active/3,
wait_for_result/2,
@@ -103,7 +106,7 @@
verify_server_early_data/3,
verify_session_ticket_extension/2,
update_session_ticket_extension/2,
- check_sane_openssl_version/1,
+ check_sane_openssl_version/2,
check_ok/1,
check_result/4,
check_result/2,
@@ -124,9 +127,10 @@
client_msg/2,
server_msg/2,
hardcode_rsa_key/1,
+ hardcode_dsa_key/1,
bigger_buffers/0,
stop/2,
- working_openssl_client/0,
+ working_openssl_client/1,
hostname_format/1
]).
@@ -146,6 +150,7 @@
-export([tls_version/1,
is_protocol_version/1,
+ is_tls_version/1,
is_dtls_version/1,
protocol_version/1,
protocol_version/2,
@@ -193,7 +198,6 @@
openssl_sane_dtls/0,
kill_openssl/0,
openssl_allows_server_renegotiate/1,
- openssl_dtls_maxfraglen_support/0,
openssl_maxfraglen_support/0,
is_sane_oppenssl_pss/1,
consume_port_exit/1,
@@ -204,7 +208,7 @@
openssl_ecdsa_suites/0,
openssl_dsa_suites/0,
enough_openssl_crl_support/1,
- openssl_ocsp_support/0,
+ openssl_ocsp_support/1,
openssl_allows_client_renegotiate/1,
version_flag/1,
portable_cmd/2,
@@ -298,8 +302,43 @@ get_client_opts(Config) ->
COpts = proplists:get_value(client_opts, Config, DCOpts),
ssl_options(COpts, Config).
+
+init_per_suite(Config0, Type) ->
+ end_per_suite(Config0),
+ try crypto:start() of
+ ok ->
+ clean_start(),
+ ssl:clear_pem_cache(),
+ case Type of
+ openssl ->
+ Version = portable_cmd("openssl", ["version"]),
+ case Version of
+ "OpenSSL" ++ _ -> ok;
+ "LibreSSL" ++ _ -> ok;
+ _ -> throw({skip, "Unknown openssl version: " ++ Version})
+ end,
+ [{openssl_version, Version}|Config0];
+ _ ->
+ Config0
+ end
+ catch _:_ ->
+ throw({skip, "Crypto did not start"})
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(ssl),
+ application:stop(crypto),
+ ssl_test_lib:kill_openssl().
+
+
%% Default callback functions
init_per_group(GroupName, Config0) ->
+ case proplists:get_value(openssl_version, Config0) of
+ undefined ->
+ ok;
+ Version ->
+ put(openssl_version, Version)
+ end,
case is_protocol_version(GroupName) andalso sufficient_crypto_support(GroupName) of
true ->
Config = clean_protocol_version(Config0),
@@ -314,8 +353,8 @@ init_per_group(GroupName, Config0) ->
end
end.
-working_openssl_client() ->
- case portable_cmd("openssl", ["version"]) of
+working_openssl_client(Config) ->
+ case proplists:get_value(openssl_version, Config) of
%% These versions of OpenSSL has a client that
%% can not handle hello extensions. And will
%% fail with bad packet length if they are present
@@ -324,14 +363,25 @@ working_openssl_client() ->
false;
"OpenSSL 0.9.8k" ++ _ ->
false;
- _ ->
+ "OpenSSL" ++ _ ->
+ true;
+ "LibreSSL" ++ _ ->
true
end.
init_per_group_openssl(GroupName, Config0) ->
- case is_protocol_version(GroupName) andalso sufficient_crypto_support(GroupName) of
- true ->
+ case proplists:get_value(openssl_version, Config0) of
+ undefined ->
+ ok;
+ Version ->
+ put(openssl_version, Version)
+ end,
+ CryptoSupport = sufficient_crypto_support(GroupName),
+ IsProtocolVersion = is_protocol_version(GroupName),
+ if
+ CryptoSupport andalso IsProtocolVersion ->
Config = clean_protocol_version(Config0),
+ ssl:start(),
case openssl_tls_version_support(GroupName, Config)
of
true ->
@@ -339,14 +389,11 @@ init_per_group_openssl(GroupName, Config0) ->
false ->
{skip, "Missing openssl support"}
end;
- _ ->
- case sufficient_crypto_support(GroupName) of
- true ->
- ssl:start(),
- Config0;
- false ->
- {skip, "Missing crypto support"}
- end
+ CryptoSupport ->
+ ssl:start(),
+ Config0;
+ true ->
+ {skip, "Missing crypto support"}
end.
end_per_group(GroupName, Config) ->
@@ -357,8 +404,8 @@ end_per_group(GroupName, Config) ->
Config
end.
-openssl_ocsp_support() ->
- case portable_cmd("openssl", ["version"]) of
+openssl_ocsp_support(Config) ->
+ case proplists:get_value(openssl_version, Config) of
"OpenSSL 1.1.1" ++ _Rest ->
true;
_ ->
@@ -432,12 +479,13 @@ normalize_loopback(Address, _) ->
start_server(Args0, Config) ->
{_, ServerNode, _} = run_where(Config),
ServerOpts = get_server_opts(Config),
+ TcServerOpts = proplists:get_value(options, Args0, []),
Node = proplists:get_value(node, Args0, ServerNode),
Port = proplists:get_value(port, Args0, 0),
Args = [{from, self()},
{node, Node},
{port, Port},
- {options, ServerOpts} | Args0],
+ {options, ServerOpts++TcServerOpts} | Args0],
start_server(Args).
%%
start_server(Args) ->
@@ -456,7 +504,6 @@ run_server(Opts) ->
Pid = proplists:get_value(from, Opts),
Transport = proplists:get_value(transport, Opts, ssl),
?LOG("~nssl:listen(~p, ~p)~n", [Port, format_options(Options)]),
- %% {ok, ListenSocket} = Transport:listen(Port, Options),
case Transport:listen(Port, Options) of
{ok, ListenSocket} ->
Pid ! {listen, up},
@@ -495,7 +542,10 @@ do_run_server(ListenSocket, AcceptSocket, Opts) ->
ok;
Msg ->
?LOG("~nServer Msg: ~p ~n", [Msg]),
- Pid ! {self(), Msg}
+ case lists:member(return_socket, Opts) of
+ true -> Pid ! {self(), {Msg, AcceptSocket}};
+ false -> Pid ! {self(), Msg}
+ end
end,
do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid).
@@ -723,7 +773,12 @@ init_openssl_server(openssl, _, Options) ->
DOpenssl = proplists:get_value(debug_openssl, Options, false),
Port = inet_port(node()),
Pid = proplists:get_value(from, Options),
-
+
+ case proplists:get_value(openssl_version, Options) of
+ undefined -> ok;
+ Version -> put(openssl_version, Version)
+ end,
+
Exe = "openssl",
Ciphers = proplists:get_value(ciphers, Options, default_ciphers(Version)),
Groups0 = proplists:get_value(groups, Options),
@@ -865,6 +920,11 @@ init_openssl_client(Options) ->
Port = proplists:get_value(port, Options),
Pid = proplists:get_value(from, Options),
SslPort = start_client(openssl, Port, Options, [{version, Version}]),
+ case proplists:get_value(openssl_version, Options) of
+ undefined -> ok;
+ Version -> put(openssl_version, Version)
+ end,
+
openssl_client_loop(Pid, SslPort, []).
@@ -1047,13 +1107,17 @@ client_loop_core(Socket, Pid, Transport) ->
{gen_tcp, closed} ->
ok;
{apply, From, Fun} ->
- try
- Res = Fun(Socket, Transport),
- From ! {apply_res, Res}
+ try Fun(Socket, Transport) of
+ {replace, NewSocket} = Res ->
+ From ! {apply_res, Res},
+ client_loop_core(NewSocket, Pid, Transport);
+ Res ->
+ From ! {apply_res, Res},
+ client_loop_core(Socket, Pid, Transport)
catch E:R:ST ->
- From ! {apply_res, {E,R,ST}}
- end,
- client_loop_core(Socket, Pid, Transport)
+ From ! {apply_res, {E,R,ST}},
+ client_loop_core(Socket, Pid, Transport)
+ end
end.
client_cont_loop(_Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
@@ -1324,7 +1388,10 @@ format_certs(Cert) when is_binary(Cert) ->
lists:flatten(format_cert(Cert)).
format_cert(BinCert) when is_binary(BinCert) ->
- OtpCert = #'OTPCertificate'{tbsCertificate = Cert} = public_key:pkix_decode_cert(BinCert, otp),
+ format_cert(public_key:pkix_decode_cert(BinCert, otp));
+format_cert(#cert{otp=Otp}) ->
+ format_cert(Otp);
+format_cert(#'OTPCertificate'{tbsCertificate = Cert} = OtpCert) ->
#'OTPTBSCertificate'{subject = Subject, serialNumber = Nr, issuer = Issuer} = Cert,
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -1990,6 +2057,25 @@ run_upgrade_client(Opts) ->
ssl:close(SslSocket)
end.
+start_upgrade_client_error(Args) ->
+ Node = proplists:get_value(node, Args),
+ spawn_link(Node, ?MODULE, run_upgrade_client_error, [Args]).
+
+run_upgrade_client_error(Opts) ->
+ Host = proplists:get_value(host, Opts),
+ Port = proplists:get_value(port, Opts),
+ Pid = proplists:get_value(from, Opts),
+ Timeout = proplists:get_value(timeout, Opts, infinity),
+ TcpOptions = proplists:get_value(tcp_options, Opts),
+ SslOptions = proplists:get_value(ssl_options, Opts),
+ ?LOG("gen_tcp:connect(~p, ~p, ~p)",
+ [Host, Port, TcpOptions]),
+ {ok, Socket} = gen_tcp:connect(Host, Port, TcpOptions),
+ send_selected_port(Pid, Port, Socket),
+ ?LOG("ssl:connect(~p, ~p)", [Socket, SslOptions]),
+ Error = ssl:connect(Socket, SslOptions, Timeout),
+ Pid ! {self(), Error}.
+
start_upgrade_server_error(Args) ->
Node = proplists:get_value(node, Args),
Result = spawn_link(Node,?MODULE, run_upgrade_server_error, [Args]),
@@ -2669,8 +2755,7 @@ is_dtls_version('dtlsv1') ->
is_dtls_version(_) ->
false.
-openssl_tls_version_support(Version, Config0) ->
- %% Check if version is supported
+openssl_tls_version_support(Version, Config0) ->
Config = make_rsa_cert(Config0),
ServerOpts = proplists:get_value(server_rsa_opts, Config),
Port = inet_port(node()),
@@ -2679,20 +2764,37 @@ openssl_tls_version_support(Version, Config0) ->
KeyFile = proplists:get_value(keyfile, ServerOpts),
Exe = "openssl",
Opts0 = [{versions, [Version]}, {verify, verify_none}],
- {Proto, Opts} = case is_tls_version(Version) of
- true -> {tls, [{protocol,tls}|Opts0]};
- false -> {dtls, patch_dtls_options([{protocol, dtls}|Opts0])}
- end,
- Args0 = case Proto of
- tls ->
- ["s_server", "-accept",
- integer_to_list(Port), "-CAfile", CaCertFile,
- "-cert", CertFile,"-key", KeyFile];
- dtls ->
- ["s_server", "-accept",
- integer_to_list(Port), "-dtls", "-CAfile", CaCertFile,
- "-cert", CertFile,"-key", KeyFile]
- end,
+ TLSOpts = [{protocol,tls}|Opts0],
+ DTLSOpts = patch_dtls_options([{protocol, dtls}|Opts0]),
+
+ TLSArgs = ["s_server", "-accept",
+ integer_to_list(Port), "-CAfile", CaCertFile,
+ "-cert", CertFile,"-key", KeyFile],
+ DTLSArgs = ["s_server", "-accept",
+ integer_to_list(Port), "-dtls", "-CAfile", CaCertFile,
+ "-cert", CertFile,"-key", KeyFile],
+
+ case is_tls_version(Version) of
+ true ->
+ openssl_tls_version_support(tls, TLSOpts, Port, Exe, TLSArgs);
+ false ->
+ DTLSTupleVersion = dtls_record:protocol_version(Version),
+ CorrespondingTLSVersion = dtls_v1:corresponding_tls_version(DTLSTupleVersion),
+ AtomTLSVersion = tls_record:protocol_version(CorrespondingTLSVersion),
+ CorrTLSOpts = [{protocol,tls}, {versions, [AtomTLSVersion]},
+ {verify, verify_none}],
+ case openssl_tls_version_support(tls, CorrTLSOpts, Port, Exe, TLSArgs) of
+ true ->
+ %% If corresponding TLS version is not supported DTLS
+ %% will not be supported and test for it will be inconclusive
+ %% due to UDP not being a reliable transport
+ openssl_tls_version_support(dtls, DTLSOpts, Port, Exe, DTLSArgs);
+ false ->
+ false
+ end
+ end.
+
+openssl_tls_version_support(Proto, Opts, Port, Exe, Args0) ->
Args = maybe_force_ipv4(Args0),
OpensslPort = portable_open_port(Exe, Args),
try wait_for_openssl_server(Port, Proto) of
@@ -2703,7 +2805,7 @@ openssl_tls_version_support(Version, Config0) ->
close_port(OpensslPort),
true;
{error, {tls_alert, {protocol_version, _}}} ->
- ?PAL("OpenSSL does not support ~p", [Version]),
+ ?PAL("OpenSSL does not support ~p", [proplists:get_value(versions, Opts)]),
close_port(OpensslPort),
false;
{error, {tls_alert, Alert}} ->
@@ -2717,7 +2819,7 @@ openssl_tls_version_support(Version, Config0) ->
end
catch
_:_ ->
- ?PAL("OpenSSL does not support ~p", [Version]),
+ ?PAL("OpenSSL does not support ~p", [proplists:get_value(versions, Opts)]),
close_port(OpensslPort),
false
end.
@@ -3117,24 +3219,27 @@ is_sane_oppenssl_pss(rsa_pss_rsae) ->
false
end.
-is_fips(openssl) ->
- VersionStr = portable_cmd("openssl",["version"]),
+is_fips(openssl, Config) ->
+ VersionStr = proplists:get_value(openssl_version, Config),
case re:split(VersionStr, "fips") of
[_] ->
- false;
- _ ->
+ case re:split(VersionStr, "FIPS") of
+ [_] ->
+ false;
+ _ ->
+ true
+ end;
+ _ ->
true
end;
-is_fips(crypto) ->
+is_fips(crypto, _) ->
[{_,_, Bin}] = crypto:info_lib(),
case re:split(Bin, <<"fips">>) of
[_] ->
false;
_ ->
true
- end;
-is_fips(_) ->
- false.
+ end.
%% Actual support is tested elsewhere, this is to exclude some LibreSSL and OpenSSL versions
openssl_sane_dtls() ->
@@ -3157,10 +3262,10 @@ openssl_sane_dtls() ->
false
end.
-check_sane_openssl_version(Version) ->
- case supports_ssl_tls_version(Version) of
+check_sane_openssl_version(Version, Config) ->
+ case supports_ssl_tls_version(Version, Config) of
true ->
- case {Version, portable_cmd("openssl",["version"])} of
+ case {Version, proplists:get_value(openssl_version, Config)} of
{'dtlsv1', "OpenSSL 0" ++ _} ->
false;
{'dtlsv1.2', "OpenSSL 0" ++ _} ->
@@ -3170,9 +3275,9 @@ check_sane_openssl_version(Version) ->
{'dtlsv1', "OpenSSL 1.0.0" ++ _} ->
false;
{'dtlsv1', _} ->
- not is_fips(openssl);
+ not is_fips(openssl, Config);
{'dtlsv1.2', _} ->
- not is_fips(openssl);
+ not is_fips(openssl, Config);
{_, "OpenSSL 1.0.2" ++ _} ->
true;
{_, "OpenSSL 1.0.1" ++ _} ->
@@ -3196,7 +3301,7 @@ check_sane_openssl_version(Version) ->
check_sane_openssl_renegotiate(Config, Version) when Version == 'tlsv1';
Version == 'tlsv1.1';
Version == 'tlsv1.2' ->
- case portable_cmd("openssl", ["version"]) of
+ case proplists:get_value(openssl_version, Config) of
"OpenSSL 1.0.1c" ++ _ ->
{skip, "Known renegotiation bug in OpenSSL"};
"OpenSSL 1.0.1b" ++ _ ->
@@ -3216,7 +3321,7 @@ check_sane_openssl_renegotiate(Config, _) ->
check_sane_openssl_renegotiate(Config).
check_sane_openssl_renegotiate(Config) ->
- case portable_cmd("openssl", ["version"]) of
+ case proplists:get_value(openssl_version, Config) of
"OpenSSL 1.0.0" ++ _ ->
{skip, "Known renegotiation bug in OpenSSL"};
"OpenSSL 0.9.8" ++ _ ->
@@ -3232,7 +3337,7 @@ check_sane_openssl_renegotiate(Config) ->
end.
openssl_allows_client_renegotiate(Config) ->
- case portable_cmd("openssl", ["version"]) of
+ case proplists:get_value(openssl_version, Config) of
"OpenSSL 3" ++ _ ->
{skip, "OpenSSL does not allow client renegotiation"};
"OpenSSL 1.1" ++ _ ->
@@ -3244,7 +3349,7 @@ openssl_allows_client_renegotiate(Config) ->
end.
openssl_allows_server_renegotiate(Config) ->
- case portable_cmd("openssl", ["version"]) of
+ case proplists:get_value(openssl_version, Config) of
"LibreSSL 3.1" ++ _ ->
{skip, "LibreSSL 3.1 does not allow server renegotiation"};
_ ->
@@ -3362,6 +3467,17 @@ portable_open_port(Exe, Args) ->
open_port({spawn_executable, AbsPath},
[{args, Args}, stderr_to_stdout]).
+
+portable_cmd("openssl", ["version"]) ->
+ case get(openssl_version) of
+ undefined ->
+ Port = portable_open_port("openssl", ["version"]),
+ Version = collect_port_data(Port),
+ put(openssl_version, Version),
+ Version;
+ Version ->
+ Version
+ end;
portable_cmd(Exe, Args) ->
Port = portable_open_port(Exe, Args),
collect_port_data(Port).
@@ -3383,12 +3499,13 @@ maybe_collect_more_port_data(Port, Acc) ->
Acc
end.
-supports_ssl_tls_version(Version) when Version == sslv2;
- Version == sslv3 ->
+supports_ssl_tls_version(Version, Config)
+ when Version == sslv2;
+ Version == sslv3 ->
case ubuntu_legacy_support() of
true ->
- case portable_cmd("openssl", ["version"]) of
+ case proplists:get_value(openssl_version, Config) of
"OpenSSL 1.0.1" ++ _ ->
Version =/= sslv2;
"OpenSSL 1" ++ _ ->
@@ -3411,7 +3528,7 @@ supports_ssl_tls_version(Version) when Version == sslv2;
false ->
false
end;
-supports_ssl_tls_version(Version) ->
+supports_ssl_tls_version(Version, _) ->
VersionFlag = version_flag(Version),
Exe = "openssl",
Args = ["s_client", VersionFlag],
@@ -3854,13 +3971,14 @@ erlang_ssl_receive_and_assert_negotiated_protocol(Socket, Protocol, Data) ->
end.
check_openssl_npn_support(Config) ->
- HelpText = portable_cmd("openssl", ["s_client --help"]),
- case string:str(HelpText, "nextprotoneg") of
- 0 ->
- {skip, "Openssl not compiled with nextprotoneg support"};
+ case proplists:get_value(openssl_version, Config) of
+ "OpenSSL 1.0" ++ _ ->
+ false;
+ "OpenSSL 1.1" ++ _ ->
+ true;
_ ->
- Config
- end.
+ false
+ end.
new_config(PrivDir, ServerOpts0) ->
CaCertFile = proplists:get_value(cacertfile, ServerOpts0),
@@ -3976,26 +4094,6 @@ openssl_maxfraglen_support() ->
false
end.
-openssl_dtls_maxfraglen_support() ->
- case portable_cmd("openssl", ["version"]) of
- "OpenSSL 0" ++ _ ->
- false;
- "OpenSSL 1.0" ++ _ ->
- false;
- "OpenSSL 1.1.0" ++ _ ->
- false;
- "OpenSSL 1.1.1" ++ _ ->
- false;
- "OpenSSL 1.1" ++ _ ->
- false;
- "OpenSSL 3.0.1" ++ _ ->
- false; %% OpenSSL sends internal error alert
- "OpenSSL" ++ _ ->
- true;
- _ ->
- false
- end.
-
assert_mfl(Socket, undefined) ->
InfoMFL = ssl:connection_information(Socket, [max_fragment_length]),
?LOG("Connection MFL ~p, Expecting: [] ~n", [InfoMFL]),
diff --git a/lib/ssl/test/tls_1_3_record_SUITE.erl b/lib/ssl/test/tls_1_3_record_SUITE.erl
index 0520b70620..75819d0565 100644
--- a/lib/ssl/test/tls_1_3_record_SUITE.erl
+++ b/lib/ssl/test/tls_1_3_record_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -106,9 +106,9 @@ encode_decode(_Config) ->
<<92,24,205,75,244,60,136,212,250,32,214,20,37,3,213,87,61,207,
147,61,168,145,177,118,160,153,33,53,48,108,191,174>>},
sequence_number => 0,server_verify_data => undefined,
- max_early_data_size => 0,
+ pending_early_data_size => 0,
trial_decryption => false,
- early_data_limit => false},
+ early_data_accepted => false},
current_write =>
#{beast_mitigation => one_n_minus_one,
cipher_state =>
diff --git a/lib/ssl/test/tls_1_3_version_SUITE.erl b/lib/ssl/test/tls_1_3_version_SUITE.erl
index 2dc72d2ca3..8a3ff288f7 100644
--- a/lib/ssl/test/tls_1_3_version_SUITE.erl
+++ b/lib/ssl/test/tls_1_3_version_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2019-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2019-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,9 +51,19 @@
tls11_client_tls_server/0,
tls11_client_tls_server/1,
tls12_client_tls_server/0,
- tls12_client_tls_server/1
+ tls12_client_tls_server/1,
+ middle_box_tls13_client/0,
+ middle_box_tls13_client/1,
+ middle_box_tls12_enabled_client/0,
+ middle_box_tls12_enabled_client/1,
+ middle_box_client_tls_v2_session_reused/0,
+ middle_box_client_tls_v2_session_reused/1
]).
+
+%% Test callback
+-export([check_session_id/2]).
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
@@ -77,7 +87,11 @@ tls_1_3_1_2_tests() ->
tls13_client_with_ext_tls12_server,
tls12_client_tls13_server,
tls_client_tls12_server,
- tls12_client_tls_server].
+ tls12_client_tls_server,
+ middle_box_tls13_client,
+ middle_box_tls12_enabled_client,
+ middle_box_client_tls_v2_session_reused
+ ].
legacy_tests() ->
[tls_client_tls10_server,
tls_client_tls11_server,
@@ -263,3 +277,86 @@ tls12_client_tls_server(Config) when is_list(Config) ->
['tlsv1','tlsv1.1', 'tlsv1.2', 'tlsv1.3']} |
ssl_test_lib:ssl_options(server_cert_opts, Config)],
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
+
+
+middle_box_tls13_client() ->
+ [{doc,"Test that a TLS 1.3 client can connect to a 1.3 server with and without middle box compatible mode."}].
+middle_box_tls13_client(Config) when is_list(Config) ->
+ ClientOpts = [{versions,
+ ['tlsv1.3']} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{versions, ['tlsv1.3']} |
+ ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ middlebox_test(true, not_empty, ClientOpts, ServerOpts, Config),
+ middlebox_test(false, empty, ClientOpts, ServerOpts, Config).
+
+middle_box_tls12_enabled_client() ->
+ [{doc,"Test that a TLS 1.2 enabled client can connect to a TLS 1.3 server with and without middle box compatible mode."}].
+middle_box_tls12_enabled_client(Config) when is_list(Config) ->
+ ClientOpts = [{versions, ['tlsv1.2', 'tlsv1.3']} | ssl_test_lib:ssl_options(client_cert_opts, Config)],
+ ServerOpts = [{versions, ['tlsv1.3']} |
+ ssl_test_lib:ssl_options(server_cert_opts, Config)],
+ middlebox_test(true, not_empty, ClientOpts, ServerOpts, Config),
+ middlebox_test(false, empty, ClientOpts, ServerOpts, Config).
+
+middle_box_client_tls_v2_session_reused() ->
+ [{doc, "Test that TLS-1.3 middlebox enabled client can reuse TLS-1.2 session when talking to TLS-1.2 server"}].
+middle_box_client_tls_v2_session_reused(Config) when is_list(Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{versions, ['tlsv1.2']} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {_Client, CSock} = ssl_test_lib:start_client([return_socket, {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options,
+ [{versions, ['tlsv1.2']}, {reuse_sessions, save}| ClientOpts]}]),
+ Server ! listen,
+ {ok,[{session_id, SessionId}, {session_data, SessData}]} = ssl:connection_information(CSock, [session_id, session_data]),
+ {_Client1, CSock1} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options,
+ [{versions, ['tlsv1.3', 'tlsv1.2']},
+ {middlebox_comp_mode, true},
+ {reuse_session, {SessionId, SessData}} | ClientOpts]}]),
+ {ok,[{session_id, SessionId}]} = ssl:connection_information(CSock1, [session_id]).
+
+%%--------------------------------------------------------------------
+%% Internal functions and callbacks -----------------------------------
+%%--------------------------------------------------------------------
+
+middlebox_test(Mode, Expected, ClientOpts, ServerOpts, Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, check_session_id, [Expected]}},
+ {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, check_session_id, [Expected]}},
+ {options,
+ [{middlebox_comp_mode, Mode}| ClientOpts]}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok).
+
+check_session_id(Socket, Expected) ->
+ {ok, [{session_id, SessionId}]} = ssl:connection_information(Socket, [session_id]),
+ case {Expected, SessionId} of
+ {empty, <<>>} ->
+ ok;
+ {not_empty, SessionId} when SessionId =/= <<>> ->
+ ok;
+ _ ->
+ {nok, {{expected, Expected}, {got, SessionId}}}
+ end.
+
+
diff --git a/lib/ssl/test/tls_api_SUITE.erl b/lib/ssl/test/tls_api_SUITE.erl
index 4dd32ab0dc..ccba623861 100644
--- a/lib/ssl/test/tls_api_SUITE.erl
+++ b/lib/ssl/test/tls_api_SUITE.erl
@@ -28,6 +28,7 @@
-include_lib("ssl/src/ssl_api.hrl").
-include_lib("ssl/src/tls_handshake.hrl").
-include_lib("ssl/src/ssl_alert.hrl").
+-include_lib("ssl/src/ssl_cipher.hrl").
%% Common test
-export([all/0,
@@ -45,8 +46,12 @@
tls_upgrade/1,
tls_upgrade_new_opts/0,
tls_upgrade_new_opts/1,
+ tls_upgrade_new_opts_with_sni_fun/0,
+ tls_upgrade_new_opts_with_sni_fun/1,
tls_upgrade_with_timeout/0,
tls_upgrade_with_timeout/1,
+ tls_upgrade_with_client_timeout/0,
+ tls_upgrade_with_client_timeout/1,
tls_downgrade/0,
tls_downgrade/1,
tls_shutdown/0,
@@ -85,6 +90,10 @@
tls_reject_fake_warning_alert_in_initial_hs/1,
tls_app_data_in_initial_hs_state/0,
tls_app_data_in_initial_hs_state/1,
+ tls_13_reject_change_cipher_spec_as_first_msg/0,
+ tls_13_reject_change_cipher_spec_as_first_msg/1,
+ tls_13_middlebox_reject_change_cipher_spec_as_first_msg/0,
+ tls_13_middlebox_reject_change_cipher_spec_as_first_msg/1,
peername/0,
peername/1,
sockname/0,
@@ -133,7 +142,8 @@ all() ->
groups() ->
[
- {'tlsv1.3', [], api_tests() -- [sockname]},
+ {'tlsv1.3', [], (api_tests() ++ [tls_13_reject_change_cipher_spec_as_first_msg,
+ tls_13_middlebox_reject_change_cipher_spec_as_first_msg]) -- [sockname]},
{'tlsv1.2', [], api_tests()},
{'tlsv1.1', [], api_tests()},
{'tlsv1', [], api_tests()}
@@ -143,7 +153,9 @@ api_tests() ->
[
tls_upgrade,
tls_upgrade_new_opts,
+ tls_upgrade_new_opts_with_sni_fun,
tls_upgrade_with_timeout,
+ tls_upgrade_with_client_timeout,
tls_downgrade,
tls_shutdown,
tls_shutdown_write,
@@ -280,6 +292,52 @@ tls_upgrade_new_opts(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+tls_upgrade_new_opts_with_sni_fun() ->
+ [{doc,"Test that you can upgrade an tcp connection to an ssl connection with new versions option provided by sni_fun"}].
+
+tls_upgrade_new_opts_with_sni_fun(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+ Version = ssl_test_lib:protocol_version(Config),
+ NewVersions = new_versions(Version),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, Version), []),
+
+ NewOpts = [{versions, NewVersions},
+ {ciphers, Ciphers},
+ {verify, verify_peer}],
+
+ Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ upgrade_result, []}},
+ {tcp_options,
+ [{active, false} | TcpOpts]},
+ {ssl_options, [{versions, [Version |NewVersions]}, {sni_fun, fun(_SNI) -> ServerOpts ++ NewOpts end}]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_upgrade_client([{node, ClientNode},
+ {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, upgrade_result, []}},
+ {tcp_options, [binary]},
+ {ssl_options, [{verify, verify_peer},
+ {versions, [Version |NewVersions]},
+ {ciphers, Ciphers},
+ {server_name_indication, Hostname} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+
+%%--------------------------------------------------------------------
tls_upgrade_with_timeout() ->
[{doc,"Test handshake/3"}].
@@ -315,6 +373,37 @@ tls_upgrade_with_timeout(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+tls_upgrade_with_client_timeout() ->
+ [{doc,"Test upgrade with connect/3 and a timeout value"}].
+
+tls_upgrade_with_client_timeout(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+
+ Server = ssl_test_lib:start_upgrade_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE,
+ upgrade_result, []}},
+ {tcp_options,
+ [{active, false} | TcpOpts]},
+ {ssl_options, [{verify, verify_peer} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_upgrade_client_error([{node, ClientNode},
+ {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {timeout, 0},
+ {mfa, {?MODULE, upgrade_result, []}},
+ {tcp_options, [binary]},
+ {ssl_options, [{verify, verify_peer},
+ {server_name_indication, Hostname} | ClientOpts]}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p", [self(), Client, Server]),
+ ok = ssl_test_lib:check_result(Client, {error, timeout}),
+ ssl_test_lib:close(Server).
+
%%--------------------------------------------------------------------
tls_downgrade() ->
[{doc,"Test that you can downgarde an ssl connection to an tcp connection"}].
@@ -659,7 +748,7 @@ tls_dont_crash_on_handshake_garbage(Config) ->
% Ensure we receive an alert, not sudden disconnect
case Version of
'tlsv1.3' ->
- ssl_test_lib:check_server_alert(Server, illegal_parameter);
+ ssl_test_lib:check_server_alert(Server, protocol_version);
_ ->
ssl_test_lib:check_server_alert(Server, handshake_failure)
end.
@@ -750,7 +839,7 @@ tls_app_data_in_initial_hs_state() ->
tls_app_data_in_initial_hs_state(Config) when is_list(Config) ->
ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{_ClientNode, ServerNode, _Hostname} = ssl_test_lib:run_where(Config),
- Version = ssl_test_lib:protocol_version(Config, tuple),
+ Version = ssl_test_lib:protocol_version(Config, tuple),
{Major, Minor} = case Version of
{3,4} ->
{3,3};
@@ -763,19 +852,61 @@ tls_app_data_in_initial_hs_state(Config) when is_list(Config) ->
{options, [{versions, [ssl_test_lib:protocol_version(Config)]} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
{ok, Socket} = gen_tcp:connect("localhost", Port, [{active, false}, binary]),
- AppData = <<?BYTE(?APPLICATION_DATA), ?BYTE(Major), ?BYTE(Minor), ?UINT16(3), ?BYTE($F), ?BYTE($O), ?BYTE($O)>>,
+ AppData = case Version of
+ {3, 4} ->
+ <<?BYTE(?APPLICATION_DATA), ?BYTE(3), ?BYTE(3), ?UINT16(4), ?BYTE($F),
+ ?BYTE($O), ?BYTE($O), ?BYTE(?APPLICATION_DATA)>>;
+ _ ->
+ <<?BYTE(?APPLICATION_DATA), ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(3), ?BYTE($F), ?BYTE($O), ?BYTE($O)>>
+ end,
gen_tcp:send(Socket, AppData),
- UnexpectedMsgAlert =
- case Version of
- {_, 4} ->
- <<?BYTE(?ALERT), ?BYTE(Major), ?BYTE(Minor), ?UINT16(2), ?BYTE(?FATAL), ?BYTE(?DECODE_ERROR)>>;
- _ ->
- <<?BYTE(?ALERT), ?BYTE(Major), ?BYTE(Minor), ?UINT16(2), ?BYTE(?FATAL), ?BYTE(?UNEXPECTED_MESSAGE)>>
- end,
+ UnexpectedMsgAlert = <<?BYTE(?ALERT), ?BYTE(Major), ?BYTE(Minor), ?UINT16(2),
+ ?BYTE(?FATAL), ?BYTE(?UNEXPECTED_MESSAGE)>>,
+ {ok, UnexpectedMsgAlert} = gen_tcp:recv(Socket, 7),
+ {error, closed} = gen_tcp:recv(Socket, 0).
+%%--------------------------------------------------------------------
+tls_13_reject_change_cipher_spec_as_first_msg() ->
+ [{doc,"change_cipher_spec messages can be sent in TLS-1.3 middlebox_comp_mode, but can not be sent as first msg"}].
+tls_13_reject_change_cipher_spec_as_first_msg(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_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, [{versions, [ssl_test_lib:protocol_version(Config)]} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {ok, Socket} = gen_tcp:connect("localhost", Port, [{active, false}, binary]),
+ ChangeCipherSpec = <<?BYTE(?CHANGE_CIPHER_SPEC), ?BYTE(3), ?BYTE(3),
+ ?UINT16(1), ?BYTE(?CHANGE_CIPHER_SPEC_PROTO)>>,
+ gen_tcp:send(Socket, ChangeCipherSpec),
+ UnexpectedMsgAlert = <<?BYTE(?ALERT), ?BYTE(3), ?BYTE(3), ?UINT16(2),
+ ?BYTE(?FATAL), ?BYTE(?UNEXPECTED_MESSAGE)>>,
{ok, UnexpectedMsgAlert} = gen_tcp:recv(Socket, 7),
{error, closed} = gen_tcp:recv(Socket, 0).
%%--------------------------------------------------------------------
+tls_13_middlebox_reject_change_cipher_spec_as_first_msg() ->
+ [{doc,"change_cipher_spec messages can be sent in TLS-1.3 middlebox_comp_mode, but can not be sent as first msg"}].
+tls_13_middlebox_reject_change_cipher_spec_as_first_msg(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_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, [{middlebox_comp_mode, false},
+ {versions, [ssl_test_lib:protocol_version(Config)]}
+ | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ {ok, Socket} = gen_tcp:connect("localhost", Port, [{active, false}, binary]),
+ ChangeCipherSpec = <<?BYTE(?CHANGE_CIPHER_SPEC), ?BYTE(3), ?BYTE(3),
+ ?UINT16(1), ?BYTE(?CHANGE_CIPHER_SPEC_PROTO)>>,
+ gen_tcp:send(Socket, ChangeCipherSpec),
+ UnexpectedMsgAlert = <<?BYTE(?ALERT), ?BYTE(3), ?BYTE(3), ?UINT16(2),
+ ?BYTE(?FATAL), ?BYTE(?UNEXPECTED_MESSAGE)>>,
+ {ok, UnexpectedMsgAlert} = gen_tcp:recv(Socket, 7),
+ {error, closed} = gen_tcp:recv(Socket, 0).
+%%--------------------------------------------------------------------
peername() ->
[{doc,"Test API function peername/1"}].
@@ -1304,3 +1435,13 @@ session_info(_) ->
count_children(ChildType, SupRef) ->
proplists:get_value(ChildType, supervisor:count_children(SupRef)).
+
+
+new_versions('tlsv1.3') ->
+ ['tlsv1.2'];
+new_versions('tlsv1.2') ->
+ ['tlsv1.1'];
+new_versions('tlsv1.1') ->
+ ['tlsv1'];
+new_versions('tlsv1') ->
+ ['tlsv1'].
diff --git a/lib/ssl/test/tls_client_ticket_store_SUITE.erl b/lib/ssl/test/tls_client_ticket_store_SUITE.erl
new file mode 100644
index 0000000000..ebc602c4e8
--- /dev/null
+++ b/lib/ssl/test/tls_client_ticket_store_SUITE.erl
@@ -0,0 +1,108 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(tls_client_ticket_store_SUITE).
+-behaviour(ct_suite).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("ssl/src/ssl_internal.hrl").
+-include_lib("ssl/src/tls_handshake_1_3.hrl").
+
+%% Callback functions
+-export([all/0, init_per_testcase/2, end_per_testcase/2]).
+
+%% Testcases
+-export([ticket_obfuscated_age/0,
+ ticket_obfuscated_age/1,
+ ticket_expired/0,
+ ticket_expired/1]).
+
+-define(TICKET_STORE_SIZE, 2).
+-define(LIFETIME, 2). % tickets expire after 2 second
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [ticket_obfuscated_age, ticket_expired].
+
+init_per_testcase(_TestCase, Config) ->
+ {ok, Pid} = tls_client_ticket_store:start_link(
+ ?TICKET_STORE_SIZE, ?LIFETIME),
+ [{server_pid, Pid} | Config].
+
+end_per_testcase(_TestCase, Config) ->
+ Pid = ?config(server_pid, Config),
+ exit(Pid, normal),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+ticket_obfuscated_age() ->
+ [{doc, "Verify the ticket store computes the obfuscated ticket age correctly"}].
+ticket_obfuscated_age(_Config) ->
+ TicketAgeAdd = 2900512354,
+ Ticket =
+ #new_session_ticket{
+ ticket_lifetime = ?LIFETIME,
+ ticket_age_add = TicketAgeAdd,
+ ticket_nonce = <<0,0,0,0,0,0,0,1>>,
+ ticket = <<1, 1, 1, 1, 1, 1, 1, 1>>,
+ extensions = #{early_data => {early_data_indication_nst, 16384}}
+ },
+ CipherSuite = {Cipher, HashAlgo} = {aes_256_gcm, sha384},
+ SNI = "some-test-sni",
+ PSK = <<10, 10, 10, 10>>,
+
+ ok = tls_client_ticket_store:store_ticket(Ticket, CipherSuite, SNI, PSK),
+
+ timer:sleep(100),
+
+ {Key, _} = tls_client_ticket_store:find_ticket(self(), [Cipher], [HashAlgo], SNI, undefined),
+ [#ticket_data{identity = Identity}] = tls_client_ticket_store:get_tickets(self(), [Key]),
+ #psk_identity{obfuscated_ticket_age = ObfAge} = Identity,
+ Age = ObfAge - TicketAgeAdd,
+ ct:log("Ticket age: ~p (obfuscated age: ~p, ticket age add: ~p)~n",
+ [Age, ObfAge, TicketAgeAdd]),
+ true = Age < 1000 andalso Age >= 100.
+
+ticket_expired() ->
+ [{doc, "Verify the ticket store does not return an expired ticket"}].
+ticket_expired(_Config) ->
+ TicketAgeAdd = 1234563451,
+ Ticket =
+ #new_session_ticket{
+ ticket_lifetime = ?LIFETIME,
+ ticket_age_add = TicketAgeAdd,
+ ticket_nonce = <<0,0,0,0,0,0,0,2>>,
+ ticket = <<2, 2, 2, 2, 2, 2, 2, 2>>,
+ extensions = #{early_data => {early_data_indication_nst, 16384}}
+ },
+ CipherSuite = {Cipher, HashAlgo} = {aes_256_gcm, sha384},
+ SNI = "some-test-sni",
+ PSK = <<20, 20, 20, 20>>,
+
+ ok = tls_client_ticket_store:store_ticket(Ticket, CipherSuite, SNI, PSK),
+
+ timer:sleep(?LIFETIME * 1000 + 500),
+
+ {undefined, undefined} = tls_client_ticket_store:find_ticket(
+ self(), [Cipher], [HashAlgo], SNI, undefined).
diff --git a/lib/ssl/test/tls_server_session_ticket_SUITE.erl b/lib/ssl/test/tls_server_session_ticket_SUITE.erl
index 7f45dee083..954afa9fb5 100644
--- a/lib/ssl/test/tls_server_session_ticket_SUITE.erl
+++ b/lib/ssl/test/tls_server_session_ticket_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,8 +27,14 @@
-include_lib("ssl/src/tls_handshake_1_3.hrl").
%% Callback functions
--export([all/0, groups/0, init_per_group/2, end_per_group/2,
- init_per_testcase/2, end_per_testcase/2]).
+-export([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]).
%% Testcases
-export([expired_ticket_test/0,
expired_ticket_test/1,
@@ -58,6 +64,20 @@ groups() ->
{stateless_antireplay, [], [main_test, misc_test]}
].
+init_per_suite(Config0) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ ssl_test_lib:clean_start(),
+ Config0
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
init_per_group(stateless_antireplay, Config) ->
check_environment([{server_session_tickets, stateless},
{anti_replay, {10, 20, 30}}]
@@ -71,15 +91,18 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(_TestCase, Config) ->
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active, false}]),
{ok, Pid} = tls_server_session_ticket:start_link(
- ?config(server_session_tickets, Config), ?LIFETIME,
- ?TICKET_STORE_SIZE, _MaxEarlyDataSize = 100,
+ ListenSocket, ?config(server_session_tickets, Config),
+ ?LIFETIME, ?TICKET_STORE_SIZE, _MaxEarlyDataSize = 100,
?config(anti_replay, Config)),
- [{server_pid, Pid} | Config].
+ [{server_pid, Pid}, {listen_socket, ListenSocket} | Config].
end_per_testcase(_TestCase, Config) ->
Pid = ?config(server_pid, Config),
exit(Pid, normal),
+ ListenSocket = ?config(listen_socket, Config),
+ ok = gen_tcp:close(ListenSocket),
Config.
%%--------------------------------------------------------------------
@@ -94,7 +117,12 @@ main_test(Config) when is_list(Config) ->
% Reach ticket store size limit - force GB tree pruning
SessionTicket = #new_session_ticket{} =
tls_server_session_ticket:new(Pid, ?PRF, ?MASTER_SECRET),
- {HandshakeHist, OferredPsks} = get_handshake_hist(SessionTicket, ?PSK),
+ TicketRecvTime = erlang:system_time(millisecond),
+ %% Sleep more than the ticket lifetime (which is in seconds) in
+ %% milliseconds, to confirm that the client reported age (which is in
+ %% milliseconds) is compared correctly with the lifetime
+ ct:sleep(5 * ?LIFETIME),
+ {HandshakeHist, OferredPsks} = get_handshake_hist(SessionTicket, TicketRecvTime, ?PSK),
AcceptResponse = {ok, {0, ?PSK}},
AcceptResponse = tls_server_session_ticket:use(Pid, OferredPsks, ?PRF,
[iolist_to_binary(HandshakeHist)]),
@@ -132,8 +160,9 @@ expired_ticket_test() ->
expired_ticket_test(Config) when is_list(Config) ->
Pid = ?config(server_pid, Config),
SessionTicket = tls_server_session_ticket:new(Pid, ?PRF, ?MASTER_SECRET),
- {HandshakeHist, OFPSKs} = get_handshake_hist(SessionTicket, ?PSK),
+ TicketRecvTime = erlang:system_time(millisecond),
ct:sleep({seconds, 2 * ?LIFETIME}),
+ {HandshakeHist, OFPSKs} = get_handshake_hist(SessionTicket, TicketRecvTime, ?PSK),
{ok, undefined} = tls_server_session_ticket:use(Pid, OFPSKs, ?PRF,
[iolist_to_binary(HandshakeHist)]),
true = is_process_alive(Pid).
@@ -152,18 +181,18 @@ misc_test(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
%% Helpers -----------------------------------------------------------
%%--------------------------------------------------------------------
-get_handshake_hist(#new_session_ticket{ticket=Ticket} = T, PSK0) ->
- Ids = [#psk_identity{identity = Ticket, obfuscated_ticket_age = 100}],
- SomeBinder = <<159, 187, 86, 6, 55, 20, 149, 208, 3, 221, 78, 126, 254, 101,
- 123, 251, 151, 189, 17, 53>>,
- OfferedPSKs0 = #offered_psks{identities = Ids, binders = [SomeBinder]},
- Hello0 = get_client_hello(OfferedPSKs0),
+get_handshake_hist(#new_session_ticket{} = T, TicketRecvTime, PSK0) ->
M = #{cipher_suite => {nothing, ?PRF},
sni => nothing,
psk => PSK0,
- timestamp => erlang:system_time(seconds),
+ timestamp => TicketRecvTime,
ticket => T},
TicketData = tls_handshake_1_3:get_ticket_data(self(), manual, [M]),
+ [#ticket_data{identity = Identity}] = TicketData,
+ SomeBinder = <<159, 187, 86, 6, 55, 20, 149, 208, 3, 221, 78, 126, 254, 101,
+ 123, 251, 151, 189, 17, 53>>,
+ OfferedPSKs0 = #offered_psks{identities = [Identity], binders = [SomeBinder]},
+ Hello0 = get_client_hello(OfferedPSKs0),
Hello1 = tls_handshake_1_3:maybe_add_binders(Hello0, TicketData, ?VERSION),
PSK1 = maps:get(pre_shared_key, Hello1#client_hello.extensions),
OfferedPSKs1 = PSK1#pre_shared_key_client_hello.offered_psks,
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index bdc7ce4739..7b821e2bc8 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 10.7.3
+SSL_VSN = 10.9
diff --git a/lib/stdlib/Makefile b/lib/stdlib/Makefile
index 45ca3f3b6a..f1db3c77e3 100644
--- a/lib/stdlib/Makefile
+++ b/lib/stdlib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,5 +37,14 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=compiler crypto
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
+
+# Enable feature maybe_expr in runtime when running tests.
+# This is very non local and somewhat ugly.
+.PHONY: test
+test:
+ $(MAKE) TEST_NEEDS_RELEASE=$(TEST_NEEDS_RELEASE) \
+ ERL_ARGS="-enable-feature maybe_expr $(ERL_ARGS)" \
+ -f $(ERL_TOP)/make/app_targets.mk $@
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 8bbf5b3800..8cd2ceb53c 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -48,6 +48,7 @@ XML_REF3_FILES = \
erl_error.xmlsrc \
erl_eval.xml \
erl_expand_records.xml \
+ erl_features.xml \
erl_id_trans.xml \
erl_internal.xml \
erl_lint.xml \
@@ -74,6 +75,7 @@ XML_REF3_FILES = \
ms_transform.xml \
orddict.xml \
ordsets.xml \
+ peer.xml \
pool.xml \
proc_lib.xml \
proplists.xml \
diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml
index 7764831eb5..bfe97c7f89 100644
--- a/lib/stdlib/doc/src/array.xml
+++ b/lib/stdlib/doc/src/array.xml
@@ -300,7 +300,7 @@ A3 = array:fix(A2).</pre>
<fsummary>Create a new array according to the specified options.
</fsummary>
<desc>
- <p>Creates a new array according to the specified otions. By default,
+ <p>Creates a new array according to the specified options. By default,
the array is extendible and has initial size zero. Array indices
start at <c>0</c>.</p>
<p><c><anno>Options</anno></c> is a single term or a list of terms,
diff --git a/lib/stdlib/doc/src/beam_lib.xml b/lib/stdlib/doc/src/beam_lib.xml
index bc550c1494..e743741ea8 100644
--- a/lib/stdlib/doc/src/beam_lib.xml
+++ b/lib/stdlib/doc/src/beam_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2021</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -138,8 +138,11 @@ io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).</code>
<section>
<title>.erlang.crypt</title>
<p><c>beam_lib</c> searches for <c>.erlang.crypt</c> in the current
- directory and then the home directory for the current user. If
- the file is found and contains a key, <c>beam_lib</c>
+ directory, then the <seeerl marker="erts:init#home">
+ user&apos;s home directory</seeerl> and then
+ <seeerl marker="stdlib:filename#user_config">
+ <c>filename:basedir(user_config, "erlang")</c></seeerl>.
+ If the file is found and contains a key, <c>beam_lib</c>
implicitly creates a crypto key fun and registers it.</p>
<p>File <c>.erlang.crypt</c> is to contain a single list of tuples:</p>
@@ -459,11 +462,11 @@ CryptoKeyFun(clear) -> term()</code>
<func>
<name name="strip" arity="1" since=""/>
- <fsummary>Remove chunks not needed by the loader from a BEAM file.
+ <fsummary>Remove chunks not used by the loader from a BEAM file.
</fsummary>
<desc>
<p>Removes all chunks from a BEAM
- file except those needed by the loader. In particular,
+ file except those used by the loader. In particular,
the debug information (chunk <c>debug_info</c> and <c>abstract_code</c>)
is removed.</p>
</desc>
@@ -471,23 +474,23 @@ CryptoKeyFun(clear) -> term()</code>
<func>
<name name="strip" arity="2" since="OTP 22.0"/>
- <fsummary>Remove chunks not needed by the loader from a BEAM file.
+ <fsummary>Remove chunks not used by the loader from a BEAM file.
</fsummary>
<desc>
- <p>Removes all chunks from a BEAM
- file except those needed by the loader or passed in. In particular,
- the debug information (chunk <c>debug_info</c> and <c>abstract_code</c>)
- is removed.</p>
+ <p>Removes all chunks from a BEAM file except those used by
+ the loader or mentioned in <c><anno>AdditionalChunks</anno></c>. In
+ particular, the debug information (chunk <c>debug_info</c> and
+ <c>abstract_code</c>) is removed.</p>
</desc>
</func>
<func>
<name name="strip_files" arity="1" since=""/>
- <fsummary>Removes chunks not needed by the loader from BEAM files.
+ <fsummary>Removes chunks not used by the loader from BEAM files.
</fsummary>
<desc>
<p>Removes all chunks except
- those needed by the loader from BEAM files. In particular,
+ those used by the loader from BEAM files. In particular,
the debug information (chunk <c>debug_info</c> and <c>abstract_code</c>)
is removed. The returned list contains one element for each
specified filename, in the same order as in <c>Files</c>.</p>
@@ -496,24 +499,25 @@ CryptoKeyFun(clear) -> term()</code>
<func>
<name name="strip_files" arity="2" since="OTP 22.0"/>
- <fsummary>Removes chunks not needed by the loader from BEAM files.
+ <fsummary>Removes chunks not used by the loader from BEAM files.
</fsummary>
<desc>
- <p>Removes all chunks except
- those needed by the loader or passed in from BEAM files. In particular,
- the debug information (chunk <c>debug_info</c> and <c>abstract_code</c>)
- is removed. The returned list contains one element for each
- specified filename, in the same order as in <c>Files</c>.</p>
+ <p>Removes all chunks except those used by the loader or
+ mentioned in <c><anno>AdditionalChunks</anno></c>. In
+ particular, the debug information (chunk <c>debug_info</c> and
+ <c>abstract_code</c>) is removed. The returned list contains
+ one element for each specified filename, in the same order as
+ in <c>Files</c>.</p>
</desc>
</func>
<func>
<name name="strip_release" arity="1" since=""/>
- <fsummary>Remove chunks not needed by the loader from all BEAM files of
+ <fsummary>Remove chunks not used by the loader from all BEAM files of
a release.</fsummary>
<desc>
<p>Removes all chunks
- except those needed by the loader from the BEAM files of a
+ except those used by the loader from the BEAM files of a
release. <c><anno>Dir</anno></c> is to be the installation root
directory. For example, the current OTP release can be
stripped with the call
@@ -526,12 +530,12 @@ CryptoKeyFun(clear) -> term()</code>
<fsummary>Remove chunks not needed by the loader from all BEAM files of
a release.</fsummary>
<desc>
- <p>Removes all chunks
- except those needed by the loader or passed in from the BEAM files of a
- release. <c><anno>Dir</anno></c> is to be the installation root
- directory. For example, the current OTP release can be
- stripped with the call
- <c>beam_lib:strip_release(code:root_dir())</c>.</p>
+ <p>Removes all chunks except those used by the loader or
+ mentioned in <c><anno>AdditionalChunks</anno></c>.
+ <c><anno>Dir</anno></c> is to be the installation
+ root directory. For example, the current OTP release can be
+ stripped with the call
+ <c>beam_lib:strip_release(code:root_dir())</c>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml
index 9d61999043..343c384cb6 100644
--- a/lib/stdlib/doc/src/c.xml
+++ b/lib/stdlib/doc/src/c.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -198,6 +198,35 @@
</func>
<func>
+ <name name="hcb" arity="1" since="OTP 23.0"/>
+ <fsummary>Module help information</fsummary>
+ <type name="h_return"/>
+ <desc>
+ <p>Print the callback documentation for <c>Module</c></p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="hcb" arity="2" since="OTP 23.0"/>
+ <fsummary>Function help information</fsummary>
+ <type name="h_return"/>
+ <type name="hcb_return"/>
+ <desc>
+ <p>Print the callback documentation for all <c>Module:Callback</c>s (regardless of arity).</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="hcb" arity="3" since="OTP 23.0"/>
+ <fsummary>Function help information</fsummary>
+ <type name="h_return"/>
+ <type name="hcb_return"/>
+ <desc>
+ <p>Print the callback documentation for <c>Module:Callback/Arity</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="ht" arity="1" since="OTP 23.0"/>
<fsummary>Type help information</fsummary>
<type name="h_return"/>
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 213bca365d..228c0808d3 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -124,6 +124,13 @@
<datatype>
<name name="weeknum"/>
</datatype>
+ <datatype>
+ <name name="rfc3339_time_unit"/>
+ <desc><note><p>
+ The <c>native</c> time unit was added to <c>rfc3339_time_unit()</c>
+ in OTP 25.0.</p></note>
+ </desc>
+ </datatype>
</datatypes>
<funcs>
@@ -321,11 +328,11 @@
<name name="rfc3339_to_system_time" arity="2" since="OTP 21.0"/>
<fsummary>Convert from RFC 3339 timestamp to system time.</fsummary>
<type name="rfc3339_string"/>
- <type name="rfc3339_time_unit"/>
<desc>
<p>Converts an RFC 3339 timestamp into system time. The data format
of RFC 3339 timestamps is described by
- <url href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</url>.</p>
+ <url href="https://www.ietf.org/rfc/rfc3339.txt">RFC 3339</url>.
+ Starting from OTP 25.1, the minutes part of the time zone is optional.</p>
<p>Valid option:</p>
<taglist>
<tag><c>{unit, Unit}</c></tag>
@@ -378,7 +385,6 @@
<fsummary>Convert from system to RFC 3339 timestamp.</fsummary>
<type name="offset"/>
<type name="rfc3339_string"/>
- <type name="rfc3339_time_unit"/>
<desc>
<p>Converts a system time into an RFC 3339 timestamp. The data format
of RFC 3339 timestamps is described by
@@ -401,12 +407,13 @@
<tag><c>{unit, Unit}</c></tag>
<item><p>The time unit of <c><anno>Time</anno></c>. The
default is <c>second</c>. If some other unit is given
- (<c>millisecond</c>, <c>microsecond</c>, or
- <c>nanosecond</c>), the formatted string includes a
+ (<c>millisecond</c>, <c>microsecond</c>, <c>nanosecond</c>, or
+ <c>native</c>), the formatted string includes a
fraction of a second. The number of fractional second
digits is three, six, or nine depending on what time unit
- is chosen. Notice that trailing zeros are not removed from
- the fraction.
+ is chosen. For <c>native</c> three fractional digits are
+ included. Notice that trailing zeros are not removed from the
+ fraction.
</p>
</item>
</taglist>
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index 6cd715c55c..11130b0065 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -131,6 +131,10 @@
attributes inserted during preprocessing, you can do with
<c>{source_name, <anno>SourceName</anno>}</c>. If unset it will
default to the name of the opened file.</p>
+ <p>Setting <c>{deterministic, <anno>Enabled</anno>}</c> will
+ additionally reduce the file name of the implicit -file()
+ attributes inserted during preprocessing to only the basename
+ of the path.</p>
<p>If <c>extra</c> is specified in
<c><anno>Options</anno></c>, the return value is
<c>{ok, <anno>Epp</anno>, <anno>Extra</anno>}</c> instead
diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml
index 41566d9aec..45d9a150ea 100644
--- a/lib/stdlib/doc/src/erl_eval.xml
+++ b/lib/stdlib/doc/src/erl_eval.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -273,10 +273,13 @@ Func(Name, Arguments, Bindings)</code>
<taglist>
<tag><c>{value,Func}</c></tag>
<item>
- <p>This defines a non-local function handler that is called with:</p>
- <code type="none">
-Func(FuncSpec, Arguments)</code>
- <p><c>FuncSpec</c> is the name of the function on the form
+ <p>This defines a non-local function handler. The function
+ may be called with two arguments:</p>
+ <code type="none">Func(FuncSpec, Arguments)</code>
+ <p>or three arguments:</p>
+ <code type="none">Func(Anno, FuncSpec, Arguments)</code>
+ <p><c>Anno</c> is the <c>erl_anno:anno()</c> of the node,
+ <c>FuncSpec</c> is the name of the function on the form
<c>{Module,Function}</c> or a fun, and <c>Arguments</c> is a
list of the <em>evaluated</em> arguments. The function
handler returns the value of the function. To
diff --git a/lib/stdlib/doc/src/erl_features.xml b/lib/stdlib/doc/src/erl_features.xml
new file mode 100644
index 0000000000..cf85b4ccd6
--- /dev/null
+++ b/lib/stdlib/doc/src/erl_features.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2022</year><year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>erl_features</title>
+ <prepared>Cons T &Aring;hs</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved></approved>
+ <checked></checked>
+ <date>2022-05-02</date>
+ <rev>B</rev>
+ <file>erl_features.xml</file>
+ </header>
+ <module since="OTP 25.0">erl_features</module>
+ <modulesummary>Feature support.</modulesummary>
+ <description>
+ <p>This module contains functions for supporting features that can
+ be enabled/disabled in Erlang. It should be considered as mostly
+ for internal use, although there are some functions that might be
+ useful when writing tools.
+ <marker id="erl_features"/>
+ </p>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="feature"></name>
+ </datatype>
+ <datatype>
+ <name name="release"></name>
+ </datatype>
+ <datatype>
+ <name name="status"></name>
+ </datatype>
+ <datatype>
+ <name name="type"></name>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name name="all" arity="0" since="OTP 25.0"/>
+ <fsummary>Return all known features.</fsummary>
+ <desc>
+ <p>Return a list of all known features. This list will
+ include features that have been removed (status
+ <c>rejected</c>) and features that are no longer configurable
+ (status <c>permanent</c>).</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="configurable" arity="0" since="OTP 25.1"/>
+ <fsummary>Return all configurable features.</fsummary>
+ <desc>
+ <p>Return a list of all configurable features, that is, features
+ with status <c>experimental</c> or <c>approved</c>. These are
+ the features that can be enabled or disabled.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="info" arity="1" since="OTP 25.0"/>
+ <fsummary>Return information about the given feature.</fsummary>
+ <desc>
+ <p>Return a map containing information about the given feature.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="enabled" arity="0" since="OTP 25.0"/>
+ <fsummary>Return list of currently enabled features.</fsummary>
+ <desc>
+ <p>Return a list of the features that are currently enabled.
+ Note that the set of enabled is set during startup and can
+ then not be changed.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="used" arity="1" since="OTP 25.0"/>
+ <fsummary>Return features used by a module or beam file.</fsummary>
+ <desc>
+ <p>Return the list of features enabled when compiling the
+ module. The module need not be loaded, but is found if it
+ exists in the loadpath. If not all features used by the
+ module are enabled in the runtime, loading the module is not
+ allowed.</p>
+ </desc>
+ </func>
+ </funcs>
+
+</erlref>
diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml
index 79b85eb06a..7a05067443 100644
--- a/lib/stdlib/doc/src/erl_pp.xml
+++ b/lib/stdlib/doc/src/erl_pp.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2021</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -45,6 +45,14 @@
<p>All functions can have an optional argument, which specifies a hook
that is called if an attempt is made to print an unknown form.</p>
+
+ <p>Note that if the functions in this module are used to convert
+ abstract code back to Erlang source code, the enclosing function
+ should first be processed by <seemfa
+ marker="#legalize_vars/1"><c>legalize_vars/1</c></seemfa> in order
+ to ensure that the output is semantically equivalent to the
+ abstract code.</p>
+
</description>
<datatypes>
@@ -146,6 +154,29 @@
but only for the guard test <c><anno>Guard</anno></c>.</p>
</desc>
</func>
+
+ <func>
+ <name name="legalize_vars" arity="1" since="OTP 25.0"/>
+ <fsummary>Ensure all variable names are valid.</fsummary>
+ <desc>
+ <p>The Erlang compiler will, when expanding records to tuples,
+ introduce new variables in the abstract representation. As the
+ expansion is done on the abstract representation, the compiler
+ can safely name the new variables with names that are not
+ syntactically valid in Erlang source code (the name starts
+ with a lowercase letter), thus ensuring the uniqueness of the
+ new names.</p>
+
+ <p>The above strategy leads to problems if a user wants to
+ convert the abstract representation, using the functions of
+ this module back to Erlang source code. Typically, pattern
+ variables are output as atoms thus changing the sematics of
+ the program. To solve this problem <c>legalize_vars/1</c>,
+ when run on the abstract representation of a function, will
+ return an equivalent function where all variables will have
+ syntactically valid names.</p>
+ </desc>
+ </func>
</funcs>
<section>
diff --git a/lib/stdlib/doc/src/erl_scan.xml b/lib/stdlib/doc/src/erl_scan.xml
index 4cfad284e7..960ff9d019 100644
--- a/lib/stdlib/doc/src/erl_scan.xml
+++ b/lib/stdlib/doc/src/erl_scan.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -70,6 +70,9 @@
<datatype>
<name name="tokens_result"></name>
</datatype>
+ <datatype>
+ <name name="text_fun"></name>
+ </datatype>
</datatypes>
<funcs>
@@ -220,9 +223,19 @@
<tag><c>return</c></tag>
<item><p>Short for <c>[return_comments, return_white_spaces]</c>.</p>
</item>
- <tag><c>text</c></tag>
+ <tag><marker id="text"/><c>text</c></tag>
<item><p>Include the token text in the token annotation. The
- text is the part of the input corresponding to the token.</p>
+ text is the part of the input corresponding to the token.
+ See also <seeerl marker="#text_fun"><c>text_fun</c></seeerl>.</p>
+ </item>
+ <tag><marker id="text_fun"/><c>{text_fun, text_fun()}</c></tag>
+ <item><p>A callback function used to determine whether the
+ full text for the token shall be included in the token
+ annotation. Arguments of the function are the category of
+ the token and the full token string. This is only used when
+ <seeerl marker="#text"><c>text</c></seeerl> is not present.
+ If neither are present the text will not be saved in the
+ token annotation.</p>
</item>
</taglist>
</desc>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 8f4c013145..ce116c50be 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>2021</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,7 +48,26 @@
A <c>set</c> or <c>ordered_set</c> table can only have one object
associated with each key. A <c>bag</c> or <c>duplicate_bag</c> table can
have many objects associated with each key.</p>
-
+ <p>
+ Insert and lookup times in tables of type <c>set</c> are constant,
+ regardless of the table size. For table types <c>bag</c> and
+ <c>duplicate_bag</c> time is proportional to the number of objects with the
+ same key. Even seemingly unrelated keys may inflict linear search to be
+ skipped past while looking for the key of interest (due to hash collision).
+ </p>
+ <warning>
+ <p>
+ For tables of type <c>bag</c> and <c>duplicate_bag</c>, avoid inserting
+ an extensive amount of objects with the same key. It will hurt insert and
+ lookup performance as well as real time characteristics of the runtime
+ environment (hash bucket linear search do not yield).
+ </p>
+ </warning>
+ <p>
+ The <c>ordered_set</c> table type uses a binary search tree. Insert and
+ lookup times are proportional to the logarithm of the number of objects in
+ the table.
+ </p>
<marker id="max_ets_tables"></marker>
<note>
<p>
@@ -283,7 +302,7 @@ true
<datatypes>
<datatype>
- <name name="access"/>
+ <name name="table_access"/>
</datatype>
<datatype>
<name>continuation()</name>
@@ -297,17 +316,17 @@ true
</datatype>
<datatype>
<name name="match_spec"/>
- <desc><p>A match specification, see above.</p></desc>
+ <desc><p>A match specification, see <seeerl marker="#match_spec">Match Specifications</seeerl>.</p></desc>
</datatype>
<datatype>
- <name name="comp_match_spec"/>
+ <name name="compiled_match_spec"/>
<desc><p>A compiled match specification.</p></desc>
</datatype>
<datatype>
<name name="match_pattern"/>
</datatype>
<datatype>
- <name name="tab"/>
+ <name name="table"/>
</datatype>
<datatype>
<name name="tid"/>
@@ -315,7 +334,7 @@ true
<seemfa marker="#new/2"><c>new/2</c></seemfa>.</p></desc>
</datatype>
<datatype>
- <name name="type"/>
+ <name name="table_type"/>
</datatype>
</datatypes>
@@ -339,7 +358,7 @@ true
<name name="delete" arity="1" since=""/>
<fsummary>Delete an entire ETS table.</fsummary>
<desc>
- <p>Deletes the entire table <c><anno>Tab</anno></c>.</p>
+ <p>Deletes the entire table <c><anno>Table</anno></c>.</p>
</desc>
</func>
@@ -349,7 +368,8 @@ true
table.</fsummary>
<desc>
<p>Deletes all objects with key <c><anno>Key</anno></c> from table
- <c><anno>Tab</anno></c>.</p>
+ <c><anno>Table</anno></c>. This function succeeds even if
+ no objects with key <c><anno>Key</anno></c> exist.</p>
</desc>
</func>
@@ -357,7 +377,7 @@ true
<name name="delete_all_objects" arity="1" since=""/>
<fsummary>Delete all objects in an ETS table.</fsummary>
<desc>
- <p>Delete all objects in the ETS table <c><anno>Tab</anno></c>.
+ <p>Delete all objects in the ETS table <c><anno>Table</anno></c>.
The operation is guaranteed to be
<seeerl marker="#concurrency">atomic and isolated</seeerl>.</p>
</desc>
@@ -382,7 +402,7 @@ true
<p>Reads a file produced by <seemfa marker="#tab2file/2">
<c>tab2file/2</c></seemfa> or
<seemfa marker="#tab2file/3"><c>tab2file/3</c></seemfa> and
- creates the corresponding table <c><anno>Tab</anno></c>.</p>
+ creates the corresponding table <c><anno>Table</anno></c>.</p>
<p>Equivalent to <c>file2tab(<anno>Filename</anno>, [])</c>.</p>
</desc>
</func>
@@ -394,7 +414,7 @@ true
<p>Reads a file produced by <seemfa marker="#tab2file/2">
<c>tab2file/2</c></seemfa> or <seemfa marker="#tab2file/3">
<c>tab2file/3</c></seemfa> and creates the
- corresponding table <c><anno>Tab</anno></c>.</p>
+ corresponding table <c><anno>Table</anno></c>.</p>
<p>The only supported option is <c>{verify,boolean()}</c>.
If verification is turned on (by specifying <c>{verify,true}</c>),
the function uses whatever information is present in the file to
@@ -424,7 +444,7 @@ true
<fsummary>Return the first key in an ETS table.</fsummary>
<desc>
<p>Returns the first key <c><anno>Key</anno></c> in table
- <c><anno>Tab</anno></c>. For an <c>ordered_set</c> table, the first
+ <c><anno>Table</anno></c>. For an <c>ordered_set</c> table, the first
key in Erlang term order is returned. For other
table types, the first key according to the internal
order of the table is returned. If the table is empty,
@@ -554,8 +574,8 @@ Error: fun containing local Erlang function calls
<fsummary>Change owner of a table.</fsummary>
<desc>
<p>Make process <c><anno>Pid</anno></c> the new owner of table
- <c><anno>Tab</anno></c>. If successful, message
- <c>{'ETS-TRANSFER',<anno>Tab</anno>,FromPid,<anno>GiftData</anno>}</c>
+ <c><anno>Table</anno></c>. If successful, message
+ <c>{'ETS-TRANSFER',<anno>Table</anno>,FromPid,<anno>GiftData</anno>}</c>
is sent to the new owner.</p>
<p>The process <c><anno>Pid</anno></c> must be alive, local, and not
already the owner of the table.
@@ -580,7 +600,7 @@ Error: fun containing local Erlang function calls
<name name="i" arity="1" since=""/>
<fsummary>Browse an ETS table on a terminal.</fsummary>
<desc>
- <p>Browses table <c><anno>Tab</anno></c> on a terminal.</p>
+ <p>Browses table <c><anno>Table</anno></c> on a terminal.</p>
</desc>
</func>
@@ -588,10 +608,10 @@ Error: fun containing local Erlang function calls
<name name="info" arity="1" since=""/>
<fsummary>Return information about an <c>table</c>.</fsummary>
<desc>
- <p>Returns information about table <c><anno>Tab</anno></c> as a list of
- tuples. If <c><anno>Tab</anno></c> has the correct type
+ <p>Returns information about table <c><anno>Table</anno></c> as a list of
+ tuples. If <c><anno>Table</anno></c> has the correct type
for a table identifier, but does not refer to an existing ETS
- table, <c>undefined</c> is returned. If <c><anno>Tab</anno></c> is
+ table, <c>undefined</c> is returned. If <c><anno>Table</anno></c> is
not of the correct type, a <c>badarg</c> exception is raised.</p>
<taglist>
<tag><c>{compressed, boolean()}</c></tag>
@@ -616,7 +636,7 @@ Error: fun containing local Erlang function calls
<item>
<p>The key position.</p>
</item>
- <tag><c>{memory, integer() >= 0</c></tag>
+ <tag><c>{memory, integer() >= 0}</c></tag>
<item>
<p>The number of words allocated to the table.</p>
</item>
@@ -637,16 +657,16 @@ Error: fun containing local Erlang function calls
<item>
<p>The pid of the owner of the table.</p>
</item>
- <tag><c>{protection,</c> <seetype marker="#access">
+ <tag><c>{protection,</c> <seetype marker="#table_access">
<c>access()</c></seetype><c>}</c></tag>
<item>
<p>The table access rights.</p>
</item>
- <tag><c>{size, integer() >= 0</c></tag>
+ <tag><c>{size, integer() >= 0}</c></tag>
<item>
<p>The number of objects inserted in the table.</p>
</item>
- <tag><c>{type,</c> <seetype marker="#type">
+ <tag><c>{type,</c> <seetype marker="#table_type">
<c>type()</c></seetype><c>}</c></tag>
<item>
<p>The table type.</p>
@@ -656,9 +676,9 @@ Error: fun containing local Erlang function calls
<p>Indicates whether the table uses <c>read_concurrency</c> or
not.</p>
</item>
- <tag><c>{write_concurrency, boolean()}</c></tag>
+ <tag><c>{write_concurrency, WriteConcurrencyAlternative}</c></tag>
<item>
- <p>Indicates whether the table uses <c>write_concurrency</c>.</p>
+ <p>Indicates which <c>write_concurrency</c> option the table uses.</p>
</item>
</taglist>
<note><p>The execution time of this function is affected by
@@ -677,9 +697,9 @@ Error: fun containing local Erlang function calls
an ETS table.</fsummary>
<desc>
<p>Returns the information associated with <c>Item</c> for table
- <c><anno>Tab</anno></c>, or returns <c>undefined</c> if <c>Tab</c>
+ <c><anno>Table</anno></c>, or returns <c>undefined</c> if <c>Table</c>
does not refer an existing ETS table. If
- <c><anno>Tab</anno></c> is
+ <c><anno>Table</anno></c> is
not of the correct type, or if <c><anno>Item</anno></c> is not
one of the allowed values, a <c>badarg</c> exception is raised.</p>
<p>In addition to the <c>{<anno>Item</anno>,<anno>Value</anno>}</c>
@@ -769,7 +789,7 @@ Error: fun containing local Erlang function calls
<name name="init_table" arity="2" since=""/>
<fsummary>Replace all objects of an ETS table.</fsummary>
<desc>
- <p>Replaces the existing objects of table <c><anno>Tab</anno></c> with
+ <p>Replaces the existing objects of table <c><anno>Table</anno></c> with
objects created by calling the input function
<c><anno>InitFun</anno></c>,
see below. This function is provided for compatibility with
@@ -801,7 +821,7 @@ Error: fun containing local Erlang function calls
<desc>
<p>Inserts the object or all of the objects in list
<c><anno>ObjectOrObjects</anno></c> into table
- <c><anno>Tab</anno></c>.</p>
+ <c><anno>Table</anno></c>.</p>
<list type="bulleted">
<item>
<p>If the table type is <c>set</c> and the key of the inserted
@@ -814,6 +834,12 @@ Error: fun containing local Erlang function calls
in the table, the old object is replaced.</p>
</item>
<item>
+ <p>
+ If the table type is <c>bag</c> and the object <em>matches</em>
+ any whole object in the table, the object is not inserted.
+ </p>
+ </item>
+ <item>
<p>If the list contains more than one object with
<em>matching</em> keys and the table type is <c>set</c>, one is
inserted, which one is not defined.
@@ -824,6 +850,27 @@ Error: fun containing local Erlang function calls
<p>The entire operation is guaranteed to be
<seeerl marker="#concurrency">atomic and isolated</seeerl>,
even when a list of objects is inserted.</p>
+ <marker id="insert_list_order"></marker>
+ <p>
+ For <c>bag</c> and <c>duplicate_bag</c>, objects in the list with
+ identical keys will be inserted in list order (from head to tail). That
+ is, a subsequent call to <seemfa marker="#lookup/2"><c>lookup(T,Key)</c></seemfa>
+ will return them in that inserted order.
+ </p>
+ <note>
+ <p>
+ For <c>bag</c> the insertion order of indentical keys described above was
+ accidentally reverted in OTP 23.0 and later fixed in OTP 25.3. That
+ is, from OTP 23.0 up until OTP 25.3 the objects in a list are
+ inserted in reverse order (from tail to head).
+ </p>
+ <p>
+ For <c>duplicate_bag</c> the same faulty reverse insertion exist
+ from OTP 23.0 until OTP 25.3. However, it is unpredictable and may
+ or may not happen. A longer list will increase the probabiliy of the
+ insertion being done in reverse.
+ </p>
+ </note>
</desc>
</func>
@@ -853,7 +900,7 @@ Error: fun containing local Erlang function calls
<desc>
<p>Checks if a term represent a valid compiled
<seeerl marker="#match_spec">match specification</seeerl>.
- A compiled match specifications is only valid on the Erlang node where
+ A compiled match specification is only valid on the Erlang node where
it was compiled by calling <seemfa marker="#match_spec_compile/1">
<c>match_spec_compile/1</c></seemfa>.</p>
<note>
@@ -880,7 +927,7 @@ Error: fun containing local Erlang function calls
<c>ordered_set</c>.</fsummary>
<desc>
<p>Returns the last key <c><anno>Key</anno></c> according to Erlang
- term order in table <c>Tab</c> of type <c>ordered_set</c>. For
+ term order in table <c>Table</c> of type <c>ordered_set</c>. For
other table types, the function is synonymous to
<seemfa marker="#first/1"><c>first/1</c></seemfa>.
If the table is empty, <c>'$end_of_table'</c> is returned.</p>
@@ -895,7 +942,7 @@ Error: fun containing local Erlang function calls
</fsummary>
<desc>
<p>Returns a list of all objects with key <c><anno>Key</anno></c> in
- table <c><anno>Tab</anno></c>.</p>
+ table <c><anno>Table</anno></c>.</p>
<list type="bulleted">
<item>
<p>For tables of type <c>set</c>, <c>bag</c>, or
@@ -918,14 +965,11 @@ Error: fun containing local Erlang function calls
element, as there cannot be more than one object with the same
key. For tables of type <c>bag</c> or <c>duplicate_bag</c>, the
function returns a list of arbitrary length.</p>
- <p>Notice that the time order of object insertions is preserved;
+ <p>Notice that the sequential order of object insertions is preserved;
the first object inserted with the specified key is the first
- in the resulting list, and so on.</p>
- <p>Insert and lookup times in tables of type <c>set</c>,
- <c>bag</c>, and <c>duplicate_bag</c> are constant, regardless
- of the table size. For the <c>ordered_set</c>
- datatype, time is proportional to the (binary) logarithm of
- the number of objects.</p>
+ in the resulting list, and so on. See also the note about
+ <seeerl marker="#insert_list_order">list insertion order</seeerl>.
+ </p>
</desc>
</func>
@@ -934,7 +978,7 @@ Error: fun containing local Erlang function calls
<fsummary>Return the <c>Pos</c>:th element of all objects with a
specified key in an ETS table.</fsummary>
<desc>
- <p>For a table <c><anno>Tab</anno></c> of type <c>set</c> or
+ <p>For a table <c><anno>Table</anno></c> of type <c>set</c> or
<c>ordered_set</c>, the function returns the
<c><anno>Pos</anno></c>:th
element of the object with key <c><anno>Key</anno></c>.</p>
@@ -943,6 +987,8 @@ Error: fun containing local Erlang function calls
element of every object with key <c><anno>Key</anno></c>.</p>
<p>If no object with key <c><anno>Key</anno></c> exists, the
function exits with reason <c>badarg</c>.</p>
+ <p>If <c><anno>Pos</anno></c> is larger than the size of the tuple,
+ the function exits with reason <c>badarg</c>.</p>
<p>The difference between <c>set</c>, <c>bag</c>, and
<c>duplicate_bag</c> on one hand, and <c>ordered_set</c> on
the other, regarding the fact that <c>ordered_set</c>
@@ -971,7 +1017,7 @@ Error: fun containing local Erlang function calls
<fsummary>Match the objects in an ETS table against a pattern.
</fsummary>
<desc>
- <p>Matches the objects in table <c><anno>Tab</anno></c> against
+ <p>Matches the objects in table <c><anno>Table</anno></c> against
pattern <c><anno>Pattern</anno></c>.</p>
<p>A pattern is a term that can contain:</p>
<list type="bulleted">
@@ -1026,7 +1072,7 @@ Error: fun containing local Erlang function calls
ETS table.</fsummary>
<desc>
<p>Deletes all objects that match pattern <c><anno>Pattern</anno></c>
- from table <c><anno>Tab</anno></c>. For a description of patterns,
+ from table <c><anno>Table</anno></c>. For a description of patterns,
see <seemfa marker="#match/2"><c>match/2</c></seemfa>.</p>
</desc>
</func>
@@ -1051,7 +1097,7 @@ Error: fun containing local Erlang function calls
<fsummary>Match the objects in an ETS table against a pattern.
</fsummary>
<desc>
- <p>Matches the objects in table <c><anno>Tab</anno></c> against
+ <p>Matches the objects in table <c><anno>Table</anno></c> against
pattern <c><anno>Pattern</anno></c>. For a description of patterns,
see <seemfa marker="#match/2"><c>match/2</c></seemfa>.
The function returns a list of all objects that
@@ -1258,17 +1304,24 @@ ets:select(Table, MatchSpec),</code>
when the owner terminates.</p>
<marker id="new_2_write_concurrency"></marker>
</item>
- <tag><c>{write_concurrency,boolean()}</c></tag>
+ <tag><c>{write_concurrency,WriteConcurrencyAlternative}</c></tag>
<item>
<p>Performance tuning. Defaults to <c>false</c>, in which case an
operation that
mutates (writes to) the table obtains exclusive access,
blocking any concurrent access of the same table until finished.
- If set to <c>true</c>, the table is optimized to concurrent
+ If set to <c>true</c>, the table is optimized for concurrent
write access. Different objects of the same table can be mutated
(and read) by concurrent processes. This is achieved to some
degree at the expense of memory consumption and the performance
of sequential access and concurrent reading.</p>
+ <p>The <c>auto</c> alternative for the
+ <c>write_concurrency</c> option is similar to the
+ <c>true</c> option but automatically adjusts the
+ synchronization granularity during runtime depending on how the
+ table is used. This is the recommended
+ <c>write_concurrency</c> option when using Erlang/OTP 25
+ and above as it performs well in most scenarios.</p>
<p>The <c>write_concurrency</c> option can be combined with the options
<seeerl marker="#new_2_read_concurrency">
<c>read_concurrency</c></seeerl> and
@@ -1278,12 +1331,9 @@ ets:select(Table, MatchSpec),</code>
concurrent read bursts and large concurrent
write bursts are common; for more information, see option
<seeerl marker="#new_2_read_concurrency">
- <c>read_concurrency</c></seeerl>. The <c>decentralized_counters</c>
- option is turned on by default for tables of type <c>ordered_set</c>
- with the <c>write_concurrency</c> option enabled, and the
- <c>decentralized_counters</c> option is turned off by default for
- all other table types.
- For more information, see the documentation for the
+ <c>read_concurrency</c></seeerl>. It is almost always a
+ good idea to combine the <c>write_concurrency</c> option
+ with the
<seeerl marker="#new_2_decentralized_counters">
<c>decentralized_counters</c></seeerl> option.</p>
<p>Notice that this option does not change any guarantees about
@@ -1291,17 +1341,24 @@ ets:select(Table, MatchSpec),</code>
Functions that makes such promises over many objects (like
<seemfa marker="#insert/2"><c>insert/2</c></seemfa>)
gain less (or nothing) from this option.</p>
- <p>The memory consumption inflicted by both <c>write_concurrency</c>
- and <c>read_concurrency</c> is a constant overhead per table for
- <c>set</c>, <c>bag</c> and <c>duplicate_bag</c>. For
- <c>ordered_set</c> the memory overhead depends on the number
- of inserted objects and the amount of actual detected
- concurrency in runtime. The memory overhead can be especially
- large when both options are combined.</p>
+ <p>The memory consumption inflicted by both
+ <c>write_concurrency</c> and <c>read_concurrency</c> is a
+ constant overhead per table for <c>set</c>, <c>bag</c> and
+ <c>duplicate_bag</c> when the <c>true</c> alternative for
+ the <c>write_concurrency</c> option is not used. For
+ all tables with the <c>auto</c> alternative and <c>ordered_set</c>
+ tables with <c>true</c> alternative the
+ memory overhead depends on the amount of actual detected concurrency during
+ runtime. The memory overhead can be especially large when
+ both <c>write_concurrency</c> and <c>read_concurrency</c> are combined.</p>
<note>
<p>Prior to stdlib-3.7 (OTP-22.0) <c>write_concurrency</c> had no
effect on <c>ordered_set</c>.</p>
</note>
+ <note>
+ <p>The <c>auto</c> alternative for the <c>write_concurrency</c>
+ option is only available in OTP-25.0 and above.</p>
+ </note>
<marker id="new_2_read_concurrency"></marker>
</item>
<tag><c>{read_concurrency,boolean()}</c></tag>
@@ -1332,12 +1389,15 @@ ets:select(Table, MatchSpec),</code>
<tag><c>{decentralized_counters,boolean()}</c></tag>
<item>
<p>
- Performance tuning. Defaults to <c>true</c> for tables
- of type <c>ordered_set</c> with the
- <seeerl marker="#new_2_write_concurrency">
- <c>write_concurrency</c></seeerl> option enabled, and defaults to
- false for all other table types. This option has no effect if
- the <c>write_concurrency</c> option is set to <c>false</c>.</p>
+ Performance tuning. Defaults to <c>true</c> for all
+ tables with the <c>write_concurrency</c> option set
+ to <c>auto</c>. For
+ tables of type <c>ordered_set</c> the option also
+ defaults to true when the <c>write_concurrency</c> option
+ is set to <c>true</c>. The option defaults to
+ <c>false</c> for all other configurations. This option
+ has no effect if the <c>write_concurrency</c> option is
+ set to <c>false</c>.</p>
<p>
When this option is set to <c>true</c>, the table is optimized for
frequent concurrent calls to operations that modify the tables
@@ -1378,7 +1438,7 @@ ets:select(Table, MatchSpec),</code>
<fsummary>Return the next key in an ETS table.</fsummary>
<desc>
<p>Returns the next key <c><anno>Key2</anno></c>, following key
- <c><anno>Key1</anno></c> in table <c><anno>Tab</anno></c>. For table
+ <c><anno>Key1</anno></c> in table <c><anno>Table</anno></c>. For table
type <c>ordered_set</c>, the next key in Erlang term order is
returned. For other table types, the next key
according to the internal order of the table is returned. If no
@@ -1403,7 +1463,7 @@ ets:select(Table, MatchSpec),</code>
<desc>
<p>Returns the previous key <c><anno>Key2</anno></c>, preceding key
<c><anno>Key1</anno></c> according to Erlang term order in table
- <c><anno>Tab</anno></c> of type <c>ordered_set</c>. For other
+ <c><anno>Table</anno></c> of type <c>ordered_set</c>. For other
table types, the function is synonymous to
<seemfa marker="#next/2"><c>next/2</c></seemfa>.
If no previous key exists, <c>'$end_of_table'</c> is returned.</p>
@@ -1416,7 +1476,7 @@ ets:select(Table, MatchSpec),</code>
<name name="rename" arity="2" since=""/>
<fsummary>Rename a named ETS table.</fsummary>
<desc>
- <p>Renames the named table <c><anno>Tab</anno></c> to the new name
+ <p>Renames the named table <c><anno>Table</anno></c> to the new name
<c><anno>Name</anno></c>. Afterwards, the old name cannot be used to
access the table. Renaming an unnamed table has no effect.</p>
</desc>
@@ -1488,9 +1548,9 @@ ets:select(ets:repair_continuation(MaybeBroken,MS)).</code>
<seemfa marker="#select/3"><c>select/3</c></seemfa> &amp;
<seemfa marker="#select/1"><c>select/1</c></seemfa>.</p>
<p>A process fixes a table by calling
- <c>safe_fixtable(<anno>Tab</anno>, true)</c>. The table remains
+ <c>safe_fixtable(<anno>Table</anno>, true)</c>. The table remains
fixed until the process releases it by calling
- <c>safe_fixtable(<anno>Tab</anno>, false)</c>, or until the process
+ <c>safe_fixtable(<anno>Table</anno>, false)</c>, or until the process
terminates.</p>
<p>If many processes fix a table, the table remains fixed
until all processes have released it (or terminated).
@@ -1506,21 +1566,21 @@ ets:select(ets:repair_continuation(MaybeBroken,MS)).</code>
<c>next/2</c> is called.</p>
<p><em>Example:</em></p>
<code type="none">
-clean_all_with_value(Tab,X) ->
- safe_fixtable(Tab,true),
- clean_all_with_value(Tab,X,ets:first(Tab)),
- safe_fixtable(Tab,false).
+clean_all_with_value(Table,X) ->
+ safe_fixtable(Table,true),
+ clean_all_with_value(Table,X,ets:first(Table)),
+ safe_fixtable(Table,false).
-clean_all_with_value(Tab,X,'$end_of_table') ->
+clean_all_with_value(Table,X,'$end_of_table') ->
true;
-clean_all_with_value(Tab,X,Key) ->
- case ets:lookup(Tab,Key) of
+clean_all_with_value(Table,X,Key) ->
+ case ets:lookup(Table,Key) of
[{Key,X}] ->
- ets:delete(Tab,Key);
+ ets:delete(Table,Key);
_ ->
true
end,
- clean_all_with_value(Tab,X,ets:next(Tab,Key)).</code>
+ clean_all_with_value(Table,X,ets:next(Table,Key)).</code>
<p>Notice that deleted objects are not freed from a
fixed table until it has been released. If a process fixes a
table but never releases it, the memory used by the deleted
@@ -1528,7 +1588,7 @@ clean_all_with_value(Tab,X,Key) ->
the table also degrades significantly.</p>
<p>To retrieve information about which processes have fixed which
tables, use <seeerl marker="#info_2_safe_fixed_monotonic_time">
- <c>info(Tab, safe_fixed_monotonic_time)</c></seeerl>. A system with
+ <c>info(Table, safe_fixed_monotonic_time)</c></seeerl>. A system with
many processes fixing tables can need a monitor that sends alarms
when tables have been fixed for too long.</p>
<p>Notice that <c>safe_fixtable/2</c> is not necessary for table type
@@ -1556,7 +1616,7 @@ clean_all_with_value(Tab,X,Key) ->
<fsummary>Match the objects in an ETS table against a
match specification.</fsummary>
<desc>
- <p>Matches the objects in table <c><anno>Tab</anno></c> using a
+ <p>Matches the objects in table <c><anno>Table</anno></c> using a
<seeerl marker="#match_spec">match specification</seeerl>.
This is a more general call than
<seemfa marker="#match/2"><c>match/2</c></seemfa> and
@@ -1585,23 +1645,23 @@ Result = "Term construct"</code>
match variables in a list), so that the following
<c>match/2</c> expression:</p>
<code type="none">
-ets:match(Tab,{'$1','$2','$3'})</code>
+ets:match(Table,{'$1','$2','$3'})</code>
<p>is exactly equivalent to:</p>
<code type="none">
-ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}])</code>
+ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])</code>
<p>And that the following <c>match_object/2</c> call:</p>
<code type="none">
-ets:match_object(Tab,{'$1','$2','$1'})</code>
+ets:match_object(Table,{'$1','$2','$1'})</code>
<p>is exactly equivalent to</p>
<code type="none">
-ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}])</code>
+ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])</code>
<p>Composite terms can be constructed in the <c>Result</c> part
either by simply writing a list, so that the following code:</p>
<code type="none">
-ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}])</code>
+ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])</code>
<p>gives the same output as:</p>
<code type="none">
-ets:select(Tab,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])</code>
+ets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])</code>
<p>That is, all the bound variables in the match head as a list. If
tuples are to be constructed, one has to write a tuple of
arity 1 where the single element in the tuple is the tuple
@@ -1609,10 +1669,10 @@ ets:select(Tab,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])</code>
for a <c>Guard</c>).</p>
<p>Therefore the following call:</p>
<code type="none">
-ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}])</code>
+ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])</code>
<p>gives the same output as:</p>
<code type="none">
-ets:select(Tab,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])</code>
+ets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])</code>
<p>This syntax is equivalent to the syntax used in the trace
patterns (see the
<seeerl marker="runtime_tools:dbg">
@@ -1674,7 +1734,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
specification and return the number of objects for which the match
specification returned <c>true</c>.</fsummary>
<desc>
- <p>Matches the objects in table <c><anno>Tab</anno></c> using a
+ <p>Matches the objects in table <c><anno>Table</anno></c> using a
<seeerl marker="#match_spec">match specification</seeerl>. If the
match specification returns <c>true</c> for an object, that object
considered a match and is counted. For any other result from
@@ -1693,7 +1753,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
specification and delete objects where the match specification
returns <c>true</c>.</fsummary>
<desc>
- <p>Matches the objects in table <c><anno>Tab</anno></c> using a
+ <p>Matches the objects in table <c><anno>Table</anno></c> using a
<seeerl marker="#match_spec">match specification</seeerl>. If the
match specification returns <c>true</c> for an object, that object is
removed from the table. For any other result from the match
@@ -1715,7 +1775,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
<name name="select_replace" arity="2" since="OTP 20.0"/>
<fsummary>Match and replace objects atomically in an ETS table</fsummary>
<desc>
- <p>Matches the objects in the table <c><anno>Tab</anno></c> using a
+ <p>Matches the objects in the table <c><anno>Table</anno></c> using a
<seeerl marker="#match_spec">match specification</seeerl>. For each
matched object, the existing object is replaced with
the match specification result.</p>
@@ -1723,7 +1783,7 @@ is_integer(X), is_integer(Y), X + Y < 4711]]></code>
<seeerl marker="#concurrency">atomic and isolated</seeerl>. The
<c>select_replace</c> table traversal as a whole, like all other select functions,
does not give such guarantees.</p>
- <p>The match specifiction must be guaranteed to <em>retain the key</em>
+ <p>The match specification must be guaranteed to <em>retain the key</em>
of any matched object. If not, <c>select_replace</c> will fail with <c>badarg</c>
without updating any objects.</p>
<p>For the moment, due to performance and semantic constraints,
@@ -1833,7 +1893,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
<c>first</c>/<c>next</c> or <c>last</c>/<c>prev</c> are to be used
instead.</p>
<p>Returns all objects in slot <c><anno>I</anno></c> of table
- <c><anno>Tab</anno></c>. A table can be traversed by repeatedly
+ <c><anno>Table</anno></c>. A table can be traversed by repeatedly
calling the function,
starting with the first slot <c><anno>I</anno>=0</c> and
ending when <c>'$end_of_table'</c> is returned.
@@ -1853,10 +1913,10 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
<name name="tab2file" arity="2" since=""/>
<fsummary>Dump an ETS table to a file.</fsummary>
<desc>
- <p>Dumps table <c><anno>Tab</anno></c> to file
+ <p>Dumps table <c><anno>Table</anno></c> to file
<c><anno>Filename</anno></c>.</p>
<p>Equivalent to
- <c>tab2file(<anno>Tab</anno>, <anno>Filename</anno>,[])</c></p>
+ <c>tab2file(<anno>Table</anno>, <anno>Filename</anno>,[])</c></p>
</desc>
</func>
@@ -1864,7 +1924,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
<name name="tab2file" arity="3" since=""/>
<fsummary>Dump an ETS table to a file.</fsummary>
<desc>
- <p>Dumps table <c><anno>Tab</anno></c> to file
+ <p>Dumps table <c><anno>Table</anno></c> to file
<c><anno>Filename</anno></c>.</p>
<p>When dumping the table, some information about the table
is dumped to a header at the beginning of the dump. This
@@ -1911,7 +1971,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
<name name="tab2list" arity="1" since=""/>
<fsummary>Return a list of all objects in an ETS table.</fsummary>
<desc>
- <p>Returns a list of all objects in table <c><anno>Tab</anno></c>.</p>
+ <p>Returns a list of all objects in table <c><anno>Table</anno></c>.</p>
</desc>
</func>
@@ -2005,7 +2065,7 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
tables, Dets tables,
and lists are also recognized by QLC as sources of
data. Calling <c>table/1,2</c> is the means to make the
- ETS table <c>Tab</c> usable to QLC.</p>
+ ETS table <c>Table</c> usable to QLC.</p>
<p>When there are only simple restrictions on the key position,
QLC uses <seemfa marker="#lookup/2"><c>lookup/2</c></seemfa>
to look up the keys. When
@@ -2053,12 +2113,12 @@ Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
<p>An explicit match specification is here used to traverse the
table:</p>
<pre>
-9> <input>true = ets:insert(Tab = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),</input>
+9> <input>true = ets:insert(Table = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),</input>
<input>MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X &lt; 5) -> {Y} end),</input>
-<input>QH1 = ets:table(Tab, [{traverse, {select, MS}}]).</input></pre>
+<input>QH1 = ets:table(Table, [{traverse, {select, MS}}]).</input></pre>
<p>An example with an implicit match specification:</p>
<pre>
-10> <input>QH2 = qlc:q([{Y} || {X,Y} &lt;- ets:table(Tab), (X > 1) or (X &lt; 5)]).</input></pre>
+10> <input>QH2 = qlc:q([{Y} || {X,Y} &lt;- ets:table(Table), (X > 1) or (X &lt; 5)]).</input></pre>
<p>The latter example is equivalent to the former, which
can be verified using function <c>qlc:info/1</c>:</p>
<pre>
@@ -2076,7 +2136,7 @@ true</pre>
ETS table.</fsummary>
<desc>
<p>Returns and removes a list of all objects with key
- <c><anno>Key</anno></c> in table <c><anno>Tab</anno></c>.</p>
+ <c><anno>Key</anno></c> in table <c><anno>Table</anno></c>.</p>
<p>The specified <c><anno>Key</anno></c> is used to identify the object
by either <em>comparing equal</em> the key of an object in an
<c>ordered_set</c> table, or <em>matching</em> in other types of
@@ -2118,7 +2178,7 @@ true</pre>
</fsummary>
<desc>
<p>Fills an already created/opened Dets table with the objects
- in the already opened ETS table named <c><anno>Tab</anno></c>.
+ in the already opened ETS table named <c><anno>Table</anno></c>.
The Dets table is emptied before the objects are inserted.</p>
</desc>
</func>
@@ -2131,7 +2191,7 @@ true</pre>
<name name="update_counter" arity="3" clause_i="3" since=""/>
<name name="update_counter" arity="4" clause_i="3" since="OTP 18.0"/>
<fsummary>Update a counter object in an ETS table.</fsummary>
- <type variable="Tab"/>
+ <type variable="Table"/>
<type variable="Key"/>
<type variable="UpdateOp" name_i="1"/>
<type variable="Pos" name_i="1"/>
@@ -2144,8 +2204,8 @@ true</pre>
the object by incrementing an element, and insert the resulting
object into the table again. The operation is guaranteed to be
<seeerl marker="#concurrency">atomic and isolated</seeerl>.</p>
- <p>This function destructively update the object with key
- <c><anno>Key</anno></c> in table <c><anno>Tab</anno></c> by adding
+ <p>This function destructively updates the object with key
+ <c><anno>Key</anno></c> in table <c><anno>Table</anno></c> by adding
<c><anno>Incr</anno></c> to the element at position
<c><anno>Pos</anno></c>. The new counter value is
returned. If no position is specified, the element directly
@@ -2211,7 +2271,7 @@ true</pre>
<name name="update_element" arity="3" clause_i="2" since=""/>
<fsummary>Update the <c>Pos</c>:th element of the object with a
specified key in an ETS table.</fsummary>
- <type variable="Tab"/>
+ <type variable="Table"/>
<type variable="Key"/>
<type variable="Value"/>
<type variable="Pos"/>
@@ -2220,7 +2280,7 @@ true</pre>
elements within an object, without the trouble of having to look up,
update, and write back the entire object.</p>
<p>This function destructively updates the object with key
- <c><anno>Key</anno></c> in table <c><anno>Tab</anno></c>.
+ <c><anno>Key</anno></c> in table <c><anno>Table</anno></c>.
The element at position <c><anno>Pos</anno></c> is given
the value <c><anno>Value</anno></c>.</p>
<p>A list of <c>{<anno>Pos</anno>,<anno>Value</anno>}</c> can be
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index 815eb23931..f07d878110 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -108,6 +108,23 @@
</func>
<func>
+ <name name="ensure_path" arity="1" since="OTP 25.0"/>
+ <fsummary>Ensure that all parent directories for a target directory exist.</fsummary>
+ <desc>
+ <p>Ensures that all parent directories for the specified path
+ <c><anno>Path</anno></c> exist, trying to create them if
+ necessary.</p>
+ <p>Unlike <seemfa
+ marker="#ensure_dir/1"><c>ensure_dir/1</c></seemfa>, this
+ function will attempt to create all path segments as a
+ directory, including the last segment.</p>
+ <p>Returns <c>ok</c> if all parent directories already exist
+ or can be created. Returns <c>{error, <anno>Reason</anno>}</c> if
+ some parent directory does not exist and cannot be created.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="file_size" arity="1" since=""/>
<fsummary>Return the size in bytes of a file.</fsummary>
<desc>
@@ -120,7 +137,8 @@
<fsummary>Fold over all files matching a regular expression.</fsummary>
<desc>
<p>Folds function <c><anno>Fun</anno></c> over all (regular) files
- <c><anno>F</anno></c> in directory <c><anno>Dir</anno></c> that match
+ <c><anno>F</anno></c> in directory <c><anno>Dir</anno></c> whose basename
+ (for example, just <c>"baz.erl"</c> in <c>"foo/bar/baz.erl"</c>) matches
the regular expression <c><anno>RegExp</anno></c> (for a description
of the allowed regular expressions,
see the <seeerl marker="re"><c>re</c></seeerl> module).
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index 46e2b2378f..cb9010ed53 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -136,7 +136,7 @@
<p>Joins an absolute directory with a relative filename. Similar to
<seemfa marker="#join/2"><c>join/2</c></seemfa>, but on platforms
with tight restrictions on raw filename length and no support for
- symbolic links (read: VxWorks), leading parent directory components
+ symbolic links, leading parent directory components
in <c><anno>Filename</anno></c> are matched against trailing
directory components in <c><anno>Dir</anno></c> so they can be
removed from the result - minimizing its length.</p>
@@ -188,7 +188,7 @@ basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seeerl>.
The options <c>'author'</c> and <c>'version'</c> are only used with <c>'windows'</c> option mode.
</p>
<list type="bulleted">
- <item><c>user_cache</c>
+ <item><marker id="user_cache"/><c>user_cache</c>
<p>The path location is intended for transient data files on a local machine.</p>
<p>
On Linux:
@@ -212,7 +212,7 @@ basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seeerl>.
5> <input>filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).</input>
"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"</pre>
</item>
- <item><c>user_config</c>
+ <item><marker id="user_config"/><c>user_config</c>
<p>
The path location is intended for persistent configuration files.
</p>
@@ -232,7 +232,7 @@ basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seeerl>.
2> <input>filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).</input>
"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"</pre>
</item>
- <item><c>user_data</c>
+ <item><marker id="user_data"/><c>user_data</c>
<p>
The path location is intended for persistent data files.
</p>
@@ -252,7 +252,7 @@ basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seeerl>.
9> <input>filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).</input>
"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"</pre>
</item>
- <item><c>user_log</c>
+ <item><marker id="user_log"/><c>user_log</c>
<p>The path location is intended for transient log files on a local machine.</p>
<p>
On Linux:
@@ -269,11 +269,11 @@ basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seeerl>.
13> <input>filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).</input>
"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"</pre>
</item>
- <item><c>site_config</c><p>
+ <item><marker id="site_config"/><c>site_config</c><p>
On Linux:
Respects the os environment variable <c>XDG_CONFIG_DIRS</c>.</p>
<pre>
-5> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input>
+5> <input>filename:basedir(site_config, "my_application", #{os=>linux}).</input>
["/usr/local/share/my_application",
"/usr/share/my_application"]
6> <input>os:getenv("XDG_CONFIG_DIRS").</input>
@@ -290,7 +290,7 @@ true
5> <input>filename:basedir(site_config, "my_application", #{os=>darwin}).</input>
["/Library/Application Support/my_application"]</pre>
</item>
- <item><c>site_data</c><p>
+ <item><marker id="site_data"/><c>site_data</c><p>
On Linux:
Respects the os environment variable <c>XDG_DATA_DIRS</c>.</p>
<pre>
@@ -509,37 +509,6 @@ true
</func>
<func>
- <name name="safe_relative_path" arity="1" since="OTP 19.3"/>
- <fsummary>Sanitize a relative path to avoid directory traversal attacks.</fsummary>
- <desc>
- <p>Sanitizes the relative path by eliminating ".." and "."
- components to protect against directory traversal attacks.
- Either returns the sanitized path name, or the atom
- <c>unsafe</c> if the path is unsafe.
- The path is considered unsafe in the following circumstances:</p>
- <list type="bulleted">
- <item><p>The path is not relative.</p></item>
- <item><p>A ".." component would climb up above the root of
- the relative path.</p></item>
- </list>
- <warning>
- <p>This function is deprecated. Use <seemfa marker="filelib#safe_relative_path/2">
- <c>filelib:safe_relative_path/2</c></seemfa> instead for sanitizing paths.</p>
- </warning>
- <p><em>Examples:</em></p>
- <pre>
-1> <input>filename:safe_relative_path("dir/sub_dir/..").</input>
-"dir"
-2> <input>filename:safe_relative_path("dir/..").</input>
-[]
-3> <input>filename:safe_relative_path("dir/../..").</input>
-unsafe
-4> <input>filename:safe_relative_path("/abs/path").</input>
-unsafe</pre>
- </desc>
- </func>
-
- <func>
<name name="split" arity="1" since=""/>
<fsummary>Split a filename into its path components.</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml
index 9aafca90c3..3477c2c90e 100644
--- a/lib/stdlib/doc/src/gb_sets.xml
+++ b/lib/stdlib/doc/src/gb_sets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2021</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -29,13 +29,21 @@
<rev></rev>
</header>
<module since="">gb_sets</module>
- <modulesummary>General balanced trees.</modulesummary>
+ <modulesummary>Sets represented by general balanced trees.</modulesummary>
<description>
<p>This module provides ordered sets using Prof. Arne Andersson's
General Balanced Trees. Ordered sets can be much more efficient than
using ordered lists, for larger sets, but depends on the
application.</p>
+ <p>The data representing a set as used by this module is to be
+ regarded as opaque by other modules. In abstract terms, the
+ representation is a composite type of existing Erlang terms. See
+ note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>. Any code assuming knowledge of the format is
+ running on thin ice.</p>
+
<p>This module considers two elements as different if and only if
they do not compare equal (<c>==</c>).</p>
</description>
@@ -304,8 +312,14 @@
<name name="is_set" arity="1" since=""/>
<fsummary>Test for a set.</fsummary>
<desc>
- <p>Returns <c>true</c> if <c><anno>Term</anno></c> appears to be a set,
- otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> appears to
+ be a set, otherwise <c>false</c>. This function will return
+ <c>true</c> for any term that coincides with the
+ representation of a <c>gb_set</c>, while not really being a
+ <c>gb_set</c>, thus it might return false positive results.
+ See also note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 44682e91e2..26a7f5646b 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>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -119,24 +119,114 @@ gen_event:stop -----> Module:terminate/2
<datatype>
<name name="handler"/>
</datatype>
+
<datatype>
<name name="handler_args"/>
</datatype>
+
<datatype>
<name name="add_handler_ret"/>
</datatype>
+
<datatype>
<name name="del_handler_ret"/>
</datatype>
+
+ <datatype>
+ <name name="emgr_ref"/>
+ </datatype>
+
<datatype>
<name name="request_id"/>
<desc>
<p>
- A request handle, see <seemfa marker="#send_request/3"> <c>send_request/3</c> </seemfa>
+ An opaque request identifier. See
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
for details.
</p>
</desc>
</datatype>
+
+ <datatype>
+ <name name="request_id_collection"/>
+ <desc>
+ <p>
+ An opaque collection of request identifiers
+ (<seetype marker="#request_id"><c>request_id()</c></seetype>)
+ where each request identifier can be associated with a label
+ chosen by the user. For more information see
+ <seemfa marker="#reqids_new/0"><c>reqids_new/0</c></seemfa>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="response_timeout"/>
+ <desc>
+ <p>
+ Used to set a time limit on how long to wait for a response using
+ either
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ or
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ The time unit used is <c>millisecond</c>. Currently valid values:
+ </p>
+ <taglist>
+ <tag><c>0..4294967295</c></tag>
+ <item><p>
+ Timeout relative to current time in milliseconds.
+ </p></item>
+ <tag><c>infinity</c></tag>
+ <item><p>
+ Infinite timeout. That is, the operation will never time out.
+ </p></item>
+ <tag><c>{abs, Timeout}</c></tag>
+ <item><p>
+ An absolute
+ <seemfa marker="erts:erlang#monotonic_time/1">Erlang monotonic time</seemfa>
+ timeout in milliseconds. That is, the operation will time out when
+ <seemfa marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time(millisecond)</c></seemfa>
+ returns a value larger than or equal to <c>Timeout</c>. <c>Timeout</c>
+ is not allowed to identify a time further into the future than <c>4294967295</c>
+ milliseconds. Identifying the timeout using an absolute timeout value
+ is especially handy when you have a deadline for responses corresponding
+ to a complete collection of requests
+ (<seetype marker="#request_id_collection"><c>request_id_collection()</c></seetype>)
+,
+ since you do not have to recalculate the relative time until the deadline
+ over and over again.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="format_status"/>
+ <desc>
+ <p>
+ A map that describes the <c>gen_event</c> process status.
+ The keys are:
+ </p>
+ <taglist>
+ <tag><c>state</c></tag>
+ <item>The internal state of the event handler.</item>
+ <tag><c>message</c></tag>
+ <item>The message that caused the event handler to terminate.</item>
+ <tag><c>reason</c></tag>
+ <item>The reason that caused the event handler to terminate.</item>
+ <tag><c>log</c></tag>
+ <item>
+ The <seemfa marker="sys#log/2">sys log</seemfa> of the server.
+ </item>
+ </taglist>
+ <p>
+ New associations may be added into the status map
+ without prior notice.
+ </p>
+ </desc>
+ </datatype>
</datatypes>
<funcs>
@@ -207,14 +297,17 @@ gen_event:stop -----> Module:terminate/2
<desc>
<p>Adds a new event handler in the same way as
<seemfa marker="#add_handler/3"><c>add_handler/3</c></seemfa>,
- but also supervises the connection between the event handler
+ but also supervises the connection by linking the event handler
and the calling process.</p>
<list type="bulleted">
<item>If the calling process later terminates with <c>Reason</c>,
- the event manager deletes the event handler by calling
+ the event manager deletes any supervised event handlers by calling
<seemfa marker="#Module:terminate/2">
- <c>Module:terminate/2</c></seemfa>
- with <c>{stop,Reason}</c> as argument.
+ <c>Module:terminate/2</c></seemfa>,
+ then calls
+ <seemfa marker="#Module:handle_info/2">
+ <c>Module:handle_info/2</c></seemfa>
+ for each remaining handler.
</item>
<item>
<p>If the event handler is deleted later, the event manager
@@ -292,31 +385,41 @@ gen_event:stop -----> Module:terminate/2
unexpected value <c>Term</c>, this function returns
<c>{error,{'EXIT',Reason}}</c> or <c>{error,Term}</c>,
respectively.</p>
+ <p>
+ When this call fails it
+ <seemfa marker="erts:erlang#exit/1">exits</seemfa>
+ the calling process.
+ The exit term is on the form
+ <c>{Reason,&nbsp;Location}</c> where
+ <c>Location&nbsp;=&nbsp;{gen_event,call,ArgList}</c>.
+ See
+ <seemfa marker="gen_server#call/3">
+ <c>gen_server:call/3</c>
+ </seemfa>
+ that has a description of relevant
+ values for the <c>Reason</c> in the exit term.
+ </p>
</desc>
</func>
-
<func>
- <name since="OTP 23.0">check_response(Msg, RequestId) -> Result</name>
- <fsummary>Check if a message is a reply from a server.</fsummary>
- <type>
- <v>Msg = term()</v>
- <v>RequestId = request_id()</v>
- <v>Result = {reply, Reply} | no_reply | {error, Error}</v>
- <v>Reply = Error = term()</v>
- </type>
+ <name name="check_response" arity="2" since="OTP 23.0"/>
+ <fsummary>Check if a message is a response to an asynchronous call request
+ to a generic event manager.</fsummary>
<desc>
<p>
- This function is used to check if a previously received
- message, for example by <c>receive</c> or
- <c>handle_info/2</c>, is a result of a request made with
+ Check if <c><anno>Msg</anno></c> is a response corresponding
+ to the request identifier <c><anno>ReqId</anno></c>. The request
+ must have been made by
<seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>.
- If <c>Msg</c> is a reply to the handle <c>RequestId</c>
- the result of the request is returned in <c>Reply</c>.
- Otherwise returns <c>no_reply</c> and no cleanup is done, and
- thus the function shall be invoked repeatedly until a reply
- is returned.
</p>
+ <p>
+ If <c><anno>Msg</anno></c> is a response corresponding to
+ <c><anno>ReqId</anno></c> the response is returned; otherwise,
+ <c>no_reply</c> is returned and no cleanup is done, and
+ thus the function must be invoked repeatedly until a response
+ is returned.
+ </p>
<p>
If the specified event handler is not
installed, the function returns <c>{error,bad_module}</c>. If
@@ -329,6 +432,74 @@ gen_event:stop -----> Module:terminate/2
</desc>
</func>
+ <func>
+ <name name="check_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Check if a message is a response to an asynchronous call request
+ to a generic event manager.</fsummary>
+ <desc>
+ <p>
+ Check if <c><anno>Msg</anno></c> is a response corresponding
+ to a request identifier saved in <c><anno>ReqIdCollection</anno></c>.
+ All request identifiers of <c><anno>ReqIdCollection</anno></c>
+ must correspond to requests that have been made using
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa> or
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">saving the request id</seemfa>
+ in a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>check_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned. If <c><anno>Msg</anno></c>
+ does not correspond to any of the request identifiers in
+ <c><anno>ReqIdCollection</anno></c>, the atom
+ <c>no_reply</c> is returned.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>check_response/3</c>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>check_response/3</c>, it will always
+ return <c>no_reply</c>.
+ </p>
+ </desc>
+ </func>
+
<func>
<name since="">delete_handler(EventMgrRef, Handler, Args) -> Result</name>
<fsummary>Delete an event handler from a generic event manager.</fsummary>
@@ -392,34 +563,29 @@ gen_event:stop -----> Module:terminate/2
does not exist, unless it is specified as <c>Name</c>.</p>
</desc>
</func>
-
+
<func>
- <name since="OTP 24.0">receive_response(RequestId, Timeout) -> Result</name>
- <fsummary>Receive for a reply from a server.</fsummary>
- <type>
- <v>RequestId = request_id()</v>
- <v>Reply = term()</v>
- <v>Timeout = timeout()</v>
- <v>Result = {reply, Reply} | timeout | {error, Error}</v>
- <v>Reply = Error = term()</v>
- </type>
+ <name name="receive_response" arity="2" clause_i="1" since="OTP 24.0"/>
+ <fsummary>Receive a response to an asynchronous call request
+ to a generic event manager.</fsummary>
<desc>
<p>
- This function is used to receive for a reply of a request made with
- <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
- to the event manager. This function must be called from the same
- process from which <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
- was made.
+ Receive a response corresponding to the request identifier
+ <c><anno>ReqId</anno></c>- The request must have been made by
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ to the <c>gen_statem</c> process. This function must be called
+ from the same process from which
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ was made.
</p>
<p>
- <c>Timeout</c> is an integer greater then or equal to zero
- that specifies how many milliseconds to wait for an reply, or
- the atom <c>infinity</c> to wait indefinitely.
- If no reply is received within the specified
- time, the function returns <c>timeout</c>. Assuming that the
+ <c><anno>Timeout</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified time,
+ the function returns <c>timeout</c>. Assuming that the
server executes on a node supporting aliases (introduced in
- OTP 24) no response will be received after a timeout. Otherwise,
- a garbage response might be received at a later time.
+ OTP 24) the request will also be abandoned. That is, no
+ response will be received after a timeout. Otherwise, a
+ stray response might be received at a later time.
</p>
<p>
The return value <c>Reply</c> is defined in the return value
@@ -436,44 +602,197 @@ gen_event:stop -----> Module:terminate/2
</p>
<p>
The difference between
- <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa>
- and <c>receive_response()</c> is that <c>receive_response()</c>
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>
+ and <c>receive_response/2</c> is that <c>receive_response/2</c>
abandons the request at timeout so that a potential future
- response is ignored, while <c>wait_response()</c> does not.
+ response is ignored, while <c>wait_response/2</c> does not.
</p>
</desc>
</func>
<func>
- <name since="OTP 23.0">send_request(EventMgrRef, Handler, Request) -> RequestId</name>
- <fsummary>Send a request to a generic event manager.</fsummary>
- <type>
- <v>EventMgrRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;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>
- <v>Request = term()</v>
- <v>RequestId = request_id()</v>
- </type>
+ <name name="receive_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Receive a response to an asynchronous call request
+ to a generic event manager.</fsummary>
<desc>
+ <p>
+ Receive a response corresponding to a request identifier saved
+ in <c><anno>ReqIdCollection</anno></c>. All request identifiers
+ of <c><anno>ReqIdCollection</anno></c> must correspond to requests
+ that have been made using
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa> or
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">adding the request id</seemfa>
+ in a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ will be wrapped in a 3-tuple. The first element of this tuple equals
+ the value that would have been produced by <c>receive_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
<p>
- Sends a request to event handler <c>Handler</c> installed in
- event manager <c>EventMgrRef</c> and returns a handle
- <c>RequestId</c>. The return value <c>RequestId</c> shall
- later be used with <seemfa marker="#receive_response/2">
- <c>receive_response/2</c></seemfa>, <seemfa marker="#wait_response/2">
- <c>wait_response/2</c></seemfa>, or <seemfa
- marker="#check_response/2">
- <c>check_response/2</c></seemfa> in the same process to
- fetch the actual result of the request.
+ If <c><anno>ReqIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified time,
+ the function returns <c>timeout</c>. Assuming that the
+ server executes on a node supporting aliases (introduced in
+ OTP 24) all requests identified by <c><anno>ReqIdCollection</anno></c>
+ will also be abandoned. That is, no responses will be received
+ after a timeout. Otherwise, stray responses might be received
+ at a later time.
</p>
<p>
- The call <c>gen_event:wait_response(gen_event:send_request(EventMgrRef,Handler,Request), Timeout)</c>
+ The difference between <c>receive_response/3</c> and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>
+ is that <c>receive_response/3</c> abandons the requests at timeout
+ so that potential future responses are ignored, while
+ <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>receive_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>receive_response/3</c>, it will always block
+ until a timeout determined by <c><anno>Timeout</anno></c> is
+ triggered.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_add" arity="3" since="OTP 25.0"/>
+ <fsummary>Save a request identifier.</fsummary>
+ <desc>
+ <p>
+ Saves <c><anno>ReqId</anno></c> and associates a <c><anno>Label</anno></c>
+ with the request identifier by adding this information to
+ <c><anno>ReqIdCollection</anno></c> and returning the
+ resulting request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_new" arity="0" since="OTP 25.0"/>
+ <fsummary>Create a new empty request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns a new empty request identifier collection. A
+ request identifier collection can be utilized in order
+ the handle multiple outstanding requests.
+ </p>
+ <p>
+ Request identifiers of requests made by
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ can be saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+ <p>
+ <seemfa marker="#reqids_size/1"><c>reqids_size/1</c></seemfa>
+ can be used to determine the amount of request identifiers in a
+ request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_size" arity="1" since="OTP 25.0"/>
+ <fsummary>Get size of a request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns the amount of request identifiers saved in
+ <c><anno>ReqIdCollection</anno></c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_to_list" arity="1" since="OTP 25.0"/>
+ <fsummary>List a request identifiers.</fsummary>
+ <desc>
+ <p>
+ Returns a list of <c>{<anno>ReqId</anno>, <anno>Label</anno>}</c>
+ tuples which corresponds to all request identifiers with their
+ associated labels present in the <c><anno>ReqIdCollection</anno></c>
+ collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send_request" arity="3" since="OTP 23.0"/>
+ <fsummary>Send an asyncronous call request to a generic event manager.</fsummary>
+ <desc>
+ <p>
+ Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c> to
+ event handler <c><anno>Handler</anno></c> installed in the event manager
+ identified by <c><anno>EventMgrRef</anno></c> and returns a request
+ identifier <c>ReqId</c>. The return value <c><anno>ReqId</anno></c>
+ shall later be used with
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>, or
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>
+ to fetch the actual result of the request. Besides passing
+ the request identifier directly to these functions, it can also be
+ saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>, or
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ If you are about to save the request identifier in a request identifier
+ collection, you may want to consider using
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>
+ instead.
+ </p>
+ <p>
+ The call <c>gen_event:receive_response(gen_event:send_request(<anno>EventMgrRef</anno>,
+ <anno>Handler</anno>, <anno>Request</anno>), Timeout)</c>
can be seen as equivalent to
- <seemfa marker="#call/3"><c>gen_event:call(EventMgrRef,Handler,Request,Timeout)</c></seemfa>,
+ <seemfa marker="#call/3"><c>gen_event:call(<anno>EventMgrRef</anno>,
+ <anno>Handler</anno>, <anno>Request</anno>, Timeout)</c></seemfa>,
ignoring the error handling.
</p>
<p>
@@ -487,6 +806,38 @@ gen_event:stop -----> Module:terminate/2
</desc>
</func>
+
+ <func>
+ <name name="send_request" arity="5" since="OTP 25.0"/>
+ <fsummary>Sends a request to a generic server.</fsummary>
+ <desc>
+ <p>
+ Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c> to
+ event handler <c><anno>Handler</anno></c> installed in the event manager
+ identified by <c><anno>EventMgrRef</anno></c>.
+ The <c><anno>Label</anno></c> will be associated with the request
+ identifier of the operation and added to the returned request
+ identifier collection <c><anno>NewReqIdCollection</anno></c>.
+ The collection can later be used in order to get one response
+ corresponding to a request in the collection by passing the
+ collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+
+ <p>
+ The same as calling
+ <seemfa marker="#reqids_add/3"><c>gen_event:reqids_add</c></seemfa>(<seemfa
+ marker="#send_request/3"><c>gen_event:send_request</c></seemfa><c>(<anno>EventMgrRef</anno>,
+ <anno>Handler</anno>, <anno>Request</anno>), <anno>Label</anno>,
+ <anno>ReqIdCollection</anno>)</c>, but calling <c>send_request/5</c>
+ is slightly more efficient.
+ </p>
+ </desc>
+ </func>
+
<func>
<name since="">start() -> Result</name>
<name since="">start(EventMgrName | Options) -> Result</name>
@@ -637,10 +988,16 @@ gen_event:stop -----> Module:terminate/2
specifies how many milliseconds to wait for the event manager to
terminate, or the atom <c>infinity</c> to wait
indefinitely. Defaults to <c>infinity</c>. If the
- event manager has not terminated within the specified time, a
- <c>timeout</c> exception is raised.</p>
- <p>If the process does not exist, a <c>noproc</c> exception
- is raised.</p>
+ event manager has not terminated within the specified time,
+ the call exits the calling process
+ with reason <c>timeout</c>.</p>
+ <p>
+ If the process does not exist, the call exits
+ the calling process with reason <c>noproc</c>,
+ and with reason <c>{nodedown,Node}</c>
+ if the connection fails to the remote <c>Node</c>
+ where the server runs.
+ </p>
<p>For a description of <c>EventMgrRef</c>, see
<seemfa marker="#add_handler/3"><c>add_handler/3</c></seemfa>.</p>
</desc>
@@ -719,30 +1076,24 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
- <name since="OTP 23.0">wait_response(RequestId, Timeout) -> Result</name>
- <fsummary>Wait for a reply from a server.</fsummary>
- <type>
- <v>RequestId = request_id()</v>
- <v>Reply = term()</v>
- <v>Timeout = timeout()</v>
- <v>Result = {reply, Reply} | timeout | {error, Error}</v>
- <v>Reply = Error = term()</v>
- </type>
+ <name name="wait_response" arity="2" since="OTP 23.0"/>
+ <fsummary>Wait or poll for a response to an asynchronous call request
+ to a generic event manager.</fsummary>
<desc>
<p>
- This function is used to wait for a reply of a request made with
- <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
- to the event manager. This function must be called from the same
- process from which <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
- was made.
+ Wait for a response corresponding to the request identifier
+ <c><anno>ReqId</anno></c>. The request must have been made by
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ to the <c>gen_statem</c> process. This function must be called
+ from the same process from which
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa>
+ was made.
</p>
<p>
- <c>Timeout</c> is an integer greater then or equal to zero
- that specifies how many milliseconds to wait for an reply, or
- the atom <c>infinity</c> to wait indefinitely.
- If no reply is received within the specified
+ <c><anno>WaitTime</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified
time, the function returns <c>timeout</c> and no cleanup is
- done, and thus the function must be invoked repeatedly until a
+ done, and thus the function can be invoked repeatedly until a
reply is returned.
</p>
<p>
@@ -760,11 +1111,89 @@ gen_event:stop -----> Module:terminate/2
</p>
<p>
The difference between
- <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa>
- and <c>wait_response()</c> is that <c>receive_response()</c>
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>
+ and <c>wait_response/2</c> is that <c>receive_response/2</c>
abandons the request at timeout so that a potential future
- response is ignored, while <c>wait_response()</c> does not.
+ response is ignored, while <c>wait_response/2</c> does not.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="wait_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Wait or poll for a response to an asynchronous call request
+ to a generic event manager.</fsummary>
+ <desc>
+ <p>
+ Wait for a response corresponding to a request identifier saved
+ in <c><anno>ReqIdCollection</anno></c>. All request identifiers
+ of <c><anno>ReqIdCollection</anno></c> must correspond to requests
+ that have been made using
+ <seemfa marker="#send_request/3"><c>send_request/3</c></seemfa> or
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">saving the request id</seemfa> in
+ a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/5"><c>send_request/5</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>wait_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, <c>no_request</c>
+ will be returned. If no response is received before the
+ <c><anno>WaitTime</anno></c> timeout has triggered, the atom
+ <c>timeout</c> is returned. It is valid to continue waiting for a
+ response as many times as needed up until a response has been received
+ and completed by <c>check_response()</c>, <c>receive_response()</c>,
+ or <c>wait_response()</c>.
+ </p>
+ <p>
+ The difference between
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>
+ and <c>wait_response/3</c> is that <c>receive_response/3</c>
+ abandons requests at timeout so that a potential future
+ responses are ignored, while <c>wait_response/3</c> does not.
</p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>wait_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>wait_response/3</c>, it will always block
+ until a timeout determined by <c><anno>WaitTime</anno></c> is
+ triggered and then return <c>no_reply</c>.
+ </p>
</desc>
</func>
@@ -835,6 +1264,67 @@ gen_event:stop -----> Module:terminate/2
</func>
<func>
+ <name since="OTP 25.0">Module:format_status(Status) -> NewStatus</name>
+ <fsummary>Optional function for providing a term describing the
+ current event handler state.</fsummary>
+ <type>
+ <v>Status = <seetype marker="#format_status">format_status()</seetype></v>
+ <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v>
+ </type>
+ <desc>
+ <note>
+ <p>This callback is optional, so event handler modules need
+ not export it. If a handler does not export this function,
+ the <c>gen_event</c> module uses the handler state directly for
+ the purposes described below.</p>
+ <p>
+ If this callback is exported but fails, to hide possibly sensitive
+ data, the default function will instead return the fact that
+ <c>format_status/1</c> has crashed.</p>
+ </note>
+ <p>This function is called by a <c>gen_event</c> process in the
+ following situations:</p>
+ <list type="bulleted">
+ <item>One of <seemfa marker="sys#get_status/1">
+ <c>sys:get_status/1,2</c></seemfa>
+ is invoked to get the <c>gen_event</c> status.</item>
+ <item>The event handler terminates abnormally and <c>gen_event</c>
+ logs an error.</item>
+ </list>
+ <p>
+ This callback is used to limit the status of the event handler
+ returned by
+ <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa>
+ or sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>.
+ </p>
+ <p>
+ The callback gets a map <c>Status</c>
+ describing the current status and shall return a map
+ <c>NewStatus</c> with the same keys,
+ but it may transform some values.
+ </p>
+ <p>
+ Two possible use cases for this callback is to
+ remove sensitive information from the state
+ to prevent it from being printed in log files,
+ or to compact large irrelevant status items
+ that would only clutter the logs.
+ </p>
+ <code type="erl"><![CDATA[
+format_status(Status) ->
+ maps:map(
+ fun(state,State) ->
+ maps:remove(private_key, State);
+ (message,{password, _Pass}) ->
+ {password, removed};
+ (_,Value) ->
+ Value
+ end, Status).
+]]></code>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R14B">Module:format_status(Opt, [PDict, State]) -> Status</name>
<fsummary>Optional function for providing a term describing the
current event handler state.</fsummary>
@@ -845,6 +1335,11 @@ gen_event:stop -----> Module:terminate/2
<v>Status = term()</v>
</type>
<desc>
+ <warning>
+ <p>This callback is deprecated, in new code use <seemfa marker="#Module:format_status/1">
+ format_status/1</seemfa>. If a <seemfa marker="#Module:format_status/1">format_status/1</seemfa>
+ callback exists, then this function will never be called.</p>
+ </warning>
<note>
<p>This callback is optional, so event handler modules need
not export it. If a handler does not export this function,
@@ -1005,6 +1500,14 @@ gen_event:stop -----> Module:terminate/2
an event manager receives any other message than an event or
a synchronous request (or a system message).</p>
<p><c>Info</c> is the received message.</p>
+ <p>In particular, this callback will be made when a process terminated
+ after calling
+ <seemfa marker="#add_sup_handler/3">
+ <c>add_sup_handler/3</c></seemfa>. Any event handler
+ attached to an event manager which in turn has a supervised handler
+ should expect callbacks of the shape
+ <seemfa marker="#Module:handle_info/2">
+ <c>Module:handle_info({'EXIT', Pid, Reason}, State)</c></seemfa>.</p>
<p>For a description of <c>State</c> and possible return values, see
<seemfa marker="#Module:handle_event/2">
<c>Module:handle_event/2</c></seemfa>.</p>
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index c0c806c309..4948418b3d 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>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -109,632 +109,1379 @@ gen_server:abcast -----> Module:handle_cast/2
</description>
+
+
+ <datatypes>
+ <datatype>
+ <name name="server_name"/>
+ <desc>
+ <p>
+ Name specification to use when starting a <c>gen_server</c>.
+ See functions
+ <seemfa marker="#start/3"><c>start/3,4</c></seemfa>,
+ <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>,
+ <seemfa marker="#start_monitor/3"><c>start_monitor/3,4</c></seemfa>,
+ <seemfa marker="#enter_loop/3"><c>enter_loop/3,4,5</c></seemfa>,
+ and the type
+ <seetype marker="#server_ref"><c>server_ref()</c></seetype>
+ below.
+ </p>
+ <taglist>
+ <tag><c>{local,<anno>LocalName</anno>}</c></tag>
+ <item>
+ <p>
+ Register the <c>gen_server</c> locally
+ as <c><anno>LocalName</anno></c> using
+ <seemfa marker="erts:erlang#register/2">
+ <c>register/2</c></seemfa>.
+ </p>
+ </item>
+ <tag><c>{global,<anno>GlobalName</anno>}</c></tag>
+ <item>
+ <p>
+ Register the <c>gen_server</c> process id
+ globally as <c>GlobalName</c> using
+ <seemfa marker="kernel:global#register_name/2">
+ <c>global:register_name/2</c></seemfa>.
+ </p>
+ </item>
+ <tag><c>{via,<anno>RegMod</anno>,<anno>ViaName</anno>}</c></tag>
+ <item>
+ <p>
+ Register the <c>gen_server</c> process with the registry
+ represented by <c><anno>RegMod</anno></c>.
+ The <c><anno>RegMod</anno></c> callback is to export
+ the functions <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c>, and <c>send/2</c>, which are to behave
+ like the corresponding functions in
+ <seeerl marker="kernel:global"><c>global</c></seeerl>.
+ Thus, <c>{via,global,<anno>GlobalName</anno>}</c>
+ is a valid reference equivalent to
+ <c>{global,<anno>GlobalName</anno>}</c>.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="server_ref"/>
+ <desc>
+ <p>
+ Server specification to use when addressing
+ a <c>gen_server</c>.
+ See <seemfa marker="#call/2"><c>call/2,3</c></seemfa>,
+ <seemfa marker="#cast/2"><c>cast/2</c></seemfa>,
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>,
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>,
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ <seemfa marker="#stop/1"><c>stop/2,3</c></seemfa>
+ and the type
+ <seetype marker="#server_name"><c>server_name()</c></seetype>
+ above.
+ </p>
+ <p>It can be:</p>
+ <taglist>
+ <tag><c>pid()</c></tag>
+ <item>
+ <p>
+ The <c>gen_server</c>'s process identifier.
+ </p>
+ </item>
+ <tag><c><anno>LocalName</anno></c></tag>
+ <item>
+ <p>
+ The <c>gen_server</c> is locally registered
+ as <c><anno>LocalName</anno></c> with
+ <seemfa marker="erts:erlang#register/2">
+ <c>register/2</c></seemfa>.
+ </p>
+ </item>
+ <tag><c>{<anno>Name</anno>,<anno>Node</anno>}</c></tag>
+ <item>
+ <p>
+ The <c>gen_server</c> is locally registered
+ on another node.
+ </p>
+ </item>
+ <tag><c>{global,<anno>GlobalName</anno>}</c></tag>
+ <item>
+ <p>
+ The <c>gen_server</c> is globally registered in
+ <seeerl marker="kernel:global"><c>global</c></seeerl>.
+ </p>
+ </item>
+ <tag><c>{via,<anno>RegMod</anno>,<anno>ViaName</anno>}</c></tag>
+ <item>
+ <p>
+ The <c>gen_server</c> is registered in
+ an alternative process registry.
+ The registry callback module <c><anno>RegMod</anno></c>
+ is to export functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c>, and <c>send/2</c>,
+ which are to behave like the corresponding functions in
+ <seeerl marker="kernel:global"><c>global</c></seeerl>.
+ Thus, <c>{via,global,<anno>GlobalName</anno>}</c>
+ is the same as <c>{global,<anno>GlobalName</anno>}</c>.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="start_opt"/>
+ <desc>
+ <p>
+ Options that can be used when starting
+ a <c>gen_server</c> server through, for example,
+ <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.
+ </p>
+ <taglist>
+ <tag><c>{timeout,<anno>Timeout</anno>}</c></tag>
+ <item>
+ <p>
+ How many milliseconds the <c>gen_server</c> process is allowed
+ to spend initializing or it is terminated and the
+ start function returns <c>{error,timeout}</c>.
+ </p>
+ </item>
+ <tag>
+ <c>{spawn_opt,<anno>SpawnOptions</anno>}</c>
+ </tag>
+ <item>
+ <p>
+ The <c><anno>SpawnOptions</anno></c> option list
+ is passed to the function used to spawn
+ the <c>gen_server</c>; see
+ <seemfa marker="erts:erlang#spawn_opt/2">
+ <c>spawn_opt/2</c></seemfa>.
+ </p>
+ <note>
+ <p>
+ Using spawn option <c>monitor</c> is not
+ allowed, it causes a <c>badarg</c> failure.
+ </p>
+ </note>
+ </item>
+ <tag><c>enter_loop_opt()</c></tag>
+ <item>
+ <p>
+ See the type
+ <seetype marker="#enter_loop_opt"><c>enter_loop_opt()</c></seetype>
+ below for more start options that are also allowed by
+ <seemfa marker="#enter_loop/3"><c>enter_loop/3,4,5</c></seemfa>.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="enter_loop_opt"/>
+ <desc>
+ <p>
+ Options that can be used when starting
+ a <c>gen_server</c> server through
+ <seemfa marker="#enter_loop/3"><c>enter_loop/3-5</c></seemfa>
+ or the start functions such as
+ <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.
+ </p>
+ <taglist>
+ <tag><c>{hibernate_after,<anno>HibernateAfterTimeout</anno>}</c></tag>
+ <item>
+ <p>
+ Specifies that the <c>gen_server</c> process awaits
+ any message for <c>HibernateAfterTimeout</c> milliseconds and
+ if no message is received, the process goes into hibernation
+ automatically (by calling
+ <seemfa marker="proc_lib#hibernate/3">
+ <c>proc_lib:hibernate/3</c></seemfa>).
+ </p>
+ </item>
+ <tag><c>{debug,<anno>Dbgs</anno>}</c></tag>
+ <item>
+ <p>
+ For every entry in <c><anno>Dbgs</anno></c>,
+ the corresponding function in
+ <seeerl marker="sys"><c>sys(3)</c></seeerl> is called.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="start_ret"/>
+ <desc>
+ <p>
+ Return value from the
+ <seemfa marker="#start/3"><c>start/3,4</c></seemfa>
+ and
+ <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>
+ functions.
+ </p>
+ <taglist>
+ <tag><c>{ok,<anno>Pid</anno>}</c></tag>
+ <item>
+ <p>
+ The <c>gen_server</c> process was succesfully created
+ and initialized, with the process identifier
+ <c><anno>Pid</anno></c>.
+ </p>
+ </item>
+ <tag><c>{error,{already_started,OtherPid}}</c></tag>
+ <item>
+ <p>
+ A process with the specified <c>ServerName</c> exists already
+ with the process identifier <c>OtherPid</c>.
+ This <c>gen_server</c> was not started.
+ </p>
+ </item>
+ <tag><c>ignore</c></tag>
+ <item>
+ <p>
+ <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>
+ returned <c>ignore</c>, the <c>gen_server</c> process
+ is terminated. An exit signal <c>normal</c> is sent
+ to linked processes and ports.
+ </p>
+ </item>
+ <tag><c>{error,<anno>Reason</anno>}</c></tag>
+ <item>
+ <p>
+ <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>
+ returned <c>{stop,<anno>Reason</anno>}</c>
+ or failed with <c><anno>Reason</anno></c>.
+ The <c>gen_server</c> process is terminated and
+ an exit signal with the same <c><anno>Reason</anno></c>
+ is sent to linked processes and ports.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="start_mon_ret"/>
+ <desc>
+ <p>
+ Return value from the
+ <seemfa marker="#start_monitor/3"><c>start_monitor/3,4</c></seemfa>
+ functions.
+ The same as type
+ <seetype marker="#start_ret"><c>start_ret()</c></seetype>
+ except that for a succesful start it returns both
+ the process identifier <c><anno>Pid</anno></c> and a
+ <seemfa marker="erts:erlang#monitor/2"><c>monitor/2,3</c></seemfa>
+ <c>reference()</c> <c><anno>MonRef</anno></c>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="from"/>
+ <desc>
+ <p>
+ Destination, given to the <c>gen_server</c>
+ as the first argument to the callback function
+ <seemfa marker="#Module:handle_call/3"><c>Module:handle_call/3</c></seemfa>,
+ to be used by the when replying through
+ <seemfa marker="#reply/2"><c>reply/2</c></seemfa>
+ (instead of through the callback function's return value)
+ to the process <c><anno>Client</anno></c>
+ that has called the <c>gen_server</c> using
+ <seemfa marker="#call/2"><c>call/2,3</c></seemfa>.
+ <c><anno>Tag</anno></c> is a term that is unique
+ for this call/request instance.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="reply_tag"/>
+ <desc>
+ <p>
+ A handle that associates a reply to the corresponding request.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="request_id"/>
+ <desc>
+ <p>
+ An opaque request identifier. See
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ for details.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="request_id_collection"/>
+ <desc>
+ <p>
+ An opaque collection of request identifiers
+ (<seetype marker="#request_id"><c>request_id()</c></seetype>)
+ where each request identifier can be associated with a label
+ chosen by the user. For more information see
+ <seemfa marker="#reqids_new/0"><c>reqids_new/0</c></seemfa>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="response_timeout"/>
+ <desc>
+ <p>
+ Used to set a time limit on how long to wait for a response using
+ either
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ or
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ The time unit used is <c>millisecond</c>. Currently valid values:
+ </p>
+ <taglist>
+ <tag><c>0..4294967295</c></tag>
+ <item><p>
+ Timeout relative to current time in milliseconds.
+ </p></item>
+ <tag><c>infinity</c></tag>
+ <item><p>
+ Infinite timeout. That is, the operation will never time out.
+ </p></item>
+ <tag><c>{abs, Timeout}</c></tag>
+ <item><p>
+ An absolute
+ <seemfa marker="erts:erlang#monotonic_time/1">Erlang monotonic time</seemfa>
+ timeout in milliseconds. That is, the operation will time out when
+ <seemfa marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time(millisecond)</c></seemfa>
+ returns a value larger than or equal to <c>Timeout</c>. <c>Timeout</c>
+ is not allowed to identify a time further into the future than <c>4294967295</c>
+ milliseconds. Identifying the timeout using an absolute timeout value
+ is especially handy when you have a deadline for responses corresponding
+ to a complete collection of requests
+ (<seetype marker="#request_id_collection"><c>request_id_collection()</c></seetype>)
+,
+ since you do not have to recalculate the relative time until the deadline
+ over and over again.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="format_status"/>
+ <desc>
+ <p>
+ A map that describes the <c>gen_server</c> status.
+ The keys are:
+ </p>
+ <taglist>
+ <tag><c>state</c></tag>
+ <item>The internal state of the <c>gen_server</c> process.</item>
+ <tag><c>message</c></tag>
+ <item>The message that caused the server to terminate.</item>
+ <tag><c>reason</c></tag>
+ <item>The reason that caused the server to terminate.</item>
+ <tag><c>log</c></tag>
+ <item>
+ The <seemfa marker="sys#log/2">sys log</seemfa> of the server.
+ </item>
+ </taglist>
+ <p>
+ New associations may be added to the status map
+ without prior notice.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+
+
<funcs>
<func>
- <name since="">abcast(Name, Request) -> abcast</name>
- <name since="">abcast(Nodes, Name, Request) -> abcast</name>
- <fsummary>Send an asynchronous request to many generic servers.</fsummary>
- <type>
- <v>Nodes = [Node]</v>
- <v>&nbsp;Node = atom()</v>
- <v>Name = atom()</v>
- <v>Request = term()</v>
- </type>
+ <name name="abcast" arity="2" since=""/>
+ <name name="abcast" arity="3" since=""/>
+ <fsummary>
+ Send an asynchronous request to many generic servers.
+ </fsummary>
<desc>
- <p>Sends an asynchronous request to the <c>gen_server</c> processes
- locally registered as <c>Name</c> at the specified nodes. The function
+ <p>
+ Sends an asynchronous request to the <c>gen_server</c> processes
+ locally registered as <c><anno>Name</anno></c>
+ at the specified nodes. The function
returns immediately and ignores nodes that do not exist, or
- where the <c>gen_server</c> <c>Name</c> does not exist.
+ where the <c>gen_server</c>
+ <c><anno>Name</anno></c> does not exist.
The <c>gen_server</c> processes call
<seemfa marker="#Module:handle_cast/2">
- <c>Module:handle_cast/2</c></seemfa> to handle the request.</p>
- <p>For a description of the arguments, see
- <seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>.</p>
+ <c>Module:handle_cast/2</c>
+ </seemfa> to handle the request.
+ </p>
+ <p>
+ For a description of the arguments, see
+ <seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>.
+ </p>
</desc>
</func>
<func>
- <name since="">call(ServerRef, Request) -> Reply</name>
- <name since="">call(ServerRef, Request, Timeout) -> Reply</name>
+ <name name="call" arity="2" since=""/>
+ <name name="call" arity="3" since=""/>
<fsummary>Make a synchronous call to a generic server.</fsummary>
- <type>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Request = term()</v>
- <v>Timeout = int()>0 | infinity</v>
- <v>Reply = term()</v>
- </type>
<desc>
- <p>Makes a synchronous call to the <c>ServerRef</c> of the
- <c>gen_server</c> process
+ <p>
+ Makes a synchronous call to the
+ <c><anno>ServerRef</anno></c> of the <c>gen_server</c> process
by sending a request and waiting until a reply arrives or a
time-out occurs. The <c>gen_server</c> process calls
<seemfa marker="#Module:handle_call/3">
- <c>Module:handle_call/3</c></seemfa> to handle the request.</p>
- <p><c>ServerRef</c> can be any of the following:</p>
- <list type="bulleted">
- <item>The pid</item>
- <item><c>Name</c>, if the <c>gen_server</c> process is locally
- registered</item>
- <item><c>{Name,Node}</c>, if the <c>gen_server</c> process is locally
- registered at another node</item>
- <item><c>{global,GlobalName}</c>, if the <c>gen_server</c> process is
- globally registered</item>
- <item><c>{via,Module,ViaName}</c>, if the <c>gen_server</c> process is
- registered through an alternative process registry</item>
- </list>
- <p><c>Request</c> is any term that is passed as the
- first argument to <c>Module:handle_call/3</c>.</p>
- <p><c>Timeout</c> is an integer greater than zero that
+ <c>Module:handle_call/3</c>
+ </seemfa>
+ to handle the request.
+ </p>
+ <p>
+ See also <c><anno>ServerRef</anno></c>'s type
+ <seetype marker="#server_ref"><c>server_ref()</c></seetype>.
+ </p>
+ <p>
+ <c><anno>Request</anno></c> is any term that is passed as the
+ first argument to <c>Module:handle_call/3</c>.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> is an integer that
specifies how many milliseconds to wait for a reply, or
- the atom <c>infinity</c> to wait indefinitely. Defaults to
- 5000. If no reply is received within the specified time,
- the function call fails. If the caller catches the failure
- and continues running, and the server is just late with the reply,
- it can arrive at any time later into the message queue of the caller.
- The caller must in this case be prepared for this
- and discard any such garbage messages that are two element
- tuples with a reference as the first element.</p>
- <p>The return value <c>Reply</c> is defined in the return value
- of <c>Module:handle_call/3</c>.</p>
- <p>The call can fail for many reasons, including time-out and the
- called <c>gen_server</c> process dying before or during the call.</p>
+ the atom <c>infinity</c> to wait indefinitely.
+ Defaults to 5000.
+ If no reply is received within the specified time,
+ this function exits the calling process with an exit term
+ containing <c>Reason&nbsp;=&nbsp;timeout</c> as described below.
+ </p>
+ <note>
+ <p>
+ Before OTP 24, if the caller uses (<c>try</c>...)<c>catch</c>
+ to avoid process exit,
+ and the server happens to just be late with the reply,
+ it may arrive to the process message queue any time later.
+ The calling process must therefore after catching a time-out exit
+ be prepared to receive garbage message(s)
+ on the form <c>{reference(),&nbsp;_}</c>
+ and deal with them appropriately (discard them)
+ so they do not clog the process message queue
+ or gets mistaken for other messages.
+ </p>
+ <p>
+ Starting with OTP 24, <c>gen_server:call</c> uses process aliases,
+ so late replies will not be received.
+ </p>
+ </note>
+ <p>
+ The return value <c><anno>Reply</anno></c>
+ is passed from the return value of <c>Module:handle_call/3</c>.
+ </p>
+ <p>
+ This call may exit the calling process
+ with an exit term on the form
+ <c>{Reason,&nbsp;Location}</c> where
+ <c>Location&nbsp;=&nbsp;{gen_server,call,ArgList}</c>
+ and <c>Reason</c> can be (at least) one of:
+ </p>
+ <taglist>
+ <tag><c>timeout</c></tag>
+ <item>
+ <p>
+ The call was aborted after waiting
+ <c><anno>Timeout</anno></c> milliseconds for a reply,
+ as described above.
+ </p>
+ </item>
+ <tag><c>noproc</c></tag>
+ <item>
+ <p>
+ The <c><anno>ServerRef</anno></c> refers to
+ a server by name (it is not a <c>pid()</c>)
+ and looking up the server process failed,
+ or the <c>pid()</c> was already terminated.
+ </p>
+ </item>
+ <tag><c>{nodedown,Node}</c></tag>
+ <item>
+ <p>
+ The <c><anno>ServerRef</anno></c> refers to a server
+ on the remote node <c>Node</c> and the connection
+ to that node failed.
+ </p>
+ </item>
+ <tag><c>calling_self</c></tag>
+ <item>
+ <p>A call to <c>self()</c> would hang indefinitely.</p>
+ </item>
+ <tag>
+ <c>shutdown</c><br/>
+ </tag>
+ <item>
+ <p>
+ The server was stopped during the call
+ by its supervisor. See also
+ <seemfa marker="#stop/3"><c>stop/3</c></seemfa>.
+ </p>
+ </item>
+ <tag>
+ <c>normal</c><br/>
+ <c>{shutdown,Term}</c><br/>
+ </tag>
+ <item>
+ <p>
+ The server stopped during the call by returning
+ <c>{stop,Reason,_}</c> from its
+ <seemfa marker="#Module:handle_call/3">
+ <c>Module:handle_call/3</c>
+ </seemfa>
+ callback, without replying. See also
+ <seemfa marker="#stop/3"><c>stop/3</c></seemfa>.
+ </p>
+ </item>
+ <tag><c>_OtherTerm</c></tag>
+ <item>
+ <p>
+ The server process exited during the call,
+ with reason <c>Reason</c>. Either by returning
+ <c>{stop,Reason,_}</c> from its
+ <seemfa marker="#Module:handle_call/3">
+ <c>Module:handle_call/3</c>
+ </seemfa>
+ callback (without replying),
+ by raising an exception,
+ or due to getting an exit signal it did not trap.
+ </p>
+ </item>
+ </taglist>
</desc>
</func>
<func>
- <name since="">cast(ServerRef, Request) -> ok</name>
+ <name name="cast" arity="2" since=""/>
<fsummary>Send an asynchronous request to a generic server.</fsummary>
- <type>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Request = term()</v>
- </type>
<desc>
- <p>Sends an asynchronous request to the <c>ServerRef</c> of the
- <c>gen_server</c> process
- and returns <c>ok</c> immediately, ignoring
- if the destination node or <c>gen_server</c> process does not exist.
+ <p>
+ Sends an asynchronous request to the
+ <c><anno>ServerRef</anno></c> of the
+ <c>gen_server</c> process and returns <c>ok</c> immediately,
+ ignoring if the destination node or <c>gen_server</c> process
+ does not exist.
The <c>gen_server</c> process calls
<seemfa marker="#Module:handle_cast/2">
- <c>Module:handle_cast/2</c></seemfa> to handle the request.</p>
- <p>For a description of <c>ServerRef</c>, see
- <seemfa marker="#call/2"><c>call/2,3</c></seemfa>.</p>
- <p><c>Request</c> is any term that is passed as one
- of the arguments to <c>Module:handle_cast/2</c>.</p>
+ <c>Module:handle_cast/2</c>
+ </seemfa>
+ to handle the request.
+ </p>
+ <p>
+ See also <c><anno>ServerRef</anno></c>'s type
+ <seetype marker="#server_ref"><c>server_ref()</c></seetype>.
+ </p>
+ <p>
+ <c><anno>Request</anno></c> is any term that is passed as
+ the first argument to <c>Module:handle_cast/2</c>.
+ </p>
</desc>
</func>
<func>
- <name since="OTP-23">check_response(Msg, RequestId) -> Result</name>
- <fsummary>Check if a message is a reply from a server.</fsummary>
- <type>
- <v>RequestId = term()</v>
- <v>Result = {reply, Reply} | no_reply | {error, {Reason, ServerRef}}</v>
- <v>Msg = Reply = term()</v>
- <v>Timeout = timeout()</v>
- <v>Reason = term()</v>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- </type>
+ <name name="check_response" arity="2" since="OTP 23.0"/>
+ <fsummary>Check if a message is a response from a server.</fsummary>
<desc>
<p>
- This function is used to check if a previously received
- message, for example by <c>receive</c> or
- <c>handle_info/2</c>, is a result of a request made with
- <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>.
- If <c>Msg</c> is a reply to the handle <c>RequestId</c>
- the result of the request is returned in <c>Reply</c>.
- Otherwise returns <c>no_reply</c> and no cleanup is done, and
- thus the function must be invoked repeatedly until a reply
- is returned.
+ Check if <c><anno>Msg</anno></c> is a response corresponding
+ to the request identifier <c><anno>ReqId</anno></c>. The request
+ must have been made by
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>,
+ and it must have been made by the same process calling
+ this function.
</p>
+ <p>
+ If <c><anno>Msg</anno></c> is a response corresponding to
+ <c><anno>ReqId</anno></c> the response is returned; otherwise,
+ <c>no_reply</c> is returned and no cleanup is done, and
+ thus the function must be invoked repeatedly until a response
+ is returned.
+ </p>
<p>
- The return value <c>Reply</c> is defined in the return value
- of <c>Module:handle_call/3</c>.
+ The return value <c><anno>Reply</anno></c> is passed from the
+ return value of <c>Module:handle_call/3</c>.
</p>
<p>
The function returns an error if the <c>gen_server</c>
- dies before or during this request.
+ died before a reply was sent.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="check_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Check if a message is a response from a server.</fsummary>
+ <desc>
+ <p>
+ Check if <c><anno>Msg</anno></c> is a response corresponding
+ to a request identifier saved in <c><anno>ReqIdCollection</anno></c>.
+ All request identifiers of <c><anno>ReqIdCollection</anno></c>
+ must correspond to requests that have been made using
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
</p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">saving the request id</seemfa>
+ in a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>check_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned. If <c><anno>Msg</anno></c>
+ does not correspond to any of the request identifiers in
+ <c><anno>ReqIdCollection</anno></c>, the atom
+ <c>no_reply</c> is returned.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>check_response/3</c>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>check_response/3</c>, it will always
+ return <c>no_reply</c>.
+ </p>
</desc>
</func>
<func>
- <name since="">enter_loop(Module, Options, State)</name>
- <name since="">enter_loop(Module, Options, State, ServerName)</name>
- <name since="">enter_loop(Module, Options, State, Timeout)</name>
- <name since="">enter_loop(Module, Options, State, ServerName, Timeout)</name>
+ <name name="enter_loop" arity="3" since=""/>
+ <name name="enter_loop" arity="4" clause_i="1" since=""/>
+ <name name="enter_loop" arity="4" clause_i="2" since=""/>
+ <name name="enter_loop" arity="4" clause_i="3" since=""/>
+ <name name="enter_loop" arity="4" clause_i="4" since=""/>
+ <name name="enter_loop" arity="5" clause_i="1" since=""/>
+ <name name="enter_loop" arity="5" clause_i="2" since=""/>
+ <name name="enter_loop" arity="5" clause_i="3" since=""/>
<fsummary>Enter the <c>gen_server</c> receive loop.</fsummary>
- <type>
- <v>Module = atom()</v>
- <v>Options = [Option]</v>
- <v>&nbsp;Option = {debug,Dbgs} | {hibernate_after,HibernateAfterTimeout}</v>
- <v>&nbsp;&nbsp;Dbgs = [Dbg]</v>
- <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>&nbsp;&nbsp;| {via,Module,ViaName}</v>
- <v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Timeout = int() | infinity</v>
- </type>
<desc>
- <p>Makes an existing process into a <c>gen_server</c> process. Does not
- return, instead the calling process enters the <c>gen_server</c>
- process receive
- loop and becomes a <c>gen_server</c> process. The process
- <em>must</em> have been started using one of the start functions in
- <seeerl marker="proc_lib"><c>proc_lib(3)</c></seeerl>. The user is
- responsible for any initialization of the process, including
- registering a name for it.</p>
- <p>This function is useful when a more complex initialization procedure
- is needed than the <c>gen_server</c> process behavior provides.</p>
- <p><c>Module</c>, <c>Options</c>, and <c>ServerName</c> have
+ <p>
+ Makes an existing process a <c>gen_server</c> process.
+ Does not return, instead the calling process enters
+ the <c>gen_server</c> process receive loop
+ and becomes a <c>gen_server</c> process.
+ The process <em>must</em> have been started using
+ one of the start functions in
+ <seeerl marker="proc_lib"><c>proc_lib(3)</c></seeerl>.
+ The user is responsible for any initialization of the process,
+ including registering a name for it.
+ </p>
+ <p>
+ This function is useful when a more complex
+ initialization procedure is needed
+ than the <c>gen_server</c> process behavior provides.
+ </p>
+ <p>
+ <c><anno>Module</anno></c>, <c><anno>Options</anno></c>,
+ and <c><anno>ServerName</anno></c> have
the same meanings as when calling
- <seemfa marker="#start_link/3"><c>start[_link|_monitor]/3,4</c></seemfa>.
- However, if <c>ServerName</c> is specified, the process must
- have been registered accordingly <em>before</em> this function
- is called.</p>
- <p><c>State</c> and <c>Timeout</c> have the same meanings as in
+ <seemfa marker="#start_link/3">
+ <c>start[_link|_monitor]/3,4</c>
+ </seemfa>
+ or it can be <c>self()</c> for an anonymous server,
+ which is the same as calling an <c>enter_loop/3,4</c> function
+ without a <c><anno>ServerName</anno></c> argument.
+ However, if <c><anno>ServerName</anno></c> is specified
+ (and not as <c>self()</c>),
+ the process must have been registered accordingly
+ <em>before</em> this function is called.
+ </p>
+ <p>
+ <c><anno>State</anno></c>, <c><anno>Timeout</anno></c>,
+ <c><anno>Hibernate</anno></c> and <c><anno>Cont</anno></c> have the same meanings as in
the return value of
- <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>.
- The callback module <c>Module</c> does not need to
- export an <c>init/1</c> function.</p>
- <p>The function fails if the calling process was not started by a
+ <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>,
+ which is <em>not</em> called when <c>enter_loop/3,4,5</c> is used.
+ Note that to adhere to the
+ <seeguide marker="system/design_principles:gen_server_concepts">
+ gen_server Behaviour
+ </seeguide>
+ such a callback function needs to be defined,
+ and it might as well be the one used when starting
+ the <c>gen_server</c> process through <c>proc_lib</c>,
+ and then be the one that calls <c>enter_loop/3,4,5</c>.
+ But if such a <c>Module:init/1</c> function
+ in for example error cases cannot call
+ <c>enter_loop/3,4,5</c>, it should return a value
+ that follows the type specification for
+ <c>Module:init/1</c> such as <c>ignore</c>,
+ although that value will be lost
+ when returning to the spawning function.
+ </p>
+ <p>
+ This function fails if the calling process was not started by a
<c>proc_lib</c> start function, or if it is not registered
- according to <c>ServerName</c>.</p>
+ according to <c><anno>ServerName</anno></c>.
+ </p>
</desc>
</func>
<func>
- <name since="">multi_call(Name, Request) -> Result</name>
- <name since="">multi_call(Nodes, Name, Request) -> Result</name>
- <name since="">multi_call(Nodes, Name, Request, Timeout) -> Result</name>
+ <name name="multi_call" arity="2" since=""/>
+ <name name="multi_call" arity="3" since=""/>
+ <name name="multi_call" arity="4" since=""/>
<fsummary>Make a synchronous call to many generic servers.</fsummary>
- <type>
- <v>Nodes = [Node]</v>
- <v>&nbsp;Node = atom()</v>
- <v>Name = atom()</v>
- <v>Request = term()</v>
- <v>Timeout = int()>=0 | infinity</v>
- <v>Result = {Replies,BadNodes}</v>
- <v>&nbsp;Replies = [{Node,Reply}]</v>
- <v>&nbsp;&nbsp;Reply = term()</v>
- <v>BadNodes = [Node]</v>
- </type>
<desc>
- <p>Makes a synchronous call to all <c>gen_server</c> processes locally
- registered as <c>Name</c> at the specified nodes by first
- sending a request to every node and then waits for
- the replies. The <c>gen_server</c> process calls
+ <p>
+ Makes a synchronous call to all <c>gen_server</c> processes
+ locally registered as <c><anno>Name</anno></c>
+ at the specified nodes,
+ by first sending the request to the nodes,
+ and then waiting for the replies.
+ The <c>gen_server</c> processes on the nodes call
<seemfa marker="#Module:handle_call/3">
- <c>Module:handle_call/3</c></seemfa> to handle the request.</p>
- <p>The function returns a tuple <c>{Replies,BadNodes}</c>, where
- <c>Replies</c> is a list of <c>{Node,Reply}</c> and
- <c>BadNodes</c> is a list of node that either did not exist,
- or where the <c>gen_server</c> <c>Name</c> did not exist or did not
- reply.</p>
- <p><c>Nodes</c> is a list of node names to which the request
- is to be sent. Default value is the list of all known nodes
- <c>[node()|nodes()]</c>.</p>
- <p><c>Name</c> is the locally registered name of each
- <c>gen_server</c> process.</p>
- <p><c>Request</c> is any term that is passed as the first
- argument to <c>Module:handle_call/3</c>.</p>
- <p><c>Timeout</c> is an integer greater than zero that
- specifies how many milliseconds to wait for each reply, or
- the atom <c>infinity</c> to wait indefinitely. Defaults
- to <c>infinity</c>. If no reply is received from a node within
- the specified time, the node is added to <c>BadNodes</c>.</p>
- <p>When a reply <c>Reply</c> is received from the <c>gen_server</c>
- process at a node <c>Node</c>, <c>{Node,Reply}</c> is added to
- <c>Replies</c>. <c>Reply</c> is defined in the return value of
- <c>Module:handle_call/3</c>.</p>
+ <c>Module:handle_call/3</c>
+ </seemfa>
+ to handle the request.
+ </p>
+ <p>
+ The function returns a tuple
+ <c>{<anno>Replies</anno>,<anno>BadNodes</anno>}</c>,
+ where <c><anno>Replies</anno></c> is a list of
+ <c>{<anno>Node</anno>,<anno>Reply</anno>}</c> tuples,
+ and <c><anno>BadNodes</anno></c> is a list of nodes
+ that either did not exist,
+ where <c><anno>Name</anno></c>
+ was not a registered <c>gen_server</c>,
+ or where it did not reply.
+ </p>
+ <p>
+ <c><anno>Nodes</anno></c> is a list of node names
+ to which the request is to be sent.
+ Default value is the list of all known nodes
+ <c>[node()|nodes()]</c>.
+ </p>
+ <p>
+ <c><anno>Name</anno></c> is the locally registered name
+ for each <c>gen_server</c> process.
+ </p>
+ <p>
+ <c><anno>Request</anno></c> is any term that is passed
+ as the first argument to <c>Module:handle_call/3</c>.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> is an integer that
+ specifies how many milliseconds to wait for all replies,
+ or the atom <c>infinity</c> to wait indefinitely,
+ which is the default.
+ If no reply is received from a node within the specified time,
+ the node is added to <c><anno>BadNodes</anno></c>.
+ </p>
+ <p>
+ When a reply <c><anno>Reply</anno></c> is received
+ from the <c>gen_server</c> process
+ at a node <c><anno>Node</anno></c>,
+ <c>{<anno>Node</anno>,<anno>Reply</anno>}</c> is added to
+ <c><anno>Replies</anno></c>.
+ <c><anno>Reply</anno></c> is passed from the return value of
+ <c>Module:handle_call/3</c>.
+ </p>
<warning>
- <p>If one of the nodes cannot process monitors, for example,
+ <p>
+ If one of the nodes cannot process monitors, for example,
C or Java nodes, and the <c>gen_server</c> process is not started
when the requests are sent, but starts within 2 seconds,
this function waits the whole <c>Timeout</c>,
- which may be infinity.</p>
+ which may be infinity.
+ </p>
<p>This problem does not exist if all nodes are Erlang nodes.</p>
</warning>
- <p>To prevent late answers (after the time-out) from polluting
- the message queue of the caller, a middleman process is used to
- do the calls. Late answers are then discarded
- when they arrive to a terminated process.</p>
+ <p>
+ To prevent late answers (after the time-out) from polluting
+ the message queue of the caller, a middleman process is used
+ to do the calls. Late answers are then discarded
+ when they arrive to a terminated process.
+ </p>
</desc>
</func>
<func>
- <name since="OTP 24.0">receive_response(RequestId, Timeout) -> Result</name>
- <fsummary>Receive for a reply from a server.</fsummary>
- <type>
- <v>RequestId = term()</v>
- <v>Result = {reply, Reply} | timeout | {error, {Reason, ServerRef}}</v>
- <v>Reply = term()</v>
- <v>Timeout = timeout()</v>
- <v>Reason = term()</v>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- </type>
+ <name name="receive_response" arity="2" since="OTP 24.0"/>
+ <fsummary>Receive a response from a server.</fsummary>
<desc>
<p>
- This function is used to receive a reply of a request made with
- <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
- to a <c>gen_server</c> process. This function must be called
- from the same process from which
- <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
- was made.
+ Receive a response corresponding to the request identifier
+ <c><anno>ReqId</anno></c>. The request must have been made by
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>,
+ and it must have been made by the same process calling
+ this function.
</p>
<p>
- <c>Timeout</c> is an integer greater then or equal to zero
- that specifies how many milliseconds to wait for an reply, or
- the atom <c>infinity</c> to wait indefinitely.
- If no reply is received within the specified
- time, the function returns <c>timeout</c>. Assuming that the
+ <c><anno>Timeout</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified time,
+ the function returns <c>timeout</c>. Assuming that the
server executes on a node supporting aliases (introduced in
- OTP 24) no response will be received after a timeout. Otherwise,
- a garbage response might be received at a later time.
+ OTP 24) the request will also be abandoned. That is, no
+ response will be received after a timeout. Otherwise, a
+ stray response might be received at a later time.
</p>
<p>
- The return value <c>Reply</c> is defined in the return value
- of <c>Module:handle_call/3</c>.
+ The return value <c><anno>Reply</anno></c> is passed from the
+ return value of <c>Module:handle_call/3</c>.
</p>
<p>
The function returns an error if the <c>gen_server</c>
- dies before or during this request.
+ died before a reply was sent.
</p>
<p>
- The difference between
- <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa>
- and <c>receive_response()</c> is that <c>receive_response()</c>
- abandons the request at timeout so that a potential future
- response is ignored, while <c>wait_response()</c> does not.
+ The difference between <c>receive_response/2</c> and
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>
+ is that <c>receive_response/2</c> abandons the request at
+ timeout so that a potential future response is ignored, while
+ <c>wait_response/2</c> does not.
</p>
</desc>
</func>
<func>
- <name since="">reply(Client, Reply) -> ok</name>
+ <name name="receive_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Receive a response from a server.</fsummary>
+ <desc>
+ <p>
+ Receive a response corresponding to a request identifier saved
+ in <c><anno>ReqIdCollection</anno></c>. All request identifiers
+ of <c><anno>ReqIdCollection</anno></c> must correspond to requests
+ that have been made using
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">adding the request id</seemfa>
+ in a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ will be wrapped in a 3-tuple. The first element of this tuple equals
+ the value that would have been produced by <c>receive_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified time,
+ the function returns <c>timeout</c>. Assuming that the
+ server executes on a node supporting aliases (introduced in
+ OTP 24) all requests identified by <c><anno>ReqIdCollection</anno></c>
+ will also be abandoned. That is, no responses will be received
+ after a timeout. Otherwise, stray responses might be received
+ at a later time.
+ </p>
+ <p>
+ The difference between <c>receive_response/3</c> and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>
+ is that <c>receive_response/3</c> abandons the requests at timeout
+ so that potential future responses are ignored, while
+ <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>receive_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>receive_response/3</c>, it will always block
+ until a timeout determined by <c><anno>Timeout</anno></c> is
+ triggered.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reply" arity="2" since=""/>
<fsummary>Send a reply to a client.</fsummary>
- <type>
- <v>Client - see below</v>
- <v>Reply = term()</v>
- </type>
<desc>
- <p>This function can be used by a <c>gen_server</c> process to
+ <p>
+ This function can be used by a <c>gen_server</c> process to
explicitly send a reply to a client that called
<seemfa marker="#call/2"><c>call/2,3</c></seemfa> or
<seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>,
- when the reply cannot be defined in the return value of
+ when the reply cannot be passed in the return value of
<seemfa marker="#Module:handle_call/3">
- <c>Module:handle_call/3</c></seemfa>.</p>
- <p><c>Client</c> must be the <c>From</c> argument provided to
- the callback function. <c>Reply</c> is any term
- given back to the client as the return value of
- <c>call/2,3</c> or <c>multi_call/2,3,4</c>.</p>
+ <c>Module:handle_call/3</c></seemfa>.
+ </p>
+ <p>
+ <c><anno>Client</anno></c> must be the <c>From</c> argument
+ provided to the <c>handle_call</c> callback function.
+ <c><anno>Reply</anno></c> is any term
+ passed back to the client as the return value of
+ <c>call/2,3</c> or <c>multi_call/2,3,4</c>.
+ </p>
</desc>
</func>
<func>
- <name since="OTP 23.0">send_request(ServerRef, Request) -> RequestId</name>
+ <name name="reqids_add" arity="3" since="OTP 25.0"/>
+ <fsummary>Save a request identifier.</fsummary>
+ <desc>
+ <p>
+ Saves <c><anno>ReqId</anno></c> and associates a <c><anno>Label</anno></c>
+ with the request identifier by adding this information to
+ <c><anno>ReqIdCollection</anno></c> and returning the
+ resulting request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_new" arity="0" since="OTP 25.0"/>
+ <fsummary>Create a new empty request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns a new empty request identifier collection. A
+ request identifier collection can be utilized in order
+ the handle multiple outstanding requests.
+ </p>
+ <p>
+ Request identifiers of requests made by
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ can be saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+ <p>
+ <seemfa marker="#reqids_size/1"><c>reqids_size/1</c></seemfa>
+ can be used to determine the amount of request identifiers in a
+ request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_size" arity="1" since="OTP 25.0"/>
+ <fsummary>Get size of a request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns the amount of request identifiers saved in
+ <c><anno>ReqIdCollection</anno></c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_to_list" arity="1" since="OTP 25.0"/>
+ <fsummary>List a request identifiers.</fsummary>
+ <desc>
+ <p>
+ Returns a list of <c>{<anno>ReqId</anno>, <anno>Label</anno>}</c>
+ tuples which corresponds to all request identifiers with their
+ associated labels present in the <c><anno>ReqIdCollection</anno></c>
+ collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send_request" arity="2" since="OTP 23.0"/>
<fsummary>Sends a request to a generic server.</fsummary>
- <type>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>RequestId = term()</v>
- <v>Timeout = int()>0 | infinity</v>
- <v>Request = term()</v>
- </type>
<desc>
<p>
- Sends a request to the <c>ServerRef</c> of the
- <c>gen_server</c> process and returns a handle <c>RequestId</c>.
- The return value <c>RequestId</c> shall later be used with
+ Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c>
+ to the <c>gen_server</c> process identified by <c><anno>ServerRef</anno></c>
+ and returns a request identifier <c><anno>ReqId</anno></c>. The return
+ value <c><anno>ReqId</anno></c> shall later be used with
<seemfa marker="#receive_response/2"> <c>receive_response/2</c></seemfa>,
<seemfa marker="#wait_response/2"> <c>wait_response/2</c></seemfa>, or
<seemfa marker="#check_response/2"> <c>check_response/2</c></seemfa>
- to fetch the actual result of the request.
+ to fetch the actual result of the request. Besides passing
+ the request identifier directly to these functions, it can also be
+ saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>, or
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ If you are about to save the request identifier in a request identifier
+ collection, you may want to consider using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>
+ instead.
</p>
<p>
- The call <c>gen_server:wait_response(gen_server:send_request(ServerRef,Request), Timeout)</c>
- can be seen as equivalent to
- <seemfa marker="#call/3"><c>gen_server:call(Server,Request,Timeout)</c></seemfa>,
- ignoring the error handling.
+ The call <c>gen_server:receive_response(gen_server:send_request(<anno>ServerRef</anno>,
+ <anno>Request</anno>), Timeout)</c> can be seen as equivalent to
+ <seemfa marker="#call/3"><c>gen_server:call(<anno>ServerRef</anno>, <anno>Request</anno>,
+ Timeout)</c></seemfa>, ignoring the error handling.
</p>
<p>
The <c>gen_server</c> process calls
- <seemfa marker="#Module:handle_call/3"> <c>Module:handle_call/3</c></seemfa>
+ <seemfa marker="#Module:handle_call/3">
+ <c>Module:handle_call/3</c>
+ </seemfa>
to handle the request.
</p>
- <p><c>ServerRef</c> can be any of the following:</p>
- <list type="bulleted">
- <item>The pid</item>
- <item><c>Name</c>, if the <c>gen_server</c> process is locally
- registered</item>
- <item><c>{Name,Node}</c>, if the <c>gen_server</c> process is locally
- registered at another node</item>
- <item><c>{global,GlobalName}</c>, if the <c>gen_server</c> process is
- globally registered</item>
- <item><c>{via,Module,ViaName}</c>, if the <c>gen_server</c> process is
- registered through an alternative process registry</item>
- </list>
- <p><c>Request</c> is any term that is passed as the first
- argument to <c>Module:handle_call/3</c>.</p>
+ <p>
+ See the type
+ <seetype marker="#server_ref"><c>server_ref()</c></seetype>
+ for the possible values for <c><anno>ServerRef</anno></c>.
+ </p>
+ <p>
+ <c><anno>Request</anno></c> is any term that is passed
+ as the first argument to <c>Module:handle_call/3</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send_request" arity="4" since="OTP 25.0"/>
+ <fsummary>Sends a request to a generic server.</fsummary>
+ <desc>
+ <p>
+ Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c>
+ to the <c>gen_server</c> process identified by <c><anno>ServerRef</anno></c>.
+ The <c><anno>Label</anno></c> will be associated with the request
+ identifier of the operation and added to the returned request
+ identifier collection <c><anno>NewReqIdCollection</anno></c>.
+ The collection can later be used in order to get one response
+ corresponding to a request in the collection by passing the
+ collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+
+ <p>
+ The same as calling
+ <seemfa marker="#reqids_add/3"><c>gen_server:reqids_add</c></seemfa>(<seemfa
+ marker="#send_request/2"><c>gen_server:send_request</c></seemfa><c>(<anno>ServerRef</anno>,
+ <anno>Request</anno>), <anno>Label</anno>,
+ <anno>ReqIdCollection</anno>)</c>, but calling <c>send_request/4</c>
+ is slightly more efficient.
+ </p>
</desc>
</func>
<func>
- <name since="">start(Module, Args, Options) -> Result</name>
- <name since="">start(ServerName, Module, Args, Options) -> Result</name>
+ <name name="start" arity="3" since=""/>
+ <name name="start" arity="4" since=""/>
<fsummary>Create a standalone <c>gen_server</c> process.</fsummary>
- <type>
- <v>ServerName = {local,Name} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName}</v>
- <v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Module = atom()</v>
- <v>Args = term()</v>
- <v>Options = [Option]</v>
- <v>&nbsp;Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}</v>
- <v>&nbsp;&nbsp;Dbgs = [Dbg]</v>
- <v>&nbsp;&nbsp;&nbsp;Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}</v>
- <v>&nbsp;&nbsp;SOpts = [term()]</v>
- <v>Result = {ok,Pid} | ignore | {error,Error}</v>
- <v>&nbsp;Pid = pid()</v>
- <v>&nbsp;Error = {already_started,Pid} | term()</v>
- </type>
<desc>
- <p>Creates a standalone <c>gen_server</c> process, that is, a
+ <p>
+ Creates a standalone <c>gen_server</c> process, that is, a
<c>gen_server</c> process that is not part of a supervision tree
and thus has no supervisor.</p>
- <p>For a description of arguments and return values, see
- <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.</p>
+ <p>
+ Other than that see
+ <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.
+ </p>
</desc>
</func>
<func>
- <name since="">start_link(Module, Args, Options) -> Result</name>
- <name since="">start_link(ServerName, Module, Args, Options) -> Result</name>
- <fsummary>Create a <c>gen_server</c> process in a supervision tree.
+ <name name="start_link" arity="3" since=""/>
+ <name name="start_link" arity="4" since=""/>
+ <fsummary>
+ Create a <c>gen_server</c> process in a supervision tree.
</fsummary>
- <type>
- <v>ServerName = {local,Name} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName}</v>
- <v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Module = atom()</v>
- <v>Args = term()</v>
- <v>Options = [Option]</v>
- <v>&nbsp;Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}</v>
- <v>&nbsp;&nbsp;Dbgs = [Dbg]</v>
- <v>&nbsp;&nbsp;&nbsp;Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}</v>
- <v>&nbsp;&nbsp;SOpts = [term()]</v>
- <v>Result = {ok,Pid} | ignore | {error,Error}</v>
- <v>&nbsp;Pid = pid()</v>
- <v>&nbsp;Error = {already_started,Pid} | term()</v>
- </type>
<desc>
- <p>Creates a <c>gen_server</c> process as part of a supervision tree.
+ <p>
+ Creates a <c>gen_server</c> process as part of a supervision tree.
This function is to be called, directly or indirectly, by
the supervisor. For example, it ensures that
- the <c>gen_server</c> process is linked to the supervisor.</p>
- <p>The <c>gen_server</c> process calls
- <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa> to
- initialize. To ensure a synchronized startup procedure,
+ the <c>gen_server</c> process is linked to the supervisor.
+ </p>
+ <p>
+ The <c>gen_server</c> process calls
+ <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>
+ to initialize.
+ To ensure a synchronized startup procedure,
<c>start_link/3,4</c> does not return until
- <c>Module:init/1</c> has returned.</p>
- <list type="bulleted">
- <item>
- <p>If <c>ServerName={local,Name}</c>, the <c>gen_server</c> process
- is registered locally as <c>Name</c> using <c>register/2</c>.</p>
- </item>
- <item>
- <p>If <c>ServerName={global,GlobalName}</c>, the <c>gen_server</c>
- process id registered globally as <c>GlobalName</c> using
- <seemfa marker="kernel:global#register_name/2">
- <c>global:register_name/2</c></seemfa> If no name is
- provided, the <c>gen_server</c> process is not registered.</p>
- </item>
- <item>
- <p>If <c>ServerName={via,Module,ViaName}</c>, the <c>gen_server</c>
- process registers with the registry represented by <c>Module</c>.
- The <c>Module</c> callback is to export the functions
- <c>register_name/2</c>, <c>unregister_name/1</c>,
- <c>whereis_name/1</c>, and <c>send/2</c>, which are to behave
- like the corresponding functions in
- <seeerl marker="kernel:global"><c>global</c></seeerl>.
- Thus, <c>{via,global,GlobalName}</c> is a valid reference.</p>
- </item>
- </list>
- <p><c>Module</c> is the name of the callback module.</p>
- <p><c>Args</c> is any term that is passed as
+ <c>Module:init/1</c> has returned.
+ </p>
+ <p>
+ Using the argument <c><anno>ServerName</anno></c>
+ creates a <c>gen_server</c> with a registered name.
+ See type
+ <seetype marker="#server_name"><c>server_name()</c></seetype>
+ for different name registrations.
+ If no <c><anno>ServerName</anno></c> is provided,
+ the <c>gen_server</c> process 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 any term that is passed as
the argument to
- <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>.</p>
- <list type="bulleted">
- <item>
- <p>If option <c>{timeout,Time}</c> is present, the <c>gen_server</c>
- process is allowed to spend <c>Time</c> milliseconds
- initializing or it is terminated and the start function
- returns <c>{error,timeout}</c>.</p>
- </item>
- <item>
- <p>If option <c>{hibernate_after,HibernateAfterTimeout}</c> is present, the <c>gen_server</c>
- process awaits any message for <c>HibernateAfterTimeout</c> milliseconds and
- if no message is received, the process goes into hibernation automatically
- (by calling <seemfa marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seemfa>).</p>
- </item>
- <item>
- <p>If option <c>{debug,Dbgs}</c> is present,
- the corresponding <c>sys</c> function is called for each
- item in <c>Dbgs</c>; see
- <seeerl marker="sys"><c>sys(3)</c></seeerl>.</p>
- </item>
- <item>
- <p>If option <c>{spawn_opt,SOpts}</c> is present,
- <c>SOpts</c> is passed as option list to
- the <c>spawn_opt</c> BIF, which is used to spawn
- the <c>gen_server</c> process; see
- <seemfa marker="erts:erlang#spawn_opt/2">
- <c>spawn_opt/2</c></seemfa>.</p>
- </item>
- </list>
- <note>
- <p>Using spawn option <c>monitor</c> is not
- allowed, it causes the function to fail with reason
- <c>badarg</c>.</p>
- </note>
- <p>If the <c>gen_server</c> process is successfully created and
- initialized, the function returns <c>{ok,Pid}</c>, where <c>Pid</c>
- is the pid of the <c>gen_server</c> process. If a process with the
- specified <c>ServerName</c> exists already, the function returns
- <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is
- the pid of that process.</p>
- <p>If <c>Module:init/1</c> fails with <c>Reason</c>,
- the function returns <c>{error,Reason}</c>. If
- <c>Module:init/1</c> returns <c>{stop,Reason}</c> or
- <c>ignore</c>, the process is terminated and the function
- returns <c>{error,Reason}</c> or <c>ignore</c>, respectively.
- An exit signal with the same <c>Reason</c> (or <c>normal</c> if
- <c>Module:init/1</c> returns <c>ignore</c>) is sent to linked
- processes and ports.</p>
+ <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>.
+ </p>
+ <p>
+ See type
+ <seetype marker="#start_opt"><c>start_opt()</c></seetype>
+ for <c><anno>Options</anno></c> when starting
+ the <c>gen_server</c> process.
+ </p>
+ <p>
+ See type
+ <seetype marker="#start_ret"><c>start_ret()</c></seetype>
+ for a description this function's return values.
+ </p>
</desc>
</func>
<func>
- <name since="OTP 23.0">start_monitor(Module, Args, Options) -> Result</name>
- <name since="OTP 23.0">start_monitor(ServerName, Module, Args, Options) -> Result</name>
+ <name name="start_monitor" arity="3" since="OTP 23.0"/>
+ <name name="start_monitor" arity="4" since="OTP 23.0"/>
<fsummary>Create a standalone <c>gen_server</c> process.</fsummary>
- <type>
- <v>ServerName = {local,Name} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName}</v>
- <v>&nbsp;Name = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Module = atom()</v>
- <v>Args = term()</v>
- <v>Options = [Option]</v>
- <v>&nbsp;Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}</v>
- <v>&nbsp;&nbsp;Dbgs = [Dbg]</v>
- <v>&nbsp;&nbsp;&nbsp;Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}</v>
- <v>&nbsp;&nbsp;SOpts = [term()]</v>
- <v>Result = {ok,{Pid,Mon}} | ignore | {error,Error}</v>
- <v>&nbsp;Pid = pid()</v>
- <v>&nbsp;Error = {already_started,Pid} | term()</v>
- </type>
<desc>
- <p>Creates a standalone <c>gen_server</c> process, that is, a
+ <p>
+ Creates a standalone <c>gen_server</c> process, that is, a
<c>gen_server</c> process that is not part of a supervision tree
(and thus has no supervisor) and atomically sets up a monitor to
- the newly created server.</p>
- <p>For a description of arguments and return values, see
- <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.
- Note that the return value on successful start differs from
- <c>start_link/3,4</c>. <c>start_monitor/3,4</c> will return
- <c>{ok,{Pid,Mon}}</c> where <c>Pid</c> is the process identifier
- of the server, and <c>Mon</c> is a reference to the monitor
- set up to monitor the server. If the start is not successful,
- the caller will be blocked until the <c>DOWN</c> message has
- been received and removed from the message queue.</p>
+ the newly created server.
+ </p>
+ <p>
+ Other than that see
+ <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.
+ Note that the return value for a successful start differs
+ in that it returns a monitor <c>reference</c>.
+ See type
+ <seetype marker="#start_mon_ret"><c>start_mon_ret()</c></seetype>.
+ </p>
+ <p>
+ If the start is not successful,
+ the caller will be blocked until the monitor's
+ <c>'DOWN'</c> message has been received
+ and removed from the message queue.
+ </p>
</desc>
</func>
<func>
- <name since="OTP 18.0">stop(ServerRef) -> ok</name>
- <name since="OTP 18.0">stop(ServerRef, Reason, Timeout) -> ok</name>
+ <name name="stop" arity="1" since="OTP 18.0"/>
+ <name name="stop" arity="3" since="OTP 18.0"/>
<fsummary>Synchronously stop a generic server.</fsummary>
- <type>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- <v>Reason = term()</v>
- <v>Timeout = int()>0 | infinity</v>
- </type>
<desc>
- <p>Orders a generic server to exit with the specified <c>Reason</c>
- and waits for it to terminate. The <c>gen_server</c> process calls
+ <p>
+ Orders the generic server specified by
+ <c><anno>ServerRef</anno></c> to exit
+ with the specified <c><anno>Reason</anno></c>,
+ default 'normal', and waits for it to terminate.
+ The <c>gen_server</c> process calls
<seemfa marker="#Module:terminate/2">
- <c>Module:terminate/2</c></seemfa> before exiting.</p>
- <p>The function returns <c>ok</c> if the server terminates
+ <c>Module:terminate/2</c>
+ </seemfa>
+ before exiting.
+ </p>
+ <p>
+ The function returns <c>ok</c> if the server terminates
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued using
<seeerl marker="kernel:logger"><c>logger(3)</c></seeerl>.
- An exit signal with the same reason is sent to linked processes
- and ports.
- The default <c>Reason</c> is <c>normal</c>.</p>
- <p><c>Timeout</c> is an integer greater than zero that
+ An exit signal with the same reason
+ is sent to linked processes and ports.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> is an integer that
specifies how many milliseconds to wait for the server to
terminate, or the atom <c>infinity</c> to wait
- indefinitely. Defaults to <c>infinity</c>. If the
- server has not terminated within the specified time, a
- <c>timeout</c> exception is raised.</p>
- <p>If the process does not exist, a <c>noproc</c> exception
- is raised.</p>
+ indefinitely, which is the default. If the
+ server has not terminated within the specified time,
+ the call exits the calling process
+ with reason <c>timeout</c>.
+ </p>
+ <p>
+ If the process does not exist, the call exits
+ the calling process with reason <c>noproc</c>,
+ and with reason <c>{nodedown,Node}</c>
+ if the connection fails to the remote <c>Node</c>
+ where the server runs.
+ </p>
</desc>
</func>
<func>
- <name since="OTP 23.0">wait_response(RequestId, Timeout) -> Result</name>
- <fsummary>Wait for a reply from a server.</fsummary>
- <type>
- <v>RequestId = term()</v>
- <v>Result = {reply, Reply} | timeout | {error, {Reason, ServerRef}}</v>
- <v>Reply = term()</v>
- <v>Timeout = timeout()</v>
- <v>Reason = term()</v>
- <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v>
- <v>&nbsp;&nbsp;| {via,Module,ViaName} | pid()</v>
- <v>&nbsp;Node = atom()</v>
- <v>&nbsp;GlobalName = ViaName = term()</v>
- </type>
+ <name name="wait_response" arity="2" since="OTP 23.0"/>
+ <fsummary>Wait or poll for a response from a server.</fsummary>
<desc>
<p>
- This function is used to wait for a reply of a request made with
- <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
- from the <c>gen_server</c> process. This function must be called
- from the same process from which
- <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
- was made.
+ Wait for a response corresponding to the request identifier
+ <c><anno>ReqId</anno></c>. The request must have been made by
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>,
+ and it must have been made by the same process calling
+ this function.
</p>
<p>
- <c>Timeout</c> is an integer greater then or equal to zero
- that specifies how many milliseconds to wait for an reply, or
- the atom <c>infinity</c> to wait indefinitely.
- If no reply is received within the specified
+ <c><anno>WaitTime</anno></c> specifies how long to wait for
+ a reply. If no reply is received within the specified
time, the function returns <c>timeout</c> and no cleanup is
done, and thus the function can be invoked repeatedly until a
reply is returned.
</p>
<p>
- The return value <c>Reply</c> is defined in the return value
- of <c>Module:handle_call/3</c>.
+ The return value <c><anno>Reply</anno></c> is passed from the
+ return value of <c>Module:handle_call/3</c>.
</p>
<p>
The function returns an error if the <c>gen_server</c>
- dies before or during this request.
+ died before a reply was sent.
</p>
<p>
The difference between
- <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa>
- and <c>wait_response()</c> is that <c>receive_response()</c>
- abandons the request at timeout so that a potential future
- response is ignored, while <c>wait_response()</c> does not.
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>
+ and <c>wait_response/2</c> is that <c>receive_response/2</c>
+ abandons the request at time-out so that a potential future
+ response is ignored, while <c>wait_response/2</c> does not.
</p>
</desc>
</func>
+
+ <func>
+ <name name="wait_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Wait or poll for a response from a server.</fsummary>
+ <desc>
+ <p>
+ Wait for a response corresponding to a request identifier saved
+ in <c><anno>ReqIdCollection</anno></c>. All request identifiers
+ of <c><anno>ReqIdCollection</anno></c> must correspond to requests
+ that have been made using
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">saving the request id</seemfa> in
+ a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>wait_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, <c>no_request</c>
+ will be returned. If no response is received before the
+ <c><anno>WaitTime</anno></c> timeout has triggered, the atom
+ <c>timeout</c> is returned. It is valid to continue waiting for a
+ response as many times as needed up until a response has been received
+ and completed by <c>check_response()</c>, <c>receive_response()</c>,
+ or <c>wait_response()</c>.
+ </p>
+ <p>
+ The difference between
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>
+ and <c>wait_response/3</c> is that <c>receive_response/3</c>
+ abandons requests at timeout so that a potential future
+ responses are ignored, while <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>wait_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>wait_response/3</c>, it will always block
+ until a timeout determined by <c><anno>WaitTime</anno></c> is
+ triggered and then return <c>no_reply</c>.
+ </p>
+ </desc>
+ </func>
</funcs>
@@ -788,6 +1535,69 @@ gen_server:abcast -----> Module:handle_cast/2
</func>
<func>
+ <name since="OTP 25.0">Module:format_status(Status) -> NewStatus</name>
+ <fsummary>Optional function for providing a term describing the
+ current <c>gen_server</c> status.</fsummary>
+ <type>
+ <v>Status = <seetype marker="#format_status">format_status()</seetype></v>
+ <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v>
+ </type>
+ <desc>
+ <note>
+ <p>This callback is optional, so callback modules need not
+ export it. The <c>gen_server</c> module provides a default
+ implementation of this function that returns the callback
+ module state.</p>
+ <p>
+ If this callback is exported but fails, to hide possibly sensitive
+ data, the default function will instead return the fact that
+ <c>format_status/1</c> has crashed.</p>
+ </note>
+ <p>This function is called by a <c>gen_server</c> process in the following situations:</p>
+ <list type="bulleted">
+ <item>
+ <p><seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa>
+ is invoked to get the <c>gen_server</c> status.</p>
+ </item>
+ <item>
+ <p>The <c>gen_server</c> process terminates abnormally and logs an error.</p>
+ </item>
+ </list>
+ <p>
+ This callback is used to limit the status of the process
+ returned by
+ <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa>
+ or sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>.
+ </p>
+ <p>
+ The callback gets a map <c>Status</c>
+ describing the current status and shall return a map
+ <c>NewStatus</c> with the same keys,
+ but it may transform some values.
+ </p>
+ <p>
+ Two possible use cases for this callback is to
+ remove sensitive information from the state
+ to prevent it from being printed in log files,
+ or to compact large irrelevant status items
+ that would only clutter the logs.
+ </p>
+ <p>Example:</p>
+ <code type="erl"><![CDATA[
+format_status(Status) ->
+ maps:map(
+ fun(state,State) ->
+ maps:remove(private_key, State);
+ (message,{password, _Pass}) ->
+ {password, removed};
+ (_,Value) ->
+ Value
+ end, Status).
+]]></code>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04">Module:format_status(Opt, [PDict, State]) -> Status</name>
<fsummary>Optional function for providing a term describing the
current <c>gen_server</c> status.</fsummary>
@@ -798,6 +1608,11 @@ gen_server:abcast -----> Module:handle_cast/2
<v>Status = term()</v>
</type>
<desc>
+ <warning>
+ <p>This callback is deprecated, in new code use <seemfa marker="#Module:format_status/1">
+ format_status/1</seemfa>. If a <seemfa marker="#Module:format_status/1">format_status/1</seemfa>
+ callback exists, then this function will never be called.</p>
+ </warning>
<note>
<p>This callback is optional, so callback modules need not
export it. The <c>gen_server</c> module provides a default
@@ -852,18 +1667,24 @@ gen_server:abcast -----> Module:handle_cast/2
<fsummary>Handle a synchronous request.</fsummary>
<type>
<v>Request = term()</v>
- <v>From = {pid(),Tag}</v>
+ <v>From = <seetype marker="#from">from()</seetype></v>
<v>State = term()</v>
- <v>Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}</v>
+ <v>Result = {reply,Reply,NewState}</v>
+ <v>&nbsp;&nbsp;| {reply,Reply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {reply,Reply,NewState,hibernate}</v>
<v>&nbsp;&nbsp;| {reply,Reply,NewState,{continue,Continue}}</v>
- <v>&nbsp;&nbsp;| {noreply,NewState} | {noreply,NewState,Timeout}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
- <v>&nbsp;&nbsp;| {stop,Reason,Reply,NewState} | {stop,Reason,NewState}</v>
+ <v>&nbsp;&nbsp;| {stop,Reason,Reply,NewState}</v>
+ <v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
<v>&nbsp;Reply = term()</v>
<v>&nbsp;NewState = term()</v>
- <v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>
+ &nbsp;Timeout =
+ <seetype marker="erts:erlang#timeout">timeout()</seetype>
+ </v>
<v>&nbsp;Continue = term()</v>
<v>&nbsp;Reason = term()</v>
</type>
@@ -872,45 +1693,109 @@ gen_server:abcast -----> Module:handle_cast/2
<seemfa marker="#call/2"><c>call/2,3</c></seemfa> or
<seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>,
this function is called to handle the request.</p>
- <p><c>Request</c> is the <c>Request</c> argument provided
- to <c>call</c> or <c>multi_call</c>.</p>
- <p><c>From</c> is a tuple <c>{Pid,Tag}</c>, where <c>Pid</c> is
- the pid of the client and <c>Tag</c> is a unique tag.</p>
<p><c>State</c> is the internal state of the <c>gen_server</c>
- process.</p>
- <list type="bulleted">
+ process, and <c>NewState</c> a possibly updated one.</p>
+ <p><c>Request</c> is passed from the same argument provided
+ to <c>call</c> or <c>multi_call</c>.</p>
+ <p>The return value <c>Result</c> is interpreted as follows:</p>
+ <taglist>
+ <tag>
+ <c>{reply,Reply,NewState}</c><br/>
+ <c>{reply,Reply,NewState,_}</c>
+ </tag>
<item>
- <p>If <c>{reply,Reply,NewState}</c> is returned,
- <c>{reply,Reply,NewState,Timeout}</c> or
- <c>{reply,Reply,NewState,hibernate}</c>, <c>Reply</c> is
- given back to <c>From</c> as the return value of
- <c>call/2,3</c> or included in the return value of
- <c>multi_call/2,3,4</c>. The <c>gen_server</c> process then
- continues executing with the possibly updated internal state
- <c>NewState</c>.</p>
- <p>For a description of <c>Timeout</c> and <c>hibernate</c>, see
- <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>.</p>
+ <p>
+ The <c>Reply</c> value is sent back to the client request
+ and there becomes its return value.
+ </p>
+ <p>
+ The <c>gen_server</c> process continues executing
+ with the possibly updated internal state <c>NewState</c>.
+ </p>
</item>
+ <tag>
+ <c>{noreply,NewState}</c><br/>
+ <c>{noreply,NewState,_}</c>
+ </tag>
<item>
- <p>If <c>{noreply,NewState}</c> is returned,
- <c>{noreply,NewState,Timeout}</c>, or
- <c>{noreply,NewState,hibernate}</c>, the <c>gen_server</c>
- process continues executing with <c>NewState</c>. Any reply to
- <c>From</c> must be specified explicitly using
- <seemfa marker="#reply/2"><c>reply/2</c></seemfa>.</p>
+ <p>
+ The <c>gen_server</c> process continues executing
+ with the possibly updated internal state <c>NewState</c>.
+ </p>
+ <p>
+ A reply to the client request has to be created by calling
+ <seemfa marker="#reply/2"><c>reply(From,&nbsp;Reply)</c></seemfa>,
+ either in this or in a later callback.
+ </p>
</item>
+ <tag>
+ <c>{reply,_,_,Timeout}</c><br/>
+ <c>{noreply,_,Timeout}</c>
+ </tag>
<item>
- <p>If <c>{stop,Reason,Reply,NewState}</c> is returned,
- <c>Reply</c> is given back to <c>From</c>.</p>
+ <p>
+ If an integer <c>Timeout</c> is provided, a time-out occurs
+ unless a request or a message is received within
+ that many milliseconds. A time-out is represented by
+ the atom <c>timeout</c> to be handled by the
+ <seemfa marker="#Module:handle_info/2">
+ <c>Module:handle_info/2</c>
+ </seemfa>
+ callback function.
+ <c>Timeout&nbsp;=:=&nbsp;infinity</c>
+ can be used to wait indefinitely, which is the same as
+ returning a value without a <c>Timeout</c> member.
+ </p>
</item>
+ <tag>
+ <c>{reply,_,_,hibernate}</c><br/>
+ <c>{noreply,_,hibernate}</c>
+ </tag>
<item>
- <p>If <c>{stop,Reason,NewState}</c> is returned, any reply
- to <c>From</c> must be specified explicitly using
- <seemfa marker="#reply/2"><c>reply/2</c></seemfa>.
- The <c>gen_server</c> process then calls
- <c>Module:terminate(Reason,NewState)</c> and terminates.</p>
+ <p>
+ The process goes into hibernation waiting for
+ the next message to arrive (by calling
+ <seemfa marker="proc_lib#hibernate/3">
+ <c>proc_lib:hibernate/3</c></seemfa>).
+ </p>
</item>
- </list>
+ <tag>
+ <c>{reply,_,_,{continue,Continue}}</c><br/>
+ <c>{noreply,_,{continue,Continue}}</c>
+ </tag>
+ <item>
+ <p>
+ The process will execute the
+ <seemfa marker="#Module:handle_continue/2">
+ <c>Module:handle_continue/2</c>
+ </seemfa>
+ callback function, with <c>Continue</c> as the first argument.
+ </p>
+ </item>
+ <tag>
+ <c>{stop,Reason,NewState}</c><br/>
+ <c>{stop,Reason,Reply,NewState}</c>
+ </tag>
+ <item>
+ <p>
+ The <c>gen_server</c> process will call
+ <seemfa marker="#Module:terminate/2">
+ <c>Module:terminate(Reason,NewState)</c>
+ </seemfa>
+ and then terminate.
+ </p>
+ <p>
+ <c>{stop,_,Reply,_}</c> will create
+ a reply to the client request just as
+ <c>{reply,Reply,...}</c> while
+ <c>{stop,_,_}</c> will not,
+ so just as for <c>{noreply,NewState,...}</c>
+ a reply has to be created by calling
+ <c>reply(From,&nbsp;Reply)</c>
+ before returning <c>{stop,_,_}</c>.
+ </p>
+ </item>
+ </taglist>
</desc>
</func>
@@ -920,12 +1805,16 @@ gen_server:abcast -----> Module:handle_cast/2
<type>
<v>Request = term()</v>
<v>State = term()</v>
- <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v>
+ <v>Result = {noreply,NewState}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
<v>&nbsp;NewState = term()</v>
- <v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>
+ &nbsp;Timeout =
+ <seetype marker="erts:erlang#timeout">timeout()</seetype>
+ </v>
<v>&nbsp;Continue = term()</v>
<v>&nbsp;Reason = term()</v>
</type>
@@ -946,25 +1835,31 @@ gen_server:abcast -----> Module:handle_cast/2
<type>
<v>Continue = term()</v>
<v>State = term()</v>
- <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v>
+ <v>Result = {noreply,NewState}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
<v>&nbsp;NewState = term()</v>
- <v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>
+ &nbsp;Timeout =
+ <seetype marker="erts:erlang#timeout">timeout()</seetype>
+ </v>
<v>&nbsp;Continue = term()</v>
<v>&nbsp;Reason = normal | term()</v>
</type>
<desc>
<note>
<p>This callback is optional, so callback modules need to
- export it only if they return <c>{continue,Continue}</c>
- from another callback. If continue is used and the callback
- is not implemented, the process will exit with <c>undef</c>
- error.</p>
+ export it only if they return one of the tuples containing
+ <c>{continue,Continue}</c>
+ from another callback. If such a <c>{continue,_}</c> tuple
+ is used and the callback is not implemented,
+ the process will exit with <c>undef</c> error.</p>
</note>
- <p>This function is called by a <c>gen_server</c> process whenever
- a previous callback returns <c>{continue, Continue}</c>.
+ <p>This function is called by a <c>gen_server</c> process
+ whenever a previous callback returns
+ one of the tuples containing <c>{continue, Continue}</c>.
<c>handle_continue/2</c> is invoked immediately after the previous
callback, which makes it useful for performing work after
initialization or for splitting the work in a callback in
@@ -981,12 +1876,16 @@ gen_server:abcast -----> Module:handle_cast/2
<type>
<v>Info = timeout | term()</v>
<v>State = term()</v>
- <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v>
+ <v>Result = {noreply,NewState}</v>
+ <v>&nbsp;&nbsp;| {noreply,NewState,Timeout}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,hibernate}</v>
<v>&nbsp;&nbsp;| {noreply,NewState,{continue,Continue}}</v>
<v>&nbsp;&nbsp;| {stop,Reason,NewState}</v>
<v>&nbsp;NewState = term()</v>
- <v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>
+ &nbsp;Timeout =
+ <seetype marker="erts:erlang#timeout">timeout()</seetype>
+ </v>
<v>&nbsp;Reason = normal | term()</v>
</type>
<desc>
@@ -1012,10 +1911,17 @@ gen_server:abcast -----> Module:handle_cast/2
<fsummary>Initialize process and internal state.</fsummary>
<type>
<v>Args = term()</v>
- <v>Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate}</v>
- <v>&nbsp;| {ok,State,{continue,Continue}} | {stop,Reason} | ignore</v>
+ <v>Result = {ok,State}</v>
+ <v>&nbsp;&nbsp;| {ok,State,Timeout}</v>
+ <v>&nbsp;&nbsp;| {ok,State,hibernate}</v>
+ <v>&nbsp;&nbsp;| {ok,State,{continue,Continue}}</v>
+ <v>&nbsp;&nbsp;| {stop,Reason}</v>
+ <v>&nbsp;&nbsp;| ignore</v>
<v>&nbsp;State = term()</v>
- <v>&nbsp;Timeout = int()>=0 | infinity</v>
+ <v>
+ &nbsp;Timeout =
+ <seetype marker="erts:erlang#timeout">timeout()</seetype>
+ </v>
<v>&nbsp;Reason = term()</v>
</type>
<desc>
@@ -1026,35 +1932,50 @@ gen_server:abcast -----> Module:handle_cast/2
this function is called by the new process to initialize.</p>
<p><c>Args</c> is the <c>Args</c> argument provided to the start
function.</p>
- <p>If the initialization is successful, the function is to
- return <c>{ok,State}</c>, <c>{ok,State,Timeout}</c>,
- <c>{ok,State,hibernate}</c>, or <c>{ok,State,{continue,Continue}}</c>
- where <c>State</c> is the internal state of the <c>gen_server</c>
- process.</p>
- <p>If an integer time-out value is provided, a time-out occurs
- unless a request or a message is received within
- <c>Timeout</c> milliseconds. A time-out is represented by
- the atom <c>timeout</c>, which is to be handled by the
- <seemfa marker="#Module:handle_info/2">
- <c>Module:handle_info/2</c></seemfa> callback function. The atom
- <c>infinity</c> can be used to wait indefinitely, this is
- the default value.</p>
- <p>If <c>hibernate</c> is specified instead of a time-out value,
- the process goes into
- hibernation when waiting for the next message to arrive (by calling
- <seemfa marker="proc_lib#hibernate/3">
- <c>proc_lib:hibernate/3</c></seemfa>).</p>
- <p>If <c>{continue,Continue}</c> is specified, the process will
- execute the <seemfa marker="#Module:handle_continue/2">
- <c>Module:handle_continue/2</c></seemfa> callback function, with
- <c>Continue</c> as the first argument.</p>
- <p>If the initialization fails, the function is to return
- <c>{stop,Reason}</c>, where <c>Reason</c> is any term, or
- <c>ignore</c>. An exit signal with this <c>Reason</c> (or with reason
- <c>normal</c> if <c>ignore</c> is returned) is sent to linked
- processes and ports, notably to the process starting the gen_server
- when <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>
- is used.</p>
+ <p>The return value <c>Result</c> is interpreted as follows:</p>
+ <taglist>
+ <tag>
+ <c>{ok,State}</c><br/>
+ <c>{ok,State,_}</c>
+ </tag>
+ <item>
+ <p>
+ Initialization was succesful and <c>State</c>
+ is the internal state of the <c>gen_server</c> process.
+ </p>
+ </item>
+ <tag>
+ <c>{ok,_,Timeout}</c><br/>
+ <c>{ok,_,hibernate}</c><br/>
+ <c>{ok,_,{continue,Continue}}</c>
+ </tag>
+ <item>
+ <p>
+ See the corresponding return values from
+ <seemfa marker="#Module:handle_call/3">
+ <c>Module:handle_call/3</c>
+ </seemfa>
+ for a description of this tuple member.
+ </p>
+ </item>
+ <tag>
+ <c>{stop,Reason}</c><br/>
+ <c>ignore</c>
+ </tag>
+ <item>
+ <p>
+ Initialization failed.
+ An exit signal with this <c>Reason</c>
+ (or with reason <c>normal</c> if <c>ignore</c> is returned)
+ is sent to linked processes and ports,
+ notably to the process starting the gen_server when
+ <seemfa marker="#start_link/3">
+ <c>start_link/3,4</c>
+ </seemfa>
+ is used.
+ </p>
+ </item>
+ </taglist>
</desc>
</func>
@@ -1104,11 +2025,14 @@ gen_server:abcast -----> Module:handle_cast/2
<c>'EXIT'</c> message from its parent. <c>Reason</c> is the same
as in the <c>'EXIT'</c> message.</p>
<p>Otherwise, the <c>gen_server</c> process terminates immediately.</p>
- <p>Notice that for any other reason than <c>normal</c>,
- <c>shutdown</c>, or <c>{shutdown,Term}</c>, the <c>gen_server</c>
- process is assumed to terminate because of an error and
- an error report is issued using
- <seeerl marker="kernel:logger"><c>logger(3)</c></seeerl>.</p>
+ <p>
+ Notice that for any other reason than <c>normal</c>,
+ <c>shutdown</c>, or <c>{shutdown,Term}</c>, see
+ <seemfa marker="#stop/3"><c>stop/3</c></seemfa>,
+ the <c>gen_server</c> process is assumed to terminate
+ because of an error, and an error report is issued using
+ <seeerl marker="kernel:logger"><c>logger(3)</c></seeerl>.
+ </p>
<p>When the gen_server process exits, an exit signal with the same
reason is sent to linked processes and ports.</p>
</desc>
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index fd3d11bbcf..9dd1c6f270 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2016</year><year>2021</year>
+ <year>2016</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -639,6 +639,14 @@ handle_event(_, _, State, Data) ->
</desc>
</datatype>
<datatype>
+ <name name="reply_tag"/>
+ <desc>
+ <p>
+ A handle that associates a reply to the corresponding request.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="state"/>
<desc>
<p>
@@ -726,6 +734,19 @@ handle_event(_, _, State, Data) ->
</desc>
</datatype>
<datatype>
+ <name name="event_content"/>
+ <desc>
+ <p>
+ Any event's content can be any term.
+ </p>
+ <p>
+ See <seetype marker="#event_type"><c>event_type</c></seetype>
+ that describes the origins of the different event types,
+ which is also where the event content comes from.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="callback_mode_result"/>
<desc>
<p>
@@ -1246,8 +1267,8 @@ handle_event(_, _, State, Data) ->
such as the
<seeerl marker="#state callback">state callback</seeerl>,
<seemfa marker="#Module:code_change/4"><c><anno>NewModule</anno>:code_change/4</c></seemfa>,
- <seemfa marker="#Module:format_status/2">
- <c><anno>NewModule</anno>:format_status/2</c>
+ <seemfa marker="#Module:format_status/1">
+ <c><anno>NewModule</anno>:format_status/1</c>
</seemfa>
and
<seemfa marker="#Module:terminate/3">
@@ -1616,11 +1637,106 @@ handle_event(_, _, State, Data) ->
<name name="request_id"/>
<desc>
<p>
- A request handle, see <seemfa marker="#send_request/2"> <c>send_request/2</c> </seemfa>
+ An opaque request identifier. See
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
for details.
</p>
</desc>
</datatype>
+
+ <datatype>
+ <name name="request_id_collection"/>
+ <desc>
+ <p>
+ An opaque collection of request identifiers
+ (<seetype marker="#request_id"><c>request_id()</c></seetype>)
+ where each request identifier can be associated with a label
+ chosen by the user. For more information see
+ <seemfa marker="#reqids_new/0"><c>reqids_new/0</c></seemfa>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="response_timeout"/>
+ <desc>
+ <p>
+ Used to set a time limit on how long to wait for a response using
+ either
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ or
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ The time unit used is <c>millisecond</c>. Currently valid values:
+ </p>
+ <taglist>
+ <tag><c>0..4294967295</c></tag>
+ <item><p>
+ Timeout relative to current time in milliseconds.
+ </p></item>
+ <tag><c>infinity</c></tag>
+ <item><p>
+ Infinite timeout. That is, the operation will never time out.
+ </p></item>
+ <tag><c>{abs, Timeout}</c></tag>
+ <item><p>
+ An absolute
+ <seemfa marker="erts:erlang#monotonic_time/1">Erlang monotonic time</seemfa>
+ timeout in milliseconds. That is, the operation will time out when
+ <seemfa marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time(millisecond)</c></seemfa>
+ returns a value larger than or equal to <c>Timeout</c>. <c>Timeout</c>
+ is not allowed to identify a time further into the future than <c>4294967295</c>
+ milliseconds. Identifying the timeout using an absolute timeout value
+ is especially handy when you have a deadline for responses corresponding
+ to a complete collection of requests
+ (<seetype marker="#request_id_collection"><c>request_id_collection()</c></seetype>)
+,
+ since you do not have to recalculate the relative time until the deadline
+ over and over again.
+ </p></item>
+ </taglist>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="format_status"/>
+ <desc>
+ <p>
+ A map that describes the <c>gen_statem</c> status.
+ The keys are:
+ </p>
+ <taglist>
+ <tag><c>state</c></tag>
+ <item>The current state of the <c>gen_statem</c> process.</item>
+ <tag><c>data</c></tag>
+ <item>The state data of the the <c>gen_statem</c> process.</item>
+ <tag><c>reason</c></tag>
+ <item>The reason that caused the state machine to terminate.</item>
+ <tag><c>queue</c></tag>
+ <item>The event queue of the <c>gen_statem</c> process.</item>
+ <tag><c>postponed</c></tag>
+ <item>
+ The <seetype marker="#postpone">postponed</seetype>
+ events queue of the <c>gen_statem</c> process.
+ </item>
+ <tag><c>timeouts</c></tag>
+ <item>
+ The active
+ <seetype marker="#timeout_action">time-outs</seetype>
+ of the <c>gen_statem</c> process.
+ </item>
+ <tag><c>log</c></tag>
+ <item>
+ The <seemfa marker="sys#log/2">sys log</seemfa> of the server.
+ </item>
+ </taglist>
+ <p>
+ New associations may be added to the status map
+ without prior notice.
+ </p>
+ </desc>
+ </datatype>
</datatypes>
<funcs>
@@ -1698,6 +1814,20 @@ handle_event(_, _, State, Data) ->
The call can also fail, for example, if the <c>gen_statem</c>
dies before or during this function call.
</p>
+ <p>
+ When this call fails it
+ <seemfa marker="erts:erlang#exit/1">exits</seemfa>
+ the calling process.
+ The exit term is on the form
+ <c>{Reason,&nbsp;Location}</c> where
+ <c>Location&nbsp;=&nbsp;{gen_statem,call,ArgList}</c>.
+ See
+ <seemfa marker="gen_server#call/3">
+ <c>gen_server:call/3</c>
+ </seemfa>
+ that has a description of relevant
+ values for the <c>Reason</c> in the exit term.
+ </p>
</desc>
</func>
@@ -1722,15 +1852,15 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="check_response" arity="2" since="OTP-23"/>
+ <name name="check_response" arity="2" since="OTP 23.0"/>
<fsummary>Check if a message is a reply from a server.</fsummary>
<desc>
<p>
- This function is used to check if a previously received
- message, for example by <c>receive</c> or
- <c>handle_info/2</c>, is a result of a request made with
+ Check if <c><anno>Msg</anno></c> is a response corresponding
+ to the request identifier <c><anno>ReqId</anno></c>. The request
+ must have been made by
<seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>.
- If <c>Msg</c> is a reply to the handle <c>RequestId</c>
+ If <c>Msg</c> is a reply to the handle <c>ReqId</c>
the result of the request is returned in <c>Reply</c>.
Otherwise returns <c>no_reply</c> and no cleanup is done, and
thus the function shall be invoked repeatedly until a reply
@@ -1753,6 +1883,73 @@ handle_event(_, _, State, Data) ->
</func>
<func>
+ <name name="check_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Check if a message is a reply from a server.</fsummary>
+ <desc>
+ <p>
+ Check if <c><anno>Msg</anno></c> is a response corresponding
+ to a request identifier saved in <c><anno>ReqIdCollection</anno></c>.
+ All request identifiers of <c><anno>ReqIdCollection</anno></c>
+ must correspond to requests that have been made using
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">saving the request id</seemfa>
+ in a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>check_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned. If <c><anno>Msg</anno></c>
+ does not correspond to any of the request identifiers in
+ <c><anno>ReqIdCollection</anno></c>, the atom
+ <c>no_reply</c> is returned.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>check_response/3</c>,
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>check_response/3</c>, it will always
+ return <c>no_reply</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="enter_loop" arity="4" since="OTP 19.1"/>
<fsummary>Enter the <c>gen_statem</c> receive loop.</fsummary>
<desc>
@@ -1849,11 +2046,23 @@ handle_event(_, _, State, Data) ->
<func>
<name name="receive_response" arity="1" since="OTP 24.0"/>
- <name name="receive_response" arity="2" since="OTP 24.0"/>
<fsummary>Receive for a reply from a server.</fsummary>
<desc>
<p>
- This function is used to receive for a reply of a request made with
+ The same as calling
+ <seemfa marker="#receive_response/2"><c>gen_statem:receive_response(ReqId,
+ infinity)</c></seemfa>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="receive_response" arity="2" clause_i="1" since="OTP 24.0"/>
+ <fsummary>Receive for a reply from a server.</fsummary>
+ <desc>
+ <p>
+ Receive a response corresponding to the request identifier
+ <c><anno>ReqId</anno></c>- The request must have been made by
<seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
to the <c>gen_statem</c> process. This function must be called
from the same process from which
@@ -1861,15 +2070,13 @@ handle_event(_, _, State, Data) ->
was made.
</p>
<p>
- <c>Timeout</c> is an integer greater then or equal to zero
- that specifies how many milliseconds to wait for an reply, or
- the atom <c>infinity</c> to wait indefinitely. Defaults to
- <c>infinity</c>.
- If no reply is received within the specified
- time, the function returns <c>timeout</c>. Assuming that the
+ <c><anno>Timeout</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified time,
+ the function returns <c>timeout</c>. Assuming that the
server executes on a node supporting aliases (introduced in
- OTP 24) no response will be received after a timeout. Otherwise,
- a garbage response might be received at a later time.
+ OTP 24) the request will also be abandoned. That is, no
+ response will be received after a timeout. Otherwise, a
+ stray response might be received at a later time.
</p>
<p>
The return value <c><anno>Reply</anno></c> is generated when a
@@ -1886,11 +2093,92 @@ handle_event(_, _, State, Data) ->
</p>
<p>
The difference between
- <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa>
- and <c>receive_response()</c> is that <c>receive_response()</c>
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>
+ and <c>receive_response/2</c> is that <c>receive_response/2</c>
abandons the request at timeout so that a potential future
- response is ignored, while <c>wait_response()</c> does not.
+ response is ignored, while <c>wait_response/2</c> does not.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="receive_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Receive a response from a server.</fsummary>
+ <desc>
+ <p>
+ Receive a response corresponding to a request identifier saved
+ in <c><anno>ReqIdCollection</anno></c>. All request identifiers
+ of <c><anno>ReqIdCollection</anno></c> must correspond to requests
+ that have been made using
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">adding the request id</seemfa>
+ in a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ will be wrapped in a 3-tuple. The first element of this tuple equals
+ the value that would have been produced by <c>receive_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, the atom
+ <c>no_request</c> will be returned.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> specifies how long to wait for
+ a response. If no response is received within the specified time,
+ the function returns <c>timeout</c>. Assuming that the
+ server executes on a node supporting aliases (introduced in
+ OTP 24) all requests identified by <c><anno>ReqIdCollection</anno></c>
+ will also be abandoned. That is, no responses will be received
+ after a timeout. Otherwise, stray responses might be received
+ at a later time.
</p>
+ <p>
+ The difference between <c>receive_response/3</c> and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>
+ is that <c>receive_response/3</c> abandons the requests at timeout
+ so that potential future responses are ignored, while
+ <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>receive_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>receive_response/3</c>, it will always block
+ until a timeout determined by <c><anno>Timeout</anno></c> is
+ triggered.
+ </p>
</desc>
</func>
@@ -1928,20 +2216,98 @@ handle_event(_, _, State, Data) ->
</func>
<func>
- <name name="send_request" arity="2" since="OTP-23"/>
- <fsummary>Send a request to a <c>gen_statem</c>.</fsummary>
+ <name name="reqids_add" arity="3" since="OTP 25.0"/>
+ <fsummary>Save a request identifier.</fsummary>
<desc>
+ <p>
+ Saves <c><anno>ReqId</anno></c> and associates a <c><anno>Label</anno></c>
+ with the request identifier by adding this information to
+ <c><anno>ReqIdCollection</anno></c> and returning the
+ resulting request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_new" arity="0" since="OTP 25.0"/>
+ <fsummary>Create a new empty request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns a new empty request identifier collection. A
+ request identifier collection can be utilized in order
+ the handle multiple outstanding requests.
+ </p>
<p>
- Sends a request to the <c>gen_statem</c>
- <seetype marker="#server_ref"><c><anno>ServerRef</anno></c></seetype>
- and returns a handle <c><anno>RequestId</anno></c>.
- </p>
+ Request identifiers of requests made by
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
+ can be saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+ <p>
+ <seemfa marker="#reqids_size/1"><c>reqids_size/1</c></seemfa>
+ can be used to determine the amount of request identifiers in a
+ request identifier collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_size" arity="1" since="OTP 25.0"/>
+ <fsummary>Get size of a request identifier collection.</fsummary>
+ <desc>
+ <p>
+ Returns the amount of request identifiers saved in
+ <c><anno>ReqIdCollection</anno></c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reqids_to_list" arity="1" since="OTP 25.0"/>
+ <fsummary>List a request identifiers.</fsummary>
+ <desc>
<p>
- The return value <c><anno>RequestId</anno></c> shall later be used with
- <seemfa marker="#receive_response/2"> <c>receive_response/1,2</c></seemfa>,
- <seemfa marker="#wait_response/2"> <c>wait_response/1,2</c></seemfa>, or
+ Returns a list of <c>{<anno>ReqId</anno>, <anno>Label</anno>}</c>
+ tuples which corresponds to all request identifiers with their
+ associated labels present in the <c><anno>ReqIdCollection</anno></c>
+ collection.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send_request" arity="2" since="OTP 23.0"/>
+ <fsummary>Send a request to a <c>gen_statem</c>.</fsummary>
+ <desc>
+ <p>
+ Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c>
+ to the <c>gen_statem</c> process identified by <c><anno>ServerRef</anno></c>
+ and returns a request identifier <c><anno>ReqId</anno></c>. The return
+ value <c><anno>ReqId</anno></c> shall later be used with
+ <seemfa marker="#receive_response/2"> <c>receive_response/2</c></seemfa>,
+ <seemfa marker="#wait_response/2"> <c>wait_response/2</c></seemfa>, or
<seemfa marker="#check_response/2"> <c>check_response/2</c></seemfa>
- to fetch the actual result of the request.
+ to fetch the actual result of the request. Besides passing
+ the request identifier directly to these functions, it can also be
+ saved in a request identifier collection using
+ <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>.
+ Such a collection of request identifiers can later be used in
+ order to get one response corresponding to a request in the
+ collection by passing the collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>, or
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ If you are about to save the request identifier in a request identifier
+ collection, you may want to consider using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>
+ instead.
</p>
<p>
The call <c>gen_statem:wait_response(gen_statem:send_request(ServerRef,Request), Timeout)</c>
@@ -1972,6 +2338,36 @@ handle_event(_, _, State, Data) ->
</func>
<func>
+ <name name="send_request" arity="4" since="OTP 25.0"/>
+ <fsummary>Sends a request to a generic server.</fsummary>
+ <desc>
+ <p>
+ Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c>
+ to the <c>gen_statem</c> process identified by <c><anno>ServerRef</anno></c>.
+ The <c><anno>Label</anno></c> will be associated with the request
+ identifier of the operation and added to the returned request
+ identifier collection <c><anno>NewReqIdCollection</anno></c>.
+ The collection can later be used in order to get one response
+ corresponding to a request in the collection by passing the
+ collection as argument to
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>,
+ <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>,
+ or,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>.
+ </p>
+
+ <p>
+ The same as calling
+ <seemfa marker="#reqids_add/3"><c>gen_statem:reqids_add</c></seemfa>(<seemfa
+ marker="#send_request/2"><c>statem:send_request</c></seemfa><c>(<anno>ServerRef</anno>,
+ <anno>Request</anno>), <anno>Label</anno>,
+ <anno>ReqIdCollection</anno>)</c>, but calling <c>send_request/4</c>
+ is slightly more efficient.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="start" arity="3" since="OTP 19.0"/>
<name name="start" arity="4" since="OTP 19.0"/>
<fsummary>Create a standalone <c>gen_statem</c> process.</fsummary>
@@ -2186,22 +2582,38 @@ handle_event(_, _, State, Data) ->
terminate, or the atom <c>infinity</c> to wait indefinitely.
Defaults to <c>infinity</c>.
If the server does not terminate within the specified time,
- a <c>timeout</c> exception is raised.
- </p>
- <p>
- If the process does not exist, a <c>noproc</c> exception
- is raised.
+ the call exits the calling process
+ with reason <c>timeout</c>.
</p>
+ <p>
+ If the process does not exist, the call exits
+ the calling process with reason <c>noproc</c>,
+ and with reason <c>{nodedown,Node}</c>
+ if the connection fails to the remote <c>Node</c>
+ where the server runs.
+ </p>
</desc>
</func>
<func>
- <name name="wait_response" arity="1" since="OTP 23.0"/>
- <name name="wait_response" arity="2" since="OTP 23.0"/>
+ <name name="wait_response" arity="1" clause_i="1" since="OTP 23.0"/>
<fsummary>Wait for a reply from a server.</fsummary>
<desc>
<p>
- This function is used to wait for a reply of a request made with
+ The same as calling
+ <seemfa marker="#receive_response/2"><c>gen_statem:receive_response(ReqId,
+ infinity)</c></seemfa>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="wait_response" arity="2" since="OTP 23.0"/>
+ <fsummary>Wait or poll for a reply from a server.</fsummary>
+ <desc>
+ <p>
+ Wait for a response corresponding to the request identifier
+ <c><anno>ReqId</anno></c>. The request must have been made by
<seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>
to the <c>gen_statem</c> process. This function must be called
from the same process from which
@@ -2209,11 +2621,8 @@ handle_event(_, _, State, Data) ->
was made.
</p>
<p>
- <c>Timeout</c> is an integer greater then or equal to zero
- that specifies how many milliseconds to wait for an reply, or
- the atom <c>infinity</c> to wait indefinitely. Defaults to
- <c>infinity</c>.
- If no reply is received within the specified
+ <c><anno>WaitTime</anno></c> specifies how long to wait for
+ a reply. If no reply is received within the specified
time, the function returns <c>timeout</c> and no cleanup is
done, and thus the function can be invoked repeatedly until a
reply is returned.
@@ -2233,13 +2642,90 @@ handle_event(_, _, State, Data) ->
</p>
<p>
The difference between
- <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa>
- and <c>wait_response()</c> is that <c>receive_response()</c>
+ <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>
+ and <c>wait_response/2</c> is that <c>receive_response/2</c>
abandons the request at timeout so that a potential future
- response is ignored, while <c>wait_response()</c> does not.
+ response is ignored, while <c>wait_response/2</c> does not.
</p>
</desc>
</func>
+
+ <func>
+ <name name="wait_response" arity="3" since="OTP 25.0"/>
+ <fsummary>Wait or poll for a response from a server.</fsummary>
+ <desc>
+ <p>
+ Wait for a response corresponding to a request identifier saved
+ in <c><anno>ReqIdCollection</anno></c>. All request identifiers
+ of <c><anno>ReqIdCollection</anno></c> must correspond to requests
+ that have been made using
+ <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>,
+ and all request must have been made by the process calling this
+ function.
+ </p>
+ <p>
+ The <c><anno>Label</anno></c> in the response equals the
+ <c><anno>Label</anno></c> associated with the request identifier
+ that the response corresponds to. The <c><anno>Label</anno></c>
+ of a request identifier is associated when
+ <seemfa marker="#reqids_add/3">saving the request id</seemfa> in
+ a request identifier collection, or when sending the request using
+ <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>.
+ </p>
+ <p>
+ Compared to
+ <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>,
+ the returned result associated with a specific request identifier
+ or an exception associated with a specific request identifier will
+ be wrapped in a 3-tuple. The first element of this tuple equals the
+ value that would have been produced by <c>wait_response/2</c>,
+ the second element equals the <c><anno>Label</anno></c> associated
+ with the specific request identifier, and the third element
+ <c><anno>NewReqIdCollection</anno></c> is a possibly modified
+ request identifier collection.
+ </p>
+ <p>
+ If <c><anno>ReqIdCollection</anno></c> is empty, <c>no_request</c>
+ will be returned. If no response is received before the
+ <c><anno>WaitTime</anno></c> timeout has triggered, the atom
+ <c>timeout</c> is returned. It is valid to continue waiting for a
+ response as many times as needed up until a response has been received
+ and completed by <c>check_response()</c>, <c>receive_response()</c>,
+ or <c>wait_response()</c>.
+ </p>
+ <p>
+ The difference between
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>
+ and <c>wait_response/3</c> is that <c>receive_response/3</c>
+ abandons requests at timeout so that a potential future
+ responses are ignored, while <c>wait_response/3</c> does not.
+ </p>
+ <p>
+ If <c><anno>Delete</anno></c> equals <c>true</c>, the association
+ with <c><anno>Label</anno></c> will have been deleted from
+ <c><anno>ReqIdCollection</anno></c> in the resulting
+ <c><anno>NewReqIdCollection</anno></c>. If
+ <c><anno>Delete</anno></c> equals <c>false</c>,
+ <c><anno>NewReqIdCollection</anno></c> will equal
+ <c><anno>ReqIdCollection</anno></c>. Note that deleting an
+ association is not for free and that a collection containing
+ already handled requests can still be used by subsequent calls to
+ <c>wait_response/3</c>,
+ <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>,
+ and
+ <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>.
+ However, without deleting handled associations, the above calls will
+ not be able to detect when there are no more outstanding requests to
+ handle, so you will have to keep track of this some other way than
+ relying on a <c>no_request</c> return. Note that if you pass a
+ collection only containing associations of already handled or
+ abandoned requests to <c>wait_response/3</c>, it will always block
+ until a timeout determined by <c><anno>WaitTime</anno></c> is
+ triggered and then return <c>no_reply</c>.
+ </p>
+ </desc>
+ </func>
</funcs>
@@ -2480,6 +2966,76 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
</func>
<func>
+ <name since="OTP 25.0">Module:format_status(Status) -> NewStatus</name>
+ <fsummary>Optional function for providing a term describing the
+ current <c>gen_statem</c> status.</fsummary>
+ <type>
+ <v>Status = <seetype marker="#format_status">format_status()</seetype></v>
+ <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v>
+ </type>
+ <desc>
+ <note>
+ <p>
+ This callback is optional, so a callback module does not need
+ to export it. The <c>gen_statem</c> module provides a default
+ implementation of this function that returns
+ <c>{State,Data}</c>.
+ </p>
+ <p>
+ If this callback is exported but fails,
+ to hide possibly sensitive data,
+ the default function will instead return <c>{State,Info}</c>,
+ where <c>Info</c> says nothing but the fact that
+ <c>format_status/2</c> has crashed.
+ </p>
+ </note>
+ <p>This function is called by a <c>gen_statem</c> process when
+ any of the following apply:</p>
+ <list type="bulleted">
+ <item>
+ <p><seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa>
+ is invoked to get the <c>gen_statem</c> status.</p>
+ </item>
+ <item>
+ <p>The <c>gen_statem</c> process terminates abnormally and logs an error.</p>
+ </item>
+ </list>
+ <p>
+ This function is useful for changing the form and
+ appearance of the <c>gen_statem</c> status for these cases. A
+ callback module wishing to change the
+ <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa>
+ return value and how
+ its status appears in termination error logs exports
+ an instance of <c>format_status/1</c>,
+ which will get a map <c>Status</c> that describes
+ the current states of the <c>gen_statem</c>,
+ and shall return a map <c>NewStatus</c>
+ containing the same keys as the input map,
+ but it may transform some values.
+ </p>
+ <p>
+ One use case for this function is to return compact alternative
+ state representations to avoid having large state terms
+ printed in log files. Another is to hide sensitive data from
+ being written to the error log.
+ </p>
+ <p>Example:</p>
+ <code type="erl"><![CDATA[
+format_status(Status) ->
+ maps:map(
+ fun(state,State) ->
+ maps:remove(private_key, State);
+ (message,{password, _Pass}) ->
+ {password, removed};
+ (_,Value) ->
+ Value
+ end, Status).
+]]></code>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP 19.0">Module:format_status(Opt, [PDict,State,Data]) ->
Status
</name>
@@ -2502,6 +3058,11 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
<v>Status = term()</v>
</type>
<desc>
+ <warning>
+ <p>This callback is deprecated, in new code use <seemfa marker="#Module:format_status/1">
+ format_status/1</seemfa>. If a <seemfa marker="#Module:format_status/1">format_status/1</seemfa>
+ callback exists, then this function will never be called.</p>
+ </warning>
<note>
<p>
This callback is optional, so a callback module does not need
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index f7b4506f14..d2d9870aee 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>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -175,6 +175,48 @@
</func>
<func>
+ <name name="enumerate" arity="1" since="OTP 25.0"/>
+ <fsummary>Annotates elements with their index.</fsummary>
+ <desc>
+ <p>Returns <c><anno>List1</anno></c> with each element
+ <c>H</c> replaced by a tuple of form <c>{I, H}</c> where
+ <c>I</c> is the position of <c>H</c> in
+ <c><anno>List1</anno></c>. The enumeration starts with 1 and
+ increases by 1 in each step.</p>
+ <p>That is, <c>enumerate/1</c> behaves as if it had been defined as follows:</p>
+ <code type="erl">
+enumerate(List) ->
+ {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+1} end, 1, List),
+ List1.</code>
+ <p><em>Example:</em></p>
+ <pre>
+> <input>lists:enumerate([a,b,c]).</input>
+[{1,a},{2,b},{3,c}]</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="enumerate" arity="2" since="OTP 25.0"/>
+ <fsummary>Annotates elements with their index.</fsummary>
+ <desc>
+ <p>Returns <c><anno>List1</anno></c> with each element
+ <c>H</c> replaced by a tuple of form <c>{I, H}</c> where
+ <c>I</c> is the position of <c>H</c> in
+ <c><anno>List1</anno></c>. The enumeration starts with
+ <c><anno>Index</anno></c> and increases by 1 in each step.</p>
+ <p>That is, <c>enumerate/2</c> behaves as if it had been defined as follows:</p>
+ <code type="erl">
+enumerate(I, List) ->
+ {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+1} end, I, List),
+ List1.</code>
+ <p><em>Example:</em></p>
+ <pre>
+> <input>lists:enumerate(10, [a,b,c]).</input>
+[{10,a},{11,b},{12,c}]</pre>
+ </desc>
+ </func>
+
+ <func>
<name name="filter" arity="2" since=""/>
<fsummary>Select elements that satisfy a predicate.</fsummary>
<desc>
@@ -1084,6 +1126,43 @@ splitwith(Pred, List) ->
[[a,x,1],[b,y,2],[c,z,3]]</pre>
</desc>
</func>
+
+ <func>
+ <name name="uniq" arity="1" since="OTP 25.0"/>
+ <fsummary>Removes duplicate elements of a list preserving the order.</fsummary>
+ <desc>
+ <p>Returns a list containing the elements of
+ <c><anno>List1</anno></c> with duplicated elements removed
+ (preserving the order of the elements). The first occurrence of
+ each element is kept.</p>
+ <p><em>Examples:</em></p>
+ <pre>
+> <input>lists:uniq([3,3,1,2,1,2,3]).</input>
+[3,1,2]
+> <input>lists:uniq([a, a, 1, b, 2, a, 3]).</input>
+[a, 1, b, 2, 3]</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="uniq" arity="2" since="OTP 25.0"/>
+ <fsummary>
+ Removes duplicate elements of a list using
+ a fun as a key preserving the order.
+ </fsummary>
+ <desc>
+ <p>Returns a list containing the elements of
+ <c><anno>List1</anno></c> without the elements for which
+ <c><anno>Fun</anno></c> returned duplicate values
+ (preserving the order of the elements). The first occurrence
+ of each element is kept.</p>
+ <p><em>Examples:</em></p>
+ <pre>
+> <input>lists:uniq(fun({X, _}) -> X end, [{b, 2}, {a, 1}, {c, 3}, {a, 2}]).</input>
+[{b, 2}, {a, 1}, {c, 3}]</pre>
+ </desc>
+ </func>
+
</funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml
index ea0f16eec9..203eeccaf3 100644
--- a/lib/stdlib/doc/src/maps.xml
+++ b/lib/stdlib/doc/src/maps.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2013</year><year>2021</year>
+ <year>2013</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,10 +43,15 @@
<p>An iterator representing the associations in a map with keys of type
<c><anno>Key</anno></c> and values of type <c><anno>Value</anno></c>.</p>
<p>Created using <seemfa marker="#iterator/1"><c>maps:iterator/1</c></seemfa>.</p>
- <p>Consumed by <seemfa marker="#next/1"><c>maps:next/1</c></seemfa>,
- <seemfa marker="#filter/2"><c>maps:filter/2</c></seemfa>,
- <seemfa marker="#fold/3"><c>maps:fold/3</c></seemfa> and
- <seemfa marker="#map/2"><c>maps:map/2</c></seemfa>.</p>
+ <p>Consumed by:</p>
+ <list type="bulleted">
+ <item><seemfa marker="#next/1"><c>maps:next/1</c></seemfa></item>
+ <item><seemfa marker="#filter/2"><c>maps:filter/2</c></seemfa></item>
+ <item><seemfa marker="#filtermap/2"><c>maps:filtermap/2</c></seemfa></item>
+ <item><seemfa marker="#fold/3"><c>maps:fold/3</c></seemfa></item>
+ <item><seemfa marker="#foreach/2"><c>maps:foreach/2</c></seemfa></item>
+ <item><seemfa marker="#map/2"><c>maps:map/2</c></seemfa></item>
+ </list>
</desc>
</datatype>
@@ -231,6 +236,39 @@ val1
</func>
<func>
+ <name name="groups_from_list" arity="2" since="OTP 25.0"/>
+ <fsummary>Splits the list into groups using a function as discriminator.</fsummary>
+ <desc>
+ <p>The result is a map where each key is given by <anno>Fun</anno>
+ and each value is a list of elements. The order of elements within
+ each list is preserved from the list.</p>
+ <p><em>Examples:</em></p>
+ <pre>
+> <input>maps:groups_from_list(fun(X) -> X rem 2 end, [1,2,3]).</input>
+#{0 => [2], 1 => [1, 3]}
+> <input>maps:groups_from_list(fun erlang:length/1, ["ant", "buffalo", "cat", "dingo"]).</input>
+#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="groups_from_list" arity="3" since="OTP 25.0"/>
+ <fsummary>Splits the list into groups using a function as discriminator.</fsummary>
+ <desc>
+ <p>The result is a map where each key is given by
+ <anno>Fun</anno> and each value is a list of elements given by
+ the <anno>ValueFun</anno>. The order of elements within each
+ list is preserved from the list.</p>
+ <p><em>Examples:</em></p>
+ <pre>
+> <input>maps:groups_from_list(fun(X) -> X rem 2 end, fun(X) -> X*X end, [1,2,3]).</input>
+#{0 => [4], 1 => [1, 9]}
+> <input>maps:groups_from_list(fun erlang:length/1, fun lists:reverse/1, ["ant", "buffalo", "cat", "dingo"]).</input>
+#{3 => ["tna","tac"],5 => ["ognid"],7 => ["olaffub"]}</pre>
+ </desc>
+ </func>
+
+ <func>
<name name="intersect" arity="2" since="OTP 24.0"/>
<fsummary></fsummary>
<desc>
@@ -606,7 +644,7 @@ error</code>
maps:update_with("new counter",Fun,42,Map).
#{"counter" => 1,"new counter" => 42}</code>
</desc>
- </func>
+ </func>
<func>
<name name="values" arity="1" since="OTP 17.0"/>
@@ -657,5 +695,6 @@ error</code>
#{1337 => "value two"}</code>
</desc>
</func>
+
</funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index bde9223eb0..2df25805f0 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2020</year>
+ <year>2002</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -389,8 +389,8 @@ ets:select(emp_tab, ets:fun2ms(
<item>
<p>The guard BIFs: <c>abs</c>, <c>element</c>,
<c>hd</c>, <c>length</c>,
- <c>node</c>, <c>round</c>, <c>size</c>, <c>tl</c>, <c>trunc</c>,
- <c>self</c></p>
+ <c>node</c>, <c>round</c>, <c>size</c>, <c>byte_size</c>, <c>tl</c>,
+ <c>trunc</c>, <c>binary_part</c>, <c>self</c></p>
</item>
</list>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index aaf1887dc8..403abf2be8 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2021</year>
+ <year>2004</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,713 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that would cause analysis to crash.</p>
+ <p>
+ Own Id: OTP-18372 Aux Id: GH-6580 </p>
+ </item>
+ <item>
+ <p>Fixed a crash when formatting stack traces for error
+ reports.</p>
+ <p>
+ Own Id: OTP-18375 Aux Id: GH-6591 </p>
+ </item>
+ <item>
+ <p>Instead of crashing, the <c>list_to_integer/1</c> and
+ <c>list_to_integer/2</c> BIFs now raise the
+ <c>system_limit</c> exception for overlong lists that
+ can't be converted to integers. Similarly, the
+ <c>string:to_integer/1</c> BIF now returns
+ <c>{error,system_limit}</c> for overlong lists.</p>
+ <p>
+ Own Id: OTP-18475 Aux Id: PR-6897 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Removal of non-necessary <c>undefined</c> types added to
+ the state's <c>supervisor</c> record.</p>
+ <p>
+ Own Id: OTP-18393 Aux Id: PR-6666 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>erl_tar</c> can now read gzip-compressed tar files
+ that are padded. There is a new option
+ <c>compressed_one</c> for <c>file:open/2</c> that will
+ read a single member from a gzip file,</p>
+ <p>
+ Own Id: OTP-18289 Aux Id: PR-6343 </p>
+ </item>
+ <item>
+ <p>
+ A concurrent call to <c>ets:rename</c> could cause
+ <c>ets:delete_all_objects</c> to fail halfway through
+ with badarg.</p>
+ <p>
+ Own Id: OTP-18292 Aux Id: PR-6366 </p>
+ </item>
+ <item>
+ <p>It is not allowed to call functions from guards. The
+ compiler failed to reject a call in a guard when done by
+ constructing a record with a default initialization
+ expression that called a function.</p>
+ <p>
+ Own Id: OTP-18325 Aux Id: GH-6465, GH-6466 </p>
+ </item>
+ <item>
+ <p>The compiler could crash when using a record with
+ complex field initialization expression as a filter in a
+ list comprehension.</p>
+ <p>
+ Own Id: OTP-18336 Aux Id: GH-6501, PR-6502 </p>
+ </item>
+ <item>
+ <p>
+ <c>unicode:characters_to_binary()</c> could build
+ unnecessarily large call stack.</p>
+ <p>
+ Own Id: OTP-18351 Aux Id: ERIERL-885, PR-6529 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improve error message for ets:new/2 name clash. Say "name
+ already exists" instead of less specific "invalid
+ options".</p>
+ <p>
+ Own Id: OTP-18283 Aux Id: PR-6338 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 4.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <seeerl marker="stdlib:peer"><c>peer</c></seeerl> nodes
+ failed to halt when the process supervising the control
+ connection crashed. When an alternative control
+ connection was used, this supervision process also quite
+ frequently crashed when the <c>peer</c> node was stopped
+ by the node that started it which caused the <c>peer</c>
+ node to linger without ever halting.</p>
+ <p>
+ Own Id: OTP-18249 Aux Id: PR-6301 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed inconsistency bugs in <seeerl
+ marker="kernel:global"><c>global</c></seeerl> due to
+ <c>nodeup</c>/<c>nodedown</c> messages not being
+ delivered before/after traffic over connections. Also
+ fixed various other inconsistency bugs and deadlocks in
+ both <seeerl
+ marker="kernel:global_group"><c>global_group</c></seeerl>
+ and <c>global</c>.</p>
+ <p>
+ As building blocks for these fixes, a new BIF <seemfa
+ marker="erts:erlang#nodes/2"><c>erlang:nodes/2</c></seemfa>
+ has been introduced and <seemfa
+ marker="kernel:net_kernel#monitor_nodes/2"><c>net_kernel:monitor_nodes/2</c></seemfa>
+ has been extended.</p>
+ <p>
+ The <seecom
+ marker="erts:erl#hidden"><c>-hidden</c></seecom> and
+ <seecom
+ marker="erts:erl#connect_all"><c>-connect_all</c></seecom>
+ command line arguments did not work if multiple instances
+ were present on the command line which has been fixed.
+ The new kernel parameter <seeapp
+ marker="kernel:kernel_app#connect_all"><c>connect_all</c></seeapp>
+ has also been introduced in order to replace the
+ <c>-connect_all</c> command line argument.</p>
+ <p>
+ Own Id: OTP-17934 Aux Id: PR-6007 </p>
+ </item>
+ <item>
+ <p>
+ Fix the <c>public_key:ssh*</c> functions to be listed
+ under the correct release in the Removed Functionality
+ User's Guide.</p>
+ <p>
+ Own Id: OTP-18139 Aux Id: PR-6060 </p>
+ </item>
+ <item>
+ <p>
+ The type spec for <c>format_status/1</c> in
+ <c>gen_statem</c>, <c>gen_server</c> and <c>gen_event</c>
+ has been corrected to state that the return value is of
+ the same type as the argument (instead of the same value
+ as the argument).</p>
+ <p>
+ Own Id: OTP-18142 Aux Id: PR-6078 </p>
+ </item>
+ <item>
+ <p>
+ If the <c>timer</c> server child spec was already present
+ in <c>kernel_sup</c> but it was not started, the
+ <c>timer</c> server would fail to start with an
+ <c>{error, already_present}</c> error instead of
+ restarting the server.</p>
+ <p>
+ Own Id: OTP-18146 Aux Id: PR-5983 </p>
+ </item>
+ <item>
+ <p>When changing callback module in <c>gen_statem</c> the
+ state_enter calls flag from the old module was used in
+ for the first event in the new module, which could
+ confuse the new module and cause malfunction. This bug
+ has been corrected. </p><p> With this change some
+ <c>sys</c> debug message formats have been modified,
+ which can be a problem for debug code relying on the
+ format. </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18239</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ <item>
+ <p>The <c>rfc339_to_system_time/1,2</c> functions now
+ allows the minutes part to be omitted from the time
+ zone.</p>
+ <p>
+ Own Id: OTP-18166 Aux Id: PR-6108 </p>
+ </item>
+ <item>
+ <p>
+ The <c>receive</c> statement in <c>gen_event</c> has been
+ optimized to not use selective receive (which was never
+ needed, and could cause severe performance degradation
+ under heavy load).</p>
+ <p>
+ Own Id: OTP-18194 Aux Id: PR-6199 </p>
+ </item>
+ <item>
+ <p>
+ Add new API function erl_features:configurable/0</p>
+ <p>
+ Own Id: OTP-18199 Aux Id: PR-5790 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 4.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ In the initial release of Erlang/OTP 25, the expression
+ bound to the <c>_</c> pseudo-field in a record
+ initialization would always be evaluated once, even if
+ all other fields in the record were explicitly
+ initialized. That would break the use case of binding the
+ expression <c>error(...)</c> to <c>_</c> in order to get
+ an exception if not all fields were initialized.</p>
+ <p>
+ The behavior of binding to <c>_</c> has been reverted to
+ the pre-OTP 25 behavior, that is, to not evaluate the
+ expression if all fields have been bound to explicit
+ values.</p>
+ <p>
+ Own Id: OTP-18110 Aux Id: GH-6000 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 4.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improve the Erlang code linter's check of unused types.</p>
+ <p>
+ Own Id: OTP-17370 Aux Id: GH-4784 </p>
+ </item>
+ <item>
+ <p>
+ Fix race condition in <seemfa
+ marker="stdlib:proc_lib#stop/3"><c>proc_lib:stop/3</c></seemfa>
+ where the process is not stopped when the timeout given
+ is very short.</p>
+ <p>
+ Own Id: OTP-17480 Aux Id: GH-4853 PR-4872 </p>
+ </item>
+ <item>
+ <p>Maps are now fully supported in by
+ <c>ms_transform</c>.</p>
+ <p>
+ Own Id: OTP-17518 Aux Id: GH-4915 </p>
+ </item>
+ <item>
+ <p>
+ Fix gen_server:call with the first argument as self() to
+ throw an error instead of failing with a timeout.</p>
+ <p>
+ The same fix has also been done for gen_statem:call/3,
+ gen_event:sync_notify/2 and any other functionality
+ relying on the internal gen:call/3 function.</p>
+ <p>
+ A similar fix was also done when using io:format/2 and
+ the current group_leader was set to the current process.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17544 Aux Id: PR-5008 </p>
+ </item>
+ <item>
+ <p>
+ erl_pp printed unary - and + operators with a space
+ between the operator and the operand. This is fixed by
+ not having any space in between.</p>
+ <p>
+ Own Id: OTP-17566 Aux Id: PR-5095, GH-5093 </p>
+ </item>
+ <item>
+ <p>
+ Adjust uri_string:normalize behavior for URIs with
+ undefined port (URI string with a port colon but no port
+ value or URI map with port => undefined).</p>
+ <p>
+ Remove redundant normalization from http_request module.</p>
+ <p>
+ Before this change, normalize would not remove port
+ subcomponent in such cases and could for example return
+ "http://localhost:" URI.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17627</p>
+ </item>
+ <item>
+ <p>
+ Fix reduction counting bug in <c>re:run</c> that caused
+ the function to yield too frequently when doing
+ <c>global</c> matches.</p>
+ <p>
+ Own Id: OTP-17661 Aux Id: PR-5165 </p>
+ </item>
+ <item>
+ <p>
+ Fix the memory value returned from
+ <c>ets:info(Tid,memory)</c> when the
+ <c>read_concurrency</c> option is used.</p>
+ <p>
+ Before this fix the memory used by the scheduler specific
+ lock cache lines was not counted towards the total. This
+ caused the returned memory usage to be very incorrect on
+ systems with many schedulers for tables with man locks.</p>
+ <p>
+ Own Id: OTP-17832 Aux Id: PR-5494 </p>
+ </item>
+ <item>
+ <p>
+ Avoid confusion by correcting the argument order in the
+ gen_event crash log printout.</p>
+ <p>
+ Own Id: OTP-17878</p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>string:next_grapheme/1</c> to return an empty
+ binary in the tail for binary input for the last grapheme
+ cluster.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18009 Aux Id: PR-5785 </p>
+ </item>
+ <item>
+ <p>
+ Fixed type specifications of the
+ <c>supervisor:sup_name/0</c> and
+ <c>supervisor:sup_ref/0</c> types.</p>
+ <p>
+ Own Id: OTP-18034 Aux Id: PR-4661, GH-4622 </p>
+ </item>
+ <item>
+ <p>
+ If a default record field initialization (<c>_ =
+ Expr</c>) was used even though all records fields were
+ explicitly initialized, <c>Expr</c> would not be
+ evaluated. That would not be a problem, except when
+ <c>Expr</c> would bind a variable subsequently used, in
+ which case the compiler would crash.</p>
+ <p>
+ As an example, if record <c>#r{}</c> is defined to have
+ only one field <c>a</c>, the following code would crash
+ the compiler:</p>
+ <p>
+ <c>#r{a=[],_=V=42}, V</c></p>
+ <p>
+ To fix that problem, the compiler will make sure that
+ <c>Expr</c> is always evaluated at least once. The
+ compiler will now rewrite the example to essentially:</p>
+ <p>
+ <c>V=42, #r{a=[]}, V</c></p>
+ <p>
+ Own Id: OTP-18083</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Users can now configure ETS tables with the
+ <c>{write_concurrency, auto}</c> option. This option
+ forces tables to automatically change the number of locks
+ that are used at run-time depending on how much
+ concurrency is detected. The <c>{decentralized_counters,
+ true}</c> option is enabled by default when
+ <c>{write_concurrency, auto}</c> is active.</p>
+ <p>
+ Benchmark results comparing this option with the other
+ ETS optimization options are available here:</p>
+ <p>
+ https://erlang.org/bench/ets_bench_result_lock_config.html</p>
+ <p>
+ Own Id: OTP-15991 Aux Id: PR-5208 </p>
+ </item>
+ <item>
+ <p>
+ The <c>format_status/2</c> callback for
+ <c>gen_server</c>, <c>gen_statem</c> and <c>gen_event</c>
+ has been deprecated in favor of the new
+ <c>format_status/1</c> callback.</p>
+ <p>
+ The new callback adds the possibility to limit and change
+ many more things than the just the state, such as the
+ last received message, the reason for terminating and
+ more events specific to each type of behavior. See the
+ respective modules documentation for more details.</p>
+ <p>
+ Own Id: OTP-17351 Aux Id: GH-4673 PR-4952 </p>
+ </item>
+ <item>
+ <p>The <c>timer</c> module has been modernized and made
+ more efficient, which makes the timer server less
+ susceptible to being overloaded. The <c>timer:sleep/1</c>
+ function now accepts an arbitrarily large integer.</p>
+ <p>
+ Own Id: OTP-17481 Aux Id: PR-4811 </p>
+ </item>
+ <item>
+ <p>
+ Add <c>lists:enumerate/[1,2]</c>.</p>
+ <p>
+ Own Id: OTP-17523 Aux Id: PR-4928 </p>
+ </item>
+ <item>
+ <p>
+ The configuration files <seecom
+ marker="erts:erl"><c>.erlang</c></seecom>, <seeguide
+ marker="system/reference_manual:distributed"><c>.erlang.cookie</c></seeguide>
+ and <seeerl
+ marker="stdlib:beam_lib#.erlang.crypt"><c>.erlang.crypt</c></seeerl>
+ can now be located in the XDG Config Home directory.</p>
+ <p>
+ See the documentation for each file and
+ <c>filename:basedir/2</c> for more details.</p>
+ <p>
+ Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821 </p>
+ </item>
+ <item>
+ <p>
+ Support <c>native</c> time unit in <c>calendar</c>
+ functions <c>system_time_to_rfc3339/2</c> and
+ <c>rfc3339_to_system_time</c>.</p>
+ <p>
+ Own Id: OTP-17592 Aux Id: ERIERL-663, PR-5243 </p>
+ </item>
+ <item>
+ <p>
+ The tagged tuple tests and fun-calls have been optimized
+ and are now a little bit cheaper than previously.</p>
+ <p>
+ These optimizations become possible after making sure
+ that all boxed terms have at least one word allocated
+ after the arity word. This has been accomplished by
+ letting all empty tuples refer to the same empty tuple
+ literal which also reduces memory usage for empty tuples.</p>
+ <p>
+ Own Id: OTP-17608</p>
+ </item>
+ <item>
+ <p>
+ The signal queue benchmark in parallel_messages_SUITE and
+ the ETS benchmark in ets_SUITE have benchmark result
+ visualization HTML pages with "fill-screen" buttons to
+ make the graphs bigger. This button did not work as
+ intended before. When pressing the button for a graph,
+ the last graph got replaced with a bigger version and not
+ the one over the button. This is now fixed.</p>
+ <p>
+ Own Id: OTP-17630</p>
+ </item>
+ <item>
+ <p>
+ The new module <c>peer</c> supersedes the <c>slave</c>
+ module. The <c>slave</c> module is now deprecated and
+ will be removed in OTP 27.</p>
+ <p>
+ <c>peer</c> contains an extended and more robust API for
+ starting erlang nodes.</p>
+ <p>
+ Own Id: OTP-17720 Aux Id: PR-5162 </p>
+ </item>
+ <item>
+ <p>
+ This change introduces quote and unquote functions in
+ uri_string module - a replacement for deprecated encode
+ and decode functions from http_uri.</p>
+ <p>
+ Own Id: OTP-17778 Aux Id: GH-5368 </p>
+ </item>
+ <item>
+ <p>
+ In order to make it easier for the user to manage
+ multiple outstanding asynchronous <c>call</c> requests,
+ new functionality utilizing request identifier
+ collections have been introduced in <seetype
+ marker="kernel:erpc#request_id_collection"><c>erpc</c></seetype>,
+ <seetype
+ marker="stdlib:gen_server#request_id_collection"><c>gen_server</c></seetype>,
+ <seetype
+ marker="stdlib:gen_statem#request_id_collection"><c>gen_statem</c></seetype>,
+ and <seetype
+ marker="stdlib:gen_event#request_id_collection"><c>gen_event</c></seetype>.</p>
+ <p>
+ Own Id: OTP-17784 Aux Id: PR-5792 </p>
+ </item>
+ <item>
+ <p>
+ Update to the Unicode 14.0 specification.</p>
+ <p>
+ Own Id: OTP-17869 Aux Id: PR-5595 </p>
+ </item>
+ <item>
+ <p>
+ The following ets types have been renamed to a clearer
+ name: <c>tab/0</c> to <c>table/0</c> and
+ <c>comp_match_spec/0</c> to <c>compiled_match_spec/0</c>.</p>
+ <p>
+ The types <c>table_access/0</c> and <c>table_type/0</c>
+ have been exported.</p>
+ <p>
+ Own Id: OTP-17901 Aux Id: GH-4968 PR-5649 </p>
+ </item>
+ <item>
+ <p>
+ Add support for locating <c>.asn1</c> files to the
+ default search rules of <c>filelib:find_file/1</c> and
+ <c>filelib:find_source/1</c>.</p>
+ <p>
+ Own Id: OTP-17908 Aux Id: GH-5655 PR-5669 </p>
+ </item>
+ <item>
+ <p>Type specifications have been added to the
+ <c>gen_server</c>, and the documentation has been updated
+ to utilize this. </p><p>This surfaced a few type
+ violations that has been corrected in <c>global</c>,
+ <c>logger_olp</c> and <c>rpc</c>. </p>
+ <p>
+ Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690 </p>
+ </item>
+ <item>
+ <p>The non-local function handler for the <c>erl_eval</c>
+ can now be called with either two or three arguments.
+ When called with three arguments, the first argument is
+ the annotation for the node in the abstract format.</p>
+ <p>All errors during evaluation will now be passed
+ through <c>erlang:raise/3</c>. If the restricted shell is
+ active and it does not let <c>erlang:raise/3</c> through,
+ evaluation errors will be printed in less clear way. See
+ the documentation for restricted shell in
+ <c>shell</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17925 Aux Id: PR-5631 </p>
+ </item>
+ <item>
+ <p>Added <c>filelib:ensure_path/1</c> that ensures that
+ all directories for the given path exists (unlike
+ <c>filelib:ensure_dir/1</c>, which will not create the
+ last segment of the path).</p>
+ <p>
+ Own Id: OTP-17953 Aux Id: PR-5621 </p>
+ </item>
+ <item>
+ <p>The functions <c>groups_from_list/2</c> and
+ <c>groups_from_list/3</c> have been added to the
+ <c>maps</c> module.</p>
+ <p>
+ Own Id: OTP-17969 Aux Id: PR-5588 </p>
+ </item>
+ <item>
+ <p>
+ <c>gen_server</c> has been refactored to throw more
+ readable exceptions when a callback returns bad values in
+ the <c>Timeout</c> field (<c>timeout() | 'hibernate' |
+ {'continue,_}</c>), and also to verify that argument in
+ the <c>gen_server:enter_loop/3,4,5</c> API function.</p>
+ <p>
+ Own Id: OTP-17974 Aux Id: GH-5683 </p>
+ </item>
+ <item>
+ <p>The functions <c>uniq/1</c> and <c>uniq/2</c> for
+ removing duplicates have been added to the <c>lists</c>
+ module.</p>
+ <p>
+ Own Id: OTP-17977 Aux Id: GH-5606, PR-5766 </p>
+ </item>
+ <item>
+ <p>
+ Added support for configurable features as described in
+ EEP-60. Features can be enabled/disabled during
+ compilation with options (<c>-enable-feature Feature</c>,
+ <c>-disable-feature Feature</c> and <c>+{feature,
+ Feature, enable|disable}</c>) to <c>erlc</c> as well as
+ with directives (<c>-feature(Feature,
+ enable|disable).</c>) in the file. Similar options can be
+ used to <c>erl</c> for enabling/disabling features
+ allowed at runtime. The new <c>maybe</c> expression
+ (EEP-49) is fully supported as the feature
+ <c>maybe_expr</c>. The features support is documented in
+ the reference manual.</p>
+ <p>
+ Own Id: OTP-17988</p>
+ </item>
+ <item>
+ <p>The function <c>filename:safe_relative_path/1</c>,
+ which has been deprecated since OTP 25, has been removed.
+ Use <c>filelib:safe_relative_path/2</c> instead.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17991</p>
+ </item>
+ <item>
+ <p> A new PRNG have been added to the <c>rand</c> module:
+ <c>mwc59</c> which has been developed in collaboration
+ with Sebastiano Vigna. It is intended for applications
+ that need really fast pseudo-random numbers, and it comes
+ with two output value scramblers, one fast and one
+ thorough. </p><p> Two internal functions for the
+ <c>exsp</c> generator have also been exported so they can
+ be used outside the <c>rand</c> plug-in framework to
+ shave off some overhead. </p><p> The internal
+ <c>splitmix64</c> generator has also been exported which
+ can be useful for seeding other kinds of PRNG:s than its
+ own. </p>
+ <p>
+ Own Id: OTP-18011</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.17.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>It is not allowed to call functions from guards. The
+ compiler failed to reject a call in a guard when done by
+ constructing a record with a default initialization
+ expression that called a function.</p>
+ <p>
+ Own Id: OTP-18325 Aux Id: GH-6465, GH-6466 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>STDLIB 3.17.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>When changing callback module in <c>gen_statem</c> the
+ state_enter calls flag from the old module was used in
+ for the first event in the new module, which could
+ confuse the new module and cause malfunction. This bug
+ has been corrected. </p><p> With this change some
+ <c>sys</c> debug message formats have been modified,
+ which can be a problem for debug code relying on the
+ format. </p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-18239</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.17.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml
index e4540e9217..35127dcf95 100644
--- a/lib/stdlib/doc/src/ordsets.xml
+++ b/lib/stdlib/doc/src/ordsets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -155,7 +155,9 @@
<fsummary>Test for an <c>Ordset</c>.</fsummary>
<desc>
<p>Returns <c>true</c> if <c><anno>Ordset</anno></c> is an ordered set
- of elements, otherwise <c>false</c>.</p>
+ of elements, otherwise <c>false</c>. This function will
+ return <c>true</c> for any ordered list, even when not
+ constructed by the functions in this module.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/peer.xml b/lib/stdlib/doc/src/peer.xml
new file mode 100644
index 0000000000..d8ac800605
--- /dev/null
+++ b/lib/stdlib/doc/src/peer.xml
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<!-- %ExternalCopyright% -->
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2021</year><year>2021</year>
+ <holder>Maxim Fedorov, WhatsApp Inc.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>peer</title>
+ <prepared>maximfca@gmail.com</prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>peer.xml</file>
+ </header>
+ <module since="OTP 25.0">peer</module>
+ <modulesummary>Start and control linked Erlang nodes.
+ </modulesummary>
+ <description>
+ <p>
+ This module provides functions for starting linked Erlang nodes.
+ The node spawning new nodes is called <em>origin</em>, and newly started
+ nodes are <em>peer</em> nodes, or peers. A peer node automatically
+ terminates when it loses the <em>control connection</em> to the origin. This
+ connection could be an Erlang distribution connection, or an alternative -
+ TCP or standard I/O. The alternative connection provides a way to execute
+ remote procedure calls even when Erlang Distribution is not available,
+ allowing to test the distribution itself.
+ </p>
+
+ <p>
+ Peer node terminal input/output is relayed through the origin.
+ If a standard I/O alternative connection is requested, console output
+ also goes via the origin, allowing debugging of node startup and boot
+ script execution (see <seecom marker="erts:erl#init_debug">
+ <c>-init_debug</c></seecom>). File I/O is not redirected, contrary to
+ <seeerl marker="slave"><c>slave(3)</c></seeerl> behaviour.
+ </p>
+
+ <p>
+ The peer node can start on the same or a different host (via <c>ssh</c>)
+ or in a separate container (for example Docker).
+ When the peer starts on the same host as the origin, it inherits
+ the current directory and environment variables from the origin.
+ </p>
+
+ <note>
+ <p>
+ This module is designed to facilitate multi-node testing with Common Test.
+ Use the <c>?CT_PEER()</c> macro to start a linked peer node according to
+ Common Test conventions: crash dumps written to specific location, node
+ name prefixed with module name, calling function, and origin OS process
+ ID). Use <seemfa marker="#random_name/1"><c>random_name/1</c></seemfa> to
+ create sufficiently unique node names if you need more control.
+ </p>
+ <p>
+ A peer node started without alternative connection behaves similarly
+ to <seeerl marker="slave"><c>slave(3)</c></seeerl>. When an alternative
+ connection is requested, the behaviour is similar to
+ <c>test_server:start_node(Name, peer, Args).</c>
+ </p> </note>
+
+ </description>
+
+ <section>
+ <title>Example</title>
+ <p>
+ The following example implements a test suite starting extra Erlang nodes.
+ It employs a number of techniques to speed up testing and reliably shut
+ down peer nodes:
+ </p>
+ <list>
+ <item>peers start linked to test runner process. If the test case fails,
+ the peer node is stopped automatically, leaving no rogue nodes running in
+ the background</item>
+ <item>arguments used to start the peer are saved in the control process
+ state for manual analysis. If the test case fails, the CRASH REPORT contains
+ these arguments</item>
+ <item>multiple test cases can run concurrently speeding up overall testing
+ process, peer node names are unique even when there are multiple instances
+ of the same test suite running in parallel</item>
+ </list>
+ <code type="erl">
+ -module(my_SUITE).
+ -behaviour(ct_suite).
+ -export([all/0, groups/0]).
+ -export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).
+
+ -include_lib("common_test/include/ct.hrl").
+
+ groups() ->
+ [{quick, [parallel],
+ [basic, args, named, restart_node, multi_node]}].
+
+ all() ->
+ [{group, quick}].
+
+ basic(Config) when is_list(Config) ->
+ {ok, Peer, _Node} = ?CT_PEER(),
+ peer:stop(Peer).
+
+ args(Config) when is_list(Config) ->
+ %% specify additional arguments to the new node
+ {ok, Peer, _Node} = ?CT_PEER(["-emu_flavor", "smp"]),
+ peer:stop(Peer).
+
+ named(Config) when is_list(Config) ->
+ %% pass test case name down to function starting nodes
+ Peer = start_node_impl(named_test),
+ peer:stop(Peer).
+
+ start_node_impl(ActualTestCase) ->
+ {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),
+ %% extra setup needed for multiple test cases
+ ok = rpc:call(Node, application, set_env, [kernel, key, value]),
+ Peer.
+
+ restart_node(Config) when is_list(Config) ->
+ Name = ?CT_PEER_NAME(),
+ {ok, Peer, Node} = ?CT_PEER(#{name => Name}),
+ peer:stop(Peer),
+ %% restart the node with the same name as before
+ {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => ["+fnl"]}),
+ peer:stop(Peer2).
+ </code>
+
+ <p>
+ The next example demonstrates how to start multiple nodes concurrently:
+ </p>
+ <code type="erl">
+ multi_node(Config) when is_list(Config) ->
+ Peers = [?CT_PEER(#{wait_boot => {self(), tag}})
+ || _ &lt;- lists:seq(1, 4)],
+ %% wait for all nodes to complete boot process, get their names:
+ _Nodes = [receive {tag, {started, Node, Peer}} -> Node end
+ || {ok, Peer} &lt;- Peers],
+ [peer:stop(Peer) || {ok, Peer} &lt;- Peers].
+ </code>
+
+ <p>
+ Start a peer on a different host. Requires <c>ssh</c> key-based
+ authentication set up, allowing "another_host" connection without password
+ prompt.
+ </p>
+ <code type="erl">
+ Ssh = os:find_executable("ssh"),
+ peer:start_link(#{exec => {Ssh, ["another_host", "erl"]},
+ connection => standard_io}),
+ </code>
+
+ <p>
+ The following Common Test case demonstrates Docker integration, starting two
+ containers with hostnames "one" and "two". In this example Erlang nodes
+ running inside containers form an Erlang cluster.
+ </p>
+ <code type="erl">
+ docker(Config) when is_list(Config) ->
+ Docker = os:find_executable("docker"),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ build_release(PrivDir),
+ build_image(PrivDir),
+
+ %% start two Docker containers
+ {ok, Peer, Node} = peer:start_link(#{name => lambda,
+ connection => standard_io,
+ exec => {Docker, ["run", "-h", "one", "-i", "lambda"]}}),
+ {ok, Peer2, Node2} = peer:start_link(#{name => lambda,
+ connection => standard_io,
+ exec => {Docker, ["run", "-h", "two", "-i", "lambda"]}}),
+
+ %% find IP address of the second node using alternative connection RPC
+ {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),
+ {"eth0", Eth0} = lists:keyfind("eth0", 1, Ips),
+ {addr, Ip} = lists:keyfind(addr, 1, Eth0),
+
+ %% make first node to discover second one
+ ok = peer:call(Peer, inet_db, set_lookup, [[file]]),
+ ok = peer:call(Peer, inet_db, add_host, [Ip, ["two"]]),
+
+ %% join a cluster
+ true = peer:call(Peer, net_kernel, connect_node, [Node2]),
+ %% verify that second peer node has only the first node visible
+ [Node] = peer:call(Peer2, erlang, nodes, []),
+
+ %% stop peers, causing containers to also stop
+ peer:stop(Peer2),
+ peer:stop(Peer).
+
+ build_release(Dir) ->
+ %% load sasl.app file, otherwise application:get_key will fail
+ application:load(sasl),
+ %% create *.rel - release file
+ RelFile = filename:join(Dir, "lambda.rel"),
+ Release = {release, {"lambda", "1.0.0"},
+ {erts, erlang:system_info(version)},
+ [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}
+ || App &lt;- [kernel, stdlib, sasl]]},
+ ok = file:write_file(RelFile, list_to_binary(lists:flatten(
+ io_lib:format("~tp.", [Release])))),
+ RelFileNoExt = filename:join(Dir, "lambda"),
+
+ %% create boot script
+ {ok, systools_make, []} = systools:make_script(RelFileNoExt,
+ [silent, {outdir, Dir}]),
+ %% package release into *.tar.gz
+ ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).
+
+ build_image(Dir) ->
+ %% Create Dockerfile example, working only for Ubuntu 20.04
+ %% Expose port 4445, and make Erlang distribution to listen
+ %% on this port, and connect to it without EPMD
+ %% Set cookie on both nodes to be the same.
+ BuildScript = filename:join(Dir, "Dockerfile"),
+ Dockerfile =
+ "FROM ubuntu:20.04 as runner\n"
+ "EXPOSE 4445\n"
+ "WORKDIR /opt/lambda\n"
+ "COPY lambda.tar.gz /tmp\n"
+ "RUN tar -zxvf /tmp/lambda.tar.gz -C /opt/lambda\n"
+ "ENTRYPOINT [\"/opt/lambda/erts-" ++ erlang:system_info(version) ++
+ "/bin/dyn_erl\", \"-boot\", \"/opt/lambda/releases/1.0.0/start\","
+ " \"-kernel\", \"inet_dist_listen_min\", \"4445\","
+ " \"-erl_epmd_port\", \"4445\","
+ " \"-setcookie\", \"secret\"]\n",
+ ok = file:write_file(BuildScript, Dockerfile),
+ os:cmd("docker build -t lambda " ++ Dir).
+ </code>
+ </section>
+
+ <datatypes>
+ <datatype>
+ <name name="server_ref"/>
+ <desc>
+ <p>
+ Identifies the controlling process of a peer node.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="start_options"/>
+ <desc>
+ <p>
+ Options that can be used when starting
+ a <c>peer</c> node through <seemfa marker="#start/1"><c>start/1</c></seemfa>
+ and <seemfa marker="#start_link/0"><c>start_link/0,1</c></seemfa>.
+ </p>
+ <taglist>
+ <tag><c>name</c></tag>
+ <item>
+ <p>
+ Node name (the part before "@"). When <c>name</c> is not specified, but <c>host</c>
+ is, <c>peer</c> follows compatibility behaviour and uses the origin node name.
+ </p>
+ </item>
+ <tag><c>host</c></tag>
+ <item>
+ <p>
+ Enforces a specific host name. Can be used to override the default
+ behaviour and start "node@localhost" instead of "node@realhostname".
+ </p>
+ </item>
+ <tag><c>longnames</c></tag>
+ <item>
+ <p>
+ Use long names to start a node. Default is taken from the origin
+ using <c>net_kernel:longnames()</c>. If the origin is not distributed,
+ short names is the default.
+ </p>
+ </item>
+ <tag><c>peer_down</c></tag>
+ <item>
+ <p>
+ Defines the peer control process behaviour when the control connection is
+ closed from the peer node side (for example when the peer crashes or dumps core).
+ When set to <c>stop</c> (default), a lost control connection causes
+ the control process to exit normally. Setting <c>peer_down</c> to <c>continue</c>
+ keeps the control process running, and <c>crash</c> will cause
+ the controlling process to exit abnormally.
+ </p>
+ </item>
+ <tag><c>exec</c></tag>
+ <item>
+ <p>
+ Alternative mechanism to start peer nodes with, for example, ssh instead of the
+ default bash.
+ </p>
+ </item>
+ <tag><c>connection</c></tag>
+ <item>
+ <p>Alternative connection specification. See the
+ <seetype marker="#connection"><c>connection</c> datatype</seetype>.</p>
+ </item>
+ <tag><c>args</c></tag>
+ <item>
+ <p>Extra command line arguments to append to the "erl" command. Arguments are
+ passed as is, no escaping or quoting is needed or accepted.</p>
+ </item>
+ <tag><c>env</c></tag>
+ <item>
+ <p>
+ List of environment variables with their values. This list is applied
+ to a locally started executable. If you need to change the environment of
+ the remote peer, adjust <c>args</c> to contain
+ <c>-env ENV_KEY ENV_VALUE</c>.
+ </p>
+ </item>
+ <tag><c>wait_boot</c></tag>
+ <item>
+ <p>Specifies the start/start_link timeout.
+ See <seetype marker="#wait_boot"><c>wait_boot</c> datatype</seetype>.
+ </p>
+ </item>
+ <tag><c>shutdown</c></tag>
+ <item>
+ <p>Specifies the peer node stopping behaviour. See
+ <seemfa marker="#stop/1"><c>stop()</c></seemfa>.</p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="peer_state"/>
+ <desc><p>Peer node state.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="connection"/>
+ <desc><p>Alternative connection between the origin and the peer. When the
+ connection closes, the peer node terminates automatically. If
+ the <c>peer_down</c> startup flag is set to <c>crash</c>, the controlling
+ process on the origin node exits with corresponding reason, effectively
+ providing a two-way link. </p>
+ <p>When <c>connection</c> is set to a port number, the origin starts listening on
+ the requested TCP port, and the peer node connects to the port. When it is set to
+ an <c>{IP, Port}</c> tuple, the origin listens only on the specified IP. The port
+ number can be set to 0 for automatic selection.
+ </p>
+ <p>Using the <c>standard_io</c> alternative connection starts the peer attached to
+ the origin (other connections use <c>-detached</c> flag to erl). In this mode
+ peer and origin communicate via stdin/stdout.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="exec"/>
+ <desc>
+ <p>
+ Overrides executable to start peer nodes with. By default it is
+ the path to "erl", taken from <c>init:get_argument(progname)</c>.
+ If <c>progname</c> is not known, <c>peer</c> makes best guess given the current
+ ERTS version.
+ </p>
+ <p>
+ When a tuple is passed, the first element is the path to executable,
+ and the second element is prepended to the final command line. This can be used
+ to start peers on a remote host or in a Docker container. See the examples
+ above.
+ </p>
+ <p>
+ This option is useful for testing backwards compatibility with previous releases,
+ installed at specific paths, or when the Erlang installation location
+ is missing from the <c>PATH</c>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="wait_boot"/>
+ <desc><p>Specifies start/start_link timeout in milliseconds. Can be set to
+ <c>false</c>, allowing the peer to start asynchronously. If <c>{Pid, Tag}</c>
+ is specified instead of a timeout, the peer will send <c>Tag</c> to the
+ requested process.</p></desc>
+ </datatype>
+ <datatype>
+ <name name="disconnect_timeout"/>
+ <desc><p>Disconnect timeout. See
+ <seemfa marker="#stop/1"><c>stop()</c></seemfa>.</p></desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+
+ <func>
+ <name name="call" arity="4" since="OTP 25.0"/>
+ <name name="call" arity="5" since="OTP 25.0"/>
+ <fsummary>Evaluates a function call on a peer node.</fsummary>
+ <desc>
+ <p>
+ Uses the alternative connection to
+ evaluate <c>apply(<anno>Module</anno>, <anno>Function</anno>,
+ <anno>Args</anno>)</c> on the peer node and returns
+ the corresponding value <c><anno>Result</anno></c>.
+ <c><anno>Timeout</anno></c> is an integer representing
+ the timeout in milliseconds or the atom <c>infinity</c>
+ which prevents the operation from ever timing out.
+ </p>
+ <p>
+ When an alternative connection is not requested, this
+ function will raise <c>exit</c> signal with the <c>noconnection</c>
+ reason. Use <seeerl marker="kernel:erpc"><c>erpc</c></seeerl> module
+ to communicate over Erlang distribution.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="cast" arity="4" since="OTP 25.0"/>
+ <fsummary>Evaluates a function call on a peer node ignoring the result.</fsummary>
+ <desc>
+ <p>
+ Uses the alternative connection to
+ evaluate <c>apply(<anno>Module</anno>, <anno>Function</anno>,
+ <anno>Args</anno>)</c> on the peer node. No response is delivered to the
+ calling process.
+ </p>
+ <p>
+ <c>peer:cast/4</c> fails silently when the alternative connection is not
+ configured. Use <seeerl marker="kernel:erpc"><c>erpc</c></seeerl> module
+ to communicate over Erlang distribution.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send" arity="3" since="OTP 25.0"/>
+ <fsummary>Sends a message to a process on the peer node.</fsummary>
+ <desc>
+ <p>
+ Uses the alternative connection to send <anno>Message</anno> to a process on the
+ the peer node. Silently fails if no alternative connection is configured.
+ The process can be referenced by process ID or registered name.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_state" arity="1" since="OTP 25.0"/>
+ <fsummary>Returns peer node state.</fsummary>
+ <desc>
+ <p>Returns the peer node state. Th initial state is <c>booting</c>; the node stays in that
+ state until then boot script is complete, and then the node progresses to <c>running</c>.
+ If the node stops (gracefully or not), the state changes to <c>down</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="random_name" arity="0" since="OTP 25.0"/>
+ <fsummary>Creates a sufficiently unique node name.</fsummary>
+ <desc>
+ <p>
+ The same as <seemfa marker="#random_name/1"><c>random_name(peer)</c></seemfa>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="random_name" arity="1" since="OTP 25.0"/>
+ <fsummary>Creates a sufficiently unique node name given a prefix.</fsummary>
+ <desc>
+ <p>
+ Creates a sufficiently unique node name for the current host,
+ combining a prefix, a unique number, and the current OS process ID.
+ </p>
+ <note>
+ <p>
+ Use the <c>?CT_PEER(["erl_arg1"])</c> macro provided by Common Test
+ <c>-include_lib("common_test/include/ct.hrl")</c> for convenience.
+ It starts a new peer using Erlang distribution as the control channel,
+ supplies thes calling module's code path to the peer, and uses the calling
+ function name for the name prefix.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="start" arity="1" since="OTP 25.0"/>
+ <fsummary>Starts a peer node.</fsummary>
+ <desc>
+ <p>
+ Starts a peer node with the specified
+ <seetype marker="#start_options"><c>start_options()</c></seetype>.
+ Returns the controlling process and the full peer node name, unless
+ <c>wait_boot</c> is not requested and the host name is not known in advance.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="start_link" arity="0" since="OTP 25.0"/>
+ <fsummary>Starts a peer node, and links controlling process to caller process.</fsummary>
+ <desc>
+ <p>
+ The same as
+ <seemfa marker="#start_link/1"><c>start_link(#{name => random_name()})</c></seemfa>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="start_link" arity="1" since="OTP 25.0"/>
+ <fsummary>Starts a peer node, and links controlling process to caller process.</fsummary>
+ <desc>
+ <p>Starts a peer node in the same way as <seemfa marker="#start/1"><c>start/1</c></seemfa>,
+ except that the peer node is linked to the currently
+ executing process. If that process terminates, the peer node
+ also terminates.</p>
+ <p>
+ Accepts <seetype marker="#start_options"><c>start_options()</c></seetype>.
+ Returns the controlling process and the full peer node name, unless <c>wait_boot</c> is not
+ requested and host name is not known in advance.
+ </p>
+ <p>
+ When the <c>standard_io</c> alternative connection is requested, and <c>wait_boot</c> is
+ not set to <c>false</c>, a failed peer boot sequence causes the caller to exit with
+ the <c>{boot_failed, {exit_status, ExitCode}}</c> reason.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="stop" arity="1" since="OTP 25.0"/>
+ <fsummary>Stop controlling process and terminate peer node.</fsummary>
+ <type name="disconnect_timeout"/>
+ <desc>
+ <p>
+ Stops a peer node. How the node is stopped depends on the
+ <seetype marker="#start_options"><c>shutdown</c></seetype>
+ option passed when starting the peer node. Currently the
+ following <c>shutdown</c> options are supported:
+ </p>
+ <taglist>
+ <tag><c>halt</c></tag>
+ <item><p>
+ This is the default shutdown behavior. It behaves as <c>shutdown</c>
+ option <c>{halt, DefaultTimeout}</c> where <c>DefaultTimeout</c>
+ currently equals <c>5000</c>.
+ </p></item>
+ <tag><c>{halt, Timeout :: disconnect_timeout()}</c></tag>
+ <item><p>
+ Triggers a call to
+ <seemfa marker="erts:erlang#halt/0"><c>erlang:halt()</c></seemfa>
+ on the peer node and then waits for the Erlang distribution
+ connection to the peer node to be taken down. If this connection
+ has not been taken down after <c>Timeout</c> milliseconds, it will
+ forcefully be taken down by <c>peer:stop/1</c>. See the
+ <seeerl marker="#dist_connection_close">warning</seeerl> below for
+ more info about this.
+ </p></item>
+ <tag><c>Timeout :: disconnect_timeout()</c></tag>
+ <item><p>
+ Triggers a call to
+ <seemfa marker="erts:init#stop/0"><c>init:stop()</c></seemfa>
+ on the peer node and then waits for the Erlang distribution
+ connection to the peer node to be taken down. If this connection
+ has not been taken down after <c>Timeout</c> milliseconds, it will
+ forcefully be taken down by <c>peer:stop/1</c>. See the
+ <seeerl marker="#dist_connection_close">warning</seeerl> below for
+ more info about this.
+ </p></item>
+ <tag><c>close</c></tag>
+ <item><p>
+ Close the <i>control connection</i> to the peer node and
+ return. This is the fastest way for the caller of
+ <c>peer:stop/1</c> to stop a peer node.
+ </p>
+ <p>
+ Note that if the Erlang distribution connection is not used as
+ control connection it might not have been taken down when
+ <c>peer:stop/1</c> returns. Also note that the
+ <seeerl marker="#dist_connection_close">warning</seeerl> below
+ applies when the Erlang distribution connection is used as control
+ connection.
+ </p>
+ </item>
+ </taglist>
+
+ <marker id="dist_connection_close"/>
+ <warning>
+ <p>
+ In the cases where the Erlang distribution connection is taken
+ down by <c>peer:stop/1</c>, other code independent of the peer
+ code might react to the connection loss before the peer node is
+ stopped which might cause undesirable effects. For example,
+ <seeerl marker="kernel:global#prevent_overlapping_partitions"><c>global</c></seeerl>
+ might trigger even more Erlang distribution connections to other
+ nodes to be taken down. The potential undesirable effects are,
+ however, not limited to this. It is hard to say what the effects
+ will be since these effects can be caused by any code with links
+ or monitors to something on the origin node, or code monitoring
+ the connection to the origin node.
+ </p>
+ </warning>
+ </desc>
+ </func>
+
+ </funcs>
+</erlref>
+
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index e2ffffd2f7..2e6f424a84 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,9 +48,13 @@
<p>Some functions, where noted, fail with reason <c>empty</c>
for an empty queue.</p>
- <p>The data representing a queue as used by this module
- is to be regarded as opaque by other modules. Any code
- assuming knowledge of the format is running on thin ice.</p>
+ <p>The data representing a queue as used by this module is to be
+ regarded as opaque by other modules. In abstract terms, the
+ representation is a composite type of existing Erlang terms. See
+ note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>. Any code assuming knowledge of the format is
+ running on thin ice.</p>
<p>All operations have an amortized O(1) running time, except
<seemfa marker="#all/2"><c>all/2</c></seemfa>,
@@ -285,8 +289,13 @@
<name name="is_queue" arity="1" since=""/>
<fsummary>Test if a term is a queue.</fsummary>
<desc>
- <p>Tests if <c><anno>Term</anno></c> is a queue and returns <c>true</c>
- if so, otherwise <c>false</c>.</p>
+ <p>Tests if <c><anno>Term</anno></c> is a queue and returns
+ <c>true</c> if so, otherwise <c>false</c>. Note that the test
+ will return <c>true</c> for a term coinciding with the
+ representation of a queue, even when not constructed by thus
+ module. See also note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index e7a2823bc0..471a23f6b9 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2015</year><year>2021</year>
+ <year>2015</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -54,7 +54,22 @@
non-overlapping sequences for parallel computations.
The jump functions perform calculations
equivalent to perform a large number of repeated calls
- for calculating new states.
+ for calculating new states, but execute in a time
+ roughly equivalent to one regular iteration per generator bit.
+ </p>
+
+ <p>
+ At the end of this module documentation there are also some
+ <seeerl marker="#niche_algorithms">
+ niche algorithms
+ </seeerl>
+ to be used without this module's normal
+ <seeerl marker="#plug_in_api">
+ plug-in framework API
+ </seeerl>
+ that may be useful for special purposes like
+ short generation time when quality is not essential,
+ for seeding other generators, and such.
</p>
<p>
@@ -290,9 +305,10 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
If this is a problem; to generate a boolean with these algorithms
use something like this:
</p>
- <pre>(rand:uniform(16) > 8)</pre>
+ <pre>(rand:uniform(256) > 128) % -> boolean()</pre>
+ <pre>((rand:uniform(256) - 1) bsr 7) % -> 0 | 1</pre>
<p>
- And for a general range, with <c>N = 1</c> for <c>exrop</c>,
+ For a general range, with <c>N = 1</c> for <c>exrop</c>,
and <c>N = 3</c> for <c>exs1024s</c>:
</p>
<pre>(((rand:uniform(Range bsl N) - 1) bsr N) + 1)</pre>
@@ -376,13 +392,38 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<name name="exs64_state"/>
<desc><p>Algorithm specific internal state</p></desc>
</datatype>
+ <datatype>
+ <name name="dummy_state"/>
+ <desc><p>Algorithm specific internal state</p></desc>
+ </datatype>
+ <datatype>
+ <name name="splitmix64_state"/>
+ <desc><p>Algorithm specific state</p></desc>
+ </datatype>
+ <datatype>
+ <name name="uint58"/>
+ <desc><p>0 .. (2^58 - 1)</p></desc>
+ </datatype>
+ <datatype>
+ <name name="uint64"/>
+ <desc><p>0 .. (2^64 - 1)</p></desc>
+ </datatype>
+ <datatype>
+ <name name="mwc59_state"/>
+ <desc><p>1 .. ((16#1ffb072 * 2^29 - 1) - 1)</p></desc>
+ </datatype>
</datatypes>
+
<funcs>
+ <fsdescription>
+ <marker id="plug_in_api"/>
+ <title>Plug-in framework API</title>
+ </fsdescription>
<func>
<name name="bytes" arity="1" since="OTP 24.0"/>
<fsummary>Return a random binary.</fsummary>
- <desc><marker id="bytes-1"/>
+ <desc>
<p>
Returns, for a specified integer <c><anno>N</anno> >= 0</c>,
a <c>binary()</c> with that number of random bytes.
@@ -396,7 +437,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<func>
<name name="bytes_s" arity="2" since="OTP 24.0"/>
<fsummary>Return a random binary.</fsummary>
- <desc><marker id="bytes-1"/>
+ <desc>
<p>
Returns, for a specified integer <c><anno>N</anno> >= 0</c>
and a state, a <c>binary()</c> with that number of random bytes,
@@ -411,7 +452,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<func>
<name name="export_seed" arity="0" since="OTP 18.0"/>
<fsummary>Export the random number generation state.</fsummary>
- <desc><marker id="export_seed-0"/>
+ <desc>
<p>Returns the random number state in an external format.
To be used with <seemfa marker="#seed/1"><c>seed/1</c></seemfa>.</p>
</desc>
@@ -420,7 +461,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<func>
<name name="export_seed_s" arity="1" since="OTP 18.0"/>
<fsummary>Export the random number generation state.</fsummary>
- <desc><marker id="export_seed_s-1"/>
+ <desc>
<p>Returns the random number generator state in an external format.
To be used with <seemfa marker="#seed/1"><c>seed/1</c></seemfa>.</p>
</desc>
@@ -430,7 +471,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<name name="jump" arity="0" since="OTP 20.0"/>
<fsummary>Return the seed after performing jump calculation
to the state in the process dictionary.</fsummary>
- <desc><marker id="jump-0" />
+ <desc>
<p>Returns the state
after performing jump calculation
to the state in the process dictionary.</p>
@@ -444,7 +485,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<func>
<name name="jump" arity="1" since="OTP 20.0"/>
<fsummary>Return the seed after performing jump calculation.</fsummary>
- <desc><marker id="jump-1" />
+ <desc>
<p>Returns the state after performing jump calculation
to the given state. </p>
<p>This function generates a <c>not_implemented</c> error exception
@@ -496,7 +537,6 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<name name="seed" arity="1" clause_i="2" since="OTP 24.0"/>
<fsummary>Seed random number generator.</fsummary>
<desc>
- <marker id="seed-1"/>
<p>
Seeds random number generation with the specifed algorithm and
time-dependent data if <c><anno>AlgOrStateOrExpState</anno></c>
@@ -571,7 +611,7 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<func>
<name name="uniform" arity="0" since="OTP 18.0"/>
<fsummary>Return a random float.</fsummary>
- <desc><marker id="uniform-0"/>
+ <desc>
<p>
Returns a random float uniformly distributed in the value
range <c>0.0 =&lt; <anno>X</anno> &lt; 1.0</c> and
@@ -607,7 +647,7 @@ end.</pre>
<func>
<name name="uniform_real" arity="0" since="OTP 21.0"/>
<fsummary>Return a random float.</fsummary>
- <desc><marker id="uniform_real-0"/>
+ <desc>
<p>
Returns a random float
uniformly distributed in the value range
@@ -643,7 +683,7 @@ end.</pre>
<func>
<name name="uniform" arity="1" since="OTP 18.0"/>
<fsummary>Return a random integer.</fsummary>
- <desc><marker id="uniform-1"/>
+ <desc>
<p>Returns, for a specified integer <c><anno>N</anno> >= 1</c>,
a random integer uniformly distributed in the value range
<c>1 =&lt; <anno>X</anno> =&lt; <anno>N</anno></c> and
@@ -760,4 +800,472 @@ end.</pre>
</desc>
</func>
</funcs>
+
+
+ <funcs>
+ <fsdescription>
+ <marker id="niche_algorithms"/>
+ <title>Niche algorithms API</title>
+ <p>
+ This section contains special purpose algorithms
+ that does not use the
+ <seeerl marker="#plug_in_api">plug-in framework API</seeerl>,
+ for example for speed reasons.
+ </p>
+ <p>
+ Since these algorithms lack the plug-in framework support,
+ generating numbers in a range other than the
+ generator's own generated range may become a problem.
+ </p>
+ <p>
+ There are at least 3 ways to do this, assuming that
+ the range is less than the generator's range:
+ </p>
+ <taglist>
+ <tag>Modulo</tag>
+ <item>
+ <p>
+ To generate a number <c>V</c> in the range 0..<c>Range</c>-1:
+ </p>
+ <list type="bulleted">
+ <item>Generate a number <c>X</c>.</item>
+ <item>
+ Use <c>V&nbsp;=&nbsp;X&nbsp;rem&nbsp;Range</c> as your value.
+ </item>
+ </list>
+ <p>
+ This method uses <c>rem</c>, that is, the remainder of
+ an integer division, which is a slow operation.
+ </p>
+ <p>
+ Low bits from the generator propagate straight through
+ to the generated value, so if the generator has got
+ weaknesses in the low bits this method propagates
+ them too.
+ </p>
+ <p>
+ If <c>Range</c> is not a divisor of the generator range,
+ the generated numbers have a bias.
+ Example:
+ </p>
+ <p>
+ Say the generator generates a byte, that is,
+ the generator range is 0..255,
+ and the desired range is 0..99 (<c>Range=100</c>).
+ Then there are 3 generator outputs that produce the value 0,
+ that is; 0, 100 and 200. But there are only
+ 2 generator outputs that produce the value 99,
+ which are; 99 and 199. So the probability for
+ a value <c>V</c> in 0..55 is 3/2 times
+ the probability for the other values 56..99.
+ </p>
+ <p>
+ If <c>Range</c> is much smaller than the generator range,
+ then this bias gets hard to detect. The rule of thumb is
+ that if <c>Range</c> is smaller than the square root
+ of the generator range, the bias is small enough.
+ Example:
+ </p>
+ <p>
+ A byte generator when <c>Range=20</c>.
+ There are 12 (<c>256&nbsp;div&nbsp;20</c>)
+ possibilities to generate the highest numbers
+ and one more to generate a number
+ <c>V</c>&nbsp;&lt;&nbsp;16 (<c>256&nbsp;rem&nbsp;20</c>).
+ So the probability is 13/12 for a low number
+ versus a high. To detect that difference
+ with some confidence you would need to generate
+ a lot more numbers than the generator range,
+ 256 in this small example.
+ </p>
+ </item>
+ <tag>Truncated multiplication</tag>
+ <item>
+ <p>
+ To generate a number <c>V</c> in the range 0..<c>Range</c>-1,
+ when you have a generator with the range
+ 0..2^<c>Bits</c>-1:
+ </p>
+ <list type="bulleted">
+ <item>Generate a number <c>X</c>.</item>
+ <item>
+ Use <c>V&nbsp;=&nbsp;X*Range&nbsp;bsr&nbsp;Bits</c>
+ as your value.
+ </item>
+ </list>
+ <p>
+ If the multiplication <c>X*Range</c> creates a bignum
+ this method becomes very slow.
+ </p>
+ <p>
+ High bits from the generator propagate through
+ to the generated value, so if the generator has got
+ weaknesses in the high bits this method propagates
+ them too.
+ </p>
+ <p>
+ If <c>Range</c> is not a divisor of the generator range,
+ the generated numbers have a bias,
+ pretty much as for the <em>Modulo</em> method above.
+ </p>
+ </item>
+ <tag>Shift or mask</tag>
+ <item>
+ <p>
+ To generate a number in the range 0..2^<c>RBits</c>-1,
+ when you have a generator with the range 0..2^<c>Bits</c>:
+ </p>
+ <list type="bulleted">
+ <item>Generate a number <c>X</c>.</item>
+ <item>
+ Use <c>V&nbsp;=&nbsp;X&nbsp;band&nbsp;((1&nbsp;bsl&nbsp;RBits)-1)</c>
+ or <c>V&nbsp;=&nbsp;X&nbsp;bsr&nbsp;(Bits-RBits)</c>
+ as your value.
+ </item>
+ </list>
+ <p>
+ Masking with <c>band</c> preserves the low bits,
+ and right shifting with <c>bsr</c> preserves the high,
+ so if the generator has got weaknesses in high or low
+ bits; choose the right operator.
+ </p>
+ <p>
+ If the generator has got a range that is not a power of 2
+ and this method is used anyway, it introduces bias
+ in the same way as for the <em>Modulo</em> method above.
+ </p>
+ </item>
+ <tag>Rejection</tag>
+ <item>
+ <list type="bulleted">
+ <item>Generate a number <c>X</c>.</item>
+ <item>
+ If <c>X</c> is in the range, use <c>V&nbsp;=&nbsp;X</c>
+ as your value, otherwise reject it and repeat.
+ </item>
+ </list>
+ <p>
+ In theory it is not certain that this method
+ will ever complete, but in practice you ensure
+ that the probability of rejection is low.
+ Then the probability for yet another iteration
+ decreases exponentially so the expected mean
+ number of iterations will often be between 1 and 2.
+ Also, since the base generator is a full length generator,
+ a value that will break the loop must eventually
+ be generated.
+ </p>
+ </item>
+ </taglist>
+ <p>
+ Chese methods can be combined, such as using the <em>Modulo</em>
+ method and only if the generator value would create bias
+ use <em>Rejection</em>. Or using <em>Shift or mask</em>
+ to reduce the size of a generator value so that
+ <em>Truncated multiplication</em> will not create a bignum.
+ </p>
+ <p>
+ The recommended way to generate a floating point number
+ (IEEE 745 double, that has got a 53-bit mantissa)
+ in the range 0..1, that is
+ 0.0&nbsp;=&lt;&nbsp;<c>V</c>&nbsp;&lt;1.0
+ is to generate a 53-bit number <c>X</c> and then use
+ <c>V&nbsp;=&nbsp;X&nbsp;*&nbsp;(1.0/((1&nbsp;bsl&nbsp;53)))</c>
+ as your value. This will create a value on the form
+ <c>N</c>*2^-53 with equal probability for every
+ possible <c>N</c> for the range.
+ </p>
+ </fsdescription>
+ <func>
+ <name name="splitmix64_next" arity="1" since="OTP 25.0"/>
+ <fsummary>Return a random integer and new state.</fsummary>
+ <desc>
+ <p>
+ Returns a random 64-bit integer <c><anno>X</anno></c>
+ and a new generator state <c><anno>NewAlgState</anno></c>,
+ according to the SplitMix64 algorithm.
+ </p>
+ <p>
+ This generator is used internally in the <c>rand</c>
+ module for seeding other generators since it is of a
+ quite different breed which reduces the probability for
+ creating an accidentally bad seed.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="exsp_next" arity="1" since="OTP 25.0"/>
+ <fsummary>Return a random integer and new state.</fsummary>
+ <desc>
+ <p>
+ Returns a random 58-bit integer <c><anno>X</anno></c>
+ and a new generator state <c><anno>NewAlgState</anno></c>,
+ according to the Xorshift116+ algorithm.
+ </p>
+ <p>
+ This is an API function into the internal implementation of the
+ <seeerl marker="#algorithms"><c>exsp</c></seeerl>
+ algorithm that enables using it without the overhead
+ of the plug-in framework, which might be useful
+ for time critial applications.
+ On a typical 64 bit Erlang VM this approach executes
+ in just above 30% (1/3) of the time
+ for the default algorithm through
+ this module's normal plug-in framework.
+ </p>
+ <p>
+ To seed this generator use
+ <seemfa marker="#seed_s/1">
+ <c>{_, <anno>AlgState</anno>} = rand:seed_s(exsp)</c>
+ </seemfa>
+ or
+ <seemfa marker="#seed_s/1">
+ <c>{_, <anno>AlgState</anno>} = rand:seed_s(exsp, Seed)</c>
+ </seemfa>
+ with a specific <c>Seed</c>.
+ </p>
+ <note>
+ <p>
+ This function offers no help in generating a number
+ on a selected range, nor in generating a floating point number.
+ It is easy to accidentally mess up the fairly good
+ statistical properties of this generator when doing either.
+ See the recepies at the start of this
+ <seeerl marker="#niche_algorithms">
+ Niche algorithms API
+ </seeerl>
+ description.
+ Note also the caveat about weak low bits that
+ this generator suffers from.
+ The generator is exported in this form
+ primarily for performance.
+ </p>
+ </note>
+ </desc>
+ </func>
+ <func>
+ <name name="exsp_jump" arity="1" since="OTP 25.0"/>
+ <fsummary>Return the new state as from 2^64 iterations.</fsummary>
+ <desc>
+ <p>
+ Returns a new generator state equivalent of the state
+ after iterating over
+ <seemfa marker="#exsp_next/1"><c>exsp_next/1</c></seemfa>
+ 2^64 times.
+ </p>
+ <p>
+ See the description of jump functions
+ at the top of this module description.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="mwc59" arity="1" since="OTP 25.0"/>
+ <fsummary>Return a new generator state.</fsummary>
+ <desc>
+ <p>
+ Returns a new generator state <c><anno>CX1</anno></c>,
+ according to a Multiply With Carry generator,
+ which is an efficient implementation of a
+ Multiplicative Congruential Generator with
+ a power of 2 multiplier and a prime modulus.
+ </p>
+ <p>
+ This generator uses the multiplier 2^32 and the modulus
+ 16#7fa6502&nbsp;*&nbsp;2^32&nbsp;-&nbsp;1,
+ which have been selected,
+ in collaboration with Sebastiano Vigna,
+ to avoid bignum operations
+ and still get good statistical quality.
+ It can be written as:<br/>
+ <c>C&nbsp;=&nbsp;<anno>CX0</anno>&nbsp;bsr&nbsp;32</c><br/>
+ <c>X&nbsp;=&nbsp;<anno>CX0</anno>&nbsp;band&nbsp;((1&nbsp;bsl&nbsp;32)-1))</c><br/>
+ <c><anno>CX1</anno>&nbsp;=&nbsp;16#7fa6502&nbsp;*&nbsp;X&nbsp;+&nbsp;C</c>
+ </p>
+ <p>
+ Because the generator uses a multiplier that is
+ a power of 2 it gets statistical flaws for collision tests
+ and birthday spacings tests in 2 and 3 dimensions,
+ and even these caveats apply only to the MWC "digit",
+ that is the low 32 bits (due to the multiplier) of
+ the generator state.
+ </p>
+ <p>
+ The quality of the output value improves much by using
+ a scrambler instead of just taking the low bits.
+ Function
+ <seemfa marker="#mwc59_value32/1">
+ <c>mwc59_value32</c>
+ </seemfa>
+ is a fast scrambler that returns a decent 32-bit number.
+ The slightly slower
+ <seemfa marker="#mwc59_value/1">
+ <c>mwc59_value</c>
+ </seemfa>
+ scrambler returns 59 bits of very good quality, and
+ <seemfa marker="#mwc59_float/1"><c>mwc59_float</c></seemfa>
+ returns a <c>float()</c> of very good quality.
+ </p>
+ <p>
+ The low bits of the base generator are surprisingly good,
+ so the lowest 16 bits actually pass fairly strict PRNG tests,
+ despite the generator's weaknesses that lie in the high
+ bits of the 32-bit MWC "digit". It is recommended
+ to use <c>rem</c> on the the generator state,
+ or bit mask extracting the lowest bits to produce numbers
+ in a range 16 bits or less.
+ See the recepies at the start of this
+ <seeerl marker="#niche_algorithms">
+ Niche algorithms API
+ </seeerl>
+ description.
+ </p>
+ <p>
+ On a typical 64 bit Erlang VM this generator executes
+ in below 8% (1/13) of the time
+ for the default algorithm in the
+ <seeerl marker="#plug_in_api">
+ plug-in framework API
+ </seeerl>
+ of this module. With the
+ <seemfa marker="#mwc59_value32/1">
+ <c>mwc59_value32</c>
+ </seemfa>
+ scrambler the total time becomes 16% (1/6),
+ and with
+ <seemfa marker="#mwc59_value/1">
+ <c>mwc59_value</c>
+ </seemfa>
+ it becomes 20% (1/5) of the time for the default algorithm.
+ With
+ <seemfa marker="#mwc59_float/1"><c>mwc59_float</c></seemfa>
+ the total time is 60% of the time for the default
+ algorithm generating a <c>float()</c>.
+ </p>
+ <note>
+ <p>
+ This generator is a niche generator for high speed
+ applications. It has a much shorter period
+ than the default generator, which in itself
+ is a quality concern, although when used with the
+ value scramblers it passes strict PRNG tests.
+ The generator is much faster than
+ <seemfa marker="#exsp_next/1"><c>exsp_next/1</c></seemfa>
+ but with a bit lower quality.
+ </p>
+ </note>
+ </desc>
+ </func>
+ <func>
+ <name name="mwc59_value32" arity="1" since="OTP 25.0"/>
+ <fsummary>Return the generator value.</fsummary>
+ <desc>
+ <p>
+ Returns a 32-bit value <c><anno>V</anno></c>
+ from a generator state <c><anno>CX</anno></c>.
+ The generator state is scrambled using
+ an 8-bit xorshift which masks
+ the statistical imperfecions of the base generator
+ <seemfa marker="#mwc59/1"><c>mwc59</c></seemfa>
+ enough to produce numbers of decent quality.
+ Still some problems in 2- and 3-dimensional
+ birthday spacing and collision tests show through.
+ </p>
+ <p>
+ When using this scrambler it is in general better to use
+ the high bits of the value than the low.
+ The lowest 8 bits are of good quality and pass right through
+ from the base generator. They are combined with the next 8
+ in the xorshift making the low 16 good quality,
+ but in the range 16..31 bits there are weaker bits
+ that you do not want to have as the high bits
+ of your generated values.
+ Therefore it is in general safer to shift out low bits.
+ See the recepies at the start of this
+ <seeerl marker="#niche_algorithms">
+ Niche algorithms API
+ </seeerl>
+ description.
+ </p>
+ <p>
+ For a non power of 2 range less than about 16 bits
+ (to not get too much bias and to avoid bignums)
+ truncated multiplication can be used,
+ which is much faster than using <c>rem</c>:
+ <c>(Range*<anno>V</anno>)&nbsp;bsr&nbsp;32</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="mwc59_value" arity="1" since="OTP 25.0"/>
+ <fsummary>Return the generator value.</fsummary>
+ <desc>
+ <p>
+ Returns a 59-bit value <c><anno>V</anno></c>
+ from a generator state <c><anno>CX</anno></c>.
+ The generator state is scrambled using
+ an 4-bit followed by a 27-bit xorshift, which masks
+ the statistical imperfecions of the base generator
+ <seemfa marker="#mwc59/1"><c>mwc59</c></seemfa>
+ enough that all 59 bits are of very good quality.
+ </p>
+ <p>
+ Be careful to not accidentaly create a bignum
+ when handling the value <c><anno>V</anno></c>.
+ </p>
+ <p>
+ It is in general general better to use the high bits
+ from this scrambler than the low.
+ See the recepies at the start of this
+ <seeerl marker="#niche_algorithms">
+ Niche algorithms API
+ </seeerl>
+ description.
+ </p>
+ <p>
+ For a non power of 2 range less than about 29 bits
+ (to not get too much bias and to avoid bignums)
+ truncated multiplication can be used,
+ which is much faster than using <c>rem</c>.
+ Example for range 1'000'000'000;
+ the range is 30 bits, we use 29 bits from the generator,
+ adding up to 59 bits, which is not a bignum:
+ <c>(1000000000&nbsp;*&nbsp;(<anno>V</anno>&nbsp;bsr&nbsp;(59-29)))&nbsp;bsr&nbsp;29</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="mwc59_float" arity="1" since="OTP 25.0"/>
+ <fsummary>Return a generated float.</fsummary>
+ <desc>
+ <p>
+ Returns the generator value <c><anno>V</anno></c>
+ from a generator state <c><anno>CX</anno></c>,
+ as a <c>float()</c>.
+ The generator state is scrambled as with
+ <seemfa marker="#mwc59_value/1">
+ <c>mwc59_value/1</c>
+ </seemfa>
+ before converted to a <c>float()</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="mwc59_seed" arity="0" since="OTP 25.0"/>
+ <name name="mwc59_seed" arity="1" since="OTP 25.0"/>
+ <fsummary>Create a generator state.</fsummary>
+ <desc>
+ <p>
+ Returns a generator state <c><anno>CX</anno></c>.
+ <c><anno>S</anno></c> is hashed to create the generator state,
+ to avoid that similar seeds create similar sequences.
+ </p>
+ <p>
+ Without <c><anno>S</anno></c>,
+ the generator state is created as for
+ <seemfa marker="#seed_s/1"><c>seed_s(atom())</c></seemfa>.
+ </p>
+ </desc>
+ </func>
+ </funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml
index e404b1a3c8..e63c455ec8 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>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -48,6 +48,7 @@
<xi:include href="erl_error.xml"/>
<xi:include href="erl_eval.xml"/>
<xi:include href="erl_expand_records.xml"/>
+ <xi:include href="erl_features.xml"/>
<xi:include href="erl_id_trans.xml"/>
<xi:include href="erl_internal.xml"/>
<xi:include href="erl_lint.xml"/>
@@ -74,6 +75,7 @@
<xi:include href="ms_transform.xml"/>
<xi:include href="orddict.xml"/>
<xi:include href="ordsets.xml"/>
+ <xi:include href="peer.xml"/>
<xi:include href="pool.xml"/>
<xi:include href="proc_lib.xml"/>
<xi:include href="proplists.xml"/>
diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml
index 5d81ca4f0d..53b64a3ac0 100644
--- a/lib/stdlib/doc/src/sets.xml
+++ b/lib/stdlib/doc/src/sets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2021</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,8 +35,17 @@
<module since="">sets</module>
<modulesummary>Functions for set manipulation.</modulesummary>
<description>
- <p>Sets are collections of elements with no duplicate elements.
- The representation of a set is undefined.</p>
+ <p>Sets are collections of elements with no duplicate
+ elements.</p>
+
+ <p>The data representing a set as used by this module is to be
+ regarded as opaque by other modules. In abstract terms, the
+ representation is a composite type of existing Erlang terms. See
+ note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>. Any code assuming knowledge of the format is
+ running on thin ice.</p>
+
<p>This module provides the same interface as the
<seeerl marker="ordsets"><c>ordsets(3)</c></seeerl> module
@@ -174,8 +183,13 @@
<name name="is_set" arity="1" since=""/>
<fsummary>Test for a <c>Set</c>.</fsummary>
<desc>
- <p>Returns <c>true</c> if <c><anno>Set</anno></c> is a set of
- elements, otherwise <c>false</c>.</p>
+ <p>Returns <c>true</c> if <c><anno>Set</anno></c> appears to
+ be a set of elements, otherwise <c>false</c>. Note that the
+ test is shallow and will return <c>true</c> for any term that
+ coincides with the possible representations of a set. See
+ also note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml
index dc68af4328..928d2686b6 100644
--- a/lib/stdlib/doc/src/shell.xml
+++ b/lib/stdlib/doc/src/shell.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,16 +39,26 @@
<p>The shell is a user interface program
for entering expression sequences. The expressions are
- evaluated and a value is returned.
- A history mechanism saves previous commands and their
+ evaluated and a value is returned. The shell provides an Emacs like set of
+ shortcuts for editing the text of the current line. See <seeguide marker="erts:tty">
+ tty - A Command-Line Interface</seeguide> in the ERTS User's Guide
+ for a list of all available shortcuts.</p>
+
+ <p>A history mechanism saves previous commands and their
values, which can then be incorporated in later commands.
How many commands and results to save can be determined by the user,
either interactively, by calling
<seemfa marker="#history/1"><c>history/1</c></seemfa> and
<seemfa marker="#results/1"><c>results/1</c></seemfa>,
or by setting the application configuration
- parameters <c>shell_history_length</c> and
- <c>shell_saved_results</c> for the STDLIB application.</p>
+ parameters <seeapp marker="STDLIB_app#shell_history_length">
+ <c>shell_history_length</c></seeapp> and
+ <seeapp marker="STDLIB_app#shell_saved_results"><c>shell_saved_results</c></seeapp>
+ for the STDLIB application. The shell history can be saved to disk by
+ setting the application configuration parameter
+ <seeapp marker="kernel:kernel_app#shell_history"><c>shell_history</c></seeapp>
+ for the Kernel application.
+ </p>
<p>The shell uses a helper process for evaluating commands
to protect the history mechanism from exceptions. By
@@ -168,6 +178,21 @@
<item>
<p>Evaluates <c>shell_default:help()</c>.</p>
</item>
+ <tag><c>h(Module, Function)</c></tag>
+ <item>
+ <p>Print the documentation for <c>Module:Function</c> in the shell
+ if available.</p>
+ </item>
+ <tag><c>ht(Module, Type)</c></tag>
+ <item>
+ <p>Print the documentation for <c>Module:Type</c> in the shell
+ if available.</p>
+ </item>
+ <tag><c>hcb(Module, Callback)</c></tag>
+ <item>
+ <p>Print the documentation for <c>Module:Callback</c> in the shell
+ if available.</p>
+ </item>
<tag><c>c(Mod)</c></tag>
<item>
<p>Evaluates <c>shell_default:c(Mod)</c>. This compiles and
@@ -789,6 +814,14 @@ q - quit erlang
manual page. (Arguments in <c>ArgList</c> are evaluated before the
callback functions are called.)</p>
+ <p>From OTP 25.0, if there are errors evaluating Erlang constructs,
+ such as <c>badmatch</c> during pattern matching or <c>bad_generator</c>
+ in a comprehension, the evaluator will dispatch to
+ <c>erlang:raise(error, Reason, Stacktrace)</c>. This call will be
+ checked against the <c>non_local_allowed/3</c> callback function.
+ You can either forbid it, allow it, or redirect to another call of
+ your choice.</p>
+
<p>Argument <c>State</c> is a tuple
<c>{ShellState,ExprState}</c>. The return value <c>NewState</c>
has the same form. This can be used to carry a state between calls
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 9b96c4d39a..6d47054cb8 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>2020</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -40,6 +40,14 @@
collection of elements; every element belongs to the set, and
the set contains every element.</p>
+ <p>The data representing <c>sofs</c> as used by this module is to
+ be regarded as opaque by other modules. In abstract terms, the
+ representation is a composite type of existing Erlang terms. See
+ note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>. Any code assuming knowledge of the format is
+ running on thin ice.</p>
+
<p>Given a set A and a sentence S(x), where x is a free variable,
a new set B whose elements are exactly those elements of A for
which S(x) holds can be formed, this is denoted B&nbsp;=
@@ -1167,20 +1175,31 @@ true</pre>
<name name="is_set" arity="1" since=""/>
<fsummary>Test for an unordered set.</fsummary>
<desc>
- <p>Returns <c>true</c> if <c><anno>AnySet</anno></c> is
- an <seeerl marker="#sets_definition">unordered set</seeerl>, and
- <c>false</c> if <c><anno>AnySet</anno></c> is an ordered set or an
- atomic set.</p>
+ <p>Returns <c>true</c> if <c><anno>AnySet</anno></c> appears
+ to be an <seeerl marker="#sets_definition">unordered
+ set</seeerl>, and <c>false</c> if <c><anno>AnySet</anno></c>
+ is an ordered set or an atomic set or any other term. Note
+ that the test is shallow and this function will return
+ <c>true</c> for any term that coincides with the
+ representation of an unordered set. See also note on
+ <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>.</p>
</desc>
</func>
<func>
<name name="is_sofs_set" arity="1" since=""/>
- <fsummary>Test for an unordered set.</fsummary>
- <desc>
- <p>Returns <c>true</c> if <c><anno>Term</anno></c> is
- an <seeerl marker="#sets_definition">unordered set</seeerl>, an
- ordered set, or an atomic set, otherwise <c>false</c>.</p>
+ <fsummary>Test for a sofs set.</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c><anno>Term</anno></c> appears to
+ be an <seeerl marker="#sets_definition">unordered
+ set</seeerl>, an ordered set, or an atomic set, otherwise
+ <c>false</c>. Note that this function will return <c>true</c>
+ for any term that coincides with the representation of a
+ <c>sofs</c> set. See also note on <seeguide
+ marker="system/reference_manual:data_types#no_user_types">data
+ types</seeguide>.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
index 75266530f2..9fdd0d1c21 100644
--- a/lib/stdlib/doc/src/specs.xml
+++ b/lib/stdlib/doc/src/specs.xml
@@ -15,6 +15,7 @@
<xi:include href="../specs/specs_erl_error.xml"/>
<xi:include href="../specs/specs_erl_eval.xml"/>
<xi:include href="../specs/specs_erl_expand_records.xml"/>
+ <xi:include href="../specs/specs_erl_features.xml"/>
<xi:include href="../specs/specs_erl_id_trans.xml"/>
<xi:include href="../specs/specs_erl_internal.xml"/>
<xi:include href="../specs/specs_erl_lint.xml"/>
@@ -41,6 +42,7 @@
<xi:include href="../specs/specs_ms_transform.xml"/>
<xi:include href="../specs/specs_orddict.xml"/>
<xi:include href="../specs/specs_ordsets.xml"/>
+ <xi:include href="../specs/specs_peer.xml"/>
<xi:include href="../specs/specs_pool.xml"/>
<xi:include href="../specs/specs_proc_lib.xml"/>
<xi:include href="../specs/specs_proplists.xml"/>
diff --git a/lib/stdlib/doc/src/stdlib_app.xml b/lib/stdlib/doc/src/stdlib_app.xml
index 298fbb4b91..243853140b 100644
--- a/lib/stdlib/doc/src/stdlib_app.xml
+++ b/lib/stdlib/doc/src/stdlib_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>2005</year><year>2021</year>
+ <year>2005</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -43,26 +43,26 @@
<seefile marker="kernel:app"><c>app(4)</c></seefile> module in Kernel.</p>
<taglist>
- <tag><c>shell_esc = icl | abort</c></tag>
+ <tag><marker id="shell_esc"/><c>shell_esc = icl | abort</c></tag>
<item>
<p>Can be used to change the behavior of the Erlang shell when
<em>^G</em> is pressed.</p>
</item>
- <tag><c>restricted_shell = module()</c></tag>
+ <tag><marker id="restricted_shell"/><c>restricted_shell = module()</c></tag>
<item>
<p>Can be used to run the Erlang shell in restricted mode.</p>
</item>
- <tag><c>shell_catch_exception = boolean()</c></tag>
+ <tag><marker id="shell_catch_exception"/><c>shell_catch_exception = boolean()</c></tag>
<item>
<p>Can be used to set the exception handling of the evaluator process of
Erlang shell.</p>
</item>
- <tag><c>shell_history_length = integer() >= 0</c></tag>
+ <tag><marker id="shell_history_length"/><c>shell_history_length = integer() >= 0</c></tag>
<item>
<p>Can be used to determine how many commands are saved by the Erlang
shell.</p>
</item>
- <tag><c>shell_prompt_func = {Mod, Func} | default</c></tag>
+ <tag><marker id="shell_prompt_func"/><c>shell_prompt_func = {Mod, Func} | default</c></tag>
<item>
<p>where</p>
<list type="bulleted">
@@ -71,12 +71,12 @@
</list>
<p>Can be used to set a customized Erlang shell prompt function.</p>
</item>
- <tag><c>shell_saved_results = integer() >= 0</c></tag>
+ <tag><marker id="shell_saved_results"/><c>shell_saved_results = integer() >= 0</c></tag>
<item>
<p>Can be used to determine how many results are saved by the Erlang
shell.</p>
</item>
- <tag><c>shell_strings = boolean()</c></tag>
+ <tag><marker id="shell_strings"/><c>shell_strings = boolean()</c></tag>
<item>
<p>Can be used to determine how the Erlang shell outputs lists of
integers.</p>
diff --git a/lib/stdlib/doc/src/supervisor_bridge.xml b/lib/stdlib/doc/src/supervisor_bridge.xml
index eb21f06b16..3e8b5a7da9 100644
--- a/lib/stdlib/doc/src/supervisor_bridge.xml
+++ b/lib/stdlib/doc/src/supervisor_bridge.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2021</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -115,7 +115,7 @@
<item>
<p>If <c><anno>Module</anno>:init/1</c> fails or returns an error
tuple or an incorrect value, this function returns
- <c>{error,<anno>Error</anno>r}</c>, where
+ <c>{error,<anno>Error</anno>}</c>, where
<c><anno>Error</anno></c> is a term with information about the
error, and the supervisor bridge
terminates with reason <c><anno>Error</anno></c>.</p>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index c08e9a04e1..6c1973f762 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2021</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -189,21 +189,6 @@
</p>
</item>
<tag>
- <c>{code_change,<anno>Event</anno>,<anno>State</anno>}</c>
- </tag>
- <item>
- <p>
- Is produced by <c>gen_statem</c>
- when the message <c><anno>Event</anno></c>
- arrives in state <c><anno>State</anno></c>
- as the first event after a code change.
- </p>
- <p>
- <c><anno>Event</anno></c> is
- an <c>{EventType,EventContent}</c> tuple.
- </p>
- </item>
- <tag>
<c>
{postpone,<anno>Event</anno>,<anno>State</anno>,<anno>NextState</anno>}
</c>
@@ -267,13 +252,26 @@
</item>
<tag>
<c>
- {enter,<anno>State</anno>}
+ {enter,<anno>Module</anno>,<anno>State</anno>}
+ </c>
+ </tag>
+ <item>
+ <p>
+ Is produced by <c>gen_statem</c>
+ when module <c><anno>Module</anno></c>
+ enters the first state <c><anno>State</anno></c>.
+ </p>
+ </item>
+ <tag>
+ <c>
+ {module,<anno>Module</anno>,<anno>State</anno>}
</c>
</tag>
<item>
<p>
Is produced by <c>gen_statem</c>
- when the first state <c><anno>State</anno></c> is entered.
+ when setting module <c><anno>Module</anno></c>
+ in state <c><anno>State</anno></c>.
</p>
</item>
<tag>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index 2ff124885d..11279ff410 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -50,7 +50,9 @@
<p>Creating timers using
<seemfa marker="erts:erlang#send_after/3">erlang:send_after/3</seemfa> and
<seemfa marker="erts:erlang#start_timer/3">erlang:start_timer/3</seemfa>
- is much more efficient than using the timers provided by this module. See
+ is more efficient than using the timers provided by this module. However,
+ the timer module has been improved in OTP 25, making it more efficient and
+ less susceptible to being overloaded. See
<seeguide marker="system/efficiency_guide:commoncaveats#timer-module">the
Timer Module section in the Efficiency Guide</seeguide>.</p>
</description>
@@ -116,8 +118,9 @@
<c>exit_after(<anno>Time</anno>, self(),
<anno>Reason1</anno>)</c>.</p>
<p><c>exit_after/3</c> sends an exit signal with reason
- <c><anno>Reason1</anno></c> to
- pid <c><anno>Pid</anno></c>. Returns <c>{ok, <anno>TRef</anno>}</c>
+ <c><anno>Reason1</anno></c> to <c><anno>Target</anno></c>,
+ which can be a local process identifier or an atom of a registered
+ name. Returns <c>{ok, <anno>TRef</anno>}</c>
or <c>{error, <anno>Reason2</anno>}</c>.</p>
</desc>
</func>
@@ -149,7 +152,7 @@
<p><c>kill_after/1</c> is the same as
<c>exit_after(<anno>Time</anno>, self(), kill)</c>.</p>
<p><c>kill_after/2</c> is the same as
- <c>exit_after(<anno>Time</anno>, <anno>Pid</anno>, kill)</c>.</p>
+ <c>exit_after(<anno>Time</anno>, <anno>Target</anno>, kill)</c>.</p>
</desc>
</func>
@@ -190,15 +193,16 @@
<func>
<name name="send_after" arity="2" since=""/>
<name name="send_after" arity="3" since=""/>
- <fsummary>Send <c>Message</c> to <c>Pid</c> after a specified
+ <fsummary>Send <c>Message</c> to <c>Destination</c> after a specified
<c>Time</c>.</fsummary>
<desc>
<taglist>
<tag><c>send_after/3</c></tag>
<item>
- <p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c> after
- <c><anno>Time</anno></c> milliseconds. (<c><anno>Pid</anno></c>
- can also be an atom of a registered name.)</p>
+ <p>Evaluates <c><anno>Destination</anno> ! <anno>Message</anno></c> after
+ <c><anno>Time</anno></c> milliseconds. (<c><anno>Destination</anno></c> can
+ be a remote or local process identifier, an atom of a registered name or
+ a tuple <c>{RegName, Node}</c> for a registered name at another node.)</p>
<p>Returns <c>{ok, <anno>TRef</anno>}</c> or
<c>{error, <anno>Reason</anno>}</c>.</p>
<p>See also
@@ -223,10 +227,11 @@
<taglist>
<tag><c>send_interval/3</c></tag>
<item>
- <p>Evaluates <c><anno>Pid</anno> ! <anno>Message</anno></c>
+ <p>Evaluates <c><anno>Destination</anno> ! <anno>Message</anno></c>
repeatedly after <c><anno>Time</anno></c> milliseconds.
- (<c><anno>Pid</anno></c> can also be
- an atom of a registered name.)</p>
+ (<c><anno>Destination</anno></c> can be a remote or local process
+ identifier, an atom of a registered name or a tuple <c>{RegName, Node}</c>
+ for a registered name at another node.)</p>
<p>Returns <c>{ok, <anno>TRef</anno>}</c> or
<c>{error, <anno>Reason</anno>}</c>.</p>
</item>
@@ -249,6 +254,11 @@
or suspends the process forever if <c><anno>Time</anno></c> is the
atom <c>infinity</c>. Naturally, this
function does <em>not</em> return immediately.</p>
+ <note>
+ <p>Before OTP 25, <c>timer:sleep/1</c> did not accept integer
+ timeout values greater than <c>16#ffffffff</c>, that is, <c>2^32-1</c>.
+ Since OTP 25, arbitrarily high integer values are accepted.</p>
+ </note>
</desc>
</func>
@@ -350,4 +360,3 @@ timer:cancel(R),
<seemfa marker="#cancel/1"><c>cancel/1</c></seemfa>.</p>
</section>
</erlref>
-
diff --git a/lib/stdlib/doc/src/uri_string.xml b/lib/stdlib/doc/src/uri_string.xml
index 4fe24e656f..08fc09e150 100644
--- a/lib/stdlib/doc/src/uri_string.xml
+++ b/lib/stdlib/doc/src/uri_string.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2017</year><year>2020</year>
+ <year>2017</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -84,9 +84,14 @@
<item>Dissecting form-urlencoded query strings into a list of key-value pairs<br></br>
<seemfa marker="#dissect_query/1"><c>dissect_query/1</c></seemfa>
</item>
- <item>Decoding percent-encoded triplets<br></br>
+ <item>Decoding percent-encoded triplets in URI map or a specific component of URI<br></br>
<seemfa marker="#percent_decode/1"><c>percent_decode/1</c></seemfa>
</item>
+ <item>Preparing and retrieving application specific data included in URI components<br></br>
+ <seemfa marker="#quote/1"><c>quote/1</c></seemfa>
+ <seemfa marker="#quote/2"><c>quote/2</c></seemfa>
+ <seemfa marker="#unquote/1"><c>unquote/1</c></seemfa>
+ </item>
</list>
<p>There are four different encodings present during the handling of URIs:</p>
<list type="bulleted">
@@ -110,6 +115,15 @@
character encoding and it is usually defined by the protocol or surrounding text. This library
takes the same assumption, binary and percent-encoding are handled as one configuration unit,
they cannot be set to different values.</p>
+ <p>Quoting functions are intended to be used by URI producing application
+ during component preparation or retrieval phase to avoid conflicts between
+ data and characters used in URI syntax. Quoting functions use percent
+ encoding, but with different rules than for example during execution of
+ <c>recompose/1</c>. It is user responsibility to provide quoting
+ functions with application data only and using their output to combine an
+ URI component.<br></br>Quoting functions can for instance be used for constructing a path
+ component with a segment containing '/' character which should not collide with
+ '/' used as general delimiter in path component.</p>
</description>
<datatypes>
@@ -358,6 +372,48 @@
</func>
<func>
+ <name name="quote" arity="1" since="OTP 25.0"/>
+ <fsummary>Percent encode characters out of unreserved set.</fsummary>
+ <desc>
+ <p>Replaces characters out of unreserved set with their percent encoded equivalents.</p>
+ <p>Unreserved characters defined in
+ <url href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url> are not quoted.</p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input><![CDATA[uri_string:quote("SomeId/04").]]></input>
+<![CDATA["SomeId%2F04"]]>
+2> <input><![CDATA[uri_string:quote(<<"SomeId/04">>).]]></input>
+<![CDATA[<<"SomeId%2F04">>]]>
+ </pre>
+
+ <warning><p>Function is not aware about any URI component context and
+ should not be used on whole URI. If applied more than once on the same
+ data, might produce unexpected results.</p></warning>
+ </desc>
+ </func>
+
+ <func>
+ <name name="quote" arity="2" since="OTP 25.0"/>
+ <fsummary>Percent encode characters out of unreserved set and user defined
+ safe list.</fsummary>
+ <desc>
+ <p>Same as <c>quote/1</c>, but <c><anno>Safe</anno></c> allows user to
+ provide a list of characters to be protected from encoding.</p>
+ <p><em>Example:</em></p>
+ <pre>
+1> <input><![CDATA[uri_string:quote("SomeId/04", "/").]]></input>
+<![CDATA["SomeId/04"]]>
+2> <input><![CDATA[uri_string:quote(<<"SomeId/04">>, "/").]]></input>
+<![CDATA[<<"SomeId/04">>]]>
+ </pre>
+
+ <warning><p>Function is not aware about any URI component context and
+ should not be used on whole URI. If applied more than once on the same
+ data, might produce unexpected results.</p></warning>
+ </desc>
+ </func>
+
+ <func>
<name name="recompose" arity="1" since="OTP 21.0"/>
<fsummary>Recompose URI.</fsummary>
<desc>
@@ -445,5 +501,24 @@
</desc>
</func>
+ <func>
+ <name name="unquote" arity="1" since="OTP 25.0"/>
+ <fsummary>Percent decode characters.</fsummary>
+ <desc>
+ <p>Percent decode characters.</p>
+
+ <p><em>Example:</em></p>
+ <pre>
+1> <input><![CDATA[uri_string:unquote("SomeId%2F04").]]></input>
+<![CDATA["SomeId/04"]]>
+2> <input><![CDATA[uri_string:unquote(<<"SomeId%2F04">>).]]></input>
+<![CDATA[<<"SomeId/04">>]]>
+ </pre>
+
+ <warning><p>Function is not aware about any URI component context and
+ should not be used on whole URI. If applied more than once on the same
+ data, might produce unexpected results.</p></warning>
+ </desc>
+ </func>
</funcs>
</erlref>
diff --git a/lib/stdlib/doc/src/uri_string_usage.xml b/lib/stdlib/doc/src/uri_string_usage.xml
index 72851096b7..31e2c23c45 100644
--- a/lib/stdlib/doc/src/uri_string_usage.xml
+++ b/lib/stdlib/doc/src/uri_string_usage.xml
@@ -4,8 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2020</year>
- <year>2020</year>
+ <year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -294,12 +293,14 @@
and it happens when converting a
<seetype marker="uri_string#uri_map"><c>uri_map()</c></seetype>
into a <seetype marker="uri_string#uri_string"><c>uri_string()</c></seetype>.
- There is no equivalent to a raw percent-encoding function as percent-encoding
- shall be applied on the component level using different sets of allowed characters.
- Applying percent-encoding directly on an input URI would not be safe just as in
+ Applying any percent-encoding directly on an input URI would not be safe just as in
the case of
<seemfa marker="uri_string#percent_decode/1"><c>uri_string:percent_decode/1</c></seemfa>,
the output could be an invalid URI.
+ Quoting functions allow users to perform raw percent encoding and decoding
+ on application data which cannot be handled automatically by
+ <c>uri_string:recompose/1</c>. For example in scenario when user would
+ need to use '/' or sub-delimeter as data rather than delimeter in a path component.
</p>
</note>
</section>
diff --git a/lib/stdlib/examples/Makefile b/lib/stdlib/examples/Makefile
index 743ea87179..cbef038500 100644
--- a/lib/stdlib/examples/Makefile
+++ b/lib/stdlib/examples/Makefile
@@ -29,7 +29,7 @@ include ../vsn.mk
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index 292c06506a..d9d1154515 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -502,6 +502,17 @@ expr({'catch',Anno,E0}) ->
%% No new variables added.
E1 = expr(E0),
{'catch',Anno,E1};
+expr({'maybe',MaybeAnno,Es0}) ->
+ Es = exprs(Es0),
+ {'maybe',MaybeAnno,Es};
+expr({'maybe',MaybeAnno,Es0,{'else',ElseAnno,Cs0}}) ->
+ Es = exprs(Es0),
+ Cs = clauses(Cs0),
+ {'maybe',MaybeAnno,Es,{'else',ElseAnno,Cs}};
+expr({maybe_match,Anno,P0,E0}) ->
+ E = expr(E0),
+ P = pattern(P0),
+ {maybe_match,Anno,P,E};
expr({match,Anno,P0,E0}) ->
E1 = expr(E0),
P1 = pattern(P0),
diff --git a/lib/stdlib/scripts/generate_ryu_table.escript b/lib/stdlib/scripts/generate_ryu_table.escript
deleted file mode 100755
index dce203401c..0000000000
--- a/lib/stdlib/scripts/generate_ryu_table.escript
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%! +A0
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--mode(compile).
-
--define(MOD, "io_lib_format_ryu_table").
-
--define(TABLE_SIZE, 326).
--define(INV_TABLE_SIZE, 342).
-
--define(POW5_BITCOUNT, 125).
--define(POW5_INV_BITCOUNT, 125).
-
-main(_) ->
- Values = [ values(X) || X <- lists:seq(0, ?TABLE_SIZE - 1)],
- InvValues = [ inv_values(X) || X <- lists:seq(0, ?INV_TABLE_SIZE - 1)],
-
- %% Make module
- {ok, Out} = file:open("../src/" ++ ?MOD ++ ".erl", [write]),
- gen_file(Out, Values, InvValues),
- ok = file:close(Out),
- ok.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-inv_values(X) ->
- Pow = pow5(X),
- Pow5len = log2floor(Pow),
- J = Pow5len + ?POW5_INV_BITCOUNT - 1,
- Inv = ((1 bsl J) div Pow) + 1,
- {X, Inv}.
-
-values(X) ->
- Pow = pow5(X),
- Pow5len = log2floor(Pow),
- Pow5 = Pow bsr (Pow5len - ?POW5_BITCOUNT),
- {X, Pow5}.
-
-pow5(0) ->
- 1;
-pow5(1) ->
- 5;
-pow5(X) ->
- 5 * pow5(X - 1).
-
-log2floor(Int) when is_integer(Int), Int > 0 ->
- log2floor(Int, 0).
-
-log2floor(0, N) ->
- N;
-log2floor(Int, N) ->
- log2floor(Int bsr 1, 1 + N).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-gen_file(Fd, Values, InvValues) ->
- gen_header(Fd),
- gen_pow5_static(Fd),
- gen_table(Fd, Values),
- gen_inv_table(Fd, InvValues),
- ok.
-
-gen_header(Fd) ->
- io:put_chars(Fd, "%%\n%% this file is generated do not modify\n"),
- io:put_chars(Fd, "%% see ../script/generate_ryu_table.escript\n\n"),
- io:put_chars(Fd, "-module(" ++ ?MOD ++").\n"),
- io:put_chars(Fd, "-export([pow5_bitcount/0, pow5_inv_bitcount/0, value/1, inv_value/1]).\n\n"),
- ok.
-
-gen_pow5_static(Fd) ->
- io:put_chars(Fd, "-spec pow5_bitcount() -> integer().\n"),
- io:format(Fd, "pow5_bitcount() -> ~p.~n~n", [?POW5_BITCOUNT]),
- io:put_chars(Fd, "-spec pow5_inv_bitcount() -> integer().\n"),
- io:format(Fd, "pow5_inv_bitcount() -> ~p.~n~n", [?POW5_INV_BITCOUNT]),
- ok.
-
-gen_table(Fd, Values) ->
- io:put_chars(Fd, "-spec value(integer()) -> integer().\n"),
- [io:format(Fd, "value(~p) -> ~p;~n", [Key, Val]) || {Key,Val} <- Values],
- io:put_chars(Fd, "value(_) -> error(function_clause).\n\n"),
- ok.
-
-gen_inv_table(Fd, Values) ->
- io:put_chars(Fd, "-spec inv_value(integer()) -> integer().\n"),
- [io:format(Fd, "inv_value(~p) -> ~p;~n", [Key, Val]) || {Key,Val} <- Values],
- io:put_chars(Fd, "inv_value(_) -> error(function_clause).\n"),
- ok.
-
diff --git a/lib/stdlib/scripts/update_deprecations b/lib/stdlib/scripts/update_deprecations
index ef6be3b5af..ba34392c36 100755
--- a/lib/stdlib/scripts/update_deprecations
+++ b/lib/stdlib/scripts/update_deprecations
@@ -4,7 +4,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -237,13 +237,32 @@ make_xml(Top, Type, OutFile, InfoText0) ->
InfoTextMap = maps:from_list(make_xml_info(InfoText0, AttrTag)),
Collected = make_xml_collect(Depr, RelKey, InfoTextMap, []),
- All = make_xml_gen(lists:reverse(Collected), Type, OutDir),
- file:write_file(OutFile, All),
+ case Type of
+ "removed" ->
+ {ok, Vsn} = file:read_file(filename:join(Top,"OTP_VERSION")),
+ [Release|_] = string:split(Vsn,"."),
+ lists:foreach(
+ fun({Rel, Functions}) ->
+ case Rel > binary_to_integer(Release) of
+ true ->
+ io:format(standard_error,
+ "Some functions have been marked "
+ "as removed in the future: ~n~p~n",
+ [Functions]),
+ halt(1);
+ false ->
+ ok
+ end
+ end, Collected);
+ _ ->
+ ok
+ end,
- ok.
+ All = make_xml_gen(lists:reverse(Collected), Type, OutDir),
+ ok = file:write_file(OutFile, All).
make_xml_info([{Tag,M,F,A,Text} | Attributes], Tag) ->
- [{{M,F,A}, Text} | make_xml_info(Attributes, Tag)];
+ [{{M,F,A}, info_string(Text)} | make_xml_info(Attributes, Tag)];
make_xml_info([_ | Attributes], Tag) ->
make_xml_info(Attributes, Tag);
make_xml_info([], _Tag) ->
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index 509648cb2b..761d6c4c28 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2020. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -65,6 +65,7 @@ MODULES= \
erl_error \
erl_eval \
erl_expand_records \
+ erl_features \
erl_internal \
erl_lint \
erl_parse \
@@ -91,7 +92,6 @@ MODULES= \
io \
io_lib \
io_lib_format \
- io_lib_format_ryu_table \
io_lib_fread \
io_lib_pretty \
lists \
@@ -103,6 +103,7 @@ MODULES= \
orddict \
ordsets \
re \
+ peer \
pool \
proc_lib \
proplists \
@@ -165,11 +166,17 @@ endif
ERL_COMPILE_FLAGS += -Werror
ERL_COMPILE_FLAGS += -I../include -I../../kernel/include
+ifeq ($(ERL_DETERMINISTIC),yes)
+ DETERMINISM_FLAG = +deterministic
+else
+ DETERMINISM_FLAG =
+endif
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
clean:
rm -f $(TARGET_FILES)
@@ -184,22 +191,24 @@ primary_bootstrap_compiler: \
$(BOOTSTRAP_COMPILER)/ebin/epp.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_anno.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_error.beam \
+ $(BOOTSTRAP_COMPILER)/ebin/erl_features.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_scan.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam \
$(BOOTSTRAP_COMPILER)/ebin/erl_lint.beam \
$(BOOTSTRAP_COMPILER)/ebin/io.beam \
$(BOOTSTRAP_COMPILER)/ebin/otp_internal.beam
+
$(BOOTSTRAP_COMPILER)/ebin/erl_parse.beam: erl_parse.yrl
$(gen_verbose)
- $(V_at)$(ERLC) -o $(BOOTSTRAP_COMPILER)/egen erl_parse.yrl
- $(V_at)$(ERLC) -o $(BOOTSTRAP_COMPILER)/ebin $(BOOTSTRAP_COMPILER)/egen/erl_parse.erl
+ $(V_at)$(ERLC) -o $(BOOTSTRAP_COMPILER)/egen $(DETERMINISM_FLAG) erl_parse.yrl
+ $(V_at)$(ERLC) -o $(BOOTSTRAP_COMPILER)/ebin $(DETERMINISM_FLAG) $(BOOTSTRAP_COMPILER)/egen/erl_parse.erl
$(BOOTSTRAP_TOP)/lib/stdlib/egen/erl_parse.erl: erl_parse.yrl
$(yecc_verbose)$(ERLC) $(YRL_FLAGS) -o$(BOOTSTRAP_TOP)/lib/stdlib/egen erl_parse.yrl
$(BOOTSTRAP_COMPILER)/ebin/%.beam: %.erl
- $(V_ERLC) -o $(BOOTSTRAP_COMPILER)/ebin $<
+ $(V_ERLC) -o $(BOOTSTRAP_COMPILER)/ebin $(DETERMINISM_FLAG) $<
# ----------------------------------------------------
# Special Build Targets
diff --git a/lib/stdlib/src/beam_lib.erl b/lib/stdlib/src/beam_lib.erl
index 438d76e47f..5eed3c06b6 100644
--- a/lib/stdlib/src/beam_lib.erl
+++ b/lib/stdlib/src/beam_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -953,13 +953,13 @@ error(Reason) ->
%% The following chunks must be kept when stripping a BEAM file.
significant_chunks() ->
- ["Line" | md5_chunks()].
+ ["Line", "Type" | md5_chunks()].
%% The following chunks are significant when calculating the MD5
%% for a module. They are listed in the order that they should be MD5:ed.
md5_chunks() ->
- ["Atom", "AtU8", "Code", "StrT", "ImpT", "ExpT", "FunT", "LitT"].
+ ["Atom", "AtU8", "Code", "StrT", "ImpT", "ExpT", "FunT", "LitT", "Meta"].
%% The following chunks are mandatory in every Beam file.
@@ -1150,11 +1150,12 @@ terminate(_Reason, _State) ->
ok.
crypto_key_fun_from_file() ->
+ UserConfig = filename:basedir(user_config,"erlang"),
case init:get_argument(home) of
{ok,[[Home]]} ->
- crypto_key_fun_from_file_1([".",Home]);
+ crypto_key_fun_from_file_1([".", Home, UserConfig]);
_ ->
- crypto_key_fun_from_file_1(["."])
+ crypto_key_fun_from_file_1([".", UserConfig])
end.
crypto_key_fun_from_file_1(Path) ->
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index 01b70f7f6a..88573d1df1 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -793,9 +793,10 @@ lm() ->
erlangrc() ->
case init:get_argument(home) of
- {ok,[[Home]]} ->
- erlangrc([Home]);
- _ ->
+ {ok,[[Home]]} ->
+ UserConfig = filename:basedir(user_config,"erlang"),
+ erlangrc([Home, UserConfig]);
+ _ ->
{error, enoent}
end.
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 2f95f54312..788444a664 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,11 +94,11 @@
-type yearweeknum() :: {year(),weeknum()}.
-type rfc3339_string() :: [byte(), ...].
-%% By design 'native' is not supported:
-type rfc3339_time_unit() :: 'microsecond'
| 'millisecond'
| 'nanosecond'
- | 'second'.
+ | 'second'
+ | 'native'.
%%----------------------------------------------------------------------
@@ -326,7 +326,7 @@ local_time_to_universal_time_dst(DateTime) ->
-spec now_to_datetime(Now) -> datetime1970() when
Now :: erlang:timestamp().
now_to_datetime({MSec, Sec, _uSec}) ->
- system_time_to_datetime(MSec*1000000 + Sec).
+ system_time_to_datetime(MSec*1_000_000 + Sec).
-spec now_to_universal_time(Now) -> datetime1970() when
Now :: erlang:timestamp().
@@ -444,7 +444,23 @@ system_time_to_rfc3339(Time) ->
system_time_to_rfc3339(Time, Options) ->
Unit = proplists:get_value(unit, Options, second),
- OffsetOption = proplists:get_value(offset, Options, ""),
+ OffsetOpt0 = proplists:get_value(offset, Options, ""),
+ case Unit of
+ native ->
+ TimeMS = erlang:convert_time_unit(Time, native, millisecond),
+ OffsetOpt1 =
+ if is_integer(OffsetOpt0) ->
+ erlang:convert_time_unit(OffsetOpt0, native,
+ millisecond);
+ true ->
+ OffsetOpt0
+ end,
+ system_time_to_rfc3339_do(TimeMS, Options, millisecond, OffsetOpt1);
+ _ ->
+ system_time_to_rfc3339_do(Time, Options, Unit, OffsetOpt0)
+ end.
+
+system_time_to_rfc3339_do(Time, Options, Unit, OffsetOption) ->
T = proplists:get_value(time_designator, Options, $T),
AdjustmentSecs = offset_adjustment(Time, Unit, OffsetOption),
Offset = offset(OffsetOption, AdjustmentSecs),
@@ -702,9 +718,14 @@ offset_string_adjustment(_Time, _Unit, "Z") ->
offset_string_adjustment(_Time, _Unit, "z") ->
0;
offset_string_adjustment(_Time, _Unit, Tz) ->
- [Sign, H1, H2, $:, M1, M2] = Tz,
+ [Sign, H1, H2 | MinutesDiff] = Tz,
Hour = list_to_integer([H1, H2]),
- Min = list_to_integer([M1, M2]),
+ Min = case MinutesDiff of
+ [$:, M1, M2] ->
+ list_to_integer([M1, M2]);
+ [] ->
+ 0
+ end,
Adjustment = 3600 * Hour + 60 * Min,
case Sign of
$- -> -Adjustment;
@@ -738,12 +759,13 @@ copy_sign(N1, _N2) -> N1.
factor(second) -> 1;
factor(millisecond) -> 1000;
-factor(microsecond) -> 1000000;
-factor(nanosecond) -> 1000000000.
+factor(microsecond) -> 1_000_000;
+factor(nanosecond) -> 1_000_000_000;
+factor(native) -> erlang:convert_time_unit(1, second, native).
log10(1000) -> 3;
-log10(1000000) -> 6;
-log10(1000000000) -> 9.
+log10(1_000_000) -> 6;
+log10(1_000_000_000) -> 9.
pad(0, S) ->
S;
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index 0488c2bef2..640ad7a81c 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -149,7 +149,7 @@
proc :: 'undefined' | pid(), % the pid of the Dets process
match_program :: 'true'
| 'undefined'
- | {'match_spec', ets:comp_match_spec()}
+ | {'match_spec', ets:compiled_match_spec()}
}).
-record(open_args, {
@@ -321,7 +321,7 @@ foldl(Fun, Acc, Tab) ->
-spec from_ets(Name, EtsTab) -> 'ok' | {'error', Reason} when
Name :: tab_name(),
- EtsTab :: ets:tab(),
+ EtsTab :: ets:table(),
Reason :: term().
from_ets(DTab, ETab) ->
@@ -861,7 +861,7 @@ table_info(_Tab, _) ->
-spec to_ets(Name, EtsTab) -> EtsTab | {'error', Reason} when
Name :: tab_name(),
- EtsTab :: ets:tab(),
+ EtsTab :: ets:table(),
Reason :: term().
to_ets(DTab, ETab) ->
diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl
index 6f9bbcd2bd..797839ac4e 100644
--- a/lib/stdlib/src/digraph.erl
+++ b/lib/stdlib/src/digraph.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,9 +39,9 @@
-export_type([graph/0, d_type/0, vertex/0, edge/0, label/0]).
--record(digraph, {vtab = notable :: ets:tab(),
- etab = notable :: ets:tab(),
- ntab = notable :: ets:tab(),
+-record(digraph, {vtab = notable :: ets:table(),
+ etab = notable :: ets:table(),
+ ntab = notable :: ets:table(),
cyclic = true :: boolean()}).
-opaque graph() :: #digraph{}.
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 53b91530c5..bdb0bc64a2 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,8 +72,13 @@
uses = #{} %Macro use structure
:: #{name() => [{argspec(), [used()]}]},
default_encoding = ?DEFAULT_ENCODING :: source_encoding(),
- pre_opened = false :: boolean(),
- fname = [] :: function_name_type()
+ pre_opened = false :: boolean(),
+ in_prefix = true :: boolean(),
+ erl_scan_opts = [] :: [_],
+ features = [] :: [atom()],
+ else_reserved = false :: boolean(),
+ fname = [] :: function_name_type(),
+ deterministic = false :: boolean()
}).
%% open(Options)
@@ -115,6 +120,7 @@ open(Name, Path, Pdm) ->
Options :: [{'default_encoding', DefEncoding :: source_encoding()} |
{'includes', IncludePath :: [DirectoryName :: file:name()]} |
{'source_name', SourceName :: file:name()} |
+ {'deterministic', Enabled :: boolean()} |
{'macros', PredefMacros :: macros()} |
{'name',FileName :: file:name()} |
{'location',StartLocation :: erl_anno:location()} |
@@ -131,12 +137,14 @@ open(Options) ->
Name ->
Self = self(),
Epp = spawn(fun() -> server(Self, Name, Options) end),
+ Extra = proplists:get_bool(extra, Options),
case epp_request(Epp) of
- {ok, Pid, Encoding} ->
- case proplists:get_bool(extra, Options) of
- true -> {ok, Pid, [{encoding, Encoding}]};
- false -> {ok, Pid}
- end;
+ {ok, Pid, Encoding} when Extra ->
+ {ok, Pid, [{encoding, Encoding}]};
+ {ok, Pid, _} ->
+ {ok, Pid};
+ {ok, Pid} when Extra ->
+ {ok, Pid, []};
Other ->
Other
end
@@ -239,6 +247,8 @@ format_error({error,Term}) ->
io_lib:format("-error(~tp).", [Term]);
format_error({warning,Term}) ->
io_lib:format("-warning(~tp).", [Term]);
+format_error(ftr_after_prefix) ->
+ "feature directive not allowed after exports or record definitions";
format_error(E) -> file:format_error(E).
-spec scan_file(FileName, Options) ->
@@ -297,6 +307,8 @@ parse_file(Ifile, Path, Predefs) ->
{'macros', PredefMacros :: macros()} |
{'default_encoding', DefEncoding :: source_encoding()} |
{'location',StartLocation :: erl_anno:location()} |
+ {'reserved_word_fun', Fun :: fun((atom()) -> boolean())} |
+ {'features', [Feature :: atom()]} |
'extra'],
Form :: erl_parse:abstract_form()
| {'error', ErrorInfo}
@@ -311,11 +323,13 @@ parse_file(Ifile, Options) ->
{ok,Epp} ->
Forms = parse_file(Epp),
close(Epp),
- {ok,Forms};
+ {ok, Forms};
{ok,Epp,Extra} ->
Forms = parse_file(Epp),
+ Epp ! {get_features, self()},
+ Ftrs = receive {features, X} -> X end,
close(Epp),
- {ok,Forms,Extra};
+ {ok, Forms, [{features, Ftrs} | Extra]};
{error,E} ->
{error,E}
end.
@@ -593,7 +607,8 @@ server(Pid, Name, Options) ->
init_server(Pid, FileName, Options, St0) ->
SourceName = proplists:get_value(source_name, Options, FileName),
Pdm = proplists:get_value(macros, Options, []),
- Ms0 = predef_macros(SourceName),
+ Features = proplists:get_value(features, Options, []),
+ Ms0 = predef_macros(SourceName, Features),
case user_predef(Pdm, Ms0) of
{ok,Ms1} ->
DefEncoding = proplists:get_value(default_encoding, Options,
@@ -604,28 +619,58 @@ init_server(Pid, FileName, Options, St0) ->
%% first in path
Path = [filename:dirname(FileName) |
proplists:get_value(includes, Options, [])],
+ ResWordFun =
+ proplists:get_value(reserved_word_fun, Options,
+ fun erl_scan:f_reserved_word/1),
%% the default location is 1 for backwards compatibility, not {1,1}
AtLocation = proplists:get_value(location, Options, 1),
+
+ Deterministic = proplists:get_value(deterministic, Options, false),
St = St0#epp{delta=0, name=SourceName, name2=SourceName,
path=Path, location=AtLocation, macs=Ms1,
- default_encoding=DefEncoding},
+ default_encoding=DefEncoding,
+ erl_scan_opts =
+ [{text_fun, keep_ftr_keywords()},
+ {reserved_word_fun, ResWordFun}],
+ features = Features,
+ else_reserved = ResWordFun('else'),
+ deterministic = Deterministic},
From = wait_request(St),
Anno = erl_anno:new(AtLocation),
enter_file_reply(From, file_name(SourceName), Anno,
- AtLocation, code),
+ AtLocation, code, Deterministic),
wait_req_scan(St);
{error,E} ->
epp_reply(Pid, {error,E})
end.
+%% Return a function that keeps quoted atoms that are keywords in
+%% configurable features. Need in erl_lint to avoid warning about
+%% them.
+keep_ftr_keywords() ->
+ Features = erl_features:configurable(),
+ Keywords = lists:flatmap(fun erl_features:keywords/1, Features),
+ F = fun(Atom) -> atom_to_list(Atom) ++ "'" end,
+ Strings = lists:map(F, Keywords),
+ fun(atom, [$'|S]) -> lists:member(S, Strings);
+ (_, _) -> false
+ end.
+
%% predef_macros(FileName) -> Macrodict
%% Initialise the macro dictionary with the default predefined macros,
%% FILE, LINE, MODULE as undefined, MACHINE and MACHINE value.
-predef_macros(File) ->
+predef_macros(File, EnabledFeatures0) ->
Machine = list_to_atom(erlang:system_info(machine)),
Anno = line1(),
OtpVersion = list_to_integer(erlang:system_info(otp_release)),
+ AvailableFeatures =
+ [Ftr || Ftr <- erl_features:all(),
+ maps:get(status, erl_features:info(Ftr)) /= rejected],
+ PermanentFeatures =
+ [Ftr || Ftr <- erl_features:all(),
+ maps:get(status, erl_features:info(Ftr)) == permanent],
+ EnabledFeatures = EnabledFeatures0 ++ PermanentFeatures,
Defs = [{'FILE', {none,[{string,Anno,File}]}},
{'FUNCTION_NAME', undefined},
{'FUNCTION_ARITY', undefined},
@@ -636,10 +681,36 @@ predef_macros(File) ->
{'BASE_MODULE_STRING', undefined},
{'MACHINE', {none,[{atom,Anno,Machine}]}},
{Machine, {none,[{atom,Anno,true}]}},
- {'OTP_RELEASE', {none,[{integer,Anno,OtpVersion}]}}
+ {'OTP_RELEASE', {none,[{integer,Anno,OtpVersion}]}},
+ {'FEATURE_AVAILABLE', [ftr_macro(AvailableFeatures)]},
+ {'FEATURE_ENABLED', [ftr_macro(EnabledFeatures)]}
],
maps:from_list(Defs).
+%% Make macro definition from a list of features. The macro takes one
+%% argument and returns true when argument is available as a feature.
+ftr_macro(Features) ->
+ Anno = line1(),
+ Arg = 'X',
+ Fexp = fun(Ftr) -> [{'(', Anno},
+ {var, Anno, Arg},
+ {')', Anno},
+ {'==', Anno},
+ {atom, Anno, Ftr}]
+ end,
+ Body =
+ case Features of
+ [] -> [{atom, Anno, false}];
+ [Ftr| Ftrs] ->
+ [{'(', Anno}|
+ lists:foldl(fun(F, Expr) ->
+ Fexp(F) ++ [{'orelse', Anno} | Expr]
+ end,
+ Fexp(Ftr) ++ [{')', Anno}],
+ Ftrs)]
+ end,
+ {1, {[Arg], Body}}.
+
%% user_predef(PreDefMacros, Macros) ->
%% {ok,MacroDict} | {error,E}
%% Add the predefined macros to the macros dictionary. A macro without a
@@ -674,6 +745,9 @@ user_predef([], Ms) -> {ok,Ms}.
wait_request(St) ->
receive
{epp_request,From,scan_erl_form} -> From;
+ {get_features, From} ->
+ From ! {features, St#epp.features},
+ wait_request(St);
{epp_request,From,macro_defs} ->
%% Return the old format to avoid any incompability issues.
Defs = [{{atom,K},V} || {K,V} <- maps:to_list(St#epp.macs)],
@@ -728,10 +802,15 @@ enter_file(NewName, Inc, From, St) ->
enter_file2(NewF, Pname, From, St0, AtLocation) ->
Anno = erl_anno:new(AtLocation),
- enter_file_reply(From, Pname, Anno, AtLocation, code),
+ enter_file_reply(From, Pname, Anno, AtLocation, code, St0#epp.deterministic),
#epp{macs = Ms0,
- default_encoding = DefEncoding} = St0,
- Ms = Ms0#{'FILE':={none,[{string,Anno,Pname}]}},
+ default_encoding = DefEncoding,
+ in_prefix = InPrefix,
+ erl_scan_opts = ScanOpts,
+ else_reserved = ElseReserved,
+ features = Ftrs,
+ deterministic = Deterministic} = St0,
+ Ms = Ms0#{'FILE':={none,[{string,Anno,source_name(St0,Pname)}]}},
%% 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
@@ -742,16 +821,21 @@ enter_file2(NewF, Pname, From, St0, AtLocation) ->
_ = set_encoding(NewF, DefEncoding),
#epp{file=NewF,location=AtLocation,name=Pname,name2=Pname,delta=0,
sstk=[St0|St0#epp.sstk],path=Path,macs=Ms,
- default_encoding=DefEncoding}.
-
-enter_file_reply(From, Name, LocationAnno, AtLocation, Where) ->
+ in_prefix = InPrefix,
+ features = Ftrs,
+ erl_scan_opts = ScanOpts,
+ else_reserved = ElseReserved,
+ default_encoding=DefEncoding,
+ deterministic=Deterministic}.
+
+enter_file_reply(From, Name, LocationAnno, AtLocation, Where, Deterministic) ->
Anno0 = erl_anno:new(AtLocation),
Anno = case Where of
code -> Anno0;
generated -> erl_anno:set_generated(true, Anno0)
end,
Rep = {ok, [{'-',Anno},{atom,Anno,file},{'(',Anno},
- {string,Anno,Name},{',',Anno},
+ {string,Anno,source_name(Deterministic,Name)},{',',Anno},
{integer,Anno,get_line(LocationAnno)},{')',LocationAnno},
{dot,Anno}]},
epp_reply(From, Rep).
@@ -783,9 +867,17 @@ leave_file(From, St) ->
CurrLoc = add_line(OldLoc, Delta),
Anno = erl_anno:new(CurrLoc),
Ms0 = St#epp.macs,
- Ms = Ms0#{'FILE':={none,[{string,Anno,OldName2}]}},
- NextSt = OldSt#epp{sstk=Sts,macs=Ms,uses=St#epp.uses},
- enter_file_reply(From, OldName, Anno, CurrLoc, code),
+ InPrefix = St#epp.in_prefix,
+ Ftrs = St#epp.features,
+ ElseReserved = St#epp.else_reserved,
+ ScanOpts = St#epp.erl_scan_opts,
+ Ms = Ms0#{'FILE':={none,[{string,Anno,source_name(St,OldName2)}]}},
+ NextSt = OldSt#epp{sstk=Sts,macs=Ms,uses=St#epp.uses,
+ in_prefix = InPrefix,
+ features = Ftrs,
+ else_reserved = ElseReserved,
+ erl_scan_opts = ScanOpts},
+ enter_file_reply(From, OldName, Anno, CurrLoc, code, St#epp.deterministic),
case OldName2 =:= OldName of
true ->
ok;
@@ -793,7 +885,7 @@ leave_file(From, St) ->
NFrom = wait_request(NextSt),
OldAnno = erl_anno:new(OldLoc),
enter_file_reply(NFrom, OldName2, OldAnno,
- CurrLoc, generated)
+ CurrLoc, generated, St#epp.deterministic)
end,
wait_req_scan(NextSt);
[] ->
@@ -806,27 +898,30 @@ leave_file(From, St) ->
%% scan_toks(Tokens, From, EppState)
scan_toks(From, St) ->
- case io:scan_erl_form(St#epp.file, '', St#epp.location) of
- {ok,Toks,Cl} ->
- scan_toks(Toks, From, St#epp{location=Cl});
- {error,E,Cl} ->
- epp_reply(From, {error,E}),
- wait_req_scan(St#epp{location=Cl});
- {eof,Cl} ->
- leave_file(From, St#epp{location=Cl});
- {error,_E} ->
+ #epp{file = File, location = Loc, erl_scan_opts = ScanOpts} = St,
+ case io:scan_erl_form(File, '', Loc, ScanOpts) of
+ {ok,Toks,Cl} ->
+ scan_toks(Toks, From, St#epp{location=Cl});
+ {error,E,Cl} ->
+ epp_reply(From, {error,E}),
+ wait_req_scan(St#epp{location=Cl});
+ {eof,Cl} ->
+ leave_file(From, St#epp{location=Cl});
+ {error,_E} ->
epp_reply(From, {error,{St#epp.location,epp,cannot_parse}}),
- leave_file(wait_request(St), St) %This serious, just exit!
+ leave_file(wait_request(St), St) %This serious, just exit!
end.
+scan_toks([{'-',_Lh},{atom,_Ld,feature}=Feature|Toks], From, St) ->
+ scan_feature(Toks, Feature, From, St);
scan_toks([{'-',_Lh},{atom,_Ld,define}=Define|Toks], From, St) ->
scan_define(Toks, Define, From, St);
scan_toks([{'-',_Lh},{atom,_Ld,undef}=Undef|Toks], From, St) ->
- scan_undef(Toks, Undef, From, St);
+ scan_undef(Toks, Undef, From, leave_prefix(St));
scan_toks([{'-',_Lh},{atom,_Ld,error}=Error|Toks], From, St) ->
- scan_err_warn(Toks, Error, From, St);
+ scan_err_warn(Toks, Error, From, leave_prefix(St));
scan_toks([{'-',_Lh},{atom,_Ld,warning}=Warn|Toks], From, St) ->
- scan_err_warn(Toks, Warn, From, St);
+ scan_err_warn(Toks, Warn, From, leave_prefix(St));
scan_toks([{'-',_Lh},{atom,_Li,include}=Inc|Toks], From, St) ->
scan_include(Toks, Inc, From, St);
scan_toks([{'-',_Lh},{atom,_Li,include_lib}=IncLib|Toks], From, St) ->
@@ -837,6 +932,10 @@ scan_toks([{'-',_Lh},{atom,_Li,ifndef}=IfnDef|Toks], From, St) ->
scan_ifndef(Toks, IfnDef, From, St);
scan_toks([{'-',_Lh},{atom,_Le,'else'}=Else|Toks], From, St) ->
scan_else(Toks, Else, From, St);
+%% conditionally allow else as a keyword
+scan_toks([{'-',_Lh},{'else',_Le}=Else|Toks], From, St)
+ when St#epp.else_reserved ->
+ scan_else(Toks, Else, From, St);
scan_toks([{'-',_Lh},{'if',_Le}=If|Toks], From, St) ->
scan_if(Toks, If, From, St);
scan_toks([{'-',_Lh},{atom,_Le,elif}=Elif|Toks], From, St) ->
@@ -854,13 +953,37 @@ scan_toks([{'-',_Lh},{atom,_Lf,file}=FileToken|Toks0], From, St) ->
scan_toks(Toks0, From, St) ->
case catch expand_macros(Toks0, St#epp{fname=Toks0}) of
Toks1 when is_list(Toks1) ->
+ InPrefix =
+ St#epp.in_prefix
+ andalso case Toks1 of
+ [] -> true;
+ [{'-', _Loc}, Tok | _] ->
+ in_prefix(Tok);
+ _ ->
+ false
+ end,
epp_reply(From, {ok,Toks1}),
- wait_req_scan(St#epp{macs=scan_module(Toks1, St#epp.macs)});
+ wait_req_scan(St#epp{in_prefix = InPrefix,
+ macs=scan_module(Toks1, St#epp.macs)});
{error,ErrL,What} ->
epp_reply(From, {error,{ErrL,epp,What}}),
wait_req_scan(St)
end.
+%% Determine whether we have passed the prefix where a -feature
+%% directive is allowed.
+in_prefix({atom, _, Atom}) ->
+ %% These directives are allowed inside the prefix
+ lists:member(Atom, ['module', 'feature',
+ 'if', 'else', 'elif', 'endif', 'ifdef', 'ifndef',
+ 'define', 'undef',
+ 'include', 'include_lib']);
+in_prefix(_T) ->
+ false.
+
+leave_prefix(#epp{} = St) ->
+ St#epp{in_prefix = false}.
+
scan_module([{'-',_Ah},{atom,_Am,module},{'(',_Al}|Ts], Ms) ->
scan_module_1(Ts, Ms);
scan_module([{'-',_Ah},{atom,_Am,extends},{'(',_Al}|Ts], Ms) ->
@@ -901,6 +1024,54 @@ scan_err_warn(Toks, {atom,_,Tag}=Token, From, St) ->
epp_reply(From, {error,{loc(T),epp,{bad,Tag}}}),
wait_req_scan(St).
+%% scan a feature directive
+scan_feature([{'(', _Ap}, {atom, _Am, Ftr},
+ {',', _}, {atom, _, Ind}, {')', _}, {dot, _}],
+ Feature, From, St)
+ when St#epp.in_prefix,
+ (Ind =:= enable
+ orelse Ind =:= disable) ->
+ case update_features(St, Ind, Ftr, loc(Feature)) of
+ {ok, St1} ->
+ scan_toks(From, St1);
+ {error, {{Mod, Reason}, ErrLoc}} ->
+ epp_reply(From, {error, {ErrLoc, Mod, Reason}}),
+ wait_req_scan(St)
+ end;
+scan_feature([{'(', _Ap}, {atom, _Am, _Ind},
+ {',', _}, {atom, _, _Ftr}, {')', _}, {dot, _}| _Toks],
+ Feature, From, St) when not St#epp.in_prefix ->
+ epp_reply(From, {error, {loc(Feature), epp,
+ ftr_after_prefix}}),
+ wait_req_scan(St);
+scan_feature(Toks, {atom, _, Tag} = Token, From, St) ->
+ T = no_match(Toks, Token),
+ epp_reply(From, {error,{loc(T),epp,{bad,Tag}}}),
+ wait_req_scan(St).
+
+update_features(St0, Ind, Ftr, Loc) ->
+ Ftrs0 = St0#epp.features,
+ ScanOpts0 = St0#epp.erl_scan_opts,
+ KeywordFun =
+ case proplists:get_value(reserved_word_fun, ScanOpts0) of
+ undefined -> fun erl_scan:f_reserved_word/1;
+ Fun -> Fun
+ end,
+ case erl_features:keyword_fun(Ind, Ftr, Ftrs0, KeywordFun) of
+ {error, Reason} ->
+ {error, {Reason, Loc}};
+ {ok, {Ftrs1, ResWordFun1}} ->
+ Macs0 = St0#epp.macs,
+ Macs1 = Macs0#{'FEATURE_ENABLED' => [ftr_macro(Ftrs1)]},
+ ScanOpts1 = proplists:delete(reserved_word_fun, ScanOpts0),
+ St = St0#epp{erl_scan_opts =
+ [{reserved_word_fun, ResWordFun1}| ScanOpts1],
+ features = Ftrs1,
+ else_reserved = ResWordFun1('else'),
+ macs = Macs1},
+ {ok, St}
+ end.
+
%% scan_define(Tokens, DefineToken, From, EppState)
scan_define([{'(',_Ap},{Type,_Am,_}=Mac|Toks], Def, From, St)
@@ -1298,9 +1469,9 @@ scan_file(Tokens0, Tf, From, St) ->
scan_file1([{'(',_Alp},{string,_As,Name},{',',_Ac},{integer,_Ai,Ln},{')',_Arp},
{dot,_Ad}], Tf, From, St) ->
Anno = erl_anno:new(Ln),
- enter_file_reply(From, Name, Anno, loc(Tf), generated),
+ enter_file_reply(From, Name, Anno, loc(Tf), generated, St#epp.deterministic),
Ms0 = St#epp.macs,
- Ms = Ms0#{'FILE':={none,[{string,line1(),Name}]}},
+ Ms = Ms0#{'FILE':={none,[{string,line1(),source_name(St,Name)}]}},
Locf = loc(Tf),
NewLoc = new_location(Ln, St#epp.location, Locf),
Delta = get_line(element(2, Tf))-Ln + St#epp.delta,
@@ -1320,7 +1491,8 @@ new_location(Ln, {Le,_}, {Lf,_}) ->
%% nested conditionals and repeated 'else's.
skip_toks(From, St, [I|Sis]) ->
- case io:scan_erl_form(St#epp.file, '', St#epp.location) of
+ ElseReserved = St#epp.else_reserved,
+ case io:scan_erl_form(St#epp.file, '', St#epp.location, St#epp.erl_scan_opts) of
{ok,[{'-',_Ah},{atom,_Ai,ifdef}|_Toks],Cl} ->
skip_toks(From, St#epp{location=Cl}, [ifdef,I|Sis]);
{ok,[{'-',_Ah},{atom,_Ai,ifndef}|_Toks],Cl} ->
@@ -1329,6 +1501,9 @@ skip_toks(From, St, [I|Sis]) ->
skip_toks(From, St#epp{location=Cl}, ['if',I|Sis]);
{ok,[{'-',_Ah},{atom,_Ae,'else'}=Else|_Toks],Cl}->
skip_else(Else, From, St#epp{location=Cl}, [I|Sis]);
+ %% conditionally allow else as reserved word
+ {ok,[{'-',_Ah},{'else',_Ae}=Else|_Toks],Cl} when ElseReserved ->
+ skip_else(Else, From, St#epp{location=Cl}, [I|Sis]);
{ok,[{'-',_Ah},{atom,_Ae,'elif'}=Elif|Toks],Cl}->
skip_elif(Toks, Elif, From, St#epp{location=Cl}, [I|Sis]);
{ok,[{'-',_Ah},{atom,_Ae,endif}|_Toks],Cl} ->
@@ -1915,3 +2090,12 @@ interpret_file_attr([Form0 | Forms], Delta, Fs) ->
[Form | interpret_file_attr(Forms, Delta, Fs)];
interpret_file_attr([], _Delta, _Fs) ->
[].
+
+-spec source_name(#epp{} | boolean(), file:filename_all()) -> file:filename_all().
+source_name(Deterministic, Name) when is_boolean(Deterministic) ->
+ case Deterministic of
+ true -> filename:basename(Name);
+ false -> Name
+ end;
+source_name(St, Name) ->
+ source_name(St#epp.deterministic, Name).
diff --git a/lib/stdlib/src/erl_anno.erl b/lib/stdlib/src/erl_anno.erl
index d0310f52e2..356417aa72 100644
--- a/lib/stdlib/src/erl_anno.erl
+++ b/lib/stdlib/src/erl_anno.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -361,7 +361,7 @@ anno_info(Anno, Item, Default) ->
Value
catch
_:_ ->
- erlang:error(badarg, [Anno])
+ erlang:error(badarg, [Anno, Item, Default])
end.
anno_info(Anno, Item) ->
@@ -372,7 +372,7 @@ anno_info(Anno, Item) ->
undefined
catch
_:_ ->
- erlang:error(badarg, [Anno])
+ erlang:error(badarg, [Anno, Item])
end.
end_location("", Line, Column) ->
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index 9701f77292..991efd4442 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,8 @@ compile_cmdline() ->
compile_cmdline1(List).
%% Run a compilation. Meant to be used by the compilation server.
--spec compile(list(), file:filename()) -> 'ok' | {'error', binary()}.
+-spec compile(list(), file:filename()) ->
+ 'ok' | {'error', binary()} | {'crash', {atom(), term(), term()}}.
compile(Args, Cwd) ->
try compile1(Args, #options{outdir=Cwd,cwd=Cwd}) of
ok ->
@@ -101,13 +102,16 @@ compile1(["-"++Option|T], Opts) ->
compile1(["+"++Option|Rest], Opts) ->
Term = make_term(Option),
Specific = Opts#options.specific,
- compile1(Rest, Opts#options{specific=[Term|Specific]});
+ compile1(Rest, Opts#options{specific=Specific++[Term]});
compile1(Files, Opts) ->
compile2(Files, Opts).
parse_generic_option("b"++Opt, T0, Opts) ->
{OutputType,T} = get_option("b", Opt, T0),
compile1(T, Opts#options{output_type=list_to_atom(OutputType)});
+%% parse_generic_option("c"++Opt, T0, Opts) ->
+%% {InputType,T} = get_option("c", Opt, T0),
+%% compile1(T, Opts#options{input_type=[$.| InputType]});
parse_generic_option("D"++Opt, T0, #options{defines=Defs}=Opts) ->
{Val0,T} = get_option("D", Opt, T0),
{Key0,Val1} = split_at_equals(Val0, []),
@@ -170,6 +174,25 @@ parse_generic_option("P", T, #options{specific=Spec}=Opts) ->
compile1(T, Opts#options{specific=['P'|Spec]});
parse_generic_option("S", T, #options{specific=Spec}=Opts) ->
compile1(T, Opts#options{specific=['S'|Spec]});
+parse_generic_option("enable-feature" ++ Str, T0,
+ #options{specific = Spec} = Opts) ->
+ {FtrStr, T} = get_option("enable-feature", Str, T0),
+ Feature = list_to_atom(FtrStr),
+ compile1(T, Opts#options{
+ specific = Spec ++ [{feature, Feature, enable}]});
+parse_generic_option("disable-feature" ++ Str, T0,
+ #options{specific = Spec} = Opts) ->
+ {FtrStr, T} = get_option("disable-feature", Str, T0),
+ Feature = list_to_atom(FtrStr),
+ compile1(T, Opts#options{specific = Spec ++ [{feature, Feature, disable}]});
+parse_generic_option("describe-feature" ++ Str, T0,
+ #options{specific = Spec} = Opts) ->
+ {FtrStr, T} = get_option("disable-feature", Str, T0),
+ Feature = list_to_atom(FtrStr),
+ compile1(T, Opts#options{specific =[{describe_feature, Feature}| Spec]});
+parse_generic_option("list-features", T,
+ #options{specific = Spec} = Opts) ->
+ compile1(T, Opts#options{specific =[{list_features, true}| Spec]});
parse_generic_option(Option, _T, _Opts) ->
usage(io_lib:format("Unknown option: -~ts\n", [Option])).
@@ -229,11 +252,24 @@ usage(Error) ->
{"-E","generate listing of expanded code (Erlang compiler)"},
{"-S","generate assembly listing (Erlang compiler)"},
{"-P","generate listing of preprocessed code (Erlang compiler)"},
+ {"-enable-feature <feature>",
+ "enable <feature> when compiling (Erlang compiler)"},
+ {"-disable-feature <feature>",
+ "disable <feature> when compiling (Erlang compiler)"},
+ {"-list-features",
+ "list short descriptions of available features (Erlang compiler)"},
+ {"-describe-feature <feature>",
+ "show long description of <feature>"},
{"+term","pass the Erlang term unchanged to the compiler"}],
+ Fmt = fun(K, D) when length(K) < 15 ->
+ io_lib:format("~-14s ~s\n", [K, D]);
+ (K, D) ->
+ io_lib:format("~s\n~-14s ~s\n", [K, "", D])
+ end,
Msg = [Error,
"Usage: erlc [Options] file.ext ...\n",
"Options:\n",
- [io_lib:format("~-14s ~s\n", [K,D]) || {K,D} <- H]],
+ [Fmt(K, D) || {K,D} <- H]],
throw({error, Msg}).
get_option(_Name, [], [[C|_]=Option|T]) when C =/= $- ->
@@ -251,14 +287,19 @@ split_at_equals([], Acc) ->
{lists:reverse(Acc),[]}.
compile2(Files, #options{cwd=Cwd,includes=Incl,outfile=Outfile}=Opts0) ->
- Opts = Opts0#options{includes=lists:reverse(Incl)},
- case {Outfile,length(Files)} of
- {"", _} ->
- compile3(Files, Cwd, Opts);
- {[_|_], 1} ->
- compile3(Files, Cwd, Opts);
- {[_|_], _N} ->
- throw({error, "Output file name given, but more than one input file.\n"})
+ case show_info(Opts0) of
+ {ok, Msg} ->
+ throw({error, Msg});
+ false ->
+ Opts = Opts0#options{includes=lists:reverse(Incl)},
+ case {Outfile,length(Files)} of
+ {"", _} ->
+ compile3(Files, Cwd, Opts);
+ {[_|_], 1} ->
+ compile3(Files, Cwd, Opts);
+ {[_|_], _N} ->
+ throw({error, "Output file name given, but more than one input file.\n"})
+ end
end.
%% Compile the list of files, until done or compilation fails.
@@ -277,6 +318,35 @@ compile3([File|Rest], Cwd, Options) ->
compile3(Rest, Cwd, Options);
compile3([], _Cwd, _Options) -> ok.
+show_info(#options{specific = Spec}) ->
+ G = fun G0([]) -> undefined;
+ G0([E|Es]) ->
+ case proplists:get_value(E, Spec) of
+ undefined -> G0(Es);
+ V -> {E, V}
+ end
+ end,
+
+ case G([list_features, describe_feature]) of
+ {list_features, true} ->
+ Features = erl_features:configurable(),
+ Msg = ["Available features:\n",
+ [io_lib:format(" ~-18s ~s\n", [Ftr, erl_features:short(Ftr)])
+ || Ftr <- Features]],
+ {ok, Msg};
+ {describe_feature, Ftr} ->
+ Description =
+ try
+ erl_features:long(Ftr)
+ catch
+ error:invalid_feature ->
+ io_lib:format("Unknown feature: ~p\n", [Ftr])
+ end,
+ {ok, Description};
+ _ ->
+ false
+ end.
+
%% Invoke the appropriate compiler, depending on the file extension.
compile_file("", Input, _Output, _Options) ->
throw({error, io_lib:format("File has no extension: ~ts~n", [Input])});
diff --git a/lib/stdlib/src/erl_error.erl b/lib/stdlib/src/erl_error.erl
index 7d5d9d8ae7..e3e7e11ff9 100644
--- a/lib/stdlib/src/erl_error.erl
+++ b/lib/stdlib/src/erl_error.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -269,6 +269,8 @@ explain_reason(restricted_shell_started, exit, [], _PF, _S, _Enc, _CL) ->
<<"restricted shell starts now">>;
explain_reason(restricted_shell_stopped, exit, [], _PF, _S, _Enc, _CL) ->
<<"restricted shell stopped">>;
+explain_reason(calling_self, exit, [], _PF, _S, _Enc, _CL) ->
+ <<"the current process attempted to call itself">>;
%% Other exit code:
explain_reason(Reason, Class, [], PF, S, _Enc, CL) ->
{L, _} = PF(Reason, (iolist_size(S)+1) + exited_size(Class), CL),
@@ -319,7 +321,7 @@ format_stacktrace2(S, [{M,F,As,_Info}|Fs], N, PF, Enc, CL, Reason, ErrorMap)
[sep(N, S), origin(N, M, F, A),
mfa_to_string(M, F, A, Enc),
CalledAs, C, FormattedError]),
- CL1 = sub(CL, Enc, Cs),
+ CL1 = sub(CL, Cs, Enc),
[Cs | format_stacktrace2(S, Fs, N + 1, PF, Enc, CL1, Reason, #{})];
format_stacktrace2(_S, [], _N, _PF, _Enc, _CL, _Reason, _ErrorMap) ->
"".
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index df2e6a25a1..987ba0cf0a 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -24,8 +24,7 @@
-export([exprs/2,exprs/3,exprs/4,expr/2,expr/3,expr/4,expr/5,
expr_list/2,expr_list/3,expr_list/4]).
-export([new_bindings/0,bindings/1,binding/2,add_binding/3,del_binding/2]).
--export([extended_parse_exprs/1, extended_parse_term/1,
- subst_values_for_vars/2]).
+-export([extended_parse_exprs/1, extended_parse_term/1]).
-export([is_constant_expr/1, partial_eval/1, eval_str/1]).
%% Is used by standalone Erlang (escript).
@@ -62,14 +61,17 @@
-type(func_spec() :: {Module :: module(), Function :: atom()} | function()).
-type(nlfun_handler() :: fun((FuncSpec :: func_spec(),
- Arguments :: [term()]) ->
- term())).
+ Arguments :: [term()]) -> term())
+ | fun((Anno :: erl_anno:anno(), FuncSpec :: func_spec(),
+ Arguments :: [term()]) -> term())).
-type(non_local_function_handler() :: {value, nlfun_handler()}
| none).
-define(STACKTRACE,
element(2, erlang:process_info(self(), current_stacktrace))).
+empty_fun_used_vars() -> #{}.
+
%% exprs(ExpressionSeq, Bindings)
%% exprs(ExpressionSeq, Bindings, LocalFuncHandler)
%% exprs(ExpressionSeq, Bindings, LocalFuncHandler, ExternalFuncHandler)
@@ -88,8 +90,8 @@
NewBindings :: binding_struct()).
exprs(Exprs, Bs) ->
case check_command(Exprs, Bs) of
- ok ->
- exprs(Exprs, Bs, none, none, none);
+ ok ->
+ exprs(Exprs, Bs, none, none, none, empty_fun_used_vars());
{error,{_Location,_Mod,Error}} ->
erlang:raise(error, Error, ?STACKTRACE)
end.
@@ -102,7 +104,7 @@ exprs(Exprs, Bs) ->
Value :: value(),
NewBindings :: binding_struct()).
exprs(Exprs, Bs, Lf) ->
- exprs(Exprs, Bs, Lf, none, none).
+ exprs(Exprs, Bs, Lf, none, none, empty_fun_used_vars()).
-spec(exprs(Expressions, Bindings, LocalFunctionHandler,
NonLocalFunctionHandler) ->
@@ -114,14 +116,51 @@ exprs(Exprs, Bs, Lf) ->
Value :: value(),
NewBindings :: binding_struct()).
exprs(Exprs, Bs, Lf, Ef) ->
- exprs(Exprs, Bs, Lf, Ef, none).
+ exprs(Exprs, Bs, Lf, Ef, none, empty_fun_used_vars()).
-exprs([E], Bs0, Lf, Ef, RBs) ->
- expr(E, Bs0, Lf, Ef, RBs);
-exprs([E|Es], Bs0, Lf, Ef, RBs) ->
+-spec(exprs(Expressions, Bindings, LocalFunctionHandler,
+ NonLocalFunctionHandler, ReturnFormat, FunUsedVars) ->
+ {value, Value, NewBindings} when
+ Expressions :: expressions(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ NonLocalFunctionHandler :: non_local_function_handler(),
+ ReturnFormat :: none | value,
+ FunUsedVars :: erl_lint:fun_used_vars(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
+exprs([E], Bs0, Lf, Ef, RBs, FUVs) ->
+ expr(E, Bs0, Lf, Ef, RBs, FUVs);
+exprs([E|Es], Bs0, Lf, Ef, RBs, FUVs) ->
RBs1 = none,
- {value,_V,Bs} = expr(E, Bs0, Lf, Ef, RBs1),
- exprs(Es, Bs, Lf, Ef, RBs).
+ {value,_V,Bs} = expr(E, Bs0, Lf, Ef, RBs1, FUVs),
+ exprs(Es, Bs, Lf, Ef, RBs, FUVs).
+
+%% maybe_match_exprs(Expression, Bindings, LocalFuncHandler, ExternalFuncHandler)
+%% Returns one of:
+%% {success,Value}
+%% {failure,Value}
+%% or raises an exception.
+
+maybe_match_exprs([{maybe_match,Anno,Lhs,Rhs0}|Es], Bs0, Lf, Ef) ->
+ {value,Rhs,Bs1} = expr(Rhs0, Bs0, Lf, Ef, none),
+ case match(Lhs, Rhs, Anno, Bs1, Bs1, Ef) of
+ {match,Bs} ->
+ case Es of
+ [] ->
+ {success,Rhs};
+ [_|_] ->
+ maybe_match_exprs(Es, Bs, Lf, Ef)
+ end;
+ nomatch ->
+ {failure,Rhs}
+ end;
+maybe_match_exprs([E], Bs0, Lf, Ef) ->
+ {value,V,_Bs} = expr(E, Bs0, Lf, Ef, none),
+ {success,V};
+maybe_match_exprs([E|Es], Bs0, Lf, Ef) ->
+ {value,_V,Bs} = expr(E, Bs0, Lf, Ef, none),
+ maybe_match_exprs(Es, Bs, Lf, Ef).
%% expr(Expression, Bindings)
%% expr(Expression, Bindings, LocalFuncHandler)
@@ -139,7 +178,7 @@ exprs([E|Es], Bs0, Lf, Ef, RBs) ->
NewBindings :: binding_struct()).
expr(E, Bs) ->
case check_command([E], Bs) of
- ok ->
+ ok ->
expr(E, Bs, none, none, none);
{error,{_Location,_Mod,Error}} ->
erlang:raise(error, Error, ?STACKTRACE)
@@ -185,9 +224,9 @@ fun_data(F) when is_function(F) ->
case erlang:fun_info(F, module) of
{module,?MODULE} ->
case erlang:fun_info(F, env) of
- {env,[{FBs,_FLf,_FEf,FCs}]} ->
+ {env,[{_FAnno,FBs,_FLf,_FEf,_FUVs,FCs}]} ->
{fun_data,FBs,FCs};
- {env,[{FBs,_FLf,_FEf,FCs,FName}]} ->
+ {env,[{_FAnno,FBs,_FLf,_FEf,_FUVs,FCs,FName}]} ->
{named_fun_data,FBs,FName,FCs}
end;
_ ->
@@ -206,92 +245,103 @@ fun_data(_T) ->
ReturnFormat :: none | value,
Value :: value(),
NewBindings :: binding_struct()).
-expr({var,_,V}, Bs, _Lf, _Ef, RBs) ->
+expr(Expr, Bs, Lf, Ef, Rbs) ->
+ expr(Expr, Bs, Lf, Ef, Rbs, empty_fun_used_vars()).
+
+-spec(expr(Expression, Bindings, LocalFunctionHandler,
+ NonLocalFunctionHandler, ReturnFormat, FunUsedVars) ->
+ {value, Value, NewBindings} | Value when
+ Expression :: expression(),
+ Bindings :: binding_struct(),
+ LocalFunctionHandler :: local_function_handler(),
+ NonLocalFunctionHandler :: non_local_function_handler(),
+ ReturnFormat :: none | value,
+ FunUsedVars :: erl_lint:fun_used_vars(),
+ Value :: value(),
+ NewBindings :: binding_struct()).
+expr({var,Anno,V}, Bs, _Lf, Ef, RBs, _FUVs) ->
case binding(V, Bs) of
{value,Val} ->
ret_expr(Val, Bs, RBs);
unbound -> % Cannot not happen if checked by erl_lint
- erlang:raise(error, {unbound,V}, ?STACKTRACE)
+ apply_error({unbound,V}, ?STACKTRACE, Anno, Bs, Ef, RBs)
end;
-expr({char,_,C}, Bs, _Lf, _Ef, RBs) ->
+expr({char,_,C}, Bs, _Lf, _Ef, RBs, _FUVs) ->
ret_expr(C, Bs, RBs);
-expr({integer,_,I}, Bs, _Lf, _Ef, RBs) ->
+expr({integer,_,I}, Bs, _Lf, _Ef, RBs, _FUVs) ->
ret_expr(I, Bs, RBs);
-expr({float,_,F}, Bs, _Lf, _Ef, RBs) ->
+expr({float,_,F}, Bs, _Lf, _Ef, RBs, _FUVs) ->
ret_expr(F, Bs, RBs);
-expr({atom,_,A}, Bs, _Lf, _Ef, RBs) ->
+expr({atom,_,A}, Bs, _Lf, _Ef, RBs, _FUVs) ->
ret_expr(A, Bs, RBs);
-expr({string,_,S}, Bs, _Lf, _Ef, RBs) ->
+expr({string,_,S}, Bs, _Lf, _Ef, RBs, _FUVs) ->
ret_expr(S, Bs, RBs);
-expr({nil, _}, Bs, _Lf, _Ef, RBs) ->
+expr({nil, _}, Bs, _Lf, _Ef, RBs, _FUVs) ->
ret_expr([], Bs, RBs);
-expr({cons,_,H0,T0}, Bs0, Lf, Ef, RBs) ->
- {value,H,Bs1} = expr(H0, Bs0, Lf, Ef, none),
- {value,T,Bs2} = expr(T0, Bs0, Lf, Ef, none),
- ret_expr([H|T], merge_bindings(Bs1, Bs2), RBs);
-expr({lc,_,E,Qs}, Bs, Lf, Ef, RBs) ->
- eval_lc(E, Qs, Bs, Lf, Ef, RBs);
-expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs) ->
- eval_bc(E, Qs, Bs, Lf, Ef, RBs);
-expr({tuple,_,Es}, Bs0, Lf, Ef, RBs) ->
- {Vs,Bs} = expr_list(Es, Bs0, Lf, Ef),
+expr({cons,Anno,H0,T0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,H,Bs1} = expr(H0, Bs0, Lf, Ef, none, FUVs),
+ {value,T,Bs2} = expr(T0, Bs0, Lf, Ef, none, FUVs),
+ ret_expr([H|T], merge_bindings(Bs1, Bs2, Anno, Ef), RBs);
+expr({lc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) ->
+ eval_lc(E, Qs, Bs, Lf, Ef, RBs, FUVs);
+expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) ->
+ eval_bc(E, Qs, Bs, Lf, Ef, RBs, FUVs);
+expr({tuple,_,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {Vs,Bs} = expr_list(Es, Bs0, Lf, Ef, FUVs),
ret_expr(list_to_tuple(Vs), Bs, RBs);
-expr({record_field,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
-expr({record_index,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
-expr({record,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
-expr({record,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
+expr({record_field,Anno,_,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+ apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
+expr({record_index,Anno,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+ apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
+expr({record,Anno,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+ apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
+expr({record,Anno,_,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+ apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
%% map
-expr({map,_,Binding,Es}, Bs0, Lf, Ef, RBs) ->
- {value, Map0, Bs1} = expr(Binding, Bs0, Lf, Ef, none),
- {Vs,Bs2} = eval_map_fields(Es, Bs0, Lf, Ef),
+expr({map,Anno,Binding,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value, Map0, Bs1} = expr(Binding, Bs0, Lf, Ef, none, FUVs),
+ {Vs,Bs2} = eval_map_fields(Es, Bs0, Lf, Ef, FUVs),
_ = maps:put(k, v, Map0), %Validate map.
Map1 = lists:foldl(fun ({map_assoc,K,V}, Mi) ->
maps:put(K, V, Mi);
({map_exact,K,V}, Mi) ->
maps:update(K, V, Mi)
end, Map0, Vs),
- ret_expr(Map1, merge_bindings(Bs2, Bs1), RBs);
-expr({map,_,Es}, Bs0, Lf, Ef, RBs) ->
- {Vs,Bs} = eval_map_fields(Es, Bs0, Lf, Ef),
+ ret_expr(Map1, merge_bindings(Bs2, Bs1, Anno, Ef), RBs);
+expr({map,_,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {Vs,Bs} = eval_map_fields(Es, Bs0, Lf, Ef, FUVs),
ret_expr(lists:foldl(fun
({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi)
end, maps:new(), Vs), Bs, RBs);
-expr({block,_,Es}, Bs, Lf, Ef, RBs) ->
- exprs(Es, Bs, Lf, Ef, RBs);
-expr({'if',_,Cs}, Bs, Lf, Ef, RBs) ->
- if_clauses(Cs, Bs, Lf, Ef, RBs);
-expr({'case',_,E,Cs}, Bs0, Lf, Ef, RBs) ->
- {value,Val,Bs} = expr(E, Bs0, Lf, Ef, none),
- case_clauses(Val, Cs, Bs, Lf, Ef, RBs);
-expr({'try',_,B,Cases,Catches,AB}, Bs, Lf, Ef, RBs) ->
- try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs);
-expr({'receive',_,Cs}, Bs, Lf, Ef, RBs) ->
- receive_clauses(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',_Anno,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) ->
- {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef),
+expr({block,_,Es}, Bs, Lf, Ef, RBs, FUVs) ->
+ exprs(Es, Bs, Lf, Ef, RBs, FUVs);
+expr({'if',Anno,Cs}, Bs, Lf, Ef, RBs, FUVs) ->
+ if_clauses(Cs, Anno, Bs, Lf, Ef, RBs, FUVs);
+expr({'case',Anno,E,Cs}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,Val,Bs} = expr(E, Bs0, Lf, Ef, none, FUVs),
+ case_clauses(Val, Cs, Anno, Bs, Lf, Ef, RBs, FUVs);
+expr({'try',Anno,B,Cases,Catches,AB}, Bs, Lf, Ef, RBs, FUVs) ->
+ try_clauses(B, Cases, Catches, AB, Anno, Bs, Lf, Ef, RBs, FUVs);
+expr({'receive',_,Cs}, Bs, Lf, Ef, RBs, FUVs) ->
+ receive_clauses(Cs, Bs, Lf, Ef, RBs, FUVs);
+expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,T,Bs} = expr(E, Bs0, Lf, Ef, none, FUVs),
+ receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, RBs, FUVs);
+expr({'fun',_Anno,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef, FUVs),
F = erlang:make_fun(Mod, Name, Arity),
- ret_expr(F, Bs, RBs);
-expr({'fun',_Anno,{function,Name,Arity}}, _Bs0, _Lf, _Ef, _RBs) -> % R8
+ ret_expr(F, Bs, RBs);
+expr({'fun',Anno,{function,Name,Arity}}, Bs0, _Lf, Ef, RBs, _FUVs) -> % R8
%% Don't know what to do...
- erlang:raise(error, undef, [{?MODULE,Name,Arity}|?STACKTRACE]);
-expr({'fun',Anno,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs) ->
- %% Save only used variables in the function environment.
- %% {value,L,V} are hidden while lint finds used variables.
- {Ex1, _} = hide_calls(Ex, 0),
- {ok,Used} = erl_lint:used_vars([Ex1], bindings(Bs)),
- En = filter_bindings(fun(K,_V) -> member(K,Used) end, Bs),
- Info = {En,Lf,Ef,Cs},
+ apply_error(undef, [{?MODULE,Name,Arity}|?STACKTRACE], Anno, Bs0, Ef, RBs);
+expr({'fun',Anno,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs, FUVs) ->
+ {En,NewFUVs} = fun_used_bindings(Ex, Cs, Bs, FUVs),
+ Info = {Anno,En,Lf,Ef,NewFUVs,Cs},
+
%% This is a really ugly hack!
- F =
+ F =
case length(element(3,hd(Cs))) of
0 -> fun () -> eval_fun([], Info) end;
1 -> fun (A) -> eval_fun([A], Info) end;
@@ -327,17 +377,14 @@ expr({'fun',Anno,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs) ->
eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T], Info) end;
_Other ->
L = erl_anno:location(Anno),
- erlang:raise(error, {'argument_limit',{'fun',L,to_terms(Cs)}},
- ?STACKTRACE)
+ Reason = {'argument_limit',{'fun',L,to_terms(Cs)}},
+ apply_error(Reason, ?STACKTRACE, Anno, Bs, Ef, RBs)
end,
ret_expr(F, Bs, RBs);
-expr({named_fun,Anno,Name,Cs} = Ex, Bs, Lf, Ef, RBs) ->
- %% Save only used variables in the function environment.
- %% {value,L,V} are hidden while lint finds used variables.
- {Ex1, _} = hide_calls(Ex, 0),
- {ok,Used} = erl_lint:used_vars([Ex1], bindings(Bs)),
- En = filter_bindings(fun(K,_V) -> member(K,Used) end, Bs),
- Info = {En,Lf,Ef,Cs,Name},
+expr({named_fun,Anno,Name,Cs} = Ex, Bs, Lf, Ef, RBs, FUVs) ->
+ {En,NewFUVs} = fun_used_bindings(Ex, Cs, Bs, FUVs),
+ Info = {Anno,En,Lf,Ef,NewFUVs,Cs,Name},
+
%% This is a really ugly hack!
F =
case length(element(3,hd(Cs))) of
@@ -380,58 +427,57 @@ expr({named_fun,Anno,Name,Cs} = Ex, Bs, Lf, Ef, RBs) ->
RF, Info) end;
_Other ->
L = erl_anno:location(Anno),
- erlang:raise(error, {'argument_limit',
- {named_fun,L,Name,to_terms(Cs)}},
- ?STACKTRACE)
+ Reason = {'argument_limit',{named_fun,L,Name,to_terms(Cs)}},
+ apply_error(Reason, ?STACKTRACE, Anno, Bs, Ef, RBs)
end,
ret_expr(F, Bs, RBs);
-expr({call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[{lc,_,_E,_Qs}=LC | As0]},
- Bs0, Lf, Ef, RBs) when length(As0) =< 1 ->
+expr({call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[{lc,_,_E,_Qs}=LC | As0]},
+ Bs0, Lf, Ef, RBs, FUVs) when length(As0) =< 1 ->
%% No expansion or evaluation of module name or function name.
MaxLine = find_maxline(LC),
{LC1, D} = hide_calls(LC, MaxLine),
case qlc:transform_from_evaluator(LC1, Bs0) of
{ok,{call,A,Remote,[QLC]}} ->
QLC1 = unhide_calls(QLC, MaxLine, D),
- expr({call,A,Remote,[QLC1 | As0]}, Bs0, Lf, Ef, RBs);
+ expr({call,A,Remote,[QLC1 | As0]}, Bs0, Lf, Ef, RBs, FUVs);
{not_ok,Error} ->
ret_expr(Error, Bs0, RBs)
end;
expr({call,A1,{remote,A2,{record_field,_,{atom,_,''},{atom,_,qlc}=Mod},
{atom,_,q}=Func},
- [{lc,_,_E,_Qs} | As0]=As},
- Bs, Lf, Ef, RBs) when length(As0) =< 1 ->
- expr({call,A1,{remote,A2,Mod,Func},As}, Bs, Lf, Ef, RBs);
-expr({call,_,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs) ->
- {value,M,Bs1} = expr(Mod, Bs0, Lf, Ef, none),
- {value,F,Bs2} = expr(Func, Bs0, Lf, Ef, none),
- {As,Bs3} = expr_list(As0, merge_bindings(Bs1, Bs2), Lf, Ef),
+ [{lc,_,_E,_Qs} | As0]=As},
+ Bs, Lf, Ef, RBs, FUVs) when length(As0) =< 1 ->
+ expr({call,A1,{remote,A2,Mod,Func},As}, Bs, Lf, Ef, RBs, FUVs);
+expr({call,Anno,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,M,Bs1} = expr(Mod, Bs0, Lf, Ef, none, FUVs),
+ {value,F,Bs2} = expr(Func, Bs0, Lf, Ef, none, FUVs),
+ {As,Bs3} = expr_list(As0, merge_bindings(Bs1, Bs2, Anno, Ef), Lf, Ef, FUVs),
%% M could be a parameterized module (not an atom).
case is_atom(M) andalso erl_internal:bif(M, F, length(As)) of
true ->
- bif(F, As, Bs3, Ef, RBs);
+ bif(F, As, Anno, Bs3, Ef, RBs);
false ->
- do_apply(M, F, As, Bs3, Ef, RBs)
+ do_apply(M, F, As, Anno, Bs3, Ef, RBs)
end;
-expr({call,_,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs) ->
+expr({call,Anno,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs, FUVs) ->
case erl_internal:bif(Func, length(As0)) of
true ->
{As,Bs} = expr_list(As0, Bs0, Lf, Ef),
- bif(Func, As, Bs, Ef, RBs);
+ bif(Func, As, Anno, Bs, Ef, RBs);
false ->
- local_func(Func, As0, Bs0, Lf, Ef, RBs)
+ local_func(Func, As0, Anno, Bs0, Lf, Ef, RBs, FUVs)
end;
-expr({call,_,Func0,As0}, Bs0, Lf, Ef, RBs) -> % function or {Mod,Fun}
- {value,Func,Bs1} = expr(Func0, Bs0, Lf, Ef, none),
- {As,Bs2} = expr_list(As0, Bs1, Lf, Ef),
+expr({call,Anno,Func0,As0}, Bs0, Lf, Ef, RBs, FUVs) -> % function or {Mod,Fun}
+ {value,Func,Bs1} = expr(Func0, Bs0, Lf, Ef, none, FUVs),
+ {As,Bs2} = expr_list(As0, Bs1, Lf, Ef, FUVs),
case Func of
{M,F} when is_atom(M), is_atom(F) ->
- erlang:raise(error, {badfun,Func}, ?STACKTRACE);
+ apply_error({badfun,Func}, ?STACKTRACE, Anno, Bs0, Ef, RBs);
_ ->
- do_apply(Func, As, Bs2, Ef, RBs)
+ do_apply(Func, As, Anno, Bs2, Ef, RBs)
end;
-expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs) ->
- try expr(Expr, Bs0, Lf, Ef, none) of
+expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs, FUVs) ->
+ try expr(Expr, Bs0, Lf, Ef, none, FUVs) of
{value,V,Bs} ->
ret_expr(V, Bs, RBs)
catch
@@ -442,48 +488,65 @@ expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs) ->
error:Reason:Stacktrace ->
ret_expr({'EXIT',{Reason,Stacktrace}}, Bs0, RBs)
end;
-expr({match,_,Lhs,Rhs0}, Bs0, Lf, Ef, RBs) ->
- {value,Rhs,Bs1} = expr(Rhs0, Bs0, Lf, Ef, none),
- case match(Lhs, Rhs, Bs1) of
+expr({match,Anno,Lhs,Rhs0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,Rhs,Bs1} = expr(Rhs0, Bs0, Lf, Ef, none, FUVs),
+ case match(Lhs, Rhs, Anno, Bs1, Bs1, Ef) of
{match,Bs} ->
ret_expr(Rhs, Bs, RBs);
- nomatch -> erlang:raise(error, {badmatch,Rhs}, ?STACKTRACE)
+ nomatch -> apply_error({badmatch,Rhs}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
+ end;
+expr({'maybe',_,Es}, Bs, Lf, Ef, RBs, _FUVs) ->
+ {_,Val} = maybe_match_exprs(Es, Bs, Lf, Ef),
+ ret_expr(Val, Bs, RBs);
+expr({'maybe',Anno,Es,{'else',_,Cs}}, Bs0, Lf, Ef, RBs, FUVs) ->
+ case maybe_match_exprs(Es, Bs0, Lf, Ef) of
+ {success,Val} ->
+ ret_expr(Val, Bs0, RBs);
+ {failure,Val} ->
+ case match_clause(Cs, [Val], Bs0, Lf, Ef) of
+ {B, Bs} ->
+ exprs(B, Bs, Lf, Ef, RBs, FUVs);
+ nomatch ->
+ apply_error({else_clause,Val}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
+ end
end;
-expr({op,_,Op,A0}, Bs0, Lf, Ef, RBs) ->
- {value,A,Bs} = expr(A0, Bs0, Lf, Ef, none),
- eval_op(Op, A, Bs, Ef, RBs);
-expr({op,_,'andalso',L0,R0}, Bs0, Lf, Ef, RBs) ->
- {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none),
+expr({op,Anno,Op,A0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,A,Bs} = expr(A0, Bs0, Lf, Ef, none, FUVs),
+ eval_op(Op, A, Anno, Bs, Ef, RBs);
+expr({op,Anno,'andalso',L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
V = case L of
true ->
- {value,R,_} = expr(R0, Bs1, Lf, Ef, none),
+ {value,R,_} = expr(R0, Bs1, Lf, Ef, none, FUVs),
R;
false -> false;
- _ -> erlang:raise(error, {badarg,L}, ?STACKTRACE)
+ _ -> apply_error({badarg,L}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
end,
ret_expr(V, Bs1, RBs);
-expr({op,_,'orelse',L0,R0}, Bs0, Lf, Ef, RBs) ->
- {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none),
+expr({op,Anno,'orelse',L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
V = case L of
true -> true;
false ->
- {value,R,_} = expr(R0, Bs1, Lf, Ef, none),
+ {value,R,_} = expr(R0, Bs1, Lf, Ef, none, FUVs),
R;
- _ -> erlang:raise(error, {badarg,L}, ?STACKTRACE)
+ _ -> apply_error({badarg,L}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
end,
ret_expr(V, Bs1, RBs);
-expr({op,_,Op,L0,R0}, Bs0, Lf, Ef, RBs) ->
- {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none),
- {value,R,Bs2} = expr(R0, Bs0, Lf, Ef, none),
- eval_op(Op, L, R, merge_bindings(Bs1, Bs2), Ef, RBs);
-expr({bin,_,Fs}, Bs0, Lf, Ef, RBs) ->
- EvalFun = fun(E, B) -> expr(E, B, Lf, Ef, none) end,
- {value,V,Bs} = eval_bits:expr_grp(Fs, Bs0, EvalFun),
+expr({op,Anno,Op,L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
+ {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
+ {value,R,Bs2} = expr(R0, Bs0, Lf, Ef, none, FUVs),
+ eval_op(Op, L, R, Anno, merge_bindings(Bs1, Bs2, Anno, Ef), Ef, RBs);
+expr({bin,_,Fs}, Bs0, Lf, Ef, RBs, FUVs) ->
+ EvalFun = fun(E, B) -> expr(E, B, Lf, Ef, none, FUVs) end,
+ ErrorFun = fun(A, R, S) -> apply_error(R, S, A, Bs0, Ef, RBs) end,
+ {value,V,Bs} = eval_bits:expr_grp(Fs, Bs0, EvalFun, ErrorFun),
ret_expr(V, Bs, RBs);
-expr({remote,_,_,_}, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, {badexpr,':'}, ?STACKTRACE);
-expr({value,_,Val}, Bs, _Lf, _Ef, RBs) -> % Special case straight values.
- ret_expr(Val, Bs, RBs).
+expr({remote,Anno,_,_}, Bs0, _Lf, Ef, RBs, _FUVs) ->
+ apply_error({badexpr,':'}, ?STACKTRACE, Anno, Bs0, Ef, RBs).
+
+apply_error(Reason, Stack, Anno, Bs0, Ef, RBs) ->
+ do_apply(erlang, raise, [error, Reason, Stack], Anno, Bs0, Ef, RBs).
find_maxline(LC) ->
put('$erl_eval_max_line', 0),
@@ -503,43 +566,52 @@ find_maxline(LC) ->
_ = erl_parse:map_anno(F, LC),
erase('$erl_eval_max_line').
+fun_used_bindings(Fun, Cs, Bs, FUVs) ->
+ {Used,InnerFUVs} =
+ case FUVs of
+ %% If this clause is in our fun used vars tree,
+ %% then we do not need to compute to traverse it again.
+ #{Cs := UsedAndFUVs} ->
+ UsedAndFUVs;
+
+ #{} ->
+ %% Save only used variables in the function environment.
+ AllUsedVars = erl_lint:used_vars([Fun], bindings(Bs)),
+
+ %% At the root we should see only a single function,
+ %% so we extract its used vars and its tree out.
+ [{_,UsedAndFUVs}] = maps:to_list(AllUsedVars),
+ UsedAndFUVs
+ end,
+
+ {filter_bindings(fun(K,_V) -> member(K,Used) end, Bs),InnerFUVs}.
+
hide_calls(LC, MaxLine) ->
LineId0 = MaxLine + 1,
{NLC, _, D} = hide(LC, LineId0, maps:new()),
{NLC, D}.
-%% v/1 and local calls are hidden.
-hide({value,L,V}, Id, D) ->
- A = erl_anno:new(Id),
- {{atom,A,ok}, Id+1, maps:put(Id, {value,L,V}, D)};
+%% Local calls are hidden from qlc so they are not expanded.
hide({call,A,{atom,_,N}=Atom,Args}, Id0, D0) ->
{NArgs, Id, D} = hide(Args, Id0, D0),
C = case erl_internal:bif(N, length(Args)) of
true ->
{call,A,Atom,NArgs};
- false ->
+ false ->
Anno = erl_anno:new(Id),
{call,Anno,{remote,A,{atom,A,m},{atom,A,f}},NArgs}
end,
{C, Id+1, maps:put(Id, {call,Atom}, D)};
-hide(T0, Id0, D0) when is_tuple(T0) ->
+hide(T0, Id0, D0) when is_tuple(T0) ->
{L, Id, D} = hide(tuple_to_list(T0), Id0, D0),
{list_to_tuple(L), Id, D};
-hide([E0 | Es0], Id0, D0) ->
+hide([E0 | Es0], Id0, D0) ->
{E, Id1, D1} = hide(E0, Id0, D0),
{Es, Id, D} = hide(Es0, Id1, D1),
{[E | Es], Id, D};
-hide(E, Id, D) ->
+hide(E, Id, D) ->
{E, Id, D}.
-unhide_calls({atom,A,ok}=E, MaxLine, D) ->
- L = erl_anno:line(A),
- if
- L > MaxLine ->
- map_get(L, D);
- true ->
- E
- end;
unhide_calls({call,Anno,{remote,A,{atom,A,m},{atom,A,f}}=F,Args},
MaxLine, D) ->
Line = erl_anno:line(Anno),
@@ -550,84 +622,71 @@ unhide_calls({call,Anno,{remote,A,{atom,A,m},{atom,A,f}}=F,Args},
true ->
{call,Anno,F,unhide_calls(Args, MaxLine, D)}
end;
-unhide_calls(T, MaxLine, D) when is_tuple(T) ->
+unhide_calls(T, MaxLine, D) when is_tuple(T) ->
list_to_tuple(unhide_calls(tuple_to_list(T), MaxLine, D));
-unhide_calls([E | Es], MaxLine, D) ->
+unhide_calls([E | Es], MaxLine, D) ->
[unhide_calls(E, MaxLine, D) | unhide_calls(Es, MaxLine, D)];
-unhide_calls(E, _MaxLine, _D) ->
+unhide_calls(E, _MaxLine, _D) ->
E.
-%% local_func(Function, Arguments, Bindings, LocalFuncHandler,
-%% ExternalFuncHandler, RBs) ->
+%% local_func(Function, Arguments, Anno, Bindings, LocalFuncHandler,
+%% ExternalFuncHandler, RBs, FunUsedVars) ->
%% {value,Value,Bindings} | Value when
%% LocalFuncHandler = {value,F} | {value,F,Eas} |
%% {eval,F} | {eval,F,Eas} | none.
-local_func(Func, As0, Bs0, {value,F}, Ef, value) ->
- {As1,_Bs1} = expr_list(As0, Bs0, {value,F}, Ef),
+local_func(Func, As0, _Anno, Bs0, {value,F}, Ef, value, FUVs) ->
+ {As1,_Bs1} = expr_list(As0, Bs0, {value,F}, Ef, FUVs),
%% Make tail recursive calls when possible.
F(Func, As1);
-local_func(Func, As0, Bs0, {value,F}, Ef, RBs) ->
- {As1,Bs1} = expr_list(As0, Bs0, {value,F}, Ef),
+local_func(Func, As0, _Anno, Bs0, {value,F}, Ef, RBs, FUVs) ->
+ {As1,Bs1} = expr_list(As0, Bs0, {value,F}, Ef, FUVs),
ret_expr(F(Func, As1), Bs1, RBs);
-local_func(Func, As0, Bs0, {value,F,Eas}, Ef, RBs) ->
+local_func(Func, As0, Anno, Bs0, {value,F,Eas}, Ef, RBs, FUVs) ->
Fun = fun(Name, Args) -> apply(F, [Name,Args|Eas]) end,
- local_func(Func, As0, Bs0, {value, Fun}, Ef, RBs);
-local_func(Func, As, Bs, {eval,F}, _Ef, RBs) ->
- local_func2(F(Func, As, Bs), RBs);
-local_func(Func, As, Bs, {eval,F,Eas}, _Ef, RBs) ->
- local_func2(apply(F, [Func,As,Bs|Eas]), RBs);
+ local_func(Func, As0, Anno, Bs0, {value, Fun}, Ef, RBs, FUVs);
+local_func(Func, As, Anno, Bs, {eval,F}, _Ef, RBs, _FUVs) ->
+ local_func2(F(Func, As, Bs), Anno, RBs);
+local_func(Func, As, Anno, Bs, {eval,F,Eas}, _Ef, RBs, _FUVs) ->
+ local_func2(apply(F, [Func,As,Bs|Eas]), Anno, RBs);
%% These two clauses are for backwards compatibility.
-local_func(Func, As0, Bs0, {M,F}, Ef, RBs) ->
- {As1,Bs1} = expr_list(As0, Bs0, {M,F}, Ef),
+local_func(Func, As0, _Anno, Bs0, {M,F}, Ef, RBs, FUVs) ->
+ {As1,Bs1} = expr_list(As0, Bs0, {M,F}, Ef, FUVs),
ret_expr(M:F(Func,As1), Bs1, RBs);
-local_func(Func, As, _Bs, {M,F,Eas}, _Ef, RBs) ->
- local_func2(apply(M, F, [Func,As|Eas]), RBs);
+local_func(Func, As, Anno, _Bs, {M,F,Eas}, _Ef, RBs, _FUVs) ->
+ local_func2(apply(M, F, [Func,As|Eas]), Anno, RBs);
%% Default unknown function handler to undefined function.
-local_func(Func, As0, _Bs0, none, _Ef, _RBs) ->
- erlang:raise(error, undef, [{?MODULE,Func,length(As0)}|?STACKTRACE]).
+local_func(Func, As0, Anno, Bs0, none, Ef, RBs, _FUVs) ->
+ apply_error(undef, [{?MODULE,Func,length(As0)}|?STACKTRACE], Anno, Bs0, Ef, RBs).
-local_func2({value,V,Bs}, RBs) ->
+local_func2({value,V,Bs}, _Anno, RBs) ->
ret_expr(V, Bs, RBs);
-local_func2({eval,F,As,Bs}, RBs) -> % This reply is not documented.
+local_func2({eval,F,As,Bs}, Anno, RBs) -> % This reply is not documented.
%% The shell found F. erl_eval tries to do a tail recursive call,
%% something the shell cannot do. Do not use Ef here.
- do_apply(F, As, Bs, none, RBs).
+ do_apply(F, As, Anno, Bs, none, RBs).
%% bif(Name, Arguments, RBs)
%% Evaluate the Erlang auto-imported function Name. erlang:apply/2,3
%% are "hidden" from the external function handler.
-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);
-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).
+bif(apply, [erlang,apply,As], Anno, Bs, Ef, RBs) ->
+ bif(apply, As, Anno, Bs, Ef, RBs);
+bif(apply, [M,F,As], Anno, Bs, Ef, RBs) ->
+ do_apply(M, F, As, Anno, Bs, Ef, RBs);
+bif(apply, [F,As], Anno, Bs, Ef, RBs) ->
+ do_apply(F, As, Anno, Bs, Ef, RBs);
+bif(Name, As, Anno, Bs, Ef, RBs) ->
+ do_apply(erlang, Name, As, Anno, Bs, Ef, RBs).
-%% do_apply(MF, Arguments, Bindings, ExternalFuncHandler, RBs) ->
+%% do_apply(Func, Arguments, Bindings, ExternalFuncHandler, RBs) ->
%% {value,Value,Bindings} | Value when
-%% ExternalFuncHandler = {value,F} | none.
-%% MF is a tuple {Module,Function} or a fun.
+%% ExternalFuncHandler = {value,F} | none,
+%% Func = fun()
-do_apply({M,F}=Func, As, Bs0, Ef, RBs)
- when tuple_size(M) >= 1, is_atom(element(1, M)), is_atom(F) ->
- case Ef of
- none when RBs =:= value ->
- %% Make tail recursive calls when possible.
- apply(M, F, As);
- none ->
- ret_expr(apply(M, F, As), Bs0, RBs);
- {value,Fun} when RBs =:= value ->
- Fun(Func, As);
- {value,Fun} ->
- ret_expr(Fun(Func, As), Bs0, RBs)
- end;
-do_apply(Func, As, Bs0, Ef, RBs) ->
+do_apply(Func, As, Anno, Bs0, Ef, RBs) ->
Env = if
- is_function(Func) ->
+ is_function(Func) ->
case {erlang:fun_info(Func, module),
erlang:fun_info(Func, env)} of
{{module,?MODULE},{env,Env1}} when Env1 =/= [] ->
@@ -635,12 +694,12 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
_ ->
no_env
end;
- true ->
+ true ->
no_env
end,
case {Env,Ef} of
- {{env,[{FBs,FLf,FEf,FCs}]},_} ->
- %% If we are evaluting within another function body
+ {{env,[{FAnno,FBs,FLf,FEf,FFUVs,FCs}]},_} ->
+ %% If we are evaluting within another function body
%% (RBs =/= none), we return RBs when this function body
%% has been evalutated, otherwise we return Bs0, the
%% bindings when evalution of this function body started.
@@ -650,20 +709,20 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
end,
case {erlang:fun_info(Func, arity), length(As)} of
{{arity, Arity}, Arity} ->
- eval_fun(FCs, As, FBs, FLf, FEf, NRBs);
+ eval_fun(FCs, As, FAnno, FBs, FLf, FEf, NRBs, FFUVs);
_ ->
- erlang:raise(error, {badarity,{Func,As}},?STACKTRACE)
+ apply_error({badarity,{Func,As}}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
end;
- {{env,[{FBs,FLf,FEf,FCs,FName}]},_} ->
+ {{env,[{FAnno,FBs,FLf,FEf,FFUVs,FCs,FName}]},_} ->
NRBs = if
RBs =:= none -> Bs0;
true -> RBs
end,
case {erlang:fun_info(Func, arity), length(As)} of
{{arity, Arity}, Arity} ->
- eval_named_fun(FCs, As, FBs, FLf, FEf, FName, Func, NRBs);
+ eval_named_fun(FCs, As, FAnno, FBs, FLf, FEf, FName, Func, NRBs, FFUVs);
_ ->
- erlang:raise(error, {badarity,{Func,As}},?STACKTRACE)
+ apply_error({badarity,{Func,As}}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
end;
{no_env,none} when RBs =:= value ->
%% Make tail recursive calls when possible.
@@ -671,12 +730,12 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
{no_env,none} ->
ret_expr(apply(Func, As), Bs0, RBs);
{no_env,{value,F}} when RBs =:= value ->
- F(Func,As);
+ do_apply(F, Anno, Func, As);
{no_env,{value,F}} ->
- ret_expr(F(Func, As), Bs0, RBs)
+ ret_expr(do_apply(F, Anno, Func, As), Bs0, RBs)
end.
-do_apply(Mod, Func, As, Bs0, Ef, RBs) ->
+do_apply(Mod, Func, As, Anno, Bs0, Ef, RBs) ->
case Ef of
none when RBs =:= value ->
%% Make tail recursive calls when possible.
@@ -684,86 +743,92 @@ do_apply(Mod, Func, As, Bs0, Ef, RBs) ->
none ->
ret_expr(apply(Mod, Func, As), Bs0, RBs);
{value,F} when RBs =:= value ->
- F({Mod,Func}, As);
+ do_apply(F, Anno, {Mod,Func}, As);
{value,F} ->
- ret_expr(F({Mod,Func}, As), Bs0, RBs)
+ ret_expr(do_apply(F, Anno, {Mod,Func}, As), Bs0, RBs)
end.
-%% eval_lc(Expr, [Qualifier], Bindings, LocalFunctionHandler,
+do_apply(F, Anno, FunOrModFun, Args) when is_function(F, 3) ->
+ F(Anno, FunOrModFun, Args);
+do_apply(F, _Anno, FunOrModFun, Args) when is_function(F, 2) ->
+ F(FunOrModFun, Args).
+
+%% eval_lc(Expr, [Qualifier], Bindings, LocalFunctionHandler,
%% ExternalFuncHandler, RetBindings) ->
%% {value,Value,Bindings} | Value
-eval_lc(E, Qs, Bs, Lf, Ef, RBs) ->
- ret_expr(lists:reverse(eval_lc1(E, Qs, Bs, Lf, Ef, [])), Bs, RBs).
-
-eval_lc1(E, [{generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->
- {value,L1,_Bs1} = expr(L0, Bs0, Lf, Ef, none),
- CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, Acc) end,
- eval_generate(L1, P, Bs0, Lf, Ef, CompFun, Acc0);
-eval_lc1(E, [{b_generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->
- {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none),
- CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, Acc) end,
- eval_b_generate(Bin, P, Bs0, Lf, Ef, CompFun, Acc0);
-eval_lc1(E, [F|Qs], Bs0, Lf, Ef, Acc) ->
- CompFun = fun(Bs) -> eval_lc1(E, Qs, Bs, Lf, Ef, Acc) end,
- eval_filter(F, Bs0, Lf, Ef, CompFun, Acc);
-eval_lc1(E, [], Bs, Lf, Ef, Acc) ->
- {value,V,_} = expr(E, Bs, Lf, Ef, none),
+eval_lc(E, Qs, Bs, Lf, Ef, RBs, FUVs) ->
+ ret_expr(lists:reverse(eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, [])), Bs, RBs).
+
+eval_lc1(E, [{generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+ {value,L1,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
+ CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
+ eval_generate(L1, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
+eval_lc1(E, [{b_generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+ {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
+ CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
+ eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
+eval_lc1(E, [F|Qs], Bs0, Lf, Ef, FUVs, Acc) ->
+ CompFun = fun(Bs) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
+ eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc);
+eval_lc1(E, [], Bs, Lf, Ef, FUVs, Acc) ->
+ {value,V,_} = expr(E, Bs, Lf, Ef, none, FUVs),
[V|Acc].
-%% eval_bc(Expr, [Qualifier], Bindings, LocalFunctionHandler,
+%% eval_bc(Expr, [Qualifier], Bindings, LocalFunctionHandler,
%% ExternalFuncHandler, RetBindings) ->
%% {value,Value,Bindings} | Value
-eval_bc(E, Qs, Bs, Lf, Ef, RBs) ->
- ret_expr(eval_bc1(E, Qs, Bs, Lf, Ef, <<>>), Bs, RBs).
-
-eval_bc1(E, [{b_generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->
- {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none),
- CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, Acc) end,
- eval_b_generate(Bin, P, Bs0, Lf, Ef, CompFun, Acc0);
-eval_bc1(E, [{generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->
- {value,List,_Bs1} = expr(L0, Bs0, Lf, Ef, none),
- CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, Acc) end,
- eval_generate(List, P, Bs0, Lf, Ef, CompFun, Acc0);
-eval_bc1(E, [F|Qs], Bs0, Lf, Ef, Acc) ->
- CompFun = fun(Bs) -> eval_bc1(E, Qs, Bs, Lf, Ef, Acc) end,
- eval_filter(F, Bs0, Lf, Ef, CompFun, Acc);
-eval_bc1(E, [], Bs, Lf, Ef, Acc) ->
- {value,V,_} = expr(E, Bs, Lf, Ef, none),
+eval_bc(E, Qs, Bs, Lf, Ef, RBs, FUVs) ->
+ ret_expr(eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, <<>>), Bs, RBs).
+
+eval_bc1(E, [{b_generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+ {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
+ CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
+ eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
+eval_bc1(E, [{generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+ {value,List,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
+ CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
+ eval_generate(List, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
+eval_bc1(E, [F|Qs], Bs0, Lf, Ef, FUVs, Acc) ->
+ CompFun = fun(Bs) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
+ eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc);
+eval_bc1(E, [], Bs, Lf, Ef, FUVs, Acc) ->
+ {value,V,_} = expr(E, Bs, Lf, Ef, none, FUVs),
<<Acc/bitstring,V/bitstring>>.
-eval_generate([V|Rest], P, Bs0, Lf, Ef, CompFun, Acc) ->
- case match(P, V, new_bindings(Bs0), Bs0) of
+eval_generate([V|Rest], P, Anno, Bs0, Lf, Ef, CompFun, Acc) ->
+ case match(P, V, Anno, new_bindings(Bs0), Bs0, Ef) of
{match,Bsn} ->
Bs2 = add_bindings(Bsn, Bs0),
NewAcc = CompFun(Bs2, Acc),
- eval_generate(Rest, P, Bs0, Lf, Ef, CompFun, NewAcc);
- nomatch ->
- eval_generate(Rest, P, Bs0, Lf, Ef, CompFun, Acc)
+ eval_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, NewAcc);
+ nomatch ->
+ eval_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, Acc)
end;
-eval_generate([], _P, _Bs0, _Lf, _Ef, _CompFun, Acc) ->
+eval_generate([], _P, _Anno, _Bs0, _Lf, _Ef, _CompFun, Acc) ->
Acc;
-eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
- erlang:raise(error, {bad_generator,Term}, ?STACKTRACE).
+eval_generate(Term, _P, Anno, Bs0, _Lf, Ef, _CompFun, _Acc) ->
+ apply_error({bad_generator,Term}, ?STACKTRACE, Anno, Bs0, Ef, none).
-eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->
- Mfun = match_fun(Bs0),
+eval_b_generate(<<_/bitstring>>=Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc) ->
+ Mfun = match_fun(Bs0, Ef),
Efun = fun(Exp, Bs) -> expr(Exp, Bs, Lf, Ef, none) end,
- case eval_bits:bin_gen(P, Bin, new_bindings(Bs0), Bs0, Mfun, Efun) of
+ ErrorFun = fun(A, R, S) -> apply_error(R, S, A, Bs0, Ef, none) end,
+ case eval_bits:bin_gen(P, Bin, new_bindings(Bs0), Bs0, Mfun, Efun, ErrorFun) of
{match, Rest, Bs1} ->
Bs2 = add_bindings(Bs1, Bs0),
NewAcc = CompFun(Bs2, Acc),
- eval_b_generate(Rest, P, Bs0, Lf, Ef, CompFun, NewAcc);
+ eval_b_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, NewAcc);
{nomatch, Rest} ->
- eval_b_generate(Rest, P, Bs0, Lf, Ef, CompFun, Acc);
+ eval_b_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, Acc);
done ->
Acc
end;
-eval_b_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
- erlang:raise(error, {bad_generator,Term}, ?STACKTRACE).
+eval_b_generate(Term, _P, Anno, Bs0, _Lf, Ef, _CompFun, _Acc) ->
+ apply_error({bad_generator,Term}, ?STACKTRACE, Anno, Bs0, Ef, none).
-eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->
+eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc) ->
case erl_lint:is_guard_test(F) of
true ->
case guard_test(F, Bs0, Lf, Ef) of
@@ -771,11 +836,11 @@ eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->
{value,false,_} -> Acc
end;
false ->
- case expr(F, Bs0, Lf, Ef, none) of
+ case expr(F, Bs0, Lf, Ef, none, FUVs) of
{value,true,Bs1} -> CompFun(Bs1);
{value,false,_} -> Acc;
- {value,V,_} ->
- erlang:raise(error, {bad_filter,V}, ?STACKTRACE)
+ {value,V,_} ->
+ apply_error({bad_filter,V}, ?STACKTRACE, element(2, F), Bs0, Ef, none)
end
end.
@@ -783,18 +848,18 @@ eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->
%% ExternalFuncHandler) ->
%% {[{map_assoc | map_exact,Key,Value}],Bindings}
-eval_map_fields(Fs, Bs, Lf, Ef) ->
- eval_map_fields(Fs, Bs, Lf, Ef, []).
-
-eval_map_fields([{map_field_assoc,_,K0,V0}|Fs], Bs0, Lf, Ef, Acc) ->
- {value,K1,Bs1} = expr(K0, Bs0, Lf, Ef, none),
- {value,V1,Bs2} = expr(V0, Bs1, Lf, Ef, none),
- eval_map_fields(Fs, Bs2, Lf, Ef, [{map_assoc,K1,V1}|Acc]);
-eval_map_fields([{map_field_exact,_,K0,V0}|Fs], Bs0, Lf, Ef, Acc) ->
- {value,K1,Bs1} = expr(K0, Bs0, Lf, Ef, none),
- {value,V1,Bs2} = expr(V0, Bs1, Lf, Ef, none),
- eval_map_fields(Fs, Bs2, Lf, Ef, [{map_exact,K1,V1}|Acc]);
-eval_map_fields([], Bs, _Lf, _Ef, Acc) ->
+eval_map_fields(Fs, Bs, Lf, Ef, FUVs) ->
+ eval_map_fields(Fs, Bs, Lf, Ef, FUVs, []).
+
+eval_map_fields([{map_field_assoc,_,K0,V0}|Fs], Bs0, Lf, Ef, FUVs, Acc) ->
+ {value,K1,Bs1} = expr(K0, Bs0, Lf, Ef, none, FUVs),
+ {value,V1,Bs2} = expr(V0, Bs1, Lf, Ef, none, FUVs),
+ eval_map_fields(Fs, Bs2, Lf, Ef, FUVs, [{map_assoc,K1,V1}|Acc]);
+eval_map_fields([{map_field_exact,_,K0,V0}|Fs], Bs0, Lf, Ef, FUVs, Acc) ->
+ {value,K1,Bs1} = expr(K0, Bs0, Lf, Ef, none, FUVs),
+ {value,V1,Bs2} = expr(V0, Bs1, Lf, Ef, none, FUVs),
+ eval_map_fields(Fs, Bs2, Lf, Ef, FUVs, [{map_exact,K1,V1}|Acc]);
+eval_map_fields([], Bs, _Lf, _Ef, _FUVs, Acc) ->
{lists:reverse(Acc),Bs}.
@@ -810,48 +875,48 @@ ret_expr(V, Bs, none) ->
ret_expr(V, _Bs, RBs) when is_list(RBs); is_map(RBs) ->
{value,V,RBs}.
-%% eval_fun(Arguments, {Bindings,LocalFunctionHandler,
-%% ExternalFunctionHandler,Clauses}) -> Value
+%% eval_fun(Arguments, {Anno,Bindings,LocalFunctionHandler,
+%% ExternalFunctionHandler,FunUsedVars,Clauses}) -> Value
%% This function is called when the fun is called from compiled code
%% or from apply.
-eval_fun(As, {Bs0,Lf,Ef,Cs}) ->
- eval_fun(Cs, As, Bs0, Lf, Ef, value).
+eval_fun(As, {Anno,Bs0,Lf,Ef,FUVs,Cs}) ->
+ eval_fun(Cs, As, Anno, Bs0, Lf, Ef, value, FUVs).
-eval_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, RBs) ->
- case match_list(H, As, new_bindings(Bs0), Bs0) of
+eval_fun([{clause,_,H,G,B}|Cs], As, Anno, Bs0, Lf, Ef, RBs, FUVs) ->
+ case match_list(H, As, Anno, new_bindings(Bs0), Bs0, Ef) of
{match,Bsn} -> % The new bindings for the head
Bs1 = add_bindings(Bsn, Bs0), % which then shadow!
case guard(G, Bs1, Lf, Ef) of
- true -> exprs(B, Bs1, Lf, Ef, RBs);
- false -> eval_fun(Cs, As, Bs0, Lf, Ef, RBs)
+ true -> exprs(B, Bs1, Lf, Ef, RBs, FUVs);
+ false -> eval_fun(Cs, As, Anno, Bs0, Lf, Ef, RBs, FUVs)
end;
nomatch ->
- eval_fun(Cs, As, Bs0, Lf, Ef, RBs)
+ eval_fun(Cs, As, Anno, Bs0, Lf, Ef, RBs, FUVs)
end;
-eval_fun([], As, _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, function_clause,
- [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE]).
+eval_fun([], As, Anno, Bs, _Lf, Ef, RBs, _FUVs) ->
+ Stack = [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE],
+ apply_error(function_clause, Stack, Anno, Bs, Ef, RBs).
-eval_named_fun(As, Fun, {Bs0,Lf,Ef,Cs,Name}) ->
- eval_named_fun(Cs, As, Bs0, Lf, Ef, Name, Fun, value).
+eval_named_fun(As, Fun, {Anno,Bs0,Lf,Ef,FUVs,Cs,Name}) ->
+ eval_named_fun(Cs, As, Anno, Bs0, Lf, Ef, Name, Fun, value, FUVs).
-eval_named_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, Name, Fun, RBs) ->
+eval_named_fun([{clause,_,H,G,B}|Cs], As, Anno, Bs0, Lf, Ef, Name, Fun, RBs, FUVs) ->
Bs1 = add_binding(Name, Fun, Bs0),
- case match_list(H, As, new_bindings(Bs0), Bs1) of
+ case match_list(H, As, Anno, new_bindings(Bs0), Bs1, Ef) of
{match,Bsn} -> % The new bindings for the head
Bs2 = add_bindings(Bsn, Bs1), % which then shadow!
case guard(G, Bs2, Lf, Ef) of
- true -> exprs(B, Bs2, Lf, Ef, RBs);
- false -> eval_named_fun(Cs, As, Bs0, Lf, Ef, Name, Fun, RBs)
+ true -> exprs(B, Bs2, Lf, Ef, RBs, FUVs);
+ false -> eval_named_fun(Cs, As, Anno, Bs0, Lf, Ef, Name, Fun, RBs, FUVs)
end;
nomatch ->
- eval_named_fun(Cs, As, Bs0, Lf, Ef, Name, Fun, RBs)
+ eval_named_fun(Cs, As, Anno, Bs0, Lf, Ef, Name, Fun, RBs, FUVs)
end;
-eval_named_fun([], As, _Bs, _Lf, _Ef, _Name, _Fun, _RBs) ->
- erlang:raise(error, function_clause,
- [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE]).
+eval_named_fun([], As, Anno, Bs, _Lf, Ef, _Name, _Fun, RBs, _FUVs) ->
+ Stack = [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE],
+ apply_error(function_clause, Stack, Anno, Bs, Ef, RBs).
%% expr_list(ExpressionList, Bindings)
@@ -865,7 +930,7 @@ eval_named_fun([], As, _Bs, _Lf, _Ef, _Name, _Fun, _RBs) ->
ValueList :: [value()],
NewBindings :: binding_struct()).
expr_list(Es, Bs) ->
- expr_list(Es, Bs, none, none).
+ expr_list(Es, Bs, none, none, empty_fun_used_vars()).
-spec(expr_list(ExpressionList, Bindings, LocalFunctionHandler) ->
{ValueList, NewBindings} when
@@ -875,7 +940,7 @@ expr_list(Es, Bs) ->
ValueList :: [value()],
NewBindings :: binding_struct()).
expr_list(Es, Bs, Lf) ->
- expr_list(Es, Bs, Lf, none).
+ expr_list(Es, Bs, Lf, none, empty_fun_used_vars()).
-spec(expr_list(ExpressionList, Bindings, LocalFunctionHandler,
NonLocalFunctionHandler) ->
@@ -887,44 +952,47 @@ expr_list(Es, Bs, Lf) ->
ValueList :: [value()],
NewBindings :: binding_struct()).
expr_list(Es, Bs, Lf, Ef) ->
- expr_list(Es, [], Bs, Bs, Lf, Ef).
+ expr_list(Es, Bs, Lf, Ef, empty_fun_used_vars()).
-expr_list([E|Es], Vs, BsOrig, Bs0, Lf, Ef) ->
- {value,V,Bs1} = expr(E, BsOrig, Lf, Ef, none),
- expr_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0), Lf, Ef);
-expr_list([], Vs, _, Bs, _Lf, _Ef) ->
+expr_list(Es, Bs, Lf, Ef, FUVs) ->
+ expr_list(Es, [], Bs, Bs, Lf, Ef, FUVs).
+
+expr_list([E|Es], Vs, BsOrig, Bs0, Lf, Ef, FUVs) ->
+ {value,V,Bs1} = expr(E, BsOrig, Lf, Ef, none, FUVs),
+ expr_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0, element(2, E), Ef), Lf, Ef, FUVs);
+expr_list([], Vs, _, Bs, _Lf, _Ef, _FUVs) ->
{reverse(Vs),Bs}.
-eval_op(Op, Arg1, Arg2, Bs, Ef, RBs) ->
- do_apply(erlang, Op, [Arg1,Arg2], Bs, Ef, RBs).
+eval_op(Op, Arg1, Arg2, Anno, Bs, Ef, RBs) ->
+ do_apply(erlang, Op, [Arg1,Arg2], Anno, Bs, Ef, RBs).
-eval_op(Op, Arg, Bs, Ef, RBs) ->
- do_apply(erlang, Op, [Arg], Bs, Ef, RBs).
+eval_op(Op, Arg, Anno, Bs, Ef, RBs) ->
+ do_apply(erlang, Op, [Arg], Anno, Bs, Ef, RBs).
-%% if_clauses(Clauses, Bindings, LocalFuncHandler, ExtFuncHandler, RBs)
+%% if_clauses(Clauses, Anno, Bindings, LocalFuncHandler, ExtFuncHandler, RBs)
-if_clauses([{clause,_,[],G,B}|Cs], Bs, Lf, Ef, RBs) ->
+if_clauses([{clause,_,[],G,B}|Cs], Anno, Bs, Lf, Ef, RBs, FUVs) ->
case guard(G, Bs, Lf, Ef) of
- true -> exprs(B, Bs, Lf, Ef, RBs);
- false -> if_clauses(Cs, Bs, Lf, Ef, RBs)
+ true -> exprs(B, Bs, Lf, Ef, RBs, FUVs);
+ false -> if_clauses(Cs, Anno, Bs, Lf, Ef, RBs, FUVs)
end;
-if_clauses([], _Bs, _Lf, _Ef, _RBs) ->
- erlang:raise(error, if_clause, ?STACKTRACE).
+if_clauses([], Anno, Bs, _Lf, Ef, RBs, _FUVs) ->
+ apply_error(if_clause, ?STACKTRACE, Anno, Bs, Ef, RBs).
-%% try_clauses(Body, CaseClauses, CatchClauses, AfterBody, Bindings,
+%% try_clauses(Body, CaseClauses, CatchClauses, AfterBody, Anno, Bindings,
%% LocalFuncHandler, ExtFuncHandler, RBs)
-try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs) ->
- check_stacktrace_vars(Catches, Bs),
- try exprs(B, Bs, Lf, Ef, none) of
+try_clauses(B, Cases, Catches, AB, Anno, Bs, Lf, Ef, RBs, FUVs) ->
+ check_stacktrace_vars(Catches, Anno, Bs, Ef, RBs),
+ try exprs(B, Bs, Lf, Ef, none, FUVs) of
{value,V,Bs1} when Cases =:= [] ->
ret_expr(V, Bs1, RBs);
{value,V,Bs1} ->
case match_clause(Cases, [V], Bs1, Lf, Ef) of
{B2,Bs2} ->
- exprs(B2, Bs2, Lf, Ef, RBs);
+ exprs(B2, Bs2, Lf, Ef, RBs, FUVs);
nomatch ->
- erlang:raise(error, {try_clause,V}, ?STACKTRACE)
+ apply_error({try_clause, V}, ?STACKTRACE, Anno, Bs, Ef, RBs)
end
catch
Class:Reason:Stacktrace when Catches =:= [] ->
@@ -933,63 +1001,63 @@ try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs) ->
V = {Class,Reason,Stacktrace},
case match_clause(Catches, [V], Bs, Lf, Ef) of
{B2,Bs2} ->
- exprs(B2, Bs2, Lf, Ef, RBs);
+ exprs(B2, Bs2, Lf, Ef, RBs, FUVs);
nomatch ->
erlang:raise(Class, Reason, Stacktrace)
end
after
- if AB =:= [] ->
+ if AB =:= [] ->
Bs; % any
true ->
- exprs(AB, Bs, Lf, Ef, none)
+ exprs(AB, Bs, Lf, Ef, none, FUVs)
end
end.
-check_stacktrace_vars([{clause,_,[{tuple,_,[_,_,STV]}],_,_}|Cs], Bs) ->
+
+check_stacktrace_vars([{clause,_,[{tuple,_,[_,_,STV]}],_,_}|Cs], Anno, Bs, Ef, RBs) ->
case STV of
{var,_,V} ->
case binding(V, Bs) of
{value, _} ->
- erlang:raise(error, stacktrace_bound, ?STACKTRACE);
+ apply_error(stacktrace_bound, ?STACKTRACE, Anno, Bs, Ef, RBs);
unbound ->
- check_stacktrace_vars(Cs, Bs)
+ check_stacktrace_vars(Cs, Anno, Bs, Ef, RBs)
end;
_ ->
- erlang:raise(error,
- {illegal_stacktrace_variable,STV},
- ?STACKTRACE)
+ Reason = {illegal_stacktrace_variable,STV},
+ apply_error(Reason, ?STACKTRACE, Anno, Bs, Ef, RBs)
end;
-check_stacktrace_vars([], _Bs) ->
+check_stacktrace_vars([], _Anno, _Bs, _Ef, _RBs) ->
ok.
-%% case_clauses(Value, Clauses, Bindings, LocalFuncHandler, ExtFuncHandler,
-%% RBs)
+%% case_clauses(Value, Clauses, Anno, Bindings, LocalFuncHandler,
+%% ExtFuncHandler, RBs)
-case_clauses(Val, Cs, Bs, Lf, Ef, RBs) ->
+case_clauses(Val, Cs, Anno, Bs, Lf, Ef, RBs, FUVs) ->
case match_clause(Cs, [Val], Bs, Lf, Ef) of
{B, Bs1} ->
- exprs(B, Bs1, Lf, Ef, RBs);
+ exprs(B, Bs1, Lf, Ef, RBs, FUVs);
nomatch ->
- erlang:raise(error, {case_clause,Val}, ?STACKTRACE)
+ apply_error({case_clause,Val}, ?STACKTRACE, Anno, Bs, Ef, RBs)
end.
%%
-%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, RBs)
+%% receive_clauses(Clauses, Bindings, LocalFuncHnd, ExtFuncHnd, RBs)
%%
-receive_clauses(Cs, Bs, Lf, Ef, RBs) ->
- receive_clauses(infinity, Cs, unused, Bs, Lf, Ef, RBs).
+receive_clauses(Cs, Bs, Lf, Ef, RBs, FUVs) ->
+ receive_clauses(infinity, Cs, unused, Bs, Lf, Ef, RBs, FUVs).
%%
-%% receive_clauses(TimeOut, Clauses, TimeoutBody, Bindings,
+%% receive_clauses(TimeOut, Clauses, TimeoutBody, Bindings,
%% ExternalFuncHandler, LocalFuncHandler, RBs)
%%
-receive_clauses(T, Cs, TB, Bs, Lf, Ef, RBs) ->
+receive_clauses(T, Cs, TB, Bs, Lf, Ef, RBs, FUVs) ->
F = fun (M) -> match_clause(Cs, [M], Bs, Lf, Ef) end,
case prim_eval:'receive'(F, T) of
{B, Bs1} ->
- exprs(B, Bs1, Lf, Ef, RBs);
+ exprs(B, Bs1, Lf, Ef, RBs, FUVs);
timeout ->
{B, Bs1} = TB,
- exprs(B, Bs1, Lf, Ef, RBs)
+ exprs(B, Bs1, Lf, Ef, RBs, FUVs)
end.
%% match_clause -> {Body, Bindings} or nomatch
@@ -1006,8 +1074,8 @@ receive_clauses(T, Cs, TB, Bs, Lf, Ef, RBs) ->
match_clause(Cs, Vs, Bs, Lf) ->
match_clause(Cs, Vs, Bs, Lf, none).
-match_clause([{clause,_,H,G,B}|Cs], Vals, Bs, Lf, Ef) ->
- case match_list(H, Vals, Bs) of
+match_clause([{clause,Anno,H,G,B}|Cs], Vals, Bs, Lf, Ef) ->
+ case match_list(H, Vals, Anno, Bs, Bs, Ef) of
{match, Bs1} ->
case guard(G, Bs1, Lf, Ef) of
true -> {B, Bs1};
@@ -1045,7 +1113,7 @@ guard0([G|Gs], Bs0, Lf, Ef) ->
{value,false,_} -> false
end;
false ->
- erlang:raise(error, guard_expr, ?STACKTRACE)
+ apply_error(guard_expr, ?STACKTRACE, element(2, G), Bs0, Ef, none)
end;
guard0([], _Bs, _Lf, _Ef) -> true.
@@ -1068,7 +1136,7 @@ guard_test(G, Bs0, Lf, Ef) ->
expr_guard_test(G, Bs0, Lf, Ef) ->
try {value,true,_} = expr(G, Bs0, Lf, Ef, none)
catch error:_ -> {value,false,Bs0} end.
-
+
type_test(integer) -> is_integer;
type_test(float) -> is_float;
type_test(number) -> is_number;
@@ -1084,23 +1152,19 @@ type_test(record) -> is_record;
type_test(map) -> is_map;
type_test(Test) -> Test.
-
-%% match(Pattern, Term, Bindings) ->
-%% {match,NewBindings} | nomatch
+%% match(Pattern, Term, Anno, NewBindings, Bindings, ExternalFunHnd) ->
+%% {match,NewBindings} | nomatch
%% or erlang:error({illegal_pattern, Pattern}).
-%% Try to match Pattern against Term with the current bindings.
-
-match(Pat, Term, Bs) ->
- match(Pat, Term, Bs, Bs).
-
+%%
+%% Try to match Pattern against Term with the current bindings.
%% Bs are the bindings that are augmented with new bindings. BBs are
%% the bindings used for "binsize" variables (in <<X:Y>>, Y is a
%% binsize variable).
-match(Pat, Term, Bs, BBs) ->
- case catch match1(Pat, Term, Bs, BBs) of
+match(Pat, Term, Anno, Bs, BBs, Ef) ->
+ case catch match1(Pat, Term, Bs, BBs, Ef) of
invalid ->
- erlang:raise(error, {illegal_pattern,to_term(Pat)}, ?STACKTRACE);
+ apply_error({illegal_pattern,to_term(Pat)}, ?STACKTRACE, Anno, Bs, Ef, none);
Other ->
Other
end.
@@ -1109,29 +1173,29 @@ string_to_conses([], _, Tail) -> Tail;
string_to_conses([E|Rest], Anno, Tail) ->
{cons, Anno, {integer, Anno, E}, string_to_conses(Rest, Anno, Tail)}.
-match1({atom,_,A0}, A, Bs, _BBs) ->
+match1({atom,_,A0}, A, Bs, _BBs, _Ef) ->
case A of
A0 -> {match,Bs};
_ -> throw(nomatch)
end;
-match1({integer,_,I0}, I, Bs, _BBs) ->
+match1({integer,_,I0}, I, Bs, _BBs, _Ef) ->
case I of
I0 -> {match,Bs};
_ -> throw(nomatch)
end;
-match1({float,_,F0}, F, Bs, _BBs) ->
+match1({float,_,F0}, F, Bs, _BBs, _Ef) ->
case F of
F0 -> {match,Bs};
_ -> throw(nomatch)
end;
-match1({char,_,C0}, C, Bs, _BBs) ->
+match1({char,_,C0}, C, Bs, _BBs, _Ef) ->
case C of
C0 -> {match,Bs};
_ -> throw(nomatch)
end;
-match1({var,_,'_'}, _, Bs, _BBs) -> %Anonymous variable matches
+match1({var,_,'_'}, _, Bs, _BBs, _Ef) -> %Anonymous variable matches
{match,Bs}; % everything, no new bindings
-match1({var,_,Name}, Term, Bs, _BBs) ->
+match1({var,_,Name}, Term, Bs, _BBs, _Ef) ->
case binding(Name, Bs) of
{value,Term} ->
{match,Bs};
@@ -1140,34 +1204,34 @@ match1({var,_,Name}, Term, Bs, _BBs) ->
unbound ->
{match,add_binding(Name, Term, Bs)}
end;
-match1({match,_,Pat1,Pat2}, Term, Bs0, BBs) ->
- {match, Bs1} = match1(Pat1, Term, Bs0, BBs),
- match1(Pat2, Term, Bs1, BBs);
-match1({string,_,S0}, S, Bs, _BBs) ->
+match1({match,_,Pat1,Pat2}, Term, Bs0, BBs, Ef) ->
+ {match, Bs1} = match1(Pat1, Term, Bs0, BBs, Ef),
+ match1(Pat2, Term, Bs1, BBs, Ef);
+match1({string,_,S0}, S, Bs, _BBs, _Ef) ->
case S of
S0 -> {match,Bs};
_ -> throw(nomatch)
end;
-match1({nil,_}, Nil, Bs, _BBs) ->
+match1({nil,_}, Nil, Bs, _BBs, _Ef) ->
case Nil of
[] -> {match,Bs};
_ -> throw(nomatch)
end;
-match1({cons,_,H,T}, [H1|T1], Bs0, BBs) ->
- {match,Bs} = match1(H, H1, Bs0, BBs),
- match1(T, T1, Bs, BBs);
-match1({cons,_,_,_}, _, _Bs, _BBs) ->
+match1({cons,_,H,T}, [H1|T1], Bs0, BBs, Ef) ->
+ {match,Bs} = match1(H, H1, Bs0, BBs, Ef),
+ match1(T, T1, Bs, BBs, Ef);
+match1({cons,_,_,_}, _, _Bs, _BBs, _Ef) ->
throw(nomatch);
-match1({tuple,_,Elts}, Tuple, Bs, BBs)
+match1({tuple,_,Elts}, Tuple, Bs, BBs, Ef)
when length(Elts) =:= tuple_size(Tuple) ->
- match_tuple(Elts, Tuple, 1, Bs, BBs);
-match1({tuple,_,_}, _, _Bs, _BBs) ->
+ match_tuple(Elts, Tuple, 1, Bs, BBs, Ef);
+match1({tuple,_,_}, _, _Bs, _BBs, _Ef) ->
throw(nomatch);
-match1({map,_,Fs}, #{}=Map, Bs, BBs) ->
- match_map(Fs, Map, Bs, BBs);
-match1({map,_,_}, _, _Bs, _BBs) ->
+match1({map,_,Fs}, #{}=Map, Bs, BBs, Ef) ->
+ match_map(Fs, Map, Bs, BBs, Ef);
+match1({map,_,_}, _, _Bs, _BBs, _Ef) ->
throw(nomatch);
-match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) ->
+match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs, Ef) ->
EvalFun = fun(E, Bs) ->
case erl_lint:is_guard_expr(E) of
true -> ok;
@@ -1180,74 +1244,72 @@ match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) ->
throw(invalid)
end
end,
- eval_bits:match_bits(Fs, B, Bs0, BBs, match_fun(BBs), EvalFun);
-match1({bin,_,_}, _, _Bs, _BBs) ->
+ ErrorFun = fun(A, R, S) -> apply_error(R, S, A, Bs0, Ef, none) end,
+ eval_bits:match_bits(Fs, B, Bs0, BBs, match_fun(BBs, Ef), EvalFun, ErrorFun);
+match1({bin,_,_}, _, _Bs, _BBs, _Ef) ->
throw(nomatch);
-match1({op,_,'++',{nil,_},R}, Term, Bs, BBs) ->
- match1(R, Term, Bs, BBs);
-match1({op,_,'++',{cons,Ai,{integer,A2,I},T},R}, Term, Bs, BBs) ->
- match1({cons,Ai,{integer,A2,I},{op,Ai,'++',T,R}}, Term, Bs, BBs);
-match1({op,_,'++',{cons,Ai,{char,A2,C},T},R}, Term, Bs, BBs) ->
- match1({cons,Ai,{char,A2,C},{op,Ai,'++',T,R}}, Term, Bs, BBs);
-match1({op,_,'++',{string,Ai,L},R}, Term, Bs, BBs) ->
- match1(string_to_conses(L, Ai, R), Term, Bs, BBs);
-match1({op,Anno,Op,A}, Term, Bs, BBs) ->
+match1({op,_,'++',{nil,_},R}, Term, Bs, BBs, Ef) ->
+ match1(R, Term, Bs, BBs, Ef);
+match1({op,_,'++',{cons,Ai,{integer,A2,I},T},R}, Term, Bs, BBs, Ef) ->
+ match1({cons,Ai,{integer,A2,I},{op,Ai,'++',T,R}}, Term, Bs, BBs, Ef);
+match1({op,_,'++',{cons,Ai,{char,A2,C},T},R}, Term, Bs, BBs, Ef) ->
+ match1({cons,Ai,{char,A2,C},{op,Ai,'++',T,R}}, Term, Bs, BBs, Ef);
+match1({op,_,'++',{string,Ai,L},R}, Term, Bs, BBs, Ef) ->
+ match1(string_to_conses(L, Ai, R), Term, Bs, BBs, Ef);
+match1({op,Anno,Op,A}, Term, Bs, BBs, Ef) ->
case partial_eval({op,Anno,Op,A}) of
{op,Anno,Op,A} ->
throw(invalid);
X ->
- match1(X, Term, Bs, BBs)
+ match1(X, Term, Bs, BBs, Ef)
end;
-match1({op,Anno,Op,L,R}, Term, Bs, BBs) ->
+match1({op,Anno,Op,L,R}, Term, Bs, BBs, Ef) ->
case partial_eval({op,Anno,Op,L,R}) of
{op,Anno,Op,L,R} ->
throw(invalid);
X ->
- match1(X, Term, Bs, BBs)
+ match1(X, Term, Bs, BBs, Ef)
end;
-match1(_, _, _Bs, _BBs) ->
+match1(_, _, _Bs, _BBs, _Ef) ->
throw(invalid).
-match_fun(BBs) ->
- fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs);
+match_fun(BBs, Ef) ->
+ fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs, Ef);
(binding, {Name,Bs}) -> binding(Name, Bs);
(add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs)
end.
-match_tuple([E|Es], Tuple, I, Bs0, BBs) ->
- {match,Bs} = match1(E, element(I, Tuple), Bs0, BBs),
- match_tuple(Es, Tuple, I+1, Bs, BBs);
-match_tuple([], _, _, Bs, _BBs) ->
+match_tuple([E|Es], Tuple, I, Bs0, BBs, Ef) ->
+ {match,Bs} = match1(E, element(I, Tuple), Bs0, BBs, Ef),
+ match_tuple(Es, Tuple, I+1, Bs, BBs, Ef);
+match_tuple([], _, _, Bs, _BBs, _Ef) ->
{match,Bs}.
-match_map([{map_field_exact, _, K, V}|Fs], Map, Bs0, BBs) ->
+match_map([{map_field_exact, _, K, V}|Fs], Map, Bs0, BBs, Ef) ->
Vm = try
{value, Ke, _} = expr(K, BBs),
maps:get(Ke,Map)
catch error:_ ->
throw(nomatch)
end,
- {match, Bs} = match1(V, Vm, Bs0, BBs),
- match_map(Fs, Map, Bs, BBs);
-match_map([], _, Bs, _) ->
+ {match, Bs} = match1(V, Vm, Bs0, BBs, Ef),
+ match_map(Fs, Map, Bs, BBs, Ef);
+match_map([], _, Bs, _, _) ->
{match, Bs}.
-%% match_list(PatternList, TermList, Bindings) ->
+%% match_list(PatternList, TermList, Anno, NewBindings, Bindings, ExternalFunHnd) ->
%% {match,NewBindings} | nomatch
%% Try to match a list of patterns against a list of terms with the
%% current bindings.
-match_list(Ps, Ts, Bs) ->
- match_list(Ps, Ts, Bs, Bs).
-
-match_list([P|Ps], [T|Ts], Bs0, BBs) ->
- case match(P, T, Bs0, BBs) of
- {match,Bs1} -> match_list(Ps, Ts, Bs1, BBs);
+match_list([P|Ps], [T|Ts], Anno, Bs0, BBs, Ef) ->
+ case match(P, T, Anno, Bs0, BBs, Ef) of
+ {match,Bs1} -> match_list(Ps, Ts, Anno, Bs1, BBs, Ef);
nomatch -> nomatch
end;
-match_list([], [], Bs, _BBs) ->
+match_list([], [], _Anno, Bs, _BBs, _Ef) ->
{match,Bs};
-match_list(_, _, _Bs, _BBs) ->
+match_list(_, _, _Anno, _Bs, _BBs, _Ef) ->
nomatch.
%% new_bindings()
@@ -1296,17 +1358,17 @@ add_bindings(Bs1, Bs2) ->
foldl(fun ({Name,Val}, Bs) -> orddict:store(Name, Val, Bs) end,
Bs2, orddict:to_list(Bs1)).
-merge_bindings(Bs1, Bs2) when is_map(Bs1), is_map(Bs2) ->
+merge_bindings(Bs1, Bs2, Anno, Ef) when is_map(Bs1), is_map(Bs2) ->
maps:merge_with(fun
(_K, V, V) -> V;
- (_K, _, V) -> erlang:raise(error, {badmatch,V}, ?STACKTRACE)
+ (_K, _, V) -> apply_error({badmatch,V}, ?STACKTRACE, Anno, Bs1, Ef, none)
end, Bs2, Bs1);
-merge_bindings(Bs1, Bs2) ->
+merge_bindings(Bs1, Bs2, Anno, Ef) ->
foldl(fun ({Name,Val}, Bs) ->
case orddict:find(Name, Bs) of
{ok,Val} -> Bs; %Already with SAME value
- {ok,V1} ->
- erlang:raise(error, {badmatch,V1}, ?STACKTRACE);
+ {ok,V1} ->
+ apply_error({badmatch,V1}, ?STACKTRACE, Anno, Bs1, Ef, none);
error -> orddict:store(Name, Val, Bs)
end end,
Bs2, orddict:to_list(Bs1)).
@@ -1323,28 +1385,6 @@ to_terms(Abstrs) ->
to_term(Abstr) ->
erl_parse:anno_to_term(Abstr).
-%% Substitute {value, A, Item} for {var, A, Var}, preserving A.
-%% {value, A, Item} is a shell/erl_eval convention, and for example
-%% the linter cannot handle it.
-
--spec subst_values_for_vars(ExprList, Bindings) -> [term()] when
- ExprList :: [erl_parse:abstract_expr()],
- Bindings :: binding_struct().
-
-subst_values_for_vars({var, A, V}=Var, Bs) ->
- case erl_eval:binding(V, Bs) of
- {value, Value} ->
- {value, A, Value};
- unbound ->
- Var
- end;
-subst_values_for_vars(L, Bs) when is_list(L) ->
- [subst_values_for_vars(E, Bs) || E <- L];
-subst_values_for_vars(T, Bs) when is_tuple(T) ->
- list_to_tuple(subst_values_for_vars(tuple_to_list(T), Bs));
-subst_values_for_vars(T, _Bs) ->
- T.
-
%% `Tokens' is assumed to have been scanned with the 'text' option.
%% The annotations of the returned expressions are locations.
%%
@@ -1353,18 +1393,17 @@ subst_values_for_vars(T, _Bs) ->
%% the items themselves are stored in the returned bindings.
-spec extended_parse_exprs(Tokens) ->
- {'ok', ExprList, Bindings} | {'error', ErrorInfo} when
+ {'ok', ExprList} | {'error', ErrorInfo} when
Tokens :: [erl_scan:token()],
ExprList :: [erl_parse:abstract_expr()],
- Bindings :: erl_eval:binding_struct(),
ErrorInfo :: erl_parse:error_info().
extended_parse_exprs(Tokens) ->
Ts = tokens_fixup(Tokens),
case erl_parse:parse_exprs(Ts) of
{ok, Exprs0} ->
- {Exprs, Bs} = expr_fixup(Exprs0),
- {ok, reset_expr_anno(Exprs), Bs};
+ Exprs = expr_fixup(Exprs0),
+ {ok, reset_expr_anno(Exprs)};
_ErrorInfo ->
erl_parse:parse_exprs(reset_token_anno(Ts))
end.
@@ -1382,7 +1421,7 @@ tokens_fixup([T|Ts]=Ts0) ->
token_fixup(Ts) ->
{AnnoL, NewTs, FixupTag} = unscannable(Ts),
String = lists:append([erl_anno:text(A) || A <- AnnoL]),
- _ = (fixup_fun(FixupTag))(String),
+ _ = validate_tag(FixupTag, String),
NewAnno = erl_anno:set_text(fixup_text(FixupTag), hd(AnnoL)),
{{string, NewAnno, String}, NewTs}.
@@ -1403,37 +1442,26 @@ unscannable([{'#', A1}, {var, A2, 'Ref'}, {'<', A3}, {float, A4, _},
{'.', A5}, {float, A6, _}, {'>', A7}|Ts]) ->
{[A1, A2, A3, A4, A5, A6, A7], Ts, reference}.
-expr_fixup(Expr0) ->
- {Expr, Bs, _} = expr_fixup(Expr0, erl_eval:new_bindings(), 1),
- {Expr, Bs}.
-
-expr_fixup({string,A,S}=T, Bs0, I) ->
- try string_fixup(A, S) of
- Value ->
- Var = new_var(I),
- Bs = erl_eval:add_binding(Var, Value, Bs0),
- {{var, A, Var}, Bs, I+1}
+expr_fixup({string,A,S}=T) ->
+ try string_fixup(A, S, T) of
+ Expr -> Expr
catch
- _:_ ->
- {T, Bs0, I}
+ _:_ -> T
end;
-expr_fixup(Tuple, Bs0, I0) when is_tuple(Tuple) ->
- {L, Bs, I} = expr_fixup(tuple_to_list(Tuple), Bs0, I0),
- {list_to_tuple(L), Bs, I};
-expr_fixup([E0|Es0], Bs0, I0) ->
- {E, Bs1, I1} = expr_fixup(E0, Bs0, I0),
- {Es, Bs, I} = expr_fixup(Es0, Bs1, I1),
- {[E|Es], Bs, I};
-expr_fixup(T, Bs, I) ->
- {T, Bs, I}.
-
-string_fixup(A, S) ->
- Text = erl_anno:text(A),
- FixupTag = fixup_tag(Text, S),
- (fixup_fun(FixupTag))(S).
-
-new_var(I) ->
- list_to_atom(lists:concat(['__ExtendedParseExprs_', I, '__'])).
+expr_fixup(Tuple) when is_tuple(Tuple) ->
+ L = expr_fixup(tuple_to_list(Tuple)),
+ list_to_tuple(L);
+expr_fixup([E0|Es0]) ->
+ E = expr_fixup(E0),
+ Es = expr_fixup(Es0),
+ [E|Es];
+expr_fixup(T) ->
+ T.
+
+string_fixup(Anno, String, Token) ->
+ Text = erl_anno:text(Anno),
+ FixupTag = fixup_tag(Text, String),
+ fixup_ast(FixupTag, Anno, String, Token).
reset_token_anno(Tokens) ->
[setelement(2, T, (reset_anno())(element(2, T))) || T <- Tokens].
@@ -1444,18 +1472,15 @@ reset_expr_anno(Exprs) ->
reset_anno() ->
fun(A) -> erl_anno:new(erl_anno:location(A)) end.
-fixup_fun(function) -> fun function/1;
-fixup_fun(pid) -> fun erlang:list_to_pid/1;
-fixup_fun(port) -> fun erlang:list_to_port/1;
-fixup_fun(reference) -> fun erlang:list_to_ref/1.
-
-function(S) ->
- %% External function.
- {ok, [_, _, _,
- {atom, _, Module}, _,
- {atom, _, Function}, _,
- {integer, _, Arity}|_], _} = erl_scan:string(S),
- erlang:make_fun(Module, Function, Arity).
+fixup_ast(pid, A, _S, T) ->
+ {call,A,{remote,A,{atom,A,erlang},{atom,A,list_to_pid}},[T]};
+fixup_ast(port, A, _S, T) ->
+ {call,A,{remote,A,{atom,A,erlang},{atom,A,list_to_port}},[T]};
+fixup_ast(reference, A, _S, T) ->
+ {call,A,{remote,A,{atom,A,erlang},{atom,A,list_to_ref}},[T]};
+fixup_ast(function, A, S, _T) ->
+ {Module, Function, Arity} = fixup_mfa(S),
+ {'fun',A,{function,{atom,A,Module},{atom,A,Function},{integer,A,Arity}}}.
fixup_text(function) -> "function";
fixup_text(pid) -> "pid";
@@ -1467,6 +1492,20 @@ fixup_tag("pid", "<"++_) -> pid;
fixup_tag("port", "#"++_) -> port;
fixup_tag("reference", "#"++_) -> reference.
+fixup_mfa(S) ->
+ {ok, [_, _, _,
+ {atom, _, Module}, _,
+ {atom, _, Function}, _,
+ {integer, _, Arity}|_], _} = erl_scan:string(S),
+ {Module, Function, Arity}.
+
+validate_tag(pid, String) -> erlang:list_to_pid(String);
+validate_tag(port, String) -> erlang:list_to_port(String);
+validate_tag(reference, String) -> erlang:list_to_ref(String);
+validate_tag(function, String) ->
+ {Module, Function, Arity} = fixup_mfa(String),
+ erlang:make_fun(Module, Function, Arity).
+
%%% End of extended_parse_exprs.
%% `Tokens' is assumed to have been scanned with the 'text' option.
@@ -1481,8 +1520,8 @@ fixup_tag("reference", "#"++_) -> reference.
extended_parse_term(Tokens) ->
case extended_parse_exprs(Tokens) of
- {ok, [Expr], Bindings} ->
- try normalise(Expr, Bindings) of
+ {ok, [Expr]} ->
+ try normalise(Expr) of
Term ->
{ok, Term}
catch
@@ -1490,7 +1529,7 @@ extended_parse_term(Tokens) ->
Loc = erl_anno:location(element(2, Expr)),
{error,{Loc,?MODULE,"bad term"}}
end;
- {ok, [_,Expr|_], _Bindings} ->
+ {ok, [_,Expr|_]} ->
Loc = erl_anno:location(element(2, Expr)),
{error,{Loc,?MODULE,"bad term"}};
{error, _} = Error ->
@@ -1498,46 +1537,47 @@ extended_parse_term(Tokens) ->
end.
%% From erl_parse.
-normalise({var, _, V}, Bs) ->
- {value, Value} = erl_eval:binding(V, Bs),
- Value;
-normalise({char,_,C}, _Bs) -> C;
-normalise({integer,_,I}, _Bs) -> I;
-normalise({float,_,F}, _Bs) -> F;
-normalise({atom,_,A}, _Bs) -> A;
-normalise({string,_,S}, _Bs) -> S;
-normalise({nil,_}, _Bs) -> [];
-normalise({bin,_,Fs}, Bs) ->
+normalise({char,_,C}) -> C;
+normalise({integer,_,I}) -> I;
+normalise({float,_,F}) -> F;
+normalise({atom,_,A}) -> A;
+normalise({string,_,S}) -> S;
+normalise({nil,_}) -> [];
+normalise({bin,_,Fs}) ->
{value, B, _} =
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
- {value, normalise(E, Bs), []}
- end, [], true),
+ {value, normalise(E), []}
+ end),
B;
-normalise({cons,_,Head,Tail}, Bs) ->
- [normalise(Head, Bs)|normalise(Tail, Bs)];
-normalise({tuple,_,Args}, Bs) ->
- list_to_tuple(normalise_list(Args, Bs));
-normalise({map,_,Pairs}, Bs) ->
+normalise({cons,_,Head,Tail}) ->
+ [normalise(Head)|normalise(Tail)];
+normalise({tuple,_,Args}) ->
+ list_to_tuple(normalise_list(Args));
+normalise({map,_,Pairs}) ->
maps:from_list(lists:map(fun
%% only allow '=>'
({map_field_assoc,_,K,V}) ->
- {normalise(K, Bs),normalise(V, Bs)}
+ {normalise(K),normalise(V)}
end, Pairs));
%% Special case for unary +/-.
-normalise({op,_,'+',{char,_,I}}, _Bs) -> I;
-normalise({op,_,'+',{integer,_,I}}, _Bs) -> I;
-normalise({op,_,'+',{float,_,F}}, _Bs) -> F;
-normalise({op,_,'-',{char,_,I}}, _Bs) -> -I; %Weird, but compatible!
-normalise({op,_,'-',{integer,_,I}}, _Bs) -> -I;
-normalise({op,_,'-',{float,_,F}}, _Bs) -> -F;
-normalise({'fun',_,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Bs) ->
+normalise({op,_,'+',{char,_,I}}) -> I;
+normalise({op,_,'+',{integer,_,I}}) -> I;
+normalise({op,_,'+',{float,_,F}}) -> F;
+normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible!
+normalise({op,_,'-',{integer,_,I}}) -> -I;
+normalise({op,_,'-',{float,_,F}}) -> -F;
+%% Special case for #...<>
+normalise({call,_,{remote,_,{atom,_,erlang},{atom,_,Fun}},[{string,_,S}]}) when
+ Fun =:= list_to_ref; Fun =:= list_to_port; Fun =:= list_to_pid ->
+ erlang:Fun(S);
+normalise({'fun',_,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}) ->
%% Since "#Fun<M.F.A>" is recognized, "fun M:F/A" should be too.
fun M:F/A.
-normalise_list([H|T], Bs) ->
- [normalise(H, Bs)|normalise_list(T, Bs)];
-normalise_list([], _Bs) ->
+normalise_list([H|T]) ->
+ [normalise(H)|normalise_list(T)];
+normalise_list([]) ->
[].
%%----------------------------------------------------------------------------
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 4c8ba0578b..7715f7d458 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
vcount=0, % Variable counter
calltype=#{}, % Call types
records=#{}, % Record definitions
+ raw_records=[],% Raw record forms
strict_ra=[], % strict record accesses
checked_ra=[], % successfully accessed records
dialyzer=false % Cached value of compile flag 'dialyzer'
@@ -70,7 +71,8 @@ init_calltype_imports([], Ctype) -> Ctype.
forms([{attribute,_,record,{Name,Defs}}=Attr | Fs], St0) ->
NDefs = normalise_fields(Defs),
- St = St0#exprec{records=maps:put(Name, NDefs, St0#exprec.records)},
+ St = St0#exprec{records=maps:put(Name, NDefs, St0#exprec.records),
+ raw_records=[Attr | St0#exprec.raw_records]},
{Fs1, St1} = forms(Fs, St),
{[Attr | Fs1], St1};
forms([{function,Anno,N,A,Cs0} | Fs0], St0) ->
@@ -406,6 +408,17 @@ expr({'try',Anno,Es0,Scs0,Ccs0,As0}, St0) ->
expr({'catch',Anno,E0}, St0) ->
{E,St1} = expr(E0, St0),
{{'catch',Anno,E},St1};
+expr({'maybe',MaybeAnno,Es0}, St0) ->
+ {Es,St1} = exprs(Es0, St0),
+ {{'maybe',MaybeAnno,Es},St1};
+expr({'maybe',MaybeAnno,Es0,{'else',ElseAnno,Cs0}}, St0) ->
+ {Es,St1} = exprs(Es0, St0),
+ {Cs,St2} = clauses(Cs0, St1),
+ {{'maybe',MaybeAnno,Es,{'else',ElseAnno,Cs}},St2};
+expr({maybe_match,Anno,P0,E0}, St0) ->
+ {E,St1} = expr(E0, St0),
+ {P,St2} = pattern(P0, St1),
+ {{maybe_match,Anno,P,E},St2};
expr({match,Anno,P0,E0}, St0) ->
{E,St1} = expr(E0, St0),
{P,St2} = pattern(P0, St1),
@@ -500,7 +513,7 @@ lc_tq(Anno, [{b_generate,AnnoG,P0,G0} | Qs0], St0) ->
{P1,St2} = pattern(P0, St1),
{Qs1,St3} = lc_tq(Anno, Qs0, St2),
{[{b_generate,AnnoG,P1,G1} | Qs1],St3};
-lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype}=St0) ->
+lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype,raw_records=Records}=St0) ->
%% Allow record/2 and expand out as guard test.
IsOverriden = fun(FA) ->
case Calltype of
@@ -509,7 +522,7 @@ lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype}=St0) ->
_ -> false
end
end,
- case erl_lint:is_guard_test(F0, [], IsOverriden) of
+ case erl_lint:is_guard_test(F0, Records, IsOverriden) of
true ->
{F1,St1} = guard_test(F0, St0),
{Qs1,St2} = lc_tq(Anno, Qs0, St1),
@@ -595,11 +608,11 @@ strict_get_record_field(Anno, R, {atom,_,F}=Index, Name, St0) ->
RAnno = mark_record(NAnno, St),
E = {'case',Anno,R,
[{clause,NAnno,[{tuple,RAnno,P}],[],[Var]},
- {clause,NAnno,[{var,NAnno,'_'}],[],
+ {clause,NAnno,[Var],[],
[{call,NAnno,{remote,NAnno,
{atom,NAnno,erlang},
{atom,NAnno,error}},
- [{tuple,NAnno,[{atom,NAnno,badrecord},{atom,NAnno,Name}]}]}]}]},
+ [{tuple,NAnno,[{atom,NAnno,badrecord},Var]}]}]}]},
expr(E, St);
true -> %In a guard.
Fs = record_fields(Name, Anno, St0),
@@ -714,7 +727,7 @@ record_match(R, Name, AnnoR, Fs, Us, St0) ->
[{clause,AnnoR,[{tuple,RAnno,[{atom,AnnoR,Name} | Ps]}],[],
[{tuple,RAnno,[{atom,AnnoR,Name} | News]}]},
{clause,NAnnoR,[{var,NAnnoR,'_'}],[],
- [call_error(NAnnoR, {tuple,NAnnoR,[{atom,NAnnoR,badrecord},{atom,NAnnoR,Name}]})]}
+ [call_error(NAnnoR, {tuple,NAnnoR,[{atom,NAnnoR,badrecord},R]})]}
]},
St1}.
@@ -752,7 +765,7 @@ record_setel(R, Name, Fs, Us0) ->
{atom,Anno,setelement}},[I,Acc,Val]} end,
R, Us)]},
{clause,NAnnoR,[{var,NAnnoR,'_'}],[],
- [call_error(NAnnoR, {tuple,NAnnoR,[{atom,NAnnoR,badrecord},{atom,NAnnoR,Name}]})]}]}.
+ [call_error(NAnnoR, {tuple,NAnnoR,[{atom,NAnnoR,badrecord},R]})]}]}.
%% Expand a call to record_info/2. We have checked that it is not
%% shadowed by an import.
diff --git a/lib/stdlib/src/erl_features.erl b/lib/stdlib/src/erl_features.erl
new file mode 100644
index 0000000000..625a9d7952
--- /dev/null
+++ b/lib/stdlib/src/erl_features.erl
@@ -0,0 +1,570 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(erl_features).
+
+-export([all/0,
+ configurable/0,
+ info/1,
+ short/1,
+ long/1,
+ enabled/0,
+ load_allowed/1,
+ keywords/0,
+ keywords/1,
+ keyword_fun/2,
+ keyword_fun/4,
+ used/1,
+ format_error/1,
+ format_error/2]).
+
+-type type() :: 'extension' | 'backwards_incompatible_change'.
+-type status() :: 'experimental'
+ | 'approved'
+ | 'permanent'
+ | 'rejected'.
+-type release() :: non_neg_integer().
+-type feature() :: atom().
+-type error() :: {?MODULE,
+ {'invalid_features', [atom()]}
+ | {'incorrect_features', [atom()]}
+ | {'not_configurable', [atom()]}}.
+
+-define(VALID_FEATURE(Feature),
+ (case is_valid(Feature) of
+ false ->
+ error(invalid_feature, [Feature],
+ [{error_info,
+ #{module => ?MODULE,
+ cause => #{1 => "unknown feature"}}}]);
+ true -> ok
+ end)).
+
+%% Specification about currently known features.
+feature_specs() ->
+ #{maybe_expr =>
+ #{short => "Value based error handling (EEP49)",
+ description =>
+ "Implementation of the maybe expression proposed in EEP49 -- "
+ "Value based error handling.",
+ status => experimental,
+ experimental => 25,
+ keywords => ['maybe', 'else'],
+ type => extension}}.
+
+%% Return all currently known features.
+-spec all() -> [feature()].
+all() ->
+ Map = case persistent_term:get({?MODULE, feature_specs}, none) of
+ none -> init_specs();
+ M -> M
+ end,
+ lists:sort(maps:keys(Map)).
+
+-spec configurable() -> [feature()].
+configurable() ->
+ [Ftr || Ftr <- all(),
+ lists:member(maps:get(status, info(Ftr)),
+ [experimental, approved])].
+
+is_valid(Ftr) ->
+ lists:member(Ftr, all()).
+
+is_configurable(Ftr) ->
+ lists:member(Ftr, configurable()).
+
+-spec short(feature()) -> iolist() | no_return().
+short(Feature) ->
+ #{short := Short,
+ status := Status} = Info = info(Feature),
+ #{Status := Release} = Info,
+ io_lib:format("~-40s ~-12s (~p)", [Short, Status, Release]).
+
+-spec long(feature()) -> iolist() | no_return().
+long(Feature) ->
+ #{short := Short,
+ description := Description,
+ status := Status,
+ keywords := Keywords,
+ type := Type} = Info = info(Feature),
+ StatusFmt = " ~-10s ~-12s (~p)\n",
+ History = [io_lib:format(StatusFmt, [T, S, R])
+ || {T, S, R} <- history(Status, Info)],
+ KeywordsStrs =
+ if Keywords == [] -> "";
+ true ->
+ io_lib:format(" ~-10s ~p\n", ["Keywords", Keywords])
+ end,
+ Lines = [{"~s - ~s\n", [Feature, Short]},
+ {" ~-10s ~s\n", ["Type", Type]},
+ {"~s", [History]},
+ {"~s", [KeywordsStrs]},
+ {"\n~s\n", [nqTeX(Description)]}],
+ [io_lib:format(FStr, Args) || {FStr, Args} <- Lines].
+
+history(Current, Info) ->
+ G = fun(Key, S) ->
+ case maps:find(Key, Info) of
+ error -> [];
+ {ok, R} -> [{S, Key, R}]
+ end
+ end,
+ F = fun(Key) -> G(Key, "") end,
+ History =
+ case Current of
+ experimental -> [];
+ rejected -> F(experimental);
+ approved -> F(experimental);
+ permanent -> F(approved) ++ F(experimental)
+ end,
+ G(Current, "Status") ++ History.
+
+%% Dead simple line breaking for better presentation.
+nqTeX(String) ->
+ Words = string:tokens(String, " "),
+ WithLens = lists:map(fun(W) -> {W, length(W)} end, Words),
+ adjust(WithLens).
+
+adjust(WLs) ->
+ adjust(0, WLs, []).
+
+adjust(_, [], Ws) ->
+ lists:reverse(tl(Ws));
+adjust(Col, [{W, L}| WLs], Ws) ->
+ case Col + L > 72 of
+ true ->
+ lists:reverse(["\n"| tl(Ws)])
+ ++ adjust(L+1, WLs, [" ", W]);
+ false ->
+ adjust(Col + L + 1, WLs, [" ", W| Ws])
+ end.
+
+
+-spec info(feature()) -> FeatureInfoMap | no_return()
+ when
+ Description :: string(),
+ FeatureInfoMap ::
+ #{description := Description,
+ short := Description,
+ type := type(),
+ keywords := [atom()],
+ status := status(),
+ experimental => release(),
+ approved => release(),
+ permanent => release(),
+ rejected => release()
+ }.
+info(Feature) ->
+ ?VALID_FEATURE(Feature),
+
+ Map = persistent_term:get({?MODULE, feature_specs}),
+ maps:get(Feature, Map).
+
+%% New keywords introduced by a feature.
+-spec keywords(feature()) -> [atom()] | no_return().
+keywords(Ftr) ->
+ ?VALID_FEATURE(Ftr),
+
+ #{keywords := Keywords} = info(Ftr),
+ Keywords.
+
+%% Internal - Ftr is valid
+keywords(Ftr, Map) ->
+ maps:get(keywords, maps:get(Ftr, Map)).
+
+%% Utilities
+%% Returns list of enabled features and a new keywords function
+-spec keyword_fun([term()], fun((atom()) -> boolean())) ->
+ {'ok', {[feature()], fun((atom()) -> boolean())}}
+ | {'error', error()}.
+keyword_fun(Opts, KeywordFun) ->
+ %% Get items enabling or disabling features, preserving order.
+ IsFtr = fun({feature, _, enable}) -> true;
+ ({feature, _, disable}) -> true;
+ (_) -> false
+ end,
+ FeatureOps = lists:filter(IsFtr, Opts),
+ {AddFeatures, DelFeatures, RawFtrs} = collect_features(FeatureOps),
+
+ case configurable_features(RawFtrs) of
+ ok ->
+ {ok, Fun} = add_features_fun(AddFeatures, KeywordFun),
+ {ok, FunX} = remove_features_fun(DelFeatures, Fun),
+ {ok, {AddFeatures -- DelFeatures, FunX}};
+ {error, _} = Error ->
+ Error
+ end.
+
+-spec keyword_fun('enable' | 'disable', feature(), [feature()],
+ fun((atom()) -> boolean())) ->
+ {'ok', {[feature()], fun((atom()) -> boolean())}}
+ | {'error', error()}.
+keyword_fun(Ind, Feature, Ftrs, KeywordFun) ->
+ case is_configurable(Feature) of
+ true ->
+ case Ind of
+ enable ->
+ NewFtrs = case lists:member(Feature, Ftrs) of
+ true -> Ftrs;
+ false -> [Feature | Ftrs]
+ end,
+ {ok, {NewFtrs,
+ add_feature_fun(Feature, KeywordFun)}};
+ disable ->
+ {ok, {Ftrs -- [Feature],
+ remove_feature_fun(Feature, KeywordFun)}}
+ end;
+ false ->
+ Error =
+ case is_valid(Feature) of
+ true -> not_configurable;
+ false -> invalid_features
+ end,
+ {error, {?MODULE, {Error, [Feature]}}}
+ end.
+
+add_feature_fun(Feature, F) ->
+ Words = keywords(Feature),
+ fun(Word) ->
+ lists:member(Word, Words)
+ orelse F(Word)
+ end.
+
+remove_feature_fun(Feature, F) ->
+ Words = keywords(Feature),
+ fun(Word) ->
+ case lists:member(Word, Words) of
+ true -> false;
+ false -> F(Word)
+ end
+ end.
+
+-spec add_features_fun([feature()], fun((atom()) -> boolean())) ->
+ {'ok', fun((atom()) -> boolean())}.
+add_features_fun(Features, F) ->
+ {ok, lists:foldl(fun add_feature_fun/2, F, Features)}.
+
+-spec remove_features_fun([feature()], fun((atom()) -> boolean())) ->
+ {'ok', fun((atom()) -> boolean())}.
+remove_features_fun(Features, F) ->
+ {ok, lists:foldl(fun remove_feature_fun/2, F, Features)}.
+
+configurable_features(Features) ->
+ case lists:all(fun is_configurable/1, Features) of
+ true ->
+ ok;
+ false ->
+ feature_error(Features)
+ end.
+
+feature_error(Features) ->
+ IsInvalid = fun(Ftr) -> not is_valid(Ftr) end,
+ IsNonConfig = fun(Ftr) ->
+ is_valid(Ftr)
+ andalso
+ (not is_configurable(Ftr))
+ end,
+ Invalid = lists:filter(IsInvalid, Features),
+ NonConfig = lists:filter(IsNonConfig, Features),
+ {Error, Culprits} =
+ case {Invalid, NonConfig} of
+ {[], NC} -> {not_configurable, NC};
+ {NV, []} -> {invalid_features, NV};
+ {NV, NC} -> {incorrect_features, NV ++ NC}
+ end,
+ {error, {?MODULE, {Error, Culprits}}}.
+
+-spec format_error(Reason, StackTrace) -> ErrorDescription
+ when Reason :: term(),
+ StackTrace :: erlang:stacktrace(),
+ ArgumentPosition :: pos_integer(),
+ ErrorDescription :: #{ArgumentPosition => unicode:chardata(),
+ general => unicode:chardata(),
+ reason => unicode:chardata()}.
+format_error(Reason, [{_M, _F, _Args, Info}| _St]) ->
+ ErrorInfo = proplists:get_value(error_info, Info, #{}),
+ ErrorMap = maps:get(cause, ErrorInfo),
+ ErrorMap#{reason => io_lib:format("~p: ~p", [?MODULE, Reason])}.
+
+-spec format_error(Reason) -> iolist()
+ when Reason :: term().
+format_error({Error, Features}) ->
+ Fmt = fun F([Ftr]) -> io_lib:fwrite("'~p'", [Ftr]);
+ F([Ftr1, Ftr2]) ->
+ io_lib:fwrite("'~p' and '~p'", [Ftr1, Ftr2]);
+ F([Ftr| Ftrs]) ->
+ io_lib:fwrite("'~p', ~s", [Ftr, F(Ftrs)])
+ end,
+ FmtStr =
+ case {Error, Features} of
+ {invalid_features, [_]} ->
+ "the feature ~s does not exist.";
+ {invalid_features, _} ->
+ "the features ~s do not exist.";
+ {not_configurable, [_]} ->
+ "the feature ~s is not configurable.";
+ {not_configurable, _} ->
+ "the features ~s are not configurable.";
+ {incorrect_features, _} ->
+ "the features ~s do not exist or are not configurable."
+ end,
+
+ io_lib:fwrite(FmtStr, [Fmt(Features)]).
+
+%% Hold the state of which features are currently enabled.
+%% This is almost static, so we go for an almost permanent state,
+%% i.e., use persistent_term.
+init_features() ->
+ Map = init_specs(),
+
+ persistent_term:put({?MODULE, enabled_features}, []),
+ persistent_term:put({?MODULE, keywords}, []),
+
+ RawOps = lists:filter(fun({Tag, _}) ->
+ Tag == 'enable-feature'
+ orelse Tag == 'disable-feature';
+ (_) -> false
+ end,
+ init:get_arguments()),
+
+ Cnv = fun('enable-feature') -> enable;
+ ('disable-feature') -> disable
+ end,
+
+ FeatureOps = lists:append(lists:map(fun({Tag, Strings}) ->
+ lists:map(fun(S) ->
+ {Tag, S} end,
+ Strings)
+ end,
+ RawOps)),
+
+ %% Convert failure, e.g., too long string for atom, to not
+ %% being a valid feature.
+ F = fun({Tag, String}) ->
+ try
+ Atom = list_to_atom(String),
+ case is_configurable(Atom) of
+ true -> {true, {feature, Atom, Cnv(Tag)}};
+ false when Atom == all ->
+ {true, {feature, Atom, Cnv(Tag)}};
+ false -> false
+ end
+ catch
+ _ -> false
+ end
+ end,
+ FOps = lists:filtermap(F, FeatureOps),
+ {Features, _, _} = collect_features(FOps),
+ {Enabled, Keywords} =
+ lists:foldl(fun(Ftr, {Ftrs, Keys}) ->
+ case lists:member(Ftr, Ftrs) of
+ true ->
+ {Ftrs, Keys};
+ false ->
+ {[Ftr| Ftrs],
+ keywords(Ftr, Map) ++ Keys}
+ end
+ end,
+ {[], []},
+ Features),
+
+ %% Save state
+ enabled_features(Enabled),
+ set_keywords(Keywords),
+ persistent_term:put({?MODULE, init_done}, true),
+ ok.
+
+init_specs() ->
+ Specs = case os:getenv("OTP_TEST_FEATURES") of
+ "true" -> test_features();
+ _ -> feature_specs()
+ end,
+ persistent_term:put({?MODULE, feature_specs}, Specs),
+ Specs.
+
+ensure_init() ->
+ case persistent_term:get({?MODULE, init_done}, false) of
+ true -> ok;
+ false ->
+ init_features()
+ end.
+
+%% Return list of currently enabled features
+-spec enabled() -> [feature()].
+enabled() ->
+ ensure_init(),
+ persistent_term:get({?MODULE, enabled_features}).
+
+enabled_features(Ftrs) ->
+ persistent_term:put({?MODULE, enabled_features}, Ftrs).
+
+%% Return list of keywords activated by enabled features
+-spec keywords() -> [atom()].
+keywords() ->
+ ensure_init(),
+ persistent_term:get({?MODULE, keywords}).
+
+set_keywords(Words) ->
+ persistent_term:put({?MODULE, keywords}, Words).
+
+%% Check that any features used in the module are enabled in the
+%% runtime system. If not, return
+%% {not_allowed, <list of not enabled features>}.
+-spec load_allowed(binary()) -> ok | {not_allowed, [feature()]}.
+load_allowed(Binary) ->
+ case erts_internal:beamfile_chunk(Binary, "Meta") of
+ undefined ->
+ ok;
+ Meta ->
+ MetaData = erlang:binary_to_term(Meta),
+ case proplists:get_value(enabled_features, MetaData) of
+ undefined ->
+ ok;
+ Used ->
+ Enabled = enabled(),
+ case lists:filter(fun(UFtr) ->
+ not lists:member(UFtr, Enabled)
+ end,
+ Used) of
+ [] -> ok;
+ NotEnabled ->
+ {not_allowed, NotEnabled}
+ end
+ end
+ end.
+
+%% Return features used by module or beam file
+-spec used(module() | file:filename()) -> [feature()].
+used(Module) when is_atom(Module) ->
+ case code:get_object_code(Module) of
+ error ->
+ not_found;
+ {_Mod, Bin, _Fname} ->
+ features_in(Bin)
+ end;
+used(FName) when is_list(FName) ->
+ features_in(FName).
+
+features_in(NameOrBin) ->
+ case beam_lib:chunks(NameOrBin, ["Meta"], [allow_missing_chunks]) of
+ {ok, {_, [{_, missing_chunk}]}} ->
+ [];
+ {ok, {_, [{_, Meta}]}} ->
+ MetaData = erlang:binary_to_term(Meta),
+ proplists:get_value(enabled_features, MetaData, []);
+ _ ->
+ not_found
+ end.
+
+%% Interpret feature ops (enable or disable) to build the full set of
+%% features. The meta feature 'all' is expanded to all known
+%% features.
+collect_features(FOps) ->
+ %% Features enabled by default
+ Enabled = [Ftr || Ftr <- all(),
+ maps:get(status, info(Ftr)) == approved],
+ collect_features(FOps, Enabled, [], []).
+
+collect_features([], Add, Del, Raw) ->
+ {Add, Del, Raw};
+collect_features([{feature, all, enable}| FOps], Add, _Del, Raw) ->
+ All = configurable(),
+ Add1 = lists:foldl(fun add_ftr/2, Add, All),
+ collect_features(FOps, Add1, [], Raw);
+collect_features([{feature, Feature, enable}| FOps], Add, Del, Raw) ->
+ collect_features(FOps, add_ftr(Feature, Add), Del -- [Feature],
+ Raw ++ [Feature]);
+collect_features([{feature, all, disable}| FOps], _Add, Del, Raw) ->
+ %% Start over
+ All = configurable(),
+ collect_features(FOps, [], Del -- All, Raw);
+collect_features([{feature, Feature, disable}| FOps], Add, Del, Raw) ->
+ collect_features(FOps, Add -- [Feature],
+ add_ftr(Feature, Del),
+ Raw ++ [Feature]).
+
+add_ftr(F, []) ->
+ [F];
+add_ftr(F, [F| _] = Fs) ->
+ Fs;
+add_ftr(F, [F0| Fs]) ->
+ [F0| add_ftr(F, Fs)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Test features - not present in a release
+test_features() ->
+ #{experimental_ftr_1 =>
+ #{short => "Experimental test feature #1",
+ description =>
+ "Test feature in the experimental state. "
+ "It is disabled by default, but can be enabled.",
+ status => experimental,
+ experimental => 24,
+ keywords => ['ifn'],
+ type => extension},
+ experimental_ftr_2 =>
+ #{short => "Experimental test features #2",
+ description =>
+ "Test feature in experimental state. "
+ "It is disabled by default, but can be enabled.",
+ status => experimental,
+ experimental => 25,
+ keywords => ['while', 'until'],
+ type => extension},
+ approved_ftr_1 =>
+ #{short => "Approved test feature #1",
+ description => "Test feature in the approved state. "
+ "It is on by default and can be disabled.",
+ status => approved,
+ experimental => 24,
+ approved => 25,
+ keywords => [],
+ type => extension},
+ approved_ftr_2 =>
+ #{short => "Approved test feature #2",
+ description =>
+ "Test feature in the approved state. "
+ "It is enabled by default, but can still be disabled.",
+ status => approved,
+ experimental => 24,
+ approved => 25,
+ keywords => ['unless'],
+ type => extension},
+ permanent_ftr =>
+ #{short => "Permanent test feature",
+ description => "Test feature in the permanent state. "
+ "This means it is on by default and cannot be disabled. "
+ "It is now a permanent part of Erlang/OTP.",
+ status => permanent,
+ experimental => 17,
+ approved => 18,
+ permanent => 19,
+ keywords => [],
+ type => extension},
+ rejected_ftr =>
+ #{short => "Rejected test feature.",
+ description =>
+ "Test feature existing only to end up as rejected. "
+ "It is not available and cannot be enabled. "
+ "This should be the only trace of it",
+ status => rejected,
+ experimental => 24,
+ rejected => 25,
+ keywords => ['inline', 'return', 'set'],
+ type => extension}}.
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 52fbe470bd..92651084c7 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -356,6 +356,7 @@ bif(node, 0) -> true;
bif(node, 1) -> true;
bif(nodes, 0) -> true;
bif(nodes, 1) -> true;
+bif(nodes, 2) -> true;
bif(now, 0) -> true;
bif(open_port, 2) -> true;
bif(pid_to_list, 1) -> true;
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 76b6597055..b9b58d6576 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
-export([check_format_string/1]).
-export_type([error_info/0, error_description/0]).
+-export_type([fun_used_vars/0]). % Used from erl_eval.erl.
-import(lists, [all/2,any/2,
foldl/3,foldr/3,
@@ -93,6 +94,18 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
-record(typeinfo, {attr, anno}).
+-type type_id() :: {'export', []}
+ | {'record', atom()}
+ | {'spec', mfa()}
+ | {'type', ta()}.
+
+-record(used_type, {anno :: erl_anno:anno(),
+ at = {export, []} :: type_id()}).
+
+-type used_type() :: #used_type{}.
+
+-type fun_used_vars() :: #{erl_parse:abstract_expr() => {[atom()], fun_used_vars()}}.
+
%% Usage of records, functions, and imports. The variable table, which
%% is passed on as an argument, holds the usage of variables.
-record(usage, {
@@ -101,7 +114,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
used_records = gb_sets:new() %Used record definitions
:: gb_sets:set(atom()),
used_types = maps:new() %Used type definitions
- :: #{ta() := anno()}
+ :: #{ta() := [used_type()]}
}).
@@ -130,6 +143,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
not_removed=gb_sets:empty() %Not considered removed
:: gb_sets:set(module_or_mfa()),
func=[], %Current function
+ type_id=[], %Current type id
warn_format=0, %Warn format calls
enabled_warnings=[], %All enabled warnings (ordset).
nowarn_bif_clash=[], %All no warn bif clashes (ordset).
@@ -140,6 +154,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
%outside any fun or lc
xqlc= false :: boolean(), %true if qlc.hrl included
called= [] :: [{fa(),anno()}], %Called functions
+ fun_used_vars = undefined %Funs used vars
+ :: fun_used_vars() | undefined,
usage = #usage{} :: #usage{},
specs = maps:new() %Type specifications
:: #{mfa() => anno()},
@@ -151,9 +167,13 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
:: #{ta() => #typeinfo{}},
exp_types=gb_sets:empty() %Exported types
:: gb_sets:set(ta()),
+ feature_keywords = %Keywords in
+ %configurable features
+ feature_keywords() :: #{atom() => atom()},
bvt = none :: 'none' | [any()], %Variables in binary pattern
gexpr_context = guard %Context of guard expression
- :: gexpr_context()
+ :: gexpr_context(),
+ load_nif=false :: boolean() %true if calls erlang:load_nif/2
}).
-type lint_state() :: #lint{}.
@@ -176,12 +196,21 @@ format_error(pmod_unsupported) ->
%% io_lib:format("module '~s' already imported from package '~s'", [M, P]);
format_error(non_latin1_module_unsupported) ->
"module names with non-latin1 characters are not supported";
+format_error(empty_module_name) ->
+ "the module name must not be empty";
+format_error(blank_module_name) ->
+ "the module name must contain at least one visible character";
+format_error(ctrl_chars_in_module_name) ->
+ "the module name must not contain control characters";
format_error(invalid_call) ->
"invalid function call";
format_error(invalid_record) ->
"invalid record expression";
+format_error({future_feature, Ftr, Atom}) ->
+ io_lib:format("atom '~p' is reserved in the experimental feature '~p'",
+ [Atom, Ftr]);
format_error({attribute,A}) ->
io_lib:format("attribute ~tw after function definitions", [A]);
format_error({missing_qlc_hrl,A}) ->
@@ -190,6 +219,10 @@ format_error({redefine_import,{{F,A},M}}) ->
io_lib:format("function ~tw/~w already imported from ~w", [F,A,M]);
format_error({bad_inline,{F,A}}) ->
io_lib:format("inlined function ~tw/~w undefined", [F,A]);
+format_error({undefined_nif,{F,A}}) ->
+ io_lib:format("nif ~tw/~w undefined", [F,A]);
+format_error(no_load_nif) ->
+ io_lib:format("nifs defined, but no call to erlang:load_nif/2", []);
format_error({invalid_deprecated,D}) ->
io_lib:format("badly formed deprecated attribute ~tw", [D]);
format_error({bad_deprecated,{F,A}}) ->
@@ -518,10 +551,9 @@ used_vars(Exprs, BindingsList) ->
({V,_Val}, Vs0) -> [{V,{bound,unused,[]}} | Vs0]
end, [], BindingsList),
Vt = orddict:from_list(Vs),
- {Evt,_St} = exprs(set_file(Exprs, "nofile"), Vt, start()),
- {ok, foldl(fun({V,{_,used,_}}, L) -> [V | L];
- (_, L) -> L
- end, [], Evt)}.
+ St0 = (start())#lint{fun_used_vars=maps:new()},
+ {_Evt,St1} = exprs(Exprs, Vt, St0),
+ St1#lint.fun_used_vars.
%% module([Form]) ->
%% module([Form], FileName) ->
@@ -568,6 +600,7 @@ module(Forms, FileName) ->
ErrorInfo :: error_info()).
module(Forms, FileName, Opts0) ->
+ %% FIXME Hmm, this is not coherent with the semantics of features
%% We want the options given on the command line to take
%% precedence over options in the module.
Opts = compiler_options(Forms) ++ Opts0,
@@ -638,7 +671,10 @@ start(File, Opts) ->
true, Opts)},
{nif_inline,
bool_option(warn_nif_inline, nowarn_nif_inline,
- true, Opts)}
+ true, Opts)},
+ {keyword_warning,
+ bool_option(warn_keywords, nowarn_keywords,
+ false, Opts)}
],
Enabled1 = [Category || {Category,true} <- Enabled0],
Enabled = ordsets:from_list(Enabled1),
@@ -979,7 +1015,8 @@ post_traversal_check(Forms, St0) ->
StF = check_local_opaque_types(StE),
StG = check_dialyzer_attribute(Forms, StF),
StH = check_callback_information(StG),
- check_removed(Forms, StH).
+ StI = check_nifs(Forms, StH),
+ check_removed(Forms, StI).
%% check_behaviour(State0) -> State
%% Check that the behaviour attribute is valid.
@@ -1288,8 +1325,10 @@ check_undefined_types(#lint{usage=Usage,types=Def}=St0) ->
TA <- UTAs,
not is_map_key(TA, Def),
not is_default_type(TA)],
- foldl(fun ({TA,Anno}, St) ->
- add_error(Anno, {undefined_type,TA}, St)
+ foldl(fun ({TA,UsedTypeList}, St) ->
+ foldl( fun(#used_type{anno = Anno}, St1) ->
+ add_error(Anno, {undefined_type,TA}, St1)
+ end, St, UsedTypeList)
end, St0, Undef).
%% check_bif_clashes(Forms, State0) -> State
@@ -1310,6 +1349,19 @@ check_option_functions(Forms, Tag0, Type, St0) ->
Bad = [{FA,Anno} || {FA,Anno} <- FAsAnno, not member(FA, DefFunctions)],
func_location_error(Type, Bad, St0).
+check_nifs(Forms, St0) ->
+ FAsAnno = [{FA,Anno} || {attribute, Anno, nifs, Args} <- Forms,
+ FA <- Args],
+ St1 = case {FAsAnno, St0#lint.load_nif} of
+ {[{_,Anno1}|_], false} ->
+ add_warning(Anno1, no_load_nif, St0);
+ _ ->
+ St0
+ end,
+ DefFunctions = gb_sets:subtract(St1#lint.defined, gb_sets:from_list(pseudolocals())),
+ Bad = [{FA,Anno} || {FA,Anno} <- FAsAnno, not gb_sets:is_element(FA, DefFunctions)],
+ func_location_error(undefined_nif, Bad, St1).
+
nowarn_function(Tag, Opts) ->
ordsets:from_list([FA || {Tag1,FAs} <- Opts,
Tag1 =:= Tag,
@@ -1423,21 +1475,21 @@ export(Anno, Es, #lint{exports = Es0, called = Called} = St0) ->
-spec export_type(anno(), [ta()], lint_state()) -> lint_state().
%% Mark types as exported; also mark them as used from the export line.
-export_type(Anno, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) ->
- UTs0 = Usage#usage.used_types,
- try foldl(fun ({T,A}=TA, {E,U,St2}) when is_atom(T), is_integer(A) ->
+export_type(Anno, ETs, #lint{exp_types = ETs0} = St0) ->
+ try foldl(fun ({T,A}=TA, {E,St2}) when is_atom(T), is_integer(A) ->
St = case gb_sets:is_element(TA, E) of
true ->
Warn = {duplicated_export_type,TA},
add_warning(Anno, Warn, St2);
false ->
- St2
+ St3 = St2#lint{type_id = {export, []}},
+ used_type(TA, Anno, St3)
end,
- {gb_sets:add_element(TA, E), maps:put(TA, Anno, U), St}
+ {gb_sets:add_element(TA, E), St}
end,
- {ETs0,UTs0,St0}, ETs) of
- {ETs1,UTs1,St1} ->
- St1#lint{usage = Usage#usage{used_types = UTs1}, exp_types = ETs1}
+ {ETs0,St0}, ETs) of
+ {ETs1,St1} ->
+ St1#lint{exp_types = ETs1}
catch
error:_ ->
add_error(Anno, {bad_export_type, ETs}, St0)
@@ -2247,13 +2299,24 @@ is_guard_test(Expression, Forms) ->
IsOverridden :: fun((fa()) -> boolean()).
is_guard_test(Expression, Forms, IsOverridden) ->
- RecordAttributes = [A || A = {attribute, _, record, _D} <- Forms],
- St0 = foldl(fun(Attr0, St1) ->
- Attr = set_file(Attr0, "none"),
- attribute_state(Attr, St1)
- end, start(), RecordAttributes),
- is_guard_test2(set_file(Expression, "nofile"),
- {St0#lint.records,IsOverridden}).
+ NoFileExpression = set_file(Expression, "nofile"),
+
+ %% Unless the expression constructs a record, the record
+ %% definitions are not needed. Therefore, because there can be a
+ %% huge number of record definitions in the forms, delay
+ %% processing the forms until we'll know that the record
+ %% definitions are truly needed.
+ F = fun() ->
+ St = foldl(fun({attribute, _, record, _}=Attr0, St0) ->
+ Attr = set_file(Attr0, "none"),
+ attribute_state(Attr, St0);
+ (_, St0) ->
+ St0
+ end, start(), Forms),
+ St#lint.records
+ end,
+
+ is_guard_test2(NoFileExpression, {F,IsOverridden}).
%% is_guard_test2(Expression, RecordDefs :: dict:dict()) -> boolean().
is_guard_test2({call,Anno,{atom,Ar,record},[E,A]}, Info) ->
@@ -2291,7 +2354,13 @@ is_gexpr({record_index,_A,_Name,Field}, Info) ->
is_gexpr(Field, Info);
is_gexpr({record_field,_A,Rec,_Name,Field}, Info) ->
is_gexpr_list([Rec,Field], Info);
-is_gexpr({record,A,Name,Inits}, Info) ->
+is_gexpr({record,A,Name,Inits}, Info0) ->
+ Info = case Info0 of
+ {#{},_} ->
+ Info0;
+ {F,IsOverridden} when is_function(F, 0) ->
+ {F(),IsOverridden}
+ end,
is_gexpr_fields(Inits, A, Name, Info);
is_gexpr({bin,_A,Fs}, Info) ->
all(fun ({bin_element,_Anno,E,Sz,_Ts}) ->
@@ -2566,6 +2635,23 @@ expr({match,_Anno,P,E}, Vt, St0) ->
{Pvt,Pnew,St2} = pattern(P, vtupdate(Evt, Vt), St1),
St = reject_invalid_alias_expr(P, E, Vt, St2),
{vtupdate(Pnew, vtmerge(Evt, Pvt)),St};
+expr({maybe_match,Anno,P,E}, Vt, St0) ->
+ expr({match,Anno,P,E}, Vt, St0);
+expr({'maybe',Anno,Es}, Vt, St) ->
+ %% No variables are exported.
+ {Evt0, St1} = exprs(Es, Vt, St),
+ Evt1 = vtupdate(vtunsafe({'maybe',Anno}, Evt0, Vt), Vt),
+ Evt2 = vtmerge(Evt0, Evt1),
+ {Evt2,St1};
+expr({'maybe',MaybeAnno,Es,{'else',ElseAnno,Cs}}, Vt, St) ->
+ %% No variables are exported.
+ {Evt0, St1} = exprs(Es, Vt, St),
+ Evt1 = vtupdate(vtunsafe({'maybe',MaybeAnno}, Evt0, Vt), Vt),
+ {Cvt0, St2} = icrt_clauses(Cs, {'else',ElseAnno}, Evt1, St1),
+ Cvt1 = vtupdate(vtunsafe({'else',ElseAnno}, Cvt0, Vt), Vt),
+ Evt2 = vtmerge(Evt0, Evt1),
+ Cvt2 = vtmerge(Cvt0, Cvt1),
+ {vtmerge(Evt2, Cvt2),St2};
%% No comparison or boolean operators yet.
expr({op,_Anno,_Op,A}, Vt, St) ->
expr(A, Vt, St);
@@ -2673,7 +2759,8 @@ record_def(Anno, Name, Fs0, St0) ->
St2 = St1#lint{records=maps:put(Name, {Anno,Fs1},
St1#lint.records)},
Types = [T || {typed_record_field, _, T} <- Fs0],
- check_type({type, nowarn(), product, Types}, St2)
+ St3 = St2#lint{type_id = {record, Name}},
+ check_type({type, nowarn(), product, Types}, St3)
end.
%% def_fields([RecDef], RecordName, State) -> {[DefField],State}.
@@ -2847,9 +2934,8 @@ ginit_fields(Ifs, Anno, Name, Dfs, Vt0, St0) ->
Defs = init_fields(Ifs, Anno, Dfs),
St2 = St1#lint{errors = []},
{_,St3} = check_fields(Defs, Name, Dfs, Vt1, St2, fun gexpr/3),
- #lint{usage = Usage, errors = Errors} = St3,
- IllErrs = [E || {_File,{_Anno,erl_lint,illegal_guard_expr}}=E <- Errors],
- St4 = St1#lint{usage = Usage, errors = IllErrs ++ St1#lint.errors},
+ #lint{usage = Usage, errors = IllErrors} = St3,
+ St4 = St1#lint{usage = Usage, errors = IllErrors ++ St1#lint.errors},
{Vt1,St4}.
%% Default initializations to be carried out
@@ -2893,7 +2979,8 @@ type_def(Attr, Anno, TypeName, ProtoType, Args, St0) ->
fun(St) ->
NewDefs = maps:put(TypePair, Info, TypeDefs),
CheckType = {type, nowarn(), product, [ProtoType|Args]},
- check_type(CheckType, St#lint{types=NewDefs})
+ St1 = St#lint{types=NewDefs, type_id={type, TypePair}},
+ check_type(CheckType, St1)
end,
case is_default_type(TypePair) andalso
not member(no_auto_import_types, St0#lint.compile) of
@@ -3088,16 +3175,15 @@ check_record_types([], _Name, _DefFields, SeenVars, St, _SeenFields) ->
{SeenVars, St}.
used_type(TypePair, Anno, #lint{usage = Usage, file = File} = St) ->
- OldUsed = Usage#usage.used_types,
- UsedTypes = maps:put(TypePair, erl_anno:set_file(File, Anno), OldUsed),
- St#lint{usage=Usage#usage{used_types=UsedTypes}}.
+ Used = Usage#usage.used_types,
+ UsedType = #used_type{anno = erl_anno:set_file(File, Anno),
+ at = St#lint.type_id},
+ NewUsed = maps_prepend(TypePair, UsedType, Used),
+ St#lint{usage=Usage#usage{used_types=NewUsed}}.
is_default_type({Name, NumberOfTypeVariables}) ->
erl_internal:is_type(Name, NumberOfTypeVariables).
-%% OTP 24.0
-is_newly_introduced_builtin_type({nonempty_binary, 0}) -> true;
-is_newly_introduced_builtin_type({nonempty_bitstring, 0}) -> true;
is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false.
is_obsolete_builtin_type(TypePair) ->
@@ -3120,12 +3206,12 @@ spec_decl(Anno, MFA0, TypeSpecs, St00 = #lint{specs = Specs, module = Mod}) ->
case is_map_key(MFA, Specs) of
true -> add_error(Anno, {redefine_spec, MFA0}, St1);
false ->
- case MFA of
- {Mod, _, _} ->
- check_specs(TypeSpecs, spec_wrong_arity, Arity, St1);
- _ ->
- add_error(Anno, {bad_module, MFA}, St1)
- end
+ St2 = case MFA of
+ {Mod, _, _} -> St1;
+ _ -> add_error(Anno, {bad_module, MFA}, St1)
+ end,
+ St3 = St2#lint{type_id = {spec, MFA}},
+ check_specs(TypeSpecs, spec_wrong_arity, Arity, St3)
end.
%% callback_decl(Anno, Fun, Types, State) -> State.
@@ -3141,8 +3227,9 @@ callback_decl(Anno, MFA0, TypeSpecs,
St1 = St0#lint{callbacks = maps:put(MFA, Anno, Callbacks)},
case is_map_key(MFA, Callbacks) of
true -> add_error(Anno, {redefine_callback, MFA0}, St1);
- false -> check_specs(TypeSpecs, callback_wrong_arity,
- Arity, St1)
+ false ->
+ St2 = St1#lint{type_id = {spec, MFA}},
+ check_specs(TypeSpecs, callback_wrong_arity, Arity, St2)
end
end.
@@ -3179,15 +3266,42 @@ is_fa({FuncName, Arity})
when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> true;
is_fa(_) -> false.
-check_module_name(M, Anno, St) ->
- case is_latin1_name(M) of
- true -> St;
- false ->
- add_error(Anno, non_latin1_module_unsupported, St)
+check_module_name(M, Anno, St0) ->
+ AllChars = atom_to_list(M),
+ VisibleChars = remove_non_visible(AllChars),
+ case {AllChars, VisibleChars} of
+ {[], []} ->
+ add_error(Anno, empty_module_name, St0);
+ {[_|_], []} ->
+ add_error(Anno, blank_module_name, St0);
+ {Cs,[_|_]} ->
+ St1 = case io_lib:latin1_char_list(Cs) of
+ true ->
+ St0;
+ false ->
+ add_error(Anno,
+ non_latin1_module_unsupported,
+ St0)
+ end,
+ case any_control_characters(Cs) of
+ true ->
+ add_error(Anno, ctrl_chars_in_module_name, St1);
+ false ->
+ St1
+ end
end.
-is_latin1_name(Name) ->
- io_lib:latin1_char_list(atom_to_list(Name)).
+remove_non_visible(Cs) ->
+ SP = $\s, %Plain space.
+ NBSP = 16#A0, %Non-breaking space.
+ SHY = 16#AD, %Soft hyphen.
+ [C || C <- Cs, C =/= SP, C =/= NBSP, C =/= SHY].
+
+any_control_characters(Cs) ->
+ any(fun(C) when is_integer(C), 0 =< C, C < 16#20;
+ is_integer(C), 16#7F =< C, C < 16#A0 -> true;
+ (_) -> false
+ end, Cs).
check_specs([FunType|Left], ETag, Arity, St0) ->
{FunType1, CTypes} =
@@ -3263,11 +3377,10 @@ check_unused_types(Forms, St) ->
false -> St
end.
-check_unused_types_1(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) ->
+check_unused_types_1(Forms, #lint{types=Ts}=St) ->
case [File || {attribute,_A,file,{File,_Anno}} <- Forms] of
[FirstFile|_] ->
- D = Usage#usage.used_types,
- L = gb_sets:to_list(ExpTs) ++ maps:keys(D),
+ L = reached_types(St),
UsedTypes = gb_sets:from_list(L),
FoldFun =
fun({{record, _}=_Type, 0}, _, AccSt) ->
@@ -3291,6 +3404,19 @@ check_unused_types_1(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) ->
St
end.
+reached_types(#lint{usage = Usage}) ->
+ Es = [{From, {type, To}} ||
+ {To, UsedTs} <- maps:to_list(Usage#usage.used_types),
+ #used_type{at = From} <- UsedTs],
+ Initial = initially_reached_types(Es),
+ G = sofs:family_to_digraph(sofs:rel2fam(sofs:relation(Es))),
+ R = digraph_utils:reachable(Initial, G),
+ true = digraph:delete(G),
+ [T || {type, T} <- R].
+
+initially_reached_types(Es) ->
+ [FromTypeId || {{T, _}=FromTypeId, _} <- Es, T =/= type].
+
check_local_opaque_types(St) ->
#lint{types=Ts, exp_types=ExpTs} = St,
FoldFun =
@@ -3358,7 +3484,8 @@ is_module_dialyzer_option(Option) ->
no_behaviours,no_undefined_callbacks,unmatched_returns,
error_handling,race_conditions,no_missing_calls,
specdiffs,overspecs,underspecs,unknown,
- no_underspecs
+ no_underspecs,extra_return,no_extra_return,
+ missing_return,no_missing_return
]).
%% try_catch_clauses(Scs, Ccs, In, ImportVarTable, State) ->
@@ -3582,7 +3709,20 @@ handle_bitstring_gen_pat(_,St) ->
%% unless it was introduced in a fun or an lc. Only if pat_var finds
%% such variables can the correct line number be given.
+%% If fun_used_vars is set, we want to compute the tree of used
+%% vars across functions. This is by erl_eval to compute used vars
+%% without having to traverse the tree multiple times.
+
+fun_clauses(Cs, Vt, #lint{fun_used_vars=(#{}=FUV)} = St) ->
+ {Uvt, St0} = fun_clauses1(Cs, Vt, St#lint{fun_used_vars=maps:new()}),
+ #lint{fun_used_vars=InnerFUV} = St0,
+ UsedVars = [V || {V, {_, used, _}} <- Uvt],
+ OuterFUV = maps:put(Cs, {UsedVars, InnerFUV}, FUV),
+ {Uvt, St0#lint{fun_used_vars=OuterFUV}};
fun_clauses(Cs, Vt, St) ->
+ fun_clauses1(Cs, Vt, St).
+
+fun_clauses1(Cs, Vt, St) ->
OldRecDef = St#lint.recdef_top,
{Bvt,St2} = foldl(fun (C, {Bvt0, St0}) ->
{Cvt,St1} = fun_clause(C, Vt, St0),
@@ -3957,7 +4097,8 @@ check_remote_function(Anno, M, F, As, St0) ->
%% check_load_nif(Anno, ModName, FuncName, [Arg], State) -> State
%% Add warning if erlang:load_nif/2 is called when any kind of inlining has
%% been enabled.
-check_load_nif(Anno, erlang, load_nif, [_, _], St) ->
+check_load_nif(Anno, erlang, load_nif, [_, _], St0) ->
+ St = St0#lint{load_nif = true},
case is_warn_enabled(nif_inline, St) of
true -> check_nif_inline(Anno, St);
false -> St
@@ -4076,10 +4217,36 @@ test_overriden_by_local(Anno, OldTest, Arity, St) ->
St
end.
+feature_keywords() ->
+ Features = erl_features:configurable(),
+ G = fun(Ftr, Map) ->
+ Keywords = erl_features:keywords(Ftr),
+ Add = fun(Keyword, M) -> maps:put(Keyword, Ftr, M) end,
+ lists:foldl(Add, Map, Keywords)
+ end,
+ lists:foldl(G, #{}, Features).
+
%% keyword_warning(Anno, Atom, State) -> State.
%% Add warning for atoms that will be reserved keywords in the future.
%% (Currently, no such keywords to warn for.)
-keyword_warning(_Anno, _A, St) -> St.
+keyword_warning(Anno, Atom, St) ->
+ case is_warn_enabled(keyword_warning, St) of
+ true ->
+ case erl_anno:text(Anno) of
+ [$'| _] ->
+ %% Don't warn for quoted atoms
+ St;
+ _ ->
+ Keywords = St#lint.feature_keywords,
+ case maps:find(Atom, Keywords) of
+ error -> St;
+ {ok, Ftr} ->
+ add_warning(Anno, {future_feature, Ftr, Atom}, St)
+ end
+ end;
+ false ->
+ St
+ end.
%% format_function(Anno, ModName, FuncName, [Arg], State) -> State.
%% Add warning for bad calls to io:fwrite/format functions.
@@ -4143,7 +4310,7 @@ check_format_2a(Fmt, FmtAnno, As) ->
false ->
Anno = element(2, As),
{warn,1,Anno,"format arguments not a list",[]};
- maybe ->
+ 'maybe' ->
Anno = erl_parse:first_anno(As),
{warn,2,Anno,"format arguments perhaps not a list",[]}
end.
@@ -4189,12 +4356,12 @@ arguments(N) ->
args_list({cons,_A,_H,T}) -> args_list(T);
%% Strange case: user has written something like [a | "bcd"]; pretend
%% we don't know:
-args_list({string,_A,_Cs}) -> maybe;
+args_list({string,_A,_Cs}) -> 'maybe';
args_list({nil,_A}) -> true;
args_list({atom,_,_}) -> false;
args_list({integer,_,_}) -> false;
args_list({float,_,_}) -> false;
-args_list(_Other) -> maybe.
+args_list(_Other) -> 'maybe'.
args_length({cons,_A,_H,T}) -> 1 + args_length(T);
args_length({nil,_A}) -> 0.
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 33569d4a8d..6228c5857a 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,13 +48,15 @@ top_type top_types type typed_expr typed_attr_val
type_sig type_sigs type_guard type_guards fun_type binary_type
type_spec spec_fun typed_exprs typed_record_fields field_types field_type
map_pair_types map_pair_type
-bin_base_type bin_unit_type.
+bin_base_type bin_unit_type
+maybe_expr maybe_match_exprs maybe_match.
Terminals
char integer float atom string var
'(' ')' ',' '->' '{' '}' '[' ']' '|' '||' '<-' ';' ':' '#' '.'
'after' 'begin' 'case' 'try' 'catch' 'end' 'fun' 'if' 'of' 'receive' 'when'
+'maybe' 'else'
'andalso' 'orelse'
'bnot' 'not'
'*' '/' 'div' 'rem' 'band' 'and'
@@ -63,6 +65,7 @@ char integer float atom string var
'==' '/=' '=<' '<' '>=' '>' '=:=' '=/=' '<=' '=>' ':='
'<<' '>>'
'!' '=' '::' '..' '...'
+'?='
'spec' 'callback' % helper
dot.
@@ -257,6 +260,7 @@ expr_max -> case_expr : '$1'.
expr_max -> receive_expr : '$1'.
expr_max -> fun_expr : '$1'.
expr_max -> try_expr : '$1'.
+expr_max -> maybe_expr : '$1'.
pat_expr -> pat_expr '=' pat_expr : {match,first_anno('$1'),'$1','$3'}.
pat_expr -> pat_expr comp_op pat_expr : ?mkop2('$1', '$2', '$3').
@@ -277,10 +281,6 @@ pat_expr_max -> '(' pat_expr ')' : '$2'.
map_pat_expr -> '#' map_tuple :
{map, ?anno('$1'),'$2'}.
-map_pat_expr -> pat_expr_max '#' map_tuple :
- {map, ?anno('$2'),'$1','$3'}.
-map_pat_expr -> map_pat_expr '#' map_tuple :
- {map, ?anno('$2'),'$1','$3'}.
record_pat_expr -> '#' atom '.' atom :
{record_index,?anno('$1'),element(3, '$2'),'$4'}.
@@ -401,7 +401,6 @@ if_clauses -> if_clause ';' if_clauses : ['$1' | '$3'].
if_clause -> guard clause_body :
{clause,first_anno(hd(hd('$1'))),[],'$1','$2'}.
-
case_expr -> 'case' expr 'of' cr_clauses 'end' :
{'case',?anno('$1'),'$2','$4'}.
@@ -477,6 +476,21 @@ try_clause -> var ':' pat_expr try_opt_stacktrace clause_guard clause_body :
try_opt_stacktrace -> ':' var : '$2'.
try_opt_stacktrace -> '$empty' : '_'.
+
+maybe_expr -> 'maybe' maybe_match_exprs 'end' :
+ {'maybe',?anno('$1'),'$2'}.
+maybe_expr -> 'maybe' maybe_match_exprs 'else' cr_clauses 'end' :
+ %% `erl_lint` can produce a better warning when the position
+ %% of the `else` keyword is known.
+ {'maybe',?anno('$1'),'$2',{'else',?anno('$3'),'$4'}}.
+
+maybe_match_exprs -> maybe_match : ['$1'].
+maybe_match_exprs -> maybe_match ',' maybe_match_exprs : ['$1' | '$3'].
+maybe_match_exprs -> expr : ['$1'].
+maybe_match_exprs -> expr ',' maybe_match_exprs : ['$1' | '$3'].
+
+maybe_match -> expr '?=' expr : {maybe_match,?anno('$2'),'$1','$3'}.
+
argument_list -> '(' ')' : {[],?anno('$1')}.
argument_list -> '(' exprs ')' : {'$2',?anno('$1')}.
@@ -647,6 +661,7 @@ Erlang code.
-type abstract_expr() :: af_literal()
| af_match(abstract_expr())
+ | af_maybe_match()
| af_variable()
| af_tuple(abstract_expr())
| af_nil()
@@ -673,7 +688,9 @@ Erlang code.
| af_local_fun()
| af_remote_fun()
| af_fun()
- | af_named_fun().
+ | af_named_fun()
+ | af_maybe()
+ | af_maybe_else().
-type af_record_update(T) :: {'record',
anno(),
@@ -816,6 +833,9 @@ Erlang code.
-type af_map_pattern() ::
{'map', anno(), [af_assoc_exact(af_pattern())]}.
+-type af_maybe() :: {'maybe', anno(), af_body()}.
+-type af_maybe_else() :: {'maybe', anno(), af_body(), {'else', anno(), af_clause_seq()}}.
+
-type abstract_type() :: af_annotated_type()
| af_atom()
| af_bitstring_type()
@@ -926,6 +946,8 @@ Erlang code.
-type af_match(T) :: {'match', anno(), af_pattern(), T}.
+-type af_maybe_match() :: {'maybe_match', anno(), af_pattern(), abstract_expr()}.
+
-type af_variable() :: {'var', anno(), atom()}. % | af_anon_variable()
%-type af_anon_variable() :: {'var', anno(), '_'}.
@@ -951,7 +973,7 @@ Erlang code.
-type binary_op() :: '/' | '*' | 'div' | 'rem' | 'band' | 'and' | '+' | '-'
| 'bor' | 'bxor' | 'bsl' | 'bsr' | 'or' | 'xor' | '++'
| '--' | '==' | '/=' | '=<' | '<' | '>=' | '>' | '=:='
- | '=/='.
+ | '=/=' | '!'.
-type af_unary_op(T) :: {'op', anno(), unary_op(), T}.
@@ -1397,7 +1419,7 @@ normalise({bin,_,Fs}) ->
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
{value, normalise(E), []}
- end, [], true),
+ end),
B;
normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
diff --git a/lib/stdlib/src/erl_posix_msg.erl b/lib/stdlib/src/erl_posix_msg.erl
index b9ed4a3a9d..e86ba81170 100644
--- a/lib/stdlib/src/erl_posix_msg.erl
+++ b/lib/stdlib/src/erl_posix_msg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -139,7 +139,7 @@ message_1(eprocunavail) -> <<"bad procedure for program">>;
message_1(eprogmismatch) -> <<"program version wrong">>;
message_1(eprogunavail) -> <<"RPC program not available">>;
message_1(eproto) -> <<"protocol error">>;
-message_1(eprotonosupport) -> <<"protocol not suppored">>;
+message_1(eprotonosupport) -> <<"protocol not supported">>;
message_1(eprototype) -> <<"protocol wrong type for socket">>;
message_1(erange) -> <<"math result unrepresentable">>;
message_1(erefused) -> <<"EREFUSED">>;
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 74b42a3b40..191aa75698 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -24,7 +24,8 @@
-export([form/1,form/2,
attribute/1,attribute/2,function/1,function/2,
- guard/1,guard/2,exprs/1,exprs/2,exprs/3,expr/1,expr/2,expr/3,expr/4]).
+ guard/1,guard/2,exprs/1,exprs/2,exprs/3,expr/1,expr/2,expr/3,expr/4,
+ legalize_vars/1]).
-import(lists, [append/1,foldr/3,map/2,mapfoldl/3,reverse/1,reverse/2]).
-import(io_lib, [write/1,format/2]).
@@ -199,6 +200,34 @@ expr(E, I, P, Options) ->
?TEST(E),
frmt(lexpr(E, P, options(Options)), I, state(Options)).
+-spec(legalize_vars(Function) -> erl_parse:abstract_form() when
+ Function :: erl_parse:abstract_form()).
+
+legalize_vars({function,ANNO,Name0,Arity,Clauses0}) ->
+ ?TEST(F),
+ %% Collect all used variables in this function and classify them
+ %% as either syntactically valid or not.
+ F = fun({var,_Anno,Name}, {Valid, Invalid}) ->
+ Str = [First|_] = atom_to_list(Name),
+ case First of
+ X when X >= $a, X =< $z ->
+ {Valid,Invalid#{Name => Str}};
+ _ ->
+ {Valid#{Name => Name},Invalid}
+ end
+ end,
+ {Valid, Invalid} = fold_vars(F, {#{}, #{}}, Clauses0),
+ %% Make up an unique variable name for each key in Invalid, then
+ %% replace all invalid names.
+ Mapping = maps:fold(fun legalize_name/3, Valid, Invalid),
+ Subs = fun({var,Anno,Name}) ->
+ {var,Anno,map_get(Name, Mapping)}
+ end,
+ Clauses = map_vars(Subs, Clauses0),
+ {function,ANNO,Name0,Arity,Clauses};
+legalize_vars(Form) ->
+ erlang:error(badarg, [Form]).
+
%%%
%%% Local functions
%%%
@@ -675,12 +704,26 @@ lexpr({'catch',_,Expr}, Prec, Opts) ->
{P,R} = preop_prec('catch'),
El = {list,[{step,'catch',lexpr(Expr, R, Opts)}]},
maybe_paren(P, Prec, El);
+lexpr({'maybe',_,Es}, _, Opts) ->
+ {list,[{step,'maybe',body(Es, Opts)},{reserved,'end'}]};
+lexpr({'maybe',_,Es,{'else',_,Cs}}, _, Opts) ->
+ {list,[{step,'maybe',body(Es, Opts)},{step,'else',cr_clauses(Cs, Opts)},{reserved,'end'}]};
+lexpr({maybe_match,_,Lhs,Rhs}, _, Opts) ->
+ Pl = lexpr(Lhs, 0, Opts),
+ Rl = lexpr(Rhs, 0, Opts),
+ {list,[{cstep,[Pl,leaf(" ?=")],Rl}]};
lexpr({match,_,Lhs,Rhs}, Prec, Opts) ->
{L,P,R} = inop_prec('='),
Pl = lexpr(Lhs, L, Opts),
Rl = lexpr(Rhs, R, Opts),
El = {list,[{cstep,[Pl,' ='],Rl}]},
maybe_paren(P, Prec, El);
+lexpr({op,_,Op,Arg}, Prec, Opts) when Op =:= '+';
+ Op =:= '-' ->
+ {P,R} = preop_prec(Op),
+ Ol = {reserved, leaf(atom_to_list(Op))},
+ El = [Ol,lexpr(Arg, R, Opts)],
+ maybe_paren(P, Prec, El);
lexpr({op,_,Op,Arg}, Prec, Opts) ->
{P,R} = preop_prec(Op),
Ol = {reserved, leaf(format("~s ", [Op]))},
@@ -1324,7 +1367,7 @@ wordtable() ->
L = [begin {leaf,Sz,S} = leaf(W), {S,Sz} end ||
W <- [" ->"," =","<<",">>","[]","after","begin","case","catch",
"end","fun","if","of","receive","try","when"," ::","..",
- " |"]],
+ " |","maybe","else"]],
list_to_tuple(L).
word(' ->', WT) -> element(1, WT);
@@ -1345,4 +1388,39 @@ word('try', WT) -> element(15, WT);
word('when', WT) -> element(16, WT);
word(' ::', WT) -> element(17, WT);
word('..', WT) -> element(18, WT);
-word(' |', WT) -> element(19, WT).
+word(' |', WT) -> element(19, WT);
+word('maybe', WT) -> element(20, WT);
+word('else', WT) -> element(21, WT).
+
+%% Make up an unique variable name for Name that won't clash with any
+%% name in Used. We first try by converting the name to uppercase and
+%% if that fails we start prepending 'X'es until we find an unused
+%% name.
+legalize_name(InvalidName, StringName, Used) ->
+ Upper = string:to_upper(StringName),
+ NewName = list_to_atom(Upper),
+ case Used of
+ #{ NewName := _ } ->
+ legalize_name(InvalidName, [$X|StringName], Used);
+ #{} ->
+ Used#{ InvalidName => NewName }
+ end.
+
+fold_vars(F, Acc0, Forms) when is_list(Forms) ->
+ lists:foldl(fun(Elem, Acc) -> fold_vars(F, Acc, Elem) end, Acc0, Forms);
+fold_vars(F, Acc0, V={var,_,_}) ->
+ F(V, Acc0);
+fold_vars(F, Acc0, Form) when is_tuple(Form) ->
+ lists:foldl(fun(Elem, Acc) -> fold_vars(F, Acc, Elem) end,
+ Acc0, tuple_to_list(Form));
+fold_vars(_, Acc, _) ->
+ Acc.
+
+map_vars(F, Forms) when is_list(Forms) ->
+ [map_vars(F, Form) || Form <- Forms];
+map_vars(F, V={var,_,_}) ->
+ F(V);
+map_vars(F, Form) when is_tuple(Form) ->
+ list_to_tuple([map_vars(F, Elem) || Elem <- tuple_to_list(Form)]);
+map_vars(_, Form) ->
+ Form.
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl
index 5d988e7438..f2e9d2d7b9 100644
--- a/lib/stdlib/src/erl_scan.erl
+++ b/lib/stdlib/src/erl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,7 +52,8 @@
%%% External exports
-export([string/1,string/2,string/3,tokens/3,tokens/4,
- format_error/1,reserved_word/1]).
+ format_error/1,reserved_word/1,
+ f_reserved_word/1]).
-export([column/1,end_location/1,line/1,location/1,text/1,
category/1,symbol/1]).
@@ -89,8 +90,10 @@
-type category() :: atom().
-type resword_fun() :: fun((atom()) -> boolean()).
+-type text_fun() :: fun((atom(), string()) -> boolean()).
-type option() :: 'return' | 'return_white_spaces' | 'return_comments'
- | 'text' | {'reserved_word_fun', resword_fun()}.
+ | 'text' | {'reserved_word_fun', resword_fun()}
+ | {'text_fun', text_fun()}.
-type options() :: option() | [option()].
-type symbol() :: atom() | float() | integer() | string().
-type token() :: {category(), Anno :: erl_anno:anno(), symbol()}
@@ -101,10 +104,11 @@
%%% Local record.
-record(erl_scan,
- {resword_fun = fun reserved_word/1 :: resword_fun(),
- ws = false :: boolean(),
- comment = false :: boolean(),
- text = false :: boolean()}).
+ {resword_fun = fun reserved_word/1 :: resword_fun(),
+ text_fun = fun(_, _) -> false end :: text_fun(),
+ ws = false :: boolean(),
+ comment = false :: boolean(),
+ has_fun = false :: boolean()}).
%%----------------------------------------------------------------------------
@@ -282,10 +286,19 @@ options(Opts0) when is_list(Opts0) ->
Comment = proplists:get_bool(return_comments, Opts),
WS = proplists:get_bool(return_white_spaces, Opts),
Txt = proplists:get_bool(text, Opts),
+ TxtFunOpt = proplists:get_value(text_fun, Opts, none),
+ DefTxtFun = fun(_, _) -> Txt end,
+ {HasFun, TxtFun} =
+ if
+ Txt -> {Txt, DefTxtFun};
+ TxtFunOpt == none -> {Txt, DefTxtFun};
+ true -> {true, TxtFunOpt}
+ end,
#erl_scan{resword_fun = RW_fun,
comment = Comment,
ws = WS,
- text = Txt};
+ text_fun = TxtFun,
+ has_fun = HasFun};
options(Opt) ->
options([Opt]).
@@ -427,6 +440,11 @@ scan1([C|Cs], St, Line, Col, Toks) when ?WHITE_SPACE(C) ->
skip_white_space(Cs, St, Line, Col, Toks, 1)
end;
%% Punctuation characters and operators, first recognise multiples.
+%% ?= for the maybe ... else ... end construct
+scan1("?="++Cs, St, Line, Col, Toks) ->
+ tok2(Cs, St, Line, Col, Toks, "?=", '?=', 2);
+scan1("?"=Cs, _St, Line, Col, Toks) ->
+ {more,{Cs,Col,Toks,Line,[],fun scan/6}};
%% << <- <=
scan1("<<"++Cs, St, Line, Col, Toks) ->
tok2(Cs, St, Line, Col, Toks, "<<", '<<', 2);
@@ -591,19 +609,24 @@ scan_name([], Ncs) ->
scan_name(Cs, Ncs) ->
{lists:reverse(Ncs),Cs}.
--define(STR(St, S), if St#erl_scan.text -> S; true -> [] end).
+-define(STR(Cl, St, S),
+ case (St#erl_scan.has_fun)
+ andalso (St#erl_scan.text_fun)(Cl, S) of
+ true -> S;
+ false -> []
+ end).
scan_dot([$%|_]=Cs, St, Line, Col, Toks, Ncs) ->
- Anno = anno(Line, Col, St, Ncs),
+ Anno = anno(Line, Col, St, ?STR(dot, St, Ncs)),
{ok,[{dot,Anno}|Toks],Cs,Line,incr_column(Col, 1)};
scan_dot([$\n=C|Cs], St, Line, Col, Toks, Ncs) ->
- Anno = anno(Line, Col, St, ?STR(St, Ncs++[C])),
+ Anno = anno(Line, Col, St, ?STR(dot, St, Ncs++[C])),
{ok,[{dot,Anno}|Toks],Cs,Line+1,new_column(Col, 1)};
scan_dot([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) ->
- Anno = anno(Line, Col, St, ?STR(St, Ncs++[C])),
+ Anno = anno(Line, Col, St, ?STR(dot, St, Ncs++[C])),
{ok,[{dot,Anno}|Toks],Cs,Line,incr_column(Col, 2)};
scan_dot(eof=Cs, St, Line, Col, Toks, Ncs) ->
- Anno = anno(Line, Col, St, Ncs),
+ Anno = anno(Line, Col, St, ?STR(dot, St, Ncs)),
{ok,[{dot,Anno}|Toks],Cs,Line,incr_column(Col, 1)};
scan_dot(Cs, St, Line, Col, Toks, Ncs) ->
tok2(Cs, St, Line, Col, Toks, Ncs, '.', 1).
@@ -657,34 +680,34 @@ scan_nl_tabs(Cs, St, Line, Col, Toks, N) ->
%% Note: returning {more,Cont} is meaningless here; one could just as
%% well return several tokens. But since tokens() scans up to a full
%% stop anyway, nothing is gained by not collecting all white spaces.
-scan_nl_white_space([$\n|Cs], #erl_scan{text = false}=St, Line, no_col=Col,
+scan_nl_white_space([$\n|Cs], #erl_scan{has_fun = false}=St, Line, no_col=Col,
Toks0, Ncs) ->
Toks = [{white_space,anno(Line),lists:reverse(Ncs)}|Toks0],
scan_newline(Cs, St, Line+1, Col, Toks);
scan_nl_white_space([$\n|Cs], St, Line, Col, Toks, Ncs0) ->
Ncs = lists:reverse(Ncs0),
- Anno = anno(Line, Col, St, Ncs),
+ Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)),
Token = {white_space,Anno,Ncs},
scan_newline(Cs, St, Line+1, new_column(Col, length(Ncs)), [Token|Toks]);
scan_nl_white_space([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) ->
scan_nl_white_space(Cs, St, Line, Col, Toks, [C|Ncs]);
scan_nl_white_space([]=Cs, _St, Line, Col, Toks, Ncs) ->
{more,{Cs,Col,Toks,Line,Ncs,fun scan_nl_white_space/6}};
-scan_nl_white_space(Cs, #erl_scan{text = false}=St, Line, no_col=Col,
+scan_nl_white_space(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col,
Toks, Ncs) ->
Anno = anno(Line),
scan1(Cs, St, Line+1, Col, [{white_space,Anno,lists:reverse(Ncs)}|Toks]);
scan_nl_white_space(Cs, St, Line, Col, Toks, Ncs0) ->
Ncs = lists:reverse(Ncs0),
- Anno = anno(Line, Col, St, Ncs),
+ Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)),
Token = {white_space,Anno,Ncs},
scan1(Cs, St, Line+1, new_column(Col, length(Ncs)), [Token|Toks]).
-newline_end(Cs, #erl_scan{text = false}=St, Line, no_col=Col,
+newline_end(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col,
Toks, _N, Ncs) ->
scan1(Cs, St, Line+1, Col, [{white_space,anno(Line),Ncs}|Toks]);
newline_end(Cs, St, Line, Col, Toks, N, Ncs) ->
- Anno = anno(Line, Col, St, Ncs),
+ Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)),
scan1(Cs, St, Line+1, new_column(Col, N), [{white_space,Anno,Ncs}|Toks]).
scan_spcs([$\s|Cs], St, Line, Col, Toks, N) when N < 16 ->
@@ -734,19 +757,19 @@ scan_char([$\\|Cs]=Cs0, St, Line, Col, Toks) ->
{eof,Ncol} ->
scan_error(char, Line, Col, Line, Ncol, eof);
{nl,Val,Str,Ncs,Ncol} ->
- Anno = anno(Line, Col, St, ?STR(St, "$\\"++Str)), %"
+ Anno = anno(Line, Col, St, ?STR(char, St, "$\\"++Str)), %"
Ntoks = [{char,Anno,Val}|Toks],
scan1(Ncs, St, Line+1, Ncol, Ntoks);
{Val,Str,Ncs,Ncol} ->
- Anno = anno(Line, Col, St, ?STR(St, "$\\"++Str)), %"
+ Anno = anno(Line, Col, St, ?STR(char, St, "$\\"++Str)), %"
Ntoks = [{char,Anno,Val}|Toks],
scan1(Ncs, St, Line, Ncol, Ntoks)
end;
scan_char([$\n=C|Cs], St, Line, Col, Toks) ->
- Anno = anno(Line, Col, St, ?STR(St, [$$,C])),
+ Anno = anno(Line, Col, St, ?STR(char, St, [$$,C])),
scan1(Cs, St, Line+1, new_column(Col, 1), [{char,Anno,C}|Toks]);
scan_char([C|Cs], St, Line, Col, Toks) when ?UNICODE(C) ->
- Anno = anno(Line, Col, St, ?STR(St, [$$,C])),
+ Anno = anno(Line, Col, St, ?STR(char, St, [$$,C])),
scan1(Cs, St, Line, incr_column(Col, 2), [{char,Anno,C}|Toks]);
scan_char([C|_Cs], _St, Line, Col, _Toks) when ?CHAR(C) ->
scan_error({illegal,character}, Line, Col, Line, incr_column(Col, 1), eof);
@@ -766,7 +789,7 @@ scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) ->
Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars.
scan_error({string,$\",Estr}, Line0, Col0, Nline, Ncol, Ncs); %"
{Ncs,Nline,Ncol,Nstr,Nwcs} ->
- Anno = anno(Line0, Col0, St, Nstr),
+ Anno = anno(Line0, Col0, St, ?STR(string, St, Nstr)),
scan1(Ncs, St, Nline, Ncol, [{string,Anno,Nwcs}|Toks])
end.
@@ -783,16 +806,16 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) ->
{Ncs,Nline,Ncol,Nstr,Nwcs} ->
case catch list_to_atom(Nwcs) of
A when is_atom(A) ->
- Anno = anno(Line0, Col0, St, Nstr),
+ Anno = anno(Line0, Col0, St, ?STR(atom, St, Nstr)),
scan1(Ncs, St, Nline, Ncol, [{atom,Anno,A}|Toks]);
_ ->
scan_error({illegal,atom}, Line0, Col0, Nline, Ncol, Ncs)
end
end.
-scan_string0(Cs, #erl_scan{text=false}, Line, no_col=Col, Q, [], Wcs) ->
+scan_string0(Cs, #erl_scan{has_fun=false}, Line, no_col=Col, Q, [], Wcs) ->
scan_string_no_col(Cs, Line, Col, Q, Wcs);
-scan_string0(Cs, #erl_scan{text=true}, Line, no_col=Col, Q, Str, Wcs) ->
+scan_string0(Cs, #erl_scan{has_fun=true}, Line, no_col=Col, Q, Str, Wcs) ->
scan_string1(Cs, Line, Col, Q, Str, Wcs);
scan_string0(Cs, St, Line, Col, Q, [], Wcs) ->
scan_string_col(Cs, St, Line, Col, Q, Wcs);
@@ -812,7 +835,7 @@ scan_string_no_col(Cs, Line, Col, Q, Wcs) ->
%% Optimization. Col =/= no_col.
scan_string_col([Q|Cs], St, Line, Col, Q, Wcs0) ->
Wcs = lists:reverse(Wcs0),
- Str = ?STR(St, [Q|Wcs++[Q]]),
+ Str = ?STR(atom, St, [Q|Wcs++[Q]]),
{Cs,Line,Col+1,Str,Wcs};
scan_string_col([$\n=C|Cs], St, Line, _xCol, Q, Wcs) ->
scan_string_col(Cs, St, Line+1, 1, Q, [C|Wcs]);
@@ -1100,29 +1123,29 @@ scan_comment(Cs, St, Line, Col, Toks, Ncs0) ->
Ncs = lists:reverse(Ncs0),
tok3(Cs, St, Line, Col, Toks, comment, Ncs, Ncs).
-tok2(Cs, #erl_scan{text = false}=St, Line, no_col=Col, Toks, _Wcs, P) ->
+tok2(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _Wcs, P) ->
scan1(Cs, St, Line, Col, [{P,anno(Line)}|Toks]);
tok2(Cs, St, Line, Col, Toks, Wcs, P) ->
- Anno = anno(Line, Col, St, Wcs),
+ Anno = anno(Line, Col, St, ?STR(P, St, Wcs)),
scan1(Cs, St, Line, incr_column(Col, length(Wcs)), [{P,Anno}|Toks]).
-tok2(Cs, #erl_scan{text = false}=St, Line, no_col=Col, Toks, _Wcs, P, _N) ->
+tok2(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _Wcs, P, _N) ->
scan1(Cs, St, Line, Col, [{P,anno(Line)}|Toks]);
tok2(Cs, St, Line, Col, Toks, Wcs, P, N) ->
- Anno = anno(Line, Col, St, Wcs),
+ Anno = anno(Line, Col, St, ?STR(P,St,Wcs)),
scan1(Cs, St, Line, incr_column(Col, N), [{P,Anno}|Toks]).
-tok3(Cs, #erl_scan{text = false}=St, Line, no_col=Col, Toks, Item, _S, Sym) ->
+tok3(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Item, _S, Sym) ->
scan1(Cs, St, Line, Col, [{Item,anno(Line),Sym}|Toks]);
tok3(Cs, St, Line, Col, Toks, Item, String, Sym) ->
- Token = {Item,anno(Line, Col, St, String),Sym},
+ Token = {Item,anno(Line, Col, St, ?STR(Item, St, String)),Sym},
scan1(Cs, St, Line, incr_column(Col, length(String)), [Token|Toks]).
-tok3(Cs, #erl_scan{text = false}=St, Line, no_col=Col, Toks, Item,
+tok3(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Item,
_String, Sym, _Length) ->
scan1(Cs, St, Line, Col, [{Item,anno(Line),Sym}|Toks]);
tok3(Cs, St, Line, Col, Toks, Item, String, Sym, Length) ->
- Token = {Item,anno(Line, Col, St, String),Sym},
+ Token = {Item,anno(Line, Col, St, ?STR(Item, St, String)),Sym},
scan1(Cs, St, Line, incr_column(Col, Length), [Token|Toks]).
scan_error(Error, Line, Col, EndLine, EndCol, Rest) ->
@@ -1135,14 +1158,18 @@ scan_error(Error, ErrorLoc, EndLoc, Rest) ->
-compile({inline,[anno/4]}).
-anno(Line, no_col, #erl_scan{text = false}, _String) ->
+anno(Line, no_col, #erl_scan{has_fun = false}, _String) ->
anno(Line);
-anno(Line, no_col, #erl_scan{text = true}, String) ->
+anno(Line, no_col, #erl_scan{has_fun = true}, []) ->
+ anno(Line);
+anno(Line, no_col, #erl_scan{has_fun = true}, String) ->
Anno = anno(Line),
erl_anno:set_text(String, Anno);
-anno(Line, Col, #erl_scan{text = false}, _String) ->
+anno(Line, Col, #erl_scan{has_fun = false}, _String) ->
+ anno({Line, Col});
+anno(Line, Col, #erl_scan{has_fun = true}, []) ->
anno({Line, Col});
-anno(Line, Col, #erl_scan{text = true}, String) ->
+anno(Line, Col, #erl_scan{has_fun = true}, String) ->
Anno = anno({Line, Col}),
erl_anno:set_text(String, Anno).
@@ -1222,32 +1249,43 @@ tabs(8) -> "\t\t\t\t\t\t\t\t";
tabs(9) -> "\t\t\t\t\t\t\t\t\t";
tabs(10) -> "\t\t\t\t\t\t\t\t\t\t".
+%% Dynamic version of reserved_word that knows about the possibility
+%% that enabled features might change the set of reserved words.
-spec reserved_word(Atom :: atom()) -> boolean().
-reserved_word('after') -> true;
-reserved_word('begin') -> true;
-reserved_word('case') -> true;
-reserved_word('try') -> true;
-reserved_word('cond') -> true;
-reserved_word('catch') -> true;
-reserved_word('andalso') -> true;
-reserved_word('orelse') -> true;
-reserved_word('end') -> true;
-reserved_word('fun') -> true;
-reserved_word('if') -> true;
-reserved_word('let') -> true;
-reserved_word('of') -> true;
-reserved_word('receive') -> true;
-reserved_word('when') -> true;
-reserved_word('bnot') -> true;
-reserved_word('not') -> true;
-reserved_word('div') -> true;
-reserved_word('rem') -> true;
-reserved_word('band') -> true;
-reserved_word('and') -> true;
-reserved_word('bor') -> true;
-reserved_word('bxor') -> true;
-reserved_word('bsl') -> true;
-reserved_word('bsr') -> true;
-reserved_word('or') -> true;
-reserved_word('xor') -> true;
-reserved_word(_) -> false.
+reserved_word(Atom) ->
+ case f_reserved_word(Atom) of
+ true -> true;
+ false ->
+ lists:member(Atom, erl_features:keywords())
+ end.
+
+%% Static version of reserved_words. These represent the fixed set of
+%% reserved words.
+f_reserved_word('after') -> true;
+f_reserved_word('begin') -> true;
+f_reserved_word('case') -> true;
+f_reserved_word('try') -> true;
+f_reserved_word('cond') -> true;
+f_reserved_word('catch') -> true;
+f_reserved_word('andalso') -> true;
+f_reserved_word('orelse') -> true;
+f_reserved_word('end') -> true;
+f_reserved_word('fun') -> true;
+f_reserved_word('if') -> true;
+f_reserved_word('let') -> true;
+f_reserved_word('of') -> true;
+f_reserved_word('receive') -> true;
+f_reserved_word('when') -> true;
+f_reserved_word('bnot') -> true;
+f_reserved_word('not') -> true;
+f_reserved_word('div') -> true;
+f_reserved_word('rem') -> true;
+f_reserved_word('band') -> true;
+f_reserved_word('and') -> true;
+f_reserved_word('bor') -> true;
+f_reserved_word('bxor') -> true;
+f_reserved_word('bsl') -> true;
+f_reserved_word('bsr') -> true;
+f_reserved_word('or') -> true;
+f_reserved_word('xor') -> true;
+f_reserved_word(_) -> false.
diff --git a/lib/stdlib/src/erl_stdlib_errors.erl b/lib/stdlib/src/erl_stdlib_errors.erl
index 356ac0b792..eeccb77db1 100644
--- a/lib/stdlib/src/erl_stdlib_errors.erl
+++ b/lib/stdlib/src/erl_stdlib_errors.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2020-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2020-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -189,7 +189,20 @@ format_lists_error(keysearch, Args) ->
format_lists_error(member, [_Key, List]) ->
[[], must_be_list(List)];
format_lists_error(reverse, [List, _Acc]) ->
- [must_be_list(List)].
+ [must_be_list(List)];
+format_lists_error(seq, [First, Last, Inc]) ->
+ case [must_be_integer(First), must_be_integer(Last), must_be_integer(Inc)] of
+ [[], [], []] ->
+ IncError = if
+ (Inc =< 0 andalso First - Inc =< Last) ->
+ <<"not a positive increment">>;
+ (Inc >= 0 andalso First - Inc >= Last) ->
+ <<"not a negative increment">>
+ end,
+ [[], [], IncError];
+ Errors -> Errors
+ end.
+
format_maps_error(filter, Args) ->
format_maps_error(map, Args);
@@ -212,6 +225,10 @@ format_maps_error(get, [_Key,Map]) ->
true ->
[[],not_map]
end;
+format_maps_error(groups_from_list, [Fun, List]) ->
+ [must_be_fun(Fun, 1), must_be_list(List)];
+format_maps_error(groups_from_list, [Fun1, Fun2, List]) ->
+ [must_be_fun(Fun1, 1), must_be_fun(Fun2, 1), must_be_list(List)];
format_maps_error(get, [_,_,_]) ->
[[],not_map];
format_maps_error(intersect, [Map1, Map2]) ->
@@ -382,6 +399,12 @@ format_unicode_error(characters_to_nfkd_list, [_]) ->
unicode_char_data(Chars) ->
try unicode:characters_to_binary(Chars) of
+ {error,_,_} ->
+ bad_char_data;
+
+ {incomplete,_,_} ->
+ bad_char_data;
+
_ ->
[]
catch
@@ -426,6 +449,11 @@ format_io_error(_, _, {io, arguments}, true) ->
[device_arguments];
format_io_error(_, _, {io, arguments}, false) ->
[{general,device_arguments}];
+%% calling_self, Io =:= self()
+format_io_error(_, _, {io, calling_self}, true) ->
+ [calling_self];
+format_io_error(_, _, {io, calling_self}, false) ->
+ [{general,calling_self}];
%% terminated, monitor(Io) failed
format_io_error(_, _, {io, terminated}, true) ->
[device_terminated];
@@ -625,17 +653,19 @@ format_ets_error(match_spec_compile, [_], _Cause) ->
[bad_matchspec];
format_ets_error(next, Args, Cause) ->
format_default(bad_key, Args, Cause);
-format_ets_error(new, [Name,Options], _Cause) ->
+format_ets_error(new, [Name,Options], Cause) ->
NameError = if
is_atom(Name) -> [];
true -> not_atom
end,
OptsError = must_be_list(Options),
- case {NameError,OptsError} of
- {[],[]} ->
- [[],bad_options];
- {_,_} ->
- [NameError,OptsError]
+ case {NameError, OptsError, Cause} of
+ {[], [], already_exists} ->
+ [name_already_exists, []];
+ {[], [], _} ->
+ [[], bad_options];
+ {_, _, _} ->
+ [NameError, OptsError]
end;
format_ets_error(prev, Args, Cause) ->
format_default(bad_key, Args, Cause);
@@ -1008,6 +1038,8 @@ expand_error(bad_update_op) ->
<<"not a valid update operation">>;
expand_error(bitstring) ->
<<"is a bitstring (expected a binary)">>;
+expand_error(calling_self) ->
+ <<"the device is not allowed to be the current process">>;
expand_error(counter_not_integer) ->
<<"the value in the given position, in the object, is not an integer">>;
expand_error(dead_process) ->
diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl
index c689be30d8..da188c1bf1 100644
--- a/lib/stdlib/src/erl_tar.erl
+++ b/lib/stdlib/src/erl_tar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -324,10 +324,17 @@ do_open(Name, Mode) when is_list(Mode) ->
open1({binary,Bin0}=Handle, read, _Raw, Opts) when is_binary(Bin0) ->
Bin = case lists:member(compressed, Opts) of
true ->
+ %% emulate file:open with Modes = [compressed_one ...]
+ Z = zlib:open(),
+ zlib:inflateInit(Z, 31, cut),
try
- zlib:gunzip(Bin0)
+ IoList = zlib:inflate(Z, Bin0),
+ zlib:inflateEnd(Z),
+ iolist_to_binary(IoList)
catch
_:_ -> Bin0
+ after
+ zlib:close(Z)
end;
false ->
Bin0
@@ -354,7 +361,13 @@ open1({file, Fd}=Handle, read, [raw], Opts) ->
end;
open1({file, _Fd}=Handle, read, [], _Opts) ->
{error, {Handle, {incompatible_option, cooked}}};
-open1(Name, Access, Raw, Opts) when is_list(Name) or is_binary(Name) ->
+open1(Name, Access, Raw, Opts0) when is_list(Name); is_binary(Name) ->
+ Opts = case lists:member(compressed, Opts0) andalso Access == read of
+ true ->
+ [compressed_one | (Opts0 -- [compressed])];
+ false ->
+ Opts0
+ end,
case file:open(Name, Raw ++ [binary, Access|Opts]) of
{ok, File} ->
{ok, #reader{handle=File,access=Access,func=fun file_op/2}};
@@ -1019,11 +1032,14 @@ do_get_format({error, _} = Err, _Bin) ->
do_get_format(#header_v7{}=V7, Bin)
when is_binary(Bin), byte_size(Bin) =:= ?BLOCK_SIZE ->
Checksum = parse_octal(V7#header_v7.checksum),
- Chk1 = compute_checksum(Bin),
- Chk2 = compute_signed_checksum(Bin),
- if Checksum =/= Chk1 andalso Checksum =/= Chk2 ->
+ IsBadChecksum = case compute_checksum(Bin) of
+ Checksum -> false;
+ _ -> compute_signed_checksum(Bin) =/= Checksum
+ end,
+ case IsBadChecksum of
+ true ->
?FORMAT_UNKNOWN;
- true ->
+ false ->
%% guess magic
Ustar = to_ustar(V7, Bin),
Star = to_star(V7, Bin),
@@ -1203,6 +1219,9 @@ compute_signed_checksum(<<H1:?V7_CHKSUM/binary,
%% Returns the checksum of a binary.
checksum(Bin) -> checksum(Bin, 0).
+
+checksum(<<A/unsigned,B/unsigned,C/unsigned,D/unsigned,Rest/binary>>, Sum) ->
+ checksum(Rest, Sum+A+B+C+D);
checksum(<<A/unsigned,Rest/binary>>, Sum) ->
checksum(Rest, Sum+A);
checksum(<<>>, Sum) -> Sum.
@@ -1251,39 +1270,40 @@ parse_numeric(<<First, _/binary>> = Bin) ->
parse_octal(Bin)
end.
-parse_octal(Bin) when is_binary(Bin) ->
+parse_octal(<<Bin/binary>>) ->
%% skip leading/trailing zero bytes and spaces
- do_parse_octal(Bin, <<>>).
-do_parse_octal(<<>>, <<>>) ->
- 0;
-do_parse_octal(<<>>, Acc) ->
- case io_lib:fread("~8u", binary:bin_to_list(Acc)) of
- {error, _} -> throw({error, invalid_tar_checksum});
- {ok, [Octal], []} -> Octal;
- {ok, _, _} -> throw({error, invalid_tar_checksum})
- end;
-do_parse_octal(<<$\s,Rest/binary>>, Acc) ->
+ do_parse_octal(Bin, 0).
+
+do_parse_octal(<<$\s, Rest/binary>>, Acc) ->
do_parse_octal(Rest, Acc);
do_parse_octal(<<0, Rest/binary>>, Acc) ->
do_parse_octal(Rest, Acc);
do_parse_octal(<<C, Rest/binary>>, Acc) ->
- do_parse_octal(Rest, <<Acc/binary, C>>).
+ Digit = C - $0,
+ case Digit band 7 of
+ Digit ->
+ do_parse_octal(Rest, Acc bsl 3 bor Digit);
+ _ ->
+ throw({error, invalid_tar_checksum})
+ end;
+do_parse_octal(<<>>, Acc) ->
+ Acc.
parse_string(Bin) when is_binary(Bin) ->
- do_parse_string(Bin, <<>>).
-do_parse_string(<<>>, Acc) ->
- case unicode:characters_to_list(Acc) of
+ N = strlen(Bin, 0),
+ <<Prefix:N/binary,_/binary>> = Bin,
+ case unicode:characters_to_list(Prefix) of
Str when is_list(Str) ->
Str;
{incomplete, _Str, _Rest} ->
- binary:bin_to_list(Acc);
+ binary_to_list(Bin);
{error, _Str, _Rest} ->
throw({error, {bad_header, invalid_string}})
- end;
-do_parse_string(<<0, _/binary>>, Acc) ->
- do_parse_string(<<>>, Acc);
-do_parse_string(<<C, Rest/binary>>, Acc) ->
- do_parse_string(Rest, <<Acc/binary, C>>).
+ end.
+
+strlen(<<>>, N) -> N;
+strlen(<<0, _/binary>>, N) -> N;
+strlen(<<_, Rest/binary>>, N) -> strlen(Rest, N + 1).
convert_header(Bin, #reader{pos=Pos}=Reader)
when byte_size(Bin) =:= ?BLOCK_SIZE, (Pos rem ?BLOCK_SIZE) =:= 0 ->
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index 224937d4d3..979a75b231 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,22 +42,27 @@
-export([i/0, i/1, i/2, i/3]).
--export_type([tab/0, tid/0, match_spec/0, comp_match_spec/0, match_pattern/0]).
+-export_type([table/0, table_access/0, table_type/0,
+ tid/0, match_spec/0, compiled_match_spec/0, match_pattern/0]).
%%-----------------------------------------------------------------------------
--type access() :: public | protected | private.
--type tab() :: atom() | tid().
--type type() :: set | ordered_set | bag | duplicate_bag.
--type continuation() :: '$end_of_table'
- | {tab(),integer(),integer(),comp_match_spec(),list(),integer()}
- | {tab(),_,_,integer(),comp_match_spec(),list(),integer(),integer()}.
+-type table_access() :: public | protected | private.
+-type table() :: atom() | tid().
+-type table_type() :: set | ordered_set | bag | duplicate_bag.
+-type continuation() :: '$end_of_table'
+ | {table(),integer(),integer(),compiled_match_spec(),list(),integer()}
+ | {table(),_,_,integer(),compiled_match_spec(),list(),integer(),integer()}.
--opaque tid() :: reference().
+-opaque tid() :: reference().
-type match_pattern() :: atom() | tuple().
-type match_spec() :: [{match_pattern(), [_], [_]}].
+%% Keep for backwards compatibility
+-export_type([tab/0, comp_match_spec/0]).
+-type tab() :: table().
+
%%-----------------------------------------------------------------------------
%%% BIFs
@@ -80,8 +85,8 @@
internal_delete_all/2,
internal_select_delete/2]).
--spec all() -> [Tab] when
- Tab :: tab().
+-spec all() -> [Table] when
+ Table :: table().
all() ->
receive_all(ets:internal_request_all(),
@@ -101,57 +106,57 @@ receive_all(Ref, N, All) ->
internal_request_all() ->
erlang:nif_error(undef).
--spec delete(Tab) -> true when
- Tab :: tab().
+-spec delete(Table) -> true when
+ Table :: table().
delete(_) ->
erlang:nif_error(undef).
--spec delete(Tab, Key) -> true when
- Tab :: tab(),
+-spec delete(Table, Key) -> true when
+ Table :: table(),
Key :: term().
delete(_, _) ->
erlang:nif_error(undef).
--spec delete_all_objects(Tab) -> true when
- Tab :: tab().
+-spec delete_all_objects(Table) -> true when
+ Table :: table().
-delete_all_objects(Tab) ->
- _ = ets:internal_delete_all(Tab, undefined),
+delete_all_objects(Table) ->
+ _ = ets:internal_delete_all(Table, undefined),
true.
--spec internal_delete_all(Tab, undefined) -> NumDeleted when
- Tab :: tab(),
+-spec internal_delete_all(Table, undefined) -> NumDeleted when
+ Table :: table(),
NumDeleted :: non_neg_integer().
internal_delete_all(_, _) ->
erlang:nif_error(undef).
--spec delete_object(Tab, Object) -> true when
- Tab :: tab(),
+-spec delete_object(Table, Object) -> true when
+ Table :: table(),
Object :: tuple().
delete_object(_, _) ->
erlang:nif_error(undef).
--spec first(Tab) -> Key | '$end_of_table' when
- Tab :: tab(),
+-spec first(Table) -> Key | '$end_of_table' when
+ Table :: table(),
Key :: term().
first(_) ->
erlang:nif_error(undef).
--spec give_away(Tab, Pid, GiftData) -> true when
- Tab :: tab(),
+-spec give_away(Table, Pid, GiftData) -> true when
+ Table :: table(),
Pid :: pid(),
GiftData :: term().
give_away(_, _, _) ->
erlang:nif_error(undef).
--spec info(Tab) -> InfoList | undefined when
- Tab :: tab(),
+-spec info(Table) -> InfoList | undefined when
+ Table :: table(),
InfoList :: [InfoTuple],
InfoTuple :: {compressed, boolean()}
| {decentralized_counters, boolean()}
@@ -163,17 +168,17 @@ give_away(_, _, _) ->
| {named_table, boolean()}
| {node, node()}
| {owner, pid()}
- | {protection, access()}
+ | {protection, table_access()}
| {size, non_neg_integer()}
- | {type, type()}
+ | {type, table_type()}
| {write_concurrency, boolean()}
| {read_concurrency, boolean()}.
info(_) ->
erlang:nif_error(undef).
--spec info(Tab, Item) -> Value | undefined when
- Tab :: tab(),
+-spec info(Table, Item) -> Value | undefined when
+ Table :: table(),
Item :: binary | compressed | decentralized_counters | fixed | heir | id | keypos | memory
| name | named_table | node | owner | protection
| safe_fixed | safe_fixed_monotonic_time | size | stats | type
@@ -183,15 +188,15 @@ info(_) ->
info(_, _) ->
erlang:nif_error(undef).
--spec insert(Tab, ObjectOrObjects) -> true when
- Tab :: tab(),
+-spec insert(Table, ObjectOrObjects) -> true when
+ Table :: table(),
ObjectOrObjects :: tuple() | [tuple()].
insert(_, _) ->
erlang:nif_error(undef).
--spec insert_new(Tab, ObjectOrObjects) -> boolean() when
- Tab :: tab(),
+-spec insert_new(Table, ObjectOrObjects) -> boolean() when
+ Table :: table(),
ObjectOrObjects :: tuple() | [tuple()].
insert_new(_, _) ->
@@ -203,23 +208,23 @@ insert_new(_, _) ->
is_compiled_ms(_) ->
erlang:nif_error(undef).
--spec last(Tab) -> Key | '$end_of_table' when
- Tab :: tab(),
+-spec last(Table) -> Key | '$end_of_table' when
+ Table :: table(),
Key :: term().
last(_) ->
erlang:nif_error(undef).
--spec lookup(Tab, Key) -> [Object] when
- Tab :: tab(),
+-spec lookup(Table, Key) -> [Object] when
+ Table :: table(),
Key :: term(),
Object :: tuple().
lookup(_, _) ->
erlang:nif_error(undef).
--spec lookup_element(Tab, Key, Pos) -> Elem when
- Tab :: tab(),
+-spec lookup_element(Table, Key, Pos) -> Elem when
+ Table :: table(),
Key :: term(),
Pos :: pos_integer(),
Elem :: term() | [term()].
@@ -227,17 +232,17 @@ lookup(_, _) ->
lookup_element(_, _, _) ->
erlang:nif_error(undef).
--spec match(Tab, Pattern) -> [Match] when
- Tab :: tab(),
+-spec match(Table, Pattern) -> [Match] when
+ Table :: table(),
Pattern :: match_pattern(),
Match :: [term()].
match(_, _) ->
erlang:nif_error(undef).
--spec match(Tab, Pattern, Limit) -> {[Match], Continuation} |
+-spec match(Table, Pattern, Limit) -> {[Match], Continuation} |
'$end_of_table' when
- Tab :: tab(),
+ Table :: table(),
Pattern :: match_pattern(),
Limit :: pos_integer(),
Match :: [term()],
@@ -254,17 +259,17 @@ match(_, _, _) ->
match(_) ->
erlang:nif_error(undef).
--spec match_object(Tab, Pattern) -> [Object] when
- Tab :: tab(),
+-spec match_object(Table, Pattern) -> [Object] when
+ Table :: table(),
Pattern :: match_pattern(),
Object :: tuple().
match_object(_, _) ->
erlang:nif_error(undef).
--spec match_object(Tab, Pattern, Limit) -> {[Object], Continuation} |
+-spec match_object(Table, Pattern, Limit) -> {[Object], Continuation} |
'$end_of_table' when
- Tab :: tab(),
+ Table :: table(),
Pattern :: match_pattern(),
Limit :: pos_integer(),
Object :: tuple(),
@@ -283,33 +288,34 @@ match_object(_) ->
-spec match_spec_compile(MatchSpec) -> CompiledMatchSpec when
MatchSpec :: match_spec(),
- CompiledMatchSpec :: comp_match_spec().
+ CompiledMatchSpec :: compiled_match_spec().
match_spec_compile(_) ->
erlang:nif_error(undef).
-spec match_spec_run_r(List, CompiledMatchSpec, list()) -> list() when
List :: [term()],
- CompiledMatchSpec :: comp_match_spec().
+ CompiledMatchSpec :: compiled_match_spec().
match_spec_run_r(_, _, _) ->
erlang:nif_error(undef).
--spec member(Tab, Key) -> boolean() when
- Tab :: tab(),
+-spec member(Table, Key) -> boolean() when
+ Table :: table(),
Key :: term().
member(_, _) ->
erlang:nif_error(undef).
--spec new(Name, Options) -> tid() | atom() when
+-spec new(Name, Options) -> table() 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()}
+ Type :: table_type(),
+ Access :: table_access(),
+ WriteConcurrencyAlternative :: boolean() | auto,
+ Tweaks :: {write_concurrency, WriteConcurrencyAlternative}
| {read_concurrency, boolean()}
| {decentralized_counters, boolean()}
| compressed,
@@ -319,16 +325,16 @@ member(_, _) ->
new(_, _) ->
erlang:nif_error(undef).
--spec next(Tab, Key1) -> Key2 | '$end_of_table' when
- Tab :: tab(),
+-spec next(Table, Key1) -> Key2 | '$end_of_table' when
+ Table :: table(),
Key1 :: term(),
Key2 :: term().
next(_, _) ->
erlang:nif_error(undef).
--spec prev(Tab, Key1) -> Key2 | '$end_of_table' when
- Tab :: tab(),
+-spec prev(Table, Key1) -> Key2 | '$end_of_table' when
+ Table :: table(),
Key1 :: term(),
Key2 :: term().
@@ -336,31 +342,31 @@ prev(_, _) ->
erlang:nif_error(undef).
%% Shadowed by erl_bif_types: ets:rename/2
--spec rename(Tab, Name) -> Name when
- Tab :: tab(),
+-spec rename(Table, Name) -> Name when
+ Table :: table(),
Name :: atom().
rename(_, _) ->
erlang:nif_error(undef).
--spec safe_fixtable(Tab, Fix) -> true when
- Tab :: tab(),
+-spec safe_fixtable(Table, Fix) -> true when
+ Table :: table(),
Fix :: boolean().
safe_fixtable(_, _) ->
erlang:nif_error(undef).
--spec select(Tab, MatchSpec) -> [Match] when
- Tab :: tab(),
+-spec select(Table, MatchSpec) -> [Match] when
+ Table :: table(),
MatchSpec :: match_spec(),
Match :: term().
select(_, _) ->
erlang:nif_error(undef).
--spec select(Tab, MatchSpec, Limit) -> {[Match],Continuation} |
+-spec select(Table, MatchSpec, Limit) -> {[Match],Continuation} |
'$end_of_table' when
- Tab :: tab(),
+ Table :: table(),
MatchSpec :: match_spec(),
Limit :: pos_integer(),
Match :: term(),
@@ -376,51 +382,51 @@ select(_, _, _) ->
select(_) ->
erlang:nif_error(undef).
--spec select_count(Tab, MatchSpec) -> NumMatched when
- Tab :: tab(),
+-spec select_count(Table, MatchSpec) -> NumMatched when
+ Table :: table(),
MatchSpec :: match_spec(),
NumMatched :: non_neg_integer().
select_count(_, _) ->
erlang:nif_error(undef).
--spec select_delete(Tab, MatchSpec) -> NumDeleted when
- Tab :: tab(),
+-spec select_delete(Table, MatchSpec) -> NumDeleted when
+ Table :: table(),
MatchSpec :: match_spec(),
NumDeleted :: non_neg_integer().
-select_delete(Tab, [{'_',[],[true]}]) ->
- ets:internal_delete_all(Tab, undefined);
-select_delete(Tab, MatchSpec) ->
- ets:internal_select_delete(Tab, MatchSpec).
+select_delete(Table, [{'_',[],[true]}]) ->
+ ets:internal_delete_all(Table, undefined);
+select_delete(Table, MatchSpec) ->
+ ets:internal_select_delete(Table, MatchSpec).
--spec internal_select_delete(Tab, MatchSpec) -> NumDeleted when
- Tab :: tab(),
+-spec internal_select_delete(Table, MatchSpec) -> NumDeleted when
+ Table :: table(),
MatchSpec :: match_spec(),
NumDeleted :: non_neg_integer().
internal_select_delete(_, _) ->
erlang:nif_error(undef).
--spec select_replace(Tab, MatchSpec) -> NumReplaced when
- Tab :: tab(),
+-spec select_replace(Table, MatchSpec) -> NumReplaced when
+ Table :: table(),
MatchSpec :: match_spec(),
NumReplaced :: non_neg_integer().
select_replace(_, _) ->
erlang:nif_error(undef).
--spec select_reverse(Tab, MatchSpec) -> [Match] when
- Tab :: tab(),
+-spec select_reverse(Table, MatchSpec) -> [Match] when
+ Table :: table(),
MatchSpec :: match_spec(),
Match :: term().
select_reverse(_, _) ->
erlang:nif_error(undef).
--spec select_reverse(Tab, MatchSpec, Limit) -> {[Match],Continuation} |
+-spec select_reverse(Table, MatchSpec, Limit) -> {[Match],Continuation} |
'$end_of_table' when
- Tab :: tab(),
+ Table :: table(),
MatchSpec :: match_spec(),
Limit :: pos_integer(),
Match :: term(),
@@ -437,8 +443,8 @@ select_reverse(_, _, _) ->
select_reverse(_) ->
erlang:nif_error(undef).
--spec setopts(Tab, Opts) -> true when
- Tab :: tab(),
+-spec setopts(Table, Opts) -> true when
+ Table :: table(),
Opts :: Opt | [Opt],
Opt :: {heir, pid(), HeirData} | {heir,none},
HeirData :: term().
@@ -446,24 +452,24 @@ select_reverse(_) ->
setopts(_, _) ->
erlang:nif_error(undef).
--spec slot(Tab, I) -> [Object] | '$end_of_table' when
- Tab :: tab(),
+-spec slot(Table, I) -> [Object] | '$end_of_table' when
+ Table :: table(),
I :: non_neg_integer(),
Object :: tuple().
slot(_, _) ->
erlang:nif_error(undef).
--spec take(Tab, Key) -> [Object] when
- Tab :: tab(),
+-spec take(Table, Key) -> [Object] when
+ Table :: table(),
Key :: term(),
Object :: tuple().
take(_, _) ->
erlang:nif_error(undef).
--spec update_counter(Tab, Key, UpdateOp) -> Result when
- Tab :: tab(),
+-spec update_counter(Table, Key, UpdateOp) -> Result when
+ Table :: table(),
Key :: term(),
UpdateOp :: {Pos, Incr} | {Pos, Incr, Threshold, SetValue},
Pos :: integer(),
@@ -471,8 +477,8 @@ take(_, _) ->
Threshold :: integer(),
SetValue :: integer(),
Result :: integer();
- (Tab, Key, [UpdateOp]) -> [Result] when
- Tab :: tab(),
+ (Table, Key, [UpdateOp]) -> [Result] when
+ Table :: table(),
Key :: term(),
UpdateOp :: {Pos, Incr} | {Pos, Incr, Threshold, SetValue},
Pos :: integer(),
@@ -480,8 +486,8 @@ take(_, _) ->
Threshold :: integer(),
SetValue :: integer(),
Result :: integer();
- (Tab, Key, Incr) -> Result when
- Tab :: tab(),
+ (Table, Key, Incr) -> Result when
+ Table :: table(),
Key :: term(),
Incr :: integer(),
Result :: integer().
@@ -489,8 +495,8 @@ take(_, _) ->
update_counter(_, _, _) ->
erlang:nif_error(undef).
--spec update_counter(Tab, Key, UpdateOp, Default) -> Result when
- Tab :: tab(),
+-spec update_counter(Table, Key, UpdateOp, Default) -> Result when
+ Table :: table(),
Key :: term(),
UpdateOp :: {Pos, Incr}
| {Pos, Incr, Threshold, SetValue},
@@ -500,8 +506,8 @@ update_counter(_, _, _) ->
SetValue :: integer(),
Result :: integer(),
Default :: tuple();
- (Tab, Key, [UpdateOp], Default) -> [Result] when
- Tab :: tab(),
+ (Table, Key, [UpdateOp], Default) -> [Result] when
+ Table :: table(),
Key :: term(),
UpdateOp :: {Pos, Incr}
| {Pos, Incr, Threshold, SetValue},
@@ -511,8 +517,8 @@ update_counter(_, _, _) ->
SetValue :: integer(),
Result :: integer(),
Default :: tuple();
- (Tab, Key, Incr, Default) -> Result when
- Tab :: tab(),
+ (Table, Key, Incr, Default) -> Result when
+ Table :: table(),
Key :: term(),
Incr :: integer(),
Result :: integer(),
@@ -521,13 +527,13 @@ update_counter(_, _, _) ->
update_counter(_, _, _, _) ->
erlang:nif_error(undef).
--spec update_element(Tab, Key, ElementSpec :: {Pos, Value}) -> boolean() when
- Tab :: tab(),
+-spec update_element(Table, Key, ElementSpec :: {Pos, Value}) -> boolean() when
+ Table :: table(),
Key :: term(),
Pos :: pos_integer(),
Value :: term();
- (Tab, Key, ElementSpec :: [{Pos, Value}]) -> boolean() when
- Tab :: tab(),
+ (Table, Key, ElementSpec :: [{Pos, Value}]) -> boolean() when
+ Table :: table(),
Key :: term(),
Pos :: pos_integer(),
Value :: term().
@@ -542,11 +548,12 @@ whereis(_) ->
%%% End of BIFs
--opaque comp_match_spec() :: reference().
+-opaque compiled_match_spec() :: reference().
+-type comp_match_spec() :: compiled_match_spec().
-spec match_spec_run(List, CompiledMatchSpec) -> list() when
List :: [term()],
- CompiledMatchSpec :: comp_match_spec().
+ CompiledMatchSpec :: compiled_match_spec().
match_spec_run(List, CompiledMS) ->
lists:reverse(ets:match_spec_run_r(List, CompiledMS, [])).
@@ -613,9 +620,9 @@ fun2ms(ShellFun) when is_function(ShellFun) ->
shell]}})
end.
--spec foldl(Function, Acc0, Tab) -> Acc1 when
+-spec foldl(Function, Acc0, Table) -> Acc1 when
Function :: fun((Element :: term(), AccIn) -> AccOut),
- Tab :: tab(),
+ Table :: table(),
Acc0 :: term(),
Acc1 :: term(),
AccIn :: term(),
@@ -640,9 +647,9 @@ do_foldl(F, Accu0, Key, T) ->
ets:next(T, Key), T)
end.
--spec foldr(Function, Acc0, Tab) -> Acc1 when
+-spec foldr(Function, Acc0, Table) -> Acc1 when
Function :: fun((Element :: term(), AccIn) -> AccOut),
- Tab :: tab(),
+ Table :: table(),
Acc0 :: term(),
Acc1 :: term(),
AccIn :: term(),
@@ -667,8 +674,8 @@ do_foldr(F, Accu0, Key, T) ->
ets:prev(T, Key), T)
end.
--spec from_dets(Tab, DetsTab) -> 'true' when
- Tab :: tab(),
+-spec from_dets(Table, DetsTab) -> 'true' when
+ Table :: table(),
DetsTab :: dets:tab_name().
from_dets(EtsTable, DetsTable) ->
@@ -685,8 +692,8 @@ from_dets(EtsTable, DetsTable) ->
erlang:error(Unexpected,[EtsTable,DetsTable])
end.
--spec to_dets(Tab, DetsTab) -> DetsTab when
- Tab :: tab(),
+-spec to_dets(Table, DetsTab) -> DetsTab when
+ Table :: table(),
DetsTab :: dets:tab_name().
to_dets(EtsTable, DetsTable) ->
@@ -717,8 +724,8 @@ test_ms(Term, MS) ->
Error
end.
--spec init_table(Tab, InitFun) -> 'true' when
- Tab :: tab(),
+-spec init_table(Table, InitFun) -> 'true' when
+ Table :: table(),
InitFun :: fun((Arg) -> Res),
Arg :: 'read' | 'close',
Res :: 'end_of_input' | {Objects :: [term()], InitFun} | term().
@@ -746,8 +753,8 @@ init_table_sub(Table, [H|T]) ->
ets:insert(Table, H),
init_table_sub(Table, T).
--spec match_delete(Tab, Pattern) -> 'true' when
- Tab :: tab(),
+-spec match_delete(Table, Pattern) -> 'true' when
+ Table :: table(),
Pattern :: match_pattern().
match_delete(Table, Pattern) ->
@@ -756,8 +763,8 @@ match_delete(Table, Pattern) ->
%% Produce a list of tuples from a table
--spec tab2list(Tab) -> [Object] when
- Tab :: tab(),
+-spec tab2list(Table) -> [Object] when
+ Table :: table(),
Object :: tuple().
tab2list(T) ->
@@ -780,23 +787,23 @@ tab2list(T) ->
sync = false :: boolean()
}).
--spec tab2file(Tab, Filename) -> 'ok' | {'error', Reason} when
- Tab :: tab(),
+-spec tab2file(Table, Filename) -> 'ok' | {'error', Reason} when
+ Table :: table(),
Filename :: file:name(),
Reason :: term().
-tab2file(Tab, File) ->
- tab2file(Tab, File, []).
+tab2file(Table, File) ->
+ tab2file(Table, File, []).
--spec tab2file(Tab, Filename, Options) -> 'ok' | {'error', Reason} when
- Tab :: tab(),
+-spec tab2file(Table, Filename, Options) -> 'ok' | {'error', Reason} when
+ Table :: table(),
Filename :: file:name(),
Options :: [Option],
Option :: {'extended_info', [ExtInfo]} | {'sync', boolean()},
ExtInfo :: 'md5sum' | 'object_count',
Reason :: term().
-tab2file(Tab, File, Options) ->
+tab2file(Table, File, Options) ->
try
{ok, FtOptions} = parse_ft_options(Options),
_ = file:delete(File),
@@ -812,9 +819,9 @@ tab2file(Tab, File, Options) ->
throw(Reason)
end,
try
- Info0 = case ets:info(Tab) of
+ Info0 = case ets:info(Table) of
undefined ->
- %% erlang:error(badarg, [Tab, File, Options]);
+ %% erlang:error(badarg, [Table, File, Options]);
throw(badtab);
I ->
I
@@ -845,14 +852,14 @@ tab2file(Tab, File, Options) ->
end,
true}
end,
- ets:safe_fixtable(Tab,true),
+ ets:safe_fixtable(Table,true),
{NewState1,Num} = try
NewState = LogFun(InitState,Info),
dump_file(
- ets:select(Tab,[{'_',[],['$_']}],100),
+ ets:select(Table,[{'_',[],['$_']}],100),
LogFun, NewState, 0)
after
- (catch ets:safe_fixtable(Tab,false))
+ (catch ets:safe_fixtable(Table,false))
end,
EndInfo =
case FtOptions#filetab_options.object_count of
@@ -967,24 +974,24 @@ parse_ft_info_options(_,Malformed) ->
%% Opt := {verify,boolean()}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec file2tab(Filename) -> {'ok', Tab} | {'error', Reason} when
+-spec file2tab(Filename) -> {'ok', Table} | {'error', Reason} when
Filename :: file:name(),
- Tab :: tab(),
+ Table :: table(),
Reason :: term().
file2tab(File) ->
file2tab(File, []).
--spec file2tab(Filename, Options) -> {'ok', Tab} | {'error', Reason} when
+-spec file2tab(Filename, Options) -> {'ok', Table} | {'error', Reason} when
Filename :: file:name(),
- Tab :: tab(),
+ Table :: table(),
Options :: [Option],
Option :: {'verify', boolean()},
Reason :: term().
file2tab(File, Opts) ->
try
- {ok,Verify,TabArg} = parse_f2t_opts(Opts,false,[]),
+ {ok,Verify,TableArg} = parse_f2t_opts(Opts,false,[]),
Name = make_ref(),
{ok, Name} =
case disk_log:open([{name, Name},
@@ -1019,7 +1026,7 @@ file2tab(File, Opts) ->
true ->
ok
end,
- {ok, Tab, HeadCount} = create_tab(FullHeader, TabArg),
+ {ok, Table, HeadCount} = create_tab(FullHeader, TableArg),
StrippedOptions =
case Verify of
true ->
@@ -1061,17 +1068,17 @@ file2tab(File, Opts) ->
{false,0,[],DLContext}}
end,
try
- do_read_and_verify(ReadFun,InitState,Tab,
+ do_read_and_verify(ReadFun,InitState,Table,
StrippedOptions,HeadCount,Verify)
catch
throw:TReason ->
- ets:delete(Tab),
+ ets:delete(Table),
throw(TReason);
exit:ExReason ->
- ets:delete(Tab),
+ ets:delete(Table),
exit(ExReason);
error:ErReason:StackTrace ->
- ets:delete(Tab),
+ ets:delete(Table),
erlang:raise(error,ErReason,StackTrace)
end
after
@@ -1084,8 +1091,8 @@ file2tab(File, Opts) ->
{error,ExReason2}
end.
-do_read_and_verify(ReadFun,InitState,Tab,FtOptions,HeadCount,Verify) ->
- case load_table(ReadFun,InitState,Tab) of
+do_read_and_verify(ReadFun,InitState,Table,FtOptions,HeadCount,Verify) ->
+ case load_table(ReadFun,InitState,Table) of
{ok,{_,FinalCount,[],_}} ->
case {FtOptions#filetab_options.md5sum,
FtOptions#filetab_options.object_count} of
@@ -1104,7 +1111,7 @@ do_read_and_verify(ReadFun,InitState,Tab,FtOptions,HeadCount,Verify) ->
_ ->
throw(badfile)
end,
- {ok,Tab};
+ {ok,Table};
{ok,{FinalMD5State,FinalCount,['$end_of_table',LastInfo],_}} ->
ECount = case lists:keyfind(count,1,LastInfo) of
{count,N} ->
@@ -1152,17 +1159,17 @@ do_read_and_verify(ReadFun,InitState,Tab,FtOptions,HeadCount,Verify) ->
ok
end
end,
- {ok,Tab}
+ {ok,Table}
end.
-parse_f2t_opts([],Verify,Tab) ->
- {ok,Verify,Tab};
-parse_f2t_opts([{verify, true}|T],_OV,Tab) ->
- parse_f2t_opts(T,true,Tab);
-parse_f2t_opts([{verify,false}|T],OV,Tab) ->
- parse_f2t_opts(T,OV,Tab);
-parse_f2t_opts([{table,Tab}|T],OV,[]) ->
- parse_f2t_opts(T,OV,Tab);
+parse_f2t_opts([],Verify,Table) ->
+ {ok,Verify,Table};
+parse_f2t_opts([{verify, true}|T],_OV,Table) ->
+ parse_f2t_opts(T,true,Table);
+parse_f2t_opts([{verify,false}|T],OV,Table) ->
+ parse_f2t_opts(T,OV,Table);
+parse_f2t_opts([{table,Table}|T],OV,[]) ->
+ parse_f2t_opts(T,OV,Table);
parse_f2t_opts([Unexpected|_],_,_) ->
throw({unknown_option,Unexpected});
parse_f2t_opts(Malformed,_,_) ->
@@ -1331,17 +1338,17 @@ scan_for_endinfo([Term|T], Count) ->
{NewLast,NCount,Rest} = scan_for_endinfo(T, Count+1),
{NewLast,NCount,[Term | Rest]}.
-load_table(ReadFun, State, Tab) ->
+load_table(ReadFun, State, Table) ->
{NewState,NewData} = ReadFun(State),
case NewData of
[] ->
{ok,NewState};
List ->
- ets:insert(Tab, List),
- load_table(ReadFun, NewState, Tab)
+ ets:insert(Table, List),
+ load_table(ReadFun, NewState, Table)
end.
-create_tab(I, TabArg) ->
+create_tab(I, TableArg) ->
{name, Name} = lists:keyfind(name, 1, I),
{type, Type} = lists:keyfind(type, 1, I),
{protection, P} = lists:keyfind(protection, 1, I),
@@ -1365,16 +1372,16 @@ create_tab(I, TabArg) ->
{read_concurrency, _}=Rcc -> [Rcc | L4];
false -> L4
end,
- case TabArg of
+ case TableArg of
[] ->
try
- Tab = ets:new(Name, L5),
- {ok, Tab, Sz}
+ Table = ets:new(Name, L5),
+ {ok, Table, Sz}
catch _:_ ->
throw(cannot_create_table)
end;
_ ->
- {ok, TabArg, Sz}
+ {ok, TableArg, Sz}
end.
@@ -1446,15 +1453,15 @@ tabfile_info(File) when is_list(File) ; is_atom(File) ->
{error,ExReason}
end.
--spec table(Tab) -> QueryHandle when
- Tab :: tab(),
+-spec table(Table) -> QueryHandle when
+ Table :: table(),
QueryHandle :: qlc:query_handle().
-table(Tab) ->
- table(Tab, []).
+table(Table) ->
+ table(Table, []).
--spec table(Tab, Options) -> QueryHandle when
- Tab :: tab(),
+-spec table(Table, Options) -> QueryHandle when
+ Table :: table(),
QueryHandle :: qlc:query_handle(),
Options :: [Option] | Option,
Option :: {'n_objects', NObjects}
@@ -1463,25 +1470,25 @@ table(Tab) ->
TraverseMethod :: 'first_next' | 'last_prev'
| 'select' | {'select', MatchSpec :: match_spec()}.
-table(Tab, Opts) ->
+table(Table, Opts) ->
case options(Opts, [traverse, n_objects]) of
{badarg,_} ->
- erlang:error(badarg, [Tab, Opts]);
+ erlang:error(badarg, [Table, Opts]);
[[Traverse, NObjs], QlcOptions] ->
TF = case Traverse of
first_next ->
- fun() -> qlc_next(Tab, ets:first(Tab)) end;
+ fun() -> qlc_next(Table, ets:first(Table)) end;
last_prev ->
- fun() -> qlc_prev(Tab, ets:last(Tab)) end;
+ fun() -> qlc_prev(Table, ets:last(Table)) end;
select ->
- fun(MS) -> qlc_select(ets:select(Tab, MS, NObjs)) end;
+ fun(MS) -> qlc_select(ets:select(Table, MS, NObjs)) end;
{select, MS} ->
- fun() -> qlc_select(ets:select(Tab, MS, NObjs)) end
+ fun() -> qlc_select(ets:select(Table, MS, NObjs)) end
end,
- PreFun = fun(_) -> ets:safe_fixtable(Tab, true) end,
- PostFun = fun() -> ets:safe_fixtable(Tab, false) end,
- InfoFun = fun(Tag) -> table_info(Tab, Tag) end,
- KeyEquality = case ets:info(Tab, type) of
+ PreFun = fun(_) -> ets:safe_fixtable(Table, true) end,
+ PostFun = fun() -> ets:safe_fixtable(Table, false) end,
+ InfoFun = fun(Tag) -> table_info(Table, Tag) end,
+ KeyEquality = case ets:info(Table, type) of
ordered_set -> '==';
_ -> '=:='
end,
@@ -1491,28 +1498,28 @@ table(Tab, Opts) ->
undefined;
_ ->
fun(_Pos, [K]) ->
- ets:lookup(Tab, K);
+ ets:lookup(Table, K);
(_Pos, Ks) ->
- lists:flatmap(fun(K) -> ets:lookup(Tab, K)
+ lists:flatmap(fun(K) -> ets:lookup(Table, K)
end, Ks)
end
end,
FormatFun =
fun({all, _NElements, _ElementFun}) ->
- As = [Tab | [Opts || _ <- [[]], Opts =/= []]],
+ As = [Table | [Opts || _ <- [[]], Opts =/= []]],
{?MODULE, table, As};
({match_spec, MS}) ->
{?MODULE, table,
- [Tab, [{traverse, {select, MS}} |
+ [Table, [{traverse, {select, MS}} |
listify(Opts)]]};
({lookup, _KeyPos, [Value], _NElements, ElementFun}) ->
io_lib:format("~w:lookup(~w, ~w)",
- [?MODULE, Tab, ElementFun(Value)]);
+ [?MODULE, Table, ElementFun(Value)]);
({lookup, _KeyPos, Values, _NElements, ElementFun}) ->
Vals = [ElementFun(V) || V <- Values],
io_lib:format("lists:flatmap(fun(V) -> "
"~w:lookup(~w, V) end, ~w)",
- [?MODULE, Tab, Vals])
+ [?MODULE, Table, Vals])
end,
qlc:table(TF, [{pre_fun, PreFun}, {post_fun, PostFun},
{info_fun, InfoFun}, {format_fun, FormatFun},
@@ -1520,26 +1527,26 @@ table(Tab, Opts) ->
{lookup_fun, LookupFun}] ++ QlcOptions)
end.
-table_info(Tab, num_of_objects) ->
- ets:info(Tab, size);
-table_info(Tab, keypos) ->
- ets:info(Tab, keypos);
-table_info(Tab, is_unique_objects) ->
- ets:info(Tab, type) =/= duplicate_bag;
-table_info(Tab, is_sorted_key) ->
- ets:info(Tab, type) =:= ordered_set;
-table_info(_Tab, _) ->
+table_info(Table, num_of_objects) ->
+ ets:info(Table, size);
+table_info(Table, keypos) ->
+ ets:info(Table, keypos);
+table_info(Table, is_unique_objects) ->
+ ets:info(Table, type) =/= duplicate_bag;
+table_info(Table, is_sorted_key) ->
+ ets:info(Table, type) =:= ordered_set;
+table_info(_Table, _) ->
undefined.
-qlc_next(_Tab, '$end_of_table') ->
+qlc_next(_Table, '$end_of_table') ->
[];
-qlc_next(Tab, Key) ->
- ets:lookup(Tab, Key) ++ fun() -> qlc_next(Tab, ets:next(Tab, Key)) end.
+qlc_next(Table, Key) ->
+ ets:lookup(Table, Key) ++ fun() -> qlc_next(Table, ets:next(Table, Key)) end.
-qlc_prev(_Tab, '$end_of_table') ->
+qlc_prev(_Table, '$end_of_table') ->
[];
-qlc_prev(Tab, Key) ->
- ets:lookup(Tab, Key) ++ fun() -> qlc_prev(Tab, ets:prev(Tab, Key)) end.
+qlc_prev(Table, Key) ->
+ ets:lookup(Table, Key) ++ fun() -> qlc_prev(Table, ets:prev(Table, Key)) end.
qlc_select('$end_of_table') ->
[];
@@ -1604,20 +1611,20 @@ i() ->
tabs() ->
lists:sort(ets:all()).
-prinfo(Tab) ->
- case catch prinfo2(Tab) of
+prinfo(Table) ->
+ case catch prinfo2(Table) of
{'EXIT', _} ->
- io:format("~-10s ... unreadable \n", [to_string(Tab)]);
+ io:format("~-10s ... unreadable \n", [to_string(Table)]);
ok ->
ok
end.
-prinfo2(Tab) ->
- Name = ets:info(Tab, name),
- Type = ets:info(Tab, type),
- Size = ets:info(Tab, size),
- Mem = ets:info(Tab, memory),
- Owner = ets:info(Tab, owner),
- hform(Tab, Name, Type, Size, Mem, is_reg(Owner)).
+prinfo2(Table) ->
+ Name = ets:info(Table, name),
+ Type = ets:info(Table, type),
+ Size = ets:info(Table, size),
+ Mem = ets:info(Table, memory),
+ Owner = ets:info(Table, owner),
+ hform(Table, Name, Type, Size, Mem, is_reg(Owner)).
is_reg(Owner) ->
case process_info(Owner, registered_name) of
@@ -1651,69 +1658,69 @@ to_string(X) ->
lists:flatten(io_lib:format("~p", [X])).
%% view a specific table
--spec i(Tab) -> 'ok' when
- Tab :: tab().
+-spec i(Table) -> 'ok' when
+ Table :: table().
-i(Tab) ->
- i(Tab, 40).
+i(Table) ->
+ i(Table, 40).
--spec i(tab(), pos_integer()) -> 'ok'.
+-spec i(table(), pos_integer()) -> 'ok'.
-i(Tab, Height) ->
- i(Tab, Height, 80).
+i(Table, Height) ->
+ i(Table, Height, 80).
--spec i(tab(), pos_integer(), pos_integer()) -> 'ok'.
+-spec i(table(), pos_integer(), pos_integer()) -> 'ok'.
-i(Tab, Height, Width) ->
- First = ets:first(Tab),
- display_items(Height, Width, Tab, First, 1, 1).
+i(Table, Height, Width) ->
+ First = ets:first(Table),
+ display_items(Height, Width, Table, First, 1, 1).
-display_items(Height, Width, Tab, '$end_of_table', Turn, Opos) ->
+display_items(Height, Width, Table, '$end_of_table', Turn, Opos) ->
P = 'EOT (q)uit (p)Digits (k)ill /Regexp -->',
- choice(Height, Width, P, eot, Tab, '$end_of_table', Turn, Opos);
-display_items(Height, Width, Tab, Key, Turn, Opos) when Turn < Height ->
- do_display(Height, Width, Tab, Key, Turn, Opos);
-display_items(Height, Width, Tab, Key, Turn, Opos) when Turn >= Height ->
+ choice(Height, Width, P, eot, Table, '$end_of_table', Turn, Opos);
+display_items(Height, Width, Table, Key, Turn, Opos) when Turn < Height ->
+ do_display(Height, Width, Table, Key, Turn, Opos);
+display_items(Height, Width, Table, Key, Turn, Opos) when Turn >= Height ->
P = '(c)ontinue (q)uit (p)Digits (k)ill /Regexp -->',
- choice(Height, Width, P, normal, Tab, Key, Turn, Opos).
+ choice(Height, Width, P, normal, Table, Key, Turn, Opos).
-choice(Height, Width, P, Mode, Tab, Key, Turn, Opos) ->
+choice(Height, Width, P, Mode, Table, Key, Turn, Opos) ->
case get_line(P, "c\n") of
"c\n" when Mode =:= normal ->
- do_display(Height, Width, Tab, Key, 1, Opos);
+ do_display(Height, Width, Table, Key, 1, Opos);
"c\n" when is_tuple(Mode), element(1, Mode) =:= re ->
{re, Re} = Mode,
- re_search(Height, Width, Tab, Key, Re, 1, Opos);
+ re_search(Height, Width, Table, Key, Re, 1, Opos);
"q\n" ->
ok;
"k\n" ->
- ets:delete(Tab),
+ ets:delete(Table),
ok;
[$p|Digs] ->
catch case catch list_to_integer(nonl(Digs)) of
{'EXIT', _} ->
io:put_chars("Bad digits\n");
Number when Mode =:= normal ->
- print_number(Tab, ets:first(Tab), Number);
+ print_number(Table, ets:first(Table), Number);
Number when Mode =:= eot ->
- print_number(Tab, ets:first(Tab), Number);
+ print_number(Table, ets:first(Table), Number);
Number -> %% regexp
{re, Re} = Mode,
- print_re_num(Tab, ets:first(Tab), Number, Re)
+ print_re_num(Table, ets:first(Table), Number, Re)
end,
- choice(Height, Width, P, Mode, Tab, Key, Turn, Opos);
+ choice(Height, Width, P, Mode, Table, Key, Turn, Opos);
[$/|Regexp] -> %% from regexp
case re:compile(nonl(Regexp),[unicode]) of
{ok,Re} ->
- re_search(Height, Width, Tab, ets:first(Tab), Re, 1, 1);
+ re_search(Height, Width, Table, ets:first(Table), Re, 1, 1);
{error,{ErrorString,_Pos}} ->
io:format("~ts\n", [ErrorString]),
- choice(Height, Width, P, Mode, Tab, Key, Turn, Opos)
+ choice(Height, Width, P, Mode, Table, Key, Turn, Opos)
end;
eof ->
ok;
_ ->
- choice(Height, Width, P, Mode, Tab, Key, Turn, Opos)
+ choice(Height, Width, P, Mode, Table, Key, Turn, Opos)
end.
get_line(P, Default) ->
@@ -1731,22 +1738,22 @@ line_string(Other) -> Other.
nonl(S) -> string:trim(S, trailing, "$\n").
-print_number(Tab, Key, Num) ->
- Os = ets:lookup(Tab, Key),
+print_number(Table, Key, Num) ->
+ Os = ets:lookup(Table, Key),
Len = length(Os),
if
(Num - Len) < 1 ->
O = lists:nth(Num, Os),
io:format("~p~n", [O]); %% use ppterm here instead
true ->
- print_number(Tab, ets:next(Tab, Key), Num - Len)
+ print_number(Table, ets:next(Table, Key), Num - Len)
end.
-do_display(Height, Width, Tab, Key, Turn, Opos) ->
- Objs = ets:lookup(Tab, Key),
+do_display(Height, Width, Table, Key, Turn, Opos) ->
+ Objs = ets:lookup(Table, Key),
do_display_items(Height, Width, Objs, Opos),
Len = length(Objs),
- display_items(Height, Width, Tab, ets:next(Tab, Key), Turn+Len, Opos+Len).
+ display_items(Height, Width, Table, ets:next(Table, Key), Turn+Len, Opos+Len).
do_display_items(Height, Width, [Obj|Tail], Opos) ->
do_display_item(Height, Width, Obj, Opos),
@@ -1764,37 +1771,37 @@ do_display_item(_Height, Width, I, Opos) ->
end,
io:format("<~-4w> ~s~n", [Opos,L2]).
-re_search(Height, Width, Tab, '$end_of_table', Re, Turn, Opos) ->
+re_search(Height, Width, Table, '$end_of_table', Re, Turn, Opos) ->
P = 'EOT (q)uit (p)Digits (k)ill /Regexp -->',
- choice(Height, Width, P, {re, Re}, Tab, '$end_of_table', Turn, Opos);
-re_search(Height, Width, Tab, Key, Re, Turn, Opos) when Turn < Height ->
- re_display(Height, Width, Tab, Key, ets:lookup(Tab, Key), Re, Turn, Opos);
-re_search(Height, Width, Tab, Key, Re, Turn, Opos) ->
+ choice(Height, Width, P, {re, Re}, Table, '$end_of_table', Turn, Opos);
+re_search(Height, Width, Table, Key, Re, Turn, Opos) when Turn < Height ->
+ re_display(Height, Width, Table, Key, ets:lookup(Table, Key), Re, Turn, Opos);
+re_search(Height, Width, Table, Key, Re, Turn, Opos) ->
P = '(c)ontinue (q)uit (p)Digits (k)ill /Regexp -->',
- choice(Height, Width, P, {re, Re}, Tab, Key, Turn, Opos).
+ choice(Height, Width, P, {re, Re}, Table, Key, Turn, Opos).
-re_display(Height, Width, Tab, Key, [], Re, Turn, Opos) ->
- re_search(Height, Width, Tab, ets:next(Tab, Key), Re, Turn, Opos);
-re_display(Height, Width, Tab, Key, [H|T], Re, Turn, Opos) ->
+re_display(Height, Width, Table, Key, [], Re, Turn, Opos) ->
+ re_search(Height, Width, Table, ets:next(Table, Key), Re, Turn, Opos);
+re_display(Height, Width, Table, Key, [H|T], Re, Turn, Opos) ->
Str = to_string(H),
case re:run(Str, Re, [{capture,none}]) of
match ->
do_display_item(Height, Width, H, Opos),
- re_display(Height, Width, Tab, Key, T, Re, Turn+1, Opos+1);
+ re_display(Height, Width, Table, Key, T, Re, Turn+1, Opos+1);
nomatch ->
- re_display(Height, Width, Tab, Key, T, Re, Turn, Opos)
+ re_display(Height, Width, Table, Key, T, Re, Turn, Opos)
end.
print_re_num(_,'$end_of_table',_,_) -> ok;
-print_re_num(Tab, Key, Num, Re) ->
- Os = re_match(ets:lookup(Tab, Key), Re),
+print_re_num(Table, Key, Num, Re) ->
+ Os = re_match(ets:lookup(Table, Key), Re),
Len = length(Os),
if
(Num - Len) < 1 ->
O = lists:nth(Num, Os),
io:format("~p~n", [O]); %% use ppterm here instead
true ->
- print_re_num(Tab, ets:next(Tab, Key), Num - Len, Re)
+ print_re_num(Table, ets:next(Table, Key), Num - Len, Re)
end.
re_match([], _) -> [];
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index 966bc65902..b7c4d02ea5 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,8 +22,8 @@
%% Avoid warning for local function error/1 clashing with autoimported BIF.
-compile({no_auto_import,[error/1]}).
--export([expr_grp/3,expr_grp/5,match_bits/6,
- match_bits/7,bin_gen/6]).
+-export([expr_grp/3,expr_grp/4,match_bits/6,
+ match_bits/7,bin_gen/6,bin_gen/7]).
-define(STACKTRACE,
element(2, erlang:process_info(self(), current_stacktrace))).
@@ -40,11 +40,13 @@
%% lookup a variable in the bindings, or add a new binding
%%
%% @type field(). Represents a field in a "bin".
+%%
+%% @type errorfun(). A closure invoked in case of errors.
%%% Part 1: expression evaluation (binary construction)
%% @spec expr_grp(Fields::[field()], Bindings::bindings(),
-%% EvalFun::evalfun(), term(), term()) ->
+%% EvalFun::evalfun(), ErrorFun::errorfun()) ->
%% {value, binary(), bindings()}
%%
%% @doc Returns a tuple with {value,Bin,Bs} where Bin is the binary
@@ -52,29 +54,23 @@
%% contains the present bindings. This function can also throw an
%% exception if the construction fails.
-expr_grp(Fields, Bindings, EvalFun, [], _) ->
- expr_grp(Fields, Bindings, EvalFun, <<>>);
-expr_grp(Fields, Bindings, EvalFun, ListOfBits, _) ->
- Bin = convert_list(ListOfBits),
- expr_grp(Fields, Bindings, EvalFun, Bin).
-
-convert_list(List) ->
- << <<X:1>> || X <- List >>.
+expr_grp(Fields, Bindings, EvalFun, ErrorFun) ->
+ expr_grp(Fields, Bindings, EvalFun, ErrorFun, <<>>).
expr_grp(Fields, Bindings, EvalFun) ->
- expr_grp(Fields, Bindings, EvalFun, <<>>).
+ expr_grp(Fields, Bindings, EvalFun, fun default_error/3, <<>>).
-expr_grp(FS, Bs0, Ef, Acc) ->
+expr_grp(FS, Bs0, EvalFun, ErrorFun, Acc) ->
%% Separate the evaluation of values, sizes, and TLS:s from the
%% creation of the binary in order to mimic compiled code when it
%% comes to loops and failures.
- {ListOfEvalField,Bs1} = expr_grp1(FS, Bs0, Ef, []),
+ {ListOfEvalField,Bs1} = expr_grp1(FS, Bs0, EvalFun, ErrorFun, [], 1),
{value,create_binary(ListOfEvalField, Acc),Bs1}.
-expr_grp1([Field | FS], Bs0, Ef, ListOfEvalField) ->
- {EvalField,Bs} = eval_field(Field, Bs0, Ef),
- expr_grp1(FS, Bs, Ef, [EvalField|ListOfEvalField]);
-expr_grp1([], Bs, _Ef, ListOfFieldData) ->
+expr_grp1([Field | FS], Bs0, EvalFun, ErrorFun, ListOfEvalField, Pos) ->
+ {EvalField,Bs} = eval_field(Field, Bs0, EvalFun, ErrorFun, Pos),
+ expr_grp1(FS, Bs, EvalFun, ErrorFun, [EvalField|ListOfEvalField], Pos + 1);
+expr_grp1([], Bs, _EvalFun, _ErrorFun, ListOfFieldData, _Pos) ->
{lists:reverse(ListOfFieldData),Bs}.
create_binary([EvalField|ListOfEvalField], Acc) ->
@@ -83,44 +79,54 @@ create_binary([EvalField|ListOfEvalField], Acc) ->
create_binary([], Acc) ->
Acc.
-eval_field({bin_element, _, {string, _, S}, {integer,_,8}, [integer,{unit,1},unsigned,big]}, Bs0, _Fun) ->
+eval_field({bin_element, _, {string, _, S}, {integer,_,8}, [integer,{unit,1},unsigned,big]}, Bs0, _Fun, _ErrorFun, _Pos) ->
Latin1 = [C band 16#FF || C <- S],
{fun() -> list_to_binary(Latin1) end,Bs0};
-eval_field({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun) ->
+eval_field({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun, _ErrorFun, _Pos) ->
Latin1 = [C band 16#FF || C <- S],
{fun() ->list_to_binary(Latin1) end,Bs0};
-eval_field({bin_element, Anno, {string, _, S}, Size0, Options0}, Bs0, Fun) ->
+eval_field({bin_element, Anno, {string, _, S}, Size0, Options0}, Bs0, Fun, ErrorFun, Pos) ->
{Size1,[Type,{unit,Unit},Sign,Endian]} =
- make_bit_type(Anno, Size0, Options0),
+ make_bit_type(Anno, Size0, Options0, ErrorFun),
{value,Size,Bs1} = Fun(Size1, Bs0),
{fun() ->
- Res = << <<(eval_exp_field1(C, Size, Unit,
- Type, Endian, Sign))/bitstring>> ||
+ Res = << <<(eval_exp_field1(Anno, C, Size, Unit,
+ Type, Endian, Sign, ErrorFun, Pos))/bitstring>> ||
C <- S >>,
case S of
"" -> % find errors also when the string is empty
- _ = eval_exp_field1(0, Size, Unit, Type, Endian, Sign),
+ _ = eval_exp_field1(Anno, 0, Size, Unit, Type, Endian, Sign, ErrorFun, Pos),
ok;
_ ->
ok
end,
Res
end,Bs1};
-eval_field({bin_element,Anno,E,Size0,Options0}, Bs0, Fun) ->
+eval_field({bin_element,Anno,E,Size0,Options0}, Bs0, Fun, ErrorFun, Pos) ->
{value,V,Bs1} = Fun(E, Bs0),
{Size1,[Type,{unit,Unit},Sign,Endian]} =
- make_bit_type(Anno, Size0, Options0),
+ make_bit_type(Anno, Size0, Options0, ErrorFun),
{value,Size,Bs} = Fun(Size1, Bs1),
- {fun() -> eval_exp_field1(V, Size, Unit, Type, Endian, Sign) end,Bs}.
+ {fun() -> eval_exp_field1(Anno, V, Size, Unit, Type, Endian, Sign, ErrorFun, Pos) end,Bs}.
-eval_exp_field1(V, Size, Unit, Type, Endian, Sign) ->
+eval_exp_field1(Anno, V, Size, Unit, Type, Endian, Sign, ErrorFun, Pos) ->
try
- eval_exp_field(V, Size, Unit, Type, Endian, Sign)
+ eval_exp_field(V, Size, Unit, Type, Endian, Sign)
catch
- error:system_limit ->
- erlang:raise(error, system_limit, ?STACKTRACE);
- error:_ ->
- erlang:raise(error, badarg, ?STACKTRACE)
+ error:system_limit:Stacktrace ->
+ ErrorFun(Anno, system_limit, add_eval_pos_to_error_info(Stacktrace, Pos));
+ error:_:Stacktrace ->
+ ErrorFun(Anno, badarg, add_eval_pos_to_error_info(Stacktrace, Pos))
+ end.
+
+add_eval_pos_to_error_info([{Mod, Fun, Arity, Meta0} = Head, _Skip | Rest], Pos) ->
+ case lists:keytake(error_info, 1, Meta0) of
+ {value, {error_info, #{} = Info}, Meta1} ->
+ Meta2 = Meta1 ++ [{error_info, Info#{override_segment_position => Pos}}],
+ [{Mod, Fun, Arity, Meta2} | Rest];
+
+ _ ->
+ [Head | Rest]
end.
eval_exp_field(Val, Size, Unit, integer, little, signed) ->
@@ -169,7 +175,8 @@ eval_exp_field(Val, Size, Unit, binary, _, _) ->
%%% Part 2: matching in binary comprehensions
%% @spec bin_gen(BinPattern::{bin,integer(),[field()]}, Bin::binary(),
%% GlobalEnv::bindings(), LocalEnv::bindings(),
-%% MatchFun::matchfun(), EvalFun::evalfun()) ->
+%% MatchFun::matchfun(), EvalFun::evalfun(),
+%% ErrorFun::errorfun()) ->
%% {match, binary(), bindings()} | {nomatch, binary()} | done
%%
%% @doc Used to perform matching in a comprehension. If the match
@@ -178,25 +185,28 @@ eval_exp_field(Val, Size, Unit, binary, _, _) ->
%% If nothing remains of the binary the atom 'done' is returned.
bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun) ->
- bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, true).
+ bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, fun default_error/3, true).
+
+bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
+ bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, ErrorFun, true).
-bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag)
+bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, ErrorFun, Flag)
when is_function(Mfun, 2), is_function(Efun, 2) ->
- case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun) of
+ case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) of
{match,Bs,BBs,Rest} ->
- bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, Flag);
+ bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, ErrorFun, Flag);
{nomatch,Rest} ->
- bin_gen(Fs, Rest, Bs0, BBs0, Mfun, Efun, false);
+ bin_gen(Fs, Rest, Bs0, BBs0, Mfun, Efun, ErrorFun, false);
done ->
done
end;
-bin_gen([], Bin, Bs0, _BBs0, _Mfun, _Efun, true) ->
+bin_gen([], Bin, Bs0, _BBs0, _Mfun, _Efun, _ErrorFun, true) ->
{match, Bin, Bs0};
-bin_gen([], Bin, _Bs0, _BBs0, _Mfun, _Efun, false) ->
+bin_gen([], Bin, _Bs0, _BBs0, _Mfun, _Efun, _ErrorFun, false) ->
{nomatch, Bin}.
bin_gen_field({bin_element,_,{string,_,S},default,default},
- Bin, Bs, BBs, _Mfun, _Efun) ->
+ Bin, Bs, BBs, _Mfun, _Efun, _ErrorFun) ->
Bits = try list_to_binary(S)
catch _:_ -> <<>>
end,
@@ -210,9 +220,9 @@ bin_gen_field({bin_element,_,{string,_,S},default,default},
done
end;
bin_gen_field({bin_element,Anno,{string,SAnno,S},Size0,Options0},
- Bin0, Bs0, BBs0, Mfun, Efun) ->
+ Bin0, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
- make_bit_type(Anno, Size0, Options0),
+ make_bit_type(Anno, Size0, Options0, ErrorFun),
case catch Efun(Size1, BBs0) of
{value, Size, _BBs} -> %
F = fun(C, Bin, Bs, BBs) ->
@@ -222,9 +232,9 @@ bin_gen_field({bin_element,Anno,{string,SAnno,S},Size0,Options0},
bin_gen_field_string(S, Bin0, Bs0, BBs0, F)
end;
bin_gen_field({bin_element,Anno,VE,Size0,Options0},
- Bin, Bs0, BBs0, Mfun, Efun) ->
+ Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
- make_bit_type(Anno, Size0, Options0),
+ make_bit_type(Anno, Size0, Options0, ErrorFun),
V = erl_eval:partial_eval(VE),
NewV = coerce_to_float(V, Type),
case catch Efun(Size1, BBs0) of
@@ -264,41 +274,42 @@ bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun) ->
%%% Part 3: binary pattern matching
%% @spec match_bits(Fields::[field()], Bin::binary(),
%% GlobalEnv::bindings(), LocalEnv::bindings(),
-%% MatchFun::matchfun(),EvalFun::evalfun(), term()) ->
-%% {match, bindings()}
+%% MatchFun::matchfun(),EvalFun::evalfun(),
+%% ErrorFun::errorfun()) ->
+%% {match, bindings()}
%% @doc Used to perform matching. If the match succeeds a new
%% environment is returned. If the match have some syntactic or
%% semantic problem which would have been caught at compile time this
%% function throws 'invalid', if the matching fails for other reasons
%% the function throws 'nomatch'
-match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, _) ->
- match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun).
+match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun) ->
+ match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, fun default_error/3).
-match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun)
- when is_function(Mfun, 2), is_function(Efun, 2) ->
- case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun) of
+match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, ErrorFun)
+ when is_function(Mfun, 2), is_function(Efun, 2), is_function(ErrorFun, 3) ->
+ case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun, ErrorFun) of
{match,Bs} -> {match,Bs};
invalid -> throw(invalid);
_Error -> throw(nomatch)
end.
-match_bits_1([], <<>>, Bs, _BBs, _Mfun, _Efun) ->
+match_bits_1([], <<>>, Bs, _BBs, _Mfun, _Efun, _ErrorFun) ->
{match,Bs};
-match_bits_1([F|Fs], Bits0, Bs0, BBs0, Mfun, Efun) ->
- {Bs,BBs,Bits} = match_field_1(F, Bits0, Bs0, BBs0, Mfun, Efun),
- match_bits_1(Fs, Bits, Bs, BBs, Mfun, Efun).
+match_bits_1([F|Fs], Bits0, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
+ {Bs,BBs,Bits} = match_field_1(F, Bits0, Bs0, BBs0, Mfun, Efun, ErrorFun),
+ match_bits_1(Fs, Bits, Bs, BBs, Mfun, Efun, ErrorFun).
match_field_1({bin_element,_,{string,_,S},default,default},
- Bin, Bs, BBs, _Mfun, _Efun) ->
+ Bin, Bs, BBs, _Mfun, _Efun, _ErrorFun) ->
Bits = list_to_binary(S), % fails if there are characters > 255
Size = byte_size(Bits),
<<Bits:Size/binary,Rest/binary-unit:1>> = Bin,
{Bs,BBs,Rest};
match_field_1({bin_element,Anno,{string,SAnno,S},Size0,Options0},
- Bin0, Bs0, BBs0, Mfun, Efun) ->
+ Bin0, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
- make_bit_type(Anno, Size0, Options0),
+ make_bit_type(Anno, Size0, Options0, ErrorFun),
Size2 = erl_eval:partial_eval(Size1),
{value, Size, _BBs} = Efun(Size2, BBs0),
F = fun(C, Bin, Bs, BBs) ->
@@ -307,9 +318,9 @@ match_field_1({bin_element,Anno,{string,SAnno,S},Size0,Options0},
end,
match_field_string(S, Bin0, Bs0, BBs0, F);
match_field_1({bin_element,Anno,VE,Size0,Options0},
- Bin, Bs0, BBs0, Mfun, Efun) ->
+ Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
- make_bit_type(Anno, Size0, Options0),
+ make_bit_type(Anno, Size0, Options0, ErrorFun),
V = erl_eval:partial_eval(VE),
NewV = coerce_to_float(V, Type),
Size2 = erl_eval:partial_eval(Size1),
@@ -410,15 +421,18 @@ get_float(Bin, Size, big) ->
{Val,Rest}.
%% Identical to the one in sys_pre_expand.
-make_bit_type(Anno, default, Type0) ->
+make_bit_type(Anno, default, Type0, ErrorFun) ->
case erl_bits:set_bit_type(default, Type0) of
{ok,all,Bt} -> {{atom,Anno,all},erl_bits:as_list(Bt)};
{ok,undefined,Bt} -> {{atom,Anno,undefined},erl_bits:as_list(Bt)};
{ok,Size,Bt} -> {{integer,Anno,Size},erl_bits:as_list(Bt)};
- {error,Reason} -> erlang:raise(error, Reason, ?STACKTRACE)
+ {error,Reason} -> ErrorFun(Anno, Reason, ?STACKTRACE)
end;
-make_bit_type(_Anno, Size, Type0) -> %Size evaluates to an integer or 'all'
+make_bit_type(Anno, Size, Type0, ErrorFun) -> %Size evaluates to an integer or 'all'
case erl_bits:set_bit_type(Size, Type0) of
{ok,Size,Bt} -> {Size,erl_bits:as_list(Bt)};
- {error,Reason} -> erlang:raise(error, Reason, ?STACKTRACE)
+ {error,Reason} -> ErrorFun(Anno, Reason, ?STACKTRACE)
end.
+
+default_error(_Anno, Reason, Stacktrace) ->
+ erlang:raise(error, Reason, Stacktrace).
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index 7f8c282a79..de08352398 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
%% File utilities.
-export([wildcard/1, wildcard/2, is_dir/1, is_file/1, is_regular/1]).
--export([fold_files/5, last_modified/1, file_size/1, ensure_dir/1]).
+-export([fold_files/5, last_modified/1, file_size/1, ensure_dir/1, ensure_path/1]).
-export([wildcard/3, is_dir/2, is_file/2, is_regular/2]).
-export([fold_files/6, last_modified/2, file_size/2]).
-export([find_file/2, find_file/3, find_source/1, find_source/2, find_source/3]).
@@ -218,6 +218,7 @@ do_file_size(File, Mod) ->
0
end.
+
%%----------------------------------------------------------------------
%% +type ensure_dir(X) -> ok | {error, Reason}.
%% +type X = filename() | dirname()
@@ -230,27 +231,37 @@ ensure_dir("/") ->
ok;
ensure_dir(F) ->
Dir = filename:dirname(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
- {error,eexist}=EExist ->
- case do_is_dir(Dir, file) of
- true ->
- ok;
- false ->
- EExist
- end;
- Err ->
- Err
- end
- end.
+ ensure_path(Dir).
+-spec ensure_path(Path) -> 'ok' | {'error', Reason} when
+ Path :: dirname_all(),
+ Reason :: file:posix().
+ensure_path("/") ->
+ ok;
+
+ensure_path(Path) ->
+ case do_is_dir(Path, file) of
+ true ->
+ ok;
+ false ->
+ case filename:dirname(Path) of
+ Parent when Parent =:= Path ->
+ {error,einval};
+ Parent ->
+ _ = ensure_path(Parent),
+ case file:make_dir(Path) of
+ {error,eexist}=EExist ->
+ case do_is_dir(Path, file) of
+ true ->
+ ok;
+ false ->
+ EExist
+ end;
+ Other ->
+ Other
+ end
+ end
+ end.
%%%
%%% Pattern matching using a compiled wildcard.
@@ -646,6 +657,7 @@ default_search_rules() ->
{".o", ".c", c_source_search_rules()},
{"", ".c", c_source_search_rules()},
{"", ".in", basic_source_search_rules()},
+ {".beam", ".asn1", asn1_source_search_rules()},
%% plain old directory rules, backwards compatible
{"", ""}] ++ erl_source_search_rules().
@@ -661,6 +673,9 @@ erl_source_search_rules() ->
c_source_search_rules() ->
[{"priv","c_src"}, {"priv","src"}, {"bin","c_src"}, {"bin","src"}, {"", "src"}].
+asn1_source_search_rules() ->
+ [{"ebin","src"},{"ebin","asn1"}].
+
%% Looks for a file relative to a given directory
-type find_file_rule() :: {ObjDirSuffix::string(), SrcDirSuffix::string()}.
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 68b3f3200d..8bf4e97b9f 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
-module(filename).
-removed([{find_src,'_',"use filelib:find_source/1,3 instead"}]).
--deprecated([{safe_relative_path,1,"use filelib:safe_relative_path/2 instead"}]).
+-removed([{safe_relative_path,1,"use filelib:safe_relative_path/2 instead"}]).
%% Purpose: Provides generic manipulation of filenames.
%%
@@ -69,8 +69,7 @@
-export([absname/1, absname/2, absname_join/2,
basename/1, basename/2, dirname/1,
extension/1, join/1, join/2, pathtype/1,
- rootname/1, rootname/2, split/1, flatten/1, nativename/1,
- safe_relative_path/1]).
+ rootname/1, rootname/2, split/1, flatten/1, nativename/1]).
-export([basedir/2, basedir/3]).
-export([validate/1]).
@@ -816,39 +815,6 @@ separators() ->
_ -> {false, false}
end.
--spec safe_relative_path(Filename) -> 'unsafe' | SafeFilename when
- Filename :: file:name_all(),
- SafeFilename :: file:name_all().
-
-safe_relative_path(Path) ->
- case pathtype(Path) of
- relative ->
- Cs0 = split(Path),
- safe_relative_path_1(Cs0, []);
- _ ->
- unsafe
- end.
-
-safe_relative_path_1(["."|T], Acc) ->
- safe_relative_path_1(T, Acc);
-safe_relative_path_1([<<".">>|T], Acc) ->
- safe_relative_path_1(T, Acc);
-safe_relative_path_1([".."|T], Acc) ->
- climb(T, Acc);
-safe_relative_path_1([<<"..">>|T], Acc) ->
- climb(T, Acc);
-safe_relative_path_1([H|T], Acc) ->
- safe_relative_path_1(T, [H|Acc]);
-safe_relative_path_1([], []) ->
- [];
-safe_relative_path_1([], Acc) ->
- join(lists:reverse(Acc)).
-
-climb(_, []) ->
- unsafe;
-climb(T, [_|Acc]) ->
- safe_relative_path_1(T, Acc).
-
major_os_type() ->
{OsT, _} = os:type(),
OsT.
diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl
index 6d6f7d40ac..8dda0d4ee0 100644
--- a/lib/stdlib/src/gb_sets.erl
+++ b/lib/stdlib/src/gb_sets.erl
@@ -871,7 +871,7 @@ is_set(_) -> false.
Set1 :: set(Element),
Set2 :: set(Element).
-filter(F, S) ->
+filter(F, S) when is_function(F, 1) ->
from_ordset([X || X <- to_list(S), F(X)]).
-spec fold(Function, Acc0, Set) -> Acc1 when
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 9a7ccaa312..363094fb15 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,37 +29,58 @@
-export([start/5, start/6, debug_options/2, hibernate_after/1,
name/1, unregister_name/1, get_proc_name/1, get_parent/0,
call/3, call/4, reply/2,
- send_request/3, wait_response/2,
- receive_response/2, check_response/2,
+ send_request/3, send_request/5,
+ wait_response/2, receive_response/2, check_response/2,
+ wait_response/3, receive_response/3, check_response/3,
+ reqids_new/0, reqids_size/1,
+ reqids_add/3, reqids_to_list/1,
stop/1, stop/3]).
-export([init_it/6, init_it/7]).
--export([format_status_header/2]).
+-export([format_status_header/2, format_status/4]).
+-define(MAX_INT_TIMEOUT, 4294967295).
-define(default_timeout, 5000).
+-include("logger.hrl").
+
%%-----------------------------------------------------------------
+-export_type([reply_tag/0,
+ request_id/0,
+ request_id_collection/0]).
+
-type linkage() :: 'monitor' | 'link' | 'nolink'.
-type emgr_name() :: {'local', atom()}
| {'global', term()}
| {'via', Module :: module(), Name :: term()}.
--type start_ret() :: {'ok', pid()} | {'ok', {pid(), reference()}} | 'ignore' | {'error', term()}.
+-type start_ret() :: {'ok', pid()}
+ | {'ok', {pid(), reference()}}
+ | 'ignore'
+ | {'error', term()}.
--type debug_flag() :: 'trace' | 'log' | 'statistics' | 'debug'
- | {'logfile', string()}.
-type option() :: {'timeout', timeout()}
- | {'debug', [debug_flag()]}
+ | {'debug', [sys:debug_option()]}
| {'hibernate_after', timeout()}
| {'spawn_opt', [proc_lib:spawn_option()]}.
--type options() :: [option()].
-type server_ref() :: pid() | atom() | {atom(), node()}
| {global, term()} | {via, module(), term()}.
--type request_id() :: term().
+-opaque reply_tag() :: % As accepted by reply/2
+ reference()
+ | nonempty_improper_list('alias', reference())
+ | nonempty_improper_list(
+ nonempty_improper_list('alias', reference()), term()).
+
+-opaque request_id() :: reference().
+
+-opaque request_id_collection() :: map().
+
+-type response_timeout() ::
+ 0..?MAX_INT_TIMEOUT | 'infinity' | {abs, integer()}.
%%-----------------------------------------------------------------
%% Starts a generic process.
@@ -77,7 +98,7 @@
%% The 'already_started' is returned only if Name is given
%%-----------------------------------------------------------------
--spec start(module(), linkage(), emgr_name(), module(), term(), options()) ->
+-spec start(module(), linkage(), emgr_name(), module(), term(), [option()]) ->
start_ret().
start(GenMod, LinkP, Name, Mod, Args, Options) ->
@@ -88,7 +109,7 @@ start(GenMod, LinkP, Name, Mod, Args, Options) ->
{error, {already_started, Pid}}
end.
--spec start(module(), linkage(), module(), term(), options()) -> start_ret().
+-spec start(module(), linkage(), module(), term(), [option()]) -> start_ret().
start(GenMod, LinkP, Mod, Args, Options) ->
do_spawn(GenMod, LinkP, Mod, Args, Options).
@@ -201,6 +222,8 @@ call(Process, Label, Request, Timeout)
-dialyzer({no_improper_lists, do_call/4}).
+do_call(Process, _Label, _Request, _Timeout) when Process =:= self() ->
+ exit(calling_self);
do_call(Process, Label, Request, infinity)
when (is_pid(Process)
andalso (node(Process) == node()))
@@ -263,11 +286,12 @@ get_node(Process) ->
node(Process)
end.
--spec send_request(Name::server_ref(), Label::term(), Request::term()) -> request_id().
-send_request(Process, Label, Request) when is_pid(Process) ->
- do_send_request(Process, Label, Request);
-send_request(Process, Label, Request) ->
- Fun = fun(Pid) -> do_send_request(Pid, Label, Request) end,
+-spec send_request(Name::server_ref(), Tag::term(), Request::term()) ->
+ request_id().
+send_request(Process, Tag, Request) when is_pid(Process) ->
+ do_send_request(Process, Tag, Request);
+send_request(Process, Tag, Request) ->
+ Fun = fun(Pid) -> do_send_request(Pid, Tag, Request) end,
try do_for_proc(Process, Fun)
catch exit:Reason ->
%% Make send_request async and fake a down message
@@ -276,62 +300,232 @@ send_request(Process, Label, Request) ->
Mref
end.
+-spec send_request(Name::server_ref(), Tag::term(), Request::term(),
+ Label::term(), ReqIdCol::request_id_collection()) ->
+ request_id_collection().
+send_request(Process, Tag, Request, Label, ReqIdCol) when is_map(ReqIdCol) ->
+ maps:put(send_request(Process, Tag, Request), Label, ReqIdCol).
+
-dialyzer({no_improper_lists, do_send_request/3}).
-do_send_request(Process, Label, Request) ->
- Mref = erlang:monitor(process, Process, [{alias, demonitor}]),
- erlang:send(Process, {Label, {self(), [alias|Mref]}, Request}, [noconnect]),
- Mref.
+do_send_request(Process, Tag, Request) ->
+ ReqId = erlang:monitor(process, Process, [{alias, demonitor}]),
+ _ = erlang:send(Process, {Tag, {self(), [alias|ReqId]}, Request}, [noconnect]),
+ ReqId.
%%
%% Wait for a reply to the client.
%% Note: if timeout is returned monitors are kept.
--spec wait_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
-wait_response(Mref, Timeout) when is_reference(Mref) ->
+-spec wait_response(ReqId, Timeout) -> Result when
+ ReqId :: request_id(),
+ Timeout :: response_timeout(),
+ Resp :: {reply, Reply::term()} | {error, {Reason::term(), server_ref()}},
+ Result :: Resp | 'timeout'.
+
+wait_response(ReqId, Timeout) ->
+ TMO = timeout_value(Timeout),
receive
- {[alias|Mref], Reply} ->
- erlang:demonitor(Mref, [flush]),
+ {[alias|ReqId], Reply} ->
+ erlang:demonitor(ReqId, [flush]),
{reply, Reply};
- {'DOWN', Mref, _, Object, Reason} ->
+ {'DOWN', ReqId, _, Object, Reason} ->
{error, {Reason, Object}}
- after Timeout ->
+ after TMO ->
timeout
end.
--spec receive_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
-receive_response(Mref, Timeout) when is_reference(Mref) ->
+-spec wait_response(ReqIdCol, Timeout, Delete) -> Result when
+ ReqIdCol :: request_id_collection(),
+ Timeout :: response_timeout(),
+ Delete :: boolean(),
+ Resp :: {reply, Reply::term()} | {error, {Reason::term(), server_ref()}},
+ Result :: {Resp, Label::term(), NewReqIdCol::request_id_collection()} |
+ 'no_request' | 'timeout'.
+
+wait_response(ReqIdCol, Timeout, Delete) when map_size(ReqIdCol) == 0,
+ is_boolean(Delete) ->
+ _ = timeout_value(Timeout),
+ no_request;
+wait_response(ReqIdCol, Timeout, Delete) when is_map(ReqIdCol),
+ is_boolean(Delete) ->
+ TMO = timeout_value(Timeout),
receive
- {[alias|Mref], Reply} ->
- erlang:demonitor(Mref, [flush]),
+ {[alias|ReqId], _} = Msg when is_map_key(ReqId, ReqIdCol) ->
+ collection_result(Msg, ReqIdCol, Delete);
+ {'DOWN', ReqId, _, _, _} = Msg when is_map_key(ReqId, ReqIdCol) ->
+ collection_result(Msg, ReqIdCol, Delete)
+ after TMO ->
+ timeout
+ end.
+
+-spec receive_response(ReqId, Timeout) -> Result when
+ ReqId :: request_id(),
+ Timeout :: response_timeout(),
+ Resp :: {reply, Reply::term()} | {error, {Reason::term(), server_ref()}},
+ Result :: Resp | 'timeout'.
+
+receive_response(ReqId, Timeout) ->
+ TMO = timeout_value(Timeout),
+ receive
+ {[alias|ReqId], Reply} ->
+ erlang:demonitor(ReqId, [flush]),
{reply, Reply};
- {'DOWN', Mref, _, Object, Reason} ->
+ {'DOWN', ReqId, _, Object, Reason} ->
{error, {Reason, Object}}
- after Timeout ->
- erlang:demonitor(Mref, [flush]),
+ after TMO ->
+ erlang:demonitor(ReqId, [flush]),
receive
- {[alias|Mref], Reply} ->
+ {[alias|ReqId], Reply} ->
{reply, Reply}
after 0 ->
timeout
end
end.
--spec check_response(RequestId::term(), Key::request_id()) ->
- {reply, Reply::term()} | 'no_reply' | {error, {term(), server_ref()}}.
-check_response(Msg, Mref) when is_reference(Mref) ->
+-spec receive_response(ReqIdCol, Timeout, Delete) -> Result when
+ ReqIdCol :: request_id_collection(),
+ Timeout :: response_timeout(),
+ Delete :: boolean(),
+ Resp :: {reply, Reply::term()} | {error, {Reason::term(), server_ref()}},
+ Result :: {Resp, Label::term(), NewReqIdCol::request_id_collection()}
+ | 'no_request' | 'timeout'.
+
+receive_response(ReqIdCol, Timeout, Delete) when map_size(ReqIdCol) == 0,
+ is_boolean(Delete) ->
+ _ = timeout_value(Timeout),
+ no_request;
+receive_response(ReqIdCol, Timeout, Delete) when is_map(ReqIdCol),
+ is_boolean(Delete) ->
+ TMO = timeout_value(Timeout),
+ receive
+ {[alias|ReqId], _} = Msg when is_map_key(ReqId, ReqIdCol) ->
+ collection_result(Msg, ReqIdCol, Delete);
+ {'DOWN', Mref, _, _, _} = Msg when is_map_key(Mref, ReqIdCol) ->
+ collection_result(Msg, ReqIdCol, Delete)
+ after TMO ->
+ maps:foreach(fun (ReqId, _Label) when is_reference(ReqId) ->
+ erlang:demonitor(ReqId, [flush]);
+ (_, _) ->
+ error(badarg)
+ end, ReqIdCol),
+ flush_responses(ReqIdCol),
+ timeout
+ end.
+
+-spec check_response(Msg::term(), ReqIdOrReqIdCol) -> Result when
+ ReqIdOrReqIdCol :: request_id() | request_id_collection(),
+ ReqIdResp :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ ReqIdColResp :: {{reply, Reply::term()}, Label::term()} |
+ {{error, {Reason::term(), server_ref()}}, Label::term()},
+ Result :: ReqIdResp | ReqIdColResp | 'no_reply'.
+
+check_response(Msg, ReqId) when is_reference(ReqId) ->
case Msg of
- {[alias|Mref], Reply} ->
- erlang:demonitor(Mref, [flush]),
+ {[alias|ReqId], Reply} ->
+ erlang:demonitor(ReqId, [flush]),
{reply, Reply};
- {'DOWN', Mref, _, Object, Reason} ->
+ {'DOWN', ReqId, _, Object, Reason} ->
{error, {Reason, Object}};
_ ->
no_reply
+ end;
+check_response(_, _) ->
+ error(badarg).
+
+-spec check_response(Msg, ReqIdCol, Delete) -> Result when
+ Msg :: term(),
+ ReqIdCol :: request_id_collection(),
+ Delete :: boolean(),
+ Resp :: {reply, Reply::term()} | {error, {Reason::term(), server_ref()}},
+ Result :: {Resp, Label::term(), NewReqIdCol::request_id_collection()}
+ | 'no_request' | 'no_reply'.
+
+check_response(_Msg, ReqIdCol, Delete) when map_size(ReqIdCol) == 0,
+ is_boolean(Delete) ->
+ no_request;
+check_response(Msg, ReqIdCol, Delete) when is_map(ReqIdCol),
+ is_boolean(Delete) ->
+ case Msg of
+ {[alias|ReqId], _} = Msg when is_map_key(ReqId, ReqIdCol) ->
+ collection_result(Msg, ReqIdCol, Delete);
+ {'DOWN', Mref, _, _, _} = Msg when is_map_key(Mref, ReqIdCol) ->
+ collection_result(Msg, ReqIdCol, Delete);
+ _ ->
+ no_reply
+ end.
+
+collection_result({[alias|ReqId], Reply}, ReqIdCol, Delete) ->
+ _ = erlang:demonitor(ReqId, [flush]),
+ collection_result({reply, Reply}, ReqId, ReqIdCol, Delete);
+collection_result({'DOWN', ReqId, _, Object, Reason}, ReqIdCol, Delete) ->
+ collection_result({error, {Reason, Object}}, ReqId, ReqIdCol, Delete).
+
+collection_result(Resp, ReqId, ReqIdCol, false) ->
+ {Resp, maps:get(ReqId, ReqIdCol), ReqIdCol};
+collection_result(Resp, ReqId, ReqIdCol, true) ->
+ {Label, NewReqIdCol} = maps:take(ReqId, ReqIdCol),
+ {Resp, Label, NewReqIdCol}.
+
+flush_responses(ReqIdCol) ->
+ receive
+ {[alias|Mref], _Reply} when is_map_key(Mref, ReqIdCol) ->
+ flush_responses(ReqIdCol)
+ after 0 ->
+ ok
end.
+timeout_value(infinity) ->
+ infinity;
+timeout_value(Timeout) when 0 =< Timeout, Timeout =< ?MAX_INT_TIMEOUT ->
+ Timeout;
+timeout_value({abs, Timeout}) when is_integer(Timeout) ->
+ case Timeout - erlang:monotonic_time(millisecond) of
+ TMO when TMO < 0 ->
+ 0;
+ TMO when TMO > ?MAX_INT_TIMEOUT ->
+ error(badarg);
+ TMO ->
+ TMO
+ end;
+timeout_value(_) ->
+ error(badarg).
+
+-spec reqids_new() ->
+ NewReqIdCol::request_id_collection().
+
+reqids_new() ->
+ maps:new().
+
+-spec reqids_size(request_id_collection()) ->
+ non_neg_integer().
+reqids_size(ReqIdCol) when is_map(ReqIdCol) ->
+ maps:size(ReqIdCol);
+reqids_size(_) ->
+ error(badarg).
+
+-spec reqids_add(ReqId::request_id(), Label::term(),
+ ReqIdCol::request_id_collection()) ->
+ NewReqIdCol::request_id_collection().
+
+reqids_add(ReqId, _, ReqIdCol) when is_reference(ReqId),
+ is_map_key(ReqId, ReqIdCol) ->
+ error(badarg);
+reqids_add(ReqId, Label, ReqIdCol) when is_reference(ReqId),
+ is_map(ReqIdCol) ->
+ maps:put(ReqId, Label, ReqIdCol);
+reqids_add(_, _, _) ->
+ error(badarg).
+
+-spec reqids_to_list(ReqIdCol::request_id_collection()) ->
+ [{ReqId::request_id(), Label::term()}].
+
+reqids_to_list(ReqIdCol) when is_map(ReqIdCol) ->
+ maps:to_list(ReqIdCol);
+reqids_to_list(_) ->
+ error(badarg).
+
%%
%% Send a reply to the client.
%%
@@ -546,3 +740,41 @@ format_status_header(TagLine, RegName) when is_atom(RegName) ->
lists:concat([TagLine, " ", RegName]);
format_status_header(TagLine, Name) ->
{TagLine, Name}.
+
+-spec format_status(Mod :: module(), Opt :: terminate | normal, Status, Args) ->
+ ReturnStatus when
+ Status :: #{ atom() => term() },
+ ReturnStatus :: #{ atom() => term(), '$status' => term()},
+ Args :: list(term()) | undefined.
+format_status(Mod, Opt, Status, Args) ->
+ case {erlang:function_exported(Mod, format_status, 1),
+ erlang:function_exported(Mod, format_status, 2)} of
+ {true, _} ->
+ try Mod:format_status(Status) of
+ NewStatus when is_map(NewStatus) ->
+ MergedStatus = maps:merge(Status, NewStatus),
+ case maps:size(MergedStatus) =:= maps:size(NewStatus) of
+ true ->
+ MergedStatus;
+ false ->
+ Status#{ 'EXIT' => atom_to_list(Mod) ++ ":format_status/1 returned a map with unknown keys" }
+ end;
+ _ ->
+ Status#{ 'EXIT' => atom_to_list(Mod) ++ ":format_status/1 did not return a map" }
+ catch
+ _:_ ->
+ Status#{ 'EXIT' => atom_to_list(Mod) ++ ":format_status/1 crashed" }
+ end;
+ {false, true} when is_list(Args) ->
+ try Mod:format_status(Opt, Args) of
+ Result ->
+ Status#{ '$status' => Result }
+ catch
+ throw:Result ->
+ Status#{ '$status' => Result };
+ _:_ ->
+ Status#{ 'EXIT' => atom_to_list(Mod) ++ ":format_status/2 crashed" }
+ end;
+ {false, _} ->
+ Status
+ end.
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index 17b914e5da..fd4b5d9add 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,11 @@
notify/2, sync_notify/2,
add_handler/3, add_sup_handler/3, delete_handler/3, swap_handler/3,
swap_sup_handler/3, which_handlers/1, call/3, call/4,
- send_request/3, wait_response/2, receive_response/2, check_response/2,
+ send_request/3, send_request/5,
+ wait_response/2, receive_response/2, check_response/2,
+ wait_response/3, receive_response/3, check_response/3,
+ reqids_new/0, reqids_size/1,
+ reqids_add/3, reqids_to_list/1,
wake_hib/5]).
-export([init_it/6,
@@ -58,7 +62,8 @@
-export([format_log/1, format_log/2]).
-export_type([handler/0, handler_args/0, add_handler_ret/0,
- del_handler_ret/0]).
+ del_handler_ret/0, request_id/0, request_id_collection/0,
+ format_status/0]).
-record(handler, {module :: atom(),
id = false,
@@ -118,9 +123,17 @@
PDict :: [{Key :: term(), Value :: term()}],
State :: term(),
Status :: term().
+-type format_status() ::
+ #{ state => term(),
+ message => term(),
+ reason => term(),
+ log => [sys:system_event()] }.
+-callback format_status(Status) -> NewStatus when
+ Status :: format_status(),
+ NewStatus :: format_status().
-optional_callbacks(
- [handle_info/2, terminate/2, code_change/3, format_status/2]).
+ [handle_info/2, terminate/2, code_change/3, format_status/1, format_status/2]).
%%---------------------------------------------------------------------------
@@ -141,7 +154,13 @@
| {'via', atom(), term()} | pid().
-type start_ret() :: {'ok', pid()} | {'error', term()}.
-type start_mon_ret() :: {'ok', {pid(),reference()}} | {'error', term()}.
--type request_id() :: term().
+
+-opaque request_id() :: gen:request_id().
+
+-opaque request_id_collection() :: gen:request_id_collection().
+
+-type response_timeout() ::
+ timeout() | {abs, integer()}.
%%---------------------------------------------------------------------------
@@ -236,32 +255,182 @@ call(M, Handler, Query) -> call1(M, Handler, Query).
-spec call(emgr_ref(), handler(), term(), timeout()) -> term().
call(M, Handler, Query, Timeout) -> call1(M, Handler, Query, Timeout).
--spec send_request(emgr_ref(), handler(), term()) -> request_id().
-send_request(M, Handler, Query) ->
- gen:send_request(M, self(), {call, Handler, Query}).
+-spec send_request(EventMgrRef::emgr_ref(), Handler::handler(), Request::term()) ->
+ ReqId::request_id().
+send_request(M, Handler, Request) ->
+ try
+ gen:send_request(M, self(), {call, Handler, Request})
+ catch
+ error:badarg ->
+ error(badarg, [M, Handler, Request])
+ end.
--spec wait_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), emgr_ref()}}.
-wait_response(RequestId, Timeout) ->
- case gen:wait_response(RequestId, Timeout) of
+-spec send_request(EventMgrRef::emgr_ref(),
+ Handler::handler(),
+ Request::term(),
+ Label::term(),
+ ReqIdCollection::request_id_collection()) ->
+ NewReqIdCollection::request_id_collection().
+send_request(M, Handler, Request, Label, ReqIdCol) ->
+ try
+ gen:send_request(M, self(), {call, Handler, Request}, Label, ReqIdCol)
+ catch
+ error:badarg ->
+ error(badarg, [M, Handler, Request, Label, ReqIdCol])
+ end.
+
+-spec wait_response(ReqId, WaitTime) -> Result when
+ ReqId :: request_id(),
+ WaitTime :: response_timeout(),
+ Response :: {reply, Reply::term()}
+ | {error, {Reason::term(), emgr_ref()}},
+ Result :: Response | 'timeout'.
+
+wait_response(ReqId, WaitTime) ->
+ try gen:wait_response(ReqId, WaitTime) of
{reply, {error, _} = Err} -> Err;
Return -> Return
+ catch
+ error:badarg ->
+ error(badarg, [ReqId, WaitTime])
+ end.
+
+-spec wait_response(ReqIdCollection, WaitTime, Delete) -> Result when
+ ReqIdCollection :: request_id_collection(),
+ WaitTime :: response_timeout(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), emgr_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'timeout'.
+
+wait_response(ReqIdCol, WaitTime, Delete) ->
+ try gen:wait_response(ReqIdCol, WaitTime, Delete) of
+ {{reply, {error, _} = Err}, Label, NewReqIdCol} ->
+ {Err, Label, NewReqIdCol};
+ Return ->
+ Return
+ catch
+ error:badarg ->
+ error(badarg, [ReqIdCol, WaitTime, Delete])
end.
--spec receive_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), emgr_ref()}}.
-receive_response(RequestId, Timeout) ->
- case gen:receive_response(RequestId, Timeout) of
+-spec receive_response(ReqId, Timeout) -> Result when
+ ReqId :: request_id(),
+ Timeout :: response_timeout(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), emgr_ref()}},
+ Result :: Response | 'timeout'.
+
+receive_response(ReqId, Timeout) ->
+ try gen:receive_response(ReqId, Timeout) of
{reply, {error, _} = Err} -> Err;
Return -> Return
+ catch
+ error:badarg ->
+ error(badarg, [ReqId, Timeout])
end.
--spec check_response(Msg::term(), RequestId::request_id()) ->
- {reply, Reply::term()} | 'no_reply' | {error, {Reason::term(), emgr_ref()}}.
-check_response(Msg, RequestId) ->
- case gen:check_response(Msg, RequestId) of
+-spec receive_response(ReqIdCollection, Timeout, Delete) -> Result when
+ ReqIdCollection :: request_id_collection(),
+ Timeout :: response_timeout(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), emgr_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'timeout'.
+
+receive_response(ReqIdCol, Timeout, Delete) ->
+ try gen:receive_response(ReqIdCol, Timeout, Delete) of
+ {{reply, {error, _} = Err}, Label, NewReqIdCol} ->
+ {Err, Label, NewReqIdCol};
+ Return ->
+ Return
+ catch
+ error:badarg ->
+ error(badarg, [ReqIdCol, Timeout, Delete])
+ end.
+
+-spec check_response(Msg, ReqId) -> Result when
+ Msg :: term(),
+ ReqId :: request_id(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), emgr_ref()}},
+ Result :: Response | 'no_reply'.
+
+check_response(Msg, ReqId) ->
+ try gen:check_response(Msg, ReqId) of
{reply, {error, _} = Err} -> Err;
Return -> Return
+ catch
+ error:badarg ->
+ error(badarg, [Msg, ReqId])
+ end.
+
+-spec check_response(Msg, ReqIdCollection, Delete) -> Result when
+ Msg :: term(),
+ ReqIdCollection :: request_id_collection(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), emgr_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'no_reply'.
+
+check_response(Msg, ReqIdCol, Delete) ->
+ try gen:check_response(Msg, ReqIdCol, Delete) of
+ {{reply, {error, _} = Err}, Label, NewReqIdCol} ->
+ {Err, Label, NewReqIdCol};
+ Return ->
+ Return
+ catch
+ error:badarg ->
+ error(badarg, [Msg, ReqIdCol, Delete])
+ end.
+
+-spec reqids_new() ->
+ NewReqIdCollection::request_id_collection().
+
+reqids_new() ->
+ gen:reqids_new().
+
+-spec reqids_size(ReqIdCollection::request_id_collection()) ->
+ non_neg_integer().
+
+reqids_size(ReqIdCollection) ->
+ try
+ gen:reqids_size(ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqIdCollection])
+ end.
+
+-spec reqids_add(ReqId::request_id(), Label::term(),
+ ReqIdCollection::request_id_collection()) ->
+ NewReqIdCollection::request_id_collection().
+
+reqids_add(ReqId, Label, ReqIdCollection) ->
+ try
+ gen:reqids_add(ReqId, Label, ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqId, Label, ReqIdCollection])
+ end.
+
+-spec reqids_to_list(ReqIdCollection::request_id_collection()) ->
+ [{ReqId::request_id(), Label::term()}].
+
+reqids_to_list(ReqIdCollection) ->
+ try
+ gen:reqids_to_list(ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqIdCollection])
end.
-spec delete_handler(emgr_ref(), handler(), term()) -> term().
@@ -330,19 +499,25 @@ wake_hib(Parent, ServerName, MSL, HibernateAfterTimeout, Debug) ->
fetch_msg(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib) ->
receive
+ Msg ->
+ decode_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib)
+ after HibernateAfterTimeout ->
+ loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true)
+ end.
+
+decode_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug, Hib) ->
+ case Msg of
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
[ServerName, MSL, HibernateAfterTimeout, Hib],Hib);
{'EXIT', Parent, Reason} ->
terminate_server(Reason, Parent, MSL, ServerName);
- Msg when Debug =:= [] ->
+ _Msg when Debug =:= [] ->
handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, []);
- Msg ->
+ _Msg ->
Debug1 = sys:handle_debug(Debug, fun print_event/3,
ServerName, {in, Msg}),
handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug1)
- after HibernateAfterTimeout ->
- loop(Parent, ServerName, MSL, HibernateAfterTimeout, Debug, true)
end.
handle_msg(Msg, Parent, ServerName, MSL, HibernateAfterTimeout, Debug) ->
@@ -776,6 +951,8 @@ do_terminate(Mod, Handler, Args, State, LastIn, SName, Reason) ->
ok
end.
+-spec report_terminate(_, How, _, _, _, _, _) -> ok when
+ How :: crash | normal | shutdown | {swapped, handler(), false | pid()}.
report_terminate(Handler, crash, {error, Why}, State, LastIn, SName, _) ->
report_terminate(Handler, Why, State, LastIn, SName);
report_terminate(Handler, How, _, State, LastIn, SName, _) ->
@@ -795,14 +972,34 @@ report_terminate(Handler, Reason, State, LastIn, SName) ->
report_error(_Handler, normal, _, _, _) -> ok;
report_error(_Handler, shutdown, _, _, _) -> ok;
report_error(_Handler, {swapped,_,_}, _, _, _) -> ok;
-report_error(Handler, Reason, State, LastIn, SName) ->
+report_error(Handler, Exit, State, LastIn, SName) ->
+
+ %% The reason comes from a catch expression, so we remove
+ %% the 'EXIT' and stacktrace from it so that the format_status
+ %% callback does not have deal with that.
+ {Reason, ReasonFun} =
+ case Exit of
+ {'EXIT',{R,ST}} ->
+ {R, fun(Reason) -> {'EXIT',{Reason,ST}} end};
+ {'EXIT',R} ->
+ {R, fun(Reason) -> {'EXIT',Reason} end};
+ R ->
+ {R, fun(Reason) -> Reason end}
+ end,
+ Status = gen:format_status(
+ Handler#handler.module,
+ terminate,
+ #{ state => State,
+ message => LastIn,
+ reason => Reason
+ },
+ [get(), State]),
?LOG_ERROR(#{label=>{gen_event,terminate},
handler=>handler(Handler),
name=>SName,
- last_message=>LastIn,
- state=>format_status(terminate,Handler#handler.module,
- get(),State),
- reason=>Reason},
+ last_message=>maps:get(message,Status),
+ state=>maps:get('$status',Status,maps:get(state,Status)),
+ reason=>ReasonFun(maps:get(reason,Status))},
#{domain=>[otp],
report_cb=>fun gen_event:format_log/2,
error_logger=>#{tag=>error,
@@ -869,10 +1066,10 @@ format_log_single(#{label:={gen_event,terminate},
Args1 =
case Depth of
unlimited ->
- [Handler,SName,Reason1,LastIn,State];
+ [Handler,SName,LastIn,State,Reason1];
_ ->
- [Handler,Depth,SName,Depth,Reason1,Depth,
- LastIn,Depth,State,Depth]
+ [Handler,Depth,SName,Depth,LastIn,Depth,
+ State,Depth,Reason1,Depth]
end,
{Format1, Args1};
format_log_single(#{label:={gen_event,no_handle_info},
@@ -992,24 +1189,19 @@ get_modules(MSL) ->
%% Status information
%%-----------------------------------------------------------------
format_status(Opt, StatusData) ->
- [PDict, SysState, Parent, _Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]] = StatusData,
- Header = gen:format_status_header("Status for event handler",
- ServerName),
- FmtMSL = [MS#handler{state=format_status(Opt, Mod, PDict, State)}
- || #handler{module = Mod, state = State} = MS <- MSL],
+ [PDict, SysState, Parent, Debug, [ServerName, MSL, _HibernateAfterTimeout, _Hib]] = StatusData,
+ Header = gen:format_status_header("Status for event handler", ServerName),
+ {FmtMSL, Logs} =
+ lists:mapfoldl(
+ fun(#handler{module = Mod, state = State} = MS, Logs) ->
+ Status = gen:format_status(
+ Mod, Opt, #{ log => Logs, state => State },
+ [PDict, State]),
+ {MS#handler{state=maps:get('$status',Status,maps:get(state,Status))},
+ maps:get(log,Status)}
+ end, sys:get_log(Debug), MSL),
[{header, Header},
{data, [{"Status", SysState},
+ {"Logged Events", Logs},
{"Parent", Parent}]},
{items, {"Installed handlers", FmtMSL}}].
-
-format_status(Opt, Mod, PDict, State) ->
- case erlang:function_exported(Mod, format_status, 2) of
- true ->
- Args = [PDict, State],
- case catch Mod:format_status(Opt, Args) of
- {'EXIT', _} -> State;
- Else -> Else
- end;
- false ->
- State
- end.
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index 03541ccb50..af5e04f78a 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -97,8 +97,11 @@
start_monitor/3, start_monitor/4,
stop/1, stop/3,
call/2, call/3,
- send_request/2, wait_response/2,
- receive_response/2, check_response/2,
+ send_request/2, send_request/4,
+ wait_response/2, receive_response/2, check_response/2,
+ wait_response/3, receive_response/3, check_response/3,
+ reqids_new/0, reqids_size/1,
+ reqids_add/3, reqids_to_list/1,
cast/2, reply/2,
abcast/2, abcast/3,
multi_call/2, multi_call/3, multi_call/4,
@@ -120,19 +123,29 @@
-include("logger.hrl").
+-export_type(
+ [from/0,
+ reply_tag/0,
+ request_id/0,
+ request_id_collection/0,
+ format_status/0]).
+
+-export_type(
+ [server_name/0,
+ server_ref/0,
+ start_opt/0,
+ enter_loop_opt/0,
+ start_ret/0,
+ start_mon_ret/0]).
+
-define(
STACKTRACE(),
element(2, erlang:process_info(self(), current_stacktrace))).
-
--type server_ref() ::
- pid()
- | (LocalName :: atom())
- | {Name :: atom(), Node :: atom()}
- | {'global', GlobalName :: term()}
- | {'via', RegMod :: module(), ViaName :: term()}.
-
--type request_id() :: term().
+-define(
+ is_timeout(X),
+ ( (X) =:= infinity orelse ( is_integer(X) andalso (X) >= 0 ) )
+).
%%%=========================================================================
%%% API
@@ -141,7 +154,7 @@
-callback init(Args :: term()) ->
{ok, State :: term()} | {ok, State :: term(), timeout() | hibernate | {continue, term()}} |
{stop, Reason :: term()} | ignore.
--callback handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+-callback handle_call(Request :: term(), From :: from(),
State :: term()) ->
{reply, Reply :: term(), NewState :: term()} |
{reply, Reply :: term(), NewState :: term(), timeout() | hibernate | {continue, term()}} |
@@ -174,9 +187,30 @@
PDict :: [{Key :: term(), Value :: term()}],
State :: term(),
Status :: term().
+-type format_status() ::
+ #{ state => term(),
+ message => term(),
+ reason => term(),
+ log => [sys:system_event()] }.
+-callback format_status(Status) -> NewStatus when
+ Status :: format_status(),
+ NewStatus :: format_status().
-optional_callbacks(
- [handle_info/2, handle_continue/2, terminate/2, code_change/3, format_status/2]).
+ [handle_info/2, handle_continue/2, terminate/2, code_change/3,
+ format_status/1, format_status/2]).
+
+
+
+-type from() :: {Client :: pid(), Tag :: reply_tag()}.
+-opaque reply_tag() :: gen:reply_tag().
+
+-opaque request_id() :: gen:request_id().
+
+-opaque request_id_collection() :: gen:request_id_collection().
+
+-type response_timeout() ::
+ timeout() | {abs, integer()}.
%%% -----------------------------------------------------------------
%%% Starts a generic server.
@@ -194,23 +228,102 @@
%%% {error, {already_started, Pid}} |
%%% {error, Reason}
%%% -----------------------------------------------------------------
-start(Mod, Args, Options) ->
- gen:start(?MODULE, nolink, Mod, Args, Options).
-start(Name, Mod, Args, Options) ->
- gen:start(?MODULE, nolink, Name, Mod, Args, Options).
+-type server_name() :: % Duplicate of gen:emgr_name()
+ {'local', LocalName :: atom()}
+ | {'global', GlobalName :: term()}
+ | {'via', RegMod :: module(), ViaName :: term()}.
+
+-type server_ref() :: % What gen:call/3,4 and gen:stop/1,3 accepts
+ pid()
+ | (LocalName :: atom())
+ | {Name :: atom(), Node :: atom()}
+ | {'global', GlobalName :: term()}
+ | {'via', RegMod :: module(), ViaName :: term()}.
-start_link(Mod, Args, Options) ->
- gen:start(?MODULE, link, Mod, Args, Options).
+-type start_opt() :: % Duplicate of gen:option()
+ {'timeout', Timeout :: timeout()}
+ | {'spawn_opt', SpawnOptions :: [proc_lib:spawn_option()]}
+ | enter_loop_opt().
+%%
+-type enter_loop_opt() :: % Some gen:option()s works for enter_loop/*
+ {'hibernate_after', HibernateAfterTimeout :: timeout()}
+ | {'debug', Dbgs :: [sys:debug_option()]}.
-start_link(Name, Mod, Args, Options) ->
- gen:start(?MODULE, link, Name, Mod, Args, Options).
+-type start_ret() :: % gen:start_ret() without monitor return
+ {'ok', Pid :: pid()}
+ | 'ignore'
+ | {'error', Reason :: term()}.
-start_monitor(Mod, Args, Options) ->
- gen:start(?MODULE, monitor, Mod, Args, Options).
+-type start_mon_ret() :: % gen:start_ret() with only monitor return
+ {'ok', {Pid :: pid(), MonRef :: reference()}}
+ | 'ignore'
+ | {'error', Reason :: term()}.
-start_monitor(Name, Mod, Args, Options) ->
- gen:start(?MODULE, monitor, Name, Mod, Args, Options).
+%%% ---------------------------------------------------
+
+-spec start(
+ Module :: module(),
+ Args :: term(),
+ Options :: [start_opt()]
+ ) ->
+ start_ret().
+%%
+start(Module, Args, Options) ->
+ gen:start(?MODULE, nolink, Module, Args, Options).
+
+-spec start(
+ ServerName :: server_name(),
+ Module :: module(),
+ Args :: term(),
+ Options :: [start_opt()]
+ ) ->
+ start_ret().
+%%
+start(ServerName, Module, Args, Options) ->
+ gen:start(?MODULE, nolink, ServerName, Module, Args, Options).
+
+-spec start_link(
+ Module :: module(),
+ Args :: term(),
+ Options :: [start_opt()]
+ ) ->
+ start_ret().
+%%
+start_link(Module, Args, Options) ->
+ gen:start(?MODULE, link, Module, Args, Options).
+
+-spec start_link(
+ ServerName :: server_name(),
+ Module :: module(),
+ Args :: term(),
+ Options :: [start_opt()]
+ ) ->
+ start_ret().
+%%
+start_link(ServerName, Module, Args, Options) ->
+ gen:start(?MODULE, link, ServerName, Module, Args, Options).
+
+-spec start_monitor(
+ Module :: module(),
+ Args :: term(),
+ Options :: [start_opt()]
+ ) ->
+ start_mon_ret().
+%%
+start_monitor(Module, Args, Options) ->
+ gen:start(?MODULE, monitor, Module, Args, Options).
+
+-spec start_monitor(
+ ServerName :: server_name(),
+ Module :: module(),
+ Args :: term(),
+ Options :: [start_opt()]
+ ) ->
+ start_mon_ret().
+%%
+start_monitor(ServerName, Module, Args, Options) ->
+ gen:start(?MODULE, monitor, ServerName, Module, Args, Options).
%% -----------------------------------------------------------------
@@ -218,11 +331,22 @@ start_monitor(Name, Mod, Args, Options) ->
%% If the server is located at another node, that node will
%% be monitored.
%% -----------------------------------------------------------------
-stop(Name) ->
- gen:stop(Name).
-stop(Name, Reason, Timeout) ->
- gen:stop(Name, Reason, Timeout).
+-spec stop(
+ ServerRef :: server_ref()
+ ) -> ok.
+%%
+stop(ServerRef) ->
+ gen:stop(ServerRef).
+
+-spec stop(
+ ServerRef :: server_ref(),
+ Reason :: term(),
+ Timeout :: timeout()
+ ) -> ok.
+%%
+stop(ServerRef, Reason, Timeout) ->
+ gen:stop(ServerRef, Reason, Timeout).
%% -----------------------------------------------------------------
%% Make a call to a generic server.
@@ -231,20 +355,34 @@ stop(Name, Reason, Timeout) ->
%% If the client is trapping exits and is linked server termination
%% is handled here (? Shall we do that here (or rely on timeouts) ?).
%% -----------------------------------------------------------------
-call(Name, Request) ->
- case catch gen:call(Name, '$gen_call', Request) of
+
+-spec call(
+ ServerRef :: server_ref(),
+ Request :: term()
+ ) ->
+ Reply :: term().
+%%
+call(ServerRef, Request) ->
+ case catch gen:call(ServerRef, '$gen_call', Request) of
{ok,Res} ->
Res;
{'EXIT',Reason} ->
- exit({Reason, {?MODULE, call, [Name, Request]}})
+ exit({Reason, {?MODULE, call, [ServerRef, Request]}})
end.
-call(Name, Request, Timeout) ->
- case catch gen:call(Name, '$gen_call', Request, Timeout) of
+-spec call(
+ ServerRef :: server_ref(),
+ Request :: term(),
+ Timeout :: timeout()
+ ) ->
+ Reply :: term().
+%%
+call(ServerRef, Request, Timeout) ->
+ case catch gen:call(ServerRef, '$gen_call', Request, Timeout) of
{ok,Res} ->
Res;
{'EXIT',Reason} ->
- exit({Reason, {?MODULE, call, [Name, Request, Timeout]}})
+ exit({Reason, {?MODULE, call, [ServerRef, Request, Timeout]}})
end.
%% -----------------------------------------------------------------
@@ -252,28 +390,183 @@ call(Name, Request, Timeout) ->
%% used with wait_response/2 or check_response/2 to fetch the
%% result of the request.
--spec send_request(Name::server_ref(), Request::term()) -> request_id().
-send_request(Name, Request) ->
- gen:send_request(Name, '$gen_call', Request).
+-spec send_request(ServerRef::server_ref(), Request::term()) ->
+ ReqId::request_id().
+
+send_request(ServerRef, Request) ->
+ try
+ gen:send_request(ServerRef, '$gen_call', Request)
+ catch
+ error:badarg ->
+ error(badarg, [ServerRef, Request])
+ end.
+
+-spec send_request(ServerRef::server_ref(),
+ Request::term(),
+ Label::term(),
+ ReqIdCollection::request_id_collection()) ->
+ NewReqIdCollection::request_id_collection().
+
+send_request(ServerRef, Request, Label, ReqIdCol) ->
+ try
+ gen:send_request(ServerRef, '$gen_call', Request, Label, ReqIdCol)
+ catch
+ error:badarg ->
+ error(badarg, [ServerRef, Request, Label, ReqIdCol])
+ end.
+
+-spec wait_response(ReqId, WaitTime) -> Result when
+ ReqId :: request_id(),
+ WaitTime :: response_timeout(),
+ Response :: {reply, Reply::term()}
+ | {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'timeout'.
+
+wait_response(ReqId, WaitTime) ->
+ try
+ gen:wait_response(ReqId, WaitTime)
+ catch
+ error:badarg ->
+ error(badarg, [ReqId, WaitTime])
+ end.
+
+-spec wait_response(ReqIdCollection, WaitTime, Delete) -> Result when
+ ReqIdCollection :: request_id_collection(),
+ WaitTime :: response_timeout(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'timeout'.
+
+wait_response(ReqIdCol, WaitTime, Delete) ->
+ try
+ gen:wait_response(ReqIdCol, WaitTime, Delete)
+ catch
+ error:badarg ->
+ error(badarg, [ReqIdCol, WaitTime, Delete])
+ end.
+
+-spec receive_response(ReqId, Timeout) -> Result when
+ ReqId :: request_id(),
+ Timeout :: response_timeout(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'timeout'.
+
+receive_response(ReqId, Timeout) ->
+ try
+ gen:receive_response(ReqId, Timeout)
+ catch
+ error:badarg ->
+ error(badarg, [ReqId, Timeout])
+ end.
+
+-spec receive_response(ReqIdCollection, Timeout, Delete) -> Result when
+ ReqIdCollection :: request_id_collection(),
+ Timeout :: response_timeout(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'timeout'.
+
+receive_response(ReqIdCol, Timeout, Delete) ->
+ try
+ gen:receive_response(ReqIdCol, Timeout, Delete)
+ catch
+ error:badarg ->
+ error(badarg, [ReqIdCol, Timeout, Delete])
+ end.
+
+-spec check_response(Msg, ReqId) -> Result when
+ Msg :: term(),
+ ReqId :: request_id(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'no_reply'.
+
+check_response(Msg, ReqId) ->
+ try
+ gen:check_response(Msg, ReqId)
+ catch
+ error:badarg ->
+ error(badarg, [Msg, ReqId])
+ end.
+
+-spec check_response(Msg, ReqIdCollection, Delete) -> Result when
+ Msg :: term(),
+ ReqIdCollection :: request_id_collection(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'no_reply'.
+
+check_response(Msg, ReqIdCol, Delete) ->
+ try
+ gen:check_response(Msg, ReqIdCol, Delete)
+ catch
+ error:badarg ->
+ error(badarg, [Msg, ReqIdCol, Delete])
+ end.
--spec wait_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), server_ref()}}.
-wait_response(RequestId, Timeout) ->
- gen:wait_response(RequestId, Timeout).
+-spec reqids_new() ->
+ NewReqIdCollection::request_id_collection().
--spec receive_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {Reason::term(), server_ref()}}.
-receive_response(RequestId, Timeout) ->
- gen:receive_response(RequestId, Timeout).
+reqids_new() ->
+ gen:reqids_new().
--spec check_response(Msg::term(), RequestId::request_id()) ->
- {reply, Reply::term()} | 'no_reply' | {error, {Reason::term(), server_ref()}}.
-check_response(Msg, RequestId) ->
- gen:check_response(Msg, RequestId).
+-spec reqids_size(ReqIdCollection::request_id_collection()) ->
+ non_neg_integer().
+
+reqids_size(ReqIdCollection) ->
+ try
+ gen:reqids_size(ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqIdCollection])
+ end.
+
+-spec reqids_add(ReqId::request_id(), Label::term(),
+ ReqIdCollection::request_id_collection()) ->
+ NewReqIdCollection::request_id_collection().
+
+reqids_add(ReqId, Label, ReqIdCollection) ->
+ try
+ gen:reqids_add(ReqId, Label, ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqId, Label, ReqIdCollection])
+ end.
+
+-spec reqids_to_list(ReqIdCollection::request_id_collection()) ->
+ [{ReqId::request_id(), Label::term()}].
+
+reqids_to_list(ReqIdCollection) ->
+ try
+ gen:reqids_to_list(ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqIdCollection])
+ end.
%% -----------------------------------------------------------------
%% Make a cast to a generic server.
%% -----------------------------------------------------------------
+
+-spec cast(
+ ServerRef :: server_ref(),
+ Request :: term()
+ ) ->
+ ok.
+%%
cast({global,Name}, Request) ->
catch global:send(Name, cast_msg(Request)),
ok;
@@ -296,15 +589,36 @@ cast_msg(Request) -> {'$gen_cast',Request}.
%% -----------------------------------------------------------------
%% Send a reply to the client.
%% -----------------------------------------------------------------
-reply(From, Reply) ->
- gen:reply(From, Reply).
+
+-spec reply(
+ Client :: from(),
+ Reply :: term()
+ ) ->
+ ok.
+%%
+reply(Client, Reply) ->
+ gen:reply(Client, Reply).
%% -----------------------------------------------------------------
%% Asynchronous broadcast, returns nothing, it's just send 'n' pray
%%-----------------------------------------------------------------
+
+-spec abcast(
+ Name :: atom(),
+ Request :: term()
+ ) ->
+ abcast.
+%%
abcast(Name, Request) when is_atom(Name) ->
do_abcast([node() | nodes()], Name, cast_msg(Request)).
+-spec abcast(
+ Nodes :: [node()],
+ Name :: atom(),
+ Request :: term()
+ ) ->
+ abcast.
+%%
abcast(Nodes, Name, Request) when is_list(Nodes), is_atom(Name) ->
do_abcast(Nodes, Name, cast_msg(Request)).
@@ -323,19 +637,48 @@ do_abcast([], _,_) -> abcast.
%%% queue, it would probably become confused. Late answers will
%%% now arrive to the terminated middleman and so be discarded.
%%% -----------------------------------------------------------------
-multi_call(Name, Req)
- when is_atom(Name) ->
- do_multi_call([node() | nodes()], Name, Req, infinity).
-multi_call(Nodes, Name, Req)
+-spec multi_call(
+ Name :: atom(),
+ Request :: term()
+ ) ->
+ {Replies ::
+ [{Node :: node(), Reply :: term()}],
+ BadNodes :: [node()]
+ }.
+%%
+multi_call(Name, Request)
+ when is_atom(Name) ->
+ do_multi_call([node() | nodes()], Name, Request, infinity).
+
+-spec multi_call(
+ Nodes :: [node()],
+ Name :: atom(),
+ Request :: term()
+ ) ->
+ {Replies ::
+ [{Node :: node(), Reply :: term()}],
+ BadNodes :: [node()]
+ }.
+%%
+multi_call(Nodes, Name, Request)
when is_list(Nodes), is_atom(Name) ->
- do_multi_call(Nodes, Name, Req, infinity).
-
-multi_call(Nodes, Name, Req, infinity) ->
- do_multi_call(Nodes, Name, Req, infinity);
-multi_call(Nodes, Name, Req, Timeout)
- when is_list(Nodes), is_atom(Name), is_integer(Timeout), Timeout >= 0 ->
- do_multi_call(Nodes, Name, Req, Timeout).
+ do_multi_call(Nodes, Name, Request, infinity).
+
+-spec multi_call(
+ Nodes :: [node()],
+ Name :: atom(),
+ Request :: term(),
+ Timeout :: timeout()
+ ) ->
+ {Replies ::
+ [{Node :: node(), Reply :: term()}],
+ BadNodes :: [node()]
+ }.
+%%
+multi_call(Nodes, Name, Request, Timeout)
+ when is_list(Nodes), is_atom(Name), ?is_timeout(Timeout) ->
+ do_multi_call(Nodes, Name, Request, Timeout).
%%-----------------------------------------------------------------
@@ -349,25 +692,106 @@ multi_call(Nodes, Name, Req, Timeout)
%% The user is responsible for any initialization of the
%% process, including registering a name for it.
%%-----------------------------------------------------------------
-enter_loop(Mod, Options, State) ->
+
+-spec enter_loop(
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term()
+ ) ->
+ no_return().
+%%
+enter_loop(Mod, Options, State)
+ when is_atom(Mod), is_list(Options) ->
enter_loop(Mod, Options, State, self(), infinity).
+-spec enter_loop(
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ ServerName :: server_name() | pid()
+ ) ->
+ no_return();
+ (
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ Timeout :: timeout()
+ ) ->
+ no_return();
+ (
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ Hibernate :: 'hibernate'
+ ) ->
+ no_return();
+ (
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ Cont :: {'continue', term()}
+ ) ->
+ no_return().
+%%
enter_loop(Mod, Options, State, ServerName = {Scope, _})
- when Scope == local; Scope == global ->
+ when is_atom(Mod), is_list(Options), Scope == local;
+ is_atom(Mod), is_list(Options), Scope == global ->
enter_loop(Mod, Options, State, ServerName, infinity);
-
-enter_loop(Mod, Options, State, ServerName = {via, _, _}) ->
+%%
+enter_loop(Mod, Options, State, ServerName = {via, _, _})
+ when is_atom(Mod), is_list(Options) ->
enter_loop(Mod, Options, State, ServerName, infinity);
-
-enter_loop(Mod, Options, State, Timeout) ->
- enter_loop(Mod, Options, State, self(), Timeout).
-
-enter_loop(Mod, Options, State, ServerName, Timeout) ->
+%%
+enter_loop(Mod, Options, State, TimeoutOrHibernate)
+ when is_atom(Mod), is_list(Options), ?is_timeout(TimeoutOrHibernate);
+ is_atom(Mod), is_list(Options), TimeoutOrHibernate =:= hibernate ->
+ enter_loop(Mod, Options, State, self(), TimeoutOrHibernate);
+%%
+enter_loop(Mod, Options, State, {continue, _}=Continue)
+ when is_atom(Mod), is_list(Options) ->
+ enter_loop(Mod, Options, State, self(), Continue).
+
+-spec enter_loop(
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ ServerName :: server_name() | pid(),
+ Timeout :: timeout()
+ ) ->
+ no_return();
+ (
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ ServerName :: server_name() | pid(),
+ Hibernate :: 'hibernate'
+ ) ->
+ no_return();
+ (
+ Module :: module(),
+ Options :: [enter_loop_opt()],
+ State :: term(),
+ ServerName :: server_name() | pid(),
+ Cont :: {'continue', term()}
+ ) ->
+ no_return().
+%%
+enter_loop(Mod, Options, State, ServerName, TimeoutOrHibernate)
+ when is_atom(Mod), is_list(Options), ?is_timeout(TimeoutOrHibernate);
+ is_atom(Mod), is_list(Options), TimeoutOrHibernate =:= hibernate ->
Name = gen:get_proc_name(ServerName),
Parent = gen:get_parent(),
Debug = gen:debug_options(Name, Options),
HibernateAfterTimeout = gen:hibernate_after(Options),
- loop(Parent, Name, State, Mod, Timeout, HibernateAfterTimeout, Debug).
+ loop(Parent, Name, State, Mod, TimeoutOrHibernate, HibernateAfterTimeout, Debug);
+%%
+enter_loop(Mod, Options, State, ServerName, {continue, _}=Continue)
+ when is_atom(Mod), is_list(Options) ->
+ Name = gen:get_proc_name(ServerName),
+ Parent = gen:get_parent(),
+ Debug = gen:debug_options(Name, Options),
+ HibernateAfterTimeout = gen:hibernate_after(Options),
+ loop(Parent, Name, State, Mod, Continue, HibernateAfterTimeout, Debug).
%%%========================================================================
%%% Gen-callback functions
@@ -391,10 +815,14 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
{ok, {ok, State}} ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, State, Mod, infinity, HibernateAfterTimeout, Debug);
- {ok, {ok, State, TimeoutHibernateOrContinue}} ->
+ {ok, {ok, State, TimeoutOrHibernate}}
+ when ?is_timeout(TimeoutOrHibernate);
+ TimeoutOrHibernate =:= hibernate ->
proc_lib:init_ack(Starter, {ok, self()}),
- loop(Parent, Name, State, Mod, TimeoutHibernateOrContinue,
- HibernateAfterTimeout, Debug);
+ loop(Parent, Name, State, Mod, TimeoutOrHibernate, HibernateAfterTimeout, Debug);
+ {ok, {ok, State, {continue, _}=Continue}} ->
+ proc_lib:init_ack(Starter, {ok, self()}),
+ loop(Parent, Name, State, Mod, Continue, HibernateAfterTimeout, Debug);
{ok, {stop, Reason}} ->
%% For consistency, we must make sure that the
%% registered name (if any) is unregistered before
@@ -752,13 +1180,14 @@ handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod, HibernateAfterTim
{ok, {reply, Reply, NState}} ->
reply(From, Reply),
loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, []);
- {ok, {reply, Reply, NState, Time1}} ->
+ {ok, {reply, Reply, NState, TimeoutOrHibernate}}
+ when ?is_timeout(TimeoutOrHibernate);
+ TimeoutOrHibernate =:= hibernate ->
reply(From, Reply),
- loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, []);
- {ok, {noreply, NState}} ->
- loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, []);
- {ok, {noreply, NState, Time1}} ->
- loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, []);
+ loop(Parent, Name, NState, Mod, TimeoutOrHibernate, HibernateAfterTimeout, []);
+ {ok, {reply, Reply, NState, {continue, _}=Continue}} ->
+ reply(From, Reply),
+ loop(Parent, Name, NState, Mod, Continue, HibernateAfterTimeout, []);
{ok, {stop, Reason, Reply, NState}} ->
try
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, [])
@@ -777,17 +1206,14 @@ handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Mod, HibernateAfterTim
{ok, {reply, Reply, NState}} ->
Debug1 = reply(Name, From, Reply, NState, Debug),
loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, Debug1);
- {ok, {reply, Reply, NState, Time1}} ->
+ {ok, {reply, Reply, NState, TimeoutOrHibernate}}
+ when ?is_timeout(TimeoutOrHibernate);
+ TimeoutOrHibernate =:= hibernate ->
Debug1 = reply(Name, From, Reply, NState, Debug),
- loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, Debug1);
- {ok, {noreply, NState}} ->
- Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
- {noreply, NState}),
- loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, Debug1);
- {ok, {noreply, NState, Time1}} ->
- Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
- {noreply, NState}),
- loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, Debug1);
+ loop(Parent, Name, NState, Mod, TimeoutOrHibernate, HibernateAfterTimeout, Debug1);
+ {ok, {reply, Reply, NState, {continue, _}=Continue}} ->
+ Debug1 = reply(Name, From, Reply, NState, Debug),
+ loop(Parent, Name, NState, Mod, Continue, HibernateAfterTimeout, Debug1);
{ok, {stop, Reason, Reply, NState}} ->
try
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, Debug)
@@ -805,8 +1231,12 @@ handle_common_reply(Reply, Parent, Name, From, Msg, Mod, HibernateAfterTimeout,
case Reply of
{ok, {noreply, NState}} ->
loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, []);
- {ok, {noreply, NState, Time1}} ->
- loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, []);
+ {ok, {noreply, NState, TimeoutOrHibernate}}
+ when ?is_timeout(TimeoutOrHibernate);
+ TimeoutOrHibernate =:= hibernate ->
+ loop(Parent, Name, NState, Mod, TimeoutOrHibernate, HibernateAfterTimeout, []);
+ {ok, {noreply, NState, {continue, _}=Continue}} ->
+ loop(Parent, Name, NState, Mod, Continue, HibernateAfterTimeout, []);
{ok, {stop, Reason, NState}} ->
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, []);
{'EXIT', Class, Reason, Stacktrace} ->
@@ -821,10 +1251,14 @@ handle_common_reply(Reply, Parent, Name, From, Msg, Mod, HibernateAfterTimeout,
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loop(Parent, Name, NState, Mod, infinity, HibernateAfterTimeout, Debug1);
- {ok, {noreply, NState, Time1}} ->
- Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
- {noreply, NState}),
- loop(Parent, Name, NState, Mod, Time1, HibernateAfterTimeout, Debug1);
+ {ok, {noreply, NState, TimeoutOrHibernate}}
+ when ?is_timeout(TimeoutOrHibernate);
+ TimeoutOrHibernate =:= hibernate ->
+ Debug1 = sys:handle_debug(Debug, fun print_event/3, Name, {noreply, NState}),
+ loop(Parent, Name, NState, Mod, TimeoutOrHibernate, HibernateAfterTimeout, Debug1);
+ {ok, {noreply, NState, {continue, _}=Continue}} ->
+ Debug1 = sys:handle_debug(Debug, fun print_event/3, Name, {noreply, NState}),
+ loop(Parent, Name, NState, Mod, Continue, HibernateAfterTimeout, Debug1);
{ok, {stop, Reason, NState}} ->
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Mod, NState, Debug);
{'EXIT', Class, Reason, Stacktrace} ->
@@ -906,27 +1340,28 @@ print_event(Dev, Event, Name) ->
-spec terminate(_, _, _, _, _, _, _, _) -> no_return().
terminate(Reason, Stacktrace, Name, From, Msg, Mod, State, Debug) ->
- terminate(exit, Reason, Stacktrace, Reason, Name, From, Msg, Mod, State, Debug).
+ terminate(exit, Reason, Stacktrace, false, Name, From, Msg, Mod, State, Debug).
-spec terminate(_, _, _, _, _, _, _, _, _) -> no_return().
terminate(Class, Reason, Stacktrace, Name, From, Msg, Mod, State, Debug) ->
- ReportReason = {Reason, Stacktrace},
- terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State, Debug).
+ terminate(Class, Reason, Stacktrace, true, Name, From, Msg, Mod, State, Debug).
-spec terminate(_, _, _, _, _, _, _, _, _, _) -> no_return().
-terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State, Debug) ->
+terminate(Class, Reason, Stacktrace, ReportStacktrace, Name, From, Msg, Mod, State, Debug) ->
Reply = try_terminate(Mod, terminate_reason(Class, Reason, Stacktrace), State),
case Reply of
{'EXIT', C, R, S} ->
- error_info({R, S}, Name, From, Msg, Mod, State, Debug),
+ error_info(R, S, Name, From, Msg, Mod, State, Debug),
erlang:raise(C, R, S);
_ ->
case {Class, Reason} of
{exit, normal} -> ok;
{exit, shutdown} -> ok;
{exit, {shutdown,_}} -> ok;
- _ ->
- error_info(ReportReason, Name, From, Msg, Mod, State, Debug)
+ _ when ReportStacktrace ->
+ error_info(Reason, Stacktrace, Name, From, Msg, Mod, State, Debug);
+ _ ->
+ error_info(Reason, undefined, Name, From, Msg, Mod, State, Debug)
end
end,
case Stacktrace of
@@ -939,19 +1374,37 @@ terminate(Class, Reason, Stacktrace, ReportReason, Name, From, Msg, Mod, State,
terminate_reason(error, Reason, Stacktrace) -> {Reason, Stacktrace};
terminate_reason(exit, Reason, _Stacktrace) -> Reason.
-error_info(_Reason, application_controller, _From, _Msg, _Mod, _State, _Debug) ->
+error_info(_Reason, _ST, application_controller, _From, _Msg, _Mod, _State, _Debug) ->
%% OTP-5811 Don't send an error report if it's the system process
%% application_controller which is terminating - let init take care
%% of it instead
ok;
-error_info(Reason, Name, From, Msg, Mod, State, Debug) ->
+error_info(Reason, ST, Name, From, Msg, Mod, State, Debug) ->
Log = sys:get_log(Debug),
+ Status =
+ gen:format_status(Mod, terminate,
+ #{ reason => Reason,
+ state => State,
+ message => Msg,
+ log => Log },
+ [get(),State]),
+ ReportReason =
+ if ST == undefined ->
+ %% When ST is undefined, it should not be included in the
+ %% reported reason for the crash as it is then caused
+ %% by an invalid return from a callback and thus thus the
+ %% stacktrace is irrelevant.
+ maps:get(reason, Status);
+ true ->
+ {maps:get(reason, Status), ST}
+ end,
+
?LOG_ERROR(#{label=>{gen_server,terminate},
name=>Name,
- last_message=>Msg,
- state=>format_status(terminate, Mod, get(), State),
- log=>format_log_state(Mod, Log),
- reason=>Reason,
+ last_message=>maps:get(message,Status),
+ state=>maps:get('EXIT',Status,maps:get('$status',Status,maps:get(state,Status))),
+ log=>format_log_state(Mod,maps:get(log,Status)),
+ reason=>ReportReason,
client_info=>client_stacktrace(From)},
#{domain=>[otp],
report_cb=>fun gen_server:format_log/2,
@@ -1208,37 +1661,42 @@ mod(_) -> "t".
format_status(Opt, StatusData) ->
[PDict, SysState, Parent, Debug, [Name, State, Mod, _Time, _HibernateAfterTimeout]] = StatusData,
Header = gen:format_status_header("Status for generic server", Name),
- Log = sys:get_log(Debug),
- Specific = case format_status(Opt, Mod, PDict, State) of
- S when is_list(S) -> S;
- S -> [S]
- end,
+ Status =
+ case gen:format_status(Mod, Opt, #{ state => State, log => sys:get_log(Debug) },
+ [PDict, State]) of
+ #{ 'EXIT' := R } = M ->
+ M#{ '$status' => [{data,[{"State",R}]}] };
+ %% Status is set when the old format_status/2 is called,
+ %% so we do a little backwards compatibility dance here
+ #{ '$status' := S } = M when is_list(S) -> M;
+ #{ '$status' := S } = M -> M#{ '$status' := [S] };
+ #{ state := S } = M ->
+ M#{ '$status' => [{data, [{"State",S}] }] }
+ end,
[{header, Header},
{data, [{"Status", SysState},
{"Parent", Parent},
- {"Logged events", format_log_state(Mod, Log)}]} |
- Specific].
+ {"Logged events", format_log_state(Mod, maps:get(log,Status))}]} |
+ maps:get('$status',Status)].
format_log_state(Mod, Log) ->
- [case Event of
- {out,Msg,From,State} ->
- {out,Msg,From,format_status(terminate, Mod, get(), State)};
- {noreply,State} ->
- {noreply,format_status(terminate, Mod, get(), State)};
- _ -> Event
- end || Event <- Log].
-
-format_status(Opt, Mod, PDict, State) ->
- DefStatus = case Opt of
- terminate -> State;
- _ -> [{data, [{"State", State}]}]
- end,
- case erlang:function_exported(Mod, format_status, 2) of
- true ->
- case catch Mod:format_status(Opt, [PDict, State]) of
- {'EXIT', _} -> DefStatus;
- Else -> Else
- end;
- _ ->
- DefStatus
+ %% If format_status/1 was exported, the log has already been handled by
+ %% that call, so we should not pass all log events into the callback again.
+ case erlang:function_exported(Mod, format_status, 1) of
+ false ->
+ [case Event of
+ {out,Msg,From,State} ->
+ Status = gen:format_status(
+ Mod, terminate, #{ state => State },
+ [get(), State]),
+ {out, Msg, From, maps:get(state, Status) };
+ {noreply,State} ->
+ Status = gen:format_status(
+ Mod, terminate, #{ state => State },
+ [get(), State]),
+ {noreply, maps:get(state, Status)};
+ _ -> Event
+ end || Event <- Log];
+ true ->
+ Log
end.
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index 30d40fefc5..e3fa14a8a8 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,8 +32,12 @@
start_monitor/3,start_monitor/4,
stop/1,stop/3,
cast/2,call/2,call/3,
- send_request/2,wait_response/1,wait_response/2,
- receive_response/1,receive_response/2,check_response/2,
+ send_request/2, send_request/4,
+ wait_response/1, wait_response/2, wait_response/3,
+ receive_response/1, receive_response/2, receive_response/3,
+ check_response/2, check_response/3,
+ reqids_new/0, reqids_size/1,
+ reqids_add/3, reqids_to_list/1,
enter_loop/4,enter_loop/5,enter_loop/6,
reply/1,reply/2]).
@@ -61,6 +65,7 @@
-export_type(
[event_type/0,
from/0,
+ reply_tag/0,
callback_mode_result/0,
init_result/1,
init_result/2,
@@ -70,7 +75,10 @@
event_handler_result/2,
reply_action/0,
enter_action/0,
- action/0
+ action/0,
+ request_id/0,
+ request_id_collection/0,
+ format_status/0
]).
%% Old types, not advertised
-export_type(
@@ -85,15 +93,17 @@
[server_name/0,
server_ref/0,
start_opt/0,
+ enter_loop_opt/0,
start_ret/0,
- enter_loop_opt/0]).
+ start_mon_ret/0]).
%%%==========================================================================
%%% Interface functions.
%%%==========================================================================
-type from() ::
- {To :: pid(), Tag :: term()}. % Reply-to specifier for call
+ {To :: pid(), Tag :: reply_tag()}. % Reply-to specifier for call
+-opaque reply_tag() :: gen:reply_tag().
-type state() ::
state_name() | % For StateName/3 callback functions
@@ -110,6 +120,8 @@
-type timeout_event_type() ::
'timeout' | {'timeout', Name :: term()} | 'state_timeout'.
+-type event_content() :: term().
+
-type callback_mode_result() ::
callback_mode() | [callback_mode() | state_enter()].
-type callback_mode() :: 'state_functions' | 'handle_event_function'.
@@ -161,7 +173,7 @@
%% action() list is the first to be delivered.
{'next_event', % Insert event as the next to handle
EventType :: event_type(),
- EventContent :: term()} |
+ EventContent :: event_content()} |
{'change_callback_module', NewModule :: module()} |
{'push_callback_module', NewModule :: module()} |
'pop_callback_module' |
@@ -174,24 +186,24 @@
-type timeout_action() ::
(Time :: event_timeout()) | % {timeout,Time,Time}
{'timeout', % Set the event_timeout option
- Time :: event_timeout(), EventContent :: term()} |
+ Time :: event_timeout(), EventContent :: event_content()} |
{'timeout', % Set the event_timeout option
Time :: event_timeout(),
- EventContent :: term(),
+ EventContent :: event_content(),
Options :: (timeout_option() | [timeout_option()])} |
%%
{{'timeout', Name :: term()}, % Set the generic_timeout option
- Time :: generic_timeout(), EventContent :: term()} |
+ Time :: generic_timeout(), EventContent :: event_content()} |
{{'timeout', Name :: term()}, % Set the generic_timeout option
Time :: generic_timeout(),
- EventContent :: term(),
+ EventContent :: event_content(),
Options :: (timeout_option() | [timeout_option()])} |
%%
{'state_timeout', % Set the state_timeout option
- Time :: state_timeout(), EventContent :: term()} |
+ Time :: state_timeout(), EventContent :: event_content()} |
{'state_timeout', % Set the state_timeout option
Time :: state_timeout(),
- EventContent :: term(),
+ EventContent :: event_content(),
Options :: (timeout_option() | [timeout_option()])} |
timeout_cancel_action() |
timeout_update_action().
@@ -200,9 +212,10 @@
{{'timeout', Name :: term()}, 'cancel'} |
{'state_timeout', 'cancel'}.
-type timeout_update_action() ::
- {'timeout', 'update', EventContent :: term()} |
- {{'timeout', Name :: term()}, 'update', EventContent :: term()} |
- {'state_timeout', 'update', EventContent :: term()}.
+ {'timeout', 'update', EventContent :: event_content()} |
+ {{'timeout', Name :: term()},
+ 'update', EventContent :: event_content()} |
+ {'state_timeout', 'update', EventContent :: event_content()}.
-type reply_action() ::
{'reply', % Reply to a caller
From :: from(), Reply :: term()}.
@@ -278,7 +291,12 @@
Replies :: [reply_action()] | reply_action(),
NewData :: DataType}.
--type request_id() :: term().
+-opaque request_id() :: gen:request_id().
+
+-opaque request_id_collection() :: gen:request_id_collection().
+
+-type response_timeout() ::
+ timeout() | {abs, integer()}.
%% The state machine init function. It is called only once and
%% the server is not running until this function has returned
@@ -303,11 +321,11 @@
-callback state_name(
'enter',
OldStateName :: state_name(),
- Data :: data()) ->
+ data()) ->
state_enter_result('state_name');
(event_type(),
- EventContent :: term(),
- Data :: data()) ->
+ event_content(),
+ data()) ->
event_handler_result(state_name()).
%%
%% State callback for all states
@@ -315,21 +333,21 @@
-callback handle_event(
'enter',
OldState :: state(),
- State, % Current state
- Data :: data()) ->
- state_enter_result(State);
+ CurrentState,
+ data()) ->
+ state_enter_result(CurrentState);
(event_type(),
- EventContent :: term(),
- State :: state(), % Current state
- Data :: data()) ->
- event_handler_result(state()).
+ event_content(),
+ CurrentState :: state(),
+ data()) ->
+ event_handler_result(state()). % New state
%% Clean up before the server terminates.
-callback terminate(
Reason :: 'normal' | 'shutdown' | {'shutdown', term()}
| term(),
- State :: state(),
- Data :: data()) ->
+ CurrentState :: state(),
+ data()) ->
any().
%% Note that the new code can expect to get an OldState from
@@ -347,6 +365,8 @@
%% often condensed way. For StatusOption =:= 'normal' the preferred
%% return term is [{data,[{"State",FormattedState}]}], and for
%% StatusOption =:= 'terminate' it is just FormattedState.
+%%
+%% Deprecated
-callback format_status(
StatusOption,
[ [{Key :: term(), Value :: term()}] |
@@ -355,8 +375,24 @@
Status :: term() when
StatusOption :: 'normal' | 'terminate'.
+-type format_status() ::
+ #{ state => state(),
+ data => data(),
+ reason => term(),
+ queue => [{event_type(), event_content()}],
+ postponed => [{event_type(), event_content()}],
+ timeouts => [{timeout_event_type(), event_content()}],
+ log => [sys:system_event()] }.
+
+%% Format the callback module status in some sensible that is
+%% often condensed way.
+-callback format_status(Status) -> NewStatus when
+ Status :: format_status(),
+ NewStatus :: format_status().
+
-optional_callbacks(
- [format_status/2, % Has got a default implementation
+ [format_status/1, % Has got a default implementation
+ format_status/2, % Has got a default implementation
terminate/3, % Has got a default implementation
code_change/4, % Only needed by advanced soft upgrade
%%
@@ -393,25 +429,35 @@ state_enter(StateEnter) ->
false
end.
%%
+-define(
+ timeout_event_type(Type),
+ case (Type) of
+ timeout -> true;
+ state_timeout -> true;
+ {timeout,_} -> true;
+ _ -> false
+ end).
+timeout_event_type(Type) ->
+ ?timeout_event_type(Type).
+%%
+-define(
+ from(From),
+ case (From) of
+ {_,_} when is_pid(element(1, (From))) -> true;
+ _ -> false
+ end).
+from(From) ->
+ ?from(From).
+%%
event_type(Type) ->
case Type of
- {call,From} -> from(From);
+ {call,From} -> ?from(From);
%%
cast -> true;
info -> true;
internal -> true;
- _ -> timeout_event_type(Type)
- end.
-%%
-from({Pid,_}) when is_pid(Pid) -> true;
-from(_) -> false.
-%%
-timeout_event_type(Type) ->
- case Type of
- timeout -> true;
- state_timeout -> true;
- {timeout,_Name} -> true;
- _ -> false
+ %%
+ _ -> ?timeout_event_type(Type)
end.
@@ -442,10 +488,10 @@ timeout_event_type(Type) ->
end).
-record(params,
- {callback_mode = undefined :: callback_mode() | undefined,
+ {callback_mode = state_functions :: callback_mode(),
state_enter = false :: boolean(),
parent :: pid(),
- modules :: [module()],
+ modules = [?MODULE] :: nonempty_list(module()),
name :: atom() | pid(),
hibernate_after = infinity :: timeout()
}).
@@ -453,7 +499,7 @@ timeout_event_type(Type) ->
-record(state,
{state_data = {undefined,undefined} ::
{State :: term(),Data :: term()},
- postponed = [] :: [{event_type(),term()}],
+ postponed = [] :: [{event_type(),event_content()}],
timers = #{t0q => []} ::
#{
%% Timeout 0 Queue.
@@ -464,38 +510,44 @@ timeout_event_type(Type) ->
TimeoutType :: timeout_event_type() =>
{TimerRef :: reference() | 0,
- TimeoutMsg :: term()}},
+ TimeoutMsg :: event_content()}},
hibernate = false :: boolean()
}).
%%%==========================================================================
%%% API
--type server_name() ::
- {'global', GlobalName :: term()}
- | {'via', RegMod :: module(), Name :: term()}
- | {'local', atom()}.
--type server_ref() ::
+-type server_name() :: % Duplicate of gen:emgr_name()
+ {'local', atom()}
+ | {'global', GlobalName :: term()}
+ | {'via', RegMod :: module(), Name :: term()}.
+
+-type server_ref() :: % What gen:call/3,4 and gen:stop/1,3 accepts
pid()
| (LocalName :: atom())
| {Name :: atom(), Node :: atom()}
| {'global', GlobalName :: term()}
| {'via', RegMod :: module(), ViaName :: term()}.
--type start_opt() ::
+
+-type start_opt() :: % Duplicate of gen:option()
{'timeout', Time :: timeout()}
- | {'spawn_opt', [proc_lib:start_spawn_option()]}
+ | {'spawn_opt', [proc_lib:spawn_option()]}
| enter_loop_opt().
--type start_ret() ::
+%%
+-type enter_loop_opt() :: % Some gen:option()s works for enter_loop/*
+ {'hibernate_after', HibernateAfterTimeout :: timeout()}
+ | {'debug', Dbgs :: [sys:debug_option()]}.
+
+-type start_ret() :: % gen:start_ret() without monitor return
{'ok', pid()}
| 'ignore'
| {'error', term()}.
--type start_mon_ret() ::
+
+-type start_mon_ret() :: % gen:start_ret() with only monitor return
{'ok', {pid(),reference()}}
| 'ignore'
| {'error', term()}.
--type enter_loop_opt() ::
- {'hibernate_after', HibernateAfterTimeout :: timeout()}
- | {'debug', Dbgs :: [sys:debug_option()]}.
+
@@ -600,34 +652,189 @@ call(ServerRef, Request, Timeout) ->
call_clean(ServerRef, Request, Timeout, Timeout).
-spec send_request(ServerRef::server_ref(), Request::term()) ->
- RequestId::request_id().
+ ReqId::request_id().
send_request(Name, Request) ->
- gen:send_request(Name, '$gen_call', Request).
+ try
+ gen:send_request(Name, '$gen_call', Request)
+ catch
+ error:badarg ->
+ error(badarg, [Name, Request])
+ end.
+
+-spec send_request(ServerRef::server_ref(),
+ Request::term(),
+ Label::term(),
+ ReqIdCollection::request_id_collection()) ->
+ NewReqIdCollection::request_id_collection().
+
+send_request(ServerRef, Request, Label, ReqIdCol) ->
+ try
+ gen:send_request(ServerRef, '$gen_call', Request, Label, ReqIdCol)
+ catch
+ error:badarg ->
+ error(badarg, [ServerRef, Request, Label, ReqIdCol])
+ end.
+
+
+-spec wait_response(ReqId) -> Result when
+ ReqId :: request_id(),
+ Response :: {reply, Reply::term()}
+ | {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'timeout'.
+
+wait_response(ReqId) ->
+ wait_response(ReqId, infinity).
+
+-spec wait_response(ReqId, WaitTime) -> Result when
+ ReqId :: request_id(),
+ WaitTime :: response_timeout(),
+ Response :: {reply, Reply::term()}
+ | {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'timeout'.
+
+wait_response(ReqId, WaitTime) ->
+ try
+ gen:wait_response(ReqId, WaitTime)
+ catch
+ error:badarg ->
+ error(badarg, [ReqId, WaitTime])
+ end.
+
+-spec wait_response(ReqIdCollection, WaitTime, Delete) -> Result when
+ ReqIdCollection :: request_id_collection(),
+ WaitTime :: response_timeout(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'timeout'.
+
+wait_response(ReqIdCol, WaitTime, Delete) ->
+ try
+ gen:wait_response(ReqIdCol, WaitTime, Delete)
+ catch
+ error:badarg ->
+ error(badarg, [ReqIdCol, WaitTime, Delete])
+ end.
+
+-spec receive_response(ReqId) -> Result when
+ ReqId :: request_id(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'timeout'.
--spec wait_response(RequestId::request_id()) ->
- {reply, Reply::term()} | {error, {term(), server_ref()}}.
-wait_response(RequestId) ->
- gen:wait_response(RequestId, infinity).
+receive_response(ReqId) ->
+ receive_response(ReqId, infinity).
--spec wait_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
-wait_response(RequestId, Timeout) ->
- gen:wait_response(RequestId, Timeout).
+-spec receive_response(ReqId, Timeout) -> Result when
+ ReqId :: request_id(),
+ Timeout :: response_timeout(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'timeout'.
--spec receive_response(RequestId::request_id()) ->
- {reply, Reply::term()} | {error, {term(), server_ref()}}.
-receive_response(RequestId) ->
- gen:receive_response(RequestId, infinity).
+receive_response(ReqId, Timeout) ->
+ try
+ gen:receive_response(ReqId, Timeout)
+ catch
+ error:badarg ->
+ error(badarg, [ReqId, Timeout])
+ end.
--spec receive_response(RequestId::request_id(), timeout()) ->
- {reply, Reply::term()} | 'timeout' | {error, {term(), server_ref()}}.
-receive_response(RequestId, Timeout) ->
- gen:receive_response(RequestId, Timeout).
+-spec receive_response(ReqIdCollection, Timeout, Delete) -> Result when
+ ReqIdCollection :: request_id_collection(),
+ Timeout :: response_timeout(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'timeout'.
+
+receive_response(ReqIdCol, Timeout, Delete) ->
+ try
+ gen:receive_response(ReqIdCol, Timeout, Delete)
+ catch
+ error:badarg ->
+ error(badarg, [ReqIdCol, Timeout, Delete])
+ end.
--spec check_response(Msg::term(), RequestId::request_id()) ->
- {reply, Reply::term()} | 'no_reply' | {error, {term(), server_ref()}}.
-check_response(Msg, RequestId) ->
- gen:check_response(Msg, RequestId).
+-spec check_response(Msg, ReqId) -> Result when
+ Msg :: term(),
+ ReqId :: request_id(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: Response | 'no_reply'.
+
+check_response(Msg, ReqId) ->
+ try
+ gen:check_response(Msg, ReqId)
+ catch
+ error:badarg ->
+ error(badarg, [Msg, ReqId])
+ end.
+
+-spec check_response(Msg, ReqIdCollection, Delete) -> Result when
+ Msg :: term(),
+ ReqIdCollection :: request_id_collection(),
+ Delete :: boolean(),
+ Response :: {reply, Reply::term()} |
+ {error, {Reason::term(), server_ref()}},
+ Result :: {Response,
+ Label::term(),
+ NewReqIdCollection::request_id_collection()} |
+ 'no_request' |
+ 'no_reply'.
+
+check_response(Msg, ReqIdCol, Delete) ->
+ try
+ gen:check_response(Msg, ReqIdCol, Delete)
+ catch
+ error:badarg ->
+ error(badarg, [Msg, ReqIdCol, Delete])
+ end.
+
+-spec reqids_new() ->
+ NewReqIdCollection::request_id_collection().
+
+reqids_new() ->
+ gen:reqids_new().
+
+-spec reqids_size(ReqIdCollection::request_id_collection()) ->
+ non_neg_integer().
+
+reqids_size(ReqIdCollection) ->
+ try
+ gen:reqids_size(ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqIdCollection])
+ end.
+
+-spec reqids_add(ReqId::request_id(), Label::term(),
+ ReqIdCollection::request_id_collection()) ->
+ NewReqIdCollection::request_id_collection().
+
+reqids_add(ReqId, Label, ReqIdCollection) ->
+ try
+ gen:reqids_add(ReqId, Label, ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqId, Label, ReqIdCollection])
+ end.
+
+-spec reqids_to_list(ReqIdCollection::request_id_collection()) ->
+ [{ReqId::request_id(), Label::term()}].
+
+reqids_to_list(ReqIdCollection) ->
+ try
+ gen:reqids_to_list(ReqIdCollection)
+ catch
+ error:badarg -> error(badarg, [ReqIdCollection])
+ end.
%% Reply from a state machine callback to whom awaits in call/2
-spec reply([reply_action()] | reply_action()) -> ok.
@@ -694,9 +901,11 @@ call_dirty(ServerRef, Request, Timeout, T) ->
{ok,Reply} ->
Reply
catch
- Class:Reason:Stacktrace ->
+ %% 'gen' raises 'exit' for problems
+ Class:Reason:Stacktrace when Class =:= exit ->
erlang:raise(
Class,
+ %% Wrap the reason according to tradition
{Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
Stacktrace)
end.
@@ -738,12 +947,19 @@ call_clean(ServerRef, Request, Timeout, T) ->
{ok,Reply} ->
Reply
end;
- {Ref,Class,Reason,Stacktrace} ->
+ {Ref,Class,Reason,Stacktrace} when Class =:= exit ->
+ %% 'gen' raises 'exit' for problems
demonitor(Mref, [flush]),
+ %% Pretend it happened in this process
erlang:raise(
Class,
+ %% Wrap the reason according to tradition
{Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
Stacktrace);
+ {Ref,Class,Reason,Stacktrace} ->
+ demonitor(Mref, [flush]),
+ %% Pretend it happened in this process
+ erlang:raise(Class, Reason, Stacktrace);
{'DOWN',Mref,_,_,Reason} ->
%% There is a theoretical possibility that the
%% proxy process gets killed between try--of and !
@@ -774,21 +990,21 @@ enter(
%% We enforce {postpone,false} to ensure that
%% our fake Event gets discarded, thought it might get logged
Actions_1 = listify(Actions) ++ [{postpone,false}],
+ Modules = [Module],
P =
#params{
parent = Parent,
- modules = [Module],
name = Name,
hibernate_after = HibernateAfterTimeout},
S = #state{state_data = {State,Data}},
- Debug_1 = ?sys_debug(Debug, Name, {enter,State}),
- loop_state_callback(
- P, Debug_1, S, Q, {State,Data},
- %% Tunneling Actions through CallbackEvent here...
- %% Special path to go to action handling, after first
- %% finding out the callback mode. CallbackEvent is
- %% a 2-tuple and Actions a list, which achieves this distinction.
- Actions_1).
+ case get_callback_mode(P, Modules) of
+ #params{} = P_1 ->
+ Debug_1 = ?sys_debug(Debug, Name, {enter,Module,State}),
+ loop_enter(P_1, Debug_1, S, Q, {State,Data}, Actions_1);
+ {Class, Reason, Stacktrace} ->
+ P_1 = P#params{modules = Modules},
+ terminate(Class, Reason, Stacktrace, P_1, Debug, S, Q)
+ end.
%%%==========================================================================
%%% gen callbacks
@@ -871,7 +1087,7 @@ system_terminate(Reason, Parent, Debug, {P,S}) ->
update_parent(P, Parent), Debug, S, []).
system_code_change(
- {#params{modules = [Module | _]} = P,
+ {#params{modules = [Module | _] = Modules} = P,
#state{state_data = {State,Data}} = S},
_Mod, OldVsn, Extra) ->
case
@@ -881,9 +1097,14 @@ system_code_change(
end
of
{ok,NewState,NewData} ->
- {ok,
- {P#params{callback_mode = undefined},
- S#state{state_data = {NewState,NewData}}}};
+ case get_callback_mode(P, Modules) of
+ #params{} = P_1 ->
+ {ok,
+ {P_1,
+ S#state{state_data = {NewState,NewData}}}};
+ {Class, Reason, Stacktrace} ->
+ erlang:raise(Class, Reason, Stacktrace)
+ end;
{ok,_} = Error ->
error({case_clause,Error});
Error ->
@@ -902,22 +1123,39 @@ system_replace_state(
format_status(
Opt,
[PDict,SysState,Parent,Debug,
- {#params{name = Name, modules = Modules} = P,
- #state{postponed = Postponed, timers = Timers} = S}]) ->
+ {#params{name = Name, modules = [Mod | _] = Modules},
+ #state{postponed = Postponed, timers = Timers,
+ state_data = {State,Data}}}]) ->
Header = gen:format_status_header("Status for state machine", Name),
- Log = sys:get_log(Debug),
+
+ {NumTimers, ListTimers} = list_timeouts(Timers),
+ StatusMap = #{ state => State, data => Data,
+ postponed => Postponed, log => sys:get_log(Debug),
+ timeouts => ListTimers
+ },
+
+ NewStatusMap =
+ case gen:format_status(Mod, Opt, StatusMap, [PDict,State,Data]) of
+ #{ 'EXIT' := R } ->
+ Crashed = [{data,[{"State",{State,R}}]}],
+ StatusMap#{ '$status' => Crashed };
+ %% Status is set when the old format_status/2 is called,
+ %% so we do a little backwards compatibility dance here
+ #{ '$status' := L } = SM when is_list(L) -> SM;
+ #{ '$status' := T } = SM -> SM#{ '$status' := [T] };
+ #{ state := S, data := D } = SM ->
+ SM#{ '$status' => [{data,[{"State",{S,D}}]}]}
+ end,
+
[{header,Header},
{data,
[{"Status",SysState},
{"Parent",Parent},
{"Modules",Modules},
- {"Time-outs",list_timeouts(Timers)},
- {"Logged Events",Log},
- {"Postponed",Postponed}]} |
- case format_status(Opt, PDict, update_parent(P, Parent), S) of
- L when is_list(L) -> L;
- T -> [T]
- end].
+ {"Time-outs",{NumTimers,maps:get(timeouts,NewStatusMap)}},
+ {"Logged Events",maps:get(log,NewStatusMap)},
+ {"Postponed",maps:get(postponed,NewStatusMap)}]} |
+ maps:get('$status',NewStatusMap)].
%% Update #params.parent only if it differs. This should not
%% be possible today (OTP-22.0), but could happen for example
@@ -946,18 +1184,18 @@ print_event(Dev, SystemEvent, Name) ->
io:format(
Dev, "*DBG* ~tp receive ~ts in state ~tp~n",
[Name,event_string(Event),State]);
- {code_change,Event,State} ->
- io:format(
- Dev, "*DBG* ~tp receive ~ts after code change in state ~tp~n",
- [Name,event_string(Event),State]);
{out,Reply,{To,_Tag}} ->
io:format(
Dev, "*DBG* ~tp send ~tp to ~tw~n",
[Name,Reply,To]);
- {enter,State} ->
+ {enter,Module,State} ->
+ io:format(
+ Dev, "*DBG* ~tp enter ~tp in state ~tp~n",
+ [Name,Module,State]);
+ {module,Module,State} ->
io:format(
- Dev, "*DBG* ~tp enter in state ~tp~n",
- [Name,State]);
+ Dev, "*DBG* ~tp module ~tp in state ~tp~n",
+ [Name,Module,State]);
{start_timer,Action,State} ->
io:format(
Dev, "*DBG* ~tp start_timer ~tp in state ~tp~n",
@@ -1095,15 +1333,9 @@ loop_receive_result(P, ?not_sys_debug = Debug, S, Event) ->
Events = [],
loop_event(P, Debug, S, Event, Events);
loop_receive_result(
- #params{name = Name, callback_mode = CallbackMode} = P, Debug,
+ #params{name = Name} = P, Debug,
#state{state_data = {State,_Data}} = S, Event) ->
- Debug_1 =
- case CallbackMode of
- undefined ->
- sys_debug(Debug, Name, {code_change,Event,State});
- _ ->
- sys_debug(Debug, Name, {in,Event,State})
- end,
+ Debug_1 = sys_debug(Debug, Name, {in,Event,State}),
%% Here is the queue of not yet handled events created
Events = [],
loop_event(P, Debug_1, S, Event, Events).
@@ -1122,25 +1354,24 @@ loop_event(
%% and immediately was awakened.
%%
_ = garbage_collect(),
- loop_event_handler(P, Debug, S, Event, Events);
+ %%
+ %% The field 'hibernate' in S is now invalid and will be
+ %% restored when looping back to loop/3 or loop_event/5.
+ %%
+ Q = [Event|Events],
+ loop_state_callback(P, Debug, S, Q, S#state.state_data, Event);
loop_event(P, Debug, S, Event, Events) ->
- loop_event_handler(P, Debug, S, Event, Events).
-
-%% Call the state function, eventually
-%%
--compile({inline, [loop_event_handler/5]}).
-loop_event_handler(
- P, Debug, #state{state_data = State_Data} = S, Event, Events) ->
%%
%% The field 'hibernate' in S is now invalid and will be
%% restored when looping back to loop/3 or loop_event/5.
%%
Q = [Event|Events],
- loop_state_callback(P, Debug, S, Q, State_Data, Event).
+ loop_state_callback(P, Debug, S, Q, S#state.state_data, Event).
%% Make a state enter call to the state function, we loop back here
%% from further down if state enter calls are enabled
%%
+-compile({inline, [loop_state_enter/9]}).
loop_state_enter(
P, Debug, #state{state_data = {PrevState,_PrevData}} = S,
Q, NextState_NewData,
@@ -1153,8 +1384,26 @@ loop_state_enter(
NextEventsR, Hibernate, TimeoutsR, Postpone,
StateCall, CallbackEvent).
+%% Loop entry point from enter/8 skipping to loop_actions_list
+%% since we should not call a state callback, but initialize
+%% loop variables in the same way; compare to
+%% loop_state_callback/6 just below
+-compile({inline, [loop_enter/6]}).
+loop_enter(P, Debug, S, Q, State_Data, Actions) ->
+ NextEventsR = [],
+ Hibernate = false,
+ TimeoutsR = [],
+ Postpone = false,
+ CallEnter = true,
+ StateCall = true,
+ loop_actions_list(
+ P, Debug, S, Q, State_Data,
+ NextEventsR, Hibernate, TimeoutsR, Postpone,
+ CallEnter, StateCall, Actions).
+
%% Make a state call (not state enter call) to the state function
%%
+-compile({inline, [loop_state_callback/6]}).
loop_state_callback(P, Debug, S, Q, State_Data, CallbackEvent) ->
NextEventsR = [],
Hibernate = false,
@@ -1167,32 +1416,6 @@ loop_state_callback(P, Debug, S, Q, State_Data, CallbackEvent) ->
StateCall, CallbackEvent).
%%
loop_state_callback(
- #params{callback_mode = undefined, modules = [Module | _]} = P,
- Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent) ->
- %%
- %% Figure out the callback mode
- %%
- try Module:callback_mode() of
- CallbackMode ->
- loop_callback_mode_result(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent,
- CallbackMode, listify(CallbackMode), undefined, false)
- catch
- CallbackMode ->
- loop_callback_mode_result(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent,
- CallbackMode, listify(CallbackMode), undefined, false);
- Class:Reason:Stacktrace ->
- terminate(
- Class, Reason, Stacktrace, P, Debug, S, Q)
- end;
-loop_state_callback(
#params{callback_mode = CallbackMode, modules = [Module | _]} = P,
Debug, S, Q, {State,Data} = State_Data,
NextEventsR, Hibernate, TimeoutsR, Postpone,
@@ -1218,71 +1441,6 @@ loop_state_callback(
StateCall, Result);
Class:Reason:Stacktrace ->
terminate(Class, Reason, Stacktrace, P, Debug, S, Q)
- end;
-loop_state_callback(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, Actions) when is_list(Actions) ->
- %% Tunneled actions from enter/8
- CallEnter = true,
- loop_actions_list(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- CallEnter, StateCall, Actions).
-
-%% Check the result of Module:callback_mode()
-%%
-loop_callback_mode_result(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent,
- CallbackMode, [H|T], NewCallbackMode, NewStateEnter) ->
- %%
- case callback_mode(H) of
- true ->
- loop_callback_mode_result(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent,
- CallbackMode, T, H, NewStateEnter);
- false ->
- case state_enter(H) of
- true ->
- loop_callback_mode_result(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent,
- CallbackMode, T, NewCallbackMode, true);
- false ->
- terminate(
- error,
- {bad_return_from_callback_mode,CallbackMode},
- ?STACKTRACE(),
- P, Debug, S, Q)
- end
- end;
-loop_callback_mode_result(
- P, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent,
- CallbackMode, [], NewCallbackMode, NewStateEnter) ->
- %%
- case NewCallbackMode of
- undefined ->
- terminate(
- error,
- {bad_return_from_callback_mode,CallbackMode},
- ?STACKTRACE(),
- P, Debug, S, Q);
- _ ->
- P_1 =
- P#params{
- callback_mode = NewCallbackMode,
- state_enter = NewStateEnter},
- loop_state_callback(
- P_1, Debug, S, Q, State_Data,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- StateCall, CallbackEvent)
end.
%% Process the result from the state function
@@ -1447,7 +1605,6 @@ loop_actions(
CallEnter, StateCall, listify(Actions)).
%%
%% Shortcut for no actions
--compile({inline, [loop_actions/10]}).
loop_actions(
P, Debug, S, Q, NextState_NewData,
NextEventsR, Hibernate, TimeoutsR, Postpone,
@@ -1546,13 +1703,25 @@ loop_actions_list(
push_callback_module ->
[NewModule | P#params.modules]
end,
- P_1 =
- P#params{
- callback_mode = undefined, modules = NewModules},
- loop_actions_list(
- P_1, Debug, S, Q, NextState_NewData,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- CallEnter, StateCall, Actions);
+ case get_callback_mode(P, NewModules) of
+ #params{} = P_1 ->
+ {NextState,_NewData} = NextState_NewData,
+ Debug_1 =
+ ?sys_debug(
+ Debug, P#params.name,
+ {module,NewModule,NextState}),
+ loop_actions_list(
+ P_1, Debug_1, S, Q, NextState_NewData,
+ NextEventsR, Hibernate, TimeoutsR, Postpone,
+ CallEnter, StateCall, Actions);
+ {Class, Reason, Stacktrace} ->
+ terminate(
+ Class, Reason, Stacktrace, P, Debug,
+ S#state{
+ state_data = NextState_NewData,
+ hibernate = Hibernate},
+ Q)
+ end;
true ->
terminate(
error,
@@ -1567,14 +1736,25 @@ loop_actions_list(
if
StateCall ->
NewModules = tl(P#params.modules),
- P_1 =
- P#params{
- callback_mode = undefined,
- modules = NewModules},
- loop_actions_list(
- P_1, Debug, S, Q, NextState_NewData,
- NextEventsR, Hibernate, TimeoutsR, Postpone,
- CallEnter, StateCall, Actions);
+ case get_callback_mode(P, NewModules) of
+ #params{} = P_1 ->
+ {NextState,_NewData} = NextState_NewData,
+ Debug_1 =
+ ?sys_debug(
+ Debug, P#params.name,
+ {module,hd(NewModules),NextState}),
+ loop_actions_list(
+ P_1, Debug_1, S, Q, NextState_NewData,
+ NextEventsR, Hibernate, TimeoutsR, Postpone,
+ CallEnter, StateCall, Actions);
+ {Class, Reason, Stacktrace} ->
+ terminate(
+ Class, Reason, Stacktrace, P, Debug,
+ S#state{
+ state_data = NextState_NewData,
+ hibernate = Hibernate},
+ Q)
+ end;
true ->
terminate(
error,
@@ -1776,41 +1956,47 @@ loop_actions_next_event(
case event_type(Type) of
true when StateCall ->
NextEvent = {Type,Content},
- case Debug of
- ?not_sys_debug ->
+ if
+ Debug =:= ?not_sys_debug ->
loop_actions_list(
P, Debug, S, Q, NextState_NewData,
[NextEvent|NextEventsR],
Hibernate, TimeoutsR, Postpone,
CallEnter, StateCall, Actions);
- _ ->
+ true ->
Name = P#params.name,
- {State,_Data} = S#state.state_data,
- Debug_1 =
- sys_debug(Debug, Name, {in,{Type,Content},State}),
+ {NextState,_NewData} = NextState_NewData,
+ Debug_1 = sys_debug(Debug, Name, {in,NextEvent,NextState}),
loop_actions_list(
P, Debug_1, S, Q, NextState_NewData,
[NextEvent|NextEventsR],
Hibernate, TimeoutsR, Postpone,
CallEnter, StateCall, Actions)
- end;
+ end;
_ ->
- terminate(
- error,
- {if
- StateCall ->
- bad_action_from_state_function;
- true ->
- bad_state_enter_action_from_state_function
- end,
- {next_event,Type,Content}},
- ?STACKTRACE(), P, Debug,
- S#state{
- state_data = NextState_NewData,
- hibernate = Hibernate},
- Q)
+ loop_actions_next_event_bad(
+ P, Debug, S, Q, NextState_NewData,
+ StateCall, Hibernate, Type, Content)
end.
+loop_actions_next_event_bad(
+ P, Debug, S, Q, NextState_NewData,
+ StateCall, Hibernate, Type, Content) ->
+ terminate(
+ error,
+ {case StateCall of
+ true ->
+ bad_action_from_state_function;
+ false ->
+ bad_state_enter_action_from_state_function
+ end,
+ {next_event,Type,Content}},
+ ?STACKTRACE(), P, Debug,
+ S#state{
+ state_data = NextState_NewData,
+ hibernate = Hibernate},
+ Q).
+
%% Do the state transition
%%
loop_state_transition(
@@ -2315,7 +2501,58 @@ parse_timeout_opts_abs(Opts, Abs) ->
badarg
end.
+%% Get the callback mode, update #params{}
+%%
+get_callback_mode(P, [Module | _] = Modules) ->
+ try Module:callback_mode() of
+ CallbackModeResult ->
+ callback_mode_result(P, Modules, CallbackModeResult)
+ catch
+ CallbackModeResult ->
+ callback_mode_result(P, Modules, CallbackModeResult);
+ Class:Reason:Stacktrace ->
+ {Class,Reason,Stacktrace}
+ end.
+callback_mode_result(P, Modules, CallbackModeResult) ->
+ callback_mode_result(
+ P, Modules, CallbackModeResult,
+ listify(CallbackModeResult), undefined, false).
+%%
+callback_mode_result(
+ P, Modules, CallbackModeResult,
+ [H|T], CallbackMode, StateEnter) ->
+ case callback_mode(H) of
+ true ->
+ callback_mode_result(
+ P, Modules, CallbackModeResult,
+ T, H, StateEnter);
+ false ->
+ case state_enter(H) of
+ true ->
+ callback_mode_result(
+ P, Modules, CallbackModeResult,
+ T, CallbackMode, true);
+ false ->
+ {error,
+ {bad_return_from_callback_mode, CallbackModeResult},
+ ?STACKTRACE()}
+ end
+ end;
+callback_mode_result(
+ P, Modules, CallbackModeResult,
+ [], CallbackMode, StateEnter) ->
+ if
+ CallbackMode =:= undefined ->
+ {error,
+ {bad_return_from_callback_mode, CallbackModeResult},
+ ?STACKTRACE()};
+ true ->
+ P#params{
+ modules = Modules,
+ callback_mode = CallbackMode,
+ state_enter = StateEnter}
+ end.
%%---------------------------------------------------------------------------
%% Server helpers
@@ -2399,25 +2636,44 @@ error_info(
Class, Reason, Stacktrace, Debug,
#params{
name = Name,
- modules = Modules,
+ modules = [Mod|_] = Modules,
callback_mode = CallbackMode,
- state_enter = StateEnter} = P,
+ state_enter = StateEnter},
#state{
postponed = Postponed,
- timers = Timers} = S,
+ timers = Timers,
+ state_data = {State,Data}},
Q) ->
- Log = sys:get_log(Debug),
+
+ {NumTimers,ListTimers} = list_timeouts(Timers),
+
+ Status =
+ gen:format_status(Mod, terminate,
+ #{ reason => Reason,
+ state => State,
+ data => Data,
+ queue => Q,
+ postponed => Postponed,
+ timeouts => ListTimers,
+ log => sys:get_log(Debug)},
+ [get(),State,Data]),
+ NewState = case maps:find('$status', Status) of
+ error ->
+ {maps:get(state,Status),maps:get(data,Status)};
+ {ok, S} ->
+ S
+ end,
?LOG_ERROR(#{label=>{gen_statem,terminate},
name=>Name,
- queue=>Q,
- postponed=>Postponed,
+ queue=>maps:get(queue,Status),
+ postponed=>maps:get(postponed,Status),
modules=>Modules,
callback_mode=>CallbackMode,
state_enter=>StateEnter,
- state=>format_status(terminate, get(), P, S),
- timeouts=>list_timeouts(Timers),
- log=>Log,
- reason=>{Class,Reason,Stacktrace},
+ state=>NewState,
+ timeouts=>{NumTimers,maps:get(timeouts,Status)},
+ log=>maps:get(log,Status),
+ reason=>{Class,maps:get(reason,Status),Stacktrace},
client_info=>client_stacktrace(Q)},
#{domain=>[otp],
report_cb=>fun gen_statem:format_log/2,
@@ -2750,34 +3006,6 @@ single(false) -> "".
mod(latin1) -> "";
mod(_) -> "t".
-%% Call Module:format_status/2 or return a default value
-format_status(
- Opt, PDict,
- #params{modules = [Module | _]},
- #state{state_data = {State,Data} = State_Data}) ->
- case erlang:function_exported(Module, format_status, 2) of
- true ->
- try Module:format_status(Opt, [PDict,State,Data])
- catch
- Result -> Result;
- _:_ ->
- format_status_default(
- Opt,
- {State,
- atom_to_list(Module) ++ ":format_status/2 crashed"})
- end;
- false ->
- format_status_default(Opt, State_Data)
- end.
-
-%% The default Module:format_status/3
-format_status_default(Opt, State_Data) ->
- case Opt of
- terminate ->
- State_Data;
- _ ->
- [{data,[{"State",State_Data}]}]
- end.
-compile({inline, [listify/1]}).
listify(Item) when is_list(Item) ->
diff --git a/lib/stdlib/src/io.erl b/lib/stdlib/src/io.erl
index d7158f64a8..18f6ef3dde 100644
--- a/lib/stdlib/src/io.erl
+++ b/lib/stdlib/src/io.erl
@@ -335,6 +335,7 @@ read(Io, Prompt, Pos0, Options) ->
conv_reason(arguments) -> badarg;
conv_reason(terminated) -> terminated;
+conv_reason(calling_self) -> calling_self;
conv_reason({no_translation,_,_}) -> no_translation;
conv_reason(_Reason) -> badarg.
@@ -596,6 +597,8 @@ request(Name, Request, ErrorTag) when is_atom(Name) ->
request(Pid, Request, ErrorTag)
end.
+execute_request(Pid, _Tuple, ErrorTag) when Pid =:= self() ->
+ {ErrorTag, calling_self};
execute_request(Pid, {Convert,Converted}, ErrorTag) ->
Mref = erlang:monitor(process, Pid),
Pid ! {io_request,self(),Mref,Converted},
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index 40b84405e8..fb77957036 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -539,268 +539,10 @@ float_data([_|Cs], Ds) ->
%% Returns a correctly rounded string that converts to Float when
%% read back with list_to_float/1.
-%%
-%% When abs(Float) < float(1 bsl 53) the shortest such string is
-%% returned, and otherwise the shortest such string using scientific
-%% notation is returned. That is, scientific notation is used if and
-%% only if scientific notation results in a shorter string than
-%% normal notation when abs(Float) < float(1 bsl 53), and scientific
-%% notation is used unconditionally if abs(Float) >= float(1 bsl
-%% 53). See comment in insert_decimal/2 for an explanation for why
-%% float(1 bsl 53) is chosen as cutoff point.
-%%
-%% The algorithm that is used to find the decimal number that is
-%% represented by the returned String is described in "Ryu: Fast
-%% Float-to-String Conversion" in Proceedings of 39th ACM SIGPLAN
-%% Conference on Programming Language Design and Implementation.
-%% https://dl.acm.org/doi/pdf/10.1145/3192366.3192369
-spec fwrite_g(float()) -> string().
fwrite_g(Float) ->
- case sign_mantissa_exponent(Float) of
- {0, 0, 0} -> "0.0";
- {1, 0, 0} -> "-0.0";
- {S, M, E} when E < 2047 ->
- {Place, Digits} =
- case is_small_int(M, E) of
- {int, M1, E1} ->
- compute_shortest_int(M1, E1);
- not_int ->
- fwrite_g_1(M, E)
- end,
- DigitList = insert_decimal(Place, Digits, Float),
- insert_minus(S, DigitList)
- end.
-
--define(BIG_POW, (1 bsl 52)).
--define(DECODE_CORRECTION, 1075).
-
-sign_mantissa_exponent(F) ->
- <<S:1, BE:11, M:52>> = <<F:64/float>>,
- {S, M , BE}.
-
-is_small_int(M, E) ->
- M2 = ?BIG_POW bor M,
- E2 = E - ?DECODE_CORRECTION,
- case E2 > 0 orelse E2 < -52 of
- true ->
- %% f = m2 * 2^e2 >= 2^53 is an integer.
- %% Ignore this case for now.
- %% or f < 1
- not_int;
- _ ->
- %% Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52: 1 <= f = m2 / 2^-e2 < 2^53.
- %% Test if the lower -e2 bits of the significand are 0, i.e. whether the fraction is 0.
- Mask = (1 bsl -E2) - 1,
- Fraction = M2 band Mask,
- case Fraction of
- 0 ->
- %% f is an integer in the range [1, 2^53).
- %% Note: mantissa might contain trailing (decimal) 0's.
- {int, M2 bsr -E2, 0};
- _ ->
- not_int
- end
- end.
-
-%% For small integers in the range [1, 2^53), v.mantissa might contain trailing (decimal) zeros.
-compute_shortest_int(M, E) when M rem 10 =:= 0 ->
- Q = M div 10,
- compute_shortest_int(Q, E + 1);
-compute_shortest_int(M, E) ->
- {E, integer_to_list(M)}.
-
-fwrite_g_1(M, E) ->
- {Mf, Ef} = decode(M, E),
- Shift = mmshift(M, E),
- Mv = 4 * Mf,
- {Q, Vm, Vr, Vp, E10} = convert_to_decimal(Ef, Mv, Shift),
- Accept = M rem 2 == 0,
- {VmIsTrailingZero, VrIsTrailingZero, Vp1} = bounds(Mv, Q, Vp, Accept, Ef, Shift),
- {D1, E1} = compute_shortest(Vm, Vr, Vp1, VmIsTrailingZero, VrIsTrailingZero, Accept),
- {E1 + E10, integer_to_list(D1)}.
-
-decode(Mantissa, 0) ->
- {Mantissa, 1 - ?DECODE_CORRECTION - 2};
-decode(Mantissa, Exponent) ->
- {Mantissa + ?BIG_POW, Exponent - ?DECODE_CORRECTION - 2}.
-
-mmshift(0, E) when E > 1 ->
- 0;
-mmshift(_M, _E) ->
- 1.
-
-convert_to_decimal(E2, Mv, Shift) when E2 >= 0 ->
- Q = max(0, ((E2 * 78913) bsr 18) - 1),
- Mul = io_lib_format_ryu_table:inv_value(Q),
- K = io_lib_format_ryu_table:pow5_inv_bitcount() + pow5bits(Q) - 1,
- I = -E2 + Q + K,
- {Vm, Vr, Vp} = mulShiftAll(Mv, Shift, I, Mul),
- {Q, Vm, Vr, Vp, Q};
-
-convert_to_decimal(E2, Mv, Shift) when E2 < 0 ->
- Q = max(0, ((-E2 * 732923) bsr 20) - 1),
- I = -E2 - Q,
- K = pow5bits(I) - io_lib_format_ryu_table:pow5_bitcount(),
- From_file = io_lib_format_ryu_table:value(I),
- J = Q - K,
- {Vm, Vr, Vp} = mulShiftAll(Mv, Shift, J, From_file),
- E10 = E2 + Q,
- {Q, Vm, Vr, Vp, E10}.
-
-pow5bits(E) ->
- ((E * 1217359) bsr 19) + 1.
-
-mulShiftAll(Mv, Shift, J, Mul) ->
- A = mulShift64(Mv - 1 - Shift, Mul, J),
- B = mulShift64(Mv, Mul, J),
- C = mulShift64(Mv + 2,Mul, J),
- {A, B, C}.
-
-mulShift64(M, Mul, J) ->
- (M * Mul) bsr J.
-
-bounds(Mv, Q, Vp, _Accept, E2, _Shift) when E2 >= 0, Q =< 21, Mv rem 5 =:= 0 ->
- {false, multipleOfPowerOf5(Mv, Q) , Vp};
-bounds(Mv, Q, Vp, true, E2, Shift) when E2 >= 0, Q =< 21 ->
- {multipleOfPowerOf5(Mv - 1 - Shift, Q), false , Vp};
-bounds(Mv, Q, Vp, _Accept, E2, _Shift) when E2 >= 0, Q =< 21 ->
- {false, false , Vp - vpmodifier(multipleOfPowerOf5(Mv + 2, Q))};
-bounds(_Mv, Q, Vp, true, E2, Shift) when E2 < 0, Q =< 1 ->
- {Shift =:= 1, true, Vp};
-bounds(_Mv, Q, Vp, false, E2, _Shift) when E2 < 0, Q =< 1 ->
- {false, true, Vp - 1};
-bounds(Mv, Q, Vp, _Accept, E2, _Shift) when E2 < 0, Q < 63 ->
- {false, (Mv band ((1 bsl Q) -1 )) =:= 0, Vp};
-bounds(_Mv, _Q, Vp, _Accept, _E2, _Shift) ->
- {false, false, Vp}.
-
-multipleOfPowerOf5(Value, Q) ->
- pow5factor(Value) >= Q.
-
-pow5factor(Val) ->
- pow5factor(Val div 5, 0).
-
-pow5factor(Val, Count) when (Val rem 5) /= 0->
- Count;
-pow5factor(Val, Count) ->
- pow5factor(Val div 5, Count + 1).
-
-vpmodifier(true) ->
- 1;
-vpmodifier(false) ->
- 0.
-
-compute_shortest(Vm, Vr, Vp, false, false, _Accept) ->
- {Vm1, Vr1, Removed, RoundUp} =
- general_case(Vm, Vr, Vp, 0, false),
- Output = Vr1 + handle_normal_output_mod(Vr1, Vm1, RoundUp),
- {Output, Removed};
-compute_shortest(Vm, Vr, Vp, VmIsTrailingZero, VrIsTrailingZero, Accept) ->
- {Vm1, Vr1, Removed, LastRemovedDigit} =
- handle_trailing_zeros(Vm, Vr, Vp, VmIsTrailingZero, VrIsTrailingZero, 0, 0),
- Output = Vr1 + handle_zero_output_mod(Vr1, Vm1, Accept, VmIsTrailingZero, LastRemovedDigit),
- {Output, Removed}.
-
-general_case(Vm, Vr, Vp, Removed, RoundUp) when (Vp div 100) =< (Vm div 100)->
- general_case_10(Vm, Vr, Vp, Removed, RoundUp);
-general_case(Vm, Vr, Vp, Removed, _RU) ->
- VmD100 = Vm div 100,
- VrD100 = Vr div 100,
- VpD100 = Vp div 100,
- RoundUp = ((Vr rem 100) >= 50),
- general_case_10(VmD100, VrD100, VpD100, 2 + Removed, RoundUp).
-
-general_case_10(Vm, Vr, Vp, Removed, RoundUp)
- when (Vp div 10) =< (Vm div 10)->
- {Vm, Vr, Removed, RoundUp};
-general_case_10(Vm, Vr, Vp, Removed, _RU) ->
- VmD10 = Vm div 10,
- VrD10 = Vr div 10,
- VpD10 = Vp div 10,
- RoundUp = ((Vr rem 10) >= 5),
- general_case_10(VmD10, VrD10, VpD10, 1 + Removed, RoundUp).
-
-handle_normal_output_mod(Vr, Vm, RoundUp) when (Vm =:= Vr) or RoundUp ->
- 1;
-handle_normal_output_mod(_Vr, _Vm, _RoundUp) ->
- 0.
-
-handle_trailing_zeros(Vm, Vr, Vp, VmTZ, VrTZ, Removed, LastRemovedDigit)
- when (Vp div 10) =< (Vm div 10)->
- vmIsTrailingZero(Vm, Vr, Vp, VmTZ, VrTZ, Removed, LastRemovedDigit);
-handle_trailing_zeros(Vm, Vr, Vp, VmIsTrailingZero, VrIsTrailingZero, Removed, LastRemovedDigit) ->
- VmTZ = VmIsTrailingZero and ((Vm rem 10) =:= 0),
- VrTZ = VrIsTrailingZero and (LastRemovedDigit =:= 0),
- handle_trailing_zeros(Vm div 10, Vr div 10, Vp div 10, VmTZ, VrTZ, 1 + Removed, Vr rem 10).
-
-vmIsTrailingZero(Vm, Vr, _Vp, false = _VmTZ, VrTZ, Removed, LastRemovedDigit) ->
- handle_50_dotdot_0(Vm, Vr, VrTZ, Removed, LastRemovedDigit);
-vmIsTrailingZero(Vm, Vr, _Vp, _VmTZ, VrTZ, Removed, LastRemovedDigit) when (Vm rem 10) /= 0 ->
- handle_50_dotdot_0(Vm, Vr, VrTZ, Removed, LastRemovedDigit);
-vmIsTrailingZero(Vm, Vr, Vp, VmTZ, VrTZ, Removed, LastRemovedDigit) ->
- vmIsTrailingZero(Vm div 10, Vr div 10, Vp div 10, VmTZ, LastRemovedDigit == 0 andalso VrTZ, 1 + Removed, Vr rem 10).
-
-handle_50_dotdot_0(Vm, Vr, true, Removed, 5) when (Vr rem 2) =:= 0 ->
- {Vm, Vr, Removed, 4};
-handle_50_dotdot_0(Vm, Vr, _VrTZ, Removed, LastRemovedDigit) ->
- {Vm, Vr, Removed, LastRemovedDigit}.
-
-handle_zero_output_mod(_Vr, _Vm, _Accept, _VmTZ, LastRemovedDigit) when LastRemovedDigit >= 5 ->
- 1;
-handle_zero_output_mod(Vr, Vm, Accept, VmTZ, _LastRemovedDigit) when Vr =:= Vm, ((not Accept) or (not VmTZ)) ->
- 1;
-handle_zero_output_mod(_Vr, _Vm, _Accept, _VmTZ, _LastRemovedDigit) ->
- 0.
-
-insert_decimal(Place, S, Float) ->
- L = length(S),
- Exp = Place + L - 1,
- ExpL = integer_to_list(Exp),
- ExpCost = length(ExpL) + 2,
- if
- Place < 0 ->
- if
- Exp >= 0 ->
- {S0, S1} = lists:split(L + Place, S),
- S0 ++ "." ++ S1;
- 2 - Place - L =< ExpCost ->
- "0." ++ lists:duplicate(-Place - L, $0) ++ S;
- true ->
- insert_exp(ExpL, S)
- end;
- true ->
- Dot = if L =:= 1 -> 1; true -> 0 end,
- if
- %% All integers in the range [-2^53, 2^53] can
- %% be stored without loss of precision in an
- %% IEEE 754 64-bit double but 2^53+1 cannot be
- %% stored in an IEEE 754 64-bit double without
- %% loss of precision (float((1 bsl 53)+1) =:=
- %% float(1 bsl 53)). It thus makes sense to
- %% show floats that are >= 2^53 or <= -2^53 in
- %% scientific notation to indicate that the
- %% number is so large that there could be loss
- %% in precion when adding or subtracting 1.
- %%
- %% https://stackoverflow.com/questions/1848700/biggest-integer-that-can-be-stored-in-a-double?answertab=votes#tab-top
- ExpCost + Dot >= Place + 2 andalso abs(Float) < float(1 bsl 53) ->
- S ++ lists:duplicate(Place, $0) ++ ".0";
- true ->
- insert_exp(ExpL, S)
- end
- end.
-
-
-insert_exp(ExpL, [C]) ->
- [C] ++ ".0e" ++ ExpL;
-insert_exp(ExpL, [C | S]) ->
- [C] ++ "." ++ S ++ "e" ++ ExpL.
-
-insert_minus(0, Digits) ->
- Digits;
-insert_minus(1, Digits) ->
- [$-] ++ Digits.
+ float_to_list(Float, [short]).
%% fwrite_g(Float, Field, Adjust, Precision, PadChar)
%% Use the f form if Float is >= 0.1 and < 1.0e4,
diff --git a/lib/stdlib/src/io_lib_format_ryu_table.erl b/lib/stdlib/src/io_lib_format_ryu_table.erl
deleted file mode 100644
index b20268a939..0000000000
--- a/lib/stdlib/src/io_lib_format_ryu_table.erl
+++ /dev/null
@@ -1,686 +0,0 @@
-%%
-%% this file is generated do not modify
-%% see ../script/generate_ryu_table.escript
-
--module(io_lib_format_ryu_table).
--export([pow5_bitcount/0, pow5_inv_bitcount/0, value/1, inv_value/1]).
-
--spec pow5_bitcount() -> integer().
-pow5_bitcount() -> 125.
-
--spec pow5_inv_bitcount() -> integer().
-pow5_inv_bitcount() -> 125.
-
--spec value(integer()) -> integer().
-value(0) -> 21267647932558653966460912964485513216;
-value(1) -> 26584559915698317458076141205606891520;
-value(2) -> 33230699894622896822595176507008614400;
-value(3) -> 41538374868278621028243970633760768000;
-value(4) -> 25961484292674138142652481646100480000;
-value(5) -> 32451855365842672678315602057625600000;
-value(6) -> 40564819207303340847894502572032000000;
-value(7) -> 25353012004564588029934064107520000000;
-value(8) -> 31691265005705735037417580134400000000;
-value(9) -> 39614081257132168796771975168000000000;
-value(10) -> 24758800785707605497982484480000000000;
-value(11) -> 30948500982134506872478105600000000000;
-value(12) -> 38685626227668133590597632000000000000;
-value(13) -> 24178516392292583494123520000000000000;
-value(14) -> 30223145490365729367654400000000000000;
-value(15) -> 37778931862957161709568000000000000000;
-value(16) -> 23611832414348226068480000000000000000;
-value(17) -> 29514790517935282585600000000000000000;
-value(18) -> 36893488147419103232000000000000000000;
-value(19) -> 23058430092136939520000000000000000000;
-value(20) -> 28823037615171174400000000000000000000;
-value(21) -> 36028797018963968000000000000000000000;
-value(22) -> 22517998136852480000000000000000000000;
-value(23) -> 28147497671065600000000000000000000000;
-value(24) -> 35184372088832000000000000000000000000;
-value(25) -> 21990232555520000000000000000000000000;
-value(26) -> 27487790694400000000000000000000000000;
-value(27) -> 34359738368000000000000000000000000000;
-value(28) -> 21474836480000000000000000000000000000;
-value(29) -> 26843545600000000000000000000000000000;
-value(30) -> 33554432000000000000000000000000000000;
-value(31) -> 41943040000000000000000000000000000000;
-value(32) -> 26214400000000000000000000000000000000;
-value(33) -> 32768000000000000000000000000000000000;
-value(34) -> 40960000000000000000000000000000000000;
-value(35) -> 25600000000000000000000000000000000000;
-value(36) -> 32000000000000000000000000000000000000;
-value(37) -> 40000000000000000000000000000000000000;
-value(38) -> 25000000000000000000000000000000000000;
-value(39) -> 31250000000000000000000000000000000000;
-value(40) -> 39062500000000000000000000000000000000;
-value(41) -> 24414062500000000000000000000000000000;
-value(42) -> 30517578125000000000000000000000000000;
-value(43) -> 38146972656250000000000000000000000000;
-value(44) -> 23841857910156250000000000000000000000;
-value(45) -> 29802322387695312500000000000000000000;
-value(46) -> 37252902984619140625000000000000000000;
-value(47) -> 23283064365386962890625000000000000000;
-value(48) -> 29103830456733703613281250000000000000;
-value(49) -> 36379788070917129516601562500000000000;
-value(50) -> 22737367544323205947875976562500000000;
-value(51) -> 28421709430404007434844970703125000000;
-value(52) -> 35527136788005009293556213378906250000;
-value(53) -> 22204460492503130808472633361816406250;
-value(54) -> 27755575615628913510590791702270507812;
-value(55) -> 34694469519536141888238489627838134765;
-value(56) -> 21684043449710088680149056017398834228;
-value(57) -> 27105054312137610850186320021748542785;
-value(58) -> 33881317890172013562732900027185678482;
-value(59) -> 42351647362715016953416125033982098102;
-value(60) -> 26469779601696885595885078146238811314;
-value(61) -> 33087224502121106994856347682798514142;
-value(62) -> 41359030627651383743570434603498142678;
-value(63) -> 25849394142282114839731521627186339173;
-value(64) -> 32311742677852643549664402033982923967;
-value(65) -> 40389678347315804437080502542478654959;
-value(66) -> 25243548967072377773175314089049159349;
-value(67) -> 31554436208840472216469142611311449186;
-value(68) -> 39443045261050590270586428264139311483;
-value(69) -> 24651903288156618919116517665087069677;
-value(70) -> 30814879110195773648895647081358837096;
-value(71) -> 38518598887744717061119558851698546370;
-value(72) -> 24074124304840448163199724282311591481;
-value(73) -> 30092655381050560203999655352889489352;
-value(74) -> 37615819226313200254999569191111861690;
-value(75) -> 23509887016445750159374730744444913556;
-value(76) -> 29387358770557187699218413430556141945;
-value(77) -> 36734198463196484624023016788195177431;
-value(78) -> 22958874039497802890014385492621985894;
-value(79) -> 28698592549372253612517981865777482368;
-value(80) -> 35873240686715317015647477332221852960;
-value(81) -> 22420775429197073134779673332638658100;
-value(82) -> 28025969286496341418474591665798322625;
-value(83) -> 35032461608120426773093239582247903282;
-value(84) -> 21895288505075266733183274738904939551;
-value(85) -> 27369110631344083416479093423631174439;
-value(86) -> 34211388289180104270598866779538968048;
-value(87) -> 21382117680737565169124291737211855030;
-value(88) -> 26727647100921956461405364671514818788;
-value(89) -> 33409558876152445576756705839393523485;
-value(90) -> 41761948595190556970945882299241904356;
-value(91) -> 26101217871994098106841176437026190222;
-value(92) -> 32626522339992622633551470546282737778;
-value(93) -> 40783152924990778291939338182853422223;
-value(94) -> 25489470578119236432462086364283388889;
-value(95) -> 31861838222649045540577607955354236111;
-value(96) -> 39827297778311306925722009944192795139;
-value(97) -> 24892061111444566828576256215120496962;
-value(98) -> 31115076389305708535720320268900621202;
-value(99) -> 38893845486632135669650400336125776503;
-value(100) -> 24308653429145084793531500210078610314;
-value(101) -> 30385816786431355991914375262598262893;
-value(102) -> 37982270983039194989892969078247828616;
-value(103) -> 23738919364399496868683105673904892885;
-value(104) -> 29673649205499371085853882092381116106;
-value(105) -> 37092061506874213857317352615476395133;
-value(106) -> 23182538441796383660823345384672746958;
-value(107) -> 28978173052245479576029181730840933698;
-value(108) -> 36222716315306849470036477163551167122;
-value(109) -> 22639197697066780918772798227219479451;
-value(110) -> 28298997121333476148465997784024349314;
-value(111) -> 35373746401666845185582497230030436643;
-value(112) -> 22108591501041778240989060768769022902;
-value(113) -> 27635739376302222801236325960961278627;
-value(114) -> 34544674220377778501545407451201598284;
-value(115) -> 21590421387736111563465879657000998927;
-value(116) -> 26988026734670139454332349571251248659;
-value(117) -> 33735033418337674317915436964064060824;
-value(118) -> 42168791772922092897394296205080076030;
-value(119) -> 26355494858076308060871435128175047519;
-value(120) -> 32944368572595385076089293910218809399;
-value(121) -> 41180460715744231345111617387773511748;
-value(122) -> 25737787947340144590694760867358444843;
-value(123) -> 32172234934175180738368451084198056053;
-value(124) -> 40215293667718975922960563855247570067;
-value(125) -> 25134558542324359951850352409529731292;
-value(126) -> 31418198177905449939812940511912164115;
-value(127) -> 39272747722381812424766175639890205143;
-value(128) -> 24545467326488632765478859774931378214;
-value(129) -> 30681834158110790956848574718664222768;
-value(130) -> 38352292697638488696060718398330278460;
-value(131) -> 23970182936024055435037948998956424037;
-value(132) -> 29962728670030069293797436248695530047;
-value(133) -> 37453410837537586617246795310869412559;
-value(134) -> 23408381773460991635779247069293382849;
-value(135) -> 29260477216826239544724058836616728561;
-value(136) -> 36575596521032799430905073545770910702;
-value(137) -> 22859747825645499644315670966106819189;
-value(138) -> 28574684782056874555394588707633523986;
-value(139) -> 35718355977571093194243235884541904982;
-value(140) -> 22323972485981933246402022427838690614;
-value(141) -> 27904965607477416558002528034798363267;
-value(142) -> 34881207009346770697503160043497954084;
-value(143) -> 21800754380841731685939475027186221303;
-value(144) -> 27250942976052164607424343783982776628;
-value(145) -> 34063678720065205759280429729978470785;
-value(146) -> 21289799200040753599550268581236544241;
-value(147) -> 26612249000050941999437835726545680301;
-value(148) -> 33265311250063677499297294658182100376;
-value(149) -> 41581639062579596874121618322727625471;
-value(150) -> 25988524414112248046326011451704765919;
-value(151) -> 32485655517640310057907514314630957399;
-value(152) -> 40607069397050387572384392893288696749;
-value(153) -> 25379418373156492232740245558305435468;
-value(154) -> 31724272966445615290925306947881794335;
-value(155) -> 39655341208057019113656633684852242919;
-value(156) -> 24784588255035636946035396053032651824;
-value(157) -> 30980735318794546182544245066290814780;
-value(158) -> 38725919148493182728180306332863518475;
-value(159) -> 24203699467808239205112691458039699047;
-value(160) -> 30254624334760299006390864322549623809;
-value(161) -> 37818280418450373757988580403187029761;
-value(162) -> 23636425261531483598742862751991893600;
-value(163) -> 29545531576914354498428578439989867001;
-value(164) -> 36931914471142943123035723049987333751;
-value(165) -> 23082446544464339451897326906242083594;
-value(166) -> 28853058180580424314871658632802604493;
-value(167) -> 36066322725725530393589573291003255616;
-value(168) -> 22541451703578456495993483306877034760;
-value(169) -> 28176814629473070619991854133596293450;
-value(170) -> 35221018286841338274989817666995366813;
-value(171) -> 22013136429275836421868636041872104258;
-value(172) -> 27516420536594795527335795052340130322;
-value(173) -> 34395525670743494409169743815425162903;
-value(174) -> 21497203544214684005731089884640726814;
-value(175) -> 26871504430268355007163862355800908518;
-value(176) -> 33589380537835443758954827944751135647;
-value(177) -> 41986725672294304698693534930938919559;
-value(178) -> 26241703545183940436683459331836824724;
-value(179) -> 32802129431479925545854324164796030906;
-value(180) -> 41002661789349906932317905205995038632;
-value(181) -> 25626663618343691832698690753746899145;
-value(182) -> 32033329522929614790873363442183623931;
-value(183) -> 40041661903662018488591704302729529914;
-value(184) -> 25026038689788761555369815189205956196;
-value(185) -> 31282548362235951944212268986507445245;
-value(186) -> 39103185452794939930265336233134306557;
-value(187) -> 24439490907996837456415835145708941598;
-value(188) -> 30549363634996046820519793932136176997;
-value(189) -> 38186704543745058525649742415170221247;
-value(190) -> 23866690339840661578531089009481388279;
-value(191) -> 29833362924800826973163861261851735349;
-value(192) -> 37291703656001033716454826577314669186;
-value(193) -> 23307314785000646072784266610821668241;
-value(194) -> 29134143481250807590980333263527085302;
-value(195) -> 36417679351563509488725416579408856627;
-value(196) -> 22761049594727193430453385362130535392;
-value(197) -> 28451311993408991788066731702663169240;
-value(198) -> 35564139991761239735083414628328961550;
-value(199) -> 22227587494850774834427134142705600969;
-value(200) -> 27784484368563468543033917678382001211;
-value(201) -> 34730605460704335678792397097977501514;
-value(202) -> 21706628412940209799245248186235938446;
-value(203) -> 27133285516175262249056560232794923058;
-value(204) -> 33916606895219077811320700290993653822;
-value(205) -> 42395758619023847264150875363742067278;
-value(206) -> 26497349136889904540094297102338792048;
-value(207) -> 33121686421112380675117871377923490061;
-value(208) -> 41402108026390475843897339222404362576;
-value(209) -> 25876317516494047402435837014002726610;
-value(210) -> 32345396895617559253044796267503408262;
-value(211) -> 40431746119521949066305995334379260328;
-value(212) -> 25269841324701218166441247083987037705;
-value(213) -> 31587301655876522708051558854983797131;
-value(214) -> 39484127069845653385064448568729746414;
-value(215) -> 24677579418653533365665280355456091509;
-value(216) -> 30846974273316916707081600444320114386;
-value(217) -> 38558717841646145883852000555400142982;
-value(218) -> 24099198651028841177407500347125089364;
-value(219) -> 30123998313786051471759375433906361705;
-value(220) -> 37654997892232564339699219292382952131;
-value(221) -> 23534373682645352712312012057739345082;
-value(222) -> 29417967103306690890390015072174181352;
-value(223) -> 36772458879133363612987518840217726691;
-value(224) -> 22982786799458352258117199275136079181;
-value(225) -> 28728483499322940322646499093920098977;
-value(226) -> 35910604374153675403308123867400123721;
-value(227) -> 22444127733846047127067577417125077326;
-value(228) -> 28055159667307558908834471771406346657;
-value(229) -> 35068949584134448636043089714257933322;
-value(230) -> 21918093490084030397526931071411208326;
-value(231) -> 27397616862605037996908663839264010407;
-value(232) -> 34247021078256297496135829799080013009;
-value(233) -> 21404388173910185935084893624425008131;
-value(234) -> 26755485217387732418856117030531260163;
-value(235) -> 33444356521734665523570146288164075204;
-value(236) -> 41805445652168331904462682860205094006;
-value(237) -> 26128403532605207440289176787628183753;
-value(238) -> 32660504415756509300361470984535229692;
-value(239) -> 40825630519695636625451838730669037115;
-value(240) -> 25516019074809772890907399206668148197;
-value(241) -> 31895023843512216113634249008335185246;
-value(242) -> 39868779804390270142042811260418981558;
-value(243) -> 24917987377743918838776757037761863473;
-value(244) -> 31147484222179898548470946297202329342;
-value(245) -> 38934355277724873185588682871502911677;
-value(246) -> 24333972048578045740992926794689319798;
-value(247) -> 30417465060722557176241158493361649748;
-value(248) -> 38021831325903196470301448116702062185;
-value(249) -> 23763644578689497793938405072938788865;
-value(250) -> 29704555723361872242423006341173486082;
-value(251) -> 37130694654202340303028757926466857602;
-value(252) -> 23206684158876462689392973704041786001;
-value(253) -> 29008355198595578361741217130052232502;
-value(254) -> 36260443998244472952176521412565290627;
-value(255) -> 22662777498902795595110325882853306642;
-value(256) -> 28328471873628494493887907353566633302;
-value(257) -> 35410589842035618117359884191958291628;
-value(258) -> 22131618651272261323349927619973932267;
-value(259) -> 27664523314090326654187409524967415334;
-value(260) -> 34580654142612908317734261906209269168;
-value(261) -> 21612908839133067698583913691380793230;
-value(262) -> 27016136048916334623229892114225991537;
-value(263) -> 33770170061145418279037365142782489422;
-value(264) -> 42212712576431772848796706428478111778;
-value(265) -> 26382945360269858030497941517798819861;
-value(266) -> 32978681700337322538122426897248524826;
-value(267) -> 41223352125421653172653033621560656033;
-value(268) -> 25764595078388533232908146013475410020;
-value(269) -> 32205743847985666541135182516844262526;
-value(270) -> 40257179809982083176418978146055328157;
-value(271) -> 25160737381238801985261861341284580098;
-value(272) -> 31450921726548502481577326676605725123;
-value(273) -> 39313652158185628101971658345757156403;
-value(274) -> 24571032598866017563732286466098222752;
-value(275) -> 30713790748582521954665358082622778440;
-value(276) -> 38392238435728152443331697603278473050;
-value(277) -> 23995149022330095277082311002049045656;
-value(278) -> 29993936277912619096352888752561307070;
-value(279) -> 37492420347390773870441110940701633838;
-value(280) -> 23432762717119233669025694337938521149;
-value(281) -> 29290953396399042086282117922423151436;
-value(282) -> 36613691745498802607852647403028939295;
-value(283) -> 22883557340936751629907904626893087059;
-value(284) -> 28604446676170939537384880783616358824;
-value(285) -> 35755558345213674421731100979520448530;
-value(286) -> 22347223965758546513581938112200280331;
-value(287) -> 27934029957198183141977422640250350414;
-value(288) -> 34917537446497728927471778300312938018;
-value(289) -> 21823460904061080579669861437695586261;
-value(290) -> 27279326130076350724587326797119482826;
-value(291) -> 34099157662595438405734158496399353533;
-value(292) -> 21311973539122149003583849060249595958;
-value(293) -> 26639966923902686254479811325311994947;
-value(294) -> 33299958654878357818099764156639993684;
-value(295) -> 41624948318597947272624705195799992106;
-value(296) -> 26015592699123717045390440747374995066;
-value(297) -> 32519490873904646306738050934218743833;
-value(298) -> 40649363592380807883422563667773429791;
-value(299) -> 25405852245238004927139102292358393619;
-value(300) -> 31757315306547506158923877865447992024;
-value(301) -> 39696644133184382698654847331809990030;
-value(302) -> 24810402583240239186659279582381243769;
-value(303) -> 31013003229050298983324099477976554711;
-value(304) -> 38766254036312873729155124347470693389;
-value(305) -> 24228908772695546080721952717169183368;
-value(306) -> 30286135965869432600902440896461479210;
-value(307) -> 37857669957336790751128051120576849012;
-value(308) -> 23661043723335494219455031950360530633;
-value(309) -> 29576304654169367774318789937950663291;
-value(310) -> 36970380817711709717898487422438329114;
-value(311) -> 23106488011069818573686554639023955696;
-value(312) -> 28883110013837273217108193298779944620;
-value(313) -> 36103887517296591521385241623474930775;
-value(314) -> 22564929698310369700865776014671831734;
-value(315) -> 28206162122887962126082220018339789668;
-value(316) -> 35257702653609952657602775022924737085;
-value(317) -> 22036064158506220411001734389327960678;
-value(318) -> 27545080198132775513752167986659950848;
-value(319) -> 34431350247665969392190209983324938560;
-value(320) -> 21519593904791230870118881239578086600;
-value(321) -> 26899492380989038587648601549472608250;
-value(322) -> 33624365476236298234560751936840760312;
-value(323) -> 42030456845295372793200939921050950390;
-value(324) -> 26269035528309607995750587450656843994;
-value(325) -> 32836294410387009994688234313321054992;
-value(_) -> error(function_clause).
-
--spec inv_value(integer()) -> integer().
-inv_value(0) -> 42535295865117307932921825928971026433;
-inv_value(1) -> 34028236692093846346337460743176821146;
-inv_value(2) -> 27222589353675077077069968594541456917;
-inv_value(3) -> 21778071482940061661655974875633165534;
-inv_value(4) -> 34844914372704098658649559801013064854;
-inv_value(5) -> 27875931498163278926919647840810451883;
-inv_value(6) -> 22300745198530623141535718272648361506;
-inv_value(7) -> 35681192317648997026457149236237378410;
-inv_value(8) -> 28544953854119197621165719388989902728;
-inv_value(9) -> 22835963083295358096932575511191922183;
-inv_value(10) -> 36537540933272572955092120817907075492;
-inv_value(11) -> 29230032746618058364073696654325660394;
-inv_value(12) -> 23384026197294446691258957323460528315;
-inv_value(13) -> 37414441915671114706014331717536845304;
-inv_value(14) -> 29931553532536891764811465374029476243;
-inv_value(15) -> 23945242826029513411849172299223580995;
-inv_value(16) -> 38312388521647221458958675678757729591;
-inv_value(17) -> 30649910817317777167166940543006183673;
-inv_value(18) -> 24519928653854221733733552434404946938;
-inv_value(19) -> 39231885846166754773973683895047915101;
-inv_value(20) -> 31385508676933403819178947116038332081;
-inv_value(21) -> 25108406941546723055343157692830665665;
-inv_value(22) -> 40173451106474756888549052308529065064;
-inv_value(23) -> 32138760885179805510839241846823252051;
-inv_value(24) -> 25711008708143844408671393477458601641;
-inv_value(25) -> 41137613933030151053874229563933762625;
-inv_value(26) -> 32910091146424120843099383651147010100;
-inv_value(27) -> 26328072917139296674479506920917608080;
-inv_value(28) -> 42124916667422874679167211073468172928;
-inv_value(29) -> 33699933333938299743333768858774538343;
-inv_value(30) -> 26959946667150639794667015087019630674;
-inv_value(31) -> 21567957333720511835733612069615704539;
-inv_value(32) -> 34508731733952818937173779311385127263;
-inv_value(33) -> 27606985387162255149739023449108101810;
-inv_value(34) -> 22085588309729804119791218759286481448;
-inv_value(35) -> 35336941295567686591665950014858370317;
-inv_value(36) -> 28269553036454149273332760011886696254;
-inv_value(37) -> 22615642429163319418666208009509357003;
-inv_value(38) -> 36185027886661311069865932815214971205;
-inv_value(39) -> 28948022309329048855892746252171976964;
-inv_value(40) -> 23158417847463239084714197001737581571;
-inv_value(41) -> 37053468555941182535542715202780130514;
-inv_value(42) -> 29642774844752946028434172162224104411;
-inv_value(43) -> 23714219875802356822747337729779283529;
-inv_value(44) -> 37942751801283770916395740367646853646;
-inv_value(45) -> 30354201441027016733116592294117482917;
-inv_value(46) -> 24283361152821613386493273835293986334;
-inv_value(47) -> 38853377844514581418389238136470378133;
-inv_value(48) -> 31082702275611665134711390509176302507;
-inv_value(49) -> 24866161820489332107769112407341042006;
-inv_value(50) -> 39785858912782931372430579851745667209;
-inv_value(51) -> 31828687130226345097944463881396533767;
-inv_value(52) -> 25462949704181076078355571105117227014;
-inv_value(53) -> 40740719526689721725368913768187563222;
-inv_value(54) -> 32592575621351777380295131014550050577;
-inv_value(55) -> 26074060497081421904236104811640040462;
-inv_value(56) -> 41718496795330275046777767698624064739;
-inv_value(57) -> 33374797436264220037422214158899251791;
-inv_value(58) -> 26699837949011376029937771327119401433;
-inv_value(59) -> 21359870359209100823950217061695521147;
-inv_value(60) -> 34175792574734561318320347298712833834;
-inv_value(61) -> 27340634059787649054656277838970267067;
-inv_value(62) -> 21872507247830119243725022271176213654;
-inv_value(63) -> 34996011596528190789960035633881941846;
-inv_value(64) -> 27996809277222552631968028507105553477;
-inv_value(65) -> 22397447421778042105574422805684442782;
-inv_value(66) -> 35835915874844867368919076489095108450;
-inv_value(67) -> 28668732699875893895135261191276086760;
-inv_value(68) -> 22934986159900715116108208953020869408;
-inv_value(69) -> 36695977855841144185773134324833391053;
-inv_value(70) -> 29356782284672915348618507459866712843;
-inv_value(71) -> 23485425827738332278894805967893370274;
-inv_value(72) -> 37576681324381331646231689548629392439;
-inv_value(73) -> 30061345059505065316985351638903513951;
-inv_value(74) -> 24049076047604052253588281311122811161;
-inv_value(75) -> 38478521676166483605741250097796497857;
-inv_value(76) -> 30782817340933186884593000078237198286;
-inv_value(77) -> 24626253872746549507674400062589758629;
-inv_value(78) -> 39402006196394479212279040100143613806;
-inv_value(79) -> 31521604957115583369823232080114891045;
-inv_value(80) -> 25217283965692466695858585664091912836;
-inv_value(81) -> 40347654345107946713373737062547060537;
-inv_value(82) -> 32278123476086357370698989650037648430;
-inv_value(83) -> 25822498780869085896559191720030118744;
-inv_value(84) -> 41315998049390537434494706752048189990;
-inv_value(85) -> 33052798439512429947595765401638551992;
-inv_value(86) -> 26442238751609943958076612321310841594;
-inv_value(87) -> 42307582002575910332922579714097346550;
-inv_value(88) -> 33846065602060728266338063771277877240;
-inv_value(89) -> 27076852481648582613070451017022301792;
-inv_value(90) -> 21661481985318866090456360813617841434;
-inv_value(91) -> 34658371176510185744730177301788546293;
-inv_value(92) -> 27726696941208148595784141841430837035;
-inv_value(93) -> 22181357552966518876627313473144669628;
-inv_value(94) -> 35490172084746430202603701557031471404;
-inv_value(95) -> 28392137667797144162082961245625177124;
-inv_value(96) -> 22713710134237715329666368996500141699;
-inv_value(97) -> 36341936214780344527466190394400226718;
-inv_value(98) -> 29073548971824275621972952315520181375;
-inv_value(99) -> 23258839177459420497578361852416145100;
-inv_value(100) -> 37214142683935072796125378963865832159;
-inv_value(101) -> 29771314147148058236900303171092665728;
-inv_value(102) -> 23817051317718446589520242536874132582;
-inv_value(103) -> 38107282108349514543232388058998612131;
-inv_value(104) -> 30485825686679611634585910447198889705;
-inv_value(105) -> 24388660549343689307668728357759111764;
-inv_value(106) -> 39021856878949902892269965372414578822;
-inv_value(107) -> 31217485503159922313815972297931663058;
-inv_value(108) -> 24973988402527937851052777838345330446;
-inv_value(109) -> 39958381444044700561684444541352528714;
-inv_value(110) -> 31966705155235760449347555633082022971;
-inv_value(111) -> 25573364124188608359478044506465618377;
-inv_value(112) -> 40917382598701773375164871210344989403;
-inv_value(113) -> 32733906078961418700131896968275991523;
-inv_value(114) -> 26187124863169134960105517574620793218;
-inv_value(115) -> 41899399781070615936168828119393269149;
-inv_value(116) -> 33519519824856492748935062495514615319;
-inv_value(117) -> 26815615859885194199148049996411692255;
-inv_value(118) -> 21452492687908155359318439997129353804;
-inv_value(119) -> 34323988300653048574909503995406966087;
-inv_value(120) -> 27459190640522438859927603196325572870;
-inv_value(121) -> 21967352512417951087942082557060458296;
-inv_value(122) -> 35147764019868721740707332091296733273;
-inv_value(123) -> 28118211215894977392565865673037386618;
-inv_value(124) -> 22494568972715981914052692538429909295;
-inv_value(125) -> 35991310356345571062484308061487854871;
-inv_value(126) -> 28793048285076456849987446449190283897;
-inv_value(127) -> 23034438628061165479989957159352227118;
-inv_value(128) -> 36855101804897864767983931454963563388;
-inv_value(129) -> 29484081443918291814387145163970850711;
-inv_value(130) -> 23587265155134633451509716131176680569;
-inv_value(131) -> 37739624248215413522415545809882688910;
-inv_value(132) -> 30191699398572330817932436647906151128;
-inv_value(133) -> 24153359518857864654345949318324920902;
-inv_value(134) -> 38645375230172583446953518909319873443;
-inv_value(135) -> 30916300184138066757562815127455898755;
-inv_value(136) -> 24733040147310453406050252101964719004;
-inv_value(137) -> 39572864235696725449680403363143550406;
-inv_value(138) -> 31658291388557380359744322690514840325;
-inv_value(139) -> 25326633110845904287795458152411872260;
-inv_value(140) -> 40522612977353446860472733043858995616;
-inv_value(141) -> 32418090381882757488378186435087196493;
-inv_value(142) -> 25934472305506205990702549148069757194;
-inv_value(143) -> 41495155688809929585124078636911611511;
-inv_value(144) -> 33196124551047943668099262909529289209;
-inv_value(145) -> 26556899640838354934479410327623431367;
-inv_value(146) -> 42491039425341367895167056524197490187;
-inv_value(147) -> 33992831540273094316133645219357992150;
-inv_value(148) -> 27194265232218475452906916175486393720;
-inv_value(149) -> 21755412185774780362325532940389114976;
-inv_value(150) -> 34808659497239648579720852704622583961;
-inv_value(151) -> 27846927597791718863776682163698067169;
-inv_value(152) -> 22277542078233375091021345730958453735;
-inv_value(153) -> 35644067325173400145634153169533525976;
-inv_value(154) -> 28515253860138720116507322535626820781;
-inv_value(155) -> 22812203088110976093205858028501456625;
-inv_value(156) -> 36499524940977561749129372845602330600;
-inv_value(157) -> 29199619952782049399303498276481864480;
-inv_value(158) -> 23359695962225639519442798621185491584;
-inv_value(159) -> 37375513539561023231108477793896786534;
-inv_value(160) -> 29900410831648818584886782235117429227;
-inv_value(161) -> 23920328665319054867909425788093943382;
-inv_value(162) -> 38272525864510487788655081260950309411;
-inv_value(163) -> 30618020691608390230924065008760247529;
-inv_value(164) -> 24494416553286712184739252007008198023;
-inv_value(165) -> 39191066485258739495582803211213116837;
-inv_value(166) -> 31352853188206991596466242568970493469;
-inv_value(167) -> 25082282550565593277172994055176394776;
-inv_value(168) -> 40131652080904949243476790488282231641;
-inv_value(169) -> 32105321664723959394781432390625785313;
-inv_value(170) -> 25684257331779167515825145912500628250;
-inv_value(171) -> 41094811730846668025320233460001005200;
-inv_value(172) -> 32875849384677334420256186768000804160;
-inv_value(173) -> 26300679507741867536204949414400643328;
-inv_value(174) -> 42081087212386988057927919063041029325;
-inv_value(175) -> 33664869769909590446342335250432823460;
-inv_value(176) -> 26931895815927672357073868200346258768;
-inv_value(177) -> 21545516652742137885659094560277007015;
-inv_value(178) -> 34472826644387420617054551296443211223;
-inv_value(179) -> 27578261315509936493643641037154568979;
-inv_value(180) -> 22062609052407949194914912829723655183;
-inv_value(181) -> 35300174483852718711863860527557848292;
-inv_value(182) -> 28240139587082174969491088422046278634;
-inv_value(183) -> 22592111669665739975592870737637022907;
-inv_value(184) -> 36147378671465183960948593180219236651;
-inv_value(185) -> 28917902937172147168758874544175389321;
-inv_value(186) -> 23134322349737717735007099635340311457;
-inv_value(187) -> 37014915759580348376011359416544498331;
-inv_value(188) -> 29611932607664278700809087533235598665;
-inv_value(189) -> 23689546086131422960647270026588478932;
-inv_value(190) -> 37903273737810276737035632042541566291;
-inv_value(191) -> 30322618990248221389628505634033253033;
-inv_value(192) -> 24258095192198577111702804507226602426;
-inv_value(193) -> 38812952307517723378724487211562563882;
-inv_value(194) -> 31050361846014178702979589769250051106;
-inv_value(195) -> 24840289476811342962383671815400040885;
-inv_value(196) -> 39744463162898148739813874904640065415;
-inv_value(197) -> 31795570530318518991851099923712052332;
-inv_value(198) -> 25436456424254815193480879938969641866;
-inv_value(199) -> 40698330278807704309569407902351426985;
-inv_value(200) -> 32558664223046163447655526321881141588;
-inv_value(201) -> 26046931378436930758124421057504913271;
-inv_value(202) -> 41675090205499089212999073692007861233;
-inv_value(203) -> 33340072164399271370399258953606288986;
-inv_value(204) -> 26672057731519417096319407162885031189;
-inv_value(205) -> 21337646185215533677055525730308024951;
-inv_value(206) -> 34140233896344853883288841168492839922;
-inv_value(207) -> 27312187117075883106631072934794271938;
-inv_value(208) -> 21849749693660706485304858347835417550;
-inv_value(209) -> 34959599509857130376487773356536668080;
-inv_value(210) -> 27967679607885704301190218685229334464;
-inv_value(211) -> 22374143686308563440952174948183467571;
-inv_value(212) -> 35798629898093701505523479917093548114;
-inv_value(213) -> 28638903918474961204418783933674838491;
-inv_value(214) -> 22911123134779968963535027146939870793;
-inv_value(215) -> 36657797015647950341656043435103793269;
-inv_value(216) -> 29326237612518360273324834748083034615;
-inv_value(217) -> 23460990090014688218659867798466427692;
-inv_value(218) -> 37537584144023501149855788477546284307;
-inv_value(219) -> 30030067315218800919884630782037027446;
-inv_value(220) -> 24024053852175040735907704625629621957;
-inv_value(221) -> 38438486163480065177452327401007395130;
-inv_value(222) -> 30750788930784052141961861920805916104;
-inv_value(223) -> 24600631144627241713569489536644732884;
-inv_value(224) -> 39361009831403586741711183258631572614;
-inv_value(225) -> 31488807865122869393368946606905258091;
-inv_value(226) -> 25191046292098295514695157285524206473;
-inv_value(227) -> 40305674067357272823512251656838730356;
-inv_value(228) -> 32244539253885818258809801325470984285;
-inv_value(229) -> 25795631403108654607047841060376787428;
-inv_value(230) -> 41273010244973847371276545696602859885;
-inv_value(231) -> 33018408195979077897021236557282287908;
-inv_value(232) -> 26414726556783262317616989245825830326;
-inv_value(233) -> 42263562490853219708187182793321328522;
-inv_value(234) -> 33810849992682575766549746234657062818;
-inv_value(235) -> 27048679994146060613239796987725650254;
-inv_value(236) -> 21638943995316848490591837590180520204;
-inv_value(237) -> 34622310392506957584946940144288832325;
-inv_value(238) -> 27697848314005566067957552115431065860;
-inv_value(239) -> 22158278651204452854366041692344852688;
-inv_value(240) -> 35453245841927124566985666707751764301;
-inv_value(241) -> 28362596673541699653588533366201411441;
-inv_value(242) -> 22690077338833359722870826692961129153;
-inv_value(243) -> 36304123742133375556593322708737806644;
-inv_value(244) -> 29043298993706700445274658166990245316;
-inv_value(245) -> 23234639194965360356219726533592196253;
-inv_value(246) -> 37175422711944576569951562453747514004;
-inv_value(247) -> 29740338169555661255961249962998011203;
-inv_value(248) -> 23792270535644529004768999970398408963;
-inv_value(249) -> 38067632857031246407630399952637454340;
-inv_value(250) -> 30454106285624997126104319962109963472;
-inv_value(251) -> 24363285028499997700883455969687970778;
-inv_value(252) -> 38981256045599996321413529551500753244;
-inv_value(253) -> 31185004836479997057130823641200602595;
-inv_value(254) -> 24948003869183997645704658912960482076;
-inv_value(255) -> 39916806190694396233127454260736771322;
-inv_value(256) -> 31933444952555516986501963408589417058;
-inv_value(257) -> 25546755962044413589201570726871533646;
-inv_value(258) -> 40874809539271061742722513162994453834;
-inv_value(259) -> 32699847631416849394178010530395563067;
-inv_value(260) -> 26159878105133479515342408424316450454;
-inv_value(261) -> 41855804968213567224547853478906320726;
-inv_value(262) -> 33484643974570853779638282783125056581;
-inv_value(263) -> 26787715179656683023710626226500045265;
-inv_value(264) -> 21430172143725346418968500981200036212;
-inv_value(265) -> 34288275429960554270349601569920057938;
-inv_value(266) -> 27430620343968443416279681255936046351;
-inv_value(267) -> 21944496275174754733023745004748837081;
-inv_value(268) -> 35111194040279607572837992007598139329;
-inv_value(269) -> 28088955232223686058270393606078511463;
-inv_value(270) -> 22471164185778948846616314884862809171;
-inv_value(271) -> 35953862697246318154586103815780494673;
-inv_value(272) -> 28763090157797054523668883052624395738;
-inv_value(273) -> 23010472126237643618935106442099516591;
-inv_value(274) -> 36816755401980229790296170307359226545;
-inv_value(275) -> 29453404321584183832236936245887381236;
-inv_value(276) -> 23562723457267347065789548996709904989;
-inv_value(277) -> 37700357531627755305263278394735847982;
-inv_value(278) -> 30160286025302204244210622715788678386;
-inv_value(279) -> 24128228820241763395368498172630942709;
-inv_value(280) -> 38605166112386821432589597076209508334;
-inv_value(281) -> 30884132889909457146071677660967606667;
-inv_value(282) -> 24707306311927565716857342128774085334;
-inv_value(283) -> 39531690099084105146971747406038536534;
-inv_value(284) -> 31625352079267284117577397924830829227;
-inv_value(285) -> 25300281663413827294061918339864663382;
-inv_value(286) -> 40480450661462123670499069343783461410;
-inv_value(287) -> 32384360529169698936399255475026769128;
-inv_value(288) -> 25907488423335759149119404380021415303;
-inv_value(289) -> 41451981477337214638591047008034264484;
-inv_value(290) -> 33161585181869771710872837606427411587;
-inv_value(291) -> 26529268145495817368698270085141929270;
-inv_value(292) -> 42446829032793307789917232136227086832;
-inv_value(293) -> 33957463226234646231933785708981669466;
-inv_value(294) -> 27165970580987716985547028567185335573;
-inv_value(295) -> 21732776464790173588437622853748268458;
-inv_value(296) -> 34772442343664277741500196565997229533;
-inv_value(297) -> 27817953874931422193200157252797783626;
-inv_value(298) -> 22254363099945137754560125802238226901;
-inv_value(299) -> 35606980959912220407296201283581163042;
-inv_value(300) -> 28485584767929776325836961026864930433;
-inv_value(301) -> 22788467814343821060669568821491944347;
-inv_value(302) -> 36461548502950113697071310114387110955;
-inv_value(303) -> 29169238802360090957657048091509688764;
-inv_value(304) -> 23335391041888072766125638473207751011;
-inv_value(305) -> 37336625667020916425801021557132401617;
-inv_value(306) -> 29869300533616733140640817245705921294;
-inv_value(307) -> 23895440426893386512512653796564737035;
-inv_value(308) -> 38232704683029418420020246074503579256;
-inv_value(309) -> 30586163746423534736016196859602863405;
-inv_value(310) -> 24468930997138827788812957487682290724;
-inv_value(311) -> 39150289595422124462100731980291665158;
-inv_value(312) -> 31320231676337699569680585584233332127;
-inv_value(313) -> 25056185341070159655744468467386665702;
-inv_value(314) -> 40089896545712255449191149547818665122;
-inv_value(315) -> 32071917236569804359352919638254932098;
-inv_value(316) -> 25657533789255843487482335710603945678;
-inv_value(317) -> 41052054062809349579971737136966313085;
-inv_value(318) -> 32841643250247479663977389709573050468;
-inv_value(319) -> 26273314600197983731181911767658440375;
-inv_value(320) -> 42037303360316773969891058828253504599;
-inv_value(321) -> 33629842688253419175912847062602803679;
-inv_value(322) -> 26903874150602735340730277650082242944;
-inv_value(323) -> 21523099320482188272584222120065794355;
-inv_value(324) -> 34436958912771501236134755392105270968;
-inv_value(325) -> 27549567130217200988907804313684216774;
-inv_value(326) -> 22039653704173760791126243450947373419;
-inv_value(327) -> 35263445926678017265801989521515797471;
-inv_value(328) -> 28210756741342413812641591617212637977;
-inv_value(329) -> 22568605393073931050113273293770110382;
-inv_value(330) -> 36109768628918289680181237270032176610;
-inv_value(331) -> 28887814903134631744144989816025741288;
-inv_value(332) -> 23110251922507705395315991852820593031;
-inv_value(333) -> 36976403076012328632505586964512948849;
-inv_value(334) -> 29581122460809862906004469571610359079;
-inv_value(335) -> 23664897968647890324803575657288287263;
-inv_value(336) -> 37863836749836624519685721051661259621;
-inv_value(337) -> 30291069399869299615748576841329007697;
-inv_value(338) -> 24232855519895439692598861473063206158;
-inv_value(339) -> 38772568831832703508158178356901129852;
-inv_value(340) -> 31018055065466162806526542685520903882;
-inv_value(341) -> 24814444052372930245221234148416723105;
-inv_value(_) -> error(function_clause).
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 161b5634b2..d2cb5aab3c 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,29 +22,57 @@
-compile({no_auto_import,[max/2]}).
-compile({no_auto_import,[min/2]}).
--export([append/2, append/1, subtract/2, reverse/1,
- nth/2, nthtail/2, prefix/2, suffix/2, droplast/1, last/1,
- seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3,
- delete/2,
- unzip/1, unzip3/1, zip/2, zip3/3, zipwith/3, zipwith3/4,
- sort/1, merge/1, merge/2, rmerge/2, merge3/3, rmerge3/3,
- usort/1, umerge/1, umerge3/3, umerge/2, rumerge3/3, rumerge/2,
- concat/1, flatten/1, flatten/2, flatlength/1,
- keydelete/3, keyreplace/4, keytake/3, keystore/4,
- keysort/2, keymerge/3, rkeymerge/3, rukeymerge/3,
- ukeysort/2, ukeymerge/3, keymap/3]).
-
--export([merge/3, rmerge/3, sort/2, umerge/3, rumerge/3, usort/2]).
-
--export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,
- partition/2,zf/2,filtermap/2,
- mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,
- search/2, splitwith/2,split/2,
- join/2]).
-
-%%% BIFs
+%% BIFs (implemented in the runtime system).
-export([keyfind/3, keymember/3, keysearch/3, member/2, reverse/2]).
+%% Miscellaneous list functions that don't take funs as
+%% arguments. Please keep in alphabetical order.
+-export([append/1, append/2, concat/1,
+ delete/2, droplast/1, duplicate/2,
+ enumerate/1, enumerate/2,
+ flatlength/1, flatten/1, flatten/2,
+ join/2, last/1, min/1, max/1,
+ nth/2, nthtail/2,
+ prefix/2, reverse/1, seq/2, seq/3,
+ split/2, sublist/2, sublist/3,
+ subtract/2, suffix/2, sum/1,
+ uniq/1, unzip/1, unzip3/1,
+ zip/2, zip3/3]).
+
+%% Functions taking a list of tuples and a position within the tuple.
+-export([keydelete/3, keyreplace/4, keymap/3,
+ keytake/3, keystore/4]).
+
+%% Sort functions that operate on list of tuples.
+-export([keymerge/3, keysort/2, ukeymerge/3, ukeysort/2]).
+
+%% Sort and merge functions.
+-export([merge/1, merge/2, merge/3, merge3/3,
+ sort/1, sort/2,
+ umerge/1, umerge/2, umerge/3, umerge3/3,
+ usort/1, usort/2]).
+
+%% Functions that take fun arguments (high-order functions). Please
+%% keep in alphabetical order.
+-export([all/2, any/2, dropwhile/2,
+ filter/2, filtermap/2, flatmap/2,
+ foldl/3, foldr/3, foreach/2,
+ map/2, mapfoldl/3, mapfoldr/3,
+ partition/2, search/2,
+ splitwith/2, takewhile/2, uniq/2,
+ zipwith/3, zipwith3/4]).
+
+%% Undocumented, but used within Erlang/OTP.
+-export([zf/2]).
+
+%% Undocumented and unused merge functions for lists sorted in reverse
+%% order. They are exported so that the fundamental building blocks
+%% for the sort functions can be tested. (Removing them would save
+%% very little because they are thin wrappers calling helper functions
+%% used by the documented sort functions.)
+-export([rkeymerge/3, rmerge/2, rmerge/3, rmerge3/3,
+ rukeymerge/3, rumerge/2, rumerge/3, rumerge3/3]).
+
%% Shadowed by erl_bif_types: lists:keyfind/3
-spec keyfind(Key, N, TupleList) -> Tuple | false when
Key :: term(),
@@ -259,16 +287,16 @@ seq_loop(0, _, L) ->
Incr :: integer(),
Seq :: [integer()].
-seq(First, Last, Inc)
- when is_integer(First), is_integer(Last), is_integer(Inc) ->
- if
- Inc > 0, First - Inc =< Last;
- Inc < 0, First - Inc >= Last ->
- N = (Last - First + Inc) div Inc,
- seq_loop(N, Inc*(N-1)+First, Inc, []);
- Inc =:= 0, First =:= Last ->
- seq_loop(1, First, Inc, [])
- end.
+seq(First, Last, Inc)
+ when is_integer(First), is_integer(Last), is_integer(Inc),
+ (Inc > 0 andalso First - Inc =< Last) orelse
+ (Inc < 0 andalso First - Inc >= Last) ->
+ N = (Last - First + Inc) div Inc,
+ seq_loop(N, Inc * (N - 1) + First, Inc, []);
+seq(Same, Same, 0) when is_integer(Same) ->
+ [Same];
+seq(First, Last, Inc) ->
+ erlang:error(badarg, [First, Last, Inc], [{error_info, #{module => erl_stdlib_errors}}]).
seq_loop(N, X, D, L) when N >= 4 ->
Y = X-D, Z = Y-D, W = Z-D,
@@ -957,6 +985,27 @@ keymap(Fun, Index, [Tup|Tail]) ->
keymap(Fun, Index, []) when is_integer(Index), Index >= 1,
is_function(Fun, 1) -> [].
+-spec enumerate(List1) -> List2 when
+ List1 :: [T],
+ List2 :: [{Index, T}],
+ Index :: integer(),
+ T :: term().
+enumerate(List1) when is_list(List1) ->
+ enumerate_1(1, List1).
+
+-spec enumerate(Index, List1) -> List2 when
+ List1 :: [T],
+ List2 :: [{Index, T}],
+ Index :: integer(),
+ T :: term().
+enumerate(Index, List1) when is_integer(Index), is_list(List1) ->
+ enumerate_1(Index, List1).
+
+enumerate_1(Index, [H|T]) ->
+ [{Index, H}|enumerate_1(Index + 1, T)];
+enumerate_1(_Index, []) ->
+ [].
+
%%% Suggestion from OTP-2948: sort and merge with Fun.
-spec sort(Fun, List1) -> List2 when
@@ -1213,24 +1262,46 @@ rumerge(T1, [H2 | T2]) ->
List :: [T],
T :: term().
-all(Pred, [Hd|Tail]) ->
+all(Pred, List) when is_function(Pred, 1) ->
+ case List of
+ [Hd | Tail] ->
+ case Pred(Hd) of
+ true -> all_1(Pred, Tail);
+ false -> false
+ end;
+ [] -> true
+ end.
+
+all_1(Pred, [Hd | Tail]) ->
case Pred(Hd) of
- true -> all(Pred, Tail);
- false -> false
+ true -> all_1(Pred, Tail);
+ false -> false
end;
-all(Pred, []) when is_function(Pred, 1) -> true.
+all_1(_Pred, []) ->
+ true.
-spec any(Pred, List) -> boolean() when
Pred :: fun((Elem :: T) -> boolean()),
List :: [T],
T :: term().
-any(Pred, [Hd|Tail]) ->
+any(Pred, List) when is_function(Pred, 1) ->
+ case List of
+ [Hd | Tail] ->
+ case Pred(Hd) of
+ true -> true;
+ false -> any_1(Pred, Tail)
+ end;
+ [] -> false
+ end.
+
+any_1(Pred, [Hd | Tail]) ->
case Pred(Hd) of
- true -> true;
- false -> any(Pred, Tail)
+ true -> true;
+ false -> any_1(Pred, Tail)
end;
-any(Pred, []) when is_function(Pred, 1) -> false.
+any_1(_Pred, []) ->
+ false.
-spec map(Fun, List1) -> List2 when
Fun :: fun((A) -> B),
@@ -1239,9 +1310,16 @@ any(Pred, []) when is_function(Pred, 1) -> false.
A :: term(),
B :: term().
-map(F, [H|T]) ->
- [F(H)|map(F, T)];
-map(F, []) when is_function(F, 1) -> [].
+map(F, List) when is_function(F, 1) ->
+ case List of
+ [Hd | Tail] -> [F(Hd) | map_1(F, Tail)];
+ [] -> []
+ end.
+
+map_1(F, [Hd | Tail]) ->
+ [F(Hd) | map_1(F, Tail)];
+map_1(_F, []) ->
+ [].
-spec flatmap(Fun, List1) -> List2 when
Fun :: fun((A) -> [B]),
@@ -1250,9 +1328,13 @@ map(F, []) when is_function(F, 1) -> [].
A :: term(),
B :: term().
-flatmap(F, [Hd|Tail]) ->
- F(Hd) ++ flatmap(F, Tail);
-flatmap(F, []) when is_function(F, 1) -> [].
+flatmap(F, List) when is_function(F, 1) ->
+ flatmap_1(F, List).
+
+flatmap_1(F, [Hd | Tail]) ->
+ F(Hd) ++ flatmap_1(F, Tail);
+flatmap_1(_F, []) ->
+ [].
-spec foldl(Fun, Acc0, List) -> Acc1 when
Fun :: fun((Elem :: T, AccIn) -> AccOut),
@@ -1263,9 +1345,16 @@ flatmap(F, []) when is_function(F, 1) -> [].
List :: [T],
T :: term().
-foldl(F, Accu, [Hd|Tail]) ->
- foldl(F, F(Hd, Accu), Tail);
-foldl(F, Accu, []) when is_function(F, 2) -> Accu.
+foldl(F, Accu, List) when is_function(F, 2) ->
+ case List of
+ [Hd | Tail] -> foldl_1(F, F(Hd, Accu), Tail);
+ [] -> Accu
+ end.
+
+foldl_1(F, Accu, [Hd | Tail]) ->
+ foldl_1(F, F(Hd, Accu), Tail);
+foldl_1(_F, Accu, []) ->
+ Accu.
-spec foldr(Fun, Acc0, List) -> Acc1 when
Fun :: fun((Elem :: T, AccIn) -> AccOut),
@@ -1276,9 +1365,13 @@ foldl(F, Accu, []) when is_function(F, 2) -> Accu.
List :: [T],
T :: term().
-foldr(F, Accu, [Hd|Tail]) ->
- F(Hd, foldr(F, Accu, Tail));
-foldr(F, Accu, []) when is_function(F, 2) -> Accu.
+foldr(F, Accu, List) when is_function(F, 2) ->
+ foldr_1(F, Accu, List).
+
+foldr_1(F, Accu, [Hd | Tail]) ->
+ F(Hd, foldr_1(F, Accu, Tail));
+foldr_1(_F, Accu, []) ->
+ Accu.
-spec filter(Pred, List1) -> List2 when
Pred :: fun((Elem :: T) -> boolean()),
@@ -1299,15 +1392,15 @@ filter(Pred, List) when is_function(Pred, 1) ->
NotSatisfying :: [T],
T :: term().
-partition(Pred, L) ->
- partition(Pred, L, [], []).
+partition(Pred, L) when is_function(Pred, 1) ->
+ partition_1(Pred, L, [], []).
-partition(Pred, [H | T], As, Bs) ->
+partition_1(Pred, [H | T], As, Bs) ->
case Pred(H) of
- true -> partition(Pred, T, [H | As], Bs);
- false -> partition(Pred, T, As, [H | Bs])
+ true -> partition_1(Pred, T, [H | As], Bs);
+ false -> partition_1(Pred, T, As, [H | Bs])
end;
-partition(Pred, [], As, Bs) when is_function(Pred, 1) ->
+partition_1(_Pred, [], As, Bs) ->
{reverse(As), reverse(Bs)}.
-spec filtermap(Fun, List1) -> List2 when
@@ -1317,16 +1410,20 @@ partition(Pred, [], As, Bs) when is_function(Pred, 1) ->
Elem :: term(),
Value :: term().
-filtermap(F, [Hd|Tail]) ->
+filtermap(F, List) when is_function(F, 1) ->
+ filtermap_1(F, List).
+
+filtermap_1(F, [Hd|Tail]) ->
case F(Hd) of
- true ->
- [Hd|filtermap(F, Tail)];
- {true,Val} ->
- [Val|filtermap(F, Tail)];
- false ->
- filtermap(F, Tail)
+ true ->
+ [Hd | filtermap_1(F, Tail)];
+ {true,Val} ->
+ [Val | filtermap_1(F, Tail)];
+ false ->
+ filtermap_1(F, Tail)
end;
-filtermap(F, []) when is_function(F, 1) -> [].
+filtermap_1(_F, []) ->
+ [].
-spec zf(fun((T) -> boolean() | {'true', X}), [T]) -> [(T | X)].
@@ -1338,10 +1435,14 @@ zf(F, L) ->
List :: [T],
T :: term().
-foreach(F, [Hd|Tail]) ->
+foreach(F, List) when is_function(F, 1) ->
+ foreach_1(F, List).
+
+foreach_1(F, [Hd | Tail]) ->
F(Hd),
- foreach(F, Tail);
-foreach(F, []) when is_function(F, 1) -> ok.
+ foreach_1(F, Tail);
+foreach_1(_F, []) ->
+ ok.
-spec mapfoldl(Fun, Acc0, List1) -> {List2, Acc1} when
Fun :: fun((A, AccIn) -> {B, AccOut}),
@@ -1354,11 +1455,15 @@ foreach(F, []) when is_function(F, 1) -> ok.
A :: term(),
B :: term().
-mapfoldl(F, Accu0, [Hd|Tail]) ->
- {R,Accu1} = F(Hd, Accu0),
- {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
- {[R|Rs],Accu2};
-mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
+mapfoldl(F, Accu, List) when is_function(F, 2) ->
+ mapfoldl_1(F, Accu, List).
+
+mapfoldl_1(F, Accu0, [Hd | Tail]) ->
+ {R, Accu1} = F(Hd, Accu0),
+ {Rs, Accu2} = mapfoldl_1(F, Accu1, Tail),
+ {[R | Rs], Accu2};
+mapfoldl_1(_F, Accu, []) ->
+ {[], Accu}.
-spec mapfoldr(Fun, Acc0, List1) -> {List2, Acc1} when
Fun :: fun((A, AccIn) -> {B, AccOut}),
@@ -1371,11 +1476,15 @@ mapfoldl(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
A :: term(),
B :: term().
-mapfoldr(F, Accu0, [Hd|Tail]) ->
- {Rs,Accu1} = mapfoldr(F, Accu0, Tail),
- {R,Accu2} = F(Hd, Accu1),
- {[R|Rs],Accu2};
-mapfoldr(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
+mapfoldr(F, Accu, List) when is_function(F, 2) ->
+ mapfoldr_1(F, Accu, List).
+
+mapfoldr_1(F, Accu0, [Hd|Tail]) ->
+ {Rs, Accu1} = mapfoldr_1(F, Accu0, Tail),
+ {R, Accu2} = F(Hd, Accu1),
+ {[R | Rs], Accu2};
+mapfoldr_1(_F, Accu, []) ->
+ {[], Accu}.
-spec takewhile(Pred, List1) -> List2 when
Pred :: fun((Elem :: T) -> boolean()),
@@ -1383,12 +1492,16 @@ mapfoldr(F, Accu, []) when is_function(F, 2) -> {[],Accu}.
List2 :: [T],
T :: term().
-takewhile(Pred, [Hd|Tail]) ->
+takewhile(Pred, List) when is_function(Pred, 1) ->
+ takewhile_1(Pred, List).
+
+takewhile_1(Pred, [Hd | Tail]) ->
case Pred(Hd) of
- true -> [Hd|takewhile(Pred, Tail)];
- false -> []
+ true -> [Hd | takewhile_1(Pred, Tail)];
+ false -> []
end;
-takewhile(Pred, []) when is_function(Pred, 1) -> [].
+takewhile_1(_Pred, []) ->
+ [].
-spec dropwhile(Pred, List1) -> List2 when
Pred :: fun((Elem :: T) -> boolean()),
@@ -1396,24 +1509,31 @@ takewhile(Pred, []) when is_function(Pred, 1) -> [].
List2 :: [T],
T :: term().
-dropwhile(Pred, [Hd|Tail]=Rest) ->
+dropwhile(Pred, List) when is_function(Pred, 1) ->
+ dropwhile_1(Pred, List).
+
+dropwhile_1(Pred, [Hd | Tail]=Rest) ->
case Pred(Hd) of
- true -> dropwhile(Pred, Tail);
- false -> Rest
+ true -> dropwhile_1(Pred, Tail);
+ false -> Rest
end;
-dropwhile(Pred, []) when is_function(Pred, 1) -> [].
+dropwhile_1(_Pred, []) ->
+ [].
-spec search(Pred, List) -> {value, Value} | false when
Pred :: fun((T) -> boolean()),
List :: [T],
Value :: T.
-search(Pred, [Hd|Tail]) ->
+search(Pred, List) when is_function(Pred, 1) ->
+ search_1(Pred, List).
+
+search_1(Pred, [Hd | Tail]) ->
case Pred(Hd) of
true -> {value, Hd};
- false -> search(Pred, Tail)
+ false -> search_1(Pred, Tail)
end;
-search(Pred, []) when is_function(Pred, 1) ->
+search_1(_Pred, []) ->
false.
-spec splitwith(Pred, List) -> {List1, List2} when
@@ -1424,14 +1544,14 @@ search(Pred, []) when is_function(Pred, 1) ->
T :: term().
splitwith(Pred, List) when is_function(Pred, 1) ->
- splitwith(Pred, List, []).
+ splitwith_1(Pred, List, []).
-splitwith(Pred, [Hd|Tail], Taken) ->
+splitwith_1(Pred, [Hd|Tail], Taken) ->
case Pred(Hd) of
- true -> splitwith(Pred, Tail, [Hd|Taken]);
+ true -> splitwith_1(Pred, Tail, [Hd|Taken]);
false -> {reverse(Taken), [Hd|Tail]}
end;
-splitwith(Pred, [], Taken) when is_function(Pred, 1) ->
+splitwith_1(_Pred, [], Taken) ->
{reverse(Taken),[]}.
-spec split(N, List1) -> {List2, List3} when
@@ -2855,3 +2975,44 @@ rufmerge2_2(H1, T1, Fun, [], M, H2M) ->
lists:reverse(T1, [H1, H2M | M])
end.
+%% uniq/1: return a new list with the unique elements of the given list
+
+-spec uniq(List1) -> List2 when
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
+
+uniq(L) ->
+ uniq_1(L, #{}).
+
+uniq_1([X | Xs], M) ->
+ case is_map_key(X, M) of
+ true ->
+ uniq_1(Xs, M);
+ false ->
+ [X | uniq_1(Xs, M#{X => true})]
+ end;
+uniq_1([], _) ->
+ [].
+
+%% uniq/2: return a new list with the unique elements of the given list using a function key
+
+-spec uniq(Fun, List1) -> List2 when
+ Fun :: fun((T) -> any()),
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
+
+uniq(F, L) when is_function(F, 1) ->
+ uniq_2(L, F, #{}).
+
+uniq_2([X | Xs], F, M) ->
+ Key = F(X),
+ case is_map_key(Key, M) of
+ true ->
+ uniq_2(Xs, F, M);
+ false ->
+ [X | uniq_2(Xs, F, M#{Key => true})]
+ end;
+uniq_2([], _, _) ->
+ [].
diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl
index e6192eb22b..c7107031fb 100644
--- a/lib/stdlib/src/maps.erl
+++ b/lib/stdlib/src/maps.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
without/2, with/2,
iterator/1, next/1,
intersect/2, intersect_with/3,
- merge_with/3]).
+ merge_with/3,
+ groups_from_list/2, groups_from_list/3]).
%% BIFs
-export([get/2, find/2, from_list/1, from_keys/2,
@@ -497,6 +498,69 @@ with_1([K|Ks], Map) ->
end;
with_1([], _Map) -> [].
+%% groups_from_list/2 & groups_from_list/3
+
+-spec groups_from_list(Fun, List) -> MapOut when
+ Fun :: fun((Elem :: T) -> Selected),
+ MapOut :: #{Selected => List},
+ Selected :: term(),
+ List :: [T],
+ T :: term().
+
+groups_from_list(Fun, List0) when is_function(Fun, 1) ->
+ try lists:reverse(List0) of
+ List ->
+ groups_from_list_1(Fun, List, #{})
+ catch
+ error:_ ->
+ badarg_with_info([Fun, List0])
+ end;
+groups_from_list(Fun, List) ->
+ badarg_with_info([Fun, List]).
+
+groups_from_list_1(Fun, [H | Tail], Acc) ->
+ K = Fun(H),
+ NewAcc = case Acc of
+ #{K := Vs} -> Acc#{K := [H | Vs]};
+ #{} -> Acc#{K => [H]}
+ end,
+ groups_from_list_1(Fun, Tail, NewAcc);
+groups_from_list_1(_Fun, [], Acc) ->
+ Acc.
+
+-spec groups_from_list(Fun, ValueFun, List) -> MapOut when
+ Fun :: fun((Elem :: T) -> Key),
+ ValueFun :: fun((Elem :: T) -> ValOut),
+ MapOut :: #{Key := ListOut},
+ Key :: term(),
+ ValOut :: term(),
+ List :: [T],
+ ListOut :: [ValOut],
+ T :: term().
+
+groups_from_list(Fun, ValueFun, List0) when is_function(Fun, 1),
+ is_function(ValueFun, 1) ->
+ try lists:reverse(List0) of
+ List ->
+ groups_from_list_2(Fun, ValueFun, List, #{})
+ catch
+ error:_ ->
+ badarg_with_info([Fun, ValueFun, List0])
+ end;
+groups_from_list(Fun, ValueFun, List) ->
+ badarg_with_info([Fun, ValueFun, List]).
+
+groups_from_list_2(Fun, ValueFun, [H | Tail], Acc) ->
+ K = Fun(H),
+ V = ValueFun(H),
+ NewAcc = case Acc of
+ #{K := Vs} -> Acc#{K := [V | Vs]};
+ #{} -> Acc#{K => [V]}
+ end,
+ groups_from_list_2(Fun, ValueFun, Tail, NewAcc);
+groups_from_list_2(_Fun, _ValueFun, [], Acc) ->
+ Acc.
+
error_type(M) when is_map(M) -> badarg;
error_type(V) -> {badmap, V}.
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index 890267b439..dde8e572a3 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -756,7 +756,12 @@ tg({bin_element,Anno,X,Y,Z},B) ->
tg({bin,Anno,List},B) ->
{bin,Anno,[tg(X,B) || X <- List]};
-
+
+tg({map_field_assoc, Anno, Field, Value}, B) ->
+ {map_field_assoc, Anno, tg(Field, B), tg(Value, B)};
+tg({map, Anno, List}, B) ->
+ {map, Anno, [tg(X, B) || X <- List]};
+
tg(T,B) when is_tuple(T), tuple_size(T) >= 2 ->
Element = element(1,T),
Anno = element(2,T),
@@ -858,6 +863,9 @@ th({var,Anno,Name},B,OB) ->
Trans ->
{{atom,Anno,Trans},B}
end;
+th({map_field_exact,Anno,Field,Value},B,OB) ->
+ {[NField, NValue], NB} = th([Field, Value], B, OB),
+ {{map_field_assoc,Anno,NField,NValue}, NB};
th([H|T],B,OB) ->
{NH,NB} = th(H,B,OB),
{NT,NNB} = th(T,NB,OB),
@@ -974,8 +982,11 @@ real_guard_function(node,1) -> true;
real_guard_function(round,1) -> true;
real_guard_function(size,1) -> true;
real_guard_function(bit_size,1) -> true;
+real_guard_function(byte_size,1) -> true;
real_guard_function(map_size,1) -> true;
real_guard_function(map_get,2) -> true;
+real_guard_function(binary_part,2) -> true;
+real_guard_function(binary_part,3) -> true;
real_guard_function(tl,1) -> true;
real_guard_function(trunc,1) -> true;
real_guard_function(self,0) -> true;
@@ -1123,7 +1134,7 @@ normalise({bin,_,Fs}) ->
eval_bits:expr_grp(Fs, [],
fun(E, _) ->
{value, normalise(E), []}
- end, [], true),
+ end),
B;
normalise({cons,_,Head,Tail}) ->
[normalise(Head)|normalise(Tail)];
@@ -1131,12 +1142,11 @@ normalise({op,_,'++',A,B}) ->
normalise(A) ++ normalise(B);
normalise({tuple,_,Args}) ->
list_to_tuple(normalise_list(Args));
-normalise({map,_,Pairs0}) ->
- Pairs1 = lists:map(fun ({map_field_exact,_,K,V}) ->
- {normalise(K),normalise(V)}
- end,
- Pairs0),
- maps:from_list(Pairs1);
+normalise({map,_,Pairs}) ->
+ maps:from_list(lists:map(fun
+ %% only allow '=>'
+ ({map_field_assoc,_,K,V}) -> {normalise(K),normalise(V)}
+ end, Pairs));
%% Special case for unary +/-.
normalise({op,_,'+',{char,_,I}}) -> I;
normalise({op,_,'+',{integer,_,I}}) -> I;
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 86196d47d1..3afbbfb881 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -35,6 +35,10 @@ obsolete(code, is_module_native, 1) ->
{deprecated, "HiPE has been removed", "OTP 26"};
obsolete(code, rehash, 0) ->
{deprecated, "the code path cache feature has been removed", "OTP 26"};
+obsolete(crypto, crypto_dyn_iv_init, 3) ->
+ {deprecated, "see the documentation for details", "OTP 27"};
+obsolete(crypto, crypto_dyn_iv_update, 3) ->
+ {deprecated, "see the documentation for details", "OTP 27"};
obsolete(crypto, rand_uniform, 2) ->
{deprecated, "use rand:uniform/1 instead"};
obsolete(disk_log, accessible_logs, 0) ->
@@ -47,24 +51,20 @@ obsolete(erlang, now, 0) ->
{deprecated, "see the \"Time and Time Correction in Erlang\" chapter of the ERTS User's Guide for more information"};
obsolete(erlang, phash, 2) ->
{deprecated, "use erlang:phash2/2 instead"};
-obsolete(filename, safe_relative_path, 1) ->
- {deprecated, "use filelib:safe_relative_path/2 instead", "OTP 25"};
obsolete(ftp, start_service, 1) ->
{deprecated, "use ftp:open/2 instead", "OTP 26"};
obsolete(ftp, stop_service, 1) ->
{deprecated, "use ftp:close/1 instead", "OTP 26"};
obsolete(http_uri, decode, 1) ->
- {deprecated, "use uri_string functions instead", "OTP 25"};
+ {deprecated, "use uri_string:unquote function instead", "OTP 26"};
obsolete(http_uri, encode, 1) ->
- {deprecated, "use uri_string functions instead", "OTP 25"};
-obsolete(http_uri, parse, 1) ->
- {deprecated, "use uri_string functions instead", "OTP 25"};
-obsolete(http_uri, parse, 2) ->
- {deprecated, "use uri_string functions instead", "OTP 25"};
-obsolete(http_uri, scheme_defaults, 0) ->
- {deprecated, "use uri_string functions instead", "OTP 25"};
+ {deprecated, "use uri_string:quote function instead", "OTP 26"};
obsolete(httpd, parse_query, 1) ->
{deprecated, "use uri_string:dissect_query/1 instead"};
+obsolete(httpd_util, decode_hex, 1) ->
+ {deprecated, "use uri_string:unquote function instead", "OTP 26"};
+obsolete(httpd_util, encode_hex, 1) ->
+ {deprecated, "use uri_string:quote function instead", "OTP 26"};
obsolete(httpd_util, flatlength, 1) ->
{deprecated, "use erlang:iolist_size/1 instead", "OTP 26"};
obsolete(httpd_util, hexlist_to_integer, 1) ->
@@ -83,84 +83,10 @@ obsolete(net, cast, 4) ->
{deprecated, "use rpc:cast/4 instead"};
obsolete(net, ping, 1) ->
{deprecated, "use net_adm:ping/1 instead"};
-obsolete(net, relay, 1) ->
- {deprecated, "use slave:relay/1 instead"};
obsolete(net, sleep, 1) ->
{deprecated, "use 'receive after T -> ok end' instead"};
-obsolete(public_key, ssh_decode, 2) ->
- {deprecated, "use ssh_file:decode/2 instead", "OTP 26"};
-obsolete(public_key, ssh_encode, 2) ->
- {deprecated, "use ssh_file:encode/2 instead", "OTP 26"};
-obsolete(public_key, ssh_hostkey_fingerprint, 1) ->
- {deprecated, "use ssh:hostkey_fingerprint/1 instead", "OTP 26"};
-obsolete(public_key, ssh_hostkey_fingerprint, 2) ->
- {deprecated, "use ssh:hostkey_fingerprint/2 instead", "OTP 26"};
obsolete(queue, lait, 1) ->
{deprecated, "use queue:liat/1 instead"};
-obsolete(snmpm, async_get, 3) ->
- {deprecated, "use snmpm:async_get2/3 instead.", "OTP 25"};
-obsolete(snmpm, async_get, 4) ->
- {deprecated, "use snmpm:async_get2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_get, 5) ->
- {deprecated, "use snmpm:async_get2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_get, 6) ->
- {deprecated, "use snmpm:async_get2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_get_bulk, 5) ->
- {deprecated, "use snmpm:async_get_bulk2/5 instead.", "OTP 25"};
-obsolete(snmpm, async_get_bulk, 6) ->
- {deprecated, "use snmpm:async_get_bulk2/6 instead.", "OTP 25"};
-obsolete(snmpm, async_get_bulk, 7) ->
- {deprecated, "use snmpm:async_get_bulk2/6 instead.", "OTP 25"};
-obsolete(snmpm, async_get_bulk, 8) ->
- {deprecated, "use snmpm:async_get_bulk2/6 instead.", "OTP 25"};
-obsolete(snmpm, async_get_next, 3) ->
- {deprecated, "use snmpm:async_get_next2/3 instead.", "OTP 25"};
-obsolete(snmpm, async_get_next, 4) ->
- {deprecated, "use snmpm:async_get_next2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_get_next, 5) ->
- {deprecated, "use snmpm:async_get_next2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_get_next, 6) ->
- {deprecated, "use snmpm:async_get_next2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_set, 3) ->
- {deprecated, "use snmpm:async_set2/3 instead.", "OTP 25"};
-obsolete(snmpm, async_set, 4) ->
- {deprecated, "use snmpm:async_set2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_set, 5) ->
- {deprecated, "use snmpm:async_set2/4 instead.", "OTP 25"};
-obsolete(snmpm, async_set, 6) ->
- {deprecated, "use snmpm:async_set2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_get, 3) ->
- {deprecated, "use snmpm:sync_get2/3 instead.", "OTP 25"};
-obsolete(snmpm, sync_get, 4) ->
- {deprecated, "use snmpm:sync_get2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_get, 5) ->
- {deprecated, "use snmpm:sync_get2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_get, 6) ->
- {deprecated, "use snmpm:sync_get2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_bulk, 5) ->
- {deprecated, "use snmpm:sync_get_bulk2/5 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_bulk, 6) ->
- {deprecated, "use snmpm:sync_get_bulk2/6 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_bulk, 7) ->
- {deprecated, "use snmpm:sync_get_bulk2/6 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_bulk, 8) ->
- {deprecated, "use snmpm:sync_get_bulk2/6 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_next, 3) ->
- {deprecated, "use snmpm:sync_get_next2/3 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_next, 4) ->
- {deprecated, "use snmpm:sync_get_next2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_next, 5) ->
- {deprecated, "use snmpm:sync_get_next2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_get_next, 6) ->
- {deprecated, "use snmpm:sync_get_next2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_set, 3) ->
- {deprecated, "use snmpm:sync_set2/3 instead.", "OTP 25"};
-obsolete(snmpm, sync_set, 4) ->
- {deprecated, "use snmpm:sync_set2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_set, 5) ->
- {deprecated, "use snmpm:sync_set2/4 instead.", "OTP 25"};
-obsolete(snmpm, sync_set, 6) ->
- {deprecated, "use snmpm:sync_set2/4 instead.", "OTP 25"};
obsolete(sys, get_debug, 3) ->
{deprecated, "incorrectly documented and only for internal use. Can often be replaced with sys:get_log/1"};
obsolete(wxCalendarCtrl, enableYearChange, 1) ->
@@ -243,18 +169,36 @@ obsolete(erlang, get_stacktrace, 0) ->
{removed, "use the new try/catch syntax for retrieving the stack backtrace"};
obsolete(erlang, hash, 2) ->
{removed, "use erlang:phash2/2 instead"};
+obsolete(filename, safe_relative_path, 1) ->
+ {removed, "use filelib:safe_relative_path/2 instead"};
+obsolete(http_uri, parse, 1) ->
+ {removed, "use uri_string functions instead"};
+obsolete(http_uri, parse, 2) ->
+ {removed, "use uri_string functions instead"};
+obsolete(http_uri, scheme_defaults, 0) ->
+ {removed, "use uri_string functions instead"};
obsolete(httpd_conf, check_enum, 2) ->
{removed, "use lists:member/2 instead"};
obsolete(httpd_conf, clean, 1) ->
- {removed, "use sting:strip/1 instead or possibly the re module"};
+ {removed, "use string:strip/1 instead or possibly the re module"};
obsolete(httpd_conf, custom_clean, 3) ->
- {removed, "use sting:strip/1 instead or possibly the re module"};
+ {removed, "use string:strip/1 instead or possibly the re module"};
obsolete(httpd_conf, is_directory, 1) ->
{removed, "use filelib:is_dir/1 instead"};
obsolete(httpd_conf, is_file, 1) ->
{removed, "use filelib:is_file/1 instead"};
obsolete(httpd_conf, make_integer, 1) ->
{removed, "use erlang:list_to_integer/1 instead"};
+obsolete(net, relay, 1) ->
+ {removed, "use fun Relay(Pid) -> receive X -> Pid ! X end, Relay(Pid) instead"};
+obsolete(public_key, ssh_decode, 2) ->
+ {removed, "use ssh_file:decode/2 instead"};
+obsolete(public_key, ssh_encode, 2) ->
+ {removed, "use ssh_file:encode/2 instead"};
+obsolete(public_key, ssh_hostkey_fingerprint, 1) ->
+ {removed, "use ssh:hostkey_fingerprint/1 instead"};
+obsolete(public_key, ssh_hostkey_fingerprint, 2) ->
+ {removed, "use ssh:hostkey_fingerprint/2 instead"};
obsolete(rpc, safe_multi_server_call, 2) ->
{removed, "use rpc:multi_server_call/2 instead"};
obsolete(rpc, safe_multi_server_call, 3) ->
@@ -285,10 +229,16 @@ obsolete(filename, find_src, _) ->
{removed, "use filelib:find_source/1,3 instead"};
obsolete(ssl, ssl_accept, _) ->
{removed, "use ssl_handshake/1,2,3 instead"};
+obsolete(ct_slave, _, _) ->
+ {deprecated, "use ?CT_PEER(), or the 'peer' module instead", "OTP 27"};
+obsolete(erts_alloc_config, _, _) ->
+ {deprecated, "this module will be removed in OTP 26.0. See the documentation for details", "OTP 26"};
obsolete(gen_fsm, _, _) ->
{deprecated, "use the 'gen_statem' module instead"};
obsolete(random, _, _) ->
{deprecated, "use the 'rand' module instead"};
+obsolete(slave, _, _) ->
+ {deprecated, "use the 'peer' module instead", "OTP 27"};
obsolete(os_mon_mib, _, _) ->
{removed, "this module was removed in OTP 22.0"};
obsolete(pg2, _, _) ->
@@ -314,5 +264,19 @@ obsolete_type(erl_scan, line, 0) ->
{removed, "use erl_anno:line() instead"};
obsolete_type(erl_scan, location, 0) ->
{removed, "use erl_anno:location() instead"};
+obsolete_type(http_uri, default_scheme_port_number, 0) ->
+ {removed, "use uri_string instead"};
+obsolete_type(http_uri, fragment, 0) ->
+ {removed, "use uri_string instead"};
+obsolete_type(http_uri, host, 0) ->
+ {removed, "use uri_string instead"};
+obsolete_type(http_uri, path, 0) ->
+ {removed, "use uri_string instead"};
+obsolete_type(http_uri, query, 0) ->
+ {removed, "use uri_string instead"};
+obsolete_type(http_uri, scheme, 0) ->
+ {removed, "use uri_string instead"};
+obsolete_type(http_uri, user_info, 0) ->
+ {removed, "use uri_string instead"};
obsolete_type(_,_,_) -> no.
diff --git a/lib/stdlib/src/peer.erl b/lib/stdlib/src/peer.erl
new file mode 100644
index 0000000000..b4867c1bdf
--- /dev/null
+++ b/lib/stdlib/src/peer.erl
@@ -0,0 +1,1185 @@
+%%
+%% Copyright WhatsApp Inc. and its affiliates. All rights reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+
+%% @doc
+%% Controller for additional Erlang node running on the same host,
+%% or in a different container/host (e.g. Docker).
+%%
+%% == Terms ==
+%% Origin node - Erlang VM instance that spawns additional nodes.
+%% Peer node - a node spawned by the origin.
+%% Control process - a process running on origin node, if it terminates,
+%% peer node terminates too.
+%% Control connection - a connection between origin and peer, can be
+%% ether Erlang Distribution connection, or alternative one.
+%%
+%% I/O is forwarded from peer node to origin via control connection.
+%%
+%% When standard_io is used as alternative connection, peer node
+%% uses standard out to multiplex console output and control sequences.
+%% Characters in range of 192-255 are reserved for control sequences,
+%% see encode_port_data for details. If peer node attempts to print
+%% characters in this range, an controlling process on the origin
+%% node may terminate with an error (because CRC check will fail).
+%%
+%% Alternative connection via TCP does not have that limitation, but
+%% it also does not redirect console I/O from the peer node.
+%% @end
+-module(peer).
+-author("maximfca@gmail.com").
+
+%% API
+-export([
+ start_link/0,
+ start_link/1,
+ start/1,
+ stop/1,
+
+ random_name/0,
+ random_name/1,
+
+ get_state/1,
+
+ call/4,
+ call/5,
+ cast/4,
+ send/3
+ ]).
+
+-export_type([server_ref/0]).
+
+-type server_ref() :: % What stop, get_state, call, cast, send accepts
+ pid().
+
+
+%% Could be gen_statem too, with peer_state, but most interactions
+%% are anyway available in all states.
+-behaviour(gen_server).
+
+%% gen_server callbacks
+-export([
+ init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2
+ ]).
+
+%% Internal exports for stdin/stdout, non-distribution RPC, and tests
+-export([
+ start/0, %% this function must be named "start", requirement for user.erl
+
+ %% Peer supervision...
+ supervision_child_spec/0,
+ start_supervision/0,
+ init_supervision/2,
+ system_continue/3,
+ system_terminate/4,
+ system_code_change/4,
+ system_get_state/1,
+ system_replace_state/2
+ ]).
+
+%% Origin node will listen to the specified port (port 0 is auto-select),
+%% or specified IP/Port, and expect peer node to connect to this port.
+-type connection() ::
+ Port :: 0..65535 |
+ {inet:ip_address(), 0..65535} |
+ standard_io.
+
+%% Specification for boot waiting
+-type wait_boot() ::
+ timeout() | %% wait for node to boot (default, 15 sec),
+ {pid(), Tag :: term()} | %% do not wait, send {Tag, {started, node(), pid()}} to Pid when node boots
+ false. %% don't wait, don't notify
+
+-type exec() ::
+ file:name() | %% path to "erl" (default is init:get_argument(progname))
+ {file:name(), [string()]}. %% SSH support: {"/usr/bin/ssh", ["account@host_b", "/usr/bin/erl"]}
+
+%% Peer node start options
+-type start_options() ::
+ #{
+ name => atom() | string(), %% node name (part before @), if not defined, peer
+ %% starts in non-distributed mode (requires alternative connection)
+ longnames => boolean(), %% long/short names (default is net_kernel:longnames(), and shortnames)
+ host => string(), %% force hostname (when not specified, actual peer node hostname is used)
+ peer_down => stop | continue | crash, %% stop (default): when peer terminates, peer control process
+ %% stops normally regardless of the reason.
+ %% continue: when peer terminates, peer control process stays up
+ %% saving exit reason in the state
+ %% crash: when peer terminates, origin process
+ %% terminates with underlying reason
+ exec => exec(), %% path to executable, or SSH/Docker support
+ connection => connection(), %% alternative connection specification
+ args => [string()], %% additional command line parameters to append
+ env => [{string(), string()}], %% additional environment variables
+ wait_boot => wait_boot(), %% default is synchronous start with 15 sec timeout
+ shutdown => close | %% close supervision channel
+ halt | %% The default... %% stop node using erlang:halt() wait default timeout for nodedown
+ {halt, disconnect_timeout()} | %% stop node using erlang:halt() wait timeout() for nodedown
+ disconnect_timeout() %% send init:stop() request and wait up to specified timeout for nodedown
+ }.
+
+%% Peer node states
+-type peer_state() :: booting | running | {down, Reason :: term()}.
+
+-export_type([
+ start_options/0,
+ peer_state/0,
+ exec/0,
+ disconnect_timeout/0
+ ]).
+
+%% Maximum integer timeout value in a receive...
+-define (MAX_INT_TIMEOUT, 4294967295).
+
+%% Default time we wait for distributed connection to be removed,
+%% when shutdown type is halt, before we disconnect from the node...
+-define (DEFAULT_HALT_DISCONNECT_TIMEOUT, 5000).
+
+%% Minimum time we wait for distributed connection to be removed,
+%% before we disconnect from the node (except in the shutdown
+%% close case)...
+-define (MIN_DISCONNECT_TIMEOUT, 1000).
+
+%% Socket connect timeout, for TCP connection.
+-define (CONNECT_TIMEOUT, 10000).
+
+%% Socket accept timeout, for TCP connection.
+-define (ACCEPT_TIMEOUT, 60000).
+
+%% How long to wait for graceful shutdown.
+-define (SHUTDOWN_TIMEOUT, 10000).
+
+%% Synchronous RPC timeout for alternative connection.
+-define (SYNC_RPC_TIMEOUT, 5000).
+
+%% Default timeout for peer node to boot.
+-define (WAIT_BOOT_TIMEOUT, 15000).
+
+-type disconnect_timeout() :: ?MIN_DISCONNECT_TIMEOUT..?MAX_INT_TIMEOUT | infinity.
+
+%% Peer supervisor channel connect timeout.
+-define(PEER_SUP_CHANNEL_CONNECT_TIMEOUT, 30000).
+
+%% @doc Creates random node name, using "peer" as prefix.
+-spec random_name() -> string().
+random_name() ->
+ random_name(?MODULE_STRING).
+
+%% @doc Creates sufficiently random node name,
+%% using OS process ID for origin VM, resulting name
+%% looks like prefix-3-7161
+-spec random_name(Prefix :: string() | atom()) -> string().
+random_name(Prefix) ->
+ OsPid = os:getpid(),
+ Uniq = erlang:unique_integer([positive]),
+ lists:concat([Prefix, "-", Uniq, "-", OsPid]).
+
+%% @doc Starts a distributed node with random name, on this host,
+%% and waits for that node to boot. Returns full node name,
+%% registers local process with the same name as peer node.
+-spec start_link() -> {ok, pid(), node()} | {error, Reason :: term()}.
+start_link() ->
+ start_link(#{name => random_name()}).
+
+%% @doc Starts peer node, linked to the calling process.
+%% Accepts additional command line arguments and
+%% other important options.
+-spec start_link(start_options()) -> {ok, pid()} | {ok, pid(), node()} | {error, Reason}
+ when Reason :: term().
+start_link(Options) ->
+ start_it(Options, start_link).
+
+%% @doc Starts peer node, not linked to the calling process.
+-spec start(start_options()) -> {ok, pid()} | {ok, pid(), node()} | {error, Reason}
+ when Reason :: term().
+start(Options) ->
+ start_it(Options, start).
+
+%% @doc Stops controlling process, shutting down peer node synchronously
+-spec stop(Dest :: server_ref()) -> ok.
+stop(Dest) ->
+ gen_server:stop(Dest).
+
+%% @doc returns peer node state.
+-spec get_state(Dest :: server_ref()) -> peer_state().
+get_state(Dest) ->
+ gen_server:call(Dest, get_state).
+
+%% @doc Calls M:F(A) remotely, via alternative connection, with default 5 seconds timeout
+-spec call(Dest :: server_ref(), Module :: module(), Function :: atom(),
+ Args :: [term()]) -> Result :: term().
+call(Dest, M, F, A) ->
+ call(Dest, M, F, A, ?SYNC_RPC_TIMEOUT).
+
+%% @doc Call M:F(A) remotely, timeout is explicitly specified
+-spec call(Dest :: server_ref(), Module :: module(), Function :: atom(),
+ Args :: [term()], Timeout :: timeout()) -> Result :: term().
+call(Dest, M, F, A, Timeout) ->
+ case gen_server:call(Dest, {call, M, F, A}, Timeout) of
+ {ok, Reply} ->
+ Reply;
+ {Class, {Reason, Stack}} ->
+ erlang:raise(Class, Reason, Stack);
+ {error, Reason} ->
+ erlang:error(Reason)
+ end.
+
+%% @doc Cast M:F(A) remotely, don't care about the result
+-spec cast(Dest :: server_ref(), Module :: module(), Function :: atom(), Args :: [term()]) -> ok.
+cast(Dest, M, F, A) ->
+ gen_server:cast(Dest, {cast, M, F, A}).
+
+%% @doc Sends a message to pid or named process on the peer node
+%% using alternative connection. No delivery guarantee.
+-spec send(Dest :: server_ref(), To :: pid() | atom(), Message :: term()) -> ok.
+send(Dest, To, Message) ->
+ gen_server:cast(Dest, {send, To, Message}).
+
+%%--------------------------------------------------------------------
+%%% gen_server callbacks
+
+-record(peer_state, {
+ options :: start_options(),
+ %% full node name, can be 'undefined'
+ node :: atom(),
+ %% debugging information: executable and arguments used to
+ %% start the peer
+ exec :: file:name(),
+ args :: [string()],
+ %% alternative connection socket/port
+ connection :: undefined | port() | gen_tcp:socket(),
+ %% listening socket, while waiting for network alternative connection
+ listen_socket :: undefined | gen_tcp:socket(),
+ %% accumulator for RPC over standard_io
+ stdio = <<>> :: binary(),
+ %% peer state
+ peer_state = booting :: peer_state(),
+ %% pid/ref saved for gen:reply() when node is booted, or false
+ notify = false :: false | {pid(), reference()},
+ %% counter (reference) for calls.
+ %% it is not possible to use erlang reference, or pid,
+ %% because it changes when node becomes distributed dynamically.
+ seq = 0 :: non_neg_integer(),
+ %% outstanding calls
+ outstanding = #{} :: #{non_neg_integer() => {reference(), pid()}}
+ }).
+
+-type state() :: #peer_state{}.
+
+-spec init([Name :: atom(), ... ]) -> {ok, state()}.
+init([Notify, Options]) ->
+ process_flag(trap_exit, true), %% need this to ensure terminate/2 is called
+
+ {ListenSocket, Listen} = maybe_listen(Options),
+ {Exec, Args} = command_line(Listen, Options),
+
+ Env = maps:get(env, Options, []),
+
+ %% close port if running detached
+ Conn =
+ case maps:find(connection, Options) of
+ {ok, standard_io} ->
+ %% Cannot detach a peer that uses stdio. Request exit_status.
+ open_port({spawn_executable, Exec}, [{args, Args}, {env, Env}, hide, binary, exit_status]);
+ _ ->
+ Port = open_port({spawn_executable, Exec}, [{args, Args}, {env, Env}, hide, binary]),
+ %% peer can close the port before we get here which will cause
+ %% port_close to throw. Catch this and ignore.
+ catch erlang:port_close(Port),
+ receive {'EXIT', Port, _} -> undefined end
+ end,
+
+ %% Remove the default 'halt' shutdown option if present; the default is
+ %% defined in terminate()...
+ SaveOptions = case maps:find(shutdown, Options) of
+ {ok, halt} ->
+ maps:remove(shutdown, Options);
+ _ ->
+ Options
+ end,
+
+ State = #peer_state{options = SaveOptions, notify = Notify, args = Args, exec = Exec},
+
+ %% accept TCP connection if requested
+ if ListenSocket =:= undefined ->
+ {ok, State#peer_state{connection = Conn}};
+ true ->
+ _ = prim_inet:async_accept(ListenSocket, ?ACCEPT_TIMEOUT),
+ {ok, State#peer_state{listen_socket = ListenSocket}}
+ end.
+
+%% not connected: no alternative connection available
+handle_call({call, _M, _F, _A}, _From, #peer_state{connection = undefined} = State) ->
+ {reply, {error, noconnection}, State};
+
+handle_call({call, M, F, A}, From,
+ #peer_state{connection = Port, options = #{connection := standard_io},
+ outstanding = Out, seq = Seq} = State) ->
+ origin_to_peer(port, Port, {call, Seq, M, F, A}),
+ {noreply, State#peer_state{outstanding = Out#{Seq => From}, seq = Seq + 1}};
+
+handle_call({call, M, F, A}, From,
+ #peer_state{connection = Socket, outstanding = Out, seq = Seq} = State) ->
+ origin_to_peer(tcp, Socket, {call, Seq, M, F, A}),
+ {noreply, State#peer_state{outstanding = Out#{Seq => From}, seq = Seq + 1}};
+
+handle_call(get_node, _From, #peer_state{node = Node} = State) ->
+ {reply, Node, State};
+
+handle_call(get_state, _From, #peer_state{peer_state = PeerState} = State) ->
+ {reply, PeerState, State};
+
+handle_call(group_leader, _From, State) ->
+ {reply, group_leader(), State}.
+
+handle_cast({cast, _M, _F, _A}, #peer_state{connection = undefined} = State) ->
+ {noreply, State};
+
+handle_cast({cast, M, F, A},
+ #peer_state{connection = Port, options = #{connection := standard_io}} = State) ->
+ origin_to_peer(port, Port, {cast, M, F, A}),
+ {noreply, State};
+
+handle_cast({cast, M, F, A}, #peer_state{connection = Socket} = State) ->
+ origin_to_peer(tcp, Socket, {cast, M, F, A}),
+ {noreply, State};
+
+handle_cast({send, _Dest, _Message}, #peer_state{connection = undefined} = State) ->
+ {noreply, State};
+
+handle_cast({send, Dest, Message},
+ #peer_state{connection = Port, options = #{connection := standard_io}} = State) ->
+ origin_to_peer(port, Port, {message, Dest, Message}),
+ {noreply, State};
+
+handle_cast({send, Dest, Message}, #peer_state{connection = Socket} = State) ->
+ origin_to_peer(tcp, Socket, {message, Dest, Message}),
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% alternative connections handling
+
+%% alternative communications - request or response from peer
+handle_info({tcp, Socket, SocketData}, #peer_state{connection = Socket} = State) ->
+ ok = inet:setopts(Socket, [{active, once}]),
+ {noreply, handle_alternative_data(tcp, binary_to_term(SocketData), State)};
+
+%% standard_io
+handle_info({Port, {data, PortData}}, #peer_state{connection = Port, stdio = PrevBin} = State) ->
+ {Str, NewBin} = decode_port_data(PortData, <<>>, PrevBin),
+ Str =/= <<>> andalso io:put_chars(Str),
+ {noreply, handle_port_binary(NewBin, State)};
+
+%% booting: accepted TCP connection from the peer, but it is not yet
+%% complete handshake
+handle_info({inet_async, LSock, _Ref, {ok, CliSocket}},
+ #peer_state{listen_socket = LSock} = State) ->
+ true = inet_db:register_socket(CliSocket, inet_tcp),
+ ok = inet:setopts(CliSocket, [{active, once}]),
+ catch gen_tcp:close(LSock),
+ {noreply, State#peer_state{connection = CliSocket, listen_socket = undefined}};
+
+handle_info({inet_async, LSock, _Ref, {error, Reason}},
+ #peer_state{listen_socket = LSock} = State) ->
+ %% failed to accept a TCP connection
+ catch gen_tcp:close(LSock),
+ %% stop unconditionally, it is essentially a part of gen_server:init callback
+ {stop, {inet_async, Reason}, State#peer_state{connection = undefined, listen_socket = undefined}};
+
+%% booting: peer notifies via Erlang distribution
+handle_info({started, Node}, State)->
+ true = erlang:monitor_node(Node, true),
+ {noreply, boot_complete(Node, started, State)};
+
+%% nodedown: no-alternative dist-connected peer node is down
+handle_info({nodedown, Node}, #peer_state{connection = undefined} = State) ->
+ maybe_stop({nodedown, Node}, State);
+
+%% external program exited, returned Status code
+handle_info({Port, {exit_status, Status}}, #peer_state{connection = Port} = State) ->
+ catch erlang:port_close(Port),
+ maybe_stop({exit_status, Status}, State);
+
+%% port terminated: cannot proceed, stop the server
+handle_info({'EXIT', Port, Reason}, #peer_state{connection = Port} = State) ->
+ catch erlang:port_close(Port),
+ maybe_stop(Reason, State);
+
+handle_info({tcp_closed, Sock}, #peer_state{connection = Sock} = State) ->
+ %% TCP connection closed, no i/o port - assume node is stopped
+ catch gen_tcp:close(Sock),
+ maybe_stop(tcp_closed, State#peer_state{connection = undefined}).
+
+%%--------------------------------------------------------------------
+%% cleanup/termination
+
+-spec terminate(Reason :: term(), state()) -> ok.
+terminate(_Reason, #peer_state{connection = Port, options = Options, node = Node}) ->
+ case {maps:get(shutdown, Options, {halt, ?DEFAULT_HALT_DISCONNECT_TIMEOUT}),
+ maps:find(connection, Options)} of
+ {close, {ok, standard_io}} ->
+ Port /= undefined andalso (catch erlang:port_close(Port));
+ {close, {ok, _TCP}} ->
+ Port /= undefined andalso (catch gen_tcp:close(Port));
+ {close, error} ->
+ _ = erlang:disconnect_node(Node);
+ {{halt, Timeout}, {ok, standard_io}} ->
+ Port /= undefined andalso (catch erlang:port_close(Port)),
+ wait_disconnected(Node, {timeout, Timeout});
+ {{halt, Timeout}, {ok, _TCP}} ->
+ Port /= undefined andalso (catch gen_tcp:close(Port)),
+ wait_disconnected(Node, {timeout, Timeout});
+ {{halt, Timeout}, error} ->
+ try
+ _ = erpc:call(Node, erlang, halt, [], Timeout),
+ ok
+ catch
+ error:{erpc,noconnection} -> ok;
+ _:_ -> force_disconnect_node(Node)
+ end;
+ {Shutdown, error} ->
+ Timeout = shutdown(dist, undefined, Node, Shutdown),
+ wait_disconnected(Node, {timeout, Timeout});
+ {Shutdown, {ok, standard_io}} ->
+ Timeout = shutdown(port, Port, Node, Shutdown),
+ Deadline = deadline(Timeout),
+ receive {'EXIT', Port, _Reason2} -> ok after Timeout -> ok end,
+ catch erlang:port_close(Port),
+ wait_disconnected(Node, Deadline);
+ {Shutdown, {ok, _TCP}} ->
+ Timeout = shutdown(tcp, Port, Node, Shutdown),
+ Deadline = deadline(Timeout),
+ receive {tcp_closed, Port} -> ok after Timeout -> ok end,
+ catch catch gen_tcp:close(Port),
+ wait_disconnected(Node, Deadline)
+ end,
+ ok.
+
+%%--------------------------------------------------------------------
+%% Internal implementation
+
+deadline(infinity) ->
+ {timeout, infinity};
+deadline(Timeout) when is_integer(Timeout) ->
+ {deadline, erlang:monotonic_time(millisecond) + Timeout}.
+
+wait_disconnected(Node, WaitUntil) ->
+ %% Should only be called just before we are exiting the caller, so
+ %% we do not bother disabling nodes monitoring if we enable it and
+ %% do not flush any nodeup/nodedown messages that we got due to the
+ %% nodes monitoring...
+ case lists:member(Node, nodes(connected)) of
+ false ->
+ ok;
+ true ->
+ _ = net_kernel:monitor_nodes(true, [{node_type, all}]),
+ %% Need to check connected nodes list again, since it
+ %% might have disconnected before we enabled nodes
+ %% monitoring...
+ case lists:member(Node, nodes(connected)) of
+ false ->
+ ok;
+ true ->
+ Tmo = case WaitUntil of
+ {timeout, T} ->
+ T;
+ {deadline, T} ->
+ TL = T - erlang:monotonic_time(millisecond),
+ if TL < 0 -> 0;
+ true -> TL
+ end
+ end,
+ receive {nodedown, Node, _} -> ok
+ after Tmo -> force_disconnect_node(Node)
+ end
+ end
+ end.
+
+force_disconnect_node(Node) ->
+ _ = erlang:disconnect_node(Node),
+ logger:warning("peer:stop() timed out waiting for disconnect from "
+ "node ~p. The connection was forcefully taken down.",
+ [Node]).
+
+%% This hack is a temporary workaround for test coverage reports
+shutdown(_Type, _Port, Node, Timeout) when is_integer(Timeout); Timeout =:= infinity ->
+ erpc:cast(Node, init, stop, []),
+ Timeout;
+shutdown(dist, undefined, Node, {Timeout, CoverNode}) when is_integer(Timeout); Timeout =:= infinity ->
+ rpc:call(CoverNode, cover, flush, [Node]),
+ erpc:cast(Node, init, stop, []),
+ Timeout;
+shutdown(Type, Port, Node, {Timeout, CoverNode}) when is_integer(Timeout); Timeout =:= infinity ->
+ rpc:call(CoverNode, cover, flush, [Node]),
+ Port /= undefined andalso origin_to_peer(Type, Port, {cast, init, stop, []}),
+ Timeout.
+
+%% Verify options correctness (Dialyzer also does the job, but slightly less convenient)
+verify_args(Options) ->
+ %% verify that "Args" is valid - common problem is when Args aren't strings
+ Args = maps:get(args, Options, []),
+ is_list(Args) orelse error({invalid_arg, Args}),
+ [error({invalid_arg, Arg}) || Arg <- Args, not io_lib:char_list(Arg)],
+ %% alternative connection must be requested for non-distributed node,
+ %% or a distributed node when origin is not alive
+ is_map_key(connection, Options) orelse
+ (is_map_key(name, Options) andalso erlang:is_alive()) orelse error(not_alive),
+ %% exec must be a string, or a tuple of string(), [string()]
+ case maps:find(exec, Options) of
+ {ok, {Exec, Strs}} ->
+ io_lib:char_list(Exec) orelse error({exec, Exec}),
+ [error({exec, Str}) || Str <- Strs, not io_lib:char_list(Str)],
+ ok;
+ {ok, Exec} when is_list(Exec) ->
+ io_lib:char_list(Exec) orelse error({exec, Exec}),
+ ok;
+ error ->
+ ok;
+ {ok, Err} ->
+ error({exec, Err})
+ end,
+ case maps:find(shutdown, Options) of
+ {ok, close} ->
+ ok;
+ {ok, halt} ->
+ ok;
+ {ok, {halt, Tmo}} when (is_integer(Tmo)
+ andalso ?MIN_DISCONNECT_TIMEOUT =< Tmo
+ andalso Tmo =< ?MAX_INT_TIMEOUT)
+ orelse Tmo == infinity ->
+ ok;
+ {ok, Tmo} when (is_integer(Tmo)
+ andalso ?MIN_DISCONNECT_TIMEOUT =< Tmo
+ andalso Tmo =< ?MAX_INT_TIMEOUT)
+ orelse Tmo == infinity ->
+ ok;
+ {ok, {Tmo, Node}} when ((is_integer(Tmo)
+ andalso ?MIN_DISCONNECT_TIMEOUT =< Tmo
+ andalso Tmo =< ?MAX_INT_TIMEOUT)
+ orelse Tmo == infinity)
+ andalso is_atom(Node) ->
+ ok;
+ error ->
+ ok;
+ {ok, Err2} ->
+ error({shutdown, Err2})
+ end.
+
+
+make_notify_ref(infinity) ->
+ {self(), make_ref()};
+make_notify_ref(WaitBoot) when is_integer(WaitBoot) ->
+ {self(), make_ref()};
+make_notify_ref({ReplyTo, Tag}) when is_pid(ReplyTo) ->
+ {ReplyTo, Tag};
+make_notify_ref(false) ->
+ false.
+
+start_it(Options, StartFun) ->
+ verify_args(Options),
+ WaitBoot = maps:get(wait_boot, Options, ?WAIT_BOOT_TIMEOUT),
+ Notify = make_notify_ref(WaitBoot),
+ case gen_server:StartFun(?MODULE, [Notify, Options], []) of
+ {ok, Pid} when WaitBoot =:= infinity; is_integer(WaitBoot) ->
+ {_, Ref} = Notify,
+ Mref = erlang:monitor(process, Pid),
+ receive
+ {Ref, {started, NodeName, Pid}} ->
+ erlang:demonitor(Mref, [flush]),
+ {ok, Pid, NodeName};
+ {Ref, {boot_failed, Reason, Pid}} ->
+ erlang:demonitor(Mref, [flush]),
+ erlang:exit({boot_failed, Reason});
+ {'DOWN', Mref, _, _, Reason} ->
+ erlang:exit(Reason)
+ after
+ WaitBoot ->
+ _ = gen_server:stop(Pid),
+ erlang:demonitor(Mref, [flush]),
+ erlang:exit(timeout)
+ end;
+ {ok, Pid} when is_map_key(host, Options) ->
+ {ok, Pid, node_name(Options)};
+ {ok, Pid} ->
+ {ok, Pid};
+ Error ->
+ Error
+ end.
+
+node_name(#{name := Name, host := Host}) ->
+ list_to_atom(lists:concat([Name, "@", Host]));
+node_name(_Options) ->
+ undefined.
+
+%% Lost control connection to the peer while the node was
+%% booting, this generally means a crash
+maybe_stop(Reason, #peer_state{peer_state = booting} = State) ->
+ _ = boot_complete(Reason, boot_failed, State),
+ maybe_stop(Reason, State#peer_state{peer_state = {down, Reason}});
+%%
+maybe_stop(Reason, #peer_state{options = #{peer_down := crash}} = State) ->
+ {stop, Reason, State#peer_state{peer_state = {down, Reason}, connection = undefined}};
+%% if state was already down, keep the original reason
+maybe_stop(_Reason, #peer_state{options = #{peer_down := continue}, peer_state = {down, _}} = State) ->
+ {noreply, State};
+%% continue working setting peer state to down
+maybe_stop(Reason, #peer_state{options = #{peer_down := continue}} = State) ->
+ {noreply, State#peer_state{peer_state = {down, Reason}}};
+%% default: ignore Reason and shut down normally
+maybe_stop(Reason, State) ->
+ {stop, normal, State#peer_state{peer_state = {down, Reason}}}.
+
+%% i/o protocol from origin:
+%% * {io_reply, ...}
+%% * {message, To, Content}
+%% * {call, From, M, F, A}
+%%
+%% i/o port protocol, from peer:
+%% * {io_request, From, ReplyAs, Request}
+%% * {message, To, Content}
+%% * {reply, From, ok | throw | error | exit | crash, Result | {Reason, Stack}}
+
+%% Handles bytes coming from alternative connection, forwarding as needed.
+handle_alternative_data(Kind, {io_request, From, FromRef, IoReq}, #peer_state{connection = Conn} = State) ->
+ %% TODO: make i/o completely async
+ Reply = {io_reply, From, FromRef, forward_request(IoReq)},
+ origin_to_peer(Kind, Conn, Reply),
+ State;
+handle_alternative_data(_Kind, {message, To, Content}, State) ->
+ To ! Content,
+ State;
+handle_alternative_data(_Kind, {reply, Seq, Class, Result}, #peer_state{outstanding = Out} = State) ->
+ {From, NewOut} = maps:take(Seq, Out),
+ gen:reply(From, {Class, Result}),
+ State#peer_state{outstanding = NewOut};
+handle_alternative_data(_Kind, {started, NodeName}, State)->
+ boot_complete(NodeName, started, State).
+
+forward_request(Req) ->
+ GL = group_leader(),
+ MRef = erlang:monitor(process, GL),
+ GL ! {io_request,self(), MRef, Req},
+ receive
+ {io_reply, MRef, Reply} ->
+ erlang:demonitor(MRef, [flush]),
+ Reply;
+ {'DOWN', MRef, _, _, _} ->
+ {error, terminated}
+ end.
+
+%% generic primitive to send data from origin to peer via alternative connection
+origin_to_peer(tcp, Sock, Term) ->
+ ok = gen_tcp:send(Sock, term_to_binary(Term));
+origin_to_peer(port, Port, Term) ->
+ true = erlang:port_command(Port, encode_port_data(term_to_binary(Term))).
+
+%% generic primitive to send data from peer to origin
+peer_to_origin(tcp, Sock, Term) ->
+ ok = gen_tcp:send(Sock, term_to_binary(Term));
+peer_to_origin(port, Port, Term) ->
+ %% converts Erlang term to terminal codes
+ %% Every binary byte is converted into two 4-bit sequences.
+ Bytes = term_to_binary(Term),
+ true = erlang:port_command(Port, encode_port_data(Bytes)).
+
+%% convert/escape Erlang term into terminal codes.
+%% Protocol consists of Erlang terms serialised into
+%% External Term Format (ETF) via term_to_binary. Then
+%% every byte of the resulting binary is split into two
+%% nibbles (4-bit sequences), which are encoded into two
+%% characters.
+%% Control characters must have first two and last two bits
+%% set, so the byte looks this way: 11xxxx11.
+%% Example encoding, hexadecimal 16#0F will be encoded as
+%% 11000011 11111111 (decimal 195 255).
+encode_port_data(Bytes) ->
+ Size = byte_size(Bytes),
+ Crc = erlang:crc32(Bytes),
+ Total = <<Size:32, Bytes/binary, Crc:32>>,
+ <<<<3:2, Upper:4, 3:2, 3:2, Lower:4, 3:2>> || <<Upper:4, Lower:4>> <= Total>>.
+
+%% convert terminal codes to Erlang term, printing everything that
+%% was detected as text
+decode_port_data(<<>>, Str, Bin) ->
+ {Str, Bin};
+decode_port_data(<<3:2, Quad:4, 3:2, Rest/binary>>, Str, Bin) ->
+ decode_port_data(Rest, Str, <<Bin/bitstring, Quad:4>>);
+decode_port_data(<<Char:8, Rest/binary>>, Str, Bin) ->
+ decode_port_data(Rest, <<Str/binary, Char>>, Bin).
+
+%% recursively process buffers, potentially changing the state
+handle_port_binary(<<Size:32, Payload:Size/binary, Crc:32, Rest/binary>>, State) ->
+ Crc = erlang:crc32(Payload),
+ Term = binary_to_term(Payload),
+ NewState = handle_alternative_data(port, Term, State),
+ handle_port_binary(Rest, NewState);
+handle_port_binary(NewBin, State) ->
+ State#peer_state{stdio = NewBin}.
+
+boot_complete(Node, _Result, #peer_state{notify = false} = State) ->
+ State#peer_state{peer_state = running, node = Node};
+boot_complete(Node, Result, #peer_state{notify = {ReplyTo, Tag}} = State) ->
+ ReplyTo ! {Tag, {Result, Node, self()}},
+ State#peer_state{peer_state = running, node = Node}.
+
+%% check if TCP connection is enabled, and starts listener
+maybe_listen(#{connection := Port}) when is_integer(Port) ->
+ {ok, LSock} = gen_tcp:listen(Port, [binary, {reuseaddr, true}, {packet, 4}]),
+ {ok, WaitPort} = inet:port(LSock),
+ %% try guessing a local IP address
+ {ok, Ifs} = inet:getifaddrs(),
+ %% next incantation gets all IP addresses of all local interfaces that are up
+ LocalUp = lists:append(
+ [proplists:get_all_values(addr, Opts)
+ || {_, Opts} <- Ifs, lists:member(up, proplists:get_value(flags, Opts, []))]),
+ %% filter invalid addresses
+ Local = prefer_localhost([Valid || Valid <- LocalUp, is_list(inet:ntoa(Valid))], [], []),
+ {LSock, {Local, WaitPort}};
+maybe_listen(#{connection := {Ip, Port}}) when is_integer(Port) ->
+ {ok, LSock} = gen_tcp:listen(Port, [binary, {reuseaddr, true}, {packet, 4}, {ip, Ip}]),
+ WaitPort = if Port =:= 0 -> {ok, Dyn} = inet:port(LSock), Dyn; true -> Port end,
+ {LSock, {[Ip], WaitPort}};
+maybe_listen(_Options) ->
+ {undefined, undefined}.
+
+%% prefer localhost, IPv6 localhost, then everything else
+prefer_localhost([], Preferred, Other) ->
+ Preferred ++ Other;
+prefer_localhost([{127, _, _, _} = Local | Tail], Preferred, Other) ->
+ prefer_localhost(Tail, [Local | Preferred], Other);
+prefer_localhost([{0, 0, 0, 0, 0, 0, 0, 1} = Local | Tail], Preferred, Other) ->
+ prefer_localhost(Tail, [Local | Preferred], Other);
+prefer_localhost([Local | Tail], Preferred, Other) ->
+ prefer_localhost(Tail, Preferred, [Local | Other]).
+
+name_arg(error, error, _) ->
+ []; %% no name, no host - starting node that is not distributed
+name_arg(error, {ok, Host}, LongOrShort) ->
+ %% interesting fallback: host is set, name is not. Do what predecessor did,
+ %% take the current node name and use it...
+ [Name, _] = string:lexemes(atom_to_list(node()), "@"),
+ name_arg(Name ++ "@" ++ Host, error, LongOrShort);
+name_arg({ok, Name}, Host, LongOrShort) ->
+ name_arg(Name, Host, LongOrShort); %% unpack node name
+name_arg(Name, Host, LongOrShort) when is_atom(Name) ->
+ name_arg(atom_to_list(Name), Host, LongOrShort); %% convert atom to list for command line
+name_arg(Name, Host, {ok, ignored}) ->
+ name_arg(Name, Host, {ok, false}); %% fallback to shortnames when origin is not distributed
+name_arg(Name, Host, error) ->
+ name_arg(Name, Host, {ok, net_kernel:longnames()}); %% no longnames present it start options
+name_arg(Name, {ok, Host}, LongOrShort) ->
+ name_arg(Name ++ "@" ++ Host, error, LongOrShort); %% merge host part
+%% only these are actual name creation clauses
+name_arg(Name, error, {ok, true}) ->
+ ["-name", Name];
+name_arg(Name, error, {ok, false}) ->
+ ["-sname", Name].
+
+command_line(Listen, Options) ->
+ %% Node name/sname
+ NameArg = name_arg(maps:find(name, Options), maps:find(host, Options), maps:find(longnames, Options)),
+ %% additional command line args
+ CmdOpts = maps:get(args, Options, []),
+ %% start command
+ StartCmd =
+ case Listen of
+ undefined when map_get(connection, Options) =:= standard_io ->
+ ["-user", atom_to_list(?MODULE)];
+ undefined ->
+ Self = base64:encode_to_string(term_to_binary(self())),
+ ["-detached", "-noinput", "-user", atom_to_list(?MODULE), "-origin", Self];
+ {Ips, Port} ->
+ IpStr = lists:concat(lists:join(",", [inet:ntoa(Ip) || Ip <- Ips])),
+ ["-detached", "-noinput", "-user", atom_to_list(?MODULE), "-origin", IpStr, integer_to_list(Port)]
+ end,
+ %% build command line
+ {Exec, PreArgs} = exec(Options),
+ {Exec, PreArgs ++ NameArg ++ StartCmd ++ CmdOpts}.
+
+exec(#{exec := Prog}) when is_list(Prog) ->
+ {Prog, []};
+exec(#{exec := {Prog, Args}}) when is_list(Prog), is_list(Args) ->
+ {Prog, Args};
+exec(Options) when not is_map_key(exec, Options) ->
+ case init:get_argument(progname) of
+ {ok, [[Prog]]} ->
+ case os:find_executable(Prog) of
+ Exec when is_list(Exec) ->
+ {Exec, []};
+ false ->
+ maybe_otp_test_suite(Prog)
+ end;
+ _ ->
+ default_erts()
+ end.
+
+maybe_otp_test_suite(Prog) ->
+ case string:split(Prog, "cerl ") of
+ [CerlPath, Args] ->
+ %% This is a hack to handle the 'cerl' script used
+ %% by the Erlang/OTP test suites. When 'cerl'
+ %% starts the runtime system, it typically sets
+ %% 'progname' to the path of the 'cerl' script,
+ %% followed by an argument. For example:
+ %%
+ %% /<full_path_to>/cerl -debug
+ %% /<full_path_to>/cerl -asan
+ %% /<full_path_to>/cerl -gcov
+ %%
+ %% We should find a better way to handle this, for
+ %% example by passing the emulator type and flavor
+ %% using the '-emu_type' and '-emu_flavor'
+ %% options. However, this is not without
+ %% complications as those options do not really
+ %% work for an installed system. Also, it is
+ %% probably a good idea to stop using 'slave'
+ %% before attempting to do this.
+ {filename:join(CerlPath, "cerl"), parse_args(Args)};
+ _ ->
+ default_erts()
+ end.
+
+
+%% Split command line string into a list of arguments.
+-spec parse_args(string()) -> [string()].
+parse_args([]) ->
+ [];
+parse_args([Deep | _] = AlreadyParsed) when is_list(Deep) ->
+ AlreadyParsed;
+parse_args(CmdLine) ->
+ %% following regex splits command line, preserving quoted arguments, into argv[] list
+ Re = <<"((?:\"[^\"\\\\]*(?:\\\\[\\S\\s][^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\[\\S\\s][^'\\\\]*)*'|\\/[^\\/\\\\]*(?:\\\\[\\S\\s][^\\/\\\\]*)*\\/[gimy]*(?=\\s|$)|(?:\\\\\\s|\\S))+)(?=\\s|$)">>,
+ {match, Args} = re:run(CmdLine, Re, [{capture, all_but_first, list}, global]),
+ %% unquote arguments. It is possible to change regex capture groups to avoid extra processing.
+ [unquote(Arg) || [Arg] <- Args].
+
+unquote([Q | Arg]) when Q =:= $\"; Q =:= $\' ->
+ case lists:last(Arg) of
+ Q -> lists:droplast(Arg);
+ _ -> [Q | Arg]
+ end;
+ unquote(Arg) ->
+ Arg.
+
+%% if progname is not known, use `erlexec` from the same ERTS version we're currently running
+%% BINDIR environment variable is already set
+%% EMU variable it also set
+default_erts() ->
+ Root = code:root_dir(),
+ Erts = filename:join(Root, lists:concat(["erts-", erlang:system_info(version)])),
+ BinDir = filename:join(Erts, "bin"),
+ {filename:join(BinDir, "erlexec"), []}.
+
+%%--------------------------------------------------------------------
+%% peer node implementation
+
+notify_when_started(Kind, Port) ->
+ init:notify_when_started(self()) =:= started andalso
+ notify_started(Kind, Port),
+ ok.
+
+notify_started(dist, Process) ->
+ Process ! {started, node()},
+ ok;
+notify_started(Kind, Port) ->
+ peer_to_origin(Kind, Port, {started, node()}).
+
+%%
+%% Supervision of peer user process (which supervise the control channel) making
+%% sure that the peer node is halted if the peer user process crashes...
+%%
+
+supervision_child_spec() ->
+ case init:get_argument(user) of
+ {ok, [["peer"]]} ->
+ {ok, #{id => peer_supervision,
+ start => {?MODULE, start_supervision, []},
+ restart => permanent,
+ shutdown => 1000,
+ type => worker,
+ modules => [?MODULE]}};
+ _ ->
+ none
+ end.
+
+start_supervision() ->
+ proc_lib:start_link(?MODULE, init_supervision, [self(), true]).
+
+start_orphan_supervision() ->
+ proc_lib:start(?MODULE, init_supervision, [self(), false]).
+
+-record(peer_sup_state, {parent, channel, in_sup_tree}).
+
+-spec init_supervision(term(), term()) -> no_return().
+init_supervision(Parent, InSupTree) ->
+ try
+ process_flag(priority, high),
+ process_flag(trap_exit, true),
+ register(peer_supervision, self()),
+ proc_lib:init_ack(Parent, {ok, self()}),
+ Channel = receive
+ {channel_connect, Ref, From, ConnectChannel} ->
+ true = is_pid(ConnectChannel),
+ From ! Ref,
+ try
+ link(ConnectChannel)
+ catch error:noproc ->
+ exit({peer_channel_terminated, noproc})
+ end,
+ ConnectChannel
+ after
+ ?PEER_SUP_CHANNEL_CONNECT_TIMEOUT ->
+ exit(peer_channel_connect_timeout)
+ end,
+ loop_supervision(#peer_sup_state{parent = Parent,
+ channel = Channel,
+ in_sup_tree = InSupTree})
+ catch
+ _:_ when not InSupTree ->
+ erlang:halt(1)
+ end.
+
+peer_sup_connect_channel(PeerSupervision, PeerChannelHandler) ->
+ Ref = make_ref(),
+ PeerSupervision ! {channel_connect, Ref, self(), PeerChannelHandler},
+ receive
+ Ref -> ok
+ after
+ ?PEER_SUP_CHANNEL_CONNECT_TIMEOUT ->
+ exit(peer_supervision_connect_timeout)
+ end.
+
+loop_supervision(#peer_sup_state{parent = Parent,
+ channel = Channel} = State) ->
+ receive
+ {'EXIT', Channel, Reason} ->
+ exit({peer_channel_terminated, Reason});
+ {system, From, Request} ->
+ sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State);
+ _ ->
+ loop_supervision(State)
+ end.
+
+
+system_continue(_Parent, _, #peer_sup_state{} = State) ->
+ loop_supervision(State).
+
+system_terminate(Reason, _Parent, _Debug, _State) ->
+ exit(Reason).
+
+system_code_change(State, _Module, _OldVsn, _Extra) ->
+ {ok, State}.
+
+system_get_state(State) ->
+ {ok, State}.
+
+system_replace_state(StateFun, State) ->
+ NState = StateFun(State),
+ {ok, NState, NState}.
+
+%% End of peer user supervision
+
+%% I/O redirection: peer side
+-spec start() -> pid().
+start() ->
+ try
+ PeerChannelHandler = start_peer_channel_handler(),
+ PeerSup = case whereis(peer_supervision) of
+ PeerSup0 when is_pid(PeerSup0) ->
+ PeerSup0;
+ undefined ->
+ {ok, PeerSup0} = start_orphan_supervision(),
+ PeerSup0
+ end,
+ peer_sup_connect_channel(PeerSup, PeerChannelHandler),
+ PeerChannelHandler
+ catch _:_ ->
+ erlang:halt(1)
+ end.
+
+start_peer_channel_handler() ->
+ case init:get_argument(origin) of
+ {ok, [[IpStr, PortString]]} ->
+ %% enter this clause when -origin IpList Port is specified in the command line.
+ Port = list_to_integer(PortString),
+ Ips = [begin {ok, Addr} = inet:parse_address(Ip), Addr end || Ip <- string:lexemes(IpStr, ",")],
+ spawn(fun () -> tcp_init(Ips, Port) end);
+ {ok, [[Base64EncProc]]} ->
+ %% No alternative connection, but have "-origin Base64EncProc"
+ OriginProcess = binary_to_term(base64:decode(Base64EncProc)),
+ %% setup 'user' process, I/O redirection: ask controlling process
+ %% who is the group leader.
+ GroupLeader = gen_server:call(OriginProcess, group_leader),
+ RelayPid = spawn(fun () -> relay(GroupLeader) end),
+ register(user, RelayPid),
+ spawn(
+ fun () ->
+ link(RelayPid),
+ MRef = monitor(process, OriginProcess),
+ notify_when_started(dist, OriginProcess),
+ origin_link(MRef, OriginProcess)
+ end);
+ error ->
+ %% no -origin specified, meaning that standard I/O is used for alternative
+ spawn(fun io_server/0)
+ end.
+
+relay(GroupLeader) ->
+ receive
+ IO ->
+ GroupLeader ! IO,
+ relay(GroupLeader)
+ end.
+
+origin_link(MRef, Origin) ->
+ receive
+ {'DOWN', MRef, process, Origin, _Reason} ->
+ erlang:halt();
+ {init, started} ->
+ notify_started(dist, Origin),
+ origin_link(MRef, Origin)
+ end.
+
+-spec io_server() -> no_return().
+io_server() ->
+ try
+ process_flag(trap_exit, true),
+ Port = erlang:open_port({fd, 0, 1}, [eof, binary]),
+ register(user, self()),
+ group_leader(self(), self()),
+ notify_when_started(port, Port),
+ io_server_loop(port, Port, #{}, #{}, <<>>)
+ catch
+ _:_ ->
+ erlang:halt(1)
+ end.
+
+-spec tcp_init([term()], term()) -> no_return().
+tcp_init(IpList, Port) ->
+ try
+ Sock = loop_connect(IpList, Port),
+ register(user, self()),
+ erlang:group_leader(self(), self()),
+ notify_when_started(tcp, Sock),
+ io_server_loop(tcp, Sock, #{}, #{}, undefined)
+ catch
+ _:_ ->
+ erlang:halt(1)
+ end.
+
+loop_connect([], _Port) ->
+ error(noconnection);
+loop_connect([Ip | More], Port) ->
+ case gen_tcp:connect(Ip, Port, [binary, {packet, 4}], ?CONNECT_TIMEOUT) of
+ {ok, Sock} ->
+ Sock;
+ _Error ->
+ loop_connect(More, Port)
+ end.
+
+%% Message protocol between peers
+io_server_loop(Kind, Port, Refs, Out, PortBuf) ->
+ receive
+ {io_request, From, ReplyAs, Request} when is_pid(From) ->
+ %% i/o request from this node, forward it to origin
+ peer_to_origin(Kind, Port, {io_request, From, ReplyAs, Request}),
+ io_server_loop(Kind, Port, Refs, Out, PortBuf);
+ {Port, {data, Bytes}} when Kind =:= port ->
+ {_Str, NewBin} = decode_port_data(Bytes, <<>>, PortBuf),
+ {NewRefs, NewOut, NewBuf} = handle_port_alternative(NewBin, Refs, Out),
+ io_server_loop(Kind, Port, NewRefs, NewOut, NewBuf);
+ {Port, eof} when Kind =:= port ->
+ %% stdin closed, if there is no active alternative, stop the node
+ erlang:halt(1);
+ {'EXIT', Port, badsig} when Kind =:= port ->
+ %% ignore badsig (what is it?)
+ io_server_loop(Kind, Port, Refs, Out, PortBuf);
+ {'EXIT', Port, _Reason} when Kind =:= port ->
+ %% stdin closed, if there is no active alternative, stop the node
+ erlang:halt(1);
+ {tcp, Port, Data} when Kind =:= tcp ->
+ ok = inet:setopts(Port, [{active, once}]), %% flow control
+ {NewRefs, NewOut} = handle_peer_alternative(binary_to_term(Data), Refs, Out),
+ io_server_loop(Kind, Port, NewRefs, NewOut, PortBuf);
+ {tcp_closed, Port} when Kind =:= tcp ->
+ %% TCP connection closed, time to shut down
+ erlang:halt(1);
+ {reply, Seq, Class, Reply} when is_integer(Seq), is_map_key(Seq, Out) ->
+ %% stdin/stdout RPC
+ {CallerRef, Out2} = maps:take(Seq, Out),
+ Refs2 = maps:remove(CallerRef, Refs),
+ erlang:demonitor(CallerRef, [flush]),
+ peer_to_origin(Kind, Port, {reply, Seq, Class, Reply}),
+ io_server_loop(Kind, Port, Refs2, Out2, PortBuf);
+ %% stdin/stdout message forwarding
+ {message, To, Content} ->
+ peer_to_origin(Kind, Port, {message, To, Content}),
+ io_server_loop(Kind, Port, Refs, Out, PortBuf);
+ {'DOWN', CallerRef, _, _, Reason} ->
+ %% this is really not expected to happen, because "do_call"
+ %% catches all exceptions
+ {Seq, Refs3} = maps:take(CallerRef, Refs),
+ {CallerRef, Out3} = maps:take(Seq, Out),
+ peer_to_origin(Kind, Port, {reply, Seq, crash, Reason}),
+ io_server_loop(Kind, Port, Refs3, Out3, PortBuf);
+ {init, started} ->
+ notify_started(Kind, Port),
+ io_server_loop(Kind, Port, Refs, Out, PortBuf);
+ _Other ->
+ %% below, what is it?
+ io_server_loop(Kind, Port, Refs, Out, PortBuf)
+ end.
+
+handle_peer_alternative({io_reply, From, FromRef, Reply}, Refs, Out) ->
+ From ! {io_reply, FromRef, Reply},
+ {Refs, Out};
+handle_peer_alternative({call, Seq, M, F, A}, Refs, Out) ->
+ CallerRef = do_call(Seq, M, F, A),
+ {Refs#{CallerRef => Seq}, Out#{Seq => CallerRef}};
+handle_peer_alternative({cast, M, F, A}, Refs, Out) ->
+ %% spawn a separate process to avoid blocking further RPC
+ spawn(fun () -> erlang:apply(M, F, A) end),
+ {Refs, Out};
+handle_peer_alternative({message, Dest, Message}, Refs, Out) ->
+ Dest ! Message,
+ {Refs, Out}.
+
+%% single port input message may contain multiple messages
+handle_port_alternative(<<Size:32, Payload:Size/binary, Crc:32, Rest/binary>>, Refs, Out) ->
+ Crc = erlang:crc32(Payload), %% assert
+ {NewRefs, NewOut} = handle_peer_alternative(binary_to_term(Payload), Refs, Out),
+ handle_port_alternative(Rest, NewRefs, NewOut);
+handle_port_alternative(Rest, Refs, Out) ->
+ {Refs, Out, Rest}.
+
+do_call(Seq, M, F, A) ->
+ Proxy = self(),
+ {_, CallerRef} =
+ spawn_monitor(
+ fun () ->
+ %% catch all errors, otherwise emulator will log
+ %% ERROR REPORT when it is not expected
+ try
+ Proxy ! {reply, Seq, ok, erlang:apply(M, F, A)}
+ catch
+ Class:Reason:Stack ->
+ Proxy ! {reply, Seq, Class, {Reason, Stack}}
+ end
+ end),
+ CallerRef.
diff --git a/lib/stdlib/src/pool.erl b/lib/stdlib/src/pool.erl
index 39f9cb2f4c..e0fb9b6dfb 100644
--- a/lib/stdlib/src/pool.erl
+++ b/lib/stdlib/src/pool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -103,6 +103,8 @@ pspawn(M, F, A) ->
pspawn_link(M, F, A) ->
spawn_link(get_node(), M, F, A).
+-compile([{nowarn_deprecated_function,[{slave,start,3}]}]).
+
start_nodes([], _, _) -> [];
start_nodes([Host|Tail], Name, Args) ->
case slave:start(Host, Name, Args) of
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index 66438ef224..a95d75b9f6 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,13 +46,33 @@
%%-----------------------------------------------------------------------------
+%% This shall be spawn_option() -- monitor options and must be kept in sync
+%% (with erlang:spawn_opt_options())
+%%
-type start_spawn_option() :: 'link'
| {'priority', erlang:priority_level()}
- | {'max_heap_size', erlang:max_heap_size()}
+ | {'fullsweep_after', non_neg_integer()}
| {'min_heap_size', non_neg_integer()}
| {'min_bin_vheap_size', non_neg_integer()}
- | {'fullsweep_after', non_neg_integer()}
+ | {'max_heap_size', erlang:max_heap_size()}
| {'message_queue_data', erlang:message_queue_data() }.
+%% and this macro is used to verify that there are no monitor options
+%% which also needs to be kept in sync all kinds of monitor options
+%% in erlang:spawn_opt_options().
+%%
+-define(VERIFY_NO_MONITOR_OPT(M, F, A, T, Opts),
+ Monitor = monitor,
+ case lists:member(Monitor, Opts) of
+ true ->
+ erlang:error(badarg, [M,F,A,T,Opts]);
+ false ->
+ case lists:keyfind(Monitor, 1, Opts) of
+ false ->
+ ok;
+ {Monitor, _} ->
+ erlang:error(badarg, [M,F,A,T,Opts])
+ end
+ end).
-type spawn_option() :: erlang:spawn_opt_option().
@@ -62,12 +82,6 @@
%%-----------------------------------------------------------------------------
--define(VERIFY_NO_MONITOR_OPT(M, F, A, T, Opts),
- case lists:member(monitor, Opts) of
- true -> erlang:error(badarg, [M,F,A,T,Opts]);
- false -> ok
- end).
-
%%-----------------------------------------------------------------------------
-spec spawn(Fun) -> pid() when
@@ -1062,33 +1076,32 @@ stop(Process) ->
Reason :: term(),
Timeout :: timeout().
stop(Process, Reason, Timeout) ->
- {Pid, Mref} = erlang:spawn_monitor(do_stop(Process, Reason)),
+ Mref = erlang:monitor(process, Process),
+ T0 = erlang:monotonic_time(millisecond),
+ RemainingTimeout = try
+ sys:terminate(Process, Reason, Timeout)
+ of
+ ok when Timeout =:= infinity ->
+ infinity;
+ ok ->
+ Timeout - (((erlang:monotonic_time(microsecond) + 999) div 1000) - T0)
+ catch
+ exit:{noproc, {sys, terminate, _}} ->
+ demonitor(Mref, [flush]),
+ exit(noproc);
+ exit:{timeout, {sys, terminate, _}} ->
+ demonitor(Mref, [flush]),
+ exit(timeout);
+ exit:Reason1 ->
+ demonitor(Mref, [flush]),
+ exit(Reason1)
+ end,
receive
{'DOWN', Mref, _, _, Reason} ->
ok;
- {'DOWN', Mref, _, _, {noproc,{sys,terminate,_}}} ->
- exit(noproc);
- {'DOWN', Mref, _, _, CrashReason} ->
- exit(CrashReason)
- after Timeout ->
- exit(Pid, kill),
- receive
- {'DOWN', Mref, _, _, _} ->
- exit(timeout)
- end
- end.
-
--spec do_stop(Process, Reason) -> Fun when
- Process :: pid() | RegName | {RegName,node()},
- RegName :: atom(),
- Reason :: term(),
- Fun :: fun(() -> no_return()).
-do_stop(Process, Reason) ->
- fun() ->
- Mref = erlang:monitor(process, Process),
- ok = sys:terminate(Process, Reason, infinity),
- receive
- {'DOWN', Mref, _, _, ExitReason} ->
- exit(ExitReason)
- end
+ {'DOWN', Mref, _, _, Reason2} ->
+ exit(Reason2)
+ after RemainingTimeout ->
+ demonitor(Mref, [flush]),
+ exit(timeout)
end.
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index 0b1d6c467e..cc4a988552 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -652,21 +652,20 @@ string_to_handle(Str, Options, Bindings) when is_list(Str) ->
{ok, Tokens, _} ->
ScanRes =
case erl_eval:extended_parse_exprs(Tokens) of
- {ok, [Expr0], SBs} ->
- {ok, Expr0, SBs};
- {ok, _ExprList, _SBs} ->
+ {ok, [Expr0]} ->
+ {ok, Expr0};
+ {ok, _ExprList} ->
erlang:error(badarg,
[Str, Options, Bindings]);
E ->
E
end,
case ScanRes of
- {ok, Expr, XBs} ->
- Bs1 = merge_binding_structs(Bindings, XBs),
- case qlc_pt:transform_expression(Expr, Bs1) of
+ {ok, Expr} ->
+ case qlc_pt:transform_expression(Expr, Bindings) of
{ok, {call, _, _QlcQ, Handle}} ->
{value, QLC_lc, _} =
- erl_eval:exprs(Handle, Bs1),
+ erl_eval:exprs(Handle, Bindings),
O = #qlc_opt{unique = Unique,
cache = Cache,
max_lookup = MaxLookup,
@@ -792,10 +791,6 @@ all_selections([{I,Cs} | ICs]) ->
%%% Local functions
%%%
-merge_binding_structs(Bs1, Bs2) ->
- lists:foldl(fun({N, V}, Bs) -> erl_eval:add_binding(N, V, Bs)
- end, Bs1, erl_eval:bindings(Bs2)).
-
aux_name1(Name, N, AllNames) ->
SN = name_suffix(Name, N),
case gb_sets:is_member(SN, AllNames) of
@@ -1208,9 +1203,7 @@ abstract1({table, TableDesc}, _NElements, _Depth, _A) ->
true ->
{ok, Tokens, _} =
erl_scan:string(lists:flatten(TableDesc++"."), 1, [text]),
- {ok, Es, Bs} =
- erl_eval:extended_parse_exprs(Tokens),
- [Expr] = erl_eval:subst_values_for_vars(Es, Bs),
+ {ok, [Expr]} = erl_eval:extended_parse_exprs(Tokens),
special(Expr);
false -> % abstract expression
TableDesc
diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl
index 67ea0f8be4..a71121ad2d 100644
--- a/lib/stdlib/src/queue.erl
+++ b/lib/stdlib/src/queue.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -703,11 +703,11 @@ r2f([]) ->
{[],[]};
r2f([_]=R) ->
{[],R};
-r2f([X,Y]) ->
- {[X],[Y]};
+r2f([Y,X]) ->
+ {[Y],[X]};
r2f(List) ->
- {FF,RR} = lists:split(length(List) div 2 + 1, List),
- {FF,lists:reverse(RR, [])}.
+ {RR,FF} = lists:split(length(List) div 2, List),
+ {RR,lists:reverse(FF, [])}.
%% Move half of elements from F to R, if there are enough
f2r([]) ->
@@ -717,5 +717,5 @@ f2r([_]=F) ->
f2r([X,Y]) ->
{[Y],[X]};
f2r(List) ->
- {FF,RR} = lists:split(length(List) div 2 + 1, List),
+ {FF,RR} = lists:split(length(List) div 2, List),
{lists:reverse(RR, []),FF}.
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index d5906d3730..5f8d3a4c59 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,6 +36,11 @@
normal/0, normal/2, normal_s/1, normal_s/3
]).
+%% Utilities
+-export([exsp_next/1, exsp_jump/1, splitmix64_next/1,
+ mwc59/1, mwc59_value32/1, mwc59_value/1, mwc59_float/1,
+ mwc59_seed/0, mwc59_seed/1]).
+
%% Test, dev and internal
-export([exro928_jump_2pow512/1, exro928_jump_2pow20/1,
exro928_seed/1, exro928_next/1, exro928_next_state/1,
@@ -44,10 +49,11 @@
%% Debug
-export([make_float/3, float2str/1, bc64/1]).
--compile({inline, [exs64_next/1, exsplus_next/1, exsss_next/1,
+-compile({inline, [exs64_next/1, exsp_next/1, exsss_next/1,
exs1024_next/1, exs1024_calc/2,
exro928_next_state/4,
exrop_next/1, exrop_next_s/2,
+ mwc59_value/1,
get_52/1, normal_kiwi/1]}).
-define(DEFAULT_ALG_HANDLER, exsss).
@@ -88,7 +94,7 @@
%% This depends on the algorithm handler function
-type alg_state() ::
exsplus_state() | exro928_state() | exrop_state() | exs1024_state() |
- exs64_state() | term().
+ exs64_state() | dummy_state() | term().
%% This is the algorithm handling definition within this module,
%% and the type to use for plugins.
@@ -132,7 +138,8 @@
%% Algorithm state
-type state() :: {alg_handler(), alg_state()}.
-type builtin_alg() ::
- exsss | exro928ss | exrop | exs1024s | exsp | exs64 | exsplus | exs1024.
+ exsss | exro928ss | exrop | exs1024s | exsp | exs64 | exsplus |
+ exs1024 | dummy.
-type alg() :: builtin_alg() | atom().
-type export_state() :: {alg(), alg_state()}.
-type seed() :: [integer()] | integer() | {integer(), integer(), integer()}.
@@ -141,7 +148,9 @@
state/0, export_state/0, seed/0]).
-export_type(
[exsplus_state/0, exro928_state/0, exrop_state/0, exs1024_state/0,
- exs64_state/0]).
+ exs64_state/0, mwc59_state/0, dummy_state/0]).
+-export_type(
+ [uint58/0, uint64/0, splitmix64_state/0]).
%% =====================================================================
%% Range macro and helper
@@ -266,9 +275,12 @@ seed_s({Alg, AlgState}) when is_atom(Alg) ->
{AlgHandler,_SeedFun} = mk_alg(Alg),
{AlgHandler,AlgState};
seed_s(Alg) ->
- seed_s(Alg, {erlang:phash2([{node(),self()}]),
- erlang:system_time(),
- erlang:unique_integer()}).
+ seed_s(Alg, default_seed()).
+
+default_seed() ->
+ {erlang:phash2([{node(),self()}]),
+ erlang:system_time(),
+ erlang:unique_integer()}.
%% seed/2: seeds RNG with the algorithm and given values
%% and returns the NEW state.
@@ -583,6 +595,22 @@ bytes_r(N, AlgHandler, Next, R, Bits, WeakLowBits) ->
bytes_r(N, AlgHandler, Next, R, <<>>, GoodBytes, GoodBits, Shift).
%%
bytes_r(N0, AlgHandler, Next, R0, Bytes0, GoodBytes, GoodBits, Shift)
+ when (GoodBytes bsl 2) < N0 ->
+ %% Loop unroll 4 iterations
+ %% - gives about 25% shorter time for large binaries
+ {V1, R1} = Next(R0),
+ {V2, R2} = Next(R1),
+ {V3, R3} = Next(R2),
+ {V4, R4} = Next(R3),
+ Bytes1 =
+ <<Bytes0/binary,
+ (V1 bsr Shift):GoodBits,
+ (V2 bsr Shift):GoodBits,
+ (V3 bsr Shift):GoodBits,
+ (V4 bsr Shift):GoodBits>>,
+ N1 = N0 - (GoodBytes bsl 2),
+ bytes_r(N1, AlgHandler, Next, R4, Bytes1, GoodBytes, GoodBits, Shift);
+bytes_r(N0, AlgHandler, Next, R0, Bytes0, GoodBytes, GoodBits, Shift)
when GoodBytes < N0 ->
{V, R1} = Next(R0),
Bytes1 = <<Bytes0/binary, (V bsr Shift):GoodBits>>,
@@ -679,11 +707,11 @@ mk_alg(exs64) ->
{#{type=>exs64, max=>?MASK(64), next=>fun exs64_next/1},
fun exs64_seed/1};
mk_alg(exsplus) ->
- {#{type=>exsplus, max=>?MASK(58), next=>fun exsplus_next/1,
+ {#{type=>exsplus, max=>?MASK(58), next=>fun exsp_next/1,
jump=>fun exsplus_jump/1},
fun exsplus_seed/1};
mk_alg(exsp) ->
- {#{type=>exsp, bits=>58, weak_low_bits=>1, next=>fun exsplus_next/1,
+ {#{type=>exsp, bits=>58, weak_low_bits=>1, next=>fun exsp_next/1,
uniform=>fun exsp_uniform/1, uniform_n=>fun exsp_uniform/2,
jump=>fun exsplus_jump/1},
fun exsplus_seed/1};
@@ -710,7 +738,12 @@ mk_alg(exro928ss) ->
uniform=>fun exro928ss_uniform/1,
uniform_n=>fun exro928ss_uniform/2,
jump=>fun exro928_jump/1},
- fun exro928_seed/1}.
+ fun exro928_seed/1};
+mk_alg(dummy=Name) ->
+ {#{type=>Name, bits=>58, next=>fun dummy_next/1,
+ uniform=>fun dummy_uniform/1,
+ uniform_n=>fun dummy_uniform/2},
+ fun dummy_seed/1}.
%% =====================================================================
%% exs64 PRNG: Xorshift64*
@@ -724,7 +757,7 @@ exs64_seed(L) when is_list(L) ->
[R] = seed64_nz(1, L),
R;
exs64_seed(A) when is_integer(A) ->
- [R] = seed64(1, ?MASK(64, A)),
+ [R] = seed64(1, A),
R;
%%
%% Traditional integer triplet seed
@@ -788,15 +821,15 @@ exsplus_seed(L) when is_list(L) ->
[S0,S1] = seed58_nz(2, L),
[S0|S1];
exsplus_seed(X) when is_integer(X) ->
- [S0,S1] = seed58(2, ?MASK(64, X)),
+ [S0,S1] = seed58(2, X),
[S0|S1];
%%
%% Traditional integer triplet seed
exsplus_seed({A1, A2, A3}) ->
- {_, R1} = exsplus_next(
+ {_, R1} = exsp_next(
[?MASK(58, (A1 * 4294967197) + 1)|
?MASK(58, (A2 * 4294967231) + 1)]),
- {_, R2} = exsplus_next(
+ {_, R2} = exsp_next(
[?MASK(58, (A3 * 4294967279) + 1)|
tl(R1)]),
R2.
@@ -807,21 +840,21 @@ exsss_seed(L) when is_list(L) ->
[S0,S1] = seed58_nz(2, L),
[S0|S1];
exsss_seed(X) when is_integer(X) ->
- [S0,S1] = seed58(2, ?MASK(64, X)),
+ [S0,S1] = seed58(2, X),
[S0|S1];
%%
%% Seed from traditional integer triple - mix into splitmix
exsss_seed({A1, A2, A3}) ->
- {_, X0} = seed58(?MASK(64, A1)),
- {S0, X1} = seed58(?MASK(64, A2) bxor X0),
- {S1, _} = seed58(?MASK(64, A3) bxor X1),
+ {_, X0} = seed58(A1),
+ {S0, X1} = seed58(A2 bxor X0),
+ {S1, _} = seed58(A3 bxor X1),
[S0|S1].
%% Advance Xorshift116 state one step
-define(
exs_next(S0, S1, S1_b),
begin
- S1_b = S1 bxor ?BSL(58, S1, 24),
+ S1_b = ?MASK(58, S1) bxor ?BSL(58, S1, 24),
S1_b bxor S0 bxor (S1_b bsr 11) bxor (S0 bsr 41)
end).
@@ -831,35 +864,38 @@ exsss_seed({A1, A2, A3}) ->
%% The multiply by add shifted trick avoids creating bignums
%% which improves performance significantly
%%
- V_a = ?MASK(58, S + ?BSL(58, S, 2)), % V_a = S * 5
- V_b = ?ROTL(58, V_a, 7),
- ?MASK(58, V_b + ?BSL(58, V_b, 3)) % V_b * 9
+ %% Scramble ** (all operations modulo word size)
+ %% ((S * 5) rotl 7) * 9
+ %%
+ V_a = S + ?BSL(58, S, 2), % * 5
+ V_b = ?BSL(58, V_a, 7) bor ?MASK(7, V_a bsr (58-7)), % rotl 7
+ ?MASK(58, V_b + ?BSL(58, V_b, 3)) % * 9
end).
--dialyzer({no_improper_lists, exsplus_next/1}).
-
%% Advance state and generate 58bit unsigned integer
--spec exsplus_next(exsplus_state()) -> {uint58(), exsplus_state()}.
-exsplus_next([S1|S0]) ->
+%%
+-dialyzer({no_improper_lists, exsp_next/1}).
+-spec exsp_next(AlgState :: exsplus_state()) ->
+ {X :: uint58(), NewAlgState :: exsplus_state()}.
+exsp_next([S1|S0]) ->
%% Note: members s0 and s1 are swapped here
- NewS1 = ?exs_next(S0, S1, S1_1),
- {?MASK(58, S0 + NewS1), [S0|NewS1]}.
-%% %% Note: members s0 and s1 are swapped here
-%% S11 = S1 bxor ?BSL(58, S1, 24),
-%% S12 = S11 bxor S0 bxor (S11 bsr 11) bxor (S0 bsr 41),
-%% {?MASK(58, S0 + S12), [S0|S12]}.
+ S0_1 = ?MASK(58, S0),
+ NewS1 = ?exs_next(S0_1, S1, S1_b),
+ %% Scramble + (all operations modulo word size)
+ %% S0 + NewS1
+ {?MASK(58, S0_1 + NewS1), [S0_1|NewS1]}.
-dialyzer({no_improper_lists, exsss_next/1}).
-spec exsss_next(exsplus_state()) -> {uint58(), exsplus_state()}.
exsss_next([S1|S0]) ->
%% Note: members s0 and s1 are swapped here
- NewS1 = ?exs_next(S0, S1, S1_1),
- {?scramble_starstar(S0, V_0, V_1), [S0|NewS1]}.
-%% {?MASK(58, S0 + NewS1), [S0|NewS1]}.
+ S0_1 = ?MASK(58, S0),
+ NewS1 = ?exs_next(S0_1, S1, S1_b),
+ {?scramble_starstar(S0_1, V_1, V_2), [S0_1|NewS1]}.
exsp_uniform({AlgHandler, R0}) ->
- {I, R1} = exsplus_next(R0),
+ {I, R1} = exsp_next(R0),
%% Waste the lowest bit since it is of lower
%% randomness quality than the others
{(I bsr (58-53)) * ?TWO_POW_MINUS53, {AlgHandler, R1}}.
@@ -869,7 +905,7 @@ exsss_uniform({AlgHandler, R0}) ->
{(I bsr (58-53)) * ?TWO_POW_MINUS53, {AlgHandler, R1}}.
exsp_uniform(Range, {AlgHandler, R}) ->
- {V, R1} = exsplus_next(R),
+ {V, R1} = exsp_next(R),
MaxMinusRange = ?BIT(58) - Range,
?uniform_range(Range, AlgHandler, R1, V, MaxMinusRange, I).
@@ -879,7 +915,7 @@ exsss_uniform(Range, {AlgHandler, R}) ->
?uniform_range(Range, AlgHandler, R1, V, MaxMinusRange, I).
-%% This is the jump function for the exs* generators,
+%% This is the jump function for the exs... generators,
%% i.e the Xorshift116 generators, equivalent
%% to 2^64 calls to next/1; it can be used to generate 2^52
%% non-overlapping subsequences for parallel computations.
@@ -918,15 +954,21 @@ exsss_uniform(Range, {AlgHandler, R}) ->
-spec exsplus_jump({alg_handler(), exsplus_state()}) ->
{alg_handler(), exsplus_state()}.
exsplus_jump({AlgHandler, S}) ->
+ {AlgHandler, exsp_jump(S)}.
+
+-dialyzer({no_improper_lists, exsp_jump/1}).
+-spec exsp_jump(AlgState :: exsplus_state()) ->
+ NewAlgState :: exsplus_state().
+exsp_jump(S) ->
{S1, AS1} = exsplus_jump(S, [0|0], ?JUMPCONST1, ?JUMPELEMLEN),
{_, AS2} = exsplus_jump(S1, AS1, ?JUMPCONST2, ?JUMPELEMLEN),
- {AlgHandler, AS2}.
+ AS2.
-dialyzer({no_improper_lists, exsplus_jump/4}).
exsplus_jump(S, AS, _, 0) ->
{S, AS};
exsplus_jump(S, [AS0|AS1], J, N) ->
- {_, NS} = exsplus_next(S),
+ {_, NS} = exsp_next(S),
case ?MASK(1, J) of
1 ->
[S0|S1] = S,
@@ -946,7 +988,7 @@ exsplus_jump(S, [AS0|AS1], J, N) ->
exs1024_seed(L) when is_list(L) ->
{seed64_nz(16, L), []};
exs1024_seed(X) when is_integer(X) ->
- {seed64(16, ?MASK(64, X)), []};
+ {seed64(16, X), []};
%%
%% Seed from traditional triple, remain backwards compatible
exs1024_seed({A1, A2, A3}) ->
@@ -1135,13 +1177,13 @@ exs1024_jump({L, RL}, AS, JL, J, N, TN) ->
exro928_seed(L) when is_list(L) ->
{seed58_nz(16, L), []};
exro928_seed(X) when is_integer(X) ->
- {seed58(16, ?MASK(64, X)), []};
+ {seed58(16, X), []};
%%
%% Seed from traditional integer triple - mix into splitmix
exro928_seed({A1, A2, A3}) ->
- {S0, X0} = seed58(?MASK(64, A1)),
- {S1, X1} = seed58(?MASK(64, A2) bxor X0),
- {S2, X2} = seed58(?MASK(64, A3) bxor X1),
+ {S0, X0} = seed58(A1),
+ {S1, X1} = seed58(A2 bxor X0),
+ {S2, X2} = seed58(A3 bxor X1),
{[S0,S1,S2|seed58(13, X2)], []}.
@@ -1154,13 +1196,6 @@ exro928ss_next({[S15,S0|Ss], Rs}) ->
%% const uint64_t result_starstar = rotl(s0 * S, R) * T;
%%
{?scramble_starstar(S0, V_0, V_1), SR};
-%% %% The multiply by add shifted trick avoids creating bignums
-%% %% which improves performance significantly
-%% %%
-%% V0 = ?MASK(58, S0 + ?BSL(58, S0, 2)), % V0 = S0 * 5
-%% V1 = ?ROTL(58, V0, 7),
-%% V = ?MASK(58, V1 + ?BSL(58, V1, 3)), % V = V1 * 9
-%% {V, SR};
exro928ss_next({[S15], Rs}) ->
exro928ss_next({[S15|lists:reverse(Rs)], []}).
@@ -1185,8 +1220,9 @@ exro928_next_state(Ss, Rs, S15, S0) ->
%% NewS15: s[q] = rotl(s0, A) ^ s15 ^ (s15 << B);
%% NewS0: s[p] = rotl(s15, C);
%%
- Q = S15 bxor S0,
- NewS15 = ?ROTL(58, S0, 44) bxor Q bxor ?BSL(58, Q, 9),
+ S0_1 = ?MASK(58, S0),
+ Q = ?MASK(58, S15) bxor S0_1,
+ NewS15 = ?ROTL(58, S0_1, 44) bxor Q bxor ?BSL(58, Q, 9),
NewS0 = ?ROTL(58, Q, 45),
{[NewS0|Ss], [NewS15|Rs]}.
@@ -1307,7 +1343,7 @@ exrop_seed(L) when is_list(L) ->
[S0,S1] = seed58_nz(2, L),
[S0|S1];
exrop_seed(X) when is_integer(X) ->
- [S0,S1] = seed58(2, ?MASK(64, X)),
+ [S0,S1] = seed58(2, X),
[S0|S1];
%%
%% Traditional integer triplet seed
@@ -1374,6 +1410,159 @@ exrop_jump([S__0|S__1] = _S, S0, S1, J, Js) ->
end.
%% =====================================================================
+%% dummy "PRNG": Benchmark dummy overhead reference
+%%
+%% As fast as possible - return something daft and update state;
+%% to measure plug-in framework overhead.
+%%
+%% =====================================================================
+
+-type dummy_state() :: uint58().
+
+dummy_uniform(_Range, {AlgHandler,R}) ->
+ {1, {AlgHandler,(R bxor ?MASK(58))}}. % 1 is always in Range
+dummy_next(R) ->
+ {R, R bxor ?MASK(58)}.
+dummy_uniform({AlgHandler,R}) ->
+ {0.5, {AlgHandler,(R bxor ?MASK(58))}}. % Perfect mean value
+
+%% Serious looking seed, to avoid rand_SUITE seed test failure
+%%
+dummy_seed(L) when is_list(L) ->
+ case L of
+ [] ->
+ erlang:error(zero_seed);
+ [X] when is_integer(X) ->
+ ?MASK(58, X);
+ [X|_] when is_integer(X) ->
+ erlang:error(too_many_seed_integers);
+ [_|_] ->
+ erlang:error(non_integer_seed)
+ end;
+dummy_seed(X) when is_integer(X) ->
+ {Z1, _} = splitmix64_next(X),
+ ?MASK(58, Z1);
+dummy_seed({A1, A2, A3}) ->
+ {_, X1} = splitmix64_next(A1),
+ {_, X2} = splitmix64_next(A2 bxor X1),
+ {Z3, _} = splitmix64_next(A3 bxor X2),
+ ?MASK(58, Z3).
+
+
+%% =====================================================================
+%% mcg58 PRNG: Multiply With Carry generator
+%%
+%% Parameters deduced in collaboration with
+%% Prof. Sebastiano Vigna of the University of Milano.
+%%
+%% X = CX0 & (2^B - 1) % Low B bits - digit
+%% C = CX0 >> B % High bits - carry
+%% CX1 = A * X0 + C0
+%%
+%% An MWC generator is an efficient alternative implementation of
+%% a Multiplicative Congruential Generator, that is, the generator
+%% CX1 = (CX0 * 2^B) rem P
+%% where P is the safe prime (A * 2^B - 1), that generates
+%% the same sequence in the reverse order. The generator
+%% CX1 = (A * CX0) rem P
+%% that uses the multiplicative inverse mod P is, indeed,
+%% an exact equevalent to the corresponding MWC generator.
+%%
+%% An MWC generator has, due to the power of two multiplier
+%% in the corresponding MCG, got known statistical weaknesses
+%% in the spectral score for 3 dimensions, so it should be used
+%% with a scrambler that hides the flaws. The scramblers
+%% have been tried out in the PractRand and TestU01 frameworks
+%% and settled for a single Xorshift to get B good bits,
+%% and a double Xorshift to get all bits good enough.
+%%
+%% The chosen parameters are:
+%% A = 16#7fa6502
+%% B = 32
+%% Single Xorshift: 8
+%% Double Xorshift: 4, 27
+%%
+%% These parameters gives the MWC "digit" size 32 bits
+%% which gives them theoretical statistical guarantees,
+%% and keeps the state in 59 bits.
+%%
+%% The state should only be used to mask or rem out low bits.
+%% The scramblers return 58 bits from which a number should
+%% be masked or rem:ed out.
+%%
+%% =====================================================================
+-define(MWC59_A, (16#7fa6502)).
+-define(MWC59_B, (32)).
+-define(MWC59_P, ((?MWC59_A bsl ?MWC59_B) - 1)).
+
+-define(MWC59_XS, 8).
+-define(MWC59_XS1, 4).
+-define(MWC59_XS2, 27).
+
+-type mwc59_state() :: 1..?MWC59_P-1.
+
+-spec mwc59(CX0 :: mwc59_state()) -> CX1 :: mwc59_state().
+mwc59(CX0) -> % when is_integer(CX0), 1 =< CX0, CX0 < ?MWC59_P ->
+ CX = ?MASK(59, CX0),
+ C = CX bsr ?MWC59_B,
+ X = ?MASK(?MWC59_B, CX),
+ ?MWC59_A * X + C.
+
+%%% %% Verification by equivalent MCG generator
+%%% mwc59_r(CX1) ->
+%%% (CX1 bsl ?MWC59_B) rem ?MWC59_P. % Reverse
+%%% %%% (CX1 * ?MWC59_A) rem ?MWC59_P. % Forward
+%%%
+%%% mwc59(CX0, 0) ->
+%%% CX0;
+%%% mwc59(CX0, N) ->
+%%% CX1 = mwc59(CX0),
+%%% CX0 = mwc59_r(CX1),
+%%% mwc59(CX1, N - 1).
+
+-spec mwc59_value32(CX :: mwc59_state()) -> V :: 0..?MASK(32).
+mwc59_value32(CX1) -> % when is_integer(CX1), 1 =< CX1, CX1 < ?MWC59_P ->
+ CX = ?MASK(32, CX1),
+ CX bxor ?BSL(32, CX, ?MWC59_XS).
+
+-spec mwc59_value(CX :: mwc59_state()) -> V :: 0..?MASK(59).
+mwc59_value(CX1) -> % when is_integer(CX1), 1 =< CX1, CX1 < ?MWC59_P ->
+ CX = ?MASK(59, CX1),
+ CX2 = CX bxor ?BSL(59, CX, ?MWC59_XS1),
+ CX2 bxor ?BSL(59, CX2, ?MWC59_XS2).
+
+-spec mwc59_float(CX :: mwc59_state()) -> V :: float().
+mwc59_float(CX1) ->
+ CX = ?MASK(53, CX1),
+ CX2 = CX bxor ?BSL(53, CX, ?MWC59_XS1),
+ CX3 = CX2 bxor ?BSL(53, CX2, ?MWC59_XS2),
+ CX3 * ?TWO_POW_MINUS53.
+
+-spec mwc59_seed() -> CX :: mwc59_state().
+mwc59_seed() ->
+ {A1, A2, A3} = default_seed(),
+ X1 = hash58(A1),
+ X2 = hash58(A2),
+ X3 = hash58(A3),
+ (X1 bxor X2 bxor X3) + 1.
+
+-spec mwc59_seed(S :: 0..?MASK(58)) -> CX :: mwc59_state().
+mwc59_seed(S) when is_integer(S), 0 =< S, S =< ?MASK(58) ->
+ hash58(S) + 1.
+
+%% Constants a'la SplitMix64, MurMurHash, etc.
+%% Not that critical, just mix the bits using bijections
+%% (reversible mappings) to not have any two user input seeds
+%% become the same generator start state.
+%%
+hash58(X) ->
+ X0 = ?MASK(58, X),
+ X1 = ?MASK(58, (X0 bxor (X0 bsr 29)) * 16#351afd7ed558ccd),
+ X2 = ?MASK(58, (X1 bxor (X1 bsr 29)) * 16#0ceb9fe1a85ec53),
+ X2 bxor (X2 bsr 29).
+
+
+%% =====================================================================
%% Mask and fill state list, ensure not all zeros
%% =====================================================================
@@ -1436,6 +1625,7 @@ seed64(X_0) ->
ZX
end.
+%% =====================================================================
%% The SplitMix64 generator:
%%
%% uint64_t splitmix64_next() {
@@ -1445,6 +1635,11 @@ seed64(X_0) ->
%% return z ^ (z >> 31);
%% }
%%
+
+-type splitmix64_state() :: uint64().
+
+-spec splitmix64_next(AlgState :: integer()) ->
+ {X :: uint64(), NewAlgState :: splitmix64_state()}.
splitmix64_next(X_0) ->
X = ?MASK(64, X_0 + 16#9e3779b97f4a7c15),
Z_0 = ?MASK(64, (X bxor (X bsr 30)) * 16#bf58476d1ce4e5b9),
@@ -1793,7 +1988,21 @@ bc64(V) -> ?BC(V, 64).
%% Linear from high bit - higher probability first gives faster execution
bc(V, B, N) when B =< V -> N;
bc(V, B, N) -> bc(V, B bsr 1, N - 1).
-
+
+
+%%% %% Non-negative rem
+%%% mod(Q, X) when 0 =< X, X < Q ->
+%%% X;
+%%% mod(Q, X) ->
+%%% Y = X rem Q,
+%%% if
+%%% Y < 0 ->
+%%% Y + Q;
+%%% true ->
+%%% Y
+%%% end.
+
+
make_float(S, E, M) ->
<<F/float>> = <<S:1, E:11, M:52>>,
F.
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index 2783ec11eb..bdc0ed40f3 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -426,8 +426,10 @@ is_subset_1(Set, Iter) ->
Acc1 :: Acc,
AccIn :: Acc,
AccOut :: Acc.
-fold(F, Acc, #{}=D) -> fold_1(F, Acc, maps:iterator(D));
-fold(F, Acc, #set{}=D) -> fold_set(F, Acc, D).
+fold(F, Acc, #{}=D) when is_function(F, 2)->
+ fold_1(F, Acc, maps:iterator(D));
+fold(F, Acc, #set{}=D) when is_function(F, 2)->
+ fold_set(F, Acc, D).
fold_1(Fun, Acc, Iter) ->
case maps:next(Iter) of
@@ -443,8 +445,10 @@ fold_1(Fun, Acc, Iter) ->
Pred :: fun((Element) -> boolean()),
Set1 :: set(Element),
Set2 :: set(Element).
-filter(F, #{}=D) -> maps:from_keys(filter_1(F, maps:iterator(D)), ?VALUE);
-filter(F, #set{}=D) -> filter_set(F, D).
+filter(F, #{}=D) when is_function(F, 1)->
+ maps:from_keys(filter_1(F, maps:iterator(D)), ?VALUE);
+filter(F, #set{}=D) when is_function(F, 1)->
+ filter_set(F, D).
filter_1(Fun, Iter) ->
case maps:next(Iter) of
@@ -482,7 +486,7 @@ get_bucket(T, Slot) -> get_bucket_s(T#set.segs, Slot).
%% implemented map and hash using fold but these should be faster.
%% We hope!
-fold_set(F, Acc, D) when is_function(F, 2) ->
+fold_set(F, Acc, D) ->
Segs = D#set.segs,
fold_segs(F, Acc, Segs, tuple_size(Segs)).
@@ -499,7 +503,7 @@ fold_bucket(F, Acc, [E|Bkt]) ->
fold_bucket(F, F(E, Acc), Bkt);
fold_bucket(_, Acc, []) -> Acc.
-filter_set(F, D) when is_function(F, 1) ->
+filter_set(F, D) ->
Segs0 = tuple_to_list(D#set.segs),
{Segs1,Fc} = filter_seg_list(F, Segs0, [], 0),
maybe_contract(D#set{segs = list_to_tuple(Segs1)}, Fc).
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index 246e5ca567..7de78758b0 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -228,10 +228,10 @@ server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
N = N0 + 1,
{Eval_1,Bs0,Ds0,Prompt} = prompt(N, Eval_0, Bs00, RT, Ds00),
{Res,Eval0} = get_command(Prompt, Eval_1, Bs0, RT, Ds0),
+
case Res of
- {ok,Es0,XBs} ->
- Es1 = erl_eval:subst_values_for_vars(Es0, XBs),
- case expand_hist(Es1, N) of
+ {ok,Es0} ->
+ case expand_hist(Es0, N) of
{ok,Es} ->
{V,Eval,Bs,Ds} = shell_cmd(Es, Eval0, Bs0, RT, Ds0, cmd),
{History,Results} = check_and_get_history_and_results(),
@@ -273,11 +273,13 @@ server_loop(N0, Eval_0, Bs00, RT, Ds00, History0, Results0) ->
end.
get_command(Prompt, Eval, Bs, RT, Ds) ->
+ ResWordFun = fun erl_scan:reserved_word/1,
Parse =
fun() ->
exit(
case
- io:scan_erl_exprs(group_leader(), Prompt, {1,1}, [text])
+ io:scan_erl_exprs(group_leader(), Prompt, {1,1},
+ [text,{reserved_word_fun,ResWordFun}])
of
{ok,Toks,_EndPos} ->
erl_eval:extended_parse_exprs(Toks);
@@ -315,9 +317,9 @@ get_command1(Pid, Eval, Bs, RT, Ds) ->
prompt(N, Eval0, Bs0, RT, Ds0) ->
case get_prompt_func() of
{M,F} ->
- L = [{history,N}],
A = erl_anno:new(1),
- C = {call,A,{remote,A,{atom,A,M},{atom,A,F}},[{value,A,L}]},
+ L = {cons,A,{tuple,A,[{atom,A,history},{integer,A,N}]},{nil,A}},
+ C = {call,A,{remote,A,{atom,A,M},{atom,A,F}},[L]},
{V,Eval,Bs,Ds} = shell_cmd([C], Eval0, Bs0, RT, Ds0, pmt),
{Eval,Bs,Ds,case V of
{pmt,Val} ->
@@ -414,12 +416,12 @@ expand_expr({call,A,{atom,_,e},[N]}, C) ->
{Ces,_V,_CommandN} when is_list(Ces) ->
{block,A,Ces}
end;
-expand_expr({call,_A,{atom,_,v},[N]}, C) ->
+expand_expr({call,CA,{atom,VA,v},[N]}, C) ->
case get_cmd(N, C) of
{_,undefined,_} ->
no_command(N);
- {Ces,V,CommandN} when is_list(Ces) ->
- {value,erl_anno:new(CommandN),V}
+ {Ces,_V,CommandN} when is_list(Ces) ->
+ {call,CA,{atom,VA,v},[{integer,VA,CommandN}]}
end;
expand_expr({call,A,F,Args}, C) ->
{call,A,expand_expr(F, C),expand_exprs(Args, C)};
@@ -539,6 +541,9 @@ shell_rep(Ev, Bs0, RT, Ds0) ->
fwrite_severity(benign, <<"~s: ~ts">>,
[pos(Location), M:format_error(Error)]),
{{'EXIT',Error},Ev,Bs0,Ds0};
+ {shell_req,Ev,{get_cmd,N}} ->
+ Ev ! {shell_rep,self(),getc(N)},
+ shell_rep(Ev, Bs0, RT, Ds0);
{shell_req,Ev,get_cmd} ->
Ev ! {shell_rep,self(),get()},
shell_rep(Ev, Bs0, RT, Ds0);
@@ -956,6 +961,10 @@ init_dict([]) -> true.
%% handled in this module (i.e. those that are not eventually handled by
%% non_builtin_local_func/3 (user_default/shell_default).
+local_func(v, [{integer,_,V}], Bs, Shell, _RT, _Lf, _Ef) ->
+ %% This command is validated and expanded prior.
+ {_Ces,Value,_N} = shell_req(Shell, {get_cmd, V}),
+ {value,Value,Bs};
local_func(h, [], Bs, Shell, RT, _Lf, _Ef) ->
Cs = shell_req(Shell, get_cmd),
Cs1 = lists:filter(fun({{command, _},_}) -> true;
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index a5169c38f7..342c55e3eb 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
%%
-module(slave).
+-deprecated([{'_','_',"use the 'peer' module instead"}]).
+
%% If the macro DEBUG is defined during compilation,
%% debug printouts are done through erlang:display/1.
%% Activate this feature by starting the compiler
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index abef604bdd..358ebf471d 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -46,6 +46,7 @@
erl_error,
erl_eval,
erl_expand_records,
+ erl_features,
erl_internal,
erl_lint,
erl_parse,
@@ -71,7 +72,6 @@
io,
io_lib,
io_lib_format,
- io_lib_format_ryu_table,
io_lib_fread,
io_lib_pretty,
lists,
@@ -82,6 +82,7 @@
orddict,
ordsets,
otp_internal,
+ peer,
pool,
proc_lib,
proplists,
@@ -111,6 +112,6 @@
dets]},
{applications, [kernel]},
{env, []},
- {runtime_dependencies, ["sasl-3.0","kernel-7.0","erts-12.0","crypto-3.3",
+ {runtime_dependencies, ["sasl-3.0","kernel-8.5.1","erts-13.1","crypto-4.5",
"compiler-5.0"]}
]}.
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 393e4efaa9..0cb84fd3dc 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -19,25 +19,16 @@
%%
%% We allow upgrade from, and downgrade to all previous
%% versions from the following OTP releases:
-%% - OTP 22
%% - OTP 23
%% - OTP 24
+%% - OTP 25
%%
%% We also allow upgrade from, and downgrade to all
%% versions that have branched off from the above
%% stated previous versions.
%%
{"%VSN%",
- [{<<"^3\\.10$">>,[restart_new_emulator]},
- {<<"^3\\.10\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.11$">>,[restart_new_emulator]},
- {<<"^3\\.11\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.11\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.11\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.12$">>,[restart_new_emulator]},
- {<<"^3\\.12\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.12\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.13$">>,[restart_new_emulator]},
+ [{<<"^3\\.13$">>,[restart_new_emulator]},
{<<"^3\\.13\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.13\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^3\\.13\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
@@ -55,20 +46,16 @@
{<<"^3\\.17$">>,[restart_new_emulator]},
{<<"^3\\.17\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.17\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.9$">>,[restart_new_emulator]},
- {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.9\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.9\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
- [{<<"^3\\.10$">>,[restart_new_emulator]},
- {<<"^3\\.10\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.11$">>,[restart_new_emulator]},
- {<<"^3\\.11\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.11\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.11\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.12$">>,[restart_new_emulator]},
- {<<"^3\\.12\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.12\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.13$">>,[restart_new_emulator]},
+ {<<"^3\\.17\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.0$">>,[restart_new_emulator]},
+ {<<"^4\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^4\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.1$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.2$">>,[restart_new_emulator]},
+ {<<"^4\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
+ [{<<"^3\\.13$">>,[restart_new_emulator]},
{<<"^3\\.13\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.13\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
{<<"^3\\.13\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
@@ -86,7 +73,12 @@
{<<"^3\\.17$">>,[restart_new_emulator]},
{<<"^3\\.17\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.17\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.9$">>,[restart_new_emulator]},
- {<<"^3\\.9\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.9\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
- {<<"^3\\.9\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
+ {<<"^3\\.17\\.2(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.0$">>,[restart_new_emulator]},
+ {<<"^4\\.0\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^4\\.0\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.1$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
+ {<<"^4\\.1\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^4\\.2$">>,[restart_new_emulator]},
+ {<<"^4\\.2\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 281e7a92f1..58b943d874 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -72,11 +72,11 @@
-type shutdown() :: 'brutal_kill' | timeout().
-type worker() :: 'worker' | 'supervisor'.
-type sup_name() :: {'local', Name :: atom()}
- | {'global', Name :: atom()}
+ | {'global', Name :: term()}
| {'via', Module :: module(), Name :: any()}.
-type sup_ref() :: (Name :: atom())
| {Name :: atom(), Node :: node()}
- | {'global', Name :: atom()}
+ | {'global', Name :: term()}
| {'via', Module :: module(), Name :: any()}
| pid().
-type child_spec() :: #{id := child_id(), % mandatory
@@ -132,16 +132,16 @@
-type child_rec() :: #child{}.
-record(state, {name,
- strategy :: strategy() | 'undefined',
+ strategy = one_for_one:: strategy(),
children = {[],#{}} :: children(), % Ids in start order
dynamics :: {'maps', #{pid() => list()}}
| {'mapsets', #{pid() => []}}
| 'undefined',
- intensity :: non_neg_integer() | 'undefined',
- period :: pos_integer() | 'undefined',
+ intensity = 1 :: non_neg_integer(),
+ period = 5 :: pos_integer(),
restarts = [],
dynamic_restarts = 0 :: non_neg_integer(),
- auto_shutdown :: auto_shutdown(),
+ auto_shutdown = never :: auto_shutdown(),
module,
args}).
-type state() :: #state{}.
@@ -161,7 +161,7 @@
%%% ---------------------------------------------------
%%% This is a general process supervisor built upon gen_server.erl.
%%% Servers/processes should/could also be built using gen_server.erl.
-%%% SupName = {local, atom()} | {global, atom()}.
+%%% SupName = {local, atom()} | {global, term()}.
%%% ---------------------------------------------------
-type startlink_err() :: {'already_started', pid()}
@@ -255,7 +255,7 @@ which_children(Supervisor) ->
Count :: {specs, ChildSpecCount :: non_neg_integer()}
| {active, ActiveProcessCount :: non_neg_integer()}
| {supervisors, ChildSupervisorCount :: non_neg_integer()}
- |{workers, ChildWorkerCount :: non_neg_integer()}.
+ | {workers, ChildWorkerCount :: non_neg_integer()}.
count_children(Supervisor) ->
call(Supervisor, count_children).
@@ -371,7 +371,7 @@ init_dynamic(_State, StartSpec) ->
%%-----------------------------------------------------------------
%% Func: start_children/2
%% Args: Children = children() % Ids in start order
-%% SupName = {local, atom()} | {global, atom()} | {pid(), Mod}
+%% SupName = {local, atom()} | {global, term()} | {pid(), Mod}
%% Purpose: Start all children. The new map contains #child's
%% with pids.
%% Returns: {ok, NChildren} | {error, NChildren, Reason}
@@ -879,7 +879,7 @@ try_again_restart(TryAgainId) ->
%%-----------------------------------------------------------------
%% Func: terminate_children/2
%% Args: Children = children() % Ids in termination order
-%% SupName = {local, atom()} | {global, atom()} | {pid(),Mod}
+%% SupName = {local, atom()} | {global, term()} | {pid(),Mod}
%% Returns: NChildren = children() % Ids in startup order
%% % (reversed termination order)
%%-----------------------------------------------------------------
@@ -1296,7 +1296,7 @@ append({Ids1,Db1},{Ids2,Db2}) ->
%%-----------------------------------------------------------------
%% Func: init_state/4
-%% Args: SupName = {local, atom()} | {global, atom()} | self
+%% Args: SupName = {local, atom()} | {global, term()} | self
%% Type = {Strategy, MaxIntensity, Period}
%% Strategy = one_for_one | one_for_all | simple_one_for_one |
%% rest_for_one
@@ -1516,7 +1516,7 @@ add_restart(State) ->
P = State#state.period,
R = State#state.restarts,
Now = erlang:monotonic_time(1),
- R1 = add_restart([Now|R], Now, P),
+ R1 = add_restart(R, Now, P),
State1 = State#state{restarts = R1},
case length(R1) of
CurI when CurI =< I ->
@@ -1525,18 +1525,13 @@ add_restart(State) ->
{terminate, State1}
end.
-add_restart([R|Restarts], Now, Period) ->
- case inPeriod(R, Now, Period) of
- true ->
- [R|add_restart(Restarts, Now, Period)];
- _ ->
- []
- end;
-add_restart([], _, _) ->
- [].
-
-inPeriod(Then, Now, Period) ->
- Now =< Then + Period.
+add_restart(Restarts0, Now, Period) ->
+ Treshold = Now - Period,
+ Restarts1 = lists:takewhile(
+ fun (R) -> R >= Treshold end,
+ Restarts0
+ ),
+ [Now | Restarts1].
%%% ------------------------------------------------------
%%% Error and progress reporting.
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index eeeceda769..6ec29aa1ff 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@
%% Types
%%-----------------------------------------------------------------
--export_type([dbg_opt/0, dbg_fun/0, debug_option/0]).
+-export_type([dbg_opt/0, dbg_fun/0, debug_option/0, system_event/0]).
-type name() :: pid() | atom()
| {'global', term()}
@@ -51,12 +51,12 @@
| {'out', Msg :: _, To :: _, State :: _}
| {'noreply', State :: _}
| {'continue', Continuation :: _}
- | {'code_change', Event :: _, State :: _}
| {'postpone', Event :: _, State :: _, NextState :: _}
| {'consume', Event :: _, State :: _, NextState :: _}
| {'start_timer', Action :: _, State :: _}
| {'insert_timeout', Event :: _, State :: _}
- | {'enter', State :: _}
+ | {'enter', Module :: module(), State :: _}
+ | {'module', Module :: module(), State :: _}
| {'terminate', Reason :: _, State :: _}
| term().
-opaque dbg_opt() :: {'trace', 'true'}
diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl
index df10790ea0..182f5cb4f2 100644
--- a/lib/stdlib/src/timer.erl
+++ b/lib/stdlib/src/timer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,135 +20,204 @@
-module(timer).
-export([apply_after/4,
- send_after/3, send_after/2,
- exit_after/3, exit_after/2, kill_after/2, kill_after/1,
- apply_interval/4, send_interval/3, send_interval/2,
- cancel/1, sleep/1, tc/1, tc/2, tc/3, now_diff/2,
- seconds/1, minutes/1, hours/1, hms/3]).
-
--export([start_link/0, start/0,
- handle_call/3, handle_info/2,
- init/1,
- code_change/3, handle_cast/2, terminate/2]).
-
-%% internal exports for test purposes only
--export([get_status/0]).
-
-%% types which can be used by other modules
+ send_after/3, send_after/2,
+ exit_after/3, exit_after/2, kill_after/2, kill_after/1,
+ apply_interval/4, send_interval/3, send_interval/2,
+ cancel/1, sleep/1, tc/1, tc/2, tc/3, now_diff/2,
+ seconds/1, minutes/1, hours/1, hms/3]).
+
+-export([start_link/0, start/0,
+ handle_call/3, handle_info/2,
+ init/1,
+ code_change/3, handle_cast/2, terminate/2]).
+
+%% Types which can be used by other modules
-export_type([tref/0]).
-%% Max
--define(MAX_TIMEOUT, 16#0800000).
--define(TIMER_TAB, timer_tab).
--define(INTERVAL_TAB, timer_interval_tab).
+%% Max value for a receive's after clause.
+-define(MAX_RECEIVE_AFTER, 16#ffffffff).
+
+%% Validations
+-define(valid_time(T), is_integer(T), T >= 0).
+-define(valid_mfa(M, F, A), is_atom(M), is_atom(F), is_list(A)).
%%
%% Time is in milliseconds.
%%
--opaque tref() :: {integer(), reference()}.
--type time() :: non_neg_integer().
+-opaque tref() :: {type(), reference()}.
+-type type() :: 'once' | 'interval' | 'instant' | 'send_local'.
+-type time() :: non_neg_integer().
%%
%% Interface functions
%%
-spec apply_after(Time, Module, Function, Arguments) ->
- {'ok', TRef} | {'error', Reason} when
- Time :: time(),
- Module :: module(),
- Function :: atom(),
- Arguments :: [term()],
- TRef :: tref(),
- Reason :: term().
-
-apply_after(Time, M, F, A) ->
- req(apply_after, {Time, {M, F, A}}).
-
--spec send_after(Time, Pid, Message) -> {'ok', TRef} | {'error', Reason} when
- Time :: time(),
- Pid :: pid() | (RegName :: atom()),
- Message :: term(),
- TRef :: tref(),
- Reason :: term().
-send_after(Time, Pid, Message) ->
- req(apply_after, {Time, {?MODULE, send, [Pid, Message]}}).
-
--spec send_after(Time, Message) -> {'ok', TRef} | {'error', Reason} when
- Time :: time(),
- Message :: term(),
- TRef :: tref(),
- Reason :: term().
+ {'ok', TRef} | {'error', Reason}
+ when Time :: time(),
+ Module :: module(),
+ Function :: atom(),
+ Arguments :: [term()],
+ TRef :: tref(),
+ Reason :: term().
+apply_after(0, M, F, A)
+ when ?valid_mfa(M, F, A) ->
+ do_apply({M, F, A}),
+ {ok, {instant, make_ref()}};
+apply_after(Time, M, F, A)
+ when ?valid_time(Time),
+ ?valid_mfa(M, F, A) ->
+ req(apply_once, {system_time(), Time, {M, F, A}});
+apply_after(_Time, _M, _F, _A) ->
+ {error, badarg}.
+
+-spec send_after(Time, Destination, Message) -> {'ok', TRef} | {'error', Reason}
+ when Time :: time(),
+ Destination :: pid() | (RegName :: atom()) | {RegName :: atom(), Node :: node()},
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
+send_after(0, PidOrRegName, Message)
+ when is_pid(PidOrRegName);
+ is_atom(PidOrRegName) ->
+ PidOrRegName ! Message,
+ {ok, {instant, make_ref()}};
+send_after(0, {RegName, Node} = Dest, Message)
+ when is_atom(RegName),
+ is_atom(Node) ->
+ Dest ! Message,
+ {ok, {instant, make_ref()}};
+send_after(Time, Pid, Message)
+ when ?valid_time(Time),
+ is_pid(Pid),
+ node(Pid) =:= node() ->
+ TRef = erlang:send_after(Time, Pid, Message),
+ {ok, {send_local, TRef}};
+send_after(Time, Pid, Message)
+ when is_pid(Pid) ->
+ apply_after(Time, ?MODULE, send, [Pid, Message]);
+send_after(Time, RegName, Message)
+ when is_atom(RegName) ->
+ apply_after(Time, ?MODULE, send, [RegName, Message]);
+send_after(Time, {RegName, Node} = Dest, Message)
+ when is_atom(RegName),
+ is_atom(Node) ->
+ apply_after(Time, ?MODULE, send, [Dest, Message]);
+send_after(_Time, _PidOrRegName, _Message) ->
+ {error, badarg}.
+
+-spec send_after(Time, Message) -> {'ok', TRef} | {'error', Reason}
+ when Time :: time(),
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
send_after(Time, Message) ->
send_after(Time, self(), Message).
--spec exit_after(Time, Pid, Reason1) -> {'ok', TRef} | {'error', Reason2} when
- Time :: time(),
- Pid :: pid() | (RegName :: atom()),
- TRef :: tref(),
- Reason1 :: term(),
- Reason2 :: term().
+-spec exit_after(Time, Target, Reason1) -> {'ok', TRef} | {'error', Reason2}
+ when Time :: time(),
+ Target :: pid() | (RegName :: atom()),
+ TRef :: tref(),
+ Reason1 :: term(),
+ Reason2 :: term().
exit_after(Time, Pid, Reason) ->
- req(apply_after, {Time, {erlang, exit, [Pid, Reason]}}).
+ apply_after(Time, erlang, exit, [Pid, Reason]).
--spec exit_after(Time, Reason1) -> {'ok', TRef} | {'error', Reason2} when
- Time :: time(),
- TRef :: tref(),
- Reason1 :: term(),
- Reason2 :: term().
+-spec exit_after(Time, Reason1) -> {'ok', TRef} | {'error', Reason2}
+ when Time :: time(),
+ TRef :: tref(),
+ Reason1 :: term(),
+ Reason2 :: term().
exit_after(Time, Reason) ->
exit_after(Time, self(), Reason).
--spec kill_after(Time, Pid) -> {'ok', TRef} | {'error', Reason2} when
- Time :: time(),
- Pid :: pid() | (RegName :: atom()),
- TRef :: tref(),
- Reason2 :: term().
+-spec kill_after(Time, Target) -> {'ok', TRef} | {'error', Reason2}
+ when Time :: time(),
+ Target :: pid() | (RegName :: atom()),
+ TRef :: tref(),
+ Reason2 :: term().
kill_after(Time, Pid) ->
exit_after(Time, Pid, kill).
--spec kill_after(Time) -> {'ok', TRef} | {'error', Reason2} when
- Time :: time(),
- TRef :: tref(),
- Reason2 :: term().
+-spec kill_after(Time) -> {'ok', TRef} | {'error', Reason2}
+ when Time :: time(),
+ TRef :: tref(),
+ Reason2 :: term().
kill_after(Time) ->
exit_after(Time, self(), kill).
-spec apply_interval(Time, Module, Function, Arguments) ->
- {'ok', TRef} | {'error', Reason} when
- Time :: time(),
- Module :: module(),
- Function :: atom(),
- Arguments :: [term()],
- TRef :: tref(),
- Reason :: term().
-apply_interval(Time, M, F, A) ->
- req(apply_interval, {Time, self(), {M, F, A}}).
-
--spec send_interval(Time, Pid, Message) ->
- {'ok', TRef} | {'error', Reason} when
- Time :: time(),
- Pid :: pid() | (RegName :: atom()),
- Message :: term(),
- TRef :: tref(),
- Reason :: term().
-send_interval(Time, Pid, Message) ->
- req(apply_interval, {Time, Pid, {?MODULE, send, [Pid, Message]}}).
-
--spec send_interval(Time, Message) -> {'ok', TRef} | {'error', Reason} when
- Time :: time(),
- Message :: term(),
- TRef :: tref(),
- Reason :: term().
+ {'ok', TRef} | {'error', Reason}
+ when Time :: time(),
+ Module :: module(),
+ Function :: atom(),
+ Arguments :: [term()],
+ TRef :: tref(),
+ Reason :: term().
+apply_interval(Time, M, F, A)
+ when ?valid_time(Time),
+ ?valid_mfa(M, F, A) ->
+ req(apply_interval, {system_time(), Time, self(), {M, F, A}});
+apply_interval(_Time, _M, _F, _A) ->
+ {error, badarg}.
+
+-spec send_interval(Time, Destination, Message) -> {'ok', TRef} | {'error', Reason}
+ when Time :: time(),
+ Destination :: pid() | (RegName :: atom()) | {RegName :: atom(), Node :: node()},
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
+send_interval(Time, Pid, Message)
+ when ?valid_time(Time),
+ is_pid(Pid) ->
+ req(apply_interval, {system_time(), Time, Pid, {?MODULE, send, [Pid, Message]}});
+send_interval(Time, RegName, Message)
+ when ?valid_time(Time),
+ is_atom(RegName) ->
+ req(apply_interval, {system_time(), Time, RegName, {?MODULE, send, [RegName, Message]}});
+send_interval(Time, Dest = {RegName, Node}, Message)
+ when ?valid_time(Time),
+ is_atom(RegName),
+ is_atom(Node) ->
+ req(apply_interval, {system_time(), Time, Dest, {?MODULE, send, [Dest, Message]}});
+send_interval(_Time, _Pid, _Message) ->
+ {error, badarg}.
+
+-spec send_interval(Time, Message) -> {'ok', TRef} | {'error', Reason}
+ when Time :: time(),
+ Message :: term(),
+ TRef :: tref(),
+ Reason :: term().
send_interval(Time, Message) ->
send_interval(Time, self(), Message).
--spec cancel(TRef) -> {'ok', 'cancel'} | {'error', Reason} when
- TRef :: tref(),
- Reason :: term().
-cancel(BRef) ->
- req(cancel, BRef).
-
--spec sleep(Time) -> 'ok' when
- Time :: timeout().
+-spec cancel(TRef) -> {'ok', 'cancel'} | {'error', Reason}
+ when TRef :: tref(),
+ Reason :: term().
+cancel({instant, Ref})
+ when is_reference(Ref) ->
+ {ok, cancel};
+cancel({send_local, Ref})
+ when is_reference(Ref) ->
+ _ = erlang:cancel_timer(Ref),
+ {ok, cancel};
+cancel({once, Ref} = TRef)
+ when is_reference(Ref) ->
+ req(cancel, TRef);
+cancel({interval, Ref} = TRef)
+ when is_reference(Ref) ->
+ req(cancel, TRef);
+cancel(_TRef) ->
+ {error, badarg}.
+
+-spec sleep(Time) -> 'ok'
+ when Time :: timeout().
+sleep(T)
+ when is_integer(T),
+ T > ?MAX_RECEIVE_AFTER ->
+ receive
+ after ?MAX_RECEIVE_AFTER ->
+ sleep(T - ?MAX_RECEIVE_AFTER)
+ end;
sleep(T) ->
receive
after T -> ok
@@ -157,10 +226,10 @@ sleep(T) ->
%%
%% Measure the execution time (in microseconds) for Fun().
%%
--spec tc(Fun) -> {Time, Value} when
- Fun :: function(),
- Time :: integer(),
- Value :: term().
+-spec tc(Fun) -> {Time, Value}
+ when Fun :: function(),
+ Time :: integer(),
+ Value :: term().
tc(F) ->
T1 = erlang:monotonic_time(),
Val = F(),
@@ -171,11 +240,11 @@ tc(F) ->
%%
%% Measure the execution time (in microseconds) for Fun(Args).
%%
--spec tc(Fun, Arguments) -> {Time, Value} when
- Fun :: function(),
- Arguments :: [term()],
- Time :: integer(),
- Value :: term().
+-spec tc(Fun, Arguments) -> {Time, Value}
+ when Fun :: function(),
+ Arguments :: [term()],
+ Time :: integer(),
+ Value :: term().
tc(F, A) ->
T1 = erlang:monotonic_time(),
Val = apply(F, A),
@@ -186,12 +255,12 @@ tc(F, A) ->
%%
%% Measure the execution time (in microseconds) for an MFA.
%%
--spec tc(Module, Function, Arguments) -> {Time, Value} when
- Module :: module(),
- Function :: atom(),
- Arguments :: [term()],
- Time :: integer(),
- Value :: term().
+-spec tc(Module, Function, Arguments) -> {Time, Value}
+ when Module :: module(),
+ Function :: atom(),
+ Arguments :: [term()],
+ Time :: integer(),
+ Value :: term().
tc(M, F, A) ->
T1 = erlang:monotonic_time(),
Val = apply(M, F, A),
@@ -203,250 +272,252 @@ tc(M, F, A) ->
%% Calculate the time difference (in microseconds) of two
%% erlang:now() timestamps, T2-T1.
%%
--spec now_diff(T2, T1) -> Tdiff when
- T1 :: erlang:timestamp(),
- T2 :: erlang:timestamp(),
- Tdiff :: integer().
+-spec now_diff(T2, T1) -> Tdiff
+ when T1 :: erlang:timestamp(),
+ T2 :: erlang:timestamp(),
+ Tdiff :: integer().
now_diff({A2, B2, C2}, {A1, B1, C1}) ->
((A2-A1)*1000000 + B2-B1)*1000000 + C2-C1.
%%
-%% Convert seconds, minutes etc. to milliseconds.
+%% Convert seconds, minutes etc. to milliseconds.
%%
--spec seconds(Seconds) -> MilliSeconds when
- Seconds :: non_neg_integer(),
- MilliSeconds :: non_neg_integer().
+-spec seconds(Seconds) -> MilliSeconds
+ when Seconds :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
seconds(Seconds) ->
1000*Seconds.
--spec minutes(Minutes) -> MilliSeconds when
- Minutes :: non_neg_integer(),
- MilliSeconds :: non_neg_integer().
+
+-spec minutes(Minutes) -> MilliSeconds
+ when Minutes :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
minutes(Minutes) ->
1000*60*Minutes.
--spec hours(Hours) -> MilliSeconds when
- Hours :: non_neg_integer(),
- MilliSeconds :: non_neg_integer().
+
+-spec hours(Hours) -> MilliSeconds
+ when Hours :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
hours(Hours) ->
1000*60*60*Hours.
--spec hms(Hours, Minutes, Seconds) -> MilliSeconds when
- Hours :: non_neg_integer(),
- Minutes :: non_neg_integer(),
- Seconds :: non_neg_integer(),
- MilliSeconds :: non_neg_integer().
+
+-spec hms(Hours, Minutes, Seconds) -> MilliSeconds
+ when Hours :: non_neg_integer(),
+ Minutes :: non_neg_integer(),
+ Seconds :: non_neg_integer(),
+ MilliSeconds :: non_neg_integer().
hms(H, M, S) ->
hours(H) + minutes(M) + seconds(S).
-%%
+%%
%% Start/init functions
%%
-%% Start is only included because of backward compatibility!
-spec start() -> 'ok'.
start() ->
- ensure_started().
+ {ok, _Pid} = do_start(),
+ ok.
+
+do_start() ->
+ case
+ supervisor:start_child(
+ kernel_sup,
+ #{
+ id => timer_server,
+ start => {?MODULE, start_link, []},
+ restart => permanent,
+ shutdown => 1000,
+ type => worker,
+ modules => [?MODULE]
+ }
+ )
+ of
+ {ok, Pid} ->
+ {ok, Pid};
+ {ok, Pid, _} ->
+ {ok, Pid};
+ {error, {already_started, Pid}} ->
+ {ok, Pid};
+ {error, already_present} ->
+ case supervisor:restart_child(kernel_sup, timer_server) of
+ {ok, Pid} ->
+ {ok, Pid};
+ {error, {already_started, Pid}} ->
+ {ok, Pid}
+ end;
+ Error ->
+ Error
+ end.
-spec start_link() -> {'ok', pid()} | {'error', term()}.
start_link() ->
- gen_server:start_link({local, timer_server}, ?MODULE, [], []).
+ gen_server:start_link({local, timer_server}, ?MODULE, [], []).
--spec init([]) -> {'ok', [], 'infinity'}.
+-spec init([]) -> {'ok', ets:tid()}.
init([]) ->
process_flag(trap_exit, true),
- ?TIMER_TAB = ets:new(?TIMER_TAB, [named_table,ordered_set,protected]),
- ?INTERVAL_TAB = ets:new(?INTERVAL_TAB, [named_table,protected]),
- {ok, [], infinity}.
-
--spec ensure_started() -> 'ok'.
-ensure_started() ->
- case whereis(timer_server) of
- undefined ->
- C = {timer_server, {?MODULE, start_link, []}, permanent, 1000,
- worker, [?MODULE]},
- _ = supervisor:start_child(kernel_safe_sup, C),
- ok;
- _ -> ok
- end.
+ Tab = ets:new(?MODULE, []),
+ {ok, Tab}.
%% server calls
+%% Try sending a call. If it fails with reason noproc,
+%% try starting the timer server and try once again.
req(Req, Arg) ->
- SysTime = system_time(),
- ensure_started(),
- gen_server:call(timer_server, {Req, Arg, SysTime}, infinity).
+ try
+ maybe_req(Req, Arg)
+ catch
+ exit:{noproc, _} ->
+ {ok, _Pid} = do_start(),
+ maybe_req(Req, Arg)
+ end.
-%%
-%% handle_call(Request, From, Timers) ->
-%% {reply, Response, Timers, Timeout}
-%%
-%% Time and Timeout is in milliseconds. Started is in microseconds.
-%%
--type timers() :: term(). % XXX: refine?
-
--spec handle_call(term(), term(), timers()) ->
- {'reply', term(), timers(), timeout()} | {'noreply', timers(), timeout()}.
-handle_call({apply_after, {Time, Op}, Started}, _From, _Ts)
- when is_integer(Time), Time >= 0 ->
- BRef = {Started + 1000*Time, make_ref()},
- Timer = {BRef, timeout, Op},
- ets:insert(?TIMER_TAB, Timer),
- Timeout = timer_timeout(system_time()),
- {reply, {ok, BRef}, [], Timeout};
-handle_call({apply_interval, {Time, To, MFA}, Started}, _From, _Ts)
- when is_integer(Time), Time >= 0 ->
- %% To must be a pid or a registered name
- case get_pid(To) of
- Pid when is_pid(Pid) ->
- catch link(Pid),
- SysTime = system_time(),
- Ref = make_ref(),
- BRef1 = {interval, Ref},
- Interval = Time*1000,
- BRef2 = {Started + Interval, Ref},
- Timer = {BRef2, {repeat, Interval, Pid}, MFA},
- ets:insert(?INTERVAL_TAB, {BRef1,BRef2,Pid}),
- ets:insert(?TIMER_TAB, Timer),
- Timeout = timer_timeout(SysTime),
- {reply, {ok, BRef1}, [], Timeout};
- _ ->
- {reply, {error, badarg}, [], next_timeout()}
- end;
-handle_call({cancel, BRef = {_Time, Ref}, _}, _From, Ts)
- when is_reference(Ref) ->
- delete_ref(BRef),
- {reply, {ok, cancel}, Ts, next_timeout()};
-handle_call({cancel, _BRef, _}, _From, Ts) ->
- {reply, {error, badarg}, Ts, next_timeout()};
-handle_call({apply_after, _, _}, _From, Ts) ->
- {reply, {error, badarg}, Ts, next_timeout()};
-handle_call({apply_interval, _, _}, _From, Ts) ->
- {reply, {error, badarg}, Ts, next_timeout()};
-handle_call(_Else, _From, Ts) -> % Catch anything else
- {noreply, Ts, next_timeout()}.
-
--spec handle_info(term(), timers()) -> {'noreply', timers(), timeout()}.
-handle_info(timeout, Ts) -> % Handle timeouts
- Timeout = timer_timeout(system_time()),
- {noreply, Ts, Timeout};
-handle_info({'EXIT', Pid, _Reason}, Ts) -> % Oops, someone died
- pid_delete(Pid),
- {noreply, Ts, next_timeout()};
-handle_info(_OtherMsg, Ts) -> % Other Msg's
- {noreply, Ts, next_timeout()}.
-
--spec handle_cast(term(), timers()) -> {'noreply', timers(), timeout()}.
-handle_cast(_Req, Ts) -> % Not predicted but handled
- {noreply, Ts, next_timeout()}.
-
--spec terminate(term(), _State) -> 'ok'.
-terminate(_Reason, _State) ->
+maybe_req(Req, Arg) ->
+ gen_server:call(timer_server, {Req, Arg}, infinity).
+
+%% Call handling.
+-spec handle_call(term(), term(), Tab) ->
+ {'reply', term(), Tab} | {'noreply', Tab} when
+ Tab :: ets:tid().
+%% Start a one-shot timer.
+handle_call({apply_once, {Started, Time, MFA}}, _From, Tab) ->
+ Timeout = Started + Time,
+ Reply = try
+ erlang:start_timer(
+ Timeout,
+ self(),
+ {apply_once, MFA},
+ [{abs, true}]
+ )
+ of
+ SRef ->
+ ets:insert(Tab, {SRef, SRef}),
+ {ok, {once, SRef}}
+ catch
+ error:badarg ->
+ {error, badarg}
+ end,
+ {reply, Reply, Tab};
+%% Start an interval timer.
+handle_call({apply_interval, {Started, Time, Pid, MFA}}, _From, Tab) ->
+ NextTimeout = Started + Time,
+ TRef = monitor(process, Pid),
+ Reply = try
+ erlang:start_timer(
+ NextTimeout,
+ self(),
+ {apply_interval, NextTimeout, Time, TRef, MFA},
+ [{abs, true}]
+ )
+ of
+ SRef ->
+ ets:insert(Tab, {TRef, SRef}),
+ {ok, {interval, TRef}}
+ catch
+ error:badarg ->
+ demonitor(TRef, [flush]),
+ {error, badarg}
+ end,
+ {reply, Reply, Tab};
+%% Cancel a one-shot timer.
+handle_call({cancel, {once, TRef}}, _From, Tab) ->
+ _ = remove_timer(TRef, Tab),
+ {reply, {ok, cancel}, Tab};
+%% Cancel an interval timer.
+handle_call({cancel, {interval, TRef}}, _From, Tab) ->
+ _ = case remove_timer(TRef, Tab) of
+ true ->
+ demonitor(TRef, [flush]);
+ false ->
+ ok
+ end,
+ {reply, {ok, cancel}, Tab};
+%% Unexpected.
+handle_call(_Req, _From, Tab) ->
+ {noreply, Tab}.
+
+%% Info handling.
+-spec handle_info(term(), Tab) -> {'noreply', Tab}
+ when Tab :: ets:tid().
+%% One-shot timer timeout.
+handle_info({timeout, TRef, {apply_once, MFA}}, Tab) ->
+ case ets:take(Tab, TRef) of
+ [{TRef, _SRef}] ->
+ do_apply(MFA);
+ [] ->
+ ok
+ end,
+ {noreply, Tab};
+%% Interval timer timeout.
+handle_info({timeout, _, {apply_interval, CurTimeout, Time, TRef, MFA}}, Tab) ->
+ case ets:member(Tab, TRef) of
+ true ->
+ NextTimeout = CurTimeout + Time,
+ SRef = erlang:start_timer(
+ NextTimeout,
+ self(),
+ {apply_interval, NextTimeout, Time, TRef, MFA},
+ [{abs, true}]
+ ),
+ ets:update_element(Tab, TRef, {2, SRef}),
+ do_apply(MFA);
+ false ->
+ ok
+ end,
+ {noreply, Tab};
+%% A process related to an interval timer died.
+handle_info({'DOWN', TRef, process, _Pid, _Reason}, Tab) ->
+ _ = remove_timer(TRef, Tab),
+ {noreply, Tab};
+%% Unexpected.
+handle_info(_Req, Tab) ->
+ {noreply, Tab}.
+
+%% Cast handling.
+-spec handle_cast(term(), Tab) -> {'noreply', Tab}
+ when Tab :: ets:tid().
+%% Unexpected.
+handle_cast(_Req, Tab) ->
+ {noreply, Tab}.
+
+-spec terminate(term(), _Tab) -> 'ok'.
+terminate(_Reason, _Tab) ->
ok.
-spec code_change(term(), State, term()) -> {'ok', State}.
-code_change(_OldVsn, State, _Extra) ->
+code_change(_OldVsn, Tab, _Extra) ->
%% According to the man for gen server no timer can be set here.
- {ok, State}.
-
-%%
-%% timer_timeout(SysTime)
-%%
-%% Apply and remove already timed-out timers. A timer is a tuple
-%% {Time, BRef, Op, MFA}, where Time is in microseconds.
-%% Returns {Timeout, Timers}, where Timeout is in milliseconds.
-%%
-timer_timeout(SysTime) ->
- case ets:first(?TIMER_TAB) of
- '$end_of_table' ->
- infinity;
- {Time, _Ref} when Time > SysTime ->
- Timeout = (Time - SysTime + 999) div 1000,
- %% Returned timeout must fit in a small int
- erlang:min(Timeout, ?MAX_TIMEOUT);
- Key ->
- case ets:lookup(?TIMER_TAB, Key) of
- [{Key, timeout, MFA}] ->
- ets:delete(?TIMER_TAB,Key),
- do_apply(MFA),
- timer_timeout(SysTime);
- [{{Time, Ref}, Repeat = {repeat, Interv, To}, MFA}] ->
- ets:delete(?TIMER_TAB,Key),
- NewTime = Time + Interv,
- %% Update the interval entry (last in table)
- ets:insert(?INTERVAL_TAB,{{interval,Ref},{NewTime,Ref},To}),
- do_apply(MFA),
- ets:insert(?TIMER_TAB, {{NewTime, Ref}, Repeat, MFA}),
- timer_timeout(SysTime)
- end
- end.
-
-%%
-%% delete_ref
-%%
-
-delete_ref(BRef = {interval, _}) ->
- case ets:lookup(?INTERVAL_TAB, BRef) of
- [{_, BRef2, _Pid}] ->
- ets:delete(?INTERVAL_TAB, BRef),
- ets:delete(?TIMER_TAB, BRef2);
- _ -> % TimerReference does not exist, do nothing
- ok
- end;
-delete_ref(BRef) ->
- ets:delete(?TIMER_TAB, BRef).
-
-%%
-%% pid_delete
-%%
-
--spec pid_delete(pid()) -> 'ok'.
-pid_delete(Pid) ->
- IntervalTimerList =
- ets:select(?INTERVAL_TAB,
- [{{'_', '_','$1'},
- [{'==','$1',Pid}],
- ['$_']}]),
- lists:foreach(fun({IntKey, TimerKey, _ }) ->
- ets:delete(?INTERVAL_TAB, IntKey),
- ets:delete(?TIMER_TAB, TimerKey)
- end, IntervalTimerList).
-
-%% Calculate time to the next timeout. Returned timeout must fit in a
-%% small int.
-
--spec next_timeout() -> timeout().
-next_timeout() ->
- case ets:first(?TIMER_TAB) of
- '$end_of_table' ->
- infinity;
- {Time, _} ->
- erlang:min(positive((Time - system_time() + 999) div 1000), ?MAX_TIMEOUT)
+ {ok, Tab}.
+
+%% Remove a timer.
+remove_timer(TRef, Tab) ->
+ case ets:take(Tab, TRef) of
+ [{TRef, SRef}] ->
+ ok = erlang:cancel_timer(SRef, [{async, true}, {info, false}]),
+ true;
+ [] -> % TimerReference does not exist, do nothing
+ false
end.
%% Help functions
-do_apply({M,F,A}) ->
- case {M, F, A} of
- {?MODULE, send, A} ->
- %% If send op. send directly, (faster than spawn)
- catch send(A);
- {erlang, exit, [Name, Reason]} ->
- catch exit(get_pid(Name), Reason);
- _ ->
- %% else spawn process with the operation
- catch spawn(M,F,A)
- end.
-
-positive(X) ->
- erlang:max(X, 0).
+%% If send op. send directly (faster than spawn)
+do_apply({?MODULE, send, A}) ->
+ catch send(A);
+%% If exit op. resolve registered name
+do_apply({erlang, exit, [Name, Reason]}) ->
+ catch exit(get_pid(Name), Reason);
+do_apply({M,F,A}) ->
+ catch spawn(M, F, A).
-%%
-%% system_time() -> time in microseconds
-%%
+%% Get current time in milliseconds,
+%% ceil'ed to the next millisecond.
system_time() ->
- erlang:monotonic_time(1000000).
+ (erlang:monotonic_time(microsecond) + 999) div 1000.
send([Pid, Msg]) ->
Pid ! Msg.
+%% Resolve a registered name.
get_pid(Name) when is_pid(Name) ->
Name;
get_pid(undefined) ->
@@ -455,22 +526,3 @@ get_pid(Name) when is_atom(Name) ->
get_pid(whereis(Name));
get_pid(_) ->
undefined.
-
-%%
-%% get_status() ->
-%% {{TimerTabName,TotalNumTimers},{IntervalTabName,NumIntervalTimers}}
-%%
-%% This function is for test purposes only; it is used by the test suite.
-%% There is a small possibility that there is a mismatch of one entry
-%% between the 2 tables if this call is made when the timer server is
-%% in the middle of a transaction
-
--spec get_status() ->
- {{?TIMER_TAB,non_neg_integer()},{?INTERVAL_TAB,non_neg_integer()}}.
-
-get_status() ->
- Info1 = ets:info(?TIMER_TAB),
- {size,TotalNumTimers} = lists:keyfind(size, 1, Info1),
- Info2 = ets:info(?INTERVAL_TAB),
- {size,NumIntervalTimers} = lists:keyfind(size, 1, Info2),
- {{?TIMER_TAB,TotalNumTimers},{?INTERVAL_TAB,NumIntervalTimers}}.
diff --git a/lib/stdlib/src/unicode.erl b/lib/stdlib/src/unicode.erl
index 7ae5dec878..f9d52d30d3 100644
--- a/lib/stdlib/src/unicode.erl
+++ b/lib/stdlib/src/unicode.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -390,6 +390,8 @@ characters_to_binary_int(ML, InEncoding) ->
fake_stacktrace(Reason, characters_to_binary, [ML, InEncoding])
end.
+-spec fake_stacktrace(term(), atom(), [term()]) -> no_return().
+
fake_stacktrace(Reason, Name, Args) ->
try
error(new_stacktrace, Args)
@@ -442,10 +444,12 @@ characters_to_binary_int(ML, InEncoding, OutEncoding) ->
{error, Accum, [Part]}
end,<<>>),
case Res of
+ Bin when is_binary(Bin) ->
+ Bin;
{incomplete,A,B,_} ->
{incomplete,A,B};
- _ ->
- Res
+ {error, _Converted, _Rest} = Error ->
+ Error
end.
@@ -525,14 +529,7 @@ ml_map([Part|_] = Whole,_,{{Incomplete, _}, Accum}) when is_integer(Part) ->
ml_map([Part|T],Fun,Accum) when is_integer(Part) ->
case Fun(Part,Accum) of
Bin when is_binary(Bin) ->
- case ml_map(T,Fun,Bin) of
- Bin2 when is_binary(Bin2) ->
- Bin2;
- {error, Converted, Rest} ->
- {error, Converted, Rest};
- {incomplete, Converted, Rest,X} ->
- {incomplete, Converted, Rest,X}
- end;
+ ml_map(T,Fun,Bin);
% Can not be incomplete - it's an integer
{error, Converted, Rest} ->
{error, Converted, [Rest|T]}
diff --git a/lib/stdlib/src/uri_string.erl b/lib/stdlib/src/uri_string.erl
index 3060f2bfaa..dbbb835036 100644
--- a/lib/stdlib/src/uri_string.erl
+++ b/lib/stdlib/src/uri_string.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -237,7 +237,10 @@
recompose/1,
resolve/2,
resolve/3,
- transcode/2]).
+ transcode/2,
+ quote/1,
+ quote/2,
+ unquote/1]).
-export_type([error/0,
uri_map/0,
uri_string/0]).
@@ -518,6 +521,29 @@ percent_decode(URI) when is_list(URI) orelse
is_binary(URI) ->
raw_decode(URI).
+-spec quote(Data) -> QuotedData when
+ Data :: unicode:chardata(),
+ QuotedData :: unicode:chardata().
+quote(D) ->
+ encode(D, fun is_unreserved/1).
+
+-spec quote(Data, Safe) -> QuotedData when
+ Data :: unicode:chardata(),
+ Safe :: string(),
+ QuotedData :: unicode:chardata().
+quote(D, Safe) ->
+ UnreservedOrSafe =
+ fun(C) ->
+ is_unreserved(C) orelse lists:member(C, Safe)
+ end,
+ encode(D, UnreservedOrSafe).
+
+-spec unquote(QuotedData) -> Data when
+ QuotedData :: unicode:chardata(),
+ Data :: unicode:chardata().
+unquote(D) ->
+ raw_decode(D).
+
%%-------------------------------------------------------------------------
%% Functions for working with the query part of a URI as a list
%% of key/value pairs.
@@ -2216,8 +2242,9 @@ base10_decode_unicode(<<H,_/binary>>, _, _) ->
normalize_map(URIMap) ->
normalize_path_segment(
normalize_scheme_based(
- normalize_percent_encoding(
- normalize_case(URIMap)))).
+ normalize_undefined_port(
+ normalize_percent_encoding(
+ normalize_case(URIMap))))).
%% 6.2.2.1. Case Normalization
@@ -2357,28 +2384,30 @@ normalize_scheme_based(Map, _, _, _) ->
normalize_http(Map, Port, Path) ->
- M1 = normalize_port(Map, Port, 80),
+ M1 = normalize_default_port(Map, Port, 80),
normalize_http_path(M1, Path).
normalize_https(Map, Port, Path) ->
- M1 = normalize_port(Map, Port, 443),
+ M1 = normalize_default_port(Map, Port, 443),
normalize_http_path(M1, Path).
normalize_ftp(Map, Port) ->
- normalize_port(Map, Port, 21).
+ normalize_default_port(Map, Port, 21).
normalize_ssh_sftp(Map, Port) ->
- normalize_port(Map, Port, 22).
+ normalize_default_port(Map, Port, 22).
normalize_tftp(Map, Port) ->
- normalize_port(Map, Port, 69).
+ normalize_default_port(Map, Port, 69).
-normalize_port(Map, Port, Default) ->
+%% RFC 3986, 3.2.3. Port
+%% RFC 3986, 6.2.3. Scheme-Based Normalization
+normalize_default_port(Map, Port, Default) ->
case Port of
Default ->
maps:remove(port, Map);
@@ -2387,6 +2416,12 @@ normalize_port(Map, Port, Default) ->
end.
+normalize_undefined_port(#{port := undefined} = Map) ->
+ maps:remove(port, Map);
+normalize_undefined_port(#{} = Map) ->
+ Map.
+
+
normalize_http_path(Map, Path) ->
case Path of
"" ->
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index 4c606761ba..c59398a84e 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@
-define(WRITE_BLOCK_SIZE, 8*1024).
%% for debugging, to turn off catch
--define(CATCH, catch).
+-define(CATCH(Expr), (catch (Expr))).
%% Debug.
-define(SHOW_GP_BIT_11(B, F), ok).
@@ -227,7 +227,7 @@ openzip_open(F) ->
openzip_open(F, []).
openzip_open(F, Options) ->
- case ?CATCH do_openzip_open(F, Options) of
+ case ?CATCH(do_openzip_open(F, Options)) of
{ok, OpenZip} ->
{ok, OpenZip};
Error ->
@@ -252,7 +252,7 @@ do_openzip_open(F, Options) ->
%% retrieve all files from an open archive
openzip_get(OpenZip) ->
- case ?CATCH do_openzip_get(OpenZip) of
+ case ?CATCH(do_openzip_get(OpenZip)) of
{ok, Result} -> {ok, Result};
Error -> {error, Error}
end.
@@ -269,7 +269,7 @@ do_openzip_get(_) ->
%% retrieve a file from an open archive
openzip_get(FileName, OpenZip) ->
- case ?CATCH do_openzip_get(FileName, OpenZip) of
+ case ?CATCH(do_openzip_get(FileName, OpenZip)) of
{ok, Result} -> {ok, Result};
Error -> {error, Error}
end.
@@ -372,7 +372,7 @@ unzip(F) -> unzip(F, []).
| {error, {Name :: file:name(), Reason :: term()}}).
unzip(F, Options) ->
- case ?CATCH do_unzip(F, Options) of
+ case ?CATCH(do_unzip(F, Options)) of
{ok, R} -> {ok, R};
Error -> {error, Error}
end.
@@ -452,7 +452,7 @@ zip(F, Files) -> zip(F, Files, []).
| {error, Reason :: term()}).
zip(F, Files, Options) ->
- case ?CATCH do_zip(F, Files, Options) of
+ case ?CATCH(do_zip(F, Files, Options)) of
{ok, R} -> {ok, R};
Error -> {error, Error}
end.
@@ -496,7 +496,7 @@ list_dir(F) -> list_dir(F, []).
Option :: cooked).
list_dir(F, Options) ->
- case ?CATCH do_list_dir(F, Options) of
+ case ?CATCH(do_list_dir(F, Options)) of
{ok, R} -> {ok, R};
Error -> {error, Error}
end.
@@ -521,7 +521,7 @@ t(F) when is_record(F, openzip) -> openzip_t(F);
t(F) -> t(F, fun raw_short_print_info_etc/5).
t(F, RawPrint) ->
- case ?CATCH do_t(F, RawPrint) of
+ case ?CATCH(do_t(F, RawPrint)) of
ok -> ok;
Error -> {error, Error}
end.
@@ -1543,7 +1543,7 @@ get_z_data(?DEFLATED, In0, FileName, CompSize, Input, Output, OpO, Z) ->
Out0 = Output({open, FileName, [write | OpO]}, []),
CRC0 = 0,
{In1, Out1, UncompSize, CRC} = get_z_data_loop(CompSize, 0, In0, Out0, Input, Output, CRC0, Z),
- ?CATCH zlib:inflateEnd(Z),
+ _ = ?CATCH(zlib:inflateEnd(Z)),
Out2 = Output({close, FileName}, Out1),
{Out2, In1, CRC, UncompSize};
get_z_data(?STORED, In0, FileName, CompSize, Input, Output, OpO, _Z) ->
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index bda16c263d..b8e4d89996 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -8,6 +8,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES= \
array_SUITE \
base64_SUITE \
+ base64_property_test_SUITE \
beam_lib_SUITE \
binary_module_SUITE \
binref \
@@ -51,11 +52,13 @@ MODULES= \
log_mf_h_SUITE \
math_SUITE \
ms_transform_SUITE \
+ peer_SUITE \
pool_SUITE \
proc_lib_SUITE \
proplists_SUITE \
qlc_SUITE \
queue_SUITE \
+ queue_property_test_SUITE \
rand_SUITE \
random_SUITE \
re_SUITE \
@@ -100,8 +103,13 @@ MODULES= \
zzz_SUITE
ERTS_MODULES= erts_test_utils
+SASL_MODULES= otp_vsns
-ERL_FILES= $(MODULES:%=%.erl) $(ERTS_MODULES:%=$(ERL_TOP)/erts/emulator/test/%.erl)
+ERL_FILES= $(MODULES:%=%.erl) \
+ $(ERTS_MODULES:%=$(ERL_TOP)/erts/emulator/test/%.erl) \
+ $(SASL_MODULES:%=$(ERL_TOP)/lib/sasl/test/%.erl)
+
+EXTRA_FILES= $(ERL_TOP)/otp_versions.table
# ----------------------------------------------------
# Release directory specification
@@ -112,9 +120,9 @@ RELSYSDIR = $(RELEASE_PATH)/stdlib_test
# FLAGS
# ----------------------------------------------------
-ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/kernel/include \
-I$(ERL_TOP)/lib/stdlib/include
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -126,10 +134,11 @@ COVERFILE=stdlib.cover
# ----------------------------------------------------
make_emakefile:
- $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) $(ERTS_MODULES) \
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
+ $(MODULES) $(ERTS_MODULES) $(SASL_MODULES) \
> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
@@ -149,8 +158,9 @@ release_spec: opt
release_tests_spec: make_emakefile
$(INSTALL_DIR) "$(RELSYSDIR)"
$(INSTALL_DATA) stdlib.spec stdlib_bench.spec error_info.spec $(EMAKEFILE) \
- $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)"
+ $(ERL_FILES) $(COVERFILE) $(EXTRA_FILES) "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
@tar cf - *_SUITE_data property_test | (cd "$(RELSYSDIR)"; tar xf -)
+ $(INSTALL_DATA) $(ERL_TOP)/make/otp_version_tickets "$(RELSYSDIR)/stdlib_SUITE_data"
release_docs_spec:
diff --git a/lib/stdlib/test/base64_property_test_SUITE.erl b/lib/stdlib/test/base64_property_test_SUITE.erl
new file mode 100644
index 0000000000..7717b62767
--- /dev/null
+++ b/lib/stdlib/test/base64_property_test_SUITE.erl
@@ -0,0 +1,86 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(base64_property_test_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-compile([export_all, nowarn_export_all]).
+
+all() ->
+ [
+ encode_case,
+ encode_to_string_case,
+ decode_case,
+ decode_malformed_case,
+ decode_noisy_case,
+ decode_to_string_case,
+ decode_to_string_malformed_case,
+ decode_to_string_noisy_case,
+ mime_decode_case,
+ mime_decode_malformed_case,
+ mime_decode_to_string_case,
+ mime_decode_to_string_malformed_case
+ ].
+
+init_per_suite(Config) ->
+ ct_property_test:init_per_suite(Config).
+
+end_per_suite(Config) ->
+ Config.
+
+encode_case(Config) ->
+ do_proptest(prop_encode, Config).
+
+encode_to_string_case(Config) ->
+ do_proptest(prop_encode_to_string, Config).
+
+decode_case(Config) ->
+ do_proptest(prop_decode, Config).
+
+decode_malformed_case(Config) ->
+ do_proptest(prop_decode_malformed, Config).
+
+decode_noisy_case(Config) ->
+ do_proptest(prop_decode_noisy, Config).
+
+decode_to_string_case(Config) ->
+ do_proptest(prop_decode_to_string, Config).
+
+decode_to_string_malformed_case(Config) ->
+ do_proptest(prop_decode_to_string_malformed, Config).
+
+decode_to_string_noisy_case(Config) ->
+ do_proptest(prop_decode_to_string_noisy, Config).
+
+mime_decode_case(Config) ->
+ do_proptest(prop_mime_decode, Config).
+
+mime_decode_malformed_case(Config) ->
+ do_proptest(prop_mime_decode_malformed, Config).
+
+mime_decode_to_string_case(Config) ->
+ do_proptest(prop_mime_decode_to_string, Config).
+
+mime_decode_to_string_malformed_case(Config) ->
+ do_proptest(prop_mime_decode_to_string_malformed, Config).
+
+do_proptest(Prop, Config) ->
+ ct_property_test:quickcheck(
+ base64_prop:Prop(),
+ Config).
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 097d88c7ec..ef3a615699 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,7 +58,16 @@ init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
- ok.
+ %% Cleanup after strip and strip_add_chunks
+ case code:is_sticky(sofs) of
+ false ->
+ false = code:purge(sofs),
+ {module, sofs} = code:load_file(sofs),
+ code:stick_mod(sofs),
+ ok;
+ true ->
+ ok
+ end.
init_per_group(_GroupName, Config) ->
Config.
@@ -85,7 +94,6 @@ normal(Conf) when is_list(Conf) ->
P0 = pps(),
do_normal(Source, PrivDir, BeamFile, []),
- do_normal(Source, PrivDir, BeamFile, [no_utf8_atoms]),
{ok,_} = compile:file(Source, [{outdir,PrivDir}, no_debug_info]),
{ok, {simple, [{debug_info, {debug_info_v1, erl_abstract_code, {none, _}}}]}} =
@@ -384,22 +392,29 @@ strip(Conf) when is_list(Conf) ->
{ok, [{simple,_},{simple2,_},{make_fun,_},{constant,_}]} =
beam_lib:strip_files([BeamFileD1, BeamFile2D1, BeamFile3D1, BeamFile4D1]),
+ %% strip a complex module
+ OrigSofsPath = code:where_is_file("sofs.beam"),
+ BeamFileSofs = filename:join(PrivDir,"sofs.beam"),
+ file:copy(OrigSofsPath, BeamFileSofs),
+ {ok, {sofs,_}} = beam_lib:strip(BeamFileSofs),
+ code:unstick_mod(sofs),
+ false = code:purge(sofs),
+
%% check that each module can be loaded.
{module, simple} = code:load_abs(filename:rootname(BeamFileD1)),
{module, simple2} = code:load_abs(filename:rootname(BeamFile2D1)),
{module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)),
{module, constant} = code:load_abs(filename:rootname(BeamFile4D1)),
+ {module, sofs} = code:load_abs(filename:rootname(BeamFileSofs)),
%% check that line number information is still present after stripping
{module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
- {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
- (catch lines:t(atom)),
+ Info = get_line_number_info(),
true = code:delete(lines),
false = code:purge(lines),
{ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1),
{module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
- {'EXIT',{badarith,[{lines,t,1,Info}|_]}} =
- (catch lines:t(atom)),
+ Info = get_line_number_info(),
true = (P0 == pps()),
NoOfTables = erlang:system_info(ets_count),
@@ -408,7 +423,12 @@ strip(Conf) when is_list(Conf) ->
Source2D1, BeamFile2D1,
Source3D1, BeamFile3D1,
Source4D1, BeamFile4D1,
- Source5D1, BeamFile5D1]),
+ Source5D1, BeamFile5D1,
+ BeamFileSofs]),
+
+ false = code:purge(sofs),
+ {module, sofs} = code:load_file(sofs),
+ code:stick_mod(sofs),
ok.
strip_add_chunks(Conf) when is_list(Conf) ->
@@ -433,7 +453,7 @@ strip_add_chunks(Conf) when is_list(Conf) ->
compare_chunks(B1, NB1, NBId1),
%% Keep all the extra chunks
- ExtraChunks = ["Abst" , "Dbgi" , "Attr" , "CInf" , "LocT" , "Atom" ],
+ ExtraChunks = ["Abst", "Dbgi", "Attr", "CInf", "LocT", "Atom"],
{ok, {simple, AB1}} = beam_lib:strip(B1, ExtraChunks),
ABId1 = chunk_ids(AB1),
true = length(BId1) == length(ABId1),
@@ -450,20 +470,29 @@ strip_add_chunks(Conf) when is_list(Conf) ->
{ok, [{simple,_},{simple2,_},{make_fun,_},{constant,_}]} =
beam_lib:strip_files([BeamFileD1, BeamFile2D1, BeamFile3D1, BeamFile4D1], ExtraChunks),
+ %% strip a complex module
+ OrigSofsPath = code:where_is_file("sofs.beam"),
+ BeamFileSofs = filename:join(PrivDir,"sofs.beam"),
+ file:copy(OrigSofsPath, BeamFileSofs),
+ {ok, {sofs,_}} = beam_lib:strip(BeamFileSofs, ExtraChunks),
+ code:unstick_mod(sofs),
+ false = code:purge(sofs),
+
%% check that each module can be loaded.
{module, simple} = code:load_abs(filename:rootname(BeamFileD1)),
{module, simple2} = code:load_abs(filename:rootname(BeamFile2D1)),
{module, make_fun} = code:load_abs(filename:rootname(BeamFile3D1)),
{module, constant} = code:load_abs(filename:rootname(BeamFile4D1)),
+ {module, sofs} = code:load_abs(filename:rootname(BeamFileSofs)),
%% check that line number information is still present after stripping
{module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
- {'EXIT',{badarith,[{lines,t,1,Info}|_]}} = (catch lines:t(atom)),
+ Info = get_line_number_info(),
false = code:purge(lines),
true = code:delete(lines),
{ok, {lines,BeamFile5D1}} = beam_lib:strip(BeamFile5D1),
{module, lines} = code:load_abs(filename:rootname(BeamFile5D1)),
- {'EXIT',{badarith,[{lines,t,1,Info}|_]}} = (catch lines:t(atom)),
+ Info = get_line_number_info(),
true = (P0 == pps()),
NoOfTables = erlang:system_info(ets_count),
@@ -472,7 +501,13 @@ strip_add_chunks(Conf) when is_list(Conf) ->
Source2D1, BeamFile2D1,
Source3D1, BeamFile3D1,
Source4D1, BeamFile4D1,
- Source5D1, BeamFile5D1]),
+ Source5D1, BeamFile5D1,
+ BeamFileSofs]),
+
+ false = code:purge(sofs),
+ {module, sofs} = code:load_file(sofs),
+ code:stick_mod(sofs),
+
ok.
otp_6711(Conf) when is_list(Conf) ->
@@ -964,3 +999,13 @@ run_if_crypto_works(Test) ->
{skip,"The crypto application is missing or broken"}
end.
+get_line_number_info() ->
+ %% The stacktrace for operators such a '+' can vary depending on
+ %% whether the JIT is used or not.
+ case catch lines:t(atom) of
+ {'EXIT',{badarith,[{erlang,'+',[atom,1],_},
+ {lines,t,1,Info}|_]}} ->
+ Info;
+ {'EXIT',{badarith,[{lines,t,1,Info}|_]}} ->
+ Info
+ end.
diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl
index a52bda8910..315ae64173 100644
--- a/lib/stdlib/test/c_SUITE.erl
+++ b/lib/stdlib/test/c_SUITE.erl
@@ -180,7 +180,7 @@ ls(Config) when is_list(Config) ->
ok = c:ls(File),
ok = c:ls([[[[File]]]]),
ok = c:ls("no_such_file"),
- ok = c:ls(list_to_atom(code:which(c))),
+ ok = c:ls(code:where_is_file("c.beam")),
ok.
%% Check that c:memory/[0,1] returns consistent results.
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index bea5a217db..1dbbf678fd 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -112,21 +112,23 @@ leap_years(Config) when is_list(Config) ->
last_day_of_the_month(Config) when is_list(Config) ->
check_last_day_of_the_month({?START_YEAR, 1}, {?END_YEAR, 1}).
-%% Tests local_time_to_universal_time_dst for MET.
+%% Tests local_time_to_universal_time_dst for CET/CEST/MET/MEST.
local_time_to_universal_time_dst(Config) when is_list(Config) ->
case os:type() of
{unix,_} ->
case os:cmd("date '+%Z'") of
- "SAST"++_ ->
- {comment, "Spoky time zone with zero-set DST, skipped"};
+ "ME"++_ -> %% covers MET/MEST
+ local_time_to_universal_time_dst_x(Config);
+ "CE"++_ -> %% covers CET/CEST
+ local_time_to_universal_time_dst_x(Config);
_ ->
- local_time_to_universal_time_dst_x(Config)
+ {skip, "This test runs only for MET/MEST/CET/CEST"}
end;
_ ->
local_time_to_universal_time_dst_x(Config)
end.
local_time_to_universal_time_dst_x(Config) when is_list(Config) ->
- %% Assumes MET (UTC+1 / UTC+2(dst)
+ %% Assumes CET (UTC+1 / UTC+2(dst) or MET (same as CET)
LtW = {{2003,01,15},{14,00,00}}, % Winter
UtW = {{2003,01,15},{13,00,00}}, %
UtWd = {{2003,01,15},{12,00,00}}, % dst
@@ -192,15 +194,19 @@ rfc3339(Config) when is_list(Config) ->
Mys = [{unit, microsecond}],
Ns = [{unit, nanosecond}],
S = [{unit, second}],
+ Na = [{unit, native}],
D = [{time_designator, $\s}],
Z = [{offset, "Z"}],
"1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
- "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12t23:20:50.52z", Ms),
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12t23:20:50.52z", Na),
"1985-04-12T21:20:50.520Z" =
test_parse("1985-04-12T23:20:50.52+02:00", Ms),
+ "1985-04-12T21:20:50.520Z" =
+ test_parse("1985-04-12T23:20:50.52+02:00", Na),
"1985-04-12T23:20:50Z" = test_parse("1985-04-12T23:20:50.52Z", S),
"1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Na),
"1985-04-12T23:20:50.520000Z" =
test_parse("1985-04-12t23:20:50.52z", Mys),
"1985-04-12 21:20:50.520000000Z" =
@@ -216,13 +222,15 @@ rfc3339(Config) when is_list(Config) ->
"9999-12-31T23:59:59Z" = do_format_z(253402300799, []),
"9999-12-31T23:59:59.999Z" = do_format_z(253402300799*1000+999, Ms),
+ NaPerSec = erlang:convert_time_unit(1, second, native),
+ "9999-12-31T23:59:59.999Z" = do_format_z(253402300799*NaPerSec+(NaPerSec-1), Na),
"9999-12-31T23:59:59.999999Z" =
- do_format_z(253402300799*1000000+999999, Mys),
+ do_format_z(253402300799*1_000_000+999_999, Mys),
"9999-12-31T23:59:59.999999999Z" =
- do_format_z(253402300799*1000000000+999999999, Ns),
+ do_format_z(253402300799*1_000_000_000+999_999_999, Ns),
{'EXIT', _} = (catch do_format_z(253402300799+1, [])),
{'EXIT', _} = (catch do_parse("9999-12-31T23:59:60Z", [])),
- {'EXIT', _} = (catch do_format_z(253402300799*1000000000+999999999+1, Ns)),
+ {'EXIT', _} = (catch do_format_z(253402300799*1_000_000_000+999_999_999+1, Ns)),
{'EXIT', _} = (catch do_parse("2010-04-11T22:35:41", [])), % OTP-16514
253402300799 = do_parse("9999-12-31T23:59:59Z", []),
@@ -236,6 +244,7 @@ rfc3339(Config) when is_list(Config) ->
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.5Z"),
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.55Z"),
"1970-01-02T00:00:00.550Z" = test_parse("1970-01-01T23:59:60.55Z", Ms),
+ "1970-01-02T00:00:00.550Z" = test_parse("1970-01-01T23:59:60.55Z", Na),
"1970-01-02T00:00:00.550000Z" =
test_parse("1970-01-01T23:59:60.55Z", Mys),
"1970-01-02T00:00:00.550000000Z" =
@@ -263,33 +272,45 @@ rfc3339(Config) when is_list(Config) ->
Str = "2000-01-01T10:02:00+00:02",
Str = do_format(TO, [{offset, 120}]),
"2000-01-01T10:02:00.000+00:02" =
- do_format(TO * 1000, [{offset, 120 * 1000}]++Ms),
+ do_format(TO * 1000, [{offset, 120_000}]++Ms),
"2000-01-01T10:02:00.000000+00:02" =
- do_format(TO * 1000 * 1000, [{offset, 120 * 1000 * 1000}]++Mys),
+ do_format(TO * 1_000_000, [{offset, 120_000_000}]++Mys),
"2000-01-01T10:02:00.000000000+00:02" =
- do_format(TO * 1000 * 1000 * 1000,
- [{offset, 120 * 1000 * 1000 * 1000}]++Ns),
+ do_format(TO * 1_000_000_000,
+ [{offset, 120_000_000_000}]++Ns),
+ "2000-01-01T10:02:00.000+00:02" =
+ do_format(TO * NaPerSec, [{offset, 120 * NaPerSec}]++Na),
+
+ 1656147840 = do_parse("2022-06-25 11:04:00+02", []),
+ 1656155040 = do_parse("2022-06-25 11:04:00-00", []),
+
NStr = "2000-01-01T09:58:00-00:02",
NStr = do_format(TO, [{offset, -120}]),
"2000-01-01T09:58:00.000-00:02" =
- do_format(TO * 1000, [{offset, -120 * 1000}]++Ms),
+ do_format(TO * 1000, [{offset, -120_000}]++Ms),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * NaPerSec, [{offset, -120 * NaPerSec}]++Na),
"2000-01-01T09:58:00.000000-00:02" =
- do_format(TO * 1000 * 1000, [{offset, -120 * 1000 * 1000}]++Mys),
+ do_format(TO * 1_000_000, [{offset, -120_000_000}]++Mys),
"2000-01-01T09:58:00.000000000-00:02" =
- do_format(TO * 1000 * 1000 * 1000,
- [{offset, -120 * 1000 * 1000 * 1000}]++Ns),
+ do_format(TO * 1_000_000_000,
+ [{offset, -120_000_000_000}]++Ns),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * 1000, [{offset, -120_000}]++Ms),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * NaPerSec, [{offset, -120 * NaPerSec}]++Na),
- 543210000 = do_parse("1970-01-01T00:00:00.54321Z", Ns),
- 54321000 = do_parse("1970-01-01T00:00:00.054321Z", Ns),
- 543210 = do_parse("1970-01-01T00:00:00.54321Z", Mys),
+ 543_210_000 = do_parse("1970-01-01T00:00:00.54321Z", Ns),
+ 543_210_00 = do_parse("1970-01-01T00:00:00.054321Z", Ns),
+ 543_210 = do_parse("1970-01-01T00:00:00.54321Z", Mys),
543 = do_parse("1970-01-01T00:00:00.54321Z", Ms),
0 = do_parse("1970-01-01T00:00:00.000001Z", Ms),
1 = do_parse("1970-01-01T00:00:00.000001Z", Mys),
1000 = do_parse("1970-01-01T00:00:00.000001Z", Ns),
0 = do_parse("1970-01-01Q00:00:00.00049Z", Ms),
1 = do_parse("1970-01-01Q00:00:00.0005Z", Ms),
- 6543210 = do_parse("1970-01-01T00:00:06.54321Z", Mys),
+ 6543_210 = do_parse("1970-01-01T00:00:06.54321Z", Mys),
298815132000000 = do_parse("1979-06-21T12:12:12Z", Mys),
-1613826000000000 = do_parse("1918-11-11T11:00:00Z", Mys),
-1613833200000000 = do_parse("1918-11-11T11:00:00+02:00", Mys),
@@ -300,11 +321,11 @@ rfc3339(Config) when is_list(Config) ->
"1970-01-01T00:00:00.001Z" = do_format_z(1, Ms),
"1970-01-01T00:00:00.000001Z" = do_format_z(1, Mys),
"1970-01-01T00:00:00.000000001Z" = do_format_z(1, Ns),
- "1970-01-01T00:00:01.000000Z" = do_format_z(1000000, Mys),
- "1970-01-01T00:00:00.543210Z" = do_format_z(543210, Mys),
+ "1970-01-01T00:00:01.000000Z" = do_format_z(1_000_000, Mys),
+ "1970-01-01T00:00:00.543210Z" = do_format_z(543_210, Mys),
"1970-01-01T00:00:00.543Z" = do_format_z(543, Ms),
- "1970-01-01T00:00:00.543210000Z" = do_format_z(543210000, Ns),
- "1970-01-01T00:00:06.543210Z" = do_format_z(6543210, Mys),
+ "1970-01-01T00:00:00.543210000Z" = do_format_z(543_210_000, Ns),
+ "1970-01-01T00:00:06.543210Z" = do_format_z(6_543_210, Mys),
"1979-06-21T12:12:12.000000Z" = do_format_z(298815132000000, Mys),
"1918-11-11T13:00:00.000000Z" = do_format_z(-1613818800000000, Mys),
ok.
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index 51aa21f919..c50a2d5baf 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -115,9 +115,9 @@ end_per_group(_GroupName, Config) ->
%% OTP-3621
newly_started(Config) when is_list(Config) ->
true = is_alive(),
- {ok, Node} = test_server:start_node(slave1, slave, []),
+ {ok, Peer, Node} = ?CT_PEER(),
[] = rpc:call(Node, dets, all, []),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
basic(Config) when is_list(Config) ->
@@ -153,7 +153,7 @@ open(Config) when is_list(Config) ->
%% Running this test twice means that the Dets server is restarted
%% twice. dets_sup specifies a maximum of 4 restarts in an hour.
%% If this becomes a problem, one should consider running this
- %% test on a slave node.
+ %% test on a peer node.
{Sets, Bags, Dups} = args(Config),
@@ -373,12 +373,7 @@ dirty_mark(Config) when is_list(Config) ->
exit(other_process_dead)
end
end,
- {ok, Node} = test_server:start_node(dets_dirty_mark,
- slave,
- [{linked, false},
- {args, "-pa " ++
- filename:dirname
- (code:which(?MODULE))}]),
+ {ok, Peer, Node} = ?CT_PEER(),
ok = ensure_node(20, Node),
%% io:format("~p~n",[rpc:call(Node, code, get_path, [])]),
%% io:format("~p~n",[rpc:call(Node, file, get_cwd, [])]),
@@ -387,7 +382,7 @@ dirty_mark(Config) when is_list(Config) ->
[?MODULE, dets_dirty_loop, []]),
{ok, Tab} = Call(Pid, [open, Tab, [{file, FName}]]),
[{opel,germany}] = Call(Pid, [read,Tab,opel]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
{ok, Tab} = dets:open_file(Tab,[{file, FName},
{repair,false}]),
ok = dets:close(Tab),
@@ -421,12 +416,7 @@ dirty_mark2(Config) when is_list(Config) ->
exit(other_process_dead)
end
end,
- {ok, Node} = test_server:start_node(dets_dirty_mark2,
- slave,
- [{linked, false},
- {args, "-pa " ++
- filename:dirname
- (code:which(?MODULE))}]),
+ {ok, Peer, Node} = ?CT_PEER(),
ok = ensure_node(20, Node),
Pid = rpc:call(Node,erlang, spawn,
[?MODULE, dets_dirty_loop, []]),
@@ -435,7 +425,7 @@ dirty_mark2(Config) when is_list(Config) ->
timer:sleep(2100),
%% Read something, just to give auto save time to finish.
[{opel,germany}] = Call(Pid, [read,Tab,opel]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
{ok, Tab} = dets:open_file(Tab, [{file, FName}, {repair,false}]),
ok = dets:close(Tab),
file:delete(FName),
diff --git a/lib/stdlib/test/dummy_h.erl b/lib/stdlib/test/dummy_h.erl
index 7a9eb11f98..4fffcd86d8 100644
--- a/lib/stdlib/test/dummy_h.erl
+++ b/lib/stdlib/test/dummy_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
%% Test event handler for gen_event_SUITE.erl
-export([init/1, handle_event/2, handle_call/2, handle_info/2,
- terminate/2]).
+ terminate/2, format_status/1]).
init(make_error) ->
{error, my_error};
@@ -63,6 +63,9 @@ handle_call(hibernate, _State) ->
handle_call(hibernate_later, _State) ->
timer:send_after(1000,sleep),
{ok,later,[]};
+handle_call({delayed_answer, T}, State) ->
+ receive after T -> ok end,
+ {ok, delayed, State};
handle_call(_Query, State) ->
{ok, ok, State}.
@@ -97,3 +100,5 @@ terminate(_Reason, {undef_in_terminate, {Mod, Fun}}) ->
terminate(_Reason, _State) ->
ok.
+format_status(#{ state := _State } = S) ->
+ S#{ state := "dummy1_h handler state" }.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index d9462fc17b..c62f6fa3c1 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,8 @@
otp_8562/1, otp_8665/1, otp_8911/1, otp_10302/1, otp_10820/1,
otp_11728/1, encoding/1, extends/1, function_macro/1,
test_error/1, test_warning/1, otp_14285/1,
- test_if/1,source_name/1,otp_16978/1,otp_16824/1,scan_file/1,file_macro/1]).
+ test_if/1,source_name/1,otp_16978/1,otp_16824/1,scan_file/1,file_macro/1,
+ deterministic_include/1, nondeterministic_include/1]).
-export([epp_parse_erl_form/2]).
@@ -50,6 +51,7 @@ config(data_dir, _) ->
filename:absname("./epp_SUITE_data").
-else.
-include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
-export([init_per_testcase/2, end_per_testcase/2]).
init_per_testcase(_, Config) ->
@@ -70,7 +72,8 @@ all() ->
overload_mac, otp_8388, otp_8470, otp_8562,
otp_8665, otp_8911, otp_10302, otp_10820, otp_11728,
encoding, extends, function_macro, test_error, test_warning,
- otp_14285, test_if, source_name, otp_16978, otp_16824, scan_file, file_macro].
+ otp_14285, test_if, source_name, otp_16978, otp_16824, scan_file, file_macro,
+ deterministic_include, nondeterministic_include].
groups() ->
[{upcase_mac, [], [upcase_mac_1, upcase_mac_2]},
@@ -124,6 +127,64 @@ file_macro(Config) when is_list(Config) ->
"Other source" = FileA = FileB,
ok.
+deterministic_include(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "deterministic_include.erl"),
+ {ok, List} = epp:parse_file(File, [{includes, [DataDir]},
+ {deterministic, true},
+ {source_name, "deterministic_include.erl"}]),
+
+ %% In deterministic mode, only basenames, rather than full paths, should
+ %% be written to the -file() attributes resulting from -include and -include_lib
+ ?assert(lists:any(fun
+ ({attribute,_Anno,file,{"baz.hrl",_Line}}) -> true;
+ (_) -> false
+ end,
+ List),
+ "Expected a basename in the -file attribute resulting from " ++
+ "including baz.hrl in deterministic mode."),
+ ?assert(lists:any(fun
+ ({attribute,_Anno,file,{"file.hrl",_Line}}) -> true;
+ (_) -> false
+ end,
+ List),
+ "Expected a basename in the -file attribute resulting from " ++
+ "including file.hrl in deterministic mode."),
+ ok.
+
+nondeterministic_include(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ File = filename:join(DataDir, "deterministic_include.erl"),
+ {ok, List} = epp:parse_file(File, [{includes, [DataDir]},
+ {source_name, "deterministic_include.erl"}]),
+
+ %% Outside of deterministic mode, full paths, should be written to
+ %% the -file() attributes resulting from -include and -include_lib
+ %% to make debugging easier.
+ %% We don't try to assume what the full absolute path will be in the
+ %% unit test, since that can depend on the environment and how the
+ %% test is executed. Instead, we just look for whether there is
+ %% the parent directory along with the basename at least.
+ IncludeAbsolutePathSuffix = filename:join("include","baz.hrl"),
+ ?assert(lists:any(fun
+ ({attribute,_Anno,file,{IncludePath,_Line}}) ->
+ lists:suffix(IncludeAbsolutePathSuffix,IncludePath);
+ (_) -> false
+ end,
+ List),
+ "Expected an absolute in the -file attribute resulting from " ++
+ "including baz.hrl outside of deterministic mode."),
+ IncludeLibAbsolutePathSuffix = filename:join("include","file.hrl"),
+ ?assert(lists:any(fun
+ ({attribute,_Anno,file,{IncludePath,_line}}) ->
+ lists:suffix(IncludeLibAbsolutePathSuffix,IncludePath);
+ (_) -> false
+ end,
+ List),
+ "Expected an absolute in the -file attribute resulting from " ++
+ "including file.hrl outside of deterministic mode."),
+ 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
@@ -816,7 +877,8 @@ otp_8130(Config) when is_list(Config) ->
"t() -> ?a.\n"),
{ok,Epp} = epp:open(File, []),
PreDefMacs = macs(Epp),
- ['BASE_MODULE','BASE_MODULE_STRING','BEAM','FILE',
+ ['BASE_MODULE','BASE_MODULE_STRING','BEAM',
+ 'FEATURE_AVAILABLE', 'FEATURE_ENABLED','FILE',
'FUNCTION_ARITY','FUNCTION_NAME',
'LINE','MACHINE','MODULE','MODULE_STRING',
'OTP_RELEASE'] = PreDefMacs,
@@ -941,7 +1003,7 @@ ifdef(Config) ->
"-else.\n"
"t() -> a.\n"
"-endif.\n">>,
- {errors,[{{3,1},epp,{bad,else}}],[]}},
+ {errors,[{{3,1},epp,{bad,'else'}}],[]}},
{ifdef_c8,
<<"-ifdef(a).\n"
@@ -1530,20 +1592,20 @@ otp_10820(Config) when is_list(Config) ->
Dir = proplists:get_value(priv_dir, Config),
File = filename:join(Dir, L++".erl"),
C1 = <<"%% coding: utf-8\n -module(any).">>,
- ok = do_otp_10820(File, C1, "+pc latin1"),
- ok = do_otp_10820(File, C1, "+pc unicode"),
+ ok = do_otp_10820(File, C1, ["+pc", "latin1"]),
+ ok = do_otp_10820(File, C1, ["+pc", "unicode"]),
C2 = <<"\n-module(any).">>,
- ok = do_otp_10820(File, C2, "+pc latin1"),
- ok = do_otp_10820(File, C2, "+pc unicode").
+ ok = do_otp_10820(File, C2, ["+pc", "latin1"]),
+ ok = do_otp_10820(File, C2, ["+pc", "unicode"]).
do_otp_10820(File, C, PC) ->
- {ok,Node} = start_node(erl_pp_helper, "+fnu " ++ PC),
+ {ok,Peer,Node} = ?CT_PEER(["+fnu"] ++ PC),
ok = rpc:call(Node, file, write_file, [File, C]),
{ok, Forms} = rpc:call(Node, epp, parse_file, [File, [],[]]),
[{attribute,1,file,{File,1}},
{attribute,2,module,any},
{eof,2}] = unopaque_forms(Forms),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
%% OTP_14285: Unicode atoms.
@@ -1609,8 +1671,9 @@ encoding(Config) when is_list(Config) ->
epp_parse_file(ErlFile, [{default_encoding,latin1}]),
{ok,[{attribute,1,file,_},
{attribute,1,module,encoding},
- {eof,3}],[{encoding,none}]} =
+ {eof,3}],Extra0} =
epp_parse_file(ErlFile, [{default_encoding,latin1},extra]),
+ none = proplists:get_value(encoding, Extra0),
%% Try a latin-1 file with encoding given in a comment.
C2 = <<"-module(encoding).
@@ -1632,16 +1695,20 @@ encoding(Config) when is_list(Config) ->
epp_parse_file(ErlFile, [{default_encoding,utf8}]),
{ok,[{attribute,1,file,_},
{attribute,1,module,encoding},
- {eof,4}],[{encoding,latin1}]} =
+ {eof,4}],Extra1} =
epp_parse_file(ErlFile, [extra]),
+ latin1 = proplists:get_value(encoding, Extra1),
+
{ok,[{attribute,1,file,_},
{attribute,1,module,encoding},
- {eof,4}],[{encoding,latin1}]} =
+ {eof,4}],Extra2} =
epp_parse_file(ErlFile, [{default_encoding,latin1},extra]),
+ latin1 = proplists:get_value(encoding, Extra2),
{ok,[{attribute,1,file,_},
{attribute,1,module,encoding},
- {eof,4}],[{encoding,latin1}]} =
+ {eof,4}],Extra3} =
epp_parse_file(ErlFile, [{default_encoding,utf8},extra]),
+ latin1 = proplists:get_value(encoding, Extra3),
ok.
extends(Config) ->
@@ -1802,7 +1869,7 @@ otp_16824(Config) when is_list(Config) ->
{otp_16824_8,
<<"\n-else\n"
"-endif.">>,
- {errors,[{{3,1},epp,{bad,else}}],[]}},
+ {errors,[{{3,1},epp,{bad,'else'}}],[]}},
{otp_16824_9,
<<"\n-ifndef.\n"
@@ -2010,6 +2077,9 @@ eval_tests(Config, Fun, Tests) ->
F = fun({N,P,Opts,E}, BadL) ->
%% io:format("Testing ~p~n", [P]),
Return = Fun(Config, P, Opts),
+ %% The result should be the same when enabling maybe ... end
+ %% (making 'else' a keyword instead of an atom).
+ Return = Fun(Config, P, [{feature,maybe_expr,enable}|Opts]),
case message_compare(E, Return) of
true ->
case E of
@@ -2032,7 +2102,7 @@ check_test(Config, Test, Opts) ->
PrivDir = proplists:get_value(priv_dir, Config),
File = filename:join(PrivDir, Filename),
ok = file:write_file(File, Test),
- case epp:parse_file(File, [PrivDir], Opts) of
+ case epp:parse_file(File, [{includes, PrivDir}| Opts]) of
{ok,Forms} ->
Errors = [E || E={error,_} <- Forms],
call_format_error([E || {error,E} <- Errors]),
@@ -2107,18 +2177,28 @@ run_test(Config, Test0, Opts0) ->
Opts = [return, {i,PrivDir},{outdir,PrivDir}] ++ Opts0,
{ok, epp_test, []} = compile:file(File, Opts),
AbsFile = filename:rootname(File, ".erl"),
- {module, epp_test} = code:load_abs(AbsFile, epp_test),
- Reply = epp_test:t(),
- code:purge(epp_test),
- Reply.
+
+ case lists:member({feature, maybe_expr, enable}, Opts0) of
+ false ->
+ %% Run in node
+ {module, epp_test} = code:load_abs(AbsFile, epp_test),
+ Reply = epp_test:t(),
+ code:purge(epp_test),
+ Reply;
+ true ->
+ %% Run in peer with maybe_expr enabled
+ {ok, Peer, Node} =
+ ?CT_PEER(#{args => ["-enable-feature","maybe_expr"],
+ connection => 0}),
+ {module, epp_test} =
+ rpc:call(Node, code, load_abs, [AbsFile, epp_test]),
+ Reply = rpc:call(Node, epp_test, t, []),
+ peer:stop(Peer),
+ Reply
+ end.
fail() ->
ct:fail(failed).
message_compare(T, T) ->
T =:= T.
-
-%% +fnu means a peer node has to be started; slave will not do
-start_node(Name, Xargs) ->
- PA = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, peer, [{args, "-pa " ++ PA ++ " " ++ Xargs}]).
diff --git a/lib/stdlib/test/epp_SUITE_data/deterministic_include.erl b/lib/stdlib/test/epp_SUITE_data/deterministic_include.erl
new file mode 100644
index 0000000000..67763b29a0
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/deterministic_include.erl
@@ -0,0 +1,6 @@
+-module(deterministic_include).
+
+-export([]).
+
+-include("include/baz.hrl").
+-include_lib("kernel/include/file.hrl").
diff --git a/lib/stdlib/test/epp_SUITE_data/include/baz.hrl b/lib/stdlib/test/epp_SUITE_data/include/baz.hrl
new file mode 100644
index 0000000000..c0ef7a6e51
--- /dev/null
+++ b/lib/stdlib/test/epp_SUITE_data/include/baz.hrl
@@ -0,0 +1 @@
+-define(BAZ, true).
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 0bf59cf60e..faaa9f727f 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
%% %CopyrightEnd%
-module(erl_eval_SUITE).
+-feature(maybe_expr, enable).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2,
init_per_group/2,end_per_group/2]).
@@ -43,6 +44,7 @@
otp_13228/1,
otp_14826/1,
funs/1,
+ custom_stacktrace/1,
try_catch/1,
eval_expr_5/1,
zero_width/1,
@@ -52,7 +54,8 @@
otp_16439/1,
otp_14708/1,
otp_16545/1,
- otp_16865/1]).
+ otp_16865/1,
+ eep49/1]).
%%
%% Define to run outside of test server
@@ -91,8 +94,9 @@ all() ->
simple_cases, unary_plus, apply_atom, otp_5269,
otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
otp_8133, otp_10622, otp_13228, otp_14826,
- funs, try_catch, eval_expr_5, zero_width,
- eep37, eep43, otp_15035, otp_16439, otp_14708, otp_16545, otp_16865].
+ funs, custom_stacktrace, try_catch, eval_expr_5, zero_width,
+ eep37, eep43, otp_15035, otp_16439, otp_14708, otp_16545, otp_16865,
+ eep49].
groups() ->
[].
@@ -1000,23 +1004,23 @@ otp_14826(_Config) ->
backtrace_check("fun(P) when is_pid(P) -> true end(a).",
function_clause,
[{erl_eval,'-inside-an-interpreted-fun-',[a],[]},
- {erl_eval,eval_fun,6},
+ {erl_eval,eval_fun,8},
?MODULE]),
backtrace_check("B.",
{unbound_var, 'B'},
[{erl_eval,expr,2}, ?MODULE]),
backtrace_check("B.",
{unbound, 'B'},
- [{erl_eval,expr,5}, ?MODULE],
+ [{erl_eval,expr,6}, ?MODULE],
none, none),
backtrace_check("1/0.",
badarith,
[{erlang,'/',[1,0],[]},
- {erl_eval,do_apply,6}]),
+ {erl_eval,do_apply,7}]),
backtrace_catch("catch 1/0.",
badarith,
[{erlang,'/',[1,0],[]},
- {erl_eval,do_apply,6}]),
+ {erl_eval,do_apply,7}]),
check(fun() -> catch exit(foo) end,
"catch exit(foo).",
{'EXIT', foo}),
@@ -1026,33 +1030,33 @@ otp_14826(_Config) ->
backtrace_check("try 1/0 after foo end.",
badarith,
[{erlang,'/',[1,0],[]},
- {erl_eval,do_apply,6}]),
+ {erl_eval,do_apply,7}]),
backtrace_catch("catch (try 1/0 after foo end).",
badarith,
[{erlang,'/',[1,0],[]},
- {erl_eval,do_apply,6}]),
+ {erl_eval,do_apply,7}]),
backtrace_catch("try catch 1/0 after foo end.",
badarith,
[{erlang,'/',[1,0],[]},
- {erl_eval,do_apply,6}]),
+ {erl_eval,do_apply,7}]),
backtrace_check("try a of b -> bar after foo end.",
{try_clause,a},
- [{erl_eval,try_clauses,8}]),
+ [{erl_eval,try_clauses,10}]),
check(fun() -> X = try foo:bar() catch A:B:C -> {A,B} end, X end,
"try foo:bar() catch A:B:C -> {A,B} end.",
{error, undef}),
backtrace_check("C = 4, try foo:bar() catch A:B:C -> {A,B,C} end.",
stacktrace_bound,
- [{erl_eval,check_stacktrace_vars,2},
- {erl_eval,try_clauses,8}],
+ [{erl_eval,check_stacktrace_vars,5},
+ {erl_eval,try_clauses,10}],
none, none),
backtrace_catch("catch (try a of b -> bar after foo end).",
{try_clause,a},
- [{erl_eval,try_clauses,8}]),
+ [{erl_eval,try_clauses,10}]),
backtrace_check("try 1/0 catch exit:a -> foo end.",
badarith,
[{erlang,'/',[1,0],[]},
- {erl_eval,do_apply,6}]),
+ {erl_eval,do_apply,7}]),
Es = [{'try',1,[{call,1,{remote,1,{atom,1,foo},{atom,1,bar}},[]}],
[],
[{clause,1,[{tuple,1,[{var,1,'A'},{var,1,'B'},{atom,1,'C'}]}],
@@ -1062,8 +1066,8 @@ otp_14826(_Config) ->
ct:fail(stacktrace_variable)
catch
error:{illegal_stacktrace_variable,{atom,1,'C'}}:S ->
- [{erl_eval,check_stacktrace_vars,2,_},
- {erl_eval,try_clauses,8,_}|_] = S
+ [{erl_eval,check_stacktrace_vars,5,_},
+ {erl_eval,try_clauses,10,_}|_] = S
end,
backtrace_check("{1,1} = {A = 1, A = 2}.",
{badmatch, 1},
@@ -1073,53 +1077,53 @@ otp_14826(_Config) ->
[{erl_eval,guard0,4}], none, none),
backtrace_check("case a of foo() -> ok end.",
{illegal_pattern,{call,1,{atom,1,foo},[]}},
- [{erl_eval,match,4}], none, none),
+ [{erl_eval,match,6}], none, none),
backtrace_check("case a of b -> ok end.",
{case_clause,a},
- [{erl_eval,case_clauses,6}, ?MODULE]),
+ [{erl_eval,case_clauses,8}, ?MODULE]),
backtrace_check("if a =:= b -> ok end.",
if_clause,
- [{erl_eval,if_clauses,5}, ?MODULE]),
+ [{erl_eval,if_clauses,7}, ?MODULE]),
backtrace_check("fun A(b) -> ok end(a).",
function_clause,
[{erl_eval,'-inside-an-interpreted-fun-',[a],[]},
- {erl_eval,eval_named_fun,8},
+ {erl_eval,eval_named_fun,10},
?MODULE]),
backtrace_check("[A || A <- a].",
{bad_generator, a},
- [{erl_eval,eval_generate,7}, {erl_eval, eval_lc, 6}]),
+ [{erl_eval,eval_generate,8}, {erl_eval, eval_lc, 7}]),
backtrace_check("<< <<A>> || <<A>> <= a>>.",
{bad_generator, a},
- [{erl_eval,eval_b_generate,7}, {erl_eval, eval_bc, 6}]),
+ [{erl_eval,eval_b_generate,8}, {erl_eval, eval_bc, 7}]),
backtrace_check("[A || A <- [1], begin a end].",
{bad_filter, a},
- [{erl_eval,eval_filter,6}, {erl_eval, eval_generate, 7}]),
+ [{erl_eval,eval_filter,7}, {erl_eval, eval_generate, 8}]),
fun() ->
{'EXIT', {{badarity, {_Fun, []}}, BT}} =
(catch parse_and_run("fun(A) -> A end().")),
- check_backtrace([{erl_eval,do_apply,5}, ?MODULE], BT)
+ check_backtrace([{erl_eval,do_apply,6}, ?MODULE], BT)
end(),
fun() ->
{'EXIT', {{badarity, {_Fun, []}}, BT}} =
(catch parse_and_run("fun F(A) -> A end().")),
- check_backtrace([{erl_eval,do_apply,5}, ?MODULE], BT)
+ check_backtrace([{erl_eval,do_apply,6}, ?MODULE], BT)
end(),
backtrace_check("foo().",
undef,
- [{erl_eval,foo,0},{erl_eval,local_func,6}],
+ [{erl_eval,foo,0},{erl_eval,local_func,8}],
none, none),
backtrace_check("a orelse false.",
{badarg, a},
- [{erl_eval,expr,5}, ?MODULE]),
+ [{erl_eval,expr,6}, ?MODULE]),
backtrace_check("a andalso false.",
{badarg, a},
- [{erl_eval,expr,5}, ?MODULE]),
+ [{erl_eval,expr,6}, ?MODULE]),
backtrace_check("t = u.",
{badmatch, u},
- [{erl_eval,expr,5}, ?MODULE]),
+ [{erl_eval,expr,6}, ?MODULE]),
backtrace_check("{math,sqrt}(2).",
{badfun, {math,sqrt}},
- [{erl_eval,expr,5}, ?MODULE]),
+ [{erl_eval,expr,6}, ?MODULE]),
backtrace_check("erl_eval_SUITE:simple().",
simple,
[{?MODULE,simple1,0},{?MODULE,simple,0},erl_eval]),
@@ -1128,31 +1132,39 @@ otp_14826(_Config) ->
"19,20,21,22,23,24,25,26,27,28,29,30) -> a end.",
{argument_limit,
{'fun',1,[{clause,1,Args,[],[{atom,1,a}]}]}},
- [{erl_eval,expr,5}, ?MODULE]),
+ [{erl_eval,expr,6}, ?MODULE]),
backtrace_check("fun F(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,"
"19,20,21,22,23,24,25,26,27,28,29,30) -> a end.",
{argument_limit,
{named_fun,1,'F',[{clause,1,Args,[],[{atom,1,a}]}]}},
- [{erl_eval,expr,5}, ?MODULE]),
+ [{erl_eval,expr,6}, ?MODULE]),
backtrace_check("#r{}.",
{undef_record,r},
- [{erl_eval,expr,5}, ?MODULE],
+ [{erl_eval,expr,6}, ?MODULE],
none, none),
%% eval_bits
backtrace_check("<<100:8/bitstring>>.",
badarg,
- [{eval_bits,eval_exp_field1,6},
+ [{eval_bits,eval_exp_field,6},
eval_bits,eval_bits,erl_eval]),
backtrace_check("<<100:8/foo>>.",
{undefined_bittype,foo},
- [{eval_bits,make_bit_type,3},eval_bits,
+ [{eval_bits,make_bit_type,4},eval_bits,
eval_bits,eval_bits],
none, none),
backtrace_check("B = <<\"foo\">>, <<B/binary-unit:7>>.",
badarg,
- [{eval_bits,eval_exp_field1,6},
+ [{eval_bits,eval_exp_field,6},
eval_bits,eval_bits,erl_eval],
none, none),
+
+ %% eval_bits with error info
+ {error_info, #{cause := _, override_segment_position := 1}} =
+ error_info_catch("<<100:8/bitstring>>.", badarg),
+
+ {error_info, #{cause := _, override_segment_position := 2}} =
+ error_info_catch("<<0:8, 100:8/bitstring>>.", badarg),
+
ok.
simple() ->
@@ -1172,13 +1184,143 @@ simple1() ->
WillNeverHappen -> WillNeverHappen
end.
+custom_stacktrace(Config) when is_list(Config) ->
+ EFH = {value, fun custom_stacktrace_eval_handler/3},
+
+ backtrace_check("1 + atom.", badarith,
+ [{erlang,'+',[1,atom]}, mystack(1)], none, EFH),
+ backtrace_check("\n1 + atom.", badarith,
+ [{erlang,'+',[1,atom]}, mystack(2)], none, EFH),
+
+ backtrace_check("lists:flatten(atom).", function_clause,
+ [{lists,flatten,[atom]}, mystack(1)], none, EFH),
+
+ backtrace_check("invalid andalso true.", {badarg, invalid},
+ [mystack(1)], none, EFH),
+ backtrace_check("invalid orelse true.", {badarg, invalid},
+ [mystack(1)], none, EFH),
+
+ backtrace_check("invalid = valid.", {badmatch, valid},
+ [erl_eval, mystack(1)], none, EFH),
+
+ backtrace_check("1:2.", {badexpr, ':'},
+ [erl_eval, mystack(1)], none, EFH),
+
+ backtrace_check("Unknown.", {unbound, 'Unknown'},
+ [erl_eval, mystack(1)], none, EFH),
+
+ backtrace_check("#unknown{}.", {undef_record,unknown},
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("#unknown{foo=bar}.", {undef_record,unknown},
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("#unknown.index.", {undef_record,unknown},
+ [erl_eval, mystack(1)], none, EFH),
+
+ backtrace_check("fun foo/2.", undef,
+ [{erl_eval, foo, 2}, erl_eval, mystack(1)], none, EFH),
+ backtrace_check("foo(1, 2).", undef,
+ [{erl_eval, foo, 2}, erl_eval, mystack(1)], none, EFH),
+
+ fun() ->
+ {'EXIT', {{badarity, {_Fun, []}}, BT}} =
+ (catch parse_and_run("fun(A) -> A end().", none, EFH)),
+ check_backtrace([erl_eval, mystack(1)], BT)
+ end(),
+
+ fun() ->
+ {'EXIT', {{badarity, {_Fun, []}}, BT}} =
+ (catch parse_and_run("fun F(A) -> A end().", none, EFH)),
+ check_backtrace([erl_eval, mystack(1)], BT)
+ end(),
+
+ backtrace_check("[X || X <- 1].", {bad_generator, 1},
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("[X || <<X>> <= 1].", {bad_generator, 1},
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("<<X || X <- 1>>.", {bad_generator, 1},
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("<<X || <<X>> <= 1>>.", {bad_generator, 1},
+ [erl_eval, mystack(1)], none, EFH),
+
+ backtrace_check("if false -> true end.", if_clause,
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("case 0 of 1 -> true end.", {case_clause, 0},
+ [erl_eval, mystack(1)], none, EFH),
+ backtrace_check("try 0 of 1 -> true after ok end.", {try_clause, 0},
+ [mystack(1)], none, EFH),
+
+ backtrace_check("fun(0) -> 1 end(1).", function_clause,
+ [{erl_eval,'-inside-an-interpreted-fun-', [1]}, erl_eval, mystack(1)],
+ none, EFH),
+ backtrace_check("fun F(0) -> 1 end(1).", function_clause,
+ [{erl_eval,'-inside-an-interpreted-fun-', [1]}, erl_eval, mystack(1)],
+ none, EFH),
+
+ fun() ->
+ {'EXIT', {{illegal_pattern,_}, BT}} =
+ (catch parse_and_run("make_ref() = 1.", none, EFH)),
+ check_backtrace([erl_eval, mystack(1)], BT)
+ end(),
+
+ %% eval_bits
+ backtrace_check("<<100:8/bitstring>>.",
+ badarg,
+ [{eval_bits,eval_exp_field,6}, mystack(1)],
+ none, EFH),
+ backtrace_check("<<100:8/foo>>.",
+ {undefined_bittype,foo},
+ [{eval_bits,make_bit_type,4}, mystack(1)],
+ none, EFH),
+ backtrace_check("B = <<\"foo\">>, <<B/binary-unit:7>>.",
+ badarg,
+ [{eval_bits,eval_exp_field,6}, mystack(1)],
+ none, EFH),
+
+ ok.
+
+mystack(Line) ->
+ {my_module, my_function, 0, [{file, "evaluator"}, {line, Line}]}.
+
+custom_stacktrace_eval_handler(Ann, FunOrModFun, Args) ->
+ try
+ case FunOrModFun of
+ {Mod, Fun} -> apply(Mod, Fun, Args);
+ Fun -> apply(Fun, Args)
+ end
+ catch
+ Kind:Reason:Stacktrace ->
+ %% Take everything up to the evaluation function
+ Pruned =
+ lists:takewhile(fun
+ ({erl_eval_SUITE,backtrace_check,5,_}) -> false;
+ (_) -> true
+ end, Stacktrace),
+ %% Now we prune any shared code path from erl_eval
+ {current_stacktrace, Current} =
+ erlang:process_info(self(), current_stacktrace),
+ Reversed = drop_common(lists:reverse(Current), lists:reverse(Pruned)),
+ Location = [{file, "evaluator"}, {line, erl_anno:line(Ann)}],
+ %% Add our file+line information at the bottom
+ Custom = lists:reverse([{my_module, my_function, 0, Location} | Reversed]),
+ erlang:raise(Kind, Reason, Custom)
+ end.
+
+drop_common([H | T1], [H | T2]) -> drop_common(T1, T2);
+drop_common([H | T1], T2) -> drop_common(T1, T2);
+drop_common([], [{?MODULE, custom_stacktrace_eval_handler, _, _} | T2]) -> T2;
+drop_common([], T2) -> T2.
+
%% Simple cases, just to cover some code.
funs(Config) when is_list(Config) ->
do_funs(none, none),
do_funs(lfh(), none),
+ do_funs(none, efh()),
do_funs(lfh(), efh()),
+ do_funs(none, ann_efh()),
+ do_funs(lfh(), ann_efh()),
error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()),
+ error_check("nix:foo().", {access_not_allowed,nix}, lfh(), ann_efh()),
error_check("bar().", undef, none, none),
check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
@@ -1217,6 +1359,15 @@ funs(Config) when is_list(Config) ->
error_check("apply(timer, sleep, [1]).", got_it, none, EFH),
error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
got_it, none, EFH),
+
+ AnnEF = fun(1, {timer,sleep}, As) when length(As) == 1 -> exit({got_it,sleep});
+ (1, {M,F}, As) -> apply(M, F, As)
+ end,
+ AnnEFH = {value, AnnEF},
+ error_check("apply(timer, sleep, [1]).", got_it, none, AnnEFH),
+ error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
+ got_it, none, AnnEFH),
+
error_check("fun c/1.", undef),
error_check("fun a:b/0().", undef),
@@ -1398,6 +1549,9 @@ local_func_value(F, As) when is_atom(F) ->
efh() ->
{value, fun(F, As) -> external_func(F, As) end}.
+ann_efh() ->
+ {value, fun(_Ann, F, As) -> external_func(F, As) end}.
+
external_func({M,_}, _As) when M == nix ->
exit({{access_not_allowed,M},[mfa]});
external_func(F, As) when is_function(F) ->
@@ -1756,6 +1910,67 @@ otp_16865(Config) when is_list(Config) ->
{badmatch, b}),
ok.
+eep49(Config) when is_list(Config) ->
+ check(fun() ->
+ maybe empty end
+ end,
+ "maybe empty end.",
+ empty),
+ check(fun() ->
+ maybe ok ?= ok end
+ end,
+ "maybe ok ?= ok end.",
+ ok),
+ check(fun() ->
+ maybe {ok,A} ?= {ok,good}, A end
+ end,
+ "maybe {ok,A} ?= {ok,good}, A end.",
+ good),
+ check(fun() ->
+ maybe {ok,A} ?= {ok,good}, {ok,B} ?= {ok,also_good}, {A,B} end
+ end,
+ "maybe {ok,A} ?= {ok,good}, {ok,B} ?= {ok,also_good}, {A,B} end.",
+ {good,also_good}),
+ check(fun() ->
+ maybe {ok,A} ?= {ok,good}, {ok,B} ?= {error,wrong}, {A,B} end
+ end,
+ "maybe {ok,A} ?= {ok,good}, {ok,B} ?= {error,wrong}, {A,B} end.",
+ {error,wrong}),
+
+ %% Test maybe ... else ... end.
+ check(fun() ->
+ maybe empty else _ -> error end
+ end,
+ "maybe empty else _ -> error end.",
+ empty),
+ check(fun() ->
+ maybe ok ?= ok else _ -> error end
+ end,
+ "maybe ok ?= ok else _ -> error end.",
+ ok),
+ check(fun() ->
+ maybe ok ?= other else _ -> error end
+ end,
+ "maybe ok ?= other else _ -> error end.",
+ error),
+ check(fun() ->
+ maybe {ok,A} ?= {ok,good}, {ok,B} ?= {ok,also_good}, {A,B}
+ else {error,_} -> error end
+ end,
+ "maybe {ok,A} ?= {ok,good}, {ok,B} ?= {ok,also_good}, {A,B} "
+ "else {error,_} -> error end.",
+ {good,also_good}),
+ check(fun() ->
+ maybe {ok,A} ?= {ok,good}, {ok,B} ?= {error,other}, {A,B}
+ else {error,_} -> error end
+ end,
+ "maybe {ok,A} ?= {ok,good}, {ok,B} ?= {error,other}, {A,B} "
+ "else {error,_} -> error end.",
+ error),
+ error_check("maybe ok ?= simply_wrong else {error,_} -> error end.",
+ {else_clause,simply_wrong}),
+ ok.
+
%% Check the string in different contexts: as is; in fun; from compiled code.
check(F, String, Result) ->
check1(F, String, Result),
@@ -1869,6 +2084,14 @@ backtrace_catch(String, Result, Backtrace) ->
ct:fail({eval, Other, Result})
end.
+error_info_catch(String, Result) ->
+ case catch parse_and_run(String) of
+ {'EXIT', {Result, [{_, _, _, Info}|_]}} ->
+ lists:keyfind(error_info, 1, Info);
+ Other ->
+ ct:fail({eval, Other, Result})
+ end.
+
check_backtrace([B1|Backtrace], [B2|BT]) ->
case {B1, B2} of
{M, {M,_,_,_}} ->
@@ -1887,15 +2110,26 @@ eval_string(String) ->
Result.
parse_expr(String) ->
- {ok,Tokens,_} = erl_scan:string(String),
+ Tokens = erl_scan_string(String),
{ok, [Expr]} = erl_parse:parse_exprs(Tokens),
Expr.
parse_exprs(String) ->
- {ok,Tokens,_} = erl_scan:string(String),
+ Tokens = erl_scan_string(String),
{ok, Exprs} = erl_parse:parse_exprs(Tokens),
Exprs.
+erl_scan_string(String) ->
+ %% FIXME: When the experimental features EEP has been implemented, we should
+ %% dig out all keywords defined in all features.
+ ResWordFun =
+ fun('maybe') -> true;
+ ('else') -> true;
+ (Other) -> erl_scan:reserved_word(Other)
+ end,
+ {ok,Tokens,_} = erl_scan:string(String, 1, [{reserved_word_fun,ResWordFun}]),
+ Tokens.
+
parse_and_run(String) ->
erl_eval:expr(parse_expr(String), []).
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index ed5b6325fc..ea5cc4a354 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,7 +39,8 @@
-export([attributes/1, expr/1, guard/1,
init/1, pattern/1, strict/1, update/1,
otp_5915/1, otp_7931/1, otp_5990/1,
- otp_7078/1, otp_7101/1, maps/1]).
+ otp_7078/1, otp_7101/1, maps/1,
+ side_effects/1]).
init_per_testcase(_Case, Config) ->
Config.
@@ -53,7 +54,8 @@ suite() ->
all() ->
[attributes, expr, guard, init,
- pattern, strict, update, maps, {group, tickets}].
+ pattern, strict, update, maps,
+ side_effects, {group, tickets}].
groups() ->
[{tickets, [],
@@ -146,6 +148,22 @@ expr(Config) when is_list(Config) ->
is_record(_, _, _) ->
error(wrong_is_record).
+ ">>,
+ <<"
+ -record(foo, {bar = [Bar || Bar <- ?MODULE:id([]), size(Bar) > 0]}).
+
+ t() ->
+ {'EXIT',{{bad_filter,{foo,[]}},[_|_]}} = catch gh6501a(whatever),
+ [whatever] = gh6501b(whatever),
+ ok.
+
+ gh6501a(Bar) ->
+ [Bar || #foo{}].
+
+ gh6501b(Bar) ->
+ [Bar || is_tuple(#foo{})].
+
+ id(I) -> I.
">>
],
@@ -317,7 +335,7 @@ strict(Config) when is_list(Config) ->
ok = try
{1, 2} = {A#r2.a, A#r2.b},
not_ok
- catch error:{badrecord,r2} -> ok
+ catch error:{badrecord,{r1,1,2}} -> ok
end,
try
case foo of
@@ -761,6 +779,30 @@ otp_7101_update3(R) ->
otp_7101_update4(R) ->
R#otp_7101{a=1,b=2}.
+
+-record(side_effects, {a,b,c}).
+
+%% Make sure that the record expression is only evaluated once.
+side_effects(_Config) ->
+ init_counter(),
+
+ {'EXIT',{{badrecord,0},_}} = catch (id(bump_counter()))#side_effects{a=1},
+ 1 = read_counter(),
+
+ {'EXIT',{{badrecord,1},_}} = catch (id(bump_counter()))#side_effects.b,
+ 2 = read_counter(),
+
+ ok.
+
+init_counter() ->
+ put(counter, 0).
+
+bump_counter() ->
+ put(counter, get(counter) + 1).
+
+read_counter() ->
+ get(counter).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
run(Config, Tests) ->
diff --git a/lib/stdlib/test/erl_internal_SUITE.erl b/lib/stdlib/test/erl_internal_SUITE.erl
index 7d9df1f989..5c2d6b0091 100644
--- a/lib/stdlib/test/erl_internal_SUITE.erl
+++ b/lib/stdlib/test/erl_internal_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -80,7 +80,7 @@ callbacks(application) ->
callbacks(gen_server) ->
[{init,1}, {handle_call,3}, {handle_cast,2},
{handle_info,2}, {terminate,2}, {code_change,3},
- {format_status,2}, {handle_continue, 2}];
+ {format_status,1}, {format_status,2}, {handle_continue, 2}];
callbacks(gen_fsm) ->
[{init,1}, {handle_event,3}, {handle_sync_event,4},
{handle_info,3}, {terminate,3}, {code_change,4},
@@ -88,11 +88,11 @@ callbacks(gen_fsm) ->
callbacks(gen_event) ->
[{init,1}, {handle_event,2}, {handle_call,2},
{handle_info,2}, {terminate,2}, {code_change,3},
- {format_status,2}];
+ {format_status,1}, {format_status,2}];
callbacks(gen_statem) ->
[{init, 1}, {callback_mode, 0}, {state_name, 3},
{handle_event, 4}, {terminate, 3}, {code_change, 4},
- {format_status, 2}];
+ {format_status, 1}, {format_status, 2}];
callbacks(supervisor_bridge) ->
[{init,1}, {terminate,2}];
callbacks(supervisor) ->
@@ -101,14 +101,14 @@ callbacks(supervisor) ->
optional_callbacks(application) ->
[];
optional_callbacks(gen_server) ->
- [{handle_info, 2}, {handle_continue, 2}, {terminate, 2}, {code_change, 3}, {format_status, 2}];
+ [{handle_info, 2}, {handle_continue, 2}, {terminate, 2}, {code_change, 3}, {format_status, 1}, {format_status, 2}];
optional_callbacks(gen_fsm) ->
[{handle_info, 3}, {terminate, 3}, {code_change, 4}, {format_status, 2}];
optional_callbacks(gen_event) ->
- [{handle_info, 2}, {terminate, 2}, {code_change, 3}, {format_status, 2}];
+ [{handle_info, 2}, {terminate, 2}, {code_change, 3}, {format_status, 1}, {format_status, 2}];
optional_callbacks(gen_statem) ->
[{state_name, 3}, {handle_event, 4},
- {terminate, 3}, {code_change, 4}, {format_status, 2}];
+ {terminate, 3}, {code_change, 4}, {format_status, 1}, {format_status, 2}];
optional_callbacks(supervisor_bridge) ->
[];
optional_callbacks(supervisor) ->
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index c54efc20c6..770e12e3f0 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,16 +65,20 @@
maps/1,maps_type/1,maps_parallel_match/1,
otp_11851/1,otp_11879/1,otp_13230/1,
record_errors/1, otp_11879_cont/1,
- non_latin1_module/1, otp_14323/1,
+ non_latin1_module/1, illegal_module_name/1, otp_14323/1,
stacktrace_syntax/1,
otp_14285/1, otp_14378/1,
external_funs/1,otp_15456/1,otp_15563/1,
unused_type/1,binary_types/1,removed/1, otp_16516/1,
inline_nifs/1,
+ undefined_nifs/1,
+ no_load_nif/1,
warn_missing_spec/1,
otp_16824/1,
underscore_match/1,
- unused_record/1]).
+ unused_record/1,
+ unused_type2/1,
+ eep49/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -94,11 +98,15 @@ all() ->
too_many_arguments, basic_errors, bin_syntax_errors, predef,
maps, maps_type, maps_parallel_match,
otp_11851, otp_11879, otp_13230,
- record_errors, otp_11879_cont, non_latin1_module, otp_14323,
+ record_errors, otp_11879_cont,
+ non_latin1_module, illegal_module_name, otp_14323,
stacktrace_syntax, otp_14285, otp_14378, external_funs,
otp_15456, otp_15563, unused_type, binary_types, removed, otp_16516,
+ undefined_nifs,
+ no_load_nif,
inline_nifs, warn_missing_spec, otp_16824,
- underscore_match, unused_record].
+ underscore_match, unused_record, unused_type2,
+ eep49].
groups() ->
[{unused_vars_warn, [],
@@ -958,14 +966,13 @@ binary_types(Config) when is_list(Config) ->
Ts = [{binary1,
<<"-type nonempty_binary() :: term().">>,
[nowarn_unused_type],
- {warnings,[{{1,22},erl_lint,
- {new_builtin_type,{nonempty_binary,0}}}]}},
-
+ {errors,[{{1,22},erl_lint,
+ {builtin_type,{nonempty_binary,0}}}],[]}},
{binary2,
<<"-type nonempty_bitstring() :: term().">>,
[nowarn_unused_type],
- {warnings,[{{1,22},erl_lint,
- {new_builtin_type,{nonempty_bitstring,0}}}]}}],
+ {errors,[{{1,22},erl_lint,
+ {builtin_type,{nonempty_bitstring,0}}}],[]}}],
[] = run(Config, Ts),
ok.
@@ -1645,8 +1652,20 @@ guard(Config) when is_list(Config) ->
[],
{error,
[{{2,26},erl_lint,{obsolete_guard_overridden,port}}],
- [{{2,26},erl_lint,{obsolete_guard,{port,1}}}]}}
- ],
+ [{{2,26},erl_lint,{obsolete_guard,{port,1}}}]}},
+ {guard11,
+ <<"-record(bar, {a = mk_a()}).
+ mk_a() -> 1.
+
+ test_rec(Rec) when Rec =:= #bar{} -> true.
+ map_pattern(#{#bar{} := _}) -> ok.
+ ">>,
+ [],
+ {errors,
+ [{{4,43},erl_lint,{illegal_guard_local_call,{mk_a,0}}},
+ {{5,30},erl_lint,{illegal_guard_local_call,{mk_a,0}}}],
+ []}}
+ ],
[] = run(Config, Ts1),
ok.
@@ -3725,7 +3744,10 @@ predef(Config) when is_list(Config) ->
%% dict(), digraph() and so on were removed in Erlang/OTP 18.0.
E2 = get_compilation_result(Config, "predef2", []),
Tag = undefined_type,
- {[{{7,13},erl_lint,{Tag,{array,0}}},
+ {[{{5,2},erl_lint,{Tag,{array,0}}},
+ {{5,2},erl_lint,{Tag,{digraph,0}}},
+ {{5,2},erl_lint,{Tag,{gb_set,0}}},
+ {{7,13},erl_lint,{Tag,{array,0}}},
{{12,12},erl_lint,{Tag,{dict,0}}},
{{17,15},erl_lint,{Tag,{digraph,0}}},
{{27,14},erl_lint,{Tag,{gb_set,0}}},
@@ -4091,9 +4113,10 @@ otp_11879_cont(Config) ->
%% OTP-14285: We currently don't support non-latin1 module names.
non_latin1_module(Config) ->
- do_non_latin1_module('юникод'),
- do_non_latin1_module(list_to_atom([256,$a,$b,$c])),
- do_non_latin1_module(list_to_atom([$a,$b,256,$c])),
+ Expected = [non_latin1_module_unsupported],
+ Expected = check_module_name('юникод'),
+ Expected = check_module_name(list_to_atom([256,$a,$b,$c])),
+ Expected = check_module_name(list_to_atom([$a,$b,256,$c])),
"module names with non-latin1 characters are not supported" =
format_error(non_latin1_module_unsupported),
@@ -4152,16 +4175,48 @@ non_latin1_module(Config) ->
run(Config, Ts),
ok.
-do_non_latin1_module(Mod) ->
+illegal_module_name(_Config) ->
+ [empty_module_name] = check_module_name(''),
+
+ [ctrl_chars_in_module_name] = check_module_name('\x00'),
+ [ctrl_chars_in_module_name] = check_module_name('abc\x1F'),
+ [ctrl_chars_in_module_name] = check_module_name('\x7F'),
+ [ctrl_chars_in_module_name] = check_module_name('abc\x80'),
+ [ctrl_chars_in_module_name] = check_module_name('abc\x80xyz'),
+ [ctrl_chars_in_module_name] = check_module_name('\x9Fxyz'),
+
+ [ctrl_chars_in_module_name,
+ non_latin1_module_unsupported] = check_module_name('атом\x00'),
+
+ [blank_module_name] = check_module_name(' '),
+ [blank_module_name] = check_module_name('\xA0'),
+ [blank_module_name] = check_module_name('\xAD'),
+ [blank_module_name] = check_module_name(' \xA0\xAD '),
+
+ %% White space and soft hyphens are OK if there are visible
+ %% characters in the name.
+ ok = check_module_name(' abc '),
+ ok = check_module_name('abc '),
+ ok = check_module_name(' abc '),
+ ok = check_module_name(' abc xyz '),
+ ok = check_module_name(' abc\xADxyz '),
+
+ ok.
+
+check_module_name(Mod) ->
File = atom_to_list(Mod) ++ ".erl",
L1 = erl_anno:new(1),
Forms = [{attribute,L1,file,{File,1}},
{attribute,L1,module,Mod},
{eof,2}],
- error = compile:forms(Forms),
- {error,_,[]} = compile:forms(Forms, [return]),
- ok.
-
+ _ = compile:forms(Forms),
+ case compile:forms(Forms, [return]) of
+ {error,Errors,[]} ->
+ [{_ModName,L}] = Errors,
+ lists:sort([Reason || {1,erl_lint,Reason} <- L]);
+ {ok,Mod,Code,Ws} when is_binary(Code), is_list(Ws) ->
+ ok
+ end.
otp_14378(Config) ->
Ts = [
@@ -4479,6 +4534,34 @@ inline_nifs(Config) ->
{warnings,[{{2,22},erl_lint,nif_inline}]}}],
[] = run(Config, Ts).
+undefined_nifs(Config) when is_list(Config) ->
+ Ts = [{undefined_nifs,
+ <<"-export([t/0]).
+ -nifs([hej/1]).
+ t() ->
+ erlang:load_nif(\"lib\", []).
+ ">>,
+ [],
+ {errors,[{{2,15},erl_lint,{undefined_nif,{hej,1}}}],[]}}
+ ],
+ [] = run(Config, Ts),
+
+ ok.
+
+no_load_nif(Config) when is_list(Config) ->
+ Ts = [{no_load_nif,
+ <<"-export([t/0]).
+ -nifs([t/0]).
+ t() ->
+ a.
+ ">>,
+ [],
+ {warnings,[{{2,15},erl_lint,no_load_nif}]}}
+ ],
+ [] = run(Config, Ts),
+
+ ok.
+
warn_missing_spec(Config) ->
Test = <<"-export([external_with_spec/0, external_no_spec/0]).
@@ -4631,6 +4714,141 @@ unused_record(Config) when is_list(Config) ->
ok.
+unused_type2(Config) when is_list(Config) ->
+ Ts = [{unused_type2_1,
+ <<"-type t() :: [t()].
+ t() ->
+ a.
+ ">>,
+ {[]},
+ {warnings,[{{1,22},erl_lint,{unused_type,{t,0}}},
+ {{2,15},erl_lint,{unused_function,{t,0}}}]}},
+ {unused_type2_2,
+ <<"-type t1() :: t2().
+ -type t2() :: t1().
+ t() ->
+ a.
+ ">>,
+ {[]},
+ {warnings,[{{1,22},erl_lint,{unused_type,{t1,0}}},
+ {{2,16},erl_lint,{unused_type,{t2,0}}},
+ {{3,16},erl_lint,{unused_function,{t,0}}}]}},
+ {unused_type2_3,
+ <<"-callback cb() -> t().
+ -type t() :: atom().
+ t() ->
+ a.
+ ">>,
+ {[]},
+ {warnings,[{{3,16},erl_lint,{unused_function,{t,0}}}]}},
+ {unused_type2_4,
+ <<"-spec t() -> t().
+ -type t() :: atom().
+ t() ->
+ a.
+ ">>,
+ {[]},
+ {warnings,[{{3,16},erl_lint,{unused_function,{t,0}}}]}},
+ {unused_type2_5,
+ <<"-export_type([t/0]).
+ -type t() :: atom().
+ t() ->
+ a.
+ ">>,
+ {[]},
+ {warnings,[{{3,16},erl_lint,{unused_function,{t,0}}}]}},
+ {unused_type2_6,
+ <<"-record(r, {f :: t()}).
+ -type t() :: atom().
+ t() ->
+ a.
+ ">>,
+ {[]},
+ {warnings,[{{1,22},erl_lint,{unused_record,r}},
+ {{3,16},erl_lint,{unused_function,{t,0}}}]}}
+ ],
+ [] = run(Config, Ts),
+
+ ok.
+
+%% Test maybe ... else ... end.
+eep49(Config) when is_list(Config) ->
+ EnableMaybe = {feature,maybe_expr,enable},
+ Ts = [{exp1,
+ <<"t(X) ->
+ maybe
+ A = X()
+ end,
+ A.
+ ">>,
+ [EnableMaybe],
+ {errors,[{{5,19},erl_lint,{unsafe_var,'A',{'maybe',{2,19}}}}],
+ []}},
+
+ {exp2,
+ <<"t(X) ->
+ maybe
+ A = X()
+ else
+ _ -> {ok,A}
+ end,
+ A.
+ ">>,
+ [EnableMaybe],
+ {errors,[{{5,32},erl_lint,{unsafe_var,'A',{'maybe',{2,19}}}},
+ {{7,19},erl_lint,{unsafe_var,'A',{'maybe',{2,19}}}}],
+ []}},
+
+ {exp3,
+ <<"t(X) ->
+ maybe
+ X()
+ else
+ A ->
+ B = 42,
+ {error,A}
+ end,
+ {A,B}.
+ ">>,
+ [EnableMaybe],
+ {errors,[{{9,20},erl_lint,{unsafe_var,'A',{'else',{4,19}}}},
+ {{9,22},erl_lint,{unsafe_var,'B',{'else',{4,19}}}}],
+ []}},
+
+ {exp4,
+ <<"t(X) ->
+ maybe
+ X()
+ else
+ ok ->
+ A = 42;
+ error ->
+ error
+ end,
+ A.
+ ">>,
+ [EnableMaybe],
+ {errors,[{{10,19},erl_lint,{unsafe_var,'A',{'else',{4,19}}}}],
+ []}},
+
+ %% Using '?=' not at the top-level of a 'maybe' ... 'else' is forbidden.
+ {illegal_maybe_match1,
+ <<"t(X) ->
+ maybe (ok ?= X()) end.
+ ">>,
+ [EnableMaybe],
+ {errors,[{{2,29},erl_parse,["syntax error before: ","'?='"]}],[]}},
+ {illegal_maybe_match2,
+ <<"t(X) ->
+ ok ?= X().
+ ">>,
+ [EnableMaybe],
+ {errors,[{{2,22},erl_parse,["syntax error before: ","'?='"]}],[]}}
+ ],
+
+ [] = run(Config, Ts),
+ ok.
+
format_error(E) ->
lists:flatten(erl_lint:format_error(E)).
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index ce0abd213e..c8c1a206ca 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -48,13 +48,15 @@
neg_indent/1,
maps_syntax/1,
format_options/1,
- quoted_atom_types/1,
+ form_vars/1,
+ quoted_atom_types/1,
otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
otp_10302/1, otp_10820/1, otp_11100/1, otp_11861/1, pr_1014/1,
otp_13662/1, otp_14285/1, otp_15592/1, otp_15751/1, otp_15755/1,
- otp_16435/1]).
+ otp_16435/1, gh_5093/1,
+ eep49/1]).
%% Internal export.
-export([ehook/6]).
@@ -78,14 +80,15 @@ groups() ->
[func, call, recs, try_catch, if_then, receive_after,
bits, head_tail, cond1, block, case1, ops,
messages, maps_syntax, quoted_atom_types,
- format_options
+ format_options, form_vars
]},
{attributes, [], [misc_attrs, import_export, dialyzer_attrs]},
{tickets, [],
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
otp_8473, otp_8522, otp_8567, otp_8664, otp_9147,
otp_10302, otp_10820, otp_11100, otp_11861, pr_1014, otp_13662,
- otp_14285, otp_15592, otp_15751, otp_15755, otp_16435]}].
+ otp_14285, otp_15592, otp_15751, otp_15755, otp_16435,
+ gh_5093, eep49]}].
init_per_suite(Config) ->
Config.
@@ -577,6 +580,37 @@ format_options(Config) when is_list(Config) ->
)
).
+form_vars(Config) when is_list(Config) ->
+ %% Check that erl_pp:legalize_vars/1 does its job. If
+ %% legalize_vars/1 fails to convert variable names starting with a
+ %% lower case letter, the compiler will detect that `X` is an atom
+ %% and report that the `+` operation will fail. If legalize_vars/1
+ %% fails to generate unique variable names and just converts the
+ %% name to uppercase, the variable named `REC0` will be used in an
+ %% unsafe way.
+ String = <<"-module(erl_pp_test).
+ -export([f/1]).
+ -record(r, {a, b}).
+ f(#r{b = B} = C) ->
+ receive
+ B ->
+ X = C#r.a,
+ REC0 = X + X,
+ REC0
+ end.">>,
+ FileName = filename('erl_pp_test.erl', Config),
+ ok = file:write_file(FileName, String),
+ Opts = [binary,deterministic,nowarn_unused_record],
+ {ok, [], Forms} = compile:file(FileName, ['E'|Opts]),
+ Forms1 = lists:map(fun(F={function,_,_,_,_}) ->
+ erl_pp:legalize_vars(F);
+ (F) ->
+ F
+ end, Forms),
+ ok = file:write_file(FileName, [erl_pp:form(F) || F <- Forms1]),
+ {ok, _, _, []} = compile:file(FileName, [return|Opts]),
+ ok.
+
misc_attrs(Config) when is_list(Config) ->
ok = pp_forms(<<"-module(m). ">>),
ok = pp_forms(<<"-module(m, [Aafjlksfjdlsjflsdfjlsdjflkdsfjlk,"
@@ -1085,14 +1119,14 @@ unicode_hook({foo,E}, I, P, H) ->
%% OTP-10820. Unicode filenames.
otp_10820(Config) when is_list(Config) ->
C1 = <<"%% coding: utf-8\n -module(any).">>,
- ok = do_otp_10820(Config, C1, "+pc latin1"),
- ok = do_otp_10820(Config, C1, "+pc unicode"),
+ ok = do_otp_10820(Config, C1, ["+pc", "latin1"]),
+ ok = do_otp_10820(Config, C1, ["+pc", "unicode"]),
C2 = <<"%% coding: latin-1\n -module(any).">>,
- ok = do_otp_10820(Config, C2, "+pc latin1"),
- ok = do_otp_10820(Config, C2, "+pc unicode").
+ ok = do_otp_10820(Config, C2, ["+pc", "latin1"]),
+ ok = do_otp_10820(Config, C2, ["+pc", "unicode"]).
do_otp_10820(Config, C, PC) ->
- {ok,Node} = start_node(erl_pp_helper, "+fnu " ++ PC),
+ {ok,Peer,Node} = ?CT_PEER(["+fnu"] ++ PC),
L = [915,953,959,973,957,953,954,959,957,964],
FileName = filename(L++".erl", Config),
ok = rpc:call(Node, file, write_file, [FileName, C]),
@@ -1100,7 +1134,7 @@ do_otp_10820(Config, C, PC) ->
[FileName, [return,'P',{outdir,?privdir}]]),
PFileName = filename(L++".P", Config),
{ok, Bin} = rpc:call(Node, file, read_file, [PFileName]),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
true = file_attr_is_string(binary_to_list(Bin)),
ok.
@@ -1335,6 +1369,30 @@ otp_16435(_Config) ->
ok.
+gh_5093(_Config) ->
+ assert_same("f() ->\n -1.\n"),
+ assert_same("f() ->\n +1.\n"),
+ assert_same("f() ->\n +1.1.\n"),
+ assert_same("f() ->\n +(+1).\n"),
+ assert_same("f(X) ->\n -X.\n"),
+ assert_same("f(X) ->\n +X.\n"),
+ assert_same("f(X, Y) ->\n X + Y.\n"),
+ assert_same("f(X, Y) ->\n X + +Y.\n"),
+ assert_same("f(X, Y) ->\n X - Y.\n"),
+ ok.
+
+eep49(_Config) ->
+ assert_same("f() ->\n"
+ " maybe ok ?= ok end.\n"),
+ assert_same("f() ->\n"
+ " maybe\n"
+ " ok ?= ok\n"
+ " else\n"
+ " {error, _} ->\n"
+ " error\n"
+ " end.\n"),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compile(Config, Tests) ->
@@ -1430,7 +1488,15 @@ parse_forms(Chars) ->
parse_forms2([], _Cont, _Line, Forms) ->
lists:reverse(Forms);
parse_forms2(String, Cont0, Line, Forms) ->
- case erl_scan:tokens(Cont0, String, Line) of
+ %% FIXME: When the experimental features EEP has been implemented, we should
+ %% dig out all keywords defined in all features.
+ ResWordFun =
+ fun('maybe') -> true;
+ ('else') -> true;
+ (Other) -> erl_scan:reserved_word(Other)
+ end,
+ Options = [{reserved_word_fun,ResWordFun}],
+ case erl_scan:tokens(Cont0, String, Line, Options) of
{done, {ok, Tokens, EndLine}, Chars} ->
{ok, Form} = erl_parse:parse_form(Tokens),
parse_forms2(Chars, [], EndLine, [Form | Forms]);
@@ -1514,7 +1580,9 @@ filename(Name, Config) ->
fail() ->
ct:fail(failed).
-%% +fnu means a peer node has to be started; slave will not do
-start_node(Name, Xargs) ->
- PA = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, peer, [{args, "-pa " ++ PA ++ " " ++ Xargs}]).
+assert_same(Expected) when is_list(Expected) ->
+ Actual = binary_to_list(iolist_to_binary(parse_and_pp_forms(Expected, []))),
+ case Expected == Actual of
+ true -> ok;
+ false -> error({Expected, Actual})
+ end.
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index f853ad7ad7..ee8bc8420f 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,8 @@
init_per_group/2,end_per_group/2]).
-export([error_1/1, error_2/1, iso88591/1, otp_7810/1, otp_10302/1,
- otp_10990/1, otp_10992/1, otp_11807/1, otp_16480/1, otp_17024/1]).
+ otp_10990/1, otp_10992/1, otp_11807/1, otp_16480/1, otp_17024/1,
+ text_fun/1]).
-import(lists, [nth/2,flatten/1]).
-import(io_lib, [print/1]).
@@ -58,7 +59,7 @@ suite() ->
all() ->
[{group, error}, iso88591, otp_7810, otp_10302, otp_10990, otp_10992,
- otp_11807, otp_16480, otp_17024].
+ otp_11807, otp_16480, otp_17024, text_fun].
groups() ->
[{error, [], [error_1, error_2]}].
@@ -1212,6 +1213,79 @@ otp_17024(Config) when is_list(Config) ->
{integer,Location,1} = erl_parse_abstract(1, Opts2),
ok.
+text_fun(Config) when is_list(Config) ->
+ KeepClass = fun(Class) ->
+ fun(C, _) -> C == Class end
+ end,
+
+ Join = fun(L, S) -> string:join(L, S) end,
+ String = fun(L) -> Join(L, " ") end,
+
+ TextAtom = KeepClass(atom),
+ TextInt = KeepClass(integer),
+ %% Keep text for integers written with a base.
+ TextBase = fun(C, S) ->
+ C == integer andalso string:find(S, "#") /= nomatch
+ end,
+ %% Keep text for long strings, regardless of class
+ TextLong = fun(_, S) -> length(S) > 10 end,
+
+ Texts = fun(Toks) -> [erl_scan:text(T) || T <- Toks] end,
+ Values = fun(Toks) -> [erl_scan:symbol(T) || T <- Toks] end,
+
+ Atom1 = "foo",
+ Atom2 = "'this is a long atom'",
+ Int1 = "42",
+ Int2 = "16#10",
+ Int3 = "8#20",
+ Int4 = "16",
+ Int5 = "12345678901234567890",
+ String1 = "\"A String\"",
+ String2 = "\"guitar string\"",
+ Name1 = "Short",
+ Name2 = "LongAndDescriptiveName",
+ Sep1 = "{",
+ Sep2 = "+",
+ Sep3 = "]",
+ Sep4 = "/",
+
+ All = [Atom1, Atom2, Int1, Int2, Int3, Int4, Int5,
+ String1, String2, Name1, Name2,
+ Sep1, Sep2, Sep3, Sep4],
+
+ {ok, Tokens0, 2} =
+ erl_scan:string(String([Atom1, Int1]), 2, [{text_fun, TextAtom}]),
+ [Atom1, undefined] = Texts(Tokens0),
+ [foo, 42] = Values(Tokens0),
+
+ {ok, Tokens1, 3} =
+ erl_scan:string(Join([Int2, Int3, Int4], "\n"), 1,
+ [{text_fun, TextInt}]),
+ [Int2, Int3, Int4] = Texts(Tokens1),
+ [16, 16, 16] = Values(Tokens1),
+
+ TS = [Int2, String1, Atom1, Int3, Int4, String2],
+ {ok, Tokens2, 6} =
+ %% If text is present, we supply text for *all* tokens.
+ erl_scan:string(Join(TS, "\n"), 1, [{text_fun, TextAtom}, text]),
+ TS = Texts(Tokens2),
+ [16, "A String", foo, 16, 16, "guitar string"] = Values(Tokens2),
+
+ Ints = [Int1, Int2, Int3, Int4],
+ {ok, Tokens3, 1} = erl_scan:string(String(Ints), 1, [{text_fun, TextBase}]),
+ [undefined, Int2, Int3, undefined] = Texts(Tokens3),
+ [42, 16, 16, 16] = Values(Tokens3),
+
+ Longs = lists:filter(fun(S) -> length(S) > 10 end, All),
+ {ok, Tokens4, 1} =
+ erl_scan:string(String(All), 1, [{text_fun, TextLong}]),
+ Longs = lists:filter(fun(T) -> T /= undefined end, Texts(Tokens4)),
+
+ {ok, Tokens5, 7} =
+ erl_scan:string(String(All), 7, [{text_fun, KeepClass('{')}]),
+ [Sep1] = lists:filter(fun(T) -> T /= undefined end, Texts(Tokens5)).
+
+
test_string(String, ExpectedWithCol) ->
{ok, ExpectedWithCol, _EndWithCol} = erl_scan_string(String, {1, 1}, []),
Expected = [ begin
diff --git a/lib/stdlib/test/error_info_lib.erl b/lib/stdlib/test/error_info_lib.erl
index 716fa47eb9..22347b6638 100644
--- a/lib/stdlib/test/error_info_lib.erl
+++ b/lib/stdlib/test/error_info_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2021. All Rights Reserved.
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,6 +20,21 @@
-module(error_info_lib).
-export([test_error_info/2, test_error_info/3]).
+%% The wrapper fun should behave as if it was apply/3.
+%% See os_SUITE for an example usage.
+-type wrapper() :: fun((module(),function(),list(term)) -> term()).
+
+%% Options that can be given to testcases
+-type option() :: {integer(), Regexp :: string()} | %% Match argument #1 against RegExp
+ {general, Regexp :: string()} | %% Match general info against RegExp
+ {wrapper, wrapper()} | %% Wrap the test call using this fun
+ {gl, pid()} | %% Use this group leader for the test
+ no_fail | %% The test will not fail
+ allow_rename | %% Allow the exception to not originate from Func
+ unexplained. %% Allow the test to not provide any explanation
+-type test() :: {Func :: function(), Args :: [term()]} |
+ {Func :: function(), Args :: [term()], Opts :: list(option())}.
+-spec test_error_info(module(), list(test())) -> ok.
test_error_info(Module, List) ->
test_error_info(Module, List, []).
@@ -75,7 +90,8 @@ do_error_info([], _Module, Errors0) ->
eval_bif_error(F, Args, Opts, T, Module, Errors0) ->
OldGl = group_leader(),
group_leader(proplists:get_value(gl, Opts, OldGl), self()),
- try apply(Module, F, Args) of
+ Wrapper = proplists:get_value(wrapper, Opts, fun(M, Fun, A) -> apply(M, Fun, A) end),
+ try Wrapper(Module, F, Args) of
Result ->
group_leader(OldGl, self()),
case lists:member(no_fail, Opts) of
diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl
index bf9b6d9ad6..d1f375459b 100644
--- a/lib/stdlib/test/error_logger_h_SUITE.erl
+++ b/lib/stdlib/test/error_logger_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,8 +57,7 @@ logfile(Config) ->
do_one_logfile(Log, Ev, unlimited),
- Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
- {ok,Node} = start_node(logfile, Pa),
+ {ok,Peer,Node} = ?CT_PEER(),
error_logger:logfile({open,Log}),
ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
AtNode = iolist_to_binary(["** at node ",atom_to_list(Node)," **"]),
@@ -79,7 +78,7 @@ logfile(Config) ->
end
end, processes()),
- test_server:stop_node(Node),
+ peer:stop(Peer),
cleanup(Log),
ok.
@@ -119,8 +118,7 @@ tty(Config) ->
do_one_tty(Log, Ev, unlimited),
- Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
- {ok,Node} = start_node(tty, Pa),
+ {ok,Peer,Node} = ?CT_PEER(),
tty_log_open(Log),
ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
tty_log_close(),
@@ -128,7 +126,7 @@ tty(Config) ->
timer:sleep(1000), % some time get all log events in the log
analyse_events(Log, Ev, [AtNode], unlimited),
- test_server:stop_node(Node),
+ peer:stop(Peer),
cleanup(Log),
ok.
@@ -339,14 +337,6 @@ match_head(Tag, Head) ->
"\\d\\d:\\d\\d:\\d\\d ===$">>,
{match,_} = re:run(Head, Re).
-start_node(Name, Args) ->
- case test_server:start_node(Name, slave, [{args,Args}]) of
- {ok,Node} ->
- {ok,Node};
- Error ->
- ct:fail(Error)
- end.
-
cleanup(File) ->
%% The point of this test case is not to test file operations.
%% Therefore ignore any failures.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 588096301d..ffa088543d 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@
-export([match1/1, match2/1, match_object/1, match_object2/1]).
-export([dups/1, misc1/1, safe_fixtable/1, info/1, tab2list/1]).
-export([info_binary_stress/1]).
+-export([info_whereis_busy/1]).
+-export([insert_trap_delete/1, insert_trap_rename/1]).
-export([tab2file/1, tab2file2/1, tabfile_ext1/1,
tabfile_ext2/1, tabfile_ext3/1, tabfile_ext4/1, badfile/1]).
-export([heavy_lookup/1, heavy_lookup_element/1, heavy_concurrent/1]).
@@ -42,13 +44,15 @@
-export([foldl_ordered/1, foldr_ordered/1, foldl/1, foldr/1, fold_empty/1]).
-export([t_delete_object/1, t_init_table/1, t_whitebox/1,
select_bound_chunk/1, t_delete_all_objects/1, t_test_ms/1,
+ t_delete_all_objects_trap/1,
t_select_delete/1,t_select_replace/1,t_select_replace_next_bug/1,
t_select_pam_stack_overflow_bug/1,
t_ets_dets/1]).
-export([t_insert_list/1, t_insert_list_bag/1, t_insert_list_duplicate_bag/1,
t_insert_list_set/1, t_insert_list_delete_set/1,
t_insert_list_parallel/1, t_insert_list_delete_parallel/1,
- t_insert_list_kill_process/1]).
+ t_insert_list_kill_process/1,
+ t_insert_list_insert_order_preserved/1]).
-export([test_table_size_concurrency/1,test_table_memory_concurrency/1,
test_delete_table_while_size_snapshot/1, test_delete_table_while_size_snapshot_helper/1,
test_decentralized_counters_setting/1]).
@@ -131,7 +135,7 @@ end_per_testcase(_Func, _Config) ->
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,5}}].
+ {timetrap,{minutes,30}}].
all() ->
[{group, new}, {group, insert}, {group, lookup},
@@ -149,6 +153,7 @@ all() ->
match_heavy, {group, fold}, member, t_delete_object,
select_bound_chunk,
t_init_table, t_whitebox, t_delete_all_objects,
+ t_delete_all_objects_trap,
t_test_ms, t_select_delete, t_select_replace,
t_select_replace_next_bug,
t_select_pam_stack_overflow_bug,
@@ -173,14 +178,15 @@ all() ->
take,
whereis_table,
delete_unfix_race,
- %test_throughput_benchmark,
- %{group, benchmark},
+ test_throughput_benchmark,
+ {group, benchmark},
test_table_size_concurrency,
test_table_memory_concurrency,
test_delete_table_while_size_snapshot,
test_decentralized_counters_setting,
ms_excessive_nesting,
- error_info].
+ error_info
+ ].
groups() ->
@@ -197,7 +203,7 @@ groups() ->
{match, [],
[match1, match2, match_object, match_object2]},
{misc, [],
- [misc1, safe_fixtable, info, info_binary_stress, dups, tab2list]},
+ [misc1, safe_fixtable, info, info_binary_stress, info_whereis_busy, dups, tab2list]},
{files, [],
[tab2file, tab2file2, tabfile_ext1,
tabfile_ext2, tabfile_ext3, tabfile_ext4, badfile]},
@@ -216,7 +222,10 @@ groups() ->
[t_insert_list, t_insert_list_set, t_insert_list_bag,
t_insert_list_duplicate_bag, t_insert_list_delete_set,
t_insert_list_parallel, t_insert_list_delete_parallel,
- t_insert_list_kill_process]}].
+ t_insert_list_kill_process,
+ t_insert_list_insert_order_preserved,
+ insert_trap_delete,
+ insert_trap_rename]}].
init_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
@@ -265,10 +274,15 @@ end_per_group(benchmark, Config) ->
T = proplists:get_value(ets_benchmark_result_summary_tab, Config),
EtsProcess = proplists:get_value(ets_benchmark_result_summary_tab_process, Config),
Report =
- fun(NOfBenchmarksCtr, TotThroughoutCtr, Name) ->
+ fun(NOfBenchmarksCtr, TotThroughputCtr, Name) ->
Average =
- ets:lookup_element(T, TotThroughoutCtr, 2) /
- ets:lookup_element(T, NOfBenchmarksCtr, 2),
+ case {ets:lookup_element(T, TotThroughputCtr, 2),
+ ets:lookup_element(T, NOfBenchmarksCtr, 2)} of
+ {0.0, 0.0} ->
+ 0;
+ {TotThrp, NBench} ->
+ TotThrp / NBench
+ end,
io:format("~p ~p~n", [Name, Average]),
ct_event:notify(
#event{name = benchmark_data,
@@ -583,12 +597,14 @@ t_repair_continuation(Config) when is_list(Config) ->
repeat_for_opts(fun t_repair_continuation_do/1).
-t_repair_continuation_do(Opts) ->
+t_repair_continuation_do(OptsIn) ->
EtsMem = etsmem(),
MS = [{'_',[],[true]}],
MS2 = [{{{'$1','_'},'_'},[],['$1']}],
- (fun() ->
- T = ets_new(x,[ordered_set|Opts]),
+ run_if_valid_opts(
+ [ordered_set|OptsIn],
+ fun(Opts) ->
+ T = ets_new(x, Opts),
F = fun(0,_)->ok;(N,F) -> ets:insert(T,{N,N}), F(N-1,F) end,
F(1000,F),
{_,C} = ets:select(T,MS,5),
@@ -598,9 +614,11 @@ t_repair_continuation_do(Opts) ->
{[true,true,true,true,true],_} = ets:select(C3),
{[true,true,true,true,true],_} = ets:select(C),
true = ets:delete(T)
- end)(),
- (fun() ->
- T = ets_new(x,[ordered_set|Opts]),
+ end),
+ run_if_valid_opts(
+ [ordered_set|OptsIn],
+ fun(Opts) ->
+ T = ets_new(x, Opts),
F = fun(0,_)->ok;(N,F) -> ets:insert(T,{N,N}), F(N-1,F) end,
F(1000,F),
{_,C} = ets:select(T,MS,1001),
@@ -609,10 +627,12 @@ t_repair_continuation_do(Opts) ->
'$end_of_table' = ets:select(C3),
'$end_of_table' = ets:select(C),
true = ets:delete(T)
- end)(),
+ end),
- (fun() ->
- T = ets_new(x,[ordered_set|Opts]),
+ run_if_valid_opts(
+ [ordered_set|OptsIn],
+ fun(Opts) ->
+ T = ets_new(x, Opts),
F = fun(0,_)->ok;(N,F) ->
ets:insert(T,{integer_to_list(N),N}),
F(N-1,F)
@@ -625,9 +645,11 @@ t_repair_continuation_do(Opts) ->
{[true,true,true,true,true],_} = ets:select(C3),
{[true,true,true,true,true],_} = ets:select(C),
true = ets:delete(T)
- end)(),
- (fun() ->
- T = ets_new(x,[ordered_set|Opts]),
+ end),
+ run_if_valid_opts(
+ [ordered_set|OptsIn],
+ fun(Opts) ->
+ T = ets_new(x, Opts),
F = fun(0,_)->ok;(N,F) ->
ets:insert(T,{{integer_to_list(N),N},N}),
F(N-1,F)
@@ -640,10 +662,10 @@ t_repair_continuation_do(Opts) ->
{[_,_,_,_,_],_} = ets:select(C3),
{[_,_,_,_,_],_} = ets:select(C),
true = ets:delete(T)
- end)(),
+ end),
(fun() ->
- T = ets_new(x,[set|Opts]),
+ T = ets_new(x,[set|OptsIn]),
F = fun(0,_)->ok;(N,F) ->
ets:insert(T,{N,N}),
F(N-1,F)
@@ -658,7 +680,7 @@ t_repair_continuation_do(Opts) ->
true = ets:delete(T)
end)(),
(fun() ->
- T = ets_new(x,[set|Opts]),
+ T = ets_new(x,[set|OptsIn]),
F = fun(0,_)->ok;(N,F) ->
ets:insert(T,{integer_to_list(N),N}),
F(N-1,F)
@@ -673,7 +695,7 @@ t_repair_continuation_do(Opts) ->
true = ets:delete(T)
end)(),
(fun() ->
- T = ets_new(x,[bag|Opts]),
+ T = ets_new(x,[bag|OptsIn]),
F = fun(0,_)->ok;(N,F) ->
ets:insert(T,{integer_to_list(N),N}),
F(N-1,F)
@@ -688,7 +710,7 @@ t_repair_continuation_do(Opts) ->
true = ets:delete(T)
end)(),
(fun() ->
- T = ets_new(x,[duplicate_bag|Opts]),
+ T = ets_new(x,[duplicate_bag|OptsIn]),
F = fun(0,_)->ok;(N,F) ->
ets:insert(T,{integer_to_list(N),N}),
F(N-1,F)
@@ -889,14 +911,19 @@ whitebox_1(Opts) ->
ets:delete(T),
ok.
-whitebox_2(Opts) ->
- T=ets_new(x,[ordered_set, {keypos,2} | Opts]),
- T2=ets_new(x,[set, {keypos,2}| Opts]),
- 0 = ets:select_delete(T,[{{hej},[],[true]}]),
- 0 = ets:select_delete(T,[{{hej,hopp},[],[true]}]),
+whitebox_2(OptsIn) ->
+ run_if_valid_opts(
+ [ordered_set, {keypos,2} | OptsIn],
+ fun (Opts) ->
+ T = ets_new(x, Opts),
+ 0 = ets:select_delete(T,[{{hej},[],[true]}]),
+ 0 = ets:select_delete(T,[{{hej,hopp},[],[true]}]),
+ ets:delete(T)
+ end),
+
+ T2 = ets_new(x,[set, {keypos,2}| OptsIn]),
0 = ets:select_delete(T2,[{{hej},[],[true]}]),
0 = ets:select_delete(T2,[{{hej,hopp},[],[true]}]),
- ets:delete(T),
ets:delete(T2),
ok.
@@ -953,14 +980,14 @@ t_delete_all_objects(Config) when is_list(Config) ->
get_kept_objects(T) ->
case ets:info(T,stats) of
- {_,_,_,_,_,_,KO} ->
+ {_,_,_,_,_,_,KO,_} ->
KO;
_ ->
0
end.
t_delete_all_objects_do(Opts) ->
- KeyRange = 4000,
+ KeyRange = 40_000,
T=ets_new(x, Opts, KeyRange),
filltabint(T,KeyRange),
O=ets:first(T),
@@ -1039,6 +1066,79 @@ inserter(T, Next, Papa) ->
end.
+%% Poke table during delete_all_objects
+t_delete_all_objects_trap(Config) when is_list(Config) ->
+ EtsMem = etsmem(),
+ repeat_for_opts_all_set_table_types(
+ fun(Opts) ->
+ delete_all_objects_trap(Opts, unfix),
+ delete_all_objects_trap(Opts, exit),
+ delete_all_objects_trap(Opts, rename)
+ end),
+ verify_etsmem(EtsMem),
+ ok.
+
+delete_all_objects_trap(Opts, Mode) ->
+ io:format("Opts = ~p\nMode = ~p\n", [Opts, Mode]),
+ Tester = self(),
+ KeyRange = 50_000,
+ TableName = delete_all_objects_trap,
+ {Tref,T} =
+ case Mode of
+ rename ->
+ TableName = ets_new(TableName, [named_table,public|Opts], KeyRange),
+ {ets:whereis(TableName), TableName};
+ _ ->
+ Tid = ets_new(x, Opts, KeyRange),
+ {Tid,Tid}
+ end,
+ filltabint(T, KeyRange),
+ KeyRange = ets:info(T,size),
+ FixerFun =
+ fun() ->
+ erlang:trace(Tester, true, [running]),
+ case Mode of
+ rename -> ok;
+ _ -> ets:safe_fixtable(T, true)
+ end,
+ io:format("Wait for ets:delete_all_objects/1 to yield...\n", []),
+ Tester ! {ready, self()},
+ repeat_while(
+ fun() ->
+ case receive_any() of
+ {trace, Tester, out, {ets,internal_delete_all,2}} ->
+ false;
+ "delete_all_objects done" ->
+ ct:fail("No trap detected");
+ M ->
+ %%io:format("Ignored msg: ~p\n", [M]),
+ true
+ end
+ end),
+ case Mode of
+ unfix ->
+ io:format("Unfix table and then exit...\n",[]),
+ ets:safe_fixtable(T, false);
+ exit ->
+ %%io:format("Exit and do auto-unfix...\n",[]),
+ exit;
+ rename ->
+ %%io:format("Rename table...\n",[]),
+ renamed = ets:rename(T, renamed)
+ end
+ end,
+ {Fixer, Mon} = spawn_opt(FixerFun, [link, monitor]),
+ {ready, Fixer} = receive_any(),
+ true = ets:delete_all_objects(T),
+ Fixer ! "delete_all_objects done",
+ 0 = ets:info(Tref,size),
+ {'DOWN', Mon, process, Fixer, normal} = receive_any(),
+ 0 = get_kept_objects(Tref),
+ false = ets:info(Tref,safe_fixed),
+ ets:delete(Tref),
+ ok.
+
+
%% Test ets:delete_object/2.
t_delete_object(Config) when is_list(Config) ->
EtsMem = etsmem(),
@@ -1063,12 +1163,16 @@ t_delete_object_do(Opts) ->
3999 = ets:info(T,size),
0 = get_kept_objects(T),
ets:delete(T),
- T1 = ets_new(x,[ordered_set | Opts]),
- filltabint(T1,4000),
- del_one_by_one_set(T1,1,4001),
- filltabint(T1,4000),
- del_one_by_one_set(T1,4000,0),
- ets:delete(T1),
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun (Opts1) ->
+ T1 = ets_new(x, Opts1),
+ filltabint(T1,4000),
+ del_one_by_one_set(T1,1,4001),
+ filltabint(T1,4000),
+ del_one_by_one_set(T1,4000,0),
+ ets:delete(T1)
+ end),
T2 = ets_new(x,[bag | Opts]),
filltabint2(T2,4000),
del_one_by_one_bag(T2,1,4001),
@@ -1451,6 +1555,32 @@ t_insert_list_kill_process_do(Opts) ->
fun ets:insert_new/2]],
ok.
+t_insert_list_insert_order_preserved(Config) when is_list(Config) ->
+ insert_list_insert_order_preserved(bag),
+ insert_list_insert_order_preserved(duplicate_bag),
+ ok.
+
+insert_list_insert_order_preserved(Type) ->
+ Tab = ets:new(?FUNCTION_NAME, [Type]),
+ K = a,
+ Values1 = [{K, 1}, {K, 2}, {K, 3}],
+ Values2 = [{K, 4}, {K, 5}, {K, 6}],
+ ets:insert(Tab, Values1),
+ ets:insert(Tab, Values2),
+ [{K, 1}, {K, 2}, {K, 3}, {K, 4}, {K, 5}, {K, 6}] = ets:lookup(Tab, K),
+
+ ets:delete(Tab, K),
+ [] = ets:lookup(Tab, K),
+
+ %% Insert order in duplicate_bag depended on reductions left
+ ITERATIONS_PER_RED = 8,
+ NTuples = 4000 * ITERATIONS_PER_RED + 10,
+ LongList = [{K, V} || V <- lists:seq(1, NTuples)],
+ ets:insert(Tab, LongList),
+ LongList = ets:lookup(Tab, K),
+
+ ets:delete(Tab).
+
%% Test interface of ets:test_ms/2.
t_test_ms(Config) when is_list(Config) ->
EtsMem = etsmem(),
@@ -1906,7 +2036,7 @@ t_select_replace_next_bug(Config) when is_list(Config) ->
%% OTP-17379
-t_select_pam_stack_overflow_bug(Config) ->
+t_select_pam_stack_overflow_bug(_Config) ->
T = ets:new(k, []),
ets:insert(T,[{x,17}]),
[{x,18}] = ets:select(T,[{{x,17}, [], [{{{element,1,'$_'},{const,18}}}]}]),
@@ -2247,11 +2377,16 @@ update_element_opts(Opts) ->
update_element_opts(Tuple,KeyPos,UpdPos,Opts) ->
Set = ets_new(set,[{keypos,KeyPos} | Opts]),
- OrdSet = ets_new(ordered_set,[ordered_set,{keypos,KeyPos} | Opts]),
update_element(Set,Tuple,KeyPos,UpdPos),
- update_element(OrdSet,Tuple,KeyPos,UpdPos),
true = ets:delete(Set),
- true = ets:delete(OrdSet),
+
+ run_if_valid_opts(
+ [ordered_set,{keypos,KeyPos} | Opts],
+ fun (OptsOrdSet) ->
+ OrdSet = ets_new(ordered_set, OptsOrdSet),
+ update_element(OrdSet,Tuple,KeyPos,UpdPos),
+ true = ets:delete(OrdSet)
+ end),
ok.
update_element(T,Tuple,KeyPos,UpdPos) ->
@@ -2336,13 +2471,18 @@ update_tuple([], Tpl) ->
update_element_neg(Opts) ->
Set = ets_new(set,Opts),
- OrdSet = ets_new(ordered_set,[ordered_set | Opts]),
update_element_neg_do(Set),
- update_element_neg_do(OrdSet),
ets:delete(Set),
{'EXIT',{badarg,_}} = (catch ets:update_element(Set,key,{2,1})),
- ets:delete(OrdSet),
- {'EXIT',{badarg,_}} = (catch ets:update_element(OrdSet,key,{2,1})),
+
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun(OptsOrdSet) ->
+ OrdSet = ets_new(ordered_set, OptsOrdSet),
+ update_element_neg_do(OrdSet),
+ ets:delete(OrdSet),
+ {'EXIT',{badarg,_}} = (catch ets:update_element(OrdSet,key,{2,1}))
+ end),
Bag = ets_new(bag,[bag | Opts]),
DBag = ets_new(duplicate_bag,[duplicate_bag | Opts]),
@@ -2393,19 +2533,25 @@ update_counter(Config) when is_list(Config) ->
update_counter_do(Opts) ->
Set = ets_new(set,Opts),
- OrdSet = ets_new(ordered_set,[ordered_set | Opts]),
update_counter_for(Set),
- update_counter_for(OrdSet),
ets:delete_all_objects(Set),
- ets:delete_all_objects(OrdSet),
ets:safe_fixtable(Set, true),
- ets:safe_fixtable(OrdSet, true),
update_counter_for(Set),
- update_counter_for(OrdSet),
ets:safe_fixtable(Set, false),
- ets:safe_fixtable(OrdSet, false),
ets:delete(Set),
- ets:delete(OrdSet),
+
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun (OptsOrdSet) ->
+ OrdSet = ets_new(ordered_set, OptsOrdSet),
+ update_counter_for(OrdSet),
+ ets:delete_all_objects(OrdSet),
+ ets:safe_fixtable(OrdSet, true),
+ update_counter_for(OrdSet),
+ ets:safe_fixtable(OrdSet, false),
+ ets:delete(OrdSet)
+ end),
+
update_counter_neg(Opts).
update_counter_for(T) ->
@@ -2553,13 +2699,18 @@ uc_adder(Init, {_Pos, Add, Thres, Warp}) ->
update_counter_neg(Opts) ->
Set = ets_new(set,Opts),
- OrdSet = ets_new(ordered_set,[ordered_set | Opts]),
update_counter_neg_for(Set),
- update_counter_neg_for(OrdSet),
ets:delete(Set),
{'EXIT',{badarg,_}} = (catch ets:update_counter(Set,key,1)),
- ets:delete(OrdSet),
- {'EXIT',{badarg,_}} = (catch ets:update_counter(OrdSet,key,1)),
+
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun (OptsOrdSet) ->
+ OrdSet = ets_new(ordered_set, OptsOrdSet),
+ update_counter_neg_for(OrdSet),
+ ets:delete(OrdSet),
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(OrdSet,key,1))
+ end),
Bag = ets_new(bag,[bag | Opts]),
DBag = ets_new(duplicate_bag,[duplicate_bag | Opts]),
@@ -2684,39 +2835,43 @@ update_counter_with_default_do(Opts) ->
2 = ets:info(T1, size),
%% Same with ordered set.
- T2 = ets_new(b, [ordered_set | Opts]),
- 3 = ets:update_counter(T2, foo, 2, {maroilles,1}),
- 1 = ets:info(T2, size),
- 5 = ets:update_counter(T2, foo, 2, {mimolette,1}),
- 1 = ets:info(T2, size),
- [9] = ets:update_counter(T2, foo, [{2,4}], {morbier,1}),
- 1 = ets:info(T2, size),
- 3 = ets:update_counter(T2, {foo,bar}, 2, {{laguiole},1}),
- 2 = ets:info(T2, size),
- 5 = ets:update_counter(T2, {foo,bar}, 2, {{saint,nectaire},1}),
- 2 = ets:info(T2, size),
- [9] = ets:update_counter(T2, {foo,bar}, [{2,4}], {{rocamadour},1}),
- 2 = ets:info(T2, size),
- %% Arithmetically-equal keys.
- 3 = ets:update_counter(T2, 1.0, 2, {1,1}),
- 3 = ets:info(T2, size),
- 5 = ets:update_counter(T2, 1, 2, {1,1}),
- 3 = ets:info(T2, size),
- 7 = ets:update_counter(T2, 1, 2, {1.0,1}),
- 3 = ets:info(T2, size),
- %% Same with reversed type difference.
- 3 = ets:update_counter(T2, 2, 2, {2.0,1}),
- 4 = ets:info(T2, size),
- 5 = ets:update_counter(T2, 2.0, 2, {2.0,1}),
- 4 = ets:info(T2, size),
- 7 = ets:update_counter(T2, 2.0, 2, {2,1}),
- 4 = ets:info(T2, size),
- %% default counter is not an integer.
- {'EXIT',{badarg,_}} = (catch ets:update_counter(T1, qux, 3, {saint,félicien})),
- 4 = ets:info(T2, size),
- %% No third element in default value.
- {'EXIT',{badarg,_}} = (catch ets:update_counter(T1, qux, [{3,1}], {roquefort,1})),
- 4 = ets:info(T2, size),
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun (Opts2) ->
+ T2 = ets_new(b, Opts2),
+ 3 = ets:update_counter(T2, foo, 2, {maroilles,1}),
+ 1 = ets:info(T2, size),
+ 5 = ets:update_counter(T2, foo, 2, {mimolette,1}),
+ 1 = ets:info(T2, size),
+ [9] = ets:update_counter(T2, foo, [{2,4}], {morbier,1}),
+ 1 = ets:info(T2, size),
+ 3 = ets:update_counter(T2, {foo,bar}, 2, {{laguiole},1}),
+ 2 = ets:info(T2, size),
+ 5 = ets:update_counter(T2, {foo,bar}, 2, {{saint,nectaire},1}),
+ 2 = ets:info(T2, size),
+ [9] = ets:update_counter(T2, {foo,bar}, [{2,4}], {{rocamadour},1}),
+ 2 = ets:info(T2, size),
+ %% Arithmetically-equal keys.
+ 3 = ets:update_counter(T2, 1.0, 2, {1,1}),
+ 3 = ets:info(T2, size),
+ 5 = ets:update_counter(T2, 1, 2, {1,1}),
+ 3 = ets:info(T2, size),
+ 7 = ets:update_counter(T2, 1, 2, {1.0,1}),
+ 3 = ets:info(T2, size),
+ %% Same with reversed type difference.
+ 3 = ets:update_counter(T2, 2, 2, {2.0,1}),
+ 4 = ets:info(T2, size),
+ 5 = ets:update_counter(T2, 2.0, 2, {2.0,1}),
+ 4 = ets:info(T2, size),
+ 7 = ets:update_counter(T2, 2.0, 2, {2,1}),
+ 4 = ets:info(T2, size),
+ %% default counter is not an integer.
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T2, qux, 3, {saint,félicien})),
+ 4 = ets:info(T2, size),
+ %% No third element in default value.
+ {'EXIT',{badarg,_}} = (catch ets:update_counter(T2, qux, [{3,1}], {roquefort,1})),
+ 4 = ets:info(T2, size)
+ end),
ok.
%% ERL-1125
@@ -2740,8 +2895,14 @@ update_counter_table_growth(_Config) ->
update_counter_table_growth_do(Opts) ->
Set = ets_new(b, [set | Opts]),
[ets:update_counter(Set, N, {2, 1}, {N, 1}) || N <- lists:seq(1,10000)],
- OrderedSet = ets_new(b, [ordered_set | Opts]),
- [ets:update_counter(OrderedSet, N, {2, 1}, {N, 1}) || N <- lists:seq(1,10000)],
+
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun(OptsOrdSet) ->
+ OrdSet = ets_new(b, OptsOrdSet),
+ [ets:update_counter(OrdSet, N, {2, 1}, {N, 1})
+ || N <- lists:seq(1,10000)]
+ end),
ok.
%% Check that a first-next sequence always works on a fixed table.
@@ -2994,8 +3155,9 @@ write_concurrency(Config) when is_list(Config) ->
YesTreeMem = ets:info(Yes7,memory),
YesYesTreeMem = ets:info(Yes14,memory),
NoTreeMem = ets:info(No4,memory),
- io:format("YesMem=~p NoHashMem=~p NoTreeMem=~p YesTreeMem=~p\n",[YesMem,NoHashMem,
- NoTreeMem,YesTreeMem]),
+
+ io:format("YesMem=~p NoHashMem=~p NoTreeMem=~p YesTreeMem=~p YesYesTreeMem=~p\n",
+ [YesMem,NoHashMem,NoTreeMem,YesTreeMem,YesYesTreeMem]),
YesMem = ets:info(Yes2,memory),
YesMem = ets:info(Yes3,memory),
@@ -3020,14 +3182,26 @@ write_concurrency(Config) when is_list(Config) ->
true = YesMem > YesTreeMem,
- case erlang:system_info(schedulers) > 1 of
- true ->
+ case erlang:system_info(schedulers) of
+ 1 ->
+ YesMem = NoHashMem,
+ YesTreeMem = NoTreeMem,
+ YesYesTreeMem = YesTreeMem;
+ NoSchedulers ->
true = YesMem > NoHashMem,
true = YesMem > NoTreeMem,
- true = YesTreeMem < NoTreeMem,
- true = YesYesTreeMem > YesTreeMem;
- _ ->
- one_scheduler_only
+
+ %% The memory of ordered_set with write concurrency is
+ %% smaller than without write concurrency on 64-bit systems with
+ %% few schedulers.
+ Bits = 8*erlang:system_info(wordsize),
+ if Bits =:= 32;
+ NoSchedulers > 6 ->
+ true = YesTreeMem >= NoTreeMem;
+ true ->
+ true = YesTreeMem < NoTreeMem
+ end,
+ true = YesYesTreeMem > YesTreeMem
end,
{'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,foo}])),
@@ -3511,7 +3685,8 @@ interface_equality(Config) when is_list(Config) ->
interface_equality_do(Opts) ->
EtsMem = etsmem(),
Set = ets_new(set,[set | Opts]),
- OrderedSet = ets_new(ordered_set,[ordered_set | Opts]),
+ OrderedSet = ets_new(ordered_set,
+ replace_dbg_hash_fixed_nr_of_locks([ordered_set | Opts])),
F = fun(X,T,FF) -> case X of
0 -> true;
_ ->
@@ -3570,7 +3745,7 @@ maybe_sort(Any) ->
%% Test match, match_object and match_delete in ordered set's.
ordered_match(Config) when is_list(Config)->
- repeat_for_opts(fun ordered_match_do/1).
+ repeat_for_opts_extra_opt(fun ordered_match_do/1, ordered_set).
ordered_match_do(Opts) ->
EtsMem = etsmem(),
@@ -3616,7 +3791,7 @@ ordered_match_do(Opts) ->
%% Test basic functionality in ordered_set's.
ordered(Config) when is_list(Config) ->
- repeat_for_opts(fun ordered_do/1).
+ repeat_for_opts_extra_opt(fun ordered_do/1, ordered_set).
ordered_do(Opts) ->
EtsMem = etsmem(),
@@ -4053,8 +4228,16 @@ delete_large_tab(Config) when is_list(Config) ->
delete_large_tab_do(Config, Opts,Data) ->
delete_large_tab_1(Config, foo_hash, Opts, Data, false),
- delete_large_tab_1(Config, foo_tree, [ordered_set | Opts], Data, false),
- delete_large_tab_1(Config, foo_tree, [stim_cat_ord_set | Opts], Data, false),
+ run_if_valid_opts(
+ [ordered_set | Opts],
+ fun(OptsOrdSet) ->
+ delete_large_tab_1(Config, foo_tree, OptsOrdSet, Data, false)
+ end),
+ run_if_valid_opts(
+ [stim_cat_ord_set | Opts],
+ fun(OptsCat) ->
+ delete_large_tab_1(Config, foo_tree, OptsCat, Data, false)
+ end),
delete_large_tab_1(Config, foo_hash_fix, Opts, Data, true).
@@ -4143,8 +4326,16 @@ delete_large_named_table(Config) when is_list(Config) ->
delete_large_named_table_do(Opts,Data) ->
delete_large_named_table_1(foo_hash, [named_table | Opts], Data, false),
- delete_large_named_table_1(foo_tree, [ordered_set,named_table | Opts], Data, false),
- delete_large_named_table_1(foo_tree, [stim_cat_ord_set,named_table | Opts], Data, false),
+ run_if_valid_opts(
+ [ordered_set,named_table | Opts],
+ fun(OptsOrdSet) ->
+ delete_large_named_table_1(foo_tree, OptsOrdSet, Data, false)
+ end),
+ run_if_valid_opts(
+ [stim_cat_ord_set,named_table | Opts],
+ fun(OptsStimCat) ->
+ delete_large_named_table_1(foo_tree, OptsStimCat, Data, false)
+ end),
delete_large_named_table_1(foo_hash, [named_table | Opts], Data, true).
delete_large_named_table_1(Name, Flags, Data, Fix) ->
@@ -4316,15 +4507,39 @@ exit_many_tables_owner(Config) when is_list(Config) ->
exit_many_many_tables_owner(Config) when is_list(Config) ->
Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 50)],
FEData = fun(Do) -> lists:foreach(Do, Data) end,
- repeat_for_opts(fun(Opts) -> exit_many_many_tables_owner_do(Opts,FEData,Config) end).
+ repeat_for_opts(fun(Opts) -> exit_many_many_tables_owner_do1(Opts,FEData,Config) end).
-exit_many_many_tables_owner_do(Opts,FEData,Config) ->
- verify_rescheduling_exit(Config, FEData, [named_table | Opts], true, 200, 5),
- verify_rescheduling_exit(Config, FEData, Opts, false, 200, 5),
+exit_many_many_tables_owner_do1(Opts,FEData,Config) ->
+ case has_fixed_number_of_locks(Opts) of
+ true ->
+ %% Few memory hogging tables => not enough yielding for the test
+ io:format("Skip option combo ~p\n", [Opts]);
+ false ->
+ exit_many_many_tables_owner_do2(Opts,FEData,Config)
+ end.
+
+exit_many_many_tables_owner_do2(Opts,FEData,Config) ->
+ E = ets_new(tmp,Opts),
+ FEData(fun(Data) -> ets:insert(E, Data) end),
+ Mem = ets:info(E,memory) * erlang:system_info(wordsize),
+ ets:delete(E),
+
+ ct:log("Memory per table: ~p bytes",[Mem]),
+
+ Tables =
+ case erlang:system_info(wordsize) of
+ 8 ->
+ 200;
+ 4 ->
+ lists:min([200,2_000_000_000 div (Mem * 5)])
+ end,
+
+ verify_rescheduling_exit(Config, FEData, [named_table | Opts], true, Tables, 5),
+ verify_rescheduling_exit(Config, FEData, Opts, false, Tables, 5),
wait_for_test_procs(),
EtsMem = etsmem(),
- verify_rescheduling_exit(Config, FEData, Opts, true, 200, 5),
- verify_rescheduling_exit(Config, FEData, [named_table | Opts], false, 200, 5),
+ verify_rescheduling_exit(Config, FEData, Opts, true, Tables, 5),
+ verify_rescheduling_exit(Config, FEData, [named_table | Opts], false, Tables, 5),
verify_etsmem(EtsMem).
@@ -4889,6 +5104,44 @@ info(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch ets:info(make_ref())),
{'EXIT',{badarg,_}} = (catch ets:info(make_ref(), type)),
+ case erlang:system_info(schedulers) of
+ 1 -> %% Fine grained locking is not activated when there is only one scheduler
+ lists:foreach(
+ fun(Type) ->
+ T1 = ets:new(t1, [public, Type, {write_concurrency, auto}]),
+ false = ets:info(T1, write_concurrency),
+ T2 = ets:new(t2, [public, Type, {write_concurrency, true}]),
+ false = ets:info(T2, write_concurrency)
+ end,
+ [set, bag, duplicate_bag, ordered_set]),
+ T2 = ets:new(t2, [public, {write_concurrency, {debug_hash_fixed_number_of_locks, 2049}}]),
+ false = ets:info(T2, write_concurrency);
+ _ ->
+ %% Test that one can set the synchronization granularity level for
+ %% tables of type set
+ T1 = ets:new(t1, [public, {write_concurrency, {debug_hash_fixed_number_of_locks, 1024}}]),
+ {debug_hash_fixed_number_of_locks, 1024} = ets:info(T1, write_concurrency),
+ T2 = ets:new(t2, [public, {write_concurrency, {debug_hash_fixed_number_of_locks, 2048}}]),
+ {debug_hash_fixed_number_of_locks, 2048} = ets:info(T2, write_concurrency),
+ T3 = ets:new(t3, [public, {write_concurrency, {debug_hash_fixed_number_of_locks, 1024}}, {write_concurrency, true}]),
+ true = ets:info(T3, write_concurrency),
+ T4 = ets:new(t4, [private, {write_concurrency, {debug_hash_fixed_number_of_locks, 1024}}]),
+ false = ets:info(T4, write_concurrency),
+ %% Test the auto option
+ lists:foreach(
+ fun(Type) ->
+ T5 = ets:new(t5, [public, Type, {write_concurrency, auto}]),
+ auto = ets:info(T5, write_concurrency)
+ end,
+ [set, bag, duplicate_bag, ordered_set]),
+ T6 = ets:new(t6, [private, {write_concurrency, true}]),
+ false = ets:info(T6, write_concurrency),
+ T7 = ets:new(t7, [private, {write_concurrency, auto}]),
+ false = ets:info(T7, write_concurrency),
+ %% Test that the number of locks is rounded down to the nearest power of two
+ T8 = ets:new(t8, [public, {write_concurrency, {debug_hash_fixed_number_of_locks, 2049}}]),
+ {debug_hash_fixed_number_of_locks, 2048} = ets:info(T8, write_concurrency)
+ end,
ok.
info_do(Opts) ->
@@ -4954,7 +5207,6 @@ info_do(Opts) ->
{value, {id, Tab}} = lists:keysearch(id, 1, Res),
{value, {decentralized_counters, _DecentralizedCtrs}} =
lists:keysearch(decentralized_counters, 1, Res),
-
%% Test 'binary'
[] = ?ets_info(Tab, binary, SlavePid),
BinSz = 100,
@@ -4979,7 +5231,6 @@ info_do(Opts) ->
unlink(SlavePid),
exit(SlavePid,kill),
-
true = ets:delete(Tab),
verify_etsmem(EtsMem).
@@ -5113,22 +5364,233 @@ test_table_counter_concurrency(WhatToTest, TableOptions) ->
erts_debug:set_internal_state(available_internal_state, IntStatePrevOn),
ok.
+%% ERIERL-855: Calling info or whereis on a table being busy trapping (insert)
+%% could return 'undefined'.
+info_whereis_busy(Config) when is_list(Config) ->
+ TName = info_whereis_busy,
+ TName = ets:new(TName, [named_table, public]),
+ T = ets:whereis(TName),
+ NKeys = 100_000,
+ Tuples = [{K} || K <- lists:seq(1,NKeys)],
+ _Inserter = spawn_link(fun() ->
+ ets:insert(TName, Tuples)
+ end),
+ repeat_while(fun() ->
+ Info = ets:info(TName),
+ false = (Info =:= undefined),
+ T = ets:whereis(TName),
+ case lists:keyfind(size, 1, Info) of
+ {size, NKeys} ->
+ false;
+ {size, _} ->
+ true
+ end
+ end),
+ ets:delete(T),
+ ok.
+
+%% Delete table during trapping ets:insert
+insert_trap_delete(Config) when is_list(Config) ->
+ repeat_for_opts(fun(Opts) ->
+ [insert_trap_delete_run1({Opts,InsertFunc,Mode})
+ || InsertFunc <- [insert,insert_new],
+ Mode <- [exit, delete]]
+ end,
+ [all_non_stim_types, write_concurrency, compressed]),
+ ok.
+
+insert_trap_delete_run1(Params) ->
+ NKeys = 50_000 + rand:uniform(50_000),
+ %% First measure how many traps the insert op will do
+ Traps0 = insert_trap_delete_run3(unlimited, Params, NKeys),
+ %% Then do again and delete table at different moments
+ Decr = (Traps0 div 5) + 1,
+ insert_trap_delete_run2(Traps0-1, Decr, Params, NKeys).
+
+insert_trap_delete_run2(Traps, _Decr, Params, NKeys) when Traps =< 1 ->
+ insert_trap_delete_run3(1, Params, NKeys),
+ ok;
+insert_trap_delete_run2(Traps, Decr, Params, NKeys) ->
+ insert_trap_delete_run3(Traps, Params, NKeys),
+ insert_trap_delete_run2(Traps - Decr, Decr, Params, NKeys).
+
+insert_trap_delete_run3(Traps, {Opts, InsertFunc, Mode}, NKeys) ->
+ io:format("insert_trap_delete_run(~p, ~p, ~p) NKeys=~p\n",
+ [Traps, InsertFunc, Mode, NKeys]),
+ TabName = insert_trap_delete,
+ Tester = self(),
+ Tuples = [{K} || K <- lists:seq(1,NKeys)],
+
+ OwnerFun =
+ fun() ->
+ erlang:trace(Tester, true, [running]),
+ ets_new(TabName, [named_table, public | Opts]),
+ Tester ! {ets_new, ets:whereis(TabName)},
+ io:format("Wait for ets:~p/2 to yield...\n", [InsertFunc]),
+ GotTraps = repeat_while(
+ fun(N) ->
+ case receive_any() of
+ {trace, Tester, out, {ets,InsertFunc,2}} ->
+ case N of
+ Traps -> {false, Traps};
+ _ -> {true, N+1}
+ end;
+ "Insert done" ->
+ io:format("Too late! Got ~p traps\n", [N]),
+ {false, N};
+ _M ->
+ %%io:format("[~p] Ignored msg: ~p\n", [N,_M]),
+ {true, N}
+ end
+ end,
+ 0),
+ case Mode of
+ delete ->
+ io:format("Delete table and then exit...\n",[]),
+ ets:delete(TabName);
+ exit ->
+ io:format("Exit and let table die...\n",[])
+ end,
+ Tester ! {traps, GotTraps}
+ end,
+ {Owner, Mon} = spawn_opt(OwnerFun, [link, monitor]),
+
+ {ets_new, Tid} = receive_any(),
+ try ets:InsertFunc(TabName, Tuples) of
+ true ->
+ try ets:lookup(Tid, NKeys) of
+ [{NKeys}] -> ok
+ catch
+ error:badarg ->
+ %% Table must been deleted just after insert finished
+ undefined = ets:info(Tid, id),
+ undefined = ets:whereis(TabName)
+ end,
+ Owner ! "Insert done"
+ catch
+ error:badarg ->
+ %% Insert failed, table must have been deleted
+ undefined = ets:info(Tid, id),
+ undefined = ets:whereis(TabName)
+ end,
+ {traps, GotTraps} = receive_any(),
+ {'DOWN', Mon, process, Owner, _} = receive_any(),
+ undefined = ets:whereis(TabName),
+ undefined = ets:info(Tid, id),
+ GotTraps.
+
+%% Rename table during trapping ets:insert
+insert_trap_rename(Config) when is_list(Config) ->
+ repeat_for_opts(fun(Opts) ->
+ [insert_trap_rename_run1(InsertFunc)
+ || InsertFunc <- [insert, insert_new]]
+ end,
+ [all_non_stim_types, write_concurrency, compressed]),
+ ok.
+
+insert_trap_rename_run1(InsertFunc) ->
+ NKeys = 50_000 + rand:uniform(50_000),
+ %% First measure how many traps the insert op will do
+ Traps0 = insert_trap_rename_run3(unlimited, InsertFunc, NKeys),
+ %% Then do again and rename table at different moments
+ Decr = (Traps0 div 5) + 1,
+ insert_trap_rename_run2(Traps0-1, Decr, InsertFunc, NKeys),
+ ok.
+
+insert_trap_rename_run2(Traps, _Decr, InsertFunc, NKeys) when Traps =< 1 ->
+ insert_trap_rename_run3(1, InsertFunc, NKeys),
+ ok;
+insert_trap_rename_run2(Traps, Decr, InsertFunc, NKeys) ->
+ insert_trap_rename_run3(Traps, InsertFunc, NKeys),
+ insert_trap_rename_run2(Traps - Decr, Decr, InsertFunc, NKeys).
+
+
+insert_trap_rename_run3(Traps, InsertFunc, NKeys) ->
+ io:format("insert_trap_rename_run(~p, ~p)\n", [Traps, InsertFunc]),
+ TabName = insert_trap_rename,
+ TabRenamed = insert_trap_rename_X,
+ Tester = self(),
+ Tuples = [{K} || K <- lists:seq(1,NKeys)],
+
+ OwnerFun =
+ fun() ->
+ erlang:trace(Tester, true, [running]),
+ ets:new(TabName, [named_table, public]),
+ Tester ! {ets_new, ets:whereis(TabName)},
+ io:format("Wait for ets:~p/2 to yield...\n", [InsertFunc]),
+ GotTraps = repeat_while(
+ fun(N) ->
+ case receive_any() of
+ {trace, Tester, out, {ets,InsertFunc,2}} ->
+ case N of
+ Traps -> {false, ok};
+ _ -> {true, N+1}
+ end;
+ "Insert done" ->
+ io:format("Too late! Got ~p traps\n", [N]),
+ {false, N};
+ _M ->
+ %%io:format("[~p] Ignored msg: ~p\n", [N,_M]),
+ {true, N}
+ end
+ end,
+ 0),
+ io:format("Rename table and wait...\n",[]),
+ ets:rename(TabName, TabRenamed),
+ ets:delete(TabRenamed, 42),
+ Tester ! {renamed, GotTraps},
+ receive die -> ok end
+ end,
+ {Owner, Mon} = spawn_opt(OwnerFun, [link,monitor]),
+
+ {ets_new, Tid} = receive_any(),
+ try ets:InsertFunc(TabName, Tuples) of
+ true ->
+ io:format("ets:~p succeeded\n", [InsertFunc]),
+ true = ets:member(Tid, 1),
+ true = ets:member(Tid, NKeys)
+ catch
+ error:badarg ->
+ io:format("ets:~p failed\n", [InsertFunc]),
+ false = ets:member(Tid, 1),
+ false = ets:member(Tid, NKeys)
+ end,
+ Owner ! "Insert done",
+ {renamed, GotTraps} = receive_any(),
+ [] = ets:lookup(Tid, 42),
+ undefined = ets:whereis(TabName),
+ Tid = ets:whereis(TabRenamed),
+ Owner ! die,
+ {'DOWN', Mon, process, Owner, _} = receive_any(),
+ undefined = ets:whereis(TabName),
+ undefined = ets:whereis(TabRenamed),
+ GotTraps.
+
+
test_table_size_concurrency(Config) when is_list(Config) ->
case erlang:system_info(schedulers) of
1 -> {skip,"Only valid on smp > 1 systems"};
_ ->
- BaseOptions = [public, {write_concurrency, true}],
- test_table_counter_concurrency(size, [set | BaseOptions]),
- test_table_counter_concurrency(size, [ordered_set | BaseOptions])
+ lists:foreach(
+ fun(WriteConcurrencyOpt) ->
+ BaseOptions = [public, {write_concurrency, WriteConcurrencyOpt}],
+ test_table_counter_concurrency(size, [set | BaseOptions]),
+ test_table_counter_concurrency(size, [ordered_set | BaseOptions])
+ end,
+ [true, auto])
end.
test_table_memory_concurrency(Config) when is_list(Config) ->
case erlang:system_info(schedulers) of
1 -> {skip,"Only valid on smp > 1 systems"};
_ ->
- BaseOptions = [public, {write_concurrency, true}],
- test_table_counter_concurrency(memory, [set | BaseOptions]),
- test_table_counter_concurrency(memory, [ordered_set | BaseOptions])
+ lists:foreach(
+ fun(WriteConcurrencyOpt) ->
+ BaseOptions = [public, {write_concurrency, WriteConcurrencyOpt}],
+ test_table_counter_concurrency(memory, [set | BaseOptions]),
+ test_table_counter_concurrency(memory, [ordered_set | BaseOptions])
+ end,
+ [true, auto])
end.
%% Tests that calling the ets:delete operation on a table T with
@@ -5138,13 +5600,13 @@ test_delete_table_while_size_snapshot(Config) when is_list(Config) ->
%% Run test case in a slave node as other test suites in stdlib
%% depend on that pids are ordered in creation order which is no
%% longer the case when many processes have been started before
- Node = start_slave(),
+ {ok, Peer, Node} = ?CT_PEER(),
[ok = rpc:call(Node,
?MODULE,
test_delete_table_while_size_snapshot_helper,
[TableType])
|| TableType <- [set, ordered_set]],
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
test_delete_table_while_size_snapshot_helper(TableType) ->
@@ -5181,13 +5643,6 @@ size_process(Table, Parent) ->
E -> Parent ! {got_unexpected_exception, E}
end.
-start_slave() ->
- MicroSecs = erlang:monotonic_time(),
- Name = "ets_" ++ integer_to_list(MicroSecs),
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, Node} = test_server:start_node(list_to_atom(Name), slave, [{args, "-pa " ++ Pa}]),
- Node.
-
repeat_par(FunToRepeat, NrOfTimes) ->
repeat_par_help(FunToRepeat, NrOfTimes, NrOfTimes).
@@ -5218,25 +5673,42 @@ test_decentralized_counters_setting(Config) when is_list(Config) ->
do_test_decentralized_counters_setting(TableType) ->
wait_for_memory_deallocations(),
FlxCtrMemUsage = erts_debug:get_internal_state(flxctr_memory_usage),
+ FixOptsList =
+ fun(Opts) ->
+ case TableType of
+ ordered_set ->
+ replace_dbg_hash_fixed_nr_of_locks(Opts);
+ set ->
+ Opts
+ end
+ end,
lists:foreach(
fun(OptList) ->
- T1 = ets:new(t1, [public, TableType] ++ OptList ++ [TableType]),
+ T1 = ets:new(t1, FixOptsList([public, TableType] ++ OptList ++ [TableType])),
check_decentralized_counters(T1, false, FlxCtrMemUsage),
ets:delete(T1)
end,
- [[{write_concurrency, false}],
- [{write_concurrency, true}, {decentralized_counters, false}]]),
+ [[{write_concurrency, false}]] ++
+ case TableType of
+ set ->
+ [[{write_concurrency, true}, {decentralized_counters, false}],
+ [{write_concurrency, {debug_hash_fixed_number_of_locks, 1024}}, {write_concurrency, true}]];
+ ordered_set -> []
+ end),
lists:foreach(
fun(OptList) ->
- T1 = ets:new(t1, [public,
- TableType,
- {write_concurrency, true}] ++ OptList ++ [TableType]),
+ T1 = ets:new(t1,
+ FixOptsList([public,
+ TableType,
+ {write_concurrency, true}] ++ OptList ++ [TableType])),
check_decentralized_counters(T1, true, FlxCtrMemUsage),
ets:delete(T1),
wait_for_memory_deallocations(),
FlxCtrMemUsage = erts_debug:get_internal_state(flxctr_memory_usage)
end,
- [[{decentralized_counters, true}]]),
+ [[{decentralized_counters, true}],
+ [{write_concurrency, {debug_hash_fixed_number_of_locks, 1024}}],
+ [{write_concurrency, auto}]]),
ok.
do_test_decentralized_counters_default_setting() ->
@@ -6028,7 +6500,8 @@ xfilltabstr(Tab,N) ->
fill_sets_int(N) ->
fill_sets_int(N,[]).
fill_sets_int(N,Opts) ->
- Tab1 = ets_new(xxx, [ordered_set|Opts]),
+ Tab1 = ets_new(xxx,
+ replace_dbg_hash_fixed_nr_of_locks([ordered_set|Opts])),
filltabint(Tab1,N),
Tab2 = ets_new(xxx, [set|Opts]),
filltabint(Tab2,N),
@@ -6039,7 +6512,8 @@ fill_sets_int(N,Opts) ->
[Tab1,Tab2,Tab3,Tab4].
fill_sets_intup(N,Opts) ->
- Tab1 = ets_new(xxx, [ordered_set|Opts]),
+ Tab1 = ets_new(xxx,
+ replace_dbg_hash_fixed_nr_of_locks([ordered_set|Opts])),
filltabintup(Tab1,N),
Tab2 = ets_new(xxx, [set|Opts]),
filltabintup(Tab2,N),
@@ -6910,7 +7384,7 @@ verify_table_load(T) ->
ordered_set -> ok;
_ ->
Stats = ets:info(T,stats),
- {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
+ {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_,_} = Stats,
ok = if
AvgLen > 1.2 ->
io:format("Table overloaded: Stats=~p\n~p\n",
@@ -7406,9 +7880,15 @@ whereis_table(Config) when is_list(Config) ->
Tid = ets:whereis(whereis_test),
ets:insert(whereis_test, [{hello}, {there}]),
-
- [[{hello}],[{there}]] = ets:match(whereis_test, '$1'),
- [[{hello}],[{there}]] = ets:match(Tid, '$1'),
+ CheckMatch =
+ fun(MatchRes) ->
+ case MatchRes of
+ [[{there}],[{hello}]] -> ok;
+ [[{hello}],[{there}]] -> ok
+ end
+ end,
+ CheckMatch(ets:match(whereis_test, '$1')),
+ CheckMatch(ets:match(Tid, '$1')),
true = ets:delete_all_objects(Tid),
@@ -7674,7 +8154,9 @@ prefill_insert_map_loop(T, RS0, N, ObjFun, InsertMap, NrOfSchedulers) ->
[set, public],
[set, public, {write_concurrency, true}],
[set, public, {read_concurrency, true}],
- [set, public, {write_concurrency, true}, {read_concurrency, true}]
+ [set, public, {write_concurrency, true}, {read_concurrency, true}],
+ [set, public, {write_concurrency, auto}, {read_concurrency, true}],
+ [set, public, {write_concurrency, {debug_hash_fixed_number_of_locks, 16384}}]
],
etsmem_fun = fun() -> ok end,
verify_etsmem_fun = fun(_) -> true end,
@@ -8039,10 +8521,15 @@ long_throughput_benchmark(Config) when is_list(Config) ->
]
],
table_types =
- [
- [ordered_set, public, {write_concurrency, true}, {read_concurrency, true}],
- [set, public, {write_concurrency, true}, {read_concurrency, true}]
- ],
+ ([
+ [ordered_set, public, {write_concurrency, true}, {read_concurrency, true}],
+ [set, public, {write_concurrency, true}, {read_concurrency, true}]
+ ] ++
+ case catch list_to_integer(erlang:system_info(otp_release)) of
+ Recent when is_integer(Recent), Recent >= 25 ->
+ [[set, public, {write_concurrency, auto}, {read_concurrency, true}]];
+ _Old -> []
+ end),
etsmem_fun = fun etsmem/0,
verify_etsmem_fun = fun verify_etsmem/1,
notify_res_fun =
@@ -8438,7 +8925,7 @@ repeat_for_permutations(Fun, List, N) ->
receive_any() ->
receive M ->
- io:format("Process ~p got msg ~p\n", [self(),M]),
+ %%io:format("Process ~p got msg ~p\n", [self(),M]),
M
end.
@@ -8635,6 +9122,7 @@ error_info(_Config) ->
end),
receive T -> T end
end,
+ _ = ets:new(name_already_exists, [named_table]),
L = [{delete, ['$Tab']},
{delete, ['$Tab', no_key], [no_fail]},
@@ -8676,6 +9164,8 @@ error_info(_Config) ->
{insert, ['$Tab', [a|b]]},
{insert, ['$Tab', {a,b,c}], [no_fail]},
{insert, ['$Tab', [{a,b,c}]], [no_fail]},
+ {insert, ['$Tab', [{a,b,c},{d,e,f}]], [no_fail]},
+ {insert, ['$Tab', [{I,b,c} || I <- lists:seq(1,10_000)]], [no_fail]},
{insert_new, ['$Tab', bad_object]},
{insert_new, ['$Tab', {a,b,c}], [no_fail]},
@@ -8719,6 +9209,8 @@ error_info(_Config) ->
{new, [name, [a|b]], [no_table]},
{new, [name, [a,b]], [no_table]},
{new, [{bad,name}, [a,b]], [no_table]},
+ {new, [name_already_exists, [named_table]], [no_table,
+ {error_term,already_exists}]},
%% For a set, ets:next/2 and ets:prev/2 fails if the key does
%% not exist.
@@ -8834,7 +9326,7 @@ error_info(_Config) ->
[] ->
ok;
[_|_]=Errors ->
- io:format("~p\n", [Errors]),
+ io:format("~P\n", [Errors, 100]),
ct:fail({length(Errors),errors})
end.
@@ -8891,8 +9383,9 @@ ets_eval_bif_errors_once(F, Args, Opts) ->
io:format("\n\n*** ets:~p/~p", [F,length(Args)]),
NoFail = lists:member(no_fail, Opts),
+ ErrorTerm = proplists:get_value(error_term, Opts, none),
case ets_apply(F, Args, Opts) of
- {error,none} ->
+ {error,ErrorTerm} when not NoFail ->
ok;
{error,Info} ->
store_error(wrong_failure_reason, MFA, Info);
@@ -9059,7 +9552,7 @@ ets_apply(F, Args, Opts) ->
end.
ets_format_args(Args) ->
- lists:join(", ", [io_lib:format("~p", [A]) || A <- Args]).
+ lists:join(", ", [io_lib:format("~P", [A,10]) || A <- Args]).
%%%
%%% Common utility functions.
@@ -9210,8 +9703,30 @@ make_unaligned_sub_binary(Bin0) when is_binary(Bin0) ->
make_unaligned_sub_binary(List) ->
make_unaligned_sub_binary(list_to_binary(List)).
+replace_dbg_hash_fixed_nr_of_locks(Opts) ->
+ [case X of
+ {write_concurrency, {debug_hash_fixed_number_of_locks, _}} ->
+ {write_concurrency, true};
+ _ -> X
+ end || X <- Opts].
+
%% Repeat test function with different combination of table options
-%%
+%%
+repeat_for_opts_extra_opt(F, Extra) ->
+ repeat_for_opts(
+ fun(Opts) ->
+ WithExtra =
+ case erlang:is_list(Extra) of
+ true -> Extra ++ Opts;
+ false ->[Extra | Opts]
+ end,
+ case is_invalid_opts_combo(WithExtra) of
+ true -> ok;
+ false -> F(WithExtra)
+ end
+ end,
+ [write_concurrency, read_concurrency, compressed]).
+
repeat_for_opts(F) ->
repeat_for_opts(F, [write_concurrency, read_concurrency, compressed]).
@@ -9270,17 +9785,44 @@ repeat_for_opts_atom2list(ord_set_types) -> [ordered_set,stim_cat_ord_set,cat_or
repeat_for_opts_atom2list(all_types) -> [set,ordered_set,stim_cat_ord_set,cat_ord_set,bag,duplicate_bag];
repeat_for_opts_atom2list(all_non_stim_types) -> [set,ordered_set,cat_ord_set,bag,duplicate_bag];
repeat_for_opts_atom2list(all_non_stim_set_types) -> [set,ordered_set,cat_ord_set];
-repeat_for_opts_atom2list(write_concurrency) -> [{write_concurrency,false},{write_concurrency,true}];
+repeat_for_opts_atom2list(write_concurrency) -> [{write_concurrency,false},
+ {write_concurrency,true},
+ {write_concurrency, {debug_hash_fixed_number_of_locks, 2048}},
+ {write_concurrency,auto}];
repeat_for_opts_atom2list(read_concurrency) -> [{read_concurrency,false},{read_concurrency,true}];
repeat_for_opts_atom2list(compressed) -> [void,compressed].
+has_fixed_number_of_locks(Opts) ->
+ lists:any(
+ fun({write_concurrency, {debug_hash_fixed_number_of_locks, _}}) ->
+ true;
+ (_) ->
+ false
+ end,
+ Opts).
+
+is_invalid_opts_combo(Opts) ->
+ OrderedSet = lists:member(ordered_set, Opts) orelse
+ lists:member(stim_cat_ord_set, Opts) orelse
+ lists:member(cat_ord_set, Opts),
+ OrderedSet andalso has_fixed_number_of_locks(Opts).
+
+run_if_valid_opts(Opts, F) ->
+ case is_invalid_opts_combo(Opts) of
+ true -> ignore;
+ false -> F(Opts)
+ end.
+
is_redundant_opts_combo(Opts) ->
- (lists:member(stim_cat_ord_set, Opts) orelse
- lists:member(cat_ord_set, Opts))
- andalso
- (lists:member({write_concurrency, false}, Opts) orelse
- lists:member(private, Opts) orelse
- lists:member(protected, Opts)).
+ IsRed1 =
+ ((lists:member(stim_cat_ord_set, Opts) orelse
+ lists:member(cat_ord_set, Opts))
+ andalso
+ (lists:member({write_concurrency, false}, Opts) orelse
+ lists:member(private, Opts) orelse
+ lists:member(protected, Opts))),
+ IsRed2 = is_invalid_opts_combo(Opts),
+ IsRed1 orelse IsRed2.
%% Add fake table option with info about key range.
%% Will be consumed by ets_new and used for stim_cat_ord_set.
diff --git a/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html b/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html
index 922a3790ea..43076c70ca 100644
--- a/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html
+++ b/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html
@@ -4,7 +4,7 @@
<!-- %% -->
<!-- %% %CopyrightBegin% -->
<!-- %% -->
-<!-- %% Copyright Ericsson AB and Kjell Winblad 1996-2020. All Rights Reserved. -->
+<!-- %% Copyright Ericsson AB and Kjell Winblad 1996-2021. All Rights Reserved. -->
<!-- %% -->
<!-- %% Licensed under the Apache License, Version 2.0 (the "License"); -->
<!-- %% you may not use this file except in compliance with the License. -->
@@ -240,10 +240,12 @@
function plotScenario(name, plotType) {
var data = scenarioDataMap[name];
var yAxisTitle = undefined;
+ var graphId = "graph" + nrOfGraphs;
+ var fullscreenButtonid = "fullscreenButton" + nrOfGraphs;
nrOfGraphs = nrOfGraphs + 1;
- $("<div class='added' id='graph" + nrOfGraphs + "'>")
+ $("<div class='added' id='" + graphId + "'>")
.insertBefore(insertPlaceholder);
- $("<button type='button' class='added' id='fullscreenButton" + nrOfGraphs + "'>Fill screen</button>")
+ $("<button type='button' class='added' id='" + fullscreenButtonid + "'>Fill screen</button>")
.insertBefore(insertPlaceholder);
$("<span class='added'><br><hr><br></span>")
.insertBefore(insertPlaceholder);
@@ -265,17 +267,17 @@
title: yAxisTitle
}
};
- $("#fullscreenButton" + nrOfGraphs).click(
+ $("#" + fullscreenButtonid).click(
function () {
- $('#graph' + nrOfGraphs).replaceWith(
- $("<div class='added' id='graph" + nrOfGraphs + "'>"));
+ $('#' + graphId).replaceWith(
+ $("<div class='added' id='" + graphId + "'>"));
layout = $.extend({}, layout, {
width: $(window).width() - 40,
height: $(window).height() - 40
});
- Plotly.newPlot('graph' + nrOfGraphs, data, layout);
+ Plotly.newPlot(graphId, data, layout);
});
- Plotly.newPlot('graph' + nrOfGraphs, data, layout);
+ Plotly.newPlot(graphId, data, layout);
}
$.each(scenarioList,
function (index, name) {
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index 15603aee9a..179567f128 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,9 +25,13 @@
init_per_testcase/2,end_per_testcase/2,
wildcard_one/1,wildcard_two/1,wildcard_errors/1,
fold_files/1,otp_5960/1,ensure_dir_eexist/1,ensure_dir_symlink/1,
+ ensure_path_single_dir/1, ensure_path_nested_dirs/1,
+ ensure_path_binary_args/1, ensure_path_symlink/1,
+ ensure_path_relative_path/1, ensure_path_relative_path_dot_dot/1,
+ ensure_path_invalid_path/1,
wildcard_symlink/1, is_file_symlink/1, file_props_symlink/1,
- find_source/1, find_source_subdir/1, safe_relative_path/1,
- safe_relative_path_links/1]).
+ find_source/1, find_source_subdir/1, find_source_otp/1,
+ safe_relative_path/1, safe_relative_path_links/1]).
-import(lists, [foreach/2]).
@@ -49,9 +53,13 @@ suite() ->
all() ->
[wildcard_one, wildcard_two, wildcard_errors,
fold_files, otp_5960, ensure_dir_eexist, ensure_dir_symlink,
+ ensure_path_single_dir, ensure_path_nested_dirs, ensure_path_binary_args,
+ ensure_path_symlink, ensure_path_relative_path,
+ ensure_path_relative_path_dot_dot,
+ ensure_path_invalid_path,
wildcard_symlink, is_file_symlink, file_props_symlink,
- find_source, find_source_subdir, safe_relative_path,
- safe_relative_path_links].
+ find_source, find_source_subdir, find_source_otp,
+ safe_relative_path, safe_relative_path_links].
groups() ->
[].
@@ -458,6 +466,83 @@ ensure_dir_symlink(Config) when is_list(Config) ->
ok = filelib:ensure_dir(SymlinkedName)
end.
+ensure_path_single_dir(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, "ensure_path_single_dir"),
+ ok = filelib:ensure_path(Dir),
+ true = filelib:is_dir(Dir).
+
+ensure_path_nested_dirs(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ BaseDir = filename:join(PrivDir, "ensure_path_nested_dirs"),
+ Path = filename:join(BaseDir, "foo/bar/baz"),
+ ok = filelib:ensure_path(Path),
+ true = filelib:is_dir(Path).
+
+ensure_path_binary_args(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ BaseDir = filename:join(PrivDir, "ensure_path_binary_args"),
+ Path = filename:join(BaseDir, "foo/bar/baz"),
+ ok = filelib:ensure_path(list_to_binary(Path)),
+ true = filelib:is_dir(Path).
+
+ensure_path_invalid_path(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ BaseDir = filename:join(PrivDir, "ensure_path_invalid_path"),
+ ok = filelib:ensure_path(BaseDir),
+ FileName = filename:join(BaseDir, "foo"),
+ ok = file:write_file(FileName, <<"eh?\n">>),
+ Path = filename:join(FileName, "foo/bar/baz"),
+ case filelib:ensure_path(Path) of
+ {error,enotdir} ->
+ ok;
+ {error,enoent} ->
+ %% The documentation has the following to say about the
+ %% `enotdir` error reason:
+ %%
+ %% "On some platforms, enoent is returned instead."
+ ok
+ end,
+ false = filelib:is_dir(Path).
+
+ensure_path_relative_path(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ BaseDir = filename:join(PrivDir, "ensure_path_relative_path"),
+ ok = filelib:ensure_path(BaseDir),
+ ok = file:set_cwd(BaseDir),
+ Path = filename:join(BaseDir, "foo/bar/baz"),
+ ok = filelib:ensure_path("foo/bar/baz"),
+ true = filelib:is_dir(Path).
+
+ensure_path_relative_path_dot_dot(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ BaseDir = filename:join(PrivDir, "ensure_path_relative_path"),
+ SubDir = filename:join(BaseDir, "dot_dot"),
+ ok = filelib:ensure_path(SubDir),
+ ok = file:set_cwd(SubDir),
+ Path = filename:join(BaseDir, "foo/bar/baz"),
+ ok = filelib:ensure_path("../foo/bar/baz"),
+ true = filelib:is_dir(Path).
+
+ensure_path_symlink(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Dir = filename:join(PrivDir, "ensure_path_symlink"),
+ Name = filename:join(Dir, "same_name_as_file_and_dir"),
+ ok = filelib:ensure_path(Dir),
+ ok = file:write_file(Name, <<"some string\n">>),
+ %% With a symlink to the directory.
+ Symlink = filename:join(PrivDir, "ensure_path_symlink_link"),
+ case file:make_symlink(Dir, Symlink) of
+ {error,enotsup} ->
+ {skip,"Symlinks not supported on this platform"};
+ {error,eperm} ->
+ {win32,_} = os:type(),
+ {skip,"Windows user not privileged to create symlinks"};
+ ok ->
+ SymlinkedName = filename:join(Symlink, "same_name_as_file_and_dir"),
+ ok = filelib:ensure_dir(SymlinkedName)
+ end.
+
wildcard_symlink(Config) when is_list(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
Dir = filename:join(PrivDir, ?MODULE_STRING++"_wildcard_symlink"),
@@ -652,6 +737,32 @@ find_source_subdir(Config) when is_list(Config) ->
ok.
+%% Test that all available beam files in Erlang/OTP can be
+%% tracked to their source files.
+find_source_otp(Config) when is_list(Config) ->
+ %% We do this in a peer as testcases before this may have
+ %% edited the code path and thus more modules show up as
+ %% available than should.
+ {ok, Peer, Node} = ?CT_PEER(#{ env => [{"ERL_LIBS", false}] }),
+ erpc:call(
+ Node,
+ fun() ->
+ lists:map(
+ fun F({Module, preloaded, Loaded}) ->
+ F({Module, code:where_is_file(Module ++ ".beam"), Loaded});
+ F({Module, cover_compiled, Loaded}) ->
+ ok;
+ F({Module, Filename, _Loaded}) ->
+ case filelib:find_source(Filename) of
+ {ok, _} -> ok;
+ {error,_} = E ->
+ ct:fail({failed_to_find, Module, Filename, E})
+ end
+ end, code:all_available())
+ end),
+ peer:stop(Peer),
+ ok.
+
safe_relative_path(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
Root = filename:join(PrivDir, "filelib_SUITE_safe_relative_path"),
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index 1fdea75844..b005651302 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
dirname_bin/1, extension_bin/1, join_bin/1, t_nativename_bin/1]).
-export([pathtype_bin/1,rootname_bin/1,split_bin/1]).
-export([t_basedir_api/1, t_basedir_xdg/1, t_basedir_windows/1]).
--export([safe_relative_path/1]).
-include_lib("common_test/include/ct.hrl").
@@ -41,8 +40,7 @@ all() ->
[absname, absname_2,
absname_bin, absname_bin_2,
{group,p},
- t_basedir_xdg, t_basedir_windows,
- safe_relative_path].
+ t_basedir_xdg, t_basedir_windows].
groups() ->
[{p, [parallel],
@@ -876,71 +874,6 @@ t_nativename_bin(Config) when is_list(Config) ->
filename:nativename(<<"/usr/tmp//arne/">>)
end.
-safe_relative_path(Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- Root = filename:join(PrivDir, "filename_SUITE_safe_relative_path"),
- ok = file:make_dir(Root),
- ok = file:set_cwd(Root),
-
- ok = file:make_dir("a"),
- ok = file:set_cwd("a"),
- ok = file:make_dir("b"),
- ok = file:set_cwd("b"),
- ok = file:make_dir("c"),
-
- ok = file:set_cwd(Root),
-
- "a" = test_srp("a"),
- "a/b" = test_srp("a/b"),
- "a/b" = test_srp("a/./b"),
- "a/b" = test_srp("a/./b/."),
-
- "" = test_srp("a/.."),
- "" = test_srp("a/./.."),
- "" = test_srp("a/../."),
- "a" = test_srp("a/b/.."),
- "a" = test_srp("a/../a"),
- "a" = test_srp("a/../a/../a"),
- "a/b/c" = test_srp("a/../a/b/c"),
-
- unsafe = test_srp("a/../.."),
- unsafe = test_srp("a/../../.."),
- unsafe = test_srp("a/./../.."),
- unsafe = test_srp("a/././../../.."),
- unsafe = test_srp("a/b/././../../.."),
-
- unsafe = test_srp(PrivDir), %Absolute path.
-
- ok.
-
-test_srp(RelPath) ->
- Res = do_test_srp(RelPath),
- Res = case do_test_srp(list_to_binary(RelPath)) of
- Bin when is_binary(Bin) ->
- binary_to_list(Bin);
- Other ->
- Other
- end.
-
-do_test_srp(RelPath) ->
- {ok,Root} = file:get_cwd(),
- ok = file:set_cwd(RelPath),
- {ok,Cwd} = file:get_cwd(),
- ok = file:set_cwd(Root),
- case filename:safe_relative_path(RelPath) of
- unsafe ->
- true = length(Cwd) < length(Root),
- unsafe;
- "" ->
- "";
- SafeRelPath ->
- ok = file:set_cwd(SafeRelPath),
- {ok,Cwd} = file:get_cwd(),
- true = length(Cwd) >= length(Root),
- ok = file:set_cwd(Root),
- SafeRelPath
- end.
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% basedirs
t_basedir_api(Config) when is_list(Config) ->
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index 0787dee5e1..65c5a83c9e 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,9 @@
start_opt/1,
undef_init/1, undef_handle_call/1, undef_handle_event/1,
undef_handle_info/1, undef_code_change/1, undef_terminate/1,
- undef_in_terminate/1, format_log_1/1, format_log_2/1]).
+ undef_in_terminate/1, format_log_1/1, format_log_2/1,
+ send_request_receive_reqid_collection/1, send_request_wait_reqid_collection/1,
+ send_request_check_reqid_collection/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -41,7 +43,9 @@ all() ->
call_format_status, call_format_status_anon, error_format_status,
get_state, replace_state,
start_opt, {group, undef_callbacks}, undef_in_terminate,
- format_log_1, format_log_2].
+ format_log_1, format_log_2,
+ send_request_receive_reqid_collection, send_request_wait_reqid_collection,
+ send_request_check_reqid_collection].
groups() ->
[{test_all, [],
@@ -974,7 +978,7 @@ call(Config) when is_list(Config) ->
ok.
flush() ->
- receive _ -> flush() after 0 -> ok end.
+ receive M -> [M|flush()] after 0 -> [] end.
info(Config) when is_list(Config) ->
{ok,_} = gen_event:start({local, my_dummy_handler}),
@@ -1100,22 +1104,25 @@ info(Config) when is_list(Config) ->
ok = gen_event:stop(my_dummy_handler),
ok.
-%% Test that sys:get_status/1,2 calls format_status/2.
+%% Test that sys:get_status/1,2 calls format_status/1,2.
call_format_status(Config) when is_list(Config) ->
+ call_format_status(dummy1_h),
+ call_format_status(dummy_h);
+call_format_status(Module) when is_atom(Module) ->
{ok, Pid} = gen_event:start({local, my_dummy_handler}),
%% State here intentionally differs from what we expect from format_status
State = self(),
FmtState = "dummy1_h handler state",
- ok = gen_event:add_handler(my_dummy_handler, dummy1_h, [State]),
+ ok = gen_event:add_handler(my_dummy_handler, Module, [State]),
Status1 = sys:get_status(Pid),
Status2 = sys:get_status(Pid, 5000),
ok = gen_event:stop(Pid),
{status, Pid, _, [_, _, Pid, [], Data1]} = Status1,
HandlerInfo1 = proplists:get_value(items, Data1),
- {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo1,
+ {"Installed handlers", [{_,Module,_,FmtState,_}]} = HandlerInfo1,
{status, Pid, _, [_, _, Pid, [], Data2]} = Status2,
HandlerInfo2 = proplists:get_value(items, Data2),
- {"Installed handlers", [{_,dummy1_h,_,FmtState,_}]} = HandlerInfo2,
+ {"Installed handlers", [{_,Module,_,FmtState,_}]} = HandlerInfo2,
ok.
%% Test that sys:get_status/1,2 calls format_status/2 for anonymous
@@ -1136,28 +1143,38 @@ call_format_status_anon(Config) when is_list(Config) ->
error_format_status(Config) when is_list(Config) ->
error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
+ try
+ error_format_status(dummy1_h),
+ error_format_status(dummy_h)
+ after
+ process_flag(trap_exit, OldFl),
+ error_logger_forwarder:unregister()
+ end;
+error_format_status(Module) when is_atom(Module) ->
State = self(),
{ok, Pid} = gen_event:start({local, my_dummy_handler}),
- ok = gen_event:add_sup_handler(my_dummy_handler, dummy1_h, [State]),
+ ok = gen_event:add_sup_handler(my_dummy_handler, Module, [State]),
ok = gen_event:notify(my_dummy_handler, do_crash),
receive
- {gen_event_EXIT,dummy1_h,{'EXIT',_}} -> ok
+ {gen_event_EXIT,Module,{'EXIT',_}} -> ok
after 5000 ->
- ct:fail(exit_gen_event)
+ ct:fail({exit_gen_event,flush()})
end,
FmtState = "dummy1_h handler state",
receive
{error,_GroupLeader, {Pid,
"** gen_event handler"++_,
- [dummy1_h,my_dummy_handler,do_crash,
+ [Module,my_dummy_handler,do_crash,
FmtState, _]}} ->
ok;
Other ->
- io:format("Unexpected: ~p", [Other]),
+ ct:pal("Unexpected: ~p", [Other]),
ct:fail(failed)
+ after 5000 ->
+ ct:fail({exit_gen_event,flush()})
end,
+ unlink(Pid),
ok = gen_event:stop(Pid),
- process_flag(trap_exit, OldFl),
ok.
%% Test that sys:get_state/1,2 return the gen_event state.
@@ -1321,23 +1338,30 @@ format_log_1(_Config) ->
Warning = #{label=>{gen_event,no_handle_info},
module=>?MODULE,
- message=>Term},
+ message=> Term},
{WF1,WA1} = gen_event:format_log(Warning),
WFExpected1 = "** Undefined handle_info in ~p\n"
"** Unhandled message: ~tp\n",
ct:log("WF1: ~ts~nWA1: ~tp", [WF1,WA1]),
WFExpected1 = WF1,
[?MODULE,Term] = WA1,
+ WarningLimited = [1,2,3,4,5,6,7,8,9,'...'],
Depth = 10,
ok = application:set_env(kernel, error_logger_format_depth, Depth),
- Limited = [1,2,3,4,5,6,7,8,9,'...'],
+ Limited = [1,2,3,4,5,6,7,8,'...'],
+ LastMsg = ["Last msg" | Term],
+ State = ["State" | Term],
+ Reason = ["Reason" | Term],
+ LastMsgLimited = ["Last msg" | Limited],
+ StateLimited = ["State" | Limited],
+ ReasonLimited = ["Reason" | Limited],
{F2,A2} = gen_event:format_log(#{label=>{gen_event,terminate},
handler=>Handler,
name=>Name,
- last_message=>Term,
- state=>Term,
- reason=>Term}),
+ last_message=>LastMsg,
+ state=>State,
+ reason=>Reason}),
FExpected2 = "** gen_event handler ~tP crashed.\n"
"** Was installed in ~tP\n"
"** Last event was: ~tP\n"
@@ -1345,14 +1369,15 @@ format_log_1(_Config) ->
"** Reason == ~tP\n",
ct:log("F2: ~ts~nA2: ~tp", [F2,A2]),
FExpected2 = F2,
- [Handler,Depth,Name,Depth,Limited,Depth,Limited,Depth,Limited,Depth] = A2,
+ [Handler,Depth,Name,Depth,LastMsgLimited,Depth,StateLimited,Depth,ReasonLimited,Depth] = A2,
{WF2,WA2} = gen_event:format_log(Warning),
WFExpected2 = "** Undefined handle_info in ~p\n"
"** Unhandled message: ~tP\n",
ct:log("WF2: ~ts~nWA2: ~tp", [WF2,WA2]),
WFExpected2 = WF2,
- [?MODULE,Limited,Depth] = WA2,
+ ct:log("WF2: ~tp~nWA2: ~tp", [[?MODULE,WarningLimited,Depth], WA2]),
+ [?MODULE,WarningLimited,Depth] = WA2,
case FD of
undefined ->
@@ -1501,3 +1526,324 @@ format_log_2(_Config) ->
flatten_format_log(Report, Format) ->
lists:flatten(gen_event:format_log(Report, Format)).
+
+
+send_request_receive_reqid_collection(Config) when is_list(Config) ->
+ {ok, Pid1} = gen_event:start(),
+ ok = gen_event:add_handler(Pid1, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid1),
+ {ok, Pid2} = gen_event:start(),
+ ok = gen_event:add_handler(Pid2, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid2),
+ {ok, Pid3} = gen_event:start(),
+ ok = gen_event:add_handler(Pid3, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid3),
+ send_request_receive_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_receive_reqid_collection_timeout(Pid1, Pid2, Pid3),
+ send_request_receive_reqid_collection_error(Pid1, Pid2, Pid3),
+ ok = gen_event:stop(Pid1),
+ try gen_event:stop(Pid2) catch exit:noproc -> ok end,
+ ok = gen_event:stop(Pid3).
+
+send_request_receive_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,400}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = gen_event:reqids_size(ReqIdC1),
+
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+ 2 = gen_event:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_event:reqids_size(ReqIdC3),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_event:receive_response(ReqIdC3, infinity, true),
+ 2 = gen_event:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_event:receive_response(ReqIdC4, 5678, true),
+ 1 = gen_event:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_event:receive_response(ReqIdC5, 5000, true),
+ 0 = gen_event:reqids_size(ReqIdC6),
+
+ no_request = gen_event:receive_response(ReqIdC6, 5000, true),
+
+ {reply, {ok, hejhopp}} = gen_event:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_timeout(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,1000}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqId3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,500}),
+ ReqIdC3 = gen_event:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_event:receive_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = gen_event:reqids_size(ReqIdC4),
+
+ timeout = gen_event:receive_response(ReqIdC4, {abs, Deadline}, true),
+
+ Abandoned = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Abandoned = lists:sort(gen_event:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were abandoned...
+ timeout = gen_event:receive_response(ReqIdC4, {abs, Deadline+1000}, true),
+
+ {reply, {ok, hejhopp}} = gen_event:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,400}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_event:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ exit(Pid2, kill),
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+ ReqIdC3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,200}, req3, ReqIdC2),
+ ReqIdC4 = gen_event:send_request(Pid1, bad_h, hejsan, req4, ReqIdC3),
+ 4 = gen_event:reqids_size(ReqIdC4),
+
+ {{error, {noproc, _}}, req2, ReqIdC5} = gen_event:receive_response(ReqIdC4, 2000, true),
+ 3 = gen_event:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_event:receive_response(ReqIdC5, infinity, false),
+ {{reply, delayed}, req1, ReqIdC5} = gen_event:receive_response(ReqIdC5, infinity, false),
+ {{error, bad_module}, req4, ReqIdC5} = gen_event:wait_response(ReqIdC5, infinity, false),
+
+ {reply, {ok, hejhopp}} = gen_event:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection(Config) when is_list(Config) ->
+ {ok, Pid1} = gen_event:start(),
+ ok = gen_event:add_handler(Pid1, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid1),
+ {ok, Pid2} = gen_event:start(),
+ ok = gen_event:add_handler(Pid2, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid2),
+ {ok, Pid3} = gen_event:start(),
+ ok = gen_event:add_handler(Pid3, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid3),
+ send_request_wait_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_wait_reqid_collection_timeout(Pid1, Pid2, Pid3),
+ send_request_wait_reqid_collection_error(Pid1, Pid2, Pid3),
+ ok = gen_event:stop(Pid1),
+ try gen_event:stop(Pid2) catch exit:noproc -> ok end,
+ ok = gen_event:stop(Pid3).
+
+send_request_wait_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,400}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = gen_event:reqids_size(ReqIdC1),
+
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+ 2 = gen_event:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_event:reqids_size(ReqIdC3),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_event:wait_response(ReqIdC3, infinity, true),
+ 2 = gen_event:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_event:wait_response(ReqIdC4, 5678, true),
+ 1 = gen_event:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_event:wait_response(ReqIdC5, 5000, true),
+ 0 = gen_event:reqids_size(ReqIdC6),
+
+ no_request = gen_event:wait_response(ReqIdC6, 5000, true),
+
+ {reply, {ok, hejhopp}} = gen_event:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection_timeout(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,1000}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqId3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,500}),
+ ReqIdC3 = gen_event:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_event:wait_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = gen_event:reqids_size(ReqIdC4),
+
+ timeout = gen_event:wait_response(ReqIdC4, {abs, Deadline}, true),
+
+ Unhandled = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Unhandled = lists:sort(gen_event:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were not abandoned...
+ {{reply, delayed}, req3, ReqIdC4} = gen_event:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+ {{reply, delayed}, req1, ReqIdC4} = gen_event:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+
+ {reply, {ok, hejhopp}} = gen_event:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,400}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_event:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ exit(Pid2, kill),
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+ ReqIdC3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,200}, req3, ReqIdC2),
+ ReqIdC4 = gen_event:send_request(Pid1, bad_h, hejsan, req4, ReqIdC3),
+ 4 = gen_event:reqids_size(ReqIdC4),
+
+ {{error, {noproc, _}}, req2, ReqIdC5} = gen_event:wait_response(ReqIdC4, 2000, true),
+ 3 = gen_event:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_event:wait_response(ReqIdC5, infinity, false),
+ {{reply, delayed}, req1, ReqIdC5} = gen_event:wait_response(ReqIdC5, infinity, false),
+ {{error, bad_module}, req4, ReqIdC5} = gen_event:wait_response(ReqIdC5, infinity, false),
+
+ {reply, {ok, hejhopp}} = gen_event:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_check_reqid_collection(Config) when is_list(Config) ->
+ {ok, Pid1} = gen_event:start(),
+ ok = gen_event:add_handler(Pid1, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid1),
+ {ok, Pid2} = gen_event:start(),
+ ok = gen_event:add_handler(Pid2, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid2),
+ {ok, Pid3} = gen_event:start(),
+ ok = gen_event:add_handler(Pid3, dummy_h, [self()]),
+ [dummy_h] = gen_event:which_handlers(Pid3),
+ send_request_check_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_check_reqid_collection_error(Pid1, Pid2, Pid3),
+ ok = gen_event:stop(Pid1),
+ try gen_event:stop(Pid2) catch exit:noproc -> ok end,
+ ok = gen_event:stop(Pid3).
+
+send_request_check_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ receive after 100 -> ok end,
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqIdC1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,400}, req1, ReqIdC0),
+ 1 = gen_event:reqids_size(ReqIdC1),
+
+ ReqId2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}),
+ ReqIdC2 = gen_event:reqids_add(ReqId2, req2, ReqIdC1),
+ 2 = gen_event:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_event:reqids_size(ReqIdC3),
+
+ Msg0 = next_msg(),
+ no_reply = gen_event:check_response(Msg0, ReqIdC3, true),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_event:check_response(next_msg(), ReqIdC3, true),
+ 2 = gen_event:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_event:check_response(next_msg(), ReqIdC4, true),
+ 1 = gen_event:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_event:check_response(next_msg(), ReqIdC5, true),
+ 0 = gen_event:reqids_size(ReqIdC6),
+
+ no_request = gen_event:check_response(Msg0, ReqIdC6, true),
+
+ {reply, {ok, hejhopp}} = gen_event:check_response(Msg0, ReqId0),
+
+ ok.
+
+send_request_check_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_event:send_request(Pid1, dummy_h, hejsan),
+
+ receive after 100 -> ok end,
+
+ ReqIdC0 = gen_event:reqids_new(),
+
+ ReqId1 = gen_event:send_request(Pid1, dummy_h, {delayed_answer,400}),
+ ReqIdC1 = gen_event:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_event:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ exit(Pid2, kill),
+ ReqIdC2 = gen_event:send_request(Pid2, dummy_h, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqIdC3 = gen_event:send_request(Pid3, dummy_h, {delayed_answer,200}, req3, ReqIdC2),
+
+ ReqIdC4 = gen_event:send_request(Pid1, bad_h, hejsan, req4, ReqIdC3),
+ 4 = gen_event:reqids_size(ReqIdC4),
+
+ Msg0 = next_msg(),
+
+ no_reply = gen_event:check_response(Msg0, ReqIdC3, true),
+
+ {{error, {noproc, _}}, req2, ReqIdC5} = gen_event:check_response(next_msg(), ReqIdC4, true),
+ 3 = gen_event:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_event:check_response(next_msg(), ReqIdC5, false),
+ {{reply, delayed}, req1, ReqIdC5} = gen_event:check_response(next_msg(), ReqIdC5, false),
+ {{error, bad_module}, req4, ReqIdC5} = gen_event:check_response(next_msg(), ReqIdC5, false),
+
+ no_reply = gen_event:check_response(Msg0, ReqIdC3, false),
+
+ {reply, {ok, hejhopp}} = gen_event:check_response(Msg0, ReqId0),
+
+ ok.
+
+next_msg() ->
+ receive M -> M end.
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index d416bf2f8f..9d912ab257 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -366,20 +366,20 @@ stop7(_Config) ->
%% Anonymous on remote node
stop8(_Config) ->
- {ok,Node} = test_server:start_node(gen_fsm_SUITE_stop8,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_fsm,start,[?MODULE,[],[]]),
ok = gen_fsm:stop(Pid),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_fsm:stop(Pid)),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
{'EXIT',{{nodedown,Node},_}} = (catch gen_fsm:stop(Pid)),
ok.
%% Registered name on remote node
stop9(_Config) ->
- {ok,Node} = test_server:start_node(gen_fsm_SUITE_stop9,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_fsm,start,[{local,to_stop},?MODULE,[],[]]),
@@ -387,13 +387,13 @@ stop9(_Config) ->
undefined = rpc:call(Node,erlang,whereis,[to_stop]),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_fsm:stop({to_stop,Node})),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
{'EXIT',{{nodedown,Node},_}} = (catch gen_fsm:stop({to_stop,Node})),
ok.
%% Globally registered name on remote node
stop10(_Config) ->
- {ok,Node} = test_server:start_node(gen_fsm_SUITE_stop10,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_fsm,start,[{global,to_stop},?MODULE,[],[]]),
@@ -401,7 +401,7 @@ stop10(_Config) ->
ok = gen_fsm:stop({global,to_stop}),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_fsm:stop({global,to_stop})),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
{'EXIT',noproc} = (catch gen_fsm:stop({global,to_stop})),
ok.
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index 0118b7bc66..5fa604d4fd 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -26,14 +26,19 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([start/1, crash/1, call/1, send_request/1, cast/1, cast_fast/1,
+-export([start/1, crash/1, call/1, send_request/1,
+ send_request_receive_reqid_collection/1,
+ send_request_wait_reqid_collection/1,
+ send_request_check_reqid_collection/1,
+ cast/1, cast_fast/1,
continue/1, info/1, abcast/1, multicall/1, multicall_down/1,
- call_remote1/1, call_remote2/1, call_remote3/1,
+ call_remote1/1, call_remote2/1, call_remote3/1, calling_self/1,
call_remote_n1/1, call_remote_n2/1, call_remote_n3/1, spec_init/1,
spec_init_local_registered_parent/1,
spec_init_global_registered_parent/1,
otp_5854/1, hibernate/1, auto_hibernate/1, otp_7669/1, call_format_status/1,
- error_format_status/1, terminate_crash_format/1,
+ error_format_status/1, terminate_crash_format/1, crash_in_format_status/1,
+ throw_in_format_status/1, format_all_status/1,
get_state/1, replace_state/1, call_with_huge_message_queue/1,
undef_handle_call/1, undef_handle_cast/1, undef_handle_info/1,
undef_init/1, undef_code_change/1, undef_terminate1/1,
@@ -64,14 +69,16 @@ suite() ->
{timetrap,{minutes,1}}].
all() ->
- [start, {group,stop}, crash, call, send_request, cast, cast_fast, info, abcast,
- continue, multicall, multicall_down, call_remote1, call_remote2,
+ [start, {group,stop}, crash, call, send_request,
+ send_request_receive_reqid_collection, send_request_wait_reqid_collection,
+ send_request_check_reqid_collection, cast, cast_fast, info, abcast,
+ continue, multicall, multicall_down, call_remote1, call_remote2, calling_self,
call_remote3, call_remote_n1, call_remote_n2,
call_remote_n3, spec_init,
spec_init_local_registered_parent,
spec_init_global_registered_parent, otp_5854, hibernate, auto_hibernate,
otp_7669,
- call_format_status, error_format_status, terminate_crash_format,
+ {group, format_status},
get_state, replace_state,
call_with_huge_message_queue, {group, undef_callbacks},
undef_in_terminate, undef_in_handle_info,
@@ -80,12 +87,18 @@ all() ->
groups() ->
[{stop, [],
[stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10]},
+ {format_status, [],
+ [call_format_status, error_format_status, terminate_crash_format,
+ crash_in_format_status, throw_in_format_status, format_all_status]},
{undef_callbacks, [],
[undef_handle_call, undef_handle_cast, undef_handle_info, undef_handle_continue,
undef_init, undef_code_change, undef_terminate1, undef_terminate2]}].
init_per_suite(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Server = filename:join(DataDir, "format_status_server.erl"),
+ {ok, format_status_server} = compile:file(Server),
Config.
end_per_suite(_Config) ->
@@ -110,18 +123,19 @@ init_per_testcase(Case, Config) when Case == call_remote1;
Case == call_remote_n2;
Case == call_remote_n3;
Case == send_request ->
- {ok,N} = start_node(hubba),
- [{node,N} | Config];
+ {ok,Peer,Node} = ?CT_PEER(),
+ ok = global:sync(),
+ [{node,Node}, {peer, Peer} | Config];
init_per_testcase(_Case, Config) ->
Config.
end_per_testcase(_Case, Config) ->
- case proplists:get_value(node, Config) of
+ case proplists:get_value(peer, Config) of
undefined ->
ok;
- N ->
- test_server:stop_node(N)
+ Peer ->
+ peer:stop(Peer)
end,
ok.
@@ -365,20 +379,20 @@ stop7(_Config) ->
%% Anonymous on remote node
stop8(_Config) ->
- {ok,Node} = test_server:start_node(gen_server_SUITE_stop8,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_server,start,[?MODULE,[],[]]),
ok = gen_server:stop(Pid),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_server:stop(Pid)),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
{'EXIT',{{nodedown,Node},_}} = (catch gen_server:stop(Pid)),
ok.
%% Registered name on remote node
stop9(_Config) ->
- {ok,Node} = test_server:start_node(gen_server_SUITE_stop9,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_server,start,[{local,to_stop},?MODULE,[],[]]),
@@ -386,13 +400,13 @@ stop9(_Config) ->
undefined = rpc:call(Node,erlang,whereis,[to_stop]),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_server:stop({to_stop,Node})),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
{'EXIT',{{nodedown,Node},_}} = (catch gen_server:stop({to_stop,Node})),
ok.
%% Globally registered name on remote node
stop10(_Config) ->
- {ok,Node} = test_server:start_node(gen_server_SUITE_stop10,slave,[]),
+ {ok,Peer,Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
{ok, Pid} = rpc:call(Node,gen_server,start,[{global,to_stop},?MODULE,[],[]]),
@@ -400,7 +414,7 @@ stop10(_Config) ->
ok = gen_server:stop({global,to_stop}),
false = rpc:call(Node,erlang,is_process_alive,[Pid]),
{'EXIT',noproc} = (catch gen_server:stop({global,to_stop})),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
{'EXIT',noproc} = (catch gen_server:stop({global,to_stop})),
ok.
@@ -590,6 +604,323 @@ send_request(Config) when is_list(Config) ->
process_flag(trap_exit, OldFl),
ok.
+send_request_receive_reqid_collection(Config) when is_list(Config) ->
+ {ok, Pid1} = gen_server:start_link({local, my_test_name1},
+ gen_server_SUITE, [], []),
+ {ok, Pid2} = gen_server:start_link({local, my_test_name2},
+ gen_server_SUITE, [], []),
+ {ok, Pid3} = gen_server:start_link({local, my_test_name3},
+ gen_server_SUITE, [], []),
+ send_request_receive_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_receive_reqid_collection_timeout(Pid1, Pid2, Pid3),
+ send_request_receive_reqid_collection_error(Pid1, Pid2, Pid3),
+ unlink(Pid1),
+ exit(Pid1, kill),
+ unlink(Pid2),
+ exit(Pid2, kill),
+ unlink(Pid3),
+ exit(Pid3, kill),
+ false = is_process_alive(Pid1),
+ false = is_process_alive(Pid2),
+ false = is_process_alive(Pid3),
+ ok.
+
+send_request_receive_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = gen_server:reqids_size(ReqIdC1),
+
+ ReqIdC2 = gen_server:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+ 2 = gen_server:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_server:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_server:reqids_size(ReqIdC3),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_server:receive_response(ReqIdC3, infinity, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_server:receive_response(ReqIdC4, 5678, true),
+ 1 = gen_server:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_server:receive_response(ReqIdC5, 5000, true),
+ 0 = gen_server:reqids_size(ReqIdC6),
+
+ no_request = gen_server:receive_response(ReqIdC6, 5000, true),
+
+ {reply, ok} = gen_server:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_timeout(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,1000}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = gen_server:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqId3 = gen_server:send_request(Pid3, {delayed_answer,500}),
+ ReqIdC3 = gen_server:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_server:receive_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ timeout = gen_server:receive_response(ReqIdC4, {abs, Deadline}, true),
+
+ Abandoned = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Abandoned = lists:sort(gen_server:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were abandoned...
+ timeout = gen_server:receive_response(ReqIdC4, {abs, Deadline+1000}, true),
+
+ {reply, ok} = gen_server:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_server:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ ReqIdC2 = gen_server:send_request(Pid2, stop_shutdown, req2, ReqIdC1),
+ ReqIdC3 = gen_server:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_server:reqids_size(ReqIdC3),
+
+ {{error, {shutdown, _}}, req2, ReqIdC4} = gen_server:receive_response(ReqIdC3, 2000, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC4} = gen_server:receive_response(ReqIdC4, infinity, false),
+
+ {{reply, delayed}, req1, ReqIdC4} = gen_server:receive_response(ReqIdC4, infinity, false),
+
+ {reply, ok} = gen_server:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection(Config) when is_list(Config) ->
+ {ok, Pid1} = gen_server:start_link({local, my_test_name1},
+ gen_server_SUITE, [], []),
+ {ok, Pid2} = gen_server:start_link({local, my_test_name2},
+ gen_server_SUITE, [], []),
+ {ok, Pid3} = gen_server:start_link({local, my_test_name3},
+ gen_server_SUITE, [], []),
+ send_request_wait_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_wait_reqid_collection_timeout(Pid1, Pid2, Pid3),
+ send_request_wait_reqid_collection_error(Pid1, Pid2, Pid3),
+ unlink(Pid1),
+ exit(Pid1, kill),
+ unlink(Pid2),
+ exit(Pid2, kill),
+ unlink(Pid3),
+ exit(Pid3, kill),
+ false = is_process_alive(Pid1),
+ false = is_process_alive(Pid2),
+ false = is_process_alive(Pid3),
+ ok.
+
+send_request_wait_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = gen_server:reqids_size(ReqIdC1),
+
+ ReqIdC2 = gen_server:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+ 2 = gen_server:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_server:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_server:reqids_size(ReqIdC3),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_server:wait_response(ReqIdC3, infinity, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_server:wait_response(ReqIdC4, 5678, true),
+ 1 = gen_server:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_server:wait_response(ReqIdC5, 5000, true),
+ 0 = gen_server:reqids_size(ReqIdC6),
+
+ no_request = gen_server:wait_response(ReqIdC6, 5000, true),
+
+ {reply, ok} = gen_server:wait_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection_timeout(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,1000}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = gen_server:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqId3 = gen_server:send_request(Pid3, {delayed_answer,500}),
+ ReqIdC3 = gen_server:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_server:wait_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ timeout = gen_server:wait_response(ReqIdC4, {abs, Deadline}, true),
+
+ Unhandled = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Unhandled = lists:sort(gen_server:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were not abandoned...
+ {{reply, delayed}, req3, ReqIdC4} = gen_server:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+ {{reply, delayed}, req1, ReqIdC4} = gen_server:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+
+ {reply, ok} = gen_server:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_server:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ ReqIdC2 = gen_server:send_request(Pid2, stop_shutdown, req2, ReqIdC1),
+ ReqIdC3 = gen_server:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_server:reqids_size(ReqIdC3),
+
+ {{error, {shutdown, _}}, req2, ReqIdC4} = gen_server:wait_response(ReqIdC3, 2000, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC4} = gen_server:wait_response(ReqIdC4, infinity, false),
+
+ {{reply, delayed}, req1, ReqIdC4} = gen_server:wait_response(ReqIdC4, infinity, false),
+
+ {reply, ok} = gen_server:wait_response(ReqId0, infinity),
+
+ ok.
+
+send_request_check_reqid_collection(Config) when is_list(Config) ->
+ {ok, Pid1} = gen_server:start_link({local, my_test_name1},
+ gen_server_SUITE, [], []),
+ {ok, Pid2} = gen_server:start_link({local, my_test_name2},
+ gen_server_SUITE, [], []),
+ {ok, Pid3} = gen_server:start_link({local, my_test_name3},
+ gen_server_SUITE, [], []),
+ send_request_check_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_check_reqid_collection_error(Pid1, Pid2, Pid3),
+ unlink(Pid1),
+ exit(Pid1, kill),
+ unlink(Pid2),
+ exit(Pid2, kill),
+ unlink(Pid3),
+ exit(Pid3, kill),
+ false = is_process_alive(Pid1),
+ false = is_process_alive(Pid2),
+ false = is_process_alive(Pid3),
+ ok.
+
+send_request_check_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ receive after 100 -> ok end,
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqIdC1 = gen_server:send_request(Pid1, {delayed_answer,400}, req1, ReqIdC0),
+ 1 = gen_server:reqids_size(ReqIdC1),
+
+ ReqId2 = gen_server:send_request(Pid2, {delayed_answer,1}),
+ ReqIdC2 = gen_server:reqids_add(ReqId2, req2, ReqIdC1),
+ 2 = gen_server:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_server:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_server:reqids_size(ReqIdC3),
+
+ Msg0 = next_msg(),
+ no_reply = gen_server:check_response(Msg0, ReqIdC3, true),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_server:check_response(next_msg(), ReqIdC3, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_server:check_response(next_msg(), ReqIdC4, true),
+ 1 = gen_server:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_server:check_response(next_msg(), ReqIdC5, true),
+ 0 = gen_server:reqids_size(ReqIdC6),
+
+ no_request = gen_server:check_response(Msg0, ReqIdC6, true),
+
+ {reply, ok} = gen_server:check_response(Msg0, ReqId0),
+
+ ok.
+
+send_request_check_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_server:send_request(Pid1, started_p),
+
+ receive after 100 -> ok end,
+
+ ReqIdC0 = gen_server:reqids_new(),
+
+ ReqId1 = gen_server:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_server:reqids_add(ReqId1, req1, ReqIdC0),
+
+ unlink(Pid2),
+ ReqIdC2 = gen_server:send_request(Pid2, stop_shutdown, req2, ReqIdC1),
+
+ ReqIdC3 = gen_server:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_server:reqids_size(ReqIdC3),
+
+ Msg0 = next_msg(),
+
+ no_reply = gen_server:check_response(Msg0, ReqIdC3, true),
+
+ {{error, {shutdown, _}}, req2, ReqIdC4} = gen_server:check_response(next_msg(), ReqIdC3, true),
+ 2 = gen_server:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC4} = gen_server:check_response(next_msg(), ReqIdC4, false),
+
+ {{reply, delayed}, req1, ReqIdC4} = gen_server:check_response(next_msg(), ReqIdC4, false),
+
+ {reply, ok} = gen_server:check_response(Msg0, ReqId0),
+
+ ok.
+
+next_msg() ->
+ receive M -> M end.
%% --------------------------------------
%% Test handle_continue.
@@ -636,15 +967,6 @@ read_replies() ->
%% Test call to nonexisting processes on remote nodes
%% --------------------------------------
-start_node(Name) ->
- Pa = filename:dirname(code:which(?MODULE)),
- N = test_server:start_node(Name, slave, [{args, " -pa " ++ Pa}]),
- %% After starting a slave, it takes a little while until global knows
- %% about it, even if nodes() includes it, so we make sure that global
- %% knows about it before registering something on all nodes.
- ok = global:sync(),
- N.
-
call_remote1(Config) when is_list(Config) ->
N = hubba,
Node = proplists:get_value(node,Config),
@@ -691,7 +1013,7 @@ call_remote_n1(Config) when is_list(Config) ->
Node = proplists:get_value(node,Config),
{ok, _Pid} = rpc:call(Node, gen_server, start,
[{global, N}, ?MODULE, [], []]),
- _ = test_server:stop_node(Node),
+ peer:stop(proplists:get_value(peer,Config)),
{'EXIT', {noproc, _}} =
(catch gen_server:call({global, N}, started_p, infinity)),
@@ -703,7 +1025,7 @@ call_remote_n2(Config) when is_list(Config) ->
{ok, Pid} = rpc:call(Node, gen_server, start,
[{global, N}, ?MODULE, [], []]),
- _ = test_server:stop_node(Node),
+ peer:stop(proplists:get_value(peer,Config)),
{'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call(Pid,
started_p, infinity)),
@@ -714,13 +1036,22 @@ call_remote_n3(Config) when is_list(Config) ->
{ok, _Pid} = rpc:call(Node, gen_server, start,
[{local, piller}, ?MODULE, [], []]),
- _ = test_server:stop_node(Node),
+ peer:stop(proplists:get_value(peer,Config)),
{'EXIT', {{nodedown, Node}, _}} = (catch gen_server:call({piller, Node},
started_p, infinity)),
ok.
%% --------------------------------------
+%% Other bad calls
+%% --------------------------------------
+
+calling_self(Config) when is_list(Config) ->
+ {'EXIT', {calling_self, _}} = (catch gen_server:call(self(), oops)),
+ {'EXIT', {calling_self, _}} = (catch gen_server:call(self(), oops, infinity)),
+ ok.
+
+%% --------------------------------------
%% Test gen_server:cast and handle_cast.
%% Test all different return values from
%% handle_cast.
@@ -760,7 +1091,11 @@ cast(Config) when is_list(Config) ->
%% Test that cast really return immediately.
cast_fast(Config) when is_list(Config) ->
- {ok,Node} = start_node(hubba),
+ {ok,Peer,Node} = ?CT_PEER(),
+ %% After starting a slave, it takes a little while until global knows
+ %% about it, even if nodes() includes it, so we make sure that global
+ %% knows about it before registering something on all nodes.
+ ok = global:sync(),
{_,"@"++Host} = lists:splitwith(fun ($@) -> false; (_) -> true end,
atom_to_list(Node)),
FalseNode = list_to_atom("hopp@"++Host),
@@ -770,7 +1105,7 @@ cast_fast(Config) when is_list(Config) ->
{Time,ok} = timer:tc(fun() ->
gen_server:cast({hopp,FalseNode}, hopp)
end),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
if Time > 1000000 -> % Default listen timeout is about 7.0 s
ct:fail(hanging_cast);
true ->
@@ -1330,48 +1665,65 @@ do_otp_7669_stop() ->
?MODULE, stop, []),
undefined = global:whereis_name(?MODULE).
-%% Verify that sys:get_status correctly calls our format_status/2 fun.
+%% Verify that sys:get_status correctly calls our format_status/1,2 fun.
call_format_status(Config) when is_list(Config) ->
+ OldFl = process_flag(trap_exit, true),
+ call_format_status(?MODULE, format_status_called),
+ call_format_status(format_status_server,{data,[{"State",format_status_called}]}),
+ process_flag(trap_exit, OldFl).
+call_format_status(Module, Match) when is_atom(Module) ->
+
Parent = self(),
{ok, Pid} = gen_server:start_link({local, call_format_status},
- ?MODULE, [], []),
+ Module, [], []),
Status1 = sys:get_status(call_format_status),
{status, Pid, Mod, [_Pdict1, running, Parent, _, Data1]} = Status1,
- [format_status_called | _] = lists:reverse(Data1),
+ [Match | _] = lists:reverse(Data1),
Status2 = sys:get_status(call_format_status, 5000),
{status, Pid, Mod, [_Pdict2, running, Parent, _, Data2]} = Status2,
- [format_status_called | _] = lists:reverse(Data2),
+ [Match | _] = lists:reverse(Data2),
+ gen_server:call(Pid, stop),
+ receive {'EXIT',_,_} -> ok end,
%% check that format_status can handle a name being a pid (atom is
%% already checked by the previous test)
- {ok, Pid3} = gen_server:start_link(gen_server_SUITE, [], []),
+ {ok, Pid3} = gen_server:start_link(Module, [], []),
Status3 = sys:get_status(Pid3),
{status, Pid3, Mod, [_PDict3, running, Parent, _, Data3]} = Status3,
- [format_status_called | _] = lists:reverse(Data3),
+ [Match | _] = lists:reverse(Data3),
+ gen_server:call(Pid3, stop),
+ receive {'EXIT',_,_} -> ok end,
%% check that format_status can handle a name being a term other than a
%% pid or atom
GlobalName1 = {global, "CallFormatStatus"},
- {ok, Pid4} = gen_server:start_link(GlobalName1,
- gen_server_SUITE, [], []),
+ {ok, Pid4} = gen_server:start_link(GlobalName1, Module, [], []),
Status4 = sys:get_status(Pid4),
{status, Pid4, Mod, [_PDict4, running, Parent, _, Data4]} = Status4,
- [format_status_called | _] = lists:reverse(Data4),
+ [Match | _] = lists:reverse(Data4),
+ gen_server:call(Pid4, stop),
+ receive {'EXIT',_,_} -> ok end,
GlobalName2 = {global, {name, "term"}},
- {ok, Pid5} = gen_server:start_link(GlobalName2,
- gen_server_SUITE, [], []),
+ {ok, Pid5} = gen_server:start_link(GlobalName2, Module, [], []),
Status5 = sys:get_status(GlobalName2),
{status, Pid5, Mod, [_PDict5, running, Parent, _, Data5]} = Status5,
- [format_status_called | _] = lists:reverse(Data5),
+ [Match | _] = lists:reverse(Data5),
+ gen_server:call(Pid5, stop),
+ receive {'EXIT',_,_} -> ok end,
ok.
-%% Verify that error termination correctly calls our format_status/2 fun.
+%% Verify that error termination correctly calls our format_status/1,2 fun.
error_format_status(Config) when is_list(Config) ->
error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
+ error_format_status(?MODULE),
+ error_format_status(format_status_server),
+ process_flag(trap_exit, OldFl);
+error_format_status(Module) when is_atom(Module) ->
+
State = "called format_status",
- {ok, Pid} = gen_server:start_link(?MODULE, {state, State}, []),
+ {ok, Pid} = gen_server:start_link(Module, {state, State}, []),
{'EXIT',{crashed,_}} = (catch gen_server:call(Pid, crash)),
receive
{'EXIT', Pid, crashed} ->
@@ -1387,19 +1739,24 @@ error_format_status(Config) when is_list(Config) ->
ClientPid, [_|_] = _ClientStack]}} ->
ok;
Other ->
- io:format("Unexpected: ~p", [Other]),
+ ct:pal("Unexpected: ~p", [Other]),
ct:fail(failed)
end,
- process_flag(trap_exit, OldFl),
+ receive
+ {error_report,_,_} -> ok
+ end,
ok.
-%% Verify that error when terminating correctly calls our format_status/2 fun
-%%
+%% Verify that error when terminating correctly calls our format_status/1,2 fun
terminate_crash_format(Config) when is_list(Config) ->
error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
+ terminate_crash_format(?MODULE),
+ terminate_crash_format(format_status_server),
+ process_flag(trap_exit, OldFl);
+terminate_crash_format(Module) when is_atom(Module) ->
State = crash_terminate,
- {ok, Pid} = gen_server:start_link(?MODULE, {state, State}, []),
+ {ok, Pid} = gen_server:start_link(Module, {state, State}, []),
gen_server:call(Pid, stop),
receive {'EXIT', Pid, {crash, terminate}} -> ok end,
ClientPid = self(),
@@ -1418,9 +1775,167 @@ terminate_crash_format(Config) when is_list(Config) ->
io:format("Timeout: expected error logger msg", []),
ct:fail(failed)
end,
- process_flag(trap_exit, OldFl),
+ receive
+ {error_report,_,_} -> ok
+ end,
+ ok.
+
+crash_in_format_status(Config) when is_list(Config) ->
+ error_logger_forwarder:register(),
+ OldFl = process_flag(trap_exit, true),
+ crash_in_format_status(?MODULE, "gen_server_SUITE:format_status/2 crashed"),
+ crash_in_format_status(format_status_server, "format_status_server:format_status/1 crashed"),
+ process_flag(trap_exit, OldFl).
+crash_in_format_status(Module, Match) when is_atom(Module) ->
+ State = fun(_) -> exit({crash,format_status}) end,
+ {ok, Pid} = gen_server:start_link(Module, {state, State}, []),
+
+ {status,Pid, _, [_,_,_,_,Info]} = sys:get_status(Pid),
+ {data,[{"State",Match}]} = lists:last(Info),
+
+ gen_server:call(Pid, stop),
+ receive {'EXIT', Pid, stopped} -> ok end,
+ ClientPid = self(),
+ receive
+ {error,_GroupLeader,
+ {Pid,
+ "** Generic server"++_,
+ [Pid, stop, Match, stopped,
+ ClientPid, [_|_] = _ClientStack]}} ->
+ ok;
+ Other ->
+ ct:pal("Unexpected: ~p", [Other]),
+ ct:fail(failed)
+ after 5000 ->
+ io:format("Timeout: expected error logger msg", []),
+ ct:fail(failed)
+ end,
+ receive
+ {error_report,_,_} -> ok
+ end,
+ ok.
+
+throw_in_format_status(Config) when is_list(Config) ->
+ error_logger_forwarder:register(),
+ OldFl = process_flag(trap_exit, true),
+ throw_in_format_status(?MODULE,{throw,format_status}),
+ throw_in_format_status(format_status_server,"format_status_server:format_status/1 crashed"),
+ process_flag(trap_exit, OldFl).
+throw_in_format_status(Module, Match) when is_atom(Module) ->
+ State = fun(_) -> throw({throw,format_status}) end,
+ {ok, Pid} = gen_server:start_link(Module, {state, State}, []),
+
+ {status,Pid, _, [_,_,_,_,Info]} = sys:get_status(Pid),
+ case lists:last(Info) of
+ {data,[{"State",Match}]} ->
+ ok;
+ Match ->
+ ok
+ end,
+
+ gen_server:call(Pid, stop),
+ receive {'EXIT', Pid, stopped} -> ok end,
+ ClientPid = self(),
+ receive
+ {error,_GroupLeader,
+ {Pid, "** Generic server"++_,
+ [Pid, stop, Match, stopped,
+ ClientPid, [_|_] = _ClientStack]}} ->
+ ok;
+ Other ->
+ ct:pal("Unexpected: ~p", [Other]),
+ ct:fail(failed)
+ after 5000 ->
+ io:format("Timeout: expected error logger msg", []),
+ ct:fail(failed)
+ end,
+ receive
+ {error_report,_,_} -> ok
+ end,
ok.
+%% Test that the state, reason, message format status calls works as they should
+%% The test makes sure that both sys:get_status and the crash report works as they
+%% should and can be used to strip data from both the reason, message, state and the
+%% sys logger logs.
+
+%%%% The sys logger log messages that should be matched
+-define(LOG_MESSAGES,
+ {log,{in,{_,_,started_p}}},
+ {log,{out,ok,_,State}},
+ {log,{in,{_,_,{delayed_answer,10}}}},
+ {log,{noreply,{_,_,State}}},
+ {log,{in,timeout}},
+ {log,{noreply,State}}).
+
+format_all_status(Config) when is_list(Config) ->
+ error_logger_forwarder:register(),
+ OldFl = process_flag(trap_exit, true),
+
+ State = fun(M) ->
+ maps:map(
+ fun(log, Values) ->
+ [{log, Value} || Value <- Values];
+ (Key, Value) ->
+ {Key, Value}
+ end, M)
+ end,
+ {ok, Pid} = gen_server:start_link(format_status_server, {state, State}, []),
+ sys:log(Pid, true),
+ ok = gen_server:call(Pid, started_p),
+ delayed = gen_server:call(Pid, {delayed_answer, 10}),
+
+ {status,Pid, _, [_,_,_,_,Info]} = sys:get_status(Pid),
+ [{header, _Hdr},
+ {data, [_Status,_Parent,{"Logged events",LoggedEvents}]},
+ {data, [{"State",{state,State}}]}] = Info,
+
+ [?LOG_MESSAGES] = LoggedEvents,
+
+ ok = gen_server:call(Pid, stop),
+ receive {'EXIT', Pid, stopped} -> ok end,
+ ClientPid = self(),
+ receive
+ {error,_GroupLeader,
+ {Pid, "** Generic server"++_,
+ [Pid, {message, stop}, {state,State}, {reason, stopped},
+ ?LOG_MESSAGES, {log,{in,{_,_,stop}}},
+ ClientPid, [_|_] = _ClientStack]}} ->
+ ok;
+ Other ->
+ ct:pal("Unexpected: ~p", [Other]),
+ ct:fail(failed)
+ after 5000 ->
+ io:format("Timeout: expected error logger msg", []),
+ ct:fail(failed)
+ end,
+ receive
+ {error_report,_,_} -> ok
+ end,
+
+ {ok, Pid2} = gen_server:start_link(format_status_server, {state, State}, []),
+ catch gen_server:call(Pid2, crash),
+ receive {'EXIT', Pid2, crashed} -> ok end,
+ receive
+ {error,_GroupLeader2,
+ {Pid2, "** Generic server"++_,
+ [Pid2, {message, crash}, {state,State},
+ {{reason, crashed},[_|_] = _ServerStack},
+ ClientPid, [_|_] = _ClientStack2]}} ->
+ ok;
+ Other2 ->
+ ct:pal("Unexpected: ~p", [Other2]),
+ ct:fail(failed)
+ after 5000 ->
+ io:format("Timeout: expected error logger msg", []),
+ ct:fail(failed)
+ end,
+ receive
+ {error_report,_,_} -> ok
+ end,
+
+ process_flag(trap_exit, OldFl).
+
%% Verify that sys:get_state correctly returns gen_server state
get_state(Config) when is_list(Config) ->
State = self(),
@@ -1985,8 +2500,8 @@ init({state,State}) ->
handle_call(started_p, _From, State) ->
io:format("FROZ"),
{reply,ok,State};
-handle_call({delayed_answer, T}, From, _State) ->
- {noreply,{reply_to,From},T};
+handle_call({delayed_answer, T}, From, State) ->
+ {noreply,{reply_to,From,State},T};
handle_call({call_within, T}, _From, _) ->
{reply,ok,call_within,T};
handle_call(next_call, _From, call_within) ->
@@ -2042,9 +2557,9 @@ handle_cast({From, stop}, State) ->
io:format("BAZ"),
{stop, {From,stopped}, State}.
-handle_info(timeout, {reply_to, From}) ->
+handle_info(timeout, {reply_to, From, State}) ->
gen_server:reply(From, delayed),
- {noreply, []};
+ {noreply, State};
handle_info(timeout, hibernate_me) -> % Arrive here from
% handle_info(hibernate_later,...)
{noreply, [], hibernate};
@@ -2124,6 +2639,8 @@ terminate(_, {undef_in_terminate, {Mod, Fun}}) ->
terminate(_Reason, _State) ->
ok.
+format_status(_, [_PDict, Fun] = S) when is_function(Fun) ->
+ Fun(S);
format_status(terminate, [_PDict, State]) ->
{formatted, State};
format_status(normal, [_PDict, _State]) ->
diff --git a/lib/stdlib/test/gen_server_SUITE_data/format_status_server.erl b/lib/stdlib/test/gen_server_SUITE_data/format_status_server.erl
new file mode 100644
index 0000000000..96f1f74132
--- /dev/null
+++ b/lib/stdlib/test/gen_server_SUITE_data/format_status_server.erl
@@ -0,0 +1,55 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(format_status_server).
+
+-behaviour(gen_server).
+
+%% API
+-export([start/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, format_status/1]).
+
+start(Arg) ->
+ gen_server:start(?MODULE, ok, Arg).
+init(Args) ->
+ gen_server_SUITE:init(Args).
+handle_call(Call, From, State) ->
+ gen_server_SUITE:handle_call(Call, From, State).
+handle_cast(Cast, State) ->
+ gen_server_SUITE:handle_cast(Cast, State).
+handle_info(Info, State) ->
+ gen_server_SUITE:handle_info(Info, State).
+terminate(Reason, State) ->
+ gen_server_SUITE:terminate(Reason, State).
+
+format_status(#{ state := Fun } = S) when is_function(Fun) ->
+ Fun(S);
+format_status(#{ state := {_,_,Fun} } = S) when is_function(Fun) ->
+ Fun(S);
+format_status(#{ message := Msg } = S) when not is_map_key(state, S) ->
+ S#{message := {message,Msg}};
+format_status(#{ reason := _, state := State } = Map) ->
+ ct:pal("format_status(~p)",[Map]),
+ Map#{ state => {formatted, State}};
+format_status(Map) ->
+ ct:pal("format_status(~p)",[Map]),
+ Map#{ state => format_status_called }.
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index b9084cc825..9b4ee9413f 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,9 @@ all() ->
{group, sys},
hibernate, auto_hibernate, enter_loop, {group, undef_callbacks},
undef_in_terminate, {group, format_log},
- reply_by_alias_with_payload].
+ reply_by_alias_with_payload,
+ send_request_receive_reqid_collection, send_request_wait_reqid_collection,
+ send_request_check_reqid_collection].
groups() ->
[{start, [], tcs(start)},
@@ -53,6 +55,7 @@ groups() ->
{abnormal, [], tcs(abnormal)},
{abnormal_handle_event, [], tcs(abnormal)},
{sys, [], tcs(sys)},
+ {format_status, [], tcs(format_status)},
{sys_handle_event, [], tcs(sys)},
{undef_callbacks, [], tcs(undef_callbacks)},
{format_log, [], tcs(format_log)}].
@@ -66,9 +69,10 @@ tcs(abnormal) ->
[abnormal1, abnormal1clean, abnormal1dirty,
abnormal2, abnormal3, abnormal4];
tcs(sys) ->
- [sys1, call_format_status,
- error_format_status, terminate_crash_format,
- get_state, replace_state];
+ [sys1, {group, format_status}, get_state, replace_state];
+tcs(format_status) ->
+ [call_format_status, error_format_status, terminate_crash_format,
+ format_all_status];
tcs(undef_callbacks) ->
[undef_code_change, undef_terminate1, undef_terminate2,
pop_too_many];
@@ -88,7 +92,13 @@ init_per_group(GroupName, Config)
GroupName =:= sys_handle_event ->
[{callback_mode,handle_event_function}|Config];
init_per_group(undef_callbacks, Config) ->
- compile_oc_statem(Config),
+ try compile_oc_statem(Config)
+ catch Class : Reason : Stacktrace ->
+ {fail,{Class,Reason,Stacktrace}}
+ end,
+ Config;
+init_per_group(sys, Config) ->
+ compile_format_status_statem(Config),
Config;
init_per_group(_GroupName, Config) ->
Config.
@@ -119,6 +129,12 @@ compile_oc_statem(Config) ->
{ok, oc_statem} = compile:file(StatemPath),
ok.
+compile_format_status_statem(Config) ->
+ DataDir = ?config(data_dir, Config),
+ StatemPath = filename:join(DataDir, "format_status_statem.erl"),
+ {ok, format_status_statem} = compile:file(StatemPath),
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(EXPECT_FAILURE(Code, Reason),
try begin Code end of
@@ -452,76 +468,64 @@ stop7(Config) ->
%% Anonymous on remote node
stop8(Config) ->
- Node = gen_statem_stop8,
- {ok,NodeName} = ct_slave:start(Node),
- Statem =
- try
- Dir = filename:dirname(code:which(?MODULE)),
- rpc:block_call(NodeName, code, add_path, [Dir]),
- {ok,Pid} =
- rpc:block_call(
- NodeName, gen_statem,start,
- [?MODULE,start_arg(Config, []),[]]),
- ok = gen_statem:stop(Pid),
- false = rpc:block_call(NodeName, erlang, is_process_alive, [Pid]),
- noproc =
- ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason1),
- Pid
- after
- {ok,NodeName} = ct_slave:stop(Node)
- end,
+ {ok,Peer,NodeName} = ?CT_PEER(),
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:block_call(NodeName, code, add_path, [Dir]),
+ {ok,Pid} =
+ rpc:block_call(
+ NodeName, gen_statem,start,
+ [?MODULE,start_arg(Config, []),[]]),
+ ok = gen_statem:stop(Pid),
+ false = rpc:block_call(NodeName, erlang, is_process_alive, [Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason1),
+
+ peer:stop(Peer),
{{nodedown,NodeName},{sys,terminate,_}} =
- ?EXPECT_FAILURE(gen_statem:stop(Statem), Reason2),
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason2),
ok.
%% Registered name on remote node
stop9(Config) ->
Name = to_stop,
LocalSTM = {local,Name},
- Node = gen_statem__stop9,
- {ok,NodeName} = ct_slave:start(Node),
- Statem =
- try
- STM = {Name,NodeName},
- Dir = filename:dirname(code:which(?MODULE)),
- rpc:block_call(NodeName, code, add_path, [Dir]),
- {ok,Pid} =
- rpc:block_call(
- NodeName, gen_statem, start,
- [LocalSTM,?MODULE,start_arg(Config, []),[]]),
- ok = gen_statem:stop(STM),
- undefined = rpc:block_call(NodeName,erlang,whereis,[Name]),
- false = rpc:block_call(NodeName,erlang,is_process_alive,[Pid]),
- noproc =
- ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
- STM
- after
- {ok,NodeName} = ct_slave:stop(Node)
- end,
+ {ok,Peer,NodeName} = ?CT_PEER(),
+
+ STM = {Name,NodeName},
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:block_call(NodeName, code, add_path, [Dir]),
+ {ok,Pid} =
+ rpc:block_call(
+ NodeName, gen_statem, start,
+ [LocalSTM,?MODULE,start_arg(Config, []),[]]),
+ ok = gen_statem:stop(STM),
+ undefined = rpc:block_call(NodeName,erlang,whereis,[Name]),
+ false = rpc:block_call(NodeName,erlang,is_process_alive,[Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
+ peer:stop(Peer),
+
{{nodedown,NodeName},{sys,terminate,_}} =
- ?EXPECT_FAILURE(gen_statem:stop(Statem), Reason2),
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason2),
ok.
%% Globally registered name on remote node
stop10(Config) ->
- Node = gen_statem_stop10,
STM = {global,to_stop},
- {ok,NodeName} = ct_slave:start(Node),
- try
- Dir = filename:dirname(code:which(?MODULE)),
- rpc:block_call(NodeName,code,add_path,[Dir]),
- {ok,Pid} =
- rpc:block_call(
- NodeName, gen_statem, start,
- [STM,?MODULE,start_arg(Config, []),[]]),
- global:sync(),
- ok = gen_statem:stop(STM),
- false = rpc:block_call(NodeName, erlang, is_process_alive, [Pid]),
- noproc =
- ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1)
- after
- {ok,NodeName} = ct_slave:stop(Node)
- end,
+ {ok,Peer,NodeName} = ?CT_PEER(),
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:block_call(NodeName,code,add_path,[Dir]),
+ {ok,Pid} =
+ rpc:block_call(
+ NodeName, gen_statem, start,
+ [STM,?MODULE,start_arg(Config, []),[]]),
+ global:sync(),
+ ok = gen_statem:stop(STM),
+ false = rpc:block_call(NodeName, erlang, is_process_alive, [Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
+ peer:stop(Peer),
+
noproc =
?EXPECT_FAILURE(gen_statem:stop(STM), Reason2),
ok.
@@ -1240,20 +1244,24 @@ code_change(_Config) ->
stop_it(Pid).
call_format_status(Config) ->
- {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ call_format_status(Config,?MODULE,format_status_called),
+ call_format_status(Config, format_status_statem,
+ {data,[{"State",{format_status_called,format_data}}]}).
+call_format_status(Config, Module, Match) ->
+ {ok,Pid} = gen_statem:start(Module, start_arg(Config, []), []),
Status = sys:get_status(Pid),
{status,Pid,_Mod,[_PDict,running,_,_, Data]} = Status,
- [format_status_called|_] = lists:reverse(Data),
+ [Match|_] = lists:reverse(Data),
stop_it(Pid),
%% check that format_status can handle a name being an atom (pid is
%% already checked by the previous test)
{ok, Pid2} =
gen_statem:start(
- {local, gstm}, ?MODULE, start_arg(Config, []), []),
+ {local, gstm}, Module, start_arg(Config, []), []),
Status2 = sys:get_status(gstm),
{status,Pid2,Mod,[_PDict2,running,_,_,Data2]} = Status2,
- [format_status_called|_] = lists:reverse(Data2),
+ [Match|_] = lists:reverse(Data2),
stop_it(Pid2),
%% check that format_status can handle a name being a term other than a
@@ -1261,47 +1269,54 @@ call_format_status(Config) ->
GlobalName1 = {global,"CallFormatStatus"},
{ok,Pid3} =
gen_statem:start(
- GlobalName1, ?MODULE, start_arg(Config, []), []),
+ GlobalName1, Module, start_arg(Config, []), []),
Status3 = sys:get_status(GlobalName1),
{status,Pid3,Mod,[_PDict3,running,_,_,Data3]} = Status3,
- [format_status_called|_] = lists:reverse(Data3),
+ [Match|_] = lists:reverse(Data3),
stop_it(Pid3),
GlobalName2 = {global,{name, "term"}},
{ok,Pid4} =
gen_statem:start(
- GlobalName2, ?MODULE, start_arg(Config, []), []),
+ GlobalName2, Module, start_arg(Config, []), []),
Status4 = sys:get_status(GlobalName2),
{status,Pid4,Mod,[_PDict4,running,_,_, Data4]} = Status4,
- [format_status_called|_] = lists:reverse(Data4),
+ [Match|_] = lists:reverse(Data4),
stop_it(Pid4),
%% check that format_status can handle a name being a term other than a
%% pid or atom
dummy_via:reset(),
ViaName1 = {via,dummy_via,"CallFormatStatus"},
- {ok,Pid5} = gen_statem:start(ViaName1, ?MODULE, start_arg(Config, []), []),
+ {ok,Pid5} = gen_statem:start(ViaName1, Module, start_arg(Config, []), []),
Status5 = sys:get_status(ViaName1),
{status,Pid5,Mod, [_PDict5,running,_,_, Data5]} = Status5,
- [format_status_called|_] = lists:reverse(Data5),
+ [Match|_] = lists:reverse(Data5),
stop_it(Pid5),
ViaName2 = {via,dummy_via,{name,"term"}},
{ok, Pid6} =
gen_statem:start(
- ViaName2, ?MODULE, start_arg(Config, []), []),
+ ViaName2, Module, start_arg(Config, []), []),
Status6 = sys:get_status(ViaName2),
{status,Pid6,Mod,[_PDict6,running,_,_,Data6]} = Status6,
- [format_status_called|_] = lists:reverse(Data6),
+ [Match|_] = lists:reverse(Data6),
stop_it(Pid6).
-
-
error_format_status(Config) ->
error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
+ try
+ error_format_status(Config,?MODULE,{formatted,idle,"called format_status"}),
+ error_format_status(Config,format_status_statem,
+ {{formatted,idle},{formatted,"called format_status"}})
+ after
+ process_flag(trap_exit, OldFl),
+ error_logger_forwarder:unregister()
+ end.
+error_format_status(Config,Module,Match) ->
Data = "called format_status",
{ok,Pid} =
gen_statem:start(
- ?MODULE, start_arg(Config, {data,Data}), []),
+ Module, start_arg(Config, {data,Data}), []),
%% bad return value in the gen_statem loop
{{{bad_return_from_state_function,badreturn},_},_} =
?EXPECT_FAILURE(gen_statem:call(Pid, badreturn), Reason),
@@ -1310,18 +1325,15 @@ error_format_status(Config) ->
{Pid,
"** State machine"++_,
[Pid,{{call,_},badreturn},
- {formatted,idle,Data},
+ Match,
error,{bad_return_from_state_function,badreturn}|_]}} ->
ok;
Other when is_tuple(Other), element(1, Other) =:= error ->
- error_logger_forwarder:unregister(),
ct:fail({unexpected,Other})
after 1000 ->
- error_logger_forwarder:unregister(),
- ct:fail(timeout)
+ ct:fail({timeout,(fun F() -> receive M -> [M|F()] after 0 -> [] end end)()})
end,
- process_flag(trap_exit, OldFl),
- error_logger_forwarder:unregister(),
+
receive
%% Comes with SASL
{error_report,_,{Pid,crash_report,_}} ->
@@ -1332,12 +1344,24 @@ error_format_status(Config) ->
ok = verify_empty_msgq().
terminate_crash_format(Config) ->
+ dbg:tracer(),
error_logger_forwarder:register(),
OldFl = process_flag(trap_exit, true),
+ try
+ terminate_crash_format(Config,?MODULE,{formatted,idle,crash_terminate}),
+ terminate_crash_format(Config,format_status_statem,
+ {{formatted,idle},{formatted,crash_terminate}})
+ after
+ dbg:stop_clear(),
+ process_flag(trap_exit, OldFl),
+ error_logger_forwarder:unregister()
+ end.
+
+terminate_crash_format(Config, Module, Match) ->
Data = crash_terminate,
{ok,Pid} =
gen_statem:start(
- ?MODULE, start_arg(Config, {data,Data}), []),
+ Module, start_arg(Config, {data,Data}), []),
stop_it(Pid),
Self = self(),
receive
@@ -1346,18 +1370,14 @@ terminate_crash_format(Config) ->
"** State machine"++_,
[Pid,
{{call,{Self,_}},stop},
- {formatted,idle,Data},
- exit,{crash,terminate}|_]}} ->
+ Match,exit,{crash,terminate}|_]}} ->
ok;
Other when is_tuple(Other), element(1, Other) =:= error ->
- error_logger_forwarder:unregister(),
ct:fail({unexpected,Other})
after 1000 ->
- error_logger_forwarder:unregister(),
- ct:fail(timeout)
+ ct:fail({timeout,flush()})
end,
- process_flag(trap_exit, OldFl),
- error_logger_forwarder:unregister(),
+
receive
%% Comes with SASL
{error_report,_,{Pid,crash_report,_}} ->
@@ -1367,6 +1387,67 @@ terminate_crash_format(Config) ->
end,
ok = verify_empty_msgq().
+%% We test that all of the different status items can be
+%% formatted by the format_status/1 callback.
+format_all_status(Config) ->
+ error_logger_forwarder:register(),
+ OldFl = process_flag(trap_exit, true),
+
+ Data = fun(M) ->
+ maps:map(
+ fun(Key, Values) when Key =:= log;
+ Key =:= queue;
+ Key =:= postponed;
+ Key =:= timeouts ->
+ [{Key, Value} || Value <- Values];
+ (Key, Value) ->
+ {Key, Value}
+ end, M)
+ end,
+ {ok,Pid} =
+ gen_statem:start(
+ format_status_statem, start_arg(Config, {data,Data}), []),
+ sys:log(Pid, true),
+ ok = gen_statem:cast(Pid, postpone_event),
+ ok = gen_statem:cast(Pid, {timeout, 100000}),
+
+ {status,Pid, _, [_,_,_,_,Info]} = sys:get_status(Pid),
+ [{header, _Hdr},
+ {data, [_Status,_Parent,_Modules,
+ {"Time-outs",{1,[{timeouts,_}]}},
+ {"Logged Events",[{log,_}|_]},
+ {"Postponed",[{postponed,_}]}]},
+ {data, [{"State",{{state,idle},{data,Data}}}]}] = Info,
+
+ %% bad return value in the gen_statem loop
+ {{{bad_return_from_state_function,badreturn},_},_} =
+ ?EXPECT_FAILURE(gen_statem:call(Pid, badreturn), Reason),
+ Self = self(),
+ receive
+ {error,_GroupLeader,
+ {Pid,
+ "** State machine"++_,
+ [Pid,
+ {queue,{{call,{Self,_}},badreturn}},
+ {{state,idle},{data,Data}},error,
+ {reason,{bad_return_from_state_function,badreturn}},
+ __Modules,_StateFunctions,
+ [{postponed,{cast,postpone_event}}],
+ [_|_] = _Stacktrace,
+ {1,[{timeouts,{timeout,idle}}]},
+ [{log,_}|_] |_]}} ->
+ ok;
+ Other when is_tuple(Other), element(1, Other) =:= error ->
+ ct:fail({unexpected,Other})
+ after 1000 ->
+ ct:fail({timeout,flush()})
+ end,
+ receive
+ {error_report,_,_} -> ok
+ end,
+ error_logger_forwarder:unregister(),
+ process_flag(trap_exit, OldFl),
+ ok.
get_state(Config) ->
State = self(),
@@ -1851,12 +1932,14 @@ pop_too_many(_Config) ->
Machine =
#{init =>
fun () ->
- {ok,start,undefined}
+ {ok,state_1,undefined}
end,
- start =>
- fun ({call, From}, {change_callback_module, _Module} = Action,
- undefined = _Data) ->
- {keep_state_and_data,
+ state_1 =>
+ fun (enter, state_2, undefined) ->
+ {keep_state, enter}; % OTP-18239, should not be called
+ ({call, From}, {change_callback_module, _Module} = Action,
+ undefined = Data) ->
+ {next_state, state_2, Data,
[Action,
{reply,From,ok}]};
({call, From}, {verify, ?MODULE},
@@ -1864,8 +1947,8 @@ pop_too_many(_Config) ->
{keep_state_and_data,
[{reply,From,ok}]};
({call, From}, pop_callback_module = Action,
- undefined = _Data) ->
- {keep_state_and_data,
+ undefined = Data) ->
+ {next_state, state_2, Data,
[Action,
{reply,From,ok}]}
end},
@@ -1875,10 +1958,11 @@ pop_too_many(_Config) ->
{map_statem, Machine, []},
[{debug, [trace]}]),
- ok = gen_statem:call(STM, {change_callback_module, oc_statem}),
- ok = gen_statem:call(STM, {push_callback_module, ?MODULE}),
- ok = gen_statem:call(STM, {verify, ?MODULE}),
- ok = gen_statem:call(STM, pop_callback_module),
+ ok = gen_statem:call(STM, {change_callback_module, oc_statem}),
+ enter = gen_statem:call(STM, get_data), % OTP-18239
+ ok = gen_statem:call(STM, {push_callback_module, ?MODULE}),
+ ok = gen_statem:call(STM, {verify, ?MODULE}),
+ ok = gen_statem:call(STM, pop_callback_module),
BadAction = {bad_action_from_state_function, pop_callback_module},
{{BadAction, _},
{gen_statem,call,[STM,pop_callback_module,infinity]}} =
@@ -2229,6 +2313,311 @@ reply_by_alias_with_payload(Config) when is_list(Config) ->
ok
end.
+send_request_receive_reqid_collection(Config) when is_list(Config) ->
+ {ok,Pid1} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid2} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid3} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ send_request_receive_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_receive_reqid_collection_timeout(Pid1, Pid2, Pid3),
+ send_request_receive_reqid_collection_error(Pid1, Pid2, Pid3),
+ stopped = gen_statem:call(Pid1, {stop,shutdown}),
+ stopped = gen_statem:call(Pid3, {stop,shutdown}),
+ check_stopped(Pid1),
+ check_stopped(Pid2),
+ check_stopped(Pid3),
+ ok.
+
+send_request_receive_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = gen_statem:reqids_size(ReqIdC1),
+
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+ 2 = gen_statem:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_statem:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_statem:reqids_size(ReqIdC3),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_statem:receive_response(ReqIdC3, infinity, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_statem:receive_response(ReqIdC4, 5678, true),
+ 1 = gen_statem:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_statem:receive_response(ReqIdC5, 5000, true),
+ 0 = gen_statem:reqids_size(ReqIdC6),
+
+ no_request = gen_statem:receive_response(ReqIdC6, 5000, true),
+
+ {reply, yes} = gen_statem:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_timeout(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,1000}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqId3 = gen_statem:send_request(Pid3, {delayed_answer,500}),
+ ReqIdC3 = gen_statem:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_statem:receive_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ timeout = gen_statem:receive_response(ReqIdC4, {abs, Deadline}, true),
+
+ Abandoned = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Abandoned = lists:sort(gen_statem:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were abandoned...
+ timeout = gen_statem:receive_response(ReqIdC4, {abs, Deadline+1000}, true),
+
+ {reply, yes} = gen_statem:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_receive_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_statem:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ exit(Pid2, kill),
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+ ReqIdC3 = gen_statem:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_statem:reqids_size(ReqIdC3),
+
+ {{error, {noproc, _}}, req2, ReqIdC4} = gen_statem:receive_response(ReqIdC3, 2000, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC4} = gen_statem:receive_response(ReqIdC4, infinity, false),
+
+ {{reply, delayed}, req1, ReqIdC4} = gen_statem:receive_response(ReqIdC4, infinity, false),
+
+ {reply, yes} = gen_statem:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection(Config) when is_list(Config) ->
+ {ok,Pid1} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid2} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid3} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ send_request_wait_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_wait_reqid_collection_timeout(Pid1, Pid2, Pid3),
+ send_request_wait_reqid_collection_error(Pid1, Pid2, Pid3),
+ stopped = gen_statem:call(Pid1, {stop,shutdown}),
+ stopped = gen_statem:call(Pid3, {stop,shutdown}),
+ check_stopped(Pid1),
+ check_stopped(Pid2),
+ check_stopped(Pid3),
+ ok.
+
+send_request_wait_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+ 1 = gen_statem:reqids_size(ReqIdC1),
+
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+ 2 = gen_statem:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_statem:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_statem:reqids_size(ReqIdC3),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_statem:wait_response(ReqIdC3, infinity, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_statem:wait_response(ReqIdC4, 5678, true),
+ 1 = gen_statem:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_statem:wait_response(ReqIdC5, 5000, true),
+ 0 = gen_statem:reqids_size(ReqIdC6),
+
+ no_request = gen_statem:wait_response(ReqIdC6, 5000, true),
+
+ {reply, yes} = gen_statem:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_wait_reqid_collection_timeout(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,1000}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqId3 = gen_statem:send_request(Pid3, {delayed_answer,500}),
+ ReqIdC3 = gen_statem:reqids_add(ReqId3, req3, ReqIdC2),
+
+ Deadline = erlang:monotonic_time(millisecond) + 100,
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_statem:wait_response(ReqIdC3, {abs, Deadline}, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ timeout = gen_statem:wait_response(ReqIdC4, {abs, Deadline}, true),
+
+ Unhandled = lists:sort([{ReqId1, req1}, {ReqId3, req3}]),
+ Unhandled = lists:sort(gen_statem:reqids_to_list(ReqIdC4)),
+
+ %% Make sure requests were not abandoned...
+ {{reply, delayed}, req3, ReqIdC4} = gen_statem:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+ {{reply, delayed}, req1, ReqIdC4} = gen_statem:wait_response(ReqIdC4, {abs, Deadline+1500}, false),
+
+ {reply, yes} = gen_statem:receive_response(ReqId0),
+
+ ok.
+
+send_request_wait_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_statem:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ exit(Pid2, kill),
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+ ReqIdC3 = gen_statem:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_statem:reqids_size(ReqIdC3),
+
+ {{error, {noproc, _}}, req2, ReqIdC4} = gen_statem:wait_response(ReqIdC3, 2000, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC4} = gen_statem:wait_response(ReqIdC4, infinity, false),
+
+ {{reply, delayed}, req1, ReqIdC4} = gen_statem:wait_response(ReqIdC4, infinity, false),
+
+ {reply, yes} = gen_statem:receive_response(ReqId0, infinity),
+
+ ok.
+
+send_request_check_reqid_collection(Config) when is_list(Config) ->
+ {ok,Pid1} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid2} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid3} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ send_request_check_reqid_collection(Pid1, Pid2, Pid3),
+ send_request_check_reqid_collection_error(Pid1, Pid2, Pid3),
+ stopped = gen_statem:call(Pid1, {stop,shutdown}),
+ stopped = gen_statem:call(Pid3, {stop,shutdown}),
+ check_stopped(Pid1),
+ check_stopped(Pid2),
+ check_stopped(Pid3),
+ ok.
+
+send_request_check_reqid_collection(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ receive after 100 -> ok end,
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqIdC1 = gen_statem:send_request(Pid1, {delayed_answer,400}, req1, ReqIdC0),
+ 1 = gen_statem:reqids_size(ReqIdC1),
+
+ ReqId2 = gen_statem:send_request(Pid2, {delayed_answer,1}),
+ ReqIdC2 = gen_statem:reqids_add(ReqId2, req2, ReqIdC1),
+ 2 = gen_statem:reqids_size(ReqIdC2),
+
+ ReqIdC3 = gen_statem:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_statem:reqids_size(ReqIdC3),
+
+ Msg0 = next_msg(),
+ no_reply = gen_statem:check_response(Msg0, ReqIdC3, true),
+
+ {{reply, delayed}, req2, ReqIdC4} = gen_statem:check_response(next_msg(), ReqIdC3, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC5} = gen_statem:check_response(next_msg(), ReqIdC4, true),
+ 1 = gen_statem:reqids_size(ReqIdC5),
+
+ {{reply, delayed}, req1, ReqIdC6} = gen_statem:check_response(next_msg(), ReqIdC5, true),
+ 0 = gen_statem:reqids_size(ReqIdC6),
+
+ no_request = gen_statem:check_response(Msg0, ReqIdC6, true),
+
+ {reply, yes} = gen_statem:check_response(Msg0, ReqId0),
+
+ ok.
+
+send_request_check_reqid_collection_error(Pid1, Pid2, Pid3) ->
+
+ ReqId0 = gen_statem:send_request(Pid1, 'alive?'),
+
+ receive after 100 -> ok end,
+
+ ReqIdC0 = gen_statem:reqids_new(),
+
+ ReqId1 = gen_statem:send_request(Pid1, {delayed_answer,400}),
+ ReqIdC1 = gen_statem:reqids_add(ReqId1, req1, ReqIdC0),
+ try
+ nope = gen_statem:reqids_add(ReqId1, req2, ReqIdC1)
+ catch
+ error:badarg -> ok
+ end,
+
+ unlink(Pid2),
+ exit(Pid2, kill),
+ ReqIdC2 = gen_statem:send_request(Pid2, {delayed_answer,1}, req2, ReqIdC1),
+
+ ReqIdC3 = gen_statem:send_request(Pid3, {delayed_answer,200}, req3, ReqIdC2),
+ 3 = gen_statem:reqids_size(ReqIdC3),
+
+ Msg0 = next_msg(),
+
+ no_reply = gen_statem:check_response(Msg0, ReqIdC3, true),
+
+ {{error, {noproc, _}}, req2, ReqIdC4} = gen_statem:check_response(next_msg(), ReqIdC3, true),
+ 2 = gen_statem:reqids_size(ReqIdC4),
+
+ {{reply, delayed}, req3, ReqIdC4} = gen_statem:check_response(next_msg(), ReqIdC4, false),
+
+ {{reply, delayed}, req1, ReqIdC4} = gen_statem:check_response(next_msg(), ReqIdC4, false),
+
+ {reply, yes} = gen_statem:check_response(Msg0, ReqId0),
+
+ ok.
+
+next_msg() ->
+ receive M -> M end.
+
%%
%% Functionality check
%%
@@ -2473,6 +2862,11 @@ idle({call,From}, {timeout,Time}, _Data) ->
AbsTime = erlang:monotonic_time(millisecond) + Time,
{next_state,timeout,{From,Time},
{timeout,AbsTime,idle,[{abs,true}]}};
+idle(cast, {timeout,Time}, _Data) ->
+ AbsTime = erlang:monotonic_time(millisecond) + Time,
+ {keep_state_and_data,{timeout,AbsTime,idle,[{abs,true}]}};
+idle(cast, postpone_event, _Data) ->
+ {keep_state_and_data,postpone};
idle(cast, next_event, _Data) ->
{next_state,next_events,[a,b,c],
[{next_event,internal,a},
diff --git a/lib/stdlib/test/gen_statem_SUITE_data/format_status_statem.erl b/lib/stdlib/test/gen_statem_SUITE_data/format_status_statem.erl
new file mode 100644
index 0000000000..7c0ee1f4d0
--- /dev/null
+++ b/lib/stdlib/test/gen_statem_SUITE_data/format_status_statem.erl
@@ -0,0 +1,40 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(format_status_statem).
+
+%% gen_statem callbacks
+-export(['$handle_undefined_function'/2, terminate/3, format_status/1]).
+
+'$handle_undefined_function'(format_status, [_,_]) ->
+ erlang:error(undef);
+'$handle_undefined_function'(Func, Args) ->
+ apply(gen_statem_SUITE, Func, Args).
+
+terminate(Reason, State, Data) ->
+ gen_statem_SUITE:terminate(Reason, State, Data).
+
+format_status(#{ data := Fun } = S) when is_function(Fun) ->
+ Fun(S);
+format_status(#{ reason := _, state := State, data := Data } = Map) ->
+ ct:pal("format_status(~p)",[Map]),
+ Map#{ state := {formatted, State}, data := {formatted, Data}};
+format_status(Map) ->
+ ct:pal("format_status(~p)",[Map]),
+ Map#{ data := format_data, state := format_status_called }.
diff --git a/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl b/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl
index 1de7de527b..04d9cfaad9 100644
--- a/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl
+++ b/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -49,22 +49,24 @@ init([]) ->
exit(Statem, kill)
end
end),
- {ok, start, #{}}.
+ {ok, state_2, [undefined]}.
callback_mode() ->
[handle_event_function, state_enter].
-handle_event(enter, start, start, _Data) ->
- keep_state_and_data;
+handle_event(enter, _OldState, state_2, [undefined|Data]) ->
+ {keep_state, [enter|Data]};
+handle_event({call,From}, get_data, state_2, Data) ->
+ {keep_state_and_data, [{reply,From,hd(Data)}]};
handle_event(
- {call,From}, {push_callback_module,NewModule} = Action,
- start, _Data) ->
- {keep_state_and_data,
+ {call,From}, {push_callback_module,_NewModule} = Action,
+ state_2, [enter|Data]) ->
+ {next_state, state_1, [undefined|Data],
[Action,
{reply,From,ok}]};
handle_event(
{call,From}, pop_callback_module = Action,
- start, _Data) ->
+ state_2, [enter|_Data]) ->
{keep_state_and_data,
[Action,
{reply,From,ok}]}.
diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl
index 0addf09461..a8d52c1680 100644
--- a/lib/stdlib/test/id_transform_SUITE.erl
+++ b/lib/stdlib/test/id_transform_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ end_per_group(_GroupName, Config) ->
id_transform(Config) when is_list(Config) ->
File = filename:join([code:lib_dir(stdlib),"examples",
"erl_id_trans.erl"]),
- {ok,erl_id_trans,Bin} = compile:file(File,[binary]),
+ {ok,erl_id_trans,Bin} = compile:file(File, [binary,report]),
{module,erl_id_trans} = code:load_binary(erl_id_trans, File, Bin),
case test_server:is_valgrind() of
false ->
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 046bd71ed6..17fd6d41fd 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@
io_fread_newlines/1, otp_8989/1, io_lib_fread_literal/1,
printable_range/1, bad_printable_range/1,
io_lib_print_binary_depth_one/1, otp_10302/1, otp_10755/1,
- otp_10836/1, io_lib_width_too_small/1,
+ otp_10836/1, io_lib_width_too_small/1, calling_self/1,
io_with_huge_message_queue/1, format_string/1, format_neg_zero/1,
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
@@ -63,7 +63,7 @@ all() ->
io_fread_newlines, otp_8989, io_lib_fread_literal,
printable_range, bad_printable_range, format_neg_zero,
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
- io_lib_width_too_small, io_with_huge_message_queue,
+ io_lib_width_too_small, io_with_huge_message_queue, calling_self,
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159,
otp_15639, otp_15705, otp_15847, otp_15875, github_4801, chars_limit,
@@ -210,6 +210,10 @@ float_w(Config) when is_list(Config) ->
ok.
+calling_self(Config) when is_list(Config) ->
+ {'EXIT', {calling_self, _}} = (catch io:format(self(), "~p", [oops])),
+ ok.
+
%% OTP-5403. ~s formats I/O lists and a single binary.
otp_5403(Config) when is_list(Config) ->
"atom" = fmt("~s", [atom]),
@@ -1966,22 +1970,16 @@ io_lib_fread_literal(Suite) when is_list(Suite) ->
%% Check that the printable range set by the user actually works.
printable_range(Suite) when is_list(Suite) ->
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
- [{args, " +pc unicode -pa " ++ Pa}]),
- {ok, LNode} = test_server:start_node(printable_range_latin1, slave,
- [{args, " +pc latin1 -pa " ++ Pa}]),
- {ok, DNode} = test_server:start_node(printable_range_default, slave,
- [{args, " -pa " ++ Pa}]),
- unicode = rpc:call(UNode,io,printable_range,[]),
- latin1 = rpc:call(LNode,io,printable_range,[]),
+ {ok, UPeer0, UNode0} = ?CT_PEER(["+pc", "unicode"]),
+ {ok, LPeer0, LNode0} = ?CT_PEER(["+pc", "latin1"]),
+ {ok, DPeer, DNode} = ?CT_PEER(),
+ unicode = rpc:call(UNode0,io,printable_range,[]),
+ latin1 = rpc:call(LNode0,io,printable_range,[]),
latin1 = rpc:call(DNode,io,printable_range,[]),
- test_server:stop_node(UNode),
- test_server:stop_node(LNode),
- {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
- [{args, " +pcunicode -pa " ++ Pa}]),
- {ok, LNode} = test_server:start_node(printable_range_latin1, slave,
- [{args, " +pclatin1 -pa " ++ Pa}]),
+ peer:stop(UPeer0),
+ peer:stop(LPeer0),
+ {ok, UPeer, UNode} = ?CT_PEER(["+pcunicode"]),
+ {ok, LPeer, LNode} = ?CT_PEER(["+pclatin1"]),
unicode = rpc:call(UNode,io,printable_range,[]),
latin1 = rpc:call(LNode,io,printable_range,[]),
PrettyOptions = [{column,1},
@@ -2029,9 +2027,9 @@ printable_range(Suite) when is_list(Suite) ->
$\e = format_max(LNode, ["~ts", [PrintableControls]]),
$\e = format_max(DNode, ["~ts", [PrintableControls]]),
- test_server:stop_node(UNode),
- test_server:stop_node(LNode),
- test_server:stop_node(DNode),
+ peer:stop(UPeer),
+ peer:stop(LPeer),
+ peer:stop(DPeer),
ok.
print_max(Node, Args) ->
@@ -2079,11 +2077,8 @@ io_lib_print_binary_depth_one(Suite) when is_list(Suite) ->
%% OTP-10302. Unicode.
otp_10302(Suite) when is_list(Suite) ->
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
- [{args, " +pc unicode -pa " ++ Pa}]),
- {ok, LNode} = test_server:start_node(printable_range_latin1, slave,
- [{args, " +pc latin1 -pa " ++ Pa}]),
+ {ok, UPeer, UNode} = ?CT_PEER(["+pc", "unicode"]),
+ {ok, LPeer, LNode} = ?CT_PEER(["+pc", "latin1"]),
"\"\x{400}\"" = rpc:call(UNode,?MODULE,pretty,["\x{400}", -1]),
"<<\"\x{400}\"/utf8>>" = rpc:call(UNode,?MODULE,pretty,
[<<"\x{400}"/utf8>>, -1]),
@@ -2094,8 +2089,8 @@ otp_10302(Suite) when is_list(Suite) ->
"<<208,128>>" = rpc:call(LNode,?MODULE,pretty,[<<"\x{400}"/utf8>>, -1]),
"<<208,...>>" = rpc:call(LNode,?MODULE,pretty,[<<"\x{400}foo"/utf8>>, 2]),
- test_server:stop_node(UNode),
- test_server:stop_node(LNode),
+ peer:stop(UPeer),
+ peer:stop(LPeer),
"<<\"äppl\"/utf8>>" = pretty(<<"äppl"/utf8>>, 2),
"<<\"äppl\"/utf8...>>" = pretty(<<"äpple"/utf8>>, 2),
@@ -2740,9 +2735,7 @@ trunc_string() ->
"str str" = trf("str ~s", ["str"], 7),
"str str" = trf("str ~8s", ["str"], 6),
"str ..." = trf("str ~8s", ["str1"], 6),
- Pa = filename:dirname(code:which(?MODULE)),
- {ok, UNode} = test_server:start_node(printable_range_unicode, slave,
- [{args, " +pc unicode -pa " ++ Pa}]),
+ {ok, UPeer, UNode} = ?CT_PEER(["+pc", "unicode"]),
U = "кириллиÌчеÑкий атом",
UFun = fun(Format, Args, CharsLimit) ->
rpc:call(UNode,
@@ -2760,7 +2753,7 @@ trunc_string() ->
"<<\"кириллиÌ\"/utf8...>>" = UFun("~tp", [BU], 20),
"<<\"кириллиÌ\"/utf8...>>" = UFun("~tp", [BU], 21),
"<<\"кириллиÌчеÑк\"/utf8...>>" = UFun("~tp", [BU], 22),
- test_server:stop_node(UNode).
+ peer:stop(UPeer).
trunc_depth(D, Fun) ->
"..." = Fun("", D, 0),
@@ -3011,6 +3004,11 @@ error_info(Config) ->
Dev
end,
+ UnicodeDev = fun() ->
+ {ok, Dev} = file:open(TmpFile, [read, write, {encoding, unicode}]),
+ Dev
+ end,
+
DeadDev = spawn(fun() -> ok end),
UserDev = fun() -> whereis(user) end,
@@ -3032,8 +3030,12 @@ error_info(Config) ->
{put_chars,["test"], [{gl,FullDev()},{general,"no space left on device"}]},
{put_chars,[Latin1Dev(),"Спутник-1"], [{1,"transcode"}]},
{put_chars,[a], [{1,"not valid character data"}]},
+ {put_chars,[UnicodeDev(), <<222>>], [{1,"transcode"}]},
+ {put_chars,[<<1:1>>], [{1,"not valid character data"}]},
{put_chars,[UnknownDev(),"test"], [{general,"unknown error: 'Спутник-1'"}]},
{put_chars,["test"], [{gl,UnknownDev()},{general,"unknown error: 'Спутник-1'"}]},
+ {put_chars,[self(),"test"],[{1,"the device is not allowed to be the current process"}]},
+ {put_chars,["test"],[{gl,self()},{general,"the device is not allowed to be the current process"}]},
{write,[DeadDev,"test"],[{1,"terminated"}]},
{write,["test"],[{gl,DeadDev},{general,"terminated"}]},
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index df6958cfa9..525b479fef 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-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -460,7 +460,8 @@ unicode_options(Config) when is_list(Config) ->
%% Tests various unicode options on random generated files.
unicode_options_gen(Config) when is_list(Config) ->
ct:timetrap({minutes,30}), %% valgrind needs a alot of time
- random:seed(1240, 900586, 553728),
+ rand:seed(default),
+ io:format("*** SEED: ~p ***\n", [rand:export_seed()]),
PrivDir = proplists:get_value(priv_dir, Config),
AllModes = [utf8,utf16,{utf16,big},{utf16,little},
utf32,{utf32,big},{utf32,little}],
@@ -513,12 +514,11 @@ unicode_options_gen(Config) when is_list(Config) ->
[read,read_ahead,{encoding,Encoding}],
Read4),
- Ulist2 = [X || X <- Ulist, X =/= $\n, X =/= $\s],
- Ulist3 = [X || X <- Ulist, X =/= $\n],
+ Ulist2 = [X || X <- Ulist, X =/= $\n, X =/= $\s, X =/= $\t],
Ulist = done(Res1),
Ulist = done(Res2),
Ulist2 = done(Res3),
- Ulist3 = done(Res4),
+ Ulist2 = done(Res4),
file:delete(Fname)
end,
@@ -635,22 +635,31 @@ enc2str({A1,A2}) when is_atom(A1), is_atom(A2) ->
random_unicode(0) ->
- [];
+ %% io:fread(Device, Promp, "~ts") will return an error if the file
+ %% ends with whitespace characters. This behavior seems to be
+ %% deliberate. Therefore, be sure that we never end the file with
+ %% a sequence of whitespace characters.
+ [$! + rand:uniform(64) |
+ case rand:uniform(20) of
+ A when A =< 1 -> [$\n];
+ _ -> []
+ end];
random_unicode(N) ->
- %% Favour large unicode and make linebreaks
- X = case random:uniform(20) of
+ %% Favor large unicode code points and make line breaks.
+ X = case rand:uniform(20) of
A when A =< 1 -> $\n;
- A0 when A0 =< 3 -> random:uniform(16#10FFFF);
- A1 when A1 =< 6 -> random:uniform(16#10FFFF - 16#7F) + 16#7F;
- A2 when A2 =< 12 -> random:uniform(16#10FFFF - 16#7FF) + 16#7FF;
- _ -> random:uniform(16#10FFFF - 16#FFFF) + 16#FFFF
+ A when A =< 3 -> rand:uniform(16#10FFFF);
+ A when A =< 6 -> rand:uniform(16#10FFFF - 16#7F) + 16#7F;
+ A when A =< 12 -> rand:uniform(16#10FFFF - 16#7FF) + 16#7FF;
+ _ -> rand:uniform(16#10FFFF - 16#FFFF) + 16#FFFF
end,
- case X of
- Inv1 when Inv1 >= 16#D800, Inv1 =< 16#DFFF;
- Inv1 =:= 16#FFFE;
- Inv1 =:= 16#FFFF ->
+ if
+ X =:= $\r; %Can be eaten by io:get_line/2.
+ 16#D800 =< X, X =< 16#DFFF;
+ X =:= 16#FFFE;
+ X =:= 16#FFFF ->
random_unicode(N);
- _ ->
+ true ->
[X | random_unicode(N-1)]
end.
@@ -1179,7 +1188,7 @@ get_and_put(CPid, [{getline_pred,Pred,Msg}|T]=T0, N)
"(command number ~p)\n",
[?MODULE,Msg,N]),
{error, no_match};
- maybe ->
+ 'maybe' ->
List = get(getline_skipped),
put(getline_skipped, List ++ [Data]),
get_and_put(CPid, T0, N)
@@ -1190,7 +1199,7 @@ get_and_put(CPid, [{getline, Match}|T],N) ->
F = fun(Data) ->
case lists:prefix(Match, Data) of
true -> yes;
- false -> maybe
+ false -> 'maybe'
end
end,
get_and_put(CPid, [{getline_pred,F,Match}|T], N);
@@ -1198,7 +1207,7 @@ get_and_put(CPid, [{getline_re, Match}|T],N) ->
F = fun(Data) ->
case re:run(Data, Match, [{capture,none}]) of
match -> yes;
- _ -> maybe
+ _ -> 'maybe'
end
end,
get_and_put(CPid, [{getline_pred,F,Match}|T], N);
@@ -1498,7 +1507,7 @@ get_default_shell() ->
case re:run(Data, "<\\d+[.]\\d+[.]\\d+>",
[{capture,none}]) of
match -> no;
- _ -> maybe
+ _ -> 'maybe'
end
end
end,
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index bbd0d81b1c..b369b6918e 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
%% Test cases must be exported.
-export([member/1, reverse/1,
keymember/1, keysearch_keyfind/1,
- keystore/1, keytake/1, keyreplace/1,
+ keystore/1, keytake/1, keyreplace/1,
append_1/1, append_2/1,
seq_loop/1, seq_2/1, seq_3/1, seq_2_e/1, seq_3_e/1,
@@ -53,12 +53,13 @@
ufunmerge/1, rufunmerge/1,
ufunsort_1/1, ufunsort_stable/1, ufunsort_rand/1,
ufunsort_error/1,
+ uniq_1/1, uniq_2/1,
zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1,
filter_partition/1,
join/1,
otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1,
suffix/1, subtract/1, droplast/1, search/1, hof/1,
- error_info/1]).
+ enumerate/1, error_info/1]).
%% Sort randomized lists until stopped.
%%
@@ -81,10 +82,11 @@ suite() ->
all() ->
[{group, append},
{group, key},
- {group,sort},
+ {group, sort},
{group, usort},
{group, keysort},
{group, ukeysort},
+ {group, uniq},
{group, funsort},
{group, ufunsort},
{group, sublist},
@@ -120,9 +122,10 @@ groups() ->
[flatten_1, flatten_2, flatten_1_e, flatten_2_e]},
{tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]},
{zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]},
+ {uniq, [parallel], [uniq_1, uniq_2]},
{misc, [parallel], [reverse, member, dropwhile, takewhile,
filter_partition, suffix, subtract, join,
- hof, droplast, search, error_info]}
+ hof, droplast, search, enumerate, error_info]}
].
init_per_suite(Config) ->
@@ -2743,6 +2746,22 @@ hof(Config) when is_list(Config) ->
ok.
+%% Test lists:enumerate/1 and lists:enumerate/2
+enumerate(Config) when is_list(Config) ->
+ [] = lists:enumerate([]),
+ [] = lists:enumerate(10, []),
+ [{1,a},{2,b},{3,c}] = lists:enumerate([a,b,c]),
+ [{10,a},{11,b},{12,c}] = lists:enumerate(10, [a,b,c]),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(0),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(0, 10),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(1.0, []),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(1.0, [a,b,c]),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(<<1>>, []),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(<<1>>, [a,b,c]),
+ {'EXIT', {function_clause, _}} = catch lists:enumerate(1, <<1,2,3>>),
+
+ ok.
+
error_info(_Config) ->
L = [{keyfind, [whatever, bad_position, bad_list], [{2,".*"},{3,".*"}]},
{keymember, [key, 0, bad_list], [{2,".*"}, {3,".*"}]},
@@ -2767,3 +2786,22 @@ do_error_info(L0) ->
NYI = [{F,lists:duplicate(A, '*'),nyi} || {F,A} <- Bifs -- Tests],
L = lists:sort(NYI ++ L1),
error_info_lib:test_error_info(lists, L, [snifs_only]).
+
+uniq_1(_Config) ->
+ [] = lists:uniq([]),
+ [foo] = lists:uniq([foo]),
+ ["foo", "bar", "zoo"] = lists:uniq(["foo", "foo", "bar", "foo", "zoo",
+ "foo", "bar", "zoo"]),
+ [a, 1, b, 2] = lists:uniq([a, a, a, 1, b, 2, a, 2, 1]),
+ [<<"home">>, "home"] = lists:uniq([<<"home">>, "home"]),
+ [3.14159, 2.71828, 3.17] = lists:uniq([3.14159, 3.14159, 2.71828, 3.17]),
+ [42, 42.0] = lists:uniq([42, 42.0, 42, 42.0]),
+ ok.
+
+uniq_2(_Config) ->
+ [] = lists:uniq(fun(X) -> X end, []),
+ [{42, 1}, {42.0, 99}, {a, 99}] =
+ lists:uniq(fun(X) -> element(1, X) end,
+ [{42, 1}, {42.0, 99}, {a, 99}, {a, 1}, {42, 100}]),
+ [1] = lists:uniq(fun(_) -> whatever end, lists:seq(1, 10)),
+ ok.
diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl
index 28895c4efe..8d479f8211 100644
--- a/lib/stdlib/test/maps_SUITE.erl
+++ b/lib/stdlib/test/maps_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,8 @@
t_from_list_check_trapping/1,
t_from_keys_check_trapping/1,
t_keys_trapping/1,
- t_values_trapping/1]).
+ t_values_trapping/1,
+ t_groups_from_list/1]).
-define(badmap(V,F,Args), {'EXIT', {{badmap,V}, [{maps,F,Args,_}|_]}}).
-define(badkey(K,F,Args), {'EXIT', {{badkey,K}, [{maps,F,Args,_}|_]}}).
@@ -68,7 +69,8 @@ all() ->
t_from_list_check_trapping,
t_from_keys_check_trapping,
t_keys_trapping,
- t_values_trapping].
+ t_values_trapping,
+ t_groups_from_list].
t_from_list_kill_process(Config) when is_list(Config) ->
Killer = self(),
@@ -770,6 +772,16 @@ t_size_1(Config) when is_list(Config) ->
{'EXIT', {{badmap,<<>>}, _}} = (catch maps:size(id(<<>>))),
ok.
+t_groups_from_list(_Config) ->
+ #{} = maps:groups_from_list(fun erlang:length/1, []),
+ #{3 := ["tna","tac"], 5 := ["ognid"], 7 := ["olaffub"]} =
+ maps:groups_from_list(
+ fun erlang:length/1,
+ fun lists:reverse/1,
+ ["ant", "buffalo", "cat", "dingo"]
+ ),
+ #{0 := [2], 1 := [1, 3]} = maps:groups_from_list(fun(X) -> X rem 2 end, [1, 2, 3]).
+
error_info(_Config) ->
BadIterator = [-1|#{}],
GoodIterator = maps:iterator(#{}),
@@ -806,6 +818,13 @@ error_info(_Config) ->
{get, [key, {no,map}]},
{get, [key, {no,map}, default]},
+ {groups_from_list, [not_a_fun, []]},
+ {groups_from_list, [fun hd/1, not_a_list]},
+
+ {groups_from_list, [not_a_fun, fun(_) -> ok end, []]},
+ {groups_from_list, [fun(_) -> ok end, not_a_fun, []]},
+ {groups_from_list, [fun(_) -> ok end, fun(_) -> ok end, not_a_list]},
+
{intersect, [#{a => b}, y]},
{intersect, [x, #{a => b}]},
{intersect, [x, y],[{1,".*"},{2,".*"}]},
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index a28de19372..c34c7e9e69 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -30,12 +30,19 @@
-export([from_shell/1]).
-export([records/1]).
-export([record_index/1]).
--export([multipass/1]).
+-export([map_pattern/1]).
+-export([map_expr_in_head/1]).
+-export([map_pattern_from_shell/1]).
+-export([map_expr_in_head_from_shell/1]).
+-export([map_exprs/1]).
+-export([map_exprs_from_shell/1]).
-export([top_match/1]).
+-export([multipass/1]).
-export([old_guards/1]).
-export([autoimported/1]).
-export([semicolon/1]).
-export([bitsyntax/1]).
+-export([binary_bifs/1]).
-export([record_defaults/1]).
-export([andalso_orelse/1]).
-export([float_1_function/1]).
@@ -59,10 +66,13 @@ suite() ->
all() ->
[from_shell, basic_ets, basic_dbg, records,
- record_index, multipass, bitsyntax, record_defaults,
+ record_index, multipass, bitsyntax, binary_bifs, record_defaults,
andalso_orelse, float_1_function, action_function,
warnings, no_warnings, top_match, old_guards, autoimported,
- semicolon, eep37, otp_14454, otp_16824, unused_record].
+ semicolon, eep37, otp_14454, otp_16824, unused_record,
+ map_pattern, map_expr_in_head,
+ map_pattern_from_shell, map_expr_in_head_from_shell,
+ map_exprs, map_exprs_from_shell].
groups() ->
[].
@@ -257,6 +267,32 @@ bitsyntax(Config) when is_list(Config) ->
" end)">>),
ok.
+
+%% Test that binary BIFs byte_size/1, binary_part/2, binary_part/3 are accepted
+binary_bifs(Config) when is_list(Config) ->
+ setup(Config),
+ TestSet = [{<<"hello">>, <<"world">>}, {<<"souldn't">>, <<"match">>}],
+ RunMS = fun(MS) -> ets:match_spec_run(TestSet, ets:match_spec_compile(MS)) end,
+ % check byte_size/1
+ MS1 = compile_and_run(<<"ets:fun2ms(fun({A, B}) when byte_size(A) == 5 -> {A, byte_size(B)} end)">>),
+ [{{'$1','$2'},
+ [{'==',{byte_size,'$1'},5}],
+ [{{'$1',{byte_size,'$2'}}}]}] = MS1,
+ [{<<"hello">>, 5}] = RunMS(MS1),
+ % check binary_part/2
+ MS2 = compile_and_run(<<"ets:fun2ms(fun({A, B}) when binary_part(A, {1, 2}) == <<\"el\">> -> binary_part(B, {2, 3}) end)">>),
+ [{{'$1','$2'},
+ [{'==',{binary_part,'$1',{{1,2}}},<<"el">>}],
+ [{binary_part,'$2',{{2,3}}}]}] = MS2,
+ [<<"rld">>] = RunMS(MS2),
+ % check binary_part/3
+ MS3 = compile_and_run(<<"ets:fun2ms(fun({A, B}) when binary_part(A, 1, 2) == <<\"el\">> -> binary_part(B, 2, 3) end)">>),
+ [{{'$1','$2'},
+ [{'==',{binary_part,'$1',1,2},<<"el">>}],
+ [{binary_part,'$2',2,3}]}] = MS3,
+ [<<"rld">>] = RunMS(MS3),
+ ok.
+
%% Test that record defaults works.
record_defaults(Config) when is_list(Config) ->
setup(Config),
@@ -289,7 +325,7 @@ basic_ets(Config) when is_list(Config) ->
compile_and_run(<<"ets:fun2ms(fun({\"foo\" ++ _, X}) -> X end)">>),
ok.
-%% Tests basic ets:fun2ms.
+%% Tests basic dbg:fun2ms.
basic_dbg(Config) when is_list(Config) ->
setup(Config),
[{[a,b],[],[{message,banan},{return_trace}]}] =
@@ -382,6 +418,59 @@ record_index(Config) when is_list(Config) ->
<<"ets:fun2ms(fun({#a.a,A}) when A > #a.a -> #a.a end)">>),
ok.
+map_pattern(Config) when is_list(Config) ->
+ setup(Config),
+ MS = [{{key, #{foo => '$1'}},[],['$1']}],
+ MS = compile_and_run(<<"ets:fun2ms(fun({key, #{foo := V}}) -> V end)">>),
+ ok.
+
+map_expr_in_head(Config) when is_list(Config) ->
+ setup(Config),
+ MS = [{{key, #{foo => '$1'}},[],['$1']}],
+ %% Accidentally it is possible to use => instead of := in the fun head,
+ %% in compiled code.
+ %% Although this is not an intended behaviour it is kept to
+ %% maintain backwards compatibility.
+ MS = compile_and_run(<<"ets:fun2ms(fun({key, #{foo => V}}) -> V end)">>),
+ ok.
+
+map_pattern_from_shell(Config) when is_list(Config) ->
+ MS = [{{key, #{foo => '$1'}},[],['$1']}],
+ MS = do_eval("ets:fun2ms(fun({key, #{foo := V}}) -> V end)"),
+ ok.
+
+map_expr_in_head_from_shell(Config) when is_list(Config) ->
+ setup(Config),
+ MS = [{{key, #{foo => '$1'}},[],['$1']}],
+ %% Accidentally it is possible to use => instead of := in the fun head,
+ %% in compiled code. This behaviour is kept for backwards compatibility.
+
+ %% As a side-effect, it is also possible to do the same with
+ %% `transform_from_shell/3', if the AST of the shell fun is
+ %% created bypassing the linter. (The linter would prevent
+ %% constructing such invalid syntax, so normally this is not
+ %% possible in the Erlang shell)
+ MS = do_eval("ets:fun2ms(fun({key, #{foo => V}}) -> V end)"),
+ ok.
+
+map_exprs(Config) when is_list(Config) ->
+ setup(Config),
+ MSGuard = [{{key,'$1','$2'}, [{'=:=','$1',#{foo => '$2'}}], ['$1']}],
+ MSGuard = compile_and_run(
+ <<"ets:fun2ms(fun({key, V1, V2}) when V1 =:= #{foo => V2} -> V1 end)">>),
+ MSBody = [{{key,'$1'}, [], [#{foo => '$1'}]}],
+ MSBody = compile_and_run(
+ <<"ets:fun2ms(fun({key, V}) -> #{foo => V} end)">>),
+ ok.
+
+map_exprs_from_shell(Config) when is_list(Config) ->
+ setup(Config),
+ MSGuard = [{{key,'$1','$2'}, [{'=:=','$1',#{foo => '$2'}}], ['$1']}],
+ MSGuard = do_eval("ets:fun2ms(fun({key, V1, V2}) when V1 =:= #{foo => V2} -> V1 end)"),
+ MSBody = [{{key,'$1'}, [], [#{foo => '$1'}]}],
+ MSBody = do_eval("ets:fun2ms(fun({key, V}) -> #{foo => V} end)"),
+ ok.
+
%% Tests matching on top level in head to give alias for object().
top_match(Config) when is_list(Config) ->
setup(Config),
@@ -897,5 +986,5 @@ do_eval(String) ->
[],
String++".\n",1),
{ok,Tree} = erl_parse:parse_exprs(T),
- {value,Res,[]} = erl_eval:exprs(Tree,[]),
+ {value,Res,[]} = erl_eval:exprs(Tree,[],none,none),
Res.
diff --git a/lib/stdlib/test/peer_SUITE.erl b/lib/stdlib/test/peer_SUITE.erl
new file mode 100644
index 0000000000..02bd16bd76
--- /dev/null
+++ b/lib/stdlib/test/peer_SUITE.erl
@@ -0,0 +1,655 @@
+%%% @doc
+%%% Smoke tests for peer node controller
+%%% @end
+-module(peer_SUITE).
+-author("maximfca@gmail.com").
+
+%% Common Test headers
+-include_lib("stdlib/include/assert.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+%% Test server callbacks
+-export([
+ suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2
+]).
+
+%% Test cases
+-export([
+ dist/0, dist/1,
+ peer_down_crash/0, peer_down_crash/1,
+ peer_down_crash_tcp/1,
+ peer_down_continue/0, peer_down_continue/1,
+ peer_down_boot/0, peer_down_boot/1,
+ dist_io_redirect/0, dist_io_redirect/1,
+ dist_localhost/0, dist_localhost/1,
+ errors/0, errors/1,
+ basic/0, basic/1,
+ peer_states/0, peer_states/1,
+ cast/0, cast/1,
+ detached/0, detached/1,
+ dyn_peer/0, dyn_peer/1,
+ stop_peer/0, stop_peer/1,
+ shutdown_halt/0, shutdown_halt/1,
+ shutdown_halt_timeout/0, shutdown_halt_timeout/1,
+ shutdown_stop/0, shutdown_stop/1,
+ shutdown_stop_timeout/0, shutdown_stop_timeout/1,
+ shutdown_close/0, shutdown_close/1,
+ init_debug/0, init_debug/1,
+ io_redirect/0, io_redirect/1,
+ multi_node/0, multi_node/1,
+ dist_up_down/0, dist_up_down/1,
+ duplicate_name/0, duplicate_name/1,
+ old_release/0, old_release/1,
+ ssh/0, ssh/1,
+ docker/0, docker/1,
+ cntrl_channel_handler_crash/0, cntrl_channel_handler_crash/1,
+ cntrl_channel_handler_crash_old_release/0, cntrl_channel_handler_crash_old_release/1
+]).
+
+suite() ->
+ [{timetrap, {minutes, 1}}].
+
+shutdown_alternatives() ->
+ [shutdown_halt, shutdown_halt_timeout, shutdown_stop, shutdown_stop_timeout, shutdown_close].
+
+alternative() ->
+ [basic, peer_states, cast, detached, dyn_peer, stop_peer,
+ io_redirect, multi_node, duplicate_name, cntrl_channel_handler_crash,
+ cntrl_channel_handler_crash_old_release | shutdown_alternatives()].
+
+groups() ->
+ [
+ {dist, [parallel], [errors, dist, peer_down_crash, peer_down_continue, peer_down_boot,
+ dist_up_down, dist_localhost, cntrl_channel_handler_crash,
+ cntrl_channel_handler_crash_old_release | shutdown_alternatives()]},
+ {dist_seq, [], [dist_io_redirect, %% Cannot be run in parallel in dist group
+ peer_down_crash_tcp]},
+ {tcp, [parallel], alternative()},
+ {standard_io, [parallel], [init_debug | alternative()]},
+ {compatibility, [parallel], [old_release]},
+ {remote, [parallel], [ssh]}
+ ].
+
+all() ->
+ [{group, dist}, {group, dist_seq}, {group, tcp}, {group, standard_io},
+ {group, compatibility}, {group, remote}].
+
+init_per_group(remote, Config) ->
+ %% check that SSH can connect to localhost, skip the test if not
+ try os:cmd("ssh localhost echo ok") of
+ "ok\n" -> Config;
+ _ -> {skip, "'ssh localhost echo ok' did not return ok"}
+ catch
+ Class:Reason ->
+ SkipReason = io_lib:format("'ssh localhost echo ok' failed with ~s:~p", [Class, Reason]),
+ {skip, SkipReason}
+ end;
+init_per_group(dist, Config) ->
+ case erlang:is_alive() of
+ true -> Config;
+ false -> {skip, "origin is not distributed"}
+ end;
+init_per_group(tcp, Config) ->
+ [{connection, 0} | Config];
+init_per_group(standard_io, Config) ->
+ [{connection, standard_io} | Config];
+init_per_group(_Group, Config) ->
+ Config.
+
+end_per_group(_TestCase, Config) ->
+ proplists:delete(connection, Config).
+
+%% -------------------------------------------------------------------
+%% Distribution-enabled cases
+
+errors() ->
+ [{doc, "Verify that invalid command line is rejected immediately"}].
+
+errors(Config) when is_list(Config) ->
+ ?assertException(error, {invalid_arg, atom}, peer:start(#{args => atom})),
+ ?assertException(error, {invalid_arg, $s}, peer:start(#{args => "string"})),
+ ?assertException(error, {invalid_arg, ["2"]}, peer:start(#{args => ["1", ["2"]]})),
+ ?assertException(error, {exec, atom}, peer:start(#{exec => atom, name => name})),
+ ?assertException(error, {exec, atom}, peer:start(#{exec => {atom, []}, name => name})),
+ ?assertException(error, {exec, atom}, peer:start(#{exec => {"erl", [atom]}, name => name})),
+ ?assertException(error, not_alive, peer:start(#{})). %% peer node won't start - it's not alive
+
+dist() ->
+ [{doc, "Classic behaviour: detached peer with no alternative, connects via dist"}].
+
+%% Classic 'slave': start new node locally, with random name, ask peer control process to exit normally
+dist(Config) when is_list(Config) ->
+ {ok, Peer, Node} = peer:start_link(),
+ %% distribution is expected to be connected
+ ?assertEqual(Node, erpc:call(Node, erlang, node, [])),
+ %% but not alternative...
+ ?assertException(error, noconnection, peer:call(Peer, erlang, node, [])),
+ ?assertEqual(true, net_kernel:disconnect(Node)),
+ %% ^^^ this makes the node go down, but we also need to ensure that net_kernel
+ %% finished processing
+ ct:sleep(500),
+ _ = sys:get_state(net_kernel),
+ ?assertException(exit, {noproc, _}, peer:get_state(Peer)).
+
+peer_down_crash() ->
+ [{doc, "Tests peer_down handling when crash mode is requested"}].
+
+peer_down_crash(Config) when is_list(Config) ->
+ %% two-way link: "crash" mode
+ {ok, Peer, Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ args => ["-connect_all", "false"], peer_down => crash}),
+ %% verify node started locally
+ ?assertEqual(Node, erpc:call(Node, erlang, node, [])),
+ %% verify there is no alternative connection
+ ?assertException(error, noconnection, peer:call(Peer, erlang, node, [])),
+ %% unlink and monitor
+ unlink(Peer),
+ MRef = monitor(process, Peer),
+ ?assertEqual(true, net_kernel:disconnect(Node)),
+ %% ^^^ this makes the node go down
+ %% since two-way link is requested, it triggers peer to stop
+ receive
+ {'DOWN', MRef, process, Peer, {nodedown, Node}} ->
+ ok
+ after 2000 ->
+ link(Peer),
+ {fail, disconnect_timeout}
+ end.
+
+%% Verify option combo #{peer_down=>crash, connection=>0}
+%% exits control process abnormally.
+peer_down_crash_tcp(Config) when is_list(Config) ->
+ %% two-way link: "crash" mode
+ {ok, Peer, Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ peer_down => crash,
+ connection => 0}),
+ %% verify node started locally
+ ?assertEqual(Node, peer:call(Peer, erlang, node, [])),
+ %% verify there is no distribution connection
+ ?assertEqual([], erlang:nodes(connected)),
+ %% unlink and monitor
+ unlink(Peer),
+ MRef = monitor(process, Peer),
+ %% Make the node go down
+ ok = erpc:cast(Node, erlang, halt, [0]),
+
+ %% since two-way link is requested, it triggers peer to stop
+ receive
+ {'DOWN', MRef, process, Peer, tcp_closed} ->
+ ok
+ after 5000 ->
+ link(Peer),
+ {fail, disconnect_timeout}
+ end.
+
+peer_down_continue() ->
+ [{doc, "Tests peer_down handling for continue setting"}].
+
+peer_down_continue(Config) when is_list(Config) ->
+ {ok, Peer, Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ args => ["-connect_all", "false"], peer_down => continue}),
+ ?assertEqual(ok, erpc:cast(Node, erlang, halt, [])),
+ ct:sleep(500),
+ sys:replace_state(net_kernel, fun(S) -> sys:get_state(Peer), S end),
+ ?assertMatch({down, _}, peer:get_state(Peer)),
+ peer:stop(Peer).
+
+peer_down_boot() ->
+ [{doc, "Tests that peer node failing boot fails start_link correctly"}].
+
+peer_down_boot(Config) when is_list(Config) ->
+ ?assertException(exit, {boot_failed, {exit_status, 1}},
+ peer:start_link(#{connection => standard_io, name => peer:random_name(), args => ["-no_epmd"]})).
+
+dist_io_redirect() ->
+ [{doc, "Tests i/o redirection working for dist"}].
+
+dist_io_redirect(Config) when is_list(Config) ->
+ %% Common Test changes group leader process to capture output.
+ %% 'peer' relays output via control process group leader.
+ ct:capture_start(),
+ {ok, Peer, Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ args => ["-connect_all", "false", "-eval", "io:format(\"out\")."]}),
+ %% RPC is smart enough to set the group leader, so force 'user' output
+ %% to check that peer node redirects 'user' to the current process group
+ %% leader.
+ ?assertEqual(ok, erpc:call(Node, io, format, [user, "STRONGFLOUR.", []])),
+ %% verify that 'send' is ignored when no alternative connection is done
+ ?assertEqual(ok, peer:send(Peer, init, {stop, stop})),
+ %% check that RPC sets the group leader, even via 'apply'
+ ?assertEqual(ok, erpc:call(Node, erlang, apply, [io, format, ["second."]])),
+ %% 'eval' at the end may be quite slow, so have to wait here
+ ct:sleep(500),
+ peer:stop(Peer),
+ ct:capture_stop(),
+ Texts = ct:capture_get(),
+ %% order is not guaranteed, so sort explicitly
+ ?assertEqual(lists:sort(["STRONGFLOUR.", "second.", "out"]), lists:sort(Texts)).
+
+dist_up_down() ->
+ [{doc, "Test that Erlang distribution can go up and down (with TCP alternative)"}].
+
+dist_up_down(Config) when is_list(Config) ->
+ %% skip establishing full mesh, for it makes 'global' hang
+ %% TODO: fix 'global.erl' locker process so it does not hang
+ {ok, Peer, Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ connection => {{127, 0, 0, 1}, 0}, args => ["-connect_all", "false"]}),
+ ?assertEqual(true, net_kernel:connect_node(Node)),
+ ?assertEqual(true, net_kernel:disconnect(Node)),
+ ?assertEqual(true, net_kernel:connect_node(Node)),
+ peer:stop(Peer).
+
+dist_localhost() ->
+ [{doc, "Test that localhost and gethostname operate together"}].
+
+dist_localhost(Config) when is_list(Config) ->
+ {ok, Peer, Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME), host => "localhost"}),
+ ?assertMatch([_, "localhost"], string:lexemes(atom_to_list(Node), "@")),
+ %% start second peer, ensure they see each other
+ {ok, Host} = inet:gethostname(),
+ {ok, Peer2, Node2} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME), host => Host}),
+ true = erpc:call(Node, net_kernel, connect_node, [Node2]),
+ peer:stop(Peer),
+ peer:stop(Peer2).
+
+%% -------------------------------------------------------------------
+%% alternative connection cases
+
+%% Runs in the peer node context, forward a message from peer node to origin
+%% node via alternative connection.
+-spec forward(Dest :: pid() | atom(), Message :: term()) -> term().
+forward(Dest, Message) ->
+ group_leader() ! {message, Dest, Message}.
+
+basic() ->
+ [{doc, "Tests peer node start, and do some RPC via stdin/stdout"}].
+
+basic(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, _Node} = peer:start_link(#{connection => Conn}),
+ %% test the alternative connection
+ ?assertEqual('nonode@nohost', peer:call(Peer, erlang, node, [])),
+ ?assertException(throw, ball, peer:call(Peer, erlang, throw, [ball])),
+ %% setup code path to this module (needed to "fancy RPC")
+ Path = filename:dirname(code:which(?MODULE)),
+ ?assertEqual(true, peer:call(Peer, code, add_path, [Path])),
+ %% fancy RPC via message exchange (uses forwarding from the peer)
+ Control = self(),
+ RFun = fun() -> receive do -> forward(Control, done) end end,
+ RemotePid = peer:call(Peer, erlang, spawn, [RFun]),
+ peer:send(Peer, RemotePid, do),
+ %% wait back from that process
+ receive done -> ok end,
+ %% shutdown the node
+ ?assertEqual(ok, peer:stop(Peer)),
+ ?assertNot(is_process_alive(Peer)).
+
+peer_states() ->
+ [{doc, "Tests peer node states"}].
+
+peer_states(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer} = peer:start_link(#{connection => Conn, wait_boot => {self(), ?FUNCTION_NAME},
+ peer_down => continue}),
+ ?assertEqual(booting, peer:get_state(Peer)),
+ %% running
+ receive {?FUNCTION_NAME, {started, _Node, Peer}} -> ok end,
+ ?assertEqual(running, peer:get_state(Peer)),
+ peer:cast(Peer, erlang, halt, []),
+ ct:sleep(1000), %% source of flakiness, should switch to some better notification mechanism
+ %% down
+ ?assertMatch({down, _}, peer:get_state(Peer)),
+ peer:stop(Peer).
+
+cast() ->
+ [{doc, "Tests casts via alternative connections"}].
+
+cast(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, _Node} = peer:start_link(#{connection => Conn}),
+ %% cast RPC
+ ?assertEqual(undefined, peer:call(Peer, application, get_env, [kernel, foo])),
+ peer:cast(Peer, application, set_env, [kernel, foo, bar]),
+ %% this is only to ensure application_controller completed processing
+ peer:call(Peer, sys, get_state, [application_controller]),
+ ?assertEqual({ok, bar}, peer:call(Peer, application, get_env, [kernel, foo])),
+ peer:stop(Peer).
+
+detached() ->
+ [{doc, "Tests detached node (RPC via alternative connection)"}].
+
+detached(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, _Node} = peer:start_link(#{connection => Conn}),
+ ?assertEqual('nonode@nohost', peer:call(Peer, erlang, node, [])),
+ %% check exceptions
+ ?assertException(throw, ball, peer:call(Peer, erlang, throw, [ball])),
+ %% check tcp forwarding
+ Path = filename:dirname(code:which(?MODULE)),
+ ?assertEqual(true, peer:call(Peer, code, add_path, [Path])),
+ %% fancy RPC via message exchange (uses forwarding from the peer)
+ Control = self(),
+ RFun = fun() -> receive do -> forward(Control, done) end end,
+ RemotePid = peer:call(Peer, erlang, spawn, [RFun]),
+ %% test that sending message over alternative TCP connection works
+ peer:send(Peer, RemotePid, do),
+ %% wait back from that process
+ receive done -> ok end,
+ %% logging via TCP
+ ct:capture_start(),
+ peer:call(Peer, io, format, ["one."]),
+ peer:call(Peer, erlang, apply, [io, format, ["two."]]),
+ peer:stop(Peer),
+ ct:capture_stop(),
+ Texts = ct:capture_get(),
+ %% just stop
+ ?assertEqual(["one.", "two."], Texts).
+
+dyn_peer() ->
+ [{doc, "Origin is not distributed, and peer becomes distributed dynamically"}].
+
+dyn_peer(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, 'nonode@nohost'} = peer:start_link(#{connection => Conn}), %% start not distributed
+ Node = list_to_atom(lists:concat([peer:random_name(?FUNCTION_NAME), "@forced.host"])),
+ {ok, _} = peer:call(Peer, net_kernel, start, [[Node, longnames]]),
+ ?assertEqual(Node, peer:call(Peer, erlang, node, [])),
+ peer:stop(Peer).
+
+stop_peer() ->
+ [{doc, "Test that peer shuts down even when node sleeps, but control connection closed"}].
+
+stop_peer(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, _Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ connection => Conn, args => ["-eval", "timer:sleep(60000)."]}),
+ %% shutdown node
+ peer:stop(Peer).
+
+shutdown_halt() ->
+ [{doc, "Test that peer shutdown halt wait until node connection is down"}].
+shutdown_halt(Config) when is_list(Config) ->
+ false = shutdown_test(Config, ?FUNCTION_NAME, halt, 500, false, 1000),
+ ok.
+
+shutdown_halt_timeout() ->
+ [{doc, "Test that peer shutdown halt forcefully takes down connection on timeout"}].
+shutdown_halt_timeout(Config) when is_list(Config) ->
+ false = shutdown_test(Config, ?FUNCTION_NAME, {halt, 1000}, 5000, true, 1500),
+ ok.
+
+shutdown_stop() ->
+ [{doc, "Test that peer shutdown stop wait until node connection is down"}].
+shutdown_stop(Config) when is_list(Config) ->
+ false = shutdown_test(Config, ?FUNCTION_NAME, infinity, 500, false, 2000),
+ ok.
+
+shutdown_stop_timeout() ->
+ [{doc, "Test that peer shutdown stop forcefully takes down connection on timeout"}].
+shutdown_stop_timeout(Config) when is_list(Config) ->
+ false = shutdown_test(Config, ?FUNCTION_NAME, 1000, 5000, true, 2500),
+ ok.
+
+shutdown_close() ->
+ [{doc, "Test that peer shutdown close does not wait for dist connection"}].
+shutdown_close(Config) when is_list(Config) ->
+ _ = shutdown_test(Config, ?FUNCTION_NAME, close, 5000, true, 200),
+ ok.
+
+shutdown_test(Config, TC, Shutdown, BlockTime, StopWhileBlocked, MaxWaitTime) ->
+ Options0 = #{name => ?CT_PEER_NAME(TC),
+ shutdown => Shutdown,
+ args => ["-hidden", "-pa", filename:dirname(code:which(?MODULE)),
+ "-setcookie", atom_to_list(erlang:get_cookie())]},
+ Options = case proplists:get_value(connection, Config) of
+ undefined -> Options0;
+ Conn -> maps:put(connection, Conn, Options0)
+ end,
+ {ok, Peer, Node} = peer:start_link(Options),
+ EnsureBlockedWait = 500,
+ BlockStart = erlang:monotonic_time(millisecond),
+ erpc:cast(Node,
+ fun () ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ erts_debug:set_internal_state(block, BlockTime+EnsureBlockedWait)
+ end),
+ receive after EnsureBlockedWait -> ok end, %% Ensure blocked...
+ Start = erlang:monotonic_time(millisecond),
+ peer:stop(Peer),
+ End = erlang:monotonic_time(millisecond),
+ WaitTime = End - Start,
+ BlockTimeLeft = BlockTime + EnsureBlockedWait - (Start - BlockStart),
+ Connected = lists:member(Node, nodes(connected)),
+ ct:pal("Connected = ~p~nWaitTime = ~p~nBlockTimeLeft = ~p~n",
+ [Connected, WaitTime, BlockTimeLeft]),
+ true = WaitTime =< MaxWaitTime,
+ case StopWhileBlocked of
+ true -> ok;
+ false -> true = WaitTime >= BlockTimeLeft, ok
+ end,
+ Connected.
+
+init_debug() ->
+ [{doc, "Test that debug messages in init work"}].
+
+init_debug(Config) when is_list(Config) ->
+ ct:capture_start(),
+ {ok, Peer, _Node} = peer:start_link(#{name => peer:random_name(?FUNCTION_NAME), shutdown => 1000,
+ connection => standard_io, args => ["-init_debug"]}),
+ ct:sleep(200), %% without this sleep, peer is not fast enough to print
+ peer:stop(Peer),
+ ct:capture_stop(),
+ Texts = lists:append([string:trim(Str, trailing, "\r\n") || Str <- ct:capture_get()]),
+ %% every boot script starts with this
+ Expected = "{progress,preloaded}",
+ Actual = lists:sublist(Texts, 1, length(Expected)),
+ ?assertEqual(Expected, Actual).
+
+io_redirect() ->
+ [{doc, "Tests i/o redirection working for std"}].
+
+io_redirect(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, _Node} = peer:start_link(#{connection => Conn}),
+ ct:capture_start(),
+ peer:call(Peer, io, format, [user, "test.", []]),
+ peer:call(Peer, erlang, apply, [io, format, ["second."]]),
+ %% ensure no dist connection is set up
+ ?assertNot(lists:member(Peer, nodes()), {dist_connected, Peer, nodes()}),
+ ct:capture_stop(),
+ Texts = ct:capture_get(),
+ peer:stop(Peer),
+ ?assertEqual(["test.", "second."], Texts).
+
+multi_node() ->
+ [{doc, "Tests several nodes starting concurrently"}].
+
+multi_node(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ Peers = [
+ peer:start_link(#{name => peer:random_name(?FUNCTION_NAME),
+ wait_boot => {self(), tag}, connection => Conn})
+ || _ <- lists:seq(1, 4)],
+ Nodes = [receive {tag, {started, Node, Peer}} -> Node end || {ok, Peer} <- Peers],
+ ?assertEqual(4, length(Nodes)),
+ [?assertEqual(ok, peer:stop(Peer)) || {ok, Peer} <- Peers].
+
+duplicate_name() ->
+ [{doc, "Tests that a node with the same name fails to start"}].
+
+duplicate_name(Config) when is_list(Config) ->
+ Conn = proplists:get_value(connection, Config),
+ {ok, Peer, _Node} = peer:start_link(#{connection => Conn, name => ?FUNCTION_NAME, register => false}),
+ ?assertException(exit, _, peer:start_link(#{connection => standard_io, name => ?FUNCTION_NAME})),
+ peer:stop(Peer).
+
+%% -------------------------------------------------------------------
+%% Compatibility: old releases
+old_release() ->
+ [{doc, "Verity running with previous OTP release"}].
+
+old_release(Config) when is_list(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ %% don't expect OTP 10 to be available
+ ?assertEqual(not_available, ?CT_PEER_REL([], "10", PrivDir)),
+ PrevRel = integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 2),
+ case ?CT_PEER_REL([], PrevRel, PrivDir) of
+ not_available ->
+ {skip, "OTP " ++ PrevRel ++ " not found"};
+ {ok, Peer, Node} ->
+ ?assertEqual(PrevRel, rpc:call(Node, erlang, system_info, [otp_release])),
+ peer:stop(Peer)
+ end.
+
+%% -------------------------------------------------------------------
+%% SSH/Docker cases
+
+ssh() ->
+ [{doc, "Tests ssh (localhost) node support"}].
+
+ssh(Config) when is_list(Config) ->
+ %% figure out path to 'erl' locally ('erl' may not be in path via SSH)
+ case {os:find_executable("erl"), os:find_executable("ssh")} of
+ {false, _} ->
+ {skip, "erl not found"};
+ {ErlPath, SshPath} ->
+ Name = peer:random_name(?FUNCTION_NAME),
+ {OsName, _} = os:type(),
+ Options = #{exec => {SshPath, ["localhost", ErlPath]},
+ connection => standard_io, name => Name, host => "localhost"},
+ {ok, Peer, _Node} =
+ try peer:start_link(Options) of
+ Result -> Result
+ catch error:{boot_failed, normal} when OsName =:= win32 ->
+ %% If the boot fails on windows, ssh may have ended up
+ %% in wsl, so we try to boot using a wsl path
+ WslPath = string:trim(os:cmd("wsl wslpath -u " ++ ErlPath)),
+ peer:start_link(
+ Options#{ exec => {SshPath, ["localhost", WslPath]}})
+ end,
+
+ %% TODO: how to check it really goes over SSH?
+ %% ssh-ed node is not distributed
+ ?assertEqual(list_to_atom(Name ++ "@localhost"), peer:call(Peer, erlang, node, [])),
+ peer:stop(Peer)
+ end.
+
+docker() ->
+ [{doc, "Tests starting peer node in Docker container"}, {timetrap, {seconds, 60}}].
+
+build_release(Dir) ->
+ application:load(sasl), %% otherwise application:get_key will fail
+ %% build release (tarball)
+ RelFile = filename:join(Dir, "lambda.rel"),
+ Release = {release, {"lambda", "1.0.0"}, {erts, erlang:system_info(version)},
+ [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end} || App <- [kernel, stdlib, sasl]]},
+ ok = file:write_file(RelFile, list_to_binary(lists:flatten(io_lib:format("~tp.", [Release])))),
+ RelFileNoExt = filename:join(Dir, "lambda"),
+ {ok, systools_make, []} = systools:make_script(RelFileNoExt, [silent, {outdir, Dir}]),
+ ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).
+
+build_image(Dir) ->
+ %% build docker image
+ BuildScript = filename:join(Dir, "Dockerfile"),
+ Dockerfile =
+ "FROM ubuntu:20.04 as runner\n"
+ "WORKDIR /opt/lambda\n"
+ "COPY lambda.tar.gz /tmp\n"
+ "RUN tar -zxvf /tmp/lambda.tar.gz -C /opt/lambda\n"
+ "ENTRYPOINT [\"/opt/lambda/erts-" ++ erlang:system_info(version) ++ "/bin/dyn_erl\", \"-boot\", \"/opt/lambda/releases/1.0.0/start\"]\n",
+ ok = file:write_file(BuildScript, Dockerfile),
+ Output = os:cmd("docker build -t lambda " ++ Dir),
+ ct:pal("Build result: ~s~n", [Output]).
+
+docker(Config) when is_list(Config) ->
+ case os:find_executable("docker") of
+ false ->
+ {skip, "Docker not found"};
+ Docker ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ build_release(PrivDir),
+ build_image(PrivDir),
+
+ {ok, Peer, Node} = peer:start_link(#{name => ?CT_PEER_NAME(),
+ exec => {Docker, ["run", "-i", "lambda"]}, connection => standard_io}),
+ ?assertEqual(Node, peer:call(Peer, erlang, node, [])),
+ peer:stop(Peer)
+ end.
+
+cntrl_channel_handler_crash() ->
+ [{doc, "Test that peer node is halted if peer control channel handler process crashes"}].
+
+cntrl_channel_handler_crash(Config) ->
+ NameOpts = #{name => ?CT_PEER_NAME()},
+ Opts = case proplists:get_value(connection, Config) of
+ undefined -> NameOpts;
+ Conn -> NameOpts#{connection => Conn}
+ end,
+ {ok, _Peer, Node} = peer:start_link(Opts),
+ cntrl_channel_handler_crash_test(Node).
+
+cntrl_channel_handler_crash_old_release() ->
+ [{doc, "Test that peer node running an old release is halted if peer control channel handler process crashes"}].
+
+cntrl_channel_handler_crash_old_release(Config) ->
+ NameOpts = #{name => ?CT_PEER_NAME()},
+ Opts = case proplists:get_value(connection, Config) of
+ undefined -> NameOpts;
+ Conn -> NameOpts#{connection => Conn}
+ end,
+ PrivDir = proplists:get_value(priv_dir, Config),
+ OldRel = integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 2),
+ case ?CT_PEER_REL(Opts, OldRel, PrivDir) of
+ not_available ->
+ {skip, "No OTP " ++ OldRel ++ " installation found"};
+ {ok, _Peer, Node} ->
+ cntrl_channel_handler_crash_test(Node)
+ end.
+
+cntrl_channel_handler_crash_test(Node) ->
+ true = monitor_node(Node, true),
+ ChkStck = fun ChkStck (_Pid, []) ->
+ ok;
+ ChkStck (Pid, [{peer, io_server_loop, _, _} | _]) ->
+ throw(Pid);
+ ChkStck (Pid, [{peer, origin_link, _, _} | _]) ->
+ throw(Pid);
+ ChkStck (Pid, [_SF|SFs]) ->
+ ChkStck(Pid, SFs)
+ end,
+ ChkConnHandler = fun (undefined) ->
+ ok;
+ (Pid) when is_pid(Pid) ->
+ case erpc:call(Node, erlang, process_info,
+ [Pid, current_stacktrace]) of
+ {current_stacktrace, STrace} ->
+ ChkStck(Pid, STrace);
+ _ ->
+ ok
+ end
+ end,
+ ConnHandler = try
+ ChkConnHandler(erpc:call(Node, erlang, whereis, [user])),
+ lists:foreach(fun (Pid) ->
+ ChkConnHandler(Pid)
+ end, erpc:call(Node, erlang, processes, [])),
+ error(no_cntrl_channel_handler_found)
+ catch
+ throw:Pid when is_pid(Pid) -> Pid
+ end,
+ PeerSup = erpc:call(Node, erlang, whereis, [peer_supervision]),
+ ct:log("peer_supervision state: ~p~n", [erpc:call(Node, sys, get_state, [PeerSup])]),
+ {links, Links} = erpc:call(Node, erlang, process_info, [PeerSup, links]),
+ true = lists:member(ConnHandler, Links),
+ ok = erpc:cast(Node, erlang, exit, [ConnHandler, kill]),
+ receive
+ {nodedown, Node} ->
+ ok
+ after
+ 5000 ->
+ ct:fail(peer_did_not_halt)
+ end.
diff --git a/lib/stdlib/test/pool_SUITE.erl b/lib/stdlib/test/pool_SUITE.erl
index 618d71f6c4..a097f1a17e 100644
--- a/lib/stdlib/test/pool_SUITE.erl
+++ b/lib/stdlib/test/pool_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
init_per_group/2,end_per_group/2]).
-export([basic/1, link_race/1, echo/1]).
+-include_lib("common_test/include/ct.hrl").
+
suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames, 1}]}]}].
all() ->
@@ -45,7 +47,7 @@ end_per_group(_GroupName, Config) ->
basic(Config) ->
- {ok, Node, PoolNode} = init_pool(pool_SUITE_basic, basic, Config),
+ {ok, Peer, Node, PoolNode} = init_pool(?FUNCTION_NAME, basic, Config),
Node = rpc:call(Node, pool, get_node, []),
PoolNode = rpc:call(Node, pool, get_node, []),
@@ -53,19 +55,19 @@ basic(Config) ->
do_echo(Node),
do_echo(Node),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
link_race(Config) ->
- {ok, Node, PoolNode} = init_pool(pool_SUITE_basic, basic, Config),
+ {ok, Peer, Node, PoolNode} = init_pool(?FUNCTION_NAME, basic, Config),
Node = rpc:call(Node, pool, get_node, []),
PoolNode = rpc:call(Node, pool, get_node, []),
rpc:call(Node, pool, pspawn_link, [erlang, is_atom, [?MODULE]]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
do_echo(Node) ->
@@ -79,10 +81,9 @@ echo(Parent) ->
end.
-init_pool(Proxy, Name, Config) ->
+init_pool(Case, Name, Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- [Slave] = proplists:get_value(nodenames, Config),
- {ok, Node} = test_server:start_node(Proxy, slave, []),
+ {ok, Peer, Node} = ?CT_PEER(#{name => Case}),
{ok, Hostname} = inet:gethostname(),
file:write_file(filename:join(PrivDir,".hosts.erlang"),"'"++Hostname++"'.\n"),
ok = rpc:call(Node, file, set_cwd, [PrivDir]),
@@ -92,4 +93,4 @@ init_pool(Proxy, Name, Config) ->
Nodes = rpc:call(Node, pool, get_nodes, []),
[rpc:call(N, code, add_patha, [filename:dirname(code:which(?MODULE))]) || N <- Nodes],
- {ok, Node, PoolNode}.
+ {ok, Peer, Node, PoolNode}.
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index b2ad0ba28f..5db6d88a15 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -668,40 +668,53 @@ stop(_Config) ->
Pid3 = proc_lib:spawn(HangProc),
{'EXIT',timeout} = (catch proc_lib:stop(Pid3,normal,1000)),
+ %% Ensure that a termination message is always sent to the
+ %% target process and that it eventually terminates.
+ Pid4 = proc_lib:spawn(HangProc),
+ Ref4 = monitor(process, Pid4),
+ {'EXIT', timeout} = (catch proc_lib:stop(Pid4, normal, 0)),
+ ok = receive
+ {'DOWN', Ref4, process, _, _} ->
+ ok;
+ M -> M
+ after 6000 ->
+ timeout
+ end,
+
%% Success case with other reason than 'normal'
- Pid4 = proc_lib:spawn(SysMsgProc),
- ok = proc_lib:stop(Pid4,other_reason,infinity),
- false = erlang:is_process_alive(Pid4),
+ Pid5 = proc_lib:spawn(SysMsgProc),
+ ok = proc_lib:stop(Pid5,other_reason,infinity),
+ false = erlang:is_process_alive(Pid5),
%% System message is handled, but process dies with other reason
%% than the given (in system_terminate/4 below)
- Pid5 = proc_lib:spawn(SysMsgProc),
- {'EXIT',{{badmatch,2},_Stacktrace}} = (catch proc_lib:stop(Pid5,crash,infinity)),
- false = erlang:is_process_alive(Pid5),
+ Pid6 = proc_lib:spawn(SysMsgProc),
+ {'EXIT',{{badmatch,2},_Stacktrace}} = (catch proc_lib:stop(Pid6,crash,infinity)),
+ false = erlang:is_process_alive(Pid6),
%% Local registered name
- Pid6 = proc_lib:spawn(SysMsgProc),
- register(to_stop,Pid6),
+ Pid7 = proc_lib:spawn(SysMsgProc),
+ register(to_stop,Pid7),
ok = proc_lib:stop(to_stop),
undefined = whereis(to_stop),
- false = erlang:is_process_alive(Pid6),
+ false = erlang:is_process_alive(Pid7),
%% Remote registered name
- {ok,Node} = test_server:start_node(proc_lib_SUITE_stop,slave,[]),
+ {ok, Peer, Node} = ?CT_PEER(),
Dir = filename:dirname(code:which(?MODULE)),
rpc:call(Node,code,add_path,[Dir]),
- Pid7 = spawn(Node,SysMsgProc),
- true = rpc:call(Node,erlang,register,[to_stop,Pid7]),
- Pid7 = rpc:call(Node,erlang,whereis,[to_stop]),
+ Pid8 = spawn(Node,SysMsgProc),
+ true = rpc:call(Node,erlang,register,[to_stop,Pid8]),
+ Pid8 = rpc:call(Node,erlang,whereis,[to_stop]),
ok = proc_lib:stop({to_stop,Node}),
undefined = rpc:call(Node,erlang,whereis,[to_stop]),
- false = rpc:call(Node,erlang,is_process_alive,[Pid7]),
+ false = rpc:call(Node,erlang,is_process_alive,[Pid8]),
%% Local and remote registered name, but non-existing
{'EXIT',noproc} = (catch proc_lib:stop(to_stop)),
{'EXIT',noproc} = (catch proc_lib:stop({to_stop,Node})),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
%% Remote registered name, but non-existing node
{'EXIT',{{nodedown,Node},_}} = (catch proc_lib:stop({to_stop,Node})),
diff --git a/lib/stdlib/test/property_test/base64_prop.erl b/lib/stdlib/test/property_test/base64_prop.erl
new file mode 100644
index 0000000000..a2e3026dcc
--- /dev/null
+++ b/lib/stdlib/test/property_test/base64_prop.erl
@@ -0,0 +1,429 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(base64_prop).
+
+-compile([export_all, nowarn_export_all]).
+
+-proptest(eqc).
+-proptest([triq, proper]).
+
+-ifndef(EQC).
+-ifndef(PROPER).
+-ifndef(TRIQ).
+-define(EQC, true).
+-endif.
+-endif.
+-endif.
+
+-ifdef(EQC).
+-include_lib("eqc/include/eqc.hrl").
+-define(MOD_eqc,eqc).
+
+-else.
+-ifdef(PROPER).
+-include_lib("proper/include/proper.hrl").
+-define(MOD_eqc,proper).
+
+-else.
+-ifdef(TRIQ).
+-define(MOD_eqc,triq).
+-include_lib("triq/include/triq.hrl").
+
+-endif.
+-endif.
+-endif.
+
+%%%%%%%%%%%%%%%%%%
+%%% Properties %%%
+%%%%%%%%%%%%%%%%%%
+
+prop_encode() ->
+ ?FORALL(
+ Str,
+ oneof([list(byte()), binary()]),
+ begin
+ Enc = base64:encode(Str),
+ Dec = base64:decode(Enc),
+ is_b64_binary(Enc) andalso str_equals(Str, Dec)
+ end
+ ).
+
+prop_encode_to_string() ->
+ ?FORALL(
+ Str,
+ oneof([list(byte()), binary()]),
+ begin
+ Enc = base64:encode_to_string(Str),
+ Dec = base64:decode_to_string(Enc),
+ is_b64_string(Enc) andalso str_equals(Str, Dec)
+ end
+ ).
+
+prop_decode() ->
+ ?FORALL(
+ {NormalizedB64, WspedB64},
+ wsped_b64(),
+ begin
+ Dec = base64:decode(WspedB64),
+ Enc = base64:encode(Dec),
+ is_binary(Dec) andalso b64_equals(NormalizedB64, Enc)
+ end
+ ).
+
+prop_decode_malformed() ->
+ common_decode_malformed(wsped_b64(), fun base64:decode/1).
+
+prop_decode_noisy() ->
+ common_decode_noisy(fun base64:decode/1).
+
+prop_decode_to_string() ->
+ ?FORALL(
+ {NormalizedB64, WspedB64},
+ wsped_b64(),
+ begin
+ Dec = base64:decode_to_string(WspedB64),
+ Enc = base64:encode(Dec),
+ is_bytelist(Dec) andalso b64_equals(NormalizedB64, Enc)
+ end
+ ).
+
+prop_decode_to_string_malformed() ->
+ common_decode_malformed(wsped_b64(), fun base64:decode_to_string/1).
+
+prop_decode_to_string_noisy() ->
+ common_decode_noisy(fun base64:decode_to_string/1).
+
+prop_mime_decode() ->
+ ?FORALL(
+ {NormalizedB64, NoisyB64},
+ noisy_b64(),
+ begin
+ Dec = base64:mime_decode(NoisyB64),
+ Enc = base64:encode(Dec),
+ is_binary(Dec) andalso b64_equals(NormalizedB64, Enc)
+ end
+ ).
+
+prop_mime_decode_malformed() ->
+ common_decode_malformed(noisy_b64(), fun base64:mime_decode/1).
+
+prop_mime_decode_to_string() ->
+ ?FORALL(
+ {NormalizedB64, NoisyB64},
+ noisy_b64(),
+ begin
+ Dec = base64:mime_decode_to_string(NoisyB64),
+ Enc = base64:encode(Dec),
+ is_bytelist(Dec) andalso b64_equals(NormalizedB64, Enc)
+ end
+ ).
+
+prop_mime_decode_to_string_malformed() ->
+ common_decode_malformed(noisy_b64(), fun base64:mime_decode_to_string/1).
+
+common_decode_noisy(Fn) ->
+ ?FORALL(
+ {_, NoisyB64},
+ ?SUCHTHAT({NormalizedB64, NoisyB64}, noisy_b64(), NormalizedB64 =/= NoisyB64),
+ try
+ Fn(NoisyB64)
+ of
+ _ ->
+ false
+ catch
+ error:_ ->
+ true
+ end
+ ).
+
+common_decode_malformed(Gen, Fn) ->
+ ?FORALL(
+ MalformedB64,
+ ?LET(
+ {{NormalizedB64, NoisyB64}, Malformings},
+ {
+ Gen,
+ oneof(
+ [
+ [b64_char()],
+ [b64_char(), b64_char()],
+ [b64_char(), b64_char(), b64_char()]
+ ]
+ )
+ },
+ {NormalizedB64, insert_noise(NoisyB64, Malformings)}
+ ),
+ try
+ Fn(MalformedB64)
+ of
+ _ ->
+ false
+ catch
+ error:_ ->
+ true
+ end
+ ).
+
+%%%%%%%%%%%%%%%%%%
+%%% Generators %%%
+%%%%%%%%%%%%%%%%%%
+
+%% Generate a single character from the base64 alphabet.
+b64_char() ->
+ oneof(b64_chars()).
+
+%% Generate a string of characters from the base64 alphabet,
+%% including padding if needed.
+b64_string() ->
+ ?LET(
+ {L, Filler},
+ {list(b64_char()), b64_char()},
+ case length(L) rem 4 of
+ 0 -> L;
+ 1 -> L ++ [Filler, $=, $=];
+ 2 -> L ++ [$=, $=];
+ 3 -> L ++ [$=]
+ end
+ ).
+
+%% Generate a binary of characters from the base64 alphabet,
+%% including padding if needed.
+b64_binary() ->
+ ?LET(
+ L,
+ b64_string(),
+ list_to_binary(L)
+ ).
+
+%% Generate a string or binary of characters from the
+%% base64 alphabet, including padding if needed.
+b64() ->
+ oneof([b64_string(), b64_binary()]).
+
+%% Generate a string or binary of characters from the
+%% base64 alphabet, including padding if needed, with
+%% whitespaces inserted at random indexes.
+wsped_b64() ->
+ ?LET(
+ {B64, Wsps},
+ {b64(), list(oneof([$\t, $\r, $\n, $\s]))},
+ {B64, insert_noise(B64, Wsps)}
+ ).
+
+%% Generate a single character outside of the base64 alphabet.
+%% As whitespaces are allowed but ignored in base64, this generator
+%% will produce no whitespaces, either.
+non_b64_char() ->
+ oneof(lists:seq(16#00, 16#FF) -- b64_allowed_chars()).
+
+%% Generate a string or binary of characters from the
+%% base64 alphabet, including padding if needed, with
+%% whitespaces and non-base64 ("invalid") characters
+%% inserted at random indexes.
+noisy_b64() ->
+ ?LET(
+ {{B64, WspedB64}, Noise},
+ {wsped_b64(), non_empty(list(non_b64_char()))},
+ {B64, insert_noise(WspedB64, Noise)}
+ ).
+
+%%%%%%%%%%%%%%%
+%%% Helpers %%%
+%%%%%%%%%%%%%%%
+
+%% The characters of the base64 alphabet.
+%% "=" is not included, as it is special in that it
+%% may only appear at the end of a base64 encoded string
+%% for padding.
+b64_chars() ->
+ lists:seq($0, $9) ++
+ lists:seq($a, $z) ++
+ lists:seq($A, $Z) ++
+ [$+, $/].
+
+%% In addition to the above, the whitespace characters
+%% HTAB, CR, LF and SP are allowed to appear in a base64
+%% encoded string and should be ignored.
+b64_allowed_chars() ->
+ [$\t, $\r, $\n, $\s | b64_chars()].
+
+%% Insert the given list of noise characters at random
+%% places into the given base64 string.
+insert_noise(B64, []) ->
+ B64;
+insert_noise([], Noise) ->
+ Noise;
+insert_noise(<<>>, Noise) ->
+ list_to_binary(Noise);
+insert_noise([B|Bs] = B64, [N|Ns] = Noise) ->
+ case rand:uniform(2) of
+ 1 ->
+ [B|insert_noise(Bs, Noise)];
+ 2 ->
+ [N|insert_noise(B64, Ns)]
+ end;
+insert_noise(<<B, Bs/binary>> = B64, [N|Ns] = Noise) ->
+ case rand:uniform(2) of
+ 1 ->
+ <<B, (insert_noise(Bs, Noise))/binary>>;
+ 2 ->
+ <<N, (insert_noise(B64, Ns))/binary>>
+ end.
+
+%% Check if the given character is in the base64 alphabet.
+%% This does not include the padding character "=".
+is_b64_char($+) ->
+ true;
+is_b64_char($/) ->
+ true;
+is_b64_char(C) when C >= $0, C =< $9 ->
+ true;
+is_b64_char(C) when C >= $A, C =< $Z ->
+ true;
+is_b64_char(C) when C >= $a, C =< $z ->
+ true;
+is_b64_char(_) ->
+ false.
+
+%% Check if the given argument is a base64 binary,
+%% ie that it consists of quadruplets of characters
+%% from the base64 alphabet, whereas the last quadruplet
+%% may be padded with one or two "="s
+is_b64_binary(B) ->
+ is_b64_binary(B, 0).
+
+is_b64_binary(<<>>, N) ->
+ N rem 4 =:= 0;
+is_b64_binary(<<$=>>, N) ->
+ N rem 4 =:= 3;
+is_b64_binary(<<$=, $=>>, N) ->
+ N rem 4 =:= 2;
+is_b64_binary(<<C, More/binary>>, N) ->
+ case is_b64_char(C) of
+ true ->
+ is_b64_binary(More, N + 1);
+ false ->
+ false
+ end.
+
+%% Check if the given argument is a base64 string
+%% (see is_b64_binary/1)
+is_b64_string(S) ->
+ is_b64_binary(list_to_binary(S)).
+
+%% Check if the argument is a list of bytes.
+is_bytelist(L) ->
+ lists:all(
+ fun (B) ->
+ is_integer(B) andalso B >= 16#00 andalso B =< 16#FF
+ end,
+ L
+ ).
+
+%% Check two byte-lists or binaries for equality.
+str_equals(Str1, Str2) when is_list(Str1) ->
+ str_equals(list_to_binary(Str1), Str2);
+str_equals(Str1, Str2) when is_list(Str2) ->
+ str_equals(Str1, list_to_binary(Str2));
+str_equals(Str1, Str2) when is_binary(Str1), is_binary(Str2) ->
+ Str1 =:= Str2.
+
+%% Check two base64-encoded byte-lists or binaries for equality.
+%% Assumes that the given arguments are in a normalized form,
+%% ie that they consist only of characters from the base64
+%% alphabet and possible padding ("=").
+b64_equals(L, B) when is_list(L) ->
+ b64_equals(list_to_binary(L), B);
+b64_equals(B, L) when is_list(L) ->
+ b64_equals(B, list_to_binary(L));
+b64_equals(B1, B2) when is_binary(B1), is_binary(B2) ->
+ b64_equals1(B1, B2).
+
+b64_equals1(<<Eq:4/bytes>>, <<Eq:4/bytes>>) ->
+ is_b64_binary(Eq);
+b64_equals1(<<Eq:4/bytes, More1/binary>>, <<Eq:4/bytes, More2/binary>>) ->
+ case lists:all(fun is_b64_char/1, binary_to_list(Eq)) of
+ true ->
+ b64_equals1(More1, More2);
+ false ->
+ false
+ end;
+b64_equals1(<<Eq, B1, $=, $=>>, <<Eq, B2, $=, $=>>) ->
+ %% If the encoded string ends with "==", there exist multiple
+ %% possibilities for the character preceding the "==" as only the
+ %% 3rd and 4th bits of the encoded byte represented by that
+ %% character are significant.
+ %%
+ %% For example, all of the encoded strings "QQ==", "QR==", ..., "QZ=="
+ %% decode to the string "A", since all the bytes represented by Q to Z
+ %% are the same in the significant 3rd and 4th bit.
+ case is_b64_char(Eq) of
+ true ->
+ Normalize = fun
+ (C) when C >= $A, C =< $P -> $A;
+ (C) when C >= $Q, C =< $Z -> $Q;
+ (C) when C >= $a, C =< $f -> $Q;
+ (C) when C >= $g, C =< $v -> $g;
+ (C) when C >= $w, C =< $z -> $w;
+ (C) when C >= $0, C =< $9 -> $w;
+ ($+) -> $w;
+ ($/) -> $w
+ end,
+ Normalize(B1) =:= Normalize(B2);
+ false ->
+ false
+ end;
+b64_equals1(<<Eq:2/bytes, B1, $=>>, <<Eq:2/bytes, B2, $=>>) ->
+ %% Similar to the above, but with the encoded string ending with a
+ %% single "=" the 3rd to 6th bits of the encoded byte are significant,
+ %% such that, for example, all the encoded strings "QUE=" to "QUH="
+ %% decode to the same string "AA".
+ <<Eq1, Eq2>> = Eq,
+ case is_b64_char(Eq1) andalso is_b64_char(Eq2) of
+ true ->
+ Normalize = fun
+ (C) when C >= $A, C =< $D -> $A;
+ (C) when C >= $E, C =< $H -> $E;
+ (C) when C >= $I, C =< $L -> $I;
+ (C) when C >= $M, C =< $P -> $M;
+ (C) when C >= $Q, C =< $T -> $Q;
+ (C) when C >= $U, C =< $X -> $U;
+ (C) when C >= $Y, C =< $Z -> $Y;
+ (C) when C >= $a, C =< $b -> $Y;
+ (C) when C >= $c, C =< $f -> $c;
+ (C) when C >= $g, C =< $j -> $g;
+ (C) when C >= $k, C =< $n -> $k;
+ (C) when C >= $o, C =< $r -> $o;
+ (C) when C >= $s, C =< $v -> $s;
+ (C) when C >= $w, C =< $z -> $w;
+ (C) when C >= $0, C =< $3 -> $0;
+ (C) when C >= $4, C =< $7 -> $4;
+ (C) when C >= $8, C =< $9 -> $8;
+ ($+) -> $8;
+ ($/) -> $8
+ end,
+ Normalize(B1) =:= Normalize(B2);
+ false ->
+ false
+ end;
+b64_equals1(<<>>, <<>>) ->
+ true;
+b64_equals1(_, _) ->
+ false.
diff --git a/lib/stdlib/test/property_test/queue_prop.erl b/lib/stdlib/test/property_test/queue_prop.erl
new file mode 100644
index 0000000000..03372d2aab
--- /dev/null
+++ b/lib/stdlib/test/property_test/queue_prop.erl
@@ -0,0 +1,898 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(queue_prop).
+
+-compile(export_all).
+
+-proptest(eqc).
+-proptest([triq, proper]).
+
+-ifndef(EQC).
+-ifndef(PROPER).
+-ifndef(TRIQ).
+-define(EQC, true).
+-endif.
+-endif.
+-endif.
+
+-ifdef(EQC).
+-include_lib("eqc/include/eqc.hrl").
+-define(MOD_eqc,eqc).
+
+-else.
+-ifdef(PROPER).
+-include_lib("proper/include/proper.hrl").
+-define(MOD_eqc,proper).
+
+-else.
+-ifdef(TRIQ).
+-define(MOD_eqc,triq).
+-include_lib("triq/include/triq.hrl").
+
+-endif.
+-endif.
+-endif.
+
+%%%%%%%%%%%%%%%%%%
+%%% Properties %%%
+%%%%%%%%%%%%%%%%%%
+
+prop_new() ->
+ [] =:= queue:to_list(queue:new()).
+
+prop_is_queue() ->
+ ?FORALL(
+ {IsQueue, Q},
+ oneof([
+ {true, queue()},
+ {false, non_queue()}
+ ]),
+ begin
+ IsQueue =:= queue:is_queue(Q)
+ end
+ ).
+
+prop_list_conversion() ->
+ ?FORALL(
+ List,
+ list(),
+ begin
+ Queue = queue:from_list(List),
+ queue:is_queue(Queue) andalso
+ List =:= queue:to_list(Queue)
+ end
+ ).
+
+prop_from_list_invalid() ->
+ ?FORALL(
+ NonList,
+ ?SUCHTHAT(T, term(), not is_list(T)),
+ expect_badarg(fun queue:from_list/1, [NonList])
+ ).
+
+prop_to_list_invalid() ->
+ common_invalid(fun queue:to_list/1).
+
+prop_all() ->
+ ?FORALL(
+ {L, Q},
+ oneof([list_queue(atom()), list_queue(term())]),
+ begin
+ lists:all(fun is_atom/1, L) =:= queue:all(fun is_atom/1, Q)
+ end
+ ).
+
+prop_all_invalid() ->
+ common_invalid_pred(fun queue:all/2).
+
+prop_any() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ lists:any(fun is_atom/1, L) =:= queue:any(fun is_atom/1, Q)
+ end
+ ).
+
+prop_any_invalid() ->
+ common_invalid_pred(fun queue:any/2).
+
+prop_cons() ->
+ common_in_r_cons(fun queue:cons/2).
+
+prop_cons_invalid() ->
+ common_invalid_term(fun queue:cons/2).
+
+prop_daeh() ->
+ common_get_r_last_daeh(fun queue:daeh/1).
+
+prop_daeh_invalid() ->
+ common_invalid(fun queue:daeh/1).
+
+prop_delete() ->
+ ?FORALL(
+ {X, {L, Q}},
+ {term(), list_queue()},
+ begin
+ R1 = if
+ L =:= [] ->
+ true;
+ true ->
+ Y = lists:nth(rand:uniform(length(L)), L),
+ equal(lists:delete(Y, L), queue:delete(Y, Q))
+ end,
+ R2 = equal(lists:delete(X, L), queue:delete(X, Q)),
+
+ R1 andalso R2
+ end
+ ).
+
+prop_delete_invalid() ->
+ common_invalid_term(fun queue:delete/2).
+
+prop_delete_r() ->
+ ?FORALL(
+ {X, {L, Q}},
+ {term(), list_queue()},
+ begin
+ R1 = if
+ L =:= [] ->
+ true;
+ true ->
+ Y = lists:nth(rand:uniform(length(L)), L),
+ equal(lists:reverse(lists:delete(Y, lists:reverse(L))), queue:delete_r(Y, Q))
+ end,
+ R2 = equal(lists:reverse(lists:delete(X, lists:reverse(L))), queue:delete_r(X, Q)),
+
+ R1 andalso R2
+ end
+ ).
+
+prop_delete_r_invalid() ->
+ common_invalid_term(fun queue:delete_r/2).
+
+prop_delete_with() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ Q1 = queue:delete_with(fun is_atom/1, Q),
+ L1 = case lists:search(fun is_atom/1, L) of
+ false ->
+ L;
+ {value, V} ->
+ lists:delete(V, L)
+ end,
+ equal(L1, Q1)
+ end
+ ).
+
+prop_delete_with_invalid() ->
+ common_invalid_pred(fun queue:delete_with/2).
+
+prop_delete_with_r() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ Q1 = queue:delete_with_r(fun is_atom/1, Q),
+ L1 = lists:reverse(L),
+ L2 = case lists:search(fun is_atom/1, L1) of
+ false ->
+ L;
+ {value, V} ->
+ lists:reverse(lists:delete(V, L1))
+ end,
+ equal(L2, Q1)
+ end
+ ).
+
+prop_delete_with_r_invalid() ->
+ common_invalid_pred(fun queue:delete_with_r/2).
+
+prop_drop() ->
+ common_drop_tail(fun queue:drop/1).
+
+prop_drop_invalid() ->
+ common_invalid(fun queue:drop/1).
+
+prop_drop_r() ->
+ common_drop_r_init_liat(fun queue:drop_r/1).
+
+prop_drop_r_invalid() ->
+ common_invalid(fun queue:drop_r/1).
+
+prop_filter() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ Q1 = queue:filter(
+ fun
+ (I) when is_atom(I) -> true;
+ (I) when is_integer(I) -> [I * 2];
+ (I) when is_float(I) -> [{I, I}];
+ (I) when is_tuple(I) -> [I, I];
+ (_) -> false
+ end,
+ Q
+ ),
+ L1 = lists:foldr(
+ fun
+ (I, Acc) when is_atom(I) -> [I|Acc];
+ (I, Acc) when is_integer(I) -> [I * 2|Acc];
+ (I, Acc) when is_float(I) -> [{I, I}|Acc];
+ (I, Acc) when is_tuple(I) -> [I, I|Acc];
+ (_, Acc) -> Acc
+ end,
+ [],
+ L
+ ),
+ equal(L1, Q1)
+ end
+ ).
+
+prop_filter_invalid() ->
+ common_invalid_pred(fun queue:filter/2).
+
+prop_filtermap() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ F = fun
+ (I) when is_atom(I) ->
+ true;
+ (I) when is_integer(I) ->
+ {true, {I, I}};
+ (_) ->
+ false
+ end,
+ Q1 = queue:filtermap(F, Q),
+ L1 = lists:filtermap(F, L),
+ equal(L1, Q1)
+ end
+ ).
+
+prop_filtermap_invalid() ->
+ common_invalid_pred(fun queue:filtermap/2).
+
+prop_fold() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ % order-independent fold
+ F1 = fun
+ (I, Acc) when is_number(I) -> Acc + 2 * I;
+ (_, Acc) -> Acc
+ end,
+ RQ1 = queue:fold(F1, 0, Q),
+ RL1 = lists:foldl(F1, 0, L),
+
+ % order-dependent fold
+ F2 = fun
+ (I, Acc) -> [{I, I}|Acc]
+ end,
+ RQ2 = queue:fold(F2, [], Q),
+ RL2 = lists:foldl(F2, [], L),
+
+ RQ1 =:= RL1 andalso
+ RQ2 =:= RL2
+ end
+ ).
+
+prop_fold_invalid() ->
+ ?FORALL(
+ {Q, Fn},
+ oneof([{non_queue(), fun erlang:'+'/2}, {queue(), non_fun(2)}, {non_queue(), non_fun(2)}]),
+ expect_badarg(fun queue:fold/3, [Fn, 0, Q])
+ ).
+
+prop_get() ->
+ common_get_head(fun queue:get/1).
+
+prop_get_invalid() ->
+ common_invalid(fun queue:get/1).
+
+prop_get_r() ->
+ common_get_r_last_daeh(fun queue:get_r/1).
+
+prop_get_r_invalid() ->
+ common_invalid(fun queue:get_r/1).
+
+prop_head() ->
+ common_get_head(fun queue:head/1).
+
+prop_head_invalid() ->
+ common_invalid(fun queue:head/1).
+
+prop_in() ->
+ ?FORALL(
+ L,
+ list(),
+ begin
+ Q = lists:foldl(
+ fun(I, Acc) ->
+ queue:in(I, Acc)
+ end,
+ queue:new(),
+ L
+ ),
+ equal(L, Q)
+ end
+ ).
+
+prop_in_invalid() ->
+ common_invalid_term(fun queue:in/2).
+
+prop_in_r() ->
+ common_in_r_cons(fun queue:in_r/2).
+
+prop_in_r_invalid() ->
+ common_invalid_term(fun queue:in_r/2).
+
+prop_init() ->
+ common_drop_r_init_liat(fun queue:init/1).
+
+prop_init_invalid() ->
+ common_invalid(fun queue:init/1).
+
+prop_is_empty() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ (length(L) =:= 0) =:= queue:is_empty(Q)
+ end
+ ).
+
+prop_is_empty_invalid() ->
+ common_invalid(fun queue:is_empty/1).
+
+prop_join() ->
+ ?FORALL(
+ {{L1, Q1}, {L2, Q2}},
+ {list_queue(), list_queue()},
+ begin
+ equal(L1 ++ L2, queue:join(Q1, Q2))
+ end
+ ).
+
+prop_join_invalid() ->
+ ?FORALL(
+ {Q1, Q2},
+ oneof([{non_queue(), queue()}, {queue(), non_queue()}, {non_queue(), non_queue()}]),
+ expect_badarg(fun queue:join/2, [Q1, Q2])
+ ).
+
+prop_last() ->
+ common_get_r_last_daeh(fun queue:last/1).
+
+prop_last_invalid() ->
+ common_invalid(fun queue:last/1).
+
+prop_len() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ length(L) =:= queue:len(Q)
+ end
+ ).
+
+prop_len_invalid() ->
+ common_invalid(fun queue:len/1).
+
+prop_liat() ->
+ common_drop_r_init_liat(fun queue:liat/1).
+
+prop_liat_invalid() ->
+ common_invalid(fun queue:liat/1).
+
+prop_member() ->
+ ?FORALL(
+ {X, {L, Q}},
+ {term(), list_queue()},
+ begin
+ % all members of L are members of Q
+ lists:all(
+ fun(I) ->
+ queue:member(I, Q)
+ end,
+ L
+ )
+ andalso
+ % all members of Q are members of L
+ lists:all(
+ fun(I) ->
+ lists:member(I, L)
+ end,
+ queue:to_list(Q)
+ )
+ andalso
+ % if X is a member of L, it is also a member of Q,
+ % and if X is not a member of L, it is also not a
+ % member of Q
+ lists:member(X, L) =:= queue:member(X, Q)
+ end
+ ).
+
+prop_member_invalid() ->
+ common_invalid_term(fun queue:member/2).
+
+prop_out() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ case queue:out(Q) of
+ {{value, I}, Q1} ->
+ I =:= hd(L) andalso
+ equal(tl(L), Q1);
+ {empty, Q1} ->
+ L =:= [] andalso
+ equal(L, Q1)
+ end
+ end
+ ).
+
+prop_out_invalid() ->
+ common_invalid(fun queue:out/1).
+
+prop_out_r() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ case queue:out_r(Q) of
+ {{value, I}, Q1} ->
+ L1 = lists:reverse(L),
+ I =:= hd(L1) andalso
+ equal(lists:reverse(tl(L1)), Q1);
+ {empty, Q1} ->
+ L =:= [] andalso
+ equal(L, Q1)
+ end
+ end
+ ).
+
+prop_out_r_invalid() ->
+ common_invalid(fun queue:out_r/1).
+
+prop_peek() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ case queue:peek(Q) of
+ {value, I} ->
+ I =:= hd(L);
+ empty ->
+ L =:= []
+ end
+ end
+ ).
+
+prop_peek_invalid() ->
+ common_invalid(fun queue:peek/1).
+
+prop_peek_r() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ case queue:peek_r(Q) of
+ {value, I} ->
+ I =:= lists:last(L);
+ empty ->
+ L =:= []
+ end
+ end
+ ).
+
+prop_peek_r_invalid() ->
+ common_invalid(fun queue:peek_r/1).
+
+prop_reverse() ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ begin
+ equal(lists:reverse(L), queue:reverse(Q))
+ end
+ ).
+
+prop_reverse_invalid() ->
+ common_invalid(fun queue:reverse/1).
+
+prop_snoc() ->
+ ?FORALL(
+ L,
+ list(),
+ begin
+ Q = lists:foldl(
+ fun(I, Acc) ->
+ queue:snoc(Acc, I)
+ end,
+ queue:new(),
+ L
+ ),
+ equal(L, Q)
+ end
+ ).
+
+prop_snoc_invalid() ->
+ ?FORALL(
+ {I, NonQueue},
+ {term(), non_queue()},
+ expect_badarg(fun queue:snoc/2, [NonQueue, I])
+ ).
+
+prop_split() ->
+ ?FORALL(
+ {N, {L, Q}},
+ {non_neg_integer(), list_queue()},
+ begin
+ N1 = N rem (length(L) + 1),
+ {Q1, Q2} = queue:split(N1, Q),
+ {L1, L2} = lists:split(N1, L),
+
+ equal(L1, Q1) andalso
+ equal(L2, Q2)
+ end
+ ).
+
+prop_split_invalid() ->
+ ?FORALL(
+ {Q, N},
+ oneof(
+ [
+ {non_queue(), 0},
+ ?SUCHTHAT(
+ {Q1, N1},
+ {queue(), term()},
+ not(is_integer(N1) andalso N1>=0 andalso N1=<queue:len(Q1))
+ )
+ ]
+ ),
+ expect_badarg(fun queue:split/2, [N, Q])
+ ).
+
+prop_tail() ->
+ common_drop_tail(fun queue:tail/1).
+
+prop_tail_invalid() ->
+ common_invalid(fun queue:tail/1).
+
+% Test sequences of insert and retrieval operations
+prop_ops() ->
+ ?FORALL(
+ {Ops, {L, Q}},
+ {
+ list(
+ oneof([{cons, term()},
+ daeh,
+ drop,
+ drop_r,
+ get,
+ get_r,
+ head,
+ {in, term()},
+ {in_r, term()},
+ init,
+ liat,
+ last,
+ out,
+ out_r,
+ peek,
+ peek_r,
+ {snoc, term()},
+ tail])
+ ),
+ list_queue()
+ },
+ do_ops(Ops, L, Q)
+ ).
+
+%% Executes the given sequence of queue operations on a model (list)
+%% and a queue and compares the returned items (if any) as well as
+%% the model and queue.
+do_ops([], L, Q) ->
+ equal(L, Q);
+do_ops([Op|Ops], L0, Q0) ->
+ {LItem, L1} = do_op_list(Op, L0),
+ {QItem, Q1} = do_op_queue(Op, Q0),
+
+ LItem =:= QItem andalso
+ equal(L1, Q1) andalso
+ do_ops(Ops, L1, Q1).
+
+list_op_map() ->
+ % Inserts item at the rear; affects only the model list, returns no value
+ InsertRearOp = fun(I, L) -> {undefined, L ++ [I]} end,
+ % Inserts item at the front; affects only the model list, returns no value
+ InsertFrontOp = fun(I, L) -> {undefined, [I|L]} end,
+
+ % Helper for functions that should return empty when the model list is empty
+ MaybeEmpty = fun(F) -> fun([]) -> {empty, []}; (L) -> F(L) end end,
+
+ % For functions that both affect the model list and return a value
+ TakeOp = fun(VF, QF) -> fun(L) -> {{value, VF(L)}, QF(L)} end end,
+
+ % For functions that do not affect the model list but return a value
+ ValueOp = fun(F) -> fun(L) -> {{value, F(L)}, L} end end,
+
+ % For functions that affect the model list and do not return a value
+ QueueOp = fun(F) -> fun(L) -> {undefined, F(L)} end end,
+
+ #{
+ in => InsertRearOp,
+ in_r => InsertFrontOp,
+ cons => InsertFrontOp,
+ snoc => InsertRearOp,
+ out => MaybeEmpty(TakeOp(fun erlang:hd/1, fun erlang:tl/1)),
+ out_r => MaybeEmpty(TakeOp(fun lists:last/1, fun lists:droplast/1)),
+ peek => MaybeEmpty(ValueOp(fun erlang:hd/1)),
+ peek_r => MaybeEmpty(ValueOp(fun lists:last/1)),
+ get => MaybeEmpty(ValueOp(fun erlang:hd/1)),
+ get_r => MaybeEmpty(ValueOp(fun lists:last/1)),
+ head => MaybeEmpty(ValueOp(fun erlang:hd/1)),
+ daeh => MaybeEmpty(ValueOp(fun lists:last/1)),
+ last => MaybeEmpty(ValueOp(fun lists:last/1)),
+ init => MaybeEmpty(QueueOp(fun lists:droplast/1)),
+ drop => MaybeEmpty(QueueOp(fun erlang:tl/1)),
+ drop_r => MaybeEmpty(QueueOp(fun lists:droplast/1)),
+ tail => MaybeEmpty(QueueOp(fun erlang:tl/1)),
+ liat => MaybeEmpty(QueueOp(fun lists:droplast/1))
+ }.
+
+do_op_list({Op, I}, L) ->
+ F = maps:get(Op, list_op_map()),
+ F(I, L);
+do_op_list(Op, L) ->
+ F = maps:get(Op, list_op_map()),
+ F(L).
+
+queue_op_map() ->
+ % Helper for swapping arguments
+ SwapArgs = fun(F) -> fun(X, Y) -> F(Y, X) end end,
+
+ % For functions that affect the queue but do not return a value
+ QueueOp1 = fun(F) -> fun(Q) -> {undefined, F(Q)} end end,
+ QueueOp2 = fun(F) -> fun(I, Q) -> {undefined, F(I, Q)} end end,
+
+ % For functions that return a value wrapped in a tuple
+ WrappedReturn = fun(F) -> fun(Q) -> {F(Q), Q} end end,
+
+ % For functions that return an unwrapped value
+ PlainReturn = fun(F) -> fun(Q) -> {{value, F(Q)}, Q} end end,
+
+ % Helper for functions that raise an error when used on
+ % an empty queue
+ CatchEmpty = fun(F) ->
+ fun(Q) ->
+ try F(Q) catch error:empty -> {empty, Q} end
+ end
+ end,
+
+ #{
+ in => QueueOp2(fun queue:in/2),
+ in_r => QueueOp2(fun queue:in_r/2),
+ cons => QueueOp2(fun queue:cons/2),
+ snoc => QueueOp2(SwapArgs(fun queue:snoc/2)),
+ out => fun queue:out/1,
+ out_r => fun queue:out_r/1,
+ peek => WrappedReturn(fun queue:peek/1),
+ peek_r => WrappedReturn(fun queue:peek_r/1),
+ get => CatchEmpty(PlainReturn(fun queue:get/1)),
+ get_r => CatchEmpty(PlainReturn(fun queue:get_r/1)),
+ head => CatchEmpty(PlainReturn(fun queue:head/1)),
+ daeh => CatchEmpty(PlainReturn(fun queue:daeh/1)),
+ last => CatchEmpty(PlainReturn(fun queue:last/1)),
+ init => CatchEmpty(QueueOp1(fun queue:init/1)),
+ drop => CatchEmpty(QueueOp1(fun queue:drop/1)),
+ drop_r => CatchEmpty(QueueOp1(fun queue:drop_r/1)),
+ tail => CatchEmpty(QueueOp1(fun queue:tail/1)),
+ liat => CatchEmpty(QueueOp1(fun queue:liat/1))
+ }.
+
+do_op_queue({Op, I}, Q) ->
+ F = maps:get(Op, queue_op_map()),
+ F(I, Q);
+do_op_queue(Op, Q) ->
+ F = maps:get(Op, queue_op_map()),
+ F(Q).
+
+%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Property helpers %%%
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+% get/1 and head/1 have the same semantics
+common_get_head(Fn) ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ try
+ Fn(Q)
+ of E ->
+ E =:= hd(L)
+ catch error:empty ->
+ L =:= []
+ end
+ ).
+
+% get_r/1, last/1 and daeh/1 have the same semantics
+common_get_r_last_daeh(Fn) ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ try
+ Fn(Q)
+ of E ->
+ E =:= lists:last(L)
+ catch error:empty ->
+ L =:= []
+ end
+ ).
+
+% drop_r/1, init/1 and liat/1 have the same semantics
+common_drop_r_init_liat(Fn) ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ try
+ Fn(Q)
+ of Q1 ->
+ equal(lists:droplast(L), Q1)
+ catch error:empty ->
+ L =:= []
+ end
+ ).
+
+% drop/1 and tail/1 have the same semantics
+common_drop_tail(Fn) ->
+ ?FORALL(
+ {L, Q},
+ list_queue(),
+ try
+ Fn(Q)
+ of Q1 ->
+ equal(tl(L), Q1)
+ catch error:empty ->
+ L =:= []
+ end
+ ).
+
+% in_r/2 and cons/2 have the same semantics
+common_in_r_cons(Fn) ->
+ ?FORALL(
+ L,
+ list(),
+ begin
+ Q = lists:foldl(
+ fun(I, Acc) ->
+ Fn(I, Acc)
+ end,
+ queue:new(),
+ L
+ ),
+ equal(lists:reverse(L), Q)
+ end
+ ).
+
+common_invalid(Fn) ->
+ ?FORALL(
+ NonQueue,
+ non_queue(),
+ expect_badarg(Fn, [NonQueue])
+ ).
+
+common_invalid_pred(Fn) ->
+ ?FORALL(
+ {Q, Pred},
+ oneof([{non_queue(), fun is_atom/1}, {queue(), non_fun(1)}, {non_queue(), non_fun(1)}]),
+ expect_badarg(Fn, [Pred, Q])
+ ).
+
+common_invalid_term(Fn) ->
+ ?FORALL(
+ {I, NonQueue},
+ {term(), non_queue()},
+ expect_badarg(Fn, [I, NonQueue])
+ ).
+
+%%%%%%%%%%%%%%%%%%
+%%% Generators %%%
+%%%%%%%%%%%%%%%%%%
+
+list_queue() ->
+ list_queue(term()).
+
+list_queue(Type) ->
+ ?LET(
+ {List1, List2},
+ {list(Type), list(Type)},
+ begin
+ Queue=lists:foldl(
+ fun(X, Acc) -> queue:in(X, Acc) end,
+ queue:from_list(List1),
+ List2
+ ),
+ {List1 ++ List2, Queue}
+ end
+ ).
+
+queue() ->
+ queue(term()).
+
+queue(Type) ->
+ ?LET(List, list(Type), queue:from_list(List)).
+
+%% This generator produces terms that are not queues.
+%%
+%% Therefore, it relies on knowledge of the internal representation
+%% of queues (at the time of this writing, a tuple of two lists) in
+%% order to prevent accidential generation of a queue.
+%%
+%% If the internal representation of queues ever changes, this
+%% generator has to be changed to reflect this.
+non_queue() ->
+ ?SUCHTHAT(
+ T,
+ term(),
+ not(
+ is_tuple(T) andalso
+ tuple_size(T) =:= 2 andalso
+ is_list(element(1, T)) andalso
+ is_list(element(2, T))
+ )
+ ).
+
+non_fun(Arity) ->
+ ?SUCHTHAT(
+ T,
+ term(),
+ not is_function(T, Arity)
+ ).
+
+%%%%%%%%%%%%%%%
+%%% Helpers %%%
+%%%%%%%%%%%%%%%
+
+% Check equality of lists and/or queues,
+% ie that they contain the same items in
+% the same order.
+equal(L1, L2) when is_list(L1), is_list(L2) ->
+ L1 =:= L2;
+equal(Q, L) when is_list(L) ->
+ equal(queue:to_list(Q), L);
+equal(L, Q) ->
+ equal(L, queue:to_list(Q)).
+
+expect_badarg(Fn, Args) when is_function(Fn, length(Args)) ->
+ try
+ erlang:apply(Fn, Args)
+ of
+ _ -> false
+ catch
+ error:badarg -> true;
+ _:_ -> false
+ end.
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index cb4e710c44..74c8aabf8e 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -1163,9 +1163,9 @@ append(Config) when is_list(Config) ->
evaluator(Config) when is_list(Config) ->
true = is_alive(),
evaluator_2(Config, []),
- {ok, Node} = start_node(qlc_SUITE_evaluator),
+ {ok, Peer, Node} = ?CT_PEER(),
ok = rpc:call(Node, ?MODULE, evaluator_2, [Config, [compiler]]),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
evaluator_2(Config, Apps) ->
@@ -1191,10 +1191,6 @@ evaluator_2(Config, Apps) ->
_ = file:delete(FileName),
ok.
-start_node(Name) ->
- PA = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, "-pa " ++ PA}]).
-
%% string_to_handle/1,2.
string_to_handle(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch qlc:string_to_handle(14)),
@@ -2636,9 +2632,9 @@ info(Config) when is_list(Config) ->
L = [{#{k => #{v => Fun}}, Fun}],
H = qlc:q([Q || Q <- L, Q =:= {#{k => #{v => Fun}}, Fun}]),
L = qlc:e(H),
- {call,_,_,[{lc,_,{var,_,'Q'},
- [{generate,_,_,_},
- {op,_,_,_,_}]}]} =
+ {call,_,{remote,_,{atom,_,ets},{atom,_,match_spec_run}},
+ [_,
+ {call,_,{remote,_,{atom,_,ets},{atom,_,match_spec_compile}},[_]}]} =
qlc:info(H, [{format,abstract_code}])">>
],
@@ -7470,10 +7466,10 @@ etsc(F, Opts, Objs) ->
V.
join_info(H) ->
- {{qlc, S, Options}, Bs} = strip_qlc_call2(H),
+ {qlc, S, Options} = strip_qlc_call(H),
%% "Hide" the call to qlc_pt from the test in run_test().
LoadedPT = code:is_loaded(qlc_pt),
- QH = qlc:string_to_handle(S, Options, Bs),
+ QH = qlc:string_to_handle(S, Options, []),
_ = [unload_pt() || false <- [LoadedPT]], % doesn't take long...
case {join_info_count(H), join_info_count(QH)} of
{N, N} ->
@@ -7483,26 +7479,22 @@ join_info(H) ->
end.
strip_qlc_call(H) ->
- {Expr, _Bs} = strip_qlc_call2(H),
- Expr.
-
-strip_qlc_call2(H) ->
S = qlc:info(H, {flat, false}),
{ok, Tokens, _EndLine} = erl_scan:string(S++".", 1, [text]),
- {ok, [Expr], Bs} = erl_eval:extended_parse_exprs(Tokens),
- {case Expr of
- {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC]} ->
- {qlc, lists:flatten([erl_pp:expr(LC), "."]), []};
- {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC, Opts]} ->
- {qlc, lists:flatten([erl_pp:expr(LC), "."]),
- erl_parse:normalise(Opts)};
- {call,_,{remote,_,{atom,_,ets},{atom,_,match_spec_run}},_} ->
- {match_spec, Expr};
- {call,_,{remote,_,{atom,_,M},{atom,_,table}},_} ->
- {table, M, Expr};
- _ ->
- []
- end, Bs}.
+ {ok, [Expr]} = erl_eval:extended_parse_exprs(Tokens),
+ case Expr of
+ {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC]} ->
+ {qlc, lists:flatten([erl_pp:expr(LC), "."]), []};
+ {call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[LC, Opts]} ->
+ {qlc, lists:flatten([erl_pp:expr(LC), "."]),
+ erl_parse:normalise(Opts)};
+ {call,_,{remote,_,{atom,_,ets},{atom,_,match_spec_run}},_} ->
+ {match_spec, Expr};
+ {call,_,{remote,_,{atom,_,M},{atom,_,table}},_} ->
+ {table, M, Expr};
+ _ ->
+ []
+ end.
-record(ji, {nmerge = 0, nlookup = 0, nnested_loop = 0, nkeysort = 0}).
@@ -7510,7 +7502,7 @@ strip_qlc_call2(H) ->
join_info_count(H) ->
S = qlc:info(H, {flat, false}),
{ok, Tokens, _EndLine} = erl_scan:string(S++".", 1, [text]),
- {ok, [Expr], _Bs} = erl_eval:extended_parse_exprs(Tokens),
+ {ok, [Expr]} = erl_eval:extended_parse_exprs(Tokens),
#ji{nmerge = Nmerge, nlookup = Nlookup,
nkeysort = NKeysort, nnested_loop = Nnested_loop} =
ji(Expr, #ji{}),
@@ -7554,7 +7546,7 @@ lookup_keys({generate,_,Q}, L) ->
lookup_keys(Q, L);
lookup_keys({table,Chars}, L) when is_list(Chars) ->
{ok, Tokens, _} = erl_scan:string(lists:flatten(Chars++"."), 1, [text]),
- {ok, [Expr], _Bs} = erl_eval:extended_parse_exprs(Tokens),
+ {ok, [Expr]} = erl_eval:extended_parse_exprs(Tokens),
case Expr of
{call,_,_,[_fun,AKs]} ->
case erl_parse:normalise(AKs) of
diff --git a/lib/stdlib/test/queue_property_test_SUITE.erl b/lib/stdlib/test/queue_property_test_SUITE.erl
new file mode 100644
index 0000000000..497e8c5fd8
--- /dev/null
+++ b/lib/stdlib/test/queue_property_test_SUITE.erl
@@ -0,0 +1,327 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(queue_property_test_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-compile(export_all).
+
+all() -> [
+ new_case,
+ is_queue_case,
+ list_conversion_case,
+ from_list_invalid_case,
+ to_list_invalid_case,
+
+ all_case,
+ all_invalid_case,
+ any_case,
+ any_invalid_case,
+ cons_case,
+ cons_invalid_case,
+ daeh_case,
+ daeh_invalid_case,
+ delete_case,
+ delete_invalid_case,
+ delete_r_case,
+ delete_r_invalid_case,
+ delete_with_case,
+ delete_with_invalid_case,
+ delete_with_r_case,
+ delete_with_r_invalid_case,
+ drop_case,
+ drop_invalid_case,
+ drop_r_case,
+ drop_r_invalid_case,
+ filter_case,
+ filter_invalid_case,
+ filtermap_case,
+ filtermap_invalid_case,
+ fold_case,
+ fold_invalid_case,
+ get_case,
+ get_invalid_case,
+ get_r_case,
+ get_r_invalid_case,
+ head_case,
+ head_invalid_case,
+ in_case,
+ in_invalid_case,
+ in_r_case,
+ in_r_invalid_case,
+ init_case,
+ init_invalid_case,
+ is_empty_case,
+ is_empty_invalid_case,
+ join_case,
+ join_invalid_case,
+ last_case,
+ last_invalid_case,
+ len_case,
+ len_invalid_case,
+ liat_case,
+ liat_invalid_case,
+ member_case,
+ member_invalid_case,
+ out_case,
+ out_invalid_case,
+ out_r_case,
+ out_r_invalid_case,
+ peek_case,
+ peek_invalid_case,
+ peek_r_case,
+ peek_r_invalid_case,
+ reverse_case,
+ reverse_invalid_case,
+ snoc_case,
+ snoc_invalid_case,
+ split_case,
+ split_invalid_case,
+ tail_case,
+ tail_invalid_case,
+
+ ops_case
+ ].
+
+init_per_suite(Config) ->
+ ct_property_test:init_per_suite(Config).
+
+end_per_suite(Config) ->
+ Config.
+
+new_case(Config) ->
+ do_proptest(prop_new, Config).
+
+is_queue_case(Config) ->
+ do_proptest(prop_is_queue, Config).
+
+list_conversion_case(Config) ->
+ do_proptest(prop_list_conversion, Config).
+
+from_list_invalid_case(Config) ->
+ do_proptest(prop_from_list_invalid, Config).
+
+to_list_invalid_case(Config) ->
+ do_proptest(prop_to_list_invalid, Config).
+
+all_case(Config) ->
+ do_proptest(prop_all, Config).
+
+all_invalid_case(Config) ->
+ do_proptest(prop_all_invalid, Config).
+
+any_case(Config) ->
+ do_proptest(prop_any, Config).
+
+any_invalid_case(Config) ->
+ do_proptest(prop_any_invalid, Config).
+
+cons_case(Config) ->
+ do_proptest(prop_cons, Config).
+
+cons_invalid_case(Config) ->
+ do_proptest(prop_cons_invalid, Config).
+
+daeh_case(Config) ->
+ do_proptest(prop_daeh, Config).
+
+daeh_invalid_case(Config) ->
+ do_proptest(prop_daeh_invalid, Config).
+
+delete_case(Config) ->
+ do_proptest(prop_delete, Config).
+
+delete_invalid_case(Config) ->
+ do_proptest(prop_delete_invalid, Config).
+
+delete_r_case(Config) ->
+ do_proptest(prop_delete_r, Config).
+
+delete_r_invalid_case(Config) ->
+ do_proptest(prop_delete_r_invalid, Config).
+
+delete_with_case(Config) ->
+ do_proptest(prop_delete_with, Config).
+
+delete_with_invalid_case(Config) ->
+ do_proptest(prop_delete_with_invalid, Config).
+
+delete_with_r_case(Config) ->
+ do_proptest(prop_delete_with_r, Config).
+
+delete_with_r_invalid_case(Config) ->
+ do_proptest(prop_delete_with_r_invalid, Config).
+
+drop_case(Config) ->
+ do_proptest(prop_drop, Config).
+
+drop_invalid_case(Config) ->
+ do_proptest(prop_drop_invalid, Config).
+
+drop_r_case(Config) ->
+ do_proptest(prop_drop_r, Config).
+
+drop_r_invalid_case(Config) ->
+ do_proptest(prop_drop_r_invalid, Config).
+
+filter_case(Config) ->
+ do_proptest(prop_filter, Config).
+
+filter_invalid_case(Config) ->
+ do_proptest(prop_filter_invalid, Config).
+
+filtermap_case(Config) ->
+ do_proptest(prop_filtermap, Config).
+
+filtermap_invalid_case(Config) ->
+ do_proptest(prop_filtermap_invalid, Config).
+
+fold_case(Config) ->
+ do_proptest(prop_fold, Config).
+
+fold_invalid_case(Config) ->
+ do_proptest(prop_fold_invalid, Config).
+
+get_case(Config) ->
+ do_proptest(prop_get, Config).
+
+get_invalid_case(Config) ->
+ do_proptest(prop_get_invalid, Config).
+
+get_r_case(Config) ->
+ do_proptest(prop_get_r, Config).
+
+get_r_invalid_case(Config) ->
+ do_proptest(prop_get_r_invalid, Config).
+
+head_case(Config) ->
+ do_proptest(prop_head, Config).
+
+head_invalid_case(Config) ->
+ do_proptest(prop_head_invalid, Config).
+
+in_case(Config) ->
+ do_proptest(prop_in, Config).
+
+in_invalid_case(Config) ->
+ do_proptest(prop_in_invalid, Config).
+
+in_r_case(Config) ->
+ do_proptest(prop_in_r, Config).
+
+in_r_invalid_case(Config) ->
+ do_proptest(prop_in_r_invalid, Config).
+
+init_case(Config) ->
+ do_proptest(prop_init, Config).
+
+init_invalid_case(Config) ->
+ do_proptest(prop_init_invalid, Config).
+
+is_empty_case(Config) ->
+ do_proptest(prop_is_empty, Config).
+
+is_empty_invalid_case(Config) ->
+ do_proptest(prop_is_empty_invalid, Config).
+
+join_case(Config) ->
+ do_proptest(prop_join, Config).
+
+join_invalid_case(Config) ->
+ do_proptest(prop_join_invalid, Config).
+
+last_case(Config) ->
+ do_proptest(prop_last, Config).
+
+last_invalid_case(Config) ->
+ do_proptest(prop_last_invalid, Config).
+
+len_case(Config) ->
+ do_proptest(prop_len, Config).
+
+len_invalid_case(Config) ->
+ do_proptest(prop_len_invalid, Config).
+
+liat_case(Config) ->
+ do_proptest(prop_liat, Config).
+
+liat_invalid_case(Config) ->
+ do_proptest(prop_liat_invalid, Config).
+
+member_case(Config) ->
+ do_proptest(prop_member, Config).
+
+member_invalid_case(Config) ->
+ do_proptest(prop_member_invalid, Config).
+
+out_case(Config) ->
+ do_proptest(prop_out, Config).
+
+out_invalid_case(Config) ->
+ do_proptest(prop_out_invalid, Config).
+
+out_r_case(Config) ->
+ do_proptest(prop_out_r, Config).
+
+out_r_invalid_case(Config) ->
+ do_proptest(prop_out_r_invalid, Config).
+
+peek_case(Config) ->
+ do_proptest(prop_peek, Config).
+
+peek_invalid_case(Config) ->
+ do_proptest(prop_peek_invalid, Config).
+
+peek_r_case(Config) ->
+ do_proptest(prop_peek_r, Config).
+
+peek_r_invalid_case(Config) ->
+ do_proptest(prop_peek_r_invalid, Config).
+
+reverse_case(Config) ->
+ do_proptest(prop_reverse, Config).
+
+reverse_invalid_case(Config) ->
+ do_proptest(prop_reverse_invalid, Config).
+
+snoc_case(Config) ->
+ do_proptest(prop_snoc, Config).
+
+snoc_invalid_case(Config) ->
+ do_proptest(prop_snoc_invalid, Config).
+
+split_case(Config) ->
+ do_proptest(prop_split, Config).
+
+split_invalid_case(Config) ->
+ do_proptest(prop_split_invalid, Config).
+
+tail_case(Config) ->
+ do_proptest(prop_tail, Config).
+
+tail_invalid_case(Config) ->
+ do_proptest(prop_tail_invalid, Config).
+
+ops_case(Config) ->
+ do_proptest(prop_ops, Config).
+
+do_proptest(Prop, Config) ->
+ ct_property_test:quickcheck(
+ queue_prop:Prop(),
+ Config).
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 207cff00e5..11722fd060 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,6 +35,9 @@ all() ->
[seed, interval_int, interval_float,
bytes_count,
api_eq,
+ mwc59_api,
+ exsp_next_api, exsp_jump_api,
+ splitmix64_next_api,
reference,
{group, basic_stats},
{group, distr_stats},
@@ -205,6 +208,106 @@ api_eq_1(S00) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Verify mwc59 behaviour
+%%
+mwc59_api(Config) when is_list(Config) ->
+ try rand:mwc59_seed(-1) of
+ CX1 ->
+ error({bad_return, CX1})
+ catch
+ error : function_clause ->
+ try rand:mwc59_seed(1 bsl 58) of
+ CX2 ->
+ error({bad_return, CX2})
+ catch
+ error : function_clause ->
+ Seed = 11213862807209314,
+ Seed = rand:mwc59_seed(1),
+ mwc59_api(Seed, 1000000)
+ end
+ end.
+
+mwc59_api(CX0, 0) ->
+ CX = 182322083224642863,
+ {CX, CX} = {CX0, CX},
+ V0 = rand:mwc59_value32(CX0),
+ V = 2905950767,
+ {V, V} = {V0, V},
+ W0 = rand:mwc59_value(CX0),
+ W = 269866568368142303,
+ {W, W} = {W0, W},
+ F0 = rand:mwc59_float(CX0),
+ F = (W band ((1 bsl 53)-1)) * (1 / (1 bsl 53)),
+ {F, F} = {F0, F},
+ ok;
+mwc59_api(CX, N)
+ when is_integer(CX), 1 =< CX, CX < (16#7fa6502 bsl 32) - 1 ->
+ V = rand:mwc59_value32(CX),
+ W = rand:mwc59_value(CX),
+ F = rand:mwc59_float(CX),
+ true = 0 =< V,
+ true = V < 1 bsl 32,
+ true = 0 =< W,
+ true = W < 1 bsl 59,
+ true = 0.0 =< F,
+ true = F < 1.0,
+ mwc59_api(rand:mwc59(CX), N - 1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Verify exsp_next behaviour
+%%
+exsp_next_api(Config) when is_list(Config) ->
+ {_, AlgState} = State = rand:seed_s(exsp, 87654321),
+ exsp_next_api(State, AlgState, 1000000).
+
+exsp_next_api(_State, _AlgState, 0) ->
+ ok;
+exsp_next_api(State, AlgState, N) ->
+ {X, NewState} = rand:uniform_s(1 bsl 58, State),
+ {Y, NewAlgState} = rand:exsp_next(AlgState),
+ Y1 = Y + 1,
+ {X, X, N} = {Y1, X, N},
+ exsp_next_api(NewState, NewAlgState, N - 1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Verify exsp_jump behaviour
+%%
+exsp_jump_api(Config) when is_list(Config) ->
+ {_, AlgState} = State = rand:seed_s(exsp, 12345678),
+ exsp_jump_api(State, AlgState, 10000).
+
+exsp_jump_api(_State, _AlgState, 0) ->
+ ok;
+exsp_jump_api(State, AlgState, N) ->
+ {X, NewState} = rand:uniform_s(1 bsl 58, State),
+ {Y, NewAlgState} = rand:exsp_next(AlgState),
+ Y1 = Y + 1,
+ {X, X, N} = {Y1, X, N},
+ exsp_jump_api(
+ rand:jump(NewState),
+ rand:exsp_jump(NewAlgState),
+ N - 1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Verify splitmix64_next behaviour
+%%
+splitmix64_next_api(Config) when is_list(Config) ->
+ splitmix64_next_api(55555555, 100000, 0).
+
+splitmix64_next_api(_State, 0, X) ->
+ X0 = 13069087632117122295,
+ {X0, X0} = {X, X0},
+ ok;
+splitmix64_next_api(AlgState, N, X)
+ when is_integer(X), 0 =< X, X < 1 bsl 64 ->
+ {X1, NewAlgState} = rand:splitmix64_next(AlgState),
+ splitmix64_next_api(NewAlgState, N - 1, X1).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
%% Check that uniform/1 returns values within the proper interval.
interval_int(Config) when is_list(Config) ->
Algs = [default|algs()],
@@ -350,21 +453,35 @@ gen(_, _, _, Acc) -> lists:reverse(Acc).
basic_stats_uniform_1(Config) when is_list(Config) ->
ct:timetrap({minutes,15}), %% valgrind needs a lot of time
- [basic_uniform_1(?LOOP, rand:seed_s(Alg), 0.0, array:new([{default, 0}]))
- || Alg <- [default|algs()]],
+ Result =
+ lists:filter(
+ fun (R) -> R =/= [] end,
+ [basic_uniform_1(Alg, ?LOOP, 100)
+ || Alg <- [default|algs()]]),
+ Result =:= [] orelse
+ ct:fail(Result),
ok.
basic_stats_uniform_2(Config) when is_list(Config) ->
ct:timetrap({minutes,15}), %% valgrind needs a lot of time
- [basic_uniform_2(?LOOP, rand:seed_s(Alg), 0, array:new([{default, 0}]))
- || Alg <- [default|algs()]],
+ Result =
+ lists:filter(
+ fun (R) -> R =/= [] end,
+ [basic_uniform_2(Alg, ?LOOP, 100)
+ || Alg <- [default|algs()]]),
+ Result =:= [] orelse
+ ct:fail(Result),
ok.
basic_stats_bytes(Config) when is_list(Config) ->
ct:timetrap({minutes,15}), %% valgrind needs a lot of time
- [basic_bytes(
- ?LOOP div 100, rand:seed_s(Alg), 0, array:new(256, [{default, 0}]))
- || Alg <- [default|algs()]],
+ Result =
+ lists:filter(
+ fun (R) -> R =/= [] end,
+ [basic_bytes(Alg, ?LOOP div 100, 113)
+ || Alg <- [default|algs()]]),
+ Result =:= [] orelse
+ ct:fail(Result),
ok.
basic_stats_standard_normal(Config) when is_list(Config) ->
@@ -372,9 +489,14 @@ basic_stats_standard_normal(Config) when is_list(Config) ->
io:format("Testing standard normal~n",[]),
IntendedMean = 0,
IntendedVariance = 1,
- [basic_normal_1(?LOOP, IntendedMean, IntendedVariance,
- rand:seed_s(Alg), 0, 0)
- || Alg <- [default|algs()]],
+ Result =
+ lists:filter(
+ fun (R) -> R =/= [] end,
+ [basic_normal_1(?LOOP, IntendedMean, IntendedVariance,
+ rand:seed_s(Alg), 0, 0)
+ || Alg <- [default|algs()]]),
+ Result =:= [] orelse
+ ct:fail(Result),
ok.
basic_stats_normal(Config) when is_list(Config) ->
@@ -385,20 +507,32 @@ basic_stats_normal(Config) when is_list(Config) ->
[{Mean, Variance} || Mean <- IntendedMeans,
Variance <- IntendedVariances],
- ct:timetrap({minutes, 6 * length(IntendedMeanVariancePairs)}), %% valgrind needs a lot of time
- lists:foreach(
- fun ({IntendedMean, IntendedVariance}) ->
- ct:pal(
- "Testing normal(~.2f, ~.2f)~n",
- [float(IntendedMean), float(IntendedVariance)]),
- [basic_normal_1(?LOOP, IntendedMean, IntendedVariance,
- rand:seed_s(Alg), 0, 0)
- || Alg <- [default|algs()]]
- end,
- IntendedMeanVariancePairs).
-
-
-basic_uniform_1(N, S0, Sum, A0) when N > 0 ->
+ %% valgrind needs a lot of time
+ ct:timetrap({minutes, 6 * length(IntendedMeanVariancePairs)}),
+ Result =
+ lists:filter(
+ fun (R) -> R =/= [] end,
+ [begin
+ ct:pal(
+ "Testing normal(~.2f, ~.2f)~n",
+ [float(IntendedMean), float(IntendedVariance)]),
+ lists:filter(
+ fun (R) -> R =/= [] end,
+ [basic_normal_1(?LOOP, IntendedMean, IntendedVariance,
+ rand:seed_s(Alg), 0, 0)
+ || Alg <- [default|algs()]])
+ end || {IntendedMean, IntendedVariance}
+ <- IntendedMeanVariancePairs]),
+ Result =:= [] orelse
+ ct:fail(Result),
+ ok.
+
+basic_uniform_1(Alg, Loop, Buckets) ->
+ basic_uniform_1(
+ 0, Loop, Buckets, rand:seed_s(Alg), 0.0,
+ array:new(Buckets, [{default, 0}])).
+%%
+basic_uniform_1(N, Loop, Buckets, S0, Sum, A0) when N < Loop ->
{X,S} =
case N band 1 of
0 ->
@@ -406,45 +540,41 @@ basic_uniform_1(N, S0, Sum, A0) when N > 0 ->
1 ->
rand:uniform_real_s(S0)
end,
- I = trunc(X*100),
+ I = trunc(X*Buckets),
A = array:set(I, 1+array:get(I,A0), A0),
- basic_uniform_1(N-1, S, Sum+X, A);
-basic_uniform_1(0, {#{type:=Alg}, _}, Sum, A) ->
- Loop = ?LOOP,
+ basic_uniform_1(N+1, Loop, Buckets, S, Sum+X, A);
+basic_uniform_1(_N, Loop, Buckets, {#{type:=Alg}, _}, Sum, A) ->
AverExp = 1.0 / 2,
- Buckets = 100,
Counters = array:to_list(A),
- Min = lists:min(Counters),
- Max = lists:max(Counters),
- basic_verify(Alg, Loop, Sum, AverExp, Buckets, Min, Max).
+ basic_verify(Alg, Loop, Sum, AverExp, Buckets, Counters).
-basic_uniform_2(N, S0, Sum, A0) when N > 0 ->
- {X,S} = rand:uniform_s(100, S0),
+basic_uniform_2(Alg, Loop, Buckets) ->
+ basic_uniform_2(
+ 0, Loop, Buckets, rand:seed_s(Alg), 0,
+ array:new(Buckets, [ {default, 0}])).
+%%
+basic_uniform_2(N, Loop, Buckets, S0, Sum, A0) when N < Loop ->
+ {X,S} = rand:uniform_s(Buckets, S0),
A = array:set(X-1, 1+array:get(X-1,A0), A0),
- basic_uniform_2(N-1, S, Sum+X, A);
-basic_uniform_2(0, {#{type:=Alg}, _}, Sum, A) ->
- Loop = ?LOOP,
- AverExp = ((100 - 1) / 2) + 1,
- Buckets = 100,
+ basic_uniform_2(N+1, Loop, Buckets, S, Sum+X, A);
+basic_uniform_2(_N, Loop, Buckets, {#{type:=Alg}, _}, Sum, A) ->
+ AverExp = ((Buckets - 1) / 2) + 1,
Counters = tl(array:to_list(A)),
- Min = lists:min(Counters),
- Max = lists:max(Counters),
- basic_verify(Alg, Loop, Sum, AverExp, Buckets, Min, Max).
-
-basic_bytes(N, S0, Sum0, A0) when N > 0 ->
- ByteSize = 100,
- {Bin,S} = rand:bytes_s(ByteSize, S0),
+ basic_verify(Alg, Loop, Sum, AverExp, Buckets, Counters).
+
+basic_bytes(Alg, Loop, BytesSize) ->
+ basic_bytes(
+ 0, Loop, BytesSize, rand:seed_s(Alg), 0,
+ array:new(256, [{default, 0}])).
+basic_bytes(N, Loop, BytesSize, S0, Sum0, A0) when N < Loop ->
+ {Bin,S} = rand:bytes_s(BytesSize, S0),
{Sum,A} = basic_bytes_incr(Bin, Sum0, A0),
- basic_bytes(N-1, S, Sum, A);
-basic_bytes(0, {#{type:=Alg}, _}, Sum, A) ->
- ByteSize = 100,
- Loop = (?LOOP * ByteSize) div 100,
+ basic_bytes(N+1, Loop, BytesSize, S, Sum, A);
+basic_bytes(_N, Loop, BytesSize, {#{type:=Alg}, _}, Sum, A) ->
Buckets = 256,
AverExp = (Buckets - 1) / 2,
Counters = array:to_list(A),
- Min = lists:min(Counters),
- Max = lists:max(Counters),
- basic_verify(Alg, Loop, Sum, AverExp, Buckets, Min, Max).
+ basic_verify(Alg, Loop * BytesSize, Sum, AverExp, Buckets, Counters).
basic_bytes_incr(Bin, Sum, A) ->
basic_bytes_incr(Bin, Sum, A, 0).
@@ -458,7 +588,7 @@ basic_bytes_incr(Bin, Sum, A, N) ->
{Sum,A}
end.
-basic_verify(Alg, Loop, Sum, AverExp, Buckets, Min, Max) ->
+basic_verify(Alg, Loop, Sum, AverExp, Buckets, Counters) ->
AverDiff = AverExp * 0.01,
Aver = Sum / Loop,
io:format(
@@ -467,19 +597,39 @@ basic_verify(Alg, Loop, Sum, AverExp, Buckets, Min, Max) ->
%%
CountExp = Loop / Buckets,
CountDiff = CountExp * 0.1,
+ {MinBucket, Min} = lists_where(fun erlang:min/2, Counters),
+ {MaxBucket, Max} = lists_where(fun erlang:max/2, Counters),
io:format(
"~.12w: Expected Count: ~p, Allowed Diff: ~p, Min: ~p, Max: ~p~n",
[Alg, CountExp, CountDiff, Min, Max]),
%%
%% Verify that the basic statistics are ok
- %% be gentle we don't want to see to many failing tests
- abs(Aver - AverExp) < AverDiff orelse
- ct:fail({average, Alg, Aver, AverExp, AverDiff}),
- abs(Min - CountExp) < CountDiff orelse
- ct:fail({min, Alg, Min, CountExp, CountDiff}),
- abs(Max - CountExp) < CountDiff orelse
- ct:fail({max, Alg, Max, CountExp, CountDiff}),
- ok.
+ %% be gentle - we don't want to see to many failing tests
+ if
+ abs(Aver - AverExp) < AverDiff -> [];
+ true -> [{average, Alg, Aver, AverExp, AverDiff}]
+ end ++
+ if
+ abs(Min - CountExp) < CountDiff -> [];
+ true -> [{min, Alg, {MinBucket,Min}, CountExp, CountDiff}]
+ end ++
+ if
+ abs(Max - CountExp) < CountDiff -> [];
+ true -> [{max, Alg, {MaxBucket,Max}, CountExp, CountDiff}]
+ end.
+
+lists_where(Fun, [X | L]) ->
+ lists_where(Fun, L, 2, 1, X).
+%%
+lists_where(_Fun, [], _N, Where, What) ->
+ {Where, What};
+lists_where(Fun, [X | L], N, Where, What) ->
+ case Fun(X, What) of
+ What ->
+ lists_where(Fun, L, N+1, Where, What);
+ X ->
+ lists_where(Fun, L, N+1, N, X)
+ end.
basic_normal_1(N, IntendedMean, IntendedVariance, S0, StandardSum, StandardSq) when N > 0 ->
@@ -491,7 +641,7 @@ basic_normal_1(N, IntendedMean, IntendedVariance, S0, StandardSum, StandardSq) w
StandardX = (X - IntendedMean) / math:sqrt(IntendedVariance),
basic_normal_1(N-1, IntendedMean, IntendedVariance, S,
StandardX+StandardSum, StandardX*StandardX+StandardSq);
-basic_normal_1(0, _IntendedMean, _IntendedVariance, {#{type:=Alg}, _}, StandardSum, StandardSumSq) ->
+basic_normal_1(0, IntendedMean, IntendedVariance, {#{type:=Alg}, _}, StandardSum, StandardSumSq) ->
StandardMean = StandardSum / ?LOOP,
StandardVariance = (StandardSumSq - (StandardSum*StandardSum/?LOOP))/(?LOOP - 1),
StandardStdDev = math:sqrt(StandardVariance),
@@ -500,9 +650,16 @@ basic_normal_1(0, _IntendedMean, _IntendedVariance, {#{type:=Alg}, _}, StandardS
%%
%% Verify that the basic statistics are ok
%% be gentle we don't want to see to many failing tests
- abs(StandardMean) < 0.005 orelse ct:fail({average, Alg, StandardMean}),
- abs(StandardStdDev - 1.0) < 0.005 orelse ct:fail({stddev, Alg, StandardStdDev}),
- ok.
+ if
+ abs(StandardMean) < 0.005 -> [];
+ true ->
+ [{average, Alg, StandardMean, IntendedMean, IntendedVariance}]
+ end ++
+ if
+ abs(StandardStdDev - 1.0) < 0.005 -> [];
+ true ->
+ [{stddev, Alg, StandardStdDev, IntendedMean, IntendedVariance}]
+ end.
normal_s(Mean, Variance, State0) when Mean == 0, Variance == 1 ->
% Make sure we're also testing the standard normal interface
@@ -904,14 +1061,19 @@ crypto64_uniform_n(N, State0) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Not a test but measures the time characteristics of the different algorithms
-measure(Config) ->
+measure(Config) when is_list(Config) ->
ct:timetrap({minutes,60}), %% valgrind needs a lot of time
case ct:get_timetrap_info() of
{_,{_,1}} -> % No scaling
- do_measure(Config);
+ Effort = proplists:get_value(measure_effort, Config, 1),
+ measure(Effort);
{_,{_,Scale}} ->
{skip,{will_not_run_in_scaled_time,Scale}}
- end.
+ end;
+measure(Effort) when is_integer(Effort) ->
+ Iterations = ?LOOP div 5,
+ do_measure(Iterations * Effort).
+
-define(CHECK_UNIFORM_RANGE(Gen, Range, X, St),
case (Gen) of
@@ -939,7 +1101,7 @@ measure(Config) ->
St
end).
-do_measure(_Config) ->
+do_measure(Iterations) ->
Algs =
case crypto_support() of
ok ->
@@ -949,218 +1111,607 @@ do_measure(_Config) ->
end,
%%
ct:pal("~nRNG uniform integer range 10000 performance~n",[]),
+ [TMarkUniformRange10000,OverheadUniformRange1000|_] =
+ measure_1(
+ fun (Mod, _State) ->
+ Range = 10000,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
_ =
measure_1(
- fun (_) -> 10000 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ %% Just a 'rem' with slightly skewed distribution
+ case (St1 rem Range) + 1 of
+ R when is_integer(R), 0 < R, R =< Range ->
+ St1
+ end
+ end
end,
- Algs),
+ {mwc59,raw_mod}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ %% Just a 'rem' with slightly skewed distribution
+ case (rand:mwc59_value(St1) rem Range) + 1 of
+ R when is_integer(R), 0 < R, R =< Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,value_mod}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ {V,St1} = rand:exsp_next(St0),
+ %% Just a 'rem' with slightly skewed distribution
+ case (V rem Range) + 1 of
+ X when is_integer(X), 0 < X, X =< Range ->
+ St1
+ end
+ end
+ end,
+ {exsp,mod}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ %% Truncated multiplication, slightly skewed
+ case
+ ((Range * (St1 band ((1 bsl 16)-1))) bsr 16)
+ + 1
+ of
+ R when is_integer(R), 0 < R, R =< Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,raw_tm}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ %% Truncated multiplication, slightly skewed
+ case
+ ((Range * rand:mwc59_value32(St1)) bsr 32)
+ + 1
+ of
+ R when is_integer(R), 0 < R, R =< Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,value32_tm}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000, % 14 bits
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ %% Truncated multiplication, slightly skewed
+ case
+ ( (Range *
+ (rand:mwc59_value(St1) bsr 14) )
+ bsr (59-14) )
+ + 1
+ of
+ R when is_integer(R), 0 < R, R =< Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,value_tm}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ {V,St1} = rand:exsp_next(St0),
+ %% Truncated multiplication, slightly skewed
+ case
+ ((Range * (V bsr 14)) bsr (58-14)) + 1
+ of
+ X when is_integer(X), 0 < X, X =< Range ->
+ St1
+ end
+ end
+ end,
+ {exsp,tm}, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ %% Just a 'rem' with slightly skewed distribution
+ case
+ erlang:phash2(erlang:unique_integer(), Range)
+ of
+ X when is_integer(X), 0 =< X, X < Range ->
+ St0
+ end
+ end
+ end,
+ unique_phash2, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 10000,
+ fun (St0) ->
+ %% Just a 'rem' with slightly skewed distribution
+ case os:system_time(microsecond) rem Range of
+ R
+ when is_integer(R), 0 =< R, R < Range ->
+ St0
+ end
+ end
+ end,
+ system_time, Iterations,
+ TMarkUniformRange10000, OverheadUniformRange1000),
%%
ct:pal("~nRNG uniform integer 32 bit performance~n",[]),
+ [TMarkUniform32Bit,OverheadUniform32Bit|_] =
+ measure_1(
+ fun (Mod, _State) ->
+ Range = 1 bsl 32,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end,
+ Algs, Iterations),
_ =
measure_1(
- fun (_) -> 1 bsl 32 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ case St1 band ((1 bsl 32)-1) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St1
+ end
+ end
end,
- Algs),
+ {mwc59,raw_mask}, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ case rand:mwc59_value32(St1) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,value32}, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ case rand:mwc59_value(St1) bsr (59-32) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,value_shift}, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ {V, St1} = rand:exsp_next(St0),
+ case V bsr (58-32) of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St1
+ end
+ end
+ end,
+ {exsp,shift}, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ case
+ erlang:phash2(erlang:unique_integer(), Range)
+ of
+ R
+ when is_integer(R), 0 =< R, R < Range ->
+ St0
+ end
+ end
+ end,
+ unique_phash2, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 32,
+ fun (St0) ->
+ case
+ os:system_time(microsecond)
+ band ((1 bsl 32) - 1)
+ of
+ R when is_integer(R), 0 =< R, R < Range ->
+ St0
+ end
+ end
+ end,
+ system_time, Iterations,
+ TMarkUniform32Bit, OverheadUniform32Bit),
%%
ct:pal("~nRNG uniform integer half range performance~n",[]),
_ =
measure_1(
- fun (State) -> half_range(State) end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (Mod, State) ->
+ Range = half_range(State),
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
end,
- Algs),
+ Algs, Iterations),
%%
ct:pal("~nRNG uniform integer half range + 1 performance~n",[]),
_ =
measure_1(
- fun (State) -> half_range(State) + 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = half_range(State) + 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer full range - 1 performance~n",[]),
_ =
measure_1(
- fun (State) -> (half_range(State) bsl 1) - 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = (half_range(State) bsl 1) - 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer full range performance~n",[]),
+ [TMarkUniformFullRange,OverheadUniformFullRange|_] =
+ measure_1(
+ fun (Mod, State) ->
+ Range = half_range(State) bsl 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs ++ [dummy], Iterations),
_ =
measure_1(
- fun (State) -> half_range(State) bsl 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = (16#7fa6502 bsl 32) - 1,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ V = St1,
+ if
+ is_integer(V), 1 =< V, V < Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,raw}, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = (1 bsl 32) - 1,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ V = rand:mwc59_value32(St1),
+ if
+ is_integer(V), 0 =< V, V =< Range ->
+ St1
+ end
+ end
end,
- Algs),
+ {mwc59,value32}, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = (1 bsl 59) - 1,
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ V = rand:mwc59_value(St1),
+ if
+ is_integer(V), 0 =< V, V =< Range ->
+ St1
+ end
+ end
+ end,
+ {mwc59,value}, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 58,
+ fun (St0) ->
+ {V, St1} = rand:exsp_next(St0),
+ if
+ is_integer(V), 0 =< V, V < Range ->
+ St1
+ end
+ end
+ end,
+ {exsp,next}, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 64,
+ fun (St0) ->
+ {V, St1} = rand:splitmix64_next(St0),
+ if
+ is_integer(V), 0 =< V, V < Range ->
+ St1
+ end
+ end
+ end,
+ {splitmix64,next}, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1 bsl 27,
+ fun (St0) ->
+ case erlang:phash2(erlang:unique_integer()) of
+ X
+ when is_integer(X), 0 =< X, X < Range ->
+ St0
+ end
+ end
+ end,
+ unique_phash2, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (Mod, _State) ->
+ Range = 1 bsl 27,
+ Generator = fun Mod:uniform/1,
+ fun (St0) ->
+ case Generator(Range) of
+ X when is_integer(X), 1 =< X, X =< Range ->
+ St0
+ end
+ end
+ end,
+ procdict, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = (16#7fa6502 bsl 32) - 1,
+ fun (St0) ->
+ case
+ put(mwc59_procdict,
+ rand:mwc59(get(mwc59_procdict)))
+ of
+ X when is_integer(X), 0 =< X, X < Range ->
+ St0
+ end
+ end
+ end,
+ {mwc59,procdict}, Iterations,
+ TMarkUniformFullRange, OverheadUniformFullRange),
%%
ct:pal("~nRNG uniform integer full range + 1 performance~n",[]),
_ =
measure_1(
- fun (State) -> (half_range(State) bsl 1) + 1 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = (half_range(State) bsl 1) + 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer double range performance~n",[]),
_ =
measure_1(
- fun (State) ->
- half_range(State) bsl 2
- end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = half_range(State) bsl 2,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer double range + 1 performance~n",[]),
_ =
measure_1(
- fun (State) ->
- (half_range(State) bsl 2) + 1
- end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
- end,
- Algs),
+ fun (Mod, State) ->
+ Range = (half_range(State) bsl 2) + 1,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
%%
ct:pal("~nRNG uniform integer 64 bit performance~n",[]),
+ [TMarkUniform64Bit, OverheadUniform64Bit | _] =
+ measure_1(
+ fun (Mod, _State) ->
+ Range = 1 bsl 64,
+ Generator = fun Mod:uniform_s/2,
+ fun (St0) ->
+ ?CHECK_UNIFORM_RANGE(
+ Generator(Range, St0), Range, X, St1)
+ end
+ end, Algs, Iterations),
_ =
measure_1(
- fun (_) -> 1 bsl 64 end,
- fun (State, Range, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM_RANGE(
- Mod:uniform_s(Range, St0), Range,
- X, St1)
- end,
- State)
+ fun (_Mod, _State) ->
+ Range = 1 bsl 64,
+ fun (St0) ->
+ {V, St1} = rand:splitmix64_next(St0),
+ if
+ is_integer(V), 0 =< V, V < Range ->
+ St1
+ end
+ end
end,
- Algs),
+ {splitmix64,next}, Iterations,
+ TMarkUniform64Bit, OverheadUniform64Bit),
%%
ByteSize = 16, % At about 100 bytes crypto_bytes breaks even to exsss
ct:pal("~nRNG ~w bytes performance~n",[ByteSize]),
+ [TMarkBytes1,OverheadBytes1|_] =
+ measure_1(
+ fun (Mod, _State) ->
+ Generator = fun Mod:bytes_s/2,
+ fun (St0) ->
+ ?CHECK_BYTE_SIZE(
+ Generator(ByteSize, St0), ByteSize, Bin, St1)
+ end
+ end,
+ case crypto_support() of
+ ok ->
+ Algs ++ [crypto_bytes, crypto_bytes_cached];
+ _ ->
+ Algs
+ end, Iterations),
_ =
measure_1(
- fun (_) -> ByteSize end,
- fun (State, Size, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_BYTE_SIZE(
- Mod:bytes_s(Size, St0), Size,
- Bin, St1)
- end,
- State)
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ ?CHECK_BYTE_SIZE(
+ mwc59_bytes(ByteSize, St0), ByteSize, Bin, St1)
+ end
+ end, {mwc59,bytes}, Iterations,
+ TMarkBytes1, OverheadBytes1),
+ %%
+ ByteSize2 = 1000, % At about 100 bytes crypto_bytes breaks even to exsss
+ ct:pal("~nRNG ~w bytes performance~n",[ByteSize2]),
+ [TMarkBytes2,OverheadBytes2|_] =
+ measure_1(
+ fun (Mod, _State) ->
+ Generator = fun Mod:bytes_s/2,
+ fun (St0) ->
+ ?CHECK_BYTE_SIZE(
+ Generator(ByteSize2, St0), ByteSize2, Bin, St1)
+ end
end,
case crypto_support() of
ok ->
Algs ++ [crypto_bytes, crypto_bytes_cached];
_ ->
Algs
- end),
+ end, Iterations div 50),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ ?CHECK_BYTE_SIZE(
+ mwc59_bytes(ByteSize2, St0), ByteSize2, Bin, St1)
+ end
+ end, {mwc59,bytes}, Iterations div 50,
+ TMarkBytes2, OverheadBytes2),
%%
ct:pal("~nRNG uniform float performance~n",[]),
+ [TMarkUniformFloat,OverheadUniformFloat|_] =
+ measure_1(
+ fun (Mod, _State) ->
+ Generator = fun Mod:uniform_s/1,
+ fun (St0) ->
+ ?CHECK_UNIFORM(Generator(St0), X, St)
+ end
+ end,
+ Algs, Iterations),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM(Mod:uniform_s(St0), X, St)
- end,
- State)
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ St1 = rand:mwc59(St0),
+ case rand:mwc59_float(St1) of
+ R when is_float(R), 0.0 =< R, R < 1.0 ->
+ St1
+ end
+ end
+ end,
+ {mwc59,float}, Iterations,
+ TMarkUniformFloat, OverheadUniformFloat),
+ _ =
+ measure_1(
+ fun (_Mod, _State) ->
+ fun (St0) ->
+ {V,St1} = rand:exsp_next(St0),
+ case V * (1/(1 bsl 58)) of
+ R when is_float(R), 0.0 =< R, R < 1.0 ->
+ St1
+ end
+ end
end,
- Algs),
+ {exsp,float}, Iterations,
+ TMarkUniformFloat, OverheadUniformFloat),
%%
ct:pal("~nRNG uniform_real float performance~n",[]),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_UNIFORM(Mod:uniform_real_s(St0), X, St)
- end,
- State)
+ fun (Mod, _State) ->
+ Generator = fun Mod:uniform_real_s/1,
+ fun (St0) ->
+ ?CHECK_UNIFORM(Generator(St0), X, St)
+ end
end,
- Algs),
+ Algs, Iterations),
%%
ct:pal("~nRNG normal float performance~n",[]),
- [TMarkNormalFloat|_] =
+ [TMarkNormalFloat, OverheadNormalFloat|_] =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (St0) ->
- ?CHECK_NORMAL(Mod:normal_s(St0), X, St1)
- end,
- State)
+ fun (Mod, _State) ->
+ Generator = fun Mod:normal_s/1,
+ fun (St0) ->
+ ?CHECK_NORMAL(Generator(St0), X, St1)
+ end
end,
- Algs),
+ Algs, Iterations),
%% Just for fun try an implementation of the Box-Muller
%% transformation for creating normal distribution floats
%% to compare with our Ziggurat implementation.
@@ -1170,81 +1721,121 @@ do_measure(_Config) ->
TwoPi = 2 * math:pi(),
_ =
measure_1(
- fun (_) -> 0 end,
- fun (State, _, Mod) ->
- measure_loop(
- fun (State0) ->
- {U1, State1} = Mod:uniform_real_s(State0),
- {U2, State2} = Mod:uniform_s(State1),
- R = math:sqrt(-2.0 * math:log(U1)),
- T = TwoPi * U2,
- Z0 = R * math:cos(T),
- Z1 = R * math:sin(T),
- ?CHECK_NORMAL({Z0 + Z1, State2}, X, State3)
- end,
- State)
+ fun (Mod, _State) ->
+ fun (St0) ->
+ {U1, St1} = Mod:uniform_real_s(St0),
+ {U2, St2} = Mod:uniform_s(St1),
+ R = math:sqrt(-2.0 * math:log(U1)),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ ?CHECK_NORMAL({Z0 + Z1, St2}, X, St3)
+ end
end,
- exsss, TMarkNormalFloat),
+ exsss, Iterations,
+ TMarkNormalFloat, OverheadNormalFloat),
ok.
--define(LOOP_MEASURE, (?LOOP div 5)).
-
-measure_loop(Fun, State) ->
- measure_loop(Fun, State, ?LOOP_MEASURE).
-%%
-measure_loop(Fun, State, N) when 0 < N ->
- measure_loop(Fun, Fun(State), N-1);
+measure_loop(State, Fun, I) when 10 =< I ->
+ %% Loop unrolling to dilute benchmark overhead...
+ measure_loop(
+ Fun(Fun(Fun(Fun(Fun( Fun(Fun(Fun(Fun(Fun(State))))) ))))),
+ Fun, I - 10);
+measure_loop(State, Fun, I) when 1 =< I ->
+ measure_loop(Fun(State), Fun, I - 1);
measure_loop(_, _, _) ->
ok.
-measure_1(RangeFun, Fun, Algs) ->
- TMark = measure_1(RangeFun, Fun, hd(Algs), undefined),
- [TMark] ++
- [measure_1(RangeFun, Fun, Alg, TMark) || Alg <- tl(Algs)].
-
-measure_1(RangeFun, Fun, Alg, TMark) ->
+measure_1(InitFun, Algs, Iterations) ->
+ WMark = measure_1(InitFun, hd(Algs), Iterations, warm_up, 0),
+ Overhead =
+ measure_1(
+ fun (_Mod, _State) ->
+ Range = 1,
+ fun (St0)
+ when is_integer(St0), 1 =< St0, St0 =< Range ->
+ St0
+ end
+ end, overhead, Iterations, WMark, 0),
+ TMark = measure_1(InitFun, hd(Algs), Iterations, undefined, Overhead),
+ [TMark,Overhead] ++
+ [measure_1(InitFun, Alg, Iterations, TMark, Overhead)
+ || Alg <- tl(Algs)].
+
+measure_1(InitFun, Alg, Iterations, TMark, Overhead) ->
Parent = self(),
- {Mod, State} =
- case Alg of
- crypto64 ->
- {rand, crypto64_seed()};
- crypto_cache ->
- {rand, crypto:rand_seed_alg(crypto_cache)};
- crypto ->
- {rand, crypto:rand_seed_s()};
- crypto_aes ->
- {rand,
- crypto:rand_seed_alg(
- crypto_aes, crypto:strong_rand_bytes(256))};
- random ->
- {random, random:seed(os:timestamp()), get(random_seed)};
- crypto_bytes ->
- {?MODULE, ignored_state};
- crypto_bytes_cached ->
- {?MODULE, <<>>};
- _ ->
- {rand, rand:seed_s(Alg)}
+ MeasureFun =
+ fun () ->
+ {Mod, State} = measure_init(Alg),
+ IterFun = InitFun(Mod, State),
+ {T, ok} =
+ timer:tc(
+ fun () ->
+ measure_loop(State, IterFun, Iterations)
+ end),
+ Time = T - Overhead,
+ Percent =
+ case TMark of
+ warm_up -> "(warm-up)";
+ undefined -> " 100.0%";
+ _ ->
+ io_lib:format(
+ "~8.1f%", [(Time * 100 + 50) / TMark])
+ end,
+ io:format(
+ "~.24w: ~8.1f ns ~s~n",
+ [Alg, (Time * 1000 + 500) / Iterations, Percent]),
+ Parent ! {self(), Time},
+ ok
end,
- Range = RangeFun(State),
- Pid = spawn_link(
- fun() ->
- {Time, ok} = timer:tc(fun () -> Fun(State, Range, Mod) end),
- Percent =
- case TMark of
- undefined -> 100;
- _ -> (Time * 100 + 50) div TMark
- end,
- io:format(
- "~.20w: ~p ns ~p% [16#~.16b]~n",
- [Alg, (Time * 1000 + 500) div ?LOOP_MEASURE,
- Percent, Range]),
- Parent ! {self(), Time},
- normal
- end),
+ Pid = spawn_link(MeasureFun),
receive
{Pid, Msg} -> Msg
end.
+measure_init(Alg) ->
+ case Alg of
+ overhead ->
+ {?MODULE, 1};
+ crypto64 ->
+ {rand, crypto64_seed()};
+ crypto_cache ->
+ {rand, crypto:rand_seed_alg(crypto_cache)};
+ crypto ->
+ {rand, crypto:rand_seed_s()};
+ crypto_aes ->
+ {rand,
+ crypto:rand_seed_alg(
+ crypto_aes, crypto:strong_rand_bytes(256))};
+ random ->
+ {random, random:seed(os:timestamp()), get(random_seed)};
+ crypto_bytes ->
+ {?MODULE, undefined};
+ crypto_bytes_cached ->
+ {?MODULE, <<>>};
+ unique_phash2 ->
+ {?MODULE, undefined};
+ system_time ->
+ {?MODULE, undefined};
+ procdict ->
+ {rand, rand:seed(exsss)};
+ {Name, Tag} ->
+ case Name of
+ mwc59 when Tag =:= procdict ->
+ _ = put(mwc59_procdict, rand:mwc59_seed()),
+ {rand, undefined};
+ mwc59 ->
+ {rand, rand:mwc59_seed()};
+ exsp ->
+ {_, S} = rand:seed_s(exsp),
+ {rand, S};
+ splitmix64 ->
+ {rand, erlang:unique_integer()}
+ end;
+ _ ->
+ {rand, rand:seed_s(Alg)}
+ end.
+
%% Comparison algorithm for rand:bytes_s/2 vs. crypto:strong_rand_bytes/1
bytes_s(N, Cache) when is_binary(Cache) ->
%% crypto_bytes_cached
@@ -1256,10 +1847,37 @@ bytes_s(N, Cache) when is_binary(Cache) ->
<<Part/binary, (crypto:strong_rand_bytes(N * 16))/binary>>,
{Bytes, Rest}
end;
-bytes_s(N, ignored_state = St) ->
+bytes_s(N, undefined = St) ->
%% crypto_bytes
{crypto:strong_rand_bytes(N), St}.
+mwc59_bytes(N, R0) ->
+ mwc59_bytes(N, R0, <<>>).
+%%
+mwc59_bytes(N, R0, Bin) when is_integer(N), 7*4 =< N ->
+ R1 = rand:mwc59(R0),
+ R2 = rand:mwc59(R1),
+ R3 = rand:mwc59(R2),
+ R4 = rand:mwc59(R3),
+ Shift = 59 - 56,
+ V1 = rand:mwc59_value(R1) bsr Shift,
+ V2 = rand:mwc59_value(R2) bsr Shift,
+ V3 = rand:mwc59_value(R3) bsr Shift,
+ V4 = rand:mwc59_value(R4) bsr Shift,
+ mwc59_bytes(N-7*4, R4, <<Bin/binary, V1:56, V2:56, V3:56, V4:56>>);
+mwc59_bytes(N, R0, Bin) when is_integer(N), 7 =< N ->
+ R1 = rand:mwc59(R0),
+ V = rand:mwc59_value(R1) bsr (59-56),
+ mwc59_bytes(N-7, R1, <<Bin/binary, V:56>>);
+mwc59_bytes(N, R0, Bin) when is_integer(N), 0 < N ->
+ R1 = rand:mwc59(R0),
+ Bits = N bsl 3,
+ V = rand:mwc59_value(R1) bsr (59-Bits),
+ {<<Bin/binary, V:Bits>>, R1};
+mwc59_bytes(0, R0, Bin) ->
+ {Bin, R0}.
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% The jump sequence tests has two parts
%% for those with the functional API (jump/1)
diff --git a/lib/stdlib/test/random_iolist.erl b/lib/stdlib/test/random_iolist.erl
index 6621c7ac77..63a6c7dd03 100644
--- a/lib/stdlib/test/random_iolist.erl
+++ b/lib/stdlib/test/random_iolist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ random_list(N,Acc) ->
random_list(N-1,[random_byte() | Acc]).
random_binary(N) ->
- B = list_to_binary(random_list(N,[])),
+ B = rand:bytes(N),
case {rand:uniform(2),size(B)} of
{2,M} when M > 1 ->
S = M-1,
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index 1c9919c8de..09a65d8fdd 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -162,7 +162,7 @@ run_options(Config) when is_list(Config) ->
{match,["ABCabcdABC","abcd"]} = re:run("ABCabcdABC",MP,[{capture,all,list}]),
{match,[<<"ABCabcdABC">>,<<"abcd">>]} = re:run("ABCabcdABC",MP,[{capture,all,binary}]),
{match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first}]),
- {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first,index}]), ?line {match,["ABCabcdABC"]} = re:run("ABCabcdABC",MP,[{capture,first,list}]),
+ {match,[{0,10}]} = re:run("ABCabcdABC",MP,[{capture,first,index}]), {match,["ABCabcdABC"]} = re:run("ABCabcdABC",MP,[{capture,first,list}]),
{match,[<<"ABCabcdABC">>]} = re:run("ABCabcdABC",MP,[{capture,first,binary}]),
{match,[{3,4}]} = re:run("ABCabcdABC",MP,[{capture,all_but_first}]),
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index 25ea6d02f1..b38dee47e7 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -190,16 +190,15 @@ ok.
%% Check restricted shell when started from the command line.
start_restricted_on_command_line(Config) when is_list(Config) ->
- {ok,Node} = start_node(shell_suite_helper_1,
- "-pa "++proplists:get_value(priv_dir,Config)++
- " -stdlib restricted_shell foo"),
+ {ok, Peer, Node} = ?CT_PEER(["-pa", proplists:get_value(priv_dir,Config),
+ "-stdlib", "restricted_shell", "foo"]),
"Warning! Restricted shell module foo not found: nofile"++_ =
t({Node, <<"begin m() end.">>}),
"exception exit: restricted shell does not allow m()" =
comm_err({Node, <<"begin m() end.">>}),
[ok] =
(catch scan({Node, <<"begin q() end.">>})),
- test_server:stop_node(Node),
+ peer:stop(Peer),
Test = filename:join(proplists:get_value(priv_dir, Config),
"test_restricted2.erl"),
Contents = <<"-module(test_restricted2).
@@ -217,9 +216,8 @@ start_restricted_on_command_line(Config) when is_list(Config) ->
{false,State}.
">>,
ok = compile_file(Config, Test, Contents, []),
- {ok,Node2} = start_node(shell_suite_helper_2,
- "-pa "++proplists:get_value(priv_dir,Config)++
- " -stdlib restricted_shell test_restricted2"),
+ {ok, Peer2, Node2} = ?CT_PEER(["-pa", proplists:get_value(priv_dir,Config),
+ "-stdlib", "restricted_shell", "test_restricted2"]),
"Module" ++ _ = t({Node2,<<"begin m() end.">>, utf8}),
"exception exit: restricted shell does not allow c(foo)" =
comm_err({Node2,<<"begin c(foo) end.">>}),
@@ -235,7 +233,7 @@ start_restricted_on_command_line(Config) when is_list(Config) ->
comm_err({Node2,<<"begin shell:stop_restricted() end.">>}),
[ok] =
scan({Node2, <<"begin q() end.">>}),
- test_server:stop_node(Node2),
+ peer:stop(Peer2),
ok.
%% Tests calling local shell functions with spectacular arguments in
@@ -258,6 +256,8 @@ restricted_local(Config) when is_list(Config) ->
local_allowed(_,_,State) ->
{false,State}.
+ non_local_allowed({erlang,raise},[error, _, _],State) ->
+ {true,State};
non_local_allowed({shell,stop_restricted},[],State) ->
{true,State};
non_local_allowed(_,_,State) ->
@@ -590,11 +590,11 @@ otp_5327(Config) when is_list(Config) ->
default,default}]}),
[<<"abc">>] = scan(<<"<<(<<\"abc\">>):3/binary>>.">>),
[<<"abc">>] = scan(<<"<<(<<\"abc\">>)/binary>>.">>),
- "exception error: bad argument" =
+ "exception error: construction of binary failed" =
comm_err(<<"<<(<<\"abc\">>):4/binary>>.">>),
true = byte_size(hd(scan("<<3.14:64/float>>."))) =:= 8,
true = byte_size(hd(scan("<<3.14:32/float>>."))) =:= 4,
- "exception error: bad argument" =
+ "exception error: construction of binary failed" =
comm_err(<<"<<3.14:128/float>>.">>),
"exception error: bad argument" =
comm_err(<<"<<10:default>>.">>),
@@ -661,15 +661,11 @@ otp_5435(Config) when is_list(Config) ->
true = <<103133.0:64/float>> =:=
evaluate(<<"<<103133.0:64/float>> = <<103133:64/float>>.">>, []),
true = is_alive(),
- {ok, Node} = start_node(shell_SUITE_otp_5435),
+ {ok, Peer, Node} = ?CT_PEER(),
ok = rpc:call(Node, ?MODULE, otp_5435_2, []),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
-start_node(Name) ->
- PA = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, slave, [{args, "-pa " ++ PA}]).
-
otp_5435_2() ->
true = code:del_path(compiler),
%% Make sure record evaluation is not dependent on the compiler
@@ -701,7 +697,7 @@ otp_5195(Config) when is_list(Config) ->
{'EXIT',{undef,_}} = (catch evaluate(Ugly, [])),
V_1 = <<"qlc:e(qlc:q([X || X <- qlc:append([[1,2,3],v(-1)])])).">>,
- "- 1: command not found" = comm_err(V_1),
+ "-1: command not found" = comm_err(V_1),
{'EXIT', {undef,_}} = (catch evaluate(V_1, [])),
"1\n2\n3\n3.\n" =
@@ -2750,9 +2746,8 @@ prompt_err(B) ->
%% OTP-10302. Unicode. Also OTP-14285, Unicode atoms.
otp_10302(Config) when is_list(Config) ->
- {ok,Node} = start_node(shell_suite_helper_2,
- "-pa "++proplists:get_value(priv_dir,Config)++
- " +pc unicode"),
+ {ok, Peer, Node} = ?CT_PEER(["-pa", proplists:get_value(priv_dir,Config),
+ "+pc", "unicode"]),
Test1 =
<<"begin
io:setopts([{encoding,utf8}]),
@@ -2902,7 +2897,7 @@ otp_10302(Config) when is_list(Config) ->
"ok.\n** exception error: undefined function "
"shell_SUITE:'\x{447}\x{435}'/0.\n" =
t({Node,Test17}),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
otp_13719(Config) when is_list(Config) ->
@@ -2919,9 +2914,8 @@ otp_13719(Config) when is_list(Config) ->
ok.
otp_14285(Config) ->
- {ok,Node} = start_node(shell_suite_helper_4,
- "-pa "++proplists:get_value(priv_dir,Config)++
- " +pc unicode"),
+ {ok, Peer, Node} = ?CT_PEER(["-pa", proplists:get_value(priv_dir,Config),
+ "+pc", "unicode"]),
Test1 =
<<"begin
io:setopts([{encoding,utf8}]),
@@ -2931,7 +2925,7 @@ otp_14285(Config) ->
end.">>,
"-record('\x{400}',{'\x{400}' = '\x{400}'}).\nok.\n" =
t({Node,Test1}),
- test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
otp_14296(Config) when is_list(Config) ->
@@ -3233,11 +3227,6 @@ filename(Name, Config) when is_atom(Name) ->
filename(Name, Config) ->
filename:join(proplists:get_value(priv_dir, Config), Name).
-start_node(Name, Xargs) ->
- N = test_server:start_node(Name, slave, [{args, " " ++ Xargs}]),
- global:sync(),
- N.
-
purge_and_delete(Module) ->
(catch code:purge(Module)),
(catch code:delete(Module)).
diff --git a/lib/stdlib/test/shell_docs_SUITE.erl b/lib/stdlib/test/shell_docs_SUITE.erl
index ba0f256df9..028e2c0aba 100644
--- a/lib/stdlib/test/shell_docs_SUITE.erl
+++ b/lib/stdlib/test/shell_docs_SUITE.erl
@@ -70,7 +70,7 @@ end_per_group(_GroupName, Config) ->
%% tested.
%%
%% Currently the modules are:
--define(RENDER_MODULES, [sofs, re, file, erlang]).
+-define(RENDER_MODULES, [sofs, re, file, erlang, user_drv, ?MODULE]).
%% If you need to update the definition because this
%% testcase fails, just run update_render/0,1.
render(Config) ->
@@ -88,7 +88,12 @@ render(Config) ->
{ok, Original} ->
ct:log("Original: ~n~ts",[Original]),
ct:log("Current : ~n~ts",[Current]),
- ct:fail(output_changed)
+ ct:fail(output_changed);
+ {error, enoent} ->
+ %% All modules are not available on all
+ %% platforms. For instance socket is not
+ %% available on windows.
+ ok
end
end, render_module(Module, D))
end, ?RENDER_MODULES).
@@ -108,7 +113,9 @@ update_render(DataDir) ->
maps:map(
fun(FName, Output) ->
ok = file:write_file(filename:join(DataDir, FName), Output)
- end, render_module(Module, D))
+ end, render_module(Module, D));
+ E ->
+ io:format("Error processing: ~p ~p",[Module, E])
end
end, ?RENDER_MODULES).
@@ -275,8 +282,8 @@ render_all(Dir) ->
docsmap(fun(Mod, D) ->
maps:map(
fun(FName, Value) ->
- file:write_file(filename:join(Dir, FName), Value) end,
- render_module(Mod, D))
+ file:write_file(filename:join(Dir, FName), Value)
+ end, render_module(Mod, D))
end).
render_module(Mod, #docs_v1{ docs = Docs } = D) ->
@@ -315,7 +322,11 @@ render_module(Mod, #docs_v1{ docs = Docs } = D) ->
end, Files, Docs).
sanitize(FName) ->
- re:replace(FName,"[/:]","_",[global,{return,list}]).
+ lists:foldl(
+ fun({Re,Replace}, Txt) ->
+ re:replace(Txt,Re,Replace,[global,{return,list}])
+ end, FName, [{"/","slash"},{":","colon"},
+ {"\\*","star"},{"<","lt"},{">","gt"},{"=","eq"}]).
docsmap(Fun) ->
lists:map(
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/erlang.docs_v1 b/lib/stdlib/test/shell_docs_SUITE_data/erlang.docs_v1
index 71704fff5a..72d7f5f4ef 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/erlang.docs_v1
+++ b/lib/stdlib/test/shell_docs_SUITE_data/erlang.docs_v1
@@ -1 +1 @@
-{docs_v1,[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<66,121,32,99,111,110,118,101,110,116,105,111,110,44,32,109,111,115,116,32,66,117,105,108,116,45,73,110,32,70,117,110,99,116,105,111,110,115,32,40,66,73,70,115,41,32,97,114,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,46,32,83,111,109,101,32,111,102,32,116,104,101,32,66,73,70,115,32,97,114,101,32,118,105,101,119,101,100,32,109,111,114,101,32,111,114,32,108,101,115,115,32,97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,32,97,110,100,32,97,114,101,32>>,{em,[],[<<97,117,116,111,45,105,109,112,111,114,116,101,100>>]},<<46,32,84,104,117,115,44,32,105,116,32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,121,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,97,108,108,115,32>>,{code,[],[<<97,116,111,109,95,116,111,95,108,105,115,116,40,101,114,108,97,110,103,41>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,108,97,110,103,58,97,116,111,109,95,116,111,95,108,105,115,116,40,101,114,108,97,110,103,41>>]},<<32,97,114,101,32,105,100,101,110,116,105,99,97,108,46>>]},{p,[],[<<65,117,116,111,45,105,109,112,111,114,116,101,100,32,66,73,70,115,32,97,114,101,32,108,105,115,116,101,100,32,119,105,116,104,111,117,116,32,109,111,100,117,108,101,32,112,114,101,102,105,120,46,32,66,73,70,115,32,108,105,115,116,101,100,32,119,105,116,104,32,109,111,100,117,108,101,32,112,114,101,102,105,120,32,97,114,101,32,110,111,116,32,97,117,116,111,45,105,109,112,111,114,116,101,100,46>>]},{p,[],[<<66,73,70,115,32,99,97,110,32,102,97,105,108,32,102,111,114,32,118,97,114,105,111,117,115,32,114,101,97,115,111,110,115,46,32,65,108,108,32,66,73,70,115,32,102,97,105,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,121,32,97,114,101,32,99,97,108,108,101,100,32,119,105,116,104,32,97,114,103,117,109,101,110,116,115,32,111,102,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,46,32,84,104,101,32,111,116,104,101,114,32,114,101,97,115,111,110,115,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,101,97,99,104,32,105,110,100,105,118,105,100,117,97,108,32,66,73,70,46>>]},{p,[],[<<83,111,109,101,32,66,73,70,115,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,32,97,110,100,32,97,114,101,32,109,97,114,107,101,100,32,119,105,116,104,32,34,65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,34,46>>]}]},#{name => <<101,114,108,97,110,103>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,101,114,108,97,110,103,46,120,109,108],types => #{{time_unit,0} => {attribute,93,type,{time_unit,{type,94,union,[{type,94,pos_integer,[]},{atom,95,second},{atom,96,millisecond},{atom,97,microsecond},{atom,98,nanosecond},{atom,99,native},{atom,100,perf_counter},{user_type,101,deprecated_time_unit,[]}]},[]}},{prepared_code,0} => {attribute,110,opaque,{prepared_code,{type,110,reference,[]},[]}},{nif_resource,0} => {attribute,113,opaque,{nif_resource,{type,113,reference,[]},[]}},{system_monitor_option,0} => {attribute,274,type,{system_monitor_option,{type,275,union,[{atom,275,busy_port},{atom,276,busy_dist_port},{type,277,tuple,[{atom,277,long_gc},{type,277,non_neg_integer,[]}]},{type,278,tuple,[{atom,278,long_schedule},{type,278,non_neg_integer,[]}]},{type,279,tuple,[{atom,279,large_heap},{type,279,non_neg_integer,[]}]}]},[]}},{module_info_key,0} => {attribute,2123,type,{module_info_key,{type,2123,union,[{atom,2123,attributes},{atom,2123,compile},{atom,2123,exports},{atom,2123,functions},{atom,2123,md5},{atom,2124,module},{atom,2124,native},{atom,2124,native_addresses},{atom,2124,nifs}]},[]}},{trace_info_flag,0} => {attribute,327,type,{trace_info_flag,{type,328,union,[{atom,328,send},{atom,329,'receive'},{atom,330,set_on_spawn},{atom,331,call},{atom,332,return_to},{atom,333,procs},{atom,334,set_on_first_spawn},{atom,335,set_on_link},{atom,336,running},{atom,337,garbage_collection},{atom,338,timestamp},{atom,339,monotonic_timestamp},{atom,340,strict_monotonic_timestamp},{atom,341,arity}]},[]}},{ext_iovec,0} => {attribute,88,type,{ext_iovec,{user_type,88,iovec,[]},[]}},{trace_match_spec,0} => {attribute,2702,type,{trace_match_spec,{type,2703,list,[{type,2703,tuple,[{type,2703,union,[{type,2703,list,[{type,2703,term,[]}]},{atom,2703,'_'},{user_type,2703,match_variable,[]}]},{type,2703,list,[{type,2703,term,[]}]},{type,2703,list,[{type,2703,term,[]}]}]}]},[]}},{max_heap_size,0} => {attribute,2981,type,{max_heap_size,{ann_type,2982,[{var,2982,'Size'},{type,2982,union,[{type,2982,non_neg_integer,[]},{type,2984,map,[{type,2984,map_field_assoc,[{atom,2984,size},{type,2984,non_neg_integer,[]}]},{type,2985,map_field_assoc,[{atom,2985,kill},{type,2985,boolean,[]}]},{type,2986,map_field_assoc,[{atom,2986,error_logger},{type,2986,boolean,[]}]}]}]}]},[]}},{fun_info_item,0} => {attribute,247,type,{fun_info_item,{type,248,union,[{atom,248,arity},{atom,249,env},{atom,250,index},{atom,251,name},{atom,252,module},{atom,253,new_index},{atom,254,new_uniq},{atom,255,pid},{atom,256,type},{atom,257,uniq}]},[]}},{stack_item,0} => {attribute,2472,type,{stack_item,{type,2473,tuple,[{ann_type,2473,[{var,2473,'Module'},{type,2473,module,[]}]},{ann_type,2474,[{var,2474,'Function'},{type,2474,atom,[]}]},{ann_type,2475,[{var,2475,'Arity'},{type,2475,union,[{type,2475,arity,[]},{ann_type,2475,[{var,2475,'Args'},{type,2475,list,[{type,2475,term,[]}]}]}]}]},{ann_type,2476,[{var,2476,'Location'},{type,2476,list,[{type,2476,union,[{type,2476,tuple,[{atom,2476,file},{ann_type,2476,[{var,2476,'Filename'},{type,2476,string,[]}]}]},{type,2477,tuple,[{atom,2477,line},{ann_type,2477,[{var,2477,'Line'},{type,2477,pos_integer,[]}]}]}]}]}]}]},[]}},{monitor_option,0} => {attribute,1397,type,{monitor_option,{type,1397,union,[{type,1397,tuple,[{atom,1397,alias},{type,1397,union,[{atom,1397,explicit_unalias},{atom,1397,demonitor},{atom,1397,reply_demonitor}]}]},{type,1398,tuple,[{atom,1398,tag},{type,1398,term,[]}]}]},[]}},{trace_flag,0} => {attribute,291,type,{trace_flag,{type,292,union,[{atom,292,all},{atom,293,send},{atom,294,'receive'},{atom,295,procs},{atom,296,ports},{atom,297,call},{atom,298,arity},{atom,299,return_to},{atom,300,silent},{atom,301,running},{atom,302,exiting},{atom,303,running_procs},{atom,304,running_ports},{atom,305,garbage_collection},{atom,306,timestamp},{atom,307,cpu_timestamp},{atom,308,monotonic_timestamp},{atom,309,strict_monotonic_timestamp},{atom,310,set_on_spawn},{atom,311,set_on_first_spawn},{atom,312,set_on_link},{atom,313,set_on_first_link},{type,314,tuple,[{atom,314,tracer},{type,314,union,[{type,314,pid,[]},{type,314,port,[]}]}]},{type,315,tuple,[{atom,315,tracer},{type,315,module,[]},{type,315,term,[]}]}]},[]}},{sub_level,0} => {attribute,2760,type,{sub_level,{type,2760,union,[{type,2760,list,[{ann_type,2760,[{var,2760,'LevelEntry'},{user_type,2760,level_entry,[]}]}]},{ann_type,2761,[{var,2761,'LogicalCpuId'},{type,2761,tuple,[{atom,2761,logical},{type,2761,non_neg_integer,[]}]}]}]},[]}},{monitor_port_identifier,0} => {attribute,1396,type,{monitor_port_identifier,{type,1396,union,[{type,1396,port,[]},{user_type,1396,registered_name,[]}]},[]}},{iovec,0} => {attribute,119,type,{iovec,{type,119,list,[{type,119,binary,[]}]},[]}},{ext_binary,0} => {attribute,87,type,{ext_binary,{type,87,binary,[]},[]}},{registered_process_identifier,0} => {attribute,1394,type,{registered_process_identifier,{type,1394,union,[{user_type,1394,registered_name,[]},{type,1394,tuple,[{user_type,1394,registered_name,[]},{type,1394,node,[]}]}]},[]}},{process_info_result_item,0} => {attribute,2425,type,{process_info_result_item,{type,2426,union,[{type,2426,tuple,[{atom,2426,backtrace},{ann_type,2426,[{var,2426,'Bin'},{type,2426,binary,[]}]}]},{type,2427,tuple,[{atom,2427,binary},{ann_type,2427,[{var,2427,'BinInfo'},{type,2427,list,[{type,2427,tuple,[{type,2427,non_neg_integer,[]},{type,2428,non_neg_integer,[]},{type,2429,non_neg_integer,[]}]}]}]}]},{type,2430,tuple,[{atom,2430,catchlevel},{ann_type,2430,[{var,2430,'CatchLevel'},{type,2430,non_neg_integer,[]}]}]},{type,2431,tuple,[{atom,2431,current_function},{type,2432,union,[{type,2432,tuple,[{ann_type,2432,[{var,2432,'Module'},{type,2432,module,[]}]},{ann_type,2432,[{var,2432,'Function'},{type,2432,atom,[]}]},{ann_type,2432,[{var,2432,'Arity'},{type,2432,arity,[]}]}]},{atom,2432,undefined}]}]},{type,2433,tuple,[{atom,2433,current_location},{type,2434,tuple,[{ann_type,2434,[{var,2434,'Module'},{type,2434,module,[]}]},{ann_type,2434,[{var,2434,'Function'},{type,2434,atom,[]}]},{ann_type,2434,[{var,2434,'Arity'},{type,2434,arity,[]}]},{ann_type,2435,[{var,2435,'Location'},{type,2435,list,[{type,2435,union,[{type,2435,tuple,[{atom,2435,file},{ann_type,2435,[{var,2435,'Filename'},{type,2435,string,[]}]}]},{type,2436,tuple,[{atom,2436,line},{ann_type,2436,[{var,2436,'Line'},{type,2436,pos_integer,[]}]}]}]}]}]}]}]},{type,2437,tuple,[{atom,2437,current_stacktrace},{ann_type,2437,[{var,2437,'Stack'},{type,2437,list,[{user_type,2437,stack_item,[]}]}]}]},{type,2438,tuple,[{atom,2438,dictionary},{ann_type,2438,[{var,2438,'Dictionary'},{type,2438,list,[{type,2438,tuple,[{ann_type,2438,[{var,2438,'Key'},{type,2438,term,[]}]},{ann_type,2438,[{var,2438,'Value'},{type,2438,term,[]}]}]}]}]}]},{type,2439,tuple,[{atom,2439,error_handler},{ann_type,2439,[{var,2439,'Module'},{type,2439,module,[]}]}]},{type,2440,tuple,[{atom,2440,garbage_collection},{ann_type,2440,[{var,2440,'GCInfo'},{type,2440,list,[{type,2440,tuple,[{type,2440,atom,[]},{type,2440,non_neg_integer,[]}]}]}]}]},{type,2441,tuple,[{atom,2441,garbage_collection_info},{ann_type,2441,[{var,2441,'GCInfo'},{type,2441,list,[{type,2441,tuple,[{type,2441,atom,[]},{type,2441,non_neg_integer,[]}]}]}]}]},{type,2442,tuple,[{atom,2442,group_leader},{ann_type,2442,[{var,2442,'GroupLeader'},{type,2442,pid,[]}]}]},{type,2443,tuple,[{atom,2443,heap_size},{ann_type,2443,[{var,2443,'Size'},{type,2443,non_neg_integer,[]}]}]},{type,2444,tuple,[{atom,2444,initial_call},{type,2444,mfa,[]}]},{type,2445,tuple,[{atom,2445,links},{ann_type,2445,[{var,2445,'PidsAndPorts'},{type,2445,list,[{type,2445,union,[{type,2445,pid,[]},{type,2445,port,[]}]}]}]}]},{type,2446,tuple,[{atom,2446,last_calls},{type,2446,union,[{atom,2446,false},{ann_type,2446,[{var,2446,'Calls'},{type,2446,list,[{type,2446,mfa,[]}]}]}]}]},{type,2447,tuple,[{atom,2447,memory},{ann_type,2447,[{var,2447,'Size'},{type,2447,non_neg_integer,[]}]}]},{type,2448,tuple,[{atom,2448,message_queue_len},{ann_type,2448,[{var,2448,'MessageQueueLen'},{type,2448,non_neg_integer,[]}]}]},{type,2449,tuple,[{atom,2449,messages},{ann_type,2449,[{var,2449,'MessageQueue'},{type,2449,list,[{type,2449,term,[]}]}]}]},{type,2450,tuple,[{atom,2450,min_heap_size},{ann_type,2450,[{var,2450,'MinHeapSize'},{type,2450,non_neg_integer,[]}]}]},{type,2451,tuple,[{atom,2451,min_bin_vheap_size},{ann_type,2451,[{var,2451,'MinBinVHeapSize'},{type,2451,non_neg_integer,[]}]}]},{type,2452,tuple,[{atom,2452,max_heap_size},{ann_type,2452,[{var,2452,'MaxHeapSize'},{user_type,2452,max_heap_size,[]}]}]},{type,2453,tuple,[{atom,2453,monitored_by},{ann_type,2453,[{var,2453,'MonitoredBy'},{type,2453,list,[{type,2453,union,[{type,2453,pid,[]},{type,2453,port,[]},{user_type,2453,nif_resource,[]}]}]}]}]},{type,2454,tuple,[{atom,2454,monitors},{ann_type,2455,[{var,2455,'Monitors'},{type,2455,list,[{type,2455,tuple,[{type,2455,union,[{atom,2455,process},{atom,2455,port}]},{ann_type,2455,[{var,2455,'Pid'},{type,2455,union,[{type,2455,pid,[]},{type,2455,port,[]},{type,2456,tuple,[{ann_type,2456,[{var,2456,'RegName'},{type,2456,atom,[]}]},{ann_type,2456,[{var,2456,'Node'},{type,2456,node,[]}]}]}]}]}]}]}]}]},{type,2457,tuple,[{atom,2457,message_queue_data},{ann_type,2457,[{var,2457,'MQD'},{user_type,2457,message_queue_data,[]}]}]},{type,2458,tuple,[{atom,2458,priority},{ann_type,2458,[{var,2458,'Level'},{user_type,2458,priority_level,[]}]}]},{type,2459,tuple,[{atom,2459,reductions},{ann_type,2459,[{var,2459,'Number'},{type,2459,non_neg_integer,[]}]}]},{type,2460,tuple,[{atom,2460,registered_name},{type,2460,union,[{type,2460,nil,[]},{ann_type,2460,[{var,2460,'Atom'},{type,2460,atom,[]}]}]}]},{type,2461,tuple,[{atom,2461,sequential_trace_token},{type,2461,union,[{type,2461,nil,[]},{ann_type,2461,[{var,2461,'SequentialTraceToken'},{type,2461,term,[]}]}]}]},{type,2462,tuple,[{atom,2462,stack_size},{ann_type,2462,[{var,2462,'Size'},{type,2462,non_neg_integer,[]}]}]},{type,2463,tuple,[{atom,2463,status},{ann_type,2463,[{var,2463,'Status'},{type,2463,union,[{atom,2463,exiting},{atom,2463,garbage_collecting},{atom,2463,waiting},{atom,2463,running},{atom,2463,runnable},{atom,2463,suspended}]}]}]},{type,2464,tuple,[{atom,2464,suspending},{ann_type,2465,[{var,2465,'SuspendeeList'},{type,2465,list,[{type,2465,tuple,[{ann_type,2465,[{var,2465,'Suspendee'},{type,2465,pid,[]}]},{ann_type,2466,[{var,2466,'ActiveSuspendCount'},{type,2466,non_neg_integer,[]}]},{ann_type,2467,[{var,2467,'OutstandingSuspendCount'},{type,2467,non_neg_integer,[]}]}]}]}]}]},{type,2468,tuple,[{atom,2468,total_heap_size},{ann_type,2468,[{var,2468,'Size'},{type,2468,non_neg_integer,[]}]}]},{type,2469,tuple,[{atom,2469,trace},{ann_type,2469,[{var,2469,'InternalTraceFlags'},{type,2469,non_neg_integer,[]}]}]},{type,2470,tuple,[{atom,2470,trap_exit},{ann_type,2470,[{var,2470,'Boolean'},{type,2470,boolean,[]}]}]}]},[]}},{seq_trace_info_returns,0} => {attribute,259,type,{seq_trace_info_returns,{type,260,union,[{type,260,tuple,[{type,260,union,[{atom,260,send},{atom,260,'receive'},{atom,260,print},{atom,260,timestamp},{atom,260,monotonic_timestamp},{atom,260,strict_monotonic_timestamp}]},{type,260,boolean,[]}]},{type,261,tuple,[{atom,261,label},{type,261,term,[]}]},{type,262,tuple,[{atom,262,serial},{type,262,tuple,[{type,262,non_neg_integer,[]},{type,262,non_neg_integer,[]}]}]},{type,263,nil,[]}]},[]}},{process_info_item,0} => {attribute,2390,type,{process_info_item,{type,2391,union,[{atom,2391,backtrace},{atom,2392,binary},{atom,2393,catchlevel},{atom,2394,current_function},{atom,2395,current_location},{atom,2396,current_stacktrace},{atom,2397,dictionary},{atom,2398,error_handler},{atom,2399,garbage_collection},{atom,2400,garbage_collection_info},{atom,2401,group_leader},{atom,2402,heap_size},{atom,2403,initial_call},{atom,2404,links},{atom,2405,last_calls},{atom,2406,memory},{atom,2407,message_queue_len},{atom,2408,messages},{atom,2409,min_heap_size},{atom,2410,min_bin_vheap_size},{atom,2411,monitored_by},{atom,2412,monitors},{atom,2413,message_queue_data},{atom,2414,priority},{atom,2415,reductions},{atom,2416,registered_name},{atom,2417,sequential_trace_token},{atom,2418,stack_size},{atom,2419,status},{atom,2420,suspending},{atom,2421,total_heap_size},{atom,2422,trace},{atom,2423,trap_exit}]},[]}},{trace_info_return,0} => {attribute,343,type,{trace_info_return,{type,344,union,[{atom,344,undefined},{type,345,tuple,[{atom,345,flags},{type,345,list,[{user_type,345,trace_info_flag,[]}]}]},{type,346,tuple,[{atom,346,tracer},{type,346,union,[{type,346,pid,[]},{type,346,port,[]},{type,346,nil,[]}]}]},{type,347,tuple,[{atom,347,tracer},{type,347,module,[]},{type,347,term,[]}]},{user_type,348,trace_info_item_result,[]},{type,349,tuple,[{atom,349,all},{type,349,union,[{type,349,list,[{user_type,349,trace_info_item_result,[]}]},{atom,349,false},{atom,349,undefined}]}]}]},[]}},{trace_info_item_result,0} => {attribute,317,type,{trace_info_item_result,{type,318,union,[{type,318,tuple,[{atom,318,traced},{type,318,union,[{atom,318,global},{atom,318,local},{atom,318,false},{atom,318,undefined}]}]},{type,319,tuple,[{atom,319,match_spec},{type,319,union,[{user_type,319,trace_match_spec,[]},{atom,319,false},{atom,319,undefined}]}]},{type,320,tuple,[{atom,320,meta},{type,320,union,[{type,320,pid,[]},{type,320,port,[]},{atom,320,false},{atom,320,undefined},{type,320,nil,[]}]}]},{type,321,tuple,[{atom,321,meta},{type,321,module,[]},{type,321,term,[]}]},{type,322,tuple,[{atom,322,meta_match_spec},{type,322,union,[{user_type,322,trace_match_spec,[]},{atom,322,false},{atom,322,undefined}]}]},{type,323,tuple,[{atom,323,call_count},{type,323,union,[{type,323,non_neg_integer,[]},{type,323,boolean,[]},{atom,323,undefined}]}]},{type,324,tuple,[{atom,324,call_time},{type,324,union,[{type,324,list,[{type,324,tuple,[{type,324,pid,[]},{type,324,non_neg_integer,[]},{type,325,non_neg_integer,[]},{type,325,non_neg_integer,[]}]}]},{type,325,boolean,[]},{atom,325,undefined}]}]}]},[]}},{trace_pattern_mfa,0} => {attribute,2700,type,{trace_pattern_mfa,{type,2701,union,[{type,2701,tuple,[{type,2701,atom,[]},{type,2701,atom,[]},{type,2701,union,[{type,2701,arity,[]},{atom,2701,'_'}]}]},{atom,2701,on_load}]},[]}},{registered_name,0} => {attribute,1393,type,{registered_name,{type,1393,atom,[]},[]}},{dist_handle,0} => {attribute,116,opaque,{dist_handle,{type,116,atom,[]},[]}},{info_list,0} => {attribute,2762,type,{info_list,{type,2762,nil,[]},[]}},{cpu_topology,0} => {attribute,2752,type,{cpu_topology,{type,2753,union,[{type,2753,list,[{ann_type,2753,[{var,2753,'LevelEntry'},{user_type,2753,level_entry,[]}]}]},{atom,2753,undefined}]},[]}},{memory_type,0} => {attribute,3977,type,{memory_type,{type,3977,union,[{atom,3977,total},{atom,3977,processes},{atom,3977,processes_used},{atom,3977,system},{atom,3978,atom},{atom,3978,atom_used},{atom,3978,binary},{atom,3978,code},{atom,3978,ets}]},[]}},{level_tag,0} => {attribute,2759,type,{level_tag,{type,2759,union,[{atom,2759,core},{atom,2759,node},{atom,2759,processor},{atom,2759,thread}]},[]}},{timestamp,0} => {attribute,89,type,{timestamp,{type,89,tuple,[{ann_type,89,[{var,89,'MegaSecs'},{type,89,non_neg_integer,[]}]},{ann_type,90,[{var,90,'Secs'},{type,90,non_neg_integer,[]}]},{ann_type,91,[{var,91,'MicroSecs'},{type,91,non_neg_integer,[]}]}]},[]}},{deprecated_time_unit,0} => {attribute,104,type,{deprecated_time_unit,{type,105,union,[{atom,105,seconds},{atom,106,milli_seconds},{atom,107,micro_seconds},{atom,108,nano_seconds}]},[]}},{spawn_opt_option,0} => {attribute,2988,type,{spawn_opt_option,{type,2989,union,[{atom,2989,link},{atom,2990,monitor},{type,2991,tuple,[{atom,2991,monitor},{ann_type,2991,[{var,2991,'MonitorOpts'},{type,2991,list,[{user_type,2991,monitor_option,[]}]}]}]},{type,2992,tuple,[{atom,2992,priority},{ann_type,2992,[{var,2992,'Level'},{user_type,2992,priority_level,[]}]}]},{type,2993,tuple,[{atom,2993,fullsweep_after},{ann_type,2993,[{var,2993,'Number'},{type,2993,non_neg_integer,[]}]}]},{type,2994,tuple,[{atom,2994,min_heap_size},{ann_type,2994,[{var,2994,'Size'},{type,2994,non_neg_integer,[]}]}]},{type,2995,tuple,[{atom,2995,min_bin_vheap_size},{ann_type,2995,[{var,2995,'VSize'},{type,2995,non_neg_integer,[]}]}]},{type,2996,tuple,[{atom,2996,max_heap_size},{ann_type,2996,[{var,2996,'Size'},{user_type,2996,max_heap_size,[]}]}]},{type,2997,tuple,[{atom,2997,message_queue_data},{ann_type,2997,[{var,2997,'MQD'},{user_type,2997,message_queue_data,[]}]}]}]},[]}},{dst,0} => {attribute,3452,type,{dst,{type,3452,union,[{type,3452,pid,[]},{type,3453,reference,[]},{type,3454,port,[]},{ann_type,3455,[{var,3455,'RegName'},{type,3455,atom,[]}]},{type,3456,tuple,[{ann_type,3456,[{var,3456,'RegName'},{type,3456,atom,[]}]},{ann_type,3456,[{var,3456,'Node'},{type,3456,node,[]}]}]}]},[]}},{bitstring_list,0} => {attribute,288,type,{bitstring_list,{type,289,maybe_improper_list,[{type,289,union,[{type,289,byte,[]},{type,289,bitstring,[]},{user_type,289,bitstring_list,[]}]},{type,289,union,[{type,289,bitstring,[]},{type,289,nil,[]}]}]},[]}},{match_variable,0} => {attribute,2699,type,{match_variable,{type,2699,atom,[]},[]}},{monitor_process_identifier,0} => {attribute,1395,type,{monitor_process_identifier,{type,1395,union,[{type,1395,pid,[]},{user_type,1395,registered_process_identifier,[]}]},[]}},{scheduler_bind_type,0} => {attribute,2596,type,{scheduler_bind_type,{type,2597,union,[{atom,2597,no_node_processor_spread},{atom,2598,no_node_thread_spread},{atom,2599,no_spread},{atom,2600,processor_spread},{atom,2601,spread},{atom,2602,thread_spread},{atom,2603,thread_no_node_processor_spread},{atom,2604,unbound}]},[]}},{trace_pattern_flag,0} => {attribute,2718,type,{trace_pattern_flag,{type,2719,union,[{atom,2719,global},{atom,2719,local},{atom,2720,meta},{type,2720,tuple,[{atom,2720,meta},{ann_type,2720,[{var,2720,'Pid'},{type,2720,pid,[]}]}]},{type,2721,tuple,[{atom,2721,meta},{ann_type,2721,[{var,2721,'TracerModule'},{type,2721,module,[]}]},{ann_type,2721,[{var,2721,'TracerState'},{type,2721,term,[]}]}]},{atom,2722,call_count},{atom,2723,call_time}]},[]}},{system_profile_option,0} => {attribute,265,type,{system_profile_option,{type,266,union,[{atom,266,exclusive},{atom,267,runnable_ports},{atom,268,runnable_procs},{atom,269,scheduler},{atom,270,timestamp},{atom,271,monotonic_timestamp},{atom,272,strict_monotonic_timestamp}]},[]}},{message_queue_data,0} => {attribute,2353,type,{message_queue_data,{type,2354,union,[{atom,2354,off_heap},{atom,2354,on_heap}]},[]}},{raise_stacktrace,0} => {attribute,282,type,{raise_stacktrace,{type,283,union,[{type,283,list,[{type,283,union,[{type,283,tuple,[{type,283,module,[]},{type,283,atom,[]},{type,283,union,[{type,283,arity,[]},{type,283,list,[{type,283,term,[]}]}]}]},{type,284,tuple,[{type,284,function,[]},{type,284,list,[{type,284,term,[]}]}]}]}]},{type,285,list,[{type,285,union,[{type,285,tuple,[{type,285,module,[]},{type,285,atom,[]},{type,285,union,[{type,285,arity,[]},{type,285,list,[{type,285,term,[]}]}]},{type,285,list,[{type,285,tuple,[{type,285,atom,[]},{type,285,term,[]}]}]}]},{type,286,tuple,[{type,286,function,[]},{type,286,list,[{type,286,term,[]}]},{type,286,list,[{type,286,tuple,[{type,286,atom,[]},{type,286,term,[]}]}]}]}]}]}]},[]}},{priority_level,0} => {attribute,2350,type,{priority_level,{type,2351,union,[{atom,2351,low},{atom,2351,normal},{atom,2351,high},{atom,2351,max}]},[]}},{level_entry,0} => {attribute,2754,type,{level_entry,{type,2755,union,[{type,2755,tuple,[{ann_type,2755,[{var,2755,'LevelTag'},{user_type,2755,level_tag,[]}]},{ann_type,2755,[{var,2755,'SubLevel'},{user_type,2755,sub_level,[]}]}]},{type,2756,tuple,[{ann_type,2756,[{var,2756,'LevelTag'},{user_type,2756,level_tag,[]}]},{ann_type,2757,[{var,2757,'InfoList'},{user_type,2757,info_list,[]}]},{ann_type,2758,[{var,2758,'SubLevel'},{user_type,2758,sub_level,[]}]}]}]},[]}}}},[{{function,abs,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2100}],[<<97,98,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,111,114,32,102,108,111,97,116,32,116,104,97,116,32,105,115,32,116,104,101,32,97,114,105,116,104,109,101,116,105,99,97,108,32,97,98,115,111,108,117,116,101,32,118,97,108,117,101,32,111,102,32>>,{code,[],[<<70,108,111,97,116>>]},<<32,111,114,32>>,{code,[],[<<73,110,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,98,115,40,45,51,46,51,51,41,46,10,51,46,51,51,10,62,32,97,98,115,40,45,51,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,54>>,signature => [{attribute,2100,spec,{{abs,1},[{type,2100,bounded_fun,[{type,2100,'fun',[{type,2100,product,[{var,2100,'Float'}]},{type,2100,float,[]}]},[{type,2101,constraint,[{atom,2101,is_subtype},[{var,2101,'Float'},{type,2101,float,[]}]]}]]},{type,2102,bounded_fun,[{type,2102,'fun',[{type,2102,product,[{var,2102,'Int'}]},{type,2102,non_neg_integer,[]}]},[{type,2103,constraint,[{atom,2103,is_subtype},[{var,2103,'Int'},{type,2103,integer,[]}]]}]]}]}}]}},{{function,adler32,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,353}],[<<97,100,108,101,114,51,50,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,117,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,97,100,108,101,114,51,50,32,99,104,101,99,107,115,117,109,32,102,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,51>>,signature => [{attribute,353,spec,{{erlang,adler32,1},[{type,353,bounded_fun,[{type,353,'fun',[{type,353,product,[{var,353,'Data'}]},{type,353,non_neg_integer,[]}]},[{type,354,constraint,[{atom,354,is_subtype},[{var,354,'Data'},{type,354,iodata,[]}]]}]]}]}}]}},{{function,adler32,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,359}],[<<97,100,108,101,114,51,50,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,110,116,105,110,117,101,115,32,99,111,109,112,117,116,105,110,103,32,116,104,101,32,97,100,108,101,114,51,50,32,99,104,101,99,107,115,117,109,32,98,121,32,99,111,109,98,105,110,105,110,103,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,104,101,99,107,115,117,109,44,32>>,{code,[],[<<79,108,100,65,100,108,101,114>>]},<<44,32,119,105,116,104,32,116,104,101,32,99,104,101,99,107,115,117,109,32,111,102,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,88,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<89>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,91,68,97,116,97,49,44,68,97,116,97,50,93,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,50>>,signature => [{attribute,359,spec,{{erlang,adler32,2},[{type,359,bounded_fun,[{type,359,'fun',[{type,359,product,[{var,359,'OldAdler'},{var,359,'Data'}]},{type,359,non_neg_integer,[]}]},[{type,360,constraint,[{atom,360,is_subtype},[{var,360,'OldAdler'},{type,360,non_neg_integer,[]}]]},{type,361,constraint,[{atom,361,is_subtype},[{var,361,'Data'},{type,361,iodata,[]}]]}]]}]}}]}},{{function,adler32_combine,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,366}],[<<97,100,108,101,114,51,50,95,99,111,109,98,105,110,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32,116,119,111,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,117,116,101,100,32,97,100,108,101,114,51,50,32,99,104,101,99,107,115,117,109,115,46,32,84,104,105,115,32,99,111,109,112,117,116,97,116,105,111,110,32,114,101,113,117,105,114,101,115,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,100,97,116,97,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101,32,115,101,99,111,110,100,32,99,104,101,99,107,115,117,109,32,116,111,32,98,101,32,107,110,111,119,110,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,49,41,44,10,90,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,89,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<90>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,50,41,44,10,90,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,95,99,111,109,98,105,110,101,40,88,44,89,44,105,111,108,105,115,116,95,115,105,122,101,40,68,97,116,97,50,41,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,57>>,signature => [{attribute,366,spec,{{erlang,adler32_combine,3},[{type,366,bounded_fun,[{type,366,'fun',[{type,366,product,[{var,366,'FirstAdler'},{var,366,'SecondAdler'},{var,366,'SecondSize'}]},{type,366,non_neg_integer,[]}]},[{type,367,constraint,[{atom,367,is_subtype},[{var,367,'FirstAdler'},{type,367,non_neg_integer,[]}]]},{type,368,constraint,[{atom,368,is_subtype},[{var,368,'SecondAdler'},{type,368,non_neg_integer,[]}]]},{type,369,constraint,[{atom,369,is_subtype},[{var,369,'SecondSize'},{type,369,non_neg_integer,[]}]]}]]}]}}]}},{{function,alias,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,759}],[<<97,108,105,97,115,47,49>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,56>>,equiv => {function,alias,0},signature => [{attribute,759,spec,{{alias,1},[{type,759,bounded_fun,[{type,759,'fun',[{type,759,product,[{var,759,'Opts'}]},{var,759,'Alias'}]},[{type,760,constraint,[{atom,760,is_subtype},[{var,760,'Alias'},{type,760,reference,[]}]]},{type,761,constraint,[{atom,761,is_subtype},[{var,761,'Opts'},{type,761,list,[{type,761,union,[{atom,761,explicit_unalias},{atom,761,reply}]}]}]]}]]}]}}],since => <<79,84,80,32,64,79,84,80,45,49,54,55,49,56,64>>}},{{function,alias,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,753}],[<<97,108,105,97,115,47,48>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,32,97,110,32,97,108,105,97,115,32,119,104,105,99,104,32,99,97,110,32,98,101,32,117,115,101,100,32,119,104,101,110,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,97,108,105,97,115,46,32,87,104,101,110,32,116,104,101,32,97,108,105,97,115,32,104,97,115,32,98,101,101,110,32,100,101,97,99,116,105,118,97,116,101,100,44,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,117,115,105,110,103,32,116,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,100,114,111,112,112,101,100,46,32,65,110,32,97,108,105,97,115,32,99,97,110,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,97,108,105,97,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,97,108,105,97,115,47,49>>]}]},<<46,32,67,117,114,114,101,110,116,108,121,32,97,118,97,105,108,97,98,108,101,32,111,112,116,105,111,110,115,32,102,111,114,32>>,{code,[],[<<97,108,105,97,115,47,49>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,112,108,105,99,105,116,95,117,110,97,108,105,97,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,99,97,110,32,111,110,108,121,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46,32,84,104,105,115,32,105,115,32,97,108,115,111,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,117,114,32,105,102,32,110,111,32,111,112,116,105,111,110,115,32,97,114,101,32,112,97,115,115,101,100,32,111,114,32,105,102,32>>,{code,[],[<<97,108,105,97,115,47,48>>]},<<32,105,115,32,99,97,108,108,101,100,46>>]}]},{dt,[],[{code,[],[<<114,101,112,108,121>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,119,104,101,110,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,115,101,110,116,32,118,105,97,32,116,104,101,32,97,108,105,97,115,32,105,115,32,114,101,99,101,105,118,101,100,46,32,84,104,101,32,97,108,105,97,115,32,99,97,110,32,97,108,115,111,32,115,116,105,108,108,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,56>>,signature => [{attribute,753,spec,{{alias,0},[{type,753,bounded_fun,[{type,753,'fun',[{type,753,product,[]},{var,753,'Alias'}]},[{type,754,constraint,[{atom,754,is_subtype},[{var,754,'Alias'},{type,754,reference,[]}]]}]]}]}}],since => <<79,84,80,32,64,79,84,80,45,49,54,55,49,56,64>>}},{{function,append_element,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,374}],[<<97,112,112,101,110,100,95,101,108,101,109,101,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,101,119,32,116,117,112,108,101,32,116,104,97,116,32,104,97,115,32,111,110,101,32,101,108,101,109,101,110,116,32,109,111,114,101,32,116,104,97,110,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<44,32,97,110,100,32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,105,110,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<32,102,111,108,108,111,119,101,100,32,98,121,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,115,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,46,32,83,101,109,97,110,116,105,99,97,108,108,121,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<108,105,115,116,95,116,111,95,116,117,112,108,101,40,116,117,112,108,101,95,116,111,95,108,105,115,116,40,84,117,112,108,101,49,41,32,43,43,32,91,84,101,114,109,93,41>>]},<<44,32,98,117,116,32,109,117,99,104,32,102,97,115,116,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,97,112,112,101,110,100,95,101,108,101,109,101,110,116,40,123,111,110,101,44,32,116,119,111,125,44,32,116,104,114,101,101,41,46,10,123,111,110,101,44,116,119,111,44,116,104,114,101,101,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,48>>,signature => [{attribute,374,spec,{{erlang,append_element,2},[{type,374,bounded_fun,[{type,374,'fun',[{type,374,product,[{var,374,'Tuple1'},{var,374,'Term'}]},{var,374,'Tuple2'}]},[{type,375,constraint,[{atom,375,is_subtype},[{var,375,'Tuple1'},{type,375,tuple,any}]]},{type,376,constraint,[{atom,376,is_subtype},[{var,376,'Tuple2'},{type,376,tuple,any}]]},{type,377,constraint,[{atom,377,is_subtype},[{var,377,'Term'},{type,377,term,[]}]]}]]}]}}]}},{{function,apply,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2888}],[<<97,112,112,108,121,47,50>>],#{<<101,110>> => [{p,[],[<<67,97,108,108,115,32,97,32,102,117,110,44,32,112,97,115,115,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,105,110,32>>,{code,[],[<<65,114,103,115>>]},<<32,97,115,32,97,114,103,117,109,101,110,116,115,46>>]},{p,[],[<<73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,105,110,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,107,110,111,119,110,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,44,32,116,104,101,32,99,97,108,108,32,105,115,32,98,101,116,116,101,114,32,119,114,105,116,116,101,110,32,97,115,32>>,{code,[],[<<70,117,110,40,65,114,103,49,44,32,65,114,103,50,44,32,46,46,46,32,65,114,103,78,41>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<69,97,114,108,105,101,114,44,32>>,{code,[],[<<70,117,110>>]},<<32,99,111,117,108,100,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,125>>]},<<44,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<97,112,112,108,121,40,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,103,115,41>>]},<<46,32>>,{em,[],[<<84,104,105,115,32,117,115,101,32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97,110,100,32,119,105,108,108,32,115,116,111,112,32,119,111,114,107,105,110,103,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,55>>,signature => [{attribute,2888,spec,{{apply,2},[{type,2888,bounded_fun,[{type,2888,'fun',[{type,2888,product,[{var,2888,'Fun'},{var,2888,'Args'}]},{type,2888,term,[]}]},[{type,2889,constraint,[{atom,2889,is_subtype},[{var,2889,'Fun'},{type,2889,function,[]}]]},{type,2890,constraint,[{atom,2890,is_subtype},[{var,2890,'Args'},{type,2890,list,[{type,2890,term,[]}]}]]}]]}]}}]}},{{function,apply,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2895}],[<<97,112,112,108,121,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,110,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,84,104,101,32,97,112,112,108,105,101,100,32,102,117,110,99,116,105,111,110,32,109,117,115,116,32,98,101,32,101,120,112,111,114,116,101,100,32,102,114,111,109,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46,32,84,104,101,32,97,114,105,116,121,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,112,112,108,121,40,108,105,115,116,115,44,32,114,101,118,101,114,115,101,44,32,91,91,97,44,32,98,44,32,99,93,93,41,46,10,91,99,44,98,44,97,93,10,62,32,97,112,112,108,121,40,101,114,108,97,110,103,44,32,97,116,111,109,95,116,111,95,108,105,115,116,44,32,91,39,69,114,108,97,110,103,39,93,41,46,10,34,69,114,108,97,110,103,34>>]}]},{p,[],[<<73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,107,110,111,119,110,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,44,32,116,104,101,32,99,97,108,108,32,105,115,32,98,101,116,116,101,114,32,119,114,105,116,116,101,110,32,97,115,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,40,65,114,103,49,44,32,65,114,103,50,44,32,46,46,46,44,32,65,114,103,78,41>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{a,[{href,<<107,101,114,110,101,108,58,101,114,114,111,114,95,104,97,110,100,108,101,114,35,117,110,100,101,102,105,110,101,100,95,102,117,110,99,116,105,111,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114,58,117,110,100,101,102,105,110,101,100,95,102,117,110,99,116,105,111,110,47,51>>]}]},<<32,105,115,32,99,97,108,108,101,100,32,105,102,32,116,104,101,32,97,112,112,108,105,101,100,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,101,120,112,111,114,116,101,100,46,32,84,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,99,97,110,32,98,101,32,114,101,100,101,102,105,110,101,100,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<41,46,32,73,102,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,111,114,32,105,102,32,116,104,101,32,117,115,101,114,32,104,97,115,32,114,101,100,101,102,105,110,101,100,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,115,111,32,116,104,101,32,114,101,112,108,97,99,101,109,101,110,116,32,109,111,100,117,108,101,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,110,32,101,114,114,111,114,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<117,110,100,101,102>>]},<<32,105,115,32,103,101,110,101,114,97,116,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,53>>,signature => [{attribute,2895,spec,{{apply,3},[{type,2895,bounded_fun,[{type,2895,'fun',[{type,2895,product,[{var,2895,'Module'},{var,2895,'Function'},{var,2895,'Args'}]},{type,2895,term,[]}]},[{type,2896,constraint,[{atom,2896,is_subtype},[{var,2896,'Module'},{type,2896,module,[]}]]},{type,2897,constraint,[{atom,2897,is_subtype},[{var,2897,'Function'},{type,2897,atom,[]}]]},{type,2898,constraint,[{atom,2898,is_subtype},[{var,2898,'Args'},{type,2898,list,[{type,2898,term,[]}]}]]}]]}]}}]}},{{function,atom_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,382}],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,97,116,111,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121>>]},<<32>>]},{code,[],[<<40,65,116,111,109,44,32,117,116,102,56,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,53>>,signature => [{attribute,382,spec,{{atom_to_binary,1},[{type,382,bounded_fun,[{type,382,'fun',[{type,382,product,[{var,382,'Atom'}]},{type,382,binary,[]}]},[{type,383,constraint,[{atom,383,is_subtype},[{var,383,'Atom'},{type,383,atom,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,atom_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,393}],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<65,116,111,109>>]},<<46,32,73,102,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<32,105,115,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,111,110,101,32,98,121,116,101,32,101,120,105,115,116,115,32,102,111,114,32,101,97,99,104,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46,32,73,102,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,111,114,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,85,84,70,45,56,32,119,104,101,114,101,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,114,101,113,117,105,114,101,32,109,117,108,116,105,112,108,101,32,98,121,116,101,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,50,48,44,32,97,116,111,109,115,32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,97,110,100,32>>,{code,[],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121,40,65,116,111,109,44,32,108,97,116,105,110,49,41>>]},<<32,109,97,121,32,102,97,105,108,32,105,102,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,102,111,114,32>>,{code,[],[<<65,116,111,109>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,62,32,50,53,53,46>>]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,116,111,109,95,116,111,95,98,105,110,97,114,121,40,39,69,114,108,97,110,103,39,44,32,108,97,116,105,110,49,41,46,10,60,60,34,69,114,108,97,110,103,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,53>>,signature => [{attribute,393,spec,{{atom_to_binary,2},[{type,393,bounded_fun,[{type,393,'fun',[{type,393,product,[{var,393,'Atom'},{var,393,'Encoding'}]},{type,393,binary,[]}]},[{type,394,constraint,[{atom,394,is_subtype},[{var,394,'Atom'},{type,394,atom,[]}]]},{type,395,constraint,[{atom,395,is_subtype},[{var,395,'Encoding'},{type,395,union,[{atom,395,latin1},{atom,395,unicode},{atom,395,utf8}]}]]}]]}]}}]}},{{function,atom_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,400}],[<<97,116,111,109,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,117,110,105,99,111,100,101,32,99,111,100,101,32,112,111,105,110,116,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<65,116,111,109>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,116,111,109,95,116,111,95,108,105,115,116,40,39,69,114,108,97,110,103,39,41,46,10,34,69,114,108,97,110,103,34>>]}]},{pre,[],[{code,[],[<<62,32,97,116,111,109,95,116,111,95,108,105,115,116,40,39,228,189,160,229,165,189,39,41,46,10,91,50,48,51,50,48,44,50,50,57,48,57,93>>]}]},{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,100,108,105,98,58,117,110,105,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,105,99,111,100,101,40,51,41>>]}]},<<32,102,111,114,32,104,111,119,32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,32,116,111,32,100,105,102,102,101,114,101,110,116,32,102,111,114,109,97,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,53,48>>,signature => [{attribute,400,spec,{{atom_to_list,1},[{type,400,bounded_fun,[{type,400,'fun',[{type,400,product,[{var,400,'Atom'}]},{type,400,string,[]}]},[{type,401,constraint,[{atom,401,is_subtype},[{var,401,'Atom'},{type,401,atom,[]}]]}]]}]}}]}},{{function,binary_part,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,407}],[<<98,105,110,97,114,121,95,112,97,114,116,47,50>>],#{<<101,110>> => [{p,[],[<<69,120,116,114,97,99,116,115,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,100,101,115,99,114,105,98,101,100,32,98,121,32>>,{code,[],[<<80,111,115,76,101,110>>]},<<46>>]},{p,[],[<<78,101,103,97,116,105,118,101,32,108,101,110,103,116,104,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,101,120,116,114,97,99,116,32,98,121,116,101,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,97,32,98,105,110,97,114,121,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<49,62,32,66,105,110,32,61,32,60,60,49,44,50,44,51,44,52,44,53,44,54,44,55,44,56,44,57,44,49,48,62,62,46,10,50,62,32,98,105,110,97,114,121,95,112,97,114,116,40,66,105,110,44,123,98,121,116,101,95,115,105,122,101,40,66,105,110,41,44,32,45,53,125,41,46,10,60,60,54,44,55,44,56,44,57,44,49,48,62,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,115,76,101,110>>]},<<32,105,110,32,97,110,121,32,119,97,121,32,114,101,102,101,114,101,110,99,101,115,32,111,117,116,115,105,100,101,32,116,104,101,32,98,105,110,97,114,121,46>>]},{p,[],[{code,[],[<<83,116,97,114,116>>]},<<32,105,115,32,122,101,114,111,45,98,97,115,101,100,44,32,116,104,97,116,32,105,115,58>>]},{pre,[],[{code,[],[<<49,62,32,66,105,110,32,61,32,60,60,49,44,50,44,51,62,62,10,50,62,32,98,105,110,97,114,121,95,112,97,114,116,40,66,105,110,44,123,48,44,50,125,41,46,10,60,60,49,44,50,62,62>>]}]},{p,[],[<<70,111,114,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<80,111,115,76,101,110>>]},<<32,115,101,109,97,110,116,105,99,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,100,108,105,98,58,98,105,110,97,114,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<98,105,110,97,114,121,40,51,41>>]}]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,54,56>>,signature => [{attribute,407,spec,{{binary_part,2},[{type,407,bounded_fun,[{type,407,'fun',[{type,407,product,[{var,407,'Subject'},{var,407,'PosLen'}]},{type,407,binary,[]}]},[{type,408,constraint,[{atom,408,is_subtype},[{var,408,'Subject'},{type,408,binary,[]}]]},{type,409,constraint,[{atom,409,is_subtype},[{var,409,'PosLen'},{type,409,tuple,[{ann_type,409,[{var,409,'Start'},{type,409,non_neg_integer,[]}]},{ann_type,409,[{var,409,'Length'},{type,409,integer,[]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,binary_part,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,415}],[<<98,105,110,97,114,121,95,112,97,114,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<98,105,110,97,114,121,95,112,97,114,116,40,83,117,98,106,101,99,116,44,32,123,83,116,97,114,116,44,32,76,101,110,103,116,104,125,41>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,57,51>>,signature => [{attribute,415,spec,{{binary_part,3},[{type,415,bounded_fun,[{type,415,'fun',[{type,415,product,[{var,415,'Subject'},{var,415,'Start'},{var,415,'Length'}]},{type,415,binary,[]}]},[{type,416,constraint,[{atom,416,is_subtype},[{var,416,'Subject'},{type,416,binary,[]}]]},{type,417,constraint,[{atom,417,is_subtype},[{var,417,'Start'},{type,417,non_neg_integer,[]}]]},{type,418,constraint,[{atom,418,is_subtype},[{var,418,'Length'},{type,418,integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,binary_to_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,423}],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109>>]},<<32>>]},{code,[],[<<40,66,105,110,97,114,121,44,32,117,116,102,56,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,48,51>>,signature => [{attribute,423,spec,{{binary_to_atom,1},[{type,423,bounded_fun,[{type,423,'fun',[{type,423,product,[{var,423,'Binary'}]},{type,423,atom,[]}]},[{type,424,constraint,[{atom,424,is_subtype},[{var,424,'Binary'},{type,424,binary,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,binary_to_atom,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,433}],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46,32,73,102,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,111,114,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,116,104,101,32,98,105,110,97,114,121,32,109,117,115,116,32,99,111,110,116,97,105,110,32,118,97,108,105,100,32,85,84,70,45,56,32,115,101,113,117,101,110,99,101,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,50,48,44,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,40,66,105,110,97,114,121,44,32,117,116,102,56,41>>]},<<32,105,115,32,99,97,112,97,98,108,101,32,111,102,32,101,110,99,111,100,105,110,103,32,97,110,121,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,46,32,69,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,119,111,117,108,100,32,102,97,105,108,32,105,102,32,116,104,101,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,101,100,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,62,32,50,53,53,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,85,110,105,99,111,100,101,32,115,117,112,112,111,114,116,32,105,110,32,97,116,111,109,115,44,32,115,101,101,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,101,120,116,95,100,105,115,116,35,117,116,102,56,95,97,116,111,109,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,116,101,32,111,110,32,85,84,70,45,56,32,101,110,99,111,100,101,100,32,97,116,111,109,115>>]},<<32,105,110,32,115,101,99,116,105,111,110,32,34,69,120,116,101,114,110,97,108,32,84,101,114,109,32,70,111,114,109,97,116,34,32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,97,110,32,97,116,111,109,32,110,97,109,101,32,105,115,32,108,105,109,105,116,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,99,111,110,102,105,103,117,114,97,98,108,101,32,108,105,109,105,116,32,111,110,32,104,111,119,32,109,97,110,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,101,120,105,115,116,32,97,110,100,32,97,116,111,109,115,32,97,114,101,32,110,111,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,99,111,110,115,105,100,101,114,32,119,104,101,116,104,101,114,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,50>>]},<<32,105,115,32,97,32,98,101,116,116,101,114,32,111,112,116,105,111,110,32,116,104,97,110,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,97,116,111,109,40,60,60,34,69,114,108,97,110,103,34,62,62,44,32,108,97,116,105,110,49,41,46,10,39,69,114,108,97,110,103,39>>]}]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,97,116,111,109,40,60,60,49,48,50,52,47,117,116,102,56,62,62,44,32,117,116,102,56,41,46,10,39,208,128,39>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,49,51>>,signature => [{attribute,433,spec,{{binary_to_atom,2},[{type,433,bounded_fun,[{type,433,'fun',[{type,433,product,[{var,433,'Binary'},{var,433,'Encoding'}]},{type,433,atom,[]}]},[{type,434,constraint,[{atom,434,is_subtype},[{var,434,'Binary'},{type,434,binary,[]}]]},{type,435,constraint,[{atom,435,is_subtype},[{var,435,'Encoding'},{type,435,union,[{atom,435,latin1},{atom,435,unicode},{atom,435,utf8}]}]]}]]}]}}]}},{{function,binary_to_existing_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,440}],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109>>]}]},<<32>>,{code,[],[<<40,66,105,110,97,114,121,44,32,117,116,102,56,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,54>>,signature => [{attribute,440,spec,{{binary_to_existing_atom,1},[{type,440,bounded_fun,[{type,440,'fun',[{type,440,product,[{var,440,'Binary'}]},{type,440,atom,[]}]},[{type,441,constraint,[{atom,441,is_subtype},[{var,441,'Binary'},{type,441,binary,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,binary_to_existing_atom,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,450}],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,50>>],#{<<101,110>> => [{p,[],[<<65,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]}]},<<44,32,98,117,116,32,116,104,101,32,97,116,111,109,32,109,117,115,116,32,101,120,105,115,116,46>>]},{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,104,97,115,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,111,110,102,105,103,117,114,97,98,108,101,32,108,105,109,105,116>>]},<<32,102,111,114,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,101,120,105,115,116,44,32,97,110,100,32,97,116,111,109,115,32,97,114,101,32,110,111,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,105,115,32,110,111,116,32,115,97,102,101,32,116,111,32,99,114,101,97,116,101,32,109,97,110,121,32,97,116,111,109,115,32,102,114,111,109,32,98,105,110,97,114,105,101,115,32,116,104,97,116,32,99,111,109,101,32,102,114,111,109,32,97,110,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,105,108,101,32,102,101,116,99,104,101,100,32,102,114,111,109,32,116,104,101,32,73,110,116,101,114,110,101,116,41,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]}]},<<46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,104,117,115,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,111,112,116,105,111,110,32,119,104,101,110,32,116,104,101,32,105,110,112,117,116,32,98,105,110,97,114,121,32,99,111,109,101,115,32,102,114,111,109,32,97,110,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,46>>]},{p,[],[<<65,110,32,97,116,111,109,32,101,120,105,115,116,115,32,105,110,32,97,110,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,119,104,101,110,32,105,110,99,108,117,100,101,100,32,105,110,32,97,32,108,111,97,100,101,100,32,69,114,108,97,110,103,32,109,111,100,117,108,101,32,111,114,32,119,104,101,110,32,99,114,101,97,116,101,100,32,112,114,111,103,114,97,109,109,97,116,105,99,97,108,108,121,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,98,121,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]},<<41,46,32,83,101,101,32,116,104,101,32,110,101,120,116,32,110,111,116,101,32,102,111,114,32,97,110,32,101,120,97,109,112,108,101,32,111,102,32,119,104,101,110,32,97,110,32,97,116,111,109,32,101,120,105,115,116,115,32,105,110,32,116,104,101,32,115,111,117,114,99,101,32,99,111,100,101,32,102,111,114,32,97,110,32,69,114,108,97,110,103,32,109,111,100,117,108,101,32,98,117,116,32,110,111,116,32,105,110,32,116,104,101,32,99,111,109,112,105,108,101,100,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,115,97,109,101,32,109,111,100,117,108,101,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,97,116,111,109,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,99,111,109,112,105,108,101,114,32,109,97,121,32,111,112,116,105,109,105,122,101,32,97,119,97,121,32,97,116,111,109,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,111,109,112,105,108,101,114,32,119,105,108,108,32,114,101,119,114,105,116,101,32>>,{code,[],[<<97,116,111,109,95,116,111,95,108,105,115,116,40,115,111,109,101,95,97,116,111,109,41>>]},<<32,116,111,32>>,{code,[],[<<34,115,111,109,101,95,97,116,111,109,34>>]},<<46,32,73,102,32,116,104,97,116,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,104,101,32,111,110,108,121,32,109,101,110,116,105,111,110,32,111,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,111,109,101,95,97,116,111,109>>]},<<32,105,110,32,116,104,101,32,99,111,110,116,97,105,110,105,110,103,32,109,111,100,117,108,101,44,32,116,104,101,32,97,116,111,109,32,119,105,108,108,32,110,111,116,32,98,101,32,99,114,101,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32,108,111,97,100,101,100,44,32,97,110,100,32,97,32,115,117,98,115,101,113,117,101,110,116,32,99,97,108,108,32,116,111,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,40,60,60,34,115,111,109,101,95,97,116,111,109,34,62,62,44,32,117,116,102,56,41>>]},<<32,119,105,108,108,32,102,97,105,108,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,97,110,32,97,116,111,109,32,110,97,109,101,32,105,115,32,108,105,109,105,116,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,54,55>>,signature => [{attribute,450,spec,{{binary_to_existing_atom,2},[{type,450,bounded_fun,[{type,450,'fun',[{type,450,product,[{var,450,'Binary'},{var,450,'Encoding'}]},{type,450,atom,[]}]},[{type,451,constraint,[{atom,451,is_subtype},[{var,451,'Binary'},{type,451,binary,[]}]]},{type,452,constraint,[{atom,452,is_subtype},[{var,452,'Encoding'},{type,452,union,[{atom,452,latin1},{atom,452,unicode},{atom,452,utf8}]}]]}]]}]}}]}},{{function,binary_to_float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,457}],[<<98,105,110,97,114,121,95,116,111,95,102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,102,108,111,97,116,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,102,108,111,97,116,40,60,60,34,50,46,50,48,49,55,55,54,52,101,43,48,34,62,62,41,46,10,50,46,50,48,49,55,55,54,52>>]}]},{p,[],[<<84,104,101,32,102,108,111,97,116,32,115,116,114,105,110,103,32,102,111,114,109,97,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,102,111,114,109,97,116,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,102,108,111,97,116,32,108,105,116,101,114,97,108,115>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,97,116,32,117,110,100,101,114,115,99,111,114,101,115,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,102,108,111,97,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,49,51>>,signature => [{attribute,457,spec,{{binary_to_float,1},[{type,457,bounded_fun,[{type,457,'fun',[{type,457,product,[{var,457,'Binary'}]},{type,457,float,[]}]},[{type,458,constraint,[{atom,458,is_subtype},[{var,458,'Binary'},{type,458,binary,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,binary_to_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,463}],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,40,60,60,34,49,50,51,34,62,62,41,46,10,49,50,51>>]}]},{p,[],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,49>>]},<<32,97,99,99,101,112,116,115,32,116,104,101,32,115,97,109,101,32,115,116,114,105,110,103,32,102,111,114,109,97,116,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,49>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,49>>,signature => [{attribute,463,spec,{{binary_to_integer,1},[{type,463,bounded_fun,[{type,463,'fun',[{type,463,product,[{var,463,'Binary'}]},{type,463,integer,[]}]},[{type,464,constraint,[{atom,464,is_subtype},[{var,464,'Binary'},{type,464,binary,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,binary_to_integer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,469}],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,40,60,60,34,51,70,70,34,62,62,44,32,49,54,41,46,10,49,48,50,51>>]}]},{p,[],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,50>>]},<<32,97,99,99,101,112,116,115,32,116,104,101,32,115,97,109,101,32,115,116,114,105,110,103,32,102,111,114,109,97,116,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,50>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,52,56>>,signature => [{attribute,469,spec,{{binary_to_integer,2},[{type,469,bounded_fun,[{type,469,'fun',[{type,469,product,[{var,469,'Binary'},{var,469,'Base'}]},{type,469,integer,[]}]},[{type,470,constraint,[{atom,470,is_subtype},[{var,470,'Binary'},{type,470,binary,[]}]]},{type,471,constraint,[{atom,471,is_subtype},[{var,471,'Base'},{type,471,range,[{integer,471,2},{integer,471,36}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,binary_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,476}],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,121,116,101,115,32,111,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,54,54>>,signature => [{attribute,476,spec,{{binary_to_list,1},[{type,476,bounded_fun,[{type,476,'fun',[{type,476,product,[{var,476,'Binary'}]},{type,476,list,[{type,476,byte,[]}]}]},[{type,477,constraint,[{atom,477,is_subtype},[{var,477,'Binary'},{type,477,binary,[]}]]}]]}]}}]}},{{function,binary_to_list,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,482}],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<65,115,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,49>>]},<<44,32,98,117,116,32,114,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,121,116,101,115,32,102,114,111,109,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<83,116,97,114,116>>]},<<32,116,111,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<83,116,111,112>>]},<<32,105,110,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46,32,84,104,101,32,112,111,115,105,116,105,111,110,115,32,105,110,32,116,104,101,32,98,105,110,97,114,121,32,97,114,101,32,110,117,109,98,101,114,101,100,32,115,116,97,114,116,105,110,103,32,102,114,111,109,32,49,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{em,[],[<<84,104,101,32,111,110,101,45,98,97,115,101,100,32,105,110,100,101,120,105,110,103,32,102,111,114,32,98,105,110,97,114,105,101,115,32,117,115,101,100,32,98,121,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46>>]},<<32,78,101,119,32,99,111,100,101,32,105,115,32,116,111,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,98,105,110,97,114,121,35,98,105,110,95,116,111,95,108,105,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,58,98,105,110,95,116,111,95,108,105,115,116,47,51>>]}]},<<32,105,110,32,83,84,68,76,73,66,32,105,110,115,116,101,97,100,46,32,65,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,109,111,100,117,108,101,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,99,111,110,115,105,115,116,101,110,116,108,121,32,117,115,101,32,122,101,114,111,45,98,97,115,101,100,32,105,110,100,101,120,105,110,103,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,53>>,signature => [{attribute,482,spec,{{binary_to_list,3},[{type,482,bounded_fun,[{type,482,'fun',[{type,482,product,[{var,482,'Binary'},{var,482,'Start'},{var,482,'Stop'}]},{type,482,list,[{type,482,byte,[]}]}]},[{type,483,constraint,[{atom,483,is_subtype},[{var,483,'Binary'},{type,483,binary,[]}]]},{type,484,constraint,[{atom,484,is_subtype},[{var,484,'Start'},{type,484,pos_integer,[]}]]},{type,485,constraint,[{atom,485,is_subtype},[{var,485,'Stop'},{type,485,pos_integer,[]}]]}]]}]}}]}},{{function,binary_to_term,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,490}],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,69,114,108,97,110,103,32,116,101,114,109,32,116,104,97,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,100,101,99,111,100,105,110,103,32,98,105,110,97,114,121,32,111,98,106,101,99,116,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,119,104,105,99,104,32,109,117,115,116,32,98,101,32,101,110,99,111,100,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,108,95,101,120,116,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116>>]},<<46>>]},{pre,[],[{code,[],[<<62,32,66,105,110,32,61,32,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,104,101,108,108,111,41,46,10,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,62,62,10,62,32,104,101,108,108,111,32,61,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,66,105,110,41,46,10,104,101,108,108,111>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<87,104,101,110,32,100,101,99,111,100,105,110,103,32,98,105,110,97,114,105,101,115,32,102,114,111,109,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,115,44,32,99,111,110,115,105,100,101,114,32,117,115,105,110,103,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>]},<<32,116,111,32,112,114,101,118,101,110,116,32,68,101,110,105,97,108,32,111,102,32,83,101,114,118,105,99,101,32,97,116,116,97,99,107,115,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,55>>,signature => [{attribute,490,spec,{{binary_to_term,1},[{type,490,bounded_fun,[{type,490,'fun',[{type,490,product,[{var,490,'Binary'}]},{type,490,term,[]}]},[{type,491,constraint,[{atom,491,is_subtype},[{var,491,'Binary'},{user_type,491,ext_binary,[]}]]}]]}]}}]}},{{function,binary_to_term,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,496}],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>],#{<<101,110>> => [{p,[],[<<65,115,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]},<<44,32,98,117,116,32,116,97,107,101,115,32,116,104,101,115,101,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,97,102,101>>]}]},{dd,[],[{p,[],[<<85,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,119,104,101,110,32,114,101,99,101,105,118,105,110,103,32,98,105,110,97,114,105,101,115,32,102,114,111,109,32,97,110,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,46>>]},{p,[],[<<87,104,101,110,32,101,110,97,98,108,101,100,44,32,105,116,32,112,114,101,118,101,110,116,115,32,100,101,99,111,100,105,110,103,32,100,97,116,97,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,97,116,116,97,99,107,32,116,104,101,32,69,114,108,97,110,103,32,115,121,115,116,101,109,46,32,73,110,32,116,104,101,32,101,118,101,110,116,32,111,102,32,114,101,99,101,105,118,105,110,103,32,117,110,115,97,102,101,32,100,97,116,97,44,32,100,101,99,111,100,105,110,103,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,114,114,111,114,46>>]},{p,[],[<<84,104,105,115,32,112,114,101,118,101,110,116,115,32,99,114,101,97,116,105,111,110,32,111,102,32,110,101,119,32,97,116,111,109,115,32,100,105,114,101,99,116,108,121,44,32,99,114,101,97,116,105,111,110,32,111,102,32,110,101,119,32,97,116,111,109,115,32,105,110,100,105,114,101,99,116,108,121,32,40,97,115,32,116,104,101,121,32,97,114,101,32,101,109,98,101,100,100,101,100,32,105,110,32,99,101,114,116,97,105,110,32,115,116,114,117,99,116,117,114,101,115,44,32,115,117,99,104,32,97,115,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,44,32,114,101,102,115,44,32,97,110,100,32,102,117,110,115,41,44,32,97,110,100,32,99,114,101,97,116,105,111,110,32,111,102,32,110,101,119,32,101,120,116,101,114,110,97,108,32,102,117,110,99,116,105,111,110,32,114,101,102,101,114,101,110,99,101,115,46,32,78,111,110,101,32,111,102,32,116,104,111,115,101,32,114,101,115,111,117,114,99,101,115,32,97,114,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,44,32,115,111,32,117,110,99,104,101,99,107,101,100,32,99,114,101,97,116,105,111,110,32,111,102,32,116,104,101,109,32,99,97,110,32,101,120,104,97,117,115,116,32,97,118,97,105,108,97,98,108,101,32,109,101,109,111,114,121,46>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,60,60,49,51,49,44,49,48,48,44,48,44,53,44,34,104,101,108,108,111,34,62,62,44,32,91,115,97,102,101,93,41,46,10,42,42,32,101,120,99,101,112,116,105,111,110,32,101,114,114,111,114,58,32,98,97,100,32,97,114,103,117,109,101,110,116,10,62,32,104,101,108,108,111,46,10,104,101,108,108,111,10,62,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,60,60,49,51,49,44,49,48,48,44,48,44,53,44,34,104,101,108,108,111,34,62,62,44,32,91,115,97,102,101,93,41,46,10,104,101,108,108,111>>]}]}]},{dt,[],[{code,[],[<<117,115,101,100>>]}]},{dd,[],[{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<123,84,101,114,109,44,32,85,115,101,100,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<85,115,101,100>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,97,99,116,117,97,108,108,121,32,114,101,97,100,32,102,114,111,109,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46>>]},{pre,[],[{code,[],[<<62,32,73,110,112,117,116,32,61,32,60,60,49,51,49,44,49,48,48,44,48,44,53,44,34,104,101,108,108,111,34,44,34,119,111,114,108,100,34,62,62,46,10,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,44,49,49,57,44,49,49,49,44,49,49,52,44,49,48,56,44,49,48,48,62,62,10,62,32,123,84,101,114,109,44,32,85,115,101,100,125,32,61,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,73,110,112,117,116,44,32,91,117,115,101,100,93,41,46,10,123,104,101,108,108,111,44,32,57,125,10,62,32,115,112,108,105,116,95,98,105,110,97,114,121,40,73,110,112,117,116,44,32,85,115,101,100,41,46,10,123,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,62,62,44,32,60,60,34,119,111,114,108,100,34,62,62,125>>]}]}]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<115,97,102,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,110,100,32,117,110,115,97,102,101,32,100,97,116,97,32,105,115,32,100,101,99,111,100,101,100,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,51>>,signature => [{attribute,496,spec,{{binary_to_term,2},[{type,496,bounded_fun,[{type,496,'fun',[{type,496,product,[{var,496,'Binary'},{var,496,'Opts'}]},{type,496,union,[{type,496,term,[]},{type,496,tuple,[{type,496,term,[]},{var,496,'Used'}]}]}]},[{type,497,constraint,[{atom,497,is_subtype},[{var,497,'Binary'},{user_type,497,ext_binary,[]}]]},{type,498,constraint,[{atom,498,is_subtype},[{var,498,'Opt'},{type,498,union,[{atom,498,safe},{atom,498,used}]}]]},{type,499,constraint,[{atom,499,is_subtype},[{var,499,'Opts'},{type,499,list,[{var,499,'Opt'}]}]]},{type,500,constraint,[{atom,500,is_subtype},[{var,500,'Used'},{type,500,pos_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,51,66,48,52>>}},{{function,bit_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,506}],[<<98,105,116,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,116,104,97,116,32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,105,116,115,32,111,102,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,116,95,115,105,122,101,40,60,60,52,51,51,58,49,54,44,51,58,51,62,62,41,46,10,49,57,10,62,32,98,105,116,95,115,105,122,101,40,60,60,49,44,50,44,51,62,62,41,46,10,50,52>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,55>>,signature => [{attribute,506,spec,{{bit_size,1},[{type,506,bounded_fun,[{type,506,'fun',[{type,506,product,[{var,506,'Bitstring'}]},{type,506,non_neg_integer,[]}]},[{type,507,constraint,[{atom,507,is_subtype},[{var,507,'Bitstring'},{type,507,bitstring,[]}]]}]]}]}}]}},{{function,bitstring_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,512}],[<<98,105,116,115,116,114,105,110,103,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,121,116,101,115,32,111,102,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,105,116,115,32,105,110,32,116,104,101,32,98,105,110,97,114,121,32,105,115,32,110,111,116,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,44,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,108,105,115,116,32,105,115,32,97,32,98,105,116,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,49,45,55,32,98,105,116,115,46,32,69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,98,105,116,115,116,114,105,110,103,95,116,111,95,108,105,115,116,40,60,60,52,51,51,58,49,54,62,62,41,46,10,91,49,44,49,55,55,93>>]}]},{pre,[],[{code,[],[<<62,32,98,105,116,115,116,114,105,110,103,95,116,111,95,108,105,115,116,40,60,60,52,51,51,58,49,54,44,51,58,51,62,62,41,46,10,91,49,44,49,55,55,44,60,60,51,58,51,62,62,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,50>>,signature => [{attribute,512,spec,{{bitstring_to_list,1},[{type,512,bounded_fun,[{type,512,'fun',[{type,512,product,[{var,512,'Bitstring'}]},{type,512,list,[{type,512,union,[{type,512,byte,[]},{type,512,bitstring,[]}]}]}]},[{type,513,constraint,[{atom,513,is_subtype},[{var,513,'Bitstring'},{type,513,bitstring,[]}]]}]]}]}}]}},{{function,bump_reductions,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,518}],[<<98,117,109,112,95,114,101,100,117,99,116,105,111,110,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,105,115,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,32,102,117,110,99,116,105,111,110,32,105,110,99,114,101,109,101,110,116,115,32,116,104,101,32,114,101,100,117,99,116,105,111,110,32,99,111,117,110,116,101,114,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,73,110,32,116,104,101,32,66,101,97,109,32,101,109,117,108,97,116,111,114,44,32,116,104,101,32,114,101,100,117,99,116,105,111,110,32,99,111,117,110,116,101,114,32,105,115,32,110,111,114,109,97,108,108,121,32,105,110,99,114,101,109,101,110,116,101,100,32,98,121,32,111,110,101,32,102,111,114,32,101,97,99,104,32,102,117,110,99,116,105,111,110,32,97,110,100,32,66,73,70,32,99,97,108,108,46,32,65,32,99,111,110,116,101,120,116,32,115,119,105,116,99,104,32,105,115,32,102,111,114,99,101,100,32,119,104,101,110,32,116,104,101,32,99,111,117,110,116,101,114,32,114,101,97,99,104,101,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,114,101,100,117,99,116,105,111,110,115,32,102,111,114,32,97,32,112,114,111,99,101,115,115,32,40,52,48,48,48,32,114,101,100,117,99,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103,47,79,84,80,32,49,57,46,50,32,97,110,100,32,108,97,116,101,114,41,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,99,97,110,32,98,101,32,114,101,109,111,118,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,66,101,97,109,32,109,97,99,104,105,110,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,119,97,114,110,105,110,103,46,32,73,116,32,105,115,32,117,110,108,105,107,101,108,121,32,116,111,32,98,101,32,105,109,112,108,101,109,101,110,116,101,100,32,105,110,32,111,116,104,101,114,32,69,114,108,97,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,48,57>>,signature => [{attribute,518,spec,{{erlang,bump_reductions,1},[{type,518,bounded_fun,[{type,518,'fun',[{type,518,product,[{var,518,'Reductions'}]},{atom,518,true}]},[{type,519,constraint,[{atom,519,is_subtype},[{var,519,'Reductions'},{type,519,pos_integer,[]}]]}]]}]}}]}},{{function,byte_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,525}],[<<98,121,116,101,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,116,104,97,116,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,110,101,101,100,101,100,32,116,111,32,99,111,110,116,97,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<46,32,84,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,105,116,115,32,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<32,105,115,32,110,111,116,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,44,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,115,32,114,111,117,110,100,101,100,32>>,{em,[],[<<117,112>>]},<<46,32,69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,98,121,116,101,95,115,105,122,101,40,60,60,52,51,51,58,49,54,44,51,58,51,62,62,41,46,10,51,10,62,32,98,121,116,101,95,115,105,122,101,40,60,60,49,44,50,44,51,62,62,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,50,55>>,signature => [{attribute,525,spec,{{byte_size,1},[{type,525,bounded_fun,[{type,525,'fun',[{type,525,product,[{var,525,'Bitstring'}]},{type,525,non_neg_integer,[]}]},[{type,526,constraint,[{atom,526,is_subtype},[{var,526,'Bitstring'},{type,526,bitstring,[]}]]}]]}]}}]}},{{function,cancel_timer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,537}],[<<99,97,110,99,101,108,95,116,105,109,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<67,97,110,99,101,108,115,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,40,84,105,109,101,114,82,101,102,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,52,52>>,signature => [{attribute,537,spec,{{erlang,cancel_timer,1},[{type,537,bounded_fun,[{type,537,'fun',[{type,537,product,[{var,537,'TimerRef'}]},{var,537,'Result'}]},[{type,538,constraint,[{atom,538,is_subtype},[{var,538,'TimerRef'},{type,538,reference,[]}]]},{type,539,constraint,[{atom,539,is_subtype},[{var,539,'Time'},{type,539,non_neg_integer,[]}]]},{type,540,constraint,[{atom,540,is_subtype},[{var,540,'Result'},{type,540,union,[{var,540,'Time'},{atom,540,false}]}]]}]]}]}}]}},{{function,cancel_timer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,546}],[<<99,97,110,99,101,108,95,116,105,109,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<67,97,110,99,101,108,115,32,97,32,116,105,109,101,114,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114>>]}]},<<46,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,105,100,101,110,116,105,102,105,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,119,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32,116,104,101,32,66,73,70,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,116,105,109,101,114,46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,65,115,121,110,99,125>>]}]},{dd,[],[{p,[],[<<65,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,99,97,110,99,101,108,108,97,116,105,111,110,46,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,119,104,105,99,104,32,99,97,117,115,101,115,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,32,116,111,32,98,101,32,112,101,114,102,111,114,109,101,100,32,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,99,97,110,99,101,108,32,111,112,101,114,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,84,104,97,116,32,105,115,44,32>>,{code,[],[<<99,97,110,99,101,108,95,116,105,109,101,114,40,41>>]},<<32,115,101,110,100,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,99,97,110,99,101,108,108,97,116,105,111,110,32,116,111,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,116,104,101,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,105,110,102,111,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<82,101,113,117,101,115,116,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,111,102,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,119,104,105,99,104,32,109,101,97,110,115,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,103,105,118,101,110,46,32,87,104,101,110,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,32,105,115,32,103,105,118,101,110,46>>]},{ul,[],[{li,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<58,32,105,102,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,40,41>>]},<<46,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<111,107>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{li,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<58,32,105,102,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,99,97,110,99,101,108,95,116,105,109,101,114,44,32,84,105,109,101,114,82,101,102,44,32,82,101,115,117,108,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,40,41>>]},<<32,119,104,101,110,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,101,114,102,111,114,109,101,100,44,32,111,116,104,101,114,119,105,115,101,32,110,111,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,46>>]}]}]}]}]},{p,[],[<<77,111,114,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,109,97,121,32,98,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,105,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,32,108,101,102,116,32,117,110,116,105,108,32,116,104,101,32,99,97,110,99,101,108,101,100,32,116,105,109,101,114,32,119,111,117,108,100,32,104,97,118,101,32,101,120,112,105,114,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,97,32,116,105,109,101,114,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,99,111,117,108,100,32,110,111,116,32,98,101,32,102,111,117,110,100,46,32,84,104,105,115,32,99,97,110,32,98,101,32,101,105,116,104,101,114,32,98,101,99,97,117,115,101,32,116,104,101,32,116,105,109,101,114,32,104,97,100,32,101,120,112,105,114,101,100,44,32,97,108,114,101,97,100,121,32,104,97,100,32,98,101,101,110,32,99,97,110,99,101,108,101,100,44,32,111,114,32,98,101,99,97,117,115,101,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,110,101,118,101,114,32,99,111,114,114,101,115,112,111,110,100,101,100,32,116,111,32,97,32,116,105,109,101,114,46,32,69,118,101,110,32,105,102,32,116,104,101,32,116,105,109,101,114,32,104,97,100,32,101,120,112,105,114,101,100,44,32,105,116,32,100,111,101,115,32,110,111,116,32,116,101,108,108,32,121,111,117,32,105,102,32,116,104,101,32,116,105,109,101,45,111,117,116,32,109,101,115,115,97,103,101,32,104,97,115,32,97,114,114,105,118,101,100,32,97,116,32,105,116,115,32,100,101,115,116,105,110,97,116,105,111,110,32,121,101,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,32,99,97,110,32,98,101,32,99,111,45,108,111,99,97,116,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32,115,99,104,101,100,117,108,101,114,32,116,104,97,110,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32,73,102,32,115,111,44,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,97,107,101,115,32,109,117,99,104,32,108,111,110,103,101,114,32,116,105,109,101,32,116,104,97,110,32,105,102,32,105,116,32,105,115,32,108,111,99,97,116,101,100,32,108,111,99,97,108,108,121,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,105,110,32,99,114,105,116,105,99,97,108,32,112,97,116,104,44,32,97,110,100,32,99,97,110,32,100,111,32,111,116,104,101,114,32,116,104,105,110,103,115,32,119,104,105,108,101,32,119,97,105,116,105,110,103,32,102,111,114,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,44,32,111,114,32,105,115,32,110,111,116,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,44,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,116,114,117,101,125>>]},<<46,32,73,102,32,117,115,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,102,97,108,115,101,125>>]},<<44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,98,108,111,99,107,115,32,117,110,116,105,108,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,101,114,102,111,114,109,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,47,52>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,47,52>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,97,100,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,52>>,signature => [{attribute,546,spec,{{erlang,cancel_timer,2},[{type,546,bounded_fun,[{type,546,'fun',[{type,546,product,[{var,546,'TimerRef'},{var,546,'Options'}]},{type,546,union,[{var,546,'Result'},{atom,546,ok}]}]},[{type,547,constraint,[{atom,547,is_subtype},[{var,547,'TimerRef'},{type,547,reference,[]}]]},{type,548,constraint,[{atom,548,is_subtype},[{var,548,'Async'},{type,548,boolean,[]}]]},{type,549,constraint,[{atom,549,is_subtype},[{var,549,'Info'},{type,549,boolean,[]}]]},{type,550,constraint,[{atom,550,is_subtype},[{var,550,'Option'},{type,550,union,[{type,550,tuple,[{atom,550,async},{var,550,'Async'}]},{type,550,tuple,[{atom,550,info},{var,550,'Info'}]}]}]]},{type,551,constraint,[{atom,551,is_subtype},[{var,551,'Options'},{type,551,list,[{var,551,'Option'}]}]]},{type,552,constraint,[{atom,552,is_subtype},[{var,552,'Time'},{type,552,non_neg_integer,[]}]]},{type,553,constraint,[{atom,553,is_subtype},[{var,553,'Result'},{type,553,union,[{var,553,'Time'},{atom,553,false}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,ceil,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,560}],[<<99,101,105,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,105,110,116,101,103,101,114,32,110,111,116,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,99,101,105,108,40,53,46,53,41,46,10,54>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,51,54>>,signature => [{attribute,560,spec,{{ceil,1},[{type,560,bounded_fun,[{type,560,'fun',[{type,560,product,[{var,560,'Number'}]},{type,560,integer,[]}]},[{type,561,constraint,[{atom,561,is_subtype},[{var,561,'Number'},{type,561,number,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,check_old_code,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,566}],[<<99,104,101,99,107,95,111,108,100,95,99,111,100,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,104,97,115,32,111,108,100,32,99,111,100,101,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,52,57>>,signature => [{attribute,566,spec,{{check_old_code,1},[{type,566,bounded_fun,[{type,566,'fun',[{type,566,product,[{var,566,'Module'}]},{type,566,boolean,[]}]},[{type,567,constraint,[{atom,567,is_subtype},[{var,567,'Module'},{type,567,module,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66,48,52>>}},{{function,check_process_code,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,572}],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,40,80,105,100,44,32,77,111,100,117,108,101,44,32,91,93,41>>]},<<32>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,54,48>>,signature => [{attribute,572,spec,{{check_process_code,2},[{type,572,bounded_fun,[{type,572,'fun',[{type,572,product,[{var,572,'Pid'},{var,572,'Module'}]},{var,572,'CheckResult'}]},[{type,573,constraint,[{atom,573,is_subtype},[{var,573,'Pid'},{type,573,pid,[]}]]},{type,574,constraint,[{atom,574,is_subtype},[{var,574,'Module'},{type,574,module,[]}]]},{type,575,constraint,[{atom,575,is_subtype},[{var,575,'CheckResult'},{type,575,boolean,[]}]]}]]}]}}]}},{{function,check_process_code,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,584}],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,104,101,99,107,115,32,105,102,32,116,104,101,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,101,99,117,116,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,98,111,111,108,101,97,110,40,41,125>>]}]},{dd,[],[{p,[],[<<68,101,116,101,114,109,105,110,101,115,32,105,102,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,97,108,108,111,119,101,100,32,119,104,101,110,32,112,101,114,102,111,114,109,105,110,103,32,116,104,101,32,111,112,101,114,97,116,105,111,110,46,32,73,102,32>>,{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,102,97,108,115,101,125>>]},<<32,105,115,32,112,97,115,115,101,100,44,32,97,110,100,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,110,101,101,100,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,97,98,111,114,116,101,100,32,40,115,101,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32>>,{code,[],[<<67,104,101,99,107,82,101,115,117,108,116>>]},<<32,98,101,108,111,119,41,46,32,84,104,101,32,100,101,102,97,117,108,116,32,105,115,32,116,111,32,97,108,108,111,119,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,44,32,116,104,97,116,32,105,115,44,32>>,{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,116,114,117,101,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,82,101,113,117,101,115,116,73,100,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,51>>]},<<32,114,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,115,101,110,116,46,32,87,104,101,110,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,44,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,97,108,108,101,100,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,112,97,115,115,101,100,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,44,32,82,101,113,117,101,115,116,73,100,44,32,67,104,101,99,107,82,101,115,117,108,116,125>>]},<<46>>]}]}]},{p,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<115,101,108,102,40,41>>]},<<44,32,97,110,100,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,116,32,111,110,99,101,46,32,79,116,104,101,114,119,105,115,101,32,97,32,114,101,113,117,101,115,116,32,102,111,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,97,110,100,32,105,115,32,104,97,110,100,108,101,100,32,119,104,101,110,32,97,112,112,114,111,112,114,105,97,116,101,46,32,73,102,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,98,108,111,99,107,115,32,117,110,116,105,108,32>>,{code,[],[<<67,104,101,99,107,82,101,115,117,108,116>>]},<<32,105,115,32,97,118,97,105,108,97,98,108,101,32,97,110,100,32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<67,104,101,99,107,82,101,115,117,108,116>>]},<<32,105,110,102,111,114,109,115,32,97,98,111,117,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,114,101,113,117,101,115,116,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,101,99,117,116,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,99,97,108,108,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,101,99,117,116,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,99,111,110,116,97,105,110,115,32,102,117,110,115,32,116,104,97,116,32,114,101,102,101,114,101,110,99,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,101,99,117,116,101,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,98,111,114,116,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,101,114,97,116,105,111,110,32,119,97,115,32,97,98,111,114,116,101,100,44,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,110,101,101,100,101,100,32,116,111,32,98,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,114,101,115,117,108,116,44,32,97,110,100,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,119,97,115,32,114,101,113,117,101,115,116,101,100,32,98,121,32,112,97,115,115,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,102,97,108,115,101,125>>]},<<46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<85,112,32,117,110,116,105,108,32,69,82,84,83,32,118,101,114,115,105,111,110,32,56,46,42,44,32,116,104,101,32,99,104,101,99,107,32,112,114,111,99,101,115,115,32,99,111,100,101,32,111,112,101,114,97,116,105,111,110,32,99,104,101,99,107,115,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,116,104,101,32,111,108,100,32,99,111,100,101,46,32,84,104,97,116,32,105,115,44,32,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,40,101,46,103,46,32,114,101,116,117,114,110,32,97,100,100,114,101,115,115,101,115,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,41,44,32,105,110,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,40>>,{code,[],[<<102,117,110>>]},<<115,32,105,110,32,112,114,111,99,101,115,115,32,99,111,110,116,101,120,116,41,44,32,97,110,100,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,108,105,116,101,114,97,108,115,32,105,110,32,116,104,101,32,99,111,100,101,46>>]},{p,[],[<<65,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,57,46,48,44,32,116,104,101,32,99,104,101,99,107,32,112,114,111,99,101,115,115,32,99,111,100,101,32,111,112,101,114,97,116,105,111,110,32,111,110,108,121,32,99,104,101,99,107,115,32,102,111,114,32,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,116,104,101,32,99,111,100,101,46,32,73,110,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,118,105,97,32>>,{code,[],[<<102,117,110>>]},<<115,32,119,105,108,108,32,98,101,32,105,103,110,111,114,101,100,46,32,73,102,32,115,117,99,104,32>>,{code,[],[<<102,117,110>>]},<<115,32,101,120,105,115,116,32,97,110,100,32,97,114,101,32,117,115,101,100,32,97,102,116,101,114,32,97,32,112,117,114,103,101,32,111,102,32,116,104,101,32,111,108,100,32,99,111,100,101,44,32,97,110,32,101,120,99,101,112,116,105,111,110,32,119,105,108,108,32,98,101,32,114,97,105,115,101,100,32,117,112,111,110,32,117,115,97,103,101,32,40,115,97,109,101,32,97,115,32,116,104,101,32,99,97,115,101,32,119,104,101,110,32,116,104,101,32>>,{code,[],[<<102,117,110>>]},<<32,105,115,32,114,101,99,101,105,118,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,97,102,116,101,114,32,116,104,101,32,112,117,114,103,101,41,46,32,76,105,116,101,114,97,108,115,32,119,105,108,108,32,98,101,32,116,97,107,101,110,32,99,97,114,101,32,111,102,32,40,99,111,112,105,101,100,41,32,97,116,32,97,32,108,97,116,101,114,32,115,116,97,103,101,46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,99,97,110,32,97,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,56,46,49,32,98,101,32,101,110,97,98,108,101,100,32,119,104,101,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,105,110,115,116,97,108,108,97,116,105,111,110,95,103,117,105,100,101,58,73,78,83,84,65,76,76,35,65,100,118,97,110,99,101,100,45,99,111,110,102,105,103,117,114,97,116,105,111,110,45,97,110,100,45,98,117,105,108,100,45,111,102,45,69,114,108,97,110,103,79,84,80,95,67,111,110,102,105,103,117,114,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<98,117,105,108,100,105,110,103,32,79,84,80>>]},<<44,32,97,110,100,32,119,105,108,108,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,98,101,32,101,110,97,98,108,101,100,32,105,102,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,32,115,117,112,112,111,114,116,32,105,115,32,101,110,97,98,108,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,55,49>>,signature => [{attribute,584,spec,{{check_process_code,3},[{type,584,bounded_fun,[{type,584,'fun',[{type,584,product,[{var,584,'Pid'},{var,584,'Module'},{var,584,'OptionList'}]},{type,584,union,[{var,584,'CheckResult'},{atom,584,async}]}]},[{type,585,constraint,[{atom,585,is_subtype},[{var,585,'Pid'},{type,585,pid,[]}]]},{type,586,constraint,[{atom,586,is_subtype},[{var,586,'Module'},{type,586,module,[]}]]},{type,587,constraint,[{atom,587,is_subtype},[{var,587,'RequestId'},{type,587,term,[]}]]},{type,588,constraint,[{atom,588,is_subtype},[{var,588,'Option'},{type,588,union,[{type,588,tuple,[{atom,588,async},{var,588,'RequestId'}]},{type,588,tuple,[{atom,588,allow_gc},{type,588,boolean,[]}]}]}]]},{type,589,constraint,[{atom,589,is_subtype},[{var,589,'OptionList'},{type,589,list,[{var,589,'Option'}]}]]},{type,590,constraint,[{atom,590,is_subtype},[{var,590,'CheckResult'},{type,590,union,[{type,590,boolean,[]},{atom,590,aborted}]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,convert_time_unit,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1556}],[<<99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,111,102,32,116,105,109,101,32,117,110,105,116,32>>,{code,[],[<<70,114,111,109,85,110,105,116>>]},<<32,116,111,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<67,111,110,118,101,114,116,101,100,84,105,109,101>>]},<<32,118,97,108,117,101,32,111,102,32,116,105,109,101,32,117,110,105,116,32>>,{code,[],[<<84,111,85,110,105,116>>]},<<46,32,84,104,101,32,114,101,115,117,108,116,32,105,115,32,114,111,117,110,100,101,100,32,117,115,105,110,103,32,116,104,101,32,102,108,111,111,114,32,102,117,110,99,116,105,111,110,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<89,111,117,32,99,97,110,32,108,111,115,101,32,97,99,99,117,114,97,99,121,32,97,110,100,32,112,114,101,99,105,115,105,111,110,32,119,104,101,110,32,99,111,110,118,101,114,116,105,110,103,32,98,101,116,119,101,101,110,32,116,105,109,101,32,117,110,105,116,115,46,32,84,111,32,109,105,110,105,109,105,122,101,32,115,117,99,104,32,108,111,115,115,44,32,99,111,108,108,101,99,116,32,97,108,108,32,100,97,116,97,32,97,116,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,97,110,100,32,100,111,32,116,104,101,32,99,111,110,118,101,114,115,105,111,110,32,111,110,32,116,104,101,32,101,110,100,32,114,101,115,117,108,116,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,55,52>>,signature => [{attribute,1556,spec,{{erlang,convert_time_unit,3},[{type,1556,bounded_fun,[{type,1556,'fun',[{type,1556,product,[{var,1556,'Time'},{var,1556,'FromUnit'},{var,1556,'ToUnit'}]},{var,1556,'ConvertedTime'}]},[{type,1557,constraint,[{atom,1557,is_subtype},[{var,1557,'Time'},{type,1557,integer,[]}]]},{type,1558,constraint,[{atom,1558,is_subtype},[{var,1558,'ConvertedTime'},{type,1558,integer,[]}]]},{type,1559,constraint,[{atom,1559,is_subtype},[{var,1559,'FromUnit'},{user_type,1559,time_unit,[]}]]},{type,1560,constraint,[{atom,1560,is_subtype},[{var,1560,'ToUnit'},{user_type,1560,time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,crc32,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,602}],[<<99,114,99,51,50,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,117,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,99,114,99,51,50,32,40,73,69,69,69,32,56,48,50,46,51,32,115,116,121,108,101,41,32,99,104,101,99,107,115,117,109,32,102,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,57,50>>,signature => [{attribute,602,spec,{{erlang,crc32,1},[{type,602,bounded_fun,[{type,602,'fun',[{type,602,product,[{var,602,'Data'}]},{type,602,non_neg_integer,[]}]},[{type,603,constraint,[{atom,603,is_subtype},[{var,603,'Data'},{type,603,iodata,[]}]]}]]}]}}]}},{{function,crc32,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,608}],[<<99,114,99,51,50,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,110,116,105,110,117,101,115,32,99,111,109,112,117,116,105,110,103,32,116,104,101,32,99,114,99,51,50,32,99,104,101,99,107,115,117,109,32,98,121,32,99,111,109,98,105,110,105,110,103,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,104,101,99,107,115,117,109,44,32>>,{code,[],[<<79,108,100,67,114,99>>]},<<44,32,119,105,116,104,32,116,104,101,32,99,104,101,99,107,115,117,109,32,111,102,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,88,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<89>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,91,68,97,116,97,49,44,68,97,116,97,50,93,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,48,49>>,signature => [{attribute,608,spec,{{erlang,crc32,2},[{type,608,bounded_fun,[{type,608,'fun',[{type,608,product,[{var,608,'OldCrc'},{var,608,'Data'}]},{type,608,non_neg_integer,[]}]},[{type,609,constraint,[{atom,609,is_subtype},[{var,609,'OldCrc'},{type,609,non_neg_integer,[]}]]},{type,610,constraint,[{atom,610,is_subtype},[{var,610,'Data'},{type,610,iodata,[]}]]}]]}]}}]}},{{function,crc32_combine,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,615}],[<<99,114,99,51,50,95,99,111,109,98,105,110,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32,116,119,111,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,117,116,101,100,32,99,114,99,51,50,32,99,104,101,99,107,115,117,109,115,46,32,84,104,105,115,32,99,111,109,112,117,116,97,116,105,111,110,32,114,101,113,117,105,114,101,115,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,100,97,116,97,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101,32,115,101,99,111,110,100,32,99,104,101,99,107,115,117,109,32,116,111,32,98,101,32,107,110,111,119,110,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,49,41,44,10,90,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,89,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<90>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,50,41,44,10,90,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,95,99,111,109,98,105,110,101,40,88,44,89,44,105,111,108,105,115,116,95,115,105,122,101,40,68,97,116,97,50,41,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,49,56>>,signature => [{attribute,615,spec,{{erlang,crc32_combine,3},[{type,615,bounded_fun,[{type,615,'fun',[{type,615,product,[{var,615,'FirstCrc'},{var,615,'SecondCrc'},{var,615,'SecondSize'}]},{type,615,non_neg_integer,[]}]},[{type,616,constraint,[{atom,616,is_subtype},[{var,616,'FirstCrc'},{type,616,non_neg_integer,[]}]]},{type,617,constraint,[{atom,617,is_subtype},[{var,617,'SecondCrc'},{type,617,non_neg_integer,[]}]]},{type,618,constraint,[{atom,618,is_subtype},[{var,618,'SecondSize'},{type,618,non_neg_integer,[]}]]}]]}]}}]}},{{function,date,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,623}],[<<100,97,116,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,100,97,116,101,32,97,115,32>>,{code,[],[<<123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125>>]},<<46>>]},{p,[],[<<84,104,101,32,116,105,109,101,32,122,111,110,101,32,97,110,100,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,99,111,114,114,101,99,116,105,111,110,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,100,97,116,101,40,41,46,10,123,49,57,57,53,44,50,44,49,57,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,51,55>>,signature => [{attribute,623,spec,{{date,0},[{type,623,bounded_fun,[{type,623,'fun',[{type,623,product,[]},{var,623,'Date'}]},[{type,624,constraint,[{atom,624,is_subtype},[{var,624,'Date'},{remote_type,624,[{atom,624,calendar},{atom,624,date},[]]}]]}]]}]}}]}},{{function,decode_packet,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,629}],[<<100,101,99,111,100,101,95,112,97,99,107,101,116,47,51>>],#{<<101,110>> => [{p,[],[<<68,101,99,111,100,101,115,32,116,104,101,32,98,105,110,97,114,121,32>>,{code,[],[<<66,105,110>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,112,97,99,107,101,116,32,112,114,111,116,111,99,111,108,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<84,121,112,101>>]},<<46,32,83,105,109,105,108,97,114,32,116,111,32,116,104,101,32,112,97,99,107,101,116,32,104,97,110,100,108,105,110,103,32,100,111,110,101,32,98,121,32,115,111,99,107,101,116,115,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<123,112,97,99,107,101,116,44,84,121,112,101,125,46>>]}]},{p,[],[<<73,102,32,97,110,32,101,110,116,105,114,101,32,112,97,99,107,101,116,32,105,115,32,99,111,110,116,97,105,110,101,100,32,105,110,32>>,{code,[],[<<66,105,110>>]},<<44,32,105,116,32,105,115,32,114,101,116,117,114,110,101,100,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,116,104,101,32,114,101,109,97,105,110,100,101,114,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,97,115,32>>,{code,[],[<<123,111,107,44,80,97,99,107,101,116,44,82,101,115,116,125>>]},<<46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,105,110>>]},<<32,100,111,101,115,32,110,111,116,32,99,111,110,116,97,105,110,32,116,104,101,32,101,110,116,105,114,101,32,112,97,99,107,101,116,44,32>>,{code,[],[<<123,109,111,114,101,44,76,101,110,103,116,104,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32>>,{code,[],[<<76,101,110,103,116,104>>]},<<32,105,115,32,101,105,116,104,101,114,32,116,104,101,32,101,120,112,101,99,116,101,100,32>>,{em,[],[<<116,111,116,97,108,32,115,105,122,101>>]},<<32,111,102,32,116,104,101,32,112,97,99,107,101,116,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,101,120,112,101,99,116,101,100,32,112,97,99,107,101,116,32,115,105,122,101,32,105,115,32,117,110,107,110,111,119,110,46,32>>,{code,[],[<<100,101,99,111,100,101,95,112,97,99,107,101,116>>]},<<32,99,97,110,32,116,104,101,110,32,98,101,32,99,97,108,108,101,100,32,97,103,97,105,110,32,119,105,116,104,32,109,111,114,101,32,100,97,116,97,32,97,100,100,101,100,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,97,99,107,101,116,32,100,111,101,115,32,110,111,116,32,99,111,110,102,111,114,109,32,116,111,32,116,104,101,32,112,114,111,116,111,99,111,108,32,102,111,114,109,97,116,44,32>>,{code,[],[<<123,101,114,114,111,114,44,82,101,97,115,111,110,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<84,121,112,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<114,97,119,32,124,32,48>>]}]},{dd,[],[{p,[],[<<78,111,32,112,97,99,107,101,116,32,104,97,110,100,108,105,110,103,32,105,115,32,100,111,110,101,46,32,84,104,101,32,101,110,116,105,114,101,32,98,105,110,97,114,121,32,105,115,32,114,101,116,117,114,110,101,100,32,117,110,108,101,115,115,32,105,116,32,105,115,32,101,109,112,116,121,46>>]}]},{dt,[],[{code,[],[<<49,32,124,32,50,32,124,32,52>>]}]},{dd,[],[{p,[],[<<80,97,99,107,101,116,115,32,99,111,110,115,105,115,116,32,111,102,32,97,32,104,101,97,100,101,114,32,115,112,101,99,105,102,121,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,110,32,116,104,101,32,112,97,99,107,101,116,44,32,102,111,108,108,111,119,101,100,32,98,121,32,116,104,97,116,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,46,32,84,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,104,101,97,100,101,114,32,99,97,110,32,98,101,32,111,110,101,44,32,116,119,111,44,32,111,114,32,102,111,117,114,32,98,121,116,101,115,59,32,116,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,98,121,116,101,115,32,105,115,32,98,105,103,45,101,110,100,105,97,110,46,32,84,104,101,32,104,101,97,100,101,114,32,105,115,32,115,116,114,105,112,112,101,100,32,111,102,102,32,119,104,101,110,32,116,104,101,32,112,97,99,107,101,116,32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{code,[],[<<108,105,110,101>>]}]},{dd,[],[{p,[],[<<65,32,112,97,99,107,101,116,32,105,115,32,97,32,108,105,110,101,45,116,101,114,109,105,110,97,116,101,100,32,98,121,32,97,32,100,101,108,105,109,105,116,101,114,32,98,121,116,101,44,32,100,101,102,97,117,108,116,32,105,115,32,116,104,101,32,108,97,116,105,110,45,49,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,100,101,108,105,109,105,116,101,114,32,98,121,116,101,32,105,115,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,112,97,99,107,101,116,32,117,110,108,101,115,115,32,116,104,101,32,108,105,110,101,32,119,97,115,32,116,114,117,110,99,97,116,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,111,112,116,105,111,110,32>>,{code,[],[<<108,105,110,101,95,108,101,110,103,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,115,110,49,32,124,32,99,100,114,32,124,32,115,117,110,114,109,32,124,32,102,99,103,105,32,124,32,116,112,107,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,104,101,97,100,101,114,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,115,116,114,105,112,112,101,100,32,111,102,102,46>>]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,116,104,101,32,112,97,99,107,101,116,32,116,121,112,101,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,115,110,49>>]},<<32,45,32,65,83,78,46,49,32,66,69,82>>]},{dd,[],[]},{dt,[],[{code,[],[<<115,117,110,114,109>>]},<<32,45,32,83,117,110,39,115,32,82,80,67,32,101,110,99,111,100,105,110,103>>]},{dd,[],[]},{dt,[],[{code,[],[<<99,100,114>>]},<<32,45,32,67,79,82,66,65,32,40,71,73,79,80,32,49,46,49,41>>]},{dd,[],[]},{dt,[],[{code,[],[<<102,99,103,105>>]},<<32,45,32,70,97,115,116,32,67,71,73>>]},{dd,[],[]},{dt,[],[{code,[],[<<116,112,107,116>>]},<<32,45,32,84,80,75,84,32,102,111,114,109,97,116,32,91,82,70,67,49,48,48,54,93>>]},{dd,[],[]}]}]},{dt,[],[{code,[],[<<104,116,116,112,32,124,32,104,116,116,112,104,32,124,32,104,116,116,112,95,98,105,110,32,124,32,104,116,116,112,104,95,98,105,110>>]}]},{dd,[],[{p,[],[<<84,104,101,32,72,121,112,101,114,116,101,120,116,32,84,114,97,110,115,102,101,114,32,80,114,111,116,111,99,111,108,46,32,84,104,101,32,112,97,99,107,101,116,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,119,105,116,104,32,116,104,101,32,102,111,114,109,97,116,32,97,99,99,111,114,100,105,110,103,32,116,111,32>>,{code,[],[<<72,116,116,112,80,97,99,107,101,116>>]},<<32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46,32,65,32,112,97,99,107,101,116,32,105,115,32,101,105,116,104,101,114,32,97,32,114,101,113,117,101,115,116,44,32,97,32,114,101,115,112,111,110,115,101,44,32,97,32,104,101,97,100,101,114,44,32,111,114,32,97,110,32,101,110,100,32,111,102,32,104,101,97,100,101,114,32,109,97,114,107,46,32,73,110,118,97,108,105,100,32,108,105,110,101,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32>>,{code,[],[<<72,116,116,112,69,114,114,111,114>>]},<<46>>]},{p,[],[<<82,101,99,111,103,110,105,122,101,100,32,114,101,113,117,101,115,116,32,109,101,116,104,111,100,115,32,97,110,100,32,104,101,97,100,101,114,32,102,105,101,108,100,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,97,116,111,109,115,46,32,79,116,104,101,114,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,115,116,114,105,110,103,115,46,32,83,116,114,105,110,103,115,32,111,102,32,117,110,114,101,99,111,103,110,105,122,101,100,32,104,101,97,100,101,114,32,102,105,101,108,100,115,32,97,114,101,32,102,111,114,109,97,116,116,101,100,32,119,105,116,104,32,111,110,108,121,32,99,97,112,105,116,97,108,32,108,101,116,116,101,114,115,32,102,105,114,115,116,32,97,110,100,32,97,102,116,101,114,32,104,121,112,104,101,110,32,99,104,97,114,97,99,116,101,114,115,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<34,83,101,99,45,87,101,98,115,111,99,107,101,116,45,75,101,121,34>>]},<<46,32,72,101,97,100,101,114,32,102,105,101,108,100,32,110,97,109,101,115,32,97,114,101,32,97,108,115,111,32,114,101,116,117,114,110,101,100,32,105,110,32>>,{code,[],[<<85,110,109,111,100,105,102,105,101,100,70,105,101,108,100>>]},<<32,97,115,32,115,116,114,105,110,103,115,44,32,119,105,116,104,111,117,116,32,97,110,121,32,99,111,110,118,101,114,115,105,111,110,32,111,114,32,102,111,114,109,97,116,116,105,110,103,46>>]},{p,[],[<<84,104,101,32,112,114,111,116,111,99,111,108,32,116,121,112,101,32>>,{code,[],[<<104,116,116,112>>]},<<32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,102,111,114,32,116,104,101,32,102,105,114,115,116,32,108,105,110,101,32,119,104,101,110,32,97,110,32>>,{code,[],[<<72,116,116,112,82,101,113,117,101,115,116>>]},<<32,111,114,32,97,110,32>>,{code,[],[<<72,116,116,112,82,101,115,112,111,110,115,101>>]},<<32,105,115,32,101,120,112,101,99,116,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,115,32,97,114,101,32,116,111,32,117,115,101,32>>,{code,[],[<<104,116,116,112,104>>]},<<32,116,111,32,103,101,116,32>>,{code,[],[<<72,116,116,112,72,101,97,100,101,114>>]},<<115,32,117,110,116,105,108,32>>,{code,[],[<<104,116,116,112,95,101,111,104>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,119,104,105,99,104,32,109,97,114,107,115,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,104,101,97,100,101,114,115,32,97,110,100,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,97,110,121,32,102,111,108,108,111,119,105,110,103,32,109,101,115,115,97,103,101,32,98,111,100,121,46>>]},{p,[],[<<84,104,101,32,118,97,114,105,97,110,116,115,32>>,{code,[],[<<104,116,116,112,95,98,105,110>>]},<<32,97,110,100,32>>,{code,[],[<<104,116,116,112,104,95,98,105,110>>]},<<32,114,101,116,117,114,110,32,115,116,114,105,110,103,115,32,40>>,{code,[],[<<72,116,116,112,83,116,114,105,110,103>>]},<<41,32,97,115,32,98,105,110,97,114,105,101,115,32,105,110,115,116,101,97,100,32,111,102,32,108,105,115,116,115,46>>]}]}]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,97,99,107,101,116,95,115,105,122,101,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,120,105,109,117,109,32,97,108,108,111,119,101,100,32,115,105,122,101,32,111,102,32,116,104,101,32,112,97,99,107,101,116,32,98,111,100,121,46,32,73,102,32,116,104,101,32,112,97,99,107,101,116,32,104,101,97,100,101,114,32,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,112,97,99,107,101,116,32,105,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,101,32,109,97,120,105,109,117,109,32,97,108,108,111,119,101,100,32,108,101,110,103,116,104,44,32,116,104,101,32,112,97,99,107,101,116,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,105,110,118,97,108,105,100,46,32,68,101,102,97,117,108,116,115,32,116,111,32,48,44,32,119,104,105,99,104,32,109,101,97,110,115,32,110,111,32,115,105,122,101,32,108,105,109,105,116,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,101,95,108,101,110,103,116,104,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<70,111,114,32,112,97,99,107,101,116,32,116,121,112,101,32>>,{code,[],[<<108,105,110,101>>]},<<44,32,108,105,110,101,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,101,32,105,110,100,105,99,97,116,101,100,32,108,101,110,103,116,104,32,97,114,101,32,116,114,117,110,99,97,116,101,100,46>>]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<108,105,110,101,95,108,101,110,103,116,104>>]},<<32,97,108,115,111,32,97,112,112,108,105,101,115,32,116,111,32>>,{code,[],[<<104,116,116,112,42>>]},<<32,112,97,99,107,101,116,32,116,121,112,101,115,32,97,115,32,97,110,32,97,108,105,97,115,32,102,111,114,32,111,112,116,105,111,110,32>>,{code,[],[<<112,97,99,107,101,116,95,115,105,122,101>>]},<<32,105,102,32>>,{code,[],[<<112,97,99,107,101,116,95,115,105,122,101>>]},<<32,105,116,115,101,108,102,32,105,115,32,110,111,116,32,115,101,116,46,32,84,104,105,115,32,117,115,101,32,105,115,32,111,110,108,121,32,105,110,116,101,110,100,101,100,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,101,95,100,101,108,105,109,105,116,101,114,44,32,48,32,61,60,32,98,121,116,101,40,41,32,61,60,32,50,53,53,125>>]}]},{dd,[],[{p,[],[<<70,111,114,32,112,97,99,107,101,116,32,116,121,112,101,32>>,{code,[],[<<108,105,110,101>>]},<<44,32,115,101,116,115,32,116,104,101,32,100,101,108,105,109,105,116,105,110,103,32,98,121,116,101,46,32,68,101,102,97,117,108,116,32,105,115,32,116,104,101,32,108,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32>>,{code,[],[<<36,92,110>>]},<<46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,100,101,99,111,100,101,95,112,97,99,107,101,116,40,49,44,60,60,51,44,34,97,98,99,100,34,62,62,44,91,93,41,46,10,123,111,107,44,60,60,34,97,98,99,34,62,62,44,60,60,34,100,34,62,62,125,10,62,32,101,114,108,97,110,103,58,100,101,99,111,100,101,95,112,97,99,107,101,116,40,49,44,60,60,53,44,34,97,98,99,100,34,62,62,44,91,93,41,46,10,123,109,111,114,101,44,54,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,53,50>>,signature => [{attribute,629,spec,{{erlang,decode_packet,3},[{type,629,bounded_fun,[{type,629,'fun',[{type,629,product,[{var,629,'Type'},{var,629,'Bin'},{var,629,'Options'}]},{type,630,union,[{type,630,tuple,[{atom,630,ok},{var,630,'Packet'},{var,630,'Rest'}]},{type,631,tuple,[{atom,631,more},{var,631,'Length'}]},{type,632,tuple,[{atom,632,error},{var,632,'Reason'}]}]}]},[{type,633,constraint,[{atom,633,is_subtype},[{var,633,'Type'},{type,633,union,[{atom,633,raw},{integer,633,0},{integer,633,1},{integer,633,2},{integer,633,4},{atom,633,asn1},{atom,633,cdr},{atom,633,sunrm},{atom,633,fcgi},{atom,634,tpkt},{atom,634,line},{atom,634,http},{atom,634,http_bin},{atom,634,httph},{atom,634,httph_bin}]}]]},{type,635,constraint,[{atom,635,is_subtype},[{var,635,'Bin'},{type,635,binary,[]}]]},{type,636,constraint,[{atom,636,is_subtype},[{var,636,'Options'},{type,636,list,[{var,636,'Opt'}]}]]},{type,637,constraint,[{atom,637,is_subtype},[{var,637,'Opt'},{type,637,union,[{type,637,tuple,[{atom,637,packet_size},{type,637,non_neg_integer,[]}]},{type,638,tuple,[{atom,638,line_length},{type,638,non_neg_integer,[]}]}]}]]},{type,639,constraint,[{atom,639,is_subtype},[{var,639,'Packet'},{type,639,union,[{type,639,binary,[]},{var,639,'HttpPacket'}]}]]},{type,640,constraint,[{atom,640,is_subtype},[{var,640,'Rest'},{type,640,binary,[]}]]},{type,641,constraint,[{atom,641,is_subtype},[{var,641,'Length'},{type,641,union,[{type,641,non_neg_integer,[]},{atom,641,undefined}]}]]},{type,642,constraint,[{atom,642,is_subtype},[{var,642,'Reason'},{type,642,term,[]}]]},{type,643,constraint,[{atom,643,is_subtype},[{var,643,'HttpPacket'},{type,643,union,[{var,643,'HttpRequest'},{var,644,'HttpResponse'},{var,645,'HttpHeader'},{atom,646,http_eoh},{var,647,'HttpError'}]}]]},{type,648,constraint,[{atom,648,is_subtype},[{var,648,'HttpRequest'},{type,648,tuple,[{atom,648,http_request},{var,648,'HttpMethod'},{var,648,'HttpUri'},{var,648,'HttpVersion'}]}]]},{type,649,constraint,[{atom,649,is_subtype},[{var,649,'HttpResponse'},{type,649,tuple,[{atom,649,http_response},{var,649,'HttpVersion'},{type,649,integer,[]},{var,649,'HttpString'}]}]]},{type,650,constraint,[{atom,650,is_subtype},[{var,650,'HttpHeader'},{type,650,tuple,[{atom,650,http_header},{type,651,integer,[]},{var,652,'HttpField'},{ann_type,653,[{var,653,'UnmodifiedField'},{var,653,'HttpString'}]},{ann_type,654,[{var,654,'Value'},{var,654,'HttpString'}]}]}]]},{type,655,constraint,[{atom,655,is_subtype},[{var,655,'HttpError'},{type,655,tuple,[{atom,655,http_error},{var,655,'HttpString'}]}]]},{type,656,constraint,[{atom,656,is_subtype},[{var,656,'HttpMethod'},{type,656,union,[{atom,656,'OPTIONS'},{atom,656,'GET'},{atom,656,'HEAD'},{atom,656,'POST'},{atom,656,'PUT'},{atom,656,'DELETE'},{atom,657,'TRACE'},{var,657,'HttpString'}]}]]},{type,658,constraint,[{atom,658,is_subtype},[{var,658,'HttpUri'},{type,658,union,[{atom,658,'*'},{type,659,tuple,[{atom,659,absoluteURI},{type,660,union,[{atom,660,http},{atom,660,https}]},{ann_type,661,[{var,661,'Host'},{var,661,'HttpString'}]},{ann_type,662,[{var,662,'Port'},{type,662,union,[{remote_type,662,[{atom,662,inet},{atom,662,port_number},[]]},{atom,662,undefined}]}]},{ann_type,663,[{var,663,'Path'},{var,663,'HttpString'}]}]},{type,664,tuple,[{atom,664,scheme},{ann_type,664,[{var,664,'Scheme'},{var,664,'HttpString'}]},{var,664,'HttpString'}]},{type,665,tuple,[{atom,665,abs_path},{var,665,'HttpString'}]},{var,666,'HttpString'}]}]]},{type,667,constraint,[{atom,667,is_subtype},[{var,667,'HttpVersion'},{type,667,tuple,[{ann_type,667,[{var,667,'Major'},{type,667,non_neg_integer,[]}]},{ann_type,667,[{var,667,'Minor'},{type,667,non_neg_integer,[]}]}]}]]},{type,668,constraint,[{atom,668,is_subtype},[{var,668,'HttpField'},{type,668,union,[{atom,668,'Cache-Control'},{atom,669,'Connection'},{atom,670,'Date'},{atom,671,'Pragma'},{atom,672,'Transfer-Encoding'},{atom,673,'Upgrade'},{atom,674,'Via'},{atom,675,'Accept'},{atom,676,'Accept-Charset'},{atom,677,'Accept-Encoding'},{atom,678,'Accept-Language'},{atom,679,'Authorization'},{atom,680,'From'},{atom,681,'Host'},{atom,682,'If-Modified-Since'},{atom,683,'If-Match'},{atom,684,'If-None-Match'},{atom,685,'If-Range'},{atom,686,'If-Unmodified-Since'},{atom,687,'Max-Forwards'},{atom,688,'Proxy-Authorization'},{atom,689,'Range'},{atom,690,'Referer'},{atom,691,'User-Agent'},{atom,692,'Age'},{atom,693,'Location'},{atom,694,'Proxy-Authenticate'},{atom,695,'Public'},{atom,696,'Retry-After'},{atom,697,'Server'},{atom,698,'Vary'},{atom,699,'Warning'},{atom,700,'Www-Authenticate'},{atom,701,'Allow'},{atom,702,'Content-Base'},{atom,703,'Content-Encoding'},{atom,704,'Content-Language'},{atom,705,'Content-Length'},{atom,706,'Content-Location'},{atom,707,'Content-Md5'},{atom,708,'Content-Range'},{atom,709,'Content-Type'},{atom,710,'Etag'},{atom,711,'Expires'},{atom,712,'Last-Modified'},{atom,713,'Accept-Ranges'},{atom,714,'Set-Cookie'},{atom,715,'Set-Cookie2'},{atom,716,'X-Forwarded-For'},{atom,717,'Cookie'},{atom,718,'Keep-Alive'},{atom,719,'Proxy-Connection'},{var,720,'HttpString'}]}]]},{type,721,constraint,[{atom,721,is_subtype},[{var,721,'HttpString'},{type,721,union,[{type,721,string,[]},{type,721,binary,[]}]}]]}]]}]}}]}},{{function,delete_element,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,726}],[<<100,101,108,101,116,101,95,101,108,101,109,101,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,101,119,32,116,117,112,108,101,32,119,105,116,104,32,101,108,101,109,101,110,116,32,97,116,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,100,101,108,101,116,101,95,101,108,101,109,101,110,116,40,50,44,32,123,111,110,101,44,32,116,119,111,44,32,116,104,114,101,101,125,41,46,10,123,111,110,101,44,116,104,114,101,101,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,54,52>>,signature => [{attribute,726,spec,{{erlang,delete_element,2},[{type,726,bounded_fun,[{type,726,'fun',[{type,726,product,[{var,726,'Index'},{var,726,'Tuple1'}]},{var,726,'Tuple2'}]},[{type,727,constraint,[{atom,727,is_subtype},[{var,727,'Index'},{type,727,pos_integer,[]}]]},{type,728,constraint,[{atom,728,is_subtype},[{var,728,'Tuple1'},{type,728,tuple,any}]]},{type,729,constraint,[{atom,729,is_subtype},[{var,729,'Tuple2'},{type,729,tuple,any}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,delete_module,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,734}],[<<100,101,108,101,116,101,95,109,111,100,117,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<77,97,107,101,115,32,116,104,101,32,99,117,114,114,101,110,116,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,98,101,99,111,109,101,32,111,108,100,32,99,111,100,101,32,97,110,100,32,100,101,108,101,116,101,115,32,97,108,108,32,114,101,102,101,114,101,110,99,101,115,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,32,102,114,111,109,32,116,104,101,32,101,120,112,111,114,116,32,116,97,98,108,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,109,111,100,117,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,114,101,32,97,108,114,101,97,100,121,32,105,115,32,97,110,32,111,108,100,32,118,101,114,115,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,55,55>>,signature => [{attribute,734,spec,{{delete_module,1},[{type,734,bounded_fun,[{type,734,'fun',[{type,734,product,[{var,734,'Module'}]},{type,734,union,[{atom,734,true},{atom,734,undefined}]}]},[{type,735,constraint,[{atom,735,is_subtype},[{var,735,'Module'},{type,735,module,[]}]]}]]}]}}]}},{{function,demonitor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,740}],[<<100,101,109,111,110,105,116,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,111,98,116,97,105,110,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,50>>]}]},<<44,32,116,104,105,115,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,102,102,46,32,73,102,32,116,104,101,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,97,108,114,101,97,100,121,32,116,117,114,110,101,100,32,111,102,102,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46>>]},{p,[],[<<79,110,99,101,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41>>]},<<32,104,97,115,32,114,101,116,117,114,110,101,100,44,32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,110,111,32>>,{code,[],[<<123,39,68,79,87,78,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,44,32,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,44,32,119,105,108,108,32,98,101,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46,32,72,111,119,101,118,101,114,44,32,97,32>>,{code,[],[<<123,39,68,79,87,78,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,32,99,97,110,32,104,97,118,101,32,98,101,101,110,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,46,32,73,116,32,105,115,32,116,104,101,114,101,102,111,114,101,32,117,115,117,97,108,108,121,32,97,100,118,105,115,97,98,108,101,32,116,111,32,114,101,109,111,118,101,32,115,117,99,104,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,102,114,111,109,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,102,116,101,114,32,109,111,110,105,116,111,114,105,110,103,32,104,97,115,32,98,101,101,110,32,115,116,111,112,112,101,100,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,44,32,91,102,108,117,115,104,93,41>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41>>]},<<32,105,102,32,116,104,105,115,32,99,108,101,97,110,117,112,32,105,115,32,119,97,110,116,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,32,40,69,82,84,83,32,53,46,53,41,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,47,49>>]},<<32,98,101,104,97,118,101,100,32,99,111,109,112,108,101,116,101,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,109,111,110,105,116,111,114,32,119,97,115,32,97,99,116,105,118,101,32,117,110,116,105,108,32,116,104,101,32,34,100,101,109,111,110,105,116,111,114,32,115,105,103,110,97,108,34,32,114,101,97,99,104,101,100,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,46,32,84,104,105,115,32,104,97,100,32,111,110,101,32,117,110,100,101,115,105,114,97,98,108,101,32,101,102,102,101,99,116,46,32,89,111,117,32,99,111,117,108,100,32,110,101,118,101,114,32,107,110,111,119,32,119,104,101,110,32,121,111,117,32,119,101,114,101,32,103,117,97,114,97,110,116,101,101,100,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,114,101,99,101,105,118,101,32,97,32>>,{code,[],[<<68,79,87,78>>]},<<32,109,101,115,115,97,103,101,32,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,118,105,101,119,101,100,32,97,115,32,116,119,111,32,99,111,109,98,105,110,101,100,32,111,112,101,114,97,116,105,111,110,115,58,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,32,115,101,110,100,32,97,32,34,100,101,109,111,110,105,116,111,114,32,115,105,103,110,97,108,34,32,116,111,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,32,97,110,100,32,105,103,110,111,114,101,32,97,110,121,32,102,117,116,117,114,101,32,114,101,115,117,108,116,115,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32,73,116,32,105,115,32,97,110,32,101,114,114,111,114,32,105,102,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,109,111,110,105,116,111,114,105,110,103,32,115,116,97,114,116,101,100,32,98,121,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,78,111,116,32,97,108,108,32,115,117,99,104,32,99,97,115,101,115,32,97,114,101,32,99,104,101,97,112,32,116,111,32,99,104,101,99,107,46,32,73,102,32,99,104,101,99,107,105,110,103,32,105,115,32,99,104,101,97,112,44,32,116,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,32,105,102,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,105,115,32,97,32,114,101,109,111,116,101,32,114,101,102,101,114,101,110,99,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,53>>,signature => [{attribute,740,spec,{{demonitor,1},[{type,740,bounded_fun,[{type,740,'fun',[{type,740,product,[{var,740,'MonitorRef'}]},{atom,740,true}]},[{type,741,constraint,[{atom,741,is_subtype},[{var,741,'MonitorRef'},{type,741,reference,[]}]]}]]}]}}]}},{{function,demonitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,746}],[<<100,101,109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,117,110,108,101,115,115,32>>,{code,[],[<<105,110,102,111>>]},<<32,105,115,32,112,97,114,116,32,111,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<46>>]},{p,[],[{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,44,32,91,93,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41>>]}]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,108,117,115,104>>]}]},{dd,[],[{p,[],[<<82,101,109,111,118,101,115,32,40,111,110,101,41,32>>,{code,[],[<<123,95,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,44,32,105,102,32,116,104,101,114,101,32,105,115,32,111,110,101,44,32,102,114,111,109,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,102,116,101,114,32,109,111,110,105,116,111,114,105,110,103,32,104,97,115,32,98,101,101,110,32,115,116,111,112,112,101,100,46>>]},{p,[],[<<67,97,108,108,105,110,103,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,44,32,91,102,108,117,115,104,93,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41,44,10,114,101,99,101,105,118,101,10,32,32,32,32,123,95,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,97,102,116,101,114,32,48,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,101,110,100>>]}]}]},{dt,[],[{code,[],[<<105,110,102,111>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,119,97,115,32,102,111,117,110,100,32,97,110,100,32,114,101,109,111,118,101,100,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,110,111,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,105,115,32,109,111,110,105,116,111,114,32,104,97,115,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,97,110,100,32,119,105,108,108,32,110,111,116,32,98,101,32,100,101,108,105,118,101,114,101,100,46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,119,97,115,32,110,111,116,32,102,111,117,110,100,32,97,110,100,32,99,111,117,108,100,32,110,111,116,32,98,101,32,114,101,109,111,118,101,100,46,32,84,104,105,115,32,112,114,111,98,97,98,108,121,32,98,101,99,97,117,115,101,32,115,111,109,101,111,110,101,32,97,108,114,101,97,100,121,32,104,97,115,32,112,108,97,99,101,100,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,105,115,32,109,111,110,105,116,111,114,32,105,110,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]}]}]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<105,110,102,111>>]},<<32,105,115,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<102,108,117,115,104>>]},<<44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,102,32,97,32,102,108,117,115,104,32,119,97,115,32,110,101,101,100,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<77,111,114,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,111,112,116,105,111,110,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<84,104,101,32,115,97,109,101,32,102,97,105,108,117,114,101,32,97,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,47,49>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,51,55>>,signature => [{attribute,746,spec,{{demonitor,2},[{type,746,bounded_fun,[{type,746,'fun',[{type,746,product,[{var,746,'MonitorRef'},{var,746,'OptionList'}]},{type,746,boolean,[]}]},[{type,747,constraint,[{atom,747,is_subtype},[{var,747,'MonitorRef'},{type,747,reference,[]}]]},{type,748,constraint,[{atom,748,is_subtype},[{var,748,'OptionList'},{type,748,list,[{var,748,'Option'}]}]]},{type,749,constraint,[{atom,749,is_subtype},[{var,749,'Option'},{type,749,union,[{atom,749,flush},{atom,749,info}]}]]}]]}]}}]}},{{function,disconnect_node,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3429}],[<<100,105,115,99,111,110,110,101,99,116,95,110,111,100,101,47,49>>],#{<<101,110>> => [{p,[],[<<70,111,114,99,101,115,32,116,104,101,32,100,105,115,99,111,110,110,101,99,116,105,111,110,32,111,102,32,97,32,110,111,100,101,46,32,84,104,105,115,32,97,112,112,101,97,114,115,32,116,111,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<32,97,115,32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,104,97,115,32,99,114,97,115,104,101,100,46,32,84,104,105,115,32,66,73,70,32,105,115,32,109,97,105,110,108,121,32,117,115,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,110,101,116,119,111,114,107,32,97,117,116,104,101,110,116,105,99,97,116,105,111,110,32,112,114,111,116,111,99,111,108,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,100,105,115,99,111,110,110,101,99,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,73,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<105,103,110,111,114,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,109,97,121,32,114,101,116,117,114,110,32,98,101,102,111,114,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,95,110,111,100,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,109,101,115,115,97,103,101,115>>]},<<32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,48,53>>,signature => [{attribute,3429,spec,{{disconnect_node,1},[{type,3429,bounded_fun,[{type,3429,'fun',[{type,3429,product,[{var,3429,'Node'}]},{type,3429,union,[{type,3429,boolean,[]},{atom,3429,ignored}]}]},[{type,3430,constraint,[{atom,3430,is_subtype},[{var,3430,'Node'},{type,3430,node,[]}]]}]]}]}}]}},{{function,display,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,773}],[<<100,105,115,112,108,97,121,47,49>>],#{<<101,110>> => [{p,[],[<<80,114,105,110,116,115,32,97,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,111,110,32,116,104,101,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,50,52>>,signature => [{attribute,773,spec,{{erlang,display,1},[{type,773,bounded_fun,[{type,773,'fun',[{type,773,product,[{var,773,'Term'}]},{atom,773,true}]},[{type,774,constraint,[{atom,774,is_subtype},[{var,774,'Term'},{type,774,term,[]}]]}]]}]}}]}},{{function,dist_ctrl_get_data,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3713}],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,47,49>>],#{<<101,110>> => [{p,[],[<<71,101,116,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,100,97,116,97,32,102,114,111,109,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,116,104,97,116,32,105,115,32,116,111,32,98,101,32,112,97,115,115,101,100,32,116,111,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,46,32,84,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,73,102,32,110,111,32,100,97,116,97,32,105,115,32,97,118,97,105,108,97,98,108,101,44,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,110,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,110,101,32,99,97,110,32,114,101,113,117,101,115,116,32,116,111,32,98,101,32,105,110,102,111,114,109,101,100,32,98,121,32,97,32,109,101,115,115,97,103,101,32,119,104,101,110,32,109,111,114,101,32,100,97,116,97,32,105,115,32,97,118,97,105,108,97,98,108,101,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,40,68,72,97,110,100,108,101,41>>]}]},<<46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,119,104,101,110,32,116,104,101,114,101,32,97,114,101,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,99,111,110,102,105,103,117,114,101,100,32,111,110,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>]}]},<<32,102,117,110,99,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,51,54>>,signature => [{attribute,3713,spec,{{erlang,dist_ctrl_get_data,1},[{type,3713,bounded_fun,[{type,3713,'fun',[{type,3713,product,[{var,3713,'DHandle'}]},{type,3713,union,[{type,3713,tuple,[{var,3713,'Size'},{var,3713,'Data'}]},{var,3713,'Data'},{atom,3713,none}]}]},[{type,3714,constraint,[{atom,3714,is_subtype},[{var,3714,'Size'},{type,3714,non_neg_integer,[]}]]},{type,3715,constraint,[{atom,3715,is_subtype},[{var,3715,'DHandle'},{user_type,3715,dist_handle,[]}]]},{type,3716,constraint,[{atom,3716,is_subtype},[{var,3716,'Data'},{user_type,3716,iovec,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_get_opt,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3735}],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,111,112,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,111,110,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>]}]},<<32,102,117,110,99,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,55,55>>,signature => [{attribute,3735,spec,{{erlang,dist_ctrl_get_opt,2},[{type,3735,bounded_fun,[{type,3735,'fun',[{type,3735,product,[{var,3735,'DHandle'},{atom,3735,get_size}]},{var,3735,'Value'}]},[{type,3736,constraint,[{atom,3736,is_subtype},[{var,3736,'DHandle'},{user_type,3736,dist_handle,[]}]]},{type,3737,constraint,[{atom,3737,is_subtype},[{var,3737,'Value'},{type,3737,boolean,[]}]]}]]}]}}],since => <<79,84,80,32,50,50,46,48>>}},{{function,dist_ctrl_get_data_notification,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3721}],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,113,117,101,115,116,32,110,111,116,105,102,105,99,97,116,105,111,110,32,119,104,101,110,32,109,111,114,101,32,100,97,116,97,32,105,115,32,97,118,97,105,108,97,98,108,101,32,116,111,32,102,101,116,99,104,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]}]},<<32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,87,104,101,110,32,109,111,114,101,32,100,97,116,97,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<100,105,115,116,95,100,97,116,97>>]},<<46,32,79,110,99,101,32,97,32>>,{code,[],[<<100,105,115,116,95,100,97,116,97>>]},<<32,109,101,115,115,97,103,101,115,32,104,97,115,32,98,101,101,110,32,115,101,110,116,44,32,110,111,32,109,111,114,101,32>>,{code,[],[<<100,105,115,116,95,100,97,116,97>>]},<<32,109,101,115,115,97,103,101,115,32,119,105,108,108,32,98,101,32,115,101,110,116,32,117,110,116,105,108,32,116,104,101,32>>,{code,[],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,47,49>>]},<<32,102,117,110,99,116,105,111,110,32,104,97,115,32,98,101,101,110,32,99,97,108,108,101,100,32,97,103,97,105,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,53,48,54>>,signature => [{attribute,3721,spec,{{erlang,dist_ctrl_get_data_notification,1},[{type,3721,bounded_fun,[{type,3721,'fun',[{type,3721,product,[{var,3721,'DHandle'}]},{atom,3721,ok}]},[{type,3722,constraint,[{atom,3722,is_subtype},[{var,3722,'DHandle'},{user_type,3722,dist_handle,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_input_handler,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3699}],[<<100,105,115,116,95,99,116,114,108,95,105,110,112,117,116,95,104,97,110,100,108,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,103,105,115,116,101,114,32,97,110,32,97,108,116,101,114,110,97,116,101,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,112,114,111,99,101,115,115,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,79,110,99,101,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,104,97,115,32,98,101,101,110,32,99,97,108,108,101,100,44,32>>,{code,[],[<<73,110,112,117,116,72,97,110,100,108,101,114>>]},<<32,105,115,32,116,104,101,32,111,110,108,121,32,112,114,111,99,101,115,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,112,117,116,95,100,97,116,97,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,112,117,116,95,100,97,116,97,40,68,72,97,110,100,108,101,44,32,68,97,116,97,41>>]}]},<<32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,100,101,110,116,105,102,105,110,103,32,116,104,105,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,53,52,50>>,signature => [{attribute,3699,spec,{{erlang,dist_ctrl_input_handler,2},[{type,3699,bounded_fun,[{type,3699,'fun',[{type,3699,product,[{var,3699,'DHandle'},{var,3699,'InputHandler'}]},{atom,3699,ok}]},[{type,3700,constraint,[{atom,3700,is_subtype},[{var,3700,'DHandle'},{user_type,3700,dist_handle,[]}]]},{type,3701,constraint,[{atom,3701,is_subtype},[{var,3701,'InputHandler'},{type,3701,pid,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_put_data,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3706}],[<<100,105,115,116,95,99,116,114,108,95,112,117,116,95,100,97,116,97,47,50>>],#{<<101,110>> => [{p,[],[<<68,101,108,105,118,101,114,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,100,97,116,97,32,102,114,111,109,32,97,32,114,101,109,111,116,101,32,110,111,100,101,32,116,111,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,117,110,108,101,115,115,32,97,110,32,97,108,116,101,114,110,97,116,101,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,112,114,111,99,101,115,115,32,104,97,115,32,98,101,101,110,32,114,101,103,105,115,116,101,114,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,105,110,112,117,116,95,104,97,110,100,108,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,105,110,112,117,116,95,104,97,110,100,108,101,114,40,68,72,97,110,100,108,101,44,32,73,110,112,117,116,72,97,110,100,108,101,114,41>>]}]},<<46,32,73,102,32,97,110,32,97,108,116,101,114,110,97,116,101,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,104,97,115,32,98,101,101,110,32,114,101,103,105,115,116,101,114,101,100,44,32,111,110,108,121,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,112,114,111,99,101,115,115,32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,53,55,53>>,signature => [{attribute,3706,spec,{{erlang,dist_ctrl_put_data,2},[{type,3706,bounded_fun,[{type,3706,'fun',[{type,3706,product,[{var,3706,'DHandle'},{var,3706,'Data'}]},{atom,3706,ok}]},[{type,3707,constraint,[{atom,3707,is_subtype},[{var,3707,'DHandle'},{user_type,3707,dist_handle,[]}]]},{type,3708,constraint,[{atom,3708,is_subtype},[{var,3708,'Data'},{type,3708,iodata,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_set_opt,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3727}],[<<100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,111,110,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,84,104,105,115,32,111,112,116,105,111,110,32,99,111,110,116,114,111,108,115,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32,99,97,108,108,115,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,117,115,101,100,32,119,104,101,110,32,115,101,116,116,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,46,32,87,104,101,110,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,105,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[<<97,110,100,32,116,104,101,114,101,32,97,114,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,44,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]},<<32,119,105,108,108,32,106,117,115,116,32,114,101,116,117,114,110,32>>,{code,[],[<<68,97,116,97>>]},<<32,116,111,32,112,97,115,115,32,111,118,101,114,32,116,104,101,32,99,104,97,110,110,101,108,46,32,84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,46>>]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[<<97,110,100,32,116,104,101,114,101,32,97,114,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,44,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]},<<32,119,105,108,108,32,114,101,116,117,114,110,32>>,{code,[],[<<68,97,116,97>>]},<<32,116,111,32,112,97,115,115,32,111,118,101,114,32,116,104,101,32,99,104,97,110,110,101,108,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32>>,{code,[],[<<83,105,122,101>>]},<<32,111,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,110,32,98,121,116,101,115,46,32,84,104,105,115,32,105,115,32,114,101,116,117,114,110,101,100,32,97,115,32,97,32,116,117,112,108,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,83,105,122,101,44,32,68,97,116,97,125>>]},<<46>>]}]},{p,[],[<<65,108,108,32,111,112,116,105,111,110,115,32,97,114,101,32,115,101,116,32,116,111,32,100,101,102,97,117,108,116,32,119,104,101,110,32,97,32,99,104,97,110,110,101,108,32,105,115,32,99,108,111,115,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,48,56>>,signature => [{attribute,3727,spec,{{erlang,dist_ctrl_set_opt,3},[{type,3727,bounded_fun,[{type,3727,'fun',[{type,3727,product,[{var,3727,'DHandle'},{atom,3727,get_size},{var,3727,'Value'}]},{var,3727,'OldValue'}]},[{type,3728,constraint,[{atom,3728,is_subtype},[{var,3728,'DHandle'},{user_type,3728,dist_handle,[]}]]},{type,3729,constraint,[{atom,3729,is_subtype},[{var,3729,'Value'},{type,3729,boolean,[]}]]},{type,3730,constraint,[{atom,3730,is_subtype},[{var,3730,'OldValue'},{type,3730,boolean,[]}]]}]]}]}}],since => <<79,84,80,32,50,50,46,48>>}},{{function,element,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2116}],[<<101,108,101,109,101,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{code,[],[<<78>>]},<<116,104,32,101,108,101,109,101,110,116,32,40,110,117,109,98,101,114,105,110,103,32,102,114,111,109,32,49,41,32,111,102,32>>,{code,[],[<<84,117,112,108,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,108,101,109,101,110,116,40,50,44,32,123,97,44,32,98,44,32,99,125,41,46,10,98>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,53,55>>,signature => [{attribute,2116,spec,{{element,2},[{type,2116,bounded_fun,[{type,2116,'fun',[{type,2116,product,[{var,2116,'N'},{var,2116,'Tuple'}]},{type,2116,term,[]}]},[{type,2117,constraint,[{atom,2117,is_subtype},[{var,2117,'N'},{type,2117,pos_integer,[]}]]},{type,2118,constraint,[{atom,2118,is_subtype},[{var,2118,'Tuple'},{type,2118,tuple,any}]]}]]}]}}]}},{{function,erase,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,832}],[<<101,114,97,115,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,97,110,100,32,100,101,108,101,116,101,115,32,105,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,123,49,44,32,50,44,32,51,125,41,44,10,112,117,116,40,107,101,121,50,44,32,91,97,44,32,98,44,32,99,93,41,44,10,101,114,97,115,101,40,41,46,10,91,123,107,101,121,49,44,123,49,44,50,44,51,125,125,44,123,107,101,121,50,44,91,97,44,98,44,99,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,55,49>>,signature => [{attribute,832,spec,{{erase,0},[{type,832,bounded_fun,[{type,832,'fun',[{type,832,product,[]},{type,832,list,[{type,832,tuple,[{var,832,'Key'},{var,832,'Val'}]}]}]},[{type,833,constraint,[{atom,833,is_subtype},[{var,833,'Key'},{type,833,term,[]}]]},{type,834,constraint,[{atom,834,is_subtype},[{var,834,'Val'},{type,834,term,[]}]]}]]}]}}]}},{{function,erase,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,839}],[<<101,114,97,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<32,97,110,100,32,100,101,108,101,116,101,115,32,105,116,32,102,114,111,109,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,110,111,32,118,97,108,117,101,32,105,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<46,32,84,104,101,32,97,118,101,114,97,103,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,79,40>>,{code,[],[<<49>>]},<<41,32,97,110,100,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,105,115,32,79,40>>,{code,[],[<<78>>]},<<41,44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,105,116,101,109,115,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,123,109,101,114,114,121,44,32,108,97,109,98,115,44,32,97,114,101,44,32,112,108,97,121,105,110,103,125,41,44,10,88,32,61,32,101,114,97,115,101,40,107,101,121,49,41,44,10,123,88,44,32,101,114,97,115,101,40,107,101,121,49,41,125,46,10,123,123,109,101,114,114,121,44,108,97,109,98,115,44,97,114,101,44,112,108,97,121,105,110,103,125,44,117,110,100,101,102,105,110,101,100,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,56,53>>,signature => [{attribute,839,spec,{{erase,1},[{type,839,bounded_fun,[{type,839,'fun',[{type,839,product,[{var,839,'Key'}]},{type,839,union,[{var,839,'Val'},{atom,839,undefined}]}]},[{type,840,constraint,[{atom,840,is_subtype},[{var,840,'Key'},{type,840,term,[]}]]},{type,841,constraint,[{atom,841,is_subtype},[{var,841,'Val'},{type,841,term,[]}]]}]]}]}}]}},{{function,error,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,847}],[<<101,114,114,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,119,105,116,104,32,116,104,101,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,97,110,121,32,116,101,114,109,46,32,84,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,32,105,115,32>>,{code,[],[<<123,82,101,97,115,111,110,44,32,87,104,101,114,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<87,104,101,114,101>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,99,97,108,108,101,100,32,40,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,102,105,114,115,116,41,46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,116,104,114,111,119,110,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,105,115,32,116,111,32,115,105,103,110,97,108,32,116,104,97,116,32,97,110,32,117,110,101,120,112,101,99,116,101,100,32,101,114,114,111,114,32,104,97,115,32,104,97,112,112,101,110,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,119,105,116,104,32,97,32,112,97,114,97,109,101,116,101,114,32,116,104,97,116,32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,41,46,32,83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,99,97,116,99,104,32,101,114,114,111,114,40,102,111,111,98,97,114,41,46,10,123,39,69,88,73,84,39,44,123,102,111,111,98,97,114,44,91,123,115,104,101,108,108,44,97,112,112,108,121,95,102,117,110,44,51,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,57,48,54,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,101,114,108,95,101,118,97,108,44,100,111,95,97,112,112,108,121,44,54,44,91,123,102,105,108,101,44,34,101,114,108,95,101,118,97,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,55,55,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,101,114,108,95,101,118,97,108,44,101,120,112,114,44,53,44,91,123,102,105,108,101,44,34,101,114,108,95,101,118,97,108,46,101,114,108,34,125,44,123,108,105,110,101,44,52,51,48,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,115,104,101,108,108,44,101,120,112,114,115,44,55,44,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,56,55,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,115,104,101,108,108,44,101,118,97,108,95,101,120,112,114,115,44,55,44,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,52,50,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,115,104,101,108,108,44,101,118,97,108,95,108,111,111,112,44,51,44,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,50,55,125,93,125,93,125,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,48,54>>,signature => [{attribute,847,spec,{{error,1},[{type,847,bounded_fun,[{type,847,'fun',[{type,847,product,[{var,847,'Reason'}]},{type,847,no_return,[]}]},[{type,848,constraint,[{atom,848,is_subtype},[{var,848,'Reason'},{type,848,term,[]}]]}]]}]}}]}},{{function,error,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,854}],[<<101,114,114,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,119,105,116,104,32,116,104,101,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,97,110,121,32,116,101,114,109,46,32,84,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,32,105,115,32>>,{code,[],[<<123,82,101,97,115,111,110,44,32,87,104,101,114,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<87,104,101,114,101>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,99,97,108,108,101,100,32,40,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,102,105,114,115,116,41,46,32>>,{code,[],[<<65,114,103,115>>]},<<32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,116,104,101,32,108,105,115,116,32,111,102,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,59,32,105,116,32,105,115,32,117,115,101,100,32,116,111,32,112,114,111,118,105,100,101,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,105,110,32,116,104,101,32,116,101,114,109,32>>,{code,[],[<<87,104,101,114,101>>]},<<46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,105,115,32,116,111,32,115,105,103,110,97,108,32,116,104,97,116,32,97,110,32,117,110,101,120,112,101,99,116,101,100,32,101,114,114,111,114,32,104,97,115,32,104,97,112,112,101,110,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,119,105,116,104,32,97,32,112,97,114,97,109,101,116,101,114,32,116,104,97,116,32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,41,46,32,83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46,32,69,120,97,109,112,108,101,58>>]},{p,[],[{code,[],[<<116,101,115,116,46,101,114,108>>]},<<58>>]},{pre,[],[{code,[],[<<45,109,111,100,117,108,101,40,116,101,115,116,41,46,10,45,101,120,112,111,114,116,40,91,101,120,97,109,112,108,101,95,102,117,110,47,50,93,41,46,10,10,101,120,97,109,112,108,101,95,102,117,110,40,65,49,44,32,65,50,41,32,45,62,10,32,32,32,32,101,114,108,97,110,103,58,101,114,114,111,114,40,109,121,95,101,114,114,111,114,44,32,91,65,49,44,32,65,50,93,41,46>>]}]},{p,[],[<<69,114,108,97,110,103,32,115,104,101,108,108,58>>]},{pre,[],[{code,[],[<<54,62,32,99,40,116,101,115,116,41,46,10,123,111,107,44,116,101,115,116,125,10,55,62,32,116,101,115,116,58,101,120,97,109,112,108,101,95,102,117,110,40,97,114,103,49,44,34,116,104,105,115,32,105,115,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,34,41,46,10,42,42,32,101,120,99,101,112,116,105,111,110,32,101,114,114,111,114,58,32,109,121,95,101,114,114,111,114,10,32,32,32,32,32,105,110,32,102,117,110,99,116,105,111,110,32,32,116,101,115,116,58,101,120,97,109,112,108,101,95,102,117,110,47,50,10,32,32,32,32,32,32,32,32,32,99,97,108,108,101,100,32,97,115,32,116,101,115,116,58,101,120,97,109,112,108,101,95,102,117,110,40,97,114,103,49,44,34,116,104,105,115,32,105,115,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,34,41,10,32>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,51,53>>,signature => [{attribute,854,spec,{{error,2},[{type,854,bounded_fun,[{type,854,'fun',[{type,854,product,[{var,854,'Reason'},{var,854,'Args'}]},{type,854,no_return,[]}]},[{type,855,constraint,[{atom,855,is_subtype},[{var,855,'Reason'},{type,855,term,[]}]]},{type,856,constraint,[{atom,856,is_subtype},[{var,856,'Args'},{type,856,list,[{type,856,term,[]}]}]]}]]}]}}]}},{{function,error,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,862}],[<<101,114,114,111,114,47,51>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,119,105,116,104,32,116,104,101,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,97,110,121,32,116,101,114,109,46,32>>,{code,[],[<<65,114,103,115>>]},<<32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,116,104,101,32,108,105,115,116,32,111,102,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,59,32,105,116,32,105,115,32,117,115,101,100,32,116,111,32,112,114,111,118,105,100,101,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,105,110,32,116,104,101,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,46,32,73,102,32,116,104,101,32>>,{code,[],[<<123,101,114,114,111,114,95,105,110,102,111,44,32,69,114,114,111,114,73,110,102,111,77,97,112,125>>]},<<32,111,112,116,105,111,110,32,105,115,32,103,105,118,101,110,44,32,105,116,32,119,105,108,108,32,98,101,32,105,110,106,101,99,116,101,100,32,105,110,116,111,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,46>>]},{p,[],[<<65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,105,115,32,116,111,32,115,105,103,110,97,108,32,116,104,97,116,32,97,110,32,117,110,101,120,112,101,99,116,101,100,32,101,114,114,111,114,32,104,97,115,32,104,97,112,112,101,110,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,119,105,116,104,32,97,32,112,97,114,97,109,101,116,101,114,32,116,104,97,116,32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,41,46,32,83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,55,53>>,signature => [{attribute,862,spec,{{error,3},[{type,862,bounded_fun,[{type,862,'fun',[{type,862,product,[{var,862,'Reason'},{var,862,'Args'},{var,862,'Options'}]},{type,862,no_return,[]}]},[{type,863,constraint,[{atom,863,is_subtype},[{var,863,'Reason'},{type,863,term,[]}]]},{type,864,constraint,[{atom,864,is_subtype},[{var,864,'Args'},{type,864,list,[{type,864,term,[]}]}]]},{type,865,constraint,[{atom,865,is_subtype},[{var,865,'Options'},{type,865,list,[{var,865,'Option'}]}]]},{type,866,constraint,[{atom,866,is_subtype},[{var,866,'Option'},{type,866,tuple,[{atom,866,error_info},{var,866,'ErrorInfoMap'}]}]]},{type,867,constraint,[{atom,867,is_subtype},[{var,867,'ErrorInfoMap'},{type,867,map,[{type,867,map_field_assoc,[{atom,867,cause},{type,867,term,[]}]},{type,868,map_field_assoc,[{atom,868,module},{type,868,module,[]}]},{type,869,map_field_assoc,[{atom,869,function},{type,869,atom,[]}]}]}]]}]]}]}}],since => <<50,52,46,48>>}},{{function,exit,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,875}],[<<101,120,105,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,120,105,116>>]},<<32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,97,110,121,32,116,101,114,109,46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,105,110,116,101,110,116,32,105,115,32,116,111,32,115,116,111,112,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,100,105,102,102,101,114,32,102,114,111,109,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,114,114,111,114,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,114,114,111,114,47,50>>]}]},<<32,98,121,32,99,97,117,115,105,110,103,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,97,32,100,105,102,102,101,114,101,110,116,32,99,108,97,115,115,32,97,110,100,32,98,121,32,104,97,118,105,110,103,32,97,32,114,101,97,115,111,110,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,116,104,101,32,108,105,115,116,32,111,102,32,102,117,110,99,116,105,111,110,115,32,102,114,111,109,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,46>>]},{p,[],[<<83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,120,105,116,40,102,111,111,98,97,114,41,46,10,42,42,32,101,120,99,101,112,116,105,111,110,32,101,120,105,116,58,32,102,111,111,98,97,114,10,62,32,99,97,116,99,104,32,101,120,105,116,40,102,111,111,98,97,114,41,46,10,123,39,69,88,73,84,39,44,102,111,111,98,97,114,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,99,97,108,108,115,32>>,{code,[],[<<101,120,105,116,40,107,105,108,108,41>>]},<<32,97,110,100,32,100,111,101,115,32,110,111,116,32,99,97,116,99,104,32,116,104,101,32,101,120,99,101,112,116,105,111,110,44,32,105,116,32,119,105,108,108,32,116,101,114,109,105,110,97,116,101,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,97,110,100,32,97,108,115,111,32,101,109,105,116,32,101,120,105,116,32,115,105,103,110,97,108,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,40,110,111,116,32>>,{code,[],[<<107,105,108,108,101,100>>]},<<41,32,116,111,32,97,108,108,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,46,32,83,117,99,104,32,101,120,105,116,32,115,105,103,110,97,108,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,99,97,110,32,98,101,32,116,114,97,112,112,101,100,32,98,121,32,116,104,101,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,46,32,78,111,116,101,32,116,104,97,116,32,116,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,115,105,103,110,97,108,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,98,101,104,97,118,101,32,100,105,102,102,101,114,101,110,116,108,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,121,32,97,114,101,32,115,101,110,116,32,98,101,99,97,117,115,101,32,116,104,101,32,115,105,103,110,97,108,32,119,105,108,108,32,98,101,32,117,110,116,114,97,112,112,97,98,108,101,32,105,102,32,97,32,112,114,111,99,101,115,115,32,115,101,110,100,115,32,115,117,99,104,32,97,32,115,105,103,110,97,108,32,116,111,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,57,55>>,signature => [{attribute,875,spec,{{exit,1},[{type,875,bounded_fun,[{type,875,'fun',[{type,875,product,[{var,875,'Reason'}]},{type,875,no_return,[]}]},[{type,876,constraint,[{atom,876,is_subtype},[{var,876,'Reason'},{type,876,term,[]}]]}]]}]}}]}},{{function,exit,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,881}],[<<101,120,105,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,98,101,104,97,118,105,111,114,32,97,112,112,108,105,101,115,32,105,102,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,97,110,121,32,116,101,114,109,44,32,101,120,99,101,112,116,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,111,114,32>>,{code,[],[<<107,105,108,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<80>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32,110,111,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32>>,{code,[],[<<80>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,116,114,97,110,115,102,111,114,109,101,100,32,105,110,116,111,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,82,101,97,115,111,110,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,114,111,109>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,115,101,110,116,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,44,32,97,110,100,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,102,32>>,{code,[],[<<80>>]},<<46>>]}]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,98,101,104,97,118,105,111,114,32,97,112,112,108,105,101,115,32,105,102,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,116,104,101,32,116,101,114,109,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80>>]},<<32,119,104,105,99,104,32,105,115,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,105,110,118,111,107,101,100,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,40,80,105,100,44,32,110,111,114,109,97,108,41>>]},<<32,40,116,104,101,32,98,101,104,97,118,105,111,114,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32,115,101,110,100,115,32,97,32,115,105,103,110,97,108,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,114,101,97,115,111,110,32,116,111,32,105,116,115,101,108,102,32,105,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,119,97,114,110,105,110,103,41,58>>]},{ul,[],[{li,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,116,114,97,110,115,102,111,114,109,101,100,32,105,110,116,111,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,110,111,114,109,97,108,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,114,111,109>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,115,101,110,116,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,44,32,97,110,100,32,100,101,108,105,118,101,114,101,100,32,116,111,32>>,{code,[],[<<80>>]},<<39,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]},{li,[],[<<84,104,101,32,115,105,103,110,97,108,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,105,102,32>>,{code,[],[<<80>>]},<<32,105,115,32,110,111,116,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,46>>]}]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<107,105,108,108>>]},<<44,32,116,104,97,116,32,105,115,44,32,105,102,32>>,{code,[],[<<101,120,105,116,40,80,105,100,44,32,107,105,108,108,41>>]},<<32,105,115,32,99,97,108,108,101,100,44,32,97,110,32,117,110,116,114,97,112,112,97,98,108,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,105,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,119,104,105,99,104,32,117,110,99,111,110,100,105,116,105,111,110,97,108,108,121,32,101,120,105,116,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108,101,100>>]},<<46,32,84,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,105,115,32,99,104,97,110,103,101,100,32,102,114,111,109,32>>,{code,[],[<<107,105,108,108>>]},<<32,116,111,32>>,{code,[],[<<107,105,108,108,101,100>>]},<<32,116,111,32,104,105,110,116,32,116,111,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,116,104,101,32,107,105,108,108,101,100,32,112,114,111,99,101,115,115,32,103,111,116,32,107,105,108,108,101,100,32,98,121,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,120,105,116,40,80,105,100,44,32,107,105,108,108,41>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]}]},<<32,97,114,101,32,110,97,109,101,100,32,115,105,109,105,108,97,114,108,121,32,98,117,116,32,112,114,111,118,105,100,101,32,118,101,114,121,32,100,105,102,102,101,114,101,110,116,32,102,117,110,99,116,105,111,110,97,108,105,116,105,101,115,46,32,84,104,101,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,49>>]},<<32,102,117,110,99,116,105,111,110,32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,105,110,116,101,110,116,32,105,115,32,116,111,32,115,116,111,112,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,119,104,105,108,101,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]},<<32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,105,110,116,101,110,116,32,105,115,32,116,111,32,115,101,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,116,111,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,78,111,116,101,32,97,108,115,111,32,116,104,97,116,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,49>>]},<<32,114,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,104,97,116,32,99,97,110,32,98,101,32,99,97,117,103,104,116,32,119,104,105,108,101,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]},<<32,100,111,101,115,32,110,111,116,32,99,97,117,115,101,32,97,110,121,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,32,111,110,108,121,32,115,99,101,110,97,114,105,111,32,116,104,97,116,32,104,97,115,32,110,111,116,32,98,101,101,110,32,99,111,118,101,114,101,100,32,98,121,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,97,98,111,118,101,32,105,115,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80>>]},<<32,115,101,110,100,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,116,111,32,105,116,115,101,108,102,44,32,116,104,97,116,32,105,115,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,40,115,101,108,102,40,41,44,32,110,111,114,109,97,108,41>>]},<<46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,105,110,32,116,104,105,115,32,115,99,101,110,97,114,105,111,32,105,115,32,97,115,32,102,111,108,108,111,119,115,58>>]},{ul,[],[{li,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,116,114,97,110,115,102,111,114,109,101,100,32,105,110,116,111,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,110,111,114,109,97,108,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,114,111,109>>]},<<32,105,115,32>>,{code,[],[<<80>>]},<<39,115,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,97,110,100,32,100,101,108,105,118,101,114,101,100,32,116,111,32>>,{code,[],[<<80>>]},<<39,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]},{li,[],[{code,[],[<<80>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,105,102,32>>,{code,[],[<<80>>]},<<32,105,115,32,110,111,116,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,46>>]}]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,98,101,104,97,118,105,111,114,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32,115,101,110,100,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,116,111,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,115,32,97,114,103,117,97,98,108,121,32,115,116,114,97,110,103,101,32,98,117,116,32,116,104,105,115,32,98,101,104,97,118,105,111,114,32,105,115,32,107,101,112,116,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,114,101,97,115,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,56,51,57>>,signature => [{attribute,881,spec,{{exit,2},[{type,881,bounded_fun,[{type,881,'fun',[{type,881,product,[{var,881,'Pid'},{var,881,'Reason'}]},{atom,881,true}]},[{type,882,constraint,[{atom,882,is_subtype},[{var,882,'Pid'},{type,882,union,[{type,882,pid,[]},{type,882,port,[]}]}]]},{type,883,constraint,[{atom,883,is_subtype},[{var,883,'Reason'},{type,883,term,[]}]]}]]}]}}]}},{{function,external_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,895}],[<<101,120,116,101,114,110,97,108,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,97,108,99,117,108,97,116,101,115,44,32,119,105,116,104,111,117,116,32,100,111,105,110,103,32,116,104,101,32,101,110,99,111,100,105,110,103,44,32,116,104,101,32,109,97,120,105,109,117,109,32,98,121,116,101,32,115,105,122,101,32,102,111,114,32,97,32,116,101,114,109,32,101,110,99,111,100,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,32,97,112,112,108,105,101,115,32,97,108,119,97,121,115,58>>]},{pre,[],[{code,[],[<<62,32,83,105,122,101,49,32,61,32,98,121,116,101,95,115,105,122,101,40,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,41,41,44,10,62,32,83,105,122,101,50,32,61,32,101,114,108,97,110,103,58,101,120,116,101,114,110,97,108,95,115,105,122,101,40,84,101,114,109,41,44,10,62,32,116,114,117,101,32,61,32,83,105,122,101,49,32,61,60,32,83,105,122,101,50,46,10,116,114,117,101>>]}]},{p,[],[<<84,104,105,115,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,97,32,99,97,108,108,32,116,111,58>>]},{pre,[],[{code,[],[<<101,114,108,97,110,103,58,101,120,116,101,114,110,97,108,95,115,105,122,101,40,84,101,114,109,44,32,91,93,41>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,50,53>>,signature => [{attribute,895,spec,{{erlang,external_size,1},[{type,895,bounded_fun,[{type,895,'fun',[{type,895,product,[{var,895,'Term'}]},{type,895,non_neg_integer,[]}]},[{type,896,constraint,[{atom,896,is_subtype},[{var,896,'Term'},{type,896,term,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66,48,52>>}},{{function,external_size,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,901}],[<<101,120,116,101,114,110,97,108,95,115,105,122,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,97,108,99,117,108,97,116,101,115,44,32,119,105,116,104,111,117,116,32,100,111,105,110,103,32,116,104,101,32,101,110,99,111,100,105,110,103,44,32,116,104,101,32,109,97,120,105,109,117,109,32,98,121,116,101,32,115,105,122,101,32,102,111,114,32,97,32,116,101,114,109,32,101,110,99,111,100,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,32,97,112,112,108,105,101,115,32,97,108,119,97,121,115,58>>]},{pre,[],[{code,[],[<<62,32,83,105,122,101,49,32,61,32,98,121,116,101,95,115,105,122,101,40,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,44,32,79,112,116,105,111,110,115,41,41,44,10,62,32,83,105,122,101,50,32,61,32,101,114,108,97,110,103,58,101,120,116,101,114,110,97,108,95,115,105,122,101,40,84,101,114,109,44,32,79,112,116,105,111,110,115,41,44,10,62,32,116,114,117,101,32,61,32,83,105,122,101,49,32,61,60,32,83,105,122,101,50,46,10,116,114,117,101>>]}]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<123,109,105,110,111,114,95,118,101,114,115,105,111,110,44,32,86,101,114,115,105,111,110,125>>]},<<32,115,112,101,99,105,102,105,101,115,32,104,111,119,32,102,108,111,97,116,115,32,97,114,101,32,101,110,99,111,100,101,100,46,32,70,111,114,32,97,32,100,101,116,97,105,108,101,100,32,100,101,115,99,114,105,112,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,52,52>>,signature => [{attribute,901,spec,{{erlang,external_size,2},[{type,901,bounded_fun,[{type,901,'fun',[{type,901,product,[{var,901,'Term'},{var,901,'Options'}]},{type,901,non_neg_integer,[]}]},[{type,902,constraint,[{atom,902,is_subtype},[{var,902,'Term'},{type,902,term,[]}]]},{type,903,constraint,[{atom,903,is_subtype},[{var,903,'Options'},{type,903,list,[{type,903,tuple,[{atom,903,minor_version},{ann_type,903,[{var,903,'Version'},{type,903,non_neg_integer,[]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66,48,52>>}},{{function,float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,925}],[<<102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,102,108,111,97,116,32,98,121,32,99,111,110,118,101,114,116,105,110,103,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,97,32,102,108,111,97,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,97,116,40,53,53,41,46,10,53,53,46,48>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,117,115,101,100,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,105,110,32,97,32,103,117,97,114,100,44,32,105,116,32,116,101,115,116,115,32,119,104,101,116,104,101,114,32,116,104,101,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,102,108,111,97,116,105,110,103,32,112,111,105,110,116,32,110,117,109,98,101,114,59,32,102,111,114,32,99,108,97,114,105,116,121,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,115,95,102,108,111,97,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,102,108,111,97,116,47,49>>]}]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<87,104,101,110,32>>,{code,[],[<<102,108,111,97,116,47,49>>]},<<32,105,115,32,117,115,101,100,32,105,110,32,97,110,32,101,120,112,114,101,115,115,105,111,110,32,105,110,32,97,32,103,117,97,114,100,44,32,115,117,99,104,32,97,115,32,39>>,{code,[],[<<102,108,111,97,116,40,65,41,32,61,61,32,52,46,48>>]},<<39,44,32,105,116,32,99,111,110,118,101,114,116,115,32,97,32,110,117,109,98,101,114,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,54,52>>,signature => [{attribute,925,spec,{{float,1},[{type,925,bounded_fun,[{type,925,'fun',[{type,925,product,[{var,925,'Number'}]},{type,925,float,[]}]},[{type,926,constraint,[{atom,926,is_subtype},[{var,926,'Number'},{type,926,number,[]}]]}]]}]}}]}},{{function,float_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,931}],[<<102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,70,108,111,97,116,44,91,123,115,99,105,101,110,116,105,102,105,99,44,50,48,125,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,56,54>>,signature => [{attribute,931,spec,{{float_to_binary,1},[{type,931,bounded_fun,[{type,931,'fun',[{type,931,product,[{var,931,'Float'}]},{type,931,binary,[]}]},[{type,932,constraint,[{atom,932,is_subtype},[{var,932,'Float'},{type,932,float,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,float_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,937}],[<<102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,108,111,97,116>>]},<<32,117,115,105,110,103,32,102,105,120,101,100,32,100,101,99,105,109,97,108,32,112,111,105,110,116,32,102,111,114,109,97,116,116,105,110,103,46,32>>,{code,[],[<<79,112,116,105,111,110,115>>]},<<32,98,101,104,97,118,101,115,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,108,111,97,116,95,116,111,95,108,105,115,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,50>>]}]},<<46,32,69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,93,41,46,10,60,60,34,55,46,49,50,48,48,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,44,32,99,111,109,112,97,99,116,93,41,46,10,60,60,34,55,46,49,50,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,123,115,99,105,101,110,116,105,102,105,99,44,32,51,125,93,41,46,10,60,60,34,55,46,49,50,48,101,43,48,48,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,57,53>>,signature => [{attribute,937,spec,{{float_to_binary,2},[{type,937,bounded_fun,[{type,937,'fun',[{type,937,product,[{var,937,'Float'},{var,937,'Options'}]},{type,937,binary,[]}]},[{type,938,constraint,[{atom,938,is_subtype},[{var,938,'Float'},{type,938,float,[]}]]},{type,939,constraint,[{atom,939,is_subtype},[{var,939,'Options'},{type,939,list,[{var,939,'Option'}]}]]},{type,940,constraint,[{atom,940,is_subtype},[{var,940,'Option'},{type,940,union,[{type,940,tuple,[{atom,940,decimals},{ann_type,940,[{var,940,'Decimals'},{type,940,range,[{integer,940,0},{integer,940,253}]}]}]},{type,941,tuple,[{atom,941,scientific},{ann_type,941,[{var,941,'Decimals'},{type,941,range,[{integer,941,0},{integer,941,249}]}]}]},{atom,942,compact}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,float_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,947}],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,40,70,108,111,97,116,44,91,123,115,99,105,101,110,116,105,102,105,99,44,50,48,125,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,49,53>>,signature => [{attribute,947,spec,{{float_to_list,1},[{type,947,bounded_fun,[{type,947,'fun',[{type,947,product,[{var,947,'Float'}]},{type,947,string,[]}]},[{type,948,constraint,[{atom,948,is_subtype},[{var,948,'Float'},{type,948,float,[]}]]}]]}]}}]}},{{function,float_to_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,953}],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,108,111,97,116>>]},<<32,117,115,105,110,103,32,102,105,120,101,100,32,100,101,99,105,109,97,108,32,112,111,105,110,116,32,102,111,114,109,97,116,116,105,110,103,46>>]},{p,[],[<<65,118,97,105,108,97,98,108,101,32,111,112,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<100,101,99,105,109,97,108,115>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,99,111,110,116,97,105,110,115,32,97,116,32,109,111,115,116,32>>,{code,[],[<<68,101,99,105,109,97,108,115>>]},<<32,110,117,109,98,101,114,32,111,102,32,100,105,103,105,116,115,32,112,97,115,116,32,116,104,101,32,100,101,99,105,109,97,108,32,112,111,105,110,116,46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,116,104,101,32,105,110,116,101,114,110,97,108,32,115,116,97,116,105,99,32,98,117,102,102,101,114,32,111,102,32,50,53,54,32,98,121,116,101,115,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,104,114,111,119,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46>>]}]},{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,97,99,116>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,116,114,97,105,108,105,110,103,32,122,101,114,111,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,108,105,115,116,32,97,114,101,32,116,114,117,110,99,97,116,101,100,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,111,110,108,121,32,109,101,97,110,105,110,103,102,117,108,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<100,101,99,105,109,97,108,115>>]},<<46>>]}]},{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<115,99,105,101,110,116,105,102,105,99>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,108,111,97,116,32,105,115,32,102,111,114,109,97,116,116,101,100,32,117,115,105,110,103,32,115,99,105,101,110,116,105,102,105,99,32,110,111,116,97,116,105,111,110,32,119,105,116,104,32>>,{code,[],[<<68,101,99,105,109,97,108,115>>]},<<32,100,105,103,105,116,115,32,111,102,32,112,114,101,99,105,115,105,111,110,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,115>>]},<<32,105,115,32>>,{code,[],[<<91,93>>]},<<44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,98,101,104,97,118,101,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,108,111,97,116,95,116,111,95,108,105,115,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,49>>]}]},<<46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,93,41,46,10,34,55,46,49,50,48,48,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,44,32,99,111,109,112,97,99,116,93,41,46,10,34,55,46,49,50,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,123,115,99,105,101,110,116,105,102,105,99,44,32,51,125,93,41,46,10,34,55,46,49,50,48,101,43,48,48,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,48,46,49,43,48,46,50,41,10,34,51,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,52,52,48,57,101,45,48,49,34>>]}]},{p,[],[<<73,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,40,48,46,49,43,48,46,50,41>>]},<<32,101,118,97,108,117,97,116,101,115,32,116,111,32>>,{code,[],[<<34,51,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,52,52,48,57,101,45,48,49,34>>]},<<46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,101,120,112,108,97,105,110,101,100,32,105,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,108,111,97,116,95,114,101,112,114,101,115,101,110,116,97,116,105,111,110,95,112,114,111,98,108,101,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,70,108,111,97,116,105,110,103,32,80,111,105,110,116,32,78,117,109,98,101,114,115>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,50,52>>,signature => [{attribute,953,spec,{{float_to_list,2},[{type,953,bounded_fun,[{type,953,'fun',[{type,953,product,[{var,953,'Float'},{var,953,'Options'}]},{type,953,string,[]}]},[{type,954,constraint,[{atom,954,is_subtype},[{var,954,'Float'},{type,954,float,[]}]]},{type,955,constraint,[{atom,955,is_subtype},[{var,955,'Options'},{type,955,list,[{var,955,'Option'}]}]]},{type,956,constraint,[{atom,956,is_subtype},[{var,956,'Option'},{type,956,union,[{type,956,tuple,[{atom,956,decimals},{ann_type,956,[{var,956,'Decimals'},{type,956,range,[{integer,956,0},{integer,956,253}]}]}]},{type,957,tuple,[{atom,957,scientific},{ann_type,957,[{var,957,'Decimals'},{type,957,range,[{integer,957,0},{integer,957,249}]}]}]},{atom,958,compact}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,floor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,964}],[<<102,108,111,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,97,114,103,101,115,116,32,105,110,116,101,103,101,114,32,110,111,116,32,103,114,101,97,116,101,114,32,116,104,97,110,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,111,114,40,45,49,48,46,53,41,46,10,45,49,49>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,55,48>>,signature => [{attribute,964,spec,{{floor,1},[{type,964,bounded_fun,[{type,964,'fun',[{type,964,product,[{var,964,'Number'}]},{type,964,integer,[]}]},[{type,965,constraint,[{atom,965,is_subtype},[{var,965,'Number'},{type,965,number,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,fun_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3434}],[<<102,117,110,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,102,117,110,32>>,{code,[],[<<70,117,110>>]},<<46,32,69,97,99,104,32,108,105,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,116,117,112,108,101,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,110,100,32,109,111,114,101,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,109,97,105,110,108,121,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,44,32,98,117,116,32,105,116,32,99,97,110,32,115,111,109,101,116,105,109,101,115,32,98,101,32,117,115,101,102,117,108,32,105,110,32,108,105,98,114,97,114,121,32,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,110,101,101,100,32,116,111,32,118,101,114,105,102,121,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,114,105,116,121,32,111,102,32,97,32,102,117,110,46>>]}]},{p,[],[<<84,119,111,32,116,121,112,101,115,32,111,102,32,102,117,110,115,32,104,97,118,101,32,115,108,105,103,104,116,108,121,32,100,105,102,102,101,114,101,110,116,32,115,101,109,97,110,116,105,99,115,58>>]},{ul,[],[{li,[],[{p,[],[<<65,32,102,117,110,32,99,114,101,97,116,101,100,32,98,121,32>>,{code,[],[<<102,117,110,32,77,58,70,47,65>>]},<<32,105,115,32,99,97,108,108,101,100,32,97,110,32>>,{em,[],[<<101,120,116,101,114,110,97,108>>]},<<32,102,117,110,46,32,67,97,108,108,105,110,103,32,105,116,32,119,105,108,108,32,97,108,119,97,121,115,32,99,97,108,108,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<70>>]},<<32,119,105,116,104,32,97,114,105,116,121,32>>,{code,[],[<<65>>]},<<32,105,110,32,116,104,101,32,108,97,116,101,115,116,32,99,111,100,101,32,102,111,114,32,109,111,100,117,108,101,32>>,{code,[],[<<77>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,109,111,100,117,108,101,32>>,{code,[],[<<77>>]},<<32,100,111,101,115,32,110,111,116,32,101,118,101,110,32,110,101,101,100,32,116,111,32,98,101,32,108,111,97,100,101,100,32,119,104,101,110,32,116,104,101,32,102,117,110,32>>,{code,[],[<<102,117,110,32,77,58,70,47,65>>]},<<32,105,115,32,99,114,101,97,116,101,100,46>>]}]},{li,[],[{p,[],[<<65,108,108,32,111,116,104,101,114,32,102,117,110,115,32,97,114,101,32,99,97,108,108,101,100,32>>,{em,[],[<<108,111,99,97,108>>]},<<46,32,87,104,101,110,32,97,32,108,111,99,97,108,32,102,117,110,32,105,115,32,99,97,108,108,101,100,44,32,116,104,101,32,115,97,109,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,99,111,100,101,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,102,117,110,32,105,115,32,99,97,108,108,101,100,32,40,101,118,101,110,32,105,102,32,97,32,110,101,119,101,114,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,104,97,115,32,98,101,101,110,32,108,111,97,100,101,100,41,46>>]}]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,108,101,109,101,110,116,115,32,97,114,101,32,97,108,119,97,121,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,32,102,111,114,32,98,111,116,104,32,108,111,99,97,108,32,97,110,100,32,101,120,116,101,114,110,97,108,32,102,117,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,116,121,112,101,44,32,84,121,112,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,111,114,32>>,{code,[],[<<101,120,116,101,114,110,97,108>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,109,111,100,117,108,101,44,32,77,111,100,117,108,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<32,40,97,110,32,97,116,111,109,41,32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,44,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,105,110,32,119,104,105,99,104,32,116,104,101,32,102,117,110,32,105,115,32,100,101,102,105,110,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,110,32,101,120,116,101,114,110,97,108,32,102,117,110,44,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,116,104,97,116,32,116,104,101,32,102,117,110,32,114,101,102,101,114,115,32,116,111,46>>]}]},{dt,[],[{code,[],[<<123,110,97,109,101,44,32,78,97,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<78,97,109,101>>]},<<32,40,97,110,32,97,116,111,109,41,32,105,115,32,97,32,102,117,110,99,116,105,111,110,32,110,97,109,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,44,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,105,109,112,108,101,109,101,110,116,115,32,116,104,101,32,102,117,110,46,32,40,84,104,105,115,32,110,97,109,101,32,119,97,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,116,104,101,32,99,111,109,112,105,108,101,114,44,32,97,110,100,32,105,115,32,111,110,108,121,32,111,102,32,105,110,102,111,114,109,97,116,105,111,110,97,108,32,117,115,101,46,32,65,115,32,105,116,32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,44,32,105,116,32,99,97,110,110,111,116,32,98,101,32,99,97,108,108,101,100,32,100,105,114,101,99,116,108,121,46,41,32,73,102,32,110,111,32,99,111,100,101,32,105,115,32,99,117,114,114,101,110,116,108,121,32,108,111,97,100,101,100,32,102,111,114,32,116,104,101,32,102,117,110,44,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,32,111,102,32,97,110,32,97,116,111,109,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,110,32,101,120,116,101,114,110,97,108,32,102,117,110,44,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,112,111,114,116,101,100,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,116,104,101,32,102,117,110,32,114,101,102,101,114,115,32,116,111,46>>]}]},{dt,[],[{code,[],[<<123,97,114,105,116,121,44,32,65,114,105,116,121,125>>]}]},{dd,[],[{p,[],[{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,114,103,117,109,101,110,116,115,32,116,104,97,116,32,116,104,101,32,102,117,110,32,105,115,32,116,111,32,98,101,32,99,97,108,108,101,100,32,119,105,116,104,46>>]}]},{dt,[],[{code,[],[<<123,101,110,118,44,32,69,110,118,125>>]}]},{dd,[],[{p,[],[{code,[],[<<69,110,118>>]},<<32,40,97,32,108,105,115,116,41,32,105,115,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,111,114,32,102,114,101,101,32,118,97,114,105,97,98,108,101,115,32,102,111,114,32,116,104,101,32,102,117,110,46,32,70,111,114,32,101,120,116,101,114,110,97,108,32,102,117,110,115,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,105,115,32,97,108,119,97,121,115,32,101,109,112,116,121,46>>]}]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,108,101,109,101,110,116,115,32,97,114,101,32,111,110,108,121,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,32,105,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,108,111,99,97,108,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,105,100,44,32,80,105,100,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,111,114,105,103,105,110,97,108,108,121,32,99,114,101,97,116,101,100,32,116,104,101,32,102,117,110,46>>]},{p,[],[<<73,116,32,109,105,103,104,116,32,112,111,105,110,116,32,116,111,32,116,104,101,32>>,{code,[],[<<105,110,105,116>>]},<<32,112,114,111,99,101,115,115,32,105,102,32,116,104,101,32>>,{code,[],[<<70,117,110>>]},<<32,119,97,115,32,115,116,97,116,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,119,104,101,110,32,109,111,100,117,108,101,32,119,97,115,32,108,111,97,100,101,100,32,40,116,104,105,115,32,111,112,116,105,109,105,115,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,102,111,114,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,100,111,32,110,111,116,32,99,97,112,116,117,114,101,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,41,46>>]}]},{dt,[],[{code,[],[<<123,105,110,100,101,120,44,32,73,110,100,101,120,125>>]}]},{dd,[],[{p,[],[{code,[],[<<73,110,100,101,120>>]},<<32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,115,32,97,110,32,105,110,100,101,120,32,105,110,116,111,32,116,104,101,32,109,111,100,117,108,101,32,102,117,110,32,116,97,98,108,101,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,95,105,110,100,101,120,44,32,73,110,100,101,120,125>>]}]},{dd,[],[{p,[],[{code,[],[<<73,110,100,101,120>>]},<<32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,115,32,97,110,32,105,110,100,101,120,32,105,110,116,111,32,116,104,101,32,109,111,100,117,108,101,32,102,117,110,32,116,97,98,108,101,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,95,117,110,105,113,44,32,85,110,105,113,125>>]}]},{dd,[],[{p,[],[{code,[],[<<85,110,105,113>>]},<<32,40,97,32,98,105,110,97,114,121,41,32,105,115,32,97,32,117,110,105,113,117,101,32,118,97,108,117,101,32,102,111,114,32,116,104,105,115,32,102,117,110,46,32,73,116,32,105,115,32,99,97,108,99,117,108,97,116,101,100,32,102,114,111,109,32,116,104,101,32,99,111,109,112,105,108,101,100,32,99,111,100,101,32,102,111,114,32,116,104,101,32,101,110,116,105,114,101,32,109,111,100,117,108,101,46>>]}]},{dt,[],[{code,[],[<<123,117,110,105,113,44,32,85,110,105,113,125>>]}]},{dd,[],[{p,[],[{code,[],[<<85,110,105,113>>]},<<32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,115,32,97,32,117,110,105,113,117,101,32,118,97,108,117,101,32,102,111,114,32,116,104,105,115,32,102,117,110,46,32,65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,53,44,32,116,104,105,115,32,105,110,116,101,103,101,114,32,105,115,32,99,97,108,99,117,108,97,116,101,100,32,102,114,111,109,32,116,104,101,32,99,111,109,112,105,108,101,100,32,99,111,100,101,32,102,111,114,32,116,104,101,32,101,110,116,105,114,101,32,109,111,100,117,108,101,46,32,66,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,53,44,32,116,104,105,115,32,105,110,116,101,103,101,114,32,119,97,115,32,98,97,115,101,100,32,111,110,32,111,110,108,121,32,116,104,101,32,98,111,100,121,32,111,102,32,116,104,101,32,102,117,110,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,56,52>>,signature => [{attribute,3434,spec,{{erlang,fun_info,1},[{type,3434,bounded_fun,[{type,3434,'fun',[{type,3434,product,[{var,3434,'Fun'}]},{type,3434,list,[{type,3434,tuple,[{var,3434,'Item'},{var,3434,'Info'}]}]}]},[{type,3435,constraint,[{atom,3435,is_subtype},[{var,3435,'Fun'},{type,3435,function,[]}]]},{type,3436,constraint,[{atom,3436,is_subtype},[{var,3436,'Item'},{type,3436,union,[{atom,3436,arity},{atom,3436,env},{atom,3436,index},{atom,3436,name},{atom,3437,module},{atom,3437,new_index},{atom,3437,new_uniq},{atom,3437,pid},{atom,3437,type},{atom,3437,uniq}]}]]},{type,3438,constraint,[{atom,3438,is_subtype},[{var,3438,'Info'},{type,3438,term,[]}]]}]]}]}}]}},{{function,fun_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,970}],[<<102,117,110,95,105,110,102,111,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<102,117,110,95,105,110,102,111,95,105,116,101,109>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32>>,{code,[],[<<70,117,110>>]},<<32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<44,32,105,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,73,116,101,109,44,73,110,102,111,125>>]},<<46>>]},{p,[],[<<70,111,114,32,97,110,121,32,102,117,110,44,32>>,{code,[],[<<73,116,101,109>>]},<<32,99,97,110,32,98,101,32,97,110,121,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<109,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<110,97,109,101>>]},<<44,32>>,{code,[],[<<97,114,105,116,121>>]},<<44,32>>,{code,[],[<<101,110,118>>]},<<44,32,111,114,32>>,{code,[],[<<116,121,112,101>>]},<<46>>]},{p,[],[<<70,111,114,32,97,32,108,111,99,97,108,32,102,117,110,44,32>>,{code,[],[<<73,116,101,109>>]},<<32,99,97,110,32,97,108,115,111,32,98,101,32,97,110,121,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<105,110,100,101,120>>]},<<44,32>>,{code,[],[<<110,101,119,95,105,110,100,101,120>>]},<<44,32>>,{code,[],[<<110,101,119,95,117,110,105,113>>]},<<44,32>>,{code,[],[<<117,110,105,113>>]},<<44,32,97,110,100,32>>,{code,[],[<<112,105,100>>]},<<46,32,70,111,114,32,97,110,32,101,120,116,101,114,110,97,108,32,102,117,110,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,97,110,121,32,111,102,32,116,104,101,115,101,32,105,116,101,109,115,32,105,115,32,97,108,119,97,121,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,117,110,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,102,117,110,95,105,110,102,111,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,49,56,57>>,signature => [{attribute,970,spec,{{erlang,fun_info,2},[{type,970,bounded_fun,[{type,970,'fun',[{type,970,product,[{var,970,'Fun'},{var,970,'Item'}]},{type,970,tuple,[{var,970,'Item'},{var,970,'Info'}]}]},[{type,971,constraint,[{atom,971,is_subtype},[{var,971,'Fun'},{type,971,function,[]}]]},{type,972,constraint,[{atom,972,is_subtype},[{var,972,'Item'},{user_type,972,fun_info_item,[]}]]},{type,973,constraint,[{atom,973,is_subtype},[{var,973,'Info'},{type,973,term,[]}]]}]]}]}}]}},{{function,fun_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,987}],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,116,104,97,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,99,111,100,101,32,116,104,97,116,32,99,114,101,97,116,101,100,32>>,{code,[],[<<70,117,110>>]},<<46>>]},{p,[],[{code,[],[<<83,116,114,105,110,103>>]},<<32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,44,32,105,102,32>>,{code,[],[<<70,117,110>>]},<<32,119,97,115,32,99,114,101,97,116,101,100,32,98,121,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,102,117,110,45,101,120,112,114,101,115,115,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<102,117,110,32,101,120,112,114,101,115,115,105,111,110>>]},<<32,111,102,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<102,117,110,32,77,111,100,117,108,101,78,97,109,101,58,70,117,110,99,78,97,109,101,47,65,114,105,116,121>>]},<<58>>]},{p,[],[{code,[],[<<34,102,117,110,32,77,111,100,117,108,101,78,97,109,101,58,70,117,110,99,78,97,109,101,47,65,114,105,116,121,34>>]}]},{p,[],[<<84,104,101,32,102,111,114,109,32,111,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,119,104,101,110,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,99,114,101,97,116,101,100,32,102,114,111,109,32,111,116,104,101,114,32,116,121,112,101,115,32,111,102,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,102,117,110,45,101,120,112,114,101,115,115,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<102,117,110,32,101,120,112,114,101,115,115,105,111,110,115>>]},<<32,100,105,102,102,101,114,115,32,100,101,112,101,110,100,105,110,103,32,111,110,32,105,102,32,116,104,101,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,101,120,101,99,117,116,101,100,32,119,104,105,108,101,32,101,120,101,99,117,116,105,110,103,32,99,111,109,112,105,108,101,100,32,99,111,100,101,32,111,114,32,105,102,32,116,104,101,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,101,120,101,99,117,116,101,100,32,119,104,105,108,101,32,101,120,101,99,117,116,105,110,103,32,117,110,99,111,109,112,105,108,101,100,32,99,111,100,101,32,40,117,110,99,111,109,112,105,108,101,100,32,101,115,99,114,105,112,116,115,44,32,116,104,101,32,69,114,108,97,110,103,32,115,104,101,108,108,44,32,97,110,100,32,111,116,104,101,114,32,99,111,100,101,32,101,120,101,99,117,116,101,100,32,98,121,32,116,104,101,32,101,114,108,95,101,118,97,108,32,109,111,100,117,108,101,41,58>>]},{dl,[],[{dt,[],[<<99,111,109,112,105,108,101,100,32,99,111,100,101>>]},{dd,[],[{p,[],[{code,[],[<<34,35,70,117,110,60,77,46,73,46,85,62,34>>]},<<44,32,119,104,101,114,101,32,77,44,32,73,32,97,110,100,32,85,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,116,104,101,32,118,97,108,117,101,115,32,110,97,109,101,100,32>>,{code,[],[<<109,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<105,110,100,101,120>>]},<<32,97,110,100,32>>,{code,[],[<<117,110,105,113>>]},<<32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,117,110,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,102,117,110,95,105,110,102,111,40,70,117,110,41>>]}]},<<46>>]}]},{dt,[],[<<117,110,99,111,109,112,105,108,101,100,32,99,111,100,101>>]},{dd,[],[<<65,108,108,32,102,117,110,115,32,99,114,101,97,116,101,100,32,102,114,111,109,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,117,110,99,111,109,112,105,108,101,100,32,99,111,100,101,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,97,114,105,116,121,32,97,114,101,32,109,97,112,112,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,108,105,115,116,32,98,121,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<71,101,110,101,114,97,108,108,121,44,32,111,110,101,32,99,97,110,32,110,111,116,32,117,115,101,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<32,116,111,32,99,104,101,99,107,32,105,102,32,116,119,111,32,102,117,110,115,32,97,114,101,32,101,113,117,97,108,32,97,115,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<32,100,111,101,115,32,110,111,116,32,116,97,107,101,32,116,104,101,32,102,117,110,39,115,32,101,110,118,105,114,111,110,109,101,110,116,32,105,110,116,111,32,97,99,99,111,117,110,116,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,117,110,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,102,117,110,95,105,110,102,111,47,49>>]}]},<<32,102,111,114,32,104,111,119,32,116,111,32,103,101,116,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,111,102,32,97,32,102,117,110,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,111,117,116,112,117,116,32,111,102,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,69,114,108,97,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,32,97,110,100,32,109,97,121,32,99,104,97,110,103,101,32,105,110,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,115,46>>]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<45,109,111,100,117,108,101,40,116,101,115,116,41,46,10,45,101,120,112,111,114,116,40,91,97,100,100,47,49,44,32,97,100,100,50,47,48,44,32,102,117,110,95,116,117,112,108,101,47,48,93,41,46,10,97,100,100,40,65,41,32,45,62,32,102,117,110,40,66,41,32,45,62,32,65,32,43,32,66,32,101,110,100,46,10,97,100,100,50,40,41,32,45,62,32,102,117,110,32,97,100,100,47,49,46,10,102,117,110,95,116,117,112,108,101,40,41,32,45,62,32,123,102,117,110,40,41,32,45,62,32,49,32,101,110,100,44,32,102,117,110,40,41,32,45,62,32,49,32,101,110,100,125,46,10,32,32,32,32,32,32,32,32>>]}]},{pre,[],[{code,[],[<<62,32,123,102,117,110,32,116,101,115,116,58,97,100,100,47,49,44,32,116,101,115,116,58,97,100,100,50,40,41,125,46,10,123,102,117,110,32,116,101,115,116,58,97,100,100,47,49,44,35,70,117,110,60,116,101,115,116,46,49,46,49,48,55,55,51,56,57,56,51,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32>>,{code,[],[<<102,117,110,32,116,101,115,116,58,97,100,100,47,49>>]},<<32,105,115,32,117,112,103,114,97,100,97,98,108,101,32,98,117,116,32>>,{code,[],[<<116,101,115,116,58,97,100,100,50,40,41>>]},<<32,105,115,32,110,111,116,32,117,112,103,114,97,100,97,98,108,101,46>>]},{pre,[],[{code,[],[<<62,32,123,116,101,115,116,58,97,100,100,40,49,41,44,32,116,101,115,116,58,97,100,100,40,52,50,41,125,46,10,123,35,70,117,110,60,116,101,115,116,46,48,46,49,48,55,55,51,56,57,56,51,62,44,35,70,117,110,60,116,101,115,116,46,48,46,49,48,55,55,51,56,57,56,51,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32>>,{code,[],[<<116,101,115,116,58,97,100,100,40,49,41>>]},<<32,97,110,100,32>>,{code,[],[<<116,101,115,116,58,97,100,100,40,52,50,41>>]},<<32,104,97,115,32,116,104,101,32,115,97,109,101,32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,97,115,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,105,115,32,110,111,116,32,116,97,107,101,110,32,105,110,116,111,32,97,99,99,111,117,110,116,46>>]},{pre,[],[{code,[],[<<62,116,101,115,116,58,102,117,110,95,116,117,112,108,101,40,41,46,10,123,35,70,117,110,60,116,101,115,116,46,50,46,49,48,55,55,51,56,57,56,51,62,44,35,70,117,110,60,116,101,115,116,46,51,46,49,48,55,55,51,56,57,56,51,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32,84,104,101,32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,115,32,100,105,102,102,101,114,32,98,101,99,97,117,115,101,32,116,104,101,32,102,117,110,115,32,99,111,109,101,32,102,114,111,109,32,100,105,102,102,101,114,101,110,116,32,102,117,110,32,101,120,112,101,114,115,115,105,111,110,115,46>>]},{pre,[],[{code,[],[<<62,32,123,102,117,110,40,41,32,45,62,32,49,32,101,110,100,44,32,102,117,110,40,41,32,45,62,32,49,32,101,110,100,125,46,32,62,32,10,123,35,70,117,110,60,101,114,108,95,101,118,97,108,46,52,53,46,57,55,50,56,51,48,57,53,62,44,35,70,117,110,60,101,114,108,95,101,118,97,108,46,52,53,46,57,55,50,56,51,48,57,53,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32,65,108,108,32,102,117,110,115,32,99,114,101,97,116,101,100,32,102,114,111,109,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,115,32,111,102,32,116,104,105,115,32,102,111,114,109,32,105,110,32,117,110,99,111,109,112,105,108,101,100,32,99,111,100,101,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,97,114,105,116,121,32,97,114,101,32,109,97,112,112,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,108,105,115,116,32,98,121,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,50,48,57>>,signature => [{attribute,987,spec,{{erlang,fun_to_list,1},[{type,987,bounded_fun,[{type,987,'fun',[{type,987,product,[{var,987,'Fun'}]},{ann_type,987,[{var,987,'String'},{type,987,string,[]}]}]},[{type,988,constraint,[{atom,988,is_subtype},[{var,988,'Fun'},{type,988,function,[]}]]}]]}]}}]}},{{function,function_exported,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,993}],[<<102,117,110,99,116,105,111,110,95,101,120,112,111,114,116,101,100,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,108,111,97,100,101,100,32,97,110,100,32,99,111,110,116,97,105,110,115,32,97,110,32,101,120,112,111,114,116,101,100,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<44,32,111,114,32,105,102,32,116,104,101,114,101,32,105,115,32,97,32,66,73,70,32,40,97,32,98,117,105,108,116,45,105,110,32,102,117,110,99,116,105,111,110,32,105,109,112,108,101,109,101,110,116,101,100,32,105,110,32,67,41,32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,110,97,109,101,44,32,111,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,117,115,101,100,32,116,111,32,114,101,116,117,114,110,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,102,111,114,32,66,73,70,115,32,98,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,49,56,46,48,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,50,57,56>>,signature => [{attribute,993,spec,{{erlang,function_exported,3},[{type,993,bounded_fun,[{type,993,'fun',[{type,993,product,[{var,993,'Module'},{var,993,'Function'},{var,993,'Arity'}]},{type,993,boolean,[]}]},[{type,994,constraint,[{atom,994,is_subtype},[{var,994,'Module'},{type,994,module,[]}]]},{type,995,constraint,[{atom,995,is_subtype},[{var,995,'Function'},{type,995,atom,[]}]]},{type,996,constraint,[{atom,996,is_subtype},[{var,996,'Arity'},{type,996,arity,[]}]]}]]}]}}]}},{{function,garbage_collect,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1001}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>],#{<<101,110>> => [{p,[],[<<70,111,114,99,101,115,32,97,110,32,105,109,109,101,100,105,97,116,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,116,104,101,32,101,120,101,99,117,116,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,117,110,108,101,115,115,32,105,116,32,104,97,115,32,98,101,101,110,32,110,111,116,105,99,101,100,32,40,111,114,32,116,104,101,114,101,32,97,114,101,32,103,111,111,100,32,114,101,97,115,111,110,115,32,116,111,32,115,117,115,112,101,99,116,41,32,116,104,97,116,32,116,104,101,32,115,112,111,110,116,97,110,101,111,117,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,119,105,108,108,32,111,99,99,117,114,32,116,111,111,32,108,97,116,101,32,111,114,32,110,111,116,32,97,116,32,97,108,108,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,109,112,114,111,112,101,114,32,117,115,101,32,99,97,110,32,115,101,114,105,111,117,115,108,121,32,100,101,103,114,97,100,101,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,49,52>>,signature => [{attribute,1001,spec,{{garbage_collect,0},[{type,1001,'fun',[{type,1001,product,[]},{atom,1001,true}]}]}}]}},{{function,garbage_collect,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1006}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,40,80,105,100,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,51,48>>,signature => [{attribute,1006,spec,{{garbage_collect,1},[{type,1006,bounded_fun,[{type,1006,'fun',[{type,1006,product,[{var,1006,'Pid'}]},{var,1006,'GCResult'}]},[{type,1007,constraint,[{atom,1007,is_subtype},[{var,1007,'Pid'},{type,1007,pid,[]}]]},{type,1008,constraint,[{atom,1008,is_subtype},[{var,1008,'GCResult'},{type,1008,boolean,[]}]]}]]}]}}]}},{{function,garbage_collect,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1022}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<71,97,114,98,97,103,101,32,99,111,108,108,101,99,116,115,32,116,104,101,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,82,101,113,117,101,115,116,73,100,125>>]}]},{dd,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,50>>]},<<32,114,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,115,101,110,116,46,32,87,104,101,110,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,44,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,97,108,108,101,100,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,112,97,115,115,101,100,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,44,32,82,101,113,117,101,115,116,73,100,44,32,71,67,82,101,115,117,108,116,125>>]},<<46>>]},{dt,[],[{code,[],[<<123,116,121,112,101,44,32,39,109,97,106,111,114,39,32,124,32,39,109,105,110,111,114,39,125>>]}]},{dd,[],[<<84,114,105,103,103,101,114,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,114,101,113,117,101,115,116,101,100,32,116,121,112,101,46,32,68,101,102,97,117,108,116,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<39,109,97,106,111,114,39>>]},<<44,32,119,104,105,99,104,32,119,111,117,108,100,32,116,114,105,103,103,101,114,32,97,32,102,117,108,108,115,119,101,101,112,32,71,67,46,32,84,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<39,109,105,110,111,114,39>>]},<<32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,104,105,110,116,32,97,110,100,32,109,97,121,32,108,101,97,100,32,116,111,32,101,105,116,104,101,114,32,109,105,110,111,114,32,111,114,32,109,97,106,111,114,32,71,67,32,114,117,110,46>>]}]},{p,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<115,101,108,102,40,41>>]},<<44,32,97,110,100,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,116,32,111,110,99,101,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>]}]},<<46,32,79,116,104,101,114,119,105,115,101,32,97,32,114,101,113,117,101,115,116,32,102,111,114,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,97,110,100,32,119,105,108,108,32,98,101,32,104,97,110,100,108,101,100,32,119,104,101,110,32,97,112,112,114,111,112,114,105,97,116,101,46,32,73,102,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,98,108,111,99,107,115,32,117,110,116,105,108,32>>,{code,[],[<<71,67,82,101,115,117,108,116>>]},<<32,105,115,32,97,118,97,105,108,97,98,108,101,32,97,110,100,32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<71,67,82,101,115,117,108,116>>]},<<32,105,110,102,111,114,109,115,32,97,98,111,117,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,114,101,113,117,101,115,116,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,104,97,115,32,98,101,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46>>]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[<<78,111,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,119,97,115,32,112,101,114,102,111,114,109,101,100,44,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,116,101,114,109,105,110,97,116,101,100,32,98,101,102,111,114,101,32,116,104,101,32,114,101,113,117,101,115,116,32,99,111,117,108,100,32,98,101,32,115,97,116,105,115,102,105,101,100,46>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,115,97,109,101,32,99,97,118,101,97,116,115,32,97,112,112,108,121,32,97,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,52,48>>,signature => [{attribute,1022,spec,{{garbage_collect,2},[{type,1022,bounded_fun,[{type,1022,'fun',[{type,1022,product,[{var,1022,'Pid'},{var,1022,'OptionList'}]},{type,1022,union,[{var,1022,'GCResult'},{atom,1022,async}]}]},[{type,1023,constraint,[{atom,1023,is_subtype},[{var,1023,'Pid'},{type,1023,pid,[]}]]},{type,1024,constraint,[{atom,1024,is_subtype},[{var,1024,'RequestId'},{type,1024,term,[]}]]},{type,1025,constraint,[{atom,1025,is_subtype},[{var,1025,'Option'},{type,1025,union,[{type,1025,tuple,[{atom,1025,async},{var,1025,'RequestId'}]},{type,1025,tuple,[{atom,1025,type},{type,1025,union,[{atom,1025,major},{atom,1025,minor}]}]}]}]]},{type,1026,constraint,[{atom,1026,is_subtype},[{var,1026,'OptionList'},{type,1026,list,[{var,1026,'Option'}]}]]},{type,1027,constraint,[{atom,1027,is_subtype},[{var,1027,'GCResult'},{type,1027,boolean,[]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,get,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1076}],[<<103,101,116,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,97,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,75,101,121,44,32,86,97,108,125>>]},<<32,116,117,112,108,101,115,46,32,84,104,101,32,105,116,101,109,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,105,110,32,97,110,121,32,111,114,100,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,109,101,114,114,121,41,44,10,112,117,116,40,107,101,121,50,44,32,108,97,109,98,115,41,44,10,112,117,116,40,107,101,121,51,44,32,123,97,114,101,44,32,112,108,97,121,105,110,103,125,41,44,10,103,101,116,40,41,46,10,91,123,107,101,121,49,44,109,101,114,114,121,125,44,123,107,101,121,50,44,108,97,109,98,115,125,44,123,107,101,121,51,44,123,97,114,101,44,112,108,97,121,105,110,103,125,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,48,53>>,signature => [{attribute,1076,spec,{{get,0},[{type,1076,bounded_fun,[{type,1076,'fun',[{type,1076,product,[]},{type,1076,list,[{type,1076,tuple,[{var,1076,'Key'},{var,1076,'Val'}]}]}]},[{type,1077,constraint,[{atom,1077,is_subtype},[{var,1077,'Key'},{type,1077,term,[]}]]},{type,1078,constraint,[{atom,1078,is_subtype},[{var,1078,'Val'},{type,1078,term,[]}]]}]]}]}}]}},{{function,get,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1083}],[<<103,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32>>,{code,[],[<<75,101,121>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,84,104,101,32,101,120,112,101,99,116,101,100,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,79,40>>,{code,[],[<<49>>]},<<41,32,97,110,100,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,105,115,32,79,40>>,{code,[],[<<78>>]},<<41,44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,105,116,101,109,115,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,109,101,114,114,121,41,44,10,112,117,116,40,107,101,121,50,44,32,108,97,109,98,115,41,44,10,112,117,116,40,123,97,110,121,44,32,91,118,97,108,105,100,44,32,116,101,114,109,93,125,44,32,123,97,114,101,44,32,112,108,97,121,105,110,103,125,41,44,10,103,101,116,40,123,97,110,121,44,32,91,118,97,108,105,100,44,32,116,101,114,109,93,125,41,46,10,123,97,114,101,44,112,108,97,121,105,110,103,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,50,50>>,signature => [{attribute,1083,spec,{{get,1},[{type,1083,bounded_fun,[{type,1083,'fun',[{type,1083,product,[{var,1083,'Key'}]},{type,1083,union,[{var,1083,'Val'},{atom,1083,undefined}]}]},[{type,1084,constraint,[{atom,1084,is_subtype},[{var,1084,'Key'},{type,1084,term,[]}]]},{type,1085,constraint,[{atom,1085,is_subtype},[{var,1085,'Val'},{type,1085,term,[]}]]}]]}]}}]}},{{function,get_cookie,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3794}],[<<103,101,116,95,99,111,111,107,105,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,103,105,99,32,99,111,111,107,105,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,102,32,116,104,101,32,110,111,100,101,32,105,115,32,97,108,105,118,101,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,99,111,111,107,105,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,52,50>>,signature => [{attribute,3794,spec,{{erlang,get_cookie,0},[{type,3794,bounded_fun,[{type,3794,'fun',[{type,3794,product,[]},{type,3794,union,[{var,3794,'Cookie'},{atom,3794,nocookie}]}]},[{type,3795,constraint,[{atom,3795,is_subtype},[{var,3795,'Cookie'},{type,3795,atom,[]}]]}]]}]}}]}},{{function,get_keys,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1090}],[<<103,101,116,95,107,101,121,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,108,108,32,107,101,121,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,84,104,101,32,105,116,101,109,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,105,110,32,97,110,121,32,111,114,100,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,100,111,103,44,32,123,97,110,105,109,97,108,44,49,125,41,44,10,112,117,116,40,99,111,119,44,32,123,97,110,105,109,97,108,44,50,125,41,44,10,112,117,116,40,108,97,109,98,44,32,123,97,110,105,109,97,108,44,51,125,41,44,10,103,101,116,95,107,101,121,115,40,41,46,10,91,100,111,103,44,99,111,119,44,108,97,109,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,53,49>>,signature => [{attribute,1090,spec,{{get_keys,0},[{type,1090,bounded_fun,[{type,1090,'fun',[{type,1090,product,[]},{type,1090,list,[{var,1090,'Key'}]}]},[{type,1091,constraint,[{atom,1091,is_subtype},[{var,1091,'Key'},{type,1091,term,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,get_keys,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1096}],[<<103,101,116,95,107,101,121,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,107,101,121,115,32,116,104,97,116,32,97,114,101,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,84,104,101,32,105,116,101,109,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,105,110,32,97,110,121,32,111,114,100,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,109,97,114,121,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,104,97,100,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,97,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,108,105,116,116,108,101,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,100,111,103,44,32,123,49,44,32,51,125,41,44,10,112,117,116,40,108,97,109,98,44,32,123,49,44,32,50,125,41,44,10,103,101,116,95,107,101,121,115,40,123,49,44,32,50,125,41,46,10,91,109,97,114,121,44,104,97,100,44,97,44,108,105,116,116,108,101,44,108,97,109,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,54,56>>,signature => [{attribute,1096,spec,{{get_keys,1},[{type,1096,bounded_fun,[{type,1096,'fun',[{type,1096,product,[{var,1096,'Val'}]},{type,1096,list,[{var,1096,'Key'}]}]},[{type,1097,constraint,[{atom,1097,is_subtype},[{var,1097,'Val'},{type,1097,term,[]}]]},{type,1098,constraint,[{atom,1098,is_subtype},[{var,1098,'Key'},{type,1098,term,[]}]]}]]}]}}]}},{{function,group_leader,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1110}],[<<103,114,111,117,112,95,108,101,97,100,101,114,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,46>>]},{p,[],[<<69,118,101,114,121,32,112,114,111,99,101,115,115,32,105,115,32,97,32,109,101,109,98,101,114,32,111,102,32,115,111,109,101,32,112,114,111,99,101,115,115,32,103,114,111,117,112,32,97,110,100,32,97,108,108,32,103,114,111,117,112,115,32,104,97,118,101,32,97,32>>,{em,[],[<<103,114,111,117,112,32,108,101,97,100,101,114>>]},<<46,32,65,108,108,32,73,47,79,32,102,114,111,109,32,116,104,101,32,103,114,111,117,112,32,105,115,32,99,104,97,110,110,101,108,101,100,32,116,111,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,46,32,87,104,101,110,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,112,97,119,110,101,100,44,32,105,116,32,103,101,116,115,32,116,104,101,32,115,97,109,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,97,115,32,116,104,101,32,115,112,97,119,110,105,110,103,32,112,114,111,99,101,115,115,46,32,73,110,105,116,105,97,108,108,121,44,32,97,116,32,115,121,115,116,101,109,32,115,116,97,114,116,117,112,44,32>>,{code,[],[<<105,110,105,116>>]},<<32,105,115,32,98,111,116,104,32,105,116,115,32,111,119,110,32,103,114,111,117,112,32,108,101,97,100,101,114,32,97,110,100,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,111,102,32,97,108,108,32,112,114,111,99,101,115,115,101,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,56,56>>,signature => [{attribute,1110,spec,{{group_leader,0},[{type,1110,'fun',[{type,1110,product,[]},{type,1110,pid,[]}]}]}}]}},{{function,group_leader,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1115}],[<<103,114,111,117,112,95,108,101,97,100,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<32,116,111,32>>,{code,[],[<<71,114,111,117,112,76,101,97,100,101,114>>]},<<46,32,84,121,112,105,99,97,108,108,121,44,32,116,104,105,115,32,105,115,32,117,115,101,100,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,102,114,111,109,32,97,32,99,101,114,116,97,105,110,32,115,104,101,108,108,32,105,115,32,116,111,32,104,97,118,101,32,97,110,111,116,104,101,114,32,103,114,111,117,112,32,108,101,97,100,101,114,32,116,104,97,110,32>>,{code,[],[<<105,110,105,116>>]},<<46>>]},{p,[],[<<84,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,115,104,111,117,108,100,32,98,101,32,114,97,114,101,108,121,32,99,104,97,110,103,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,115,32,119,105,116,104,32,97,32,115,117,112,101,114,118,105,115,105,111,110,32,116,114,101,101,44,32,98,101,99,97,117,115,101,32,79,84,80,32,97,115,115,117,109,101,115,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,111,102,32,116,104,101,105,114,32,112,114,111,99,101,115,115,101,115,32,105,115,32,116,104,101,105,114,32,97,112,112,108,105,99,97,116,105,111,110,32,109,97,115,116,101,114,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,114,111,117,112,95,108,101,97,100,101,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,114,111,117,112,95,108,101,97,100,101,114,47,48>>]}]},<<32,97,110,100,32>>,{a,[{href,<<115,121,115,116,101,109,47,100,101,115,105,103,110,95,112,114,105,110,99,105,112,108,101,115,58,97,112,112,108,105,99,97,116,105,111,110,115,35,115,116,111,112,112,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,84,80,32,100,101,115,105,103,110,32,112,114,105,110,99,105,112,108,101,115>>]},<<32,114,101,108,97,116,101,100,32,116,111,32,115,116,97,114,116,105,110,103,32,97,110,100,32,115,116,111,112,112,105,110,103,32,97,112,112,108,105,99,97,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,48,51>>,signature => [{attribute,1115,spec,{{group_leader,2},[{type,1115,bounded_fun,[{type,1115,'fun',[{type,1115,product,[{var,1115,'GroupLeader'},{var,1115,'Pid'}]},{atom,1115,true}]},[{type,1116,constraint,[{atom,1116,is_subtype},[{var,1116,'GroupLeader'},{type,1116,pid,[]}]]},{type,1117,constraint,[{atom,1117,is_subtype},[{var,1117,'Pid'},{type,1117,pid,[]}]]}]]}]}}]}},{{function,halt,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1135}],[<<104,97,108,116,47,48>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,104,97,108,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<104,97,108,116,40,48,44,32,91,93,41>>]}]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,104,97,108,116,40,41,46,10,111,115,95,112,114,111,109,112,116,37>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,50,52>>,signature => [{attribute,1135,spec,{{halt,0},[{type,1135,'fun',[{type,1135,product,[]},{type,1135,no_return,[]}]}]}}]}},{{function,halt,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1141}],[<<104,97,108,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,104,97,108,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<104,97,108,116,40,83,116,97,116,117,115,44,32,91,93,41>>]}]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,104,97,108,116,40,49,55,41,46,10,111,115,95,112,114,111,109,112,116,37,32,101,99,104,111,32,36,63,10,49,55,10,111,115,95,112,114,111,109,112,116,37>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,51,55>>,signature => [{attribute,1141,spec,{{halt,1},[{type,1141,bounded_fun,[{type,1141,'fun',[{type,1141,product,[{var,1141,'Status'}]},{type,1141,no_return,[]}]},[{type,1142,constraint,[{atom,1142,is_subtype},[{var,1142,'Status'},{type,1142,union,[{type,1142,non_neg_integer,[]},{atom,1142,abort},{type,1142,string,[]}]}]]}]]}]}}]}},{{function,halt,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1153}],[<<104,97,108,116,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<83,116,97,116,117,115>>]},<<32,109,117,115,116,32,98,101,32,97,32,110,111,110,45,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,44,32,97,32,115,116,114,105,110,103,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<97,98,111,114,116>>]},<<46,32,72,97,108,116,115,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,72,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,68,101,112,101,110,100,105,110,103,32,111,110,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,99,99,117,114,115,58>>]},{dl,[],[{dt,[],[<<105,110,116,101,103,101,114,40,41>>]},{dd,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,101,120,105,116,115,32,119,105,116,104,32,105,110,116,101,103,101,114,32,118,97,108,117,101,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<32,97,115,32,115,116,97,116,117,115,32,99,111,100,101,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,101,110,118,105,114,111,110,109,101,110,116,32,40,79,83,41,46>>,{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,32,109,97,110,121,32,112,108,97,116,102,111,114,109,115,44,32,116,104,101,32,79,83,32,115,117,112,112,111,114,116,115,32,111,110,108,121,32,115,116,97,116,117,115,32,99,111,100,101,115,32,48,45,50,53,53,46,32,65,32,116,111,111,32,108,97,114,103,101,32,115,116,97,116,117,115,32,99,111,100,101,32,105,115,32,116,114,117,110,99,97,116,101,100,32,98,121,32,99,108,101,97,114,105,110,103,32,116,104,101,32,104,105,103,104,32,98,105,116,115,46>>]}]}]},{dt,[],[<<115,116,114,105,110,103,40,41>>]},{dd,[],[<<65,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,32,105,115,32,112,114,111,100,117,99,101,100,32,119,105,116,104,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<32,97,115,32,115,108,111,103,97,110,46,32,84,104,101,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,101,120,105,116,115,32,119,105,116,104,32,115,116,97,116,117,115,32,99,111,100,101,32>>,{code,[],[<<49>>]},<<46,32,84,104,101,32,115,116,114,105,110,103,32,119,105,108,108,32,98,101,32,116,114,117,110,99,97,116,101,100,32,105,102,32,108,111,110,103,101,114,32,116,104,97,110,32,50,48,48,32,99,104,97,114,97,99,116,101,114,115,46>>,{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,82,84,83,32,57,46,49,32,40,79,84,80,45,50,48,46,49,41,32,111,110,108,121,32,99,111,100,101,32,112,111,105,110,116,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,48,45,50,53,53,32,119,97,115,32,97,99,99,101,112,116,101,100,32,105,110,32,116,104,101,32,115,116,114,105,110,103,46,32,78,111,119,32,97,110,121,32,117,110,105,99,111,100,101,32,115,116,114,105,110,103,32,105,115,32,118,97,108,105,100,46>>]}]}]},{dt,[],[{code,[],[<<97,98,111,114,116>>]}]},{dd,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,97,98,111,114,116,115,32,112,114,111,100,117,99,105,110,103,32,97,32,99,111,114,101,32,100,117,109,112,44,32,105,102,32,116,104,97,116,32,105,115,32,101,110,97,98,108,101,100,32,105,110,32,116,104,101,32,79,83,46>>]}]},{p,[],[<<70,111,114,32,105,110,116,101,103,101,114,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<44,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,99,108,111,115,101,115,32,97,108,108,32,112,111,114,116,115,32,97,110,100,32,97,108,108,111,119,115,32,97,115,121,110,99,32,116,104,114,101,97,100,115,32,116,111,32,102,105,110,105,115,104,32,116,104,101,105,114,32,111,112,101,114,97,116,105,111,110,115,32,98,101,102,111,114,101,32,101,120,105,116,105,110,103,46,32,84,111,32,101,120,105,116,32,119,105,116,104,111,117,116,32,115,117,99,104,32,102,108,117,115,104,105,110,103,44,32,117,115,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<32,97,115,32>>,{code,[],[<<123,102,108,117,115,104,44,102,97,108,115,101,125>>]},<<46>>]},{p,[],[<<70,111,114,32,115,116,97,116,117,115,101,115,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<32,97,110,100,32>>,{code,[],[<<97,98,111,114,116>>]},<<44,32,111,112,116,105,111,110,32>>,{code,[],[<<102,108,117,115,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,32,97,110,100,32,102,108,117,115,104,105,110,103,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,100,111,110,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,53,49>>,signature => [{attribute,1153,spec,{{halt,2},[{type,1153,bounded_fun,[{type,1153,'fun',[{type,1153,product,[{var,1153,'Status'},{var,1153,'Options'}]},{type,1153,no_return,[]}]},[{type,1154,constraint,[{atom,1154,is_subtype},[{var,1154,'Status'},{type,1154,union,[{type,1154,non_neg_integer,[]},{atom,1154,abort},{type,1154,string,[]}]}]]},{type,1155,constraint,[{atom,1155,is_subtype},[{var,1155,'Options'},{type,1155,list,[{var,1155,'Option'}]}]]},{type,1156,constraint,[{atom,1156,is_subtype},[{var,1156,'Option'},{type,1156,tuple,[{atom,1156,flush},{type,1156,boolean,[]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66,48,49>>}},{{function,hd,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2133}],[<<104,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,104,101,97,100,32,111,102,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,104,100,40,91,49,44,50,44,51,44,52,44,53,93,41,46,10,49>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,105,115,116>>]},<<32,105,115,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,57,51>>,signature => [{attribute,2133,spec,{{hd,1},[{type,2133,bounded_fun,[{type,2133,'fun',[{type,2133,product,[{var,2133,'List'}]},{type,2133,term,[]}]},[{type,2134,constraint,[{atom,2134,is_subtype},[{var,2134,'List'},{type,2134,nonempty_list,[{type,2134,term,[]}]}]]}]]}]}}]}},{{function,hibernate,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1167}],[<<104,105,98,101,114,110,97,116,101,47,51>>],#{<<101,110>> => [{p,[],[<<80,117,116,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,110,116,111,32,97,32,119,97,105,116,32,115,116,97,116,101,32,119,104,101,114,101,32,105,116,115,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,114,101,100,117,99,101,100,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,46,32,84,104,105,115,32,105,115,32,117,115,101,102,117,108,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,100,111,101,115,32,110,111,116,32,101,120,112,101,99,116,32,116,111,32,114,101,99,101,105,118,101,32,97,110,121,32,109,101,115,115,97,103,101,115,32,115,111,111,110,46>>]},{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,119,97,107,101,110,32,119,104,101,110,32,97,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,105,116,44,32,97,110,100,32,99,111,110,116,114,111,108,32,114,101,115,117,109,101,115,32,105,110,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,119,105,116,104,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<65,114,103,115>>]},<<32,119,105,116,104,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,32,101,109,112,116,105,101,100,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,116,104,101,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,32,119,104,101,110,32,116,104,97,116,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46,32,84,104,117,115,32>>,{code,[],[<<101,114,108,97,110,103,58,104,105,98,101,114,110,97,116,101,47,51>>]},<<32,110,101,118,101,114,32,114,101,116,117,114,110,115,32,116,111,32,105,116,115,32,99,97,108,108,101,114,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,97,110,121,32,109,101,115,115,97,103,101,32,105,110,32,105,116,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,44,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,119,97,107,101,110,101,100,32,105,109,109,101,100,105,97,116,101,108,121,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46>>]},{p,[],[<<73,110,32,109,111,114,101,32,116,101,99,104,110,105,99,97,108,32,116,101,114,109,115,44,32>>,{code,[],[<<101,114,108,97,110,103,58,104,105,98,101,114,110,97,116,101,47,51>>]},<<32,100,105,115,99,97,114,100,115,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,97,110,100,32,116,104,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,115,32,116,104,101,32,112,114,111,99,101,115,115,46,32,65,102,116,101,114,32,116,104,105,115,44,32,97,108,108,32,108,105,118,101,32,100,97,116,97,32,105,115,32,105,110,32,111,110,101,32,99,111,110,116,105,110,117,111,117,115,32,104,101,97,112,46,32,84,104,101,32,104,101,97,112,32,105,115,32,116,104,101,110,32,115,104,114,117,110,107,101,110,32,116,111,32,116,104,101,32,101,120,97,99,116,32,115,97,109,101,32,115,105,122,101,32,97,115,32,116,104,101,32,108,105,118,101,32,100,97,116,97,32,116,104,97,116,32,105,116,32,104,111,108,100,115,32,40,101,118,101,110,32,105,102,32,116,104,97,116,32,115,105,122,101,32,105,115,32,108,101,115,115,32,116,104,97,110,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,41,46>>]},{p,[],[<<73,102,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,108,105,118,101,32,100,97,116,97,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,108,101,115,115,32,116,104,97,110,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,44,32,116,104,101,32,102,105,114,115,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,99,99,117,114,114,105,110,103,32,97,102,116,101,114,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,119,97,107,101,110,101,100,32,101,110,115,117,114,101,115,32,116,104,97,116,32,116,104,101,32,104,101,97,112,32,115,105,122,101,32,105,115,32,99,104,97,110,103,101,100,32,116,111,32,97,32,115,105,122,101,32,110,111,116,32,115,109,97,108,108,101,114,32,116,104,97,110,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,101,109,112,116,121,105,110,103,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,32,109,101,97,110,115,32,116,104,97,116,32,97,110,121,32,115,117,114,114,111,117,110,100,105,110,103,32>>,{code,[],[<<99,97,116,99,104>>]},<<32,105,115,32,114,101,109,111,118,101,100,32,97,110,100,32,109,117,115,116,32,98,101,32,114,101,45,105,110,115,101,114,116,101,100,32,97,102,116,101,114,32,104,105,98,101,114,110,97,116,105,111,110,46,32,79,110,101,32,101,102,102,101,99,116,32,111,102,32,116,104,105,115,32,105,115,32,116,104,97,116,32,112,114,111,99,101,115,115,101,115,32,115,116,97,114,116,101,100,32,117,115,105,110,103,32>>,{code,[],[<<112,114,111,99,95,108,105,98>>]},<<32,40,97,108,115,111,32,105,110,100,105,114,101,99,116,108,121,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<103,101,110,95,115,101,114,118,101,114>>]},<<32,112,114,111,99,101,115,115,101,115,41,44,32,97,114,101,32,116,111,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,112,114,111,99,95,108,105,98,35,104,105,98,101,114,110,97,116,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,95,108,105,98,58,104,105,98,101,114,110,97,116,101,47,51>>]}]},<<32,105,110,115,116,101,97,100,44,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,104,97,110,100,108,101,114,32,99,111,110,116,105,110,117,101,115,32,116,111,32,119,111,114,107,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,119,97,107,101,115,32,117,112,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,48,56>>,signature => [{attribute,1167,spec,{{erlang,hibernate,3},[{type,1167,bounded_fun,[{type,1167,'fun',[{type,1167,product,[{var,1167,'Module'},{var,1167,'Function'},{var,1167,'Args'}]},{type,1167,no_return,[]}]},[{type,1168,constraint,[{atom,1168,is_subtype},[{var,1168,'Module'},{type,1168,module,[]}]]},{type,1169,constraint,[{atom,1169,is_subtype},[{var,1169,'Function'},{type,1169,atom,[]}]]},{type,1170,constraint,[{atom,1170,is_subtype},[{var,1170,'Args'},{type,1170,list,[{type,1170,term,[]}]}]]}]]}]}}]}},{{function,insert_element,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1175}],[<<105,110,115,101,114,116,95,101,108,101,109,101,110,116,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,101,119,32,116,117,112,108,101,32,119,105,116,104,32,101,108,101,109,101,110,116,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,110,115,101,114,116,101,100,32,97,116,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,105,110,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<46,32,65,108,108,32,101,108,101,109,101,110,116,115,32,102,114,111,109,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,97,110,100,32,117,112,119,97,114,100,115,32,97,114,101,32,112,117,115,104,101,100,32,111,110,101,32,115,116,101,112,32,104,105,103,104,101,114,32,105,110,32,116,104,101,32,110,101,119,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,50>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,105,110,115,101,114,116,95,101,108,101,109,101,110,116,40,50,44,32,123,111,110,101,44,32,116,119,111,44,32,116,104,114,101,101,125,44,32,110,101,119,41,46,10,123,111,110,101,44,110,101,119,44,116,119,111,44,116,104,114,101,101,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,52,57>>,signature => [{attribute,1175,spec,{{erlang,insert_element,3},[{type,1175,bounded_fun,[{type,1175,'fun',[{type,1175,product,[{var,1175,'Index'},{var,1175,'Tuple1'},{var,1175,'Term'}]},{var,1175,'Tuple2'}]},[{type,1176,constraint,[{atom,1176,is_subtype},[{var,1176,'Index'},{type,1176,pos_integer,[]}]]},{type,1177,constraint,[{atom,1177,is_subtype},[{var,1177,'Tuple1'},{type,1177,tuple,any}]]},{type,1178,constraint,[{atom,1178,is_subtype},[{var,1178,'Tuple2'},{type,1178,tuple,any}]]},{type,1179,constraint,[{atom,1179,is_subtype},[{var,1179,'Term'},{type,1179,term,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,integer_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1184}],[<<105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,40,55,55,41,46,10,60,60,34,55,55,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,54,55>>,signature => [{attribute,1184,spec,{{integer_to_binary,1},[{type,1184,bounded_fun,[{type,1184,'fun',[{type,1184,product,[{var,1184,'Integer'}]},{type,1184,binary,[]}]},[{type,1185,constraint,[{atom,1185,is_subtype},[{var,1185,'Integer'},{type,1185,integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,integer_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3805}],[<<105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,40,49,48,50,51,44,32,49,54,41,46,10,60,60,34,51,70,70,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,55,57>>,signature => [{attribute,3805,spec,{{integer_to_binary,2},[{type,3805,bounded_fun,[{type,3805,'fun',[{type,3805,product,[{var,3805,'Integer'},{var,3805,'Base'}]},{type,3805,binary,[]}]},[{type,3806,constraint,[{atom,3806,is_subtype},[{var,3806,'Integer'},{type,3806,integer,[]}]]},{type,3807,constraint,[{atom,3807,is_subtype},[{var,3807,'Base'},{type,3807,range,[{integer,3807,2},{integer,3807,36}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,integer_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1190}],[<<105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,40,55,55,41,46,10,34,55,55,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,57,50>>,signature => [{attribute,1190,spec,{{integer_to_list,1},[{type,1190,bounded_fun,[{type,1190,'fun',[{type,1190,product,[{var,1190,'Integer'}]},{type,1190,string,[]}]},[{type,1191,constraint,[{atom,1191,is_subtype},[{var,1191,'Integer'},{type,1191,integer,[]}]]}]]}]}}]}},{{function,integer_to_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3799}],[<<105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,40,49,48,50,51,44,32,49,54,41,46,10,34,51,70,70,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,48,52>>,signature => [{attribute,3799,spec,{{integer_to_list,2},[{type,3799,bounded_fun,[{type,3799,'fun',[{type,3799,product,[{var,3799,'Integer'},{var,3799,'Base'}]},{type,3799,string,[]}]},[{type,3800,constraint,[{atom,3800,is_subtype},[{var,3800,'Integer'},{type,3800,integer,[]}]]},{type,3801,constraint,[{atom,3801,is_subtype},[{var,3801,'Base'},{type,3801,range,[{integer,3801,2},{integer,3801,36}]}]]}]]}]}}]}},{{function,iolist_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1196}],[<<105,111,108,105,115,116,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,44,32,116,104,97,116,32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,121,116,101,115,44,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,116,104,97,116,32,119,111,117,108,100,32,98,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,73,116,101,109,41>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,111,108,105,115,116,95,115,105,122,101,40,91,49,44,50,124,60,60,51,44,52,62,62,93,41,46,10,52>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,49,55>>,signature => [{attribute,1196,spec,{{iolist_size,1},[{type,1196,bounded_fun,[{type,1196,'fun',[{type,1196,product,[{var,1196,'Item'}]},{type,1196,non_neg_integer,[]}]},[{type,1197,constraint,[{atom,1197,is_subtype},[{var,1197,'Item'},{type,1197,union,[{type,1197,iolist,[]},{type,1197,binary,[]}]}]]}]]}]}}]}},{{function,iolist_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1202}],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,32,105,110,32>>,{code,[],[<<73,111,76,105,115,116,79,114,66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,62,62,46,10,60,60,54,62,62,10,62,32,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,51,48>>,signature => [{attribute,1202,spec,{{iolist_to_binary,1},[{type,1202,bounded_fun,[{type,1202,'fun',[{type,1202,product,[{var,1202,'IoListOrBinary'}]},{type,1202,binary,[]}]},[{type,1203,constraint,[{atom,1203,is_subtype},[{var,1203,'IoListOrBinary'},{type,1203,union,[{type,1203,iolist,[]},{type,1203,binary,[]}]}]]}]]}]}}]}},{{function,iolist_to_iovec,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1208}],[<<105,111,108,105,115,116,95,116,111,95,105,111,118,101,99,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,111,118,101,99,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,32,105,110,32>>,{code,[],[<<73,111,76,105,115,116,79,114,66,105,110,97,114,121>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,52,56>>,signature => [{attribute,1208,spec,{{erlang,iolist_to_iovec,1},[{type,1208,bounded_fun,[{type,1208,'fun',[{type,1208,product,[{var,1208,'IoListOrBinary'}]},{user_type,1208,iovec,[]}]},[{type,1209,constraint,[{atom,1209,is_subtype},[{var,1209,'IoListOrBinary'},{type,1209,union,[{type,1209,iolist,[]},{type,1209,binary,[]}]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,49>>}},{{function,is_alive,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1214}],[<<105,115,95,97,108,105,118,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,97,108,105,118,101,32,40,116,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,110,111,100,101,32,99,97,110,32,98,101,32,112,97,114,116,32,111,102,32,97,32,100,105,115,116,114,105,98,117,116,101,100,32,115,121,115,116,101,109,41,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,65,32,110,111,100,101,32,105,115,32,97,108,105,118,101,32,105,102,32,105,116,32,105,115,32,115,116,97,114,116,101,100,32,119,105,116,104,58>>]},{ol,[],[{li,[],[{a,[{href,<<101,114,116,115,58,101,114,108,35,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<34,101,114,108,32,45,110,97,109,101,32,76,79,78,71,78,65,77,69,34>>]}]},<<32,111,114,44>>]},{li,[],[{a,[{href,<<101,114,116,115,58,101,114,108,35,115,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<34,101,114,108,32,45,115,110,97,109,101,32,83,72,79,82,84,78,65,77,69,34>>]}]},<<46>>]}]},{p,[],[<<65,32,110,111,100,101,32,99,97,110,32,97,108,115,111,32,98,101,32,97,108,105,118,101,32,105,102,32,105,116,32,104,97,115,32,103,111,116,32,97,32,110,97,109,101,32,102,114,111,109,32,97,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,110,101,116,95,107,101,114,110,101,108,35,115,116,97,114,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,101,116,95,107,101,114,110,101,108,58,115,116,97,114,116,47,49>>]}]},<<32,97,110,100,32,104,97,115,32,110,111,116,32,98,101,101,110,32,115,116,111,112,112,101,100,32,98,121,32,97,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,110,101,116,95,107,101,114,110,101,108,35,115,116,111,112,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,101,116,95,107,101,114,110,101,108,58,115,116,111,112,47,48>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,53,55>>,signature => [{attribute,1214,spec,{{is_alive,0},[{type,1214,'fun',[{type,1214,product,[]},{type,1214,boolean,[]}]}]}}]}},{{function,is_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2141}],[<<105,115,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32,97,116,111,109,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,55,54>>,signature => [{attribute,2141,spec,{{is_atom,1},[{type,2141,bounded_fun,[{type,2141,'fun',[{type,2141,product,[{var,2141,'Term'}]},{type,2141,boolean,[]}]},[{type,2142,constraint,[{atom,2142,is_subtype},[{var,2142,'Term'},{type,2142,term,[]}]]}]]}]}}]}},{{function,is_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2147}],[<<105,115,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,32,98,105,110,97,114,121,32,97,108,119,97,121,115,32,99,111,110,116,97,105,110,115,32,97,32,99,111,109,112,108,101,116,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,56,54>>,signature => [{attribute,2147,spec,{{is_binary,1},[{type,2147,bounded_fun,[{type,2147,'fun',[{type,2147,product,[{var,2147,'Term'}]},{type,2147,boolean,[]}]},[{type,2148,constraint,[{atom,2148,is_subtype},[{var,2148,'Term'},{type,2148,term,[]}]]}]]}]}}]}},{{function,is_bitstring,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2153}],[<<105,115,95,98,105,116,115,116,114,105,110,103,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,98,105,116,115,116,114,105,110,103,32,40,105,110,99,108,117,100,105,110,103,32,97,32,98,105,110,97,114,121,41,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,57,55>>,signature => [{attribute,2153,spec,{{is_bitstring,1},[{type,2153,bounded_fun,[{type,2153,'fun',[{type,2153,product,[{var,2153,'Term'}]},{type,2153,boolean,[]}]},[{type,2154,constraint,[{atom,2154,is_subtype},[{var,2154,'Term'},{type,2154,term,[]}]]}]]}]}}]}},{{function,is_boolean,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2159}],[<<105,115,95,98,111,111,108,101,97,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<116,114,117,101>>]},<<32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,40,116,104,97,116,32,105,115,44,32,97,32,98,111,111,108,101,97,110,41,46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,48,55>>,signature => [{attribute,2159,spec,{{is_boolean,1},[{type,2159,bounded_fun,[{type,2159,'fun',[{type,2159,product,[{var,2159,'Term'}]},{type,2159,boolean,[]}]},[{type,2160,constraint,[{atom,2160,is_subtype},[{var,2160,'Term'},{type,2160,term,[]}]]}]]}]}}]}},{{function,is_builtin,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1219}],[<<105,115,95,98,117,105,108,116,105,110,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,117,115,101,102,117,108,32,102,111,114,32,98,117,105,108,100,101,114,115,32,111,102,32,99,114,111,115,115,45,114,101,102,101,114,101,110,99,101,32,116,111,111,108,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<32,105,115,32,97,32,66,73,70,32,105,109,112,108,101,109,101,110,116,101,100,32,105,110,32,67,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,49,56>>,signature => [{attribute,1219,spec,{{erlang,is_builtin,3},[{type,1219,bounded_fun,[{type,1219,'fun',[{type,1219,product,[{var,1219,'Module'},{var,1219,'Function'},{var,1219,'Arity'}]},{type,1219,boolean,[]}]},[{type,1220,constraint,[{atom,1220,is_subtype},[{var,1220,'Module'},{type,1220,module,[]}]]},{type,1221,constraint,[{atom,1221,is_subtype},[{var,1221,'Function'},{type,1221,atom,[]}]]},{type,1222,constraint,[{atom,1222,is_subtype},[{var,1222,'Arity'},{type,1222,arity,[]}]]}]]}]}}]}},{{function,is_float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2165}],[<<105,115,95,102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,102,108,111,97,116,105,110,103,32,112,111,105,110,116,32,110,117,109,98,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,50,57>>,signature => [{attribute,2165,spec,{{is_float,1},[{type,2165,bounded_fun,[{type,2165,'fun',[{type,2165,product,[{var,2165,'Term'}]},{type,2165,boolean,[]}]},[{type,2166,constraint,[{atom,2166,is_subtype},[{var,2166,'Term'},{type,2166,term,[]}]]}]]}]}}]}},{{function,is_function,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2171}],[<<105,115,95,102,117,110,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,102,117,110,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,51,57>>,signature => [{attribute,2171,spec,{{is_function,1},[{type,2171,bounded_fun,[{type,2171,'fun',[{type,2171,product,[{var,2171,'Term'}]},{type,2171,boolean,[]}]},[{type,2172,constraint,[{atom,2172,is_subtype},[{var,2172,'Term'},{type,2172,term,[]}]]}]]}]}}]}},{{function,is_function,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2177}],[<<105,115,95,102,117,110,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,102,117,110,32,116,104,97,116,32,99,97,110,32,98,101,32,97,112,112,108,105,101,100,32,119,105,116,104,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,110,117,109,98,101,114,32,111,102,32,97,114,103,117,109,101,110,116,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,52,57>>,signature => [{attribute,2177,spec,{{is_function,2},[{type,2177,bounded_fun,[{type,2177,'fun',[{type,2177,product,[{var,2177,'Term'},{var,2177,'Arity'}]},{type,2177,boolean,[]}]},[{type,2178,constraint,[{atom,2178,is_subtype},[{var,2178,'Term'},{type,2178,term,[]}]]},{type,2179,constraint,[{atom,2179,is_subtype},[{var,2179,'Arity'},{type,2179,arity,[]}]]}]]}]}}]}},{{function,is_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2184}],[<<105,115,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,54,49>>,signature => [{attribute,2184,spec,{{is_integer,1},[{type,2184,bounded_fun,[{type,2184,'fun',[{type,2184,product,[{var,2184,'Term'}]},{type,2184,boolean,[]}]},[{type,2185,constraint,[{atom,2185,is_subtype},[{var,2185,'Term'},{type,2185,term,[]}]]}]]}]}}]}},{{function,is_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2190}],[<<105,115,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,108,105,115,116,32,119,105,116,104,32,122,101,114,111,32,111,114,32,109,111,114,101,32,101,108,101,109,101,110,116,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,55,49>>,signature => [{attribute,2190,spec,{{is_list,1},[{type,2190,bounded_fun,[{type,2190,'fun',[{type,2190,product,[{var,2190,'Term'}]},{type,2190,boolean,[]}]},[{type,2191,constraint,[{atom,2191,is_subtype},[{var,2191,'Term'},{type,2191,term,[]}]]}]]}]}}]}},{{function,is_map,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2208}],[<<105,115,95,109,97,112,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,109,97,112,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,56,49>>,signature => [{attribute,2208,spec,{{is_map,1},[{type,2208,bounded_fun,[{type,2208,'fun',[{type,2208,product,[{var,2208,'Term'}]},{type,2208,boolean,[]}]},[{type,2209,constraint,[{atom,2209,is_subtype},[{var,2209,'Term'},{type,2209,term,[]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,is_map_key,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1227}],[<<105,115,95,109,97,112,95,107,101,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,109,97,112,32>>,{code,[],[<<77,97,112>>]},<<32,99,111,110,116,97,105,110,115,32>>,{code,[],[<<75,101,121>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,99,111,110,116,97,105,110,32,116,104,101,32>>,{code,[],[<<75,101,121>>]},<<46>>]},{p,[],[<<84,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<123,98,97,100,109,97,112,44,77,97,112,125>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32>>,{code,[],[<<77,97,112>>]},<<32,105,115,32,110,111,116,32,97,32,109,97,112,46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<62,32,77,97,112,32,61,32,35,123,34,52,50,34,32,61,62,32,118,97,108,117,101,125,46,10,35,123,34,52,50,34,32,61,62,32,118,97,108,117,101,125,10,62,32,105,115,95,109,97,112,95,107,101,121,40,34,52,50,34,44,77,97,112,41,46,10,116,114,117,101,10,62,32,105,115,95,109,97,112,95,107,101,121,40,118,97,108,117,101,44,77,97,112,41,46,10,102,97,108,115,101>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,57,49>>,signature => [{attribute,1227,spec,{{is_map_key,2},[{type,1227,bounded_fun,[{type,1227,'fun',[{type,1227,product,[{var,1227,'Key'},{var,1227,'Map'}]},{type,1227,boolean,[]}]},[{type,1228,constraint,[{atom,1228,is_subtype},[{var,1228,'Key'},{type,1228,term,[]}]]},{type,1229,constraint,[{atom,1229,is_subtype},[{var,1229,'Map'},{type,1229,map,any}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,is_number,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2196}],[<<105,115,95,110,117,109,98,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,111,114,32,97,32,102,108,111,97,116,105,110,103,32,112,111,105,110,116,32,110,117,109,98,101,114,46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,49,50>>,signature => [{attribute,2196,spec,{{is_number,1},[{type,2196,bounded_fun,[{type,2196,'fun',[{type,2196,product,[{var,2196,'Term'}]},{type,2196,boolean,[]}]},[{type,2197,constraint,[{atom,2197,is_subtype},[{var,2197,'Term'},{type,2197,term,[]}]]}]]}]}}]}},{{function,is_pid,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2202}],[<<105,115,95,112,105,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,50,50>>,signature => [{attribute,2202,spec,{{is_pid,1},[{type,2202,bounded_fun,[{type,2202,'fun',[{type,2202,product,[{var,2202,'Term'}]},{type,2202,boolean,[]}]},[{type,2203,constraint,[{atom,2203,is_subtype},[{var,2203,'Term'},{type,2203,term,[]}]]}]]}]}}]}},{{function,is_port,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2214}],[<<105,115,95,112,111,114,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,51,50>>,signature => [{attribute,2214,spec,{{is_port,1},[{type,2214,bounded_fun,[{type,2214,'fun',[{type,2214,product,[{var,2214,'Term'}]},{type,2214,boolean,[]}]},[{type,2215,constraint,[{atom,2215,is_subtype},[{var,2215,'Term'},{type,2215,term,[]}]]}]]}]}}]}},{{function,is_process_alive,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1234}],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,47,49>>],#{<<101,110>> => [{p,[],[{code,[],[<<80,105,100>>]},<<32,109,117,115,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,115,116,115,32,97,110,100,32,105,115,32,97,108,105,118,101,44,32,116,104,97,116,32,105,115,44,32,105,115,32,110,111,116,32,101,120,105,116,105,110,103,32,97,110,100,32,104,97,115,32,110,111,116,32,101,120,105,116,101,100,46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<73,102,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,49>>]},<<32,99,97,108,108,115,32>>,{code,[],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,40,80,50,80,105,100,41>>]},<<32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,97,108,108,32,115,105,103,110,97,108,115,44,32,115,101,110,116,32,102,114,111,109,32>>,{code,[],[<<80,49>>]},<<32,116,111,32>>,{code,[],[<<80,50>>]},<<32,40>>,{code,[],[<<80,50>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,105,100,101,110,116,105,102,105,101,114,32>>,{code,[],[<<80,50,80,105,100>>]},<<41,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,44,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32>>,{code,[],[<<80,50>>]},<<32,98,101,102,111,114,101,32,116,104,101,32,97,108,105,118,101,110,101,115,115,32,111,102,32>>,{code,[],[<<80,50>>]},<<32,105,115,32,99,104,101,99,107,101,100,46,32,84,104,105,115,32,103,117,97,114,97,110,116,101,101,32,109,101,97,110,115,32,116,104,97,116,32,111,110,101,32,99,97,110,32,117,115,101,32>>,{code,[],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,47,49>>]},<<32,116,111,32,108,101,116,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,49>>]},<<32,119,97,105,116,32,117,110,116,105,108,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,50>>]},<<44,32,119,104,105,99,104,32,104,97,115,32,103,111,116,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,102,114,111,109,32,80,49,44,32,105,115,32,107,105,108,108,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<101,120,105,116,40,80,50,80,105,100,44,32,107,105,108,108,41,44,10,37,32,80,50,32,109,105,103,104,116,32,110,111,116,32,98,101,32,107,105,108,108,101,100,10,105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,40,80,50,80,105,100,41,44,10,37,32,80,50,32,105,115,32,110,111,116,32,97,108,105,118,101,32,40,116,104,101,32,99,97,108,108,32,97,98,111,118,101,32,97,108,119,97,121,115,32,114,101,116,117,114,110,32,102,97,108,115,101,41>>]}]},{p,[],[<<83,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,99,111,109,109,117,110,105,99,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,111,109,109,117,110,105,99,97,116,105,111,110,32,105,110,32,69,114,108,97,110,103>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]},<<32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,105,103,110,97,108,115,32,97,110,100,32,101,120,105,116,32,115,105,110,103,110,97,108,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,52,50>>,signature => [{attribute,1234,spec,{{is_process_alive,1},[{type,1234,bounded_fun,[{type,1234,'fun',[{type,1234,product,[{var,1234,'Pid'}]},{type,1234,boolean,[]}]},[{type,1235,constraint,[{atom,1235,is_subtype},[{var,1235,'Pid'},{type,1235,pid,[]}]]}]]}]}}]}},{{function,is_record,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2220}],[<<105,115,95,114,101,99,111,114,100,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,32,97,110,100,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,114,109,97,108,108,121,32,116,104,101,32,99,111,109,112,105,108,101,114,32,116,114,101,97,116,115,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<105,115,95,114,101,99,111,114,100,47,50>>]},<<32,101,115,112,101,99,105,97,108,108,121,46,32,73,116,32,101,109,105,116,115,32,99,111,100,101,32,116,111,32,118,101,114,105,102,121,32,116,104,97,116,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,44,32,116,104,97,116,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<44,32,97,110,100,32,116,104,97,116,32,116,104,101,32,115,105,122,101,32,105,115,32,99,111,114,114,101,99,116,46,32,72,111,119,101,118,101,114,44,32,105,102,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,105,115,32,110,111,116,32,97,32,108,105,116,101,114,97,108,32,97,116,111,109,44,32,116,104,101,32,66,73,70,32>>,{code,[],[<<105,115,95,114,101,99,111,114,100,47,50>>]},<<32,105,115,32,99,97,108,108,101,100,32,105,110,115,116,101,97,100,32,97,110,100,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,116,117,112,108,101,32,105,115,32,110,111,116,32,118,101,114,105,102,105,101,100,46>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,44,32,105,102,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,105,115,32,97,32,108,105,116,101,114,97,108,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,55,52>>,signature => [{attribute,2220,spec,{{is_record,2},[{type,2220,bounded_fun,[{type,2220,'fun',[{type,2220,product,[{var,2220,'Term'},{var,2220,'RecordTag'}]},{type,2220,boolean,[]}]},[{type,2221,constraint,[{atom,2221,is_subtype},[{var,2221,'Term'},{type,2221,term,[]}]]},{type,2222,constraint,[{atom,2222,is_subtype},[{var,2222,'RecordTag'},{type,2222,atom,[]}]]}]]}]}}]}},{{function,is_record,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2227}],[<<105,115,95,114,101,99,111,114,100,47,51>>],#{<<101,110>> => [{p,[],[{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,109,117,115,116,32,98,101,32,97,110,32,97,116,111,109,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,44,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<44,32,97,110,100,32,105,116,115,32,115,105,122,101,32,105,115,32>>,{code,[],[<<83,105,122,101>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,32,105,102,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,105,115,32,97,32,108,105,116,101,114,97,108,32,97,116,111,109,32,97,110,100,32>>,{code,[],[<<83,105,122,101>>]},<<32,105,115,32,97,32,108,105,116,101,114,97,108,32,105,110,116,101,103,101,114,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,100,111,99,117,109,101,110,116,101,100,32,102,111,114,32,99,111,109,112,108,101,116,101,110,101,115,115,46,32,85,115,117,97,108,108,121,32>>,{code,[],[<<105,115,95,114,101,99,111,114,100,47,50>>]},<<32,105,115,32,116,111,32,98,101,32,117,115,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,57,53>>,signature => [{attribute,2227,spec,{{is_record,3},[{type,2227,bounded_fun,[{type,2227,'fun',[{type,2227,product,[{var,2227,'Term'},{var,2227,'RecordTag'},{var,2227,'Size'}]},{type,2227,boolean,[]}]},[{type,2228,constraint,[{atom,2228,is_subtype},[{var,2228,'Term'},{type,2228,term,[]}]]},{type,2229,constraint,[{atom,2229,is_subtype},[{var,2229,'RecordTag'},{type,2229,atom,[]}]]},{type,2230,constraint,[{atom,2230,is_subtype},[{var,2230,'Size'},{type,2230,non_neg_integer,[]}]]}]]}]}}]}},{{function,is_reference,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2235}],[<<105,115,95,114,101,102,101,114,101,110,99,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,49,52>>,signature => [{attribute,2235,spec,{{is_reference,1},[{type,2235,bounded_fun,[{type,2235,'fun',[{type,2235,product,[{var,2235,'Term'}]},{type,2235,boolean,[]}]},[{type,2236,constraint,[{atom,2236,is_subtype},[{var,2236,'Term'},{type,2236,term,[]}]]}]]}]}}]}},{{function,is_tuple,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2241}],[<<105,115,95,116,117,112,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,50,52>>,signature => [{attribute,2241,spec,{{is_tuple,1},[{type,2241,bounded_fun,[{type,2241,'fun',[{type,2241,product,[{var,2241,'Term'}]},{type,2241,boolean,[]}]},[{type,2242,constraint,[{atom,2242,is_subtype},[{var,2242,'Term'},{type,2242,term,[]}]]}]]}]}}]}},{{function,length,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1241}],[<<108,101,110,103,116,104,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,101,110,103,116,104,40,91,49,44,50,44,51,44,52,44,53,44,54,44,55,44,56,44,57,93,41,46,10,57>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,51,52>>,signature => [{attribute,1241,spec,{{length,1},[{type,1241,bounded_fun,[{type,1241,'fun',[{type,1241,product,[{var,1241,'List'}]},{type,1241,non_neg_integer,[]}]},[{type,1242,constraint,[{atom,1242,is_subtype},[{var,1242,'List'},{type,1242,list,[{type,1242,term,[]}]}]]}]]}]}}]}},{{function,link,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1247}],[<<108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,40,111,114,32,112,111,114,116,41,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<46,32,73,102,32,116,104,101,32,108,105,110,107,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,32,111,114,32,97,32,112,114,111,99,101,115,115,32,97,116,116,101,109,112,116,115,32,116,111,32,99,114,101,97,116,101,32,97,32,108,105,110,107,32,116,111,32,105,116,115,101,108,102,44,32,110,111,116,104,105,110,103,32,105,115,32,100,111,110,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,108,105,110,107,32,105,115,32,115,101,116,32,117,112,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,97,110,100,32,99,104,101,99,107,105,110,103,32,105,116,32,105,115,32,99,104,101,97,112,44,32,97,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<32,101,114,114,111,114,32,105,115,32,114,97,105,115,101,100,46,32,67,117,114,114,101,110,116,108,121,44,32,99,104,101,99,107,105,110,103,32,105,115,32,99,104,101,97,112,32,105,102,32,116,104,101,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,108,111,99,97,108,32,97,110,100,32,116,104,101,32,99,97,108,108,101,114,32,100,111,101,115,32,110,111,116,32,116,114,97,112,32,101,120,105,116,115,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50,32>>]}]},<<41,46>>]},{p,[],[<<65,112,97,114,116,32,102,114,111,109,32,97,110,121,32,101,120,105,116,32,115,105,103,110,97,108,115,32,102,114,111,109,32,116,104,101,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,32,105,116,115,101,108,102,44,32,116,119,111,32,115,112,101,99,105,97,108,32,101,120,105,116,32,115,105,103,110,97,108,115,32,109,97,121,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<110,111,112,114,111,99>>]},<<32,105,115,32,115,101,110,116,32,105,109,109,101,100,105,97,116,101,108,121,32,105,102,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,108,105,110,107,105,110,103,32,40,105,102,32,116,104,101,32,99,97,108,108,101,114,32,105,115,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,32,111,114,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,114,101,109,111,116,101,41,46>>]}]},{li,[],[{p,[],[{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,105,102,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,114,101,109,111,116,101,32,97,110,100,32,97,32,99,111,110,110,101,99,116,105,111,110,32,98,101,116,119,101,101,110,32,116,104,101,32,110,111,100,101,115,32,99,111,117,108,100,32,110,111,116,32,98,101,32,101,115,116,97,98,108,105,115,104,101,100,32,111,114,32,119,97,115,32,115,101,118,101,114,101,100,46>>]}]}]},{p,[],[<<83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,108,105,110,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<80,114,111,99,101,115,115,101,115,32,226,158,156,32,76,105,110,107,115>>]},<<32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,52,54>>,signature => [{attribute,1247,spec,{{link,1},[{type,1247,bounded_fun,[{type,1247,'fun',[{type,1247,product,[{var,1247,'PidOrPort'}]},{atom,1247,true}]},[{type,1248,constraint,[{atom,1248,is_subtype},[{var,1248,'PidOrPort'},{type,1248,union,[{type,1248,pid,[]},{type,1248,port,[]}]}]]}]]}]}}]}},{{function,list_to_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1253}],[<<108,105,115,116,95,116,111,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,50,48,44,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,109,97,121,32,99,111,110,116,97,105,110,32,97,110,121,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,46,32,69,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,97,108,108,111,119,101,100,32,111,110,108,121,32,73,83,79,45,108,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,100,105,100,32,110,111,116,32,97,108,108,111,119,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,97,98,111,118,101,32,50,53,53,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,85,110,105,99,111,100,101,32,115,117,112,112,111,114,116,32,105,110,32,97,116,111,109,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,101,120,116,95,100,105,115,116,35,117,116,102,56,95,97,116,111,109,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,116,101,32,111,110,32,85,84,70,45,56,32,101,110,99,111,100,101,100,32,97,116,111,109,115>>]},<<32,105,110,32,115,101,99,116,105,111,110,32,34,69,120,116,101,114,110,97,108,32,84,101,114,109,32,70,111,114,109,97,116,34,32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,97,110,32,97,116,111,109,32,110,97,109,101,32,105,115,32,108,105,109,105,116,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,99,111,110,102,105,103,117,114,97,98,108,101,32,108,105,109,105,116,32,111,110,32,104,111,119,32,109,97,110,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,101,120,105,115,116,32,97,110,100,32,97,116,111,109,115,32,97,114,101,32,110,111,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,99,111,110,115,105,100,101,114,32,105,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>]}]},<<32,105,115,32,97,32,98,101,116,116,101,114,32,111,112,116,105,111,110,32,116,104,97,110,32>>,{code,[],[<<108,105,115,116,95,116,111,95,97,116,111,109,47,49>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,97,116,111,109,40,34,69,114,108,97,110,103,34,41,46,10,39,69,114,108,97,110,103,39>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,56,52>>,signature => [{attribute,1253,spec,{{list_to_atom,1},[{type,1253,bounded_fun,[{type,1253,'fun',[{type,1253,product,[{var,1253,'String'}]},{type,1253,atom,[]}]},[{type,1254,constraint,[{atom,1254,is_subtype},[{var,1254,'String'},{type,1254,string,[]}]]}]]}]}}]}},{{function,list_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1259}],[<<108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,32,105,110,32>>,{code,[],[<<73,111,76,105,115,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,62,62,46,10,60,60,54,62,62,10,62,32,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,50,48>>,signature => [{attribute,1259,spec,{{list_to_binary,1},[{type,1259,bounded_fun,[{type,1259,'fun',[{type,1259,product,[{var,1259,'IoList'}]},{type,1259,binary,[]}]},[{type,1260,constraint,[{atom,1260,is_subtype},[{var,1260,'IoList'},{type,1260,iolist,[]}]]}]]}]}}]}},{{function,list_to_bitstring,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1265}],[<<108,105,115,116,95,116,111,95,98,105,116,115,116,114,105,110,103,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<98,105,116,115,116,114,105,110,103,95,108,105,115,116>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,116,115,116,114,105,110,103,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,116,115,116,114,105,110,103,115,32,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103,76,105,115,116>>]},<<46,32,40,84,104,101,32,108,97,115,116,32,116,97,105,108,32,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103,76,105,115,116>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,97,32,98,105,116,115,116,114,105,110,103,46,41,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,44,55,58,52,62,62,46,10,60,60,54,44,55,58,52,62,62,10,62,32,108,105,115,116,95,116,111,95,98,105,116,115,116,114,105,110,103,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,44,55,58,52,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,51,56>>,signature => [{attribute,1265,spec,{{list_to_bitstring,1},[{type,1265,bounded_fun,[{type,1265,'fun',[{type,1265,product,[{var,1265,'BitstringList'}]},{type,1265,bitstring,[]}]},[{type,1266,constraint,[{atom,1266,is_subtype},[{var,1266,'BitstringList'},{user_type,1266,bitstring_list,[]}]]}]]}]}}]}},{{function,list_to_existing_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1271}],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,98,117,116,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,32,115,117,99,104,32,97,116,111,109,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,114,101,32,100,111,101,115,32,110,111,116,32,97,108,114,101,97,100,121,32,101,120,105,115,116,32,97,110,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,99,111,109,112,105,108,101,114,32,109,97,121,32,111,112,116,105,109,105,122,101,32,97,119,97,121,32,97,116,111,109,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,111,109,112,105,108,101,114,32,119,105,108,108,32,114,101,119,114,105,116,101,32>>,{code,[],[<<97,116,111,109,95,116,111,95,108,105,115,116,40,115,111,109,101,95,97,116,111,109,41>>]},<<32,116,111,32>>,{code,[],[<<34,115,111,109,101,95,97,116,111,109,34>>]},<<46,32,73,102,32,116,104,97,116,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,104,101,32,111,110,108,121,32,109,101,110,116,105,111,110,32,111,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,111,109,101,95,97,116,111,109>>]},<<32,105,110,32,116,104,101,32,99,111,110,116,97,105,110,105,110,103,32,109,111,100,117,108,101,44,32,116,104,101,32,97,116,111,109,32,119,105,108,108,32,110,111,116,32,98,101,32,99,114,101,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32,108,111,97,100,101,100,44,32,97,110,100,32,97,32,115,117,98,115,101,113,117,101,110,116,32,99,97,108,108,32,116,111,32>>,{code,[],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,40,34,115,111,109,101,95,97,116,111,109,34,41>>]},<<32,119,105,108,108,32,102,97,105,108,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,53,57>>,signature => [{attribute,1271,spec,{{list_to_existing_atom,1},[{type,1271,bounded_fun,[{type,1271,'fun',[{type,1271,product,[{var,1271,'String'}]},{type,1271,atom,[]}]},[{type,1272,constraint,[{atom,1272,is_subtype},[{var,1272,'String'},{type,1272,string,[]}]]}]]}]}}]}},{{function,list_to_float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1277}],[<<108,105,115,116,95,116,111,95,102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,102,108,111,97,116,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,102,108,111,97,116,40,34,50,46,50,48,49,55,55,54,52,101,43,48,34,41,46,10,50,46,50,48,49,55,55,54,52>>]}]},{p,[],[<<84,104,101,32,102,108,111,97,116,32,115,116,114,105,110,103,32,102,111,114,109,97,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,102,111,114,109,97,116,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,102,108,111,97,116,32,108,105,116,101,114,97,108,115>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,97,116,32,117,110,100,101,114,115,99,111,114,101,115,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,102,108,111,97,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,56,48>>,signature => [{attribute,1277,spec,{{list_to_float,1},[{type,1277,bounded_fun,[{type,1277,'fun',[{type,1277,product,[{var,1277,'String'}]},{type,1277,float,[]}]},[{type,1278,constraint,[{atom,1278,is_subtype},[{var,1278,'String'},{type,1278,string,[]}]]}]]}]}}]}},{{function,list_to_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1283}],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,49,50,51,34,41,46,10,49,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,45,49,50,51,34,41,46,10,45,49,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,43,49,50,51,50,51,52,57,56,50,51,48,52,57,56,50,51,48,57,52,56,50,48,57,51,56,51,51,50,51,52,50,51,52,34,41,46,10,49,50,51,50,51,52,57,56,50,51,48,52,57,56,50,51,48,57,52,56,50,48,57,51,56,51,51,50,51,52,50,51,52>>]}]},{p,[],[{code,[],[<<83,116,114,105,110,103>>]},<<32,109,117,115,116,32,99,111,110,116,97,105,110,32,97,116,32,108,101,97,115,116,32,111,110,101,32,100,105,103,105,116,32,99,104,97,114,97,99,116,101,114,32,97,110,100,32,99,97,110,32,104,97,118,101,32,97,110,32,111,112,116,105,111,110,97,108,32,112,114,101,102,105,120,32,99,111,110,115,105,115,116,105,110,103,32,111,102,32,97,32,115,105,110,103,108,101,32,34>>,{code,[],[<<43>>]},<<34,32,111,114,32,34>>,{code,[],[<<45>>]},<<34,32,99,104,97,114,97,99,116,101,114,32,40,116,104,97,116,32,105,115,44,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,109,117,115,116,32,109,97,116,99,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32>>,{code,[],[<<34,94,91,43,45,93,63,91,48,45,57,93,43,36,34>>]},<<41,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,57,56>>,signature => [{attribute,1283,spec,{{list_to_integer,1},[{type,1283,bounded_fun,[{type,1283,'fun',[{type,1283,product,[{var,1283,'String'}]},{type,1283,integer,[]}]},[{type,1284,constraint,[{atom,1284,is_subtype},[{var,1284,'String'},{type,1284,string,[]}]]}]]}]}}]}},{{function,list_to_integer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1289}],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,51,70,70,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,43,51,70,70,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,51,102,102,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,51,102,70,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,45,51,70,70,34,44,32,49,54,41,46,10,45,49,48,50,51>>]}]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32>>,{code,[],[<<66,97,115,101>>]},<<32,105,115,32,49,54,44,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,109,117,115,116,32,109,97,116,99,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32>>,{code,[],[<<34,94,91,43,45,93,63,40,91,48,45,57,93,124,91,65,45,70,93,124,91,97,45,102,93,41,43,36,34>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,50,51>>,signature => [{attribute,1289,spec,{{list_to_integer,2},[{type,1289,bounded_fun,[{type,1289,'fun',[{type,1289,product,[{var,1289,'String'},{var,1289,'Base'}]},{type,1289,integer,[]}]},[{type,1290,constraint,[{atom,1290,is_subtype},[{var,1290,'String'},{type,1290,string,[]}]]},{type,1291,constraint,[{atom,1291,is_subtype},[{var,1291,'Base'},{type,1291,range,[{integer,1291,2},{integer,1291,36}]}]]}]]}]}}]}},{{function,list_to_pid,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1296}],[<<108,105,115,116,95,116,111,95,112,105,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,97,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,112,105,100,40,34,60,48,46,52,46,49,62,34,41,46,10,60,48,46,52,46,49,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,53,51>>,signature => [{attribute,1296,spec,{{list_to_pid,1},[{type,1296,bounded_fun,[{type,1296,'fun',[{type,1296,product,[{var,1296,'String'}]},{type,1296,pid,[]}]},[{type,1297,constraint,[{atom,1297,is_subtype},[{var,1297,'String'},{type,1297,string,[]}]]}]]}]}}]}},{{function,list_to_port,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1302}],[<<108,105,115,116,95,116,111,95,112,111,114,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,97,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,112,111,114,116,40,34,35,80,111,114,116,60,48,46,52,62,34,41,46,10,35,80,111,114,116,60,48,46,52,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,55,49>>,signature => [{attribute,1302,spec,{{list_to_port,1},[{type,1302,bounded_fun,[{type,1302,'fun',[{type,1302,product,[{var,1302,'String'}]},{type,1302,port,[]}]},[{type,1303,constraint,[{atom,1303,is_subtype},[{var,1303,'String'},{type,1303,string,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,list_to_ref,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1308}],[<<108,105,115,116,95,116,111,95,114,101,102,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,114,101,102,101,114,101,110,99,101,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,97,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,114,101,102,40,34,35,82,101,102,60,48,46,52,49,57,50,53,51,55,54,55,56,46,52,48,55,51,49,57,51,52,55,53,46,55,49,49,56,49,62,34,41,46,10,35,82,101,102,60,48,46,52,49,57,50,53,51,55,54,55,56,46,52,48,55,51,49,57,51,52,55,53,46,55,49,49,56,49,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,114,101,102,101,114,101,110,99,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,56,57>>,signature => [{attribute,1308,spec,{{list_to_ref,1},[{type,1308,bounded_fun,[{type,1308,'fun',[{type,1308,product,[{var,1308,'String'}]},{type,1308,reference,[]}]},[{type,1309,constraint,[{atom,1309,is_subtype},[{var,1309,'String'},{type,1309,string,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,list_to_tuple,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1314}],[<<108,105,115,116,95,116,111,95,116,117,112,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,116,117,112,108,101,40,91,115,104,97,114,101,44,32,91,39,69,114,105,99,115,115,111,110,95,66,39,44,32,49,54,51,93,93,41,46,10,123,115,104,97,114,101,44,32,91,39,69,114,105,99,115,115,111,110,95,66,39,44,32,49,54,51,93,125>>]}]},{p,[],[{code,[],[<<76,105,115,116>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,69,114,108,97,110,103,32,116,101,114,109,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,48,55>>,signature => [{attribute,1314,spec,{{list_to_tuple,1},[{type,1314,bounded_fun,[{type,1314,'fun',[{type,1314,product,[{var,1314,'List'}]},{type,1314,tuple,any}]},[{type,1315,constraint,[{atom,1315,is_subtype},[{var,1315,'List'},{type,1315,list,[{type,1315,term,[]}]}]]}]]}]}}]}},{{function,load_module,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2246}],[<<108,111,97,100,95,109,111,100,117,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,111,98,106,101,99,116,32,99,111,100,101,32,102,111,114,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<44,32,116,104,105,115,32,66,73,70,32,108,111,97,100,115,32,116,104,97,116,32,111,98,106,101,99,116,32,99,111,100,101,46,32,73,102,32,116,104,101,32,99,111,100,101,32,102,111,114,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,44,32,97,108,108,32,101,120,112,111,114,116,32,114,101,102,101,114,101,110,99,101,115,32,97,114,101,32,114,101,112,108,97,99,101,100,32,115,111,32,116,104,101,121,32,112,111,105,110,116,32,116,111,32,116,104,101,32,110,101,119,108,121,32,108,111,97,100,101,100,32,99,111,100,101,46,32,84,104,101,32,112,114,101,118,105,111,117,115,108,121,32,108,111,97,100,101,100,32,99,111,100,101,32,105,115,32,107,101,112,116,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,97,115,32,111,108,100,32,99,111,100,101,44,32,97,115,32,116,104,101,114,101,32,99,97,110,32,115,116,105,108,108,32,98,101,32,112,114,111,99,101,115,115,101,115,32,101,120,101,99,117,116,105,110,103,32,116,104,97,116,32,99,111,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,101,105,116,104,101,114,32>>,{code,[],[<<123,109,111,100,117,108,101,44,32,77,111,100,117,108,101,125>>]},<<44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,105,102,32,108,111,97,100,105,110,103,32,102,97,105,108,115,46,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,102,105,108,101>>]}]},{dd,[],[<<84,104,101,32,111,98,106,101,99,116,32,99,111,100,101,32,105,110,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,102,111,114,109,97,116,32>>,{em,[],[<<111,114>>]},<<32,116,104,101,32,111,98,106,101,99,116,32,99,111,100,101,32,99,111,110,116,97,105,110,115,32,99,111,100,101,32,102,111,114,32,97,110,111,116,104,101,114,32,109,111,100,117,108,101,32,116,104,97,110,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,116,95,112,117,114,103,101,100>>]}]},{dd,[],[{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,109,111,100,117,108,101,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,108,111,97,100,101,100,32,98,101,99,97,117,115,101,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,50,48>>,signature => [{attribute,2246,spec,{{load_module,2},[{type,2246,bounded_fun,[{type,2246,'fun',[{type,2246,product,[{var,2246,'Module'},{var,2246,'Binary'}]},{type,2246,union,[{type,2246,tuple,[{atom,2246,module},{var,2246,'Module'}]},{type,2246,tuple,[{atom,2246,error},{var,2246,'Reason'}]}]}]},[{type,2247,constraint,[{atom,2247,is_subtype},[{var,2247,'Module'},{type,2247,module,[]}]]},{type,2248,constraint,[{atom,2248,is_subtype},[{var,2248,'Binary'},{type,2248,binary,[]}]]},{type,2249,constraint,[{atom,2249,is_subtype},[{var,2249,'Reason'},{type,2249,union,[{atom,2249,badfile},{atom,2249,not_purged},{atom,2249,on_load}]}]]}]]}]}}]}},{{function,load_nif,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2267}],[<<108,111,97,100,95,110,105,102,47,50>>],#{<<101,110>> => [{p,[],[<<76,111,97,100,115,32,97,110,100,32,108,105,110,107,115,32,97,32,100,121,110,97,109,105,99,32,108,105,98,114,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,110,97,116,105,118,101,32,105,109,112,108,101,109,101,110,116,101,100,32,102,117,110,99,116,105,111,110,115,32,40,78,73,70,115,41,32,102,111,114,32,97,32,109,111,100,117,108,101,46,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,97,32,102,105,108,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115,104,97,114,101,97,98,108,101,32,111,98,106,101,99,116,47,100,121,110,97,109,105,99,32,108,105,98,114,97,114,121,32,102,105,108,101,32,109,105,110,117,115,32,116,104,101,32,79,83,45,100,101,112,101,110,100,101,110,116,32,102,105,108,101,32,101,120,116,101,110,115,105,111,110,32,40>>,{code,[],[<<46,115,111>>]},<<32,102,111,114,32,85,110,105,120,32,97,110,100,32>>,{code,[],[<<46,100,108,108>>]},<<32,102,111,114,32,87,105,110,100,111,119,115,41,46,32,78,111,116,105,99,101,32,116,104,97,116,32,111,110,32,109,111,115,116,32,79,83,115,32,116,104,101,32,108,105,98,114,97,114,121,32,104,97,115,32,116,111,32,104,97,118,101,32,97,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,32,111,110,32,100,105,115,99,32,119,104,101,110,32,97,110,32,117,112,103,114,97,100,101,32,111,102,32,116,104,101,32,110,105,102,32,105,115,32,100,111,110,101,46,32,73,102,32,116,104,101,32,110,97,109,101,32,105,115,32,116,104,101,32,115,97,109,101,44,32,98,117,116,32,116,104,101,32,99,111,110,116,101,110,116,115,32,100,105,102,102,101,114,44,32,116,104,101,32,111,108,100,32,108,105,98,114,97,114,121,32,109,97,121,32,98,101,32,108,111,97,100,101,100,32,105,110,115,116,101,97,100,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,104,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,32,78,73,70,32,108,105,98,114,97,114,121,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,108,95,110,105,102>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,108,95,110,105,102,40,51,41>>]}]},<<46>>]},{p,[],[{code,[],[<<76,111,97,100,73,110,102,111>>]},<<32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,46,32,73,116,32,105,115,32,112,97,115,115,101,100,32,111,110,32,116,111,32,116,104,101,32,108,105,98,114,97,114,121,32,97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,105,110,105,116,105,97,108,105,122,97,116,105,111,110,46,32,65,32,103,111,111,100,32,112,114,97,99,116,105,99,101,32,105,115,32,116,111,32,105,110,99,108,117,100,101,32,97,32,109,111,100,117,108,101,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,32,116,111,32,115,117,112,112,111,114,116,32,102,117,116,117,114,101,32,99,111,100,101,32,117,112,103,114,97,100,101,32,115,99,101,110,97,114,105,111,115,46>>]},{p,[],[<<84,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<108,111,97,100,95,110,105,102,47,50>>]},<<32,109,117,115,116,32,98,101,32,109,97,100,101,32>>,{em,[],[<<100,105,114,101,99,116,108,121>>]},<<32,102,114,111,109,32,116,104,101,32,69,114,108,97,110,103,32,99,111,100,101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,116,104,97,116,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,32,98,101,108,111,110,103,115,32,116,111,46,32,73,116,32,114,101,116,117,114,110,115,32,101,105,116,104,101,114,32>>,{code,[],[<<111,107>>]},<<44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,123,82,101,97,115,111,110,44,84,101,120,116,125,125>>]},<<32,105,102,32,108,111,97,100,105,110,103,32,102,97,105,108,115,46,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,32,119,104,105,108,101,32>>,{code,[],[<<84,101,120,116>>]},<<32,105,115,32,97,32,104,117,109,97,110,32,114,101,97,100,97,98,108,101,32,115,116,114,105,110,103,32,116,104,97,116,32,99,97,110,32,103,105,118,101,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,102,97,105,108,117,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,111,97,100,95,102,97,105,108,101,100>>]}]},{dd,[],[<<84,104,101,32,79,83,32,102,97,105,108,101,100,32,116,111,32,108,111,97,100,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,46>>]},{dt,[],[{code,[],[<<98,97,100,95,108,105,98>>]}]},{dd,[],[<<84,104,101,32,108,105,98,114,97,114,121,32,100,105,100,32,110,111,116,32,102,117,108,102,105,108,108,32,116,104,101,32,114,101,113,117,105,114,101,109,101,110,116,115,32,97,115,32,97,32,78,73,70,32,108,105,98,114,97,114,121,32,111,102,32,116,104,101,32,99,97,108,108,105,110,103,32,109,111,100,117,108,101,46>>]},{dt,[],[{code,[],[<<108,111,97,100,32,124,32,117,112,103,114,97,100,101>>]}]},{dd,[],[<<84,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,108,105,98,114,97,114,121,32,99,97,108,108,98,97,99,107,32,119,97,115,32,117,110,115,117,99,99,101,115,115,102,117,108,46>>]},{dt,[],[{code,[],[<<114,101,108,111,97,100>>]}]},{dd,[],[<<65,32,78,73,70,32,108,105,98,114,97,114,121,32,105,115,32,97,108,114,101,97,100,121,32,108,111,97,100,101,100,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,32,105,110,115,116,97,110,99,101,46,32,84,104,101,32,112,114,101,118,105,111,117,115,108,121,32,100,101,112,114,101,99,97,116,101,100,32>>,{code,[],[<<114,101,108,111,97,100>>]},<<32,102,101,97,116,117,114,101,32,119,97,115,32,114,101,109,111,118,101,100,32,105,110,32,79,84,80,32,50,48,46>>]},{dt,[],[{code,[],[<<111,108,100,95,99,111,100,101>>]}]},{dd,[],[<<84,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<108,111,97,100,95,110,105,102,47,50>>]},<<32,119,97,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,111,108,100,32,99,111,100,101,32,111,102,32,97,32,109,111,100,117,108,101,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,117,112,103,114,97,100,101,100,59,32,116,104,105,115,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,53,51>>,signature => [{attribute,2267,spec,{{erlang,load_nif,2},[{type,2267,bounded_fun,[{type,2267,'fun',[{type,2267,product,[{var,2267,'Path'},{var,2267,'LoadInfo'}]},{type,2267,union,[{atom,2267,ok},{var,2267,'Error'}]}]},[{type,2268,constraint,[{atom,2268,is_subtype},[{var,2268,'Path'},{type,2268,string,[]}]]},{type,2269,constraint,[{atom,2269,is_subtype},[{var,2269,'LoadInfo'},{type,2269,term,[]}]]},{type,2270,constraint,[{atom,2270,is_subtype},[{var,2270,'Error'},{type,2270,tuple,[{atom,2270,error},{type,2270,tuple,[{var,2270,'Reason'},{ann_type,2270,[{var,2270,'Text'},{type,2270,string,[]}]}]}]}]]},{type,2271,constraint,[{atom,2271,is_subtype},[{var,2271,'Reason'},{type,2271,union,[{atom,2271,load_failed},{atom,2271,bad_lib},{atom,2271,load},{atom,2271,reload},{atom,2271,upgrade},{atom,2271,old_code}]}]]}]]}]}}]}},{{function,loaded,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1320}],[<<108,111,97,100,101,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,108,108,32,108,111,97,100,101,100,32,69,114,108,97,110,103,32,109,111,100,117,108,101,115,32,40,99,117,114,114,101,110,116,32,97,110,100,32,111,108,100,32,99,111,100,101,41,44,32,105,110,99,108,117,100,105,110,103,32,112,114,101,108,111,97,100,101,100,32,109,111,100,117,108,101,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,48,50>>,signature => [{attribute,1320,spec,{{erlang,loaded,0},[{type,1320,bounded_fun,[{type,1320,'fun',[{type,1320,product,[]},{type,1320,list,[{var,1320,'Module'}]}]},[{type,1321,constraint,[{atom,1321,is_subtype},[{var,1321,'Module'},{type,1321,module,[]}]]}]]}]}}]}},{{function,localtime,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1326}],[<<108,111,99,97,108,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,44,32>>,{code,[],[<<123,123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125,44,32,123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125,125>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,40,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,122,111,110,101,32,97,110,100,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,99,111,114,114,101,99,116,105,111,110,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,49,51>>,signature => [{attribute,1326,spec,{{erlang,localtime,0},[{type,1326,bounded_fun,[{type,1326,'fun',[{type,1326,product,[]},{var,1326,'DateTime'}]},[{type,1327,constraint,[{atom,1327,is_subtype},[{var,1327,'DateTime'},{remote_type,1327,[{atom,1327,calendar},{atom,1327,datetime},[]]}]]}]]}]}}]}},{{function,localtime_to_universaltime,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3481}],[<<108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,116,111,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,44,32,105,102,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32,110,111,32,99,111,110,118,101,114,115,105,111,110,32,105,115,32,100,111,110,101,32,97,110,100,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,51,44,52,53,44,49,55,125,125>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,100,101,110,111,116,101,115,32,97,110,32,105,110,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,51,48>>,signature => [{attribute,3481,spec,{{erlang,localtime_to_universaltime,1},[{type,3481,bounded_fun,[{type,3481,'fun',[{type,3481,product,[{var,3481,'Localtime'}]},{var,3481,'Universaltime'}]},[{type,3482,constraint,[{atom,3482,is_subtype},[{var,3482,'Localtime'},{remote_type,3482,[{atom,3482,calendar},{atom,3482,datetime},[]]}]]},{type,3483,constraint,[{atom,3483,is_subtype},[{var,3483,'Universaltime'},{remote_type,3483,[{atom,3483,calendar},{atom,3483,datetime},[]]}]]}]]}]}}]}},{{function,localtime_to_universaltime,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2275}],[<<108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,116,111,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,32,97,115,32>>,{code,[],[<<101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,49>>]},<<44,32,98,117,116,32,116,104,101,32,99,97,108,108,101,114,32,100,101,99,105,100,101,115,32,105,102,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,105,115,32,97,99,116,105,118,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<73,115,68,115,116,32,61,61,32,116,114,117,101>>]},<<44,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,105,115,32,100,117,114,105,110,103,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,44,32,105,102,32>>,{code,[],[<<73,115,68,115,116,32,61,61,32,102,97,108,115,101>>]},<<32,105,116,32,105,115,32,110,111,116,46,32,73,102,32>>,{code,[],[<<73,115,68,115,116,32,61,61,32,117,110,100,101,102,105,110,101,100>>]},<<44,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,32,99,97,110,32,103,117,101,115,115,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,76,111,99,97,108,116,105,109,101,41>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,44,32,116,114,117,101,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,50,44,52,53,44,49,55,125,125,10,62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,44,32,102,97,108,115,101,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,51,44,52,53,44,49,55,125,125,10,62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,44,32,117,110,100,101,102,105,110,101,100,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,51,44,52,53,44,49,55,125,125>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,100,101,110,111,116,101,115,32,97,110,32,105,110,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,52,55>>,signature => [{attribute,2275,spec,{{erlang,localtime_to_universaltime,2},[{type,2275,bounded_fun,[{type,2275,'fun',[{type,2275,product,[{var,2275,'Localtime'},{var,2275,'IsDst'}]},{var,2275,'Universaltime'}]},[{type,2276,constraint,[{atom,2276,is_subtype},[{var,2276,'Localtime'},{remote_type,2276,[{atom,2276,calendar},{atom,2276,datetime},[]]}]]},{type,2277,constraint,[{atom,2277,is_subtype},[{var,2277,'Universaltime'},{remote_type,2277,[{atom,2277,calendar},{atom,2277,datetime},[]]}]]},{type,2278,constraint,[{atom,2278,is_subtype},[{var,2278,'IsDst'},{type,2278,union,[{atom,2278,true},{atom,2278,false},{atom,2278,undefined}]}]]}]]}]}}]}},{{function,make_ref,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1332}],[<<109,97,107,101,95,114,101,102,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100,35,117,110,105,113,117,101,95,114,101,102,101,114,101,110,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<117,110,105,113,117,101,32,114,101,102,101,114,101,110,99,101>>]},<<46,32,84,104,101,32,114,101,102,101,114,101,110,99,101,32,105,115,32,117,110,105,113,117,101,32,97,109,111,110,103,32,99,111,110,110,101,99,116,101,100,32,110,111,100,101,115,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<75,110,111,119,110,32,105,115,115,117,101,58,32,87,104,101,110,32,97,32,110,111,100,101,32,105,115,32,114,101,115,116,97,114,116,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,110,97,109,101,44,32,114,101,102,101,114,101,110,99,101,115,32,99,114,101,97,116,101,100,32,111,110,32,97,32,110,101,119,101,114,32,110,111,100,101,32,99,97,110,32,98,101,32,109,105,115,116,97,107,101,110,32,102,111,114,32,97,32,114,101,102,101,114,101,110,99,101,32,99,114,101,97,116,101,100,32,111,110,32,97,110,32,111,108,100,101,114,32,110,111,100,101,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,110,97,109,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,55,51>>,signature => [{attribute,1332,spec,{{make_ref,0},[{type,1332,'fun',[{type,1332,product,[]},{type,1332,reference,[]}]}]}}]}},{{function,make_tuple,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2294}],[<<109,97,107,101,95,116,117,112,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,110,101,119,32,116,117,112,108,101,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32>>,{code,[],[<<65,114,105,116,121>>]},<<44,32,119,104,101,114,101,32,97,108,108,32,101,108,101,109,101,110,116,115,32,97,114,101,32>>,{code,[],[<<73,110,105,116,105,97,108,86,97,108,117,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,109,97,107,101,95,116,117,112,108,101,40,52,44,32,91,93,41,46,10,123,91,93,44,91,93,44,91,93,44,91,93,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,57,48>>,signature => [{attribute,2294,spec,{{erlang,make_tuple,2},[{type,2294,bounded_fun,[{type,2294,'fun',[{type,2294,product,[{var,2294,'Arity'},{var,2294,'InitialValue'}]},{type,2294,tuple,any}]},[{type,2295,constraint,[{atom,2295,is_subtype},[{var,2295,'Arity'},{type,2295,arity,[]}]]},{type,2296,constraint,[{atom,2296,is_subtype},[{var,2296,'InitialValue'},{type,2296,term,[]}]]}]]}]}}]}},{{function,make_tuple,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2301}],[<<109,97,107,101,95,116,117,112,108,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,116,117,112,108,101,32,111,102,32,115,105,122,101,32>>,{code,[],[<<65,114,105,116,121>>]},<<44,32,119,104,101,114,101,32,101,97,99,104,32,101,108,101,109,101,110,116,32,104,97,115,32,118,97,108,117,101,32>>,{code,[],[<<68,101,102,97,117,108,116,86,97,108,117,101>>]},<<44,32,97,110,100,32,116,104,101,110,32,102,105,108,108,115,32,105,110,32,118,97,108,117,101,115,32,102,114,111,109,32>>,{code,[],[<<73,110,105,116,76,105,115,116>>]},<<46,32,69,97,99,104,32,108,105,115,116,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<73,110,105,116,76,105,115,116>>]},<<32,109,117,115,116,32,98,101,32,97,32,116,119,111,45,116,117,112,108,101,44,32,119,104,101,114,101,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,116,117,112,108,101,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,32,105,115,32,97,110,121,32,116,101,114,109,46,32,73,102,32,97,32,112,111,115,105,116,105,111,110,32,111,99,99,117,114,115,32,109,111,114,101,32,116,104,97,110,32,111,110,99,101,32,105,110,32,116,104,101,32,108,105,115,116,44,32,116,104,101,32,116,101,114,109,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,108,97,115,116,32,111,99,99,117,114,114,101,110,99,101,32,105,115,32,117,115,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,109,97,107,101,95,116,117,112,108,101,40,53,44,32,91,93,44,32,91,123,50,44,105,103,110,111,114,101,100,125,44,123,53,44,122,122,125,44,123,50,44,97,97,125,93,41,46,10,123,91,93,44,97,97,44,91,93,44,91,93,44,122,122,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,48,50>>,signature => [{attribute,2301,spec,{{erlang,make_tuple,3},[{type,2301,bounded_fun,[{type,2301,'fun',[{type,2301,product,[{var,2301,'Arity'},{var,2301,'DefaultValue'},{var,2301,'InitList'}]},{type,2301,tuple,any}]},[{type,2302,constraint,[{atom,2302,is_subtype},[{var,2302,'Arity'},{type,2302,arity,[]}]]},{type,2303,constraint,[{atom,2303,is_subtype},[{var,2303,'DefaultValue'},{type,2303,term,[]}]]},{type,2304,constraint,[{atom,2304,is_subtype},[{var,2304,'InitList'},{type,2304,list,[{type,2304,tuple,[{ann_type,2304,[{var,2304,'Position'},{type,2304,pos_integer,[]}]},{type,2304,term,[]}]}]}]]}]]}]}}]}},{{function,map_get,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1343}],[<<109,97,112,95,103,101,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<32,105,102,32>>,{code,[],[<<77,97,112>>]},<<32,99,111,110,116,97,105,110,115,32>>,{code,[],[<<75,101,121>>]},<<46>>]},{p,[],[<<84,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<123,98,97,100,109,97,112,44,77,97,112,125>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32>>,{code,[],[<<77,97,112>>]},<<32,105,115,32,110,111,116,32,97,32,109,97,112,44,32,111,114,32,119,105,116,104,32,97,32>>,{code,[],[<<123,98,97,100,107,101,121,44,75,101,121,125>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32,110,111,32,118,97,108,117,101,32,105,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<62,32,75,101,121,32,61,32,49,51,51,55,44,10,32,32,77,97,112,32,61,32,35,123,52,50,32,61,62,32,118,97,108,117,101,95,116,119,111,44,49,51,51,55,32,61,62,32,34,118,97,108,117,101,32,111,110,101,34,44,34,97,34,32,61,62,32,49,125,44,10,32,32,109,97,112,95,103,101,116,40,75,101,121,44,77,97,112,41,46,10,34,118,97,108,117,101,32,111,110,101,34>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,50,48>>,signature => [{attribute,1343,spec,{{map_get,2},[{type,1343,bounded_fun,[{type,1343,'fun',[{type,1343,product,[{var,1343,'Key'},{var,1343,'Map'}]},{var,1343,'Value'}]},[{type,1344,constraint,[{atom,1344,is_subtype},[{var,1344,'Map'},{type,1344,map,any}]]},{type,1345,constraint,[{atom,1345,is_subtype},[{var,1345,'Key'},{type,1345,any,[]}]]},{type,1346,constraint,[{atom,1346,is_subtype},[{var,1346,'Value'},{type,1346,any,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,map_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1337}],[<<109,97,112,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,107,101,121,45,118,97,108,117,101,32,112,97,105,114,115,32,105,110,32>>,{code,[],[<<77,97,112>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,109,97,112,95,115,105,122,101,40,35,123,97,61,62,49,44,32,98,61,62,50,44,32,99,61,62,51,125,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,52,48>>,signature => [{attribute,1337,spec,{{map_size,1},[{type,1337,bounded_fun,[{type,1337,'fun',[{type,1337,product,[{var,1337,'Map'}]},{type,1337,non_neg_integer,[]}]},[{type,1338,constraint,[{atom,1338,is_subtype},[{var,1338,'Map'},{type,1338,map,any}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,match_spec_test,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1351}],[<<109,97,116,99,104,95,115,112,101,99,95,116,101,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,101,115,116,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,117,115,101,100,32,105,110,32,99,97,108,108,115,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,116,115,35,115,101,108,101,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,116,115,58,115,101,108,101,99,116,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,101,115,116,115,32,98,111,116,104,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,34,115,121,110,116,97,99,116,105,99,34,32,99,111,114,114,101,99,116,110,101,115,115,32,97,110,100,32,114,117,110,115,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,103,97,105,110,115,116,32,116,104,101,32,111,98,106,101,99,116,46,32,73,102,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,99,111,110,116,97,105,110,115,32,101,114,114,111,114,115,44,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,69,114,114,111,114,115,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,119,104,101,114,101,32>>,{code,[],[<<69,114,114,111,114,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,110,97,116,117,114,97,108,32,108,97,110,103,117,97,103,101,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,119,104,97,116,32,119,97,115,32,119,114,111,110,103,32,119,105,116,104,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<116,97,98,108,101>>]},<<44,32,116,104,101,32,111,98,106,101,99,116,32,116,111,32,109,97,116,99,104,32,97,103,97,105,110,115,116,32,105,115,32,116,111,32,98,101,32,97,32,116,117,112,108,101,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,104,101,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,82,101,115,117,108,116,44,91,93,44,87,97,114,110,105,110,103,115,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,119,104,97,116,32,119,111,117,108,100,32,104,97,118,101,32,98,101,101,110,32,116,104,101,32,114,101,115,117,108,116,32,105,110,32,97,32,114,101,97,108,32>>,{code,[],[<<101,116,115,58,115,101,108,101,99,116,47,50>>]},<<32,99,97,108,108,44,32,111,114,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,111,98,106,101,99,116,32,116,117,112,108,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<116,114,97,99,101>>]},<<44,32,116,104,101,32,111,98,106,101,99,116,32,116,111,32,109,97,116,99,104,32,97,103,97,105,110,115,116,32,105,115,32,116,111,32,98,101,32,97,32,108,105,115,116,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,82,101,115,117,108,116,44,32,70,108,97,103,115,44,32,87,97,114,110,105,110,103,115,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{code,[],[<<116,114,117,101>>]},<<32,105,102,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,116,111,32,98,101,32,101,109,105,116,116,101,100>>]},{li,[],[{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,110,111,116,32,116,111,32,98,101,32,101,109,105,116,116,101,100>>]},{li,[],[<<84,104,101,32,109,101,115,115,97,103,101,32,116,101,114,109,32,116,111,32,98,101,32,97,112,112,101,110,100,101,100,32,116,111,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101>>]}]},{p,[],[{code,[],[<<70,108,97,103,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,97,108,108,32,116,104,101,32,116,114,97,99,101,32,102,108,97,103,115,32,116,111,32,98,101,32,101,110,97,98,108,101,100,44,32,99,117,114,114,101,110,116,108,121,32,116,104,105,115,32,105,115,32,111,110,108,121,32>>,{code,[],[<<114,101,116,117,114,110,95,116,114,97,99,101>>]},<<46>>]},{p,[],[<<84,104,105,115,32,105,115,32,97,32,117,115,101,102,117,108,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,116,101,115,116,32,116,111,111,108,44,32,101,115,112,101,99,105,97,108,108,121,32,119,104,101,110,32,119,114,105,116,105,110,103,32,99,111,109,112,108,105,99,97,116,101,100,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,116,115,35,116,101,115,116,95,109,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,116,115,58,116,101,115,116,95,109,115,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,53,51>>,signature => [{attribute,1351,spec,{{erlang,match_spec_test,3},[{type,1351,bounded_fun,[{type,1351,'fun',[{type,1351,product,[{var,1351,'MatchAgainst'},{var,1351,'MatchSpec'},{var,1351,'Type'}]},{var,1351,'TestResult'}]},[{type,1352,constraint,[{atom,1352,is_subtype},[{var,1352,'MatchAgainst'},{type,1352,union,[{type,1352,list,[{type,1352,term,[]}]},{type,1352,tuple,any}]}]]},{type,1353,constraint,[{atom,1353,is_subtype},[{var,1353,'MatchSpec'},{type,1353,term,[]}]]},{type,1354,constraint,[{atom,1354,is_subtype},[{var,1354,'Type'},{type,1354,union,[{atom,1354,table},{atom,1354,trace}]}]]},{type,1355,constraint,[{atom,1355,is_subtype},[{var,1355,'TestResult'},{type,1355,union,[{type,1355,tuple,[{atom,1355,ok},{type,1355,term,[]},{type,1355,list,[{atom,1355,return_trace}]},{type,1355,list,[{type,1355,tuple,[{type,1355,union,[{atom,1355,error},{atom,1355,warning}]},{type,1355,string,[]}]}]}]},{type,1355,tuple,[{atom,1355,error},{type,1355,list,[{type,1355,tuple,[{type,1355,union,[{atom,1355,error},{atom,1355,warning}]},{type,1355,string,[]}]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,max,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3962}],[<<109,97,120,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,97,114,103,101,115,116,32,111,102,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,97,110,100,32>>,{code,[],[<<84,101,114,109,50>>]},<<46,32,73,102,32,116,104,101,32,116,101,114,109,115,32,99,111,109,112,97,114,101,32,101,113,117,97,108,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,44,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,116,101,114,109,45,99,111,109,112,97,114,105,115,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,120,112,114,101,115,115,105,111,110,115,32,115,101,99,116,105,111,110>>]},<<32,99,111,110,116,97,105,110,115,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,32,97,110,100,32,104,111,119,32,116,101,114,109,115,32,97,114,101,32,111,114,100,101,114,101,100,46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,109,97,120,40,49,44,32,50,41,46,10,50>>]}]},{pre,[],[{code,[],[<<62,32,109,97,120,40,49,46,48,44,32,49,41,46,10,49,46,48>>]}]},{pre,[],[{code,[],[<<62,32,109,97,120,40,49,44,32,49,46,48,41,46,10,49>>]}]},{pre,[],[{code,[],[<<62,32,109,97,120,40,34,97,98,99,34,44,32,34,98,34,41,46,10,34,98,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,57,49>>,signature => [{attribute,3962,spec,{{max,2},[{type,3962,bounded_fun,[{type,3962,'fun',[{type,3962,product,[{var,3962,'Term1'},{var,3962,'Term2'}]},{var,3962,'Maximum'}]},[{type,3963,constraint,[{atom,3963,is_subtype},[{var,3963,'Term1'},{type,3963,term,[]}]]},{type,3964,constraint,[{atom,3964,is_subtype},[{var,3964,'Term2'},{type,3964,term,[]}]]},{type,3965,constraint,[{atom,3965,is_subtype},[{var,3965,'Maximum'},{type,3965,term,[]}]]}]]}]}}]}},{{function,md5,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1360}],[<<109,100,53,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,117,116,101,115,32,97,110,32,77,68,53,32,109,101,115,115,97,103,101,32,100,105,103,101,115,116,32,102,114,111,109,32>>,{code,[],[<<68,97,116,97>>]},<<44,32,119,104,101,114,101,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,100,105,103,101,115,116,32,105,115,32,49,50,56,32,98,105,116,115,32,40,49,54,32,98,121,116,101,115,41,46,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,111,114,32,97,32,108,105,115,116,32,111,102,32,115,109,97,108,108,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,77,68,53,44,32,115,101,101,32>>,{a,[{href,<<104,116,116,112,115,58,47,47,119,119,119,46,105,101,116,102,46,111,114,103,47,114,102,99,47,114,102,99,49,51,50,49,46,116,120,116>>}],[<<82,70,67,32,49,51,50,49,32,45,32,84,104,101,32,77,68,53,32,77,101,115,115,97,103,101,45,68,105,103,101,115,116,32,65,108,103,111,114,105,116,104,109>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,32,77,68,53,32,77,101,115,115,97,103,101,45,68,105,103,101,115,116,32,65,108,103,111,114,105,116,104,109,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,99,111,110,115,105,100,101,114,101,100,32,115,97,102,101,32,102,111,114,32,99,111,100,101,45,115,105,103,110,105,110,103,32,111,114,32,115,111,102,116,119,97,114,101,45,105,110,116,101,103,114,105,116,121,32,112,117,114,112,111,115,101,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,50,48>>,signature => [{attribute,1360,spec,{{erlang,md5,1},[{type,1360,bounded_fun,[{type,1360,'fun',[{type,1360,product,[{var,1360,'Data'}]},{var,1360,'Digest'}]},[{type,1361,constraint,[{atom,1361,is_subtype},[{var,1361,'Data'},{type,1361,iodata,[]}]]},{type,1362,constraint,[{atom,1362,is_subtype},[{var,1362,'Digest'},{type,1362,binary,[]}]]}]]}]}}]}},{{function,md5_final,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1367}],[<<109,100,53,95,102,105,110,97,108,47,49>>],#{<<101,110>> => [{p,[],[<<70,105,110,105,115,104,101,115,32,116,104,101,32,117,112,100,97,116,101,32,111,102,32,97,110,32,77,68,53,32>>,{code,[],[<<67,111,110,116,101,120,116>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,99,111,109,112,117,116,101,100,32>>,{code,[],[<<77,68,53>>]},<<32,109,101,115,115,97,103,101,32,100,105,103,101,115,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,51,56>>,signature => [{attribute,1367,spec,{{erlang,md5_final,1},[{type,1367,bounded_fun,[{type,1367,'fun',[{type,1367,product,[{var,1367,'Context'}]},{var,1367,'Digest'}]},[{type,1368,constraint,[{atom,1368,is_subtype},[{var,1368,'Context'},{type,1368,binary,[]}]]},{type,1369,constraint,[{atom,1369,is_subtype},[{var,1369,'Digest'},{type,1369,binary,[]}]]}]]}]}}]}},{{function,md5_init,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1374}],[<<109,100,53,95,105,110,105,116,47,48>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,110,32,77,68,53,32,99,111,110,116,101,120,116,44,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,100,53,95,117,112,100,97,116,101,47,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,52,56>>,signature => [{attribute,1374,spec,{{erlang,md5_init,0},[{type,1374,bounded_fun,[{type,1374,'fun',[{type,1374,product,[]},{var,1374,'Context'}]},[{type,1375,constraint,[{atom,1375,is_subtype},[{var,1375,'Context'},{type,1375,binary,[]}]]}]]}]}}]}},{{function,md5_update,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1380}],[<<109,100,53,95,117,112,100,97,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<85,112,100,97,116,101,32,97,110,32,77,68,53,32>>,{code,[],[<<67,111,110,116,101,120,116>>]},<<32,119,105,116,104,32>>,{code,[],[<<68,97,116,97>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32,97,32>>,{code,[],[<<78,101,119,67,111,110,116,101,120,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,53,55>>,signature => [{attribute,1380,spec,{{erlang,md5_update,2},[{type,1380,bounded_fun,[{type,1380,'fun',[{type,1380,product,[{var,1380,'Context'},{var,1380,'Data'}]},{var,1380,'NewContext'}]},[{type,1381,constraint,[{atom,1381,is_subtype},[{var,1381,'Context'},{type,1381,binary,[]}]]},{type,1382,constraint,[{atom,1382,is_subtype},[{var,1382,'Data'},{type,1382,iodata,[]}]]},{type,1383,constraint,[{atom,1383,is_subtype},[{var,1383,'NewContext'},{type,1383,binary,[]}]]}]]}]}}]}},{{function,memory,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3994}],[<<109,101,109,111,114,121,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,101,109,111,114,121,95,116,121,112,101>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,109,101,109,111,114,121,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,101,109,117,108,97,116,111,114,46,32,69,97,99,104,32,108,105,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,84,121,112,101,44,32,83,105,122,101,125>>]},<<46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,109,101,109,111,114,121,32,116,121,112,101,46,32,84,104,101,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,32>>,{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,109,101,109,111,114,121,32,115,105,122,101,32,105,110,32,98,121,116,101,115,46>>]},{p,[],[<<77,101,109,111,114,121,32,116,121,112,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,111,116,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,115,105,122,101,32,102,111,114,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<46>>]}]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,46>>]}]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,101,115,95,117,115,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,46,32,84,104,105,115,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,116,104,101,32,101,109,117,108,97,116,111,114,32,116,104,97,116,32,105,115,32,110,111,116,32,100,105,114,101,99,116,108,121,32,114,101,108,97,116,101,100,32,116,111,32,97,110,121,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,46,32,77,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,105,115,32,110,111,116,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,105,115,32,109,101,109,111,114,121,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,111,111,108,115,58,105,110,115,116,114,117,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,115,116,114,117,109,101,110,116,40,51,41>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,103,101,116,32,97,32,109,111,114,101,32,100,101,116,97,105,108,101,100,32,98,114,101,97,107,100,111,119,110,32,111,102,32,119,104,97,116,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,105,115,32,116,121,112,101,46>>]}]},{dt,[],[{code,[],[<<97,116,111,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,97,116,111,109,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<97,116,111,109,95,117,115,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,102,111,114,32,97,116,111,109,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<97,116,111,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,98,105,110,97,114,105,101,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<99,111,100,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,69,114,108,97,110,103,32,99,111,100,101,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<101,116,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,69,84,83,32,116,97,98,108,101,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<108,111,119>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,111,110,32,54,52,45,98,105,116,32,104,97,108,102,119,111,114,100,32,101,109,117,108,97,116,111,114,46,32,84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,105,110,32,108,111,119,32,109,101,109,111,114,121,32,97,114,101,97,115,32,116,104,97,116,32,97,114,101,32,114,101,115,116,114,105,99,116,101,100,32,116,111,32,60,32,52,32,71,66,44,32,97,108,116,104,111,117,103,104,32,116,104,101,32,115,121,115,116,101,109,32,99,97,110,32,104,97,118,101,32,109,111,114,101,32,109,101,109,111,114,121,46>>]},{p,[],[<<67,97,110,32,98,101,32,114,101,109,111,118,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,32,111,102,32,116,104,101,32,104,97,108,102,119,111,114,100,32,101,109,117,108,97,116,111,114,46>>]}]},{dt,[],[{code,[],[<<109,97,120,105,109,117,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,115,105,110,99,101,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,97,115,32,115,116,97,114,116,101,100,46,32,84,104,105,115,32,116,117,112,108,101,32,105,115,32,111,110,108,121,32,112,114,101,115,101,110,116,32,119,104,101,110,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,114,117,110,32,119,105,116,104,32,105,110,115,116,114,117,109,101,110,116,97,116,105,111,110,46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,104,111,119,32,116,111,32,114,117,110,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,105,116,104,32,105,110,115,116,114,117,109,101,110,116,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,111,111,108,115,58,105,110,115,116,114,117,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,115,116,114,117,109,101,110,116,40,51,41>>]}]},<<32,97,110,100,47,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<101,114,108,40,49,41>>]}]},<<46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,118,97,108,117,101,32,105,115,32,110,111,116,32,99,111,109,112,108,101,116,101,46,32,83,111,109,101,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,116,104,97,116,32,105,115,32,116,111,32,98,101,32,112,97,114,116,32,111,102,32,116,104,105,115,32,118,97,108,117,101,32,105,115,32,110,111,116,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,114,117,110,32,119,105,116,104,32,105,110,115,116,114,117,109,101,110,116,97,116,105,111,110,44,32,116,104,101,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,118,97,108,117,101,32,105,115,32,109,111,114,101,32,97,99,99,117,114,97,116,101,44,32,98,117,116,32,109,101,109,111,114,121,32,100,105,114,101,99,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32>>,{code,[],[<<109,97,108,108,111,99>>]},<<32,40,97,110,100,32,102,114,105,101,110,100,115,41,32,105,115,32,115,116,105,108,108,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,118,97,108,117,101,46,32,68,105,114,101,99,116,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,97,108,108,111,99>>]},<<32,97,114,101,32,111,110,108,121,32,100,111,110,101,32,102,114,111,109,32,79,83,45,115,112,101,99,105,102,105,99,32,114,117,110,116,105,109,101,32,108,105,98,114,97,114,105,101,115,32,97,110,100,32,112,101,114,104,97,112,115,32,102,114,111,109,32,117,115,101,114,45,105,109,112,108,101,109,101,110,116,101,100,32,69,114,108,97,110,103,32,100,114,105,118,101,114,115,32,116,104,97,116,32,100,111,32,110,111,116,32,117,115,101,32,116,104,101,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32,100,114,105,118,101,114,32,105,110,116,101,114,102,97,99,101,46>>]},{p,[],[<<65,115,32,116,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,32,105,115,32,116,104,101,32,115,117,109,32,111,102,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<44,32,116,104,101,32,101,114,114,111,114,32,105,110,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,112,114,111,112,97,103,97,116,101,115,32,116,111,32,116,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,46>>]},{p,[],[<<84,104,101,32,100,105,102,102,101,114,101,110,116,32,97,109,111,117,110,116,115,32,111,102,32,109,101,109,111,114,121,32,116,104,97,116,32,97,114,101,32,115,117,109,109,101,100,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,44,32,119,104,105,99,104,32,105,110,116,114,111,100,117,99,101,115,32,97,110,32,101,114,114,111,114,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},{p,[],[<<84,104,101,32,100,105,102,102,101,114,101,110,116,32,118,97,108,117,101,115,32,104,97,118,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,101,108,97,116,105,111,110,32,116,111,32,101,97,99,104,32,111,116,104,101,114,46,32,86,97,108,117,101,115,32,98,101,103,105,110,110,105,110,103,32,119,105,116,104,32,97,110,32,117,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114,32,105,115,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<116,111,116,97,108,32,32,32,32,32,32,61,32,112,114,111,99,101,115,115,101,115,32,43,32,115,121,115,116,101,109,10,112,114,111,99,101,115,115,101,115,32,32,61,32,112,114,111,99,101,115,115,101,115,95,117,115,101,100,32,43,32,80,114,111,99,101,115,115,101,115,78,111,116,85,115,101,100,10,115,121,115,116,101,109,32,32,32,32,32,61,32,97,116,111,109,32,43,32,98,105,110,97,114,121,32,43,32,99,111,100,101,32,43,32,101,116,115,32,43,32,79,116,104,101,114,83,121,115,116,101,109,10,97,116,111,109,32,32,32,32,32,32,32,61,32,97,116,111,109,95,117,115,101,100,32,43,32,65,116,111,109,78,111,116,85,115,101,100,10,82,101,97,108,84,111,116,97,108,32,32,61,32,112,114,111,99,101,115,115,101,115,32,43,32,82,101,97,108,83,121,115,116,101,109,10,82,101,97,108,83,121,115,116,101,109,32,61,32,115,121,115,116,101,109,32,43,32,77,105,115,115,101,100,83,121,115,116,101,109>>]}]},{p,[],[<<77,111,114,101,32,116,117,112,108,101,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,116,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,104,97,114,101,100,32,108,105,98,114,97,114,105,101,115,44,32,116,104,101,32,99,111,100,101,32,111,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,116,115,101,108,102,44,32,97,110,100,32,116,104,101,32,101,109,117,108,97,116,111,114,32,115,116,97,99,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,105,110,99,108,117,100,101,100,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,101,113,117,97,108,32,116,111,32,116,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,97,108,108,32,112,97,103,101,115,32,109,97,112,112,101,100,32,116,111,32,116,104,101,32,101,109,117,108,97,116,111,114,46>>]},{p,[],[<<65,108,115,111,44,32,98,101,99,97,117,115,101,32,111,102,32,102,114,97,103,109,101,110,116,97,116,105,111,110,32,97,110,100,32,112,114,101,114,101,115,101,114,118,97,116,105,111,110,32,111,102,32,109,101,109,111,114,121,32,97,114,101,97,115,44,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,115,101,103,109,101,110,116,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,98,108,111,99,107,115,32,99,97,110,32,98,101,32,109,117,99,104,32,108,97,114,103,101,114,32,116,104,97,110,32,116,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,116,104,101,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,98,108,111,99,107,115,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,54,46,52,44,32>>,{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48>>]},<<32,114,101,113,117,105,114,101,115,32,116,104,97,116,32,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,115,32,97,114,101,32,101,110,97,98,108,101,100,32,40,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,41,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,105,102,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,32,104,97,115,32,98,101,101,110,32,100,105,115,97,98,108,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,54,56>>,signature => [{attribute,3994,spec,{{erlang,memory,0},[{type,3994,bounded_fun,[{type,3994,'fun',[{type,3994,product,[]},{type,3994,list,[{type,3994,tuple,[{var,3994,'Type'},{var,3994,'Size'}]}]}]},[{type,3995,constraint,[{atom,3995,is_subtype},[{var,3995,'Type'},{user_type,3995,memory_type,[]}]]},{type,3996,constraint,[{atom,3996,is_subtype},[{var,3996,'Size'},{type,3996,non_neg_integer,[]}]]}]]}]}}]}},{{function,memory,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,4013}],[<<109,101,109,111,114,121,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,101,109,111,114,121,95,116,121,112,101>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,101,109,111,114,121,32,115,105,122,101,32,105,110,32,98,121,116,101,115,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,109,101,109,111,114,121,32,111,102,32,116,121,112,101,32>>,{code,[],[<<84,121,112,101>>]},<<46,32,84,104,101,32,97,114,103,117,109,101,110,116,32,99,97,110,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<109,101,109,111,114,121,95,116,121,112,101,40,41>>]},<<32,97,116,111,109,115,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,97,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,109,101,109,111,114,121,95,116,121,112,101,40,41,44,32,83,105,122,101,32,58,58,32,105,110,116,101,103,101,114,32,62,61,32,48,125>>]},<<32,116,117,112,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,54,46,52,44,32>>,{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,49>>]},<<32,114,101,113,117,105,114,101,115,32,116,104,97,116,32,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,115,32,97,114,101,32,101,110,97,98,108,101,100,32,40,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,41,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,110,111,116,32,111,110,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,116,121,112,101,115,32,108,105,115,116,101,100,32,105,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,101,109,111,114,121,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48>>]}]},<<46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<109,97,120,105,109,117,109>>]},<<32,105,115,32,112,97,115,115,101,100,32,97,115,32>>,{code,[],[<<84,121,112,101>>]},<<32,97,110,100,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,110,111,116,32,114,117,110,32,105,110,32,105,110,115,116,114,117,109,101,110,116,101,100,32,109,111,100,101,46>>]},{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[<<73,102,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,32,104,97,115,32,98,101,101,110,32,100,105,115,97,98,108,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,101,109,111,114,121,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,49,50>>,signature => [{attribute,4013,spec,{{erlang,memory,1},[{type,4013,'fun',[{type,4013,product,[{ann_type,4013,[{var,4013,'Type'},{user_type,4013,memory_type,[]}]}]},{type,4013,non_neg_integer,[]}]},{type,4014,'fun',[{type,4014,product,[{ann_type,4014,[{var,4014,'TypeList'},{type,4014,list,[{user_type,4014,memory_type,[]}]}]}]},{type,4014,list,[{type,4014,tuple,[{user_type,4014,memory_type,[]},{type,4014,non_neg_integer,[]}]}]}]}]}}]}},{{function,min,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3955}],[<<109,105,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,111,102,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,97,110,100,32>>,{code,[],[<<84,101,114,109,50>>]},<<46,32,73,102,32,116,104,101,32,116,101,114,109,115,32,99,111,109,112,97,114,101,32,101,113,117,97,108,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,44,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,116,101,114,109,45,99,111,109,112,97,114,105,115,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,120,112,114,101,115,115,105,111,110,115,32,115,101,99,116,105,111,110>>]},<<32,99,111,110,116,97,105,110,115,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,32,97,110,100,32,104,111,119,32,116,101,114,109,115,32,97,114,101,32,111,114,100,101,114,101,100,46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,109,105,110,40,49,44,32,50,41,46,10,49>>]}]},{pre,[],[{code,[],[<<62,32,109,105,110,40,49,46,48,44,32,49,41,46,10,49,46,48>>]}]},{pre,[],[{code,[],[<<62,32,109,105,110,40,49,44,32,49,46,48,41,46,10,49>>]}]},{pre,[],[{code,[],[<<62,32,109,105,110,40,34,97,98,99,34,44,32,34,98,34,41,46,10,34,97,98,99,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,53,50>>,signature => [{attribute,3955,spec,{{min,2},[{type,3955,bounded_fun,[{type,3955,'fun',[{type,3955,product,[{var,3955,'Term1'},{var,3955,'Term2'}]},{var,3955,'Minimum'}]},[{type,3956,constraint,[{atom,3956,is_subtype},[{var,3956,'Term1'},{type,3956,term,[]}]]},{type,3957,constraint,[{atom,3957,is_subtype},[{var,3957,'Term2'},{type,3957,term,[]}]]},{type,3958,constraint,[{atom,3958,is_subtype},[{var,3958,'Minimum'},{type,3958,term,[]}]]}]]}]}}]}},{{function,module_loaded,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1388}],[<<109,111,100,117,108,101,95,108,111,97,100,101,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,108,111,97,100,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,73,116,32,100,111,101,115,32,110,111,116,32,97,116,116,101,109,112,116,32,116,111,32,108,111,97,100,32,116,104,101,32,109,111,100,117,108,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,56,49>>,signature => [{attribute,1388,spec,{{module_loaded,1},[{type,1388,bounded_fun,[{type,1388,'fun',[{type,1388,product,[{var,1388,'Module'}]},{type,1388,boolean,[]}]},[{type,1389,constraint,[{atom,1389,is_subtype},[{var,1389,'Module'},{type,1389,module,[]}]]}]]}]}}]}},{{function,monitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1401}],[<<109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,111,110,105,116,111,114,95,112,111,114,116,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<109,111,110,105,116,111,114,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]}]},{p,[],[{a,[{id,<<109,111,110,105,116,111,114,95,109,101,115,115,97,103,101>>}],[]},<<83,101,110,100,115,32,97,32,109,111,110,105,116,111,114,32,114,101,113,117,101,115,116,32,111,102,32,116,121,112,101,32>>,{code,[],[<<84,121,112,101>>]},<<32,116,111,32,116,104,101,32,101,110,116,105,116,121,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<46,32,73,102,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,111,114,32,105,116,32,99,104,97,110,103,101,115,32,109,111,110,105,116,111,114,101,100,32,115,116,97,116,101,44,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,105,115,32,110,111,116,105,102,105,101,100,32,98,121,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,97,116,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<123,84,97,103,44,32,77,111,110,105,116,111,114,82,101,102,44,32,84,121,112,101,44,32,79,98,106,101,99,116,44,32,73,110,102,111,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,114,101,113,117,101,115,116,32,105,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,115,105,103,110,97,108,46,32,84,104,97,116,32,105,115,44,32,105,116,32,116,97,107,101,115,32,116,105,109,101,32,98,101,102,111,114,101,32,116,104,101,32,115,105,103,110,97,108,32,114,101,97,99,104,101,115,32,105,116,115,32,100,101,115,116,105,110,97,116,105,111,110,46>>]}]},{p,[],[{code,[],[<<84,121,112,101>>]},<<32,99,97,110,32,98,101,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,58,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<44,32>>,{code,[],[<<112,111,114,116>>]},<<32,111,114,32>>,{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]},<<46>>]},{p,[],[<<65,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116>>]},<<32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,111,110,108,121,32,111,110,99,101,44,32,97,102,116,101,114,32,116,104,97,116,32,105,116,32,105,115,32,114,101,109,111,118,101,100,32,102,114,111,109,32,98,111,116,104,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,46,32,77,111,110,105,116,111,114,115,32,97,114,101,32,102,105,114,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,116,101,114,109,105,110,97,116,101,115,44,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,97,116,32,116,104,101,32,109,111,109,101,110,116,32,111,102,32,99,114,101,97,116,105,111,110,44,32,111,114,32,105,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,105,116,32,105,115,32,108,111,115,116,46,32,73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,105,116,32,105,115,32,108,111,115,116,44,32,119,101,32,100,111,32,110,111,116,32,107,110,111,119,32,105,102,32,105,116,32,115,116,105,108,108,32,101,120,105,115,116,115,46,32,84,104,101,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,97,108,115,111,32,116,117,114,110,101,100,32,111,102,102,32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<100,101,109,111,110,105,116,111,114,47,49>>]},<<32,105,115,32,99,97,108,108,101,100,46>>]},{p,[],[<<65,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116>>]},<<32,109,111,110,105,116,111,114,32,98,121,32,110,97,109,101,32,114,101,115,111,108,118,101,115,32,116,104,101,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,116,111,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<32,111,110,108,121,32,111,110,99,101,32,97,116,32,116,104,101,32,109,111,109,101,110,116,32,111,102,32,109,111,110,105,116,111,114,32,105,110,115,116,97,110,116,105,97,116,105,111,110,44,32,108,97,116,101,114,32,99,104,97,110,103,101,115,32,116,111,32,116,104,101,32,110,97,109,101,32,114,101,103,105,115,116,114,97,116,105,111,110,32,119,105,108,108,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,101,120,105,115,116,105,110,103,32,109,111,110,105,116,111,114,46>>]},{p,[],[<<87,104,101,110,32,97,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116>>]},<<32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,44,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,104,97,116,32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<123,39,68,79,87,78,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,84,121,112,101,44,32,79,98,106,101,99,116,44,32,73,110,102,111,125>>]}]},{p,[],[<<73,110,32,116,104,101,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,97,110,100,32>>,{code,[],[<<84,121,112,101>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,44,32,97,110,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<79,98,106,101,99,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,44,32,119,104,105,99,104,32,116,114,105,103,103,101,114,101,100,32,116,104,101,32,101,118,101,110,116,46,32,87,104,101,110,32,109,111,110,105,116,111,114,105,110,103,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,44,32>>,{code,[],[<<79,98,106,101,99,116>>]},<<32,119,105,108,108,32,98,101,32,101,113,117,97,108,32,116,111,32,116,104,101,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<32,116,104,97,116,32,119,97,115,32,98,101,105,110,103,32,109,111,110,105,116,111,114,101,100,46,32,87,104,101,110,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,98,121,32,110,97,109,101,44,32>>,{code,[],[<<79,98,106,101,99,116>>]},<<32,119,105,108,108,32,104,97,118,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,82,101,103,105,115,116,101,114,101,100,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,119,104,105,99,104,32,104,97,115,32,98,101,101,110,32,117,115,101,100,32,119,105,116,104,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,99,97,108,108,32,97,110,100,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,108,111,99,97,108,32,111,114,32,114,101,109,111,116,101,32,110,111,100,101,32,110,97,109,101,32,40,102,111,114,32,112,111,114,116,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,110,97,109,101,44,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,97,108,119,97,121,115,32,108,111,99,97,108,32,110,111,100,101,32,110,97,109,101,41,46>>]}]},{dt,[],[{code,[],[<<73,110,102,111>>]}]},{dd,[],[{p,[],[<<69,105,116,104,101,114,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,44,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<32,40,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,100,105,100,32,110,111,116,32,101,120,105,115,116,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,109,111,110,105,116,111,114,32,99,114,101,97,116,105,111,110,41,44,32,111,114,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,40,110,111,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,101,32,110,111,100,101,32,119,104,101,114,101,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,32,114,101,115,105,100,101,115,41,46>>]}]}]},{dl,[],[{dt,[],[<<77,111,110,105,116,111,114,105,110,103,32,97,32>>,{a,[{id,<<109,111,110,105,116,111,114,95,112,114,111,99,101,115,115>>}],[]},{code,[],[<<112,114,111,99,101,115,115>>]}]},{dd,[],[{p,[],[<<67,114,101,97,116,101,115,32,109,111,110,105,116,111,114,32,98,101,116,119,101,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,97,110,100,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,40,108,111,99,97,108,32,111,114,32,114,101,109,111,116,101,41,44,32,97,110,32,97,116,111,109,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,111,114,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,82,101,103,105,115,116,101,114,101,100,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,102,111,114,32,97,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,44,32,108,111,99,97,116,101,100,32,101,108,115,101,119,104,101,114,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,82,84,83,32,49,48,46,48,32,40,79,84,80,32,50,49,46,48,41,44,32,109,111,110,105,116,111,114,105,110,103,32,97,32,112,114,111,99,101,115,115,32,99,111,117,108,100,32,102,97,105,108,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,32,114,101,115,105,100,101,100,32,111,110,32,97,32,112,114,105,109,105,116,105,118,101,32,110,111,100,101,32,40,115,117,99,104,32,97,115,32,101,114,108,95,105,110,116,101,114,102,97,99,101,32,111,114,32,106,105,110,116,101,114,102,97,99,101,41,44,32,119,104,101,114,101,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,46>>]},{p,[],[<<78,111,119,44,32,115,117,99,104,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,119,105,108,108,32,105,110,115,116,101,97,100,32,115,117,99,99,101,101,100,32,97,110,100,32,97,32,109,111,110,105,116,111,114,32,105,115,32,99,114,101,97,116,101,100,46,32,66,117,116,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,111,110,108,121,32,115,117,112,101,114,118,105,115,101,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,46,32,84,104,97,116,32,105,115,44,32,97,32>>,{code,[],[<<123,39,68,79,87,78,39,44,32,95,44,32,112,114,111,99,101,115,115,44,32,95,44,32,110,111,99,111,110,110,101,99,116,105,111,110,125>>]},<<32,105,115,32,116,104,101,32,111,110,108,121,32,109,101,115,115,97,103,101,32,116,104,97,116,32,109,97,121,32,98,101,32,114,101,99,101,105,118,101,100,44,32,97,115,32,116,104,101,32,112,114,105,109,105,116,105,118,101,32,110,111,100,101,32,104,97,118,101,32,110,111,32,119,97,121,32,111,102,32,114,101,112,111,114,116,105,110,103,32,116,104,101,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,46>>]}]}]},{dt,[],[<<77,111,110,105,116,111,114,105,110,103,32,97,32>>,{a,[{id,<<109,111,110,105,116,111,114,95,112,111,114,116>>}],[]},{code,[],[<<112,111,114,116>>]}]},{dd,[],[{p,[],[<<67,114,101,97,116,101,115,32,109,111,110,105,116,111,114,32,98,101,116,119,101,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,97,110,100,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,97,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<32,40,111,110,108,121,32,108,111,99,97,108,41,44,32,97,110,32,97,116,111,109,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,111,114,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,82,101,103,105,115,116,101,114,101,100,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,102,111,114,32,97,32,114,101,103,105,115,116,101,114,101,100,32,112,111,114,116,44,32,108,111,99,97,116,101,100,32,111,110,32,116,104,105,115,32,110,111,100,101,46,32,78,111,116,101,44,32,116,104,97,116,32,97,116,116,101,109,112,116,32,116,111,32,109,111,110,105,116,111,114,32,97,32,114,101,109,111,116,101,32,112,111,114,116,32,119,105,108,108,32,114,101,115,117,108,116,32,105,110,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46>>]}]},{dt,[],[<<77,111,110,105,116,111,114,105,110,103,32,97,32>>,{a,[{id,<<109,111,110,105,116,111,114,95,116,105,109,101,95,111,102,102,115,101,116>>}],[]},{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]}]},{dd,[],[{p,[],[<<77,111,110,105,116,111,114,115,32,99,104,97,110,103,101,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,105,109,101,32,111,102,102,115,101,116>>]}]},<<32,98,101,116,119,101,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<46,32,79,110,101,32,118,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,101,120,105,115,116,115,32,105,110,32,99,111,109,98,105,110,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<116,105,109,101,95,111,102,102,115,101,116,32,84,121,112,101>>]},<<44,32,110,97,109,101,108,121,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<99,108,111,99,107,95,115,101,114,118,105,99,101>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<99,108,111,99,107,95,115,101,114,118,105,99,101>>]},<<32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,32,112,114,111,99,101,115,115,46,32,73,110,32,116,104,105,115,32,99,97,115,101,32,105,116,32,115,101,114,118,101,115,32,97,115,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,116,101,114,110,97,108,32,99,108,111,99,107,32,115,101,114,118,105,99,101,32,97,116,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,119,104,101,110,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,46,32,84,104,105,115,32,101,105,116,104,101,114,32,105,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,118,97,108,117,101,32,105,115,32,99,104,97,110,103,101,100,44,32,111,114,32,105,102,32,116,104,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,32,102,114,111,109,32,112,114,101,108,105,109,105,110,97,114,121,32,116,111,32,102,105,110,97,108,32,100,117,114,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,116,105,109,101,95,111,102,102,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,110,97,108,105,122,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116>>]},<<32,119,104,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46,32,87,104,101,110,32,97,32,99,104,97,110,103,101,32,102,114,111,109,32,112,114,101,108,105,109,105,110,97,114,121,32,116,111,32,102,105,110,97,108,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,109,97,100,101,44,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,111,110,99,101,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,118,97,108,117,101,32,119,97,115,32,99,104,97,110,103,101,100,32,111,114,32,110,111,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,32,119,104,101,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,101,116,101,99,116,115,32,116,104,97,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,104,97,115,32,99,104,97,110,103,101,100,46,32,84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,111,101,115,44,32,104,111,119,101,118,101,114,44,32,110,111,116,32,100,101,116,101,99,116,32,116,104,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,119,104,101,110,32,105,116,32,111,99,99,117,114,115,46,32,65,32,116,97,115,107,32,99,104,101,99,107,105,110,103,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,101,120,101,99,117,116,101,32,97,116,32,108,101,97,115,116,32,111,110,99,101,32,97,32,109,105,110,117,116,101,44,32,115,111,32,117,110,100,101,114,32,110,111,114,109,97,108,32,111,112,101,114,97,116,105,111,110,32,116,104,105,115,32,105,115,32,116,111,32,98,101,32,100,101,116,101,99,116,101,100,32,119,105,116,104,105,110,32,97,32,109,105,110,117,116,101,44,32,98,117,116,32,100,117,114,105,110,103,32,104,101,97,118,121,32,108,111,97,100,32,105,116,32,99,97,110,32,116,97,107,101,32,108,111,110,103,101,114,32,116,105,109,101,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,32,97,102,116,101,114,32,105,116,32,104,97,115,32,98,101,101,110,32,116,114,105,103,103,101,114,101,100,46,32,84,104,97,116,32,105,115,44,32,114,101,112,101,97,116,101,100,32,99,104,97,110,103,101,115,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,116,114,105,103,103,101,114,32,116,104,101,32,109,111,110,105,116,111,114,32,114,101,112,101,97,116,101,100,108,121,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,97,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,46,32,65,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<123,39,67,72,65,78,71,69,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,84,121,112,101,44,32,73,116,101,109,44,32,78,101,119,84,105,109,101,79,102,102,115,101,116,125>>]}]},{p,[],[<<119,104,101,114,101,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<44,32>>,{code,[],[<<84,121,112,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,44,32,97,110,100,32>>,{code,[],[<<78,101,119,84,105,109,101,79,102,102,115,101,116>>]},<<32,105,115,32,116,104,101,32,110,101,119,32,116,105,109,101,32,111,102,102,115,101,116,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,32,104,97,115,32,98,101,101,110,32,114,101,99,101,105,118,101,100,32,121,111,117,32,97,114,101,32,103,117,97,114,97,110,116,101,101,100,32,110,111,116,32,116,111,32,114,101,116,114,105,101,118,101,32,116,104,101,32,111,108,100,32,116,105,109,101,32,111,102,102,115,101,116,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]}]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,121,111,117,32,99,97,110,32,111,98,115,101,114,118,101,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]},<<32,98,101,102,111,114,101,32,121,111,117,32,103,101,116,32,116,104,101,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,46>>]}]}]},{p,[],[<<77,97,107,105,110,103,32,115,101,118,101,114,97,108,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,102,111,114,32,116,104,101,32,115,97,109,101,32>>,{code,[],[<<73,116,101,109>>]},<<32,97,110,100,47,111,114,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,114,114,111,114,59,32,105,116,32,114,101,115,117,108,116,115,32,105,110,32,97,115,32,109,97,110,121,32,105,110,100,101,112,101,110,100,101,110,116,32,109,111,110,105,116,111,114,105,110,103,32,105,110,115,116,97,110,99,101,115,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,101,120,116,101,110,100,101,100,46,32,84,104,97,116,32,105,115,44,32,111,116,104,101,114,32>>,{code,[],[<<84,121,112,101>>]},<<115,32,97,110,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,115,117,112,112,111,114,116,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,111,114,32,119,104,101,110,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,105,115,32,101,120,116,101,110,100,101,100,44,32,111,116,104,101,114,32,112,111,115,115,105,98,108,101,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<84,97,103>>]},<<44,32>>,{code,[],[<<79,98,106,101,99,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,110,32,116,104,101,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,105,110,116,114,111,100,117,99,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,57,54>>,signature => [{attribute,1401,spec,{{monitor,2},[{type,1402,bounded_fun,[{type,1402,'fun',[{type,1402,product,[{atom,1402,process},{user_type,1402,monitor_process_identifier,[]}]},{var,1402,'MonitorRef'}]},[{type,1403,constraint,[{atom,1403,is_subtype},[{var,1403,'MonitorRef'},{type,1403,reference,[]}]]}]]},{type,1404,bounded_fun,[{type,1404,'fun',[{type,1404,product,[{atom,1404,port},{user_type,1404,monitor_port_identifier,[]}]},{var,1404,'MonitorRef'}]},[{type,1405,constraint,[{atom,1405,is_subtype},[{var,1405,'MonitorRef'},{type,1405,reference,[]}]]}]]},{type,1406,bounded_fun,[{type,1406,'fun',[{type,1406,product,[{atom,1406,time_offset},{atom,1406,clock_service}]},{var,1406,'MonitorRef'}]},[{type,1407,constraint,[{atom,1407,is_subtype},[{var,1407,'MonitorRef'},{type,1407,reference,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48,44,79,84,80,32,49,57,46,48>>}},{{function,monitor,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1413}],[<<109,111,110,105,116,111,114,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,111,110,105,116,111,114,95,112,111,114,116,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<109,111,110,105,116,111,114,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]}]},{p,[],[<<80,114,111,118,105,100,101,115,32,97,110,32,111,112,116,105,111,110,32,108,105,115,116,32,102,111,114,32,109,111,100,105,102,105,99,97,116,105,111,110,32,111,102,32,109,111,110,105,116,111,114,105,110,103,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,112,114,111,118,105,100,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,50>>]}]},<<46,32,84,104,101,32>>,{code,[],[<<84,121,112,101>>]},<<32,97,110,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,97,114,103,117,109,101,110,116,115,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,109,101,97,110,105,110,103,32,97,115,32,119,104,101,110,32,112,97,115,115,101,100,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<46,32,67,117,114,114,101,110,116,108,121,32,97,118,97,105,108,97,98,108,101,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,108,105,97,115,44,32,85,110,97,108,105,97,115,79,112,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,109,111,110,105,116,111,114,32,114,101,102,101,114,101,110,99,101,32,119,105,108,108,32,97,108,115,111,32,98,101,99,111,109,101,32,97,110,32,97,108,105,97,115,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,97,108,105,97,115,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,108,105,97,115,47,48>>]}]},<<46,32,84,104,101,32>>,{code,[],[<<85,110,97,108,105,97,115,79,112,116>>]},<<32,100,101,116,101,114,109,105,110,101,115,32,104,111,119,32,116,104,101,32,97,108,105,97,115,32,115,104,111,117,108,100,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,46>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,112,108,105,99,105,116,95,117,110,97,108,105,97,115>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,97,110,32,101,120,112,108,105,99,105,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,97,108,105,97,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,97,108,105,97,115,47,49>>]}]},<<32,119,105,108,108,32,100,101,97,99,116,105,118,97,116,101,32,116,104,101,32,97,108,105,97,115,46>>]}]},{dt,[],[{code,[],[<<100,101,109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,114,101,109,111,118,101,100,46,32,84,104,105,115,32,101,105,116,104,101,114,32,118,105,97,32,97,110,32,101,120,112,108,105,99,105,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,47,49>>]}]},<<32,111,114,32,119,104,101,110,32,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,32,97,115,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,100,101,108,105,118,101,114,101,100,32,100,117,101,32,116,111,32,116,104,101,32,109,111,110,105,116,111,114,46,32,84,104,101,32,97,108,105,97,115,32,99,97,110,32,97,108,115,111,32,115,116,105,108,108,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46>>]}]},{dt,[],[{code,[],[<<114,101,112,108,121,95,100,101,109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,114,101,109,111,118,101,100,32,40,115,101,101,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114>>]},<<32,111,112,116,105,111,110,32,97,98,111,118,101,41,32,111,114,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,115,101,110,116,32,118,105,97,32,116,104,101,32,97,108,105,97,115,32,105,115,32,114,101,99,101,105,118,101,100,46,32,87,104,101,110,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,105,115,32,114,101,99,101,105,118,101,100,32,118,105,97,32,116,104,101,32,97,108,105,97,115,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,97,108,115,111,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,46,32,84,104,105,115,32,105,115,32,117,115,101,102,117,108,32,105,110,32,99,108,105,101,110,116,47,115,101,114,118,101,114,32,115,99,101,110,97,114,105,111,115,32,119,104,101,110,32,97,32,99,108,105,101,110,116,32,109,111,110,105,116,111,114,115,32,116,104,101,32,115,101,114,118,101,114,32,97,110,100,32,119,105,108,108,32,103,101,116,32,116,104,101,32,114,101,112,108,121,32,118,105,97,32,116,104,101,32,97,108,105,97,115,46,32,79,110,99,101,32,116,104,101,32,114,101,115,112,111,110,115,101,32,105,115,32,114,101,99,101,105,118,101,100,32,98,111,116,104,32,116,104,101,32,97,108,105,97,115,32,97,110,100,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,114,101,115,112,111,110,115,101,32,105,115,32,97,32,114,101,112,108,121,32,111,114,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,46,32,84,104,101,32,97,108,105,97,115,32,99,97,110,32,97,108,115,111,32,115,116,105,108,108,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46,32,78,111,116,101,32,116,104,97,116,32,105,102,32,116,104,101,32,97,108,105,97,115,32,105,115,32,114,101,109,111,118,101,100,32,117,115,105,110,103,32,116,104,101,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<32,66,73,70,44,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,115,116,105,108,108,32,98,101,32,108,101,102,116,32,97,99,116,105,118,101,46>>]}]}]}]},{dt,[],[{code,[],[<<123,116,97,103,44,32,85,115,101,114,68,101,102,105,110,101,100,84,97,103,125>>]}]},{dd,[],[{p,[],[<<82,101,112,108,97,99,101,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<84,97,103>>]},<<32,119,105,116,104,32>>,{code,[],[<<85,115,101,114,68,101,102,105,110,101,100,84,97,103>>]},<<32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,111,110,105,116,111,114,32,109,101,115,115,97,103,101>>]},<<32,100,101,108,105,118,101,114,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32,109,111,110,105,116,111,114,105,110,103,32,97,32,112,114,111,99,101,115,115,44,32,116,104,101,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,116,97,103,32,105,110,32,116,104,101,32,100,111,119,110,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,114,101,112,108,97,99,101,100,32,98,121,32>>,{code,[],[<<85,115,101,114,68,101,102,105,110,101,100,84,97,103>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,48,55,50>>,signature => [{attribute,1413,spec,{{monitor,3},[{type,1414,bounded_fun,[{type,1414,'fun',[{type,1414,product,[{atom,1414,process},{user_type,1414,monitor_process_identifier,[]},{type,1414,list,[{user_type,1414,monitor_option,[]}]}]},{var,1414,'MonitorRef'}]},[{type,1415,constraint,[{atom,1415,is_subtype},[{var,1415,'MonitorRef'},{type,1415,reference,[]}]]}]]},{type,1416,bounded_fun,[{type,1416,'fun',[{type,1416,product,[{atom,1416,port},{user_type,1416,monitor_port_identifier,[]},{type,1416,list,[{user_type,1416,monitor_option,[]}]}]},{var,1416,'MonitorRef'}]},[{type,1417,constraint,[{atom,1417,is_subtype},[{var,1417,'MonitorRef'},{type,1417,reference,[]}]]}]]},{type,1418,bounded_fun,[{type,1418,'fun',[{type,1418,product,[{atom,1418,time_offset},{atom,1418,clock_service},{type,1418,list,[{user_type,1418,monitor_option,[]}]}]},{var,1418,'MonitorRef'}]},[{type,1419,constraint,[{atom,1419,is_subtype},[{var,1419,'MonitorRef'},{type,1419,reference,[]}]]}]]}]}}],since => <<79,84,80,32,64,79,84,80,45,49,54,55,49,56,64>>}},{{function,monitor_node,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1425}],[<<109,111,110,105,116,111,114,95,110,111,100,101,47,50>>],#{<<101,110>> => [{p,[],[<<77,111,110,105,116,111,114,32,116,104,101,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,108,97,103>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,110,46,32,73,102,32>>,{code,[],[<<70,108,97,103>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,102,102,46>>]},{p,[],[<<77,97,107,105,110,103,32,115,101,118,101,114,97,108,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,95,110,111,100,101,40,78,111,100,101,44,32,116,114,117,101,41>>]},<<32,102,111,114,32,116,104,101,32,115,97,109,101,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,114,114,111,114,59,32,105,116,32,114,101,115,117,108,116,115,32,105,110,32,97,115,32,109,97,110,121,32,105,110,100,101,112,101,110,100,101,110,116,32,109,111,110,105,116,111,114,105,110,103,32,105,110,115,116,97,110,99,101,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,102,97,105,108,115,32,111,114,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,110,111,100,101,100,111,119,110,44,32,78,111,100,101,125>>]},<<32,105,115,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,46,32,73,102,32,97,32,112,114,111,99,101,115,115,32,104,97,115,32,109,97,100,101,32,116,119,111,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,95,110,111,100,101,40,78,111,100,101,44,32,116,114,117,101,41>>]},<<32,97,110,100,32>>,{code,[],[<<78,111,100,101>>]},<<32,116,101,114,109,105,110,97,116,101,115,44,32,116,119,111,32>>,{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,109,101,115,115,97,103,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,101,114,101,32,105,115,32,110,111,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32>>,{code,[],[<<78,111,100,101>>]},<<44,32,97,110,32,97,116,116,101,109,112,116,32,105,115,32,109,97,100,101,32,116,111,32,99,114,101,97,116,101,32,111,110,101,46,32,73,102,32,116,104,105,115,32,102,97,105,108,115,44,32,97,32>>,{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,100,101,108,105,118,101,114,101,100,46>>]},{p,[],[<<78,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,104,114,111,117,103,104,32,104,105,100,100,101,110,32,99,111,110,110,101,99,116,105,111,110,115,32,99,97,110,32,98,101,32,109,111,110,105,116,111,114,101,100,32,97,115,32,97,110,121,32,111,116,104,101,114,32,110,111,100,101,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<110,111,116,97,108,105,118,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,53,52>>,signature => [{attribute,1425,spec,{{monitor_node,2},[{type,1425,bounded_fun,[{type,1425,'fun',[{type,1425,product,[{var,1425,'Node'},{var,1425,'Flag'}]},{atom,1425,true}]},[{type,1426,constraint,[{atom,1426,is_subtype},[{var,1426,'Node'},{type,1426,node,[]}]]},{type,1427,constraint,[{atom,1427,is_subtype},[{var,1427,'Flag'},{type,1427,boolean,[]}]]}]]}]}}]}},{{function,monitor_node,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1432}],[<<109,111,110,105,116,111,114,95,110,111,100,101,47,51>>],#{<<101,110>> => [{p,[],[<<66,101,104,97,118,101,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,95,110,111,100,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,95,110,111,100,101,47,50>>]}]},<<32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,97,108,108,111,119,115,32,97,110,32,101,120,116,114,97,32,111,112,116,105,111,110,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,44,32,110,97,109,101,108,121,32>>,{code,[],[<<97,108,108,111,119,95,112,97,115,115,105,118,101,95,99,111,110,110,101,99,116>>]},<<46,32,84,104,105,115,32,111,112,116,105,111,110,32,97,108,108,111,119,115,32,116,104,101,32,66,73,70,32,116,111,32,119,97,105,116,32,116,104,101,32,110,111,114,109,97,108,32,110,101,116,119,111,114,107,32,99,111,110,110,101,99,116,105,111,110,32,116,105,109,101,45,111,117,116,32,102,111,114,32,116,104,101,32>>,{em,[],[<<109,111,110,105,116,111,114,101,100,32,110,111,100,101>>]},<<32,116,111,32,99,111,110,110,101,99,116,32,105,116,115,101,108,102,44,32,101,118,101,110,32,105,102,32,105,116,32,99,97,110,110,111,116,32,98,101,32,97,99,116,105,118,101,108,121,32,99,111,110,110,101,99,116,101,100,32,102,114,111,109,32,116,104,105,115,32,110,111,100,101,32,40,116,104,97,116,32,105,115,44,32,105,116,32,105,115,32,98,108,111,99,107,101,100,41,46,32,84,104,101,32,115,116,97,116,101,32,119,104,101,114,101,32,116,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,99,97,110,32,111,110,108,121,32,98,101,32,97,99,104,105,101,118,101,100,32,98,121,32,117,115,105,110,103,32,116,104,101,32,75,101,114,110,101,108,32,111,112,116,105,111,110,32>>,{code,[],[<<100,105,115,116,95,97,117,116,111,95,99,111,110,110,101,99,116,32,111,110,99,101>>]},<<46,32,73,102,32,116,104,97,116,32,111,112,116,105,111,110,32,105,115,32,110,111,116,32,117,115,101,100,44,32,111,112,116,105,111,110,32>>,{code,[],[<<97,108,108,111,119,95,112,97,115,115,105,118,101,95,99,111,110,110,101,99,116>>]},<<32,104,97,115,32,110,111,32,101,102,102,101,99,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<97,108,108,111,119,95,112,97,115,115,105,118,101,95,99,111,110,110,101,99,116>>]},<<32,105,115,32,117,115,101,100,32,105,110,116,101,114,110,97,108,108,121,32,97,110,100,32,105,115,32,115,101,108,100,111,109,32,110,101,101,100,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,115,32,119,104,101,114,101,32,116,104,101,32,110,101,116,119,111,114,107,32,116,111,112,111,108,111,103,121,32,97,110,100,32,116,104,101,32,75,101,114,110,101,108,32,111,112,116,105,111,110,115,32,105,110,32,101,102,102,101,99,116,32,97,114,101,32,107,110,111,119,110,32,105,110,32,97,100,118,97,110,99,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,32,111,114,32,116,104,101,32,111,112,116,105,111,110,32,108,105,115,116,32,105,115,32,109,97,108,102,111,114,109,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,55,56>>,signature => [{attribute,1432,spec,{{erlang,monitor_node,3},[{type,1432,bounded_fun,[{type,1432,'fun',[{type,1432,product,[{var,1432,'Node'},{var,1432,'Flag'},{var,1432,'Options'}]},{atom,1432,true}]},[{type,1433,constraint,[{atom,1433,is_subtype},[{var,1433,'Node'},{type,1433,node,[]}]]},{type,1434,constraint,[{atom,1434,is_subtype},[{var,1434,'Flag'},{type,1434,boolean,[]}]]},{type,1435,constraint,[{atom,1435,is_subtype},[{var,1435,'Options'},{type,1435,list,[{var,1435,'Option'}]}]]},{type,1436,constraint,[{atom,1436,is_subtype},[{var,1436,'Option'},{atom,1436,allow_passive_connect}]]}]]}]}}]}},{{function,monotonic_time,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1534}],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46,32,84,104,105,115,32,105,115,32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,115,105,110,99,101,32,115,111,109,101,32,117,110,115,112,101,99,105,102,105,101,100,32,112,111,105,110,116,32,105,110,32,116,105,109,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,105,115,32,97,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,111,110,111,116,111,110,105,99,97,108,108,121,95,73,110,99,114,101,97,115,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103>>]},<<32,116,105,109,101,44,32,98,117,116,32>>,{em,[],[<<110,111,116>>]},<<32,97,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,116,114,105,99,116,108,121,95,77,111,110,111,116,111,110,105,99,97,108,108,121,95,73,110,99,114,101,97,115,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103>>]},<<32,116,105,109,101,46,32,84,104,97,116,32,105,115,44,32,99,111,110,115,101,99,117,116,105,118,101,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>]},<<32,99,97,110,32,112,114,111,100,117,99,101,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,46>>]},{p,[],[<<68,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,115,32,119,105,108,108,32,117,115,101,32,100,105,102,102,101,114,101,110,116,32,117,110,115,112,101,99,105,102,105,101,100,32,112,111,105,110,116,115,32,105,110,32,116,105,109,101,32,97,115,32,98,97,115,101,32,102,111,114,32,116,104,101,105,114,32,69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,99,108,111,99,107,115,46,32,84,104,97,116,32,105,115,44,32,105,116,32,105,115,32>>,{em,[],[<<112,111,105,110,116,108,101,115,115>>]},<<32,99,111,109,112,97,114,105,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,115,32,102,114,111,109,32,100,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,115,46,32,68,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,115,32,99,97,110,32,97,108,115,111,32,112,108,97,99,101,32,116,104,105,115,32,117,110,115,112,101,99,105,102,105,101,100,32,112,111,105,110,116,32,105,110,32,116,105,109,101,32,100,105,102,102,101,114,101,110,116,32,114,101,108,97,116,105,118,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,46,32,73,116,32,99,97,110,32,98,101,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,32,40,116,105,109,101,32,97,116,32,115,116,97,114,116,32,105,115,32,97,32,110,101,103,97,116,105,118,101,32,118,97,108,117,101,41,44,32,116,104,101,32,112,97,115,116,32,40,116,105,109,101,32,97,116,32,115,116,97,114,116,32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,118,97,108,117,101,41,44,32,111,114,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,32,40,116,105,109,101,32,97,116,32,115,116,97,114,116,32,105,115,32,122,101,114,111,41,46,32,84,104,101,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,97,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,116,97,114,116,95,116,105,109,101,41>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,48,52>>,signature => [{attribute,1534,spec,{{erlang,monotonic_time,0},[{type,1534,'fun',[{type,1534,product,[]},{type,1534,integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,monotonic_time,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1539}],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,99,111,110,118,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32>>,{code,[],[<<85,110,105,116>>]},<<32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{p,[],[<<83,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]}]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<32>>,{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,41>>]}]},{code,[],[<<44,32,110,97,116,105,118,101,44,32,85,110,105,116,41>>]},<<44,32,104,111,119,101,118,101,114,32,111,112,116,105,109,105,122,101,100,32,102,111,114,32,99,111,109,109,111,110,108,121,32,117,115,101,100,32>>,{code,[],[<<85,110,105,116>>]},<<115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,51,56>>,signature => [{attribute,1539,spec,{{erlang,monotonic_time,1},[{type,1539,bounded_fun,[{type,1539,'fun',[{type,1539,product,[{var,1539,'Unit'}]},{type,1539,integer,[]}]},[{type,1540,constraint,[{atom,1540,is_subtype},[{var,1540,'Unit'},{user_type,1540,time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,nif_error,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1442}],[<<110,105,102,95,101,114,114,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<87,111,114,107,115,32,101,120,97,99,116,108,121,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,47,49>>]}]},<<44,32,98,117,116,32,68,105,97,108,121,122,101,114,32,116,104,105,110,107,115,32,116,104,97,116,32,116,104,105,115,32,66,73,70,32,119,105,108,108,32,114,101,116,117,114,110,32,97,110,32,97,114,98,105,116,114,97,114,121,32,116,101,114,109,46,32,87,104,101,110,32,117,115,101,100,32,105,110,32,97,32,115,116,117,98,32,102,117,110,99,116,105,111,110,32,102,111,114,32,97,32,78,73,70,32,116,111,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,32,119,104,101,110,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,32,105,115,32,110,111,116,32,108,111,97,100,101,100,44,32,68,105,97,108,121,122,101,114,32,100,111,101,115,32,110,111,116,32,103,101,110,101,114,97,116,101,32,102,97,108,115,101,32,119,97,114,110,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,53,54>>,signature => [{attribute,1442,spec,{{erlang,nif_error,1},[{type,1442,bounded_fun,[{type,1442,'fun',[{type,1442,product,[{var,1442,'Reason'}]},{type,1442,no_return,[]}]},[{type,1443,constraint,[{atom,1443,is_subtype},[{var,1443,'Reason'},{type,1443,term,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,nif_error,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1449}],[<<110,105,102,95,101,114,114,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<87,111,114,107,115,32,101,120,97,99,116,108,121,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,47,50>>]}]},<<44,32,98,117,116,32,68,105,97,108,121,122,101,114,32,116,104,105,110,107,115,32,116,104,97,116,32,116,104,105,115,32,66,73,70,32,119,105,108,108,32,114,101,116,117,114,110,32,97,110,32,97,114,98,105,116,114,97,114,121,32,116,101,114,109,46,32,87,104,101,110,32,117,115,101,100,32,105,110,32,97,32,115,116,117,98,32,102,117,110,99,116,105,111,110,32,102,111,114,32,97,32,78,73,70,32,116,111,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,32,119,104,101,110,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,32,105,115,32,110,111,116,32,108,111,97,100,101,100,44,32,68,105,97,108,121,122,101,114,32,100,111,101,115,32,110,111,116,32,103,101,110,101,114,97,116,101,32,102,97,108,115,101,32,119,97,114,110,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,54,57>>,signature => [{attribute,1449,spec,{{erlang,nif_error,2},[{type,1449,bounded_fun,[{type,1449,'fun',[{type,1449,product,[{var,1449,'Reason'},{var,1449,'Args'}]},{type,1449,no_return,[]}]},[{type,1450,constraint,[{atom,1450,is_subtype},[{var,1450,'Reason'},{type,1450,term,[]}]]},{type,1451,constraint,[{atom,1451,is_subtype},[{var,1451,'Args'},{type,1451,list,[{type,1451,term,[]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,node,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1457}],[<<110,111,100,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,73,102,32,116,104,101,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<110,111,110,111,100,101,64,110,111,104,111,115,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,56,50>>,signature => [{attribute,1457,spec,{{node,0},[{type,1457,bounded_fun,[{type,1457,'fun',[{type,1457,product,[]},{var,1457,'Node'}]},[{type,1458,constraint,[{atom,1458,is_subtype},[{var,1458,'Node'},{type,1458,node,[]}]]}]]}]}}]}},{{function,node,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1464}],[<<110,111,100,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,111,100,101,32,119,104,101,114,101,32>>,{code,[],[<<65,114,103>>]},<<32,111,114,105,103,105,110,97,116,101,115,46,32>>,{code,[],[<<65,114,103>>]},<<32,99,97,110,32,98,101,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,97,32,114,101,102,101,114,101,110,99,101,44,32,111,114,32,97,32,112,111,114,116,46,32,73,102,32>>,{code,[],[<<65,114,103>>]},<<32,111,114,105,103,105,110,97,116,101,115,32,102,114,111,109,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,110,100,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<110,111,110,111,100,101,64,110,111,104,111,115,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,57,50>>,signature => [{attribute,1464,spec,{{node,1},[{type,1464,bounded_fun,[{type,1464,'fun',[{type,1464,product,[{var,1464,'Arg'}]},{var,1464,'Node'}]},[{type,1465,constraint,[{atom,1465,is_subtype},[{var,1465,'Arg'},{type,1465,union,[{type,1465,pid,[]},{type,1465,port,[]},{type,1465,reference,[]}]}]]},{type,1466,constraint,[{atom,1466,is_subtype},[{var,1466,'Node'},{type,1466,node,[]}]]}]]}]}}]}},{{function,nodes,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3424}],[<<110,111,100,101,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,108,108,32,110,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,32,116,104,114,111,117,103,104,32,110,111,114,109,97,108,32,99,111,110,110,101,99,116,105,111,110,115,32,40,116,104,97,116,32,105,115,44,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,105,115,116,114,105,98,117,116,101,100,35,104,105,100,100,101,110,45,110,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<104,105,100,100,101,110,32,110,111,100,101,115>>]},<<32,97,114,101,32,110,111,116,32,108,105,115,116,101,100,41,46,32,83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,110,111,100,101,115,95,118,105,115,105,98,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,111,100,101,115,40,118,105,115,105,98,108,101,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,48,53>>,signature => [{attribute,3424,spec,{{nodes,0},[{type,3424,bounded_fun,[{type,3424,'fun',[{type,3424,product,[]},{var,3424,'Nodes'}]},[{type,3425,constraint,[{atom,3425,is_subtype},[{var,3425,'Nodes'},{type,3425,list,[{type,3425,node,[]}]}]]}]]}]}}]}},{{function,nodes,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2308}],[<<110,111,100,101,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,110,111,100,101,115,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102,105,101,100,46,32,84,104,101,32,114,101,116,117,114,110,101,100,32,114,101,115,117,108,116,44,32,119,104,101,110,32,116,104,101,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,108,105,115,116,44,32,105,115,32,116,104,101,32,108,105,115,116,32,111,102,32,110,111,100,101,115,32,115,97,116,105,115,102,121,105,110,103,32,116,104,101,32,100,105,115,106,117,110,99,116,105,111,110,40,115,41,32,111,102,32,116,104,101,32,108,105,115,116,32,101,108,101,109,101,110,116,115,46>>]},{p,[],[{code,[],[<<78,111,100,101,84,121,112,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{a,[{id,<<110,111,100,101,115,95,118,105,115,105,98,108,101>>}],[]},{code,[],[<<118,105,115,105,98,108,101>>]}]},{dd,[],[{p,[],[<<78,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,32,116,104,114,111,117,103,104,32,110,111,114,109,97,108,32,99,111,110,110,101,99,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<104,105,100,100,101,110>>]}]},{dd,[],[{p,[],[<<78,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,32,116,104,114,111,117,103,104,32,104,105,100,100,101,110,32,99,111,110,110,101,99,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<99,111,110,110,101,99,116,101,100>>]}]},{dd,[],[{p,[],[<<65,108,108,32,110,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,46>>]}]},{dt,[],[{code,[],[<<116,104,105,115>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,110,111,100,101,46>>]}]},{dt,[],[{code,[],[<<107,110,111,119,110>>]}]},{dd,[],[{p,[],[<<78,111,100,101,115,32,116,104,97,116,32,97,114,101,32,107,110,111,119,110,32,116,111,32,116,104,105,115,32,110,111,100,101,46,32,84,104,97,116,32,105,115,44,32,99,111,110,110,101,99,116,101,100,32,110,111,100,101,115,32,97,110,100,32,110,111,100,101,115,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,44,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,44,32,97,110,100,32,114,101,102,101,114,101,110,99,101,115,32,108,111,99,97,116,101,100,32,111,110,32,116,104,105,115,32,110,111,100,101,46,32,84,104,101,32,115,101,116,32,111,102,32,107,110,111,119,110,32,110,111,100,101,115,32,105,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,99,97,110,32,98,101,32,100,101,108,97,121,101,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99,41>>]}]},<<46>>]}]}]},{p,[],[<<83,111,109,101,32,101,113,117,97,108,105,116,105,101,115,58,32>>,{code,[],[<<91,110,111,100,101,40,41,93,32,61,32,110,111,100,101,115,40,116,104,105,115,41>>]},<<44,32>>,{code,[],[<<110,111,100,101,115,40,99,111,110,110,101,99,116,101,100,41,32,61,32,110,111,100,101,115,40,91,118,105,115,105,98,108,101,44,32,104,105,100,100,101,110,93,41>>]},<<44,32,97,110,100,32>>,{code,[],[<<110,111,100,101,115,40,41,32,61,32,110,111,100,101,115,40,118,105,115,105,98,108,101,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,49,55>>,signature => [{attribute,2308,spec,{{nodes,1},[{type,2308,bounded_fun,[{type,2308,'fun',[{type,2308,product,[{var,2308,'Arg'}]},{var,2308,'Nodes'}]},[{type,2309,constraint,[{atom,2309,is_subtype},[{var,2309,'Arg'},{type,2309,union,[{var,2309,'NodeType'},{type,2309,list,[{var,2309,'NodeType'}]}]}]]},{type,2310,constraint,[{atom,2310,is_subtype},[{var,2310,'NodeType'},{type,2310,union,[{atom,2310,visible},{atom,2310,hidden},{atom,2310,connected},{atom,2310,this},{atom,2310,known}]}]]},{type,2311,constraint,[{atom,2311,is_subtype},[{var,2311,'Nodes'},{type,2311,list,[{type,2311,node,[]}]}]]}]]}]}}]}},{{function,now,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1471}],[<<110,111,119,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<116,105,109,101,115,116,97,109,112>>}],[]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[{em,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,68,111,32,110,111,116,32,117,115,101,32,105,116,46>>]}]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<84,105,109,101,32,97,110,100,32,84,105,109,101,32,67,111,114,114,101,99,116,105,111,110>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46,32,83,112,101,99,105,102,105,99,97,108,108,121,44,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,68,111,115,95,97,110,100,95,68,111,110,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<68,111,115,32,97,110,100,32,68,111,110,116,39,115>>]},<<32,100,101,115,99,114,105,98,101,115,32,119,104,97,116,32,116,111,32,117,115,101,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,47,48>>]},<<46>>]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,77,101,103,97,83,101,99,115,44,32,83,101,99,115,44,32,77,105,99,114,111,83,101,99,115,125>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,101,108,97,112,115,101,100,32,116,105,109,101,32,115,105,110,99,101,32,48,48,58,48,48,32,71,77,84,44,32,74,97,110,117,97,114,121,32,49,44,32,49,57,55,48,32,40,122,101,114,111,32,104,111,117,114,41,44,32,105,102,32,112,114,111,118,105,100,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32,115,111,109,101,32,111,116,104,101,114,32,112,111,105,110,116,32,105,110,32,116,105,109,101,32,105,115,32,99,104,111,115,101,110,46,32,73,116,32,105,115,32,97,108,115,111,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,115,32,116,111,32,116,104,105,115,32,66,73,70,32,114,101,116,117,114,110,32,99,111,110,116,105,110,117,111,117,115,108,121,32,105,110,99,114,101,97,115,105,110,103,32,118,97,108,117,101,115,46,32,72,101,110,99,101,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,102,114,111,109,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,47,48>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,103,101,110,101,114,97,116,101,32,117,110,105,113,117,101,32,116,105,109,101,32,115,116,97,109,112,115,46,32,73,102,32,105,116,32,105,115,32,99,97,108,108,101,100,32,105,110,32,97,32,116,105,103,104,116,32,108,111,111,112,32,111,110,32,97,32,102,97,115,116,32,109,97,99,104,105,110,101,44,32,116,104,101,32,116,105,109,101,32,111,102,32,116,104,101,32,110,111,100,101,32,99,97,110,32,98,101,99,111,109,101,32,115,107,101,119,101,100,46>>]},{p,[],[<<67,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,116,111,32,99,104,101,99,107,32,116,104,101,32,108,111,99,97,108,32,116,105,109,101,32,111,102,32,100,97,121,32,105,102,32,116,104,101,32,116,105,109,101,45,122,111,110,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,102,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,32,105,115,32,112,114,111,112,101,114,108,121,32,99,111,110,102,105,103,117,114,101,100,46>>]}]},#{deprecated => <<101,114,108,97,110,103,58,110,111,119,47,48,32,105,115,32,100,101,112,114,101,99,97,116,101,100,59,32,115,101,101,32,116,104,101,32,34,84,105,109,101,32,97,110,100,32,84,105,109,101,32,67,111,114,114,101,99,116,105,111,110,32,105,110,32,69,114,108,97,110,103,34,32,99,104,97,112,116,101,114,32,111,102,32,116,104,101,32,69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110>>,edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,54,48>>,signature => [{attribute,1471,spec,{{now,0},[{type,1471,bounded_fun,[{type,1471,'fun',[{type,1471,product,[]},{var,1471,'Timestamp'}]},[{type,1472,constraint,[{atom,1472,is_subtype},[{var,1472,'Timestamp'},{user_type,1472,timestamp,[]}]]}]]}]}}]}},{{function,open_port,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2315}],[<<111,112,101,110,95,112,111,114,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,111,112,101,110,105,110,103,32,97,32,110,101,119,32,69,114,108,97,110,103,32,112,111,114,116,46,32,65,32,112,111,114,116,32,99,97,110,32,98,101,32,115,101,101,110,32,97,115,32,97,110,32,101,120,116,101,114,110,97,108,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<84,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,115,112,101,99,105,102,101,100,32,105,110,32>>,{code,[],[<<99,100>>]},<<44,32>>,{code,[],[<<101,110,118>>]},<<44,32>>,{code,[],[<<97,114,103,115>>]},<<44,32,97,110,100,32>>,{code,[],[<<97,114,103,48>>]},<<32,97,114,101,32,115,117,98,106,101,99,116,32,116,111,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,116,114,97,110,115,108,97,116,105,111,110,32,105,102,32,116,104,101,32,115,121,115,116,101,109,32,105,115,32,114,117,110,110,105,110,103,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,46,32,84,111,32,97,118,111,105,100,32,116,114,97,110,115,108,97,116,105,111,110,32,111,114,32,116,111,32,102,111,114,99,101,44,32,102,111,114,32,101,120,97,109,112,108,101,32,85,84,70,45,56,44,32,115,117,112,112,108,121,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,97,110,100,47,111,114,32,97,114,103,117,109,101,110,116,115,32,97,115,32,97,32,98,105,110,97,114,121,32,105,110,32,116,104,101,32,99,111,114,114,101,99,116,32,101,110,99,111,100,105,110,103,46,32,70,111,114,32,100,101,116,97,105,108,115,44,32,115,101,101,32,116,104,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,102,105,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,105,108,101,40,51,41>>]}]},<<44,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,105,108,101,58,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>]}]},<<32,105,110,32,75,101,114,110,101,108,44,32,97,110,100,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,100,108,105,98,58,117,110,105,99,111,100,101,95,117,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<85,115,105,110,103,32,85,110,105,99,111,100,101,32,105,110,32,69,114,108,97,110,103>>]}]},<<32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,110,97,109,101,32,40,105,102,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,108,105,115,116,41,32,99,97,110,32,111,110,108,121,32,98,101,32,62,32,50,53,53,32,105,102,32,116,104,101,32,69,114,108,97,110,103,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,105,115,32,115,116,97,114,116,101,100,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,116,114,97,110,115,108,97,116,105,111,110,32,109,111,100,101,46,32,79,116,104,101,114,119,105,115,101,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,105,115,32,108,105,109,105,116,101,100,32,116,111,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,46>>]}]},{p,[],[{code,[],[<<80,111,114,116,78,97,109,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,115,32,97,110,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,32,116,111,32,98,101,32,114,117,110,46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,114,117,110,115,32,111,117,116,115,105,100,101,32,116,104,101,32,69,114,108,97,110,103,32,119,111,114,107,32,115,112,97,99,101,32,117,110,108,101,115,115,32,97,110,32,69,114,108,97,110,103,32,100,114,105,118,101,114,32,119,105,116,104,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32,102,111,117,110,100,44,32,116,104,97,116,32,100,114,105,118,101,114,32,105,115,32,115,116,97,114,116,101,100,46,32,65,32,100,114,105,118,101,114,32,114,117,110,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,119,111,114,107,32,115,112,97,99,101,44,32,119,104,105,99,104,32,109,101,97,110,115,32,116,104,97,116,32,105,116,32,105,115,32,108,105,110,107,101,100,32,119,105,116,104,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<70,111,114,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,115,44,32>>,{code,[],[<<80,65,84,72>>]},<<32,105,115,32,115,101,97,114,99,104,101,100,32,40,111,114,32,97,110,32,101,113,117,105,118,97,108,101,110,116,32,109,101,116,104,111,100,32,105,115,32,117,115,101,100,32,116,111,32,102,105,110,100,32,112,114,111,103,114,97,109,115,44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,79,83,41,46,32,84,104,105,115,32,105,115,32,100,111,110,101,32,98,121,32,105,110,118,111,107,105,110,103,32,116,104,101,32,115,104,101,108,108,32,111,110,32,99,101,114,116,97,105,110,32,112,108,97,116,102,111,114,109,115,46,32,84,104,101,32,102,105,114,115,116,32,115,112,97,99,101,45,115,101,112,97,114,97,116,101,100,32,116,111,107,101,110,32,111,102,32,116,104,101,32,99,111,109,109,97,110,100,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,40,111,114,32,100,114,105,118,101,114,41,46,32,84,104,105,115,32,40,97,109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,41,32,109,97,107,101,115,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,115,117,105,116,97,98,108,101,32,102,111,114,32,114,117,110,110,105,110,103,32,112,114,111,103,114,97,109,115,32,119,105,116,104,32,115,112,97,99,101,115,32,105,110,32,102,105,108,101,110,97,109,101,115,32,111,114,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,46,32,73,102,32,115,112,97,99,101,115,32,105,110,32,101,120,101,99,117,116,97,98,108,101,32,102,105,108,101,110,97,109,101,115,32,97,114,101,32,100,101,115,105,114,101,100,44,32,117,115,101,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,67,111,109,109,97,110,100,125>>]},<<32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,115,112,97,119,110,95,100,114,105,118,101,114,44,32,67,111,109,109,97,110,100,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<44,32,98,117,116,32,100,101,109,97,110,100,115,32,116,104,101,32,102,105,114,115,116,32,40,115,112,97,99,101,45,115,101,112,97,114,97,116,101,100,41,32,116,111,107,101,110,32,111,102,32,116,104,101,32,99,111,109,109,97,110,100,32,116,111,32,98,101,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,108,111,97,100,101,100,32,100,114,105,118,101,114,46,32,73,102,32,110,111,32,100,114,105,118,101,114,32,119,105,116,104,32,116,104,97,116,32,110,97,109,101,32,105,115,32,108,111,97,100,101,100,44,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,114,114,111,114,32,105,115,32,114,97,105,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<123,115,112,97,119,110,44,32,70,105,108,101,78,97,109,101,125>>]},<<44,32,98,117,116,32,111,110,108,121,32,114,117,110,115,32,101,120,116,101,114,110,97,108,32,101,120,101,99,117,116,97,98,108,101,115,46,32>>,{code,[],[<<70,105,108,101,78,97,109,101>>]},<<32,105,110,32,105,116,115,32,119,104,111,108,101,32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,44,32,105,110,99,108,117,100,105,110,103,32,97,110,121,32,115,112,97,99,101,115,46,32,73,102,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,116,111,32,98,101,32,112,97,115,115,101,100,44,32,116,104,101,32>>,{code,[],[<<80,111,114,116,83,101,116,116,105,110,103,115>>]},<<32>>,{code,[],[<<97,114,103,115>>]},<<32,97,110,100,32>>,{code,[],[<<97,114,103,48>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,115,104,101,108,108,32,105,115,32,117,115,117,97,108,108,121,32,110,111,116,32,105,110,118,111,107,101,100,32,116,111,32,115,116,97,114,116,32,116,104,101,32,112,114,111,103,114,97,109,44,32,105,116,32,105,115,32,101,120,101,99,117,116,101,100,32,100,105,114,101,99,116,108,121,46,32>>,{code,[],[<<80,65,84,72>>]},<<32,40,111,114,32,101,113,117,105,118,97,108,101,110,116,41,32,105,115,32,110,111,116,32,115,101,97,114,99,104,101,100,46,32,84,111,32,102,105,110,100,32,97,32,112,114,111,103,114,97,109,32,105,110,32>>,{code,[],[<<80,65,84,72>>]},<<32,116,111,32,101,120,101,99,117,116,101,44,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,102,105,110,100,95,101,120,101,99,117,116,97,98,108,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,102,105,110,100,95,101,120,101,99,117,116,97,98,108,101,47,49>>]}]},<<46>>]},{p,[],[<<79,110,108,121,32,105,102,32,97,32,115,104,101,108,108,32,115,99,114,105,112,116,32,111,114,32>>,{code,[],[<<46,98,97,116>>]},<<32,102,105,108,101,32,105,115,32,101,120,101,99,117,116,101,100,44,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,99,111,109,109,97,110,100,32,105,110,116,101,114,112,114,101,116,101,114,32,105,115,32,105,110,118,111,107,101,100,32,105,109,112,108,105,99,105,116,108,121,44,32,98,117,116,32,116,104,101,114,101,32,105,115,32,115,116,105,108,108,32,110,111,32,99,111,109,109,97,110,100,45,97,114,103,117,109,101,110,116,32,101,120,112,97,110,115,105,111,110,32,111,114,32,105,109,112,108,105,99,105,116,32>>,{code,[],[<<80,65,84,72>>]},<<32,115,101,97,114,99,104,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,105,108,101,78,97,109,101>>]},<<32,99,97,110,110,111,116,32,98,101,32,114,117,110,44,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,105,115,32,114,97,105,115,101,100,44,32,119,105,116,104,32,116,104,101,32,80,79,83,73,88,32,101,114,114,111,114,32,99,111,100,101,32,97,115,32,116,104,101,32,114,101,97,115,111,110,46,32,84,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,79,83,115,46,32,84,121,112,105,99,97,108,108,121,32,116,104,101,32,101,114,114,111,114,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,97,105,115,101,100,32,119,104,101,110,32,97,110,32,97,116,116,101,109,112,116,32,105,115,32,109,97,100,101,32,116,111,32,114,117,110,32,97,32,112,114,111,103,114,97,109,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,117,110,100,32,97,110,100,32>>,{code,[],[<<101,97,99,99,101,115>>]},<<32,105,115,32,114,97,105,115,101,100,32,119,104,101,110,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,105,108,101,32,105,115,32,110,111,116,32,101,120,101,99,117,116,97,98,108,101,46>>]}]},{dt,[],[{code,[],[<<123,102,100,44,32,73,110,44,32,79,117,116,125>>]}]},{dd,[],[{p,[],[<<65,108,108,111,119,115,32,97,110,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,116,111,32,97,99,99,101,115,115,32,97,110,121,32,99,117,114,114,101,110,116,108,121,32,111,112,101,110,101,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,117,115,101,100,32,98,121,32,69,114,108,97,110,103,46,32,84,104,101,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32>>,{code,[],[<<73,110>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,44,32,97,110,100,32,116,104,101,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32>>,{code,[],[<<79,117,116>>]},<<32,102,111,114,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,46,32,73,116,32,105,115,32,111,110,108,121,32,117,115,101,100,32,102,111,114,32,118,97,114,105,111,117,115,32,115,101,114,118,101,114,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,79,83,32,40>>,{code,[],[<<115,104,101,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<117,115,101,114>>]},<<41,46,32,72,101,110,99,101,44,32,105,116,115,32,117,115,101,32,105,115,32,108,105,109,105,116,101,100,46>>]}]}]},{p,[],[{code,[],[<<80,111,114,116,83,101,116,116,105,110,103,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,115,101,116,116,105,110,103,115,32,102,111,114,32,116,104,101,32,112,111,114,116,46,32,84,104,101,32,118,97,108,105,100,32,115,101,116,116,105,110,103,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,97,99,107,101,116,44,32,78,125>>]}]},{dd,[],[{p,[],[<<77,101,115,115,97,103,101,115,32,97,114,101,32,112,114,101,99,101,100,101,100,32,98,121,32,116,104,101,105,114,32,108,101,110,103,116,104,44,32,115,101,110,116,32,105,110,32>>,{code,[],[<<78>>]},<<32,98,121,116,101,115,44,32,119,105,116,104,32,116,104,101,32,109,111,115,116,32,115,105,103,110,105,102,105,99,97,110,116,32,98,121,116,101,32,102,105,114,115,116,46,32,84,104,101,32,118,97,108,105,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<78>>]},<<32,97,114,101,32,49,44,32,50,44,32,97,110,100,32,52,46>>]}]},{dt,[],[{code,[],[<<115,116,114,101,97,109>>]}]},{dd,[],[{p,[],[<<79,117,116,112,117,116,32,109,101,115,115,97,103,101,115,32,97,114,101,32,115,101,110,116,32,119,105,116,104,111,117,116,32,112,97,99,107,101,116,32,108,101,110,103,116,104,115,46,32,65,32,117,115,101,114,45,100,101,102,105,110,101,100,32,112,114,111,116,111,99,111,108,32,109,117,115,116,32,98,101,32,117,115,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,101,120,116,101,114,110,97,108,32,111,98,106,101,99,116,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,101,44,32,76,125>>]}]},{dd,[],[{p,[],[<<77,101,115,115,97,103,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,111,110,32,97,32,112,101,114,32,108,105,110,101,32,98,97,115,105,115,46,32,69,97,99,104,32,108,105,110,101,32,40,100,101,108,105,109,105,116,101,100,32,98,121,32,116,104,101,32,79,83,45,100,101,112,101,110,100,101,110,116,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,41,32,105,115,32,100,101,108,105,118,101,114,101,100,32,105,110,32,97,32,115,105,110,103,108,101,32,109,101,115,115,97,103,101,46,32,84,104,101,32,109,101,115,115,97,103,101,32,100,97,116,97,32,102,111,114,109,97,116,32,105,115,32>>,{code,[],[<<123,70,108,97,103,44,32,76,105,110,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,108,97,103>>]},<<32,105,115,32>>,{code,[],[<<101,111,108>>]},<<32,111,114,32>>,{code,[],[<<110,111,101,111,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<76,105,110,101>>]},<<32,105,115,32,116,104,101,32,100,97,116,97,32,100,101,108,105,118,101,114,101,100,32,40,119,105,116,104,111,117,116,32,116,104,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,41,46>>]},{p,[],[{code,[],[<<76>>]},<<32,115,112,101,99,105,102,105,101,115,32,116,104,101,32,109,97,120,105,109,117,109,32,108,105,110,101,32,108,101,110,103,116,104,32,105,110,32,98,121,116,101,115,46,32,76,105,110,101,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,105,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,105,110,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,109,101,115,115,97,103,101,44,32,119,105,116,104,32>>,{code,[],[<<70,108,97,103>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<110,111,101,111,108>>]},<<32,102,111,114,32,97,108,108,32,98,117,116,32,116,104,101,32,108,97,115,116,32,109,101,115,115,97,103,101,46,32,73,102,32,101,110,100,32,111,102,32,102,105,108,101,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,32,97,110,121,119,104,101,114,101,32,101,108,115,101,32,116,104,97,110,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,105,110,103,32,97,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,44,32,116,104,101,32,108,97,115,116,32,108,105,110,101,32,105,115,32,97,108,115,111,32,100,101,108,105,118,101,114,101,100,32,119,105,116,104,32>>,{code,[],[<<70,108,97,103>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<110,111,101,111,108>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,108,105,110,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,119,105,116,104,32>>,{code,[],[<<70,108,97,103>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<101,111,108>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<123,112,97,99,107,101,116,44,32,78,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,108,105,110,101,44,32,76,125>>]},<<32,115,101,116,116,105,110,103,115,32,97,114,101,32,109,117,116,117,97,108,108,121,32,101,120,99,108,117,115,105,118,101,46>>]}]},{dt,[],[{code,[],[<<123,99,100,44,32,68,105,114,125>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46,32,84,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,32,115,116,97,114,116,115,32,117,115,105,110,103,32>>,{code,[],[<<68,105,114>>]},<<32,97,115,32,105,116,115,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,46,32>>,{code,[],[<<68,105,114>>]},<<32,109,117,115,116,32,98,101,32,97,32,115,116,114,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,101,110,118,44,32,69,110,118,125>>]}]},{dd,[],[{p,[],[<<84,121,112,101,115,58>>,{br,[],[]},<<194,160,194,160>>,{code,[],[<<78,97,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,111,115,35,101,110,118,95,118,97,114,95,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<111,115,58,101,110,118,95,118,97,114,95,110,97,109,101,40,41>>]}]},{br,[],[]},<<194,160,194,160>>,{code,[],[<<86,97,108,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,111,115,35,101,110,118,95,118,97,114,95,118,97,108,117,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<111,115,58,101,110,118,95,118,97,114,95,118,97,108,117,101,40,41>>]}]},{code,[],[<<32,124,32,102,97,108,115,101>>]},{br,[],[]},<<194,160,194,160>>,{code,[],[<<69,110,118,32,61,32,91,123,78,97,109,101,44,32,86,97,108,125,93>>]}]},{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<44,32,97,110,100,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46,32,84,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,111,102,32,116,104,101,32,115,116,97,114,116,101,100,32,112,114,111,99,101,115,115,32,105,115,32,101,120,116,101,110,100,101,100,32,117,115,105,110,103,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32>>,{code,[],[<<69,110,118>>]},<<46>>]},{p,[],[{code,[],[<<69,110,118>>]},<<32,105,115,32,116,111,32,98,101,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32>>,{code,[],[<<123,78,97,109,101,44,32,86,97,108,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,97,110,32,101,110,118,105,114,111,110,109,101,110,116,32,118,97,114,105,97,98,108,101,44,32,97,110,100,32>>,{code,[],[<<86,97,108>>]},<<32,105,115,32,116,104,101,32,118,97,108,117,101,32,105,116,32,105,115,32,116,111,32,104,97,118,101,32,105,110,32,116,104,101,32,115,112,97,119,110,101,100,32,112,111,114,116,32,112,114,111,99,101,115,115,46,32,66,111,116,104,32>>,{code,[],[<<78,97,109,101>>]},<<32,97,110,100,32>>,{code,[],[<<86,97,108>>]},<<32,109,117,115,116,32,98,101,32,115,116,114,105,110,103,115,46,32,84,104,101,32,111,110,101,32,101,120,99,101,112,116,105,111,110,32,105,115,32>>,{code,[],[<<86,97,108>>]},<<32,98,101,105,110,103,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,40,105,110,32,97,110,97,108,111,103,121,32,119,105,116,104,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,103,101,116,101,110,118,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,103,101,116,101,110,118,47,49>>]}]},<<44,32,119,104,105,99,104,32,114,101,109,111,118,101,115,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,118,97,114,105,97,98,108,101,46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,101,110,99,111,100,105,110,103,32,114,101,113,117,105,114,101,109,101,110,116,115,44,32,115,101,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,121,112,101,115,32,102,111,114,32>>,{code,[],[<<78,97,109,101>>]},<<32,97,110,100,32>>,{code,[],[<<86,97,108>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,97,114,103,115,44,32,91,32,115,116,114,105,110,103,40,41,32,124,32,98,105,110,97,114,121,40,41,32,93,125>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<32,97,110,100,32,115,112,101,99,105,102,105,101,115,32,97,114,103,117,109,101,110,116,115,32,116,111,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,46,32,69,97,99,104,32,97,114,103,117,109,101,110,116,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,115,101,112,97,114,97,116,101,32,115,116,114,105,110,103,32,97,110,100,32,40,111,110,32,85,110,105,120,41,32,101,118,101,110,116,117,97,108,108,121,32,101,110,100,115,32,117,112,32,97,115,32,111,110,101,32,101,108,101,109,101,110,116,32,101,97,99,104,32,105,110,32,116,104,101,32,97,114,103,117,109,101,110,116,32,118,101,99,116,111,114,46,32,79,110,32,111,116,104,101,114,32,112,108,97,116,102,111,114,109,115,44,32,97,32,115,105,109,105,108,97,114,32,98,101,104,97,118,105,111,114,32,105,115,32,109,105,109,105,99,107,101,100,46>>]},{p,[],[<<84,104,101,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,110,111,116,32,101,120,112,97,110,100,101,100,32,98,121,32,116,104,101,32,115,104,101,108,108,32,98,101,102,111,114,101,32,116,104,101,121,32,97,114,101,32,115,117,112,112,108,105,101,100,32,116,111,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,46,32,77,111,115,116,32,110,111,116,97,98,108,121,32,116,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,102,105,108,101,32,119,105,108,100,99,97,114,100,32,101,120,112,97,110,115,105,111,110,32,100,111,101,115,32,110,111,116,32,111,99,99,117,114,46,32,84,111,32,101,120,112,97,110,100,32,119,105,108,100,99,97,114,100,115,32,102,111,114,32,116,104,101,32,97,114,103,117,109,101,110,116,115,44,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,102,105,108,101,108,105,98,35,119,105,108,100,99,97,114,100,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,105,108,101,108,105,98,58,119,105,108,100,99,97,114,100,47,49>>]}]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,101,118,101,110,32,105,102,32,116,104,101,32,112,114,111,103,114,97,109,32,105,115,32,97,32,85,110,105,120,32,115,104,101,108,108,32,115,99,114,105,112,116,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,116,104,101,32,115,104,101,108,108,32,117,108,116,105,109,97,116,101,108,121,32,105,115,32,105,110,118,111,107,101,100,44,32,119,105,108,100,99,97,114,100,32,101,120,112,97,110,115,105,111,110,32,100,111,101,115,32,110,111,116,32,111,99,99,117,114,44,32,97,110,100,32,116,104,101,32,115,99,114,105,112,116,32,105,115,32,112,114,111,118,105,100,101,100,32,119,105,116,104,32,116,104,101,32,117,110,116,111,117,99,104,101,100,32,97,114,103,117,109,101,110,116,115,46,32,79,110,32,87,105,110,100,111,119,115,44,32,119,105,108,100,99,97,114,100,32,101,120,112,97,110,115,105,111,110,32,105,115,32,97,108,119,97,121,115,32,117,112,32,116,111,32,116,104,101,32,112,114,111,103,114,97,109,32,105,116,115,101,108,102,44,32,116,104,101,114,101,102,111,114,101,32,116,104,105,115,32,105,115,32,110,111,116,32,97,110,32,105,115,115,117,101,46>>]},{p,[],[<<84,104,101,32,101,120,101,99,117,116,97,98,108,101,32,110,97,109,101,32,40,97,108,115,111,32,107,110,111,119,110,32,97,115,32>>,{code,[],[<<97,114,103,118,91,48,93>>]},<<41,32,105,115,32,110,111,116,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,105,115,32,108,105,115,116,46,32,84,104,101,32,112,114,111,112,101,114,32,101,120,101,99,117,116,97,98,108,101,32,110,97,109,101,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,117,115,101,100,32,97,115,32>>,{code,[],[<<97,114,103,118,91,48,93>>]},<<44,32,119,104,101,114,101,32,97,112,112,108,105,99,97,98,108,101,46>>]},{p,[],[<<73,102,32,121,111,117,32,101,120,112,108,105,99,105,116,108,121,32,119,97,110,116,32,116,111,32,115,101,116,32,116,104,101,32,112,114,111,103,114,97,109,32,110,97,109,101,32,105,110,32,116,104,101,32,97,114,103,117,109,101,110,116,32,118,101,99,116,111,114,44,32,111,112,116,105,111,110,32>>,{code,[],[<<97,114,103,48>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,97,114,103,48,44,32,115,116,114,105,110,103,40,41,32,124,32,98,105,110,97,114,121,40,41,125>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<32,97,110,100,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,115,32,116,104,101,32,112,114,111,103,114,97,109,32,110,97,109,101,32,97,114,103,117,109,101,110,116,32,119,104,101,110,32,114,117,110,110,105,110,103,32,97,110,32,101,120,101,99,117,116,97,98,108,101,46,32,84,104,105,115,32,99,97,110,32,105,110,32,115,111,109,101,32,99,105,114,99,117,109,115,116,97,110,99,101,115,44,32,111,110,32,115,111,109,101,32,79,83,115,44,32,98,101,32,100,101,115,105,114,97,98,108,101,46,32,72,111,119,32,116,104,101,32,112,114,111,103,114,97,109,32,114,101,115,112,111,110,100,115,32,116,111,32,116,104,105,115,32,105,115,32,104,105,103,104,108,121,32,115,121,115,116,101,109,45,100,101,112,101,110,100,101,110,116,32,97,110,100,32,110,111,32,115,112,101,99,105,102,105,99,32,101,102,102,101,99,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,46>>]}]},{dt,[],[{code,[],[<<101,120,105,116,95,115,116,97,116,117,115>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,110,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,44,32,97,110,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,99,101,115,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,101,32,112,111,114,116,32,101,120,105,116,115,44,32,97,32,109,101,115,115,97,103,101,32,111,102,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,80,111,114,116,44,123,101,120,105,116,95,115,116,97,116,117,115,44,83,116,97,116,117,115,125,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,114,111,99,101,115,115,44,32,119,104,101,114,101,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<32,105,115,32,116,104,101,32,101,120,105,116,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,101,32,112,114,111,103,114,97,109,32,97,98,111,114,116,115,32,111,110,32,85,110,105,120,44,32,116,104,101,32,115,97,109,101,32,99,111,110,118,101,110,116,105,111,110,32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,115,104,101,108,108,115,32,100,111,32,40,116,104,97,116,32,105,115,44,32,49,50,56,43,115,105,103,110,97,108,41,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<101,111,102>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,108,115,111,44,32,116,104,101,32,109,101,115,115,97,103,101,115,32>>,{code,[],[<<101,111,102>>]},<<32,97,110,100,32>>,{code,[],[<<101,120,105,116,95,115,116,97,116,117,115>>]},<<32,97,112,112,101,97,114,32,105,110,32,97,110,32,117,110,115,112,101,99,105,102,105,101,100,32,111,114,100,101,114,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,32,99,108,111,115,101,115,32,105,116,115,32>>,{code,[],[<<115,116,100,111,117,116>>]},<<32,119,105,116,104,111,117,116,32,101,120,105,116,105,110,103,44,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,105,116,95,115,116,97,116,117,115>>]},<<32,100,111,101,115,32,110,111,116,32,119,111,114,107,46>>]}]},{dt,[],[{code,[],[<<117,115,101,95,115,116,100,105,111>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46,32,73,116,32,97,108,108,111,119,115,32,116,104,101,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,32,97,110,100,32,111,117,116,112,117,116,32,40,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,48,32,97,110,100,32,49,41,32,111,102,32,116,104,101,32,115,112,97,119,110,101,100,32,40,85,110,105,120,41,32,112,114,111,99,101,115,115,32,102,111,114,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,69,114,108,97,110,103,46>>]}]},{dt,[],[{code,[],[<<110,111,117,115,101,95,115,116,100,105,111>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,112,111,115,105,116,101,32,111,102,32>>,{code,[],[<<117,115,101,95,115,116,100,105,111>>]},<<46,32,73,116,32,117,115,101,115,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,51,32,97,110,100,32,52,32,102,111,114,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,69,114,108,97,110,103,46>>]}]},{dt,[],[{code,[],[<<115,116,100,101,114,114,95,116,111,95,115,116,100,111,117,116>>]}]},{dd,[],[{p,[],[<<65,102,102,101,99,116,115,32,112,111,114,116,115,32,116,111,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,115,46,32,84,104,101,32,101,120,101,99,117,116,101,100,32,112,114,111,103,114,97,109,32,103,101,116,115,32,105,116,115,32,115,116,97,110,100,97,114,100,32,101,114,114,111,114,32,102,105,108,101,32,114,101,100,105,114,101,99,116,101,100,32,116,111,32,105,116,115,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,32,102,105,108,101,46,32>>,{code,[],[<<115,116,100,101,114,114,95,116,111,95,115,116,100,111,117,116>>]},<<32,97,110,100,32>>,{code,[],[<<110,111,117,115,101,95,115,116,100,105,111>>]},<<32,97,114,101,32,109,117,116,117,97,108,108,121,32,101,120,99,108,117,115,105,118,101,46>>]}]},{dt,[],[{code,[],[<<111,118,101,114,108,97,112,112,101,100,95,105,111>>]}]},{dd,[],[{p,[],[<<65,102,102,101,99,116,115,32,112,111,114,116,115,32,116,111,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,115,32,111,110,32,87,105,110,100,111,119,115,32,111,110,108,121,46,32,84,104,101,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,32,97,110,100,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,32,104,97,110,100,108,101,115,32,111,102,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,32,97,114,101,44,32,105,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,117,112,112,108,105,101,100,44,32,111,112,101,110,101,100,32,119,105,116,104,32,102,108,97,103,32>>,{code,[],[<<70,73,76,69,95,70,76,65,71,95,79,86,69,82,76,65,80,80,69,68>>]},<<44,32,115,111,32,116,104,97,116,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,32,99,97,110,32,40,97,110,100,32,109,117,115,116,41,32,100,111,32,111,118,101,114,108,97,112,112,101,100,32,73,47,79,32,111,110,32,105,116,115,32,115,116,97,110,100,97,114,100,32,104,97,110,100,108,101,115,46,32,84,104,105,115,32,105,115,32,110,111,116,32,110,111,114,109,97,108,108,121,32,116,104,101,32,99,97,115,101,32,102,111,114,32,115,105,109,112,108,101,32,112,111,114,116,32,112,114,111,103,114,97,109,115,44,32,98,117,116,32,97,110,32,111,112,116,105,111,110,32,111,102,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,101,120,112,101,114,105,101,110,99,101,100,32,87,105,110,100,111,119,115,32,112,114,111,103,114,97,109,109,101,114,46,32>>,{em,[],[<<79,110,32,97,108,108,32,111,116,104,101,114,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,105,108,101,110,116,108,121,32,100,105,115,99,97,114,100,101,100,46>>]}]}]},{dt,[],[{code,[],[<<105,110>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,99,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,102,111,114,32,105,110,112,117,116,46>>]}]},{dt,[],[{code,[],[<<111,117,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,99,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,102,111,114,32,111,117,116,112,117,116,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<65,108,108,32,73,47,79,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,115,32,97,115,32,111,112,112,111,115,101,100,32,116,111,32,108,105,115,116,115,32,111,102,32,98,121,116,101,115,46>>]}]},{dt,[],[{code,[],[<<101,111,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,99,108,111,115,101,100,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,102,105,108,101,32,97,110,100,32,100,111,101,115,32,110,111,116,32,112,114,111,100,117,99,101,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,46,32,73,110,115,116,101,97,100,44,32,105,116,32,114,101,109,97,105,110,115,32,111,112,101,110,32,97,110,100,32,97,32>>,{code,[],[<<123,80,111,114,116,44,32,101,111,102,125>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,104,111,108,100,105,110,103,32,116,104,101,32,112,111,114,116,46>>]}]},{dt,[],[{code,[],[<<104,105,100,101>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32,114,117,110,110,105,110,103,32,111,110,32,87,105,110,100,111,119,115,44,32,115,117,112,112,114,101,115,115,101,115,32,99,114,101,97,116,105,111,110,32,111,102,32,97,32,110,101,119,32,99,111,110,115,111,108,101,32,119,105,110,100,111,119,32,119,104,101,110,32,115,112,97,119,110,105,110,103,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,46,32,40,84,104,105,115,32,111,112,116,105,111,110,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,111,110,32,111,116,104,101,114,32,112,108,97,116,102,111,114,109,115,46,41>>]}]},{dt,[],[{code,[],[<<123,112,97,114,97,108,108,101,108,105,115,109,44,32,66,111,111,108,101,97,110,125>>]}]},{dd,[],[{a,[{id,<<111,112,101,110,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>}],[]},{p,[],[<<83,101,116,115,32,115,99,104,101,100,117,108,101,114,32,104,105,110,116,32,102,111,114,32,112,111,114,116,32,112,97,114,97,108,108,101,108,105,115,109,46,32,73,102,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,115,99,104,101,100,117,108,101,115,32,112,111,114,116,32,116,97,115,107,115,59,32,119,104,101,110,32,100,111,105,110,103,32,115,111,44,32,105,116,32,105,109,112,114,111,118,101,115,32,112,97,114,97,108,108,101,108,105,115,109,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,73,102,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,116,114,105,101,115,32,116,111,32,112,101,114,102,111,114,109,32,112,111,114,116,32,116,97,115,107,115,32,105,109,109,101,100,105,97,116,101,108,121,44,32,105,109,112,114,111,118,105,110,103,32,108,97,116,101,110,99,121,32,97,116,32,116,104,101,32,101,120,112,101,110,115,101,32,111,102,32,112,97,114,97,108,108,101,108,105,115,109,46,32,84,104,101,32,100,101,102,97,117,108,116,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,121,115,116,101,109,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,112,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,112,112>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,98,117,115,121,95,108,105,109,105,116,115,95,112,111,114,116,44,32,123,76,111,119,44,32,72,105,103,104,125,32,124,32,100,105,115,97,98,108,101,100,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,108,105,109,105,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,117,115,101,100,32,102,111,114,32,99,111,110,116,114,111,108,108,105,110,103,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,32,111,102,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,112,111,114,116,115,32,105,110,116,101,114,110,97,108,32,111,117,116,112,117,116,32,113,117,101,117,101,32,115,105,122,101,32,98,101,99,111,109,101,115,32,108,97,114,103,101,114,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<72,105,103,104>>]},<<32,98,121,116,101,115,44,32,105,116,32,101,110,116,101,114,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,105,116,32,98,101,99,111,109,101,115,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<76,111,119>>]},<<32,98,121,116,101,115,32,105,116,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,116,104,101,32,112,111,114,116,32,105,115,32,105,110,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,44,32,112,114,111,99,101,115,115,101,115,32,115,101,110,100,105,110,103,32,99,111,109,109,97,110,100,115,32,116,111,32,105,116,32,119,105,108,108,32,98,101,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,67,111,109,109,97,110,100,115,32,97,114,101,32,105,110,32,116,104,105,115,32,99,111,110,116,101,120,116,32,101,105,116,104,101,114,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,91,50,44,51,93>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<76,111,119>>]},<<32,108,105,109,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,97,100,106,117,115,116,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,102,32,105,116,32,105,115,32,115,101,116,32,108,97,114,103,101,114,32,116,104,101,110,32>>,{code,[],[<<72,105,103,104>>]},<<46,32,86,97,108,105,100,32,114,97,110,103,101,32,111,102,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<76,111,119>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,115,32>>,{code,[],[<<91,49,44,32,40,49,32,98,115,108,32,40,56,42,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,119,111,114,100,115,105,122,101,41,41,41,45,50,93>>]},<<46,32,73,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<32,105,115,32,112,97,115,115,101,100,44,32,116,104,101,32,112,111,114,116,32,119,105,108,108,32,110,101,118,101,114,32,101,110,116,101,114,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,115,32,97,114,101,32>>,{code,[],[<<76,111,119,32,61,32,52,48,57,54>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104,32,61,32,56,49,57,50>>]},<<46>>]},{p,[],[{em,[],[<<78,111,116,101>>]},<<32,116,104,97,116,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,111,110,108,121,32,118,97,108,105,100,32,119,104,101,110,32,115,112,97,119,110,105,110,103,32,97,110,32,101,120,101,99,117,116,97,98,108,101,32,40,112,111,114,116,32,112,114,111,103,114,97,109,41,32,98,121,32,111,112,101,110,105,110,103,32,116,104,101,32,115,112,97,119,110,32,100,114,105,118,101,114,32,97,110,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32>>,{code,[],[<<102,100>>]},<<32,100,114,105,118,101,114,46,32,84,104,105,115,32,111,112,116,105,111,110,32,119,105,108,108,32,99,97,117,115,101,32,97,32,102,97,105,108,117,114,101,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,119,104,101,110,32,111,112,101,110,105,110,103,32,111,116,104,101,114,32,100,114,105,118,101,114,115,46>>]}]},{dt,[],[{code,[],[<<123,98,117,115,121,95,108,105,109,105,116,115,95,109,115,103,113,44,32,123,76,111,119,44,32,72,105,103,104,125,32,124,32,100,105,115,97,98,108,101,100,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,108,105,109,105,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,117,115,101,100,32,102,111,114,32,99,111,110,116,114,111,108,108,105,110,103,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,32,111,102,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,112,111,114,116,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,115,105,122,101,32,98,101,99,111,109,101,115,32,108,97,114,103,101,114,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<72,105,103,104>>]},<<32,98,121,116,101,115,32,105,116,32,101,110,116,101,114,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,105,116,32,98,101,99,111,109,101,115,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<76,111,119>>]},<<32,98,121,116,101,115,32,105,116,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,105,115,32,105,110,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,44,32,112,114,111,99,101,115,115,101,115,32,115,101,110,100,105,110,103,32,99,111,109,109,97,110,100,115,32,116,111,32,105,116,32,119,105,108,108,32,98,101,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,67,111,109,109,97,110,100,115,32,97,114,101,32,105,110,32,116,104,105,115,32,99,111,110,116,101,120,116,32,101,105,116,104,101,114,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,91,50,44,51,93>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<76,111,119>>]},<<32,108,105,109,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,97,100,106,117,115,116,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,102,32,105,116,32,105,115,32,115,101,116,32,108,97,114,103,101,114,32,116,104,101,110,32>>,{code,[],[<<72,105,103,104>>]},<<46,32,86,97,108,105,100,32,114,97,110,103,101,32,111,102,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<76,111,119>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,115,32>>,{code,[],[<<91,49,44,32,40,49,32,98,115,108,32,40,56,42,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,119,111,114,100,115,105,122,101,41,41,41,45,50,93>>]},<<46,32,73,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<32,105,115,32,112,97,115,115,101,100,44,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,110,101,118,101,114,32,101,110,116,101,114,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46>>]},{p,[],[{em,[],[<<78,111,116,101>>]},<<32,116,104,97,116,32,105,102,32,116,104,101,32,100,114,105,118,101,114,32,115,116,97,116,105,99,97,108,108,121,32,104,97,115,32,100,105,115,97,98,108,101,100,32,116,104,101,32,117,115,101,32,111,102,32,116,104,105,115,32,102,101,97,116,117,114,101,44,32,97,32,102,97,105,108,117,114,101,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,119,105,108,108,32,98,101,32,114,97,105,115,101,100,32,117,110,108,101,115,115,32,116,104,105,115,32,111,112,116,105,111,110,32,97,108,115,111,32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<100,105,115,97,98,108,101>>]},<<32,111,114,32,110,111,116,32,112,97,115,115,101,100,32,97,116,32,97,108,108,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,115,32,97,114,101,32>>,{code,[],[<<76,111,119,32,61,32,52,48,57,54>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104,32,61,32,56,49,57,50>>]},<<32,117,110,108,101,115,115,32,116,104,101,32,100,114,105,118,101,114,32,105,116,115,101,108,102,32,100,111,101,115,32,109,111,100,105,102,105,99,97,116,105,111,110,115,32,111,102,32,116,104,101,115,101,32,118,97,108,117,101,115,46>>]},{p,[],[{em,[],[<<78,111,116,101>>]},<<32,116,104,97,116,32,116,104,101,32,100,114,105,118,101,114,32,109,105,103,104,116,32,102,97,105,108,32,105,102,32,105,116,32,97,108,115,111,32,97,100,106,117,115,116,32,116,104,101,115,101,32,108,105,109,105,116,115,32,98,121,32,105,116,115,101,108,102,32,97,110,100,32,121,111,117,32,104,97,118,101,32,100,105,115,97,98,108,101,100,32,116,104,105,115,32,102,101,97,116,117,114,101,46>>]},{p,[],[<<84,104,101,32,115,112,97,119,110,32,100,114,105,118,101,114,32,40,117,115,101,100,32,119,104,101,110,32,115,112,97,119,110,105,110,103,32,97,110,32,101,120,101,99,117,116,97,98,108,101,41,32,97,110,100,32,116,104,101,32>>,{code,[],[<<102,100>>]},<<32,100,114,105,118,101,114,32,100,111,32,110,111,116,32,100,105,115,97,98,108,101,32,116,104,105,115,32,102,101,97,116,117,114,101,32,97,110,100,32,100,111,32,110,111,116,32,97,100,106,117,115,116,32,116,104,101,115,101,32,108,105,109,105,116,115,32,98,121,32,116,104,101,109,115,101,108,118,101,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,114,105,118,101,114,35,101,114,108,95,100,114,118,95,98,117,115,121,95,109,115,103,113,95,108,105,109,105,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,108,95,100,114,118,95,98,117,115,121,95,109,115,103,113,95,108,105,109,105,116,115,40,41>>]}]},<<46>>]}]}]},{p,[],[<<68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<115,116,114,101,97,109>>]},<<32,102,111,114,32,97,108,108,32,112,111,114,116,32,116,121,112,101,115,32,97,110,100,32>>,{code,[],[<<117,115,101,95,115,116,100,105,111>>]},<<32,102,111,114,32,115,112,97,119,110,101,100,32,112,111,114,116,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32,105,102,32,116,104,101,32,112,111,114,116,32,99,97,110,110,111,116,32,98,101,32,111,112,101,110,101,100,44,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<44,32>>,{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]},<<44,32,111,114,32,116,104,101,32,80,79,83,73,88,32,101,114,114,111,114,32,99,111,100,101,32,116,104,97,116,32,109,111,115,116,32,99,108,111,115,101,108,121,32,100,101,115,99,114,105,98,101,115,32,116,104,101,32,101,114,114,111,114,44,32,111,114,32>>,{code,[],[<<101,105,110,118,97,108>>]},<<32,105,102,32,110,111,32,80,79,83,73,88,32,99,111,100,101,32,105,115,32,97,112,112,114,111,112,114,105,97,116,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<66,97,100,32,105,110,112,117,116,32,97,114,103,117,109,101,110,116,115,32,116,111,32>>,{code,[],[<<111,112,101,110,95,112,111,114,116>>]},<<46>>]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[<<65,108,108,32,97,118,97,105,108,97,98,108,101,32,112,111,114,116,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,101,109,117,108,97,116,111,114,32,97,114,101,32,105,110,32,117,115,101,46>>]},{dt,[],[{code,[],[<<101,110,111,109,101,109>>]}]},{dd,[],[<<78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,116,111,32,99,114,101,97,116,101,32,116,104,101,32,112,111,114,116,46>>]},{dt,[],[{code,[],[<<101,97,103,97,105,110>>]}]},{dd,[],[<<78,111,32,109,111,114,101,32,97,118,97,105,108,97,98,108,101,32,79,83,32,112,114,111,99,101,115,115,101,115,46>>]},{dt,[],[{code,[],[<<101,110,97,109,101,116,111,111,108,111,110,103>>]}]},{dd,[],[<<84,111,111,32,108,111,110,103,32,101,120,116,101,114,110,97,108,32,99,111,109,109,97,110,100,46>>]},{dt,[],[{code,[],[<<101,109,102,105,108,101>>]}]},{dd,[],[<<78,111,32,109,111,114,101,32,97,118,97,105,108,97,98,108,101,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,40,102,111,114,32,116,104,101,32,79,83,32,112,114,111,99,101,115,115,32,116,104,97,116,32,116,104,101,32,69,114,108,97,110,103,32,101,109,117,108,97,116,111,114,32,114,117,110,115,32,105,110,41,46>>]},{dt,[],[{code,[],[<<101,110,102,105,108,101>>]}]},{dd,[],[<<70,117,108,108,32,102,105,108,101,32,116,97,98,108,101,32,40,102,111,114,32,116,104,101,32,101,110,116,105,114,101,32,79,83,41,46>>]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{code,[],[<<67,111,109,109,97,110,100>>]},<<32,115,112,101,99,105,102,105,101,100,32,105,110,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,67,111,109,109,97,110,100,125>>]},<<32,100,111,101,115,32,110,111,116,32,112,111,105,110,116,32,111,117,116,32,97,110,32,101,120,101,99,117,116,97,98,108,101,32,102,105,108,101,46>>]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{code,[],[<<70,105,108,101,78,97,109,101>>]},<<32,115,112,101,99,105,102,105,101,100,32,105,110,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<32,100,111,101,115,32,110,111,116,32,112,111,105,110,116,32,111,117,116,32,97,110,32,101,120,105,115,116,105,110,103,32,102,105,108,101,46>>]}]},{p,[],[<<68,117,114,105,110,103,32,117,115,101,32,111,102,32,97,32,112,111,114,116,32,111,112,101,110,101,100,32,117,115,105,110,103,32>>,{code,[],[<<123,115,112,97,119,110,44,32,78,97,109,101,125>>]},<<44,32>>,{code,[],[<<123,115,112,97,119,110,95,100,114,105,118,101,114,44,32,78,97,109,101,125>>]},<<44,32,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,78,97,109,101,125>>]},<<44,32,101,114,114,111,114,115,32,97,114,105,115,105,110,103,32,119,104,101,110,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,105,116,32,97,114,101,32,114,101,112,111,114,116,101,100,32,116,111,32,116,104,101,32,111,119,110,105,110,103,32,112,114,111,99,101,115,115,32,117,115,105,110,103,32,115,105,103,110,97,108,115,32,111,102,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,80,111,114,116,44,32,80,111,115,105,120,67,111,100,101,125>>]},<<46,32,70,111,114,32,116,104,101,32,112,111,115,115,105,98,108,101,32,118,97,108,117,101,115,32,111,102,32>>,{code,[],[<<80,111,115,105,120,67,111,100,101>>]},<<44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,102,105,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,105,108,101,40,51,41>>]}]},<<46>>]},{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,111,114,116,115,32,116,104,97,116,32,99,97,110,32,98,101,32,111,112,101,110,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,109,97,120,95,112,111,114,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,81>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,56,57>>,signature => [{attribute,2315,spec,{{open_port,2},[{type,2315,bounded_fun,[{type,2315,'fun',[{type,2315,product,[{var,2315,'PortName'},{var,2315,'PortSettings'}]},{type,2315,port,[]}]},[{type,2316,constraint,[{atom,2316,is_subtype},[{var,2316,'PortName'},{type,2316,union,[{type,2316,tuple,[{atom,2316,spawn},{ann_type,2316,[{var,2316,'Command'},{type,2316,union,[{type,2316,string,[]},{type,2316,binary,[]}]}]}]},{type,2317,tuple,[{atom,2317,spawn_driver},{ann_type,2317,[{var,2317,'Command'},{type,2317,union,[{type,2317,string,[]},{type,2317,binary,[]}]}]}]},{type,2318,tuple,[{atom,2318,spawn_executable},{ann_type,2318,[{var,2318,'FileName'},{remote_type,2318,[{atom,2318,file},{atom,2318,name_all},[]]}]}]},{type,2319,tuple,[{atom,2319,fd},{ann_type,2319,[{var,2319,'In'},{type,2319,non_neg_integer,[]}]},{ann_type,2319,[{var,2319,'Out'},{type,2319,non_neg_integer,[]}]}]}]}]]},{type,2320,constraint,[{atom,2320,is_subtype},[{var,2320,'PortSettings'},{type,2320,list,[{var,2320,'Opt'}]}]]},{type,2321,constraint,[{atom,2321,is_subtype},[{var,2321,'Opt'},{type,2321,union,[{type,2321,tuple,[{atom,2321,packet},{ann_type,2321,[{var,2321,'N'},{type,2321,union,[{integer,2321,1},{integer,2321,2},{integer,2321,4}]}]}]},{atom,2322,stream},{type,2323,tuple,[{atom,2323,line},{ann_type,2323,[{var,2323,'L'},{type,2323,non_neg_integer,[]}]}]},{type,2324,tuple,[{atom,2324,cd},{ann_type,2324,[{var,2324,'Dir'},{type,2324,union,[{type,2324,string,[]},{type,2324,binary,[]}]}]}]},{type,2325,tuple,[{atom,2325,env},{ann_type,2325,[{var,2325,'Env'},{type,2325,list,[{type,2325,tuple,[{ann_type,2325,[{var,2325,'Name'},{remote_type,2325,[{atom,2325,os},{atom,2325,env_var_name},[]]}]},{ann_type,2325,[{var,2325,'Val'},{type,2325,union,[{remote_type,2325,[{atom,2325,os},{atom,2325,env_var_value},[]]},{atom,2325,false}]}]}]}]}]}]},{type,2326,tuple,[{atom,2326,args},{type,2326,list,[{type,2326,union,[{type,2326,string,[]},{type,2326,binary,[]}]}]}]},{type,2327,tuple,[{atom,2327,arg0},{type,2327,union,[{type,2327,string,[]},{type,2327,binary,[]}]}]},{atom,2328,exit_status},{atom,2329,use_stdio},{atom,2330,nouse_stdio},{atom,2331,stderr_to_stdout},{atom,2332,in},{atom,2333,out},{atom,2334,binary},{atom,2335,eof},{type,2336,tuple,[{atom,2336,parallelism},{ann_type,2336,[{var,2336,'Boolean'},{type,2336,boolean,[]}]}]},{atom,2337,hide},{type,2338,tuple,[{atom,2338,busy_limits_port},{type,2338,union,[{type,2338,tuple,[{type,2338,non_neg_integer,[]},{type,2338,non_neg_integer,[]}]},{atom,2338,disabled}]}]},{type,2339,tuple,[{atom,2339,busy_limits_msgq},{type,2339,union,[{type,2339,tuple,[{type,2339,non_neg_integer,[]},{type,2339,non_neg_integer,[]}]},{atom,2339,disabled}]}]}]}]]}]]}]}}]}},{{function,phash,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1477}],[<<112,104,97,115,104,47,50>>],#{<<101,110>> => [{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,104,97,115,104,50,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,112,104,97,115,104,50,47,50>>]}]},<<32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,102,111,114,32,110,101,119,32,99,111,100,101,46,32,78,111,116,101,32,116,104,97,116,32>>,{code,[],[<<101,114,108,97,110,103,58,112,104,97,115,104,40,88,44,78,41>>]},<<32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,121,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,112,104,97,115,104,50,40,88,44,78,41>>]}]}]},{p,[],[<<80,111,114,116,97,98,108,101,32,104,97,115,104,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,104,97,115,104,32,102,111,114,32,116,104,101,32,115,97,109,101,32,69,114,108,97,110,103,32,116,101,114,109,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,109,97,99,104,105,110,101,32,97,114,99,104,105,116,101,99,116,117,114,101,32,97,110,100,32,69,82,84,83,32,118,101,114,115,105,111,110,32,40,116,104,101,32,66,73,70,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,82,84,83,32,52,46,57,46,49,46,49,41,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,97,32,104,97,115,104,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<84,101,114,109>>]},<<32,119,105,116,104,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<49,46,46,82,97,110,103,101>>]},<<46,32,84,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<82,97,110,103,101>>]},<<32,105,115,32,50,94,51,50,46>>]}]},#{deprecated => <<101,114,108,97,110,103,58,112,104,97,115,104,47,50,32,105,115,32,100,101,112,114,101,99,97,116,101,100,59,32,117,115,101,32,101,114,108,97,110,103,58,112,104,97,115,104,50,47,50,32,105,110,115,116,101,97,100>>,edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,55,57,53>>,signature => [{attribute,1477,spec,{{erlang,phash,2},[{type,1477,bounded_fun,[{type,1477,'fun',[{type,1477,product,[{var,1477,'Term'},{var,1477,'Range'}]},{var,1477,'Hash'}]},[{type,1478,constraint,[{atom,1478,is_subtype},[{var,1478,'Term'},{type,1478,term,[]}]]},{type,1479,constraint,[{atom,1479,is_subtype},[{var,1479,'Range'},{type,1479,pos_integer,[]}]]},{type,1480,constraint,[{atom,1480,is_subtype},[{var,1480,'Hash'},{type,1480,pos_integer,[]}]]}]]}]}}]}},{{function,phash2,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1492}],[<<112,104,97,115,104,50,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,49,55>>,equiv => {function,phash2,1},signature => [{attribute,1492,spec,{{erlang,phash2,2},[{type,1492,bounded_fun,[{type,1492,'fun',[{type,1492,product,[{var,1492,'Term'},{var,1492,'Range'}]},{var,1492,'Hash'}]},[{type,1493,constraint,[{atom,1493,is_subtype},[{var,1493,'Term'},{type,1493,term,[]}]]},{type,1494,constraint,[{atom,1494,is_subtype},[{var,1494,'Range'},{type,1494,pos_integer,[]}]]},{type,1495,constraint,[{atom,1495,is_subtype},[{var,1495,'Hash'},{type,1495,non_neg_integer,[]}]]}]]}]}}]}},{{function,phash2,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1485}],[<<112,104,97,115,104,50,47,49>>],#{<<101,110>> => [{p,[],[<<80,111,114,116,97,98,108,101,32,104,97,115,104,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,104,97,115,104,32,102,111,114,32,116,104,101,32,115,97,109,101,32,69,114,108,97,110,103,32,116,101,114,109,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,109,97,99,104,105,110,101,32,97,114,99,104,105,116,101,99,116,117,114,101,32,97,110,100,32,69,82,84,83,32,118,101,114,115,105,111,110,32,40,116,104,101,32,66,73,70,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,82,84,83,32,53,46,50,41,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,97,32,104,97,115,104,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<84,101,114,109>>]},<<32,119,105,116,104,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<48,46,46,82,97,110,103,101,45,49>>]},<<46,32,84,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<82,97,110,103,101>>]},<<32,105,115,32,50,94,51,50,46,32,87,104,101,110,32,119,105,116,104,111,117,116,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<82,97,110,103,101>>]},<<44,32,97,32,118,97,108,117,101,32,105,110,32,116,104,101,32,114,97,110,103,101,32,48,46,46,50,94,50,55,45,49,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,97,108,119,97,121,115,32,116,111,32,98,101,32,117,115,101,100,32,102,111,114,32,104,97,115,104,105,110,103,32,116,101,114,109,115,46,32,73,116,32,100,105,115,116,114,105,98,117,116,101,115,32,115,109,97,108,108,32,105,110,116,101,103,101,114,115,32,98,101,116,116,101,114,32,116,104,97,110,32>>,{code,[],[<<112,104,97,115,104,47,50>>]},<<44,32,97,110,100,32,105,116,32,105,115,32,102,97,115,116,101,114,32,102,111,114,32,98,105,103,110,117,109,115,32,97,110,100,32,98,105,110,97,114,105,101,115,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<48,46,46,82,97,110,103,101,45,49>>]},<<32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,114,97,110,103,101,32,111,102,32>>,{code,[],[<<112,104,97,115,104,47,50>>]},<<44,32,119,104,105,99,104,32,105,115,32>>,{code,[],[<<49,46,46,82,97,110,103,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,49,55>>,signature => [{attribute,1485,spec,{{erlang,phash2,1},[{type,1485,bounded_fun,[{type,1485,'fun',[{type,1485,product,[{var,1485,'Term'}]},{var,1485,'Hash'}]},[{type,1486,constraint,[{atom,1486,is_subtype},[{var,1486,'Term'},{type,1486,term,[]}]]},{type,1487,constraint,[{atom,1487,is_subtype},[{var,1487,'Hash'},{type,1487,non_neg_integer,[]}]]}]]}]}}]}},{{function,pid_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1500}],[<<112,105,100,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,112,105,100,95,116,111,95,108,105,115,116,40,115,101,108,102,40,41,41,46,10,34,60,48,46,56,53,46,48,62,34>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,108,95,100,105,115,116,95,112,114,111,116,111,99,111,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,114,101,97,116,105,111,110>>]},<<32,102,111,114,32,116,104,101,32,110,111,100,101,32,105,115,32,110,111,116,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<46,32,84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,112,114,111,99,101,115,115,101,115,32,105,110,32,100,105,102,102,101,114,101,110,116,32,105,110,99,97,114,110,97,116,105,111,110,115,32,111,102,32,97,32,110,111,100,101,32,119,105,116,104,32,97,32,115,112,101,99,105,102,105,99,32,110,97,109,101,32,99,97,110,32,103,101,116,32,116,104,101,32,115,97,109,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,52,50>>,signature => [{attribute,1500,spec,{{pid_to_list,1},[{type,1500,bounded_fun,[{type,1500,'fun',[{type,1500,product,[{var,1500,'Pid'}]},{type,1500,string,[]}]},[{type,1501,constraint,[{atom,1501,is_subtype},[{var,1501,'Pid'},{type,1501,pid,[]}]]}]]}]}}]}},{{function,port_call,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3594}],[<<112,111,114,116,95,99,97,108,108,47,51>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,121,110,99,104,114,111,110,111,117,115,32,99,97,108,108,32,116,111,32,97,32,112,111,114,116,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,97,110,100,32>>,{code,[],[<<68,97,116,97>>]},<<32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,44,32,116,104,97,116,32,105,115,44,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46,32,78,111,116,32,97,108,108,32,112,111,114,116,32,100,114,105,118,101,114,115,32,115,117,112,112,111,114,116,32,116,104,105,115,32,102,101,97,116,117,114,101,46>>]},{p,[],[{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,114,101,102,101,114,114,105,110,103,32,116,111,32,97,32,100,114,105,118,101,114,46>>]},{p,[],[{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,119,104,105,99,104,32,105,115,32,112,97,115,115,101,100,32,111,110,32,116,111,32,116,104,101,32,100,114,105,118,101,114,46>>]},{p,[],[{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,121,32,69,114,108,97,110,103,32,116,101,114,109,46,32,84,104,105,115,32,100,97,116,97,32,105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,98,105,110,97,114,121,32,116,101,114,109,32,102,111,114,109,97,116,32,97,110,100,32,115,101,110,116,32,116,111,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,101,114,109,32,102,114,111,109,32,116,104,101,32,100,114,105,118,101,114,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,116,104,101,32,114,101,116,117,114,110,101,100,32,100,97,116,97,32,97,108,115,111,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,97,32,51,50,45,98,105,116,32,105,110,116,101,103,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,110,99,104,114,111,110,111,117,115,32,99,111,110,116,114,111,108,32,111,112,101,114,97,116,105,111,110,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,115,111,32,100,101,99,105,100,101,115,32,102,111,114,32,97,110,121,32,114,101,97,115,111,110,32,40,112,114,111,98,97,98,108,121,32,115,111,109,101,116,104,105,110,103,32,119,114,111,110,103,32,119,105,116,104,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<41,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,99,97,108,108,32>>,{code,[],[<<112,111,114,116,95,99,97,108,108>>]},<<32,119,105,116,104,32,97,110,32,117,110,107,110,111,119,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,101,120,112,101,99,116,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,115,117,112,112,108,105,101,100,32,97,114,103,117,109,101,110,116,115,46>>]}]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,54,49>>,signature => [{attribute,3594,spec,{{erlang,port_call,3},[{type,3594,bounded_fun,[{type,3594,'fun',[{type,3594,product,[{var,3594,'Port'},{var,3594,'Operation'},{var,3594,'Data'}]},{type,3594,term,[]}]},[{type,3595,constraint,[{atom,3595,is_subtype},[{var,3595,'Port'},{type,3595,union,[{type,3595,port,[]},{type,3595,atom,[]}]}]]},{type,3596,constraint,[{atom,3596,is_subtype},[{var,3596,'Operation'},{type,3596,integer,[]}]]},{type,3597,constraint,[{atom,3597,is_subtype},[{var,3597,'Data'},{type,3597,term,[]}]]}]]}]}}]}},{{function,port_close,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3555}],[<<112,111,114,116,95,99,108,111,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,108,111,115,101,115,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,82,111,117,103,104,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<80,111,114,116,32,33,32,123,115,101,108,102,40,41,44,32,99,108,111,115,101,125>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,32,40,115,101,101,32,98,101,108,111,119,41,44,32,98,101,105,110,103,32,115,121,110,99,104,114,111,110,111,117,115,44,32,97,110,100,32,116,104,97,116,32,116,104,101,32,112,111,114,116,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,114,101,112,108,121,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,32,99,108,111,115,101,100,125>>]},<<46,32,65,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,99,108,111,115,101,32,97,32,112,111,114,116,32,119,105,116,104,32>>,{code,[],[<<112,111,114,116,95,99,108,111,115,101,47,49>>]},<<44,32,110,111,116,32,111,110,108,121,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,40,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,114,111,99,101,115,115,41,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,99,108,111,115,101,47,49>>]},<<32,114,101,116,117,114,110,115,46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,114,105,115,111,110,58,32>>,{code,[],[<<80,111,114,116,32,33,32,123,115,101,108,102,40,41,44,32,99,108,111,115,101,125>>]},<<32,111,110,108,121,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,111,114,116,32,111,114,32,97,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,99,108,111,115,101,100,32,112,111,114,116,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,110,32,111,112,101,110,32,112,111,114,116,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32,112,111,114,116,32,114,101,112,108,105,101,115,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,32,99,108,111,115,101,100,125>>]},<<32,119,104,101,110,32,97,108,108,32,98,117,102,102,101,114,115,32,104,97,118,101,32,98,101,101,110,32,102,108,117,115,104,101,100,32,97,110,100,32,116,104,101,32,112,111,114,116,32,114,101,97,108,108,121,32,99,108,111,115,101,115,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32>>,{em,[],[<<112,111,114,116,32,111,119,110,101,114>>]},<<32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,99,108,111,115,101,32,97,32,112,111,114,116,32,117,115,105,110,103,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,99,108,111,115,101,125>>]},<<32,97,115,32,105,102,32,105,116,32,105,116,115,101,108,102,32,119,97,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,98,117,116,32,116,104,101,32,114,101,112,108,121,32,97,108,119,97,121,115,32,103,111,101,115,32,116,111,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,54,44,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,99,108,111,115,101,125>>]},<<32,105,115,32,116,114,117,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,97,108,119,97,121,115,32,98,101,101,110,32,100,111,99,117,109,101,110,116,101,100,32,97,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,108,101,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,121,110,99,104,114,111,110,111,117,115,46,32>>,{code,[],[<<112,111,114,116,95,99,108,111,115,101,47,49>>]},<<32,105,115,32,104,111,119,101,118,101,114,32,115,116,105,108,108,32,102,117,108,108,121,32,115,121,110,99,104,114,111,110,111,117,115,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,57,49,51>>,signature => [{attribute,3555,spec,{{port_close,1},[{type,3555,bounded_fun,[{type,3555,'fun',[{type,3555,product,[{var,3555,'Port'}]},{atom,3555,true}]},[{type,3556,constraint,[{atom,3556,is_subtype},[{var,3556,'Port'},{type,3556,union,[{type,3556,port,[]},{type,3556,atom,[]}]}]]}]]}]}}]}},{{function,port_command,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3513}],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,100,97,116,97,32,116,111,32,97,32,112,111,114,116,46,32,83,97,109,101,32,97,115,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,32,97,110,100,32,98,101,105,110,103,32,115,121,110,99,104,114,111,110,111,117,115,32,40,115,101,101,32,98,101,108,111,119,41,46,32,65,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,110,100,32,100,97,116,97,32,116,111,32,97,32,112,111,114,116,32,119,105,116,104,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>]},<<44,32,110,111,116,32,111,110,108,121,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,40,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,114,111,99,101,115,115,41,46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,114,105,115,111,110,58,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,111,110,108,121,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,111,114,116,32,111,114,32,97,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,99,108,111,115,101,100,32,112,111,114,116,44,32,116,104,101,32,100,97,116,97,32,109,101,115,115,97,103,101,32,100,105,115,97,112,112,101,97,114,115,32,119,105,116,104,111,117,116,32,97,32,115,111,117,110,100,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,111,112,101,110,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32>>,{em,[],[<<112,111,114,116,32,111,119,110,101,114>>]},<<32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<46,32,84,104,101,32,112,111,114,116,32,111,119,110,101,114,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<32,97,108,115,111,32,105,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,73,47,79,32,108,105,115,116,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,110,100,32,116,111,32,97,32,112,111,114,116,32,117,115,105,110,103,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,97,115,32,105,102,32,105,116,32,105,116,115,101,108,102,32,119,97,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,98,117,115,121,32,97,110,121,32,109,111,114,101,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,54,44,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,105,115,32,116,114,117,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,97,108,119,97,121,115,32,98,101,101,110,32,100,111,99,117,109,101,110,116,101,100,32,97,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,108,101,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,121,110,99,104,114,111,110,111,117,115,46,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>]},<<32,105,115,32,104,111,119,101,118,101,114,32,115,116,105,108,108,32,102,117,108,108,121,32,115,121,110,99,104,114,111,110,111,117,115,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]}]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,73,47,79,32,108,105,115,116,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,115,101,110,100,32,100,97,116,97,32,116,111,32,97,110,32,117,110,107,110,111,119,110,32,112,111,114,116,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,100,97,116,97,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,57,53,51>>,signature => [{attribute,3513,spec,{{port_command,2},[{type,3513,bounded_fun,[{type,3513,'fun',[{type,3513,product,[{var,3513,'Port'},{var,3513,'Data'}]},{atom,3513,true}]},[{type,3514,constraint,[{atom,3514,is_subtype},[{var,3514,'Port'},{type,3514,union,[{type,3514,port,[]},{type,3514,atom,[]}]}]]},{type,3515,constraint,[{atom,3515,is_subtype},[{var,3515,'Data'},{type,3515,iodata,[]}]]}]]}]}}]}},{{function,port_command,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3526}],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,100,97,116,97,32,116,111,32,97,32,112,111,114,116,46,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,40,80,111,114,116,44,32,68,97,116,97,44,32,91,93,41>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,40,80,111,114,116,44,32,68,97,116,97,41>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,99,111,109,109,97,110,100,32,105,115,32,97,98,111,114,116,101,100,44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,98,117,115,121,32,97,110,121,109,111,114,101,46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,111,114,99,101>>]}]},{dd,[],[<<84,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,115,117,115,112,101,110,100,101,100,32,105,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,105,110,115,116,101,97,100,32,116,104,101,32,112,111,114,116,32,99,111,109,109,97,110,100,32,105,115,32,102,111,114,99,101,100,32,116,104,114,111,117,103,104,46,32,84,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32,116,104,101,32,100,114,105,118,101,114,32,111,102,32,116,104,101,32,112,111,114,116,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,105,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,100,114,105,118,101,114,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,100,114,105,118,101,114,95,101,110,116,114,121,35,100,114,105,118,101,114,95,102,108,97,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<69,82,76,95,68,82,86,95,70,76,65,71,95,83,79,70,84,95,66,85,83,89>>]}]},<<46>>]},{dt,[],[{code,[],[<<110,111,115,117,115,112,101,110,100>>]}]},{dd,[],[<<84,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,115,117,115,112,101,110,100,101,100,32,105,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,105,110,115,116,101,97,100,32,116,104,101,32,112,111,114,116,32,99,111,109,109,97,110,100,32,105,115,32,97,98,111,114,116,101,100,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<77,111,114,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,73,47,79,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,111,112,116,105,111,110,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<102,111,114,99,101>>]},<<32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,98,117,116,32,116,104,101,32,100,114,105,118,101,114,32,111,102,32,116,104,101,32,112,111,114,116,32,100,111,101,115,32,110,111,116,32,97,108,108,111,119,32,102,111,114,99,105,110,103,32,116,104,114,111,117,103,104,32,97,32,98,117,115,121,32,112,111,114,116,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,115,101,110,100,32,100,97,116,97,32,116,111,32,97,110,32,117,110,107,110,111,119,110,32,112,111,114,116,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,100,97,116,97,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,48,48,53>>,signature => [{attribute,3526,spec,{{port_command,3},[{type,3526,bounded_fun,[{type,3526,'fun',[{type,3526,product,[{var,3526,'Port'},{var,3526,'Data'},{var,3526,'OptionList'}]},{type,3526,boolean,[]}]},[{type,3527,constraint,[{atom,3527,is_subtype},[{var,3527,'Port'},{type,3527,union,[{type,3527,port,[]},{type,3527,atom,[]}]}]]},{type,3528,constraint,[{atom,3528,is_subtype},[{var,3528,'Data'},{type,3528,iodata,[]}]]},{type,3529,constraint,[{atom,3529,is_subtype},[{var,3529,'Option'},{type,3529,union,[{atom,3529,force},{atom,3529,nosuspend}]}]]},{type,3530,constraint,[{atom,3530,is_subtype},[{var,3530,'OptionList'},{type,3530,list,[{var,3530,'Option'}]}]]}]]}]}}]}},{{function,port_connect,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3542}],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,40,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,111,114,116,41,32,116,111,32>>,{code,[],[<<80,105,100>>]},<<46,32,82,111,117,103,104,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{p,[],[<<84,104,101,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,32,100,105,102,102,101,114,115,44,32,115,101,101,32,98,101,108,111,119,46>>]}]},{li,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,114,101,112,108,121,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,99,111,110,110,101,99,116,101,100,125>>]},<<46>>]}]},{li,[],[{p,[],[{code,[],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,49>>]},<<32,105,115,32,115,121,110,99,104,114,111,110,111,117,115,44,32,115,101,101,32,98,101,108,111,119,46>>]}]},{li,[],[{p,[],[<<84,104,101,32,110,101,119,32,112,111,114,116,32,111,119,110,101,114,32,103,101,116,115,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,46>>]}]}]},{p,[],[<<84,104,101,32,111,108,100,32,112,111,114,116,32,111,119,110,101,114,32,115,116,97,121,115,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,32,97,110,100,32,109,117,115,116,32,99,97,108,108,32>>,{code,[],[<<117,110,108,105,110,107,40,80,111,114,116,41>>]},<<32,105,102,32,116,104,105,115,32,105,115,32,110,111,116,32,100,101,115,105,114,101,100,46,32,65,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,116,111,32,98,101,32,97,110,121,32,112,114,111,99,101,115,115,32,119,105,116,104,32>>,{code,[],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,50>>]},<<46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,114,105,115,111,110,58,32>>,{code,[],[<<80,111,114,116,32,33,32,123,115,101,108,102,40,41,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,111,110,108,121,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,111,114,116,32,111,114,32,97,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,99,108,111,115,101,100,32,112,111,114,116,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,110,32,111,112,101,110,32,112,111,114,116,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32,112,111,114,116,32,114,101,112,108,105,101,115,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,32,99,111,110,110,101,99,116,101,100,125>>]},<<32,116,111,32,116,104,101,32,111,108,100,32,112,111,114,116,32,111,119,110,101,114,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,111,108,100,32,112,111,114,116,32,111,119,110,101,114,32,105,115,32,115,116,105,108,108,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,119,104,105,108,101,32,116,104,101,32,110,101,119,32,105,115,32,110,111,116,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,110,32,111,112,101,110,32,112,111,114,116,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32>>,{em,[],[<<112,111,114,116,32,111,119,110,101,114>>]},<<32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<46,32,84,104,101,32,112,111,114,116,32,111,119,110,101,114,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<32,97,108,115,111,32,105,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,120,105,115,116,105,110,103,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,117,115,105,110,103,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,97,115,32,105,102,32,105,116,32,105,116,115,101,108,102,32,119,97,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,98,117,116,32,116,104,101,32,114,101,112,108,121,32,97,108,119,97,121,115,32,103,111,101,115,32,116,111,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,54,44,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,105,115,32,116,114,117,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,97,108,119,97,121,115,32,98,101,101,110,32,100,111,99,117,109,101,110,116,101,100,32,97,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,108,101,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,121,110,99,104,114,111,110,111,117,115,46,32>>,{code,[],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,50>>]},<<32,105,115,32,104,111,119,101,118,101,114,32,115,116,105,108,108,32,102,117,108,108,121,32,115,121,110,99,104,114,111,110,111,117,115,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,120,105,115,116,105,110,103,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,48,54,57>>,signature => [{attribute,3542,spec,{{port_connect,2},[{type,3542,bounded_fun,[{type,3542,'fun',[{type,3542,product,[{var,3542,'Port'},{var,3542,'Pid'}]},{atom,3542,true}]},[{type,3543,constraint,[{atom,3543,is_subtype},[{var,3543,'Port'},{type,3543,union,[{type,3543,port,[]},{type,3543,atom,[]}]}]]},{type,3544,constraint,[{atom,3544,is_subtype},[{var,3544,'Pid'},{type,3544,pid,[]}]]}]]}]}}]}},{{function,port_control,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3567}],[<<112,111,114,116,95,99,111,110,116,114,111,108,47,51>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,121,110,99,104,114,111,110,111,117,115,32,99,111,110,116,114,111,108,32,111,112,101,114,97,116,105,111,110,32,111,110,32,97,32,112,111,114,116,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,97,110,100,32>>,{code,[],[<<68,97,116,97>>]},<<32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,44,32,116,104,97,116,32,105,115,44,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46,32,78,111,116,32,97,108,108,32,112,111,114,116,32,100,114,105,118,101,114,115,32,115,117,112,112,111,114,116,32,116,104,105,115,32,99,111,110,116,114,111,108,32,102,101,97,116,117,114,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,48,46,46,50,53,53,44,32,111,114,32,97,32,98,105,110,97,114,121,44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,116,104,101,32,114,101,116,117,114,110,101,100,32,100,97,116,97,32,97,108,115,111,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,111,112,101,110,32,112,111,114,116,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,99,97,110,110,111,116,32,102,105,116,32,105,110,32,97,32,51,50,45,98,105,116,32,105,110,116,101,103,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,110,99,104,114,111,110,111,117,115,32,99,111,110,116,114,111,108,32,111,112,101,114,97,116,105,111,110,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,115,111,32,100,101,99,105,100,101,115,32,102,111,114,32,97,110,121,32,114,101,97,115,111,110,32,40,112,114,111,98,97,98,108,121,32,115,111,109,101,116,104,105,110,103,32,119,114,111,110,103,32,119,105,116,104,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<41,46>>,{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,99,97,108,108,32>>,{code,[],[<<112,111,114,116,95,99,111,110,116,114,111,108,47,51>>]},<<32,119,105,116,104,32,97,110,32,117,110,107,110,111,119,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,101,120,112,101,99,116,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,115,117,112,112,108,105,101,100,32,97,114,103,117,109,101,110,116,115,46>>]}]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,49,51,56>>,signature => [{attribute,3567,spec,{{port_control,3},[{type,3567,bounded_fun,[{type,3567,'fun',[{type,3567,product,[{var,3567,'Port'},{var,3567,'Operation'},{var,3567,'Data'}]},{type,3567,union,[{type,3567,iodata,[]},{type,3567,binary,[]}]}]},[{type,3568,constraint,[{atom,3568,is_subtype},[{var,3568,'Port'},{type,3568,union,[{type,3568,port,[]},{type,3568,atom,[]}]}]]},{type,3569,constraint,[{atom,3569,is_subtype},[{var,3569,'Operation'},{type,3569,integer,[]}]]},{type,3570,constraint,[{atom,3570,is_subtype},[{var,3570,'Data'},{type,3570,iodata,[]}]]}]]}]}}]}},{{function,port_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3608}],[<<112,111,114,116,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,116,117,112,108,101,115,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,111,112,101,110,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,110,100,32,97,108,108,32,116,104,101,32,116,117,112,108,101,115,32,97,114,101,32,110,111,116,32,109,97,110,100,97,116,111,114,121,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,49>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<84,104,101,32,114,101,115,117,108,116,32,99,111,110,116,97,105,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32>>,{code,[],[<<73,116,101,109>>]},<<115,58>>]},{ul,[],[{li,[],[{code,[],[<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,40,105,102,32,116,104,101,32,112,111,114,116,32,104,97,115,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,41>>]},{li,[],[{code,[],[<<105,100>>]}]},{li,[],[{code,[],[<<99,111,110,110,101,99,116,101,100>>]}]},{li,[],[{code,[],[<<108,105,110,107,115>>]}]},{li,[],[{code,[],[<<110,97,109,101>>]}]},{li,[],[{code,[],[<<105,110,112,117,116>>]}]},{li,[],[{code,[],[<<111,117,116,112,117,116>>]}]}]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32>>,{code,[],[<<73,116,101,109>>]},<<115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,111,114,116,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,49,56,50>>,signature => [{attribute,3608,spec,{{erlang,port_info,1},[{type,3608,bounded_fun,[{type,3608,'fun',[{type,3608,product,[{var,3608,'Port'}]},{var,3608,'Result'}]},[{type,3609,constraint,[{atom,3609,is_subtype},[{var,3609,'Port'},{type,3609,union,[{type,3609,port,[]},{type,3609,atom,[]}]}]]},{type,3610,constraint,[{atom,3610,is_subtype},[{var,3610,'ResultItem'},{type,3610,union,[{type,3610,tuple,[{atom,3610,registered_name},{ann_type,3610,[{var,3610,'RegisteredName'},{type,3610,atom,[]}]}]},{type,3611,tuple,[{atom,3611,id},{ann_type,3611,[{var,3611,'Index'},{type,3611,non_neg_integer,[]}]}]},{type,3612,tuple,[{atom,3612,connected},{ann_type,3612,[{var,3612,'Pid'},{type,3612,pid,[]}]}]},{type,3613,tuple,[{atom,3613,links},{ann_type,3613,[{var,3613,'Pids'},{type,3613,list,[{type,3613,pid,[]}]}]}]},{type,3614,tuple,[{atom,3614,name},{ann_type,3614,[{var,3614,'String'},{type,3614,string,[]}]}]},{type,3615,tuple,[{atom,3615,input},{ann_type,3615,[{var,3615,'Bytes'},{type,3615,non_neg_integer,[]}]}]},{type,3616,tuple,[{atom,3616,output},{ann_type,3616,[{var,3616,'Bytes'},{type,3616,non_neg_integer,[]}]}]},{type,3617,tuple,[{atom,3617,os_pid},{ann_type,3617,[{var,3617,'OsPid'},{type,3617,union,[{type,3617,non_neg_integer,[]},{atom,3617,undefined}]}]}]}]}]]},{type,3618,constraint,[{atom,3618,is_subtype},[{var,3618,'Result'},{type,3618,union,[{type,3618,list,[{var,3618,'ResultItem'}]},{atom,3618,undefined}]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,50,49,51>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3629,bounded_fun,[{type,3629,'fun',[{type,3629,product,[{var,3629,'Port'},{atom,3629,connected}]},{type,3629,union,[{type,3629,tuple,[{atom,3629,connected},{var,3629,'Pid'}]},{atom,3629,undefined}]}]},[{type,3630,constraint,[{atom,3630,is_subtype},[{var,3630,'Port'},{type,3630,union,[{type,3630,port,[]},{type,3630,atom,[]}]}]]},{type,3631,constraint,[{atom,3631,is_subtype},[{var,3631,'Pid'},{type,3631,pid,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<73,110,100,101,120>>]},<<32,105,115,32,116,104,101,32,105,110,116,101,114,110,97,108,32,105,110,100,101,120,32,111,102,32,116,104,101,32,112,111,114,116,46,32,84,104,105,115,32,105,110,100,101,120,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,115,101,112,97,114,97,116,101,32,112,111,114,116,115,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,50,50,57>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3632,bounded_fun,[{type,3632,'fun',[{type,3632,product,[{var,3632,'Port'},{atom,3632,id}]},{type,3632,union,[{type,3632,tuple,[{atom,3632,id},{var,3632,'Index'}]},{atom,3632,undefined}]}]},[{type,3633,constraint,[{atom,3633,is_subtype},[{var,3633,'Port'},{type,3633,union,[{type,3633,port,[]},{type,3633,atom,[]}]}]]},{type,3634,constraint,[{atom,3634,is_subtype},[{var,3634,'Index'},{type,3634,non_neg_integer,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,50,52,53>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3635,bounded_fun,[{type,3635,'fun',[{type,3635,product,[{var,3635,'Port'},{atom,3635,input}]},{type,3635,union,[{type,3635,tuple,[{atom,3635,input},{var,3635,'Bytes'}]},{atom,3635,undefined}]}]},[{type,3636,constraint,[{atom,3636,is_subtype},[{var,3636,'Port'},{type,3636,union,[{type,3636,port,[]},{type,3636,atom,[]}]}]]},{type,3637,constraint,[{atom,3637,is_subtype},[{var,3637,'Bytes'},{type,3637,non_neg_integer,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<80,105,100,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,116,104,101,32,112,111,114,116,32,105,115,32,108,105,110,107,101,100,32,116,111,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,50,54,49>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3638,bounded_fun,[{type,3638,'fun',[{type,3638,product,[{var,3638,'Port'},{atom,3638,links}]},{type,3638,union,[{type,3638,tuple,[{atom,3638,links},{var,3638,'Pids'}]},{atom,3638,undefined}]}]},[{type,3639,constraint,[{atom,3639,is_subtype},[{var,3639,'Port'},{type,3639,union,[{type,3639,port,[]},{type,3639,atom,[]}]}]]},{type,3640,constraint,[{atom,3640,is_subtype},[{var,3640,'Pids'},{type,3640,list,[{type,3640,pid,[]}]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<76,111,99,107,105,110,103>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{code,[],[<<112,111,114,116,95,108,101,118,101,108>>]},<<32,40,112,111,114,116,45,115,112,101,99,105,102,105,99,32,108,111,99,107,105,110,103,41>>]},{li,[],[{code,[],[<<100,114,105,118,101,114,95,108,101,118,101,108>>]},<<32,40,100,114,105,118,101,114,45,115,112,101,99,105,102,105,99,32,108,111,99,107,105,110,103,41>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,115,101,32,114,101,115,117,108,116,115,32,97,114,101,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,115,112,101,99,105,102,105,99,32,97,110,100,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,50,55,55>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3641,bounded_fun,[{type,3641,'fun',[{type,3641,product,[{var,3641,'Port'},{atom,3641,locking}]},{type,3641,union,[{type,3641,tuple,[{atom,3641,locking},{var,3641,'Locking'}]},{atom,3641,undefined}]}]},[{type,3642,constraint,[{atom,3642,is_subtype},[{var,3642,'Port'},{type,3642,union,[{type,3642,port,[]},{type,3642,atom,[]}]}]]},{type,3643,constraint,[{atom,3643,is_subtype},[{var,3643,'Locking'},{type,3643,union,[{atom,3643,false},{atom,3643,port_level},{atom,3643,driver_level}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{a,[{id,<<112,111,114,116,95,105,110,102,111,95,109,101,109,111,114,121>>}],[]},{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,116,104,105,115,32,112,111,114,116,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,101,32,112,111,114,116,32,105,116,115,101,108,102,32,99,97,110,32,104,97,118,101,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,116,104,97,116,32,105,115,32,110,111,116,32,105,110,99,108,117,100,101,100,32,105,110,32>>,{code,[],[<<66,121,116,101,115>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,50,57,56>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3644,bounded_fun,[{type,3644,'fun',[{type,3644,product,[{var,3644,'Port'},{atom,3644,memory}]},{type,3644,union,[{type,3644,tuple,[{atom,3644,memory},{var,3644,'Bytes'}]},{atom,3644,undefined}]}]},[{type,3645,constraint,[{atom,3645,is_subtype},[{var,3645,'Port'},{type,3645,union,[{type,3645,port,[]},{type,3645,atom,[]}]}]]},{type,3646,constraint,[{atom,3646,is_subtype},[{var,3646,'Bytes'},{type,3646,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<77,111,110,105,116,111,114,115>>]},<<32,114,101,112,114,101,115,101,110,116,32,112,114,111,99,101,115,115,101,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,116,104,105,115,32,112,111,114,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,49,55>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3647,bounded_fun,[{type,3647,'fun',[{type,3647,product,[{var,3647,'Port'},{atom,3647,monitors}]},{type,3647,union,[{type,3647,tuple,[{atom,3647,monitors},{var,3647,'Monitors'}]},{atom,3647,undefined}]}]},[{type,3648,constraint,[{atom,3648,is_subtype},[{var,3648,'Port'},{type,3648,union,[{type,3648,port,[]},{type,3648,atom,[]}]}]]},{type,3649,constraint,[{atom,3649,is_subtype},[{var,3649,'Monitors'},{type,3649,list,[{type,3649,tuple,[{atom,3649,process},{type,3649,pid,[]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,108,105,115,116,32,111,102,32,112,105,100,115,32,116,104,97,116,32,97,114,101,32,109,111,110,105,116,111,114,105,110,103,32,103,105,118,101,110,32,112,111,114,116,32,97,116,32,116,104,101,32,109,111,109,101,110,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,51,51>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3650,bounded_fun,[{type,3650,'fun',[{type,3650,product,[{var,3650,'Port'},{atom,3650,monitored_by}]},{type,3650,union,[{type,3650,tuple,[{atom,3650,monitored_by},{var,3650,'MonitoredBy'}]},{atom,3650,undefined}]}]},[{type,3651,constraint,[{atom,3651,is_subtype},[{var,3651,'Port'},{type,3651,union,[{type,3651,port,[]},{type,3651,atom,[]}]}]]},{type,3652,constraint,[{atom,3652,is_subtype},[{var,3652,'MonitoredBy'},{type,3652,list,[{type,3652,pid,[]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,99,111,109,109,97,110,100,32,110,97,109,101,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,95,112,111,114,116,47,50>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,52,57>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3653,bounded_fun,[{type,3653,'fun',[{type,3653,product,[{var,3653,'Port'},{atom,3653,name}]},{type,3653,union,[{type,3653,tuple,[{atom,3653,name},{var,3653,'Name'}]},{atom,3653,undefined}]}]},[{type,3654,constraint,[{atom,3654,is_subtype},[{var,3654,'Port'},{type,3654,union,[{type,3654,port,[]},{type,3654,atom,[]}]}]]},{type,3655,constraint,[{atom,3655,is_subtype},[{var,3655,'Name'},{type,3655,string,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<79,115,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,111,114,32,101,113,117,105,118,97,108,101,110,116,41,32,111,102,32,97,110,32,79,83,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,95,112,111,114,116,40,123,115,112,97,119,110,32,124,32,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,67,111,109,109,97,110,100,125,44,32,79,112,116,105,111,110,115,41>>]}]},<<46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,112,97,119,110,105,110,103,32,97,110,32,79,83,32,112,114,111,99,101,115,115,44,32,116,104,101,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,54,53>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3656,bounded_fun,[{type,3656,'fun',[{type,3656,product,[{var,3656,'Port'},{atom,3656,os_pid}]},{type,3656,union,[{type,3656,tuple,[{atom,3656,os_pid},{var,3656,'OsPid'}]},{atom,3656,undefined}]}]},[{type,3657,constraint,[{atom,3657,is_subtype},[{var,3657,'Port'},{type,3657,union,[{type,3657,port,[]},{type,3657,atom,[]}]}]]},{type,3658,constraint,[{atom,3658,is_subtype},[{var,3658,'OsPid'},{type,3658,union,[{type,3658,non_neg_integer,[]},{atom,3658,undefined}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,119,114,105,116,116,101,110,32,116,111,32,116,104,101,32,112,111,114,116,32,102,114,111,109,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,111,114,116,95,99,111,109,109,97,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,111,114,116,95,99,111,109,109,97,110,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,51>>]}]},<<44,32,111,114,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,56,52>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3659,bounded_fun,[{type,3659,'fun',[{type,3659,product,[{var,3659,'Port'},{atom,3659,output}]},{type,3659,union,[{type,3659,tuple,[{atom,3659,output},{var,3659,'Bytes'}]},{atom,3659,undefined}]}]},[{type,3660,constraint,[{atom,3660,is_subtype},[{var,3660,'Port'},{type,3660,union,[{type,3660,port,[]},{type,3660,atom,[]}]}]]},{type,3661,constraint,[{atom,3661,is_subtype},[{var,3661,'Bytes'},{type,3661,non_neg_integer,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,111,111,108,101,97,110>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,112,111,114,116,32,112,97,114,97,108,108,101,108,105,115,109,32,104,105,110,116,32,117,115,101,100,32,98,121,32,116,104,105,115,32,112,111,114,116,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,111,112,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,97,114,97,108,108,101,108,105,115,109>>]}]},<<32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,95,112,111,114,116,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,48,51>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3662,bounded_fun,[{type,3662,'fun',[{type,3662,product,[{var,3662,'Port'},{atom,3662,parallelism}]},{type,3662,union,[{type,3662,tuple,[{atom,3662,parallelism},{var,3662,'Boolean'}]},{atom,3662,undefined}]}]},[{type,3663,constraint,[{atom,3663,is_subtype},[{var,3663,'Port'},{type,3663,union,[{type,3663,port,[]},{type,3663,atom,[]}]}]]},{type,3664,constraint,[{atom,3664,is_subtype},[{var,3664,'Boolean'},{type,3664,boolean,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,113,117,101,117,101,100,32,98,121,32,116,104,101,32,112,111,114,116,32,117,115,105,110,103,32,116,104,101,32,69,82,84,83,32,100,114,105,118,101,114,32,113,117,101,117,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,49,52>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3665,bounded_fun,[{type,3665,'fun',[{type,3665,product,[{var,3665,'Port'},{atom,3665,queue_size}]},{type,3665,union,[{type,3665,tuple,[{atom,3665,queue_size},{var,3665,'Bytes'}]},{atom,3665,undefined}]}]},[{type,3666,constraint,[{atom,3666,is_subtype},[{var,3666,'Port'},{type,3666,union,[{type,3666,port,[]},{type,3666,atom,[]}]}]]},{type,3667,constraint,[{atom,3667,is_subtype},[{var,3667,'Bytes'},{type,3667,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3629}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,116,104,101,32,112,111,114,116,46,32,73,102,32,116,104,101,32,112,111,114,116,32,104,97,115,32,110,111,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,51,49>>,signature => [{attribute,3629,spec,{{erlang,port_info,2},[{type,3668,bounded_fun,[{type,3668,'fun',[{type,3668,product,[{var,3668,'Port'},{atom,3668,registered_name}]},{type,3668,union,[{type,3668,tuple,[{atom,3668,registered_name},{var,3668,'RegisteredName'}]},{type,3668,nil,[]},{atom,3668,undefined}]}]},[{type,3669,constraint,[{atom,3669,is_subtype},[{var,3669,'Port'},{type,3669,union,[{type,3669,port,[]},{type,3669,atom,[]}]}]]},{type,3670,constraint,[{atom,3670,is_subtype},[{var,3670,'RegisteredName'},{type,3670,atom,[]}]]}]]}]}}]}},{{function,port_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1506}],[<<112,111,114,116,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32>>,{code,[],[<<80,111,114,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,52,56>>,signature => [{attribute,1506,spec,{{port_to_list,1},[{type,1506,bounded_fun,[{type,1506,'fun',[{type,1506,product,[{var,1506,'Port'}]},{type,1506,string,[]}]},[{type,1507,constraint,[{atom,1507,is_subtype},[{var,1507,'Port'},{type,1507,port,[]}]]}]]}]}}]}},{{function,ports,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1512}],[<<112,111,114,116,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,97,108,108,32,116,104,101,32,112,111,114,116,115,32,101,120,105,115,116,105,110,103,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,32,101,120,105,116,105,110,103,32,112,111,114,116,32,101,120,105,115,116,115,44,32,98,117,116,32,105,115,32,110,111,116,32,111,112,101,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,53,55>>,signature => [{attribute,1512,spec,{{erlang,ports,0},[{type,1512,'fun',[{type,1512,product,[]},{type,1512,list,[{type,1512,port,[]}]}]}]}}]}},{{function,pre_loaded,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1658}],[<<112,114,101,95,108,111,97,100,101,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,69,114,108,97,110,103,32,109,111,100,117,108,101,115,32,116,104,97,116,32,97,114,101,32,112,114,101,108,111,97,100,101,100,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,65,115,32,97,108,108,32,108,111,97,100,105,110,103,32,111,102,32,99,111,100,101,32,105,115,32,100,111,110,101,32,116,104,114,111,117,103,104,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,44,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,109,117,115,116,32,104,97,118,101,32,98,101,101,110,32,108,111,97,100,101,100,32,112,114,101,118,105,111,117,115,108,121,46,32,72,101,110,99,101,44,32,97,116,32,108,101,97,115,116,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<105,110,105,116>>]},<<32,109,117,115,116,32,98,101,32,112,114,101,108,111,97,100,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,54,55>>,signature => [{attribute,1658,spec,{{pre_loaded,0},[{type,1658,'fun',[{type,1658,product,[]},{type,1658,list,[{type,1658,module,[]}]}]}]}}]}},{{function,process_display,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1663}],[<<112,114,111,99,101,115,115,95,100,105,115,112,108,97,121,47,50>>],#{<<101,110>> => [{p,[],[<<87,114,105,116,101,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<32,111,110,32,115,116,97,110,100,97,114,100,32,101,114,114,111,114,46,32,84,104,101,32,111,110,108,121,32,97,108,108,111,119,101,100,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<98,97,99,107,116,114,97,99,101>>]},<<44,32,119,104,105,99,104,32,115,104,111,119,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,44,32,105,110,99,108,117,100,105,110,103,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,97,108,108,32,99,104,97,105,110,44,32,119,105,116,104,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,112,114,105,110,116,101,100,32,102,105,114,115,116,46,32,84,104,101,32,102,111,114,109,97,116,32,111,102,32,116,104,101,32,111,117,116,112,117,116,32,105,115,32,110,111,116,32,102,117,114,116,104,101,114,32,100,101,102,105,110,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,55,56>>,signature => [{attribute,1663,spec,{{erlang,process_display,2},[{type,1663,bounded_fun,[{type,1663,'fun',[{type,1663,product,[{var,1663,'Pid'},{var,1663,'Type'}]},{atom,1663,true}]},[{type,1664,constraint,[{atom,1664,is_subtype},[{var,1664,'Pid'},{type,1664,pid,[]}]]},{type,1665,constraint,[{atom,1665,is_subtype},[{var,1665,'Type'},{atom,1665,backtrace}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<87,104,101,110,32>>,{code,[],[<<116,114,97,112,95,101,120,105,116>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,101,120,105,116,32,115,105,103,110,97,108,115,32,97,114,114,105,118,105,110,103,32,116,111,32,97,32,112,114,111,99,101,115,115,32,97,114,101,32,99,111,110,118,101,114,116,101,100,32,116,111,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,82,101,97,115,111,110,125>>]},<<32,109,101,115,115,97,103,101,115,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,114,101,99,101,105,118,101,100,32,97,115,32,111,114,100,105,110,97,114,121,32,109,101,115,115,97,103,101,115,46,32,73,102,32>>,{code,[],[<<116,114,97,112,95,101,120,105,116>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,32,105,102,32,105,116,32,114,101,99,101,105,118,101,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,111,116,104,101,114,32,116,104,97,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,112,114,111,112,97,103,97,116,101,100,32,116,111,32,105,116,115,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,46,32,65,112,112,108,105,99,97,116,105,111,110,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,110,111,114,109,97,108,108,121,32,110,111,116,32,116,111,32,116,114,97,112,32,101,120,105,116,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,120,105,116,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,57,50>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2356,bounded_fun,[{type,2356,'fun',[{type,2356,product,[{atom,2356,trap_exit},{var,2356,'Boolean'}]},{var,2356,'OldBoolean'}]},[{type,2357,constraint,[{atom,2357,is_subtype},[{var,2357,'Boolean'},{type,2357,boolean,[]}]]},{type,2358,constraint,[{atom,2358,is_subtype},[{var,2358,'OldBoolean'},{type,2358,boolean,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<85,115,101,100,32,98,121,32,97,32,112,114,111,99,101,115,115,32,116,111,32,114,101,100,101,102,105,110,101,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,102,111,114,32,117,110,100,101,102,105,110,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,110,100,32,117,110,100,101,102,105,110,101,100,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,101,115,46,32,73,110,101,120,112,101,114,105,101,110,99,101,100,32,117,115,101,114,115,32,97,114,101,32,110,111,116,32,116,111,32,117,115,101,32,116,104,105,115,32,102,108,97,103,44,32,97,115,32,99,111,100,101,32,97,117,116,111,45,108,111,97,100,105,110,103,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,99,111,114,114,101,99,116,32,111,112,101,114,97,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103,32,109,111,100,117,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,48,57>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2359,bounded_fun,[{type,2359,'fun',[{type,2359,product,[{atom,2359,error_handler},{var,2359,'Module'}]},{var,2359,'OldModule'}]},[{type,2360,constraint,[{atom,2360,is_subtype},[{var,2360,'Module'},{type,2360,atom,[]}]]},{type,2361,constraint,[{atom,2361,is_subtype},[{var,2361,'OldModule'},{type,2361,atom,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,50,51>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2362,bounded_fun,[{type,2362,'fun',[{type,2362,product,[{atom,2362,min_heap_size},{var,2362,'MinHeapSize'}]},{var,2362,'OldMinHeapSize'}]},[{type,2363,constraint,[{atom,2363,is_subtype},[{var,2363,'MinHeapSize'},{type,2363,non_neg_integer,[]}]]},{type,2364,constraint,[{atom,2364,is_subtype},[{var,2364,'OldMinHeapSize'},{type,2364,non_neg_integer,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,51,52>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2365,bounded_fun,[{type,2365,'fun',[{type,2365,product,[{atom,2365,min_bin_vheap_size},{var,2365,'MinBinVHeapSize'}]},{var,2365,'OldMinBinVHeapSize'}]},[{type,2366,constraint,[{atom,2366,is_subtype},[{var,2366,'MinBinVHeapSize'},{type,2366,non_neg_integer,[]}]]},{type,2367,constraint,[{atom,2367,is_subtype},[{var,2367,'OldMinBinVHeapSize'},{type,2367,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,51,66,48,52>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]}]},{p,[],[<<84,104,105,115,32,102,108,97,103,32,115,101,116,115,32,116,104,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<77,97,120,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<107,105,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,114,111,114,95,108,111,103,103,101,114>>]},<<32,97,114,101,32,117,115,101,100,46>>]},{dl,[],[{dt,[],[{code,[],[<<115,105,122,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,115,105,122,101,32,105,110,32,119,111,114,100,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,73,102,32,115,101,116,32,116,111,32,122,101,114,111,44,32,116,104,101,32,104,101,97,112,32,115,105,122,101,32,108,105,109,105,116,32,105,115,32,100,105,115,97,98,108,101,100,46,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,115,32,98,101,32,116,104,114,111,119,110,32,105,102,32,116,104,101,32,118,97,108,117,101,32,105,115,32,115,109,97,108,108,101,114,32,116,104,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,105,110,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]}]},<<46,32,84,104,101,32,115,105,122,101,32,99,104,101,99,107,32,105,115,32,111,110,108,121,32,100,111,110,101,32,119,104,101,110,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,116,114,105,103,103,101,114,101,100,46>>]},{p,[],[{code,[],[<<115,105,122,101>>]},<<32,105,115,32,116,104,101,32,101,110,116,105,114,101,32,104,101,97,112,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,119,104,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,116,114,105,103,103,101,114,101,100,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,97,108,108,32,103,101,110,101,114,97,116,105,111,110,97,108,32,104,101,97,112,115,44,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,44,32,97,110,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,101,115,115,97,103,101,115,32,116,104,97,116,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,104,101,97,112>>]},<<44,32,97,110,100,32,97,110,121,32,101,120,116,114,97,32,109,101,109,111,114,121,32,116,104,97,116,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,111,114,32,110,101,101,100,115,32,100,117,114,105,110,103,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[{code,[],[<<115,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,95,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,112,114,111,99,101,115,115,95,105,110,102,111,40,80,105,100,44,32,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101,41>>]}]},<<44,32,111,114,32,98,121,32,97,100,100,105,110,103,32>>,{code,[],[<<104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<111,108,100,95,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<32,97,110,100,32>>,{code,[],[<<109,98,117,102,95,115,105,122,101>>]},<<32,102,114,111,109,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,112,114,111,99,101,115,115,95,105,110,102,111,40,80,105,100,44,32,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<107,105,108,108>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,101,110,100,115,32,97,110,32,117,110,116,114,97,112,112,97,98,108,101,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,102,32,116,104,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,105,115,32,114,101,97,99,104,101,100,46,32,84,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,116,104,97,116,32,116,114,105,103,103,101,114,101,100,32,116,104,101,32>>,{code,[],[<<107,105,108,108>>]},<<32,105,115,32,110,111,116,32,99,111,109,112,108,101,116,101,100,44,32,105,110,115,116,101,97,100,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,32,97,115,32,115,111,111,110,32,97,115,32,112,111,115,115,105,98,108,101,46,32,87,104,101,110,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,110,111,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,44,32,105,110,115,116,101,97,100,32,105,116,32,99,111,110,116,105,110,117,101,115,32,101,120,101,99,117,116,105,110,103,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<107,105,108,108>>]},<<32,105,115,32,110,111,116,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,109,97,112,44,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,119,105,108,108,32,98,101,32,117,115,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,101,105,116,104,101,114,32,111,112,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<43,104,109,97,120,107>>]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<101,114,114,111,114,95,108,111,103,103,101,114>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,108,111,103,115,32,97,110,32,101,114,114,111,114,32,101,118,101,110,116,32,118,105,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,108,111,103,103,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,103,103,101,114>>]}]},<<44,32,99,111,110,116,97,105,110,105,110,103,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,119,104,101,110,32,116,104,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,105,115,32,114,101,97,99,104,101,100,46,32,79,110,101,32,108,111,103,32,101,118,101,110,116,32,105,115,32,115,101,110,116,32,101,97,99,104,32,116,105,109,101,32,116,104,101,32,108,105,109,105,116,32,105,115,32,114,101,97,99,104,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<101,114,114,111,114,95,108,111,103,103,101,114>>]},<<32,105,115,32,110,111,116,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,109,97,112,44,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,105,115,32,117,115,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,101,105,116,104,101,114,32,116,104,101,32,111,112,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<43,104,109,97,120,101,108>>]},<<32,105,110,116,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46>>]}]}]},{p,[],[<<84,104,101,32,104,101,97,112,32,115,105,122,101,32,111,102,32,97,32,112,114,111,99,101,115,115,32,105,115,32,113,117,105,116,101,32,104,97,114,100,32,116,111,32,112,114,101,100,105,99,116,44,32,101,115,112,101,99,105,97,108,108,121,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,116,104,97,116,32,105,115,32,117,115,101,100,32,100,117,114,105,110,103,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,104,101,110,32,99,111,110,116,101,109,112,108,97,116,105,110,103,32,117,115,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,102,105,114,115,116,32,114,117,110,32,105,116,32,105,110,32,112,114,111,100,117,99,116,105,111,110,32,119,105,116,104,32>>,{code,[],[<<107,105,108,108>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,97,110,100,32,105,110,115,112,101,99,116,32,116,104,101,32,108,111,103,32,101,118,101,110,116,115,32,116,111,32,115,101,101,32,119,104,97,116,32,116,104,101,32,110,111,114,109,97,108,32,112,101,97,107,32,115,105,122,101,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,105,115,32,97,110,100,32,116,104,101,110,32,116,117,110,101,32,116,104,101,32,118,97,108,117,101,32,97,99,99,111,114,100,105,110,103,108,121,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,52,53>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2368,bounded_fun,[{type,2368,'fun',[{type,2368,product,[{atom,2368,max_heap_size},{var,2368,'MaxHeapSize'}]},{var,2368,'OldMaxHeapSize'}]},[{type,2369,constraint,[{atom,2369,is_subtype},[{var,2369,'MaxHeapSize'},{user_type,2369,max_heap_size,[]}]]},{type,2370,constraint,[{atom,2370,is_subtype},[{var,2370,'OldMaxHeapSize'},{user_type,2370,max_heap_size,[]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]}]},{p,[],[<<84,104,105,115,32,102,108,97,103,32,100,101,116,101,114,109,105,110,101,115,32,104,111,119,32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,114,101,32,115,116,111,114,101,100,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<111,102,102,95,104,101,97,112>>]}]},{dd,[],[{p,[],[{em,[],[<<65,108,108>>]},<<32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,98,101,32,115,116,111,114,101,100,32,111,117,116,115,105,100,101,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,104,101,97,112,46,32,84,104,105,115,32,105,109,112,108,105,101,115,32,116,104,97,116,32>>,{em,[],[<<110,111>>]},<<32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,98,101,32,112,97,114,116,32,111,102,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<111,110,95,104,101,97,112>>]}]},{dd,[],[{p,[],[<<65,108,108,32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,101,118,101,110,116,117,97,108,108,121,32,98,101,32,112,108,97,99,101,100,32,111,110,32,104,101,97,112,46,32,84,104,101,121,32,99,97,110,32,104,111,119,101,118,101,114,32,116,101,109,112,111,114,97,114,105,108,121,32,98,101,32,115,116,111,114,101,100,32,111,102,102,32,104,101,97,112,46,32,84,104,105,115,32,105,115,32,104,111,119,32,109,101,115,115,97,103,101,115,32,97,108,119,97,121,115,32,104,97,118,101,32,98,101,101,110,32,115,116,111,114,101,100,32,117,112,32,117,110,116,105,108,32,69,82,84,83,32,56,46,48,46>>]}]}]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,113,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,113,100>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,112,111,116,101,110,116,105,97,108,108,121,32,99,97,110,32,103,101,116,32,109,97,110,121,32,109,101,115,115,97,103,101,115,32,105,110,32,105,116,115,32,113,117,101,117,101,44,32,121,111,117,32,97,114,101,32,97,100,118,105,115,101,100,32,116,111,32,115,101,116,32,116,104,101,32,102,108,97,103,32,116,111,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<46,32,84,104,105,115,32,98,101,99,97,117,115,101,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,119,105,116,104,32,109,97,110,121,32,109,101,115,115,97,103,101,115,32,112,108,97,99,101,100,32,111,110,32,116,104,101,32,104,101,97,112,32,99,97,110,32,98,101,99,111,109,101,32,101,120,116,114,101,109,101,108,121,32,101,120,112,101,110,115,105,118,101,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,110,32,99,111,110,115,117,109,101,32,108,97,114,103,101,32,97,109,111,117,110,116,115,32,111,102,32,109,101,109,111,114,121,46,32,80,101,114,102,111,114,109,97,110,99,101,32,111,102,32,116,104,101,32,97,99,116,117,97,108,32,109,101,115,115,97,103,101,32,112,97,115,115,105,110,103,32,105,115,32,104,111,119,101,118,101,114,32,103,101,110,101,114,97,108,108,121,32,98,101,116,116,101,114,32,119,104,101,110,32,110,111,116,32,117,115,105,110,103,32,102,108,97,103,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<46>>]},{p,[],[<<87,104,101,110,32,99,104,97,110,103,105,110,103,32,116,104,105,115,32,102,108,97,103,32,109,101,115,115,97,103,101,115,32,119,105,108,108,32,98,101,32,109,111,118,101,100,46,32,84,104,105,115,32,119,111,114,107,32,104,97,115,32,98,101,101,110,32,105,110,105,116,105,97,116,101,100,32,98,117,116,32,110,111,116,32,99,111,109,112,108,101,116,101,100,32,119,104,101,110,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,114,101,116,117,114,110,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,54,49,57>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2371,bounded_fun,[{type,2371,'fun',[{type,2371,product,[{atom,2371,message_queue_data},{var,2371,'MQD'}]},{var,2371,'OldMQD'}]},[{type,2372,constraint,[{atom,2372,is_subtype},[{var,2372,'MQD'},{user_type,2372,message_queue_data,[]}]]},{type,2373,constraint,[{atom,2373,is_subtype},[{var,2373,'OldMQD'},{user_type,2373,message_queue_data,[]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,112,114,105,111,114,105,116,121,46,32>>,{code,[],[<<76,101,118,101,108>>]},<<32,105,115,32,97,110,32,97,116,111,109,46,32,70,111,117,114,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,115,32,101,120,105,115,116,58,32>>,{code,[],[<<108,111,119>>]},<<44,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<44,32>>,{code,[],[<<104,105,103,104>>]},<<44,32,97,110,100,32>>,{code,[],[<<109,97,120>>]},<<46,32,68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<80,114,105,111,114,105,116,121,32,108,101,118,101,108,32>>,{code,[],[<<109,97,120>>]},<<32,105,115,32,114,101,115,101,114,118,101,100,32,102,111,114,32,105,110,116,101,114,110,97,108,32,117,115,101,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,44,32,97,110,100,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,98,101,32,117,115,101,100,32,98,121,32,111,116,104,101,114,115,46>>]}]},{p,[],[<<73,110,116,101,114,110,97,108,108,121,32,105,110,32,101,97,99,104,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,44,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,115,99,104,101,100,117,108,101,100,32,105,110,32,97,32,114,111,117,110,100,32,114,111,98,105,110,32,102,97,115,104,105,111,110,46>>]},{p,[],[<<69,120,101,99,117,116,105,111,110,32,111,102,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32>>,{code,[],[<<108,111,119>>]},<<32,97,114,101,32,105,110,116,101,114,108,101,97,118,101,100,46,32,80,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<32,97,114,101,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,32,108,101,115,115,32,102,114,101,113,117,101,110,116,108,121,32,116,104,97,110,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{p,[],[<<87,104,101,110,32,114,117,110,110,97,98,108,101,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<32,101,120,105,115,116,44,32,110,111,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<32,111,114,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,114,101,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,46,32,78,111,116,105,99,101,32,104,111,119,101,118,101,114,32,116,104,97,116,32,116,104,105,115,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,109,101,97,110,32,116,104,97,116,32,110,111,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<32,111,114,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,99,97,110,32,114,117,110,32,119,104,101,110,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,114,117,110,110,105,110,103,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<46,32,87,104,101,110,32,117,115,105,110,103,32,109,117,108,116,105,112,108,101,32,115,99,104,101,100,117,108,101,114,115,44,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,32,99,97,110,32,98,101,32,114,117,110,110,105,110,103,32,105,110,32,112,97,114,97,108,108,101,108,32,116,104,97,110,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<46,32,84,104,97,116,32,105,115,44,32,97,32>>,{code,[],[<<108,111,119>>]},<<32,97,110,100,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,99,97,110,32,101,120,101,99,117,116,101,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46>>]},{p,[],[<<87,104,101,110,32,114,117,110,110,97,98,108,101,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<109,97,120>>]},<<32,101,120,105,115,116,44,32,110,111,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<44,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<44,32,111,114,32>>,{code,[],[<<104,105,103,104>>]},<<32,97,114,101,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,46,32,65,115,32,119,105,116,104,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<44,32,112,114,111,99,101,115,115,101,115,32,111,110,32,108,111,119,101,114,32,112,114,105,111,114,105,116,105,101,115,32,99,97,110,32,101,120,101,99,117,116,101,32,105,110,32,112,97,114,97,108,108,101,108,32,119,105,116,104,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<109,97,120>>]},<<46>>]},{p,[],[<<83,99,104,101,100,117,108,105,110,103,32,105,115,32,112,114,101,45,101,109,112,116,105,118,101,46,32,82,101,103,97,114,100,108,101,115,115,32,111,102,32,112,114,105,111,114,105,116,121,44,32,97,32,112,114,111,99,101,115,115,32,105,115,32,112,114,101,45,101,109,112,116,101,100,32,119,104,101,110,32,105,116,32,104,97,115,32,99,111,110,115,117,109,101,100,32,109,111,114,101,32,116,104,97,110,32,97,32,99,101,114,116,97,105,110,32,110,117,109,98,101,114,32,111,102,32,114,101,100,117,99,116,105,111,110,115,32,115,105,110,99,101,32,116,104,101,32,108,97,115,116,32,116,105,109,101,32,105,116,32,119,97,115,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<68,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,115,99,104,101,100,117,108,105,110,103,32,116,111,32,114,101,109,97,105,110,32,101,120,97,99,116,108,121,32,97,115,32,105,116,32,105,115,32,116,111,100,97,121,46,32,83,99,104,101,100,117,108,105,110,103,32,105,115,32,108,105,107,101,108,121,32,116,111,32,98,101,32,99,104,97,110,103,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,32,116,111,32,117,115,101,32,97,118,97,105,108,97,98,108,101,32,112,114,111,99,101,115,115,111,114,32,99,111,114,101,115,32,98,101,116,116,101,114,46>>]}]},{p,[],[<<84,104,101,114,101,32,105,115,32>>,{em,[],[<<110,111>>]},<<32,97,117,116,111,109,97,116,105,99,32,109,101,99,104,97,110,105,115,109,32,102,111,114,32,97,118,111,105,100,105,110,103,32,112,114,105,111,114,105,116,121,32,105,110,118,101,114,115,105,111,110,44,32,115,117,99,104,32,97,115,32,112,114,105,111,114,105,116,121,32,105,110,104,101,114,105,116,97,110,99,101,32,111,114,32,112,114,105,111,114,105,116,121,32,99,101,105,108,105,110,103,115,46,32,87,104,101,110,32,117,115,105,110,103,32,112,114,105,111,114,105,116,105,101,115,44,32,116,97,107,101,32,116,104,105,115,32,105,110,116,111,32,97,99,99,111,117,110,116,32,97,110,100,32,104,97,110,100,108,101,32,115,117,99,104,32,115,99,101,110,97,114,105,111,115,32,98,121,32,121,111,117,114,115,101,108,102,46>>]},{p,[],[<<77,97,107,105,110,103,32,99,97,108,108,115,32,102,114,111,109,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,105,110,116,111,32,99,111,100,101,32,116,104,97,116,32,121,111,117,32,104,97,115,32,110,111,32,99,111,110,116,114,111,108,32,111,118,101,114,32,99,97,110,32,99,97,117,115,101,32,116,104,101,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,116,111,32,119,97,105,116,32,102,111,114,32,97,32,112,114,111,99,101,115,115,32,119,105,116,104,32,108,111,119,101,114,32,112,114,105,111,114,105,116,121,46,32,84,104,97,116,32,105,115,44,32,101,102,102,101,99,116,105,118,101,108,121,32,100,101,99,114,101,97,115,105,110,103,32,116,104,101,32,112,114,105,111,114,105,116,121,32,111,102,32,116,104,101,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,100,117,114,105,110,103,32,116,104,101,32,99,97,108,108,46,32,69,118,101,110,32,105,102,32,116,104,105,115,32,105,115,32,110,111,116,32,116,104,101,32,99,97,115,101,32,119,105,116,104,32,111,110,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,99,111,100,101,32,116,104,97,116,32,121,111,117,32,104,97,118,101,32,110,111,32,99,111,110,116,114,111,108,32,111,118,101,114,44,32,105,116,32,99,97,110,32,98,101,32,116,104,101,32,99,97,115,101,32,105,110,32,97,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,32,111,102,32,105,116,46,32,84,104,105,115,32,99,97,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,111,99,99,117,114,32,105,102,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,116,114,105,103,103,101,114,115,32,99,111,100,101,32,108,111,97,100,105,110,103,44,32,97,115,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,114,117,110,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{p,[],[<<79,116,104,101,114,32,112,114,105,111,114,105,116,105,101,115,32,116,104,97,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,114,101,32,110,111,114,109,97,108,108,121,32,110,111,116,32,110,101,101,100,101,100,46,32,87,104,101,110,32,111,116,104,101,114,32,112,114,105,111,114,105,116,105,101,115,32,97,114,101,32,117,115,101,100,44,32,117,115,101,32,116,104,101,109,32,119,105,116,104,32,99,97,114,101,44,32>>,{em,[],[<<101,115,112,101,99,105,97,108,108,121>>]},<<32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<46,32,65,32,112,114,111,99,101,115,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<32,105,115,32,111,110,108,121,32,116,111,32,112,101,114,102,111,114,109,32,119,111,114,107,32,102,111,114,32,115,104,111,114,116,32,112,101,114,105,111,100,115,46,32,66,117,115,121,32,108,111,111,112,105,110,103,32,102,111,114,32,108,111,110,103,32,112,101,114,105,111,100,115,32,105,110,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,99,97,117,115,101,115,32,109,111,115,116,32,108,105,107,101,108,121,32,112,114,111,98,108,101,109,115,44,32,97,115,32,105,109,112,111,114,116,97,110,116,32,79,84,80,32,115,101,114,118,101,114,115,32,114,117,110,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,54,54,49>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2374,bounded_fun,[{type,2374,'fun',[{type,2374,product,[{atom,2374,priority},{var,2374,'Level'}]},{var,2374,'OldLevel'}]},[{type,2375,constraint,[{atom,2375,is_subtype},[{var,2375,'Level'},{user_type,2375,priority_level,[]}]]},{type,2376,constraint,[{atom,2376,is_subtype},[{var,2376,'OldLevel'},{user_type,2376,priority_level,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<78>>]},<<32,109,117,115,116,32,98,101,32,97,110,32,105,110,116,101,103,101,114,32,105,110,32,116,104,101,32,105,110,116,101,114,118,97,108,32,48,46,46,49,48,48,48,48,46,32,73,102,32>>,{code,[],[<<78>>]},<<32,62,32,48,44,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,109,97,100,101,32,97,99,116,105,118,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<78>>]},<<32,109,111,115,116,32,114,101,99,101,110,116,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32,66,73,70,32,99,97,108,108,115,44,32,115,101,110,100,115,44,32,97,110,100,32,114,101,99,101,105,118,101,115,32,109,97,100,101,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,97,114,101,32,115,97,118,101,100,32,105,110,32,97,32,108,105,115,116,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,119,105,116,104,32>>,{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,40,80,105,100,44,32,108,97,115,116,95,99,97,108,108,115,41>>]},<<46,32,65,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,105,115,32,111,110,101,32,105,110,32,119,104,105,99,104,32,116,104,101,32,109,111,100,117,108,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,109,101,110,116,105,111,110,101,100,46,32,79,110,108,121,32,97,32,102,105,120,101,100,32,97,109,111,117,110,116,32,111,102,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,115,97,118,101,100,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{ul,[],[{li,[],[{p,[],[<<65,32,116,117,112,108,101,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<32,102,111,114,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115>>]}]},{li,[],[{p,[],[<<84,104,101,32,97,116,111,109,115,32>>,{code,[],[<<115,101,110,100>>]},<<44,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<44,32,97,110,100,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,102,111,114,32,115,101,110,100,115,32,97,110,100,32,114,101,99,101,105,118,101,115,32,40>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,119,104,101,110,32,97,32,109,101,115,115,97,103,101,32,105,115,32,114,101,99,101,105,118,101,100,32,97,110,100,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,119,104,101,110,32,97,32,114,101,99,101,105,118,101,32,116,105,109,101,115,32,111,117,116,41>>]}]}]},{p,[],[<<73,102,32>>,{code,[],[<<78>>]},<<32,61,32,48,44,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,100,105,115,97,98,108,101,100,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46,32,87,104,101,110,101,118,101,114,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,99,97,108,108,32,115,97,118,105,110,103,32,108,105,115,116,32,105,115,32,115,101,116,44,32,105,116,115,32,99,111,110,116,101,110,116,115,32,97,114,101,32,114,101,115,101,116,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,51,52>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2377,bounded_fun,[{type,2377,'fun',[{type,2377,product,[{atom,2377,save_calls},{var,2377,'N'}]},{var,2377,'OldN'}]},[{type,2378,constraint,[{atom,2378,is_subtype},[{var,2378,'N'},{type,2378,range,[{integer,2378,0},{integer,2378,10000}]}]]},{type,2379,constraint,[{atom,2379,is_subtype},[{var,2379,'OldN'},{type,2379,range,[{integer,2379,0},{integer,2379,10000}]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2356}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,111,114,32,99,108,101,97,114,115,32,102,108,97,103,32>>,{code,[],[<<115,101,110,115,105,116,105,118,101>>]},<<32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46,32,87,104,101,110,32,97,32,112,114,111,99,101,115,115,32,104,97,115,32,98,101,101,110,32,109,97,114,107,101,100,32,97,115,32,115,101,110,115,105,116,105,118,101,32,98,121,32,99,97,108,108,105,110,103,32>>,{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,115,101,110,115,105,116,105,118,101,44,32,116,114,117,101,41>>]},<<44,32,102,101,97,116,117,114,101,115,32,105,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,101,120,97,109,105,110,105,110,103,32,116,104,101,32,100,97,116,97,32,111,114,32,105,110,110,101,114,32,119,111,114,107,105,110,103,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,97,114,101,32,115,105,108,101,110,116,108,121,32,100,105,115,97,98,108,101,100,46>>]},{p,[],[<<70,101,97,116,117,114,101,115,32,116,104,97,116,32,97,114,101,32,100,105,115,97,98,108,101,100,32,105,110,99,108,117,100,101,32,40,98,117,116,32,97,114,101,32,110,111,116,32,108,105,109,105,116,101,100,32,116,111,41,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{p,[],[<<84,114,97,99,105,110,103,46,32,84,114,97,99,101,32,102,108,97,103,115,32,99,97,110,32,115,116,105,108,108,32,98,101,32,115,101,116,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,98,117,116,32,110,111,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,111,102,32,97,110,121,32,107,105,110,100,32,97,114,101,32,103,101,110,101,114,97,116,101,100,46,32,40,73,102,32,102,108,97,103,32>>,{code,[],[<<115,101,110,115,105,116,105,118,101>>]},<<32,105,115,32,116,117,114,110,101,100,32,111,102,102,44,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,97,103,97,105,110,32,103,101,110,101,114,97,116,101,100,32,105,102,32,97,110,121,32,116,114,97,99,101,32,102,108,97,103,115,32,97,114,101,32,115,101,116,46,41>>]}]},{li,[],[{p,[],[<<83,101,113,117,101,110,116,105,97,108,32,116,114,97,99,105,110,103,46,32,84,104,101,32,115,101,113,117,101,110,116,105,97,108,32,116,114,97,99,101,32,116,111,107,101,110,32,105,115,32,112,114,111,112,97,103,97,116,101,100,32,97,115,32,117,115,117,97,108,44,32,98,117,116,32,110,111,32,115,101,113,117,101,110,116,105,97,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,103,101,110,101,114,97,116,101,100,46>>]}]}]},{p,[],[{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,49,44,50>>]},<<32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,32,116,111,32,114,101,97,100,32,111,117,116,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,40,98,111,116,104,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,101,109,112,116,121,32,108,105,115,116,115,41,46>>]},{p,[],[<<83,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,115,32,99,97,110,110,111,116,32,98,101,32,100,105,115,112,108,97,121,101,100,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,110,32,99,114,97,115,104,32,100,117,109,112,115,44,32,116,104,101,32,115,116,97,99,107,44,32,109,101,115,115,97,103,101,115,44,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,97,114,101,32,111,109,105,116,116,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<123,115,97,118,101,95,99,97,108,108,115,44,78,125>>]},<<32,104,97,115,32,98,101,101,110,32,115,101,116,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,110,111,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,114,101,32,115,97,118,101,100,32,116,111,32,116,104,101,32,99,97,108,108,32,115,97,118,105,110,103,32,108,105,115,116,46,32,40,84,104,101,32,99,97,108,108,32,115,97,118,105,110,103,32,108,105,115,116,32,105,115,32,110,111,116,32,99,108,101,97,114,101,100,46,32,65,108,115,111,44,32,115,101,110,100,44,32,114,101,99,101,105,118,101,44,32,97,110,100,32,116,105,109,101,45,111,117,116,32,101,118,101,110,116,115,32,97,114,101,32,115,116,105,108,108,32,97,100,100,101,100,32,116,111,32,116,104,101,32,108,105,115,116,46,41>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,54,53>>,signature => [{attribute,2356,spec,{{process_flag,2},[{type,2380,bounded_fun,[{type,2380,'fun',[{type,2380,product,[{atom,2380,sensitive},{var,2380,'Boolean'}]},{var,2380,'OldBoolean'}]},[{type,2381,constraint,[{atom,2381,is_subtype},[{var,2381,'Boolean'},{type,2381,boolean,[]}]]},{type,2382,constraint,[{atom,2382,is_subtype},[{var,2382,'OldBoolean'},{type,2382,boolean,[]}]]}]]}]}}]}},{{function,process_flag,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1685}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,99,101,114,116,97,105,110,32,102,108,97,103,115,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<44,32,105,110,32,116,104,101,32,115,97,109,101,32,109,97,110,110,101,114,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46,32,82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46,32,84,104,101,32,118,97,108,105,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<70,108,97,103>>]},<<32,97,114,101,32,111,110,108,121,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,111,115,101,32,97,108,108,111,119,101,100,32,105,110,32>>,{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]},<<44,32,110,97,109,101,108,121,32>>,{code,[],[<<115,97,118,101,95,99,97,108,108,115>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,57,57>>,signature => [{attribute,1685,spec,{{process_flag,3},[{type,1685,bounded_fun,[{type,1685,'fun',[{type,1685,product,[{var,1685,'Pid'},{var,1685,'Flag'},{var,1685,'Value'}]},{var,1685,'OldValue'}]},[{type,1686,constraint,[{atom,1686,is_subtype},[{var,1686,'Pid'},{type,1686,pid,[]}]]},{type,1687,constraint,[{atom,1687,is_subtype},[{var,1687,'Flag'},{atom,1687,save_calls}]]},{type,1688,constraint,[{atom,1688,is_subtype},[{var,1688,'Value'},{type,1688,non_neg_integer,[]}]]},{type,1689,constraint,[{atom,1689,is_subtype},[{var,1689,'OldValue'},{type,1689,non_neg_integer,[]}]]}]]}]}}]}},{{function,process_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1702}],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<112,114,111,99,101,115,115,95,105,110,102,111,95,114,101,115,117,108,116,95,105,116,101,109>>}],[]},{li,[{name,<<115,116,97,99,107,95,105,116,101,109>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,119,105,116,104,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]},{p,[],[<<84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,105,115,32,117,110,100,101,102,105,110,101,100,32,97,110,100,32,97,108,108,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,97,114,101,32,110,111,116,32,109,97,110,100,97,116,111,114,121,46,32,84,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,119,105,116,104,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,116,101,109,115,32,97,114,101,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,58>>]},{ul,[],[{li,[],[{code,[],[<<99,117,114,114,101,110,116,95,102,117,110,99,116,105,111,110>>]}]},{li,[],[{code,[],[<<105,110,105,116,105,97,108,95,99,97,108,108>>]}]},{li,[],[{code,[],[<<115,116,97,116,117,115>>]}]},{li,[],[{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,108,101,110>>]}]},{li,[],[{code,[],[<<108,105,110,107,115>>]}]},{li,[],[{code,[],[<<100,105,99,116,105,111,110,97,114,121>>]}]},{li,[],[{code,[],[<<116,114,97,112,95,101,120,105,116>>]}]},{li,[],[{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]}]},{li,[],[{code,[],[<<112,114,105,111,114,105,116,121>>]}]},{li,[],[{code,[],[<<103,114,111,117,112,95,108,101,97,100,101,114>>]}]},{li,[],[{code,[],[<<116,111,116,97,108,95,104,101,97,112,95,115,105,122,101>>]}]},{li,[],[{code,[],[<<104,101,97,112,95,115,105,122,101>>]}]},{li,[],[{code,[],[<<115,116,97,99,107,95,115,105,122,101>>]}]},{li,[],[{code,[],[<<114,101,100,117,99,116,105,111,110,115>>]}]},{li,[],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]}]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,104,97,115,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32,97,108,115,111,32,97,110,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,119,105,116,104,32,105,116,101,109,32>>,{code,[],[<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,105,115,32,105,110,99,108,117,100,101,100,46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,112,101,99,105,102,105,99,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,50>>]}]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32>>,{em,[],[<<100,101,98,117,103,103,105,110,103,32,111,110,108,121>>]},<<46,32,70,111,114,32,97,108,108,32,111,116,104,101,114,32,112,117,114,112,111,115,101,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,50>>]}]},<<46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,49,52>>,signature => [{attribute,1702,spec,{{process_info,1},[{type,1702,bounded_fun,[{type,1702,'fun',[{type,1702,product,[{var,1702,'Pid'}]},{var,1702,'Info'}]},[{type,1703,constraint,[{atom,1703,is_subtype},[{var,1703,'Pid'},{type,1703,pid,[]}]]},{type,1704,constraint,[{atom,1704,is_subtype},[{var,1704,'Info'},{type,1704,union,[{type,1704,list,[{var,1704,'InfoTuple'}]},{atom,1704,undefined}]}]]},{type,1705,constraint,[{atom,1705,is_subtype},[{var,1705,'InfoTuple'},{user_type,1705,process_info_result_item,[]}]]}]]}]}}]}},{{function,process_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2479}],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<112,114,111,99,101,115,115,95,105,110,102,111,95,105,116,101,109>>}],[]},{li,[{name,<<112,114,111,99,101,115,115,95,105,110,102,111,95,114,101,115,117,108,116,95,105,116,101,109>>}],[]},{li,[{name,<<115,116,97,99,107,95,105,116,101,109>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<32,111,114,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,108,105,118,101,32,97,110,100,32,97,32,115,105,110,103,108,101,32>>,{code,[],[<<73,116,101,109>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<44,32,117,110,108,101,115,115,32>>,{code,[],[<<73,116,101,109,32,61,58,61,32,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,110,111,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,105,115,32,115,116,114,97,110,103,101,32,98,101,104,97,118,105,111,114,32,105,115,32,98,101,99,97,117,115,101,32,111,102,32,104,105,115,116,111,114,105,99,97,108,32,114,101,97,115,111,110,115,44,32,97,110,100,32,105,115,32,107,101,112,116,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101,76,105,115,116>>]},<<46,32,84,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,105,110,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101,76,105,115,116>>]},<<32,97,114,101,32,105,110,99,108,117,100,101,100,32,119,105,116,104,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,105,110,32,116,104,101,32,115,97,109,101,32,111,114,100,101,114,32,97,115,32,116,104,101,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,119,101,114,101,32,105,110,99,108,117,100,101,100,32,105,110,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<46,32,86,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,99,97,110,32,98,101,32,105,110,99,108,117,100,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,105,110,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32>>,{code,[],[<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,105,115,32,112,97,114,116,32,111,102,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,110,111,32,110,97,109,101,32,114,101,103,105,115,116,101,114,101,100,44,32,97,32>>,{code,[],[<<123,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101,44,32,91,93,125>>]},<<44,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32>>,{em,[],[<<119,105,108,108>>]},<<32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101,76,105,115,116>>]},<<46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,105,115,32,100,105,102,102,101,114,101,110,116,32,119,104,101,110,32,97,32,115,105,110,103,108,101,32>>,{code,[],[<<73,116,101,109,32,61,58,61,32,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,97,110,100,32,119,104,101,110,32>>,{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,49>>]},<<32,105,115,32,117,115,101,100,46>>]}]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,119,105,116,104,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<73,116,101,109>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,98,97,99,107,116,114,97,99,101,44,32,66,105,110,125>>]}]},{dd,[],[{p,[],[<<66,105,110,97,114,121,32>>,{code,[],[<<66,105,110>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,115,32,116,104,101,32,111,117,116,112,117,116,32,102,114,111,109,32>>,{code,[],[<<101,114,108,97,110,103,58,112,114,111,99,101,115,115,95,100,105,115,112,108,97,121,40,80,105,100,44,32,98,97,99,107,116,114,97,99,101,41>>]},<<46,32,85,115,101,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,49>>]},<<32,116,111,32,111,98,116,97,105,110,32,116,104,101,32,115,116,114,105,110,103,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,98,105,110,97,114,121,46>>]}]},{dt,[],[{code,[],[<<123,98,105,110,97,114,121,44,32,66,105,110,73,110,102,111,125>>]}]},{dd,[],[{p,[],[{code,[],[<<66,105,110,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,98,105,110,97,114,105,101,115,32,111,110,32,116,104,101,32,104,101,97,112,32,111,102,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46,32,73,110,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32>>,{code,[],[<<66,105,110,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,46,32,84,104,101,32,116,117,112,108,101,115,32,99,111,110,116,97,105,110,59,32>>,{code,[],[<<66,105,110,97,114,121,73,100>>]},<<44,32>>,{code,[],[<<66,105,110,97,114,121,83,105,122,101>>]},<<44,32>>,{code,[],[<<66,105,110,97,114,121,82,101,102,99,67,111,117,110,116>>]},<<46>>]},{p,[],[<<84,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,105,115,32,111,110,32,116,104,101,32,104,101,97,112,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,99,97,116,99,104,108,101,118,101,108,44,32,67,97,116,99,104,76,101,118,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<67,97,116,99,104,76,101,118,101,108>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,99,117,114,114,101,110,116,108,121,32,97,99,116,105,118,101,32,99,97,116,99,104,101,115,32,105,110,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,114,101,110,116,95,102,117,110,99,116,105,111,110,44,32,123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125,32,124,32,117,110,100,101,102,105,110,101,100,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,101,32,118,97,108,117,101,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,99,117,114,114,101,110,116,108,121,32,101,120,101,99,117,116,105,110,103,32,110,97,116,105,118,101,32,99,111,109,112,105,108,101,100,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,114,101,110,116,95,108,111,99,97,116,105,111,110,44,32,123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,44,32,76,111,99,97,116,105,111,110,125,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,116,117,112,108,101,115,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,108,111,99,97,116,105,111,110,32,105,110,32,116,104,101,32,115,111,117,114,99,101,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,114,101,110,116,95,115,116,97,99,107,116,114,97,99,101,44,32,83,116,97,99,107,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,99,97,108,108,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,32,40>>,{em,[],[<<115,116,97,99,107,116,114,97,99,101>>]},<<41,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,101,32,115,116,97,99,107,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,115,32,105,110,32,116,104,101,32>>,{code,[],[<<99,97,116,99,104>>]},<<32,112,97,114,116,32,111,102,32,97,32>>,{code,[],[<<116,114,121>>]},<<46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115,35,115,116,97,99,107,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<84,104,101,32,99,97,108,108,45,115,116,97,99,107,32,98,97,99,107,32,116,114,97,99,101,32,40,115,116,97,99,107,116,114,97,99,101,41>>]},<<46,32,84,104,101,32,100,101,112,116,104,32,111,102,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,32,105,115,32,116,114,117,110,99,97,116,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32>>,{code,[],[<<98,97,99,107,116,114,97,99,101,95,100,101,112,116,104>>]},<<32,115,121,115,116,101,109,32,102,108,97,103,32,115,101,116,116,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,100,105,99,116,105,111,110,97,114,121,44,32,68,105,99,116,105,111,110,97,114,121,125>>]}]},{dd,[],[{p,[],[{code,[],[<<68,105,99,116,105,111,110,97,114,121>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,95,104,97,110,100,108,101,114,44,32,77,111,100,117,108,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,109,111,100,117,108,101,32,117,115,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,40,102,111,114,32,117,110,100,101,102,105,110,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32,102,111,114,32,101,120,97,109,112,108,101,41,46>>]}]},{dt,[],[{code,[],[<<123,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,44,32,71,67,73,110,102,111,125>>]}]},{dd,[],[{p,[],[{code,[],[<<71,67,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,102,111,114,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,101,32,99,111,110,116,101,110,116,32,111,102,32>>,{code,[],[<<71,67,73,110,102,111>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{a,[{id,<<112,114,111,99,101,115,115,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111>>}],[]},{code,[],[<<123,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111,44,32,71,67,73,110,102,111,125>>]}]},{dd,[],[{p,[],[{code,[],[<<71,67,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,100,101,116,97,105,108,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,102,111,114,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,101,32,99,111,110,116,101,110,116,32,111,102,32>>,{code,[],[<<71,67,73,110,102,111>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46,32,70,111,114,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32,109,101,97,110,105,110,103,32,111,102,32,101,97,99,104,32,105,116,101,109,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]}]},<<32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,103,114,111,117,112,95,108,101,97,100,101,114,44,32,71,114,111,117,112,76,101,97,100,101,114,125>>]}]},{dd,[],[{p,[],[{code,[],[<<71,114,111,117,112,76,101,97,100,101,114>>]},<<32,105,115,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,102,111,114,32,116,104,101,32,73,47,79,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,119,111,114,100,115,32,111,102,32,116,104,101,32,121,111,117,110,103,101,115,116,32,104,101,97,112,32,103,101,110,101,114,97,116,105,111,110,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,103,101,110,101,114,97,116,105,111,110,32,105,110,99,108,117,100,101,115,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,46,32,84,104,105,115,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,44,32,97,110,100,32,99,97,110,32,99,104,97,110,103,101,32,105,102,32,116,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,99,104,97,110,103,101,115,46>>]}]},{dt,[],[{code,[],[<<123,105,110,105,116,105,97,108,95,99,97,108,108,44,32,123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,105,110,105,116,105,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,119,105,116,104,32,119,104,105,99,104,32,116,104,101,32,112,114,111,99,101,115,115,32,119,97,115,32,115,112,97,119,110,101,100,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,107,115,44,32,80,105,100,115,65,110,100,80,111,114,116,115,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,105,100,115,65,110,100,80,111,114,116,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,32,97,110,100,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,44,32,119,105,116,104,32,112,114,111,99,101,115,115,101,115,32,111,114,32,112,111,114,116,115,32,116,111,32,119,104,105,99,104,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,97,32,108,105,110,107,46>>]}]},{dt,[],[{code,[],[<<123,108,97,115,116,95,99,97,108,108,115,44,32,102,97,108,115,101,124,67,97,108,108,115,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,110,111,116,32,97,99,116,105,118,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,51>>]}]},<<41,46,32,73,102,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,97,99,116,105,118,101,44,32,97,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,44,32,105,110,32,119,104,105,99,104,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,99,97,108,108,101,100,46>>]}]},{dt,[],[{code,[],[<<123,109,101,109,111,114,121,44,32,83,105,122,101,125>>]}]},{dd,[],[{a,[{id,<<112,114,111,99,101,115,115,95,105,110,102,111,95,109,101,109,111,114,121>>}],[]},{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,121,116,101,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,99,97,108,108,32,115,116,97,99,107,44,32,104,101,97,112,44,32,97,110,100,32,105,110,116,101,114,110,97,108,32,115,116,114,117,99,116,117,114,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,95,113,117,101,117,101,95,108,101,110,44,32,77,101,115,115,97,103,101,81,117,101,117,101,76,101,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,101,115,115,97,103,101,81,117,101,117,101,76,101,110>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,109,101,115,115,97,103,101,115,32,99,117,114,114,101,110,116,108,121,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<77,101,115,115,97,103,101,81,117,101,117,101>>]},<<32,114,101,116,117,114,110,101,100,32,97,115,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,116,101,109,32>>,{code,[],[<<109,101,115,115,97,103,101,115>>]},<<32,40,115,101,101,32,98,101,108,111,119,41,46>>]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,115,44,32,77,101,115,115,97,103,101,81,117,101,117,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,101,115,115,97,103,101,81,117,101,117,101>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,44,32,119,104,105,99,104,32,104,97,118,101,32,110,111,116,32,121,101,116,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,109,105,110,95,104,101,97,112,95,115,105,122,101,44,32,77,105,110,72,101,97,112,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,105,110,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101,44,32,77,105,110,66,105,110,86,72,101,97,112,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,105,110,66,105,110,86,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,101,100,95,98,121,44,32,77,111,110,105,116,111,114,101,100,66,121,125>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,105,100,101,110,116,105,102,105,101,114,115,32,102,111,114,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,44,32,112,111,114,116,115,32,97,110,100,32,78,73,70,32,114,101,115,111,117,114,99,101,115,44,32,116,104,97,116,32,97,114,101,32,109,111,110,105,116,111,114,105,110,103,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,115,44,32,77,111,110,105,116,111,114,115,125>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,111,110,105,116,111,114,115,32,40,115,116,97,114,116,101,100,32,98,121,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<41,32,116,104,97,116,32,97,114,101,32,97,99,116,105,118,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,70,111,114,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,32,111,114,32,97,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,32,98,121,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,116,104,101,32,108,105,115,116,32,99,111,110,115,105,115,116,115,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,114,111,99,101,115,115,44,32,80,105,100,125>>]}]},{dd,[],[<<80,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,112,105,100,46>>]},{dt,[],[{code,[],[<<123,112,114,111,99,101,115,115,44,32,123,82,101,103,78,97,109,101,44,32,78,111,100,101,125,125>>]}]},{dd,[],[<<76,111,99,97,108,32,111,114,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,110,97,109,101,46>>]},{dt,[],[{code,[],[<<123,112,111,114,116,44,32,80,111,114,116,73,100,125>>]}]},{dd,[],[<<76,111,99,97,108,32,112,111,114,116,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,112,111,114,116,32,105,100,46>>]},{dt,[],[{code,[],[<<123,112,111,114,116,44,32,123,82,101,103,78,97,109,101,44,32,78,111,100,101,125,125>>]}]},{dd,[],[<<76,111,99,97,108,32,112,111,114,116,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,110,97,109,101,46,32,80,108,101,97,115,101,32,110,111,116,101,44,32,116,104,97,116,32,114,101,109,111,116,101,32,112,111,114,116,32,109,111,110,105,116,111,114,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,44,32,115,111,32>>,{code,[],[<<78,111,100,101>>]},<<32,119,105,108,108,32,97,108,119,97,121,115,32,98,101,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,110,97,109,101,46>>]}]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,116,101,32,111,102,32,112,114,111,99,101,115,115,32,102,108,97,103,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<46,32>>,{code,[],[<<77,81,68>>]},<<32,105,115,32,101,105,116,104,101,114,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<32,111,114,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<76,101,118,101,108>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,105,111,114,105,116,105,101,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,100,117,99,116,105,111,110,115,44,32,78,117,109,98,101,114,125>>]}]},{dd,[],[{p,[],[{code,[],[<<78,117,109,98,101,114>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,114,101,100,117,99,116,105,111,110,115,32,101,120,101,99,117,116,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101,44,32,65,116,111,109,125>>]}]},{dd,[],[{p,[],[{code,[],[<<65,116,111,109>>]},<<32,105,115,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,32,110,97,109,101,46,32,73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,110,111,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32,116,104,105,115,32,116,117,112,108,101,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,46>>]}]},{dt,[],[{code,[],[<<123,115,101,113,117,101,110,116,105,97,108,95,116,114,97,99,101,95,116,111,107,101,110,44,32,91,93,32,124,32,83,101,113,117,101,110,116,105,97,108,84,114,97,99,101,84,111,107,101,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,101,113,117,101,110,116,105,97,108,84,114,97,99,101,84,111,107,101,110>>]},<<32,105,115,32,116,104,101,32,115,101,113,117,101,110,116,105,97,108,32,116,114,97,99,101,32,116,111,107,101,110,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,115,116,97,99,107,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,116,97,99,107,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,44,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,115,116,97,116,117,115,44,32,83,116,97,116,117,115,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,116,97,116,117,115>>]},<<32,105,115,32,116,104,101,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,97,110,100,32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{code,[],[<<101,120,105,116,105,110,103>>]}]},{li,[],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,110,103>>]}]},{li,[],[{code,[],[<<119,97,105,116,105,110,103>>]},<<32,40,102,111,114,32,97,32,109,101,115,115,97,103,101,41>>]},{li,[],[{code,[],[<<114,117,110,110,105,110,103>>]}]},{li,[],[{code,[],[<<114,117,110,110,97,98,108,101>>]},<<32,40,114,101,97,100,121,32,116,111,32,114,117,110,44,32,98,117,116,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,105,115,32,114,117,110,110,105,110,103,41>>]},{li,[],[{code,[],[<<115,117,115,112,101,110,100,101,100>>]},<<32,40,115,117,115,112,101,110,100,101,100,32,111,110,32,97,32,34,98,117,115,121,34,32,112,111,114,116,32,111,114,32,98,121,32,116,104,101,32,66,73,70,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49,44,50>>]},<<41>>]}]}]},{dt,[],[{code,[],[<<123,115,117,115,112,101,110,100,105,110,103,44,32,83,117,115,112,101,110,100,101,101,76,105,115,116,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101,76,105,115,116>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,83,117,115,112,101,110,100,101,101,44,32,65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116,44,32,79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116,125>>]},<<32,116,117,112,108,101,115,46,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,98,101,101,110,44,32,111,114,32,105,115,32,116,111,32,98,101,44,32,115,117,115,112,101,110,100,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,116,104,114,111,117,103,104,32,116,104,101,32,66,73,70,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>]}]},<<46>>]},{p,[],[{code,[],[<<65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46,32>>,{code,[],[<<79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,110,111,116,32,121,101,116,32,99,111,109,112,108,101,116,101,100,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,115,32,115,101,110,116,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,116,104,97,116,32,105,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116,32,61,47,61,32,48>>]},<<44,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,99,117,114,114,101,110,116,108,121,32,105,110,32,116,104,101,32,115,117,115,112,101,110,100,101,100,32,115,116,97,116,101,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116,32,61,47,61,32,48>>]},<<44,32,111,112,116,105,111,110,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<32,104,97,115,32,98,101,101,110,32,117,115,101,100,32,97,110,100,32,116,104,101,32,115,117,115,112,101,110,100,101,101,32,104,97,115,32,110,111,116,32,121,101,116,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,97,114,101,32,110,111,116,32,116,104,101,32,116,111,116,97,108,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<44,32,111,110,108,121,32,116,104,101,32,112,97,114,116,115,32,99,111,110,116,114,105,98,117,116,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]},{dt,[],[{a,[{id,<<112,114,111,99,101,115,115,95,105,110,102,111,95,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<123,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,44,32,111,102,32,97,108,108,32,104,101,97,112,32,102,114,97,103,109,101,110,116,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,32,97,110,100,32,97,110,121,32,117,110,114,101,99,101,105,118,101,100,32,109,101,115,115,97,103,101,115,32,116,104,97,116,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,104,101,97,112,46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,99,101,44,32,73,110,116,101,114,110,97,108,84,114,97,99,101,70,108,97,103,115,125>>]}]},{dd,[],[{p,[],[{code,[],[<<73,110,116,101,114,110,97,108,84,114,97,99,101,70,108,97,103,115>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,105,110,116,101,114,110,97,108,32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,112,95,101,120,105,116,44,32,66,111,111,108,101,97,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<66,111,111,108,101,97,110>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,110,111,116,32,97,108,108,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,32,115,117,112,112,111,114,116,32,97,108,108,32,116,104,101,115,101,32>>,{code,[],[<<73,116,101,109>>]},<<115,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<73,116,101,109>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,105,116,101,109,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,54,53>>,signature => [{attribute,2479,spec,{{process_info,2},[{type,2479,bounded_fun,[{type,2479,'fun',[{type,2479,product,[{var,2479,'Pid'},{var,2479,'Item'}]},{type,2480,union,[{var,2480,'InfoTuple'},{type,2480,nil,[]},{atom,2480,undefined}]}]},[{type,2481,constraint,[{atom,2481,is_subtype},[{var,2481,'Pid'},{type,2481,pid,[]}]]},{type,2482,constraint,[{atom,2482,is_subtype},[{var,2482,'Item'},{user_type,2482,process_info_item,[]}]]},{type,2483,constraint,[{atom,2483,is_subtype},[{var,2483,'InfoTuple'},{user_type,2483,process_info_result_item,[]}]]}]]},{type,2484,bounded_fun,[{type,2484,'fun',[{type,2484,product,[{var,2484,'Pid'},{var,2484,'ItemList'}]},{type,2484,union,[{var,2484,'InfoTupleList'},{type,2484,nil,[]},{atom,2484,undefined}]}]},[{type,2485,constraint,[{atom,2485,is_subtype},[{var,2485,'Pid'},{type,2485,pid,[]}]]},{type,2486,constraint,[{atom,2486,is_subtype},[{var,2486,'ItemList'},{type,2486,list,[{var,2486,'Item'}]}]]},{type,2487,constraint,[{atom,2487,is_subtype},[{var,2487,'Item'},{user_type,2487,process_info_item,[]}]]},{type,2488,constraint,[{atom,2488,is_subtype},[{var,2488,'InfoTupleList'},{type,2488,list,[{var,2488,'InfoTuple'}]}]]},{type,2489,constraint,[{atom,2489,is_subtype},[{var,2489,'InfoTuple'},{user_type,2489,process_info_result_item,[]}]]}]]}]}}]}},{{function,processes,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1710}],[<<112,114,111,99,101,115,115,101,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,32,101,120,105,116,105,110,103,32,112,114,111,99,101,115,115,32,101,120,105,115,116,115,44,32,98,117,116,32,105,115,32,110,111,116,32,97,108,105,118,101,46,32,84,104,97,116,32,105,115,44,32>>,{code,[],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,47,49>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,102,111,114,32,97,110,32,101,120,105,116,105,110,103,32,112,114,111,99,101,115,115,44,32,98,117,116,32,105,116,115,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115,47,48>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,114,111,99,101,115,115,101,115,40,41,46,10,91,60,48,46,48,46,48,62,44,60,48,46,50,46,48,62,44,60,48,46,52,46,48,62,44,60,48,46,53,46,48,62,44,60,48,46,55,46,48,62,44,60,48,46,56,46,48,62,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,50,48,51>>,signature => [{attribute,1710,spec,{{processes,0},[{type,1710,'fun',[{type,1710,product,[]},{type,1710,list,[{type,1710,pid,[]}]}]}]}}]}},{{function,purge_module,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1715}],[<<112,117,114,103,101,95,109,111,100,117,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,109,111,118,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46,32,66,101,102,111,114,101,32,116,104,105,115,32,66,73,70,32,105,115,32,117,115,101,100,44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,50>>]}]},<<32,105,115,32,116,111,32,98,101,32,99,97,108,108,101,100,32,116,111,32,99,104,101,99,107,32,116,104,97,116,32,110,111,32,112,114,111,99,101,115,115,101,115,32,101,120,101,99,117,116,101,32,111,108,100,32,99,111,100,101,32,105,110,32,116,104,101,32,109,111,100,117,108,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,56,46,48,32,40,69,114,108,97,110,103,47,79,84,80,32,49,57,41,44,32,97,110,121,32,108,105,110,103,101,114,105,110,103,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,115,116,105,108,108,32,101,120,101,99,117,116,101,32,116,104,101,32,111,108,100,32,99,111,100,101,32,105,115,32,107,105,108,108,101,100,32,98,121,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46,32,73,110,32,101,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,44,32,115,117,99,104,32,105,110,99,111,114,114,101,99,116,32,117,115,101,32,99,111,117,108,100,32,99,97,117,115,101,32,109,117,99,104,32,109,111,114,101,32,102,97,116,97,108,32,102,97,105,108,117,114,101,115,44,32,108,105,107,101,32,101,109,117,108,97,116,111,114,32,99,114,97,115,104,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,50,50,48>>,signature => [{attribute,1715,spec,{{purge_module,1},[{type,1715,bounded_fun,[{type,1715,'fun',[{type,1715,product,[{var,1715,'Module'}]},{atom,1715,true}]},[{type,1716,constraint,[{atom,1716,is_subtype},[{var,1716,'Module'},{type,1716,atom,[]}]]}]]}]}}]}},{{function,put,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1729}],[<<112,117,116,47,50>>],#{<<101,110>> => [{p,[],[<<65,100,100,115,32,97,32,110,101,119,32>>,{code,[],[<<75,101,121>>]},<<32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,44,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<44,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46,32,73,102,32>>,{code,[],[<<75,101,121>>]},<<32,101,120,105,115,116,115,44,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,105,115,32,100,101,108,101,116,101,100,32,97,110,100,32,114,101,112,108,97,99,101,100,32,98,121,32>>,{code,[],[<<86,97,108>>]},<<44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,46,32,84,104,101,32,97,118,101,114,97,103,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,79,40>>,{code,[],[<<49>>]},<<41,32,97,110,100,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,105,115,32,79,40>>,{code,[],[<<78>>]},<<41,44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,105,116,101,109,115,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,88,32,61,32,112,117,116,40,110,97,109,101,44,32,119,97,108,114,117,115,41,44,32,89,32,61,32,112,117,116,40,110,97,109,101,44,32,99,97,114,112,101,110,116,101,114,41,44,10,90,32,61,32,103,101,116,40,110,97,109,101,41,44,10,123,88,44,32,89,44,32,90,125,46,10,123,117,110,100,101,102,105,110,101,100,44,119,97,108,114,117,115,44,99,97,114,112,101,110,116,101,114,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,118,97,108,117,101,115,32,115,116,111,114,101,100,32,119,104,101,110,32>>,{code,[],[<<112,117,116>>]},<<32,105,115,32,101,118,97,108,117,97,116,101,100,32,119,105,116,104,105,110,32,116,104,101,32,115,99,111,112,101,32,111,102,32,97,32>>,{code,[],[<<99,97,116,99,104>>]},<<32,97,114,101,32,110,111,116,32,114,101,116,114,97,99,116,101,100,32,105,102,32,97,32>>,{code,[],[<<116,104,114,111,119>>]},<<32,105,115,32,101,118,97,108,117,97,116,101,100,44,32,111,114,32,105,102,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,50,52,53>>,signature => [{attribute,1729,spec,{{put,2},[{type,1729,bounded_fun,[{type,1729,'fun',[{type,1729,product,[{var,1729,'Key'},{var,1729,'Val'}]},{type,1729,term,[]}]},[{type,1730,constraint,[{atom,1730,is_subtype},[{var,1730,'Key'},{type,1730,term,[]}]]},{type,1731,constraint,[{atom,1731,is_subtype},[{var,1731,'Val'},{type,1731,term,[]}]]}]]}]}}]}},{{function,raise,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1736}],[<<114,97,105,115,101,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<114,97,105,115,101,95,115,116,97,99,107,116,114,97,99,101>>}],[]}]},{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,99,108,97,115,115,44,32,114,101,97,115,111,110,44,32,97,110,100,32,99,97,108,108,32,115,116,97,99,107,32,98,97,99,107,116,114,97,99,101,32,40>>,{em,[],[<<115,116,97,99,107,116,114,97,99,101>>]},<<41,46>>]},{p,[],[{code,[],[<<67,108,97,115,115>>]},<<32,105,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<44,32>>,{code,[],[<<101,120,105,116>>]},<<44,32,111,114,32>>,{code,[],[<<116,104,114,111,119>>]},<<46,32,83,111,44,32,105,102,32,105,116,32,119,101,114,101,32,110,111,116,32,102,111,114,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,44,32>>,{code,[],[<<101,114,108,97,110,103,58,114,97,105,115,101,40,67,108,97,115,115,44,32,82,101,97,115,111,110,44,32,83,116,97,99,107,116,114,97,99,101,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,67,108,97,115,115,40,82,101,97,115,111,110,41>>]},<<32,40,103,105,118,101,110,32,116,104,97,116,32>>,{code,[],[<<67,108,97,115,115>>]},<<32,105,115,32,97,32,118,97,108,105,100,32,99,108,97,115,115,41,46>>]},{p,[],[{code,[],[<<82,101,97,115,111,110>>]},<<32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,46>>]},{p,[],[{code,[],[<<83,116,97,99,107,116,114,97,99,101>>]},<<32,105,115,32,97,32,108,105,115,116,32,97,115,32,112,114,111,118,105,100,101,100,32,105,110,32,97,32,116,114,121,45,99,97,116,99,104,32,99,108,97,117,115,101,46>>]},{pre,[],[{code,[],[<<116,114,121,10,32,32,32,32,46,46,46,10,99,97,116,99,104,32,67,108,97,115,115,58,82,101,97,115,111,110,58,83,116,97,99,107,116,114,97,99,101,32,45,62,10,32,32,32,32,46,46,46,10,101,110,100>>]}]},{p,[],[<<84,104,97,116,32,105,115,44,32,97,32,108,105,115,116,32,111,102,32,102,111,117,114,45,116,117,112,108,101,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,32,124,32,65,114,103,115,44,32,76,111,99,97,116,105,111,110,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,97,110,100,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,97,114,101,32,97,116,111,109,115,44,32,97,110,100,32,116,104,101,32,116,104,105,114,100,32,101,108,101,109,101,110,116,32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,97,114,105,116,121,32,111,114,32,97,110,32,97,114,103,117,109,101,110,116,32,108,105,115,116,46,32,84,104,101,32,115,116,97,99,107,116,114,97,99,101,32,99,97,110,32,97,108,115,111,32,99,111,110,116,97,105,110,32>>,{code,[],[<<123,70,117,110,44,32,65,114,103,115,44,32,76,111,99,97,116,105,111,110,125>>]},<<32,116,117,112,108,101,115,44,32,119,104,101,114,101,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,32,97,110,100,32>>,{code,[],[<<65,114,103,115>>]},<<32,105,115,32,97,110,32,97,114,103,117,109,101,110,116,32,108,105,115,116,46>>]},{p,[],[<<69,108,101,109,101,110,116,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,97,116,32,116,104,101,32,101,110,100,32,105,115,32,111,112,116,105,111,110,97,108,46,32,79,109,105,116,116,105,110,103,32,105,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,112,101,99,105,102,121,105,110,103,32,97,110,32,101,109,112,116,121,32,108,105,115,116,46>>]},{p,[],[<<84,104,101,32,115,116,97,99,107,116,114,97,99,101,32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,115,116,97,99,107,116,114,97,99,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,59,32,105,116,32,105,115,32,116,114,117,110,99,97,116,101,100,32,116,111,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,120,105,109,117,109,32,115,116,97,99,107,116,114,97,99,101,32,100,101,112,116,104,46>>]},{p,[],[<<65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,111,32,116,101,114,109,105,110,97,116,101,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,32,117,110,108,101,115,115,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,105,110,118,97,108,105,100,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{em,[],[<<114,101,116,117,114,110,115,32,116,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110>>]},<<32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46,32,73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,98,101,32,115,117,114,101,32,110,111,116,32,116,111,32,114,101,116,117,114,110,44,32,121,111,117,32,99,97,110,32,99,97,108,108,32>>,{code,[],[<<101,114,114,111,114,40,101,114,108,97,110,103,58,114,97,105,115,101,40,67,108,97,115,115,44,32,82,101,97,115,111,110,44,32,83,116,97,99,107,116,114,97,99,101,41,41>>]},<<32,97,110,100,32,104,111,112,101,32,116,111,32,100,105,115,116,105,110,103,117,105,115,104,32,101,120,99,101,112,116,105,111,110,115,32,108,97,116,101,114,46>>]},{p,[],[<<83,101,101,32,116,104,101,32,114,101,102,101,114,101,110,99,101,32,109,97,110,117,97,108,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,101,115,32,97,110,100,32,104,111,119,32,116,111,32,99,97,116,99,104,32,101,120,99,101,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,50,55,49>>,signature => [{attribute,1736,spec,{{erlang,raise,3},[{type,1736,bounded_fun,[{type,1736,'fun',[{type,1736,product,[{var,1736,'Class'},{var,1736,'Reason'},{var,1736,'Stacktrace'}]},{atom,1736,badarg}]},[{type,1737,constraint,[{atom,1737,is_subtype},[{var,1737,'Class'},{type,1737,union,[{atom,1737,error},{atom,1737,exit},{atom,1737,throw}]}]]},{type,1738,constraint,[{atom,1738,is_subtype},[{var,1738,'Reason'},{type,1738,term,[]}]]},{type,1739,constraint,[{atom,1739,is_subtype},[{var,1739,'Stacktrace'},{user_type,1739,raise_stacktrace,[]}]]}]]}]}}]}},{{function,read_timer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1744}],[<<114,101,97,100,95,116,105,109,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,97,100,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114,40,84,105,109,101,114,82,101,102,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,50,49>>,signature => [{attribute,1744,spec,{{erlang,read_timer,1},[{type,1744,bounded_fun,[{type,1744,'fun',[{type,1744,product,[{var,1744,'TimerRef'}]},{var,1744,'Result'}]},[{type,1745,constraint,[{atom,1745,is_subtype},[{var,1745,'TimerRef'},{type,1745,reference,[]}]]},{type,1746,constraint,[{atom,1746,is_subtype},[{var,1746,'Time'},{type,1746,non_neg_integer,[]}]]},{type,1747,constraint,[{atom,1747,is_subtype},[{var,1747,'Result'},{type,1747,union,[{var,1747,'Time'},{atom,1747,false}]}]]}]]}]}}]}},{{function,read_timer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1753}],[<<114,101,97,100,95,116,105,109,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,97,32,116,105,109,101,114,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,32,98,121,32,101,105,116,104,101,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114>>]}]},<<46,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,105,100,101,110,116,105,102,105,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,119,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32,116,104,101,32,66,73,70,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,116,105,109,101,114,46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110,115>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,65,115,121,110,99,125>>]}]},{dd,[],[{p,[],[<<65,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,115,116,97,116,101,32,105,110,102,111,114,109,97,116,105,111,110,46,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,119,104,105,99,104,32,99,97,117,115,101,115,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,116,111,32,98,101,32,112,101,114,102,111,114,109,101,100,32,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114>>]},<<46,32,87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114>>]},<<32,115,101,110,100,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,116,104,101,32,115,116,97,116,101,32,105,110,102,111,114,109,97,116,105,111,110,32,116,111,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,116,104,101,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<46,32,65,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,114,101,97,100,95,116,105,109,101,114,44,32,84,105,109,101,114,82,101,102,44,32,82,101,115,117,108,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114>>]},<<32,119,104,101,110,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,46>>]}]}]},{p,[],[<<77,111,114,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,105,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,32,108,101,102,116,32,117,110,116,105,108,32,116,104,101,32,116,105,109,101,114,32,101,120,112,105,114,101,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,97,32,116,105,109,101,114,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,99,111,117,108,100,32,110,111,116,32,98,101,32,102,111,117,110,100,46,32,84,104,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,116,105,109,101,114,32,104,97,100,32,101,120,112,105,114,101,100,44,32,111,114,32,98,101,101,110,32,99,97,110,99,101,108,101,100,44,32,111,114,32,98,101,99,97,117,115,101,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,110,101,118,101,114,32,104,97,115,32,99,111,114,114,101,115,112,111,110,100,101,100,32,116,111,32,97,32,116,105,109,101,114,46,32,69,118,101,110,32,105,102,32,116,104,101,32,116,105,109,101,114,32,104,97,115,32,101,120,112,105,114,101,100,44,32,105,116,32,100,111,101,115,32,110,111,116,32,116,101,108,108,32,121,111,117,32,119,104,101,116,104,101,114,32,111,114,32,110,111,116,32,116,104,101,32,116,105,109,101,45,111,117,116,32,109,101,115,115,97,103,101,32,104,97,115,32,97,114,114,105,118,101,100,32,97,116,32,105,116,115,32,100,101,115,116,105,110,97,116,105,111,110,32,121,101,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,32,99,97,110,32,98,101,32,99,111,45,108,111,99,97,116,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32,115,99,104,101,100,117,108,101,114,32,116,104,97,110,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32,73,102,32,115,111,44,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,97,107,101,115,32,109,117,99,104,32,108,111,110,103,101,114,32,116,105,109,101,32,116,104,97,110,32,105,102,32,105,116,32,105,115,32,108,111,99,97,116,101,100,32,108,111,99,97,108,108,121,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,105,110,32,97,32,99,114,105,116,105,99,97,108,32,112,97,116,104,44,32,97,110,100,32,99,97,110,32,100,111,32,111,116,104,101,114,32,116,104,105,110,103,115,32,119,104,105,108,101,32,119,97,105,116,105,110,103,32,102,111,114,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,44,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,116,114,117,101,125>>]},<<46,32,73,102,32,117,115,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,102,97,108,115,101,125>>]},<<44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,98,108,111,99,107,101,100,32,117,110,116,105,108,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,101,114,102,111,114,109,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,47,52>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,47,52>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,51,49>>,signature => [{attribute,1753,spec,{{erlang,read_timer,2},[{type,1753,bounded_fun,[{type,1753,'fun',[{type,1753,product,[{var,1753,'TimerRef'},{var,1753,'Options'}]},{type,1753,union,[{var,1753,'Result'},{atom,1753,ok}]}]},[{type,1754,constraint,[{atom,1754,is_subtype},[{var,1754,'TimerRef'},{type,1754,reference,[]}]]},{type,1755,constraint,[{atom,1755,is_subtype},[{var,1755,'Async'},{type,1755,boolean,[]}]]},{type,1756,constraint,[{atom,1756,is_subtype},[{var,1756,'Option'},{type,1756,tuple,[{atom,1756,async},{var,1756,'Async'}]}]]},{type,1757,constraint,[{atom,1757,is_subtype},[{var,1757,'Options'},{type,1757,list,[{var,1757,'Option'}]}]]},{type,1758,constraint,[{atom,1758,is_subtype},[{var,1758,'Time'},{type,1758,non_neg_integer,[]}]]},{type,1759,constraint,[{atom,1759,is_subtype},[{var,1759,'Result'},{type,1759,union,[{var,1759,'Time'},{atom,1759,false}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,ref_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1765}],[<<114,101,102,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<82,101,102>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,56,55>>,signature => [{attribute,1765,spec,{{ref_to_list,1},[{type,1765,bounded_fun,[{type,1765,'fun',[{type,1765,product,[{var,1765,'Ref'}]},{type,1765,string,[]}]},[{type,1766,constraint,[{atom,1766,is_subtype},[{var,1766,'Ref'},{type,1766,reference,[]}]]}]]}]}}]}},{{function,register,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1771}],[<<114,101,103,105,115,116,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<65,115,115,111,99,105,97,116,101,115,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,119,105,116,104,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,114,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,46,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<44,32,119,104,105,99,104,32,109,117,115,116,32,98,101,32,97,110,32,97,116,111,109,44,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,112,105,100,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,105,110,32,115,101,110,100,32,111,112,101,114,97,116,111,114,32,40>>,{code,[],[<<82,101,103,78,97,109,101,32,33,32,77,101,115,115,97,103,101>>]},<<41,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,114,101,103,105,115,116,101,114,40,100,98,44,32,80,105,100,41,46,10,116,114,117,101>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,120,105,115,116,105,110,103,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,105,115,32,97,108,114,101,97,100,121,32,105,110,32,117,115,101,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,115,32,97,108,114,101,97,100,121,32,114,101,103,105,115,116,101,114,101,100,32,40,97,108,114,101,97,100,121,32,104,97,115,32,97,32,110,97,109,101,41,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,52,48,48>>,signature => [{attribute,1771,spec,{{register,2},[{type,1771,bounded_fun,[{type,1771,'fun',[{type,1771,product,[{var,1771,'RegName'},{var,1771,'PidOrPort'}]},{atom,1771,true}]},[{type,1772,constraint,[{atom,1772,is_subtype},[{var,1772,'RegName'},{type,1772,atom,[]}]]},{type,1773,constraint,[{atom,1773,is_subtype},[{var,1773,'PidOrPort'},{type,1773,union,[{type,1773,port,[]},{type,1773,pid,[]}]}]]}]]}]}}]}},{{function,registered,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1778}],[<<114,101,103,105,115,116,101,114,101,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,110,97,109,101,115,32,116,104,97,116,32,104,97,118,101,32,98,101,101,110,32,114,101,103,105,115,116,101,114,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,103,105,115,116,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,103,105,115,116,101,114,47,50>>]}]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,114,101,103,105,115,116,101,114,101,100,40,41,46,10,91,99,111,100,101,95,115,101,114,118,101,114,44,32,102,105,108,101,95,115,101,114,118,101,114,44,32,105,110,105,116,44,32,117,115,101,114,44,32,109,121,95,100,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,52,50,57>>,signature => [{attribute,1778,spec,{{registered,0},[{type,1778,bounded_fun,[{type,1778,'fun',[{type,1778,product,[]},{type,1778,list,[{var,1778,'RegName'}]}]},[{type,1779,constraint,[{atom,1779,is_subtype},[{var,1779,'RegName'},{type,1779,atom,[]}]]}]]}]}}]}},{{function,resume_process,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1784}],[<<114,101,115,117,109,101,95,112,114,111,99,101,115,115,47,49>>],#{<<101,110>> => [{p,[],[<<68,101,99,114,101,97,115,101,115,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,112,114,101,118,105,111,117,115,108,121,32,116,111,32,104,97,118,101,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,116,104,114,111,117,103,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>]}]},<<32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,115,117,109,101,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]},<<46,32,87,104,101,110,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,114,101,97,99,104,101,115,32,122,101,114,111,44,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,114,101,115,117,109,101,100,44,32,116,104,97,116,32,105,115,44,32,105,116,115,32,115,116,97,116,101,32,105,115,32,99,104,97,110,103,101,100,32,102,114,111,109,32,115,117,115,112,101,110,100,101,100,32,105,110,116,111,32,116,104,101,32,115,116,97,116,101,32,105,116,32,104,97,100,32,98,101,102,111,114,101,32,105,116,32,119,97,115,32,115,117,115,112,101,110,100,101,100,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,115,117,109,101,95,112,114,111,99,101,115,115,47,49>>]},<<32,104,97,100,32,110,111,116,32,112,114,101,118,105,111,117,115,108,121,32,105,110,99,114,101,97,115,101,100,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,52,52,50>>,signature => [{attribute,1784,spec,{{erlang,resume_process,1},[{type,1784,bounded_fun,[{type,1784,'fun',[{type,1784,product,[{var,1784,'Suspendee'}]},{atom,1784,true}]},[{type,1785,constraint,[{atom,1785,is_subtype},[{var,1785,'Suspendee'},{type,1785,pid,[]}]]}]]}]}}]}},{{function,round,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1791}],[<<114,111,117,110,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,98,121,32,114,111,117,110,100,105,110,103,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,111,117,110,100,40,52,50,46,49,41,46,10,52,50>>]}]},{pre,[],[{code,[],[<<114,111,117,110,100,40,53,46,53,41,46,10,54>>]}]},{pre,[],[{code,[],[<<114,111,117,110,100,40,45,53,46,53,41,46,10,45,54>>]}]},{pre,[],[{code,[],[<<114,111,117,110,100,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41,46,10,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]}]},{p,[],[<<73,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<114,111,117,110,100,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41>>]},<<32,101,118,97,108,117,97,116,101,115,32,116,111,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]},<<46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,116,104,97,116,32,116,104,101,32,110,117,109,98,101,114,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48>>]},<<32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,73,110,115,116,101,97,100,44,32,116,104,101,32,102,108,111,97,116,32,108,105,116,101,114,97,108,32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56,46,48>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,99,108,111,115,101,115,116,32,110,117,109,98,101,114,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,108,111,97,116,95,114,101,112,114,101,115,101,110,116,97,116,105,111,110,95,112,114,111,98,108,101,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,70,108,111,97,116,105,110,103,32,80,111,105,110,116,32,78,117,109,98,101,114,115>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,52,56,51>>,signature => [{attribute,1791,spec,{{round,1},[{type,1791,bounded_fun,[{type,1791,'fun',[{type,1791,product,[{var,1791,'Number'}]},{type,1791,integer,[]}]},[{type,1792,constraint,[{atom,1792,is_subtype},[{var,1792,'Number'},{type,1792,number,[]}]]}]]}]}}]}},{{function,self,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1798}],[<<115,101,108,102,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,101,108,102,40,41,46,10,60,48,46,50,54,46,48,62>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,53,49,52>>,signature => [{attribute,1798,spec,{{self,0},[{type,1798,'fun',[{type,1798,product,[]},{type,1798,pid,[]}]}]}}]}},{{function,send,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2493}],[<<115,101,110,100,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<83,101,110,100,115,32,97,32,109,101,115,115,97,103,101,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<77,115,103>>]},<<46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,117,115,105,110,103,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,115,101,110,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,101,110,100,32,111,112,101,114,97,116,111,114>>]},<<58,32>>,{code,[],[<<68,101,115,116,32,33,32,77,115,103>>]},<<46>>]},{p,[],[{code,[],[<<68,101,115,116>>]},<<32,99,97,110,32,98,101,32,97,32,114,101,109,111,116,101,32,111,114,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,97,32,40,108,111,99,97,108,41,32,112,111,114,116,44,32,97,32,108,111,99,97,108,108,121,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32,111,114,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,82,101,103,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,102,111,114,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,97,116,32,97,110,111,116,104,101,114,32,110,111,100,101,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,114,117,110,45,116,105,109,101,32,101,114,114,111,114,32,105,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,110,32,97,116,111,109,32,110,97,109,101,44,32,98,117,116,32,116,104,105,115,32,110,97,109,101,32,105,115,32,110,111,116,32,114,101,103,105,115,116,101,114,101,100,46,32,84,104,105,115,32,105,115,32,116,104,101,32,111,110,108,121,32,99,97,115,101,32,119,104,101,110,32>>,{code,[],[<<115,101,110,100>>]},<<32,102,97,105,108,115,32,102,111,114,32,97,110,32,117,110,114,101,97,99,104,97,98,108,101,32,100,101,115,116,105,110,97,116,105,111,110,32>>,{code,[],[<<68,101,115,116>>]},<<32,40,111,102,32,99,111,114,114,101,99,116,32,116,121,112,101,41,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,53,50,55>>,signature => [{attribute,2493,spec,{{erlang,send,2},[{type,2493,bounded_fun,[{type,2493,'fun',[{type,2493,product,[{var,2493,'Dest'},{var,2493,'Msg'}]},{var,2493,'Msg'}]},[{type,2494,constraint,[{atom,2494,is_subtype},[{var,2494,'Dest'},{user_type,2494,dst,[]}]]},{type,2495,constraint,[{atom,2495,is_subtype},[{var,2495,'Msg'},{type,2495,term,[]}]]}]]}]}}]}},{{function,send,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2499}],[<<115,101,110,100,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<69,105,116,104,101,114,32,115,101,110,100,115,32,97,32,109,101,115,115,97,103,101,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<44,32,111,114,32,100,111,101,115,32,110,111,116,32,115,101,110,100,32,116,104,101,32,109,101,115,115,97,103,101,32,98,117,116,32,114,101,116,117,114,110,115,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,40,115,101,101,32,98,101,108,111,119,41,46,32,79,116,104,101,114,119,105,115,101,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,47,50>>]}]},<<46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,101,100,32,101,120,112,108,97,110,97,116,105,111,110,32,97,110,100,32,119,97,114,110,105,110,103,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50,44,51>>]}]},<<46>>]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<110,111,115,117,115,112,101,110,100>>]}]},{dd,[],[<<73,102,32,116,104,101,32,115,101,110,100,101,114,32,119,111,117,108,100,32,104,97,118,101,32,116,111,32,98,101,32,115,117,115,112,101,110,100,101,100,32,116,111,32,100,111,32,116,104,101,32,115,101,110,100,44,32>>,{code,[],[<<110,111,115,117,115,112,101,110,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]},{dt,[],[{code,[],[<<110,111,99,111,110,110,101,99,116>>]}]},{dd,[],[<<73,102,32,116,104,101,32,100,101,115,116,105,110,97,116,105,111,110,32,110,111,100,101,32,119,111,117,108,100,32,104,97,118,101,32,116,111,32,98,101,32,97,117,116,111,45,99,111,110,110,101,99,116,101,100,32,116,111,32,100,111,32,116,104,101,32,115,101,110,100,44,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<65,115,32,119,105,116,104,32>>,{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50,44,51>>]},<<58,32,117,115,101,32,119,105,116,104,32,101,120,116,114,101,109,101,32,99,97,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,53,52,55>>,signature => [{attribute,2499,spec,{{erlang,send,3},[{type,2499,bounded_fun,[{type,2499,'fun',[{type,2499,product,[{var,2499,'Dest'},{var,2499,'Msg'},{var,2499,'Options'}]},{var,2499,'Res'}]},[{type,2500,constraint,[{atom,2500,is_subtype},[{var,2500,'Dest'},{user_type,2500,dst,[]}]]},{type,2501,constraint,[{atom,2501,is_subtype},[{var,2501,'Msg'},{type,2501,term,[]}]]},{type,2502,constraint,[{atom,2502,is_subtype},[{var,2502,'Options'},{type,2502,list,[{type,2502,union,[{atom,2502,nosuspend},{atom,2502,noconnect}]}]}]]},{type,2503,constraint,[{atom,2503,is_subtype},[{var,2503,'Res'},{type,2503,union,[{atom,2503,ok},{atom,2503,nosuspend},{atom,2503,noconnect}]}]]}]]}]}}]}},{{function,send_after,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1803}],[<<115,101,110,100,95,97,102,116,101,114,47,51>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,40,84,105,109,101,44,32,68,101,115,116,44,32,77,115,103,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,53,55,57>>,signature => [{attribute,1803,spec,{{erlang,send_after,3},[{type,1803,bounded_fun,[{type,1803,'fun',[{type,1803,product,[{var,1803,'Time'},{var,1803,'Dest'},{var,1803,'Msg'}]},{var,1803,'TimerRef'}]},[{type,1804,constraint,[{atom,1804,is_subtype},[{var,1804,'Time'},{type,1804,non_neg_integer,[]}]]},{type,1805,constraint,[{atom,1805,is_subtype},[{var,1805,'Dest'},{type,1805,union,[{type,1805,pid,[]},{type,1805,atom,[]}]}]]},{type,1806,constraint,[{atom,1806,is_subtype},[{var,1806,'Msg'},{type,1806,term,[]}]]},{type,1807,constraint,[{atom,1807,is_subtype},[{var,1807,'TimerRef'},{type,1807,reference,[]}]]}]]}]}}]}},{{function,send_after,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1813}],[<<115,101,110,100,95,97,102,116,101,114,47,52>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,87,104,101,110,32,116,104,101,32,116,105,109,101,114,32,101,120,112,105,114,101,115,44,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,101,115,116>>]},<<46,32,65,112,97,114,116,32,102,114,111,109,32,116,104,101,32,102,111,114,109,97,116,32,111,102,32,116,104,101,32,116,105,109,101,45,111,117,116,32,109,101,115,115,97,103,101,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,119,111,114,107,115,32,101,120,97,99,116,108,121,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,47,52>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,53,57,48>>,signature => [{attribute,1813,spec,{{erlang,send_after,4},[{type,1813,bounded_fun,[{type,1813,'fun',[{type,1813,product,[{var,1813,'Time'},{var,1813,'Dest'},{var,1813,'Msg'},{var,1813,'Options'}]},{var,1813,'TimerRef'}]},[{type,1814,constraint,[{atom,1814,is_subtype},[{var,1814,'Time'},{type,1814,integer,[]}]]},{type,1815,constraint,[{atom,1815,is_subtype},[{var,1815,'Dest'},{type,1815,union,[{type,1815,pid,[]},{type,1815,atom,[]}]}]]},{type,1816,constraint,[{atom,1816,is_subtype},[{var,1816,'Msg'},{type,1816,term,[]}]]},{type,1817,constraint,[{atom,1817,is_subtype},[{var,1817,'Options'},{type,1817,list,[{var,1817,'Option'}]}]]},{type,1818,constraint,[{atom,1818,is_subtype},[{var,1818,'Abs'},{type,1818,boolean,[]}]]},{type,1819,constraint,[{atom,1819,is_subtype},[{var,1819,'Option'},{type,1819,tuple,[{atom,1819,abs},{var,1819,'Abs'}]}]]},{type,1820,constraint,[{atom,1820,is_subtype},[{var,1820,'TimerRef'},{type,1820,reference,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,send_nosuspend,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3458}],[<<115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,40,68,101,115,116,44,32,77,115,103,44,32,91,110,111,115,117,115,112,101,110,100,93,41>>]}]},<<44,32,98,117,116,32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,109,101,115,115,97,103,101,32,119,97,115,32,115,101,110,116,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,109,101,115,115,97,103,101,32,119,97,115,32,110,111,116,32,115,101,110,116,32,98,101,99,97,117,115,101,32,116,104,101,32,115,101,110,100,101,114,32,119,111,117,108,100,32,104,97,118,101,32,104,97,100,32,116,111,32,98,101,32,115,117,115,112,101,110,100,101,100,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,115,101,110,100,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,97,110,32,117,110,114,101,108,105,97,98,108,101,32,114,101,109,111,116,101,32,110,111,100,101,32,119,105,116,104,111,117,116,32,101,118,101,114,32,98,108,111,99,107,105,110,103,32,116,104,101,32,115,101,110,100,105,110,103,32,40,69,114,108,97,110,103,41,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,32,40,117,115,117,97,108,108,121,32,110,111,116,32,97,32,114,101,97,108,32,69,114,108,97,110,103,32,110,111,100,101,44,32,98,117,116,32,97,32,110,111,100,101,32,119,114,105,116,116,101,110,32,105,110,32,67,32,111,114,32,74,97,118,97,41,32,105,115,32,111,118,101,114,108,111,97,100,101,100,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32>>,{em,[],[<<100,111,101,115,32,110,111,116,32,115,101,110,100,32,116,104,101,32,109,101,115,115,97,103,101>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<84,104,101,32,115,97,109,101,32,111,99,99,117,114,115,32,105,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,108,111,99,97,108,32,112,111,114,116,32,116,104,97,116,32,105,115,32,98,117,115,121,46,32,70,111,114,32,97,108,108,32,111,116,104,101,114,32,100,101,115,116,105,110,97,116,105,111,110,115,32,40,97,108,108,111,119,101,100,32,102,111,114,32,116,104,101,32,111,114,100,105,110,97,114,121,32,115,101,110,100,32,111,112,101,114,97,116,111,114,32>>,{code,[],[<<39,33,39>>]},<<41,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,115,101,110,100,115,32,116,104,101,32,109,101,115,115,97,103,101,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,114,97,114,101,32,99,105,114,99,117,109,115,116,97,110,99,101,115,32,119,104,101,114,101,32,97,32,112,114,111,99,101,115,115,32,99,111,109,109,117,110,105,99,97,116,101,115,32,119,105,116,104,32,69,114,108,97,110,103,32,110,111,100,101,115,32,116,104,97,116,32,99,97,110,32,100,105,115,97,112,112,101,97,114,32,119,105,116,104,111,117,116,32,97,110,121,32,116,114,97,99,101,44,32,99,97,117,115,105,110,103,32,116,104,101,32,84,67,80,32,98,117,102,102,101,114,115,32,97,110,100,32,116,104,101,32,100,114,105,118,101,114,115,32,113,117,101,117,101,32,116,111,32,98,101,32,111,118,101,114,45,102,117,108,108,32,98,101,102,111,114,101,32,116,104,101,32,110,111,100,101,32,105,115,32,115,104,117,116,32,100,111,119,110,32,40,98,101,99,97,117,115,101,32,111,102,32,116,105,99,107,32,116,105,109,101,45,111,117,116,115,41,32,98,121,32>>,{code,[],[<<110,101,116,95,107,101,114,110,101,108>>]},<<46,32,84,104,101,32,110,111,114,109,97,108,32,114,101,97,99,116,105,111,110,32,116,111,32,116,97,107,101,32,119,104,101,110,32,116,104,105,115,32,111,99,99,117,114,115,32,105,115,32,115,111,109,101,32,107,105,110,100,32,111,102,32,112,114,101,109,97,116,117,114,101,32,115,104,117,116,100,111,119,110,32,111,102,32,116,104,101,32,111,116,104,101,114,32,110,111,100,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,105,103,110,111,114,105,110,103,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,102,114,111,109,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,119,111,117,108,100,32,114,101,115,117,108,116,32,105,110,32,97,110,32>>,{em,[],[<<117,110,114,101,108,105,97,98,108,101>>]},<<32,109,101,115,115,97,103,101,32,112,97,115,115,105,110,103,44,32,119,104,105,99,104,32,105,115,32,99,111,110,116,114,97,100,105,99,116,111,114,121,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,105,110,103,32,109,111,100,101,108,46,32,84,104,101,32,109,101,115,115,97,103,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,115,101,110,116,32,105,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<73,110,32,109,97,110,121,32,115,121,115,116,101,109,115,44,32,116,114,97,110,115,105,101,110,116,32,115,116,97,116,101,115,32,111,102,32,111,118,101,114,108,111,97,100,101,100,32,113,117,101,117,101,115,32,97,114,101,32,110,111,114,109,97,108,46,32,65,108,116,104,111,117,103,104,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,100,111,101,115,32,110,111,116,32,109,101,97,110,32,116,104,97,116,32,116,104,101,32,111,116,104,101,114,32,110,111,100,101,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,110,111,110,45,114,101,115,112,111,110,115,105,118,101,44,32,105,116,32,99,111,117,108,100,32,98,101,32,97,32,116,101,109,112,111,114,97,114,121,32,111,118,101,114,108,111,97,100,46,32,65,108,115,111,44,32,97,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32>>,{code,[],[<<116,114,117,101>>]},<<32,100,111,101,115,32,111,110,108,121,32,109,101,97,110,32,116,104,97,116,32,116,104,101,32,109,101,115,115,97,103,101,32,99,97,110,32,98,101,32,115,101,110,116,32,111,110,32,116,104,101,32,40,84,67,80,41,32,99,104,97,110,110,101,108,32,119,105,116,104,111,117,116,32,98,108,111,99,107,105,110,103,59,32,116,104,101,32,109,101,115,115,97,103,101,32,105,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,97,114,114,105,118,101,32,97,116,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,46,32,70,111,114,32,97,32,100,105,115,99,111,110,110,101,99,116,101,100,32,110,111,110,45,114,101,115,112,111,110,115,105,118,101,32,110,111,100,101,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,40,109,105,109,105,99,115,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,111,112,101,114,97,116,111,114,32>>,{code,[],[<<33>>]},<<41,46,32,84,104,101,32,101,120,112,101,99,116,101,100,32,98,101,104,97,118,105,111,114,32,97,110,100,32,116,104,101,32,97,99,116,105,111,110,115,32,116,111,32,116,97,107,101,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,97,114,101,32,97,112,112,108,105,99,97,116,105,111,110,45,32,97,110,100,32,104,97,114,100,119,97,114,101,45,115,112,101,99,105,102,105,99,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<85,115,101,32,119,105,116,104,32,101,120,116,114,101,109,101,32,99,97,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,54,48,51>>,signature => [{attribute,3458,spec,{{erlang,send_nosuspend,2},[{type,3458,bounded_fun,[{type,3458,'fun',[{type,3458,product,[{var,3458,'Dest'},{var,3458,'Msg'}]},{type,3458,boolean,[]}]},[{type,3459,constraint,[{atom,3459,is_subtype},[{var,3459,'Dest'},{user_type,3459,dst,[]}]]},{type,3460,constraint,[{atom,3460,is_subtype},[{var,3460,'Msg'},{type,3460,term,[]}]]}]]}]}}]}},{{function,send_nosuspend,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3468}],[<<115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,40,68,101,115,116,44,32,77,115,103,44,32,91,110,111,115,117,115,112,101,110,100,32,124,32,79,112,116,105,111,110,115,93,41>>]}]},<<44,32,98,117,116,32,119,105,116,104,32,97,32,66,111,111,108,101,97,110,32,114,101,116,117,114,110,32,118,97,108,117,101,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,98,101,104,97,118,101,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>]}]},<<44,32,98,117,116,32,116,97,107,101,115,32,97,32,116,104,105,114,100,32,112,97,114,97,109,101,116,101,114,44,32,97,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46,32,84,104,101,32,111,110,108,121,32,111,112,116,105,111,110,32,105,115,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<44,32,119,104,105,99,104,32,109,97,107,101,115,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,32,105,115,32,110,111,116,32,99,117,114,114,101,110,116,108,121,32,114,101,97,99,104,97,98,108,101,32,98,121,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,110,111,114,109,97,108,32,98,101,104,97,118,105,111,114,32,105,115,32,116,111,32,116,114,121,32,116,111,32,99,111,110,110,101,99,116,32,116,111,32,116,104,101,32,110,111,100,101,44,32,119,104,105,99,104,32,99,97,110,32,115,116,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,32,100,117,114,105,110,103,32,97,32,115,104,111,114,116,32,112,101,114,105,111,100,46,32,84,104,101,32,117,115,101,32,111,102,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,98,101,32,115,117,114,101,32,110,111,116,32,116,111,32,103,101,116,32,116,104,101,32,115,108,105,103,104,116,101,115,116,32,100,101,108,97,121,32,119,104,101,110,32,115,101,110,100,105,110,103,32,116,111,32,97,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,115,32,101,115,112,101,99,105,97,108,108,121,32,117,115,101,102,117,108,32,119,104,101,110,32,99,111,109,109,117,110,105,99,97,116,105,110,103,32,119,105,116,104,32,110,111,100,101,115,32,116,104,97,116,32,101,120,112,101,99,116,32,116,111,32,97,108,119,97,121,115,32,98,101,32,116,104,101,32,99,111,110,110,101,99,116,105,110,103,32,112,97,114,116,32,40,116,104,97,116,32,105,115,44,32,110,111,100,101,115,32,119,114,105,116,116,101,110,32,105,110,32,67,32,111,114,32,74,97,118,97,41,46>>]},{p,[],[<<87,104,101,110,101,118,101,114,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,40,101,105,116,104,101,114,32,119,104,101,110,32,97,32,115,117,115,112,101,110,100,32,119,111,117,108,100,32,111,99,99,117,114,32,111,114,32,119,104,101,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<32,119,97,115,32,115,112,101,99,105,102,105,101,100,32,97,110,100,32,116,104,101,32,110,111,100,101,32,119,97,115,32,110,111,116,32,97,108,114,101,97,100,121,32,99,111,110,110,101,99,116,101,100,41,44,32,116,104,101,32,109,101,115,115,97,103,101,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,104,97,118,101,32,98,101,101,110,32,115,101,110,116,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<85,115,101,32,119,105,116,104,32,101,120,116,114,101,109,101,32,99,97,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,54,53,51>>,signature => [{attribute,3468,spec,{{erlang,send_nosuspend,3},[{type,3468,bounded_fun,[{type,3468,'fun',[{type,3468,product,[{var,3468,'Dest'},{var,3468,'Msg'},{var,3468,'Options'}]},{type,3468,boolean,[]}]},[{type,3469,constraint,[{atom,3469,is_subtype},[{var,3469,'Dest'},{user_type,3469,dst,[]}]]},{type,3470,constraint,[{atom,3470,is_subtype},[{var,3470,'Msg'},{type,3470,term,[]}]]},{type,3471,constraint,[{atom,3471,is_subtype},[{var,3471,'Options'},{type,3471,list,[{atom,3471,noconnect}]}]]}]]}]}}]}},{{function,set_cookie,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3783}],[<<115,101,116,95,99,111,111,107,105,101,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,103,105,99,32,99,111,111,107,105,101,32,111,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,116,111,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<67,111,111,107,105,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,108,115,111,32,115,101,116,115,32,116,104,101,32,99,111,111,107,105,101,32,111,102,32,97,108,108,32,111,116,104,101,114,32,117,110,107,110,111,119,110,32,110,111,100,101,115,32,116,111,32>>,{code,[],[<<67,111,111,107,105,101>>]},<<32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,105,115,116,114,105,98,117,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<68,105,115,116,114,105,98,117,116,101,100,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,32,105,110,32,83,121,115,116,101,109,32,68,111,99,117,109,101,110,116,97,116,105,111,110,41,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<102,117,110,99,116,105,111,110,95,99,108,97,117,115,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,54,56,54>>,signature => [{attribute,3783,spec,{{erlang,set_cookie,2},[{type,3783,bounded_fun,[{type,3783,'fun',[{type,3783,product,[{var,3783,'Node'},{var,3783,'Cookie'}]},{atom,3783,true}]},[{type,3784,constraint,[{atom,3784,is_subtype},[{var,3784,'Node'},{type,3784,node,[]}]]},{type,3785,constraint,[{atom,3785,is_subtype},[{var,3785,'Cookie'},{type,3785,atom,[]}]]}]]}]}}]}},{{function,setelement,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2520}],[<<115,101,116,101,108,101,109,101,110,116,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,116,104,97,116,32,105,115,32,97,32,99,111,112,121,32,111,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<32,119,105,116,104,32,116,104,101,32,101,108,101,109,101,110,116,32,115,112,101,99,105,102,105,101,100,32,98,121,32,105,110,116,101,103,101,114,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,40,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,116,104,101,32,101,108,101,109,101,110,116,32,119,105,116,104,32,105,110,100,101,120,32,49,41,32,114,101,112,108,97,99,101,100,32,98,121,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<86,97,108,117,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,101,116,101,108,101,109,101,110,116,40,50,44,32,123,49,48,44,32,103,114,101,101,110,44,32,98,111,116,116,108,101,115,125,44,32,114,101,100,41,46,10,123,49,48,44,114,101,100,44,98,111,116,116,108,101,115,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,48,51>>,signature => [{attribute,2520,spec,{{setelement,3},[{type,2520,bounded_fun,[{type,2520,'fun',[{type,2520,product,[{var,2520,'Index'},{var,2520,'Tuple1'},{var,2520,'Value'}]},{var,2520,'Tuple2'}]},[{type,2521,constraint,[{atom,2521,is_subtype},[{var,2521,'Index'},{type,2521,pos_integer,[]}]]},{type,2522,constraint,[{atom,2522,is_subtype},[{var,2522,'Tuple1'},{type,2522,tuple,any}]]},{type,2523,constraint,[{atom,2523,is_subtype},[{var,2523,'Tuple2'},{type,2523,tuple,any}]]},{type,2524,constraint,[{atom,2524,is_subtype},[{var,2524,'Value'},{type,2524,term,[]}]]}]]}]}}]}},{{function,size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1874}],[<<115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,105,110,32,97,32,116,117,112,108,101,32,111,114,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,110,32,97,32,98,105,110,97,114,121,32,111,114,32,98,105,116,115,116,114,105,110,103,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,105,122,101,40,123,109,111,114,110,105,44,32,109,117,108,108,101,44,32,98,119,97,110,103,101,125,41,46,10,51,10,62,32,115,105,122,101,40,60,60,49,49,44,32,50,50,44,32,51,51,62,62,41,46,10,51>>]}]},{p,[],[<<70,111,114,32,98,105,116,115,116,114,105,110,103,115,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,119,104,111,108,101,32,98,121,116,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,105,116,115,32,105,110,32,116,104,101,32,98,105,116,115,116,114,105,110,103,32,105,115,32,110,111,116,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,44,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,115,32,114,111,117,110,100,101,100,32>>,{em,[],[<<100,111,119,110>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,117,112,108,101,95,115,105,122,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,117,112,108,101,95,115,105,122,101,47,49>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,121,116,101,95,115,105,122,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,121,116,101,95,115,105,122,101,47,49>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,116,95,115,105,122,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,116,95,115,105,122,101,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,50,48>>,signature => [{attribute,1874,spec,{{size,1},[{type,1874,bounded_fun,[{type,1874,'fun',[{type,1874,product,[{var,1874,'Item'}]},{type,1874,non_neg_integer,[]}]},[{type,1875,constraint,[{atom,1875,is_subtype},[{var,1875,'Item'},{type,1875,union,[{type,1875,tuple,any},{type,1875,binary,[]}]}]]}]]}]}}]}},{{function,spawn,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2904}],[<<115,112,97,119,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,52,51>>,signature => [{attribute,2904,spec,{{spawn,1},[{type,2904,bounded_fun,[{type,2904,'fun',[{type,2904,product,[{var,2904,'Fun'}]},{type,2904,pid,[]}]},[{type,2905,constraint,[{atom,2905,is_subtype},[{var,2905,'Fun'},{type,2905,function,[]}]]}]]}]}}]}},{{function,spawn,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2913}],[<<115,112,97,119,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,53,52>>,signature => [{attribute,2913,spec,{{spawn,2},[{type,2913,bounded_fun,[{type,2913,'fun',[{type,2913,product,[{var,2913,'Node'},{var,2913,'Fun'}]},{type,2913,pid,[]}]},[{type,2914,constraint,[{atom,2914,is_subtype},[{var,2914,'Node'},{type,2914,node,[]}]]},{type,2915,constraint,[{atom,2915,is_subtype},[{var,2915,'Fun'},{type,2915,function,[]}]]}]]}]}}]}},{{function,spawn,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1880}],[<<115,112,97,119,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46>>]},{p,[],[{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114,58,117,110,100,101,102,105,110,101,100,95,102,117,110,99,116,105,111,110,40,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,103,115,41>>]},<<32,105,115,32,101,118,97,108,117,97,116,101,100,32,98,121,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,105,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,40,119,104,101,114,101,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32>>,{code,[],[<<65,114,103,115>>]},<<41,46,32,84,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,99,97,110,32,98,101,32,114,101,100,101,102,105,110,101,100,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<41,46,32,73,102,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,111,114,32,116,104,101,32,117,115,101,114,32,104,97,115,32,114,101,100,101,102,105,110,101,100,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,97,110,100,32,105,116,115,32,114,101,112,108,97,99,101,109,101,110,116,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,32,102,97,105,108,117,114,101,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<117,110,100,101,102>>]},<<32,111,99,99,117,114,115,46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,112,97,119,110,40,115,112,101,101,100,44,32,114,101,103,117,108,97,116,111,114,44,32,91,104,105,103,104,95,115,112,101,101,100,44,32,116,104,105,110,95,99,117,116,93,41,46,10,60,48,46,49,51,46,49,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,54,56>>,signature => [{attribute,1880,spec,{{spawn,3},[{type,1880,bounded_fun,[{type,1880,'fun',[{type,1880,product,[{var,1880,'Module'},{var,1880,'Function'},{var,1880,'Args'}]},{type,1880,pid,[]}]},[{type,1881,constraint,[{atom,1881,is_subtype},[{var,1881,'Module'},{type,1881,module,[]}]]},{type,1882,constraint,[{atom,1882,is_subtype},[{var,1882,'Function'},{type,1882,atom,[]}]]},{type,1883,constraint,[{atom,1883,is_subtype},[{var,1883,'Args'},{type,1883,list,[{type,1883,term,[]}]}]]}]]}]}}]}},{{function,spawn,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3042}],[<<115,112,97,119,110,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,57,51>>,signature => [{attribute,3042,spec,{{spawn,4},[{type,3042,bounded_fun,[{type,3042,'fun',[{type,3042,product,[{var,3042,'Node'},{var,3042,'Module'},{var,3042,'Function'},{var,3042,'Args'}]},{type,3042,pid,[]}]},[{type,3043,constraint,[{atom,3043,is_subtype},[{var,3043,'Node'},{type,3043,node,[]}]]},{type,3044,constraint,[{atom,3044,is_subtype},[{var,3044,'Module'},{type,3044,module,[]}]]},{type,3045,constraint,[{atom,3045,is_subtype},[{var,3045,'Function'},{type,3045,atom,[]}]]},{type,3046,constraint,[{atom,3046,is_subtype},[{var,3046,'Args'},{type,3046,list,[{type,3046,term,[]}]}]]}]]}]}}]}},{{function,spawn_link,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2925}],[<<115,112,97,119,110,95,108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,48,56>>,signature => [{attribute,2925,spec,{{spawn_link,1},[{type,2925,bounded_fun,[{type,2925,'fun',[{type,2925,product,[{var,2925,'Fun'}]},{type,2925,pid,[]}]},[{type,2926,constraint,[{atom,2926,is_subtype},[{var,2926,'Fun'},{type,2926,function,[]}]]}]]}]}}]}},{{function,spawn_link,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2934}],[<<115,112,97,119,110,95,108,105,110,107,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,32,97,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,50,50>>,signature => [{attribute,2934,spec,{{spawn_link,2},[{type,2934,bounded_fun,[{type,2934,'fun',[{type,2934,product,[{var,2934,'Node'},{var,2934,'Fun'}]},{type,2934,pid,[]}]},[{type,2935,constraint,[{atom,2935,is_subtype},[{var,2935,'Node'},{type,2935,node,[]}]]},{type,2936,constraint,[{atom,2936,is_subtype},[{var,2936,'Fun'},{type,2936,function,[]}]]}]]}]}}]}},{{function,spawn_link,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1888}],[<<115,112,97,119,110,95,108,105,110,107,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,51,57>>,signature => [{attribute,1888,spec,{{spawn_link,3},[{type,1888,bounded_fun,[{type,1888,'fun',[{type,1888,product,[{var,1888,'Module'},{var,1888,'Function'},{var,1888,'Args'}]},{type,1888,pid,[]}]},[{type,1889,constraint,[{atom,1889,is_subtype},[{var,1889,'Module'},{type,1889,module,[]}]]},{type,1890,constraint,[{atom,1890,is_subtype},[{var,1890,'Function'},{type,1890,atom,[]}]]},{type,1891,constraint,[{atom,1891,is_subtype},[{var,1891,'Args'},{type,1891,list,[{type,1891,term,[]}]}]]}]]}]}}]}},{{function,spawn_link,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3064}],[<<115,112,97,119,110,95,108,105,110,107,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,32,97,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,53,51>>,signature => [{attribute,3064,spec,{{spawn_link,4},[{type,3064,bounded_fun,[{type,3064,'fun',[{type,3064,product,[{var,3064,'Node'},{var,3064,'Module'},{var,3064,'Function'},{var,3064,'Args'}]},{type,3064,pid,[]}]},[{type,3065,constraint,[{atom,3065,is_subtype},[{var,3065,'Node'},{type,3065,node,[]}]]},{type,3066,constraint,[{atom,3066,is_subtype},[{var,3066,'Module'},{type,3066,module,[]}]]},{type,3067,constraint,[{atom,3067,is_subtype},[{var,3067,'Function'},{type,3067,atom,[]}]]},{type,3068,constraint,[{atom,3068,is_subtype},[{var,3068,'Args'},{type,3068,list,[{type,3068,term,[]}]}]]}]]}]}}]}},{{function,spawn_monitor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2948}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,44,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<44,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,97,32,109,111,110,105,116,111,114,32,99,114,101,97,116,101,100,32,116,111,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,55,49>>,signature => [{attribute,2948,spec,{{spawn_monitor,1},[{type,2948,bounded_fun,[{type,2948,'fun',[{type,2948,product,[{var,2948,'Fun'}]},{type,2948,tuple,[{type,2948,pid,[]},{type,2948,reference,[]}]}]},[{type,2949,constraint,[{atom,2949,is_subtype},[{var,2949,'Fun'},{type,2949,function,[]}]]}]]}]}}]}},{{function,spawn_monitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2955}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,44,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<44,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,97,32,109,111,110,105,116,111,114,32,99,114,101,97,116,101,100,32,116,111,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,100,105,115,116,114,105,98,117,116,101,100,32>>,{code,[],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,40,41>>]},<<44,32,116,104,101,32,99,97,108,108,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,101,120,99,101,112,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,56,53>>,signature => [{attribute,2955,spec,{{spawn_monitor,2},[{type,2955,bounded_fun,[{type,2955,'fun',[{type,2955,product,[{var,2955,'Node'},{var,2955,'Fun'}]},{type,2955,tuple,[{type,2955,pid,[]},{type,2955,reference,[]}]}]},[{type,2956,constraint,[{atom,2956,is_subtype},[{var,2956,'Node'},{type,2956,node,[]}]]},{type,2957,constraint,[{atom,2957,is_subtype},[{var,2957,'Fun'},{type,2957,function,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_monitor,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2969}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,51>>],#{<<101,110>> => [{p,[],[<<65,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,84,104,101,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,48,50>>,signature => [{attribute,2969,spec,{{spawn_monitor,3},[{type,2969,bounded_fun,[{type,2969,'fun',[{type,2969,product,[{var,2969,'Module'},{var,2969,'Function'},{var,2969,'Args'}]},{type,2969,tuple,[{type,2969,pid,[]},{type,2969,reference,[]}]}]},[{type,2970,constraint,[{atom,2970,is_subtype},[{var,2970,'Module'},{type,2970,module,[]}]]},{type,2971,constraint,[{atom,2971,is_subtype},[{var,2971,'Function'},{type,2971,atom,[]}]]},{type,2972,constraint,[{atom,2972,is_subtype},[{var,2972,'Args'},{type,2972,list,[{type,2972,term,[]}]}]]}]]}]}}]}},{{function,spawn_monitor,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3086}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,52>>],#{<<101,110>> => [{p,[],[<<65,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,84,104,101,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,100,105,115,116,114,105,98,117,116,101,100,32>>,{code,[],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,40,41>>]},<<44,32,116,104,101,32,99,97,108,108,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,101,120,99,101,112,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,49,54>>,signature => [{attribute,3086,spec,{{spawn_monitor,4},[{type,3086,bounded_fun,[{type,3086,'fun',[{type,3086,product,[{var,3086,'Node'},{var,3086,'Module'},{var,3086,'Function'},{var,3086,'Args'}]},{type,3086,tuple,[{type,3086,pid,[]},{type,3086,reference,[]}]}]},[{type,3087,constraint,[{atom,3087,is_subtype},[{var,3087,'Node'},{type,3087,node,[]}]]},{type,3088,constraint,[{atom,3088,is_subtype},[{var,3088,'Module'},{type,3088,module,[]}]]},{type,3089,constraint,[{atom,3089,is_subtype},[{var,3089,'Function'},{type,3089,atom,[]}]]},{type,3090,constraint,[{atom,3090,is_subtype},[{var,3090,'Args'},{type,3090,list,[{type,3090,term,[]}]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_opt,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2999}],[<<115,112,97,119,110,95,111,112,116,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<115,112,97,119,110,95,111,112,116,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,44,32,97,110,100,32,98,111,116,104,32,116,104,101,32,112,105,100,32,97,110,100,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,32,97,114,101,32,114,101,116,117,114,110,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,51,51>>,signature => [{attribute,2999,spec,{{spawn_opt,2},[{type,2999,bounded_fun,[{type,2999,'fun',[{type,2999,product,[{var,2999,'Fun'},{var,2999,'Options'}]},{type,2999,union,[{type,2999,pid,[]},{type,2999,tuple,[{type,2999,pid,[]},{type,2999,reference,[]}]}]}]},[{type,3000,constraint,[{atom,3000,is_subtype},[{var,3000,'Fun'},{type,3000,function,[]}]]},{type,3001,constraint,[{atom,3001,is_subtype},[{var,3001,'Options'},{type,3001,list,[{user_type,3001,spawn_opt_option,[]}]}]]}]]}]}}]}},{{function,spawn_opt,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3014}],[<<115,112,97,119,110,95,111,112,116,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]},{p,[],[<<86,97,108,105,100,32,111,112,116,105,111,110,115,32,100,101,112,101,110,100,115,32,111,110,32,119,104,97,116,32,111,112,116,105,111,110,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,102,111,114,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,111,102,32,99,117,114,114,101,110,116,32,79,84,80,32,118,101,114,115,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,53,49>>,signature => [{attribute,3014,spec,{{spawn_opt,3},[{type,3014,bounded_fun,[{type,3014,'fun',[{type,3014,product,[{var,3014,'Node'},{var,3014,'Fun'},{var,3014,'Options'}]},{type,3014,union,[{type,3014,pid,[]},{type,3014,tuple,[{type,3014,pid,[]},{type,3014,reference,[]}]}]}]},[{type,3015,constraint,[{atom,3015,is_subtype},[{var,3015,'Node'},{type,3015,node,[]}]]},{type,3016,constraint,[{atom,3016,is_subtype},[{var,3016,'Fun'},{type,3016,function,[]}]]},{type,3017,constraint,[{atom,3017,is_subtype},[{var,3017,'Options'},{type,3017,list,[{type,3017,union,[{atom,3017,monitor},{type,3018,tuple,[{atom,3018,monitor},{type,3018,list,[{user_type,3018,monitor_option,[]}]}]},{atom,3019,link},{var,3020,'OtherOption'}]}]}]]},{type,3021,constraint,[{atom,3021,is_subtype},[{var,3021,'OtherOption'},{type,3021,term,[]}]]}]]}]}}]}},{{function,spawn_opt,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3131}],[<<115,112,97,119,110,95,111,112,116,47,52>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<115,112,97,119,110,95,111,112,116,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<87,111,114,107,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,97,110,32,101,120,116,114,97,32,111,112,116,105,111,110,32,108,105,115,116,32,105,115,32,115,112,101,99,105,102,105,101,100,32,119,104,101,110,32,99,114,101,97,116,105,110,103,32,116,104,101,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,44,32,97,110,100,32,98,111,116,104,32,116,104,101,32,112,105,100,32,97,110,100,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,32,97,114,101,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,105,110,107>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,97,32,108,105,110,107,32,116,111,32,116,104,101,32,112,97,114,101,110,116,32,112,114,111,99,101,115,115,32,40,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,108,105,110,107,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,108,105,110,107,47,51>>]}]},<<32,100,111,101,115,41,46>>]}]},{dt,[],[{code,[],[<<109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<77,111,110,105,116,111,114,115,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,40,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,41>>]}]},<<32,100,111,101,115,41,46,32,65,32>>,{code,[],[<<123,80,105,100,44,32,77,111,110,105,116,111,114,82,101,102,125>>]},<<32,116,117,112,108,101,32,119,105,108,108,32,98,101,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,32,111,102,32,106,117,115,116,32,97,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,44,32,77,111,110,105,116,111,114,79,112,116,115,125>>]}]},{dd,[],[{p,[],[<<77,111,110,105,116,111,114,115,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,119,105,116,104,32,111,112,116,105,111,110,115,32,40,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,44,32,77,111,110,105,116,111,114,79,112,116,115,41>>]}]},<<32,100,111,101,115,41,46,32,65,32>>,{code,[],[<<123,80,105,100,44,32,77,111,110,105,116,111,114,82,101,102,125>>]},<<32,116,117,112,108,101,32,119,105,108,108,32,98,101,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,32,111,102,32,106,117,115,116,32,97,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,112,114,105,111,114,105,116,121,32,111,102,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,46,32,69,113,117,105,118,97,108,101,110,116,32,116,111,32,101,120,101,99,117,116,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]},<<32,105,110,32,116,104,101,32,115,116,97,114,116,32,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,101,120,99,101,112,116,32,116,104,97,116,32,116,104,101,32,112,114,105,111,114,105,116,121,32,105,115,32,115,101,116,32,98,101,102,111,114,101,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,32,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,105,111,114,105,116,105,101,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114,44,32,78,117,109,98,101,114,125>>]}]},{dd,[],[{p,[],[<<85,115,101,102,117,108,32,111,110,108,121,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,116,117,110,105,110,103,46,32,68,111,32,110,111,116,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,112,114,111,98,108,101,109,32,119,105,116,104,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,115,32,111,114,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,44,32,97,110,100,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,111,112,116,105,111,110,32,105,109,112,114,111,118,101,115,32,109,97,116,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,117,115,101,115,32,97,32,103,101,110,101,114,97,116,105,111,110,97,108,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,99,104,101,109,101,44,32,117,115,105,110,103,32,97,110,32,34,111,108,100,32,104,101,97,112,34,32,102,111,114,32,100,97,116,97,32,116,104,97,116,32,104,97,115,32,115,117,114,118,105,118,101,100,32,97,116,32,108,101,97,115,116,32,111,110,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,104,101,110,32,116,104,101,114,101,32,105,115,32,110,111,32,109,111,114,101,32,114,111,111,109,32,111,110,32,116,104,101,32,111,108,100,32,104,101,97,112,44,32,97,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,100,111,110,101,46>>]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,103,101,110,101,114,97,116,105,111,110,97,108,32,99,111,108,108,101,99,116,105,111,110,115,32,98,101,102,111,114,101,32,102,111,114,99,105,110,103,32,97,32,102,117,108,108,115,119,101,101,112,44,32,101,118,101,110,32,105,102,32,116,104,101,114,101,32,105,115,32,114,111,111,109,32,111,110,32,116,104,101,32,111,108,100,32,104,101,97,112,46,32,83,101,116,116,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,116,111,32,122,101,114,111,32,100,105,115,97,98,108,101,115,32,116,104,101,32,103,101,110,101,114,97,108,32,99,111,108,108,101,99,116,105,111,110,32,97,108,103,111,114,105,116,104,109,44,32,116,104,97,116,32,105,115,44,32,97,108,108,32,108,105,118,101,32,100,97,116,97,32,105,115,32,99,111,112,105,101,100,32,97,116,32,101,118,101,114,121,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[<<65,32,102,101,119,32,99,97,115,101,115,32,119,104,101,110,32,105,116,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,116,111,32,99,104,97,110,103,101,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,98,105,110,97,114,105,101,115,32,116,104,97,116,32,97,114,101,32,110,111,32,108,111,110,103,101,114,32,117,115,101,100,32,97,114,101,32,116,111,32,98,101,32,116,104,114,111,119,110,32,97,119,97,121,32,97,115,32,115,111,111,110,32,97,115,32,112,111,115,115,105,98,108,101,46,32,40,83,101,116,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,122,101,114,111,46,41>>]}]},{li,[],[{p,[],[<<65,32,112,114,111,99,101,115,115,32,116,104,97,116,32,109,111,115,116,108,121,32,104,97,118,101,32,115,104,111,114,116,45,108,105,118,101,100,32,100,97,116,97,32,105,115,32,102,117,108,108,115,119,101,101,112,101,100,32,115,101,108,100,111,109,32,111,114,32,110,101,118,101,114,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,111,108,100,32,104,101,97,112,32,99,111,110,116,97,105,110,115,32,109,111,115,116,108,121,32,103,97,114,98,97,103,101,46,32,84,111,32,101,110,115,117,114,101,32,97,32,102,117,108,108,115,119,101,101,112,32,111,99,99,97,115,105,111,110,97,108,108,121,44,32,115,101,116,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,97,32,115,117,105,116,97,98,108,101,32,118,97,108,117,101,44,32,115,117,99,104,32,97,115,32,49,48,32,111,114,32,50,48,46>>]}]},{li,[],[<<73,110,32,101,109,98,101,100,100,101,100,32,115,121,115,116,101,109,115,32,119,105,116,104,32,97,32,108,105,109,105,116,101,100,32,97,109,111,117,110,116,32,111,102,32,82,65,77,32,97,110,100,32,110,111,32,118,105,114,116,117,97,108,32,109,101,109,111,114,121,44,32,121,111,117,32,109,105,103,104,116,32,119,97,110,116,32,116,111,32,112,114,101,115,101,114,118,101,32,109,101,109,111,114,121,32,98,121,32,115,101,116,116,105,110,103,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,122,101,114,111,46,32,40,84,104,101,32,118,97,108,117,101,32,99,97,110,32,98,101,32,115,101,116,32,103,108,111,98,97,108,108,121,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,47,50>>]}]},<<46,41>>]}]}]},{dt,[],[{code,[],[<<123,109,105,110,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<85,115,101,102,117,108,32,111,110,108,121,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,116,117,110,105,110,103,46,32,68,111,32,110,111,116,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,112,114,111,98,108,101,109,32,119,105,116,104,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,115,32,111,114,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,44,32,97,110,100,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,111,112,116,105,111,110,32,105,109,112,114,111,118,101,115,32,109,97,116,116,101,114,115,46>>]},{p,[],[<<71,105,118,101,115,32,97,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,118,97,108,117,101,32,104,105,103,104,101,114,32,116,104,97,110,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,99,97,110,32,115,112,101,101,100,32,117,112,32,115,111,109,101,32,112,114,111,99,101,115,115,101,115,32,98,101,99,97,117,115,101,32,108,101,115,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,100,111,110,101,46,32,72,111,119,101,118,101,114,44,32,115,101,116,116,105,110,103,32,97,32,116,111,111,32,104,105,103,104,32,118,97,108,117,101,32,99,97,110,32,119,97,115,116,101,32,109,101,109,111,114,121,32,97,110,100,32,115,108,111,119,32,100,111,119,110,32,116,104,101,32,115,121,115,116,101,109,32,98,101,99,97,117,115,101,32,111,102,32,119,111,114,115,101,32,100,97,116,97,32,108,111,99,97,108,105,116,121,46,32,84,104,101,114,101,102,111,114,101,44,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,111,110,108,121,32,102,111,114,32,102,105,110,101,45,116,117,110,105,110,103,32,97,110,32,97,112,112,108,105,99,97,116,105,111,110,32,97,110,100,32,116,111,32,109,101,97,115,117,114,101,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,119,105,116,104,32,118,97,114,105,111,117,115,32>>,{code,[],[<<83,105,122,101>>]},<<32,118,97,108,117,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101,44,32,86,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<85,115,101,102,117,108,32,111,110,108,121,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,116,117,110,105,110,103,46,32,68,111,32,110,111,116,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,112,114,111,98,108,101,109,32,119,105,116,104,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,115,32,111,114,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,44,32,97,110,100,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,111,112,116,105,111,110,32,105,109,112,114,111,118,101,115,32,109,97,116,116,101,114,115,46>>]},{p,[],[<<71,105,118,101,115,32,97,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,118,97,108,117,101,32,104,105,103,104,101,114,32,116,104,97,110,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,99,97,110,32,115,112,101,101,100,32,117,112,32,115,111,109,101,32,112,114,111,99,101,115,115,101,115,32,98,101,99,97,117,115,101,32,108,101,115,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,100,111,110,101,46,32,72,111,119,101,118,101,114,44,32,115,101,116,116,105,110,103,32,97,32,116,111,111,32,104,105,103,104,32,118,97,108,117,101,32,99,97,110,32,119,97,115,116,101,32,109,101,109,111,114,121,46,32,84,104,101,114,101,102,111,114,101,44,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,111,110,108,121,32,102,111,114,32,102,105,110,101,45,116,117,110,105,110,103,32,97,110,32,97,112,112,108,105,99,97,116,105,111,110,32,97,110,100,32,116,111,32,109,101,97,115,117,114,101,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,119,105,116,104,32,118,97,114,105,111,117,115,32>>,{code,[],[<<86,83,105,122,101>>]},<<32,118,97,108,117,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,46,32,84,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,46,32>>,{code,[],[<<77,81,68>>]},<<32,105,115,32,116,111,32,98,101,32,101,105,116,104,101,114,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<32,111,114,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,113,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,113,100>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,55,52>>,signature => [{attribute,3131,spec,{{spawn_opt,4},[{type,3131,bounded_fun,[{type,3131,'fun',[{type,3131,product,[{var,3131,'Module'},{var,3131,'Function'},{var,3131,'Args'},{var,3131,'Options'}]},{type,3132,union,[{var,3132,'Pid'},{type,3132,tuple,[{var,3132,'Pid'},{var,3132,'MonitorRef'}]}]}]},[{type,3133,constraint,[{atom,3133,is_subtype},[{var,3133,'Module'},{type,3133,module,[]}]]},{type,3134,constraint,[{atom,3134,is_subtype},[{var,3134,'Function'},{type,3134,atom,[]}]]},{type,3135,constraint,[{atom,3135,is_subtype},[{var,3135,'Args'},{type,3135,list,[{type,3135,term,[]}]}]]},{type,3136,constraint,[{atom,3136,is_subtype},[{var,3136,'Options'},{type,3136,list,[{user_type,3136,spawn_opt_option,[]}]}]]},{type,3137,constraint,[{atom,3137,is_subtype},[{var,3137,'Pid'},{type,3137,pid,[]}]]},{type,3138,constraint,[{atom,3138,is_subtype},[{var,3138,'MonitorRef'},{type,3138,reference,[]}]]}]]}]}}]}},{{function,spawn_opt,5},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3143}],[<<115,112,97,119,110,95,111,112,116,47,53>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]},{p,[],[<<86,97,108,105,100,32,111,112,116,105,111,110,115,32,100,101,112,101,110,100,115,32,111,110,32,119,104,97,116,32,111,112,116,105,111,110,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,102,111,114,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,111,102,32,99,117,114,114,101,110,116,32,79,84,80,32,118,101,114,115,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,50,50>>,signature => [{attribute,3143,spec,{{spawn_opt,5},[{type,3143,bounded_fun,[{type,3143,'fun',[{type,3143,product,[{var,3143,'Node'},{var,3143,'Module'},{var,3143,'Function'},{var,3143,'Args'},{var,3143,'Options'}]},{type,3144,union,[{type,3144,pid,[]},{type,3144,tuple,[{type,3144,pid,[]},{type,3144,reference,[]}]}]}]},[{type,3145,constraint,[{atom,3145,is_subtype},[{var,3145,'Node'},{type,3145,node,[]}]]},{type,3146,constraint,[{atom,3146,is_subtype},[{var,3146,'Module'},{type,3146,module,[]}]]},{type,3147,constraint,[{atom,3147,is_subtype},[{var,3147,'Function'},{type,3147,atom,[]}]]},{type,3148,constraint,[{atom,3148,is_subtype},[{var,3148,'Args'},{type,3148,list,[{type,3148,term,[]}]}]]},{type,3149,constraint,[{atom,3149,is_subtype},[{var,3149,'Options'},{type,3149,list,[{type,3149,union,[{atom,3149,monitor},{type,3150,tuple,[{atom,3150,monitor},{type,3150,list,[{user_type,3150,monitor_option,[]}]}]},{atom,3151,link},{var,3152,'OtherOption'}]}]}]]},{type,3153,constraint,[{atom,3153,is_subtype},[{var,3153,'OtherOption'},{type,3153,term,[]}]]}]]}]}}]}},{{function,spawn_request,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3246}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,70,117,110,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,52,54>>,signature => [{attribute,3246,spec,{{spawn_request,1},[{type,3246,bounded_fun,[{type,3246,'fun',[{type,3246,product,[{var,3246,'Fun'}]},{var,3246,'ReqId'}]},[{type,3247,constraint,[{atom,3247,is_subtype},[{var,3247,'Fun'},{type,3247,function,[]}]]},{type,3248,constraint,[{atom,3248,is_subtype},[{var,3248,'ReqId'},{type,3248,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3264}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,70,117,110,44,79,112,116,105,111,110,115,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,53,56>>,signature => [{attribute,3264,spec,{{spawn_request,2},[{type,3264,bounded_fun,[{type,3264,'fun',[{type,3264,product,[{var,3264,'Fun'},{var,3264,'Options'}]},{var,3264,'ReqId'}]},[{type,3265,constraint,[{atom,3265,is_subtype},[{var,3265,'Fun'},{type,3265,function,[]}]]},{type,3266,constraint,[{atom,3266,is_subtype},[{var,3266,'Option'},{type,3266,union,[{type,3266,tuple,[{atom,3266,reply_tag},{var,3266,'ReplyTag'}]},{type,3267,tuple,[{atom,3267,reply},{var,3267,'Reply'}]},{user_type,3268,spawn_opt_option,[]}]}]]},{type,3269,constraint,[{atom,3269,is_subtype},[{var,3269,'ReplyTag'},{type,3269,term,[]}]]},{type,3270,constraint,[{atom,3270,is_subtype},[{var,3270,'Reply'},{type,3270,union,[{atom,3270,yes},{atom,3270,no},{atom,3270,error_only},{atom,3270,success_only}]}]]},{type,3271,constraint,[{atom,3271,is_subtype},[{var,3271,'Options'},{type,3271,list,[{var,3271,'Option'}]}]]},{type,3272,constraint,[{atom,3272,is_subtype},[{var,3272,'ReqId'},{type,3272,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3264}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,78,111,100,101,44,70,117,110,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,55,48>>,signature => [{attribute,3264,spec,{{spawn_request,2},[{type,3273,bounded_fun,[{type,3273,'fun',[{type,3273,product,[{var,3273,'Node'},{var,3273,'Fun'}]},{var,3273,'ReqId'}]},[{type,3274,constraint,[{atom,3274,is_subtype},[{var,3274,'Node'},{type,3274,node,[]}]]},{type,3275,constraint,[{atom,3275,is_subtype},[{var,3275,'Fun'},{type,3275,function,[]}]]},{type,3276,constraint,[{atom,3276,is_subtype},[{var,3276,'ReqId'},{type,3276,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3299}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,78,111,100,101,44,101,114,108,97,110,103,44,97,112,112,108,121,44,91,70,117,110,44,91,93,93,44,79,112,116,105,111,110,115,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,117,115,105,110,103,32,116,104,101,32,102,117,110,32>>,{code,[],[<<70,117,110>>]},<<32,111,102,32,97,114,105,116,121,32,122,101,114,111,32,97,115,32,101,110,116,114,121,32,112,111,105,110,116,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<78,111,100,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<70,117,110>>]},<<32,105,115,32,110,111,116,32,97,32,102,117,110,32,111,102,32,97,114,105,116,121,32,122,101,114,111,46>>]}]},{li,[],[{p,[],[{code,[],[<<79,112,116,105,111,110,115>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,116,101,114,109,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,56,50>>,signature => [{attribute,3299,spec,{{spawn_request,3},[{type,3299,bounded_fun,[{type,3299,'fun',[{type,3299,product,[{var,3299,'Node'},{var,3299,'Fun'},{var,3299,'Options'}]},{var,3299,'ReqId'}]},[{type,3300,constraint,[{atom,3300,is_subtype},[{var,3300,'Node'},{type,3300,node,[]}]]},{type,3301,constraint,[{atom,3301,is_subtype},[{var,3301,'Fun'},{type,3301,function,[]}]]},{type,3302,constraint,[{atom,3302,is_subtype},[{var,3302,'Options'},{type,3302,list,[{var,3302,'Option'}]}]]},{type,3303,constraint,[{atom,3303,is_subtype},[{var,3303,'Option'},{type,3303,union,[{atom,3303,monitor},{type,3304,tuple,[{atom,3304,monitor},{type,3304,list,[{user_type,3304,monitor_option,[]}]}]},{atom,3305,link},{type,3306,tuple,[{atom,3306,reply_tag},{var,3306,'ReplyTag'}]},{type,3307,tuple,[{atom,3307,reply},{var,3307,'Reply'}]},{var,3308,'OtherOption'}]}]]},{type,3309,constraint,[{atom,3309,is_subtype},[{var,3309,'ReplyTag'},{type,3309,term,[]}]]},{type,3310,constraint,[{atom,3310,is_subtype},[{var,3310,'Reply'},{type,3310,union,[{atom,3310,yes},{atom,3310,no},{atom,3310,error_only},{atom,3310,success_only}]}]]},{type,3311,constraint,[{atom,3311,is_subtype},[{var,3311,'OtherOption'},{type,3311,term,[]}]]},{type,3312,constraint,[{atom,3312,is_subtype},[{var,3312,'ReqId'},{type,3312,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3299}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,65,114,103,115,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,48,50>>,signature => [{attribute,3299,spec,{{spawn_request,3},[{type,3313,bounded_fun,[{type,3313,'fun',[{type,3313,product,[{var,3313,'Module'},{var,3313,'Function'},{var,3313,'Args'}]},{var,3314,'ReqId'}]},[{type,3315,constraint,[{atom,3315,is_subtype},[{var,3315,'Module'},{type,3315,module,[]}]]},{type,3316,constraint,[{atom,3316,is_subtype},[{var,3316,'Function'},{type,3316,atom,[]}]]},{type,3317,constraint,[{atom,3317,is_subtype},[{var,3317,'Args'},{type,3317,list,[{type,3317,term,[]}]}]]},{type,3318,constraint,[{atom,3318,is_subtype},[{var,3318,'ReqId'},{type,3318,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3339}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,52>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,78,111,100,101,44,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,65,114,103,115,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,49,52>>,signature => [{attribute,3339,spec,{{spawn_request,4},[{type,3339,bounded_fun,[{type,3339,'fun',[{type,3339,product,[{var,3339,'Node'},{var,3339,'Module'},{var,3339,'Function'},{var,3339,'Args'}]},{var,3340,'ReqId'}]},[{type,3341,constraint,[{atom,3341,is_subtype},[{var,3341,'Node'},{type,3341,node,[]}]]},{type,3342,constraint,[{atom,3342,is_subtype},[{var,3342,'Module'},{type,3342,module,[]}]]},{type,3343,constraint,[{atom,3343,is_subtype},[{var,3343,'Function'},{type,3343,atom,[]}]]},{type,3344,constraint,[{atom,3344,is_subtype},[{var,3344,'Args'},{type,3344,list,[{type,3344,term,[]}]}]]},{type,3345,constraint,[{atom,3345,is_subtype},[{var,3345,'ReqId'},{type,3345,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3339}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,52>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,65,114,103,115,44,79,112,116,105,111,110,115,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,50,54>>,signature => [{attribute,3339,spec,{{spawn_request,4},[{type,3346,bounded_fun,[{type,3346,'fun',[{type,3346,product,[{var,3346,'Module'},{var,3346,'Function'},{var,3346,'Args'},{var,3346,'Options'}]},{var,3347,'ReqId'}]},[{type,3348,constraint,[{atom,3348,is_subtype},[{var,3348,'Module'},{type,3348,module,[]}]]},{type,3349,constraint,[{atom,3349,is_subtype},[{var,3349,'Function'},{type,3349,atom,[]}]]},{type,3350,constraint,[{atom,3350,is_subtype},[{var,3350,'Args'},{type,3350,list,[{type,3350,term,[]}]}]]},{type,3351,constraint,[{atom,3351,is_subtype},[{var,3351,'Option'},{type,3351,union,[{type,3351,tuple,[{atom,3351,reply_tag},{var,3351,'ReplyTag'}]},{type,3352,tuple,[{atom,3352,reply},{var,3352,'Reply'}]},{user_type,3353,spawn_opt_option,[]}]}]]},{type,3354,constraint,[{atom,3354,is_subtype},[{var,3354,'ReplyTag'},{type,3354,term,[]}]]},{type,3355,constraint,[{atom,3355,is_subtype},[{var,3355,'Reply'},{type,3355,union,[{atom,3355,yes},{atom,3355,no},{atom,3355,error_only},{atom,3355,success_only}]}]]},{type,3356,constraint,[{atom,3356,is_subtype},[{var,3356,'Options'},{type,3356,list,[{var,3356,'Option'}]}]]},{type,3357,constraint,[{atom,3357,is_subtype},[{var,3357,'ReqId'},{type,3357,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,5},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3380}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>],#{<<101,110>> => [{p,[],[<<65,115,121,110,99,104,114,111,110,111,117,115,108,121,32,115,101,110,100,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46,32,82,101,116,117,114,110,115,32,97,32,114,101,113,117,101,115,116,32,105,100,101,110,116,105,102,105,101,114,32>>,{code,[],[<<82,101,113,73,100>>]},<<46>>]},{a,[{id,<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>}],[]},{p,[],[<<73,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,99,114,101,97,116,101,100,32,111,110,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,87,104,101,110,32,97,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,98,121,32,100,101,102,97,117,108,116,32,98,101,32,115,101,110,116,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,82,101,112,108,121,84,97,103,44,32,82,101,113,73,100,44,32,111,107,44,32,80,105,100,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,83,117,99,104,32,97,32,109,101,115,115,97,103,101,32,105,115,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,97,32>>,{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]},<<32,98,101,108,111,119,32,105,110,32,116,104,101,32,116,101,120,116,46,32>>,{code,[],[<<82,101,112,108,121,84,97,103>>]},<<32,105,115,32,98,121,32,100,101,102,97,117,108,116,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,112,97,119,110,95,114,101,112,108,121>>]},<<32,117,110,108,101,115,115,32,109,111,100,105,102,105,101,100,32,98,121,32,116,104,101,32>>,{code,[],[<<123,114,101,112,108,121,95,116,97,103,44,32,82,101,112,108,121,84,97,103,125>>]},<<32,111,112,116,105,111,110,46,32,84,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46>>]},{a,[{id,<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>}],[]},{p,[],[<<84,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,32,101,105,116,104,101,114,32,105,102,32,99,114,101,97,116,105,111,110,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,102,97,105,108,101,100,32,111,114,32,105,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,119,97,115,32,105,110,116,101,114,114,117,112,116,101,100,32,98,121,32,97,32,99,111,110,110,101,99,116,105,111,110,32,102,97,105,108,117,114,101,46,32,87,104,101,110,32,97,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,98,121,32,100,101,102,97,117,108,116,32,98,101,32,115,101,110,116,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,82,101,112,108,121,84,97,103,44,32,82,101,113,73,100,44,32,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,116,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,46,32,83,117,99,104,32,97,32,109,101,115,115,97,103,101,32,105,115,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,97,110,32>>,{i,[],[<<101,114,114,111,114,32,109,101,115,115,97,103,101>>]},<<32,98,101,108,111,119,32,105,110,32,116,104,101,32,116,101,120,116,46,32,67,117,114,114,101,110,116,108,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,112,97,119,110,32,101,114,114,111,114,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<115,32,97,114,101,32,100,101,102,105,110,101,100,44,32,98,117,116,32,111,116,104,101,114,32,114,101,97,115,111,110,115,32,99,97,110,32,97,112,112,101,97,114,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,111,112,116>>]}]},{dd,[],[{p,[],[<<65,110,32,105,110,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<32,119,97,115,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46,32,78,111,116,101,32,116,104,97,116,32,100,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,115,32,109,97,121,32,115,117,112,112,111,114,116,32,100,105,102,102,101,114,101,110,116,32,111,112,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,115,32,105,115,115,117,101,100,32,98,121,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<70,97,105,108,117,114,101,32,116,111,32,115,101,116,32,117,112,32,97,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,111,114,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,97,116,32,110,111,100,101,32,119,97,115,32,108,111,115,116,32,100,117,114,105,110,103,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,73,110,32,116,104,101,32,99,97,115,101,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,119,97,115,32,108,111,115,116,44,32,97,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,104,97,118,101,32,98,101,101,110,32,99,114,101,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<67,111,117,108,100,32,110,111,116,32,99,114,101,97,116,101,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,100,117,101,32,116,111,32,116,104,97,116,32,115,111,109,101,32,115,121,115,116,101,109,32,108,105,109,105,116,32,119,97,115,32,114,101,97,99,104,101,100,46,32,84,121,112,105,99,97,108,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,116,97,98,108,101,32,119,97,115,32,102,117,108,108,46>>]}]}]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<73,110,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,117,114,101,115,44,32,97,116,111,109,105,99,97,108,108,121,32,115,101,116,115,32,117,112,32,97,32,109,111,110,105,116,111,114,32,116,111,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,97,115,32,105,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,104,97,100,32,99,97,108,108,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,41>>]}]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,101,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<32,105,115,32,97,108,115,111,32,117,115,101,100,32,97,115,32,109,111,110,105,116,111,114,32,114,101,102,101,114,101,110,99,101,32,97,115,32,105,102,32,105,116,32,119,97,115,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,41>>]},<<46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,97,116,101,100,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,84,104,101,32,109,111,110,105,116,111,114,32,99,97,110,32,110,111,116,32,98,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<100,101,109,111,110,105,116,111,114,101,100>>]},<<32,98,101,102,111,114,101,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,65,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,102,111,114,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,109,111,110,105,116,111,114,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,110,111,116,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,116,104,97,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,73,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,110,111,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,46>>]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,98,101,116,119,101,101,110,32,116,104,101,32,110,111,100,101,115,32,105,110,118,111,108,118,101,100,32,105,110,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,105,115,32,108,111,115,116,32,100,117,114,105,110,103,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<46,32,65,32,110,101,119,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,104,97,118,101,32,98,101,101,110,32,99,114,101,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,44,32,77,111,110,105,116,111,114,79,112,116,115,125>>]}]},{dd,[],[{p,[],[<<73,110,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,117,114,101,115,44,32,97,116,111,109,105,99,97,108,108,121,32,115,101,116,115,32,117,112,32,97,32,109,111,110,105,116,111,114,32,116,111,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,97,115,32,105,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,104,97,100,32,99,97,108,108,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,44,32,77,111,110,105,116,111,114,79,112,116,115,41>>]}]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,83,101,101,32,116,104,101,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,111,112,116,105,111,110,32,97,98,111,118,101,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,97,116,101,100,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,116,104,101,32,99,97,115,101,32,116,104,97,116,32,97,110,32,97,108,105,97,115,32,105,115,32,99,114,101,97,116,101,100,32,117,115,105,110,103,32,116,104,101,32,109,111,110,105,116,111,114,32,111,112,116,105,111,110,44,32,116,104,101,32,97,108,105,97,115,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,101,32,117,110,116,105,108,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,97,99,116,105,118,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<108,105,110,107>>]}]},{dd,[],[{p,[],[<<73,110,32,97,98,115,101,110,99,101,32,111,102,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,117,114,101,115,44,32,97,116,111,109,105,99,97,108,108,121,32,115,101,116,115,32,117,112,32,97,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,97,115,32,105,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,104,97,100,32,99,97,108,108,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,110,107,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,110,107,40,80,105,100,41>>]}]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<84,104,101,32,108,105,110,107,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,97,116,101,100,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,84,104,101,32,108,105,110,107,32,99,97,110,32,110,111,116,32,98,101,32,114,101,109,111,118,101,100,32,98,101,102,111,114,101,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,65,110,32,101,120,105,116,32,115,105,103,110,97,108,32,100,117,101,32,116,111,32,116,104,101,32,108,105,110,107,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,110,111,116,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,116,104,97,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,73,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,110,111,32,101,120,105,116,32,115,105,103,110,97,108,32,100,117,101,32,116,111,32,116,104,101,32,108,105,110,107,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,98,101,116,119,101,101,110,32,116,104,101,32,110,111,100,101,115,32,105,110,118,111,108,118,101,100,32,105,110,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,105,115,32,108,111,115,116,32,100,117,114,105,110,103,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<46,32,65,32,110,101,119,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,104,97,118,101,32,98,101,101,110,32,99,114,101,97,116,101,100,46,32,73,102,32,105,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,44,32,105,116,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,97,110,32,101,120,105,116,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,112,108,121,44,32,82,101,112,108,121,125>>]}]},{dd,[],[{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<82,101,112,108,121>>]},<<32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<121,101,115>>]}]},{dd,[],[{p,[],[<<65,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,32,111,114,32,110,111,116,46,32,73,102,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<32,114,101,116,117,114,110,115,32,119,105,116,104,111,117,116,32,114,97,105,115,105,110,103,32,97,110,32,101,120,99,101,112,116,105,111,110,32,97,110,100,32,116,104,101,32>>,{code,[],[<<114,101,112,108,121>>]},<<32,111,112,116,105,111,110,32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<121,101,115>>]},<<44,32,116,104,101,32,99,97,108,108,101,114,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,101,105,116,104,101,114,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,111,114,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<101,114,114,111,114,32,109,101,115,115,97,103,101>>]}]},<<46,32,84,104,101,32>>,{code,[],[<<114,101,112,108,121>>]},<<32,111,112,116,105,111,110,32,105,115,32,98,121,32,100,101,102,97,117,108,116,32,115,101,116,32,116,111,32>>,{code,[],[<<121,101,115>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,111>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,119,104,101,110,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,99,111,109,112,108,101,116,101,115,46,32,84,104,105,115,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,32,111,114,32,110,111,116,46>>]}]},{dt,[],[{code,[],[<<101,114,114,111,114,95,111,110,108,121>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,98,117,116,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<101,114,114,111,114,32,109,101,115,115,97,103,101>>]}]},<<32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,46>>]}]},{dt,[],[{code,[],[<<115,117,99,99,101,115,115,95,111,110,108,121>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,98,117,116,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,46>>]}]}]}]},{dt,[],[{code,[],[<<123,114,101,112,108,121,95,116,97,103,44,32,82,101,112,108,121,84,97,103,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,114,101,112,108,121,32,116,97,103,32,116,111,32>>,{code,[],[<<82,101,112,108,121,84,97,103>>]},<<32,105,110,32,116,104,101,32,114,101,112,108,121,32,109,101,115,115,97,103,101,46,32,84,104,97,116,32,105,115,44,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<101,114,114,111,114>>]}]},<<32,109,101,115,115,97,103,101,32,116,104,97,116,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,100,117,101,32,116,111,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,84,104,101,32,100,101,102,97,117,108,116,32,114,101,112,108,121,32,116,97,103,32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,112,97,119,110,95,114,101,112,108,121>>]},<<46>>]}]},{dt,[],[{code,[],[<<79,116,104,101,114,79,112,116,105,111,110>>]}]},{dd,[],[{p,[],[<<79,116,104,101,114,32,118,97,108,105,100,32,111,112,116,105,111,110,115,32,100,101,112,101,110,100,115,32,111,110,32,119,104,97,116,32,111,112,116,105,111,110,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,111,116,104,101,114,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,102,111,114,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,111,102,32,99,117,114,114,101,110,116,32,79,84,80,32,118,101,114,115,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]}]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<78,111,100,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<65,114,103,115>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,116,101,114,109,115,46>>]}]},{li,[],[{p,[],[{code,[],[<<79,112,116,105,111,110,115>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,116,101,114,109,115,46>>]}]}]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,110,111,116,32,97,108,108,32,105,110,100,105,118,105,100,117,97,108,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,97,114,101,32,99,104,101,99,107,101,100,32,119,104,101,110,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,46,32,83,111,109,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,99,97,110,32,111,110,108,121,32,98,101,32,99,104,101,99,107,101,100,32,111,110,32,114,101,99,101,112,116,105,111,110,32,111,102,32,116,104,101,32,114,101,113,117,101,115,116,46,32,84,104,101,114,101,102,111,114,101,32,97,110,32,105,110,118,97,108,105,100,32,111,112,116,105,111,110,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,99,97,117,115,101,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,44,32,98,117,116,32,119,105,108,108,32,99,97,117,115,101,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,116,111,32,102,97,105,108,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<98,97,100,111,112,116>>]},<<46>>]},{p,[],[<<65,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,99,97,110,32,98,101,32,97,98,97,110,100,111,110,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,51,56>>,signature => [{attribute,3380,spec,{{spawn_request,5},[{type,3380,bounded_fun,[{type,3380,'fun',[{type,3380,product,[{var,3380,'Node'},{var,3380,'Module'},{var,3380,'Function'},{var,3380,'Args'},{var,3380,'Options'}]},{var,3381,'ReqId'}]},[{type,3382,constraint,[{atom,3382,is_subtype},[{var,3382,'Node'},{type,3382,node,[]}]]},{type,3383,constraint,[{atom,3383,is_subtype},[{var,3383,'Module'},{type,3383,module,[]}]]},{type,3384,constraint,[{atom,3384,is_subtype},[{var,3384,'Function'},{type,3384,atom,[]}]]},{type,3385,constraint,[{atom,3385,is_subtype},[{var,3385,'Args'},{type,3385,list,[{type,3385,term,[]}]}]]},{type,3386,constraint,[{atom,3386,is_subtype},[{var,3386,'Options'},{type,3386,list,[{var,3386,'Option'}]}]]},{type,3387,constraint,[{atom,3387,is_subtype},[{var,3387,'Option'},{type,3387,union,[{atom,3387,monitor},{type,3388,tuple,[{atom,3388,monitor},{type,3388,list,[{user_type,3388,monitor_option,[]}]}]},{atom,3389,link},{type,3390,tuple,[{atom,3390,reply_tag},{var,3390,'ReplyTag'}]},{type,3391,tuple,[{atom,3391,reply},{var,3391,'Reply'}]},{var,3392,'OtherOption'}]}]]},{type,3393,constraint,[{atom,3393,is_subtype},[{var,3393,'ReplyTag'},{type,3393,term,[]}]]},{type,3394,constraint,[{atom,3394,is_subtype},[{var,3394,'Reply'},{type,3394,union,[{atom,3394,yes},{atom,3394,no},{atom,3394,error_only},{atom,3394,success_only}]}]]},{type,3395,constraint,[{atom,3395,is_subtype},[{var,3395,'OtherOption'},{type,3395,term,[]}]]},{type,3396,constraint,[{atom,3396,is_subtype},[{var,3396,'ReqId'},{type,3396,reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request_abandon,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3413}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<65,98,97,110,100,111,110,32,97,32,112,114,101,118,105,111,117,115,108,121,32,105,115,115,117,101,100,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,97,32,114,101,113,117,101,115,116,32,105,100,101,110,116,105,102,105,101,114,32,112,114,101,118,105,111,117,115,108,121,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]}]},<<32,105,110,32,97,32,99,97,108,108,32,102,114,111,109,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,109,97,100,101,32,116,104,101,32,114,101,113,117,101,115,116,32,99,97,110,32,97,98,97,110,100,111,110,32,116,104,101,32,114,101,113,117,101,115,116,46>>]},{p,[],[<<65,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,99,97,110,32,111,110,108,121,32,98,101,32,115,117,99,99,101,115,115,102,117,108,108,121,32,97,98,97,110,100,111,110,101,100,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,104,97,115,32,99,111,109,112,108,101,116,101,100,46,32,87,104,101,110,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,115,117,99,99,101,115,115,102,117,108,108,121,32,97,98,97,110,100,111,110,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,110,111,116,32,98,101,32,101,102,102,101,99,116,101,100,32,98,121,32,102,117,116,117,114,101,32,100,105,114,101,99,116,32,101,102,102,101,99,116,115,32,111,102,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,116,115,101,108,102,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,119,105,108,108,32,110,111,116,32,114,101,99,101,105,118,101,32,97,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,46,32,84,104,101,32,114,101,113,117,101,115,116,32,105,115,32,104,111,119,101,118,101,114,32,110,111,116,32,119,105,116,104,100,114,97,119,110,44,32,115,111,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,98,101,32,99,114,101,97,116,101,100,32,100,117,101,32,116,111,32,116,104,101,32,114,101,113,117,101,115,116,46,32,73,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,99,114,101,97,116,101,100,32,97,102,116,101,114,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,97,115,32,97,98,97,110,100,111,110,101,100,44,32,110,111,32,109,111,110,105,116,111,114,115,32,110,111,114,32,108,105,110,107,115,32,119,105,108,108,32,98,101,32,115,101,116,32,117,112,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>]},<<32,100,117,101,32,116,111,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46,32,73,102,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,110,99,108,117,100,101,100,32,116,104,101,32>>,{code,[],[<<108,105,110,107>>]},<<32,111,112,116,105,111,110,44,32,116,104,101,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,100,117,101,32,116,111,32,116,104,105,115,32,114,101,113,117,101,115,116,32,119,105,108,108,32,98,101,32,115,101,110,116,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,105,116,115,32,112,97,114,101,110,116,32,119,105,116,104,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<97,98,97,110,100,111,110,101,100>>]},<<32,119,104,101,110,32,105,116,32,105,115,32,100,101,116,101,99,116,101,100,32,116,104,97,116,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,100,117,101,32,116,111,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,97,98,97,110,100,111,110,101,100,32,109,97,121,32,99,111,109,109,117,110,105,99,97,116,101,32,119,105,116,104,32,105,116,115,32,112,97,114,101,110,116,32,97,115,32,97,110,121,32,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,73,116,32,105,115,32>>,{em,[],[<<111,110,108,121>>]},<<32,116,104,101,32,100,105,114,101,99,116,32,101,102,102,101,99,116,115,32,111,110,32,116,104,101,32,112,97,114,101,110,116,32,111,102,32,116,104,101,32,97,99,116,117,97,108,32,115,112,97,119,110,32,114,101,113,117,101,115,116,44,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,97,110,99,101,108,101,100,32,98,121,32,97,98,97,110,100,111,110,105,110,103,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46>>]}]},{p,[],[<<82,101,116,117,114,110,32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,97,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,97,98,97,110,100,111,110,101,100,46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,97,115,32,97,98,97,110,100,111,110,101,100,46,32,84,104,101,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,114,101,113,117,101,115,116,32,105,100,101,110,116,105,102,105,101,114,32,100,105,100,32,110,111,116,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,97,110,32,111,117,116,115,116,97,110,100,105,110,103,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,115,115,117,101,100,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,101,105,116,104,101,114,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<82,101,113,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,112,114,101,118,105,111,117,108,115,121,32,109,97,100,101,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,99,111,109,112,108,101,116,101,100,32,97,110,100,32,97,32,115,112,97,119,110,32,114,101,112,108,121,32,104,97,115,32,97,108,114,101,97,100,121,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,108,101,115,115,32,116,104,101,32,115,112,97,119,110,32,114,101,112,108,121,32,119,97,115,32,100,105,115,97,98,108,101,100,32,105,110,32,116,104,101,32,114,101,113,117,101,115,116,46>>]}]},{li,[],[{p,[],[{code,[],[<<82,101,113,73,100>>]},<<32,100,111,101,115,32,110,111,116,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,109,97,100,101,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]}]}]}]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,105,115,32,110,111,116,32,97,32,114,101,102,101,114,101,110,99,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,57,53>>,signature => [{attribute,3413,spec,{{spawn_request_abandon,1},[{type,3413,'fun',[{type,3413,product,[{ann_type,3413,[{var,3413,'ReqId'},{type,3413,reference,[]}]}]},{type,3413,boolean,[]}]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,split_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1896}],[<<115,112,108,105,116,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,98,105,110,97,114,105,101,115,32,116,104,97,116,32,97,114,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,112,108,105,116,116,105,110,103,32>>,{code,[],[<<66,105,110>>]},<<32,105,110,116,111,32,116,119,111,32,112,97,114,116,115,32,97,116,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<80,111,115>>]},<<46,32,84,104,105,115,32,105,115,32,110,111,116,32,97,32,100,101,115,116,114,117,99,116,105,118,101,32,111,112,101,114,97,116,105,111,110,46,32,65,102,116,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,114,101,32,97,114,101,32,116,104,114,101,101,32,98,105,110,97,114,105,101,115,32,97,108,116,111,103,101,116,104,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,32,61,32,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,34,48,49,50,51,52,53,54,55,56,57,34,41,46,10,60,60,34,48,49,50,51,52,53,54,55,56,57,34,62,62,10,62,32,98,121,116,101,95,115,105,122,101,40,66,41,46,10,49,48,10,62,32,123,66,49,44,32,66,50,125,32,61,32,115,112,108,105,116,95,98,105,110,97,114,121,40,66,44,51,41,46,10,123,60,60,34,48,49,50,34,62,62,44,60,60,34,51,52,53,54,55,56,57,34,62,62,125,10,62,32,98,121,116,101,95,115,105,122,101,40,66,49,41,46,10,51,10,62,32,98,121,116,101,95,115,105,122,101,40,66,50,41,46,10,55>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,54,49>>,signature => [{attribute,1896,spec,{{split_binary,2},[{type,1896,bounded_fun,[{type,1896,'fun',[{type,1896,product,[{var,1896,'Bin'},{var,1896,'Pos'}]},{type,1896,tuple,[{type,1896,binary,[]},{type,1896,binary,[]}]}]},[{type,1897,constraint,[{atom,1897,is_subtype},[{var,1897,'Bin'},{type,1897,binary,[]}]]},{type,1898,constraint,[{atom,1898,is_subtype},[{var,1898,'Pos'},{type,1898,non_neg_integer,[]}]]}]]}]}}]}},{{function,start_timer,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1903}],[<<115,116,97,114,116,95,116,105,109,101,114,47,51>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,40,84,105,109,101,44,32,68,101,115,116,44,32,77,115,103,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,56,53>>,signature => [{attribute,1903,spec,{{erlang,start_timer,3},[{type,1903,bounded_fun,[{type,1903,'fun',[{type,1903,product,[{var,1903,'Time'},{var,1903,'Dest'},{var,1903,'Msg'}]},{var,1903,'TimerRef'}]},[{type,1904,constraint,[{atom,1904,is_subtype},[{var,1904,'Time'},{type,1904,non_neg_integer,[]}]]},{type,1905,constraint,[{atom,1905,is_subtype},[{var,1905,'Dest'},{type,1905,union,[{type,1905,pid,[]},{type,1905,atom,[]}]}]]},{type,1906,constraint,[{atom,1906,is_subtype},[{var,1906,'Msg'},{type,1906,term,[]}]]},{type,1907,constraint,[{atom,1907,is_subtype},[{var,1907,'TimerRef'},{type,1907,reference,[]}]]}]]}]}}]}},{{function,start_timer,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1913}],[<<115,116,97,114,116,95,116,105,109,101,114,47,52>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,87,104,101,110,32,116,104,101,32,116,105,109,101,114,32,101,120,112,105,114,101,115,44,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,84,105,109,101,114,82,101,102,44,32,77,115,103,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,101,115,116>>]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,98,115,44,32,102,97,108,115,101,125>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46,32,73,116,32,109,101,97,110,115,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,32>>,{em,[],[<<114,101,108,97,116,105,118,101>>]},<<32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,97,98,115,44,32,116,114,117,101,125>>]}]},{dd,[],[{p,[],[<<65,98,115,111,108,117,116,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,46,32,84,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,110,32,97,98,115,111,108,117,116,101,32,69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,46>>]}]}]},{p,[],[<<77,111,114,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{p,[],[<<84,104,101,32,97,98,115,111,108,117,116,101,32,112,111,105,110,116,32,105,110,32,116,105,109,101,44,32,116,104,101,32,116,105,109,101,114,32,105,115,32,115,101,116,32,116,111,32,101,120,112,105,114,101,32,111,110,44,32,109,117,115,116,32,98,101,32,105,110,32,116,104,101,32,105,110,116,101,114,118,97,108,32>>,{code,[],[<<91,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111>>]},{code,[],[<<40,115,116,97,114,116,95,116,105,109,101,41,44,32,110,97,116,105,118,101,44,32,109,105,108,108,105,115,101,99,111,110,100,41,44,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111>>]},{code,[],[<<40,101,110,100,95,116,105,109,101,41,44,32,110,97,116,105,118,101,44,32,109,105,108,108,105,115,101,99,111,110,100,41,32,93>>]},<<46,32,73,102,32,97,32,114,101,108,97,116,105,118,101,32,116,105,109,101,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,110,101,103,97,116,105,118,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<44,32,105,116,32,109,117,115,116,32,98,101,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,111,102,32,97,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,111,110,32,116,104,101,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,84,104,105,115,32,112,114,111,99,101,115,115,32,104,97,115,32,101,105,116,104,101,114,32,116,101,114,109,105,110,97,116,101,100,32,111,114,32,110,111,116,46,32,73,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,110,32>>,{code,[],[<<97,116,111,109,40,41>>]},<<44,32,105,116,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,108,111,99,97,108,108,121,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,46,32,84,104,101,32,112,114,111,99,101,115,115,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32,116,104,101,32,110,97,109,101,32,105,115,32,108,111,111,107,101,100,32,117,112,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,116,105,109,101,114,32,101,120,112,105,114,97,116,105,111,110,46,32,78,111,32,101,114,114,111,114,32,105,115,32,114,101,116,117,114,110,101,100,32,105,102,32,116,104,101,32,110,97,109,101,32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<44,32,116,104,101,32,116,105,109,101,114,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,97,110,99,101,108,101,100,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32,116,104,101,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,105,115,32,110,111,116,32,97,108,105,118,101,44,32,111,114,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,46,32,84,104,105,115,32,102,101,97,116,117,114,101,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,82,84,83,32,53,46,52,46,49,49,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,105,109,101,114,115,32,97,114,101,32,110,111,116,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,97,110,99,101,108,101,100,32,119,104,101,110,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,110,32>>,{code,[],[<<97,116,111,109,40,41>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,47,52>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,97,100,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114,47,50>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,100,111,32,110,111,116,32,115,97,116,105,115,102,121,32,116,104,101,32,114,101,113,117,105,114,101,109,101,110,116,115,32,115,112,101,99,105,102,105,101,100,32,104,101,114,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,57,54>>,signature => [{attribute,1913,spec,{{erlang,start_timer,4},[{type,1913,bounded_fun,[{type,1913,'fun',[{type,1913,product,[{var,1913,'Time'},{var,1913,'Dest'},{var,1913,'Msg'},{var,1913,'Options'}]},{var,1913,'TimerRef'}]},[{type,1914,constraint,[{atom,1914,is_subtype},[{var,1914,'Time'},{type,1914,integer,[]}]]},{type,1915,constraint,[{atom,1915,is_subtype},[{var,1915,'Dest'},{type,1915,union,[{type,1915,pid,[]},{type,1915,atom,[]}]}]]},{type,1916,constraint,[{atom,1916,is_subtype},[{var,1916,'Msg'},{type,1916,term,[]}]]},{type,1917,constraint,[{atom,1917,is_subtype},[{var,1917,'Options'},{type,1917,list,[{var,1917,'Option'}]}]]},{type,1918,constraint,[{atom,1918,is_subtype},[{var,1918,'Abs'},{type,1918,boolean,[]}]]},{type,1919,constraint,[{atom,1919,is_subtype},[{var,1919,'Option'},{type,1919,tuple,[{atom,1919,abs},{var,1919,'Abs'}]}]]},{type,1920,constraint,[{atom,1920,is_subtype},[{var,1920,'TimerRef'},{type,1920,reference,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},<<32,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,116,104,97,116,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,116,97,115,107,115,32,116,104,97,116,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,67,80,85,32,98,111,117,110,100,32,97,114,101,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,54,53,54>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2528,bounded_fun,[{type,2528,'fun',[{type,2528,product,[{atom,2528,active_tasks}]},{type,2528,list,[{var,2528,'ActiveTasks'}]}]},[{type,2529,constraint,[{atom,2529,is_subtype},[{var,2529,'ActiveTasks'},{type,2529,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,104,101,114,101,32,101,97,99,104,32,101,108,101,109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,97,99,116,105,118,101,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,111,110,32,101,97,99,104,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,115,99,104,101,100,117,108,101,114,115,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,116,104,97,116,32,97,114,101,32,114,101,97,100,121,32,116,111,32,114,117,110,44,32,111,114,32,97,114,101,32,99,117,114,114,101,110,116,108,121,32,114,117,110,110,105,110,103,46,32,86,97,108,117,101,115,32,102,111,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,97,110,100,32,116,104,101,105,114,32,97,115,115,111,99,105,97,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,108,111,99,97,116,101,100,32,102,105,114,115,116,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,115,99,104,101,100,117,108,101,114,32,110,117,109,98,101,114,32,49,32,97,110,100,32,115,111,32,111,110,46,32,73,102,32,115,117,112,112,111,114,116,32,102,111,114,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,101,120,105,115,116,44,32,97,110,32,101,108,101,109,101,110,116,32,119,105,116,104,32,116,104,101,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,102,111,108,108,111,119,32,97,110,100,32,116,104,101,110,32,97,115,32,108,97,115,116,32,101,108,101,109,101,110,116,32,116,104,101,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,100,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,102,111,108,108,111,119,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,105,108,121,32,97,32,99,111,110,115,105,115,116,101,110,116,32,115,110,97,112,115,104,111,116,32,111,102,32,116,104,101,32,115,116,97,116,101,44,32,98,117,116,32,105,110,115,116,101,97,100,32,113,117,105,116,101,32,101,102,102,105,99,105,101,110,116,108,121,32,103,97,116,104,101,114,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<69,97,99,104,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,104,97,115,32,111,110,101,32,114,117,110,32,113,117,101,117,101,32,116,104,97,116,32,105,116,32,109,97,110,97,103,101,115,46,32,73,102,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,44,32,97,108,108,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,44,32,97,110,100,32,97,108,108,32,100,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,46,32,84,104,97,116,32,105,115,44,32,119,101,32,104,97,118,101,32,109,117,108,116,105,112,108,101,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,44,32,111,110,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,111,110,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,46,32,87,111,114,107,32,99,97,110,32>>,{em,[],[<<110,111,116>>]},<<32,109,105,103,114,97,116,101,32,98,101,116,119,101,101,110,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,114,117,110,32,113,117,101,117,101,115,46,32,79,110,108,121,32,119,111,114,107,32,105,110,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,99,97,110,32,109,105,103,114,97,116,101,32,116,111,32,111,116,104,101,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,46,32,84,104,105,115,32,104,97,115,32,116,111,32,98,101,32,116,97,107,101,110,32,105,110,116,111,32,97,99,99,111,117,110,116,32,119,104,101,110,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,54,55,49>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2530,bounded_fun,[{type,2530,'fun',[{type,2530,product,[{atom,2530,active_tasks_all}]},{type,2530,list,[{var,2530,'ActiveTasks'}]}]},[{type,2531,constraint,[{atom,2531,is_subtype},[{var,2531,'ActiveTasks'},{type,2531,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,99,111,110,116,101,120,116,32,115,119,105,116,99,104,101,115,32,115,105,110,99,101,32,116,104,101,32,115,121,115,116,101,109,32,115,116,97,114,116,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,49,51>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2532,bounded_fun,[{type,2532,'fun',[{type,2532,product,[{atom,2532,context_switches}]},{type,2532,tuple,[{var,2532,'ContextSwitches'},{integer,2532,0}]}]},[{type,2533,constraint,[{atom,2533,is_subtype},[{var,2533,'ContextSwitches'},{type,2533,non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,120,97,99,116,32,114,101,100,117,99,116,105,111,110,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,101,120,97,99,116,95,114,101,100,117,99,116,105,111,110,115,41>>]},<<32,105,115,32,97,32,109,111,114,101,32,101,120,112,101,110,115,105,118,101,32,111,112,101,114,97,116,105,111,110,32,116,104,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,101,100,117,99,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,116,97,116,105,115,116,105,99,115,40,114,101,100,117,99,116,105,111,110,115,41>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,50,50>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2534,bounded_fun,[{type,2534,'fun',[{type,2534,product,[{atom,2534,exact_reductions}]},{type,2534,tuple,[{var,2534,'Total_Exact_Reductions'},{var,2535,'Exact_Reductions_Since_Last_Call'}]}]},[{type,2536,constraint,[{atom,2536,is_subtype},[{var,2536,'Total_Exact_Reductions'},{type,2536,non_neg_integer,[]}]]},{type,2537,constraint,[{atom,2537,is_subtype},[{var,2537,'Exact_Reductions_Since_Last_Call'},{type,2537,non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,116,97,116,105,115,116,105,99,115,40,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,41,46,10,123,56,53,44,50,51,57,54,49,44,48,125>>]}]},{p,[],[<<84,104,105,115,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,105,110,118,97,108,105,100,32,102,111,114,32,115,111,109,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,51,55>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2538,bounded_fun,[{type,2538,'fun',[{type,2538,product,[{atom,2538,garbage_collection}]},{type,2538,tuple,[{var,2538,'Number_of_GCs'},{var,2538,'Words_Reclaimed'},{integer,2538,0}]}]},[{type,2539,constraint,[{atom,2539,is_subtype},[{var,2539,'Number_of_GCs'},{type,2539,non_neg_integer,[]}]]},{type,2540,constraint,[{atom,2540,is_subtype},[{var,2540,'Words_Reclaimed'},{type,2540,non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<73,110,112,117,116>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,114,101,99,101,105,118,101,100,32,116,104,114,111,117,103,104,32,112,111,114,116,115,44,32,97,110,100,32>>,{code,[],[<<79,117,116,112,117,116>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,111,117,116,112,117,116,32,116,111,32,112,111,114,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,52,57>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2541,bounded_fun,[{type,2541,'fun',[{type,2541,product,[{atom,2541,io}]},{type,2541,tuple,[{type,2541,tuple,[{atom,2541,input},{var,2541,'Input'}]},{type,2541,tuple,[{atom,2541,output},{var,2541,'Output'}]}]}]},[{type,2542,constraint,[{atom,2542,is_subtype},[{var,2542,'Input'},{type,2542,non_neg_integer,[]}]]},{type,2543,constraint,[{atom,2543,is_subtype},[{var,2543,'Output'},{type,2543,non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<77,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,101,97,115,117,114,101,32,104,111,119,32,109,117,99,104,32,116,105,109,101,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,112,101,110,100,115,32,100,111,105,110,103,32,118,97,114,105,111,117,115,32,116,97,115,107,115,46,32,73,116,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,98,101,32,97,115,32,108,105,103,104,116,119,101,105,103,104,116,32,97,115,32,112,111,115,115,105,98,108,101,44,32,98,117,116,32,115,111,109,101,32,111,118,101,114,104,101,97,100,32,101,120,105,115,116,115,32,119,104,101,110,32,116,104,105,115,32,105,115,32,101,110,97,98,108,101,100,46,32,77,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,105,115,32,109,101,97,110,116,32,116,111,32,98,101,32,97,32,112,114,111,102,105,108,105,110,103,32,116,111,111,108,32,116,111,32,104,101,108,112,32,102,105,110,100,105,110,103,32,112,101,114,102,111,114,109,97,110,99,101,32,98,111,116,116,108,101,110,101,99,107,115,46,32,84,111,32>>,{code,[],[<<115,116,97,114,116>>]},<<47>>,{code,[],[<<115,116,111,112>>]},<<47>>,{code,[],[<<114,101,115,101,116>>]},<<32,109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,44,32,117,115,101,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>]}]},<<46>>]},{p,[],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41>>]},<<32,114,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,109,97,112,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,115,111,109,101,32,111,102,32,116,104,101,32,79,83,32,116,104,114,101,97,100,115,32,119,105,116,104,105,110,32,69,82,84,83,46,32,69,97,99,104,32,109,97,112,32,99,111,110,116,97,105,110,115,32>>,{code,[],[<<116,121,112,101>>]},<<32,97,110,100,32>>,{code,[],[<<105,100>>]},<<32,102,105,101,108,100,115,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,105,100,101,110,116,105,102,121,32,119,104,97,116,32,116,104,114,101,97,100,32,105,116,32,105,115,44,32,97,110,100,32,97,108,115,111,32,97,32,99,111,117,110,116,101,114,115,32,102,105,101,108,100,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,100,97,116,97,32,97,98,111,117,116,32,104,111,119,32,109,117,99,104,32,116,105,109,101,32,104,97,115,32,98,101,101,110,32,115,112,101,110,116,32,105,110,32,116,104,101,32,118,97,114,105,111,117,115,32,115,116,97,116,101,115,46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41,46,10,91,35,123,99,111,117,110,116,101,114,115,32,61,62,32,35,123,97,117,120,32,61,62,32,49,56,57,57,49,56,50,57,49,52,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,104,101,99,107,95,105,111,32,61,62,32,50,54,48,53,56,54,51,54,48,50,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,109,117,108,97,116,111,114,32,61,62,32,52,53,55,51,49,56,56,48,52,54,51,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,103,99,32,61,62,32,49,53,49,50,50,48,54,57,49,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,116,104,101,114,32,61,62,32,53,52,50,49,51,51,56,52,53,54,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,111,114,116,32,61,62,32,50,50,49,54,51,49,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,108,101,101,112,32,61,62,32,53,49,53,48,50,57,52,49,48,48,125,44,10,32,32,32,105,100,32,61,62,32,49,44,10,32,32,32,116,121,112,101,32,61,62,32,115,99,104,101,100,117,108,101,114,125,124,46,46,46,93>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,117,110,105,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>]}]},<<46,32,83,111,44,32,116,111,32,99,111,110,118,101,114,116,32,105,116,32,116,111,32,109,105,108,108,105,115,101,99,111,110,100,115,44,32,121,111,117,32,99,97,110,32,100,111,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<108,105,115,116,115,58,109,97,112,40,10,32,32,102,117,110,40,35,123,32,99,111,117,110,116,101,114,115,32,58,61,32,67,110,116,32,125,32,61,32,77,41,32,45,62,10,32,32,32,32,32,32,32,32,32,32,77,115,67,110,116,32,61,32,109,97,112,115,58,109,97,112,40,102,117,110,40,95,75,44,32,80,101,114,102,67,111,117,110,116,41,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,40,80,101,114,102,67,111,117,110,116,44,32,112,101,114,102,95,99,111,117,110,116,101,114,44,32,49,48,48,48,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,110,100,44,32,67,110,116,41,44,10,32,32,32,32,32,32,32,32,32,77,35,123,32,99,111,117,110,116,101,114,115,32,58,61,32,77,115,67,110,116,32,125,10,32,32,101,110,100,44,32,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41,41,46>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,115,101,32,118,97,108,117,101,115,32,97,114,101,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,116,104,101,32,101,120,97,99,116,32,116,105,109,101,32,115,112,101,110,116,32,105,110,32,101,97,99,104,32,115,116,97,116,101,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,111,102,32,118,97,114,105,111,117,115,32,111,112,116,105,109,105,115,97,116,105,111,110,32,100,111,110,101,32,116,111,32,107,101,101,112,32,116,104,101,32,111,118,101,114,104,101,97,100,32,97,115,32,115,109,97,108,108,32,97,115,32,112,111,115,115,105,98,108,101,46>>]},{p,[],[{code,[],[<<77,83,65,99,99,95,84,104,114,101,97,100,95,84,121,112,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[<<84,104,101,32,109,97,105,110,32,101,120,101,99,117,116,105,111,110,32,116,104,114,101,97,100,115,32,116,104,97,116,32,100,111,32,109,111,115,116,32,111,102,32,116,104,101,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,83>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[<<84,104,101,32,116,104,114,101,97,100,115,32,102,111,114,32,108,111,110,103,32,114,117,110,110,105,110,103,32,99,112,117,32,105,110,116,101,110,115,105,118,101,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,83,68,99,112,117>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[<<84,104,101,32,116,104,114,101,97,100,115,32,102,111,114,32,108,111,110,103,32,114,117,110,110,105,110,103,32,73,47,79,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,83,68,105,111>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<97,115,121,110,99>>]}]},{dd,[],[<<65,115,121,110,99,32,116,104,114,101,97,100,115,32,97,114,101,32,117,115,101,100,32,98,121,32,118,97,114,105,111,117,115,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,115,32,40,109,97,105,110,108,121,32,116,104,101,32,102,105,108,101,32,100,114,105,118,101,114,115,41,32,100,111,32,111,102,102,108,111,97,100,32,110,111,110,45,67,80,85,32,105,110,116,101,110,115,105,118,101,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,97,115,121,110,99,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,65>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<97,117,120>>]}]},{dd,[],[<<84,97,107,101,115,32,99,97,114,101,32,111,102,32,97,110,121,32,119,111,114,107,32,116,104,97,116,32,105,115,32,110,111,116,32,115,112,101,99,105,102,105,99,97,108,108,121,32,97,115,115,105,103,110,101,100,32,116,111,32,97,32,115,99,104,101,100,117,108,101,114,46>>]},{dt,[],[{code,[],[<<112,111,108,108>>]}]},{dd,[],[<<68,111,101,115,32,116,104,101,32,73,79,32,112,111,108,108,105,110,103,32,102,111,114,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,73,79,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,73,79,116>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32>>,{code,[],[<<77,83,65,99,99,95,84,104,114,101,97,100,95,83,116,97,116,101>>]},<<115,32,97,114,101,32,97,118,97,105,108,97,98,108,101,46,32,65,108,108,32,115,116,97,116,101,115,32,97,114,101,32,101,120,99,108,117,115,105,118,101,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,97,32,116,104,114,101,97,100,32,99,97,110,110,111,116,32,98,101,32,105,110,32,116,119,111,32,115,116,97,116,101,115,32,97,116,32,111,110,99,101,46,32,83,111,44,32,105,102,32,121,111,117,32,97,100,100,32,116,104,101,32,110,117,109,98,101,114,115,32,111,102,32,97,108,108,32,99,111,117,110,116,101,114,115,32,105,110,32,97,32,116,104,114,101,97,100,44,32,121,111,117,32,103,101,116,32,116,104,101,32,116,111,116,97,108,32,114,117,110,116,105,109,101,32,102,111,114,32,116,104,97,116,32,116,104,114,101,97,100,46>>]},{dl,[],[{dt,[],[{code,[],[<<97,117,120>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,104,97,110,100,108,105,110,103,32,97,117,120,105,108,105,97,114,121,32,106,111,98,115,46>>]},{dt,[],[{code,[],[<<99,104,101,99,107,95,105,111>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,99,104,101,99,107,105,110,103,32,102,111,114,32,110,101,119,32,73,47,79,32,101,118,101,110,116,115,46>>]},{dt,[],[{code,[],[<<101,109,117,108,97,116,111,114>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,101,120,101,99,117,116,105,110,103,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,46>>]},{dt,[],[{code,[],[<<103,99>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,104,101,110,32,101,120,116,114,97,32,115,116,97,116,101,115,32,97,114,101,32,101,110,97,98,108,101,100,32,116,104,105,115,32,105,115,32,116,104,101,32,116,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,110,111,110,45,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,46>>]},{dt,[],[{code,[],[<<111,116,104,101,114>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,117,110,97,99,99,111,117,110,116,101,100,32,116,104,105,110,103,115,46>>]},{dt,[],[{code,[],[<<112,111,114,116>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,101,120,101,99,117,116,105,110,103,32,112,111,114,116,115,46>>]},{dt,[],[{code,[],[<<115,108,101,101,112>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,115,108,101,101,112,105,110,103,46>>]}]},{p,[],[<<77,111,114,101,32,102,105,110,101,45,103,114,97,105,110,101,100,32>>,{code,[],[<<77,83,65,99,99,95,84,104,114,101,97,100,95,83,116,97,116,101>>]},<<115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,116,104,114,111,117,103,104,32,99,111,110,102,105,103,117,114,101,32,40,115,117,99,104,32,97,115,32>>,{code,[],[<<46,47,99,111,110,102,105,103,117,114,101,32,45,45,119,105,116,104,45,109,105,99,114,111,115,116,97,116,101,45,97,99,99,111,117,110,116,105,110,103,61,101,120,116,114,97>>]},<<41,46,32,69,110,97,98,108,105,110,103,32,116,104,101,115,101,32,115,116,97,116,101,115,32,99,97,117,115,101,115,32,112,101,114,102,111,114,109,97,110,99,101,32,100,101,103,114,97,100,97,116,105,111,110,32,119,104,101,110,32,109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,102,102,32,97,110,100,32,105,110,99,114,101,97,115,101,115,32,116,104,101,32,111,118,101,114,104,101,97,100,32,119,104,101,110,32,105,116,32,105,115,32,116,117,114,110,101,100,32,111,110,46>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108,111,99>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,109,97,110,97,103,105,110,103,32,109,101,109,111,114,121,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,115,112,114,101,97,100,32,111,117,116,32,111,118,101,114,32,97,108,108,32,111,116,104,101,114,32,115,116,97,116,101,115,46>>]},{dt,[],[{code,[],[<<98,105,102>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,105,110,32,66,73,70,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<98,117,115,121,95,119,97,105,116>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,98,117,115,121,32,119,97,105,116,105,110,103,46,32,84,104,105,115,32,105,115,32,97,108,115,111,32,116,104,101,32,115,116,97,116,101,32,119,104,101,114,101,32,97,32,115,99,104,101,100,117,108,101,114,32,110,111,32,108,111,110,103,101,114,32,114,101,112,111,114,116,115,32,116,104,97,116,32,105,116,32,105,115,32,97,99,116,105,118,101,32,119,104,101,110,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]}]},<<46,32,83,111,44,32,105,102,32,121,111,117,32,97,100,100,32,97,108,108,32,111,116,104,101,114,32,115,116,97,116,101,115,32,98,117,116,32,116,104,105,115,32,97,110,100,32,115,108,101,101,112,44,32,97,110,100,32,116,104,101,110,32,100,105,118,105,100,101,32,116,104,97,116,32,98,121,32,97,108,108,32,116,105,109,101,32,105,110,32,116,104,101,32,116,104,114,101,97,100,44,32,121,111,117,32,115,104,111,117,108,100,32,103,101,116,32,115,111,109,101,116,104,105,110,103,32,118,101,114,121,32,115,105,109,105,108,97,114,32,116,111,32,116,104,101,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,102,114,97,99,116,105,111,110,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<111,116,104,101,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<101,116,115>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,101,120,101,99,117,116,105,110,103,32,69,84,83,32,66,73,70,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<103,99,95,102,117,108,108>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<103,99>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<110,105,102>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,105,110,32,78,73,70,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<115,101,110,100>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,40,112,114,111,99,101,115,115,101,115,32,111,110,108,121,41,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<116,105,109,101,114,115>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,109,97,110,97,103,105,110,103,32,116,105,109,101,114,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<111,116,104,101,114>>]},<<32,115,116,97,116,101,46>>]}]},{p,[],[<<84,104,101,32,117,116,105,108,105,116,121,32,109,111,100,117,108,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,117,110,116,105,109,101,95,116,111,111,108,115,58,109,115,97,99,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,115,97,99,99,40,51,41>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,111,114,101,32,101,97,115,105,108,121,32,97,110,97,108,121,115,101,32,116,104,101,115,101,32,115,116,97,116,105,115,116,105,99,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>]}]},<<32,105,115,32,116,117,114,110,101,100,32,111,102,102,46>>]},{p,[],[<<84,104,101,32,108,105,115,116,32,111,102,32,116,104,114,101,97,100,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,117,110,115,111,114,116,101,100,32,97,110,100,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,100,105,102,102,101,114,101,110,116,32,111,114,100,101,114,32,98,101,116,119,101,101,110,32,99,97,108,108,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,116,104,114,101,97,100,115,32,97,110,100,32,115,116,97,116,101,115,32,97,114,101,32,115,117,98,106,101,99,116,32,116,111,32,99,104,97,110,103,101,32,119,105,116,104,111,117,116,32,97,110,121,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,54,48>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2544,bounded_fun,[{type,2544,'fun',[{type,2544,product,[{atom,2544,microstate_accounting}]},{type,2544,union,[{type,2544,list,[{var,2544,'MSAcc_Thread'}]},{atom,2544,undefined}]}]},[{type,2545,constraint,[{atom,2545,is_subtype},[{var,2545,'MSAcc_Thread'},{type,2545,map,[{type,2545,map_field_exact,[{atom,2545,type},{var,2545,'MSAcc_Thread_Type'}]},{type,2546,map_field_exact,[{atom,2546,id},{var,2546,'MSAcc_Thread_Id'}]},{type,2547,map_field_exact,[{atom,2547,counters},{var,2547,'MSAcc_Counters'}]}]}]]},{type,2548,constraint,[{atom,2548,is_subtype},[{var,2548,'MSAcc_Thread_Type'},{type,2548,union,[{atom,2548,async},{atom,2548,aux},{atom,2548,dirty_io_scheduler},{atom,2549,dirty_cpu_scheduler},{atom,2549,poll},{atom,2549,scheduler}]}]]},{type,2550,constraint,[{atom,2550,is_subtype},[{var,2550,'MSAcc_Thread_Id'},{type,2550,non_neg_integer,[]}]]},{type,2551,constraint,[{atom,2551,is_subtype},[{var,2551,'MSAcc_Counters'},{type,2551,map,[{type,2551,map_field_assoc,[{var,2551,'MSAcc_Thread_State'},{type,2551,non_neg_integer,[]}]}]}]]},{type,2552,constraint,[{atom,2552,is_subtype},[{var,2552,'MSAcc_Thread_State'},{type,2552,union,[{atom,2552,alloc},{atom,2552,aux},{atom,2552,bif},{atom,2552,busy_wait},{atom,2552,check_io},{atom,2553,emulator},{atom,2553,ets},{atom,2553,gc},{atom,2553,gc_fullsweep},{atom,2553,nif},{atom,2554,other},{atom,2554,port},{atom,2554,send},{atom,2554,sleep},{atom,2554,timers}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,114,101,100,117,99,116,105,111,110,115,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,116,97,116,105,115,116,105,99,115,40,114,101,100,117,99,116,105,111,110,115,41,46,10,123,50,48,52,54,44,49,49,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,53,32,40,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,41,44,32,116,104,105,115,32,118,97,108,117,101,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,114,101,100,117,99,116,105,111,110,115,32,112,101,114,102,111,114,109,101,100,32,105,110,32,99,117,114,114,101,110,116,32,116,105,109,101,32,115,108,105,99,101,115,32,111,102,32,99,117,114,114,101,110,116,108,121,32,115,99,104,101,100,117,108,101,100,32,112,114,111,99,101,115,115,101,115,46,32,73,102,32,97,110,32,101,120,97,99,116,32,118,97,108,117,101,32,105,115,32,119,97,110,116,101,100,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,101,120,97,99,116,95,114,101,100,117,99,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,101,120,97,99,116,95,114,101,100,117,99,116,105,111,110,115,41>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,48,51>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2555,bounded_fun,[{type,2555,'fun',[{type,2555,product,[{atom,2555,reductions}]},{type,2555,tuple,[{var,2555,'Total_Reductions'},{var,2556,'Reductions_Since_Last_Call'}]}]},[{type,2557,constraint,[{atom,2557,is_subtype},[{var,2557,'Total_Reductions'},{type,2557,non_neg_integer,[]}]]},{type,2558,constraint,[{atom,2558,is_subtype},[{var,2558,'Reductions_Since_Last_Call'},{type,2558,non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,111,116,97,108,32,108,101,110,103,116,104,32,111,102,32,97,108,108,32,110,111,114,109,97,108,32,97,110,100,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,115,46,32,84,104,97,116,32,105,115,44,32,113,117,101,117,101,100,32,119,111,114,107,32,116,104,97,116,32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,67,80,85,32,98,111,117,110,100,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,99,111,110,115,105,115,116,101,110,116,32,115,110,97,112,115,104,111,116,32,111,102,32,116,104,101,32,115,116,97,116,101,44,32,98,117,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,105,115,32,109,117,99,104,32,109,111,114,101,32,101,120,112,101,110,115,105,118,101,32,99,111,109,112,97,114,101,100,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32,101,115,112,101,99,105,97,108,108,121,32,119,104,101,110,32,97,32,108,97,114,103,101,32,97,109,111,117,110,116,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,105,115,32,117,115,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,50,50>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2559,'fun',[{type,2559,product,[{atom,2559,run_queue}]},{type,2559,non_neg_integer,[]}]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<32,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,116,104,97,116,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,114,117,110,32,113,117,101,117,101,115,32,119,105,116,104,32,119,111,114,107,32,116,104,97,116,32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,67,80,85,32,98,111,117,110,100,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,51,56>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2560,bounded_fun,[{type,2560,'fun',[{type,2560,product,[{atom,2560,run_queue_lengths}]},{type,2560,list,[{var,2560,'RunQueueLength'}]}]},[{type,2561,constraint,[{atom,2561,is_subtype},[{var,2561,'RunQueueLength'},{type,2561,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,104,101,114,101,32,101,97,99,104,32,101,108,101,109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,114,101,97,100,121,32,116,111,32,114,117,110,32,102,111,114,32,101,97,99,104,32,114,117,110,32,113,117,101,117,101,46,32,86,97,108,117,101,115,32,102,111,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,97,114,101,32,108,111,99,97,116,101,100,32,102,105,114,115,116,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,32,111,102,32,115,99,104,101,100,117,108,101,114,32,110,117,109,98,101,114,32,49,32,97,110,100,32,115,111,32,111,110,46,32,73,102,32,115,117,112,112,111,114,116,32,102,111,114,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,101,120,105,115,116,44,32,118,97,108,117,101,115,32,102,111,114,32,116,104,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,102,111,108,108,111,119,32,40,105,110,32,116,104,97,116,32,111,114,100,101,114,41,32,97,116,32,116,104,101,32,101,110,100,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,105,108,121,32,97,32,99,111,110,115,105,115,116,101,110,116,32,115,110,97,112,115,104,111,116,32,111,102,32,116,104,101,32,115,116,97,116,101,44,32,98,117,116,32,105,110,115,116,101,97,100,32,113,117,105,116,101,32,101,102,102,105,99,105,101,110,116,108,121,32,103,97,116,104,101,114,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<69,97,99,104,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,104,97,115,32,111,110,101,32,114,117,110,32,113,117,101,117,101,32,116,104,97,116,32,105,116,32,109,97,110,97,103,101,115,46,32,73,102,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,44,32,97,108,108,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,44,32,97,110,100,32,97,108,108,32,100,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,46,32,84,104,97,116,32,105,115,44,32,119,101,32,104,97,118,101,32,109,117,108,116,105,112,108,101,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,44,32,111,110,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,111,110,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,46,32,87,111,114,107,32,99,97,110,32>>,{em,[],[<<110,111,116>>]},<<32,109,105,103,114,97,116,101,32,98,101,116,119,101,101,110,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,114,117,110,32,113,117,101,117,101,115,46,32,79,110,108,121,32,119,111,114,107,32,105,110,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,99,97,110,32,109,105,103,114,97,116,101,32,116,111,32,111,116,104,101,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,46,32,84,104,105,115,32,104,97,115,32,116,111,32,98,101,32,116,97,107,101,110,32,105,110,116,111,32,97,99,99,111,117,110,116,32,119,104,101,110,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,53,51>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2562,bounded_fun,[{type,2562,'fun',[{type,2562,product,[{atom,2562,run_queue_lengths_all}]},{type,2562,list,[{var,2562,'RunQueueLength'}]}]},[{type,2563,constraint,[{atom,2563,is_subtype},[{var,2563,'RunQueueLength'},{type,2563,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,114,117,110,116,105,109,101,44,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,46>>]},{p,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,102,111,114,32,97,108,108,32,116,104,114,101,97,100,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,97,110,100,32,99,97,110,32,116,104,101,114,101,102,111,114,101,32,98,101,32,103,114,101,97,116,101,114,32,116,104,97,110,32,116,104,101,32,119,97,108,108,32,99,108,111,99,107,32,116,105,109,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,118,97,108,117,101,32,109,105,103,104,116,32,119,114,97,112,32,100,117,101,32,116,111,32,108,105,109,105,116,97,116,105,111,110,115,32,105,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,112,114,111,118,105,100,101,100,32,98,121,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,116,104,97,116,32,105,115,32,117,115,101,100,46>>]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,116,97,116,105,115,116,105,99,115,40,114,117,110,116,105,109,101,41,46,10,123,49,54,57,48,44,49,54,50,48,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,57,54>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2564,bounded_fun,[{type,2564,'fun',[{type,2564,product,[{atom,2564,runtime}]},{type,2564,tuple,[{var,2564,'Total_Run_Time'},{var,2564,'Time_Since_Last_Call'}]}]},[{type,2565,constraint,[{atom,2565,is_subtype},[{var,2565,'Total_Run_Time'},{type,2565,non_neg_integer,[]}]]},{type,2566,constraint,[{atom,2566,is_subtype},[{var,2566,'Time_Since_Last_Call'},{type,2566,non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32,119,105,116,104,32>>,{code,[],[<<123,83,99,104,101,100,117,108,101,114,73,100,44,32,65,99,116,105,118,101,84,105,109,101,44,32,84,111,116,97,108,84,105,109,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<83,99,104,101,100,117,108,101,114,73,100>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,73,68,32,111,102,32,116,104,101,32,115,99,104,101,100,117,108,101,114,44,32>>,{code,[],[<<65,99,116,105,118,101,84,105,109,101>>]},<<32,105,115,32,116,104,101,32,100,117,114,97,116,105,111,110,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,104,97,115,32,98,101,101,110,32,98,117,115,121,44,32,97,110,100,32>>,{code,[],[<<84,111,116,97,108,84,105,109,101>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,116,105,109,101,32,100,117,114,97,116,105,111,110,32,115,105,110,99,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]}]},<<32,97,99,116,105,118,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,99,32,115,99,104,101,100,117,108,101,114,46,32,78,111,116,101,32,116,104,97,116,32,97,99,116,105,118,97,116,105,111,110,32,116,105,109,101,32,99,97,110,32,100,105,102,102,101,114,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,98,101,116,119,101,101,110,32,115,99,104,101,100,117,108,101,114,115,46,32,67,117,114,114,101,110,116,108,121,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,99,116,105,118,97,116,101,100,32,97,116,32,115,121,115,116,101,109,32,115,116,97,114,116,32,119,104,105,108,101,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,99,116,105,118,97,116,101,100,32,115,111,109,101,32,116,105,109,101,32,97,102,116,101,114,32,116,104,101,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,105,115,32,101,110,97,98,108,101,100,46,32,84,104,101,32,116,105,109,101,32,117,110,105,116,32,105,115,32,117,110,100,101,102,105,110,101,100,32,97,110,100,32,99,97,110,32,98,101,32,115,117,98,106,101,99,116,32,116,111,32,99,104,97,110,103,101,32,98,101,116,119,101,101,110,32,114,101,108,101,97,115,101,115,44,32,79,83,115,44,32,97,110,100,32,115,121,115,116,101,109,32,114,101,115,116,97,114,116,115,46,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,116,111,32,99,97,108,99,117,108,97,116,101,32,114,101,108,97,116,105,118,101,32,118,97,108,117,101,115,32,102,111,114,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,46,32>>,{code,[],[<<65,99,116,105,118,101,84,105,109,101>>]},<<32,99,97,110,32,110,101,118,101,114,32,101,120,99,101,101,100,32>>,{code,[],[<<84,111,116,97,108,84,105,109,101>>]},<<46>>]},{p,[],[<<84,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,97,32,98,117,115,121,32,115,99,104,101,100,117,108,101,114,32,105,115,32,119,104,101,110,32,105,116,32,105,115,32,110,111,116,32,105,100,108,101,32,97,110,100,32,105,115,32,110,111,116,32,115,99,104,101,100,117,108,105,110,103,32,40,115,101,108,101,99,116,105,110,103,41,32,97,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,44,32,116,104,97,116,32,105,115,58>>]},{ul,[],[{li,[],[<<69,120,101,99,117,116,105,110,103,32,112,114,111,99,101,115,115,32,99,111,100,101>>]},{li,[],[<<69,120,101,99,117,116,105,110,103,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,111,114,32,78,73,70,32,99,111,100,101>>]},{li,[],[<<69,120,101,99,117,116,105,110,103,32,66,73,70,115,44,32,111,114,32,97,110,121,32,111,116,104,101,114,32,114,117,110,116,105,109,101,32,104,97,110,100,108,105,110,103>>]},{li,[],[<<71,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,110,103>>]},{li,[],[<<72,97,110,100,108,105,110,103,32,97,110,121,32,111,116,104,101,114,32,109,101,109,111,114,121,32,109,97,110,97,103,101,109,101,110,116>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,32,115,99,104,101,100,117,108,101,114,32,99,97,110,32,97,108,115,111,32,98,101,32,98,117,115,121,32,101,118,101,110,32,105,102,32,116,104,101,32,79,83,32,104,97,115,32,115,99,104,101,100,117,108,101,100,32,111,117,116,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]}]},<<32,105,115,32,116,117,114,110,101,100,32,111,102,102,46>>]},{p,[],[<<84,104,101,32,108,105,115,116,32,111,102,32,115,99,104,101,100,117,108,101,114,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,117,110,115,111,114,116,101,100,32,97,110,100,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,100,105,102,102,101,114,101,110,116,32,111,114,100,101,114,32,98,101,116,119,101,101,110,32,99,97,108,108,115,46>>]},{p,[],[<<65,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,57,46,48,44,32,97,108,115,111,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46,32,84,104,97,116,32,105,115,44,32,97,108,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,116,104,97,116,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,104,97,110,100,108,101,32,67,80,85,32,98,111,117,110,100,32,119,111,114,107,46,32,73,102,32,121,111,117,32,97,108,115,111,32,119,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,95,97,108,108,41>>]}]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<78,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,104,97,118,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<49,32,61,60,32,83,99,104,101,100,117,108,101,114,73,100,32,61,60,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46,32,68,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,104,97,118,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,32,60,32,83,99,104,101,100,117,108,101,114,73,100,32,61,60,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,104,97,110,100,108,101,32,115,112,101,99,105,102,105,99,32,116,121,112,101,115,32,111,102,32,106,111,98,115,46,32,69,118,101,114,121,32,106,111,98,32,105,115,32,97,115,115,105,103,110,101,100,32,116,111,32,97,32,115,112,101,99,105,102,105,99,32,115,99,104,101,100,117,108,101,114,32,116,121,112,101,46,32,74,111,98,115,32,99,97,110,32,109,105,103,114,97,116,101,32,98,101,116,119,101,101,110,32,100,105,102,102,101,114,101,110,116,32,115,99,104,101,100,117,108,101,114,115,32,111,102,32,116,104,101,32,115,97,109,101,32,116,121,112,101,44,32,98,117,116,32,110,101,118,101,114,32,98,101,116,119,101,101,110,32,115,99,104,101,100,117,108,101,114,115,32,111,102,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,46,32,84,104,105,115,32,102,97,99,116,32,104,97,115,32,116,111,32,98,101,32,116,97,107,101,110,32,117,110,100,101,114,32,99,111,110,115,105,100,101,114,97,116,105,111,110,32,119,104,101,110,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,114,101,116,117,114,110,101,100,46>>]}]},{p,[],[<<85,115,105,110,103,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,116,111,32,99,97,108,99,117,108,97,116,101,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,44,32,116,114,117,101,41,46,10,102,97,108,115,101,10,62,32,84,115,48,32,61,32,108,105,115,116,115,58,115,111,114,116,40,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41,41,44,32,111,107,46,10,111,107>>]}]},{p,[],[<<83,111,109,101,32,116,105,109,101,32,108,97,116,101,114,32,116,104,101,32,117,115,101,114,32,116,97,107,101,115,32,97,110,111,116,104,101,114,32,115,110,97,112,115,104,111,116,32,97,110,100,32,99,97,108,99,117,108,97,116,101,115,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,112,101,114,32,115,99,104,101,100,117,108,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,84,115,49,32,61,32,108,105,115,116,115,58,115,111,114,116,40,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41,41,44,32,111,107,46,10,111,107,10,62,32,108,105,115,116,115,58,109,97,112,40,102,117,110,40,123,123,73,44,32,65,48,44,32,84,48,125,44,32,123,73,44,32,65,49,44,32,84,49,125,125,41,32,45,62,10,9,123,73,44,32,40,65,49,32,45,32,65,48,41,47,40,84,49,32,45,32,84,48,41,125,32,101,110,100,44,32,108,105,115,116,115,58,122,105,112,40,84,115,48,44,84,115,49,41,41,46,10,91,123,49,44,48,46,57,55,52,51,52,55,52,55,51,48,49,55,55,53,52,56,125,44,10,32,123,50,44,48,46,57,55,52,52,56,52,51,55,56,50,55,53,49,52,52,52,125,44,10,32,123,51,44,48,46,57,57,57,53,57,48,50,51,54,49,54,54,57,48,52,53,125,44,10,32,123,52,44,48,46,57,55,51,56,48,49,50,53,57,54,53,55,50,49,54,49,125,44,10,32,123,53,44,48,46,57,55,49,55,57,53,54,54,54,55,48,49,56,49,48,51,125,44,10,32,123,54,44,48,46,57,55,51,57,50,51,53,56,52,54,52,50,48,55,52,49,125,44,10,32,123,55,44,48,46,57,55,51,50,51,55,48,51,51,48,55,55,56,55,54,125,44,10,32,123,56,44,48,46,57,55,52,49,50,57,55,50,57,51,50,52,56,54,53,54,125,93>>]}]},{p,[],[<<85,115,105,110,103,32,116,104,101,32,115,97,109,101,32,115,110,97,112,115,104,111,116,115,32,116,111,32,99,97,108,99,117,108,97,116,101,32,97,32,116,111,116,97,108,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<62,32,123,65,44,32,84,125,32,61,32,108,105,115,116,115,58,102,111,108,100,108,40,102,117,110,40,123,123,95,44,32,65,48,44,32,84,48,125,44,32,123,95,44,32,65,49,44,32,84,49,125,125,44,32,123,65,105,44,84,105,125,41,32,45,62,10,9,123,65,105,32,43,32,40,65,49,32,45,32,65,48,41,44,32,84,105,32,43,32,40,84,49,32,45,32,84,48,41,125,32,101,110,100,44,32,123,48,44,32,48,125,44,32,108,105,115,116,115,58,122,105,112,40,84,115,48,44,84,115,49,41,41,44,10,9,84,111,116,97,108,83,99,104,101,100,117,108,101,114,85,116,105,108,105,122,97,116,105,111,110,32,61,32,65,47,84,46,10,48,46,57,55,54,57,49,51,54,56,48,51,55,54,52,56,50,53>>]}]},{p,[],[<<84,111,116,97,108,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,119,105,108,108,32,101,113,117,97,108,32>>,{code,[],[<<49,46,48>>]},<<32,119,104,101,110,32,97,108,108,32,115,99,104,101,100,117,108,101,114,115,32,104,97,118,101,32,98,101,101,110,32,97,99,116,105,118,101,32,97,108,108,32,116,104,101,32,116,105,109,101,32,98,101,116,119,101,101,110,32,116,104,101,32,116,119,111,32,109,101,97,115,117,114,101,109,101,110,116,115,46>>]},{p,[],[<<65,110,111,116,104,101,114,32,40,112,114,111,98,97,98,108,121,32,109,111,114,101,41,32,117,115,101,102,117,108,32,118,97,108,117,101,32,105,115,32,116,111,32,99,97,108,99,117,108,97,116,101,32,116,111,116,97,108,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,119,101,105,103,104,116,101,100,32,97,103,97,105,110,115,116,32,109,97,120,105,109,117,109,32,97,109,111,117,110,116,32,111,102,32,97,118,97,105,108,97,98,108,101,32,67,80,85,32,116,105,109,101,58>>]},{pre,[],[{code,[],[<<62,32,87,101,105,103,104,116,101,100,83,99,104,101,100,117,108,101,114,85,116,105,108,105,122,97,116,105,111,110,32,61,32,40,84,111,116,97,108,83,99,104,101,100,117,108,101,114,85,116,105,108,105,122,97,116,105,111,110,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,42,32,40,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,43,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41,41,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101,41,46,10,48,46,57,55,54,57,49,51,54,56,48,51,55,54,52,56,50,53>>]}]},{p,[],[<<84,104,105,115,32,119,101,105,103,104,116,101,100,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,119,105,108,108,32,114,101,97,99,104,32>>,{code,[],[<<49,46,48>>]},<<32,119,104,101,110,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,99,116,105,118,101,32,116,104,101,32,115,97,109,101,32,97,109,111,117,110,116,32,111,102,32,116,105,109,101,32,97,115,32,109,97,120,105,109,117,109,32,97,118,97,105,108,97,98,108,101,32,67,80,85,32,116,105,109,101,46,32,73,102,32,109,111,114,101,32,115,99,104,101,100,117,108,101,114,115,32,101,120,105,115,116,32,116,104,97,110,32,97,118,97,105,108,97,98,108,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,105,115,32,118,97,108,117,101,32,109,97,121,32,98,101,32,103,114,101,97,116,101,114,32,116,104,97,110,32>>,{code,[],[<<49,46,48>>]},<<46>>]},{p,[],[<<65,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,57,46,48,44,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,119,105,108,108,32,97,115,32,100,101,102,97,117,108,116,32,104,97,118,101,32,109,111,114,101,32,115,99,104,101,100,117,108,101,114,115,32,116,104,97,110,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,84,104,105,115,32,100,117,101,32,116,111,32,116,104,101,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,105,115,32,98,121,32,100,101,102,97,117,108,116,32,100,105,115,97,98,108,101,100,46,32,84,111,32,101,110,97,98,108,101,32,105,116,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,44,32,116,114,117,101,41>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,48,49,52>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2567,bounded_fun,[{type,2567,'fun',[{type,2567,product,[{atom,2567,scheduler_wall_time}]},{type,2567,union,[{type,2567,list,[{type,2567,tuple,[{var,2567,'SchedulerId'},{var,2567,'ActiveTime'},{var,2567,'TotalTime'}]}]},{atom,2567,undefined}]}]},[{type,2568,constraint,[{atom,2568,is_subtype},[{var,2568,'SchedulerId'},{type,2568,pos_integer,[]}]]},{type,2569,constraint,[{atom,2569,is_subtype},[{var,2569,'ActiveTime'},{type,2569,non_neg_integer,[]}]]},{type,2570,constraint,[{atom,2570,is_subtype},[{var,2570,'TotalTime'},{type,2570,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66,48,49>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]}]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,97,108,115,111,32,105,110,99,108,117,100,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,108,108,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,46>>]},{p,[],[<<68,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,104,97,118,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},{code,[],[<<32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},{code,[],[<<32,60,32,83,99,104,101,100,117,108,101,114,73,100,32,61,60,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,32,43,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41,32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,119,111,114,107,32,101,120,101,99,117,116,105,110,103,32,111,110,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,109,97,105,110,108,121,32,119,97,105,116,32,102,111,114,32,73,47,79,46,32,84,104,97,116,32,105,115,44,32,119,104,101,110,32,121,111,117,32,103,101,116,32,104,105,103,104,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,111,110,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,44,32,67,80,85,32,117,116,105,108,105,122,97,116,105,111,110,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,104,105,103,104,32,100,117,101,32,116,111,32,116,104,105,115,32,119,111,114,107,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,51,56>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2571,bounded_fun,[{type,2571,'fun',[{type,2571,product,[{atom,2571,scheduler_wall_time_all}]},{type,2571,union,[{type,2571,list,[{type,2571,tuple,[{var,2571,'SchedulerId'},{var,2571,'ActiveTime'},{var,2571,'TotalTime'}]}]},{atom,2571,undefined}]}]},[{type,2572,constraint,[{atom,2572,is_subtype},[{var,2572,'SchedulerId'},{type,2572,pos_integer,[]}]]},{type,2573,constraint,[{atom,2573,is_subtype},[{var,2573,'ActiveTime'},{type,2573,non_neg_integer,[]}]]},{type,2574,constraint,[{atom,2574,is_subtype},[{var,2574,'TotalTime'},{type,2574,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,54,54>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2575,bounded_fun,[{type,2575,'fun',[{type,2575,product,[{atom,2575,total_active_tasks}]},{var,2575,'ActiveTasks'}]},[{type,2576,constraint,[{atom,2576,is_subtype},[{var,2576,'ActiveTasks'},{type,2576,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,55,55>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2577,bounded_fun,[{type,2577,'fun',[{type,2577,product,[{atom,2577,total_active_tasks_all}]},{var,2577,'ActiveTasks'}]},[{type,2578,constraint,[{atom,2578,is_subtype},[{var,2578,'ActiveTasks'},{type,2578,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,56,56>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2579,bounded_fun,[{type,2579,'fun',[{type,2579,product,[{atom,2579,total_run_queue_lengths}]},{var,2579,'TotalRunQueueLengths'}]},[{type,2580,constraint,[{atom,2580,is_subtype},[{var,2580,'TotalRunQueueLengths'},{type,2580,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,57,57>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2581,bounded_fun,[{type,2581,'fun',[{type,2581,product,[{atom,2581,total_run_queue_lengths_all}]},{var,2581,'TotalRunQueueLengths'}]},[{type,2582,constraint,[{atom,2582,is_subtype},[{var,2582,'TotalRunQueueLengths'},{type,2582,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2528}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,119,97,108,108,32,99,108,111,99,107,46,32>>,{code,[],[<<119,97,108,108,95,99,108,111,99,107>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,32,116,104,101,32,115,97,109,101,32,109,97,110,110,101,114,32,97,115,32>>,{code,[],[<<114,117,110,116,105,109,101>>]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,114,101,97,108,32,116,105,109,101,32,105,115,32,109,101,97,115,117,114,101,100,32,97,115,32,111,112,112,111,115,101,100,32,116,111,32,114,117,110,116,105,109,101,32,111,114,32,67,80,85,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,50,49,48>>,signature => [{attribute,2528,spec,{{statistics,1},[{type,2583,bounded_fun,[{type,2583,'fun',[{type,2583,product,[{atom,2583,wall_clock}]},{type,2583,tuple,[{var,2583,'Total_Wallclock_Time'},{var,2584,'Wallclock_Time_Since_Last_Call'}]}]},[{type,2585,constraint,[{atom,2585,is_subtype},[{var,2585,'Total_Wallclock_Time'},{type,2585,non_neg_integer,[]}]]},{type,2586,constraint,[{atom,2586,is_subtype},[{var,2586,'Wallclock_Time_Since_Last_Call'},{type,2586,non_neg_integer,[]}]]}]]}]}}]}},{{function,suspend_process,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1942}],[<<115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>],#{<<101,110>> => [{p,[],[<<83,117,115,112,101,110,100,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,44,32,91,93,41>>]}]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,50,50,49>>,signature => [{attribute,1942,spec,{{erlang,suspend_process,1},[{type,1942,bounded_fun,[{type,1942,'fun',[{type,1942,product,[{var,1942,'Suspendee'}]},{atom,1942,true}]},[{type,1943,constraint,[{atom,1943,is_subtype},[{var,1943,'Suspendee'},{type,1943,pid,[]}]]}]]}]}}]}},{{function,suspend_process,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1926}],[<<115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>],#{<<101,110>> => [{p,[],[<<73,110,99,114,101,97,115,101,115,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,97,110,100,32,112,117,116,115,32,105,116,32,105,110,32,116,104,101,32,115,117,115,112,101,110,100,101,100,32,115,116,97,116,101,32,105,102,32,105,116,32,105,115,32,110,111,116,32,97,108,114,101,97,100,121,32,105,110,32,116,104,97,116,32,115,116,97,116,101,46,32,65,32,115,117,115,112,101,110,100,101,100,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,115,99,104,101,100,117,108,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,32,117,110,116,105,108,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,98,101,101,110,32,114,101,115,117,109,101,100,46>>]},{p,[],[<<65,32,112,114,111,99,101,115,115,32,99,97,110,32,98,101,32,115,117,115,112,101,110,100,101,100,32,98,121,32,109,117,108,116,105,112,108,101,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,99,97,110,32,98,101,32,115,117,115,112,101,110,100,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,98,121,32,97,32,115,105,110,103,108,101,32,112,114,111,99,101,115,115,46,32,65,32,115,117,115,112,101,110,100,101,100,32,112,114,111,99,101,115,115,32,100,111,101,115,32,110,111,116,32,108,101,97,118,101,32,116,104,101,32,115,117,115,112,101,110,100,101,100,32,115,116,97,116,101,32,117,110,116,105,108,32,105,116,115,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,114,101,97,99,104,101,115,32,122,101,114,111,46,32,84,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,102,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,100,101,99,114,101,97,115,101,100,32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,115,117,109,101,95,112,114,111,99,101,115,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,115,117,109,101,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]}]},<<32,105,115,32,99,97,108,108,101,100,32,98,121,32,116,104,101,32,115,97,109,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,97,108,108,101,100,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]},<<46,32,65,108,108,32,105,110,99,114,101,97,115,101,100,32,115,117,115,112,101,110,100,32,99,111,117,110,116,115,32,111,110,32,111,116,104,101,114,32,112,114,111,99,101,115,115,101,115,32,97,99,113,117,105,114,101,100,32,98,121,32,97,32,112,114,111,99,101,115,115,32,97,114,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,99,114,101,97,115,101,100,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,46>>]},{p,[],[<<79,112,116,105,111,110,115,32,40>>,{code,[],[<<79,112,116>>]},<<115,41,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]}]},{dd,[],[{p,[],[<<65,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,101,118,101,110,116,117,97,108,108,121,32,115,117,115,112,101,110,100,115,32,117,110,108,101,115,115,32,105,116,32,105,115,32,114,101,115,117,109,101,100,32,98,101,102,111,114,101,32,105,116,32,99,111,117,108,100,32,115,117,115,112,101,110,100,46,32,84,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<32,114,101,116,117,114,110,115,32,105,109,109,101,100,105,97,116,101,108,121,44,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,115,117,115,112,101,110,100,101,100,32,121,101,116,32,111,114,32,110,111,116,46,32,84,104,101,32,112,111,105,110,116,32,105,110,32,116,105,109,101,32,119,104,101,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,115,117,115,112,101,110,100,115,32,99,97,110,110,111,116,32,98,101,32,100,101,100,117,99,101,100,32,102,114,111,109,32,111,116,104,101,114,32,101,118,101,110,116,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,73,116,32,105,115,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32>>,{em,[],[<<101,118,101,110,116,117,97,108,108,121>>]},<<32,115,117,115,112,101,110,100,115,32,40,117,110,108,101,115,115,32,105,116,32,105,115,32,114,101,115,117,109,101,100,41,46,32,73,102,32,110,111,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,111,112,116,105,111,110,115,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<32,105,115,32,98,108,111,99,107,101,100,32,117,110,116,105,108,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,115,117,115,112,101,110,100,101,100,46>>]}]},{dt,[],[{code,[],[<<123,97,115,121,110,99,104,114,111,110,111,117,115,44,32,82,101,112,108,121,84,97,103,125>>]}]},{dd,[],[{p,[],[<<65,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32,87,104,101,110,32,116,104,101,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,44,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46,32,84,104,101,32,114,101,112,108,121,32,105,115,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,82,101,112,108,121,84,97,103,44,32,83,116,97,116,101,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<83,116,97,116,101>>]},<<32,105,115,32,101,105,116,104,101,114,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,105,116,101,100>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,101,120,105,116,101,100,46>>]}]},{dt,[],[{code,[],[<<115,117,115,112,101,110,100,101,100>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,119,32,115,117,115,112,101,110,100,101,100,46>>]}]},{dt,[],[{code,[],[<<110,111,116,95,115,117,115,112,101,110,100,101,100>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,115,117,115,112,101,110,100,101,100,46,32,84,104,105,115,32,99,97,110,32,111,110,108,121,32,104,97,112,112,101,110,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,105,115,115,117,101,100,32,116,104,105,115,32,114,101,113,117,101,115,116,44,32,104,97,118,101,32,99,97,108,108,101,100,32>>,{code,[],[<<114,101,115,117,109,101,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]},<<32,98,101,102,111,114,101,32,103,101,116,116,105,110,103,32,116,104,101,32,114,101,112,108,121,46>>]}]}]},{p,[],[<<65,112,112,97,114,116,32,102,114,111,109,32,116,104,101,32,114,101,112,108,121,32,109,101,115,115,97,103,101,44,32,116,104,101,32>>,{code,[],[<<123,97,115,121,110,99,104,114,111,110,111,117,115,44,32,82,101,112,108,121,84,97,103,125>>]},<<32,111,112,116,105,111,110,32,98,101,104,97,118,101,115,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,111,112,116,105,111,110,32,119,105,116,104,111,117,116,32,114,101,112,108,121,32,116,97,103,46>>]}]},{dt,[],[{code,[],[<<117,110,108,101,115,115,95,115,117,115,112,101,110,100,105,110,103>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,115,117,115,112,101,110,100,101,100,32,117,110,108,101,115,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,108,114,101,97,100,121,32,105,115,32,115,117,115,112,101,110,100,105,110,103,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32,73,102,32>>,{code,[],[<<117,110,108,101,115,115,95,115,117,115,112,101,110,100,105,110,103>>]},<<32,105,115,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<44,32,97,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,32,117,110,108,101,115,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,108,114,101,97,100,121,32,105,115,32,115,117,115,112,101,110,100,105,110,103,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,111,114,32,105,102,32,97,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,97,108,114,101,97,100,121,32,104,97,115,32,98,101,101,110,32,115,101,110,116,32,97,110,100,32,105,115,32,105,110,32,116,114,97,110,115,105,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,108,114,101,97,100,121,32,105,115,32,115,117,115,112,101,110,100,105,110,103,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<44,32,111,114,32,105,102,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,97,110,100,32,97,32,115,101,110,100,32,114,101,113,117,101,115,116,32,97,108,114,101,97,100,121,32,105,115,32,105,110,32,116,114,97,110,115,105,116,44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,97,110,100,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,114,101,109,97,105,110,115,32,117,110,99,104,97,110,103,101,100,46>>]}]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,105,110,99,114,101,97,115,101,100,44,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<89,111,117,32,99,97,110,32,101,97,115,105,108,121,32,99,114,101,97,116,101,32,100,101,97,100,108,111,99,107,115,32,105,102,32,112,114,111,99,101,115,115,101,115,32,115,117,115,112,101,110,100,115,32,101,97,99,104,32,111,116,104,101,114,32,40,100,105,114,101,99,116,108,121,32,111,114,32,105,110,32,99,105,114,99,108,101,115,41,46,32,73,110,32,69,82,84,83,32,118,101,114,115,105,111,110,115,32,112,114,105,111,114,32,116,111,32,69,82,84,83,32,118,101,114,115,105,111,110,32,49,48,46,48,44,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,112,114,101,118,101,110,116,101,100,32,115,117,99,104,32,100,101,97,100,108,111,99,107,115,44,32,98,117,116,32,116,104,105,115,32,112,114,101,118,101,110,116,105,111,110,32,104,97,115,32,110,111,119,32,98,101,101,110,32,114,101,109,111,118,101,100,32,100,117,101,32,116,111,32,112,101,114,102,111,114,109,97,110,99,101,32,114,101,97,115,111,110,115,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,116,104,101,32,115,97,109,101,32,112,114,111,99,101,115,115,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,114,101,115,105,100,101,115,32,111,110,32,97,110,111,116,104,101,114,32,110,111,100,101,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,76,105,115,116>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116>>]},<<115,46>>]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,109,111,114,101,32,116,105,109,101,115,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,116,104,97,110,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,105,110,116,101,114,110,97,108,32,100,97,116,97,32,115,116,114,117,99,116,117,114,101,115,46,32,84,104,101,32,115,121,115,116,101,109,32,108,105,109,105,116,32,105,115,32,103,114,101,97,116,101,114,32,116,104,97,110,32,50,44,48,48,48,44,48,48,48,44,48,48,48,32,115,117,115,112,101,110,100,115,32,97,110,100,32,119,105,108,108,32,110,101,118,101,114,32,98,101,32,108,111,119,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,50,51,54>>,signature => [{attribute,1926,spec,{{erlang,suspend_process,2},[{type,1926,bounded_fun,[{type,1926,'fun',[{type,1926,product,[{var,1926,'Suspendee'},{var,1926,'OptList'}]},{type,1926,boolean,[]}]},[{type,1927,constraint,[{atom,1927,is_subtype},[{var,1927,'Suspendee'},{type,1927,pid,[]}]]},{type,1928,constraint,[{atom,1928,is_subtype},[{var,1928,'OptList'},{type,1928,list,[{var,1928,'Opt'}]}]]},{type,1929,constraint,[{atom,1929,is_subtype},[{var,1929,'Opt'},{type,1929,union,[{atom,1929,unless_suspending},{atom,1929,asynchronous},{type,1929,tuple,[{atom,1929,asynchronous},{type,1929,term,[]}]}]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,120,105,109,117,109,32,100,101,112,116,104,32,111,102,32,99,97,108,108,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,115,32,105,110,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<39,69,88,73,84,39>>]},<<32,116,117,112,108,101,115,46,32,84,104,101,32,102,108,97,103,32,97,108,115,111,32,108,105,109,105,116,115,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,32,100,101,112,116,104,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111>>]},<<32,105,116,101,109,32>>,{code,[],[<<99,117,114,114,101,110,116,95,115,116,97,99,107,116,114,97,99,101,46>>]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,56,50>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2606,bounded_fun,[{type,2606,'fun',[{type,2606,product,[{atom,2606,backtrace_depth},{var,2606,'Depth'}]},{var,2606,'OldDepth'}]},[{type,2607,constraint,[{atom,2607,is_subtype},[{var,2607,'Depth'},{type,2607,non_neg_integer,[]}]]},{type,2608,constraint,[{atom,2608,is_subtype},[{var,2608,'OldDepth'},{type,2608,non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<99,112,117,95,116,111,112,111,108,111,103,121>>}],[]},{li,[{name,<<105,110,102,111,95,108,105,115,116>>}],[]},{li,[{name,<<108,101,118,101,108,95,101,110,116,114,121>>}],[]},{li,[{name,<<108,101,118,101,108,95,116,97,103>>}],[]},{li,[{name,<<115,117,98,95,108,101,118,101,108>>}],[]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[{em,[],[<<84,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46>>]},<<32,73,110,115,116,101,97,100,32,111,102,32,117,115,105,110,103,32,116,104,105,115,32,97,114,103,117,109,101,110,116,44,32,117,115,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,114,101,109,111,118,101,100,44,32,97,32,102,105,110,97,108,32,67,80,85,32,116,111,112,111,108,111,103,121,32,116,111,32,117,115,101,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,46>>]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<46,32,84,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121,32,111,118,101,114,114,105,100,101,115,32,97,110,121,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121,46,32,66,121,32,112,97,115,115,105,110,103,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,97,115,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<44,32,116,104,101,32,115,121,115,116,101,109,32,114,101,118,101,114,116,115,32,116,111,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,46,32,84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,101,113,117,97,108,115,32,116,104,101,32,118,97,108,117,101,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,99,112,117,95,116,111,112,111,108,111,103,121,41>>]},<<32,98,101,102,111,114,101,32,116,104,101,32,99,104,97,110,103,101,32,119,97,115,32,109,97,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<84,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,117,115,101,100,32,119,104,101,110,32,98,105,110,100,105,110,103,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,73,102,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,108,114,101,97,100,121,32,98,111,117,110,100,32,119,104,101,110,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,99,104,97,110,103,101,100,44,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,115,101,110,116,32,97,32,114,101,113,117,101,115,116,32,116,111,32,114,101,98,105,110,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,110,101,119,32,67,80,85,32,116,111,112,111,108,111,103,121,46>>]},{p,[],[<<84,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,121,112,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,97,110,100,32,109,111,114,101,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,99,112,117,95,116,111,112,111,108,111,103,121,41>>]}]},<<32,97,115,32,119,101,108,108,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,57,52>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2609,bounded_fun,[{type,2609,'fun',[{type,2609,product,[{atom,2609,cpu_topology},{var,2609,'CpuTopology'}]},{var,2609,'OldCpuTopology'}]},[{type,2610,constraint,[{atom,2610,is_subtype},[{var,2610,'CpuTopology'},{user_type,2610,cpu_topology,[]}]]},{type,2611,constraint,[{atom,2611,is_subtype},[{var,2611,'OldCpuTopology'},{user_type,2611,cpu_topology,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,82,97,110,103,101,32,105,115,32>>,{code,[],[<<49,32,60,61,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,32,60,61,32,78>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,99,104,97,110,103,101,32,105,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,104,97,110,103,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,49,50,32,115,99,104,101,100,117,108,101,114,115,32,97,110,100,32,54,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,111,110,108,105,110,101,44,32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>]},<<32,105,115,32,117,115,101,100,32,116,111,32,115,101,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,116,111,32,54,44,32,116,104,101,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,99,114,101,97,115,101,100,32,98,121,32,104,97,108,102,32,97,115,32,119,101,108,108,44,32,100,111,119,110,32,116,111,32,51,46,32,83,105,109,105,108,97,114,108,121,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,110,99,114,101,97,115,101,115,32,112,114,111,112,111,114,116,105,111,110,97,108,108,121,32,116,111,32,105,110,99,114,101,97,115,101,115,32,105,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,52,52,50>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2612,bounded_fun,[{type,2612,'fun',[{type,2612,product,[{atom,2612,dirty_cpu_schedulers_online},{var,2612,'DirtyCPUSchedulersOnline'}]},{var,2613,'OldDirtyCPUSchedulersOnline'}]},[{type,2614,constraint,[{atom,2614,is_subtype},[{var,2614,'DirtyCPUSchedulersOnline'},{type,2614,pos_integer,[]}]]},{type,2615,constraint,[{atom,2615,is_subtype},[{var,2615,'OldDirtyCPUSchedulersOnline'},{type,2615,pos_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,115,121,115,116,101,109,32,102,108,97,103,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<46,32>>,{code,[],[<<65,108,108,111,99>>]},<<32,105,115,32,116,104,101,32,97,108,108,111,99,97,116,111,114,32,116,111,32,97,102,102,101,99,116,44,32,102,111,114,32,101,120,97,109,112,108,101,32>>,{code,[],[<<98,105,110,97,114,121,95,97,108,108,111,99>>]},<<46,32>>,{code,[],[<<70>>]},<<32,105,115,32,116,104,101,32,102,108,97,103,32,116,111,32,99,104,97,110,103,101,32,97,110,100,32>>,{code,[],[<<86>>]},<<32,105,115,32,116,104,101,32,110,101,119,32,118,97,108,117,101,46>>]},{p,[],[<<79,110,108,121,32,97,32,115,117,98,115,101,116,32,111,102,32,97,108,108,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99>>]},<<32,102,108,97,103,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,114,117,110,32,116,105,109,101,46,32,84,104,105,115,32,115,117,98,115,101,116,32,105,115,32,99,117,114,114,101,110,116,108,121,32,111,110,108,121,32,116,104,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99,35,77,95,115,98,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<115,98,99,116>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,116,104,101,32,102,108,97,103,32,119,97,115,32,115,101,116,32,111,114,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,105,102,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,52,55,49>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2616,bounded_fun,[{type,2616,'fun',[{type,2616,product,[{atom,2616,erts_alloc},{type,2616,tuple,[{var,2616,'Alloc'},{var,2616,'F'},{var,2616,'V'}]}]},{type,2616,union,[{atom,2616,ok},{atom,2616,notsup}]}]},[{type,2617,constraint,[{atom,2617,is_subtype},[{var,2617,'Alloc'},{type,2617,atom,[]}]]},{type,2618,constraint,[{atom,2618,is_subtype},[{var,2618,'F'},{type,2618,atom,[]}]]},{type,2619,constraint,[{atom,2619,is_subtype},[{var,2619,'V'},{type,2619,integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,50,46,51>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<46,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,105,115,32,97,32,110,111,110,45,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,32,105,110,100,105,99,97,116,105,110,103,32,104,111,119,32,109,97,110,121,32,116,105,109,101,115,32,103,101,110,101,114,97,116,105,111,110,97,108,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,32,99,97,110,32,98,101,32,100,111,110,101,32,119,105,116,104,111,117,116,32,102,111,114,99,105,110,103,32,97,32,102,117,108,108,115,119,101,101,112,32,99,111,108,108,101,99,116,105,111,110,46,32,84,104,101,32,118,97,108,117,101,32,97,112,112,108,105,101,115,32,116,111,32,110,101,119,32,112,114,111,99,101,115,115,101,115,44,32,119,104,105,108,101,32,112,114,111,99,101,115,115,101,115,32,97,108,114,101,97,100,121,32,114,117,110,110,105,110,103,32,97,114,101,32,110,111,116,32,97,102,102,101,99,116,101,100,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<73,110,32,108,111,119,45,109,101,109,111,114,121,32,115,121,115,116,101,109,115,32,40,101,115,112,101,99,105,97,108,108,121,32,119,105,116,104,111,117,116,32,118,105,114,116,117,97,108,32,109,101,109,111,114,121,41,44,32,115,101,116,116,105,110,103,32,116,104,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<48>>]},<<32,99,97,110,32,104,101,108,112,32,116,111,32,99,111,110,115,101,114,118,101,32,109,101,109,111,114,121,46>>]},{p,[],[<<84,104,105,115,32,118,97,108,117,101,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,116,104,114,111,117,103,104,32,40,79,83,41,32,101,110,118,105,114,111,110,109,101,110,116,32,118,97,114,105,97,98,108,101,32>>,{code,[],[<<69,82,76,95,70,85,76,76,83,87,69,69,80,95,65,70,84,69,82>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,52,56,56>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2620,bounded_fun,[{type,2620,'fun',[{type,2620,product,[{atom,2620,fullsweep_after},{var,2620,'Number'}]},{var,2620,'OldNumber'}]},[{type,2621,constraint,[{atom,2621,is_subtype},[{var,2621,'Number'},{type,2621,non_neg_integer,[]}]]},{type,2622,constraint,[{atom,2622,is_subtype},[{var,2622,'OldNumber'},{type,2622,non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<84,117,114,110,115,32,111,110,47,111,102,102,32,109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,109,101,97,115,117,114,101,109,101,110,116,115,46,32,87,104,101,110,32,112,97,115,115,105,110,103,32,114,101,115,101,116,44,32,97,108,108,32,99,111,117,110,116,101,114,115,32,97,114,101,32,114,101,115,101,116,32,116,111,32,48,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,48,55>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2623,bounded_fun,[{type,2623,'fun',[{type,2623,product,[{atom,2623,microstate_accounting},{var,2623,'Action'}]},{var,2623,'OldState'}]},[{type,2624,constraint,[{atom,2624,is_subtype},[{var,2624,'Action'},{type,2624,union,[{atom,2624,true},{atom,2624,false},{atom,2624,reset}]}]]},{type,2625,constraint,[{atom,2625,is_subtype},[{var,2625,'OldState'},{type,2625,union,[{atom,2625,true},{atom,2625,false}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,46,32,84,104,101,32,115,105,122,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,119,111,114,100,115,46,32,84,104,101,32,110,101,119,32>>,{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]},<<32,101,102,102,101,99,116,115,32,111,110,108,121,32,112,114,111,99,101,115,115,101,115,32,115,112,97,119,110,101,100,32,97,102,116,101,114,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32>>,{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]},<<32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32>>,{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,112,114,111,99,101,115,115,101,115,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,50,49>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2626,bounded_fun,[{type,2626,'fun',[{type,2626,product,[{atom,2626,min_heap_size},{var,2626,'MinHeapSize'}]},{var,2626,'OldMinHeapSize'}]},[{type,2627,constraint,[{atom,2627,is_subtype},[{var,2627,'MinHeapSize'},{type,2627,non_neg_integer,[]}]]},{type,2628,constraint,[{atom,2628,is_subtype},[{var,2628,'OldMinHeapSize'},{type,2628,non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,46,32,84,104,101,32,115,105,122,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,119,111,114,100,115,46,32,84,104,101,32,110,101,119,32>>,{code,[],[<<109,105,110,95,98,105,110,95,118,104,104,101,97,112,95,115,105,122,101>>]},<<32,101,102,102,101,99,116,115,32,111,110,108,121,32,112,114,111,99,101,115,115,101,115,32,115,112,97,119,110,101,100,32,97,102,116,101,114,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32>>,{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]},<<32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32>>,{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,112,114,111,99,101,115,115,101,115,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,50,44,51,44,52>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,51,54>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2629,bounded_fun,[{type,2629,'fun',[{type,2629,product,[{atom,2629,min_bin_vheap_size},{var,2629,'MinBinVHeapSize'}]},{var,2630,'OldMinBinVHeapSize'}]},[{type,2631,constraint,[{atom,2631,is_subtype},[{var,2631,'MinBinVHeapSize'},{type,2631,non_neg_integer,[]}]]},{type,2632,constraint,[{atom,2632,is_subtype},[{var,2632,'OldMinBinVHeapSize'},{type,2632,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,51,66,48,52>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,115,101,116,116,105,110,103,115,32,102,111,114,32,112,114,111,99,101,115,115,101,115,46,32,84,104,101,32,115,105,122,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,119,111,114,100,115,46,32,84,104,101,32,110,101,119,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,101,102,102,101,99,116,115,32,111,110,108,121,32,112,114,111,99,101,115,115,101,115,32,115,112,97,119,110,101,100,32,101,102,116,101,114,32,116,104,101,32,99,104,97,110,103,101,32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,112,114,111,99,101,115,115,101,115,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,50,44,51,44,52>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,53,51>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2633,bounded_fun,[{type,2633,'fun',[{type,2633,product,[{atom,2633,max_heap_size},{var,2633,'MaxHeapSize'}]},{var,2633,'OldMaxHeapSize'}]},[{type,2634,constraint,[{atom,2634,is_subtype},[{var,2634,'MaxHeapSize'},{user_type,2634,max_heap_size,[]}]]},{type,2635,constraint,[{atom,2635,is_subtype},[{var,2635,'OldMaxHeapSize'},{user_type,2635,max_heap_size,[]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,101,110,97,98,108,101,100,44,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,105,115,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,77,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,99,97,110,32,98,101,32,98,108,111,99,107,101,100,32,105,110,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,46,32,69,105,116,104,101,114,32,97,108,108,32,115,99,104,101,100,117,108,101,114,115,32,98,117,116,32,111,110,101,32,105,115,32,98,108,111,99,107,101,100,44,32,111,114,32,97,108,108,32>>,{em,[],[<<110,111,114,109,97,108>>]},<<32,115,99,104,101,100,117,108,101,114,115,32,98,117,116,32,111,110,101,32,105,115,32,98,108,111,99,107,101,100,46,32,87,104,101,110,32,111,110,108,121,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,108,111,99,107,101,100,44,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,102,114,101,101,32,116,111,32,99,111,110,116,105,110,117,101,32,116,111,32,115,99,104,101,100,117,108,101,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,98,108,111,99,107>>]},<<44,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,111,110,101,32,97,110,100,32,111,110,108,121,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,119,105,108,108,32,101,120,101,99,117,116,101,46,32,73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,117,110,98,108,111,99,107>>]},<<32,97,110,100,32,110,111,32,111,110,101,32,101,108,115,101,32,98,108,111,99,107,115,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,44,32,97,110,100,32,116,104,105,115,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,111,110,108,121,32,111,110,99,101,44,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,117,110,98,108,111,99,107,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,98,108,111,99,107,95,110,111,114,109,97,108>>]},<<44,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,111,110,101,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,119,105,108,108,32,101,120,101,99,117,116,101,44,32,98,117,116,32,109,117,108,116,105,112,108,101,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,99,97,110,32,101,120,101,99,117,116,101,46,32,73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,117,110,98,108,111,99,107,95,110,111,114,109,97,108>>]},<<32,97,110,100,32,110,111,32,111,110,101,32,101,108,115,101,32,98,108,111,99,107,115,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,44,32,97,110,100,32,116,104,105,115,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,111,110,108,121,32,111,110,99,101,44,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,117,110,98,108,111,99,107,101,100,46>>]},{p,[],[<<79,110,101,32,112,114,111,99,101,115,115,32,99,97,110,32,98,108,111,99,107,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,46,32,73,102,32,97,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,44,32,105,116,32,109,117,115,116,32,117,110,98,108,111,99,107,32,101,120,97,99,116,108,121,32,97,115,32,109,97,110,121,32,116,105,109,101,115,32,97,115,32,105,116,32,104,97,115,32,98,108,111,99,107,101,100,32,98,101,102,111,114,101,32,105,116,32,104,97,115,32,114,101,108,101,97,115,101,100,32,105,116,115,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,98,108,111,99,107,46,32,73,102,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,111,114,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,101,120,105,116,115,44,32,105,116,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,108,101,97,115,101,115,32,105,116,115,32,98,108,111,99,107,105,110,103,32,111,102,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,97,114,101,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<44,32>>,{code,[],[<<98,108,111,99,107,101,100>>]},<<44,32>>,{code,[],[<<98,108,111,99,107,101,100,95,110,111,114,109,97,108>>]},<<44,32,111,114,32>>,{code,[],[<<101,110,97,98,108,101,100>>]},<<46,32,84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,100,101,115,99,114,105,98,101,115,32,116,104,101,32,115,116,97,116,101,32,106,117,115,116,32,97,102,116,101,114,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]},<<32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,108,111,99,107,105,110,103,32,111,102,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,110,111,114,109,97,108,108,121,32,110,111,116,32,110,101,101,100,101,100,46,32,73,102,32,121,111,117,32,102,101,101,108,32,116,104,97,116,32,121,111,117,32,110,101,101,100,32,116,111,32,117,115,101,32,116,104,101,115,101,32,102,101,97,116,117,114,101,115,44,32,99,111,110,115,105,100,101,114,32,105,116,32,97,32,102,101,119,32,109,111,114,101,32,116,105,109,101,115,32,97,103,97,105,110,46,32,66,108,111,99,107,105,110,103,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,97,115,32,97,32,108,97,115,116,32,114,101,115,111,114,116,44,32,97,115,32,105,116,32,105,115,32,109,111,115,116,32,108,105,107,101,108,121,32,97,32>>,{em,[],[<<118,101,114,121,32,105,110,101,102,102,105,99,105,101,110,116>>]},<<32,119,97,121,32,116,111,32,115,111,108,118,101,32,116,104,101,32,112,114,111,98,108,101,109,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,55,49>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2636,bounded_fun,[{type,2636,'fun',[{type,2636,product,[{atom,2636,multi_scheduling},{var,2636,'BlockState'}]},{var,2636,'OldBlockState'}]},[{type,2637,constraint,[{atom,2637,is_subtype},[{var,2637,'BlockState'},{type,2637,union,[{atom,2637,block},{atom,2637,unblock},{atom,2637,block_normal},{atom,2637,unblock_normal}]}]]},{type,2638,constraint,[{atom,2638,is_subtype},[{var,2638,'OldBlockState'},{type,2638,union,[{atom,2638,blocked},{atom,2638,disabled},{atom,2638,enabled}]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>}],[]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[{em,[],[<<84,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46>>]},<<32,73,110,115,116,101,97,100,32,111,102,32,117,115,105,110,103,32,116,104,105,115,32,97,114,103,117,109,101,110,116,44,32,117,115,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,87,104,101,110,32,116,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,114,101,109,111,118,101,100,44,32,97,32,102,105,110,97,108,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,32,116,121,112,101,32,116,111,32,117,115,101,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,46>>]}]},{p,[],[<<67,111,110,116,114,111,108,115,32,105,102,32,97,110,100,32,104,111,119,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,111,117,110,100,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]},{p,[],[<<87,104,101,110,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101,44,32,72,111,119,41>>]},<<32,105,115,32,99,97,108,108,101,100,44,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,32,116,111,32,97,108,108,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,44,32,99,97,117,115,105,110,103,32,116,104,101,109,32,116,111,32,116,114,121,32,116,111,32,98,105,110,100,32,111,114,32,117,110,98,105,110,100,32,97,115,32,114,101,113,117,101,115,116,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,97,32,115,99,104,101,100,117,108,101,114,32,102,97,105,108,115,32,116,111,32,98,105,110,100,44,32,116,104,105,115,32,105,115,32,111,102,116,101,110,32,115,105,108,101,110,116,108,121,32,105,103,110,111,114,101,100,44,32,97,115,32,105,116,32,105,115,32,110,111,116,32,97,108,119,97,121,115,32,112,111,115,115,105,98,108,101,32,116,111,32,118,101,114,105,102,121,32,118,97,108,105,100,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,115,46,32,73,102,32,97,110,32,101,114,114,111,114,32,105,115,32,114,101,112,111,114,116,101,100,44,32,97,110,32,101,114,114,111,114,32,101,118,101,110,116,32,105,115,32,108,111,103,103,101,100,46,32,84,111,32,118,101,114,105,102,121,32,116,104,97,116,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,32,104,97,118,101,32,98,111,117,110,100,32,97,115,32,114,101,113,117,101,115,116,101,100,44,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<46>>]}]},{p,[],[<<83,99,104,101,100,117,108,101,114,115,32,99,97,110,32,98,101,32,98,111,117,110,100,32,111,110,32,110,101,119,101,114,32,76,105,110,117,120,44,32,83,111,108,97,114,105,115,44,32,70,114,101,101,66,83,68,44,32,97,110,100,32,87,105,110,100,111,119,115,32,115,121,115,116,101,109,115,44,32,98,117,116,32,109,111,114,101,32,115,121,115,116,101,109,115,32,119,105,108,108,32,98,101,32,115,117,112,112,111,114,116,101,100,32,105,110,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,115,46>>]},{p,[],[<<73,110,32,111,114,100,101,114,32,102,111,114,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,116,111,32,98,101,32,97,98,108,101,32,116,111,32,98,105,110,100,32,115,99,104,101,100,117,108,101,114,115,44,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,109,117,115,116,32,98,101,32,107,110,111,119,110,46,32,73,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,102,97,105,108,115,32,116,111,32,100,101,116,101,99,116,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,97,117,116,111,109,97,116,105,99,97,108,108,121,44,32,105,116,32,99,97,110,32,98,101,32,100,101,102,105,110,101,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,104,111,119,32,116,111,32,100,101,102,105,110,101,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,111,101,115,32,98,121,32,100,101,102,97,117,108,116,32>>,{em,[],[<<110,111,116>>]},<<32,98,105,110,100,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,116,104,101,32,111,110,108,121,32,79,83,32,112,114,111,99,101,115,115,32,98,105,110,100,105,110,103,32,116,104,114,101,97,100,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,105,115,32,105,109,112,114,111,118,101,115,32,116,104,101,32,112,101,114,102,111,114,109,97,110,99,101,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,116,104,101,114,32,79,83,32,112,114,111,99,101,115,115,101,115,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,110,111,116,104,101,114,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,41,32,97,108,115,111,32,98,105,110,100,32,116,104,114,101,97,100,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,101,114,101,32,99,97,110,32,98,101,32,97,32,112,101,114,102,111,114,109,97,110,99,101,32,112,101,110,97,108,116,121,32,105,110,115,116,101,97,100,46,32,83,111,109,101,116,105,109,101,115,32,116,104,105,115,32,112,101,114,102,111,114,109,97,110,99,101,32,112,101,110,97,108,116,121,32,99,97,110,32,98,101,32,115,101,118,101,114,101,46,32,73,102,32,115,111,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,110,111,116,32,98,105,110,100,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,46>>]}]},{p,[],[<<83,99,104,101,100,117,108,101,114,115,32,99,97,110,32,98,101,32,98,111,117,110,100,32,105,110,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,46,32,65,114,103,117,109,101,110,116,32>>,{code,[],[<<72,111,119>>]},<<32,100,101,116,101,114,109,105,110,101,115,32,104,111,119,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,111,117,110,100,32,97,110,100,32,99,97,110,32,98,101,32,97,110,121,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<117,110,98,111,117,110,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,117>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,110,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<116,104,114,101,97,100,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,116,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,111,114,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,112,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,95,110,111,100,101,95,116,104,114,101,97,100,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,110,110,116,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,95,110,111,100,101,95,112,114,111,99,101,115,115,111,114,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,110,110,112,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<116,104,114,101,97,100,95,110,111,95,110,111,100,101,95,112,114,111,99,101,115,115,111,114,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,116,110,110,112,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<100,101,102,97,117,108,116,95,98,105,110,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,100,98>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,101,113,117,97,108,115,32>>,{code,[],[<<72,111,119>>]},<<32,98,101,102,111,114,101,32,102,108,97,103,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>]},<<32,119,97,115,32,99,104,97,110,103,101,100,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[<<73,102,32,98,105,110,100,105,110,103,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<72,111,119>>]},<<32,105,115,32,110,111,116,32,111,110,101,32,111,102,32,116,104,101,32,100,111,99,117,109,101,110,116,101,100,32,97,108,116,101,114,110,97,116,105,118,101,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,117,110,97,118,97,105,108,97,98,108,101,46>>]}]},{p,[],[<<84,104,101,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,32,116,121,112,101,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<44,32,97,115,32,119,101,108,108,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,54,50,55>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2639,bounded_fun,[{type,2639,'fun',[{type,2639,product,[{atom,2639,scheduler_bind_type},{var,2639,'How'}]},{var,2639,'OldBindType'}]},[{type,2640,constraint,[{atom,2640,is_subtype},[{var,2640,'How'},{type,2640,union,[{user_type,2640,scheduler_bind_type,[]},{atom,2640,default_bind}]}]]},{type,2641,constraint,[{atom,2641,is_subtype},[{var,2641,'OldBindType'},{user_type,2641,scheduler_bind_type,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,115,99,104,101,100,117,108,101,114,32,119,97,108,108,32,116,105,109,101,32,109,101,97,115,117,114,101,109,101,110,116,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,55,53,52>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2642,bounded_fun,[{type,2642,'fun',[{type,2642,product,[{atom,2642,scheduler_wall_time},{var,2642,'Boolean'}]},{var,2642,'OldBoolean'}]},[{type,2643,constraint,[{atom,2643,is_subtype},[{var,2643,'Boolean'},{type,2643,boolean,[]}]]},{type,2644,constraint,[{atom,2644,is_subtype},[{var,2644,'OldBoolean'},{type,2644,boolean,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66,48,49>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,82,97,110,103,101,32,105,115,32>>,{code,[],[<<49,32,60,61,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,32,60,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<73,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,97,115,32,98,117,105,108,116,32,119,105,116,104,32,115,117,112,112,111,114,116,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115>>]},<<44,32,99,104,97,110,103,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,97,108,115,111,32,99,104,97,110,103,101,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,49,50,32,115,99,104,101,100,117,108,101,114,115,32,97,110,100,32,54,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,111,110,108,105,110,101,44,32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>]},<<32,105,115,32,117,115,101,100,32,116,111,32,115,101,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,116,111,32,54,44,32,116,104,101,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,99,114,101,97,115,101,100,32,98,121,32,104,97,108,102,32,97,115,32,119,101,108,108,44,32,100,111,119,110,32,116,111,32,51,46,32,83,105,109,105,108,97,114,108,121,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,110,99,114,101,97,115,101,115,32,112,114,111,112,111,114,116,105,111,110,97,108,108,121,32,116,111,32,105,110,99,114,101,97,115,101,115,32,105,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,55,54,55>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2645,bounded_fun,[{type,2645,'fun',[{type,2645,product,[{atom,2645,schedulers_online},{var,2645,'SchedulersOnline'}]},{var,2646,'OldSchedulersOnline'}]},[{type,2647,constraint,[{atom,2647,is_subtype},[{var,2647,'SchedulersOnline'},{type,2647,pos_integer,[]}]]},{type,2648,constraint,[{atom,2648,is_subtype},[{var,2648,'OldSchedulersOnline'},{type,2648,pos_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,119,105,108,108,32,114,101,99,101,105,118,101,32,116,104,101,32,108,111,103,103,105,110,103,32,109,101,115,115,97,103,101,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,69,82,84,83,46,32,73,102,32,115,101,116,32,116,111,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<44,32,97,108,108,32,108,111,103,103,105,110,103,32,109,101,115,115,97,103,101,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,69,82,84,83,32,119,105,108,108,32,98,101,32,100,114,111,112,112,101,100,46,32,84,104,101,32,109,101,115,115,97,103,101,115,32,119,105,108,108,32,98,101,32,105,110,32,116,104,101,32,102,111,114,109,97,116,58>>]},{pre,[],[{code,[],[<<123,108,111,103,44,76,101,118,101,108,44,70,111,114,109,97,116,44,65,114,103,76,105,115,116,44,77,101,116,97,100,97,116,97,125,32,119,104,101,114,101,10,10,76,101,118,101,108,32,61,32,97,116,111,109,40,41,44,10,70,111,114,109,97,116,32,61,32,115,116,114,105,110,103,40,41,44,10,65,114,103,76,105,115,116,32,61,32,108,105,115,116,40,116,101,114,109,40,41,41,44,10,77,101,116,97,100,97,116,97,32,61,32,35,123,32,112,105,100,32,61,62,32,112,105,100,40,41,44,10,32,32,32,103,114,111,117,112,95,108,101,97,100,101,114,32,61,62,32,112,105,100,40,41,44,10,32,32,32,116,105,109,101,32,58,61,32,108,111,103,103,101,114,58,116,105,109,101,115,116,97,109,112,40,41,44,10,32,32,32,101,114,114,111,114,95,108,111,103,103,101,114,32,58,61,32,35,123,32,101,109,117,108,97,116,111,114,32,58,61,32,116,114,117,101,44,32,116,97,103,32,58,61,32,97,116,111,109,40,41,32,125,10,32,32,32,32,32,32,32,32>>]}]},{p,[],[<<73,102,32,116,104,101,32>>,{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]},<<32,112,114,111,99,101,115,115,32,100,105,101,115,44,32,116,104,105,115,32,102,108,97,103,32,119,105,108,108,32,98,101,32,114,101,115,101,116,32,116,111,32>>,{code,[],[<<108,111,103,103,101,114>>]},<<46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,110,97,109,101,100,32>>,{code,[],[<<108,111,103,103,101,114>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,98,101,32,117,115,101,100,32,98,121,32,116,104,101,32,75,69,82,78,69,76,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,108,111,103,103,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,103,103,101,114>>]}]},<<46,32,66,101,32,99,97,114,101,102,117,108,32,105,102,32,121,111,117,32,99,104,97,110,103,101,32,105,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,97,115,32,108,111,103,32,109,101,115,115,97,103,101,115,32,109,97,121,32,98,101,32,108,111,115,116,46,32,73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,105,110,116,101,114,99,101,112,116,32,101,109,117,108,97,116,111,114,32,108,111,103,32,109,101,115,115,97,103,101,115,44,32,100,111,32,105,116,32,98,121,32,97,100,100,105,110,103,32,97,32,115,112,101,99,105,97,108,105,122,101,100,32,104,97,110,100,108,101,114,32,116,111,32,116,104,101,32,75,69,82,78,69,76,32,108,111,103,103,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,55,57,54>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2649,bounded_fun,[{type,2649,'fun',[{type,2649,product,[{atom,2649,system_logger},{var,2649,'Logger'}]},{var,2649,'PrevLogger'}]},[{type,2650,constraint,[{atom,2650,is_subtype},[{var,2650,'Logger'},{type,2650,union,[{atom,2650,logger},{atom,2650,undefined},{type,2650,pid,[]}]}]]},{type,2651,constraint,[{atom,2651,is_subtype},[{var,2651,'PrevLogger'},{type,2651,union,[{atom,2651,logger},{atom,2651,undefined},{type,2651,pid,[]}]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,51>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,110,111,100,101,32,116,114,97,99,101,32,99,111,110,116,114,111,108,32,119,111,114,100,32,116,111,32>>,{code,[],[<<84,67,87>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,111,32,98,101,32,97,110,32,117,110,115,105,103,110,101,100,32,105,110,116,101,103,101,114,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99,35,115,101,116,95,116,99,119>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<115,101,116,95,116,99,119>>]}]},<<32,105,110,32,115,101,99,116,105,111,110,32,34,77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103,34,32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,50,56>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2652,bounded_fun,[{type,2652,'fun',[{type,2652,product,[{atom,2652,trace_control_word},{var,2652,'TCW'}]},{var,2652,'OldTCW'}]},[{type,2653,constraint,[{atom,2653,is_subtype},[{var,2653,'TCW'},{type,2653,non_neg_integer,[]}]]},{type,2654,constraint,[{atom,2654,is_subtype},[{var,2654,'OldTCW'},{type,2654,non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2606}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<70,105,110,97,108,105,122,101,115,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,105,109,101,32,111,102,102,115,101,116>>]},<<32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46,32,73,102,32,97,110,111,116,104,101,114,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101,32,105,115,32,117,115,101,100,44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,115,116,97,116,101,32,105,115,32,108,101,102,116,32,117,110,99,104,97,110,103,101,100,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,115,116,97,116,101,32,105,100,101,110,116,105,102,105,101,114,44,32,116,104,97,116,32,105,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<112,114,101,108,105,109,105,110,97,114,121>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,102,105,110,97,108,105,122,97,116,105,111,110,32,119,97,115,32,112,101,114,102,111,114,109,101,100,32,97,110,100,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,110,111,119,32,102,105,110,97,108,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<102,105,110,97,108>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,119,97,115,32,97,108,114,101,97,100,121,32,105,110,32,116,104,101,32,102,105,110,97,108,32,115,116,97,116,101,46,32,84,104,105,115,32,101,105,116,104,101,114,32,98,101,99,97,117,115,101,32,97,110,111,116,104,101,114,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,116,105,109,101,95,111,102,102,115,101,116,44,32,102,105,110,97,108,105,122,101,41>>]},<<32,99,97,108,108,32,111,114,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,78,111,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<118,111,108,97,116,105,108,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,99,97,110,110,111,116,32,98,101,32,102,105,110,97,108,105,122,101,100,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,52,50>>,signature => [{attribute,2606,spec,{{erlang,system_flag,2},[{type,2655,bounded_fun,[{type,2655,'fun',[{type,2655,product,[{atom,2655,time_offset},{atom,2655,finalize}]},{var,2655,'OldState'}]},[{type,2656,constraint,[{atom,2656,is_subtype},[{var,2656,'OldState'},{type,2656,union,[{atom,2656,preliminary},{atom,2656,final},{atom,2656,volatile}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,46,32,84,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,98,114,111,107,101,110,32,105,110,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,32,105,110,32,111,114,100,101,114,32,116,111,32,109,97,107,101,32,105,116,32,101,97,115,105,101,114,32,116,111,32,110,97,118,105,103,97,116,101,46>>]},{dl,[],[{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<77,101,109,111,114,121,32,65,108,108,111,99,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,97,116,111,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,115,105,122,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,97,116,111,114,95,115,105,122,101,115>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<67,80,85,32,84,111,112,111,108,111,103,121>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<80,114,111,99,101,115,115,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,115,105,122,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<104,101,97,112,95,115,105,122,101,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<104,101,97,112,95,116,121,112,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,115>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,105,109,105,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,121,115,116,101,109,32,76,105,109,105,116,115>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,116,111,109,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,116,111,109,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,116,115,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,116,115,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,111,114,116,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,111,114,116,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,108,105,109,105,116>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,121,115,116,101,109,32,84,105,109,101>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,110,100,95,116,105,109,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,114,116,95,116,105,109,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,111,102,102,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,119,97,114,112,95,109,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,119,97,114,112,95,109,111,100,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,99,104,101,100,117,108,101,114,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,105,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,105,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,109,112,95,115,117,112,112,111,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,109,112,95,115,117,112,112,111,114,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,104,114,101,97,100,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<68,105,115,116,114,105,98,117,116,105,111,110,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,114,101,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,114,101,97,116,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,115,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,99,116,114,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,115,116,95,99,116,114,108>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,105,115,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,121,115,116,101,109,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,104,101,99,107,95,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,104,101,99,107,95,105,111>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,111,109,112,97,116,95,114,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,109,112,97,116,95,114,101,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,101,98,117,103,95,99,111,109,112,105,108,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,101,98,117,103,95,99,111,109,112,105,108,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,114,105,118,101,114,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,114,105,118,101,114,95,118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,102,108,97,118,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,109,117,95,102,108,97,118,111,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,109,117,95,116,121,112,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,105,110,102,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,102,111>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,107,101,114,110,101,108,95,112,111,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<107,101,114,110,101,108,95,112,111,108,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,97,100,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,97,100,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,97,99,104,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,99,104,105,110,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,105,102,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<110,105,102,95,118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,111,116,112,95,114,101,108,101,97,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,116,112,95,114,101,108,101,97,115,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,108,111,103,103,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,121,115,116,101,109,95,118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,119,111,114,100,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<119,111,114,100,115,105,122,101>>]}]}]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,55,50>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2866,'fun',[{type,2866,product,[{atom,2866,version}]},{type,2866,string,[]}]}]}}]}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,111,114,115,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>}],[]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>}],[]},{code,[],[<<97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,97,114,101,97,115,46>>]},{p,[],[<<69,97,99,104,32,116,117,112,108,101,32,99,111,110,116,97,105,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,116,121,112,101,32,111,102,32,109,101,109,111,114,121,32,97,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,97,110,100,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,105,110,32,98,121,116,101,115,32,97,115,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,46,32,87,104,101,110,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,108,108,111,99,97,116,101,100,32,97,110,100,32,117,115,101,100,32,109,101,109,111,114,121,32,105,115,32,112,114,101,115,101,110,116,44,32,97,108,115,111,32,97,32,116,104,105,114,100,32,101,108,101,109,101,110,116,32,105,115,32,112,114,101,115,101,110,116,44,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,117,115,101,100,32,109,101,109,111,114,121,32,105,110,32,98,121,116,101,115,46>>]},{p,[],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115,41>>]},<<32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,44,32,97,110,100,32,116,104,101,32,99,111,110,116,101,110,116,32,105,115,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,46,32,84,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,115,32,116,104,101,114,101,102,111,114,101,32,99,104,97,110,103,101,115,32,119,104,101,110,32,110,101,101,100,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,115,101,32,118,97,108,117,101,115,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,116,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,111,109,101,32,118,97,108,117,101,115,32,97,114,101,32,112,97,114,116,32,111,102,32,111,116,104,101,114,32,118,97,108,117,101,115,44,32,97,110,100,32,115,111,109,101,32,109,101,109,111,114,121,32,97,114,101,97,115,32,97,114,101,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,101,109,111,114,121,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48,44,49>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114>>}],[]},{code,[],[<<97,108,108,111,99,97,116,111,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,65,108,108,111,99,97,116,111,114,44,32,86,101,114,115,105,111,110,44,32,70,101,97,116,117,114,101,115,44,32,83,101,116,116,105,110,103,115>>]},<<44,32,119,104,101,114,101,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<65,108,108,111,99,97,116,111,114>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32>>,{code,[],[<<109,97,108,108,111,99,40,41>>]},<<32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,117,115,101,100,46,32,73,102,32>>,{code,[],[<<65,108,108,111,99,97,116,111,114>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<44,32,116,104,101,32>>,{code,[],[<<109,97,108,108,111,99,40,41>>]},<<32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,117,115,101,100,32,99,97,110,110,111,116,32,98,101,32,105,100,101,110,116,105,102,105,101,100,46,32>>,{code,[],[<<103,108,105,98,99>>]},<<32,99,97,110,32,98,101,32,105,100,101,110,116,105,102,105,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<86,101,114,115,105,111,110>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,40,98,117,116,32,110,111,116,32,97,32,115,116,114,105,110,103,41,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<109,97,108,108,111,99,40,41>>]},<<32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,117,115,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<70,101,97,116,117,114,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,97,116,111,109,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,97,108,108,111,99,97,116,105,111,110,32,102,101,97,116,117,114,101,115,32,117,115,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<83,101,116,116,105,110,103,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,115,117,98,115,121,115,116,101,109,115,44,32,116,104,101,105,114,32,99,111,110,102,105,103,117,114,97,98,108,101,32,112,97,114,97,109,101,116,101,114,115,44,32,97,110,100,32,117,115,101,100,32,118,97,108,117,101,115,46,32,83,101,116,116,105,110,103,115,32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,100,105,102,102,101,114,101,110,116,32,99,111,109,98,105,110,97,116,105,111,110,115,32,111,102,32,112,108,97,116,102,111,114,109,115,44,32,97,108,108,111,99,97,116,111,114,115,44,32,97,110,100,32,97,108,108,111,99,97,116,105,111,110,32,102,101,97,116,117,114,101,115,46,32,77,101,109,111,114,121,32,115,105,122,101,115,32,97,114,101,32,103,105,118,101,110,32,105,110,32,98,121,116,101,115,46>>]}]}]},{p,[],[<<83,101,101,32,97,108,115,111,32,34,83,121,115,116,101,109,32,70,108,97,103,115,32,69,102,102,101,99,116,105,110,103,32,101,114,116,115,95,97,108,108,111,99,34,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99,35,102,108,97,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,116,117,112,108,101>>}],[]},{code,[],[<<123,97,108,108,111,99,97,116,111,114,44,32,65,108,108,111,99,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,97,108,108,111,99,97,116,111,114,46,32,65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,54,46,49,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,105,110,115,116,97,110,99,101,44,32,73,110,115,116,97,110,99,101,78,111,44,32,73,110,115,116,97,110,99,101,73,110,102,111,125>>]},<<32,116,117,112,108,101,115,44,32,119,104,101,114,101,32>>,{code,[],[<<73,110,115,116,97,110,99,101,73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,115,112,101,99,105,102,105,99,32,105,110,115,116,97,110,99,101,32,111,102,32,116,104,101,32,97,108,108,111,99,97,116,111,114,46,32,73,102,32>>,{code,[],[<<65,108,108,111,99>>]},<<32,105,115,32,110,111,116,32,97,32,114,101,99,111,103,110,105,122,101,100,32,97,108,108,111,99,97,116,111,114,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32>>,{code,[],[<<65,108,108,111,99>>]},<<32,105,115,32,100,105,115,97,98,108,101,100,44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,105,115,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,32,97,110,100,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46,32,73,116,32,119,97,115,32,105,110,105,116,105,97,108,108,121,32,105,110,116,101,110,100,101,100,32,97,115,32,97,32,116,111,111,108,32,119,104,101,110,32,100,101,118,101,108,111,112,105,110,103,32,110,101,119,32,97,108,108,111,99,97,116,111,114,115,44,32,98,117,116,32,97,115,32,105,116,32,99,97,110,32,98,101,32,111,102,32,105,110,116,101,114,101,115,116,32,102,111,114,32,111,116,104,101,114,115,32,105,116,32,104,97,115,32,98,101,101,110,32,98,114,105,101,102,108,121,32,100,111,99,117,109,101,110,116,101,100,46>>]},{p,[],[<<84,104,101,32,114,101,99,111,103,110,105,122,101,100,32,97,108,108,111,99,97,116,111,114,115,32,97,114,101,32,108,105,115,116,101,100,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<46,32,73,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,117,112,101,114,32,99,97,114,114,105,101,114,115,32,99,97,110,32,98,101,32,111,98,116,97,105,110,101,100,32,102,114,111,109,32,69,82,84,83,32,56,46,48,32,119,105,116,104,32>>,{code,[],[<<123,97,108,108,111,99,97,116,111,114,44,32,101,114,116,115,95,109,109,97,112,125>>]},<<32,111,114,32,102,114,111,109,32,69,82,84,83,32,53,46,49,48,46,52,59,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,119,104,101,110,32,99,97,108,108,105,110,103,32,119,105,116,104,32>>,{code,[],[<<123,97,108,108,111,99,97,116,111,114,44,32,109,115,101,103,95,97,108,108,111,99,125>>]},<<32,97,108,115,111,32,105,110,99,108,117,100,101,115,32,97,110,32>>,{code,[],[<<123,101,114,116,115,95,109,109,97,112,44,32,95,125>>]},<<32,116,117,112,108,101,32,97,115,32,111,110,101,32,101,108,101,109,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,46>>]},{p,[],[<<65,102,116,101,114,32,114,101,97,100,105,110,103,32,116,104,101,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]},<<32,100,111,99,117,109,101,110,116,97,116,105,111,110,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,109,111,114,101,32,111,114,32,108,101,115,115,32,115,112,101,97,107,115,32,102,111,114,32,105,116,115,101,108,102,44,32,98,117,116,32,105,116,32,99,97,110,32,98,101,32,119,111,114,116,104,32,101,120,112,108,97,105,110,105,110,103,32,115,111,109,101,32,116,104,105,110,103,115,46,32,67,97,108,108,32,99,111,117,110,116,115,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,98,121,32,116,119,111,32,118,97,108,117,101,115,44,32,116,104,101,32,102,105,114,115,116,32,118,97,108,117,101,32,105,115,32,103,105,103,97,32,99,97,108,108,115,44,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,118,97,108,117,101,32,105,115,32,99,97,108,108,115,46,32>>,{code,[],[<<109,98,99,115>>]},<<32,97,110,100,32>>,{code,[],[<<115,98,99,115>>]},<<32,100,101,110,111,116,101,32,109,117,108,116,105,45,98,108,111,99,107,32,99,97,114,114,105,101,114,115,44,32,97,110,100,32,115,105,110,103,108,101,45,98,108,111,99,107,32,99,97,114,114,105,101,114,115,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,83,105,122,101,115,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,105,110,32,98,121,116,101,115,46,32,87,104,101,110,32,97,32,115,105,122,101,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,101,100,44,32,105,116,32,105,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,115,111,109,101,116,104,105,110,103,46,32,83,105,122,101,115,32,97,110,100,32,97,109,111,117,110,116,115,32,97,114,101,32,111,102,116,101,110,32,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,114,101,101,32,118,97,108,117,101,115,58>>]},{ul,[],[{li,[],[<<84,104,101,32,102,105,114,115,116,32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,118,97,108,117,101,46>>]},{li,[],[<<84,104,101,32,115,101,99,111,110,100,32,105,115,32,116,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,115,105,110,99,101,32,116,104,101,32,108,97,115,116,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,123,97,108,108,111,99,97,116,111,114,44,32,65,108,108,111,99,125,41>>]},<<46>>]},{li,[],[<<84,104,101,32,116,104,105,114,100,32,105,115,32,116,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,115,105,110,99,101,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,97,115,32,115,116,97,114,116,101,100,46>>]}]},{p,[],[<<73,102,32,111,110,108,121,32,111,110,101,32,118,97,108,117,101,32,105,115,32,112,114,101,115,101,110,116,44,32,105,116,32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,118,97,108,117,101,46,32>>,{code,[],[<<102,105,120,95,97,108,108,111,99>>]},<<32,109,101,109,111,114,121,32,98,108,111,99,107,32,116,121,112,101,115,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,98,121,32,116,119,111,32,118,97,108,117,101,115,46,32,84,104,101,32,102,105,114,115,116,32,118,97,108,117,101,32,105,115,32,116,104,101,32,109,101,109,111,114,121,32,112,111,111,108,32,115,105,122,101,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,118,97,108,117,101,32,105,115,32,116,104,101,32,117,115,101,100,32,109,101,109,111,114,121,32,115,105,122,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>}],[]},{code,[],[<<97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,97,108,108,111,99,97,116,111,114,115,32,117,115,105,110,103,32,116,104,101,32,69,82,84,83,32,105,110,116,101,114,110,97,108,32>>,{code,[],[<<97,108,108,111,99,95,117,116,105,108>>]},<<32,102,114,97,109,101,119,111,114,107,32,97,115,32,97,116,111,109,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99,35,97,108,108,111,99,95,117,116,105,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<84,104,101,32,97,108,108,111,99,95,117,116,105,108,32,102,114,97,109,101,119,111,114,107>>]},<<32,105,110,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,115,105,122,101,115>>}],[]},{code,[],[<<123,97,108,108,111,99,97,116,111,114,95,115,105,122,101,115,44,32,65,108,108,111,99,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,115,105,122,101,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,97,108,108,111,99,97,116,111,114,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,123,97,108,108,111,99,97,116,111,114,44,32,65,108,108,111,99,125,41>>]}]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,48,48,53>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2767,'fun',[{type,2767,product,[{atom,2767,allocated_areas}]},{type,2767,list,[{type,2767,tuple,any}]}]},{type,2768,bounded_fun,[{type,2768,'fun',[{type,2768,product,[{atom,2768,allocator}]},{type,2769,tuple,[{var,2769,'Allocator'},{var,2769,'Version'},{var,2769,'Features'},{var,2769,'Settings'}]}]},[{type,2770,constraint,[{atom,2770,is_subtype},[{var,2770,'Allocator'},{type,2770,union,[{atom,2770,undefined},{atom,2770,glibc}]}]]},{type,2771,constraint,[{atom,2771,is_subtype},[{var,2771,'Version'},{type,2771,list,[{type,2771,non_neg_integer,[]}]}]]},{type,2772,constraint,[{atom,2772,is_subtype},[{var,2772,'Features'},{type,2772,list,[{type,2772,atom,[]}]}]]},{type,2773,constraint,[{atom,2773,is_subtype},[{var,2773,'Settings'},{type,2773,list,[{type,2773,tuple,[{ann_type,2773,[{var,2773,'Subsystem'},{type,2773,atom,[]}]},{type,2774,list,[{type,2774,tuple,[{ann_type,2774,[{var,2774,'Parameter'},{type,2774,atom,[]}]},{ann_type,2775,[{var,2775,'Value'},{type,2775,term,[]}]}]}]}]}]}]]}]]},{type,2776,bounded_fun,[{type,2776,'fun',[{type,2776,product,[{type,2776,tuple,[{atom,2776,allocator},{var,2776,'Alloc'}]}]},{type,2776,list,[{var,2776,'_'}]}]},[{type,2777,constraint,[{atom,2777,is_subtype},[{var,2777,'Alloc'},{type,2777,atom,[]}]]}]]},{type,2778,bounded_fun,[{type,2778,'fun',[{type,2778,product,[{atom,2778,alloc_util_allocators}]},{type,2778,list,[{var,2778,'Alloc'}]}]},[{type,2779,constraint,[{atom,2779,is_subtype},[{var,2779,'Alloc'},{type,2779,atom,[]}]]}]]},{type,2780,bounded_fun,[{type,2780,'fun',[{type,2780,product,[{type,2780,tuple,[{atom,2780,allocator_sizes},{var,2780,'Alloc'}]}]},{type,2780,list,[{var,2780,'_'}]}]},[{type,2781,constraint,[{atom,2781,is_subtype},[{var,2781,'Alloc'},{type,2781,atom,[]}]]}]]}]}}]}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<99,112,117,95,116,111,112,111,108,111,103,121>>}],[]},{li,[{name,<<99,112,117,95,116,111,112,111,108,111,103,121>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,108,108,32>>,{code,[],[<<76,101,118,101,108,69,110,116,114,121>>]},<<115,32,111,102,32,97,32,108,105,115,116,32,109,117,115,116,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32>>,{code,[],[<<76,101,118,101,108,84,97,103>>]},<<44,32,101,120,99,101,112,116,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,119,104,101,114,101,32,98,111,116,104,32>>,{code,[],[<<110,111,100,101>>]},<<32,97,110,100,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},{code,[],[<<76,101,118,101,108,84,97,103>>]},<<115,32,99,97,110,32,99,111,101,120,105,115,116,46>>]},{li,[{name,<<105,110,102,111,95,108,105,115,116>>}],[]},{li,[{name,<<105,110,102,111,95,108,105,115,116>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<84,104,101,32>>,{code,[],[<<105,110,102,111,95,108,105,115,116,40,41>>]},<<32,99,97,110,32,98,101,32,101,120,116,101,110,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{li,[{name,<<108,101,118,101,108,95,101,110,116,114,121>>}],[]},{li,[{name,<<108,101,118,101,108,95,101,110,116,114,121>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[{code,[],[<<123,76,101,118,101,108,84,97,103,44,32,83,117,98,76,101,118,101,108,125,32,61,61,32,123,76,101,118,101,108,84,97,103,44,32,91,93,44,32,83,117,98,76,101,118,101,108,125>>]}]},{li,[{name,<<108,101,118,101,108,95,116,97,103>>}],[]},{li,[{name,<<108,101,118,101,108,95,116,97,103>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<77,111,114,101,32>>,{code,[],[<<76,101,118,101,108,84,97,103>>]},<<115,32,99,97,110,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{li,[{name,<<115,117,98,95,108,101,118,101,108>>}],[]}]},{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>}],[]},{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,84,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,117,115,101,100,32,119,104,101,110,32,98,105,110,100,105,110,103,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,84,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,117,115,101,100,32,105,115,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,102,105,110,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,115,101,114,45,100,101,102,105,110,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121>>]},<<44,32,105,102,32,115,117,99,104,32,101,120,105,115,116,115,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,116,101,99,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121>>]},<<44,32,105,102,32,115,117,99,104,32,101,120,105,115,116,115,46,32,73,102,32,110,111,32,67,80,85,32,116,111,112,111,108,111,103,121,32,101,120,105,115,116,115,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<110,111,100,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,78,111,110,45,85,110,105,102,111,114,109,32,77,101,109,111,114,121,32,65,99,99,101,115,115,32,40,78,85,77,65,41,32,110,111,100,101,115,46,32>>,{code,[],[<<116,104,114,101,97,100>>]},<<32,114,101,102,101,114,115,32,116,111,32,104,97,114,100,119,97,114,101,32,116,104,114,101,97,100,115,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,73,110,116,101,108,32,104,121,112,101,114,45,116,104,114,101,97,100,115,41,46>>]},{p,[],[<<65,32,108,101,118,101,108,32,105,110,32,116,101,114,109,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,99,97,110,32,98,101,32,111,109,105,116,116,101,100,32,105,102,32,111,110,108,121,32,111,110,101,32,101,110,116,114,121,32,101,120,105,115,116,115,32,97,110,100,32>>,{code,[],[<<73,110,102,111,76,105,115,116>>]},<<32,105,115,32,101,109,112,116,121,46>>]},{p,[],[{code,[],[<<116,104,114,101,97,100>>]},<<32,99,97,110,32,111,110,108,121,32,98,101,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<99,111,114,101>>]},<<46,32>>,{code,[],[<<99,111,114,101>>]},<<32,99,97,110,32,98,101,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},<<32,111,114,32>>,{code,[],[<<110,111,100,101>>]},<<46,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},<<32,99,97,110,32,98,101,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,111,114,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<110,111,100,101>>]},<<46,32>>,{code,[],[<<110,111,100,101>>]},<<32,99,97,110,32,98,101,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,111,114,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},<<46,32,84,104,97,116,32,105,115,44,32,78,85,77,65,32,110,111,100,101,115,32,99,97,110,32,98,101,32,112,114,111,99,101,115,115,111,114,32,105,110,116,101,114,110,97,108,32,111,114,32,112,114,111,99,101,115,115,111,114,32,101,120,116,101,114,110,97,108,46,32,65,32,67,80,85,32,116,111,112,111,108,111,103,121,32,99,97,110,32,99,111,110,115,105,115,116,32,111,102,32,97,32,109,105,120,32,111,102,32,112,114,111,99,101,115,115,111,114,32,105,110,116,101,114,110,97,108,32,97,110,100,32,101,120,116,101,114,110,97,108,32,78,85,77,65,32,110,111,100,101,115,44,32,97,115,32,108,111,110,103,32,97,115,32,101,97,99,104,32,108,111,103,105,99,97,108,32,67,80,85,32,98,101,108,111,110,103,115,32,116,111,32>>,{em,[],[<<111,110,101>>]},<<32,78,85,77,65,32,110,111,100,101,46,32,67,97,99,104,101,32,104,105,101,114,97,114,99,104,121,32,105,115,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,116,121,112,101,44,32,98,117,116,32,119,105,108,108,32,98,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,79,116,104,101,114,32,116,104,105,110,103,115,32,99,97,110,32,97,108,115,111,32,109,97,107,101,32,105,116,32,105,110,116,111,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,83,111,44,32,101,120,112,101,99,116,32,116,104,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,116,121,112,101,32,116,111,32,99,104,97,110,103,101,46>>]}]},{dt,[],[{code,[],[<<123,99,112,117,95,116,111,112,111,108,111,103,121,44,32,100,101,102,105,110,101,100,125>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,102,105,110,101,100>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<32,97,110,100,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,99,112,117,95,116,111,112,111,108,111,103,121,44,32,100,101,116,101,99,116,101,100,125>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,116,101,99,116,101,100>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121,121>>]},<<46,32,84,104,101,32,101,109,117,108,97,116,111,114,32,100,101,116,101,99,116,115,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,111,110,32,115,111,109,101,32,110,101,119,101,114,32,76,105,110,117,120,44,32,83,111,108,97,114,105,115,44,32,70,114,101,101,66,83,68,44,32,97,110,100,32,87,105,110,100,111,119,115,32,115,121,115,116,101,109,115,46,32,79,110,32,87,105,110,100,111,119,115,32,115,121,115,116,101,109,32,119,105,116,104,32,109,111,114,101,32,116,104,97,110,32,51,50,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,110,111,116,32,100,101,116,101,99,116,101,100,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,99,112,117,95,116,111,112,111,108,111,103,121,44,32,117,115,101,100,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>}],[]},{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,99,111,110,102,105,103,117,114,101,100,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,101,105,116,104,101,114,32,97,110,32,105,110,116,101,103,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,116,104,101,32,99,111,110,102,105,103,117,114,101,100,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>}],[]},{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,97,118,97,105,108,97,98,108,101,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,101,105,116,104,101,114,32,97,110,32,105,110,116,101,103,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,116,104,101,32,97,118,97,105,108,97,98,108,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,84,104,101,32,110,117,109,98,101,114,32,111,102,32,97,118,97,105,108,97,98,108,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,105,115,32,108,101,115,115,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>}],[]},{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101,32,111,110,32,116,104,101,32,115,121,115,116,101,109,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,101,105,116,104,101,114,32,97,110,32,105,110,116,101,103,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101,46,32,84,104,101,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101,32,105,115,32,108,101,115,115,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,99,111,110,102,105,103,117,114,101,100>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,113,117,111,116,97>>}],[]},{code,[],[<<99,112,117,95,113,117,111,116,97>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,67,80,85,32,113,117,111,116,97,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,108,105,109,105,116,101,100,32,98,121,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,115,97,121,105,110,103,32,104,111,119,32,109,97,110,121,32,112,114,111,99,101,115,115,111,114,115,39,32,119,111,114,116,104,32,111,102,32,114,117,110,116,105,109,101,32,119,101,32,103,101,116,32,40,98,101,116,119,101,101,110,32,49,32,97,110,100,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,41,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,97,32,113,117,111,116,97,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>}],[]},{code,[],[<<117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,114,101,114,101,97,100,115,32,116,104,101,32,67,80,85,32,105,110,102,111,114,109,97,116,105,111,110,32,97,118,97,105,108,97,98,108,101,32,97,110,100,32,117,112,100,97,116,101,115,32,105,116,115,32,105,110,116,101,114,110,97,108,108,121,32,115,116,111,114,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,116,101,99,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,101,116,101,99,116,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121>>]},<<32,97,110,100,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,110,102,105,103,117,114,101,100>>]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<111,110,108,105,110,101>>]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<97,118,97,105,108,97,98,108,101>>]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,113,117,111,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,112,117,32,113,117,111,116,97>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,67,80,85,32,105,110,102,111,114,109,97,116,105,111,110,32,104,97,115,32,99,104,97,110,103,101,100,32,115,105,110,99,101,32,116,104,101,32,108,97,115,116,32,116,105,109,101,32,105,116,32,119,97,115,32,114,101,97,100,44,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<99,104,97,110,103,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,99,104,97,110,103,101,100>>]},<<46,32,73,102,32,116,104,101,32,67,80,85,32,105,110,102,111,114,109,97,116,105,111,110,32,104,97,115,32,99,104,97,110,103,101,100,44,32,121,111,117,32,112,114,111,98,97,98,108,121,32,119,97,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<97,100,106,117,115,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101>>]},<<46,32,89,111,117,32,116,121,112,105,99,97,108,108,121,32,119,97,110,116,32,116,111,32,104,97,118,101,32,97,115,32,109,97,110,121,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,97,118,97,105,108,97,98,108,101>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,53,52>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2789,bounded_fun,[{type,2789,'fun',[{type,2789,product,[{atom,2789,cpu_topology}]},{var,2789,'CpuTopology'}]},[{type,2790,constraint,[{atom,2790,is_subtype},[{var,2790,'CpuTopology'},{user_type,2790,cpu_topology,[]}]]}]]},{type,2791,bounded_fun,[{type,2791,'fun',[{type,2791,product,[{type,2791,tuple,[{atom,2791,cpu_topology},{type,2791,union,[{atom,2791,defined},{atom,2791,detected},{atom,2791,used}]}]}]},{var,2791,'CpuTopology'}]},[{type,2792,constraint,[{atom,2792,is_subtype},[{var,2792,'CpuTopology'},{user_type,2792,cpu_topology,[]}]]}]]},{type,2819,'fun',[{type,2819,product,[{type,2819,union,[{atom,2819,logical_processors},{atom,2820,logical_processors_available},{atom,2821,logical_processors_online}]}]},{type,2821,union,[{atom,2821,unknown},{type,2821,pos_integer,[]}]}]},{type,2865,'fun',[{type,2865,product,[{atom,2865,update_cpu_info}]},{type,2865,union,[{atom,2865,changed},{atom,2865,unchanged}]}]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]}]},{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,101,102,97,117,108,116,32,112,114,111,99,101,115,115,32,104,101,97,112,32,115,101,116,116,105,110,103,115,58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>}],[]},{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,101,116,116,105,110,103,32,117,115,101,100,32,98,121,32,100,101,102,97,117,108,116,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]},<<32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>}],[]},{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,100,101,102,97,117,108,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,101,116,116,105,110,103,115,46,32,65,32,112,114,111,99,101,115,115,32,115,112,97,119,110,101,100,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,98,121,32,97,32>>,{code,[],[<<115,112,97,119,110>>]},<<32,111,114,32>>,{code,[],[<<115,112,97,119,110,95,108,105,110,107>>]},<<32,117,115,101,115,32,116,104,101,115,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,101,116,116,105,110,103,115,46,32,84,104,101,32,100,101,102,97,117,108,116,32,115,101,116,116,105,110,103,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,47,50>>]}]},<<46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,50,44,51,44,52>>]}]},<<32,99,97,110,32,115,112,97,119,110,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,117,115,101,32,116,104,101,32,100,101,102,97,117,108,116,32,115,101,116,116,105,110,103,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,115,105,122,101,115>>}],[]},{code,[],[<<104,101,97,112,95,115,105,122,101,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,118,97,108,105,100,32,104,101,97,112,32,115,105,122,101,115,32,105,110,32,119,111,114,100,115,46,32,65,108,108,32,69,114,108,97,110,103,32,104,101,97,112,115,32,97,114,101,32,115,105,122,101,100,32,102,114,111,109,32,115,105,122,101,115,32,105,110,32,116,104,105,115,32,108,105,115,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,116,121,112,101>>}],[]},{code,[],[<<104,101,97,112,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,104,101,97,112,32,116,121,112,101,32,117,115,101,100,32,98,121,32,116,104,101,32,99,117,114,114,101,110,116,32,101,109,117,108,97,116,111,114,46,32,79,110,101,32,104,101,97,112,32,116,121,112,101,32,101,120,105,115,116,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<112,114,105,118,97,116,101>>]}]},{dd,[],[<<69,97,99,104,32,112,114,111,99,101,115,115,32,104,97,115,32,97,32,104,101,97,112,32,114,101,115,101,114,118,101,100,32,102,111,114,32,105,116,115,32,117,115,101,32,97,110,100,32,110,111,32,114,101,102,101,114,101,110,99,101,115,32,98,101,116,119,101,101,110,32,104,101,97,112,115,32,111,102,32,100,105,102,102,101,114,101,110,116,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,97,108,108,111,119,101,100,46,32,77,101,115,115,97,103,101,115,32,112,97,115,115,101,100,32,98,101,116,119,101,101,110,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,99,111,112,105,101,100,32,98,101,116,119,101,101,110,32,104,101,97,112,115,46>>]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,97,120,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,45,119,105,100,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,115,101,116,116,105,110,103,115,32,102,111,114,32,115,112,97,119,110,101,100,32,112,114,111,99,101,115,115,101,115,46,32,84,104,105,115,32,115,101,116,116,105,110,103,32,99,97,110,32,98,101,32,115,101,116,32,117,115,105,110,103,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120,107>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120,101,108>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,73,116,32,99,97,110,32,97,108,115,111,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,114,117,110,116,105,109,101,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,44,32,119,104,105,99,104,32,105,115,32,101,105,116,104,101,114,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<32,111,114,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46,32,84,104,105,115,32,100,101,102,97,117,108,116,32,105,115,32,115,101,116,32,98,121,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,113,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,113,100>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,44,32,115,101,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,109,105,110,95,104,101,97,112,95,115,105,122,101,44,32,77,105,110,72,101,97,112,83,105,122,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,105,110,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,45,119,105,100,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,115,112,97,119,110,101,100,32,112,114,111,99,101,115,115,101,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101,44,32,77,105,110,66,105,110,86,72,101,97,112,83,105,122,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,105,110,66,105,110,86,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,45,119,105,100,101,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,115,112,97,119,110,101,100,32,112,114,111,99,101,115,115,101,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,115>>}],[]},{code,[],[<<112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,112,114,111,99,101,115,115,32,97,110,100,32,112,111,114,116,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,51,49,57>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2812,'fun',[{type,2812,product,[{atom,2812,fullsweep_after}]},{type,2812,tuple,[{atom,2812,fullsweep_after},{type,2812,non_neg_integer,[]}]}]},{type,2813,'fun',[{type,2813,product,[{atom,2813,garbage_collection}]},{type,2813,list,[{type,2813,tuple,[{type,2813,atom,[]},{type,2813,integer,[]}]}]}]},{type,2814,'fun',[{type,2814,product,[{atom,2814,heap_sizes}]},{type,2814,list,[{type,2814,non_neg_integer,[]}]}]},{type,2815,'fun',[{type,2815,product,[{atom,2815,heap_type}]},{atom,2815,private}]},{type,2823,'fun',[{type,2823,product,[{atom,2823,max_heap_size}]},{type,2823,tuple,[{atom,2823,max_heap_size},{ann_type,2823,[{var,2823,'MaxHeapSize'},{user_type,2823,max_heap_size,[]}]}]}]},{type,2824,'fun',[{type,2824,product,[{atom,2824,message_queue_data}]},{user_type,2824,message_queue_data,[]}]},{type,2825,'fun',[{type,2825,product,[{atom,2825,min_heap_size}]},{type,2825,tuple,[{atom,2825,min_heap_size},{ann_type,2825,[{var,2825,'MinHeapSize'},{type,2825,pos_integer,[]}]}]}]},{type,2826,'fun',[{type,2826,product,[{atom,2826,min_bin_vheap_size}]},{type,2826,tuple,[{atom,2826,min_bin_vheap_size},{ann_type,2827,[{var,2827,'MinBinVHeapSize'},{type,2827,pos_integer,[]}]}]}]},{type,2841,'fun',[{type,2841,product,[{atom,2841,procs}]},{type,2841,binary,[]}]}]}}],since => <<79,84,80,32,49,57,46,48,44,79,84,80,32,82,49,51,66,48,52>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,105,109,105,116,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,108,105,109,105,116,115,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,99,111,117,110,116>>}],[]},{code,[],[<<97,116,111,109,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,116,111,109,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,108,105,109,105,116>>}],[]},{code,[],[<<97,116,111,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,97,116,111,109,115,32,97,108,108,111,119,101,100,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,105,110,99,114,101,97,115,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,116>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,99,111,117,110,116>>}],[]},{code,[],[<<101,116,115,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,69,84,83,32,116,97,98,108,101,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,108,105,109,105,116>>}],[]},{code,[],[<<101,116,115,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,105,109,105,116,32,102,111,114,32,110,117,109,98,101,114,32,111,102,32,69,84,83,32,116,97,98,108,101,115,46,32,84,104,105,115,32,108,105,109,105,116,32,105,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,116,115,35,109,97,120,95,101,116,115,95,116,97,98,108,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,97,108,108,121,32,111,98,115,111,108,101,116,101>>]},<<32,97,110,100,32,110,117,109,98,101,114,32,111,102,32,116,97,98,108,101,115,32,97,114,101,32,111,110,108,121,32,108,105,109,105,116,101,100,32,98,121,32,97,118,97,105,108,97,98,108,101,32,109,101,109,111,114,121,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,99,111,117,110,116>>}],[]},{code,[],[<<112,111,114,116,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,111,114,116,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<108,101,110,103,116,104,40,101,114,108,97,110,103,58,112,111,114,116,115,40,41,41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,108,105,109,105,116>>}],[]},{code,[],[<<112,111,114,116,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,115,105,109,117,108,116,97,110,101,111,117,115,108,121,32,101,120,105,115,116,105,110,103,32,112,111,114,116,115,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,117,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,81>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,81>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,99,111,117,110,116>>}],[]},{code,[],[<<112,114,111,99,101,115,115,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<108,101,110,103,116,104,40,112,114,111,99,101,115,115,101,115,40,41,41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,108,105,109,105,116>>}],[]},{code,[],[<<112,114,111,99,101,115,115,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,115,105,109,117,108,116,97,110,101,111,117,115,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,117,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,80>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,80>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,52,51,56>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2782,'fun',[{type,2782,product,[{atom,2782,atom_count}]},{type,2782,pos_integer,[]}]},{type,2783,'fun',[{type,2783,product,[{atom,2783,atom_limit}]},{type,2783,pos_integer,[]}]},{type,2810,'fun',[{type,2810,product,[{atom,2810,ets_count}]},{type,2810,pos_integer,[]}]},{type,2811,'fun',[{type,2811,product,[{atom,2811,ets_limit}]},{type,2811,pos_integer,[]}]},{type,2837,'fun',[{type,2837,product,[{atom,2837,port_count}]},{type,2837,non_neg_integer,[]}]},{type,2838,'fun',[{type,2838,product,[{atom,2838,port_limit}]},{type,2838,pos_integer,[]}]},{type,2839,'fun',[{type,2839,product,[{atom,2839,process_count}]},{type,2839,pos_integer,[]}]},{type,2840,'fun',[{type,2840,product,[{atom,2840,process_limit}]},{type,2840,pos_integer,[]}]}]}}],since => <<79,84,80,32,50,48,46,48,44,79,84,80,32,50,49,46,49,44,79,84,80,32,82,49,54,66,44,79,84,80,32,82,49,54,66,48,51>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,116,105,109,101,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>}],[]},{code,[],[<<101,110,100,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,105,110,116,101,114,110,97,108,108,121,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,84,104,101,32,116,105,109,101,32,98,101,116,119,101,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,116,97,114,116,32,116,105,109,101>>]},<<32,97,110,100,32,116,104,101,32,101,110,100,32,116,105,109,101,32,105,115,32,97,116,32,108,101,97,115,116,32,97,32,113,117,97,114,116,101,114,32,111,102,32,97,32,109,105,108,108,101,110,110,105,117,109,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>}],[]},{code,[],[<<111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,115,111,117,114,99,101,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,116,104,97,116,32,105,115,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,110,111,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,115,32,97,118,97,105,108,97,98,108,101,46,32,84,104,101,32,108,105,115,116,32,99,111,110,116,97,105,110,115,32,116,119,111,45,116,117,112,108,101,115,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<115,32,97,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,97,110,100,32>>,{code,[],[<<86,97,108,117,101>>]},<<115,32,97,115,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,115,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,108,105,115,116,44,32,98,117,116,32,109,111,114,101,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,102,117,110,99,116,105,111,110,44,32,70,117,110,99,116,105,111,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,117,115,101,100,46,32,84,104,105,115,32,116,117,112,108,101,32,97,108,119,97,121,115,32,101,120,105,115,116,115,32,105,102,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,115,32,97,118,97,105,108,97,98,108,101,32,116,111,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]},{dt,[],[{code,[],[<<123,99,108,111,99,107,95,105,100,44,32,67,108,111,99,107,73,100,125>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,116,117,112,108,101,32,111,110,108,121,32,101,120,105,115,116,115,32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,100,105,102,102,101,114,101,110,116,32,99,108,111,99,107,115,46,32>>,{code,[],[<<67,108,111,99,107,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,99,108,111,99,107,32,105,100,101,110,116,105,102,105,101,114,32,117,115,101,100,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,115,111,108,117,116,105,111,110,44,32,79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110,125>>]}]},{dd,[],[{p,[],[<<72,105,103,104,101,115,116,32,112,111,115,115,105,98,108,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,82,101,115,111,108,117,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,115,111,108,117,116,105,111,110>>]},<<32,111,102,32,99,117,114,114,101,110,116,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,115,111,117,114,99,101,32,97,115,32,112,97,114,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,73,102,32,110,111,32,114,101,115,111,108,117,116,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,102,114,111,109,32,116,104,101,32,79,83,44,32>>,{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<32,105,115,32,115,101,116,32,116,111,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,111,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<115,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,97,99,116,117,97,108,32,114,101,115,111,108,117,116,105,111,110,32,99,97,110,32,98,101,32,108,111,119,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,100,111,101,115,32,110,111,116,32,115,97,121,32,97,110,121,116,104,105,110,103,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,65,99,99,117,114,97,99,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,99,99,117,114,97,99,121>>]},<<32,111,114,32,119,104,101,116,104,101,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,80,114,101,99,105,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,101,99,105,115,105,111,110>>]},<<32,97,108,105,103,110,115,32,119,105,116,104,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,46,32,89,111,117,32,100,111,44,32,104,111,119,101,118,101,114,44,32,107,110,111,119,32,116,104,97,116,32,116,104,101,32,112,114,101,99,105,115,105,111,110,32,105,115,32,110,111,116,32,98,101,116,116,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,120,116,101,110,100,101,100,44,32,69,120,116,101,110,100,101,100,125>>]}]},{dd,[],[{p,[],[{code,[],[<<69,120,116,101,110,100,101,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<121,101,115>>]},<<32,105,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,32,104,97,115,32,98,101,101,110,32,101,120,116,101,110,100,101,100,59,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<69,120,116,101,110,100,101,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<110,111>>]},<<46,32,84,104,101,32,114,97,110,103,101,32,109,117,115,116,32,98,101,32,101,120,116,101,110,100,101,100,32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,114,101,116,117,114,110,115,32,118,97,108,117,101,115,32,116,104,97,116,32,119,114,97,112,32,102,97,115,116,46,32,84,104,105,115,32,116,121,112,105,99,97,108,108,121,32,105,115,32,116,104,101,32,99,97,115,101,32,119,104,101,110,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,32,51,50,45,98,105,116,32,118,97,108,117,101,46>>]}]},{dt,[],[{code,[],[<<123,112,97,114,97,108,108,101,108,44,32,80,97,114,97,108,108,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<121,101,115>>]},<<32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,32,102,114,111,109,32,109,117,108,116,105,112,108,101,32,116,104,114,101,97,100,115,46,32,73,102,32,105,116,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,44,32,98,101,99,97,117,115,101,32,99,97,108,108,115,32,109,117,115,116,32,98,101,32,115,101,114,105,97,108,105,122,101,100,44,32>>,{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<110,111>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,105,109,101,44,32,79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101>>]},<<32,101,113,117,97,108,115,32,99,117,114,114,101,110,116,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46>>]}]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>}],[]},{code,[],[<<111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,115,111,117,114,99,101,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,116,104,97,116,32,105,115,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<84,104,101,32,108,105,115,116,32,99,111,110,116,97,105,110,115,32,116,119,111,45,116,117,112,108,101,115,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<115,32,97,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,97,110,100,32>>,{code,[],[<<86,97,108,117,101>>]},<<115,32,97,115,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,115,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,108,105,115,116,44,32,98,117,116,32,109,111,114,101,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,102,117,110,99,116,105,111,110,44,32,70,117,110,99,116,105,111,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,102,117,110,99,105,111,110,32,117,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,99,108,111,99,107,95,105,100,44,32,67,108,111,99,107,73,100,125>>]}]},{dd,[],[{p,[],[<<69,120,105,115,116,115,32,111,110,108,121,32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,100,105,102,102,101,114,101,110,116,32,99,108,111,99,107,115,46,32>>,{code,[],[<<67,108,111,99,107,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,99,108,111,99,107,32,105,100,101,110,116,105,102,105,101,114,32,117,115,101,100,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,115,111,108,117,116,105,111,110,44,32,79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110,125>>]}]},{dd,[],[{p,[],[<<72,105,103,104,101,115,116,32,112,111,115,115,105,98,108,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,82,101,115,111,108,117,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,115,111,108,117,116,105,111,110>>]},<<32,111,102,32,99,117,114,114,101,110,116,32,79,83,32,115,121,115,116,101,109,32,116,105,109,101,32,115,111,117,114,99,101,32,97,115,32,112,97,114,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,73,102,32,110,111,32,114,101,115,111,108,117,116,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,102,114,111,109,32,116,104,101,32,79,83,44,32>>,{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<32,105,115,32,115,101,116,32,116,111,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,111,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<115,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,97,99,116,117,97,108,32,114,101,115,111,108,117,116,105,111,110,32,99,97,110,32,98,101,32,108,111,119,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,100,111,101,115,32,110,111,116,32,115,97,121,32,97,110,121,116,104,105,110,103,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,65,99,99,117,114,97,99,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,99,99,117,114,97,99,121>>]},<<32,111,114,32,119,104,101,116,104,101,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,80,114,101,99,105,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,101,99,105,115,105,111,110>>]},<<32,100,111,32,97,108,105,103,110,32,119,105,116,104,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,46,32,89,111,117,32,100,111,44,32,104,111,119,101,118,101,114,44,32,107,110,111,119,32,116,104,97,116,32,116,104,101,32,112,114,101,99,105,115,105,111,110,32,105,115,32,110,111,116,32,98,101,116,116,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,112,97,114,97,108,108,101,108,44,32,80,97,114,97,108,108,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<121,101,115>>]},<<32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,32,102,114,111,109,32,109,117,108,116,105,112,108,101,32,116,104,114,101,97,100,115,46,32,73,102,32,105,116,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,44,32,98,101,99,97,117,115,101,32,99,97,108,108,115,32,110,101,101,100,115,32,116,111,32,98,101,32,115,101,114,105,97,108,105,122,101,100,44,32>>,{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<110,111>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,105,109,101,44,32,79,115,83,121,115,116,101,109,84,105,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101>>]},<<32,101,113,117,97,108,115,32,99,117,114,114,101,110,116,32,79,83,32,115,121,115,116,101,109,32,116,105,109,101,32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46>>]}]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>}],[]},{code,[],[<<115,116,97,114,116,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<32,97,116,32,116,104,101,32,116,105,109,101,32,119,104,101,110,32,99,117,114,114,101,110,116,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,32,115,116,97,114,116,101,100,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,101,110,100,95,116,105,109,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>}],[]},{code,[],[<<116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,111,111,108,101,97,110,32,118,97,108,117,101,32,105,110,100,105,99,97,116,105,110,103,32,119,104,101,116,104,101,114,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,67,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,99,111,114,114,101,99,116,105,111,110>>]},<<32,105,115,32,101,110,97,98,108,101,100,32,111,114,32,110,111,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,111,102,102,115,101,116>>}],[]},{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,58>>]},{dl,[],[{dt,[],[{code,[],[<<112,114,101,108,105,109,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,112,114,101,108,105,109,105,110,97,114,121,44,32,97,110,100,32,119,105,108,108,32,98,101,32,99,104,97,110,103,101,100,32,97,110,100,32,102,105,110,97,108,105,122,101,100,32,108,97,116,101,114,46,32,84,104,101,32,112,114,101,108,105,109,105,110,97,114,121,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,117,115,101,100,32,100,117,114,105,110,103,32,116,104,101,32,112,114,101,108,105,109,105,110,97,114,121,32,112,104,97,115,101,32,111,102,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<102,105,110,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,102,105,110,97,108,46,32,84,104,105,115,32,101,105,116,104,101,114,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,78,111,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,44,32,111,114,32,98,101,99,97,117,115,101,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,104,97,118,101,32,98,101,101,110,32,102,105,110,97,108,105,122,101,100,32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]},{dt,[],[{code,[],[<<118,111,108,97,116,105,108,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,118,111,108,97,116,105,108,101,46,32,84,104,97,116,32,105,115,44,32,105,116,32,99,97,110,32,99,104,97,110,103,101,32,97,116,32,97,110,121,32,116,105,109,101,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,119,97,114,112,95,109,111,100,101>>}],[]},{code,[],[<<116,105,109,101,95,119,97,114,112,95,109,111,100,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,118,97,108,117,101,32,105,100,101,110,116,105,102,121,105,110,103,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,116,104,97,116,32,105,115,32,117,115,101,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<110,111,95,116,105,109,101,95,119,97,114,112>>]}]},{dd,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,78,111,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]},{dt,[],[{code,[],[<<115,105,110,103,108,101,95,116,105,109,101,95,119,97,114,112>>]}]},{dd,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]},{dt,[],[{code,[],[<<109,117,108,116,105,95,116,105,109,101,95,119,97,114,112>>]}]},{dd,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>}],[]},{code,[],[<<116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,119,104,101,116,104,101,114,32,97,32,112,114,101,32,69,82,84,83,32,55,46,48,32,98,97,99,107,119,97,114,100,115,32,99,111,109,112,97,116,105,98,108,101,32,99,111,109,112,101,110,115,97,116,105,111,110,32,102,111,114,32,115,117,100,100,101,110,32,99,104,97,110,103,101,115,32,111,102,32,115,121,115,116,101,109,32,116,105,109,101,32,105,115,32>>,{code,[],[<<101,110,97,98,108,101,100>>]},<<32,111,114,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<46,32,83,117,99,104,32,99,111,109,112,101,110,115,97,116,105,111,110,32,105,115,32>>,{code,[],[<<101,110,97,98,108,101,100>>]},<<32,119,104,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,111,102,102,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,111,102,102,115,101,116>>]},<<32,105,115,32>>,{code,[],[<<102,105,110,97,108>>]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,99,111,114,114,101,99,116,105,111,110>>]},<<32,105,115,32,101,110,97,98,108,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,53,49,56>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2809,'fun',[{type,2809,product,[{atom,2809,end_time}]},{type,2809,non_neg_integer,[]}]},{type,2834,'fun',[{type,2834,product,[{atom,2834,os_monotonic_time_source}]},{type,2834,list,[{type,2834,tuple,[{type,2834,atom,[]},{type,2834,term,[]}]}]}]},{type,2835,'fun',[{type,2835,product,[{atom,2835,os_system_time_source}]},{type,2835,list,[{type,2835,tuple,[{type,2835,atom,[]},{type,2835,term,[]}]}]}]},{type,2854,'fun',[{type,2854,product,[{atom,2854,start_time}]},{type,2854,integer,[]}]},{type,2860,'fun',[{type,2860,product,[{atom,2860,time_correction}]},{type,2860,union,[{atom,2860,true},{atom,2860,false}]}]},{type,2861,'fun',[{type,2861,product,[{atom,2861,time_offset}]},{type,2861,union,[{atom,2861,preliminary},{atom,2861,final},{atom,2861,volatile}]}]},{type,2862,'fun',[{type,2862,product,[{atom,2862,time_warp_mode}]},{type,2862,union,[{atom,2862,no_time_warp},{atom,2862,single_time_warp},{atom,2862,multi_time_warp}]}]},{type,2863,'fun',[{type,2863,product,[{atom,2863,tolerant_timeofday}]},{type,2863,union,[{atom,2863,enabled},{atom,2863,disabled}]}]}]}}],since => <<79,84,80,32,49,55,46,49,44,79,84,80,32,49,56,46,48>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,99,104,101,100,117,108,101,114,115,44,32,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,116,104,114,101,97,100,115,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>}],[]},{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,68,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,101,120,101,99,117,116,101,32,67,80,85,45,98,111,117,110,100,32,110,97,116,105,118,101,32,102,117,110,99,116,105,111,110,115,44,32,115,117,99,104,32,97,115,32,78,73,70,115,44,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,99,111,100,101,44,32,97,110,100,32,66,73,70,115,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,109,97,110,97,103,101,100,32,99,108,101,97,110,108,121,32,98,121,32,116,104,101,32,110,111,114,109,97,108,32,101,109,117,108,97,116,111,114,32,115,99,104,101,100,117,108,101,114,115,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,32,97,110,100,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,97,102,116,101,114,32,116,104,97,116,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,46,32,84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,99,112,117>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,80,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,80,99,112,117>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>}],[]},{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,115,97,116,105,115,102,105,101,115,32>>,{code,[],[<<49,32,60,61,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,32,60,61,32,78>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]},<<46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,99,112,117>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>}],[]},{code,[],[<<100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,68,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,32,101,120,101,99,117,116,101,32,73,47,79,45,98,111,117,110,100,32,110,97,116,105,118,101,32,102,117,110,99,116,105,111,110,115,44,32,115,117,99,104,32,97,115,32,78,73,70,115,32,97,110,100,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,99,111,100,101,44,32,119,104,105,99,104,32,99,97,110,110,111,116,32,98,101,32,109,97,110,97,103,101,100,32,99,108,101,97,110,108,121,32,98,121,32,116,104,101,32,110,111,114,109,97,108,32,101,109,117,108,97,116,111,114,32,115,99,104,101,100,117,108,101,114,115,46>>]},{p,[],[<<84,104,105,115,32,118,97,108,117,101,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,105,111>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>}],[]},{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<100,105,115,97,98,108,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,98,101,101,110,32,115,116,97,114,116,101,100,32,119,105,116,104,32,111,110,108,121,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<98,108,111,99,107,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,44,32,98,117,116,32,97,108,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,101,120,99,101,112,116,32,111,110,101,32,97,114,101,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,115,99,104,101,100,117,108,101,115,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,101,120,101,99,117,116,101,115,32,69,114,108,97,110,103,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<98,108,111,99,107,101,100,95,110,111,114,109,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,44,32,98,117,116,32,97,108,108,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,101,120,99,101,112,116,32,111,110,101,32,97,114,101,32,98,108,111,99,107,101,100,46,32,78,111,116,105,99,101,32,116,104,97,116,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,110,111,116,32,98,108,111,99,107,101,100,44,32,97,110,100,32,99,97,110,32,115,99,104,101,100,117,108,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,101,120,101,99,117,116,101,32,110,97,116,105,118,101,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<101,110,97,98,108,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,44,32,97,110,100,32,110,111,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,97,114,101,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,97,108,108,32,97,118,97,105,108,97,98,108,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,115,99,104,101,100,117,108,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,101,120,101,99,117,116,101,32,69,114,108,97,110,103,32,99,111,100,101,46>>]}]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>}],[]},{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<115,32,119,104,101,110,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32>>,{code,[],[<<80,105,100>>]},<<115,32,105,110,32,116,104,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,98,108,111,99,107,105,110,103,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,46,32,65,32>>,{code,[],[<<80,105,100>>]},<<32,111,99,99,117,114,115,32,111,110,108,121,32,111,110,99,101,32,105,110,32,116,104,101,32,108,105,115,116,44,32,101,118,101,110,32,105,102,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>}],[]},{code,[],[<<110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<115,32,119,104,101,110,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,32,40,116,104,97,116,32,105,115,44,32,97,108,108,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,98,117,116,32,111,110,101,32,105,115,32,98,108,111,99,107,101,100,41,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32>>,{code,[],[<<80,105,100>>]},<<115,32,105,110,32,116,104,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,98,108,111,99,107,105,110,103,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,46,32,65,32>>,{code,[],[<<80,105,100>>]},<<32,111,99,99,117,114,115,32,111,110,108,121,32,111,110,99,101,32,105,110,32,116,104,101,32,108,105,115,116,44,32,101,118,101,110,32,105,102,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,104,111,119,32,116,104,101,32,117,115,101,114,32,104,97,115,32,114,101,113,117,101,115,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,98,101,32,98,111,117,110,100,32,111,114,32,110,111,116,32,98,111,117,110,100,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,108,116,104,111,117,103,104,32,97,32,117,115,101,114,32,104,97,115,32,114,101,113,117,101,115,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,98,101,32,98,111,117,110,100,44,32,116,104,101,121,32,99,97,110,32,115,105,108,101,110,116,108,121,32,104,97,118,101,32,102,97,105,108,101,100,32,116,111,32,98,105,110,100,46,32,84,111,32,105,110,115,112,101,99,116,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,105,110,103,115,44,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,105,110,103,115,46>>]},{p,[],[<<65,32,116,117,112,108,101,32,111,102,32,97,32,115,105,122,101,32,101,113,117,97,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,116,117,112,108,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,105,110,116,101,103,101,114,115,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,98,111,117,110,100>>]},<<46,32,76,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,115,32,97,114,101,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32,105,110,116,101,103,101,114,115,46,32,84,104,101,32>>,{code,[],[<<78>>]},<<116,104,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,116,117,112,108,101,32,101,113,117,97,108,115,32,116,104,101,32,99,117,114,114,101,110,116,32,98,105,110,100,105,110,103,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,119,105,116,104,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<78>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,111,117,110,100,44,32>>,{code,[],[<<101,108,101,109,101,110,116,40,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,105,100,41,44,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41,41>>]},<<32,114,101,116,117,114,110,115,32,116,104,101,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,111,110,108,121,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,98,111,117,110,100,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,105,100>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,95,105,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,73,68,32,40>>,{code,[],[<<83,99,104,101,100,117,108,101,114,73,100>>]},<<41,32,111,102,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{code,[],[<<83,99,104,101,100,117,108,101,114,73,100>>]},<<32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,44,32,119,104,101,114,101,32>>,{code,[],[<<49,32,60,61,32,83,99,104,101,100,117,108,101,114,73,100,32,60,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,111,110,108,105,110,101,32,115,99,104,101,100,117,108,101,115,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,69,114,108,97,110,103,32,112,111,114,116,115,44,32,97,110,100,32,101,120,101,99,117,116,101,32,69,114,108,97,110,103,32,99,111,100,101,32,97,110,100,32,69,114,108,97,110,103,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,99,111,100,101,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,32,97,110,100,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,108,97,116,101,114,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,105,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,105,100,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,84,104,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,115,97,116,105,115,102,121,32,116,104,101,32,114,101,108,97,116,105,111,110,115,104,105,112,32>>,{code,[],[<<49,32,60,61,32,83,99,104,101,100,117,108,101,114,73,100,32,60,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,109,112,95,115,117,112,112,111,114,116>>}],[]},{code,[],[<<115,109,112,95,115,117,112,112,111,114,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,115>>}],[]},{code,[],[<<116,104,114,101,97,100,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>}],[]},{code,[],[<<116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,115,121,110,99,32,116,104,114,101,97,100,115,32,105,110,32,116,104,101,32,97,115,121,110,99,32,116,104,114,101,97,100,32,112,111,111,108,32,117,115,101,100,32,102,111,114,32,97,115,121,110,99,104,114,111,110,111,117,115,32,100,114,105,118,101,114,32,99,97,108,108,115,32,40>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,114,105,118,101,114,35,100,114,105,118,101,114,95,97,115,121,110,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<32>>,{code,[],[<<101,114,108,95,100,114,105,118,101,114,58,100,114,105,118,101,114,95,97,115,121,110,99,40,41>>]}]},<<41,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,55,52,54>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2796,'fun',[{type,2796,product,[{atom,2796,dirty_cpu_schedulers}]},{type,2796,non_neg_integer,[]}]},{type,2797,'fun',[{type,2797,product,[{atom,2797,dirty_cpu_schedulers_online}]},{type,2797,non_neg_integer,[]}]},{type,2798,'fun',[{type,2798,product,[{atom,2798,dirty_io_schedulers}]},{type,2798,non_neg_integer,[]}]},{type,2829,'fun',[{type,2829,product,[{atom,2829,multi_scheduling}]},{type,2829,union,[{atom,2829,disabled},{atom,2829,blocked},{atom,2829,blocked_normal},{atom,2829,enabled}]}]},{type,2830,'fun',[{type,2830,product,[{atom,2830,multi_scheduling_blockers}]},{type,2830,list,[{ann_type,2830,[{var,2830,'Pid'},{type,2830,pid,[]}]}]}]},{type,2832,'fun',[{type,2832,product,[{atom,2832,normal_multi_scheduling_blockers}]},{type,2832,list,[{ann_type,2832,[{var,2832,'Pid'},{type,2832,pid,[]}]}]}]},{type,2842,'fun',[{type,2842,product,[{atom,2842,scheduler_bind_type}]},{type,2842,union,[{atom,2842,spread},{atom,2843,processor_spread},{atom,2844,thread_spread},{atom,2845,thread_no_node_processor_spread},{atom,2846,no_node_processor_spread},{atom,2847,no_node_thread_spread},{atom,2848,no_spread},{atom,2849,unbound}]}]},{type,2850,'fun',[{type,2850,product,[{atom,2850,scheduler_bindings}]},{type,2850,tuple,any}]},{type,2851,'fun',[{type,2851,product,[{atom,2851,scheduler_id}]},{ann_type,2851,[{var,2851,'SchedulerId'},{type,2851,pos_integer,[]}]}]},{type,2852,'fun',[{type,2852,product,[{type,2852,union,[{atom,2852,schedulers},{atom,2852,schedulers_online}]}]},{type,2852,pos_integer,[]}]},{type,2853,'fun',[{type,2853,product,[{atom,2853,smp_support}]},{type,2853,boolean,[]}]},{type,2858,'fun',[{type,2858,product,[{atom,2858,threads}]},{type,2858,boolean,[]}]},{type,2859,'fun',[{type,2859,product,[{atom,2859,thread_pool_size}]},{type,2859,non_neg_integer,[]}]}]}}],since => <<79,84,80,32,49,55,46,48,44,79,84,80,32,49,57,46,48>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,114,101,97,116,105,111,110>>}],[]},{code,[],[<<99,114,101,97,116,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,114,101,97,116,105,111,110,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,101,32,99,114,101,97,116,105,111,110,32,105,115,32,99,104,97,110,103,101,100,32,119,104,101,110,32,97,32,110,111,100,101,32,105,115,32,114,101,115,116,97,114,116,101,100,46,32,84,104,101,32,99,114,101,97,116,105,111,110,32,111,102,32,97,32,110,111,100,101,32,105,115,32,115,116,111,114,101,100,32,105,110,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,44,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,44,32,97,110,100,32,114,101,102,101,114,101,110,99,101,115,46,32,84,104,105,115,32,109,97,107,101,115,32,105,116,32,40,116,111,32,115,111,109,101,32,101,120,116,101,110,116,41,32,112,111,115,115,105,98,108,101,32,116,111,32,100,105,115,116,105,110,103,117,105,115,104,32,98,101,116,119,101,101,110,32,105,100,101,110,116,105,102,105,101,114,115,32,102,114,111,109,32,100,105,102,102,101,114,101,110,116,32,105,110,99,97,114,110,97,116,105,111,110,115,32,111,102,32,97,32,110,111,100,101,46,32,84,104,101,32,118,97,108,105,100,32,99,114,101,97,116,105,111,110,115,32,97,114,101,32,105,110,116,101,103,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,49,46,46,51,44,32,98,117,116,32,116,104,105,115,32,119,105,108,108,32,112,114,111,98,97,98,108,121,32,99,104,97,110,103,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,73,102,32,116,104,101,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<48>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>}],[]},{code,[],[<<100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,116,105,109,101,32,105,110,32,115,101,99,111,110,100,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,97,110,32,101,110,116,114,121,32,105,110,32,97,32,110,111,100,101,32,116,97,98,108,101,32,105,115,32,100,101,108,97,121,101,100,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,115,101,116,32,111,110,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,122,100,110,116,103,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,122,100,110,116,103,99>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116>>}],[]},{code,[],[<<100,105,115,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,100,105,115,116,114,105,98,117,116,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>}],[]},{code,[],[<<100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,98,117,102,102,101,114,32,98,117,115,121,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,122,100,98,98,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,122,100,98,98,108>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,99,116,114,108>>}],[]},{code,[],[<<100,105,115,116,95,99,116,114,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32>>,{code,[],[<<123,78,111,100,101,44,32,67,111,110,116,114,111,108,108,105,110,103,69,110,116,105,116,121,125>>]},<<44,32,111,110,101,32,101,110,116,114,121,32,102,111,114,32,101,97,99,104,32,99,111,110,110,101,99,116,101,100,32,114,101,109,111,116,101,32,110,111,100,101,46,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,116,104,101,32,110,111,100,101,32,110,97,109,101,32,97,110,100,32>>,{code,[],[<<67,111,110,116,114,111,108,108,105,110,103,69,110,116,105,116,121>>]},<<32,105,115,32,116,104,101,32,112,111,114,116,32,111,114,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,116,104,101,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,116,111,32,116,104,97,116,32,110,111,100,101,46,32,77,111,114,101,32,115,112,101,99,105,102,105,99,97,108,108,121,44,32>>,{code,[],[<<67,111,110,116,114,111,108,108,105,110,103,69,110,116,105,116,121>>]},<<32,102,111,114,32,110,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,104,114,111,117,103,104,32,84,67,80,47,73,80,32,40,116,104,101,32,110,111,114,109,97,108,32,99,97,115,101,41,32,105,115,32,116,104,101,32,115,111,99,107,101,116,32,117,115,101,100,32,105,110,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,99,32,110,111,100,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,48,52,54>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2793,'fun',[{type,2793,product,[{atom,2793,creation}]},{type,2793,integer,[]}]},{type,2795,'fun',[{type,2795,product,[{atom,2795,delayed_node_table_gc}]},{type,2795,union,[{atom,2795,infinity},{type,2795,non_neg_integer,[]}]}]},{type,2799,'fun',[{type,2799,product,[{atom,2799,dist}]},{type,2799,binary,[]}]},{type,2800,'fun',[{type,2800,product,[{atom,2800,dist_buf_busy_limit}]},{type,2800,non_neg_integer,[]}]},{type,2801,'fun',[{type,2801,product,[{atom,2801,dist_ctrl}]},{type,2801,tuple,[{ann_type,2801,[{var,2801,'Node'},{type,2801,node,[]}]},{ann_type,2802,[{var,2802,'ControllingEntity'},{type,2802,union,[{type,2802,port,[]},{type,2802,pid,[]}]}]}]}]}]}}],since => <<79,84,80,32,49,56,46,48,44,79,84,80,32,82,49,52,66,48,49>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2766}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,105,115,99,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,98,117,105,108,100,95,116,121,112,101>>}],[]},{code,[],[<<98,117,105,108,100,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<68,101,112,114,101,99,97,116,101,100,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,109,117,95,116,121,112,101>>]},<<32,105,110,115,116,101,97,100>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>}],[]},{code,[],[<<99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,119,111,45,116,117,112,108,101,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,67,32,99,111,109,112,105,108,101,114,32,117,115,101,100,32,119,104,101,110,32,99,111,109,112,105,108,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,99,111,109,112,105,108,101,114,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,117,110,107,110,111,119,110,46,32,84,104,101,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,32,105,115,32,97,32,116,101,114,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,99,111,109,112,105,108,101,114,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,117,110,107,110,111,119,110,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,104,101,99,107,95,105,111>>}],[]},{code,[],[<<99,104,101,99,107,95,105,111>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,101,109,117,108,97,116,111,114,115,32,105,110,116,101,114,110,97,108,32,73,47,79,32,99,104,101,99,107,105,110,103,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,118,97,114,121,32,98,101,116,119,101,101,110,32,112,108,97,116,102,111,114,109,115,32,97,110,100,32,111,118,101,114,32,116,105,109,101,46,32,73,116,32,105,115,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,97,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,111,109,112,97,116,95,114,101,108>>}],[]},{code,[],[<<99,111,109,112,97,116,95,114,101,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,109,111,100,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,101,32,105,110,116,101,103,101,114,32,114,101,116,117,114,110,101,100,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,69,114,108,97,110,103,47,79,84,80,32,114,101,108,101,97,115,101,32,116,104,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,101,109,117,108,97,116,111,114,32,104,97,115,32,98,101,101,110,32,115,101,116,32,116,111,32,98,101,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,46,32,84,104,101,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,109,111,100,101,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,117,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,99,111,109,112,97,116,95,114,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,82>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,101,98,117,103,95,99,111,109,112,105,108,101,100>>}],[]},{code,[],[<<100,101,98,117,103,95,99,111,109,112,105,108,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,98,101,101,110,32,100,101,98,117,103,45,99,111,109,112,105,108,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,114,105,118,101,114,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<100,114,105,118,101,114,95,118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,100,114,105,118,101,114,32,118,101,114,115,105,111,110,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,73,116,32,104,97,115,32,116,104,101,32,102,111,114,109,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,114,105,118,101,114,35,118,101,114,115,105,111,110,95,109,97,110,97,103,101,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<34,60,109,97,106,111,114,32,118,101,114,62,46,60,109,105,110,111,114,32,118,101,114,62,34>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101>>}],[]},{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,100,121,110,97,109,105,99,32,116,114,97,99,101,32,102,114,97,109,101,119,111,114,107,32,99,111,109,112,105,108,101,100,32,105,110,116,111,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,46,32,73,116,32,99,97,110,32,98,101,32>>,{code,[],[<<100,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<115,121,115,116,101,109,116,97,112>>]},<<44,32,111,114,32>>,{code,[],[<<110,111,110,101>>]},<<46,32,70,111,114,32,97,32,99,111,109,109,101,114,99,105,97,108,32,111,114,32,115,116,97,110,100,97,114,100,32,98,117,105,108,100,44,32,105,116,32,105,115,32,97,108,119,97,121,115,32>>,{code,[],[<<110,111,110,101>>]},<<46,32,84,104,101,32,111,116,104,101,114,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,105,110,100,105,99,97,116,101,32,97,32,99,117,115,116,111,109,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<46,47,99,111,110,102,105,103,117,114,101,32,45,45,119,105,116,104,45,100,121,110,97,109,105,99,45,116,114,97,99,101,61,100,116,114,97,99,101>>]},<<41,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,100,121,110,97,109,105,99,32,116,114,97,99,105,110,103,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,117,110,116,105,109,101,95,116,111,111,108,115,58,100,121,110,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,121,110,116,114,97,99,101,40,51,41>>]}]},<<32,109,97,110,117,97,108,32,112,97,103,101,32,97,110,100,32,116,104,101,32>>,{code,[],[<<82,69,65,68,77,69,46,100,116,114,97,99,101>>]},<<47>>,{code,[],[<<82,69,65,68,77,69,46,115,121,115,116,101,109,116,97,112>>]},<<32,102,105,108,101,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,115,111,117,114,99,101,32,99,111,100,101,32,116,111,112,32,100,105,114,101,99,116,111,114,121,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>}],[]},{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32>>,{code,[],[<<98,111,111,108,101,97,110,40,41>>]},<<32,105,110,100,105,99,97,116,105,110,103,32,105,102,32,100,121,110,97,109,105,99,32,116,114,97,99,101,32,112,114,111,98,101,115,32,40>>,{code,[],[<<100,116,114,97,99,101>>]},<<32,111,114,32>>,{code,[],[<<115,121,115,116,101,109,116,97,112>>]},<<41,32,97,114,101,32,98,117,105,108,116,32,105,110,116,111,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,84,104,105,115,32,99,97,110,32,111,110,108,121,32,98,101,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,119,97,115,32,98,117,105,108,116,32,102,111,114,32,100,121,110,97,109,105,99,32,116,114,97,99,105,110,103,32,40,116,104,97,116,32,105,115,44,32>>,{code,[],[<<115,121,115,116,101,109,95,105,110,102,111,40,100,121,110,97,109,105,99,95,116,114,97,99,101,41>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<100,116,114,97,99,101>>]},<<32,111,114,32>>,{code,[],[<<115,121,115,116,101,109,116,97,112>>]},<<41,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,102,108,97,118,111,114>>}],[]},{code,[],[<<101,109,117,95,102,108,97,118,111,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,102,108,97,118,111,114,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,105,115,32,119,105,108,108,32,98,101,32,101,105,116,104,101,114,32>>,{code,[],[<<101,109,117>>]},<<32,111,114,32>>,{code,[],[<<106,105,116>>]},<<46,32,80,111,115,115,105,98,108,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,111,114,32,114,101,109,111,118,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,116,121,112,101>>}],[]},{code,[],[<<101,109,117,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,98,117,105,108,100,32,116,121,112,101,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,105,115,32,105,115,32,110,111,114,109,97,108,108,121,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,112,116>>]},<<32,102,111,114,32,111,112,116,105,109,105,122,101,100,46,32,79,116,104,101,114,32,112,111,115,115,105,98,108,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,97,114,101,32>>,{code,[],[<<100,101,98,117,103>>]},<<44,32>>,{code,[],[<<103,99,111,118>>]},<<44,32>>,{code,[],[<<118,97,108,103,114,105,110,100>>]},<<44,32>>,{code,[],[<<103,112,114,111,102>>]},<<44,32,97,110,100,32>>,{code,[],[<<108,99,110,116>>]},<<46,32,80,111,115,115,105,98,108,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,111,114,32,114,101,109,111,118,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,105,110,102,111>>}],[]},{code,[],[<<105,110,102,111>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,115,121,115,116,101,109,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,107,101,114,110,101,108,95,112,111,108,108>>}],[]},{code,[],[<<107,101,114,110,101,108,95,112,111,108,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,117,115,101,115,32,115,111,109,101,32,107,105,110,100,32,111,102,32,107,101,114,110,101,108,45,112,111,108,108,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,97,100,101,100>>}],[]},{code,[],[<<108,111,97,100,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,108,111,97,100,101,100,32,109,111,100,117,108,101,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,97,99,104,105,110,101>>}],[]},{code,[],[<<109,97,99,104,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,109,97,99,104,105,110,101,32,110,97,109,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>}],[]},{code,[],[<<109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,111,100,105,102,105,101,100,32,116,105,109,105,110,103,45,108,101,118,101,108,32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,102,32,109,111,100,105,102,105,101,100,32,116,105,109,105,110,103,32,105,115,32,101,110,97,98,108,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,109,111,100,105,102,105,101,100,32,116,105,109,105,110,103,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,84>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,84>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,110,105,102,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<110,105,102,95,118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,78,73,70,32,105,110,116,101,114,102,97,99,101,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,73,116,32,105,115,32,111,110,32,116,104,101,32,102,111,114,109,32,34,60,109,97,106,111,114,32,118,101,114,62,46,60,109,105,110,111,114,32,118,101,114,62,34,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,116,112,95,114,101,108,101,97,115,101>>}],[]},{code,[],[<<111,116,112,95,114,101,108,101,97,115,101>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,116,112,95,114,101,108,101,97,115,101>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,79,84,80,32,114,101,108,101,97,115,101,32,110,117,109,98,101,114,32,111,102,32,116,104,101,32,79,84,80,32,114,101,108,101,97,115,101,32,116,104,97,116,32,116,104,101,32,99,117,114,114,101,110,116,108,121,32,101,120,101,99,117,116,105,110,103,32,69,82,84,83,32,97,112,112,108,105,99,97,116,105,111,110,32,105,115,32,112,97,114,116,32,111,102,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,49,55,44,32,116,104,101,32,79,84,80,32,114,101,108,101,97,115,101,32,110,117,109,98,101,114,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,109,97,106,111,114,32,79,84,80,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,46,32,78,111,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,41>>]},<<32,97,114,103,117,109,101,110,116,32,103,105,118,101,115,32,116,104,101,32,101,120,97,99,116,32,79,84,80,32,118,101,114,115,105,111,110,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,101,120,97,99,116,32,79,84,80,32,118,101,114,115,105,111,110,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,32,105,115,32,100,105,102,102,105,99,117,108,116,32,116,111,32,100,101,116,101,114,109,105,110,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,118,101,114,115,105,111,110,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,115,121,115,116,101,109,95,112,114,105,110,99,105,112,108,101,115,58,118,101,114,115,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<83,121,115,116,101,109,32,112,114,105,110,99,105,112,108,101,115>>]},<<32,105,110,32,83,121,115,116,101,109,32,68,111,99,117,109,101,110,116,97,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>}],[]},{code,[],[<<112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,102,97,117,108,116,32,112,111,114,116,32,112,97,114,97,108,108,101,108,105,115,109,32,115,99,104,101,100,117,108,105,110,103,32,104,105,110,116,32,117,115,101,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,112,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,112,112>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>}],[]},{code,[],[<<115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,112,114,111,99,101,115,115,111,114,32,97,110,100,32,79,83,32,97,114,99,104,105,116,101,99,116,117,114,101,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,98,117,105,108,116,32,102,111,114,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,108,111,103,103,101,114>>}],[]},{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32>>,{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]},<<32,97,115,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,121,115,116,101,109,95,108,111,103,103,101,114,44,32,95,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<115,121,115,116,101,109,95,118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,32,97,110,100,32,115,111,109,101,32,105,109,112,111,114,116,97,110,116,32,112,114,111,112,101,114,116,105,101,115,44,32,115,117,99,104,32,97,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>}],[]},{code,[],[<<116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,110,111,100,101,32,116,114,97,99,101,32,99,111,110,116,114,111,108,32,119,111,114,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<103,101,116,95,116,99,119>>]},<<32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99,35,103,101,116,95,116,99,119>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,32,111,102,32,116,104,101,32,101,109,117,108,97,116,111,114,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,119,111,114,100,115,105,122,101>>}],[]},{code,[],[<<119,111,114,100,115,105,122,101>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<123,119,111,114,100,115,105,122,101,44,32,105,110,116,101,114,110,97,108,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,119,111,114,100,115,105,122,101,44,32,105,110,116,101,114,110,97,108,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,105,122,101,32,111,102,32,69,114,108,97,110,103,32,116,101,114,109,32,119,111,114,100,115,32,105,110,32,98,121,116,101,115,32,97,115,32,97,110,32,105,110,116,101,103,101,114,44,32,116,104,97,116,32,105,115,44,32,52,32,105,115,32,114,101,116,117,114,110,101,100,32,111,110,32,97,32,51,50,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,44,32,97,110,100,32,56,32,105,115,32,114,101,116,117,114,110,101,100,32,111,110,32,97,32,112,117,114,101,32,54,52,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,46,32,79,110,32,97,32,104,97,108,102,119,111,114,100,32,54,52,45,98,105,116,32,101,109,117,108,97,116,111,114,44,32,52,32,105,115,32,114,101,116,117,114,110,101,100,44,32,97,115,32,116,104,101,32,69,114,108,97,110,103,32,116,101,114,109,115,32,97,114,101,32,115,116,111,114,101,100,32,117,115,105,110,103,32,97,32,118,105,114,116,117,97,108,32,119,111,114,100,32,115,105,122,101,32,111,102,32,104,97,108,102,32,116,104,101,32,115,121,115,116,101,109,32,119,111,114,100,32,115,105,122,101,46>>]}]},{dt,[],[{code,[],[<<123,119,111,114,100,115,105,122,101,44,32,101,120,116,101,114,110,97,108,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,114,117,101,32,119,111,114,100,32,115,105,122,101,32,111,102,32,116,104,101,32,101,109,117,108,97,116,111,114,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,115,105,122,101,32,111,102,32,97,32,112,111,105,110,116,101,114,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,105,110,32,98,121,116,101,115,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,79,110,32,97,32,112,117,114,101,32,51,50,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,44,32,52,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,110,32,98,111,116,104,32,97,32,104,97,108,102,32,119,111,114,100,32,97,110,100,32,111,110,32,97,32,112,117,114,101,32,54,52,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,44,32,56,32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,49,49,55>>,signature => [{attribute,2766,spec,{{erlang,system_info,1},[{type,2786,'fun',[{type,2786,product,[{atom,2786,c_compiler_used}]},{type,2786,tuple,[{type,2786,atom,[]},{type,2786,term,[]}]}]},{type,2787,'fun',[{type,2787,product,[{atom,2787,check_io}]},{type,2787,list,[{var,2787,'_'}]}]},{type,2788,'fun',[{type,2788,product,[{atom,2788,compat_rel}]},{type,2788,integer,[]}]},{type,2794,'fun',[{type,2794,product,[{atom,2794,debug_compiled}]},{type,2794,boolean,[]}]},{type,2803,'fun',[{type,2803,product,[{atom,2803,driver_version}]},{type,2803,string,[]}]},{type,2804,'fun',[{type,2804,product,[{atom,2804,dynamic_trace}]},{type,2804,union,[{atom,2804,none},{atom,2804,dtrace},{atom,2804,systemtap}]}]},{type,2805,'fun',[{type,2805,product,[{atom,2805,dynamic_trace_probes}]},{type,2805,boolean,[]}]},{type,2807,'fun',[{type,2807,product,[{atom,2807,emu_flavor}]},{type,2807,union,[{atom,2807,emu},{atom,2807,jit}]}]},{type,2808,'fun',[{type,2808,product,[{atom,2808,emu_type}]},{type,2808,union,[{atom,2808,opt},{atom,2808,debug},{atom,2808,gcov},{atom,2808,valgrind},{atom,2808,gprof},{atom,2808,lcnt},{atom,2808,frmptr}]}]},{type,2816,'fun',[{type,2816,product,[{atom,2816,info}]},{type,2816,binary,[]}]},{type,2817,'fun',[{type,2817,product,[{atom,2817,kernel_poll}]},{type,2817,boolean,[]}]},{type,2818,'fun',[{type,2818,product,[{atom,2818,loaded}]},{type,2818,binary,[]}]},{type,2822,'fun',[{type,2822,product,[{atom,2822,machine}]},{type,2822,string,[]}]},{type,2828,'fun',[{type,2828,product,[{atom,2828,modified_timing_level}]},{type,2828,union,[{type,2828,integer,[]},{atom,2828,undefined}]}]},{type,2831,'fun',[{type,2831,product,[{atom,2831,nif_version}]},{type,2831,string,[]}]},{type,2833,'fun',[{type,2833,product,[{atom,2833,otp_release}]},{type,2833,string,[]}]},{type,2836,'fun',[{type,2836,product,[{atom,2836,port_parallelism}]},{type,2836,boolean,[]}]},{type,2855,'fun',[{type,2855,product,[{atom,2855,system_architecture}]},{type,2855,string,[]}]},{type,2856,'fun',[{type,2856,product,[{atom,2856,system_logger}]},{type,2856,union,[{atom,2856,logger},{atom,2856,undefined},{type,2856,pid,[]}]}]},{type,2857,'fun',[{type,2857,product,[{atom,2857,system_version}]},{type,2857,string,[]}]},{type,2864,'fun',[{type,2864,product,[{atom,2864,trace_control_word}]},{type,2864,non_neg_integer,[]}]},{type,2866,'fun',[{type,2866,product,[{atom,2866,version}]},{type,2866,string,[]}]},{type,2867,'fun',[{type,2867,product,[{type,2867,union,[{atom,2867,wordsize},{type,2867,tuple,[{atom,2867,wordsize},{atom,2867,internal}]},{type,2867,tuple,[{atom,2867,wordsize},{atom,2867,external}]}]}]},{type,2867,union,[{integer,2867,4},{integer,2867,8}]}]}]}}],since => <<79,84,80,32,49,55,46,52,44,79,84,80,32,50,49,46,51,44,79,84,80,32,50,52,46,48,44,79,84,80,32,82,49,53,66,48,49,44,79,84,80,32,82,49,54,66>>}},{{function,system_monitor,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1957}],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,105,110,103,32,115,101,116,116,105,110,103,115,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>]}]},<<32,97,115,32>>,{code,[],[<<123,77,111,110,105,116,111,114,80,105,100,44,32,79,112,116,105,111,110,115,125>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,110,111,32,115,101,116,116,105,110,103,115,32,101,120,105,115,116,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,111,110,101,32,116,104,97,116,32,119,97,115,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,52,50,52>>,signature => [{attribute,1957,spec,{{erlang,system_monitor,0},[{type,1957,bounded_fun,[{type,1957,'fun',[{type,1957,product,[]},{var,1957,'MonSettings'}]},[{type,1958,constraint,[{atom,1958,is_subtype},[{var,1958,'MonSettings'},{type,1958,union,[{atom,1958,undefined},{type,1958,tuple,[{var,1958,'MonitorPid'},{var,1958,'Options'}]}]}]]},{type,1959,constraint,[{atom,1959,is_subtype},[{var,1959,'MonitorPid'},{type,1959,pid,[]}]]},{type,1960,constraint,[{atom,1960,is_subtype},[{var,1960,'Options'},{type,1960,list,[{user_type,1960,system_monitor_option,[]}]}]]}]]}]}}]}},{{function,system_monitor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1965}],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<87,104,101,110,32,99,97,108,108,101,100,32,119,105,116,104,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<44,32,97,108,108,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,32,109,111,110,105,116,111,114,105,110,103,32,115,101,116,116,105,110,103,115,32,97,114,101,32,99,108,101,97,114,101,100,46>>]},{p,[],[<<67,97,108,108,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,32,119,105,116,104,32>>,{code,[],[<<123,77,111,110,105,116,111,114,80,105,100,44,32,79,112,116,105,111,110,115,125>>]},<<32,97,115,32,97,114,103,117,109,101,110,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,80,105,100,44,32,79,112,116,105,111,110,115,41>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,115,101,116,116,105,110,103,115,32,106,117,115,116,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,52,51,56>>,signature => [{attribute,1965,spec,{{erlang,system_monitor,1},[{type,1965,bounded_fun,[{type,1965,'fun',[{type,1965,product,[{var,1965,'Arg'}]},{var,1965,'MonSettings'}]},[{type,1966,constraint,[{atom,1966,is_subtype},[{var,1966,'Arg'},{type,1966,union,[{atom,1966,undefined},{type,1966,tuple,[{var,1966,'MonitorPid'},{var,1966,'Options'}]}]}]]},{type,1967,constraint,[{atom,1967,is_subtype},[{var,1967,'MonSettings'},{type,1967,union,[{atom,1967,undefined},{type,1967,tuple,[{var,1967,'MonitorPid'},{var,1967,'Options'}]}]}]]},{type,1968,constraint,[{atom,1968,is_subtype},[{var,1968,'MonitorPid'},{type,1968,pid,[]}]]},{type,1969,constraint,[{atom,1969,is_subtype},[{var,1969,'Options'},{type,1969,list,[{user_type,1969,system_monitor_option,[]}]}]]}]]}]}}]}},{{function,system_monitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1974}],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,32,109,111,110,105,116,111,114,105,110,103,32,111,112,116,105,111,110,115,46,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,114,101,99,101,105,118,105,110,103,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,108,105,115,116,32,111,102,32,109,111,110,105,116,111,114,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,108,111,110,103,95,103,99,44,32,84,105,109,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,116,97,107,101,115,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<84,105,109,101>>]},<<32,119,97,108,108,32,99,108,111,99,107,32,109,105,108,108,105,115,101,99,111,110,100,115,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,71,99,80,105,100,44,32,108,111,110,103,95,103,99,44,32,73,110,102,111,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<71,99,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,105,100,32,116,104,97,116,32,119,97,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,101,108,101,109,101,110,116,32,116,117,112,108,101,115,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[<<79,110,101,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,115,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,71,99,84,105,109,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<71,99,84,105,109,101>>]},<<32,105,115,32,116,104,101,32,116,105,109,101,32,102,111,114,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,46,32,84,104,101,32,111,116,104,101,114,32,116,117,112,108,101,115,32,97,114,101,32,116,97,103,103,101,100,32,119,105,116,104,32>>,{code,[],[<<104,101,97,112,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<115,116,97,99,107,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<109,98,117,102,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<111,108,100,95,104,101,97,112,95,115,105,122,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<111,108,100,95,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<46,32,84,104,101,115,101,32,116,117,112,108,101,115,32,97,114,101,32,101,120,112,108,97,105,110,101,100,32,105,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]}]},<<32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<41,46,32,78,101,119,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,44,32,97,110,100,32,116,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,110,32,116,104,101,32>>,{code,[],[<<73,110,102,111>>]},<<32,108,105,115,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,108,111,110,103,95,115,99,104,101,100,117,108,101,44,32,84,105,109,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,114,117,110,115,32,117,110,105,110,116,101,114,114,117,112,116,101,100,32,102,111,114,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<84,105,109,101>>]},<<32,119,97,108,108,32,99,108,111,99,107,32,109,105,108,108,105,115,101,99,111,110,100,115,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,80,105,100,79,114,80,111,114,116,44,32,108,111,110,103,95,115,99,104,101,100,117,108,101,44,32,73,110,102,111,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,116,104,97,116,32,119,97,115,32,114,117,110,110,105,110,103,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,101,108,101,109,101,110,116,32,116,117,112,108,101,115,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,101,118,101,110,116,46>>]},{p,[],[<<73,102,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<44,32,116,104,101,32,116,117,112,108,101,115,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,77,105,108,108,105,115,125>>]},<<44,32>>,{code,[],[<<123,105,110,44,32,76,111,99,97,116,105,111,110,125>>]},<<44,32,97,110,100,32>>,{code,[],[<<123,111,117,116,44,32,76,111,99,97,116,105,111,110,125>>]},<<32,97,114,101,32,112,114,101,115,101,110,116,44,32,119,104,101,114,101,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,101,105,116,104,101,114,32,97,110,32,77,70,65,32,40>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<41,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,32,119,104,101,114,101,32,116,104,101,32,112,114,111,99,101,115,115,32,119,97,115,32,115,99,104,101,100,117,108,101,100,32,105,110,47,111,117,116,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<73,102,32,97,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<44,32,116,104,101,32,116,117,112,108,101,115,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,77,105,108,108,105,115,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,112,111,114,116,95,111,112,44,79,112,125>>]},<<32,97,114,101,32,112,114,101,115,101,110,116,46,32>>,{code,[],[<<79,112>>]},<<32,105,115,32,111,110,101,32,111,102,32>>,{code,[],[<<112,114,111,99,95,115,105,103>>]},<<44,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<44,32>>,{code,[],[<<105,110,112,117,116>>]},<<44,32>>,{code,[],[<<111,117,116,112,117,116>>]},<<44,32>>,{code,[],[<<101,118,101,110,116>>]},<<44,32,111,114,32>>,{code,[],[<<100,105,115,116,95,99,109,100>>]},<<44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,119,104,105,99,104,32,100,114,105,118,101,114,32,99,97,108,108,98,97,99,107,32,119,97,115,32,101,120,101,99,117,116,105,110,103,46>>]},{p,[],[{code,[],[<<112,114,111,99,95,115,105,103>>]},<<32,105,115,32,97,110,32,105,110,116,101,114,110,97,108,32,111,112,101,114,97,116,105,111,110,32,97,110,100,32,105,115,32,110,101,118,101,114,32,116,111,32,97,112,112,101,97,114,44,32,119,104,105,108,101,32,116,104,101,32,111,116,104,101,114,115,32,114,101,112,114,101,115,101,110,116,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,100,114,105,118,101,114,32,99,97,108,108,98,97,99,107,115,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<44,32>>,{code,[],[<<114,101,97,100,121,95,105,110,112,117,116>>]},<<44,32>>,{code,[],[<<114,101,97,100,121,95,111,117,116,112,117,116>>]},<<44,32>>,{code,[],[<<101,118,101,110,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<111,117,116,112,117,116,118>>]},<<32,40,119,104,101,110,32,116,104,101,32,112,111,114,116,32,105,115,32,117,115,101,100,32,98,121,32,100,105,115,116,114,105,98,117,116,105,111,110,41,46,32,86,97,108,117,101,32>>,{code,[],[<<77,105,108,108,105,115>>]},<<32,105,110,32,116,117,112,108,101,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,105,110,102,111,114,109,115,32,97,98,111,117,116,32,116,104,101,32,117,110,105,110,116,101,114,114,117,112,116,101,100,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,44,32,119,104,105,99,104,32,97,108,119,97,121,115,32,105,115,32,101,113,117,97,108,32,116,111,32,111,114,32,104,105,103,104,101,114,32,116,104,97,110,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,115,117,112,112,108,105,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,116,114,97,99,101,46,32,78,101,119,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,116,111,32,116,104,101,32>>,{code,[],[<<73,110,102,111>>]},<<32,108,105,115,116,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,110,32,116,104,101,32,108,105,115,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]},{p,[],[<<84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,100,101,116,101,99,116,32,112,114,111,98,108,101,109,115,32,119,105,116,104,32,78,73,70,115,32,111,114,32,100,114,105,118,101,114,115,32,116,104,97,116,32,116,97,107,101,32,116,111,111,32,108,111,110,103,32,116,111,32,101,120,101,99,117,116,101,46,32,49,32,109,115,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,103,111,111,100,32,109,97,120,105,109,117,109,32,116,105,109,101,32,102,111,114,32,97,32,100,114,105,118,101,114,32,99,97,108,108,98,97,99,107,32,111,114,32,97,32,78,73,70,46,32,72,111,119,101,118,101,114,44,32,97,32,116,105,109,101,45,115,104,97,114,105,110,103,32,115,121,115,116,101,109,32,105,115,32,117,115,117,97,108,108,121,32,116,111,32,99,111,110,115,105,100,101,114,32,101,118,101,114,121,116,104,105,110,103,32,60,32,49,48,48,32,109,115,32,97,115,32,34,112,111,115,115,105,98,108,101,34,32,97,110,100,32,102,97,105,114,108,121,32,34,110,111,114,109,97,108,34,46,32,72,111,119,101,118,101,114,44,32,108,111,110,103,101,114,32,115,99,104,101,100,117,108,101,32,116,105,109,101,115,32,99,97,110,32,105,110,100,105,99,97,116,101,32,115,119,97,112,112,105,110,103,32,111,114,32,97,32,109,105,115,98,101,104,97,118,105,110,103,32,78,73,70,47,100,114,105,118,101,114,46,32,77,105,115,98,101,104,97,118,105,110,103,32,78,73,70,115,32,97,110,100,32,100,114,105,118,101,114,115,32,99,97,110,32,99,97,117,115,101,32,98,97,100,32,114,101,115,111,117,114,99,101,32,117,116,105,108,105,122,97,116,105,111,110,32,97,110,100,32,98,97,100,32,111,118,101,114,97,108,108,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,46>>]}]},{dt,[],[{code,[],[<<123,108,97,114,103,101,95,104,101,97,112,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,114,101,115,117,108,116,115,32,105,110,32,116,104,101,32,97,108,108,111,99,97,116,101,100,32,115,105,122,101,32,111,102,32,97,32,104,101,97,112,32,98,101,105,110,103,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<83,105,122,101>>]},<<32,119,111,114,100,115,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,71,99,80,105,100,44,32,108,97,114,103,101,95,104,101,97,112,44,32,73,110,102,111,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<71,99,80,105,100>>]},<<32,97,110,100,32>>,{code,[],[<<73,110,102,111>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,102,111,114,32>>,{code,[],[<<108,111,110,103,95,103,99>>]},<<32,101,97,114,108,105,101,114,44,32,101,120,99,101,112,116,32,116,104,97,116,32,116,104,101,32,116,117,112,108,101,32,116,97,103,103,101,100,32,119,105,116,104,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,115,105,122,101,115,32,111,102,32,97,108,108,32,109,101,109,111,114,121,32,98,108,111,99,107,115,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,97,108,108,32,104,101,97,112,32,103,101,110,101,114,97,116,105,111,110,115,32,97,102,116,101,114,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,101,113,117,97,108,32,116,111,32,111,114,32,104,105,103,104,101,114,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<46>>]},{p,[],[<<87,104,101,110,32,97,32,112,114,111,99,101,115,115,32,105,115,32,107,105,108,108,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32,105,116,32,105,115,32,107,105,108,108,101,100,32,98,101,102,111,114,101,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,99,111,109,112,108,101,116,101,32,97,110,100,32,116,104,117,115,32,110,111,32,108,97,114,103,101,32,104,101,97,112,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,46>>]}]},{dt,[],[{code,[],[<<98,117,115,121,95,112,111,114,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,103,101,116,115,32,115,117,115,112,101,110,100,101,100,32,98,101,99,97,117,115,101,32,105,116,32,115,101,110,100,115,32,116,111,32,97,32,98,117,115,121,32,112,111,114,116,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,83,117,115,80,105,100,44,32,98,117,115,121,95,112,111,114,116,44,32,80,111,114,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<83,117,115,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,105,100,32,116,104,97,116,32,103,111,116,32,115,117,115,112,101,110,100,101,100,32,119,104,101,110,32,115,101,110,100,105,110,103,32,116,111,32>>,{code,[],[<<80,111,114,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<98,117,115,121,95,100,105,115,116,95,112,111,114,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,103,101,116,115,32,115,117,115,112,101,110,100,101,100,32,98,101,99,97,117,115,101,32,105,116,32,115,101,110,100,115,32,116,111,32,97,32,112,114,111,99,101,115,115,32,111,110,32,97,32,114,101,109,111,116,101,32,110,111,100,101,32,119,104,111,115,101,32,105,110,116,101,114,45,110,111,100,101,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,97,115,32,104,97,110,100,108,101,100,32,98,121,32,97,32,98,117,115,121,32,112,111,114,116,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,83,117,115,80,105,100,44,32,98,117,115,121,95,100,105,115,116,95,112,111,114,116,44,32,80,111,114,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<83,117,115,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,105,100,32,116,104,97,116,32,103,111,116,32,115,117,115,112,101,110,100,101,100,32,119,104,101,110,32,115,101,110,100,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,32,105,110,116,101,114,45,110,111,100,101,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,112,111,114,116,32>>,{code,[],[<<80,111,114,116>>]},<<46>>]}]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,115,101,116,116,105,110,103,115,32,106,117,115,116,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>]}]},<<46>>]},{p,[],[<<84,104,101,32,97,114,103,117,109,101,110,116,115,32,116,111,32>>,{code,[],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>]},<<32,115,112,101,99,105,102,105,101,115,32,104,111,119,32,97,108,108,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,105,110,103,32,111,110,32,116,104,101,32,110,111,100,101,32,115,104,111,117,108,100,32,98,101,32,100,111,110,101,44,32,110,111,116,32,104,111,119,32,105,116,32,115,104,111,117,108,100,32,98,101,32,99,104,97,110,103,101,100,46,32,84,104,105,115,32,109,101,97,110,115,32,111,110,108,121,32,111,110,101,32,112,114,111,99,101,115,115,32,97,116,32,97,32,116,105,109,101,32,40>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<41,32,99,97,110,32,98,101,32,116,104,101,32,114,101,99,101,105,118,101,114,32,111,102,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,115,46,32,65,108,115,111,44,32,116,104,101,32,119,97,121,32,116,111,32,99,108,101,97,114,32,97,32,115,112,101,99,105,102,105,99,32,109,111,110,105,116,111,114,32,111,112,116,105,111,110,32,105,115,32,116,111,32,110,111,116,32,105,110,99,108,117,100,101,32,105,116,32,105,110,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<79,112,116,105,111,110,115>>]},<<46,32,65,108,108,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,105,110,103,32,119,105,108,108,44,32,104,111,119,101,118,101,114,44,32,98,101,32,99,108,101,97,114,101,100,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,116,101,114,109,105,110,97,116,101,115,46>>]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,110,111,32,115,112,101,99,105,97,108,32,111,112,116,105,111,110,32,118,97,108,117,101,115,32,40,108,105,107,101,32,122,101,114,111,41,32,116,111,32,99,108,101,97,114,32,97,110,32,111,112,116,105,111,110,46,32,83,111,109,101,32,111,102,32,116,104,101,32,111,112,116,105,111,110,115,32,104,97,118,101,32,97,32,117,110,115,112,101,99,105,102,105,101,100,32,109,105,110,105,109,117,109,32,118,97,108,117,101,46,32,76,111,119,101,114,32,118,97,108,117,101,115,32,119,105,108,108,32,98,101,32,97,100,106,117,115,116,101,100,32,116,111,32,116,104,101,32,109,105,110,105,109,117,109,32,118,97,108,117,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,105,115,32,99,117,114,114,101,110,116,108,121,32,110,111,116,32,112,111,115,115,105,98,108,101,32,116,111,32,109,111,110,105,116,111,114,32,97,108,108,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,32,119,105,116,104,32>>,{code,[],[<<123,108,111,110,103,95,103,99,44,32,48,125>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,97,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,103,101,116,115,32,115,111,32,108,97,114,103,101,32,116,104,97,116,32,105,116,32,105,116,115,101,108,102,32,115,116,97,114,116,115,32,116,111,32,99,97,117,115,101,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,115,32,119,104,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,110,103,44,32,116,104,101,32,109,101,115,115,97,103,101,115,32,101,110,108,97,114,103,101,32,116,104,101,32,112,114,111,99,101,115,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,110,100,32,112,114,111,98,97,98,108,121,32,109,97,107,101,32,116,104,101,32,112,114,111,98,108,101,109,32,119,111,114,115,101,46>>]},{p,[],[<<75,101,101,112,32,116,104,101,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,110,101,97,116,32,97,110,100,32,100,111,32,110,111,116,32,115,101,116,32,116,104,101,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,108,105,109,105,116,115,32,116,111,111,32,116,105,103,104,116,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,52,53,54>>,signature => [{attribute,1974,spec,{{erlang,system_monitor,2},[{type,1974,bounded_fun,[{type,1974,'fun',[{type,1974,product,[{var,1974,'MonitorPid'},{var,1974,'Options'}]},{var,1974,'MonSettings'}]},[{type,1975,constraint,[{atom,1975,is_subtype},[{var,1975,'MonitorPid'},{type,1975,pid,[]}]]},{type,1976,constraint,[{atom,1976,is_subtype},[{var,1976,'Options'},{type,1976,list,[{user_type,1976,system_monitor_option,[]}]}]]},{type,1977,constraint,[{atom,1977,is_subtype},[{var,1977,'MonSettings'},{type,1977,union,[{atom,1977,undefined},{type,1977,tuple,[{var,1977,'OldMonitorPid'},{var,1977,'OldOptions'}]}]}]]},{type,1978,constraint,[{atom,1978,is_subtype},[{var,1978,'OldMonitorPid'},{type,1978,pid,[]}]]},{type,1979,constraint,[{atom,1979,is_subtype},[{var,1979,'OldOptions'},{type,1979,list,[{user_type,1979,system_monitor_option,[]}]}]]}]]}]}}]}},{{function,system_profile,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1984}],[<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,112,114,111,102,105,108,105,110,103,32,115,101,116,116,105,110,103,115,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>]}]},<<32,97,115,32>>,{code,[],[<<123,80,114,111,102,105,108,101,114,80,105,100,44,32,79,112,116,105,111,110,115,125>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,114,101,32,97,114,101,32,110,111,32,115,101,116,116,105,110,103,115,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,111,110,101,32,116,104,97,116,32,119,97,115,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,54,48,48>>,signature => [{attribute,1984,spec,{{erlang,system_profile,0},[{type,1984,bounded_fun,[{type,1984,'fun',[{type,1984,product,[]},{var,1984,'ProfilerSettings'}]},[{type,1985,constraint,[{atom,1985,is_subtype},[{var,1985,'ProfilerSettings'},{type,1985,union,[{atom,1985,undefined},{type,1985,tuple,[{var,1985,'ProfilerPid'},{var,1985,'Options'}]}]}]]},{type,1986,constraint,[{atom,1986,is_subtype},[{var,1986,'ProfilerPid'},{type,1986,union,[{type,1986,pid,[]},{type,1986,port,[]}]}]]},{type,1987,constraint,[{atom,1987,is_subtype},[{var,1987,'Options'},{type,1987,list,[{user_type,1987,system_profile_option,[]}]}]]}]]}]}}]}},{{function,system_profile,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1992}],[<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<83,101,116,115,32,115,121,115,116,101,109,32,112,114,111,102,105,108,101,114,32,111,112,116,105,111,110,115,46,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,114,32,112,111,114,116,32,114,101,99,101,105,118,105,110,103,32,112,114,111,102,105,108,105,110,103,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,114,101,99,101,105,118,101,114,32,105,115,32,101,120,99,108,117,100,101,100,32,102,114,111,109,32,97,108,108,32,112,114,111,102,105,108,105,110,103,46,32,84,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,108,105,115,116,32,111,102,32,112,114,111,102,105,108,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,99,108,117,115,105,118,101>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,115,121,110,99,104,114,111,110,111,117,115,32,99,97,108,108,32,116,111,32,97,32,112,111,114,116,32,102,114,111,109,32,97,32,112,114,111,99,101,115,115,32,105,115,32,100,111,110,101,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,110,111,116,32,114,117,110,110,97,98,108,101,32,100,117,114,105,110,103,32,116,104,101,32,99,97,108,108,32,114,117,110,116,105,109,101,32,116,111,32,116,104,101,32,112,111,114,116,46,32,84,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,105,102,105,101,100,32,97,115,32>>,{code,[],[<<105,110,97,99,116,105,118,101>>]},<<44,32,97,110,100,32,108,97,116,101,114,32>>,{code,[],[<<97,99,116,105,118,101>>]},<<32,119,104,101,110,32,116,104,101,32,112,111,114,116,32,99,97,108,108,98,97,99,107,32,114,101,116,117,114,110,115,46>>]}]},{dt,[],[{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,115,116,97,109,112,115,32,105,110,32,112,114,111,102,105,108,101,32,109,101,115,115,97,103,101,115,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,97,98,108,101,95,112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,105,115,32,112,117,116,32,105,110,116,111,32,111,114,32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,104,101,32,114,117,110,32,113,117,101,117,101,44,32,97,32,109,101,115,115,97,103,101,44,32>>,{code,[],[<<123,112,114,111,102,105,108,101,44,32,80,105,100,44,32,83,116,97,116,101,44,32,77,102,97,44,32,84,115,125>>]},<<44,32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<46,32,82,117,110,110,105,110,103,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,97,114,101,32,114,101,105,110,115,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32,114,117,110,32,113,117,101,117,101,32,97,102,116,101,114,32,104,97,118,105,110,103,32,98,101,101,110,32,112,114,101,45,101,109,112,116,101,100,32,100,111,32,110,111,116,32,116,114,105,103,103,101,114,32,116,104,105,115,32,109,101,115,115,97,103,101,46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,97,98,108,101,95,112,111,114,116,115>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,111,114,116,32,105,115,32,112,117,116,32,105,110,116,111,32,111,114,32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,104,101,32,114,117,110,32,113,117,101,117,101,44,32,97,32,109,101,115,115,97,103,101,44,32>>,{code,[],[<<123,112,114,111,102,105,108,101,44,32,80,111,114,116,44,32,83,116,97,116,101,44,32,48,44,32,84,115,125>>]},<<44,32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,115,99,104,101,100,117,108,101,114,32,105,115,32,112,117,116,32,116,111,32,115,108,101,101,112,32,111,114,32,97,119,111,107,101,110,44,32,97,32,109,101,115,115,97,103,101,44,32>>,{code,[],[<<123,112,114,111,102,105,108,101,44,32,115,99,104,101,100,117,108,101,114,44,32,73,100,44,32,83,116,97,116,101,44,32,78,111,83,99,104,101,100,115,44,32,84,115,125>>]},<<44,32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,115,116,97,109,112,115,32,105,110,32,112,114,111,102,105,108,101,32,109,101,115,115,97,103,101,115,32,99,111,110,115,105,115,116,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,105,110,116,101,103,101,114,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{code,[],[<<123,101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41,44,32,101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,115,116,97,109,112,115,32,105,110,32,112,114,111,102,105,108,101,32,109,101,115,115,97,103,101,115,32,105,110,99,108,117,100,101,32,97,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,116,104,97,116,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,40,41>>]},<<46,32,84,104,105,115,32,105,115,32,97,108,115,111,32,116,104,101,32,100,101,102,97,117,108,116,32,105,102,32,110,111,32,116,105,109,101,32,115,116,97,109,112,32,102,108,97,103,32,105,115,32,115,112,101,99,105,102,105,101,100,46,32,73,102,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<32,104,97,115,32,98,101,101,110,32,101,110,97,98,108,101,100,32,116,104,114,111,117,103,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<44,32,116,104,105,115,32,97,108,115,111,32,101,102,102,101,99,116,115,32,116,104,101,32,116,105,109,101,32,115,116,97,109,112,32,112,114,111,100,117,99,101,100,32,105,110,32,112,114,111,102,105,108,105,110,103,32,109,101,115,115,97,103,101,115,32,119,104,101,110,32,102,108,97,103,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,101,110,97,98,108,101,100,46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,112,114,111,102,105,108,101>>]},<<32,98,101,104,97,118,105,111,114,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,54,49,53>>,signature => [{attribute,1992,spec,{{erlang,system_profile,2},[{type,1992,bounded_fun,[{type,1992,'fun',[{type,1992,product,[{var,1992,'ProfilerPid'},{var,1992,'Options'}]},{var,1992,'ProfilerSettings'}]},[{type,1993,constraint,[{atom,1993,is_subtype},[{var,1993,'ProfilerPid'},{type,1993,union,[{type,1993,pid,[]},{type,1993,port,[]},{atom,1993,undefined}]}]]},{type,1994,constraint,[{atom,1994,is_subtype},[{var,1994,'Options'},{type,1994,list,[{user_type,1994,system_profile_option,[]}]}]]},{type,1995,constraint,[{atom,1995,is_subtype},[{var,1995,'ProfilerSettings'},{type,1995,union,[{atom,1995,undefined},{type,1995,tuple,[{type,1995,union,[{type,1995,pid,[]},{type,1995,port,[]}]},{type,1995,list,[{user_type,1995,system_profile_option,[]}]}]}]}]]}]]}]}}]}},{{function,system_time,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1545}],[<<115,121,115,116,101,109,95,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46>>]},{p,[],[<<67,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,116,105,109,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,54,56,57>>,signature => [{attribute,1545,spec,{{erlang,system_time,0},[{type,1545,'fun',[{type,1545,product,[]},{type,1545,integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,system_time,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1550}],[<<115,121,115,116,101,109,95,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,99,111,110,118,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32>>,{code,[],[<<85,110,105,116>>]},<<32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{p,[],[<<67,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,85,110,105,116,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]}]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,41>>]}]},{code,[],[<<44,32,110,97,116,105,118,101,44,32,85,110,105,116,41>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,116,105,109,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,55,49,49>>,signature => [{attribute,1550,spec,{{erlang,system_time,1},[{type,1550,bounded_fun,[{type,1550,'fun',[{type,1550,product,[{var,1550,'Unit'}]},{type,1550,integer,[]}]},[{type,1551,constraint,[{atom,1551,is_subtype},[{var,1551,'Unit'},{user_type,1551,time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,term_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2667}],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,32,116,104,97,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,101,110,99,111,100,105,110,103,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,108,95,101,120,116,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]}]},{p,[],[<<84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,118,97,114,105,111,117,115,32,112,117,114,112,111,115,101,115,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,119,114,105,116,105,110,103,32,97,32,116,101,114,109,32,116,111,32,97,32,102,105,108,101,32,105,110,32,97,110,32,101,102,102,105,99,105,101,110,116,32,119,97,121,44,32,111,114,32,115,101,110,100,105,110,103,32,97,110,32,69,114,108,97,110,103,32,116,101,114,109,32,116,111,32,115,111,109,101,32,116,121,112,101,32,111,102,32,99,111,109,109,117,110,105,99,97,116,105,111,110,115,32,99,104,97,110,110,101,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,100,105,115,116,114,105,98,117,116,101,100,32,69,114,108,97,110,103,46>>]},{pre,[],[{code,[],[<<62,32,66,105,110,32,61,32,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,104,101,108,108,111,41,46,10,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,62,62,10,62,32,104,101,108,108,111,32,61,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,66,105,110,41,46,10,104,101,108,108,111>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,110,111,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32,114,101,116,117,114,110,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,101,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,97,109,101,32,116,101,114,109,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,55,51,51>>,signature => [{attribute,2667,spec,{{term_to_binary,1},[{type,2667,bounded_fun,[{type,2667,'fun',[{type,2667,product,[{var,2667,'Term'}]},{user_type,2667,ext_binary,[]}]},[{type,2668,constraint,[{atom,2668,is_subtype},[{var,2668,'Term'},{type,2668,term,[]}]]}]]}]}}]}},{{function,term_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,32,116,104,97,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,101,110,99,111,100,105,110,103,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,105,115,32,112,114,111,118,105,100,101,100,44,32,116,104,101,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,32,105,115,32,99,111,109,112,114,101,115,115,101,100,46,32,84,104,101,32,99,111,109,112,114,101,115,115,101,100,32,102,111,114,109,97,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,99,111,103,110,105,122,101,100,32,98,121,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]},<<32,97,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,55,66,46>>]},{p,[],[<<65,32,99,111,109,112,114,101,115,115,105,111,110,32,108,101,118,101,108,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,103,105,118,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,99,111,109,112,114,101,115,115,101,100,44,32,76,101,118,101,108,125>>]},<<46,32>>,{code,[],[<<76,101,118,101,108>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,119,105,116,104,32,114,97,110,103,101,32,48,46,46,57,44,32,119,104,101,114,101,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<48>>]},<<32,45,32,78,111,32,99,111,109,112,114,101,115,115,105,111,110,32,105,115,32,100,111,110,101,32,40,105,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,103,105,118,105,110,103,32,110,111,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,111,112,116,105,111,110,41,46>>]}]},{li,[],[{p,[],[{code,[],[<<49>>]},<<32,45,32,84,97,107,101,115,32,108,101,97,115,116,32,116,105,109,101,32,98,117,116,32,109,97,121,32,110,111,116,32,99,111,109,112,114,101,115,115,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32,104,105,103,104,101,114,32,108,101,118,101,108,115,46>>]}]},{li,[],[{p,[],[{code,[],[<<54>>]},<<32,45,32,68,101,102,97,117,108,116,32,108,101,118,101,108,32,119,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,105,115,32,112,114,111,118,105,100,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<57>>]},<<32,45,32,84,97,107,101,115,32,109,111,115,116,32,116,105,109,101,32,97,110,100,32,116,114,105,101,115,32,116,111,32,112,114,111,100,117,99,101,32,97,32,115,109,97,108,108,101,114,32,114,101,115,117,108,116,46,32,78,111,116,105,99,101,32,34,116,114,105,101,115,34,32,105,110,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,115,101,110,116,101,110,99,101,59,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,105,110,112,117,116,32,116,101,114,109,44,32,108,101,118,101,108,32,57,32,99,111,109,112,114,101,115,115,105,111,110,32,101,105,116,104,101,114,32,100,111,101,115,32,111,114,32,100,111,101,115,32,110,111,116,32,112,114,111,100,117,99,101,32,97,32,115,109,97,108,108,101,114,32,114,101,115,117,108,116,32,116,104,97,110,32,108,101,118,101,108,32,49,32,99,111,109,112,114,101,115,115,105,111,110,46>>]}]}]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<123,109,105,110,111,114,95,118,101,114,115,105,111,110,44,32,86,101,114,115,105,111,110,125>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,99,111,110,116,114,111,108,32,115,111,109,101,32,101,110,99,111,100,105,110,103,32,100,101,116,97,105,108,115,46,32,84,104,105,115,32,111,112,116,105,111,110,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,45,52,46,32,84,104,101,32,118,97,108,105,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<86,101,114,115,105,111,110>>]},<<32,97,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<48>>]}]},{dd,[],[{p,[],[<<70,108,111,97,116,115,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,97,32,116,101,120,116,117,97,108,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,117,115,101,102,117,108,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,114,101,108,101,97,115,101,115,32,98,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,45,52,32,99,97,110,32,100,101,99,111,100,101,32,114,101,115,117,108,116,105,110,103,32,98,105,110,97,114,121,46>>]},{p,[],[<<84,104,105,115,32,118,101,114,115,105,111,110,32,101,110,99,111,100,101,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,108,97,116,105,110,49,32,115,116,114,105,110,103,32,117,115,105,110,103,32,108,97,116,105,110,49,32,101,110,99,111,100,105,110,103,32,119,104,105,108,101,32,111,110,108,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,108,97,116,105,110,49,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,117,116,102,56,46>>]}]},{dt,[],[{code,[],[<<49>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,105,115,32,97,115,32,111,102,32,69,114,108,97,110,103,47,79,84,80,32,49,55,46,48,32,116,104,101,32,100,101,102,97,117,108,116,46,32,73,116,32,102,111,114,99,101,115,32,97,110,121,32,102,108,111,97,116,115,32,105,110,32,116,104,101,32,116,101,114,109,32,116,111,32,98,101,32,101,110,99,111,100,101,100,32,105,110,32,97,32,109,111,114,101,32,115,112,97,99,101,45,101,102,102,105,99,105,101,110,116,32,97,110,100,32,101,120,97,99,116,32,119,97,121,32,40,110,97,109,101,108,121,32,105,110,32,116,104,101,32,54,52,45,98,105,116,32,73,69,69,69,32,102,111,114,109,97,116,44,32,114,97,116,104,101,114,32,116,104,97,110,32,99,111,110,118,101,114,116,101,100,32,116,111,32,97,32,116,101,120,116,117,97,108,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,41,46,32,65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,45,52,44,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]},<<32,99,97,110,32,100,101,99,111,100,101,32,116,104,105,115,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46>>]},{p,[],[<<84,104,105,115,32,118,101,114,115,105,111,110,32,101,110,99,111,100,101,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,108,97,116,105,110,49,32,115,116,114,105,110,103,32,117,115,105,110,103,32,108,97,116,105,110,49,32,101,110,99,111,100,105,110,103,32,119,104,105,108,101,32,111,110,108,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,108,97,116,105,110,49,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,117,116,102,56,46>>]}]},{dt,[],[{code,[],[<<50>>]}]},{dd,[],[{p,[],[<<68,114,111,112,115,32,117,115,97,103,101,32,111,102,32,116,104,101,32,108,97,116,105,110,49,32,97,116,111,109,32,101,110,99,111,100,105,110,103,32,97,110,100,32,117,110,99,111,110,100,105,116,105,111,110,97,108,108,121,32,117,115,101,32,117,116,102,56,32,101,110,99,111,100,105,110,103,32,102,111,114,32,97,108,108,32,97,116,111,109,115,46,32,84,104,105,115,32,119,105,108,108,32,98,101,32,99,104,97,110,103,101,100,32,116,111,32,116,104,101,32,100,101,102,97,117,108,116,32,105,110,32,97,32,102,117,116,117,114,101,32,109,97,106,111,114,32,114,101,108,101,97,115,101,32,111,102,32,69,114,108,97,110,103,47,79,84,80,46,32,69,114,108,97,110,103,47,79,84,80,32,115,121,115,116,101,109,115,32,97,115,32,111,102,32,82,49,54,66,32,99,97,110,32,100,101,99,111,100,101,32,116,104,105,115,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46>>]}]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,55,54,49>>,signature => [{attribute,2672,spec,{{term_to_binary,2},[{type,2672,bounded_fun,[{type,2672,'fun',[{type,2672,product,[{var,2672,'Term'},{var,2672,'Options'}]},{user_type,2672,ext_binary,[]}]},[{type,2673,constraint,[{atom,2673,is_subtype},[{var,2673,'Term'},{type,2673,term,[]}]]},{type,2674,constraint,[{atom,2674,is_subtype},[{var,2674,'Options'},{type,2674,list,[{type,2674,union,[{atom,2674,compressed},{type,2675,tuple,[{atom,2675,compressed},{ann_type,2675,[{var,2675,'Level'},{type,2675,range,[{integer,2675,0},{integer,2675,9}]}]}]},{type,2676,tuple,[{atom,2676,minor_version},{ann_type,2676,[{var,2676,'Version'},{type,2676,range,[{integer,2676,0},{integer,2676,2}]}]}]}]}]}]]}]]}]}}]}},{{function,term_to_iovec,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2680}],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<101,120,116,95,105,111,118,101,99,40,41>>]}]},<<46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,112,114,111,100,117,99,101,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,105,110,103,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<44,32,98,117,116,32,119,105,116,104,32,97,110,111,116,104,101,114,32,114,101,116,117,114,110,32,116,121,112,101,46,32,84,104,101,32,99,97,108,108,32>>,{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,116,101,114,109,95,116,111,95,105,111,118,101,99,40,84,101,114,109,41,41>>]},<<32,119,105,108,108,32,112,114,111,100,117,99,101,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,41>>]},<<46>>]},{p,[],[{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,105,115,32,97,32,112,117,114,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,41>>]},<<32,112,114,111,118,105,100,101,46,32>>,{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,99,97,110,32,102,111,114,32,101,120,97,109,112,108,101,32,114,101,102,101,114,32,100,105,114,101,99,116,108,121,32,116,111,32,111,102,102,32,104,101,97,112,32,98,105,110,97,114,105,101,115,32,105,110,115,116,101,97,100,32,111,102,32,99,111,112,121,105,110,103,32,116,104,101,32,98,105,110,97,114,121,32,100,97,116,97,32,105,110,116,111,32,116,104,101,32,114,101,115,117,108,116,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,56,50,54>>,signature => [{attribute,2680,spec,{{term_to_iovec,1},[{type,2680,bounded_fun,[{type,2680,'fun',[{type,2680,product,[{var,2680,'Term'}]},{user_type,2680,ext_iovec,[]}]},[{type,2681,constraint,[{atom,2681,is_subtype},[{var,2681,'Term'},{type,2681,term,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,term_to_iovec,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2685}],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<101,120,116,95,105,111,118,101,99,40,41>>]}]},<<46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,112,114,111,100,117,99,101,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,105,110,103,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<44,32,98,117,116,32,119,105,116,104,32,97,110,111,116,104,101,114,32,114,101,116,117,114,110,32,116,121,112,101,46,32,84,104,101,32,99,97,108,108,32>>,{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,116,101,114,109,95,116,111,95,105,111,118,101,99,40,84,101,114,109,44,32,79,112,116,115,41,41>>]},<<32,119,105,108,108,32,112,114,111,100,117,99,101,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,44,32,79,112,116,115,41>>]},<<46>>]},{p,[],[<<67,117,114,114,101,110,116,108,121,32,114,101,99,111,103,110,105,115,101,100,32,111,112,116,105,111,110,115,32,97,114,101,32,97,108,108,32,111,112,116,105,111,110,115,32,114,101,99,111,103,110,105,115,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<46>>]},{p,[],[{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,105,115,32,97,32,112,117,114,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,41>>]},<<32,112,114,111,118,105,100,101,46,32>>,{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,99,97,110,32,102,111,114,32,101,120,97,109,112,108,101,32,114,101,102,101,114,32,100,105,114,101,99,116,108,121,32,116,111,32,111,102,102,32,104,101,97,112,32,98,105,110,97,114,105,101,115,32,105,110,115,116,101,97,100,32,111,102,32,99,111,112,121,105,110,103,32,116,104,101,32,98,105,110,97,114,121,32,100,97,116,97,32,105,110,116,111,32,116,104,101,32,114,101,115,117,108,116,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,56,53,49>>,signature => [{attribute,2685,spec,{{term_to_iovec,2},[{type,2685,bounded_fun,[{type,2685,'fun',[{type,2685,product,[{var,2685,'Term'},{var,2685,'Options'}]},{user_type,2685,ext_iovec,[]}]},[{type,2686,constraint,[{atom,2686,is_subtype},[{var,2686,'Term'},{type,2686,term,[]}]]},{type,2687,constraint,[{atom,2687,is_subtype},[{var,2687,'Options'},{type,2687,list,[{type,2687,union,[{atom,2687,compressed},{type,2688,tuple,[{atom,2688,compressed},{ann_type,2688,[{var,2688,'Level'},{type,2688,range,[{integer,2688,0},{integer,2688,9}]}]}]},{type,2689,tuple,[{atom,2689,minor_version},{ann_type,2689,[{var,2689,'Version'},{type,2689,range,[{integer,2689,0},{integer,2689,2}]}]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,throw,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2001}],[<<116,104,114,111,119,47,49>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<116,104,114,111,119>>]},<<46,32,73,110,116,101,110,100,101,100,32,116,111,32,98,101,32,117,115,101,100,32,116,111,32,100,111,32,110,111,110,45,108,111,99,97,108,32,114,101,116,117,114,110,115,32,102,114,111,109,32,102,117,110,99,116,105,111,110,115,46>>]},{p,[],[<<73,102,32,101,118,97,108,117,97,116,101,100,32,119,105,116,104,105,110,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,99,97,116,99,104>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,97,116,99,104,32,101,120,112,114,101,115,115,105,111,110>>]},<<44,32,116,104,101,32,99,97,116,99,104,32,101,120,112,114,101,115,115,105,111,110,32,114,101,116,117,114,110,115,32,118,97,108,117,101,32>>,{code,[],[<<65,110,121>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,99,97,116,99,104,32,116,104,114,111,119,40,123,104,101,108,108,111,44,32,116,104,101,114,101,125,41,46,10,32,32,32,32,32,32,32,32,123,104,101,108,108,111,44,116,104,101,114,101,125>>]}]},{p,[],[<<73,102,32,101,118,97,108,117,97,116,101,100,32,119,105,116,104,105,110,32,97,32>>,{code,[],[<<116,114,121>>]},<<45,98,108,111,99,107,32,111,102,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,116,114,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,114,121,32,101,120,112,114,101,115,115,105,111,110>>]},<<44,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<65,110,121>>]},<<32,99,97,110,32,98,101,32,99,97,117,103,104,116,32,119,105,116,104,105,110,32,116,104,101,32,99,97,116,99,104,32,98,108,111,99,107,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<116,114,121,10,32,32,32,32,116,104,114,111,119,40,123,109,121,95,101,120,99,101,112,116,105,111,110,44,32,34,83,111,109,101,116,104,105,110,103,32,104,97,112,112,101,110,101,100,34,125,41,10,99,97,116,99,104,10,32,32,32,32,116,104,114,111,119,58,123,109,121,95,101,120,99,101,112,116,105,111,110,44,32,68,101,115,99,125,32,45,62,10,32,32,32,32,32,32,32,32,105,111,58,102,111,114,109,97,116,40,115,116,97,110,100,97,114,100,95,101,114,114,111,114,44,32,34,69,114,114,111,114,58,32,126,115,126,110,34,44,32,91,68,101,115,99,93,41,10,101,110,100>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<110,111,99,97,116,99,104>>]},<<32,105,102,32,110,111,116,32,99,97,117,103,104,116,32,98,121,32,97,110,32,101,120,99,101,112,116,105,111,110,32,104,97,110,100,108,101,114,46>>]},{p,[],[<<83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,56,55,57>>,signature => [{attribute,2001,spec,{{throw,1},[{type,2001,bounded_fun,[{type,2001,'fun',[{type,2001,product,[{var,2001,'Any'}]},{type,2001,no_return,[]}]},[{type,2002,constraint,[{atom,2002,is_subtype},[{var,2002,'Any'},{type,2002,term,[]}]]}]]}]}}]}},{{function,time,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2007}],[<<116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,32,97,115,32>>,{code,[],[<<123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125>>]},<<46>>]},{p,[],[<<84,104,101,32,116,105,109,101,32,122,111,110,101,32,97,110,100,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,99,111,114,114,101,99,116,105,111,110,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,105,109,101,40,41,46,10,123,57,44,52,50,44,52,52,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,57,48,55>>,signature => [{attribute,2007,spec,{{time,0},[{type,2007,bounded_fun,[{type,2007,'fun',[{type,2007,product,[]},{var,2007,'Time'}]},[{type,2008,constraint,[{atom,2008,is_subtype},[{var,2008,'Time'},{remote_type,2008,[{atom,2008,calendar},{atom,2008,time},[]]}]]}]]}]}}]}},{{function,time_offset,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1605}],[<<116,105,109,101,95,111,102,102,115,101,116,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,32,111,102,102,115,101,116,32,98,101,116,119,101,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46,32,67,117,114,114,101,110,116,32,116,105,109,101,32,111,102,102,115,101,116,32,97,100,100,101,100,32,116,111,32,97,110,32,69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,103,105,118,101,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101,46>>]},{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,99,104,97,110,103,101,32,100,117,114,105,110,103,32,111,112,101,114,97,116,105,111,110,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,117,115,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,99,104,97,110,103,101,32,105,110,32,116,105,109,101,32,111,102,102,115,101,116,32,99,97,110,32,98,101,32,111,98,115,101,114,118,101,100,32,97,116,32,115,108,105,103,104,116,108,121,32,100,105,102,102,101,114,101,110,116,32,112,111,105,110,116,115,32,105,110,32,116,105,109,101,32,98,121,32,100,105,102,102,101,114,101,110,116,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,32,119,104,101,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,101,116,101,99,116,115,32,116,104,97,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,104,97,115,32,99,104,97,110,103,101,100,46,32,84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,119,105,108,108,44,32,104,111,119,101,118,101,114,44,32,110,111,116,32,100,101,116,101,99,116,32,116,104,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,119,104,101,110,32,105,116,32,111,99,99,117,114,115,46,32,65,32,116,97,115,107,32,99,104,101,99,107,105,110,103,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,101,120,101,99,117,116,101,32,97,116,32,108,101,97,115,116,32,111,110,99,101,32,97,32,109,105,110,117,116,101,59,32,115,111,44,32,117,110,100,101,114,32,110,111,114,109,97,108,32,111,112,101,114,97,116,105,111,110,32,116,104,105,115,32,105,115,32,116,111,32,98,101,32,100,101,116,101,99,116,101,100,32,119,105,116,104,105,110,32,97,32,109,105,110,117,116,101,44,32,98,117,116,32,100,117,114,105,110,103,32,104,101,97,118,121,32,108,111,97,100,32,105,116,32,99,97,110,32,116,97,107,101,32,108,111,110,103,101,114,32,116,105,109,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,57,50,50>>,signature => [{attribute,1605,spec,{{erlang,time_offset,0},[{type,1605,'fun',[{type,1605,product,[]},{type,1605,integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,time_offset,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1610}],[<<116,105,109,101,95,111,102,102,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,32,111,102,102,115,101,116,32,98,101,116,119,101,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,99,111,110,118,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32>>,{code,[],[<<85,110,105,116>>]},<<32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{p,[],[<<83,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]}]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]}]},{code,[],[<<44,32,110,97,116,105,118,101,44,32,85,110,105,116,41>>]},<<32,104,111,119,101,118,101,114,32,111,112,116,105,109,105,122,101,100,32,102,111,114,32,99,111,109,109,111,110,108,121,32,117,115,101,100,32>>,{code,[],[<<85,110,105,116>>]},<<115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,57,53,52>>,signature => [{attribute,1610,spec,{{erlang,time_offset,1},[{type,1610,bounded_fun,[{type,1610,'fun',[{type,1610,product,[{var,1610,'Unit'}]},{type,1610,integer,[]}]},[{type,1611,constraint,[{atom,1611,is_subtype},[{var,1611,'Unit'},{user_type,1611,time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,timestamp,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1616}],[<<116,105,109,101,115,116,97,109,112,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<116,105,109,101,115,116,97,109,112>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,111,110,32,116,104,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,77,101,103,97,83,101,99,115,44,32,83,101,99,115,44,32,77,105,99,114,111,83,101,99,115,125>>]},<<46,32,84,104,105,115,32,102,111,114,109,97,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,116,105,109,101,115,116,97,109,112,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,116,105,109,101,115,116,97,109,112,47,48>>]}]},<<32,97,110,100,32,116,104,101,32,100,101,112,114,101,99,97,116,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,110,111,119,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,110,111,119,47,48>>]}]},<<32,117,115,101,46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,101,32,101,120,105,115,116,101,110,99,101,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,115,116,97,109,112,40,41>>]},<<32,105,115,32,112,117,114,101,108,121,32,116,111,32,115,105,109,112,108,105,102,121,32,117,115,101,32,102,111,114,32,101,120,105,115,116,105,110,103,32,99,111,100,101,32,116,104,97,116,32,97,115,115,117,109,101,115,32,116,104,105,115,32,116,105,109,101,32,115,116,97,109,112,32,102,111,114,109,97,116,46,32,67,117,114,114,101,110,116,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101,32,99,97,110,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,108,121,32,98,101,32,114,101,116,114,105,101,118,101,100,32,105,110,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,111,102,32,121,111,117,114,32,99,104,111,105,99,101,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,116,105,109,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,47,49>>]}]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,115,116,97,109,112,40,41>>]},<<32,66,73,70,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<116,105,109,101,115,116,97,109,112,40,41,32,45,62,10,32,32,32,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,109,105,99,114,111,115,101,99,111,110,100,41,44,10,32,32,32,32,77,101,103,97,83,101,99,115,32,61,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,100,105,118,32,49,48,48,48,95,48,48,48,95,48,48,48,95,48,48,48,44,10,32,32,32,32,83,101,99,115,32,61,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,100,105,118,32,49,48,48,48,95,48,48,48,32,45,32,77,101,103,97,83,101,99,115,42,49,48,48,48,95,48,48,48,44,10,32,32,32,32,77,105,99,114,111,83,101,99,115,32,61,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,114,101,109,32,49,48,48,48,95,48,48,48,44,10,32,32,32,32,123,77,101,103,97,83,101,99,115,44,32,83,101,99,115,44,32,77,105,99,114,111,83,101,99,115,125,46>>]}]},{p,[],[<<73,116,44,32,104,111,119,101,118,101,114,44,32,117,115,101,115,32,97,32,110,97,116,105,118,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,98,117,105,108,100,32,103,97,114,98,97,103,101,32,111,110,32,116,104,101,32,104,101,97,112,32,97,110,100,32,119,105,116,104,32,115,108,105,103,104,116,108,121,32,98,101,116,116,101,114,32,112,101,114,102,111,114,109,97,110,99,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,116,105,109,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,57,55,51>>,signature => [{attribute,1616,spec,{{erlang,timestamp,0},[{type,1616,bounded_fun,[{type,1616,'fun',[{type,1616,product,[]},{var,1616,'Timestamp'}]},[{type,1617,constraint,[{atom,1617,is_subtype},[{var,1617,'Timestamp'},{user_type,1617,timestamp,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,tl,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2694}],[<<116,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,97,105,108,32,111,102,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,108,105,115,116,32,109,105,110,117,115,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,44,32,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,93,41,46,10,91,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,93>>]}]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,93,41,46,10,91,93>>]}]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,44,32,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,32,124,32,105,109,112,114,111,112,101,114,95,101,110,100,93,41,46,10,91,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,32,124,32,105,109,112,114,111,112,101,114,95,101,110,100,93>>]}]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,32,124,32,105,109,112,114,111,112,101,114,95,101,110,100,93,41,46,10,105,109,112,114,111,112,101,114,95,101,110,100>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,105,115,116>>]},<<32,105,115,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,48,49,50>>,signature => [{attribute,2694,spec,{{tl,1},[{type,2694,bounded_fun,[{type,2694,'fun',[{type,2694,product,[{var,2694,'List'}]},{type,2694,term,[]}]},[{type,2695,constraint,[{atom,2695,is_subtype},[{var,2695,'List'},{type,2695,nonempty_maybe_improper_list,[]}]]}]]}]}}]}},{{function,trace,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2013}],[<<116,114,97,99,101,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<116,114,97,99,101,95,102,108,97,103>>}],[]}]},{p,[],[<<84,117,114,110,115,32,111,110,32,40,105,102,32>>,{code,[],[<<72,111,119,32,61,61,32,116,114,117,101>>]},<<41,32,111,114,32,111,102,102,32,40,105,102,32>>,{code,[],[<<72,111,119,32,61,61,32,102,97,108,115,101>>]},<<41,32,116,104,101,32,116,114,97,99,101,32,102,108,97,103,115,32,105,110,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,114,111,99,101,115,115,101,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<46>>]},{p,[],[{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32,101,105,116,104,101,114,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,102,111,114,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,44,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,97,110,100,32,97,108,108,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,97,108,108,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<112,111,114,116,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,111,114,116,115,32,97,110,100,32,97,108,108,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<101,120,105,115,116,105,110,103>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,46>>]},{dt,[],[{code,[],[<<101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,46>>]},{dt,[],[{code,[],[<<101,120,105,115,116,105,110,103,95,112,111,114,116,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,111,114,116,115,46>>]},{dt,[],[{code,[],[<<110,101,119>>]}]},{dd,[],[<<65,108,108,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<110,101,119,95,112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[<<65,108,108,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<110,101,119,95,112,111,114,116,115>>]}]},{dd,[],[<<65,108,108,32,112,111,114,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]}]},{p,[],[{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,108,97,103,115,32,40,116,104,101,32,34,109,101,115,115,97,103,101,32,116,97,103,115,34,32,114,101,102,101,114,115,32,116,111,32,116,104,101,32,108,105,115,116,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,114,97,99,101,32,109,101,115,115,97,103,101,115>>]}]},<<41,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,97,108,108,32,116,114,97,99,101,32,102,108,97,103,115,32,101,120,99,101,112,116,32>>,{code,[],[<<116,114,97,99,101,114>>]},<<32,97,110,100,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<44,32,119,104,105,99,104,32,97,114,101,32,105,110,32,116,104,101,105,114,32,110,97,116,117,114,101,32,100,105,102,102,101,114,101,110,116,32,116,104,97,110,32,116,104,101,32,111,116,104,101,114,115,46>>]}]},{dt,[],[{code,[],[<<115,101,110,100>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,101,110,100,105,110,103,32,111,102,32,109,101,115,115,97,103,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,110,100>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<39,114,101,99,101,105,118,101,39>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,114,101,99,101,105,118,105,110,103,32,111,102,32,109,101,115,115,97,103,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,99,101,105,118,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<39,114,101,99,101,105,118,101,39>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,99,101,114,116,97,105,110,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,83,112,101,99,105,102,121,32,119,104,105,99,104,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,116,111,32,116,114,97,99,101,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,97,108,108>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,102,114,111,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,102,114,111,109>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<115,105,108,101,110,116>>]}]},{dd,[],[{p,[],[<<85,115,101,100,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,46,32,84,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<114,101,116,117,114,110,95,102,114,111,109>>]},<<44,32,97,110,100,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,105,110,104,105,98,105,116,101,100,32,105,102,32,116,104,105,115,32,102,108,97,103,32,105,115,32,115,101,116,44,32,98,117,116,32,116,104,101,121,32,97,114,101,32,101,120,101,99,117,116,101,100,32,97,115,32,110,111,114,109,97,108,32,105,102,32,116,104,101,114,101,32,97,114,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46>>]},{p,[],[<<83,105,108,101,110,116,32,109,111,100,101,32,105,115,32,105,110,104,105,98,105,116,101,100,32,98,121,32,101,120,101,99,117,116,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,40,95,44,32,102,97,108,115,101,44,32,91,115,105,108,101,110,116,124,95,93,41>>]},<<44,32,111,114,32,98,121,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,101,120,101,99,117,116,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,115,105,108,101,110,116,44,32,102,97,108,115,101,125>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<115,105,108,101,110,116>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,97,99,105,108,105,116,97,116,101,115,32,115,101,116,116,105,110,103,32,117,112,32,97,32,116,114,97,99,101,32,111,110,32,109,97,110,121,32,111,114,32,101,118,101,110,32,97,108,108,32,112,114,111,99,101,115,115,101,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,84,104,101,32,116,114,97,99,101,32,99,97,110,32,116,104,101,110,32,98,101,32,97,99,116,105,118,97,116,101,100,32,97,110,100,32,100,101,97,99,116,105,118,97,116,101,100,32,117,115,105,110,103,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,115,105,108,101,110,116,44,66,111,111,108,125>>]},<<44,32,103,105,118,105,110,103,32,97,32,104,105,103,104,32,100,101,103,114,101,101,32,111,102,32,99,111,110,116,114,111,108,32,111,102,32,119,104,105,99,104,32,102,117,110,99,116,105,111,110,115,32,119,105,116,104,32,119,104,105,99,104,32,97,114,103,117,109,101,110,116,115,32,116,104,97,116,32,116,114,105,103,103,101,114,32,116,104,101,32,116,114,97,99,101,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,97,108,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,102,114,111,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,102,114,111,109>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,116,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,116,111>>]}]},<<46,32,79,114,32,114,97,116,104,101,114,44,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,46>>]}]},{dt,[],[{code,[],[<<114,101,116,117,114,110,95,116,111>>]}]},{dd,[],[{p,[],[<<85,115,101,100,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,46,32,84,114,97,99,101,115,32,116,104,101,32,114,101,116,117,114,110,32,102,114,111,109,32,97,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,32,98,97,99,107,32,116,111,32,105,116,115,32,99,97,108,108,101,114,46,32,79,110,108,121,32,119,111,114,107,115,32,102,111,114,32,102,117,110,99,116,105,111,110,115,32,116,114,97,99,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]},{p,[],[<<84,104,101,32,115,101,109,97,110,116,105,99,115,32,105,115,32,116,104,97,116,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,119,104,101,110,32,97,32,99,97,108,108,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,44,32,116,104,97,116,32,105,115,44,32,119,104,101,110,32,97,32,99,104,97,105,110,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,115,32,101,110,100,115,46,32,79,110,108,121,32,111,110,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,112,101,114,32,99,104,97,105,110,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,115,44,32,115,111,32,116,104,101,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,110,101,115,115,32,102,111,114,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,114,101,32,107,101,112,116,32,119,104,105,108,101,32,116,114,97,99,105,110,103,32,119,105,116,104,32,116,104,105,115,32,102,108,97,103,46,32,85,115,105,110,103,32>>,{code,[],[<<99,97,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,116,114,97,99,101,32,116,111,103,101,116,104,101,114,32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,107,110,111,119,32,101,120,97,99,116,108,121,32,105,110,32,119,104,105,99,104,32,102,117,110,99,116,105,111,110,32,97,32,112,114,111,99,101,115,115,32,101,120,101,99,117,116,101,115,32,97,116,32,97,110,121,32,116,105,109,101,46>>]},{p,[],[<<84,111,32,103,101,116,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,99,111,110,116,97,105,110,105,110,103,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,102,114,111,109,32,102,117,110,99,116,105,111,110,115,44,32,117,115,101,32,116,104,101,32>>,{code,[],[<<123,114,101,116,117,114,110,95,116,114,97,99,101,125>>]},<<32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,99,116,105,111,110,32,105,110,115,116,101,97,100,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,116,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,116,111>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,112,114,111,99,101,115,115,45,114,101,108,97,116,101,100,32,101,118,101,110,116,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,112,97,119,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,112,97,119,110,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,120,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,108,105,110,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,105,110,107>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,108,105,110,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,108,105,110,107>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,108,105,110,107,101,100>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<112,111,114,116,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,112,111,114,116,45,114,101,108,97,116,101,100,32,101,118,101,110,116,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,112,101,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,112,101,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,108,111,115,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,108,111,115,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,108,105,110,107,101,100>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,105,110,103>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<101,120,105,116,105,110,103>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,101,120,105,116,105,110,103,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,101,120,105,116,105,110,103,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,95,101,120,105,116,105,110,103>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,105,110,103,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116,95,101,120,105,116,105,110,103>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,101,100,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116,95,101,120,105,116,101,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,105,110,103,95,112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,112,114,111,99,101,115,115,101,115,32,106,117,115,116,32,108,105,107,101,32>>,{code,[],[<<114,117,110,110,105,110,103>>]},<<46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,111,112,116,105,111,110,32,97,108,115,111,32,105,110,99,108,117,100,101,115,32,115,99,104,101,100,117,108,101,32,101,118,101,110,116,115,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,101,99,117,116,101,115,32,119,105,116,104,105,110,32,116,104,101,32,99,111,110,116,101,120,116,32,111,102,32,97,32,112,111,114,116,32,119,105,116,104,111,117,116,32,98,101,105,110,103,32,115,99,104,101,100,117,108,101,100,32,111,117,116,32,105,116,115,101,108,102,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,105,110,103,95,112,111,114,116,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,112,111,114,116,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,111,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,111,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,32,111,102,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,101,110,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,101,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<73,110,99,108,117,100,101,115,32,97,32,116,105,109,101,32,115,116,97,109,112,32,105,110,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,40,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<65,32,103,108,111,98,97,108,32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,110,111,100,101,32,116,104,97,116,32,109,97,107,101,115,32,97,108,108,32,116,114,97,99,101,32,116,105,109,101,32,115,116,97,109,112,115,32,117,115,105,110,103,32,102,108,97,103,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<32,116,111,32,98,101,32,105,110,32,67,80,85,32,116,105,109,101,44,32,110,111,116,32,119,97,108,108,32,99,108,111,99,107,32,116,105,109,101,46,32,84,104,97,116,32,105,115,44,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,110,111,116,32,98,101,32,117,115,101,100,32,105,102,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<32,111,114,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,101,110,97,98,108,101,100,46,32,79,110,108,121,32,97,108,108,111,119,101,100,32,119,105,116,104,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99,61,61,97,108,108>>]},<<46,32,73,102,32,116,104,101,32,104,111,115,116,32,109,97,99,104,105,110,101,32,79,83,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,104,105,103,104,45,114,101,115,111,108,117,116,105,111,110,32,67,80,85,32,116,105,109,101,32,109,101,97,115,117,114,101,109,101,110,116,115,44,32>>,{code,[],[<<116,114,97,99,101,47,51>>]},<<32,101,120,105,116,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,109,111,115,116,32,79,83,32,100,111,32,110,111,116,32,115,121,110,99,104,114,111,110,105,122,101,32,116,104,105,115,32,118,97,108,117,101,32,97,99,114,111,115,115,32,99,111,114,101,115,44,32,115,111,32,98,101,32,112,114,101,112,97,114,101,100,32,116,104,97,116,32,116,105,109,101,32,99,97,110,32,115,101,101,109,32,116,111,32,103,111,32,98,97,99,107,119,97,114,100,115,32,119,104,101,110,32,117,115,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<73,110,99,108,117,100,101,115,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,116,105,109,101,32,115,116,97,109,112,32,105,110,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41>>]}]},<<46,32,84,104,105,115,32,102,108,97,103,32,111,118,101,114,114,105,100,101,115,32,102,108,97,103,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<73,110,99,108,117,100,101,115,32,97,110,32,116,105,109,101,32,115,116,97,109,112,32,99,111,110,115,105,115,116,105,110,103,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,105,110,116,101,103,101,114,32,105,110,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{code,[],[<<123>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41>>]}]},{code,[],[<<44>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]}]},{code,[],[<<125>>]},<<46,32,84,104,105,115,32,102,108,97,103,32,111,118,101,114,114,105,100,101,115,32,102,108,97,103,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,114,105,116,121>>]}]},{dd,[],[{p,[],[<<85,115,101,100,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,46,32>>,{code,[],[<<123,77,44,32,70,44,32,65,114,105,116,121,125>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<123,77,44,32,70,44,32,65,114,103,115,125>>]},<<32,105,110,32,99,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,97,110,121,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,105,110,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,116,104,101,32,102,105,114,115,116,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,101,120,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,97,110,121,32,112,114,111,99,101,115,115,32,108,105,110,107,101,100,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,105,110,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,116,104,101,32,102,105,114,115,116,32,112,114,111,99,101,115,115,32,108,105,110,107,101,100,32,116,111,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,101,120,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,99,101,114,44,32,84,114,97,99,101,114,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,119,104,101,114,101,32,116,111,32,115,101,110,100,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32>>,{code,[],[<<84,114,97,99,101,114>>]},<<32,109,117,115,116,32,98,101,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,111,114,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,108,111,99,97,108,32,112,111,114,116,46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,99,101,114,44,32,84,114,97,99,101,114,77,111,100,117,108,101,44,32,84,114,97,99,101,114,83,116,97,116,101,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,97,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,105,115,32,116,111,32,98,101,32,99,97,108,108,101,100,32,105,110,115,116,101,97,100,32,111,102,32,115,101,110,100,105,110,103,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,46,32,84,104,101,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,99,97,110,32,116,104,101,110,32,105,103,110,111,114,101,32,111,114,32,99,104,97,110,103,101,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,111,110,32,104,111,119,32,116,111,32,119,114,105,116,101,32,97,32,116,114,97,99,101,114,32,109,111,100,117,108,101,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,108,95,116,114,97,99,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,116,114,97,99,101,114,40,51,41>>]}]},<<46>>]}]}]},{p,[],[<<73,102,32,110,111,32>>,{code,[],[<<116,114,97,99,101,114>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,114,101,99,101,105,118,101,115,32,97,108,108,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46>>]},{p,[],[<<84,104,101,32,101,102,102,101,99,116,32,111,102,32,99,111,109,98,105,110,105,110,103,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]},<<32,119,105,116,104,32>>,{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]},<<32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]},<<32,97,108,111,110,101,46,32,76,105,107,101,119,105,115,101,32,102,111,114,32>>,{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]},<<32,97,110,100,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]},<<46>>]},{p,[],[<<84,104,101,32,116,114,97,99,105,110,103,32,112,114,111,99,101,115,115,32,114,101,99,101,105,118,101,115,32,116,104,101,32>>,{em,[],[<<116,114,97,99,101,32,109,101,115,115,97,103,101,115>>]},<<32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,108,105,115,116,46,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,32,119,104,105,99,104,32,116,104,101,32,116,114,97,99,101,100,32,101,118,101,110,116,32,104,97,115,32,111,99,99,117,114,114,101,100,46,32,84,104,101,32,116,104,105,114,100,32,116,117,112,108,101,32,101,108,101,109,101,110,116,32,105,115,32,116,104,101,32,109,101,115,115,97,103,101,32,116,97,103,46>>]},{p,[],[<<73,102,32,102,108,97,103,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<44,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32,111,114,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,105,114,115,116,32,116,117,112,108,101,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<116,114,97,99,101,95,116,115>>]},<<32,105,110,115,116,101,97,100,44,32,97,110,100,32,116,104,101,32,116,105,109,101,32,115,116,97,109,112,32,105,115,32,97,100,100,101,100,32,97,115,32,97,110,32,101,120,116,114,97,32,101,108,101,109,101,110,116,32,108,97,115,116,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,116,117,112,108,101,46,32,73,102,32,109,117,108,116,105,112,108,101,32,116,105,109,101,32,115,116,97,109,112,32,102,108,97,103,115,32,97,114,101,32,112,97,115,115,101,100,44,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<32,104,97,115,32,112,114,101,99,101,100,101,110,99,101,32,111,118,101,114,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32,119,104,105,99,104,32,105,110,32,116,117,114,110,32,104,97,115,32,112,114,101,99,101,100,101,110,99,101,32,111,118,101,114,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<46,32,65,108,108,32,116,105,109,101,32,115,116,97,109,112,32,102,108,97,103,115,32,97,114,101,32,114,101,109,101,109,98,101,114,101,100,44,32,115,111,32,105,102,32,116,119,111,32,97,114,101,32,112,97,115,115,101,100,32,97,110,100,32,116,104,101,32,111,110,101,32,119,105,116,104,32,104,105,103,104,101,115,116,32,112,114,101,99,101,100,101,110,99,101,32,108,97,116,101,114,32,105,115,32,100,105,115,97,98,108,101,100,44,32,116,104,101,32,111,116,104,101,114,32,111,110,101,32,98,101,99,111,109,101,115,32,97,99,116,105,118,101,46>>]},{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,40,97,112,112,108,105,99,97,98,108,101,32,111,110,108,121,32,102,111,114,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<115,101,110,100>>]},<<32,97,110,100,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,105,110,103,41,32,99,111,110,116,97,105,110,115,32,97,32>>,{code,[],[<<123,109,101,115,115,97,103,101,125>>]},<<32,97,99,116,105,111,110,32,102,117,110,99,116,105,111,110,32,119,105,116,104,32,97,32,110,111,110,45,98,111,111,108,101,97,110,32,118,97,108,117,101,44,32,116,104,97,116,32,118,97,108,117,101,32,105,115,32,97,100,100,101,100,32,97,115,32,97,110,32,101,120,116,114,97,32,101,108,101,109,101,110,116,32,116,111,32,116,104,101,32,109,101,115,115,97,103,101,32,116,117,112,108,101,32,101,105,116,104,101,114,32,105,110,32,116,104,101,32,108,97,115,116,32,112,111,115,105,116,105,111,110,32,111,114,32,98,101,102,111,114,101,32,116,104,101,32,116,105,109,101,115,116,97,109,112,32,40,105,102,32,105,116,32,105,115,32,112,114,101,115,101,110,116,41,46>>]},{p,[],[<<84,114,97,99,101,32,109,101,115,115,97,103,101,115,58>>]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115>>}],[]},{dl,[],[{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,115,101,110,100,44,32,77,115,103,44,32,84,111,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,115,101,110,100,115,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<32,116,111,32,112,114,111,99,101,115,115,32>>,{code,[],[<<84,111>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115,44,32,77,115,103,44,32,84,111,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,115,101,110,100,115,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<32,116,111,32,116,104,101,32,110,111,110,45,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,32>>,{code,[],[<<84,111>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,99,101,105,118,101>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,39,114,101,99,101,105,118,101,39,44,32,77,115,103,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,114,101,99,101,105,118,101,115,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<46,32,73,102,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,116,105,109,101,45,111,117,116,44,32,97,32,114,101,99,101,105,118,101,32,115,116,97,116,101,109,101,110,116,32,99,97,110,32,104,97,118,101,32,116,105,109,101,100,32,111,117,116,44,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,99,101,105,118,101,100,32,97,32,109,101,115,115,97,103,101,32,119,105,116,104,32,116,104,101,32,112,97,121,108,111,97,100,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,97,108,108>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,99,97,108,108,44,32,123,77,44,32,70,44,32,65,114,103,115,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,99,97,108,108,115,32,97,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,111,102,32,99,97,108,108,115,32,97,114,101,32,110,101,118,101,114,32,115,117,112,112,108,105,101,100,44,32,111,110,108,121,32,116,104,101,32,99,97,108,108,32,97,110,100,32,105,116,115,32,97,114,103,117,109,101,110,116,115,46>>]},{p,[],[<<84,114,97,99,101,32,102,108,97,103,32>>,{code,[],[<<97,114,105,116,121>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,105,115,32,109,101,115,115,97,103,101,44,32,115,111,32,116,104,97,116,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<65,114,103,115>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,116,111>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,114,101,116,117,114,110,95,116,111,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,114,101,116,117,114,110,115,32>>,{em,[],[<<116,111>>]},<<32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,46,32,84,104,105,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,98,111,116,104,32,116,104,101,32,102,108,97,103,115,32>>,{code,[],[<<99,97,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,97,114,101,32,115,101,116,44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,115,101,116,32,116,111,32,98,101,32,116,114,97,99,101,100,32,111,110,32>>,{em,[],[<<108,111,99,97,108>>]},<<32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,84,104,101,32,109,101,115,115,97,103,101,32,105,115,32,111,110,108,121,32,115,101,110,116,32,119,104,101,110,32,114,101,116,117,114,110,105,110,103,32,102,114,111,109,32,97,32,99,104,97,105,110,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32,119,104,101,114,101,32,97,116,32,108,101,97,115,116,32,111,110,101,32,99,97,108,108,32,103,101,110,101,114,97,116,101,100,32,97,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,40,116,104,97,116,32,105,115,44,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,109,97,116,99,104,101,100,44,32,97,110,100,32>>,{code,[],[<<123,109,101,115,115,97,103,101,44,32,102,97,108,115,101,125>>]},<<32,119,97,115,32,110,111,116,32,97,110,32,97,99,116,105,111,110,41,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,102,114,111,109>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,114,101,116,117,114,110,95,102,114,111,109,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,44,32,82,101,116,117,114,110,86,97,108,117,101,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,114,101,116,117,114,110,115,32>>,{em,[],[<<102,114,111,109>>]},<<32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,46,32,84,104,105,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,102,108,97,103,32>>,{code,[],[<<99,97,108,108>>]},<<32,105,115,32,115,101,116,44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,104,97,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,119,105,116,104,32,97,32>>,{code,[],[<<114,101,116,117,114,110,95,116,114,97,99,101>>]},<<32,111,114,32>>,{code,[],[<<101,120,99,101,112,116,105,111,110,95,116,114,97,99,101>>]},<<32,97,99,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,99,101,112,116,105,111,110,95,102,114,111,109>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,101,120,99,101,112,116,105,111,110,95,102,114,111,109,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,44,32,123,67,108,97,115,115,44,32,86,97,108,117,101,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,105,116,115,32>>,{em,[],[<<102,114,111,109>>]},<<32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,32,98,101,99,97,117,115,101,32,111,102,32,97,110,32,101,120,99,101,112,116,105,111,110,46,32,84,104,105,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,102,108,97,103,32>>,{code,[],[<<99,97,108,108>>]},<<32,105,115,32,115,101,116,44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,104,97,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,119,105,116,104,32,97,110,32>>,{code,[],[<<101,120,99,101,112,116,105,111,110,95,116,114,97,99,101>>]},<<32,97,99,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,115,112,97,119,110,44,32,80,105,100,50,44,32,123,77,44,32,70,44,32,65,114,103,115,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,115,112,97,119,110,115,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,97,115,32,101,110,116,114,121,32,112,111,105,110,116,46>>]},{p,[],[{code,[],[<<65,114,103,115>>]},<<32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,116,104,101,32,97,114,103,117,109,101,110,116,32,108,105,115,116,44,32,98,117,116,32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,32,105,102,32,116,104,101,32,115,112,97,119,110,32,105,115,32,101,114,114,111,110,101,111,117,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,115,112,97,119,110,101,100,44,32,80,105,100,50,44,32,123,77,44,32,70,44,32,65,114,103,115,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,115,112,97,119,110,101,100,32,98,121,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,97,115,32,101,110,116,114,121,32,112,111,105,110,116,46>>]},{p,[],[{code,[],[<<65,114,103,115>>]},<<32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,116,104,101,32,97,114,103,117,109,101,110,116,32,108,105,115,116,44,32,98,117,116,32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,32,105,102,32,116,104,101,32,115,112,97,119,110,32,105,115,32,101,114,114,111,110,101,111,117,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,105,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,101,120,105,116,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,103,105,115,116,101,114>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,114,101,103,105,115,116,101,114,44,32,82,101,103,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,114,101,103,105,115,116,101,114,101,100,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,114,101,103,105,115,116,101,114>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,117,110,114,101,103,105,115,116,101,114,44,32,82,101,103,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,117,110,114,101,103,105,115,116,101,114,101,100,46,32,84,104,105,115,32,105,115,32,100,111,110,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,119,104,101,110,32,97,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,101,120,105,116,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,108,105,110,107>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,108,105,110,107,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,108,105,110,107,115,32,116,111,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,108,105,110,107>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,117,110,108,105,110,107,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,114,101,109,111,118,101,115,32,116,104,101,32,108,105,110,107,32,102,114,111,109,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,108,105,110,107,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,103,101,116,116,105,110,103,95,108,105,110,107,101,100,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,108,105,110,107,101,100,32,116,111,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,117,110,108,105,110,107,101,100,32,102,114,111,109,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,105,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,101,120,105,116,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,112,101,110>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,111,112,101,110,44,32,80,105,100,44,32,68,114,105,118,101,114,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,111,112,101,110,115,32,97,32,110,101,119,32,112,111,114,116,32>>,{code,[],[<<80,111,114,116>>]},<<32,119,105,116,104,32,116,104,101,32,114,117,110,110,105,110,103,32>>,{code,[],[<<68,114,105,118,101,114>>]},<<46>>]},{p,[],[{code,[],[<<68,114,105,118,101,114>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,100,114,105,118,101,114,32,97,115,32,97,110,32,97,116,111,109,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,108,111,115,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,99,108,111,115,101,100,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,99,108,111,115,101,115,32,119,105,116,104,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,114,111,99>>}],[]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,101,120,105,116,105,110,103,95,112,114,111,99>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,105,110,32,124,32,105,110,95,101,120,105,116,105,110,103,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,114,117,110,46,32,84,104,101,32,112,114,111,99,101,115,115,32,114,117,110,115,32,105,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,77,44,32,70,44,32,65,114,105,116,121,125>>]},<<46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,114,111,99>>}],[]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,105,110,103,95,112,114,111,99>>}],[]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,101,100,95,112,114,111,99>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,111,117,116,32,124,32,111,117,116,95,101,120,105,116,105,110,103,32,124,32,111,117,116,95,101,120,105,116,101,100,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,111,117,116,46,32,84,104,101,32,112,114,111,99,101,115,115,32,119,97,115,32,114,117,110,110,105,110,103,32,105,110,32,102,117,110,99,116,105,111,110,32,123,77,44,32,70,44,32,65,114,105,116,121,125,46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,111,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,105,110,44,32,67,111,109,109,97,110,100,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,114,117,110,46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,105,115,32,116,104,101,32,102,105,114,115,116,32,116,104,105,110,103,32,116,104,101,32,112,111,114,116,32,119,105,108,108,32,101,120,101,99,117,116,101,44,32,105,116,32,99,97,110,32,104,111,119,101,118,101,114,32,114,117,110,32,115,101,118,101,114,97,108,32,99,111,109,109,97,110,100,115,32,98,101,102,111,114,101,32,98,101,105,110,103,32,115,99,104,101,100,117,108,101,100,32,111,117,116,46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]},{p,[],[<<84,104,101,32,112,111,115,115,105,98,108,101,32,99,111,109,109,97,110,100,115,32,97,114,101,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<99,108,111,115,101>>]},<<44,32>>,{code,[],[<<99,111,109,109,97,110,100>>]},<<44,32>>,{code,[],[<<99,111,110,110,101,99,116>>]},<<44,32>>,{code,[],[<<99,111,110,116,114,111,108>>]},<<44,32>>,{code,[],[<<102,108,117,115,104>>]},<<44,32>>,{code,[],[<<105,110,102,111>>]},<<44,32>>,{code,[],[<<108,105,110,107>>]},<<44,32>>,{code,[],[<<111,112,101,110>>]},<<44,32,97,110,100,32>>,{code,[],[<<117,110,108,105,110,107>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,111,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,111,117,116,44,32,67,111,109,109,97,110,100,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,111,117,116,46,32,84,104,101,32,108,97,115,116,32,99,111,109,109,97,110,100,32,114,117,110,32,119,97,115,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32,99,111,109,109,97,110,100,115,32,97,115,32>>,{code,[],[<<105,110>>]}]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,105,110,111,114,95,115,116,97,114,116,44,32,73,110,102,111,125>>]}]},{dd,[],[{a,[{id,<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>}],[]},{p,[],[<<83,101,110,116,32,119,104,101,110,32,97,32,121,111,117,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,97,98,111,117,116,32,116,111,32,98,101,32,115,116,97,114,116,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,101,108,101,109,101,110,116,32,116,117,112,108,101,115,44,32,119,104,101,114,101,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,107,101,121,44,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,105,115,32,116,104,101,32,118,97,108,117,101,46,32,68,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,97,110,121,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,107,101,121,115,32,97,114,101,32,100,101,102,105,110,101,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,117,115,101,100,32,112,97,114,116,32,111,102,32,116,104,101,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,98,108,111,99,107,32,117,115,101,100,32,102,111,114,32,115,116,111,114,105,110,103,32,116,104,101,32,104,101,97,112,32,97,110,100,32,116,104,101,32,115,116,97,99,107,46>>]},{dt,[],[{code,[],[<<111,108,100,95,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,117,115,101,100,32,112,97,114,116,32,111,102,32,116,104,101,32,111,108,100,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<111,108,100,95,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,98,108,111,99,107,32,117,115,101,100,32,102,111,114,32,115,116,111,114,105,110,103,32,116,104,101,32,111,108,100,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<115,116,97,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,115,116,97,99,107,46>>]},{dt,[],[{code,[],[<<114,101,99,101,110,116,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,100,97,116,97,32,116,104,97,116,32,115,117,114,118,105,118,101,100,32,116,104,101,32,112,114,101,118,105,111,117,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{dt,[],[{code,[],[<<109,98,117,102,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,99,111,109,98,105,110,101,100,32,115,105,122,101,32,111,102,32,109,101,115,115,97,103,101,32,98,117,102,102,101,114,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,99,101,115,115,46>>]},{dt,[],[{code,[],[<<98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,117,110,105,113,117,101,32,111,102,102,45,104,101,97,112,32,98,105,110,97,114,105,101,115,32,114,101,102,101,114,101,110,99,101,100,32,102,114,111,109,32,116,104,101,32,112,114,111,99,101,115,115,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<98,105,110,95,118,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,98,105,110,97,114,105,101,115,32,97,108,108,111,119,101,100,32,105,110,32,116,104,101,32,118,105,114,116,117,97,108,32,104,101,97,112,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,98,101,102,111,114,101,32,100,111,105,110,103,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{dt,[],[{code,[],[<<98,105,110,95,111,108,100,95,118,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,117,110,105,113,117,101,32,111,102,102,45,104,101,97,112,32,98,105,110,97,114,105,101,115,32,114,101,102,101,114,101,110,99,101,100,32,102,114,111,109,32,116,104,101,32,112,114,111,99,101,115,115,32,111,108,100,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<98,105,110,95,111,108,100,95,118,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,98,105,110,97,114,105,101,115,32,97,108,108,111,119,101,100,32,105,110,32,116,104,101,32,118,105,114,116,117,97,108,32,111,108,100,32,104,101,97,112,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,98,101,102,111,114,101,32,100,111,105,110,103,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]},{p,[],[<<65,108,108,32,115,105,122,101,115,32,97,114,101,32,105,110,32,119,111,114,100,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<32,105,115,32,114,101,97,99,104,101,100,32,100,117,114,105,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,115,116,97,114,116>>]},<<44,32,98,117,116,32,116,104,101,32,115,105,122,101,115,32,114,101,102,108,101,99,116,32,116,104,101,32,115,105,122,101,115,32,116,104,97,116,32,116,114,105,103,103,101,114,101,100,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,116,111,32,98,101,32,114,101,97,99,104,101,100,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,101,110,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,105,110,111,114,95,101,110,100,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,121,111,117,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,102,105,110,105,115,104,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<44,32,98,117,116,32,116,104,101,32,115,105,122,101,115,32,114,101,102,108,101,99,116,32,116,104,101,32,110,101,119,32,115,105,122,101,115,32,97,102,116,101,114,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,106,111,114,95,115,116,97,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,97,106,111,114,95,115,116,97,114,116,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,97,98,111,117,116,32,116,111,32,98,101,32,115,116,97,114,116,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,106,111,114,95,101,110,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,97,106,111,114,95,101,110,100,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,102,105,110,105,115,104,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<44,32,98,117,116,32,116,104,101,32,115,105,122,101,115,32,114,101,102,108,101,99,116,32,116,104,101,32,110,101,119,32,115,105,122,101,115,32,97,102,116,101,114,32,97,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]}]},{p,[],[<<73,102,32,116,104,101,32,116,114,97,99,105,110,103,32,112,114,111,99,101,115,115,47,112,111,114,116,32,100,105,101,115,32,111,114,32,116,104,101,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<114,101,109,111,118,101>>]},<<44,32,116,104,101,32,102,108,97,103,115,32,97,114,101,32,115,105,108,101,110,116,108,121,32,114,101,109,111,118,101,100,46>>]},{p,[],[<<69,97,99,104,32,112,114,111,99,101,115,115,32,99,97,110,32,111,110,108,121,32,98,101,32,116,114,97,99,101,100,32,98,121,32,111,110,101,32,116,114,97,99,101,114,46,32,84,104,101,114,101,102,111,114,101,44,32,97,116,116,101,109,112,116,115,32,116,111,32,116,114,97,99,101,32,97,110,32,97,108,114,101,97,100,121,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,102,97,105,108,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,117,109,98,101,114,32,105,110,100,105,99,97,116,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,109,97,116,99,104,101,100,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<49>>]},<<46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32>>,{code,[],[<<97,108,108>>]},<<32,111,114,32>>,{code,[],[<<101,120,105,115,116,105,110,103>>]},<<44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,114,117,110,110,105,110,103,46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32>>,{code,[],[<<110,101,119>>]},<<44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,97,108,108,32,112,108,97,116,102,111,114,109,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,48,51,54>>,signature => [{attribute,2013,spec,{{erlang,trace,3},[{type,2013,bounded_fun,[{type,2013,'fun',[{type,2013,product,[{var,2013,'PidPortSpec'},{var,2013,'How'},{var,2013,'FlagList'}]},{type,2013,integer,[]}]},[{type,2014,constraint,[{atom,2014,is_subtype},[{var,2014,'PidPortSpec'},{type,2014,union,[{type,2014,pid,[]},{type,2014,port,[]},{atom,2015,all},{atom,2015,processes},{atom,2015,ports},{atom,2016,existing},{atom,2016,existing_processes},{atom,2016,existing_ports},{atom,2017,new},{atom,2017,new_processes},{atom,2017,new_ports}]}]]},{type,2018,constraint,[{atom,2018,is_subtype},[{var,2018,'How'},{type,2018,boolean,[]}]]},{type,2019,constraint,[{atom,2019,is_subtype},[{var,2019,'FlagList'},{type,2019,list,[{user_type,2019,trace_flag,[]}]}]]}]]}]}}]}},{{function,trace_delivered,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2028}],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,100,101,108,105,118,101,114,121,32,111,102,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,40,103,101,110,101,114,97,116,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,107,101,114,110,101,108,58,115,101,113,95,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,113,95,116,114,97,99,101,40,51,41>>]}]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>]}]},<<41,32,105,115,32,100,105,115,108,111,99,97,116,101,100,32,111,110,32,116,104,101,32,116,105,109,101,45,108,105,110,101,32,99,111,109,112,97,114,101,100,32,116,111,32,111,116,104,101,114,32,101,118,101,110,116,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,73,102,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,104,97,115,32,112,97,115,115,101,100,32,115,111,109,101,32,115,112,101,99,105,102,105,99,32,112,111,105,110,116,32,105,110,32,105,116,115,32,101,120,101,99,117,116,105,111,110,44,32,97,110,100,32,121,111,117,32,119,97,110,116,32,116,111,32,107,110,111,119,32,119,104,101,110,32,97,116,32,108,101,97,115,116,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,101,118,101,110,116,115,32,117,112,32,116,111,32,116,104,105,115,32,112,111,105,110,116,32,104,97,118,101,32,114,101,97,99,104,101,100,32,116,104,101,32,116,114,97,99,101,114,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<46>>]},{p,[],[<<87,104,101,110,32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,116,114,97,99,101,114,32,117,112,32,116,111,32,116,104,101,32,112,111,105,110,116,32,116,104,97,116,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,114,101,97,99,104,101,100,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<44,32,116,104,101,110,32,97,32>>,{code,[],[<<123,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,44,32,84,114,97,99,101,101,44,32,82,101,102,125>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<32,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,109,101,115,115,97,103,101,32>>,{code,[],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100>>]},<<32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,105,109,112,108,121,32,116,104,97,116,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,46,32,73,110,115,116,101,97,100,32,105,116,32,105,109,112,108,105,101,115,32,116,104,97,116,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,116,104,97,116,32>>,{em,[],[<<97,114,101,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100>>]},<<32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,46,32,73,116,32,105,115,32,110,111,116,32,97,110,32,101,114,114,111,114,32,105,102,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,105,115,32,110,111,116,44,32,97,110,100,32,104,97,115,32,110,111,116,32,98,101,101,110,32,116,114,97,99,101,100,32,98,121,32,115,111,109,101,111,110,101,44,32,98,117,116,32,105,102,32,116,104,105,115,32,105,115,32,116,104,101,32,99,97,115,101,44,32>>,{em,[],[<<110,111>>]},<<32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,119,104,101,110,32,116,104,101,32>>,{code,[],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100>>]},<<32,109,101,115,115,97,103,101,32,97,114,114,105,118,101,115,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,109,117,115,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,32,99,117,114,114,101,110,116,108,121,32,111,114,32,112,114,101,118,105,111,117,115,108,121,32,101,120,105,115,116,105,110,103,32,111,110,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,97,115,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<32,114,101,115,105,100,101,115,32,111,110,46,32,84,104,101,32,115,112,101,99,105,97,108,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,97,116,111,109,32>>,{code,[],[<<97,108,108>>]},<<32,100,101,110,111,116,101,115,32,97,108,108,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,99,117,114,114,101,110,116,108,121,32,97,114,101,32,116,114,97,99,101,100,32,105,110,32,116,104,101,32,110,111,100,101,46>>]},{p,[],[<<87,104,101,110,32,117,115,101,100,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,101,114,108,95,116,114,97,99,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<84,114,97,99,101,114,32,77,111,100,117,108,101>>]},<<44,32,97,110,121,32,109,101,115,115,97,103,101,32,115,101,110,116,32,105,110,32,116,104,101,32,116,114,97,99,101,32,99,97,108,108,98,97,99,107,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,104,97,118,101,32,114,101,97,99,104,101,100,32,105,116,115,32,114,101,99,105,112,105,101,110,116,32,98,101,102,111,114,101,32,116,104,101,32>>,{code,[],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,46>>]},{p,[],[<<69,120,97,109,112,108,101,58,32,80,114,111,99,101,115,115,32>>,{code,[],[<<65>>]},<<32,105,115,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<44,32,112,111,114,116,32>>,{code,[],[<<66>>]},<<32,105,115,32,116,114,97,99,101,114,44,32,97,110,100,32,112,114,111,99,101,115,115,32>>,{code,[],[<<67>>]},<<32,105,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,111,102,32>>,{code,[],[<<66>>]},<<46,32>>,{code,[],[<<67>>]},<<32,119,97,110,116,115,32,116,111,32,99,108,111,115,101,32>>,{code,[],[<<66>>]},<<32,119,104,101,110,32>>,{code,[],[<<65>>]},<<32,101,120,105,116,115,46,32,84,111,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,116,114,97,99,101,32,105,115,32,110,111,116,32,116,114,117,110,99,97,116,101,100,44,32>>,{code,[],[<<67>>]},<<32,99,97,110,32,99,97,108,108,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,65,41>>]},<<32,119,104,101,110,32>>,{code,[],[<<65>>]},<<32,101,120,105,116,115,44,32,97,110,100,32,119,97,105,116,32,102,111,114,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,44,32,65,44,32,82,101,102,125>>]},<<32,98,101,102,111,114,101,32,99,108,111,115,105,110,103,32>>,{code,[],[<<66>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,32,40,100,101,97,100,32,111,114,32,97,108,105,118,101,41,32,111,110,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,97,115,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<32,114,101,115,105,100,101,115,32,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,54,57,55>>,signature => [{attribute,2028,spec,{{erlang,trace_delivered,1},[{type,2028,bounded_fun,[{type,2028,'fun',[{type,2028,product,[{var,2028,'Tracee'}]},{var,2028,'Ref'}]},[{type,2029,constraint,[{atom,2029,is_subtype},[{var,2029,'Tracee'},{type,2029,union,[{type,2029,pid,[]},{atom,2029,all}]}]]},{type,2030,constraint,[{atom,2030,is_subtype},[{var,2030,'Ref'},{type,2030,reference,[]}]]}]]}]}}]}},{{function,trace_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2035}],[<<116,114,97,99,101,95,105,110,102,111,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,105,110,102,111,95,102,108,97,103>>}],[]},{li,[{name,<<116,114,97,99,101,95,105,110,102,111,95,105,116,101,109,95,114,101,115,117,108,116>>}],[]},{li,[{name,<<116,114,97,99,101,95,105,110,102,111,95,114,101,116,117,114,110>>}],[]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,114,97,99,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,112,111,114,116,44,32,112,114,111,99,101,115,115,44,32,102,117,110,99,116,105,111,110,44,32,111,114,32,101,118,101,110,116,46>>]},{p,[],[{em,[],[<<84,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,112,111,114,116,32,111,114,32,112,114,111,99,101,115,115>>]},<<44,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32,116,111,32,98,101,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,44,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,111,110,101,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<110,101,119>>]},<<44,32>>,{code,[],[<<110,101,119,95,112,114,111,99,101,115,115,101,115>>]},<<44,32,111,114,32>>,{code,[],[<<110,101,119,95,112,111,114,116,115>>]},<<46,32,84,104,101,32,97,116,111,109,32>>,{code,[],[<<110,101,119>>]},<<32,111,114,32>>,{code,[],[<<110,101,119,95,112,114,111,99,101,115,115,101,115>>]},<<32,109,101,97,110,115,32,116,104,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,116,114,97,99,101,32,115,116,97,116,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,32,116,111,32,98,101,32,99,114,101,97,116,101,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,97,116,111,109,32>>,{code,[],[<<110,101,119,95,112,111,114,116,115>>]},<<32,109,101,97,110,115,32,116,104,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,116,114,97,99,101,32,115,116,97,116,101,32,102,111,114,32,112,111,114,116,115,32,116,111,32,98,101,32,99,114,101,97,116,101,100,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,102,111,114,32,112,111,114,116,115,32,97,110,100,32,112,114,111,99,101,115,115,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,108,97,103,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,116,111,109,115,32,105,110,100,105,99,97,116,105,110,103,32,119,104,97,116,32,107,105,110,100,32,111,102,32,116,114,97,99,101,115,32,105,115,32,101,110,97,98,108,101,100,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,101,32,108,105,115,116,32,105,115,32,101,109,112,116,121,32,105,102,32,110,111,32,116,114,97,99,101,115,32,97,114,101,32,101,110,97,98,108,101,100,44,32,97,110,100,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,115,32,97,116,111,109,115,32,105,102,32,116,114,97,99,101,115,32,97,114,101,32,101,110,97,98,108,101,100,58,32>>,{code,[],[<<115,101,110,100>>]},<<44,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<44,32>>,{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]},<<44,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<44,32>>,{code,[],[<<112,114,111,99,115>>]},<<44,32>>,{code,[],[<<112,111,114,116,115>>]},<<44,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]},<<44,32>>,{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]},<<44,32>>,{code,[],[<<114,117,110,110,105,110,103>>]},<<44,32>>,{code,[],[<<114,117,110,110,105,110,103,95,112,114,111,99,115>>]},<<44,32>>,{code,[],[<<114,117,110,110,105,110,103,95,112,111,114,116,115>>]},<<44,32>>,{code,[],[<<115,105,108,101,110,116>>]},<<44,32>>,{code,[],[<<101,120,105,116,105,110,103>>]},<<44,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32>>,{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<44,32,97,110,100,32>>,{code,[],[<<97,114,105,116,121>>]},<<46,32,84,104,101,32,111,114,100,101,114,32,105,115,32,97,114,98,105,116,114,97,114,121,46>>]}]},{dt,[],[{code,[],[<<116,114,97,99,101,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,105,100,101,110,116,105,102,105,101,114,32,102,111,114,32,112,114,111,99,101,115,115,44,32,112,111,114,116,44,32,111,114,32,97,32,116,117,112,108,101,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,97,110,100,32,116,114,97,99,101,114,32,115,116,97,116,101,32,116,114,97,99,105,110,103,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,105,115,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,114,97,99,101,100,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]}]},{p,[],[{em,[],[<<84,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,102,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32,116,111,32,98,101,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<46,32,78,111,32,119,105,108,100,99,97,114,100,115,32,97,114,101,32,97,108,108,111,119,101,100,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,111,114,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,116,114,97,99,101,100,46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<44,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,114,101,102,101,114,115,32,116,111,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,102,111,114,32,99,111,100,101,32,116,104,97,116,32,119,105,108,108,32,98,101,32,108,111,97,100,101,100,46>>]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,102,111,114,32,102,117,110,99,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,97,99,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,114,97,99,101,100,32,111,110,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,105,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,114,97,99,101,100,32,111,110,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,40,116,104,97,116,32,105,115,44,32,108,111,99,97,108,32,97,110,100,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,41,44,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,108,111,99,97,108,32,111,114,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,114,101,32,110,111,116,32,116,114,97,99,101,100,46>>]}]},{dt,[],[{code,[],[<<109,97,116,99,104,95,115,112,101,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,108,111,99,97,108,108,121,32,111,114,32,103,108,111,98,97,108,108,121,32,116,114,97,99,101,100,32,98,117,116,32,104,97,115,32,110,111,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,100,101,102,105,110,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,101,116,97>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,101,116,97,45,116,114,97,99,101,32,116,114,97,99,101,114,32,112,114,111,99,101,115,115,44,32,112,111,114,116,44,32,111,114,32,116,114,97,99,101,32,109,111,100,117,108,101,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,109,101,116,97,45,116,114,97,99,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,109,101,116,97,45,116,114,97,99,101,100,32,98,117,116,32,104,97,115,32,111,110,99,101,32,100,101,116,101,99,116,101,100,32,116,104,97,116,32,116,104,101,32,116,114,97,99,101,114,32,112,114,111,99,101,115,115,32,105,115,32,105,110,118,97,108,105,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,101,116,97,95,109,97,116,99,104,95,115,112,101,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,101,116,97,45,116,114,97,99,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,109,101,116,97,45,116,114,97,99,101,100,32,98,117,116,32,104,97,115,32,110,111,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,100,101,102,105,110,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,97,108,108,32,99,111,117,110,116,32,118,97,108,117,101,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,111,114,32>>,{code,[],[<<116,114,117,101>>]},<<32,102,111,114,32,116,104,101,32,112,115,101,117,100,111,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,105,102,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,105,115,32,97,99,116,105,118,101,46,32,79,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,97,108,108,32,116,105,109,101,32,118,97,108,117,101,115,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,111,114,32>>,{code,[],[<<116,114,117,101>>]},<<32,102,111,114,32,116,104,101,32,112,115,101,117,100,111,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,105,102,32,99,97,108,108,32,116,105,109,101,32,116,114,97,99,105,110,103,32,105,115,32,97,99,116,105,118,101,46,32,79,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,99,97,108,108,32,116,105,109,101,32,118,97,108,117,101,115,32,114,101,116,117,114,110,101,100,44,32>>,{code,[],[<<91,123,80,105,100,44,32,67,111,117,110,116,44,32,83,44,32,85,115,125,93>>]},<<44,32,105,115,32,97,32,108,105,115,116,32,111,102,32,101,97,99,104,32,112,114,111,99,101,115,115,32,116,104,97,116,32,101,120,101,99,117,116,101,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,110,100,32,105,116,115,32,115,112,101,99,105,102,105,99,32,99,111,117,110,116,101,114,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32>>,{code,[],[<<123,73,116,101,109,44,32,86,97,108,117,101,125>>]},<<32,116,117,112,108,101,115,32,102,111,114,32,97,108,108,32,111,116,104,101,114,32,105,116,101,109,115,44,32,111,114,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,110,111,32,116,114,97,99,105,110,103,32,105,115,32,97,99,116,105,118,101,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]}]},{p,[],[{em,[],[<<84,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,110,32,101,118,101,110,116>>]},<<44,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32,116,111,32,98,101,32,111,110,101,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<115,101,110,100>>]},<<32,111,114,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<46>>]},{p,[],[<<79,110,101,32,118,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,102,111,114,32,101,118,101,110,116,115,32,101,120,105,115,116,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<109,97,116,99,104,95,115,112,101,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,116,104,105,115,32,101,118,101,110,116,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,44,32,111,114,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,110,111,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,101,116,46>>]}]}]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<123,73,116,101,109,44,32,86,97,108,117,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,105,115,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46,32,73,102,32,97,32,112,105,100,32,102,111,114,32,97,32,100,101,97,100,32,112,114,111,99,101,115,115,32,119,97,115,32,115,112,101,99,105,102,105,101,100,44,32,111,114,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,110,111,110,45,101,120,105,115,116,105,110,103,32,102,117,110,99,116,105,111,110,44,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,105,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,55,53,50>>,signature => [{attribute,2035,spec,{{erlang,trace_info,2},[{type,2035,bounded_fun,[{type,2035,'fun',[{type,2035,product,[{var,2035,'PidPortFuncEvent'},{var,2035,'Item'}]},{var,2035,'Res'}]},[{type,2036,constraint,[{atom,2036,is_subtype},[{var,2036,'PidPortFuncEvent'},{type,2036,union,[{type,2036,pid,[]},{type,2036,port,[]},{atom,2036,new},{atom,2036,new_processes},{atom,2036,new_ports},{type,2037,tuple,[{var,2037,'Module'},{var,2037,'Function'},{var,2037,'Arity'}]},{atom,2037,on_load},{atom,2037,send},{atom,2037,'receive'}]}]]},{type,2038,constraint,[{atom,2038,is_subtype},[{var,2038,'Module'},{type,2038,module,[]}]]},{type,2039,constraint,[{atom,2039,is_subtype},[{var,2039,'Function'},{type,2039,atom,[]}]]},{type,2040,constraint,[{atom,2040,is_subtype},[{var,2040,'Arity'},{type,2040,arity,[]}]]},{type,2041,constraint,[{atom,2041,is_subtype},[{var,2041,'Item'},{type,2041,union,[{atom,2041,flags},{atom,2041,tracer},{atom,2041,traced},{atom,2041,match_spec},{atom,2042,meta},{atom,2042,meta_match_spec},{atom,2042,call_count},{atom,2042,call_time},{atom,2042,all}]}]]},{type,2043,constraint,[{atom,2043,is_subtype},[{var,2043,'Res'},{user_type,2043,trace_info_return,[]}]]}]]}]}}]}},{{function,trace_pattern,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2705}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]},{li,[{name,<<116,114,97,99,101,95,112,97,116,116,101,114,110,95,109,102,97>>}],[]}]},{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,69,118,101,110,116,44,32,77,97,116,99,104,83,112,101,99,44,32,91,93,41>>]}]},<<44,32,114,101,116,97,105,110,101,100,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,56,56,56>>,signature => [{attribute,2705,spec,{{erlang,trace_pattern,2},[{type,2705,bounded_fun,[{type,2705,'fun',[{type,2705,product,[{var,2705,'MFA'},{var,2705,'MatchSpec'}]},{type,2705,non_neg_integer,[]}]},[{type,2706,constraint,[{atom,2706,is_subtype},[{var,2706,'MFA'},{type,2706,union,[{user_type,2706,trace_pattern_mfa,[]},{atom,2706,send},{atom,2706,'receive'}]}]]},{type,2707,constraint,[{atom,2707,is_subtype},[{var,2707,'MatchSpec'},{type,2707,union,[{ann_type,2707,[{var,2707,'MatchSpecList'},{user_type,2707,trace_match_spec,[]}]},{type,2708,boolean,[]},{atom,2709,restart},{atom,2710,pause}]}]]}]]}]}}]}},{{function,trace_pattern,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2725}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]}]},{p,[],[<<83,101,116,115,32,116,114,97,99,101,32,112,97,116,116,101,114,110,32,102,111,114,32>>,{em,[],[<<109,101,115,115,97,103,101,32,115,101,110,100,105,110,103>>]},<<46,32,77,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<32,116,111,32,115,101,116,32,116,104,101,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,46,32,66,121,32,100,101,102,97,117,108,116,32,97,108,108,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,102,114,111,109,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,116,114,97,99,101,100,46,32,84,111,32,108,105,109,105,116,32,116,114,97,99,101,100,32,115,101,110,100,32,101,118,101,110,116,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32,109,101,115,115,97,103,101,32,99,111,110,116,101,110,116,44,32,116,104,101,32,115,101,110,100,101,114,32,97,110,100,47,111,114,32,116,104,101,32,114,101,99,101,105,118,101,114,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99>>]},<<32,99,97,110,32,116,97,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<77,97,116,99,104,83,112,101,99,76,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,105,115,32,100,111,110,101,32,111,110,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<91,82,101,99,101,105,118,101,114,44,32,77,115,103,93>>]},<<46,32>>,{code,[],[<<82,101,99,101,105,118,101,114>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,116,121,32,111,102,32,116,104,101,32,114,101,99,101,105,118,101,114,32,97,110,100,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,116,104,101,32,109,101,115,115,97,103,101,32,116,101,114,109,46,32,84,104,101,32,112,105,100,32,111,102,32,116,104,101,32,115,101,110,100,105,110,103,32,112,114,111,99,101,115,115,32,99,97,110,32,98,101,32,97,99,99,101,115,115,101,100,32,119,105,116,104,32,116,104,101,32,103,117,97,114,100,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<115,101,108,102,47,48>>]},<<46,32,65,110,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,109,97,116,99,104,95,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<69,110,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,115,101,110,116,32,109,101,115,115,97,103,101,115,32,40,102,114,111,109,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,41,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46,32>>,{em,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,115,101,110,116,32,109,101,115,115,97,103,101,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]}]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,109,117,115,116,32,98,101,32>>,{code,[],[<<91,93>>]},<<32,102,111,114,32,115,101,110,100,32,116,114,97,99,105,110,103,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,108,119,97,121,115,32>>,{code,[],[<<49>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,116,111,32,97,32,115,112,101,99,105,102,105,99,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,80,105,100,44,32,39,95,39,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,109,97,116,99,104,105,110,103,32>>,{code,[],[<<123,114,101,112,108,121,44,32,95,125>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,39,95,39,44,32,123,114,101,112,108,121,44,39,95,39,125,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,116,111,32,116,104,101,32,115,101,110,100,101,114,32,105,116,115,101,108,102,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,39,36,49,39,44,32,39,95,39,93,44,91,123,39,61,58,61,39,44,39,36,49,39,44,123,115,101,108,102,125,125,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,116,111,32,111,116,104,101,114,32,110,111,100,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,39,36,49,39,44,32,39,95,39,93,44,91,123,39,61,47,61,39,44,123,110,111,100,101,44,39,36,49,39,125,44,123,110,111,100,101,125,125,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,32,99,97,110,32,117,115,101,32,97,108,108,32,103,117,97,114,100,32,97,110,100,32,98,111,100,121,32,102,117,110,99,116,105,111,110,115,32,101,120,99,101,112,116,32>>,{code,[],[<<99,97,108,108,101,114>>]},<<46>>]}]},{p,[],[<<70,97,105,108,115,32,98,121,32,114,97,105,115,105,110,103,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,97,110,32,97,114,103,117,109,101,110,116,32,105,115,32,105,110,118,97,108,105,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,32,104,97,115,32,101,120,99,101,115,115,105,118,101,32,110,101,115,116,105,110,103,32,119,104,105,99,104,32,99,97,117,115,101,115,32,115,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,101,120,104,97,117,115,116,105,111,110,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,115,99,104,101,100,95,116,104,114,101,97,100,95,115,116,97,99,107,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<83,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,57,48,54>>,signature => [{attribute,2725,spec,{{erlang,trace_pattern,3},[{type,2725,bounded_fun,[{type,2725,'fun',[{type,2725,product,[{atom,2725,send},{var,2725,'MatchSpec'},{type,2725,nil,[]}]},{type,2725,non_neg_integer,[]}]},[{type,2726,constraint,[{atom,2726,is_subtype},[{var,2726,'MatchSpec'},{type,2726,union,[{ann_type,2726,[{var,2726,'MatchSpecList'},{user_type,2726,trace_match_spec,[]}]},{type,2727,boolean,[]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,trace_pattern,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2725}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]}]},{p,[],[<<83,101,116,115,32,116,114,97,99,101,32,112,97,116,116,101,114,110,32,102,111,114,32>>,{em,[],[<<109,101,115,115,97,103,101,32,114,101,99,101,105,118,105,110,103>>]},<<46,32,77,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<32,116,111,32,115,101,116,32,116,104,101,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,46,32,66,121,32,100,101,102,97,117,108,116,32,97,108,108,32,109,101,115,115,97,103,101,115,32,114,101,99,101,105,118,101,100,32,98,121,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,116,114,97,99,101,100,46,32,84,111,32,108,105,109,105,116,32,116,114,97,99,101,100,32,114,101,99,101,105,118,101,32,101,118,101,110,116,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32,109,101,115,115,97,103,101,32,99,111,110,116,101,110,116,44,32,116,104,101,32,115,101,110,100,101,114,32,97,110,100,47,111,114,32,116,104,101,32,114,101,99,101,105,118,101,114,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99>>]},<<32,99,97,110,32,116,97,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<77,97,116,99,104,83,112,101,99,76,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,105,115,32,100,111,110,101,32,111,110,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<91,78,111,100,101,44,32,83,101,110,100,101,114,44,32,77,115,103,93>>]},<<46,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,116,104,101,32,110,111,100,101,32,110,97,109,101,32,111,102,32,116,104,101,32,115,101,110,100,101,114,46,32>>,{code,[],[<<83,101,110,100,101,114>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,116,121,32,111,102,32,116,104,101,32,115,101,110,100,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,115,101,110,100,101,114,32,105,115,32,110,111,116,32,107,110,111,119,110,32,40,119,104,105,99,104,32,99,97,110,32,98,101,32,116,104,101,32,99,97,115,101,32,102,111,114,32,114,101,109,111,116,101,32,115,101,110,100,101,114,115,41,46,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,116,104,101,32,109,101,115,115,97,103,101,32,116,101,114,109,46,32,84,104,101,32,112,105,100,32,111,102,32,116,104,101,32,114,101,99,101,105,118,105,110,103,32,112,114,111,99,101,115,115,32,99,97,110,32,98,101,32,97,99,99,101,115,115,101,100,32,119,105,116,104,32,116,104,101,32,103,117,97,114,100,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<115,101,108,102,47,48>>]},<<46,32,65,110,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,109,97,116,99,104,95,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<69,110,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,114,101,99,101,105,118,101,100,32,109,101,115,115,97,103,101,115,32,40,116,111,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,41,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46,32>>,{em,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,114,101,99,101,105,118,101,100,32,109,101,115,115,97,103,101,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]}]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,109,117,115,116,32,98,101,32>>,{code,[],[<<91,93>>]},<<32,102,111,114,32,114,101,99,101,105,118,101,32,116,114,97,99,105,110,103,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,108,119,97,121,115,32>>,{code,[],[<<49>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,97,32,115,112,101,99,105,102,105,99,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,39,114,101,99,101,105,118,101,39,44,32,91,123,91,39,95,39,44,80,105,100,44,32,39,95,39,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,109,97,116,99,104,105,110,103,32>>,{code,[],[<<123,114,101,112,108,121,44,32,95,125>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,39,114,101,99,101,105,118,101,39,44,32,91,123,91,39,95,39,44,39,95,39,44,32,123,114,101,112,108,121,44,39,95,39,125,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,111,116,104,101,114,32,110,111,100,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,39,114,101,99,101,105,118,101,39,44,32,91,123,91,39,36,49,39,44,32,39,95,39,44,32,39,95,39,93,44,91,123,39,61,47,61,39,44,39,36,49,39,44,123,110,111,100,101,125,125,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,32,99,97,110,32,117,115,101,32,97,108,108,32,103,117,97,114,100,32,97,110,100,32,98,111,100,121,32,102,117,110,99,116,105,111,110,115,32,101,120,99,101,112,116,32>>,{code,[],[<<99,97,108,108,101,114>>]},<<44,32>>,{code,[],[<<105,115,95,115,101,113,95,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<103,101,116,95,115,101,113,95,116,111,107,101,110>>]},<<44,32>>,{code,[],[<<115,101,116,95,115,101,113,95,116,111,107,101,110>>]},<<44,32>>,{code,[],[<<101,110,97,98,108,101,95,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<100,105,115,97,98,108,101,95,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<116,114,97,99,101>>]},<<44,32>>,{code,[],[<<115,105,108,101,110,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<112,114,111,99,101,115,115,95,100,117,109,112>>]},<<46>>]}]},{p,[],[<<70,97,105,108,115,32,98,121,32,114,97,105,115,105,110,103,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,97,110,32,97,114,103,117,109,101,110,116,32,105,115,32,105,110,118,97,108,105,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,32,104,97,115,32,101,120,99,101,115,115,105,118,101,32,110,101,115,116,105,110,103,32,119,104,105,99,104,32,99,97,117,115,101,115,32,115,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,101,120,104,97,117,115,116,105,111,110,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,115,99,104,101,100,95,116,104,114,101,97,100,95,115,116,97,99,107,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<83,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,57,57,51>>,signature => [{attribute,2725,spec,{{erlang,trace_pattern,3},[{type,2728,bounded_fun,[{type,2728,'fun',[{type,2728,product,[{atom,2728,'receive'},{var,2728,'MatchSpec'},{type,2728,nil,[]}]},{type,2728,non_neg_integer,[]}]},[{type,2729,constraint,[{atom,2729,is_subtype},[{var,2729,'MatchSpec'},{type,2729,union,[{ann_type,2729,[{var,2729,'MatchSpecList'},{user_type,2729,trace_match_spec,[]}]},{type,2730,boolean,[]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,trace_pattern,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2725}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]},{li,[{name,<<116,114,97,99,101,95,112,97,116,116,101,114,110,95,102,108,97,103>>}],[]},{li,[{name,<<116,114,97,99,101,95,112,97,116,116,101,114,110,95,109,102,97>>}],[]}]},{p,[],[<<69,110,97,98,108,101,115,32,111,114,32,100,105,115,97,98,108,101,115,32>>,{em,[],[<<99,97,108,108,32,116,114,97,99,105,110,103>>]},<<32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,102,117,110,99,116,105,111,110,115,46,32,77,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<32,116,111,32,115,101,116,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<67,111,110,99,101,112,116,117,97,108,108,121,44,32,99,97,108,108,32,116,114,97,99,105,110,103,32,119,111,114,107,115,32,97,115,32,102,111,108,108,111,119,115,46,32,73,110,115,105,100,101,32,116,104,101,32,69,114,108,97,110,103,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,44,32,97,32,115,101,116,32,111,102,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,97,32,115,101,116,32,111,102,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,116,111,32,98,101,32,116,114,97,99,101,100,46,32,73,102,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,99,97,108,108,115,32,97,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,44,32,116,104,101,32,116,114,97,99,101,32,97,99,116,105,111,110,32,105,115,32,116,97,107,101,110,46,32,79,116,104,101,114,119,105,115,101,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46>>]},{p,[],[<<84,111,32,97,100,100,32,111,114,32,114,101,109,111,118,101,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,32,116,111,32,116,104,101,32,115,101,116,32,111,102,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<46>>]},{p,[],[<<84,111,32,97,100,100,32,111,114,32,114,101,109,111,118,101,32,102,117,110,99,116,105,111,110,115,32,116,111,32,116,104,101,32,115,101,116,32,111,102,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,115,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<46>>]},{p,[],[<<84,104,101,32,66,73,70,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<32,99,97,110,32,97,108,115,111,32,97,100,100,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,32,116,111,32,97,32,102,117,110,99,116,105,111,110,46,32,65,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,99,111,109,112,114,105,115,101,115,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,114,103,117,109,101,110,116,115,32,109,117,115,116,32,109,97,116,99,104,44,32,97,32,103,117,97,114,100,32,101,120,112,114,101,115,115,105,111,110,32,116,104,97,116,32,109,117,115,116,32,101,118,97,108,117,97,116,101,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,97,110,100,32,97,110,32,97,99,116,105,111,110,32,116,111,32,98,101,32,112,101,114,102,111,114,109,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,97,99,116,105,111,110,32,105,115,32,116,111,32,115,101,110,100,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,111,114,32,116,104,101,32,103,117,97,114,100,32,102,97,105,108,115,44,32,116,104,101,32,97,99,116,105,111,110,32,105,115,32,110,111,116,32,101,120,101,99,117,116,101,100,46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,70,65>>]},<<32,105,115,32,116,111,32,98,101,32,97,32,116,117,112,108,101,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,40,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,41,46,32,73,116,32,99,97,110,32,98,101,32,116,104,101,32,109,111,100,117,108,101,44,32,102,117,110,99,116,105,111,110,44,32,97,110,100,32,97,114,105,116,121,32,102,111,114,32,97,32,102,117,110,99,116,105,111,110,32,40,111,114,32,97,32,66,73,70,32,105,110,32,97,110,121,32,109,111,100,117,108,101,41,46,32,84,104,101,32,97,116,111,109,32>>,{code,[],[<<39,95,39>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,97,115,32,97,32,119,105,108,100,99,97,114,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,119,97,121,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,39,95,39,125>>]}]},{dd,[],[{p,[],[<<65,108,108,32,102,117,110,99,116,105,111,110,115,32,111,102,32,97,110,121,32,97,114,105,116,121,32,110,97,109,101,100,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,110,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,77,111,100,117,108,101,44,39,95,39,44,39,95,39,125>>]}]},{dd,[],[{p,[],[<<65,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,39,95,39,44,39,95,39,44,39,95,39,125>>]}]},{dd,[],[{p,[],[<<65,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,97,108,108,32,108,111,97,100,101,100,32,109,111,100,117,108,101,115,46>>]}]}]},{p,[],[<<79,116,104,101,114,32,99,111,109,98,105,110,97,116,105,111,110,115,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,39,95,39,44,65,114,105,116,121,125>>]},<<44,32,97,114,101,32,110,111,116,32,97,108,108,111,119,101,100,46,32,76,111,99,97,108,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,32,119,105,108,100,99,97,114,100,115,32,111,110,108,121,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,105,115,32,105,110,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<46>>]},{p,[],[<<73,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<77,70,65>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<44,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,110,100,32,102,108,97,103,32,108,105,115,116,32,97,114,101,32,117,115,101,100,32,111,110,32,97,108,108,32,109,111,100,117,108,101,115,32,116,104,97,116,32,97,114,101,32,110,101,119,108,121,32,108,111,97,100,101,100,46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99>>]},<<32,99,97,110,32,116,97,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,116,104,101,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<69,110,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,116,104,101,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]},{dt,[],[{code,[],[<<77,97,116,99,104,83,112,101,99,76,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46,32,65,110,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,70,111,114,32,97,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,116,115,58,109,97,116,99,104,95,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{code,[],[<<114,101,115,116,97,114,116>>]}]},{dd,[],[{p,[],[<<70,111,114,32,116,104,101,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<99,97,108,108,95,116,105,109,101>>]},<<58,32,114,101,115,116,97,114,116,115,32,116,104,101,32,101,120,105,115,116,105,110,103,32,99,111,117,110,116,101,114,115,46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32,111,116,104,101,114,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<112,97,117,115,101>>]}]},{dd,[],[{p,[],[<<70,111,114,32,116,104,101,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<99,97,108,108,95,116,105,109,101>>]},<<58,32,112,97,117,115,101,115,32,116,104,101,32,101,120,105,115,116,105,110,103,32,99,111,117,110,116,101,114,115,46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32,111,116,104,101,114,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,46>>]}]}]},{p,[],[<<80,97,114,97,109,101,116,101,114,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,118,97,108,105,100,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<103,108,111,98,97,108>>]}]},{dd,[],[{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,99,97,108,108,32,116,114,97,99,105,110,103,32,102,111,114,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,40,116,104,97,116,32,105,115,44,32,99,97,108,108,115,32,115,112,101,99,105,102,121,105,110,103,32,116,104,101,32,109,111,100,117,108,101,32,101,120,112,108,105,99,105,116,108,121,41,46,32,79,110,108,121,32,101,120,112,111,114,116,101,100,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,32,97,110,100,32,111,110,108,121,32,103,108,111,98,97,108,32,99,97,108,108,115,32,103,101,110,101,114,97,116,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32>>,{em,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<108,111,99,97,108>>]}]},{dd,[],[{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,99,97,108,108,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,84,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,115,101,110,116,32,119,104,101,110,101,118,101,114,32,97,110,121,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,99,97,108,108,101,100,44,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,104,111,119,32,116,104,101,121,32,97,114,101,32,99,97,108,108,101,100,46,32,73,102,32,102,108,97,103,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,105,115,32,115,101,116,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,97,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,97,108,115,111,32,115,101,110,116,32,119,104,101,110,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,111,32,105,116,115,32,99,97,108,108,101,114,46>>]}]},{dt,[],[{code,[],[<<109,101,116,97,32,124,32,123,109,101,116,97,44,32,80,105,100,125,32,124,32,123,109,101,116,97,44,32,84,114,97,99,101,114,77,111,100,117,108,101,44,32,84,114,97,99,101,114,83,116,97,116,101,125>>]}]},{dd,[],[{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,109,101,116,97,45,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,84,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,115,101,110,116,32,116,111,32,116,104,101,32,116,114,97,99,101,114,32,119,104,101,110,101,118,101,114,32,97,110,121,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,99,97,108,108,101,100,46,32,73,102,32,110,111,32,116,114,97,99,101,114,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<115,101,108,102,40,41>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,97,32,100,101,102,97,117,108,116,32,116,114,97,99,101,114,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<77,101,116,97,45,116,114,97,99,105,110,103,32,116,114,97,99,101,115,32,97,108,108,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,100,111,101,115,32,110,111,116,32,99,97,114,101,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,116,114,97,99,101,32,102,108,97,103,115,32,115,101,116,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]},<<44,32,116,104,101,32,116,114,97,99,101,32,102,108,97,103,115,32,97,114,101,32,105,110,115,116,101,97,100,32,102,105,120,101,100,32,116,111,32>>,{code,[],[<<91,99,97,108,108,44,32,116,105,109,101,115,116,97,109,112,93>>]},<<46>>]},{p,[],[<<84,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,114,101,116,117,114,110,95,116,114,97,99,101,125>>]},<<32,119,111,114,107,115,32,119,105,116,104,32,109,101,116,97,45,116,114,97,99,101,32,97,110,100,32,115,101,110,100,115,32,105,116,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,116,111,32,116,104,101,32,115,97,109,101,32,116,114,97,99,101,114,46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,116,114,117,101>>]},<<41,32,111,114,32,115,116,111,112,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,102,97,108,115,101>>]},<<41,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,70,111,114,32,101,118,101,114,121,32,102,117,110,99,116,105,111,110,44,32,97,32,99,111,117,110,116,101,114,32,105,115,32,105,110,99,114,101,109,101,110,116,101,100,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,44,32,105,110,32,97,110,121,32,112,114,111,99,101,115,115,46,32,78,111,32,112,114,111,99,101,115,115,32,116,114,97,99,101,32,102,108,97,103,115,32,110,101,101,100,32,116,111,32,98,101,32,97,99,116,105,118,97,116,101,100,46>>]},{p,[],[<<73,102,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,105,115,32,115,116,97,114,116,101,100,32,119,104,105,108,101,32,97,108,114,101,97,100,121,32,114,117,110,110,105,110,103,44,32,116,104,101,32,99,111,117,110,116,32,105,115,32,114,101,115,116,97,114,116,101,100,32,102,114,111,109,32,122,101,114,111,46,32,84,111,32,112,97,117,115,101,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,44,32,117,115,101,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,112,97,117,115,101>>]},<<46,32,80,97,117,115,101,100,32,97,110,100,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,32,99,97,110,32,98,101,32,114,101,115,116,97,114,116,101,100,32,102,114,111,109,32,122,101,114,111,32,119,105,116,104,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,114,101,115,116,97,114,116>>]},<<46>>]},{p,[],[<<84,111,32,114,101,97,100,32,116,104,101,32,99,111,117,110,116,101,114,32,118,97,108,117,101,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,116,114,117,101>>]},<<41,32,111,114,32,115,116,111,112,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,102,97,108,115,101>>]},<<41,32,99,97,108,108,32,116,105,109,101,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,70,111,114,32,101,118,101,114,121,32,102,117,110,99,116,105,111,110,44,32,97,32,99,111,117,110,116,101,114,32,105,115,32,105,110,99,114,101,109,101,110,116,101,100,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,46,32,84,105,109,101,32,115,112,101,110,116,32,105,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,97,99,99,117,109,117,108,97,116,101,100,32,105,110,32,116,119,111,32,111,116,104,101,114,32,99,111,117,110,116,101,114,115,44,32,115,101,99,111,110,100,115,32,97,110,100,32,109,105,99,114,111,115,101,99,111,110,100,115,46,32,84,104,101,32,99,111,117,110,116,101,114,115,32,97,114,101,32,115,116,111,114,101,100,32,102,111,114,32,101,97,99,104,32,99,97,108,108,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,102,32,99,97,108,108,32,116,105,109,101,32,116,114,97,99,105,110,103,32,105,115,32,115,116,97,114,116,101,100,32,119,104,105,108,101,32,97,108,114,101,97,100,121,32,114,117,110,110,105,110,103,44,32,116,104,101,32,99,111,117,110,116,32,97,110,100,32,116,105,109,101,32,114,101,115,116,97,114,116,32,102,114,111,109,32,122,101,114,111,46,32,84,111,32,112,97,117,115,101,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,44,32,117,115,101,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,112,97,117,115,101>>]},<<46,32,80,97,117,115,101,100,32,97,110,100,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,32,99,97,110,32,98,101,32,114,101,115,116,97,114,116,101,100,32,102,114,111,109,32,122,101,114,111,32,119,105,116,104,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,114,101,115,116,97,114,116>>]},<<46>>]},{p,[],[<<84,111,32,114,101,97,100,32,116,104,101,32,99,111,117,110,116,101,114,32,118,97,108,117,101,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]}]},{p,[],[<<84,104,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,97,110,100,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,97,114,101,32,109,117,116,117,97,108,108,121,32,101,120,99,108,117,115,105,118,101,44,32,97,110,100,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,32,40,105,102,32,110,111,32,111,112,116,105,111,110,115,32,97,114,101,32,115,112,101,99,105,102,105,101,100,41,46,32,84,104,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<109,101,116,97>>]},<<32,112,101,114,102,111,114,109,32,97,32,107,105,110,100,32,111,102,32,108,111,99,97,108,32,116,114,97,99,105,110,103,44,32,97,110,100,32,99,97,110,110,111,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<46,32,65,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,103,108,111,98,97,108,108,121,32,111,114,32,108,111,99,97,108,108,121,32,116,114,97,99,101,100,46,32,73,102,32,103,108,111,98,97,108,32,116,114,97,99,105,110,103,32,105,115,32,115,112,101,99,105,102,105,101,100,32,102,111,114,32,97,32,115,101,116,32,111,102,32,102,117,110,99,116,105,111,110,115,44,32,116,104,101,110,32,108,111,99,97,108,44,32,109,101,116,97,44,32,99,97,108,108,32,116,105,109,101,44,32,97,110,100,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,102,111,114,32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,101,116,32,111,102,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,115,32,105,115,32,100,105,115,97,98,108,101,100,44,32,97,110,100,32,99,111,110,118,101,114,115,101,108,121,46>>]},{p,[],[<<87,104,101,110,32,100,105,115,97,98,108,105,110,103,32,116,114,97,99,101,44,32,116,104,101,32,111,112,116,105,111,110,32,109,117,115,116,32,109,97,116,99,104,32,116,104,101,32,116,121,112,101,32,111,102,32,116,114,97,99,101,32,115,101,116,32,111,110,32,116,104,101,32,102,117,110,99,116,105,111,110,46,32,84,104,97,116,32,105,115,44,32,108,111,99,97,108,32,116,114,97,99,105,110,103,32,109,117,115,116,32,98,101,32,100,105,115,97,98,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,97,110,100,32,103,108,111,98,97,108,32,116,114,97,99,105,110,103,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,40,111,114,32,110,111,32,111,112,116,105,111,110,41,44,32,97,110,100,32,115,111,32,111,110,46>>]},{p,[],[<<80,97,114,116,32,111,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,108,105,115,116,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,100,105,114,101,99,116,108,121,46,32,73,102,32,97,32,102,117,110,99,116,105,111,110,32,104,97,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,105,116,32,99,97,110,32,98,101,32,114,101,112,108,97,99,101,100,32,119,105,116,104,32,97,32,110,101,119,32,111,110,101,46,32,84,111,32,99,104,97,110,103,101,32,97,110,32,101,120,105,115,116,105,110,103,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,117,115,101,32,116,104,101,32,66,73,70,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,105,110,102,111,47,50>>]}]},<<32,116,111,32,114,101,116,114,105,101,118,101,32,116,104,101,32,101,120,105,115,116,105,110,103,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,105,110,103,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<77,70,65>>]},<<46,32,84,104,105,115,32,105,115,32,122,101,114,111,32,105,102,32,110,111,110,101,32,109,97,116,99,104,101,100,46>>]},{p,[],[<<70,97,105,108,115,32,98,121,32,114,97,105,115,105,110,103,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,97,110,32,97,114,103,117,109,101,110,116,32,105,115,32,105,110,118,97,108,105,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,32,104,97,115,32,101,120,99,101,115,115,105,118,101,32,110,101,115,116,105,110,103,32,119,104,105,99,104,32,99,97,117,115,101,115,32,115,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,101,120,104,97,117,115,116,105,111,110,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,115,99,104,101,100,95,116,104,114,101,97,100,95,115,116,97,99,107,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<83,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,48,56,49>>,signature => [{attribute,2725,spec,{{erlang,trace_pattern,3},[{type,2731,bounded_fun,[{type,2731,'fun',[{type,2731,product,[{var,2731,'MFA'},{var,2731,'MatchSpec'},{var,2731,'FlagList'}]},{type,2731,non_neg_integer,[]}]},[{type,2732,constraint,[{atom,2732,is_subtype},[{var,2732,'MFA'},{user_type,2732,trace_pattern_mfa,[]}]]},{type,2733,constraint,[{atom,2733,is_subtype},[{var,2733,'MatchSpec'},{type,2733,union,[{ann_type,2733,[{var,2733,'MatchSpecList'},{user_type,2733,trace_match_spec,[]}]},{type,2734,boolean,[]},{atom,2735,restart},{atom,2736,pause}]}]]},{type,2737,constraint,[{atom,2737,is_subtype},[{var,2737,'FlagList'},{type,2737,list,[{user_type,2737,trace_pattern_flag,[]}]}]]}]]}]}}]}},{{function,trunc,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2049}],[<<116,114,117,110,99,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,117,110,99,97,116,101,115,32,116,104,101,32,100,101,99,105,109,97,108,115,32,111,102,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,53,46,55,41,46,10,53>>]}]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,45,53,46,55,41,46,10,45,53>>]}]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,53,41,46,10,53>>]}]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41,46,10,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]}]},{p,[],[<<73,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<116,114,117,110,99,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41>>]},<<32,101,118,97,108,117,97,116,101,115,32,116,111,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]},<<46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,116,104,97,116,32,116,104,101,32,110,117,109,98,101,114,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48>>]},<<32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,73,110,115,116,101,97,100,44,32,116,104,101,32,102,108,111,97,116,32,108,105,116,101,114,97,108,32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56,46,48>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,99,108,111,115,101,115,116,32,110,117,109,98,101,114,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,108,111,97,116,95,114,101,112,114,101,115,101,110,116,97,116,105,111,110,95,112,114,111,98,108,101,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,70,108,111,97,116,105,110,103,32,80,111,105,110,116,32,78,117,109,98,101,114,115>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,50,56,56>>,signature => [{attribute,2049,spec,{{trunc,1},[{type,2049,bounded_fun,[{type,2049,'fun',[{type,2049,product,[{var,2049,'Number'}]},{type,2049,integer,[]}]},[{type,2050,constraint,[{atom,2050,is_subtype},[{var,2050,'Number'},{type,2050,number,[]}]]}]]}]}}]}},{{function,tuple_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2056}],[<<116,117,112,108,101,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,116,104,97,116,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,105,110,32>>,{code,[],[<<84,117,112,108,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,117,112,108,101,95,115,105,122,101,40,123,109,111,114,110,105,44,32,109,117,108,108,101,44,32,98,119,97,110,103,101,125,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,49,57>>,signature => [{attribute,2056,spec,{{tuple_size,1},[{type,2056,bounded_fun,[{type,2056,'fun',[{type,2056,product,[{var,2056,'Tuple'}]},{type,2056,non_neg_integer,[]}]},[{type,2057,constraint,[{atom,2057,is_subtype},[{var,2057,'Tuple'},{type,2057,tuple,any}]]}]]}]}}]}},{{function,tuple_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2747}],[<<116,117,112,108,101,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<84,117,112,108,101>>]},<<46,32>>,{code,[],[<<84,117,112,108,101>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,69,114,108,97,110,103,32,116,101,114,109,115,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,117,112,108,101,95,116,111,95,108,105,115,116,40,123,115,104,97,114,101,44,32,123,39,69,114,105,99,115,115,111,110,95,66,39,44,32,49,54,51,125,125,41,46,10,91,115,104,97,114,101,44,123,39,69,114,105,99,115,115,111,110,95,66,39,44,49,54,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,51,50>>,signature => [{attribute,2747,spec,{{tuple_to_list,1},[{type,2747,bounded_fun,[{type,2747,'fun',[{type,2747,product,[{var,2747,'Tuple'}]},{type,2747,list,[{type,2747,term,[]}]}]},[{type,2748,constraint,[{atom,2748,is_subtype},[{var,2748,'Tuple'},{type,2748,tuple,any}]]}]]}]}}]}},{{function,unalias,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,766}],[<<117,110,97,108,105,97,115,47,49>>],#{<<101,110>> => [{p,[],[<<68,101,97,99,116,105,118,97,116,101,32,116,104,101,32,97,108,105,97,115,32>>,{code,[],[<<65,108,105,97,115>>]},<<32,112,114,101,118,105,111,117,115,108,121,32,99,114,101,97,116,101,100,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,65,110,32,97,108,105,97,115,32,99,97,110,32,102,111,114,32,101,120,97,109,112,108,101,32,98,101,32,99,114,101,97,116,101,100,32,118,105,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,97,108,105,97,115,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,108,105,97,115,47,48>>]}]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,51>>]}]},<<46,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<32,119,105,108,108,32,97,108,119,97,121,115,32,100,101,97,99,116,105,118,97,116,101,32,116,104,101,32,97,108,105,97,115,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,111,112,116,105,111,110,115,32,117,115,101,100,32,119,104,101,110,32,99,114,101,97,116,105,110,103,32,116,104,101,32,97,108,105,97,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,114,117,101,32,105,102,32>>,{code,[],[<<65,108,105,97,115>>]},<<32,119,97,115,32,97,32,99,117,114,114,101,110,116,108,121,32,97,99,116,105,118,101,32,97,108,105,97,115,32,102,111,114,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,101,115,59,32,111,116,104,101,114,119,105,115,101,44,32,102,97,108,115,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,52,53>>,signature => [{attribute,766,spec,{{unalias,1},[{type,766,bounded_fun,[{type,766,'fun',[{type,766,product,[{var,766,'Alias'}]},{type,766,boolean,[]}]},[{type,767,constraint,[{atom,767,is_subtype},[{var,767,'Alias'},{type,767,reference,[]}]]}]]}]}}],since => <<79,84,80,32,64,79,84,80,45,49,54,55,49,56,64>>}},{{function,unique_integer,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1529}],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,48>>],#{<<101,110>> => [{p,[],[<<71,101,110,101,114,97,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,97,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<105,110,116,101,103,101,114,32,117,110,105,113,117,101,32,111,110,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101>>]},<<46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,54,53>>,signature => [{attribute,1529,spec,{{erlang,unique_integer,0},[{type,1529,'fun',[{type,1529,product,[]},{type,1529,integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,unique_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1522}],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<71,101,110,101,114,97,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,97,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<105,110,116,101,103,101,114,32,117,110,105,113,117,101,32,111,110,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101>>]},<<46,32,84,104,101,32,105,110,116,101,103,101,114,32,105,115,32,117,110,105,113,117,101,32,105,110,32,116,104,101,32,115,101,110,115,101,32,116,104,97,116,32,116,104,105,115,32,66,73,70,44,32,117,115,105,110,103,32,116,104,101,32,115,97,109,101,32,115,101,116,32,111,102,32,109,111,100,105,102,105,101,114,115,44,32,100,111,101,115,32,110,111,116,32,114,101,116,117,114,110,32,116,104,101,32,115,97,109,101,32,105,110,116,101,103,101,114,32,109,111,114,101,32,116,104,97,110,32,111,110,99,101,32,111,110,32,116,104,101,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,69,97,99,104,32,105,110,116,101,103,101,114,32,118,97,108,117,101,32,99,97,110,32,111,102,32,99,111,117,114,115,101,32,98,101,32,99,111,110,115,116,114,117,99,116,101,100,32,98,121,32,111,116,104,101,114,32,109,101,97,110,115,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,119,104,101,110,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,112,97,115,115,101,100,32,97,115,32>>,{code,[],[<<77,111,100,105,102,105,101,114,76,105,115,116>>]},<<44,32,98,111,116,104,32,110,101,103,97,116,105,118,101,32,97,110,100,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,115,32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,46,32,84,104,105,115,32,116,111,32,117,115,101,32,116,104,101,32,114,97,110,103,101,32,111,102,32,105,110,116,101,103,101,114,115,32,116,104,97,116,32,100,111,32,110,111,116,32,110,101,101,100,32,104,101,97,112,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,46,32,66,121,32,100,101,102,97,117,108,116,32,116,104,101,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,115,32,97,114,101,32,97,108,115,111,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,117,110,105,113,117,101,44,32,116,104,97,116,32,105,115,44,32,97,110,121,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,32,99,97,110,32,98,101,32,115,109,97,108,108,101,114,32,111,114,32,108,97,114,103,101,114,32,116,104,97,110,32,112,114,101,118,105,111,117,115,108,121,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,115,46>>]},{p,[],[{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,58>>]},{dl,[],[{dt,[],[<<112,111,115,105,116,105,118,101>>]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,111,110,108,121,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,115,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,98,121,32,112,97,115,115,105,110,103,32,116,104,101,32>>,{code,[],[<<112,111,115,105,116,105,118,101>>]},<<32,109,111,100,105,102,105,101,114,32,121,111,117,32,119,105,108,108,32,103,101,116,32,104,101,97,112,32,97,108,108,111,99,97,116,101,100,32,105,110,116,101,103,101,114,115,32,40,98,105,103,110,117,109,115,41,32,113,117,105,99,107,101,114,46>>]}]},{dt,[],[<<109,111,110,111,116,111,110,105,99>>]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,116,114,105,99,116,108,121,95,77,111,110,111,116,111,110,105,99,97,108,108,121,95,73,110,99,114,101,97,115,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103>>]},<<32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,99,114,101,97,116,105,111,110,32,116,105,109,101,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,105,110,116,101,103,101,114,32,114,101,116,117,114,110,101,100,32,105,115,32,97,108,119,97,121,115,32,108,97,114,103,101,114,32,116,104,97,110,32,112,114,101,118,105,111,117,115,108,121,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,115,32,111,110,32,116,104,101,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46>>]},{p,[],[<<84,104,101,115,101,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,111,114,100,101,114,32,98,101,116,119,101,101,110,32,101,118,101,110,116,115,32,111,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,84,104,97,116,32,105,115,44,32,105,102,32,98,111,116,104,32>>,{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]},<<32,97,110,100,32>>,{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]},<<32,97,114,101,32,101,120,101,99,117,116,101,100,32,98,121,32,100,105,102,102,101,114,101,110,116,32,112,114,111,99,101,115,115,101,115,32,40,111,114,32,116,104,101,32,115,97,109,101,32,112,114,111,99,101,115,115,41,32,111,110,32,116,104,101,32,115,97,109,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,32,97,110,100,32>>,{code,[],[<<88,32,60,32,89>>]},<<44,32,119,101,32,107,110,111,119,32,116,104,97,116,32>>,{code,[],[<<88>>]},<<32,119,97,115,32,99,114,101,97,116,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<89>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<83,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,118,97,108,117,101,115,32,97,114,101,32,105,110,104,101,114,101,110,116,108,121,32,113,117,105,116,101,32,101,120,112,101,110,115,105,118,101,32,116,111,32,103,101,110,101,114,97,116,101,32,97,110,100,32,115,99,97,108,101,115,32,112,111,111,114,108,121,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,118,97,108,117,101,115,32,110,101,101,100,32,116,111,32,98,101,32,115,121,110,99,104,114,111,110,105,122,101,100,32,98,101,116,119,101,101,110,32,67,80,85,32,99,111,114,101,115,46,32,84,104,97,116,32,105,115,44,32,100,111,32,110,111,116,32,112,97,115,115,32,116,104,101,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99>>]},<<32,109,111,100,105,102,105,101,114,32,117,110,108,101,115,115,32,121,111,117,32,114,101,97,108,108,121,32,110,101,101,100,32,115,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,118,97,108,117,101,115,46>>]}]}]}]},{p,[],[<<65,108,108,32,118,97,108,105,100,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,32,99,97,110,32,98,101,32,99,111,109,98,105,110,101,100,46,32,82,101,112,101,97,116,101,100,32,40,118,97,108,105,100,41,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,32,105,110,32,116,104,101,32>>,{code,[],[<<77,111,100,105,102,105,101,114,76,105,115,116>>]},<<32,97,114,101,32,105,103,110,111,114,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,115,101,116,32,111,102,32,105,110,116,101,103,101,114,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>]},<<32,117,115,105,110,103,32,100,105,102,102,101,114,101,110,116,32,115,101,116,115,32,111,102,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,32>>,{em,[],[<<119,105,108,108,32,111,118,101,114,108,97,112>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,98,121,32,99,97,108,108,105,110,103,32>>,{code,[],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]},<<44,32,97,110,100,32>>,{code,[],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,112,111,115,105,116,105,118,101,44,32,109,111,110,111,116,111,110,105,99,93,41>>]},<<32,114,101,112,101,97,116,101,100,108,121,44,32,121,111,117,32,119,105,108,108,32,101,118,101,110,116,117,97,108,108,121,32,115,101,101,32,115,111,109,101,32,105,110,116,101,103,101,114,115,32,116,104,97,116,32,97,114,101,32,114,101,116,117,114,110,101,100,32,98,121,32,98,111,116,104,32,99,97,108,108,115,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<105,102,32>>,{code,[],[<<77,111,100,105,102,105,101,114,76,105,115,116>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<105,102,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<32,105,115,32,110,111,116,32,97,32,118,97,108,105,100,32,109,111,100,105,102,105,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,55,56>>,signature => [{attribute,1522,spec,{{erlang,unique_integer,1},[{type,1522,bounded_fun,[{type,1522,'fun',[{type,1522,product,[{var,1522,'ModifierList'}]},{type,1522,integer,[]}]},[{type,1523,constraint,[{atom,1523,is_subtype},[{var,1523,'ModifierList'},{type,1523,list,[{var,1523,'Modifier'}]}]]},{type,1524,constraint,[{atom,1524,is_subtype},[{var,1524,'Modifier'},{type,1524,union,[{atom,1524,positive},{atom,1524,monotonic}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,universaltime,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2062}],[<<117,110,105,118,101,114,115,97,108,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,97,99,99,111,114,100,105,110,103,32,116,111,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,32,105,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125,44,32,123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125,125>>]},<<32,105,102,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,117,110,105,118,101,114,115,97,108,116,105,109,101,40,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,40,41>>]},<<46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,117,110,105,118,101,114,115,97,108,116,105,109,101,40,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,49,56,44,52,51,125,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,52,54,48>>,signature => [{attribute,2062,spec,{{erlang,universaltime,0},[{type,2062,bounded_fun,[{type,2062,'fun',[{type,2062,product,[]},{var,2062,'DateTime'}]},[{type,2063,constraint,[{atom,2063,is_subtype},[{var,2063,'DateTime'},{remote_type,2063,[{atom,2063,calendar},{atom,2063,datetime},[]]}]]}]]}]}}]}},{{function,universaltime_to_localtime,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2874}],[<<117,110,105,118,101,114,115,97,108,116,105,109,101,95,116,111,95,108,111,99,97,108,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,116,111,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,105,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125,44,32,123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125,125>>]},<<32,105,102,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32,110,111,32,99,111,110,118,101,114,115,105,111,110,32,105,115,32,100,111,110,101,44,32,97,110,100,32>>,{code,[],[<<85,110,105,118,101,114,115,97,108,116,105,109,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,117,110,105,118,101,114,115,97,108,116,105,109,101,95,116,111,95,108,111,99,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,49,56,44,52,51,125,125,41,46,10,123,123,49,57,57,54,44,49,49,44,55,125,44,123,49,53,44,49,56,44,52,51,125,125>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<85,110,105,118,101,114,115,97,108,116,105,109,101>>]},<<32,100,101,110,111,116,101,115,32,97,110,32,105,110,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,52,55,57>>,signature => [{attribute,2874,spec,{{erlang,universaltime_to_localtime,1},[{type,2874,bounded_fun,[{type,2874,'fun',[{type,2874,product,[{var,2874,'Universaltime'}]},{var,2874,'Localtime'}]},[{type,2875,constraint,[{atom,2875,is_subtype},[{var,2875,'Localtime'},{remote_type,2875,[{atom,2875,calendar},{atom,2875,datetime},[]]}]]},{type,2876,constraint,[{atom,2876,is_subtype},[{var,2876,'Universaltime'},{remote_type,2876,[{atom,2876,calendar},{atom,2876,datetime},[]]}]]}]]}]}}]}},{{function,unlink,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2074}],[<<117,110,108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,109,111,118,101,115,32,116,104,101,32,108,105,110,107,44,32,105,102,32,116,104,101,114,101,32,105,115,32,111,110,101,44,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32>>,{code,[],[<<73,100>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,97,110,100,32,100,111,101,115,32,110,111,116,32,102,97,105,108,44,32,101,118,101,110,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,108,105,110,107,32,116,111,32>>,{code,[],[<<73,100>>]},<<44,32,111,114,32,105,102,32>>,{code,[],[<<73,100>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]},{p,[],[<<79,110,99,101,32>>,{code,[],[<<117,110,108,105,110,107,40,73,100,41>>]},<<32,104,97,115,32,114,101,116,117,114,110,101,100,44,32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,116,104,101,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,101,114,32,97,110,100,32,116,104,101,32,101,110,116,105,116,121,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32>>,{code,[],[<<73,100>>]},<<32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,111,110,32,116,104,101,32,99,97,108,108,101,114,32,105,110,32,116,104,101,32,102,117,116,117,114,101,32,40,117,110,108,101,115,115,32,116,104,101,32,108,105,110,107,32,105,115,32,115,101,116,117,112,32,97,103,97,105,110,41,46,32,73,102,32,116,104,101,32,99,97,108,108,101,114,32,105,115,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,44,32,97,110,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,73,100,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,32,102,114,111,109,32,116,104,101,32,108,105,110,107,32,99,97,110,32,104,97,118,101,32,98,101,101,110,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,99,97,108,108,101,114,39,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,73,100,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,32,99,97,110,32,98,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,108,105,110,107,44,32,98,117,116,32,99,97,110,32,97,108,115,111,32,98,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<73,100>>]},<<32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,120,105,116,47,50>>]},<<46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32>>,{em,[],[<<99,97,110>>]},<<32,98,101,32,97,112,112,114,111,112,114,105,97,116,101,32,116,111,32,99,108,101,97,110,32,117,112,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,104,101,110,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,32,97,102,116,101,114,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,108,105,110,107,40,73,100,41>>]},<<44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<117,110,108,105,110,107,40,73,100,41,44,10,114,101,99,101,105,118,101,10,32,32,32,32,123,39,69,88,73,84,39,44,32,73,100,44,32,95,125,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,97,102,116,101,114,32,48,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,101,110,100>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,32,40,69,82,84,83,32,53,46,53,41,32>>,{code,[],[<<117,110,108,105,110,107,47,49>>]},<<32,98,101,104,97,118,101,100,32,99,111,109,112,108,101,116,101,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,108,105,110,107,32,119,97,115,32,97,99,116,105,118,101,32,117,110,116,105,108,32,116,104,101,32,34,117,110,108,105,110,107,32,115,105,103,110,97,108,34,32,114,101,97,99,104,101,100,32,116,104,101,32,108,105,110,107,101,100,32,101,110,116,105,116,121,46,32,84,104,105,115,32,104,97,100,32,97,110,32,117,110,100,101,115,105,114,97,98,108,101,32,101,102,102,101,99,116,44,32,97,115,32,121,111,117,32,99,111,117,108,100,32,110,101,118,101,114,32,107,110,111,119,32,119,104,101,110,32,121,111,117,32,119,101,114,101,32,103,117,97,114,97,110,116,101,101,100,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,98,101,32,101,102,102,101,99,116,101,100,32,98,121,32,116,104,101,32,108,105,110,107,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,118,105,101,119,101,100,32,97,115,32,116,119,111,32,99,111,109,98,105,110,101,100,32,111,112,101,114,97,116,105,111,110,115,58,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,32,115,101,110,100,32,97,110,32,34,117,110,108,105,110,107,32,115,105,103,110,97,108,34,32,116,111,32,116,104,101,32,108,105,110,107,101,100,32,101,110,116,105,116,121,32,97,110,100,32,105,103,110,111,114,101,32,97,110,121,32,102,117,116,117,114,101,32,114,101,115,117,108,116,115,32,111,102,32,116,104,101,32,108,105,110,107,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,52,57,56>>,signature => [{attribute,2074,spec,{{unlink,1},[{type,2074,bounded_fun,[{type,2074,'fun',[{type,2074,product,[{var,2074,'Id'}]},{atom,2074,true}]},[{type,2075,constraint,[{atom,2075,is_subtype},[{var,2075,'Id'},{type,2075,union,[{type,2075,pid,[]},{type,2075,port,[]}]}]]}]]}]}}]}},{{function,unregister,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2080}],[<<117,110,114,101,103,105,115,116,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,109,111,118,101,115,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,114,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,117,110,114,101,103,105,115,116,101,114,40,100,98,41,46,10,116,114,117,101>>]}]},{p,[],[<<85,115,101,114,115,32,97,114,101,32,97,100,118,105,115,101,100,32,110,111,116,32,116,111,32,117,110,114,101,103,105,115,116,101,114,32,115,121,115,116,101,109,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,105,115,32,110,111,116,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,53,52,52>>,signature => [{attribute,2080,spec,{{unregister,1},[{type,2080,bounded_fun,[{type,2080,'fun',[{type,2080,product,[{var,2080,'RegName'}]},{atom,2080,true}]},[{type,2081,constraint,[{atom,2081,is_subtype},[{var,2081,'RegName'},{type,2081,atom,[]}]]}]]}]}}]}},{{function,whereis,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2086}],[<<119,104,101,114,101,105,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,119,105,116,104,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,110,97,109,101,32,105,115,32,110,111,116,32,114,101,103,105,115,116,101,114,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,119,104,101,114,101,105,115,40,100,98,41,46,10,60,48,46,52,51,46,48,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,53,54,48>>,signature => [{attribute,2086,spec,{{whereis,1},[{type,2086,bounded_fun,[{type,2086,'fun',[{type,2086,product,[{var,2086,'RegName'}]},{type,2086,union,[{type,2086,pid,[]},{type,2086,port,[]},{atom,2086,undefined}]}]},[{type,2087,constraint,[{atom,2087,is_subtype},[{var,2087,'RegName'},{type,2087,atom,[]}]]}]]}]}}]}},{{function,yield,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3418}],[<<121,105,101,108,100,47,48>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,103,105,118,101,32,111,116,104,101,114,32,112,114,111,99,101,115,115,101,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,111,114,32,104,105,103,104,101,114,32,112,114,105,111,114,105,116,121,32,40,105,102,32,97,110,121,41,32,97,32,99,104,97,110,99,101,32,116,111,32,101,120,101,99,117,116,101,32,98,101,102,111,114,101,32,114,101,116,117,114,110,105,110,103,46,32,84,104,101,114,101,32,105,115,32,110,111,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,97,110,121,32,111,116,104,101,114,32,112,114,111,99,101,115,115,32,114,117,110,115,32,98,101,116,119,101,101,110,32,116,104,101,32,105,110,118,111,99,97,116,105,111,110,32,97,110,100,32,114,101,116,117,114,110,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,121,105,101,108,100,47,48>>]},<<46>>]},{p,[],[<<83,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,111,114,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,114,101,99,101,105,118,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<114,101,99,101,105,118,101,45,97,102,116,101,114>>]},<<32,101,120,112,114,101,115,115,105,111,110,115>>]},<<32,102,111,114,32,104,111,119,32,116,111,32,109,97,107,101,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,115,108,101,101,112,32,102,111,114,32,97,32,115,112,101,99,105,102,105,99,32,110,117,109,98,101,114,32,111,102,32,109,105,108,108,105,115,101,99,111,110,100,115,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,115,101,108,100,111,109,32,111,114,32,110,101,118,101,114,32,97,110,121,32,110,101,101,100,32,116,111,32,117,115,101,32,116,104,105,115,32,66,73,70,46,32,85,115,105,110,103,32,116,104,105,115,32,66,73,70,32,119,105,116,104,111,117,116,32,97,32,116,104,111,114,111,117,103,104,32,103,114,97,115,112,32,111,102,32,104,111,119,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,119,111,114,107,115,32,99,97,110,32,99,97,117,115,101,32,112,101,114,102,111,114,109,97,110,99,101,32,100,101,103,114,97,100,97,116,105,111,110,46,32,84,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,112,117,116,115,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,108,97,115,116,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,99,104,101,100,117,108,101,114,39,115,32,113,117,101,117,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,32,111,102,32,116,104,101,32,115,97,109,101,32,112,114,105,111,114,105,116,121,32,97,115,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,53,55,52>>,signature => [{attribute,3418,spec,{{erlang,yield,0},[{type,3418,'fun',[{type,3418,product,[]},{atom,3418,true}]}]}}]}},{{type,ext_binary,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,87}],[<<45,116,121,112,101,32,101,120,116,95,98,105,110,97,114,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,44,32,115,116,114,117,99,116,117,114,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]}]},#{signature => [{attribute,87,type,{ext_binary,{type,87,binary,[]},[]}}]}},{{type,ext_iovec,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,88}],[<<45,116,121,112,101,32,101,120,116,95,105,111,118,101,99,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,116,101,114,109,32,111,102,32,116,121,112,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<105,111,118,101,99,40,41>>]}]},<<44,32,115,116,114,117,99,116,117,114,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]}]},#{signature => [{attribute,88,type,{ext_iovec,{user_type,88,iovec,[]},[]}}]}},{{type,iovec,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,119}],[<<45,116,121,112,101,32,105,111,118,101,99,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,108,105,115,116,32,111,102,32,98,105,110,97,114,105,101,115,46,32,84,104,105,115,32,100,97,116,97,116,121,112,101,32,105,115,32,117,115,101,102,117,108,32,116,111,32,117,115,101,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,110,105,102,35,101,110,105,102,95,105,110,115,112,101,99,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,110,105,102,95,105,110,115,112,101,99,116,95,105,111,118,101,99>>]}]},<<46>>]}]},#{signature => [{attribute,119,type,{iovec,{type,119,list,[{type,119,binary,[]}]},[]}}]}},{{type,message_queue_data,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2353}],[<<45,116,121,112,101,32,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]},#{signature => [{attribute,2353,type,{message_queue_data,{type,2354,union,[{atom,2354,off_heap},{atom,2354,on_heap}]},[]}}]}},{{type,monitor_option,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1397}],[<<45,116,121,112,101,32,109,111,110,105,116,111,114,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,51>>]}]},<<46>>]}]},#{signature => [{attribute,1397,type,{monitor_option,{type,1397,union,[{type,1397,tuple,[{atom,1397,alias},{type,1397,union,[{atom,1397,explicit_unalias},{atom,1397,demonitor},{atom,1397,reply_demonitor}]}]},{type,1398,tuple,[{atom,1398,tag},{type,1398,term,[]}]}]},[]}}]}},{{type,timestamp,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,89}],[<<45,116,121,112,101,32,116,105,109,101,115,116,97,109,112,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,115,116,97,109,112,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,115,116,97,109,112,47,48>>]}]},<<46>>]}]},#{signature => [{attribute,89,type,{timestamp,{type,89,tuple,[{ann_type,89,[{var,89,'MegaSecs'},{type,89,non_neg_integer,[]}]},{ann_type,90,[{var,90,'Secs'},{type,90,non_neg_integer,[]}]},{ann_type,91,[{var,91,'MicroSecs'},{type,91,non_neg_integer,[]}]}]},[]}}]}},{{type,time_unit,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,93}],[<<45,116,121,112,101,32,116,105,109,101,95,117,110,105,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{a,[{id,<<116,121,112,101,95,116,105,109,101,95,117,110,105,116>>}],[]},{p,[],[<<83,117,112,112,111,114,116,101,100,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<80,97,114,116,115,80,101,114,83,101,99,111,110,100,32,58,58,32,105,110,116,101,103,101,114,40,41,32,62,61,32,49>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,117,110,105,116,32,101,120,112,114,101,115,115,101,100,32,105,110,32,112,97,114,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,101,113,117,97,108,115,32>>,{code,[],[<<49,47,80,97,114,116,115,80,101,114,83,101,99,111,110,100>>]},<<32,115,101,99,111,110,100,46>>]}]},{dt,[],[{code,[],[<<115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,108,108,105,115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49,48,48,48>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,99,114,111,115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49,48,48,48,95,48,48,48>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,97,110,111,115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49,48,48,48,95,48,48,48,95,48,48,48>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,97,116,105,118,101>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,110,97,116,105,118,101,32,116,105,109,101,32,117,110,105,116,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,44,32,97,110,100,32,114,101,109,97,105,110,115,32,116,104,101,32,115,97,109,101,32,117,110,116,105,108,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,116,101,114,109,105,110,97,116,101,115,46,32,73,102,32,97,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,115,116,111,112,112,101,100,32,97,110,100,32,116,104,101,110,32,115,116,97,114,116,101,100,32,97,103,97,105,110,32,40,101,118,101,110,32,111,110,32,116,104,101,32,115,97,109,101,32,109,97,99,104,105,110,101,41,44,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,111,102,32,116,104,101,32,110,101,119,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,32,99,97,110,32,100,105,102,102,101,114,32,102,114,111,109,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,111,102,32,116,104,101,32,111,108,100,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46>>]},{p,[],[<<79,110,101,32,99,97,110,32,103,101,116,32,97,110,32,97,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,40,49,44,32,115,101,99,111,110,100,44,32,110,97,116,105,118,101,41>>]}]},<<46,32,84,104,101,32,114,101,115,117,108,116,32,101,113,117,97,108,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,119,104,111,108,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,115,32,112,101,114,32,115,101,99,111,110,100,32,100,111,101,115,32,110,111,116,32,97,100,100,32,117,112,32,116,111,32,97,32,119,104,111,108,101,32,110,117,109,98,101,114,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,114,111,117,110,100,101,100,32,100,111,119,110,119,97,114,100,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,103,105,118,101,115,32,121,111,117,32,109,111,114,101,32,111,114,32,108,101,115,115,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,113,117,97,108,105,116,121,32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,46,32,73,116,32,115,101,116,115,32,97,32,108,105,109,105,116,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,82,101,115,111,108,117,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,115,111,108,117,116,105,111,110>>]},<<32,97,110,100,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,80,114,101,99,105,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,101,99,105,115,105,111,110>>]},<<32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,44,32,98,117,116,32,105,116,32,103,105,118,101,115,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,65,99,99,117,114,97,99,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,99,99,117,114,97,99,121>>]},<<32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,46,32,84,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,97,110,100,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,32,99,97,110,32,100,105,102,102,101,114,32,115,105,103,110,105,102,105,99,97,110,116,108,121,46>>]}]}]},{dt,[],[{code,[],[<<112,101,114,102,95,99,111,117,110,116,101,114>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,112,101,114,102,111,114,109,97,110,99,101,32,99,111,117,110,116,101,114,32,116,105,109,101,32,117,110,105,116,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<112,101,114,102,95,99,111,117,110,116,101,114>>]},<<32,116,105,109,101,32,117,110,105,116,32,98,101,104,97,118,101,115,32,109,117,99,104,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,46,32,84,104,97,116,32,105,115,44,32,105,116,32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,114,117,110,116,105,109,101,32,114,101,115,116,97,114,116,115,46,32,84,111,32,103,101,116,32,118,97,108,117,101,115,32,111,102,32,116,104,105,115,32,116,121,112,101,44,32,99,97,108,108,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>]}]},<<46>>]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116,40,41>>]}]}]},{dd,[],[{p,[],[<<68,101,112,114,101,99,97,116,101,100,32,115,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,115,32,107,101,112,116,32,102,111,114,32,98,97,99,107,119,97,114,100,115,45,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]}]}]},{p,[],[<<84,104,101,32>>,{code,[],[<<116,105,109,101,95,117,110,105,116,47,48>>]},<<32,116,121,112,101,32,99,97,110,32,98,101,32,101,120,116,101,110,100,101,100,46,32,84,111,32,99,111,110,118,101,114,116,32,116,105,109,101,32,118,97,108,117,101,115,32,98,101,116,119,101,101,110,32,116,105,109,101,32,117,110,105,116,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>]}]},<<46>>]}]},#{signature => [{attribute,93,type,{time_unit,{type,94,union,[{type,94,pos_integer,[]},{atom,95,second},{atom,96,millisecond},{atom,97,microsecond},{atom,98,nanosecond},{atom,99,native},{atom,100,perf_counter},{user_type,101,deprecated_time_unit,[]}]},[]}}]}},{{type,deprecated_time_unit,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,104}],[<<45,116,121,112,101,32,100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{a,[{id,<<116,121,112,101,95,100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116>>}],[]},{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,117,110,105,116,40,41>>]}]},<<32,116,121,112,101,32,97,108,115,111,32,99,111,110,115,105,115,116,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32>>,{em,[],[<<100,101,112,114,101,99,97,116,101,100>>]},<<32,115,121,109,98,111,108,105,99,32,116,105,109,101,32,117,110,105,116,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,99,111,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,108,108,105,95,115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,108,108,105,115,101,99,111,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,99,114,111,95,115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,99,114,111,115,101,99,111,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<110,97,110,111,95,115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<110,97,110,111,115,101,99,111,110,100>>]}]},<<46>>]}]}]}]},#{signature => [{attribute,104,type,{deprecated_time_unit,{type,105,union,[{atom,105,seconds},{atom,106,milli_seconds},{atom,107,micro_seconds},{atom,108,nano_seconds}]},[]}}]}},{{type,dist_handle,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,116}],[<<45,116,121,112,101,32,100,105,115,116,95,104,97,110,100,108,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,111,112,97,113,117,101,32,104,97,110,100,108,101,32,105,100,101,110,116,105,102,105,110,103,32,97,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,46>>]}]},#{signature => [{attribute,116,opaque,{dist_handle,{type,116,atom,[]},[]}}]}},{{type,nif_resource,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,113}],[<<45,116,121,112,101,32,110,105,102,95,114,101,115,111,117,114,99,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,111,112,97,113,117,101,32,104,97,110,100,108,101,32,105,100,101,110,116,105,102,105,110,103,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,110,105,102,35,114,101,115,111,117,114,99,101,95,111,98,106,101,99,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<78,73,70,32,114,101,115,111,117,114,99,101,32,111,98,106,101,99,116,32>>]},<<46>>]}]},#{signature => [{attribute,113,opaque,{nif_resource,{type,113,reference,[]},[]}}]}},{{type,spawn_opt_option,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2988}],[<<45,116,121,112,101,32,115,112,97,119,110,95,111,112,116,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<79,112,116,105,111,110,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,40,41>>]}]},<<46>>]}]},#{signature => [{attribute,2988,type,{spawn_opt_option,{type,2989,union,[{atom,2989,link},{atom,2990,monitor},{type,2991,tuple,[{atom,2991,monitor},{ann_type,2991,[{var,2991,'MonitorOpts'},{type,2991,list,[{user_type,2991,monitor_option,[]}]}]}]},{type,2992,tuple,[{atom,2992,priority},{ann_type,2992,[{var,2992,'Level'},{user_type,2992,priority_level,[]}]}]},{type,2993,tuple,[{atom,2993,fullsweep_after},{ann_type,2993,[{var,2993,'Number'},{type,2993,non_neg_integer,[]}]}]},{type,2994,tuple,[{atom,2994,min_heap_size},{ann_type,2994,[{var,2994,'Size'},{type,2994,non_neg_integer,[]}]}]},{type,2995,tuple,[{atom,2995,min_bin_vheap_size},{ann_type,2995,[{var,2995,'VSize'},{type,2995,non_neg_integer,[]}]}]},{type,2996,tuple,[{atom,2996,max_heap_size},{ann_type,2996,[{var,2996,'Size'},{user_type,2996,max_heap_size,[]}]}]},{type,2997,tuple,[{atom,2997,message_queue_data},{ann_type,2997,[{var,2997,'MQD'},{user_type,2997,message_queue_data,[]}]}]}]},[]}}]}},{{type,priority_level,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2350}],[<<45,116,121,112,101,32,112,114,105,111,114,105,116,121,95,108,101,118,101,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<80,114,111,99,101,115,115,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]}]}]},#{signature => [{attribute,2350,type,{priority_level,{type,2351,union,[{atom,2351,low},{atom,2351,normal},{atom,2351,high},{atom,2351,max}]},[]}}]}},{{type,max_heap_size,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2981}],[<<45,116,121,112,101,32,109,97,120,95,104,101,97,112,95,115,105,122,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<80,114,111,99,101,115,115,32,109,97,120,32,104,101,97,112,32,115,105,122,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]}]}]},#{signature => [{attribute,2981,type,{max_heap_size,{ann_type,2982,[{var,2982,'Size'},{type,2982,union,[{type,2982,non_neg_integer,[]},{type,2984,map,[{type,2984,map_field_assoc,[{atom,2984,size},{type,2984,non_neg_integer,[]}]},{type,2985,map_field_assoc,[{atom,2985,kill},{type,2985,boolean,[]}]},{type,2986,map_field_assoc,[{atom,2986,error_logger},{type,2986,boolean,[]}]}]}]}]},[]}}]}},{{type,message_queue_data,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2353}],[<<45,116,121,112,101,32,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<80,114,111,99,101,115,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,100,97,116,97,32,99,111,110,102,105,103,117,114,97,116,105,111,110,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]}]}]},#{signature => [{attribute,2353,type,{message_queue_data,{type,2354,union,[{atom,2354,off_heap},{atom,2354,on_heap}]},[]}}]}}]}. \ No newline at end of file
+{docs_v1,[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<66,121,32,99,111,110,118,101,110,116,105,111,110,44,32,109,111,115,116,32,66,117,105,108,116,45,73,110,32,70,117,110,99,116,105,111,110,115,32,40,66,73,70,115,41,32,97,110,100,32,97,108,108,32,112,114,101,100,101,102,105,110,101,100,32,116,121,112,101,115,32,97,114,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,46,32,83,111,109,101,32,111,102,32,116,104,101,32,66,73,70,115,32,97,110,100,32,97,108,108,32,111,102,32,116,104,101,32,112,114,101,100,101,102,105,110,101,100,32,116,121,112,101,115,32,97,114,101,32,118,105,101,119,101,100,32,109,111,114,101,32,111,114,32,108,101,115,115,32,97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,32,97,110,100,32,97,114,101,32>>,{em,[],[<<97,117,116,111,45,105,109,112,111,114,116,101,100>>]},<<46,32,84,104,117,115,44,32,105,116,32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,121,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,97,108,108,115,32>>,{code,[],[<<97,116,111,109,95,116,111,95,108,105,115,116,40,101,114,108,97,110,103,41>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,108,97,110,103,58,97,116,111,109,95,116,111,95,108,105,115,116,40,101,114,108,97,110,103,41>>]},<<32,97,114,101,32,105,100,101,110,116,105,99,97,108,46>>]},{p,[],[<<65,117,116,111,45,105,109,112,111,114,116,101,100,32,66,73,70,115,32,97,114,101,32,108,105,115,116,101,100,32,119,105,116,104,111,117,116,32,109,111,100,117,108,101,32,112,114,101,102,105,120,46,32,66,73,70,115,32,108,105,115,116,101,100,32,119,105,116,104,32,109,111,100,117,108,101,32,112,114,101,102,105,120,32,97,114,101,32,110,111,116,32,97,117,116,111,45,105,109,112,111,114,116,101,100,46>>]},{p,[],[<<80,114,101,100,101,102,105,110,101,100,32,116,121,112,101,115,32,97,114,101,32,108,105,115,116,101,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,80,114,101,100,101,102,105,110,101,100,32,100,97,116,97,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,114,101,100,101,102,105,110,101,100,32,100,97,116,97,116,121,112,101,115>>]},<<32,115,101,99,116,105,111,110,32,111,102,32,116,104,105,115,32,114,101,102,101,114,101,110,99,101,32,109,97,110,117,97,108,32,97,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,116,121,112,101,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<84,121,112,101,115,32,97,110,100,32,70,117,110,99,116,105,111,110,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115>>]},<<32,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,46>>]},{p,[],[<<66,73,70,115,32,99,97,110,32,102,97,105,108,32,102,111,114,32,118,97,114,105,111,117,115,32,114,101,97,115,111,110,115,46,32,65,108,108,32,66,73,70,115,32,102,97,105,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,121,32,97,114,101,32,99,97,108,108,101,100,32,119,105,116,104,32,97,114,103,117,109,101,110,116,115,32,111,102,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,46,32,84,104,101,32,111,116,104,101,114,32,114,101,97,115,111,110,115,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,101,97,99,104,32,105,110,100,105,118,105,100,117,97,108,32,66,73,70,46>>]},{p,[],[<<83,111,109,101,32,66,73,70,115,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,32,97,110,100,32,97,114,101,32,109,97,114,107,101,100,32,119,105,116,104,32,34,65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,34,46>>]}]},#{name => <<101,114,108,97,110,103>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,101,114,108,97,110,103,46,120,109,108],types => #{{nil,0} => {attribute,{103,2},type,{nil,{type,{103,16},nil,[]},[]}},{trace_flag,0} => {attribute,{356,2},type,{trace_flag,{type,{357,7},union,[{atom,{357,7},all},{atom,{358,7},send},{atom,{359,7},'receive'},{atom,{360,7},procs},{atom,{361,7},ports},{atom,{362,7},call},{atom,{363,7},arity},{atom,{364,7},return_to},{atom,{365,7},silent},{atom,{366,7},running},{atom,{367,7},exiting},{atom,{368,7},running_procs},{atom,{369,7},running_ports},{atom,{370,7},garbage_collection},{atom,{371,7},timestamp},{atom,{372,7},cpu_timestamp},{atom,{373,7},monotonic_timestamp},{atom,{374,7},strict_monotonic_timestamp},{atom,{375,7},set_on_spawn},{atom,{376,7},set_on_first_spawn},{atom,{377,7},set_on_link},{atom,{378,7},set_on_first_link},{type,{379,7},tuple,[{atom,{379,8},tracer},{type,{379,16},union,[{type,{379,16},pid,[]},{type,{379,24},port,[]}]}]},{type,{380,7},tuple,[{atom,{380,8},tracer},{type,{380,16},module,[]},{type,{380,26},term,[]}]}]},[]}},{nonempty_maybe_improper_list,0} => {attribute,{113,2},type,{nonempty_maybe_improper_list,{type,{113,41},nonempty_maybe_improper_list,[{type,{113,70},any,[]},{type,{113,77},any,[]}]},[]}},{maybe_improper_list,0} => {attribute,{98,2},type,{maybe_improper_list,{type,{98,32},maybe_improper_list,[{type,{98,52},any,[]},{type,{98,59},any,[]}]},[]}},{iodata,0} => {attribute,{93,2},type,{iodata,{type,{93,19},union,[{type,{93,19},iolist,[]},{type,{93,30},binary,[]}]},[]}},{trace_info_item_result,0} => {attribute,{382,2},type,{trace_info_item_result,{type,{383,8},union,[{type,{383,8},tuple,[{atom,{383,9},traced},{type,{383,17},union,[{atom,{383,17},global},{atom,{383,26},local},{atom,{383,34},false},{atom,{383,42},undefined}]}]},{type,{384,8},tuple,[{atom,{384,9},match_spec},{type,{384,21},union,[{user_type,{384,21},trace_match_spec,[]},{atom,{384,42},false},{atom,{384,50},undefined}]}]},{type,{385,8},tuple,[{atom,{385,9},meta},{type,{385,15},union,[{type,{385,15},pid,[]},{type,{385,23},port,[]},{atom,{385,32},false},{atom,{385,40},undefined},{type,{385,52},nil,[]}]}]},{type,{386,8},tuple,[{atom,{386,9},meta},{type,{386,15},module,[]},{type,{386,25},term,[]}]},{type,{387,8},tuple,[{atom,{387,9},meta_match_spec},{type,{387,26},union,[{user_type,{387,26},trace_match_spec,[]},{atom,{387,47},false},{atom,{387,55},undefined}]}]},{type,{388,8},tuple,[{atom,{388,9},call_count},{type,{388,21},union,[{type,{388,21},non_neg_integer,[]},{type,{388,41},boolean,[]},{atom,{388,53},undefined}]}]},{type,{389,8},tuple,[{atom,{389,9},call_time},{type,{389,20},union,[{type,{389,20},list,[{type,{389,21},tuple,[{type,{389,22},pid,[]},{type,{389,29},non_neg_integer,[]},{type,{390,8},non_neg_integer,[]},{type,{390,27},non_neg_integer,[]}]}]},{type,{390,49},boolean,[]},{atom,{390,61},undefined}]}]}]},[]}},{map,0} => {attribute,{97,2},type,{map,{type,{97,16},map,[{type,{97,25},map_field_assoc,[{type,{97,19},any,[]},{type,{97,28},any,[]}]}]},[]}},{atom,0} => {attribute,{82,2},type,{atom,{type,{82,17},atom,[]},[]}},{stacktrace,0} => {attribute,{151,2},type,{stacktrace,{type,{151,23},list,[{type,{151,24},union,[{type,{151,24},tuple,[{type,{151,25},module,[]},{type,{151,35},atom,[]},{type,{151,43},union,[{type,{151,43},arity,[]},{type,{151,53},list,[{type,{151,54},term,[]}]}]},{type,{152,25},list,[{user_type,{152,26},stacktrace_extrainfo,[]}]}]},{type,{153,24},tuple,[{type,{153,25},function,[]},{type,{153,37},union,[{type,{153,37},arity,[]},{type,{153,47},list,[{type,{153,48},term,[]}]}]},{type,{153,57},list,[{user_type,{153,58},stacktrace_extrainfo,[]}]}]}]}]},[]}},{nif_resource,0} => {attribute,{181,2},opaque,{nif_resource,{type,{181,27},reference,[]},[]}},{term,0} => {attribute,{122,2},type,{term,{type,{122,17},any,[]},[]}},{port,0} => {attribute,{118,2},type,{port,{type,{118,17},port,[]},[]}},{maybe_improper_list,2} => {attribute,{99,2},type,{maybe_improper_list,{type,{99,60},maybe_improper_list,[{var,{99,80},'ContentType'},{var,{99,93},'TerminationType'}]},[{var,{99,27},'ContentType'},{var,{99,40},'TerminationType'}]}},{number,0} => {attribute,{116,2},type,{number,{type,{116,19},union,[{type,{116,19},integer,[]},{type,{116,31},float,[]}]},[]}},{any,0} => {attribute,{80,2},type,{any,{type,{80,16},any,[]},[]}},{nonempty_list,1} => {attribute,{112,2},type,{nonempty_list,{type,{112,37},nonempty_list,[{var,{112,38},'ContentType'}]},[{var,{112,21},'ContentType'}]}},{scheduler_bind_type,0} => {attribute,{2662,2},type,{scheduler_bind_type,{type,{2663,7},union,[{atom,{2663,7},no_node_processor_spread},{atom,{2664,7},no_node_thread_spread},{atom,{2665,7},no_spread},{atom,{2666,7},processor_spread},{atom,{2667,7},spread},{atom,{2668,7},thread_spread},{atom,{2669,7},thread_no_node_processor_spread},{atom,{2670,7},unbound}]},[]}},{raise_stacktrace,0} => {attribute,{349,2},type,{raise_stacktrace,{type,{350,7},list,[{type,{350,8},union,[{type,{350,8},tuple,[{type,{350,9},module,[]},{type,{350,19},atom,[]},{type,{350,27},union,[{type,{350,27},arity,[]},{type,{350,37},list,[{type,{350,38},term,[]}]}]}]},{type,{351,8},tuple,[{type,{351,9},function,[]},{type,{351,21},union,[{type,{351,21},arity,[]},{type,{351,31},list,[{type,{351,32},term,[]}]}]}]}]}]},[]}},{timestamp,0} => {attribute,{157,2},type,{timestamp,{type,{157,22},tuple,[{ann_type,{157,23},[{var,{157,23},'MegaSecs'},{type,{157,35},non_neg_integer,[]}]},{ann_type,{158,23},[{var,{158,23},'Secs'},{type,{158,31},non_neg_integer,[]}]},{ann_type,{159,23},[{var,{159,23},'MicroSecs'},{type,{159,36},non_neg_integer,[]}]}]},[]}},{spawn_opt_option,0} => {attribute,{3056,2},type,{spawn_opt_option,{type,{3057,2},union,[{atom,{3057,2},link},{atom,{3058,9},monitor},{type,{3059,9},tuple,[{atom,{3059,10},monitor},{ann_type,{3059,19},[{var,{3059,19},'MonitorOpts'},{type,{3059,34},list,[{user_type,{3059,35},monitor_option,[]}]}]}]},{type,{3060,9},tuple,[{atom,{3060,10},priority},{ann_type,{3060,20},[{var,{3060,20},'Level'},{user_type,{3060,29},priority_level,[]}]}]},{type,{3061,9},tuple,[{atom,{3061,10},fullsweep_after},{ann_type,{3061,27},[{var,{3061,27},'Number'},{type,{3061,37},non_neg_integer,[]}]}]},{type,{3062,9},tuple,[{atom,{3062,10},min_heap_size},{ann_type,{3062,25},[{var,{3062,25},'Size'},{type,{3062,33},non_neg_integer,[]}]}]},{type,{3063,9},tuple,[{atom,{3063,10},min_bin_vheap_size},{ann_type,{3063,30},[{var,{3063,30},'VSize'},{type,{3063,39},non_neg_integer,[]}]}]},{type,{3064,9},tuple,[{atom,{3064,10},max_heap_size},{ann_type,{3064,25},[{var,{3064,25},'Size'},{user_type,{3064,33},max_heap_size,[]}]}]},{type,{3065,9},tuple,[{atom,{3065,10},message_queue_data},{ann_type,{3065,30},[{var,{3065,30},'MQD'},{user_type,{3065,37},message_queue_data,[]}]}]}]},[]}},{ext_binary,0} => {attribute,{155,2},type,{ext_binary,{type,{155,23},binary,[]},[]}},{trace_info_flag,0} => {attribute,{392,2},type,{trace_info_flag,{type,{393,7},union,[{atom,{393,7},send},{atom,{394,7},'receive'},{atom,{395,7},set_on_spawn},{atom,{396,7},call},{atom,{397,7},return_to},{atom,{398,7},procs},{atom,{399,7},set_on_first_spawn},{atom,{400,7},set_on_link},{atom,{401,7},running},{atom,{402,7},garbage_collection},{atom,{403,7},timestamp},{atom,{404,7},monotonic_timestamp},{atom,{405,7},strict_monotonic_timestamp},{atom,{406,7},arity}]},[]}},{info_list,0} => {attribute,{2830,2},type,{info_list,{type,{2830,22},nil,[]},[]}},{module,0} => {attribute,{101,2},type,{module,{type,{101,19},atom,[]},[]}},{boolean,0} => {attribute,{86,2},type,{boolean,{type,{86,20},union,[{atom,{86,20},true},{atom,{86,27},false}]},[]}},{non_neg_integer,0} => {attribute,{106,2},type,{non_neg_integer,{type,{106,28},non_neg_integer,[]},[]}},{byte,0} => {attribute,{87,2},type,{byte,{type,{87,17},range,[{integer,{87,17},0},{integer,{87,20},255}]},[]}},{nonempty_maybe_improper_list,2} => {attribute,{114,2},type,{nonempty_maybe_improper_list,{type,{114,69},nonempty_maybe_improper_list,[{var,{114,98},'ContentType'},{var,{114,111},'TerminationType'}]},[{var,{114,36},'ContentType'},{var,{114,49},'TerminationType'}]}},{process_info_result_item,0} => {attribute,{2491,2},type,{process_info_result_item,{type,{2492,7},union,[{type,{2492,7},tuple,[{atom,{2492,8},backtrace},{ann_type,{2492,19},[{var,{2492,19},'Bin'},{type,{2492,26},binary,[]}]}]},{type,{2493,7},tuple,[{atom,{2493,8},binary},{ann_type,{2493,16},[{var,{2493,16},'BinInfo'},{type,{2493,27},list,[{type,{2493,28},tuple,[{type,{2493,29},non_neg_integer,[]},{type,{2494,29},non_neg_integer,[]},{type,{2495,29},non_neg_integer,[]}]}]}]}]},{type,{2496,7},tuple,[{atom,{2496,8},catchlevel},{ann_type,{2496,20},[{var,{2496,20},'CatchLevel'},{type,{2496,34},non_neg_integer,[]}]}]},{type,{2497,7},tuple,[{atom,{2497,8},current_function},{type,{2498,8},union,[{type,{2498,8},tuple,[{ann_type,{2498,9},[{var,{2498,9},'Module'},{type,{2498,19},module,[]}]},{ann_type,{2498,29},[{var,{2498,29},'Function'},{type,{2498,41},atom,[]}]},{ann_type,{2498,49},[{var,{2498,49},'Arity'},{type,{2498,58},arity,[]}]}]},{atom,{2498,69},undefined}]}]},{type,{2499,7},tuple,[{atom,{2499,8},current_location},{type,{2500,8},tuple,[{ann_type,{2500,9},[{var,{2500,9},'Module'},{type,{2500,19},module,[]}]},{ann_type,{2500,29},[{var,{2500,29},'Function'},{type,{2500,41},atom,[]}]},{ann_type,{2500,49},[{var,{2500,49},'Arity'},{type,{2500,58},arity,[]}]},{ann_type,{2501,9},[{var,{2501,9},'Location'},{type,{2501,21},list,[{type,{2501,22},union,[{type,{2501,22},tuple,[{atom,{2501,23},file},{ann_type,{2501,29},[{var,{2501,29},'Filename'},{type,{2501,41},string,[]}]}]},{type,{2502,22},tuple,[{atom,{2502,23},line},{ann_type,{2502,29},[{var,{2502,29},'Line'},{type,{2502,37},pos_integer,[]}]}]}]}]}]}]}]},{type,{2503,7},tuple,[{atom,{2503,8},current_stacktrace},{ann_type,{2503,28},[{var,{2503,28},'Stack'},{type,{2503,37},list,[{user_type,{2503,38},stack_item,[]}]}]}]},{type,{2504,7},tuple,[{atom,{2504,8},dictionary},{ann_type,{2504,20},[{var,{2504,20},'Dictionary'},{type,{2504,34},list,[{type,{2504,35},tuple,[{ann_type,{2504,36},[{var,{2504,36},'Key'},{type,{2504,43},term,[]}]},{ann_type,{2504,51},[{var,{2504,51},'Value'},{type,{2504,60},term,[]}]}]}]}]}]},{type,{2505,7},tuple,[{atom,{2505,8},error_handler},{ann_type,{2505,23},[{var,{2505,23},'Module'},{type,{2505,33},module,[]}]}]},{type,{2506,7},tuple,[{atom,{2506,8},garbage_collection},{ann_type,{2506,28},[{var,{2506,28},'GCInfo'},{type,{2506,38},list,[{type,{2506,39},tuple,[{type,{2506,40},atom,[]},{type,{2506,47},non_neg_integer,[]}]}]}]}]},{type,{2507,7},tuple,[{atom,{2507,8},garbage_collection_info},{ann_type,{2507,33},[{var,{2507,33},'GCInfo'},{type,{2507,43},list,[{type,{2507,44},tuple,[{type,{2507,45},atom,[]},{type,{2507,52},non_neg_integer,[]}]}]}]}]},{type,{2508,7},tuple,[{atom,{2508,8},group_leader},{ann_type,{2508,22},[{var,{2508,22},'GroupLeader'},{type,{2508,37},pid,[]}]}]},{type,{2509,7},tuple,[{atom,{2509,8},heap_size},{ann_type,{2509,19},[{var,{2509,19},'Size'},{type,{2509,27},non_neg_integer,[]}]}]},{type,{2510,7},tuple,[{atom,{2510,8},initial_call},{type,{2510,22},mfa,[]}]},{type,{2511,7},tuple,[{atom,{2511,8},links},{ann_type,{2511,15},[{var,{2511,15},'PidsAndPorts'},{type,{2511,31},list,[{type,{2511,32},union,[{type,{2511,32},pid,[]},{type,{2511,40},port,[]}]}]}]}]},{type,{2512,7},tuple,[{atom,{2512,8},last_calls},{type,{2512,20},union,[{atom,{2512,20},false},{ann_type,{2512,29},[{var,{2512,29},'Calls'},{type,{2512,38},list,[{type,{2512,39},mfa,[]}]}]}]}]},{type,{2513,7},tuple,[{atom,{2513,8},memory},{ann_type,{2513,16},[{var,{2513,16},'Size'},{type,{2513,24},non_neg_integer,[]}]}]},{type,{2514,7},tuple,[{atom,{2514,8},message_queue_len},{ann_type,{2514,27},[{var,{2514,27},'MessageQueueLen'},{type,{2514,46},non_neg_integer,[]}]}]},{type,{2515,7},tuple,[{atom,{2515,8},messages},{ann_type,{2515,18},[{var,{2515,18},'MessageQueue'},{type,{2515,34},list,[{type,{2515,35},term,[]}]}]}]},{type,{2516,7},tuple,[{atom,{2516,8},min_heap_size},{ann_type,{2516,23},[{var,{2516,23},'MinHeapSize'},{type,{2516,38},non_neg_integer,[]}]}]},{type,{2517,7},tuple,[{atom,{2517,8},min_bin_vheap_size},{ann_type,{2517,28},[{var,{2517,28},'MinBinVHeapSize'},{type,{2517,47},non_neg_integer,[]}]}]},{type,{2518,7},tuple,[{atom,{2518,8},max_heap_size},{ann_type,{2518,23},[{var,{2518,23},'MaxHeapSize'},{user_type,{2518,38},max_heap_size,[]}]}]},{type,{2519,7},tuple,[{atom,{2519,8},monitored_by},{ann_type,{2519,22},[{var,{2519,22},'MonitoredBy'},{type,{2519,37},list,[{type,{2519,38},union,[{type,{2519,38},pid,[]},{type,{2519,46},port,[]},{user_type,{2519,55},nif_resource,[]}]}]}]}]},{type,{2520,7},tuple,[{atom,{2520,8},monitors},{ann_type,{2521,8},[{var,{2521,8},'Monitors'},{type,{2521,20},list,[{type,{2521,21},tuple,[{type,{2521,22},union,[{atom,{2521,22},process},{atom,{2521,32},port}]},{ann_type,{2521,38},[{var,{2521,38},'Pid'},{type,{2521,45},union,[{type,{2521,45},pid,[]},{type,{2521,53},port,[]},{type,{2522,38},tuple,[{ann_type,{2522,39},[{var,{2522,39},'RegName'},{type,{2522,50},atom,[]}]},{ann_type,{2522,58},[{var,{2522,58},'Node'},{type,{2522,66},node,[]}]}]}]}]}]}]}]}]},{type,{2523,7},tuple,[{atom,{2523,8},message_queue_data},{ann_type,{2523,28},[{var,{2523,28},'MQD'},{user_type,{2523,35},message_queue_data,[]}]}]},{type,{2524,7},tuple,[{atom,{2524,8},priority},{ann_type,{2524,18},[{var,{2524,18},'Level'},{user_type,{2524,27},priority_level,[]}]}]},{type,{2525,7},tuple,[{atom,{2525,8},reductions},{ann_type,{2525,20},[{var,{2525,20},'Number'},{type,{2525,30},non_neg_integer,[]}]}]},{type,{2526,7},tuple,[{atom,{2526,8},registered_name},{type,{2526,25},union,[{type,{2526,25},nil,[]},{ann_type,{2526,31},[{var,{2526,31},'Atom'},{type,{2526,39},atom,[]}]}]}]},{type,{2527,7},tuple,[{atom,{2527,8},sequential_trace_token},{type,{2527,32},union,[{type,{2527,32},nil,[]},{ann_type,{2527,38},[{var,{2527,38},'SequentialTraceToken'},{type,{2527,62},term,[]}]}]}]},{type,{2528,7},tuple,[{atom,{2528,8},stack_size},{ann_type,{2528,20},[{var,{2528,20},'Size'},{type,{2528,28},non_neg_integer,[]}]}]},{type,{2529,7},tuple,[{atom,{2529,8},status},{ann_type,{2529,16},[{var,{2529,16},'Status'},{type,{2529,26},union,[{atom,{2529,26},exiting},{atom,{2529,36},garbage_collecting},{atom,{2529,57},waiting},{atom,{2529,67},running},{atom,{2529,77},runnable},{atom,{2529,88},suspended}]}]}]},{type,{2530,7},tuple,[{atom,{2530,8},suspending},{ann_type,{2531,8},[{var,{2531,8},'SuspendeeList'},{type,{2531,25},list,[{type,{2531,26},tuple,[{ann_type,{2531,27},[{var,{2531,27},'Suspendee'},{type,{2531,40},pid,[]}]},{ann_type,{2532,27},[{var,{2532,27},'ActiveSuspendCount'},{type,{2532,49},non_neg_integer,[]}]},{ann_type,{2533,27},[{var,{2533,27},'OutstandingSuspendCount'},{type,{2533,53},non_neg_integer,[]}]}]}]}]}]},{type,{2534,7},tuple,[{atom,{2534,8},total_heap_size},{ann_type,{2534,25},[{var,{2534,25},'Size'},{type,{2534,33},non_neg_integer,[]}]}]},{type,{2535,7},tuple,[{atom,{2535,8},trace},{ann_type,{2535,15},[{var,{2535,15},'InternalTraceFlags'},{type,{2535,37},non_neg_integer,[]}]}]},{type,{2536,7},tuple,[{atom,{2536,8},trap_exit},{ann_type,{2536,19},[{var,{2536,19},'Boolean'},{type,{2536,30},boolean,[]}]}]}]},[]}},{nonempty_bitstring,0} => {attribute,{109,2},type,{nonempty_bitstring,{type,{109,31},binary,[{integer,{109,35},1},{integer,{109,42},1}]},[]}},{nonempty_improper_list,2} => {attribute,{110,2},type,{nonempty_improper_list,{type,{110,63},nonempty_improper_list,[{var,{110,86},'ContentType'},{var,{110,99},'TerminationType'}]},[{var,{110,30},'ContentType'},{var,{110,43},'TerminationType'}]}},{float,0} => {attribute,{89,2},type,{float,{type,{89,18},float,[]},[]}},{trace_pattern_mfa,0} => {attribute,{2768,2},type,{trace_pattern_mfa,{type,{2769,7},union,[{type,{2769,7},tuple,[{type,{2769,8},atom,[]},{type,{2769,15},atom,[]},{type,{2769,22},union,[{type,{2769,22},arity,[]},{atom,{2769,32},'_'}]}]},{atom,{2769,39},on_load}]},[]}},{level_tag,0} => {attribute,{2827,2},type,{level_tag,{type,{2827,22},union,[{atom,{2827,22},core},{atom,{2827,29},node},{atom,{2827,36},processor},{atom,{2827,48},thread}]},[]}},{fun_info_item,0} => {attribute,{315,2},type,{fun_info_item,{type,{316,7},union,[{atom,{316,7},arity},{atom,{317,7},env},{atom,{318,7},index},{atom,{319,7},name},{atom,{320,7},module},{atom,{321,7},new_index},{atom,{322,7},new_uniq},{atom,{323,7},pid},{atom,{324,7},type},{atom,{325,7},uniq}]},[]}},{memory_type,0} => {attribute,{4006,2},type,{memory_type,{type,{4006,24},union,[{atom,{4006,24},total},{atom,{4006,34},processes},{atom,{4006,48},processes_used},{atom,{4006,67},system},{atom,{4007,24},atom},{atom,{4007,33},atom_used},{atom,{4007,47},binary},{atom,{4007,58},code},{atom,{4007,67},ets}]},[]}},{stack_item,0} => {attribute,{2538,2},type,{stack_item,{type,{2539,9},tuple,[{ann_type,{2539,10},[{var,{2539,10},'Module'},{type,{2539,20},module,[]}]},{ann_type,{2540,10},[{var,{2540,10},'Function'},{type,{2540,22},atom,[]}]},{ann_type,{2541,10},[{var,{2541,10},'Arity'},{type,{2541,19},union,[{type,{2541,19},arity,[]},{ann_type,{2541,30},[{var,{2541,30},'Args'},{type,{2541,38},list,[{type,{2541,39},term,[]}]}]}]}]},{ann_type,{2542,10},[{var,{2542,10},'Location'},{type,{2542,22},list,[{type,{2542,23},union,[{type,{2542,23},tuple,[{atom,{2542,24},file},{ann_type,{2542,30},[{var,{2542,30},'Filename'},{type,{2542,42},string,[]}]}]},{type,{2543,23},tuple,[{atom,{2543,24},line},{ann_type,{2543,30},[{var,{2543,30},'Line'},{type,{2543,38},pos_integer,[]}]}]}]}]}]}]},[]}},{sub_level,0} => {attribute,{2828,2},type,{sub_level,{type,{2828,22},union,[{type,{2828,22},list,[{ann_type,{2828,23},[{var,{2828,23},'LevelEntry'},{user_type,{2828,37},level_entry,[]}]}]},{ann_type,{2829,23},[{var,{2829,23},'LogicalCpuId'},{type,{2829,39},tuple,[{atom,{2829,40},logical},{type,{2829,49},non_neg_integer,[]}]}]}]},[]}},{monitor_process_identifier,0} => {attribute,{1458,2},type,{monitor_process_identifier,{type,{1458,39},union,[{type,{1458,39},pid,[]},{user_type,{1458,47},registered_process_identifier,[]}]},[]}},{nonempty_list,0} => {attribute,{111,2},type,{nonempty_list,{type,{111,26},nonempty_list,[{type,{111,40},any,[]}]},[]}},{deprecated_time_unit,0} => {attribute,{172,2},type,{deprecated_time_unit,{type,{173,7},union,[{atom,{173,7},seconds},{atom,{174,9},milli_seconds},{atom,{175,9},micro_seconds},{atom,{176,9},nano_seconds}]},[]}},{neg_integer,0} => {attribute,{102,2},type,{neg_integer,{type,{102,24},neg_integer,[]},[]}},{bool,0} => {attribute,{85,2},type,{bool,{type,{85,17},boolean,[]},[]}},{system_monitor_option,0} => {attribute,{342,2},type,{system_monitor_option,{type,{343,7},union,[{atom,{343,7},busy_port},{atom,{344,7},busy_dist_port},{type,{345,7},tuple,[{atom,{345,8},long_gc},{type,{345,19},non_neg_integer,[]}]},{type,{346,7},tuple,[{atom,{346,8},long_schedule},{type,{346,25},non_neg_integer,[]}]},{type,{347,7},tuple,[{atom,{347,8},large_heap},{type,{347,22},non_neg_integer,[]}]}]},[]}},{no_return,0} => {attribute,{104,2},type,{no_return,{type,{104,22},none,[]},[]}},{process_info_item,0} => {attribute,{2456,2},type,{process_info_item,{type,{2457,7},union,[{atom,{2457,7},backtrace},{atom,{2458,7},binary},{atom,{2459,7},catchlevel},{atom,{2460,7},current_function},{atom,{2461,7},current_location},{atom,{2462,7},current_stacktrace},{atom,{2463,7},dictionary},{atom,{2464,7},error_handler},{atom,{2465,7},garbage_collection},{atom,{2466,7},garbage_collection_info},{atom,{2467,7},group_leader},{atom,{2468,7},heap_size},{atom,{2469,7},initial_call},{atom,{2470,7},links},{atom,{2471,7},last_calls},{atom,{2472,7},memory},{atom,{2473,7},message_queue_len},{atom,{2474,7},messages},{atom,{2475,7},min_heap_size},{atom,{2476,7},min_bin_vheap_size},{atom,{2477,7},monitored_by},{atom,{2478,7},monitors},{atom,{2479,7},message_queue_data},{atom,{2480,7},priority},{atom,{2481,7},reductions},{atom,{2482,7},registered_name},{atom,{2483,7},sequential_trace_token},{atom,{2484,7},stack_size},{atom,{2485,7},status},{atom,{2486,7},suspending},{atom,{2487,7},total_heap_size},{atom,{2488,7},trace},{atom,{2489,7},trap_exit}]},[]}},{char,0} => {attribute,{88,2},type,{char,{type,{88,17},range,[{integer,{88,17},0},{integer,{88,20},1114111}]},[]}},{pid,0} => {attribute,{117,2},type,{pid,{type,{117,16},pid,[]},[]}},{level_entry,0} => {attribute,{2822,2},type,{level_entry,{type,{2823,9},union,[{type,{2823,9},tuple,[{ann_type,{2823,10},[{var,{2823,10},'LevelTag'},{user_type,{2823,22},level_tag,[]}]},{ann_type,{2823,35},[{var,{2823,35},'SubLevel'},{user_type,{2823,47},sub_level,[]}]}]},{type,{2824,9},tuple,[{ann_type,{2824,10},[{var,{2824,10},'LevelTag'},{user_type,{2824,22},level_tag,[]}]},{ann_type,{2825,10},[{var,{2825,10},'InfoList'},{user_type,{2825,22},info_list,[]}]},{ann_type,{2826,10},[{var,{2826,10},'SubLevel'},{user_type,{2826,22},sub_level,[]}]}]}]},[]}},{cpu_topology,0} => {attribute,{2820,2},type,{cpu_topology,{type,{2821,9},union,[{type,{2821,9},list,[{ann_type,{2821,10},[{var,{2821,10},'LevelEntry'},{user_type,{2821,24},level_entry,[]}]}]},{atom,{2821,41},undefined}]},[]}},{nonempty_string,0} => {attribute,{115,2},type,{nonempty_string,{type,{115,28},nonempty_list,[{type,{115,42},char,[]}]},[]}},{integer,0} => {attribute,{92,2},type,{integer,{type,{92,20},integer,[]},[]}},{monitor_port_identifier,0} => {attribute,{1459,2},type,{monitor_port_identifier,{type,{1459,36},union,[{type,{1459,36},port,[]},{user_type,{1459,45},registered_name,[]}]},[]}},{dst,0} => {attribute,{3472,2},type,{dst,{type,{3472,16},union,[{type,{3472,16},pid,[]},{type,{3473,16},reference,[]},{type,{3474,16},port,[]},{ann_type,{3475,17},[{var,{3475,17},'RegName'},{type,{3475,28},atom,[]}]},{type,{3476,16},tuple,[{ann_type,{3476,17},[{var,{3476,17},'RegName'},{type,{3476,28},atom,[]}]},{ann_type,{3476,36},[{var,{3476,36},'Node'},{type,{3476,44},node,[]}]}]}]},[]}},{trace_info_return,0} => {attribute,{408,2},type,{trace_info_return,{type,{409,7},union,[{atom,{409,7},undefined},{type,{410,7},tuple,[{atom,{410,8},flags},{type,{410,15},list,[{user_type,{410,16},trace_info_flag,[]}]}]},{type,{411,7},tuple,[{atom,{411,8},tracer},{type,{411,16},union,[{type,{411,16},pid,[]},{type,{411,24},port,[]},{type,{411,33},nil,[]}]}]},{type,{412,7},tuple,[{atom,{412,8},tracer},{type,{412,16},module,[]},{type,{412,26},term,[]}]},{user_type,{413,7},trace_info_item_result,[]},{type,{414,7},tuple,[{atom,{414,8},all},{type,{414,13},union,[{type,{414,13},list,[{user_type,{414,15},trace_info_item_result,[]}]},{atom,{414,44},false},{atom,{414,52},undefined}]}]}]},[]}},{string,0} => {attribute,{121,2},type,{string,{type,{121,19},list,[{type,{121,20},char,[]}]},[]}},{list,0} => {attribute,{95,2},type,{list,{type,{95,17},list,[]},[]}},{node,0} => {attribute,{105,2},type,{node,{type,{105,17},atom,[]},[]}},{tuple,0} => {attribute,{124,2},type,{tuple,{type,{124,18},tuple,any},[]}},{mfa,0} => {attribute,{100,2},type,{mfa,{type,{100,16},tuple,[{type,{100,17},module,[]},{type,{100,26},atom,[]},{type,{100,33},arity,[]}]},[]}},{none,0} => {attribute,{107,2},type,{none,{type,{107,17},none,[]},[]}},{bitstring_list,0} => {attribute,{353,2},type,{bitstring_list,{type,{354,7},maybe_improper_list,[{type,{354,27},union,[{type,{354,27},byte,[]},{type,{354,36},bitstring,[]},{user_type,{354,50},bitstring_list,[]}]},{type,{354,68},union,[{type,{354,68},bitstring,[]},{type,{354,82},nil,[]}]}]},[]}},{registered_name,0} => {attribute,{1456,2},type,{registered_name,{type,{1456,28},atom,[]},[]}},{ext_iovec,0} => {attribute,{156,2},type,{ext_iovec,{user_type,{156,22},iovec,[]},[]}},{pos_integer,0} => {attribute,{119,2},type,{pos_integer,{type,{119,24},pos_integer,[]},[]}},{priority_level,0} => {attribute,{2413,2},type,{priority_level,{type,{2414,7},union,[{atom,{2414,7},low},{atom,{2414,13},normal},{atom,{2414,22},high},{atom,{2414,29},max}]},[]}},{binary,0} => {attribute,{83,2},type,{binary,{type,{83,19},binary,[{integer,83,0},{integer,{83,25},8}]},[]}},{monitor_option,0} => {attribute,{1460,2},type,{monitor_option,{type,{1460,27},union,[{type,{1460,27},tuple,[{atom,{1460,28},alias},{type,{1460,37},union,[{atom,{1460,37},explicit_unalias},{atom,{1460,58},demonitor},{atom,{1460,72},reply_demonitor}]}]},{type,{1461,27},tuple,[{atom,{1461,28},tag},{type,{1461,35},term,[]}]}]},[]}},{timeout,0} => {attribute,{123,2},type,{timeout,{type,{123,20},union,[{atom,{123,20},infinity},{type,{123,33},non_neg_integer,[]}]},[]}},{system_profile_option,0} => {attribute,{333,2},type,{system_profile_option,{type,{334,7},union,[{atom,{334,7},exclusive},{atom,{335,7},runnable_ports},{atom,{336,7},runnable_procs},{atom,{337,7},scheduler},{atom,{338,7},timestamp},{atom,{339,7},monotonic_timestamp},{atom,{340,7},strict_monotonic_timestamp}]},[]}},{reference,0} => {attribute,{120,2},type,{reference,{type,{120,22},reference,[]},[]}},{bitstring,0} => {attribute,{84,2},type,{bitstring,{type,{84,22},binary,[{integer,84,0},{integer,{84,28},1}]},[]}},{iolist,0} => {attribute,{94,2},type,{iolist,{type,{94,19},maybe_improper_list,[{type,{94,39},union,[{type,{94,39},byte,[]},{type,{94,48},binary,[]},{type,{94,59},iolist,[]}]},{type,{94,69},union,[{type,{94,69},binary,[]},{type,{94,80},nil,[]}]}]},[]}},{trace_pattern_flag,0} => {attribute,{2786,2},type,{trace_pattern_flag,{type,{2787,7},union,[{atom,{2787,7},global},{atom,{2787,16},local},{atom,{2788,7},meta},{type,{2788,14},tuple,[{atom,{2788,15},meta},{ann_type,{2788,21},[{var,{2788,21},'Pid'},{type,{2788,28},pid,[]}]}]},{type,{2789,7},tuple,[{atom,{2789,8},meta},{ann_type,{2789,14},[{var,{2789,14},'TracerModule'},{type,{2789,30},module,[]}]},{ann_type,{2789,40},[{var,{2789,40},'TracerState'},{type,{2789,55},term,[]}]}]},{atom,{2790,7},call_count},{atom,{2791,7},call_time}]},[]}},{nonempty_binary,0} => {attribute,{108,2},type,{nonempty_binary,{type,{108,28},binary,[{integer,{108,32},8},{integer,{108,39},8}]},[]}},{prepared_code,0} => {attribute,{178,2},opaque,{prepared_code,{type,{178,28},reference,[]},[]}},{dist_handle,0} => {attribute,{184,2},opaque,{dist_handle,{type,{184,26},atom,[]},[]}},{function,0} => {attribute,{90,2},type,{function,{type,{90,21},'fun',[]},[]}},{trace_match_spec,0} => {attribute,{2770,2},type,{trace_match_spec,{type,{2771,7},list,[{type,{2771,8},tuple,[{type,{2771,9},union,[{type,{2771,9},list,[{type,{2771,10},term,[]}]},{atom,{2771,20},'_'},{user_type,{2771,26},match_variable,[]}]},{type,{2771,44},list,[{type,{2771,45},term,[]}]},{type,{2771,53},list,[{type,{2771,54},term,[]}]}]}]},[]}},{list,1} => {attribute,{96,2},type,{list,{type,{96,28},list,[{var,{96,33},'ContentType'}]},[{var,{96,12},'ContentType'}]}},{stacktrace_extrainfo,0} => {attribute,{146,2},type,{stacktrace_extrainfo,{type,{147,9},union,[{type,{147,9},tuple,[{atom,{147,10},line},{type,{147,16},pos_integer,[]}]},{type,{148,9},tuple,[{atom,{148,10},file},{remote_type,{148,16},[{atom,{148,16},unicode},{atom,{148,24},chardata},[]]}]},{type,{149,9},tuple,[{atom,{149,10},error_info},{type,{149,22},map,[{type,{149,32},map_field_assoc,[{atom,{149,25},module},{type,{149,35},module,[]}]},{type,{149,54},map_field_assoc,[{atom,{149,45},function},{type,{149,57},atom,[]}]},{type,{149,71},map_field_assoc,[{atom,{149,65},cause},{type,{149,74},term,[]}]}]}]},{type,{150,9},tuple,[{type,{150,10},atom,[]},{type,{150,18},term,[]}]}]},[]}},{iovec,0} => {attribute,{187,2},type,{iovec,{type,{187,18},list,[{type,{187,19},binary,[]}]},[]}},{module_info_key,0} => {attribute,{2186,2},type,{module_info_key,{type,{2186,28},union,[{atom,{2186,28},attributes},{atom,{2186,41},compile},{atom,{2186,51},exports},{atom,{2186,61},functions},{atom,{2186,73},md5},{atom,{2187,28},module},{atom,{2187,37},native},{atom,{2187,46},native_addresses},{atom,{2187,65},nifs}]},[]}},{time_unit,0} => {attribute,{161,2},type,{time_unit,{type,{162,2},union,[{type,{162,2},pos_integer,[]},{atom,{163,9},second},{atom,{164,9},millisecond},{atom,{165,9},microsecond},{atom,{166,9},nanosecond},{atom,{167,9},native},{atom,{168,9},perf_counter},{user_type,{169,9},deprecated_time_unit,[]}]},[]}},{message_queue_data,0} => {attribute,{2416,2},type,{message_queue_data,{type,{2417,2},union,[{atom,{2417,2},off_heap},{atom,{2417,13},on_heap}]},[]}},{arity,0} => {attribute,{81,2},type,{arity,{type,{81,18},arity,[]},[]}},{identifier,0} => {attribute,{91,2},type,{identifier,{type,{91,23},union,[{type,{91,23},pid,[]},{type,{91,31},port,[]},{type,{91,40},reference,[]}]},[]}},{max_heap_size,0} => {attribute,{3049,2},type,{max_heap_size,{ann_type,{3050,9},[{var,{3050,9},'Size'},{type,{3050,17},union,[{type,{3050,17},non_neg_integer,[]},{type,{3052,9},map,[{type,{3052,17},map_field_assoc,[{atom,{3052,12},size},{type,{3052,20},non_neg_integer,[]}]},{type,{3053,17},map_field_assoc,[{atom,{3053,12},kill},{type,{3053,20},boolean,[]}]},{type,{3054,25},map_field_assoc,[{atom,{3054,12},error_logger},{type,{3054,28},boolean,[]}]}]}]}]},[]}},{seq_trace_info_returns,0} => {attribute,{327,2},type,{seq_trace_info_returns,{type,{328,7},union,[{type,{328,7},tuple,[{type,{328,9},union,[{atom,{328,9},send},{atom,{328,18},'receive'},{atom,{328,30},print},{atom,{328,40},timestamp},{atom,{328,54},monotonic_timestamp},{atom,{328,78},strict_monotonic_timestamp}]},{type,{328,108},boolean,[]}]},{type,{329,7},tuple,[{atom,{329,9},label},{type,{329,18},term,[]}]},{type,{330,7},tuple,[{atom,{330,9},serial},{type,{330,19},tuple,[{type,{330,21},non_neg_integer,[]},{type,{330,40},non_neg_integer,[]}]}]},{type,{331,7},nil,[]}]},[]}},{match_variable,0} => {attribute,{2767,2},type,{match_variable,{type,{2767,27},atom,[]},[]}},{registered_process_identifier,0} => {attribute,{1457,2},type,{registered_process_identifier,{type,{1457,42},union,[{user_type,{1457,42},registered_name,[]},{type,{1457,62},tuple,[{user_type,{1457,63},registered_name,[]},{type,{1457,82},node,[]}]}]},[]}}}},[{{function,'!',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,33,39,47,50>>],hidden,#{}},{{function,'*',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,42,39,47,50>>],hidden,#{}},{{function,'+',1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,43,39,47,49>>],hidden,#{}},{{function,'+',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,43,39,47,50>>],hidden,#{}},{{function,'++',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,43,43,39,47,50>>],hidden,#{}},{{function,'-',1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,45,39,47,49>>],hidden,#{}},{{function,'-',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,45,39,47,50>>],hidden,#{}},{{function,'--',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,45,45,39,47,50>>],hidden,#{}},{{function,'/',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,47,39,47,50>>],hidden,#{}},{{function,'/=',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,47,61,39,47,50>>],hidden,#{}},{{function,'<',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,60,39,47,50>>],hidden,#{}},{{function,'=/=',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,61,47,61,39,47,50>>],hidden,#{}},{{function,'=:=',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,61,58,61,39,47,50>>],hidden,#{}},{{function,'=<',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,61,60,39,47,50>>],hidden,#{}},{{function,'==',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,61,61,39,47,50>>],hidden,#{}},{{function,'>',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,62,39,47,50>>],hidden,#{}},{{function,'>=',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,62,61,39,47,50>>],hidden,#{}},{{function,alloc_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<97,108,108,111,99,95,105,110,102,111,47,49>>],hidden,#{}},{{function,alloc_sizes,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<97,108,108,111,99,95,115,105,122,101,115,47,49>>],hidden,#{}},{{function,'and',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,97,110,100,39,47,50>>],hidden,#{}},{{function,append,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<97,112,112,101,110,100,47,50>>],hidden,#{}},{{function,'band',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,98,97,110,100,39,47,50>>],hidden,#{}},{{function,'bnot',1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,98,110,111,116,39,47,49>>],hidden,#{}},{{function,'bor',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,98,111,114,39,47,50>>],hidden,#{}},{{function,'bsl',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,98,115,108,39,47,50>>],hidden,#{}},{{function,'bsr',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,98,115,114,39,47,50>>],hidden,#{}},{{function,'bxor',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,98,120,111,114,39,47,50>>],hidden,#{}},{{function,call_on_load_function,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<99,97,108,108,95,111,110,95,108,111,97,100,95,102,117,110,99,116,105,111,110,47,49>>],hidden,#{}},{{function,delay_trap,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,101,108,97,121,95,116,114,97,112,47,50>>],hidden,#{}},{{function,display_nl,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,105,115,112,108,97,121,95,110,108,47,48>>],hidden,#{}},{{function,display_string,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,105,115,112,108,97,121,95,115,116,114,105,110,103,47,49>>],hidden,#{}},{{function,dist_get_stat,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,105,115,116,95,103,101,116,95,115,116,97,116,47,49>>],hidden,#{}},{{function,'div',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,100,105,118,39,47,50>>],hidden,#{}},{{function,dmonitor_node,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,109,111,110,105,116,111,114,95,110,111,100,101,47,51>>],hidden,#{}},{{function,dt_append_vm_tag_data,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,97,112,112,101,110,100,95,118,109,95,116,97,103,95,100,97,116,97,47,49>>],hidden,#{}},{{function,dt_get_tag,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,103,101,116,95,116,97,103,47,48>>],hidden,#{}},{{function,dt_get_tag_data,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,103,101,116,95,116,97,103,95,100,97,116,97,47,48>>],hidden,#{}},{{function,dt_prepend_vm_tag_data,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,112,114,101,112,101,110,100,95,118,109,95,116,97,103,95,100,97,116,97,47,49>>],hidden,#{}},{{function,dt_put_tag,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,112,117,116,95,116,97,103,47,49>>],hidden,#{}},{{function,dt_restore_tag,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,114,101,115,116,111,114,101,95,116,97,103,47,49>>],hidden,#{}},{{function,dt_spread_tag,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<100,116,95,115,112,114,101,97,100,95,116,97,103,47,49>>],hidden,#{}},{{function,exit_signal,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<101,120,105,116,95,115,105,103,110,97,108,47,50>>],hidden,#{}},{{function,finish_after_on_load,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<102,105,110,105,115,104,95,97,102,116,101,114,95,111,110,95,108,111,97,100,47,50>>],hidden,#{}},{{function,finish_loading,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<102,105,110,105,115,104,95,108,111,97,100,105,110,103,47,49>>],hidden,#{}},{{function,format_cpu_topology,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<102,111,114,109,97,116,95,99,112,117,95,116,111,112,111,108,111,103,121,47,49>>],hidden,#{}},{{function,fun_info_mfa,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<102,117,110,95,105,110,102,111,95,109,102,97,47,49>>],hidden,#{}},{{function,garbage_collect_message_area,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,95,109,101,115,115,97,103,101,95,97,114,101,97,47,48>>],hidden,#{}},{{function,gather_gc_info_result,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<103,97,116,104,101,114,95,103,99,95,105,110,102,111,95,114,101,115,117,108,116,47,49>>],hidden,#{}},{{function,get_module_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<103,101,116,95,109,111,100,117,108,101,95,105,110,102,111,47,49>>],hidden,#{}},{{function,get_module_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<103,101,116,95,109,111,100,117,108,101,95,105,110,102,111,47,50>>],hidden,#{}},{{function,has_prepared_code_on_load,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<104,97,115,95,112,114,101,112,97,114,101,100,95,99,111,100,101,95,111,110,95,108,111,97,100,47,49>>],hidden,#{}},{{function,make_fun,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<109,97,107,101,95,102,117,110,47,51>>],hidden,#{}},{{function,'not',1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,110,111,116,39,47,49>>],hidden,#{}},{{function,'or',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,111,114,39,47,50>>],hidden,#{}},{{function,port_call,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<112,111,114,116,95,99,97,108,108,47,50>>],hidden,#{}},{{function,port_get_data,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<112,111,114,116,95,103,101,116,95,100,97,116,97,47,49>>],hidden,#{}},{{function,port_set_data,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<112,111,114,116,95,115,101,116,95,100,97,116,97,47,50>>],hidden,#{}},{{function,posixtime_to_universaltime,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<112,111,115,105,120,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,49>>],hidden,#{}},{{function,prepare_loading,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<112,114,101,112,97,114,101,95,108,111,97,100,105,110,103,47,50>>],hidden,#{}},{{function,'rem',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,114,101,109,39,47,50>>],hidden,#{}},{{function,seq_trace,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,113,95,116,114,97,99,101,47,50>>],hidden,#{}},{{function,seq_trace_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,113,95,116,114,97,99,101,95,105,110,102,111,47,49>>],hidden,#{}},{{function,seq_trace_print,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,113,95,116,114,97,99,101,95,112,114,105,110,116,47,49>>],hidden,#{}},{{function,seq_trace_print,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,113,95,116,114,97,99,101,95,112,114,105,110,116,47,50>>],hidden,#{}},{{function,set_cpu_topology,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,116,95,99,112,117,95,116,111,112,111,108,111,103,121,47,49>>],hidden,#{}},{{function,setnode,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,116,110,111,100,101,47,50>>],hidden,#{}},{{function,setnode,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,101,116,110,111,100,101,47,51>>],hidden,#{}},{{function,subtract,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<115,117,98,116,114,97,99,116,47,50>>],hidden,#{}},{{function,universaltime_to_posixtime,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<117,110,105,118,101,114,115,97,108,116,105,109,101,95,116,111,95,112,111,115,105,120,116,105,109,101,47,49>>],hidden,#{}},{{function,'xor',2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,0}],[<<39,120,111,114,39,47,50>>],hidden,#{}},{{function,abs,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2163}],[<<97,98,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,111,114,32,102,108,111,97,116,32,116,104,97,116,32,105,115,32,116,104,101,32,97,114,105,116,104,109,101,116,105,99,97,108,32,97,98,115,111,108,117,116,101,32,118,97,108,117,101,32,111,102,32>>,{code,[],[<<70,108,111,97,116>>]},<<32,111,114,32>>,{code,[],[<<73,110,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,98,115,40,45,51,46,51,51,41,46,10,51,46,51,51,10,62,32,97,98,115,40,45,51,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,54,56>>,signature => [{attribute,{2163,2},spec,{{abs,1},[{type,{2163,10},bounded_fun,[{type,{2163,10},'fun',[{type,{2163,10},product,[{var,{2163,11},'Float'}]},{type,{2163,21},float,[]}]},[{type,{2164,7},constraint,[{atom,{2164,7},is_subtype},[{var,{2164,7},'Float'},{type,{2164,16},float,[]}]]}]]},{type,{2165,10},bounded_fun,[{type,{2165,10},'fun',[{type,{2165,10},product,[{var,{2165,11},'Int'}]},{type,{2165,19},non_neg_integer,[]}]},[{type,{2166,7},constraint,[{atom,{2166,7},is_subtype},[{var,{2166,7},'Int'},{type,{2166,14},integer,[]}]]}]]}]}}]}},{{function,adler32,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,418}],[<<97,100,108,101,114,51,50,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,117,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,97,100,108,101,114,51,50,32,99,104,101,99,107,115,117,109,32,102,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,53>>,signature => [{attribute,{418,2},spec,{{erlang,adler32,1},[{type,{418,21},bounded_fun,[{type,{418,21},'fun',[{type,{418,21},product,[{var,{418,22},'Data'}]},{type,{418,31},non_neg_integer,[]}]},[{type,{419,7},constraint,[{atom,{419,7},is_subtype},[{var,{419,7},'Data'},{type,{419,15},iodata,[]}]]}]]}]}}]}},{{function,adler32,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,424}],[<<97,100,108,101,114,51,50,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,110,116,105,110,117,101,115,32,99,111,109,112,117,116,105,110,103,32,116,104,101,32,97,100,108,101,114,51,50,32,99,104,101,99,107,115,117,109,32,98,121,32,99,111,109,98,105,110,105,110,103,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,104,101,99,107,115,117,109,44,32>>,{code,[],[<<79,108,100,65,100,108,101,114>>]},<<44,32,119,105,116,104,32,116,104,101,32,99,104,101,99,107,115,117,109,32,111,102,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,88,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<89>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,91,68,97,116,97,49,44,68,97,116,97,50,93,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,52>>,signature => [{attribute,{424,2},spec,{{erlang,adler32,2},[{type,{424,21},bounded_fun,[{type,{424,21},'fun',[{type,{424,21},product,[{var,{424,22},'OldAdler'},{var,{424,32},'Data'}]},{type,{424,41},non_neg_integer,[]}]},[{type,{425,7},constraint,[{atom,{425,7},is_subtype},[{var,{425,7},'OldAdler'},{type,{425,19},non_neg_integer,[]}]]},{type,{426,7},constraint,[{atom,{426,7},is_subtype},[{var,{426,7},'Data'},{type,{426,15},iodata,[]}]]}]]}]}}]}},{{function,adler32_combine,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,431}],[<<97,100,108,101,114,51,50,95,99,111,109,98,105,110,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32,116,119,111,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,117,116,101,100,32,97,100,108,101,114,51,50,32,99,104,101,99,107,115,117,109,115,46,32,84,104,105,115,32,99,111,109,112,117,116,97,116,105,111,110,32,114,101,113,117,105,114,101,115,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,100,97,116,97,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101,32,115,101,99,111,110,100,32,99,104,101,99,107,115,117,109,32,116,111,32,98,101,32,107,110,111,119,110,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,49,41,44,10,90,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,89,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<90>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,40,68,97,116,97,50,41,44,10,90,32,61,32,101,114,108,97,110,103,58,97,100,108,101,114,51,50,95,99,111,109,98,105,110,101,40,88,44,89,44,105,111,108,105,115,116,95,115,105,122,101,40,68,97,116,97,50,41,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,49,49>>,signature => [{attribute,{431,2},spec,{{erlang,adler32_combine,3},[{type,{431,29},bounded_fun,[{type,{431,29},'fun',[{type,{431,29},product,[{var,{431,30},'FirstAdler'},{var,{431,42},'SecondAdler'},{var,{431,55},'SecondSize'}]},{type,{431,70},non_neg_integer,[]}]},[{type,{432,7},constraint,[{atom,{432,7},is_subtype},[{var,{432,7},'FirstAdler'},{type,{432,21},non_neg_integer,[]}]]},{type,{433,7},constraint,[{atom,{433,7},is_subtype},[{var,{433,7},'SecondAdler'},{type,{433,22},non_neg_integer,[]}]]},{type,{434,7},constraint,[{atom,{434,7},is_subtype},[{var,{434,7},'SecondSize'},{type,{434,21},non_neg_integer,[]}]]}]]}]}}]}},{{function,alias,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,824}],[<<97,108,105,97,115,47,49>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,48>>,equiv => {function,alias,0},signature => [{attribute,{824,2},spec,{{alias,1},[{type,{824,12},bounded_fun,[{type,{824,12},'fun',[{type,{824,12},product,[{var,{824,13},'Opts'}]},{var,{824,22},'Alias'}]},[{type,{825,7},constraint,[{atom,{825,7},is_subtype},[{var,{825,7},'Alias'},{type,{825,16},reference,[]}]]},{type,{826,7},constraint,[{atom,{826,7},is_subtype},[{var,{826,7},'Opts'},{type,{826,15},list,[{type,{826,16},union,[{atom,{826,16},explicit_unalias},{atom,{826,37},reply}]}]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,alias,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,818}],[<<97,108,105,97,115,47,48>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,32,97,110,32,97,108,105,97,115,32,119,104,105,99,104,32,99,97,110,32,98,101,32,117,115,101,100,32,119,104,101,110,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,97,108,105,97,115,46,32,87,104,101,110,32,116,104,101,32,97,108,105,97,115,32,104,97,115,32,98,101,101,110,32,100,101,97,99,116,105,118,97,116,101,100,44,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,117,115,105,110,103,32,116,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,100,114,111,112,112,101,100,46,32,65,110,32,97,108,105,97,115,32,99,97,110,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,97,108,105,97,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,97,108,105,97,115,47,49>>]}]},<<46,32,67,117,114,114,101,110,116,108,121,32,97,118,97,105,108,97,98,108,101,32,111,112,116,105,111,110,115,32,102,111,114,32>>,{code,[],[<<97,108,105,97,115,47,49>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,112,108,105,99,105,116,95,117,110,97,108,105,97,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,99,97,110,32,111,110,108,121,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46,32,84,104,105,115,32,105,115,32,97,108,115,111,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,117,114,32,105,102,32,110,111,32,111,112,116,105,111,110,115,32,97,114,101,32,112,97,115,115,101,100,32,111,114,32,105,102,32>>,{code,[],[<<97,108,105,97,115,47,48>>]},<<32,105,115,32,99,97,108,108,101,100,46>>]}]},{dt,[],[{code,[],[<<114,101,112,108,121>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,119,104,101,110,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,115,101,110,116,32,118,105,97,32,116,104,101,32,97,108,105,97,115,32,105,115,32,114,101,99,101,105,118,101,100,46,32,84,104,101,32,97,108,105,97,115,32,99,97,110,32,97,108,115,111,32,115,116,105,108,108,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<115,101,114,118,101,114,40,41,32,45,62,10,32,32,32,32,114,101,99,101,105,118,101,10,32,32,32,32,32,32,32,32,123,114,101,113,117,101,115,116,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,113,117,101,115,116,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,82,101,115,117,108,116,32,61,32,112,101,114,102,111,114,109,95,114,101,113,117,101,115,116,40,82,101,113,117,101,115,116,41,44,10,32,32,32,32,32,32,32,32,32,32,32,32,65,108,105,97,115,82,101,113,73,100,32,33,32,123,114,101,112,108,121,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,115,117,108,116,125,10,32,32,32,32,101,110,100,44,10,32,32,32,32,115,101,114,118,101,114,40,41,46,10,10,99,108,105,101,110,116,40,83,101,114,118,101,114,80,105,100,44,32,82,101,113,117,101,115,116,41,32,45,62,10,32,32,32,32,65,108,105,97,115,82,101,113,73,100,32,61,32,97,108,105,97,115,40,91,114,101,112,108,121,93,41,44,10,32,32,32,32,83,101,114,118,101,114,80,105,100,32,33,32,123,114,101,113,117,101,115,116,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,113,117,101,115,116,125,44,10,32,32,32,32,37,37,32,65,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,105,102,32,119,101,32,114,101,99,101,105,118,101,32,97,32,114,101,112,108,121,10,32,32,32,32,37,37,32,115,105,110,99,101,32,119,101,32,117,115,101,100,32,116,104,101,32,39,114,101,112,108,121,39,32,111,112,116,105,111,110,46,46,46,10,32,32,32,32,114,101,99,101,105,118,101,10,32,32,32,32,32,32,32,32,123,114,101,112,108,121,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,115,117,108,116,125,32,45,62,32,82,101,115,117,108,116,10,32,32,32,32,97,102,116,101,114,32,53,48,48,48,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,117,110,97,108,105,97,115,40,65,108,105,97,115,82,101,113,73,100,41,44,10,32,32,32,32,32,32,32,32,32,32,32,32,37,37,32,70,108,117,115,104,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,105,110,32,99,97,115,101,32,116,104,101,32,114,101,112,108,121,32,97,114,114,105,118,101,100,10,32,32,32,32,32,32,32,32,32,32,32,32,37,37,32,106,117,115,116,32,98,101,102,111,114,101,32,116,104,101,32,97,108,105,97,115,32,119,97,115,32,100,101,97,99,116,105,118,97,116,101,100,46,46,46,10,32,32,32,32,32,32,32,32,32,32,32,32,114,101,99,101,105,118,101,32,123,114,101,112,108,121,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,115,117,108,116,125,32,45,62,32,82,101,115,117,108,116,10,32,32,32,32,32,32,32,32,32,32,32,32,97,102,116,101,114,32,48,32,45,62,32,101,120,105,116,40,116,105,109,101,111,117,116,41,10,32,32,32,32,32,32,32,32,32,32,32,32,101,110,100,10,32,32,32,32,101,110,100,46,10,9>>]}]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,98,111,116,104,32,116,104,101,32,115,101,114,118,101,114,32,97,110,100,32,116,104,101,32,99,108,105,101,110,116,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,32,109,117,115,116,32,98,101,32,101,120,101,99,117,116,105,110,103,32,111,110,32,97,116,32,108,101,97,115,116,32,79,84,80,32,50,52,32,115,121,115,116,101,109,115,32,105,110,32,111,114,100,101,114,32,102,111,114,32,116,104,105,115,32,116,111,32,119,111,114,107,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,111,99,101,115,115,32,97,108,105,97,115,101,115,32,115,101,101,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,112,114,111,99,101,115,115,45,97,108,105,97,115,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{i,[],[<<80,114,111,99,101,115,115,32,65,108,105,97,115,101,115>>]}]},<<32,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,48>>,signature => [{attribute,{818,2},spec,{{alias,0},[{type,{818,12},bounded_fun,[{type,{818,12},'fun',[{type,{818,12},product,[]},{var,{818,18},'Alias'}]},[{type,{819,7},constraint,[{atom,{819,7},is_subtype},[{var,{819,7},'Alias'},{type,{819,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,append_element,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,439}],[<<97,112,112,101,110,100,95,101,108,101,109,101,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,101,119,32,116,117,112,108,101,32,116,104,97,116,32,104,97,115,32,111,110,101,32,101,108,101,109,101,110,116,32,109,111,114,101,32,116,104,97,110,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<44,32,97,110,100,32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,105,110,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<32,102,111,108,108,111,119,101,100,32,98,121,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,115,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,46,32,83,101,109,97,110,116,105,99,97,108,108,121,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<108,105,115,116,95,116,111,95,116,117,112,108,101,40,116,117,112,108,101,95,116,111,95,108,105,115,116,40,84,117,112,108,101,49,41,32,43,43,32,91,84,101,114,109,93,41>>]},<<44,32,98,117,116,32,109,117,99,104,32,102,97,115,116,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,97,112,112,101,110,100,95,101,108,101,109,101,110,116,40,123,111,110,101,44,32,116,119,111,125,44,32,116,104,114,101,101,41,46,10,123,111,110,101,44,116,119,111,44,116,104,114,101,101,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,57>>,signature => [{attribute,{439,2},spec,{{erlang,append_element,2},[{type,{439,28},bounded_fun,[{type,{439,28},'fun',[{type,{439,28},product,[{var,{439,29},'Tuple1'},{var,{439,37},'Term'}]},{var,{439,46},'Tuple2'}]},[{type,{440,7},constraint,[{atom,{440,7},is_subtype},[{var,{440,7},'Tuple1'},{type,{440,17},tuple,any}]]},{type,{441,7},constraint,[{atom,{441,7},is_subtype},[{var,{441,7},'Tuple2'},{type,{441,17},tuple,any}]]},{type,{442,7},constraint,[{atom,{442,7},is_subtype},[{var,{442,7},'Term'},{type,{442,15},term,[]}]]}]]}]}}]}},{{function,apply,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2956}],[<<97,112,112,108,121,47,50>>],#{<<101,110>> => [{p,[],[<<67,97,108,108,115,32,97,32,102,117,110,44,32,112,97,115,115,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,105,110,32>>,{code,[],[<<65,114,103,115>>]},<<32,97,115,32,97,114,103,117,109,101,110,116,115,46>>]},{p,[],[<<73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,105,110,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,107,110,111,119,110,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,44,32,116,104,101,32,99,97,108,108,32,105,115,32,98,101,116,116,101,114,32,119,114,105,116,116,101,110,32,97,115,32>>,{code,[],[<<70,117,110,40,65,114,103,49,44,32,65,114,103,50,44,32,46,46,46,32,65,114,103,78,41>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<69,97,114,108,105,101,114,44,32>>,{code,[],[<<70,117,110>>]},<<32,99,111,117,108,100,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,125>>]},<<44,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<97,112,112,108,121,40,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,103,115,41>>]},<<46,32>>,{em,[],[<<84,104,105,115,32,117,115,101,32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97,110,100,32,119,105,108,108,32,115,116,111,112,32,119,111,114,107,105,110,103,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,54>>,signature => [{attribute,{2956,2},spec,{{apply,2},[{type,{2956,12},bounded_fun,[{type,{2956,12},'fun',[{type,{2956,12},product,[{var,{2956,13},'Fun'},{var,{2956,18},'Args'}]},{type,{2956,27},term,[]}]},[{type,{2957,7},constraint,[{atom,{2957,7},is_subtype},[{var,{2957,7},'Fun'},{type,{2957,14},function,[]}]]},{type,{2958,7},constraint,[{atom,{2958,7},is_subtype},[{var,{2958,7},'Args'},{type,{2958,15},list,[{type,{2958,16},term,[]}]}]]}]]}]}}]}},{{function,apply,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2963}],[<<97,112,112,108,121,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,110,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,84,104,101,32,97,112,112,108,105,101,100,32,102,117,110,99,116,105,111,110,32,109,117,115,116,32,98,101,32,101,120,112,111,114,116,101,100,32,102,114,111,109,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46,32,84,104,101,32,97,114,105,116,121,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,112,112,108,121,40,108,105,115,116,115,44,32,114,101,118,101,114,115,101,44,32,91,91,97,44,32,98,44,32,99,93,93,41,46,10,91,99,44,98,44,97,93,10,62,32,97,112,112,108,121,40,101,114,108,97,110,103,44,32,97,116,111,109,95,116,111,95,108,105,115,116,44,32,91,39,69,114,108,97,110,103,39,93,41,46,10,34,69,114,108,97,110,103,34>>]}]},{p,[],[<<73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,107,110,111,119,110,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,44,32,116,104,101,32,99,97,108,108,32,105,115,32,98,101,116,116,101,114,32,119,114,105,116,116,101,110,32,97,115,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,40,65,114,103,49,44,32,65,114,103,50,44,32,46,46,46,44,32,65,114,103,78,41>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{a,[{href,<<107,101,114,110,101,108,58,101,114,114,111,114,95,104,97,110,100,108,101,114,35,117,110,100,101,102,105,110,101,100,95,102,117,110,99,116,105,111,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114,58,117,110,100,101,102,105,110,101,100,95,102,117,110,99,116,105,111,110,47,51>>]}]},<<32,105,115,32,99,97,108,108,101,100,32,105,102,32,116,104,101,32,97,112,112,108,105,101,100,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,101,120,112,111,114,116,101,100,46,32,84,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,99,97,110,32,98,101,32,114,101,100,101,102,105,110,101,100,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<41,46,32,73,102,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,111,114,32,105,102,32,116,104,101,32,117,115,101,114,32,104,97,115,32,114,101,100,101,102,105,110,101,100,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,115,111,32,116,104,101,32,114,101,112,108,97,99,101,109,101,110,116,32,109,111,100,117,108,101,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,110,32,101,114,114,111,114,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<117,110,100,101,102>>]},<<32,105,115,32,103,101,110,101,114,97,116,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,51,52>>,signature => [{attribute,{2963,2},spec,{{apply,3},[{type,{2963,12},bounded_fun,[{type,{2963,12},'fun',[{type,{2963,12},product,[{var,{2963,13},'Module'},{var,{2963,21},'Function'},{var,{2963,31},'Args'}]},{type,{2963,40},term,[]}]},[{type,{2964,7},constraint,[{atom,{2964,7},is_subtype},[{var,{2964,7},'Module'},{type,{2964,17},module,[]}]]},{type,{2965,7},constraint,[{atom,{2965,7},is_subtype},[{var,{2965,7},'Function'},{type,{2965,19},atom,[]}]]},{type,{2966,7},constraint,[{atom,{2966,7},is_subtype},[{var,{2966,7},'Args'},{type,{2966,15},list,[{type,{2966,16},term,[]}]}]]}]]}]}}]}},{{function,atom_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,447}],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,97,116,111,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121>>]},<<32>>]},{code,[],[<<40,65,116,111,109,44,32,117,116,102,56,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,54,52>>,signature => [{attribute,{447,2},spec,{{atom_to_binary,1},[{type,{447,21},bounded_fun,[{type,{447,21},'fun',[{type,{447,21},product,[{var,{447,22},'Atom'}]},{type,{447,31},binary,[]}]},[{type,{448,7},constraint,[{atom,{448,7},is_subtype},[{var,{448,7},'Atom'},{type,{448,15},atom,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,atom_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,458}],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<65,116,111,109>>]},<<46,32,73,102,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<32,105,115,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,111,110,101,32,98,121,116,101,32,101,120,105,115,116,115,32,102,111,114,32,101,97,99,104,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46,32,73,102,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,111,114,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,85,84,70,45,56,32,119,104,101,114,101,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,114,101,113,117,105,114,101,32,109,117,108,116,105,112,108,101,32,98,121,116,101,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,50,48,44,32,97,116,111,109,115,32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,97,110,100,32>>,{code,[],[<<97,116,111,109,95,116,111,95,98,105,110,97,114,121,40,65,116,111,109,44,32,108,97,116,105,110,49,41>>]},<<32,109,97,121,32,102,97,105,108,32,105,102,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,102,111,114,32>>,{code,[],[<<65,116,111,109>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,62,32,50,53,53,46>>]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,116,111,109,95,116,111,95,98,105,110,97,114,121,40,39,69,114,108,97,110,103,39,44,32,108,97,116,105,110,49,41,46,10,60,60,34,69,114,108,97,110,103,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,52>>,signature => [{attribute,{458,2},spec,{{atom_to_binary,2},[{type,{458,21},bounded_fun,[{type,{458,21},'fun',[{type,{458,21},product,[{var,{458,22},'Atom'},{var,{458,28},'Encoding'}]},{type,{458,41},binary,[]}]},[{type,{459,7},constraint,[{atom,{459,7},is_subtype},[{var,{459,7},'Atom'},{type,{459,15},atom,[]}]]},{type,{460,7},constraint,[{atom,{460,7},is_subtype},[{var,{460,7},'Encoding'},{type,{460,19},union,[{atom,{460,19},latin1},{atom,{460,28},unicode},{atom,{460,38},utf8}]}]]}]]}]}}]}},{{function,atom_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,465}],[<<97,116,111,109,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,117,110,105,99,111,100,101,32,99,111,100,101,32,112,111,105,110,116,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<65,116,111,109>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,97,116,111,109,95,116,111,95,108,105,115,116,40,39,69,114,108,97,110,103,39,41,46,10,34,69,114,108,97,110,103,34>>]}]},{pre,[],[{code,[],[<<62,32,97,116,111,109,95,116,111,95,108,105,115,116,40,39,228,189,160,229,165,189,39,41,46,10,91,50,48,51,50,48,44,50,50,57,48,57,93>>]}]},{p,[],[<<83,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,105,99,111,100,101,40,51,41>>]}]},<<32,102,111,114,32,104,111,119,32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,32,116,111,32,100,105,102,102,101,114,101,110,116,32,102,111,114,109,97,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,57,57>>,signature => [{attribute,{465,2},spec,{{atom_to_list,1},[{type,{465,19},bounded_fun,[{type,{465,19},'fun',[{type,{465,19},product,[{var,{465,20},'Atom'}]},{type,{465,29},string,[]}]},[{type,{466,7},constraint,[{atom,{466,7},is_subtype},[{var,{466,7},'Atom'},{type,{466,15},atom,[]}]]}]]}]}}]}},{{function,binary_part,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,472}],[<<98,105,110,97,114,121,95,112,97,114,116,47,50>>],#{<<101,110>> => [{p,[],[<<69,120,116,114,97,99,116,115,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,100,101,115,99,114,105,98,101,100,32,98,121,32>>,{code,[],[<<80,111,115,76,101,110>>]},<<46>>]},{p,[],[<<78,101,103,97,116,105,118,101,32,108,101,110,103,116,104,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,101,120,116,114,97,99,116,32,98,121,116,101,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,97,32,98,105,110,97,114,121,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<49,62,32,66,105,110,32,61,32,60,60,49,44,50,44,51,44,52,44,53,44,54,44,55,44,56,44,57,44,49,48,62,62,46,10,50,62,32,98,105,110,97,114,121,95,112,97,114,116,40,66,105,110,44,123,98,121,116,101,95,115,105,122,101,40,66,105,110,41,44,32,45,53,125,41,46,10,60,60,54,44,55,44,56,44,57,44,49,48,62,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,115,76,101,110>>]},<<32,105,110,32,97,110,121,32,119,97,121,32,114,101,102,101,114,101,110,99,101,115,32,111,117,116,115,105,100,101,32,116,104,101,32,98,105,110,97,114,121,46>>]},{p,[],[{code,[],[<<83,116,97,114,116>>]},<<32,105,115,32,122,101,114,111,45,98,97,115,101,100,44,32,116,104,97,116,32,105,115,58>>]},{pre,[],[{code,[],[<<49,62,32,66,105,110,32,61,32,60,60,49,44,50,44,51,62,62,10,50,62,32,98,105,110,97,114,121,95,112,97,114,116,40,66,105,110,44,123,48,44,50,125,41,46,10,60,60,49,44,50,62,62>>]}]},{p,[],[<<70,111,114,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<80,111,115,76,101,110>>]},<<32,115,101,109,97,110,116,105,99,115,44,32,115,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,98,105,110,97,114,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<98,105,110,97,114,121,40,51,41>>]}]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,55>>,signature => [{attribute,{472,2},spec,{{binary_part,2},[{type,{472,18},bounded_fun,[{type,{472,18},'fun',[{type,{472,18},product,[{var,{472,19},'Subject'},{var,{472,28},'PosLen'}]},{type,{472,39},binary,[]}]},[{type,{473,7},constraint,[{atom,{473,7},is_subtype},[{var,{473,7},'Subject'},{type,{473,18},binary,[]}]]},{type,{474,7},constraint,[{atom,{474,7},is_subtype},[{var,{474,7},'PosLen'},{type,{474,17},tuple,[{ann_type,{474,18},[{var,{474,18},'Start'},{type,{474,27},non_neg_integer,[]}]},{ann_type,{474,46},[{var,{474,46},'Length'},{type,{474,56},integer,[]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,binary_part,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,480}],[<<98,105,110,97,114,121,95,112,97,114,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<98,105,110,97,114,121,95,112,97,114,116,40,83,117,98,106,101,99,116,44,32,123,83,116,97,114,116,44,32,76,101,110,103,116,104,125,41>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,52,50>>,signature => [{attribute,{480,2},spec,{{binary_part,3},[{type,{480,18},bounded_fun,[{type,{480,18},'fun',[{type,{480,18},product,[{var,{480,19},'Subject'},{var,{480,28},'Start'},{var,{480,35},'Length'}]},{type,{480,46},binary,[]}]},[{type,{481,7},constraint,[{atom,{481,7},is_subtype},[{var,{481,7},'Subject'},{type,{481,18},binary,[]}]]},{type,{482,7},constraint,[{atom,{482,7},is_subtype},[{var,{482,7},'Start'},{type,{482,16},non_neg_integer,[]}]]},{type,{483,7},constraint,[{atom,{483,7},is_subtype},[{var,{483,7},'Length'},{type,{483,17},integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,binary_to_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,488}],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109>>]},<<32>>]},{code,[],[<<40,66,105,110,97,114,121,44,32,117,116,102,56,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,50>>,signature => [{attribute,{488,2},spec,{{binary_to_atom,1},[{type,{488,21},bounded_fun,[{type,{488,21},'fun',[{type,{488,21},product,[{var,{488,22},'Binary'}]},{type,{488,33},atom,[]}]},[{type,{489,7},constraint,[{atom,{489,7},is_subtype},[{var,{489,7},'Binary'},{type,{489,17},binary,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,binary_to_atom,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,498}],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46,32,73,102,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,111,114,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,116,104,101,32,98,105,110,97,114,121,32,109,117,115,116,32,99,111,110,116,97,105,110,32,118,97,108,105,100,32,85,84,70,45,56,32,115,101,113,117,101,110,99,101,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,50,48,44,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,40,66,105,110,97,114,121,44,32,117,116,102,56,41>>]},<<32,105,115,32,99,97,112,97,98,108,101,32,111,102,32,100,101,99,111,100,105,110,103,32,97,110,121,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,46,32,69,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,119,111,117,108,100,32,102,97,105,108,32,105,102,32,116,104,101,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,101,100,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,62,32,50,53,53,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,97,110,32,97,116,111,109,32,110,97,109,101,32,105,115,32,108,105,109,105,116,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,99,111,110,102,105,103,117,114,97,98,108,101,32,108,105,109,105,116,32,111,110,32,104,111,119,32,109,97,110,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,101,120,105,115,116,32,97,110,100,32,97,116,111,109,115,32,97,114,101,32,110,111,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,99,111,110,115,105,100,101,114,32,119,104,101,116,104,101,114,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,50>>]},<<32,105,115,32,97,32,98,101,116,116,101,114,32,111,112,116,105,111,110,32,116,104,97,110,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,97,116,111,109,40,60,60,34,69,114,108,97,110,103,34,62,62,44,32,108,97,116,105,110,49,41,46,10,39,69,114,108,97,110,103,39>>]}]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,97,116,111,109,40,60,60,49,48,50,52,47,117,116,102,56,62,62,44,32,117,116,102,56,41,46,10,39,208,128,39>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,54,50>>,signature => [{attribute,{498,2},spec,{{binary_to_atom,2},[{type,{498,21},bounded_fun,[{type,{498,21},'fun',[{type,{498,21},product,[{var,{498,22},'Binary'},{var,{498,30},'Encoding'}]},{type,{498,43},atom,[]}]},[{type,{499,7},constraint,[{atom,{499,7},is_subtype},[{var,{499,7},'Binary'},{type,{499,17},binary,[]}]]},{type,{500,7},constraint,[{atom,{500,7},is_subtype},[{var,{500,7},'Encoding'},{type,{500,19},union,[{atom,{500,19},latin1},{atom,{500,28},unicode},{atom,{500,38},utf8}]}]]}]]}]}}]}},{{function,binary_to_existing_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,505}],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109>>]}]},<<32>>,{code,[],[<<40,66,105,110,97,114,121,44,32,117,116,102,56,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,48,49>>,signature => [{attribute,{505,2},spec,{{binary_to_existing_atom,1},[{type,{505,30},bounded_fun,[{type,{505,30},'fun',[{type,{505,30},product,[{var,{505,31},'Binary'}]},{type,{505,42},atom,[]}]},[{type,{506,7},constraint,[{atom,{506,7},is_subtype},[{var,{506,7},'Binary'},{type,{506,17},binary,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,binary_to_existing_atom,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,515}],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,50>>],#{<<101,110>> => [{p,[],[<<65,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]}]},<<44,32,98,117,116,32,116,104,101,32,97,116,111,109,32,109,117,115,116,32,101,120,105,115,116,46>>]},{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,104,97,115,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,111,110,102,105,103,117,114,97,98,108,101,32,108,105,109,105,116>>]},<<32,102,111,114,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,101,120,105,115,116,44,32,97,110,100,32,97,116,111,109,115,32,97,114,101,32,110,111,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,105,115,32,110,111,116,32,115,97,102,101,32,116,111,32,99,114,101,97,116,101,32,109,97,110,121,32,97,116,111,109,115,32,102,114,111,109,32,98,105,110,97,114,105,101,115,32,116,104,97,116,32,99,111,109,101,32,102,114,111,109,32,97,110,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,105,108,101,32,102,101,116,99,104,101,100,32,102,114,111,109,32,116,104,101,32,73,110,116,101,114,110,101,116,41,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]}]},<<46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,104,117,115,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,111,112,116,105,111,110,32,119,104,101,110,32,116,104,101,32,105,110,112,117,116,32,98,105,110,97,114,121,32,99,111,109,101,115,32,102,114,111,109,32,97,110,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,46>>]},{p,[],[<<65,110,32,97,116,111,109,32,101,120,105,115,116,115,32,105,110,32,97,110,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,119,104,101,110,32,105,110,99,108,117,100,101,100,32,105,110,32,97,32,108,111,97,100,101,100,32,69,114,108,97,110,103,32,109,111,100,117,108,101,32,111,114,32,119,104,101,110,32,99,114,101,97,116,101,100,32,112,114,111,103,114,97,109,109,97,116,105,99,97,108,108,121,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,98,121,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,97,116,111,109,47,50>>]},<<41,46,32,83,101,101,32,116,104,101,32,110,101,120,116,32,110,111,116,101,32,102,111,114,32,97,110,32,101,120,97,109,112,108,101,32,111,102,32,119,104,101,110,32,97,110,32,97,116,111,109,32,101,120,105,115,116,115,32,105,110,32,116,104,101,32,115,111,117,114,99,101,32,99,111,100,101,32,102,111,114,32,97,110,32,69,114,108,97,110,103,32,109,111,100,117,108,101,32,98,117,116,32,110,111,116,32,105,110,32,116,104,101,32,99,111,109,112,105,108,101,100,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,115,97,109,101,32,109,111,100,117,108,101,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,97,116,111,109,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,99,111,109,112,105,108,101,114,32,109,97,121,32,111,112,116,105,109,105,122,101,32,97,119,97,121,32,97,116,111,109,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,111,109,112,105,108,101,114,32,119,105,108,108,32,114,101,119,114,105,116,101,32>>,{code,[],[<<97,116,111,109,95,116,111,95,108,105,115,116,40,115,111,109,101,95,97,116,111,109,41>>]},<<32,116,111,32>>,{code,[],[<<34,115,111,109,101,95,97,116,111,109,34>>]},<<46,32,73,102,32,116,104,97,116,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,104,101,32,111,110,108,121,32,109,101,110,116,105,111,110,32,111,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,111,109,101,95,97,116,111,109>>]},<<32,105,110,32,116,104,101,32,99,111,110,116,97,105,110,105,110,103,32,109,111,100,117,108,101,44,32,116,104,101,32,97,116,111,109,32,119,105,108,108,32,110,111,116,32,98,101,32,99,114,101,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32,108,111,97,100,101,100,44,32,97,110,100,32,97,32,115,117,98,115,101,113,117,101,110,116,32,99,97,108,108,32,116,111,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,40,60,60,34,115,111,109,101,95,97,116,111,109,34,62,62,44,32,117,116,102,56,41>>]},<<32,119,105,108,108,32,102,97,105,108,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,97,110,32,97,116,111,109,32,110,97,109,101,32,105,115,32,108,105,109,105,116,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,50>>,signature => [{attribute,{515,2},spec,{{binary_to_existing_atom,2},[{type,{515,30},bounded_fun,[{type,{515,30},'fun',[{type,{515,30},product,[{var,{515,31},'Binary'},{var,{515,39},'Encoding'}]},{type,{515,52},atom,[]}]},[{type,{516,7},constraint,[{atom,{516,7},is_subtype},[{var,{516,7},'Binary'},{type,{516,17},binary,[]}]]},{type,{517,7},constraint,[{atom,{517,7},is_subtype},[{var,{517,7},'Encoding'},{type,{517,19},union,[{atom,{517,19},latin1},{atom,{517,28},unicode},{atom,{517,38},utf8}]}]]}]]}]}}]}},{{function,binary_to_float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,522}],[<<98,105,110,97,114,121,95,116,111,95,102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,102,108,111,97,116,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,102,108,111,97,116,40,60,60,34,50,46,50,48,49,55,55,54,52,101,43,48,34,62,62,41,46,10,50,46,50,48,49,55,55,54,52>>]}]},{p,[],[<<84,104,101,32,102,108,111,97,116,32,115,116,114,105,110,103,32,102,111,114,109,97,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,102,111,114,109,97,116,32,102,111,114,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,102,108,111,97,116,32,108,105,116,101,114,97,108,115>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,97,116,32,117,110,100,101,114,115,99,111,114,101,115,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,102,108,111,97,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,53,54>>,signature => [{attribute,{522,2},spec,{{binary_to_float,1},[{type,{522,22},bounded_fun,[{type,{522,22},'fun',[{type,{522,22},product,[{var,{522,23},'Binary'}]},{type,{522,34},float,[]}]},[{type,{523,7},constraint,[{atom,{523,7},is_subtype},[{var,{523,7},'Binary'},{type,{523,17},binary,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,binary_to_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,528}],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,40,60,60,34,49,50,51,34,62,62,41,46,10,49,50,51>>]}]},{p,[],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,49>>]},<<32,97,99,99,101,112,116,115,32,116,104,101,32,115,97,109,101,32,115,116,114,105,110,103,32,102,111,114,109,97,116,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,49>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,55,52>>,signature => [{attribute,{528,2},spec,{{binary_to_integer,1},[{type,{528,24},bounded_fun,[{type,{528,24},'fun',[{type,{528,24},product,[{var,{528,25},'Binary'}]},{type,{528,36},integer,[]}]},[{type,{529,7},constraint,[{atom,{529,7},is_subtype},[{var,{529,7},'Binary'},{type,{529,17},binary,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,binary_to_integer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,534}],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<32,105,115,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,40,60,60,34,51,70,70,34,62,62,44,32,49,54,41,46,10,49,48,50,51>>]}]},{p,[],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,105,110,116,101,103,101,114,47,50>>]},<<32,97,99,99,101,112,116,115,32,116,104,101,32,115,97,109,101,32,115,116,114,105,110,103,32,102,111,114,109,97,116,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,50>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,57,49>>,signature => [{attribute,{534,2},spec,{{binary_to_integer,2},[{type,{534,24},bounded_fun,[{type,{534,24},'fun',[{type,{534,24},product,[{var,{534,25},'Binary'},{var,{534,32},'Base'}]},{type,{534,41},integer,[]}]},[{type,{535,7},constraint,[{atom,{535,7},is_subtype},[{var,{535,7},'Binary'},{type,{535,17},binary,[]}]]},{type,{536,7},constraint,[{atom,{536,7},is_subtype},[{var,{536,7},'Base'},{type,{536,15},range,[{integer,{536,15},2},{integer,{536,18},36}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,binary_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,541}],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,121,116,101,115,32,111,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,48,57>>,signature => [{attribute,{541,2},spec,{{binary_to_list,1},[{type,{541,21},bounded_fun,[{type,{541,21},'fun',[{type,{541,21},product,[{var,{541,22},'Binary'}]},{type,{541,33},list,[{type,{541,34},byte,[]}]}]},[{type,{542,7},constraint,[{atom,{542,7},is_subtype},[{var,{542,7},'Binary'},{type,{542,17},binary,[]}]]}]]}]}}]}},{{function,binary_to_list,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,547}],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<65,115,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,49>>]},<<44,32,98,117,116,32,114,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,121,116,101,115,32,102,114,111,109,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<83,116,97,114,116>>]},<<32,116,111,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<83,116,111,112>>]},<<32,105,110,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46,32,84,104,101,32,112,111,115,105,116,105,111,110,115,32,105,110,32,116,104,101,32,98,105,110,97,114,121,32,97,114,101,32,110,117,109,98,101,114,101,100,32,115,116,97,114,116,105,110,103,32,102,114,111,109,32,49,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{em,[],[<<84,104,101,32,111,110,101,45,98,97,115,101,100,32,105,110,100,101,120,105,110,103,32,102,111,114,32,98,105,110,97,114,105,101,115,32,117,115,101,100,32,98,121,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46>>]},<<32,78,101,119,32,99,111,100,101,32,105,115,32,116,111,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,98,105,110,97,114,121,35,98,105,110,95,116,111,95,108,105,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,58,98,105,110,95,116,111,95,108,105,115,116,47,51>>]}]},<<32,105,110,32,83,84,68,76,73,66,32,105,110,115,116,101,97,100,46,32,65,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,109,111,100,117,108,101,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,99,111,110,115,105,115,116,101,110,116,108,121,32,117,115,101,32,122,101,114,111,45,98,97,115,101,100,32,105,110,100,101,120,105,110,103,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,49,56>>,signature => [{attribute,{547,2},spec,{{binary_to_list,3},[{type,{547,21},bounded_fun,[{type,{547,21},'fun',[{type,{547,21},product,[{var,{547,22},'Binary'},{var,{547,30},'Start'},{var,{547,37},'Stop'}]},{type,{547,46},list,[{type,{547,47},byte,[]}]}]},[{type,{548,7},constraint,[{atom,{548,7},is_subtype},[{var,{548,7},'Binary'},{type,{548,17},binary,[]}]]},{type,{549,7},constraint,[{atom,{549,7},is_subtype},[{var,{549,7},'Start'},{type,{549,16},pos_integer,[]}]]},{type,{550,7},constraint,[{atom,{550,7},is_subtype},[{var,{550,7},'Stop'},{type,{550,15},pos_integer,[]}]]}]]}]}}]}},{{function,binary_to_term,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,555}],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,69,114,108,97,110,103,32,116,101,114,109,32,116,104,97,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,100,101,99,111,100,105,110,103,32,98,105,110,97,114,121,32,111,98,106,101,99,116,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<44,32,119,104,105,99,104,32,109,117,115,116,32,98,101,32,101,110,99,111,100,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,101,120,116,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116>>]},<<46>>]},{pre,[],[{code,[],[<<62,32,66,105,110,32,61,32,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,104,101,108,108,111,41,46,10,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,62,62,10,62,32,104,101,108,108,111,32,61,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,66,105,110,41,46,10,104,101,108,108,111>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<87,104,101,110,32,100,101,99,111,100,105,110,103,32,98,105,110,97,114,105,101,115,32,102,114,111,109,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,115,44,32,116,104,101,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,32,109,97,121,32,115,117,98,109,105,116,32,100,97,116,97,32,105,110,32,97,32,119,97,121,32,116,111,32,99,114,101,97,116,101,32,114,101,115,111,117,114,99,101,115,44,32,115,117,99,104,32,97,115,32,97,116,111,109,115,32,97,110,100,32,114,101,109,111,116,101,32,114,101,102,101,114,101,110,99,101,115,44,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,32,97,110,100,32,108,101,97,100,32,116,111,32,68,101,110,105,97,108,32,111,102,32,83,101,114,118,105,99,101,32,97,116,116,97,99,107,46,32,73,110,32,115,117,99,104,32,99,97,115,101,115,44,32,99,111,110,115,105,100,101,114,32,117,115,105,110,103,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>]},<<32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<115,97,102,101>>]},<<32,111,112,116,105,111,110,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,52,48>>,signature => [{attribute,{555,2},spec,{{binary_to_term,1},[{type,{555,21},bounded_fun,[{type,{555,21},'fun',[{type,{555,21},product,[{var,{555,22},'Binary'}]},{type,{555,33},term,[]}]},[{type,{556,7},constraint,[{atom,{556,7},is_subtype},[{var,{556,7},'Binary'},{user_type,{556,17},ext_binary,[]}]]}]]}]}}]}},{{function,binary_to_term,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,561}],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,50>>],#{<<101,110>> => [{p,[],[<<65,115,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]},<<44,32,98,117,116,32,116,97,107,101,115,32,116,104,101,115,101,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,97,102,101>>]}]},{dd,[],[{p,[],[<<85,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,119,104,101,110,32,114,101,99,101,105,118,105,110,103,32,98,105,110,97,114,105,101,115,32,102,114,111,109,32,97,110,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,46>>]},{p,[],[<<87,104,101,110,32,101,110,97,98,108,101,100,44,32,105,116,32,112,114,101,118,101,110,116,115,32,100,101,99,111,100,105,110,103,32,100,97,116,97,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,97,116,116,97,99,107,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,46,32,73,110,32,116,104,101,32,101,118,101,110,116,32,111,102,32,114,101,99,101,105,118,105,110,103,32,117,110,115,97,102,101,32,100,97,116,97,44,32,100,101,99,111,100,105,110,103,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,114,114,111,114,46>>]},{p,[],[<<84,104,105,115,32,112,114,101,118,101,110,116,115,32,99,114,101,97,116,105,111,110,32,111,102,32,110,101,119,32,97,116,111,109,115,32,100,105,114,101,99,116,108,121,44,32,99,114,101,97,116,105,111,110,32,111,102,32,110,101,119,32,97,116,111,109,115,32,105,110,100,105,114,101,99,116,108,121,32,40,97,115,32,116,104,101,121,32,97,114,101,32,101,109,98,101,100,100,101,100,32,105,110,32,99,101,114,116,97,105,110,32,115,116,114,117,99,116,117,114,101,115,44,32,115,117,99,104,32,97,115,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,44,32,114,101,102,115,44,32,97,110,100,32,102,117,110,115,41,44,32,97,110,100,32,99,114,101,97,116,105,111,110,32,111,102,32,110,101,119,32,101,120,116,101,114,110,97,108,32,102,117,110,99,116,105,111,110,32,114,101,102,101,114,101,110,99,101,115,46,32,78,111,110,101,32,111,102,32,116,104,111,115,101,32,114,101,115,111,117,114,99,101,115,32,97,114,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,44,32,115,111,32,117,110,99,104,101,99,107,101,100,32,99,114,101,97,116,105,111,110,32,111,102,32,116,104,101,109,32,99,97,110,32,101,120,104,97,117,115,116,32,97,118,97,105,108,97,98,108,101,32,109,101,109,111,114,121,46>>]},{pre,[],[{code,[],[<<62,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,60,60,49,51,49,44,49,48,48,44,48,44,53,44,34,104,101,108,108,111,34,62,62,44,32,91,115,97,102,101,93,41,46,10,42,42,32,101,120,99,101,112,116,105,111,110,32,101,114,114,111,114,58,32,98,97,100,32,97,114,103,117,109,101,110,116,10,62,32,104,101,108,108,111,46,10,104,101,108,108,111,10,62,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,60,60,49,51,49,44,49,48,48,44,48,44,53,44,34,104,101,108,108,111,34,62,62,44,32,91,115,97,102,101,93,41,46,10,104,101,108,108,111>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,32>>,{code,[],[<<115,97,102,101>>]},<<32,111,112,116,105,111,110,32,101,110,115,117,114,101,115,32,116,104,101,32,100,97,116,97,32,105,115,32,115,97,102,101,108,121,32,112,114,111,99,101,115,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,98,117,116,32,105,116,32,100,111,101,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,32,116,104,101,32,100,97,116,97,32,105,115,32,115,97,102,101,32,116,111,32,121,111,117,114,32,97,112,112,108,105,99,97,116,105,111,110,46,32,89,111,117,32,109,117,115,116,32,97,108,119,97,121,115,32,118,97,108,105,100,97,116,101,32,100,97,116,97,32,102,114,111,109,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,115,46,32,73,102,32,116,104,101,32,98,105,110,97,114,121,32,105,115,32,115,116,111,114,101,100,32,111,114,32,116,114,97,110,115,105,116,115,32,116,104,114,111,117,103,104,32,117,110,116,114,117,115,116,101,100,32,115,111,117,114,99,101,115,44,32,121,111,117,32,115,104,111,117,108,100,32,97,108,115,111,32,99,111,110,115,105,100,101,114,32,99,114,121,112,116,111,103,114,97,112,104,105,99,97,108,108,121,32,115,105,103,110,105,110,103,32,105,116,46>>]}]}]},{dt,[],[{code,[],[<<117,115,101,100>>]}]},{dd,[],[{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<123,84,101,114,109,44,32,85,115,101,100,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<85,115,101,100>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,97,99,116,117,97,108,108,121,32,114,101,97,100,32,102,114,111,109,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<46>>]},{pre,[],[{code,[],[<<62,32,73,110,112,117,116,32,61,32,60,60,49,51,49,44,49,48,48,44,48,44,53,44,34,104,101,108,108,111,34,44,34,119,111,114,108,100,34,62,62,46,10,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,44,49,49,57,44,49,49,49,44,49,49,52,44,49,48,56,44,49,48,48,62,62,10,62,32,123,84,101,114,109,44,32,85,115,101,100,125,32,61,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,73,110,112,117,116,44,32,91,117,115,101,100,93,41,46,10,123,104,101,108,108,111,44,32,57,125,10,62,32,115,112,108,105,116,95,98,105,110,97,114,121,40,73,110,112,117,116,44,32,85,115,101,100,41,46,10,123,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,62,62,44,32,60,60,34,119,111,114,108,100,34,62,62,125>>]}]}]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<115,97,102,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,110,100,32,117,110,115,97,102,101,32,100,97,116,97,32,105,115,32,100,101,99,111,100,101,100,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,54,57>>,signature => [{attribute,{561,2},spec,{{binary_to_term,2},[{type,{561,21},bounded_fun,[{type,{561,21},'fun',[{type,{561,21},product,[{var,{561,22},'Binary'},{var,{561,30},'Opts'}]},{type,{561,39},union,[{type,{561,39},term,[]},{type,{561,48},tuple,[{type,{561,49},term,[]},{var,{561,57},'Used'}]}]}]},[{type,{562,7},constraint,[{atom,{562,7},is_subtype},[{var,{562,7},'Binary'},{user_type,{562,17},ext_binary,[]}]]},{type,{563,7},constraint,[{atom,{563,7},is_subtype},[{var,{563,7},'Opt'},{type,{563,14},union,[{atom,{563,14},safe},{atom,{563,21},used}]}]]},{type,{564,7},constraint,[{atom,{564,7},is_subtype},[{var,{564,7},'Opts'},{type,{564,15},list,[{var,{564,16},'Opt'}]}]]},{type,{565,7},constraint,[{atom,{565,7},is_subtype},[{var,{565,7},'Used'},{type,{565,15},pos_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,51,66,48,52>>}},{{function,bit_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,571}],[<<98,105,116,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,116,104,97,116,32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,105,116,115,32,111,102,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,98,105,116,95,115,105,122,101,40,60,60,52,51,51,58,49,54,44,51,58,51,62,62,41,46,10,49,57,10,62,32,98,105,116,95,115,105,122,101,40,60,60,49,44,50,44,51,62,62,41,46,10,50,52>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,51,50>>,signature => [{attribute,{571,2},spec,{{bit_size,1},[{type,{571,15},bounded_fun,[{type,{571,15},'fun',[{type,{571,15},product,[{var,{571,16},'Bitstring'}]},{type,{571,30},non_neg_integer,[]}]},[{type,{572,7},constraint,[{atom,{572,7},is_subtype},[{var,{572,7},'Bitstring'},{type,{572,20},bitstring,[]}]]}]]}]}}]}},{{function,bitstring_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,577}],[<<98,105,116,115,116,114,105,110,103,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,121,116,101,115,32,111,102,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,105,116,115,32,105,110,32,116,104,101,32,98,105,110,97,114,121,32,105,115,32,110,111,116,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,44,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,108,105,115,116,32,105,115,32,97,32,98,105,116,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,49,45,55,32,98,105,116,115,46,32,69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,98,105,116,115,116,114,105,110,103,95,116,111,95,108,105,115,116,40,60,60,52,51,51,58,49,54,62,62,41,46,10,91,49,44,49,55,55,93>>]}]},{pre,[],[{code,[],[<<62,32,98,105,116,115,116,114,105,110,103,95,116,111,95,108,105,115,116,40,60,60,52,51,51,58,49,54,44,51,58,51,62,62,41,46,10,91,49,44,49,55,55,44,60,60,51,58,51,62,62,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,52,55>>,signature => [{attribute,{577,2},spec,{{bitstring_to_list,1},[{type,{577,24},bounded_fun,[{type,{577,24},'fun',[{type,{577,24},product,[{var,{577,25},'Bitstring'}]},{type,{577,39},list,[{type,{577,40},union,[{type,{577,40},byte,[]},{type,{577,49},bitstring,[]}]}]}]},[{type,{578,7},constraint,[{atom,{578,7},is_subtype},[{var,{578,7},'Bitstring'},{type,{578,20},bitstring,[]}]]}]]}]}}]}},{{function,bump_reductions,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,583}],[<<98,117,109,112,95,114,101,100,117,99,116,105,111,110,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,105,115,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,32,102,117,110,99,116,105,111,110,32,105,110,99,114,101,109,101,110,116,115,32,116,104,101,32,114,101,100,117,99,116,105,111,110,32,99,111,117,110,116,101,114,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,73,110,32,116,104,101,32,66,101,97,109,32,101,109,117,108,97,116,111,114,44,32,116,104,101,32,114,101,100,117,99,116,105,111,110,32,99,111,117,110,116,101,114,32,105,115,32,110,111,114,109,97,108,108,121,32,105,110,99,114,101,109,101,110,116,101,100,32,98,121,32,111,110,101,32,102,111,114,32,101,97,99,104,32,102,117,110,99,116,105,111,110,32,97,110,100,32,66,73,70,32,99,97,108,108,46,32,65,32,99,111,110,116,101,120,116,32,115,119,105,116,99,104,32,105,115,32,102,111,114,99,101,100,32,119,104,101,110,32,116,104,101,32,99,111,117,110,116,101,114,32,114,101,97,99,104,101,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,114,101,100,117,99,116,105,111,110,115,32,102,111,114,32,97,32,112,114,111,99,101,115,115,32,40,52,48,48,48,32,114,101,100,117,99,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103,47,79,84,80,32,49,57,46,50,32,97,110,100,32,108,97,116,101,114,41,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,99,97,110,32,98,101,32,114,101,109,111,118,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,66,101,97,109,32,109,97,99,104,105,110,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,119,97,114,110,105,110,103,46,32,73,116,32,105,115,32,117,110,108,105,107,101,108,121,32,116,111,32,98,101,32,105,109,112,108,101,109,101,110,116,101,100,32,105,110,32,111,116,104,101,114,32,69,114,108,97,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,54,52>>,signature => [{attribute,{583,2},spec,{{erlang,bump_reductions,1},[{type,{583,29},bounded_fun,[{type,{583,29},'fun',[{type,{583,29},product,[{var,{583,30},'Reductions'}]},{atom,{583,45},true}]},[{type,{584,7},constraint,[{atom,{584,7},is_subtype},[{var,{584,7},'Reductions'},{type,{584,21},pos_integer,[]}]]}]]}]}}]}},{{function,byte_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,590}],[<<98,121,116,101,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,116,104,97,116,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,110,101,101,100,101,100,32,116,111,32,99,111,110,116,97,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<46,32,84,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,105,116,115,32,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103>>]},<<32,105,115,32,110,111,116,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,44,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,115,32,114,111,117,110,100,101,100,32>>,{em,[],[<<117,112>>]},<<46,32,69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,98,121,116,101,95,115,105,122,101,40,60,60,52,51,51,58,49,54,44,51,58,51,62,62,41,46,10,51,10,62,32,98,121,116,101,95,115,105,122,101,40,60,60,49,44,50,44,51,62,62,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,56,50>>,signature => [{attribute,{590,2},spec,{{byte_size,1},[{type,{590,16},bounded_fun,[{type,{590,16},'fun',[{type,{590,16},product,[{var,{590,17},'Bitstring'}]},{type,{590,31},non_neg_integer,[]}]},[{type,{591,7},constraint,[{atom,{591,7},is_subtype},[{var,{591,7},'Bitstring'},{type,{591,20},bitstring,[]}]]}]]}]}}]}},{{function,cancel_timer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,602}],[<<99,97,110,99,101,108,95,116,105,109,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<67,97,110,99,101,108,115,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,40,84,105,109,101,114,82,101,102,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,57,57>>,signature => [{attribute,{602,2},spec,{{erlang,cancel_timer,1},[{type,{602,26},bounded_fun,[{type,{602,26},'fun',[{type,{602,26},product,[{var,{602,27},'TimerRef'}]},{var,{602,40},'Result'}]},[{type,{603,7},constraint,[{atom,{603,7},is_subtype},[{var,{603,7},'TimerRef'},{type,{603,19},reference,[]}]]},{type,{604,7},constraint,[{atom,{604,7},is_subtype},[{var,{604,7},'Time'},{type,{604,15},non_neg_integer,[]}]]},{type,{605,7},constraint,[{atom,{605,7},is_subtype},[{var,{605,7},'Result'},{type,{605,17},union,[{var,{605,17},'Time'},{atom,{605,24},false}]}]]}]]}]}}]}},{{function,cancel_timer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,611}],[<<99,97,110,99,101,108,95,116,105,109,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<67,97,110,99,101,108,115,32,97,32,116,105,109,101,114,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114>>]}]},<<46,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,105,100,101,110,116,105,102,105,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,119,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32,116,104,101,32,66,73,70,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,116,105,109,101,114,46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,65,115,121,110,99,125>>]}]},{dd,[],[{p,[],[<<65,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,99,97,110,99,101,108,108,97,116,105,111,110,46,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,119,104,105,99,104,32,99,97,117,115,101,115,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,32,116,111,32,98,101,32,112,101,114,102,111,114,109,101,100,32,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,99,97,110,99,101,108,32,111,112,101,114,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,84,104,97,116,32,105,115,44,32>>,{code,[],[<<99,97,110,99,101,108,95,116,105,109,101,114,40,41>>]},<<32,115,101,110,100,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,99,97,110,99,101,108,108,97,116,105,111,110,32,116,111,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,116,104,101,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,105,110,102,111,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<82,101,113,117,101,115,116,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,111,102,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,119,104,105,99,104,32,109,101,97,110,115,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,103,105,118,101,110,46,32,87,104,101,110,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,32,105,115,32,103,105,118,101,110,46>>]},{ul,[],[{li,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<58,32,105,102,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,40,41>>]},<<46,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<111,107>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{li,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<58,32,105,102,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,99,97,110,99,101,108,95,116,105,109,101,114,44,32,84,105,109,101,114,82,101,102,44,32,82,101,115,117,108,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,40,41>>]},<<32,119,104,101,110,32,116,104,101,32,99,97,110,99,101,108,108,97,116,105,111,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,101,114,102,111,114,109,101,100,44,32,111,116,104,101,114,119,105,115,101,32,110,111,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,46>>]}]}]}]}]},{p,[],[<<77,111,114,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,109,97,121,32,98,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,105,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,32,108,101,102,116,32,117,110,116,105,108,32,116,104,101,32,99,97,110,99,101,108,101,100,32,116,105,109,101,114,32,119,111,117,108,100,32,104,97,118,101,32,101,120,112,105,114,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,97,32,116,105,109,101,114,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,99,111,117,108,100,32,110,111,116,32,98,101,32,102,111,117,110,100,46,32,84,104,105,115,32,99,97,110,32,98,101,32,101,105,116,104,101,114,32,98,101,99,97,117,115,101,32,116,104,101,32,116,105,109,101,114,32,104,97,100,32,101,120,112,105,114,101,100,44,32,97,108,114,101,97,100,121,32,104,97,100,32,98,101,101,110,32,99,97,110,99,101,108,101,100,44,32,111,114,32,98,101,99,97,117,115,101,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,110,101,118,101,114,32,99,111,114,114,101,115,112,111,110,100,101,100,32,116,111,32,97,32,116,105,109,101,114,46,32,69,118,101,110,32,105,102,32,116,104,101,32,116,105,109,101,114,32,104,97,100,32,101,120,112,105,114,101,100,44,32,105,116,32,100,111,101,115,32,110,111,116,32,116,101,108,108,32,121,111,117,32,105,102,32,116,104,101,32,116,105,109,101,45,111,117,116,32,109,101,115,115,97,103,101,32,104,97,115,32,97,114,114,105,118,101,100,32,97,116,32,105,116,115,32,100,101,115,116,105,110,97,116,105,111,110,32,121,101,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,32,99,97,110,32,98,101,32,99,111,45,108,111,99,97,116,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32,115,99,104,101,100,117,108,101,114,32,116,104,97,110,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32,73,102,32,115,111,44,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,97,107,101,115,32,109,117,99,104,32,108,111,110,103,101,114,32,116,105,109,101,32,116,104,97,110,32,105,102,32,105,116,32,105,115,32,108,111,99,97,116,101,100,32,108,111,99,97,108,108,121,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,105,110,32,99,114,105,116,105,99,97,108,32,112,97,116,104,44,32,97,110,100,32,99,97,110,32,100,111,32,111,116,104,101,114,32,116,104,105,110,103,115,32,119,104,105,108,101,32,119,97,105,116,105,110,103,32,102,111,114,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,44,32,111,114,32,105,115,32,110,111,116,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,44,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,116,114,117,101,125>>]},<<46,32,73,102,32,117,115,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,102,97,108,115,101,125>>]},<<44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,98,108,111,99,107,115,32,117,110,116,105,108,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,101,114,102,111,114,109,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,47,52>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,47,52>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,97,100,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,48,57>>,signature => [{attribute,{611,2},spec,{{erlang,cancel_timer,2},[{type,{611,26},bounded_fun,[{type,{611,26},'fun',[{type,{611,26},product,[{var,{611,27},'TimerRef'},{var,{611,37},'Options'}]},{type,{611,49},union,[{var,{611,49},'Result'},{atom,{611,58},ok}]}]},[{type,{612,7},constraint,[{atom,{612,7},is_subtype},[{var,{612,7},'TimerRef'},{type,{612,19},reference,[]}]]},{type,{613,7},constraint,[{atom,{613,7},is_subtype},[{var,{613,7},'Async'},{type,{613,16},boolean,[]}]]},{type,{614,7},constraint,[{atom,{614,7},is_subtype},[{var,{614,7},'Info'},{type,{614,15},boolean,[]}]]},{type,{615,7},constraint,[{atom,{615,7},is_subtype},[{var,{615,7},'Option'},{type,{615,17},union,[{type,{615,17},tuple,[{atom,{615,18},async},{var,{615,25},'Async'}]},{type,{615,34},tuple,[{atom,{615,35},info},{var,{615,41},'Info'}]}]}]]},{type,{616,7},constraint,[{atom,{616,7},is_subtype},[{var,{616,7},'Options'},{type,{616,18},list,[{var,{616,19},'Option'}]}]]},{type,{617,7},constraint,[{atom,{617,7},is_subtype},[{var,{617,7},'Time'},{type,{617,15},non_neg_integer,[]}]]},{type,{618,7},constraint,[{atom,{618,7},is_subtype},[{var,{618,7},'Result'},{type,{618,17},union,[{var,{618,17},'Time'},{atom,{618,24},false}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,ceil,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,625}],[<<99,101,105,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,105,110,116,101,103,101,114,32,110,111,116,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,99,101,105,108,40,53,46,53,41,46,10,54>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,49>>,signature => [{attribute,{625,2},spec,{{ceil,1},[{type,{625,11},bounded_fun,[{type,{625,11},'fun',[{type,{625,11},product,[{var,{625,12},'Number'}]},{type,{625,23},integer,[]}]},[{type,{626,7},constraint,[{atom,{626,7},is_subtype},[{var,{626,7},'Number'},{type,{626,17},number,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,check_old_code,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,631}],[<<99,104,101,99,107,95,111,108,100,95,99,111,100,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,104,97,115,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,99,111,100,101,95,108,111,97,100,105,110,103,35,99,111,100,101,45,114,101,112,108,97,99,101,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<111,108,100,32,99,111,100,101>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,48,52>>,signature => [{attribute,{631,2},spec,{{check_old_code,1},[{type,{631,21},bounded_fun,[{type,{631,21},'fun',[{type,{631,21},product,[{var,{631,22},'Module'}]},{type,{631,33},boolean,[]}]},[{type,{632,7},constraint,[{atom,{632,7},is_subtype},[{var,{632,7},'Module'},{type,{632,17},module,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66,48,52>>}},{{function,check_process_code,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,637}],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,40,80,105,100,44,32,77,111,100,117,108,101,44,32,91,93,41>>]},<<32>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,49,53>>,signature => [{attribute,{637,2},spec,{{check_process_code,2},[{type,{637,25},bounded_fun,[{type,{637,25},'fun',[{type,{637,25},product,[{var,{637,26},'Pid'},{var,{637,31},'Module'}]},{var,{637,42},'CheckResult'}]},[{type,{638,7},constraint,[{atom,{638,7},is_subtype},[{var,{638,7},'Pid'},{type,{638,14},pid,[]}]]},{type,{639,7},constraint,[{atom,{639,7},is_subtype},[{var,{639,7},'Module'},{type,{639,17},module,[]}]]},{type,{640,7},constraint,[{atom,{640,7},is_subtype},[{var,{640,7},'CheckResult'},{type,{640,22},boolean,[]}]]}]]}]}}]}},{{function,check_process_code,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,649}],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,104,101,99,107,115,32,105,102,32,116,104,101,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,101,99,117,116,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,98,111,111,108,101,97,110,40,41,125>>]}]},{dd,[],[{p,[],[<<68,101,116,101,114,109,105,110,101,115,32,105,102,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,97,108,108,111,119,101,100,32,119,104,101,110,32,112,101,114,102,111,114,109,105,110,103,32,116,104,101,32,111,112,101,114,97,116,105,111,110,46,32,73,102,32>>,{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,102,97,108,115,101,125>>]},<<32,105,115,32,112,97,115,115,101,100,44,32,97,110,100,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,110,101,101,100,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,97,98,111,114,116,101,100,32,40,115,101,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32>>,{code,[],[<<67,104,101,99,107,82,101,115,117,108,116>>]},<<32,98,101,108,111,119,41,46,32,84,104,101,32,100,101,102,97,117,108,116,32,105,115,32,116,111,32,97,108,108,111,119,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,44,32,116,104,97,116,32,105,115,44,32>>,{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,116,114,117,101,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,82,101,113,117,101,115,116,73,100,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,51>>]},<<32,114,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,115,101,110,116,46,32,87,104,101,110,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,44,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,97,108,108,101,100,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,112,97,115,115,101,100,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,44,32,82,101,113,117,101,115,116,73,100,44,32,67,104,101,99,107,82,101,115,117,108,116,125>>]},<<46>>]}]}]},{p,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<115,101,108,102,40,41>>]},<<44,32,97,110,100,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,116,32,111,110,99,101,46,32,79,116,104,101,114,119,105,115,101,32,97,32,114,101,113,117,101,115,116,32,102,111,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,97,110,100,32,105,115,32,104,97,110,100,108,101,100,32,119,104,101,110,32,97,112,112,114,111,112,114,105,97,116,101,46,32,73,102,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,98,108,111,99,107,115,32,117,110,116,105,108,32>>,{code,[],[<<67,104,101,99,107,82,101,115,117,108,116>>]},<<32,105,115,32,97,118,97,105,108,97,98,108,101,32,97,110,100,32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<67,104,101,99,107,82,101,115,117,108,116>>]},<<32,105,110,102,111,114,109,115,32,97,98,111,117,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,114,101,113,117,101,115,116,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,101,99,117,116,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,99,97,108,108,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,101,99,117,116,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,99,111,110,116,97,105,110,115,32,102,117,110,115,32,116,104,97,116,32,114,101,102,101,114,101,110,99,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,101,99,117,116,101,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,98,111,114,116,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,101,114,97,116,105,111,110,32,119,97,115,32,97,98,111,114,116,101,100,44,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,110,101,101,100,101,100,32,116,111,32,98,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,114,101,115,117,108,116,44,32,97,110,100,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,119,97,115,32,114,101,113,117,101,115,116,101,100,32,98,121,32,112,97,115,115,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,108,108,111,119,95,103,99,44,32,102,97,108,115,101,125>>]},<<46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<85,112,32,117,110,116,105,108,32,69,82,84,83,32,118,101,114,115,105,111,110,32,56,46,42,44,32,116,104,101,32,99,104,101,99,107,32,112,114,111,99,101,115,115,32,99,111,100,101,32,111,112,101,114,97,116,105,111,110,32,99,104,101,99,107,115,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,116,104,101,32,111,108,100,32,99,111,100,101,46,32,84,104,97,116,32,105,115,44,32,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,40,101,46,103,46,32,114,101,116,117,114,110,32,97,100,100,114,101,115,115,101,115,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,41,44,32,105,110,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,40>>,{code,[],[<<102,117,110>>]},<<115,32,105,110,32,112,114,111,99,101,115,115,32,99,111,110,116,101,120,116,41,44,32,97,110,100,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,108,105,116,101,114,97,108,115,32,105,110,32,116,104,101,32,99,111,100,101,46>>]},{p,[],[<<65,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,57,46,48,44,32,116,104,101,32,99,104,101,99,107,32,112,114,111,99,101,115,115,32,99,111,100,101,32,111,112,101,114,97,116,105,111,110,32,111,110,108,121,32,99,104,101,99,107,115,32,102,111,114,32,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,116,104,101,32,99,111,100,101,46,32,73,110,100,105,114,101,99,116,32,114,101,102,101,114,101,110,99,101,115,32,118,105,97,32>>,{code,[],[<<102,117,110>>]},<<115,32,119,105,108,108,32,98,101,32,105,103,110,111,114,101,100,46,32,73,102,32,115,117,99,104,32>>,{code,[],[<<102,117,110>>]},<<115,32,101,120,105,115,116,32,97,110,100,32,97,114,101,32,117,115,101,100,32,97,102,116,101,114,32,97,32,112,117,114,103,101,32,111,102,32,116,104,101,32,111,108,100,32,99,111,100,101,44,32,97,110,32,101,120,99,101,112,116,105,111,110,32,119,105,108,108,32,98,101,32,114,97,105,115,101,100,32,117,112,111,110,32,117,115,97,103,101,32,40,115,97,109,101,32,97,115,32,116,104,101,32,99,97,115,101,32,119,104,101,110,32,116,104,101,32>>,{code,[],[<<102,117,110>>]},<<32,105,115,32,114,101,99,101,105,118,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,97,102,116,101,114,32,116,104,101,32,112,117,114,103,101,41,46,32,76,105,116,101,114,97,108,115,32,119,105,108,108,32,98,101,32,116,97,107,101,110,32,99,97,114,101,32,111,102,32,40,99,111,112,105,101,100,41,32,97,116,32,97,32,108,97,116,101,114,32,115,116,97,103,101,46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,99,97,110,32,97,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,56,46,49,32,98,101,32,101,110,97,98,108,101,100,32,119,104,101,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,105,110,115,116,97,108,108,97,116,105,111,110,95,103,117,105,100,101,58,73,78,83,84,65,76,76,35,65,100,118,97,110,99,101,100,45,99,111,110,102,105,103,117,114,97,116,105,111,110,45,97,110,100,45,98,117,105,108,100,45,111,102,45,69,114,108,97,110,103,79,84,80,95,67,111,110,102,105,103,117,114,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<98,117,105,108,100,105,110,103,32,79,84,80>>]},<<44,32,97,110,100,32,119,105,108,108,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,98,101,32,101,110,97,98,108,101,100,32,105,102,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,32,115,117,112,112,111,114,116,32,105,115,32,101,110,97,98,108,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,50,54>>,signature => [{attribute,{649,2},spec,{{check_process_code,3},[{type,{649,25},bounded_fun,[{type,{649,25},'fun',[{type,{649,25},product,[{var,{649,26},'Pid'},{var,{649,31},'Module'},{var,{649,39},'OptionList'}]},{type,{649,54},union,[{var,{649,54},'CheckResult'},{atom,{649,68},async}]}]},[{type,{650,7},constraint,[{atom,{650,7},is_subtype},[{var,{650,7},'Pid'},{type,{650,14},pid,[]}]]},{type,{651,7},constraint,[{atom,{651,7},is_subtype},[{var,{651,7},'Module'},{type,{651,17},module,[]}]]},{type,{652,7},constraint,[{atom,{652,7},is_subtype},[{var,{652,7},'RequestId'},{type,{652,20},term,[]}]]},{type,{653,7},constraint,[{atom,{653,7},is_subtype},[{var,{653,7},'Option'},{type,{653,17},union,[{type,{653,17},tuple,[{atom,{653,18},async},{var,{653,25},'RequestId'}]},{type,{653,38},tuple,[{atom,{653,39},allow_gc},{type,{653,49},boolean,[]}]}]}]]},{type,{654,7},constraint,[{atom,{654,7},is_subtype},[{var,{654,7},'OptionList'},{type,{654,21},list,[{var,{654,22},'Option'}]}]]},{type,{655,7},constraint,[{atom,{655,7},is_subtype},[{var,{655,7},'CheckResult'},{type,{655,22},union,[{type,{655,22},boolean,[]},{atom,{655,34},aborted}]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,convert_time_unit,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1619}],[<<99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,111,102,32,116,105,109,101,32,117,110,105,116,32>>,{code,[],[<<70,114,111,109,85,110,105,116>>]},<<32,116,111,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<67,111,110,118,101,114,116,101,100,84,105,109,101>>]},<<32,118,97,108,117,101,32,111,102,32,116,105,109,101,32,117,110,105,116,32>>,{code,[],[<<84,111,85,110,105,116>>]},<<46,32,84,104,101,32,114,101,115,117,108,116,32,105,115,32,114,111,117,110,100,101,100,32,117,115,105,110,103,32,116,104,101,32,102,108,111,111,114,32,102,117,110,99,116,105,111,110,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<89,111,117,32,99,97,110,32,108,111,115,101,32,97,99,99,117,114,97,99,121,32,97,110,100,32,112,114,101,99,105,115,105,111,110,32,119,104,101,110,32,99,111,110,118,101,114,116,105,110,103,32,98,101,116,119,101,101,110,32,116,105,109,101,32,117,110,105,116,115,46,32,84,111,32,109,105,110,105,109,105,122,101,32,115,117,99,104,32,108,111,115,115,44,32,99,111,108,108,101,99,116,32,97,108,108,32,100,97,116,97,32,97,116,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,97,110,100,32,100,111,32,116,104,101,32,99,111,110,118,101,114,115,105,111,110,32,111,110,32,116,104,101,32,101,110,100,32,114,101,115,117,108,116,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,50,57>>,signature => [{attribute,{1619,2},spec,{{erlang,convert_time_unit,3},[{type,{1619,31},bounded_fun,[{type,{1619,31},'fun',[{type,{1619,31},product,[{var,{1619,32},'Time'},{var,{1619,38},'FromUnit'},{var,{1619,48},'ToUnit'}]},{var,{1619,59},'ConvertedTime'}]},[{type,{1620,7},constraint,[{atom,{1620,7},is_subtype},[{var,{1620,7},'Time'},{type,{1620,15},integer,[]}]]},{type,{1621,7},constraint,[{atom,{1621,7},is_subtype},[{var,{1621,7},'ConvertedTime'},{type,{1621,24},integer,[]}]]},{type,{1622,7},constraint,[{atom,{1622,7},is_subtype},[{var,{1622,7},'FromUnit'},{user_type,{1622,19},time_unit,[]}]]},{type,{1623,7},constraint,[{atom,{1623,7},is_subtype},[{var,{1623,7},'ToUnit'},{user_type,{1623,17},time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,crc32,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,667}],[<<99,114,99,51,50,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,117,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,99,114,99,51,50,32,40,73,69,69,69,32,56,48,50,46,51,32,115,116,121,108,101,41,32,99,104,101,99,107,115,117,109,32,102,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,52,55>>,signature => [{attribute,{667,2},spec,{{erlang,crc32,1},[{type,{667,19},bounded_fun,[{type,{667,19},'fun',[{type,{667,19},product,[{var,{667,20},'Data'}]},{type,{667,29},non_neg_integer,[]}]},[{type,{668,7},constraint,[{atom,{668,7},is_subtype},[{var,{668,7},'Data'},{type,{668,15},iodata,[]}]]}]]}]}}]}},{{function,crc32,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,673}],[<<99,114,99,51,50,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,110,116,105,110,117,101,115,32,99,111,109,112,117,116,105,110,103,32,116,104,101,32,99,114,99,51,50,32,99,104,101,99,107,115,117,109,32,98,121,32,99,111,109,98,105,110,105,110,103,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,104,101,99,107,115,117,109,44,32>>,{code,[],[<<79,108,100,67,114,99>>]},<<44,32,119,105,116,104,32,116,104,101,32,99,104,101,99,107,115,117,109,32,111,102,32>>,{code,[],[<<68,97,116,97>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,88,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<89>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,91,68,97,116,97,49,44,68,97,116,97,50,93,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,53,54>>,signature => [{attribute,{673,2},spec,{{erlang,crc32,2},[{type,{673,19},bounded_fun,[{type,{673,19},'fun',[{type,{673,19},product,[{var,{673,20},'OldCrc'},{var,{673,28},'Data'}]},{type,{673,37},non_neg_integer,[]}]},[{type,{674,7},constraint,[{atom,{674,7},is_subtype},[{var,{674,7},'OldCrc'},{type,{674,17},non_neg_integer,[]}]]},{type,{675,7},constraint,[{atom,{675,7},is_subtype},[{var,{675,7},'Data'},{type,{675,15},iodata,[]}]]}]]}]}}]}},{{function,crc32_combine,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,680}],[<<99,114,99,51,50,95,99,111,109,98,105,110,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32,116,119,111,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,117,116,101,100,32,99,114,99,51,50,32,99,104,101,99,107,115,117,109,115,46,32,84,104,105,115,32,99,111,109,112,117,116,97,116,105,111,110,32,114,101,113,117,105,114,101,115,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,100,97,116,97,32,111,98,106,101,99,116,32,102,111,114,32,116,104,101,32,115,101,99,111,110,100,32,99,104,101,99,107,115,117,109,32,116,111,32,98,101,32,107,110,111,119,110,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,100,101,58>>]},{pre,[],[{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,49,41,44,10,90,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,89,44,68,97,116,97,50,41,46>>]}]},{p,[],[<<97,115,115,105,103,110,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<90>>]},<<32,97,115,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,49,41,44,10,89,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,40,68,97,116,97,50,41,44,10,90,32,61,32,101,114,108,97,110,103,58,99,114,99,51,50,95,99,111,109,98,105,110,101,40,88,44,89,44,105,111,108,105,115,116,95,115,105,122,101,40,68,97,116,97,50,41,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,55,51>>,signature => [{attribute,{680,2},spec,{{erlang,crc32_combine,3},[{type,{680,27},bounded_fun,[{type,{680,27},'fun',[{type,{680,27},product,[{var,{680,28},'FirstCrc'},{var,{680,38},'SecondCrc'},{var,{680,49},'SecondSize'}]},{type,{680,64},non_neg_integer,[]}]},[{type,{681,7},constraint,[{atom,{681,7},is_subtype},[{var,{681,7},'FirstCrc'},{type,{681,19},non_neg_integer,[]}]]},{type,{682,7},constraint,[{atom,{682,7},is_subtype},[{var,{682,7},'SecondCrc'},{type,{682,20},non_neg_integer,[]}]]},{type,{683,7},constraint,[{atom,{683,7},is_subtype},[{var,{683,7},'SecondSize'},{type,{683,21},non_neg_integer,[]}]]}]]}]}}]}},{{function,date,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,688}],[<<100,97,116,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,100,97,116,101,32,97,115,32>>,{code,[],[<<123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125>>]},<<46>>]},{p,[],[<<84,104,101,32,116,105,109,101,32,122,111,110,101,32,97,110,100,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,99,111,114,114,101,99,116,105,111,110,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,100,97,116,101,40,41,46,10,123,49,57,57,53,44,50,44,49,57,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,52,57,50>>,signature => [{attribute,{688,2},spec,{{date,0},[{type,{688,11},bounded_fun,[{type,{688,11},'fun',[{type,{688,11},product,[]},{var,{688,17},'Date'}]},[{type,{689,7},constraint,[{atom,{689,7},is_subtype},[{var,{689,7},'Date'},{remote_type,{689,15},[{atom,{689,15},calendar},{atom,{689,24},date},[]]}]]}]]}]}}]}},{{function,decode_packet,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,694}],[<<100,101,99,111,100,101,95,112,97,99,107,101,116,47,51>>],#{<<101,110>> => [{p,[],[<<68,101,99,111,100,101,115,32,116,104,101,32,98,105,110,97,114,121,32>>,{code,[],[<<66,105,110>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,112,97,99,107,101,116,32,112,114,111,116,111,99,111,108,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<84,121,112,101>>]},<<46,32,83,105,109,105,108,97,114,32,116,111,32,116,104,101,32,112,97,99,107,101,116,32,104,97,110,100,108,105,110,103,32,100,111,110,101,32,98,121,32,115,111,99,107,101,116,115,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<123,112,97,99,107,101,116,44,84,121,112,101,125,46>>]}]},{p,[],[<<73,102,32,97,110,32,101,110,116,105,114,101,32,112,97,99,107,101,116,32,105,115,32,99,111,110,116,97,105,110,101,100,32,105,110,32>>,{code,[],[<<66,105,110>>]},<<44,32,105,116,32,105,115,32,114,101,116,117,114,110,101,100,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,116,104,101,32,114,101,109,97,105,110,100,101,114,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,97,115,32>>,{code,[],[<<123,111,107,44,80,97,99,107,101,116,44,82,101,115,116,125>>]},<<46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,105,110>>]},<<32,100,111,101,115,32,110,111,116,32,99,111,110,116,97,105,110,32,116,104,101,32,101,110,116,105,114,101,32,112,97,99,107,101,116,44,32>>,{code,[],[<<123,109,111,114,101,44,76,101,110,103,116,104,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32>>,{code,[],[<<76,101,110,103,116,104>>]},<<32,105,115,32,101,105,116,104,101,114,32,116,104,101,32,101,120,112,101,99,116,101,100,32>>,{em,[],[<<116,111,116,97,108,32,115,105,122,101>>]},<<32,111,102,32,116,104,101,32,112,97,99,107,101,116,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,101,120,112,101,99,116,101,100,32,112,97,99,107,101,116,32,115,105,122,101,32,105,115,32,117,110,107,110,111,119,110,46,32>>,{code,[],[<<100,101,99,111,100,101,95,112,97,99,107,101,116>>]},<<32,99,97,110,32,116,104,101,110,32,98,101,32,99,97,108,108,101,100,32,97,103,97,105,110,32,119,105,116,104,32,109,111,114,101,32,100,97,116,97,32,97,100,100,101,100,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,97,99,107,101,116,32,100,111,101,115,32,110,111,116,32,99,111,110,102,111,114,109,32,116,111,32,116,104,101,32,112,114,111,116,111,99,111,108,32,102,111,114,109,97,116,44,32>>,{code,[],[<<123,101,114,114,111,114,44,82,101,97,115,111,110,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<84,121,112,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<114,97,119,32,124,32,48>>]}]},{dd,[],[{p,[],[<<78,111,32,112,97,99,107,101,116,32,104,97,110,100,108,105,110,103,32,105,115,32,100,111,110,101,46,32,84,104,101,32,101,110,116,105,114,101,32,98,105,110,97,114,121,32,105,115,32,114,101,116,117,114,110,101,100,32,117,110,108,101,115,115,32,105,116,32,105,115,32,101,109,112,116,121,46>>]}]},{dt,[],[{code,[],[<<49,32,124,32,50,32,124,32,52>>]}]},{dd,[],[{p,[],[<<80,97,99,107,101,116,115,32,99,111,110,115,105,115,116,32,111,102,32,97,32,104,101,97,100,101,114,32,115,112,101,99,105,102,121,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,110,32,116,104,101,32,112,97,99,107,101,116,44,32,102,111,108,108,111,119,101,100,32,98,121,32,116,104,97,116,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,46,32,84,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,104,101,97,100,101,114,32,99,97,110,32,98,101,32,111,110,101,44,32,116,119,111,44,32,111,114,32,102,111,117,114,32,98,121,116,101,115,59,32,116,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,98,121,116,101,115,32,105,115,32,98,105,103,45,101,110,100,105,97,110,46,32,84,104,101,32,104,101,97,100,101,114,32,105,115,32,115,116,114,105,112,112,101,100,32,111,102,102,32,119,104,101,110,32,116,104,101,32,112,97,99,107,101,116,32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{code,[],[<<108,105,110,101>>]}]},{dd,[],[{p,[],[<<65,32,112,97,99,107,101,116,32,105,115,32,97,32,108,105,110,101,45,116,101,114,109,105,110,97,116,101,100,32,98,121,32,97,32,100,101,108,105,109,105,116,101,114,32,98,121,116,101,44,32,100,101,102,97,117,108,116,32,105,115,32,116,104,101,32,108,97,116,105,110,45,49,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,100,101,108,105,109,105,116,101,114,32,98,121,116,101,32,105,115,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,112,97,99,107,101,116,32,117,110,108,101,115,115,32,116,104,101,32,108,105,110,101,32,119,97,115,32,116,114,117,110,99,97,116,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,111,112,116,105,111,110,32>>,{code,[],[<<108,105,110,101,95,108,101,110,103,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,115,110,49,32,124,32,99,100,114,32,124,32,115,117,110,114,109,32,124,32,102,99,103,105,32,124,32,116,112,107,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,104,101,97,100,101,114,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,115,116,114,105,112,112,101,100,32,111,102,102,46>>]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,116,104,101,32,112,97,99,107,101,116,32,116,121,112,101,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,115,110,49>>]},<<32,45,32,65,83,78,46,49,32,66,69,82>>]},{dd,[],[]},{dt,[],[{code,[],[<<115,117,110,114,109>>]},<<32,45,32,83,117,110,39,115,32,82,80,67,32,101,110,99,111,100,105,110,103>>]},{dd,[],[]},{dt,[],[{code,[],[<<99,100,114>>]},<<32,45,32,67,79,82,66,65,32,40,71,73,79,80,32,49,46,49,41>>]},{dd,[],[]},{dt,[],[{code,[],[<<102,99,103,105>>]},<<32,45,32,70,97,115,116,32,67,71,73>>]},{dd,[],[]},{dt,[],[{code,[],[<<116,112,107,116>>]},<<32,45,32,84,80,75,84,32,102,111,114,109,97,116,32,91,82,70,67,49,48,48,54,93>>]},{dd,[],[]}]}]},{dt,[],[{code,[],[<<104,116,116,112,32,124,32,104,116,116,112,104,32,124,32,104,116,116,112,95,98,105,110,32,124,32,104,116,116,112,104,95,98,105,110>>]}]},{dd,[],[{p,[],[<<84,104,101,32,72,121,112,101,114,116,101,120,116,32,84,114,97,110,115,102,101,114,32,80,114,111,116,111,99,111,108,46,32,84,104,101,32,112,97,99,107,101,116,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,119,105,116,104,32,116,104,101,32,102,111,114,109,97,116,32,97,99,99,111,114,100,105,110,103,32,116,111,32>>,{code,[],[<<72,116,116,112,80,97,99,107,101,116>>]},<<32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46,32,65,32,112,97,99,107,101,116,32,105,115,32,101,105,116,104,101,114,32,97,32,114,101,113,117,101,115,116,44,32,97,32,114,101,115,112,111,110,115,101,44,32,97,32,104,101,97,100,101,114,44,32,111,114,32,97,110,32,101,110,100,32,111,102,32,104,101,97,100,101,114,32,109,97,114,107,46,32,73,110,118,97,108,105,100,32,108,105,110,101,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32>>,{code,[],[<<72,116,116,112,69,114,114,111,114>>]},<<46>>]},{p,[],[<<82,101,99,111,103,110,105,122,101,100,32,114,101,113,117,101,115,116,32,109,101,116,104,111,100,115,32,97,110,100,32,104,101,97,100,101,114,32,102,105,101,108,100,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,97,116,111,109,115,46,32,79,116,104,101,114,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,115,116,114,105,110,103,115,46,32,83,116,114,105,110,103,115,32,111,102,32,117,110,114,101,99,111,103,110,105,122,101,100,32,104,101,97,100,101,114,32,102,105,101,108,100,115,32,97,114,101,32,102,111,114,109,97,116,116,101,100,32,119,105,116,104,32,111,110,108,121,32,99,97,112,105,116,97,108,32,108,101,116,116,101,114,115,32,102,105,114,115,116,32,97,110,100,32,97,102,116,101,114,32,104,121,112,104,101,110,32,99,104,97,114,97,99,116,101,114,115,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<34,83,101,99,45,87,101,98,115,111,99,107,101,116,45,75,101,121,34>>]},<<46,32,72,101,97,100,101,114,32,102,105,101,108,100,32,110,97,109,101,115,32,97,114,101,32,97,108,115,111,32,114,101,116,117,114,110,101,100,32,105,110,32>>,{code,[],[<<85,110,109,111,100,105,102,105,101,100,70,105,101,108,100>>]},<<32,97,115,32,115,116,114,105,110,103,115,44,32,119,105,116,104,111,117,116,32,97,110,121,32,99,111,110,118,101,114,115,105,111,110,32,111,114,32,102,111,114,109,97,116,116,105,110,103,46>>]},{p,[],[<<84,104,101,32,112,114,111,116,111,99,111,108,32,116,121,112,101,32>>,{code,[],[<<104,116,116,112>>]},<<32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,102,111,114,32,116,104,101,32,102,105,114,115,116,32,108,105,110,101,32,119,104,101,110,32,97,110,32>>,{code,[],[<<72,116,116,112,82,101,113,117,101,115,116>>]},<<32,111,114,32,97,110,32>>,{code,[],[<<72,116,116,112,82,101,115,112,111,110,115,101>>]},<<32,105,115,32,101,120,112,101,99,116,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,115,32,97,114,101,32,116,111,32,117,115,101,32>>,{code,[],[<<104,116,116,112,104>>]},<<32,116,111,32,103,101,116,32>>,{code,[],[<<72,116,116,112,72,101,97,100,101,114>>]},<<115,32,117,110,116,105,108,32>>,{code,[],[<<104,116,116,112,95,101,111,104>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,119,104,105,99,104,32,109,97,114,107,115,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,104,101,97,100,101,114,115,32,97,110,100,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,97,110,121,32,102,111,108,108,111,119,105,110,103,32,109,101,115,115,97,103,101,32,98,111,100,121,46>>]},{p,[],[<<84,104,101,32,118,97,114,105,97,110,116,115,32>>,{code,[],[<<104,116,116,112,95,98,105,110>>]},<<32,97,110,100,32>>,{code,[],[<<104,116,116,112,104,95,98,105,110>>]},<<32,114,101,116,117,114,110,32,115,116,114,105,110,103,115,32,40>>,{code,[],[<<72,116,116,112,83,116,114,105,110,103>>]},<<41,32,97,115,32,98,105,110,97,114,105,101,115,32,105,110,115,116,101,97,100,32,111,102,32,108,105,115,116,115,46>>]}]}]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,97,99,107,101,116,95,115,105,122,101,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,120,105,109,117,109,32,97,108,108,111,119,101,100,32,115,105,122,101,32,111,102,32,116,104,101,32,112,97,99,107,101,116,32,98,111,100,121,46,32,73,102,32,116,104,101,32,112,97,99,107,101,116,32,104,101,97,100,101,114,32,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,112,97,99,107,101,116,32,105,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,101,32,109,97,120,105,109,117,109,32,97,108,108,111,119,101,100,32,108,101,110,103,116,104,44,32,116,104,101,32,112,97,99,107,101,116,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,105,110,118,97,108,105,100,46,32,68,101,102,97,117,108,116,115,32,116,111,32,48,44,32,119,104,105,99,104,32,109,101,97,110,115,32,110,111,32,115,105,122,101,32,108,105,109,105,116,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,101,95,108,101,110,103,116,104,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<70,111,114,32,112,97,99,107,101,116,32,116,121,112,101,32>>,{code,[],[<<108,105,110,101>>]},<<44,32,108,105,110,101,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,101,32,105,110,100,105,99,97,116,101,100,32,108,101,110,103,116,104,32,97,114,101,32,116,114,117,110,99,97,116,101,100,46>>]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<108,105,110,101,95,108,101,110,103,116,104>>]},<<32,97,108,115,111,32,97,112,112,108,105,101,115,32,116,111,32>>,{code,[],[<<104,116,116,112,42>>]},<<32,112,97,99,107,101,116,32,116,121,112,101,115,32,97,115,32,97,110,32,97,108,105,97,115,32,102,111,114,32,111,112,116,105,111,110,32>>,{code,[],[<<112,97,99,107,101,116,95,115,105,122,101>>]},<<32,105,102,32>>,{code,[],[<<112,97,99,107,101,116,95,115,105,122,101>>]},<<32,105,116,115,101,108,102,32,105,115,32,110,111,116,32,115,101,116,46,32,84,104,105,115,32,117,115,101,32,105,115,32,111,110,108,121,32,105,110,116,101,110,100,101,100,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,101,95,100,101,108,105,109,105,116,101,114,44,32,48,32,61,60,32,98,121,116,101,40,41,32,61,60,32,50,53,53,125>>]}]},{dd,[],[{p,[],[<<70,111,114,32,112,97,99,107,101,116,32,116,121,112,101,32>>,{code,[],[<<108,105,110,101>>]},<<44,32,115,101,116,115,32,116,104,101,32,100,101,108,105,109,105,116,105,110,103,32,98,121,116,101,46,32,68,101,102,97,117,108,116,32,105,115,32,116,104,101,32,108,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32>>,{code,[],[<<36,92,110>>]},<<46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,100,101,99,111,100,101,95,112,97,99,107,101,116,40,49,44,60,60,51,44,34,97,98,99,100,34,62,62,44,91,93,41,46,10,123,111,107,44,60,60,34,97,98,99,34,62,62,44,60,60,34,100,34,62,62,125,10,62,32,101,114,108,97,110,103,58,100,101,99,111,100,101,95,112,97,99,107,101,116,40,49,44,60,60,53,44,34,97,98,99,100,34,62,62,44,91,93,41,46,10,123,109,111,114,101,44,54,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,53,48,55>>,signature => [{attribute,{694,2},spec,{{erlang,decode_packet,3},[{type,{694,27},bounded_fun,[{type,{694,27},'fun',[{type,{694,27},product,[{var,{694,28},'Type'},{var,{694,34},'Bin'},{var,{694,39},'Options'}]},{type,{695,35},union,[{type,{695,35},tuple,[{atom,{695,36},ok},{var,{695,40},'Packet'},{var,{695,48},'Rest'}]},{type,{696,35},tuple,[{atom,{696,36},more},{var,{696,42},'Length'}]},{type,{697,35},tuple,[{atom,{697,36},error},{var,{697,43},'Reason'}]}]}]},[{type,{698,7},constraint,[{atom,{698,7},is_subtype},[{var,{698,7},'Type'},{type,{698,15},union,[{atom,{698,15},raw},{integer,{698,23},0},{integer,{698,27},1},{integer,{698,31},2},{integer,{698,35},4},{atom,{698,39},asn1},{atom,{698,48},cdr},{atom,{698,56},sunrm},{atom,{698,66},fcgi},{atom,{699,15},tpkt},{atom,{699,24},line},{atom,{699,33},http},{atom,{699,42},http_bin},{atom,{699,55},httph},{atom,{699,65},httph_bin}]}]]},{type,{700,7},constraint,[{atom,{700,7},is_subtype},[{var,{700,7},'Bin'},{type,{700,14},binary,[]}]]},{type,{701,7},constraint,[{atom,{701,7},is_subtype},[{var,{701,7},'Options'},{type,{701,18},list,[{var,{701,19},'Opt'}]}]]},{type,{702,7},constraint,[{atom,{702,7},is_subtype},[{var,{702,7},'Opt'},{type,{702,14},union,[{type,{702,14},tuple,[{atom,{702,15},packet_size},{type,{702,28},non_neg_integer,[]}]},{type,{703,14},tuple,[{atom,{703,15},line_length},{type,{703,28},non_neg_integer,[]}]}]}]]},{type,{704,7},constraint,[{atom,{704,7},is_subtype},[{var,{704,7},'Packet'},{type,{704,17},union,[{type,{704,17},binary,[]},{var,{704,28},'HttpPacket'}]}]]},{type,{705,7},constraint,[{atom,{705,7},is_subtype},[{var,{705,7},'Rest'},{type,{705,15},binary,[]}]]},{type,{706,7},constraint,[{atom,{706,7},is_subtype},[{var,{706,7},'Length'},{type,{706,17},union,[{type,{706,17},non_neg_integer,[]},{atom,{706,37},undefined}]}]]},{type,{707,7},constraint,[{atom,{707,7},is_subtype},[{var,{707,7},'Reason'},{type,{707,17},term,[]}]]},{type,{708,7},constraint,[{atom,{708,7},is_subtype},[{var,{708,7},'HttpPacket'},{type,{708,21},union,[{var,{708,21},'HttpRequest'},{var,{709,21},'HttpResponse'},{var,{710,21},'HttpHeader'},{atom,{711,21},http_eoh},{var,{712,21},'HttpError'}]}]]},{type,{713,7},constraint,[{atom,{713,7},is_subtype},[{var,{713,7},'HttpRequest'},{type,{713,22},tuple,[{atom,{713,23},http_request},{var,{713,39},'HttpMethod'},{var,{713,51},'HttpUri'},{var,{713,60},'HttpVersion'}]}]]},{type,{714,7},constraint,[{atom,{714,7},is_subtype},[{var,{714,7},'HttpResponse'},{type,{714,23},tuple,[{atom,{714,24},http_response},{var,{714,41},'HttpVersion'},{type,{714,54},integer,[]},{var,{714,65},'HttpString'}]}]]},{type,{715,7},constraint,[{atom,{715,7},is_subtype},[{var,{715,7},'HttpHeader'},{type,{715,21},tuple,[{atom,{715,22},http_header},{type,{716,22},integer,[]},{var,{717,22},'HttpField'},{ann_type,{718,22},[{var,{718,22},'UnmodifiedField'},{var,{718,41},'HttpString'}]},{ann_type,{719,22},[{var,{719,22},'Value'},{var,{719,31},'HttpString'}]}]}]]},{type,{720,7},constraint,[{atom,{720,7},is_subtype},[{var,{720,7},'HttpError'},{type,{720,20},tuple,[{atom,{720,21},http_error},{var,{720,35},'HttpString'}]}]]},{type,{721,7},constraint,[{atom,{721,7},is_subtype},[{var,{721,7},'HttpMethod'},{type,{721,21},union,[{atom,{721,21},'OPTIONS'},{atom,{721,33},'GET'},{atom,{721,41},'HEAD'},{atom,{721,50},'POST'},{atom,{721,59},'PUT'},{atom,{721,67},'DELETE'},{atom,{722,21},'TRACE'},{var,{722,31},'HttpString'}]}]]},{type,{723,7},constraint,[{atom,{723,7},is_subtype},[{var,{723,7},'HttpUri'},{type,{723,18},union,[{atom,{723,18},'*'},{type,{724,18},tuple,[{atom,{724,20},absoluteURI},{type,{725,20},union,[{atom,{725,20},http},{atom,{725,29},https}]},{ann_type,{726,20},[{var,{726,20},'Host'},{var,{726,28},'HttpString'}]},{ann_type,{727,20},[{var,{727,20},'Port'},{type,{727,28},union,[{remote_type,{727,28},[{atom,{727,28},inet},{atom,{727,33},port_number},[]]},{atom,{727,49},undefined}]}]},{ann_type,{728,20},[{var,{728,20},'Path'},{var,{728,28},'HttpString'}]}]},{type,{729,18},tuple,[{atom,{729,19},scheme},{ann_type,{729,29},[{var,{729,29},'Scheme'},{var,{729,39},'HttpString'}]},{var,{729,51},'HttpString'}]},{type,{730,18},tuple,[{atom,{730,19},abs_path},{var,{730,31},'HttpString'}]},{var,{731,18},'HttpString'}]}]]},{type,{732,7},constraint,[{atom,{732,7},is_subtype},[{var,{732,7},'HttpVersion'},{type,{732,22},tuple,[{ann_type,{732,23},[{var,{732,23},'Major'},{type,{732,32},non_neg_integer,[]}]},{ann_type,{732,51},[{var,{732,51},'Minor'},{type,{732,60},non_neg_integer,[]}]}]}]]},{type,{733,7},constraint,[{atom,{733,7},is_subtype},[{var,{733,7},'HttpField'},{type,{733,20},union,[{atom,{733,20},'Cache-Control'},{atom,{734,20},'Connection'},{atom,{735,20},'Date'},{atom,{736,20},'Pragma'},{atom,{737,20},'Transfer-Encoding'},{atom,{738,20},'Upgrade'},{atom,{739,20},'Via'},{atom,{740,20},'Accept'},{atom,{741,20},'Accept-Charset'},{atom,{742,20},'Accept-Encoding'},{atom,{743,20},'Accept-Language'},{atom,{744,20},'Authorization'},{atom,{745,20},'From'},{atom,{746,20},'Host'},{atom,{747,20},'If-Modified-Since'},{atom,{748,20},'If-Match'},{atom,{749,20},'If-None-Match'},{atom,{750,20},'If-Range'},{atom,{751,20},'If-Unmodified-Since'},{atom,{752,20},'Max-Forwards'},{atom,{753,20},'Proxy-Authorization'},{atom,{754,20},'Range'},{atom,{755,20},'Referer'},{atom,{756,20},'User-Agent'},{atom,{757,20},'Age'},{atom,{758,20},'Location'},{atom,{759,20},'Proxy-Authenticate'},{atom,{760,20},'Public'},{atom,{761,20},'Retry-After'},{atom,{762,20},'Server'},{atom,{763,20},'Vary'},{atom,{764,20},'Warning'},{atom,{765,19},'Www-Authenticate'},{atom,{766,20},'Allow'},{atom,{767,20},'Content-Base'},{atom,{768,20},'Content-Encoding'},{atom,{769,20},'Content-Language'},{atom,{770,20},'Content-Length'},{atom,{771,20},'Content-Location'},{atom,{772,20},'Content-Md5'},{atom,{773,20},'Content-Range'},{atom,{774,20},'Content-Type'},{atom,{775,20},'Etag'},{atom,{776,20},'Expires'},{atom,{777,20},'Last-Modified'},{atom,{778,20},'Accept-Ranges'},{atom,{779,20},'Set-Cookie'},{atom,{780,20},'Set-Cookie2'},{atom,{781,20},'X-Forwarded-For'},{atom,{782,20},'Cookie'},{atom,{783,20},'Keep-Alive'},{atom,{784,20},'Proxy-Connection'},{var,{785,20},'HttpString'}]}]]},{type,{786,7},constraint,[{atom,{786,7},is_subtype},[{var,{786,7},'HttpString'},{type,{786,21},union,[{type,{786,21},string,[]},{type,{786,32},binary,[]}]}]]}]]}]}}]}},{{function,delete_element,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,791}],[<<100,101,108,101,116,101,95,101,108,101,109,101,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,101,119,32,116,117,112,108,101,32,119,105,116,104,32,101,108,101,109,101,110,116,32,97,116,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,100,101,108,101,116,101,95,101,108,101,109,101,110,116,40,50,44,32,123,111,110,101,44,32,116,119,111,44,32,116,104,114,101,101,125,41,46,10,123,111,110,101,44,116,104,114,101,101,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,49,57>>,signature => [{attribute,{791,2},spec,{{erlang,delete_element,2},[{type,{791,28},bounded_fun,[{type,{791,28},'fun',[{type,{791,28},product,[{var,{791,29},'Index'},{var,{791,36},'Tuple1'}]},{var,{791,47},'Tuple2'}]},[{type,{792,7},constraint,[{atom,{792,7},is_subtype},[{var,{792,7},'Index'},{type,{792,17},pos_integer,[]}]]},{type,{793,7},constraint,[{atom,{793,7},is_subtype},[{var,{793,7},'Tuple1'},{type,{793,17},tuple,any}]]},{type,{794,7},constraint,[{atom,{794,7},is_subtype},[{var,{794,7},'Tuple2'},{type,{794,17},tuple,any}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,delete_module,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,799}],[<<100,101,108,101,116,101,95,109,111,100,117,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<77,97,107,101,115,32,116,104,101,32,99,117,114,114,101,110,116,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,98,101,99,111,109,101,32,111,108,100,32,99,111,100,101,32,97,110,100,32,100,101,108,101,116,101,115,32,97,108,108,32,114,101,102,101,114,101,110,99,101,115,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,32,102,114,111,109,32,116,104,101,32,101,120,112,111,114,116,32,116,97,98,108,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,109,111,100,117,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,114,101,32,97,108,114,101,97,100,121,32,105,115,32,97,110,32,111,108,100,32,118,101,114,115,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,51,50>>,signature => [{attribute,{799,2},spec,{{delete_module,1},[{type,{799,20},bounded_fun,[{type,{799,20},'fun',[{type,{799,20},product,[{var,{799,21},'Module'}]},{type,{799,32},union,[{atom,{799,32},true},{atom,{799,39},undefined}]}]},[{type,{800,7},constraint,[{atom,{800,7},is_subtype},[{var,{800,7},'Module'},{type,{800,17},module,[]}]]}]]}]}}]}},{{function,demonitor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,805}],[<<100,101,109,111,110,105,116,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,111,98,116,97,105,110,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,50>>]}]},<<44,32,116,104,105,115,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,102,102,46,32,73,102,32,116,104,101,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,97,108,114,101,97,100,121,32,116,117,114,110,101,100,32,111,102,102,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46>>]},{p,[],[<<79,110,99,101,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41>>]},<<32,104,97,115,32,114,101,116,117,114,110,101,100,44,32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,110,111,32>>,{code,[],[<<123,39,68,79,87,78,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,44,32,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,44,32,119,105,108,108,32,98,101,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46,32,72,111,119,101,118,101,114,44,32,97,32>>,{code,[],[<<123,39,68,79,87,78,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,32,99,97,110,32,104,97,118,101,32,98,101,101,110,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,46,32,73,116,32,105,115,32,116,104,101,114,101,102,111,114,101,32,117,115,117,97,108,108,121,32,97,100,118,105,115,97,98,108,101,32,116,111,32,114,101,109,111,118,101,32,115,117,99,104,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,102,114,111,109,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,102,116,101,114,32,109,111,110,105,116,111,114,105,110,103,32,104,97,115,32,98,101,101,110,32,115,116,111,112,112,101,100,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,44,32,91,102,108,117,115,104,93,41>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41>>]},<<32,105,102,32,116,104,105,115,32,99,108,101,97,110,117,112,32,105,115,32,119,97,110,116,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,32,40,69,82,84,83,32,53,46,53,41,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,47,49>>]},<<32,98,101,104,97,118,101,100,32,99,111,109,112,108,101,116,101,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,109,111,110,105,116,111,114,32,119,97,115,32,97,99,116,105,118,101,32,117,110,116,105,108,32,116,104,101,32,34,100,101,109,111,110,105,116,111,114,32,115,105,103,110,97,108,34,32,114,101,97,99,104,101,100,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,46,32,84,104,105,115,32,104,97,100,32,111,110,101,32,117,110,100,101,115,105,114,97,98,108,101,32,101,102,102,101,99,116,46,32,89,111,117,32,99,111,117,108,100,32,110,101,118,101,114,32,107,110,111,119,32,119,104,101,110,32,121,111,117,32,119,101,114,101,32,103,117,97,114,97,110,116,101,101,100,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,114,101,99,101,105,118,101,32,97,32>>,{code,[],[<<68,79,87,78>>]},<<32,109,101,115,115,97,103,101,32,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,118,105,101,119,101,100,32,97,115,32,116,119,111,32,99,111,109,98,105,110,101,100,32,111,112,101,114,97,116,105,111,110,115,58,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,32,115,101,110,100,32,97,32,34,100,101,109,111,110,105,116,111,114,32,115,105,103,110,97,108,34,32,116,111,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,32,97,110,100,32,105,103,110,111,114,101,32,97,110,121,32,102,117,116,117,114,101,32,114,101,115,117,108,116,115,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32,73,116,32,105,115,32,97,110,32,101,114,114,111,114,32,105,102,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,109,111,110,105,116,111,114,105,110,103,32,115,116,97,114,116,101,100,32,98,121,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,78,111,116,32,97,108,108,32,115,117,99,104,32,99,97,115,101,115,32,97,114,101,32,99,104,101,97,112,32,116,111,32,99,104,101,99,107,46,32,73,102,32,99,104,101,99,107,105,110,103,32,105,115,32,99,104,101,97,112,44,32,116,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,32,105,102,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,105,115,32,97,32,114,101,109,111,116,101,32,114,101,102,101,114,101,110,99,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,53,48>>,signature => [{attribute,{805,2},spec,{{demonitor,1},[{type,{805,16},bounded_fun,[{type,{805,16},'fun',[{type,{805,16},product,[{var,{805,17},'MonitorRef'}]},{atom,{805,32},true}]},[{type,{806,7},constraint,[{atom,{806,7},is_subtype},[{var,{806,7},'MonitorRef'},{type,{806,21},reference,[]}]]}]]}]}}]}},{{function,demonitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,811}],[<<100,101,109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,117,110,108,101,115,115,32>>,{code,[],[<<105,110,102,111>>]},<<32,105,115,32,112,97,114,116,32,111,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<46>>]},{p,[],[{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,44,32,91,93,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41>>]}]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,108,117,115,104>>]}]},{dd,[],[{p,[],[<<82,101,109,111,118,101,115,32,40,111,110,101,41,32>>,{code,[],[<<123,95,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125>>]},<<32,109,101,115,115,97,103,101,44,32,105,102,32,116,104,101,114,101,32,105,115,32,111,110,101,44,32,102,114,111,109,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,102,116,101,114,32,109,111,110,105,116,111,114,105,110,103,32,104,97,115,32,98,101,101,110,32,115,116,111,112,112,101,100,46>>]},{p,[],[<<67,97,108,108,105,110,103,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,44,32,91,102,108,117,115,104,93,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<100,101,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,82,101,102,41,44,10,114,101,99,101,105,118,101,10,32,32,32,32,123,95,44,32,77,111,110,105,116,111,114,82,101,102,44,32,95,44,32,95,44,32,95,125,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,97,102,116,101,114,32,48,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,101,110,100>>]}]}]},{dt,[],[{code,[],[<<105,110,102,111>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,119,97,115,32,102,111,117,110,100,32,97,110,100,32,114,101,109,111,118,101,100,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,110,111,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,105,115,32,109,111,110,105,116,111,114,32,104,97,115,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,97,110,100,32,119,105,108,108,32,110,111,116,32,98,101,32,100,101,108,105,118,101,114,101,100,46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,119,97,115,32,110,111,116,32,102,111,117,110,100,32,97,110,100,32,99,111,117,108,100,32,110,111,116,32,98,101,32,114,101,109,111,118,101,100,46,32,84,104,105,115,32,112,114,111,98,97,98,108,121,32,98,101,99,97,117,115,101,32,115,111,109,101,111,110,101,32,97,108,114,101,97,100,121,32,104,97,115,32,112,108,97,99,101,100,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,105,115,32,109,111,110,105,116,111,114,32,105,110,32,116,104,101,32,99,97,108,108,101,114,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]}]}]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<105,110,102,111>>]},<<32,105,115,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<102,108,117,115,104>>]},<<44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,102,32,97,32,102,108,117,115,104,32,119,97,115,32,110,101,101,100,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<77,111,114,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,111,112,116,105,111,110,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<84,104,101,32,115,97,109,101,32,102,97,105,108,117,114,101,32,97,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,47,49>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,54,57,50>>,signature => [{attribute,{811,2},spec,{{demonitor,2},[{type,{811,16},bounded_fun,[{type,{811,16},'fun',[{type,{811,16},product,[{var,{811,17},'MonitorRef'},{var,{811,29},'OptionList'}]},{type,{811,44},boolean,[]}]},[{type,{812,7},constraint,[{atom,{812,7},is_subtype},[{var,{812,7},'MonitorRef'},{type,{812,21},reference,[]}]]},{type,{813,7},constraint,[{atom,{813,7},is_subtype},[{var,{813,7},'OptionList'},{type,{813,21},list,[{var,{813,22},'Option'}]}]]},{type,{814,7},constraint,[{atom,{814,7},is_subtype},[{var,{814,7},'Option'},{type,{814,17},union,[{atom,{814,17},flush},{atom,{814,25},info}]}]]}]]}]}}]}},{{function,disconnect_node,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3449}],[<<100,105,115,99,111,110,110,101,99,116,95,110,111,100,101,47,49>>],#{<<101,110>> => [{p,[],[<<70,111,114,99,101,115,32,116,104,101,32,100,105,115,99,111,110,110,101,99,116,105,111,110,32,111,102,32,97,32,110,111,100,101,46,32,84,104,105,115,32,97,112,112,101,97,114,115,32,116,111,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<32,97,115,32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,104,97,115,32,99,114,97,115,104,101,100,46,32,84,104,105,115,32,66,73,70,32,105,115,32,109,97,105,110,108,121,32,117,115,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,110,101,116,119,111,114,107,32,97,117,116,104,101,110,116,105,99,97,116,105,111,110,32,112,114,111,116,111,99,111,108,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,100,105,115,99,111,110,110,101,99,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,73,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<105,103,110,111,114,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,109,97,121,32,114,101,116,117,114,110,32,98,101,102,111,114,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,95,110,111,100,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,109,101,115,115,97,103,101,115>>]},<<32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,54,48>>,signature => [{attribute,{3449,2},spec,{{disconnect_node,1},[{type,{3449,22},bounded_fun,[{type,{3449,22},'fun',[{type,{3449,22},product,[{var,{3449,23},'Node'}]},{type,{3449,32},union,[{type,{3449,32},boolean,[]},{atom,{3449,44},ignored}]}]},[{type,{3450,7},constraint,[{atom,{3450,7},is_subtype},[{var,{3450,7},'Node'},{type,{3450,15},node,[]}]]}]]}]}}]}},{{function,display,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,838}],[<<100,105,115,112,108,97,121,47,49>>],#{<<101,110>> => [{p,[],[<<80,114,105,110,116,115,32,97,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,111,110,32,116,104,101,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,55,57>>,signature => [{attribute,{838,2},spec,{{erlang,display,1},[{type,{838,21},bounded_fun,[{type,{838,21},'fun',[{type,{838,21},product,[{var,{838,22},'Term'}]},{atom,{838,31},true}]},[{type,{839,7},constraint,[{atom,{839,7},is_subtype},[{var,{839,7},'Term'},{type,{839,15},term,[]}]]}]]}]}}]}},{{function,dist_ctrl_get_data,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3733}],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,47,49>>],#{<<101,110>> => [{p,[],[<<71,101,116,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,100,97,116,97,32,102,114,111,109,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,116,104,97,116,32,105,115,32,116,111,32,98,101,32,112,97,115,115,101,100,32,116,111,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,46,32,84,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,73,102,32,110,111,32,100,97,116,97,32,105,115,32,97,118,97,105,108,97,98,108,101,44,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,110,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,110,101,32,99,97,110,32,114,101,113,117,101,115,116,32,116,111,32,98,101,32,105,110,102,111,114,109,101,100,32,98,121,32,97,32,109,101,115,115,97,103,101,32,119,104,101,110,32,109,111,114,101,32,100,97,116,97,32,105,115,32,97,118,97,105,108,97,98,108,101,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,40,68,72,97,110,100,108,101,41>>]}]},<<46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,119,104,101,110,32,116,104,101,114,101,32,97,114,101,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,99,111,110,102,105,103,117,114,101,100,32,111,110,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>]}]},<<32,102,117,110,99,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,101,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,55,57,49>>,signature => [{attribute,{3733,2},spec,{{erlang,dist_ctrl_get_data,1},[{type,{3733,32},bounded_fun,[{type,{3733,32},'fun',[{type,{3733,32},product,[{var,{3733,33},'DHandle'}]},{type,{3733,45},union,[{type,{3733,45},tuple,[{var,{3733,46},'Size'},{var,{3733,52},'Data'}]},{var,{3733,60},'Data'},{atom,{3733,67},none}]}]},[{type,{3734,7},constraint,[{atom,{3734,7},is_subtype},[{var,{3734,7},'Size'},{type,{3734,15},non_neg_integer,[]}]]},{type,{3735,7},constraint,[{atom,{3735,7},is_subtype},[{var,{3735,7},'DHandle'},{user_type,{3735,18},dist_handle,[]}]]},{type,{3736,7},constraint,[{atom,{3736,7},is_subtype},[{var,{3736,7},'Data'},{user_type,{3736,15},iovec,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_get_opt,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3755}],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,111,112,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,111,110,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>]}]},<<32,102,117,110,99,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,101,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,56,51,50>>,signature => [{attribute,{3755,2},spec,{{erlang,dist_ctrl_get_opt,2},[{type,{3755,31},bounded_fun,[{type,{3755,31},'fun',[{type,{3755,31},product,[{var,{3755,32},'DHandle'},{atom,{3755,41},get_size}]},{var,{3755,56},'Value'}]},[{type,{3756,7},constraint,[{atom,{3756,7},is_subtype},[{var,{3756,7},'DHandle'},{user_type,{3756,18},dist_handle,[]}]]},{type,{3757,7},constraint,[{atom,{3757,7},is_subtype},[{var,{3757,7},'Value'},{type,{3757,16},boolean,[]}]]}]]}]}}],since => <<79,84,80,32,50,50,46,48>>}},{{function,dist_ctrl_get_data_notification,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3741}],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,113,117,101,115,116,32,110,111,116,105,102,105,99,97,116,105,111,110,32,119,104,101,110,32,109,111,114,101,32,100,97,116,97,32,105,115,32,97,118,97,105,108,97,98,108,101,32,116,111,32,102,101,116,99,104,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]}]},<<32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,87,104,101,110,32,109,111,114,101,32,100,97,116,97,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<100,105,115,116,95,100,97,116,97>>]},<<46,32,79,110,99,101,32,97,32>>,{code,[],[<<100,105,115,116,95,100,97,116,97>>]},<<32,109,101,115,115,97,103,101,115,32,104,97,115,32,98,101,101,110,32,115,101,110,116,44,32,110,111,32,109,111,114,101,32>>,{code,[],[<<100,105,115,116,95,100,97,116,97>>]},<<32,109,101,115,115,97,103,101,115,32,119,105,108,108,32,98,101,32,115,101,110,116,32,117,110,116,105,108,32,116,104,101,32>>,{code,[],[<<100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,95,110,111,116,105,102,105,99,97,116,105,111,110,47,49>>]},<<32,102,117,110,99,116,105,111,110,32,104,97,115,32,98,101,101,110,32,99,97,108,108,101,100,32,97,103,97,105,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,101,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,56,54,49>>,signature => [{attribute,{3741,2},spec,{{erlang,dist_ctrl_get_data_notification,1},[{type,{3741,45},bounded_fun,[{type,{3741,45},'fun',[{type,{3741,45},product,[{var,{3741,46},'DHandle'}]},{atom,{3741,58},ok}]},[{type,{3742,7},constraint,[{atom,{3742,7},is_subtype},[{var,{3742,7},'DHandle'},{user_type,{3742,18},dist_handle,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_input_handler,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3719}],[<<100,105,115,116,95,99,116,114,108,95,105,110,112,117,116,95,104,97,110,100,108,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,103,105,115,116,101,114,32,97,110,32,97,108,116,101,114,110,97,116,101,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,112,114,111,99,101,115,115,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,79,110,99,101,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,104,97,115,32,98,101,101,110,32,99,97,108,108,101,100,44,32>>,{code,[],[<<73,110,112,117,116,72,97,110,100,108,101,114>>]},<<32,105,115,32,116,104,101,32,111,110,108,121,32,112,114,111,99,101,115,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,112,117,116,95,100,97,116,97,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,112,117,116,95,100,97,116,97,40,68,72,97,110,100,108,101,44,32,68,97,116,97,41>>]}]},<<32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,100,101,110,116,105,102,121,105,110,103,32,116,104,105,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,101,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,56,57,55>>,signature => [{attribute,{3719,2},spec,{{erlang,dist_ctrl_input_handler,2},[{type,{3719,37},bounded_fun,[{type,{3719,37},'fun',[{type,{3719,37},product,[{var,{3719,38},'DHandle'},{var,{3719,47},'InputHandler'}]},{atom,{3719,64},ok}]},[{type,{3720,7},constraint,[{atom,{3720,7},is_subtype},[{var,{3720,7},'DHandle'},{user_type,{3720,18},dist_handle,[]}]]},{type,{3721,7},constraint,[{atom,{3721,7},is_subtype},[{var,{3721,7},'InputHandler'},{type,{3721,23},pid,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_put_data,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3726}],[<<100,105,115,116,95,99,116,114,108,95,112,117,116,95,100,97,116,97,47,50>>],#{<<101,110>> => [{p,[],[<<68,101,108,105,118,101,114,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,100,97,116,97,32,102,114,111,109,32,97,32,114,101,109,111,116,101,32,110,111,100,101,32,116,111,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,117,110,108,101,115,115,32,97,110,32,97,108,116,101,114,110,97,116,101,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,112,114,111,99,101,115,115,32,104,97,115,32,98,101,101,110,32,114,101,103,105,115,116,101,114,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,105,110,112,117,116,95,104,97,110,100,108,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,105,110,112,117,116,95,104,97,110,100,108,101,114,40,68,72,97,110,100,108,101,44,32,73,110,112,117,116,72,97,110,100,108,101,114,41>>]}]},<<46,32,73,102,32,97,110,32,97,108,116,101,114,110,97,116,101,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,104,97,115,32,98,101,101,110,32,114,101,103,105,115,116,101,114,101,100,44,32,111,110,108,121,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,105,110,112,117,116,32,104,97,110,100,108,101,114,32,112,114,111,99,101,115,115,32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,101,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,51,48>>,signature => [{attribute,{3726,2},spec,{{erlang,dist_ctrl_put_data,2},[{type,{3726,32},bounded_fun,[{type,{3726,32},'fun',[{type,{3726,32},product,[{var,{3726,33},'DHandle'},{var,{3726,42},'Data'}]},{atom,{3726,51},ok}]},[{type,{3727,7},constraint,[{atom,{3727,7},is_subtype},[{var,{3727,7},'DHandle'},{user_type,{3727,18},dist_handle,[]}]]},{type,{3728,7},constraint,[{atom,{3728,7},is_subtype},[{var,{3728,7},'Data'},{type,{3728,15},iodata,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,dist_ctrl_set_opt,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3747}],[<<100,105,115,116,95,99,116,114,108,95,115,101,116,95,111,112,116,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,111,110,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<46,32,84,104,105,115,32,111,112,116,105,111,110,32,99,111,110,116,114,111,108,115,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32,99,97,108,108,115,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,117,115,101,100,32,119,104,101,110,32,115,101,116,116,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,46,32,87,104,101,110,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,32,105,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[<<97,110,100,32,116,104,101,114,101,32,97,114,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,44,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]},<<32,119,105,108,108,32,106,117,115,116,32,114,101,116,117,114,110,32>>,{code,[],[<<68,97,116,97>>]},<<32,116,111,32,112,97,115,115,32,111,118,101,114,32,116,104,101,32,99,104,97,110,110,101,108,46,32,84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<103,101,116,95,115,105,122,101>>]},<<32,111,112,116,105,111,110,46>>]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[<<97,110,100,32,116,104,101,114,101,32,97,114,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,100,97,116,97,32,97,118,97,105,108,97,98,108,101,44,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,100,105,115,116,95,99,116,114,108,95,103,101,116,95,100,97,116,97,40,68,72,97,110,100,108,101,41>>]},<<32,119,105,108,108,32,114,101,116,117,114,110,32>>,{code,[],[<<68,97,116,97>>]},<<32,116,111,32,112,97,115,115,32,111,118,101,114,32,116,104,101,32,99,104,97,110,110,101,108,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32>>,{code,[],[<<83,105,122,101>>]},<<32,111,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,110,32,98,121,116,101,115,46,32,84,104,105,115,32,105,115,32,114,101,116,117,114,110,101,100,32,97,115,32,97,32,116,117,112,108,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,83,105,122,101,44,32,68,97,116,97,125>>]},<<46>>]}]},{p,[],[<<65,108,108,32,111,112,116,105,111,110,115,32,97,114,101,32,115,101,116,32,116,111,32,100,101,102,97,117,108,116,32,119,104,101,110,32,97,32,99,104,97,110,110,101,108,32,105,115,32,99,108,111,115,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,103,105,115,116,101,114,101,100,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,32,102,111,114,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,99,97,108,108,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,119,104,101,110,32,105,109,112,108,101,109,101,110,116,105,110,103,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,97,114,114,105,101,114,32,117,115,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,115,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,111,110,116,114,111,108,108,101,114,115,46,32>>,{code,[],[<<68,72,97,110,100,108,101>>]},<<32,105,115,32,114,101,116,114,105,101,118,101,100,32,118,105,97,32,116,104,101,32,99,97,108,108,98,97,99,107,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,104,115,95,100,97,116,97,95,102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<102,95,104,97,110,100,115,104,97,107,101,95,99,111,109,112,108,101,116,101>>]}]},<<46,32,77,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,97,108,116,95,100,105,115,116,35,100,105,115,116,114,105,98,117,116,105,111,110,95,109,111,100,117,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,226,158,156,32,72,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,110,32,65,108,116,101,114,110,97,116,105,118,101,32,67,97,114,114,105,101,114,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,226,158,156,32,68,105,115,116,114,105,98,117,116,105,111,110,32,77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,57,54,51>>,signature => [{attribute,{3747,2},spec,{{erlang,dist_ctrl_set_opt,3},[{type,{3747,31},bounded_fun,[{type,{3747,31},'fun',[{type,{3747,31},product,[{var,{3747,32},'DHandle'},{atom,{3747,41},get_size},{var,{3747,53},'Value'}]},{var,{3747,63},'OldValue'}]},[{type,{3748,7},constraint,[{atom,{3748,7},is_subtype},[{var,{3748,7},'DHandle'},{user_type,{3748,18},dist_handle,[]}]]},{type,{3749,7},constraint,[{atom,{3749,7},is_subtype},[{var,{3749,7},'Value'},{type,{3749,16},boolean,[]}]]},{type,{3750,7},constraint,[{atom,{3750,7},is_subtype},[{var,{3750,7},'OldValue'},{type,{3750,19},boolean,[]}]]}]]}]}}],since => <<79,84,80,32,50,50,46,48>>}},{{function,element,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2179}],[<<101,108,101,109,101,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{code,[],[<<78>>]},<<116,104,32,101,108,101,109,101,110,116,32,40,110,117,109,98,101,114,105,110,103,32,102,114,111,109,32,49,41,32,111,102,32>>,{code,[],[<<84,117,112,108,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,108,101,109,101,110,116,40,50,44,32,123,97,44,32,98,44,32,99,125,41,46,10,98>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,49,50>>,signature => [{attribute,{2179,2},spec,{{element,2},[{type,{2179,14},bounded_fun,[{type,{2179,14},'fun',[{type,{2179,14},product,[{var,{2179,15},'N'},{var,{2179,18},'Tuple'}]},{type,{2179,28},term,[]}]},[{type,{2180,5},constraint,[{atom,{2180,5},is_subtype},[{var,{2180,5},'N'},{type,{2180,10},pos_integer,[]}]]},{type,{2181,5},constraint,[{atom,{2181,5},is_subtype},[{var,{2181,5},'Tuple'},{type,{2181,14},tuple,any}]]}]]}]}}]}},{{function,erase,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,897}],[<<101,114,97,115,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,97,110,100,32,100,101,108,101,116,101,115,32,105,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,123,49,44,32,50,44,32,51,125,41,44,10,112,117,116,40,107,101,121,50,44,32,91,97,44,32,98,44,32,99,93,41,44,10,101,114,97,115,101,40,41,46,10,91,123,107,101,121,49,44,123,49,44,50,44,51,125,125,44,123,107,101,121,50,44,91,97,44,98,44,99,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,50,54>>,signature => [{attribute,{897,2},spec,{{erase,0},[{type,{897,12},bounded_fun,[{type,{897,12},'fun',[{type,{897,12},product,[]},{type,{897,18},list,[{type,{897,19},tuple,[{var,{897,20},'Key'},{var,{897,25},'Val'}]}]}]},[{type,{898,7},constraint,[{atom,{898,7},is_subtype},[{var,{898,7},'Key'},{type,{898,14},term,[]}]]},{type,{899,7},constraint,[{atom,{899,7},is_subtype},[{var,{899,7},'Val'},{type,{899,14},term,[]}]]}]]}]}}]}},{{function,erase,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,904}],[<<101,114,97,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<32,97,110,100,32,100,101,108,101,116,101,115,32,105,116,32,102,114,111,109,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,110,111,32,118,97,108,117,101,32,105,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<46,32,84,104,101,32,97,118,101,114,97,103,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,79,40>>,{code,[],[<<49>>]},<<41,32,97,110,100,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,105,115,32,79,40>>,{code,[],[<<78>>]},<<41,44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,105,116,101,109,115,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,123,109,101,114,114,121,44,32,108,97,109,98,115,44,32,97,114,101,44,32,112,108,97,121,105,110,103,125,41,44,10,88,32,61,32,101,114,97,115,101,40,107,101,121,49,41,44,10,123,88,44,32,101,114,97,115,101,40,107,101,121,49,41,125,46,10,123,123,109,101,114,114,121,44,108,97,109,98,115,44,97,114,101,44,112,108,97,121,105,110,103,125,44,117,110,100,101,102,105,110,101,100,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,52,48>>,signature => [{attribute,{904,2},spec,{{erase,1},[{type,{904,12},bounded_fun,[{type,{904,12},'fun',[{type,{904,12},product,[{var,{904,13},'Key'}]},{type,{904,21},union,[{var,{904,21},'Val'},{atom,{904,27},undefined}]}]},[{type,{905,7},constraint,[{atom,{905,7},is_subtype},[{var,{905,7},'Key'},{type,{905,14},term,[]}]]},{type,{906,7},constraint,[{atom,{906,7},is_subtype},[{var,{906,7},'Val'},{type,{906,14},term,[]}]]}]]}]}}]}},{{function,error,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,912}],[<<101,114,114,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,119,105,116,104,32,116,104,101,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,116,104,114,111,119,110,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46>>]},{p,[],[<<84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,105,115,32,116,111,32,115,105,103,110,97,108,32,116,104,97,116,32,97,110,32,117,110,101,120,112,101,99,116,101,100,32,101,114,114,111,114,32,104,97,115,32,104,97,112,112,101,110,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,119,105,116,104,32,97,32,112,97,114,97,109,101,116,101,114,32,116,104,97,116,32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,41,46,32,83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,99,97,116,99,104,32,101,114,114,111,114,40,102,111,111,98,97,114,41,46,10,123,39,69,88,73,84,39,44,123,102,111,111,98,97,114,44,91,123,115,104,101,108,108,44,97,112,112,108,121,95,102,117,110,44,51,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,57,48,54,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,101,114,108,95,101,118,97,108,44,100,111,95,97,112,112,108,121,44,54,44,91,123,102,105,108,101,44,34,101,114,108,95,101,118,97,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,55,55,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,101,114,108,95,101,118,97,108,44,101,120,112,114,44,53,44,91,123,102,105,108,101,44,34,101,114,108,95,101,118,97,108,46,101,114,108,34,125,44,123,108,105,110,101,44,52,51,48,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,115,104,101,108,108,44,101,120,112,114,115,44,55,44,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,56,55,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,115,104,101,108,108,44,101,118,97,108,95,101,120,112,114,115,44,55,44,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,52,50,125,93,125,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,115,104,101,108,108,44,101,118,97,108,95,108,111,111,112,44,51,44,91,123,102,105,108,101,44,34,115,104,101,108,108,46,101,114,108,34,125,44,123,108,105,110,101,44,54,50,55,125,93,125,93,125,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,54,49>>,signature => [{attribute,{912,2},spec,{{error,1},[{type,{912,12},bounded_fun,[{type,{912,12},'fun',[{type,{912,12},product,[{var,{912,13},'Reason'}]},{type,{912,24},no_return,[]}]},[{type,{913,7},constraint,[{atom,{913,7},is_subtype},[{var,{913,7},'Reason'},{type,{913,17},term,[]}]]}]]}]}}]}},{{function,error,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,919}],[<<101,114,114,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,119,105,116,104,32,116,104,101,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46,32>>,{code,[],[<<65,114,103,115>>]},<<32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,116,104,101,32,108,105,115,116,32,111,102,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,110,101>>]},<<46,32,73,102,32,105,116,32,105,115,32,97,32,108,105,115,116,44,32,105,116,32,105,115,32,117,115,101,100,32,116,111,32,112,114,111,118,105,100,101,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,105,110,32,116,104,101,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,46,32,73,102,32,105,116,32,105,115,32>>,{code,[],[<<110,111,110,101>>]},<<44,32,116,104,101,32,97,114,105,116,121,32,111,102,32,116,104,101,32,99,97,108,108,105,110,103,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,105,110,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46>>]},{p,[],[<<84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,105,115,32,116,111,32,115,105,103,110,97,108,32,116,104,97,116,32,97,110,32,117,110,101,120,112,101,99,116,101,100,32,101,114,114,111,114,32,104,97,115,32,104,97,112,112,101,110,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,119,105,116,104,32,97,32,112,97,114,97,109,101,116,101,114,32,116,104,97,116,32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,41,46,32,83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46,32,69,120,97,109,112,108,101,58>>]},{p,[],[{code,[],[<<116,101,115,116,46,101,114,108>>]},<<58>>]},{pre,[],[{code,[],[<<45,109,111,100,117,108,101,40,116,101,115,116,41,46,10,45,101,120,112,111,114,116,40,91,101,120,97,109,112,108,101,95,102,117,110,47,50,93,41,46,10,10,101,120,97,109,112,108,101,95,102,117,110,40,65,49,44,32,65,50,41,32,45,62,10,32,32,32,32,101,114,108,97,110,103,58,101,114,114,111,114,40,109,121,95,101,114,114,111,114,44,32,91,65,49,44,32,65,50,93,41,46>>]}]},{p,[],[<<69,114,108,97,110,103,32,115,104,101,108,108,58>>]},{pre,[],[{code,[],[<<54,62,32,99,40,116,101,115,116,41,46,10,123,111,107,44,116,101,115,116,125,10,55,62,32,116,101,115,116,58,101,120,97,109,112,108,101,95,102,117,110,40,97,114,103,49,44,34,116,104,105,115,32,105,115,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,34,41,46,10,42,42,32,101,120,99,101,112,116,105,111,110,32,101,114,114,111,114,58,32,109,121,95,101,114,114,111,114,10,32,32,32,32,32,105,110,32,102,117,110,99,116,105,111,110,32,32,116,101,115,116,58,101,120,97,109,112,108,101,95,102,117,110,47,50,10,32,32,32,32,32,32,32,32,32,99,97,108,108,101,100,32,97,115,32,116,101,115,116,58,101,120,97,109,112,108,101,95,102,117,110,40,97,114,103,49,44,34,116,104,105,115,32,105,115,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,34,41,10,32>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,48,56,55>>,signature => [{attribute,{919,2},spec,{{error,2},[{type,{919,12},bounded_fun,[{type,{919,12},'fun',[{type,{919,12},product,[{var,{919,13},'Reason'},{var,{919,21},'Args'}]},{type,{919,30},no_return,[]}]},[{type,{920,7},constraint,[{atom,{920,7},is_subtype},[{var,{920,7},'Reason'},{type,{920,17},term,[]}]]},{type,{921,7},constraint,[{atom,{921,7},is_subtype},[{var,{921,7},'Args'},{type,{921,15},union,[{type,{921,15},list,[{type,{921,16},term,[]}]},{atom,{921,26},none}]}]]}]]}]}}]}},{{function,error,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,927}],[<<101,114,114,111,114,47,51>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,119,105,116,104,32,116,104,101,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46,32>>,{code,[],[<<65,114,103,115>>]},<<32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,116,104,101,32,108,105,115,116,32,111,102,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,110,101>>]},<<46,32,73,102,32,105,116,32,105,115,32,97,32,108,105,115,116,44,32,105,116,32,105,115,32,117,115,101,100,32,116,111,32,112,114,111,118,105,100,101,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,105,110,32,116,104,101,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,46,32,73,102,32,105,116,32,105,115,32>>,{code,[],[<<110,111,110,101>>]},<<44,32,116,104,101,32,97,114,105,116,121,32,111,102,32,116,104,101,32,99,97,108,108,105,110,103,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,100,32,105,110,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46>>]},{p,[],[<<73,102,32,116,104,101,32>>,{code,[],[<<101,114,114,111,114,95,105,110,102,111>>]},<<32,111,112,116,105,111,110,32,105,115,32,103,105,118,101,110,44,32,116,104,101,32>>,{code,[],[<<69,114,114,111,114,73,110,102,111,77,97,112>>]},<<32,119,105,108,108,32,98,101,32,105,110,115,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,103,105,118,101,110,32,105,110,32,116,104,101,32>>,{code,[],[<<69,114,114,111,114,73,110,102,111,77,97,112>>]},<<32,105,115,32,116,111,32,98,101,32,117,115,101,100,32,98,121,32,101,114,114,111,114,32,102,111,114,109,97,116,116,101,114,115,32,115,117,99,104,32,97,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,114,108,95,101,114,114,111,114,35,102,111,114,109,97,116,95,101,120,99,101,112,116,105,111,110,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,95,101,114,114,111,114>>]}]},<<32,116,111,32,112,114,111,118,105,100,101,32,109,111,114,101,32,99,111,110,116,101,120,116,32,97,114,111,117,110,100,32,97,110,32,101,114,114,111,114,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<109,111,100,117,108,101>>]},<<32,111,102,32,116,104,101,32>>,{code,[],[<<69,114,114,111,114,73,110,102,111,77,97,112>>]},<<32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,116,104,97,116,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,47,51>>]}]},<<32,105,115,32,109,97,100,101,46,32,84,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<102,117,110,99,116,105,111,110>>]},<<32,105,115,32>>,{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114>>]},<<46,32,83,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,114,108,95,101,114,114,111,114,35,102,111,114,109,97,116,95,101,114,114,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,50>>]}]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,111,110,32,104,111,119,32,116,104,105,115,32,77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,50,32,105,115,32,116,111,32,98,101,32,117,115,101,100>>]},{p,[],[<<84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<32,105,115,32,116,111,32,115,105,103,110,97,108,32,116,104,97,116,32,97,110,32,117,110,101,120,112,101,99,116,101,100,32,101,114,114,111,114,32,104,97,115,32,104,97,112,112,101,110,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,119,105,116,104,32,97,32,112,97,114,97,109,101,116,101,114,32,116,104,97,116,32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,116,121,112,101,41,46,32,83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,49,50,52>>,signature => [{attribute,{927,2},spec,{{error,3},[{type,{927,12},bounded_fun,[{type,{927,12},'fun',[{type,{927,12},product,[{var,{927,13},'Reason'},{var,{927,21},'Args'},{var,{927,27},'Options'}]},{type,{927,39},no_return,[]}]},[{type,{928,7},constraint,[{atom,{928,7},is_subtype},[{var,{928,7},'Reason'},{type,{928,17},term,[]}]]},{type,{929,7},constraint,[{atom,{929,7},is_subtype},[{var,{929,7},'Args'},{type,{929,15},union,[{type,{929,15},list,[{type,{929,16},term,[]}]},{atom,{929,26},none}]}]]},{type,{930,7},constraint,[{atom,{930,7},is_subtype},[{var,{930,7},'Options'},{type,{930,18},list,[{var,{930,19},'Option'}]}]]},{type,{931,7},constraint,[{atom,{931,7},is_subtype},[{var,{931,7},'Option'},{type,{931,17},tuple,[{atom,{931,18},error_info},{var,{931,32},'ErrorInfoMap'}]}]]},{type,{932,7},constraint,[{atom,{932,7},is_subtype},[{var,{932,7},'ErrorInfoMap'},{type,{932,23},map,[{type,{932,33},map_field_assoc,[{atom,{932,25},cause},{type,{932,36},term,[]}]},{type,{933,34},map_field_assoc,[{atom,{933,25},module},{type,{933,37},module,[]}]},{type,{934,36},map_field_assoc,[{atom,{934,25},function},{type,{934,39},atom,[]}]}]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,exit,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,940}],[<<101,120,105,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<101,120,105,116>>]},<<32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46,32,65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46>>]},{p,[],[<<84,104,101,32,105,110,116,101,110,116,32,111,102,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,32>>,{code,[],[<<101,120,105,116>>]},<<32,105,115,32,116,104,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,115,104,111,117,108,100,32,98,101,32,115,116,111,112,112,101,100,32,40,102,111,114,32,101,120,97,109,112,108,101,32,119,104,101,110,32,97,32,109,101,115,115,97,103,101,32,116,101,108,108,105,110,103,32,97,32,112,114,111,99,101,115,115,32,116,111,32,115,116,111,112,32,105,115,32,114,101,99,101,105,118,101,100,41,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,100,105,102,102,101,114,32,102,114,111,109,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,47,49,44,50,44,51>>]}]},<<32,98,121,32,99,97,117,115,105,110,103,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,97,32,100,105,102,102,101,114,101,110,116,32,99,108,97,115,115,32,97,110,100,32,98,121,32,104,97,118,105,110,103,32,97,32,114,101,97,115,111,110,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,116,104,101,32,108,105,115,116,32,111,102,32,102,117,110,99,116,105,111,110,115,32,102,114,111,109,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,46>>]},{p,[],[<<83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,120,105,116,40,102,111,111,98,97,114,41,46,10,42,42,32,101,120,99,101,112,116,105,111,110,32,101,120,105,116,58,32,102,111,111,98,97,114,10,62,32,99,97,116,99,104,32,101,120,105,116,40,102,111,111,98,97,114,41,46,10,123,39,69,88,73,84,39,44,102,111,111,98,97,114,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,99,97,108,108,115,32>>,{code,[],[<<101,120,105,116,40,107,105,108,108,41>>]},<<32,97,110,100,32,100,111,101,115,32,110,111,116,32,99,97,116,99,104,32,116,104,101,32,101,120,99,101,112,116,105,111,110,44,32,105,116,32,119,105,108,108,32,116,101,114,109,105,110,97,116,101,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,97,110,100,32,97,108,115,111,32,101,109,105,116,32,101,120,105,116,32,115,105,103,110,97,108,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,40,110,111,116,32>>,{code,[],[<<107,105,108,108,101,100>>]},<<41,32,116,111,32,97,108,108,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,46,32,83,117,99,104,32,101,120,105,116,32,115,105,103,110,97,108,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,99,97,110,32,98,101,32,116,114,97,112,112,101,100,32,98,121,32,116,104,101,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,46,32,78,111,116,101,32,116,104,97,116,32,116,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,115,105,103,110,97,108,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,98,101,104,97,118,101,32,100,105,102,102,101,114,101,110,116,108,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,121,32,97,114,101,32,115,101,110,116,32,98,101,99,97,117,115,101,32,116,104,101,32,115,105,103,110,97,108,32,119,105,108,108,32,98,101,32,117,110,116,114,97,112,112,97,98,108,101,32,105,102,32,97,32,112,114,111,99,101,115,115,32,115,101,110,100,115,32,115,117,99,104,32,97,32,115,105,103,110,97,108,32,116,111,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,49,53,51>>,signature => [{attribute,{940,2},spec,{{exit,1},[{type,{940,11},bounded_fun,[{type,{940,11},'fun',[{type,{940,11},product,[{var,{940,12},'Reason'}]},{type,{940,23},no_return,[]}]},[{type,{941,7},constraint,[{atom,{941,7},is_subtype},[{var,{941,7},'Reason'},{type,{941,17},term,[]}]]}]]}]}}]}},{{function,exit,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,946}],[<<101,120,105,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,98,101,104,97,118,105,111,114,32,97,112,112,108,105,101,115,32,105,102,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,97,110,121,32,116,101,114,109,44,32,101,120,99,101,112,116,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,111,114,32>>,{code,[],[<<107,105,108,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<80>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32,110,111,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32>>,{code,[],[<<80>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,116,114,97,110,115,102,111,114,109,101,100,32,105,110,116,111,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,82,101,97,115,111,110,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,114,111,109>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,115,101,110,116,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,44,32,97,110,100,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,102,32>>,{code,[],[<<80>>]},<<46>>]}]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,98,101,104,97,118,105,111,114,32,97,112,112,108,105,101,115,32,105,102,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,116,104,101,32,116,101,114,109,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80>>]},<<32,119,104,105,99,104,32,105,115,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,105,110,118,111,107,101,100,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,40,80,105,100,44,32,110,111,114,109,97,108,41>>]},<<32,40,116,104,101,32,98,101,104,97,118,105,111,114,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32,115,101,110,100,115,32,97,32,115,105,103,110,97,108,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,114,101,97,115,111,110,32,116,111,32,105,116,115,101,108,102,32,105,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,119,97,114,110,105,110,103,41,58>>]},{ul,[],[{li,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,116,114,97,110,115,102,111,114,109,101,100,32,105,110,116,111,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,110,111,114,109,97,108,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,114,111,109>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,115,101,110,116,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,44,32,97,110,100,32,100,101,108,105,118,101,114,101,100,32,116,111,32>>,{code,[],[<<80>>]},<<39,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]},{li,[],[<<84,104,101,32,115,105,103,110,97,108,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,105,102,32>>,{code,[],[<<80>>]},<<32,105,115,32,110,111,116,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,46>>]}]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<107,105,108,108>>]},<<44,32,116,104,97,116,32,105,115,44,32,105,102,32>>,{code,[],[<<101,120,105,116,40,80,105,100,44,32,107,105,108,108,41>>]},<<32,105,115,32,99,97,108,108,101,100,44,32,97,110,32,117,110,116,114,97,112,112,97,98,108,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,105,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,119,104,105,99,104,32,117,110,99,111,110,100,105,116,105,111,110,97,108,108,121,32,101,120,105,116,115,32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108,101,100>>]},<<46,32,84,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,105,115,32,99,104,97,110,103,101,100,32,102,114,111,109,32>>,{code,[],[<<107,105,108,108>>]},<<32,116,111,32>>,{code,[],[<<107,105,108,108,101,100>>]},<<32,116,111,32,104,105,110,116,32,116,111,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,116,104,101,32,107,105,108,108,101,100,32,112,114,111,99,101,115,115,32,103,111,116,32,107,105,108,108,101,100,32,98,121,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,120,105,116,40,80,105,100,44,32,107,105,108,108,41>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]}]},<<32,97,114,101,32,110,97,109,101,100,32,115,105,109,105,108,97,114,108,121,32,98,117,116,32,112,114,111,118,105,100,101,32,118,101,114,121,32,100,105,102,102,101,114,101,110,116,32,102,117,110,99,116,105,111,110,97,108,105,116,105,101,115,46,32,84,104,101,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,49>>]},<<32,102,117,110,99,116,105,111,110,32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,105,110,116,101,110,116,32,105,115,32,116,111,32,115,116,111,112,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,119,104,105,108,101,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]},<<32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,105,110,116,101,110,116,32,105,115,32,116,111,32,115,101,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,116,111,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,78,111,116,101,32,97,108,115,111,32,116,104,97,116,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,49>>]},<<32,114,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,116,104,97,116,32,99,97,110,32,98,101,32,99,97,117,103,104,116,32,119,104,105,108,101,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]},<<32,100,111,101,115,32,110,111,116,32,99,97,117,115,101,32,97,110,121,32,101,120,99,101,112,116,105,111,110,32,116,111,32,98,101,32,114,97,105,115,101,100,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,32,111,110,108,121,32,115,99,101,110,97,114,105,111,32,116,104,97,116,32,104,97,115,32,110,111,116,32,98,101,101,110,32,99,111,118,101,114,101,100,32,98,121,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,97,98,111,118,101,32,105,115,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80>>]},<<32,115,101,110,100,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,116,111,32,105,116,115,101,108,102,44,32,116,104,97,116,32,105,115,32>>,{code,[],[<<101,114,108,97,110,103,58,101,120,105,116,40,115,101,108,102,40,41,44,32,110,111,114,109,97,108,41>>]},<<46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,105,110,32,116,104,105,115,32,115,99,101,110,97,114,105,111,32,105,115,32,97,115,32,102,111,108,108,111,119,115,58>>]},{ul,[],[{li,[],[<<73,102,32>>,{code,[],[<<80>>]},<<32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,116,114,97,110,115,102,111,114,109,101,100,32,105,110,116,111,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,110,111,114,109,97,108,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,114,111,109>>]},<<32,105,115,32>>,{code,[],[<<80>>]},<<39,115,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,97,110,100,32,100,101,108,105,118,101,114,101,100,32,116,111,32>>,{code,[],[<<80>>]},<<39,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]},{li,[],[{code,[],[<<80>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,105,102,32>>,{code,[],[<<80>>]},<<32,105,115,32,110,111,116,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,46>>]}]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,98,101,104,97,118,105,111,114,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32,115,101,110,100,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,116,111,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,115,32,97,114,103,117,97,98,108,121,32,115,116,114,97,110,103,101,32,98,117,116,32,116,104,105,115,32,98,101,104,97,118,105,111,114,32,105,115,32,107,101,112,116,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,114,101,97,115,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,49,57,53>>,signature => [{attribute,{946,2},spec,{{exit,2},[{type,{946,11},bounded_fun,[{type,{946,11},'fun',[{type,{946,11},product,[{var,{946,12},'Pid'},{var,{946,17},'Reason'}]},{atom,{946,28},true}]},[{type,{947,7},constraint,[{atom,{947,7},is_subtype},[{var,{947,7},'Pid'},{type,{947,14},union,[{type,{947,14},pid,[]},{type,{947,22},port,[]}]}]]},{type,{948,7},constraint,[{atom,{948,7},is_subtype},[{var,{948,7},'Reason'},{type,{948,17},term,[]}]]}]]}]}}]}},{{function,external_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,960}],[<<101,120,116,101,114,110,97,108,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,97,108,99,117,108,97,116,101,115,44,32,119,105,116,104,111,117,116,32,100,111,105,110,103,32,116,104,101,32,101,110,99,111,100,105,110,103,44,32,116,104,101,32,109,97,120,105,109,117,109,32,98,121,116,101,32,115,105,122,101,32,102,111,114,32,97,32,116,101,114,109,32,101,110,99,111,100,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,32,97,112,112,108,105,101,115,32,97,108,119,97,121,115,58>>]},{pre,[],[{code,[],[<<62,32,83,105,122,101,49,32,61,32,98,121,116,101,95,115,105,122,101,40,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,41,41,44,10,62,32,83,105,122,101,50,32,61,32,101,114,108,97,110,103,58,101,120,116,101,114,110,97,108,95,115,105,122,101,40,84,101,114,109,41,44,10,62,32,116,114,117,101,32,61,32,83,105,122,101,49,32,61,60,32,83,105,122,101,50,46,10,116,114,117,101>>]}]},{p,[],[<<84,104,105,115,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,97,32,99,97,108,108,32,116,111,58>>]},{pre,[],[{code,[],[<<101,114,108,97,110,103,58,101,120,116,101,114,110,97,108,95,115,105,122,101,40,84,101,114,109,44,32,91,93,41>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,50,56,49>>,signature => [{attribute,{960,2},spec,{{erlang,external_size,1},[{type,{960,27},bounded_fun,[{type,{960,27},'fun',[{type,{960,27},product,[{var,{960,28},'Term'}]},{type,{960,37},non_neg_integer,[]}]},[{type,{961,7},constraint,[{atom,{961,7},is_subtype},[{var,{961,7},'Term'},{type,{961,15},term,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66,48,52>>}},{{function,external_size,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,966}],[<<101,120,116,101,114,110,97,108,95,115,105,122,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,97,108,99,117,108,97,116,101,115,44,32,119,105,116,104,111,117,116,32,100,111,105,110,103,32,116,104,101,32,101,110,99,111,100,105,110,103,44,32,116,104,101,32,109,97,120,105,109,117,109,32,98,121,116,101,32,115,105,122,101,32,102,111,114,32,97,32,116,101,114,109,32,101,110,99,111,100,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,32,97,112,112,108,105,101,115,32,97,108,119,97,121,115,58>>]},{pre,[],[{code,[],[<<62,32,83,105,122,101,49,32,61,32,98,121,116,101,95,115,105,122,101,40,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,44,32,79,112,116,105,111,110,115,41,41,44,10,62,32,83,105,122,101,50,32,61,32,101,114,108,97,110,103,58,101,120,116,101,114,110,97,108,95,115,105,122,101,40,84,101,114,109,44,32,79,112,116,105,111,110,115,41,44,10,62,32,116,114,117,101,32,61,32,83,105,122,101,49,32,61,60,32,83,105,122,101,50,46,10,116,114,117,101>>]}]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<123,109,105,110,111,114,95,118,101,114,115,105,111,110,44,32,86,101,114,115,105,111,110,125>>]},<<32,115,112,101,99,105,102,105,101,115,32,104,111,119,32,102,108,111,97,116,115,32,97,114,101,32,101,110,99,111,100,101,100,46,32,70,111,114,32,97,32,100,101,116,97,105,108,101,100,32,100,101,115,99,114,105,112,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,48,48>>,signature => [{attribute,{966,2},spec,{{erlang,external_size,2},[{type,{966,27},bounded_fun,[{type,{966,27},'fun',[{type,{966,27},product,[{var,{966,28},'Term'},{var,{966,34},'Options'}]},{type,{966,46},non_neg_integer,[]}]},[{type,{967,7},constraint,[{atom,{967,7},is_subtype},[{var,{967,7},'Term'},{type,{967,15},term,[]}]]},{type,{968,7},constraint,[{atom,{968,7},is_subtype},[{var,{968,7},'Options'},{type,{968,18},list,[{type,{968,19},tuple,[{atom,{968,20},minor_version},{ann_type,{968,35},[{var,{968,35},'Version'},{type,{968,46},non_neg_integer,[]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66,48,52>>}},{{function,float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,990}],[<<102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,102,108,111,97,116,32,98,121,32,99,111,110,118,101,114,116,105,110,103,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,97,32,102,108,111,97,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,97,116,40,53,53,41,46,10,53,53,46,48>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,117,115,101,100,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,105,110,32,97,32,103,117,97,114,100,44,32,105,116,32,116,101,115,116,115,32,119,104,101,116,104,101,114,32,116,104,101,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,102,108,111,97,116,105,110,103,32,112,111,105,110,116,32,110,117,109,98,101,114,59,32,102,111,114,32,99,108,97,114,105,116,121,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,115,95,102,108,111,97,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,102,108,111,97,116,47,49>>]}]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<87,104,101,110,32>>,{code,[],[<<102,108,111,97,116,47,49>>]},<<32,105,115,32,117,115,101,100,32,105,110,32,97,110,32,101,120,112,114,101,115,115,105,111,110,32,105,110,32,97,32,103,117,97,114,100,44,32,115,117,99,104,32,97,115,32,39>>,{code,[],[<<102,108,111,97,116,40,65,41,32,61,61,32,52,46,48>>]},<<39,44,32,105,116,32,99,111,110,118,101,114,116,115,32,97,32,110,117,109,98,101,114,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,50,48>>,signature => [{attribute,{990,2},spec,{{float,1},[{type,{990,12},bounded_fun,[{type,{990,12},'fun',[{type,{990,12},product,[{var,{990,13},'Number'}]},{type,{990,24},float,[]}]},[{type,{991,7},constraint,[{atom,{991,7},is_subtype},[{var,{991,7},'Number'},{type,{991,17},number,[]}]]}]]}]}}]}},{{function,float_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,996}],[<<102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,70,108,111,97,116,44,91,123,115,99,105,101,110,116,105,102,105,99,44,50,48,125,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,52,50>>,signature => [{attribute,{996,2},spec,{{float_to_binary,1},[{type,{996,22},bounded_fun,[{type,{996,22},'fun',[{type,{996,22},product,[{var,{996,23},'Float'}]},{type,{996,33},binary,[]}]},[{type,{997,7},constraint,[{atom,{997,7},is_subtype},[{var,{997,7},'Float'},{type,{997,16},float,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,float_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1002}],[<<102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,108,111,97,116>>]},<<32,117,115,105,110,103,32,102,105,120,101,100,32,100,101,99,105,109,97,108,32,112,111,105,110,116,32,102,111,114,109,97,116,116,105,110,103,46,32>>,{code,[],[<<79,112,116,105,111,110,115>>]},<<32,98,101,104,97,118,101,115,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,108,111,97,116,95,116,111,95,108,105,115,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,50>>]}]},<<46,32,69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,93,41,46,10,60,60,34,55,46,49,50,48,48,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,44,32,99,111,109,112,97,99,116,93,41,46,10,60,60,34,55,46,49,50,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,123,115,99,105,101,110,116,105,102,105,99,44,32,51,125,93,41,46,10,60,60,34,55,46,49,50,48,101,43,48,48,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,55,46,49,50,44,32,91,115,104,111,114,116,93,41,46,10,60,60,34,55,46,49,50,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,48,46,49,43,48,46,50,44,32,91,115,104,111,114,116,93,41,46,10,60,60,34,48,46,51,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,34,62,62,10,62,32,102,108,111,97,116,95,116,111,95,98,105,110,97,114,121,40,48,46,49,43,48,46,50,41,10,60,60,34,51,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,52,52,48,57,101,45,48,49,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,53,49>>,signature => [{attribute,{1002,2},spec,{{float_to_binary,2},[{type,{1002,22},bounded_fun,[{type,{1002,22},'fun',[{type,{1002,22},product,[{var,{1002,23},'Float'},{var,{1002,30},'Options'}]},{type,{1002,42},binary,[]}]},[{type,{1003,7},constraint,[{atom,{1003,7},is_subtype},[{var,{1003,7},'Float'},{type,{1003,16},float,[]}]]},{type,{1004,7},constraint,[{atom,{1004,7},is_subtype},[{var,{1004,7},'Options'},{type,{1004,18},list,[{var,{1004,19},'Option'}]}]]},{type,{1005,7},constraint,[{atom,{1005,7},is_subtype},[{var,{1005,7},'Option'},{type,{1005,18},union,[{type,{1005,18},tuple,[{atom,{1005,19},decimals},{ann_type,{1005,29},[{var,{1005,29},'Decimals'},{type,{1005,41},range,[{integer,{1005,41},0},{integer,{1005,44},253}]}]}]},{type,{1006,18},tuple,[{atom,{1006,19},scientific},{ann_type,{1006,31},[{var,{1006,31},'Decimals'},{type,{1006,43},range,[{integer,{1006,43},0},{integer,{1006,46},249}]}]}]},{atom,{1007,18},compact},{atom,{1008,18},short}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,float_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1013}],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,40,70,108,111,97,116,44,91,123,115,99,105,101,110,116,105,102,105,99,44,50,48,125,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,55,56>>,signature => [{attribute,{1013,2},spec,{{float_to_list,1},[{type,{1013,20},bounded_fun,[{type,{1013,20},'fun',[{type,{1013,20},product,[{var,{1013,21},'Float'}]},{type,{1013,31},string,[]}]},[{type,{1014,7},constraint,[{atom,{1014,7},is_subtype},[{var,{1014,7},'Float'},{type,{1014,16},float,[]}]]}]]}]}}]}},{{function,float_to_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1019}],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,108,111,97,116>>]},<<32,117,115,105,110,103,32,102,105,120,101,100,32,100,101,99,105,109,97,108,32,112,111,105,110,116,32,102,111,114,109,97,116,116,105,110,103,46>>]},{p,[],[<<65,118,97,105,108,97,98,108,101,32,111,112,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<100,101,99,105,109,97,108,115>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,99,111,110,116,97,105,110,115,32,97,116,32,109,111,115,116,32>>,{code,[],[<<68,101,99,105,109,97,108,115>>]},<<32,110,117,109,98,101,114,32,111,102,32,100,105,103,105,116,115,32,112,97,115,116,32,116,104,101,32,100,101,99,105,109,97,108,32,112,111,105,110,116,46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,116,104,101,32,105,110,116,101,114,110,97,108,32,115,116,97,116,105,99,32,98,117,102,102,101,114,32,111,102,32,50,53,54,32,98,121,116,101,115,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,104,114,111,119,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46>>]}]},{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,97,99,116>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,116,114,97,105,108,105,110,103,32,122,101,114,111,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,108,105,115,116,32,97,114,101,32,116,114,117,110,99,97,116,101,100,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,111,110,108,121,32,109,101,97,110,105,110,103,102,117,108,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<100,101,99,105,109,97,108,115>>]},<<46>>]}]},{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<115,99,105,101,110,116,105,102,105,99>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,108,111,97,116,32,105,115,32,102,111,114,109,97,116,116,101,100,32,117,115,105,110,103,32,115,99,105,101,110,116,105,102,105,99,32,110,111,116,97,116,105,111,110,32,119,105,116,104,32>>,{code,[],[<<68,101,99,105,109,97,108,115>>]},<<32,100,105,103,105,116,115,32,111,102,32,112,114,101,99,105,115,105,111,110,46>>]}]},{li,[],[{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<115,104,111,114,116>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,108,111,97,116,32,105,115,32,102,111,114,109,97,116,116,101,100,32,119,105,116,104,32,116,104,101,32,115,109,97,108,108,101,115,116,32,110,117,109,98,101,114,32,111,102,32,100,105,103,105,116,115,32,116,104,97,116,32,115,116,105,108,108,32,103,117,97,114,97,110,116,101,101,115,32,116,104,97,116,32>>,{code,[],[<<70,32,61,58,61,32,108,105,115,116,95,116,111,95,102,108,111,97,116,40,102,108,111,97,116,95,116,111,95,108,105,115,116,40,70,44,32,91,115,104,111,114,116,93,41,41>>]},<<46,32,87,104,101,110,32,116,104,101,32,102,108,111,97,116,32,105,115,32,105,110,115,105,100,101,32,116,104,101,32,114,97,110,103,101,32,40,45,50,226,129,181,194,179,44,32,50,226,129,181,194,179,41,44,32,116,104,101,32,110,111,116,97,116,105,111,110,32,116,104,97,116,32,121,105,101,108,100,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,105,115,32,117,115,101,100,32,40,115,99,105,101,110,116,105,102,105,99,32,110,111,116,97,116,105,111,110,32,111,114,32,110,111,114,109,97,108,32,100,101,99,105,109,97,108,32,110,111,116,97,116,105,111,110,41,46,32,70,108,111,97,116,115,32,111,117,116,115,105,100,101,32,116,104,101,32,114,97,110,103,101,32,40,45,50,226,129,181,194,179,44,32,50,226,129,181,194,179,41,32,97,114,101,32,97,108,119,97,121,115,32,102,111,114,109,97,116,116,101,100,32,117,115,105,110,103,32,115,99,105,101,110,116,105,102,105,99,32,110,111,116,97,116,105,111,110,32,116,111,32,97,118,111,105,100,32,99,111,110,102,117,115,105,110,103,32,114,101,115,117,108,116,115,32,119,104,101,110,32,100,111,105,110,103,32,97,114,105,116,104,109,101,116,105,99,32,111,112,101,114,97,116,105,111,110,115,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,115>>]},<<32,105,115,32>>,{code,[],[<<91,93>>]},<<44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,98,101,104,97,118,101,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,108,111,97,116,95,116,111,95,108,105,115,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,47,49>>]}]},<<46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,93,41,46,10,34,55,46,49,50,48,48,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,123,100,101,99,105,109,97,108,115,44,32,52,125,44,32,99,111,109,112,97,99,116,93,41,46,10,34,55,46,49,50,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,123,115,99,105,101,110,116,105,102,105,99,44,32,51,125,93,41,46,10,34,55,46,49,50,48,101,43,48,48,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,55,46,49,50,44,32,91,115,104,111,114,116,93,41,46,10,34,55,46,49,50,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,48,46,49,43,48,46,50,44,32,91,115,104,111,114,116,93,41,46,10,34,48,46,51,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,34,10,62,32,102,108,111,97,116,95,116,111,95,108,105,115,116,40,48,46,49,43,48,46,50,41,10,34,51,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,52,52,48,57,101,45,48,49,34>>]}]},{p,[],[<<73,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<102,108,111,97,116,95,116,111,95,108,105,115,116,40,48,46,49,43,48,46,50,41>>]},<<32,101,118,97,108,117,97,116,101,115,32,116,111,32>>,{code,[],[<<34,51,46,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,52,52,52,48,57,101,45,48,49,34>>]},<<46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,101,120,112,108,97,105,110,101,100,32,105,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,108,111,97,116,95,114,101,112,114,101,115,101,110,116,97,116,105,111,110,95,112,114,111,98,108,101,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,70,108,111,97,116,105,110,103,32,80,111,105,110,116,32,78,117,109,98,101,114,115>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,51,56,55>>,signature => [{attribute,{1019,2},spec,{{float_to_list,2},[{type,{1019,20},bounded_fun,[{type,{1019,20},'fun',[{type,{1019,20},product,[{var,{1019,21},'Float'},{var,{1019,28},'Options'}]},{type,{1019,40},string,[]}]},[{type,{1020,7},constraint,[{atom,{1020,7},is_subtype},[{var,{1020,7},'Float'},{type,{1020,16},float,[]}]]},{type,{1021,7},constraint,[{atom,{1021,7},is_subtype},[{var,{1021,7},'Options'},{type,{1021,18},list,[{var,{1021,19},'Option'}]}]]},{type,{1022,7},constraint,[{atom,{1022,7},is_subtype},[{var,{1022,7},'Option'},{type,{1022,18},union,[{type,{1022,18},tuple,[{atom,{1022,19},decimals},{ann_type,{1022,29},[{var,{1022,29},'Decimals'},{type,{1022,41},range,[{integer,{1022,41},0},{integer,{1022,44},253}]}]}]},{type,{1023,18},tuple,[{atom,{1023,19},scientific},{ann_type,{1023,31},[{var,{1023,31},'Decimals'},{type,{1023,43},range,[{integer,{1023,43},0},{integer,{1023,46},249}]}]}]},{atom,{1024,18},compact},{atom,{1025,18},short}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,floor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1031}],[<<102,108,111,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,97,114,103,101,115,116,32,105,110,116,101,103,101,114,32,110,111,116,32,103,114,101,97,116,101,114,32,116,104,97,110,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,102,108,111,111,114,40,45,49,48,46,53,41,46,10,45,49,49>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,52,55>>,signature => [{attribute,{1031,2},spec,{{floor,1},[{type,{1031,12},bounded_fun,[{type,{1031,12},'fun',[{type,{1031,12},product,[{var,{1031,13},'Number'}]},{type,{1031,24},integer,[]}]},[{type,{1032,7},constraint,[{atom,{1032,7},is_subtype},[{var,{1032,7},'Number'},{type,{1032,17},number,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,fun_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3454}],[<<102,117,110,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,102,117,110,32>>,{code,[],[<<70,117,110>>]},<<46,32,69,97,99,104,32,108,105,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,116,117,112,108,101,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,110,100,32,109,111,114,101,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,109,97,105,110,108,121,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,44,32,98,117,116,32,105,116,32,99,97,110,32,115,111,109,101,116,105,109,101,115,32,98,101,32,117,115,101,102,117,108,32,105,110,32,108,105,98,114,97,114,121,32,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,110,101,101,100,32,116,111,32,118,101,114,105,102,121,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,114,105,116,121,32,111,102,32,97,32,102,117,110,46>>]}]},{p,[],[<<84,119,111,32,116,121,112,101,115,32,111,102,32,102,117,110,115,32,104,97,118,101,32,115,108,105,103,104,116,108,121,32,100,105,102,102,101,114,101,110,116,32,115,101,109,97,110,116,105,99,115,58>>]},{ul,[],[{li,[],[{p,[],[<<65,32,102,117,110,32,99,114,101,97,116,101,100,32,98,121,32>>,{code,[],[<<102,117,110,32,77,58,70,47,65>>]},<<32,105,115,32,99,97,108,108,101,100,32,97,110,32>>,{em,[],[<<101,120,116,101,114,110,97,108>>]},<<32,102,117,110,46,32,67,97,108,108,105,110,103,32,105,116,32,119,105,108,108,32,97,108,119,97,121,115,32,99,97,108,108,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<70>>]},<<32,119,105,116,104,32,97,114,105,116,121,32>>,{code,[],[<<65>>]},<<32,105,110,32,116,104,101,32,108,97,116,101,115,116,32,99,111,100,101,32,102,111,114,32,109,111,100,117,108,101,32>>,{code,[],[<<77>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,109,111,100,117,108,101,32>>,{code,[],[<<77>>]},<<32,100,111,101,115,32,110,111,116,32,101,118,101,110,32,110,101,101,100,32,116,111,32,98,101,32,108,111,97,100,101,100,32,119,104,101,110,32,116,104,101,32,102,117,110,32>>,{code,[],[<<102,117,110,32,77,58,70,47,65>>]},<<32,105,115,32,99,114,101,97,116,101,100,46>>]}]},{li,[],[{p,[],[<<65,108,108,32,111,116,104,101,114,32,102,117,110,115,32,97,114,101,32,99,97,108,108,101,100,32>>,{em,[],[<<108,111,99,97,108>>]},<<46,32,87,104,101,110,32,97,32,108,111,99,97,108,32,102,117,110,32,105,115,32,99,97,108,108,101,100,44,32,116,104,101,32,115,97,109,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,99,111,100,101,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,102,117,110,32,105,115,32,99,97,108,108,101,100,32,40,101,118,101,110,32,105,102,32,97,32,110,101,119,101,114,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,104,97,115,32,98,101,101,110,32,108,111,97,100,101,100,41,46>>]}]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,108,101,109,101,110,116,115,32,97,114,101,32,97,108,119,97,121,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,32,102,111,114,32,98,111,116,104,32,108,111,99,97,108,32,97,110,100,32,101,120,116,101,114,110,97,108,32,102,117,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,116,121,112,101,44,32,84,121,112,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,111,114,32>>,{code,[],[<<101,120,116,101,114,110,97,108>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,109,111,100,117,108,101,44,32,77,111,100,117,108,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<32,40,97,110,32,97,116,111,109,41,32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,44,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,105,110,32,119,104,105,99,104,32,116,104,101,32,102,117,110,32,105,115,32,100,101,102,105,110,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,110,32,101,120,116,101,114,110,97,108,32,102,117,110,44,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,116,104,101,32,109,111,100,117,108,101,32,116,104,97,116,32,116,104,101,32,102,117,110,32,114,101,102,101,114,115,32,116,111,46>>]}]},{dt,[],[{code,[],[<<123,110,97,109,101,44,32,78,97,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<78,97,109,101>>]},<<32,40,97,110,32,97,116,111,109,41,32,105,115,32,97,32,102,117,110,99,116,105,111,110,32,110,97,109,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,44,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,105,109,112,108,101,109,101,110,116,115,32,116,104,101,32,102,117,110,46,32,40,84,104,105,115,32,110,97,109,101,32,119,97,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,116,104,101,32,99,111,109,112,105,108,101,114,44,32,97,110,100,32,105,115,32,111,110,108,121,32,111,102,32,105,110,102,111,114,109,97,116,105,111,110,97,108,32,117,115,101,46,32,65,115,32,105,116,32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,44,32,105,116,32,99,97,110,110,111,116,32,98,101,32,99,97,108,108,101,100,32,100,105,114,101,99,116,108,121,46,41,32,73,102,32,110,111,32,99,111,100,101,32,105,115,32,99,117,114,114,101,110,116,108,121,32,108,111,97,100,101,100,32,102,111,114,32,116,104,101,32,102,117,110,44,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,32,111,102,32,97,110,32,97,116,111,109,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,110,32,101,120,116,101,114,110,97,108,32,102,117,110,44,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,112,111,114,116,101,100,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,116,104,101,32,102,117,110,32,114,101,102,101,114,115,32,116,111,46>>]}]},{dt,[],[{code,[],[<<123,97,114,105,116,121,44,32,65,114,105,116,121,125>>]}]},{dd,[],[{p,[],[{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,114,103,117,109,101,110,116,115,32,116,104,97,116,32,116,104,101,32,102,117,110,32,105,115,32,116,111,32,98,101,32,99,97,108,108,101,100,32,119,105,116,104,46>>]}]},{dt,[],[{code,[],[<<123,101,110,118,44,32,69,110,118,125>>]}]},{dd,[],[{p,[],[{code,[],[<<69,110,118>>]},<<32,40,97,32,108,105,115,116,41,32,105,115,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,111,114,32,102,114,101,101,32,118,97,114,105,97,98,108,101,115,32,102,111,114,32,116,104,101,32,102,117,110,46,32,70,111,114,32,101,120,116,101,114,110,97,108,32,102,117,110,115,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,105,115,32,97,108,119,97,121,115,32,101,109,112,116,121,46>>]}]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,108,101,109,101,110,116,115,32,97,114,101,32,111,110,108,121,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,32,105,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,108,111,99,97,108,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,105,100,44,32,80,105,100,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,111,114,105,103,105,110,97,108,108,121,32,99,114,101,97,116,101,100,32,116,104,101,32,102,117,110,46>>]},{p,[],[<<73,116,32,109,105,103,104,116,32,112,111,105,110,116,32,116,111,32,116,104,101,32>>,{code,[],[<<105,110,105,116>>]},<<32,112,114,111,99,101,115,115,32,105,102,32,116,104,101,32>>,{code,[],[<<70,117,110>>]},<<32,119,97,115,32,115,116,97,116,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,119,104,101,110,32,109,111,100,117,108,101,32,119,97,115,32,108,111,97,100,101,100,32,40,116,104,105,115,32,111,112,116,105,109,105,115,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,102,111,114,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,100,111,32,110,111,116,32,99,97,112,116,117,114,101,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,41,46>>]}]},{dt,[],[{code,[],[<<123,105,110,100,101,120,44,32,73,110,100,101,120,125>>]}]},{dd,[],[{p,[],[{code,[],[<<73,110,100,101,120>>]},<<32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,115,32,97,110,32,105,110,100,101,120,32,105,110,116,111,32,116,104,101,32,109,111,100,117,108,101,32,102,117,110,32,116,97,98,108,101,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,95,105,110,100,101,120,44,32,73,110,100,101,120,125>>]}]},{dd,[],[{p,[],[{code,[],[<<73,110,100,101,120>>]},<<32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,115,32,97,110,32,105,110,100,101,120,32,105,110,116,111,32,116,104,101,32,109,111,100,117,108,101,32,102,117,110,32,116,97,98,108,101,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,95,117,110,105,113,44,32,85,110,105,113,125>>]}]},{dd,[],[{p,[],[{code,[],[<<85,110,105,113>>]},<<32,40,97,32,98,105,110,97,114,121,41,32,105,115,32,97,32,117,110,105,113,117,101,32,118,97,108,117,101,32,102,111,114,32,116,104,105,115,32,102,117,110,46,32,73,116,32,105,115,32,99,97,108,99,117,108,97,116,101,100,32,102,114,111,109,32,116,104,101,32,99,111,109,112,105,108,101,100,32,99,111,100,101,32,102,111,114,32,116,104,101,32,101,110,116,105,114,101,32,109,111,100,117,108,101,46>>]}]},{dt,[],[{code,[],[<<123,117,110,105,113,44,32,85,110,105,113,125>>]}]},{dd,[],[{p,[],[{code,[],[<<85,110,105,113>>]},<<32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,115,32,97,32,117,110,105,113,117,101,32,118,97,108,117,101,32,102,111,114,32,116,104,105,115,32,102,117,110,46,32,65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,53,44,32,116,104,105,115,32,105,110,116,101,103,101,114,32,105,115,32,99,97,108,99,117,108,97,116,101,100,32,102,114,111,109,32,116,104,101,32,99,111,109,112,105,108,101,100,32,99,111,100,101,32,102,111,114,32,116,104,101,32,101,110,116,105,114,101,32,109,111,100,117,108,101,46,32,66,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,53,44,32,116,104,105,115,32,105,110,116,101,103,101,114,32,119,97,115,32,98,97,115,101,100,32,111,110,32,111,110,108,121,32,116,104,101,32,98,111,100,121,32,111,102,32,116,104,101,32,102,117,110,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,52,54,49>>,signature => [{attribute,{3454,2},spec,{{erlang,fun_info,1},[{type,{3454,22},bounded_fun,[{type,{3454,22},'fun',[{type,{3454,22},product,[{var,{3454,23},'Fun'}]},{type,{3454,31},list,[{type,{3454,32},tuple,[{var,{3454,33},'Item'},{var,{3454,39},'Info'}]}]}]},[{type,{3455,7},constraint,[{atom,{3455,7},is_subtype},[{var,{3455,7},'Fun'},{type,{3455,14},function,[]}]]},{type,{3456,7},constraint,[{atom,{3456,7},is_subtype},[{var,{3456,7},'Item'},{type,{3456,15},union,[{atom,{3456,15},arity},{atom,{3456,23},env},{atom,{3456,29},index},{atom,{3456,37},name},{atom,{3457,15},module},{atom,{3457,24},new_index},{atom,{3457,36},new_uniq},{atom,{3457,47},pid},{atom,{3457,53},type},{atom,{3457,60},uniq}]}]]},{type,{3458,7},constraint,[{atom,{3458,7},is_subtype},[{var,{3458,7},'Info'},{type,{3458,15},term,[]}]]}]]}]}}]}},{{function,fun_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1037}],[<<102,117,110,95,105,110,102,111,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<102,117,110,95,105,110,102,111,95,105,116,101,109>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32>>,{code,[],[<<70,117,110>>]},<<32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<44,32,105,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,73,116,101,109,44,73,110,102,111,125>>]},<<46>>]},{p,[],[<<70,111,114,32,97,110,121,32,102,117,110,44,32>>,{code,[],[<<73,116,101,109>>]},<<32,99,97,110,32,98,101,32,97,110,121,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<109,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<110,97,109,101>>]},<<44,32>>,{code,[],[<<97,114,105,116,121>>]},<<44,32>>,{code,[],[<<101,110,118>>]},<<44,32,111,114,32>>,{code,[],[<<116,121,112,101>>]},<<46>>]},{p,[],[<<70,111,114,32,97,32,108,111,99,97,108,32,102,117,110,44,32>>,{code,[],[<<73,116,101,109>>]},<<32,99,97,110,32,97,108,115,111,32,98,101,32,97,110,121,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<105,110,100,101,120>>]},<<44,32>>,{code,[],[<<110,101,119,95,105,110,100,101,120>>]},<<44,32>>,{code,[],[<<110,101,119,95,117,110,105,113>>]},<<44,32>>,{code,[],[<<117,110,105,113>>]},<<44,32,97,110,100,32>>,{code,[],[<<112,105,100>>]},<<46,32,70,111,114,32,97,110,32,101,120,116,101,114,110,97,108,32,102,117,110,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,97,110,121,32,111,102,32,116,104,101,115,101,32,105,116,101,109,115,32,105,115,32,97,108,119,97,121,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,117,110,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,102,117,110,95,105,110,102,111,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,54,54>>,signature => [{attribute,{1037,2},spec,{{erlang,fun_info,2},[{type,{1037,22},bounded_fun,[{type,{1037,22},'fun',[{type,{1037,22},product,[{var,{1037,23},'Fun'},{var,{1037,28},'Item'}]},{type,{1037,37},tuple,[{var,{1037,38},'Item'},{var,{1037,44},'Info'}]}]},[{type,{1038,7},constraint,[{atom,{1038,7},is_subtype},[{var,{1038,7},'Fun'},{type,{1038,14},function,[]}]]},{type,{1039,7},constraint,[{atom,{1039,7},is_subtype},[{var,{1039,7},'Item'},{user_type,{1039,15},fun_info_item,[]}]]},{type,{1040,7},constraint,[{atom,{1040,7},is_subtype},[{var,{1040,7},'Info'},{type,{1040,15},term,[]}]]}]]}]}}]}},{{function,fun_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1054}],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,116,104,97,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,99,111,100,101,32,116,104,97,116,32,99,114,101,97,116,101,100,32>>,{code,[],[<<70,117,110>>]},<<46>>]},{p,[],[{code,[],[<<83,116,114,105,110,103>>]},<<32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,44,32,105,102,32>>,{code,[],[<<70,117,110>>]},<<32,119,97,115,32,99,114,101,97,116,101,100,32,98,121,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,102,117,110,45,101,120,112,114,101,115,115,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<102,117,110,32,101,120,112,114,101,115,115,105,111,110>>]},<<32,111,102,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<102,117,110,32,77,111,100,117,108,101,78,97,109,101,58,70,117,110,99,78,97,109,101,47,65,114,105,116,121>>]},<<58>>]},{p,[],[{code,[],[<<34,102,117,110,32,77,111,100,117,108,101,78,97,109,101,58,70,117,110,99,78,97,109,101,47,65,114,105,116,121,34>>]}]},{p,[],[<<84,104,101,32,102,111,114,109,32,111,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,119,104,101,110,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,99,114,101,97,116,101,100,32,102,114,111,109,32,111,116,104,101,114,32,116,121,112,101,115,32,111,102,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,102,117,110,45,101,120,112,114,101,115,115,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<102,117,110,32,101,120,112,114,101,115,115,105,111,110,115>>]},<<32,100,105,102,102,101,114,115,32,100,101,112,101,110,100,105,110,103,32,111,110,32,105,102,32,116,104,101,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,101,120,101,99,117,116,101,100,32,119,104,105,108,101,32,101,120,101,99,117,116,105,110,103,32,99,111,109,112,105,108,101,100,32,99,111,100,101,32,111,114,32,105,102,32,116,104,101,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,101,120,101,99,117,116,101,100,32,119,104,105,108,101,32,101,120,101,99,117,116,105,110,103,32,117,110,99,111,109,112,105,108,101,100,32,99,111,100,101,32,40,117,110,99,111,109,112,105,108,101,100,32,101,115,99,114,105,112,116,115,44,32,116,104,101,32,69,114,108,97,110,103,32,115,104,101,108,108,44,32,97,110,100,32,111,116,104,101,114,32,99,111,100,101,32,101,120,101,99,117,116,101,100,32,98,121,32,116,104,101,32,101,114,108,95,101,118,97,108,32,109,111,100,117,108,101,41,58>>]},{dl,[],[{dt,[],[<<99,111,109,112,105,108,101,100,32,99,111,100,101>>]},{dd,[],[{p,[],[{code,[],[<<34,35,70,117,110,60,77,46,73,46,85,62,34>>]},<<44,32,119,104,101,114,101,32,77,44,32,73,32,97,110,100,32,85,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,116,104,101,32,118,97,108,117,101,115,32,110,97,109,101,100,32>>,{code,[],[<<109,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<105,110,100,101,120>>]},<<32,97,110,100,32>>,{code,[],[<<117,110,105,113>>]},<<32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,117,110,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,102,117,110,95,105,110,102,111,40,70,117,110,41>>]}]},<<46>>]}]},{dt,[],[<<117,110,99,111,109,112,105,108,101,100,32,99,111,100,101>>]},{dd,[],[<<65,108,108,32,102,117,110,115,32,99,114,101,97,116,101,100,32,102,114,111,109,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,117,110,99,111,109,112,105,108,101,100,32,99,111,100,101,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,97,114,105,116,121,32,97,114,101,32,109,97,112,112,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,108,105,115,116,32,98,121,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<71,101,110,101,114,97,108,108,121,44,32,111,110,101,32,99,97,110,32,110,111,116,32,117,115,101,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<32,116,111,32,99,104,101,99,107,32,105,102,32,116,119,111,32,102,117,110,115,32,97,114,101,32,101,113,117,97,108,32,97,115,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<32,100,111,101,115,32,110,111,116,32,116,97,107,101,32,116,104,101,32,102,117,110,39,115,32,101,110,118,105,114,111,110,109,101,110,116,32,105,110,116,111,32,97,99,99,111,117,110,116,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,102,117,110,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,102,117,110,95,105,110,102,111,47,49>>]}]},<<32,102,111,114,32,104,111,119,32,116,111,32,103,101,116,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,111,102,32,97,32,102,117,110,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,111,117,116,112,117,116,32,111,102,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,69,114,108,97,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,32,97,110,100,32,109,97,121,32,99,104,97,110,103,101,32,105,110,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,115,46>>]}]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<45,109,111,100,117,108,101,40,116,101,115,116,41,46,10,45,101,120,112,111,114,116,40,91,97,100,100,47,49,44,32,97,100,100,50,47,48,44,32,102,117,110,95,116,117,112,108,101,47,48,93,41,46,10,97,100,100,40,65,41,32,45,62,32,102,117,110,40,66,41,32,45,62,32,65,32,43,32,66,32,101,110,100,46,10,97,100,100,50,40,41,32,45,62,32,102,117,110,32,97,100,100,47,49,46,10,102,117,110,95,116,117,112,108,101,40,41,32,45,62,32,123,102,117,110,40,41,32,45,62,32,49,32,101,110,100,44,32,102,117,110,40,41,32,45,62,32,49,32,101,110,100,125,46,10,32,32,32,32,32,32,32,32>>]}]},{pre,[],[{code,[],[<<62,32,123,102,117,110,32,116,101,115,116,58,97,100,100,47,49,44,32,116,101,115,116,58,97,100,100,50,40,41,125,46,10,123,102,117,110,32,116,101,115,116,58,97,100,100,47,49,44,35,70,117,110,60,116,101,115,116,46,49,46,49,48,55,55,51,56,57,56,51,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32>>,{code,[],[<<102,117,110,32,116,101,115,116,58,97,100,100,47,49>>]},<<32,105,115,32,117,112,103,114,97,100,97,98,108,101,32,98,117,116,32>>,{code,[],[<<116,101,115,116,58,97,100,100,50,40,41>>]},<<32,105,115,32,110,111,116,32,117,112,103,114,97,100,97,98,108,101,46>>]},{pre,[],[{code,[],[<<62,32,123,116,101,115,116,58,97,100,100,40,49,41,44,32,116,101,115,116,58,97,100,100,40,52,50,41,125,46,10,123,35,70,117,110,60,116,101,115,116,46,48,46,49,48,55,55,51,56,57,56,51,62,44,35,70,117,110,60,116,101,115,116,46,48,46,49,48,55,55,51,56,57,56,51,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32>>,{code,[],[<<116,101,115,116,58,97,100,100,40,49,41>>]},<<32,97,110,100,32>>,{code,[],[<<116,101,115,116,58,97,100,100,40,52,50,41>>]},<<32,104,97,115,32,116,104,101,32,115,97,109,101,32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,97,115,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,105,115,32,110,111,116,32,116,97,107,101,110,32,105,110,116,111,32,97,99,99,111,117,110,116,46>>]},{pre,[],[{code,[],[<<62,116,101,115,116,58,102,117,110,95,116,117,112,108,101,40,41,46,10,123,35,70,117,110,60,116,101,115,116,46,50,46,49,48,55,55,51,56,57,56,51,62,44,35,70,117,110,60,116,101,115,116,46,51,46,49,48,55,55,51,56,57,56,51,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32,84,104,101,32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,115,32,100,105,102,102,101,114,32,98,101,99,97,117,115,101,32,116,104,101,32,102,117,110,115,32,99,111,109,101,32,102,114,111,109,32,100,105,102,102,101,114,101,110,116,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,115,46>>]},{pre,[],[{code,[],[<<62,32,123,102,117,110,40,41,32,45,62,32,49,32,101,110,100,44,32,102,117,110,40,41,32,45,62,32,49,32,101,110,100,125,46,32,62,32,10,123,35,70,117,110,60,101,114,108,95,101,118,97,108,46,52,53,46,57,55,50,56,51,48,57,53,62,44,35,70,117,110,60,101,114,108,95,101,118,97,108,46,52,53,46,57,55,50,56,51,48,57,53,62,125>>]}]},{p,[],[<<69,120,112,108,97,110,97,116,105,111,110,58,32,65,108,108,32,102,117,110,115,32,99,114,101,97,116,101,100,32,102,114,111,109,32,102,117,110,32,101,120,112,114,101,115,115,105,111,110,115,32,111,102,32,116,104,105,115,32,102,111,114,109,32,105,110,32,117,110,99,111,109,112,105,108,101,100,32,99,111,100,101,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,97,114,105,116,121,32,97,114,101,32,109,97,112,112,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,108,105,115,116,32,98,121,32>>,{code,[],[<<102,117,110,95,116,111,95,108,105,115,116,47,49>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,53,56,54>>,signature => [{attribute,{1054,2},spec,{{erlang,fun_to_list,1},[{type,{1054,25},bounded_fun,[{type,{1054,25},'fun',[{type,{1054,25},product,[{var,{1054,26},'Fun'}]},{ann_type,{1054,34},[{var,{1054,34},'String'},{type,{1054,44},string,[]}]}]},[{type,{1055,7},constraint,[{atom,{1055,7},is_subtype},[{var,{1055,7},'Fun'},{type,{1055,14},function,[]}]]}]]}]}}]}},{{function,function_exported,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1060}],[<<102,117,110,99,116,105,111,110,95,101,120,112,111,114,116,101,100,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,99,111,100,101,95,108,111,97,100,105,110,103,35,99,111,100,101,45,114,101,112,108,97,99,101,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,117,114,114,101,110,116>>]},<<32,97,110,100,32,99,111,110,116,97,105,110,115,32,97,110,32,101,120,112,111,114,116,101,100,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<44,32,111,114,32,105,102,32,116,104,101,114,101,32,105,115,32,97,32,66,73,70,32,40,97,32,98,117,105,108,116,45,105,110,32,102,117,110,99,116,105,111,110,32,105,109,112,108,101,109,101,110,116,101,100,32,105,110,32,67,41,32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,110,97,109,101,44,32,111,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,55,53>>,signature => [{attribute,{1060,2},spec,{{erlang,function_exported,3},[{type,{1060,31},bounded_fun,[{type,{1060,31},'fun',[{type,{1060,31},product,[{var,{1060,32},'Module'},{var,{1060,40},'Function'},{var,{1060,50},'Arity'}]},{type,{1060,60},boolean,[]}]},[{type,{1061,7},constraint,[{atom,{1061,7},is_subtype},[{var,{1061,7},'Module'},{type,{1061,17},module,[]}]]},{type,{1062,7},constraint,[{atom,{1062,7},is_subtype},[{var,{1062,7},'Function'},{type,{1062,19},atom,[]}]]},{type,{1063,7},constraint,[{atom,{1063,7},is_subtype},[{var,{1063,7},'Arity'},{type,{1063,16},arity,[]}]]}]]}]}}]}},{{function,garbage_collect,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1068}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>],#{<<101,110>> => [{p,[],[<<70,111,114,99,101,115,32,97,110,32,105,109,109,101,100,105,97,116,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,116,104,101,32,101,120,101,99,117,116,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,117,110,108,101,115,115,32,105,116,32,104,97,115,32,98,101,101,110,32,110,111,116,105,99,101,100,32,40,111,114,32,116,104,101,114,101,32,97,114,101,32,103,111,111,100,32,114,101,97,115,111,110,115,32,116,111,32,115,117,115,112,101,99,116,41,32,116,104,97,116,32,116,104,101,32,115,112,111,110,116,97,110,101,111,117,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,119,105,108,108,32,111,99,99,117,114,32,116,111,111,32,108,97,116,101,32,111,114,32,110,111,116,32,97,116,32,97,108,108,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,109,112,114,111,112,101,114,32,117,115,101,32,99,97,110,32,115,101,114,105,111,117,115,108,121,32,100,101,103,114,97,100,101,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,54,56,55>>,signature => [{attribute,{1068,2},spec,{{garbage_collect,0},[{type,{1068,22},'fun',[{type,{1068,22},product,[]},{atom,{1068,28},true}]}]}}]}},{{function,garbage_collect,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1073}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,40,80,105,100,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,48,51>>,signature => [{attribute,{1073,2},spec,{{garbage_collect,1},[{type,{1073,22},bounded_fun,[{type,{1073,22},'fun',[{type,{1073,22},product,[{var,{1073,23},'Pid'}]},{var,{1073,31},'GCResult'}]},[{type,{1074,7},constraint,[{atom,{1074,7},is_subtype},[{var,{1074,7},'Pid'},{type,{1074,14},pid,[]}]]},{type,{1075,7},constraint,[{atom,{1075,7},is_subtype},[{var,{1075,7},'GCResult'},{type,{1075,19},boolean,[]}]]}]]}]}}]}},{{function,garbage_collect,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1089}],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<71,97,114,98,97,103,101,32,99,111,108,108,101,99,116,115,32,116,104,101,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,82,101,113,117,101,115,116,73,100,125>>]}]},{dd,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,50>>]},<<32,114,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,115,101,110,116,46,32,87,104,101,110,32,116,104,101,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,44,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,97,108,108,101,100,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,112,97,115,115,101,100,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,44,32,82,101,113,117,101,115,116,73,100,44,32,71,67,82,101,115,117,108,116,125>>]},<<46>>]},{dt,[],[{code,[],[<<123,116,121,112,101,44,32,39,109,97,106,111,114,39,32,124,32,39,109,105,110,111,114,39,125>>]}]},{dd,[],[<<84,114,105,103,103,101,114,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,114,101,113,117,101,115,116,101,100,32,116,121,112,101,46,32,68,101,102,97,117,108,116,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<39,109,97,106,111,114,39>>]},<<44,32,119,104,105,99,104,32,119,111,117,108,100,32,116,114,105,103,103,101,114,32,97,32,102,117,108,108,115,119,101,101,112,32,71,67,46,32,84,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<39,109,105,110,111,114,39>>]},<<32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,104,105,110,116,32,97,110,100,32,109,97,121,32,108,101,97,100,32,116,111,32,101,105,116,104,101,114,32,109,105,110,111,114,32,111,114,32,109,97,106,111,114,32,71,67,32,114,117,110,46>>]}]},{p,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<115,101,108,102,40,41>>]},<<44,32,97,110,100,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,116,32,111,110,99,101,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>]}]},<<46,32,79,116,104,101,114,119,105,115,101,32,97,32,114,101,113,117,101,115,116,32,102,111,114,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,97,110,100,32,119,105,108,108,32,98,101,32,104,97,110,100,108,101,100,32,119,104,101,110,32,97,112,112,114,111,112,114,105,97,116,101,46,32,73,102,32,110,111,32>>,{code,[],[<<97,115,121,110,99>>]},<<32,111,112,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,98,108,111,99,107,115,32,117,110,116,105,108,32>>,{code,[],[<<71,67,82,101,115,117,108,116>>]},<<32,105,115,32,97,118,97,105,108,97,98,108,101,32,97,110,100,32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<71,67,82,101,115,117,108,116>>]},<<32,105,110,102,111,114,109,115,32,97,98,111,117,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,114,101,113,117,101,115,116,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,104,97,115,32,98,101,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46>>]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[<<78,111,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,119,97,115,32,112,101,114,102,111,114,109,101,100,44,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,116,101,114,109,105,110,97,116,101,100,32,98,101,102,111,114,101,32,116,104,101,32,114,101,113,117,101,115,116,32,99,111,117,108,100,32,98,101,32,115,97,116,105,115,102,105,101,100,46>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,115,97,109,101,32,99,97,118,101,97,116,115,32,97,112,112,108,121,32,97,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,47,48>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,110,111,100,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,49,51>>,signature => [{attribute,{1089,2},spec,{{garbage_collect,2},[{type,{1089,22},bounded_fun,[{type,{1089,22},'fun',[{type,{1089,22},product,[{var,{1089,23},'Pid'},{var,{1089,28},'OptionList'}]},{type,{1089,43},union,[{var,{1089,43},'GCResult'},{atom,{1089,54},async}]}]},[{type,{1090,7},constraint,[{atom,{1090,7},is_subtype},[{var,{1090,7},'Pid'},{type,{1090,14},pid,[]}]]},{type,{1091,7},constraint,[{atom,{1091,7},is_subtype},[{var,{1091,7},'RequestId'},{type,{1091,20},term,[]}]]},{type,{1092,7},constraint,[{atom,{1092,7},is_subtype},[{var,{1092,7},'Option'},{type,{1092,17},union,[{type,{1092,17},tuple,[{atom,{1092,18},async},{var,{1092,25},'RequestId'}]},{type,{1092,38},tuple,[{atom,{1092,39},type},{type,{1092,45},union,[{atom,{1092,45},major},{atom,{1092,55},minor}]}]}]}]]},{type,{1093,7},constraint,[{atom,{1093,7},is_subtype},[{var,{1093,7},'OptionList'},{type,{1093,21},list,[{var,{1093,22},'Option'}]}]]},{type,{1094,7},constraint,[{atom,{1094,7},is_subtype},[{var,{1094,7},'GCResult'},{type,{1094,19},boolean,[]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,get,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1139}],[<<103,101,116,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,97,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,75,101,121,44,32,86,97,108,125>>]},<<32,116,117,112,108,101,115,46,32,84,104,101,32,105,116,101,109,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,105,110,32,97,110,121,32,111,114,100,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,109,101,114,114,121,41,44,10,112,117,116,40,107,101,121,50,44,32,108,97,109,98,115,41,44,10,112,117,116,40,107,101,121,51,44,32,123,97,114,101,44,32,112,108,97,121,105,110,103,125,41,44,10,103,101,116,40,41,46,10,91,123,107,101,121,49,44,109,101,114,114,121,125,44,123,107,101,121,50,44,108,97,109,98,115,125,44,123,107,101,121,51,44,123,97,114,101,44,112,108,97,121,105,110,103,125,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,55,56>>,signature => [{attribute,{1139,2},spec,{{get,0},[{type,{1139,10},bounded_fun,[{type,{1139,10},'fun',[{type,{1139,10},product,[]},{type,{1139,16},list,[{type,{1139,17},tuple,[{var,{1139,18},'Key'},{var,{1139,23},'Val'}]}]}]},[{type,{1140,7},constraint,[{atom,{1140,7},is_subtype},[{var,{1140,7},'Key'},{type,{1140,14},term,[]}]]},{type,{1141,7},constraint,[{atom,{1141,7},is_subtype},[{var,{1141,7},'Val'},{type,{1141,14},term,[]}]]}]]}]}}]}},{{function,get,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1146}],[<<103,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32>>,{code,[],[<<75,101,121>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,84,104,101,32,101,120,112,101,99,116,101,100,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,79,40>>,{code,[],[<<49>>]},<<41,32,97,110,100,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,105,115,32,79,40>>,{code,[],[<<78>>]},<<41,44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,105,116,101,109,115,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,107,101,121,49,44,32,109,101,114,114,121,41,44,10,112,117,116,40,107,101,121,50,44,32,108,97,109,98,115,41,44,10,112,117,116,40,123,97,110,121,44,32,91,118,97,108,105,100,44,32,116,101,114,109,93,125,44,32,123,97,114,101,44,32,112,108,97,121,105,110,103,125,41,44,10,103,101,116,40,123,97,110,121,44,32,91,118,97,108,105,100,44,32,116,101,114,109,93,125,41,46,10,123,97,114,101,44,112,108,97,121,105,110,103,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,55,57,53>>,signature => [{attribute,{1146,2},spec,{{get,1},[{type,{1146,10},bounded_fun,[{type,{1146,10},'fun',[{type,{1146,10},product,[{var,{1146,11},'Key'}]},{type,{1146,19},union,[{var,{1146,19},'Val'},{atom,{1146,25},undefined}]}]},[{type,{1147,7},constraint,[{atom,{1147,7},is_subtype},[{var,{1147,7},'Key'},{type,{1147,14},term,[]}]]},{type,{1148,7},constraint,[{atom,{1148,7},is_subtype},[{var,{1148,7},'Val'},{type,{1148,14},term,[]}]]}]]}]}}]}},{{function,get_cookie,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3814}],[<<103,101,116,95,99,111,111,107,105,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,103,105,99,32,99,111,111,107,105,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,102,32,116,104,101,32,110,111,100,101,32,105,115,32,97,108,105,118,101,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,99,111,111,107,105,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,49,53>>,signature => [{attribute,{3814,2},spec,{{erlang,get_cookie,0},[{type,{3814,24},bounded_fun,[{type,{3814,24},'fun',[{type,{3814,24},product,[]},{type,{3814,30},union,[{var,{3814,30},'Cookie'},{atom,{3814,39},nocookie}]}]},[{type,{3815,7},constraint,[{atom,{3815,7},is_subtype},[{var,{3815,7},'Cookie'},{type,{3815,17},atom,[]}]]}]]}]}}]}},{{function,get_cookie,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3819}],[<<103,101,116,95,99,111,111,107,105,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,103,105,99,32,99,111,111,107,105,101,32,102,111,114,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,97,108,105,118,101,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<110,111,99,111,111,107,105,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,50,52>>,signature => [{attribute,{3819,2},spec,{{erlang,get_cookie,1},[{type,{3819,24},bounded_fun,[{type,{3819,24},'fun',[{type,{3819,24},product,[{var,{3819,25},'Node'}]},{type,{3819,34},union,[{var,{3819,34},'Cookie'},{atom,{3819,43},nocookie}]}]},[{type,{3820,7},constraint,[{atom,{3820,7},is_subtype},[{var,{3820,7},'Node'},{type,{3820,15},node,[]}]]},{type,{3821,7},constraint,[{atom,{3821,7},is_subtype},[{var,{3821,7},'Cookie'},{type,{3821,17},atom,[]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,49>>}},{{function,get_keys,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1153}],[<<103,101,116,95,107,101,121,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,108,108,32,107,101,121,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,84,104,101,32,105,116,101,109,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,105,110,32,97,110,121,32,111,114,100,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,100,111,103,44,32,123,97,110,105,109,97,108,44,49,125,41,44,10,112,117,116,40,99,111,119,44,32,123,97,110,105,109,97,108,44,50,125,41,44,10,112,117,116,40,108,97,109,98,44,32,123,97,110,105,109,97,108,44,51,125,41,44,10,103,101,116,95,107,101,121,115,40,41,46,10,91,100,111,103,44,99,111,119,44,108,97,109,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,51,52>>,signature => [{attribute,{1153,2},spec,{{get_keys,0},[{type,{1153,15},bounded_fun,[{type,{1153,15},'fun',[{type,{1153,15},product,[]},{type,{1153,21},list,[{var,{1153,22},'Key'}]}]},[{type,{1154,7},constraint,[{atom,{1154,7},is_subtype},[{var,{1154,7},'Key'},{type,{1154,14},term,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,get_keys,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1159}],[<<103,101,116,95,107,101,121,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,107,101,121,115,32,116,104,97,116,32,97,114,101,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,84,104,101,32,105,116,101,109,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,105,110,32,97,110,121,32,111,114,100,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,117,116,40,109,97,114,121,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,104,97,100,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,97,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,108,105,116,116,108,101,44,32,123,49,44,32,50,125,41,44,10,112,117,116,40,100,111,103,44,32,123,49,44,32,51,125,41,44,10,112,117,116,40,108,97,109,98,44,32,123,49,44,32,50,125,41,44,10,103,101,116,95,107,101,121,115,40,123,49,44,32,50,125,41,46,10,91,109,97,114,121,44,104,97,100,44,97,44,108,105,116,116,108,101,44,108,97,109,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,53,49>>,signature => [{attribute,{1159,2},spec,{{get_keys,1},[{type,{1159,15},bounded_fun,[{type,{1159,15},'fun',[{type,{1159,15},product,[{var,{1159,16},'Val'}]},{type,{1159,24},list,[{var,{1159,25},'Key'}]}]},[{type,{1160,7},constraint,[{atom,{1160,7},is_subtype},[{var,{1160,7},'Val'},{type,{1160,14},term,[]}]]},{type,{1161,7},constraint,[{atom,{1161,7},is_subtype},[{var,{1161,7},'Key'},{type,{1161,14},term,[]}]]}]]}]}}]}},{{function,group_leader,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1173}],[<<103,114,111,117,112,95,108,101,97,100,101,114,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,46>>]},{p,[],[<<69,118,101,114,121,32,112,114,111,99,101,115,115,32,105,115,32,97,32,109,101,109,98,101,114,32,111,102,32,115,111,109,101,32,112,114,111,99,101,115,115,32,103,114,111,117,112,32,97,110,100,32,97,108,108,32,103,114,111,117,112,115,32,104,97,118,101,32,97,32>>,{em,[],[<<103,114,111,117,112,32,108,101,97,100,101,114>>]},<<46,32,65,108,108,32,73,47,79,32,102,114,111,109,32,116,104,101,32,103,114,111,117,112,32,105,115,32,99,104,97,110,110,101,108,101,100,32,116,111,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,46,32,87,104,101,110,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,112,97,119,110,101,100,44,32,105,116,32,103,101,116,115,32,116,104,101,32,115,97,109,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,97,115,32,116,104,101,32,115,112,97,119,110,105,110,103,32,112,114,111,99,101,115,115,46,32,73,110,105,116,105,97,108,108,121,44,32,97,116,32,115,121,115,116,101,109,32,115,116,97,114,116,117,112,44,32>>,{code,[],[<<105,110,105,116>>]},<<32,105,115,32,98,111,116,104,32,105,116,115,32,111,119,110,32,103,114,111,117,112,32,108,101,97,100,101,114,32,97,110,100,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,111,102,32,97,108,108,32,112,114,111,99,101,115,115,101,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,55,49>>,signature => [{attribute,{1173,2},spec,{{group_leader,0},[{type,{1173,19},'fun',[{type,{1173,19},product,[]},{type,{1173,25},pid,[]}]}]}}]}},{{function,group_leader,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1178}],[<<103,114,111,117,112,95,108,101,97,100,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<32,116,111,32>>,{code,[],[<<71,114,111,117,112,76,101,97,100,101,114>>]},<<46,32,84,121,112,105,99,97,108,108,121,44,32,116,104,105,115,32,105,115,32,117,115,101,100,32,119,104,101,110,32,97,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,102,114,111,109,32,97,32,99,101,114,116,97,105,110,32,115,104,101,108,108,32,105,115,32,116,111,32,104,97,118,101,32,97,110,111,116,104,101,114,32,103,114,111,117,112,32,108,101,97,100,101,114,32,116,104,97,110,32>>,{code,[],[<<105,110,105,116>>]},<<46>>]},{p,[],[<<84,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,115,104,111,117,108,100,32,98,101,32,114,97,114,101,108,121,32,99,104,97,110,103,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,115,32,119,105,116,104,32,97,32,115,117,112,101,114,118,105,115,105,111,110,32,116,114,101,101,44,32,98,101,99,97,117,115,101,32,79,84,80,32,97,115,115,117,109,101,115,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,111,102,32,116,104,101,105,114,32,112,114,111,99,101,115,115,101,115,32,105,115,32,116,104,101,105,114,32,97,112,112,108,105,99,97,116,105,111,110,32,109,97,115,116,101,114,46>>]},{p,[],[<<83,101,116,116,105,110,103,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,102,111,108,108,111,119,115,32,116,104,101,32,115,105,103,110,97,108,32,111,114,100,101,114,105,110,103,32,103,117,97,114,97,110,116,101,101,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<80,114,111,99,101,115,115,101,115,32,67,104,97,112,116,101,114>>]},<<32,105,110,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,114,111,117,112,95,108,101,97,100,101,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,114,111,117,112,95,108,101,97,100,101,114,47,48>>]}]},<<32,97,110,100,32>>,{a,[{href,<<115,121,115,116,101,109,47,100,101,115,105,103,110,95,112,114,105,110,99,105,112,108,101,115,58,97,112,112,108,105,99,97,116,105,111,110,115,35,115,116,111,112,112,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,84,80,32,100,101,115,105,103,110,32,112,114,105,110,99,105,112,108,101,115>>]},<<32,114,101,108,97,116,101,100,32,116,111,32,115,116,97,114,116,105,110,103,32,97,110,100,32,115,116,111,112,112,105,110,103,32,97,112,112,108,105,99,97,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,56,56,54>>,signature => [{attribute,{1178,2},spec,{{group_leader,2},[{type,{1178,19},bounded_fun,[{type,{1178,19},'fun',[{type,{1178,19},product,[{var,{1178,20},'GroupLeader'},{var,{1178,33},'Pid'}]},{atom,{1178,41},true}]},[{type,{1179,7},constraint,[{atom,{1179,7},is_subtype},[{var,{1179,7},'GroupLeader'},{type,{1179,22},pid,[]}]]},{type,{1180,7},constraint,[{atom,{1180,7},is_subtype},[{var,{1180,7},'Pid'},{type,{1180,14},pid,[]}]]}]]}]}}]}},{{function,halt,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1198}],[<<104,97,108,116,47,48>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,104,97,108,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<104,97,108,116,40,48,44,32,91,93,41>>]}]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,104,97,108,116,40,41,46,10,111,115,95,112,114,111,109,112,116,37>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,49,49>>,signature => [{attribute,{1198,2},spec,{{halt,0},[{type,{1198,11},'fun',[{type,{1198,11},product,[]},{type,{1198,17},no_return,[]}]}]}}]}},{{function,halt,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1204}],[<<104,97,108,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,104,97,108,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<104,97,108,116,40,83,116,97,116,117,115,44,32,91,93,41>>]}]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,104,97,108,116,40,49,55,41,46,10,111,115,95,112,114,111,109,112,116,37,32,101,99,104,111,32,36,63,10,49,55,10,111,115,95,112,114,111,109,112,116,37>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,50,52>>,signature => [{attribute,{1204,2},spec,{{halt,1},[{type,{1204,11},bounded_fun,[{type,{1204,11},'fun',[{type,{1204,11},product,[{var,{1204,12},'Status'}]},{type,{1204,23},no_return,[]}]},[{type,{1205,7},constraint,[{atom,{1205,7},is_subtype},[{var,{1205,7},'Status'},{type,{1205,17},union,[{type,{1205,17},non_neg_integer,[]},{atom,{1205,37},abort},{type,{1205,47},string,[]}]}]]}]]}]}}]}},{{function,halt,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1216}],[<<104,97,108,116,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<83,116,97,116,117,115>>]},<<32,109,117,115,116,32,98,101,32,97,32,110,111,110,45,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,44,32,97,32,115,116,114,105,110,103,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<97,98,111,114,116>>]},<<46,32,72,97,108,116,115,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,72,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,68,101,112,101,110,100,105,110,103,32,111,110,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,99,99,117,114,115,58>>]},{dl,[],[{dt,[],[<<105,110,116,101,103,101,114,40,41>>]},{dd,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,101,120,105,116,115,32,119,105,116,104,32,105,110,116,101,103,101,114,32,118,97,108,117,101,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<32,97,115,32,115,116,97,116,117,115,32,99,111,100,101,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,101,110,118,105,114,111,110,109,101,110,116,32,40,79,83,41,46>>,{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,110,32,109,97,110,121,32,112,108,97,116,102,111,114,109,115,44,32,116,104,101,32,79,83,32,115,117,112,112,111,114,116,115,32,111,110,108,121,32,115,116,97,116,117,115,32,99,111,100,101,115,32,48,45,50,53,53,46,32,65,32,116,111,111,32,108,97,114,103,101,32,115,116,97,116,117,115,32,99,111,100,101,32,105,115,32,116,114,117,110,99,97,116,101,100,32,98,121,32,99,108,101,97,114,105,110,103,32,116,104,101,32,104,105,103,104,32,98,105,116,115,46>>]}]}]},{dt,[],[<<115,116,114,105,110,103,40,41>>]},{dd,[],[<<65,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,32,105,115,32,112,114,111,100,117,99,101,100,32,119,105,116,104,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<32,97,115,32,115,108,111,103,97,110,46,32,84,104,101,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,101,120,105,116,115,32,119,105,116,104,32,115,116,97,116,117,115,32,99,111,100,101,32>>,{code,[],[<<49>>]},<<46,32,84,104,101,32,115,116,114,105,110,103,32,119,105,108,108,32,98,101,32,116,114,117,110,99,97,116,101,100,32,105,102,32,108,111,110,103,101,114,32,116,104,97,110,32,50,48,48,32,99,104,97,114,97,99,116,101,114,115,46>>,{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,82,84,83,32,57,46,49,32,40,79,84,80,45,50,48,46,49,41,32,111,110,108,121,32,99,111,100,101,32,112,111,105,110,116,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,48,45,50,53,53,32,119,97,115,32,97,99,99,101,112,116,101,100,32,105,110,32,116,104,101,32,115,116,114,105,110,103,46,32,78,111,119,32,97,110,121,32,117,110,105,99,111,100,101,32,115,116,114,105,110,103,32,105,115,32,118,97,108,105,100,46>>]}]}]},{dt,[],[{code,[],[<<97,98,111,114,116>>]}]},{dd,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,97,98,111,114,116,115,32,112,114,111,100,117,99,105,110,103,32,97,32,99,111,114,101,32,100,117,109,112,44,32,105,102,32,116,104,97,116,32,105,115,32,101,110,97,98,108,101,100,32,105,110,32,116,104,101,32,79,83,46>>]}]},{p,[],[<<70,111,114,32,105,110,116,101,103,101,114,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<44,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,99,108,111,115,101,115,32,97,108,108,32,112,111,114,116,115,32,97,110,100,32,97,108,108,111,119,115,32,97,115,121,110,99,32,116,104,114,101,97,100,115,32,116,111,32,102,105,110,105,115,104,32,116,104,101,105,114,32,111,112,101,114,97,116,105,111,110,115,32,98,101,102,111,114,101,32,101,120,105,116,105,110,103,46,32,84,111,32,101,120,105,116,32,119,105,116,104,111,117,116,32,115,117,99,104,32,102,108,117,115,104,105,110,103,44,32,117,115,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<32,97,115,32>>,{code,[],[<<123,102,108,117,115,104,44,102,97,108,115,101,125>>]},<<46>>]},{p,[],[<<70,111,114,32,115,116,97,116,117,115,101,115,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<32,97,110,100,32>>,{code,[],[<<97,98,111,114,116>>]},<<44,32,111,112,116,105,111,110,32>>,{code,[],[<<102,108,117,115,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,32,97,110,100,32,102,108,117,115,104,105,110,103,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,100,111,110,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,51,56>>,signature => [{attribute,{1216,2},spec,{{halt,2},[{type,{1216,11},bounded_fun,[{type,{1216,11},'fun',[{type,{1216,11},product,[{var,{1216,12},'Status'},{var,{1216,20},'Options'}]},{type,{1216,32},no_return,[]}]},[{type,{1217,7},constraint,[{atom,{1217,7},is_subtype},[{var,{1217,7},'Status'},{type,{1217,17},union,[{type,{1217,17},non_neg_integer,[]},{atom,{1217,37},abort},{type,{1217,47},string,[]}]}]]},{type,{1218,7},constraint,[{atom,{1218,7},is_subtype},[{var,{1218,7},'Options'},{type,{1218,18},list,[{var,{1218,19},'Option'}]}]]},{type,{1219,7},constraint,[{atom,{1219,7},is_subtype},[{var,{1219,7},'Option'},{type,{1219,17},tuple,[{atom,{1219,18},flush},{type,{1219,25},boolean,[]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66,48,49>>}},{{function,hd,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2196}],[<<104,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,104,101,97,100,32,111,102,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,104,100,40,91,49,44,50,44,51,44,52,44,53,93,41,46,10,49>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,105,115,116>>]},<<32,105,115,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,56,48>>,signature => [{attribute,{2196,2},spec,{{hd,1},[{type,{2196,9},bounded_fun,[{type,{2196,9},'fun',[{type,{2196,9},product,[{var,{2196,10},'List'}]},{type,{2196,19},term,[]}]},[{type,{2197,7},constraint,[{atom,{2197,7},is_subtype},[{var,{2197,7},'List'},{type,{2197,15},nonempty_list,[{type,{2197,16},term,[]}]}]]}]]}]}}]}},{{function,hibernate,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1230}],[<<104,105,98,101,114,110,97,116,101,47,51>>],#{<<101,110>> => [{p,[],[<<80,117,116,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,110,116,111,32,97,32,119,97,105,116,32,115,116,97,116,101,32,119,104,101,114,101,32,105,116,115,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,114,101,100,117,99,101,100,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,46,32,84,104,105,115,32,105,115,32,117,115,101,102,117,108,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,100,111,101,115,32,110,111,116,32,101,120,112,101,99,116,32,116,111,32,114,101,99,101,105,118,101,32,97,110,121,32,109,101,115,115,97,103,101,115,32,115,111,111,110,46>>]},{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,119,97,107,101,110,32,119,104,101,110,32,97,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,105,116,44,32,97,110,100,32,99,111,110,116,114,111,108,32,114,101,115,117,109,101,115,32,105,110,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,119,105,116,104,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<65,114,103,115>>]},<<32,119,105,116,104,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,32,101,109,112,116,105,101,100,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,116,104,101,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,32,119,104,101,110,32,116,104,97,116,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46,32,84,104,117,115,32>>,{code,[],[<<101,114,108,97,110,103,58,104,105,98,101,114,110,97,116,101,47,51>>]},<<32,110,101,118,101,114,32,114,101,116,117,114,110,115,32,116,111,32,105,116,115,32,99,97,108,108,101,114,46,32,84,104,101,32,114,101,115,117,109,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<32,109,117,115,116,32,98,101,32,101,120,112,111,114,116,101,100,32,40>>,{code,[],[<<65,114,105,116,121>>]},<<32,61,58,61,32>>,{code,[],[<<108,101,110,103,116,104,40,65,114,103,115,41>>]},<<41,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,97,110,121,32,109,101,115,115,97,103,101,32,105,110,32,105,116,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,44,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,119,97,107,101,110,101,100,32,105,109,109,101,100,105,97,116,101,108,121,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46>>]},{p,[],[<<73,110,32,109,111,114,101,32,116,101,99,104,110,105,99,97,108,32,116,101,114,109,115,44,32>>,{code,[],[<<101,114,108,97,110,103,58,104,105,98,101,114,110,97,116,101,47,51>>]},<<32,100,105,115,99,97,114,100,115,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,97,110,100,32,116,104,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,115,32,116,104,101,32,112,114,111,99,101,115,115,46,32,65,102,116,101,114,32,116,104,105,115,44,32,97,108,108,32,108,105,118,101,32,100,97,116,97,32,105,115,32,105,110,32,111,110,101,32,99,111,110,116,105,110,117,111,117,115,32,104,101,97,112,46,32,84,104,101,32,104,101,97,112,32,105,115,32,116,104,101,110,32,115,104,114,117,110,107,101,110,32,116,111,32,116,104,101,32,101,120,97,99,116,32,115,97,109,101,32,115,105,122,101,32,97,115,32,116,104,101,32,108,105,118,101,32,100,97,116,97,32,116,104,97,116,32,105,116,32,104,111,108,100,115,32,40,101,118,101,110,32,105,102,32,116,104,97,116,32,115,105,122,101,32,105,115,32,108,101,115,115,32,116,104,97,110,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,41,46>>]},{p,[],[<<73,102,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,108,105,118,101,32,100,97,116,97,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,108,101,115,115,32,116,104,97,110,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,44,32,116,104,101,32,102,105,114,115,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,99,99,117,114,114,105,110,103,32,97,102,116,101,114,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,119,97,107,101,110,101,100,32,101,110,115,117,114,101,115,32,116,104,97,116,32,116,104,101,32,104,101,97,112,32,115,105,122,101,32,105,115,32,99,104,97,110,103,101,100,32,116,111,32,97,32,115,105,122,101,32,110,111,116,32,115,109,97,108,108,101,114,32,116,104,97,110,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,101,109,112,116,121,105,110,103,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,32,109,101,97,110,115,32,116,104,97,116,32,97,110,121,32,115,117,114,114,111,117,110,100,105,110,103,32>>,{code,[],[<<99,97,116,99,104>>]},<<32,105,115,32,114,101,109,111,118,101,100,32,97,110,100,32,109,117,115,116,32,98,101,32,114,101,45,105,110,115,101,114,116,101,100,32,97,102,116,101,114,32,104,105,98,101,114,110,97,116,105,111,110,46,32,79,110,101,32,101,102,102,101,99,116,32,111,102,32,116,104,105,115,32,105,115,32,116,104,97,116,32,112,114,111,99,101,115,115,101,115,32,115,116,97,114,116,101,100,32,117,115,105,110,103,32>>,{code,[],[<<112,114,111,99,95,108,105,98>>]},<<32,40,97,108,115,111,32,105,110,100,105,114,101,99,116,108,121,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<103,101,110,95,115,101,114,118,101,114>>]},<<32,112,114,111,99,101,115,115,101,115,41,44,32,97,114,101,32,116,111,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,112,114,111,99,95,108,105,98,35,104,105,98,101,114,110,97,116,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,95,108,105,98,58,104,105,98,101,114,110,97,116,101,47,51>>]}]},<<32,105,110,115,116,101,97,100,44,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,104,97,110,100,108,101,114,32,99,111,110,116,105,110,117,101,115,32,116,111,32,119,111,114,107,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,119,97,107,101,115,32,117,112,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,50,57,57,53>>,signature => [{attribute,{1230,2},spec,{{erlang,hibernate,3},[{type,{1230,23},bounded_fun,[{type,{1230,23},'fun',[{type,{1230,23},product,[{var,{1230,24},'Module'},{var,{1230,32},'Function'},{var,{1230,42},'Args'}]},{type,{1230,51},no_return,[]}]},[{type,{1231,7},constraint,[{atom,{1231,7},is_subtype},[{var,{1231,7},'Module'},{type,{1231,17},module,[]}]]},{type,{1232,7},constraint,[{atom,{1232,7},is_subtype},[{var,{1232,7},'Function'},{type,{1232,19},atom,[]}]]},{type,{1233,7},constraint,[{atom,{1233,7},is_subtype},[{var,{1233,7},'Args'},{type,{1233,15},list,[{type,{1233,16},term,[]}]}]]}]]}]}}]}},{{function,insert_element,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1238}],[<<105,110,115,101,114,116,95,101,108,101,109,101,110,116,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,101,119,32,116,117,112,108,101,32,119,105,116,104,32,101,108,101,109,101,110,116,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,110,115,101,114,116,101,100,32,97,116,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,105,110,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<46,32,65,108,108,32,101,108,101,109,101,110,116,115,32,102,114,111,109,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,97,110,100,32,117,112,119,97,114,100,115,32,97,114,101,32,112,117,115,104,101,100,32,111,110,101,32,115,116,101,112,32,104,105,103,104,101,114,32,105,110,32,116,104,101,32,110,101,119,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,50>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,105,110,115,101,114,116,95,101,108,101,109,101,110,116,40,50,44,32,123,111,110,101,44,32,116,119,111,44,32,116,104,114,101,101,125,44,32,110,101,119,41,46,10,123,111,110,101,44,110,101,119,44,116,119,111,44,116,104,114,101,101,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,51,57>>,signature => [{attribute,{1238,2},spec,{{erlang,insert_element,3},[{type,{1238,28},bounded_fun,[{type,{1238,28},'fun',[{type,{1238,28},product,[{var,{1238,29},'Index'},{var,{1238,36},'Tuple1'},{var,{1238,44},'Term'}]},{var,{1238,53},'Tuple2'}]},[{type,{1239,7},constraint,[{atom,{1239,7},is_subtype},[{var,{1239,7},'Index'},{type,{1239,17},pos_integer,[]}]]},{type,{1240,7},constraint,[{atom,{1240,7},is_subtype},[{var,{1240,7},'Tuple1'},{type,{1240,17},tuple,any}]]},{type,{1241,7},constraint,[{atom,{1241,7},is_subtype},[{var,{1241,7},'Tuple2'},{type,{1241,17},tuple,any}]]},{type,{1242,7},constraint,[{atom,{1242,7},is_subtype},[{var,{1242,7},'Term'},{type,{1242,17},term,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,integer_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1247}],[<<105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,40,55,55,41,46,10,60,60,34,55,55,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,53,55>>,signature => [{attribute,{1247,2},spec,{{integer_to_binary,1},[{type,{1247,24},bounded_fun,[{type,{1247,24},'fun',[{type,{1247,24},product,[{var,{1247,25},'Integer'}]},{type,{1247,37},binary,[]}]},[{type,{1248,7},constraint,[{atom,{1248,7},is_subtype},[{var,{1248,7},'Integer'},{type,{1248,18},integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,integer_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3834}],[<<105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,98,105,110,97,114,121,40,49,48,50,51,44,32,49,54,41,46,10,60,60,34,51,70,70,34,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,54,57>>,signature => [{attribute,{3834,2},spec,{{integer_to_binary,2},[{type,{3834,24},bounded_fun,[{type,{3834,24},'fun',[{type,{3834,24},product,[{var,{3834,25},'Integer'},{var,{3834,34},'Base'}]},{type,{3834,43},binary,[]}]},[{type,{3835,7},constraint,[{atom,{3835,7},is_subtype},[{var,{3835,7},'Integer'},{type,{3835,18},integer,[]}]]},{type,{3836,7},constraint,[{atom,{3836,7},is_subtype},[{var,{3836,7},'Base'},{type,{3836,15},range,[{integer,{3836,15},2},{integer,{3836,18},36}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,integer_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1253}],[<<105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,40,55,55,41,46,10,34,55,55,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,56,50>>,signature => [{attribute,{1253,2},spec,{{integer_to_list,1},[{type,{1253,22},bounded_fun,[{type,{1253,22},'fun',[{type,{1253,22},product,[{var,{1253,23},'Integer'}]},{type,{1253,35},string,[]}]},[{type,{1254,7},constraint,[{atom,{1254,7},is_subtype},[{var,{1254,7},'Integer'},{type,{1254,18},integer,[]}]]}]]}]}}]}},{{function,integer_to_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3828}],[<<105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<73,110,116,101,103,101,114>>]},<<32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,110,116,101,103,101,114,95,116,111,95,108,105,115,116,40,49,48,50,51,44,32,49,54,41,46,10,34,51,70,70,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,48,57,52>>,signature => [{attribute,{3828,2},spec,{{integer_to_list,2},[{type,{3828,22},bounded_fun,[{type,{3828,22},'fun',[{type,{3828,22},product,[{var,{3828,23},'Integer'},{var,{3828,32},'Base'}]},{type,{3828,41},string,[]}]},[{type,{3829,7},constraint,[{atom,{3829,7},is_subtype},[{var,{3829,7},'Integer'},{type,{3829,18},integer,[]}]]},{type,{3830,7},constraint,[{atom,{3830,7},is_subtype},[{var,{3830,7},'Base'},{type,{3830,15},range,[{integer,{3830,15},2},{integer,{3830,18},36}]}]]}]]}]}}]}},{{function,iolist_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1259}],[<<105,111,108,105,115,116,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,44,32,116,104,97,116,32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,121,116,101,115,44,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,116,104,97,116,32,119,111,117,108,100,32,98,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,73,116,101,109,41>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,105,111,108,105,115,116,95,115,105,122,101,40,91,49,44,50,124,60,60,51,44,52,62,62,93,41,46,10,52>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,48,55>>,signature => [{attribute,{1259,2},spec,{{iolist_size,1},[{type,{1259,18},bounded_fun,[{type,{1259,18},'fun',[{type,{1259,18},product,[{var,{1259,19},'Item'}]},{type,{1259,28},non_neg_integer,[]}]},[{type,{1260,7},constraint,[{atom,{1260,7},is_subtype},[{var,{1260,7},'Item'},{type,{1260,15},union,[{type,{1260,15},iolist,[]},{type,{1260,26},binary,[]}]}]]}]]}]}}]}},{{function,iolist_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1265}],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,32,105,110,32>>,{code,[],[<<73,111,76,105,115,116,79,114,66,105,110,97,114,121>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,62,62,46,10,60,60,54,62,62,10,62,32,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,50,48>>,signature => [{attribute,{1265,2},spec,{{iolist_to_binary,1},[{type,{1265,23},bounded_fun,[{type,{1265,23},'fun',[{type,{1265,23},product,[{var,{1265,24},'IoListOrBinary'}]},{type,{1265,43},binary,[]}]},[{type,{1266,7},constraint,[{atom,{1266,7},is_subtype},[{var,{1266,7},'IoListOrBinary'},{type,{1266,25},union,[{type,{1266,25},iolist,[]},{type,{1266,36},binary,[]}]}]]}]]}]}}]}},{{function,iolist_to_iovec,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1271}],[<<105,111,108,105,115,116,95,116,111,95,105,111,118,101,99,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<105,111,118,101,99>>]},<<32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,32,105,110,32>>,{code,[],[<<73,111,76,105,115,116,79,114,66,105,110,97,114,121>>]},<<46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,117,115,101,102,117,108,32,119,104,101,110,32,121,111,117,32,119,97,110,116,32,116,111,32,102,108,97,116,116,101,110,32,97,110,32,105,111,108,105,115,116,32,98,117,116,32,121,111,117,32,100,111,32,110,111,116,32,110,101,101,100,32,97,32,115,105,110,103,108,101,32,98,105,110,97,114,121,46,32,84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,102,111,114,32,112,97,115,115,105,110,103,32,116,104,101,32,100,97,116,97,32,116,111,32,110,105,102,32,102,117,110,99,116,105,111,110,115,32,115,117,99,104,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,110,105,102,35,101,110,105,102,95,105,110,115,112,101,99,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,110,105,102,95,105,110,115,112,101,99,116,95,105,111,118,101,99>>]}]},<<32,111,114,32,100,111,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,109,101,115,115,97,103,101,32,112,97,115,115,105,110,103,46,32,84,104,101,32,97,100,118,97,110,116,97,103,101,32,111,102,32,117,115,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,111,118,101,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<32,105,115,32,116,104,97,116,32,105,116,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,116,111,32,99,111,112,121,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,98,105,110,97,114,121,104,97,110,100,108,105,110,103,35,114,101,102,99,95,98,105,110,97,114,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<111,102,102,45,104,101,97,112,32,98,105,110,97,114,105,101,115>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,62,62,46,10,60,60,54,62,62,10,37,37,32,73,102,32,121,111,117,32,112,97,115,115,32,115,109,97,108,108,32,98,105,110,97,114,105,101,115,32,97,110,100,32,105,110,116,101,103,101,114,115,32,105,116,32,119,111,114,107,115,32,97,115,32,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,10,62,32,101,114,108,97,110,103,58,105,111,108,105,115,116,95,116,111,95,105,111,118,101,99,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,91,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,62,62,93,10,37,37,32,73,102,32,121,111,117,32,112,97,115,115,32,108,97,114,103,101,114,32,98,105,110,97,114,105,101,115,44,32,116,104,101,121,32,97,114,101,32,115,112,108,105,116,32,97,110,100,32,114,101,116,117,114,110,101,100,32,105,110,32,97,32,102,111,114,109,10,37,37,32,111,112,116,105,109,105,122,101,100,32,102,111,114,32,99,97,108,108,105,110,103,32,116,104,101,32,67,32,102,117,110,99,116,105,111,110,32,119,114,105,116,101,118,46,10,62,32,101,114,108,97,110,103,58,105,111,108,105,115,116,95,116,111,95,105,111,118,101,99,40,91,60,60,49,62,62,44,60,60,50,58,56,48,57,54,62,62,44,60,60,51,58,56,48,57,54,62,62,93,41,46,10,91,60,60,49,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,10,32,32,32,48,44,46,46,46,62,62,44,10,32,60,60,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,10,32,32,32,46,46,46,62,62,44,10,32,60,60,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,46,46,46,62,62,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,51,56>>,signature => [{attribute,{1271,2},spec,{{erlang,iolist_to_iovec,1},[{type,{1271,29},bounded_fun,[{type,{1271,29},'fun',[{type,{1271,29},product,[{var,{1271,30},'IoListOrBinary'}]},{user_type,{1271,49},iovec,[]}]},[{type,{1272,7},constraint,[{atom,{1272,7},is_subtype},[{var,{1272,7},'IoListOrBinary'},{type,{1272,25},union,[{type,{1272,25},iolist,[]},{type,{1272,36},binary,[]}]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,49>>}},{{function,is_alive,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1277}],[<<105,115,95,97,108,105,118,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,97,108,105,118,101,32,40,116,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,110,111,100,101,32,99,97,110,32,98,101,32,112,97,114,116,32,111,102,32,97,32,100,105,115,116,114,105,98,117,116,101,100,32,115,121,115,116,101,109,41,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,65,32,110,111,100,101,32,105,115,32,97,108,105,118,101,32,105,102,32,105,116,32,105,115,32,115,116,97,114,116,101,100,32,119,105,116,104,58>>]},{ol,[],[{li,[],[{a,[{href,<<101,114,116,115,58,101,114,108,35,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<34,101,114,108,32,45,110,97,109,101,32,76,79,78,71,78,65,77,69,34>>]}]},<<32,111,114,44>>]},{li,[],[{a,[{href,<<101,114,116,115,58,101,114,108,35,115,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<34,101,114,108,32,45,115,110,97,109,101,32,83,72,79,82,84,78,65,77,69,34>>]}]},<<46>>]}]},{p,[],[<<65,32,110,111,100,101,32,99,97,110,32,97,108,115,111,32,98,101,32,97,108,105,118,101,32,105,102,32,105,116,32,104,97,115,32,103,111,116,32,97,32,110,97,109,101,32,102,114,111,109,32,97,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,110,101,116,95,107,101,114,110,101,108,35,115,116,97,114,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,101,116,95,107,101,114,110,101,108,58,115,116,97,114,116,47,49>>]}]},<<32,97,110,100,32,104,97,115,32,110,111,116,32,98,101,101,110,32,115,116,111,112,112,101,100,32,98,121,32,97,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,110,101,116,95,107,101,114,110,101,108,35,115,116,111,112,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,101,116,95,107,101,114,110,101,108,58,115,116,111,112,47,48>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,55,53>>,signature => [{attribute,{1277,2},spec,{{is_alive,0},[{type,{1277,15},'fun',[{type,{1277,15},product,[]},{type,{1277,21},boolean,[]}]}]}}]}},{{function,is_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2204}],[<<105,115,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32,97,116,111,109,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,49,57,52>>,signature => [{attribute,{2204,2},spec,{{is_atom,1},[{type,{2204,14},bounded_fun,[{type,{2204,14},'fun',[{type,{2204,14},product,[{var,{2204,15},'Term'}]},{type,{2204,24},boolean,[]}]},[{type,{2205,7},constraint,[{atom,{2205,7},is_subtype},[{var,{2205,7},'Term'},{type,{2205,15},term,[]}]]}]]}]}}]}},{{function,is_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2210}],[<<105,115,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,32,98,105,110,97,114,121,32,97,108,119,97,121,115,32,99,111,110,116,97,105,110,115,32,97,32,99,111,109,112,108,101,116,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,48,52>>,signature => [{attribute,{2210,2},spec,{{is_binary,1},[{type,{2210,16},bounded_fun,[{type,{2210,16},'fun',[{type,{2210,16},product,[{var,{2210,17},'Term'}]},{type,{2210,26},boolean,[]}]},[{type,{2211,7},constraint,[{atom,{2211,7},is_subtype},[{var,{2211,7},'Term'},{type,{2211,15},term,[]}]]}]]}]}}]}},{{function,is_bitstring,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2216}],[<<105,115,95,98,105,116,115,116,114,105,110,103,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,98,105,116,115,116,114,105,110,103,32,40,105,110,99,108,117,100,105,110,103,32,97,32,98,105,110,97,114,121,41,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,49,53>>,signature => [{attribute,{2216,2},spec,{{is_bitstring,1},[{type,{2216,19},bounded_fun,[{type,{2216,19},'fun',[{type,{2216,19},product,[{var,{2216,20},'Term'}]},{type,{2216,29},boolean,[]}]},[{type,{2217,7},constraint,[{atom,{2217,7},is_subtype},[{var,{2217,7},'Term'},{type,{2217,15},term,[]}]]}]]}]}}]}},{{function,is_boolean,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2222}],[<<105,115,95,98,111,111,108,101,97,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<116,114,117,101>>]},<<32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,40,116,104,97,116,32,105,115,44,32,97,32,98,111,111,108,101,97,110,41,46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,50,53>>,signature => [{attribute,{2222,2},spec,{{is_boolean,1},[{type,{2222,17},bounded_fun,[{type,{2222,17},'fun',[{type,{2222,17},product,[{var,{2222,18},'Term'}]},{type,{2222,27},boolean,[]}]},[{type,{2223,7},constraint,[{atom,{2223,7},is_subtype},[{var,{2223,7},'Term'},{type,{2223,15},term,[]}]]}]]}]}}]}},{{function,is_builtin,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1282}],[<<105,115,95,98,117,105,108,116,105,110,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,117,115,101,102,117,108,32,102,111,114,32,98,117,105,108,100,101,114,115,32,111,102,32,99,114,111,115,115,45,114,101,102,101,114,101,110,99,101,32,116,111,111,108,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<32,105,115,32,97,32,66,73,70,32,105,109,112,108,101,109,101,110,116,101,100,32,105,110,32,67,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,51,54>>,signature => [{attribute,{1282,2},spec,{{erlang,is_builtin,3},[{type,{1282,24},bounded_fun,[{type,{1282,24},'fun',[{type,{1282,24},product,[{var,{1282,25},'Module'},{var,{1282,33},'Function'},{var,{1282,43},'Arity'}]},{type,{1282,53},boolean,[]}]},[{type,{1283,7},constraint,[{atom,{1283,7},is_subtype},[{var,{1283,7},'Module'},{type,{1283,17},module,[]}]]},{type,{1284,7},constraint,[{atom,{1284,7},is_subtype},[{var,{1284,7},'Function'},{type,{1284,19},atom,[]}]]},{type,{1285,7},constraint,[{atom,{1285,7},is_subtype},[{var,{1285,7},'Arity'},{type,{1285,16},arity,[]}]]}]]}]}}]}},{{function,is_float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2228}],[<<105,115,95,102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,102,108,111,97,116,105,110,103,32,112,111,105,110,116,32,110,117,109,98,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,52,55>>,signature => [{attribute,{2228,2},spec,{{is_float,1},[{type,{2228,15},bounded_fun,[{type,{2228,15},'fun',[{type,{2228,15},product,[{var,{2228,16},'Term'}]},{type,{2228,25},boolean,[]}]},[{type,{2229,7},constraint,[{atom,{2229,7},is_subtype},[{var,{2229,7},'Term'},{type,{2229,15},term,[]}]]}]]}]}}]}},{{function,is_function,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2234}],[<<105,115,95,102,117,110,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,102,117,110,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,53,55>>,signature => [{attribute,{2234,2},spec,{{is_function,1},[{type,{2234,18},bounded_fun,[{type,{2234,18},'fun',[{type,{2234,18},product,[{var,{2234,19},'Term'}]},{type,{2234,28},boolean,[]}]},[{type,{2235,7},constraint,[{atom,{2235,7},is_subtype},[{var,{2235,7},'Term'},{type,{2235,15},term,[]}]]}]]}]}}]}},{{function,is_function,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2240}],[<<105,115,95,102,117,110,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,102,117,110,32,116,104,97,116,32,99,97,110,32,98,101,32,97,112,112,108,105,101,100,32,119,105,116,104,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,110,117,109,98,101,114,32,111,102,32,97,114,103,117,109,101,110,116,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,54,55>>,signature => [{attribute,{2240,2},spec,{{is_function,2},[{type,{2240,18},bounded_fun,[{type,{2240,18},'fun',[{type,{2240,18},product,[{var,{2240,19},'Term'},{var,{2240,25},'Arity'}]},{type,{2240,35},boolean,[]}]},[{type,{2241,7},constraint,[{atom,{2241,7},is_subtype},[{var,{2241,7},'Term'},{type,{2241,15},term,[]}]]},{type,{2242,7},constraint,[{atom,{2242,7},is_subtype},[{var,{2242,7},'Arity'},{type,{2242,16},arity,[]}]]}]]}]}}]}},{{function,is_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2247}],[<<105,115,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,55,57>>,signature => [{attribute,{2247,2},spec,{{is_integer,1},[{type,{2247,17},bounded_fun,[{type,{2247,17},'fun',[{type,{2247,17},product,[{var,{2247,18},'Term'}]},{type,{2247,27},boolean,[]}]},[{type,{2248,7},constraint,[{atom,{2248,7},is_subtype},[{var,{2248,7},'Term'},{type,{2248,15},term,[]}]]}]]}]}}]}},{{function,is_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2253}],[<<105,115,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,108,105,115,116,32,119,105,116,104,32,122,101,114,111,32,111,114,32,109,111,114,101,32,101,108,101,109,101,110,116,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,56,57>>,signature => [{attribute,{2253,2},spec,{{is_list,1},[{type,{2253,14},bounded_fun,[{type,{2253,14},'fun',[{type,{2253,14},product,[{var,{2253,15},'Term'}]},{type,{2253,24},boolean,[]}]},[{type,{2254,7},constraint,[{atom,{2254,7},is_subtype},[{var,{2254,7},'Term'},{type,{2254,15},term,[]}]]}]]}]}}]}},{{function,is_map,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2271}],[<<105,115,95,109,97,112,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,109,97,112,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,50,57,57>>,signature => [{attribute,{2271,2},spec,{{is_map,1},[{type,{2271,13},bounded_fun,[{type,{2271,13},'fun',[{type,{2271,13},product,[{var,{2271,14},'Term'}]},{type,{2271,23},boolean,[]}]},[{type,{2272,7},constraint,[{atom,{2272,7},is_subtype},[{var,{2272,7},'Term'},{type,{2272,15},term,[]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,is_map_key,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1290}],[<<105,115,95,109,97,112,95,107,101,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,109,97,112,32>>,{code,[],[<<77,97,112>>]},<<32,99,111,110,116,97,105,110,115,32>>,{code,[],[<<75,101,121>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,99,111,110,116,97,105,110,32,116,104,101,32>>,{code,[],[<<75,101,121>>]},<<46>>]},{p,[],[<<84,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<123,98,97,100,109,97,112,44,77,97,112,125>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32>>,{code,[],[<<77,97,112>>]},<<32,105,115,32,110,111,116,32,97,32,109,97,112,46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<62,32,77,97,112,32,61,32,35,123,34,52,50,34,32,61,62,32,118,97,108,117,101,125,46,10,35,123,34,52,50,34,32,61,62,32,118,97,108,117,101,125,10,62,32,105,115,95,109,97,112,95,107,101,121,40,34,52,50,34,44,77,97,112,41,46,10,116,114,117,101,10,62,32,105,115,95,109,97,112,95,107,101,121,40,118,97,108,117,101,44,77,97,112,41,46,10,102,97,108,115,101>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,48,57>>,signature => [{attribute,{1290,2},spec,{{is_map_key,2},[{type,{1290,17},bounded_fun,[{type,{1290,17},'fun',[{type,{1290,17},product,[{var,{1290,18},'Key'},{var,{1290,23},'Map'}]},{type,{1290,31},boolean,[]}]},[{type,{1291,5},constraint,[{atom,{1291,5},is_subtype},[{var,{1291,5},'Key'},{type,{1291,12},term,[]}]]},{type,{1292,5},constraint,[{atom,{1292,5},is_subtype},[{var,{1292,5},'Map'},{type,{1292,12},map,any}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,is_number,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2259}],[<<105,115,95,110,117,109,98,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,111,114,32,97,32,102,108,111,97,116,105,110,103,32,112,111,105,110,116,32,110,117,109,98,101,114,46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,51,48>>,signature => [{attribute,{2259,2},spec,{{is_number,1},[{type,{2259,16},bounded_fun,[{type,{2259,16},'fun',[{type,{2259,16},product,[{var,{2259,17},'Term'}]},{type,{2259,26},boolean,[]}]},[{type,{2260,7},constraint,[{atom,{2260,7},is_subtype},[{var,{2260,7},'Term'},{type,{2260,15},term,[]}]]}]]}]}}]}},{{function,is_pid,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2265}],[<<105,115,95,112,105,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,52,48>>,signature => [{attribute,{2265,2},spec,{{is_pid,1},[{type,{2265,13},bounded_fun,[{type,{2265,13},'fun',[{type,{2265,13},product,[{var,{2265,14},'Term'}]},{type,{2265,23},boolean,[]}]},[{type,{2266,7},constraint,[{atom,{2266,7},is_subtype},[{var,{2266,7},'Term'},{type,{2266,15},term,[]}]]}]]}]}}]}},{{function,is_port,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2277}],[<<105,115,95,112,111,114,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,53,48>>,signature => [{attribute,{2277,2},spec,{{is_port,1},[{type,{2277,14},bounded_fun,[{type,{2277,14},'fun',[{type,{2277,14},product,[{var,{2277,15},'Term'}]},{type,{2277,24},boolean,[]}]},[{type,{2278,7},constraint,[{atom,{2278,7},is_subtype},[{var,{2278,7},'Term'},{type,{2278,15},term,[]}]]}]]}]}}]}},{{function,is_process_alive,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1297}],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,47,49>>],#{<<101,110>> => [{p,[],[{code,[],[<<80,105,100>>]},<<32,109,117,115,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,115,116,115,32,97,110,100,32,105,115,32,97,108,105,118,101,44,32,116,104,97,116,32,105,115,44,32,105,115,32,110,111,116,32,101,120,105,116,105,110,103,32,97,110,100,32,104,97,115,32,110,111,116,32,101,120,105,116,101,100,46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<73,102,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,49>>]},<<32,99,97,108,108,115,32>>,{code,[],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,40,80,50,80,105,100,41>>]},<<32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,97,108,108,32,115,105,103,110,97,108,115,44,32,115,101,110,116,32,102,114,111,109,32>>,{code,[],[<<80,49>>]},<<32,116,111,32>>,{code,[],[<<80,50>>]},<<32,40>>,{code,[],[<<80,50>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,105,100,101,110,116,105,102,105,101,114,32>>,{code,[],[<<80,50,80,105,100>>]},<<41,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,44,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32>>,{code,[],[<<80,50>>]},<<32,98,101,102,111,114,101,32,116,104,101,32,97,108,105,118,101,110,101,115,115,32,111,102,32>>,{code,[],[<<80,50>>]},<<32,105,115,32,99,104,101,99,107,101,100,46,32,84,104,105,115,32,103,117,97,114,97,110,116,101,101,32,109,101,97,110,115,32,116,104,97,116,32,111,110,101,32,99,97,110,32,117,115,101,32>>,{code,[],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,47,49>>]},<<32,116,111,32,108,101,116,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,49>>]},<<32,119,97,105,116,32,117,110,116,105,108,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,50>>]},<<44,32,119,104,105,99,104,32,104,97,115,32,103,111,116,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,102,114,111,109,32,80,49,44,32,105,115,32,107,105,108,108,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<101,120,105,116,40,80,50,80,105,100,44,32,107,105,108,108,41,44,10,37,32,80,50,32,109,105,103,104,116,32,110,111,116,32,98,101,32,107,105,108,108,101,100,10,105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,40,80,50,80,105,100,41,44,10,37,32,80,50,32,105,115,32,110,111,116,32,97,108,105,118,101,32,40,116,104,101,32,99,97,108,108,32,97,98,111,118,101,32,97,108,119,97,121,115,32,114,101,116,117,114,110,32,102,97,108,115,101,41>>]}]},{p,[],[<<83,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,103,110,97,108,115>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,101,120,105,116,47,50>>]},<<32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,105,103,110,97,108,115,32,97,110,100,32,101,120,105,116,32,115,105,103,110,97,108,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,54,48>>,signature => [{attribute,{1297,2},spec,{{is_process_alive,1},[{type,{1297,23},bounded_fun,[{type,{1297,23},'fun',[{type,{1297,23},product,[{var,{1297,24},'Pid'}]},{type,{1297,32},boolean,[]}]},[{type,{1298,7},constraint,[{atom,{1298,7},is_subtype},[{var,{1298,7},'Pid'},{type,{1298,14},pid,[]}]]}]]}]}}]}},{{function,is_record,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2283}],[<<105,115,95,114,101,99,111,114,100,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,32,97,110,100,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,114,109,97,108,108,121,32,116,104,101,32,99,111,109,112,105,108,101,114,32,116,114,101,97,116,115,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<105,115,95,114,101,99,111,114,100,47,50>>]},<<32,101,115,112,101,99,105,97,108,108,121,46,32,73,116,32,101,109,105,116,115,32,99,111,100,101,32,116,111,32,118,101,114,105,102,121,32,116,104,97,116,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,44,32,116,104,97,116,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<44,32,97,110,100,32,116,104,97,116,32,116,104,101,32,115,105,122,101,32,105,115,32,99,111,114,114,101,99,116,46,32,72,111,119,101,118,101,114,44,32,105,102,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,105,115,32,110,111,116,32,97,32,108,105,116,101,114,97,108,32,97,116,111,109,44,32,116,104,101,32,66,73,70,32>>,{code,[],[<<105,115,95,114,101,99,111,114,100,47,50>>]},<<32,105,115,32,99,97,108,108,101,100,32,105,110,115,116,101,97,100,32,97,110,100,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,116,117,112,108,101,32,105,115,32,110,111,116,32,118,101,114,105,102,105,101,100,46>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,44,32,105,102,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,105,115,32,97,32,108,105,116,101,114,97,108,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,51,57,50>>,signature => [{attribute,{2283,2},spec,{{is_record,2},[{type,{2283,16},bounded_fun,[{type,{2283,16},'fun',[{type,{2283,16},product,[{var,{2283,17},'Term'},{var,{2283,22},'RecordTag'}]},{type,{2283,36},boolean,[]}]},[{type,{2284,7},constraint,[{atom,{2284,7},is_subtype},[{var,{2284,7},'Term'},{type,{2284,15},term,[]}]]},{type,{2285,7},constraint,[{atom,{2285,7},is_subtype},[{var,{2285,7},'RecordTag'},{type,{2285,20},atom,[]}]]}]]}]}}]}},{{function,is_record,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2290}],[<<105,115,95,114,101,99,111,114,100,47,51>>],#{<<101,110>> => [{p,[],[{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,109,117,115,116,32,98,101,32,97,110,32,97,116,111,109,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,44,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<44,32,97,110,100,32,105,116,115,32,115,105,122,101,32,105,115,32>>,{code,[],[<<83,105,122,101>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,32,105,102,32>>,{code,[],[<<82,101,99,111,114,100,84,97,103>>]},<<32,105,115,32,97,32,108,105,116,101,114,97,108,32,97,116,111,109,32,97,110,100,32>>,{code,[],[<<83,105,122,101>>]},<<32,105,115,32,97,32,108,105,116,101,114,97,108,32,105,110,116,101,103,101,114,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,100,111,99,117,109,101,110,116,101,100,32,102,111,114,32,99,111,109,112,108,101,116,101,110,101,115,115,46,32,85,115,117,97,108,108,121,32>>,{code,[],[<<105,115,95,114,101,99,111,114,100,47,50>>]},<<32,105,115,32,116,111,32,98,101,32,117,115,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,49,51>>,signature => [{attribute,{2290,2},spec,{{is_record,3},[{type,{2290,16},bounded_fun,[{type,{2290,16},'fun',[{type,{2290,16},product,[{var,{2290,17},'Term'},{var,{2290,22},'RecordTag'},{var,{2290,32},'Size'}]},{type,{2290,41},boolean,[]}]},[{type,{2291,7},constraint,[{atom,{2291,7},is_subtype},[{var,{2291,7},'Term'},{type,{2291,15},term,[]}]]},{type,{2292,7},constraint,[{atom,{2292,7},is_subtype},[{var,{2292,7},'RecordTag'},{type,{2292,20},atom,[]}]]},{type,{2293,7},constraint,[{atom,{2293,7},is_subtype},[{var,{2293,7},'Size'},{type,{2293,15},non_neg_integer,[]}]]}]]}]}}]}},{{function,is_reference,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2298}],[<<105,115,95,114,101,102,101,114,101,110,99,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,51,50>>,signature => [{attribute,{2298,2},spec,{{is_reference,1},[{type,{2298,19},bounded_fun,[{type,{2298,19},'fun',[{type,{2298,19},product,[{var,{2298,20},'Term'}]},{type,{2298,29},boolean,[]}]},[{type,{2299,7},constraint,[{atom,{2299,7},is_subtype},[{var,{2299,7},'Term'},{type,{2299,15},term,[]}]]}]]}]}}]}},{{function,is_tuple,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2304}],[<<105,115,95,116,117,112,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32,116,117,112,108,101,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,52,50>>,signature => [{attribute,{2304,2},spec,{{is_tuple,1},[{type,{2304,15},bounded_fun,[{type,{2304,15},'fun',[{type,{2304,15},product,[{var,{2304,16},'Term'}]},{type,{2304,25},boolean,[]}]},[{type,{2305,7},constraint,[{atom,{2305,7},is_subtype},[{var,{2305,7},'Term'},{type,{2305,15},term,[]}]]}]]}]}}]}},{{function,length,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1304}],[<<108,101,110,103,116,104,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,101,110,103,116,104,40,91,49,44,50,44,51,44,52,44,53,44,54,44,55,44,56,44,57,93,41,46,10,57>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,53,50>>,signature => [{attribute,{1304,2},spec,{{length,1},[{type,{1304,13},bounded_fun,[{type,{1304,13},'fun',[{type,{1304,13},product,[{var,{1304,14},'List'}]},{type,{1304,23},non_neg_integer,[]}]},[{type,{1305,7},constraint,[{atom,{1305,7},is_subtype},[{var,{1305,7},'List'},{type,{1305,15},list,[{type,{1305,16},term,[]}]}]]}]]}]}}]}},{{function,link,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1310}],[<<108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,117,112,32,97,110,100,32,97,99,116,105,118,97,116,101,115,32,97,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,111,114,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<46,32,87,101,32,119,105,108,108,32,102,114,111,109,32,104,101,114,101,32,111,110,32,99,97,108,108,32,116,104,101,32,105,100,101,110,116,105,102,105,101,100,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,108,105,110,107,101,101,46,32,73,102,32,116,104,101,32,108,105,110,107,101,101,32,105,115,32,97,32,112,111,114,116,44,32,105,116,32,109,117,115,116,32,114,101,115,105,100,101,32,111,110,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,97,115,32,116,104,101,32,99,97,108,108,101,114,46>>]},{p,[],[<<73,102,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,116,105,99,105,112,97,110,116,115,32,111,102,32,97,32,108,105,110,107,32,116,101,114,109,105,110,97,116,101,115,44,32,105,116,32,119,105,108,108,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,101,110,100,105,110,103,95,101,120,105,116,95,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,101,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108>>]},<<32,116,111,32,116,104,101,32,111,116,104,101,114,32,112,97,114,116,105,99,105,112,97,110,116,46,32,84,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,108,108,32,99,111,110,116,97,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,108,105,110,107,95,101,120,105,116,95,115,105,103,110,97,108,95,114,101,97,115,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,120,105,116,32,114,101,97,115,111,110>>]},<<32,111,102,32,116,104,101,32,116,101,114,109,105,110,97,116,101,100,32,112,97,114,116,105,99,105,112,97,110,116,46,32,79,116,104,101,114,32,99,97,115,101,115,32,119,104,101,110,32,101,120,105,116,32,115,105,103,110,97,108,115,32,97,114,101,32,116,114,105,103,103,101,114,101,100,32,100,117,101,32,116,111,32,97,32,108,105,110,107,32,97,114,101,32,119,104,101,110,32,110,111,32,108,105,110,107,101,101,32,101,120,105,115,116,32,40>>,{code,[],[<<110,111,112,114,111,99>>]},<<32,101,120,105,116,32,114,101,97,115,111,110,41,32,97,110,100,32,119,104,101,110,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,98,101,116,119,101,101,110,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,32,111,110,32,100,105,102,102,101,114,101,110,116,32,110,111,100,101,115,32,105,115,32,108,111,115,116,32,111,114,32,99,97,110,110,111,116,32,98,101,32,101,115,116,97,98,108,105,115,104,101,100,32,40>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,101,120,105,116,32,114,101,97,115,111,110,41,46>>]},{p,[],[<<65,110,32,101,120,105,115,116,105,110,103,32,108,105,110,107,32,99,97,110,32,98,101,32,114,101,109,111,118,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,108,105,110,107,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,108,105,110,107,47,49>>]}]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,108,105,110,107,115,32,97,110,100,32,101,120,105,116,32,115,105,103,110,97,108,115,32,100,117,101,32,116,111,32,108,105,110,107,115,44,32,115,101,101,32,116,104,101,32>>,{i,[],[<<80,114,111,99,101,115,115,101,115>>]},<<32,99,104,97,112,116,101,114,32,105,110,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<58>>]},{ul,[],[{li,[],[{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,108,105,110,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<76,105,110,107,115>>]}]},{li,[],[{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,101,110,100,105,110,103,95,101,120,105,116,95,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<83,101,110,100,105,110,103,32,69,120,105,116,32,83,105,103,110,97,108,115>>]}]},{li,[],[{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,114,101,99,101,105,118,105,110,103,95,101,120,105,116,95,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,99,101,105,118,105,110,103,32,69,120,105,116,32,83,105,103,110,97,108,115>>]}]}]},{p,[],[<<70,111,114,32,104,105,115,116,111,114,105,99,97,108,32,114,101,97,115,111,110,115,44,32>>,{code,[],[<<108,105,110,107,47,49>>]},<<32,104,97,115,32,97,32,115,116,114,97,110,103,101,32,115,101,109,105,45,115,121,110,99,104,114,111,110,111,117,115,32,98,101,104,97,118,105,111,114,32,119,104,101,110,32,105,116,32,105,115,32,34,99,104,101,97,112,34,32,116,111,32,99,104,101,99,107,32,105,102,32,116,104,101,32,108,105,110,107,101,101,32,101,120,105,115,116,115,32,111,114,32,110,111,116,44,32,97,110,100,32,116,104,101,32,99,97,108,108,101,114,32,100,111,101,115,32,110,111,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,116,114,97,112,95,101,120,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,114,97,112,32,101,120,105,116,115>>]},<<46,32,73,102,32,116,104,101,32,97,98,111,118,101,32,105,115,32,116,114,117,101,32,97,110,100,32,116,104,101,32,108,105,110,107,101,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32>>,{code,[],[<<108,105,110,107,47,49>>]},<<32,119,105,108,108,32,114,97,105,115,101,32,97,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<32,101,114,114,111,114,32>>,{em,[],[<<101,120,99,101,112,116,105,111,110>>]},<<46,32,84,104,101,32,101,120,112,101,99,116,101,100,32,98,101,104,97,118,105,111,114,32,119,111,117,108,100,32,105,110,115,116,101,97,100,32,104,97,118,101,32,98,101,101,110,32,116,104,97,116,32>>,{code,[],[<<108,105,110,107,47,49>>]},<<32,114,101,116,117,114,110,101,100,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,97,110,100,32,116,104,101,32,99,97,108,108,101,114,32,108,97,116,101,114,32,119,97,115,32,115,101,110,116,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<32,101,120,105,116,32,114,101,97,115,111,110,44,32,98,117,116,32,116,104,105,115,32,105,115,32,117,110,102,111,114,116,117,110,97,116,101,108,121,32,110,111,116,32,116,104,101,32,99,97,115,101,46,32,84,104,101,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115,35,101,120,99,101,112,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,120,99,101,112,116,105,111,110>>]},<<32,105,115,32,110,111,116,32,116,111,32,98,101,32,99,111,110,102,117,115,101,100,32,119,105,116,104,32,97,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,101,110,100,105,110,103,95,101,120,105,116,95,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,120,105,116,32,115,105,103,110,97,108>>]},<<32,119,105,116,104,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<46,32,67,117,114,114,101,110,116,108,121,32,105,116,32,105,115,32,34,99,104,101,97,112,34,32,116,111,32,99,104,101,99,107,32,105,102,32,116,104,101,32,108,105,110,107,101,101,32,101,120,105,115,116,115,32,119,104,101,110,32,105,116,32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,114,101,115,105,100,101,32,111,110,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,97,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<84,104,101,32,108,105,110,107,32,115,101,116,117,112,32,97,110,100,32,97,99,116,105,118,97,116,105,111,110,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,73,102,32,116,104,101,32,108,105,110,107,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,44,32,111,114,32,105,102,32,116,104,101,32,99,97,108,108,101,114,32,97,116,116,101,109,112,116,115,32,116,111,32,99,114,101,97,116,101,32,97,32,108,105,110,107,32,116,111,32,105,116,115,101,108,102,44,32,110,111,116,104,105,110,103,32,105,115,32,100,111,110,101,46,32,65,32,100,101,116,97,105,108,101,100,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,105,115,116,95,112,114,111,116,111,99,111,108,35,108,105,110,107,95,112,114,111,116,111,99,111,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<108,105,110,107,32,112,114,111,116,111,99,111,108>>]},<<32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{i,[],[<<68,105,115,116,114,105,98,117,116,105,111,110,32,80,114,111,116,111,99,111,108>>]},<<32,99,104,97,112,116,101,114,32,111,102,32,116,104,101,32>>,{i,[],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58>>]},{ul,[],[{li,[],[{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,105,100,101,110,116,105,102,121,32,97,32,112,114,111,99,101,115,115,32,111,114,32,97,32,110,111,100,101,32,108,111,99,97,108,32,112,111,114,116,46>>]},{li,[],[{code,[],[<<110,111,112,114,111,99>>]},<<32,108,105,110,107,101,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,97,110,100,32,105,116,32,105,115,32,34,99,104,101,97,112,34,32,116,111,32,99,104,101,99,107,32,105,102,32,105,116,32,101,120,105,115,116,115,32,97,115,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,52,54,52>>,signature => [{attribute,{1310,2},spec,{{link,1},[{type,{1310,11},bounded_fun,[{type,{1310,11},'fun',[{type,{1310,11},product,[{var,{1310,12},'PidOrPort'}]},{atom,{1310,26},true}]},[{type,{1311,7},constraint,[{atom,{1311,7},is_subtype},[{var,{1311,7},'PidOrPort'},{type,{1311,20},union,[{type,{1311,20},pid,[]},{type,{1311,28},port,[]}]}]]}]]}]}}]}},{{function,list_to_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1316}],[<<108,105,115,116,95,116,111,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,50,48,44,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,109,97,121,32,99,111,110,116,97,105,110,32,97,110,121,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,46,32,69,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,97,108,108,111,119,101,100,32,111,110,108,121,32,73,83,79,45,108,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,116,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,100,105,100,32,110,111,116,32,97,108,108,111,119,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,97,98,111,118,101,32,50,53,53,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,97,110,32,97,116,111,109,32,110,97,109,101,32,105,115,32,108,105,109,105,116,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,99,111,110,102,105,103,117,114,97,98,108,101,32,108,105,109,105,116,32,111,110,32,104,111,119,32,109,97,110,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,101,120,105,115,116,32,97,110,100,32,97,116,111,109,115,32,97,114,101,32,110,111,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,99,111,110,115,105,100,101,114,32,105,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>]}]},<<32,105,115,32,97,32,98,101,116,116,101,114,32,111,112,116,105,111,110,32,116,104,97,110,32>>,{code,[],[<<108,105,115,116,95,116,111,95,97,116,111,109,47,49>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,108,105,109,105,116,115,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,102,102,105,99,105,101,110,99,121,32,103,117,105,100,101,32,40,115,101,99,116,105,111,110,32,65,100,118,97,110,99,101,100,41>>]},<<46>>]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,97,116,111,109,40,34,69,114,108,97,110,103,34,41,46,10,39,69,114,108,97,110,103,39>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,52,56>>,signature => [{attribute,{1316,2},spec,{{list_to_atom,1},[{type,{1316,19},bounded_fun,[{type,{1316,19},'fun',[{type,{1316,19},product,[{var,{1316,20},'String'}]},{type,{1316,31},atom,[]}]},[{type,{1317,7},constraint,[{atom,{1317,7},is_subtype},[{var,{1317,7},'String'},{type,{1317,17},string,[]}]]}]]}]}}]}},{{function,list_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1322}],[<<108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,32,105,110,32>>,{code,[],[<<73,111,76,105,115,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,62,62,46,10,60,60,54,62,62,10,62,32,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,56,49>>,signature => [{attribute,{1322,2},spec,{{list_to_binary,1},[{type,{1322,21},bounded_fun,[{type,{1322,21},'fun',[{type,{1322,21},product,[{var,{1322,22},'IoList'}]},{type,{1322,33},binary,[]}]},[{type,{1323,7},constraint,[{atom,{1323,7},is_subtype},[{var,{1323,7},'IoList'},{type,{1323,17},iolist,[]}]]}]]}]}}]}},{{function,list_to_bitstring,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1328}],[<<108,105,115,116,95,116,111,95,98,105,116,115,116,114,105,110,103,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<98,105,116,115,116,114,105,110,103,95,108,105,115,116>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,116,115,116,114,105,110,103,32,116,104,97,116,32,105,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,116,115,116,114,105,110,103,115,32,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103,76,105,115,116>>]},<<46,32,40,84,104,101,32,108,97,115,116,32,116,97,105,108,32,105,110,32>>,{code,[],[<<66,105,116,115,116,114,105,110,103,76,105,115,116>>]},<<32,105,115,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,97,32,98,105,116,115,116,114,105,110,103,46,41,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,105,110,49,32,61,32,60,60,49,44,50,44,51,62,62,46,10,60,60,49,44,50,44,51,62,62,10,62,32,66,105,110,50,32,61,32,60,60,52,44,53,62,62,46,10,60,60,52,44,53,62,62,10,62,32,66,105,110,51,32,61,32,60,60,54,44,55,58,52,62,62,46,10,60,60,54,44,55,58,52,62,62,10,62,32,108,105,115,116,95,116,111,95,98,105,116,115,116,114,105,110,103,40,91,66,105,110,49,44,49,44,91,50,44,51,44,66,105,110,50,93,44,52,124,66,105,110,51,93,41,46,10,60,60,49,44,50,44,51,44,49,44,50,44,51,44,52,44,53,44,52,44,54,44,55,58,52,62,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,53,57,57>>,signature => [{attribute,{1328,2},spec,{{list_to_bitstring,1},[{type,{1328,24},bounded_fun,[{type,{1328,24},'fun',[{type,{1328,24},product,[{var,{1328,25},'BitstringList'}]},{type,{1328,43},bitstring,[]}]},[{type,{1329,7},constraint,[{atom,{1329,7},is_subtype},[{var,{1329,7},'BitstringList'},{user_type,{1329,24},bitstring_list,[]}]]}]]}]}}]}},{{function,list_to_existing_atom,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1334}],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,98,117,116,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,32,115,117,99,104,32,97,116,111,109,46,32,65,110,32,97,116,111,109,32,101,120,105,115,116,115,32,105,102,32,105,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,32,98,121,32,116,104,101,32,114,117,110,45,116,105,109,101,32,115,121,115,116,101,109,32,98,121,32,101,105,116,104,101,114,32,108,111,97,100,105,110,103,32,99,111,100,101,32,111,114,32,99,114,101,97,116,105,110,103,32,97,32,116,101,114,109,32,105,110,32,119,104,105,99,104,32,116,104,101,32,97,116,111,109,32,105,115,32,112,97,114,116,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,114,101,32,100,111,101,115,32,110,111,116,32,97,108,114,101,97,100,121,32,101,120,105,115,116,32,97,110,32,97,116,111,109,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,99,111,109,112,105,108,101,114,32,109,97,121,32,111,112,116,105,109,105,122,101,32,97,119,97,121,32,97,116,111,109,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,111,109,112,105,108,101,114,32,119,105,108,108,32,114,101,119,114,105,116,101,32>>,{code,[],[<<97,116,111,109,95,116,111,95,108,105,115,116,40,115,111,109,101,95,97,116,111,109,41>>]},<<32,116,111,32>>,{code,[],[<<34,115,111,109,101,95,97,116,111,109,34>>]},<<46,32,73,102,32,116,104,97,116,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,104,101,32,111,110,108,121,32,109,101,110,116,105,111,110,32,111,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,111,109,101,95,97,116,111,109>>]},<<32,105,110,32,116,104,101,32,99,111,110,116,97,105,110,105,110,103,32,109,111,100,117,108,101,44,32,116,104,101,32,97,116,111,109,32,119,105,108,108,32,110,111,116,32,98,101,32,99,114,101,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32,108,111,97,100,101,100,44,32,97,110,100,32,97,32,115,117,98,115,101,113,117,101,110,116,32,99,97,108,108,32,116,111,32>>,{code,[],[<<108,105,115,116,95,116,111,95,101,120,105,115,116,105,110,103,95,97,116,111,109,40,34,115,111,109,101,95,97,116,111,109,34,41>>]},<<32,119,105,108,108,32,102,97,105,108,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,50,48>>,signature => [{attribute,{1334,2},spec,{{list_to_existing_atom,1},[{type,{1334,28},bounded_fun,[{type,{1334,28},'fun',[{type,{1334,28},product,[{var,{1334,29},'String'}]},{type,{1334,40},atom,[]}]},[{type,{1335,7},constraint,[{atom,{1335,7},is_subtype},[{var,{1335,7},'String'},{type,{1335,17},string,[]}]]}]]}]}}]}},{{function,list_to_float,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1340}],[<<108,105,115,116,95,116,111,95,102,108,111,97,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,102,108,111,97,116,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,102,108,111,97,116,40,34,50,46,50,48,49,55,55,54,52,101,43,48,34,41,46,10,50,46,50,48,49,55,55,54,52>>]}]},{p,[],[<<84,104,101,32,102,108,111,97,116,32,115,116,114,105,110,103,32,102,111,114,109,97,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,102,111,114,109,97,116,32,102,111,114,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,102,108,111,97,116,32,108,105,116,101,114,97,108,115>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,97,116,32,117,110,100,101,114,115,99,111,114,101,115,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,102,108,111,97,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,52,51>>,signature => [{attribute,{1340,2},spec,{{list_to_float,1},[{type,{1340,20},bounded_fun,[{type,{1340,20},'fun',[{type,{1340,20},product,[{var,{1340,21},'String'}]},{type,{1340,32},float,[]}]},[{type,{1341,7},constraint,[{atom,{1341,7},is_subtype},[{var,{1341,7},'String'},{type,{1341,17},string,[]}]]}]]}]}}]}},{{function,list_to_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1346}],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,49,50,51,34,41,46,10,49,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,45,49,50,51,34,41,46,10,45,49,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,43,49,50,51,50,51,52,57,56,50,51,48,52,57,56,50,51,48,57,52,56,50,48,57,51,56,51,51,50,51,52,50,51,52,34,41,46,10,49,50,51,50,51,52,57,56,50,51,48,52,57,56,50,51,48,57,52,56,50,48,57,51,56,51,51,50,51,52,50,51,52>>]}]},{p,[],[{code,[],[<<83,116,114,105,110,103>>]},<<32,109,117,115,116,32,99,111,110,116,97,105,110,32,97,116,32,108,101,97,115,116,32,111,110,101,32,100,105,103,105,116,32,99,104,97,114,97,99,116,101,114,32,97,110,100,32,99,97,110,32,104,97,118,101,32,97,110,32,111,112,116,105,111,110,97,108,32,112,114,101,102,105,120,32,99,111,110,115,105,115,116,105,110,103,32,111,102,32,97,32,115,105,110,103,108,101,32,34>>,{code,[],[<<43>>]},<<34,32,111,114,32,34>>,{code,[],[<<45>>]},<<34,32,99,104,97,114,97,99,116,101,114,32,40,116,104,97,116,32,105,115,44,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,109,117,115,116,32,109,97,116,99,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32>>,{code,[],[<<34,94,91,43,45,93,63,91,48,45,57,93,43,36,34>>]},<<41,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,54,49>>,signature => [{attribute,{1346,2},spec,{{list_to_integer,1},[{type,{1346,22},bounded_fun,[{type,{1346,22},'fun',[{type,{1346,22},product,[{var,{1346,23},'String'}]},{type,{1346,34},integer,[]}]},[{type,{1347,7},constraint,[{atom,{1347,7},is_subtype},[{var,{1347,7},'String'},{type,{1347,17},string,[]}]]}]]}]}}]}},{{function,list_to_integer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1352}],[<<108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,110,32,98,97,115,101,32>>,{code,[],[<<66,97,115,101>>]},<<32,105,115,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,51,70,70,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,43,51,70,70,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,51,102,102,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,51,102,70,34,44,32,49,54,41,46,10,49,48,50,51>>]}]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,105,110,116,101,103,101,114,40,34,45,51,70,70,34,44,32,49,54,41,46,10,45,49,48,50,51>>]}]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32>>,{code,[],[<<66,97,115,101>>]},<<32,105,115,32,49,54,44,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,109,117,115,116,32,109,97,116,99,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32>>,{code,[],[<<34,94,91,43,45,93,63,40,91,48,45,57,93,124,91,65,45,70,93,124,91,97,45,102,93,41,43,36,34>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,54,56,54>>,signature => [{attribute,{1352,2},spec,{{list_to_integer,2},[{type,{1352,22},bounded_fun,[{type,{1352,22},'fun',[{type,{1352,22},product,[{var,{1352,23},'String'},{var,{1352,31},'Base'}]},{type,{1352,40},integer,[]}]},[{type,{1353,7},constraint,[{atom,{1353,7},is_subtype},[{var,{1353,7},'String'},{type,{1353,17},string,[]}]]},{type,{1354,7},constraint,[{atom,{1354,7},is_subtype},[{var,{1354,7},'Base'},{type,{1354,15},range,[{integer,{1354,15},2},{integer,{1354,18},36}]}]]}]]}]}}]}},{{function,list_to_pid,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1359}],[<<108,105,115,116,95,116,111,95,112,105,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,97,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,112,105,100,40,34,60,48,46,52,46,49,62,34,41,46,10,60,48,46,52,46,49,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,55,49,54>>,signature => [{attribute,{1359,2},spec,{{list_to_pid,1},[{type,{1359,18},bounded_fun,[{type,{1359,18},'fun',[{type,{1359,18},product,[{var,{1359,19},'String'}]},{type,{1359,30},pid,[]}]},[{type,{1360,7},constraint,[{atom,{1360,7},is_subtype},[{var,{1360,7},'String'},{type,{1360,17},string,[]}]]}]]}]}}]}},{{function,list_to_port,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1365}],[<<108,105,115,116,95,116,111,95,112,111,114,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,97,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,112,111,114,116,40,34,35,80,111,114,116,60,48,46,52,62,34,41,46,10,35,80,111,114,116,60,48,46,52,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,55,51,52>>,signature => [{attribute,{1365,2},spec,{{list_to_port,1},[{type,{1365,19},bounded_fun,[{type,{1365,19},'fun',[{type,{1365,19},product,[{var,{1365,20},'String'}]},{type,{1365,31},port,[]}]},[{type,{1366,7},constraint,[{atom,{1366,7},is_subtype},[{var,{1366,7},'String'},{type,{1366,17},string,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,list_to_ref,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1371}],[<<108,105,115,116,95,116,111,95,114,101,102,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,114,101,102,101,114,101,110,99,101,32,119,104,111,115,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,97,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,114,101,102,40,34,35,82,101,102,60,48,46,52,49,57,50,53,51,55,54,55,56,46,52,48,55,51,49,57,51,52,55,53,46,55,49,49,56,49,62,34,41,46,10,35,82,101,102,60,48,46,52,49,57,50,53,51,55,54,55,56,46,52,48,55,51,49,57,51,52,55,53,46,55,49,49,56,49,62>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<83,116,114,105,110,103>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,98,97,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,97,32,114,101,102,101,114,101,110,99,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,55,53,50>>,signature => [{attribute,{1371,2},spec,{{list_to_ref,1},[{type,{1371,18},bounded_fun,[{type,{1371,18},'fun',[{type,{1371,18},product,[{var,{1371,19},'String'}]},{type,{1371,30},reference,[]}]},[{type,{1372,7},constraint,[{atom,{1372,7},is_subtype},[{var,{1372,7},'String'},{type,{1372,17},string,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,list_to_tuple,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1377}],[<<108,105,115,116,95,116,111,95,116,117,112,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101>>]},{pre,[],[{code,[],[<<62,32,108,105,115,116,95,116,111,95,116,117,112,108,101,40,91,115,104,97,114,101,44,32,91,39,69,114,105,99,115,115,111,110,95,66,39,44,32,49,54,51,93,93,41,46,10,123,115,104,97,114,101,44,32,91,39,69,114,105,99,115,115,111,110,95,66,39,44,32,49,54,51,93,125>>]}]},{p,[],[{code,[],[<<76,105,115,116>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,69,114,108,97,110,103,32,116,101,114,109,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,55,55,48>>,signature => [{attribute,{1377,2},spec,{{list_to_tuple,1},[{type,{1377,20},bounded_fun,[{type,{1377,20},'fun',[{type,{1377,20},product,[{var,{1377,21},'List'}]},{type,{1377,30},tuple,any}]},[{type,{1378,7},constraint,[{atom,{1378,7},is_subtype},[{var,{1378,7},'List'},{type,{1378,15},list,[{type,{1378,16},term,[]}]}]]}]]}]}}]}},{{function,load_module,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2309}],[<<108,111,97,100,95,109,111,100,117,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,111,98,106,101,99,116,32,99,111,100,101,32,102,111,114,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<44,32,116,104,105,115,32,66,73,70,32,108,111,97,100,115,32,116,104,97,116,32,111,98,106,101,99,116,32,99,111,100,101,46,32,73,102,32,116,104,101,32,99,111,100,101,32,102,111,114,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,44,32,97,108,108,32,101,120,112,111,114,116,32,114,101,102,101,114,101,110,99,101,115,32,97,114,101,32,114,101,112,108,97,99,101,100,32,115,111,32,116,104,101,121,32,112,111,105,110,116,32,116,111,32,116,104,101,32,110,101,119,108,121,32,108,111,97,100,101,100,32,99,111,100,101,46,32,84,104,101,32,112,114,101,118,105,111,117,115,108,121,32,108,111,97,100,101,100,32,99,111,100,101,32,105,115,32,107,101,112,116,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,97,115,32,111,108,100,32,99,111,100,101,44,32,97,115,32,116,104,101,114,101,32,99,97,110,32,115,116,105,108,108,32,98,101,32,112,114,111,99,101,115,115,101,115,32,101,120,101,99,117,116,105,110,103,32,116,104,97,116,32,99,111,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,101,105,116,104,101,114,32>>,{code,[],[<<123,109,111,100,117,108,101,44,32,77,111,100,117,108,101,125>>]},<<44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,105,102,32,108,111,97,100,105,110,103,32,102,97,105,108,115,46,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,102,105,108,101>>]}]},{dd,[],[<<84,104,101,32,111,98,106,101,99,116,32,99,111,100,101,32,105,110,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,104,97,115,32,97,110,32,105,110,99,111,114,114,101,99,116,32,102,111,114,109,97,116,32>>,{em,[],[<<111,114>>]},<<32,116,104,101,32,111,98,106,101,99,116,32,99,111,100,101,32,99,111,110,116,97,105,110,115,32,99,111,100,101,32,102,111,114,32,97,110,111,116,104,101,114,32,109,111,100,117,108,101,32,116,104,97,110,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,116,95,112,117,114,103,101,100>>]}]},{dd,[],[{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,32,109,111,100,117,108,101,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,108,111,97,100,101,100,32,98,101,99,97,117,115,101,32,111,108,100,32,99,111,100,101,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,46>>]},{dt,[],[{code,[],[<<111,110,95,108,111,97,100>>]}]},{dd,[],[<<84,104,101,32,99,111,100,101,32,105,110,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,111,110,116,97,105,110,115,32,97,110,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,100,101,99,108,97,114,97,116,105,111,110,32,116,104,97,116,32,109,117,115,116,32,98,101,32,101,120,101,99,117,116,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,99,97,110,32,98,101,99,111,109,101,32,116,104,101,32,99,117,114,114,101,110,116,32,99,111,100,101,46,32,65,110,121,32,112,114,101,118,105,111,117,115,32,99,117,114,114,101,110,116,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,119,105,108,108,32,114,101,109,97,105,110,32,117,110,116,105,108,32,116,104,101,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,99,97,108,108,32,104,97,115,32,102,105,110,105,115,104,101,100,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,55,56,51>>,signature => [{attribute,{2309,2},spec,{{load_module,2},[{type,{2309,18},bounded_fun,[{type,{2309,18},'fun',[{type,{2309,18},product,[{var,{2309,19},'Module'},{var,{2309,27},'Binary'}]},{type,{2309,38},union,[{type,{2309,38},tuple,[{atom,{2309,39},module},{var,{2309,47},'Module'}]},{type,{2309,57},tuple,[{atom,{2309,58},error},{var,{2309,65},'Reason'}]}]}]},[{type,{2310,7},constraint,[{atom,{2310,7},is_subtype},[{var,{2310,7},'Module'},{type,{2310,17},module,[]}]]},{type,{2311,7},constraint,[{atom,{2311,7},is_subtype},[{var,{2311,7},'Binary'},{type,{2311,17},binary,[]}]]},{type,{2312,7},constraint,[{atom,{2312,7},is_subtype},[{var,{2312,7},'Reason'},{type,{2312,17},union,[{atom,{2312,17},badfile},{atom,{2312,27},not_purged},{atom,{2312,40},on_load}]}]]}]]}]}}]}},{{function,load_nif,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2330}],[<<108,111,97,100,95,110,105,102,47,50>>],#{<<101,110>> => [{p,[],[<<76,111,97,100,115,32,97,110,100,32,108,105,110,107,115,32,97,32,100,121,110,97,109,105,99,32,108,105,98,114,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,110,97,116,105,118,101,32,105,109,112,108,101,109,101,110,116,101,100,32,102,117,110,99,116,105,111,110,115,32,40,78,73,70,115,41,32,102,111,114,32,97,32,109,111,100,117,108,101,46,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,97,32,102,105,108,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115,104,97,114,101,97,98,108,101,32,111,98,106,101,99,116,47,100,121,110,97,109,105,99,32,108,105,98,114,97,114,121,32,102,105,108,101,32,109,105,110,117,115,32,116,104,101,32,79,83,45,100,101,112,101,110,100,101,110,116,32,102,105,108,101,32,101,120,116,101,110,115,105,111,110,32,40>>,{code,[],[<<46,115,111>>]},<<32,102,111,114,32,85,110,105,120,32,97,110,100,32>>,{code,[],[<<46,100,108,108>>]},<<32,102,111,114,32,87,105,110,100,111,119,115,41,46,32,78,111,116,105,99,101,32,116,104,97,116,32,111,110,32,109,111,115,116,32,79,83,115,32,116,104,101,32,108,105,98,114,97,114,121,32,104,97,115,32,116,111,32,104,97,118,101,32,97,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,32,111,110,32,100,105,115,99,32,119,104,101,110,32,97,110,32,117,112,103,114,97,100,101,32,111,102,32,116,104,101,32,110,105,102,32,105,115,32,100,111,110,101,46,32,73,102,32,116,104,101,32,110,97,109,101,32,105,115,32,116,104,101,32,115,97,109,101,44,32,98,117,116,32,116,104,101,32,99,111,110,116,101,110,116,115,32,100,105,102,102,101,114,44,32,116,104,101,32,111,108,100,32,108,105,98,114,97,114,121,32,109,97,121,32,98,101,32,108,111,97,100,101,100,32,105,110,115,116,101,97,100,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,104,111,119,32,116,111,32,105,109,112,108,101,109,101,110,116,32,97,32,78,73,70,32,108,105,98,114,97,114,121,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,110,105,102>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,108,95,110,105,102,40,51,41>>]}]},<<46>>]},{p,[],[{code,[],[<<76,111,97,100,73,110,102,111>>]},<<32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,46,32,73,116,32,105,115,32,112,97,115,115,101,100,32,111,110,32,116,111,32,116,104,101,32,108,105,98,114,97,114,121,32,97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,105,110,105,116,105,97,108,105,122,97,116,105,111,110,46,32,65,32,103,111,111,100,32,112,114,97,99,116,105,99,101,32,105,115,32,116,111,32,105,110,99,108,117,100,101,32,97,32,109,111,100,117,108,101,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,32,116,111,32,115,117,112,112,111,114,116,32,102,117,116,117,114,101,32,99,111,100,101,32,117,112,103,114,97,100,101,32,115,99,101,110,97,114,105,111,115,46>>]},{p,[],[<<84,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<108,111,97,100,95,110,105,102,47,50>>]},<<32,109,117,115,116,32,98,101,32,109,97,100,101,32>>,{em,[],[<<100,105,114,101,99,116,108,121>>]},<<32,102,114,111,109,32,116,104,101,32,69,114,108,97,110,103,32,99,111,100,101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,32,116,104,97,116,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,32,98,101,108,111,110,103,115,32,116,111,46,32,73,116,32,114,101,116,117,114,110,115,32,101,105,116,104,101,114,32>>,{code,[],[<<111,107>>]},<<44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,123,82,101,97,115,111,110,44,84,101,120,116,125,125>>]},<<32,105,102,32,108,111,97,100,105,110,103,32,102,97,105,108,115,46,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,32,119,104,105,108,101,32>>,{code,[],[<<84,101,120,116>>]},<<32,105,115,32,97,32,104,117,109,97,110,32,114,101,97,100,97,98,108,101,32,115,116,114,105,110,103,32,116,104,97,116,32,99,97,110,32,103,105,118,101,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,102,97,105,108,117,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,111,97,100,95,102,97,105,108,101,100>>]}]},{dd,[],[<<84,104,101,32,79,83,32,102,97,105,108,101,100,32,116,111,32,108,111,97,100,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,46>>]},{dt,[],[{code,[],[<<98,97,100,95,108,105,98>>]}]},{dd,[],[<<84,104,101,32,108,105,98,114,97,114,121,32,100,105,100,32,110,111,116,32,102,117,108,102,105,108,108,32,116,104,101,32,114,101,113,117,105,114,101,109,101,110,116,115,32,97,115,32,97,32,78,73,70,32,108,105,98,114,97,114,121,32,111,102,32,116,104,101,32,99,97,108,108,105,110,103,32,109,111,100,117,108,101,46>>]},{dt,[],[{code,[],[<<108,111,97,100,32,124,32,117,112,103,114,97,100,101>>]}]},{dd,[],[<<84,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,108,105,98,114,97,114,121,32,99,97,108,108,98,97,99,107,32,119,97,115,32,117,110,115,117,99,99,101,115,115,102,117,108,46>>]},{dt,[],[{code,[],[<<114,101,108,111,97,100>>]}]},{dd,[],[<<65,32,78,73,70,32,108,105,98,114,97,114,121,32,105,115,32,97,108,114,101,97,100,121,32,108,111,97,100,101,100,32,102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,32,105,110,115,116,97,110,99,101,46,32,84,104,101,32,112,114,101,118,105,111,117,115,108,121,32,100,101,112,114,101,99,97,116,101,100,32>>,{code,[],[<<114,101,108,111,97,100>>]},<<32,102,101,97,116,117,114,101,32,119,97,115,32,114,101,109,111,118,101,100,32,105,110,32,79,84,80,32,50,48,46>>]},{dt,[],[{code,[],[<<111,108,100,95,99,111,100,101>>]}]},{dd,[],[<<84,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<108,111,97,100,95,110,105,102,47,50>>]},<<32,119,97,115,32,109,97,100,101,32,102,114,111,109,32,116,104,101,32,111,108,100,32,99,111,100,101,32,111,102,32,97,32,109,111,100,117,108,101,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,117,112,103,114,97,100,101,100,59,32,116,104,105,115,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,50,51>>,signature => [{attribute,{2330,2},spec,{{erlang,load_nif,2},[{type,{2330,22},bounded_fun,[{type,{2330,22},'fun',[{type,{2330,22},product,[{var,{2330,23},'Path'},{var,{2330,29},'LoadInfo'}]},{type,{2330,43},union,[{atom,{2330,43},ok},{var,{2330,48},'Error'}]}]},[{type,{2331,7},constraint,[{atom,{2331,7},is_subtype},[{var,{2331,7},'Path'},{type,{2331,15},string,[]}]]},{type,{2332,7},constraint,[{atom,{2332,7},is_subtype},[{var,{2332,7},'LoadInfo'},{type,{2332,19},term,[]}]]},{type,{2333,7},constraint,[{atom,{2333,7},is_subtype},[{var,{2333,7},'Error'},{type,{2333,16},tuple,[{atom,{2333,17},error},{type,{2333,24},tuple,[{var,{2333,25},'Reason'},{ann_type,{2333,33},[{var,{2333,33},'Text'},{type,{2333,41},string,[]}]}]}]}]]},{type,{2334,7},constraint,[{atom,{2334,7},is_subtype},[{var,{2334,7},'Reason'},{type,{2334,17},union,[{atom,{2334,17},load_failed},{atom,{2334,31},bad_lib},{atom,{2334,41},load},{atom,{2334,48},reload},{atom,{2334,57},upgrade},{atom,{2334,67},old_code}]}]]}]]}]}}]}},{{function,loaded,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1383}],[<<108,111,97,100,101,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,108,108,32,108,111,97,100,101,100,32,69,114,108,97,110,103,32,109,111,100,117,108,101,115,32,40,99,117,114,114,101,110,116,32,97,110,100,32,111,108,100,32,99,111,100,101,41,44,32,105,110,99,108,117,100,105,110,103,32,112,114,101,108,111,97,100,101,100,32,109,111,100,117,108,101,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,55,50>>,signature => [{attribute,{1383,2},spec,{{erlang,loaded,0},[{type,{1383,20},bounded_fun,[{type,{1383,20},'fun',[{type,{1383,20},product,[]},{type,{1383,26},list,[{var,{1383,27},'Module'}]}]},[{type,{1384,7},constraint,[{atom,{1384,7},is_subtype},[{var,{1384,7},'Module'},{type,{1384,17},module,[]}]]}]]}]}}]}},{{function,localtime,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1389}],[<<108,111,99,97,108,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,44,32>>,{code,[],[<<123,123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125,44,32,123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125,125>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,40,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,122,111,110,101,32,97,110,100,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,99,111,114,114,101,99,116,105,111,110,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,56,56,51>>,signature => [{attribute,{1389,2},spec,{{erlang,localtime,0},[{type,{1389,23},bounded_fun,[{type,{1389,23},'fun',[{type,{1389,23},product,[]},{var,{1389,29},'DateTime'}]},[{type,{1390,7},constraint,[{atom,{1390,7},is_subtype},[{var,{1390,7},'DateTime'},{remote_type,{1390,19},[{atom,{1390,19},calendar},{atom,{1390,28},datetime},[]]}]]}]]}]}}]}},{{function,localtime_to_universaltime,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3501}],[<<108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,116,111,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,44,32,105,102,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32,110,111,32,99,111,110,118,101,114,115,105,111,110,32,105,115,32,100,111,110,101,32,97,110,100,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,51,44,52,53,44,49,55,125,125>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,100,101,110,111,116,101,115,32,97,110,32,105,110,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,57,48,48>>,signature => [{attribute,{3501,2},spec,{{erlang,localtime_to_universaltime,1},[{type,{3501,40},bounded_fun,[{type,{3501,40},'fun',[{type,{3501,40},product,[{var,{3501,41},'Localtime'}]},{var,{3501,55},'Universaltime'}]},[{type,{3502,7},constraint,[{atom,{3502,7},is_subtype},[{var,{3502,7},'Localtime'},{remote_type,{3502,20},[{atom,{3502,20},calendar},{atom,{3502,29},datetime},[]]}]]},{type,{3503,7},constraint,[{atom,{3503,7},is_subtype},[{var,{3503,7},'Universaltime'},{remote_type,{3503,24},[{atom,{3503,24},calendar},{atom,{3503,33},datetime},[]]}]]}]]}]}}]}},{{function,localtime_to_universaltime,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2338}],[<<108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,116,111,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,32,97,115,32>>,{code,[],[<<101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,47,49>>]},<<44,32,98,117,116,32,116,104,101,32,99,97,108,108,101,114,32,100,101,99,105,100,101,115,32,105,102,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,105,115,32,97,99,116,105,118,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<73,115,68,115,116,32,61,61,32,116,114,117,101>>]},<<44,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,105,115,32,100,117,114,105,110,103,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,44,32,105,102,32>>,{code,[],[<<73,115,68,115,116,32,61,61,32,102,97,108,115,101>>]},<<32,105,116,32,105,115,32,110,111,116,46,32,73,102,32>>,{code,[],[<<73,115,68,115,116,32,61,61,32,117,110,100,101,102,105,110,101,100>>]},<<44,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,32,99,97,110,32,103,117,101,115,115,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,76,111,99,97,108,116,105,109,101,41>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,44,32,116,114,117,101,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,50,44,52,53,44,49,55,125,125,10,62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,44,32,102,97,108,115,101,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,51,44,52,53,44,49,55,125,125,10,62,32,101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,95,116,111,95,117,110,105,118,101,114,115,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,52,53,44,49,55,125,125,44,32,117,110,100,101,102,105,110,101,100,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,51,44,52,53,44,49,55,125,125>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,111,99,97,108,116,105,109,101>>]},<<32,100,101,110,111,116,101,115,32,97,110,32,105,110,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,57,49,55>>,signature => [{attribute,{2338,2},spec,{{erlang,localtime_to_universaltime,2},[{type,{2338,40},bounded_fun,[{type,{2338,40},'fun',[{type,{2338,40},product,[{var,{2338,41},'Localtime'},{var,{2338,52},'IsDst'}]},{var,{2338,62},'Universaltime'}]},[{type,{2339,7},constraint,[{atom,{2339,7},is_subtype},[{var,{2339,7},'Localtime'},{remote_type,{2339,20},[{atom,{2339,20},calendar},{atom,{2339,29},datetime},[]]}]]},{type,{2340,7},constraint,[{atom,{2340,7},is_subtype},[{var,{2340,7},'Universaltime'},{remote_type,{2340,24},[{atom,{2340,24},calendar},{atom,{2340,33},datetime},[]]}]]},{type,{2341,7},constraint,[{atom,{2341,7},is_subtype},[{var,{2341,7},'IsDst'},{type,{2341,16},union,[{atom,{2341,16},true},{atom,{2341,23},false},{atom,{2341,31},undefined}]}]]}]]}]}}]}},{{function,make_ref,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1395}],[<<109,97,107,101,95,114,101,102,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100,35,117,110,105,113,117,101,95,114,101,102,101,114,101,110,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<117,110,105,113,117,101,32,114,101,102,101,114,101,110,99,101>>]},<<46,32,84,104,101,32,114,101,102,101,114,101,110,99,101,32,105,115,32,117,110,105,113,117,101,32,97,109,111,110,103,32,99,111,110,110,101,99,116,101,100,32,110,111,100,101,115,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<66,101,102,111,114,101,32,79,84,80,45,50,51,32,119,104,101,110,32,97,32,110,111,100,101,32,105,115,32,114,101,115,116,97,114,116,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,110,97,109,101,44,32,114,101,102,101,114,101,110,99,101,115,32,99,114,101,97,116,101,100,32,111,110,32,97,32,110,101,119,101,114,32,110,111,100,101,32,99,97,110,32,98,101,32,109,105,115,116,97,107,101,110,32,102,111,114,32,97,32,114,101,102,101,114,101,110,99,101,32,99,114,101,97,116,101,100,32,111,110,32,97,110,32,111,108,100,101,114,32,110,111,100,101,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,110,97,109,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,57,52,51>>,signature => [{attribute,{1395,2},spec,{{make_ref,0},[{type,{1395,15},'fun',[{type,{1395,15},product,[]},{type,{1395,21},reference,[]}]}]}}]}},{{function,make_tuple,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2357}],[<<109,97,107,101,95,116,117,112,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,110,101,119,32,116,117,112,108,101,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32>>,{code,[],[<<65,114,105,116,121>>]},<<44,32,119,104,101,114,101,32,97,108,108,32,101,108,101,109,101,110,116,115,32,97,114,101,32>>,{code,[],[<<73,110,105,116,105,97,108,86,97,108,117,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,109,97,107,101,95,116,117,112,108,101,40,52,44,32,91,93,41,46,10,123,91,93,44,91,93,44,91,93,44,91,93,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,57,54,48>>,signature => [{attribute,{2357,2},spec,{{erlang,make_tuple,2},[{type,{2357,24},bounded_fun,[{type,{2357,24},'fun',[{type,{2357,24},product,[{var,{2357,25},'Arity'},{var,{2357,32},'InitialValue'}]},{type,{2357,49},tuple,any}]},[{type,{2358,7},constraint,[{atom,{2358,7},is_subtype},[{var,{2358,7},'Arity'},{type,{2358,16},arity,[]}]]},{type,{2359,7},constraint,[{atom,{2359,7},is_subtype},[{var,{2359,7},'InitialValue'},{type,{2359,23},term,[]}]]}]]}]}}]}},{{function,make_tuple,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2364}],[<<109,97,107,101,95,116,117,112,108,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,116,117,112,108,101,32,111,102,32,115,105,122,101,32>>,{code,[],[<<65,114,105,116,121>>]},<<44,32,119,104,101,114,101,32,101,97,99,104,32,101,108,101,109,101,110,116,32,104,97,115,32,118,97,108,117,101,32>>,{code,[],[<<68,101,102,97,117,108,116,86,97,108,117,101>>]},<<44,32,97,110,100,32,116,104,101,110,32,102,105,108,108,115,32,105,110,32,118,97,108,117,101,115,32,102,114,111,109,32>>,{code,[],[<<73,110,105,116,76,105,115,116>>]},<<46,32,69,97,99,104,32,108,105,115,116,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<73,110,105,116,76,105,115,116>>]},<<32,109,117,115,116,32,98,101,32,97,32,116,119,111,45,116,117,112,108,101,44,32,119,104,101,114,101,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,116,117,112,108,101,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,32,105,115,32,97,110,121,32,116,101,114,109,46,32,73,102,32,97,32,112,111,115,105,116,105,111,110,32,111,99,99,117,114,115,32,109,111,114,101,32,116,104,97,110,32,111,110,99,101,32,105,110,32,116,104,101,32,108,105,115,116,44,32,116,104,101,32,116,101,114,109,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,108,97,115,116,32,111,99,99,117,114,114,101,110,99,101,32,105,115,32,117,115,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,109,97,107,101,95,116,117,112,108,101,40,53,44,32,91,93,44,32,91,123,50,44,105,103,110,111,114,101,100,125,44,123,53,44,122,122,125,44,123,50,44,97,97,125,93,41,46,10,123,91,93,44,97,97,44,91,93,44,91,93,44,122,122,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,57,55,50>>,signature => [{attribute,{2364,2},spec,{{erlang,make_tuple,3},[{type,{2364,24},bounded_fun,[{type,{2364,24},'fun',[{type,{2364,24},product,[{var,{2364,25},'Arity'},{var,{2364,32},'DefaultValue'},{var,{2364,46},'InitList'}]},{type,{2364,59},tuple,any}]},[{type,{2365,7},constraint,[{atom,{2365,7},is_subtype},[{var,{2365,7},'Arity'},{type,{2365,16},arity,[]}]]},{type,{2366,7},constraint,[{atom,{2366,7},is_subtype},[{var,{2366,7},'DefaultValue'},{type,{2366,23},term,[]}]]},{type,{2367,7},constraint,[{atom,{2367,7},is_subtype},[{var,{2367,7},'InitList'},{type,{2367,19},list,[{type,{2367,20},tuple,[{ann_type,{2367,21},[{var,{2367,21},'Position'},{type,{2367,33},pos_integer,[]}]},{type,{2367,48},term,[]}]}]}]]}]]}]}}]}},{{function,map_get,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1406}],[<<109,97,112,95,103,101,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<32,105,102,32>>,{code,[],[<<77,97,112>>]},<<32,99,111,110,116,97,105,110,115,32>>,{code,[],[<<75,101,121>>]},<<46>>]},{p,[],[<<84,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<123,98,97,100,109,97,112,44,77,97,112,125>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32>>,{code,[],[<<77,97,112>>]},<<32,105,115,32,110,111,116,32,97,32,109,97,112,44,32,111,114,32,119,105,116,104,32,97,32>>,{code,[],[<<123,98,97,100,107,101,121,44,75,101,121,125>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32,110,111,32,118,97,108,117,101,32,105,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<62,32,75,101,121,32,61,32,49,51,51,55,44,10,32,32,77,97,112,32,61,32,35,123,52,50,32,61,62,32,118,97,108,117,101,95,116,119,111,44,49,51,51,55,32,61,62,32,34,118,97,108,117,101,32,111,110,101,34,44,34,97,34,32,61,62,32,49,125,44,10,32,32,109,97,112,95,103,101,116,40,75,101,121,44,77,97,112,41,46,10,34,118,97,108,117,101,32,111,110,101,34>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,51,57,57,48>>,signature => [{attribute,{1406,2},spec,{{map_get,2},[{type,{1406,14},bounded_fun,[{type,{1406,14},'fun',[{type,{1406,14},product,[{var,{1406,15},'Key'},{var,{1406,20},'Map'}]},{var,{1406,28},'Value'}]},[{type,{1407,7},constraint,[{atom,{1407,7},is_subtype},[{var,{1407,7},'Map'},{type,{1407,14},map,any}]]},{type,{1408,7},constraint,[{atom,{1408,7},is_subtype},[{var,{1408,7},'Key'},{type,{1408,14},any,[]}]]},{type,{1409,7},constraint,[{atom,{1409,7},is_subtype},[{var,{1409,7},'Value'},{type,{1409,16},any,[]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,48>>}},{{function,map_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1400}],[<<109,97,112,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,107,101,121,45,118,97,108,117,101,32,112,97,105,114,115,32,105,110,32>>,{code,[],[<<77,97,112>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,109,97,112,95,115,105,122,101,40,35,123,97,61,62,49,44,32,98,61,62,50,44,32,99,61,62,51,125,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,48,49,48>>,signature => [{attribute,{1400,2},spec,{{map_size,1},[{type,{1400,15},bounded_fun,[{type,{1400,15},'fun',[{type,{1400,15},product,[{var,{1400,16},'Map'}]},{type,{1400,24},non_neg_integer,[]}]},[{type,{1401,7},constraint,[{atom,{1401,7},is_subtype},[{var,{1401,7},'Map'},{type,{1401,14},map,any}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,match_spec_test,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1414}],[<<109,97,116,99,104,95,115,112,101,99,95,116,101,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,101,115,116,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,117,115,101,100,32,105,110,32,99,97,108,108,115,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,116,115,35,115,101,108,101,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,116,115,58,115,101,108,101,99,116,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,101,115,116,115,32,98,111,116,104,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,34,115,121,110,116,97,99,116,105,99,34,32,99,111,114,114,101,99,116,110,101,115,115,32,97,110,100,32,114,117,110,115,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,103,97,105,110,115,116,32,116,104,101,32,111,98,106,101,99,116,46,32,73,102,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,99,111,110,116,97,105,110,115,32,101,114,114,111,114,115,44,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,69,114,114,111,114,115,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,119,104,101,114,101,32>>,{code,[],[<<69,114,114,111,114,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,110,97,116,117,114,97,108,32,108,97,110,103,117,97,103,101,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,119,104,97,116,32,119,97,115,32,119,114,111,110,103,32,119,105,116,104,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<116,97,98,108,101>>]},<<44,32,116,104,101,32,111,98,106,101,99,116,32,116,111,32,109,97,116,99,104,32,97,103,97,105,110,115,116,32,105,115,32,116,111,32,98,101,32,97,32,116,117,112,108,101,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,104,101,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,82,101,115,117,108,116,44,91,93,44,87,97,114,110,105,110,103,115,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,119,104,97,116,32,119,111,117,108,100,32,104,97,118,101,32,98,101,101,110,32,116,104,101,32,114,101,115,117,108,116,32,105,110,32,97,32,114,101,97,108,32>>,{code,[],[<<101,116,115,58,115,101,108,101,99,116,47,50>>]},<<32,99,97,108,108,44,32,111,114,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,111,98,106,101,99,116,32,116,117,112,108,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<116,114,97,99,101>>]},<<44,32,116,104,101,32,111,98,106,101,99,116,32,116,111,32,109,97,116,99,104,32,97,103,97,105,110,115,116,32,105,115,32,116,111,32,98,101,32,97,32,108,105,115,116,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,82,101,115,117,108,116,44,32,70,108,97,103,115,44,32,87,97,114,110,105,110,103,115,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{code,[],[<<116,114,117,101>>]},<<32,105,102,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,116,111,32,98,101,32,101,109,105,116,116,101,100>>]},{li,[],[{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,110,111,116,32,116,111,32,98,101,32,101,109,105,116,116,101,100>>]},{li,[],[<<84,104,101,32,109,101,115,115,97,103,101,32,116,101,114,109,32,116,111,32,98,101,32,97,112,112,101,110,100,101,100,32,116,111,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101>>]}]},{p,[],[{code,[],[<<70,108,97,103,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,97,108,108,32,116,104,101,32,116,114,97,99,101,32,102,108,97,103,115,32,116,111,32,98,101,32,101,110,97,98,108,101,100,44,32,99,117,114,114,101,110,116,108,121,32,116,104,105,115,32,105,115,32,111,110,108,121,32>>,{code,[],[<<114,101,116,117,114,110,95,116,114,97,99,101>>]},<<46>>]},{p,[],[<<84,104,105,115,32,105,115,32,97,32,117,115,101,102,117,108,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,116,101,115,116,32,116,111,111,108,44,32,101,115,112,101,99,105,97,108,108,121,32,119,104,101,110,32,119,114,105,116,105,110,103,32,99,111,109,112,108,105,99,97,116,101,100,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,116,115,35,116,101,115,116,95,109,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,116,115,58,116,101,115,116,95,109,115,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,48,50,51>>,signature => [{attribute,{1414,2},spec,{{erlang,match_spec_test,3},[{type,{1414,29},bounded_fun,[{type,{1414,29},'fun',[{type,{1414,29},product,[{var,{1414,30},'MatchAgainst'},{var,{1414,44},'MatchSpec'},{var,{1414,55},'Type'}]},{var,{1414,64},'TestResult'}]},[{type,{1415,7},constraint,[{atom,{1415,7},is_subtype},[{var,{1415,7},'MatchAgainst'},{type,{1415,23},union,[{type,{1415,23},list,[{type,{1415,24},term,[]}]},{type,{1415,34},tuple,any}]}]]},{type,{1416,7},constraint,[{atom,{1416,7},is_subtype},[{var,{1416,7},'MatchSpec'},{type,{1416,20},term,[]}]]},{type,{1417,7},constraint,[{atom,{1417,7},is_subtype},[{var,{1417,7},'Type'},{type,{1417,15},union,[{atom,{1417,15},table},{atom,{1417,23},trace}]}]]},{type,{1418,7},constraint,[{atom,{1418,7},is_subtype},[{var,{1418,7},'TestResult'},{type,{1418,21},union,[{type,{1418,21},tuple,[{atom,{1418,22},ok},{type,{1418,26},term,[]},{type,{1418,34},list,[{atom,{1418,35},return_trace}]},{type,{1418,50},list,[{type,{1418,52},tuple,[{type,{1418,53},union,[{atom,{1418,53},error},{atom,{1418,61},warning}]},{type,{1418,70},string,[]}]}]}]},{type,{1418,85},tuple,[{atom,{1418,86},error},{type,{1418,93},list,[{type,{1418,95},tuple,[{type,{1418,96},union,[{atom,{1418,96},error},{atom,{1418,104},warning}]},{type,{1418,113},string,[]}]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,max,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3991}],[<<109,97,120,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,97,114,103,101,115,116,32,111,102,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,97,110,100,32>>,{code,[],[<<84,101,114,109,50>>]},<<46,32,73,102,32,116,104,101,32,116,101,114,109,115,32,99,111,109,112,97,114,101,32,101,113,117,97,108,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,44,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,116,101,114,109,45,99,111,109,112,97,114,105,115,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,120,112,114,101,115,115,105,111,110,115,32,115,101,99,116,105,111,110>>]},<<32,99,111,110,116,97,105,110,115,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,32,97,110,100,32,104,111,119,32,116,101,114,109,115,32,97,114,101,32,111,114,100,101,114,101,100,46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,109,97,120,40,49,44,32,50,41,46,10,50>>]}]},{pre,[],[{code,[],[<<62,32,109,97,120,40,49,46,48,44,32,49,41,46,10,49,46,48>>]}]},{pre,[],[{code,[],[<<62,32,109,97,120,40,49,44,32,49,46,48,41,46,10,49>>]}]},{pre,[],[{code,[],[<<62,32,109,97,120,40,34,97,98,99,34,44,32,34,98,34,41,46,10,34,98,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,48,54,49>>,signature => [{attribute,{3991,2},spec,{{max,2},[{type,{3991,10},bounded_fun,[{type,{3991,10},'fun',[{type,{3991,10},product,[{var,{3991,11},'Term1'},{var,{3991,18},'Term2'}]},{var,{3991,28},'Maximum'}]},[{type,{3992,7},constraint,[{atom,{3992,7},is_subtype},[{var,{3992,7},'Term1'},{type,{3992,16},term,[]}]]},{type,{3993,7},constraint,[{atom,{3993,7},is_subtype},[{var,{3993,7},'Term2'},{type,{3993,16},term,[]}]]},{type,{3994,7},constraint,[{atom,{3994,7},is_subtype},[{var,{3994,7},'Maximum'},{type,{3994,18},term,[]}]]}]]}]}}]}},{{function,md5,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1423}],[<<109,100,53,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,117,116,101,115,32,97,110,32,77,68,53,32,109,101,115,115,97,103,101,32,100,105,103,101,115,116,32,102,114,111,109,32>>,{code,[],[<<68,97,116,97>>]},<<44,32,119,104,101,114,101,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,100,105,103,101,115,116,32,105,115,32,49,50,56,32,98,105,116,115,32,40,49,54,32,98,121,116,101,115,41,46,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,111,114,32,97,32,108,105,115,116,32,111,102,32,115,109,97,108,108,32,105,110,116,101,103,101,114,115,32,97,110,100,32,98,105,110,97,114,105,101,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,77,68,53,44,32,115,101,101,32>>,{a,[{href,<<104,116,116,112,115,58,47,47,119,119,119,46,105,101,116,102,46,111,114,103,47,114,102,99,47,114,102,99,49,51,50,49,46,116,120,116>>}],[<<82,70,67,32,49,51,50,49,32,45,32,84,104,101,32,77,68,53,32,77,101,115,115,97,103,101,45,68,105,103,101,115,116,32,65,108,103,111,114,105,116,104,109>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,32,77,68,53,32,77,101,115,115,97,103,101,45,68,105,103,101,115,116,32,65,108,103,111,114,105,116,104,109,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,99,111,110,115,105,100,101,114,101,100,32,115,97,102,101,32,102,111,114,32,99,111,100,101,45,115,105,103,110,105,110,103,32,111,114,32,115,111,102,116,119,97,114,101,45,105,110,116,101,103,114,105,116,121,32,112,117,114,112,111,115,101,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,48,57,48>>,signature => [{attribute,{1423,2},spec,{{erlang,md5,1},[{type,{1423,17},bounded_fun,[{type,{1423,17},'fun',[{type,{1423,17},product,[{var,{1423,18},'Data'}]},{var,{1423,27},'Digest'}]},[{type,{1424,7},constraint,[{atom,{1424,7},is_subtype},[{var,{1424,7},'Data'},{type,{1424,15},iodata,[]}]]},{type,{1425,7},constraint,[{atom,{1425,7},is_subtype},[{var,{1425,7},'Digest'},{type,{1425,17},binary,[]}]]}]]}]}}]}},{{function,md5_final,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1430}],[<<109,100,53,95,102,105,110,97,108,47,49>>],#{<<101,110>> => [{p,[],[<<70,105,110,105,115,104,101,115,32,116,104,101,32,117,112,100,97,116,101,32,111,102,32,97,110,32,77,68,53,32>>,{code,[],[<<67,111,110,116,101,120,116>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,99,111,109,112,117,116,101,100,32>>,{code,[],[<<77,68,53>>]},<<32,109,101,115,115,97,103,101,32,100,105,103,101,115,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,48,56>>,signature => [{attribute,{1430,2},spec,{{erlang,md5_final,1},[{type,{1430,23},bounded_fun,[{type,{1430,23},'fun',[{type,{1430,23},product,[{var,{1430,24},'Context'}]},{var,{1430,36},'Digest'}]},[{type,{1431,7},constraint,[{atom,{1431,7},is_subtype},[{var,{1431,7},'Context'},{type,{1431,18},binary,[]}]]},{type,{1432,7},constraint,[{atom,{1432,7},is_subtype},[{var,{1432,7},'Digest'},{type,{1432,17},binary,[]}]]}]]}]}}]}},{{function,md5_init,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1437}],[<<109,100,53,95,105,110,105,116,47,48>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,110,32,77,68,53,32,99,111,110,116,101,120,116,44,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,100,53,95,117,112,100,97,116,101,47,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,49,56>>,signature => [{attribute,{1437,2},spec,{{erlang,md5_init,0},[{type,{1437,22},bounded_fun,[{type,{1437,22},'fun',[{type,{1437,22},product,[]},{var,{1437,28},'Context'}]},[{type,{1438,7},constraint,[{atom,{1438,7},is_subtype},[{var,{1438,7},'Context'},{type,{1438,18},binary,[]}]]}]]}]}}]}},{{function,md5_update,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1443}],[<<109,100,53,95,117,112,100,97,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<85,112,100,97,116,101,32,97,110,32,77,68,53,32>>,{code,[],[<<67,111,110,116,101,120,116>>]},<<32,119,105,116,104,32>>,{code,[],[<<68,97,116,97>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32,97,32>>,{code,[],[<<78,101,119,67,111,110,116,101,120,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,50,55>>,signature => [{attribute,{1443,2},spec,{{erlang,md5_update,2},[{type,{1443,24},bounded_fun,[{type,{1443,24},'fun',[{type,{1443,24},product,[{var,{1443,25},'Context'},{var,{1443,34},'Data'}]},{var,{1443,43},'NewContext'}]},[{type,{1444,7},constraint,[{atom,{1444,7},is_subtype},[{var,{1444,7},'Context'},{type,{1444,18},binary,[]}]]},{type,{1445,7},constraint,[{atom,{1445,7},is_subtype},[{var,{1445,7},'Data'},{type,{1445,15},iodata,[]}]]},{type,{1446,7},constraint,[{atom,{1446,7},is_subtype},[{var,{1446,7},'NewContext'},{type,{1446,21},binary,[]}]]}]]}]}}]}},{{function,memory,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,4023}],[<<109,101,109,111,114,121,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,101,109,111,114,121,95,116,121,112,101>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,109,101,109,111,114,121,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,101,109,117,108,97,116,111,114,46,32,69,97,99,104,32,108,105,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,84,121,112,101,44,32,83,105,122,101,125>>]},<<46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,109,101,109,111,114,121,32,116,121,112,101,46,32,84,104,101,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,32>>,{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,109,101,109,111,114,121,32,115,105,122,101,32,105,110,32,98,121,116,101,115,46>>]},{p,[],[<<77,101,109,111,114,121,32,116,121,112,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,111,116,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,115,105,122,101,32,102,111,114,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<46>>]}]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,46>>]}]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,101,115,95,117,115,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,46,32,84,104,105,115,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,116,104,101,32,101,109,117,108,97,116,111,114,32,116,104,97,116,32,105,115,32,110,111,116,32,100,105,114,101,99,116,108,121,32,114,101,108,97,116,101,100,32,116,111,32,97,110,121,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,46,32,77,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,105,115,32,110,111,116,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,105,115,32,109,101,109,111,114,121,46,32>>,{a,[{href,<<116,111,111,108,115,58,105,110,115,116,114,117,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,115,116,114,117,109,101,110,116,40,51,41>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,103,101,116,32,97,32,109,111,114,101,32,100,101,116,97,105,108,101,100,32,98,114,101,97,107,100,111,119,110,32,111,102,32,119,104,97,116,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,105,115,32,116,121,112,101,46>>]}]},{dt,[],[{code,[],[<<97,116,111,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,97,116,111,109,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<97,116,111,109,95,117,115,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,102,111,114,32,97,116,111,109,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<97,116,111,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,98,105,110,97,114,105,101,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<99,111,100,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,69,114,108,97,110,103,32,99,111,100,101,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<101,116,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,99,117,114,114,101,110,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,69,84,83,32,116,97,98,108,101,115,46,32,84,104,105,115,32,109,101,109,111,114,121,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,109,101,109,111,114,121,46>>]}]},{dt,[],[{code,[],[<<109,97,120,105,109,117,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,115,105,110,99,101,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,97,115,32,115,116,97,114,116,101,100,46,32,84,104,105,115,32,116,117,112,108,101,32,105,115,32,111,110,108,121,32,112,114,101,115,101,110,116,32,119,104,101,110,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,114,117,110,32,119,105,116,104,32,105,110,115,116,114,117,109,101,110,116,97,116,105,111,110,46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,104,111,119,32,116,111,32,114,117,110,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,105,116,104,32,105,110,115,116,114,117,109,101,110,116,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<116,111,111,108,115,58,105,110,115,116,114,117,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,115,116,114,117,109,101,110,116,40,51,41>>]}]},<<32,97,110,100,47,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<101,114,108,40,49,41>>]}]},<<46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,118,97,108,117,101,32,105,115,32,110,111,116,32,99,111,109,112,108,101,116,101,46,32,83,111,109,101,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,116,104,97,116,32,105,115,32,116,111,32,98,101,32,112,97,114,116,32,111,102,32,116,104,105,115,32,118,97,108,117,101,32,105,115,32,110,111,116,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,114,117,110,32,119,105,116,104,32,105,110,115,116,114,117,109,101,110,116,97,116,105,111,110,44,32,116,104,101,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,118,97,108,117,101,32,105,115,32,109,111,114,101,32,97,99,99,117,114,97,116,101,44,32,98,117,116,32,109,101,109,111,114,121,32,100,105,114,101,99,116,108,121,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32>>,{code,[],[<<109,97,108,108,111,99>>]},<<32,40,97,110,100,32,102,114,105,101,110,100,115,41,32,105,115,32,115,116,105,108,108,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,118,97,108,117,101,46,32,68,105,114,101,99,116,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,97,108,108,111,99>>]},<<32,97,114,101,32,111,110,108,121,32,100,111,110,101,32,102,114,111,109,32,79,83,45,115,112,101,99,105,102,105,99,32,114,117,110,116,105,109,101,32,108,105,98,114,97,114,105,101,115,32,97,110,100,32,112,101,114,104,97,112,115,32,102,114,111,109,32,117,115,101,114,45,105,109,112,108,101,109,101,110,116,101,100,32,69,114,108,97,110,103,32,100,114,105,118,101,114,115,32,116,104,97,116,32,100,111,32,110,111,116,32,117,115,101,32,116,104,101,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32,100,114,105,118,101,114,32,105,110,116,101,114,102,97,99,101,46>>]},{p,[],[<<65,115,32,116,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,32,105,115,32,116,104,101,32,115,117,109,32,111,102,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115>>]},<<32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<44,32,116,104,101,32,101,114,114,111,114,32,105,110,32>>,{code,[],[<<115,121,115,116,101,109>>]},<<32,112,114,111,112,97,103,97,116,101,115,32,116,111,32,116,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,46>>]},{p,[],[<<84,104,101,32,100,105,102,102,101,114,101,110,116,32,97,109,111,117,110,116,115,32,111,102,32,109,101,109,111,114,121,32,116,104,97,116,32,97,114,101,32,115,117,109,109,101,100,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,44,32,119,104,105,99,104,32,105,110,116,114,111,100,117,99,101,115,32,97,110,32,101,114,114,111,114,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},{p,[],[<<84,104,101,32,100,105,102,102,101,114,101,110,116,32,118,97,108,117,101,115,32,104,97,118,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,101,108,97,116,105,111,110,32,116,111,32,101,97,99,104,32,111,116,104,101,114,46,32,86,97,108,117,101,115,32,98,101,103,105,110,110,105,110,103,32,119,105,116,104,32,97,110,32,117,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114,32,105,115,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<116,111,116,97,108,32,32,32,32,32,32,61,32,112,114,111,99,101,115,115,101,115,32,43,32,115,121,115,116,101,109,10,112,114,111,99,101,115,115,101,115,32,32,61,32,112,114,111,99,101,115,115,101,115,95,117,115,101,100,32,43,32,80,114,111,99,101,115,115,101,115,78,111,116,85,115,101,100,10,115,121,115,116,101,109,32,32,32,32,32,61,32,97,116,111,109,32,43,32,98,105,110,97,114,121,32,43,32,99,111,100,101,32,43,32,101,116,115,32,43,32,79,116,104,101,114,83,121,115,116,101,109,10,97,116,111,109,32,32,32,32,32,32,32,61,32,97,116,111,109,95,117,115,101,100,32,43,32,65,116,111,109,78,111,116,85,115,101,100,10,82,101,97,108,84,111,116,97,108,32,32,61,32,112,114,111,99,101,115,115,101,115,32,43,32,82,101,97,108,83,121,115,116,101,109,10,82,101,97,108,83,121,115,116,101,109,32,61,32,115,121,115,116,101,109,32,43,32,77,105,115,115,101,100,83,121,115,116,101,109>>]}]},{p,[],[<<77,111,114,101,32,116,117,112,108,101,115,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,116,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,104,97,114,101,100,32,108,105,98,114,97,114,105,101,115,44,32,116,104,101,32,99,111,100,101,32,111,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,116,115,101,108,102,44,32,97,110,100,32,116,104,101,32,101,109,117,108,97,116,111,114,32,115,116,97,99,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,105,110,99,108,117,100,101,100,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32>>,{code,[],[<<116,111,116,97,108>>]},<<32,118,97,108,117,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,101,113,117,97,108,32,116,111,32,116,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,97,108,108,32,112,97,103,101,115,32,109,97,112,112,101,100,32,116,111,32,116,104,101,32,101,109,117,108,97,116,111,114,46>>]},{p,[],[<<65,108,115,111,44,32,98,101,99,97,117,115,101,32,111,102,32,102,114,97,103,109,101,110,116,97,116,105,111,110,32,97,110,100,32,112,114,101,114,101,115,101,114,118,97,116,105,111,110,32,111,102,32,109,101,109,111,114,121,32,97,114,101,97,115,44,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,115,101,103,109,101,110,116,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,98,108,111,99,107,115,32,99,97,110,32,98,101,32,109,117,99,104,32,108,97,114,103,101,114,32,116,104,97,110,32,116,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,116,104,101,32,100,121,110,97,109,105,99,97,108,108,121,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,98,108,111,99,107,115,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,54,46,52,44,32>>,{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48>>]},<<32,114,101,113,117,105,114,101,115,32,116,104,97,116,32,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,115,32,97,114,101,32,101,110,97,98,108,101,100,32,40,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,41,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,105,102,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,32,104,97,115,32,98,101,101,110,32,100,105,115,97,98,108,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,49,51,56>>,signature => [{attribute,{4023,2},spec,{{erlang,memory,0},[{type,{4023,20},bounded_fun,[{type,{4023,20},'fun',[{type,{4023,20},product,[]},{type,{4023,26},list,[{type,{4023,27},tuple,[{var,{4023,28},'Type'},{var,{4023,34},'Size'}]}]}]},[{type,{4024,7},constraint,[{atom,{4024,7},is_subtype},[{var,{4024,7},'Type'},{user_type,{4024,15},memory_type,[]}]]},{type,{4025,7},constraint,[{atom,{4025,7},is_subtype},[{var,{4025,7},'Size'},{type,{4025,15},non_neg_integer,[]}]]}]]}]}}]}},{{function,memory,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,4042}],[<<109,101,109,111,114,121,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,101,109,111,114,121,95,116,121,112,101>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,101,109,111,114,121,32,115,105,122,101,32,105,110,32,98,121,116,101,115,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,109,101,109,111,114,121,32,111,102,32,116,121,112,101,32>>,{code,[],[<<84,121,112,101>>]},<<46,32,84,104,101,32,97,114,103,117,109,101,110,116,32,99,97,110,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<109,101,109,111,114,121,95,116,121,112,101,40,41>>]},<<32,97,116,111,109,115,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,97,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,109,101,109,111,114,121,95,116,121,112,101,40,41,44,32,83,105,122,101,32,58,58,32,105,110,116,101,103,101,114,32,62,61,32,48,125>>]},<<32,116,117,112,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,54,46,52,44,32>>,{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,49>>]},<<32,114,101,113,117,105,114,101,115,32,116,104,97,116,32,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,115,32,97,114,101,32,101,110,97,98,108,101,100,32,40,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,41,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,110,111,116,32,111,110,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,116,121,112,101,115,32,108,105,115,116,101,100,32,105,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,101,109,111,114,121,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48>>]}]},<<46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<109,97,120,105,109,117,109>>]},<<32,105,115,32,112,97,115,115,101,100,32,97,115,32>>,{code,[],[<<84,121,112,101>>]},<<32,97,110,100,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,110,111,116,32,114,117,110,32,105,110,32,105,110,115,116,114,117,109,101,110,116,101,100,32,109,111,100,101,46>>]},{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[<<73,102,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<32,97,108,108,111,99,97,116,111,114,32,104,97,115,32,98,101,101,110,32,100,105,115,97,98,108,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,101,109,111,114,121,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,50,55,51>>,signature => [{attribute,{4042,2},spec,{{erlang,memory,1},[{type,{4042,20},'fun',[{type,{4042,20},product,[{ann_type,{4042,21},[{var,{4042,21},'Type'},{user_type,{4042,29},memory_type,[]}]}]},{type,{4042,47},non_neg_integer,[]}]},{type,{4043,20},'fun',[{type,{4043,20},product,[{ann_type,{4043,21},[{var,{4043,21},'TypeList'},{type,{4043,33},list,[{user_type,{4043,34},memory_type,[]}]}]}]},{type,{4043,53},list,[{type,{4043,54},tuple,[{user_type,{4043,55},memory_type,[]},{type,{4043,70},non_neg_integer,[]}]}]}]}]}}]}},{{function,min,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3984}],[<<109,105,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,111,102,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,97,110,100,32>>,{code,[],[<<84,101,114,109,50>>]},<<46,32,73,102,32,116,104,101,32,116,101,114,109,115,32,99,111,109,112,97,114,101,32,101,113,117,97,108,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,44,32>>,{code,[],[<<84,101,114,109,49>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,116,101,114,109,45,99,111,109,112,97,114,105,115,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,120,112,114,101,115,115,105,111,110,115,32,115,101,99,116,105,111,110>>]},<<32,99,111,110,116,97,105,110,115,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,116,104,101,32>>,{code,[],[<<61,61>>]},<<32,111,112,101,114,97,116,111,114,32,97,110,100,32,104,111,119,32,116,101,114,109,115,32,97,114,101,32,111,114,100,101,114,101,100,46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<62,32,109,105,110,40,49,44,32,50,41,46,10,49>>]}]},{pre,[],[{code,[],[<<62,32,109,105,110,40,49,46,48,44,32,49,41,46,10,49,46,48>>]}]},{pre,[],[{code,[],[<<62,32,109,105,110,40,49,44,32,49,46,48,41,46,10,49>>]}]},{pre,[],[{code,[],[<<62,32,109,105,110,40,34,97,98,99,34,44,32,34,98,34,41,46,10,34,97,98,99,34>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,49,51>>,signature => [{attribute,{3984,2},spec,{{min,2},[{type,{3984,10},bounded_fun,[{type,{3984,10},'fun',[{type,{3984,10},product,[{var,{3984,11},'Term1'},{var,{3984,18},'Term2'}]},{var,{3984,28},'Minimum'}]},[{type,{3985,7},constraint,[{atom,{3985,7},is_subtype},[{var,{3985,7},'Term1'},{type,{3985,16},term,[]}]]},{type,{3986,7},constraint,[{atom,{3986,7},is_subtype},[{var,{3986,7},'Term2'},{type,{3986,16},term,[]}]]},{type,{3987,7},constraint,[{atom,{3987,7},is_subtype},[{var,{3987,7},'Minimum'},{type,{3987,18},term,[]}]]}]]}]}}]}},{{function,module_loaded,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1451}],[<<109,111,100,117,108,101,95,108,111,97,100,101,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,108,111,97,100,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,73,116,32,100,111,101,115,32,110,111,116,32,97,116,116,101,109,112,116,32,116,111,32,108,111,97,100,32,116,104,101,32,109,111,100,117,108,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,52,50>>,signature => [{attribute,{1451,2},spec,{{module_loaded,1},[{type,{1451,20},bounded_fun,[{type,{1451,20},'fun',[{type,{1451,20},product,[{var,{1451,21},'Module'}]},{type,{1451,32},boolean,[]}]},[{type,{1452,7},constraint,[{atom,{1452,7},is_subtype},[{var,{1452,7},'Module'},{type,{1452,17},module,[]}]]}]]}]}}]}},{{function,monitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1464}],[<<109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,111,110,105,116,111,114,95,112,111,114,116,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<109,111,110,105,116,111,114,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]}]},{p,[],[{a,[{id,<<109,111,110,105,116,111,114,95,109,101,115,115,97,103,101>>}],[]},<<83,101,110,100,115,32,97,32,109,111,110,105,116,111,114,32,114,101,113,117,101,115,116,32,111,102,32,116,121,112,101,32>>,{code,[],[<<84,121,112,101>>]},<<32,116,111,32,116,104,101,32,101,110,116,105,116,121,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<46,32,73,102,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,111,114,32,105,116,32,99,104,97,110,103,101,115,32,109,111,110,105,116,111,114,101,100,32,115,116,97,116,101,44,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,105,115,32,110,111,116,105,102,105,101,100,32,98,121,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,97,116,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<123,84,97,103,44,32,77,111,110,105,116,111,114,82,101,102,44,32,84,121,112,101,44,32,79,98,106,101,99,116,44,32,73,110,102,111,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,114,101,113,117,101,115,116,32,105,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,115,105,103,110,97,108,46,32,84,104,97,116,32,105,115,44,32,105,116,32,116,97,107,101,115,32,116,105,109,101,32,98,101,102,111,114,101,32,116,104,101,32,115,105,103,110,97,108,32,114,101,97,99,104,101,115,32,105,116,115,32,100,101,115,116,105,110,97,116,105,111,110,46>>]}]},{p,[],[{code,[],[<<84,121,112,101>>]},<<32,99,97,110,32,98,101,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,58,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<44,32>>,{code,[],[<<112,111,114,116>>]},<<32,111,114,32>>,{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]},<<46>>]},{p,[],[<<65,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116>>]},<<32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,111,110,108,121,32,111,110,99,101,44,32,97,102,116,101,114,32,116,104,97,116,32,105,116,32,105,115,32,114,101,109,111,118,101,100,32,102,114,111,109,32,98,111,116,104,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,46,32,77,111,110,105,116,111,114,115,32,97,114,101,32,102,105,114,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,116,101,114,109,105,110,97,116,101,115,44,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,97,116,32,116,104,101,32,109,111,109,101,110,116,32,111,102,32,99,114,101,97,116,105,111,110,44,32,111,114,32,105,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,105,116,32,105,115,32,108,111,115,116,46,32,73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,105,116,32,105,115,32,108,111,115,116,44,32,119,101,32,100,111,32,110,111,116,32,107,110,111,119,32,105,102,32,105,116,32,115,116,105,108,108,32,101,120,105,115,116,115,46,32,84,104,101,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,97,108,115,111,32,116,117,114,110,101,100,32,111,102,102,32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<100,101,109,111,110,105,116,111,114,47,49>>]},<<32,105,115,32,99,97,108,108,101,100,46>>]},{p,[],[<<65,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116>>]},<<32,109,111,110,105,116,111,114,32,98,121,32,110,97,109,101,32,114,101,115,111,108,118,101,115,32,116,104,101,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,116,111,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<32,111,110,108,121,32,111,110,99,101,32,97,116,32,116,104,101,32,109,111,109,101,110,116,32,111,102,32,109,111,110,105,116,111,114,32,105,110,115,116,97,110,116,105,97,116,105,111,110,44,32,108,97,116,101,114,32,99,104,97,110,103,101,115,32,116,111,32,116,104,101,32,110,97,109,101,32,114,101,103,105,115,116,114,97,116,105,111,110,32,119,105,108,108,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,101,120,105,115,116,105,110,103,32,109,111,110,105,116,111,114,46>>]},{p,[],[<<87,104,101,110,32,97,32>>,{code,[],[<<112,114,111,99,101,115,115>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116>>]},<<32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,44,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,104,97,116,32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<123,39,68,79,87,78,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,84,121,112,101,44,32,79,98,106,101,99,116,44,32,73,110,102,111,125>>]}]},{p,[],[<<73,110,32,116,104,101,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<32,97,110,100,32>>,{code,[],[<<84,121,112,101>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,44,32,97,110,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<79,98,106,101,99,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,101,100,32,101,110,116,105,116,121,44,32,119,104,105,99,104,32,116,114,105,103,103,101,114,101,100,32,116,104,101,32,101,118,101,110,116,46,32,87,104,101,110,32,109,111,110,105,116,111,114,105,110,103,32,97,32,112,114,111,99,101,115,115,32,111,114,32,97,32,108,111,99,97,108,32,112,111,114,116,44,32>>,{code,[],[<<79,98,106,101,99,116>>]},<<32,119,105,108,108,32,98,101,32,101,113,117,97,108,32,116,111,32,116,104,101,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<32,116,104,97,116,32,119,97,115,32,98,101,105,110,103,32,109,111,110,105,116,111,114,101,100,46,32,87,104,101,110,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,98,121,32,110,97,109,101,44,32>>,{code,[],[<<79,98,106,101,99,116>>]},<<32,119,105,108,108,32,104,97,118,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,82,101,103,105,115,116,101,114,101,100,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,119,104,105,99,104,32,104,97,115,32,98,101,101,110,32,117,115,101,100,32,119,105,116,104,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,99,97,108,108,32,97,110,100,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,108,111,99,97,108,32,111,114,32,114,101,109,111,116,101,32,110,111,100,101,32,110,97,109,101,32,40,102,111,114,32,112,111,114,116,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,110,97,109,101,44,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,97,108,119,97,121,115,32,108,111,99,97,108,32,110,111,100,101,32,110,97,109,101,41,46>>]}]},{dt,[],[{code,[],[<<73,110,102,111>>]}]},{dd,[],[{p,[],[<<69,105,116,104,101,114,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,44,32>>,{code,[],[<<110,111,112,114,111,99>>]},<<32,40,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,100,105,100,32,110,111,116,32,101,120,105,115,116,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,109,111,110,105,116,111,114,32,99,114,101,97,116,105,111,110,41,44,32,111,114,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,40,110,111,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,101,32,110,111,100,101,32,119,104,101,114,101,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,32,114,101,115,105,100,101,115,41,46>>]}]}]},{dl,[],[{dt,[],[<<77,111,110,105,116,111,114,105,110,103,32,97,32>>,{a,[{id,<<109,111,110,105,116,111,114,95,112,114,111,99,101,115,115>>}],[]},{code,[],[<<112,114,111,99,101,115,115>>]}]},{dd,[],[{p,[],[<<67,114,101,97,116,101,115,32,109,111,110,105,116,111,114,32,98,101,116,119,101,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,97,110,100,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,40,108,111,99,97,108,32,111,114,32,114,101,109,111,116,101,41,44,32,97,110,32,97,116,111,109,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,111,114,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,82,101,103,105,115,116,101,114,101,100,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,102,111,114,32,97,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,44,32,108,111,99,97,116,101,100,32,101,108,115,101,119,104,101,114,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,101,102,111,114,101,32,69,82,84,83,32,49,48,46,48,32,40,79,84,80,32,50,49,46,48,41,44,32,109,111,110,105,116,111,114,105,110,103,32,97,32,112,114,111,99,101,115,115,32,99,111,117,108,100,32,102,97,105,108,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,32,114,101,115,105,100,101,100,32,111,110,32,97,32,112,114,105,109,105,116,105,118,101,32,110,111,100,101,32,40,115,117,99,104,32,97,115,32,101,114,108,95,105,110,116,101,114,102,97,99,101,32,111,114,32,106,105,110,116,101,114,102,97,99,101,41,44,32,119,104,101,114,101,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,110,111,116,32,105,109,112,108,101,109,101,110,116,101,100,46>>]},{p,[],[<<78,111,119,44,32,115,117,99,104,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,119,105,108,108,32,105,110,115,116,101,97,100,32,115,117,99,99,101,101,100,32,97,110,100,32,97,32,109,111,110,105,116,111,114,32,105,115,32,99,114,101,97,116,101,100,46,32,66,117,116,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,111,110,108,121,32,115,117,112,101,114,118,105,115,101,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,46,32,84,104,97,116,32,105,115,44,32,97,32>>,{code,[],[<<123,39,68,79,87,78,39,44,32,95,44,32,112,114,111,99,101,115,115,44,32,95,44,32,110,111,99,111,110,110,101,99,116,105,111,110,125>>]},<<32,105,115,32,116,104,101,32,111,110,108,121,32,109,101,115,115,97,103,101,32,116,104,97,116,32,109,97,121,32,98,101,32,114,101,99,101,105,118,101,100,44,32,97,115,32,116,104,101,32,112,114,105,109,105,116,105,118,101,32,110,111,100,101,32,104,97,118,101,32,110,111,32,119,97,121,32,111,102,32,114,101,112,111,114,116,105,110,103,32,116,104,101,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,109,111,110,105,116,111,114,101,100,32,112,114,111,99,101,115,115,46>>]}]}]},{dt,[],[<<77,111,110,105,116,111,114,105,110,103,32,97,32>>,{a,[{id,<<109,111,110,105,116,111,114,95,112,111,114,116>>}],[]},{code,[],[<<112,111,114,116>>]}]},{dd,[],[{p,[],[<<67,114,101,97,116,101,115,32,109,111,110,105,116,111,114,32,98,101,116,119,101,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,97,110,100,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,97,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<32,40,111,110,108,121,32,108,111,99,97,108,41,44,32,97,110,32,97,116,111,109,32>>,{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,111,114,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,82,101,103,105,115,116,101,114,101,100,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,102,111,114,32,97,32,114,101,103,105,115,116,101,114,101,100,32,112,111,114,116,44,32,108,111,99,97,116,101,100,32,111,110,32,116,104,105,115,32,110,111,100,101,46,32,78,111,116,101,44,32,116,104,97,116,32,97,116,116,101,109,112,116,32,116,111,32,109,111,110,105,116,111,114,32,97,32,114,101,109,111,116,101,32,112,111,114,116,32,119,105,108,108,32,114,101,115,117,108,116,32,105,110,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46>>]}]},{dt,[],[<<77,111,110,105,116,111,114,105,110,103,32,97,32>>,{a,[{id,<<109,111,110,105,116,111,114,95,116,105,109,101,95,111,102,102,115,101,116>>}],[]},{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]}]},{dd,[],[{p,[],[<<77,111,110,105,116,111,114,115,32,99,104,97,110,103,101,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,105,109,101,32,111,102,102,115,101,116>>]}]},<<32,98,101,116,119,101,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<46,32,79,110,101,32,118,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,101,120,105,115,116,115,32,105,110,32,99,111,109,98,105,110,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<116,105,109,101,95,111,102,102,115,101,116,32,84,121,112,101>>]},<<44,32,110,97,109,101,108,121,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<99,108,111,99,107,95,115,101,114,118,105,99,101>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<99,108,111,99,107,95,115,101,114,118,105,99,101>>]},<<32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,32,112,114,111,99,101,115,115,46,32,73,110,32,116,104,105,115,32,99,97,115,101,32,105,116,32,115,101,114,118,101,115,32,97,115,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,116,101,114,110,97,108,32,99,108,111,99,107,32,115,101,114,118,105,99,101,32,97,116,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,119,104,101,110,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,46,32,84,104,105,115,32,101,105,116,104,101,114,32,105,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,118,97,108,117,101,32,105,115,32,99,104,97,110,103,101,100,44,32,111,114,32,105,102,32,116,104,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,32,102,114,111,109,32,112,114,101,108,105,109,105,110,97,114,121,32,116,111,32,102,105,110,97,108,32,100,117,114,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,116,105,109,101,95,111,102,102,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,110,97,108,105,122,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116>>]},<<32,119,104,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46,32,87,104,101,110,32,97,32,99,104,97,110,103,101,32,102,114,111,109,32,112,114,101,108,105,109,105,110,97,114,121,32,116,111,32,102,105,110,97,108,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,109,97,100,101,44,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,111,110,99,101,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,118,97,108,117,101,32,119,97,115,32,99,104,97,110,103,101,100,32,111,114,32,110,111,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,32,119,104,101,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,101,116,101,99,116,115,32,116,104,97,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,104,97,115,32,99,104,97,110,103,101,100,46,32,84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,111,101,115,44,32,104,111,119,101,118,101,114,44,32,110,111,116,32,100,101,116,101,99,116,32,116,104,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,119,104,101,110,32,105,116,32,111,99,99,117,114,115,46,32,65,32,116,97,115,107,32,99,104,101,99,107,105,110,103,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,101,120,101,99,117,116,101,32,97,116,32,108,101,97,115,116,32,111,110,99,101,32,97,32,109,105,110,117,116,101,44,32,115,111,32,117,110,100,101,114,32,110,111,114,109,97,108,32,111,112,101,114,97,116,105,111,110,32,116,104,105,115,32,105,115,32,116,111,32,98,101,32,100,101,116,101,99,116,101,100,32,119,105,116,104,105,110,32,97,32,109,105,110,117,116,101,44,32,98,117,116,32,100,117,114,105,110,103,32,104,101,97,118,121,32,108,111,97,100,32,105,116,32,99,97,110,32,116,97,107,101,32,108,111,110,103,101,114,32,116,105,109,101,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,32,97,102,116,101,114,32,105,116,32,104,97,115,32,98,101,101,110,32,116,114,105,103,103,101,114,101,100,46,32,84,104,97,116,32,105,115,44,32,114,101,112,101,97,116,101,100,32,99,104,97,110,103,101,115,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,116,114,105,103,103,101,114,32,116,104,101,32,109,111,110,105,116,111,114,32,114,101,112,101,97,116,101,100,108,121,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,32,97,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,46,32,65,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<123,39,67,72,65,78,71,69,39,44,32,77,111,110,105,116,111,114,82,101,102,44,32,84,121,112,101,44,32,73,116,101,109,44,32,78,101,119,84,105,109,101,79,102,102,115,101,116,125>>]}]},{p,[],[<<119,104,101,114,101,32>>,{code,[],[<<77,111,110,105,116,111,114,82,101,102>>]},<<44,32>>,{code,[],[<<84,121,112,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,44,32,97,110,100,32>>,{code,[],[<<78,101,119,84,105,109,101,79,102,102,115,101,116>>]},<<32,105,115,32,116,104,101,32,110,101,119,32,116,105,109,101,32,111,102,102,115,101,116,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,32,104,97,115,32,98,101,101,110,32,114,101,99,101,105,118,101,100,32,121,111,117,32,97,114,101,32,103,117,97,114,97,110,116,101,101,100,32,110,111,116,32,116,111,32,114,101,116,114,105,101,118,101,32,116,104,101,32,111,108,100,32,116,105,109,101,32,111,102,102,115,101,116,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]}]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,121,111,117,32,99,97,110,32,111,98,115,101,114,118,101,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]},<<32,98,101,102,111,114,101,32,121,111,117,32,103,101,116,32,116,104,101,32>>,{code,[],[<<39,67,72,65,78,71,69,39>>]},<<32,109,101,115,115,97,103,101,46>>]}]}]},{p,[],[<<77,97,107,105,110,103,32,115,101,118,101,114,97,108,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,102,111,114,32,116,104,101,32,115,97,109,101,32>>,{code,[],[<<73,116,101,109>>]},<<32,97,110,100,47,111,114,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,114,114,111,114,59,32,105,116,32,114,101,115,117,108,116,115,32,105,110,32,97,115,32,109,97,110,121,32,105,110,100,101,112,101,110,100,101,110,116,32,109,111,110,105,116,111,114,105,110,103,32,105,110,115,116,97,110,99,101,115,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,101,120,116,101,110,100,101,100,46,32,84,104,97,116,32,105,115,44,32,111,116,104,101,114,32>>,{code,[],[<<84,121,112,101>>]},<<115,32,97,110,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,115,117,112,112,111,114,116,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,111,114,32,119,104,101,110,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<32,105,115,32,101,120,116,101,110,100,101,100,44,32,111,116,104,101,114,32,112,111,115,115,105,98,108,101,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<84,97,103>>]},<<44,32>>,{code,[],[<<79,98,106,101,99,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,110,32,116,104,101,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,105,110,116,114,111,100,117,99,101,100,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,51,53,55>>,signature => [{attribute,{1464,2},spec,{{monitor,2},[{type,{1465,7},bounded_fun,[{type,{1465,7},'fun',[{type,{1465,7},product,[{atom,{1465,8},process},{user_type,{1465,17},monitor_process_identifier,[]}]},{var,{1465,50},'MonitorRef'}]},[{type,{1466,9},constraint,[{atom,{1466,9},is_subtype},[{var,{1466,9},'MonitorRef'},{type,{1466,23},reference,[]}]]}]]},{type,{1467,7},bounded_fun,[{type,{1467,7},'fun',[{type,{1467,7},product,[{atom,{1467,8},port},{user_type,{1467,14},monitor_port_identifier,[]}]},{var,{1467,44},'MonitorRef'}]},[{type,{1468,9},constraint,[{atom,{1468,9},is_subtype},[{var,{1468,9},'MonitorRef'},{type,{1468,23},reference,[]}]]}]]},{type,{1469,7},bounded_fun,[{type,{1469,7},'fun',[{type,{1469,7},product,[{atom,{1469,8},time_offset},{atom,{1469,21},clock_service}]},{var,{1469,39},'MonitorRef'}]},[{type,{1470,9},constraint,[{atom,{1470,9},is_subtype},[{var,{1470,9},'MonitorRef'},{type,{1470,23},reference,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48,44,79,84,80,32,49,57,46,48>>}},{{function,monitor,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1476}],[<<109,111,110,105,116,111,114,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,111,110,105,116,111,114,95,112,111,114,116,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<109,111,110,105,116,111,114,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>}],[]},{li,[{name,<<114,101,103,105,115,116,101,114,101,100,95,112,114,111,99,101,115,115,95,105,100,101,110,116,105,102,105,101,114>>}],[]}]},{p,[],[<<80,114,111,118,105,100,101,115,32,97,110,32,111,112,116,105,111,110,32,108,105,115,116,32,102,111,114,32,109,111,100,105,102,105,99,97,116,105,111,110,32,111,102,32,109,111,110,105,116,111,114,105,110,103,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,112,114,111,118,105,100,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,50>>]}]},<<46,32,84,104,101,32>>,{code,[],[<<84,121,112,101>>]},<<32,97,110,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,97,114,103,117,109,101,110,116,115,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,109,101,97,110,105,110,103,32,97,115,32,119,104,101,110,32,112,97,115,115,101,100,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<46,32,67,117,114,114,101,110,116,108,121,32,97,118,97,105,108,97,98,108,101,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,108,105,97,115,44,32,85,110,97,108,105,97,115,79,112,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,109,111,110,105,116,111,114,32,114,101,102,101,114,101,110,99,101,32,119,105,108,108,32,97,108,115,111,32,98,101,99,111,109,101,32,97,110,32,97,108,105,97,115,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,97,108,105,97,115,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,108,105,97,115,47,48>>]}]},<<46,32,84,104,101,32>>,{code,[],[<<85,110,97,108,105,97,115,79,112,116>>]},<<32,100,101,116,101,114,109,105,110,101,115,32,104,111,119,32,116,104,101,32,97,108,105,97,115,32,115,104,111,117,108,100,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,46>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,112,108,105,99,105,116,95,117,110,97,108,105,97,115>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,97,110,32,101,120,112,108,105,99,105,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,97,108,105,97,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,97,108,105,97,115,47,49>>]}]},<<32,119,105,108,108,32,100,101,97,99,116,105,118,97,116,101,32,116,104,101,32,97,108,105,97,115,46>>]}]},{dt,[],[{code,[],[<<100,101,109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,114,101,109,111,118,101,100,46,32,84,104,105,115,32,101,105,116,104,101,114,32,118,105,97,32,97,110,32,101,120,112,108,105,99,105,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,101,109,111,110,105,116,111,114,47,49>>]}]},<<32,111,114,32,119,104,101,110,32,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,32,97,115,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,100,101,108,105,118,101,114,101,100,32,100,117,101,32,116,111,32,116,104,101,32,109,111,110,105,116,111,114,46,32,84,104,101,32,97,108,105,97,115,32,99,97,110,32,97,108,115,111,32,115,116,105,108,108,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46>>]}]},{dt,[],[{code,[],[<<114,101,112,108,121,95,100,101,109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,97,108,105,97,115,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,114,101,109,111,118,101,100,32,40,115,101,101,32>>,{code,[],[<<100,101,109,111,110,105,116,111,114>>]},<<32,111,112,116,105,111,110,32,97,98,111,118,101,41,32,111,114,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,115,101,110,116,32,118,105,97,32,116,104,101,32,97,108,105,97,115,32,105,115,32,114,101,99,101,105,118,101,100,46,32,87,104,101,110,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,105,115,32,114,101,99,101,105,118,101,100,32,118,105,97,32,116,104,101,32,97,108,105,97,115,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,97,108,115,111,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,46,32,84,104,105,115,32,105,115,32,117,115,101,102,117,108,32,105,110,32,99,108,105,101,110,116,47,115,101,114,118,101,114,32,115,99,101,110,97,114,105,111,115,32,119,104,101,110,32,97,32,99,108,105,101,110,116,32,109,111,110,105,116,111,114,115,32,116,104,101,32,115,101,114,118,101,114,32,97,110,100,32,119,105,108,108,32,103,101,116,32,116,104,101,32,114,101,112,108,121,32,118,105,97,32,116,104,101,32,97,108,105,97,115,46,32,79,110,99,101,32,116,104,101,32,114,101,115,112,111,110,115,101,32,105,115,32,114,101,99,101,105,118,101,100,32,98,111,116,104,32,116,104,101,32,97,108,105,97,115,32,97,110,100,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,109,111,118,101,100,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,114,101,115,112,111,110,115,101,32,105,115,32,97,32,114,101,112,108,121,32,111,114,32,97,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,46,32,84,104,101,32,97,108,105,97,115,32,99,97,110,32,97,108,115,111,32,115,116,105,108,108,32,98,101,32,100,101,97,99,116,105,118,97,116,101,100,32,118,105,97,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<46,32,78,111,116,101,32,116,104,97,116,32,105,102,32,116,104,101,32,97,108,105,97,115,32,105,115,32,114,101,109,111,118,101,100,32,117,115,105,110,103,32,116,104,101,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<32,66,73,70,44,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,115,116,105,108,108,32,98,101,32,108,101,102,116,32,97,99,116,105,118,101,46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<115,101,114,118,101,114,40,41,32,45,62,10,32,32,32,32,114,101,99,101,105,118,101,10,32,32,32,32,32,32,32,32,123,114,101,113,117,101,115,116,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,113,117,101,115,116,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,82,101,115,117,108,116,32,61,32,112,101,114,102,111,114,109,95,114,101,113,117,101,115,116,40,82,101,113,117,101,115,116,41,44,10,32,32,32,32,32,32,32,32,32,32,32,32,65,108,105,97,115,82,101,113,73,100,32,33,32,123,114,101,112,108,121,44,32,65,108,105,97,115,82,101,113,73,100,44,32,82,101,115,117,108,116,125,10,32,32,32,32,101,110,100,44,10,32,32,32,32,115,101,114,118,101,114,40,41,46,10,10,99,108,105,101,110,116,40,83,101,114,118,101,114,80,105,100,44,32,82,101,113,117,101,115,116,41,32,45,62,10,32,32,32,32,65,108,105,97,115,77,111,110,82,101,113,73,100,32,61,32,109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,83,101,114,118,101,114,80,105,100,44,32,91,123,97,108,105,97,115,44,32,114,101,112,108,121,95,100,101,109,111,110,105,116,111,114,125,93,41,44,10,32,32,32,32,83,101,114,118,101,114,80,105,100,32,33,32,123,114,101,113,117,101,115,116,44,32,65,108,105,97,115,77,111,110,82,101,113,73,100,44,32,82,101,113,117,101,115,116,125,44,10,32,32,32,32,37,37,32,65,108,105,97,115,32,97,115,32,119,101,108,108,32,97,115,32,109,111,110,105,116,111,114,32,119,105,108,108,32,98,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,97,99,116,105,118,97,116,101,100,32,105,102,32,119,101,10,32,32,32,32,37,37,32,114,101,99,101,105,118,101,32,97,32,114,101,112,108,121,32,111,114,32,97,32,39,68,79,87,78,39,32,109,101,115,115,97,103,101,32,115,105,110,99,101,32,119,101,32,117,115,101,100,32,39,114,101,112,108,121,95,100,101,109,111,110,105,116,111,114,39,10,32,32,32,32,37,37,32,97,115,32,117,110,97,108,105,97,115,32,111,112,116,105,111,110,46,46,46,10,32,32,32,32,114,101,99,101,105,118,101,10,32,32,32,32,32,32,32,32,123,114,101,112,108,121,44,32,65,108,105,97,115,77,111,110,82,101,113,73,100,44,32,82,101,115,117,108,116,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,82,101,115,117,108,116,59,10,32,32,32,32,32,32,32,32,123,39,68,79,87,78,39,44,32,65,108,105,97,115,77,111,110,82,101,113,73,100,44,32,112,114,111,99,101,115,115,44,32,83,101,114,118,101,114,80,105,100,44,32,69,120,105,116,82,101,97,115,111,110,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,101,114,114,111,114,40,69,120,105,116,82,101,97,115,111,110,41,10,32,32,32,32,101,110,100,46,10,9,32,32,32,32>>]}]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,98,111,116,104,32,116,104,101,32,115,101,114,118,101,114,32,97,110,100,32,116,104,101,32,99,108,105,101,110,116,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,32,109,117,115,116,32,98,101,32,101,120,101,99,117,116,105,110,103,32,111,110,32,97,116,32,108,101,97,115,116,32,79,84,80,32,50,52,32,115,121,115,116,101,109,115,32,105,110,32,111,114,100,101,114,32,102,111,114,32,116,104,105,115,32,116,111,32,119,111,114,107,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,111,99,101,115,115,32,97,108,105,97,115,101,115,32,115,101,101,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,112,114,111,99,101,115,115,45,97,108,105,97,115,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{i,[],[<<80,114,111,99,101,115,115,32,65,108,105,97,115,101,115>>]}]},<<32,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,97,103,44,32,85,115,101,114,68,101,102,105,110,101,100,84,97,103,125>>]}]},{dd,[],[{p,[],[<<82,101,112,108,97,99,101,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<84,97,103>>]},<<32,119,105,116,104,32>>,{code,[],[<<85,115,101,114,68,101,102,105,110,101,100,84,97,103>>]},<<32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,111,110,105,116,111,114,32,109,101,115,115,97,103,101>>]},<<32,100,101,108,105,118,101,114,101,100,32,119,104,101,110,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,116,114,105,103,103,101,114,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32,109,111,110,105,116,111,114,105,110,103,32,97,32,112,114,111,99,101,115,115,44,32,116,104,101,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,116,97,103,32,105,110,32,116,104,101,32,100,111,119,110,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,114,101,112,108,97,99,101,100,32,98,121,32>>,{code,[],[<<85,115,101,114,68,101,102,105,110,101,100,84,97,103>>]},<<46>>]},{p,[],[<<65,110,32,101,120,97,109,112,108,101,32,111,102,32,104,111,119,32,116,104,101,32>>,{code,[],[<<123,116,97,103,44,32,85,115,101,114,68,101,102,105,110,101,100,84,97,103,125>>]},<<32,111,112,116,105,111,110,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,32,111,114,100,101,114,32,116,111,32,101,110,97,98,108,101,32,116,104,101,32,110,101,119,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,112,114,111,99,101,115,115,101,115,35,114,101,99,101,105,118,105,110,103,45,109,101,115,115,97,103,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,101,108,101,99,116,105,118,101,32,114,101,99,101,105,118,101,32,111,112,116,105,109,105,122,97,116,105,111,110>>]},<<44,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,79,84,80,32,50,52,44,32,119,104,101,110,32,109,97,107,105,110,103,32,109,117,108,116,105,112,108,101,32,114,101,113,117,101,115,116,115,32,116,111,32,100,105,102,102,101,114,101,110,116,32,115,101,114,118,101,114,115,58>>]},{pre,[],[{code,[],[<<115,101,114,118,101,114,40,41,32,45,62,10,32,32,32,32,114,101,99,101,105,118,101,10,32,32,32,32,32,32,32,32,123,114,101,113,117,101,115,116,44,32,70,114,111,109,44,32,82,101,113,73,100,44,32,82,101,113,117,101,115,116,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,82,101,115,117,108,116,32,61,32,112,101,114,102,111,114,109,95,114,101,113,117,101,115,116,40,82,101,113,117,101,115,116,41,44,10,32,32,32,32,32,32,32,32,32,32,32,32,70,114,111,109,32,33,32,123,114,101,112,108,121,44,32,115,101,108,102,40,41,44,32,82,101,113,73,100,44,32,82,101,115,117,108,116,125,10,32,32,32,32,101,110,100,44,10,32,32,32,32,115,101,114,118,101,114,40,41,46,10,10,99,108,105,101,110,116,40,83,101,114,118,101,114,80,105,100,115,44,32,82,101,113,117,101,115,116,41,32,119,104,101,110,32,105,115,95,108,105,115,116,40,83,101,114,118,101,114,80,105,100,115,41,32,45,62,10,32,32,32,32,82,101,113,73,100,32,61,32,109,97,107,101,95,114,101,102,40,41,44,10,32,32,32,32,108,105,115,116,115,58,102,111,114,101,97,99,104,40,102,117,110,32,40,83,101,114,118,101,114,80,105,100,41,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,95,32,61,32,109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,83,101,114,118,101,114,80,105,100,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,91,123,116,97,103,44,32,123,39,68,79,87,78,39,44,32,82,101,113,73,100,125,125,93,41,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,83,101,114,118,101,114,80,105,100,32,33,32,123,114,101,113,117,101,115,116,44,32,115,101,108,102,40,41,44,32,82,101,113,73,100,44,32,82,101,113,117,101,115,116,125,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,110,100,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,83,101,114,118,101,114,80,105,100,115,41,44,10,32,32,32,32,114,101,99,101,105,118,101,95,114,101,112,108,105,101,115,40,82,101,113,73,100,44,32,108,101,110,103,116,104,40,83,101,114,118,101,114,80,105,100,115,41,44,32,91,93,41,46,10,10,114,101,99,101,105,118,101,95,114,101,112,108,105,101,115,40,95,82,101,113,73,100,44,32,48,44,32,65,99,99,41,32,45,62,10,32,32,32,32,65,99,99,59,10,114,101,99,101,105,118,101,95,114,101,112,108,105,101,115,40,82,101,113,73,100,44,32,78,44,32,65,99,99,41,32,45,62,10,32,32,32,32,37,37,32,84,104,101,32,99,111,109,112,105,108,101,114,32,119,105,108,108,32,100,101,116,101,99,116,32,116,104,97,116,32,119,101,32,109,97,116,99,104,32,111,110,32,116,104,101,32,39,82,101,113,73,100,39,10,32,32,32,32,37,37,32,114,101,102,101,114,101,110,99,101,32,105,110,32,97,108,108,32,99,108,97,117,115,101,115,44,32,97,110,100,32,119,105,108,108,32,101,110,97,98,108,101,32,116,104,101,32,115,101,108,101,99,116,105,118,101,10,32,32,32,32,37,37,32,114,101,99,101,105,118,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,119,104,105,99,104,32,109,97,107,101,115,32,116,104,101,32,114,101,99,101,105,118,101,32,97,98,108,101,32,116,111,10,32,32,32,32,37,37,32,115,107,105,112,32,112,97,115,116,32,97,108,108,32,109,101,115,115,97,103,101,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,116,10,32,32,32,32,37,37,32,116,104,101,32,116,105,109,101,32,119,104,101,110,32,116,104,101,32,39,82,101,113,73,100,39,32,114,101,102,101,114,101,110,99,101,32,119,97,115,32,99,114,101,97,116,101,100,46,46,46,10,32,32,32,32,82,101,115,32,61,32,114,101,99,101,105,118,101,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,114,101,112,108,121,44,32,83,101,114,118,101,114,80,105,100,44,32,82,101,113,73,100,44,32,82,101,115,117,108,116,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,37,37,32,72,101,114,101,32,119,101,32,116,121,112,105,99,97,108,108,121,32,119,111,117,108,100,32,104,97,118,101,32,100,101,97,99,116,105,118,97,116,101,100,32,116,104,101,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,37,37,32,109,111,110,105,116,111,114,32,98,121,32,97,32,99,97,108,108,32,116,111,32,100,101,109,111,110,105,116,111,114,40,77,111,110,44,32,91,102,108,117,115,104,93,41,32,98,117,116,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,37,37,32,119,101,32,105,103,110,111,114,101,32,116,104,105,115,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,32,102,111,114,32,115,105,109,112,108,105,99,105,116,121,46,46,46,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,111,107,44,32,83,101,114,118,101,114,80,105,100,44,32,82,101,115,117,108,116,125,59,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,123,39,68,79,87,78,39,44,32,82,101,113,73,100,125,44,32,95,77,111,110,44,32,112,114,111,99,101,115,115,44,32,83,101,114,118,101,114,80,105,100,44,32,69,120,105,116,82,101,97,115,111,110,125,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,123,101,114,114,111,114,44,32,83,101,114,118,101,114,80,105,100,44,32,69,120,105,116,82,101,97,115,111,110,125,10,32,32,32,32,32,32,32,32,32,32,101,110,100,44,10,32,32,32,32,114,101,99,101,105,118,101,95,114,101,112,108,105,101,115,40,82,101,113,73,100,44,32,78,45,49,44,32,91,82,101,115,32,124,32,65,99,99,93,41,46,10,9,32,32,32,32>>]}]},{p,[],[<<73,110,32,111,114,100,101,114,32,102,111,114,32,116,104,105,115,32,101,120,97,109,112,108,101,32,116,111,32,119,111,114,107,32,97,115,32,105,110,116,101,110,100,101,100,44,32,116,104,101,32,99,108,105,101,110,116,32,109,117,115,116,32,98,101,32,101,120,101,99,117,116,105,110,103,32,111,110,32,97,116,32,108,101,97,115,116,32,97,110,32,79,84,80,32,50,52,32,115,121,115,116,101,109,44,32,98,117,116,32,116,104,101,32,115,101,114,118,101,114,115,32,109,97,121,32,101,120,101,99,117,116,101,32,111,110,32,111,108,100,101,114,32,115,121,115,116,101,109,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,53,51,51>>,signature => [{attribute,{1476,2},spec,{{monitor,3},[{type,{1477,7},bounded_fun,[{type,{1477,7},'fun',[{type,{1477,7},product,[{atom,{1477,8},process},{user_type,{1477,17},monitor_process_identifier,[]},{type,{1477,47},list,[{user_type,{1477,48},monitor_option,[]}]}]},{var,{1477,70},'MonitorRef'}]},[{type,{1478,9},constraint,[{atom,{1478,9},is_subtype},[{var,{1478,9},'MonitorRef'},{type,{1478,23},reference,[]}]]}]]},{type,{1479,7},bounded_fun,[{type,{1479,7},'fun',[{type,{1479,7},product,[{atom,{1479,8},port},{user_type,{1479,14},monitor_port_identifier,[]},{type,{1479,41},list,[{user_type,{1479,42},monitor_option,[]}]}]},{var,{1479,64},'MonitorRef'}]},[{type,{1480,9},constraint,[{atom,{1480,9},is_subtype},[{var,{1480,9},'MonitorRef'},{type,{1480,23},reference,[]}]]}]]},{type,{1481,7},bounded_fun,[{type,{1481,7},'fun',[{type,{1481,7},product,[{atom,{1481,8},time_offset},{atom,{1481,21},clock_service},{type,{1481,36},list,[{user_type,{1481,37},monitor_option,[]}]}]},{var,{1481,59},'MonitorRef'}]},[{type,{1482,9},constraint,[{atom,{1482,9},is_subtype},[{var,{1482,9},'MonitorRef'},{type,{1482,23},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,monitor_node,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1488}],[<<109,111,110,105,116,111,114,95,110,111,100,101,47,50>>],#{<<101,110>> => [{p,[],[<<77,111,110,105,116,111,114,32,116,104,101,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,108,97,103>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,110,46,32,73,102,32>>,{code,[],[<<70,108,97,103>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,109,111,110,105,116,111,114,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,102,102,46>>]},{p,[],[<<77,97,107,105,110,103,32,115,101,118,101,114,97,108,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,95,110,111,100,101,40,78,111,100,101,44,32,116,114,117,101,41>>]},<<32,102,111,114,32,116,104,101,32,115,97,109,101,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,114,114,111,114,59,32,105,116,32,114,101,115,117,108,116,115,32,105,110,32,97,115,32,109,97,110,121,32,105,110,100,101,112,101,110,100,101,110,116,32,109,111,110,105,116,111,114,105,110,103,32,105,110,115,116,97,110,99,101,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,102,97,105,108,115,32,111,114,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,110,111,100,101,100,111,119,110,44,32,78,111,100,101,125>>]},<<32,105,115,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,46,32,73,102,32,97,32,112,114,111,99,101,115,115,32,104,97,115,32,109,97,100,101,32,116,119,111,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<109,111,110,105,116,111,114,95,110,111,100,101,40,78,111,100,101,44,32,116,114,117,101,41>>]},<<32,97,110,100,32>>,{code,[],[<<78,111,100,101>>]},<<32,116,101,114,109,105,110,97,116,101,115,44,32,116,119,111,32>>,{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,109,101,115,115,97,103,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,101,114,101,32,105,115,32,110,111,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32>>,{code,[],[<<78,111,100,101>>]},<<44,32,97,110,32,97,116,116,101,109,112,116,32,105,115,32,109,97,100,101,32,116,111,32,99,114,101,97,116,101,32,111,110,101,46,32,73,102,32,116,104,105,115,32,102,97,105,108,115,44,32,97,32>>,{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,100,101,108,105,118,101,114,101,100,46>>]},{p,[],[<<84,104,101,32,100,101,108,105,118,101,114,121,32,111,102,32,116,104,101,32>>,{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,115,105,103,110,97,108,32,105,115,32,110,111,116,32,111,114,100,101,114,101,100,32,119,105,116,104,32,114,101,115,112,101,99,116,32,116,111,32,111,116,104,101,114,32,108,105,110,107,32,111,114,32,109,111,110,105,116,111,114,32,115,105,103,110,97,108,115,32,102,114,111,109,32,116,104,101,32,110,111,100,101,32,116,104,97,116,32,103,111,101,115,32,100,111,119,110,46,32,73,102,32,121,111,117,32,110,101,101,100,32,97,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,97,108,108,32,115,105,103,110,97,108,115,32,102,114,111,109,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,32,104,97,115,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,101,32>>,{code,[],[<<110,111,100,101,100,111,119,110>>]},<<32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,44,32,121,111,117,32,115,104,111,117,108,100,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,110,101,116,95,107,101,114,110,101,108,35,109,111,110,105,116,111,114,95,110,111,100,101,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,101,116,95,107,101,114,110,101,108,58,109,111,110,105,116,111,114,95,110,111,100,101,115,47,49>>]}]},<<46>>]},{p,[],[<<78,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,104,114,111,117,103,104,32,104,105,100,100,101,110,32,99,111,110,110,101,99,116,105,111,110,115,32,99,97,110,32,98,101,32,109,111,110,105,116,111,114,101,100,32,97,115,32,97,110,121,32,111,116,104,101,114,32,110,111,100,101,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<110,111,116,97,108,105,118,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,54,57,57>>,signature => [{attribute,{1488,2},spec,{{monitor_node,2},[{type,{1488,19},bounded_fun,[{type,{1488,19},'fun',[{type,{1488,19},product,[{var,{1488,20},'Node'},{var,{1488,26},'Flag'}]},{atom,{1488,35},true}]},[{type,{1489,7},constraint,[{atom,{1489,7},is_subtype},[{var,{1489,7},'Node'},{type,{1489,15},node,[]}]]},{type,{1490,7},constraint,[{atom,{1490,7},is_subtype},[{var,{1490,7},'Flag'},{type,{1490,15},boolean,[]}]]}]]}]}}]}},{{function,monitor_node,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1495}],[<<109,111,110,105,116,111,114,95,110,111,100,101,47,51>>],#{<<101,110>> => [{p,[],[<<66,101,104,97,118,101,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,95,110,111,100,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,95,110,111,100,101,47,50>>]}]},<<32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,97,108,108,111,119,115,32,97,110,32,101,120,116,114,97,32,111,112,116,105,111,110,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,44,32,110,97,109,101,108,121,32>>,{code,[],[<<97,108,108,111,119,95,112,97,115,115,105,118,101,95,99,111,110,110,101,99,116>>]},<<46,32,84,104,105,115,32,111,112,116,105,111,110,32,97,108,108,111,119,115,32,116,104,101,32,66,73,70,32,116,111,32,119,97,105,116,32,116,104,101,32,110,111,114,109,97,108,32,110,101,116,119,111,114,107,32,99,111,110,110,101,99,116,105,111,110,32,116,105,109,101,45,111,117,116,32,102,111,114,32,116,104,101,32>>,{em,[],[<<109,111,110,105,116,111,114,101,100,32,110,111,100,101>>]},<<32,116,111,32,99,111,110,110,101,99,116,32,105,116,115,101,108,102,44,32,101,118,101,110,32,105,102,32,105,116,32,99,97,110,110,111,116,32,98,101,32,97,99,116,105,118,101,108,121,32,99,111,110,110,101,99,116,101,100,32,102,114,111,109,32,116,104,105,115,32,110,111,100,101,32,40,116,104,97,116,32,105,115,44,32,105,116,32,105,115,32,98,108,111,99,107,101,100,41,46,32,84,104,101,32,115,116,97,116,101,32,119,104,101,114,101,32,116,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,99,97,110,32,111,110,108,121,32,98,101,32,97,99,104,105,101,118,101,100,32,98,121,32,117,115,105,110,103,32,116,104,101,32,75,101,114,110,101,108,32,111,112,116,105,111,110,32>>,{code,[],[<<100,105,115,116,95,97,117,116,111,95,99,111,110,110,101,99,116,32,111,110,99,101>>]},<<46,32,73,102,32,116,104,97,116,32,111,112,116,105,111,110,32,105,115,32,110,111,116,32,117,115,101,100,44,32,111,112,116,105,111,110,32>>,{code,[],[<<97,108,108,111,119,95,112,97,115,115,105,118,101,95,99,111,110,110,101,99,116>>]},<<32,104,97,115,32,110,111,32,101,102,102,101,99,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<97,108,108,111,119,95,112,97,115,115,105,118,101,95,99,111,110,110,101,99,116>>]},<<32,105,115,32,117,115,101,100,32,105,110,116,101,114,110,97,108,108,121,32,97,110,100,32,105,115,32,115,101,108,100,111,109,32,110,101,101,100,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,115,32,119,104,101,114,101,32,116,104,101,32,110,101,116,119,111,114,107,32,116,111,112,111,108,111,103,121,32,97,110,100,32,116,104,101,32,75,101,114,110,101,108,32,111,112,116,105,111,110,115,32,105,110,32,101,102,102,101,99,116,32,97,114,101,32,107,110,111,119,110,32,105,110,32,97,100,118,97,110,99,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,32,111,114,32,116,104,101,32,111,112,116,105,111,110,32,108,105,115,116,32,105,115,32,109,97,108,102,111,114,109,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,55,50,57>>,signature => [{attribute,{1495,2},spec,{{erlang,monitor_node,3},[{type,{1495,26},bounded_fun,[{type,{1495,26},'fun',[{type,{1495,26},product,[{var,{1495,27},'Node'},{var,{1495,33},'Flag'},{var,{1495,39},'Options'}]},{atom,{1495,51},true}]},[{type,{1496,7},constraint,[{atom,{1496,7},is_subtype},[{var,{1496,7},'Node'},{type,{1496,15},node,[]}]]},{type,{1497,7},constraint,[{atom,{1497,7},is_subtype},[{var,{1497,7},'Flag'},{type,{1497,15},boolean,[]}]]},{type,{1498,7},constraint,[{atom,{1498,7},is_subtype},[{var,{1498,7},'Options'},{type,{1498,18},list,[{var,{1498,19},'Option'}]}]]},{type,{1499,7},constraint,[{atom,{1499,7},is_subtype},[{var,{1499,7},'Option'},{atom,{1499,17},allow_passive_connect}]]}]]}]}}]}},{{function,monotonic_time,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1597}],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46,32,84,104,105,115,32,105,115,32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,115,105,110,99,101,32,115,111,109,101,32,117,110,115,112,101,99,105,102,105,101,100,32,112,111,105,110,116,32,105,110,32,116,105,109,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,105,115,32,97,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,111,110,111,116,111,110,105,99,97,108,108,121,95,73,110,99,114,101,97,115,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103>>]},<<32,116,105,109,101,44,32,98,117,116,32>>,{em,[],[<<110,111,116>>]},<<32,97,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,116,114,105,99,116,108,121,95,77,111,110,111,116,111,110,105,99,97,108,108,121,95,73,110,99,114,101,97,115,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103>>]},<<32,116,105,109,101,46,32,84,104,97,116,32,105,115,44,32,99,111,110,115,101,99,117,116,105,118,101,32,99,97,108,108,115,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>]},<<32,99,97,110,32,112,114,111,100,117,99,101,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,46>>]},{p,[],[<<68,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,115,32,119,105,108,108,32,117,115,101,32,100,105,102,102,101,114,101,110,116,32,117,110,115,112,101,99,105,102,105,101,100,32,112,111,105,110,116,115,32,105,110,32,116,105,109,101,32,97,115,32,98,97,115,101,32,102,111,114,32,116,104,101,105,114,32,69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,99,108,111,99,107,115,46,32,84,104,97,116,32,105,115,44,32,105,116,32,105,115,32>>,{em,[],[<<112,111,105,110,116,108,101,115,115>>]},<<32,99,111,109,112,97,114,105,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,115,32,102,114,111,109,32,100,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,115,46,32,68,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,115,32,99,97,110,32,97,108,115,111,32,112,108,97,99,101,32,116,104,105,115,32,117,110,115,112,101,99,105,102,105,101,100,32,112,111,105,110,116,32,105,110,32,116,105,109,101,32,100,105,102,102,101,114,101,110,116,32,114,101,108,97,116,105,118,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,46,32,73,116,32,99,97,110,32,98,101,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,32,40,116,105,109,101,32,97,116,32,115,116,97,114,116,32,105,115,32,97,32,110,101,103,97,116,105,118,101,32,118,97,108,117,101,41,44,32,116,104,101,32,112,97,115,116,32,40,116,105,109,101,32,97,116,32,115,116,97,114,116,32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,118,97,108,117,101,41,44,32,111,114,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,32,40,116,105,109,101,32,97,116,32,115,116,97,114,116,32,105,115,32,122,101,114,111,41,46,32,84,104,101,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,97,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,116,97,114,116,95,116,105,109,101,41>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,55,53,53>>,signature => [{attribute,{1597,2},spec,{{erlang,monotonic_time,0},[{type,{1597,28},'fun',[{type,{1597,28},product,[]},{type,{1597,34},integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,monotonic_time,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1602}],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,99,111,110,118,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32>>,{code,[],[<<85,110,105,116>>]},<<32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{p,[],[<<83,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]}]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<32>>,{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,41>>]}]},{code,[],[<<44,32,110,97,116,105,118,101,44,32,85,110,105,116,41>>]},<<44,32,104,111,119,101,118,101,114,32,111,112,116,105,109,105,122,101,100,32,102,111,114,32,99,111,109,109,111,110,108,121,32,117,115,101,100,32>>,{code,[],[<<85,110,105,116>>]},<<115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,55,56,57>>,signature => [{attribute,{1602,2},spec,{{erlang,monotonic_time,1},[{type,{1602,28},bounded_fun,[{type,{1602,28},'fun',[{type,{1602,28},product,[{var,{1602,29},'Unit'}]},{type,{1602,38},integer,[]}]},[{type,{1603,7},constraint,[{atom,{1603,7},is_subtype},[{var,{1603,7},'Unit'},{user_type,{1603,15},time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,nif_error,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1505}],[<<110,105,102,95,101,114,114,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<87,111,114,107,115,32,101,120,97,99,116,108,121,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,47,49>>]}]},<<44,32,98,117,116,32,68,105,97,108,121,122,101,114,32,116,104,105,110,107,115,32,116,104,97,116,32,116,104,105,115,32,66,73,70,32,119,105,108,108,32,114,101,116,117,114,110,32,97,110,32,97,114,98,105,116,114,97,114,121,32,116,101,114,109,46,32,87,104,101,110,32,117,115,101,100,32,105,110,32,97,32,115,116,117,98,32,102,117,110,99,116,105,111,110,32,102,111,114,32,97,32,78,73,70,32,116,111,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,32,119,104,101,110,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,32,105,115,32,110,111,116,32,108,111,97,100,101,100,44,32,68,105,97,108,121,122,101,114,32,100,111,101,115,32,110,111,116,32,103,101,110,101,114,97,116,101,32,102,97,108,115,101,32,119,97,114,110,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,48,55>>,signature => [{attribute,{1505,2},spec,{{erlang,nif_error,1},[{type,{1505,23},bounded_fun,[{type,{1505,23},'fun',[{type,{1505,23},product,[{var,{1505,24},'Reason'}]},{type,{1505,35},no_return,[]}]},[{type,{1506,7},constraint,[{atom,{1506,7},is_subtype},[{var,{1506,7},'Reason'},{type,{1506,17},term,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,nif_error,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1512}],[<<110,105,102,95,101,114,114,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<87,111,114,107,115,32,101,120,97,99,116,108,121,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,114,114,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,114,111,114,47,50>>]}]},<<44,32,98,117,116,32,68,105,97,108,121,122,101,114,32,116,104,105,110,107,115,32,116,104,97,116,32,116,104,105,115,32,66,73,70,32,119,105,108,108,32,114,101,116,117,114,110,32,97,110,32,97,114,98,105,116,114,97,114,121,32,116,101,114,109,46,32,87,104,101,110,32,117,115,101,100,32,105,110,32,97,32,115,116,117,98,32,102,117,110,99,116,105,111,110,32,102,111,114,32,97,32,78,73,70,32,116,111,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,32,119,104,101,110,32,116,104,101,32,78,73,70,32,108,105,98,114,97,114,121,32,105,115,32,110,111,116,32,108,111,97,100,101,100,44,32,68,105,97,108,121,122,101,114,32,100,111,101,115,32,110,111,116,32,103,101,110,101,114,97,116,101,32,102,97,108,115,101,32,119,97,114,110,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,50,48>>,signature => [{attribute,{1512,2},spec,{{erlang,nif_error,2},[{type,{1512,23},bounded_fun,[{type,{1512,23},'fun',[{type,{1512,23},product,[{var,{1512,24},'Reason'},{var,{1512,32},'Args'}]},{type,{1512,41},no_return,[]}]},[{type,{1513,7},constraint,[{atom,{1513,7},is_subtype},[{var,{1513,7},'Reason'},{type,{1513,17},term,[]}]]},{type,{1514,7},constraint,[{atom,{1514,7},is_subtype},[{var,{1514,7},'Args'},{type,{1514,15},list,[{type,{1514,16},term,[]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,node,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1520}],[<<110,111,100,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,73,102,32,116,104,101,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<110,111,110,111,100,101,64,110,111,104,111,115,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,51,51>>,signature => [{attribute,{1520,2},spec,{{node,0},[{type,{1520,11},bounded_fun,[{type,{1520,11},'fun',[{type,{1520,11},product,[]},{var,{1520,17},'Node'}]},[{type,{1521,7},constraint,[{atom,{1521,7},is_subtype},[{var,{1521,7},'Node'},{type,{1521,15},node,[]}]]}]]}]}}]}},{{function,node,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1527}],[<<110,111,100,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,111,100,101,32,119,104,101,114,101,32>>,{code,[],[<<65,114,103>>]},<<32,111,114,105,103,105,110,97,116,101,115,46,32>>,{code,[],[<<65,114,103>>]},<<32,99,97,110,32,98,101,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,97,32,114,101,102,101,114,101,110,99,101,44,32,111,114,32,97,32,112,111,114,116,46,32,73,102,32>>,{code,[],[<<65,114,103>>]},<<32,111,114,105,103,105,110,97,116,101,115,32,102,114,111,109,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,110,100,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<110,111,110,111,100,101,64,110,111,104,111,115,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,52,51>>,signature => [{attribute,{1527,2},spec,{{node,1},[{type,{1527,11},bounded_fun,[{type,{1527,11},'fun',[{type,{1527,11},product,[{var,{1527,12},'Arg'}]},{var,{1527,20},'Node'}]},[{type,{1528,7},constraint,[{atom,{1528,7},is_subtype},[{var,{1528,7},'Arg'},{type,{1528,14},union,[{type,{1528,14},pid,[]},{type,{1528,22},port,[]},{type,{1528,31},reference,[]}]}]]},{type,{1529,7},constraint,[{atom,{1529,7},is_subtype},[{var,{1529,7},'Node'},{type,{1529,15},node,[]}]]}]]}]}}]}},{{function,nodes,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3444}],[<<110,111,100,101,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,108,108,32,110,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,32,116,104,114,111,117,103,104,32,110,111,114,109,97,108,32,99,111,110,110,101,99,116,105,111,110,115,32,40,116,104,97,116,32,105,115,44,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,105,115,116,114,105,98,117,116,101,100,35,104,105,100,100,101,110,45,110,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<104,105,100,100,101,110,32,110,111,100,101,115>>]},<<32,97,114,101,32,110,111,116,32,108,105,115,116,101,100,41,46,32,83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,110,111,100,101,115,95,118,105,115,105,98,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,111,100,101,115,40,118,105,115,105,98,108,101,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,53,54>>,signature => [{attribute,{3444,2},spec,{{nodes,0},[{type,{3444,12},bounded_fun,[{type,{3444,12},'fun',[{type,{3444,12},product,[]},{var,{3444,18},'Nodes'}]},[{type,{3445,7},constraint,[{atom,{3445,7},is_subtype},[{var,{3445,7},'Nodes'},{type,{3445,16},list,[{type,{3445,17},node,[]}]}]]}]]}]}}]}},{{function,nodes,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2371}],[<<110,111,100,101,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,110,111,100,101,115,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102,105,101,100,46,32,84,104,101,32,114,101,116,117,114,110,101,100,32,114,101,115,117,108,116,44,32,119,104,101,110,32,116,104,101,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,108,105,115,116,44,32,105,115,32,116,104,101,32,108,105,115,116,32,111,102,32,110,111,100,101,115,32,115,97,116,105,115,102,121,105,110,103,32,116,104,101,32,100,105,115,106,117,110,99,116,105,111,110,40,115,41,32,111,102,32,116,104,101,32,108,105,115,116,32,101,108,101,109,101,110,116,115,46>>]},{p,[],[{code,[],[<<78,111,100,101,84,121,112,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{a,[{id,<<110,111,100,101,115,95,118,105,115,105,98,108,101>>}],[]},{code,[],[<<118,105,115,105,98,108,101>>]}]},{dd,[],[{p,[],[<<78,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,32,116,104,114,111,117,103,104,32,110,111,114,109,97,108,32,99,111,110,110,101,99,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<104,105,100,100,101,110>>]}]},{dd,[],[{p,[],[<<78,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,32,116,104,114,111,117,103,104,32,104,105,100,100,101,110,32,99,111,110,110,101,99,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<99,111,110,110,101,99,116,101,100>>]}]},{dd,[],[{p,[],[<<65,108,108,32,110,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,105,115,32,110,111,100,101,46>>]}]},{dt,[],[{code,[],[<<116,104,105,115>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,110,111,100,101,46>>]}]},{dt,[],[{code,[],[<<107,110,111,119,110>>]}]},{dd,[],[{p,[],[<<78,111,100,101,115,32,116,104,97,116,32,97,114,101,32,107,110,111,119,110,32,116,111,32,116,104,105,115,32,110,111,100,101,46,32,84,104,97,116,32,105,115,44,32,99,111,110,110,101,99,116,101,100,32,110,111,100,101,115,32,97,110,100,32,110,111,100,101,115,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,44,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,44,32,97,110,100,32,114,101,102,101,114,101,110,99,101,115,32,108,111,99,97,116,101,100,32,111,110,32,116,104,105,115,32,110,111,100,101,46,32,84,104,101,32,115,101,116,32,111,102,32,107,110,111,119,110,32,110,111,100,101,115,32,105,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,99,97,110,32,98,101,32,100,101,108,97,121,101,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99,41>>]}]},<<46>>]}]}]},{p,[],[<<83,111,109,101,32,101,113,117,97,108,105,116,105,101,115,58,32>>,{code,[],[<<91,110,111,100,101,40,41,93,32,61,32,110,111,100,101,115,40,116,104,105,115,41>>]},<<44,32>>,{code,[],[<<110,111,100,101,115,40,99,111,110,110,101,99,116,101,100,41,32,61,32,110,111,100,101,115,40,91,118,105,115,105,98,108,101,44,32,104,105,100,100,101,110,93,41>>]},<<44,32,97,110,100,32>>,{code,[],[<<110,111,100,101,115,40,41,32,61,32,110,111,100,101,115,40,118,105,115,105,98,108,101,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,56,54,56>>,signature => [{attribute,{2371,2},spec,{{nodes,1},[{type,{2371,12},bounded_fun,[{type,{2371,12},'fun',[{type,{2371,12},product,[{var,{2371,13},'Arg'}]},{var,{2371,21},'Nodes'}]},[{type,{2372,7},constraint,[{atom,{2372,7},is_subtype},[{var,{2372,7},'Arg'},{type,{2372,14},union,[{var,{2372,14},'NodeType'},{type,{2372,25},list,[{var,{2372,26},'NodeType'}]}]}]]},{type,{2373,7},constraint,[{atom,{2373,7},is_subtype},[{var,{2373,7},'NodeType'},{type,{2373,19},union,[{atom,{2373,19},visible},{atom,{2373,29},hidden},{atom,{2373,38},connected},{atom,{2373,50},this},{atom,{2373,57},known}]}]]},{type,{2374,7},constraint,[{atom,{2374,7},is_subtype},[{var,{2374,7},'Nodes'},{type,{2374,16},list,[{type,{2374,17},node,[]}]}]]}]]}]}}]}},{{function,now,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1534}],[<<110,111,119,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<116,105,109,101,115,116,97,109,112>>}],[]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[{em,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,68,111,32,110,111,116,32,117,115,101,32,105,116,46>>]}]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<84,105,109,101,32,97,110,100,32,84,105,109,101,32,67,111,114,114,101,99,116,105,111,110>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46,32,83,112,101,99,105,102,105,99,97,108,108,121,44,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,68,111,115,95,97,110,100,95,68,111,110,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<68,111,115,32,97,110,100,32,68,111,110,116,39,115>>]},<<32,100,101,115,99,114,105,98,101,115,32,119,104,97,116,32,116,111,32,117,115,101,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,47,48>>]},<<46>>]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,77,101,103,97,83,101,99,115,44,32,83,101,99,115,44,32,77,105,99,114,111,83,101,99,115,125>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,101,108,97,112,115,101,100,32,116,105,109,101,32,115,105,110,99,101,32,48,48,58,48,48,32,71,77,84,44,32,74,97,110,117,97,114,121,32,49,44,32,49,57,55,48,32,40,122,101,114,111,32,104,111,117,114,41,44,32,105,102,32,112,114,111,118,105,100,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32,115,111,109,101,32,111,116,104,101,114,32,112,111,105,110,116,32,105,110,32,116,105,109,101,32,105,115,32,99,104,111,115,101,110,46,32,73,116,32,105,115,32,97,108,115,111,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,115,32,116,111,32,116,104,105,115,32,66,73,70,32,114,101,116,117,114,110,32,99,111,110,116,105,110,117,111,117,115,108,121,32,105,110,99,114,101,97,115,105,110,103,32,118,97,108,117,101,115,46,32,72,101,110,99,101,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,102,114,111,109,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,47,48>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,103,101,110,101,114,97,116,101,32,117,110,105,113,117,101,32,116,105,109,101,32,115,116,97,109,112,115,46,32,73,102,32,105,116,32,105,115,32,99,97,108,108,101,100,32,105,110,32,97,32,116,105,103,104,116,32,108,111,111,112,32,111,110,32,97,32,102,97,115,116,32,109,97,99,104,105,110,101,44,32,116,104,101,32,116,105,109,101,32,111,102,32,116,104,101,32,110,111,100,101,32,99,97,110,32,98,101,99,111,109,101,32,115,107,101,119,101,100,46>>]},{p,[],[<<67,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,116,111,32,99,104,101,99,107,32,116,104,101,32,108,111,99,97,108,32,116,105,109,101,32,111,102,32,100,97,121,32,105,102,32,116,104,101,32,116,105,109,101,45,122,111,110,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,102,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,32,105,115,32,112,114,111,112,101,114,108,121,32,99,111,110,102,105,103,117,114,101,100,46>>]}]},#{deprecated => <<101,114,108,97,110,103,58,110,111,119,47,48,32,105,115,32,100,101,112,114,101,99,97,116,101,100,59,32,115,101,101,32,116,104,101,32,34,84,105,109,101,32,97,110,100,32,84,105,109,101,32,67,111,114,114,101,99,116,105,111,110,32,105,110,32,69,114,108,97,110,103,34,32,99,104,97,112,116,101,114,32,111,102,32,116,104,101,32,69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110>>,edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,57,49,49>>,signature => [{attribute,{1534,2},spec,{{now,0},[{type,{1534,10},bounded_fun,[{type,{1534,10},'fun',[{type,{1534,10},product,[]},{var,{1534,16},'Timestamp'}]},[{type,{1535,7},constraint,[{atom,{1535,7},is_subtype},[{var,{1535,7},'Timestamp'},{user_type,{1535,20},timestamp,[]}]]}]]}]}}]}},{{function,open_port,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2378}],[<<111,112,101,110,95,112,111,114,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,111,112,101,110,105,110,103,32,97,32,110,101,119,32,69,114,108,97,110,103,32,112,111,114,116,46,32,65,32,112,111,114,116,32,99,97,110,32,98,101,32,115,101,101,110,32,97,115,32,97,110,32,101,120,116,101,114,110,97,108,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<84,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32>>,{code,[],[<<99,100>>]},<<44,32>>,{code,[],[<<101,110,118>>]},<<44,32>>,{code,[],[<<97,114,103,115>>]},<<44,32,97,110,100,32>>,{code,[],[<<97,114,103,48>>]},<<32,97,114,101,32,115,117,98,106,101,99,116,32,116,111,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,116,114,97,110,115,108,97,116,105,111,110,32,105,102,32,116,104,101,32,115,121,115,116,101,109,32,105,115,32,114,117,110,110,105,110,103,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,46,32,84,111,32,97,118,111,105,100,32,116,114,97,110,115,108,97,116,105,111,110,32,111,114,32,116,111,32,102,111,114,99,101,44,32,102,111,114,32,101,120,97,109,112,108,101,32,85,84,70,45,56,44,32,115,117,112,112,108,121,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,97,110,100,47,111,114,32,97,114,103,117,109,101,110,116,115,32,97,115,32,97,32,98,105,110,97,114,121,32,105,110,32,116,104,101,32,99,111,114,114,101,99,116,32,101,110,99,111,100,105,110,103,46,32,70,111,114,32,100,101,116,97,105,108,115,44,32,115,101,101,32,116,104,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,105,108,101,40,51,41>>]}]},<<44,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,105,108,101,58,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>]}]},<<32,105,110,32,75,101,114,110,101,108,44,32,97,110,100,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,95,117,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<85,115,105,110,103,32,85,110,105,99,111,100,101,32,105,110,32,69,114,108,97,110,103>>]}]},<<32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,110,97,109,101,32,40,105,102,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,108,105,115,116,41,32,99,97,110,32,111,110,108,121,32,98,101,32,62,32,50,53,53,32,105,102,32,116,104,101,32,69,114,108,97,110,103,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,105,115,32,115,116,97,114,116,101,100,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,116,114,97,110,115,108,97,116,105,111,110,32,109,111,100,101,46,32,79,116,104,101,114,119,105,115,101,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,105,115,32,108,105,109,105,116,101,100,32,116,111,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,46>>]}]},{p,[],[{code,[],[<<80,111,114,116,78,97,109,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,115,32,97,110,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,32,116,111,32,98,101,32,114,117,110,46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,114,117,110,115,32,111,117,116,115,105,100,101,32,116,104,101,32,69,114,108,97,110,103,32,119,111,114,107,32,115,112,97,99,101,32,117,110,108,101,115,115,32,97,110,32,69,114,108,97,110,103,32,100,114,105,118,101,114,32,119,105,116,104,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32,102,111,117,110,100,44,32,116,104,97,116,32,100,114,105,118,101,114,32,105,115,32,115,116,97,114,116,101,100,46,32,65,32,100,114,105,118,101,114,32,114,117,110,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,119,111,114,107,32,115,112,97,99,101,44,32,119,104,105,99,104,32,109,101,97,110,115,32,116,104,97,116,32,105,116,32,105,115,32,108,105,110,107,101,100,32,119,105,116,104,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<70,111,114,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,115,44,32>>,{code,[],[<<80,65,84,72>>]},<<32,105,115,32,115,101,97,114,99,104,101,100,32,40,111,114,32,97,110,32,101,113,117,105,118,97,108,101,110,116,32,109,101,116,104,111,100,32,105,115,32,117,115,101,100,32,116,111,32,102,105,110,100,32,112,114,111,103,114,97,109,115,44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,79,83,41,46,32,84,104,105,115,32,105,115,32,100,111,110,101,32,98,121,32,105,110,118,111,107,105,110,103,32,116,104,101,32,115,104,101,108,108,32,111,110,32,99,101,114,116,97,105,110,32,112,108,97,116,102,111,114,109,115,46,32,84,104,101,32,102,105,114,115,116,32,115,112,97,99,101,45,115,101,112,97,114,97,116,101,100,32,116,111,107,101,110,32,111,102,32,116,104,101,32,99,111,109,109,97,110,100,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,32,40,111,114,32,100,114,105,118,101,114,41,46,32,84,104,105,115,32,40,97,109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,41,32,109,97,107,101,115,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,115,117,105,116,97,98,108,101,32,102,111,114,32,114,117,110,110,105,110,103,32,112,114,111,103,114,97,109,115,32,119,105,116,104,32,115,112,97,99,101,115,32,105,110,32,102,105,108,101,110,97,109,101,115,32,111,114,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,46,32,73,102,32,115,112,97,99,101,115,32,105,110,32,101,120,101,99,117,116,97,98,108,101,32,102,105,108,101,110,97,109,101,115,32,97,114,101,32,100,101,115,105,114,101,100,44,32,117,115,101,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,67,111,109,109,97,110,100,125>>]},<<32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,115,112,97,119,110,95,100,114,105,118,101,114,44,32,67,111,109,109,97,110,100,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<44,32,98,117,116,32,100,101,109,97,110,100,115,32,116,104,101,32,102,105,114,115,116,32,40,115,112,97,99,101,45,115,101,112,97,114,97,116,101,100,41,32,116,111,107,101,110,32,111,102,32,116,104,101,32,99,111,109,109,97,110,100,32,116,111,32,98,101,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,108,111,97,100,101,100,32,100,114,105,118,101,114,46,32,73,102,32,110,111,32,100,114,105,118,101,114,32,119,105,116,104,32,116,104,97,116,32,110,97,109,101,32,105,115,32,108,111,97,100,101,100,44,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,114,114,111,114,32,105,115,32,114,97,105,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<123,115,112,97,119,110,44,32,70,105,108,101,78,97,109,101,125>>]},<<44,32,98,117,116,32,111,110,108,121,32,114,117,110,115,32,101,120,116,101,114,110,97,108,32,101,120,101,99,117,116,97,98,108,101,115,46,32>>,{code,[],[<<70,105,108,101,78,97,109,101>>]},<<32,105,110,32,105,116,115,32,119,104,111,108,101,32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,44,32,105,110,99,108,117,100,105,110,103,32,97,110,121,32,115,112,97,99,101,115,46,32,73,102,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,116,111,32,98,101,32,112,97,115,115,101,100,44,32,116,104,101,32>>,{code,[],[<<80,111,114,116,83,101,116,116,105,110,103,115>>]},<<32>>,{code,[],[<<97,114,103,115>>]},<<32,97,110,100,32>>,{code,[],[<<97,114,103,48>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,115,104,101,108,108,32,105,115,32,117,115,117,97,108,108,121,32,110,111,116,32,105,110,118,111,107,101,100,32,116,111,32,115,116,97,114,116,32,116,104,101,32,112,114,111,103,114,97,109,44,32,105,116,32,105,115,32,101,120,101,99,117,116,101,100,32,100,105,114,101,99,116,108,121,46,32>>,{code,[],[<<80,65,84,72>>]},<<32,40,111,114,32,101,113,117,105,118,97,108,101,110,116,41,32,105,115,32,110,111,116,32,115,101,97,114,99,104,101,100,46,32,84,111,32,102,105,110,100,32,97,32,112,114,111,103,114,97,109,32,105,110,32>>,{code,[],[<<80,65,84,72>>]},<<32,116,111,32,101,120,101,99,117,116,101,44,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,102,105,110,100,95,101,120,101,99,117,116,97,98,108,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,102,105,110,100,95,101,120,101,99,117,116,97,98,108,101,47,49>>]}]},<<46>>]},{p,[],[<<79,110,108,121,32,105,102,32,97,32,115,104,101,108,108,32,115,99,114,105,112,116,32,111,114,32>>,{code,[],[<<46,98,97,116>>]},<<32,102,105,108,101,32,105,115,32,101,120,101,99,117,116,101,100,44,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,99,111,109,109,97,110,100,32,105,110,116,101,114,112,114,101,116,101,114,32,105,115,32,105,110,118,111,107,101,100,32,105,109,112,108,105,99,105,116,108,121,44,32,98,117,116,32,116,104,101,114,101,32,105,115,32,115,116,105,108,108,32,110,111,32,99,111,109,109,97,110,100,45,97,114,103,117,109,101,110,116,32,101,120,112,97,110,115,105,111,110,32,111,114,32,105,109,112,108,105,99,105,116,32>>,{code,[],[<<80,65,84,72>>]},<<32,115,101,97,114,99,104,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,105,108,101,78,97,109,101>>]},<<32,99,97,110,110,111,116,32,98,101,32,114,117,110,44,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,105,115,32,114,97,105,115,101,100,44,32,119,105,116,104,32,116,104,101,32,80,79,83,73,88,32,101,114,114,111,114,32,99,111,100,101,32,97,115,32,116,104,101,32,114,101,97,115,111,110,46,32,84,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,79,83,115,46,32,84,121,112,105,99,97,108,108,121,32,116,104,101,32,101,114,114,111,114,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,97,105,115,101,100,32,119,104,101,110,32,97,110,32,97,116,116,101,109,112,116,32,105,115,32,109,97,100,101,32,116,111,32,114,117,110,32,97,32,112,114,111,103,114,97,109,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,117,110,100,32,97,110,100,32>>,{code,[],[<<101,97,99,99,101,115>>]},<<32,105,115,32,114,97,105,115,101,100,32,119,104,101,110,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,105,108,101,32,105,115,32,110,111,116,32,101,120,101,99,117,116,97,98,108,101,46>>]}]},{dt,[],[{code,[],[<<123,102,100,44,32,73,110,44,32,79,117,116,125>>]}]},{dd,[],[{p,[],[<<65,108,108,111,119,115,32,97,110,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,116,111,32,97,99,99,101,115,115,32,97,110,121,32,99,117,114,114,101,110,116,108,121,32,111,112,101,110,101,100,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,117,115,101,100,32,98,121,32,69,114,108,97,110,103,46,32,84,104,101,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32>>,{code,[],[<<73,110>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,44,32,97,110,100,32,116,104,101,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32>>,{code,[],[<<79,117,116>>]},<<32,102,111,114,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,46,32,73,116,32,105,115,32,111,110,108,121,32,117,115,101,100,32,102,111,114,32,118,97,114,105,111,117,115,32,115,101,114,118,101,114,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,79,83,32,40>>,{code,[],[<<115,104,101,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<117,115,101,114>>]},<<41,46,32,72,101,110,99,101,44,32,105,116,115,32,117,115,101,32,105,115,32,108,105,109,105,116,101,100,46>>]}]}]},{p,[],[{code,[],[<<80,111,114,116,83,101,116,116,105,110,103,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,115,101,116,116,105,110,103,115,32,102,111,114,32,116,104,101,32,112,111,114,116,46,32,84,104,101,32,118,97,108,105,100,32,115,101,116,116,105,110,103,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,97,99,107,101,116,44,32,78,125>>]}]},{dd,[],[{p,[],[<<77,101,115,115,97,103,101,115,32,97,114,101,32,112,114,101,99,101,100,101,100,32,98,121,32,116,104,101,105,114,32,108,101,110,103,116,104,44,32,115,101,110,116,32,105,110,32>>,{code,[],[<<78>>]},<<32,98,121,116,101,115,44,32,119,105,116,104,32,116,104,101,32,109,111,115,116,32,115,105,103,110,105,102,105,99,97,110,116,32,98,121,116,101,32,102,105,114,115,116,46,32,84,104,101,32,118,97,108,105,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<78>>]},<<32,97,114,101,32,49,44,32,50,44,32,97,110,100,32,52,46>>]}]},{dt,[],[{code,[],[<<115,116,114,101,97,109>>]}]},{dd,[],[{p,[],[<<79,117,116,112,117,116,32,109,101,115,115,97,103,101,115,32,97,114,101,32,115,101,110,116,32,119,105,116,104,111,117,116,32,112,97,99,107,101,116,32,108,101,110,103,116,104,115,46,32,65,32,117,115,101,114,45,100,101,102,105,110,101,100,32,112,114,111,116,111,99,111,108,32,109,117,115,116,32,98,101,32,117,115,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,101,120,116,101,114,110,97,108,32,111,98,106,101,99,116,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,101,44,32,76,125>>]}]},{dd,[],[{p,[],[<<77,101,115,115,97,103,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,111,110,32,97,32,112,101,114,32,108,105,110,101,32,98,97,115,105,115,46,32,69,97,99,104,32,108,105,110,101,32,40,100,101,108,105,109,105,116,101,100,32,98,121,32,116,104,101,32,79,83,45,100,101,112,101,110,100,101,110,116,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,41,32,105,115,32,100,101,108,105,118,101,114,101,100,32,105,110,32,97,32,115,105,110,103,108,101,32,109,101,115,115,97,103,101,46,32,84,104,101,32,109,101,115,115,97,103,101,32,100,97,116,97,32,102,111,114,109,97,116,32,105,115,32>>,{code,[],[<<123,70,108,97,103,44,32,76,105,110,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<70,108,97,103>>]},<<32,105,115,32>>,{code,[],[<<101,111,108>>]},<<32,111,114,32>>,{code,[],[<<110,111,101,111,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<76,105,110,101>>]},<<32,105,115,32,116,104,101,32,100,97,116,97,32,100,101,108,105,118,101,114,101,100,32,40,119,105,116,104,111,117,116,32,116,104,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,41,46>>]},{p,[],[{code,[],[<<76>>]},<<32,115,112,101,99,105,102,105,101,115,32,116,104,101,32,109,97,120,105,109,117,109,32,108,105,110,101,32,108,101,110,103,116,104,32,105,110,32,98,121,116,101,115,46,32,76,105,110,101,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,105,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,105,110,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,109,101,115,115,97,103,101,44,32,119,105,116,104,32>>,{code,[],[<<70,108,97,103>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<110,111,101,111,108>>]},<<32,102,111,114,32,97,108,108,32,98,117,116,32,116,104,101,32,108,97,115,116,32,109,101,115,115,97,103,101,46,32,73,102,32,101,110,100,32,111,102,32,102,105,108,101,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,32,97,110,121,119,104,101,114,101,32,101,108,115,101,32,116,104,97,110,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,105,110,103,32,97,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,44,32,116,104,101,32,108,97,115,116,32,108,105,110,101,32,105,115,32,97,108,115,111,32,100,101,108,105,118,101,114,101,100,32,119,105,116,104,32>>,{code,[],[<<70,108,97,103>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<110,111,101,111,108>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,108,105,110,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,119,105,116,104,32>>,{code,[],[<<70,108,97,103>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<101,111,108>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<123,112,97,99,107,101,116,44,32,78,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,108,105,110,101,44,32,76,125>>]},<<32,115,101,116,116,105,110,103,115,32,97,114,101,32,109,117,116,117,97,108,108,121,32,101,120,99,108,117,115,105,118,101,46>>]}]},{dt,[],[{code,[],[<<123,99,100,44,32,68,105,114,125>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46,32,84,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,32,115,116,97,114,116,115,32,117,115,105,110,103,32>>,{code,[],[<<68,105,114>>]},<<32,97,115,32,105,116,115,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,46,32>>,{code,[],[<<68,105,114>>]},<<32,109,117,115,116,32,98,101,32,97,32,115,116,114,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,101,110,118,44,32,69,110,118,125>>]}]},{dd,[],[{p,[],[<<84,121,112,101,115,58>>,{br,[],[]},<<194,160,194,160>>,{code,[],[<<78,97,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,111,115,35,101,110,118,95,118,97,114,95,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<111,115,58,101,110,118,95,118,97,114,95,110,97,109,101,40,41>>]}]},{br,[],[]},<<194,160,194,160>>,{code,[],[<<86,97,108,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,111,115,35,101,110,118,95,118,97,114,95,118,97,108,117,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<111,115,58,101,110,118,95,118,97,114,95,118,97,108,117,101,40,41>>]}]},{code,[],[<<32,124,32,102,97,108,115,101>>]},{br,[],[]},<<194,160,194,160>>,{code,[],[<<69,110,118,32,61,32,91,123,78,97,109,101,44,32,86,97,108,125,93>>]}]},{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<44,32,97,110,100,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46,32,84,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,111,102,32,116,104,101,32,115,116,97,114,116,101,100,32,112,114,111,99,101,115,115,32,105,115,32,101,120,116,101,110,100,101,100,32,117,115,105,110,103,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32>>,{code,[],[<<69,110,118>>]},<<46>>]},{p,[],[{code,[],[<<69,110,118>>]},<<32,105,115,32,116,111,32,98,101,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32>>,{code,[],[<<123,78,97,109,101,44,32,86,97,108,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,97,110,32,101,110,118,105,114,111,110,109,101,110,116,32,118,97,114,105,97,98,108,101,44,32,97,110,100,32>>,{code,[],[<<86,97,108>>]},<<32,105,115,32,116,104,101,32,118,97,108,117,101,32,105,116,32,105,115,32,116,111,32,104,97,118,101,32,105,110,32,116,104,101,32,115,112,97,119,110,101,100,32,112,111,114,116,32,112,114,111,99,101,115,115,46,32,66,111,116,104,32>>,{code,[],[<<78,97,109,101>>]},<<32,97,110,100,32>>,{code,[],[<<86,97,108>>]},<<32,109,117,115,116,32,98,101,32,115,116,114,105,110,103,115,46,32,84,104,101,32,111,110,101,32,101,120,99,101,112,116,105,111,110,32,105,115,32>>,{code,[],[<<86,97,108>>]},<<32,98,101,105,110,103,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,40,105,110,32,97,110,97,108,111,103,121,32,119,105,116,104,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,103,101,116,101,110,118,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,103,101,116,101,110,118,47,49>>]}]},<<44,32,119,104,105,99,104,32,114,101,109,111,118,101,115,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,118,97,114,105,97,98,108,101,46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,101,110,99,111,100,105,110,103,32,114,101,113,117,105,114,101,109,101,110,116,115,44,32,115,101,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,121,112,101,115,32,102,111,114,32>>,{code,[],[<<78,97,109,101>>]},<<32,97,110,100,32>>,{code,[],[<<86,97,108>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,97,114,103,115,44,32,91,32,115,116,114,105,110,103,40,41,32,124,32,98,105,110,97,114,121,40,41,32,93,125>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<32,97,110,100,32,115,112,101,99,105,102,105,101,115,32,97,114,103,117,109,101,110,116,115,32,116,111,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,46,32,69,97,99,104,32,97,114,103,117,109,101,110,116,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,115,101,112,97,114,97,116,101,32,115,116,114,105,110,103,32,97,110,100,32,40,111,110,32,85,110,105,120,41,32,101,118,101,110,116,117,97,108,108,121,32,101,110,100,115,32,117,112,32,97,115,32,111,110,101,32,101,108,101,109,101,110,116,32,101,97,99,104,32,105,110,32,116,104,101,32,97,114,103,117,109,101,110,116,32,118,101,99,116,111,114,46,32,79,110,32,111,116,104,101,114,32,112,108,97,116,102,111,114,109,115,44,32,97,32,115,105,109,105,108,97,114,32,98,101,104,97,118,105,111,114,32,105,115,32,109,105,109,105,99,107,101,100,46>>]},{p,[],[<<84,104,101,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,110,111,116,32,101,120,112,97,110,100,101,100,32,98,121,32,116,104,101,32,115,104,101,108,108,32,98,101,102,111,114,101,32,116,104,101,121,32,97,114,101,32,115,117,112,112,108,105,101,100,32,116,111,32,116,104,101,32,101,120,101,99,117,116,97,98,108,101,46,32,77,111,115,116,32,110,111,116,97,98,108,121,32,116,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,102,105,108,101,32,119,105,108,100,99,97,114,100,32,101,120,112,97,110,115,105,111,110,32,100,111,101,115,32,110,111,116,32,111,99,99,117,114,46,32,84,111,32,101,120,112,97,110,100,32,119,105,108,100,99,97,114,100,115,32,102,111,114,32,116,104,101,32,97,114,103,117,109,101,110,116,115,44,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,102,105,108,101,108,105,98,35,119,105,108,100,99,97,114,100,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,105,108,101,108,105,98,58,119,105,108,100,99,97,114,100,47,49>>]}]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,101,118,101,110,32,105,102,32,116,104,101,32,112,114,111,103,114,97,109,32,105,115,32,97,32,85,110,105,120,32,115,104,101,108,108,32,115,99,114,105,112,116,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,116,104,101,32,115,104,101,108,108,32,117,108,116,105,109,97,116,101,108,121,32,105,115,32,105,110,118,111,107,101,100,44,32,119,105,108,100,99,97,114,100,32,101,120,112,97,110,115,105,111,110,32,100,111,101,115,32,110,111,116,32,111,99,99,117,114,44,32,97,110,100,32,116,104,101,32,115,99,114,105,112,116,32,105,115,32,112,114,111,118,105,100,101,100,32,119,105,116,104,32,116,104,101,32,117,110,116,111,117,99,104,101,100,32,97,114,103,117,109,101,110,116,115,46,32,79,110,32,87,105,110,100,111,119,115,44,32,119,105,108,100,99,97,114,100,32,101,120,112,97,110,115,105,111,110,32,105,115,32,97,108,119,97,121,115,32,117,112,32,116,111,32,116,104,101,32,112,114,111,103,114,97,109,32,105,116,115,101,108,102,44,32,116,104,101,114,101,102,111,114,101,32,116,104,105,115,32,105,115,32,110,111,116,32,97,110,32,105,115,115,117,101,46>>]},{p,[],[<<84,104,101,32,101,120,101,99,117,116,97,98,108,101,32,110,97,109,101,32,40,97,108,115,111,32,107,110,111,119,110,32,97,115,32>>,{code,[],[<<97,114,103,118,91,48,93>>]},<<41,32,105,115,32,110,111,116,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,105,115,32,108,105,115,116,46,32,84,104,101,32,112,114,111,112,101,114,32,101,120,101,99,117,116,97,98,108,101,32,110,97,109,101,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,117,115,101,100,32,97,115,32>>,{code,[],[<<97,114,103,118,91,48,93>>]},<<44,32,119,104,101,114,101,32,97,112,112,108,105,99,97,98,108,101,46>>]},{p,[],[<<73,102,32,121,111,117,32,101,120,112,108,105,99,105,116,108,121,32,119,97,110,116,32,116,111,32,115,101,116,32,116,104,101,32,112,114,111,103,114,97,109,32,110,97,109,101,32,105,110,32,116,104,101,32,97,114,103,117,109,101,110,116,32,118,101,99,116,111,114,44,32,111,112,116,105,111,110,32>>,{code,[],[<<97,114,103,48>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,97,114,103,48,44,32,115,116,114,105,110,103,40,41,32,124,32,98,105,110,97,114,121,40,41,125>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<32,97,110,100,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,115,32,116,104,101,32,112,114,111,103,114,97,109,32,110,97,109,101,32,97,114,103,117,109,101,110,116,32,119,104,101,110,32,114,117,110,110,105,110,103,32,97,110,32,101,120,101,99,117,116,97,98,108,101,46,32,84,104,105,115,32,99,97,110,32,105,110,32,115,111,109,101,32,99,105,114,99,117,109,115,116,97,110,99,101,115,44,32,111,110,32,115,111,109,101,32,79,83,115,44,32,98,101,32,100,101,115,105,114,97,98,108,101,46,32,72,111,119,32,116,104,101,32,112,114,111,103,114,97,109,32,114,101,115,112,111,110,100,115,32,116,111,32,116,104,105,115,32,105,115,32,104,105,103,104,108,121,32,115,121,115,116,101,109,45,100,101,112,101,110,100,101,110,116,32,97,110,100,32,110,111,32,115,112,101,99,105,102,105,99,32,101,102,102,101,99,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,46>>]}]},{dt,[],[{code,[],[<<101,120,105,116,95,115,116,97,116,117,115>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,110,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,44,32,97,110,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,99,101,115,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,101,32,112,111,114,116,32,101,120,105,116,115,44,32,97,32,109,101,115,115,97,103,101,32,111,102,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,80,111,114,116,44,123,101,120,105,116,95,115,116,97,116,117,115,44,83,116,97,116,117,115,125,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,114,111,99,101,115,115,44,32,119,104,101,114,101,32>>,{code,[],[<<83,116,97,116,117,115>>]},<<32,105,115,32,116,104,101,32,101,120,105,116,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,101,120,116,101,114,110,97,108,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,101,32,112,114,111,103,114,97,109,32,97,98,111,114,116,115,32,111,110,32,85,110,105,120,44,32,116,104,101,32,115,97,109,101,32,99,111,110,118,101,110,116,105,111,110,32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,115,104,101,108,108,115,32,100,111,32,40,116,104,97,116,32,105,115,44,32,49,50,56,43,115,105,103,110,97,108,41,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<101,111,102>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,108,115,111,44,32,116,104,101,32,109,101,115,115,97,103,101,115,32>>,{code,[],[<<101,111,102>>]},<<32,97,110,100,32>>,{code,[],[<<101,120,105,116,95,115,116,97,116,117,115>>]},<<32,97,112,112,101,97,114,32,105,110,32,97,110,32,117,110,115,112,101,99,105,102,105,101,100,32,111,114,100,101,114,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,32,99,108,111,115,101,115,32,105,116,115,32>>,{code,[],[<<115,116,100,111,117,116>>]},<<32,119,105,116,104,111,117,116,32,101,120,105,116,105,110,103,44,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,105,116,95,115,116,97,116,117,115>>]},<<32,100,111,101,115,32,110,111,116,32,119,111,114,107,46>>]}]},{dt,[],[{code,[],[<<117,115,101,95,115,116,100,105,111>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32>>,{code,[],[<<123,115,112,97,119,110,44,32,67,111,109,109,97,110,100,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<46,32,73,116,32,97,108,108,111,119,115,32,116,104,101,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,32,97,110,100,32,111,117,116,112,117,116,32,40,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,48,32,97,110,100,32,49,41,32,111,102,32,116,104,101,32,115,112,97,119,110,101,100,32,40,85,110,105,120,41,32,112,114,111,99,101,115,115,32,102,111,114,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,69,114,108,97,110,103,46>>]}]},{dt,[],[{code,[],[<<110,111,117,115,101,95,115,116,100,105,111>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,112,111,115,105,116,101,32,111,102,32>>,{code,[],[<<117,115,101,95,115,116,100,105,111>>]},<<46,32,73,116,32,117,115,101,115,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,51,32,97,110,100,32,52,32,102,111,114,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,69,114,108,97,110,103,46>>]}]},{dt,[],[{code,[],[<<115,116,100,101,114,114,95,116,111,95,115,116,100,111,117,116>>]}]},{dd,[],[{p,[],[<<65,102,102,101,99,116,115,32,112,111,114,116,115,32,116,111,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,115,46,32,84,104,101,32,101,120,101,99,117,116,101,100,32,112,114,111,103,114,97,109,32,103,101,116,115,32,105,116,115,32,115,116,97,110,100,97,114,100,32,101,114,114,111,114,32,102,105,108,101,32,114,101,100,105,114,101,99,116,101,100,32,116,111,32,105,116,115,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,32,102,105,108,101,46,32>>,{code,[],[<<115,116,100,101,114,114,95,116,111,95,115,116,100,111,117,116>>]},<<32,97,110,100,32>>,{code,[],[<<110,111,117,115,101,95,115,116,100,105,111>>]},<<32,97,114,101,32,109,117,116,117,97,108,108,121,32,101,120,99,108,117,115,105,118,101,46>>]}]},{dt,[],[{code,[],[<<111,118,101,114,108,97,112,112,101,100,95,105,111>>]}]},{dd,[],[{p,[],[<<65,102,102,101,99,116,115,32,112,111,114,116,115,32,116,111,32,101,120,116,101,114,110,97,108,32,112,114,111,103,114,97,109,115,32,111,110,32,87,105,110,100,111,119,115,32,111,110,108,121,46,32,84,104,101,32,115,116,97,110,100,97,114,100,32,105,110,112,117,116,32,97,110,100,32,115,116,97,110,100,97,114,100,32,111,117,116,112,117,116,32,104,97,110,100,108,101,115,32,111,102,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,32,97,114,101,44,32,105,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,117,112,112,108,105,101,100,44,32,111,112,101,110,101,100,32,119,105,116,104,32,102,108,97,103,32>>,{code,[],[<<70,73,76,69,95,70,76,65,71,95,79,86,69,82,76,65,80,80,69,68>>]},<<44,32,115,111,32,116,104,97,116,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,32,99,97,110,32,40,97,110,100,32,109,117,115,116,41,32,100,111,32,111,118,101,114,108,97,112,112,101,100,32,73,47,79,32,111,110,32,105,116,115,32,115,116,97,110,100,97,114,100,32,104,97,110,100,108,101,115,46,32,84,104,105,115,32,105,115,32,110,111,116,32,110,111,114,109,97,108,108,121,32,116,104,101,32,99,97,115,101,32,102,111,114,32,115,105,109,112,108,101,32,112,111,114,116,32,112,114,111,103,114,97,109,115,44,32,98,117,116,32,97,110,32,111,112,116,105,111,110,32,111,102,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,101,120,112,101,114,105,101,110,99,101,100,32,87,105,110,100,111,119,115,32,112,114,111,103,114,97,109,109,101,114,46,32>>,{em,[],[<<79,110,32,97,108,108,32,111,116,104,101,114,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,105,108,101,110,116,108,121,32,100,105,115,99,97,114,100,101,100,46>>]}]}]},{dt,[],[{code,[],[<<105,110>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,99,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,102,111,114,32,105,110,112,117,116,46>>]}]},{dt,[],[{code,[],[<<111,117,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,99,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,102,111,114,32,111,117,116,112,117,116,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<65,108,108,32,73,47,79,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,115,32,97,115,32,111,112,112,111,115,101,100,32,116,111,32,108,105,115,116,115,32,111,102,32,98,121,116,101,115,46>>]}]},{dt,[],[{code,[],[<<101,111,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,99,108,111,115,101,100,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,102,105,108,101,32,97,110,100,32,100,111,101,115,32,110,111,116,32,112,114,111,100,117,99,101,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,46,32,73,110,115,116,101,97,100,44,32,105,116,32,114,101,109,97,105,110,115,32,111,112,101,110,32,97,110,100,32,97,32>>,{code,[],[<<123,80,111,114,116,44,32,101,111,102,125>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,104,111,108,100,105,110,103,32,116,104,101,32,112,111,114,116,46>>]}]},{dt,[],[{code,[],[<<104,105,100,101>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32,114,117,110,110,105,110,103,32,111,110,32,87,105,110,100,111,119,115,44,32,115,117,112,112,114,101,115,115,101,115,32,99,114,101,97,116,105,111,110,32,111,102,32,97,32,110,101,119,32,99,111,110,115,111,108,101,32,119,105,110,100,111,119,32,119,104,101,110,32,115,112,97,119,110,105,110,103,32,116,104,101,32,112,111,114,116,32,112,114,111,103,114,97,109,46,32,40,84,104,105,115,32,111,112,116,105,111,110,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,111,110,32,111,116,104,101,114,32,112,108,97,116,102,111,114,109,115,46,41>>]}]},{dt,[],[{code,[],[<<123,112,97,114,97,108,108,101,108,105,115,109,44,32,66,111,111,108,101,97,110,125>>]}]},{dd,[],[{a,[{id,<<111,112,101,110,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>}],[]},{p,[],[<<83,101,116,115,32,115,99,104,101,100,117,108,101,114,32,104,105,110,116,32,102,111,114,32,112,111,114,116,32,112,97,114,97,108,108,101,108,105,115,109,46,32,73,102,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,115,99,104,101,100,117,108,101,115,32,112,111,114,116,32,116,97,115,107,115,59,32,119,104,101,110,32,100,111,105,110,103,32,115,111,44,32,105,116,32,105,109,112,114,111,118,101,115,32,112,97,114,97,108,108,101,108,105,115,109,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,73,102,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,116,114,105,101,115,32,116,111,32,112,101,114,102,111,114,109,32,112,111,114,116,32,116,97,115,107,115,32,105,109,109,101,100,105,97,116,101,108,121,44,32,105,109,112,114,111,118,105,110,103,32,108,97,116,101,110,99,121,32,97,116,32,116,104,101,32,101,120,112,101,110,115,101,32,111,102,32,112,97,114,97,108,108,101,108,105,115,109,46,32,84,104,101,32,100,101,102,97,117,108,116,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,121,115,116,101,109,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,112,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,112,112>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,98,117,115,121,95,108,105,109,105,116,115,95,112,111,114,116,44,32,123,76,111,119,44,32,72,105,103,104,125,32,124,32,100,105,115,97,98,108,101,100,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,108,105,109,105,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,117,115,101,100,32,102,111,114,32,99,111,110,116,114,111,108,108,105,110,103,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,32,111,102,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,112,111,114,116,115,32,105,110,116,101,114,110,97,108,32,111,117,116,112,117,116,32,113,117,101,117,101,32,115,105,122,101,32,98,101,99,111,109,101,115,32,108,97,114,103,101,114,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<72,105,103,104>>]},<<32,98,121,116,101,115,44,32,105,116,32,101,110,116,101,114,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,105,116,32,98,101,99,111,109,101,115,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<76,111,119>>]},<<32,98,121,116,101,115,32,105,116,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,116,104,101,32,112,111,114,116,32,105,115,32,105,110,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,44,32,112,114,111,99,101,115,115,101,115,32,115,101,110,100,105,110,103,32,99,111,109,109,97,110,100,115,32,116,111,32,105,116,32,119,105,108,108,32,98,101,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,67,111,109,109,97,110,100,115,32,97,114,101,32,105,110,32,116,104,105,115,32,99,111,110,116,101,120,116,32,101,105,116,104,101,114,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,91,50,44,51,93>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<76,111,119>>]},<<32,108,105,109,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,97,100,106,117,115,116,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,102,32,105,116,32,105,115,32,115,101,116,32,108,97,114,103,101,114,32,116,104,101,110,32>>,{code,[],[<<72,105,103,104>>]},<<46,32,86,97,108,105,100,32,114,97,110,103,101,32,111,102,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<76,111,119>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,115,32>>,{code,[],[<<91,49,44,32,40,49,32,98,115,108,32,40,56,42,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,119,111,114,100,115,105,122,101,41,41,41,45,50,93>>]},<<46,32,73,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<32,105,115,32,112,97,115,115,101,100,44,32,116,104,101,32,112,111,114,116,32,119,105,108,108,32,110,101,118,101,114,32,101,110,116,101,114,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,115,32,97,114,101,32>>,{code,[],[<<76,111,119,32,61,32,52,48,57,54>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104,32,61,32,56,49,57,50>>]},<<46>>]},{p,[],[{em,[],[<<78,111,116,101>>]},<<32,116,104,97,116,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,111,110,108,121,32,118,97,108,105,100,32,119,104,101,110,32,115,112,97,119,110,105,110,103,32,97,110,32,101,120,101,99,117,116,97,98,108,101,32,40,112,111,114,116,32,112,114,111,103,114,97,109,41,32,98,121,32,111,112,101,110,105,110,103,32,116,104,101,32,115,112,97,119,110,32,100,114,105,118,101,114,32,97,110,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32>>,{code,[],[<<102,100>>]},<<32,100,114,105,118,101,114,46,32,84,104,105,115,32,111,112,116,105,111,110,32,119,105,108,108,32,99,97,117,115,101,32,97,32,102,97,105,108,117,114,101,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,119,104,101,110,32,111,112,101,110,105,110,103,32,111,116,104,101,114,32,100,114,105,118,101,114,115,46>>]}]},{dt,[],[{code,[],[<<123,98,117,115,121,95,108,105,109,105,116,115,95,109,115,103,113,44,32,123,76,111,119,44,32,72,105,103,104,125,32,124,32,100,105,115,97,98,108,101,100,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,108,105,109,105,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,117,115,101,100,32,102,111,114,32,99,111,110,116,114,111,108,108,105,110,103,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,32,111,102,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,112,111,114,116,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,115,105,122,101,32,98,101,99,111,109,101,115,32,108,97,114,103,101,114,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<72,105,103,104>>]},<<32,98,121,116,101,115,32,105,116,32,101,110,116,101,114,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,105,116,32,98,101,99,111,109,101,115,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<76,111,119>>]},<<32,98,121,116,101,115,32,105,116,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,87,104,101,110,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,105,115,32,105,110,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,44,32,112,114,111,99,101,115,115,101,115,32,115,101,110,100,105,110,103,32,99,111,109,109,97,110,100,115,32,116,111,32,105,116,32,119,105,108,108,32,98,101,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,108,101,97,118,101,115,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46,32,67,111,109,109,97,110,100,115,32,97,114,101,32,105,110,32,116,104,105,115,32,99,111,110,116,101,120,116,32,101,105,116,104,101,114,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,111,114,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,91,50,44,51,93>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<76,111,119>>]},<<32,108,105,109,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,97,100,106,117,115,116,101,100,32,116,111,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,102,32,105,116,32,105,115,32,115,101,116,32,108,97,114,103,101,114,32,116,104,101,110,32>>,{code,[],[<<72,105,103,104>>]},<<46,32,86,97,108,105,100,32,114,97,110,103,101,32,111,102,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<76,111,119>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104>>]},<<32,105,115,32>>,{code,[],[<<91,49,44,32,40,49,32,98,115,108,32,40,56,42,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,119,111,114,100,115,105,122,101,41,41,41,45,50,93>>]},<<46,32,73,102,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<32,105,115,32,112,97,115,115,101,100,44,32,116,104,101,32,112,111,114,116,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,110,101,118,101,114,32,101,110,116,101,114,32,116,104,101,32,98,117,115,121,32,115,116,97,116,101,46>>]},{p,[],[{em,[],[<<78,111,116,101>>]},<<32,116,104,97,116,32,105,102,32,116,104,101,32,100,114,105,118,101,114,32,115,116,97,116,105,99,97,108,108,121,32,104,97,115,32,100,105,115,97,98,108,101,100,32,116,104,101,32,117,115,101,32,111,102,32,116,104,105,115,32,102,101,97,116,117,114,101,44,32,97,32,102,97,105,108,117,114,101,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,119,105,108,108,32,98,101,32,114,97,105,115,101,100,32,117,110,108,101,115,115,32,116,104,105,115,32,111,112,116,105,111,110,32,97,108,115,111,32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<100,105,115,97,98,108,101>>]},<<32,111,114,32,110,111,116,32,112,97,115,115,101,100,32,97,116,32,97,108,108,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,115,32,97,114,101,32>>,{code,[],[<<76,111,119,32,61,32,52,48,57,54>>]},<<32,97,110,100,32>>,{code,[],[<<72,105,103,104,32,61,32,56,49,57,50>>]},<<32,117,110,108,101,115,115,32,116,104,101,32,100,114,105,118,101,114,32,105,116,115,101,108,102,32,100,111,101,115,32,109,111,100,105,102,105,99,97,116,105,111,110,115,32,111,102,32,116,104,101,115,101,32,118,97,108,117,101,115,46>>]},{p,[],[{em,[],[<<78,111,116,101>>]},<<32,116,104,97,116,32,116,104,101,32,100,114,105,118,101,114,32,109,105,103,104,116,32,102,97,105,108,32,105,102,32,105,116,32,97,108,115,111,32,97,100,106,117,115,116,32,116,104,101,115,101,32,108,105,109,105,116,115,32,98,121,32,105,116,115,101,108,102,32,97,110,100,32,121,111,117,32,104,97,118,101,32,100,105,115,97,98,108,101,100,32,116,104,105,115,32,102,101,97,116,117,114,101,46>>]},{p,[],[<<84,104,101,32,115,112,97,119,110,32,100,114,105,118,101,114,32,40,117,115,101,100,32,119,104,101,110,32,115,112,97,119,110,105,110,103,32,97,110,32,101,120,101,99,117,116,97,98,108,101,41,32,97,110,100,32,116,104,101,32>>,{code,[],[<<102,100>>]},<<32,100,114,105,118,101,114,32,100,111,32,110,111,116,32,100,105,115,97,98,108,101,32,116,104,105,115,32,102,101,97,116,117,114,101,32,97,110,100,32,100,111,32,110,111,116,32,97,100,106,117,115,116,32,116,104,101,115,101,32,108,105,109,105,116,115,32,98,121,32,116,104,101,109,115,101,108,118,101,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,114,105,118,101,114,35,101,114,108,95,100,114,118,95,98,117,115,121,95,109,115,103,113,95,108,105,109,105,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,108,95,100,114,118,95,98,117,115,121,95,109,115,103,113,95,108,105,109,105,116,115,40,41>>]}]},<<46>>]}]}]},{p,[],[<<68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<115,116,114,101,97,109>>]},<<32,102,111,114,32,97,108,108,32,112,111,114,116,32,116,121,112,101,115,32,97,110,100,32>>,{code,[],[<<117,115,101,95,115,116,100,105,111>>]},<<32,102,111,114,32,115,112,97,119,110,101,100,32,112,111,114,116,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32,105,102,32,116,104,101,32,112,111,114,116,32,99,97,110,110,111,116,32,98,101,32,111,112,101,110,101,100,44,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<44,32>>,{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]},<<44,32,111,114,32,116,104,101,32,80,79,83,73,88,32,101,114,114,111,114,32,99,111,100,101,32,116,104,97,116,32,109,111,115,116,32,99,108,111,115,101,108,121,32,100,101,115,99,114,105,98,101,115,32,116,104,101,32,101,114,114,111,114,44,32,111,114,32>>,{code,[],[<<101,105,110,118,97,108>>]},<<32,105,102,32,110,111,32,80,79,83,73,88,32,99,111,100,101,32,105,115,32,97,112,112,114,111,112,114,105,97,116,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<66,97,100,32,105,110,112,117,116,32,97,114,103,117,109,101,110,116,115,32,116,111,32>>,{code,[],[<<111,112,101,110,95,112,111,114,116>>]},<<46>>]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[<<65,108,108,32,97,118,97,105,108,97,98,108,101,32,112,111,114,116,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,101,109,117,108,97,116,111,114,32,97,114,101,32,105,110,32,117,115,101,46>>]},{dt,[],[{code,[],[<<101,110,111,109,101,109>>]}]},{dd,[],[<<78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,116,111,32,99,114,101,97,116,101,32,116,104,101,32,112,111,114,116,46>>]},{dt,[],[{code,[],[<<101,97,103,97,105,110>>]}]},{dd,[],[<<78,111,32,109,111,114,101,32,97,118,97,105,108,97,98,108,101,32,79,83,32,112,114,111,99,101,115,115,101,115,46>>]},{dt,[],[{code,[],[<<101,110,97,109,101,116,111,111,108,111,110,103>>]}]},{dd,[],[<<84,111,111,32,108,111,110,103,32,101,120,116,101,114,110,97,108,32,99,111,109,109,97,110,100,46>>]},{dt,[],[{code,[],[<<101,109,102,105,108,101>>]}]},{dd,[],[<<78,111,32,109,111,114,101,32,97,118,97,105,108,97,98,108,101,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,115,32,40,102,111,114,32,116,104,101,32,79,83,32,112,114,111,99,101,115,115,32,116,104,97,116,32,116,104,101,32,69,114,108,97,110,103,32,101,109,117,108,97,116,111,114,32,114,117,110,115,32,105,110,41,46>>]},{dt,[],[{code,[],[<<101,110,102,105,108,101>>]}]},{dd,[],[<<70,117,108,108,32,102,105,108,101,32,116,97,98,108,101,32,40,102,111,114,32,116,104,101,32,101,110,116,105,114,101,32,79,83,41,46>>]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{code,[],[<<67,111,109,109,97,110,100>>]},<<32,115,112,101,99,105,102,105,101,100,32,105,110,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,67,111,109,109,97,110,100,125>>]},<<32,100,111,101,115,32,110,111,116,32,112,111,105,110,116,32,111,117,116,32,97,110,32,101,120,101,99,117,116,97,98,108,101,32,102,105,108,101,46>>]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{code,[],[<<70,105,108,101,78,97,109,101>>]},<<32,115,112,101,99,105,102,105,101,100,32,105,110,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,70,105,108,101,78,97,109,101,125>>]},<<32,100,111,101,115,32,110,111,116,32,112,111,105,110,116,32,111,117,116,32,97,110,32,101,120,105,115,116,105,110,103,32,102,105,108,101,46>>]}]},{p,[],[<<68,117,114,105,110,103,32,117,115,101,32,111,102,32,97,32,112,111,114,116,32,111,112,101,110,101,100,32,117,115,105,110,103,32>>,{code,[],[<<123,115,112,97,119,110,44,32,78,97,109,101,125>>]},<<44,32>>,{code,[],[<<123,115,112,97,119,110,95,100,114,105,118,101,114,44,32,78,97,109,101,125>>]},<<44,32,111,114,32>>,{code,[],[<<123,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,78,97,109,101,125>>]},<<44,32,101,114,114,111,114,115,32,97,114,105,115,105,110,103,32,119,104,101,110,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,105,116,32,97,114,101,32,114,101,112,111,114,116,101,100,32,116,111,32,116,104,101,32,111,119,110,105,110,103,32,112,114,111,99,101,115,115,32,117,115,105,110,103,32,115,105,103,110,97,108,115,32,111,102,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,80,111,114,116,44,32,80,111,115,105,120,67,111,100,101,125>>]},<<46,32,70,111,114,32,116,104,101,32,112,111,115,115,105,98,108,101,32,118,97,108,117,101,115,32,111,102,32>>,{code,[],[<<80,111,115,105,120,67,111,100,101>>]},<<44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,105,108,101,40,51,41>>]}]},<<46>>]},{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,111,114,116,115,32,116,104,97,116,32,99,97,110,32,98,101,32,111,112,101,110,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,109,97,120,95,112,111,114,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,81>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,52,57,52,48>>,signature => [{attribute,{2378,2},spec,{{open_port,2},[{type,{2378,16},bounded_fun,[{type,{2378,16},'fun',[{type,{2378,16},product,[{var,{2378,17},'PortName'},{var,{2378,27},'PortSettings'}]},{type,{2378,44},port,[]}]},[{type,{2379,7},constraint,[{atom,{2379,7},is_subtype},[{var,{2379,7},'PortName'},{type,{2379,19},union,[{type,{2379,19},tuple,[{atom,{2379,20},spawn},{ann_type,{2379,27},[{var,{2379,27},'Command'},{type,{2379,38},union,[{type,{2379,38},string,[]},{type,{2379,49},binary,[]}]}]}]},{type,{2380,19},tuple,[{atom,{2380,20},spawn_driver},{ann_type,{2380,34},[{var,{2380,34},'Command'},{type,{2380,45},union,[{type,{2380,45},string,[]},{type,{2380,56},binary,[]}]}]}]},{type,{2381,19},tuple,[{atom,{2381,20},spawn_executable},{ann_type,{2381,38},[{var,{2381,38},'FileName'},{remote_type,{2381,50},[{atom,{2381,50},file},{atom,{2381,55},name_all},[]]}]}]},{type,{2382,19},tuple,[{atom,{2382,20},fd},{ann_type,{2382,24},[{var,{2382,24},'In'},{type,{2382,30},non_neg_integer,[]}]},{ann_type,{2382,49},[{var,{2382,49},'Out'},{type,{2382,56},non_neg_integer,[]}]}]}]}]]},{type,{2383,7},constraint,[{atom,{2383,7},is_subtype},[{var,{2383,7},'PortSettings'},{type,{2383,23},list,[{var,{2383,24},'Opt'}]}]]},{type,{2384,7},constraint,[{atom,{2384,7},is_subtype},[{var,{2384,7},'Opt'},{type,{2384,14},union,[{type,{2384,14},tuple,[{atom,{2384,15},packet},{ann_type,{2384,23},[{var,{2384,23},'N'},{type,{2384,28},union,[{integer,{2384,28},1},{integer,{2384,32},2},{integer,{2384,36},4}]}]}]},{atom,{2385,14},stream},{type,{2386,14},tuple,[{atom,{2386,15},line},{ann_type,{2386,21},[{var,{2386,21},'L'},{type,{2386,26},non_neg_integer,[]}]}]},{type,{2387,14},tuple,[{atom,{2387,15},cd},{ann_type,{2387,19},[{var,{2387,19},'Dir'},{type,{2387,26},union,[{type,{2387,26},string,[]},{type,{2387,37},binary,[]}]}]}]},{type,{2388,14},tuple,[{atom,{2388,15},env},{ann_type,{2388,20},[{var,{2388,20},'Env'},{type,{2388,27},list,[{type,{2388,28},tuple,[{ann_type,{2388,29},[{var,{2388,29},'Name'},{remote_type,{2388,37},[{atom,{2388,37},os},{atom,{2388,40},env_var_name},[]]}]},{ann_type,{2388,56},[{var,{2388,56},'Val'},{type,{2388,63},union,[{remote_type,{2388,63},[{atom,{2388,63},os},{atom,{2388,66},env_var_value},[]]},{atom,{2388,84},false}]}]}]}]}]}]},{type,{2389,14},tuple,[{atom,{2389,15},args},{type,{2389,21},list,[{type,{2389,22},union,[{type,{2389,22},string,[]},{type,{2389,33},binary,[]}]}]}]},{type,{2390,14},tuple,[{atom,{2390,15},arg0},{type,{2390,21},union,[{type,{2390,21},string,[]},{type,{2390,32},binary,[]}]}]},{atom,{2391,14},exit_status},{atom,{2392,14},use_stdio},{atom,{2393,14},nouse_stdio},{atom,{2394,14},stderr_to_stdout},{atom,{2395,14},in},{atom,{2396,14},out},{atom,{2397,14},binary},{atom,{2398,14},eof},{type,{2399,7},tuple,[{atom,{2399,8},parallelism},{ann_type,{2399,21},[{var,{2399,21},'Boolean'},{type,{2399,32},boolean,[]}]}]},{atom,{2400,7},hide},{type,{2401,14},tuple,[{atom,{2401,15},busy_limits_port},{type,{2401,33},union,[{type,{2401,33},tuple,[{type,{2401,34},non_neg_integer,[]},{type,{2401,53},non_neg_integer,[]}]},{atom,{2401,74},disabled}]}]},{type,{2402,14},tuple,[{atom,{2402,15},busy_limits_msgq},{type,{2402,33},union,[{type,{2402,33},tuple,[{type,{2402,34},non_neg_integer,[]},{type,{2402,53},non_neg_integer,[]}]},{atom,{2402,74},disabled}]}]}]}]]}]]}]}}]}},{{function,phash,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1540}],[<<112,104,97,115,104,47,50>>],#{<<101,110>> => [{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,104,97,115,104,50,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,112,104,97,115,104,50,47,50>>]}]},<<32,115,104,111,117,108,100,32,98,101,32,117,115,101,100,32,102,111,114,32,110,101,119,32,99,111,100,101,46,32,78,111,116,101,32,116,104,97,116,32>>,{code,[],[<<101,114,108,97,110,103,58,112,104,97,115,104,40,88,44,78,41>>]},<<32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,121,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,112,104,97,115,104,50,40,88,44,78,41>>]}]}]},{p,[],[<<80,111,114,116,97,98,108,101,32,104,97,115,104,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,104,97,115,104,32,102,111,114,32,116,104,101,32,115,97,109,101,32,69,114,108,97,110,103,32,116,101,114,109,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,109,97,99,104,105,110,101,32,97,114,99,104,105,116,101,99,116,117,114,101,32,97,110,100,32,69,82,84,83,32,118,101,114,115,105,111,110,32,40,116,104,101,32,66,73,70,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,82,84,83,32,52,46,57,46,49,46,49,41,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,97,32,104,97,115,104,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<84,101,114,109>>]},<<32,119,105,116,104,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<49,46,46,82,97,110,103,101>>]},<<46,32,84,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<82,97,110,103,101>>]},<<32,105,115,32,50,94,51,50,46>>]}]},#{deprecated => <<101,114,108,97,110,103,58,112,104,97,115,104,47,50,32,105,115,32,100,101,112,114,101,99,97,116,101,100,59,32,117,115,101,32,101,114,108,97,110,103,58,112,104,97,115,104,50,47,50,32,105,110,115,116,101,97,100>>,edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,52,54>>,signature => [{attribute,{1540,2},spec,{{erlang,phash,2},[{type,{1540,19},bounded_fun,[{type,{1540,19},'fun',[{type,{1540,19},product,[{var,{1540,20},'Term'},{var,{1540,26},'Range'}]},{var,{1540,36},'Hash'}]},[{type,{1541,7},constraint,[{atom,{1541,7},is_subtype},[{var,{1541,7},'Term'},{type,{1541,15},term,[]}]]},{type,{1542,7},constraint,[{atom,{1542,7},is_subtype},[{var,{1542,7},'Range'},{type,{1542,16},pos_integer,[]}]]},{type,{1543,7},constraint,[{atom,{1543,7},is_subtype},[{var,{1543,7},'Hash'},{type,{1543,15},pos_integer,[]}]]}]]}]}}]}},{{function,phash2,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1555}],[<<112,104,97,115,104,50,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,54,56>>,equiv => {function,phash2,1},signature => [{attribute,{1555,2},spec,{{erlang,phash2,2},[{type,{1555,20},bounded_fun,[{type,{1555,20},'fun',[{type,{1555,20},product,[{var,{1555,21},'Term'},{var,{1555,27},'Range'}]},{var,{1555,37},'Hash'}]},[{type,{1556,7},constraint,[{atom,{1556,7},is_subtype},[{var,{1556,7},'Term'},{type,{1556,15},term,[]}]]},{type,{1557,7},constraint,[{atom,{1557,7},is_subtype},[{var,{1557,7},'Range'},{type,{1557,16},pos_integer,[]}]]},{type,{1558,7},constraint,[{atom,{1558,7},is_subtype},[{var,{1558,7},'Hash'},{type,{1558,15},non_neg_integer,[]}]]}]]}]}}]}},{{function,phash2,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1548}],[<<112,104,97,115,104,50,47,49>>],#{<<101,110>> => [{p,[],[<<80,111,114,116,97,98,108,101,32,104,97,115,104,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,104,97,115,104,32,102,111,114,32,116,104,101,32,115,97,109,101,32,69,114,108,97,110,103,32,116,101,114,109,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,109,97,99,104,105,110,101,32,97,114,99,104,105,116,101,99,116,117,114,101,32,97,110,100,32,69,82,84,83,32,118,101,114,115,105,111,110,32,40,116,104,101,32,66,73,70,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,82,84,83,32,53,46,50,41,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,97,32,104,97,115,104,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<84,101,114,109>>]},<<32,119,105,116,104,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<48,46,46,82,97,110,103,101,45,49>>]},<<46,32,84,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<82,97,110,103,101>>]},<<32,105,115,32,50,94,51,50,46,32,87,104,101,110,32,119,105,116,104,111,117,116,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<82,97,110,103,101>>]},<<44,32,97,32,118,97,108,117,101,32,105,110,32,116,104,101,32,114,97,110,103,101,32,48,46,46,50,94,50,55,45,49,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,97,108,119,97,121,115,32,116,111,32,98,101,32,117,115,101,100,32,102,111,114,32,104,97,115,104,105,110,103,32,116,101,114,109,115,46,32,73,116,32,100,105,115,116,114,105,98,117,116,101,115,32,115,109,97,108,108,32,105,110,116,101,103,101,114,115,32,98,101,116,116,101,114,32,116,104,97,110,32>>,{code,[],[<<112,104,97,115,104,47,50>>]},<<44,32,97,110,100,32,105,116,32,105,115,32,102,97,115,116,101,114,32,102,111,114,32,98,105,103,110,117,109,115,32,97,110,100,32,98,105,110,97,114,105,101,115,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<48,46,46,82,97,110,103,101,45,49>>]},<<32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,114,97,110,103,101,32,111,102,32>>,{code,[],[<<112,104,97,115,104,47,50>>]},<<44,32,119,104,105,99,104,32,105,115,32>>,{code,[],[<<49,46,46,82,97,110,103,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,54,56>>,signature => [{attribute,{1548,2},spec,{{erlang,phash2,1},[{type,{1548,20},bounded_fun,[{type,{1548,20},'fun',[{type,{1548,20},product,[{var,{1548,21},'Term'}]},{var,{1548,30},'Hash'}]},[{type,{1549,7},constraint,[{atom,{1549,7},is_subtype},[{var,{1549,7},'Term'},{type,{1549,15},term,[]}]]},{type,{1550,7},constraint,[{atom,{1550,7},is_subtype},[{var,{1550,7},'Hash'},{type,{1550,15},non_neg_integer,[]}]]}]]}]}}]}},{{function,pid_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1563}],[<<112,105,100,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,112,105,100,95,116,111,95,108,105,115,116,40,115,101,108,102,40,41,41,46,10,34,60,48,46,56,53,46,48,62,34>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,105,115,116,95,112,114,111,116,111,99,111,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,114,101,97,116,105,111,110>>]},<<32,102,111,114,32,116,104,101,32,110,111,100,101,32,105,115,32,110,111,116,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<46,32,84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,112,114,111,99,101,115,115,101,115,32,105,110,32,100,105,102,102,101,114,101,110,116,32,105,110,99,97,114,110,97,116,105,111,110,115,32,111,102,32,97,32,110,111,100,101,32,119,105,116,104,32,97,32,115,112,101,99,105,102,105,99,32,110,97,109,101,32,99,97,110,32,103,101,116,32,116,104,101,32,115,97,109,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,51,57,51>>,signature => [{attribute,{1563,2},spec,{{pid_to_list,1},[{type,{1563,18},bounded_fun,[{type,{1563,18},'fun',[{type,{1563,18},product,[{var,{1563,19},'Pid'}]},{type,{1563,27},string,[]}]},[{type,{1564,7},constraint,[{atom,{1564,7},is_subtype},[{var,{1564,7},'Pid'},{type,{1564,14},pid,[]}]]}]]}]}}]}},{{function,port_call,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3614}],[<<112,111,114,116,95,99,97,108,108,47,51>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,121,110,99,104,114,111,110,111,117,115,32,99,97,108,108,32,116,111,32,97,32,112,111,114,116,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,97,110,100,32>>,{code,[],[<<68,97,116,97>>]},<<32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,44,32,116,104,97,116,32,105,115,44,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46,32,78,111,116,32,97,108,108,32,112,111,114,116,32,100,114,105,118,101,114,115,32,115,117,112,112,111,114,116,32,116,104,105,115,32,102,101,97,116,117,114,101,46>>]},{p,[],[{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,114,101,102,101,114,114,105,110,103,32,116,111,32,97,32,100,114,105,118,101,114,46>>]},{p,[],[{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,119,104,105,99,104,32,105,115,32,112,97,115,115,101,100,32,111,110,32,116,111,32,116,104,101,32,100,114,105,118,101,114,46>>]},{p,[],[{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,121,32,69,114,108,97,110,103,32,116,101,114,109,46,32,84,104,105,115,32,100,97,116,97,32,105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,98,105,110,97,114,121,32,116,101,114,109,32,102,111,114,109,97,116,32,97,110,100,32,115,101,110,116,32,116,111,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,101,114,109,32,102,114,111,109,32,116,104,101,32,100,114,105,118,101,114,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,116,104,101,32,114,101,116,117,114,110,101,100,32,100,97,116,97,32,97,108,115,111,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,100,111,101,115,32,110,111,116,32,102,105,116,32,105,110,32,97,32,51,50,45,98,105,116,32,105,110,116,101,103,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,110,99,104,114,111,110,111,117,115,32,99,111,110,116,114,111,108,32,111,112,101,114,97,116,105,111,110,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,115,111,32,100,101,99,105,100,101,115,32,102,111,114,32,97,110,121,32,114,101,97,115,111,110,32,40,112,114,111,98,97,98,108,121,32,115,111,109,101,116,104,105,110,103,32,119,114,111,110,103,32,119,105,116,104,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<41,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,99,97,108,108,32>>,{code,[],[<<112,111,114,116,95,99,97,108,108>>]},<<32,119,105,116,104,32,97,110,32,117,110,107,110,111,119,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,101,120,112,101,99,116,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,115,117,112,112,108,105,101,100,32,97,114,103,117,109,101,110,116,115,46>>]}]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,49,50>>,signature => [{attribute,{3614,2},spec,{{erlang,port_call,3},[{type,{3614,23},bounded_fun,[{type,{3614,23},'fun',[{type,{3614,23},product,[{var,{3614,24},'Port'},{var,{3614,30},'Operation'},{var,{3614,41},'Data'}]},{type,{3614,50},term,[]}]},[{type,{3615,7},constraint,[{atom,{3615,7},is_subtype},[{var,{3615,7},'Port'},{type,{3615,15},union,[{type,{3615,15},port,[]},{type,{3615,24},atom,[]}]}]]},{type,{3616,7},constraint,[{atom,{3616,7},is_subtype},[{var,{3616,7},'Operation'},{type,{3616,20},integer,[]}]]},{type,{3617,7},constraint,[{atom,{3617,7},is_subtype},[{var,{3617,7},'Data'},{type,{3617,15},term,[]}]]}]]}]}}]}},{{function,port_close,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3575}],[<<112,111,114,116,95,99,108,111,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,108,111,115,101,115,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,82,111,117,103,104,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<80,111,114,116,32,33,32,123,115,101,108,102,40,41,44,32,99,108,111,115,101,125>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,32,40,115,101,101,32,98,101,108,111,119,41,44,32,98,101,105,110,103,32,115,121,110,99,104,114,111,110,111,117,115,44,32,97,110,100,32,116,104,97,116,32,116,104,101,32,112,111,114,116,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,114,101,112,108,121,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,32,99,108,111,115,101,100,125>>]},<<46,32,65,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,99,108,111,115,101,32,97,32,112,111,114,116,32,119,105,116,104,32>>,{code,[],[<<112,111,114,116,95,99,108,111,115,101,47,49>>]},<<44,32,110,111,116,32,111,110,108,121,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,40,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,114,111,99,101,115,115,41,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,99,108,111,115,101,47,49>>]},<<32,114,101,116,117,114,110,115,46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,114,105,115,111,110,58,32>>,{code,[],[<<80,111,114,116,32,33,32,123,115,101,108,102,40,41,44,32,99,108,111,115,101,125>>]},<<32,111,110,108,121,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,111,114,116,32,111,114,32,97,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,99,108,111,115,101,100,32,112,111,114,116,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,110,32,111,112,101,110,32,112,111,114,116,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32,112,111,114,116,32,114,101,112,108,105,101,115,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,32,99,108,111,115,101,100,125>>]},<<32,119,104,101,110,32,97,108,108,32,98,117,102,102,101,114,115,32,104,97,118,101,32,98,101,101,110,32,102,108,117,115,104,101,100,32,97,110,100,32,116,104,101,32,112,111,114,116,32,114,101,97,108,108,121,32,99,108,111,115,101,115,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32>>,{em,[],[<<112,111,114,116,32,111,119,110,101,114>>]},<<32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,99,108,111,115,101,32,97,32,112,111,114,116,32,117,115,105,110,103,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,99,108,111,115,101,125>>]},<<32,97,115,32,105,102,32,105,116,32,105,116,115,101,108,102,32,119,97,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,98,117,116,32,116,104,101,32,114,101,112,108,121,32,97,108,119,97,121,115,32,103,111,101,115,32,116,111,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,54,44,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,99,108,111,115,101,125>>]},<<32,105,115,32,116,114,117,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,97,108,119,97,121,115,32,98,101,101,110,32,100,111,99,117,109,101,110,116,101,100,32,97,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,108,101,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,121,110,99,104,114,111,110,111,117,115,46,32>>,{code,[],[<<112,111,114,116,95,99,108,111,115,101,47,49>>]},<<32,105,115,32,104,111,119,101,118,101,114,32,115,116,105,108,108,32,102,117,108,108,121,32,115,121,110,99,104,114,111,110,111,117,115,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,52,54,52>>,signature => [{attribute,{3575,2},spec,{{port_close,1},[{type,{3575,17},bounded_fun,[{type,{3575,17},'fun',[{type,{3575,17},product,[{var,{3575,18},'Port'}]},{atom,{3575,27},true}]},[{type,{3576,7},constraint,[{atom,{3576,7},is_subtype},[{var,{3576,7},'Port'},{type,{3576,15},union,[{type,{3576,15},port,[]},{type,{3576,24},atom,[]}]}]]}]]}]}}]}},{{function,port_command,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3533}],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,100,97,116,97,32,116,111,32,97,32,112,111,114,116,46,32,83,97,109,101,32,97,115,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,32,97,110,100,32,98,101,105,110,103,32,115,121,110,99,104,114,111,110,111,117,115,32,40,115,101,101,32,98,101,108,111,119,41,46,32,65,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,110,100,32,100,97,116,97,32,116,111,32,97,32,112,111,114,116,32,119,105,116,104,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>]},<<44,32,110,111,116,32,111,110,108,121,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,40,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,114,111,99,101,115,115,41,46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,114,105,115,111,110,58,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,111,110,108,121,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,111,114,116,32,111,114,32,97,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,99,108,111,115,101,100,32,112,111,114,116,44,32,116,104,101,32,100,97,116,97,32,109,101,115,115,97,103,101,32,100,105,115,97,112,112,101,97,114,115,32,119,105,116,104,111,117,116,32,97,32,115,111,117,110,100,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,111,112,101,110,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32>>,{em,[],[<<112,111,114,116,32,111,119,110,101,114>>]},<<32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<46,32,84,104,101,32,112,111,114,116,32,111,119,110,101,114,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<32,97,108,115,111,32,105,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,73,47,79,32,108,105,115,116,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,110,100,32,116,111,32,97,32,112,111,114,116,32,117,115,105,110,103,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,97,115,32,105,102,32,105,116,32,105,116,115,101,108,102,32,119,97,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,98,117,115,121,32,97,110,121,32,109,111,114,101,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,54,44,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125,125>>]},<<32,105,115,32,116,114,117,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,97,108,119,97,121,115,32,98,101,101,110,32,100,111,99,117,109,101,110,116,101,100,32,97,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,108,101,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,121,110,99,104,114,111,110,111,117,115,46,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>]},<<32,105,115,32,104,111,119,101,118,101,114,32,115,116,105,108,108,32,102,117,108,108,121,32,115,121,110,99,104,114,111,110,111,117,115,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]}]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,73,47,79,32,108,105,115,116,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,115,101,110,100,32,100,97,116,97,32,116,111,32,97,110,32,117,110,107,110,111,119,110,32,112,111,114,116,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,100,97,116,97,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,48,52>>,signature => [{attribute,{3533,2},spec,{{port_command,2},[{type,{3533,19},bounded_fun,[{type,{3533,19},'fun',[{type,{3533,19},product,[{var,{3533,20},'Port'},{var,{3533,26},'Data'}]},{atom,{3533,35},true}]},[{type,{3534,7},constraint,[{atom,{3534,7},is_subtype},[{var,{3534,7},'Port'},{type,{3534,15},union,[{type,{3534,15},port,[]},{type,{3534,24},atom,[]}]}]]},{type,{3535,7},constraint,[{atom,{3535,7},is_subtype},[{var,{3535,7},'Data'},{type,{3535,15},iodata,[]}]]}]]}]}}]}},{{function,port_command,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3546}],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,100,97,116,97,32,116,111,32,97,32,112,111,114,116,46,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,40,80,111,114,116,44,32,68,97,116,97,44,32,91,93,41>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,40,80,111,114,116,44,32,68,97,116,97,41>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,99,111,109,109,97,110,100,32,105,115,32,97,98,111,114,116,101,100,44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,115,117,115,112,101,110,100,101,100,32,117,110,116,105,108,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,98,117,115,121,32,97,110,121,109,111,114,101,46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,111,114,99,101>>]}]},{dd,[],[<<84,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,115,117,115,112,101,110,100,101,100,32,105,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,105,110,115,116,101,97,100,32,116,104,101,32,112,111,114,116,32,99,111,109,109,97,110,100,32,105,115,32,102,111,114,99,101,100,32,116,104,114,111,117,103,104,46,32,84,104,101,32,99,97,108,108,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32,116,104,101,32,100,114,105,118,101,114,32,111,102,32,116,104,101,32,112,111,114,116,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,105,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,100,114,105,118,101,114,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,100,114,105,118,101,114,95,101,110,116,114,121,35,100,114,105,118,101,114,95,102,108,97,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<69,82,76,95,68,82,86,95,70,76,65,71,95,83,79,70,84,95,66,85,83,89>>]}]},<<46>>]},{dt,[],[{code,[],[<<110,111,115,117,115,112,101,110,100>>]}]},{dd,[],[<<84,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,115,117,115,112,101,110,100,101,100,32,105,102,32,116,104,101,32,112,111,114,116,32,105,115,32,98,117,115,121,44,32,105,110,115,116,101,97,100,32,116,104,101,32,112,111,114,116,32,99,111,109,109,97,110,100,32,105,115,32,97,98,111,114,116,101,100,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<77,111,114,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<68,97,116,97>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,73,47,79,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,105,111,110,76,105,115,116>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,111,112,116,105,111,110,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<102,111,114,99,101>>]},<<32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,98,117,116,32,116,104,101,32,100,114,105,118,101,114,32,111,102,32,116,104,101,32,112,111,114,116,32,100,111,101,115,32,110,111,116,32,97,108,108,111,119,32,102,111,114,99,105,110,103,32,116,104,114,111,117,103,104,32,97,32,98,117,115,121,32,112,111,114,116,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,115,101,110,100,32,100,97,116,97,32,116,111,32,97,110,32,117,110,107,110,111,119,110,32,112,111,114,116,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,100,97,116,97,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,53,53,54>>,signature => [{attribute,{3546,2},spec,{{port_command,3},[{type,{3546,19},bounded_fun,[{type,{3546,19},'fun',[{type,{3546,19},product,[{var,{3546,20},'Port'},{var,{3546,26},'Data'},{var,{3546,32},'OptionList'}]},{type,{3546,47},boolean,[]}]},[{type,{3547,7},constraint,[{atom,{3547,7},is_subtype},[{var,{3547,7},'Port'},{type,{3547,15},union,[{type,{3547,15},port,[]},{type,{3547,24},atom,[]}]}]]},{type,{3548,7},constraint,[{atom,{3548,7},is_subtype},[{var,{3548,7},'Data'},{type,{3548,15},iodata,[]}]]},{type,{3549,7},constraint,[{atom,{3549,7},is_subtype},[{var,{3549,7},'Option'},{type,{3549,17},union,[{atom,{3549,17},force},{atom,{3549,25},nosuspend}]}]]},{type,{3550,7},constraint,[{atom,{3550,7},is_subtype},[{var,{3550,7},'OptionList'},{type,{3550,21},list,[{var,{3550,22},'Option'}]}]]}]]}]}}]}},{{function,port_connect,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3562}],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,40,116,104,101,32,99,111,110,110,101,99,116,101,100,32,112,111,114,116,41,32,116,111,32>>,{code,[],[<<80,105,100>>]},<<46,32,82,111,117,103,104,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{p,[],[<<84,104,101,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,32,100,105,102,102,101,114,115,44,32,115,101,101,32,98,101,108,111,119,46>>]}]},{li,[],[{p,[],[<<84,104,101,32,112,111,114,116,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,114,101,112,108,121,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,99,111,110,110,101,99,116,101,100,125>>]},<<46>>]}]},{li,[],[{p,[],[{code,[],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,49>>]},<<32,105,115,32,115,121,110,99,104,114,111,110,111,117,115,44,32,115,101,101,32,98,101,108,111,119,46>>]}]},{li,[],[{p,[],[<<84,104,101,32,110,101,119,32,112,111,114,116,32,111,119,110,101,114,32,103,101,116,115,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,46>>]}]}]},{p,[],[<<84,104,101,32,111,108,100,32,112,111,114,116,32,111,119,110,101,114,32,115,116,97,121,115,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,32,97,110,100,32,109,117,115,116,32,99,97,108,108,32>>,{code,[],[<<117,110,108,105,110,107,40,80,111,114,116,41>>]},<<32,105,102,32,116,104,105,115,32,105,115,32,110,111,116,32,100,101,115,105,114,101,100,46,32,65,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,116,111,32,98,101,32,97,110,121,32,112,114,111,99,101,115,115,32,119,105,116,104,32>>,{code,[],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,50>>]},<<46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,114,105,115,111,110,58,32>>,{code,[],[<<80,111,114,116,32,33,32,123,115,101,108,102,40,41,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,111,110,108,121,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,111,114,116,32,111,114,32,97,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,32,99,108,111,115,101,100,32,112,111,114,116,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,110,32,111,112,101,110,32,112,111,114,116,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32,112,111,114,116,32,114,101,112,108,105,101,115,32,119,105,116,104,32>>,{code,[],[<<123,80,111,114,116,44,32,99,111,110,110,101,99,116,101,100,125>>]},<<32,116,111,32,116,104,101,32,111,108,100,32,112,111,114,116,32,111,119,110,101,114,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,111,108,100,32,112,111,114,116,32,111,119,110,101,114,32,105,115,32,115,116,105,108,108,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,119,104,105,108,101,32,116,104,101,32,110,101,119,32,105,115,32,110,111,116,46,32,73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,97,110,32,111,112,101,110,32,112,111,114,116,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,116,104,101,32>>,{em,[],[<<112,111,114,116,32,111,119,110,101,114>>]},<<32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<46,32,84,104,101,32,112,111,114,116,32,111,119,110,101,114,32,102,97,105,108,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,115,105,103>>]},<<32,97,108,115,111,32,105,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,120,105,115,116,105,110,103,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,121,32,112,114,111,99,101,115,115,32,99,97,110,32,115,101,116,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,117,115,105,110,103,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,97,115,32,105,102,32,105,116,32,105,116,115,101,108,102,32,119,97,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,44,32,98,117,116,32,116,104,101,32,114,101,112,108,121,32,97,108,119,97,121,115,32,103,111,101,115,32,116,111,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,54,44,32>>,{code,[],[<<80,111,114,116,32,33,32,123,80,111,114,116,79,119,110,101,114,44,32,123,99,111,110,110,101,99,116,44,32,80,105,100,125,125>>]},<<32,105,115,32,116,114,117,108,121,32,97,115,121,110,99,104,114,111,110,111,117,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,97,108,119,97,121,115,32,98,101,101,110,32,100,111,99,117,109,101,110,116,101,100,32,97,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,108,101,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,121,110,99,104,114,111,110,111,117,115,46,32>>,{code,[],[<<112,111,114,116,95,99,111,110,110,101,99,116,47,50>>]},<<32,105,115,32,104,111,119,101,118,101,114,32,115,116,105,108,108,32,102,117,108,108,121,32,115,121,110,99,104,114,111,110,111,117,115,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,32,101,114,114,111,114,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,44,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,99,108,111,115,101,100,32,112,111,114,116,44,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,116,104,105,115,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,111,99,99,117,114,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,120,105,115,116,105,110,103,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,54,50,48>>,signature => [{attribute,{3562,2},spec,{{port_connect,2},[{type,{3562,19},bounded_fun,[{type,{3562,19},'fun',[{type,{3562,19},product,[{var,{3562,20},'Port'},{var,{3562,26},'Pid'}]},{atom,{3562,34},true}]},[{type,{3563,7},constraint,[{atom,{3563,7},is_subtype},[{var,{3563,7},'Port'},{type,{3563,15},union,[{type,{3563,15},port,[]},{type,{3563,24},atom,[]}]}]]},{type,{3564,7},constraint,[{atom,{3564,7},is_subtype},[{var,{3564,7},'Pid'},{type,{3564,14},pid,[]}]]}]]}]}}]}},{{function,port_control,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3587}],[<<112,111,114,116,95,99,111,110,116,114,111,108,47,51>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,121,110,99,104,114,111,110,111,117,115,32,99,111,110,116,114,111,108,32,111,112,101,114,97,116,105,111,110,32,111,110,32,97,32,112,111,114,116,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,97,110,100,32>>,{code,[],[<<68,97,116,97>>]},<<32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,44,32,116,104,97,116,32,105,115,44,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46,32,78,111,116,32,97,108,108,32,112,111,114,116,32,100,114,105,118,101,114,115,32,115,117,112,112,111,114,116,32,116,104,105,115,32,99,111,110,116,114,111,108,32,102,101,97,116,117,114,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,48,46,46,50,53,53,44,32,111,114,32,97,32,98,105,110,97,114,121,44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46,32,84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,116,104,101,32,114,101,116,117,114,110,101,100,32,100,97,116,97,32,97,108,115,111,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,111,112,101,110,32,112,111,114,116,32,111,114,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,97,110,32,111,112,101,110,32,112,111,114,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,99,97,110,110,111,116,32,102,105,116,32,105,110,32,97,32,51,50,45,98,105,116,32,105,110,116,101,103,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,110,99,104,114,111,110,111,117,115,32,99,111,110,116,114,111,108,32,111,112,101,114,97,116,105,111,110,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,115,111,32,100,101,99,105,100,101,115,32,102,111,114,32,97,110,121,32,114,101,97,115,111,110,32,40,112,114,111,98,97,98,108,121,32,115,111,109,101,116,104,105,110,103,32,119,114,111,110,103,32,119,105,116,104,32>>,{code,[],[<<79,112,101,114,97,116,105,111,110>>]},<<32,111,114,32>>,{code,[],[<<68,97,116,97>>]},<<41,46>>,{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<68,111,32,110,111,116,32,99,97,108,108,32>>,{code,[],[<<112,111,114,116,95,99,111,110,116,114,111,108,47,51>>]},<<32,119,105,116,104,32,97,110,32,117,110,107,110,111,119,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,101,120,112,101,99,116,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,46,32,65,110,121,32,117,110,100,101,102,105,110,101,100,32,98,101,104,97,118,105,111,114,32,105,115,32,112,111,115,115,105,98,108,101,32,40,105,110,99,108,117,100,105,110,103,32,110,111,100,101,32,99,114,97,115,104,41,32,100,101,112,101,110,100,105,110,103,32,111,110,32,104,111,119,32,116,104,101,32,112,111,114,116,32,100,114,105,118,101,114,32,105,110,116,101,114,112,114,101,116,115,32,116,104,101,32,115,117,112,112,108,105,101,100,32,97,114,103,117,109,101,110,116,115,46>>]}]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,54,56,57>>,signature => [{attribute,{3587,2},spec,{{port_control,3},[{type,{3587,19},bounded_fun,[{type,{3587,19},'fun',[{type,{3587,19},product,[{var,{3587,20},'Port'},{var,{3587,26},'Operation'},{var,{3587,37},'Data'}]},{type,{3587,46},union,[{type,{3587,46},iodata,[]},{type,{3587,57},binary,[]}]}]},[{type,{3588,7},constraint,[{atom,{3588,7},is_subtype},[{var,{3588,7},'Port'},{type,{3588,15},union,[{type,{3588,15},port,[]},{type,{3588,24},atom,[]}]}]]},{type,{3589,7},constraint,[{atom,{3589,7},is_subtype},[{var,{3589,7},'Operation'},{type,{3589,20},integer,[]}]]},{type,{3590,7},constraint,[{atom,{3590,7},is_subtype},[{var,{3590,7},'Data'},{type,{3590,15},iodata,[]}]]}]]}]}}]}},{{function,port_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3628}],[<<112,111,114,116,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,116,117,112,108,101,115,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32>>,{code,[],[<<80,111,114,116>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,111,112,101,110,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,110,100,32,97,108,108,32,116,104,101,32,116,117,112,108,101,115,32,97,114,101,32,110,111,116,32,109,97,110,100,97,116,111,114,121,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,49>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<84,104,101,32,114,101,115,117,108,116,32,99,111,110,116,97,105,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32>>,{code,[],[<<73,116,101,109>>]},<<115,58>>]},{ul,[],[{li,[],[{code,[],[<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,40,105,102,32,116,104,101,32,112,111,114,116,32,104,97,115,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,41>>]},{li,[],[{code,[],[<<105,100>>]}]},{li,[],[{code,[],[<<99,111,110,110,101,99,116,101,100>>]}]},{li,[],[{code,[],[<<108,105,110,107,115>>]}]},{li,[],[{code,[],[<<110,97,109,101>>]}]},{li,[],[{code,[],[<<105,110,112,117,116>>]}]},{li,[],[{code,[],[<<111,117,116,112,117,116>>]}]}]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32>>,{code,[],[<<73,116,101,109>>]},<<115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,111,114,116,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,51,51>>,signature => [{attribute,{3628,2},spec,{{erlang,port_info,1},[{type,{3628,23},bounded_fun,[{type,{3628,23},'fun',[{type,{3628,23},product,[{var,{3628,24},'Port'}]},{var,{3628,33},'Result'}]},[{type,{3629,7},constraint,[{atom,{3629,7},is_subtype},[{var,{3629,7},'Port'},{type,{3629,15},union,[{type,{3629,15},port,[]},{type,{3629,24},atom,[]}]}]]},{type,{3630,7},constraint,[{atom,{3630,7},is_subtype},[{var,{3630,7},'ResultItem'},{type,{3630,21},union,[{type,{3630,21},tuple,[{atom,{3630,22},registered_name},{ann_type,{3630,39},[{var,{3630,39},'RegisteredName'},{type,{3630,57},atom,[]}]}]},{type,{3631,7},tuple,[{atom,{3631,8},id},{ann_type,{3631,12},[{var,{3631,12},'Index'},{type,{3631,21},non_neg_integer,[]}]}]},{type,{3632,7},tuple,[{atom,{3632,8},connected},{ann_type,{3632,19},[{var,{3632,19},'Pid'},{type,{3632,26},pid,[]}]}]},{type,{3633,7},tuple,[{atom,{3633,8},links},{ann_type,{3633,15},[{var,{3633,15},'Pids'},{type,{3633,23},list,[{type,{3633,24},pid,[]}]}]}]},{type,{3634,7},tuple,[{atom,{3634,8},name},{ann_type,{3634,14},[{var,{3634,14},'String'},{type,{3634,24},string,[]}]}]},{type,{3635,7},tuple,[{atom,{3635,8},input},{ann_type,{3635,15},[{var,{3635,15},'Bytes'},{type,{3635,24},non_neg_integer,[]}]}]},{type,{3636,7},tuple,[{atom,{3636,8},output},{ann_type,{3636,16},[{var,{3636,16},'Bytes'},{type,{3636,25},non_neg_integer,[]}]}]},{type,{3637,7},tuple,[{atom,{3637,8},os_pid},{ann_type,{3637,16},[{var,{3637,16},'OsPid'},{type,{3637,25},union,[{type,{3637,25},non_neg_integer,[]},{atom,{3637,45},undefined}]}]}]}]}]]},{type,{3638,7},constraint,[{atom,{3638,7},is_subtype},[{var,{3638,7},'Result'},{type,{3638,17},union,[{type,{3638,17},list,[{var,{3638,18},'ResultItem'}]},{atom,{3638,32},undefined}]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,99,111,110,110,101,99,116,101,100,32,116,111,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,54,52>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3649,23},bounded_fun,[{type,{3649,23},'fun',[{type,{3649,23},product,[{var,{3649,24},'Port'},{atom,{3649,30},connected}]},{type,{3649,44},union,[{type,{3649,44},tuple,[{atom,{3649,45},connected},{var,{3649,56},'Pid'}]},{atom,{3649,63},undefined}]}]},[{type,{3650,7},constraint,[{atom,{3650,7},is_subtype},[{var,{3650,7},'Port'},{type,{3650,15},union,[{type,{3650,15},port,[]},{type,{3650,24},atom,[]}]}]]},{type,{3651,7},constraint,[{atom,{3651,7},is_subtype},[{var,{3651,7},'Pid'},{type,{3651,14},pid,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<73,110,100,101,120>>]},<<32,105,115,32,116,104,101,32,105,110,116,101,114,110,97,108,32,105,110,100,101,120,32,111,102,32,116,104,101,32,112,111,114,116,46,32,84,104,105,115,32,105,110,100,101,120,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,115,101,112,97,114,97,116,101,32,112,111,114,116,115,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,56,48>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3652,9},bounded_fun,[{type,{3652,9},'fun',[{type,{3652,9},product,[{var,{3652,10},'Port'},{atom,{3652,16},id}]},{type,{3652,23},union,[{type,{3652,23},tuple,[{atom,{3652,24},id},{var,{3652,28},'Index'}]},{atom,{3652,37},undefined}]}]},[{type,{3653,7},constraint,[{atom,{3653,7},is_subtype},[{var,{3653,7},'Port'},{type,{3653,15},union,[{type,{3653,15},port,[]},{type,{3653,24},atom,[]}]}]]},{type,{3654,7},constraint,[{atom,{3654,7},is_subtype},[{var,{3654,7},'Index'},{type,{3654,16},non_neg_integer,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,112,111,114,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,55,57,54>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3655,9},bounded_fun,[{type,{3655,9},'fun',[{type,{3655,9},product,[{var,{3655,10},'Port'},{atom,{3655,16},input}]},{type,{3655,26},union,[{type,{3655,26},tuple,[{atom,{3655,27},input},{var,{3655,34},'Bytes'}]},{atom,{3655,43},undefined}]}]},[{type,{3656,7},constraint,[{atom,{3656,7},is_subtype},[{var,{3656,7},'Port'},{type,{3656,15},union,[{type,{3656,15},port,[]},{type,{3656,24},atom,[]}]}]]},{type,{3657,7},constraint,[{atom,{3657,7},is_subtype},[{var,{3657,7},'Bytes'},{type,{3657,16},non_neg_integer,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<80,105,100,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,116,104,101,32,112,111,114,116,32,105,115,32,108,105,110,107,101,100,32,116,111,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,49,50>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3658,9},bounded_fun,[{type,{3658,9},'fun',[{type,{3658,9},product,[{var,{3658,10},'Port'},{atom,{3658,16},links}]},{type,{3658,26},union,[{type,{3658,26},tuple,[{atom,{3658,27},links},{var,{3658,34},'Pids'}]},{atom,{3658,42},undefined}]}]},[{type,{3659,7},constraint,[{atom,{3659,7},is_subtype},[{var,{3659,7},'Port'},{type,{3659,15},union,[{type,{3659,15},port,[]},{type,{3659,24},atom,[]}]}]]},{type,{3660,7},constraint,[{atom,{3660,7},is_subtype},[{var,{3660,7},'Pids'},{type,{3660,15},list,[{type,{3660,16},pid,[]}]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<76,111,99,107,105,110,103>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{code,[],[<<112,111,114,116,95,108,101,118,101,108>>]},<<32,40,112,111,114,116,45,115,112,101,99,105,102,105,99,32,108,111,99,107,105,110,103,41>>]},{li,[],[{code,[],[<<100,114,105,118,101,114,95,108,101,118,101,108>>]},<<32,40,100,114,105,118,101,114,45,115,112,101,99,105,102,105,99,32,108,111,99,107,105,110,103,41>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,115,101,32,114,101,115,117,108,116,115,32,97,114,101,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,115,112,101,99,105,102,105,99,32,97,110,100,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,50,56>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3661,9},bounded_fun,[{type,{3661,9},'fun',[{type,{3661,9},product,[{var,{3661,10},'Port'},{atom,{3661,16},locking}]},{type,{3661,28},union,[{type,{3661,28},tuple,[{atom,{3661,29},locking},{var,{3661,38},'Locking'}]},{atom,{3661,49},undefined}]}]},[{type,{3662,7},constraint,[{atom,{3662,7},is_subtype},[{var,{3662,7},'Port'},{type,{3662,15},union,[{type,{3662,15},port,[]},{type,{3662,24},atom,[]}]}]]},{type,{3663,7},constraint,[{atom,{3663,7},is_subtype},[{var,{3663,7},'Locking'},{type,{3663,18},union,[{atom,{3663,18},false},{atom,{3663,28},port_level},{atom,{3663,43},driver_level}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{a,[{id,<<112,111,114,116,95,105,110,102,111,95,109,101,109,111,114,121>>}],[]},{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,116,104,105,115,32,112,111,114,116,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,101,32,112,111,114,116,32,105,116,115,101,108,102,32,99,97,110,32,104,97,118,101,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,116,104,97,116,32,105,115,32,110,111,116,32,105,110,99,108,117,100,101,100,32,105,110,32>>,{code,[],[<<66,121,116,101,115>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,52,57>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3664,9},bounded_fun,[{type,{3664,9},'fun',[{type,{3664,9},product,[{var,{3664,10},'Port'},{atom,{3664,16},memory}]},{type,{3664,27},union,[{type,{3664,27},tuple,[{atom,{3664,28},memory},{var,{3664,36},'Bytes'}]},{atom,{3664,45},undefined}]}]},[{type,{3665,7},constraint,[{atom,{3665,7},is_subtype},[{var,{3665,7},'Port'},{type,{3665,15},union,[{type,{3665,15},port,[]},{type,{3665,24},atom,[]}]}]]},{type,{3666,7},constraint,[{atom,{3666,7},is_subtype},[{var,{3666,7},'Bytes'},{type,{3666,16},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<77,111,110,105,116,111,114,115>>]},<<32,114,101,112,114,101,115,101,110,116,32,112,114,111,99,101,115,115,101,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,116,104,105,115,32,112,111,114,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,54,56>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3667,9},bounded_fun,[{type,{3667,9},'fun',[{type,{3667,9},product,[{var,{3667,10},'Port'},{atom,{3667,16},monitors}]},{type,{3667,29},union,[{type,{3667,29},tuple,[{atom,{3667,30},monitors},{var,{3667,40},'Monitors'}]},{atom,{3667,52},undefined}]}]},[{type,{3668,7},constraint,[{atom,{3668,7},is_subtype},[{var,{3668,7},'Port'},{type,{3668,15},union,[{type,{3668,15},port,[]},{type,{3668,24},atom,[]}]}]]},{type,{3669,7},constraint,[{atom,{3669,7},is_subtype},[{var,{3669,7},'Monitors'},{type,{3669,19},list,[{type,{3669,20},tuple,[{atom,{3669,21},process},{type,{3669,30},pid,[]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,108,105,115,116,32,111,102,32,112,105,100,115,32,116,104,97,116,32,97,114,101,32,109,111,110,105,116,111,114,105,110,103,32,103,105,118,101,110,32,112,111,114,116,32,97,116,32,116,104,101,32,109,111,109,101,110,116,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,56,56,52>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3670,9},bounded_fun,[{type,{3670,9},'fun',[{type,{3670,9},product,[{var,{3670,10},'Port'},{atom,{3670,16},monitored_by}]},{type,{3670,33},union,[{type,{3670,33},tuple,[{atom,{3670,34},monitored_by},{var,{3670,48},'MonitoredBy'}]},{atom,{3670,63},undefined}]}]},[{type,{3671,7},constraint,[{atom,{3671,7},is_subtype},[{var,{3671,7},'Port'},{type,{3671,15},union,[{type,{3671,15},port,[]},{type,{3671,24},atom,[]}]}]]},{type,{3672,7},constraint,[{atom,{3672,7},is_subtype},[{var,{3672,7},'MonitoredBy'},{type,{3672,22},list,[{type,{3672,23},pid,[]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<78,97,109,101>>]},<<32,105,115,32,116,104,101,32,99,111,109,109,97,110,100,32,110,97,109,101,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,95,112,111,114,116,47,50>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,48,48>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3673,9},bounded_fun,[{type,{3673,9},'fun',[{type,{3673,9},product,[{var,{3673,10},'Port'},{atom,{3673,16},name}]},{type,{3673,25},union,[{type,{3673,25},tuple,[{atom,{3673,26},name},{var,{3673,32},'Name'}]},{atom,{3673,40},undefined}]}]},[{type,{3674,7},constraint,[{atom,{3674,7},is_subtype},[{var,{3674,7},'Port'},{type,{3674,15},union,[{type,{3674,15},port,[]},{type,{3674,24},atom,[]}]}]]},{type,{3675,7},constraint,[{atom,{3675,7},is_subtype},[{var,{3675,7},'Name'},{type,{3675,15},string,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<79,115,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,111,114,32,101,113,117,105,118,97,108,101,110,116,41,32,111,102,32,97,110,32,79,83,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,95,112,111,114,116,40,123,115,112,97,119,110,32,124,32,115,112,97,119,110,95,101,120,101,99,117,116,97,98,108,101,44,32,67,111,109,109,97,110,100,125,44,32,79,112,116,105,111,110,115,41>>]}]},<<46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,110,111,116,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,112,97,119,110,105,110,103,32,97,110,32,79,83,32,112,114,111,99,101,115,115,44,32,116,104,101,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,49,54>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3676,9},bounded_fun,[{type,{3676,9},'fun',[{type,{3676,9},product,[{var,{3676,10},'Port'},{atom,{3676,16},os_pid}]},{type,{3676,27},union,[{type,{3676,27},tuple,[{atom,{3676,28},os_pid},{var,{3676,36},'OsPid'}]},{atom,{3676,45},undefined}]}]},[{type,{3677,7},constraint,[{atom,{3677,7},is_subtype},[{var,{3677,7},'Port'},{type,{3677,15},union,[{type,{3677,15},port,[]},{type,{3677,24},atom,[]}]}]]},{type,{3678,7},constraint,[{atom,{3678,7},is_subtype},[{var,{3678,7},'OsPid'},{type,{3678,16},union,[{type,{3678,16},non_neg_integer,[]},{atom,{3678,36},undefined}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,119,114,105,116,116,101,110,32,116,111,32,116,104,101,32,112,111,114,116,32,102,114,111,109,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,111,114,116,95,99,111,109,109,97,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,50>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,111,114,116,95,99,111,109,109,97,110,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,114,116,95,99,111,109,109,97,110,100,47,51>>]}]},<<44,32,111,114,32>>,{code,[],[<<80,111,114,116,32,33,32,123,79,119,110,101,114,44,32,123,99,111,109,109,97,110,100,44,32,68,97,116,97,125>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,51,53>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3679,9},bounded_fun,[{type,{3679,9},'fun',[{type,{3679,9},product,[{var,{3679,10},'Port'},{atom,{3679,16},output}]},{type,{3679,27},union,[{type,{3679,27},tuple,[{atom,{3679,28},output},{var,{3679,36},'Bytes'}]},{atom,{3679,45},undefined}]}]},[{type,{3680,7},constraint,[{atom,{3680,7},is_subtype},[{var,{3680,7},'Port'},{type,{3680,15},union,[{type,{3680,15},port,[]},{type,{3680,24},atom,[]}]}]]},{type,{3681,7},constraint,[{atom,{3681,7},is_subtype},[{var,{3681,7},'Bytes'},{type,{3681,16},non_neg_integer,[]}]]}]]}]}}]}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,111,111,108,101,97,110>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,112,111,114,116,32,112,97,114,97,108,108,101,108,105,115,109,32,104,105,110,116,32,117,115,101,100,32,98,121,32,116,104,105,115,32,112,111,114,116,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,111,112,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,97,114,97,108,108,101,108,105,115,109>>]}]},<<32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,111,112,101,110,95,112,111,114,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,95,112,111,114,116,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,53,52>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3682,9},bounded_fun,[{type,{3682,9},'fun',[{type,{3682,9},product,[{var,{3682,10},'Port'},{atom,{3682,16},parallelism}]},{type,{3682,32},union,[{type,{3682,32},tuple,[{atom,{3682,33},parallelism},{var,{3682,46},'Boolean'}]},{atom,{3682,57},undefined}]}]},[{type,{3683,7},constraint,[{atom,{3683,7},is_subtype},[{var,{3683,7},'Port'},{type,{3683,15},union,[{type,{3683,15},port,[]},{type,{3683,24},atom,[]}]}]]},{type,{3684,7},constraint,[{atom,{3684,7},is_subtype},[{var,{3684,7},'Boolean'},{type,{3684,18},boolean,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,113,117,101,117,101,100,32,98,121,32,116,104,101,32,112,111,114,116,32,117,115,105,110,103,32,116,104,101,32,69,82,84,83,32,100,114,105,118,101,114,32,113,117,101,117,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,54,53>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3685,9},bounded_fun,[{type,{3685,9},'fun',[{type,{3685,9},product,[{var,{3685,10},'Port'},{atom,{3685,16},queue_size}]},{type,{3685,31},union,[{type,{3685,31},tuple,[{atom,{3685,32},queue_size},{var,{3685,44},'Bytes'}]},{atom,{3685,53},undefined}]}]},[{type,{3686,7},constraint,[{atom,{3686,7},is_subtype},[{var,{3686,7},'Port'},{type,{3686,15},union,[{type,{3686,15},port,[]},{type,{3686,24},atom,[]}]}]]},{type,{3687,7},constraint,[{atom,{3687,7},is_subtype},[{var,{3687,7},'Bytes'},{type,{3687,16},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,port_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3649}],[<<112,111,114,116,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<82,101,103,105,115,116,101,114,101,100,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,111,102,32,116,104,101,32,112,111,114,116,46,32,73,102,32,116,104,101,32,112,111,114,116,32,104,97,115,32,110,111,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,111,112,101,110,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32,116,104,101,32,112,111,114,116,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,108,105,110,107,101,100,32,116,111,32,116,104,101,32,112,111,114,116,44,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,116,104,101,32,112,111,114,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<112,111,114,116,95,105,110,102,111,47,50>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,97,110,32,97,116,111,109,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,56,50>>,signature => [{attribute,{3649,2},spec,{{erlang,port_info,2},[{type,{3688,9},bounded_fun,[{type,{3688,9},'fun',[{type,{3688,9},product,[{var,{3688,10},'Port'},{atom,{3688,16},registered_name}]},{type,{3688,36},union,[{type,{3688,36},tuple,[{atom,{3688,37},registered_name},{var,{3688,54},'RegisteredName'}]},{type,{3688,72},nil,[]},{atom,{3688,77},undefined}]}]},[{type,{3689,7},constraint,[{atom,{3689,7},is_subtype},[{var,{3689,7},'Port'},{type,{3689,15},union,[{type,{3689,15},port,[]},{type,{3689,24},atom,[]}]}]]},{type,{3690,7},constraint,[{atom,{3690,7},is_subtype},[{var,{3690,7},'RegisteredName'},{type,{3690,25},atom,[]}]]}]]}]}}]}},{{function,port_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1569}],[<<112,111,114,116,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32>>,{code,[],[<<80,111,114,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,53,57,57,57>>,signature => [{attribute,{1569,2},spec,{{port_to_list,1},[{type,{1569,19},bounded_fun,[{type,{1569,19},'fun',[{type,{1569,19},product,[{var,{1569,20},'Port'}]},{type,{1569,29},string,[]}]},[{type,{1570,7},constraint,[{atom,{1570,7},is_subtype},[{var,{1570,7},'Port'},{type,{1570,15},port,[]}]]}]]}]}}]}},{{function,ports,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1575}],[<<112,111,114,116,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,97,108,108,32,116,104,101,32,112,111,114,116,115,32,101,120,105,115,116,105,110,103,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,32,101,120,105,116,105,110,103,32,112,111,114,116,32,101,120,105,115,116,115,44,32,98,117,116,32,105,115,32,110,111,116,32,111,112,101,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,48,56>>,signature => [{attribute,{1575,2},spec,{{erlang,ports,0},[{type,{1575,19},'fun',[{type,{1575,19},product,[]},{type,{1575,25},list,[{type,{1575,26},port,[]}]}]}]}}]}},{{function,pre_loaded,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1721}],[<<112,114,101,95,108,111,97,100,101,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,69,114,108,97,110,103,32,109,111,100,117,108,101,115,32,116,104,97,116,32,97,114,101,32,112,114,101,108,111,97,100,101,100,32,105,110,32,116,104,101,32,114,117,110,45,116,105,109,101,32,115,121,115,116,101,109,46,32,80,114,101,45,108,111,97,100,101,100,32,109,111,100,117,108,101,115,32,97,114,101,32,69,114,108,97,110,103,32,109,111,100,117,108,101,115,32,116,104,97,116,32,97,114,101,32,110,101,101,100,101,100,32,116,111,32,98,111,111,116,115,116,114,97,112,32,116,104,101,32,115,121,115,116,101,109,32,116,111,32,108,111,97,100,32,116,104,101,32,102,105,114,115,116,32,69,114,108,97,110,103,32,109,111,100,117,108,101,115,32,102,114,111,109,32,101,105,116,104,101,114,32,100,105,115,107,32,111,114,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<107,101,114,110,101,108,58,101,114,108,95,98,111,111,116,95,115,101,114,118,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,98,111,111,116,95,115,101,114,118,101,114>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,49,56>>,signature => [{attribute,{1721,2},spec,{{pre_loaded,0},[{type,{1721,17},'fun',[{type,{1721,17},product,[]},{type,{1721,23},list,[{type,{1721,24},module,[]}]}]}]}}]}},{{function,process_display,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1726}],[<<112,114,111,99,101,115,115,95,100,105,115,112,108,97,121,47,50>>],#{<<101,110>> => [{p,[],[<<87,114,105,116,101,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<32,111,110,32,115,116,97,110,100,97,114,100,32,101,114,114,111,114,46,32,84,104,101,32,111,110,108,121,32,97,108,108,111,119,101,100,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<98,97,99,107,116,114,97,99,101>>]},<<44,32,119,104,105,99,104,32,115,104,111,119,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32,99,97,108,108,32,115,116,97,99,107,44,32,105,110,99,108,117,100,105,110,103,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,97,108,108,32,99,104,97,105,110,44,32,119,105,116,104,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,112,114,105,110,116,101,100,32,102,105,114,115,116,46,32,84,104,101,32,102,111,114,109,97,116,32,111,102,32,116,104,101,32,111,117,116,112,117,116,32,105,115,32,110,111,116,32,102,117,114,116,104,101,114,32,100,101,102,105,110,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,51,48>>,signature => [{attribute,{1726,2},spec,{{erlang,process_display,2},[{type,{1726,29},bounded_fun,[{type,{1726,29},'fun',[{type,{1726,29},product,[{var,{1726,30},'Pid'},{var,{1726,35},'Type'}]},{atom,{1726,44},true}]},[{type,{1727,7},constraint,[{atom,{1727,7},is_subtype},[{var,{1727,7},'Pid'},{type,{1727,14},pid,[]}]]},{type,{1728,7},constraint,[{atom,{1728,7},is_subtype},[{var,{1728,7},'Type'},{atom,{1728,15},backtrace}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<87,104,101,110,32>>,{code,[],[<<116,114,97,112,95,101,120,105,116>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,101,120,105,116,32,115,105,103,110,97,108,115,32,97,114,114,105,118,105,110,103,32,116,111,32,97,32,112,114,111,99,101,115,115,32,97,114,101,32,99,111,110,118,101,114,116,101,100,32,116,111,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,70,114,111,109,44,32,82,101,97,115,111,110,125>>]},<<32,109,101,115,115,97,103,101,115,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,114,101,99,101,105,118,101,100,32,97,115,32,111,114,100,105,110,97,114,121,32,109,101,115,115,97,103,101,115,46,32,73,102,32>>,{code,[],[<<116,114,97,112,95,101,120,105,116>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,32,105,102,32,105,116,32,114,101,99,101,105,118,101,115,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,111,116,104,101,114,32,116,104,97,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32,116,104,101,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,112,114,111,112,97,103,97,116,101,100,32,116,111,32,105,116,115,32,108,105,110,107,101,100,32,112,114,111,99,101,115,115,101,115,46,32,65,112,112,108,105,99,97,116,105,111,110,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,110,111,114,109,97,108,108,121,32,110,111,116,32,116,111,32,116,114,97,112,32,101,120,105,116,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,120,105,116,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,52,52>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2419,19},bounded_fun,[{type,{2419,19},'fun',[{type,{2419,19},product,[{atom,{2419,20},trap_exit},{var,{2419,31},'Boolean'}]},{var,{2419,43},'OldBoolean'}]},[{type,{2420,7},constraint,[{atom,{2420,7},is_subtype},[{var,{2420,7},'Boolean'},{type,{2420,18},boolean,[]}]]},{type,{2421,7},constraint,[{atom,{2421,7},is_subtype},[{var,{2421,7},'OldBoolean'},{type,{2421,21},boolean,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<85,115,101,100,32,98,121,32,97,32,112,114,111,99,101,115,115,32,116,111,32,114,101,100,101,102,105,110,101,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,102,111,114,32,117,110,100,101,102,105,110,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,110,100,32,117,110,100,101,102,105,110,101,100,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,101,115,46,32,73,110,101,120,112,101,114,105,101,110,99,101,100,32,117,115,101,114,115,32,97,114,101,32,110,111,116,32,116,111,32,117,115,101,32,116,104,105,115,32,102,108,97,103,44,32,97,115,32,99,111,100,101,32,97,117,116,111,45,108,111,97,100,105,110,103,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,99,111,114,114,101,99,116,32,111,112,101,114,97,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103,32,109,111,100,117,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,54,50>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2422,19},bounded_fun,[{type,{2422,19},'fun',[{type,{2422,19},product,[{atom,{2422,20},error_handler},{var,{2422,35},'Module'}]},{var,{2422,46},'OldModule'}]},[{type,{2423,7},constraint,[{atom,{2423,7},is_subtype},[{var,{2423,7},'Module'},{type,{2423,17},atom,[]}]]},{type,{2424,7},constraint,[{atom,{2424,7},is_subtype},[{var,{2424,7},'OldModule'},{type,{2424,20},atom,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,103,101,110,101,114,97,116,105,111,110,97,108,32,99,111,108,108,101,99,116,105,111,110,115,32,98,101,102,111,114,101,32,102,111,114,99,105,110,103,32,97,32,102,117,108,108,115,119,101,101,112,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,55,54>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2425,19},bounded_fun,[{type,{2425,19},'fun',[{type,{2425,19},product,[{atom,{2425,20},fullsweep_after},{var,{2425,37},'FullsweepAfter'}]},{var,{2425,56},'OldFullsweepAfter'}]},[{type,{2426,7},constraint,[{atom,{2426,7},is_subtype},[{var,{2426,7},'FullsweepAfter'},{type,{2426,25},non_neg_integer,[]}]]},{type,{2427,7},constraint,[{atom,{2427,7},is_subtype},[{var,{2427,7},'OldFullsweepAfter'},{type,{2427,28},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,56,55>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2428,19},bounded_fun,[{type,{2428,19},'fun',[{type,{2428,19},product,[{atom,{2428,20},min_heap_size},{var,{2428,35},'MinHeapSize'}]},{var,{2428,51},'OldMinHeapSize'}]},[{type,{2429,7},constraint,[{atom,{2429,7},is_subtype},[{var,{2429,7},'MinHeapSize'},{type,{2429,22},non_neg_integer,[]}]]},{type,{2430,7},constraint,[{atom,{2430,7},is_subtype},[{var,{2430,7},'OldMinHeapSize'},{type,{2430,25},non_neg_integer,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,48,57,56>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2431,19},bounded_fun,[{type,{2431,19},'fun',[{type,{2431,19},product,[{atom,{2431,20},min_bin_vheap_size},{var,{2431,40},'MinBinVHeapSize'}]},{var,{2431,60},'OldMinBinVHeapSize'}]},[{type,{2432,7},constraint,[{atom,{2432,7},is_subtype},[{var,{2432,7},'MinBinVHeapSize'},{type,{2432,26},non_neg_integer,[]}]]},{type,{2433,7},constraint,[{atom,{2433,7},is_subtype},[{var,{2433,7},'OldMinBinVHeapSize'},{type,{2433,29},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,51,66,48,52>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]}]},{p,[],[<<84,104,105,115,32,102,108,97,103,32,115,101,116,115,32,116,104,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,73,102,32>>,{code,[],[<<77,97,120,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<107,105,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,114,111,114,95,108,111,103,103,101,114>>]},<<32,97,114,101,32,117,115,101,100,46>>]},{dl,[],[{dt,[],[{code,[],[<<115,105,122,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,115,105,122,101,32,105,110,32,119,111,114,100,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,73,102,32,115,101,116,32,116,111,32,122,101,114,111,44,32,116,104,101,32,104,101,97,112,32,115,105,122,101,32,108,105,109,105,116,32,105,115,32,100,105,115,97,98,108,101,100,46,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,115,32,98,101,32,116,104,114,111,119,110,32,105,102,32,116,104,101,32,118,97,108,117,101,32,105,115,32,115,109,97,108,108,101,114,32,116,104,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,105,110,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]}]},<<46,32,84,104,101,32,115,105,122,101,32,99,104,101,99,107,32,105,115,32,111,110,108,121,32,100,111,110,101,32,119,104,101,110,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,116,114,105,103,103,101,114,101,100,46>>]},{p,[],[{code,[],[<<115,105,122,101>>]},<<32,105,115,32,116,104,101,32,101,110,116,105,114,101,32,104,101,97,112,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,119,104,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,116,114,105,103,103,101,114,101,100,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,97,108,108,32,103,101,110,101,114,97,116,105,111,110,97,108,32,104,101,97,112,115,44,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,44,32,97,110,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,101,115,115,97,103,101,115,32,116,104,97,116,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,104,101,97,112>>]},<<44,32,97,110,100,32,97,110,121,32,101,120,116,114,97,32,109,101,109,111,114,121,32,116,104,97,116,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,111,114,32,110,101,101,100,115,32,100,117,114,105,110,103,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[{code,[],[<<115,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,95,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,112,114,111,99,101,115,115,95,105,110,102,111,40,80,105,100,44,32,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101,41>>]}]},<<44,32,111,114,32,98,121,32,97,100,100,105,110,103,32>>,{code,[],[<<104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<111,108,100,95,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<32,97,110,100,32>>,{code,[],[<<109,98,117,102,95,115,105,122,101>>]},<<32,102,114,111,109,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,112,114,111,99,101,115,115,95,105,110,102,111,40,80,105,100,44,32,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<107,105,108,108>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,101,110,100,115,32,97,110,32,117,110,116,114,97,112,112,97,98,108,101,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<107,105,108,108>>]},<<32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,102,32,116,104,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,105,115,32,114,101,97,99,104,101,100,46,32,84,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,116,104,97,116,32,116,114,105,103,103,101,114,101,100,32,116,104,101,32>>,{code,[],[<<107,105,108,108>>]},<<32,105,115,32,110,111,116,32,99,111,109,112,108,101,116,101,100,44,32,105,110,115,116,101,97,100,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,32,97,115,32,115,111,111,110,32,97,115,32,112,111,115,115,105,98,108,101,46,32,87,104,101,110,32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,110,111,32,101,120,105,116,32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,44,32,105,110,115,116,101,97,100,32,105,116,32,99,111,110,116,105,110,117,101,115,32,101,120,101,99,117,116,105,110,103,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<107,105,108,108>>]},<<32,105,115,32,110,111,116,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,109,97,112,44,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,119,105,108,108,32,98,101,32,117,115,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,101,105,116,104,101,114,32,111,112,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<43,104,109,97,120,107>>]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<101,114,114,111,114,95,108,111,103,103,101,114>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32,115,101,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,108,111,103,115,32,97,110,32,101,114,114,111,114,32,101,118,101,110,116,32,118,105,97,32>>,{a,[{href,<<107,101,114,110,101,108,58,108,111,103,103,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,103,103,101,114>>]}]},<<44,32,99,111,110,116,97,105,110,105,110,103,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,119,104,101,110,32,116,104,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,105,115,32,114,101,97,99,104,101,100,46,32,79,110,101,32,108,111,103,32,101,118,101,110,116,32,105,115,32,115,101,110,116,32,101,97,99,104,32,116,105,109,101,32,116,104,101,32,108,105,109,105,116,32,105,115,32,114,101,97,99,104,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<101,114,114,111,114,95,108,111,103,103,101,114>>]},<<32,105,115,32,110,111,116,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,109,97,112,44,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,105,115,32,117,115,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,101,105,116,104,101,114,32,116,104,101,32,111,112,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<43,104,109,97,120,101,108>>]},<<32,105,110,116,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46>>]}]}]},{p,[],[<<84,104,101,32,104,101,97,112,32,115,105,122,101,32,111,102,32,97,32,112,114,111,99,101,115,115,32,105,115,32,113,117,105,116,101,32,104,97,114,100,32,116,111,32,112,114,101,100,105,99,116,44,32,101,115,112,101,99,105,97,108,108,121,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,116,104,97,116,32,105,115,32,117,115,101,100,32,100,117,114,105,110,103,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,104,101,110,32,99,111,110,116,101,109,112,108,97,116,105,110,103,32,117,115,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,102,105,114,115,116,32,114,117,110,32,105,116,32,105,110,32,112,114,111,100,117,99,116,105,111,110,32,119,105,116,104,32>>,{code,[],[<<107,105,108,108>>]},<<32,115,101,116,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,97,110,100,32,105,110,115,112,101,99,116,32,116,104,101,32,108,111,103,32,101,118,101,110,116,115,32,116,111,32,115,101,101,32,119,104,97,116,32,116,104,101,32,110,111,114,109,97,108,32,112,101,97,107,32,115,105,122,101,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,105,115,32,97,110,100,32,116,104,101,110,32,116,117,110,101,32,116,104,101,32,118,97,108,117,101,32,97,99,99,111,114,100,105,110,103,108,121,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,49,48,57>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2434,19},bounded_fun,[{type,{2434,19},'fun',[{type,{2434,19},product,[{atom,{2434,20},max_heap_size},{var,{2434,35},'MaxHeapSize'}]},{var,{2434,51},'OldMaxHeapSize'}]},[{type,{2435,7},constraint,[{atom,{2435,7},is_subtype},[{var,{2435,7},'MaxHeapSize'},{user_type,{2435,22},max_heap_size,[]}]]},{type,{2436,7},constraint,[{atom,{2436,7},is_subtype},[{var,{2436,7},'OldMaxHeapSize'},{user_type,{2436,25},max_heap_size,[]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]}]},{p,[],[<<68,101,116,101,114,109,105,110,101,115,32,104,111,119,32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,114,101,32,115,116,111,114,101,100,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<111,102,102,95,104,101,97,112>>]}]},{dd,[],[{p,[],[{em,[],[<<65,108,108>>]},<<32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,98,101,32,115,116,111,114,101,100,32,111,117,116,115,105,100,101,32,116,104,101,32,112,114,111,99,101,115,115,32,104,101,97,112,46,32,84,104,105,115,32,105,109,112,108,105,101,115,32,116,104,97,116,32>>,{em,[],[<<110,111>>]},<<32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,98,101,32,112,97,114,116,32,111,102,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<111,110,95,104,101,97,112>>]}]},{dd,[],[{p,[],[<<65,108,108,32,109,101,115,115,97,103,101,115,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,119,105,108,108,32,101,118,101,110,116,117,97,108,108,121,32,98,101,32,112,108,97,99,101,100,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,104,101,97,112,46,32,84,104,101,121,32,99,97,110,44,32,104,111,119,101,118,101,114,44,32,98,101,32,116,101,109,112,111,114,97,114,105,108,121,32,115,116,111,114,101,100,32,111,102,102,32,116,104,101,32,104,101,97,112,46,32,84,104,105,115,32,105,115,32,104,111,119,32,109,101,115,115,97,103,101,115,32,104,97,118,101,32,97,108,119,97,121,115,32,98,101,101,110,32,115,116,111,114,101,100,32,117,112,32,117,110,116,105,108,32,69,82,84,83,32,56,46,48,46>>]}]}]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,113,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,113,100>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,109,97,121,32,112,111,116,101,110,116,105,97,108,108,121,32,97,99,99,117,109,117,108,97,116,101,32,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,109,101,115,115,97,103,101,115,32,105,110,32,105,116,115,32,113,117,101,117,101,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,115,101,116,32,116,104,101,32,102,108,97,103,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<46,32,84,104,105,115,32,105,115,32,100,117,101,32,116,111,32,116,104,101,32,102,97,99,116,32,116,104,97,116,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,109,101,115,115,97,103,101,115,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,104,101,97,112,32,99,97,110,32,98,101,99,111,109,101,32,101,120,116,114,101,109,101,108,121,32,101,120,112,101,110,115,105,118,101,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,110,32,99,111,110,115,117,109,101,32,108,97,114,103,101,32,97,109,111,117,110,116,115,32,111,102,32,109,101,109,111,114,121,46,32,84,104,101,32,112,101,114,102,111,114,109,97,110,99,101,32,111,102,32,116,104,101,32,97,99,116,117,97,108,32,109,101,115,115,97,103,101,32,112,97,115,115,105,110,103,32,105,115,44,32,104,111,119,101,118,101,114,44,32,103,101,110,101,114,97,108,108,121,32,98,101,116,116,101,114,32,119,104,101,110,32,116,104,101,32,102,108,97,103,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46>>]},{p,[],[<<67,104,97,110,103,105,110,103,32,116,104,101,32,102,108,97,103,32,118,97,108,117,101,32,99,97,117,115,101,115,32,97,110,121,32,101,120,105,115,116,105,110,103,32,109,101,115,115,97,103,101,115,32,116,111,32,98,101,32,109,111,118,101,100,46,32,84,104,101,32,109,111,118,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,105,110,105,116,105,97,116,101,100,44,32,98,117,116,32,110,111,116,32,110,101,99,101,115,115,97,114,105,108,121,32,99,111,109,112,108,101,116,101,100,44,32,98,121,32,116,104,101,32,116,105,109,101,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,49,56,51>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2437,19},bounded_fun,[{type,{2437,19},'fun',[{type,{2437,19},product,[{atom,{2437,20},message_queue_data},{var,{2437,40},'MQD'}]},{var,{2437,48},'OldMQD'}]},[{type,{2438,7},constraint,[{atom,{2438,7},is_subtype},[{var,{2438,7},'MQD'},{user_type,{2438,14},message_queue_data,[]}]]},{type,{2439,7},constraint,[{atom,{2439,7},is_subtype},[{var,{2439,7},'OldMQD'},{user_type,{2439,17},message_queue_data,[]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,112,114,105,111,114,105,116,121,46,32>>,{code,[],[<<76,101,118,101,108>>]},<<32,105,115,32,97,110,32,97,116,111,109,46,32,70,111,117,114,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,115,32,101,120,105,115,116,58,32>>,{code,[],[<<108,111,119>>]},<<44,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<44,32>>,{code,[],[<<104,105,103,104>>]},<<44,32,97,110,100,32>>,{code,[],[<<109,97,120>>]},<<46,32,68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<80,114,105,111,114,105,116,121,32,108,101,118,101,108,32>>,{code,[],[<<109,97,120>>]},<<32,105,115,32,114,101,115,101,114,118,101,100,32,102,111,114,32,105,110,116,101,114,110,97,108,32,117,115,101,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,44,32,97,110,100,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,98,101,32,117,115,101,100,32,98,121,32,111,116,104,101,114,115,46>>]}]},{p,[],[<<73,110,116,101,114,110,97,108,108,121,32,105,110,32,101,97,99,104,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,44,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,115,99,104,101,100,117,108,101,100,32,105,110,32,97,32,114,111,117,110,100,32,114,111,98,105,110,32,102,97,115,104,105,111,110,46>>]},{p,[],[<<69,120,101,99,117,116,105,111,110,32,111,102,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32>>,{code,[],[<<108,111,119>>]},<<32,97,114,101,32,105,110,116,101,114,108,101,97,118,101,100,46,32,80,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<32,97,114,101,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,32,108,101,115,115,32,102,114,101,113,117,101,110,116,108,121,32,116,104,97,110,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{p,[],[<<87,104,101,110,32,114,117,110,110,97,98,108,101,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<32,101,120,105,115,116,44,32,110,111,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<32,111,114,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,114,101,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,46,32,78,111,116,105,99,101,32,104,111,119,101,118,101,114,32,116,104,97,116,32,116,104,105,115,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,109,101,97,110,32,116,104,97,116,32,110,111,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<32,111,114,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,99,97,110,32,114,117,110,32,119,104,101,110,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,114,117,110,110,105,110,103,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<46,32,87,104,101,110,32,117,115,105,110,103,32,109,117,108,116,105,112,108,101,32,115,99,104,101,100,117,108,101,114,115,44,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,32,99,97,110,32,98,101,32,114,117,110,110,105,110,103,32,105,110,32,112,97,114,97,108,108,101,108,32,116,104,97,110,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<46,32,84,104,97,116,32,105,115,44,32,97,32>>,{code,[],[<<108,111,119>>]},<<32,97,110,100,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,99,97,110,32,101,120,101,99,117,116,101,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46>>]},{p,[],[<<87,104,101,110,32,114,117,110,110,97,98,108,101,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<109,97,120>>]},<<32,101,120,105,115,116,44,32,110,111,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<108,111,119>>]},<<44,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<44,32,111,114,32>>,{code,[],[<<104,105,103,104>>]},<<32,97,114,101,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,46,32,65,115,32,119,105,116,104,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<44,32,112,114,111,99,101,115,115,101,115,32,111,110,32,108,111,119,101,114,32,112,114,105,111,114,105,116,105,101,115,32,99,97,110,32,101,120,101,99,117,116,101,32,105,110,32,112,97,114,97,108,108,101,108,32,119,105,116,104,32,112,114,111,99,101,115,115,101,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<109,97,120>>]},<<46>>]},{p,[],[<<83,99,104,101,100,117,108,105,110,103,32,105,115,32,112,114,101,45,101,109,112,116,105,118,101,46,32,82,101,103,97,114,100,108,101,115,115,32,111,102,32,112,114,105,111,114,105,116,121,44,32,97,32,112,114,111,99,101,115,115,32,105,115,32,112,114,101,45,101,109,112,116,101,100,32,119,104,101,110,32,105,116,32,104,97,115,32,99,111,110,115,117,109,101,100,32,109,111,114,101,32,116,104,97,110,32,97,32,99,101,114,116,97,105,110,32,110,117,109,98,101,114,32,111,102,32,114,101,100,117,99,116,105,111,110,115,32,115,105,110,99,101,32,116,104,101,32,108,97,115,116,32,116,105,109,101,32,105,116,32,119,97,115,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<68,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,115,99,104,101,100,117,108,105,110,103,32,116,111,32,114,101,109,97,105,110,32,101,120,97,99,116,108,121,32,97,115,32,105,116,32,105,115,32,116,111,100,97,121,46,32,83,99,104,101,100,117,108,105,110,103,32,105,115,32,108,105,107,101,108,121,32,116,111,32,98,101,32,99,104,97,110,103,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,32,116,111,32,117,115,101,32,97,118,97,105,108,97,98,108,101,32,112,114,111,99,101,115,115,111,114,32,99,111,114,101,115,32,98,101,116,116,101,114,46>>]}]},{p,[],[<<84,104,101,114,101,32,105,115,32>>,{em,[],[<<110,111>>]},<<32,97,117,116,111,109,97,116,105,99,32,109,101,99,104,97,110,105,115,109,32,102,111,114,32,97,118,111,105,100,105,110,103,32,112,114,105,111,114,105,116,121,32,105,110,118,101,114,115,105,111,110,44,32,115,117,99,104,32,97,115,32,112,114,105,111,114,105,116,121,32,105,110,104,101,114,105,116,97,110,99,101,32,111,114,32,112,114,105,111,114,105,116,121,32,99,101,105,108,105,110,103,115,46,32,87,104,101,110,32,117,115,105,110,103,32,112,114,105,111,114,105,116,105,101,115,44,32,116,97,107,101,32,116,104,105,115,32,105,110,116,111,32,97,99,99,111,117,110,116,32,97,110,100,32,104,97,110,100,108,101,32,115,117,99,104,32,115,99,101,110,97,114,105,111,115,32,98,121,32,121,111,117,114,115,101,108,102,46>>]},{p,[],[<<77,97,107,105,110,103,32,99,97,108,108,115,32,102,114,111,109,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,105,110,116,111,32,99,111,100,101,32,116,104,97,116,32,121,111,117,32,104,97,115,32,110,111,32,99,111,110,116,114,111,108,32,111,118,101,114,32,99,97,110,32,99,97,117,115,101,32,116,104,101,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,116,111,32,119,97,105,116,32,102,111,114,32,97,32,112,114,111,99,101,115,115,32,119,105,116,104,32,108,111,119,101,114,32,112,114,105,111,114,105,116,121,46,32,84,104,97,116,32,105,115,44,32,101,102,102,101,99,116,105,118,101,108,121,32,100,101,99,114,101,97,115,105,110,103,32,116,104,101,32,112,114,105,111,114,105,116,121,32,111,102,32,116,104,101,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,100,117,114,105,110,103,32,116,104,101,32,99,97,108,108,46,32,69,118,101,110,32,105,102,32,116,104,105,115,32,105,115,32,110,111,116,32,116,104,101,32,99,97,115,101,32,119,105,116,104,32,111,110,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,99,111,100,101,32,116,104,97,116,32,121,111,117,32,104,97,118,101,32,110,111,32,99,111,110,116,114,111,108,32,111,118,101,114,44,32,105,116,32,99,97,110,32,98,101,32,116,104,101,32,99,97,115,101,32,105,110,32,97,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,32,111,102,32,105,116,46,32,84,104,105,115,32,99,97,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,111,99,99,117,114,32,105,102,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,116,114,105,103,103,101,114,115,32,99,111,100,101,32,108,111,97,100,105,110,103,44,32,97,115,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,114,117,110,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{p,[],[<<79,116,104,101,114,32,112,114,105,111,114,105,116,105,101,115,32,116,104,97,110,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<32,97,114,101,32,110,111,114,109,97,108,108,121,32,110,111,116,32,110,101,101,100,101,100,46,32,87,104,101,110,32,111,116,104,101,114,32,112,114,105,111,114,105,116,105,101,115,32,97,114,101,32,117,115,101,100,44,32,117,115,101,32,116,104,101,109,32,119,105,116,104,32,99,97,114,101,44,32>>,{em,[],[<<101,115,112,101,99,105,97,108,108,121>>]},<<32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<46,32,65,32,112,114,111,99,101,115,115,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<104,105,103,104>>]},<<32,105,115,32,111,110,108,121,32,116,111,32,112,101,114,102,111,114,109,32,119,111,114,107,32,102,111,114,32,115,104,111,114,116,32,112,101,114,105,111,100,115,46,32,66,117,115,121,32,108,111,111,112,105,110,103,32,102,111,114,32,108,111,110,103,32,112,101,114,105,111,100,115,32,105,110,32,97,32>>,{code,[],[<<104,105,103,104>>]},<<32,112,114,105,111,114,105,116,121,32,112,114,111,99,101,115,115,32,99,97,117,115,101,115,32,109,111,115,116,32,108,105,107,101,108,121,32,112,114,111,98,108,101,109,115,44,32,97,115,32,105,109,112,111,114,116,97,110,116,32,79,84,80,32,115,101,114,118,101,114,115,32,114,117,110,32,111,110,32,112,114,105,111,114,105,116,121,32>>,{code,[],[<<110,111,114,109,97,108>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,50,50,53>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2440,19},bounded_fun,[{type,{2440,19},'fun',[{type,{2440,19},product,[{atom,{2440,20},priority},{var,{2440,30},'Level'}]},{var,{2440,40},'OldLevel'}]},[{type,{2441,7},constraint,[{atom,{2441,7},is_subtype},[{var,{2441,7},'Level'},{user_type,{2441,16},priority_level,[]}]]},{type,{2442,7},constraint,[{atom,{2442,7},is_subtype},[{var,{2442,7},'OldLevel'},{user_type,{2442,19},priority_level,[]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[{code,[],[<<78>>]},<<32,109,117,115,116,32,98,101,32,97,110,32,105,110,116,101,103,101,114,32,105,110,32,116,104,101,32,105,110,116,101,114,118,97,108,32,48,46,46,49,48,48,48,48,46,32,73,102,32>>,{code,[],[<<78>>]},<<32,62,32,48,44,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,109,97,100,101,32,97,99,116,105,118,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<78>>]},<<32,109,111,115,116,32,114,101,99,101,110,116,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32,66,73,70,32,99,97,108,108,115,44,32,115,101,110,100,115,44,32,97,110,100,32,114,101,99,101,105,118,101,115,32,109,97,100,101,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,97,114,101,32,115,97,118,101,100,32,105,110,32,97,32,108,105,115,116,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,119,105,116,104,32>>,{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,40,80,105,100,44,32,108,97,115,116,95,99,97,108,108,115,41>>]},<<46,32,65,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,105,115,32,111,110,101,32,105,110,32,119,104,105,99,104,32,116,104,101,32,109,111,100,117,108,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,109,101,110,116,105,111,110,101,100,46,32,79,110,108,121,32,97,32,102,105,120,101,100,32,97,109,111,117,110,116,32,111,102,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,115,97,118,101,100,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{ul,[],[{li,[],[{p,[],[<<65,32,116,117,112,108,101,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<32,102,111,114,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115>>]}]},{li,[],[{p,[],[<<84,104,101,32,97,116,111,109,115,32>>,{code,[],[<<115,101,110,100>>]},<<44,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<44,32,97,110,100,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,102,111,114,32,115,101,110,100,115,32,97,110,100,32,114,101,99,101,105,118,101,115,32,40>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,119,104,101,110,32,97,32,109,101,115,115,97,103,101,32,105,115,32,114,101,99,101,105,118,101,100,32,97,110,100,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,119,104,101,110,32,97,32,114,101,99,101,105,118,101,32,116,105,109,101,115,32,111,117,116,41>>]}]}]},{p,[],[<<73,102,32>>,{code,[],[<<78>>]},<<32,61,32,48,44,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,100,105,115,97,98,108,101,100,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46,32,87,104,101,110,101,118,101,114,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,99,97,108,108,32,115,97,118,105,110,103,32,108,105,115,116,32,105,115,32,115,101,116,44,32,105,116,115,32,99,111,110,116,101,110,116,115,32,97,114,101,32,114,101,115,101,116,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,50,57,56>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2443,19},bounded_fun,[{type,{2443,19},'fun',[{type,{2443,19},product,[{atom,{2443,20},save_calls},{var,{2443,32},'N'}]},{var,{2443,38},'OldN'}]},[{type,{2444,7},constraint,[{atom,{2444,7},is_subtype},[{var,{2444,7},'N'},{type,{2444,12},range,[{integer,{2444,12},0},{integer,{2444,15},10000}]}]]},{type,{2445,7},constraint,[{atom,{2445,7},is_subtype},[{var,{2445,7},'OldN'},{type,{2445,15},range,[{integer,{2445,15},0},{integer,{2445,18},10000}]}]]}]]}]}}]}},{{function,process_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2419}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,111,114,32,99,108,101,97,114,115,32,102,108,97,103,32>>,{code,[],[<<115,101,110,115,105,116,105,118,101>>]},<<32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46,32,87,104,101,110,32,97,32,112,114,111,99,101,115,115,32,104,97,115,32,98,101,101,110,32,109,97,114,107,101,100,32,97,115,32,115,101,110,115,105,116,105,118,101,32,98,121,32,99,97,108,108,105,110,103,32>>,{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,115,101,110,115,105,116,105,118,101,44,32,116,114,117,101,41>>]},<<44,32,102,101,97,116,117,114,101,115,32,105,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,101,120,97,109,105,110,105,110,103,32,116,104,101,32,100,97,116,97,32,111,114,32,105,110,110,101,114,32,119,111,114,107,105,110,103,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,97,114,101,32,115,105,108,101,110,116,108,121,32,100,105,115,97,98,108,101,100,46>>]},{p,[],[<<70,101,97,116,117,114,101,115,32,116,104,97,116,32,97,114,101,32,100,105,115,97,98,108,101,100,32,105,110,99,108,117,100,101,32,40,98,117,116,32,97,114,101,32,110,111,116,32,108,105,109,105,116,101,100,32,116,111,41,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{p,[],[<<84,114,97,99,105,110,103,46,32,84,114,97,99,101,32,102,108,97,103,115,32,99,97,110,32,115,116,105,108,108,32,98,101,32,115,101,116,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,98,117,116,32,110,111,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,111,102,32,97,110,121,32,107,105,110,100,32,97,114,101,32,103,101,110,101,114,97,116,101,100,46,32,40,73,102,32,102,108,97,103,32>>,{code,[],[<<115,101,110,115,105,116,105,118,101>>]},<<32,105,115,32,116,117,114,110,101,100,32,111,102,102,44,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,97,103,97,105,110,32,103,101,110,101,114,97,116,101,100,32,105,102,32,97,110,121,32,116,114,97,99,101,32,102,108,97,103,115,32,97,114,101,32,115,101,116,46,41>>]}]},{li,[],[{p,[],[<<83,101,113,117,101,110,116,105,97,108,32,116,114,97,99,105,110,103,46,32,84,104,101,32,115,101,113,117,101,110,116,105,97,108,32,116,114,97,99,101,32,116,111,107,101,110,32,105,115,32,112,114,111,112,97,103,97,116,101,100,32,97,115,32,117,115,117,97,108,44,32,98,117,116,32,110,111,32,115,101,113,117,101,110,116,105,97,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,103,101,110,101,114,97,116,101,100,46>>]}]}]},{p,[],[{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,49,44,50>>]},<<32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,32,116,111,32,114,101,97,100,32,111,117,116,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,40,98,111,116,104,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,101,109,112,116,121,32,108,105,115,116,115,41,46>>]},{p,[],[<<83,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,115,32,99,97,110,110,111,116,32,98,101,32,100,105,115,112,108,97,121,101,100,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,110,32,99,114,97,115,104,32,100,117,109,112,115,44,32,116,104,101,32,115,116,97,99,107,44,32,109,101,115,115,97,103,101,115,44,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,32,97,114,101,32,111,109,105,116,116,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<123,115,97,118,101,95,99,97,108,108,115,44,78,125>>]},<<32,104,97,115,32,98,101,101,110,32,115,101,116,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,110,111,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,114,101,32,115,97,118,101,100,32,116,111,32,116,104,101,32,99,97,108,108,32,115,97,118,105,110,103,32,108,105,115,116,46,32,40,84,104,101,32,99,97,108,108,32,115,97,118,105,110,103,32,108,105,115,116,32,105,115,32,110,111,116,32,99,108,101,97,114,101,100,46,32,65,108,115,111,44,32,115,101,110,100,44,32,114,101,99,101,105,118,101,44,32,97,110,100,32,116,105,109,101,45,111,117,116,32,101,118,101,110,116,115,32,97,114,101,32,115,116,105,108,108,32,97,100,100,101,100,32,116,111,32,116,104,101,32,108,105,115,116,46,41>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,50,57>>,signature => [{attribute,{2419,2},spec,{{process_flag,2},[{type,{2446,19},bounded_fun,[{type,{2446,19},'fun',[{type,{2446,19},product,[{atom,{2446,20},sensitive},{var,{2446,31},'Boolean'}]},{var,{2446,43},'OldBoolean'}]},[{type,{2447,7},constraint,[{atom,{2447,7},is_subtype},[{var,{2447,7},'Boolean'},{type,{2447,18},boolean,[]}]]},{type,{2448,7},constraint,[{atom,{2448,7},is_subtype},[{var,{2448,7},'OldBoolean'},{type,{2448,21},boolean,[]}]]}]]}]}}]}},{{function,process_flag,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1748}],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,99,101,114,116,97,105,110,32,102,108,97,103,115,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<44,32,105,110,32,116,104,101,32,115,97,109,101,32,109,97,110,110,101,114,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46,32,82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46,32,84,104,101,32,118,97,108,105,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<70,108,97,103>>]},<<32,97,114,101,32,111,110,108,121,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,111,115,101,32,97,108,108,111,119,101,100,32,105,110,32>>,{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]},<<44,32,110,97,109,101,108,121,32>>,{code,[],[<<115,97,118,101,95,99,97,108,108,115>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,54,51>>,signature => [{attribute,{1748,2},spec,{{process_flag,3},[{type,{1748,19},bounded_fun,[{type,{1748,19},'fun',[{type,{1748,19},product,[{var,{1748,20},'Pid'},{var,{1748,25},'Flag'},{var,{1748,31},'Value'}]},{var,{1748,41},'OldValue'}]},[{type,{1749,7},constraint,[{atom,{1749,7},is_subtype},[{var,{1749,7},'Pid'},{type,{1749,14},pid,[]}]]},{type,{1750,7},constraint,[{atom,{1750,7},is_subtype},[{var,{1750,7},'Flag'},{atom,{1750,15},save_calls}]]},{type,{1751,7},constraint,[{atom,{1751,7},is_subtype},[{var,{1751,7},'Value'},{type,{1751,16},non_neg_integer,[]}]]},{type,{1752,7},constraint,[{atom,{1752,7},is_subtype},[{var,{1752,7},'OldValue'},{type,{1752,19},non_neg_integer,[]}]]}]]}]}}]}},{{function,process_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1765}],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<112,114,111,99,101,115,115,95,105,110,102,111,95,114,101,115,117,108,116,95,105,116,101,109>>}],[]},{li,[{name,<<115,116,97,99,107,95,105,116,101,109>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,119,105,116,104,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]},{p,[],[<<84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,105,115,32,117,110,100,101,102,105,110,101,100,32,97,110,100,32,97,108,108,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,97,114,101,32,110,111,116,32,109,97,110,100,97,116,111,114,121,46,32,84,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,119,105,116,104,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,116,101,109,115,32,97,114,101,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,58>>]},{ul,[],[{li,[],[{code,[],[<<99,117,114,114,101,110,116,95,102,117,110,99,116,105,111,110>>]}]},{li,[],[{code,[],[<<105,110,105,116,105,97,108,95,99,97,108,108>>]}]},{li,[],[{code,[],[<<115,116,97,116,117,115>>]}]},{li,[],[{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,108,101,110>>]}]},{li,[],[{code,[],[<<108,105,110,107,115>>]}]},{li,[],[{code,[],[<<100,105,99,116,105,111,110,97,114,121>>]}]},{li,[],[{code,[],[<<116,114,97,112,95,101,120,105,116>>]}]},{li,[],[{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]}]},{li,[],[{code,[],[<<112,114,105,111,114,105,116,121>>]}]},{li,[],[{code,[],[<<103,114,111,117,112,95,108,101,97,100,101,114>>]}]},{li,[],[{code,[],[<<116,111,116,97,108,95,104,101,97,112,95,115,105,122,101>>]}]},{li,[],[{code,[],[<<104,101,97,112,95,115,105,122,101>>]}]},{li,[],[{code,[],[<<115,116,97,99,107,95,115,105,122,101>>]}]},{li,[],[{code,[],[<<114,101,100,117,99,116,105,111,110,115>>]}]},{li,[],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]}]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,104,97,115,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32,97,108,115,111,32,97,110,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,119,105,116,104,32,105,116,101,109,32>>,{code,[],[<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,105,115,32,105,110,99,108,117,100,101,100,46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,112,101,99,105,102,105,99,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,50>>]}]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32>>,{em,[],[<<100,101,98,117,103,103,105,110,103,32,111,110,108,121>>]},<<46,32,70,111,114,32,97,108,108,32,111,116,104,101,114,32,112,117,114,112,111,115,101,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,50>>]}]},<<46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,51,55,56>>,signature => [{attribute,{1765,2},spec,{{process_info,1},[{type,{1765,19},bounded_fun,[{type,{1765,19},'fun',[{type,{1765,19},product,[{var,{1765,20},'Pid'}]},{var,{1765,28},'Info'}]},[{type,{1766,7},constraint,[{atom,{1766,7},is_subtype},[{var,{1766,7},'Pid'},{type,{1766,14},pid,[]}]]},{type,{1767,7},constraint,[{atom,{1767,7},is_subtype},[{var,{1767,7},'Info'},{type,{1767,15},union,[{type,{1767,15},list,[{var,{1767,16},'InfoTuple'}]},{atom,{1767,29},undefined}]}]]},{type,{1768,7},constraint,[{atom,{1768,7},is_subtype},[{var,{1768,7},'InfoTuple'},{user_type,{1768,20},process_info_result_item,[]}]]}]]}]}}]}},{{function,process_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2545}],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<112,114,111,99,101,115,115,95,105,110,102,111,95,105,116,101,109>>}],[]},{li,[{name,<<112,114,111,99,101,115,115,95,105,110,102,111,95,114,101,115,117,108,116,95,105,116,101,109>>}],[]},{li,[{name,<<115,116,97,99,107,95,105,116,101,109>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<32,111,114,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]},{p,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,97,108,105,118,101,32,97,110,100,32,97,32,115,105,110,103,108,101,32>>,{code,[],[<<73,116,101,109>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<44,32,117,110,108,101,115,115,32>>,{code,[],[<<73,116,101,109,32,61,58,61,32,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,110,111,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,105,115,32,115,116,114,97,110,103,101,32,98,101,104,97,118,105,111,114,32,105,115,32,98,101,99,97,117,115,101,32,111,102,32,104,105,115,116,111,114,105,99,97,108,32,114,101,97,115,111,110,115,44,32,97,110,100,32,105,115,32,107,101,112,116,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101,76,105,115,116>>]},<<46,32,84,104,101,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,105,110,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101,76,105,115,116>>]},<<32,97,114,101,32,105,110,99,108,117,100,101,100,32,119,105,116,104,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,105,110,32,116,104,101,32,115,97,109,101,32,111,114,100,101,114,32,97,115,32,116,104,101,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,119,101,114,101,32,105,110,99,108,117,100,101,100,32,105,110,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<46,32,86,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,99,97,110,32,98,101,32,105,110,99,108,117,100,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,105,110,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<46>>]},{p,[],[<<71,101,116,116,105,110,103,32,112,114,111,99,101,115,115,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,108,108,111,119,115,32,116,104,101,32,115,105,103,110,97,108,32,111,114,100,101,114,105,110,103,32,103,117,97,114,97,110,116,101,101,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<80,114,111,99,101,115,115,101,115,32,67,104,97,112,116,101,114>>]},<<32,105,110,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32>>,{code,[],[<<114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,105,115,32,112,97,114,116,32,111,102,32>>,{code,[],[<<73,116,101,109,76,105,115,116>>]},<<32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,110,111,32,110,97,109,101,32,114,101,103,105,115,116,101,114,101,100,44,32,97,32>>,{code,[],[<<123,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101,44,32,91,93,125>>]},<<44,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32>>,{em,[],[<<119,105,108,108>>]},<<32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101,76,105,115,116>>]},<<46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,105,115,32,100,105,102,102,101,114,101,110,116,32,119,104,101,110,32,97,32,115,105,110,103,108,101,32>>,{code,[],[<<73,116,101,109,32,61,58,61,32,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,97,110,100,32,119,104,101,110,32>>,{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111,47,49>>]},<<32,105,115,32,117,115,101,100,46>>]}]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<115,32,119,105,116,104,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<73,116,101,109>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,98,97,99,107,116,114,97,99,101,44,32,66,105,110,125>>]}]},{dd,[],[{p,[],[<<66,105,110,97,114,121,32>>,{code,[],[<<66,105,110>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,115,32,116,104,101,32,111,117,116,112,117,116,32,102,114,111,109,32>>,{code,[],[<<101,114,108,97,110,103,58,112,114,111,99,101,115,115,95,100,105,115,112,108,97,121,40,80,105,100,44,32,98,97,99,107,116,114,97,99,101,41>>]},<<46,32,85,115,101,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,108,105,115,116,47,49>>]},<<32,116,111,32,111,98,116,97,105,110,32,116,104,101,32,115,116,114,105,110,103,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,98,105,110,97,114,121,46>>]}]},{dt,[],[{code,[],[<<123,98,105,110,97,114,121,44,32,66,105,110,73,110,102,111,125>>]}]},{dd,[],[{p,[],[{code,[],[<<66,105,110,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,98,105,110,97,114,105,101,115,32,111,110,32,116,104,101,32,104,101,97,112,32,111,102,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46,32,73,110,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32>>,{code,[],[<<66,105,110,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,46,32,84,104,101,32,116,117,112,108,101,115,32,99,111,110,116,97,105,110,59,32>>,{code,[],[<<66,105,110,97,114,121,73,100>>]},<<44,32>>,{code,[],[<<66,105,110,97,114,121,83,105,122,101>>]},<<44,32>>,{code,[],[<<66,105,110,97,114,121,82,101,102,99,67,111,117,110,116>>]},<<46>>]},{p,[],[<<68,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]}]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,109,97,121,32,98,101,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,104,101,97,112,46>>]}]},{dt,[],[{code,[],[<<123,99,97,116,99,104,108,101,118,101,108,44,32,67,97,116,99,104,76,101,118,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<67,97,116,99,104,76,101,118,101,108>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,99,117,114,114,101,110,116,108,121,32,97,99,116,105,118,101,32,99,97,116,99,104,101,115,32,105,110,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,114,101,110,116,95,102,117,110,99,116,105,111,110,44,32,123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125,32,124,32,117,110,100,101,102,105,110,101,100,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,101,32,118,97,108,117,101,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,99,117,114,114,101,110,116,108,121,32,101,120,101,99,117,116,105,110,103,32,110,97,116,105,118,101,32,99,111,109,112,105,108,101,100,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,114,101,110,116,95,108,111,99,97,116,105,111,110,44,32,123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,44,32,76,111,99,97,116,105,111,110,125,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,116,117,112,108,101,115,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,108,111,99,97,116,105,111,110,32,105,110,32,116,104,101,32,115,111,117,114,99,101,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,114,101,110,116,95,115,116,97,99,107,116,114,97,99,101,44,32,83,116,97,99,107,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,99,97,108,108,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,32,40>>,{em,[],[<<115,116,97,99,107,116,114,97,99,101>>]},<<41,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,101,32,115,116,97,99,107,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,115,32,105,110,32,116,104,101,32>>,{code,[],[<<99,97,116,99,104>>]},<<32,112,97,114,116,32,111,102,32,97,32>>,{code,[],[<<116,114,121>>]},<<46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115,35,115,116,97,99,107,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<84,104,101,32,99,97,108,108,45,115,116,97,99,107,32,98,97,99,107,32,116,114,97,99,101,32,40,115,116,97,99,107,116,114,97,99,101,41>>]},<<46,32,84,104,101,32,100,101,112,116,104,32,111,102,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,32,105,115,32,116,114,117,110,99,97,116,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32>>,{code,[],[<<98,97,99,107,116,114,97,99,101,95,100,101,112,116,104>>]},<<32,115,121,115,116,101,109,32,102,108,97,103,32,115,101,116,116,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,100,105,99,116,105,111,110,97,114,121,44,32,68,105,99,116,105,111,110,97,114,121,125>>]}]},{dd,[],[{p,[],[{code,[],[<<68,105,99,116,105,111,110,97,114,121>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,95,104,97,110,100,108,101,114,44,32,77,111,100,117,108,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,109,111,100,117,108,101,32,117,115,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,40,102,111,114,32,117,110,100,101,102,105,110,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32,102,111,114,32,101,120,97,109,112,108,101,41,46>>]}]},{dt,[],[{code,[],[<<123,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,44,32,71,67,73,110,102,111,125>>]}]},{dd,[],[{p,[],[{code,[],[<<71,67,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,102,111,114,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,101,32,99,111,110,116,101,110,116,32,111,102,32>>,{code,[],[<<71,67,73,110,102,111>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{a,[{id,<<112,114,111,99,101,115,115,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111>>}],[]},{code,[],[<<123,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,95,105,110,102,111,44,32,71,67,73,110,102,111,125>>]}]},{dd,[],[{p,[],[{code,[],[<<71,67,73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,100,101,116,97,105,108,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,102,111,114,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,101,32,99,111,110,116,101,110,116,32,111,102,32>>,{code,[],[<<71,67,73,110,102,111>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46,32,70,111,114,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32,109,101,97,110,105,110,103,32,111,102,32,101,97,99,104,32,105,116,101,109,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]}]},<<32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,103,114,111,117,112,95,108,101,97,100,101,114,44,32,71,114,111,117,112,76,101,97,100,101,114,125>>]}]},{dd,[],[{p,[],[{code,[],[<<71,114,111,117,112,76,101,97,100,101,114>>]},<<32,105,115,32,116,104,101,32,103,114,111,117,112,32,108,101,97,100,101,114,32,102,111,114,32,116,104,101,32,73,47,79,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,119,111,114,100,115,32,111,102,32,116,104,101,32,121,111,117,110,103,101,115,116,32,104,101,97,112,32,103,101,110,101,114,97,116,105,111,110,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,103,101,110,101,114,97,116,105,111,110,32,105,110,99,108,117,100,101,115,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,46,32,84,104,105,115,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,44,32,97,110,100,32,99,97,110,32,99,104,97,110,103,101,32,105,102,32,116,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,99,104,97,110,103,101,115,46>>]}]},{dt,[],[{code,[],[<<123,105,110,105,116,105,97,108,95,99,97,108,108,44,32,123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<44,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,105,110,105,116,105,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,119,105,116,104,32,119,104,105,99,104,32,116,104,101,32,112,114,111,99,101,115,115,32,119,97,115,32,115,112,97,119,110,101,100,46>>]}]},{dt,[],[{code,[],[<<123,108,105,110,107,115,44,32,80,105,100,115,65,110,100,80,111,114,116,115,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,105,100,115,65,110,100,80,111,114,116,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,32,97,110,100,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,44,32,119,105,116,104,32,112,114,111,99,101,115,115,101,115,32,111,114,32,112,111,114,116,115,32,116,111,32,119,104,105,99,104,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,97,32,108,105,110,107,46>>]}]},{dt,[],[{code,[],[<<123,108,97,115,116,95,99,97,108,108,115,44,32,102,97,108,115,101,124,67,97,108,108,115,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,110,111,116,32,97,99,116,105,118,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,51>>]}]},<<41,46,32,73,102,32,99,97,108,108,32,115,97,118,105,110,103,32,105,115,32,97,99,116,105,118,101,44,32,97,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,44,32,105,110,32,119,104,105,99,104,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,99,97,108,108,101,100,46>>]}]},{dt,[],[{code,[],[<<123,109,101,109,111,114,121,44,32,83,105,122,101,125>>]}]},{dd,[],[{a,[{id,<<112,114,111,99,101,115,115,95,105,110,102,111,95,109,101,109,111,114,121>>}],[]},{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,121,116,101,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,99,97,108,108,32,115,116,97,99,107,44,32,104,101,97,112,44,32,97,110,100,32,105,110,116,101,114,110,97,108,32,115,116,114,117,99,116,117,114,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,95,113,117,101,117,101,95,108,101,110,44,32,77,101,115,115,97,103,101,81,117,101,117,101,76,101,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,101,115,115,97,103,101,81,117,101,117,101,76,101,110>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,109,101,115,115,97,103,101,115,32,99,117,114,114,101,110,116,108,121,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<77,101,115,115,97,103,101,81,117,101,117,101>>]},<<32,114,101,116,117,114,110,101,100,32,97,115,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,116,101,109,32>>,{code,[],[<<109,101,115,115,97,103,101,115>>]},<<32,40,115,101,101,32,98,101,108,111,119,41,46>>]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,115,44,32,77,101,115,115,97,103,101,81,117,101,117,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,101,115,115,97,103,101,81,117,101,117,101>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,109,101,115,115,97,103,101,115,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,44,32,119,104,105,99,104,32,104,97,118,101,32,110,111,116,32,121,101,116,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,109,105,110,95,104,101,97,112,95,115,105,122,101,44,32,77,105,110,72,101,97,112,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,105,110,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101,44,32,77,105,110,66,105,110,86,72,101,97,112,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,105,110,66,105,110,86,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,101,100,95,98,121,44,32,77,111,110,105,116,111,114,101,100,66,121,125>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,105,100,101,110,116,105,102,105,101,114,115,32,102,111,114,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,44,32,112,111,114,116,115,32,97,110,100,32,78,73,70,32,114,101,115,111,117,114,99,101,115,44,32,116,104,97,116,32,97,114,101,32,109,111,110,105,116,111,114,105,110,103,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,115,44,32,77,111,110,105,116,111,114,115,125>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,111,110,105,116,111,114,115,32,40,115,116,97,114,116,101,100,32,98,121,32>>,{code,[],[<<109,111,110,105,116,111,114,47,50>>]},<<41,32,116,104,97,116,32,97,114,101,32,97,99,116,105,118,101,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,70,111,114,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,32,111,114,32,97,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,32,98,121,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,116,104,101,32,108,105,115,116,32,99,111,110,115,105,115,116,115,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,112,114,111,99,101,115,115,44,32,80,105,100,125>>]}]},{dd,[],[<<80,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,112,105,100,46>>]},{dt,[],[{code,[],[<<123,112,114,111,99,101,115,115,44,32,123,82,101,103,78,97,109,101,44,32,78,111,100,101,125,125>>]}]},{dd,[],[<<76,111,99,97,108,32,111,114,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,110,97,109,101,46>>]},{dt,[],[{code,[],[<<123,112,111,114,116,44,32,80,111,114,116,73,100,125>>]}]},{dd,[],[<<76,111,99,97,108,32,112,111,114,116,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,112,111,114,116,32,105,100,46>>]},{dt,[],[{code,[],[<<123,112,111,114,116,44,32,123,82,101,103,78,97,109,101,44,32,78,111,100,101,125,125>>]}]},{dd,[],[<<76,111,99,97,108,32,112,111,114,116,32,105,115,32,109,111,110,105,116,111,114,101,100,32,98,121,32,110,97,109,101,46,32,80,108,101,97,115,101,32,110,111,116,101,44,32,116,104,97,116,32,114,101,109,111,116,101,32,112,111,114,116,32,109,111,110,105,116,111,114,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,44,32,115,111,32>>,{code,[],[<<78,111,100,101>>]},<<32,119,105,108,108,32,97,108,119,97,121,115,32,98,101,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,110,97,109,101,46>>]}]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,125>>]}]},{dd,[],[{p,[],[{code,[],[<<77,81,68>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,101,105,116,104,101,114,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<32,111,114,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<76,101,118,101,108>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,105,111,114,105,116,105,101,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,100,117,99,116,105,111,110,115,44,32,78,117,109,98,101,114,125>>]}]},{dd,[],[{p,[],[{code,[],[<<78,117,109,98,101,114>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,114,101,100,117,99,116,105,111,110,115,32,101,120,101,99,117,116,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,114,101,103,105,115,116,101,114,101,100,95,110,97,109,101,44,32,65,116,111,109,125>>]}]},{dd,[],[{p,[],[{code,[],[<<65,116,111,109>>]},<<32,105,115,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,32,110,97,109,101,46,32,73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,110,111,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32,116,104,105,115,32,116,117,112,108,101,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,46>>]}]},{dt,[],[{code,[],[<<123,115,101,113,117,101,110,116,105,97,108,95,116,114,97,99,101,95,116,111,107,101,110,44,32,91,93,32,124,32,83,101,113,117,101,110,116,105,97,108,84,114,97,99,101,84,111,107,101,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,101,113,117,101,110,116,105,97,108,84,114,97,99,101,84,111,107,101,110>>]},<<32,105,115,32,116,104,101,32,115,101,113,117,101,110,116,105,97,108,32,116,114,97,99,101,32,116,111,107,101,110,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,115,116,97,99,107,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,115,116,97,99,107,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,44,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46>>]}]},{dt,[],[{code,[],[<<123,115,116,97,116,117,115,44,32,83,116,97,116,117,115,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,116,97,116,117,115>>]},<<32,105,115,32,116,104,101,32,115,116,97,116,117,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,97,110,100,32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{ul,[],[{li,[],[{code,[],[<<101,120,105,116,105,110,103>>]}]},{li,[],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,110,103>>]}]},{li,[],[{code,[],[<<119,97,105,116,105,110,103>>]},<<32,40,102,111,114,32,97,32,109,101,115,115,97,103,101,41>>]},{li,[],[{code,[],[<<114,117,110,110,105,110,103>>]}]},{li,[],[{code,[],[<<114,117,110,110,97,98,108,101>>]},<<32,40,114,101,97,100,121,32,116,111,32,114,117,110,44,32,98,117,116,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,105,115,32,114,117,110,110,105,110,103,41>>]},{li,[],[{code,[],[<<115,117,115,112,101,110,100,101,100>>]},<<32,40,115,117,115,112,101,110,100,101,100,32,111,110,32,97,32,34,98,117,115,121,34,32,112,111,114,116,32,111,114,32,98,121,32,116,104,101,32,66,73,70,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49,44,50>>]},<<41>>]}]}]},{dt,[],[{code,[],[<<123,115,117,115,112,101,110,100,105,110,103,44,32,83,117,115,112,101,110,100,101,101,76,105,115,116,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101,76,105,115,116>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,83,117,115,112,101,110,100,101,101,44,32,65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116,44,32,79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116,125>>]},<<32,116,117,112,108,101,115,46,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,98,101,101,110,44,32,111,114,32,105,115,32,116,111,32,98,101,44,32,115,117,115,112,101,110,100,101,100,32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<32,116,104,114,111,117,103,104,32,116,104,101,32,66,73,70,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>]}]},<<46>>]},{p,[],[{code,[],[<<65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46,32>>,{code,[],[<<79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,110,111,116,32,121,101,116,32,99,111,109,112,108,101,116,101,100,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,115,32,115,101,110,116,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<44,32,116,104,97,116,32,105,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116,32,61,47,61,32,48>>]},<<44,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,99,117,114,114,101,110,116,108,121,32,105,110,32,116,104,101,32,115,117,115,112,101,110,100,101,100,32,115,116,97,116,101,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116,32,61,47,61,32,48>>]},<<44,32,111,112,116,105,111,110,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<32,104,97,115,32,98,101,101,110,32,117,115,101,100,32,97,110,100,32,116,104,101,32,115,117,115,112,101,110,100,101,101,32,104,97,115,32,110,111,116,32,121,101,116,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<65,99,116,105,118,101,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<79,117,116,115,116,97,110,100,105,110,103,83,117,115,112,101,110,100,67,111,117,110,116>>]},<<32,97,114,101,32,110,111,116,32,116,104,101,32,116,111,116,97,108,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<44,32,111,110,108,121,32,116,104,101,32,112,97,114,116,115,32,99,111,110,116,114,105,98,117,116,101,100,32,98,121,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]},{dt,[],[{a,[{id,<<112,114,111,99,101,115,115,95,105,110,102,111,95,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<123,116,111,116,97,108,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<83,105,122,101>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,44,32,111,102,32,97,108,108,32,104,101,97,112,32,102,114,97,103,109,101,110,116,115,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,116,104,101,32,112,114,111,99,101,115,115,32,115,116,97,99,107,32,97,110,100,32,97,110,121,32,117,110,114,101,99,101,105,118,101,100,32,109,101,115,115,97,103,101,115,32,116,104,97,116,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,104,101,97,112,46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,99,101,44,32,73,110,116,101,114,110,97,108,84,114,97,99,101,70,108,97,103,115,125>>]}]},{dd,[],[{p,[],[{code,[],[<<73,110,116,101,114,110,97,108,84,114,97,99,101,70,108,97,103,115>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,105,110,116,101,114,110,97,108,32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32>>,{code,[],[<<73,110,102,111,84,117,112,108,101>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,112,95,101,120,105,116,44,32,66,111,111,108,101,97,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<66,111,111,108,101,97,110>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,110,111,116,32,97,108,108,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,32,115,117,112,112,111,114,116,32,97,108,108,32,116,104,101,115,101,32>>,{code,[],[<<73,116,101,109>>]},<<115,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<73,116,101,109>>]},<<32,105,115,32,97,110,32,105,110,118,97,108,105,100,32,105,116,101,109,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,52,50,57>>,signature => [{attribute,{2545,2},spec,{{process_info,2},[{type,{2545,19},bounded_fun,[{type,{2545,19},'fun',[{type,{2545,19},product,[{var,{2545,20},'Pid'},{var,{2545,25},'Item'}]},{type,{2546,27},union,[{var,{2546,27},'InfoTuple'},{type,{2546,39},nil,[]},{atom,{2546,44},undefined}]}]},[{type,{2547,7},constraint,[{atom,{2547,7},is_subtype},[{var,{2547,7},'Pid'},{type,{2547,14},pid,[]}]]},{type,{2548,7},constraint,[{atom,{2548,7},is_subtype},[{var,{2548,7},'Item'},{user_type,{2548,15},process_info_item,[]}]]},{type,{2549,7},constraint,[{atom,{2549,7},is_subtype},[{var,{2549,7},'InfoTuple'},{user_type,{2549,20},process_info_result_item,[]}]]}]]},{type,{2550,19},bounded_fun,[{type,{2550,19},'fun',[{type,{2550,19},product,[{var,{2550,20},'Pid'},{var,{2550,25},'ItemList'}]},{type,{2550,38},union,[{var,{2550,38},'InfoTupleList'},{type,{2550,54},nil,[]},{atom,{2550,59},undefined}]}]},[{type,{2551,7},constraint,[{atom,{2551,7},is_subtype},[{var,{2551,7},'Pid'},{type,{2551,14},pid,[]}]]},{type,{2552,7},constraint,[{atom,{2552,7},is_subtype},[{var,{2552,7},'ItemList'},{type,{2552,19},list,[{var,{2552,20},'Item'}]}]]},{type,{2553,7},constraint,[{atom,{2553,7},is_subtype},[{var,{2553,7},'Item'},{user_type,{2553,15},process_info_item,[]}]]},{type,{2554,7},constraint,[{atom,{2554,7},is_subtype},[{var,{2554,7},'InfoTupleList'},{type,{2554,24},list,[{var,{2554,25},'InfoTuple'}]}]]},{type,{2555,7},constraint,[{atom,{2555,7},is_subtype},[{var,{2555,7},'InfoTuple'},{user_type,{2555,20},process_info_result_item,[]}]]}]]}]}}]}},{{function,processes,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1773}],[<<112,114,111,99,101,115,115,101,115,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,110,32,101,120,105,116,105,110,103,32,112,114,111,99,101,115,115,32,101,120,105,115,116,115,44,32,98,117,116,32,105,115,32,110,111,116,32,97,108,105,118,101,46,32,84,104,97,116,32,105,115,44,32>>,{code,[],[<<105,115,95,112,114,111,99,101,115,115,95,97,108,105,118,101,47,49>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,102,111,114,32,97,110,32,101,120,105,116,105,110,103,32,112,114,111,99,101,115,115,44,32,98,117,116,32,105,116,115,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<112,114,111,99,101,115,115,101,115,47,48>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,112,114,111,99,101,115,115,101,115,40,41,46,10,91,60,48,46,48,46,48,62,44,60,48,46,50,46,48,62,44,60,48,46,52,46,48,62,44,60,48,46,53,46,48,62,44,60,48,46,55,46,48,62,44,60,48,46,56,46,48,62,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,55,50>>,signature => [{attribute,{1773,2},spec,{{processes,0},[{type,{1773,16},'fun',[{type,{1773,16},product,[]},{type,{1773,22},list,[{type,{1773,23},pid,[]}]}]}]}}]}},{{function,purge_module,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1778}],[<<112,117,114,103,101,95,109,111,100,117,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,109,111,118,101,115,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46,32,66,101,102,111,114,101,32,116,104,105,115,32,66,73,70,32,105,115,32,117,115,101,100,44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,104,101,99,107,95,112,114,111,99,101,115,115,95,99,111,100,101,47,50>>]}]},<<32,105,115,32,116,111,32,98,101,32,99,97,108,108,101,100,32,116,111,32,99,104,101,99,107,32,116,104,97,116,32,110,111,32,112,114,111,99,101,115,115,101,115,32,101,120,101,99,117,116,101,32,111,108,100,32,99,111,100,101,32,105,110,32,116,104,101,32,109,111,100,117,108,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,116,104,101,32,99,111,100,101,32,115,101,114,118,101,114,32,40,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,100,101,40,51,41>>]}]},<<41,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,101,108,115,101,119,104,101,114,101,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,56,46,48,32,40,69,114,108,97,110,103,47,79,84,80,32,49,57,41,44,32,97,110,121,32,108,105,110,103,101,114,105,110,103,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,115,116,105,108,108,32,101,120,101,99,117,116,101,32,116,104,101,32,111,108,100,32,99,111,100,101,32,105,115,32,107,105,108,108,101,100,32,98,121,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46,32,73,110,32,101,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,44,32,115,117,99,104,32,105,110,99,111,114,114,101,99,116,32,117,115,101,32,99,111,117,108,100,32,99,97,117,115,101,32,109,117,99,104,32,109,111,114,101,32,102,97,116,97,108,32,102,97,105,108,117,114,101,115,44,32,108,105,107,101,32,101,109,117,108,97,116,111,114,32,99,114,97,115,104,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,111,108,100,32,99,111,100,101,32,102,111,114,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,55,56,57>>,signature => [{attribute,{1778,2},spec,{{purge_module,1},[{type,{1778,19},bounded_fun,[{type,{1778,19},'fun',[{type,{1778,19},product,[{var,{1778,20},'Module'}]},{atom,{1778,31},true}]},[{type,{1779,7},constraint,[{atom,{1779,7},is_subtype},[{var,{1779,7},'Module'},{type,{1779,17},atom,[]}]]}]]}]}}]}},{{function,put,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1792}],[<<112,117,116,47,50>>],#{<<101,110>> => [{p,[],[<<65,100,100,115,32,97,32,110,101,119,32>>,{code,[],[<<75,101,121>>]},<<32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,44,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<86,97,108>>]},<<44,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46,32,73,102,32>>,{code,[],[<<75,101,121>>]},<<32,101,120,105,115,116,115,44,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,105,115,32,100,101,108,101,116,101,100,32,97,110,100,32,114,101,112,108,97,99,101,100,32,98,121,32>>,{code,[],[<<86,97,108>>]},<<44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,46,32,84,104,101,32,97,118,101,114,97,103,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,79,40>>,{code,[],[<<49>>]},<<41,32,97,110,100,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,116,105,109,101,32,99,111,109,112,108,101,120,105,116,121,32,105,115,32,79,40>>,{code,[],[<<78>>]},<<41,44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,105,116,101,109,115,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,100,105,99,116,105,111,110,97,114,121,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,88,32,61,32,112,117,116,40,110,97,109,101,44,32,119,97,108,114,117,115,41,44,32,89,32,61,32,112,117,116,40,110,97,109,101,44,32,99,97,114,112,101,110,116,101,114,41,44,10,90,32,61,32,103,101,116,40,110,97,109,101,41,44,10,123,88,44,32,89,44,32,90,125,46,10,123,117,110,100,101,102,105,110,101,100,44,119,97,108,114,117,115,44,99,97,114,112,101,110,116,101,114,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,118,97,108,117,101,115,32,115,116,111,114,101,100,32,119,104,101,110,32>>,{code,[],[<<112,117,116>>]},<<32,105,115,32,101,118,97,108,117,97,116,101,100,32,119,105,116,104,105,110,32,116,104,101,32,115,99,111,112,101,32,111,102,32,97,32>>,{code,[],[<<99,97,116,99,104>>]},<<32,97,114,101,32,110,111,116,32,114,101,116,114,97,99,116,101,100,32,105,102,32,97,32>>,{code,[],[<<116,104,114,111,119>>]},<<32,105,115,32,101,118,97,108,117,97,116,101,100,44,32,111,114,32,105,102,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,49,52>>,signature => [{attribute,{1792,2},spec,{{put,2},[{type,{1792,10},bounded_fun,[{type,{1792,10},'fun',[{type,{1792,10},product,[{var,{1792,11},'Key'},{var,{1792,16},'Val'}]},{type,{1792,24},term,[]}]},[{type,{1793,7},constraint,[{atom,{1793,7},is_subtype},[{var,{1793,7},'Key'},{type,{1793,14},term,[]}]]},{type,{1794,7},constraint,[{atom,{1794,7},is_subtype},[{var,{1794,7},'Val'},{type,{1794,14},term,[]}]]}]]}]}}]}},{{function,raise,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1799}],[<<114,97,105,115,101,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<114,97,105,115,101,95,115,116,97,99,107,116,114,97,99,101>>}],[]}]},{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,99,108,97,115,115,44,32,114,101,97,115,111,110,44,32,97,110,100,32,99,97,108,108,32,115,116,97,99,107,32,98,97,99,107,116,114,97,99,101,32,40>>,{em,[],[<<115,116,97,99,107,116,114,97,99,101>>]},<<41,46>>]},{p,[],[{code,[],[<<67,108,97,115,115>>]},<<32,105,115,32>>,{code,[],[<<101,114,114,111,114>>]},<<44,32>>,{code,[],[<<101,120,105,116>>]},<<44,32,111,114,32>>,{code,[],[<<116,104,114,111,119>>]},<<46,32,83,111,44,32,105,102,32,105,116,32,119,101,114,101,32,110,111,116,32,102,111,114,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,44,32>>,{code,[],[<<101,114,108,97,110,103,58,114,97,105,115,101,40,67,108,97,115,115,44,32,82,101,97,115,111,110,44,32,83,116,97,99,107,116,114,97,99,101,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,67,108,97,115,115,40,82,101,97,115,111,110,41>>]},<<32,40,103,105,118,101,110,32,116,104,97,116,32>>,{code,[],[<<67,108,97,115,115>>]},<<32,105,115,32,97,32,118,97,108,105,100,32,99,108,97,115,115,41,46>>]},{p,[],[{code,[],[<<82,101,97,115,111,110>>]},<<32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,46>>]},{p,[],[{code,[],[<<83,116,97,99,107,116,114,97,99,101>>]},<<32,105,115,32,97,32,108,105,115,116,32,97,115,32,112,114,111,118,105,100,101,100,32,105,110,32,97,32,116,114,121,45,99,97,116,99,104,32,99,108,97,117,115,101,46>>]},{pre,[],[{code,[],[<<116,114,121,10,32,32,32,32,46,46,46,10,99,97,116,99,104,32,67,108,97,115,115,58,82,101,97,115,111,110,58,83,116,97,99,107,116,114,97,99,101,32,45,62,10,32,32,32,32,46,46,46,10,101,110,100>>]}]},{p,[],[<<84,104,97,116,32,105,115,44,32,97,32,108,105,115,116,32,111,102,32,102,111,117,114,45,116,117,112,108,101,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,32,124,32,65,114,103,115,44,32,69,120,116,114,97,73,110,102,111,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<32,97,110,100,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,97,114,101,32,97,116,111,109,115,44,32,97,110,100,32,116,104,101,32,116,104,105,114,100,32,101,108,101,109,101,110,116,32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,97,114,105,116,121,32,111,114,32,97,110,32,97,114,103,117,109,101,110,116,32,108,105,115,116,46,32,84,104,101,32,115,116,97,99,107,116,114,97,99,101,32,99,97,110,32,97,108,115,111,32,99,111,110,116,97,105,110,32>>,{code,[],[<<123,70,117,110,44,32,65,114,103,115,44,32,69,120,116,114,97,73,110,102,111,125>>]},<<32,116,117,112,108,101,115,44,32,119,104,101,114,101,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,102,117,110,32,97,110,100,32>>,{code,[],[<<65,114,103,115>>]},<<32,105,115,32,97,110,32,97,114,103,117,109,101,110,116,32,108,105,115,116,46>>]},{p,[],[<<69,108,101,109,101,110,116,32>>,{code,[],[<<69,120,116,114,97,73,110,102,111>>]},<<32,97,116,32,116,104,101,32,101,110,100,32,105,115,32,111,112,116,105,111,110,97,108,46,32,79,109,105,116,116,105,110,103,32,105,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,112,101,99,105,102,121,105,110,103,32,97,110,32,101,109,112,116,121,32,108,105,115,116,46>>]},{p,[],[<<84,104,101,32,115,116,97,99,107,116,114,97,99,101,32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,115,116,97,99,107,116,114,97,99,101,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,59,32,105,116,32,105,115,32,116,114,117,110,99,97,116,101,100,32,116,111,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,120,105,109,117,109,32,115,116,97,99,107,116,114,97,99,101,32,100,101,112,116,104,46>>]},{p,[],[<<65,115,32,101,118,97,108,117,97,116,105,110,103,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,117,115,101,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,111,32,116,101,114,109,105,110,97,116,101,44,32,105,116,32,104,97,115,32,110,111,32,114,101,116,117,114,110,32,118,97,108,117,101,32,117,110,108,101,115,115,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,105,110,118,97,108,105,100,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{em,[],[<<114,101,116,117,114,110,115,32,116,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110>>]},<<32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46,32,73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,98,101,32,115,117,114,101,32,110,111,116,32,116,111,32,114,101,116,117,114,110,44,32,121,111,117,32,99,97,110,32,99,97,108,108,32>>,{code,[],[<<101,114,114,111,114,40,101,114,108,97,110,103,58,114,97,105,115,101,40,67,108,97,115,115,44,32,82,101,97,115,111,110,44,32,83,116,97,99,107,116,114,97,99,101,41,41>>]},<<32,97,110,100,32,104,111,112,101,32,116,111,32,100,105,115,116,105,110,103,117,105,115,104,32,101,120,99,101,112,116,105,111,110,115,32,108,97,116,101,114,46>>]},{p,[],[<<83,101,101,32,116,104,101,32,114,101,102,101,114,101,110,99,101,32,109,97,110,117,97,108,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,101,120,99,101,112,116,105,111,110,32,99,108,97,115,115,101,115,32,97,110,100,32,104,111,119,32,116,111,32,99,97,116,99,104,32,101,120,99,101,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,52,48>>,signature => [{attribute,{1799,2},spec,{{erlang,raise,3},[{type,{1799,19},bounded_fun,[{type,{1799,19},'fun',[{type,{1799,19},product,[{var,{1799,20},'Class'},{var,{1799,27},'Reason'},{var,{1799,35},'Stacktrace'}]},{atom,{1799,50},badarg}]},[{type,{1800,7},constraint,[{atom,{1800,7},is_subtype},[{var,{1800,7},'Class'},{type,{1800,16},union,[{atom,{1800,16},error},{atom,{1800,26},exit},{atom,{1800,35},throw}]}]]},{type,{1801,7},constraint,[{atom,{1801,7},is_subtype},[{var,{1801,7},'Reason'},{type,{1801,17},term,[]}]]},{type,{1802,7},constraint,[{atom,{1802,7},is_subtype},[{var,{1802,7},'Stacktrace'},{type,{1802,21},union,[{user_type,{1802,21},raise_stacktrace,[]},{user_type,{1802,42},stacktrace,[]}]}]]}]]}]}}]}},{{function,read_timer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1807}],[<<114,101,97,100,95,116,105,109,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,97,100,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114,40,84,105,109,101,114,82,101,102,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,56,57,48>>,signature => [{attribute,{1807,2},spec,{{erlang,read_timer,1},[{type,{1807,24},bounded_fun,[{type,{1807,24},'fun',[{type,{1807,24},product,[{var,{1807,25},'TimerRef'}]},{var,{1807,38},'Result'}]},[{type,{1808,7},constraint,[{atom,{1808,7},is_subtype},[{var,{1808,7},'TimerRef'},{type,{1808,19},reference,[]}]]},{type,{1809,7},constraint,[{atom,{1809,7},is_subtype},[{var,{1809,7},'Time'},{type,{1809,15},non_neg_integer,[]}]]},{type,{1810,7},constraint,[{atom,{1810,7},is_subtype},[{var,{1810,7},'Result'},{type,{1810,17},union,[{var,{1810,17},'Time'},{atom,{1810,24},false}]}]]}]]}]}}]}},{{function,read_timer,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1816}],[<<114,101,97,100,95,116,105,109,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,97,32,116,105,109,101,114,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,32,98,121,32,101,105,116,104,101,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114>>]}]},<<46,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,105,100,101,110,116,105,102,105,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,119,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32,116,104,101,32,66,73,70,32,116,104,97,116,32,99,114,101,97,116,101,100,32,116,104,101,32,116,105,109,101,114,46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110,115>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,115,121,110,99,44,32,65,115,121,110,99,125>>]}]},{dd,[],[{p,[],[<<65,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,115,116,97,116,101,32,105,110,102,111,114,109,97,116,105,111,110,46,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,119,104,105,99,104,32,99,97,117,115,101,115,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,116,111,32,98,101,32,112,101,114,102,111,114,109,101,100,32,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114>>]},<<46,32,87,104,101,110,32>>,{code,[],[<<65,115,121,110,99>>]},<<32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<44,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114>>]},<<32,115,101,110,100,115,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,114,101,113,117,101,115,116,32,102,111,114,32,116,104,101,32,115,116,97,116,101,32,105,110,102,111,114,109,97,116,105,111,110,32,116,111,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,44,32,97,110,100,32,116,104,101,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<46,32,65,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,114,101,97,100,95,116,105,109,101,114,44,32,84,105,109,101,114,82,101,102,44,32,82,101,115,117,108,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114>>]},<<32,119,104,101,110,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,46>>]}]}]},{p,[],[<<77,111,114,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,44,32,105,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,32,108,101,102,116,32,117,110,116,105,108,32,116,104,101,32,116,105,109,101,114,32,101,120,112,105,114,101,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<82,101,115,117,108,116>>]},<<32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<44,32,97,32,116,105,109,101,114,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,99,111,117,108,100,32,110,111,116,32,98,101,32,102,111,117,110,100,46,32,84,104,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,116,105,109,101,114,32,104,97,100,32,101,120,112,105,114,101,100,44,32,111,114,32,98,101,101,110,32,99,97,110,99,101,108,101,100,44,32,111,114,32,98,101,99,97,117,115,101,32>>,{code,[],[<<84,105,109,101,114,82,101,102>>]},<<32,110,101,118,101,114,32,104,97,115,32,99,111,114,114,101,115,112,111,110,100,101,100,32,116,111,32,97,32,116,105,109,101,114,46,32,69,118,101,110,32,105,102,32,116,104,101,32,116,105,109,101,114,32,104,97,115,32,101,120,112,105,114,101,100,44,32,105,116,32,100,111,101,115,32,110,111,116,32,116,101,108,108,32,121,111,117,32,119,104,101,116,104,101,114,32,111,114,32,110,111,116,32,116,104,101,32,116,105,109,101,45,111,117,116,32,109,101,115,115,97,103,101,32,104,97,115,32,97,114,114,105,118,101,100,32,97,116,32,105,116,115,32,100,101,115,116,105,110,97,116,105,111,110,32,121,101,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,104,97,116,32,109,97,110,97,103,101,115,32,116,104,101,32,116,105,109,101,114,32,99,97,110,32,98,101,32,99,111,45,108,111,99,97,116,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32,115,99,104,101,100,117,108,101,114,32,116,104,97,110,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32,73,102,32,115,111,44,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,116,105,109,101,114,32,115,101,114,118,105,99,101,32,116,97,107,101,115,32,109,117,99,104,32,108,111,110,103,101,114,32,116,105,109,101,32,116,104,97,110,32,105,102,32,105,116,32,105,115,32,108,111,99,97,116,101,100,32,108,111,99,97,108,108,121,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,105,110,32,97,32,99,114,105,116,105,99,97,108,32,112,97,116,104,44,32,97,110,100,32,99,97,110,32,100,111,32,111,116,104,101,114,32,116,104,105,110,103,115,32,119,104,105,108,101,32,119,97,105,116,105,110,103,32,102,111,114,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,44,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,116,114,117,101,125>>]},<<46,32,73,102,32,117,115,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,97,115,121,110,99,44,32,102,97,108,115,101,125>>]},<<44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,98,108,111,99,107,101,100,32,117,110,116,105,108,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,112,101,114,102,111,114,109,101,100,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,47,52>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,47,52>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,48,48>>,signature => [{attribute,{1816,2},spec,{{erlang,read_timer,2},[{type,{1816,24},bounded_fun,[{type,{1816,24},'fun',[{type,{1816,24},product,[{var,{1816,25},'TimerRef'},{var,{1816,35},'Options'}]},{type,{1816,47},union,[{var,{1816,47},'Result'},{atom,{1816,56},ok}]}]},[{type,{1817,7},constraint,[{atom,{1817,7},is_subtype},[{var,{1817,7},'TimerRef'},{type,{1817,19},reference,[]}]]},{type,{1818,7},constraint,[{atom,{1818,7},is_subtype},[{var,{1818,7},'Async'},{type,{1818,16},boolean,[]}]]},{type,{1819,7},constraint,[{atom,{1819,7},is_subtype},[{var,{1819,7},'Option'},{type,{1819,17},tuple,[{atom,{1819,18},async},{var,{1819,25},'Async'}]}]]},{type,{1820,7},constraint,[{atom,{1820,7},is_subtype},[{var,{1820,7},'Options'},{type,{1820,18},list,[{var,{1820,19},'Option'}]}]]},{type,{1821,7},constraint,[{atom,{1821,7},is_subtype},[{var,{1821,7},'Time'},{type,{1821,15},non_neg_integer,[]}]]},{type,{1822,7},constraint,[{atom,{1822,7},is_subtype},[{var,{1822,7},'Result'},{type,{1822,17},union,[{var,{1822,17},'Time'},{atom,{1822,24},false}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,ref_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1828}],[<<114,101,102,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,116,101,120,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32>>,{code,[],[<<82,101,102>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,97,110,100,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,97,112,112,108,105,99,97,116,105,111,110,32,112,114,111,103,114,97,109,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,53,54>>,signature => [{attribute,{1828,2},spec,{{ref_to_list,1},[{type,{1828,18},bounded_fun,[{type,{1828,18},'fun',[{type,{1828,18},product,[{var,{1828,19},'Ref'}]},{type,{1828,27},string,[]}]},[{type,{1829,7},constraint,[{atom,{1829,7},is_subtype},[{var,{1829,7},'Ref'},{type,{1829,14},reference,[]}]]}]]}]}}]}},{{function,register,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1834}],[<<114,101,103,105,115,116,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,103,105,115,116,101,114,115,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,119,105,116,104,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,114,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,105,110,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,114,117,110,116,105,109,101,45,115,101,114,118,105,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<110,97,109,101,32,114,101,103,105,115,116,114,121>>]}]},<<46,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<44,32,119,104,105,99,104,32,109,117,115,116,32,98,101,32,97,110,32,97,116,111,109,44,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,112,105,100,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,105,110,32,115,101,110,100,32,111,112,101,114,97,116,111,114,32,40>>,{code,[],[<<82,101,103,78,97,109,101,32,33,32,77,101,115,115,97,103,101>>]},<<41,32,97,110,100,32,109,111,115,116,32,111,116,104,101,114,32,66,73,70,115,32,116,104,97,116,32,116,97,107,101,32,97,32,112,105,100,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,115,32,97,115,32,97,110,32,97,114,103,117,109,101,110,116,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,114,101,103,105,115,116,101,114,40,100,98,44,32,80,105,100,41,46,10,116,114,117,101>>]}]},{p,[],[<<84,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,118,105,115,105,98,108,101,45,114,101,115,111,117,114,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<68,105,114,101,99,116,108,121,32,86,105,115,105,98,108,101,32,69,114,108,97,110,103,32,82,101,115,111,117,114,99,101>>]},<<32,97,110,100,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,117,110,114,101,103,105,115,116,101,114,101,100,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,120,105,115,116,105,110,103,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,105,115,32,97,108,114,101,97,100,121,32,105,110,32,117,115,101,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,115,32,97,108,114,101,97,100,121,32,114,101,103,105,115,116,101,114,101,100,32,40,97,108,114,101,97,100,121,32,104,97,115,32,97,32,110,97,109,101,41,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,54,57,54,57>>,signature => [{attribute,{1834,2},spec,{{register,2},[{type,{1834,15},bounded_fun,[{type,{1834,15},'fun',[{type,{1834,15},product,[{var,{1834,16},'RegName'},{var,{1834,25},'PidOrPort'}]},{atom,{1834,39},true}]},[{type,{1835,7},constraint,[{atom,{1835,7},is_subtype},[{var,{1835,7},'RegName'},{type,{1835,18},atom,[]}]]},{type,{1836,7},constraint,[{atom,{1836,7},is_subtype},[{var,{1836,7},'PidOrPort'},{type,{1836,20},union,[{type,{1836,20},port,[]},{type,{1836,29},pid,[]}]}]]}]]}]}}]}},{{function,registered,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1841}],[<<114,101,103,105,115,116,101,114,101,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,110,97,109,101,115,32,116,104,97,116,32,104,97,118,101,32,98,101,101,110,32,114,101,103,105,115,116,101,114,101,100,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,103,105,115,116,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,103,105,115,116,101,114,47,50>>]}]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,114,101,103,105,115,116,101,114,101,100,40,41,46,10,91,99,111,100,101,95,115,101,114,118,101,114,44,32,102,105,108,101,95,115,101,114,118,101,114,44,32,105,110,105,116,44,32,117,115,101,114,44,32,109,121,95,100,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,48,48,53>>,signature => [{attribute,{1841,2},spec,{{registered,0},[{type,{1841,17},bounded_fun,[{type,{1841,17},'fun',[{type,{1841,17},product,[]},{type,{1841,23},list,[{var,{1841,24},'RegName'}]}]},[{type,{1842,7},constraint,[{atom,{1842,7},is_subtype},[{var,{1842,7},'RegName'},{type,{1842,18},atom,[]}]]}]]}]}}]}},{{function,resume_process,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1847}],[<<114,101,115,117,109,101,95,112,114,111,99,101,115,115,47,49>>],#{<<101,110>> => [{p,[],[<<68,101,99,114,101,97,115,101,115,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,112,114,101,118,105,111,117,115,108,121,32,116,111,32,104,97,118,101,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,116,104,114,111,117,103,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>]}]},<<32,98,121,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,115,117,109,101,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]},<<46,32,87,104,101,110,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,114,101,97,99,104,101,115,32,122,101,114,111,44,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,114,101,115,117,109,101,100,44,32,116,104,97,116,32,105,115,44,32,105,116,115,32,115,116,97,116,101,32,105,115,32,99,104,97,110,103,101,100,32,102,114,111,109,32,115,117,115,112,101,110,100,101,100,32,105,110,116,111,32,116,104,101,32,115,116,97,116,101,32,105,116,32,104,97,100,32,98,101,102,111,114,101,32,105,116,32,119,97,115,32,115,117,115,112,101,110,100,101,100,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,114,101,115,117,109,101,95,112,114,111,99,101,115,115,47,49>>]},<<32,104,97,100,32,110,111,116,32,112,114,101,118,105,111,117,115,108,121,32,105,110,99,114,101,97,115,101,100,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,48,49,56>>,signature => [{attribute,{1847,2},spec,{{erlang,resume_process,1},[{type,{1847,28},bounded_fun,[{type,{1847,28},'fun',[{type,{1847,28},product,[{var,{1847,29},'Suspendee'}]},{atom,{1847,43},true}]},[{type,{1848,7},constraint,[{atom,{1848,7},is_subtype},[{var,{1848,7},'Suspendee'},{type,{1848,20},pid,[]}]]}]]}]}}]}},{{function,round,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1854}],[<<114,111,117,110,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,98,121,32,114,111,117,110,100,105,110,103,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,111,117,110,100,40,52,50,46,49,41,46,10,52,50>>]}]},{pre,[],[{code,[],[<<114,111,117,110,100,40,53,46,53,41,46,10,54>>]}]},{pre,[],[{code,[],[<<114,111,117,110,100,40,45,53,46,53,41,46,10,45,54>>]}]},{pre,[],[{code,[],[<<114,111,117,110,100,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41,46,10,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]}]},{p,[],[<<73,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<114,111,117,110,100,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41>>]},<<32,101,118,97,108,117,97,116,101,115,32,116,111,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]},<<46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,116,104,97,116,32,116,104,101,32,110,117,109,98,101,114,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48>>]},<<32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,73,110,115,116,101,97,100,44,32,116,104,101,32,102,108,111,97,116,32,108,105,116,101,114,97,108,32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56,46,48>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,99,108,111,115,101,115,116,32,110,117,109,98,101,114,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,108,111,97,116,95,114,101,112,114,101,115,101,110,116,97,116,105,111,110,95,112,114,111,98,108,101,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,70,108,111,97,116,105,110,103,32,80,111,105,110,116,32,78,117,109,98,101,114,115>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,48,53,57>>,signature => [{attribute,{1854,2},spec,{{round,1},[{type,{1854,12},bounded_fun,[{type,{1854,12},'fun',[{type,{1854,12},product,[{var,{1854,13},'Number'}]},{type,{1854,24},integer,[]}]},[{type,{1855,7},constraint,[{atom,{1855,7},is_subtype},[{var,{1855,7},'Number'},{type,{1855,17},number,[]}]]}]]}]}}]}},{{function,self,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1861}],[<<115,101,108,102,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,101,108,102,40,41,46,10,60,48,46,50,54,46,48,62>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,48,57,48>>,signature => [{attribute,{1861,2},spec,{{self,0},[{type,{1861,11},'fun',[{type,{1861,11},product,[]},{type,{1861,17},pid,[]}]}]}}]}},{{function,send,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2559}],[<<115,101,110,100,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<83,101,110,100,115,32,97,32,109,101,115,115,97,103,101,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<77,115,103>>]},<<46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,117,115,105,110,103,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,115,101,110,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,101,110,100,32,111,112,101,114,97,116,111,114>>]},<<58,32>>,{code,[],[<<68,101,115,116,32,33,32,77,115,103>>]},<<46>>]},{p,[],[{code,[],[<<68,101,115,116>>]},<<32,99,97,110,32,98,101,32,97,32,114,101,109,111,116,101,32,111,114,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,97,110,32,97,108,105,97,115,44,32,97,32,40,108,111,99,97,108,41,32,112,111,114,116,44,32,97,32,108,111,99,97,108,108,121,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,44,32,111,114,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,82,101,103,78,97,109,101,44,32,78,111,100,101,125>>]},<<32,102,111,114,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,97,116,32,97,110,111,116,104,101,114,32,110,111,100,101,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,102,97,105,108,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,114,117,110,45,116,105,109,101,32,101,114,114,111,114,32,105,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,110,32,97,116,111,109,32,110,97,109,101,44,32,98,117,116,32,116,104,105,115,32,110,97,109,101,32,105,115,32,110,111,116,32,114,101,103,105,115,116,101,114,101,100,46,32,84,104,105,115,32,105,115,32,116,104,101,32,111,110,108,121,32,99,97,115,101,32,119,104,101,110,32>>,{code,[],[<<115,101,110,100>>]},<<32,102,97,105,108,115,32,102,111,114,32,97,110,32,117,110,114,101,97,99,104,97,98,108,101,32,100,101,115,116,105,110,97,116,105,111,110,32>>,{code,[],[<<68,101,115,116>>]},<<32,40,111,102,32,99,111,114,114,101,99,116,32,116,121,112,101,41,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,48,51>>,signature => [{attribute,{2559,2},spec,{{erlang,send,2},[{type,{2559,18},bounded_fun,[{type,{2559,18},'fun',[{type,{2559,18},product,[{var,{2559,19},'Dest'},{var,{2559,25},'Msg'}]},{var,{2559,33},'Msg'}]},[{type,{2560,7},constraint,[{atom,{2560,7},is_subtype},[{var,{2560,7},'Dest'},{user_type,{2560,15},dst,[]}]]},{type,{2561,7},constraint,[{atom,{2561,7},is_subtype},[{var,{2561,7},'Msg'},{type,{2561,14},term,[]}]]}]]}]}}]}},{{function,send,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2565}],[<<115,101,110,100,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<69,105,116,104,101,114,32,115,101,110,100,115,32,97,32,109,101,115,115,97,103,101,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<44,32,111,114,32,100,111,101,115,32,110,111,116,32,115,101,110,100,32,116,104,101,32,109,101,115,115,97,103,101,32,98,117,116,32,114,101,116,117,114,110,115,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,40,115,101,101,32,98,101,108,111,119,41,46,32,79,116,104,101,114,119,105,115,101,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,47,50>>]}]},<<46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,101,100,32,101,120,112,108,97,110,97,116,105,111,110,32,97,110,100,32,119,97,114,110,105,110,103,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50,44,51>>]}]},<<46>>]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<110,111,115,117,115,112,101,110,100>>]}]},{dd,[],[<<73,102,32,116,104,101,32,115,101,110,100,101,114,32,119,111,117,108,100,32,104,97,118,101,32,116,111,32,98,101,32,115,117,115,112,101,110,100,101,100,32,116,111,32,100,111,32,116,104,101,32,115,101,110,100,44,32>>,{code,[],[<<110,111,115,117,115,112,101,110,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]},{dt,[],[{code,[],[<<110,111,99,111,110,110,101,99,116>>]}]},{dd,[],[<<73,102,32,116,104,101,32,100,101,115,116,105,110,97,116,105,111,110,32,110,111,100,101,32,119,111,117,108,100,32,104,97,118,101,32,116,111,32,98,101,32,97,117,116,111,45,99,111,110,110,101,99,116,101,100,32,116,111,32,100,111,32,116,104,101,32,115,101,110,100,44,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<65,115,32,119,105,116,104,32>>,{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50,44,51>>]},<<58,32,117,115,101,32,119,105,116,104,32,101,120,116,114,101,109,101,32,99,97,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,50,51>>,signature => [{attribute,{2565,2},spec,{{erlang,send,3},[{type,{2565,18},bounded_fun,[{type,{2565,18},'fun',[{type,{2565,18},product,[{var,{2565,19},'Dest'},{var,{2565,25},'Msg'},{var,{2565,30},'Options'}]},{var,{2565,42},'Res'}]},[{type,{2566,7},constraint,[{atom,{2566,7},is_subtype},[{var,{2566,7},'Dest'},{user_type,{2566,15},dst,[]}]]},{type,{2567,7},constraint,[{atom,{2567,7},is_subtype},[{var,{2567,7},'Msg'},{type,{2567,14},term,[]}]]},{type,{2568,7},constraint,[{atom,{2568,7},is_subtype},[{var,{2568,7},'Options'},{type,{2568,18},list,[{type,{2568,19},union,[{atom,{2568,19},nosuspend},{atom,{2568,31},noconnect}]}]}]]},{type,{2569,7},constraint,[{atom,{2569,7},is_subtype},[{var,{2569,7},'Res'},{type,{2569,14},union,[{atom,{2569,14},ok},{atom,{2569,19},nosuspend},{atom,{2569,31},noconnect}]}]]}]]}]}}]}},{{function,send_after,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1866}],[<<115,101,110,100,95,97,102,116,101,114,47,51>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,40,84,105,109,101,44,32,68,101,115,116,44,32,77,115,103,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,53,53>>,signature => [{attribute,{1866,2},spec,{{erlang,send_after,3},[{type,{1866,24},bounded_fun,[{type,{1866,24},'fun',[{type,{1866,24},product,[{var,{1866,25},'Time'},{var,{1866,31},'Dest'},{var,{1866,37},'Msg'}]},{var,{1866,45},'TimerRef'}]},[{type,{1867,7},constraint,[{atom,{1867,7},is_subtype},[{var,{1867,7},'Time'},{type,{1867,15},non_neg_integer,[]}]]},{type,{1868,7},constraint,[{atom,{1868,7},is_subtype},[{var,{1868,7},'Dest'},{type,{1868,15},union,[{type,{1868,15},pid,[]},{type,{1868,23},atom,[]}]}]]},{type,{1869,7},constraint,[{atom,{1869,7},is_subtype},[{var,{1869,7},'Msg'},{type,{1869,14},term,[]}]]},{type,{1870,7},constraint,[{atom,{1870,7},is_subtype},[{var,{1870,7},'TimerRef'},{type,{1870,19},reference,[]}]]}]]}]}}]}},{{function,send_after,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1876}],[<<115,101,110,100,95,97,102,116,101,114,47,52>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,87,104,101,110,32,116,104,101,32,116,105,109,101,114,32,101,120,112,105,114,101,115,44,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,101,115,116>>]},<<46,32,65,112,97,114,116,32,102,114,111,109,32,116,104,101,32,102,111,114,109,97,116,32,111,102,32,116,104,101,32,116,105,109,101,45,111,117,116,32,109,101,115,115,97,103,101,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,119,111,114,107,115,32,101,120,97,99,116,108,121,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,47,52>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,54,54>>,signature => [{attribute,{1876,2},spec,{{erlang,send_after,4},[{type,{1876,24},bounded_fun,[{type,{1876,24},'fun',[{type,{1876,24},product,[{var,{1876,25},'Time'},{var,{1876,31},'Dest'},{var,{1876,37},'Msg'},{var,{1876,42},'Options'}]},{var,{1876,54},'TimerRef'}]},[{type,{1877,7},constraint,[{atom,{1877,7},is_subtype},[{var,{1877,7},'Time'},{type,{1877,15},integer,[]}]]},{type,{1878,7},constraint,[{atom,{1878,7},is_subtype},[{var,{1878,7},'Dest'},{type,{1878,15},union,[{type,{1878,15},pid,[]},{type,{1878,23},atom,[]}]}]]},{type,{1879,7},constraint,[{atom,{1879,7},is_subtype},[{var,{1879,7},'Msg'},{type,{1879,14},term,[]}]]},{type,{1880,7},constraint,[{atom,{1880,7},is_subtype},[{var,{1880,7},'Options'},{type,{1880,18},list,[{var,{1880,19},'Option'}]}]]},{type,{1881,7},constraint,[{atom,{1881,7},is_subtype},[{var,{1881,7},'Abs'},{type,{1881,14},boolean,[]}]]},{type,{1882,7},constraint,[{atom,{1882,7},is_subtype},[{var,{1882,7},'Option'},{type,{1882,17},tuple,[{atom,{1882,18},abs},{var,{1882,23},'Abs'}]}]]},{type,{1883,7},constraint,[{atom,{1883,7},is_subtype},[{var,{1883,7},'TimerRef'},{type,{1883,19},reference,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,send_nosuspend,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3478}],[<<115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,40,68,101,115,116,44,32,77,115,103,44,32,91,110,111,115,117,115,112,101,110,100,93,41>>]}]},<<44,32,98,117,116,32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,109,101,115,115,97,103,101,32,119,97,115,32,115,101,110,116,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,109,101,115,115,97,103,101,32,119,97,115,32,110,111,116,32,115,101,110,116,32,98,101,99,97,117,115,101,32,116,104,101,32,115,101,110,100,101,114,32,119,111,117,108,100,32,104,97,118,101,32,104,97,100,32,116,111,32,98,101,32,115,117,115,112,101,110,100,101,100,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,115,101,110,100,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,97,110,32,117,110,114,101,108,105,97,98,108,101,32,114,101,109,111,116,101,32,110,111,100,101,32,119,105,116,104,111,117,116,32,101,118,101,114,32,98,108,111,99,107,105,110,103,32,116,104,101,32,115,101,110,100,105,110,103,32,40,69,114,108,97,110,103,41,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,32,40,117,115,117,97,108,108,121,32,110,111,116,32,97,32,114,101,97,108,32,69,114,108,97,110,103,32,110,111,100,101,44,32,98,117,116,32,97,32,110,111,100,101,32,119,114,105,116,116,101,110,32,105,110,32,67,32,111,114,32,74,97,118,97,41,32,105,115,32,111,118,101,114,108,111,97,100,101,100,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32>>,{em,[],[<<100,111,101,115,32,110,111,116,32,115,101,110,100,32,116,104,101,32,109,101,115,115,97,103,101>>]},<<32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<84,104,101,32,115,97,109,101,32,111,99,99,117,114,115,32,105,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,108,111,99,97,108,32,112,111,114,116,32,116,104,97,116,32,105,115,32,98,117,115,121,46,32,70,111,114,32,97,108,108,32,111,116,104,101,114,32,100,101,115,116,105,110,97,116,105,111,110,115,32,40,97,108,108,111,119,101,100,32,102,111,114,32,116,104,101,32,111,114,100,105,110,97,114,121,32,115,101,110,100,32,111,112,101,114,97,116,111,114,32>>,{code,[],[<<39,33,39>>]},<<41,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,115,101,110,100,115,32,116,104,101,32,109,101,115,115,97,103,101,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,114,97,114,101,32,99,105,114,99,117,109,115,116,97,110,99,101,115,32,119,104,101,114,101,32,97,32,112,114,111,99,101,115,115,32,99,111,109,109,117,110,105,99,97,116,101,115,32,119,105,116,104,32,69,114,108,97,110,103,32,110,111,100,101,115,32,116,104,97,116,32,99,97,110,32,100,105,115,97,112,112,101,97,114,32,119,105,116,104,111,117,116,32,97,110,121,32,116,114,97,99,101,44,32,99,97,117,115,105,110,103,32,116,104,101,32,84,67,80,32,98,117,102,102,101,114,115,32,97,110,100,32,116,104,101,32,100,114,105,118,101,114,115,32,113,117,101,117,101,32,116,111,32,98,101,32,111,118,101,114,45,102,117,108,108,32,98,101,102,111,114,101,32,116,104,101,32,110,111,100,101,32,105,115,32,115,104,117,116,32,100,111,119,110,32,40,98,101,99,97,117,115,101,32,111,102,32,116,105,99,107,32,116,105,109,101,45,111,117,116,115,41,32,98,121,32>>,{code,[],[<<110,101,116,95,107,101,114,110,101,108>>]},<<46,32,84,104,101,32,110,111,114,109,97,108,32,114,101,97,99,116,105,111,110,32,116,111,32,116,97,107,101,32,119,104,101,110,32,116,104,105,115,32,111,99,99,117,114,115,32,105,115,32,115,111,109,101,32,107,105,110,100,32,111,102,32,112,114,101,109,97,116,117,114,101,32,115,104,117,116,100,111,119,110,32,111,102,32,116,104,101,32,111,116,104,101,114,32,110,111,100,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,105,103,110,111,114,105,110,103,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,102,114,111,109,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,119,111,117,108,100,32,114,101,115,117,108,116,32,105,110,32,97,110,32>>,{em,[],[<<117,110,114,101,108,105,97,98,108,101>>]},<<32,109,101,115,115,97,103,101,32,112,97,115,115,105,110,103,44,32,119,104,105,99,104,32,105,115,32,99,111,110,116,114,97,100,105,99,116,111,114,121,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,105,110,103,32,109,111,100,101,108,46,32,84,104,101,32,109,101,115,115,97,103,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,115,101,110,116,32,105,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{p,[],[<<73,110,32,109,97,110,121,32,115,121,115,116,101,109,115,44,32,116,114,97,110,115,105,101,110,116,32,115,116,97,116,101,115,32,111,102,32,111,118,101,114,108,111,97,100,101,100,32,113,117,101,117,101,115,32,97,114,101,32,110,111,114,109,97,108,46,32,65,108,116,104,111,117,103,104,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,100,111,101,115,32,110,111,116,32,109,101,97,110,32,116,104,97,116,32,116,104,101,32,111,116,104,101,114,32,110,111,100,101,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,110,111,110,45,114,101,115,112,111,110,115,105,118,101,44,32,105,116,32,99,111,117,108,100,32,98,101,32,97,32,116,101,109,112,111,114,97,114,121,32,111,118,101,114,108,111,97,100,46,32,65,108,115,111,44,32,97,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32>>,{code,[],[<<116,114,117,101>>]},<<32,100,111,101,115,32,111,110,108,121,32,109,101,97,110,32,116,104,97,116,32,116,104,101,32,109,101,115,115,97,103,101,32,99,97,110,32,98,101,32,115,101,110,116,32,111,110,32,116,104,101,32,40,84,67,80,41,32,99,104,97,110,110,101,108,32,119,105,116,104,111,117,116,32,98,108,111,99,107,105,110,103,59,32,116,104,101,32,109,101,115,115,97,103,101,32,105,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,97,114,114,105,118,101,32,97,116,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,46,32,70,111,114,32,97,32,100,105,115,99,111,110,110,101,99,116,101,100,32,110,111,110,45,114,101,115,112,111,110,115,105,118,101,32,110,111,100,101,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,40,109,105,109,105,99,115,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,111,112,101,114,97,116,111,114,32>>,{code,[],[<<33>>]},<<41,46,32,84,104,101,32,101,120,112,101,99,116,101,100,32,98,101,104,97,118,105,111,114,32,97,110,100,32,116,104,101,32,97,99,116,105,111,110,115,32,116,111,32,116,97,107,101,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,97,114,101,32,97,112,112,108,105,99,97,116,105,111,110,45,32,97,110,100,32,104,97,114,100,119,97,114,101,45,115,112,101,99,105,102,105,99,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<85,115,101,32,119,105,116,104,32,101,120,116,114,101,109,101,32,99,97,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,49,55,57>>,signature => [{attribute,{3478,2},spec,{{erlang,send_nosuspend,2},[{type,{3478,28},bounded_fun,[{type,{3478,28},'fun',[{type,{3478,28},product,[{var,{3478,29},'Dest'},{var,{3478,35},'Msg'}]},{type,{3478,43},boolean,[]}]},[{type,{3479,7},constraint,[{atom,{3479,7},is_subtype},[{var,{3479,7},'Dest'},{user_type,{3479,15},dst,[]}]]},{type,{3480,7},constraint,[{atom,{3480,7},is_subtype},[{var,{3480,7},'Msg'},{type,{3480,14},term,[]}]]}]]}]}}]}},{{function,send_nosuspend,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3488}],[<<115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,115,116>>}],[]}]},{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,40,68,101,115,116,44,32,77,115,103,44,32,91,110,111,115,117,115,112,101,110,100,32,124,32,79,112,116,105,111,110,115,93,41>>]}]},<<44,32,98,117,116,32,119,105,116,104,32,97,32,66,111,111,108,101,97,110,32,114,101,116,117,114,110,32,118,97,108,117,101,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,98,101,104,97,118,101,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,110,111,115,117,115,112,101,110,100,47,50>>]}]},<<44,32,98,117,116,32,116,97,107,101,115,32,97,32,116,104,105,114,100,32,112,97,114,97,109,101,116,101,114,44,32,97,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46,32,84,104,101,32,111,110,108,121,32,111,112,116,105,111,110,32,105,115,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<44,32,119,104,105,99,104,32,109,97,107,101,115,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,114,101,109,111,116,101,32,110,111,100,101,32,105,115,32,110,111,116,32,99,117,114,114,101,110,116,108,121,32,114,101,97,99,104,97,98,108,101,32,98,121,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,110,111,114,109,97,108,32,98,101,104,97,118,105,111,114,32,105,115,32,116,111,32,116,114,121,32,116,111,32,99,111,110,110,101,99,116,32,116,111,32,116,104,101,32,110,111,100,101,44,32,119,104,105,99,104,32,99,97,110,32,115,116,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,32,100,117,114,105,110,103,32,97,32,115,104,111,114,116,32,112,101,114,105,111,100,46,32,84,104,101,32,117,115,101,32,111,102,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,98,101,32,115,117,114,101,32,110,111,116,32,116,111,32,103,101,116,32,116,104,101,32,115,108,105,103,104,116,101,115,116,32,100,101,108,97,121,32,119,104,101,110,32,115,101,110,100,105,110,103,32,116,111,32,97,32,114,101,109,111,116,101,32,112,114,111,99,101,115,115,46,32,84,104,105,115,32,105,115,32,101,115,112,101,99,105,97,108,108,121,32,117,115,101,102,117,108,32,119,104,101,110,32,99,111,109,109,117,110,105,99,97,116,105,110,103,32,119,105,116,104,32,110,111,100,101,115,32,116,104,97,116,32,101,120,112,101,99,116,32,116,111,32,97,108,119,97,121,115,32,98,101,32,116,104,101,32,99,111,110,110,101,99,116,105,110,103,32,112,97,114,116,32,40,116,104,97,116,32,105,115,44,32,110,111,100,101,115,32,119,114,105,116,116,101,110,32,105,110,32,67,32,111,114,32,74,97,118,97,41,46>>]},{p,[],[<<87,104,101,110,101,118,101,114,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,40,101,105,116,104,101,114,32,119,104,101,110,32,97,32,115,117,115,112,101,110,100,32,119,111,117,108,100,32,111,99,99,117,114,32,111,114,32,119,104,101,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116>>]},<<32,119,97,115,32,115,112,101,99,105,102,105,101,100,32,97,110,100,32,116,104,101,32,110,111,100,101,32,119,97,115,32,110,111,116,32,97,108,114,101,97,100,121,32,99,111,110,110,101,99,116,101,100,41,44,32,116,104,101,32,109,101,115,115,97,103,101,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32>>,{em,[],[<<110,111,116>>]},<<32,116,111,32,104,97,118,101,32,98,101,101,110,32,115,101,110,116,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<85,115,101,32,119,105,116,104,32,101,120,116,114,101,109,101,32,99,97,114,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,50,57>>,signature => [{attribute,{3488,2},spec,{{erlang,send_nosuspend,3},[{type,{3488,28},bounded_fun,[{type,{3488,28},'fun',[{type,{3488,28},product,[{var,{3488,29},'Dest'},{var,{3488,35},'Msg'},{var,{3488,40},'Options'}]},{type,{3488,52},boolean,[]}]},[{type,{3489,7},constraint,[{atom,{3489,7},is_subtype},[{var,{3489,7},'Dest'},{user_type,{3489,15},dst,[]}]]},{type,{3490,7},constraint,[{atom,{3490,7},is_subtype},[{var,{3490,7},'Msg'},{type,{3490,14},term,[]}]]},{type,{3491,7},constraint,[{atom,{3491,7},is_subtype},[{var,{3491,7},'Options'},{type,{3491,18},list,[{atom,{3491,19},noconnect}]}]]}]]}]}}]}},{{function,set_cookie,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3797}],[<<115,101,116,95,99,111,111,107,105,101,47,49>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,103,105,99,32,99,111,111,107,105,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,116,111,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<67,111,111,107,105,101>>]},<<44,32,119,104,105,99,104,32,105,115,32,97,108,115,111,32,116,104,101,32,99,111,111,107,105,101,32,102,111,114,32,97,108,108,32,110,111,100,101,115,32,116,104,97,116,32,104,97,118,101,32,110,111,32,101,120,112,108,105,99,105,116,32,99,111,111,107,105,101,32,115,101,116,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,116,95,99,111,111,107,105,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,101,116,95,99,111,111,107,105,101,47,50>>]}]},<<32>>,{code,[],[<<67,111,111,107,105,101>>]},<<32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,105,115,116,114,105,98,117,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<68,105,115,116,114,105,98,117,116,101,100,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,32,105,110,32,83,121,115,116,101,109,32,68,111,99,117,109,101,110,116,97,116,105,111,110,41,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<102,117,110,99,116,105,111,110,95,99,108,97,117,115,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,54,50>>,signature => [{attribute,{3797,2},spec,{{erlang,set_cookie,1},[{type,{3797,24},bounded_fun,[{type,{3797,24},'fun',[{type,{3797,24},product,[{var,{3797,25},'Cookie'}]},{atom,{3797,36},true}]},[{type,{3798,7},constraint,[{atom,{3798,7},is_subtype},[{var,{3798,7},'Cookie'},{type,{3798,17},atom,[]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,49>>}},{{function,set_cookie,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3804}],[<<115,101,116,95,99,111,111,107,105,101,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,103,105,99,32,99,111,111,107,105,101,32,102,111,114,32>>,{code,[],[<<78,111,100,101>>]},<<32,116,111,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<67,111,111,107,105,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,115,101,116,115,32,116,104,101,32,99,111,111,107,105,101,32,111,102,32,97,108,108,32,111,116,104,101,114,32,110,111,100,101,115,32,40,116,104,97,116,32,104,97,118,101,32,110,111,32,101,120,112,108,105,99,105,116,32,99,111,111,107,105,101,32,115,101,116,32,119,105,116,104,32,116,104,105,115,32,102,117,110,99,116,105,111,110,41,32,116,111,32>>,{code,[],[<<67,111,111,107,105,101>>]},<<32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,105,115,116,114,105,98,117,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<68,105,115,116,114,105,98,117,116,101,100,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,32,105,110,32,83,121,115,116,101,109,32,68,111,99,117,109,101,110,116,97,116,105,111,110,41,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<102,117,110,99,116,105,111,110,95,99,108,97,117,115,101>>]},<<32,105,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,55,57>>,signature => [{attribute,{3804,2},spec,{{erlang,set_cookie,2},[{type,{3804,24},bounded_fun,[{type,{3804,24},'fun',[{type,{3804,24},product,[{var,{3804,25},'Node'},{var,{3804,31},'Cookie'}]},{atom,{3804,42},true}]},[{type,{3805,7},constraint,[{atom,{3805,7},is_subtype},[{var,{3805,7},'Node'},{type,{3805,15},node,[]}]]},{type,{3806,7},constraint,[{atom,{3806,7},is_subtype},[{var,{3806,7},'Cookie'},{type,{3806,17},atom,[]}]]}]]}]}}]}},{{function,setelement,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2586}],[<<115,101,116,101,108,101,109,101,110,116,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,116,104,97,116,32,105,115,32,97,32,99,111,112,121,32,111,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<84,117,112,108,101,49>>]},<<32,119,105,116,104,32,116,104,101,32,101,108,101,109,101,110,116,32,115,112,101,99,105,102,105,101,100,32,98,121,32,105,110,116,101,103,101,114,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<73,110,100,101,120>>]},<<32,40,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,116,104,101,32,101,108,101,109,101,110,116,32,119,105,116,104,32,105,110,100,101,120,32,49,41,32,114,101,112,108,97,99,101,100,32,98,121,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<86,97,108,117,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,101,116,101,108,101,109,101,110,116,40,50,44,32,123,49,48,44,32,103,114,101,101,110,44,32,98,111,116,116,108,101,115,125,44,32,114,101,100,41,46,10,123,49,48,44,114,101,100,44,98,111,116,116,108,101,115,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,50,57,54>>,signature => [{attribute,{2586,2},spec,{{setelement,3},[{type,{2586,17},bounded_fun,[{type,{2586,17},'fun',[{type,{2586,17},product,[{var,{2586,18},'Index'},{var,{2586,25},'Tuple1'},{var,{2586,33},'Value'}]},{var,{2586,43},'Tuple2'}]},[{type,{2587,7},constraint,[{atom,{2587,7},is_subtype},[{var,{2587,7},'Index'},{type,{2587,16},pos_integer,[]}]]},{type,{2588,7},constraint,[{atom,{2588,7},is_subtype},[{var,{2588,7},'Tuple1'},{type,{2588,17},tuple,any}]]},{type,{2589,7},constraint,[{atom,{2589,7},is_subtype},[{var,{2589,7},'Tuple2'},{type,{2589,17},tuple,any}]]},{type,{2590,7},constraint,[{atom,{2590,7},is_subtype},[{var,{2590,7},'Value'},{type,{2590,16},term,[]}]]}]]}]}}]}},{{function,size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1937}],[<<115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,105,110,32,97,32,116,117,112,108,101,32,111,114,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,110,32,97,32,98,105,110,97,114,121,32,111,114,32,98,105,116,115,116,114,105,110,103,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,105,122,101,40,123,109,111,114,110,105,44,32,109,117,108,108,101,44,32,98,119,97,110,103,101,125,41,46,10,51,10,62,32,115,105,122,101,40,60,60,49,49,44,32,50,50,44,32,51,51,62,62,41,46,10,51>>]}]},{p,[],[<<70,111,114,32,98,105,116,115,116,114,105,110,103,115,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,119,104,111,108,101,32,98,121,116,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,105,116,115,32,105,110,32,116,104,101,32,98,105,116,115,116,114,105,110,103,32,105,115,32,110,111,116,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,44,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,105,115,32,114,111,117,110,100,101,100,32>>,{em,[],[<<100,111,119,110>>]},<<46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,117,112,108,101,95,115,105,122,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,117,112,108,101,95,115,105,122,101,47,49>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,121,116,101,95,115,105,122,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,121,116,101,95,115,105,122,101,47,49>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,116,95,115,105,122,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,116,95,115,105,122,101,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,51,49,51>>,signature => [{attribute,{1937,2},spec,{{size,1},[{type,{1937,11},bounded_fun,[{type,{1937,11},'fun',[{type,{1937,11},product,[{var,{1937,12},'Item'}]},{type,{1937,21},non_neg_integer,[]}]},[{type,{1938,7},constraint,[{atom,{1938,7},is_subtype},[{var,{1938,7},'Item'},{type,{1938,15},union,[{type,{1938,15},tuple,any},{type,{1938,25},binary,[]}]}]]}]]}]}}]}},{{function,spawn,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2972}],[<<115,112,97,119,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,51,51,54>>,signature => [{attribute,{2972,2},spec,{{spawn,1},[{type,{2972,12},bounded_fun,[{type,{2972,12},'fun',[{type,{2972,12},product,[{var,{2972,13},'Fun'}]},{type,{2972,21},pid,[]}]},[{type,{2973,7},constraint,[{atom,{2973,7},is_subtype},[{var,{2973,7},'Fun'},{type,{2973,14},function,[]}]]}]]}]}}]}},{{function,spawn,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2981}],[<<115,112,97,119,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,51,52,55>>,signature => [{attribute,{2981,2},spec,{{spawn,2},[{type,{2981,12},bounded_fun,[{type,{2981,12},'fun',[{type,{2981,12},product,[{var,{2981,13},'Node'},{var,{2981,19},'Fun'}]},{type,{2981,27},pid,[]}]},[{type,{2982,7},constraint,[{atom,{2982,7},is_subtype},[{var,{2982,7},'Node'},{type,{2982,15},node,[]}]]},{type,{2983,7},constraint,[{atom,{2983,7},is_subtype},[{var,{2983,7},'Fun'},{type,{2983,14},function,[]}]]}]]}]}}]}},{{function,spawn,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1943}],[<<115,112,97,119,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46>>]},{p,[],[{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114,58,117,110,100,101,102,105,110,101,100,95,102,117,110,99,116,105,111,110,40,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,103,115,41>>]},<<32,105,115,32,101,118,97,108,117,97,116,101,100,32,98,121,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,105,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,40,119,104,101,114,101,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32>>,{code,[],[<<65,114,103,115>>]},<<41,46,32,84,104,101,32,101,114,114,111,114,32,104,97,110,100,108,101,114,32,99,97,110,32,98,101,32,114,101,100,101,102,105,110,101,100,32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<41,46,32,73,102,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,111,114,32,116,104,101,32,117,115,101,114,32,104,97,115,32,114,101,100,101,102,105,110,101,100,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<101,114,114,111,114,95,104,97,110,100,108,101,114>>]},<<32,97,110,100,32,105,116,115,32,114,101,112,108,97,99,101,109,101,110,116,32,105,115,32,117,110,100,101,102,105,110,101,100,44,32,97,32,102,97,105,108,117,114,101,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<117,110,100,101,102>>]},<<32,111,99,99,117,114,115,46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,112,97,119,110,40,115,112,101,101,100,44,32,114,101,103,117,108,97,116,111,114,44,32,91,104,105,103,104,95,115,112,101,101,100,44,32,116,104,105,110,95,99,117,116,93,41,46,10,60,48,46,49,51,46,49,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,51,54,49>>,signature => [{attribute,{1943,2},spec,{{spawn,3},[{type,{1943,12},bounded_fun,[{type,{1943,12},'fun',[{type,{1943,12},product,[{var,{1943,13},'Module'},{var,{1943,21},'Function'},{var,{1943,31},'Args'}]},{type,{1943,40},pid,[]}]},[{type,{1944,7},constraint,[{atom,{1944,7},is_subtype},[{var,{1944,7},'Module'},{type,{1944,17},module,[]}]]},{type,{1945,7},constraint,[{atom,{1945,7},is_subtype},[{var,{1945,7},'Function'},{type,{1945,19},atom,[]}]]},{type,{1946,7},constraint,[{atom,{1946,7},is_subtype},[{var,{1946,7},'Args'},{type,{1946,15},list,[{type,{1946,16},term,[]}]}]]}]]}]}}]}},{{function,spawn,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3110}],[<<115,112,97,119,110,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,51,56,54>>,signature => [{attribute,{3110,2},spec,{{spawn,4},[{type,{3110,12},bounded_fun,[{type,{3110,12},'fun',[{type,{3110,12},product,[{var,{3110,13},'Node'},{var,{3110,19},'Module'},{var,{3110,27},'Function'},{var,{3110,37},'Args'}]},{type,{3110,46},pid,[]}]},[{type,{3111,7},constraint,[{atom,{3111,7},is_subtype},[{var,{3111,7},'Node'},{type,{3111,15},node,[]}]]},{type,{3112,7},constraint,[{atom,{3112,7},is_subtype},[{var,{3112,7},'Module'},{type,{3112,17},module,[]}]]},{type,{3113,7},constraint,[{atom,{3113,7},is_subtype},[{var,{3113,7},'Function'},{type,{3113,19},atom,[]}]]},{type,{3114,7},constraint,[{atom,{3114,7},is_subtype},[{var,{3114,7},'Args'},{type,{3114,15},list,[{type,{3114,16},term,[]}]}]]}]]}]}}]}},{{function,spawn_link,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2993}],[<<115,112,97,119,110,95,108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,48,49>>,signature => [{attribute,{2993,2},spec,{{spawn_link,1},[{type,{2993,17},bounded_fun,[{type,{2993,17},'fun',[{type,{2993,17},product,[{var,{2993,18},'Fun'}]},{type,{2993,26},pid,[]}]},[{type,{2994,7},constraint,[{atom,{2994,7},is_subtype},[{var,{2994,7},'Fun'},{type,{2994,14},function,[]}]]}]]}]}}]}},{{function,spawn_link,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3002}],[<<115,112,97,119,110,95,108,105,110,107,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,32,97,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,49,53>>,signature => [{attribute,{3002,2},spec,{{spawn_link,2},[{type,{3002,17},bounded_fun,[{type,{3002,17},'fun',[{type,{3002,17},product,[{var,{3002,18},'Node'},{var,{3002,24},'Fun'}]},{type,{3002,32},pid,[]}]},[{type,{3003,7},constraint,[{atom,{3003,7},is_subtype},[{var,{3003,7},'Node'},{type,{3003,15},node,[]}]]},{type,{3004,7},constraint,[{atom,{3004,7},is_subtype},[{var,{3004,7},'Fun'},{type,{3004,14},function,[]}]]}]]}]}}]}},{{function,spawn_link,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1951}],[<<115,112,97,119,110,95,108,105,110,107,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,51,50>>,signature => [{attribute,{1951,2},spec,{{spawn_link,3},[{type,{1951,17},bounded_fun,[{type,{1951,17},'fun',[{type,{1951,17},product,[{var,{1951,18},'Module'},{var,{1951,26},'Function'},{var,{1951,36},'Args'}]},{type,{1951,45},pid,[]}]},[{type,{1952,7},constraint,[{atom,{1952,7},is_subtype},[{var,{1952,7},'Module'},{type,{1952,17},module,[]}]]},{type,{1953,7},constraint,[{atom,{1953,7},is_subtype},[{var,{1953,7},'Function'},{type,{1953,19},atom,[]}]]},{type,{1954,7},constraint,[{atom,{1954,7},is_subtype},[{var,{1954,7},'Args'},{type,{1954,15},list,[{type,{1954,16},term,[]}]}]]}]]}]}}]}},{{function,spawn_link,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3132}],[<<115,112,97,119,110,95,108,105,110,107,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,108,105,110,107,32,105,115,32,99,114,101,97,116,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,97,116,111,109,105,99,97,108,108,121,46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,32,97,110,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,52,54>>,signature => [{attribute,{3132,2},spec,{{spawn_link,4},[{type,{3132,17},bounded_fun,[{type,{3132,17},'fun',[{type,{3132,17},product,[{var,{3132,18},'Node'},{var,{3132,24},'Module'},{var,{3132,32},'Function'},{var,{3132,42},'Args'}]},{type,{3132,51},pid,[]}]},[{type,{3133,7},constraint,[{atom,{3133,7},is_subtype},[{var,{3133,7},'Node'},{type,{3133,15},node,[]}]]},{type,{3134,7},constraint,[{atom,{3134,7},is_subtype},[{var,{3134,7},'Module'},{type,{3134,17},module,[]}]]},{type,{3135,7},constraint,[{atom,{3135,7},is_subtype},[{var,{3135,7},'Function'},{type,{3135,19},atom,[]}]]},{type,{3136,7},constraint,[{atom,{3136,7},is_subtype},[{var,{3136,7},'Args'},{type,{3136,15},list,[{type,{3136,16},term,[]}]}]]}]]}]}}]}},{{function,spawn_monitor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3016}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,44,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<44,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,97,32,109,111,110,105,116,111,114,32,99,114,101,97,116,101,100,32,116,111,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,54,52>>,signature => [{attribute,{3016,2},spec,{{spawn_monitor,1},[{type,{3016,20},bounded_fun,[{type,{3016,20},'fun',[{type,{3016,20},product,[{var,{3016,21},'Fun'}]},{type,{3016,29},tuple,[{type,{3016,30},pid,[]},{type,{3016,37},reference,[]}]}]},[{type,{3017,7},constraint,[{atom,{3017,7},is_subtype},[{var,{3017,7},'Fun'},{type,{3017,14},function,[]}]]}]]}]}}]}},{{function,spawn_monitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3023}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,44,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<44,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,97,32,109,111,110,105,116,111,114,32,99,114,101,97,116,101,100,32,116,111,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,100,105,115,116,114,105,98,117,116,101,100,32>>,{code,[],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,40,41>>]},<<44,32,116,104,101,32,99,97,108,108,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,101,120,99,101,112,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,55,56>>,signature => [{attribute,{3023,2},spec,{{spawn_monitor,2},[{type,{3023,20},bounded_fun,[{type,{3023,20},'fun',[{type,{3023,20},product,[{var,{3023,21},'Node'},{var,{3023,27},'Fun'}]},{type,{3023,35},tuple,[{type,{3023,36},pid,[]},{type,{3023,43},reference,[]}]}]},[{type,{3024,7},constraint,[{atom,{3024,7},is_subtype},[{var,{3024,7},'Node'},{type,{3024,15},node,[]}]]},{type,{3025,7},constraint,[{atom,{3025,7},is_subtype},[{var,{3025,7},'Fun'},{type,{3025,14},function,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_monitor,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3037}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,51>>],#{<<101,110>> => [{p,[],[<<65,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46,32,84,104,101,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,52,57,53>>,signature => [{attribute,{3037,2},spec,{{spawn_monitor,3},[{type,{3037,20},bounded_fun,[{type,{3037,20},'fun',[{type,{3037,20},product,[{var,{3037,21},'Module'},{var,{3037,29},'Function'},{var,{3037,39},'Args'}]},{type,{3037,48},tuple,[{type,{3037,49},pid,[]},{type,{3037,56},reference,[]}]}]},[{type,{3038,7},constraint,[{atom,{3038,7},is_subtype},[{var,{3038,7},'Module'},{type,{3038,17},module,[]}]]},{type,{3039,7},constraint,[{atom,{3039,7},is_subtype},[{var,{3039,7},'Function'},{type,{3039,19},atom,[]}]]},{type,{3040,7},constraint,[{atom,{3040,7},is_subtype},[{var,{3040,7},'Args'},{type,{3040,15},list,[{type,{3040,16},term,[]}]}]]}]]}]}}]}},{{function,spawn_monitor,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3154}],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,47,52>>],#{<<101,110>> => [{p,[],[<<65,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32,116,104,101,32,110,111,100,101,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,84,104,101,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,32,97,116,32,116,104,101,32,115,97,109,101,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,97,110,100,32,97,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,100,105,115,116,114,105,98,117,116,101,100,32>>,{code,[],[<<115,112,97,119,110,95,109,111,110,105,116,111,114,40,41>>]},<<44,32,116,104,101,32,99,97,108,108,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,101,120,99,101,112,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,48,57>>,signature => [{attribute,{3154,2},spec,{{spawn_monitor,4},[{type,{3154,20},bounded_fun,[{type,{3154,20},'fun',[{type,{3154,20},product,[{var,{3154,21},'Node'},{var,{3154,27},'Module'},{var,{3154,35},'Function'},{var,{3154,45},'Args'}]},{type,{3154,54},tuple,[{type,{3154,55},pid,[]},{type,{3154,62},reference,[]}]}]},[{type,{3155,7},constraint,[{atom,{3155,7},is_subtype},[{var,{3155,7},'Node'},{type,{3155,15},node,[]}]]},{type,{3156,7},constraint,[{atom,{3156,7},is_subtype},[{var,{3156,7},'Module'},{type,{3156,17},module,[]}]]},{type,{3157,7},constraint,[{atom,{3157,7},is_subtype},[{var,{3157,7},'Function'},{type,{3157,19},atom,[]}]]},{type,{3158,7},constraint,[{atom,{3158,7},is_subtype},[{var,{3158,7},'Args'},{type,{3158,15},list,[{type,{3158,16},term,[]}]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_opt,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3067}],[<<115,112,97,119,110,95,111,112,116,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<115,112,97,119,110,95,111,112,116,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,44,32,97,110,100,32,98,111,116,104,32,116,104,101,32,112,105,100,32,97,110,100,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,32,97,114,101,32,114,101,116,117,114,110,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,50,54>>,signature => [{attribute,{3067,2},spec,{{spawn_opt,2},[{type,{3067,16},bounded_fun,[{type,{3067,16},'fun',[{type,{3067,16},product,[{var,{3067,17},'Fun'},{var,{3067,22},'Options'}]},{type,{3067,34},union,[{type,{3067,34},pid,[]},{type,{3067,42},tuple,[{type,{3067,43},pid,[]},{type,{3067,50},reference,[]}]}]}]},[{type,{3068,7},constraint,[{atom,{3068,7},is_subtype},[{var,{3068,7},'Fun'},{type,{3068,14},function,[]}]]},{type,{3069,7},constraint,[{atom,{3069,7},is_subtype},[{var,{3069,7},'Options'},{type,{3069,18},list,[{user_type,{3069,19},spawn_opt_option,[]}]}]]}]]}]}}]}},{{function,spawn_opt,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3082}],[<<115,112,97,119,110,95,111,112,116,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<70,117,110>>]},<<32,116,111,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]},{p,[],[<<86,97,108,105,100,32,111,112,116,105,111,110,115,32,100,101,112,101,110,100,115,32,111,110,32,119,104,97,116,32,111,112,116,105,111,110,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,102,111,114,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,111,102,32,99,117,114,114,101,110,116,32,79,84,80,32,118,101,114,115,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,52,52>>,signature => [{attribute,{3082,2},spec,{{spawn_opt,3},[{type,{3082,16},bounded_fun,[{type,{3082,16},'fun',[{type,{3082,16},product,[{var,{3082,17},'Node'},{var,{3082,23},'Fun'},{var,{3082,28},'Options'}]},{type,{3082,40},union,[{type,{3082,40},pid,[]},{type,{3082,48},tuple,[{type,{3082,49},pid,[]},{type,{3082,56},reference,[]}]}]}]},[{type,{3083,7},constraint,[{atom,{3083,7},is_subtype},[{var,{3083,7},'Node'},{type,{3083,15},node,[]}]]},{type,{3084,7},constraint,[{atom,{3084,7},is_subtype},[{var,{3084,7},'Fun'},{type,{3084,14},function,[]}]]},{type,{3085,7},constraint,[{atom,{3085,7},is_subtype},[{var,{3085,7},'Options'},{type,{3085,18},list,[{type,{3085,19},union,[{atom,{3085,19},monitor},{type,{3086,19},tuple,[{atom,{3086,20},monitor},{type,{3086,29},list,[{user_type,{3086,30},monitor_option,[]}]}]},{atom,{3087,19},link},{var,{3088,19},'OtherOption'}]}]}]]},{type,{3089,7},constraint,[{atom,{3089,7},is_subtype},[{var,{3089,7},'OtherOption'},{type,{3089,22},term,[]}]]}]]}]}}]}},{{function,spawn_opt,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3199}],[<<115,112,97,119,110,95,111,112,116,47,52>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{li,[{name,<<112,114,105,111,114,105,116,121,95,108,101,118,101,108>>}],[]},{li,[{name,<<115,112,97,119,110,95,111,112,116,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<87,111,114,107,115,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,47,51>>]}]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,97,110,32,101,120,116,114,97,32,111,112,116,105,111,110,32,108,105,115,116,32,105,115,32,115,112,101,99,105,102,105,101,100,32,119,104,101,110,32,99,114,101,97,116,105,110,103,32,116,104,101,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,32,105,115,32,109,111,110,105,116,111,114,101,100,44,32,97,110,100,32,98,111,116,104,32,116,104,101,32,112,105,100,32,97,110,100,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,116,104,101,32,109,111,110,105,116,111,114,32,97,114,101,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,105,110,107>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,97,32,108,105,110,107,32,116,111,32,116,104,101,32,112,97,114,101,110,116,32,112,114,111,99,101,115,115,32,40,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,108,105,110,107,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,108,105,110,107,47,51>>]}]},<<32,100,111,101,115,41,46>>]}]},{dt,[],[{code,[],[<<109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<77,111,110,105,116,111,114,115,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,40,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,41>>]}]},<<32,100,111,101,115,41,46,32,65,32>>,{code,[],[<<123,80,105,100,44,32,77,111,110,105,116,111,114,82,101,102,125>>]},<<32,116,117,112,108,101,32,119,105,108,108,32,98,101,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,32,111,102,32,106,117,115,116,32,97,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,44,32,77,111,110,105,116,111,114,79,112,116,115,125>>]}]},{dd,[],[{p,[],[<<77,111,110,105,116,111,114,115,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,119,105,116,104,32,111,112,116,105,111,110,115,32,40,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,44,32,77,111,110,105,116,111,114,79,112,116,115,41>>]}]},<<32,100,111,101,115,41,46,32,65,32>>,{code,[],[<<123,80,105,100,44,32,77,111,110,105,116,111,114,82,101,102,125>>]},<<32,116,117,112,108,101,32,119,105,108,108,32,98,101,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,32,111,102,32,106,117,115,116,32,97,32>>,{code,[],[<<80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,112,114,105,111,114,105,116,121,32,111,102,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,46,32,69,113,117,105,118,97,108,101,110,116,32,116,111,32,101,120,101,99,117,116,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]},<<32,105,110,32,116,104,101,32,115,116,97,114,116,32,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,32,110,101,119,32,112,114,111,99,101,115,115,44,32,101,120,99,101,112,116,32,116,104,97,116,32,116,104,101,32,112,114,105,111,114,105,116,121,32,105,115,32,115,101,116,32,98,101,102,111,114,101,32,116,104,101,32,112,114,111,99,101,115,115,32,105,115,32,115,101,108,101,99,116,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,32,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,105,111,114,105,116,105,101,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114,44,32,78,117,109,98,101,114,125>>]}]},{dd,[],[{p,[],[<<85,115,101,102,117,108,32,111,110,108,121,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,116,117,110,105,110,103,46,32,68,111,32,110,111,116,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,112,114,111,98,108,101,109,32,119,105,116,104,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,115,32,111,114,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,44,32,97,110,100,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,111,112,116,105,111,110,32,105,109,112,114,111,118,101,115,32,109,97,116,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,117,115,101,115,32,97,32,103,101,110,101,114,97,116,105,111,110,97,108,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,99,104,101,109,101,44,32,117,115,105,110,103,32,97,110,32,34,111,108,100,32,104,101,97,112,34,32,102,111,114,32,100,97,116,97,32,116,104,97,116,32,104,97,115,32,115,117,114,118,105,118,101,100,32,97,116,32,108,101,97,115,116,32,111,110,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,104,101,110,32,116,104,101,114,101,32,105,115,32,110,111,32,109,111,114,101,32,114,111,111,109,32,111,110,32,116,104,101,32,111,108,100,32,104,101,97,112,44,32,97,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,100,111,110,101,46>>]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,103,101,110,101,114,97,116,105,111,110,97,108,32,99,111,108,108,101,99,116,105,111,110,115,32,98,101,102,111,114,101,32,102,111,114,99,105,110,103,32,97,32,102,117,108,108,115,119,101,101,112,44,32,101,118,101,110,32,105,102,32,116,104,101,114,101,32,105,115,32,114,111,111,109,32,111,110,32,116,104,101,32,111,108,100,32,104,101,97,112,46,32,83,101,116,116,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,116,111,32,122,101,114,111,32,100,105,115,97,98,108,101,115,32,116,104,101,32,103,101,110,101,114,97,108,32,99,111,108,108,101,99,116,105,111,110,32,97,108,103,111,114,105,116,104,109,44,32,116,104,97,116,32,105,115,44,32,97,108,108,32,108,105,118,101,32,100,97,116,97,32,105,115,32,99,111,112,105,101,100,32,97,116,32,101,118,101,114,121,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[<<65,32,102,101,119,32,99,97,115,101,115,32,119,104,101,110,32,105,116,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,116,111,32,99,104,97,110,103,101,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,98,105,110,97,114,105,101,115,32,116,104,97,116,32,97,114,101,32,110,111,32,108,111,110,103,101,114,32,117,115,101,100,32,97,114,101,32,116,111,32,98,101,32,116,104,114,111,119,110,32,97,119,97,121,32,97,115,32,115,111,111,110,32,97,115,32,112,111,115,115,105,98,108,101,46,32,40,83,101,116,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,122,101,114,111,46,41>>]}]},{li,[],[{p,[],[<<65,32,112,114,111,99,101,115,115,32,116,104,97,116,32,109,111,115,116,108,121,32,104,97,118,101,32,115,104,111,114,116,45,108,105,118,101,100,32,100,97,116,97,32,105,115,32,102,117,108,108,115,119,101,101,112,101,100,32,115,101,108,100,111,109,32,111,114,32,110,101,118,101,114,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,111,108,100,32,104,101,97,112,32,99,111,110,116,97,105,110,115,32,109,111,115,116,108,121,32,103,97,114,98,97,103,101,46,32,84,111,32,101,110,115,117,114,101,32,97,32,102,117,108,108,115,119,101,101,112,32,111,99,99,97,115,105,111,110,97,108,108,121,44,32,115,101,116,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,97,32,115,117,105,116,97,98,108,101,32,118,97,108,117,101,44,32,115,117,99,104,32,97,115,32,49,48,32,111,114,32,50,48,46>>]}]},{li,[],[<<73,110,32,101,109,98,101,100,100,101,100,32,115,121,115,116,101,109,115,32,119,105,116,104,32,97,32,108,105,109,105,116,101,100,32,97,109,111,117,110,116,32,111,102,32,82,65,77,32,97,110,100,32,110,111,32,118,105,114,116,117,97,108,32,109,101,109,111,114,121,44,32,121,111,117,32,109,105,103,104,116,32,119,97,110,116,32,116,111,32,112,114,101,115,101,114,118,101,32,109,101,109,111,114,121,32,98,121,32,115,101,116,116,105,110,103,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,116,111,32,122,101,114,111,46,32,40,84,104,101,32,118,97,108,117,101,32,99,97,110,32,98,101,32,115,101,116,32,103,108,111,98,97,108,108,121,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,47,50>>]}]},<<46,41>>]}]}]},{dt,[],[{code,[],[<<123,109,105,110,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<85,115,101,102,117,108,32,111,110,108,121,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,116,117,110,105,110,103,46,32,68,111,32,110,111,116,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,112,114,111,98,108,101,109,32,119,105,116,104,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,115,32,111,114,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,44,32,97,110,100,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,111,112,116,105,111,110,32,105,109,112,114,111,118,101,115,32,109,97,116,116,101,114,115,46>>]},{p,[],[<<71,105,118,101,115,32,97,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,118,97,108,117,101,32,104,105,103,104,101,114,32,116,104,97,110,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,99,97,110,32,115,112,101,101,100,32,117,112,32,115,111,109,101,32,112,114,111,99,101,115,115,101,115,32,98,101,99,97,117,115,101,32,108,101,115,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,100,111,110,101,46,32,72,111,119,101,118,101,114,44,32,115,101,116,116,105,110,103,32,97,32,116,111,111,32,104,105,103,104,32,118,97,108,117,101,32,99,97,110,32,119,97,115,116,101,32,109,101,109,111,114,121,32,97,110,100,32,115,108,111,119,32,100,111,119,110,32,116,104,101,32,115,121,115,116,101,109,32,98,101,99,97,117,115,101,32,111,102,32,119,111,114,115,101,32,100,97,116,97,32,108,111,99,97,108,105,116,121,46,32,84,104,101,114,101,102,111,114,101,44,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,111,110,108,121,32,102,111,114,32,102,105,110,101,45,116,117,110,105,110,103,32,97,110,32,97,112,112,108,105,99,97,116,105,111,110,32,97,110,100,32,116,111,32,109,101,97,115,117,114,101,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,119,105,116,104,32,118,97,114,105,111,117,115,32>>,{code,[],[<<83,105,122,101>>]},<<32,118,97,108,117,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101,44,32,86,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<85,115,101,102,117,108,32,111,110,108,121,32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,116,117,110,105,110,103,46,32,68,111,32,110,111,116,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,112,114,111,98,108,101,109,32,119,105,116,104,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,115,32,111,114,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,44,32,97,110,100,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,111,112,116,105,111,110,32,105,109,112,114,111,118,101,115,32,109,97,116,116,101,114,115,46>>]},{p,[],[<<71,105,118,101,115,32,97,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,44,32,105,110,32,119,111,114,100,115,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,118,97,108,117,101,32,104,105,103,104,101,114,32,116,104,97,110,32,116,104,101,32,115,121,115,116,101,109,32,100,101,102,97,117,108,116,32,99,97,110,32,115,112,101,101,100,32,117,112,32,115,111,109,101,32,112,114,111,99,101,115,115,101,115,32,98,101,99,97,117,115,101,32,108,101,115,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,100,111,110,101,46,32,72,111,119,101,118,101,114,44,32,115,101,116,116,105,110,103,32,97,32,116,111,111,32,104,105,103,104,32,118,97,108,117,101,32,99,97,110,32,119,97,115,116,101,32,109,101,109,111,114,121,46,32,84,104,101,114,101,102,111,114,101,44,32,117,115,101,32,116,104,105,115,32,111,112,116,105,111,110,32,111,110,108,121,32,102,111,114,32,102,105,110,101,45,116,117,110,105,110,103,32,97,110,32,97,112,112,108,105,99,97,116,105,111,110,32,97,110,100,32,116,111,32,109,101,97,115,117,114,101,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,119,105,116,104,32,118,97,114,105,111,117,115,32>>,{code,[],[<<86,83,105,122,101>>]},<<32,118,97,108,117,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,46,32,84,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,83,105,122,101,41>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,46,32>>,{code,[],[<<77,81,68>>]},<<32,99,97,110,32,98,101,32,101,105,116,104,101,114,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<32,111,114,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,113,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,113,100>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,53,54,55>>,signature => [{attribute,{3199,2},spec,{{spawn_opt,4},[{type,{3199,16},bounded_fun,[{type,{3199,16},'fun',[{type,{3199,16},product,[{var,{3199,17},'Module'},{var,{3199,25},'Function'},{var,{3199,35},'Args'},{var,{3199,41},'Options'}]},{type,{3200,11},union,[{var,{3200,11},'Pid'},{type,{3200,17},tuple,[{var,{3200,18},'Pid'},{var,{3200,23},'MonitorRef'}]}]}]},[{type,{3201,7},constraint,[{atom,{3201,7},is_subtype},[{var,{3201,7},'Module'},{type,{3201,17},module,[]}]]},{type,{3202,7},constraint,[{atom,{3202,7},is_subtype},[{var,{3202,7},'Function'},{type,{3202,19},atom,[]}]]},{type,{3203,7},constraint,[{atom,{3203,7},is_subtype},[{var,{3203,7},'Args'},{type,{3203,15},list,[{type,{3203,16},term,[]}]}]]},{type,{3204,7},constraint,[{atom,{3204,7},is_subtype},[{var,{3204,7},'Options'},{type,{3204,18},list,[{user_type,{3204,19},spawn_opt_option,[]}]}]]},{type,{3205,7},constraint,[{atom,{3205,7},is_subtype},[{var,{3205,7},'Pid'},{type,{3205,14},pid,[]}]]},{type,{3206,7},constraint,[{atom,{3206,7},is_subtype},[{var,{3206,7},'MonitorRef'},{type,{3206,21},reference,[]}]]}]]}]}}]}},{{function,spawn_opt,5},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3211}],[<<115,112,97,119,110,95,111,112,116,47,53>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<32,111,110,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,73,102,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,97,32,117,115,101,108,101,115,115,32,112,105,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,116,104,101,114,119,105,115,101,32,119,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]},{p,[],[<<86,97,108,105,100,32,111,112,116,105,111,110,115,32,100,101,112,101,110,100,115,32,111,110,32,119,104,97,116,32,111,112,116,105,111,110,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,102,111,114,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,111,102,32,99,117,114,114,101,110,116,32,79,84,80,32,118,101,114,115,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,49,53>>,signature => [{attribute,{3211,2},spec,{{spawn_opt,5},[{type,{3211,16},bounded_fun,[{type,{3211,16},'fun',[{type,{3211,16},product,[{var,{3211,17},'Node'},{var,{3211,23},'Module'},{var,{3211,31},'Function'},{var,{3211,41},'Args'},{var,{3211,47},'Options'}]},{type,{3212,24},union,[{type,{3212,24},pid,[]},{type,{3212,32},tuple,[{type,{3212,33},pid,[]},{type,{3212,40},reference,[]}]}]}]},[{type,{3213,7},constraint,[{atom,{3213,7},is_subtype},[{var,{3213,7},'Node'},{type,{3213,15},node,[]}]]},{type,{3214,7},constraint,[{atom,{3214,7},is_subtype},[{var,{3214,7},'Module'},{type,{3214,17},module,[]}]]},{type,{3215,7},constraint,[{atom,{3215,7},is_subtype},[{var,{3215,7},'Function'},{type,{3215,19},atom,[]}]]},{type,{3216,7},constraint,[{atom,{3216,7},is_subtype},[{var,{3216,7},'Args'},{type,{3216,15},list,[{type,{3216,16},term,[]}]}]]},{type,{3217,7},constraint,[{atom,{3217,7},is_subtype},[{var,{3217,7},'Options'},{type,{3217,18},list,[{type,{3217,19},union,[{atom,{3217,19},monitor},{type,{3218,19},tuple,[{atom,{3218,20},monitor},{type,{3218,29},list,[{user_type,{3218,30},monitor_option,[]}]}]},{atom,{3219,19},link},{var,{3220,19},'OtherOption'}]}]}]]},{type,{3221,7},constraint,[{atom,{3221,7},is_subtype},[{var,{3221,7},'OtherOption'},{type,{3221,22},term,[]}]]}]]}]}}]}},{{function,spawn_request,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3266}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,70,117,110,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,51,57>>,signature => [{attribute,{3266,2},spec,{{spawn_request,1},[{type,{3266,20},bounded_fun,[{type,{3266,20},'fun',[{type,{3266,20},product,[{var,{3266,21},'Fun'}]},{var,{3266,29},'ReqId'}]},[{type,{3267,7},constraint,[{atom,{3267,7},is_subtype},[{var,{3267,7},'Fun'},{type,{3267,14},function,[]}]]},{type,{3268,7},constraint,[{atom,{3268,7},is_subtype},[{var,{3268,7},'ReqId'},{type,{3268,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3284}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,70,117,110,44,79,112,116,105,111,110,115,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,53,49>>,signature => [{attribute,{3284,2},spec,{{spawn_request,2},[{type,{3284,20},bounded_fun,[{type,{3284,20},'fun',[{type,{3284,20},product,[{var,{3284,21},'Fun'},{var,{3284,26},'Options'}]},{var,{3284,38},'ReqId'}]},[{type,{3285,7},constraint,[{atom,{3285,7},is_subtype},[{var,{3285,7},'Fun'},{type,{3285,14},function,[]}]]},{type,{3286,7},constraint,[{atom,{3286,7},is_subtype},[{var,{3286,7},'Option'},{type,{3286,17},union,[{type,{3286,17},tuple,[{atom,{3286,18},reply_tag},{var,{3286,29},'ReplyTag'}]},{type,{3287,17},tuple,[{atom,{3287,18},reply},{var,{3287,25},'Reply'}]},{user_type,{3288,17},spawn_opt_option,[]}]}]]},{type,{3289,7},constraint,[{atom,{3289,7},is_subtype},[{var,{3289,7},'ReplyTag'},{type,{3289,19},term,[]}]]},{type,{3290,7},constraint,[{atom,{3290,7},is_subtype},[{var,{3290,7},'Reply'},{type,{3290,16},union,[{atom,{3290,16},yes},{atom,{3290,22},no},{atom,{3290,27},error_only},{atom,{3290,40},success_only}]}]]},{type,{3291,7},constraint,[{atom,{3291,7},is_subtype},[{var,{3291,7},'Options'},{type,{3291,18},list,[{var,{3291,19},'Option'}]}]]},{type,{3292,7},constraint,[{atom,{3292,7},is_subtype},[{var,{3292,7},'ReqId'},{type,{3292,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3284}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,78,111,100,101,44,70,117,110,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,54,51>>,signature => [{attribute,{3284,2},spec,{{spawn_request,2},[{type,{3293,20},bounded_fun,[{type,{3293,20},'fun',[{type,{3293,20},product,[{var,{3293,21},'Node'},{var,{3293,27},'Fun'}]},{var,{3293,35},'ReqId'}]},[{type,{3294,7},constraint,[{atom,{3294,7},is_subtype},[{var,{3294,7},'Node'},{type,{3294,15},node,[]}]]},{type,{3295,7},constraint,[{atom,{3295,7},is_subtype},[{var,{3295,7},'Fun'},{type,{3295,14},function,[]}]]},{type,{3296,7},constraint,[{atom,{3296,7},is_subtype},[{var,{3296,7},'ReqId'},{type,{3296,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3319}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,78,111,100,101,44,101,114,108,97,110,103,44,97,112,112,108,121,44,91,70,117,110,44,91,93,93,44,79,112,116,105,111,110,115,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,117,115,105,110,103,32,116,104,101,32,102,117,110,32>>,{code,[],[<<70,117,110>>]},<<32,111,102,32,97,114,105,116,121,32,122,101,114,111,32,97,115,32,101,110,116,114,121,32,112,111,105,110,116,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<78,111,100,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<70,117,110>>]},<<32,105,115,32,110,111,116,32,97,32,102,117,110,32,111,102,32,97,114,105,116,121,32,122,101,114,111,46>>]}]},{li,[],[{p,[],[{code,[],[<<79,112,116,105,111,110,115>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,116,101,114,109,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,55,53>>,signature => [{attribute,{3319,2},spec,{{spawn_request,3},[{type,{3319,20},bounded_fun,[{type,{3319,20},'fun',[{type,{3319,20},product,[{var,{3319,21},'Node'},{var,{3319,27},'Fun'},{var,{3319,32},'Options'}]},{var,{3319,44},'ReqId'}]},[{type,{3320,7},constraint,[{atom,{3320,7},is_subtype},[{var,{3320,7},'Node'},{type,{3320,15},node,[]}]]},{type,{3321,7},constraint,[{atom,{3321,7},is_subtype},[{var,{3321,7},'Fun'},{type,{3321,14},function,[]}]]},{type,{3322,7},constraint,[{atom,{3322,7},is_subtype},[{var,{3322,7},'Options'},{type,{3322,18},list,[{var,{3322,19},'Option'}]}]]},{type,{3323,7},constraint,[{atom,{3323,7},is_subtype},[{var,{3323,7},'Option'},{type,{3323,17},union,[{atom,{3323,17},monitor},{type,{3324,17},tuple,[{atom,{3324,18},monitor},{type,{3324,27},list,[{user_type,{3324,28},monitor_option,[]}]}]},{atom,{3325,17},link},{type,{3326,17},tuple,[{atom,{3326,18},reply_tag},{var,{3326,29},'ReplyTag'}]},{type,{3327,17},tuple,[{atom,{3327,18},reply},{var,{3327,25},'Reply'}]},{var,{3328,17},'OtherOption'}]}]]},{type,{3329,7},constraint,[{atom,{3329,7},is_subtype},[{var,{3329,7},'ReplyTag'},{type,{3329,19},term,[]}]]},{type,{3330,7},constraint,[{atom,{3330,7},is_subtype},[{var,{3330,7},'Reply'},{type,{3330,16},union,[{atom,{3330,16},yes},{atom,{3330,22},no},{atom,{3330,27},error_only},{atom,{3330,40},success_only}]}]]},{type,{3331,7},constraint,[{atom,{3331,7},is_subtype},[{var,{3331,7},'OtherOption'},{type,{3331,22},term,[]}]]},{type,{3332,7},constraint,[{atom,{3332,7},is_subtype},[{var,{3332,7},'ReqId'},{type,{3332,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3319}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,65,114,103,115,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,55,57,53>>,signature => [{attribute,{3319,2},spec,{{spawn_request,3},[{type,{3333,20},bounded_fun,[{type,{3333,20},'fun',[{type,{3333,20},product,[{var,{3333,21},'Module'},{var,{3333,29},'Function'},{var,{3333,39},'Args'}]},{var,{3334,28},'ReqId'}]},[{type,{3335,7},constraint,[{atom,{3335,7},is_subtype},[{var,{3335,7},'Module'},{type,{3335,17},module,[]}]]},{type,{3336,7},constraint,[{atom,{3336,7},is_subtype},[{var,{3336,7},'Function'},{type,{3336,19},atom,[]}]]},{type,{3337,7},constraint,[{atom,{3337,7},is_subtype},[{var,{3337,7},'Args'},{type,{3337,15},list,[{type,{3337,16},term,[]}]}]]},{type,{3338,7},constraint,[{atom,{3338,7},is_subtype},[{var,{3338,7},'ReqId'},{type,{3338,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3359}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,52>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,78,111,100,101,44,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,65,114,103,115,44,91,93,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,105,116,104,32,110,111,32,111,112,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,56,48,55>>,signature => [{attribute,{3359,2},spec,{{spawn_request,4},[{type,{3359,20},bounded_fun,[{type,{3359,20},'fun',[{type,{3359,20},product,[{var,{3359,21},'Node'},{var,{3359,27},'Module'},{var,{3359,35},'Function'},{var,{3359,45},'Args'}]},{var,{3360,28},'ReqId'}]},[{type,{3361,7},constraint,[{atom,{3361,7},is_subtype},[{var,{3361,7},'Node'},{type,{3361,15},node,[]}]]},{type,{3362,7},constraint,[{atom,{3362,7},is_subtype},[{var,{3362,7},'Module'},{type,{3362,17},module,[]}]]},{type,{3363,7},constraint,[{atom,{3363,7},is_subtype},[{var,{3363,7},'Function'},{type,{3363,19},atom,[]}]]},{type,{3364,7},constraint,[{atom,{3364,7},is_subtype},[{var,{3364,7},'Args'},{type,{3364,15},list,[{type,{3364,16},term,[]}]}]]},{type,{3365,7},constraint,[{atom,{3365,7},is_subtype},[{var,{3365,7},'ReqId'},{type,{3365,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3359}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,52>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,110,111,100,101,40,41,44,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,65,114,103,115,44,79,112,116,105,111,110,115,41>>]}]},<<46,32,84,104,97,116,32,105,115,44,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,56,49,57>>,signature => [{attribute,{3359,2},spec,{{spawn_request,4},[{type,{3366,20},bounded_fun,[{type,{3366,20},'fun',[{type,{3366,20},product,[{var,{3366,21},'Module'},{var,{3366,29},'Function'},{var,{3366,39},'Args'},{var,{3366,45},'Options'}]},{var,{3367,28},'ReqId'}]},[{type,{3368,7},constraint,[{atom,{3368,7},is_subtype},[{var,{3368,7},'Module'},{type,{3368,17},module,[]}]]},{type,{3369,7},constraint,[{atom,{3369,7},is_subtype},[{var,{3369,7},'Function'},{type,{3369,19},atom,[]}]]},{type,{3370,7},constraint,[{atom,{3370,7},is_subtype},[{var,{3370,7},'Args'},{type,{3370,15},list,[{type,{3370,16},term,[]}]}]]},{type,{3371,7},constraint,[{atom,{3371,7},is_subtype},[{var,{3371,7},'Option'},{type,{3371,17},union,[{type,{3371,17},tuple,[{atom,{3371,18},reply_tag},{var,{3371,29},'ReplyTag'}]},{type,{3372,17},tuple,[{atom,{3372,18},reply},{var,{3372,25},'Reply'}]},{user_type,{3373,17},spawn_opt_option,[]}]}]]},{type,{3374,7},constraint,[{atom,{3374,7},is_subtype},[{var,{3374,7},'ReplyTag'},{type,{3374,19},term,[]}]]},{type,{3375,7},constraint,[{atom,{3375,7},is_subtype},[{var,{3375,7},'Reply'},{type,{3375,16},union,[{atom,{3375,16},yes},{atom,{3375,22},no},{atom,{3375,27},error_only},{atom,{3375,40},success_only}]}]]},{type,{3376,7},constraint,[{atom,{3376,7},is_subtype},[{var,{3376,7},'Options'},{type,{3376,18},list,[{var,{3376,19},'Option'}]}]]},{type,{3377,7},constraint,[{atom,{3377,7},is_subtype},[{var,{3377,7},'ReqId'},{type,{3377,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request,5},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3400}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>],#{<<101,110>> => [{p,[],[<<65,115,121,110,99,104,114,111,110,111,117,115,108,121,32,115,101,110,100,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46,32,82,101,116,117,114,110,115,32,97,32,114,101,113,117,101,115,116,32,105,100,101,110,116,105,102,105,101,114,32>>,{code,[],[<<82,101,113,73,100>>]},<<46>>]},{a,[{id,<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>}],[]},{p,[],[<<73,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,99,114,101,97,116,101,100,32,111,110,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,87,104,101,110,32,97,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,98,121,32,100,101,102,97,117,108,116,32,98,101,32,115,101,110,116,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,82,101,112,108,121,84,97,103,44,32,82,101,113,73,100,44,32,111,107,44,32,80,105,100,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,83,117,99,104,32,97,32,109,101,115,115,97,103,101,32,105,115,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,97,32>>,{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]},<<32,98,101,108,111,119,32,105,110,32,116,104,101,32,116,101,120,116,46,32>>,{code,[],[<<82,101,112,108,121,84,97,103>>]},<<32,105,115,32,98,121,32,100,101,102,97,117,108,116,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,112,97,119,110,95,114,101,112,108,121>>]},<<32,117,110,108,101,115,115,32,109,111,100,105,102,105,101,100,32,98,121,32,116,104,101,32>>,{code,[],[<<123,114,101,112,108,121,95,116,97,103,44,32,82,101,112,108,121,84,97,103,125>>]},<<32,111,112,116,105,111,110,46,32,84,104,101,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,115,116,97,114,116,101,100,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,111,102,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110>>]},<<32,116,111,32>>,{code,[],[<<65,114,103,115>>]},<<46>>]},{a,[{id,<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>}],[]},{p,[],[<<84,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,32,101,105,116,104,101,114,32,105,102,32,99,114,101,97,116,105,111,110,32,111,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,102,97,105,108,101,100,32,111,114,32,105,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,119,97,115,32,105,110,116,101,114,114,117,112,116,101,100,32,98,121,32,97,32,99,111,110,110,101,99,116,105,111,110,32,102,97,105,108,117,114,101,46,32,87,104,101,110,32,97,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,98,121,32,100,101,102,97,117,108,116,32,98,101,32,115,101,110,116,32,97,32,109,101,115,115,97,103,101,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,82,101,112,108,121,84,97,103,44,32,82,101,113,73,100,44,32,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<32,105,115,32,116,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,46,32,83,117,99,104,32,97,32,109,101,115,115,97,103,101,32,105,115,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,97,110,32>>,{i,[],[<<101,114,114,111,114,32,109,101,115,115,97,103,101>>]},<<32,98,101,108,111,119,32,105,110,32,116,104,101,32,116,101,120,116,46,32,67,117,114,114,101,110,116,108,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,112,97,119,110,32,101,114,114,111,114,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<115,32,97,114,101,32,100,101,102,105,110,101,100,44,32,98,117,116,32,111,116,104,101,114,32,114,101,97,115,111,110,115,32,99,97,110,32,97,112,112,101,97,114,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,111,112,116>>]}]},{dd,[],[{p,[],[<<65,110,32,105,110,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<32,119,97,115,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46,32,78,111,116,101,32,116,104,97,116,32,100,105,102,102,101,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,115,32,109,97,121,32,115,117,112,112,111,114,116,32,100,105,102,102,101,114,101,110,116,32,111,112,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,115,32,105,115,115,117,101,100,32,98,121,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<70,97,105,108,117,114,101,32,116,111,32,115,101,116,32,117,112,32,97,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<32,111,114,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,116,111,32,116,104,97,116,32,110,111,100,101,32,119,97,115,32,108,111,115,116,32,100,117,114,105,110,103,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,73,110,32,116,104,101,32,99,97,115,101,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,119,97,115,32,108,111,115,116,44,32,97,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,104,97,118,101,32,98,101,101,110,32,99,114,101,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<67,111,117,108,100,32,110,111,116,32,99,114,101,97,116,101,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,100,117,101,32,116,111,32,116,104,97,116,32,115,111,109,101,32,115,121,115,116,101,109,32,108,105,109,105,116,32,119,97,115,32,114,101,97,99,104,101,100,46,32,84,121,112,105,99,97,108,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,116,97,98,108,101,32,119,97,115,32,102,117,108,108,46>>]}]}]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<109,111,110,105,116,111,114>>]}]},{dd,[],[{p,[],[<<73,110,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,117,114,101,115,44,32,97,116,111,109,105,99,97,108,108,121,32,115,101,116,115,32,117,112,32,97,32,109,111,110,105,116,111,114,32,116,111,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,97,115,32,105,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,104,97,100,32,99,97,108,108,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,41>>]}]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,101,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<32,105,115,32,97,108,115,111,32,117,115,101,100,32,97,115,32,109,111,110,105,116,111,114,32,114,101,102,101,114,101,110,99,101,32,97,115,32,105,102,32,105,116,32,119,97,115,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,41>>]},<<46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,97,116,101,100,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,84,104,101,32,109,111,110,105,116,111,114,32,99,97,110,32,110,111,116,32,98,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,100,101,109,111,110,105,116,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<100,101,109,111,110,105,116,111,114,101,100>>]},<<32,98,101,102,111,114,101,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,65,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,102,111,114,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,109,111,110,105,116,111,114,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,110,111,116,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,116,104,97,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,73,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,110,111,32>>,{code,[],[<<39,68,79,87,78,39>>]},<<32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,46>>]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,98,101,116,119,101,101,110,32,116,104,101,32,110,111,100,101,115,32,105,110,118,111,108,118,101,100,32,105,110,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,105,115,32,108,111,115,116,32,100,117,114,105,110,103,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<46,32,65,32,110,101,119,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,104,97,118,101,32,98,101,101,110,32,99,114,101,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<123,109,111,110,105,116,111,114,44,32,77,111,110,105,116,111,114,79,112,116,115,125>>]}]},{dd,[],[{p,[],[<<73,110,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,117,114,101,115,44,32,97,116,111,109,105,99,97,108,108,121,32,115,101,116,115,32,117,112,32,97,32,109,111,110,105,116,111,114,32,116,111,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,97,115,32,105,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,104,97,100,32,99,97,108,108,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,40,112,114,111,99,101,115,115,44,32,80,105,100,44,32,77,111,110,105,116,111,114,79,112,116,115,41>>]}]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,83,101,101,32,116,104,101,32>>,{code,[],[<<109,111,110,105,116,111,114>>]},<<32,111,112,116,105,111,110,32,97,98,111,118,101,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,116,104,101,32,109,111,110,105,116,111,114,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,97,116,101,100,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,116,104,101,32,99,97,115,101,32,116,104,97,116,32,97,110,32,97,108,105,97,115,32,105,115,32,99,114,101,97,116,101,100,32,117,115,105,110,103,32,116,104,101,32,109,111,110,105,116,111,114,32,111,112,116,105,111,110,44,32,116,104,101,32,97,108,105,97,115,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,101,32,117,110,116,105,108,32,116,104,101,32,109,111,110,105,116,111,114,32,105,115,32,97,99,116,105,118,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<108,105,110,107>>]}]},{dd,[],[{p,[],[<<73,110,32,97,98,115,101,110,99,101,32,111,102,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,117,114,101,115,44,32,97,116,111,109,105,99,97,108,108,121,32,115,101,116,115,32,117,112,32,97,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,97,115,32,105,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,104,97,100,32,99,97,108,108,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,110,107,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,110,107,40,80,105,100,41>>]}]},<<32,119,104,101,114,101,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<84,104,101,32,108,105,110,107,32,119,105,108,108,32,110,111,116,32,98,101,32,97,99,116,105,118,97,116,101,100,32,102,111,114,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,84,104,101,32,108,105,110,107,32,99,97,110,32,110,111,116,32,98,101,32,114,101,109,111,118,101,100,32,98,101,102,111,114,101,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46,32,65,110,32,101,120,105,116,32,115,105,103,110,97,108,32,100,117,101,32,116,111,32,116,104,101,32,108,105,110,107,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,110,111,116,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,98,101,102,111,114,101,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,116,104,97,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,73,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,110,111,32,101,120,105,116,32,115,105,103,110,97,108,32,100,117,101,32,116,111,32,116,104,101,32,108,105,110,107,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,110,101,99,116,105,111,110,32,98,101,116,119,101,101,110,32,116,104,101,32,110,111,100,101,115,32,105,110,118,111,108,118,101,100,32,105,110,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,105,115,32,108,111,115,116,32,100,117,114,105,110,103,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<46,32,65,32,110,101,119,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,104,97,118,101,32,98,101,101,110,32,99,114,101,97,116,101,100,46,32,73,102,32,105,116,32,104,97,115,32,98,101,101,110,32,99,114,101,97,116,101,100,44,32,105,116,32,119,105,108,108,32,98,101,32,100,101,108,105,118,101,114,101,100,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,119,105,116,104,32,97,110,32,101,120,105,116,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<110,111,99,111,110,110,101,99,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,112,108,121,44,32,82,101,112,108,121,125>>]}]},{dd,[],[{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<82,101,112,108,121>>]},<<32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<121,101,115>>]}]},{dd,[],[{p,[],[<<65,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,32,111,114,32,110,111,116,46,32,73,102,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]},<<32,114,101,116,117,114,110,115,32,119,105,116,104,111,117,116,32,114,97,105,115,105,110,103,32,97,110,32,101,120,99,101,112,116,105,111,110,32,97,110,100,32,116,104,101,32>>,{code,[],[<<114,101,112,108,121>>]},<<32,111,112,116,105,111,110,32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<121,101,115>>]},<<44,32,116,104,101,32,99,97,108,108,101,114,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100,32,101,105,116,104,101,114,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,111,114,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<101,114,114,111,114,32,109,101,115,115,97,103,101>>]}]},<<46,32,84,104,101,32>>,{code,[],[<<114,101,112,108,121>>]},<<32,111,112,116,105,111,110,32,105,115,32,98,121,32,100,101,102,97,117,108,116,32,115,101,116,32,116,111,32>>,{code,[],[<<121,101,115>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,111>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,119,104,101,110,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,99,111,109,112,108,101,116,101,115,46,32,84,104,105,115,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,32,111,114,32,110,111,116,46>>]}]},{dt,[],[{code,[],[<<101,114,114,111,114,95,111,110,108,121>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,44,32,98,117,116,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<101,114,114,111,114,32,109,101,115,115,97,103,101>>]}]},<<32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,46>>]}]},{dt,[],[{code,[],[<<115,117,99,99,101,115,115,95,111,110,108,121>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32,98,117,116,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115,32,109,101,115,115,97,103,101>>]}]},<<32,119,105,108,108,32,98,101,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,105,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,115,117,99,99,101,101,100,115,46>>]}]}]}]},{dt,[],[{code,[],[<<123,114,101,112,108,121,95,116,97,103,44,32,82,101,112,108,121,84,97,103,125>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,116,104,101,32,114,101,112,108,121,32,116,97,103,32,116,111,32>>,{code,[],[<<82,101,112,108,121,84,97,103>>]},<<32,105,110,32,116,104,101,32,114,101,112,108,121,32,109,101,115,115,97,103,101,46,32,84,104,97,116,32,105,115,44,32,105,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,115,117,99,99,101,115,115,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<115,117,99,99,101,115,115>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,101,114,114,111,114,95,109,101,115,115,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{i,[],[<<101,114,114,111,114>>]}]},<<32,109,101,115,115,97,103,101,32,116,104,97,116,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,100,117,101,32,116,111,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,46,32,84,104,101,32,100,101,102,97,117,108,116,32,114,101,112,108,121,32,116,97,103,32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<115,112,97,119,110,95,114,101,112,108,121>>]},<<46>>]}]},{dt,[],[{code,[],[<<79,116,104,101,114,79,112,116,105,111,110>>]}]},{dd,[],[{p,[],[<<79,116,104,101,114,32,118,97,108,105,100,32,111,112,116,105,111,110,115,32,100,101,112,101,110,100,115,32,111,110,32,119,104,97,116,32,111,112,116,105,111,110,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,110,111,100,101,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<78,111,100,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,111,116,104,101,114,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,102,111,114,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,111,102,32,99,117,114,114,101,110,116,32,79,84,80,32,118,101,114,115,105,111,110,32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<46>>]}]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<78,111,100,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<77,111,100,117,108,101>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,110,111,116,32,97,110,32,97,116,111,109,46>>]}]},{li,[],[{p,[],[{code,[],[<<65,114,103,115>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,116,101,114,109,115,46>>]}]},{li,[],[{p,[],[{code,[],[<<79,112,116,105,111,110,115>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,116,101,114,109,115,46>>]}]}]},{p,[],[<<78,111,116,101,32,116,104,97,116,32,110,111,116,32,97,108,108,32,105,110,100,105,118,105,100,117,97,108,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,97,114,101,32,99,104,101,99,107,101,100,32,119,104,101,110,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,46,32,83,111,109,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,99,97,110,32,111,110,108,121,32,98,101,32,99,104,101,99,107,101,100,32,111,110,32,114,101,99,101,112,116,105,111,110,32,111,102,32,116,104,101,32,114,101,113,117,101,115,116,46,32,84,104,101,114,101,102,111,114,101,32,97,110,32,105,110,118,97,108,105,100,32,111,112,116,105,111,110,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,99,97,117,115,101,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,44,32,98,117,116,32,119,105,108,108,32,99,97,117,115,101,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,116,111,32,102,97,105,108,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,32>>,{code,[],[<<98,97,100,111,112,116>>]},<<46>>]},{p,[],[<<65,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,99,97,110,32,98,101,32,97,98,97,110,100,111,110,101,100,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,55,56,51,49>>,signature => [{attribute,{3400,2},spec,{{spawn_request,5},[{type,{3400,20},bounded_fun,[{type,{3400,20},'fun',[{type,{3400,20},product,[{var,{3400,21},'Node'},{var,{3400,27},'Module'},{var,{3400,35},'Function'},{var,{3400,45},'Args'},{var,{3400,51},'Options'}]},{var,{3401,28},'ReqId'}]},[{type,{3402,7},constraint,[{atom,{3402,7},is_subtype},[{var,{3402,7},'Node'},{type,{3402,15},node,[]}]]},{type,{3403,7},constraint,[{atom,{3403,7},is_subtype},[{var,{3403,7},'Module'},{type,{3403,17},module,[]}]]},{type,{3404,7},constraint,[{atom,{3404,7},is_subtype},[{var,{3404,7},'Function'},{type,{3404,19},atom,[]}]]},{type,{3405,7},constraint,[{atom,{3405,7},is_subtype},[{var,{3405,7},'Args'},{type,{3405,15},list,[{type,{3405,16},term,[]}]}]]},{type,{3406,7},constraint,[{atom,{3406,7},is_subtype},[{var,{3406,7},'Options'},{type,{3406,18},list,[{var,{3406,19},'Option'}]}]]},{type,{3407,7},constraint,[{atom,{3407,7},is_subtype},[{var,{3407,7},'Option'},{type,{3407,17},union,[{atom,{3407,17},monitor},{type,{3408,17},tuple,[{atom,{3408,18},monitor},{type,{3408,27},list,[{user_type,{3408,28},monitor_option,[]}]}]},{atom,{3409,17},link},{type,{3410,17},tuple,[{atom,{3410,18},reply_tag},{var,{3410,29},'ReplyTag'}]},{type,{3411,17},tuple,[{atom,{3411,18},reply},{var,{3411,25},'Reply'}]},{var,{3412,17},'OtherOption'}]}]]},{type,{3413,7},constraint,[{atom,{3413,7},is_subtype},[{var,{3413,7},'ReplyTag'},{type,{3413,19},term,[]}]]},{type,{3414,7},constraint,[{atom,{3414,7},is_subtype},[{var,{3414,7},'Reply'},{type,{3414,16},union,[{atom,{3414,16},yes},{atom,{3414,22},no},{atom,{3414,27},error_only},{atom,{3414,40},success_only}]}]]},{type,{3415,7},constraint,[{atom,{3415,7},is_subtype},[{var,{3415,7},'OtherOption'},{type,{3415,22},term,[]}]]},{type,{3416,7},constraint,[{atom,{3416,7},is_subtype},[{var,{3416,7},'ReqId'},{type,{3416,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,spawn_request_abandon,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3433}],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<65,98,97,110,100,111,110,32,97,32,112,114,101,118,105,111,117,115,108,121,32,105,115,115,117,101,100,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,97,32,114,101,113,117,101,115,116,32,105,100,101,110,116,105,102,105,101,114,32,112,114,101,118,105,111,117,115,108,121,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,114,101,113,117,101,115,116,47,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,40,41>>]}]},<<32,105,110,32,97,32,99,97,108,108,32,102,114,111,109,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,109,97,100,101,32,116,104,101,32,114,101,113,117,101,115,116,32,99,97,110,32,97,98,97,110,100,111,110,32,116,104,101,32,114,101,113,117,101,115,116,46>>]},{p,[],[<<65,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,99,97,110,32,111,110,108,121,32,98,101,32,115,117,99,99,101,115,115,102,117,108,108,121,32,97,98,97,110,100,111,110,101,100,32,117,110,116,105,108,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,104,97,115,32,99,111,109,112,108,101,116,101,100,46,32,87,104,101,110,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,115,117,99,99,101,115,115,102,117,108,108,121,32,97,98,97,110,100,111,110,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,119,105,108,108,32,110,111,116,32,98,101,32,101,102,102,101,99,116,101,100,32,98,121,32,102,117,116,117,114,101,32,100,105,114,101,99,116,32,101,102,102,101,99,116,115,32,111,102,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,116,115,101,108,102,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,119,105,108,108,32,110,111,116,32,114,101,99,101,105,118,101,32,97,32,115,112,97,119,110,32,114,101,112,108,121,32,109,101,115,115,97,103,101,46,32,84,104,101,32,114,101,113,117,101,115,116,32,105,115,32,104,111,119,101,118,101,114,32,110,111,116,32,119,105,116,104,100,114,97,119,110,44,32,115,111,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,98,101,32,99,114,101,97,116,101,100,32,100,117,101,32,116,111,32,116,104,101,32,114,101,113,117,101,115,116,46,32,73,102,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32,105,115,32,99,114,101,97,116,101,100,32,97,102,116,101,114,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,97,115,32,97,98,97,110,100,111,110,101,100,44,32,110,111,32,109,111,110,105,116,111,114,115,32,110,111,114,32,108,105,110,107,115,32,119,105,108,108,32,98,101,32,115,101,116,32,117,112,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<115,112,97,119,110,95,114,101,113,117,101,115,116,95,97,98,97,110,100,111,110,47,49>>]},<<32,100,117,101,32,116,111,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46,32,73,102,32,116,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,110,99,108,117,100,101,100,32,116,104,101,32>>,{code,[],[<<108,105,110,107>>]},<<32,111,112,116,105,111,110,44,32,116,104,101,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,100,117,101,32,116,111,32,116,104,105,115,32,114,101,113,117,101,115,116,32,119,105,108,108,32,98,101,32,115,101,110,116,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,102,114,111,109,32,105,116,115,32,112,97,114,101,110,116,32,119,105,116,104,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32>>,{code,[],[<<97,98,97,110,100,111,110,101,100>>]},<<32,119,104,101,110,32,105,116,32,105,115,32,100,101,116,101,99,116,101,100,32,116,104,97,116,32,116,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,115,117,99,99,101,101,100,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,100,117,101,32,116,111,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,97,98,97,110,100,111,110,101,100,32,109,97,121,32,99,111,109,109,117,110,105,99,97,116,101,32,119,105,116,104,32,105,116,115,32,112,97,114,101,110,116,32,97,115,32,97,110,121,32,111,116,104,101,114,32,112,114,111,99,101,115,115,46,32,73,116,32,105,115,32>>,{em,[],[<<111,110,108,121>>]},<<32,116,104,101,32,100,105,114,101,99,116,32,101,102,102,101,99,116,115,32,111,110,32,116,104,101,32,112,97,114,101,110,116,32,111,102,32,116,104,101,32,97,99,116,117,97,108,32,115,112,97,119,110,32,114,101,113,117,101,115,116,44,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,97,110,99,101,108,101,100,32,98,121,32,97,98,97,110,100,111,110,105,110,103,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,46>>]}]},{p,[],[<<82,101,116,117,114,110,32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,97,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,97,98,97,110,100,111,110,101,100,46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,119,97,115,32,97,98,97,110,100,111,110,101,100,46,32,84,104,101,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,114,101,113,117,101,115,116,32,105,100,101,110,116,105,102,105,101,114,32,100,105,100,32,110,111,116,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,97,110,32,111,117,116,115,116,97,110,100,105,110,103,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,105,115,115,117,101,100,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,101,105,116,104,101,114,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<82,101,113,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,112,114,101,118,105,111,117,108,115,121,32,109,97,100,101,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,84,104,101,32,115,112,97,119,110,32,111,112,101,114,97,116,105,111,110,32,104,97,115,32,99,111,109,112,108,101,116,101,100,32,97,110,100,32,97,32,115,112,97,119,110,32,114,101,112,108,121,32,104,97,115,32,97,108,114,101,97,100,121,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,117,110,108,101,115,115,32,116,104,101,32,115,112,97,119,110,32,114,101,112,108,121,32,119,97,115,32,100,105,115,97,98,108,101,100,32,105,110,32,116,104,101,32,114,101,113,117,101,115,116,46>>]}]},{li,[],[{p,[],[{code,[],[<<82,101,113,73,100>>]},<<32,100,111,101,115,32,110,111,116,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,97,32,115,112,97,119,110,32,114,101,113,117,101,115,116,32,116,104,97,116,32,104,97,115,32,98,101,101,110,32,109,97,100,101,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46>>]}]}]}]}]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,102,97,105,108,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,105,102,32>>,{code,[],[<<82,101,113,73,100>>]},<<32,105,115,32,110,111,116,32,97,32,114,101,102,101,114,101,110,99,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,48,56,56>>,signature => [{attribute,{3433,2},spec,{{spawn_request_abandon,1},[{type,{3433,28},'fun',[{type,{3433,28},product,[{ann_type,{3433,29},[{var,{3433,29},'ReqId'},{type,{3433,38},reference,[]}]}]},{type,{3433,54},boolean,[]}]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,split_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1959}],[<<115,112,108,105,116,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,98,105,110,97,114,105,101,115,32,116,104,97,116,32,97,114,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,112,108,105,116,116,105,110,103,32>>,{code,[],[<<66,105,110>>]},<<32,105,110,116,111,32,116,119,111,32,112,97,114,116,115,32,97,116,32,112,111,115,105,116,105,111,110,32>>,{code,[],[<<80,111,115>>]},<<46,32,84,104,105,115,32,105,115,32,110,111,116,32,97,32,100,101,115,116,114,117,99,116,105,118,101,32,111,112,101,114,97,116,105,111,110,46,32,65,102,116,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,44,32,116,104,101,114,101,32,97,114,101,32,116,104,114,101,101,32,98,105,110,97,114,105,101,115,32,97,108,116,111,103,101,116,104,101,114,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,66,32,61,32,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,34,48,49,50,51,52,53,54,55,56,57,34,41,46,10,60,60,34,48,49,50,51,52,53,54,55,56,57,34,62,62,10,62,32,98,121,116,101,95,115,105,122,101,40,66,41,46,10,49,48,10,62,32,123,66,49,44,32,66,50,125,32,61,32,115,112,108,105,116,95,98,105,110,97,114,121,40,66,44,51,41,46,10,123,60,60,34,48,49,50,34,62,62,44,60,60,34,51,52,53,54,55,56,57,34,62,62,125,10,62,32,98,121,116,101,95,115,105,122,101,40,66,49,41,46,10,51,10,62,32,98,121,116,101,95,115,105,122,101,40,66,50,41,46,10,55>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,53,52>>,signature => [{attribute,{1959,2},spec,{{split_binary,2},[{type,{1959,19},bounded_fun,[{type,{1959,19},'fun',[{type,{1959,19},product,[{var,{1959,20},'Bin'},{var,{1959,25},'Pos'}]},{type,{1959,33},tuple,[{type,{1959,34},binary,[]},{type,{1959,44},binary,[]}]}]},[{type,{1960,7},constraint,[{atom,{1960,7},is_subtype},[{var,{1960,7},'Bin'},{type,{1960,14},binary,[]}]]},{type,{1961,7},constraint,[{atom,{1961,7},is_subtype},[{var,{1961,7},'Pos'},{type,{1961,14},non_neg_integer,[]}]]}]]}]}}]}},{{function,start_timer,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1966}],[<<115,116,97,114,116,95,116,105,109,101,114,47,51>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,114,116,95,116,105,109,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,116,97,114,116,95,116,105,109,101,114,40,84,105,109,101,44,32,68,101,115,116,44,32,77,115,103,44,32,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,55,56>>,signature => [{attribute,{1966,2},spec,{{erlang,start_timer,3},[{type,{1966,25},bounded_fun,[{type,{1966,25},'fun',[{type,{1966,25},product,[{var,{1966,26},'Time'},{var,{1966,32},'Dest'},{var,{1966,38},'Msg'}]},{var,{1966,46},'TimerRef'}]},[{type,{1967,7},constraint,[{atom,{1967,7},is_subtype},[{var,{1967,7},'Time'},{type,{1967,15},non_neg_integer,[]}]]},{type,{1968,7},constraint,[{atom,{1968,7},is_subtype},[{var,{1968,7},'Dest'},{type,{1968,15},union,[{type,{1968,15},pid,[]},{type,{1968,23},atom,[]}]}]]},{type,{1969,7},constraint,[{atom,{1969,7},is_subtype},[{var,{1969,7},'Msg'},{type,{1969,14},term,[]}]]},{type,{1970,7},constraint,[{atom,{1970,7},is_subtype},[{var,{1970,7},'TimerRef'},{type,{1970,19},reference,[]}]]}]]}]}}]}},{{function,start_timer,4},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1976}],[<<115,116,97,114,116,95,116,105,109,101,114,47,52>>],#{<<101,110>> => [{p,[],[<<83,116,97,114,116,115,32,97,32,116,105,109,101,114,46,32,87,104,101,110,32,116,104,101,32,116,105,109,101,114,32,101,120,112,105,114,101,115,44,32,116,104,101,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,84,105,109,101,114,82,101,102,44,32,77,115,103,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<68,101,115,116>>]},<<46>>]},{p,[],[{code,[],[<<79,112,116,105,111,110>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,97,98,115,44,32,102,97,108,115,101,125>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46,32,73,116,32,109,101,97,110,115,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,32>>,{em,[],[<<114,101,108,97,116,105,118,101>>]},<<32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,97,98,115,44,32,116,114,117,101,125>>]}]},{dd,[],[{p,[],[<<65,98,115,111,108,117,116,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,46,32,84,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,110,32,97,98,115,111,108,117,116,101,32,69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,46>>]}]}]},{p,[],[<<77,111,114,101,32>>,{code,[],[<<79,112,116,105,111,110>>]},<<115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{p,[],[<<84,104,101,32,97,98,115,111,108,117,116,101,32,112,111,105,110,116,32,105,110,32,116,105,109,101,44,32,116,104,101,32,116,105,109,101,114,32,105,115,32,115,101,116,32,116,111,32,101,120,112,105,114,101,32,111,110,44,32,109,117,115,116,32,98,101,32,105,110,32,116,104,101,32,105,110,116,101,114,118,97,108,32>>,{code,[],[<<91,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111>>]},{code,[],[<<40,115,116,97,114,116,95,116,105,109,101,41,44,32,110,97,116,105,118,101,44,32,109,105,108,108,105,115,101,99,111,110,100,41,44,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111>>]},{code,[],[<<40,101,110,100,95,116,105,109,101,41,44,32,110,97,116,105,118,101,44,32,109,105,108,108,105,115,101,99,111,110,100,41,32,93>>]},<<46,32,73,102,32,97,32,114,101,108,97,116,105,118,101,32,116,105,109,101,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,110,101,103,97,116,105,118,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<44,32,105,116,32,109,117,115,116,32,98,101,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,111,102,32,97,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,111,110,32,116,104,101,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,84,104,105,115,32,112,114,111,99,101,115,115,32,104,97,115,32,101,105,116,104,101,114,32,116,101,114,109,105,110,97,116,101,100,32,111,114,32,110,111,116,46,32,73,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,110,32>>,{code,[],[<<97,116,111,109,40,41>>]},<<44,32,105,116,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,108,111,99,97,108,108,121,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,46,32,84,104,101,32,112,114,111,99,101,115,115,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32,116,104,101,32,110,97,109,101,32,105,115,32,108,111,111,107,101,100,32,117,112,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,116,105,109,101,114,32,101,120,112,105,114,97,116,105,111,110,46,32,78,111,32,101,114,114,111,114,32,105,115,32,114,101,116,117,114,110,101,100,32,105,102,32,116,104,101,32,110,97,109,101,32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<44,32,116,104,101,32,116,105,109,101,114,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,97,110,99,101,108,101,100,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,102,101,114,114,101,100,32,116,111,32,98,121,32,116,104,101,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,105,115,32,110,111,116,32,97,108,105,118,101,44,32,111,114,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,46,32,84,104,105,115,32,102,101,97,116,117,114,101,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,82,84,83,32,53,46,52,46,49,49,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,105,109,101,114,115,32,97,114,101,32,110,111,116,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,97,110,99,101,108,101,100,32,119,104,101,110,32>>,{code,[],[<<68,101,115,116>>]},<<32,105,115,32,97,110,32>>,{code,[],[<<97,116,111,109,40,41>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,101,110,100,95,97,102,116,101,114,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,101,110,100,95,97,102,116,101,114,47,52>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,97,110,99,101,108,95,116,105,109,101,114,47,50>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,97,100,95,116,105,109,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,97,100,95,116,105,109,101,114,47,50>>]}]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,100,111,32,110,111,116,32,115,97,116,105,115,102,121,32,116,104,101,32,114,101,113,117,105,114,101,109,101,110,116,115,32,115,112,101,99,105,102,105,101,100,32,104,101,114,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,49,56,57>>,signature => [{attribute,{1976,2},spec,{{erlang,start_timer,4},[{type,{1976,25},bounded_fun,[{type,{1976,25},'fun',[{type,{1976,25},product,[{var,{1976,26},'Time'},{var,{1976,32},'Dest'},{var,{1976,38},'Msg'},{var,{1976,43},'Options'}]},{var,{1976,55},'TimerRef'}]},[{type,{1977,7},constraint,[{atom,{1977,7},is_subtype},[{var,{1977,7},'Time'},{type,{1977,15},integer,[]}]]},{type,{1978,7},constraint,[{atom,{1978,7},is_subtype},[{var,{1978,7},'Dest'},{type,{1978,15},union,[{type,{1978,15},pid,[]},{type,{1978,23},atom,[]}]}]]},{type,{1979,7},constraint,[{atom,{1979,7},is_subtype},[{var,{1979,7},'Msg'},{type,{1979,14},term,[]}]]},{type,{1980,7},constraint,[{atom,{1980,7},is_subtype},[{var,{1980,7},'Options'},{type,{1980,18},list,[{var,{1980,19},'Option'}]}]]},{type,{1981,7},constraint,[{atom,{1981,7},is_subtype},[{var,{1981,7},'Abs'},{type,{1981,14},boolean,[]}]]},{type,{1982,7},constraint,[{atom,{1982,7},is_subtype},[{var,{1982,7},'Option'},{type,{1982,17},tuple,[{atom,{1982,18},abs},{var,{1982,23},'Abs'}]}]]},{type,{1983,7},constraint,[{atom,{1983,7},is_subtype},[{var,{1983,7},'TimerRef'},{type,{1983,19},reference,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},<<32,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,116,104,97,116,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,116,97,115,107,115,32,116,104,97,116,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,67,80,85,32,98,111,117,110,100,32,97,114,101,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,50,52,57>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2594,17},bounded_fun,[{type,{2594,17},'fun',[{type,{2594,17},product,[{atom,{2594,18},active_tasks}]},{type,{2594,35},list,[{var,{2594,36},'ActiveTasks'}]}]},[{type,{2595,7},constraint,[{atom,{2595,7},is_subtype},[{var,{2595,7},'ActiveTasks'},{type,{2595,22},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,104,101,114,101,32,101,97,99,104,32,101,108,101,109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,97,99,116,105,118,101,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,111,110,32,101,97,99,104,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,115,99,104,101,100,117,108,101,114,115,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,116,104,97,116,32,97,114,101,32,114,101,97,100,121,32,116,111,32,114,117,110,44,32,111,114,32,97,114,101,32,99,117,114,114,101,110,116,108,121,32,114,117,110,110,105,110,103,46,32,86,97,108,117,101,115,32,102,111,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,97,110,100,32,116,104,101,105,114,32,97,115,115,111,99,105,97,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,108,111,99,97,116,101,100,32,102,105,114,115,116,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,115,99,104,101,100,117,108,101,114,32,110,117,109,98,101,114,32,49,32,97,110,100,32,115,111,32,111,110,46,32,73,102,32,115,117,112,112,111,114,116,32,102,111,114,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,101,120,105,115,116,44,32,97,110,32,101,108,101,109,101,110,116,32,119,105,116,104,32,116,104,101,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,102,111,108,108,111,119,32,97,110,100,32,116,104,101,110,32,97,115,32,108,97,115,116,32,101,108,101,109,101,110,116,32,116,104,101,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,105,116,115,32,97,115,115,111,99,105,97,116,101,100,32,100,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,102,111,108,108,111,119,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,105,108,121,32,97,32,99,111,110,115,105,115,116,101,110,116,32,115,110,97,112,115,104,111,116,32,111,102,32,116,104,101,32,115,116,97,116,101,44,32,98,117,116,32,105,110,115,116,101,97,100,32,113,117,105,116,101,32,101,102,102,105,99,105,101,110,116,108,121,32,103,97,116,104,101,114,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<69,97,99,104,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,104,97,115,32,111,110,101,32,114,117,110,32,113,117,101,117,101,32,116,104,97,116,32,105,116,32,109,97,110,97,103,101,115,46,32,73,102,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,44,32,97,108,108,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,44,32,97,110,100,32,97,108,108,32,100,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,46,32,84,104,97,116,32,105,115,44,32,119,101,32,104,97,118,101,32,109,117,108,116,105,112,108,101,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,44,32,111,110,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,111,110,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,46,32,87,111,114,107,32,99,97,110,32>>,{em,[],[<<110,111,116>>]},<<32,109,105,103,114,97,116,101,32,98,101,116,119,101,101,110,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,114,117,110,32,113,117,101,117,101,115,46,32,79,110,108,121,32,119,111,114,107,32,105,110,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,99,97,110,32,109,105,103,114,97,116,101,32,116,111,32,111,116,104,101,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,46,32,84,104,105,115,32,104,97,115,32,116,111,32,98,101,32,116,97,107,101,110,32,105,110,116,111,32,97,99,99,111,117,110,116,32,119,104,101,110,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,50,54,52>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2596,3},bounded_fun,[{type,{2596,3},'fun',[{type,{2596,3},product,[{atom,{2596,4},active_tasks_all}]},{type,{2596,25},list,[{var,{2596,26},'ActiveTasks'}]}]},[{type,{2597,7},constraint,[{atom,{2597,7},is_subtype},[{var,{2597,7},'ActiveTasks'},{type,{2597,22},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,99,111,110,116,101,120,116,32,115,119,105,116,99,104,101,115,32,115,105,110,99,101,32,116,104,101,32,115,121,115,116,101,109,32,115,116,97,114,116,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,48,54>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2598,3},bounded_fun,[{type,{2598,3},'fun',[{type,{2598,3},product,[{atom,{2598,4},context_switches}]},{type,{2598,25},tuple,[{var,{2598,26},'ContextSwitches'},{integer,{2598,42},0}]}]},[{type,{2599,7},constraint,[{atom,{2599,7},is_subtype},[{var,{2599,7},'ContextSwitches'},{type,{2599,26},non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,120,97,99,116,32,114,101,100,117,99,116,105,111,110,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,101,120,97,99,116,95,114,101,100,117,99,116,105,111,110,115,41>>]},<<32,105,115,32,97,32,109,111,114,101,32,101,120,112,101,110,115,105,118,101,32,111,112,101,114,97,116,105,111,110,32,116,104,97,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,101,100,117,99,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,116,97,116,105,115,116,105,99,115,40,114,101,100,117,99,116,105,111,110,115,41>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,49,53>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2600,17},bounded_fun,[{type,{2600,17},'fun',[{type,{2600,17},product,[{atom,{2600,18},exact_reductions}]},{type,{2600,39},tuple,[{var,{2600,40},'Total_Exact_Reductions'},{var,{2601,40},'Exact_Reductions_Since_Last_Call'}]}]},[{type,{2602,7},constraint,[{atom,{2602,7},is_subtype},[{var,{2602,7},'Total_Exact_Reductions'},{type,{2602,33},non_neg_integer,[]}]]},{type,{2603,7},constraint,[{atom,{2603,7},is_subtype},[{var,{2603,7},'Exact_Reductions_Since_Last_Call'},{type,{2603,43},non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,116,97,116,105,115,116,105,99,115,40,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110,41,46,10,123,56,53,44,50,51,57,54,49,44,48,125>>]}]},{p,[],[<<84,104,105,115,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,105,110,118,97,108,105,100,32,102,111,114,32,115,111,109,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,51,48>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2604,17},bounded_fun,[{type,{2604,17},'fun',[{type,{2604,17},product,[{atom,{2604,18},garbage_collection}]},{type,{2604,41},tuple,[{var,{2604,42},'Number_of_GCs'},{var,{2604,57},'Words_Reclaimed'},{integer,{2604,74},0}]}]},[{type,{2605,7},constraint,[{atom,{2605,7},is_subtype},[{var,{2605,7},'Number_of_GCs'},{type,{2605,24},non_neg_integer,[]}]]},{type,{2606,7},constraint,[{atom,{2606,7},is_subtype},[{var,{2606,7},'Words_Reclaimed'},{type,{2606,26},non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<73,110,112,117,116>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,114,101,99,101,105,118,101,100,32,116,104,114,111,117,103,104,32,112,111,114,116,115,44,32,97,110,100,32>>,{code,[],[<<79,117,116,112,117,116>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,111,117,116,112,117,116,32,116,111,32,112,111,114,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,52,50>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2607,17},bounded_fun,[{type,{2607,17},'fun',[{type,{2607,17},product,[{atom,{2607,18},io}]},{type,{2607,25},tuple,[{type,{2607,26},tuple,[{atom,{2607,27},input},{var,{2607,34},'Input'}]},{type,{2607,42},tuple,[{atom,{2607,43},output},{var,{2607,51},'Output'}]}]}]},[{type,{2608,7},constraint,[{atom,{2608,7},is_subtype},[{var,{2608,7},'Input'},{type,{2608,16},non_neg_integer,[]}]]},{type,{2609,7},constraint,[{atom,{2609,7},is_subtype},[{var,{2609,7},'Output'},{type,{2609,17},non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<77,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,101,97,115,117,114,101,32,104,111,119,32,109,117,99,104,32,116,105,109,101,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,112,101,110,100,115,32,100,111,105,110,103,32,118,97,114,105,111,117,115,32,116,97,115,107,115,46,32,73,116,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,98,101,32,97,115,32,108,105,103,104,116,119,101,105,103,104,116,32,97,115,32,112,111,115,115,105,98,108,101,44,32,98,117,116,32,115,111,109,101,32,111,118,101,114,104,101,97,100,32,101,120,105,115,116,115,32,119,104,101,110,32,116,104,105,115,32,105,115,32,101,110,97,98,108,101,100,46,32,77,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,105,115,32,109,101,97,110,116,32,116,111,32,98,101,32,97,32,112,114,111,102,105,108,105,110,103,32,116,111,111,108,32,116,111,32,104,101,108,112,32,102,105,110,100,105,110,103,32,112,101,114,102,111,114,109,97,110,99,101,32,98,111,116,116,108,101,110,101,99,107,115,46,32,84,111,32>>,{code,[],[<<115,116,97,114,116>>]},<<47>>,{code,[],[<<115,116,111,112>>]},<<47>>,{code,[],[<<114,101,115,101,116>>]},<<32,109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,44,32,117,115,101,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>]}]},<<46>>]},{p,[],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41>>]},<<32,114,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,109,97,112,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,115,111,109,101,32,111,102,32,116,104,101,32,79,83,32,116,104,114,101,97,100,115,32,119,105,116,104,105,110,32,69,82,84,83,46,32,69,97,99,104,32,109,97,112,32,99,111,110,116,97,105,110,115,32>>,{code,[],[<<116,121,112,101>>]},<<32,97,110,100,32>>,{code,[],[<<105,100>>]},<<32,102,105,101,108,100,115,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,105,100,101,110,116,105,102,121,32,119,104,97,116,32,116,104,114,101,97,100,32,105,116,32,105,115,44,32,97,110,100,32,97,108,115,111,32,97,32,99,111,117,110,116,101,114,115,32,102,105,101,108,100,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,100,97,116,97,32,97,98,111,117,116,32,104,111,119,32,109,117,99,104,32,116,105,109,101,32,104,97,115,32,98,101,101,110,32,115,112,101,110,116,32,105,110,32,116,104,101,32,118,97,114,105,111,117,115,32,115,116,97,116,101,115,46>>]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41,46,10,91,35,123,99,111,117,110,116,101,114,115,32,61,62,32,35,123,97,117,120,32,61,62,32,49,56,57,57,49,56,50,57,49,52,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,99,104,101,99,107,95,105,111,32,61,62,32,50,54,48,53,56,54,51,54,48,50,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,109,117,108,97,116,111,114,32,61,62,32,52,53,55,51,49,56,56,48,52,54,51,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,103,99,32,61,62,32,49,53,49,50,50,48,54,57,49,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,111,116,104,101,114,32,61,62,32,53,52,50,49,51,51,56,52,53,54,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,111,114,116,32,61,62,32,50,50,49,54,51,49,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,115,108,101,101,112,32,61,62,32,53,49,53,48,50,57,52,49,48,48,125,44,10,32,32,32,105,100,32,61,62,32,49,44,10,32,32,32,116,121,112,101,32,61,62,32,115,99,104,101,100,117,108,101,114,125,124,46,46,46,93>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,117,110,105,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>]}]},<<46,32,83,111,44,32,116,111,32,99,111,110,118,101,114,116,32,105,116,32,116,111,32,109,105,108,108,105,115,101,99,111,110,100,115,44,32,121,111,117,32,99,97,110,32,100,111,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<108,105,115,116,115,58,109,97,112,40,10,32,32,102,117,110,40,35,123,32,99,111,117,110,116,101,114,115,32,58,61,32,67,110,116,32,125,32,61,32,77,41,32,45,62,10,32,32,32,32,32,32,32,32,32,32,77,115,67,110,116,32,61,32,109,97,112,115,58,109,97,112,40,102,117,110,40,95,75,44,32,80,101,114,102,67,111,117,110,116,41,32,45,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,40,80,101,114,102,67,111,117,110,116,44,32,112,101,114,102,95,99,111,117,110,116,101,114,44,32,49,48,48,48,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,101,110,100,44,32,67,110,116,41,44,10,32,32,32,32,32,32,32,32,32,77,35,123,32,99,111,117,110,116,101,114,115,32,58,61,32,77,115,67,110,116,32,125,10,32,32,101,110,100,44,32,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41,41,46>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,115,101,32,118,97,108,117,101,115,32,97,114,101,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,116,104,101,32,101,120,97,99,116,32,116,105,109,101,32,115,112,101,110,116,32,105,110,32,101,97,99,104,32,115,116,97,116,101,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,111,102,32,118,97,114,105,111,117,115,32,111,112,116,105,109,105,115,97,116,105,111,110,32,100,111,110,101,32,116,111,32,107,101,101,112,32,116,104,101,32,111,118,101,114,104,101,97,100,32,97,115,32,115,109,97,108,108,32,97,115,32,112,111,115,115,105,98,108,101,46>>]},{p,[],[{code,[],[<<77,83,65,99,99,95,84,104,114,101,97,100,95,84,121,112,101>>]},<<115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[<<84,104,101,32,109,97,105,110,32,101,120,101,99,117,116,105,111,110,32,116,104,114,101,97,100,115,32,116,104,97,116,32,100,111,32,109,111,115,116,32,111,102,32,116,104,101,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,83>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[<<84,104,101,32,116,104,114,101,97,100,115,32,102,111,114,32,108,111,110,103,32,114,117,110,110,105,110,103,32,99,112,117,32,105,110,116,101,110,115,105,118,101,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,83,68,99,112,117>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[<<84,104,101,32,116,104,114,101,97,100,115,32,102,111,114,32,108,111,110,103,32,114,117,110,110,105,110,103,32,73,47,79,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,83,68,105,111>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<97,115,121,110,99>>]}]},{dd,[],[<<65,115,121,110,99,32,116,104,114,101,97,100,115,32,97,114,101,32,117,115,101,100,32,98,121,32,118,97,114,105,111,117,115,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,115,32,40,109,97,105,110,108,121,32,116,104,101,32,102,105,108,101,32,100,114,105,118,101,114,115,41,32,100,111,32,111,102,102,108,111,97,100,32,110,111,110,45,67,80,85,32,105,110,116,101,110,115,105,118,101,32,119,111,114,107,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,97,115,121,110,99,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,65>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]},{dt,[],[{code,[],[<<97,117,120>>]}]},{dd,[],[<<84,97,107,101,115,32,99,97,114,101,32,111,102,32,97,110,121,32,119,111,114,107,32,116,104,97,116,32,105,115,32,110,111,116,32,115,112,101,99,105,102,105,99,97,108,108,121,32,97,115,115,105,103,110,101,100,32,116,111,32,97,32,115,99,104,101,100,117,108,101,114,46>>]},{dt,[],[{code,[],[<<112,111,108,108>>]}]},{dd,[],[<<68,111,101,115,32,116,104,101,32,73,79,32,112,111,108,108,105,110,103,32,102,111,114,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,73,79,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<101,114,108,32,43,73,79,116>>]},<<32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32>>,{code,[],[<<77,83,65,99,99,95,84,104,114,101,97,100,95,83,116,97,116,101>>]},<<115,32,97,114,101,32,97,118,97,105,108,97,98,108,101,46,32,65,108,108,32,115,116,97,116,101,115,32,97,114,101,32,101,120,99,108,117,115,105,118,101,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,97,32,116,104,114,101,97,100,32,99,97,110,110,111,116,32,98,101,32,105,110,32,116,119,111,32,115,116,97,116,101,115,32,97,116,32,111,110,99,101,46,32,83,111,44,32,105,102,32,121,111,117,32,97,100,100,32,116,104,101,32,110,117,109,98,101,114,115,32,111,102,32,97,108,108,32,99,111,117,110,116,101,114,115,32,105,110,32,97,32,116,104,114,101,97,100,44,32,121,111,117,32,103,101,116,32,116,104,101,32,116,111,116,97,108,32,114,117,110,116,105,109,101,32,102,111,114,32,116,104,97,116,32,116,104,114,101,97,100,46>>]},{dl,[],[{dt,[],[{code,[],[<<97,117,120>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,104,97,110,100,108,105,110,103,32,97,117,120,105,108,105,97,114,121,32,106,111,98,115,46>>]},{dt,[],[{code,[],[<<99,104,101,99,107,95,105,111>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,99,104,101,99,107,105,110,103,32,102,111,114,32,110,101,119,32,73,47,79,32,101,118,101,110,116,115,46>>]},{dt,[],[{code,[],[<<101,109,117,108,97,116,111,114>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,101,120,101,99,117,116,105,110,103,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,46>>]},{dt,[],[{code,[],[<<103,99>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,104,101,110,32,101,120,116,114,97,32,115,116,97,116,101,115,32,97,114,101,32,101,110,97,98,108,101,100,32,116,104,105,115,32,105,115,32,116,104,101,32,116,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,110,111,110,45,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,46>>]},{dt,[],[{code,[],[<<111,116,104,101,114>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,117,110,97,99,99,111,117,110,116,101,100,32,116,104,105,110,103,115,46>>]},{dt,[],[{code,[],[<<112,111,114,116>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,101,120,101,99,117,116,105,110,103,32,112,111,114,116,115,46>>]},{dt,[],[{code,[],[<<115,108,101,101,112>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,115,108,101,101,112,105,110,103,46>>]}]},{p,[],[<<77,111,114,101,32,102,105,110,101,45,103,114,97,105,110,101,100,32>>,{code,[],[<<77,83,65,99,99,95,84,104,114,101,97,100,95,83,116,97,116,101>>]},<<115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,116,104,114,111,117,103,104,32,99,111,110,102,105,103,117,114,101,32,40,115,117,99,104,32,97,115,32>>,{code,[],[<<46,47,99,111,110,102,105,103,117,114,101,32,45,45,119,105,116,104,45,109,105,99,114,111,115,116,97,116,101,45,97,99,99,111,117,110,116,105,110,103,61,101,120,116,114,97>>]},<<41,46,32,69,110,97,98,108,105,110,103,32,116,104,101,115,101,32,115,116,97,116,101,115,32,99,97,117,115,101,115,32,112,101,114,102,111,114,109,97,110,99,101,32,100,101,103,114,97,100,97,116,105,111,110,32,119,104,101,110,32,109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,105,115,32,116,117,114,110,101,100,32,111,102,102,32,97,110,100,32,105,110,99,114,101,97,115,101,115,32,116,104,101,32,111,118,101,114,104,101,97,100,32,119,104,101,110,32,105,116,32,105,115,32,116,117,114,110,101,100,32,111,110,46>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108,111,99>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,109,97,110,97,103,105,110,103,32,109,101,109,111,114,121,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,115,112,114,101,97,100,32,111,117,116,32,111,118,101,114,32,97,108,108,32,111,116,104,101,114,32,115,116,97,116,101,115,46>>]},{dt,[],[{code,[],[<<98,105,102>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,105,110,32,66,73,70,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<98,117,115,121,95,119,97,105,116>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,98,117,115,121,32,119,97,105,116,105,110,103,46,32,84,104,105,115,32,105,115,32,97,108,115,111,32,116,104,101,32,115,116,97,116,101,32,119,104,101,114,101,32,97,32,115,99,104,101,100,117,108,101,114,32,110,111,32,108,111,110,103,101,114,32,114,101,112,111,114,116,115,32,116,104,97,116,32,105,116,32,105,115,32,97,99,116,105,118,101,32,119,104,101,110,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]}]},<<46,32,83,111,44,32,105,102,32,121,111,117,32,97,100,100,32,97,108,108,32,111,116,104,101,114,32,115,116,97,116,101,115,32,98,117,116,32,116,104,105,115,32,97,110,100,32,115,108,101,101,112,44,32,97,110,100,32,116,104,101,110,32,100,105,118,105,100,101,32,116,104,97,116,32,98,121,32,97,108,108,32,116,105,109,101,32,105,110,32,116,104,101,32,116,104,114,101,97,100,44,32,121,111,117,32,115,104,111,117,108,100,32,103,101,116,32,115,111,109,101,116,104,105,110,103,32,118,101,114,121,32,115,105,109,105,108,97,114,32,116,111,32,116,104,101,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,102,114,97,99,116,105,111,110,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<111,116,104,101,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<101,116,115>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,101,120,101,99,117,116,105,110,103,32,69,84,83,32,66,73,70,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<103,99,95,102,117,108,108>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,100,111,105,110,103,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<103,99>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<110,105,102>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,105,110,32,78,73,70,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<115,101,110,100>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,115,101,110,100,105,110,103,32,109,101,115,115,97,103,101,115,32,40,112,114,111,99,101,115,115,101,115,32,111,110,108,121,41,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<101,109,117,108,97,116,111,114>>]},<<32,115,116,97,116,101,46>>]},{dt,[],[{code,[],[<<116,105,109,101,114,115>>]}]},{dd,[],[<<84,105,109,101,32,115,112,101,110,116,32,109,97,110,97,103,105,110,103,32,116,105,109,101,114,115,46,32,87,105,116,104,111,117,116,32,101,120,116,114,97,32,115,116,97,116,101,115,32,116,104,105,115,32,116,105,109,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<111,116,104,101,114>>]},<<32,115,116,97,116,101,46>>]}]},{p,[],[<<84,104,101,32,117,116,105,108,105,116,121,32,109,111,100,117,108,101,32>>,{a,[{href,<<114,117,110,116,105,109,101,95,116,111,111,108,115,58,109,115,97,99,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,115,97,99,99,40,51,41>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,111,114,101,32,101,97,115,105,108,121,32,97,110,97,108,121,115,101,32,116,104,101,115,101,32,115,116,97,116,105,115,116,105,99,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>]}]},<<32,105,115,32,116,117,114,110,101,100,32,111,102,102,46>>]},{p,[],[<<84,104,101,32,108,105,115,116,32,111,102,32,116,104,114,101,97,100,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,117,110,115,111,114,116,101,100,32,97,110,100,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,100,105,102,102,101,114,101,110,116,32,111,114,100,101,114,32,98,101,116,119,101,101,110,32,99,97,108,108,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,116,104,114,101,97,100,115,32,97,110,100,32,115,116,97,116,101,115,32,97,114,101,32,115,117,98,106,101,99,116,32,116,111,32,99,104,97,110,103,101,32,119,105,116,104,111,117,116,32,97,110,121,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,51,53,51>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2610,17},bounded_fun,[{type,{2610,17},'fun',[{type,{2610,17},product,[{atom,{2610,18},microstate_accounting}]},{type,{2610,44},union,[{type,{2610,44},list,[{var,{2610,45},'MSAcc_Thread'}]},{atom,{2610,61},undefined}]}]},[{type,{2611,7},constraint,[{atom,{2611,7},is_subtype},[{var,{2611,7},'MSAcc_Thread'},{type,{2611,23},map,[{type,{2611,31},map_field_exact,[{atom,{2611,26},type},{var,{2611,34},'MSAcc_Thread_Type'}]},{type,{2612,28},map_field_exact,[{atom,{2612,25},id},{var,{2612,31},'MSAcc_Thread_Id'}]},{type,{2613,34},map_field_exact,[{atom,{2613,25},counters},{var,{2613,37},'MSAcc_Counters'}]}]}]]},{type,{2614,7},constraint,[{atom,{2614,7},is_subtype},[{var,{2614,7},'MSAcc_Thread_Type'},{type,{2614,28},union,[{atom,{2614,28},async},{atom,{2614,36},aux},{atom,{2614,42},dirty_io_scheduler},{atom,{2615,28},dirty_cpu_scheduler},{atom,{2615,50},poll},{atom,{2615,57},scheduler}]}]]},{type,{2616,7},constraint,[{atom,{2616,7},is_subtype},[{var,{2616,7},'MSAcc_Thread_Id'},{type,{2616,26},non_neg_integer,[]}]]},{type,{2617,7},constraint,[{atom,{2617,7},is_subtype},[{var,{2617,7},'MSAcc_Counters'},{type,{2617,25},map,[{type,{2617,47},map_field_assoc,[{var,{2617,28},'MSAcc_Thread_State'},{type,{2617,50},non_neg_integer,[]}]}]}]]},{type,{2618,7},constraint,[{atom,{2618,7},is_subtype},[{var,{2618,7},'MSAcc_Thread_State'},{type,{2618,29},union,[{atom,{2618,29},alloc},{atom,{2618,37},aux},{atom,{2618,43},bif},{atom,{2618,49},busy_wait},{atom,{2618,61},check_io},{atom,{2619,29},emulator},{atom,{2619,40},ets},{atom,{2619,46},gc},{atom,{2619,51},gc_fullsweep},{atom,{2619,66},nif},{atom,{2620,29},other},{atom,{2620,37},port},{atom,{2620,44},send},{atom,{2620,51},sleep},{atom,{2620,59},timers}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,114,101,100,117,99,116,105,111,110,115,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,116,97,116,105,115,116,105,99,115,40,114,101,100,117,99,116,105,111,110,115,41,46,10,123,50,48,52,54,44,49,49,125>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,53,32,40,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,41,44,32,116,104,105,115,32,118,97,108,117,101,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,114,101,100,117,99,116,105,111,110,115,32,112,101,114,102,111,114,109,101,100,32,105,110,32,99,117,114,114,101,110,116,32,116,105,109,101,32,115,108,105,99,101,115,32,111,102,32,99,117,114,114,101,110,116,108,121,32,115,99,104,101,100,117,108,101,100,32,112,114,111,99,101,115,115,101,115,46,32,73,102,32,97,110,32,101,120,97,99,116,32,118,97,108,117,101,32,105,115,32,119,97,110,116,101,100,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,101,120,97,99,116,95,114,101,100,117,99,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,101,120,97,99,116,95,114,101,100,117,99,116,105,111,110,115,41>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,52,57,54>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2621,17},bounded_fun,[{type,{2621,17},'fun',[{type,{2621,17},product,[{atom,{2621,18},reductions}]},{type,{2621,33},tuple,[{var,{2621,34},'Total_Reductions'},{var,{2622,34},'Reductions_Since_Last_Call'}]}]},[{type,{2623,7},constraint,[{atom,{2623,7},is_subtype},[{var,{2623,7},'Total_Reductions'},{type,{2623,27},non_neg_integer,[]}]]},{type,{2624,7},constraint,[{atom,{2624,7},is_subtype},[{var,{2624,7},'Reductions_Since_Last_Call'},{type,{2624,37},non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,111,116,97,108,32,108,101,110,103,116,104,32,111,102,32,97,108,108,32,110,111,114,109,97,108,32,97,110,100,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,115,46,32,84,104,97,116,32,105,115,44,32,113,117,101,117,101,100,32,119,111,114,107,32,116,104,97,116,32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,67,80,85,32,98,111,117,110,100,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,99,111,110,115,105,115,116,101,110,116,32,115,110,97,112,115,104,111,116,32,111,102,32,116,104,101,32,115,116,97,116,101,44,32,98,117,116,32,116,104,105,115,32,111,112,101,114,97,116,105,111,110,32,105,115,32,109,117,99,104,32,109,111,114,101,32,101,120,112,101,110,115,105,118,101,32,99,111,109,112,97,114,101,100,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32,101,115,112,101,99,105,97,108,108,121,32,119,104,101,110,32,97,32,108,97,114,103,101,32,97,109,111,117,110,116,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,105,115,32,117,115,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,49,53>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2625,17},'fun',[{type,{2625,17},product,[{atom,{2625,18},run_queue}]},{type,{2625,32},non_neg_integer,[]}]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<32,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105,111,110,32,116,104,97,116,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,114,117,110,32,113,117,101,117,101,115,32,119,105,116,104,32,119,111,114,107,32,116,104,97,116,32,105,115,32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,67,80,85,32,98,111,117,110,100,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,51,49>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2626,17},bounded_fun,[{type,{2626,17},'fun',[{type,{2626,17},product,[{atom,{2626,18},run_queue_lengths}]},{type,{2626,40},list,[{var,{2626,41},'RunQueueLength'}]}]},[{type,{2627,7},constraint,[{atom,{2627,7},is_subtype},[{var,{2627,7},'RunQueueLength'},{type,{2627,25},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,119,104,101,114,101,32,101,97,99,104,32,101,108,101,109,101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,114,101,97,100,121,32,116,111,32,114,117,110,32,102,111,114,32,101,97,99,104,32,114,117,110,32,113,117,101,117,101,46,32,86,97,108,117,101,115,32,102,111,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,97,114,101,32,108,111,99,97,116,101,100,32,102,105,114,115,116,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,32,111,102,32,115,99,104,101,100,117,108,101,114,32,110,117,109,98,101,114,32,49,32,97,110,100,32,115,111,32,111,110,46,32,73,102,32,115,117,112,112,111,114,116,32,102,111,114,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,101,120,105,115,116,44,32,118,97,108,117,101,115,32,102,111,114,32,116,104,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,116,104,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,32,102,111,108,108,111,119,32,40,105,110,32,116,104,97,116,32,111,114,100,101,114,41,32,97,116,32,116,104,101,32,101,110,100,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,103,97,116,104,101,114,101,100,32,97,116,111,109,105,99,97,108,108,121,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,110,111,116,32,110,101,99,101,115,115,97,114,105,108,121,32,97,32,99,111,110,115,105,115,116,101,110,116,32,115,110,97,112,115,104,111,116,32,111,102,32,116,104,101,32,115,116,97,116,101,44,32,98,117,116,32,105,110,115,116,101,97,100,32,113,117,105,116,101,32,101,102,102,105,99,105,101,110,116,108,121,32,103,97,116,104,101,114,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<69,97,99,104,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,104,97,115,32,111,110,101,32,114,117,110,32,113,117,101,117,101,32,116,104,97,116,32,105,116,32,109,97,110,97,103,101,115,46,32,73,102,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,44,32,97,108,108,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,44,32,97,110,100,32,97,108,108,32,100,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,115,104,97,114,101,32,111,110,101,32,114,117,110,32,113,117,101,117,101,46,32,84,104,97,116,32,105,115,44,32,119,101,32,104,97,118,101,32,109,117,108,116,105,112,108,101,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,44,32,111,110,101,32,100,105,114,116,121,32,67,80,85,32,114,117,110,32,113,117,101,117,101,32,97,110,100,32,111,110,101,32,100,105,114,116,121,32,73,79,32,114,117,110,32,113,117,101,117,101,46,32,87,111,114,107,32,99,97,110,32>>,{em,[],[<<110,111,116>>]},<<32,109,105,103,114,97,116,101,32,98,101,116,119,101,101,110,32,116,104,101,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,114,117,110,32,113,117,101,117,101,115,46,32,79,110,108,121,32,119,111,114,107,32,105,110,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,32,99,97,110,32,109,105,103,114,97,116,101,32,116,111,32,111,116,104,101,114,32,110,111,114,109,97,108,32,114,117,110,32,113,117,101,117,101,115,46,32,84,104,105,115,32,104,97,115,32,116,111,32,98,101,32,116,97,107,101,110,32,105,110,116,111,32,97,99,99,111,117,110,116,32,119,104,101,110,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,116,111,116,97,108,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,52,54>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2628,17},bounded_fun,[{type,{2628,17},'fun',[{type,{2628,17},product,[{atom,{2628,18},run_queue_lengths_all}]},{type,{2628,44},list,[{var,{2628,45},'RunQueueLength'}]}]},[{type,{2629,7},constraint,[{atom,{2629,7},is_subtype},[{var,{2629,7},'RunQueueLength'},{type,{2629,25},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,114,117,110,116,105,109,101,44,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,46>>]},{p,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,102,111,114,32,97,108,108,32,116,104,114,101,97,100,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,97,110,100,32,99,97,110,32,116,104,101,114,101,102,111,114,101,32,98,101,32,103,114,101,97,116,101,114,32,116,104,97,110,32,116,104,101,32,119,97,108,108,32,99,108,111,99,107,32,116,105,109,101,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,118,97,108,117,101,32,109,105,103,104,116,32,119,114,97,112,32,100,117,101,32,116,111,32,108,105,109,105,116,97,116,105,111,110,115,32,105,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,112,114,111,118,105,100,101,100,32,98,121,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,116,104,97,116,32,105,115,32,117,115,101,100,46>>]}]},{p,[],[<<69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,115,116,97,116,105,115,116,105,99,115,40,114,117,110,116,105,109,101,41,46,10,123,49,54,57,48,44,49,54,50,48,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,53,56,57>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2630,17},bounded_fun,[{type,{2630,17},'fun',[{type,{2630,17},product,[{atom,{2630,18},runtime}]},{type,{2630,30},tuple,[{var,{2630,31},'Total_Run_Time'},{var,{2630,47},'Time_Since_Last_Call'}]}]},[{type,{2631,7},constraint,[{atom,{2631,7},is_subtype},[{var,{2631,7},'Total_Run_Time'},{type,{2631,25},non_neg_integer,[]}]]},{type,{2632,7},constraint,[{atom,{2632,7},is_subtype},[{var,{2632,7},'Time_Since_Last_Call'},{type,{2632,31},non_neg_integer,[]}]]}]]}]}}]}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,100,101,115,99,114,105,98,105,110,103,32,104,111,119,32,109,117,99,104,32,116,105,109,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,111,114,109,97,108>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,114,116,121,32,67,80,85>>]},<<32,115,99,104,101,100,117,108,101,114,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,104,97,118,101,32,98,101,101,110,32,98,117,115,121,46,32,84,104,105,115,32,118,97,108,117,101,32,105,115,32,110,111,114,109,97,108,108,121,32,97,32,98,101,116,116,101,114,32,105,110,100,105,99,97,116,111,114,32,111,102,32,104,111,119,32,109,117,99,104,32,108,111,97,100,32,97,110,32,69,114,108,97,110,103,32,110,111,100,101,32,105,115,32,117,110,100,101,114,32,105,110,115,116,101,97,100,32,111,102,32,108,111,111,107,105,110,103,32,97,116,32,116,104,101,32,67,80,85,32,117,116,105,108,105,122,97,116,105,111,110,32,112,114,111,118,105,100,101,100,32,98,121,32,116,111,111,108,115,32,115,117,99,104,32,97,115,32>>,{code,[],[<<116,111,112>>]},<<32,111,114,32>>,{code,[],[<<115,121,115,115,116,97,116>>]},<<46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,97,108,115,111,32,105,110,99,108,117,100,101,115,32,116,105,109,101,32,119,104,101,114,101,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,105,115,32,119,97,105,116,105,110,103,32,102,111,114,32,115,111,109,101,32,111,116,104,101,114,32,114,101,97,115,111,117,114,99,101,32,40,115,117,99,104,32,97,115,32,97,110,32,105,110,116,101,114,110,97,108,32,109,117,116,101,120,41,32,116,111,32,98,101,32,97,118,97,105,108,97,98,108,101,32,98,117,116,32,100,111,101,115,32,110,111,116,32,117,115,101,32,116,104,101,32,67,80,85,46,32,73,110,32,111,114,100,101,114,32,116,111,32,98,101,116,116,101,114,32,117,110,100,101,114,115,116,97,110,100,32,119,104,97,116,32,97,32,115,99,104,101,100,117,108,101,114,32,105,115,32,98,117,115,121,32,100,111,105,110,103,32,121,111,117,32,99,97,110,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103>>]},<<46>>]},{p,[],[<<84,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,97,32,98,117,115,121,32,115,99,104,101,100,117,108,101,114,32,105,115,32,119,104,101,110,32,105,116,32,105,115,32,110,111,116,32,105,100,108,101,32,97,110,100,32,110,111,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,119,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<98,117,115,121,32,119,97,105,116,105,110,103>>]},<<32,102,111,114,32,110,101,119,32,119,111,114,107,44,32,116,104,97,116,32,105,115,58>>]},{ul,[],[{li,[],[<<69,120,101,99,117,116,105,110,103,32,112,114,111,99,101,115,115,32,99,111,100,101>>]},{li,[],[<<69,120,101,99,117,116,105,110,103,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,111,114,32,78,73,70,32,99,111,100,101>>]},{li,[],[<<69,120,101,99,117,116,105,110,103,32,66,73,70,115,44,32,111,114,32,97,110,121,32,111,116,104,101,114,32,114,117,110,116,105,109,101,32,104,97,110,100,108,105,110,103>>]},{li,[],[<<71,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,110,103>>]},{li,[],[<<72,97,110,100,108,105,110,103,32,97,110,121,32,111,116,104,101,114,32,109,101,109,111,114,121,32,109,97,110,97,103,101,109,101,110,116>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,32,115,99,104,101,100,117,108,101,114,32,99,97,110,32,97,108,115,111,32,98,101,32,98,117,115,121,32,101,118,101,110,32,105,102,32,116,104,101,32,79,83,32,104,97,115,32,115,99,104,101,100,117,108,101,100,32,111,117,116,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,117,115,101,32,116,104,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<114,117,110,116,105,109,101,95,116,111,111,108,115,58,115,99,104,101,100,117,108,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114>>]}]},<<32,105,110,115,116,101,97,100,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,100,105,114,101,99,116,108,121,32,97,115,32,105,116,32,112,114,111,118,105,100,101,115,32,97,110,32,101,97,115,105,101,114,32,119,97,121,32,116,111,32,103,101,116,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,116,104,97,116,32,121,111,117,32,117,115,117,97,108,108,121,32,119,97,110,116,46>>]}]},{p,[],[<<73,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,110,97,98,108,101,100>>]},<<32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32,119,105,116,104,32>>,{code,[],[<<123,83,99,104,101,100,117,108,101,114,73,100,44,32,65,99,116,105,118,101,84,105,109,101,44,32,84,111,116,97,108,84,105,109,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<83,99,104,101,100,117,108,101,114,73,100>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,73,68,32,111,102,32,116,104,101,32,115,99,104,101,100,117,108,101,114,44,32>>,{code,[],[<<65,99,116,105,118,101,84,105,109,101>>]},<<32,105,115,32,116,104,101,32,100,117,114,97,116,105,111,110,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,104,97,115,32,98,101,101,110,32,98,117,115,121,44,32,97,110,100,32>>,{code,[],[<<84,111,116,97,108,84,105,109,101>>]},<<32,105,115,32,116,104,101,32,116,111,116,97,108,32,116,105,109,101,32,100,117,114,97,116,105,111,110,32,115,105,110,99,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]}]},<<32,97,99,116,105,118,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,99,32,115,99,104,101,100,117,108,101,114,46,32,84,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,116,117,114,110,101,100,32,105,115,32,117,110,100,101,102,105,110,101,100,32,97,110,100,32,99,97,110,32,98,101,32,115,117,98,106,101,99,116,32,116,111,32,99,104,97,110,103,101,32,98,101,116,119,101,101,110,32,114,101,108,101,97,115,101,115,44,32,79,83,115,44,32,97,110,100,32,115,121,115,116,101,109,32,114,101,115,116,97,114,116,115,46,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,116,111,32,99,97,108,99,117,108,97,116,101,32,114,101,108,97,116,105,118,101,32,118,97,108,117,101,115,32,102,111,114,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,46,32,84,104,101,32>>,{code,[],[<<65,99,116,105,118,101,84,105,109,101>>]},<<32,99,97,110,32,110,101,118,101,114,32,101,120,99,101,101,100,32>>,{code,[],[<<84,111,116,97,108,84,105,109,101>>]},<<46,32,84,104,101,32,108,105,115,116,32,111,102,32,115,99,104,101,100,117,108,101,114,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,117,110,115,111,114,116,101,100,32,97,110,100,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,100,105,102,102,101,114,101,110,116,32,111,114,100,101,114,32,98,101,116,119,101,101,110,32,99,97,108,108,115,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,115,97,98,108,101,100>>]},<<32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<84,104,101,32,97,99,116,105,118,97,116,105,111,110,32,116,105,109,101,32,99,97,110,32,100,105,102,102,101,114,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,98,101,116,119,101,101,110,32,115,99,104,101,100,117,108,101,114,115,46,32,67,117,114,114,101,110,116,108,121,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,99,116,105,118,97,116,101,100,32,97,116,32,115,121,115,116,101,109,32,115,116,97,114,116,32,119,104,105,108,101,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,99,116,105,118,97,116,101,100,32,115,111,109,101,32,116,105,109,101,32,97,102,116,101,114,32,116,104,101,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,102,117,110,99,116,105,111,110,97,108,105,116,121,32,105,115,32,101,110,97,98,108,101,100,46>>]},{p,[],[<<79,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,99,104,101,100,117,108,101,114,115,32,116,104,97,116,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,104,97,110,100,108,101,32,67,80,85,32,98,111,117,110,100,32,119,111,114,107,32,105,115,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,102,114,111,109,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46,32,73,102,32,121,111,117,32,97,108,115,111,32,119,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115>>]},<<44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,95,97,108,108,41>>]}]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<78,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,104,97,118,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<49,32,61,60,32,83,99,104,101,100,117,108,101,114,73,100,32,61,60,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46,32,68,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,104,97,118,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,32,60,32,83,99,104,101,100,117,108,101,114,73,100,32,61,60,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,104,97,110,100,108,101,32,115,112,101,99,105,102,105,99,32,116,121,112,101,115,32,111,102,32,106,111,98,115,46,32,69,118,101,114,121,32,106,111,98,32,105,115,32,97,115,115,105,103,110,101,100,32,116,111,32,97,32,115,112,101,99,105,102,105,99,32,115,99,104,101,100,117,108,101,114,32,116,121,112,101,46,32,74,111,98,115,32,99,97,110,32,109,105,103,114,97,116,101,32,98,101,116,119,101,101,110,32,100,105,102,102,101,114,101,110,116,32,115,99,104,101,100,117,108,101,114,115,32,111,102,32,116,104,101,32,115,97,109,101,32,116,121,112,101,44,32,98,117,116,32,110,101,118,101,114,32,98,101,116,119,101,101,110,32,115,99,104,101,100,117,108,101,114,115,32,111,102,32,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,46,32,84,104,105,115,32,102,97,99,116,32,104,97,115,32,116,111,32,98,101,32,116,97,107,101,110,32,117,110,100,101,114,32,99,111,110,115,105,100,101,114,97,116,105,111,110,32,119,104,101,110,32,101,118,97,108,117,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,114,101,116,117,114,110,101,100,46>>]}]},{p,[],[<<89,111,117,32,99,97,110,32,117,115,101,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,116,111,32,99,97,108,99,117,108,97,116,101,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,46,32,70,105,114,115,116,32,121,111,117,32,116,97,107,101,32,97,32,115,97,109,112,108,101,32,111,102,32,116,104,101,32,118,97,108,117,101,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]},<<46>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,44,32,116,114,117,101,41,46,10,102,97,108,115,101,10,62,32,84,115,48,32,61,32,108,105,115,116,115,58,115,111,114,116,40,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41,41,44,32,111,107,46,10,111,107>>]}]},{p,[],[<<83,111,109,101,32,116,105,109,101,32,108,97,116,101,114,32,116,104,101,32,117,115,101,114,32,116,97,107,101,115,32,97,110,111,116,104,101,114,32,115,110,97,112,115,104,111,116,32,97,110,100,32,99,97,108,99,117,108,97,116,101,115,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,112,101,114,32,115,99,104,101,100,117,108,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,84,115,49,32,61,32,108,105,115,116,115,58,115,111,114,116,40,101,114,108,97,110,103,58,115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41,41,44,32,111,107,46,10,111,107,10,62,32,108,105,115,116,115,58,109,97,112,40,102,117,110,40,123,123,73,44,32,65,48,44,32,84,48,125,44,32,123,73,44,32,65,49,44,32,84,49,125,125,41,32,45,62,10,9,123,73,44,32,40,65,49,32,45,32,65,48,41,47,40,84,49,32,45,32,84,48,41,125,32,101,110,100,44,32,108,105,115,116,115,58,122,105,112,40,84,115,48,44,84,115,49,41,41,46,10,91,123,49,44,48,46,57,55,52,51,52,55,52,55,51,48,49,55,55,53,52,56,125,44,10,32,123,50,44,48,46,57,55,52,52,56,52,51,55,56,50,55,53,49,52,52,52,125,44,10,32,123,51,44,48,46,57,57,57,53,57,48,50,51,54,49,54,54,57,48,52,53,125,44,10,32,123,52,44,48,46,57,55,51,56,48,49,50,53,57,54,53,55,50,49,54,49,125,44,10,32,123,53,44,48,46,57,55,49,55,57,53,54,54,54,55,48,49,56,49,48,51,125,44,10,32,123,54,44,48,46,57,55,51,57,50,51,53,56,52,54,52,50,48,55,52,49,125,44,10,32,123,55,44,48,46,57,55,51,50,51,55,48,51,51,48,55,55,56,55,54,125,44,10,32,123,56,44,48,46,57,55,52,49,50,57,55,50,57,51,50,52,56,54,53,54,125,93>>]}]},{p,[],[<<85,115,105,110,103,32,116,104,101,32,115,97,109,101,32,115,110,97,112,115,104,111,116,115,32,116,111,32,99,97,108,99,117,108,97,116,101,32,97,32,116,111,116,97,108,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<62,32,123,65,44,32,84,125,32,61,32,108,105,115,116,115,58,102,111,108,100,108,40,102,117,110,40,123,123,95,44,32,65,48,44,32,84,48,125,44,32,123,95,44,32,65,49,44,32,84,49,125,125,44,32,123,65,105,44,84,105,125,41,32,45,62,10,9,123,65,105,32,43,32,40,65,49,32,45,32,65,48,41,44,32,84,105,32,43,32,40,84,49,32,45,32,84,48,41,125,32,101,110,100,44,32,123,48,44,32,48,125,44,32,108,105,115,116,115,58,122,105,112,40,84,115,48,44,84,115,49,41,41,44,10,9,84,111,116,97,108,83,99,104,101,100,117,108,101,114,85,116,105,108,105,122,97,116,105,111,110,32,61,32,65,47,84,46,10,48,46,57,55,54,57,49,51,54,56,48,51,55,54,52,56,50,53>>]}]},{p,[],[<<84,111,116,97,108,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,119,105,108,108,32,101,113,117,97,108,32>>,{code,[],[<<49,46,48>>]},<<32,119,104,101,110,32,97,108,108,32,115,99,104,101,100,117,108,101,114,115,32,104,97,118,101,32,98,101,101,110,32,97,99,116,105,118,101,32,97,108,108,32,116,104,101,32,116,105,109,101,32,98,101,116,119,101,101,110,32,116,104,101,32,116,119,111,32,109,101,97,115,117,114,101,109,101,110,116,115,46>>]},{p,[],[<<65,110,111,116,104,101,114,32,40,112,114,111,98,97,98,108,121,32,109,111,114,101,41,32,117,115,101,102,117,108,32,118,97,108,117,101,32,105,115,32,116,111,32,99,97,108,99,117,108,97,116,101,32,116,111,116,97,108,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,119,101,105,103,104,116,101,100,32,97,103,97,105,110,115,116,32,109,97,120,105,109,117,109,32,97,109,111,117,110,116,32,111,102,32,97,118,97,105,108,97,98,108,101,32,67,80,85,32,116,105,109,101,58>>]},{pre,[],[{code,[],[<<62,32,87,101,105,103,104,116,101,100,83,99,104,101,100,117,108,101,114,85,116,105,108,105,122,97,116,105,111,110,32,61,32,40,84,111,116,97,108,83,99,104,101,100,117,108,101,114,85,116,105,108,105,122,97,116,105,111,110,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,42,32,40,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,43,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41,41,41,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,47,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101,41,46,10,48,46,57,55,54,57,49,51,54,56,48,51,55,54,52,56,50,53>>]}]},{p,[],[<<84,104,105,115,32,119,101,105,103,104,116,101,100,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,119,105,108,108,32,114,101,97,99,104,32>>,{code,[],[<<49,46,48>>]},<<32,119,104,101,110,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,99,116,105,118,101,32,116,104,101,32,115,97,109,101,32,97,109,111,117,110,116,32,111,102,32,116,105,109,101,32,97,115,32,109,97,120,105,109,117,109,32,97,118,97,105,108,97,98,108,101,32,67,80,85,32,116,105,109,101,46,32,73,102,32,109,111,114,101,32,115,99,104,101,100,117,108,101,114,115,32,101,120,105,115,116,32,116,104,97,110,32,97,118,97,105,108,97,98,108,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,105,115,32,118,97,108,117,101,32,109,97,121,32,98,101,32,103,114,101,97,116,101,114,32,116,104,97,110,32>>,{code,[],[<<49,46,48>>]},<<46>>]},{p,[],[<<65,115,32,111,102,32,69,82,84,83,32,118,101,114,115,105,111,110,32,57,46,48,44,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,119,105,108,108,32,97,115,32,100,101,102,97,117,108,116,32,104,97,118,101,32,109,111,114,101,32,115,99,104,101,100,117,108,101,114,115,32,116,104,97,110,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,84,104,105,115,32,100,117,101,32,116,111,32,116,104,101,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>]},<<32,105,115,32,98,121,32,100,101,102,97,117,108,116,32,100,105,115,97,98,108,101,100,46,32,84,111,32,101,110,97,98,108,101,32,105,116,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,44,32,116,114,117,101,41>>]}]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,54,48,55>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2633,17},bounded_fun,[{type,{2633,17},'fun',[{type,{2633,17},product,[{atom,{2633,18},scheduler_wall_time}]},{type,{2633,42},union,[{type,{2633,42},list,[{type,{2633,43},tuple,[{var,{2633,44},'SchedulerId'},{var,{2633,57},'ActiveTime'},{var,{2633,69},'TotalTime'}]}]},{atom,{2633,83},undefined}]}]},[{type,{2634,7},constraint,[{atom,{2634,7},is_subtype},[{var,{2634,7},'SchedulerId'},{type,{2634,22},pos_integer,[]}]]},{type,{2635,7},constraint,[{atom,{2635,7},is_subtype},[{var,{2635,7},'ActiveTime'},{type,{2635,22},non_neg_integer,[]}]]},{type,{2636,7},constraint,[{atom,{2636,7},is_subtype},[{var,{2636,7},'TotalTime'},{type,{2636,22},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66,48,49>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]}]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,97,108,115,111,32,105,110,99,108,117,100,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,108,108,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,46>>]},{p,[],[<<68,105,114,116,121,32,73,79,32,115,99,104,101,100,117,108,101,114,115,32,119,105,108,108,32,104,97,118,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},{code,[],[<<32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},{code,[],[<<32,60,32,83,99,104,101,100,117,108,101,114,73,100,32,61,60,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41,32,43,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41,32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,119,111,114,107,32,101,120,101,99,117,116,105,110,103,32,111,110,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,101,120,112,101,99,116,101,100,32,116,111,32,109,97,105,110,108,121,32,119,97,105,116,32,102,111,114,32,73,47,79,46,32,84,104,97,116,32,105,115,44,32,119,104,101,110,32,121,111,117,32,103,101,116,32,104,105,103,104,32,115,99,104,101,100,117,108,101,114,32,117,116,105,108,105,122,97,116,105,111,110,32,111,110,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,44,32,67,80,85,32,117,116,105,108,105,122,97,116,105,111,110,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,101,120,112,101,99,116,101,100,32,116,111,32,98,101,32,104,105,103,104,32,100,117,101,32,116,111,32,116,104,105,115,32,119,111,114,107,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,55,53,50>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2637,17},bounded_fun,[{type,{2637,17},'fun',[{type,{2637,17},product,[{atom,{2637,18},scheduler_wall_time_all}]},{type,{2637,46},union,[{type,{2637,46},list,[{type,{2637,47},tuple,[{var,{2637,48},'SchedulerId'},{var,{2637,61},'ActiveTime'},{var,{2637,73},'TotalTime'}]}]},{atom,{2637,87},undefined}]}]},[{type,{2638,7},constraint,[{atom,{2638,7},is_subtype},[{var,{2638,7},'SchedulerId'},{type,{2638,22},pos_integer,[]}]]},{type,{2639,7},constraint,[{atom,{2639,7},is_subtype},[{var,{2639,7},'ActiveTime'},{type,{2639,22},non_neg_integer,[]}]]},{type,{2640,7},constraint,[{atom,{2640,7},is_subtype},[{var,{2640,7},'TotalTime'},{type,{2640,22},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,55,56,48>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2641,3},bounded_fun,[{type,{2641,3},'fun',[{type,{2641,3},product,[{atom,{2641,4},total_active_tasks}]},{var,{2641,27},'ActiveTasks'}]},[{type,{2642,7},constraint,[{atom,{2642,7},is_subtype},[{var,{2642,7},'ActiveTasks'},{type,{2642,22},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,97,99,116,105,118,101,95,116,97,115,107,115,95,97,108,108,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,55,57,49>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2643,3},bounded_fun,[{type,{2643,3},'fun',[{type,{2643,3},product,[{atom,{2643,4},total_active_tasks_all}]},{var,{2643,31},'ActiveTasks'}]},[{type,{2644,7},constraint,[{atom,{2644,7},is_subtype},[{var,{2644,7},'ActiveTasks'},{type,{2644,22},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,48,50>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2645,17},bounded_fun,[{type,{2645,17},'fun',[{type,{2645,17},product,[{atom,{2645,18},total_run_queue_lengths}]},{var,{2645,46},'TotalRunQueueLengths'}]},[{type,{2646,7},constraint,[{atom,{2646,7},is_subtype},[{var,{2646,7},'TotalRunQueueLengths'},{type,{2646,31},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,51>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<108,105,115,116,115,58,115,117,109,40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,114,117,110,95,113,117,101,117,101,95,108,101,110,103,116,104,115,95,97,108,108,41>>]}]},{code,[],[<<41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,49,51>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2647,17},bounded_fun,[{type,{2647,17},'fun',[{type,{2647,17},product,[{atom,{2647,18},total_run_queue_lengths_all}]},{var,{2647,50},'TotalRunQueueLengths'}]},[{type,{2648,7},constraint,[{atom,{2648,7},is_subtype},[{var,{2648,7},'TotalRunQueueLengths'},{type,{2648,31},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,statistics,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2594}],[<<115,116,97,116,105,115,116,105,99,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,119,97,108,108,32,99,108,111,99,107,46,32>>,{code,[],[<<119,97,108,108,95,99,108,111,99,107>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,32,116,104,101,32,115,97,109,101,32,109,97,110,110,101,114,32,97,115,32>>,{code,[],[<<114,117,110,116,105,109,101>>]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,114,101,97,108,32,116,105,109,101,32,105,115,32,109,101,97,115,117,114,101,100,32,97,115,32,111,112,112,111,115,101,100,32,116,111,32,114,117,110,116,105,109,101,32,111,114,32,67,80,85,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,50,52>>,signature => [{attribute,{2594,2},spec,{{statistics,1},[{type,{2649,17},bounded_fun,[{type,{2649,17},'fun',[{type,{2649,17},product,[{atom,{2649,18},wall_clock}]},{type,{2649,33},tuple,[{var,{2649,34},'Total_Wallclock_Time'},{var,{2650,34},'Wallclock_Time_Since_Last_Call'}]}]},[{type,{2651,7},constraint,[{atom,{2651,7},is_subtype},[{var,{2651,7},'Total_Wallclock_Time'},{type,{2651,31},non_neg_integer,[]}]]},{type,{2652,7},constraint,[{atom,{2652,7},is_subtype},[{var,{2652,7},'Wallclock_Time_Since_Last_Call'},{type,{2652,41},non_neg_integer,[]}]]}]]}]}}]}},{{function,suspend_process,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2005}],[<<115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,49>>],#{<<101,110>> => [{p,[],[<<83,117,115,112,101,110,100,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,44,32,91,93,41>>]}]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,51,53>>,signature => [{attribute,{2005,2},spec,{{erlang,suspend_process,1},[{type,{2005,29},bounded_fun,[{type,{2005,29},'fun',[{type,{2005,29},product,[{var,{2005,30},'Suspendee'}]},{atom,{2005,44},true}]},[{type,{2006,7},constraint,[{atom,{2006,7},is_subtype},[{var,{2006,7},'Suspendee'},{type,{2006,20},pid,[]}]]}]]}]}}]}},{{function,suspend_process,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1989}],[<<115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>],#{<<101,110>> => [{p,[],[<<73,110,99,114,101,97,115,101,115,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,97,110,100,32,112,117,116,115,32,105,116,32,105,110,32,116,104,101,32,115,117,115,112,101,110,100,101,100,32,115,116,97,116,101,32,105,102,32,105,116,32,105,115,32,110,111,116,32,97,108,114,101,97,100,121,32,105,110,32,116,104,97,116,32,115,116,97,116,101,46,32,65,32,115,117,115,112,101,110,100,101,100,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,115,99,104,101,100,117,108,101,100,32,102,111,114,32,101,120,101,99,117,116,105,111,110,32,117,110,116,105,108,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,115,32,98,101,101,110,32,114,101,115,117,109,101,100,46>>]},{p,[],[<<65,32,112,114,111,99,101,115,115,32,99,97,110,32,98,101,32,115,117,115,112,101,110,100,101,100,32,98,121,32,109,117,108,116,105,112,108,101,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,99,97,110,32,98,101,32,115,117,115,112,101,110,100,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,98,121,32,97,32,115,105,110,103,108,101,32,112,114,111,99,101,115,115,46,32,65,32,115,117,115,112,101,110,100,101,100,32,112,114,111,99,101,115,115,32,100,111,101,115,32,110,111,116,32,108,101,97,118,101,32,116,104,101,32,115,117,115,112,101,110,100,101,100,32,115,116,97,116,101,32,117,110,116,105,108,32,105,116,115,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,114,101,97,99,104,101,115,32,122,101,114,111,46,32,84,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,102,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,100,101,99,114,101,97,115,101,100,32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,115,117,109,101,95,112,114,111,99,101,115,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,114,101,115,117,109,101,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]}]},<<32,105,115,32,99,97,108,108,101,100,32,98,121,32,116,104,101,32,115,97,109,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,99,97,108,108,101,100,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]},<<46,32,65,108,108,32,105,110,99,114,101,97,115,101,100,32,115,117,115,112,101,110,100,32,99,111,117,110,116,115,32,111,110,32,111,116,104,101,114,32,112,114,111,99,101,115,115,101,115,32,97,99,113,117,105,114,101,100,32,98,121,32,97,32,112,114,111,99,101,115,115,32,97,114,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,99,114,101,97,115,101,100,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,46>>]},{p,[],[<<79,112,116,105,111,110,115,32,40>>,{code,[],[<<79,112,116>>]},<<115,41,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]}]},{dd,[],[{p,[],[<<65,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,101,118,101,110,116,117,97,108,108,121,32,115,117,115,112,101,110,100,115,32,117,110,108,101,115,115,32,105,116,32,105,115,32,114,101,115,117,109,101,100,32,98,101,102,111,114,101,32,105,116,32,99,111,117,108,100,32,115,117,115,112,101,110,100,46,32,84,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<32,114,101,116,117,114,110,115,32,105,109,109,101,100,105,97,116,101,108,121,44,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,116,104,101,114,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,115,117,115,112,101,110,100,101,100,32,121,101,116,32,111,114,32,110,111,116,46,32,84,104,101,32,112,111,105,110,116,32,105,110,32,116,105,109,101,32,119,104,101,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,115,117,115,112,101,110,100,115,32,99,97,110,110,111,116,32,98,101,32,100,101,100,117,99,101,100,32,102,114,111,109,32,111,116,104,101,114,32,101,118,101,110,116,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,73,116,32,105,115,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32>>,{em,[],[<<101,118,101,110,116,117,97,108,108,121>>]},<<32,115,117,115,112,101,110,100,115,32,40,117,110,108,101,115,115,32,105,116,32,105,115,32,114,101,115,117,109,101,100,41,46,32,73,102,32,110,111,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,111,112,116,105,111,110,115,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<32,105,115,32,98,108,111,99,107,101,100,32,117,110,116,105,108,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,115,117,115,112,101,110,100,101,100,46>>]}]},{dt,[],[{code,[],[<<123,97,115,121,110,99,104,114,111,110,111,117,115,44,32,82,101,112,108,121,84,97,103,125>>]}]},{dd,[],[{p,[],[<<65,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32,87,104,101,110,32,116,104,101,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,104,97,115,32,98,101,101,110,32,112,114,111,99,101,115,115,101,100,44,32,97,32,114,101,112,108,121,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46,32,84,104,101,32,114,101,112,108,121,32,105,115,32,111,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,82,101,112,108,121,84,97,103,44,32,83,116,97,116,101,125>>]},<<32,119,104,101,114,101,32>>,{code,[],[<<83,116,97,116,101>>]},<<32,105,115,32,101,105,116,104,101,114,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,105,116,101,100>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,101,120,105,116,101,100,46>>]}]},{dt,[],[{code,[],[<<115,117,115,112,101,110,100,101,100>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,119,32,115,117,115,112,101,110,100,101,100,46>>]}]},{dt,[],[{code,[],[<<110,111,116,95,115,117,115,112,101,110,100,101,100>>]}]},{dd,[],[{p,[],[{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,115,117,115,112,101,110,100,101,100,46,32,84,104,105,115,32,99,97,110,32,111,110,108,121,32,104,97,112,112,101,110,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,105,115,115,117,101,100,32,116,104,105,115,32,114,101,113,117,101,115,116,44,32,104,97,118,101,32,99,97,108,108,101,100,32>>,{code,[],[<<114,101,115,117,109,101,95,112,114,111,99,101,115,115,40,83,117,115,112,101,110,100,101,101,41>>]},<<32,98,101,102,111,114,101,32,103,101,116,116,105,110,103,32,116,104,101,32,114,101,112,108,121,46>>]}]}]},{p,[],[<<65,112,97,114,116,32,102,114,111,109,32,116,104,101,32,114,101,112,108,121,32,109,101,115,115,97,103,101,44,32,116,104,101,32>>,{code,[],[<<123,97,115,121,110,99,104,114,111,110,111,117,115,44,32,82,101,112,108,121,84,97,103,125>>]},<<32,111,112,116,105,111,110,32,98,101,104,97,118,101,115,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,111,112,116,105,111,110,32,119,105,116,104,111,117,116,32,114,101,112,108,121,32,116,97,103,46>>]}]},{dt,[],[{code,[],[<<117,110,108,101,115,115,95,115,117,115,112,101,110,100,105,110,103>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,115,117,115,112,101,110,100,101,100,32,117,110,108,101,115,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,108,114,101,97,100,121,32,105,115,32,115,117,115,112,101,110,100,105,110,103,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<46,32,73,102,32>>,{code,[],[<<117,110,108,101,115,115,95,115,117,115,112,101,110,100,105,110,103>>]},<<32,105,115,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<44,32,97,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,105,115,32,115,101,110,116,32,117,110,108,101,115,115,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,108,114,101,97,100,121,32,105,115,32,115,117,115,112,101,110,100,105,110,103,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,111,114,32,105,102,32,97,32,115,117,115,112,101,110,100,32,114,101,113,117,101,115,116,32,97,108,114,101,97,100,121,32,104,97,115,32,98,101,101,110,32,115,101,110,116,32,97,110,100,32,105,115,32,105,110,32,116,114,97,110,115,105,116,46,32,73,102,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,108,114,101,97,100,121,32,105,115,32,115,117,115,112,101,110,100,105,110,103,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<44,32,111,114,32,105,102,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<97,115,121,110,99,104,114,111,110,111,117,115>>]},<<32,97,110,100,32,97,32,115,101,110,100,32,114,101,113,117,101,115,116,32,97,108,114,101,97,100,121,32,105,115,32,105,110,32,116,114,97,110,115,105,116,44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,97,110,100,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,114,101,109,97,105,110,115,32,117,110,99,104,97,110,103,101,100,46>>]}]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,115,112,101,110,100,32,99,111,117,110,116,32,111,110,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,105,110,99,114,101,97,115,101,100,44,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,66,73,70,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<89,111,117,32,99,97,110,32,101,97,115,105,108,121,32,99,114,101,97,116,101,32,100,101,97,100,108,111,99,107,115,32,105,102,32,112,114,111,99,101,115,115,101,115,32,115,117,115,112,101,110,100,115,32,101,97,99,104,32,111,116,104,101,114,32,40,100,105,114,101,99,116,108,121,32,111,114,32,105,110,32,99,105,114,99,108,101,115,41,46,32,73,110,32,69,82,84,83,32,118,101,114,115,105,111,110,115,32,112,114,105,111,114,32,116,111,32,69,82,84,83,32,118,101,114,115,105,111,110,32,49,48,46,48,44,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,112,114,101,118,101,110,116,101,100,32,115,117,99,104,32,100,101,97,100,108,111,99,107,115,44,32,98,117,116,32,116,104,105,115,32,112,114,101,118,101,110,116,105,111,110,32,104,97,115,32,110,111,119,32,98,101,101,110,32,114,101,109,111,118,101,100,32,100,117,101,32,116,111,32,112,101,114,102,111,114,109,97,110,99,101,32,114,101,97,115,111,110,115,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,116,104,101,32,115,97,109,101,32,112,114,111,99,101,115,115,32,97,115,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,115,117,115,112,101,110,100,95,112,114,111,99,101,115,115,47,50>>]},<<46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,105,115,32,110,111,116,32,97,108,105,118,101,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,114,101,115,105,100,101,115,32,111,110,32,97,110,111,116,104,101,114,32,110,111,100,101,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<79,112,116,76,105,115,116>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,32,111,102,32,118,97,108,105,100,32>>,{code,[],[<<79,112,116>>]},<<115,46>>]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[<<73,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<83,117,115,112,101,110,100,101,101>>]},<<32,104,97,115,32,98,101,101,110,32,115,117,115,112,101,110,100,101,100,32,109,111,114,101,32,116,105,109,101,115,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,116,104,97,110,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,105,110,116,101,114,110,97,108,32,100,97,116,97,32,115,116,114,117,99,116,117,114,101,115,46,32,84,104,101,32,115,121,115,116,101,109,32,108,105,109,105,116,32,105,115,32,103,114,101,97,116,101,114,32,116,104,97,110,32,50,44,48,48,48,44,48,48,48,44,48,48,48,32,115,117,115,112,101,110,100,115,32,97,110,100,32,119,105,108,108,32,110,101,118,101,114,32,98,101,32,108,111,119,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,56,53,48>>,signature => [{attribute,{1989,2},spec,{{erlang,suspend_process,2},[{type,{1989,29},bounded_fun,[{type,{1989,29},'fun',[{type,{1989,29},product,[{var,{1989,30},'Suspendee'},{var,{1989,41},'OptList'}]},{type,{1989,53},boolean,[]}]},[{type,{1990,7},constraint,[{atom,{1990,7},is_subtype},[{var,{1990,7},'Suspendee'},{type,{1990,20},pid,[]}]]},{type,{1991,7},constraint,[{atom,{1991,7},is_subtype},[{var,{1991,7},'OptList'},{type,{1991,18},list,[{var,{1991,19},'Opt'}]}]]},{type,{1992,7},constraint,[{atom,{1992,7},is_subtype},[{var,{1992,7},'Opt'},{type,{1992,14},union,[{atom,{1992,14},unless_suspending},{atom,{1992,34},asynchronous},{type,{1992,49},tuple,[{atom,{1992,50},asynchronous},{type,{1992,64},term,[]}]}]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,109,97,120,105,109,117,109,32,100,101,112,116,104,32,111,102,32,99,97,108,108,32,115,116,97,99,107,32,98,97,99,107,45,116,114,97,99,101,115,32,105,110,32,116,104,101,32,101,120,105,116,32,114,101,97,115,111,110,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<39,69,88,73,84,39>>]},<<32,116,117,112,108,101,115,46,32,84,104,101,32,102,108,97,103,32,97,108,115,111,32,108,105,109,105,116,115,32,116,104,101,32,115,116,97,99,107,116,114,97,99,101,32,100,101,112,116,104,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<112,114,111,99,101,115,115,95,105,110,102,111>>]},<<32,105,116,101,109,32>>,{code,[],[<<99,117,114,114,101,110,116,95,115,116,97,99,107,116,114,97,99,101,46>>]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,56,57,57,54>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2672,25},bounded_fun,[{type,{2672,25},'fun',[{type,{2672,25},product,[{atom,{2672,26},backtrace_depth},{var,{2672,43},'Depth'}]},{var,{2672,53},'OldDepth'}]},[{type,{2673,7},constraint,[{atom,{2673,7},is_subtype},[{var,{2673,7},'Depth'},{type,{2673,16},non_neg_integer,[]}]]},{type,{2674,7},constraint,[{atom,{2674,7},is_subtype},[{var,{2674,7},'OldDepth'},{type,{2674,19},non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<99,112,117,95,116,111,112,111,108,111,103,121>>}],[]},{li,[{name,<<105,110,102,111,95,108,105,115,116>>}],[]},{li,[{name,<<108,101,118,101,108,95,101,110,116,114,121>>}],[]},{li,[{name,<<108,101,118,101,108,95,116,97,103>>}],[]},{li,[{name,<<115,117,98,95,108,101,118,101,108>>}],[]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[{em,[],[<<84,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46>>]},<<32,73,110,115,116,101,97,100,32,111,102,32,117,115,105,110,103,32,116,104,105,115,32,97,114,103,117,109,101,110,116,44,32,117,115,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,114,101,109,111,118,101,100,44,32,97,32,102,105,110,97,108,32,67,80,85,32,116,111,112,111,108,111,103,121,32,116,111,32,117,115,101,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,46>>]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<46,32,84,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121,32,111,118,101,114,114,105,100,101,115,32,97,110,121,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121,46,32,66,121,32,112,97,115,115,105,110,103,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,97,115,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<44,32,116,104,101,32,115,121,115,116,101,109,32,114,101,118,101,114,116,115,32,116,111,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,46,32,84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,101,113,117,97,108,115,32,116,104,101,32,118,97,108,117,101,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,99,112,117,95,116,111,112,111,108,111,103,121,41>>]},<<32,98,101,102,111,114,101,32,116,104,101,32,99,104,97,110,103,101,32,119,97,115,32,109,97,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<84,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,117,115,101,100,32,119,104,101,110,32,98,105,110,100,105,110,103,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,73,102,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,97,108,114,101,97,100,121,32,98,111,117,110,100,32,119,104,101,110,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,99,104,97,110,103,101,100,44,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,115,101,110,116,32,97,32,114,101,113,117,101,115,116,32,116,111,32,114,101,98,105,110,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,110,101,119,32,67,80,85,32,116,111,112,111,108,111,103,121,46>>]},{p,[],[<<84,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,121,112,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,97,110,100,32,109,111,114,101,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,99,112,117,95,116,111,112,111,108,111,103,121,41>>]}]},<<32,97,115,32,119,101,108,108,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,48,48,56>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2675,25},bounded_fun,[{type,{2675,25},'fun',[{type,{2675,25},product,[{atom,{2675,26},cpu_topology},{var,{2675,40},'CpuTopology'}]},{var,{2675,56},'OldCpuTopology'}]},[{type,{2676,7},constraint,[{atom,{2676,7},is_subtype},[{var,{2676,7},'CpuTopology'},{user_type,{2676,22},cpu_topology,[]}]]},{type,{2677,7},constraint,[{atom,{2677,7},is_subtype},[{var,{2677,7},'OldCpuTopology'},{user_type,{2677,25},cpu_topology,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,82,97,110,103,101,32,105,115,32>>,{code,[],[<<49,32,60,61,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,32,60,61,32,78>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,99,104,97,110,103,101,32,105,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,104,97,110,103,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,49,50,32,115,99,104,101,100,117,108,101,114,115,32,97,110,100,32,54,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,111,110,108,105,110,101,44,32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>]},<<32,105,115,32,117,115,101,100,32,116,111,32,115,101,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,116,111,32,54,44,32,116,104,101,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,99,114,101,97,115,101,100,32,98,121,32,104,97,108,102,32,97,115,32,119,101,108,108,44,32,100,111,119,110,32,116,111,32,51,46,32,83,105,109,105,108,97,114,108,121,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,110,99,114,101,97,115,101,115,32,112,114,111,112,111,114,116,105,111,110,97,108,108,121,32,116,111,32,105,110,99,114,101,97,115,101,115,32,105,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,48,53,54>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2678,25},bounded_fun,[{type,{2678,25},'fun',[{type,{2678,25},product,[{atom,{2678,26},dirty_cpu_schedulers_online},{var,{2678,55},'DirtyCPUSchedulersOnline'}]},{var,{2679,33},'OldDirtyCPUSchedulersOnline'}]},[{type,{2680,7},constraint,[{atom,{2680,7},is_subtype},[{var,{2680,7},'DirtyCPUSchedulersOnline'},{type,{2680,35},pos_integer,[]}]]},{type,{2681,7},constraint,[{atom,{2681,7},is_subtype},[{var,{2681,7},'OldDirtyCPUSchedulersOnline'},{type,{2681,38},pos_integer,[]}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,115,121,115,116,101,109,32,102,108,97,103,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<46,32>>,{code,[],[<<65,108,108,111,99>>]},<<32,105,115,32,116,104,101,32,97,108,108,111,99,97,116,111,114,32,116,111,32,97,102,102,101,99,116,44,32,102,111,114,32,101,120,97,109,112,108,101,32>>,{code,[],[<<98,105,110,97,114,121,95,97,108,108,111,99>>]},<<46,32>>,{code,[],[<<70>>]},<<32,105,115,32,116,104,101,32,102,108,97,103,32,116,111,32,99,104,97,110,103,101,32,97,110,100,32>>,{code,[],[<<86>>]},<<32,105,115,32,116,104,101,32,110,101,119,32,118,97,108,117,101,46>>]},{p,[],[<<79,110,108,121,32,97,32,115,117,98,115,101,116,32,111,102,32,97,108,108,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99>>]},<<32,102,108,97,103,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,114,117,110,32,116,105,109,101,46,32,84,104,105,115,32,115,117,98,115,101,116,32,105,115,32,99,117,114,114,101,110,116,108,121,32,111,110,108,121,32,116,104,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99,35,77,95,115,98,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<115,98,99,116>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,116,104,101,32,102,108,97,103,32,119,97,115,32,115,101,116,32,111,114,32>>,{code,[],[<<110,111,116,115,117,112>>]},<<32,105,102,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,48,56,53>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2682,25},bounded_fun,[{type,{2682,25},'fun',[{type,{2682,25},product,[{atom,{2682,26},erts_alloc},{type,{2682,38},tuple,[{var,{2682,39},'Alloc'},{var,{2682,46},'F'},{var,{2682,49},'V'}]}]},{type,{2682,56},union,[{atom,{2682,56},ok},{atom,{2682,61},notsup}]}]},[{type,{2683,7},constraint,[{atom,{2683,7},is_subtype},[{var,{2683,7},'Alloc'},{type,{2683,16},atom,[]}]]},{type,{2684,7},constraint,[{atom,{2684,7},is_subtype},[{var,{2684,7},'F'},{type,{2684,12},atom,[]}]]},{type,{2685,7},constraint,[{atom,{2685,7},is_subtype},[{var,{2685,7},'V'},{type,{2685,12},integer,[]}]]}]]}]}}],since => <<79,84,80,32,50,48,46,50,46,51>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,115,121,115,116,101,109,32,102,108,97,103,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<46,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,105,115,32,97,32,110,111,110,45,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,32,105,110,100,105,99,97,116,105,110,103,32,104,111,119,32,109,97,110,121,32,116,105,109,101,115,32,103,101,110,101,114,97,116,105,111,110,97,108,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,32,99,97,110,32,98,101,32,100,111,110,101,32,119,105,116,104,111,117,116,32,102,111,114,99,105,110,103,32,97,32,102,117,108,108,115,119,101,101,112,32,99,111,108,108,101,99,116,105,111,110,46,32,84,104,101,32,118,97,108,117,101,32,97,112,112,108,105,101,115,32,116,111,32,110,101,119,32,112,114,111,99,101,115,115,101,115,44,32,119,104,105,108,101,32,112,114,111,99,101,115,115,101,115,32,97,108,114,101,97,100,121,32,114,117,110,110,105,110,103,32,97,114,101,32,110,111,116,32,97,102,102,101,99,116,101,100,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<73,110,32,108,111,119,45,109,101,109,111,114,121,32,115,121,115,116,101,109,115,32,40,101,115,112,101,99,105,97,108,108,121,32,119,105,116,104,111,117,116,32,118,105,114,116,117,97,108,32,109,101,109,111,114,121,41,44,32,115,101,116,116,105,110,103,32,116,104,101,32,118,97,108,117,101,32,116,111,32>>,{code,[],[<<48>>]},<<32,99,97,110,32,104,101,108,112,32,116,111,32,99,111,110,115,101,114,118,101,32,109,101,109,111,114,121,46>>]},{p,[],[<<84,104,105,115,32,118,97,108,117,101,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,116,104,114,111,117,103,104,32,40,79,83,41,32,101,110,118,105,114,111,110,109,101,110,116,32,118,97,114,105,97,98,108,101,32>>,{code,[],[<<69,82,76,95,70,85,76,76,83,87,69,69,80,95,65,70,84,69,82>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,48,50>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2686,25},bounded_fun,[{type,{2686,25},'fun',[{type,{2686,25},product,[{atom,{2686,26},fullsweep_after},{var,{2686,43},'Number'}]},{var,{2686,54},'OldNumber'}]},[{type,{2687,7},constraint,[{atom,{2687,7},is_subtype},[{var,{2687,7},'Number'},{type,{2687,17},non_neg_integer,[]}]]},{type,{2688,7},constraint,[{atom,{2688,7},is_subtype},[{var,{2688,7},'OldNumber'},{type,{2688,20},non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<84,117,114,110,115,32,111,110,47,111,102,102,32,109,105,99,114,111,115,116,97,116,101,32,97,99,99,111,117,110,116,105,110,103,32,109,101,97,115,117,114,101,109,101,110,116,115,46,32,87,104,101,110,32,112,97,115,115,105,110,103,32,114,101,115,101,116,44,32,97,108,108,32,99,111,117,110,116,101,114,115,32,97,114,101,32,114,101,115,101,116,32,116,111,32,48,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,109,105,99,114,111,115,116,97,116,101,95,97,99,99,111,117,110,116,105,110,103,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,50,49>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2689,25},bounded_fun,[{type,{2689,25},'fun',[{type,{2689,25},product,[{atom,{2689,26},microstate_accounting},{var,{2689,49},'Action'}]},{var,{2689,60},'OldState'}]},[{type,{2690,7},constraint,[{atom,{2690,7},is_subtype},[{var,{2690,7},'Action'},{type,{2690,17},union,[{atom,{2690,17},true},{atom,{2690,24},false},{atom,{2690,32},reset}]}]]},{type,{2691,7},constraint,[{atom,{2691,7},is_subtype},[{var,{2691,7},'OldState'},{type,{2691,19},union,[{atom,{2691,19},true},{atom,{2691,26},false}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,46,32,84,104,101,32,115,105,122,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,119,111,114,100,115,46,32,84,104,101,32,110,101,119,32>>,{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]},<<32,101,102,102,101,99,116,115,32,111,110,108,121,32,112,114,111,99,101,115,115,101,115,32,115,112,97,119,110,101,100,32,97,102,116,101,114,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32>>,{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]},<<32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32>>,{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,112,114,111,99,101,115,115,101,115,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,52>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,51,53>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2692,25},bounded_fun,[{type,{2692,25},'fun',[{type,{2692,25},product,[{atom,{2692,26},min_heap_size},{var,{2692,41},'MinHeapSize'}]},{var,{2692,57},'OldMinHeapSize'}]},[{type,{2693,7},constraint,[{atom,{2693,7},is_subtype},[{var,{2693,7},'MinHeapSize'},{type,{2693,22},non_neg_integer,[]}]]},{type,{2694,7},constraint,[{atom,{2694,7},is_subtype},[{var,{2694,7},'OldMinHeapSize'},{type,{2694,25},non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,46,32,84,104,101,32,115,105,122,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,119,111,114,100,115,46,32,84,104,101,32,110,101,119,32>>,{code,[],[<<109,105,110,95,98,105,110,95,118,104,104,101,97,112,95,115,105,122,101>>]},<<32,101,102,102,101,99,116,115,32,111,110,108,121,32,112,114,111,99,101,115,115,101,115,32,115,112,97,119,110,101,100,32,97,102,116,101,114,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32>>,{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]},<<32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32>>,{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,112,114,111,99,101,115,115,101,115,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,50,44,51,44,52>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,53,48>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2695,25},bounded_fun,[{type,{2695,25},'fun',[{type,{2695,25},product,[{atom,{2695,26},min_bin_vheap_size},{var,{2695,46},'MinBinVHeapSize'}]},{var,{2696,33},'OldMinBinVHeapSize'}]},[{type,{2697,7},constraint,[{atom,{2697,7},is_subtype},[{var,{2697,7},'MinBinVHeapSize'},{type,{2697,26},non_neg_integer,[]}]]},{type,{2698,7},constraint,[{atom,{2698,7},is_subtype},[{var,{2698,7},'OldMinBinVHeapSize'},{type,{2698,29},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,51,66,48,52>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,115,101,116,116,105,110,103,115,32,102,111,114,32,112,114,111,99,101,115,115,101,115,46,32,84,104,101,32,115,105,122,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,119,111,114,100,115,46,32,84,104,101,32,110,101,119,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,101,102,102,101,99,116,115,32,111,110,108,121,32,112,114,111,99,101,115,115,101,115,32,115,112,97,119,110,101,100,32,101,102,116,101,114,32,116,104,101,32,99,104,97,110,103,101,32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,112,114,111,99,101,115,115,101,115,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,50,44,51,44,52>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,47,50>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,54,55>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2699,25},bounded_fun,[{type,{2699,25},'fun',[{type,{2699,25},product,[{atom,{2699,26},max_heap_size},{var,{2699,41},'MaxHeapSize'}]},{var,{2699,57},'OldMaxHeapSize'}]},[{type,{2700,7},constraint,[{atom,{2700,7},is_subtype},[{var,{2700,7},'MaxHeapSize'},{user_type,{2700,22},max_heap_size,[]}]]},{type,{2701,7},constraint,[{atom,{2701,7},is_subtype},[{var,{2701,7},'OldMaxHeapSize'},{user_type,{2701,25},max_heap_size,[]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,101,110,97,98,108,101,100,44,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,105,115,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,77,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,99,97,110,32,98,101,32,98,108,111,99,107,101,100,32,105,110,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,46,32,69,105,116,104,101,114,32,97,108,108,32,115,99,104,101,100,117,108,101,114,115,32,98,117,116,32,111,110,101,32,105,115,32,98,108,111,99,107,101,100,44,32,111,114,32,97,108,108,32>>,{em,[],[<<110,111,114,109,97,108>>]},<<32,115,99,104,101,100,117,108,101,114,115,32,98,117,116,32,111,110,101,32,105,115,32,98,108,111,99,107,101,100,46,32,87,104,101,110,32,111,110,108,121,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,108,111,99,107,101,100,44,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,102,114,101,101,32,116,111,32,99,111,110,116,105,110,117,101,32,116,111,32,115,99,104,101,100,117,108,101,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,98,108,111,99,107>>]},<<44,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,111,110,101,32,97,110,100,32,111,110,108,121,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,119,105,108,108,32,101,120,101,99,117,116,101,46,32,73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,117,110,98,108,111,99,107>>]},<<32,97,110,100,32,110,111,32,111,110,101,32,101,108,115,101,32,98,108,111,99,107,115,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,44,32,97,110,100,32,116,104,105,115,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,111,110,108,121,32,111,110,99,101,44,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,117,110,98,108,111,99,107,101,100,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,98,108,111,99,107,95,110,111,114,109,97,108>>]},<<44,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,111,110,101,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,119,105,108,108,32,101,120,101,99,117,116,101,44,32,98,117,116,32,109,117,108,116,105,112,108,101,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,99,97,110,32,101,120,101,99,117,116,101,46,32,73,102,32>>,{code,[],[<<66,108,111,99,107,83,116,97,116,101,32,61,58,61,32,117,110,98,108,111,99,107,95,110,111,114,109,97,108>>]},<<32,97,110,100,32,110,111,32,111,110,101,32,101,108,115,101,32,98,108,111,99,107,115,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,44,32,97,110,100,32,116,104,105,115,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,111,110,108,121,32,111,110,99,101,44,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,117,110,98,108,111,99,107,101,100,46>>]},{p,[],[<<79,110,101,32,112,114,111,99,101,115,115,32,99,97,110,32,98,108,111,99,107,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,46,32,73,102,32,97,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,44,32,105,116,32,109,117,115,116,32,117,110,98,108,111,99,107,32,101,120,97,99,116,108,121,32,97,115,32,109,97,110,121,32,116,105,109,101,115,32,97,115,32,105,116,32,104,97,115,32,98,108,111,99,107,101,100,32,98,101,102,111,114,101,32,105,116,32,104,97,115,32,114,101,108,101,97,115,101,100,32,105,116,115,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,98,108,111,99,107,46,32,73,102,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,111,114,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,101,120,105,116,115,44,32,105,116,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,108,101,97,115,101,115,32,105,116,115,32,98,108,111,99,107,105,110,103,32,111,102,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,97,114,101,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<44,32>>,{code,[],[<<98,108,111,99,107,101,100>>]},<<44,32>>,{code,[],[<<98,108,111,99,107,101,100,95,110,111,114,109,97,108>>]},<<44,32,111,114,32>>,{code,[],[<<101,110,97,98,108,101,100>>]},<<46,32,84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,100,101,115,99,114,105,98,101,115,32,116,104,101,32,115,116,97,116,101,32,106,117,115,116,32,97,102,116,101,114,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]},<<32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<66,108,111,99,107,105,110,103,32,111,102,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,110,111,114,109,97,108,108,121,32,110,111,116,32,110,101,101,100,101,100,46,32,73,102,32,121,111,117,32,102,101,101,108,32,116,104,97,116,32,121,111,117,32,110,101,101,100,32,116,111,32,117,115,101,32,116,104,101,115,101,32,102,101,97,116,117,114,101,115,44,32,99,111,110,115,105,100,101,114,32,105,116,32,97,32,102,101,119,32,109,111,114,101,32,116,105,109,101,115,32,97,103,97,105,110,46,32,66,108,111,99,107,105,110,103,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,97,115,32,97,32,108,97,115,116,32,114,101,115,111,114,116,44,32,97,115,32,105,116,32,105,115,32,109,111,115,116,32,108,105,107,101,108,121,32,97,32>>,{em,[],[<<118,101,114,121,32,105,110,101,102,102,105,99,105,101,110,116>>]},<<32,119,97,121,32,116,111,32,115,111,108,118,101,32,116,104,101,32,112,114,111,98,108,101,109,46>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,49,56,53>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2702,25},bounded_fun,[{type,{2702,25},'fun',[{type,{2702,25},product,[{atom,{2702,26},multi_scheduling},{var,{2702,44},'BlockState'}]},{var,{2702,59},'OldBlockState'}]},[{type,{2703,7},constraint,[{atom,{2703,7},is_subtype},[{var,{2703,7},'BlockState'},{type,{2703,21},union,[{atom,{2703,21},block},{atom,{2703,29},unblock},{atom,{2703,39},block_normal},{atom,{2703,54},unblock_normal}]}]]},{type,{2704,7},constraint,[{atom,{2704,7},is_subtype},[{var,{2704,7},'OldBlockState'},{type,{2704,24},union,[{atom,{2704,24},blocked},{atom,{2704,34},disabled},{atom,{2704,45},enabled}]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>}],[]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[{em,[],[<<84,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46>>]},<<32,73,110,115,116,101,97,100,32,111,102,32,117,115,105,110,103,32,116,104,105,115,32,97,114,103,117,109,101,110,116,44,32,117,115,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,87,104,101,110,32,116,104,105,115,32,97,114,103,117,109,101,110,116,32,105,115,32,114,101,109,111,118,101,100,44,32,97,32,102,105,110,97,108,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,32,116,121,112,101,32,116,111,32,117,115,101,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,46>>]}]},{p,[],[<<67,111,110,116,114,111,108,115,32,105,102,32,97,110,100,32,104,111,119,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,111,117,110,100,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]},{p,[],[<<87,104,101,110,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101,44,32,72,111,119,41>>]},<<32,105,115,32,99,97,108,108,101,100,44,32,97,110,32,97,115,121,110,99,104,114,111,110,111,117,115,32,115,105,103,110,97,108,32,105,115,32,115,101,110,116,32,116,111,32,97,108,108,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,44,32,99,97,117,115,105,110,103,32,116,104,101,109,32,116,111,32,116,114,121,32,116,111,32,98,105,110,100,32,111,114,32,117,110,98,105,110,100,32,97,115,32,114,101,113,117,101,115,116,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,97,32,115,99,104,101,100,117,108,101,114,32,102,97,105,108,115,32,116,111,32,98,105,110,100,44,32,116,104,105,115,32,105,115,32,111,102,116,101,110,32,115,105,108,101,110,116,108,121,32,105,103,110,111,114,101,100,44,32,97,115,32,105,116,32,105,115,32,110,111,116,32,97,108,119,97,121,115,32,112,111,115,115,105,98,108,101,32,116,111,32,118,101,114,105,102,121,32,118,97,108,105,100,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,115,46,32,73,102,32,97,110,32,101,114,114,111,114,32,105,115,32,114,101,112,111,114,116,101,100,44,32,97,110,32,101,114,114,111,114,32,101,118,101,110,116,32,105,115,32,108,111,103,103,101,100,46,32,84,111,32,118,101,114,105,102,121,32,116,104,97,116,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,32,104,97,118,101,32,98,111,117,110,100,32,97,115,32,114,101,113,117,101,115,116,101,100,44,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<46>>]}]},{p,[],[<<83,99,104,101,100,117,108,101,114,115,32,99,97,110,32,98,101,32,98,111,117,110,100,32,111,110,32,110,101,119,101,114,32,76,105,110,117,120,44,32,83,111,108,97,114,105,115,44,32,70,114,101,101,66,83,68,44,32,97,110,100,32,87,105,110,100,111,119,115,32,115,121,115,116,101,109,115,44,32,98,117,116,32,109,111,114,101,32,115,121,115,116,101,109,115,32,119,105,108,108,32,98,101,32,115,117,112,112,111,114,116,101,100,32,105,110,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,115,46>>]},{p,[],[<<73,110,32,111,114,100,101,114,32,102,111,114,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,116,111,32,98,101,32,97,98,108,101,32,116,111,32,98,105,110,100,32,115,99,104,101,100,117,108,101,114,115,44,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,109,117,115,116,32,98,101,32,107,110,111,119,110,46,32,73,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,102,97,105,108,115,32,116,111,32,100,101,116,101,99,116,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,97,117,116,111,109,97,116,105,99,97,108,108,121,44,32,105,116,32,99,97,110,32,98,101,32,100,101,102,105,110,101,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,104,111,119,32,116,111,32,100,101,102,105,110,101,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,111,101,115,32,98,121,32,100,101,102,97,117,108,116,32>>,{em,[],[<<110,111,116>>]},<<32,98,105,110,100,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,116,104,101,32,111,110,108,121,32,79,83,32,112,114,111,99,101,115,115,32,98,105,110,100,105,110,103,32,116,104,114,101,97,100,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,105,115,32,105,109,112,114,111,118,101,115,32,116,104,101,32,112,101,114,102,111,114,109,97,110,99,101,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,116,104,101,114,32,79,83,32,112,114,111,99,101,115,115,101,115,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,110,111,116,104,101,114,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,41,32,97,108,115,111,32,98,105,110,100,32,116,104,114,101,97,100,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,101,114,101,32,99,97,110,32,98,101,32,97,32,112,101,114,102,111,114,109,97,110,99,101,32,112,101,110,97,108,116,121,32,105,110,115,116,101,97,100,46,32,83,111,109,101,116,105,109,101,115,32,116,104,105,115,32,112,101,114,102,111,114,109,97,110,99,101,32,112,101,110,97,108,116,121,32,99,97,110,32,98,101,32,115,101,118,101,114,101,46,32,73,102,32,115,111,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,110,111,116,32,98,105,110,100,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,46>>]}]},{p,[],[<<83,99,104,101,100,117,108,101,114,115,32,99,97,110,32,98,101,32,98,111,117,110,100,32,105,110,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,46,32,65,114,103,117,109,101,110,116,32>>,{code,[],[<<72,111,119>>]},<<32,100,101,116,101,114,109,105,110,101,115,32,104,111,119,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,111,117,110,100,32,97,110,100,32,99,97,110,32,98,101,32,97,110,121,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<117,110,98,111,117,110,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,117>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,110,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<116,104,114,101,97,100,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,116,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,111,114,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,112,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,95,110,111,100,101,95,116,104,114,101,97,100,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,110,110,116,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<110,111,95,110,111,100,101,95,112,114,111,99,101,115,115,111,114,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,110,110,112,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<116,104,114,101,97,100,95,110,111,95,110,111,100,101,95,112,114,111,99,101,115,115,111,114,95,115,112,114,101,97,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,116,110,110,112,115>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{dt,[],[{code,[],[<<100,101,102,97,117,108,116,95,98,105,110,100>>]}]},{dd,[],[<<83,97,109,101,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116,32,100,98>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,101,113,117,97,108,115,32>>,{code,[],[<<72,111,119>>]},<<32,98,101,102,111,114,101,32,102,108,97,103,32>>,{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>]},<<32,119,97,115,32,99,104,97,110,103,101,100,46>>]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<110,111,116,115,117,112>>]}]},{dd,[],[<<73,102,32,98,105,110,100,105,110,103,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<72,111,119>>]},<<32,105,115,32,110,111,116,32,111,110,101,32,111,102,32,116,104,101,32,100,111,99,117,109,101,110,116,101,100,32,97,108,116,101,114,110,97,116,105,118,101,115,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,117,110,97,118,97,105,108,97,98,108,101,46>>]}]},{p,[],[<<84,104,101,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,32,116,121,112,101,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<44,32,97,115,32,119,101,108,108,32,97,115,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,50,52,49>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2705,25},bounded_fun,[{type,{2705,25},'fun',[{type,{2705,25},product,[{atom,{2705,26},scheduler_bind_type},{var,{2705,47},'How'}]},{var,{2705,55},'OldBindType'}]},[{type,{2706,7},constraint,[{atom,{2706,7},is_subtype},[{var,{2706,7},'How'},{type,{2706,14},union,[{user_type,{2706,14},scheduler_bind_type,[]},{atom,{2706,38},default_bind}]}]]},{type,{2707,7},constraint,[{atom,{2707,7},is_subtype},[{var,{2707,7},'OldBindType'},{user_type,{2707,22},scheduler_bind_type,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,115,99,104,101,100,117,108,101,114,32,119,97,108,108,32,116,105,109,101,32,109,101,97,115,117,114,101,109,101,110,116,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,97,116,105,115,116,105,99,115,95,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,116,105,115,116,105,99,115,40,115,99,104,101,100,117,108,101,114,95,119,97,108,108,95,116,105,109,101,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,51,54,56>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2708,25},bounded_fun,[{type,{2708,25},'fun',[{type,{2708,25},product,[{atom,{2708,26},scheduler_wall_time},{var,{2708,47},'Boolean'}]},{var,{2708,60},'OldBoolean'}]},[{type,{2709,7},constraint,[{atom,{2709,7},is_subtype},[{var,{2709,7},'Boolean'},{type,{2709,18},boolean,[]}]]},{type,{2710,7},constraint,[{atom,{2710,7},is_subtype},[{var,{2710,7},'OldBoolean'},{type,{2710,21},boolean,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66,48,49>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,82,97,110,103,101,32,105,115,32>>,{code,[],[<<49,32,60,61,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,32,60,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{p,[],[<<73,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,97,115,32,98,117,105,108,116,32,119,105,116,104,32,115,117,112,112,111,114,116,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115>>]},<<44,32,99,104,97,110,103,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,97,108,115,111,32,99,104,97,110,103,101,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,49,50,32,115,99,104,101,100,117,108,101,114,115,32,97,110,100,32,54,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,111,110,108,105,110,101,44,32,97,110,100,32>>,{code,[],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>]},<<32,105,115,32,117,115,101,100,32,116,111,32,115,101,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,116,111,32,54,44,32,116,104,101,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,99,114,101,97,115,101,100,32,98,121,32,104,97,108,102,32,97,115,32,119,101,108,108,44,32,100,111,119,110,32,116,111,32,51,46,32,83,105,109,105,108,97,114,108,121,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,105,110,99,114,101,97,115,101,115,32,112,114,111,112,111,114,116,105,111,110,97,108,108,121,32,116,111,32,105,110,99,114,101,97,115,101,115,32,105,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,51,56,49>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2711,25},bounded_fun,[{type,{2711,25},'fun',[{type,{2711,25},product,[{atom,{2711,26},schedulers_online},{var,{2711,45},'SchedulersOnline'}]},{var,{2712,33},'OldSchedulersOnline'}]},[{type,{2713,7},constraint,[{atom,{2713,7},is_subtype},[{var,{2713,7},'SchedulersOnline'},{type,{2713,27},pos_integer,[]}]]},{type,{2714,7},constraint,[{atom,{2714,7},is_subtype},[{var,{2714,7},'OldSchedulersOnline'},{type,{2714,30},pos_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,119,105,108,108,32,114,101,99,101,105,118,101,32,116,104,101,32,108,111,103,103,105,110,103,32,109,101,115,115,97,103,101,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,69,82,84,83,46,32,73,102,32,115,101,116,32,116,111,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<44,32,97,108,108,32,108,111,103,103,105,110,103,32,109,101,115,115,97,103,101,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,69,82,84,83,32,119,105,108,108,32,98,101,32,100,114,111,112,112,101,100,46,32,84,104,101,32,109,101,115,115,97,103,101,115,32,119,105,108,108,32,98,101,32,105,110,32,116,104,101,32,102,111,114,109,97,116,58>>]},{pre,[],[{code,[],[<<123,108,111,103,44,76,101,118,101,108,44,70,111,114,109,97,116,44,65,114,103,76,105,115,116,44,77,101,116,97,100,97,116,97,125,32,119,104,101,114,101,10,10,76,101,118,101,108,32,61,32,97,116,111,109,40,41,44,10,70,111,114,109,97,116,32,61,32,115,116,114,105,110,103,40,41,44,10,65,114,103,76,105,115,116,32,61,32,108,105,115,116,40,116,101,114,109,40,41,41,44,10,77,101,116,97,100,97,116,97,32,61,32,35,123,32,112,105,100,32,61,62,32,112,105,100,40,41,44,10,32,32,32,103,114,111,117,112,95,108,101,97,100,101,114,32,61,62,32,112,105,100,40,41,44,10,32,32,32,116,105,109,101,32,58,61,32,108,111,103,103,101,114,58,116,105,109,101,115,116,97,109,112,40,41,44,10,32,32,32,101,114,114,111,114,95,108,111,103,103,101,114,32,58,61,32,35,123,32,101,109,117,108,97,116,111,114,32,58,61,32,116,114,117,101,44,32,116,97,103,32,58,61,32,97,116,111,109,40,41,32,125,10,32,32,32,32,32,32,32,32>>]}]},{p,[],[<<73,102,32,116,104,101,32>>,{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]},<<32,112,114,111,99,101,115,115,32,100,105,101,115,44,32,116,104,105,115,32,102,108,97,103,32,119,105,108,108,32,98,101,32,114,101,115,101,116,32,116,111,32>>,{code,[],[<<108,111,103,103,101,114>>]},<<46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,110,97,109,101,100,32>>,{code,[],[<<108,111,103,103,101,114>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,98,101,32,117,115,101,100,32,98,121,32,116,104,101,32,75,69,82,78,69,76,32>>,{a,[{href,<<107,101,114,110,101,108,58,108,111,103,103,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,103,103,101,114>>]}]},<<46,32,66,101,32,99,97,114,101,102,117,108,32,105,102,32,121,111,117,32,99,104,97,110,103,101,32,105,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,97,115,32,108,111,103,32,109,101,115,115,97,103,101,115,32,109,97,121,32,98,101,32,108,111,115,116,46,32,73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,105,110,116,101,114,99,101,112,116,32,101,109,117,108,97,116,111,114,32,108,111,103,32,109,101,115,115,97,103,101,115,44,32,100,111,32,105,116,32,98,121,32,97,100,100,105,110,103,32,97,32,115,112,101,99,105,97,108,105,122,101,100,32,104,97,110,100,108,101,114,32,116,111,32,116,104,101,32,75,69,82,78,69,76,32,108,111,103,103,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,52,49,48>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2715,25},bounded_fun,[{type,{2715,25},'fun',[{type,{2715,25},product,[{atom,{2715,26},system_logger},{var,{2715,41},'Logger'}]},{var,{2715,52},'PrevLogger'}]},[{type,{2716,7},constraint,[{atom,{2716,7},is_subtype},[{var,{2716,7},'Logger'},{type,{2716,17},union,[{atom,{2716,17},logger},{atom,{2716,26},undefined},{type,{2716,38},pid,[]}]}]]},{type,{2717,7},constraint,[{atom,{2717,7},is_subtype},[{var,{2717,7},'PrevLogger'},{type,{2717,21},union,[{atom,{2717,21},logger},{atom,{2717,30},undefined},{type,{2717,42},pid,[]}]}]]}]]}]}}],since => <<79,84,80,32,50,49,46,51>>}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,110,111,100,101,32,116,114,97,99,101,32,99,111,110,116,114,111,108,32,119,111,114,100,32,116,111,32>>,{code,[],[<<84,67,87>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,111,32,98,101,32,97,110,32,117,110,115,105,103,110,101,100,32,105,110,116,101,103,101,114,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99,35,115,101,116,95,116,99,119>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<115,101,116,95,116,99,119>>]}]},<<32,105,110,32,115,101,99,116,105,111,110,32,34,77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103,34,32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,108,97,103,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,52,52,50>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2718,25},bounded_fun,[{type,{2718,25},'fun',[{type,{2718,25},product,[{atom,{2718,26},trace_control_word},{var,{2718,46},'TCW'}]},{var,{2718,54},'OldTCW'}]},[{type,{2719,7},constraint,[{atom,{2719,7},is_subtype},[{var,{2719,7},'TCW'},{type,{2719,14},non_neg_integer,[]}]]},{type,{2720,7},constraint,[{atom,{2720,7},is_subtype},[{var,{2720,7},'OldTCW'},{type,{2720,17},non_neg_integer,[]}]]}]]}]}}]}},{{function,system_flag,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2672}],[<<115,121,115,116,101,109,95,102,108,97,103,47,50>>],#{<<101,110>> => [{p,[],[<<70,105,110,97,108,105,122,101,115,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<116,105,109,101,32,111,102,102,115,101,116>>]},<<32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46,32,73,102,32,97,110,111,116,104,101,114,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101,32,105,115,32,117,115,101,100,44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,115,116,97,116,101,32,105,115,32,108,101,102,116,32,117,110,99,104,97,110,103,101,100,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,111,108,100,32,115,116,97,116,101,32,105,100,101,110,116,105,102,105,101,114,44,32,116,104,97,116,32,105,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<112,114,101,108,105,109,105,110,97,114,121>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,102,105,110,97,108,105,122,97,116,105,111,110,32,119,97,115,32,112,101,114,102,111,114,109,101,100,32,97,110,100,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,110,111,119,32,102,105,110,97,108,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<102,105,110,97,108>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,119,97,115,32,97,108,114,101,97,100,121,32,105,110,32,116,104,101,32,102,105,110,97,108,32,115,116,97,116,101,46,32,84,104,105,115,32,101,105,116,104,101,114,32,98,101,99,97,117,115,101,32,97,110,111,116,104,101,114,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,116,105,109,101,95,111,102,102,115,101,116,44,32,102,105,110,97,108,105,122,101,41>>]},<<32,99,97,108,108,32,111,114,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,78,111,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]},{li,[],[{p,[],[<<73,102,32>>,{code,[],[<<118,111,108,97,116,105,108,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,99,97,110,110,111,116,32,98,101,32,102,105,110,97,108,105,122,101,100,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,52,53,54>>,signature => [{attribute,{2672,2},spec,{{erlang,system_flag,2},[{type,{2721,4},bounded_fun,[{type,{2721,4},'fun',[{type,{2721,4},product,[{atom,{2721,5},time_offset},{atom,{2721,18},finalize}]},{var,{2721,31},'OldState'}]},[{type,{2722,7},constraint,[{atom,{2722,7},is_subtype},[{var,{2722,7},'OldState'},{type,{2722,19},union,[{atom,{2722,19},preliminary},{atom,{2722,33},final},{atom,{2722,41},volatile}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,46,32,84,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,98,114,111,107,101,110,32,105,110,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,32,105,110,32,111,114,100,101,114,32,116,111,32,109,97,107,101,32,105,116,32,101,97,115,105,101,114,32,116,111,32,110,97,118,105,103,97,116,101,46>>]},{dl,[],[{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<77,101,109,111,114,121,32,65,108,108,111,99,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,97,116,111,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,115,105,122,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,108,108,111,99,97,116,111,114,95,115,105,122,101,115>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<67,80,85,32,84,111,112,111,108,111,103,121>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<80,114,111,99,101,115,115,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,115,105,122,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<104,101,97,112,95,115,105,122,101,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<104,101,97,112,95,116,121,112,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,115>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,105,109,105,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,121,115,116,101,109,32,76,105,109,105,116,115>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,116,111,109,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<97,116,111,109,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,116,115,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,116,115,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,111,114,116,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,111,114,116,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,99,111,117,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,99,111,117,110,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,108,105,109,105,116>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,121,115,116,101,109,32,84,105,109,101>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,110,100,95,116,105,109,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,116,97,114,116,95,116,105,109,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,111,102,102,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,119,97,114,112,95,109,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,119,97,114,112,95,109,111,100,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,99,104,101,100,117,108,101,114,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,105,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,95,105,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,99,104,101,100,117,108,101,114,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,109,112,95,115,117,112,112,111,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,109,112,95,115,117,112,112,111,114,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,104,114,101,97,100,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<68,105,115,116,114,105,98,117,116,105,111,110,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,114,101,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,114,101,97,116,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,115,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,99,116,114,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,115,116,95,99,116,114,108>>]}]}]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,105,115,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<83,121,115,116,101,109,32,73,110,102,111,114,109,97,116,105,111,110>>]}]}]},{dd,[],[{p,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,104,101,99,107,95,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,104,101,99,107,95,105,111>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,111,109,112,97,116,95,114,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,111,109,112,97,116,95,114,101,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,101,98,117,103,95,99,111,109,112,105,108,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,101,98,117,103,95,99,111,109,112,105,108,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,114,105,118,101,114,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,114,105,118,101,114,95,118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,102,108,97,118,111,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,109,117,95,102,108,97,118,111,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,109,117,95,116,121,112,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,105,110,102,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,102,111>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,107,101,114,110,101,108,95,112,111,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<107,101,114,110,101,108,95,112,111,108,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,97,100,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,111,97,100,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,97,99,104,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,99,104,105,110,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,105,102,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<110,105,102,95,118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,111,116,112,95,114,101,108,101,97,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,116,112,95,114,101,108,101,97,115,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,108,111,103,103,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,121,115,116,101,109,95,118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,118,101,114,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<118,101,114,115,105,111,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,119,111,114,100,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<119,111,114,100,115,105,122,101>>]}]}]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,52,56,54>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2934,10},'fun',[{type,{2934,10},product,[{atom,{2934,11},version}]},{type,{2934,23},string,[]}]}]}}]}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,111,114,115,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>}],[]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>}],[]},{code,[],[<<97,108,108,111,99,97,116,101,100,95,97,114,101,97,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32,119,105,116,104,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,97,114,101,97,115,46>>]},{p,[],[<<69,97,99,104,32,116,117,112,108,101,32,99,111,110,116,97,105,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,116,121,112,101,32,111,102,32,109,101,109,111,114,121,32,97,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,97,110,100,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,97,108,108,111,99,97,116,101,100,32,109,101,109,111,114,121,32,105,110,32,98,121,116,101,115,32,97,115,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,46,32,87,104,101,110,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,108,108,111,99,97,116,101,100,32,97,110,100,32,117,115,101,100,32,109,101,109,111,114,121,32,105,115,32,112,114,101,115,101,110,116,44,32,97,108,115,111,32,97,32,116,104,105,114,100,32,101,108,101,109,101,110,116,32,105,115,32,112,114,101,115,101,110,116,44,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,117,115,101,100,32,109,101,109,111,114,121,32,105,110,32,98,121,116,101,115,46>>]},{p,[],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,97,108,108,111,99,97,116,101,100,95,97,114,101,97,115,41>>]},<<32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,44,32,97,110,100,32,116,104,101,32,99,111,110,116,101,110,116,32,105,115,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,46,32,84,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,115,32,116,104,101,114,101,102,111,114,101,32,99,104,97,110,103,101,115,32,119,104,101,110,32,110,101,101,100,101,100,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,115,101,32,118,97,108,117,101,115,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,116,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,111,109,101,32,118,97,108,117,101,115,32,97,114,101,32,112,97,114,116,32,111,102,32,111,116,104,101,114,32,118,97,108,117,101,115,44,32,97,110,100,32,115,111,109,101,32,109,101,109,111,114,121,32,97,114,101,97,115,32,97,114,101,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,115,117,108,116,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,116,111,116,97,108,32,97,109,111,117,110,116,32,111,102,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,101,109,111,114,121,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,101,109,111,114,121,47,48,44,49>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114>>}],[]},{code,[],[<<97,108,108,111,99,97,116,111,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,65,108,108,111,99,97,116,111,114,44,32,86,101,114,115,105,111,110,44,32,70,101,97,116,117,114,101,115,44,32,83,101,116,116,105,110,103,115>>]},<<44,32,119,104,101,114,101,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<65,108,108,111,99,97,116,111,114>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32>>,{code,[],[<<109,97,108,108,111,99,40,41>>]},<<32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,117,115,101,100,46,32,73,102,32>>,{code,[],[<<65,108,108,111,99,97,116,111,114>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<44,32,116,104,101,32>>,{code,[],[<<109,97,108,108,111,99,40,41>>]},<<32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,117,115,101,100,32,99,97,110,110,111,116,32,98,101,32,105,100,101,110,116,105,102,105,101,100,46,32>>,{code,[],[<<103,108,105,98,99>>]},<<32,99,97,110,32,98,101,32,105,100,101,110,116,105,102,105,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<86,101,114,115,105,111,110>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,40,98,117,116,32,110,111,116,32,97,32,115,116,114,105,110,103,41,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<109,97,108,108,111,99,40,41>>]},<<32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,117,115,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<70,101,97,116,117,114,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,97,116,111,109,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,97,108,108,111,99,97,116,105,111,110,32,102,101,97,116,117,114,101,115,32,117,115,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<83,101,116,116,105,110,103,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,115,117,98,115,121,115,116,101,109,115,44,32,116,104,101,105,114,32,99,111,110,102,105,103,117,114,97,98,108,101,32,112,97,114,97,109,101,116,101,114,115,44,32,97,110,100,32,117,115,101,100,32,118,97,108,117,101,115,46,32,83,101,116,116,105,110,103,115,32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,100,105,102,102,101,114,101,110,116,32,99,111,109,98,105,110,97,116,105,111,110,115,32,111,102,32,112,108,97,116,102,111,114,109,115,44,32,97,108,108,111,99,97,116,111,114,115,44,32,97,110,100,32,97,108,108,111,99,97,116,105,111,110,32,102,101,97,116,117,114,101,115,46,32,77,101,109,111,114,121,32,115,105,122,101,115,32,97,114,101,32,103,105,118,101,110,32,105,110,32,98,121,116,101,115,46>>]}]}]},{p,[],[<<83,101,101,32,97,108,115,111,32,34,83,121,115,116,101,109,32,70,108,97,103,115,32,69,102,102,101,99,116,105,110,103,32,101,114,116,115,95,97,108,108,111,99,34,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99,35,102,108,97,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,116,117,112,108,101>>}],[]},{code,[],[<<123,97,108,108,111,99,97,116,111,114,44,32,65,108,108,111,99,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,97,108,108,111,99,97,116,111,114,46,32,65,115,32,102,114,111,109,32,69,82,84,83,32,53,46,54,46,49,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<123,105,110,115,116,97,110,99,101,44,32,73,110,115,116,97,110,99,101,78,111,44,32,73,110,115,116,97,110,99,101,73,110,102,111,125>>]},<<32,116,117,112,108,101,115,44,32,119,104,101,114,101,32>>,{code,[],[<<73,110,115,116,97,110,99,101,73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,115,112,101,99,105,102,105,99,32,105,110,115,116,97,110,99,101,32,111,102,32,116,104,101,32,97,108,108,111,99,97,116,111,114,46,32,73,102,32>>,{code,[],[<<65,108,108,111,99>>]},<<32,105,115,32,110,111,116,32,97,32,114,101,99,111,103,110,105,122,101,100,32,97,108,108,111,99,97,116,111,114,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,73,102,32>>,{code,[],[<<65,108,108,111,99>>]},<<32,105,115,32,100,105,115,97,98,108,101,100,44,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,105,115,32,104,105,103,104,108,121,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,100,101,112,101,110,100,101,110,116,32,97,110,100,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,111,114,32,114,101,109,111,118,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46,32,73,116,32,119,97,115,32,105,110,105,116,105,97,108,108,121,32,105,110,116,101,110,100,101,100,32,97,115,32,97,32,116,111,111,108,32,119,104,101,110,32,100,101,118,101,108,111,112,105,110,103,32,110,101,119,32,97,108,108,111,99,97,116,111,114,115,44,32,98,117,116,32,97,115,32,105,116,32,99,97,110,32,98,101,32,111,102,32,105,110,116,101,114,101,115,116,32,102,111,114,32,111,116,104,101,114,115,32,105,116,32,104,97,115,32,98,101,101,110,32,98,114,105,101,102,108,121,32,100,111,99,117,109,101,110,116,101,100,46>>]},{p,[],[<<84,104,101,32,114,101,99,111,103,110,105,122,101,100,32,97,108,108,111,99,97,116,111,114,115,32,97,114,101,32,108,105,115,116,101,100,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]}]},<<46,32,73,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,117,112,101,114,32,99,97,114,114,105,101,114,115,32,99,97,110,32,98,101,32,111,98,116,97,105,110,101,100,32,102,114,111,109,32,69,82,84,83,32,56,46,48,32,119,105,116,104,32>>,{code,[],[<<123,97,108,108,111,99,97,116,111,114,44,32,101,114,116,115,95,109,109,97,112,125>>]},<<32,111,114,32,102,114,111,109,32,69,82,84,83,32,53,46,49,48,46,52,59,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,119,104,101,110,32,99,97,108,108,105,110,103,32,119,105,116,104,32>>,{code,[],[<<123,97,108,108,111,99,97,116,111,114,44,32,109,115,101,103,95,97,108,108,111,99,125>>]},<<32,97,108,115,111,32,105,110,99,108,117,100,101,115,32,97,110,32>>,{code,[],[<<123,101,114,116,115,95,109,109,97,112,44,32,95,125>>]},<<32,116,117,112,108,101,32,97,115,32,111,110,101,32,101,108,101,109,101,110,116,32,105,110,32,116,104,101,32,108,105,115,116,46>>]},{p,[],[<<65,102,116,101,114,32,114,101,97,100,105,110,103,32,116,104,101,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]},<<32,100,111,99,117,109,101,110,116,97,116,105,111,110,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,109,111,114,101,32,111,114,32,108,101,115,115,32,115,112,101,97,107,115,32,102,111,114,32,105,116,115,101,108,102,44,32,98,117,116,32,105,116,32,99,97,110,32,98,101,32,119,111,114,116,104,32,101,120,112,108,97,105,110,105,110,103,32,115,111,109,101,32,116,104,105,110,103,115,46,32,67,97,108,108,32,99,111,117,110,116,115,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,98,121,32,116,119,111,32,118,97,108,117,101,115,44,32,116,104,101,32,102,105,114,115,116,32,118,97,108,117,101,32,105,115,32,103,105,103,97,32,99,97,108,108,115,44,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,118,97,108,117,101,32,105,115,32,99,97,108,108,115,46,32>>,{code,[],[<<109,98,99,115>>]},<<32,97,110,100,32>>,{code,[],[<<115,98,99,115>>]},<<32,100,101,110,111,116,101,32,109,117,108,116,105,45,98,108,111,99,107,32,99,97,114,114,105,101,114,115,44,32,97,110,100,32,115,105,110,103,108,101,45,98,108,111,99,107,32,99,97,114,114,105,101,114,115,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,83,105,122,101,115,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,105,110,32,98,121,116,101,115,46,32,87,104,101,110,32,97,32,115,105,122,101,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,101,100,44,32,105,116,32,105,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,115,111,109,101,116,104,105,110,103,46,32,83,105,122,101,115,32,97,110,100,32,97,109,111,117,110,116,115,32,97,114,101,32,111,102,116,101,110,32,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,114,101,101,32,118,97,108,117,101,115,58>>]},{ul,[],[{li,[],[<<84,104,101,32,102,105,114,115,116,32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,118,97,108,117,101,46>>]},{li,[],[<<84,104,101,32,115,101,99,111,110,100,32,105,115,32,116,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,115,105,110,99,101,32,116,104,101,32,108,97,115,116,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,123,97,108,108,111,99,97,116,111,114,44,32,65,108,108,111,99,125,41>>]},<<46>>]},{li,[],[<<84,104,101,32,116,104,105,114,100,32,105,115,32,116,104,101,32,109,97,120,105,109,117,109,32,118,97,108,117,101,32,115,105,110,99,101,32,116,104,101,32,101,109,117,108,97,116,111,114,32,119,97,115,32,115,116,97,114,116,101,100,46>>]}]},{p,[],[<<73,102,32,111,110,108,121,32,111,110,101,32,118,97,108,117,101,32,105,115,32,112,114,101,115,101,110,116,44,32,105,116,32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,118,97,108,117,101,46,32>>,{code,[],[<<102,105,120,95,97,108,108,111,99>>]},<<32,109,101,109,111,114,121,32,98,108,111,99,107,32,116,121,112,101,115,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,98,121,32,116,119,111,32,118,97,108,117,101,115,46,32,84,104,101,32,102,105,114,115,116,32,118,97,108,117,101,32,105,115,32,116,104,101,32,109,101,109,111,114,121,32,112,111,111,108,32,115,105,122,101,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,118,97,108,117,101,32,105,115,32,116,104,101,32,117,115,101,100,32,109,101,109,111,114,121,32,115,105,122,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>}],[]},{code,[],[<<97,108,108,111,99,95,117,116,105,108,95,97,108,108,111,99,97,116,111,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,97,108,108,111,99,97,116,111,114,115,32,117,115,105,110,103,32,116,104,101,32,69,82,84,83,32,105,110,116,101,114,110,97,108,32>>,{code,[],[<<97,108,108,111,99,95,117,116,105,108>>]},<<32,102,114,97,109,101,119,111,114,107,32,97,115,32,97,116,111,109,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,101,114,116,115,95,97,108,108,111,99,35,97,108,108,111,99,95,117,116,105,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<84,104,101,32,97,108,108,111,99,95,117,116,105,108,32,102,114,97,109,101,119,111,114,107>>]},<<32,105,110,32>>,{code,[],[<<101,114,116,115,95,97,108,108,111,99,40,51,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,115,105,122,101,115>>}],[]},{code,[],[<<123,97,108,108,111,99,97,116,111,114,95,115,105,122,101,115,44,32,65,108,108,111,99,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,115,105,122,101,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,97,108,108,111,99,97,116,111,114,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,97,108,108,111,99,97,116,111,114,95,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,123,97,108,108,111,99,97,116,111,114,44,32,65,108,108,111,99,125,41>>]}]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,54,49,57>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2835,10},'fun',[{type,{2835,10},product,[{atom,{2835,11},allocated_areas}]},{type,{2835,31},list,[{type,{2835,33},tuple,any}]}]},{type,{2836,10},bounded_fun,[{type,{2836,10},'fun',[{type,{2836,10},product,[{atom,{2836,11},allocator}]},{type,{2837,18},tuple,[{var,{2837,19},'Allocator'},{var,{2837,30},'Version'},{var,{2837,39},'Features'},{var,{2837,49},'Settings'}]}]},[{type,{2838,7},constraint,[{atom,{2838,7},is_subtype},[{var,{2838,7},'Allocator'},{type,{2838,20},union,[{atom,{2838,20},undefined},{atom,{2838,32},glibc}]}]]},{type,{2839,7},constraint,[{atom,{2839,7},is_subtype},[{var,{2839,7},'Version'},{type,{2839,18},list,[{type,{2839,19},non_neg_integer,[]}]}]]},{type,{2840,7},constraint,[{atom,{2840,7},is_subtype},[{var,{2840,7},'Features'},{type,{2840,19},list,[{type,{2840,20},atom,[]}]}]]},{type,{2841,7},constraint,[{atom,{2841,7},is_subtype},[{var,{2841,7},'Settings'},{type,{2841,19},list,[{type,{2841,20},tuple,[{ann_type,{2841,21},[{var,{2841,21},'Subsystem'},{type,{2841,34},atom,[]}]},{type,{2842,21},list,[{type,{2842,22},tuple,[{ann_type,{2842,23},[{var,{2842,23},'Parameter'},{type,{2842,36},atom,[]}]},{ann_type,{2843,23},[{var,{2843,23},'Value'},{type,{2843,32},term,[]}]}]}]}]}]}]]}]]},{type,{2844,10},bounded_fun,[{type,{2844,10},'fun',[{type,{2844,10},product,[{type,{2844,11},tuple,[{atom,{2844,12},allocator},{var,{2844,23},'Alloc'}]}]},{type,{2844,34},list,[{var,{2844,35},'_'}]}]},[{type,{2845,7},constraint,[{atom,{2845,7},is_subtype},[{var,{2845,7},'Alloc'},{type,{2845,16},atom,[]}]]}]]},{type,{2846,10},bounded_fun,[{type,{2846,10},'fun',[{type,{2846,10},product,[{atom,{2846,11},alloc_util_allocators}]},{type,{2846,37},list,[{var,{2846,38},'Alloc'}]}]},[{type,{2847,7},constraint,[{atom,{2847,7},is_subtype},[{var,{2847,7},'Alloc'},{type,{2847,16},atom,[]}]]}]]},{type,{2848,10},bounded_fun,[{type,{2848,10},'fun',[{type,{2848,10},product,[{type,{2848,11},tuple,[{atom,{2848,12},allocator_sizes},{var,{2848,29},'Alloc'}]}]},{type,{2848,40},list,[{var,{2848,41},'_'}]}]},[{type,{2849,7},constraint,[{atom,{2849,7},is_subtype},[{var,{2849,7},'Alloc'},{type,{2849,16},atom,[]}]]}]]}]}}]}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<99,112,117,95,116,111,112,111,108,111,103,121>>}],[]},{li,[{name,<<99,112,117,95,116,111,112,111,108,111,103,121>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,108,108,32>>,{code,[],[<<76,101,118,101,108,69,110,116,114,121>>]},<<115,32,111,102,32,97,32,108,105,115,116,32,109,117,115,116,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32>>,{code,[],[<<76,101,118,101,108,84,97,103>>]},<<44,32,101,120,99,101,112,116,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,119,104,101,114,101,32,98,111,116,104,32>>,{code,[],[<<110,111,100,101>>]},<<32,97,110,100,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},{code,[],[<<76,101,118,101,108,84,97,103>>]},<<115,32,99,97,110,32,99,111,101,120,105,115,116,46>>]},{li,[{name,<<105,110,102,111,95,108,105,115,116>>}],[]},{li,[{name,<<105,110,102,111,95,108,105,115,116>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<84,104,101,32>>,{code,[],[<<105,110,102,111,95,108,105,115,116,40,41>>]},<<32,99,97,110,32,98,101,32,101,120,116,101,110,100,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{li,[{name,<<108,101,118,101,108,95,101,110,116,114,121>>}],[]},{li,[{name,<<108,101,118,101,108,95,101,110,116,114,121>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[{code,[],[<<123,76,101,118,101,108,84,97,103,44,32,83,117,98,76,101,118,101,108,125,32,61,61,32,123,76,101,118,101,108,84,97,103,44,32,91,93,44,32,83,117,98,76,101,118,101,108,125>>]}]},{li,[{name,<<108,101,118,101,108,95,116,97,103>>}],[]},{li,[{name,<<108,101,118,101,108,95,116,97,103>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<77,111,114,101,32>>,{code,[],[<<76,101,118,101,108,84,97,103>>]},<<115,32,99,97,110,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]},{li,[{name,<<115,117,98,95,108,101,118,101,108>>}],[]}]},{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>}],[]},{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,84,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,117,115,101,100,32,119,104,101,110,32,98,105,110,100,105,110,103,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,84,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,117,115,101,100,32,105,115,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,102,105,110,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,115,101,114,45,100,101,102,105,110,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121>>]},<<44,32,105,102,32,115,117,99,104,32,101,120,105,115,116,115,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,116,101,99,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121>>]},<<44,32,105,102,32,115,117,99,104,32,101,120,105,115,116,115,46,32,73,102,32,110,111,32,67,80,85,32,116,111,112,111,108,111,103,121,32,101,120,105,115,116,115,44,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[{code,[],[<<110,111,100,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,78,111,110,45,85,110,105,102,111,114,109,32,77,101,109,111,114,121,32,65,99,99,101,115,115,32,40,78,85,77,65,41,32,110,111,100,101,115,46,32>>,{code,[],[<<116,104,114,101,97,100>>]},<<32,114,101,102,101,114,115,32,116,111,32,104,97,114,100,119,97,114,101,32,116,104,114,101,97,100,115,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,73,110,116,101,108,32,104,121,112,101,114,45,116,104,114,101,97,100,115,41,46>>]},{p,[],[<<65,32,108,101,118,101,108,32,105,110,32,116,101,114,109,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,99,97,110,32,98,101,32,111,109,105,116,116,101,100,32,105,102,32,111,110,108,121,32,111,110,101,32,101,110,116,114,121,32,101,120,105,115,116,115,32,97,110,100,32>>,{code,[],[<<73,110,102,111,76,105,115,116>>]},<<32,105,115,32,101,109,112,116,121,46>>]},{p,[],[{code,[],[<<116,104,114,101,97,100>>]},<<32,99,97,110,32,111,110,108,121,32,98,101,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<99,111,114,101>>]},<<46,32>>,{code,[],[<<99,111,114,101>>]},<<32,99,97,110,32,98,101,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},<<32,111,114,32>>,{code,[],[<<110,111,100,101>>]},<<46,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},<<32,99,97,110,32,98,101,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,111,114,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<110,111,100,101>>]},<<46,32>>,{code,[],[<<110,111,100,101>>]},<<32,99,97,110,32,98,101,32,111,110,32,116,104,101,32,116,111,112,32,108,101,118,101,108,32,111,114,32,97,32,115,117,98,108,101,118,101,108,32,116,111,32>>,{code,[],[<<112,114,111,99,101,115,115,111,114>>]},<<46,32,84,104,97,116,32,105,115,44,32,78,85,77,65,32,110,111,100,101,115,32,99,97,110,32,98,101,32,112,114,111,99,101,115,115,111,114,32,105,110,116,101,114,110,97,108,32,111,114,32,112,114,111,99,101,115,115,111,114,32,101,120,116,101,114,110,97,108,46,32,65,32,67,80,85,32,116,111,112,111,108,111,103,121,32,99,97,110,32,99,111,110,115,105,115,116,32,111,102,32,97,32,109,105,120,32,111,102,32,112,114,111,99,101,115,115,111,114,32,105,110,116,101,114,110,97,108,32,97,110,100,32,101,120,116,101,114,110,97,108,32,78,85,77,65,32,110,111,100,101,115,44,32,97,115,32,108,111,110,103,32,97,115,32,101,97,99,104,32,108,111,103,105,99,97,108,32,67,80,85,32,98,101,108,111,110,103,115,32,116,111,32>>,{em,[],[<<111,110,101>>]},<<32,78,85,77,65,32,110,111,100,101,46,32,67,97,99,104,101,32,104,105,101,114,97,114,99,104,121,32,105,115,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,116,121,112,101,44,32,98,117,116,32,119,105,108,108,32,98,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,79,116,104,101,114,32,116,104,105,110,103,115,32,99,97,110,32,97,108,115,111,32,109,97,107,101,32,105,116,32,105,110,116,111,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,83,111,44,32,101,120,112,101,99,116,32,116,104,101,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,116,121,112,101,32,116,111,32,99,104,97,110,103,101,46>>]}]},{dt,[],[{code,[],[<<123,99,112,117,95,116,111,112,111,108,111,103,121,44,32,100,101,102,105,110,101,100,125>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,102,105,110,101,100>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,117,115,101,114,45,100,101,102,105,110,101,100,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,99,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<32,97,110,100,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,99,112,117,95,116,111,112,111,108,111,103,121,44,32,100,101,116,101,99,116,101,100,125>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,116,101,99,116,101,100>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,100,101,116,101,99,116,101,100,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121,121>>]},<<46,32,84,104,101,32,101,109,117,108,97,116,111,114,32,100,101,116,101,99,116,115,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,111,110,32,115,111,109,101,32,110,101,119,101,114,32,76,105,110,117,120,44,32,83,111,108,97,114,105,115,44,32,70,114,101,101,66,83,68,44,32,97,110,100,32,87,105,110,100,111,119,115,32,115,121,115,116,101,109,115,46,32,79,110,32,87,105,110,100,111,119,115,32,115,121,115,116,101,109,32,119,105,116,104,32,109,111,114,101,32,116,104,97,110,32,51,50,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,44,32,116,104,101,32,67,80,85,32,116,111,112,111,108,111,103,121,32,105,115,32,110,111,116,32,100,101,116,101,99,116,101,100,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,99,112,117,95,116,111,112,111,108,111,103,121,44,32,117,115,101,100,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<67,112,117,84,111,112,111,108,111,103,121>>]},<<32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,112,117,95,116,111,112,111,108,111,103,121>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>}],[]},{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,99,111,110,102,105,103,117,114,101,100,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,101,105,116,104,101,114,32,97,110,32,105,110,116,101,103,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,116,104,101,32,99,111,110,102,105,103,117,114,101,100,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>}],[]},{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,97,118,97,105,108,97,98,108,101,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,101,105,116,104,101,114,32,97,110,32,105,110,116,101,103,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,116,104,101,32,97,118,97,105,108,97,98,108,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46,32,84,104,101,32,110,117,109,98,101,114,32,111,102,32,97,118,97,105,108,97,98,108,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,105,115,32,108,101,115,115,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>}],[]},{code,[],[<<108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101,32,111,110,32,116,104,101,32,115,121,115,116,101,109,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,101,105,116,104,101,114,32,97,110,32,105,110,116,101,103,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101,46,32,84,104,101,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,111,110,108,105,110,101,32,105,115,32,108,101,115,115,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,99,111,110,102,105,103,117,114,101,100>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,113,117,111,116,97>>}],[]},{code,[],[<<99,112,117,95,113,117,111,116,97>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,116,101,99,116,101,100,32,67,80,85,32,113,117,111,116,97,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,108,105,109,105,116,101,100,32,98,121,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,115,97,121,105,110,103,32,104,111,119,32,109,97,110,121,32,112,114,111,99,101,115,115,111,114,115,39,32,119,111,114,116,104,32,111,102,32,114,117,110,116,105,109,101,32,119,101,32,103,101,116,32,40,98,101,116,119,101,101,110,32,49,32,97,110,100,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,41,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,107,110,111,119,110>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,99,97,110,110,111,116,32,100,101,116,101,99,116,32,97,32,113,117,111,116,97,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>}],[]},{code,[],[<<117,112,100,97,116,101,95,99,112,117,95,105,110,102,111>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,114,101,114,101,97,100,115,32,116,104,101,32,67,80,85,32,105,110,102,111,114,109,97,116,105,111,110,32,97,118,97,105,108,97,98,108,101,32,97,110,100,32,117,112,100,97,116,101,115,32,105,116,115,32,105,110,116,101,114,110,97,108,108,121,32,115,116,111,114,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,116,111,112,111,108,111,103,121,95,100,101,116,101,99,116,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,101,116,101,99,116,101,100,32,67,80,85,32,116,111,112,111,108,111,103,121>>]},<<32,97,110,100,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,110,102,105,103,117,114,101,100>>]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<111,110,108,105,110,101>>]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<97,118,97,105,108,97,98,108,101>>]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,99,112,117,95,113,117,111,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,112,117,32,113,117,111,116,97>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,67,80,85,32,105,110,102,111,114,109,97,116,105,111,110,32,104,97,115,32,99,104,97,110,103,101,100,32,115,105,110,99,101,32,116,104,101,32,108,97,115,116,32,116,105,109,101,32,105,116,32,119,97,115,32,114,101,97,100,44,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<99,104,97,110,103,101,100>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,99,104,97,110,103,101,100>>]},<<46,32,73,102,32,116,104,101,32,67,80,85,32,105,110,102,111,114,109,97,116,105,111,110,32,104,97,115,32,99,104,97,110,103,101,100,44,32,121,111,117,32,112,114,111,98,97,98,108,121,32,119,97,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<97,100,106,117,115,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101>>]},<<46,32,89,111,117,32,116,121,112,105,99,97,108,108,121,32,119,97,110,116,32,116,111,32,104,97,118,101,32,97,115,32,109,97,110,121,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,108,111,103,105,99,97,108,95,112,114,111,99,101,115,115,111,114,115,95,97,118,97,105,108,97,98,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,32,97,118,97,105,108,97,98,108,101>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,55,54,56>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2857,10},bounded_fun,[{type,{2857,10},'fun',[{type,{2857,10},product,[{atom,{2857,11},cpu_topology}]},{var,{2857,29},'CpuTopology'}]},[{type,{2858,7},constraint,[{atom,{2858,7},is_subtype},[{var,{2858,7},'CpuTopology'},{user_type,{2858,22},cpu_topology,[]}]]}]]},{type,{2859,10},bounded_fun,[{type,{2859,10},'fun',[{type,{2859,10},product,[{type,{2859,11},tuple,[{atom,{2859,12},cpu_topology},{type,{2859,26},union,[{atom,{2859,26},defined},{atom,{2859,36},detected},{atom,{2859,47},used}]}]}]},{var,{2859,57},'CpuTopology'}]},[{type,{2860,7},constraint,[{atom,{2860,7},is_subtype},[{var,{2860,7},'CpuTopology'},{user_type,{2860,22},cpu_topology,[]}]]}]]},{type,{2887,10},'fun',[{type,{2887,10},product,[{type,{2887,11},union,[{atom,{2887,11},logical_processors},{atom,{2888,11},logical_processors_available},{atom,{2889,11},logical_processors_online}]}]},{type,{2889,41},union,[{atom,{2889,41},unknown},{type,{2889,51},pos_integer,[]}]}]},{type,{2933,10},'fun',[{type,{2933,10},product,[{atom,{2933,11},update_cpu_info}]},{type,{2933,31},union,[{atom,{2933,31},changed},{atom,{2933,41},unchanged}]}]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{li,[{name,<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]}]},{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,100,101,102,97,117,108,116,32,112,114,111,99,101,115,115,32,104,101,97,112,32,115,101,116,116,105,110,103,115,58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>}],[]},{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,102,117,108,108,115,119,101,101,112,95,97,102,116,101,114,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32>>,{code,[],[<<102,117,108,108,115,119,101,101,112,95,97,102,116,101,114>>]},<<32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,101,116,116,105,110,103,32,117,115,101,100,32,98,121,32,100,101,102,97,117,108,116,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]},<<32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>}],[]},{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,100,101,102,97,117,108,116,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,101,116,116,105,110,103,115,46,32,65,32,112,114,111,99,101,115,115,32,115,112,97,119,110,101,100,32,111,110,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,98,121,32,97,32>>,{code,[],[<<115,112,97,119,110>>]},<<32,111,114,32>>,{code,[],[<<115,112,97,119,110,95,108,105,110,107>>]},<<32,117,115,101,115,32,116,104,101,115,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,115,101,116,116,105,110,103,115,46,32,84,104,101,32,100,101,102,97,117,108,116,32,115,101,116,116,105,110,103,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,47,50>>]}]},<<46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,47,50,44,51,44,52>>]}]},<<32,99,97,110,32,115,112,97,119,110,32,97,32,112,114,111,99,101,115,115,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,117,115,101,32,116,104,101,32,100,101,102,97,117,108,116,32,115,101,116,116,105,110,103,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,115,105,122,101,115>>}],[]},{code,[],[<<104,101,97,112,95,115,105,122,101,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,118,97,108,105,100,32,104,101,97,112,32,115,105,122,101,115,32,105,110,32,119,111,114,100,115,46,32,65,108,108,32,69,114,108,97,110,103,32,104,101,97,112,115,32,97,114,101,32,115,105,122,101,100,32,102,114,111,109,32,115,105,122,101,115,32,105,110,32,116,104,105,115,32,108,105,115,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,104,101,97,112,95,116,121,112,101>>}],[]},{code,[],[<<104,101,97,112,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,104,101,97,112,32,116,121,112,101,32,117,115,101,100,32,98,121,32,116,104,101,32,99,117,114,114,101,110,116,32,101,109,117,108,97,116,111,114,46,32,79,110,101,32,104,101,97,112,32,116,121,112,101,32,101,120,105,115,116,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<112,114,105,118,97,116,101>>]}]},{dd,[],[<<69,97,99,104,32,112,114,111,99,101,115,115,32,104,97,115,32,97,32,104,101,97,112,32,114,101,115,101,114,118,101,100,32,102,111,114,32,105,116,115,32,117,115,101,32,97,110,100,32,110,111,32,114,101,102,101,114,101,110,99,101,115,32,98,101,116,119,101,101,110,32,104,101,97,112,115,32,111,102,32,100,105,102,102,101,114,101,110,116,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,97,108,108,111,119,101,100,46,32,77,101,115,115,97,103,101,115,32,112,97,115,115,101,100,32,98,101,116,119,101,101,110,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,99,111,112,105,101,100,32,98,101,116,119,101,101,110,32,104,101,97,112,115,46>>]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,97,120,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,45,119,105,100,101,32,109,97,120,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,115,101,116,116,105,110,103,115,32,102,111,114,32,115,112,97,119,110,101,100,32,112,114,111,99,101,115,115,101,115,46,32,84,104,105,115,32,115,101,116,116,105,110,103,32,99,97,110,32,98,101,32,115,101,116,32,117,115,105,110,103,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120,107>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,97,120,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,97,120,101,108>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,73,116,32,99,97,110,32,97,108,115,111,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,114,117,110,116,105,109,101,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,97,98,111,117,116,32,116,104,101,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>}],[]},{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>]},<<32,112,114,111,99,101,115,115,32,102,108,97,103,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,101,105,116,104,101,114,32>>,{code,[],[<<111,102,102,95,104,101,97,112>>]},<<32,111,114,32>>,{code,[],[<<111,110,95,104,101,97,112>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,105,115,32,115,101,116,32,98,121,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,104,109,113,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,104,109,113,100>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<109,105,110,95,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,109,105,110,95,104,101,97,112,95,115,105,122,101,44,32,77,105,110,72,101,97,112,83,105,122,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,105,110,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,45,119,105,100,101,32,109,105,110,105,109,117,109,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,115,112,97,119,110,101,100,32,112,114,111,99,101,115,115,101,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,109,105,110,95,98,105,110,95,118,104,101,97,112,95,115,105,122,101,44,32,77,105,110,66,105,110,86,72,101,97,112,83,105,122,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<77,105,110,66,105,110,86,72,101,97,112,83,105,122,101>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,45,119,105,100,101,32,109,105,110,105,109,117,109,32,98,105,110,97,114,121,32,118,105,114,116,117,97,108,32,104,101,97,112,32,115,105,122,101,32,102,111,114,32,115,112,97,119,110,101,100,32,112,114,111,99,101,115,115,101,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,115>>}],[]},{code,[],[<<112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,112,114,111,99,101,115,115,32,97,110,100,32,112,111,114,116,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,57,57,51,51>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2880,10},'fun',[{type,{2880,10},product,[{atom,{2880,11},fullsweep_after}]},{type,{2880,31},tuple,[{atom,{2880,32},fullsweep_after},{type,{2880,49},non_neg_integer,[]}]}]},{type,{2881,10},'fun',[{type,{2881,10},product,[{atom,{2881,11},garbage_collection}]},{type,{2881,34},list,[{type,{2881,35},tuple,[{type,{2881,36},atom,[]},{type,{2881,44},integer,[]}]}]}]},{type,{2882,10},'fun',[{type,{2882,10},product,[{atom,{2882,11},heap_sizes}]},{type,{2882,26},list,[{type,{2882,27},non_neg_integer,[]}]}]},{type,{2883,10},'fun',[{type,{2883,10},product,[{atom,{2883,11},heap_type}]},{atom,{2883,25},private}]},{type,{2891,10},'fun',[{type,{2891,10},product,[{atom,{2891,11},max_heap_size}]},{type,{2891,29},tuple,[{atom,{2891,30},max_heap_size},{ann_type,{2891,45},[{var,{2891,45},'MaxHeapSize'},{user_type,{2891,60},max_heap_size,[]}]}]}]},{type,{2892,10},'fun',[{type,{2892,10},product,[{atom,{2892,11},message_queue_data}]},{user_type,{2892,34},message_queue_data,[]}]},{type,{2893,10},'fun',[{type,{2893,10},product,[{atom,{2893,11},min_heap_size}]},{type,{2893,29},tuple,[{atom,{2893,30},min_heap_size},{ann_type,{2893,45},[{var,{2893,45},'MinHeapSize'},{type,{2893,60},pos_integer,[]}]}]}]},{type,{2894,10},'fun',[{type,{2894,10},product,[{atom,{2894,11},min_bin_vheap_size}]},{type,{2894,34},tuple,[{atom,{2894,35},min_bin_vheap_size},{ann_type,{2895,35},[{var,{2895,35},'MinBinVHeapSize'},{type,{2895,54},pos_integer,[]}]}]}]},{type,{2909,10},'fun',[{type,{2909,10},product,[{atom,{2909,11},procs}]},{type,{2909,21},binary,[]}]}]}}],since => <<79,84,80,32,49,57,46,48,44,79,84,80,32,82,49,51,66,48,52>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,105,109,105,116,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,108,105,109,105,116,115,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,99,111,117,110,116>>}],[]},{code,[],[<<97,116,111,109,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,116,111,109,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,97,116,111,109,95,108,105,109,105,116>>}],[]},{code,[],[<<97,116,111,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,97,116,111,109,115,32,97,108,108,111,119,101,100,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,105,110,99,114,101,97,115,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,116>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,99,111,117,110,116>>}],[]},{code,[],[<<101,116,115,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,69,84,83,32,116,97,98,108,101,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,116,115,95,108,105,109,105,116>>}],[]},{code,[],[<<101,116,115,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,108,105,109,105,116,32,102,111,114,32,110,117,109,98,101,114,32,111,102,32,69,84,83,32,116,97,98,108,101,115,46,32,84,104,105,115,32,108,105,109,105,116,32,105,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,116,115,35,109,97,120,95,101,116,115,95,116,97,98,108,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,97,108,108,121,32,111,98,115,111,108,101,116,101>>]},<<32,97,110,100,32,110,117,109,98,101,114,32,111,102,32,116,97,98,108,101,115,32,97,114,101,32,111,110,108,121,32,108,105,109,105,116,101,100,32,98,121,32,97,118,97,105,108,97,98,108,101,32,109,101,109,111,114,121,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,99,111,117,110,116>>}],[]},{code,[],[<<112,111,114,116,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,111,114,116,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<108,101,110,103,116,104,40,101,114,108,97,110,103,58,112,111,114,116,115,40,41,41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,108,105,109,105,116>>}],[]},{code,[],[<<112,111,114,116,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,115,105,109,117,108,116,97,110,101,111,117,115,108,121,32,101,120,105,115,116,105,110,103,32,112,111,114,116,115,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,117,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,81>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,81>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,99,111,117,110,116>>}],[]},{code,[],[<<112,114,111,99,101,115,115,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<108,101,110,103,116,104,40,112,114,111,99,101,115,115,101,115,40,41,41>>]},<<44,32,98,117,116,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,114,111,99,101,115,115,95,108,105,109,105,116>>}],[]},{code,[],[<<112,114,111,99,101,115,115,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,115,105,109,117,108,116,97,110,101,111,117,115,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,116,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,117,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,80>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,80>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,48,53,49>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2850,10},'fun',[{type,{2850,10},product,[{atom,{2850,11},atom_count}]},{type,{2850,26},pos_integer,[]}]},{type,{2851,10},'fun',[{type,{2851,10},product,[{atom,{2851,11},atom_limit}]},{type,{2851,26},pos_integer,[]}]},{type,{2878,10},'fun',[{type,{2878,10},product,[{atom,{2878,11},ets_count}]},{type,{2878,25},pos_integer,[]}]},{type,{2879,10},'fun',[{type,{2879,10},product,[{atom,{2879,11},ets_limit}]},{type,{2879,25},pos_integer,[]}]},{type,{2905,10},'fun',[{type,{2905,10},product,[{atom,{2905,11},port_count}]},{type,{2905,26},non_neg_integer,[]}]},{type,{2906,10},'fun',[{type,{2906,10},product,[{atom,{2906,11},port_limit}]},{type,{2906,26},pos_integer,[]}]},{type,{2907,10},'fun',[{type,{2907,10},product,[{atom,{2907,11},process_count}]},{type,{2907,29},pos_integer,[]}]},{type,{2908,10},'fun',[{type,{2908,10},product,[{atom,{2908,11},process_limit}]},{type,{2908,29},pos_integer,[]}]}]}}],since => <<79,84,80,32,50,48,46,48,44,79,84,80,32,50,49,46,49,44,79,84,80,32,82,49,54,66,44,79,84,80,32,82,49,54,66,48,51>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,116,105,109,101,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>}],[]},{code,[],[<<101,110,100,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,105,110,116,101,114,110,97,108,108,121,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,84,104,101,32,116,105,109,101,32,98,101,116,119,101,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,116,97,114,116,32,116,105,109,101>>]},<<32,97,110,100,32,116,104,101,32,101,110,100,32,116,105,109,101,32,105,115,32,97,116,32,108,101,97,115,116,32,97,32,113,117,97,114,116,101,114,32,111,102,32,97,32,109,105,108,108,101,110,110,105,117,109,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>}],[]},{code,[],[<<111,115,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,115,111,117,114,99,101,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,116,104,97,116,32,105,115,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,110,111,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,115,32,97,118,97,105,108,97,98,108,101,46,32,84,104,101,32,108,105,115,116,32,99,111,110,116,97,105,110,115,32,116,119,111,45,116,117,112,108,101,115,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<115,32,97,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,97,110,100,32>>,{code,[],[<<86,97,108,117,101>>]},<<115,32,97,115,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,115,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,108,105,115,116,44,32,98,117,116,32,109,111,114,101,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,102,117,110,99,116,105,111,110,44,32,70,117,110,99,116,105,111,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,117,115,101,100,46,32,84,104,105,115,32,116,117,112,108,101,32,97,108,119,97,121,115,32,101,120,105,115,116,115,32,105,102,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,115,32,97,118,97,105,108,97,98,108,101,32,116,111,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]},{dt,[],[{code,[],[<<123,99,108,111,99,107,95,105,100,44,32,67,108,111,99,107,73,100,125>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,116,117,112,108,101,32,111,110,108,121,32,101,120,105,115,116,115,32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,100,105,102,102,101,114,101,110,116,32,99,108,111,99,107,115,46,32>>,{code,[],[<<67,108,111,99,107,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,99,108,111,99,107,32,105,100,101,110,116,105,102,105,101,114,32,117,115,101,100,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,115,111,108,117,116,105,111,110,44,32,79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110,125>>]}]},{dd,[],[{p,[],[<<72,105,103,104,101,115,116,32,112,111,115,115,105,98,108,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,82,101,115,111,108,117,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,115,111,108,117,116,105,111,110>>]},<<32,111,102,32,99,117,114,114,101,110,116,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,115,111,117,114,99,101,32,97,115,32,112,97,114,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,73,102,32,110,111,32,114,101,115,111,108,117,116,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,102,114,111,109,32,116,104,101,32,79,83,44,32>>,{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<32,105,115,32,115,101,116,32,116,111,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,111,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<115,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,97,99,116,117,97,108,32,114,101,115,111,108,117,116,105,111,110,32,99,97,110,32,98,101,32,108,111,119,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,100,111,101,115,32,110,111,116,32,115,97,121,32,97,110,121,116,104,105,110,103,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,65,99,99,117,114,97,99,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,99,99,117,114,97,99,121>>]},<<32,111,114,32,119,104,101,116,104,101,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,80,114,101,99,105,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,101,99,105,115,105,111,110>>]},<<32,97,108,105,103,110,115,32,119,105,116,104,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,46,32,89,111,117,32,100,111,44,32,104,111,119,101,118,101,114,44,32,107,110,111,119,32,116,104,97,116,32,116,104,101,32,112,114,101,99,105,115,105,111,110,32,105,115,32,110,111,116,32,98,101,116,116,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,120,116,101,110,100,101,100,44,32,69,120,116,101,110,100,101,100,125>>]}]},{dd,[],[{p,[],[{code,[],[<<69,120,116,101,110,100,101,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<121,101,115>>]},<<32,105,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,32,104,97,115,32,98,101,101,110,32,101,120,116,101,110,100,101,100,59,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<69,120,116,101,110,100,101,100>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<110,111>>]},<<46,32,84,104,101,32,114,97,110,103,101,32,109,117,115,116,32,98,101,32,101,120,116,101,110,100,101,100,32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,114,101,116,117,114,110,115,32,118,97,108,117,101,115,32,116,104,97,116,32,119,114,97,112,32,102,97,115,116,46,32,84,104,105,115,32,116,121,112,105,99,97,108,108,121,32,105,115,32,116,104,101,32,99,97,115,101,32,119,104,101,110,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,32,51,50,45,98,105,116,32,118,97,108,117,101,46>>]}]},{dt,[],[{code,[],[<<123,112,97,114,97,108,108,101,108,44,32,80,97,114,97,108,108,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<121,101,115>>]},<<32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,32,102,114,111,109,32,109,117,108,116,105,112,108,101,32,116,104,114,101,97,100,115,46,32,73,102,32,105,116,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,44,32,98,101,99,97,117,115,101,32,99,97,108,108,115,32,109,117,115,116,32,98,101,32,115,101,114,105,97,108,105,122,101,100,44,32>>,{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<110,111>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,105,109,101,44,32,79,115,77,111,110,111,116,111,110,105,99,84,105,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<79,115,77,111,110,111,116,111,110,105,99,84,105,109,101>>]},<<32,101,113,117,97,108,115,32,99,117,114,114,101,110,116,32,79,83,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46>>]}]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>}],[]},{code,[],[<<111,115,95,115,121,115,116,101,109,95,116,105,109,101,95,115,111,117,114,99,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,115,111,117,114,99,101,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,116,104,97,116,32,105,115,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<84,104,101,32,108,105,115,116,32,99,111,110,116,97,105,110,115,32,116,119,111,45,116,117,112,108,101,115,32,119,105,116,104,32>>,{code,[],[<<75,101,121>>]},<<115,32,97,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,97,110,100,32>>,{code,[],[<<86,97,108,117,101>>]},<<115,32,97,115,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,115,101,32,116,117,112,108,101,115,32,105,115,32,117,110,100,101,102,105,110,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,112,97,114,116,32,111,102,32,116,104,101,32,108,105,115,116,44,32,98,117,116,32,109,111,114,101,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,102,117,110,99,116,105,111,110,44,32,70,117,110,99,116,105,111,110,125>>]}]},{dd,[],[{p,[],[{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,117,115,101,100,46>>]}]},{dt,[],[{code,[],[<<123,99,108,111,99,107,95,105,100,44,32,67,108,111,99,107,73,100,125>>]}]},{dd,[],[{p,[],[<<69,120,105,115,116,115,32,111,110,108,121,32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,100,105,102,102,101,114,101,110,116,32,99,108,111,99,107,115,46,32>>,{code,[],[<<67,108,111,99,107,73,100>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,99,108,111,99,107,32,105,100,101,110,116,105,102,105,101,114,32,117,115,101,100,32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,114,101,115,111,108,117,116,105,111,110,44,32,79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110,125>>]}]},{dd,[],[{p,[],[<<72,105,103,104,101,115,116,32,112,111,115,115,105,98,108,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,82,101,115,111,108,117,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,115,111,108,117,116,105,111,110>>]},<<32,111,102,32,99,117,114,114,101,110,116,32,79,83,32,115,121,115,116,101,109,32,116,105,109,101,32,115,111,117,114,99,101,32,97,115,32,112,97,114,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,73,102,32,110,111,32,114,101,115,111,108,117,116,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,99,97,110,32,98,101,32,114,101,116,114,105,101,118,101,100,32,102,114,111,109,32,116,104,101,32,79,83,44,32>>,{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<32,105,115,32,115,101,116,32,116,111,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,111,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<115,32,114,101,116,117,114,110,32,118,97,108,117,101,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,97,99,116,117,97,108,32,114,101,115,111,108,117,116,105,111,110,32,99,97,110,32,98,101,32,108,111,119,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,100,111,101,115,32,110,111,116,32,115,97,121,32,97,110,121,116,104,105,110,103,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,65,99,99,117,114,97,99,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,99,99,117,114,97,99,121>>]},<<32,111,114,32,119,104,101,116,104,101,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,80,114,101,99,105,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,101,99,105,115,105,111,110>>]},<<32,100,111,32,97,108,105,103,110,32,119,105,116,104,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,46,32,89,111,117,32,100,111,44,32,104,111,119,101,118,101,114,44,32,107,110,111,119,32,116,104,97,116,32,116,104,101,32,112,114,101,99,105,115,105,111,110,32,105,115,32,110,111,116,32,98,101,116,116,101,114,32,116,104,97,110,32>>,{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101,82,101,115,111,108,117,116,105,111,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,112,97,114,97,108,108,101,108,44,32,80,97,114,97,108,108,101,108,125>>]}]},{dd,[],[{p,[],[{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<121,101,115>>]},<<32,105,102,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,115,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,32,102,114,111,109,32,109,117,108,116,105,112,108,101,32,116,104,114,101,97,100,115,46,32,73,102,32,105,116,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,105,110,32,112,97,114,97,108,108,101,108,44,32,98,101,99,97,117,115,101,32,99,97,108,108,115,32,110,101,101,100,115,32,116,111,32,98,101,32,115,101,114,105,97,108,105,122,101,100,44,32>>,{code,[],[<<80,97,114,97,108,108,101,108>>]},<<32,101,113,117,97,108,115,32>>,{code,[],[<<110,111>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,105,109,101,44,32,79,115,83,121,115,116,101,109,84,105,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<79,115,83,121,115,116,101,109,84,105,109,101>>]},<<32,101,113,117,97,108,115,32,99,117,114,114,101,110,116,32,79,83,32,115,121,115,116,101,109,32,116,105,109,101,32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46>>]}]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,116,97,114,116,95,116,105,109,101>>}],[]},{code,[],[<<115,116,97,114,116,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<32,97,116,32,116,104,101,32,116,105,109,101,32,119,104,101,110,32,99,117,114,114,101,110,116,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,32,115,116,97,114,116,101,100,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,110,100,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,101,110,100,95,116,105,109,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>}],[]},{code,[],[<<116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,111,111,108,101,97,110,32,118,97,108,117,101,32,105,110,100,105,99,97,116,105,110,103,32,119,104,101,116,104,101,114,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,67,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,99,111,114,114,101,99,116,105,111,110>>]},<<32,105,115,32,101,110,97,98,108,101,100,32,111,114,32,110,111,116,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,111,102,102,115,101,116>>}],[]},{code,[],[<<116,105,109,101,95,111,102,102,115,101,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,116,97,116,101,32,111,102,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,58>>]},{dl,[],[{dt,[],[{code,[],[<<112,114,101,108,105,109,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,112,114,101,108,105,109,105,110,97,114,121,44,32,97,110,100,32,119,105,108,108,32,98,101,32,99,104,97,110,103,101,100,32,97,110,100,32,102,105,110,97,108,105,122,101,100,32,108,97,116,101,114,46,32,84,104,101,32,112,114,101,108,105,109,105,110,97,114,121,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,117,115,101,100,32,100,117,114,105,110,103,32,116,104,101,32,112,114,101,108,105,109,105,110,97,114,121,32,112,104,97,115,101,32,111,102,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<102,105,110,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,102,105,110,97,108,46,32,84,104,105,115,32,101,105,116,104,101,114,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,78,111,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,44,32,111,114,32,98,101,99,97,117,115,101,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,104,97,118,101,32,98,101,101,110,32,102,105,110,97,108,105,122,101,100,32,119,104,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]},{dt,[],[{code,[],[<<118,111,108,97,116,105,108,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,118,111,108,97,116,105,108,101,46,32,84,104,97,116,32,105,115,44,32,105,116,32,99,97,110,32,99,104,97,110,103,101,32,97,116,32,97,110,121,32,116,105,109,101,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,119,97,114,112,95,109,111,100,101>>}],[]},{code,[],[<<116,105,109,101,95,119,97,114,112,95,109,111,100,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,118,97,108,117,101,32,105,100,101,110,116,105,102,121,105,110,103,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,116,104,97,116,32,105,115,32,117,115,101,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<110,111,95,116,105,109,101,95,119,97,114,112>>]}]},{dd,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,78,111,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]},{dt,[],[{code,[],[<<115,105,110,103,108,101,95,116,105,109,101,95,119,97,114,112>>]}]},{dd,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,105,110,103,108,101,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,105,110,103,108,101,32,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]},{dt,[],[{code,[],[<<109,117,108,116,105,95,116,105,109,101,95,119,97,114,112>>]}]},{dd,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,105,115,32,117,115,101,100,46>>]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>}],[]},{code,[],[<<116,111,108,101,114,97,110,116,95,116,105,109,101,111,102,100,97,121>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,119,104,101,116,104,101,114,32,97,32,112,114,101,32,69,82,84,83,32,55,46,48,32,98,97,99,107,119,97,114,100,115,32,99,111,109,112,97,116,105,98,108,101,32,99,111,109,112,101,110,115,97,116,105,111,110,32,102,111,114,32,115,117,100,100,101,110,32,99,104,97,110,103,101,115,32,111,102,32,115,121,115,116,101,109,32,116,105,109,101,32,105,115,32>>,{code,[],[<<101,110,97,98,108,101,100>>]},<<32,111,114,32>>,{code,[],[<<100,105,115,97,98,108,101,100>>]},<<46,32,83,117,99,104,32,99,111,109,112,101,110,115,97,116,105,111,110,32,105,115,32>>,{code,[],[<<101,110,97,98,108,101,100>>]},<<32,119,104,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,111,102,102,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,111,102,102,115,101,116>>]},<<32,105,115,32>>,{code,[],[<<102,105,110,97,108>>]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,99,111,114,114,101,99,116,105,111,110>>]},<<32,105,115,32,101,110,97,98,108,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,49,51,49>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2877,10},'fun',[{type,{2877,10},product,[{atom,{2877,11},end_time}]},{type,{2877,24},non_neg_integer,[]}]},{type,{2902,10},'fun',[{type,{2902,10},product,[{atom,{2902,11},os_monotonic_time_source}]},{type,{2902,40},list,[{type,{2902,41},tuple,[{type,{2902,42},atom,[]},{type,{2902,49},term,[]}]}]}]},{type,{2903,10},'fun',[{type,{2903,10},product,[{atom,{2903,11},os_system_time_source}]},{type,{2903,37},list,[{type,{2903,38},tuple,[{type,{2903,39},atom,[]},{type,{2903,46},term,[]}]}]}]},{type,{2922,10},'fun',[{type,{2922,10},product,[{atom,{2922,11},start_time}]},{type,{2922,26},integer,[]}]},{type,{2928,10},'fun',[{type,{2928,10},product,[{atom,{2928,11},time_correction}]},{type,{2928,31},union,[{atom,{2928,31},true},{atom,{2928,38},false}]}]},{type,{2929,10},'fun',[{type,{2929,10},product,[{atom,{2929,11},time_offset}]},{type,{2929,27},union,[{atom,{2929,27},preliminary},{atom,{2929,41},final},{atom,{2929,49},volatile}]}]},{type,{2930,10},'fun',[{type,{2930,10},product,[{atom,{2930,11},time_warp_mode}]},{type,{2930,30},union,[{atom,{2930,30},no_time_warp},{atom,{2930,45},single_time_warp},{atom,{2930,64},multi_time_warp}]}]},{type,{2931,10},'fun',[{type,{2931,10},product,[{atom,{2931,11},tolerant_timeofday}]},{type,{2931,34},union,[{atom,{2931,34},enabled},{atom,{2931,44},disabled}]}]}]}}],since => <<79,84,80,32,49,55,46,49,44,79,84,80,32,49,56,46,48>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,115,99,104,101,100,117,108,101,114,115,44,32,115,99,104,101,100,117,108,105,110,103,32,97,110,100,32,116,104,114,101,97,100,115,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>}],[]},{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,68,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,101,120,101,99,117,116,101,32,67,80,85,45,98,111,117,110,100,32,110,97,116,105,118,101,32,102,117,110,99,116,105,111,110,115,44,32,115,117,99,104,32,97,115,32,78,73,70,115,44,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,99,111,100,101,44,32,97,110,100,32,66,73,70,115,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,109,97,110,97,103,101,100,32,99,108,101,97,110,108,121,32,98,121,32,116,104,101,32,110,111,114,109,97,108,32,101,109,117,108,97,116,111,114,32,115,99,104,101,100,117,108,101,114,115,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,32,97,110,100,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,97,102,116,101,114,32,116,104,97,116,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,46,32,84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,99,112,117>>]}]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,80,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,80,99,112,117>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>}],[]},{code,[],[<<100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,115,97,116,105,115,102,105,101,115,32>>,{code,[],[<<49,32,60,61,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,32,60,61,32,78>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]},<<32,97,110,100,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]},<<46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,67,80,85,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,99,112,117>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,99,112,117>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>}],[]},{code,[],[<<100,105,114,116,121,95,105,111,95,115,99,104,101,100,117,108,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,68,105,114,116,121,32,73,47,79,32,115,99,104,101,100,117,108,101,114,115,32,101,120,101,99,117,116,101,32,73,47,79,45,98,111,117,110,100,32,110,97,116,105,118,101,32,102,117,110,99,116,105,111,110,115,44,32,115,117,99,104,32,97,115,32,78,73,70,115,32,97,110,100,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,99,111,100,101,44,32,119,104,105,99,104,32,99,97,110,110,111,116,32,98,101,32,109,97,110,97,103,101,100,32,99,108,101,97,110,108,121,32,98,121,32,116,104,101,32,110,111,114,109,97,108,32,101,109,117,108,97,116,111,114,32,115,99,104,101,100,117,108,101,114,115,46>>]},{p,[],[<<84,104,105,115,32,118,97,108,117,101,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,83,68,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,83,68,105,111>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,100,105,114,116,121,95,99,112,117,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,68,105,114,116,121,67,80,85,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>}],[]},{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<100,105,115,97,98,108,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,98,101,101,110,32,115,116,97,114,116,101,100,32,119,105,116,104,32,111,110,108,121,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<98,108,111,99,107,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,44,32,98,117,116,32,97,108,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,101,120,99,101,112,116,32,111,110,101,32,97,114,101,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,111,110,108,121,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,115,99,104,101,100,117,108,101,115,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,101,120,101,99,117,116,101,115,32,69,114,108,97,110,103,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<98,108,111,99,107,101,100,95,110,111,114,109,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,44,32,98,117,116,32,97,108,108,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,101,120,99,101,112,116,32,111,110,101,32,97,114,101,32,98,108,111,99,107,101,100,46,32,78,111,116,105,99,101,32,116,104,97,116,32,100,105,114,116,121,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,110,111,116,32,98,108,111,99,107,101,100,44,32,97,110,100,32,99,97,110,32,115,99,104,101,100,117,108,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,101,120,101,99,117,116,101,32,110,97,116,105,118,101,32,99,111,100,101,46>>]}]},{dt,[],[{code,[],[<<101,110,97,98,108,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,44,32,97,110,100,32,110,111,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,97,114,101,32,98,108,111,99,107,101,100,46,32,84,104,97,116,32,105,115,44,32,97,108,108,32,97,118,97,105,108,97,98,108,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,115,99,104,101,100,117,108,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,101,120,101,99,117,116,101,32,69,114,108,97,110,103,32,99,111,100,101,46>>]}]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>}],[]},{code,[],[<<109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<115,32,119,104,101,110,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32>>,{code,[],[<<80,105,100>>]},<<115,32,105,110,32,116,104,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,98,108,111,99,107,105,110,103,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,46,32,65,32>>,{code,[],[<<80,105,100>>]},<<32,111,99,99,117,114,115,32,111,110,108,121,32,111,110,99,101,32,105,110,32,116,104,101,32,108,105,115,116,44,32,101,118,101,110,32,105,102,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>}],[]},{code,[],[<<110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32>>,{code,[],[<<80,105,100>>]},<<115,32,119,104,101,110,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,32,105,115,32,98,108,111,99,107,101,100,32,40,116,104,97,116,32,105,115,44,32,97,108,108,32,110,111,114,109,97,108,32,115,99,104,101,100,117,108,101,114,115,32,98,117,116,32,111,110,101,32,105,115,32,98,108,111,99,107,101,100,41,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32>>,{code,[],[<<80,105,100>>]},<<115,32,105,110,32,116,104,101,32,108,105,115,116,32,114,101,112,114,101,115,101,110,116,32,97,108,108,32,116,104,101,32,112,114,111,99,101,115,115,101,115,32,99,117,114,114,101,110,116,108,121,32,98,108,111,99,107,105,110,103,32,110,111,114,109,97,108,32,109,117,108,116,105,45,115,99,104,101,100,117,108,105,110,103,46,32,65,32>>,{code,[],[<<80,105,100>>]},<<32,111,99,99,117,114,115,32,111,110,108,121,32,111,110,99,101,32,105,110,32,116,104,101,32,108,105,115,116,44,32,101,118,101,110,32,105,102,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,112,114,111,99,101,115,115,32,104,97,115,32,98,108,111,99,107,101,100,32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,104,111,119,32,116,104,101,32,117,115,101,114,32,104,97,115,32,114,101,113,117,101,115,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,98,101,32,98,111,117,110,100,32,111,114,32,110,111,116,32,98,111,117,110,100,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,108,116,104,111,117,103,104,32,97,32,117,115,101,114,32,104,97,115,32,114,101,113,117,101,115,116,101,100,32,115,99,104,101,100,117,108,101,114,115,32,116,111,32,98,101,32,98,111,117,110,100,44,32,116,104,101,121,32,99,97,110,32,115,105,108,101,110,116,108,121,32,104,97,118,101,32,102,97,105,108,101,100,32,116,111,32,98,105,110,100,46,32,84,111,32,105,110,115,112,101,99,116,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,105,110,103,115,44,32,99,97,108,108,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,108,121,32,117,115,101,100,32,115,99,104,101,100,117,108,101,114,32,98,105,110,100,105,110,103,115,46>>]},{p,[],[<<65,32,116,117,112,108,101,32,111,102,32,97,32,115,105,122,101,32,101,113,117,97,108,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,116,117,112,108,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,105,110,116,101,103,101,114,115,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,98,111,117,110,100>>]},<<46,32,76,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,115,32,97,114,101,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32,105,110,116,101,103,101,114,115,46,32,84,104,101,32>>,{code,[],[<<78>>]},<<116,104,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,116,117,112,108,101,32,101,113,117,97,108,115,32,116,104,101,32,99,117,114,114,101,110,116,32,98,105,110,100,105,110,103,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,119,105,116,104,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,32,101,113,117,97,108,32,116,111,32>>,{code,[],[<<78>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,116,104,101,32,115,99,104,101,100,117,108,101,114,115,32,97,114,101,32,98,111,117,110,100,44,32>>,{code,[],[<<101,108,101,109,101,110,116,40,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,105,100,41,44,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,98,105,110,100,105,110,103,115,41,41>>]},<<32,114,101,116,117,114,110,115,32,116,104,101,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,111,110,108,121,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,98,111,117,110,100,32,116,111,32,108,111,103,105,99,97,108,32,112,114,111,99,101,115,115,111,114,115,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,98,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,98,116>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,105,100>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,95,105,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,73,68,32,40>>,{code,[],[<<83,99,104,101,100,117,108,101,114,73,100>>]},<<41,32,111,102,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{code,[],[<<83,99,104,101,100,117,108,101,114,73,100>>]},<<32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,44,32,119,104,101,114,101,32>>,{code,[],[<<49,32,60,61,32,83,99,104,101,100,117,108,101,114,73,100,32,60,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,117,115,101,100,32,98,121,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,83,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,111,110,108,105,110,101,32,115,99,104,101,100,117,108,101,115,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,69,114,108,97,110,103,32,112,111,114,116,115,44,32,97,110,100,32,101,120,101,99,117,116,101,32,69,114,108,97,110,103,32,99,111,100,101,32,97,110,100,32,69,114,108,97,110,103,32,108,105,110,107,101,100,45,105,110,32,100,114,105,118,101,114,32,99,111,100,101,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,32,116,104,114,101,97,100,115,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,101,109,117,108,97,116,111,114,32,98,111,111,116,32,116,105,109,101,32,97,110,100,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,108,97,116,101,114,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,95,105,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,95,105,100,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,44,32,66,108,111,99,107,83,116,97,116,101,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,41>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,110,111,114,109,97,108,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,109,117,108,116,105,95,115,99,104,101,100,117,108,105,110,103,95,98,108,111,99,107,101,114,115,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>}],[]},{code,[],[<<115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,46,32,84,104,101,32,115,99,104,101,100,117,108,101,114,32,105,100,101,110,116,105,102,105,101,114,115,32,111,102,32,115,99,104,101,100,117,108,101,114,115,32,111,110,108,105,110,101,32,115,97,116,105,115,102,121,32,116,104,101,32,114,101,108,97,116,105,111,110,115,104,105,112,32>>,{code,[],[<<49,32,60,61,32,83,99,104,101,100,117,108,101,114,73,100,32,60,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,41>>]},<<46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,115,99,104,101,100,117,108,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,115,99,104,101,100,117,108,101,114,115,41>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,95,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,99,104,101,100,117,108,101,114,115,95,111,110,108,105,110,101,44,32,83,99,104,101,100,117,108,101,114,115,79,110,108,105,110,101,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,109,112,95,115,117,112,112,111,114,116>>}],[]},{code,[],[<<115,109,112,95,115,117,112,112,111,114,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,115>>}],[]},{code,[],[<<116,104,114,101,97,100,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>}],[]},{code,[],[<<116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,104,114,101,97,100,95,112,111,111,108,95,115,105,122,101>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,115,121,110,99,32,116,104,114,101,97,100,115,32,105,110,32,116,104,101,32,97,115,121,110,99,32,116,104,114,101,97,100,32,112,111,111,108,32,117,115,101,100,32,102,111,114,32,97,115,121,110,99,104,114,111,110,111,117,115,32,100,114,105,118,101,114,32,99,97,108,108,115,32,40>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,114,105,118,101,114,35,100,114,105,118,101,114,95,97,115,121,110,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<32>>,{code,[],[<<101,114,108,95,100,114,105,118,101,114,58,100,114,105,118,101,114,95,97,115,121,110,99,40,41>>]}]},<<41,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,51,53,57>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2864,10},'fun',[{type,{2864,10},product,[{atom,{2864,11},dirty_cpu_schedulers}]},{type,{2864,36},non_neg_integer,[]}]},{type,{2865,10},'fun',[{type,{2865,10},product,[{atom,{2865,11},dirty_cpu_schedulers_online}]},{type,{2865,43},non_neg_integer,[]}]},{type,{2866,10},'fun',[{type,{2866,10},product,[{atom,{2866,11},dirty_io_schedulers}]},{type,{2866,35},non_neg_integer,[]}]},{type,{2897,10},'fun',[{type,{2897,10},product,[{atom,{2897,11},multi_scheduling}]},{type,{2897,32},union,[{atom,{2897,32},disabled},{atom,{2897,43},blocked},{atom,{2897,53},blocked_normal},{atom,{2897,70},enabled}]}]},{type,{2898,10},'fun',[{type,{2898,10},product,[{atom,{2898,11},multi_scheduling_blockers}]},{type,{2898,41},list,[{ann_type,{2898,42},[{var,{2898,42},'Pid'},{type,{2898,49},pid,[]}]}]}]},{type,{2900,10},'fun',[{type,{2900,10},product,[{atom,{2900,11},normal_multi_scheduling_blockers}]},{type,{2900,48},list,[{ann_type,{2900,49},[{var,{2900,49},'Pid'},{type,{2900,56},pid,[]}]}]}]},{type,{2910,10},'fun',[{type,{2910,10},product,[{atom,{2910,11},scheduler_bind_type}]},{type,{2910,35},union,[{atom,{2910,35},spread},{atom,{2911,35},processor_spread},{atom,{2912,35},thread_spread},{atom,{2913,35},thread_no_node_processor_spread},{atom,{2914,35},no_node_processor_spread},{atom,{2915,35},no_node_thread_spread},{atom,{2916,35},no_spread},{atom,{2917,35},unbound}]}]},{type,{2918,10},'fun',[{type,{2918,10},product,[{atom,{2918,11},scheduler_bindings}]},{type,{2918,35},tuple,any}]},{type,{2919,10},'fun',[{type,{2919,10},product,[{atom,{2919,11},scheduler_id}]},{ann_type,{2919,28},[{var,{2919,28},'SchedulerId'},{type,{2919,43},pos_integer,[]}]}]},{type,{2920,10},'fun',[{type,{2920,10},product,[{type,{2920,11},union,[{atom,{2920,11},schedulers},{atom,{2920,24},schedulers_online}]}]},{type,{2920,46},pos_integer,[]}]},{type,{2921,10},'fun',[{type,{2921,10},product,[{atom,{2921,11},smp_support}]},{type,{2921,27},boolean,[]}]},{type,{2926,10},'fun',[{type,{2926,10},product,[{atom,{2926,11},threads}]},{type,{2926,23},boolean,[]}]},{type,{2927,10},'fun',[{type,{2927,10},product,[{atom,{2927,11},thread_pool_size}]},{type,{2927,32},non_neg_integer,[]}]}]}}],since => <<79,84,80,32,49,55,46,48,44,79,84,80,32,49,57,46,48>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,69,114,108,97,110,103,32,68,105,115,116,114,105,98,117,116,105,111,110,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,114,101,97,116,105,111,110>>}],[]},{code,[],[<<99,114,101,97,116,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,114,101,97,116,105,111,110,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,101,32,99,114,101,97,116,105,111,110,32,105,115,32,99,104,97,110,103,101,100,32,119,104,101,110,32,97,32,110,111,100,101,32,105,115,32,114,101,115,116,97,114,116,101,100,46,32,84,104,101,32,99,114,101,97,116,105,111,110,32,111,102,32,97,32,110,111,100,101,32,105,115,32,115,116,111,114,101,100,32,105,110,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,115,44,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,115,44,32,97,110,100,32,114,101,102,101,114,101,110,99,101,115,46,32,84,104,105,115,32,109,97,107,101,115,32,105,116,32,40,116,111,32,115,111,109,101,32,101,120,116,101,110,116,41,32,112,111,115,115,105,98,108,101,32,116,111,32,100,105,115,116,105,110,103,117,105,115,104,32,98,101,116,119,101,101,110,32,105,100,101,110,116,105,102,105,101,114,115,32,102,114,111,109,32,100,105,102,102,101,114,101,110,116,32,105,110,99,97,114,110,97,116,105,111,110,115,32,111,102,32,97,32,110,111,100,101,46,32,84,104,101,32,118,97,108,105,100,32,99,114,101,97,116,105,111,110,115,32,97,114,101,32,105,110,116,101,103,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,49,46,46,51,44,32,98,117,116,32,116,104,105,115,32,119,105,108,108,32,112,114,111,98,97,98,108,121,32,99,104,97,110,103,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,73,102,32,116,104,101,32,110,111,100,101,32,105,115,32,110,111,116,32,97,108,105,118,101,44,32>>,{code,[],[<<48>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>}],[]},{code,[],[<<100,101,108,97,121,101,100,95,110,111,100,101,95,116,97,98,108,101,95,103,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,116,105,109,101,32,105,110,32,115,101,99,111,110,100,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,97,110,32,101,110,116,114,121,32,105,110,32,97,32,110,111,100,101,32,116,97,98,108,101,32,105,115,32,100,101,108,97,121,101,100,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,115,101,116,32,111,110,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,122,100,110,116,103,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,122,100,110,116,103,99>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116>>}],[]},{code,[],[<<100,105,115,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,100,105,115,116,114,105,98,117,116,105,111,110,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>}],[]},{code,[],[<<100,105,115,116,95,98,117,102,95,98,117,115,121,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,100,105,115,116,114,105,98,117,116,105,111,110,32,98,117,102,102,101,114,32,98,117,115,121,32,108,105,109,105,116,32,105,110,32,98,121,116,101,115,46,32,84,104,105,115,32,108,105,109,105,116,32,99,97,110,32,98,101,32,115,101,116,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,112,97,115,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,122,100,98,98,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,122,100,98,98,108>>]}]},<<32,116,111,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,105,115,116,95,99,116,114,108>>}],[]},{code,[],[<<100,105,115,116,95,99,116,114,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,116,117,112,108,101,115,32>>,{code,[],[<<123,78,111,100,101,44,32,67,111,110,116,114,111,108,108,105,110,103,69,110,116,105,116,121,125>>]},<<44,32,111,110,101,32,101,110,116,114,121,32,102,111,114,32,101,97,99,104,32,99,111,110,110,101,99,116,101,100,32,114,101,109,111,116,101,32,110,111,100,101,46,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,116,104,101,32,110,111,100,101,32,110,97,109,101,32,97,110,100,32>>,{code,[],[<<67,111,110,116,114,111,108,108,105,110,103,69,110,116,105,116,121>>]},<<32,105,115,32,116,104,101,32,112,111,114,116,32,111,114,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,116,104,101,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,116,111,32,116,104,97,116,32,110,111,100,101,46,32,77,111,114,101,32,115,112,101,99,105,102,105,99,97,108,108,121,44,32>>,{code,[],[<<67,111,110,116,114,111,108,108,105,110,103,69,110,116,105,116,121>>]},<<32,102,111,114,32,110,111,100,101,115,32,99,111,110,110,101,99,116,101,100,32,116,104,114,111,117,103,104,32,84,67,80,47,73,80,32,40,116,104,101,32,110,111,114,109,97,108,32,99,97,115,101,41,32,105,115,32,116,104,101,32,115,111,99,107,101,116,32,117,115,101,100,32,105,110,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,99,32,110,111,100,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,54,53,57>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2861,10},'fun',[{type,{2861,10},product,[{atom,{2861,11},creation}]},{type,{2861,24},integer,[]}]},{type,{2863,10},'fun',[{type,{2863,10},product,[{atom,{2863,11},delayed_node_table_gc}]},{type,{2863,37},union,[{atom,{2863,37},infinity},{type,{2863,48},non_neg_integer,[]}]}]},{type,{2867,10},'fun',[{type,{2867,10},product,[{atom,{2867,11},dist}]},{type,{2867,20},binary,[]}]},{type,{2868,10},'fun',[{type,{2868,10},product,[{atom,{2868,11},dist_buf_busy_limit}]},{type,{2868,35},non_neg_integer,[]}]},{type,{2869,10},'fun',[{type,{2869,10},product,[{atom,{2869,11},dist_ctrl}]},{type,{2869,25},tuple,[{ann_type,{2869,26},[{var,{2869,26},'Node'},{type,{2869,34},node,[]}]},{ann_type,{2870,26},[{var,{2870,26},'ControllingEntity'},{type,{2870,47},union,[{type,{2870,47},port,[]},{type,{2870,56},pid,[]}]}]}]}]}]}}],since => <<79,84,80,32,49,56,46,48,44,79,84,80,32,82,49,52,66,48,49>>}},{{function,system_info,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2834}],[<<115,121,115,116,101,109,95,105,110,102,111,47,49>>],#{<<101,110>> => [{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,105,115,99,95,116,97,103,115>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,118,97,114,105,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,40,101,109,117,108,97,116,111,114,41,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,116,101,109>>]},<<58>>]},{dl,[],[{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,98,117,105,108,100,95,116,121,112,101>>}],[]},{code,[],[<<98,117,105,108,100,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<68,101,112,114,101,99,97,116,101,100,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,109,117,95,116,121,112,101>>]},<<32,105,110,115,116,101,97,100>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>}],[]},{code,[],[<<99,95,99,111,109,112,105,108,101,114,95,117,115,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,119,111,45,116,117,112,108,101,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,67,32,99,111,109,112,105,108,101,114,32,117,115,101,100,32,119,104,101,110,32,99,111,109,112,105,108,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,99,111,109,112,105,108,101,114,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,117,110,107,110,111,119,110,46,32,84,104,101,32,115,101,99,111,110,100,32,101,108,101,109,101,110,116,32,105,115,32,97,32,116,101,114,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,99,111,109,112,105,108,101,114,44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,117,110,107,110,111,119,110,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,104,101,99,107,95,105,111>>}],[]},{code,[],[<<99,104,101,99,107,95,105,111>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,101,109,117,108,97,116,111,114,115,32,105,110,116,101,114,110,97,108,32,73,47,79,32,99,104,101,99,107,105,110,103,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,32,99,97,110,32,118,97,114,121,32,98,101,116,119,101,101,110,32,112,108,97,116,102,111,114,109,115,32,97,110,100,32,111,118,101,114,32,116,105,109,101,46,32,73,116,32,105,115,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,97,32,108,105,115,116,32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,99,111,109,112,97,116,95,114,101,108>>}],[]},{code,[],[<<99,111,109,112,97,116,95,114,101,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,109,111,100,101,32,111,102,32,116,104,101,32,108,111,99,97,108,32,110,111,100,101,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,84,104,101,32,105,110,116,101,103,101,114,32,114,101,116,117,114,110,101,100,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,69,114,108,97,110,103,47,79,84,80,32,114,101,108,101,97,115,101,32,116,104,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,101,109,117,108,97,116,111,114,32,104,97,115,32,98,101,101,110,32,115,101,116,32,116,111,32,98,101,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,46,32,84,104,101,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,109,111,100,101,32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,97,116,32,115,116,97,114,116,117,112,32,98,121,32,117,115,105,110,103,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,99,111,109,112,97,116,95,114,101,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,82>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,101,98,117,103,95,99,111,109,112,105,108,101,100>>}],[]},{code,[],[<<100,101,98,117,103,95,99,111,109,112,105,108,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,104,97,115,32,98,101,101,110,32,100,101,98,117,103,45,99,111,109,112,105,108,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,114,105,118,101,114,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<100,114,105,118,101,114,95,118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,100,114,105,118,101,114,32,118,101,114,115,105,111,110,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,73,116,32,104,97,115,32,116,104,101,32,102,111,114,109,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,114,105,118,101,114,35,118,101,114,115,105,111,110,95,109,97,110,97,103,101,109,101,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<34,60,109,97,106,111,114,32,118,101,114,62,46,60,109,105,110,111,114,32,118,101,114,62,34>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101>>}],[]},{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,100,121,110,97,109,105,99,32,116,114,97,99,101,32,102,114,97,109,101,119,111,114,107,32,99,111,109,112,105,108,101,100,32,105,110,116,111,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,46,32,73,116,32,99,97,110,32,98,101,32>>,{code,[],[<<100,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<115,121,115,116,101,109,116,97,112>>]},<<44,32,111,114,32>>,{code,[],[<<110,111,110,101>>]},<<46,32,70,111,114,32,97,32,99,111,109,109,101,114,99,105,97,108,32,111,114,32,115,116,97,110,100,97,114,100,32,98,117,105,108,100,44,32,105,116,32,105,115,32,97,108,119,97,121,115,32>>,{code,[],[<<110,111,110,101>>]},<<46,32,84,104,101,32,111,116,104,101,114,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,105,110,100,105,99,97,116,101,32,97,32,99,117,115,116,111,109,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<46,47,99,111,110,102,105,103,117,114,101,32,45,45,119,105,116,104,45,100,121,110,97,109,105,99,45,116,114,97,99,101,61,100,116,114,97,99,101>>]},<<41,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,100,121,110,97,109,105,99,32,116,114,97,99,105,110,103,44,32,115,101,101,32>>,{a,[{href,<<114,117,110,116,105,109,101,95,116,111,111,108,115,58,100,121,110,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,121,110,116,114,97,99,101,40,51,41>>]}]},<<32,109,97,110,117,97,108,32,112,97,103,101,32,97,110,100,32,116,104,101,32>>,{code,[],[<<82,69,65,68,77,69,46,100,116,114,97,99,101>>]},<<47>>,{code,[],[<<82,69,65,68,77,69,46,115,121,115,116,101,109,116,97,112>>]},<<32,102,105,108,101,115,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,115,111,117,114,99,101,32,99,111,100,101,32,116,111,112,32,100,105,114,101,99,116,111,114,121,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>}],[]},{code,[],[<<100,121,110,97,109,105,99,95,116,114,97,99,101,95,112,114,111,98,101,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32>>,{code,[],[<<98,111,111,108,101,97,110,40,41>>]},<<32,105,110,100,105,99,97,116,105,110,103,32,105,102,32,100,121,110,97,109,105,99,32,116,114,97,99,101,32,112,114,111,98,101,115,32,40>>,{code,[],[<<100,116,114,97,99,101>>]},<<32,111,114,32>>,{code,[],[<<115,121,115,116,101,109,116,97,112>>]},<<41,32,97,114,101,32,98,117,105,108,116,32,105,110,116,111,32,116,104,101,32,101,109,117,108,97,116,111,114,46,32,84,104,105,115,32,99,97,110,32,111,110,108,121,32,98,101,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,32,119,97,115,32,98,117,105,108,116,32,102,111,114,32,100,121,110,97,109,105,99,32,116,114,97,99,105,110,103,32,40,116,104,97,116,32,105,115,44,32>>,{code,[],[<<115,121,115,116,101,109,95,105,110,102,111,40,100,121,110,97,109,105,99,95,116,114,97,99,101,41>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<100,116,114,97,99,101>>]},<<32,111,114,32>>,{code,[],[<<115,121,115,116,101,109,116,97,112>>]},<<41,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,102,108,97,118,111,114>>}],[]},{code,[],[<<101,109,117,95,102,108,97,118,111,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,102,108,97,118,111,114,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,105,115,32,119,105,108,108,32,98,101,32,101,105,116,104,101,114,32>>,{code,[],[<<101,109,117>>]},<<32,111,114,32>>,{code,[],[<<106,105,116>>]},<<46,32,80,111,115,115,105,98,108,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,111,114,32,114,101,109,111,118,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,101,109,117,95,116,121,112,101>>}],[]},{code,[],[<<101,109,117,95,116,121,112,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,98,117,105,108,100,32,116,121,112,101,32,111,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,84,104,105,115,32,105,115,32,110,111,114,109,97,108,108,121,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,112,116>>]},<<32,102,111,114,32,111,112,116,105,109,105,122,101,100,46,32,79,116,104,101,114,32,112,111,115,115,105,98,108,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,97,114,101,32>>,{code,[],[<<100,101,98,117,103>>]},<<44,32>>,{code,[],[<<103,99,111,118>>]},<<44,32>>,{code,[],[<<118,97,108,103,114,105,110,100>>]},<<44,32>>,{code,[],[<<103,112,114,111,102>>]},<<44,32,97,110,100,32>>,{code,[],[<<108,99,110,116>>]},<<46,32,80,111,115,115,105,98,108,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,111,114,32,114,101,109,111,118,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,105,110,102,111>>}],[]},{code,[],[<<105,110,102,111>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,109,105,115,99,101,108,108,97,110,101,111,117,115,32,115,121,115,116,101,109,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,107,101,114,110,101,108,95,112,111,108,108>>}],[]},{code,[],[<<107,101,114,110,101,108,95,112,111,108,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,101,109,117,108,97,116,111,114,32,117,115,101,115,32,115,111,109,101,32,107,105,110,100,32,111,102,32,107,101,114,110,101,108,45,112,111,108,108,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,108,111,97,100,101,100>>}],[]},{code,[],[<<108,111,97,100,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,99,111,110,116,97,105,110,105,110,103,32,97,32,115,116,114,105,110,103,32,111,102,32,108,111,97,100,101,100,32,109,111,100,117,108,101,32,105,110,102,111,114,109,97,116,105,111,110,32,102,111,114,109,97,116,116,101,100,32,97,115,32,105,110,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,99,114,97,115,104,95,100,117,109,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<72,111,119,32,116,111,32,105,110,116,101,114,112,114,101,116,32,116,104,101,32,69,114,108,97,110,103,32,99,114,97,115,104,32,100,117,109,112,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,97,99,104,105,110,101>>}],[]},{code,[],[<<109,97,99,104,105,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,109,97,99,104,105,110,101,32,110,97,109,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>}],[]},{code,[],[<<109,111,100,105,102,105,101,100,95,116,105,109,105,110,103,95,108,101,118,101,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,111,100,105,102,105,101,100,32,116,105,109,105,110,103,45,108,101,118,101,108,32,40,97,110,32,105,110,116,101,103,101,114,41,32,105,102,32,109,111,100,105,102,105,101,100,32,116,105,109,105,110,103,32,105,115,32,101,110,97,98,108,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,109,111,100,105,102,105,101,100,32,116,105,109,105,110,103,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,102,108,97,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,84>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,84>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]}]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,110,105,102,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<110,105,102,95,118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,78,73,70,32,105,110,116,101,114,102,97,99,101,32,117,115,101,100,32,98,121,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46,32,73,116,32,105,115,32,111,110,32,116,104,101,32,102,111,114,109,32,34,60,109,97,106,111,114,32,118,101,114,62,46,60,109,105,110,111,114,32,118,101,114,62,34,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,116,112,95,114,101,108,101,97,115,101>>}],[]},{code,[],[<<111,116,112,95,114,101,108,101,97,115,101>>]}]},{dd,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,111,116,112,95,114,101,108,101,97,115,101>>}],[]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,79,84,80,32,114,101,108,101,97,115,101,32,110,117,109,98,101,114,32,111,102,32,116,104,101,32,79,84,80,32,114,101,108,101,97,115,101,32,116,104,97,116,32,116,104,101,32,99,117,114,114,101,110,116,108,121,32,101,120,101,99,117,116,105,110,103,32,69,82,84,83,32,97,112,112,108,105,99,97,116,105,111,110,32,105,115,32,112,97,114,116,32,111,102,46>>]},{p,[],[<<65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,49,55,44,32,116,104,101,32,79,84,80,32,114,101,108,101,97,115,101,32,110,117,109,98,101,114,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,109,97,106,111,114,32,79,84,80,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,46,32,78,111,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,105,110,102,111,40,41>>]},<<32,97,114,103,117,109,101,110,116,32,103,105,118,101,115,32,116,104,101,32,101,120,97,99,116,32,79,84,80,32,118,101,114,115,105,111,110,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,101,120,97,99,116,32,79,84,80,32,118,101,114,115,105,111,110,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,32,105,115,32,100,105,102,102,105,99,117,108,116,32,116,111,32,100,101,116,101,114,109,105,110,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,118,101,114,115,105,111,110,115,32,105,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,115,121,115,116,101,109,95,112,114,105,110,99,105,112,108,101,115,58,118,101,114,115,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<83,121,115,116,101,109,32,112,114,105,110,99,105,112,108,101,115>>]},<<32,105,110,32,83,121,115,116,101,109,32,68,111,99,117,109,101,110,116,97,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>}],[]},{code,[],[<<112,111,114,116,95,112,97,114,97,108,108,101,108,105,115,109>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,101,102,97,117,108,116,32,112,111,114,116,32,112,97,114,97,108,108,101,108,105,115,109,32,115,99,104,101,100,117,108,105,110,103,32,104,105,110,116,32,117,115,101,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,99,111,109,109,97,110,100,45,108,105,110,101,32,97,114,103,117,109,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,43,115,112,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<43,115,112,112>>]}]},<<32,105,110,32>>,{code,[],[<<101,114,108,40,49,41>>]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>}],[]},{code,[],[<<115,121,115,116,101,109,95,97,114,99,104,105,116,101,99,116,117,114,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,112,114,111,99,101,115,115,111,114,32,97,110,100,32,79,83,32,97,114,99,104,105,116,101,99,116,117,114,101,32,116,104,101,32,101,109,117,108,97,116,111,114,32,105,115,32,98,117,105,108,116,32,102,111,114,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,108,111,103,103,101,114>>}],[]},{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32>>,{code,[],[<<115,121,115,116,101,109,95,108,111,103,103,101,114>>]},<<32,97,115,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,102,108,97,103,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,102,108,97,103,40,115,121,115,116,101,109,95,108,111,103,103,101,114,44,32,95,41>>]}]},<<46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,115,121,115,116,101,109,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<115,121,115,116,101,109,95,118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,32,97,110,100,32,115,111,109,101,32,105,109,112,111,114,116,97,110,116,32,112,114,111,112,101,114,116,105,101,115,44,32,115,117,99,104,32,97,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,99,104,101,100,117,108,101,114,115,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>}],[]},{code,[],[<<116,114,97,99,101,95,99,111,110,116,114,111,108,95,119,111,114,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,110,111,100,101,32,116,114,97,99,101,32,99,111,110,116,114,111,108,32,119,111,114,100,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<103,101,116,95,116,99,119>>]},<<32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99,35,103,101,116,95,116,99,119>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,118,101,114,115,105,111,110>>}],[]},{code,[],[<<118,101,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,32,111,102,32,116,104,101,32,101,109,117,108,97,116,111,114,46>>]}]},{dt,[],[{a,[{id,<<115,121,115,116,101,109,95,105,110,102,111,95,119,111,114,100,115,105,122,101>>}],[]},{code,[],[<<119,111,114,100,115,105,122,101>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<123,119,111,114,100,115,105,122,101,44,32,105,110,116,101,114,110,97,108,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,119,111,114,100,115,105,122,101,44,32,105,110,116,101,114,110,97,108,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,105,122,101,32,111,102,32,69,114,108,97,110,103,32,116,101,114,109,32,119,111,114,100,115,32,105,110,32,98,121,116,101,115,32,97,115,32,97,110,32,105,110,116,101,103,101,114,44,32,116,104,97,116,32,105,115,44,32,52,32,105,115,32,114,101,116,117,114,110,101,100,32,111,110,32,97,32,51,50,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,44,32,97,110,100,32,56,32,105,115,32,114,101,116,117,114,110,101,100,32,111,110,32,97,32,54,52,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,46>>]}]},{dt,[],[{code,[],[<<123,119,111,114,100,115,105,122,101,44,32,101,120,116,101,114,110,97,108,125>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,114,117,101,32,119,111,114,100,32,115,105,122,101,32,111,102,32,116,104,101,32,101,109,117,108,97,116,111,114,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,115,105,122,101,32,111,102,32,97,32,112,111,105,110,116,101,114,46,32,84,104,101,32,118,97,108,117,101,32,105,115,32,103,105,118,101,110,32,105,110,32,98,121,116,101,115,32,97,115,32,97,110,32,105,110,116,101,103,101,114,46,32,79,110,32,97,32,112,117,114,101,32,51,50,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,44,32,52,32,105,115,32,114,101,116,117,114,110,101,100,46,32,79,110,32,97,32,54,52,45,98,105,116,32,97,114,99,104,105,116,101,99,116,117,114,101,44,32,56,32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,48,55,51,48>>,signature => [{attribute,{2834,2},spec,{{erlang,system_info,1},[{type,{2854,10},'fun',[{type,{2854,10},product,[{atom,{2854,11},c_compiler_used}]},{type,{2854,31},tuple,[{type,{2854,32},atom,[]},{type,{2854,40},term,[]}]}]},{type,{2855,10},'fun',[{type,{2855,10},product,[{atom,{2855,11},check_io}]},{type,{2855,24},list,[{var,{2855,25},'_'}]}]},{type,{2856,10},'fun',[{type,{2856,10},product,[{atom,{2856,11},compat_rel}]},{type,{2856,26},integer,[]}]},{type,{2862,10},'fun',[{type,{2862,10},product,[{atom,{2862,11},debug_compiled}]},{type,{2862,30},boolean,[]}]},{type,{2871,10},'fun',[{type,{2871,10},product,[{atom,{2871,11},driver_version}]},{type,{2871,30},string,[]}]},{type,{2872,10},'fun',[{type,{2872,10},product,[{atom,{2872,11},dynamic_trace}]},{type,{2872,29},union,[{atom,{2872,29},none},{atom,{2872,36},dtrace},{atom,{2872,45},systemtap}]}]},{type,{2873,10},'fun',[{type,{2873,10},product,[{atom,{2873,11},dynamic_trace_probes}]},{type,{2873,36},boolean,[]}]},{type,{2875,10},'fun',[{type,{2875,10},product,[{atom,{2875,11},emu_flavor}]},{type,{2875,26},union,[{atom,{2875,26},emu},{atom,{2875,32},jit}]}]},{type,{2876,10},'fun',[{type,{2876,10},product,[{atom,{2876,11},emu_type}]},{type,{2876,24},union,[{atom,{2876,24},opt},{atom,{2876,30},debug},{atom,{2876,38},gcov},{atom,{2876,45},valgrind},{atom,{2876,56},gprof},{atom,{2876,64},lcnt},{atom,{2876,71},frmptr}]}]},{type,{2884,10},'fun',[{type,{2884,10},product,[{atom,{2884,11},info}]},{type,{2884,20},binary,[]}]},{type,{2885,10},'fun',[{type,{2885,10},product,[{atom,{2885,11},kernel_poll}]},{type,{2885,27},boolean,[]}]},{type,{2886,10},'fun',[{type,{2886,10},product,[{atom,{2886,11},loaded}]},{type,{2886,22},binary,[]}]},{type,{2890,10},'fun',[{type,{2890,10},product,[{atom,{2890,11},machine}]},{type,{2890,23},string,[]}]},{type,{2896,10},'fun',[{type,{2896,10},product,[{atom,{2896,11},modified_timing_level}]},{type,{2896,37},union,[{type,{2896,37},integer,[]},{atom,{2896,49},undefined}]}]},{type,{2899,10},'fun',[{type,{2899,10},product,[{atom,{2899,11},nif_version}]},{type,{2899,27},string,[]}]},{type,{2901,10},'fun',[{type,{2901,10},product,[{atom,{2901,11},otp_release}]},{type,{2901,27},string,[]}]},{type,{2904,10},'fun',[{type,{2904,10},product,[{atom,{2904,11},port_parallelism}]},{type,{2904,32},boolean,[]}]},{type,{2923,10},'fun',[{type,{2923,10},product,[{atom,{2923,11},system_architecture}]},{type,{2923,35},string,[]}]},{type,{2924,10},'fun',[{type,{2924,10},product,[{atom,{2924,11},system_logger}]},{type,{2924,29},union,[{atom,{2924,29},logger},{atom,{2924,38},undefined},{type,{2924,50},pid,[]}]}]},{type,{2925,10},'fun',[{type,{2925,10},product,[{atom,{2925,11},system_version}]},{type,{2925,30},string,[]}]},{type,{2932,10},'fun',[{type,{2932,10},product,[{atom,{2932,11},trace_control_word}]},{type,{2932,34},non_neg_integer,[]}]},{type,{2934,10},'fun',[{type,{2934,10},product,[{atom,{2934,11},version}]},{type,{2934,23},string,[]}]},{type,{2935,10},'fun',[{type,{2935,10},product,[{type,{2935,11},union,[{atom,{2935,11},wordsize},{type,{2935,22},tuple,[{atom,{2935,23},wordsize},{atom,{2935,33},internal}]},{type,{2935,45},tuple,[{atom,{2935,46},wordsize},{atom,{2935,56},external}]}]}]},{type,{2935,70},union,[{integer,{2935,70},4},{integer,{2935,74},8}]}]}]}}],since => <<79,84,80,32,49,55,46,52,44,79,84,80,32,50,49,46,51,44,79,84,80,32,50,52,46,48,44,79,84,80,32,82,49,53,66,48,49,44,79,84,80,32,82,49,54,66>>}},{{function,system_monitor,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2020}],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,105,110,103,32,115,101,116,116,105,110,103,115,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>]}]},<<32,97,115,32>>,{code,[],[<<123,77,111,110,105,116,111,114,80,105,100,44,32,79,112,116,105,111,110,115,125>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,110,111,32,115,101,116,116,105,110,103,115,32,101,120,105,115,116,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,111,110,101,32,116,104,97,116,32,119,97,115,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,48,51,52>>,signature => [{attribute,{2020,2},spec,{{erlang,system_monitor,0},[{type,{2020,28},bounded_fun,[{type,{2020,28},'fun',[{type,{2020,28},product,[]},{var,{2020,34},'MonSettings'}]},[{type,{2021,7},constraint,[{atom,{2021,7},is_subtype},[{var,{2021,7},'MonSettings'},{type,{2021,22},union,[{atom,{2021,22},undefined},{type,{2021,34},tuple,[{var,{2021,36},'MonitorPid'},{var,{2021,48},'Options'}]}]}]]},{type,{2022,7},constraint,[{atom,{2022,7},is_subtype},[{var,{2022,7},'MonitorPid'},{type,{2022,21},pid,[]}]]},{type,{2023,7},constraint,[{atom,{2023,7},is_subtype},[{var,{2023,7},'Options'},{type,{2023,18},list,[{user_type,{2023,20},system_monitor_option,[]}]}]]}]]}]}}]}},{{function,system_monitor,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2028}],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<87,104,101,110,32,99,97,108,108,101,100,32,119,105,116,104,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<44,32,97,108,108,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,32,109,111,110,105,116,111,114,105,110,103,32,115,101,116,116,105,110,103,115,32,97,114,101,32,99,108,101,97,114,101,100,46>>]},{p,[],[<<67,97,108,108,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,32,119,105,116,104,32>>,{code,[],[<<123,77,111,110,105,116,111,114,80,105,100,44,32,79,112,116,105,111,110,115,125>>]},<<32,97,115,32,97,114,103,117,109,101,110,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,40,77,111,110,105,116,111,114,80,105,100,44,32,79,112,116,105,111,110,115,41>>]}]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,115,101,116,116,105,110,103,115,32,106,117,115,116,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,48,52,56>>,signature => [{attribute,{2028,2},spec,{{erlang,system_monitor,1},[{type,{2028,28},bounded_fun,[{type,{2028,28},'fun',[{type,{2028,28},product,[{var,{2028,29},'Arg'}]},{var,{2028,37},'MonSettings'}]},[{type,{2029,7},constraint,[{atom,{2029,7},is_subtype},[{var,{2029,7},'Arg'},{type,{2029,14},union,[{atom,{2029,14},undefined},{type,{2029,26},tuple,[{var,{2029,28},'MonitorPid'},{var,{2029,40},'Options'}]}]}]]},{type,{2030,7},constraint,[{atom,{2030,7},is_subtype},[{var,{2030,7},'MonSettings'},{type,{2030,22},union,[{atom,{2030,22},undefined},{type,{2030,34},tuple,[{var,{2030,36},'MonitorPid'},{var,{2030,48},'Options'}]}]}]]},{type,{2031,7},constraint,[{atom,{2031,7},is_subtype},[{var,{2031,7},'MonitorPid'},{type,{2031,21},pid,[]}]]},{type,{2032,7},constraint,[{atom,{2032,7},is_subtype},[{var,{2032,7},'Options'},{type,{2032,18},list,[{user_type,{2032,20},system_monitor_option,[]}]}]]}]]}]}}]}},{{function,system_monitor,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2037}],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<83,101,116,115,32,116,104,101,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,32,109,111,110,105,116,111,114,105,110,103,32,111,112,116,105,111,110,115,46,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,114,101,99,101,105,118,105,110,103,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,108,105,115,116,32,111,102,32,109,111,110,105,116,111,114,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,108,111,110,103,95,103,99,44,32,84,105,109,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,116,97,107,101,115,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<84,105,109,101>>]},<<32,119,97,108,108,32,99,108,111,99,107,32,109,105,108,108,105,115,101,99,111,110,100,115,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,71,99,80,105,100,44,32,108,111,110,103,95,103,99,44,32,73,110,102,111,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<71,99,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,105,100,32,116,104,97,116,32,119,97,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,101,108,101,109,101,110,116,32,116,117,112,108,101,115,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[<<79,110,101,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,115,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,71,99,84,105,109,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<71,99,84,105,109,101>>]},<<32,105,115,32,116,104,101,32,116,105,109,101,32,102,111,114,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,110,32,109,105,108,108,105,115,101,99,111,110,100,115,46,32,84,104,101,32,111,116,104,101,114,32,116,117,112,108,101,115,32,97,114,101,32,116,97,103,103,101,100,32,119,105,116,104,32>>,{code,[],[<<104,101,97,112,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<115,116,97,99,107,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<109,98,117,102,95,115,105,122,101>>]},<<44,32>>,{code,[],[<<111,108,100,95,104,101,97,112,95,115,105,122,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<111,108,100,95,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]},<<46,32,84,104,101,115,101,32,116,117,112,108,101,115,32,97,114,101,32,101,120,112,108,97,105,110,101,100,32,105,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]}]},<<32,40,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<41,46,32,78,101,119,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,44,32,97,110,100,32,116,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,110,32,116,104,101,32>>,{code,[],[<<73,110,102,111>>]},<<32,108,105,115,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]}]},{dt,[],[{code,[],[<<123,108,111,110,103,95,115,99,104,101,100,117,108,101,44,32,84,105,109,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,114,117,110,115,32,117,110,105,110,116,101,114,114,117,112,116,101,100,32,102,111,114,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<84,105,109,101>>]},<<32,119,97,108,108,32,99,108,111,99,107,32,109,105,108,108,105,115,101,99,111,110,100,115,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,80,105,100,79,114,80,111,114,116,44,32,108,111,110,103,95,115,99,104,101,100,117,108,101,44,32,73,110,102,111,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<80,105,100,79,114,80,111,114,116>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,116,104,97,116,32,119,97,115,32,114,117,110,110,105,110,103,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,101,108,101,109,101,110,116,32,116,117,112,108,101,115,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,101,118,101,110,116,46>>]},{p,[],[<<73,102,32,97,32>>,{code,[],[<<112,105,100,40,41>>]},<<44,32,116,104,101,32,116,117,112,108,101,115,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,77,105,108,108,105,115,125>>]},<<44,32>>,{code,[],[<<123,105,110,44,32,76,111,99,97,116,105,111,110,125>>]},<<44,32,97,110,100,32>>,{code,[],[<<123,111,117,116,44,32,76,111,99,97,116,105,111,110,125>>]},<<32,97,114,101,32,112,114,101,115,101,110,116,44,32,119,104,101,114,101,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,101,105,116,104,101,114,32,97,110,32,77,70,65,32,40>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<41,32,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,32,119,104,101,114,101,32,116,104,101,32,112,114,111,99,101,115,115,32,119,97,115,32,115,99,104,101,100,117,108,101,100,32,105,110,47,111,117,116,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]},{p,[],[<<73,102,32,97,32>>,{code,[],[<<112,111,114,116,40,41>>]},<<44,32,116,104,101,32,116,117,112,108,101,115,32>>,{code,[],[<<123,116,105,109,101,111,117,116,44,32,77,105,108,108,105,115,125>>]},<<32,97,110,100,32>>,{code,[],[<<123,112,111,114,116,95,111,112,44,79,112,125>>]},<<32,97,114,101,32,112,114,101,115,101,110,116,46,32>>,{code,[],[<<79,112>>]},<<32,105,115,32,111,110,101,32,111,102,32>>,{code,[],[<<112,114,111,99,95,115,105,103>>]},<<44,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<44,32>>,{code,[],[<<105,110,112,117,116>>]},<<44,32>>,{code,[],[<<111,117,116,112,117,116>>]},<<44,32>>,{code,[],[<<101,118,101,110,116>>]},<<44,32,111,114,32>>,{code,[],[<<100,105,115,116,95,99,109,100>>]},<<44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,119,104,105,99,104,32,100,114,105,118,101,114,32,99,97,108,108,98,97,99,107,32,119,97,115,32,101,120,101,99,117,116,105,110,103,46>>]},{p,[],[{code,[],[<<112,114,111,99,95,115,105,103>>]},<<32,105,115,32,97,110,32,105,110,116,101,114,110,97,108,32,111,112,101,114,97,116,105,111,110,32,97,110,100,32,105,115,32,110,101,118,101,114,32,116,111,32,97,112,112,101,97,114,44,32,119,104,105,108,101,32,116,104,101,32,111,116,104,101,114,115,32,114,101,112,114,101,115,101,110,116,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,100,114,105,118,101,114,32,99,97,108,108,98,97,99,107,115,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<44,32>>,{code,[],[<<114,101,97,100,121,95,105,110,112,117,116>>]},<<44,32>>,{code,[],[<<114,101,97,100,121,95,111,117,116,112,117,116>>]},<<44,32>>,{code,[],[<<101,118,101,110,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<111,117,116,112,117,116,118>>]},<<32,40,119,104,101,110,32,116,104,101,32,112,111,114,116,32,105,115,32,117,115,101,100,32,98,121,32,100,105,115,116,114,105,98,117,116,105,111,110,41,46,32,86,97,108,117,101,32>>,{code,[],[<<77,105,108,108,105,115>>]},<<32,105,110,32,116,117,112,108,101,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,105,110,102,111,114,109,115,32,97,98,111,117,116,32,116,104,101,32,117,110,105,110,116,101,114,114,117,112,116,101,100,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,44,32,119,104,105,99,104,32,97,108,119,97,121,115,32,105,115,32,101,113,117,97,108,32,116,111,32,111,114,32,104,105,103,104,101,114,32,116,104,97,110,32,116,104,101,32>>,{code,[],[<<84,105,109,101>>]},<<32,118,97,108,117,101,32,115,117,112,112,108,105,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,116,114,97,99,101,46,32,78,101,119,32,116,117,112,108,101,115,32,99,97,110,32,98,101,32,97,100,100,101,100,32,116,111,32,116,104,101,32>>,{code,[],[<<73,110,102,111>>]},<<32,108,105,115,116,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,32,105,110,32,116,104,101,32,108,105,115,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,97,116,32,97,110,121,32,116,105,109,101,32,119,105,116,104,111,117,116,32,112,114,105,111,114,32,110,111,116,105,99,101,46>>]},{p,[],[<<84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,100,101,116,101,99,116,32,112,114,111,98,108,101,109,115,32,119,105,116,104,32,78,73,70,115,32,111,114,32,100,114,105,118,101,114,115,32,116,104,97,116,32,116,97,107,101,32,116,111,111,32,108,111,110,103,32,116,111,32,101,120,101,99,117,116,101,46,32,49,32,109,115,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97,32,103,111,111,100,32,109,97,120,105,109,117,109,32,116,105,109,101,32,102,111,114,32,97,32,100,114,105,118,101,114,32,99,97,108,108,98,97,99,107,32,111,114,32,97,32,78,73,70,46,32,72,111,119,101,118,101,114,44,32,97,32,116,105,109,101,45,115,104,97,114,105,110,103,32,115,121,115,116,101,109,32,105,115,32,117,115,117,97,108,108,121,32,116,111,32,99,111,110,115,105,100,101,114,32,101,118,101,114,121,116,104,105,110,103,32,60,32,49,48,48,32,109,115,32,97,115,32,34,112,111,115,115,105,98,108,101,34,32,97,110,100,32,102,97,105,114,108,121,32,34,110,111,114,109,97,108,34,46,32,72,111,119,101,118,101,114,44,32,108,111,110,103,101,114,32,115,99,104,101,100,117,108,101,32,116,105,109,101,115,32,99,97,110,32,105,110,100,105,99,97,116,101,32,115,119,97,112,112,105,110,103,32,111,114,32,97,32,109,105,115,98,101,104,97,118,105,110,103,32,78,73,70,47,100,114,105,118,101,114,46,32,77,105,115,98,101,104,97,118,105,110,103,32,78,73,70,115,32,97,110,100,32,100,114,105,118,101,114,115,32,99,97,110,32,99,97,117,115,101,32,98,97,100,32,114,101,115,111,117,114,99,101,32,117,116,105,108,105,122,97,116,105,111,110,32,97,110,100,32,98,97,100,32,111,118,101,114,97,108,108,32,115,121,115,116,101,109,32,112,101,114,102,111,114,109,97,110,99,101,46>>]}]},{dt,[],[{code,[],[<<123,108,97,114,103,101,95,104,101,97,112,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,114,101,115,117,108,116,115,32,105,110,32,116,104,101,32,97,108,108,111,99,97,116,101,100,32,115,105,122,101,32,111,102,32,97,32,104,101,97,112,32,98,101,105,110,103,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<83,105,122,101>>]},<<32,119,111,114,100,115,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,71,99,80,105,100,44,32,108,97,114,103,101,95,104,101,97,112,44,32,73,110,102,111,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<71,99,80,105,100>>]},<<32,97,110,100,32>>,{code,[],[<<73,110,102,111>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,102,111,114,32>>,{code,[],[<<108,111,110,103,95,103,99>>]},<<32,101,97,114,108,105,101,114,44,32,101,120,99,101,112,116,32,116,104,97,116,32,116,104,101,32,116,117,112,108,101,32,116,97,103,103,101,100,32,119,105,116,104,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,46>>]},{p,[],[<<84,104,101,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,115,105,122,101,115,32,111,102,32,97,108,108,32,109,101,109,111,114,121,32,98,108,111,99,107,115,32,97,108,108,111,99,97,116,101,100,32,102,111,114,32,97,108,108,32,104,101,97,112,32,103,101,110,101,114,97,116,105,111,110,115,32,97,102,116,101,114,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,101,113,117,97,108,32,116,111,32,111,114,32,104,105,103,104,101,114,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<46>>]},{p,[],[<<87,104,101,110,32,97,32,112,114,111,99,101,115,115,32,105,115,32,107,105,108,108,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32,105,116,32,105,115,32,107,105,108,108,101,100,32,98,101,102,111,114,101,32,116,104,101,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,99,111,109,112,108,101,116,101,32,97,110,100,32,116,104,117,115,32,110,111,32,108,97,114,103,101,32,104,101,97,112,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,46>>]}]},{dt,[],[{code,[],[<<98,117,115,121,95,112,111,114,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,103,101,116,115,32,115,117,115,112,101,110,100,101,100,32,98,101,99,97,117,115,101,32,105,116,32,115,101,110,100,115,32,116,111,32,97,32,98,117,115,121,32,112,111,114,116,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,83,117,115,80,105,100,44,32,98,117,115,121,95,112,111,114,116,44,32,80,111,114,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<83,117,115,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,105,100,32,116,104,97,116,32,103,111,116,32,115,117,115,112,101,110,100,101,100,32,119,104,101,110,32,115,101,110,100,105,110,103,32,116,111,32>>,{code,[],[<<80,111,114,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<98,117,115,121,95,100,105,115,116,95,112,111,114,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,32,103,101,116,115,32,115,117,115,112,101,110,100,101,100,32,98,101,99,97,117,115,101,32,105,116,32,115,101,110,100,115,32,116,111,32,97,32,112,114,111,99,101,115,115,32,111,110,32,97,32,114,101,109,111,116,101,32,110,111,100,101,32,119,104,111,115,101,32,105,110,116,101,114,45,110,111,100,101,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,119,97,115,32,104,97,110,100,108,101,100,32,98,121,32,97,32,98,117,115,121,32,112,111,114,116,44,32,97,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,109,111,110,105,116,111,114,44,32,83,117,115,80,105,100,44,32,98,117,115,121,95,100,105,115,116,95,112,111,114,116,44,32,80,111,114,116,125>>]},<<32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<46,32>>,{code,[],[<<83,117,115,80,105,100>>]},<<32,105,115,32,116,104,101,32,112,105,100,32,116,104,97,116,32,103,111,116,32,115,117,115,112,101,110,100,101,100,32,119,104,101,110,32,115,101,110,100,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,32,105,110,116,101,114,45,110,111,100,101,32,99,111,109,109,117,110,105,99,97,116,105,111,110,32,112,111,114,116,32>>,{code,[],[<<80,111,114,116>>]},<<46>>]}]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,115,101,116,116,105,110,103,115,32,106,117,115,116,32,108,105,107,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,48>>]}]},<<46>>]},{p,[],[<<84,104,101,32,97,114,103,117,109,101,110,116,115,32,116,111,32>>,{code,[],[<<115,121,115,116,101,109,95,109,111,110,105,116,111,114,47,50>>]},<<32,115,112,101,99,105,102,105,101,115,32,104,111,119,32,97,108,108,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,105,110,103,32,111,110,32,116,104,101,32,110,111,100,101,32,115,104,111,117,108,100,32,98,101,32,100,111,110,101,44,32,110,111,116,32,104,111,119,32,105,116,32,115,104,111,117,108,100,32,98,101,32,99,104,97,110,103,101,100,46,32,84,104,105,115,32,109,101,97,110,115,32,111,110,108,121,32,111,110,101,32,112,114,111,99,101,115,115,32,97,116,32,97,32,116,105,109,101,32,40>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<41,32,99,97,110,32,98,101,32,116,104,101,32,114,101,99,101,105,118,101,114,32,111,102,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,115,46,32,65,108,115,111,44,32,116,104,101,32,119,97,121,32,116,111,32,99,108,101,97,114,32,97,32,115,112,101,99,105,102,105,99,32,109,111,110,105,116,111,114,32,111,112,116,105,111,110,32,105,115,32,116,111,32,110,111,116,32,105,110,99,108,117,100,101,32,105,116,32,105,110,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<79,112,116,105,111,110,115>>]},<<46,32,65,108,108,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,105,110,103,32,119,105,108,108,44,32,104,111,119,101,118,101,114,44,32,98,101,32,99,108,101,97,114,101,100,32,105,102,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,116,101,114,109,105,110,97,116,101,115,46>>]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,110,111,32,115,112,101,99,105,97,108,32,111,112,116,105,111,110,32,118,97,108,117,101,115,32,40,108,105,107,101,32,122,101,114,111,41,32,116,111,32,99,108,101,97,114,32,97,110,32,111,112,116,105,111,110,46,32,83,111,109,101,32,111,102,32,116,104,101,32,111,112,116,105,111,110,115,32,104,97,118,101,32,97,32,117,110,115,112,101,99,105,102,105,101,100,32,109,105,110,105,109,117,109,32,118,97,108,117,101,46,32,76,111,119,101,114,32,118,97,108,117,101,115,32,119,105,108,108,32,98,101,32,97,100,106,117,115,116,101,100,32,116,111,32,116,104,101,32,109,105,110,105,109,117,109,32,118,97,108,117,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,105,115,32,99,117,114,114,101,110,116,108,121,32,110,111,116,32,112,111,115,115,105,98,108,101,32,116,111,32,109,111,110,105,116,111,114,32,97,108,108,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,32,119,105,116,104,32>>,{code,[],[<<123,108,111,110,103,95,103,99,44,32,48,125>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,102,32,97,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,103,101,116,115,32,115,111,32,108,97,114,103,101,32,116,104,97,116,32,105,116,32,105,116,115,101,108,102,32,115,116,97,114,116,115,32,116,111,32,99,97,117,115,101,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,109,101,115,115,97,103,101,115,32,119,104,101,110,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,110,103,44,32,116,104,101,32,109,101,115,115,97,103,101,115,32,101,110,108,97,114,103,101,32,116,104,101,32,112,114,111,99,101,115,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,110,100,32,112,114,111,98,97,98,108,121,32,109,97,107,101,32,116,104,101,32,112,114,111,98,108,101,109,32,119,111,114,115,101,46>>]},{p,[],[<<75,101,101,112,32,116,104,101,32,109,111,110,105,116,111,114,105,110,103,32,112,114,111,99,101,115,115,32,110,101,97,116,32,97,110,100,32,100,111,32,110,111,116,32,115,101,116,32,116,104,101,32,115,121,115,116,101,109,32,109,111,110,105,116,111,114,32,108,105,109,105,116,115,32,116,111,111,32,116,105,103,104,116,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<73,102,32>>,{code,[],[<<77,111,110,105,116,111,114,80,105,100>>]},<<32,105,115,32,110,111,116,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,48,54,54>>,signature => [{attribute,{2037,2},spec,{{erlang,system_monitor,2},[{type,{2037,28},bounded_fun,[{type,{2037,28},'fun',[{type,{2037,28},product,[{var,{2037,29},'MonitorPid'},{var,{2037,41},'Options'}]},{var,{2037,53},'MonSettings'}]},[{type,{2038,7},constraint,[{atom,{2038,7},is_subtype},[{var,{2038,7},'MonitorPid'},{type,{2038,21},pid,[]}]]},{type,{2039,7},constraint,[{atom,{2039,7},is_subtype},[{var,{2039,7},'Options'},{type,{2039,18},list,[{user_type,{2039,20},system_monitor_option,[]}]}]]},{type,{2040,7},constraint,[{atom,{2040,7},is_subtype},[{var,{2040,7},'MonSettings'},{type,{2040,22},union,[{atom,{2040,22},undefined},{type,{2040,34},tuple,[{var,{2040,36},'OldMonitorPid'},{var,{2040,51},'OldOptions'}]}]}]]},{type,{2041,7},constraint,[{atom,{2041,7},is_subtype},[{var,{2041,7},'OldMonitorPid'},{type,{2041,24},pid,[]}]]},{type,{2042,7},constraint,[{atom,{2042,7},is_subtype},[{var,{2042,7},'OldOptions'},{type,{2042,21},list,[{user_type,{2042,23},system_monitor_option,[]}]}]]}]]}]}}]}},{{function,system_profile,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2047}],[<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,112,114,111,102,105,108,105,110,103,32,115,101,116,116,105,110,103,115,32,115,101,116,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>]}]},<<32,97,115,32>>,{code,[],[<<123,80,114,111,102,105,108,101,114,80,105,100,44,32,79,112,116,105,111,110,115,125>>]},<<44,32,111,114,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,114,101,32,97,114,101,32,110,111,32,115,101,116,116,105,110,103,115,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,111,110,101,32,116,104,97,116,32,119,97,115,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,50,49,48>>,signature => [{attribute,{2047,2},spec,{{erlang,system_profile,0},[{type,{2047,28},bounded_fun,[{type,{2047,28},'fun',[{type,{2047,28},product,[]},{var,{2047,34},'ProfilerSettings'}]},[{type,{2048,7},constraint,[{atom,{2048,7},is_subtype},[{var,{2048,7},'ProfilerSettings'},{type,{2048,27},union,[{atom,{2048,27},undefined},{type,{2048,39},tuple,[{var,{2048,41},'ProfilerPid'},{var,{2048,54},'Options'}]}]}]]},{type,{2049,7},constraint,[{atom,{2049,7},is_subtype},[{var,{2049,7},'ProfilerPid'},{type,{2049,22},union,[{type,{2049,22},pid,[]},{type,{2049,30},port,[]}]}]]},{type,{2050,7},constraint,[{atom,{2050,7},is_subtype},[{var,{2050,7},'Options'},{type,{2050,18},list,[{user_type,{2050,20},system_profile_option,[]}]}]]}]]}]}}]}},{{function,system_profile,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2055}],[<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,121,115,116,101,109,95,112,114,111,102,105,108,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<83,101,116,115,32,115,121,115,116,101,109,32,112,114,111,102,105,108,101,114,32,111,112,116,105,111,110,115,46,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<32,105,115,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,111,114,32,112,111,114,116,32,114,101,99,101,105,118,105,110,103,32,112,114,111,102,105,108,105,110,103,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,114,101,99,101,105,118,101,114,32,105,115,32,101,120,99,108,117,100,101,100,32,102,114,111,109,32,97,108,108,32,112,114,111,102,105,108,105,110,103,46,32,84,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,105,115,32,97,32,108,105,115,116,32,111,102,32,112,114,111,102,105,108,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,120,99,108,117,115,105,118,101>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,115,121,110,99,104,114,111,110,111,117,115,32,99,97,108,108,32,116,111,32,97,32,112,111,114,116,32,102,114,111,109,32,97,32,112,114,111,99,101,115,115,32,105,115,32,100,111,110,101,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,110,111,116,32,114,117,110,110,97,98,108,101,32,100,117,114,105,110,103,32,116,104,101,32,99,97,108,108,32,114,117,110,116,105,109,101,32,116,111,32,116,104,101,32,112,111,114,116,46,32,84,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,105,102,105,101,100,32,97,115,32>>,{code,[],[<<105,110,97,99,116,105,118,101>>]},<<44,32,97,110,100,32,108,97,116,101,114,32>>,{code,[],[<<97,99,116,105,118,101>>]},<<32,119,104,101,110,32,116,104,101,32,112,111,114,116,32,99,97,108,108,98,97,99,107,32,114,101,116,117,114,110,115,46>>]}]},{dt,[],[{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,115,116,97,109,112,115,32,105,110,32,112,114,111,102,105,108,101,32,109,101,115,115,97,103,101,115,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,97,98,108,101,95,112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,114,111,99,101,115,115,32,105,115,32,112,117,116,32,105,110,116,111,32,111,114,32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,104,101,32,114,117,110,32,113,117,101,117,101,44,32,97,32,109,101,115,115,97,103,101,44,32>>,{code,[],[<<123,112,114,111,102,105,108,101,44,32,80,105,100,44,32,83,116,97,116,101,44,32,77,102,97,44,32,84,115,125>>]},<<44,32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<46,32,82,117,110,110,105,110,103,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,97,114,101,32,114,101,105,110,115,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32,114,117,110,32,113,117,101,117,101,32,97,102,116,101,114,32,104,97,118,105,110,103,32,98,101,101,110,32,112,114,101,45,101,109,112,116,101,100,32,100,111,32,110,111,116,32,116,114,105,103,103,101,114,32,116,104,105,115,32,109,101,115,115,97,103,101,46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,97,98,108,101,95,112,111,114,116,115>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,112,111,114,116,32,105,115,32,112,117,116,32,105,110,116,111,32,111,114,32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,104,101,32,114,117,110,32,113,117,101,117,101,44,32,97,32,109,101,115,115,97,103,101,44,32>>,{code,[],[<<123,112,114,111,102,105,108,101,44,32,80,111,114,116,44,32,83,116,97,116,101,44,32,48,44,32,84,115,125>>]},<<44,32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,99,104,101,100,117,108,101,114>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,115,99,104,101,100,117,108,101,114,32,105,115,32,112,117,116,32,116,111,32,115,108,101,101,112,32,111,114,32,97,119,111,107,101,110,44,32,97,32,109,101,115,115,97,103,101,44,32>>,{code,[],[<<123,112,114,111,102,105,108,101,44,32,115,99,104,101,100,117,108,101,114,44,32,73,100,44,32,83,116,97,116,101,44,32,78,111,83,99,104,101,100,115,44,32,84,115,125>>]},<<44,32,105,115,32,115,101,110,116,32,116,111,32>>,{code,[],[<<80,114,111,102,105,108,101,114,80,105,100>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,115,116,97,109,112,115,32,105,110,32,112,114,111,102,105,108,101,32,109,101,115,115,97,103,101,115,32,99,111,110,115,105,115,116,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,105,110,116,101,103,101,114,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{code,[],[<<123,101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41,44,32,101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,115,116,97,109,112,115,32,105,110,32,112,114,111,102,105,108,101,32,109,101,115,115,97,103,101,115,32,105,110,99,108,117,100,101,32,97,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,116,104,97,116,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,40,41>>]},<<46,32,84,104,105,115,32,105,115,32,97,108,115,111,32,116,104,101,32,100,101,102,97,117,108,116,32,105,102,32,110,111,32,116,105,109,101,32,115,116,97,109,112,32,102,108,97,103,32,105,115,32,115,112,101,99,105,102,105,101,100,46,32,73,102,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<32,104,97,115,32,98,101,101,110,32,101,110,97,98,108,101,100,32,116,104,114,111,117,103,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<44,32,116,104,105,115,32,97,108,115,111,32,101,102,102,101,99,116,115,32,116,104,101,32,116,105,109,101,32,115,116,97,109,112,32,112,114,111,100,117,99,101,100,32,105,110,32,112,114,111,102,105,108,105,110,103,32,109,101,115,115,97,103,101,115,32,119,104,101,110,32,102,108,97,103,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,101,110,97,98,108,101,100,46>>]}]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,112,114,111,102,105,108,101>>]},<<32,98,101,104,97,118,105,111,114,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,50,50,53>>,signature => [{attribute,{2055,2},spec,{{erlang,system_profile,2},[{type,{2055,28},bounded_fun,[{type,{2055,28},'fun',[{type,{2055,28},product,[{var,{2055,29},'ProfilerPid'},{var,{2055,42},'Options'}]},{var,{2055,54},'ProfilerSettings'}]},[{type,{2056,7},constraint,[{atom,{2056,7},is_subtype},[{var,{2056,7},'ProfilerPid'},{type,{2056,22},union,[{type,{2056,22},pid,[]},{type,{2056,30},port,[]},{atom,{2056,39},undefined}]}]]},{type,{2057,7},constraint,[{atom,{2057,7},is_subtype},[{var,{2057,7},'Options'},{type,{2057,18},list,[{user_type,{2057,20},system_profile_option,[]}]}]]},{type,{2058,7},constraint,[{atom,{2058,7},is_subtype},[{var,{2058,7},'ProfilerSettings'},{type,{2058,27},union,[{atom,{2058,27},undefined},{type,{2058,39},tuple,[{type,{2058,41},union,[{type,{2058,41},pid,[]},{type,{2058,49},port,[]}]},{type,{2058,57},list,[{user_type,{2058,59},system_profile_option,[]}]}]}]}]]}]]}]}}]}},{{function,system_time,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1608}],[<<115,121,115,116,101,109,95,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46>>]},{p,[],[<<67,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,43,32>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,116,105,109,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,50,57,57>>,signature => [{attribute,{1608,2},spec,{{erlang,system_time,0},[{type,{1608,25},'fun',[{type,{1608,25},product,[]},{type,{1608,31},integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,system_time,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1613}],[<<115,121,115,116,101,109,95,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,99,111,110,118,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32>>,{code,[],[<<85,110,105,116>>]},<<32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{p,[],[<<67,97,108,108,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,85,110,105,116,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]}]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,116,105,109,101,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,41>>]}]},{code,[],[<<44,32,110,97,116,105,118,101,44,32,85,110,105,116,41>>]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,116,105,109,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,51,50,49>>,signature => [{attribute,{1613,2},spec,{{erlang,system_time,1},[{type,{1613,25},bounded_fun,[{type,{1613,25},'fun',[{type,{1613,25},product,[{var,{1613,26},'Unit'}]},{type,{1613,35},integer,[]}]},[{type,{1614,7},constraint,[{atom,{1614,7},is_subtype},[{var,{1614,7},'Unit'},{user_type,{1614,15},time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,term_to_binary,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2733}],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,32,116,104,97,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,101,110,99,111,100,105,110,103,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,101,120,116,95,100,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]}]},{p,[],[<<84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,118,97,114,105,111,117,115,32,112,117,114,112,111,115,101,115,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,119,114,105,116,105,110,103,32,97,32,116,101,114,109,32,116,111,32,97,32,102,105,108,101,32,105,110,32,97,110,32,101,102,102,105,99,105,101,110,116,32,119,97,121,44,32,111,114,32,115,101,110,100,105,110,103,32,97,110,32,69,114,108,97,110,103,32,116,101,114,109,32,116,111,32,115,111,109,101,32,116,121,112,101,32,111,102,32,99,111,109,109,117,110,105,99,97,116,105,111,110,115,32,99,104,97,110,110,101,108,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,100,105,115,116,114,105,98,117,116,101,100,32,69,114,108,97,110,103,46>>]},{pre,[],[{code,[],[<<62,32,66,105,110,32,61,32,116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,104,101,108,108,111,41,46,10,60,60,49,51,49,44,49,48,48,44,48,44,53,44,49,48,52,44,49,48,49,44,49,48,56,44,49,48,56,44,49,49,49,62,62,10,62,32,104,101,108,108,111,32,61,32,98,105,110,97,114,121,95,116,111,95,116,101,114,109,40,66,105,110,41,46,10,104,101,108,108,111>>]}]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]}]},<<46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,110,111,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32,114,101,116,117,114,110,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,101,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,97,109,101,32,116,101,114,109,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,51,52,51>>,signature => [{attribute,{2733,2},spec,{{term_to_binary,1},[{type,{2733,21},bounded_fun,[{type,{2733,21},'fun',[{type,{2733,21},product,[{var,{2733,22},'Term'}]},{user_type,{2733,31},ext_binary,[]}]},[{type,{2734,7},constraint,[{atom,{2734,7},is_subtype},[{var,{2734,7},'Term'},{type,{2734,15},term,[]}]]}]]}]}}]}},{{function,term_to_binary,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2738}],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,32,116,104,97,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,101,110,99,111,100,105,110,103,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,105,115,32,112,114,111,118,105,100,101,100,44,32,116,104,101,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,32,105,115,32,99,111,109,112,114,101,115,115,101,100,46,32,84,104,101,32,99,111,109,112,114,101,115,115,101,100,32,102,111,114,109,97,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,114,101,99,111,103,110,105,122,101,100,32,98,121,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]},<<32,97,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,55,66,46>>]},{p,[],[<<65,32,99,111,109,112,114,101,115,115,105,111,110,32,108,101,118,101,108,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,103,105,118,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<123,99,111,109,112,114,101,115,115,101,100,44,32,76,101,118,101,108,125>>]},<<46,32>>,{code,[],[<<76,101,118,101,108>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,119,105,116,104,32,114,97,110,103,101,32,48,46,46,57,44,32,119,104,101,114,101,58>>]},{ul,[],[{li,[],[{p,[],[{code,[],[<<48>>]},<<32,45,32,78,111,32,99,111,109,112,114,101,115,115,105,111,110,32,105,115,32,100,111,110,101,32,40,105,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,103,105,118,105,110,103,32,110,111,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,111,112,116,105,111,110,41,46>>]}]},{li,[],[{p,[],[{code,[],[<<49>>]},<<32,45,32,84,97,107,101,115,32,108,101,97,115,116,32,116,105,109,101,32,98,117,116,32,109,97,121,32,110,111,116,32,99,111,109,112,114,101,115,115,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32,104,105,103,104,101,114,32,108,101,118,101,108,115,46>>]}]},{li,[],[{p,[],[{code,[],[<<54>>]},<<32,45,32,68,101,102,97,117,108,116,32,108,101,118,101,108,32,119,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,105,115,32,112,114,111,118,105,100,101,100,46>>]}]},{li,[],[{p,[],[{code,[],[<<57>>]},<<32,45,32,84,97,107,101,115,32,109,111,115,116,32,116,105,109,101,32,97,110,100,32,116,114,105,101,115,32,116,111,32,112,114,111,100,117,99,101,32,97,32,115,109,97,108,108,101,114,32,114,101,115,117,108,116,46,32,78,111,116,105,99,101,32,34,116,114,105,101,115,34,32,105,110,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,115,101,110,116,101,110,99,101,59,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,105,110,112,117,116,32,116,101,114,109,44,32,108,101,118,101,108,32,57,32,99,111,109,112,114,101,115,115,105,111,110,32,101,105,116,104,101,114,32,100,111,101,115,32,111,114,32,100,111,101,115,32,110,111,116,32,112,114,111,100,117,99,101,32,97,32,115,109,97,108,108,101,114,32,114,101,115,117,108,116,32,116,104,97,110,32,108,101,118,101,108,32,49,32,99,111,109,112,114,101,115,115,105,111,110,46>>]}]}]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<123,109,105,110,111,114,95,118,101,114,115,105,111,110,44,32,86,101,114,115,105,111,110,125>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,99,111,110,116,114,111,108,32,115,111,109,101,32,101,110,99,111,100,105,110,103,32,100,101,116,97,105,108,115,46,32,84,104,105,115,32,111,112,116,105,111,110,32,119,97,115,32,105,110,116,114,111,100,117,99,101,100,32,105,110,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,45,52,46,32,84,104,101,32,118,97,108,105,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<86,101,114,115,105,111,110>>]},<<32,97,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<48>>]}]},{dd,[],[{p,[],[<<70,108,111,97,116,115,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,97,32,116,101,120,116,117,97,108,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,117,115,101,102,117,108,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,114,101,108,101,97,115,101,115,32,98,101,102,111,114,101,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,45,52,32,99,97,110,32,100,101,99,111,100,101,32,114,101,115,117,108,116,105,110,103,32,98,105,110,97,114,121,46>>]},{p,[],[<<84,104,105,115,32,118,101,114,115,105,111,110,32,101,110,99,111,100,101,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,108,97,116,105,110,49,32,115,116,114,105,110,103,32,117,115,105,110,103,32,108,97,116,105,110,49,32,101,110,99,111,100,105,110,103,32,119,104,105,108,101,32,111,110,108,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,108,97,116,105,110,49,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,117,116,102,56,46>>]}]},{dt,[],[{code,[],[<<49>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,105,115,32,97,115,32,111,102,32,69,114,108,97,110,103,47,79,84,80,32,49,55,46,48,32,116,104,101,32>>,{em,[],[<<100,101,102,97,117,108,116>>]},<<46,32,73,116,32,102,111,114,99,101,115,32,97,110,121,32,102,108,111,97,116,115,32,105,110,32,116,104,101,32,116,101,114,109,32,116,111,32,98,101,32,101,110,99,111,100,101,100,32,105,110,32,97,32,109,111,114,101,32,115,112,97,99,101,45,101,102,102,105,99,105,101,110,116,32,97,110,100,32,101,120,97,99,116,32,119,97,121,32,40,110,97,109,101,108,121,32,105,110,32,116,104,101,32,54,52,45,98,105,116,32,73,69,69,69,32,102,111,114,109,97,116,44,32,114,97,116,104,101,114,32,116,104,97,110,32,99,111,110,118,101,114,116,101,100,32,116,111,32,97,32,116,101,120,116,117,97,108,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,41,46,32,65,115,32,102,114,111,109,32,69,114,108,97,110,103,47,79,84,80,32,82,49,49,66,45,52,44,32>>,{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]},<<32,99,97,110,32,100,101,99,111,100,101,32,116,104,105,115,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46>>]},{p,[],[<<84,104,105,115,32,118,101,114,115,105,111,110,32,101,110,99,111,100,101,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,108,97,116,105,110,49,32,115,116,114,105,110,103,32,117,115,105,110,103,32,108,97,116,105,110,49,32,101,110,99,111,100,105,110,103,32,119,104,105,108,101,32,111,110,108,121,32,97,116,111,109,115,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,108,97,116,105,110,49,32,97,114,101,32,101,110,99,111,100,101,100,32,117,115,105,110,103,32,117,116,102,56,46>>]}]},{dt,[],[{code,[],[<<50>>]}]},{dd,[],[{p,[],[<<68,114,111,112,115,32,117,115,97,103,101,32,111,102,32,116,104,101,32,108,97,116,105,110,49,32,97,116,111,109,32,101,110,99,111,100,105,110,103,32,97,110,100,32,117,110,99,111,110,100,105,116,105,111,110,97,108,108,121,32,117,115,101,32,117,116,102,56,32,101,110,99,111,100,105,110,103,32,102,111,114,32,97,108,108,32,97,116,111,109,115,46,32,69,114,108,97,110,103,47,79,84,80,32,115,121,115,116,101,109,115,32,97,115,32,111,102,32,82,49,54,66,32,99,97,110,32,100,101,99,111,100,101,32,116,104,105,115,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,69,114,108,97,110,103,47,79,84,80,32,50,54,44,32,116,104,101,32,100,101,102,97,117,108,116,32>>,{code,[],[<<109,105,110,111,114,95,118,101,114,115,105,111,110>>]},<<32,105,115,32,112,108,97,110,110,101,100,32,116,111,32,99,104,97,110,103,101,32,102,114,111,109,32,49,32,116,111,32,50,46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,103,101,110,101,114,97,108,95,105,110,102,111,58,117,112,99,111,109,105,110,103,95,105,110,99,111,109,112,97,116,105,98,105,108,105,116,105,101,115,35,97,116,111,109,115,95,98,101,95,117,116,102,56>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<85,112,99,111,109,105,110,103,32,80,111,116,101,110,116,105,97,108,32,73,110,99,111,109,112,97,116,105,98,105,108,105,116,105,101,115,32>>]},<<46>>]}]}]}]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<100,101,116,101,114,109,105,110,105,115,116,105,99>>]},<<32,40,105,110,116,114,111,100,117,99,101,100,32,105,110,32,79,84,80,32,50,52,46,49,41,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,119,105,116,104,105,110,32,116,104,101,32,115,97,109,101,32,109,97,106,111,114,32,114,101,108,101,97,115,101,32,111,102,32,69,114,108,97,110,103,47,79,84,80,44,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,101,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,115,32,114,101,116,117,114,110,101,100,32,102,111,114,32,116,104,101,32,115,97,109,101,32,116,101,114,109,46,32,84,104,101,114,101,32,105,115,32,115,116,105,108,108,32,110,111,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,116,104,101,32,101,110,99,111,100,101,100,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,114,101,109,97,105,110,115,32,116,104,101,32,115,97,109,101,32,98,101,116,119,101,101,110,32,109,97,106,111,114,32,114,101,108,101,97,115,101,115,32,111,102,32,69,114,108,97,110,103,47,79,84,80,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<98,105,110,97,114,121,95,116,111,95,116,101,114,109,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,51,55,49>>,signature => [{attribute,{2738,2},spec,{{term_to_binary,2},[{type,{2738,21},bounded_fun,[{type,{2738,21},'fun',[{type,{2738,21},product,[{var,{2738,22},'Term'},{var,{2738,28},'Options'}]},{user_type,{2738,40},ext_binary,[]}]},[{type,{2739,7},constraint,[{atom,{2739,7},is_subtype},[{var,{2739,7},'Term'},{type,{2739,15},term,[]}]]},{type,{2740,7},constraint,[{atom,{2740,7},is_subtype},[{var,{2740,7},'Options'},{type,{2740,18},list,[{type,{2740,19},union,[{atom,{2740,19},compressed},{type,{2741,10},tuple,[{atom,{2741,11},compressed},{ann_type,{2741,23},[{var,{2741,23},'Level'},{type,{2741,32},range,[{integer,{2741,32},0},{integer,{2741,35},9}]}]}]},{atom,{2742,10},deterministic},{type,{2743,10},tuple,[{atom,{2743,11},minor_version},{ann_type,{2743,26},[{var,{2743,26},'Version'},{type,{2743,37},range,[{integer,{2743,37},0},{integer,{2743,40},2}]}]}]}]}]}]]}]]}]}}]}},{{function,term_to_iovec,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2747}],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<101,120,116,95,105,111,118,101,99,40,41>>]}]},<<46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,112,114,111,100,117,99,101,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,105,110,103,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<44,32,98,117,116,32,119,105,116,104,32,97,110,111,116,104,101,114,32,114,101,116,117,114,110,32,116,121,112,101,46,32,84,104,101,32,99,97,108,108,32>>,{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,116,101,114,109,95,116,111,95,105,111,118,101,99,40,84,101,114,109,41,41>>]},<<32,119,105,108,108,32,112,114,111,100,117,99,101,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,116,104,101,32,99,97,108,108,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,41>>]},<<46>>]},{p,[],[{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,105,115,32,97,32,112,117,114,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,41>>]},<<32,112,114,111,118,105,100,101,46,32>>,{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,99,97,110,32,102,111,114,32,101,120,97,109,112,108,101,32,114,101,102,101,114,32,100,105,114,101,99,116,108,121,32,116,111,32,111,102,102,32,104,101,97,112,32,98,105,110,97,114,105,101,115,32,105,110,115,116,101,97,100,32,111,102,32,99,111,112,121,105,110,103,32,116,104,101,32,98,105,110,97,114,121,32,100,97,116,97,32,105,110,116,111,32,116,104,101,32,114,101,115,117,108,116,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,52,52,56>>,signature => [{attribute,{2747,2},spec,{{term_to_iovec,1},[{type,{2747,20},bounded_fun,[{type,{2747,20},'fun',[{type,{2747,20},product,[{var,{2747,21},'Term'}]},{user_type,{2747,30},ext_iovec,[]}]},[{type,{2748,7},constraint,[{atom,{2748,7},is_subtype},[{var,{2748,7},'Term'},{type,{2748,15},term,[]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,term_to_iovec,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2752}],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<101,120,116,95,105,111,118,101,99,40,41>>]}]},<<46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,112,114,111,100,117,99,101,32,116,104,101,32,115,97,109,101,32,101,110,99,111,100,105,110,103,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<44,32,98,117,116,32,119,105,116,104,32,97,110,111,116,104,101,114,32,114,101,116,117,114,110,32,116,121,112,101,46,32,84,104,101,32,99,97,108,108,32>>,{code,[],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,40,116,101,114,109,95,116,111,95,105,111,118,101,99,40,84,101,114,109,44,32,79,112,116,115,41,41>>]},<<32,119,105,108,108,32,112,114,111,100,117,99,101,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,84,101,114,109,44,32,79,112,116,115,41>>]},<<46>>]},{p,[],[<<67,117,114,114,101,110,116,108,121,32,114,101,99,111,103,110,105,115,101,100,32,111,112,116,105,111,110,115,32,97,114,101,32,97,108,108,32,111,112,116,105,111,110,115,32,114,101,99,111,103,110,105,115,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<46>>]},{p,[],[{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,105,115,32,97,32,112,117,114,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,97,108,105,116,121,32>>,{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,40,41>>]},<<32,112,114,111,118,105,100,101,46,32>>,{code,[],[<<116,101,114,109,95,116,111,95,105,111,118,101,99,40,41>>]},<<32,99,97,110,32,102,111,114,32,101,120,97,109,112,108,101,32,114,101,102,101,114,32,100,105,114,101,99,116,108,121,32,116,111,32,111,102,102,32,104,101,97,112,32,98,105,110,97,114,105,101,115,32,105,110,115,116,101,97,100,32,111,102,32,99,111,112,121,105,110,103,32,116,104,101,32,98,105,110,97,114,121,32,100,97,116,97,32,105,110,116,111,32,116,104,101,32,114,101,115,117,108,116,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,101,114,109,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,52,55,51>>,signature => [{attribute,{2752,2},spec,{{term_to_iovec,2},[{type,{2752,20},bounded_fun,[{type,{2752,20},'fun',[{type,{2752,20},product,[{var,{2752,21},'Term'},{var,{2752,27},'Options'}]},{user_type,{2752,39},ext_iovec,[]}]},[{type,{2753,7},constraint,[{atom,{2753,7},is_subtype},[{var,{2753,7},'Term'},{type,{2753,15},term,[]}]]},{type,{2754,7},constraint,[{atom,{2754,7},is_subtype},[{var,{2754,7},'Options'},{type,{2754,18},list,[{type,{2754,19},union,[{atom,{2754,19},compressed},{type,{2755,10},tuple,[{atom,{2755,11},compressed},{ann_type,{2755,23},[{var,{2755,23},'Level'},{type,{2755,32},range,[{integer,{2755,32},0},{integer,{2755,35},9}]}]}]},{atom,{2756,10},deterministic},{type,{2757,10},tuple,[{atom,{2757,11},minor_version},{ann_type,{2757,26},[{var,{2757,26},'Version'},{type,{2757,37},range,[{integer,{2757,37},0},{integer,{2757,40},2}]}]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,throw,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2064}],[<<116,104,114,111,119,47,49>>],#{<<101,110>> => [{p,[],[<<82,97,105,115,101,115,32,97,110,32,101,120,99,101,112,116,105,111,110,32,111,102,32,99,108,97,115,115,32>>,{code,[],[<<116,104,114,111,119>>]},<<46,32,73,110,116,101,110,100,101,100,32,116,111,32,98,101,32,117,115,101,100,32,116,111,32,100,111,32,110,111,110,45,108,111,99,97,108,32,114,101,116,117,114,110,115,32,102,114,111,109,32,102,117,110,99,116,105,111,110,115,46>>]},{p,[],[<<73,102,32,101,118,97,108,117,97,116,101,100,32,119,105,116,104,105,110,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,99,97,116,99,104>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<99,97,116,99,104,32,101,120,112,114,101,115,115,105,111,110>>]},<<44,32,116,104,101,32,99,97,116,99,104,32,101,120,112,114,101,115,115,105,111,110,32,114,101,116,117,114,110,115,32,118,97,108,117,101,32>>,{code,[],[<<65,110,121>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,99,97,116,99,104,32,116,104,114,111,119,40,123,104,101,108,108,111,44,32,116,104,101,114,101,125,41,46,10,32,32,32,32,32,32,32,32,123,104,101,108,108,111,44,116,104,101,114,101,125>>]}]},{p,[],[<<73,102,32,101,118,97,108,117,97,116,101,100,32,119,105,116,104,105,110,32,97,32>>,{code,[],[<<116,114,121>>]},<<45,98,108,111,99,107,32,111,102,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,116,114,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,114,121,32,101,120,112,114,101,115,115,105,111,110>>]},<<44,32,116,104,101,32,118,97,108,117,101,32>>,{code,[],[<<65,110,121>>]},<<32,99,97,110,32,98,101,32,99,97,117,103,104,116,32,119,105,116,104,105,110,32,116,104,101,32,99,97,116,99,104,32,98,108,111,99,107,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<116,114,121,10,32,32,32,32,116,104,114,111,119,40,123,109,121,95,101,120,99,101,112,116,105,111,110,44,32,34,83,111,109,101,116,104,105,110,103,32,104,97,112,112,101,110,101,100,34,125,41,10,99,97,116,99,104,10,32,32,32,32,116,104,114,111,119,58,123,109,121,95,101,120,99,101,112,116,105,111,110,44,32,68,101,115,99,125,32,45,62,10,32,32,32,32,32,32,32,32,105,111,58,102,111,114,109,97,116,40,115,116,97,110,100,97,114,100,95,101,114,114,111,114,44,32,34,69,114,114,111,114,58,32,126,115,126,110,34,44,32,91,68,101,115,99,93,41,10,101,110,100>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<110,111,99,97,116,99,104>>]},<<32,105,102,32,110,111,116,32,99,97,117,103,104,116,32,98,121,32,97,110,32,101,120,99,101,112,116,105,111,110,32,104,97,110,100,108,101,114,46>>]},{p,[],[<<83,101,101,32,116,104,101,32,103,117,105,100,101,32,97,98,111,117,116,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<101,114,114,111,114,115,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,53,48,49>>,signature => [{attribute,{2064,2},spec,{{throw,1},[{type,{2064,12},bounded_fun,[{type,{2064,12},'fun',[{type,{2064,12},product,[{var,{2064,13},'Any'}]},{type,{2064,21},no_return,[]}]},[{type,{2065,7},constraint,[{atom,{2065,7},is_subtype},[{var,{2065,7},'Any'},{type,{2065,14},term,[]}]]}]]}]}}]}},{{function,time,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2070}],[<<116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,32,97,115,32>>,{code,[],[<<123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125>>]},<<46>>]},{p,[],[<<84,104,101,32,116,105,109,101,32,122,111,110,101,32,97,110,100,32,68,97,121,108,105,103,104,116,32,83,97,118,105,110,103,32,84,105,109,101,32,99,111,114,114,101,99,116,105,111,110,32,100,101,112,101,110,100,32,111,110,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,105,109,101,40,41,46,10,123,57,44,52,50,44,52,52,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,53,50,57>>,signature => [{attribute,{2070,2},spec,{{time,0},[{type,{2070,11},bounded_fun,[{type,{2070,11},'fun',[{type,{2070,11},product,[]},{var,{2070,17},'Time'}]},[{type,{2071,7},constraint,[{atom,{2071,7},is_subtype},[{var,{2071,7},'Time'},{remote_type,{2071,15},[{atom,{2071,15},calendar},{atom,{2071,24},time},[]]}]]}]]}]}}]}},{{function,time_offset,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1668}],[<<116,105,109,101,95,111,102,102,115,101,116,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,32,111,102,102,115,101,116,32,98,101,116,119,101,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,105,110,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,105,109,101,32,117,110,105,116>>]},<<46,32,67,117,114,114,101,110,116,32,116,105,109,101,32,111,102,102,115,101,116,32,97,100,100,101,100,32,116,111,32,97,110,32,69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101,32,103,105,118,101,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101,46>>]},{p,[],[<<84,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,99,104,97,110,103,101,32,100,117,114,105,110,103,32,111,112,101,114,97,116,105,111,110,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<32,117,115,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,99,104,97,110,103,101,32,105,110,32,116,105,109,101,32,111,102,102,115,101,116,32,99,97,110,32,98,101,32,111,98,115,101,114,118,101,100,32,97,116,32,115,108,105,103,104,116,108,121,32,100,105,102,102,101,114,101,110,116,32,112,111,105,110,116,115,32,105,110,32,116,105,109,101,32,98,121,32,100,105,102,102,101,114,101,110,116,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,105,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,77,117,108,116,105,95,84,105,109,101,95,87,97,114,112,95,77,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,117,108,116,105,45,116,105,109,101,32,119,97,114,112,32,109,111,100,101>>]},<<44,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,99,104,97,110,103,101,100,32,119,104,101,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,100,101,116,101,99,116,115,32,116,104,97,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,79,83,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,104,97,115,32,99,104,97,110,103,101,100,46,32,84,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,119,105,108,108,44,32,104,111,119,101,118,101,114,44,32,110,111,116,32,100,101,116,101,99,116,32,116,104,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,119,104,101,110,32,105,116,32,111,99,99,117,114,115,46,32,65,32,116,97,115,107,32,99,104,101,99,107,105,110,103,32,116,104,101,32,116,105,109,101,32,111,102,102,115,101,116,32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,101,120,101,99,117,116,101,32,97,116,32,108,101,97,115,116,32,111,110,99,101,32,97,32,109,105,110,117,116,101,59,32,115,111,44,32,117,110,100,101,114,32,110,111,114,109,97,108,32,111,112,101,114,97,116,105,111,110,32,116,104,105,115,32,105,115,32,116,111,32,98,101,32,100,101,116,101,99,116,101,100,32,119,105,116,104,105,110,32,97,32,109,105,110,117,116,101,44,32,98,117,116,32,100,117,114,105,110,103,32,104,101,97,118,121,32,108,111,97,100,32,105,116,32,99,97,110,32,116,97,107,101,32,108,111,110,103,101,114,32,116,105,109,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,53,52,52>>,signature => [{attribute,{1668,2},spec,{{erlang,time_offset,0},[{type,{1668,25},'fun',[{type,{1668,25},product,[]},{type,{1668,31},integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,time_offset,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1673}],[<<116,105,109,101,95,111,102,102,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,32,111,102,102,115,101,116,32,98,101,116,119,101,101,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,99,111,110,118,101,114,116,101,100,32,105,110,116,111,32,116,104,101,32>>,{code,[],[<<85,110,105,116>>]},<<32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{p,[],[<<83,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116>>]}]},{code,[],[<<40>>]},{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,95,111,102,102,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,95,111,102,102,115,101,116,40,41>>]}]},{code,[],[<<44,32,110,97,116,105,118,101,44,32,85,110,105,116,41>>]},<<32,104,111,119,101,118,101,114,32,111,112,116,105,109,105,122,101,100,32,102,111,114,32,99,111,109,109,111,110,108,121,32,117,115,101,100,32>>,{code,[],[<<85,110,105,116>>]},<<115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,53,55,54>>,signature => [{attribute,{1673,2},spec,{{erlang,time_offset,1},[{type,{1673,25},bounded_fun,[{type,{1673,25},'fun',[{type,{1673,25},product,[{var,{1673,26},'Unit'}]},{type,{1673,35},integer,[]}]},[{type,{1674,7},constraint,[{atom,{1674,7},is_subtype},[{var,{1674,7},'Unit'},{user_type,{1674,15},time_unit,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,timestamp,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1679}],[<<116,105,109,101,115,116,97,109,112,47,48>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<116,105,109,101,115,116,97,109,112>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,99,117,114,114,101,110,116,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,83,121,115,116,101,109,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101>>]},<<32,111,110,32,116,104,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,77,101,103,97,83,101,99,115,44,32,83,101,99,115,44,32,77,105,99,114,111,83,101,99,115,125>>]},<<46,32,84,104,105,115,32,102,111,114,109,97,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,116,105,109,101,115,116,97,109,112,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,116,105,109,101,115,116,97,109,112,47,48>>]}]},<<32,97,110,100,32,116,104,101,32,100,101,112,114,101,99,97,116,101,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,110,111,119,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,110,111,119,47,48>>]}]},<<32,117,115,101,46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,101,32,101,120,105,115,116,101,110,99,101,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,115,116,97,109,112,40,41>>]},<<32,105,115,32,112,117,114,101,108,121,32,116,111,32,115,105,109,112,108,105,102,121,32,117,115,101,32,102,111,114,32,101,120,105,115,116,105,110,103,32,99,111,100,101,32,116,104,97,116,32,97,115,115,117,109,101,115,32,116,104,105,115,32,116,105,109,101,32,115,116,97,109,112,32,102,111,114,109,97,116,46,32,67,117,114,114,101,110,116,32,69,114,108,97,110,103,32,115,121,115,116,101,109,32,116,105,109,101,32,99,97,110,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,108,121,32,98,101,32,114,101,116,114,105,101,118,101,100,32,105,110,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,111,102,32,121,111,117,114,32,99,104,111,105,99,101,32,117,115,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,116,105,109,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,47,49>>]}]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,115,116,97,109,112,40,41>>]},<<32,66,73,70,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<116,105,109,101,115,116,97,109,112,40,41,32,45,62,10,32,32,32,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,61,32,101,114,108,97,110,103,58,115,121,115,116,101,109,95,116,105,109,101,40,109,105,99,114,111,115,101,99,111,110,100,41,44,10,32,32,32,32,77,101,103,97,83,101,99,115,32,61,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,100,105,118,32,49,48,48,48,95,48,48,48,95,48,48,48,95,48,48,48,44,10,32,32,32,32,83,101,99,115,32,61,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,100,105,118,32,49,48,48,48,95,48,48,48,32,45,32,77,101,103,97,83,101,99,115,42,49,48,48,48,95,48,48,48,44,10,32,32,32,32,77,105,99,114,111,83,101,99,115,32,61,32,69,114,108,97,110,103,83,121,115,116,101,109,84,105,109,101,32,114,101,109,32,49,48,48,48,95,48,48,48,44,10,32,32,32,32,123,77,101,103,97,83,101,99,115,44,32,83,101,99,115,44,32,77,105,99,114,111,83,101,99,115,125,46>>]}]},{p,[],[<<73,116,44,32,104,111,119,101,118,101,114,44,32,117,115,101,115,32,97,32,110,97,116,105,118,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,98,117,105,108,100,32,103,97,114,98,97,103,101,32,111,110,32,116,104,101,32,104,101,97,112,32,97,110,100,32,119,105,116,104,32,115,108,105,103,104,116,108,121,32,98,101,116,116,101,114,32,112,101,114,102,111,114,109,97,110,99,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,116,105,109,101,32,105,115,32>>,{em,[],[<<110,111,116>>]},<<32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,116,105,109,101,32,105,110,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,115,101,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,87,97,114,112,95,77,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,105,109,101,32,119,97,114,112,32,109,111,100,101,115>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,53,57,53>>,signature => [{attribute,{1679,2},spec,{{erlang,timestamp,0},[{type,{1679,23},bounded_fun,[{type,{1679,23},'fun',[{type,{1679,23},product,[]},{var,{1679,29},'Timestamp'}]},[{type,{1680,7},constraint,[{atom,{1680,7},is_subtype},[{var,{1680,7},'Timestamp'},{user_type,{1680,20},timestamp,[]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,tl,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2762}],[<<116,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,116,97,105,108,32,111,102,32>>,{code,[],[<<76,105,115,116>>]},<<44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,108,105,115,116,32,109,105,110,117,115,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,44,32,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,93,41,46,10,91,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,93>>]}]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,93,41,46,10,91,93>>]}]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,44,32,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,32,124,32,105,109,112,114,111,112,101,114,95,101,110,100,93,41,46,10,91,103,117,105,108,105,101,115,44,32,98,101,97,115,116,105,101,115,32,124,32,105,109,112,114,111,112,101,114,95,101,110,100,93>>]}]},{pre,[],[{code,[],[<<62,32,116,108,40,91,103,101,101,115,116,105,101,115,32,124,32,105,109,112,114,111,112,101,114,95,101,110,100,93,41,46,10,105,109,112,114,111,112,101,114,95,101,110,100>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<76,105,115,116>>]},<<32,105,115,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32>>,{code,[],[<<91,93>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,54,51,52>>,signature => [{attribute,{2762,2},spec,{{tl,1},[{type,{2762,9},bounded_fun,[{type,{2762,9},'fun',[{type,{2762,9},product,[{var,{2762,10},'List'}]},{type,{2762,19},term,[]}]},[{type,{2763,7},constraint,[{atom,{2763,7},is_subtype},[{var,{2763,7},'List'},{type,{2763,15},nonempty_maybe_improper_list,[]}]]}]]}]}}]}},{{function,trace,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2076}],[<<116,114,97,99,101,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<116,114,97,99,101,95,102,108,97,103>>}],[]}]},{p,[],[<<84,117,114,110,115,32,111,110,32,40,105,102,32>>,{code,[],[<<72,111,119,32,61,61,32,116,114,117,101>>]},<<41,32,111,114,32,111,102,102,32,40,105,102,32>>,{code,[],[<<72,111,119,32,61,61,32,102,97,108,115,101>>]},<<41,32,116,104,101,32,116,114,97,99,101,32,102,108,97,103,115,32,105,110,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,114,111,99,101,115,115,101,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<46>>]},{p,[],[{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32,101,105,116,104,101,114,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,32,102,111,114,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,44,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,97,110,100,32,97,108,108,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,97,108,108,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<112,111,114,116,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,111,114,116,115,32,97,110,100,32,97,108,108,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<101,120,105,115,116,105,110,103>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,46>>]},{dt,[],[{code,[],[<<101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,101,115,46>>]},{dt,[],[{code,[],[<<101,120,105,115,116,105,110,103,95,112,111,114,116,115>>]}]},{dd,[],[<<65,108,108,32,99,117,114,114,101,110,116,108,121,32,101,120,105,115,116,105,110,103,32,112,111,114,116,115,46>>]},{dt,[],[{code,[],[<<110,101,119>>]}]},{dd,[],[<<65,108,108,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,112,111,114,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<110,101,119,95,112,114,111,99,101,115,115,101,115>>]}]},{dd,[],[<<65,108,108,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]},{dt,[],[{code,[],[<<110,101,119,95,112,111,114,116,115>>]}]},{dd,[],[<<65,108,108,32,112,111,114,116,115,32,116,104,97,116,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,105,110,32,116,104,101,32,102,117,116,117,114,101,46>>]}]},{p,[],[{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,108,97,103,115,32,40,116,104,101,32,34,109,101,115,115,97,103,101,32,116,97,103,115,34,32,114,101,102,101,114,115,32,116,111,32,116,104,101,32,108,105,115,116,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,114,97,99,101,32,109,101,115,115,97,103,101,115>>]}]},<<41,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[{p,[],[<<83,101,116,115,32,97,108,108,32,116,114,97,99,101,32,102,108,97,103,115,32,101,120,99,101,112,116,32>>,{code,[],[<<116,114,97,99,101,114>>]},<<32,97,110,100,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<44,32,119,104,105,99,104,32,97,114,101,32,105,110,32,116,104,101,105,114,32,110,97,116,117,114,101,32,100,105,102,102,101,114,101,110,116,32,116,104,97,110,32,116,104,101,32,111,116,104,101,114,115,46>>]}]},{dt,[],[{code,[],[<<115,101,110,100>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,101,110,100,105,110,103,32,111,102,32,109,101,115,115,97,103,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,110,100>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<39,114,101,99,101,105,118,101,39>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,114,101,99,101,105,118,105,110,103,32,111,102,32,109,101,115,115,97,103,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,99,101,105,118,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<39,114,101,99,101,105,118,101,39>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,99,101,114,116,97,105,110,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,83,112,101,99,105,102,121,32,119,104,105,99,104,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,116,111,32,116,114,97,99,101,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,97,108,108>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,102,114,111,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,102,114,111,109>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<115,105,108,101,110,116>>]}]},{dd,[],[{p,[],[<<85,115,101,100,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,46,32,84,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<114,101,116,117,114,110,95,102,114,111,109>>]},<<44,32,97,110,100,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,105,110,104,105,98,105,116,101,100,32,105,102,32,116,104,105,115,32,102,108,97,103,32,105,115,32,115,101,116,44,32,98,117,116,32,116,104,101,121,32,97,114,101,32,101,120,101,99,117,116,101,100,32,97,115,32,110,111,114,109,97,108,32,105,102,32,116,104,101,114,101,32,97,114,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46>>]},{p,[],[<<83,105,108,101,110,116,32,109,111,100,101,32,105,115,32,105,110,104,105,98,105,116,101,100,32,98,121,32,101,120,101,99,117,116,105,110,103,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,40,95,44,32,102,97,108,115,101,44,32,91,115,105,108,101,110,116,124,95,93,41>>]},<<44,32,111,114,32,98,121,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,101,120,101,99,117,116,105,110,103,32,116,104,101,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,115,105,108,101,110,116,44,32,102,97,108,115,101,125>>]},<<46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<115,105,108,101,110,116>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,97,99,105,108,105,116,97,116,101,115,32,115,101,116,116,105,110,103,32,117,112,32,97,32,116,114,97,99,101,32,111,110,32,109,97,110,121,32,111,114,32,101,118,101,110,32,97,108,108,32,112,114,111,99,101,115,115,101,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,84,104,101,32,116,114,97,99,101,32,99,97,110,32,116,104,101,110,32,98,101,32,97,99,116,105,118,97,116,101,100,32,97,110,100,32,100,101,97,99,116,105,118,97,116,101,100,32,117,115,105,110,103,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,115,105,108,101,110,116,44,66,111,111,108,125>>]},<<44,32,103,105,118,105,110,103,32,97,32,104,105,103,104,32,100,101,103,114,101,101,32,111,102,32,99,111,110,116,114,111,108,32,111,102,32,119,104,105,99,104,32,102,117,110,99,116,105,111,110,115,32,119,105,116,104,32,119,104,105,99,104,32,97,114,103,117,109,101,110,116,115,32,116,104,97,116,32,116,114,105,103,103,101,114,32,116,104,101,32,116,114,97,99,101,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,97,108,108>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,102,114,111,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,102,114,111,109>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,116,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,116,111>>]}]},<<46,32,79,114,32,114,97,116,104,101,114,44,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,46>>]}]},{dt,[],[{code,[],[<<114,101,116,117,114,110,95,116,111>>]}]},{dd,[],[{p,[],[<<85,115,101,100,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,46,32,84,114,97,99,101,115,32,116,104,101,32,114,101,116,117,114,110,32,102,114,111,109,32,97,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,32,98,97,99,107,32,116,111,32,105,116,115,32,99,97,108,108,101,114,46,32,79,110,108,121,32,119,111,114,107,115,32,102,111,114,32,102,117,110,99,116,105,111,110,115,32,116,114,97,99,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,116,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]},{p,[],[<<84,104,101,32,115,101,109,97,110,116,105,99,115,32,105,115,32,116,104,97,116,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,119,104,101,110,32,97,32,99,97,108,108,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,44,32,116,104,97,116,32,105,115,44,32,119,104,101,110,32,97,32,99,104,97,105,110,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,115,32,101,110,100,115,46,32,79,110,108,121,32,111,110,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,112,101,114,32,99,104,97,105,110,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,115,44,32,115,111,32,116,104,101,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,110,101,115,115,32,102,111,114,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,114,101,32,107,101,112,116,32,119,104,105,108,101,32,116,114,97,99,105,110,103,32,119,105,116,104,32,116,104,105,115,32,102,108,97,103,46,32,85,115,105,110,103,32>>,{code,[],[<<99,97,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,116,114,97,99,101,32,116,111,103,101,116,104,101,114,32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,107,110,111,119,32,101,120,97,99,116,108,121,32,105,110,32,119,104,105,99,104,32,102,117,110,99,116,105,111,110,32,97,32,112,114,111,99,101,115,115,32,101,120,101,99,117,116,101,115,32,97,116,32,97,110,121,32,116,105,109,101,46>>]},{p,[],[<<84,111,32,103,101,116,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,99,111,110,116,97,105,110,105,110,103,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,102,114,111,109,32,102,117,110,99,116,105,111,110,115,44,32,117,115,101,32,116,104,101,32>>,{code,[],[<<123,114,101,116,117,114,110,95,116,114,97,99,101,125>>]},<<32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,99,116,105,111,110,32,105,110,115,116,101,97,100,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,116,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,116,117,114,110,95,116,111>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,112,114,111,99,101,115,115,45,114,101,108,97,116,101,100,32,101,118,101,110,116,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,112,97,119,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,112,97,119,110,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,120,105,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,108,105,110,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,105,110,107>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,108,105,110,107>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,108,105,110,107>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,108,105,110,107,101,100>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<112,111,114,116,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,112,111,114,116,45,114,101,108,97,116,101,100,32,101,118,101,110,116,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,112,101,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,112,101,110>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,108,111,115,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<99,108,111,115,101,100>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,114,101,103,105,115,116,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,114,101,103,105,115,116,101,114>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,108,105,110,107,101,100>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,105,110,103>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<101,120,105,116,105,110,103>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,101,120,105,116,105,110,103,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,101,120,105,116,105,110,103,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110,95,101,120,105,116,105,110,103>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,105,110,103,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116,95,101,120,105,116,105,110,103>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,101,100,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116,95,101,120,105,116,101,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,105,110,103,95,112,114,111,99,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,112,114,111,99,101,115,115,101,115,32,106,117,115,116,32,108,105,107,101,32>>,{code,[],[<<114,117,110,110,105,110,103>>]},<<46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,111,112,116,105,111,110,32,97,108,115,111,32,105,110,99,108,117,100,101,115,32,115,99,104,101,100,117,108,101,32,101,118,101,110,116,115,32,119,104,101,110,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,101,99,117,116,101,115,32,119,105,116,104,105,110,32,116,104,101,32,99,111,110,116,101,120,116,32,111,102,32,97,32,112,111,114,116,32,119,105,116,104,111,117,116,32,98,101,105,110,103,32,115,99,104,101,100,117,108,101,100,32,111,117,116,32,105,116,115,101,108,102,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,114,111,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<114,117,110,110,105,110,103,95,112,111,114,116,115>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,115,99,104,101,100,117,108,105,110,103,32,111,102,32,112,111,114,116,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,111,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,110>>]}]},<<32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,111,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,117,116>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]}]},{dd,[],[{p,[],[<<84,114,97,99,101,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,115,32,111,102,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<77,101,115,115,97,103,101,32,116,97,103,115,58,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]}]},<<44,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,101,110,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<103,99,95,109,105,110,111,114,95,101,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<73,110,99,108,117,100,101,115,32,97,32,116,105,109,101,32,115,116,97,109,112,32,105,110,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,32,97,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,110,111,119,40,41>>]},<<46>>]}]},{dt,[],[{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<65,32,103,108,111,98,97,108,32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,116,104,101,32,69,114,108,97,110,103,32,110,111,100,101,32,116,104,97,116,32,109,97,107,101,115,32,97,108,108,32,116,114,97,99,101,32,116,105,109,101,32,115,116,97,109,112,115,32,117,115,105,110,103,32,102,108,97,103,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<32,116,111,32,98,101,32,105,110,32,67,80,85,32,116,105,109,101,44,32,110,111,116,32,119,97,108,108,32,99,108,111,99,107,32,116,105,109,101,46,32,84,104,97,116,32,105,115,44,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,110,111,116,32,98,101,32,117,115,101,100,32,105,102,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<32,111,114,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,101,110,97,98,108,101,100,46,32,79,110,108,121,32,97,108,108,111,119,101,100,32,119,105,116,104,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99,61,61,97,108,108>>]},<<46,32,73,102,32,116,104,101,32,104,111,115,116,32,109,97,99,104,105,110,101,32,79,83,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,104,105,103,104,45,114,101,115,111,108,117,116,105,111,110,32,67,80,85,32,116,105,109,101,32,109,101,97,115,117,114,101,109,101,110,116,115,44,32>>,{code,[],[<<116,114,97,99,101,47,51>>]},<<32,101,120,105,116,115,32,119,105,116,104,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,109,111,115,116,32,79,83,32,100,111,32,110,111,116,32,115,121,110,99,104,114,111,110,105,122,101,32,116,104,105,115,32,118,97,108,117,101,32,97,99,114,111,115,115,32,99,111,114,101,115,44,32,115,111,32,98,101,32,112,114,101,112,97,114,101,100,32,116,104,97,116,32,116,105,109,101,32,99,97,110,32,115,101,101,109,32,116,111,32,103,111,32,98,97,99,107,119,97,114,100,115,32,119,104,101,110,32,117,115,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<73,110,99,108,117,100,101,115,32,97,110,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,116,105,109,101,32,115,116,97,109,112,32,105,110,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41>>]}]},<<46,32,84,104,105,115,32,102,108,97,103,32,111,118,101,114,114,105,100,101,115,32,102,108,97,103,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]}]},{dd,[],[{p,[],[<<73,110,99,108,117,100,101,115,32,97,110,32,116,105,109,101,32,115,116,97,109,112,32,99,111,110,115,105,115,116,105,110,103,32,111,102,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,69,114,108,97,110,103,95,77,111,110,111,116,111,110,105,99,95,84,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,108,97,110,103,32,109,111,110,111,116,111,110,105,99,32,116,105,109,101>>]},<<32,97,110,100,32,97,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,105,110,116,101,103,101,114,32,105,110,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32,84,104,101,32,116,105,109,101,32,115,116,97,109,112,32,40,84,115,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,102,111,114,109,97,116,32,97,110,100,32,118,97,108,117,101,32,97,115,32,112,114,111,100,117,99,101,100,32,98,121,32>>,{code,[],[<<123>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,111,116,111,110,105,99,95,116,105,109,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,109,111,110,111,116,111,110,105,99,95,116,105,109,101,40,110,97,110,111,115,101,99,111,110,100,41>>]}]},{code,[],[<<44>>]},<<32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]}]},{code,[],[<<125>>]},<<46,32,84,104,105,115,32,102,108,97,103,32,111,118,101,114,114,105,100,101,115,32,102,108,97,103,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,114,105,116,121>>]}]},{dd,[],[{p,[],[<<85,115,101,100,32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,46,32>>,{code,[],[<<123,77,44,32,70,44,32,65,114,105,116,121,125>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<123,77,44,32,70,44,32,65,114,103,115,125>>]},<<32,105,110,32,99,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,97,110,121,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,105,110,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,116,104,101,32,102,105,114,115,116,32,112,114,111,99,101,115,115,32,99,114,101,97,116,101,100,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,101,120,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,97,110,121,32,112,114,111,99,101,115,115,32,108,105,110,107,101,100,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,105,110,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]},<<46>>]}]},{dt,[],[{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,116,104,101,32,102,105,114,115,116,32,112,114,111,99,101,115,115,32,108,105,110,107,101,100,32,116,111,32,98,121,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,104,101,114,105,116,32,105,116,115,32,116,114,97,99,101,32,102,108,97,103,115,44,32,101,120,99,108,117,100,105,110,103,32,102,108,97,103,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,99,101,114,44,32,84,114,97,99,101,114,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,119,104,101,114,101,32,116,111,32,115,101,110,100,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32>>,{code,[],[<<84,114,97,99,101,114>>]},<<32,109,117,115,116,32,98,101,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,108,111,99,97,108,32,112,114,111,99,101,115,115,32,111,114,32,116,104,101,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,97,32,108,111,99,97,108,32,112,111,114,116,46>>]}]},{dt,[],[{code,[],[<<123,116,114,97,99,101,114,44,32,84,114,97,99,101,114,77,111,100,117,108,101,44,32,84,114,97,99,101,114,83,116,97,116,101,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,97,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,105,115,32,116,111,32,98,101,32,99,97,108,108,101,100,32,105,110,115,116,101,97,100,32,111,102,32,115,101,110,100,105,110,103,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,46,32,84,104,101,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,99,97,110,32,116,104,101,110,32,105,103,110,111,114,101,32,111,114,32,99,104,97,110,103,101,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,111,110,32,104,111,119,32,116,111,32,119,114,105,116,101,32,97,32,116,114,97,99,101,114,32,109,111,100,117,108,101,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,116,114,97,99,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,116,114,97,99,101,114,40,51,41>>]}]},<<46>>]}]}]},{p,[],[<<73,102,32,110,111,32>>,{code,[],[<<116,114,97,99,101,114>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,114,101,99,101,105,118,101,115,32,97,108,108,32,116,104,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46>>]},{p,[],[<<84,104,101,32,101,102,102,101,99,116,32,111,102,32,99,111,109,98,105,110,105,110,103,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]},<<32,119,105,116,104,32>>,{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]},<<32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,108,105,110,107>>]},<<32,97,108,111,110,101,46,32,76,105,107,101,119,105,115,101,32,102,111,114,32>>,{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]},<<32,97,110,100,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]},<<46>>]},{p,[],[<<84,104,101,32,116,114,97,99,105,110,103,32,112,114,111,99,101,115,115,32,114,101,99,101,105,118,101,115,32,116,104,101,32>>,{em,[],[<<116,114,97,99,101,32,109,101,115,115,97,103,101,115>>]},<<32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,108,105,115,116,46,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,102,32,116,104,101,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,105,110,32,119,104,105,99,104,32,116,104,101,32,116,114,97,99,101,100,32,101,118,101,110,116,32,104,97,115,32,111,99,99,117,114,114,101,100,46,32,84,104,101,32,116,104,105,114,100,32,116,117,112,108,101,32,101,108,101,109,101,110,116,32,105,115,32,116,104,101,32,109,101,115,115,97,103,101,32,116,97,103,46>>]},{p,[],[<<73,102,32,102,108,97,103,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<44,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32,111,114,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,105,114,115,116,32,116,117,112,108,101,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<116,114,97,99,101,95,116,115>>]},<<32,105,110,115,116,101,97,100,44,32,97,110,100,32,116,104,101,32,116,105,109,101,32,115,116,97,109,112,32,105,115,32,97,100,100,101,100,32,97,115,32,97,110,32,101,120,116,114,97,32,101,108,101,109,101,110,116,32,108,97,115,116,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,116,117,112,108,101,46,32,73,102,32,109,117,108,116,105,112,108,101,32,116,105,109,101,32,115,116,97,109,112,32,102,108,97,103,115,32,97,114,101,32,112,97,115,115,101,100,44,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<32,104,97,115,32,112,114,101,99,101,100,101,110,99,101,32,111,118,101,114,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32,119,104,105,99,104,32,105,110,32,116,117,114,110,32,104,97,115,32,112,114,101,99,101,100,101,110,99,101,32,111,118,101,114,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<46,32,65,108,108,32,116,105,109,101,32,115,116,97,109,112,32,102,108,97,103,115,32,97,114,101,32,114,101,109,101,109,98,101,114,101,100,44,32,115,111,32,105,102,32,116,119,111,32,97,114,101,32,112,97,115,115,101,100,32,97,110,100,32,116,104,101,32,111,110,101,32,119,105,116,104,32,104,105,103,104,101,115,116,32,112,114,101,99,101,100,101,110,99,101,32,108,97,116,101,114,32,105,115,32,100,105,115,97,98,108,101,100,44,32,116,104,101,32,111,116,104,101,114,32,111,110,101,32,98,101,99,111,109,101,115,32,97,99,116,105,118,101,46>>]},{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,40,97,112,112,108,105,99,97,98,108,101,32,111,110,108,121,32,102,111,114,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<115,101,110,100>>]},<<32,97,110,100,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,105,110,103,41,32,99,111,110,116,97,105,110,115,32,97,32>>,{code,[],[<<123,109,101,115,115,97,103,101,125>>]},<<32,97,99,116,105,111,110,32,102,117,110,99,116,105,111,110,32,119,105,116,104,32,97,32,110,111,110,45,98,111,111,108,101,97,110,32,118,97,108,117,101,44,32,116,104,97,116,32,118,97,108,117,101,32,105,115,32,97,100,100,101,100,32,97,115,32,97,110,32,101,120,116,114,97,32,101,108,101,109,101,110,116,32,116,111,32,116,104,101,32,109,101,115,115,97,103,101,32,116,117,112,108,101,32,101,105,116,104,101,114,32,105,110,32,116,104,101,32,108,97,115,116,32,112,111,115,105,116,105,111,110,32,111,114,32,98,101,102,111,114,101,32,116,104,101,32,116,105,109,101,115,116,97,109,112,32,40,105,102,32,105,116,32,105,115,32,112,114,101,115,101,110,116,41,46>>]},{p,[],[<<84,114,97,99,101,32,109,101,115,115,97,103,101,115,58>>]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115>>}],[]},{dl,[],[{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,115,101,110,100,44,32,77,115,103,44,32,84,111,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,115,101,110,100,115,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<32,116,111,32,112,114,111,99,101,115,115,32>>,{code,[],[<<84,111>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,115,101,110,100,95,116,111,95,110,111,110,95,101,120,105,115,116,105,110,103,95,112,114,111,99,101,115,115,44,32,77,115,103,44,32,84,111,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,115,101,110,100,115,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<32,116,111,32,116,104,101,32,110,111,110,45,101,120,105,115,116,105,110,103,32,112,114,111,99,101,115,115,32>>,{code,[],[<<84,111>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,99,101,105,118,101>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,39,114,101,99,101,105,118,101,39,44,32,77,115,103,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,114,101,99,101,105,118,101,115,32,109,101,115,115,97,103,101,32>>,{code,[],[<<77,115,103>>]},<<46,32,73,102,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,116,105,109,101,45,111,117,116,44,32,97,32,114,101,99,101,105,118,101,32,115,116,97,116,101,109,101,110,116,32,99,97,110,32,104,97,118,101,32,116,105,109,101,100,32,111,117,116,44,32,111,114,32,116,104,101,32,112,114,111,99,101,115,115,32,114,101,99,101,105,118,101,100,32,97,32,109,101,115,115,97,103,101,32,119,105,116,104,32,116,104,101,32,112,97,121,108,111,97,100,32>>,{code,[],[<<116,105,109,101,111,117,116>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,97,108,108>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,99,97,108,108,44,32,123,77,44,32,70,44,32,65,114,103,115,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,99,97,108,108,115,32,97,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,111,102,32,99,97,108,108,115,32,97,114,101,32,110,101,118,101,114,32,115,117,112,112,108,105,101,100,44,32,111,110,108,121,32,116,104,101,32,99,97,108,108,32,97,110,100,32,105,116,115,32,97,114,103,117,109,101,110,116,115,46>>]},{p,[],[<<84,114,97,99,101,32,102,108,97,103,32>>,{code,[],[<<97,114,105,116,121>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,105,115,32,109,101,115,115,97,103,101,44,32,115,111,32,116,104,97,116,32>>,{code,[],[<<65,114,105,116,121>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,115,116,101,97,100,32,111,102,32>>,{code,[],[<<65,114,103,115>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,116,111>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,114,101,116,117,114,110,95,116,111,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,114,101,116,117,114,110,115,32>>,{em,[],[<<116,111>>]},<<32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,46,32,84,104,105,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,98,111,116,104,32,116,104,101,32,102,108,97,103,115,32>>,{code,[],[<<99,97,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,97,114,101,32,115,101,116,44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,115,101,116,32,116,111,32,98,101,32,116,114,97,99,101,100,32,111,110,32>>,{em,[],[<<108,111,99,97,108>>]},<<32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,84,104,101,32,109,101,115,115,97,103,101,32,105,115,32,111,110,108,121,32,115,101,110,116,32,119,104,101,110,32,114,101,116,117,114,110,105,110,103,32,102,114,111,109,32,97,32,99,104,97,105,110,32,111,102,32,116,97,105,108,32,114,101,99,117,114,115,105,118,101,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32,119,104,101,114,101,32,97,116,32,108,101,97,115,116,32,111,110,101,32,99,97,108,108,32,103,101,110,101,114,97,116,101,100,32,97,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,40,116,104,97,116,32,105,115,44,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,109,97,116,99,104,101,100,44,32,97,110,100,32>>,{code,[],[<<123,109,101,115,115,97,103,101,44,32,102,97,108,115,101,125>>]},<<32,119,97,115,32,110,111,116,32,97,110,32,97,99,116,105,111,110,41,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,116,117,114,110,95,102,114,111,109>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,114,101,116,117,114,110,95,102,114,111,109,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,44,32,82,101,116,117,114,110,86,97,108,117,101,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,114,101,116,117,114,110,115,32>>,{em,[],[<<102,114,111,109>>]},<<32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,46,32,84,104,105,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,102,108,97,103,32>>,{code,[],[<<99,97,108,108>>]},<<32,105,115,32,115,101,116,44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,104,97,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,119,105,116,104,32,97,32>>,{code,[],[<<114,101,116,117,114,110,95,116,114,97,99,101>>]},<<32,111,114,32>>,{code,[],[<<101,120,99,101,112,116,105,111,110,95,116,114,97,99,101>>]},<<32,97,99,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,99,101,112,116,105,111,110,95,102,114,111,109>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,101,120,99,101,112,116,105,111,110,95,102,114,111,109,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,44,32,123,67,108,97,115,115,44,32,86,97,108,117,101,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,105,116,115,32>>,{em,[],[<<102,114,111,109>>]},<<32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,32,98,101,99,97,117,115,101,32,111,102,32,97,110,32,101,120,99,101,112,116,105,111,110,46,32,84,104,105,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,105,102,32,102,108,97,103,32>>,{code,[],[<<99,97,108,108>>]},<<32,105,115,32,115,101,116,44,32,97,110,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,104,97,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,119,105,116,104,32,97,110,32>>,{code,[],[<<101,120,99,101,112,116,105,111,110,95,116,114,97,99,101>>]},<<32,97,99,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,115,112,97,119,110,44,32,80,105,100,50,44,32,123,77,44,32,70,44,32,65,114,103,115,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,115,112,97,119,110,115,32,97,32,110,101,119,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,97,115,32,101,110,116,114,121,32,112,111,105,110,116,46>>]},{p,[],[{code,[],[<<65,114,103,115>>]},<<32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,116,104,101,32,97,114,103,117,109,101,110,116,32,108,105,115,116,44,32,98,117,116,32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,32,105,102,32,116,104,101,32,115,112,97,119,110,32,105,115,32,101,114,114,111,110,101,111,117,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,115,112,97,119,110,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,115,112,97,119,110,101,100,44,32,80,105,100,50,44,32,123,77,44,32,70,44,32,65,114,103,115,125,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,115,112,97,119,110,101,100,32,98,121,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<32,119,105,116,104,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,32,99,97,108,108,32,97,115,32,101,110,116,114,121,32,112,111,105,110,116,46>>]},{p,[],[{code,[],[<<65,114,103,115>>]},<<32,105,115,32,115,117,112,112,111,115,101,100,32,116,111,32,98,101,32,116,104,101,32,97,114,103,117,109,101,110,116,32,108,105,115,116,44,32,98,117,116,32,99,97,110,32,98,101,32,97,110,121,32,116,101,114,109,32,105,102,32,116,104,101,32,115,112,97,119,110,32,105,115,32,101,114,114,111,110,101,111,117,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,101,120,105,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,101,120,105,116,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,101,120,105,116,115,32,119,105,116,104,32,114,101,97,115,111,110,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,114,101,103,105,115,116,101,114>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,114,101,103,105,115,116,101,114,44,32,82,101,103,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,114,101,103,105,115,116,101,114,101,100,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,114,101,103,105,115,116,101,114>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,117,110,114,101,103,105,115,116,101,114,44,32,82,101,103,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,116,104,101,32,110,97,109,101,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,117,110,114,101,103,105,115,116,101,114,101,100,46,32,84,104,105,115,32,105,115,32,100,111,110,101,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,119,104,101,110,32,97,32,114,101,103,105,115,116,101,114,101,100,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,101,120,105,116,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,108,105,110,107>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,108,105,110,107,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,108,105,110,107,115,32,116,111,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,117,110,108,105,110,107>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,117,110,108,105,110,107,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,114,101,109,111,118,101,115,32,116,104,101,32,108,105,110,107,32,102,114,111,109,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,108,105,110,107,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,103,101,116,116,105,110,103,95,108,105,110,107,101,100,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,108,105,110,107,101,100,32,116,111,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,80,111,114,116,44,32,103,101,116,116,105,110,103,95,117,110,108,105,110,107,101,100,44,32,80,105,100,50,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100,80,111,114,116>>]},<<32,103,101,116,115,32,117,110,108,105,110,107,101,100,32,102,114,111,109,32,97,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100,50>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,112,101,110>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,111,112,101,110,44,32,80,105,100,44,32,68,114,105,118,101,114,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,111,112,101,110,115,32,97,32,110,101,119,32,112,111,114,116,32>>,{code,[],[<<80,111,114,116>>]},<<32,119,105,116,104,32,116,104,101,32,114,117,110,110,105,110,103,32>>,{code,[],[<<68,114,105,118,101,114>>]},<<46>>]},{p,[],[{code,[],[<<68,114,105,118,101,114>>]},<<32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,100,114,105,118,101,114,32,97,115,32,97,110,32,97,116,111,109,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,99,108,111,115,101,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,99,108,111,115,101,100,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,99,108,111,115,101,115,32,119,105,116,104,32>>,{code,[],[<<82,101,97,115,111,110>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,114,111,99>>}],[]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,101,120,105,116,105,110,103,95,112,114,111,99>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,105,110,32,124,32,105,110,95,101,120,105,116,105,110,103,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,114,117,110,46,32,84,104,101,32,112,114,111,99,101,115,115,32,114,117,110,115,32,105,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,77,44,32,70,44,32,65,114,105,116,121,125>>]},<<46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,114,111,99>>}],[]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,105,110,103,95,112,114,111,99>>}],[]},{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,101,120,105,116,101,100,95,112,114,111,99>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,111,117,116,32,124,32,111,117,116,95,101,120,105,116,105,110,103,32,124,32,111,117,116,95,101,120,105,116,101,100,44,32,123,77,44,32,70,44,32,65,114,105,116,121,125,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,111,117,116,46,32,84,104,101,32,112,114,111,99,101,115,115,32,119,97,115,32,114,117,110,110,105,110,103,32,105,110,32,102,117,110,99,116,105,111,110,32,123,77,44,32,70,44,32,65,114,105,116,121,125,46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,105,110,95,112,111,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,105,110,44,32,67,111,109,109,97,110,100,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,116,111,32,114,117,110,46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,105,115,32,116,104,101,32,102,105,114,115,116,32,116,104,105,110,103,32,116,104,101,32,112,111,114,116,32,119,105,108,108,32,101,120,101,99,117,116,101,44,32,105,116,32,99,97,110,32,104,111,119,101,118,101,114,32,114,117,110,32,115,101,118,101,114,97,108,32,99,111,109,109,97,110,100,115,32,98,101,102,111,114,101,32,98,101,105,110,103,32,115,99,104,101,100,117,108,101,100,32,111,117,116,46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]},{p,[],[<<84,104,101,32,112,111,115,115,105,98,108,101,32,99,111,109,109,97,110,100,115,32,97,114,101,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<99,108,111,115,101>>]},<<44,32>>,{code,[],[<<99,111,109,109,97,110,100>>]},<<44,32>>,{code,[],[<<99,111,110,110,101,99,116>>]},<<44,32>>,{code,[],[<<99,111,110,116,114,111,108>>]},<<44,32>>,{code,[],[<<102,108,117,115,104>>]},<<44,32>>,{code,[],[<<105,110,102,111>>]},<<44,32>>,{code,[],[<<108,105,110,107>>]},<<44,32>>,{code,[],[<<111,112,101,110>>]},<<44,32,97,110,100,32>>,{code,[],[<<117,110,108,105,110,107>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,111,117,116,95,112,111,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,111,114,116,44,32,111,117,116,44,32,67,111,109,109,97,110,100,32,124,32,48,125>>]}]},{dd,[],[{p,[],[<<87,104,101,110,32>>,{code,[],[<<80,111,114,116>>]},<<32,105,115,32,115,99,104,101,100,117,108,101,100,32,111,117,116,46,32,84,104,101,32,108,97,115,116,32,99,111,109,109,97,110,100,32,114,117,110,32,119,97,115,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<46,32,79,110,32,115,111,109,101,32,114,97,114,101,32,111,99,99,97,115,105,111,110,115,44,32,116,104,101,32,99,117,114,114,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,100,101,116,101,114,109,105,110,101,100,44,32,116,104,101,110,32,116,104,101,32,108,97,115,116,32,101,108,101,109,101,110,116,32,105,115,32>>,{code,[],[<<48>>]},<<46,32>>,{code,[],[<<67,111,109,109,97,110,100>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32,99,111,109,109,97,110,100,115,32,97,115,32>>,{code,[],[<<105,110>>]}]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,115,116,97,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,105,110,111,114,95,115,116,97,114,116,44,32,73,110,102,111,125>>]}]},{dd,[],[{a,[{id,<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>}],[]},{p,[],[<<83,101,110,116,32,119,104,101,110,32,97,32,121,111,117,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,97,98,111,117,116,32,116,111,32,98,101,32,115,116,97,114,116,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,119,111,45,101,108,101,109,101,110,116,32,116,117,112,108,101,115,44,32,119,104,101,114,101,32,116,104,101,32,102,105,114,115,116,32,101,108,101,109,101,110,116,32,105,115,32,97,32,107,101,121,44,32,97,110,100,32,116,104,101,32,115,101,99,111,110,100,32,105,115,32,116,104,101,32,118,97,108,117,101,46,32,68,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,97,110,121,32,111,114,100,101,114,32,111,102,32,116,104,101,32,116,117,112,108,101,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,107,101,121,115,32,97,114,101,32,100,101,102,105,110,101,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,117,115,101,100,32,112,97,114,116,32,111,102,32,116,104,101,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,98,108,111,99,107,32,117,115,101,100,32,102,111,114,32,115,116,111,114,105,110,103,32,116,104,101,32,104,101,97,112,32,97,110,100,32,116,104,101,32,115,116,97,99,107,46>>]},{dt,[],[{code,[],[<<111,108,100,95,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,117,115,101,100,32,112,97,114,116,32,111,102,32,116,104,101,32,111,108,100,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<111,108,100,95,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,101,109,111,114,121,32,98,108,111,99,107,32,117,115,101,100,32,102,111,114,32,115,116,111,114,105,110,103,32,116,104,101,32,111,108,100,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<115,116,97,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,115,116,97,99,107,46>>]},{dt,[],[{code,[],[<<114,101,99,101,110,116,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,100,97,116,97,32,116,104,97,116,32,115,117,114,118,105,118,101,100,32,116,104,101,32,112,114,101,118,105,111,117,115,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{dt,[],[{code,[],[<<109,98,117,102,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,99,111,109,98,105,110,101,100,32,115,105,122,101,32,111,102,32,109,101,115,115,97,103,101,32,98,117,102,102,101,114,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,99,101,115,115,46>>]},{dt,[],[{code,[],[<<98,105,110,95,118,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,117,110,105,113,117,101,32,111,102,102,45,104,101,97,112,32,98,105,110,97,114,105,101,115,32,114,101,102,101,114,101,110,99,101,100,32,102,114,111,109,32,116,104,101,32,112,114,111,99,101,115,115,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<98,105,110,95,118,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,98,105,110,97,114,105,101,115,32,97,108,108,111,119,101,100,32,105,110,32,116,104,101,32,118,105,114,116,117,97,108,32,104,101,97,112,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,98,101,102,111,114,101,32,100,111,105,110,103,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{dt,[],[{code,[],[<<98,105,110,95,111,108,100,95,118,104,101,97,112,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,117,110,105,113,117,101,32,111,102,102,45,104,101,97,112,32,98,105,110,97,114,105,101,115,32,114,101,102,101,114,101,110,99,101,100,32,102,114,111,109,32,116,104,101,32,112,114,111,99,101,115,115,32,111,108,100,32,104,101,97,112,46>>]},{dt,[],[{code,[],[<<98,105,110,95,111,108,100,95,118,104,101,97,112,95,98,108,111,99,107,95,115,105,122,101>>]}]},{dd,[],[<<84,104,101,32,116,111,116,97,108,32,115,105,122,101,32,111,102,32,98,105,110,97,114,105,101,115,32,97,108,108,111,119,101,100,32,105,110,32,116,104,101,32,118,105,114,116,117,97,108,32,111,108,100,32,104,101,97,112,32,105,110,32,116,104,101,32,112,114,111,99,101,115,115,32,98,101,102,111,114,101,32,100,111,105,110,103,32,97,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{dt,[],[{code,[],[<<119,111,114,100,115,105,122,101>>]}]},{dd,[],[<<70,111,114,32,116,104,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<32,101,118,101,110,116,32,105,116,32,105,115,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,110,101,101,100,32,116,104,97,116,32,116,114,105,103,103,101,114,101,100,32,116,104,101,32,71,67,46,32,70,111,114,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,101,110,100>>]},<<32,101,118,101,110,116,32,105,116,32,105,115,32,116,104,101,32,115,105,122,101,32,111,102,32,114,101,99,108,97,105,109,101,100,32,109,101,109,111,114,121,32,61,32,115,116,97,114,116,32>>,{code,[],[<<104,101,97,112,95,115,105,122,101>>]},<<32,45,32,101,110,100,32>>,{code,[],[<<104,101,97,112,95,115,105,122,101>>]},<<46>>]}]},{p,[],[<<65,108,108,32,115,105,122,101,115,32,97,114,101,32,105,110,32,119,111,114,100,115,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]}]},<<32,105,115,32,114,101,97,99,104,101,100,32,100,117,114,105,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,115,116,97,114,116>>]},<<44,32,98,117,116,32,116,104,101,32,115,105,122,101,115,32,114,101,102,108,101,99,116,32,116,104,101,32,115,105,122,101,115,32,116,104,97,116,32,116,114,105,103,103,101,114,101,100,32>>,{code,[],[<<109,97,120,95,104,101,97,112,95,115,105,122,101>>]},<<32,116,111,32,98,101,32,114,101,97,99,104,101,100,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,105,110,111,114,95,101,110,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,105,110,111,114,95,101,110,100,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,121,111,117,110,103,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,102,105,110,105,115,104,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<44,32,98,117,116,32,116,104,101,32,115,105,122,101,115,32,114,101,102,108,101,99,116,32,116,104,101,32,110,101,119,32,115,105,122,101,115,32,97,102,116,101,114,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,106,111,114,95,115,116,97,114,116>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,97,106,111,114,95,115,116,97,114,116,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,97,98,111,117,116,32,116,111,32,98,101,32,115,116,97,114,116,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<46>>]}]},{dt,[],[{a,[{id,<<116,114,97,99,101,95,51,95,116,114,97,99,101,95,109,101,115,115,97,103,101,115,95,103,99,95,109,97,106,111,114,95,101,110,100>>}],[]},{code,[],[<<123,116,114,97,99,101,44,32,80,105,100,44,32,103,99,95,109,97,106,111,114,95,101,110,100,44,32,73,110,102,111,125>>]}]},{dd,[],[{p,[],[<<83,101,110,116,32,119,104,101,110,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,32,105,115,32,102,105,110,105,115,104,101,100,46,32>>,{code,[],[<<73,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,115,97,109,101,32,107,105,110,100,32,111,102,32,108,105,115,116,32,97,115,32,105,110,32,109,101,115,115,97,103,101,32>>,{code,[],[<<103,99,95,109,105,110,111,114,95,115,116,97,114,116>>]},<<44,32,98,117,116,32,116,104,101,32,115,105,122,101,115,32,114,101,102,108,101,99,116,32,116,104,101,32,110,101,119,32,115,105,122,101,115,32,97,102,116,101,114,32,97,32,102,117,108,108,115,119,101,101,112,32,103,97,114,98,97,103,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]}]},{p,[],[<<73,102,32,116,104,101,32,116,114,97,99,105,110,103,32,112,114,111,99,101,115,115,47,112,111,114,116,32,100,105,101,115,32,111,114,32,116,104,101,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,114,101,116,117,114,110,115,32>>,{code,[],[<<114,101,109,111,118,101>>]},<<44,32,116,104,101,32,102,108,97,103,115,32,97,114,101,32,115,105,108,101,110,116,108,121,32,114,101,109,111,118,101,100,46>>]},{p,[],[<<69,97,99,104,32,112,114,111,99,101,115,115,32,99,97,110,32,111,110,108,121,32,98,101,32,116,114,97,99,101,100,32,98,121,32,111,110,101,32,116,114,97,99,101,114,46,32,84,104,101,114,101,102,111,114,101,44,32,97,116,116,101,109,112,116,115,32,116,111,32,116,114,97,99,101,32,97,110,32,97,108,114,101,97,100,121,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,102,97,105,108,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,97,32,110,117,109,98,101,114,32,105,110,100,105,99,97,116,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,109,97,116,99,104,101,100,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<49>>]},<<46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32>>,{code,[],[<<97,108,108>>]},<<32,111,114,32>>,{code,[],[<<101,120,105,115,116,105,110,103>>]},<<44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,114,111,99,101,115,115,101,115,32,114,117,110,110,105,110,103,46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,83,112,101,99>>]},<<32,105,115,32>>,{code,[],[<<110,101,119>>]},<<44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<48>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<99,112,117,95,116,105,109,101,115,116,97,109,112>>]},<<32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,97,108,108,32,112,108,97,116,102,111,114,109,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,49,54,53,56>>,signature => [{attribute,{2076,2},spec,{{erlang,trace,3},[{type,{2076,19},bounded_fun,[{type,{2076,19},'fun',[{type,{2076,19},product,[{var,{2076,20},'PidPortSpec'},{var,{2076,33},'How'},{var,{2076,38},'FlagList'}]},{type,{2076,51},integer,[]}]},[{type,{2077,7},constraint,[{atom,{2077,7},is_subtype},[{var,{2077,7},'PidPortSpec'},{type,{2077,22},union,[{type,{2077,22},pid,[]},{type,{2077,30},port,[]},{atom,{2078,22},all},{atom,{2078,28},processes},{atom,{2078,40},ports},{atom,{2079,22},existing},{atom,{2079,33},existing_processes},{atom,{2079,54},existing_ports},{atom,{2080,22},new},{atom,{2080,28},new_processes},{atom,{2080,44},new_ports}]}]]},{type,{2081,7},constraint,[{atom,{2081,7},is_subtype},[{var,{2081,7},'How'},{type,{2081,14},boolean,[]}]]},{type,{2082,7},constraint,[{atom,{2082,7},is_subtype},[{var,{2082,7},'FlagList'},{type,{2082,19},list,[{user_type,{2082,20},trace_flag,[]}]}]]}]]}]}}]}},{{function,trace_delivered,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2091}],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,100,101,108,105,118,101,114,121,32,111,102,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,40,103,101,110,101,114,97,116,101,100,32,98,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<44,32>>,{a,[{href,<<107,101,114,110,101,108,58,115,101,113,95,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,113,95,116,114,97,99,101,40,51,41>>]}]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,115,121,115,116,101,109,95,112,114,111,102,105,108,101,47,50>>]}]},<<41,32,105,115,32,100,105,115,108,111,99,97,116,101,100,32,111,110,32,116,104,101,32,116,105,109,101,45,108,105,110,101,32,99,111,109,112,97,114,101,100,32,116,111,32,111,116,104,101,114,32,101,118,101,110,116,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,46,32,73,102,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,104,97,115,32,112,97,115,115,101,100,32,115,111,109,101,32,115,112,101,99,105,102,105,99,32,112,111,105,110,116,32,105,110,32,105,116,115,32,101,120,101,99,117,116,105,111,110,44,32,97,110,100,32,121,111,117,32,119,97,110,116,32,116,111,32,107,110,111,119,32,119,104,101,110,32,97,116,32,108,101,97,115,116,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,101,118,101,110,116,115,32,117,112,32,116,111,32,116,104,105,115,32,112,111,105,110,116,32,104,97,118,101,32,114,101,97,99,104,101,100,32,116,104,101,32,116,114,97,99,101,114,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<46>>]},{p,[],[<<87,104,101,110,32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,100,101,108,105,118,101,114,101,100,32,116,111,32,116,104,101,32,116,114,97,99,101,114,32,117,112,32,116,111,32,116,104,101,32,112,111,105,110,116,32,116,104,97,116,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,114,101,97,99,104,101,100,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,116,104,101,32,99,97,108,108,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<44,32,116,104,101,110,32,97,32>>,{code,[],[<<123,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,44,32,84,114,97,99,101,101,44,32,82,101,102,125>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<32,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,109,101,115,115,97,103,101,32>>,{code,[],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100>>]},<<32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,105,109,112,108,121,32,116,104,97,116,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,46,32,73,110,115,116,101,97,100,32,105,116,32,105,109,112,108,105,101,115,32,116,104,97,116,32,97,108,108,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,116,104,97,116,32>>,{em,[],[<<97,114,101,32,116,111,32,98,101,32,100,101,108,105,118,101,114,101,100>>]},<<32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,46,32,73,116,32,105,115,32,110,111,116,32,97,110,32,101,114,114,111,114,32,105,102,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,105,115,32,110,111,116,44,32,97,110,100,32,104,97,115,32,110,111,116,32,98,101,101,110,32,116,114,97,99,101,100,32,98,121,32,115,111,109,101,111,110,101,44,32,98,117,116,32,105,102,32,116,104,105,115,32,105,115,32,116,104,101,32,99,97,115,101,44,32>>,{em,[],[<<110,111>>]},<<32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,104,97,118,101,32,98,101,101,110,32,100,101,108,105,118,101,114,101,100,32,119,104,101,110,32,116,104,101,32>>,{code,[],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100>>]},<<32,109,101,115,115,97,103,101,32,97,114,114,105,118,101,115,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,109,117,115,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,32,99,117,114,114,101,110,116,108,121,32,111,114,32,112,114,101,118,105,111,117,115,108,121,32,101,120,105,115,116,105,110,103,32,111,110,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,97,115,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<32,114,101,115,105,100,101,115,32,111,110,46,32,84,104,101,32,115,112,101,99,105,97,108,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,97,116,111,109,32>>,{code,[],[<<97,108,108>>]},<<32,100,101,110,111,116,101,115,32,97,108,108,32,112,114,111,99,101,115,115,101,115,32,116,104,97,116,32,99,117,114,114,101,110,116,108,121,32,97,114,101,32,116,114,97,99,101,100,32,105,110,32,116,104,101,32,110,111,100,101,46>>]},{p,[],[<<87,104,101,110,32,117,115,101,100,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,116,114,97,99,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<84,114,97,99,101,114,32,77,111,100,117,108,101>>]},<<44,32,97,110,121,32,109,101,115,115,97,103,101,32,115,101,110,116,32,105,110,32,116,104,101,32,116,114,97,99,101,32,99,97,108,108,98,97,99,107,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,104,97,118,101,32,114,101,97,99,104,101,100,32,105,116,115,32,114,101,99,105,112,105,101,110,116,32,98,101,102,111,114,101,32,116,104,101,32>>,{code,[],[<<116,114,97,99,101,95,100,101,108,105,118,101,114,101,100>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,115,101,110,116,46>>]},{p,[],[<<69,120,97,109,112,108,101,58,32,80,114,111,99,101,115,115,32>>,{code,[],[<<65>>]},<<32,105,115,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<44,32,112,111,114,116,32>>,{code,[],[<<66>>]},<<32,105,115,32,116,114,97,99,101,114,44,32,97,110,100,32,112,114,111,99,101,115,115,32>>,{code,[],[<<67>>]},<<32,105,115,32,116,104,101,32,112,111,114,116,32,111,119,110,101,114,32,111,102,32>>,{code,[],[<<66>>]},<<46,32>>,{code,[],[<<67>>]},<<32,119,97,110,116,115,32,116,111,32,99,108,111,115,101,32>>,{code,[],[<<66>>]},<<32,119,104,101,110,32>>,{code,[],[<<65>>]},<<32,101,120,105,116,115,46,32,84,111,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,116,114,97,99,101,32,105,115,32,110,111,116,32,116,114,117,110,99,97,116,101,100,44,32>>,{code,[],[<<67>>]},<<32,99,97,110,32,99,97,108,108,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,65,41>>]},<<32,119,104,101,110,32>>,{code,[],[<<65>>]},<<32,101,120,105,116,115,44,32,97,110,100,32,119,97,105,116,32,102,111,114,32,109,101,115,115,97,103,101,32>>,{code,[],[<<123,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,44,32,65,44,32,82,101,102,125>>]},<<32,98,101,102,111,114,101,32,99,108,111,115,105,110,103,32>>,{code,[],[<<66>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<84,114,97,99,101,101>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,112,114,111,99,101,115,115,32,40,100,101,97,100,32,111,114,32,97,108,105,118,101,41,32,111,110,32,116,104,101,32,115,97,109,101,32,110,111,100,101,32,97,115,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,100,101,108,105,118,101,114,101,100,40,84,114,97,99,101,101,41>>]},<<32,114,101,115,105,100,101,115,32,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,49,56>>,signature => [{attribute,{2091,2},spec,{{erlang,trace_delivered,1},[{type,{2091,29},bounded_fun,[{type,{2091,29},'fun',[{type,{2091,29},product,[{var,{2091,30},'Tracee'}]},{var,{2091,41},'Ref'}]},[{type,{2092,7},constraint,[{atom,{2092,7},is_subtype},[{var,{2092,7},'Tracee'},{type,{2092,17},union,[{type,{2092,17},pid,[]},{atom,{2092,25},all}]}]]},{type,{2093,7},constraint,[{atom,{2093,7},is_subtype},[{var,{2093,7},'Ref'},{type,{2093,14},reference,[]}]]}]]}]}}]}},{{function,trace_info,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2098}],[<<116,114,97,99,101,95,105,110,102,111,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,105,110,102,111,95,102,108,97,103>>}],[]},{li,[{name,<<116,114,97,99,101,95,105,110,102,111,95,105,116,101,109,95,114,101,115,117,108,116>>}],[]},{li,[{name,<<116,114,97,99,101,95,105,110,102,111,95,114,101,116,117,114,110>>}],[]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]}]},{p,[],[<<82,101,116,117,114,110,115,32,116,114,97,99,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,112,111,114,116,44,32,112,114,111,99,101,115,115,44,32,102,117,110,99,116,105,111,110,44,32,111,114,32,101,118,101,110,116,46>>]},{p,[],[{em,[],[<<84,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,112,111,114,116,32,111,114,32,112,114,111,99,101,115,115>>]},<<44,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32,116,111,32,98,101,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,40,112,105,100,41,44,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,44,32,111,114,32,111,110,101,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<110,101,119>>]},<<44,32>>,{code,[],[<<110,101,119,95,112,114,111,99,101,115,115,101,115>>]},<<44,32,111,114,32>>,{code,[],[<<110,101,119,95,112,111,114,116,115>>]},<<46,32,84,104,101,32,97,116,111,109,32>>,{code,[],[<<110,101,119>>]},<<32,111,114,32>>,{code,[],[<<110,101,119,95,112,114,111,99,101,115,115,101,115>>]},<<32,109,101,97,110,115,32,116,104,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,116,114,97,99,101,32,115,116,97,116,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,32,116,111,32,98,101,32,99,114,101,97,116,101,100,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,97,116,111,109,32>>,{code,[],[<<110,101,119,95,112,111,114,116,115>>]},<<32,109,101,97,110,115,32,116,104,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,116,114,97,99,101,32,115,116,97,116,101,32,102,111,114,32,112,111,114,116,115,32,116,111,32,98,101,32,99,114,101,97,116,101,100,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,102,111,114,32,112,111,114,116,115,32,97,110,100,32,112,114,111,99,101,115,115,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,108,97,103,115>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,97,116,111,109,115,32,105,110,100,105,99,97,116,105,110,103,32,119,104,97,116,32,107,105,110,100,32,111,102,32,116,114,97,99,101,115,32,105,115,32,101,110,97,98,108,101,100,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,46,32,84,104,101,32,108,105,115,116,32,105,115,32,101,109,112,116,121,32,105,102,32,110,111,32,116,114,97,99,101,115,32,97,114,101,32,101,110,97,98,108,101,100,44,32,97,110,100,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,97,116,111,109,115,32,105,102,32,116,114,97,99,101,115,32,97,114,101,32,101,110,97,98,108,101,100,58,32>>,{code,[],[<<115,101,110,100>>]},<<44,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<44,32>>,{code,[],[<<115,101,116,95,111,110,95,115,112,97,119,110>>]},<<44,32>>,{code,[],[<<99,97,108,108>>]},<<44,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<44,32>>,{code,[],[<<112,114,111,99,115>>]},<<44,32>>,{code,[],[<<112,111,114,116,115>>]},<<44,32>>,{code,[],[<<115,101,116,95,111,110,95,102,105,114,115,116,95,115,112,97,119,110>>]},<<44,32>>,{code,[],[<<115,101,116,95,111,110,95,108,105,110,107>>]},<<44,32>>,{code,[],[<<114,117,110,110,105,110,103>>]},<<44,32>>,{code,[],[<<114,117,110,110,105,110,103,95,112,114,111,99,115>>]},<<44,32>>,{code,[],[<<114,117,110,110,105,110,103,95,112,111,114,116,115>>]},<<44,32>>,{code,[],[<<115,105,108,101,110,116>>]},<<44,32>>,{code,[],[<<101,120,105,116,105,110,103>>]},<<44,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32>>,{code,[],[<<115,116,114,105,99,116,95,109,111,110,111,116,111,110,105,99,95,116,105,109,101,115,116,97,109,112>>]},<<44,32>>,{code,[],[<<103,97,114,98,97,103,101,95,99,111,108,108,101,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<116,105,109,101,115,116,97,109,112>>]},<<44,32,97,110,100,32>>,{code,[],[<<97,114,105,116,121>>]},<<46,32,84,104,101,32,111,114,100,101,114,32,105,115,32,97,114,98,105,116,114,97,114,121,46>>]}]},{dt,[],[{code,[],[<<116,114,97,99,101,114>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,105,100,101,110,116,105,102,105,101,114,32,102,111,114,32,112,114,111,99,101,115,115,44,32,112,111,114,116,44,32,111,114,32,97,32,116,117,112,108,101,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,116,114,97,99,101,114,32,109,111,100,117,108,101,32,97,110,100,32,116,114,97,99,101,114,32,115,116,97,116,101,32,116,114,97,99,105,110,103,32,116,104,105,115,32,112,114,111,99,101,115,115,46,32,73,102,32,116,104,105,115,32,112,114,111,99,101,115,115,32,105,115,32,110,111,116,32,116,114,97,99,101,100,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]}]},{p,[],[{em,[],[<<84,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,102,117,110,99,116,105,111,110>>]},<<44,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32,116,111,32,98,101,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<46,32,78,111,32,119,105,108,100,99,97,114,100,115,32,97,114,101,32,97,108,108,111,119,101,100,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,111,114,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,116,114,97,99,101,100,46,32,73,102,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<44,32,116,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,114,101,116,117,114,110,101,100,32,114,101,102,101,114,115,32,116,111,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,102,111,114,32,99,111,100,101,32,116,104,97,116,32,119,105,108,108,32,98,101,32,108,111,97,100,101,100,46>>]},{p,[],[<<86,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<115,32,102,111,114,32,102,117,110,99,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<116,114,97,99,101,100>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,114,97,99,101,100,32,111,110,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,44,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,105,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,114,97,99,101,100,32,111,110,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,40,116,104,97,116,32,105,115,44,32,108,111,99,97,108,32,97,110,100,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,41,44,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,108,111,99,97,108,32,111,114,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,97,114,101,32,110,111,116,32,116,114,97,99,101,100,46>>]}]},{dt,[],[{code,[],[<<109,97,116,99,104,95,115,112,101,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,108,111,99,97,108,108,121,32,111,114,32,103,108,111,98,97,108,108,121,32,116,114,97,99,101,100,32,98,117,116,32,104,97,115,32,110,111,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,100,101,102,105,110,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,101,116,97>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,101,116,97,45,116,114,97,99,101,32,116,114,97,99,101,114,32,112,114,111,99,101,115,115,44,32,112,111,114,116,44,32,111,114,32,116,114,97,99,101,32,109,111,100,117,108,101,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,110,111,116,32,109,101,116,97,45,116,114,97,99,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,109,101,116,97,45,116,114,97,99,101,100,32,98,117,116,32,104,97,115,32,111,110,99,101,32,100,101,116,101,99,116,101,100,32,116,104,97,116,32,116,104,101,32,116,114,97,99,101,114,32,112,114,111,99,101,115,115,32,105,115,32,105,110,118,97,108,105,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,101,116,97,95,109,97,116,99,104,95,115,112,101,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,101,116,97,45,116,114,97,99,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,46,32,73,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,109,101,116,97,45,116,114,97,99,101,100,32,98,117,116,32,104,97,115,32,110,111,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,100,101,102,105,110,101,100,44,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<91,93>>]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,97,108,108,32,99,111,117,110,116,32,118,97,108,117,101,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,111,114,32>>,{code,[],[<<116,114,117,101>>]},<<32,102,111,114,32,116,104,101,32,112,115,101,117,100,111,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,105,102,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,105,115,32,97,99,116,105,118,101,46,32,79,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,97,108,108,32,116,105,109,101,32,118,97,108,117,101,115,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,111,114,32>>,{code,[],[<<116,114,117,101>>]},<<32,102,111,114,32,116,104,101,32,112,115,101,117,100,111,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,105,102,32,99,97,108,108,32,116,105,109,101,32,116,114,97,99,105,110,103,32,105,115,32,97,99,116,105,118,101,46,32,79,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,99,97,108,108,32,116,105,109,101,32,118,97,108,117,101,115,32,114,101,116,117,114,110,101,100,44,32>>,{code,[],[<<91,123,80,105,100,44,32,67,111,117,110,116,44,32,83,44,32,85,115,125,93>>]},<<44,32,105,115,32,97,32,108,105,115,116,32,111,102,32,101,97,99,104,32,112,114,111,99,101,115,115,32,116,104,97,116,32,101,120,101,99,117,116,101,100,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,110,100,32,105,116,115,32,115,112,101,99,105,102,105,99,32,99,111,117,110,116,101,114,115,46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32>>,{code,[],[<<123,73,116,101,109,44,32,86,97,108,117,101,125>>]},<<32,116,117,112,108,101,115,32,102,111,114,32,97,108,108,32,111,116,104,101,114,32,105,116,101,109,115,44,32,111,114,32,114,101,116,117,114,110,115,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32,110,111,32,116,114,97,99,105,110,103,32,105,115,32,97,99,116,105,118,101,32,102,111,114,32,116,104,105,115,32,102,117,110,99,116,105,111,110,46>>]}]}]},{p,[],[{em,[],[<<84,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,110,32,101,118,101,110,116>>]},<<44,32>>,{code,[],[<<80,105,100,80,111,114,116,70,117,110,99,69,118,101,110,116>>]},<<32,105,115,32,116,111,32,98,101,32,111,110,101,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<115,101,110,100>>]},<<32,111,114,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<46>>]},{p,[],[<<79,110,101,32,118,97,108,105,100,32>>,{code,[],[<<73,116,101,109>>]},<<32,102,111,114,32,101,118,101,110,116,115,32,101,120,105,115,116,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<109,97,116,99,104,95,115,112,101,99>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32,116,104,105,115,32,101,118,101,110,116,44,32,105,102,32,105,116,32,104,97,115,32,111,110,101,44,32,111,114,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,110,111,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,104,97,115,32,98,101,101,110,32,115,101,116,46>>]}]}]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<123,73,116,101,109,44,32,86,97,108,117,101,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,105,115,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,105,110,102,111,114,109,97,116,105,111,110,32,97,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,46,32,73,102,32,97,32,112,105,100,32,102,111,114,32,97,32,100,101,97,100,32,112,114,111,99,101,115,115,32,119,97,115,32,115,112,101,99,105,102,105,101,100,44,32,111,114,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,110,111,110,45,101,120,105,115,116,105,110,103,32,102,117,110,99,116,105,111,110,44,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,105,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,51,55,51>>,signature => [{attribute,{2098,2},spec,{{erlang,trace_info,2},[{type,{2098,24},bounded_fun,[{type,{2098,24},'fun',[{type,{2098,24},product,[{var,{2098,25},'PidPortFuncEvent'},{var,{2098,43},'Item'}]},{var,{2098,52},'Res'}]},[{type,{2099,7},constraint,[{atom,{2099,7},is_subtype},[{var,{2099,7},'PidPortFuncEvent'},{type,{2099,27},union,[{type,{2099,27},pid,[]},{type,{2099,35},port,[]},{atom,{2099,44},new},{atom,{2099,50},new_processes},{atom,{2099,66},new_ports},{type,{2100,24},tuple,[{var,{2100,25},'Module'},{var,{2100,33},'Function'},{var,{2100,43},'Arity'}]},{atom,{2100,52},on_load},{atom,{2100,62},send},{atom,{2100,69},'receive'}]}]]},{type,{2101,7},constraint,[{atom,{2101,7},is_subtype},[{var,{2101,7},'Module'},{type,{2101,17},module,[]}]]},{type,{2102,7},constraint,[{atom,{2102,7},is_subtype},[{var,{2102,7},'Function'},{type,{2102,19},atom,[]}]]},{type,{2103,7},constraint,[{atom,{2103,7},is_subtype},[{var,{2103,7},'Arity'},{type,{2103,16},arity,[]}]]},{type,{2104,7},constraint,[{atom,{2104,7},is_subtype},[{var,{2104,7},'Item'},{type,{2104,15},union,[{atom,{2104,15},flags},{atom,{2104,23},tracer},{atom,{2104,32},traced},{atom,{2104,41},match_spec},{atom,{2105,15},meta},{atom,{2105,22},meta_match_spec},{atom,{2105,40},call_count},{atom,{2105,53},call_time},{atom,{2105,65},all}]}]]},{type,{2106,7},constraint,[{atom,{2106,7},is_subtype},[{var,{2106,7},'Res'},{user_type,{2106,14},trace_info_return,[]}]]}]]}]}}]}},{{function,trace_pattern,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2773}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,50>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]},{li,[{name,<<116,114,97,99,101,95,112,97,116,116,101,114,110,95,109,102,97>>}],[]}]},{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,69,118,101,110,116,44,32,77,97,116,99,104,83,112,101,99,44,32,91,93,41>>]}]},<<44,32,114,101,116,97,105,110,101,100,32,102,111,114,32,98,97,99,107,119,97,114,100,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,53,48,57>>,signature => [{attribute,{2773,2},spec,{{erlang,trace_pattern,2},[{type,{2773,27},bounded_fun,[{type,{2773,27},'fun',[{type,{2773,27},product,[{var,{2773,28},'MFA'},{var,{2773,33},'MatchSpec'}]},{type,{2773,47},non_neg_integer,[]}]},[{type,{2774,7},constraint,[{atom,{2774,7},is_subtype},[{var,{2774,7},'MFA'},{type,{2774,14},union,[{user_type,{2774,14},trace_pattern_mfa,[]},{atom,{2774,36},send},{atom,{2774,43},'receive'}]}]]},{type,{2775,7},constraint,[{atom,{2775,7},is_subtype},[{var,{2775,7},'MatchSpec'},{type,{2775,21},union,[{ann_type,{2775,21},[{var,{2775,21},'MatchSpecList'},{user_type,{2775,38},trace_match_spec,[]}]},{type,{2776,20},boolean,[]},{atom,{2777,20},restart},{atom,{2778,20},pause}]}]]}]]}]}}]}},{{function,trace_pattern,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2793}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]}]},{p,[],[<<83,101,116,115,32,116,114,97,99,101,32,112,97,116,116,101,114,110,32,102,111,114,32>>,{em,[],[<<109,101,115,115,97,103,101,32,115,101,110,100,105,110,103>>]},<<46,32,77,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<32,116,111,32,115,101,116,32,116,104,101,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,46,32,66,121,32,100,101,102,97,117,108,116,32,97,108,108,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,102,114,111,109,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,116,114,97,99,101,100,46,32,84,111,32,108,105,109,105,116,32,116,114,97,99,101,100,32,115,101,110,100,32,101,118,101,110,116,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32,109,101,115,115,97,103,101,32,99,111,110,116,101,110,116,44,32,116,104,101,32,115,101,110,100,101,114,32,97,110,100,47,111,114,32,116,104,101,32,114,101,99,101,105,118,101,114,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99>>]},<<32,99,97,110,32,116,97,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<77,97,116,99,104,83,112,101,99,76,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,105,115,32,100,111,110,101,32,111,110,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<91,82,101,99,101,105,118,101,114,44,32,77,115,103,93>>]},<<46,32>>,{code,[],[<<82,101,99,101,105,118,101,114>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,116,121,32,111,102,32,116,104,101,32,114,101,99,101,105,118,101,114,32,97,110,100,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,116,104,101,32,109,101,115,115,97,103,101,32,116,101,114,109,46,32,84,104,101,32,112,105,100,32,111,102,32,116,104,101,32,115,101,110,100,105,110,103,32,112,114,111,99,101,115,115,32,99,97,110,32,98,101,32,97,99,99,101,115,115,101,100,32,119,105,116,104,32,116,104,101,32,103,117,97,114,100,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<115,101,108,102,47,48>>]},<<46,32,65,110,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<69,110,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,115,101,110,116,32,109,101,115,115,97,103,101,115,32,40,102,114,111,109,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,41,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46,32>>,{em,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,115,101,110,116,32,109,101,115,115,97,103,101,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]}]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,109,117,115,116,32,98,101,32>>,{code,[],[<<91,93>>]},<<32,102,111,114,32,115,101,110,100,32,116,114,97,99,105,110,103,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,108,119,97,121,115,32>>,{code,[],[<<49>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,116,111,32,97,32,115,112,101,99,105,102,105,99,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,80,105,100,44,32,39,95,39,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,109,97,116,99,104,105,110,103,32>>,{code,[],[<<123,114,101,112,108,121,44,32,95,125>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,39,95,39,44,32,123,114,101,112,108,121,44,39,95,39,125,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,116,111,32,116,104,101,32,115,101,110,100,101,114,32,105,116,115,101,108,102,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,39,36,49,39,44,32,39,95,39,93,44,91,123,39,61,58,61,39,44,39,36,49,39,44,123,115,101,108,102,125,125,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,115,101,110,116,32,116,111,32,111,116,104,101,114,32,110,111,100,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,115,101,110,100,44,32,91,123,91,39,36,49,39,44,32,39,95,39,93,44,91,123,39,61,47,61,39,44,123,110,111,100,101,44,39,36,49,39,125,44,123,110,111,100,101,125,125,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32>>,{code,[],[<<115,101,110,100>>]},<<32,116,114,97,99,101,32,99,97,110,32,117,115,101,32,97,108,108,32,103,117,97,114,100,32,97,110,100,32,98,111,100,121,32,102,117,110,99,116,105,111,110,115,32,101,120,99,101,112,116,32>>,{code,[],[<<99,97,108,108,101,114>>]},<<46>>]}]},{p,[],[<<70,97,105,108,115,32,98,121,32,114,97,105,115,105,110,103,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,97,110,32,97,114,103,117,109,101,110,116,32,105,115,32,105,110,118,97,108,105,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,32,104,97,115,32,101,120,99,101,115,115,105,118,101,32,110,101,115,116,105,110,103,32,119,104,105,99,104,32,99,97,117,115,101,115,32,115,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,101,120,104,97,117,115,116,105,111,110,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,115,99,104,101,100,95,116,104,114,101,97,100,95,115,116,97,99,107,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<83,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,53,50,55>>,signature => [{attribute,{2793,2},spec,{{erlang,trace_pattern,3},[{type,{2793,27},bounded_fun,[{type,{2793,27},'fun',[{type,{2793,27},product,[{atom,{2793,28},send},{var,{2793,34},'MatchSpec'},{type,{2793,45},nil,[]}]},{type,{2793,52},non_neg_integer,[]}]},[{type,{2794,7},constraint,[{atom,{2794,7},is_subtype},[{var,{2794,7},'MatchSpec'},{type,{2794,21},union,[{ann_type,{2794,21},[{var,{2794,21},'MatchSpecList'},{user_type,{2794,38},trace_match_spec,[]}]},{type,{2795,20},boolean,[]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,trace_pattern,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2793}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]}]},{p,[],[<<83,101,116,115,32,116,114,97,99,101,32,112,97,116,116,101,114,110,32,102,111,114,32>>,{em,[],[<<109,101,115,115,97,103,101,32,114,101,99,101,105,118,105,110,103>>]},<<46,32,77,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<32,116,111,32,115,101,116,32,116,104,101,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,46,32,66,121,32,100,101,102,97,117,108,116,32,97,108,108,32,109,101,115,115,97,103,101,115,32,114,101,99,101,105,118,101,100,32,98,121,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,32,97,114,101,32,116,114,97,99,101,100,46,32,84,111,32,108,105,109,105,116,32,116,114,97,99,101,100,32,114,101,99,101,105,118,101,32,101,118,101,110,116,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32,109,101,115,115,97,103,101,32,99,111,110,116,101,110,116,44,32,116,104,101,32,115,101,110,100,101,114,32,97,110,100,47,111,114,32,116,104,101,32,114,101,99,101,105,118,101,114,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99>>]},<<32,99,97,110,32,116,97,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<77,97,116,99,104,83,112,101,99,76,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,105,115,32,100,111,110,101,32,111,110,32,116,104,101,32,108,105,115,116,32>>,{code,[],[<<91,78,111,100,101,44,32,83,101,110,100,101,114,44,32,77,115,103,93>>]},<<46,32>>,{code,[],[<<78,111,100,101>>]},<<32,105,115,32,116,104,101,32,110,111,100,101,32,110,97,109,101,32,111,102,32,116,104,101,32,115,101,110,100,101,114,46,32>>,{code,[],[<<83,101,110,100,101,114>>]},<<32,105,115,32,116,104,101,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,116,121,32,111,102,32,116,104,101,32,115,101,110,100,101,114,44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,115,101,110,100,101,114,32,105,115,32,110,111,116,32,107,110,111,119,110,32,40,119,104,105,99,104,32,99,97,110,32,98,101,32,116,104,101,32,99,97,115,101,32,102,111,114,32,114,101,109,111,116,101,32,115,101,110,100,101,114,115,41,46,32>>,{code,[],[<<77,115,103>>]},<<32,105,115,32,116,104,101,32,109,101,115,115,97,103,101,32,116,101,114,109,46,32,84,104,101,32,112,105,100,32,111,102,32,116,104,101,32,114,101,99,101,105,118,105,110,103,32,112,114,111,99,101,115,115,32,99,97,110,32,98,101,32,97,99,99,101,115,115,101,100,32,119,105,116,104,32,116,104,101,32,103,117,97,114,100,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<115,101,108,102,47,48>>]},<<46,32,65,110,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<69,110,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,114,101,99,101,105,118,101,100,32,109,101,115,115,97,103,101,115,32,40,116,111,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,41,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46,32>>,{em,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,114,101,99,101,105,118,101,100,32,109,101,115,115,97,103,101,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]}]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,109,117,115,116,32,98,101,32>>,{code,[],[<<91,93>>]},<<32,102,111,114,32,114,101,99,101,105,118,101,32,116,114,97,99,105,110,103,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,108,119,97,121,115,32>>,{code,[],[<<49>>]},<<46>>]},{p,[],[<<69,120,97,109,112,108,101,115,58>>]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,97,32,115,112,101,99,105,102,105,99,32,112,114,111,99,101,115,115,32>>,{code,[],[<<80,105,100>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,39,114,101,99,101,105,118,101,39,44,32,91,123,91,39,95,39,44,80,105,100,44,32,39,95,39,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,109,97,116,99,104,105,110,103,32>>,{code,[],[<<123,114,101,112,108,121,44,32,95,125>>]},<<58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,39,114,101,99,101,105,118,101,39,44,32,91,123,91,39,95,39,44,39,95,39,44,32,123,114,101,112,108,121,44,39,95,39,125,93,44,91,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{p,[],[<<79,110,108,121,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,32,102,114,111,109,32,111,116,104,101,114,32,110,111,100,101,115,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,40,39,114,101,99,101,105,118,101,39,44,32,91,123,91,39,36,49,39,44,32,39,95,39,44,32,39,95,39,93,44,91,123,39,61,47,61,39,44,39,36,49,39,44,123,110,111,100,101,125,125,93,44,91,93,125,93,44,32,91,93,41,46,10,49>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114,32>>,{code,[],[<<39,114,101,99,101,105,118,101,39>>]},<<32,116,114,97,99,101,32,99,97,110,32,117,115,101,32,97,108,108,32,103,117,97,114,100,32,97,110,100,32,98,111,100,121,32,102,117,110,99,116,105,111,110,115,32,101,120,99,101,112,116,32>>,{code,[],[<<99,97,108,108,101,114>>]},<<44,32>>,{code,[],[<<105,115,95,115,101,113,95,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<103,101,116,95,115,101,113,95,116,111,107,101,110>>]},<<44,32>>,{code,[],[<<115,101,116,95,115,101,113,95,116,111,107,101,110>>]},<<44,32>>,{code,[],[<<101,110,97,98,108,101,95,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<100,105,115,97,98,108,101,95,116,114,97,99,101>>]},<<44,32>>,{code,[],[<<116,114,97,99,101>>]},<<44,32>>,{code,[],[<<115,105,108,101,110,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<112,114,111,99,101,115,115,95,100,117,109,112>>]},<<46>>]}]},{p,[],[<<70,97,105,108,115,32,98,121,32,114,97,105,115,105,110,103,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,97,110,32,97,114,103,117,109,101,110,116,32,105,115,32,105,110,118,97,108,105,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,32,104,97,115,32,101,120,99,101,115,115,105,118,101,32,110,101,115,116,105,110,103,32,119,104,105,99,104,32,99,97,117,115,101,115,32,115,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,101,120,104,97,117,115,116,105,111,110,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,115,99,104,101,100,95,116,104,114,101,97,100,95,115,116,97,99,107,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<83,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,54,49,52>>,signature => [{attribute,{2793,2},spec,{{erlang,trace_pattern,3},[{type,{2796,6},bounded_fun,[{type,{2796,6},'fun',[{type,{2796,6},product,[{atom,{2796,7},'receive'},{var,{2796,18},'MatchSpec'},{type,{2796,29},nil,[]}]},{type,{2796,36},non_neg_integer,[]}]},[{type,{2797,7},constraint,[{atom,{2797,7},is_subtype},[{var,{2797,7},'MatchSpec'},{type,{2797,21},union,[{ann_type,{2797,21},[{var,{2797,21},'MatchSpecList'},{user_type,{2797,38},trace_match_spec,[]}]},{type,{2798,20},boolean,[]}]}]]}]]}]}}],since => <<79,84,80,32,49,57,46,48>>}},{{function,trace_pattern,3},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2793}],[<<116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>}],[]},{li,[{name,<<109,97,116,99,104,95,118,97,114,105,97,98,108,101>>},{class,<<100,101,115,99,114,105,112,116,105,111,110>>}],[<<65,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,39,36,49,39,32,124,32,39,36,50,39,32,124,32,39,36,51,39,32,124,32,46,46,46>>]},{li,[{name,<<116,114,97,99,101,95,109,97,116,99,104,95,115,112,101,99>>}],[]},{li,[{name,<<116,114,97,99,101,95,112,97,116,116,101,114,110,95,102,108,97,103>>}],[]},{li,[{name,<<116,114,97,99,101,95,112,97,116,116,101,114,110,95,109,102,97>>}],[]}]},{p,[],[<<69,110,97,98,108,101,115,32,111,114,32,100,105,115,97,98,108,101,115,32>>,{em,[],[<<99,97,108,108,32,116,114,97,99,105,110,103>>]},<<32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,102,117,110,99,116,105,111,110,115,46,32,77,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<32,116,111,32,115,101,116,32,116,104,101,32>>,{code,[],[<<99,97,108,108>>]},<<32,116,114,97,99,101,32,102,108,97,103,32,102,111,114,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<67,111,110,99,101,112,116,117,97,108,108,121,44,32,99,97,108,108,32,116,114,97,99,105,110,103,32,119,111,114,107,115,32,97,115,32,102,111,108,108,111,119,115,46,32,73,110,115,105,100,101,32,116,104,101,32,69,114,108,97,110,103,32,118,105,114,116,117,97,108,32,109,97,99,104,105,110,101,44,32,97,32,115,101,116,32,111,102,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,97,32,115,101,116,32,111,102,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,116,111,32,98,101,32,116,114,97,99,101,100,46,32,73,102,32,97,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,32,99,97,108,108,115,32,97,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,44,32,116,104,101,32,116,114,97,99,101,32,97,99,116,105,111,110,32,105,115,32,116,97,107,101,110,46,32,79,116,104,101,114,119,105,115,101,44,32,110,111,116,104,105,110,103,32,104,97,112,112,101,110,115,46>>]},{p,[],[<<84,111,32,97,100,100,32,111,114,32,114,101,109,111,118,101,32,111,110,101,32,111,114,32,109,111,114,101,32,112,114,111,99,101,115,115,101,115,32,116,111,32,116,104,101,32,115,101,116,32,111,102,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,101,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]}]},<<46>>]},{p,[],[<<84,111,32,97,100,100,32,111,114,32,114,101,109,111,118,101,32,102,117,110,99,116,105,111,110,115,32,116,111,32,116,104,101,32,115,101,116,32,111,102,32,116,114,97,99,101,100,32,102,117,110,99,116,105,111,110,115,44,32,117,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<46>>]},{p,[],[<<84,104,101,32,66,73,70,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,112,97,116,116,101,114,110,47,51>>]},<<32,99,97,110,32,97,108,115,111,32,97,100,100,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,32,116,111,32,97,32,102,117,110,99,116,105,111,110,46,32,65,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,99,111,109,112,114,105,115,101,115,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,114,103,117,109,101,110,116,115,32,109,117,115,116,32,109,97,116,99,104,44,32,97,32,103,117,97,114,100,32,101,120,112,114,101,115,115,105,111,110,32,116,104,97,116,32,109,117,115,116,32,101,118,97,108,117,97,116,101,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<44,32,97,110,100,32,97,110,32,97,99,116,105,111,110,32,116,111,32,98,101,32,112,101,114,102,111,114,109,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,97,99,116,105,111,110,32,105,115,32,116,111,32,115,101,110,100,32,97,32,116,114,97,99,101,32,109,101,115,115,97,103,101,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,111,114,32,116,104,101,32,103,117,97,114,100,32,102,97,105,108,115,44,32,116,104,101,32,97,99,116,105,111,110,32,105,115,32,110,111,116,32,101,120,101,99,117,116,101,100,46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,70,65>>]},<<32,105,115,32,116,111,32,98,101,32,97,32,116,117,112,108,101,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,32,70,117,110,99,116,105,111,110,44,32,65,114,105,116,121,125>>]},<<44,32,111,114,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<32,40,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,41,46,32,73,116,32,99,97,110,32,98,101,32,116,104,101,32,109,111,100,117,108,101,44,32,102,117,110,99,116,105,111,110,44,32,97,110,100,32,97,114,105,116,121,32,102,111,114,32,97,32,102,117,110,99,116,105,111,110,32,40,111,114,32,97,32,66,73,70,32,105,110,32,97,110,121,32,109,111,100,117,108,101,41,46,32,84,104,101,32,97,116,111,109,32>>,{code,[],[<<39,95,39>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,97,115,32,97,32,119,105,108,100,99,97,114,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,119,97,121,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,77,111,100,117,108,101,44,70,117,110,99,116,105,111,110,44,39,95,39,125>>]}]},{dd,[],[{p,[],[<<65,108,108,32,102,117,110,99,116,105,111,110,115,32,111,102,32,97,110,121,32,97,114,105,116,121,32,110,97,109,101,100,32>>,{code,[],[<<70,117,110,99,116,105,111,110>>]},<<32,105,110,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,77,111,100,117,108,101,44,39,95,39,44,39,95,39,125>>]}]},{dd,[],[{p,[],[<<65,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,109,111,100,117,108,101,32>>,{code,[],[<<77,111,100,117,108,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,39,95,39,44,39,95,39,44,39,95,39,125>>]}]},{dd,[],[{p,[],[<<65,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,97,108,108,32,108,111,97,100,101,100,32,109,111,100,117,108,101,115,46>>]}]}]},{p,[],[<<79,116,104,101,114,32,99,111,109,98,105,110,97,116,105,111,110,115,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<123,77,111,100,117,108,101,44,39,95,39,44,65,114,105,116,121,125>>]},<<44,32,97,114,101,32,110,111,116,32,97,108,108,111,119,101,100,46,32,76,111,99,97,108,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,32,119,105,108,100,99,97,114,100,115,32,111,110,108,121,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,105,115,32,105,110,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<46>>]},{p,[],[<<73,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<77,70,65>>]},<<32,105,115,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<111,110,95,108,111,97,100>>]},<<44,32,116,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,110,100,32,102,108,97,103,32,108,105,115,116,32,97,114,101,32,117,115,101,100,32,111,110,32,97,108,108,32,109,111,100,117,108,101,115,32,116,104,97,116,32,97,114,101,32,110,101,119,108,121,32,108,111,97,100,101,100,46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99>>]},<<32,99,97,110,32,116,97,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<102,97,108,115,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,116,104,101,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]},{dt,[],[{code,[],[<<116,114,117,101>>]}]},{dd,[],[{p,[],[<<69,110,97,98,108,101,115,32,116,114,97,99,105,110,103,32,102,111,114,32,116,104,101,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,46,32,65,110,121,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,105,115,32,114,101,109,111,118,101,100,46>>]}]},{dt,[],[{code,[],[<<77,97,116,99,104,83,112,101,99,76,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,108,105,115,116,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,46,32,65,110,32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,70,111,114,32,97,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,115,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<101,114,116,115,58,109,97,116,99,104,95,115,112,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<77,97,116,99,104,32,83,112,101,99,105,102,105,99,97,116,105,111,110,115,32,105,110,32,69,114,108,97,110,103>>]},<<32,105,110,32,116,104,101,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]}]},{dt,[],[{code,[],[<<114,101,115,116,97,114,116>>]}]},{dd,[],[{p,[],[<<70,111,114,32,116,104,101,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<99,97,108,108,95,116,105,109,101>>]},<<58,32,114,101,115,116,97,114,116,115,32,116,104,101,32,101,120,105,115,116,105,110,103,32,99,111,117,110,116,101,114,115,46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32,111,116,104,101,114,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,46>>]}]},{dt,[],[{code,[],[<<112,97,117,115,101>>]}]},{dd,[],[{p,[],[<<70,111,114,32,116,104,101,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<99,97,108,108,95,116,105,109,101>>]},<<58,32,112,97,117,115,101,115,32,116,104,101,32,101,120,105,115,116,105,110,103,32,99,111,117,110,116,101,114,115,46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32,111,116,104,101,114,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,111,112,116,105,111,110,115,46>>]}]}]},{p,[],[<<80,97,114,97,109,101,116,101,114,32>>,{code,[],[<<70,108,97,103,76,105,115,116>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,111,112,116,105,111,110,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,118,97,108,105,100,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<103,108,111,98,97,108>>]}]},{dd,[],[{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,99,97,108,108,32,116,114,97,99,105,110,103,32,102,111,114,32,103,108,111,98,97,108,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,32,40,116,104,97,116,32,105,115,44,32,99,97,108,108,115,32,115,112,101,99,105,102,121,105,110,103,32,116,104,101,32,109,111,100,117,108,101,32,101,120,112,108,105,99,105,116,108,121,41,46,32,79,110,108,121,32,101,120,112,111,114,116,101,100,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,32,97,110,100,32,111,110,108,121,32,103,108,111,98,97,108,32,99,97,108,108,115,32,103,101,110,101,114,97,116,101,32,116,114,97,99,101,32,109,101,115,115,97,103,101,115,46,32>>,{em,[],[<<84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116>>]},<<46>>]}]},{dt,[],[{code,[],[<<108,111,99,97,108>>]}]},{dd,[],[{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,99,97,108,108,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,84,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,115,101,110,116,32,119,104,101,110,101,118,101,114,32,97,110,121,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,99,97,108,108,101,100,44,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,104,111,119,32,116,104,101,121,32,97,114,101,32,99,97,108,108,101,100,46,32,73,102,32,102,108,97,103,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,105,115,32,115,101,116,32,102,111,114,32,116,104,101,32,112,114,111,99,101,115,115,44,32,97,32>>,{code,[],[<<114,101,116,117,114,110,95,116,111>>]},<<32,109,101,115,115,97,103,101,32,105,115,32,97,108,115,111,32,115,101,110,116,32,119,104,101,110,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,111,32,105,116,115,32,99,97,108,108,101,114,46>>]}]},{dt,[],[{code,[],[<<109,101,116,97,32,124,32,123,109,101,116,97,44,32,80,105,100,125,32,124,32,123,109,101,116,97,44,32,84,114,97,99,101,114,77,111,100,117,108,101,44,32,84,114,97,99,101,114,83,116,97,116,101,125>>]}]},{dd,[],[{p,[],[<<84,117,114,110,115,32,111,110,32,111,114,32,111,102,102,32,109,101,116,97,45,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,84,114,97,99,101,32,109,101,115,115,97,103,101,115,32,97,114,101,32,115,101,110,116,32,116,111,32,116,104,101,32,116,114,97,99,101,114,32,119,104,101,110,101,118,101,114,32,97,110,121,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,99,97,108,108,101,100,46,32,73,102,32,110,111,32,116,114,97,99,101,114,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<115,101,108,102,40,41>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,97,32,100,101,102,97,117,108,116,32,116,114,97,99,101,114,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<77,101,116,97,45,116,114,97,99,105,110,103,32,116,114,97,99,101,115,32,97,108,108,32,112,114,111,99,101,115,115,101,115,32,97,110,100,32,100,111,101,115,32,110,111,116,32,99,97,114,101,32,97,98,111,117,116,32,116,104,101,32,112,114,111,99,101,115,115,32,116,114,97,99,101,32,102,108,97,103,115,32,115,101,116,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,47,51>>]},<<44,32,116,104,101,32,116,114,97,99,101,32,102,108,97,103,115,32,97,114,101,32,105,110,115,116,101,97,100,32,102,105,120,101,100,32,116,111,32>>,{code,[],[<<91,99,97,108,108,44,32,116,105,109,101,115,116,97,109,112,93>>]},<<46>>]},{p,[],[<<84,104,101,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<123,114,101,116,117,114,110,95,116,114,97,99,101,125>>]},<<32,119,111,114,107,115,32,119,105,116,104,32,109,101,116,97,45,116,114,97,99,101,32,97,110,100,32,115,101,110,100,115,32,105,116,115,32,116,114,97,99,101,32,109,101,115,115,97,103,101,32,116,111,32,116,104,101,32,115,97,109,101,32,116,114,97,99,101,114,46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,116,114,117,101>>]},<<41,32,111,114,32,115,116,111,112,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,102,97,108,115,101>>]},<<41,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,70,111,114,32,101,118,101,114,121,32,102,117,110,99,116,105,111,110,44,32,97,32,99,111,117,110,116,101,114,32,105,115,32,105,110,99,114,101,109,101,110,116,101,100,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,44,32,105,110,32,97,110,121,32,112,114,111,99,101,115,115,46,32,78,111,32,112,114,111,99,101,115,115,32,116,114,97,99,101,32,102,108,97,103,115,32,110,101,101,100,32,116,111,32,98,101,32,97,99,116,105,118,97,116,101,100,46>>]},{p,[],[<<73,102,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,105,115,32,115,116,97,114,116,101,100,32,119,104,105,108,101,32,97,108,114,101,97,100,121,32,114,117,110,110,105,110,103,44,32,116,104,101,32,99,111,117,110,116,32,105,115,32,114,101,115,116,97,114,116,101,100,32,102,114,111,109,32,122,101,114,111,46,32,84,111,32,112,97,117,115,101,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,44,32,117,115,101,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,112,97,117,115,101>>]},<<46,32,80,97,117,115,101,100,32,97,110,100,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,32,99,97,110,32,98,101,32,114,101,115,116,97,114,116,101,100,32,102,114,111,109,32,122,101,114,111,32,119,105,116,104,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,114,101,115,116,97,114,116>>]},<<46>>]},{p,[],[<<84,111,32,114,101,97,100,32,116,104,101,32,99,111,117,110,116,101,114,32,118,97,108,117,101,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<99,97,108,108,95,116,105,109,101>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,116,114,117,101>>]},<<41,32,111,114,32,115,116,111,112,115,32,40>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,102,97,108,115,101>>]},<<41,32,99,97,108,108,32,116,105,109,101,32,116,114,97,99,105,110,103,32,102,111,114,32,97,108,108,32,116,121,112,101,115,32,111,102,32,102,117,110,99,116,105,111,110,32,99,97,108,108,115,46,32,70,111,114,32,101,118,101,114,121,32,102,117,110,99,116,105,111,110,44,32,97,32,99,111,117,110,116,101,114,32,105,115,32,105,110,99,114,101,109,101,110,116,101,100,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,46,32,84,105,109,101,32,115,112,101,110,116,32,105,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,97,99,99,117,109,117,108,97,116,101,100,32,105,110,32,116,119,111,32,111,116,104,101,114,32,99,111,117,110,116,101,114,115,44,32,115,101,99,111,110,100,115,32,97,110,100,32,109,105,99,114,111,115,101,99,111,110,100,115,46,32,84,104,101,32,99,111,117,110,116,101,114,115,32,97,114,101,32,115,116,111,114,101,100,32,102,111,114,32,101,97,99,104,32,99,97,108,108,32,116,114,97,99,101,100,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<73,102,32,99,97,108,108,32,116,105,109,101,32,116,114,97,99,105,110,103,32,105,115,32,115,116,97,114,116,101,100,32,119,104,105,108,101,32,97,108,114,101,97,100,121,32,114,117,110,110,105,110,103,44,32,116,104,101,32,99,111,117,110,116,32,97,110,100,32,116,105,109,101,32,114,101,115,116,97,114,116,32,102,114,111,109,32,122,101,114,111,46,32,84,111,32,112,97,117,115,101,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,44,32,117,115,101,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,112,97,117,115,101>>]},<<46,32,80,97,117,115,101,100,32,97,110,100,32,114,117,110,110,105,110,103,32,99,111,117,110,116,101,114,115,32,99,97,110,32,98,101,32,114,101,115,116,97,114,116,101,100,32,102,114,111,109,32,122,101,114,111,32,119,105,116,104,32>>,{code,[],[<<77,97,116,99,104,83,112,101,99,32,61,61,32,114,101,115,116,97,114,116>>]},<<46>>]},{p,[],[<<84,111,32,114,101,97,100,32,116,104,101,32,99,111,117,110,116,101,114,32,118,97,108,117,101,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]}]},{p,[],[<<84,104,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,97,110,100,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,97,114,101,32,109,117,116,117,97,108,108,121,32,101,120,99,108,117,115,105,118,101,44,32,97,110,100,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,32,40,105,102,32,110,111,32,111,112,116,105,111,110,115,32,97,114,101,32,115,112,101,99,105,102,105,101,100,41,46,32,84,104,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,108,108,95,99,111,117,110,116>>]},<<32,97,110,100,32>>,{code,[],[<<109,101,116,97>>]},<<32,112,101,114,102,111,114,109,32,97,32,107,105,110,100,32,111,102,32,108,111,99,97,108,32,116,114,97,99,105,110,103,44,32,97,110,100,32,99,97,110,110,111,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<46,32,65,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,103,108,111,98,97,108,108,121,32,111,114,32,108,111,99,97,108,108,121,32,116,114,97,99,101,100,46,32,73,102,32,103,108,111,98,97,108,32,116,114,97,99,105,110,103,32,105,115,32,115,112,101,99,105,102,105,101,100,32,102,111,114,32,97,32,115,101,116,32,111,102,32,102,117,110,99,116,105,111,110,115,44,32,116,104,101,110,32,108,111,99,97,108,44,32,109,101,116,97,44,32,99,97,108,108,32,116,105,109,101,44,32,97,110,100,32,99,97,108,108,32,99,111,117,110,116,32,116,114,97,99,105,110,103,32,102,111,114,32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,101,116,32,111,102,32,108,111,99,97,108,32,102,117,110,99,116,105,111,110,115,32,105,115,32,100,105,115,97,98,108,101,100,44,32,97,110,100,32,99,111,110,118,101,114,115,101,108,121,46>>]},{p,[],[<<87,104,101,110,32,100,105,115,97,98,108,105,110,103,32,116,114,97,99,101,44,32,116,104,101,32,111,112,116,105,111,110,32,109,117,115,116,32,109,97,116,99,104,32,116,104,101,32,116,121,112,101,32,111,102,32,116,114,97,99,101,32,115,101,116,32,111,110,32,116,104,101,32,102,117,110,99,116,105,111,110,46,32,84,104,97,116,32,105,115,44,32,108,111,99,97,108,32,116,114,97,99,105,110,103,32,109,117,115,116,32,98,101,32,100,105,115,97,98,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<108,111,99,97,108>>]},<<32,97,110,100,32,103,108,111,98,97,108,32,116,114,97,99,105,110,103,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,40,111,114,32,110,111,32,111,112,116,105,111,110,41,44,32,97,110,100,32,115,111,32,111,110,46>>]},{p,[],[<<80,97,114,116,32,111,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,108,105,115,116,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,100,105,114,101,99,116,108,121,46,32,73,102,32,97,32,102,117,110,99,116,105,111,110,32,104,97,115,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,105,116,32,99,97,110,32,98,101,32,114,101,112,108,97,99,101,100,32,119,105,116,104,32,97,32,110,101,119,32,111,110,101,46,32,84,111,32,99,104,97,110,103,101,32,97,110,32,101,120,105,115,116,105,110,103,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,117,115,101,32,116,104,101,32,66,73,70,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,114,97,99,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,114,97,99,101,95,105,110,102,111,47,50>>]}]},<<32,116,111,32,114,101,116,114,105,101,118,101,32,116,104,101,32,101,120,105,115,116,105,110,103,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,102,117,110,99,116,105,111,110,115,32,109,97,116,99,104,105,110,103,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<77,70,65>>]},<<46,32,84,104,105,115,32,105,115,32,122,101,114,111,32,105,102,32,110,111,110,101,32,109,97,116,99,104,101,100,46>>]},{p,[],[<<70,97,105,108,115,32,98,121,32,114,97,105,115,105,110,103,32,97,110,32,101,114,114,111,114,32,101,120,99,101,112,116,105,111,110,32,119,105,116,104,32,97,110,32,101,114,114,111,114,32,114,101,97,115,111,110,32,111,102,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[<<73,102,32,97,110,32,97,114,103,117,109,101,110,116,32,105,115,32,105,110,118,97,108,105,100,46>>]}]},{dt,[],[{code,[],[<<115,121,115,116,101,109,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<73,102,32,97,32,109,97,116,99,104,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,112,97,115,115,101,100,32,97,115,32,97,114,103,117,109,101,110,116,32,104,97,115,32,101,120,99,101,115,115,105,118,101,32,110,101,115,116,105,110,103,32,119,104,105,99,104,32,99,97,117,115,101,115,32,115,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,101,120,104,97,117,115,116,105,111,110,32,102,111,114,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,116,104,97,116,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,105,115,32,101,120,101,99,117,116,105,110,103,32,111,110,46,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,35,115,99,104,101,100,95,116,104,114,101,97,100,95,115,116,97,99,107,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[<<83,99,104,101,100,117,108,101,114,32,115,116,97,99,107,32,115,105,122,101>>]},<<32,99,97,110,32,98,101,32,99,111,110,102,105,103,117,114,101,100,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,55,48,50>>,signature => [{attribute,{2793,2},spec,{{erlang,trace_pattern,3},[{type,{2799,6},bounded_fun,[{type,{2799,6},'fun',[{type,{2799,6},product,[{var,{2799,7},'MFA'},{var,{2799,12},'MatchSpec'},{var,{2799,23},'FlagList'}]},{type,{2799,36},non_neg_integer,[]}]},[{type,{2800,7},constraint,[{atom,{2800,7},is_subtype},[{var,{2800,7},'MFA'},{user_type,{2800,14},trace_pattern_mfa,[]}]]},{type,{2801,7},constraint,[{atom,{2801,7},is_subtype},[{var,{2801,7},'MatchSpec'},{type,{2801,21},union,[{ann_type,{2801,21},[{var,{2801,21},'MatchSpecList'},{user_type,{2801,38},trace_match_spec,[]}]},{type,{2802,20},boolean,[]},{atom,{2803,20},restart},{atom,{2804,20},pause}]}]]},{type,{2805,7},constraint,[{atom,{2805,7},is_subtype},[{var,{2805,7},'FlagList'},{type,{2805,19},list,[{user_type,{2805,21},trace_pattern_flag,[]}]}]]}]]}]}}]}},{{function,trunc,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2112}],[<<116,114,117,110,99,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,117,110,99,97,116,101,115,32,116,104,101,32,100,101,99,105,109,97,108,115,32,111,102,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,53,46,55,41,46,10,53>>]}]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,45,53,46,55,41,46,10,45,53>>]}]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,53,41,46,10,53>>]}]},{pre,[],[{code,[],[<<62,32,116,114,117,110,99,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41,46,10,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]}]},{p,[],[<<73,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<116,114,117,110,99,40,51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48,41>>]},<<32,101,118,97,108,117,97,116,101,115,32,116,111,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56>>]},<<46,32,84,104,101,32,114,101,97,115,111,110,32,102,111,114,32,116,104,105,115,32,105,115,32,116,104,97,116,32,116,104,101,32,110,117,109,98,101,114,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,57,46,48>>]},<<32,99,97,110,110,111,116,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,73,110,115,116,101,97,100,44,32,116,104,101,32,102,108,111,97,116,32,108,105,116,101,114,97,108,32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32>>,{code,[],[<<51,54,48,50,56,55,57,55,48,49,56,57,54,51,57,54,56,46,48>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,99,108,111,115,101,115,116,32,110,117,109,98,101,114,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,101,120,97,99,116,108,121,32,97,115,32,97,32,102,108,111,97,116,32,118,97,108,117,101,46,32,83,101,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,108,111,97,116,95,114,101,112,114,101,115,101,110,116,97,116,105,111,110,95,112,114,111,98,108,101,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,70,108,111,97,116,105,110,103,32,80,111,105,110,116,32,78,117,109,98,101,114,115>>]},<<32,102,111,114,32,97,100,100,105,116,105,111,110,97,108,32,105,110,102,111,114,109,97,116,105,111,110,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,48,57>>,signature => [{attribute,{2112,2},spec,{{trunc,1},[{type,{2112,12},bounded_fun,[{type,{2112,12},'fun',[{type,{2112,12},product,[{var,{2112,13},'Number'}]},{type,{2112,24},integer,[]}]},[{type,{2113,7},constraint,[{atom,{2113,7},is_subtype},[{var,{2113,7},'Number'},{type,{2113,17},number,[]}]]}]]}]}}]}},{{function,tuple_size,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2119}],[<<116,117,112,108,101,95,115,105,122,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,110,32,105,110,116,101,103,101,114,32,116,104,97,116,32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,105,110,32>>,{code,[],[<<84,117,112,108,101>>]},<<44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,117,112,108,101,95,115,105,122,101,40,123,109,111,114,110,105,44,32,109,117,108,108,101,44,32,98,119,97,110,103,101,125,41,46,10,51>>]}]},{p,[],[<<65,108,108,111,119,101,100,32,105,110,32,103,117,97,114,100,32,116,101,115,116,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,52,48>>,signature => [{attribute,{2119,2},spec,{{tuple_size,1},[{type,{2119,17},bounded_fun,[{type,{2119,17},'fun',[{type,{2119,17},product,[{var,{2119,18},'Tuple'}]},{type,{2119,28},non_neg_integer,[]}]},[{type,{2120,7},constraint,[{atom,{2120,7},is_subtype},[{var,{2120,7},'Tuple'},{type,{2120,16},tuple,any}]]}]]}]}}]}},{{function,tuple_to_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2815}],[<<116,117,112,108,101,95,116,111,95,108,105,115,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32>>,{code,[],[<<84,117,112,108,101>>]},<<46,32>>,{code,[],[<<84,117,112,108,101>>]},<<32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,69,114,108,97,110,103,32,116,101,114,109,115,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,116,117,112,108,101,95,116,111,95,108,105,115,116,40,123,115,104,97,114,101,44,32,123,39,69,114,105,99,115,115,111,110,95,66,39,44,32,49,54,51,125,125,41,46,10,91,115,104,97,114,101,44,123,39,69,114,105,99,115,115,111,110,95,66,39,44,49,54,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,53,51>>,signature => [{attribute,{2815,2},spec,{{tuple_to_list,1},[{type,{2815,20},bounded_fun,[{type,{2815,20},'fun',[{type,{2815,20},product,[{var,{2815,21},'Tuple'}]},{type,{2815,31},list,[{type,{2815,32},term,[]}]}]},[{type,{2816,7},constraint,[{atom,{2816,7},is_subtype},[{var,{2816,7},'Tuple'},{type,{2816,16},tuple,any}]]}]]}]}}]}},{{function,unalias,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,831}],[<<117,110,97,108,105,97,115,47,49>>],#{<<101,110>> => [{p,[],[<<68,101,97,99,116,105,118,97,116,101,32,116,104,101,32,97,108,105,97,115,32>>,{code,[],[<<65,108,105,97,115>>]},<<32,112,114,101,118,105,111,117,115,108,121,32,99,114,101,97,116,101,100,32,98,121,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,46,32,65,110,32,97,108,105,97,115,32,99,97,110,32,102,111,114,32,101,120,97,109,112,108,101,32,98,101,32,99,114,101,97,116,101,100,32,118,105,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,97,108,105,97,115,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,108,105,97,115,47,48>>]}]},<<44,32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,51>>]}]},<<46,32>>,{code,[],[<<117,110,97,108,105,97,115,47,49>>]},<<32,119,105,108,108,32,97,108,119,97,121,115,32,100,101,97,99,116,105,118,97,116,101,32,116,104,101,32,97,108,105,97,115,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,111,112,116,105,111,110,115,32,117,115,101,100,32,119,104,101,110,32,99,114,101,97,116,105,110,103,32,116,104,101,32,97,108,105,97,115,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,116,114,117,101,32,105,102,32>>,{code,[],[<<65,108,105,97,115>>]},<<32,119,97,115,32,97,32,99,117,114,114,101,110,116,108,121,32,97,99,116,105,118,101,32,97,108,105,97,115,32,102,111,114,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,101,115,59,32,111,116,104,101,114,119,105,115,101,44,32,102,97,108,115,101,46>>]},{p,[],[<<70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,112,114,111,99,101,115,115,32,97,108,105,97,115,101,115,32,115,101,101,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,112,114,111,99,101,115,115,45,97,108,105,97,115,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{i,[],[<<80,114,111,99,101,115,115,32,65,108,105,97,115,101,115>>]}]},<<32,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,54,54>>,signature => [{attribute,{831,2},spec,{{unalias,1},[{type,{831,14},bounded_fun,[{type,{831,14},'fun',[{type,{831,14},product,[{var,{831,15},'Alias'}]},{type,{831,25},boolean,[]}]},[{type,{832,7},constraint,[{atom,{832,7},is_subtype},[{var,{832,7},'Alias'},{type,{832,16},reference,[]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,unique_integer,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1592}],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,48>>],#{<<101,110>> => [{p,[],[<<71,101,110,101,114,97,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,97,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<105,110,116,101,103,101,114,32,117,110,105,113,117,101,32,111,110,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101>>]},<<46,32,84,104,101,32,115,97,109,101,32,97,115,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,93,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,50,57,57,50>>,signature => [{attribute,{1592,2},spec,{{erlang,unique_integer,0},[{type,{1592,28},'fun',[{type,{1592,28},product,[]},{type,{1592,34},integer,[]}]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,unique_integer,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1585}],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<71,101,110,101,114,97,116,101,115,32,97,110,100,32,114,101,116,117,114,110,115,32,97,110,32>>,{a,[{href,<<115,121,115,116,101,109,47,101,102,102,105,99,105,101,110,99,121,95,103,117,105,100,101,58,97,100,118,97,110,99,101,100,35,117,110,105,113,117,101,95,105,110,116,101,103,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<105,110,116,101,103,101,114,32,117,110,105,113,117,101,32,111,110,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101>>]},<<46,32,84,104,101,32,105,110,116,101,103,101,114,32,105,115,32,117,110,105,113,117,101,32,105,110,32,116,104,101,32,115,101,110,115,101,32,116,104,97,116,32,116,104,105,115,32,66,73,70,44,32,117,115,105,110,103,32,116,104,101,32,115,97,109,101,32,115,101,116,32,111,102,32,109,111,100,105,102,105,101,114,115,44,32,100,111,101,115,32,110,111,116,32,114,101,116,117,114,110,32,116,104,101,32,115,97,109,101,32,105,110,116,101,103,101,114,32,109,111,114,101,32,116,104,97,110,32,111,110,99,101,32,111,110,32,116,104,101,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,69,97,99,104,32,105,110,116,101,103,101,114,32,118,97,108,117,101,32,99,97,110,32,111,102,32,99,111,117,114,115,101,32,98,101,32,99,111,110,115,116,114,117,99,116,101,100,32,98,121,32,111,116,104,101,114,32,109,101,97,110,115,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,119,104,101,110,32>>,{code,[],[<<91,93>>]},<<32,105,115,32,112,97,115,115,101,100,32,97,115,32>>,{code,[],[<<77,111,100,105,102,105,101,114,76,105,115,116>>]},<<44,32,98,111,116,104,32,110,101,103,97,116,105,118,101,32,97,110,100,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,115,32,99,97,110,32,98,101,32,114,101,116,117,114,110,101,100,46,32,84,104,105,115,32,116,111,32,117,115,101,32,116,104,101,32,114,97,110,103,101,32,111,102,32,105,110,116,101,103,101,114,115,32,116,104,97,116,32,100,111,32,110,111,116,32,110,101,101,100,32,104,101,97,112,32,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,46,32,66,121,32,100,101,102,97,117,108,116,32,116,104,101,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,115,32,97,114,101,32,97,108,115,111,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,117,110,105,113,117,101,44,32,116,104,97,116,32,105,115,44,32,97,110,121,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,32,99,97,110,32,98,101,32,115,109,97,108,108,101,114,32,111,114,32,108,97,114,103,101,114,32,116,104,97,110,32,112,114,101,118,105,111,117,115,108,121,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,115,46>>]},{p,[],[{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,58>>]},{dl,[],[{dt,[],[<<112,111,115,105,116,105,118,101>>]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,111,110,108,121,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,115,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,98,121,32,112,97,115,115,105,110,103,32,116,104,101,32>>,{code,[],[<<112,111,115,105,116,105,118,101>>]},<<32,109,111,100,105,102,105,101,114,32,121,111,117,32,119,105,108,108,32,103,101,116,32,104,101,97,112,32,97,108,108,111,99,97,116,101,100,32,105,110,116,101,103,101,114,115,32,40,98,105,103,110,117,109,115,41,32,113,117,105,99,107,101,114,46>>]}]},{dt,[],[<<109,111,110,111,116,111,110,105,99>>]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,83,116,114,105,99,116,108,121,95,77,111,110,111,116,111,110,105,99,97,108,108,121,95,73,110,99,114,101,97,115,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<115,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103>>]},<<32,105,110,116,101,103,101,114,115,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,99,114,101,97,116,105,111,110,32,116,105,109,101,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,105,110,116,101,103,101,114,32,114,101,116,117,114,110,101,100,32,105,115,32,97,108,119,97,121,115,32,108,97,114,103,101,114,32,116,104,97,110,32,112,114,101,118,105,111,117,115,108,121,32,114,101,116,117,114,110,101,100,32,105,110,116,101,103,101,114,115,32,111,110,32,116,104,101,32,99,117,114,114,101,110,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46>>]},{p,[],[<<84,104,101,115,101,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,111,114,100,101,114,32,98,101,116,119,101,101,110,32,101,118,101,110,116,115,32,111,110,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46,32,84,104,97,116,32,105,115,44,32,105,102,32,98,111,116,104,32>>,{code,[],[<<88,32,61,32,101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]},<<32,97,110,100,32>>,{code,[],[<<89,32,61,32,101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]},<<32,97,114,101,32,101,120,101,99,117,116,101,100,32,98,121,32,100,105,102,102,101,114,101,110,116,32,112,114,111,99,101,115,115,101,115,32,40,111,114,32,116,104,101,32,115,97,109,101,32,112,114,111,99,101,115,115,41,32,111,110,32,116,104,101,32,115,97,109,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,32,97,110,100,32>>,{code,[],[<<88,32,60,32,89>>]},<<44,32,119,101,32,107,110,111,119,32,116,104,97,116,32>>,{code,[],[<<88>>]},<<32,119,97,115,32,99,114,101,97,116,101,100,32,98,101,102,111,114,101,32>>,{code,[],[<<89>>]},<<46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<83,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,118,97,108,117,101,115,32,97,114,101,32,105,110,104,101,114,101,110,116,108,121,32,113,117,105,116,101,32,101,120,112,101,110,115,105,118,101,32,116,111,32,103,101,110,101,114,97,116,101,32,97,110,100,32,115,99,97,108,101,115,32,112,111,111,114,108,121,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,118,97,108,117,101,115,32,110,101,101,100,32,116,111,32,98,101,32,115,121,110,99,104,114,111,110,105,122,101,100,32,98,101,116,119,101,101,110,32,67,80,85,32,99,111,114,101,115,46,32,84,104,97,116,32,105,115,44,32,100,111,32,110,111,116,32,112,97,115,115,32,116,104,101,32>>,{code,[],[<<109,111,110,111,116,111,110,105,99>>]},<<32,109,111,100,105,102,105,101,114,32,117,110,108,101,115,115,32,121,111,117,32,114,101,97,108,108,121,32,110,101,101,100,32,115,116,114,105,99,116,108,121,32,109,111,110,111,116,111,110,105,99,97,108,108,121,32,105,110,99,114,101,97,115,105,110,103,32,118,97,108,117,101,115,46>>]}]}]}]},{p,[],[<<65,108,108,32,118,97,108,105,100,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,32,99,97,110,32,98,101,32,99,111,109,98,105,110,101,100,46,32,82,101,112,101,97,116,101,100,32,40,118,97,108,105,100,41,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,32,105,110,32,116,104,101,32>>,{code,[],[<<77,111,100,105,102,105,101,114,76,105,115,116>>]},<<32,97,114,101,32,105,103,110,111,114,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,115,101,116,32,111,102,32,105,110,116,101,103,101,114,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<101,114,108,97,110,103,58,117,110,105,113,117,101,95,105,110,116,101,103,101,114,47,49>>]},<<32,117,115,105,110,103,32,100,105,102,102,101,114,101,110,116,32,115,101,116,115,32,111,102,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<115,32>>,{em,[],[<<119,105,108,108,32,111,118,101,114,108,97,112>>]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,98,121,32,99,97,108,108,105,110,103,32>>,{code,[],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,109,111,110,111,116,111,110,105,99,93,41>>]},<<44,32,97,110,100,32>>,{code,[],[<<117,110,105,113,117,101,95,105,110,116,101,103,101,114,40,91,112,111,115,105,116,105,118,101,44,32,109,111,110,111,116,111,110,105,99,93,41>>]},<<32,114,101,112,101,97,116,101,100,108,121,44,32,121,111,117,32,119,105,108,108,32,101,118,101,110,116,117,97,108,108,121,32,115,101,101,32,115,111,109,101,32,105,110,116,101,103,101,114,115,32,116,104,97,116,32,97,114,101,32,114,101,116,117,114,110,101,100,32,98,121,32,98,111,116,104,32,99,97,108,108,115,46>>]}]},{p,[],[<<70,97,105,108,117,114,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<105,102,32>>,{code,[],[<<77,111,100,105,102,105,101,114,76,105,115,116>>]},<<32,105,115,32,110,111,116,32,97,32,112,114,111,112,101,114,32,108,105,115,116,46>>]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[<<105,102,32>>,{code,[],[<<77,111,100,105,102,105,101,114>>]},<<32,105,115,32,110,111,116,32,97,32,118,97,108,105,100,32,109,111,100,105,102,105,101,114,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,48,48,53>>,signature => [{attribute,{1585,2},spec,{{erlang,unique_integer,1},[{type,{1585,28},bounded_fun,[{type,{1585,28},'fun',[{type,{1585,28},product,[{var,{1585,29},'ModifierList'}]},{type,{1585,46},integer,[]}]},[{type,{1586,7},constraint,[{atom,{1586,7},is_subtype},[{var,{1586,7},'ModifierList'},{type,{1586,23},list,[{var,{1586,24},'Modifier'}]}]]},{type,{1587,7},constraint,[{atom,{1587,7},is_subtype},[{var,{1587,7},'Modifier'},{type,{1587,19},union,[{atom,{1587,19},positive},{atom,{1587,30},monotonic}]}]]}]]}]}}],since => <<79,84,80,32,49,56,46,48>>}},{{function,universaltime,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2125}],[<<117,110,105,118,101,114,115,97,108,116,105,109,101,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,99,117,114,114,101,110,116,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,97,99,99,111,114,100,105,110,103,32,116,111,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,32,105,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125,44,32,123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125,125>>]},<<32,105,102,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32>>,{code,[],[<<101,114,108,97,110,103,58,117,110,105,118,101,114,115,97,108,116,105,109,101,40,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<101,114,108,97,110,103,58,108,111,99,97,108,116,105,109,101,40,41>>]},<<46,32,84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,111,115,45,115,121,115,116,101,109,45,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<79,83,32,83,121,115,116,101,109,32,84,105,109,101>>]},<<46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,117,110,105,118,101,114,115,97,108,116,105,109,101,40,41,46,10,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,49,56,44,52,51,125,125>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,48,56,55>>,signature => [{attribute,{2125,2},spec,{{erlang,universaltime,0},[{type,{2125,27},bounded_fun,[{type,{2125,27},'fun',[{type,{2125,27},product,[]},{var,{2125,33},'DateTime'}]},[{type,{2126,7},constraint,[{atom,{2126,7},is_subtype},[{var,{2126,7},'DateTime'},{remote_type,{2126,19},[{atom,{2126,19},calendar},{atom,{2126,28},datetime},[]]}]]}]]}]}}]}},{{function,universaltime_to_localtime,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2942}],[<<117,110,105,118,101,114,115,97,108,116,105,109,101,95,116,111,95,108,111,99,97,108,116,105,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,111,110,118,101,114,116,115,32,85,110,105,118,101,114,115,97,108,32,84,105,109,101,32,67,111,111,114,100,105,110,97,116,101,100,32,40,85,84,67,41,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,116,111,32,108,111,99,97,108,32,100,97,116,101,32,97,110,100,32,116,105,109,101,32,105,110,32,116,104,101,32,102,111,114,109,32>>,{code,[],[<<123,123,89,101,97,114,44,32,77,111,110,116,104,44,32,68,97,121,125,44,32,123,72,111,117,114,44,32,77,105,110,117,116,101,44,32,83,101,99,111,110,100,125,125>>]},<<32,105,102,32,115,117,112,112,111,114,116,101,100,32,98,121,32,116,104,101,32,117,110,100,101,114,108,121,105,110,103,32,79,83,46,32,79,116,104,101,114,119,105,115,101,32,110,111,32,99,111,110,118,101,114,115,105,111,110,32,105,115,32,100,111,110,101,44,32,97,110,100,32>>,{code,[],[<<85,110,105,118,101,114,115,97,108,116,105,109,101>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,101,114,108,97,110,103,58,117,110,105,118,101,114,115,97,108,116,105,109,101,95,116,111,95,108,111,99,97,108,116,105,109,101,40,123,123,49,57,57,54,44,49,49,44,54,125,44,123,49,52,44,49,56,44,52,51,125,125,41,46,10,123,123,49,57,57,54,44,49,49,44,55,125,44,123,49,53,44,49,56,44,52,51,125,125>>]}]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<85,110,105,118,101,114,115,97,108,116,105,109,101>>]},<<32,100,101,110,111,116,101,115,32,97,110,32,105,110,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,49,48,54>>,signature => [{attribute,{2942,2},spec,{{erlang,universaltime_to_localtime,1},[{type,{2942,40},bounded_fun,[{type,{2942,40},'fun',[{type,{2942,40},product,[{var,{2942,41},'Universaltime'}]},{var,{2942,60},'Localtime'}]},[{type,{2943,7},constraint,[{atom,{2943,7},is_subtype},[{var,{2943,7},'Localtime'},{remote_type,{2943,20},[{atom,{2943,20},calendar},{atom,{2943,29},datetime},[]]}]]},{type,{2944,7},constraint,[{atom,{2944,7},is_subtype},[{var,{2944,7},'Universaltime'},{remote_type,{2944,24},[{atom,{2944,24},calendar},{atom,{2944,33},datetime},[]]}]]}]]}]}}]}},{{function,unlink,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2137}],[<<117,110,108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,109,111,118,101,115,32,97,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,105,110,103,32,112,114,111,99,101,115,115,32,97,110,100,32,97,110,111,116,104,101,114,32,112,114,111,99,101,115,115,32,111,114,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,100,32,98,121,32>>,{code,[],[<<73,100>>]},<<46,32,87,101,32,119,105,108,108,32,102,114,111,109,32,104,101,114,101,32,111,110,32,99,97,108,108,32,116,104,101,32,105,100,101,110,116,105,102,105,101,100,32,112,114,111,99,101,115,115,32,111,114,32,112,111,114,116,32,117,110,108,105,110,107,101,101,46>>]},{p,[],[<<65,32,108,105,110,107,32,99,97,110,32,98,101,32,115,101,116,32,117,112,32,117,115,105,110,103,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,110,107,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,110,107,47,49>>]}]},<<32,66,73,70,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,108,105,110,107,115,32,97,110,100,32,101,120,105,116,32,115,105,103,110,97,108,115,32,100,117,101,32,116,111,32,108,105,110,107,115,44,32,115,101,101,32,116,104,101,32>>,{i,[],[<<80,114,111,99,101,115,115,101,115>>]},<<32,99,104,97,112,116,101,114,32,105,110,32,116,104,101,32>>,{i,[],[<<69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108>>]},<<58>>]},{ul,[],[{li,[],[{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,108,105,110,107,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<76,105,110,107,115>>]}]},{li,[],[{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,115,101,110,100,105,110,103,95,101,120,105,116,95,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<83,101,110,100,105,110,103,32,69,120,105,116,32,83,105,103,110,97,108,115>>]}]},{li,[],[{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,114,101,99,101,105,118,105,110,103,95,101,120,105,116,95,115,105,103,110,97,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<82,101,99,101,105,118,105,110,103,32,69,120,105,116,32,83,105,103,110,97,108,115>>]}]}]},{p,[],[<<79,110,99,101,32>>,{code,[],[<<117,110,108,105,110,107,40,73,100,41>>]},<<32,104,97,115,32,114,101,116,117,114,110,101,100,44,32,105,116,32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,104,97,116,32,116,104,101,32,108,105,110,107,32,98,101,116,119,101,101,110,32,116,104,101,32,99,97,108,108,101,114,32,97,110,100,32,116,104,101,32,117,110,108,105,110,107,101,101,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,111,110,32,116,104,101,32,99,97,108,108,101,114,32,105,110,32,116,104,101,32,102,117,116,117,114,101,32,40,117,110,108,101,115,115,32,116,104,101,32,108,105,110,107,32,105,115,32,115,101,116,117,112,32,97,103,97,105,110,41,46,32,78,111,116,101,32,116,104,97,116,32,105,102,32,116,104,101,32,99,97,108,108,101,114,32,105,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,116,114,97,112,95,101,120,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,114,97,112,112,105,110,103,32,101,120,105,116,115>>]},<<44,32,97,110,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,73,100,44,32,69,120,105,116,82,101,97,115,111,110,125>>]},<<32,109,101,115,115,97,103,101,32,100,117,101,32,116,111,32,116,104,101,32,108,105,110,107,32,109,97,121,32,104,97,118,101,32,98,101,101,110,32,112,108,97,99,101,100,32,105,110,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,111,102,32,116,104,101,32,99,97,108,108,101,114,32,98,101,102,111,114,101,32,116,104,101,32>>,{code,[],[<<117,110,108,105,110,107,40,73,100,41>>]},<<32,99,97,108,108,32,99,111,109,112,108,101,116,101,100,46,32,65,108,115,111,32,110,111,116,101,32,116,104,97,116,32,116,104,101,32>>,{code,[],[<<123,39,69,88,73,84,39,44,32,73,100,44,32,69,120,105,116,82,101,97,115,111,110,125>>]},<<32,109,101,115,115,97,103,101,32,109,97,121,32,98,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,108,105,110,107,44,32,98,117,116,32,109,97,121,32,97,108,115,111,32,98,101,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,117,110,108,105,107,101,101,32,115,101,110,100,105,110,103,32,116,104,101,32,99,97,108,108,101,114,32,97,110,32,101,120,105,116,32,115,105,103,110,97,108,32,98,121,32,99,97,108,108,105,110,103,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,101,120,105,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,120,105,116,47,50>>]}]},<<32,66,73,70,46,32,84,104,101,114,101,102,111,114,101,44,32,105,116,32,109,97,121,32,111,114,32,109,97,121,32,110,111,116,32,98,101,32,97,112,112,114,111,112,114,105,97,116,101,32,116,111,32,99,108,101,97,110,32,117,112,32,116,104,101,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,97,102,116,101,114,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<117,110,108,105,110,107,40,73,100,41>>]},<<32,97,115,32,102,111,108,108,111,119,115,44,32,119,104,101,110,32,116,114,97,112,112,105,110,103,32,101,120,105,116,115,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<117,110,108,105,110,107,40,73,100,41,44,10,114,101,99,101,105,118,101,10,32,32,32,32,123,39,69,88,73,84,39,44,32,73,100,44,32,95,125,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,97,102,116,101,114,32,48,32,45,62,10,32,32,32,32,32,32,32,32,116,114,117,101,10,101,110,100>>]}]},{p,[],[<<84,104,101,32,108,105,110,107,32,114,101,109,111,118,97,108,32,105,115,32,112,101,114,102,111,114,109,101,100,32,97,115,121,110,99,104,114,111,110,111,117,115,108,121,46,32,73,102,32,115,117,99,104,32,97,32,108,105,110,107,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,44,32,110,111,116,104,105,110,103,32,105,115,32,100,111,110,101,46,32,65,32,100,101,116,97,105,108,101,100,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,100,105,115,116,95,112,114,111,116,111,99,111,108,35,108,105,110,107,95,112,114,111,116,111,99,111,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<108,105,110,107,32,112,114,111,116,111,99,111,108>>]},<<32,99,97,110,32,98,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32>>,{i,[],[<<68,105,115,116,114,105,98,117,116,105,111,110,32,80,114,111,116,111,99,111,108>>]},<<32,99,104,97,112,116,101,114,32,111,102,32,116,104,101,32>>,{i,[],[<<69,82,84,83,32,85,115,101,114,39,115,32,71,117,105,100,101>>]},<<46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<73,100>>]},<<32,100,111,101,115,32,110,111,116,32,105,100,101,110,116,105,102,121,32,97,32,112,114,111,99,101,115,115,32,111,114,32,97,32,110,111,100,101,32,108,111,99,97,108,32,112,111,114,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,49,50,53>>,signature => [{attribute,{2137,2},spec,{{unlink,1},[{type,{2137,13},bounded_fun,[{type,{2137,13},'fun',[{type,{2137,13},product,[{var,{2137,14},'Id'}]},{atom,{2137,21},true}]},[{type,{2138,7},constraint,[{atom,{2138,7},is_subtype},[{var,{2138,7},'Id'},{type,{2138,13},union,[{type,{2138,13},pid,[]},{type,{2138,21},port,[]}]}]]}]]}]}}]}},{{function,unregister,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2143}],[<<117,110,114,101,103,105,115,116,101,114,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,109,111,118,101,115,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,103,105,115,116,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,103,105,115,116,101,114,101,100,32,110,97,109,101>>]}]},<<32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,97,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,114,32,97,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,102,114,111,109,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,114,117,110,116,105,109,101,45,115,101,114,118,105,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<110,97,109,101,32,114,101,103,105,115,116,114,121>>]}]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,117,110,114,101,103,105,115,116,101,114,40,100,98,41,46,10,116,114,117,101>>]}]},{p,[],[<<75,101,101,112,32,105,110,32,109,105,110,100,32,116,104,97,116,32,121,111,117,32,99,97,110,32,115,116,105,108,108,32,114,101,99,101,105,118,101,32,115,105,103,110,97,108,115,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,32,97,102,116,101,114,32,105,116,32,104,97,115,32,98,101,101,110,32,117,110,114,101,103,105,115,116,101,114,101,100,32,97,115,32,116,104,101,32,115,101,110,100,101,114,32,109,97,121,32,104,97,118,101,32,108,111,111,107,101,100,32,117,112,32,116,104,101,32,110,97,109,101,32,98,101,102,111,114,101,32,115,101,110,100,105,110,103,32,116,111,32,105,116,46>>]},{p,[],[<<85,115,101,114,115,32,97,114,101,32,97,100,118,105,115,101,100,32,110,111,116,32,116,111,32,117,110,114,101,103,105,115,116,101,114,32,115,121,115,116,101,109,32,112,114,111,99,101,115,115,101,115,46>>]},{p,[],[<<70,97,105,108,117,114,101,58,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,102,32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,105,115,32,110,111,116,32,97,32,114,101,103,105,115,116,101,114,101,100,32,110,97,109,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,49,57,55>>,signature => [{attribute,{2143,2},spec,{{unregister,1},[{type,{2143,17},bounded_fun,[{type,{2143,17},'fun',[{type,{2143,17},product,[{var,{2143,18},'RegName'}]},{atom,{2143,30},true}]},[{type,{2144,7},constraint,[{atom,{2144,7},is_subtype},[{var,{2144,7},'RegName'},{type,{2144,18},atom,[]}]]}]]}]}}]}},{{function,whereis,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2149}],[<<119,104,101,114,101,105,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114,32,111,114,32,112,111,114,116,32,105,100,101,110,116,105,102,105,101,114,32,119,105,116,104,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,114,101,103,105,115,116,101,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,103,105,115,116,101,114,101,100,32,110,97,109,101>>]}]},<<32>>,{code,[],[<<82,101,103,78,97,109,101>>]},<<32,102,114,111,109,32,116,104,101,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115,35,114,117,110,116,105,109,101,45,115,101,114,118,105,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<110,97,109,101,32,114,101,103,105,115,116,114,121>>]}]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<117,110,100,101,102,105,110,101,100>>]},<<32,105,102,32,116,104,101,32,110,97,109,101,32,105,115,32,110,111,116,32,114,101,103,105,115,116,101,114,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<62,32,119,104,101,114,101,105,115,40,100,98,41,46,10,60,48,46,52,51,46,48,62>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,50,49,56>>,signature => [{attribute,{2149,2},spec,{{whereis,1},[{type,{2149,14},bounded_fun,[{type,{2149,14},'fun',[{type,{2149,14},product,[{var,{2149,15},'RegName'}]},{type,{2149,27},union,[{type,{2149,27},pid,[]},{type,{2149,35},port,[]},{atom,{2149,44},undefined}]}]},[{type,{2150,7},constraint,[{atom,{2150,7},is_subtype},[{var,{2150,7},'RegName'},{type,{2150,18},atom,[]}]]}]]}]}}]}},{{function,yield,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3438}],[<<121,105,101,108,100,47,48>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,103,105,118,101,32,111,116,104,101,114,32,112,114,111,99,101,115,115,101,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,111,114,32,104,105,103,104,101,114,32,112,114,105,111,114,105,116,121,32,40,105,102,32,97,110,121,41,32,97,32,99,104,97,110,99,101,32,116,111,32,101,120,101,99,117,116,101,32,98,101,102,111,114,101,32,114,101,116,117,114,110,105,110,103,46,32,84,104,101,114,101,32,105,115,32,110,111,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,97,110,121,32,111,116,104,101,114,32,112,114,111,99,101,115,115,32,114,117,110,115,32,98,101,116,119,101,101,110,32,116,104,101,32,105,110,118,111,99,97,116,105,111,110,32,97,110,100,32,114,101,116,117,114,110,32,111,102,32>>,{code,[],[<<101,114,108,97,110,103,58,121,105,101,108,100,47,48>>]},<<46>>]},{p,[],[<<83,101,101,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,111,114,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,114,101,99,101,105,118,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[{code,[],[<<114,101,99,101,105,118,101,45,97,102,116,101,114>>]},<<32,101,120,112,114,101,115,115,105,111,110,115>>]},<<32,102,111,114,32,104,111,119,32,116,111,32,109,97,107,101,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,115,108,101,101,112,32,102,111,114,32,97,32,115,112,101,99,105,102,105,99,32,110,117,109,98,101,114,32,111,102,32,109,105,108,108,105,115,101,99,111,110,100,115,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,101,114,101,32,105,115,32,115,101,108,100,111,109,32,111,114,32,110,101,118,101,114,32,97,110,121,32,110,101,101,100,32,116,111,32,117,115,101,32,116,104,105,115,32,66,73,70,46,32,85,115,105,110,103,32,116,104,105,115,32,66,73,70,32,119,105,116,104,111,117,116,32,97,32,116,104,111,114,111,117,103,104,32,103,114,97,115,112,32,111,102,32,104,111,119,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,119,111,114,107,115,32,99,97,110,32,99,97,117,115,101,32,112,101,114,102,111,114,109,97,110,99,101,32,100,101,103,114,97,100,97,116,105,111,110,46,32,84,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,112,117,116,115,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,32,108,97,115,116,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,99,104,101,100,117,108,101,114,39,115,32,113,117,101,117,101,32,102,111,114,32,112,114,111,99,101,115,115,101,115,32,111,102,32,116,104,101,32,115,97,109,101,32,112,114,105,111,114,105,116,121,32,97,115,32,116,104,101,32,99,117,114,114,101,110,116,32,112,114,111,99,101,115,115,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,101,114,116,115,47,100,111,99,47,115,114,99,47,101,114,108,97,110,103,46,120,109,108,35,76,49,51,50,51,53>>,signature => [{attribute,{3438,2},spec,{{erlang,yield,0},[{type,{3438,19},'fun',[{type,{3438,19},product,[]},{atom,{3438,25},true}]}]}}]}},{{type,any,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,80}],[<<45,116,121,112,101,32,97,110,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,108,108,32,112,111,115,115,105,98,108,101,32,69,114,108,97,110,103,32,116,101,114,109,115,46,32,83,121,110,111,110,121,109,32,102,111,114,32>>,{code,[],[<<116,101,114,109,40,41>>]},<<46>>]}]},#{signature => [{attribute,{80,2},type,{any,{type,{80,16},any,[]},[]}}]}},{{type,arity,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,81}],[<<45,116,121,112,101,32,97,114,105,116,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,97,114,105,116,121,32,111,102,32,97,32,102,117,110,99,116,105,111,110,32,111,114,32,116,121,112,101,46>>]}]},#{signature => [{attribute,{81,2},type,{arity,{type,{81,18},arity,[]},[]}}]}},{{type,atom,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,82}],[<<45,116,121,112,101,32,97,116,111,109,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,97,116,111,109>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,116,111,109>>]},<<46>>]}]},#{signature => [{attribute,{82,2},type,{atom,{type,{82,17},atom,[]},[]}}]}},{{type,binary,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,83}],[<<45,116,121,112,101,32,98,105,110,97,114,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,98,105,116,45,115,116,114,105,110,103,115,45,97,110,100,45,98,105,110,97,114,105,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<98,105,110,97,114,121>>]},<<44,32,116,104,97,116,32,105,115,44,32,97,32,98,105,116,115,116,114,105,110,103,32,119,105,116,104,32,97,32,115,105,122,101,32,100,105,118,105,115,105,98,108,101,32,98,121,32,56,46>>]}]},#{signature => [{attribute,{83,2},type,{binary,{type,{83,19},binary,[{integer,83,0},{integer,{83,25},8}]},[]}}]}},{{type,bitstring,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,84}],[<<45,116,121,112,101,32,98,105,116,115,116,114,105,110,103,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,98,105,116,45,115,116,114,105,110,103,115,45,97,110,100,45,98,105,110,97,114,105,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<98,105,116,115,116,114,105,110,103>>]},<<46>>]}]},#{signature => [{attribute,{84,2},type,{bitstring,{type,{84,22},binary,[{integer,84,0},{integer,{84,28},1}]},[]}}]}},{{type,boolean,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,86}],[<<45,116,121,112,101,32,98,111,111,108,101,97,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,98,111,111,108,101,97,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<98,111,111,108,101,97,110>>]},<<32,118,97,108,117,101,46>>]}]},#{signature => [{attribute,{86,2},type,{boolean,{type,{86,20},union,[{atom,{86,20},true},{atom,{86,27},false}]},[]}}]}},{{type,byte,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,87}],[<<45,116,121,112,101,32,98,121,116,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,98,121,116,101,32,111,102,32,100,97,116,97,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{signature => [{attribute,{87,2},type,{byte,{type,{87,17},range,[{integer,{87,17},0},{integer,{87,20},255}]},[]}}]}},{{type,char,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,88}],[<<45,116,121,112,101,32,99,104,97,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,32,111,114,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,99,111,100,101>>]},<<32,99,111,100,101,112,111,105,110,116,32,112,114,101,115,101,110,116,101,100,32,98,121,32,97,110,32,105,110,116,101,103,101,114,46>>]}]},#{signature => [{attribute,{88,2},type,{char,{type,{88,17},range,[{integer,{88,17},0},{integer,{88,20},1114111}]},[]}}]}},{{type,float,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,89}],[<<45,116,121,112,101,32,102,108,111,97,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,110,117,109,98,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<102,108,111,97,116>>]},<<46>>]}]},#{signature => [{attribute,{89,2},type,{float,{type,{89,18},float,[]},[]}}]}},{{type,function,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,90}],[<<45,116,121,112,101,32,102,117,110,99,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,102,117,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<102,117,110>>]},<<46>>]}]},#{signature => [{attribute,{90,2},type,{function,{type,{90,21},'fun',[]},[]}}]}},{{type,identifier,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,91}],[<<45,116,121,112,101,32,105,100,101,110,116,105,102,105,101,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,117,110,105,113,117,101,32,105,100,101,110,116,105,102,105,101,114,32,102,111,114,32,115,111,109,101,32,101,110,116,105,116,121,44,32,102,111,114,32,101,120,97,109,112,108,101,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,114,111,99,101,115,115,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,111,99,101,115,115>>]},<<44,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,112,111,114,116,115,35,112,111,114,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,111,114,116>>]},<<32,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<109,111,110,105,116,111,114>>]},<<46>>]}]},#{signature => [{attribute,{91,2},type,{identifier,{type,{91,23},union,[{type,{91,23},pid,[]},{type,{91,31},port,[]},{type,{91,40},reference,[]}]},[]}}]}},{{type,integer,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,92}],[<<45,116,121,112,101,32,105,110,116,101,103,101,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,110,117,109,98,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<105,110,116,101,103,101,114>>]},<<46>>]}]},#{signature => [{attribute,{92,2},type,{integer,{type,{92,20},integer,[]},[]}}]}},{{type,iodata,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,93}],[<<45,116,121,112,101,32,105,111,100,97,116,97,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,98,105,110,97,114,121,32,111,114,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,98,121,116,101,115,32,97,110,100,47,111,114,32,105,111,100,97,116,97,46,32,84,104,105,115,32,100,97,116,97,116,121,112,101,32,105,115,32,117,115,101,100,32,116,111,32,114,101,112,114,101,115,101,110,116,32,100,97,116,97,32,116,104,97,116,32,105,115,32,109,101,97,110,116,32,116,111,32,98,101,32,111,117,116,112,117,116,32,117,115,105,110,103,32,97,110,121,32,73,47,79,32,109,111,100,117,108,101,46,32,70,111,114,32,101,120,97,109,112,108,101,58,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<102,105,108,101,58,119,114,105,116,101,47,50>>]},<<32,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,103,101,110,95,116,99,112,35,115,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<103,101,110,95,116,99,112,58,115,101,110,100,47,50>>]},<<46>>]},{p,[],[<<84,111,32,99,111,110,118,101,114,116,32,97,110,32,105,111,100,97,116,97,40,41,32,116,101,114,109,32,116,111,32,98,105,110,97,114,121,40,41,32,121,111,117,32,99,97,110,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,50>>]},<<46,32,84,111,32,116,114,97,110,115,99,111,100,101,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,114,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<115,116,114,105,110,103,40,41>>]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,35,99,104,97,114,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<117,110,105,99,111,100,101,58,99,104,97,114,100,97,116,97,40,41>>]},<<32,116,111,32,105,111,100,97,116,97,40,41,32,121,111,117,32,99,97,110,32,117,115,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,35,99,104,97,114,97,99,116,101,114,115,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<117,110,105,99,111,100,101,58,99,104,97,114,97,99,116,101,114,115,95,116,111,95,98,105,110,97,114,121,47,49>>]},<<46>>]}]},#{signature => [{attribute,{93,2},type,{iodata,{type,{93,19},union,[{type,{93,19},iolist,[]},{type,{93,30},binary,[]}]},[]}}]}},{{type,iolist,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,94}],[<<45,116,121,112,101,32,105,111,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,98,121,116,101,115,32,97,110,100,47,111,114,32,105,111,100,97,116,97,46,32,84,104,105,115,32,100,97,116,97,116,121,112,101,32,105,115,32,117,115,101,100,32,116,111,32,114,101,112,114,101,115,101,110,116,32,100,97,116,97,32,116,104,97,116,32,105,115,32,109,101,97,110,116,32,116,111,32,98,101,32,111,117,116,112,117,116,32,117,115,105,110,103,32,97,110,121,32,73,47,79,32,109,111,100,117,108,101,46,32,70,111,114,32,101,120,97,109,112,108,101,58,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<102,105,108,101,58,119,114,105,116,101,47,50>>]},<<32,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,103,101,110,95,116,99,112,35,115,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<103,101,110,95,116,99,112,58,115,101,110,100,47,50>>]},<<46>>]},{p,[],[<<73,110,32,109,111,115,116,32,117,115,101,32,99,97,115,101,115,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<105,111,100,97,116,97,40,41>>]},<<32,105,110,115,116,101,97,100,32,111,102,32,116,104,105,115,32,116,121,112,101,46>>]}]},#{signature => [{attribute,{94,2},type,{iolist,{type,{94,19},maybe_improper_list,[{type,{94,39},union,[{type,{94,39},byte,[]},{type,{94,48},binary,[]},{type,{94,59},iolist,[]}]},{type,{94,69},union,[{type,{94,69},binary,[]},{type,{94,80},nil,[]}]}]},[]}}]}},{{type,list,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,95}],[<<45,116,121,112,101,32,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<108,105,115,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,101,114,109,115,32,111,102,32,97,110,121,32,116,121,112,101,46>>]}]},#{signature => [{attribute,{95,2},type,{list,{type,{95,17},list,[]},[]}}]}},{{type,list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,96}],[<<45,116,121,112,101,32,108,105,115,116,40,65,114,103,49,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<108,105,115,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,101,114,109,115,32,111,102,32,116,104,101,32,116,121,112,101,32>>,{code,[],[<<67,111,110,116,101,110,116,84,121,112,101>>]},<<46>>]}]},#{signature => [{attribute,{96,2},type,{list,{type,{96,28},list,[{var,{96,33},'ContentType'}]},[{var,{96,12},'ContentType'}]}}]}},{{type,map,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,97}],[<<45,116,121,112,101,32,109,97,112,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,109,97,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<109,97,112>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,107,101,121,32,97,110,100,32,118,97,108,117,101,32,97,115,115,111,99,105,97,116,105,111,110,115,46>>]}]},#{signature => [{attribute,{97,2},type,{map,{type,{97,16},map,[{type,{97,25},map_field_assoc,[{type,{97,19},any,[]},{type,{97,28},any,[]}]}]},[]}}]}},{{type,maybe_improper_list,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,98}],[<<45,116,121,112,101,32,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<108,105,115,116>>]},<<32,116,104,97,116,32,105,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,101,110,100,32,119,105,116,104,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,110,105,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<91,93>>]},<<44,32,97,110,100,32,119,104,101,114,101,32,116,104,101,32,108,105,115,116,32,101,108,101,109,101,110,116,115,32,99,97,110,32,98,101,32,111,102,32,97,110,121,32,116,121,112,101,46>>]}]},#{signature => [{attribute,{98,2},type,{maybe_improper_list,{type,{98,32},maybe_improper_list,[{type,{98,52},any,[]},{type,{98,59},any,[]}]},[]}}]}},{{type,maybe_improper_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,99}],[<<45,116,121,112,101,32,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,65,114,103,49,44,65,114,103,50,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<108,105,115,116>>]},<<44,32,116,104,97,116,32,105,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,101,110,100,32,119,105,116,104,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,110,105,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<91,93>>]},<<44,32,97,110,100,32,119,104,101,114,101,32,116,104,101,32,108,105,115,116,32,101,108,101,109,101,110,116,115,32,97,114,101,32,111,102,32,116,104,101,32,116,121,112,101,32>>,{code,[],[<<67,111,110,116,101,110,116,84,121,112,101>>]},<<46>>]}]},#{signature => [{attribute,{99,2},type,{maybe_improper_list,{type,{99,60},maybe_improper_list,[{var,{99,80},'ContentType'},{var,{99,93},'TerminationType'}]},[{var,{99,27},'ContentType'},{var,{99,40},'TerminationType'}]}}]}},{{type,mfa,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,100}],[<<45,116,121,112,101,32,109,102,97,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,116,104,114,101,101,45,116,117,112,108,101,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32>>,{code,[],[<<77,111,100,117,108,101,58,70,117,110,99,116,105,111,110,47,65,114,105,116,121>>]},<<32,102,117,110,99,116,105,111,110,32,115,105,103,110,97,116,117,114,101,46>>]}]},#{signature => [{attribute,{100,2},type,{mfa,{type,{100,16},tuple,[{type,{100,17},module,[]},{type,{100,26},atom,[]},{type,{100,33},arity,[]}]},[]}}]}},{{type,module,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,101}],[<<45,116,121,112,101,32,109,111,100,117,108,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32,109,111,100,117,108,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,110,32,97,116,111,109,46>>]}]},#{signature => [{attribute,{101,2},type,{module,{type,{101,19},atom,[]},[]}}]}},{{type,neg_integer,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,102}],[<<45,116,121,112,101,32,110,101,103,95,105,110,116,101,103,101,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,46>>]}]},#{signature => [{attribute,{102,2},type,{neg_integer,{type,{102,24},neg_integer,[]},[]}}]}},{{type,nil,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,103}],[<<45,116,121,112,101,32,110,105,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,101,109,112,116,121,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<108,105,115,116,40,41>>]},<<46>>]}]},#{signature => [{attribute,{103,2},type,{nil,{type,{103,16},nil,[]},[]}}]}},{{type,no_return,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,104}],[<<45,116,121,112,101,32,110,111,95,114,101,116,117,114,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,116,121,112,101,32,117,115,101,100,32,116,111,32,115,104,111,119,32,116,104,97,116,32,97,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32>>,{em,[],[<<110,101,118,101,114>>]},<<32,114,101,116,117,114,110,32,97,32,118,97,108,117,101,44,32,116,104,97,116,32,105,115,32,105,116,32,119,105,108,108,32>>,{em,[],[<<97,108,119,97,121,115>>]},<<32,116,104,114,111,119,32,97,110,32,101,120,99,101,112,116,105,111,110,46>>]}]},#{signature => [{attribute,{104,2},type,{no_return,{type,{104,22},none,[]},[]}}]}},{{type,node,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,105}],[<<45,116,121,112,101,32,110,111,100,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,105,115,116,114,105,98,117,116,101,100,35,110,111,100,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,111,100,101>>]},<<32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,110,32,97,116,111,109,46>>]}]},#{signature => [{attribute,{105,2},type,{node,{type,{105,17},atom,[]},[]}}]}},{{type,non_neg_integer,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,106}],[<<45,116,121,112,101,32,110,111,110,95,110,101,103,95,105,110,116,101,103,101,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,110,111,110,45,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,44,32,116,104,97,116,32,105,115,32,97,110,121,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,32,111,114,32,48,46>>]}]},#{signature => [{attribute,{106,2},type,{non_neg_integer,{type,{106,28},non_neg_integer,[]},[]}}]}},{{type,none,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,107}],[<<45,116,121,112,101,32,110,111,110,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<84,104,105,115,32,116,121,112,101,32,105,115,32,117,115,101,100,32,116,111,32,115,104,111,119,32,116,104,97,116,32,97,32,102,117,110,99,116,105,111,110,32,119,105,108,108,32>>,{em,[],[<<110,101,118,101,114>>]},<<32,114,101,116,117,114,110,32,97,32,118,97,108,117,101,59,32,116,104,97,116,32,105,115,32,105,116,32,119,105,108,108,32>>,{em,[],[<<97,108,119,97,121,115>>]},<<32,116,104,114,111,119,32,97,110,32,101,120,99,101,112,116,105,111,110,46,32,73,110,32,97,32,115,112,101,99,44,32,117,115,101,32>>,{code,[],[<<110,111,95,114,101,116,117,114,110,40,41>>]},<<32,102,111,114,32,116,104,101,32,115,97,107,101,32,111,102,32,99,108,97,114,105,116,121,46>>]}]},#{signature => [{attribute,{107,2},type,{none,{type,{107,17},none,[]},[]}}]}},{{type,nonempty_binary,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,108}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,98,105,110,97,114,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,110,97,114,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<98,105,110,97,114,121,40,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,100,97,116,97,46>>]}]},#{signature => [{attribute,{108,2},type,{nonempty_binary,{type,{108,28},binary,[{integer,{108,32},8},{integer,{108,39},8}]},[]}}]}},{{type,nonempty_bitstring,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,109}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,98,105,116,115,116,114,105,110,103,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,98,105,116,115,116,114,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<98,105,116,115,116,114,105,110,103,40,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,100,97,116,97,46>>]}]},#{signature => [{attribute,{109,2},type,{nonempty_bitstring,{type,{109,31},binary,[{integer,{109,35},1},{integer,{109,42},1}]},[]}}]}},{{type,nonempty_improper_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,110}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,65,114,103,49,44,65,114,103,50,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,47,50>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,105,116,101,109,115,46>>]}]},#{signature => [{attribute,{110,2},type,{nonempty_improper_list,{type,{110,63},nonempty_improper_list,[{var,{110,86},'ContentType'},{var,{110,99},'TerminationType'}]},[{var,{110,30},'ContentType'},{var,{110,43},'TerminationType'}]}}]}},{{type,nonempty_list,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,111}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<108,105,115,116,40,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,105,116,101,109,115,46>>]}]},#{signature => [{attribute,{111,2},type,{nonempty_list,{type,{111,26},nonempty_list,[{type,{111,40},any,[]}]},[]}}]}},{{type,nonempty_list,1},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,112}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,108,105,115,116,40,65,114,103,49,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<108,105,115,116,40,67,111,110,116,101,110,116,84,121,112,101,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,105,116,101,109,115,46>>]}]},#{signature => [{attribute,{112,2},type,{nonempty_list,{type,{112,37},nonempty_list,[{var,{112,38},'ContentType'}]},[{var,{112,21},'ContentType'}]}}]}},{{type,nonempty_maybe_improper_list,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,113}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,105,116,101,109,115,46>>]}]},#{signature => [{attribute,{113,2},type,{nonempty_maybe_improper_list,{type,{113,41},nonempty_maybe_improper_list,[{type,{113,70},any,[]},{type,{113,77},any,[]}]},[]}}]}},{{type,nonempty_maybe_improper_list,2},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,114}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,65,114,103,49,44,65,114,103,50,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<109,97,121,98,101,95,105,109,112,114,111,112,101,114,95,108,105,115,116,40,67,111,110,116,101,110,116,84,121,112,101,44,32,84,101,114,109,105,110,97,116,105,111,110,84,121,112,101,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,105,116,101,109,115,46>>]}]},#{signature => [{attribute,{114,2},type,{nonempty_maybe_improper_list,{type,{114,69},nonempty_maybe_improper_list,[{var,{114,98},'ContentType'},{var,{114,111},'TerminationType'}]},[{var,{114,36},'ContentType'},{var,{114,49},'TerminationType'}]}}]}},{{type,nonempty_string,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,115}],[<<45,116,121,112,101,32,110,111,110,101,109,112,116,121,95,115,116,114,105,110,103,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,116,114,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<115,116,114,105,110,103,40,41>>]},<<32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},#{signature => [{attribute,{115,2},type,{nonempty_string,{type,{115,28},nonempty_list,[{type,{115,42},char,[]}]},[]}}]}},{{type,number,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,116}],[<<45,116,121,112,101,32,110,117,109,98,101,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,110,117,109,98,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<110,117,109,98,101,114>>]},<<46>>]}]},#{signature => [{attribute,{116,2},type,{number,{type,{116,19},union,[{type,{116,19},integer,[]},{type,{116,31},float,[]}]},[]}}]}},{{type,pid,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,117}],[<<45,116,121,112,101,32,112,105,100,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,112,105,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,111,99,101,115,115,32,105,100,101,110,116,105,102,105,101,114>>]},<<46>>]}]},#{signature => [{attribute,{117,2},type,{pid,{type,{117,16},pid,[]},[]}}]}},{{type,port,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,118}],[<<45,116,121,112,101,32,112,111,114,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,112,111,114,116,45,105,100,101,110,116,105,102,105,101,114>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,111,114,116,32,105,100,101,110,116,105,102,105,101,114>>]},<<46>>]}]},#{signature => [{attribute,{118,2},type,{port,{type,{118,17},port,[]},[]}}]}},{{type,pos_integer,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,119}],[<<45,116,121,112,101,32,112,111,115,95,105,110,116,101,103,101,114,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,105,110,116,101,103,101,114,32,103,114,101,97,116,101,114,32,116,104,97,110,32,122,101,114,111,46>>]}]},#{signature => [{attribute,{119,2},type,{pos_integer,{type,{119,24},pos_integer,[]},[]}}]}},{{type,reference,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,120}],[<<45,116,121,112,101,32,114,101,102,101,114,101,110,99,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,114,101,102,101,114,101,110,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,102,101,114,101,110,99,101>>]},<<46>>]}]},#{signature => [{attribute,{120,2},type,{reference,{type,{120,22},reference,[]},[]}}]}},{{type,string,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,121}],[<<45,116,121,112,101,32,115,116,114,105,110,103,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,108,105,115,116,32,111,102,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,111,114,32,117,110,105,99,111,100,101,32,99,111,100,101,112,111,105,110,116,115,46>>]}]},#{signature => [{attribute,{121,2},type,{string,{type,{121,19},list,[{type,{121,20},char,[]}]},[]}}]}},{{type,term,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,122}],[<<45,116,121,112,101,32,116,101,114,109,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,108,108,32,112,111,115,115,105,98,108,101,32,69,114,108,97,110,103,32,116,101,114,109,115,46,32,83,121,110,111,110,121,109,32,102,111,114,32>>,{code,[],[<<97,110,121,40,41>>]},<<46>>]}]},#{signature => [{attribute,{122,2},type,{term,{type,{122,17},any,[]},[]}}]}},{{type,timeout,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,123}],[<<45,116,121,112,101,32,116,105,109,101,111,117,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,116,105,109,101,111,117,116,32,118,97,108,117,101,32,116,104,97,116,32,99,97,110,32,98,101,32,112,97,115,115,101,100,32,116,111,32,97,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,120,112,114,101,115,115,105,111,110,115,35,114,101,99,101,105,118,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,99,101,105,118,101,32,101,120,112,114,101,115,115,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,{123,2},type,{timeout,{type,{123,20},union,[{atom,{123,20},infinity},{type,{123,33},non_neg_integer,[]}]},[]}}]}},{{type,tuple,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,124}],[<<45,116,121,112,101,32,116,117,112,108,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,100,97,116,97,95,116,121,112,101,115,35,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<116,117,112,108,101>>]},<<46>>]}]},#{signature => [{attribute,{124,2},type,{tuple,{type,{124,18},tuple,any},[]}}]}},{{type,ext_binary,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,155}],[<<45,116,121,112,101,32,101,120,116,95,98,105,110,97,114,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,44,32,115,116,114,117,99,116,117,114,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]}]},#{signature => [{attribute,{155,2},type,{ext_binary,{type,{155,23},binary,[]},[]}}]}},{{type,ext_iovec,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,156}],[<<45,116,121,112,101,32,101,120,116,95,105,111,118,101,99,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,116,101,114,109,32,111,102,32,116,121,112,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<105,111,118,101,99,40,41>>]}]},<<44,32,115,116,114,117,99,116,117,114,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,101,120,116,101,114,110,97,108,32,116,101,114,109,32,102,111,114,109,97,116,46>>]}]},#{signature => [{attribute,{156,2},type,{ext_iovec,{user_type,{156,22},iovec,[]},[]}}]}},{{type,iovec,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,187}],[<<45,116,121,112,101,32,105,111,118,101,99,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32,108,105,115,116,32,111,102,32,98,105,110,97,114,105,101,115,46,32,84,104,105,115,32,100,97,116,97,116,121,112,101,32,105,115,32,117,115,101,102,117,108,32,116,111,32,117,115,101,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,110,105,102,35,101,110,105,102,95,105,110,115,112,101,99,116,95,105,111,118,101,99>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[{code,[],[<<101,110,105,102,95,105,110,115,112,101,99,116,95,105,111,118,101,99>>]}]},<<46>>]}]},#{signature => [{attribute,{187,2},type,{iovec,{type,{187,18},list,[{type,{187,19},binary,[]}]},[]}}]}},{{type,message_queue_data,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2416}],[<<45,116,121,112,101,32,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]},<<46>>]}]},#{signature => [{attribute,{2416,2},type,{message_queue_data,{type,{2417,2},union,[{atom,{2417,2},off_heap},{atom,{2417,13},on_heap}]},[]}}]}},{{type,monitor_option,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,1460}],[<<45,116,121,112,101,32,109,111,110,105,116,111,114,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,109,111,110,105,116,111,114,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<109,111,110,105,116,111,114,47,51>>]}]},<<46>>]}]},#{signature => [{attribute,{1460,2},type,{monitor_option,{type,{1460,27},union,[{type,{1460,27},tuple,[{atom,{1460,28},alias},{type,{1460,37},union,[{atom,{1460,37},explicit_unalias},{atom,{1460,58},demonitor},{atom,{1460,72},reply_demonitor}]}]},{type,{1461,27},tuple,[{atom,{1461,28},tag},{type,{1461,35},term,[]}]}]},[]}}]}},{{type,timestamp,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,157}],[<<45,116,121,112,101,32,116,105,109,101,115,116,97,109,112,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,105,109,101,115,116,97,109,112,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,116,105,109,101,115,116,97,109,112,47,48>>]}]},<<46>>]}]},#{signature => [{attribute,{157,2},type,{timestamp,{type,{157,22},tuple,[{ann_type,{157,23},[{var,{157,23},'MegaSecs'},{type,{157,35},non_neg_integer,[]}]},{ann_type,{158,23},[{var,{158,23},'Secs'},{type,{158,31},non_neg_integer,[]}]},{ann_type,{159,23},[{var,{159,23},'MicroSecs'},{type,{159,36},non_neg_integer,[]}]}]},[]}}]}},{{type,time_unit,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,161}],[<<45,116,121,112,101,32,116,105,109,101,95,117,110,105,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{a,[{id,<<116,121,112,101,95,116,105,109,101,95,117,110,105,116>>}],[]},{p,[],[<<83,117,112,112,111,114,116,101,100,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<80,97,114,116,115,80,101,114,83,101,99,111,110,100,32,58,58,32,105,110,116,101,103,101,114,40,41,32,62,61,32,49>>]}]},{dd,[],[{p,[],[<<84,105,109,101,32,117,110,105,116,32,101,120,112,114,101,115,115,101,100,32,105,110,32,112,97,114,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,101,113,117,97,108,115,32>>,{code,[],[<<49,47,80,97,114,116,115,80,101,114,83,101,99,111,110,100>>]},<<32,115,101,99,111,110,100,46>>]}]},{dt,[],[{code,[],[<<115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,108,108,105,115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49,48,48,48>>]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,99,114,111,115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49,48,48,48,95,48,48,48>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,97,110,111,115,101,99,111,110,100>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,116,105,109,101,32,117,110,105,116,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,116,104,101,32,105,110,116,101,103,101,114,32>>,{code,[],[<<49,48,48,48,95,48,48,48,95,48,48,48>>]},<<46>>]}]},{dt,[],[{code,[],[<<110,97,116,105,118,101>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,110,97,116,105,118,101,32,116,105,109,101,32,117,110,105,116,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,105,115,32,100,101,116,101,114,109,105,110,101,100,32,97,116,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,115,116,97,114,116,44,32,97,110,100,32,114,101,109,97,105,110,115,32,116,104,101,32,115,97,109,101,32,117,110,116,105,108,32,116,104,101,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,116,101,114,109,105,110,97,116,101,115,46,32,73,102,32,97,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,115,32,115,116,111,112,112,101,100,32,97,110,100,32,116,104,101,110,32,115,116,97,114,116,101,100,32,97,103,97,105,110,32,40,101,118,101,110,32,111,110,32,116,104,101,32,115,97,109,101,32,109,97,99,104,105,110,101,41,44,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,111,102,32,116,104,101,32,110,101,119,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,32,99,97,110,32,100,105,102,102,101,114,32,102,114,111,109,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,111,102,32,116,104,101,32,111,108,100,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,32,105,110,115,116,97,110,99,101,46>>]},{p,[],[<<79,110,101,32,99,97,110,32,103,101,116,32,97,110,32,97,112,112,114,111,120,105,109,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,98,121,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,40,49,44,32,115,101,99,111,110,100,44,32,110,97,116,105,118,101,41>>]}]},<<46,32,84,104,101,32,114,101,115,117,108,116,32,101,113,117,97,108,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,119,104,111,108,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,115,32,112,101,114,32,115,101,99,111,110,100,46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,115,32,112,101,114,32,115,101,99,111,110,100,32,100,111,101,115,32,110,111,116,32,97,100,100,32,117,112,32,116,111,32,97,32,119,104,111,108,101,32,110,117,109,98,101,114,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,114,111,117,110,100,101,100,32,100,111,119,110,119,97,114,100,115,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,103,105,118,101,115,32,121,111,117,32,109,111,114,101,32,111,114,32,108,101,115,115,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,113,117,97,108,105,116,121,32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,46,32,73,116,32,115,101,116,115,32,97,32,108,105,109,105,116,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,82,101,115,111,108,117,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<114,101,115,111,108,117,116,105,111,110>>]},<<32,97,110,100,32,102,111,114,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,80,114,101,99,105,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<112,114,101,99,105,115,105,111,110>>]},<<32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,44,32,98,117,116,32,105,116,32,103,105,118,101,115,32,110,111,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32>>,{a,[{href,<<101,114,116,115,58,116,105,109,101,95,99,111,114,114,101,99,116,105,111,110,35,84,105,109,101,95,65,99,99,117,114,97,99,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<97,99,99,117,114,97,99,121>>]},<<32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,46,32,84,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,32,97,110,100,32,116,104,101,32,114,101,115,111,108,117,116,105,111,110,32,111,102,32,116,105,109,101,32,118,97,108,117,101,115,32,99,97,110,32,100,105,102,102,101,114,32,115,105,103,110,105,102,105,99,97,110,116,108,121,46>>]}]}]},{dt,[],[{code,[],[<<112,101,114,102,95,99,111,117,110,116,101,114>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,112,101,114,102,111,114,109,97,110,99,101,32,99,111,117,110,116,101,114,32,116,105,109,101,32,117,110,105,116,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<112,101,114,102,95,99,111,117,110,116,101,114>>]},<<32,116,105,109,101,32,117,110,105,116,32,98,101,104,97,118,101,115,32,109,117,99,104,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,116,104,101,32>>,{code,[],[<<110,97,116,105,118,101>>]},<<32,116,105,109,101,32,117,110,105,116,46,32,84,104,97,116,32,105,115,44,32,105,116,32,99,97,110,32,100,105,102,102,101,114,32,98,101,116,119,101,101,110,32,114,117,110,116,105,109,101,32,114,101,115,116,97,114,116,115,46,32,84,111,32,103,101,116,32,118,97,108,117,101,115,32,111,102,32,116,104,105,115,32,116,121,112,101,44,32,99,97,108,108,32>>,{a,[{href,<<107,101,114,110,101,108,58,111,115,35,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,115,58,112,101,114,102,95,99,111,117,110,116,101,114,47,48>>]}]},<<46>>]}]},{dt,[],[{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116,40,41>>]}]}]},{dd,[],[{p,[],[<<68,101,112,114,101,99,97,116,101,100,32,115,121,109,98,111,108,105,99,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,115,32,107,101,112,116,32,102,111,114,32,98,97,99,107,119,97,114,100,115,45,99,111,109,112,97,116,105,98,105,108,105,116,121,46>>]}]}]},{p,[],[<<84,104,101,32>>,{code,[],[<<116,105,109,101,95,117,110,105,116,47,48>>]},<<32,116,121,112,101,32,99,97,110,32,98,101,32,101,120,116,101,110,100,101,100,46,32,84,111,32,99,111,110,118,101,114,116,32,116,105,109,101,32,118,97,108,117,101,115,32,98,101,116,119,101,101,110,32,116,105,109,101,32,117,110,105,116,115,44,32,117,115,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,99,111,110,118,101,114,116,95,116,105,109,101,95,117,110,105,116,47,51>>]}]},<<46>>]}]},#{signature => [{attribute,{161,2},type,{time_unit,{type,{162,2},union,[{type,{162,2},pos_integer,[]},{atom,{163,9},second},{atom,{164,9},millisecond},{atom,{165,9},microsecond},{atom,{166,9},nanosecond},{atom,{167,9},native},{atom,{168,9},perf_counter},{user_type,{169,9},deprecated_time_unit,[]}]},[]}}]}},{{type,deprecated_time_unit,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,172}],[<<45,116,121,112,101,32,100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{a,[{id,<<116,121,112,101,95,100,101,112,114,101,99,97,116,101,100,95,116,105,109,101,95,117,110,105,116>>}],[]},{p,[],[<<84,104,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<116,105,109,101,95,117,110,105,116,40,41>>]}]},<<32,116,121,112,101,32,97,108,115,111,32,99,111,110,115,105,115,116,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32>>,{em,[],[<<100,101,112,114,101,99,97,116,101,100>>]},<<32,115,121,109,98,111,108,105,99,32,116,105,109,101,32,117,110,105,116,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,99,111,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,108,108,105,95,115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,108,108,105,115,101,99,111,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<109,105,99,114,111,95,115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<109,105,99,114,111,115,101,99,111,110,100>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<110,97,110,111,95,115,101,99,111,110,100,115>>]}]},{dd,[],[{p,[],[<<83,97,109,101,32,97,115,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,116,121,112,101,95,116,105,109,101,95,117,110,105,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<110,97,110,111,115,101,99,111,110,100>>]}]},<<46>>]}]}]}]},#{signature => [{attribute,{172,2},type,{deprecated_time_unit,{type,{173,7},union,[{atom,{173,7},seconds},{atom,{174,9},milli_seconds},{atom,{175,9},micro_seconds},{atom,{176,9},nano_seconds}]},[]}}]}},{{type,dist_handle,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,184}],[<<45,116,121,112,101,32,100,105,115,116,95,104,97,110,100,108,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,111,112,97,113,117,101,32,104,97,110,100,108,101,32,105,100,101,110,116,105,102,121,105,110,103,32,97,32,100,105,115,116,114,105,98,117,116,105,111,110,32,99,104,97,110,110,101,108,46>>]}]},#{signature => [{attribute,{184,2},opaque,{dist_handle,{type,{184,26},atom,[]},[]}}]}},{{type,nif_resource,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,181}],[<<45,116,121,112,101,32,110,105,102,95,114,101,115,111,117,114,99,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,111,112,97,113,117,101,32,104,97,110,100,108,101,32,105,100,101,110,116,105,102,121,105,110,103,32,97,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,95,110,105,102,35,114,101,115,111,117,114,99,101,95,111,98,106,101,99,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,114,101,102>>}],[<<78,73,70,32,114,101,115,111,117,114,99,101,32,111,98,106,101,99,116,32>>]},<<46>>]}]},#{signature => [{attribute,{181,2},opaque,{nif_resource,{type,{181,27},reference,[]},[]}}]}},{{type,spawn_opt_option,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3056}],[<<45,116,121,112,101,32,115,112,97,119,110,95,111,112,116,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<79,112,116,105,111,110,115,32,102,111,114,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,115,112,97,119,110,95,111,112,116,47,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,112,97,119,110,95,111,112,116,40,41>>]}]},<<46>>]}]},#{signature => [{attribute,{3056,2},type,{spawn_opt_option,{type,{3057,2},union,[{atom,{3057,2},link},{atom,{3058,9},monitor},{type,{3059,9},tuple,[{atom,{3059,10},monitor},{ann_type,{3059,19},[{var,{3059,19},'MonitorOpts'},{type,{3059,34},list,[{user_type,{3059,35},monitor_option,[]}]}]}]},{type,{3060,9},tuple,[{atom,{3060,10},priority},{ann_type,{3060,20},[{var,{3060,20},'Level'},{user_type,{3060,29},priority_level,[]}]}]},{type,{3061,9},tuple,[{atom,{3061,10},fullsweep_after},{ann_type,{3061,27},[{var,{3061,27},'Number'},{type,{3061,37},non_neg_integer,[]}]}]},{type,{3062,9},tuple,[{atom,{3062,10},min_heap_size},{ann_type,{3062,25},[{var,{3062,25},'Size'},{type,{3062,33},non_neg_integer,[]}]}]},{type,{3063,9},tuple,[{atom,{3063,10},min_bin_vheap_size},{ann_type,{3063,30},[{var,{3063,30},'VSize'},{type,{3063,39},non_neg_integer,[]}]}]},{type,{3064,9},tuple,[{atom,{3064,10},max_heap_size},{ann_type,{3064,25},[{var,{3064,25},'Size'},{user_type,{3064,33},max_heap_size,[]}]}]},{type,{3065,9},tuple,[{atom,{3065,10},message_queue_data},{ann_type,{3065,30},[{var,{3065,30},'MQD'},{user_type,{3065,37},message_queue_data,[]}]}]}]},[]}}]}},{{type,priority_level,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2413}],[<<45,116,121,112,101,32,112,114,105,111,114,105,116,121,95,108,101,118,101,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<80,114,111,99,101,115,115,32,112,114,105,111,114,105,116,121,32,108,101,118,101,108,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,112,114,105,111,114,105,116,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,112,114,105,111,114,105,116,121,44,32,76,101,118,101,108,41>>]}]}]}]},#{signature => [{attribute,{2413,2},type,{priority_level,{type,{2414,7},union,[{atom,{2414,7},low},{atom,{2414,13},normal},{atom,{2414,22},high},{atom,{2414,29},max}]},[]}}]}},{{type,max_heap_size,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,3049}],[<<45,116,121,112,101,32,109,97,120,95,104,101,97,112,95,115,105,122,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<80,114,111,99,101,115,115,32,109,97,120,32,104,101,97,112,32,115,105,122,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,97,120,95,104,101,97,112,95,115,105,122,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,97,120,95,104,101,97,112,95,115,105,122,101,44,32,77,97,120,72,101,97,112,83,105,122,101,41>>]}]}]}]},#{signature => [{attribute,{3049,2},type,{max_heap_size,{ann_type,{3050,9},[{var,{3050,9},'Size'},{type,{3050,17},union,[{type,{3050,17},non_neg_integer,[]},{type,{3052,9},map,[{type,{3052,17},map_field_assoc,[{atom,{3052,12},size},{type,{3052,20},non_neg_integer,[]}]},{type,{3053,17},map_field_assoc,[{atom,{3053,12},kill},{type,{3053,20},boolean,[]}]},{type,{3054,25},map_field_assoc,[{atom,{3054,12},error_logger},{type,{3054,28},boolean,[]}]}]}]}]},[]}}]}},{{type,message_queue_data,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,2416}],[<<45,116,121,112,101,32,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<80,114,111,99,101,115,115,32,109,101,115,115,97,103,101,32,113,117,101,117,101,32,100,97,116,97,32,99,111,110,102,105,103,117,114,97,116,105,111,110,46,32,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,115,101,101,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,112,114,111,99,101,115,115,95,102,108,97,103,95,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<112,114,111,99,101,115,115,95,102,108,97,103,40,109,101,115,115,97,103,101,95,113,117,101,117,101,95,100,97,116,97,44,32,77,81,68,41>>]}]}]}]},#{signature => [{attribute,{2416,2},type,{message_queue_data,{type,{2417,2},union,[{atom,{2417,2},off_heap},{atom,{2417,13},on_heap}]},[]}}]}},{{type,stacktrace_extrainfo,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,146}],[<<45,116,121,112,101,32,115,116,97,99,107,116,114,97,99,101,95,101,120,116,114,97,105,110,102,111,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32,115,116,97,99,107,116,114,97,99,101,32,97,115,32,100,101,115,99,114,105,98,101,100,32,98,121,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115,35,115,116,97,99,107,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,114,111,114,115,32,97,110,100,32,69,114,114,111,114,32,72,97,110,100,108,105,110,103>>]},<<32,115,101,99,116,105,111,110,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,46>>]}]},#{signature => [{attribute,{146,2},type,{stacktrace_extrainfo,{type,{147,9},union,[{type,{147,9},tuple,[{atom,{147,10},line},{type,{147,16},pos_integer,[]}]},{type,{148,9},tuple,[{atom,{148,10},file},{remote_type,{148,16},[{atom,{148,16},unicode},{atom,{148,24},chardata},[]]}]},{type,{149,9},tuple,[{atom,{149,10},error_info},{type,{149,22},map,[{type,{149,32},map_field_assoc,[{atom,{149,25},module},{type,{149,35},module,[]}]},{type,{149,54},map_field_assoc,[{atom,{149,45},function},{type,{149,57},atom,[]}]},{type,{149,71},map_field_assoc,[{atom,{149,65},cause},{type,{149,74},term,[]}]}]}]},{type,{150,9},tuple,[{type,{150,10},atom,[]},{type,{150,18},term,[]}]}]},[]}}]}},{{type,stacktrace,0},[{file,[101,114,108,97,110,103,46,101,114,108]},{location,151}],[<<45,116,121,112,101,32,115,116,97,99,107,116,114,97,99,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,69,114,108,97,110,103,32,115,116,97,99,107,116,114,97,99,101,32,97,115,32,100,101,115,99,114,105,98,101,100,32,98,121,32>>,{a,[{href,<<115,121,115,116,101,109,47,114,101,102,101,114,101,110,99,101,95,109,97,110,117,97,108,58,101,114,114,111,114,115,35,115,116,97,99,107,116,114,97,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<69,114,114,111,114,115,32,97,110,100,32,69,114,114,111,114,32,72,97,110,100,108,105,110,103>>]},<<32,115,101,99,116,105,111,110,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,82,101,102,101,114,101,110,99,101,32,77,97,110,117,97,108,46>>]}]},#{signature => [{attribute,{151,2},type,{stacktrace,{type,{151,23},list,[{type,{151,24},union,[{type,{151,24},tuple,[{type,{151,25},module,[]},{type,{151,35},atom,[]},{type,{151,43},union,[{type,{151,43},arity,[]},{type,{151,53},list,[{type,{151,54},term,[]}]}]},{type,{152,25},list,[{user_type,{152,26},stacktrace_extrainfo,[]}]}]},{type,{153,24},tuple,[{type,{153,25},function,[]},{type,{153,37},union,[{type,{153,37},arity,[]},{type,{153,47},list,[{type,{153,48},term,[]}]}]},{type,{153,57},list,[{user_type,{153,58},stacktrace_extrainfo,[]}]}]}]}]},[]}}]}}]}. \ No newline at end of file
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/file.docs_v1 b/lib/stdlib/test/shell_docs_SUITE_data/file.docs_v1
index 9c88ce7723..227f99dfaa 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/file.docs_v1
+++ b/lib/stdlib/test/shell_docs_SUITE_data/file.docs_v1
@@ -1 +1 @@
-{docs_v1,[{file,[102,105,108,101,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<84,104,105,115,32,109,111,100,117,108,101,32,112,114,111,118,105,100,101,115,32,97,110,32,105,110,116,101,114,102,97,99,101,32,116,111,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<70,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,97,114,101,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,97,112,112,101,97,114,32,97,116,111,109,105,99,32,119,104,101,110,32,103,111,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,32,115,97,109,101,32,102,105,108,101,32,115,101,114,118,101,114,46,32,65,32,78,73,70,32,111,114,32,111,116,104,101,114,32,79,83,32,112,114,111,99,101,115,115,32,109,97,121,32,111,98,115,101,114,118,101,32,105,110,116,101,114,109,101,100,105,97,116,101,32,115,116,101,112,115,32,111,110,32,99,101,114,116,97,105,110,32,111,112,101,114,97,116,105,111,110,115,32,111,110,32,115,111,109,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,115,44,32,101,103,46,32,114,101,110,97,109,105,110,103,32,97,110,32,101,120,105,115,116,105,110,103,32,102,105,108,101,32,111,110,32,87,105,110,100,111,119,115,44,32,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]},<<32>>]},<<111,110,32,97,110,121,32,79,83,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,119,114,105,116,105,110,103,46>>]}]},{p,[],[<<82,101,103,97,114,100,105,110,103,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,44,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,99,97,110,32,111,112,101,114,97,116,101,32,105,110,32,116,119,111,32,109,111,100,101,115,46,32,84,104,101,32,99,117,114,114,101,110,116,32,109,111,100,101,32,99,97,110,32,98,101,32,113,117,101,114,105,101,100,32,117,115,105,110,103,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>]}]},<<46,32,73,116,32,114,101,116,117,114,110,115,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,111,114,32>>,{code,[],[<<117,116,102,56>>]},<<46>>]},{p,[],[<<73,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,109,111,100,101,44,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,100,111,101,115,32,110,111,116,32,99,104,97,110,103,101,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32,102,105,108,101,110,97,109,101,115,46,32,73,110,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,44,32,102,105,108,101,110,97,109,101,115,32,99,97,110,32,99,111,110,116,97,105,110,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,103,114,101,97,116,101,114,32,116,104,97,110,32,50,53,53,32,97,110,100,32,116,104,101,32,86,77,32,99,111,110,118,101,114,116,115,32,102,105,108,101,110,97,109,101,115,32,98,97,99,107,32,97,110,100,32,102,111,114,116,104,32,116,111,32,116,104,101,32,110,97,116,105,118,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,40,117,115,117,97,108,108,121,32,85,84,70,45,56,44,32,98,117,116,32,85,84,70,45,49,54,32,111,110,32,87,105,110,100,111,119,115,41,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,109,111,100,101,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,46,32,87,105,110,100,111,119,115,44,32,77,97,99,79,83,32,88,32,97,110,100,32,65,110,100,114,111,105,100,32,101,110,102,111,114,99,101,32,99,111,110,115,105,115,116,101,110,116,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,97,110,100,32,116,104,101,114,101,102,111,114,101,32,116,104,101,32,86,77,32,117,115,101,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,46>>]},{p,[],[<<79,110,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,115,32,119,105,116,104,32,116,114,97,110,115,112,97,114,101,110,116,32,110,97,109,105,110,103,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,108,108,32,85,110,105,120,32,115,121,115,116,101,109,115,32,101,120,99,101,112,116,32,77,97,99,79,83,32,88,41,44,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,105,102,32,116,104,101,32,116,101,114,109,105,110,97,108,32,115,117,112,112,111,114,116,115,32,85,84,70,45,56,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,99,97,110,32,98,101,32,111,118,101,114,114,105,100,100,101,110,32,117,115,105,110,103,32>>,{code,[],[<<43,102,110,108>>]},<<32,40,116,111,32,102,111,114,99,101,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,109,111,100,101,41,32,111,114,32>>,{code,[],[<<43,102,110,117>>]},<<32,40,116,111,32,102,111,114,99,101,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,41,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,101,114,116,115,58,101,114,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<101,114,108>>]}]},<<46>>]},{p,[],[<<79,110,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,115,32,119,105,116,104,32,116,114,97,110,115,112,97,114,101,110,116,32,110,97,109,105,110,103,44,32,102,105,108,101,115,32,99,97,110,32,98,101,32,105,110,99,111,110,115,105,115,116,101,110,116,108,121,32,110,97,109,101,100,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,115,111,109,101,32,102,105,108,101,115,32,97,114,101,32,101,110,99,111,100,101,100,32,105,110,32,85,84,70,45,56,32,119,104,105,108,101,32,111,116,104,101,114,115,32,97,114,101,32,101,110,99,111,100,101,100,32,105,110,32,73,83,79,32,76,97,116,105,110,45,49,46,32,84,104,101,32,99,111,110,99,101,112,116,32,111,102,32>>,{em,[],[<<114,97,119,32,102,105,108,101,110,97,109,101,115>>]},<<32,105,115,32,105,110,116,114,111,100,117,99,101,100,32,116,111,32,104,97,110,100,108,101,32,102,105,108,101,32,115,121,115,116,101,109,115,32,119,105,116,104,32,105,110,99,111,110,115,105,115,116,101,110,116,32,110,97,109,105,110,103,32,119,104,101,110,32,114,117,110,110,105,110,103,32,105,110,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,46>>]},{p,[],[<<65,32>>,{em,[],[<<114,97,119,32,102,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,32,102,105,108,101,110,97,109,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,105,110,97,114,121,46,32,84,104,101,32,69,114,108,97,110,103,32,86,77,32,100,111,101,115,32,110,111,116,32,116,114,97,110,115,108,97,116,101,32,97,32,102,105,108,101,110,97,109,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,105,110,97,114,121,32,111,110,32,115,121,115,116,101,109,115,32,119,105,116,104,32,116,114,97,110,115,112,97,114,101,110,116,32,110,97,109,105,110,103,46>>]},{p,[],[<<87,104,101,110,32,114,117,110,110,105,110,103,32,105,110,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,44,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,108,105,115,116,95,100,105,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,100,105,114,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,107,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,108,105,110,107,47,49>>]}]},<<32,110,101,118,101,114,32,114,101,116,117,114,110,32,114,97,119,32,102,105,108,101,110,97,109,101,115,46,32,84,111,32,114,101,116,117,114,110,32,97,108,108,32,102,105,108,101,110,97,109,101,115,32,105,110,99,108,117,100,105,110,103,32,114,97,119,32,102,105,108,101,110,97,109,101,115,44,32,117,115,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,108,105,115,116,95,100,105,114,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,105,115,116,95,100,105,114,95,97,108,108,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,107,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,97,100,95,108,105,110,107,95,97,108,108,47,49>>]}]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,95,117,115,97,103,101,35,110,111,116,101,115,45,97,98,111,117,116,45,114,97,119,45,102,105,108,101,110,97,109,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<78,111,116,101,115,32,65,98,111,117,116,32,82,97,119,32,70,105,108,101,110,97,109,101,115>>]},<<32,105,110,32,116,104,101,32,83,84,68,76,73,66,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<70,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,117,115,101,100,32,116,111,32,97,99,99,101,112,116,32,102,105,108,101,110,97,109,101,115,32,99,111,110,116,97,105,110,105,110,103,32,110,117,108,108,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,116,101,103,101,114,32,118,97,108,117,101,32,122,101,114,111,41,46,32,84,104,105,115,32,99,97,117,115,101,100,32,116,104,101,32,110,97,109,101,32,116,111,32,98,101,32,116,114,117,110,99,97,116,101,100,32,97,110,100,32,105,110,32,115,111,109,101,32,99,97,115,101,115,32,97,114,103,117,109,101,110,116,115,32,116,111,32,112,114,105,109,105,116,105,118,101,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,98,101,32,109,105,120,101,100,32,117,112,46,32,70,105,108,101,110,97,109,101,115,32,99,111,110,116,97,105,110,105,110,103,32,110,117,108,108,32,99,104,97,114,97,99,116,101,114,115,32,105,110,115,105,100,101,32,116,104,101,32,102,105,108,101,110,97,109,101,32,97,114,101,32,110,111,119,32>>,{em,[],[<<114,101,106,101,99,116,101,100>>]},<<32,97,110,100,32,119,105,108,108,32,99,97,117,115,101,32,112,114,105,109,105,116,105,118,101,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,102,97,105,108,46>>]}]},{h2,[],[<<80,79,83,73,88,32,69,114,114,111,114,32,67,111,100,101,115>>]},{ul,[],[{li,[],[{code,[],[<<101,97,99,99,101,115>>]},<<32,45,32,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100>>]},{li,[],[{code,[],[<<101,97,103,97,105,110>>]},<<32,45,32,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101>>]},{li,[],[{code,[],[<<101,98,97,100,102>>]},<<32,45,32,66,97,100,32,102,105,108,101,32,110,117,109,98,101,114>>]},{li,[],[{code,[],[<<101,98,117,115,121>>]},<<32,45,32,70,105,108,101,32,98,117,115,121>>]},{li,[],[{code,[],[<<101,100,113,117,111,116>>]},<<32,45,32,68,105,115,107,32,113,117,111,116,97,32,101,120,99,101,101,100,101,100>>]},{li,[],[{code,[],[<<101,101,120,105,115,116>>]},<<32,45,32,70,105,108,101,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115>>]},{li,[],[{code,[],[<<101,102,97,117,108,116>>]},<<32,45,32,66,97,100,32,97,100,100,114,101,115,115,32,105,110,32,115,121,115,116,101,109,32,99,97,108,108,32,97,114,103,117,109,101,110,116>>]},{li,[],[{code,[],[<<101,102,98,105,103>>]},<<32,45,32,70,105,108,101,32,116,111,111,32,108,97,114,103,101>>]},{li,[],[{code,[],[<<101,105,110,116,114>>]},<<32,45,32,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108>>]},{li,[],[{code,[],[<<101,105,110,118,97,108>>]},<<32,45,32,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116>>]},{li,[],[{code,[],[<<101,105,111>>]},<<32,45,32,73,47,79,32,101,114,114,111,114>>]},{li,[],[{code,[],[<<101,105,115,100,105,114>>]},<<32,45,32,73,108,108,101,103,97,108,32,111,112,101,114,97,116,105,111,110,32,111,110,32,97,32,100,105,114,101,99,116,111,114,121>>]},{li,[],[{code,[],[<<101,108,111,111,112>>]},<<32,45,32,84,111,111,32,109,97,110,121,32,108,101,118,101,108,115,32,111,102,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115>>]},{li,[],[{code,[],[<<101,109,102,105,108,101>>]},<<32,45,32,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115>>]},{li,[],[{code,[],[<<101,109,108,105,110,107>>]},<<32,45,32,84,111,111,32,109,97,110,121,32,108,105,110,107,115>>]},{li,[],[{code,[],[<<101,110,97,109,101,116,111,111,108,111,110,103>>]},<<32,45,32,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103>>]},{li,[],[{code,[],[<<101,110,102,105,108,101>>]},<<32,45,32,70,105,108,101,32,116,97,98,108,101,32,111,118,101,114,102,108,111,119>>]},{li,[],[{code,[],[<<101,110,111,100,101,118>>]},<<32,45,32,78,111,32,115,117,99,104,32,100,101,118,105,99,101>>]},{li,[],[{code,[],[<<101,110,111,101,110,116>>]},<<32,45,32,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121>>]},{li,[],[{code,[],[<<101,110,111,109,101,109>>]},<<32,45,32,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121>>]},{li,[],[{code,[],[<<101,110,111,115,112,99>>]},<<32,45,32,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101>>]},{li,[],[{code,[],[<<101,110,111,116,98,108,107>>]},<<32,45,32,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100>>]},{li,[],[{code,[],[<<101,110,111,116,100,105,114>>]},<<32,45,32,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121>>]},{li,[],[{code,[],[<<101,110,111,116,115,117,112>>]},<<32,45,32,79,112,101,114,97,116,105,111,110,32,110,111,116,32,115,117,112,112,111,114,116,101,100>>]},{li,[],[{code,[],[<<101,110,120,105,111>>]},<<32,45,32,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115>>]},{li,[],[{code,[],[<<101,112,101,114,109>>]},<<32,45,32,78,111,116,32,111,119,110,101,114>>]},{li,[],[{code,[],[<<101,112,105,112,101>>]},<<32,45,32,66,114,111,107,101,110,32,112,105,112,101>>]},{li,[],[{code,[],[<<101,114,111,102,115>>]},<<32,45,32,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109>>]},{li,[],[{code,[],[<<101,115,112,105,112,101>>]},<<32,45,32,73,110,118,97,108,105,100,32,115,101,101,107>>]},{li,[],[{code,[],[<<101,115,114,99,104>>]},<<32,45,32,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115>>]},{li,[],[{code,[],[<<101,115,116,97,108,101>>]},<<32,45,32,83,116,97,108,101,32,114,101,109,111,116,101,32,102,105,108,101,32,104,97,110,100,108,101>>]},{li,[],[{code,[],[<<101,120,100,101,118>>]},<<32,45,32,67,114,111,115,115,45,100,111,109,97,105,110,32,108,105,110,107>>]}]},{h2,[],[<<80,101,114,102,111,114,109,97,110,99,101>>]},{p,[],[<<70,111,114,32,105,110,99,114,101,97,115,101,100,32,112,101,114,102,111,114,109,97,110,99,101,44,32,114,97,119,32,102,105,108,101,115,32,97,114,101,32,114,101,99,111,109,109,101,110,100,101,100,46>>]},{p,[],[<<65,32,110,111,114,109,97,108,32,102,105,108,101,32,105,115,32,114,101,97,108,108,121,32,97,32,112,114,111,99,101,115,115,32,115,111,32,105,116,32,99,97,110,32,98,101,32,117,115,101,100,32,97,115,32,97,110,32,73,47,79,32,100,101,118,105,99,101,32,40,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111>>]}]},<<41,46,32,84,104,101,114,101,102,111,114,101,44,32,119,104,101,110,32,100,97,116,97,32,105,115,32,119,114,105,116,116,101,110,32,116,111,32,97,32,110,111,114,109,97,108,32,102,105,108,101,44,32,116,104,101,32,115,101,110,100,105,110,103,32,111,102,32,116,104,101,32,100,97,116,97,32,116,111,32,116,104,101,32,102,105,108,101,32,112,114,111,99,101,115,115,44,32,99,111,112,105,101,115,32,97,108,108,32,100,97,116,97,32,116,104,97,116,32,97,114,101,32,110,111,116,32,98,105,110,97,114,105,101,115,46,32,79,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,105,110,32,98,105,110,97,114,121,32,109,111,100,101,32,97,110,100,32,119,114,105,116,105,110,103,32,98,105,110,97,114,105,101,115,32,105,115,32,116,104,101,114,101,102,111,114,101,32,114,101,99,111,109,109,101,110,100,101,100,46,32,73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,111,110,32,97,110,111,116,104,101,114,32,110,111,100,101,44,32,111,114,32,105,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,114,117,110,115,32,97,115,32,115,108,97,118,101,32,116,111,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,97,110,111,116,104,101,114,32,110,111,100,101,44,32,97,108,115,111,32,98,105,110,97,114,105,101,115,32,97,114,101,32,99,111,112,105,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<82,97,119,32,102,105,108,101,115,32,117,115,101,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,111,102,32,116,104,101,32,104,111,115,116,32,109,97,99,104,105,110,101,32,111,102,32,116,104,101,32,110,111,100,101,46,32,70,111,114,32,110,111,114,109,97,108,32,102,105,108,101,115,32,40,110,111,110,45,114,97,119,41,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,117,115,101,100,32,116,111,32,102,105,110,100,32,116,104,101,32,102,105,108,101,115,44,32,97,110,100,32,105,102,32,116,104,101,32,110,111,100,101,32,105,115,32,114,117,110,110,105,110,103,32,105,116,115,32,102,105,108,101,32,115,101,114,118,101,114,32,97,115,32,115,108,97,118,101,32,116,111,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,97,110,111,116,104,101,114,32,110,111,100,101,44,32,97,110,100,32,116,104,101,32,111,116,104,101,114,32,110,111,100,101,32,114,117,110,115,32,111,110,32,115,111,109,101,32,111,116,104,101,114,32,104,111,115,116,32,109,97,99,104,105,110,101,44,32,116,104,101,121,32,99,97,110,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,102,105,108,101,32,115,121,115,116,101,109,115,46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,105,115,32,115,101,108,100,111,109,32,97,32,112,114,111,98,108,101,109,46>>]}]},{p,[],[{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<32,99,97,110,32,98,101,32,103,105,118,101,110,32,116,104,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,97,100,95,97,104,101,97,100>>]},<<32,116,111,32,116,117,114,110,32,111,110,32,99,97,99,104,105,110,103,44,32,119,104,105,99,104,32,119,105,108,108,32,114,101,100,117,99,101,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,115,32,97,110,100,32,103,114,101,97,116,108,121,32,105,109,112,114,111,118,101,32,112,101,114,102,111,114,109,97,110,99,101,32,102,111,114,32,115,109,97,108,108,32,114,101,97,100,115,32,97,110,100,32,119,114,105,116,101,115,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,111,118,101,114,104,101,97,100,32,119,111,110,39,116,32,100,105,115,97,112,112,101,97,114,32,99,111,109,112,108,101,116,101,108,121,32,97,110,100,32,105,116,39,115,32,98,101,115,116,32,116,111,32,107,101,101,112,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,97,32,109,105,110,105,109,117,109,46,32,65,115,32,97,32,99,111,110,116,114,105,118,101,100,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,117,110,99,116,105,111,110,32,119,114,105,116,101,115,32,52,77,66,32,105,110,32,50,46,53,32,115,101,99,111,110,100,115,32,119,104,101,110,32,116,101,115,116,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,40,78,97,109,101,41,32,45,62,10,32,32,32,32,123,111,107,44,32,70,100,125,32,61,32,102,105,108,101,58,111,112,101,110,40,78,97,109,101,44,32,91,114,97,119,44,32,119,114,105,116,101,44,32,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,98,105,110,97,114,121,93,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,70,100,44,32,52,32,98,115,108,32,50,48,41,44,10,32,32,32,32,102,105,108,101,58,99,108,111,115,101,40,70,100,41,46,10,10,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,95,70,100,44,32,48,41,32,45,62,10,32,32,32,32,111,107,59,10,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,70,100,44,32,77,41,32,45,62,10,32,32,32,32,111,107,32,61,32,102,105,108,101,58,119,114,105,116,101,40,70,100,44,32,60,60,48,62,62,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,70,100,44,32,77,32,45,32,49,41,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,102,117,110,99,116,105,111,110,97,108,108,121,32,101,113,117,105,118,97,108,101,110,116,32,99,111,100,101,32,119,114,105,116,101,115,32,49,50,56,32,98,121,116,101,115,32,112,101,114,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<32,97,110,100,32,115,111,32,100,111,101,115,32,116,104,101,32,115,97,109,101,32,119,111,114,107,32,105,110,32,48,46,48,56,32,115,101,99,111,110,100,115,44,32,119,104,105,99,104,32,105,115,32,114,111,117,103,104,108,121,32,51,48,32,116,105,109,101,115,32,102,97,115,116,101,114,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<99,114,101,97,116,101,95,102,105,108,101,40,78,97,109,101,41,32,45,62,10,32,32,32,32,123,111,107,44,32,70,100,125,32,61,32,102,105,108,101,58,111,112,101,110,40,78,97,109,101,44,32,91,114,97,119,44,32,119,114,105,116,101,44,32,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,98,105,110,97,114,121,93,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,52,32,98,115,108,32,50,48,41,44,10,32,32,32,32,102,105,108,101,58,99,108,111,115,101,40,70,100,41,44,10,32,32,32,32,111,107,46,10,10,99,114,101,97,116,101,95,102,105,108,101,95,49,40,95,70,100,44,32,48,41,32,45,62,10,32,32,32,32,111,107,59,10,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,41,32,119,104,101,110,32,77,32,62,61,32,49,50,56,32,45,62,10,32,32,32,32,111,107,32,61,32,102,105,108,101,58,119,114,105,116,101,40,70,100,44,32,60,60,48,58,40,49,50,56,41,47,117,110,105,116,58,56,62,62,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,32,45,32,49,50,56,41,59,10,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,41,32,45,62,10,32,32,32,32,111,107,32,61,32,102,105,108,101,58,119,114,105,116,101,40,70,100,44,32,60,60,48,58,40,77,41,47,117,110,105,116,58,56,62,62,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,32,45,32,49,41,46>>]}]},{p,[],[<<87,104,101,110,32,119,114,105,116,105,110,103,32,100,97,116,97,32,105,116,39,115,32,103,101,110,101,114,97,108,108,121,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,111,32,119,114,105,116,101,32,97,32,108,105,115,116,32,111,102,32,98,105,110,97,114,105,101,115,32,114,97,116,104,101,114,32,116,104,97,110,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,46,32,73,116,32,105,115,32,110,111,116,32,110,101,101,100,101,100,32,116,111,32,102,108,97,116,116,101,110,32,97,32,100,101,101,112,32,108,105,115,116,32,98,101,102,111,114,101,32,119,114,105,116,105,110,103,46,32,79,110,32,85,110,105,120,32,104,111,115,116,115,44,32,115,99,97,116,116,101,114,32,111,117,116,112,117,116,44,32,119,104,105,99,104,32,119,114,105,116,101,115,32,97,32,115,101,116,32,111,102,32,98,117,102,102,101,114,115,32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,105,115,32,117,115,101,100,32,119,104,101,110,32,112,111,115,115,105,98,108,101,46,32,73,110,32,116,104,105,115,32,119,97,121,32>>,{code,[],[<<119,114,105,116,101,40,70,68,44,32,91,66,105,110,49,44,32,66,105,110,50,32,124,32,66,105,110,51,93,41>>]},<<32,119,114,105,116,101,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32,98,105,110,97,114,105,101,115,32,119,105,116,104,111,117,116,32,99,111,112,121,105,110,103,32,116,104,101,32,100,97,116,97,32,97,116,32,97,108,108,44,32,101,120,99,101,112,116,32,102,111,114,32,112,101,114,104,97,112,115,32,100,101,101,112,32,100,111,119,110,32,105,110,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,107,101,114,110,101,108,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,102,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,32,119,104,101,110,32,97,99,99,101,115,115,105,110,103,32,97,110,32,111,112,101,110,32,102,105,108,101,32,119,105,116,104,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111>>]}]},<<44,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,110,100,108,105,110,103,32,116,104,101,32,102,105,108,101,32,101,120,105,116,115,46,32,84,104,101,32,100,101,97,100,32,102,105,108,101,32,112,114,111,99,101,115,115,32,99,97,110,32,104,97,110,103,32,105,102,32,97,32,112,114,111,99,101,115,115,32,116,114,105,101,115,32,116,111,32,97,99,99,101,115,115,32,105,116,32,108,97,116,101,114,46,32,84,104,105,115,32,119,105,108,108,32,98,101,32,102,105,120,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]},{h2,[],[<<83,101,101,32,65,108,115,111>>]},{p,[],[{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,102,105,108,101,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,105,108,101,110,97,109,101,40,51,41>>]}]}]}]},#{name => <<102,105,108,101>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,102,105,108,101,46,120,109,108],types => #{{date_time,0} => {attribute,123,type,{date_time,{remote_type,123,[{atom,123,calendar},{atom,123,datetime},[]]},[]}},{deep_list,0} => {attribute,101,type,{deep_list,{type,101,list,[{type,101,union,[{type,101,char,[]},{type,101,atom,[]},{user_type,101,deep_list,[]}]}]},[]}},{delete_option,0} => {attribute,126,type,{delete_option,{atom,126,raw},[]}},{fd,0} => {attribute,87,type,{fd,{type,87,record,[{atom,87,file_descriptor}]},[]}},{file_info,0} => {attribute,86,type,{file_info,{type,86,record,[{atom,86,file_info}]},[]}},{file_info_option,0} => {attribute,129,type,{file_info_option,{type,129,union,[{type,129,tuple,[{atom,129,time},{atom,129,local}]},{type,129,tuple,[{atom,129,time},{atom,129,universal}]},{type,130,tuple,[{atom,130,time},{atom,130,posix}]},{atom,130,raw}]},[]}},{filename,0} => {attribute,84,type,{filename,{type,84,string,[]},[]}},{filename_all,0} => {attribute,85,type,{filename_all,{type,85,union,[{type,85,string,[]},{type,85,binary,[]}]},[]}},{io_device,0} => {attribute,88,type,{io_device,{type,88,union,[{type,88,pid,[]},{user_type,88,fd,[]}]},[]}},{location,0} => {attribute,89,type,{location,{type,89,union,[{type,89,integer,[]},{type,89,tuple,[{atom,89,bof},{ann_type,89,[{var,89,'Offset'},{type,89,integer,[]}]}]},{type,90,tuple,[{atom,90,cur},{ann_type,90,[{var,90,'Offset'},{type,90,integer,[]}]}]},{type,91,tuple,[{atom,91,eof},{ann_type,91,[{var,91,'Offset'},{type,91,integer,[]}]}]},{atom,91,bof},{atom,91,cur},{atom,91,eof}]},[]}},{mode,0} => {attribute,92,type,{mode,{type,92,union,[{atom,92,read},{atom,92,write},{atom,92,append},{atom,93,exclusive},{atom,93,raw},{atom,93,binary},{type,94,tuple,[{atom,94,delayed_write},{ann_type,95,[{var,95,'Size'},{type,95,non_neg_integer,[]}]},{ann_type,96,[{var,96,'Delay'},{type,96,non_neg_integer,[]}]}]},{atom,97,delayed_write},{type,97,tuple,[{atom,97,read_ahead},{ann_type,97,[{var,97,'Size'},{type,97,pos_integer,[]}]}]},{atom,98,read_ahead},{atom,98,compressed},{type,99,tuple,[{atom,99,encoding},{remote_type,99,[{atom,99,unicode},{atom,99,encoding},[]]}]},{atom,100,sync}]},[]}},{name,0} => {attribute,102,type,{name,{type,102,union,[{type,102,string,[]},{type,102,atom,[]},{user_type,102,deep_list,[]}]},[]}},{name_all,0} => {attribute,103,type,{name_all,{type,103,union,[{type,103,string,[]},{type,103,atom,[]},{user_type,103,deep_list,[]},{ann_type,103,[{var,103,'RawFilename'},{type,103,binary,[]}]}]},[]}},{posix,0} => {attribute,104,type,{posix,{type,105,union,[{atom,105,eacces},{atom,105,eagain},{atom,106,ebadf},{atom,106,ebadmsg},{atom,106,ebusy},{atom,107,edeadlk},{atom,107,edeadlock},{atom,107,edquot},{atom,108,eexist},{atom,109,efault},{atom,109,efbig},{atom,109,eftype},{atom,110,eintr},{atom,110,einval},{atom,110,eio},{atom,110,eisdir},{atom,111,eloop},{atom,112,emfile},{atom,112,emlink},{atom,112,emultihop},{atom,113,enametoolong},{atom,113,enfile},{atom,114,enobufs},{atom,114,enodev},{atom,114,enolck},{atom,114,enolink},{atom,114,enoent},{atom,115,enomem},{atom,115,enospc},{atom,115,enosr},{atom,115,enostr},{atom,115,enosys},{atom,116,enotblk},{atom,116,enotdir},{atom,116,enotsup},{atom,116,enxio},{atom,117,eopnotsupp},{atom,117,eoverflow},{atom,118,eperm},{atom,118,epipe},{atom,119,erange},{atom,119,erofs},{atom,120,espipe},{atom,120,esrch},{atom,120,estale},{atom,121,etxtbsy},{atom,122,exdev}]},[]}},{posix_file_advise,0} => {attribute,124,type,{posix_file_advise,{type,124,union,[{atom,124,normal},{atom,124,sequential},{atom,124,random},{atom,125,no_reuse},{atom,125,will_need},{atom,125,dont_need}]},[]}},{sendfile_option,0} => {attribute,127,type,{sendfile_option,{type,127,union,[{type,127,tuple,[{atom,127,chunk_size},{type,127,non_neg_integer,[]}]},{type,128,tuple,[{atom,128,use_threads},{type,128,boolean,[]}]}]},[]}}}},[{{function,advise,4},[{file,[102,105,108,101,46,101,114,108]},{location,565}],[<<97,100,118,105,115,101,47,52>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<112,111,115,105,120,95,102,105,108,101,95,97,100,118,105,115,101>>}],[]}]},{p,[],[{code,[],[<<97,100,118,105,115,101,47,52>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,97,110,110,111,117,110,99,101,32,97,110,32,105,110,116,101,110,116,105,111,110,32,116,111,32,97,99,99,101,115,115,32,102,105,108,101,32,100,97,116,97,32,105,110,32,97,32,115,112,101,99,105,102,105,99,32,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,102,117,116,117,114,101,44,32,116,104,117,115,32,97,108,108,111,119,105,110,103,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,116,111,32,112,101,114,102,111,114,109,32,97,112,112,114,111,112,114,105,97,116,101,32,111,112,116,105,109,105,122,97,116,105,111,110,115,46>>]},{p,[],[<<79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,109,105,103,104,116,32,104,97,118,101,32,110,111,32,101,102,102,101,99,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,56>>,signature => [{attribute,565,spec,{{advise,4},[{type,565,bounded_fun,[{type,565,'fun',[{type,565,product,[{var,565,'IoDevice'},{var,565,'Offset'},{var,565,'Length'},{var,565,'Advise'}]},{type,565,union,[{atom,565,ok},{type,565,tuple,[{atom,565,error},{var,565,'Reason'}]}]}]},[{type,566,constraint,[{atom,566,is_subtype},[{var,566,'IoDevice'},{user_type,566,io_device,[]}]]},{type,567,constraint,[{atom,567,is_subtype},[{var,567,'Offset'},{type,567,integer,[]}]]},{type,568,constraint,[{atom,568,is_subtype},[{var,568,'Length'},{type,568,integer,[]}]]},{type,569,constraint,[{atom,569,is_subtype},[{var,569,'Advise'},{user_type,569,posix_file_advise,[]}]]},{type,570,constraint,[{atom,570,is_subtype},[{var,570,'Reason'},{type,570,union,[{user_type,570,posix,[]},{atom,570,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,allocate,3},[{file,[102,105,108,101,46,101,114,108]},{location,579}],[<<97,108,108,111,99,97,116,101,47,51>>],#{<<101,110>> => [{p,[],[{code,[],[<<97,108,108,111,99,97,116,101,47,51>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,112,114,101,97,108,108,111,99,97,116,101,32,115,112,97,99,101,32,102,111,114,32,97,32,102,105,108,101,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,111,110,108,121,32,115,117,99,99,101,101,100,115,32,105,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,112,114,111,118,105,100,101,32,116,104,105,115,32,102,101,97,116,117,114,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,57>>,signature => [{attribute,579,spec,{{allocate,3},[{type,579,bounded_fun,[{type,579,'fun',[{type,579,product,[{var,579,'File'},{var,579,'Offset'},{var,579,'Length'}]},{type,580,union,[{atom,580,ok},{type,580,tuple,[{atom,580,error},{user_type,580,posix,[]}]}]}]},[{type,581,constraint,[{atom,581,is_subtype},[{var,581,'File'},{user_type,581,io_device,[]}]]},{type,582,constraint,[{atom,582,is_subtype},[{var,582,'Offset'},{type,582,non_neg_integer,[]}]]},{type,583,constraint,[{atom,583,is_subtype},[{var,583,'Length'},{type,583,non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,change_group,2},[{file,[102,105,108,101,46,101,114,108]},{location,1249}],[<<99,104,97,110,103,101,95,103,114,111,117,112,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,103,114,111,117,112,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,56>>,signature => [{attribute,1249,spec,{{change_group,2},[{type,1249,bounded_fun,[{type,1249,'fun',[{type,1249,product,[{var,1249,'Filename'},{var,1249,'Gid'}]},{type,1249,union,[{atom,1249,ok},{type,1249,tuple,[{atom,1249,error},{var,1249,'Reason'}]}]}]},[{type,1250,constraint,[{atom,1250,is_subtype},[{var,1250,'Filename'},{user_type,1250,name_all,[]}]]},{type,1251,constraint,[{atom,1251,is_subtype},[{var,1251,'Gid'},{type,1251,integer,[]}]]},{type,1252,constraint,[{atom,1252,is_subtype},[{var,1252,'Reason'},{type,1252,union,[{user_type,1252,posix,[]},{atom,1252,badarg}]}]]}]]}]}}]}},{{function,change_mode,2},[{file,[102,105,108,101,46,101,114,108]},{location,1221}],[<<99,104,97,110,103,101,95,109,111,100,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,112,101,114,109,105,115,115,105,111,110,115,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,49,54>>,signature => [{attribute,1221,spec,{{change_mode,2},[{type,1221,bounded_fun,[{type,1221,'fun',[{type,1221,product,[{var,1221,'Filename'},{var,1221,'Mode'}]},{type,1221,union,[{atom,1221,ok},{type,1221,tuple,[{atom,1221,error},{var,1221,'Reason'}]}]}]},[{type,1222,constraint,[{atom,1222,is_subtype},[{var,1222,'Filename'},{user_type,1222,name_all,[]}]]},{type,1223,constraint,[{atom,1223,is_subtype},[{var,1223,'Mode'},{type,1223,integer,[]}]]},{type,1224,constraint,[{atom,1224,is_subtype},[{var,1224,'Reason'},{type,1224,union,[{user_type,1224,posix,[]},{atom,1224,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,change_owner,2},[{file,[102,105,108,101,46,101,114,108]},{location,1230}],[<<99,104,97,110,103,101,95,111,119,110,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,111,119,110,101,114,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,50,52>>,signature => [{attribute,1230,spec,{{change_owner,2},[{type,1230,bounded_fun,[{type,1230,'fun',[{type,1230,product,[{var,1230,'Filename'},{var,1230,'Uid'}]},{type,1230,union,[{atom,1230,ok},{type,1230,tuple,[{atom,1230,error},{var,1230,'Reason'}]}]}]},[{type,1231,constraint,[{atom,1231,is_subtype},[{var,1231,'Filename'},{user_type,1231,name_all,[]}]]},{type,1232,constraint,[{atom,1232,is_subtype},[{var,1232,'Uid'},{type,1232,integer,[]}]]},{type,1233,constraint,[{atom,1233,is_subtype},[{var,1233,'Reason'},{type,1233,union,[{user_type,1233,posix,[]},{atom,1233,badarg}]}]]}]]}]}}]}},{{function,change_owner,3},[{file,[102,105,108,101,46,101,114,108]},{location,1239}],[<<99,104,97,110,103,101,95,111,119,110,101,114,47,51>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,111,119,110,101,114,32,97,110,100,32,103,114,111,117,112,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,51,50>>,signature => [{attribute,1239,spec,{{change_owner,3},[{type,1239,bounded_fun,[{type,1239,'fun',[{type,1239,product,[{var,1239,'Filename'},{var,1239,'Uid'},{var,1239,'Gid'}]},{type,1239,union,[{atom,1239,ok},{type,1239,tuple,[{atom,1239,error},{var,1239,'Reason'}]}]}]},[{type,1240,constraint,[{atom,1240,is_subtype},[{var,1240,'Filename'},{user_type,1240,name_all,[]}]]},{type,1241,constraint,[{atom,1241,is_subtype},[{var,1241,'Uid'},{type,1241,integer,[]}]]},{type,1242,constraint,[{atom,1242,is_subtype},[{var,1242,'Gid'},{type,1242,integer,[]}]]},{type,1243,constraint,[{atom,1243,is_subtype},[{var,1243,'Reason'},{type,1243,union,[{user_type,1243,posix,[]},{atom,1243,badarg}]}]]}]]}]}}]}},{{function,change_time,2},[{file,[102,105,108,101,46,101,114,108]},{location,1258}],[<<99,104,97,110,103,101,95,116,105,109,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,97,110,100,32,97,99,99,101,115,115,32,116,105,109,101,115,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,52,48>>,signature => [{attribute,1258,spec,{{change_time,2},[{type,1258,bounded_fun,[{type,1258,'fun',[{type,1258,product,[{var,1258,'Filename'},{var,1258,'Mtime'}]},{type,1258,union,[{atom,1258,ok},{type,1258,tuple,[{atom,1258,error},{var,1258,'Reason'}]}]}]},[{type,1259,constraint,[{atom,1259,is_subtype},[{var,1259,'Filename'},{user_type,1259,name_all,[]}]]},{type,1260,constraint,[{atom,1260,is_subtype},[{var,1260,'Mtime'},{user_type,1260,date_time,[]}]]},{type,1261,constraint,[{atom,1261,is_subtype},[{var,1261,'Reason'},{type,1261,union,[{user_type,1261,posix,[]},{atom,1261,badarg}]}]]}]]}]}}]}},{{function,change_time,3},[{file,[102,105,108,101,46,101,114,108]},{location,1268}],[<<99,104,97,110,103,101,95,116,105,109,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,97,110,100,32,108,97,115,116,32,97,99,99,101,115,115,32,116,105,109,101,115,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,52,56>>,signature => [{attribute,1268,spec,{{change_time,3},[{type,1268,bounded_fun,[{type,1268,'fun',[{type,1268,product,[{var,1268,'Filename'},{var,1268,'Atime'},{var,1268,'Mtime'}]},{type,1268,union,[{atom,1268,ok},{type,1268,tuple,[{atom,1268,error},{var,1268,'Reason'}]}]}]},[{type,1269,constraint,[{atom,1269,is_subtype},[{var,1269,'Filename'},{user_type,1269,name_all,[]}]]},{type,1270,constraint,[{atom,1270,is_subtype},[{var,1270,'Atime'},{user_type,1270,date_time,[]}]]},{type,1271,constraint,[{atom,1271,is_subtype},[{var,1271,'Mtime'},{user_type,1271,date_time,[]}]]},{type,1272,constraint,[{atom,1272,is_subtype},[{var,1272,'Reason'},{type,1272,union,[{user_type,1272,posix,[]},{atom,1272,badarg}]}]]}]]}]}}]}},{{function,close,1},[{file,[102,105,108,101,46,101,114,108]},{location,546}],[<<99,108,111,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,108,111,115,101,115,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,73,116,32,109,111,115,116,108,121,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<44,32,101,120,99,101,112,116,32,102,111,114,32,115,111,109,101,32,115,101,118,101,114,101,32,101,114,114,111,114,115,32,115,117,99,104,32,97,115,32,111,117,116,32,111,102,32,109,101,109,111,114,121,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]},<<32,119,97,115,32,117,115,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,44,32>>,{code,[],[<<99,108,111,115,101,47,49>>]},<<32,99,97,110,32,114,101,116,117,114,110,32,97,110,32,111,108,100,32,119,114,105,116,101,32,101,114,114,111,114,32,97,110,100,32,110,111,116,32,101,118,101,110,32,116,114,121,32,116,111,32,99,108,111,115,101,32,116,104,101,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,53,54>>,signature => [{attribute,546,spec,{{close,1},[{type,546,bounded_fun,[{type,546,'fun',[{type,546,product,[{var,546,'IoDevice'}]},{type,546,union,[{atom,546,ok},{type,546,tuple,[{atom,546,error},{var,546,'Reason'}]}]}]},[{type,547,constraint,[{atom,547,is_subtype},[{var,547,'IoDevice'},{user_type,547,io_device,[]}]]},{type,548,constraint,[{atom,548,is_subtype},[{var,548,'Reason'},{type,548,union,[{user_type,548,posix,[]},{atom,548,badarg},{atom,548,terminated}]}]]}]]}]}}]}},{{function,consult,1},[{file,[102,105,108,101,46,101,114,108]},{location,1025}],[<<99,111,110,115,117,108,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,69,114,108,97,110,103,32,116,101,114,109,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,44,32,102,114,111,109,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,84,101,114,109,115,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,119,97,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,116,101,114,109,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,84,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,44,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<46>>]}]}]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<102,46,116,120,116,58,32,32,123,112,101,114,115,111,110,44,32,34,107,97,108,108,101,34,44,32,50,53,125,46,10,32,32,32,32,32,32,32,32,123,112,101,114,115,111,110,44,32,34,112,101,108,108,101,34,44,32,51,48,125,46>>]}]},{pre,[],[{code,[],[<<49,62,32,102,105,108,101,58,99,111,110,115,117,108,116,40,34,102,46,116,120,116,34,41,46,10,123,111,107,44,91,123,112,101,114,115,111,110,44,34,107,97,108,108,101,34,44,50,53,125,44,123,112,101,114,115,111,110,44,34,112,101,108,108,101,34,44,51,48,125,93,125>>]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,54,57>>,signature => [{attribute,1025,spec,{{consult,1},[{type,1025,bounded_fun,[{type,1025,'fun',[{type,1025,product,[{var,1025,'Filename'}]},{type,1025,union,[{type,1025,tuple,[{atom,1025,ok},{var,1025,'Terms'}]},{type,1025,tuple,[{atom,1025,error},{var,1025,'Reason'}]}]}]},[{type,1026,constraint,[{atom,1026,is_subtype},[{var,1026,'Filename'},{user_type,1026,name_all,[]}]]},{type,1027,constraint,[{atom,1027,is_subtype},[{var,1027,'Terms'},{type,1027,list,[{type,1027,term,[]}]}]]},{type,1028,constraint,[{atom,1028,is_subtype},[{var,1028,'Reason'},{type,1028,union,[{user_type,1028,posix,[]},{atom,1028,badarg},{atom,1028,terminated},{atom,1028,system_limit},{type,1029,tuple,[{ann_type,1029,[{var,1029,'Line'},{type,1029,integer,[]}]},{ann_type,1029,[{var,1029,'Mod'},{type,1029,module,[]}]},{ann_type,1029,[{var,1029,'Term'},{type,1029,term,[]}]}]}]}]]}]]}]}}]}},{{function,copy,3},[{file,[102,105,108,101,46,101,114,108]},{location,788}],[<<99,111,112,121,47,51>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,48,55>>,equiv => {function,copy,2},signature => [{attribute,788,spec,{{copy,3},[{type,788,bounded_fun,[{type,788,'fun',[{type,788,product,[{var,788,'Source'},{var,788,'Destination'},{var,788,'ByteCount'}]},{type,789,union,[{type,789,tuple,[{atom,789,ok},{var,789,'BytesCopied'}]},{type,789,tuple,[{atom,789,error},{var,789,'Reason'}]}]}]},[{type,790,constraint,[{atom,790,is_subtype},[{var,790,'Source'},{type,790,union,[{user_type,790,io_device,[]},{var,790,'Filename'},{type,790,tuple,[{var,790,'Filename'},{var,790,'Modes'}]}]}]]},{type,791,constraint,[{atom,791,is_subtype},[{var,791,'Destination'},{type,791,union,[{user_type,791,io_device,[]},{var,791,'Filename'},{type,791,tuple,[{var,791,'Filename'},{var,791,'Modes'}]}]}]]},{type,792,constraint,[{atom,792,is_subtype},[{var,792,'Filename'},{user_type,792,name_all,[]}]]},{type,793,constraint,[{atom,793,is_subtype},[{var,793,'Modes'},{type,793,list,[{user_type,793,mode,[]}]}]]},{type,794,constraint,[{atom,794,is_subtype},[{var,794,'ByteCount'},{type,794,union,[{type,794,non_neg_integer,[]},{atom,794,infinity}]}]]},{type,795,constraint,[{atom,795,is_subtype},[{var,795,'BytesCopied'},{type,795,non_neg_integer,[]}]]},{type,796,constraint,[{atom,796,is_subtype},[{var,796,'Reason'},{type,796,union,[{user_type,796,posix,[]},{atom,796,badarg},{atom,796,terminated}]}]]}]]}]}}]}},{{function,copy,2},[{file,[102,105,108,101,46,101,114,108]},{location,777}],[<<99,111,112,121,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,112,105,101,115,32>>,{code,[],[<<66,121,116,101,67,111,117,110,116>>]},<<32,98,121,116,101,115,32,102,114,111,109,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,116,111,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<46,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,114,101,102,101,114,32,116,111,32,101,105,116,104,101,114,32,102,105,108,101,110,97,109,101,115,32,111,114,32,73,79,32,100,101,118,105,99,101,115,32,102,114,111,109,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<111,112,101,110,47,50>>]},<<46,32>>,{code,[],[<<66,121,116,101,67,111,117,110,116>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<105,110,102,105,110,105,116,121>>]},<<44,32,100,101,110,111,116,105,110,103,32,97,110,32,105,110,102,105,110,105,116,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,111,100,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,112,111,115,115,105,98,108,101,32,109,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<44,32,97,110,100,32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<91,93>>]},<<46>>]},{p,[],[<<73,102,32,98,111,116,104,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,114,101,102,101,114,32,116,111,32,102,105,108,101,110,97,109,101,115,44,32,116,104,101,32,102,105,108,101,115,32,97,114,101,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<91,114,101,97,100,44,32,98,105,110,97,114,121,93>>]},<<32,97,110,100,32>>,{code,[],[<<91,119,114,105,116,101,44,32,98,105,110,97,114,121,93>>]},<<32,112,114,101,112,101,110,100,101,100,32,116,111,32,116,104,101,105,114,32,109,111,100,101,32,108,105,115,116,115,44,32,114,101,115,112,101,99,116,105,118,101,108,121,44,32,116,111,32,111,112,116,105,109,105,122,101,32,116,104,101,32,99,111,112,121,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,102,105,108,101,110,97,109,101,44,32,105,116,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<114,101,97,100>>]},<<32,109,111,100,101,32,112,114,101,112,101,110,100,101,100,32,116,111,32,116,104,101,32,109,111,100,101,32,108,105,115,116,32,98,101,102,111,114,101,32,116,104,101,32,99,111,112,121,44,32,97,110,100,32,99,108,111,115,101,100,32,119,104,101,110,32,100,111,110,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,102,105,108,101,110,97,109,101,44,32,105,116,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,109,111,100,101,32,112,114,101,112,101,110,100,101,100,32,116,111,32,116,104,101,32,109,111,100,101,32,108,105,115,116,32,98,101,102,111,114,101,32,116,104,101,32,99,111,112,121,44,32,97,110,100,32,99,108,111,115,101,100,32,119,104,101,110,32,100,111,110,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,121,116,101,115,67,111,112,105,101,100,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<66,121,116,101,115,67,111,112,105,101,100>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,116,104,97,116,32,119,97,115,32,99,111,112,105,101,100,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<66,121,116,101,67,111,117,110,116>>]},<<32,105,102,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,101,110,99,111,117,110,116,101,114,101,100,32,111,110,32,116,104,101,32,115,111,117,114,99,101,46,32,73,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58,32,97,115,32,102,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<32,105,102,32,97,32,102,105,108,101,32,104,97,100,32,116,111,32,98,101,32,111,112,101,110,101,100,44,32,97,110,100,32,97,115,32,102,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,48,55>>,signature => [{attribute,777,spec,{{copy,2},[{type,777,bounded_fun,[{type,777,'fun',[{type,777,product,[{var,777,'Source'},{var,777,'Destination'}]},{type,777,union,[{type,777,tuple,[{atom,777,ok},{var,777,'BytesCopied'}]},{type,777,tuple,[{atom,777,error},{var,777,'Reason'}]}]}]},[{type,778,constraint,[{atom,778,is_subtype},[{var,778,'Source'},{type,778,union,[{user_type,778,io_device,[]},{var,778,'Filename'},{type,778,tuple,[{var,778,'Filename'},{var,778,'Modes'}]}]}]]},{type,779,constraint,[{atom,779,is_subtype},[{var,779,'Destination'},{type,779,union,[{user_type,779,io_device,[]},{var,779,'Filename'},{type,779,tuple,[{var,779,'Filename'},{var,779,'Modes'}]}]}]]},{type,780,constraint,[{atom,780,is_subtype},[{var,780,'Filename'},{user_type,780,name_all,[]}]]},{type,781,constraint,[{atom,781,is_subtype},[{var,781,'Modes'},{type,781,list,[{user_type,781,mode,[]}]}]]},{type,782,constraint,[{atom,782,is_subtype},[{var,782,'BytesCopied'},{type,782,non_neg_integer,[]}]]},{type,783,constraint,[{atom,783,is_subtype},[{var,783,'Reason'},{type,783,union,[{user_type,783,posix,[]},{atom,783,badarg},{atom,783,terminated}]}]]}]]}]}}]}},{{function,datasync,1},[{file,[102,105,108,101,46,101,114,108]},{location,731}],[<<100,97,116,97,115,121,110,99,47,49>>],#{<<101,110>> => [{p,[],[<<69,110,115,117,114,101,115,32,116,104,97,116,32,97,110,121,32,98,117,102,102,101,114,115,32,107,101,112,116,32,98,121,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,40,110,111,116,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,41,32,97,114,101,32,119,114,105,116,116,101,110,32,116,111,32,100,105,115,107,46,32,73,110,32,109,97,110,121,32,119,97,121,115,32,105,116,32,114,101,115,101,109,98,108,101,115,32>>,{code,[],[<<102,115,121,110,99>>]},<<32,98,117,116,32,105,116,32,100,111,101,115,32,110,111,116,32,117,112,100,97,116,101,32,115,111,109,101,32,111,102,32,116,104,101,32,109,101,116,97,100,97,116,97,32,111,102,32,116,104,101,32,102,105,108,101,44,32,115,117,99,104,32,97,115,32,116,104,101,32,97,99,99,101,115,115,32,116,105,109,101,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,104,97,115,32,110,111,32,101,102,102,101,99,116,46>>]},{p,[],[<<65,112,112,108,105,99,97,116,105,111,110,115,32,116,104,97,116,32,97,99,99,101,115,115,32,100,97,116,97,98,97,115,101,115,32,111,114,32,108,111,103,32,102,105,108,101,115,32,111,102,116,101,110,32,119,114,105,116,101,32,97,32,116,105,110,121,32,100,97,116,97,32,102,114,97,103,109,101,110,116,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,111,110,101,32,108,105,110,101,32,105,110,32,97,32,108,111,103,32,102,105,108,101,41,32,97,110,100,32,116,104,101,110,32,99,97,108,108,32>>,{code,[],[<<102,115,121,110,99,40,41>>]},<<32,105,109,109,101,100,105,97,116,101,108,121,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,119,114,105,116,116,101,110,32,100,97,116,97,32,105,115,32,112,104,121,115,105,99,97,108,108,121,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,104,97,114,100,32,100,105,115,107,46,32,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32>>,{code,[],[<<102,115,121,110,99,40,41>>]},<<32,97,108,119,97,121,115,32,105,110,105,116,105,97,116,101,115,32,116,119,111,32,119,114,105,116,101,32,111,112,101,114,97,116,105,111,110,115,58,32,111,110,101,32,102,111,114,32,116,104,101,32,110,101,119,108,121,32,119,114,105,116,116,101,110,32,100,97,116,97,32,97,110,100,32,97,110,111,116,104,101,114,32,111,110,101,32,116,111,32,117,112,100,97,116,101,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,115,116,111,114,101,100,32,105,110,32,116,104,101,32>>,{code,[],[<<105,110,111,100,101>>]},<<46,32,73,102,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,105,115,32,110,111,116,32,97,32,112,97,114,116,32,111,102,32,116,104,101,32,116,114,97,110,115,97,99,116,105,111,110,32,99,111,110,99,101,112,116,44,32>>,{code,[],[<<102,100,97,116,97,115,121,110,99,40,41>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,97,118,111,105,100,32,117,110,110,101,99,101,115,115,97,114,121,32>>,{code,[],[<<105,110,111,100,101>>]},<<32,100,105,115,107,32,119,114,105,116,101,32,111,112,101,114,97,116,105,111,110,115,46>>]},{p,[],[<<65,118,97,105,108,97,98,108,101,32,111,110,108,121,32,105,110,32,115,111,109,101,32,80,79,83,73,88,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,99,97,108,108,32,114,101,115,117,108,116,115,32,105,110,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<102,115,121,110,99,40,41>>]},<<44,32,111,114,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,105,110,32,115,121,115,116,101,109,115,32,110,111,116,32,112,114,111,118,105,100,105,110,103,32,116,104,101,32>>,{code,[],[<<102,100,97,116,97,115,121,110,99,40,41>>]},<<32,115,121,115,99,97,108,108,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,52,53>>,signature => [{attribute,731,spec,{{datasync,1},[{type,731,bounded_fun,[{type,731,'fun',[{type,731,product,[{var,731,'IoDevice'}]},{type,731,union,[{atom,731,ok},{type,731,tuple,[{atom,731,error},{var,731,'Reason'}]}]}]},[{type,732,constraint,[{atom,732,is_subtype},[{var,732,'IoDevice'},{user_type,732,io_device,[]}]]},{type,733,constraint,[{atom,733,is_subtype},[{var,733,'Reason'},{type,733,union,[{user_type,733,posix,[]},{atom,733,badarg},{atom,733,terminated}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,del_dir,1},[{file,[102,105,108,101,46,101,114,108]},{location,256}],[<<100,101,108,95,100,105,114,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,100,101,108,101,116,101,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<68,105,114>>]},<<46,32,84,104,101,32,100,105,114,101,99,116,111,114,121,32,109,117,115,116,32,98,101,32,101,109,112,116,121,32,98,101,102,111,114,101,32,105,116,32,99,97,110,32,98,101,32,100,101,108,101,116,101,100,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,105,115,32,110,111,116,32,101,109,112,116,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[<<65,116,116,101,109,112,116,32,116,111,32,100,101,108,101,116,101,32,116,104,101,32,99,117,114,114,101,110,116,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,97,99,99,101,115>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,54,56>>,signature => [{attribute,256,spec,{{del_dir,1},[{type,256,bounded_fun,[{type,256,'fun',[{type,256,product,[{var,256,'Dir'}]},{type,256,union,[{atom,256,ok},{type,256,tuple,[{atom,256,error},{var,256,'Reason'}]}]}]},[{type,257,constraint,[{atom,257,is_subtype},[{var,257,'Dir'},{user_type,257,name_all,[]}]]},{type,258,constraint,[{atom,258,is_subtype},[{var,258,'Reason'},{type,258,union,[{user_type,258,posix,[]},{atom,258,badarg}]}]]}]]}]}}]}},{{function,del_dir_r,1},[{file,[102,105,108,101,46,101,114,108]},{location,263}],[<<100,101,108,95,100,105,114,95,114,47,49>>],#{<<101,110>> => [{p,[],[<<68,101,108,101,116,101,115,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<70,105,108,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,105,108,101>>]},<<32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,44,32,105,116,115,32,99,111,110,116,101,110,116,115,32,105,115,32,102,105,114,115,116,32,114,101,99,117,114,115,105,118,101,108,121,32,100,101,108,101,116,101,100,46,32,82,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<111,107>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,101,114,97,116,105,111,110,32,99,111,109,112,108,101,116,101,100,32,119,105,116,104,111,117,116,32,101,114,114,111,114,115,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,112,111,115,105,120,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,97,99,99,101,115,115,105,110,103,32,111,114,32,100,101,108,101,116,105,110,103,32>>,{code,[],[<<70,105,108,101>>]},<<46,32,73,102,32,115,111,109,101,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32,117,110,100,101,114,32>>,{code,[],[<<70,105,108,101>>]},<<32,99,111,117,108,100,32,110,111,116,32,98,101,32,100,101,108,101,116,101,100,44,32>>,{code,[],[<<70,105,108,101>>]},<<32,99,97,110,110,111,116,32,98,101,32,100,101,108,101,116,101,100,32,97,115,32,105,116,32,105,115,32,110,111,110,45,101,109,112,116,121,44,32,97,110,100,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,101,120,105,115,116,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,48,52>>,signature => [{attribute,263,spec,{{del_dir_r,1},[{type,263,bounded_fun,[{type,263,'fun',[{type,263,product,[{var,263,'File'}]},{type,263,union,[{atom,263,ok},{type,263,tuple,[{atom,263,error},{var,263,'Reason'}]}]}]},[{type,264,constraint,[{atom,264,is_subtype},[{var,264,'File'},{user_type,264,name_all,[]}]]},{type,265,constraint,[{atom,265,is_subtype},[{var,265,'Reason'},{type,265,union,[{user_type,265,posix,[]},{atom,265,badarg}]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,delete,2},[{file,[102,105,108,101,46,101,114,108]},{location,221}],[<<100,101,108,101,116,101,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,50,54>>,equiv => {function,delete,1},signature => [{attribute,221,spec,{{delete,2},[{type,221,bounded_fun,[{type,221,'fun',[{type,221,product,[{var,221,'Filename'},{var,221,'Opts'}]},{type,221,union,[{atom,221,ok},{type,221,tuple,[{atom,221,error},{var,221,'Reason'}]}]}]},[{type,222,constraint,[{atom,222,is_subtype},[{var,222,'Filename'},{user_type,222,name_all,[]}]]},{type,223,constraint,[{atom,223,is_subtype},[{var,223,'Opts'},{type,223,list,[{user_type,223,delete_option,[]}]}]]},{type,224,constraint,[{atom,224,is_subtype},[{var,224,'Reason'},{type,224,union,[{user_type,224,posix,[]},{atom,224,badarg}]}]]}]]}]}}]}},{{function,delete,1},[{file,[102,105,108,101,46,101,114,108]},{location,214}],[<<100,101,108,101,116,101,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,101,108,101,116,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<84,114,105,101,115,32,116,111,32,100,101,108,101,116,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,46,32,84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,105,110,32,112,97,114,116,105,99,117,108,97,114,32,100,117,114,105,110,103,32,116,104,101,32,101,97,114,108,121,32,98,111,111,116,32,115,116,97,103,101,32,119,104,101,110,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,121,101,116,32,114,101,103,105,115,116,101,114,101,100,44,32,116,111,32,115,116,105,108,108,32,98,101,32,97,98,108,101,32,116,111,32,100,101,108,101,116,101,32,108,111,99,97,108,32,102,105,108,101,115,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,116,104,101,32,102,105,108,101,32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,115,46>>]}]},{dt,[],[{code,[],[<<101,112,101,114,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,32,97,110,100,32,116,104,101,32,117,115,101,114,32,105,115,32,110,111,116,32,115,117,112,101,114,117,115,101,114,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,104,97,115,32,97,110,32,105,109,112,114,111,112,101,114,32,116,121,112,101,44,32,115,117,99,104,32,97,115,32,116,117,112,108,101,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,44,32,97,32,98,97,100,32,116,121,112,101,32,102,111,114,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,119,105,108,108,32,112,114,111,98,97,98,108,121,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,50,54>>,signature => [{attribute,214,spec,{{delete,1},[{type,214,bounded_fun,[{type,214,'fun',[{type,214,product,[{var,214,'Filename'}]},{type,214,union,[{atom,214,ok},{type,214,tuple,[{atom,214,error},{var,214,'Reason'}]}]}]},[{type,215,constraint,[{atom,215,is_subtype},[{var,215,'Filename'},{user_type,215,name_all,[]}]]},{type,216,constraint,[{atom,216,is_subtype},[{var,216,'Reason'},{type,216,union,[{user_type,216,posix,[]},{atom,216,badarg}]}]]}]]}]}}]}},{{function,eval,1},[{file,[102,105,108,101,46,101,114,108]},{location,1065}],[<<101,118,97,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,32,102,114,111,109,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,84,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,32,105,115,32,110,111,116,32,114,101,116,117,114,110,101,100,59,32,97,110,121,32,101,120,112,114,101,115,115,105,111,110,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,102,105,108,101,32,109,117,115,116,32,98,101,32,116,104,101,114,101,32,102,111,114,32,105,116,115,32,115,105,100,101,32,101,102,102,101,99,116,46,32,82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<111,107>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,119,97,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,84,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,44,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,54,57>>,signature => [{attribute,1065,spec,{{eval,1},[{type,1065,bounded_fun,[{type,1065,'fun',[{type,1065,product,[{var,1065,'Filename'}]},{type,1065,union,[{atom,1065,ok},{type,1065,tuple,[{atom,1065,error},{var,1065,'Reason'}]}]}]},[{type,1066,constraint,[{atom,1066,is_subtype},[{var,1066,'Filename'},{user_type,1066,name_all,[]}]]},{type,1067,constraint,[{atom,1067,is_subtype},[{var,1067,'Reason'},{type,1067,union,[{user_type,1067,posix,[]},{atom,1067,badarg},{atom,1067,terminated},{atom,1067,system_limit},{type,1068,tuple,[{ann_type,1068,[{var,1068,'Line'},{type,1068,integer,[]}]},{ann_type,1068,[{var,1068,'Mod'},{type,1068,module,[]}]},{ann_type,1068,[{var,1068,'Term'},{type,1068,term,[]}]}]}]}]]}]]}]}}]}},{{function,eval,2},[{file,[102,105,108,101,46,101,114,108]},{location,1073}],[<<101,118,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<101,118,97,108,47,49>>]},<<44,32,98,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,32>>,{code,[],[<<66,105,110,100,105,110,103,115>>]},<<32,97,114,101,32,117,115,101,100,32,105,110,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,101,114,108,95,101,118,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,101,118,97,108,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,48,51>>,signature => [{attribute,1073,spec,{{eval,2},[{type,1073,bounded_fun,[{type,1073,'fun',[{type,1073,product,[{var,1073,'Filename'},{var,1073,'Bindings'}]},{type,1073,union,[{atom,1073,ok},{type,1073,tuple,[{atom,1073,error},{var,1073,'Reason'}]}]}]},[{type,1074,constraint,[{atom,1074,is_subtype},[{var,1074,'Filename'},{user_type,1074,name_all,[]}]]},{type,1075,constraint,[{atom,1075,is_subtype},[{var,1075,'Bindings'},{remote_type,1075,[{atom,1075,erl_eval},{atom,1075,binding_struct},[]]}]]},{type,1076,constraint,[{atom,1076,is_subtype},[{var,1076,'Reason'},{type,1076,union,[{user_type,1076,posix,[]},{atom,1076,badarg},{atom,1076,terminated},{atom,1076,system_limit},{type,1077,tuple,[{ann_type,1077,[{var,1077,'Line'},{type,1077,integer,[]}]},{ann_type,1077,[{var,1077,'Mod'},{type,1077,module,[]}]},{ann_type,1077,[{var,1077,'Term'},{type,1077,term,[]}]}]}]}]]}]]}]}}]}},{{function,format_error,1},[{file,[102,105,108,101,46,101,114,108]},{location,146}],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<71,105,118,101,110,32,116,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,32,114,101,116,117,114,110,101,100,32,98,121,32,97,110,121,32,102,117,110,99,116,105,111,110,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,114,101,116,117,114,110,115,32,97,32,100,101,115,99,114,105,112,116,105,118,101,32,115,116,114,105,110,103,32,111,102,32,116,104,101,32,101,114,114,111,114,32,105,110,32,69,110,103,108,105,115,104,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,49,51>>,signature => [{attribute,146,spec,{{format_error,1},[{type,146,bounded_fun,[{type,146,'fun',[{type,146,product,[{var,146,'Reason'}]},{var,146,'Chars'}]},[{type,147,constraint,[{atom,147,is_subtype},[{var,147,'Reason'},{type,147,union,[{user_type,147,posix,[]},{atom,147,badarg},{atom,147,terminated},{atom,147,system_limit},{type,148,tuple,[{ann_type,148,[{var,148,'Line'},{type,148,integer,[]}]},{ann_type,148,[{var,148,'Mod'},{type,148,module,[]}]},{ann_type,148,[{var,148,'Term'},{type,148,term,[]}]}]}]}]]},{type,149,constraint,[{atom,149,is_subtype},[{var,149,'Chars'},{type,149,string,[]}]]}]]}]}}]}},{{function,get_cwd,0},[{file,[102,105,108,101,46,101,114,108]},{location,191}],[<<103,101,116,95,99,119,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,68,105,114,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,114,97,114,101,32,99,105,114,99,117,109,115,116,97,110,99,101,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,110,32,102,97,105,108,32,111,110,32,85,110,105,120,46,32,73,116,32,99,97,110,32,111,99,99,117,114,32,105,102,32,114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,100,105,114,101,99,116,111,114,121,46>>]}]},{p,[],[<<65,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,115,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,100,105,114,101,99,116,111,114,121,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,50,49>>,signature => [{attribute,191,spec,{{get_cwd,0},[{type,191,bounded_fun,[{type,191,'fun',[{type,191,product,[]},{type,191,union,[{type,191,tuple,[{atom,191,ok},{var,191,'Dir'}]},{type,191,tuple,[{atom,191,error},{var,191,'Reason'}]}]}]},[{type,192,constraint,[{atom,192,is_subtype},[{var,192,'Dir'},{user_type,192,filename,[]}]]},{type,193,constraint,[{atom,193,is_subtype},[{var,193,'Reason'},{user_type,193,posix,[]}]]}]]}]}}]}},{{function,get_cwd,1},[{file,[102,105,108,101,46,101,114,108]},{location,198}],[<<103,101,116,95,99,119,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,68,105,114,125>>]},<<32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,100,114,105,118,101,46>>]},{p,[],[{code,[],[<<68,114,105,118,101>>]},<<32,105,115,32,116,111,32,98,101,32,111,102,32,116,104,101,32,102,111,114,109,32,34>>,{code,[],[<<76,101,116,116,101,114>>]},{code,[],[<<58>>]},<<34,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,34,99,58,34,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,116,115,117,112,125>>]},<<32,111,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,104,97,118,101,32,110,111,32,99,111,110,99,101,112,116,32,111,102,32,99,117,114,114,101,110,116,32,100,114,105,118,101,32,40,85,110,105,120,44,32,102,111,114,32,101,120,97,109,112,108,101,41,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,104,97,115,32,110,111,32,99,111,110,99,101,112,116,32,111,102,32,100,114,105,118,101,115,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,114,105,118,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,111,114,109,97,116,32,111,102,32>>,{code,[],[<<68,114,105,118,101>>]},<<32,105,115,32,105,110,118,97,108,105,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,52,51>>,signature => [{attribute,198,spec,{{get_cwd,1},[{type,198,bounded_fun,[{type,198,'fun',[{type,198,product,[{var,198,'Drive'}]},{type,198,union,[{type,198,tuple,[{atom,198,ok},{var,198,'Dir'}]},{type,198,tuple,[{atom,198,error},{var,198,'Reason'}]}]}]},[{type,199,constraint,[{atom,199,is_subtype},[{var,199,'Drive'},{type,199,string,[]}]]},{type,200,constraint,[{atom,200,is_subtype},[{var,200,'Dir'},{user_type,200,filename,[]}]]},{type,201,constraint,[{atom,201,is_subtype},[{var,201,'Reason'},{type,201,union,[{user_type,201,posix,[]},{atom,201,badarg}]}]]}]]}]}}]}},{{function,list_dir,1},[{file,[102,105,108,101,46,101,114,108]},{location,401}],[<<108,105,115,116,95,100,105,114,47,49>>],#{<<101,110>> => [{p,[],[<<76,105,115,116,115,32,97,108,108,32,102,105,108,101,115,32,105,110,32,97,32,100,105,114,101,99,116,111,114,121,44,32>>,{em,[],[<<101,120,99,101,112,116>>]},<<32,102,105,108,101,115,32,119,105,116,104,32,114,97,119,32,102,105,108,101,110,97,109,101,115,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,115,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,110,97,109,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,116,104,101,32,102,105,108,101,115,32,105,110,32,116,104,101,32,100,105,114,101,99,116,111,114,121,46,32,84,104,101,32,110,97,109,101,115,32,97,114,101,32,110,111,116,32,115,111,114,116,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32>>,{code,[],[<<68,105,114>>]},<<32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<123,110,111,95,116,114,97,110,115,108,97,116,105,111,110,44,32,70,105,108,101,110,97,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,32>>,{code,[],[<<98,105,110,97,114,121,40,41>>]},<<32,119,105,116,104,32,99,104,97,114,97,99,116,101,114,115,32,99,111,100,101,100,32,105,110,32,73,83,79,32,76,97,116,105,110,45,49,32,97,110,100,32,116,104,101,32,86,77,32,119,97,115,32,115,116,97,114,116,101,100,32,119,105,116,104,32,112,97,114,97,109,101,116,101,114,32>>,{code,[],[<<43,102,110,117,101>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,55,52>>,signature => [{attribute,401,spec,{{list_dir,1},[{type,401,bounded_fun,[{type,401,'fun',[{type,401,product,[{var,401,'Dir'}]},{type,401,union,[{type,401,tuple,[{atom,401,ok},{var,401,'Filenames'}]},{type,401,tuple,[{atom,401,error},{var,401,'Reason'}]}]}]},[{type,402,constraint,[{atom,402,is_subtype},[{var,402,'Dir'},{user_type,402,name_all,[]}]]},{type,403,constraint,[{atom,403,is_subtype},[{var,403,'Filenames'},{type,403,list,[{user_type,403,filename,[]}]}]]},{type,404,constraint,[{atom,404,is_subtype},[{var,404,'Reason'},{type,404,union,[{user_type,404,posix,[]},{atom,405,badarg},{type,406,tuple,[{atom,406,no_translation},{ann_type,406,[{var,406,'Filename'},{remote_type,406,[{atom,406,unicode},{atom,406,latin1_binary},[]]}]}]}]}]]}]]}]}}]}},{{function,list_dir_all,1},[{file,[102,105,108,101,46,101,114,108]},{location,411}],[<<108,105,115,116,95,100,105,114,95,97,108,108,47,49>>],#{<<101,110>> => [{p,[],[{a,[{id,<<108,105,115,116,95,100,105,114,95,97,108,108>>}],[]},<<76,105,115,116,115,32,97,108,108,32,116,104,101,32,102,105,108,101,115,32,105,110,32,97,32,100,105,114,101,99,116,111,114,121,44,32,105,110,99,108,117,100,105,110,103,32,102,105,108,101,115,32,119,105,116,104,32,114,97,119,32,102,105,108,101,110,97,109,101,115,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,115,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,110,97,109,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,116,104,101,32,102,105,108,101,115,32,105,110,32,116,104,101,32,100,105,114,101,99,116,111,114,121,46,32,84,104,101,32,110,97,109,101,115,32,97,114,101,32,110,111,116,32,115,111,114,116,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32>>,{code,[],[<<68,105,114>>]},<<32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,48,53>>,signature => [{attribute,411,spec,{{list_dir_all,1},[{type,411,bounded_fun,[{type,411,'fun',[{type,411,product,[{var,411,'Dir'}]},{type,411,union,[{type,411,tuple,[{atom,411,ok},{var,411,'Filenames'}]},{type,411,tuple,[{atom,411,error},{var,411,'Reason'}]}]}]},[{type,412,constraint,[{atom,412,is_subtype},[{var,412,'Dir'},{user_type,412,name_all,[]}]]},{type,413,constraint,[{atom,413,is_subtype},[{var,413,'Filenames'},{type,413,list,[{user_type,413,filename_all,[]}]}]]},{type,414,constraint,[{atom,414,is_subtype},[{var,414,'Reason'},{type,414,union,[{user_type,414,posix,[]},{atom,414,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,make_dir,1},[{file,[102,105,108,101,46,101,114,108]},{location,249}],[<<109,97,107,101,95,100,105,114,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,99,114,101,97,116,101,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<68,105,114>>]},<<46,32,77,105,115,115,105,110,103,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,99,114,101,97,116,101,100,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,100,32>>,{code,[],[<<68,105,114>>]},<<32,101,120,105,115,116,115,32,97,108,114,101,97,100,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,99,101,32,105,115,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,51,48>>,signature => [{attribute,249,spec,{{make_dir,1},[{type,249,bounded_fun,[{type,249,'fun',[{type,249,product,[{var,249,'Dir'}]},{type,249,union,[{atom,249,ok},{type,249,tuple,[{atom,249,error},{var,249,'Reason'}]}]}]},[{type,250,constraint,[{atom,250,is_subtype},[{var,250,'Dir'},{user_type,250,name_all,[]}]]},{type,251,constraint,[{atom,251,is_subtype},[{var,251,'Reason'},{type,251,union,[{user_type,251,posix,[]},{atom,251,badarg}]}]]}]]}]}}]}},{{function,make_link,2},[{file,[102,105,108,101,46,101,114,108]},{location,427}],[<<109,97,107,101,95,108,105,110,107,47,50>>],#{<<101,110>> => [{p,[],[<<77,97,107,101,115,32,97,32,104,97,114,100,32,108,105,110,107,32,102,114,111,109,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,116,111,32>>,{code,[],[<<78,101,119>>]},<<32,111,110,32,112,108,97,116,102,111,114,109,115,32,115,117,112,112,111,114,116,105,110,103,32,108,105,110,107,115,32,40,85,110,105,120,32,97,110,100,32,87,105,110,100,111,119,115,41,46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,116,104,101,32,108,105,110,107,32,119,97,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,99,114,101,97,116,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,110,111,116,32,115,117,112,112,111,114,116,105,110,103,32,108,105,110,107,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,101,110,111,116,115,117,112,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,111,114,32>>,{code,[],[<<78,101,119>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[{code,[],[<<78,101,119>>]},<<32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<72,97,114,100,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,54,52>>,signature => [{attribute,427,spec,{{make_link,2},[{type,427,bounded_fun,[{type,427,'fun',[{type,427,product,[{var,427,'Existing'},{var,427,'New'}]},{type,427,union,[{atom,427,ok},{type,427,tuple,[{atom,427,error},{var,427,'Reason'}]}]}]},[{type,428,constraint,[{atom,428,is_subtype},[{var,428,'Existing'},{user_type,428,name_all,[]}]]},{type,429,constraint,[{atom,429,is_subtype},[{var,429,'New'},{user_type,429,name_all,[]}]]},{type,430,constraint,[{atom,430,is_subtype},[{var,430,'Reason'},{type,430,union,[{user_type,430,posix,[]},{atom,430,badarg}]}]]}]]}]}}]}},{{function,make_symlink,2},[{file,[102,105,108,101,46,101,114,108]},{location,435}],[<<109,97,107,101,95,115,121,109,108,105,110,107,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32>>,{code,[],[<<78,101,119>>]},<<32,116,111,32,116,104,101,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,111,110,32,112,108,97,116,102,111,114,109,115,32,115,117,112,112,111,114,116,105,110,103,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,32,40,109,111,115,116,32,85,110,105,120,32,115,121,115,116,101,109,115,32,97,110,100,32,87,105,110,100,111,119,115,44,32,98,101,103,105,110,110,105,110,103,32,119,105,116,104,32,86,105,115,116,97,41,46,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,100,111,101,115,32,110,111,116,32,110,101,101,100,32,116,111,32,101,120,105,115,116,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,116,104,101,32,108,105,110,107,32,105,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,99,114,101,97,116,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,110,111,116,32,115,117,112,112,111,114,116,105,110,103,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,116,115,117,112,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,111,114,32>>,{code,[],[<<78,101,119>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[{code,[],[<<78,101,119>>]},<<32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]},{dt,[],[{code,[],[<<101,112,101,114,109>>]}]},{dd,[],[{p,[],[<<85,115,101,114,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,112,114,105,118,105,108,101,103,101,115,32,116,111,32,99,114,101,97,116,101,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,32,40>>,{code,[],[<<83,101,67,114,101,97,116,101,83,121,109,98,111,108,105,99,76,105,110,107,80,114,105,118,105,108,101,103,101>>]},<<32,111,110,32,87,105,110,100,111,119,115,41,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,57,51>>,signature => [{attribute,435,spec,{{make_symlink,2},[{type,435,bounded_fun,[{type,435,'fun',[{type,435,product,[{var,435,'Existing'},{var,435,'New'}]},{type,435,union,[{atom,435,ok},{type,435,tuple,[{atom,435,error},{var,435,'Reason'}]}]}]},[{type,436,constraint,[{atom,436,is_subtype},[{var,436,'Existing'},{user_type,436,name_all,[]}]]},{type,437,constraint,[{atom,437,is_subtype},[{var,437,'New'},{user_type,437,name_all,[]}]]},{type,438,constraint,[{atom,438,is_subtype},[{var,438,'Reason'},{type,438,union,[{user_type,438,posix,[]},{atom,438,badarg}]}]]}]]}]}}]}},{{function,native_name_encoding,0},[{file,[102,105,108,101,46,101,114,108]},{location,135}],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>],#{<<101,110>> => [{p,[],[{a,[{id,<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103>>}],[]},<<82,101,116,117,114,110,115,32,116,104,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,109,111,100,101,46,32,73,102,32,105,116,32,105,115,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,116,104,101,32,115,121,115,116,101,109,32,116,114,97,110,115,108,97,116,101,115,32,110,111,32,102,105,108,101,110,97,109,101,115,46,32,73,102,32,105,116,32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<44,32,102,105,108,101,110,97,109,101,115,32,97,114,101,32,99,111,110,118,101,114,116,101,100,32,98,97,99,107,32,97,110,100,32,102,111,114,116,104,32,116,111,32,116,104,101,32,110,97,116,105,118,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,40,117,115,117,97,108,108,121,32,85,84,70,45,56,44,32,98,117,116,32,85,84,70,45,49,54,32,111,110,32,87,105,110,100,111,119,115,41,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,55,50,57>>,signature => [{attribute,135,spec,{{native_name_encoding,0},[{type,135,'fun',[{type,135,product,[]},{type,135,union,[{atom,135,latin1},{atom,135,utf8}]}]}]}}],since => <<79,84,80,32,82,49,52,66,48,49>>}},{{function,open,2},[{file,[102,105,108,101,46,101,114,108]},{location,510}],[<<111,112,101,110,47,50>>],#{<<101,110>> => [{p,[],[<<79,112,101,110,115,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101>>]},<<32,105,110,32,116,104,101,32,109,111,100,101,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32>>,{code,[],[<<77,111,100,101,115>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,99,111,110,116,97,105,110,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<114,101,97,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,44,32,119,104,105,99,104,32,109,117,115,116,32,101,120,105,115,116,44,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,114,101,97,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<119,114,105,116,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46,32,73,116,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,73,102,32,116,104,101,32,102,105,108,101,32,101,120,105,115,116,115,32,97,110,100,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,105,115,32,110,111,116,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{code,[],[<<114,101,97,100>>]},<<44,32,116,104,101,32,102,105,108,101,32,105,115,32,116,114,117,110,99,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<97,112,112,101,110,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46,32,73,116,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,69,118,101,114,121,32,119,114,105,116,101,32,111,112,101,114,97,116,105,111,110,32,116,111,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<97,112,112,101,110,100>>]},<<32,116,97,107,101,115,32,112,108,97,99,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<101,120,99,108,117,115,105,118,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46,32,73,116,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,73,102,32,116,104,101,32,102,105,108,101,32,101,120,105,115,116,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,101,120,105,115,116,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,100,111,101,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,32,101,120,99,108,117,115,105,118,101,110,101,115,115,32,111,110,32,102,105,108,101,32,115,121,115,116,101,109,115,32,110,111,116,32,115,117,112,112,111,114,116,105,110,103,32>>,{code,[],[<<79,95,69,88,67,76>>]},<<32,112,114,111,112,101,114,108,121,44,32,115,117,99,104,32,97,115,32,78,70,83,46,32,68,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,115,117,112,112,111,114,116,115,32,105,116,32,40,105,110,32,103,101,110,101,114,97,108,44,32,108,111,99,97,108,32,102,105,108,101,32,115,121,115,116,101,109,115,32,97,114,101,32,115,97,102,101,41,46>>]}]}]},{dt,[],[{code,[],[<<114,97,119>>]}]},{dd,[],[{p,[],[{a,[{id,<<114,97,119>>}],[]},<<65,108,108,111,119,115,32,102,97,115,116,101,114,32,97,99,99,101,115,115,32,116,111,32,97,32,102,105,108,101,44,32,97,115,32,110,111,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,101,101,100,101,100,32,116,111,32,104,97,110,100,108,101,32,116,104,101,32,102,105,108,101,46,32,72,111,119,101,118,101,114,44,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32,116,104,105,115,32,119,97,121,32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,108,105,109,105,116,97,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32>>,{code,[],[<<105,111>>]},<<32,109,111,100,117,108,101,32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,44,32,97,115,32,116,104,101,121,32,99,97,110,32,111,110,108,121,32,116,97,108,107,32,116,111,32,97,110,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,46,32,73,110,115,116,101,97,100,44,32,117,115,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<46>>]}]},{li,[],[{p,[],[<<69,115,112,101,99,105,97,108,108,121,32,105,102,32>>,{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]},<<32,105,115,32,116,111,32,98,101,32,117,115,101,100,32,111,110,32,97,32>>,{code,[],[<<114,97,119>>]},<<32,102,105,108,101,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,99,111,109,98,105,110,101,32,116,104,105,115,32,111,112,116,105,111,110,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,97,115,32,108,105,110,101,45,111,114,105,101,110,116,101,100,32,73,47,79,32,105,115,32,105,110,101,102,102,105,99,105,101,110,116,32,119,105,116,104,111,117,116,32,98,117,102,102,101,114,105,110,103,46>>]}]},{li,[],[{p,[],[<<79,110,108,121,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,116,104,97,116,32,111,112,101,110,101,100,32,116,104,101,32,102,105,108,101,32,99,97,110,32,117,115,101,32,105,116,46>>]}]},{li,[],[{p,[],[<<65,32,114,101,109,111,116,101,32,69,114,108,97,110,103,32,102,105,108,101,32,115,101,114,118,101,114,32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,46,32,84,104,101,32,99,111,109,112,117,116,101,114,32,111,110,32,119,104,105,99,104,32,116,104,101,32,69,114,108,97,110,103,32,110,111,100,101,32,105,115,32,114,117,110,110,105,110,103,32,109,117,115,116,32,104,97,118,101,32,97,99,99,101,115,115,32,116,111,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,40,100,105,114,101,99,116,108,121,32,111,114,32,116,104,114,111,117,103,104,32,78,70,83,41,46>>]}]}]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,111,112,101,114,97,116,105,111,110,115,32,111,110,32,116,104,101,32,102,105,108,101,32,114,101,116,117,114,110,32,98,105,110,97,114,105,101,115,32,114,97,116,104,101,114,32,116,104,97,110,32,108,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<123,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,83,105,122,101,44,32,68,101,108,97,121,125>>]}]},{dd,[],[{p,[],[<<68,97,116,97,32,105,110,32,115,117,98,115,101,113,117,101,110,116,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,32,105,115,32,98,117,102,102,101,114,101,100,32,117,110,116,105,108,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,32,97,114,101,32,98,117,102,102,101,114,101,100,44,32,111,114,32,117,110,116,105,108,32,116,104,101,32,111,108,100,101,115,116,32,98,117,102,102,101,114,101,100,32,100,97,116,97,32,105,115,32>>,{code,[],[<<68,101,108,97,121>>]},<<32,109,105,108,108,105,115,101,99,111,110,100,115,32,111,108,100,46,32,84,104,101,110,32,97,108,108,32,98,117,102,102,101,114,101,100,32,100,97,116,97,32,105,115,32,119,114,105,116,116,101,110,32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,46,32,84,104,101,32,98,117,102,102,101,114,101,100,32,100,97,116,97,32,105,115,32,97,108,115,111,32,102,108,117,115,104,101,100,32,98,101,102,111,114,101,32,115,111,109,101,32,111,116,104,101,114,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,32,116,104,97,110,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,105,115,32,101,120,101,99,117,116,101,100,46>>]},{p,[],[<<84,104,101,32,112,117,114,112,111,115,101,32,111,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,116,111,32,105,110,99,114,101,97,115,101,32,112,101,114,102,111,114,109,97,110,99,101,32,98,121,32,114,101,100,117,99,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,115,46,32,84,104,117,115,44,32,116,104,101,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,32,109,117,115,116,32,98,101,32,102,111,114,32,115,105,122,101,115,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<44,32,97,110,100,32,110,111,116,32,105,110,116,101,114,115,112,101,114,115,101,100,32,98,121,32,116,111,111,32,109,97,110,121,32,111,116,104,101,114,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,115,46>>]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,117,115,101,100,44,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,32,99,97,110,32,112,114,101,109,97,116,117,114,101,108,121,32,98,101,32,114,101,112,111,114,116,101,100,32,97,115,32,115,117,99,99,101,115,115,102,117,108,44,32,97,110,100,32,105,102,32,97,32,119,114,105,116,101,32,101,114,114,111,114,32,111,99,99,117,114,115,44,32,116,104,101,32,101,114,114,111,114,32,105,115,32,114,101,112,111,114,116,101,100,32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,110,101,120,116,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,110,111,116,32,101,120,101,99,117,116,101,100,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32>>,{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]},<<32,105,115,32,117,115,101,100,44,32,97,102,116,101,114,32,97,32,110,117,109,98,101,114,32,111,102,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,44,32>>,{code,[],[<<99,108,111,115,101,47,49>>]},<<32,99,97,110,32,114,101,116,117,114,110,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,115,112,99,125>>]},<<44,32,97,115,32,116,104,101,114,101,32,105,115,32,110,111,116,32,101,110,111,117,103,104,32,115,112,97,99,101,32,111,110,32,116,104,101,32,100,105,115,99,32,102,111,114,32,112,114,101,118,105,111,117,115,108,121,32,119,114,105,116,116,101,110,32,100,97,116,97,46,32>>,{code,[],[<<99,108,111,115,101,47,49>>]},<<32,109,117,115,116,32,112,114,111,98,97,98,108,121,32,98,101,32,99,97,108,108,101,100,32,97,103,97,105,110,44,32,97,115,32,116,104,101,32,102,105,108,101,32,105,115,32,115,116,105,108,108,32,111,112,101,110,46>>]}]},{dt,[],[{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<123,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,83,105,122,101,44,32,68,101,108,97,121,125>>]},<<32,119,105,116,104,32,114,101,97,115,111,110,97,98,108,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<83,105,122,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,108,97,121>>]},<<32,40,114,111,117,103,104,108,121,32,115,111,109,101,32,54,52,32,75,66,44,32,50,32,115,101,99,111,110,100,115,41,46>>]}]},{dt,[],[{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<65,99,116,105,118,97,116,101,115,32,114,101,97,100,32,100,97,116,97,32,98,117,102,102,101,114,105,110,103,46,32,73,102,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,99,97,108,108,115,32,97,114,101,32,102,111,114,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,44,32,114,101,97,100,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,97,114,101,32,115,116,105,108,108,32,112,101,114,102,111,114,109,101,100,32,102,111,114,32,98,108,111,99,107,115,32,111,102,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,46,32,84,104,101,32,101,120,116,114,97,32,100,97,116,97,32,105,115,32,98,117,102,102,101,114,101,100,32,97,110,100,32,114,101,116,117,114,110,101,100,32,105,110,32,115,117,98,115,101,113,117,101,110,116,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,99,97,108,108,115,44,32,103,105,118,105,110,103,32,97,32,112,101,114,102,111,114,109,97,110,99,101,32,103,97,105,110,32,97,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,115,32,105,115,32,114,101,100,117,99,101,100,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<114,101,97,100,95,97,104,101,97,100>>]},<<32,98,117,102,102,101,114,32,105,115,32,97,108,115,111,32,104,105,103,104,108,121,32,117,115,101,100,32,98,121,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]},<<32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,44,32,116,104,101,114,101,102,111,114,101,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,40,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,114,101,97,115,111,110,115,41,32,119,104,101,110,32,97,99,99,101,115,115,105,110,103,32,114,97,119,32,102,105,108,101,115,32,117,115,105,110,103,32,116,104,97,116,32,102,117,110,99,116,105,111,110,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,99,97,108,108,115,32,97,114,101,32,102,111,114,32,115,105,122,101,115,32,110,111,116,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,108,101,115,115,32,116,104,97,110,44,32,111,114,32,101,118,101,110,32,103,114,101,97,116,101,114,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,44,32,110,111,32,112,101,114,102,111,114,109,97,110,99,101,32,103,97,105,110,32,99,97,110,32,98,101,32,101,120,112,101,99,116,101,100,46>>]}]},{dt,[],[{code,[],[<<114,101,97,100,95,97,104,101,97,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,119,105,116,104,32,97,32,114,101,97,115,111,110,97,98,108,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<83,105,122,101>>]},<<32,40,114,111,117,103,104,108,121,32,115,111,109,101,32,54,52,32,75,66,41,46>>]}]},{dt,[],[{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,103,122,105,112,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,115,46,32,79,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,109,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{code,[],[<<114,101,97,100>>]},<<32,111,114,32>>,{code,[],[<<119,114,105,116,101>>]},<<44,32,98,117,116,32,110,111,116,32,98,111,116,104,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,102,105,108,101,32,115,105,122,101,32,111,98,116,97,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>]}]},<<32,100,111,101,115,32,112,114,111,98,97,98,108,121,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,97,100,32,102,114,111,109,32,97,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,110,99,111,100,105,110,103,44,32,69,110,99,111,100,105,110,103,125>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,116,104,101,32,102,105,108,101,32,112,101,114,102,111,114,109,32,97,117,116,111,109,97,116,105,99,32,116,114,97,110,115,108,97,116,105,111,110,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,111,32,97,110,100,32,102,114,111,109,32,97,32,115,112,101,99,105,102,105,99,32,40,85,110,105,99,111,100,101,41,32,101,110,99,111,100,105,110,103,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,100,97,116,97,32,115,117,112,112,108,105,101,100,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<32,111,114,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,115,116,105,108,108,32,105,115,32,98,121,116,101,45,111,114,105,101,110,116,101,100,59,32,116,104,105,115,32,111,112,116,105,111,110,32,100,101,110,111,116,101,115,32,111,110,108,121,32,104,111,119,32,100,97,116,97,32,105,115,32,115,116,111,114,101,100,32,105,110,32,116,104,101,32,100,105,115,107,32,102,105,108,101,46>>]},{p,[],[<<68,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,101,110,99,111,100,105,110,103,44,32,100,105,102,102,101,114,101,110,116,32,109,101,116,104,111,100,115,32,111,102,32,114,101,97,100,105,110,103,32,97,110,100,32,119,114,105,116,105,110,103,32,100,97,116,97,32,105,115,32,112,114,101,102,101,114,114,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,105,109,112,108,105,101,115,32,117,115,105,110,103,32,116,104,105,115,32,109,111,100,117,108,101,32,40>>,{code,[],[<<102,105,108,101>>]},<<41,32,102,111,114,32,114,101,97,100,105,110,103,32,97,110,100,32,119,114,105,116,105,110,103,32,100,97,116,97,32,97,115,32,116,104,101,32,105,110,116,101,114,102,97,99,101,115,32,112,114,111,118,105,100,101,100,32,104,101,114,101,32,119,111,114,107,32,119,105,116,104,32,98,121,116,101,45,111,114,105,101,110,116,101,100,32,100,97,116,97,46,32,85,115,105,110,103,32,111,116,104,101,114,32,40,85,110,105,99,111,100,101,41,32,101,110,99,111,100,105,110,103,115,32,109,97,107,101,115,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,102,117,110,99,116,105,111,110,115,32>>,{code,[],[<<103,101,116,95,99,104,97,114,115>>]},<<44,32>>,{code,[],[<<103,101,116,95,108,105,110,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<112,117,116,95,99,104,97,114,115>>]},<<32,109,111,114,101,32,115,117,105,116,97,98,108,101,44,32,97,115,32,116,104,101,121,32,99,97,110,32,119,111,114,107,32,119,105,116,104,32,116,104,101,32,102,117,108,108,32,85,110,105,99,111,100,101,32,114,97,110,103,101,46>>]},{p,[],[<<73,102,32,100,97,116,97,32,105,115,32,115,101,110,116,32,116,111,32,97,110,32>>,{code,[],[<<105,111,95,100,101,118,105,99,101,40,41>>]},<<32,105,110,32,97,32,102,111,114,109,97,116,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,99,111,110,118,101,114,116,101,100,32,116,111,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,101,110,99,111,100,105,110,103,44,32,111,114,32,105,102,32,100,97,116,97,32,105,115,32,114,101,97,100,32,98,121,32,97,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,114,101,116,117,114,110,115,32,100,97,116,97,32,105,110,32,97,32,102,111,114,109,97,116,32,116,104,97,116,32,99,97,110,110,111,116,32,99,111,112,101,32,119,105,116,104,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,114,97,110,103,101,32,111,102,32,116,104,101,32,100,97,116,97,44,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,32,97,110,100,32,116,104,101,32,102,105,108,101,32,105,115,32,99,108,111,115,101,100,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<108,97,116,105,110,49>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,101,110,99,111,100,105,110,103,46,32,66,121,116,101,115,32,115,117,112,112,108,105,101,100,32,116,111,32,116,104,101,32,102,105,108,101,44,32,116,104,97,116,32,105,115,44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<32,97,114,101,32,119,114,105,116,116,101,110,32,34,97,115,32,105,115,34,32,111,110,32,116,104,101,32,102,105,108,101,46,32,76,105,107,101,119,105,115,101,44,32,98,121,116,101,115,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,44,32,116,104,97,116,32,105,115,44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,97,114,101,32,114,101,116,117,114,110,101,100,32,34,97,115,32,105,115,34,46,32,73,102,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,105,115,32,117,115,101,100,32,102,111,114,32,119,114,105,116,105,110,103,44,32,116,104,101,32,102,105,108,101,32,99,97,110,32,111,110,108,121,32,99,111,112,101,32,119,105,116,104,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,117,112,32,116,111,32,99,111,100,101,32,112,111,105,110,116,32,50,53,53,32,40,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,114,97,110,103,101,41,46>>]}]},{dt,[],[{code,[],[<<117,110,105,99,111,100,101,32,111,114,32,117,116,102,56>>]}]},{dd,[],[{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,97,114,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,97,110,100,32,102,114,111,109,32,85,84,70,45,56,32,101,110,99,111,100,105,110,103,32,98,101,102,111,114,101,32,116,104,101,121,32,97,114,101,32,119,114,105,116,116,101,110,32,116,111,32,111,114,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46,32,65,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32,116,104,105,115,32,119,97,121,32,99,97,110,32,98,101,32,114,101,97,100,97,98,108,101,32,117,115,105,110,103,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<44,32,97,115,32,108,111,110,103,32,97,115,32,110,111,32,100,97,116,97,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,102,105,108,101,32,108,105,101,115,32,98,101,121,111,110,100,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,114,97,110,103,101,32,40,48,46,46,50,53,53,41,44,32,98,117,116,32,102,97,105,108,117,114,101,32,111,99,99,117,114,115,32,105,102,32,116,104,101,32,100,97,116,97,32,99,111,110,116,97,105,110,115,32,85,110,105,99,111,100,101,32,99,111,100,101,32,112,111,105,110,116,115,32,98,101,121,111,110,100,32,116,104,97,116,32,114,97,110,103,101,46,32,84,104,101,32,102,105,108,101,32,105,115,32,98,101,115,116,32,114,101,97,100,32,119,105,116,104,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32,85,110,105,99,111,100,101,32,97,119,97,114,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<46>>]},{p,[],[<<66,121,116,101,115,32,119,114,105,116,116,101,110,32,116,111,32,116,104,101,32,102,105,108,101,32,98,121,32,97,110,121,32,109,101,97,110,115,32,97,114,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,85,84,70,45,56,32,101,110,99,111,100,105,110,103,32,98,101,102,111,114,101,32,98,101,105,110,103,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,100,105,115,107,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<117,116,102,49,54,32,111,114,32,123,117,116,102,49,54,44,98,105,103,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,98,105,103,32,101,110,100,105,97,110,32,85,84,70,45,49,54,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]},{dt,[],[{code,[],[<<123,117,116,102,49,54,44,108,105,116,116,108,101,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,108,105,116,116,108,101,32,101,110,100,105,97,110,32,85,84,70,45,49,54,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]},{dt,[],[{code,[],[<<117,116,102,51,50,32,111,114,32,123,117,116,102,51,50,44,98,105,103,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,98,105,103,32,101,110,100,105,97,110,32,85,84,70,45,51,50,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]},{dt,[],[{code,[],[<<123,117,116,102,51,50,44,108,105,116,116,108,101,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,108,105,116,116,108,101,32,101,110,100,105,97,110,32,85,84,70,45,51,50,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]}]},{p,[],[<<84,104,101,32,69,110,99,111,100,105,110,103,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,102,111,114,32,97,32,102,105,108,101,32,34,111,110,32,116,104,101,32,102,108,121,34,32,98,121,32,117,115,105,110,103,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111,35,115,101,116,111,112,116,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,111,58,115,101,116,111,112,116,115,47,50>>]}]},<<46,32,83,111,32,97,32,102,105,108,101,32,99,97,110,32,98,101,32,97,110,97,108,121,122,101,100,32,105,110,32,108,97,116,105,110,49,32,101,110,99,111,100,105,110,103,32,102,111,114,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,66,79,77,44,32,112,111,115,105,116,105,111,110,101,100,32,98,101,121,111,110,100,32,116,104,101,32,66,79,77,32,97,110,100,32,116,104,101,110,32,98,101,32,115,101,116,32,102,111,114,32,116,104,101,32,114,105,103,104,116,32,101,110,99,111,100,105,110,103,32,98,101,102,111,114,101,32,102,117,114,116,104,101,114,32,114,101,97,100,105,110,103,46,32,70,111,114,32,102,117,110,99,116,105,111,110,115,32,105,100,101,110,116,105,102,121,105,110,103,32,66,79,77,115,44,32,115,101,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,117,110,105,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,105,99,111,100,101,40,51,41>>]}]},<<46>>]},{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,102,105,108,101,115,46>>]}]},{dt,[],[{code,[],[<<114,97,109>>]}]},{dd,[],[{p,[],[{code,[],[<<70,105,108,101>>]},<<32,109,117,115,116,32,98,101,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<46,32,82,101,116,117,114,110,115,32,97,110,32>>,{code,[],[<<102,100,40,41>>]},<<44,32,119,104,105,99,104,32,108,101,116,115,32,109,111,100,117,108,101,32>>,{code,[],[<<102,105,108,101>>]},<<32,111,112,101,114,97,116,101,32,111,110,32,116,104,101,32,100,97,116,97,32,105,110,45,109,101,109,111,114,121,32,97,115,32,105,102,32,105,116,32,105,115,32,97,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<115,121,110,99>>]}]},{dd,[],[{p,[],[<<79,110,32,112,108,97,116,102,111,114,109,115,32,115,117,112,112,111,114,116,105,110,103,32,105,116,44,32,101,110,97,98,108,101,115,32,116,104,101,32,80,79,83,73,88,32>>,{code,[],[<<79,95,83,89,78,67>>]},<<32,115,121,110,99,104,114,111,110,111,117,115,32,73,47,79,32,102,108,97,103,32,111,114,32,105,116,115,32,112,108,97,116,102,111,114,109,45,100,101,112,101,110,100,101,110,116,32,101,113,117,105,118,97,108,101,110,116,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<70,73,76,69,95,70,76,65,71,95,87,82,73,84,69,95,84,72,82,79,85,71,72>>]},<<32,111,110,32,87,105,110,100,111,119,115,41,32,115,111,32,116,104,97,116,32,119,114,105,116,101,115,32,116,111,32,116,104,101,32,102,105,108,101,32,98,108,111,99,107,32,117,110,116,105,108,32,116,104,101,32,100,97,116,97,32,105,115,32,112,104,121,115,105,99,97,108,108,121,32,119,114,105,116,116,101,110,32,116,111,32,100,105,115,107,46,32,72,111,119,101,118,101,114,44,32,98,101,32,97,119,97,114,101,32,116,104,97,116,32,116,104,101,32,101,120,97,99,116,32,115,101,109,97,110,116,105,99,115,32,111,102,32,116,104,105,115,32,102,108,97,103,32,100,105,102,102,101,114,32,102,114,111,109,32,112,108,97,116,102,111,114,109,32,116,111,32,112,108,97,116,102,111,114,109,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,110,111,110,101,32,111,102,32,76,105,110,117,120,32,111,114,32,87,105,110,100,111,119,115,32,103,117,97,114,97,110,116,101,101,115,32,116,104,97,116,32,97,108,108,32,102,105,108,101,32,109,101,116,97,100,97,116,97,32,97,114,101,32,97,108,115,111,32,119,114,105,116,116,101,110,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,32,114,101,116,117,114,110,115,46,32,70,111,114,32,112,114,101,99,105,115,101,32,115,101,109,97,110,116,105,99,115,44,32,99,104,101,99,107,32,116,104,101,32,100,101,116,97,105,108,115,32,111,102,32,121,111,117,114,32,112,108,97,116,102,111,114,109,32,100,111,99,117,109,101,110,116,97,116,105,111,110,46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,119,105,116,104,32,110,111,32,115,117,112,112,111,114,116,32,102,111,114,32,80,79,83,73,88,32>>,{code,[],[<<79,95,83,89,78,67>>]},<<32,111,114,32,101,113,117,105,118,97,108,101,110,116,44,32,117,115,101,32,111,102,32,116,104,101,32>>,{code,[],[<<115,121,110,99>>]},<<32,102,108,97,103,32,99,97,117,115,101,115,32>>,{code,[],[<<111,112,101,110>>]},<<32,116,111,32,114,101,116,117,114,110,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,116,115,117,112,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<100,105,114,101,99,116,111,114,121>>]}]},{dd,[],[{p,[],[<<65,108,108,111,119,115,32>>,{code,[],[<<111,112,101,110>>]},<<32,116,111,32,119,111,114,107,32,111,110,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]}]},{p,[],[<<82,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,73,111,68,101,118,105,99,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,105,110,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,109,111,100,101,46,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,111,112,101,110,101,100,46>>]}]}]},{p,[],[{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,105,115,32,114,101,97,108,108,121,32,116,104,101,32,112,105,100,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,110,100,108,101,115,32,116,104,101,32,102,105,108,101,46,32,84,104,105,115,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,111,114,105,103,105,110,97,108,108,121,32,111,112,101,110,101,100,32,116,104,101,32,102,105,108,101,32,40,116,104,101,32,111,119,110,101,114,32,112,114,111,99,101,115,115,41,46,32,73,102,32,116,104,101,32,111,119,110,101,114,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,44,32,116,104,101,32,102,105,108,101,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,105,116,115,101,108,102,32,116,101,114,109,105,110,97,116,101,115,32,116,111,111,46,32,65,110,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,114,101,116,117,114,110,101,100,32,102,114,111,109,32,116,104,105,115,32,99,97,108,108,32,99,97,110,32,98,101,32,117,115,101,100,32,97,115,32,97,110,32,97,114,103,117,109,101,110,116,32,116,111,32,116,104,101,32,73,47,79,32,102,117,110,99,116,105,111,110,115,32,40,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,112,114,101,118,105,111,117,115,32,118,101,114,115,105,111,110,115,32,111,102,32>>,{code,[],[<<102,105,108,101>>]},<<44,32,109,111,100,101,115,32,119,101,114,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,111,110,101,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<114,101,97,100>>]},<<44,32>>,{code,[],[<<119,114,105,116,101>>]},<<44,32,111,114,32>>,{code,[],[<<114,101,97,100,95,119,114,105,116,101>>]},<<32,105,110,115,116,101,97,100,32,111,102,32,97,32,108,105,115,116,46,32,84,104,105,115,32,105,115,32,115,116,105,108,108,32,97,108,108,111,119,101,100,32,102,111,114,32,114,101,97,115,111,110,115,32,111,102,32,98,97,99,107,119,97,114,100,115,32,99,111,109,112,97,116,105,98,105,108,105,116,121,44,32,98,117,116,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,102,111,114,32,110,101,119,32,99,111,100,101,46,32,65,108,115,111,32,110,111,116,101,32,116,104,97,116,32>>,{code,[],[<<114,101,97,100,95,119,114,105,116,101>>]},<<32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,105,110,32,97,32,109,111,100,101,32,108,105,115,116,46>>]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,114,101,97,100,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,115,101,97,114,99,104,105,110,103,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,97,109,101,100,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,44,32,111,114,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,116,115,101,108,102,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,32,105,102,32>>,{code,[],[<<100,105,114,101,99,116,111,114,121>>]},<<32,109,111,100,101,32,119,97,115,32,115,112,101,99,105,102,105,101,100,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<84,104,101,114,101,32,105,115,32,110,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,32,40,105,102,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,97,99,99,101,115,115,32,119,97,115,32,115,112,101,99,105,102,105,101,100,41,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,55,52,49>>,signature => [{attribute,510,spec,{{open,2},[{type,510,bounded_fun,[{type,510,'fun',[{type,510,product,[{var,510,'File'},{var,510,'Modes'}]},{type,510,union,[{type,510,tuple,[{atom,510,ok},{var,510,'IoDevice'}]},{type,510,tuple,[{atom,510,error},{var,510,'Reason'}]}]}]},[{type,511,constraint,[{atom,511,is_subtype},[{var,511,'File'},{type,511,union,[{var,511,'Filename'},{type,511,iodata,[]}]}]]},{type,512,constraint,[{atom,512,is_subtype},[{var,512,'Filename'},{user_type,512,name_all,[]}]]},{type,513,constraint,[{atom,513,is_subtype},[{var,513,'Modes'},{type,513,list,[{type,513,union,[{user_type,513,mode,[]},{atom,513,ram},{atom,513,directory}]}]}]]},{type,514,constraint,[{atom,514,is_subtype},[{var,514,'IoDevice'},{user_type,514,io_device,[]}]]},{type,515,constraint,[{atom,515,is_subtype},[{var,515,'Reason'},{type,515,union,[{user_type,515,posix,[]},{atom,515,badarg},{atom,515,system_limit}]}]]}]]}]}}]}},{{function,path_consult,2},[{file,[102,105,108,101,46,101,114,108]},{location,1041}],[<<112,97,116,104,95,99,111,110,115,117,108,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,114,101,97,100,115,32,69,114,108,97,110,103,32,116,101,114,109,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,84,101,114,109,115,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,114,101,97,100,46,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,116,101,114,109,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,48,50,57>>,signature => [{attribute,1041,spec,{{path_consult,2},[{type,1041,bounded_fun,[{type,1041,'fun',[{type,1041,product,[{var,1041,'Path'},{var,1041,'Filename'}]},{type,1041,union,[{type,1041,tuple,[{atom,1041,ok},{var,1041,'Terms'},{var,1041,'FullName'}]},{type,1041,tuple,[{atom,1041,error},{var,1041,'Reason'}]}]}]},[{type,1042,constraint,[{atom,1042,is_subtype},[{var,1042,'Path'},{type,1042,list,[{var,1042,'Dir'}]}]]},{type,1043,constraint,[{atom,1043,is_subtype},[{var,1043,'Dir'},{user_type,1043,name_all,[]}]]},{type,1044,constraint,[{atom,1044,is_subtype},[{var,1044,'Filename'},{user_type,1044,name_all,[]}]]},{type,1045,constraint,[{atom,1045,is_subtype},[{var,1045,'Terms'},{type,1045,list,[{type,1045,term,[]}]}]]},{type,1046,constraint,[{atom,1046,is_subtype},[{var,1046,'FullName'},{user_type,1046,filename_all,[]}]]},{type,1047,constraint,[{atom,1047,is_subtype},[{var,1047,'Reason'},{type,1047,union,[{user_type,1047,posix,[]},{atom,1047,badarg},{atom,1047,terminated},{atom,1047,system_limit},{type,1048,tuple,[{ann_type,1048,[{var,1048,'Line'},{type,1048,integer,[]}]},{ann_type,1048,[{var,1048,'Mod'},{type,1048,module,[]}]},{ann_type,1048,[{var,1048,'Term'},{type,1048,term,[]}]}]}]}]]}]]}]}}]}},{{function,path_eval,2},[{file,[102,105,108,101,46,101,114,108]},{location,1089}],[<<112,97,116,104,95,101,118,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,114,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46,32,84,104,101,32,114,101,115,117,108,116,32,111,102,32,101,118,97,108,117,97,116,105,111,110,32,105,115,32,110,111,116,32,114,101,116,117,114,110,101,100,59,32,97,110,121,32,101,120,112,114,101,115,115,105,111,110,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,102,105,108,101,32,109,117,115,116,32,98,101,32,116,104,101,114,101,32,102,111,114,32,105,116,115,32,115,105,100,101,32,101,102,102,101,99,116,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,48,55,49>>,signature => [{attribute,1089,spec,{{path_eval,2},[{type,1089,bounded_fun,[{type,1089,'fun',[{type,1089,product,[{var,1089,'Path'},{var,1089,'Filename'}]},{type,1089,union,[{type,1089,tuple,[{atom,1089,ok},{var,1089,'FullName'}]},{type,1089,tuple,[{atom,1089,error},{var,1089,'Reason'}]}]}]},[{type,1090,constraint,[{atom,1090,is_subtype},[{var,1090,'Path'},{type,1090,list,[{ann_type,1090,[{var,1090,'Dir'},{user_type,1090,name_all,[]}]}]}]]},{type,1091,constraint,[{atom,1091,is_subtype},[{var,1091,'Filename'},{user_type,1091,name_all,[]}]]},{type,1092,constraint,[{atom,1092,is_subtype},[{var,1092,'FullName'},{user_type,1092,filename_all,[]}]]},{type,1093,constraint,[{atom,1093,is_subtype},[{var,1093,'Reason'},{type,1093,union,[{user_type,1093,posix,[]},{atom,1093,badarg},{atom,1093,terminated},{atom,1093,system_limit},{type,1094,tuple,[{ann_type,1094,[{var,1094,'Line'},{type,1094,integer,[]}]},{ann_type,1094,[{var,1094,'Mod'},{type,1094,module,[]}]},{ann_type,1094,[{var,1094,'Term'},{type,1094,term,[]}]}]}]}]]}]]}]}}]}},{{function,path_open,3},[{file,[102,105,108,101,46,101,114,108]},{location,1194}],[<<112,97,116,104,95,111,112,101,110,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,111,112,101,110,115,32,116,104,101,32,102,105,108,101,32,105,110,32,116,104,101,32,109,111,100,101,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32>>,{code,[],[<<77,111,100,101,115>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,73,111,68,101,118,105,99,101,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,105,110,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,109,111,100,101,46,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,102,105,108,101,32,97,110,100,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,111,112,101,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,49,49,55>>,signature => [{attribute,1194,spec,{{path_open,3},[{type,1194,bounded_fun,[{type,1194,'fun',[{type,1194,product,[{var,1194,'Path'},{var,1194,'Filename'},{var,1194,'Modes'}]},{type,1195,union,[{type,1195,tuple,[{atom,1195,ok},{var,1195,'IoDevice'},{var,1195,'FullName'}]},{type,1195,tuple,[{atom,1195,error},{var,1195,'Reason'}]}]}]},[{type,1196,constraint,[{atom,1196,is_subtype},[{var,1196,'Path'},{type,1196,list,[{ann_type,1196,[{var,1196,'Dir'},{user_type,1196,name_all,[]}]}]}]]},{type,1197,constraint,[{atom,1197,is_subtype},[{var,1197,'Filename'},{user_type,1197,name_all,[]}]]},{type,1198,constraint,[{atom,1198,is_subtype},[{var,1198,'Modes'},{type,1198,list,[{type,1198,union,[{user_type,1198,mode,[]},{atom,1198,directory}]}]}]]},{type,1199,constraint,[{atom,1199,is_subtype},[{var,1199,'IoDevice'},{user_type,1199,io_device,[]}]]},{type,1200,constraint,[{atom,1200,is_subtype},[{var,1200,'FullName'},{user_type,1200,filename_all,[]}]]},{type,1201,constraint,[{atom,1201,is_subtype},[{var,1201,'Reason'},{type,1201,union,[{user_type,1201,posix,[]},{atom,1201,badarg},{atom,1201,system_limit}]}]]}]]}]}}]}},{{function,path_script,2},[{file,[102,105,108,101,46,101,114,108]},{location,1149}],[<<112,97,116,104,95,115,99,114,105,112,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,114,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,86,97,108,117,101,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,32,97,110,100,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,108,97,115,116,32,101,120,112,114,101,115,115,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,49,52,54>>,signature => [{attribute,1149,spec,{{path_script,2},[{type,1149,bounded_fun,[{type,1149,'fun',[{type,1149,product,[{var,1149,'Path'},{var,1149,'Filename'}]},{type,1150,union,[{type,1150,tuple,[{atom,1150,ok},{var,1150,'Value'},{var,1150,'FullName'}]},{type,1150,tuple,[{atom,1150,error},{var,1150,'Reason'}]}]}]},[{type,1151,constraint,[{atom,1151,is_subtype},[{var,1151,'Path'},{type,1151,list,[{ann_type,1151,[{var,1151,'Dir'},{user_type,1151,name_all,[]}]}]}]]},{type,1152,constraint,[{atom,1152,is_subtype},[{var,1152,'Filename'},{user_type,1152,name_all,[]}]]},{type,1153,constraint,[{atom,1153,is_subtype},[{var,1153,'Value'},{type,1153,term,[]}]]},{type,1154,constraint,[{atom,1154,is_subtype},[{var,1154,'FullName'},{user_type,1154,filename_all,[]}]]},{type,1155,constraint,[{atom,1155,is_subtype},[{var,1155,'Reason'},{type,1155,union,[{user_type,1155,posix,[]},{atom,1155,badarg},{atom,1155,terminated},{atom,1155,system_limit},{type,1156,tuple,[{ann_type,1156,[{var,1156,'Line'},{type,1156,integer,[]}]},{ann_type,1156,[{var,1156,'Mod'},{type,1156,module,[]}]},{ann_type,1156,[{var,1156,'Term'},{type,1156,term,[]}]}]}]}]]}]]}]}}]}},{{function,path_script,3},[{file,[102,105,108,101,46,101,114,108]},{location,1161}],[<<112,97,116,104,95,115,99,114,105,112,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<112,97,116,104,95,115,99,114,105,112,116,47,50>>]},<<32,98,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,32>>,{code,[],[<<66,105,110,100,105,110,103,115>>]},<<32,97,114,101,32,117,115,101,100,32,105,110,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,101,114,108,95,101,118,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,101,118,97,108,40,51,41>>]}]},<<32,97,98,111,117,116,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,49,57,48>>,signature => [{attribute,1161,spec,{{path_script,3},[{type,1161,bounded_fun,[{type,1161,'fun',[{type,1161,product,[{var,1161,'Path'},{var,1161,'Filename'},{var,1161,'Bindings'}]},{type,1162,union,[{type,1162,tuple,[{atom,1162,ok},{var,1162,'Value'},{var,1162,'FullName'}]},{type,1162,tuple,[{atom,1162,error},{var,1162,'Reason'}]}]}]},[{type,1163,constraint,[{atom,1163,is_subtype},[{var,1163,'Path'},{type,1163,list,[{ann_type,1163,[{var,1163,'Dir'},{user_type,1163,name_all,[]}]}]}]]},{type,1164,constraint,[{atom,1164,is_subtype},[{var,1164,'Filename'},{user_type,1164,name_all,[]}]]},{type,1165,constraint,[{atom,1165,is_subtype},[{var,1165,'Bindings'},{remote_type,1165,[{atom,1165,erl_eval},{atom,1165,binding_struct},[]]}]]},{type,1166,constraint,[{atom,1166,is_subtype},[{var,1166,'Value'},{type,1166,term,[]}]]},{type,1167,constraint,[{atom,1167,is_subtype},[{var,1167,'FullName'},{user_type,1167,filename_all,[]}]]},{type,1168,constraint,[{atom,1168,is_subtype},[{var,1168,'Reason'},{type,1168,union,[{user_type,1168,posix,[]},{atom,1168,badarg},{atom,1168,terminated},{atom,1168,system_limit},{type,1169,tuple,[{ann_type,1169,[{var,1169,'Line'},{type,1169,integer,[]}]},{ann_type,1169,[{var,1169,'Mod'},{type,1169,module,[]}]},{ann_type,1169,[{var,1169,'Term'},{type,1169,term,[]}]}]}]}]]}]]}]}}]}},{{function,pid2name,1},[{file,[102,105,108,101,46,101,114,108]},{location,170}],[<<112,105,100,50,110,97,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,97,110,32,73,47,79,32,100,101,118,105,99,101,44,32,116,104,97,116,32,105,115,44,32,97,32,112,105,100,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<111,112,101,110,47,50>>]},<<44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,102,105,108,101,110,97,109,101,44,32,111,114,32,114,97,116,104,101,114,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,116,104,105,115,32,110,111,100,101,32,105,115,32,110,111,116,32,97,32,115,108,97,118,101,44,32,116,104,101,32,102,105,108,101,32,119,97,115,32,111,112,101,110,101,100,32,98,121,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,116,104,105,115,32,110,111,100,101,32,40,116,104,105,115,32,105,109,112,108,105,101,115,32,116,104,97,116,32>>,{code,[],[<<80,105,100>>]},<<32,109,117,115,116,32,98,101,32,97,32,108,111,99,97,108,32,112,105,100,41,32,97,110,100,32,116,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,99,108,111,115,101,100,46,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,110,32,102,108,97,116,32,115,116,114,105,110,103,32,102,111,114,109,97,116,46>>]}]},{dt,[],[{code,[],[<<117,110,100,101,102,105,110,101,100>>]}]},{dd,[],[{p,[],[<<73,110,32,97,108,108,32,111,116,104,101,114,32,99,97,115,101,115,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,48,48>>,signature => [{attribute,170,spec,{{pid2name,1},[{type,170,bounded_fun,[{type,170,'fun',[{type,170,product,[{var,170,'Pid'}]},{type,170,union,[{type,170,tuple,[{atom,170,ok},{var,170,'Filename'}]},{atom,170,undefined}]}]},[{type,171,constraint,[{atom,171,is_subtype},[{var,171,'Filename'},{user_type,171,filename_all,[]}]]},{type,172,constraint,[{atom,172,is_subtype},[{var,172,'Pid'},{type,172,pid,[]}]]}]]}]}}]}},{{function,position,2},[{file,[102,105,108,101,46,101,114,108]},{location,753}],[<<112,111,115,105,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,116,111,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,78,101,119,80,111,115,105,116,105,111,110,125>>]},<<32,40,97,115,32,97,98,115,111,108,117,116,101,32,111,102,102,115,101,116,41,32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<79,102,102,115,101,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<123,98,111,102,44,32,79,102,102,115,101,116,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,98,111,102,44,32,79,102,102,115,101,116,125>>]}]},{dd,[],[{p,[],[<<65,98,115,111,108,117,116,101,32,111,102,102,115,101,116,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,44,32,79,102,102,115,101,116,125>>]}]},{dd,[],[{p,[],[<<79,102,102,115,101,116,32,102,114,111,109,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,101,111,102,44,32,79,102,102,115,101,116,125>>]}]},{dd,[],[{p,[],[<<79,102,102,115,101,116,32,102,114,111,109,32,116,104,101,32,101,110,100,32,111,102,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<98,111,102,32,124,32,99,117,114,32,124,32,101,111,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,97,98,111,118,101,32,119,105,116,104,32>>,{code,[],[<<79,102,102,115,101,116>>]},<<32,48,46>>]}]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,111,102,102,115,101,116,115,32,97,114,101,32,99,111,117,110,116,101,100,32,105,110,32,98,121,116,101,115,44,32,110,111,116,32,105,110,32,99,104,97,114,97,99,116,101,114,115,46,32,73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,117,115,105,110,103,32,115,111,109,101,32,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,111,110,101,32,98,121,116,101,32,100,111,101,115,32,110,111,116,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,111,110,101,32,99,104,97,114,97,99,116,101,114,46,32,80,111,115,105,116,105,111,110,105,110,103,32,105,110,32,115,117,99,104,32,97,32,102,105,108,101,32,99,97,110,32,111,110,108,121,32,98,101,32,100,111,110,101,32,116,111,32,107,110,111,119,110,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,105,101,115,46,32,84,104,97,116,32,105,115,44,32,116,111,32,97,32,112,111,115,105,116,105,111,110,32,101,97,114,108,105,101,114,32,114,101,116,114,105,101,118,101,100,32,98,121,32,103,101,116,116,105,110,103,32,97,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,44,32,116,111,32,116,104,101,32,98,101,103,105,110,110,105,110,103,47,101,110,100,32,111,102,32,116,104,101,32,102,105,108,101,32,111,114,32,116,111,32,115,111,109,101,32,111,116,104,101,114,32,112,111,115,105,116,105,111,110,32>>,{em,[],[<<107,110,111,119,110>>]},<<32,116,111,32,98,101,32,111,110,32,97,32,99,111,114,114,101,99,116,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,32,98,121,32,115,111,109,101,32,111,116,104,101,114,32,109,101,97,110,115,32,40,116,121,112,105,99,97,108,108,121,32,98,101,121,111,110,100,32,97,32,98,121,116,101,32,111,114,100,101,114,32,109,97,114,107,32,105,110,32,116,104,101,32,102,105,108,101,44,32,119,104,105,99,104,32,104,97,115,32,97,32,107,110,111,119,110,32,98,121,116,101,45,115,105,122,101,41,46>>]},{p,[],[<<65,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,32,105,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[<<69,105,116,104,101,114,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,105,108,108,101,103,97,108,44,32,111,114,32,105,116,32,105,115,32,101,118,97,108,117,97,116,101,100,32,116,111,32,97,32,110,101,103,97,116,105,118,101,32,111,102,102,115,101,116,32,105,110,32,116,104,101,32,102,105,108,101,46,32,78,111,116,105,99,101,32,116,104,97,116,32,105,102,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,112,111,115,105,116,105,111,110,32,105,115,32,97,32,110,101,103,97,116,105,118,101,32,118,97,108,117,101,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,110,32,101,114,114,111,114,44,32,97,110,100,32,97,102,116,101,114,32,116,104,101,32,99,97,108,108,32,116,104,101,32,102,105,108,101,32,112,111,115,105,116,105,111,110,32,105,115,32,117,110,100,101,102,105,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,50,53>>,signature => [{attribute,753,spec,{{position,2},[{type,753,bounded_fun,[{type,753,'fun',[{type,753,product,[{var,753,'IoDevice'},{var,753,'Location'}]},{type,753,union,[{type,753,tuple,[{atom,753,ok},{var,753,'NewPosition'}]},{type,753,tuple,[{atom,753,error},{var,753,'Reason'}]}]}]},[{type,754,constraint,[{atom,754,is_subtype},[{var,754,'IoDevice'},{user_type,754,io_device,[]}]]},{type,755,constraint,[{atom,755,is_subtype},[{var,755,'Location'},{user_type,755,location,[]}]]},{type,756,constraint,[{atom,756,is_subtype},[{var,756,'NewPosition'},{type,756,integer,[]}]]},{type,757,constraint,[{atom,757,is_subtype},[{var,757,'Reason'},{type,757,union,[{user_type,757,posix,[]},{atom,757,badarg},{atom,757,terminated}]}]]}]]}]}}]}},{{function,pread,2},[{file,[102,105,108,101,46,101,114,108]},{location,632}],[<<112,114,101,97,100,47,50>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32>>,{code,[],[<<112,114,101,97,100,47,51>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,91,68,97,116,97,44,32,46,46,46,93,125>>]},<<32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<44,32,119,104,101,114,101,32,101,97,99,104,32>>,{code,[],[<<68,97,116,97>>]},<<44,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<112,114,101,97,100>>]},<<44,32,105,115,32,101,105,116,104,101,114,32,97,32,108,105,115,116,32,111,114,32,97,32,98,105,110,97,114,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109,111,100,101,32,111,102,32,116,104,101,32,102,105,108,101,44,32,111,114,32>>,{code,[],[<<101,111,102>>]},<<32,105,102,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,112,111,115,105,116,105,111,110,32,105,115,32,98,101,121,111,110,100,32,101,110,100,32,111,102,32,102,105,108,101,46>>]},{p,[],[<<65,115,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,121,116,101,45,111,102,102,115,101,116,44,32,116,97,107,101,32,115,112,101,99,105,97,108,32,99,97,117,116,105,111,110,32,119,104,101,110,32,119,111,114,107,105,110,103,32,119,105,116,104,32,102,105,108,101,115,32,119,104,101,114,101,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,97,115,32,110,111,116,32,101,118,101,114,121,32,98,121,116,101,32,112,111,115,105,116,105,111,110,32,105,115,32,97,32,118,97,108,105,100,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,32,111,110,32,115,117,99,104,32,97,32,102,105,108,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,55,55>>,signature => [{attribute,632,spec,{{pread,2},[{type,632,bounded_fun,[{type,632,'fun',[{type,632,product,[{var,632,'IoDevice'},{var,632,'LocNums'}]},{type,632,union,[{type,632,tuple,[{atom,632,ok},{var,632,'DataL'}]},{atom,632,eof},{type,632,tuple,[{atom,632,error},{var,632,'Reason'}]}]}]},[{type,633,constraint,[{atom,633,is_subtype},[{var,633,'IoDevice'},{user_type,633,io_device,[]}]]},{type,634,constraint,[{atom,634,is_subtype},[{var,634,'LocNums'},{type,634,list,[{type,634,tuple,[{ann_type,634,[{var,634,'Location'},{user_type,634,location,[]}]},{ann_type,634,[{var,634,'Number'},{type,634,non_neg_integer,[]}]}]}]}]]},{type,635,constraint,[{atom,635,is_subtype},[{var,635,'DataL'},{type,635,list,[{var,635,'Data'}]}]]},{type,636,constraint,[{atom,636,is_subtype},[{var,636,'Data'},{type,636,union,[{type,636,string,[]},{type,636,binary,[]},{atom,636,eof}]}]]},{type,637,constraint,[{atom,637,is_subtype},[{var,637,'Reason'},{type,637,union,[{user_type,637,posix,[]},{atom,637,badarg},{atom,637,terminated}]}]]}]]}]}}]}},{{function,pread,3},[{file,[102,105,108,101,46,101,114,108]},{location,660}],[<<112,114,101,97,100,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32>>,{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46>>]},{p,[],[{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,111,110,108,121,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,97,110,32,105,110,116,101,103,101,114,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,97,110,100,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,115,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,111,102,32,116,104,101,32,102,105,108,101,32,97,102,116,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,97,110,100,32,117,110,99,104,97,110,103,101,100,32,102,111,114,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,46>>]},{p,[],[<<65,115,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,121,116,101,45,111,102,102,115,101,116,44,32,116,97,107,101,32,115,112,101,99,105,97,108,32,99,97,117,116,105,111,110,32,119,104,101,110,32,119,111,114,107,105,110,103,32,119,105,116,104,32,102,105,108,101,115,32,119,104,101,114,101,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,97,115,32,110,111,116,32,101,118,101,114,121,32,98,121,116,101,32,112,111,115,105,116,105,111,110,32,105,115,32,97,32,118,97,108,105,100,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,32,111,110,32,115,117,99,104,32,97,32,102,105,108,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,57,53>>,signature => [{attribute,660,spec,{{pread,3},[{type,660,bounded_fun,[{type,660,'fun',[{type,660,product,[{var,660,'IoDevice'},{var,660,'Location'},{var,660,'Number'}]},{type,661,union,[{type,661,tuple,[{atom,661,ok},{var,661,'Data'}]},{atom,661,eof},{type,661,tuple,[{atom,661,error},{var,661,'Reason'}]}]}]},[{type,662,constraint,[{atom,662,is_subtype},[{var,662,'IoDevice'},{user_type,662,io_device,[]}]]},{type,663,constraint,[{atom,663,is_subtype},[{var,663,'Location'},{user_type,663,location,[]}]]},{type,664,constraint,[{atom,664,is_subtype},[{var,664,'Number'},{type,664,non_neg_integer,[]}]]},{type,665,constraint,[{atom,665,is_subtype},[{var,665,'Data'},{type,665,union,[{type,665,string,[]},{type,665,binary,[]}]}]]},{type,666,constraint,[{atom,666,is_subtype},[{var,666,'Reason'},{type,666,union,[{user_type,666,posix,[]},{atom,666,badarg},{atom,666,terminated}]}]]}]]}]}}]}},{{function,pwrite,2},[{file,[102,105,108,101,46,101,114,108]},{location,693}],[<<112,119,114,105,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32>>,{code,[],[<<112,119,114,105,116,101,47,51>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,123,78,44,32,82,101,97,115,111,110,125,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,117,99,99,101,115,115,102,117,108,32,119,114,105,116,101,115,32,100,111,110,101,32,98,101,102,111,114,101,32,116,104,101,32,102,97,105,108,117,114,101,46>>]},{p,[],[<<87,104,101,110,32,112,111,115,105,116,105,111,110,105,110,103,32,105,110,32,97,32,102,105,108,101,32,119,105,116,104,32,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,99,97,117,116,105,111,110,32,109,117,115,116,32,98,101,32,116,97,107,101,110,32,116,111,32,115,101,116,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,110,32,97,32,99,111,114,114,101,99,116,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,46,32,70,111,114,32,100,101,116,97,105,108,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,112,111,115,105,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,49,50>>,signature => [{attribute,693,spec,{{pwrite,2},[{type,693,bounded_fun,[{type,693,'fun',[{type,693,product,[{var,693,'IoDevice'},{var,693,'LocBytes'}]},{type,693,union,[{atom,693,ok},{type,693,tuple,[{atom,693,error},{type,693,tuple,[{var,693,'N'},{var,693,'Reason'}]}]}]}]},[{type,694,constraint,[{atom,694,is_subtype},[{var,694,'IoDevice'},{user_type,694,io_device,[]}]]},{type,695,constraint,[{atom,695,is_subtype},[{var,695,'LocBytes'},{type,695,list,[{type,695,tuple,[{ann_type,695,[{var,695,'Location'},{user_type,695,location,[]}]},{ann_type,695,[{var,695,'Bytes'},{type,695,iodata,[]}]}]}]}]]},{type,696,constraint,[{atom,696,is_subtype},[{var,696,'N'},{type,696,non_neg_integer,[]}]]},{type,697,constraint,[{atom,697,is_subtype},[{var,697,'Reason'},{type,697,union,[{user_type,697,posix,[]},{atom,697,badarg},{atom,697,terminated}]}]]}]]}]}}]}},{{function,pwrite,3},[{file,[102,105,108,101,46,101,114,108]},{location,718}],[<<112,119,114,105,116,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32>>,{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]},<<32,97,110,100,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46>>]},{p,[],[{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,111,110,108,121,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,97,110,32,105,110,116,101,103,101,114,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,97,110,100,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,115,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,111,102,32,116,104,101,32,102,105,108,101,32,97,102,116,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,97,110,100,32,117,110,99,104,97,110,103,101,100,32,102,111,114,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,46>>]},{p,[],[<<87,104,101,110,32,112,111,115,105,116,105,111,110,105,110,103,32,105,110,32,97,32,102,105,108,101,32,119,105,116,104,32,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,99,97,117,116,105,111,110,32,109,117,115,116,32,98,101,32,116,97,107,101,110,32,116,111,32,115,101,116,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,110,32,97,32,99,111,114,114,101,99,116,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,46,32,70,111,114,32,100,101,116,97,105,108,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,112,111,115,105,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,50,55>>,signature => [{attribute,718,spec,{{pwrite,3},[{type,718,bounded_fun,[{type,718,'fun',[{type,718,product,[{var,718,'IoDevice'},{var,718,'Location'},{var,718,'Bytes'}]},{type,718,union,[{atom,718,ok},{type,718,tuple,[{atom,718,error},{var,718,'Reason'}]}]}]},[{type,719,constraint,[{atom,719,is_subtype},[{var,719,'IoDevice'},{user_type,719,io_device,[]}]]},{type,720,constraint,[{atom,720,is_subtype},[{var,720,'Location'},{user_type,720,location,[]}]]},{type,721,constraint,[{atom,721,is_subtype},[{var,721,'Bytes'},{type,721,iodata,[]}]]},{type,722,constraint,[{atom,722,is_subtype},[{var,722,'Reason'},{type,722,union,[{user_type,722,posix,[]},{atom,722,badarg},{atom,722,terminated}]}]]}]]}]}}]}},{{function,read,2},[{file,[102,105,108,101,46,101,114,108]},{location,590}],[<<114,101,97,100,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,98,121,116,101,115,47,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,84,104,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,112,114,101,97,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,101,97,100,47,51>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]}]},<<32,97,114,101,32,116,104,101,32,111,110,108,121,32,119,97,121,115,32,116,111,32,114,101,97,100,32,102,114,111,109,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,40,97,108,116,104,111,117,103,104,32,116,104,101,121,32,119,111,114,107,32,102,111,114,32,110,111,114,109,97,108,108,121,32,111,112,101,110,101,100,32,102,105,108,101,115,44,32,116,111,111,41,46>>]},{p,[],[<<70,111,114,32,102,105,108,101,115,32,119,104,101,114,101,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,111,110,101,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,121,116,101,32,111,110,32,116,104,101,32,102,105,108,101,46,32,84,104,101,32,112,97,114,97,109,101,116,101,114,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,97,108,119,97,121,115,32,100,101,110,111,116,101,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{em,[],[<<99,104,97,114,97,99,116,101,114,115>>]},<<32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,44,32,119,104,105,108,101,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,102,105,108,101,32,99,97,110,32,98,101,32,109,111,118,101,100,32,109,117,99,104,32,109,111,114,101,32,116,104,97,110,32,116,104,105,115,32,110,117,109,98,101,114,32,119,104,101,110,32,114,101,97,100,105,110,103,32,97,32,85,110,105,99,111,100,101,32,102,105,108,101,46>>]},{p,[],[<<65,108,115,111,44,32,105,102,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,116,104,101,32>>,{code,[],[<<114,101,97,100,47,51>>]},<<32,99,97,108,108,32,102,97,105,108,115,32,105,102,32,116,104,101,32,100,97,116,97,32,99,111,110,116,97,105,110,115,32,99,104,97,114,97,99,116,101,114,115,32,108,97,114,103,101,114,32,116,104,97,110,32,50,53,53,44,32,119,104,105,99,104,32,105,115,32,119,104,121,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,105,115,32,116,111,32,98,101,32,112,114,101,102,101,114,114,101,100,32,119,104,101,110,32,114,101,97,100,105,110,103,32,115,117,99,104,32,97,32,102,105,108,101,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,68,97,116,97,125>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,119,97,115,32,111,112,101,110,101,100,32,105,110,32,98,105,110,97,114,121,32,109,111,100,101,44,32,116,104,101,32,114,101,97,100,32,98,121,116,101,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,105,110,32,97,32,98,105,110,97,114,121,44,32,111,116,104,101,114,119,105,115,101,32,105,110,32,97,32,108,105,115,116,46,32,84,104,101,32,108,105,115,116,32,111,114,32,98,105,110,97,114,121,32,105,115,32,115,104,111,114,116,101,114,32,116,104,97,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,114,101,113,117,101,115,116,101,100,32,105,102,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,114,101,97,99,104,101,100,46>>]}]},{dt,[],[{code,[],[<<101,111,102>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,101,100,32,105,102,32>>,{code,[],[<<78,117,109,98,101,114,62,48>>]},<<32,97,110,100,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,114,101,97,99,104,101,100,32,98,101,102,111,114,101,32,97,110,121,116,104,105,110,103,32,97,116,32,97,108,108,32,99,111,117,108,100,32,98,101,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,98,97,100,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,102,111,114,32,114,101,97,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,110,111,95,116,114,97,110,115,108,97,116,105,111,110,44,32,117,110,105,99,111,100,101,44,32,108,97,116,105,110,49,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,97,110,100,32,116,104,101,32,100,97,116,97,32,105,110,32,116,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,116,104,101,32,98,121,116,101,45,111,114,105,101,110,116,101,100,32,100,97,116,97,32,116,104,97,116,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,52,52>>,signature => [{attribute,590,spec,{{read,2},[{type,590,bounded_fun,[{type,590,'fun',[{type,590,product,[{var,590,'IoDevice'},{var,590,'Number'}]},{type,590,union,[{type,590,tuple,[{atom,590,ok},{var,590,'Data'}]},{atom,590,eof},{type,590,tuple,[{atom,590,error},{var,590,'Reason'}]}]}]},[{type,591,constraint,[{atom,591,is_subtype},[{var,591,'IoDevice'},{type,591,union,[{user_type,591,io_device,[]},{type,591,atom,[]}]}]]},{type,592,constraint,[{atom,592,is_subtype},[{var,592,'Number'},{type,592,non_neg_integer,[]}]]},{type,593,constraint,[{atom,593,is_subtype},[{var,593,'Data'},{type,593,union,[{type,593,string,[]},{type,593,binary,[]}]}]]},{type,594,constraint,[{atom,594,is_subtype},[{var,594,'Reason'},{type,594,union,[{user_type,594,posix,[]},{atom,595,badarg},{atom,596,terminated},{type,597,tuple,[{atom,597,no_translation},{atom,597,unicode},{atom,597,latin1}]}]}]]}]]}]}}]}},{{function,read_file,1},[{file,[102,105,108,101,46,101,114,108]},{location,419}],[<<114,101,97,100,95,102,105,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,105,110,97,114,121,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,105,102,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,114,101,97,100,105,110,103,32,116,104,101,32,102,105,108,101,44,32,111,114,32,102,111,114,32,115,101,97,114,99,104,105,110,103,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,97,109,101,100,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,110,111,109,101,109>>]}]},{dd,[],[{p,[],[<<84,104,101,114,101,32,105,115,32,110,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,57,56>>,signature => [{attribute,419,spec,{{read_file,1},[{type,419,bounded_fun,[{type,419,'fun',[{type,419,product,[{var,419,'Filename'}]},{type,419,union,[{type,419,tuple,[{atom,419,ok},{var,419,'Binary'}]},{type,419,tuple,[{atom,419,error},{var,419,'Reason'}]}]}]},[{type,420,constraint,[{atom,420,is_subtype},[{var,420,'Filename'},{user_type,420,name_all,[]}]]},{type,421,constraint,[{atom,421,is_subtype},[{var,421,'Binary'},{type,421,binary,[]}]]},{type,422,constraint,[{atom,422,is_subtype},[{var,422,'Reason'},{type,422,union,[{user_type,422,posix,[]},{atom,422,badarg},{atom,422,terminated},{atom,422,system_limit}]}]]}]]}]}}]}},{{function,read_file_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,294}],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,52,51,52>>,equiv => {function,read_file_info,1},signature => [{attribute,294,spec,{{read_file_info,2},[{type,294,bounded_fun,[{type,294,'fun',[{type,294,product,[{var,294,'File'},{var,294,'Opts'}]},{type,294,union,[{type,294,tuple,[{atom,294,ok},{var,294,'FileInfo'}]},{type,294,tuple,[{atom,294,error},{var,294,'Reason'}]}]}]},[{type,295,constraint,[{atom,295,is_subtype},[{var,295,'File'},{type,295,union,[{user_type,295,name_all,[]},{user_type,295,io_device,[]}]}]]},{type,296,constraint,[{atom,296,is_subtype},[{var,296,'Opts'},{type,296,list,[{user_type,296,file_info_option,[]}]}]]},{type,297,constraint,[{atom,297,is_subtype},[{var,297,'FileInfo'},{user_type,297,file_info,[]}]]},{type,298,constraint,[{atom,298,is_subtype},[{var,298,'Reason'},{type,298,union,[{user_type,298,posix,[]},{atom,298,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,read_file_info,1},[{file,[102,105,108,101,46,101,114,108]},{location,282}],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,114,105,101,118,101,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,102,105,108,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,73,110,102,111,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,73,110,102,111>>]},<<32,105,115,32,97,32,114,101,99,111,114,100,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<44,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,75,101,114,110,101,108,32,105,110,99,108,117,100,101,32,102,105,108,101,32>>,{code,[],[<<102,105,108,101,46,104,114,108>>]},<<46,32,73,110,99,108,117,100,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,100,105,114,101,99,116,105,118,101,32,105,110,32,116,104,101,32,109,111,100,117,108,101,32,102,114,111,109,32,119,104,105,99,104,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<32,45,105,110,99,108,117,100,101,95,108,105,98,40,34,107,101,114,110,101,108,47,105,110,99,108,117,100,101,47,102,105,108,101,46,104,114,108,34,41,46>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,116,121,112,101,32,114,101,116,117,114,110,101,100,32,105,110,32>>,{code,[],[<<97,116,105,109,101>>]},<<44,32>>,{code,[],[<<109,116,105,109,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<99,116,105,109,101>>]},<<32,105,115,32,100,101,112,101,110,100,101,110,116,32,111,110,32,116,104,101,32,116,105,109,101,32,116,121,112,101,32,115,101,116,32,105,110,32>>,{code,[],[<<79,112,116,115,32,58,58,32,123,116,105,109,101,44,32,84,121,112,101,125>>]},<<32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,111,99,97,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,108,111,99,97,108,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<117,110,105,118,101,114,115,97,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,117,110,105,118,101,114,115,97,108,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<112,111,115,105,120>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,115,101,99,111,110,100,115,32,115,105,110,99,101,32,111,114,32,98,101,102,111,114,101,32,85,110,105,120,32,116,105,109,101,32,101,112,111,99,104,44,32,119,104,105,99,104,32,105,115,32,49,57,55,48,45,48,49,45,48,49,32,48,48,58,48,48,32,85,84,67,46>>]}]}]},{p,[],[<<68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<123,116,105,109,101,44,32,108,111,99,97,108,125>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,97,110,100,32,111,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,108,111,99,97,108,32,102,105,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46,32,78,111,116,101,32,116,104,97,116,32,116,104,105,115,32,119,105,108,108,32,98,114,101,97,107,32,116,104,105,115,32,109,111,100,117,108,101,39,115,32,97,116,111,109,105,99,105,116,121,32,103,117,97,114,97,110,116,101,101,115,32,97,115,32,105,116,32,99,97,110,32,114,97,99,101,32,119,105,116,104,32,97,32,99,111,110,99,117,114,114,101,110,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,49,44,50>>]},<<32>>]},<<46>>]},{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,103,105,118,101,110,32,97,110,32,73,47,79,32,100,101,118,105,99,101,32,105,110,115,116,101,97,100,32,111,102,32,97,32,102,105,108,101,32,110,97,109,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,116,111,32,111,98,116,97,105,110,32,97,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,102,105,114,115,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,105,108,101,32,116,105,109,101,115,32,97,114,101,32,115,116,111,114,101,100,32,105,110,32,80,79,83,73,88,32,116,105,109,101,32,111,110,32,109,111,115,116,32,79,83,44,32,105,116,32,105,115,32,102,97,115,116,101,114,32,116,111,32,113,117,101,114,121,32,102,105,108,101,32,105,110,102,111,114,109,97,116,105,111,110,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<112,111,115,105,120>>]},<<46>>]}]},{p,[],[<<84,104,101,32,114,101,99,111,114,100,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,101,108,100,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,105,122,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<83,105,122,101,32,111,102,32,102,105,108,101,32,105,110,32,98,121,116,101,115,46>>]}]},{dt,[],[{code,[],[<<116,121,112,101,32,61,32,100,101,118,105,99,101,32,124,32,100,105,114,101,99,116,111,114,121,32,124,32,111,116,104,101,114,32,124,32,114,101,103,117,108,97,114,32,124,32,115,121,109,108,105,110,107>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<97,99,99,101,115,115,32,61,32,114,101,97,100,32,124,32,119,114,105,116,101,32,124,32,114,101,97,100,95,119,114,105,116,101,32,124,32,110,111,110,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,97,99,99,101,115,115,32,116,111,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<97,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<109,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,119,114,105,116,116,101,110,46>>]}]},{dt,[],[{code,[],[<<99,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,116,105,109,101,32,102,105,101,108,100,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,46,32,79,110,32,85,110,105,120,44,32,105,116,32,105,115,32,116,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,111,114,32,116,104,101,32>>,{code,[],[<<105,110,111,100,101>>]},<<32,119,97,115,32,99,104,97,110,103,101,100,46,32,73,110,32,87,105,110,100,111,119,115,44,32,105,116,32,105,115,32,116,104,101,32,99,114,101,97,116,101,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<109,111,100,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,112,101,114,109,105,115,115,105,111,110,115,32,97,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,98,105,116,32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<56,35,48,48,52,48,48>>]}]},{dd,[],[{p,[],[<<114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,50,48,48>>]}]},{dd,[],[{p,[],[<<119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,49,48,48>>]}]},{dd,[],[{p,[],[<<101,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,52,48>>]}]},{dd,[],[{p,[],[<<114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,50,48>>]}]},{dd,[],[{p,[],[<<119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,49,48>>]}]},{dd,[],[{p,[],[<<101,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,52>>]}]},{dd,[],[{p,[],[<<114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,50>>]}]},{dd,[],[{p,[],[<<119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,49>>]}]},{dd,[],[{p,[],[<<101,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<49,54,35,56,48,48>>]}]},{dd,[],[{p,[],[<<115,101,116,32,117,115,101,114,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]},{dt,[],[{code,[],[<<49,54,35,52,48,48>>]}]},{dd,[],[{p,[],[<<115,101,116,32,103,114,111,117,112,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]}]},{p,[],[<<79,110,32,85,110,105,120,32,112,108,97,116,102,111,114,109,115,44,32,111,116,104,101,114,32,98,105,116,115,32,116,104,97,110,32,116,104,111,115,101,32,108,105,115,116,101,100,32,97,98,111,118,101,32,109,97,121,32,98,101,32,115,101,116,46>>]}]},{dt,[],[{code,[],[<<108,105,110,107,115,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<78,117,109,98,101,114,32,111,102,32,108,105,110,107,115,32,116,111,32,116,104,101,32,102,105,108,101,32,40,116,104,105,115,32,105,115,32,97,108,119,97,121,115,32,49,32,102,111,114,32,102,105,108,101,32,115,121,115,116,101,109,115,32,116,104,97,116,32,104,97,118,101,32,110,111,32,99,111,110,99,101,112,116,32,111,102,32,108,105,110,107,115,41,46>>]}]},{dt,[],[{code,[],[<<109,97,106,111,114,95,100,101,118,105,99,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<73,100,101,110,116,105,102,105,101,115,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,119,104,101,114,101,32,116,104,101,32,102,105,108,101,32,105,115,32,108,111,99,97,116,101,100,46,32,73,110,32,87,105,110,100,111,119,115,44,32,116,104,101,32,110,117,109,98,101,114,32,105,110,100,105,99,97,116,101,115,32,97,32,100,114,105,118,101,32,97,115,32,102,111,108,108,111,119,115,58,32,48,32,109,101,97,110,115,32,65,58,44,32,49,32,109,101,97,110,115,32,66,58,44,32,97,110,100,32,115,111,32,111,110,46>>]}]},{dt,[],[{code,[],[<<109,105,110,111,114,95,100,101,118,105,99,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32,99,104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,32,111,110,32,85,110,105,120,46,32,73,110,32,97,108,108,32,111,116,104,101,114,32,99,97,115,101,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]},{dt,[],[{code,[],[<<105,110,111,100,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,116,104,101,32>>,{code,[],[<<105,110,111,100,101>>]},<<32,110,117,109,98,101,114,46,32,79,110,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]},{dt,[],[{code,[],[<<117,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<73,110,100,105,99,97,116,101,115,32,116,104,101,32,111,119,110,101,114,32,111,102,32,116,104,101,32,102,105,108,101,46,32,79,110,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]},{dt,[],[{code,[],[<<103,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,116,104,101,32,103,114,111,117,112,32,116,104,97,116,32,116,104,101,32,111,119,110,101,114,32,111,102,32,116,104,101,32,102,105,108,101,32,98,101,108,111,110,103,115,32,116,111,46,32,79,110,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,52,51,52>>,signature => [{attribute,282,spec,{{read_file_info,1},[{type,282,bounded_fun,[{type,282,'fun',[{type,282,product,[{var,282,'File'}]},{type,282,union,[{type,282,tuple,[{atom,282,ok},{var,282,'FileInfo'}]},{type,282,tuple,[{atom,282,error},{var,282,'Reason'}]}]}]},[{type,283,constraint,[{atom,283,is_subtype},[{var,283,'File'},{type,283,union,[{user_type,283,name_all,[]},{user_type,283,io_device,[]}]}]]},{type,284,constraint,[{atom,284,is_subtype},[{var,284,'FileInfo'},{user_type,284,file_info,[]}]]},{type,285,constraint,[{atom,285,is_subtype},[{var,285,'Reason'},{type,285,union,[{user_type,285,posix,[]},{atom,285,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,read_line,1},[{file,[102,105,108,101,46,101,114,108]},{location,612}],[<<114,101,97,100,95,108,105,110,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,97,32,108,105,110,101,32,111,102,32,98,121,116,101,115,47,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,76,105,110,101,115,32,97,114,101,32,100,101,102,105,110,101,100,32,116,111,32,98,101,32,100,101,108,105,109,105,116,101,100,32,98,121,32,116,104,101,32,108,105,110,101,102,101,101,100,32,40,76,70,44,32>>,{code,[],[<<92,110>>]},<<41,32,99,104,97,114,97,99,116,101,114,44,32,98,117,116,32,97,110,121,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,40,67,82,44,32>>,{code,[],[<<92,114>>]},<<41,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,101,119,108,105,110,101,32,105,115,32,97,108,115,111,32,116,114,101,97,116,101,100,32,97,115,32,97,32,115,105,110,103,108,101,32,76,70,32,99,104,97,114,97,99,116,101,114,32,40,116,104,101,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,105,115,32,115,105,108,101,110,116,108,121,32,105,103,110,111,114,101,100,41,46,32,84,104,101,32,108,105,110,101,32,105,115,32,114,101,116,117,114,110,101,100,32>>,{em,[],[<<105,110,99,108,117,100,105,110,103>>]},<<32,116,104,101,32,76,70,44,32,98,117,116,32,101,120,99,108,117,100,105,110,103,32,97,110,121,32,67,82,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,76,70,46,32,84,104,105,115,32,98,101,104,97,118,105,111,117,114,32,105,115,32,99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,32,116,104,101,32,98,101,104,97,118,105,111,117,114,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111,35,103,101,116,95,108,105,110,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,111,58,103,101,116,95,108,105,110,101,47,50>>]}]},<<46,32,73,102,32,101,110,100,32,111,102,32,102,105,108,101,32,105,115,32,114,101,97,99,104,101,100,32,119,105,116,104,111,117,116,32,97,110,121,32,76,70,32,101,110,100,105,110,103,32,116,104,101,32,108,97,115,116,32,108,105,110,101,44,32,97,32,108,105,110,101,32,119,105,116,104,32,110,111,32,116,114,97,105,108,105,110,103,32,76,70,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,117,115,101,100,32,111,110,32,102,105,108,101,115,32,111,112,101,110,101,100,32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,46,32,72,111,119,101,118,101,114,44,32,105,116,32,105,115,32,105,110,101,102,102,105,99,105,101,110,116,32,116,111,32,117,115,101,32,105,116,32,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,102,105,108,101,115,32,105,102,32,116,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,115,112,101,99,105,102,105,101,100,46,32,84,104,117,115,44,32,99,111,109,98,105,110,105,110,103,32>>,{code,[],[<<114,97,119>>]},<<32,97,110,100,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,105,115,32,104,105,103,104,108,121,32,114,101,99,111,109,109,101,110,100,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,97,32,116,101,120,116,32,102,105,108,101,32,102,111,114,32,114,97,119,32,108,105,110,101,45,111,114,105,101,110,116,101,100,32,114,101,97,100,105,110,103,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,116,104,101,32>>,{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]},<<32,99,97,108,108,32,102,97,105,108,115,32,105,102,32,116,104,101,32,100,97,116,97,32,99,111,110,116,97,105,110,115,32,99,104,97,114,97,99,116,101,114,115,32,108,97,114,103,101,114,32,116,104,97,110,32,50,53,53,44,32,119,104,121,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,105,115,32,116,111,32,98,101,32,112,114,101,102,101,114,114,101,100,32,119,104,101,110,32,114,101,97,100,105,110,103,32,115,117,99,104,32,97,32,102,105,108,101,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,68,97,116,97,125>>]}]},{dd,[],[{p,[],[<<79,110,101,32,108,105,110,101,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,105,115,32,114,101,116,117,114,110,101,100,44,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,116,114,97,105,108,105,110,103,32,76,70,44,32,98,117,116,32,119,105,116,104,32,67,82,76,70,32,115,101,113,117,101,110,99,101,115,32,114,101,112,108,97,99,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,76,70,32,40,115,101,101,32,97,98,111,118,101,41,46>>]},{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,105,110,32,98,105,110,97,114,121,32,109,111,100,101,44,32,116,104,101,32,114,101,97,100,32,98,121,116,101,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,105,110,32,97,32,98,105,110,97,114,121,44,32,111,116,104,101,114,119,105,115,101,32,105,110,32,97,32,108,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,111,102>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,101,100,32,105,102,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,114,101,97,99,104,101,100,32,98,101,102,111,114,101,32,97,110,121,116,104,105,110,103,32,97,116,32,97,108,108,32,99,111,117,108,100,32,98,101,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,98,97,100,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,102,111,114,32,114,101,97,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,110,111,95,116,114,97,110,115,108,97,116,105,111,110,44,32,117,110,105,99,111,100,101,44,32,108,97,116,105,110,49,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,97,110,100,32,116,104,101,32,100,97,116,97,32,111,110,32,116,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,116,104,101,32,98,121,116,101,45,111,114,105,101,110,116,101,100,32,100,97,116,97,32,116,104,97,116,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,53,57,51>>,signature => [{attribute,612,spec,{{read_line,1},[{type,612,bounded_fun,[{type,612,'fun',[{type,612,product,[{var,612,'IoDevice'}]},{type,612,union,[{type,612,tuple,[{atom,612,ok},{var,612,'Data'}]},{atom,612,eof},{type,612,tuple,[{atom,612,error},{var,612,'Reason'}]}]}]},[{type,613,constraint,[{atom,613,is_subtype},[{var,613,'IoDevice'},{type,613,union,[{user_type,613,io_device,[]},{type,613,atom,[]}]}]]},{type,614,constraint,[{atom,614,is_subtype},[{var,614,'Data'},{type,614,union,[{type,614,string,[]},{type,614,binary,[]}]}]]},{type,615,constraint,[{atom,615,is_subtype},[{var,615,'Reason'},{type,615,union,[{user_type,615,posix,[]},{atom,616,badarg},{atom,617,terminated},{type,618,tuple,[{atom,618,no_translation},{atom,618,unicode},{atom,618,latin1}]}]}]]}]]}]}}]}},{{function,read_link,1},[{file,[102,105,108,101,46,101,114,108]},{location,356}],[<<114,101,97,100,95,108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[{a,[{id,<<114,101,97,100,95,108,105,110,107,95,97,108,108>>}],[]},<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,125>>]},<<32,105,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,114,97,119,32,102,105,108,101,110,97,109,101,44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,111,116,104,101,114,119,105,115,101,46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,100,111,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<123,101,114,114,111,114,44,101,110,111,116,115,117,112,125>>]},<<46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<78,97,109,101>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32,111,114,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,32,116,104,97,116,32,105,116,32,114,101,102,101,114,115,32,116,111,32,100,111,101,115,32,110,111,116,32,99,111,110,102,111,114,109,32,116,111,32,116,104,101,32,101,120,112,101,99,116,101,100,32,101,110,99,111,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,54,53,48>>,signature => [{attribute,356,spec,{{read_link,1},[{type,356,bounded_fun,[{type,356,'fun',[{type,356,product,[{var,356,'Name'}]},{type,356,union,[{type,356,tuple,[{atom,356,ok},{var,356,'Filename'}]},{type,356,tuple,[{atom,356,error},{var,356,'Reason'}]}]}]},[{type,357,constraint,[{atom,357,is_subtype},[{var,357,'Name'},{user_type,357,name_all,[]}]]},{type,358,constraint,[{atom,358,is_subtype},[{var,358,'Filename'},{user_type,358,filename,[]}]]},{type,359,constraint,[{atom,359,is_subtype},[{var,359,'Reason'},{type,359,union,[{user_type,359,posix,[]},{atom,359,badarg}]}]]}]]}]}}]}},{{function,read_link_all,1},[{file,[102,105,108,101,46,101,114,108]},{location,364}],[<<114,101,97,100,95,108,105,110,107,95,97,108,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,125>>]},<<32,105,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,111,116,104,101,114,119,105,115,101,46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,100,111,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<123,101,114,114,111,114,44,101,110,111,116,115,117,112,125>>]},<<46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,101,105,116,104,101,114,32,97,32,108,105,115,116,32,111,114,32,97,32,98,105,110,97,114,121,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<78,97,109,101>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,54,56,48>>,signature => [{attribute,364,spec,{{read_link_all,1},[{type,364,bounded_fun,[{type,364,'fun',[{type,364,product,[{var,364,'Name'}]},{type,364,union,[{type,364,tuple,[{atom,364,ok},{var,364,'Filename'}]},{type,364,tuple,[{atom,364,error},{var,364,'Reason'}]}]}]},[{type,365,constraint,[{atom,365,is_subtype},[{var,365,'Name'},{user_type,365,name_all,[]}]]},{type,366,constraint,[{atom,366,is_subtype},[{var,366,'Filename'},{user_type,366,filename_all,[]}]]},{type,367,constraint,[{atom,367,is_subtype},[{var,367,'Reason'},{type,367,union,[{user_type,367,posix,[]},{atom,367,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,read_link_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,334}],[<<114,101,97,100,95,108,105,110,107,95,105,110,102,111,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,48,56>>,equiv => {function,read_link_info,1},signature => [{attribute,334,spec,{{read_link_info,2},[{type,334,bounded_fun,[{type,334,'fun',[{type,334,product,[{var,334,'Name'},{var,334,'Opts'}]},{type,334,union,[{type,334,tuple,[{atom,334,ok},{var,334,'FileInfo'}]},{type,334,tuple,[{atom,334,error},{var,334,'Reason'}]}]}]},[{type,335,constraint,[{atom,335,is_subtype},[{var,335,'Name'},{user_type,335,name_all,[]}]]},{type,336,constraint,[{atom,336,is_subtype},[{var,336,'Opts'},{type,336,list,[{user_type,336,file_info_option,[]}]}]]},{type,337,constraint,[{atom,337,is_subtype},[{var,337,'FileInfo'},{user_type,337,file_info,[]}]]},{type,338,constraint,[{atom,338,is_subtype},[{var,338,'Reason'},{type,338,union,[{user_type,338,posix,[]},{atom,338,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,read_link_info,1},[{file,[102,105,108,101,46,101,114,108]},{location,326}],[<<114,101,97,100,95,108,105,110,107,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49,44,50>>]}]},<<32,101,120,99,101,112,116,32,116,104,97,116,32,105,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,44,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,108,105,110,107,32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,32,116,104,101,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<32,114,101,99,111,114,100,32,97,110,100,32,116,104,101,32>>,{code,[],[<<116,121,112,101>>]},<<32,102,105,101,108,100,32,111,102,32,116,104,101,32,114,101,99,111,114,100,32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<115,121,109,108,105,110,107>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,97,110,100,32,111,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,108,111,99,97,108,32,102,105,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46,32,78,111,116,101,32,116,104,97,116,32,116,104,105,115,32,119,105,108,108,32,98,114,101,97,107,32,116,104,105,115,32,109,111,100,117,108,101,39,115,32,97,116,111,109,105,99,105,116,121,32,103,117,97,114,97,110,116,101,101,115,32,97,115,32,105,116,32,99,97,110,32,114,97,99,101,32,119,105,116,104,32,97,32,99,111,110,99,117,114,114,101,110,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,49,44,50>>]}]}]},{p,[],[<<73,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,110,111,116,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32>>,{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>]},<<46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,100,111,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,97,108,119,97,121,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,48,56>>,signature => [{attribute,326,spec,{{read_link_info,1},[{type,326,bounded_fun,[{type,326,'fun',[{type,326,product,[{var,326,'Name'}]},{type,326,union,[{type,326,tuple,[{atom,326,ok},{var,326,'FileInfo'}]},{type,326,tuple,[{atom,326,error},{var,326,'Reason'}]}]}]},[{type,327,constraint,[{atom,327,is_subtype},[{var,327,'Name'},{user_type,327,name_all,[]}]]},{type,328,constraint,[{atom,328,is_subtype},[{var,328,'FileInfo'},{user_type,328,file_info,[]}]]},{type,329,constraint,[{atom,329,is_subtype},[{var,329,'Reason'},{type,329,union,[{user_type,329,posix,[]},{atom,329,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,rename,2},[{file,[102,105,108,101,46,101,114,108]},{location,241}],[<<114,101,110,97,109,101,47,50>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,114,101,110,97,109,101,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,116,111,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<46,32,73,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,111,118,101,32,102,105,108,101,115,32,40,97,110,100,32,100,105,114,101,99,116,111,114,105,101,115,41,32,98,101,116,119,101,101,110,32,100,105,114,101,99,116,111,114,105,101,115,44,32,98,117,116,32,105,116,32,105,115,32,110,111,116,32,115,117,102,102,105,99,105,101,110,116,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,100,101,115,116,105,110,97,116,105,111,110,32,111,110,108,121,46,32,84,104,101,32,100,101,115,116,105,110,97,116,105,111,110,32,102,105,108,101,110,97,109,101,32,109,117,115,116,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32>>,{code,[],[<<98,97,114>>]},<<32,105,115,32,97,32,110,111,114,109,97,108,32,102,105,108,101,32,97,110,100,32>>,{code,[],[<<102,111,111>>]},<<32,97,110,100,32>>,{code,[],[<<98,97,122>>]},<<32,97,114,101,32,100,105,114,101,99,116,111,114,105,101,115,44,32>>,{code,[],[<<114,101,110,97,109,101,40,34,102,111,111,47,98,97,114,34,44,32,34,98,97,122,34,41>>]},<<32,114,101,116,117,114,110,115,32,97,110,32,101,114,114,111,114,44,32,98,117,116,32>>,{code,[],[<<114,101,110,97,109,101,40,34,102,111,111,47,98,97,114,34,44,32,34,98,97,122,47,98,97,114,34,41>>]},<<32,115,117,99,99,101,101,100,115,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,105,116,32,105,115,32,115,117,99,99,101,115,115,102,117,108,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<82,101,110,97,109,105,110,103,32,111,102,32,111,112,101,110,32,102,105,108,101,115,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,111,110,32,109,111,115,116,32,112,108,97,116,102,111,114,109,115,32,40,115,101,101,32>>,{code,[],[<<101,97,99,99,101,115>>]},<<32,98,101,108,111,119,41,46>>]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,111,114,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,101,114,114,111,114,32,105,115,32,103,105,118,101,110,32,105,102,32,101,105,116,104,101,114,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,111,114,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,111,112,101,110,46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,109,112,116,121,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,97,108,115,111,32,103,105,118,101,110,32,119,104,101,110,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,97,114,101,32,110,111,116,32,111,102,32,116,104,101,32,115,97,109,101,32,116,121,112,101,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,105,115,32,97,32,114,111,111,116,32,100,105,114,101,99,116,111,114,121,44,32,111,114,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,97,32,115,117,98,100,105,114,101,99,116,111,114,121,32,111,102,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,44,32,98,117,116,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,105,115,32,110,111,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,44,32,98,117,116,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,110,111,116,46>>]}]},{dt,[],[{code,[],[<<101,120,100,101,118>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,97,114,101,32,111,110,32,100,105,102,102,101,114,101,110,116,32,102,105,108,101,32,115,121,115,116,101,109,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,51,48>>,signature => [{attribute,241,spec,{{rename,2},[{type,241,bounded_fun,[{type,241,'fun',[{type,241,product,[{var,241,'Source'},{var,241,'Destination'}]},{type,241,union,[{atom,241,ok},{type,241,tuple,[{atom,241,error},{var,241,'Reason'}]}]}]},[{type,242,constraint,[{atom,242,is_subtype},[{var,242,'Source'},{user_type,242,name_all,[]}]]},{type,243,constraint,[{atom,243,is_subtype},[{var,243,'Destination'},{user_type,243,name_all,[]}]]},{type,244,constraint,[{atom,244,is_subtype},[{var,244,'Reason'},{type,244,union,[{user_type,244,posix,[]},{atom,244,badarg}]}]]}]]}]}}]}},{{function,script,1},[{file,[102,105,108,101,46,101,114,108]},{location,1123}],[<<115,99,114,105,112,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,86,97,108,117,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,105,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,108,97,115,116,32,101,120,112,114,101,115,115,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,57,51>>,signature => [{attribute,1123,spec,{{script,1},[{type,1123,bounded_fun,[{type,1123,'fun',[{type,1123,product,[{var,1123,'Filename'}]},{type,1123,union,[{type,1123,tuple,[{atom,1123,ok},{var,1123,'Value'}]},{type,1123,tuple,[{atom,1123,error},{var,1123,'Reason'}]}]}]},[{type,1124,constraint,[{atom,1124,is_subtype},[{var,1124,'Filename'},{user_type,1124,name_all,[]}]]},{type,1125,constraint,[{atom,1125,is_subtype},[{var,1125,'Value'},{type,1125,term,[]}]]},{type,1126,constraint,[{atom,1126,is_subtype},[{var,1126,'Reason'},{type,1126,union,[{user_type,1126,posix,[]},{atom,1126,badarg},{atom,1126,terminated},{atom,1126,system_limit},{type,1127,tuple,[{ann_type,1127,[{var,1127,'Line'},{type,1127,integer,[]}]},{ann_type,1127,[{var,1127,'Mod'},{type,1127,module,[]}]},{ann_type,1127,[{var,1127,'Term'},{type,1127,term,[]}]}]}]}]]}]]}]}}]}},{{function,script,2},[{file,[102,105,108,101,46,101,114,108]},{location,1132}],[<<115,99,114,105,112,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<115,99,114,105,112,116,47,49>>]},<<32,98,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,32>>,{code,[],[<<66,105,110,100,105,110,103,115>>]},<<32,97,114,101,32,117,115,101,100,32,105,110,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,115,116,100,108,105,98,58,101,114,108,95,101,118,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,101,118,97,108,40,51,41>>]}]},<<32,97,98,111,117,116,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,50,56>>,signature => [{attribute,1132,spec,{{script,2},[{type,1132,bounded_fun,[{type,1132,'fun',[{type,1132,product,[{var,1132,'Filename'},{var,1132,'Bindings'}]},{type,1132,union,[{type,1132,tuple,[{atom,1132,ok},{var,1132,'Value'}]},{type,1132,tuple,[{atom,1132,error},{var,1132,'Reason'}]}]}]},[{type,1133,constraint,[{atom,1133,is_subtype},[{var,1133,'Filename'},{user_type,1133,name_all,[]}]]},{type,1134,constraint,[{atom,1134,is_subtype},[{var,1134,'Bindings'},{remote_type,1134,[{atom,1134,erl_eval},{atom,1134,binding_struct},[]]}]]},{type,1135,constraint,[{atom,1135,is_subtype},[{var,1135,'Value'},{type,1135,term,[]}]]},{type,1136,constraint,[{atom,1136,is_subtype},[{var,1136,'Reason'},{type,1136,union,[{user_type,1136,posix,[]},{atom,1136,badarg},{atom,1136,terminated},{atom,1136,system_limit},{type,1137,tuple,[{ann_type,1137,[{var,1137,'Line'},{type,1137,integer,[]}]},{ann_type,1137,[{var,1137,'Mod'},{type,1137,module,[]}]},{ann_type,1137,[{var,1137,'Term'},{type,1137,term,[]}]}]}]}]]}]]}]}}]}},{{function,sendfile,2},[{file,[102,105,108,101,46,101,114,108]},{location,1316}],[<<115,101,110,100,102,105,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,116,111,32>>,{code,[],[<<83,111,99,107,101,116>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,121,116,101,115,83,101,110,116,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,51,56>>,signature => [{attribute,1316,spec,{{sendfile,2},[{type,1316,bounded_fun,[{type,1316,'fun',[{type,1316,product,[{var,1316,'Filename'},{var,1316,'Socket'}]},{type,1317,union,[{type,1317,tuple,[{atom,1317,ok},{type,1317,non_neg_integer,[]}]},{type,1317,tuple,[{atom,1317,error},{type,1317,union,[{remote_type,1317,[{atom,1317,inet},{atom,1317,posix},[]]},{atom,1318,closed},{atom,1318,badarg},{atom,1318,not_owner}]}]}]}]},[{type,1319,constraint,[{atom,1319,is_subtype},[{var,1319,'Filename'},{user_type,1319,name_all,[]}]]},{type,1320,constraint,[{atom,1320,is_subtype},[{var,1320,'Socket'},{remote_type,1320,[{atom,1320,inet},{atom,1320,socket},[]]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,sendfile,5},[{file,[102,105,108,101,46,101,114,108]},{location,1289}],[<<115,101,110,100,102,105,108,101,47,53>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,101,110,100,102,105,108,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<83,101,110,100,115,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<82,97,119,70,105,108,101>>]},<<32,98,101,103,105,110,110,105,110,103,32,97,116,32>>,{code,[],[<<79,102,102,115,101,116>>]},<<32,116,111,32>>,{code,[],[<<83,111,99,107,101,116>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,121,116,101,115,83,101,110,116,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32,73,102,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<48>>]},<<32,97,108,108,32,100,97,116,97,32,97,102,116,101,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32>>,{code,[],[<<79,102,102,115,101,116>>]},<<32,105,115,32,115,101,110,116,46>>]},{p,[],[<<84,104,101,32,102,105,108,101,32,117,115,101,100,32,109,117,115,116,32,98,101,32,111,112,101,110,101,100,32,117,115,105,110,103,32,116,104,101,32>>,{code,[],[<<114,97,119>>]},<<32,102,108,97,103,44,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<115,101,110,100,102,105,108,101>>]},<<32,109,117,115,116,32,98,101,32,116,104,101,32,99,111,110,116,114,111,108,108,105,110,103,32,112,114,111,99,101,115,115,32,111,102,32,116,104,101,32,115,111,99,107,101,116,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,103,101,110,95,116,99,112,35,99,111,110,116,114,111,108,108,105,110,103,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,101,110,95,116,99,112,58,99,111,110,116,114,111,108,108,105,110,103,95,112,114,111,99,101,115,115,47,50>>]}]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,79,83,32,117,115,101,100,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,110,111,110,45,98,108,111,99,107,105,110,103,32>>,{code,[],[<<115,101,110,100,102,105,108,101>>]},<<44,32,97,110,32,69,114,108,97,110,103,32,102,97,108,108,98,97,99,107,32,117,115,105,110,103,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,103,101,110,95,116,99,112,35,115,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,101,110,95,116,99,112,58,115,101,110,100,47,50>>]}]},<<32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,111,112,116,105,111,110,32,108,105,115,116,32,99,97,110,32,99,111,110,116,97,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<99,104,117,110,107,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,99,104,117,110,107,32,115,105,122,101,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,102,97,108,108,98,97,99,107,32,116,111,32,115,101,110,100,32,100,97,116,97,46,32,73,102,32,117,115,105,110,103,32,116,104,101,32,102,97,108,108,98,97,99,107,44,32,115,101,116,32,116,104,105,115,32,116,111,32,97,32,118,97,108,117,101,32,116,104,97,116,32,99,111,109,102,111,114,116,97,98,108,121,32,102,105,116,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,115,32,109,101,109,111,114,121,46,32,68,101,102,97,117,108,116,32,105,115,32,50,48,32,77,66,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,52,55>>,signature => [{attribute,1289,spec,{{sendfile,5},[{type,1289,bounded_fun,[{type,1289,'fun',[{type,1289,product,[{var,1289,'RawFile'},{var,1289,'Socket'},{var,1289,'Offset'},{var,1289,'Bytes'},{var,1289,'Opts'}]},{type,1290,union,[{type,1290,tuple,[{atom,1290,ok},{type,1290,non_neg_integer,[]}]},{type,1290,tuple,[{atom,1290,error},{type,1290,union,[{remote_type,1290,[{atom,1290,inet},{atom,1290,posix},[]]},{atom,1291,closed},{atom,1291,badarg},{atom,1291,not_owner}]}]}]}]},[{type,1292,constraint,[{atom,1292,is_subtype},[{var,1292,'RawFile'},{user_type,1292,fd,[]}]]},{type,1293,constraint,[{atom,1293,is_subtype},[{var,1293,'Socket'},{remote_type,1293,[{atom,1293,inet},{atom,1293,socket},[]]}]]},{type,1294,constraint,[{atom,1294,is_subtype},[{var,1294,'Offset'},{type,1294,non_neg_integer,[]}]]},{type,1295,constraint,[{atom,1295,is_subtype},[{var,1295,'Bytes'},{type,1295,non_neg_integer,[]}]]},{type,1296,constraint,[{atom,1296,is_subtype},[{var,1296,'Opts'},{type,1296,list,[{user_type,1296,sendfile_option,[]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,set_cwd,1},[{file,[102,105,108,101,46,101,114,108]},{location,206}],[<<115,101,116,95,99,119,100,47,49>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,99,117,114,114,101,110,116,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,116,111,32>>,{code,[],[<<68,105,114>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<102,105,108,101>>]},<<32,117,115,117,97,108,108,121,32,116,114,101,97,116,32,98,105,110,97,114,105,101,115,32,97,115,32,114,97,119,32,102,105,108,101,110,97,109,101,115,44,32,116,104,97,116,32,105,115,44,32,116,104,101,121,32,97,114,101,32,112,97,115,115,101,100,32,34,97,115,32,105,115,34,32,101,118,101,110,32,119,104,101,110,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,100,111,101,115,32,110,111,116,32,97,103,114,101,101,32,119,105,116,104,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,40,41>>]}]},<<46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,101,120,112,101,99,116,115,32,98,105,110,97,114,105,101,115,32,116,111,32,98,101,32,101,110,99,111,100,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,118,97,108,117,101,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,40,41>>]},<<46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,32,97,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,115,46>>]}]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[{code,[],[<<68,105,114>>]},<<32,104,97,115,32,97,110,32,105,109,112,114,111,112,101,114,32,116,121,112,101,44,32,115,117,99,104,32,97,115,32,116,117,112,108,101,46>>]}]},{dt,[],[{code,[],[<<110,111,95,116,114,97,110,115,108,97,116,105,111,110>>]}]},{dd,[],[{p,[],[{code,[],[<<68,105,114>>]},<<32,105,115,32,97,32>>,{code,[],[<<98,105,110,97,114,121,40,41>>]},<<32,119,105,116,104,32,99,104,97,114,97,99,116,101,114,115,32,99,111,100,101,100,32,105,110,32,73,83,79,45,108,97,116,105,110,45,49,32,97,110,100,32,116,104,101,32,86,77,32,105,115,32,111,112,101,114,97,116,105,110,103,32,119,105,116,104,32,117,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,44,32,97,32,98,97,100,32,116,121,112,101,32,102,111,114,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<68,105,114>>]},<<32,119,105,108,108,32,112,114,111,98,97,98,108,121,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,55,52>>,signature => [{attribute,206,spec,{{set_cwd,1},[{type,206,bounded_fun,[{type,206,'fun',[{type,206,product,[{var,206,'Dir'}]},{type,206,union,[{atom,206,ok},{type,206,tuple,[{atom,206,error},{var,206,'Reason'}]}]}]},[{type,207,constraint,[{atom,207,is_subtype},[{var,207,'Dir'},{type,207,union,[{user_type,207,name,[]},{var,207,'EncodedBinary'}]}]]},{type,208,constraint,[{atom,208,is_subtype},[{var,208,'EncodedBinary'},{type,208,binary,[]}]]},{type,209,constraint,[{atom,209,is_subtype},[{var,209,'Reason'},{type,209,union,[{user_type,209,posix,[]},{atom,209,badarg},{atom,209,no_translation}]}]]}]]}]}}]}},{{function,sync,1},[{file,[102,105,108,101,46,101,114,108]},{location,742}],[<<115,121,110,99,47,49>>],#{<<101,110>> => [{p,[],[<<69,110,115,117,114,101,115,32,116,104,97,116,32,97,110,121,32,98,117,102,102,101,114,115,32,107,101,112,116,32,98,121,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,40,110,111,116,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,41,32,97,114,101,32,119,114,105,116,116,101,110,32,116,111,32,100,105,115,107,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,109,105,103,104,116,32,104,97,118,101,32,110,111,32,101,102,102,101,99,116,46>>]},{p,[],[<<65,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,32,105,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,116,32,101,110,111,117,103,104,32,115,112,97,99,101,32,108,101,102,116,32,116,111,32,119,114,105,116,101,32,116,104,101,32,102,105,108,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,50,49>>,signature => [{attribute,742,spec,{{sync,1},[{type,742,bounded_fun,[{type,742,'fun',[{type,742,product,[{var,742,'IoDevice'}]},{type,742,union,[{atom,742,ok},{type,742,tuple,[{atom,742,error},{var,742,'Reason'}]}]}]},[{type,743,constraint,[{atom,743,is_subtype},[{var,743,'IoDevice'},{user_type,743,io_device,[]}]]},{type,744,constraint,[{atom,744,is_subtype},[{var,744,'Reason'},{type,744,union,[{user_type,744,posix,[]},{atom,744,badarg},{atom,744,terminated}]}]]}]]}]}}]}},{{function,truncate,1},[{file,[102,105,108,101,46,101,114,108]},{location,766}],[<<116,114,117,110,99,97,116,101,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,117,110,99,97,116,101,115,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,51,55>>,signature => [{attribute,766,spec,{{truncate,1},[{type,766,bounded_fun,[{type,766,'fun',[{type,766,product,[{var,766,'IoDevice'}]},{type,766,union,[{atom,766,ok},{type,766,tuple,[{atom,766,error},{var,766,'Reason'}]}]}]},[{type,767,constraint,[{atom,767,is_subtype},[{var,767,'IoDevice'},{user_type,767,io_device,[]}]]},{type,768,constraint,[{atom,768,is_subtype},[{var,768,'Reason'},{type,768,union,[{user_type,768,posix,[]},{atom,768,badarg},{atom,768,terminated}]}]]}]]}]}}]}},{{function,write,2},[{file,[102,105,108,101,46,101,114,108]},{location,676}],[<<119,114,105,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<87,114,105,116,101,115,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,116,111,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,104,101,32,111,110,108,121,32,119,97,121,32,116,111,32,119,114,105,116,101,32,116,111,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,40,97,108,116,104,111,117,103,104,32,105,116,32,119,111,114,107,115,32,102,111,114,32,110,111,114,109,97,108,108,121,32,111,112,101,110,101,100,32,102,105,108,101,115,32,116,111,111,41,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,97,110,100,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,111,116,104,101,114,119,105,115,101,46>>]},{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,101,97,99,104,32,98,121,116,101,32,119,114,105,116,116,101,110,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,109,97,110,121,32,98,121,116,101,115,32,98,101,105,110,103,32,119,114,105,116,116,101,110,32,116,111,32,116,104,101,32,102,105,108,101,44,32,97,115,32,116,104,101,32,98,121,116,101,32,114,97,110,103,101,32,48,46,46,50,53,53,32,99,97,110,32,114,101,112,114,101,115,101,110,116,32,97,110,121,116,104,105,110,103,32,98,101,116,119,101,101,110,32,111,110,101,32,97,110,100,32,102,111,117,114,32,98,121,116,101,115,32,100,101,112,101,110,100,105,110,103,32,111,110,32,118,97,108,117,101,32,97,110,100,32,85,84,70,32,101,110,99,111,100,105,110,103,32,116,121,112,101,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,98,97,100,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,99,101,32,105,115,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,52,54>>,signature => [{attribute,676,spec,{{write,2},[{type,676,bounded_fun,[{type,676,'fun',[{type,676,product,[{var,676,'IoDevice'},{var,676,'Bytes'}]},{type,676,union,[{atom,676,ok},{type,676,tuple,[{atom,676,error},{var,676,'Reason'}]}]}]},[{type,677,constraint,[{atom,677,is_subtype},[{var,677,'IoDevice'},{type,677,union,[{user_type,677,io_device,[]},{type,677,atom,[]}]}]]},{type,678,constraint,[{atom,678,is_subtype},[{var,678,'Bytes'},{type,678,iodata,[]}]]},{type,679,constraint,[{atom,679,is_subtype},[{var,679,'Reason'},{type,679,union,[{user_type,679,posix,[]},{atom,679,badarg},{atom,679,terminated}]}]]}]]}]}}]}},{{function,write_file,2},[{file,[102,105,108,101,46,101,114,108]},{location,443}],[<<119,114,105,116,101,95,102,105,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<87,114,105,116,101,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<32,116,101,114,109,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,116,111,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,84,104,101,32,102,105,108,101,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,73,102,32,105,116,32,101,120,105,115,116,115,44,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,111,110,116,101,110,116,115,32,97,114,101,32,111,118,101,114,119,114,105,116,116,101,110,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,99,101,32,105,115,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,119,114,105,116,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,115,101,97,114,99,104,105,110,103,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,97,109,101,100,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,55,50>>,signature => [{attribute,443,spec,{{write_file,2},[{type,443,bounded_fun,[{type,443,'fun',[{type,443,product,[{var,443,'Filename'},{var,443,'Bytes'}]},{type,443,union,[{atom,443,ok},{type,443,tuple,[{atom,443,error},{var,443,'Reason'}]}]}]},[{type,444,constraint,[{atom,444,is_subtype},[{var,444,'Filename'},{user_type,444,name_all,[]}]]},{type,445,constraint,[{atom,445,is_subtype},[{var,445,'Bytes'},{type,445,iodata,[]}]]},{type,446,constraint,[{atom,446,is_subtype},[{var,446,'Reason'},{type,446,union,[{user_type,446,posix,[]},{atom,446,badarg},{atom,446,terminated},{atom,446,system_limit}]}]]}]]}]}}]}},{{function,write_file,3},[{file,[102,105,108,101,46,101,114,108]},{location,455}],[<<119,114,105,116,101,95,102,105,108,101,47,51>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<119,114,105,116,101,95,102,105,108,101,47,50>>]},<<44,32,98,117,116,32,116,97,107,101,115,32,97,32,116,104,105,114,100,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<77,111,100,101,115>>]},<<44,32,97,32,108,105,115,116,32,111,102,32,112,111,115,115,105,98,108,101,32,109,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46,32,84,104,101,32,109,111,100,101,32,102,108,97,103,115,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,97,110,100,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,97,114,101,32,105,109,112,108,105,99,105,116,44,32,115,111,32,116,104,101,121,32,97,114,101,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,48,57>>,signature => [{attribute,455,spec,{{write_file,3},[{type,455,bounded_fun,[{type,455,'fun',[{type,455,product,[{var,455,'Filename'},{var,455,'Bytes'},{var,455,'Modes'}]},{type,455,union,[{atom,455,ok},{type,455,tuple,[{atom,455,error},{var,455,'Reason'}]}]}]},[{type,456,constraint,[{atom,456,is_subtype},[{var,456,'Filename'},{user_type,456,name_all,[]}]]},{type,457,constraint,[{atom,457,is_subtype},[{var,457,'Bytes'},{type,457,iodata,[]}]]},{type,458,constraint,[{atom,458,is_subtype},[{var,458,'Modes'},{type,458,list,[{user_type,458,mode,[]}]}]]},{type,459,constraint,[{atom,459,is_subtype},[{var,459,'Reason'},{type,459,union,[{user_type,459,posix,[]},{atom,459,badarg},{atom,459,terminated},{atom,459,system_limit}]}]]}]]}]}}]}},{{function,write_file_info,3},[{file,[102,105,108,101,46,101,114,108]},{location,380}],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,51>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,50,48>>,equiv => {function,write_file_info,2},signature => [{attribute,380,spec,{{write_file_info,3},[{type,380,bounded_fun,[{type,380,'fun',[{type,380,product,[{var,380,'Filename'},{var,380,'FileInfo'},{var,380,'Opts'}]},{type,380,union,[{atom,380,ok},{type,380,tuple,[{atom,380,error},{var,380,'Reason'}]}]}]},[{type,381,constraint,[{atom,381,is_subtype},[{var,381,'Filename'},{user_type,381,name_all,[]}]]},{type,382,constraint,[{atom,382,is_subtype},[{var,382,'Opts'},{type,382,list,[{user_type,382,file_info_option,[]}]}]]},{type,383,constraint,[{atom,383,is_subtype},[{var,383,'FileInfo'},{user_type,383,file_info,[]}]]},{type,384,constraint,[{atom,384,is_subtype},[{var,384,'Reason'},{type,384,union,[{user_type,384,posix,[]},{atom,384,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,write_file_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,372}],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,102,105,108,101,32,105,110,102,111,114,109,97,116,105,111,110,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,73,110,102,111>>]},<<32,105,115,32,97,32,114,101,99,111,114,100,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<44,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,75,101,114,110,101,108,32,105,110,99,108,117,100,101,32,102,105,108,101,32>>,{code,[],[<<102,105,108,101,46,104,114,108>>]},<<46,32,73,110,99,108,117,100,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,100,105,114,101,99,116,105,118,101,32,105,110,32,116,104,101,32,109,111,100,117,108,101,32,102,114,111,109,32,119,104,105,99,104,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<32,45,105,110,99,108,117,100,101,95,108,105,98,40,34,107,101,114,110,101,108,47,105,110,99,108,117,100,101,47,102,105,108,101,46,104,114,108,34,41,46>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,116,121,112,101,32,115,101,116,32,105,110,32>>,{code,[],[<<97,116,105,109,101>>]},<<44,32>>,{code,[],[<<109,116,105,109,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<99,116,105,109,101>>]},<<32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,116,105,109,101,32,116,121,112,101,32,115,101,116,32,105,110,32>>,{code,[],[<<79,112,116,115,32,58,58,32,123,116,105,109,101,44,32,84,121,112,101,125>>]},<<32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,111,99,97,108>>]}]},{dd,[],[{p,[],[<<73,110,116,101,114,112,114,101,116,115,32,116,104,101,32,116,105,109,101,32,115,101,116,32,97,115,32,108,111,99,97,108,46>>]}]},{dt,[],[{code,[],[<<117,110,105,118,101,114,115,97,108>>]}]},{dd,[],[{p,[],[<<73,110,116,101,114,112,114,101,116,115,32,105,116,32,97,115,32,117,110,105,118,101,114,115,97,108,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<112,111,115,105,120>>]}]},{dd,[],[{p,[],[<<77,117,115,116,32,98,101,32,115,101,99,111,110,100,115,32,115,105,110,99,101,32,111,114,32,98,101,102,111,114,101,32,85,110,105,120,32,116,105,109,101,32,101,112,111,99,104,44,32,119,104,105,99,104,32,105,115,32,49,57,55,48,45,48,49,45,48,49,32,48,48,58,48,48,32,85,84,67,46>>]}]}]},{p,[],[<<68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<123,116,105,109,101,44,32,108,111,99,97,108,125>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,97,110,100,32,111,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,108,111,99,97,108,32,102,105,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,101,108,100,115,32,97,114,101,32,117,115,101,100,32,102,114,111,109,32,116,104,101,32,114,101,99,111,114,100,44,32,105,102,32,116,104,101,121,32,97,114,101,32,115,112,101,99,105,102,105,101,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<109,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,119,114,105,116,116,101,110,46>>]}]},{dt,[],[{code,[],[<<99,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<79,110,32,85,110,105,120,44,32,97,110,121,32,118,97,108,117,101,32,115,112,101,99,105,102,105,101,100,32,102,111,114,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,105,103,110,111,114,101,100,32,40,116,104,101,32,34,99,116,105,109,101,34,32,102,111,114,32,116,104,101,32,102,105,108,101,32,105,115,32,115,101,116,32,116,111,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,41,46,32,79,110,32,87,105,110,100,111,119,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,116,104,101,32,110,101,119,32,99,114,101,97,116,105,111,110,32,116,105,109,101,32,116,111,32,115,101,116,32,102,111,114,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<109,111,100,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,112,101,114,109,105,115,115,105,111,110,115,32,97,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,98,105,116,32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<56,35,48,48,52,48,48>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,50,48,48>>]}]},{dd,[],[{p,[],[<<87,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,49,48,48>>]}]},{dd,[],[{p,[],[<<69,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,52,48>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,50,48>>]}]},{dd,[],[{p,[],[<<87,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,49,48>>]}]},{dd,[],[{p,[],[<<69,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,52>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,50>>]}]},{dd,[],[{p,[],[<<87,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,49>>]}]},{dd,[],[{p,[],[<<69,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<49,54,35,56,48,48>>]}]},{dd,[],[{p,[],[<<83,101,116,32,117,115,101,114,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]},{dt,[],[{code,[],[<<49,54,35,52,48,48>>]}]},{dd,[],[{p,[],[<<83,101,116,32,103,114,111,117,112,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]}]},{p,[],[<<79,110,32,85,110,105,120,32,112,108,97,116,102,111,114,109,115,44,32,111,116,104,101,114,32,98,105,116,115,32,116,104,97,110,32,116,104,111,115,101,32,108,105,115,116,101,100,32,97,98,111,118,101,32,109,97,121,32,98,101,32,115,101,116,46>>]}]},{dt,[],[{code,[],[<<117,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<73,110,100,105,99,97,116,101,115,32,116,104,101,32,102,105,108,101,32,111,119,110,101,114,46,32,73,103,110,111,114,101,100,32,102,111,114,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,46>>]}]},{dt,[],[{code,[],[<<103,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,116,104,101,32,103,114,111,117,112,32,116,104,97,116,32,116,104,101,32,102,105,108,101,32,111,119,110,101,114,32,98,101,108,111,110,103,115,32,116,111,46,32,73,103,110,111,114,101,100,32,102,111,114,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,50,48>>,signature => [{attribute,372,spec,{{write_file_info,2},[{type,372,bounded_fun,[{type,372,'fun',[{type,372,product,[{var,372,'Filename'},{var,372,'FileInfo'}]},{type,372,union,[{atom,372,ok},{type,372,tuple,[{atom,372,error},{var,372,'Reason'}]}]}]},[{type,373,constraint,[{atom,373,is_subtype},[{var,373,'Filename'},{user_type,373,name_all,[]}]]},{type,374,constraint,[{atom,374,is_subtype},[{var,374,'FileInfo'},{user_type,374,file_info,[]}]]},{type,375,constraint,[{atom,375,is_subtype},[{var,375,'Reason'},{type,375,union,[{user_type,375,posix,[]},{atom,375,badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{type,deep_list,0},[{file,[102,105,108,101,46,101,114,108]},{location,101}],[<<45,116,121,112,101,32,100,101,101,112,95,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,101,type,{deep_list,{type,101,list,[{type,101,union,[{type,101,char,[]},{type,101,atom,[]},{user_type,101,deep_list,[]}]}]},[]}}]}},{{type,fd,0},[{file,[102,105,108,101,46,101,114,108]},{location,87}],[<<102,100,40,41>>],#{<<101,110>> => [{p,[],[<<65,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,97,119>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,97,119>>]}]},<<32,109,111,100,101,46>>]}]},#{signature => [{attribute,87,type,{fd,{type,87,record,[{atom,87,file_descriptor}]},[]}}]}},{{type,filename,0},[{file,[102,105,108,101,46,101,114,108]},{location,84}],[<<45,116,121,112,101,32,102,105,108,101,110,97,109,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32,97,108,115,111,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<110,97,109,101,95,97,108,108,40,41>>]}]},<<32,116,121,112,101,46>>]}]},#{signature => [{attribute,84,type,{filename,{type,84,string,[]},[]}}]}},{{type,filename_all,0},[{file,[102,105,108,101,46,101,114,108]},{location,85}],[<<45,116,121,112,101,32,102,105,108,101,110,97,109,101,95,97,108,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32,97,108,115,111,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<110,97,109,101,95,97,108,108,40,41>>]}]},<<32,116,121,112,101,46>>]}]},#{signature => [{attribute,85,type,{filename_all,{type,85,union,[{type,85,string,[]},{type,85,binary,[]}]},[]}}]}},{{type,io_device,0},[{file,[102,105,108,101,46,101,114,108]},{location,88}],[<<45,116,121,112,101,32,105,111,95,100,101,118,105,99,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<59,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,105,115,32,97,32,112,114,111,99,101,115,115,32,104,97,110,100,108,105,110,103,32,73,47,79,45,112,114,111,116,111,99,111,108,115,46>>]}]},#{signature => [{attribute,88,type,{io_device,{type,88,union,[{type,88,pid,[]},{user_type,88,fd,[]}]},[]}}]}},{{type,name,0},[{file,[102,105,108,101,46,101,114,108]},{location,102}],[<<45,116,121,112,101,32,110,97,109,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<73,102,32,86,77,32,105,115,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,44,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<32,97,110,100,32>>,{code,[],[<<99,104,97,114,40,41>>]},<<32,97,114,101,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,62,32,50,53,53,46,32,83,101,101,32,97,108,115,111,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<110,97,109,101,95,97,108,108,40,41>>]}]},<<32,116,121,112,101,46>>]}]},#{signature => [{attribute,102,type,{name,{type,102,union,[{type,102,string,[]},{type,102,atom,[]},{user_type,102,deep_list,[]}]},[]}}]}},{{type,name_all,0},[{file,[102,105,108,101,46,101,114,108]},{location,103}],[<<45,116,121,112,101,32,110,97,109,101,95,97,108,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<73,102,32,86,77,32,105,115,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,44,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,62,32,50,53,53,46,32>>,{code,[],[<<82,97,119,70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,32,102,105,108,101,110,97,109,101,32,110,111,116,32,115,117,98,106,101,99,116,32,116,111,32,85,110,105,99,111,100,101,32,116,114,97,110,115,108,97,116,105,111,110,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,105,116,32,99,97,110,32,99,111,110,116,97,105,110,32,99,104,97,114,97,99,116,101,114,115,32,110,111,116,32,99,111,110,102,111,114,109,105,110,103,32,116,111,32,116,104,101,32,85,110,105,99,111,100,101,32,101,110,99,111,100,105,110,103,32,101,120,112,101,99,116,101,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,40,116,104,97,116,32,105,115,44,32,110,111,110,45,85,84,70,45,56,32,99,104,97,114,97,99,116,101,114,115,32,97,108,116,104,111,117,103,104,32,116,104,101,32,86,77,32,105,115,32,115,116,97,114,116,101,100,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,41,46,32,78,117,108,108,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,116,101,103,101,114,32,118,97,108,117,101,32,122,101,114,111,41,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,97,108,108,111,119,101,100,32,105,110,32,102,105,108,101,110,97,109,101,115,32,40,110,111,116,32,101,118,101,110,32,97,116,32,116,104,101,32,101,110,100,41,46>>]}]},#{signature => [{attribute,103,type,{name_all,{type,103,union,[{type,103,string,[]},{type,103,atom,[]},{user_type,103,deep_list,[]},{ann_type,103,[{var,103,'RawFilename'},{type,103,binary,[]}]}]},[]}}]}},{{type,posix,0},[{file,[102,105,108,101,46,101,114,108]},{location,104}],[<<45,116,121,112,101,32,112,111,115,105,120,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,97,116,111,109,32,116,104,97,116,32,105,115,32,110,97,109,101,100,32,102,114,111,109,32,116,104,101,32,80,79,83,73,88,32,101,114,114,111,114,32,99,111,100,101,115,32,117,115,101,100,32,105,110,32,85,110,105,120,44,32,97,110,100,32,105,110,32,116,104,101,32,114,117,110,116,105,109,101,32,108,105,98,114,97,114,105,101,115,32,111,102,32,109,111,115,116,32,67,32,99,111,109,112,105,108,101,114,115,46>>]}]},#{signature => [{attribute,104,type,{posix,{type,105,union,[{atom,105,eacces},{atom,105,eagain},{atom,106,ebadf},{atom,106,ebadmsg},{atom,106,ebusy},{atom,107,edeadlk},{atom,107,edeadlock},{atom,107,edquot},{atom,108,eexist},{atom,109,efault},{atom,109,efbig},{atom,109,eftype},{atom,110,eintr},{atom,110,einval},{atom,110,eio},{atom,110,eisdir},{atom,111,eloop},{atom,112,emfile},{atom,112,emlink},{atom,112,emultihop},{atom,113,enametoolong},{atom,113,enfile},{atom,114,enobufs},{atom,114,enodev},{atom,114,enolck},{atom,114,enolink},{atom,114,enoent},{atom,115,enomem},{atom,115,enospc},{atom,115,enosr},{atom,115,enostr},{atom,115,enosys},{atom,116,enotblk},{atom,116,enotdir},{atom,116,enotsup},{atom,116,enxio},{atom,117,eopnotsupp},{atom,117,eoverflow},{atom,118,eperm},{atom,118,epipe},{atom,119,erange},{atom,119,erofs},{atom,120,espipe},{atom,120,esrch},{atom,120,estale},{atom,121,etxtbsy},{atom,122,exdev}]},[]}}]}},{{type,date_time,0},[{file,[102,105,108,101,46,101,114,108]},{location,123}],[<<45,116,121,112,101,32,100,97,116,101,95,116,105,109,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<77,117,115,116,32,100,101,110,111,116,101,32,97,32,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{signature => [{attribute,123,type,{date_time,{remote_type,123,[{atom,123,calendar},{atom,123,datetime},[]]},[]}}]}},{{type,file_info,0},[{file,[102,105,108,101,46,101,114,108]},{location,86}],[<<45,116,121,112,101,32,102,105,108,101,95,105,110,102,111,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,86,type,{file_info,{type,86,record,[{atom,86,file_info}]},[]}}]}},{{type,location,0},[{file,[102,105,108,101,46,101,114,108]},{location,89}],[<<45,116,121,112,101,32,108,111,99,97,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,89,type,{location,{type,89,union,[{type,89,integer,[]},{type,89,tuple,[{atom,89,bof},{ann_type,89,[{var,89,'Offset'},{type,89,integer,[]}]}]},{type,90,tuple,[{atom,90,cur},{ann_type,90,[{var,90,'Offset'},{type,90,integer,[]}]}]},{type,91,tuple,[{atom,91,eof},{ann_type,91,[{var,91,'Offset'},{type,91,integer,[]}]}]},{atom,91,bof},{atom,91,cur},{atom,91,eof}]},[]}}]}},{{type,mode,0},[{file,[102,105,108,101,46,101,114,108]},{location,92}],[<<45,116,121,112,101,32,109,111,100,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,92,type,{mode,{type,92,union,[{atom,92,read},{atom,92,write},{atom,92,append},{atom,93,exclusive},{atom,93,raw},{atom,93,binary},{type,94,tuple,[{atom,94,delayed_write},{ann_type,95,[{var,95,'Size'},{type,95,non_neg_integer,[]}]},{ann_type,96,[{var,96,'Delay'},{type,96,non_neg_integer,[]}]}]},{atom,97,delayed_write},{type,97,tuple,[{atom,97,read_ahead},{ann_type,97,[{var,97,'Size'},{type,97,pos_integer,[]}]}]},{atom,98,read_ahead},{atom,98,compressed},{type,99,tuple,[{atom,99,encoding},{remote_type,99,[{atom,99,unicode},{atom,99,encoding},[]]}]},{atom,100,sync}]},[]}}]}},{{type,file_info_option,0},[{file,[102,105,108,101,46,101,114,108]},{location,129}],[<<45,116,121,112,101,32,102,105,108,101,95,105,110,102,111,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,129,type,{file_info_option,{type,129,union,[{type,129,tuple,[{atom,129,time},{atom,129,local}]},{type,129,tuple,[{atom,129,time},{atom,129,universal}]},{type,130,tuple,[{atom,130,time},{atom,130,posix}]},{atom,130,raw}]},[]}}]}}]}. \ No newline at end of file
+{docs_v1,[{file,[102,105,108,101,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<84,104,105,115,32,109,111,100,117,108,101,32,112,114,111,118,105,100,101,115,32,97,110,32,105,110,116,101,114,102,97,99,101,32,116,111,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<70,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,97,114,101,32,111,110,108,121,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,97,112,112,101,97,114,32,97,116,111,109,105,99,32,119,104,101,110,32,103,111,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,32,115,97,109,101,32,102,105,108,101,32,115,101,114,118,101,114,46,32,65,32,78,73,70,32,111,114,32,111,116,104,101,114,32,79,83,32,112,114,111,99,101,115,115,32,109,97,121,32,111,98,115,101,114,118,101,32,105,110,116,101,114,109,101,100,105,97,116,101,32,115,116,101,112,115,32,111,110,32,99,101,114,116,97,105,110,32,111,112,101,114,97,116,105,111,110,115,32,111,110,32,115,111,109,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,115,44,32,101,103,46,32,114,101,110,97,109,105,110,103,32,97,110,32,101,120,105,115,116,105,110,103,32,102,105,108,101,32,111,110,32,87,105,110,100,111,119,115,44,32,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]},<<32>>]},<<111,110,32,97,110,121,32,79,83,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,119,114,105,116,105,110,103,46>>]}]},{p,[],[<<82,101,103,97,114,100,105,110,103,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,44,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,99,97,110,32,111,112,101,114,97,116,101,32,105,110,32,116,119,111,32,109,111,100,101,115,46,32,84,104,101,32,99,117,114,114,101,110,116,32,109,111,100,101,32,99,97,110,32,98,101,32,113,117,101,114,105,101,100,32,117,115,105,110,103,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>]}]},<<46,32,73,116,32,114,101,116,117,114,110,115,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,111,114,32>>,{code,[],[<<117,116,102,56>>]},<<46>>]},{p,[],[<<73,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,109,111,100,101,44,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,100,111,101,115,32,110,111,116,32,99,104,97,110,103,101,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32,102,105,108,101,110,97,109,101,115,46,32,73,110,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,44,32,102,105,108,101,110,97,109,101,115,32,99,97,110,32,99,111,110,116,97,105,110,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,103,114,101,97,116,101,114,32,116,104,97,110,32,50,53,53,32,97,110,100,32,116,104,101,32,86,77,32,99,111,110,118,101,114,116,115,32,102,105,108,101,110,97,109,101,115,32,98,97,99,107,32,97,110,100,32,102,111,114,116,104,32,116,111,32,116,104,101,32,110,97,116,105,118,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,40,117,115,117,97,108,108,121,32,85,84,70,45,56,44,32,98,117,116,32,85,84,70,45,49,54,32,111,110,32,87,105,110,100,111,119,115,41,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,109,111,100,101,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,46,32,87,105,110,100,111,119,115,44,32,77,97,99,79,83,32,88,32,97,110,100,32,65,110,100,114,111,105,100,32,101,110,102,111,114,99,101,32,99,111,110,115,105,115,116,101,110,116,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,97,110,100,32,116,104,101,114,101,102,111,114,101,32,116,104,101,32,86,77,32,117,115,101,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,46>>]},{p,[],[<<79,110,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,115,32,119,105,116,104,32,116,114,97,110,115,112,97,114,101,110,116,32,110,97,109,105,110,103,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,97,108,108,32,85,110,105,120,32,115,121,115,116,101,109,115,32,101,120,99,101,112,116,32,77,97,99,79,83,32,88,41,44,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<32,105,102,32,116,104,101,32,116,101,114,109,105,110,97,108,32,115,117,112,112,111,114,116,115,32,85,84,70,45,56,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<46,32,84,104,101,32,100,101,102,97,117,108,116,32,99,97,110,32,98,101,32,111,118,101,114,114,105,100,100,101,110,32,117,115,105,110,103,32>>,{code,[],[<<43,102,110,108>>]},<<32,40,116,111,32,102,111,114,99,101,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,109,111,100,101,41,32,111,114,32>>,{code,[],[<<43,102,110,117>>]},<<32,40,116,111,32,102,111,114,99,101,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,41,32,119,104,101,110,32,115,116,97,114,116,105,110,103,32>>,{a,[{href,<<101,114,116,115,58,101,114,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,99,111,109>>}],[{code,[],[<<101,114,108>>]}]},<<46>>]},{p,[],[<<79,110,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,115,32,119,105,116,104,32,116,114,97,110,115,112,97,114,101,110,116,32,110,97,109,105,110,103,44,32,102,105,108,101,115,32,99,97,110,32,98,101,32,105,110,99,111,110,115,105,115,116,101,110,116,108,121,32,110,97,109,101,100,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,115,111,109,101,32,102,105,108,101,115,32,97,114,101,32,101,110,99,111,100,101,100,32,105,110,32,85,84,70,45,56,32,119,104,105,108,101,32,111,116,104,101,114,115,32,97,114,101,32,101,110,99,111,100,101,100,32,105,110,32,73,83,79,32,76,97,116,105,110,45,49,46,32,84,104,101,32,99,111,110,99,101,112,116,32,111,102,32>>,{em,[],[<<114,97,119,32,102,105,108,101,110,97,109,101,115>>]},<<32,105,115,32,105,110,116,114,111,100,117,99,101,100,32,116,111,32,104,97,110,100,108,101,32,102,105,108,101,32,115,121,115,116,101,109,115,32,119,105,116,104,32,105,110,99,111,110,115,105,115,116,101,110,116,32,110,97,109,105,110,103,32,119,104,101,110,32,114,117,110,110,105,110,103,32,105,110,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,46>>]},{p,[],[<<65,32>>,{em,[],[<<114,97,119,32,102,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,32,102,105,108,101,110,97,109,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,105,110,97,114,121,46,32,84,104,101,32,69,114,108,97,110,103,32,86,77,32,100,111,101,115,32,110,111,116,32,116,114,97,110,115,108,97,116,101,32,97,32,102,105,108,101,110,97,109,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,105,110,97,114,121,32,111,110,32,115,121,115,116,101,109,115,32,119,105,116,104,32,116,114,97,110,115,112,97,114,101,110,116,32,110,97,109,105,110,103,46>>]},{p,[],[<<87,104,101,110,32,114,117,110,110,105,110,103,32,105,110,32>>,{code,[],[<<117,116,102,56>>]},<<32,109,111,100,101,44,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,108,105,115,116,95,100,105,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<108,105,115,116,95,100,105,114,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,107,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,108,105,110,107,47,49>>]}]},<<32,110,101,118,101,114,32,114,101,116,117,114,110,32,114,97,119,32,102,105,108,101,110,97,109,101,115,46,32,84,111,32,114,101,116,117,114,110,32,97,108,108,32,102,105,108,101,110,97,109,101,115,32,105,110,99,108,117,100,105,110,103,32,114,97,119,32,102,105,108,101,110,97,109,101,115,44,32,117,115,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,108,105,115,116,95,100,105,114,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<108,105,115,116,95,100,105,114,95,97,108,108,47,49>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,107,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,101,97,100,95,108,105,110,107,95,97,108,108,47,49>>]}]},<<46>>]},{p,[],[<<83,101,101,32,97,108,115,111,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,95,117,115,97,103,101,35,110,111,116,101,115,45,97,98,111,117,116,45,114,97,119,45,102,105,108,101,110,97,109,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,103,117,105,100,101>>}],[<<78,111,116,101,115,32,65,98,111,117,116,32,82,97,119,32,70,105,108,101,110,97,109,101,115>>]},<<32,105,110,32,116,104,101,32,83,84,68,76,73,66,32,85,115,101,114,39,115,32,71,117,105,100,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<70,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,117,115,101,100,32,116,111,32,97,99,99,101,112,116,32,102,105,108,101,110,97,109,101,115,32,99,111,110,116,97,105,110,105,110,103,32,110,117,108,108,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,116,101,103,101,114,32,118,97,108,117,101,32,122,101,114,111,41,46,32,84,104,105,115,32,99,97,117,115,101,100,32,116,104,101,32,110,97,109,101,32,116,111,32,98,101,32,116,114,117,110,99,97,116,101,100,32,97,110,100,32,105,110,32,115,111,109,101,32,99,97,115,101,115,32,97,114,103,117,109,101,110,116,115,32,116,111,32,112,114,105,109,105,116,105,118,101,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,98,101,32,109,105,120,101,100,32,117,112,46,32,70,105,108,101,110,97,109,101,115,32,99,111,110,116,97,105,110,105,110,103,32,110,117,108,108,32,99,104,97,114,97,99,116,101,114,115,32,105,110,115,105,100,101,32,116,104,101,32,102,105,108,101,110,97,109,101,32,97,114,101,32,110,111,119,32>>,{em,[],[<<114,101,106,101,99,116,101,100>>]},<<32,97,110,100,32,119,105,108,108,32,99,97,117,115,101,32,112,114,105,109,105,116,105,118,101,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,102,97,105,108,46>>]}]},{h2,[],[<<80,79,83,73,88,32,69,114,114,111,114,32,67,111,100,101,115>>]},{ul,[],[{li,[],[{code,[],[<<101,97,99,99,101,115>>]},<<32,45,32,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100>>]},{li,[],[{code,[],[<<101,97,103,97,105,110>>]},<<32,45,32,82,101,115,111,117,114,99,101,32,116,101,109,112,111,114,97,114,105,108,121,32,117,110,97,118,97,105,108,97,98,108,101>>]},{li,[],[{code,[],[<<101,98,97,100,102>>]},<<32,45,32,66,97,100,32,102,105,108,101,32,110,117,109,98,101,114>>]},{li,[],[{code,[],[<<101,98,117,115,121>>]},<<32,45,32,70,105,108,101,32,98,117,115,121>>]},{li,[],[{code,[],[<<101,100,113,117,111,116>>]},<<32,45,32,68,105,115,107,32,113,117,111,116,97,32,101,120,99,101,101,100,101,100>>]},{li,[],[{code,[],[<<101,101,120,105,115,116>>]},<<32,45,32,70,105,108,101,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115>>]},{li,[],[{code,[],[<<101,102,97,117,108,116>>]},<<32,45,32,66,97,100,32,97,100,100,114,101,115,115,32,105,110,32,115,121,115,116,101,109,32,99,97,108,108,32,97,114,103,117,109,101,110,116>>]},{li,[],[{code,[],[<<101,102,98,105,103>>]},<<32,45,32,70,105,108,101,32,116,111,111,32,108,97,114,103,101>>]},{li,[],[{code,[],[<<101,105,110,116,114>>]},<<32,45,32,73,110,116,101,114,114,117,112,116,101,100,32,115,121,115,116,101,109,32,99,97,108,108>>]},{li,[],[{code,[],[<<101,105,110,118,97,108>>]},<<32,45,32,73,110,118,97,108,105,100,32,97,114,103,117,109,101,110,116>>]},{li,[],[{code,[],[<<101,105,111>>]},<<32,45,32,73,47,79,32,101,114,114,111,114>>]},{li,[],[{code,[],[<<101,105,115,100,105,114>>]},<<32,45,32,73,108,108,101,103,97,108,32,111,112,101,114,97,116,105,111,110,32,111,110,32,97,32,100,105,114,101,99,116,111,114,121>>]},{li,[],[{code,[],[<<101,108,111,111,112>>]},<<32,45,32,84,111,111,32,109,97,110,121,32,108,101,118,101,108,115,32,111,102,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115>>]},{li,[],[{code,[],[<<101,109,102,105,108,101>>]},<<32,45,32,84,111,111,32,109,97,110,121,32,111,112,101,110,32,102,105,108,101,115>>]},{li,[],[{code,[],[<<101,109,108,105,110,107>>]},<<32,45,32,84,111,111,32,109,97,110,121,32,108,105,110,107,115>>]},{li,[],[{code,[],[<<101,110,97,109,101,116,111,111,108,111,110,103>>]},<<32,45,32,70,105,108,101,110,97,109,101,32,116,111,111,32,108,111,110,103>>]},{li,[],[{code,[],[<<101,110,102,105,108,101>>]},<<32,45,32,70,105,108,101,32,116,97,98,108,101,32,111,118,101,114,102,108,111,119>>]},{li,[],[{code,[],[<<101,110,111,100,101,118>>]},<<32,45,32,78,111,32,115,117,99,104,32,100,101,118,105,99,101>>]},{li,[],[{code,[],[<<101,110,111,101,110,116>>]},<<32,45,32,78,111,32,115,117,99,104,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121>>]},{li,[],[{code,[],[<<101,110,111,109,101,109>>]},<<32,45,32,78,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121>>]},{li,[],[{code,[],[<<101,110,111,115,112,99>>]},<<32,45,32,78,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,100,101,118,105,99,101>>]},{li,[],[{code,[],[<<101,110,111,116,98,108,107>>]},<<32,45,32,66,108,111,99,107,32,100,101,118,105,99,101,32,114,101,113,117,105,114,101,100>>]},{li,[],[{code,[],[<<101,110,111,116,100,105,114>>]},<<32,45,32,78,111,116,32,97,32,100,105,114,101,99,116,111,114,121>>]},{li,[],[{code,[],[<<101,110,111,116,115,117,112>>]},<<32,45,32,79,112,101,114,97,116,105,111,110,32,110,111,116,32,115,117,112,112,111,114,116,101,100>>]},{li,[],[{code,[],[<<101,110,120,105,111>>]},<<32,45,32,78,111,32,115,117,99,104,32,100,101,118,105,99,101,32,111,114,32,97,100,100,114,101,115,115>>]},{li,[],[{code,[],[<<101,112,101,114,109>>]},<<32,45,32,78,111,116,32,111,119,110,101,114>>]},{li,[],[{code,[],[<<101,112,105,112,101>>]},<<32,45,32,66,114,111,107,101,110,32,112,105,112,101>>]},{li,[],[{code,[],[<<101,114,111,102,115>>]},<<32,45,32,82,101,97,100,45,111,110,108,121,32,102,105,108,101,32,115,121,115,116,101,109>>]},{li,[],[{code,[],[<<101,115,112,105,112,101>>]},<<32,45,32,73,110,118,97,108,105,100,32,115,101,101,107>>]},{li,[],[{code,[],[<<101,115,114,99,104>>]},<<32,45,32,78,111,32,115,117,99,104,32,112,114,111,99,101,115,115>>]},{li,[],[{code,[],[<<101,115,116,97,108,101>>]},<<32,45,32,83,116,97,108,101,32,114,101,109,111,116,101,32,102,105,108,101,32,104,97,110,100,108,101>>]},{li,[],[{code,[],[<<101,120,100,101,118>>]},<<32,45,32,67,114,111,115,115,45,100,111,109,97,105,110,32,108,105,110,107>>]}]},{h2,[],[<<80,101,114,102,111,114,109,97,110,99,101>>]},{p,[],[<<70,111,114,32,105,110,99,114,101,97,115,101,100,32,112,101,114,102,111,114,109,97,110,99,101,44,32,114,97,119,32,102,105,108,101,115,32,97,114,101,32,114,101,99,111,109,109,101,110,100,101,100,46>>]},{p,[],[<<65,32,110,111,114,109,97,108,32,102,105,108,101,32,105,115,32,114,101,97,108,108,121,32,97,32,112,114,111,99,101,115,115,32,115,111,32,105,116,32,99,97,110,32,98,101,32,117,115,101,100,32,97,115,32,97,110,32,73,47,79,32,100,101,118,105,99,101,32,40,115,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111>>]}]},<<41,46,32,84,104,101,114,101,102,111,114,101,44,32,119,104,101,110,32,100,97,116,97,32,105,115,32,119,114,105,116,116,101,110,32,116,111,32,97,32,110,111,114,109,97,108,32,102,105,108,101,44,32,116,104,101,32,115,101,110,100,105,110,103,32,111,102,32,116,104,101,32,100,97,116,97,32,116,111,32,116,104,101,32,102,105,108,101,32,112,114,111,99,101,115,115,44,32,99,111,112,105,101,115,32,97,108,108,32,100,97,116,97,32,116,104,97,116,32,97,114,101,32,110,111,116,32,98,105,110,97,114,105,101,115,46,32,79,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,105,110,32,98,105,110,97,114,121,32,109,111,100,101,32,97,110,100,32,119,114,105,116,105,110,103,32,98,105,110,97,114,105,101,115,32,105,115,32,116,104,101,114,101,102,111,114,101,32,114,101,99,111,109,109,101,110,100,101,100,46,32,73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,111,110,32,97,110,111,116,104,101,114,32,110,111,100,101,44,32,111,114,32,105,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,114,117,110,115,32,97,115,32,115,108,97,118,101,32,116,111,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,97,110,111,116,104,101,114,32,110,111,100,101,44,32,97,108,115,111,32,98,105,110,97,114,105,101,115,32,97,114,101,32,99,111,112,105,101,100,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<82,97,119,32,102,105,108,101,115,32,117,115,101,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,111,102,32,116,104,101,32,104,111,115,116,32,109,97,99,104,105,110,101,32,111,102,32,116,104,101,32,110,111,100,101,46,32,70,111,114,32,110,111,114,109,97,108,32,102,105,108,101,115,32,40,110,111,110,45,114,97,119,41,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,117,115,101,100,32,116,111,32,102,105,110,100,32,116,104,101,32,102,105,108,101,115,44,32,97,110,100,32,105,102,32,116,104,101,32,110,111,100,101,32,105,115,32,114,117,110,110,105,110,103,32,105,116,115,32,102,105,108,101,32,115,101,114,118,101,114,32,97,115,32,115,108,97,118,101,32,116,111,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,97,110,111,116,104,101,114,32,110,111,100,101,44,32,97,110,100,32,116,104,101,32,111,116,104,101,114,32,110,111,100,101,32,114,117,110,115,32,111,110,32,115,111,109,101,32,111,116,104,101,114,32,104,111,115,116,32,109,97,99,104,105,110,101,44,32,116,104,101,121,32,99,97,110,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,102,105,108,101,32,115,121,115,116,101,109,115,46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,105,115,32,115,101,108,100,111,109,32,97,32,112,114,111,98,108,101,109,46>>]}]},{p,[],[{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<32,99,97,110,32,98,101,32,103,105,118,101,110,32,116,104,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,97,100,95,97,104,101,97,100>>]},<<32,116,111,32,116,117,114,110,32,111,110,32,99,97,99,104,105,110,103,44,32,119,104,105,99,104,32,119,105,108,108,32,114,101,100,117,99,101,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,115,32,97,110,100,32,103,114,101,97,116,108,121,32,105,109,112,114,111,118,101,32,112,101,114,102,111,114,109,97,110,99,101,32,102,111,114,32,115,109,97,108,108,32,114,101,97,100,115,32,97,110,100,32,119,114,105,116,101,115,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,111,118,101,114,104,101,97,100,32,119,111,110,39,116,32,100,105,115,97,112,112,101,97,114,32,99,111,109,112,108,101,116,101,108,121,32,97,110,100,32,105,116,39,115,32,98,101,115,116,32,116,111,32,107,101,101,112,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,97,32,109,105,110,105,109,117,109,46,32,65,115,32,97,32,99,111,110,116,114,105,118,101,100,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,117,110,99,116,105,111,110,32,119,114,105,116,101,115,32,52,77,66,32,105,110,32,50,46,53,32,115,101,99,111,110,100,115,32,119,104,101,110,32,116,101,115,116,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,40,78,97,109,101,41,32,45,62,10,32,32,32,32,123,111,107,44,32,70,100,125,32,61,32,102,105,108,101,58,111,112,101,110,40,78,97,109,101,44,32,91,114,97,119,44,32,119,114,105,116,101,44,32,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,98,105,110,97,114,121,93,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,70,100,44,32,52,32,98,115,108,32,50,48,41,44,10,32,32,32,32,102,105,108,101,58,99,108,111,115,101,40,70,100,41,46,10,10,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,95,70,100,44,32,48,41,32,45,62,10,32,32,32,32,111,107,59,10,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,70,100,44,32,77,41,32,45,62,10,32,32,32,32,111,107,32,61,32,102,105,108,101,58,119,114,105,116,101,40,70,100,44,32,60,60,48,62,62,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,115,108,111,119,95,49,40,70,100,44,32,77,32,45,32,49,41,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,102,117,110,99,116,105,111,110,97,108,108,121,32,101,113,117,105,118,97,108,101,110,116,32,99,111,100,101,32,119,114,105,116,101,115,32,49,50,56,32,98,121,116,101,115,32,112,101,114,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<32,97,110,100,32,115,111,32,100,111,101,115,32,116,104,101,32,115,97,109,101,32,119,111,114,107,32,105,110,32,48,46,48,56,32,115,101,99,111,110,100,115,44,32,119,104,105,99,104,32,105,115,32,114,111,117,103,104,108,121,32,51,48,32,116,105,109,101,115,32,102,97,115,116,101,114,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<99,114,101,97,116,101,95,102,105,108,101,40,78,97,109,101,41,32,45,62,10,32,32,32,32,123,111,107,44,32,70,100,125,32,61,32,102,105,108,101,58,111,112,101,110,40,78,97,109,101,44,32,91,114,97,119,44,32,119,114,105,116,101,44,32,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,98,105,110,97,114,121,93,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,52,32,98,115,108,32,50,48,41,44,10,32,32,32,32,102,105,108,101,58,99,108,111,115,101,40,70,100,41,44,10,32,32,32,32,111,107,46,10,10,99,114,101,97,116,101,95,102,105,108,101,95,49,40,95,70,100,44,32,48,41,32,45,62,10,32,32,32,32,111,107,59,10,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,41,32,119,104,101,110,32,77,32,62,61,32,49,50,56,32,45,62,10,32,32,32,32,111,107,32,61,32,102,105,108,101,58,119,114,105,116,101,40,70,100,44,32,60,60,48,58,40,49,50,56,41,47,117,110,105,116,58,56,62,62,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,32,45,32,49,50,56,41,59,10,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,41,32,45,62,10,32,32,32,32,111,107,32,61,32,102,105,108,101,58,119,114,105,116,101,40,70,100,44,32,60,60,48,58,40,77,41,47,117,110,105,116,58,56,62,62,41,44,10,32,32,32,32,99,114,101,97,116,101,95,102,105,108,101,95,49,40,70,100,44,32,77,32,45,32,49,41,46>>]}]},{p,[],[<<87,104,101,110,32,119,114,105,116,105,110,103,32,100,97,116,97,32,105,116,39,115,32,103,101,110,101,114,97,108,108,121,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,111,32,119,114,105,116,101,32,97,32,108,105,115,116,32,111,102,32,98,105,110,97,114,105,101,115,32,114,97,116,104,101,114,32,116,104,97,110,32,97,32,108,105,115,116,32,111,102,32,105,110,116,101,103,101,114,115,46,32,73,116,32,105,115,32,110,111,116,32,110,101,101,100,101,100,32,116,111,32,102,108,97,116,116,101,110,32,97,32,100,101,101,112,32,108,105,115,116,32,98,101,102,111,114,101,32,119,114,105,116,105,110,103,46,32,79,110,32,85,110,105,120,32,104,111,115,116,115,44,32,115,99,97,116,116,101,114,32,111,117,116,112,117,116,44,32,119,104,105,99,104,32,119,114,105,116,101,115,32,97,32,115,101,116,32,111,102,32,98,117,102,102,101,114,115,32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,105,115,32,117,115,101,100,32,119,104,101,110,32,112,111,115,115,105,98,108,101,46,32,73,110,32,116,104,105,115,32,119,97,121,32>>,{code,[],[<<119,114,105,116,101,40,70,68,44,32,91,66,105,110,49,44,32,66,105,110,50,32,124,32,66,105,110,51,93,41>>]},<<32,119,114,105,116,101,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32,98,105,110,97,114,105,101,115,32,119,105,116,104,111,117,116,32,99,111,112,121,105,110,103,32,116,104,101,32,100,97,116,97,32,97,116,32,97,108,108,44,32,101,120,99,101,112,116,32,102,111,114,32,112,101,114,104,97,112,115,32,100,101,101,112,32,100,111,119,110,32,105,110,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,107,101,114,110,101,108,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,102,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,32,119,104,101,110,32,97,99,99,101,115,115,105,110,103,32,97,110,32,111,112,101,110,32,102,105,108,101,32,119,105,116,104,32,109,111,100,117,108,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111>>]}]},<<44,32,116,104,101,32,112,114,111,99,101,115,115,32,104,97,110,100,108,105,110,103,32,116,104,101,32,102,105,108,101,32,101,120,105,116,115,46,32,84,104,101,32,100,101,97,100,32,102,105,108,101,32,112,114,111,99,101,115,115,32,99,97,110,32,104,97,110,103,32,105,102,32,97,32,112,114,111,99,101,115,115,32,116,114,105,101,115,32,116,111,32,97,99,99,101,115,115,32,105,116,32,108,97,116,101,114,46,32,84,104,105,115,32,119,105,108,108,32,98,101,32,102,105,120,101,100,32,105,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,46>>]}]},{h2,[],[<<83,101,101,32,65,108,115,111>>]},{p,[],[{a,[{href,<<115,116,100,108,105,98,58,102,105,108,101,110,97,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<102,105,108,101,110,97,109,101,40,51,41>>]}]}]}]},#{name => <<102,105,108,101>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,102,105,108,101,46,120,109,108],types => #{{date_time,0} => {attribute,{123,2},type,{date_time,{remote_type,{123,22},[{atom,{123,22},calendar},{atom,{123,31},datetime},[]]},[]}},{deep_list,0} => {attribute,{101,2},type,{deep_list,{type,{101,22},list,[{type,{101,23},union,[{type,{101,23},char,[]},{type,{101,32},atom,[]},{user_type,{101,41},deep_list,[]}]}]},[]}},{delete_option,0} => {attribute,{126,2},type,{delete_option,{atom,{126,26},raw},[]}},{fd,0} => {attribute,{87,2},type,{fd,{type,{87,22},record,[{atom,{87,23},file_descriptor}]},[]}},{file_info,0} => {attribute,{86,2},type,{file_info,{type,{86,22},record,[{atom,{86,23},file_info}]},[]}},{file_info_option,0} => {attribute,{129,2},type,{file_info_option,{type,{129,29},union,[{type,{129,29},tuple,[{atom,{129,30},time},{atom,{129,38},local}]},{type,{129,49},tuple,[{atom,{129,50},time},{atom,{129,58},universal}]},{type,{130,8},tuple,[{atom,{130,9},time},{atom,{130,17},posix}]},{atom,{130,28},raw}]},[]}},{filename,0} => {attribute,{84,2},type,{filename,{type,{84,22},string,[]},[]}},{filename_all,0} => {attribute,{85,2},type,{filename_all,{type,{85,25},union,[{type,{85,25},string,[]},{type,{85,36},binary,[]}]},[]}},{io_device,0} => {attribute,{88,2},type,{io_device,{type,{88,22},union,[{type,{88,22},pid,[]},{user_type,{88,30},fd,[]}]},[]}},{location,0} => {attribute,{89,2},type,{location,{type,{89,22},union,[{type,{89,22},integer,[]},{type,{89,34},tuple,[{atom,{89,35},bof},{ann_type,{89,42},[{var,{89,42},'Offset'},{type,{89,52},integer,[]}]}]},{type,{90,22},tuple,[{atom,{90,23},cur},{ann_type,{90,30},[{var,{90,30},'Offset'},{type,{90,40},integer,[]}]}]},{type,{91,8},tuple,[{atom,{91,9},eof},{ann_type,{91,16},[{var,{91,16},'Offset'},{type,{91,26},integer,[]}]}]},{atom,{91,39},bof},{atom,{91,47},cur},{atom,{91,55},eof}]},[]}},{mode,0} => {attribute,{92,2},type,{mode,{type,{92,22},union,[{atom,{92,22},read},{atom,{92,31},write},{atom,{92,41},append},{atom,{93,22},exclusive},{atom,{93,36},raw},{atom,{93,44},binary},{type,{94,8},tuple,[{atom,{94,9},delayed_write},{ann_type,{95,23},[{var,{95,23},'Size'},{type,{95,31},non_neg_integer,[]}]},{ann_type,{96,23},[{var,{96,23},'Delay'},{type,{96,32},non_neg_integer,[]}]}]},{atom,{97,8},delayed_write},{type,{97,26},tuple,[{atom,{97,27},read_ahead},{ann_type,{97,41},[{var,{97,41},'Size'},{type,{97,49},pos_integer,[]}]}]},{atom,{98,8},read_ahead},{atom,{98,23},compressed},{type,{99,8},tuple,[{atom,{99,9},encoding},{remote_type,{99,21},[{atom,{99,21},unicode},{atom,{99,29},encoding},[]]}]},{atom,{100,8},sync}]},[]}},{name,0} => {attribute,{102,2},type,{name,{type,{102,22},union,[{type,{102,22},string,[]},{type,{102,33},atom,[]},{user_type,{102,42},deep_list,[]}]},[]}},{name_all,0} => {attribute,{103,2},type,{name_all,{type,{103,22},union,[{type,{103,22},string,[]},{type,{103,33},atom,[]},{user_type,{103,42},deep_list,[]},{ann_type,{103,57},[{var,{103,57},'RawFilename'},{type,{103,72},binary,[]}]}]},[]}},{posix,0} => {attribute,{104,2},type,{posix,{type,{105,9},union,[{atom,{105,9},eacces},{atom,{105,20},eagain},{atom,{106,9},ebadf},{atom,{106,19},ebadmsg},{atom,{106,31},ebusy},{atom,{107,9},edeadlk},{atom,{107,21},edeadlock},{atom,{107,35},edquot},{atom,{108,9},eexist},{atom,{109,9},efault},{atom,{109,20},efbig},{atom,{109,30},eftype},{atom,{110,9},eintr},{atom,{110,19},einval},{atom,{110,30},eio},{atom,{110,38},eisdir},{atom,{111,9},eloop},{atom,{112,9},emfile},{atom,{112,20},emlink},{atom,{112,31},emultihop},{atom,{113,9},enametoolong},{atom,{113,26},enfile},{atom,{114,9},enobufs},{atom,{114,21},enodev},{atom,{114,32},enolck},{atom,{114,43},enolink},{atom,{114,55},enoent},{atom,{115,9},enomem},{atom,{115,20},enospc},{atom,{115,31},enosr},{atom,{115,41},enostr},{atom,{115,52},enosys},{atom,{116,9},enotblk},{atom,{116,21},enotdir},{atom,{116,33},enotsup},{atom,{116,45},enxio},{atom,{117,9},eopnotsupp},{atom,{117,24},eoverflow},{atom,{118,9},eperm},{atom,{118,19},epipe},{atom,{119,9},erange},{atom,{119,20},erofs},{atom,{120,9},espipe},{atom,{120,21},esrch},{atom,{120,32},estale},{atom,{121,9},etxtbsy},{atom,{122,9},exdev}]},[]}},{posix_file_advise,0} => {attribute,{124,2},type,{posix_file_advise,{type,{124,30},union,[{atom,{124,30},normal},{atom,{124,41},sequential},{atom,{124,56},random},{atom,{125,30},no_reuse},{atom,{125,43},will_need},{atom,{125,57},dont_need}]},[]}},{sendfile_option,0} => {attribute,{127,2},type,{sendfile_option,{type,{127,28},union,[{type,{127,28},tuple,[{atom,{127,29},chunk_size},{type,{127,41},non_neg_integer,[]}]},{type,{128,7},tuple,[{atom,{128,8},use_threads},{type,{128,21},boolean,[]}]}]},[]}}}},[{{function,altname,1},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<97,108,116,110,97,109,101,47,49>>],hidden,#{}},{{function,copy_opened,3},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<99,111,112,121,95,111,112,101,110,101,100,47,51>>],hidden,#{}},{{function,ipread_s32bu_p32bu,3},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<105,112,114,101,97,100,95,115,51,50,98,117,95,112,51,50,98,117,47,51>>],hidden,#{}},{{function,ipread_s32bu_p32bu_int,3},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<105,112,114,101,97,100,95,115,51,50,98,117,95,112,51,50,98,117,95,105,110,116,47,51>>],hidden,#{}},{{function,path_eval,3},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<112,97,116,104,95,101,118,97,108,47,51>>],hidden,#{}},{{function,raw_read_file_info,1},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<114,97,119,95,114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>],hidden,#{}},{{function,raw_write_file_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,0}],[<<114,97,119,95,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>],hidden,#{}},{{function,advise,4},[{file,[102,105,108,101,46,101,114,108]},{location,565}],[<<97,100,118,105,115,101,47,52>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<112,111,115,105,120,95,102,105,108,101,95,97,100,118,105,115,101>>}],[]}]},{p,[],[{code,[],[<<97,100,118,105,115,101,47,52>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,97,110,110,111,117,110,99,101,32,97,110,32,105,110,116,101,110,116,105,111,110,32,116,111,32,97,99,99,101,115,115,32,102,105,108,101,32,100,97,116,97,32,105,110,32,97,32,115,112,101,99,105,102,105,99,32,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,102,117,116,117,114,101,44,32,116,104,117,115,32,97,108,108,111,119,105,110,103,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,116,111,32,112,101,114,102,111,114,109,32,97,112,112,114,111,112,114,105,97,116,101,32,111,112,116,105,109,105,122,97,116,105,111,110,115,46>>]},{p,[],[<<79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,109,105,103,104,116,32,104,97,118,101,32,110,111,32,101,102,102,101,99,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,56>>,signature => [{attribute,{565,2},spec,{{advise,4},[{type,{565,13},bounded_fun,[{type,{565,13},'fun',[{type,{565,13},product,[{var,{565,14},'IoDevice'},{var,{565,24},'Offset'},{var,{565,32},'Length'},{var,{565,40},'Advise'}]},{type,{565,51},union,[{atom,{565,51},ok},{type,{565,56},tuple,[{atom,{565,57},error},{var,{565,64},'Reason'}]}]}]},[{type,{566,7},constraint,[{atom,{566,7},is_subtype},[{var,{566,7},'IoDevice'},{user_type,{566,19},io_device,[]}]]},{type,{567,7},constraint,[{atom,{567,7},is_subtype},[{var,{567,7},'Offset'},{type,{567,17},integer,[]}]]},{type,{568,7},constraint,[{atom,{568,7},is_subtype},[{var,{568,7},'Length'},{type,{568,17},integer,[]}]]},{type,{569,7},constraint,[{atom,{569,7},is_subtype},[{var,{569,7},'Advise'},{user_type,{569,17},posix_file_advise,[]}]]},{type,{570,7},constraint,[{atom,{570,7},is_subtype},[{var,{570,7},'Reason'},{type,{570,17},union,[{user_type,{570,17},posix,[]},{atom,{570,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,allocate,3},[{file,[102,105,108,101,46,101,114,108]},{location,579}],[<<97,108,108,111,99,97,116,101,47,51>>],#{<<101,110>> => [{p,[],[{code,[],[<<97,108,108,111,99,97,116,101,47,51>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,112,114,101,97,108,108,111,99,97,116,101,32,115,112,97,99,101,32,102,111,114,32,97,32,102,105,108,101,46>>]},{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,111,110,108,121,32,115,117,99,99,101,101,100,115,32,105,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,112,114,111,118,105,100,101,32,116,104,105,115,32,102,101,97,116,117,114,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,57>>,signature => [{attribute,{579,2},spec,{{allocate,3},[{type,{579,15},bounded_fun,[{type,{579,15},'fun',[{type,{579,15},product,[{var,{579,16},'File'},{var,{579,22},'Offset'},{var,{579,30},'Length'}]},{type,{580,2},union,[{atom,{580,2},ok},{type,{580,9},tuple,[{atom,{580,10},error},{user_type,{580,19},posix,[]}]}]}]},[{type,{581,7},constraint,[{atom,{581,7},is_subtype},[{var,{581,7},'File'},{user_type,{581,15},io_device,[]}]]},{type,{582,7},constraint,[{atom,{582,7},is_subtype},[{var,{582,7},'Offset'},{type,{582,17},non_neg_integer,[]}]]},{type,{583,7},constraint,[{atom,{583,7},is_subtype},[{var,{583,7},'Length'},{type,{583,17},non_neg_integer,[]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,change_group,2},[{file,[102,105,108,101,46,101,114,108]},{location,1249}],[<<99,104,97,110,103,101,95,103,114,111,117,112,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,103,114,111,117,112,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,56>>,signature => [{attribute,{1249,2},spec,{{change_group,2},[{type,{1249,19},bounded_fun,[{type,{1249,19},'fun',[{type,{1249,19},product,[{var,{1249,20},'Filename'},{var,{1249,30},'Gid'}]},{type,{1249,38},union,[{atom,{1249,38},ok},{type,{1249,43},tuple,[{atom,{1249,44},error},{var,{1249,51},'Reason'}]}]}]},[{type,{1250,7},constraint,[{atom,{1250,7},is_subtype},[{var,{1250,7},'Filename'},{user_type,{1250,19},name_all,[]}]]},{type,{1251,7},constraint,[{atom,{1251,7},is_subtype},[{var,{1251,7},'Gid'},{type,{1251,14},integer,[]}]]},{type,{1252,7},constraint,[{atom,{1252,7},is_subtype},[{var,{1252,7},'Reason'},{type,{1252,17},union,[{user_type,{1252,17},posix,[]},{atom,{1252,27},badarg}]}]]}]]}]}}]}},{{function,change_mode,2},[{file,[102,105,108,101,46,101,114,108]},{location,1221}],[<<99,104,97,110,103,101,95,109,111,100,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,112,101,114,109,105,115,115,105,111,110,115,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,49,54>>,signature => [{attribute,{1221,2},spec,{{change_mode,2},[{type,{1221,18},bounded_fun,[{type,{1221,18},'fun',[{type,{1221,18},product,[{var,{1221,19},'Filename'},{var,{1221,29},'Mode'}]},{type,{1221,38},union,[{atom,{1221,38},ok},{type,{1221,43},tuple,[{atom,{1221,44},error},{var,{1221,51},'Reason'}]}]}]},[{type,{1222,7},constraint,[{atom,{1222,7},is_subtype},[{var,{1222,7},'Filename'},{user_type,{1222,19},name_all,[]}]]},{type,{1223,7},constraint,[{atom,{1223,7},is_subtype},[{var,{1223,7},'Mode'},{type,{1223,15},integer,[]}]]},{type,{1224,7},constraint,[{atom,{1224,7},is_subtype},[{var,{1224,7},'Reason'},{type,{1224,17},union,[{user_type,{1224,17},posix,[]},{atom,{1224,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,change_owner,2},[{file,[102,105,108,101,46,101,114,108]},{location,1230}],[<<99,104,97,110,103,101,95,111,119,110,101,114,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,111,119,110,101,114,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,50,52>>,signature => [{attribute,{1230,2},spec,{{change_owner,2},[{type,{1230,19},bounded_fun,[{type,{1230,19},'fun',[{type,{1230,19},product,[{var,{1230,20},'Filename'},{var,{1230,30},'Uid'}]},{type,{1230,38},union,[{atom,{1230,38},ok},{type,{1230,43},tuple,[{atom,{1230,44},error},{var,{1230,51},'Reason'}]}]}]},[{type,{1231,7},constraint,[{atom,{1231,7},is_subtype},[{var,{1231,7},'Filename'},{user_type,{1231,19},name_all,[]}]]},{type,{1232,7},constraint,[{atom,{1232,7},is_subtype},[{var,{1232,7},'Uid'},{type,{1232,14},integer,[]}]]},{type,{1233,7},constraint,[{atom,{1233,7},is_subtype},[{var,{1233,7},'Reason'},{type,{1233,17},union,[{user_type,{1233,17},posix,[]},{atom,{1233,27},badarg}]}]]}]]}]}}]}},{{function,change_owner,3},[{file,[102,105,108,101,46,101,114,108]},{location,1239}],[<<99,104,97,110,103,101,95,111,119,110,101,114,47,51>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,111,119,110,101,114,32,97,110,100,32,103,114,111,117,112,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,51,50>>,signature => [{attribute,{1239,2},spec,{{change_owner,3},[{type,{1239,19},bounded_fun,[{type,{1239,19},'fun',[{type,{1239,19},product,[{var,{1239,20},'Filename'},{var,{1239,30},'Uid'},{var,{1239,35},'Gid'}]},{type,{1239,43},union,[{atom,{1239,43},ok},{type,{1239,48},tuple,[{atom,{1239,49},error},{var,{1239,56},'Reason'}]}]}]},[{type,{1240,7},constraint,[{atom,{1240,7},is_subtype},[{var,{1240,7},'Filename'},{user_type,{1240,19},name_all,[]}]]},{type,{1241,7},constraint,[{atom,{1241,7},is_subtype},[{var,{1241,7},'Uid'},{type,{1241,14},integer,[]}]]},{type,{1242,7},constraint,[{atom,{1242,7},is_subtype},[{var,{1242,7},'Gid'},{type,{1242,14},integer,[]}]]},{type,{1243,7},constraint,[{atom,{1243,7},is_subtype},[{var,{1243,7},'Reason'},{type,{1243,17},union,[{user_type,{1243,17},posix,[]},{atom,{1243,27},badarg}]}]]}]]}]}}]}},{{function,change_time,2},[{file,[102,105,108,101,46,101,114,108]},{location,1258}],[<<99,104,97,110,103,101,95,116,105,109,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,97,110,100,32,97,99,99,101,115,115,32,116,105,109,101,115,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,52,48>>,signature => [{attribute,{1258,2},spec,{{change_time,2},[{type,{1258,18},bounded_fun,[{type,{1258,18},'fun',[{type,{1258,18},product,[{var,{1258,19},'Filename'},{var,{1258,29},'Mtime'}]},{type,{1258,39},union,[{atom,{1258,39},ok},{type,{1258,44},tuple,[{atom,{1258,45},error},{var,{1258,52},'Reason'}]}]}]},[{type,{1259,7},constraint,[{atom,{1259,7},is_subtype},[{var,{1259,7},'Filename'},{user_type,{1259,19},name_all,[]}]]},{type,{1260,7},constraint,[{atom,{1260,7},is_subtype},[{var,{1260,7},'Mtime'},{user_type,{1260,16},date_time,[]}]]},{type,{1261,7},constraint,[{atom,{1261,7},is_subtype},[{var,{1261,7},'Reason'},{type,{1261,17},union,[{user_type,{1261,17},posix,[]},{atom,{1261,27},badarg}]}]]}]]}]}}]}},{{function,change_time,3},[{file,[102,105,108,101,46,101,114,108]},{location,1268}],[<<99,104,97,110,103,101,95,116,105,109,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,97,110,100,32,108,97,115,116,32,97,99,99,101,115,115,32,116,105,109,101,115,32,111,102,32,97,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,52,56>>,signature => [{attribute,{1268,2},spec,{{change_time,3},[{type,{1268,18},bounded_fun,[{type,{1268,18},'fun',[{type,{1268,18},product,[{var,{1268,19},'Filename'},{var,{1268,29},'Atime'},{var,{1268,36},'Mtime'}]},{type,{1268,46},union,[{atom,{1268,46},ok},{type,{1268,51},tuple,[{atom,{1268,52},error},{var,{1268,59},'Reason'}]}]}]},[{type,{1269,7},constraint,[{atom,{1269,7},is_subtype},[{var,{1269,7},'Filename'},{user_type,{1269,19},name_all,[]}]]},{type,{1270,7},constraint,[{atom,{1270,7},is_subtype},[{var,{1270,7},'Atime'},{user_type,{1270,16},date_time,[]}]]},{type,{1271,7},constraint,[{atom,{1271,7},is_subtype},[{var,{1271,7},'Mtime'},{user_type,{1271,16},date_time,[]}]]},{type,{1272,7},constraint,[{atom,{1272,7},is_subtype},[{var,{1272,7},'Reason'},{type,{1272,17},union,[{user_type,{1272,17},posix,[]},{atom,{1272,27},badarg}]}]]}]]}]}}]}},{{function,close,1},[{file,[102,105,108,101,46,101,114,108]},{location,546}],[<<99,108,111,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<67,108,111,115,101,115,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,73,116,32,109,111,115,116,108,121,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<44,32,101,120,99,101,112,116,32,102,111,114,32,115,111,109,101,32,115,101,118,101,114,101,32,101,114,114,111,114,115,32,115,117,99,104,32,97,115,32,111,117,116,32,111,102,32,109,101,109,111,114,121,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]},<<32,119,97,115,32,117,115,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,44,32>>,{code,[],[<<99,108,111,115,101,47,49>>]},<<32,99,97,110,32,114,101,116,117,114,110,32,97,110,32,111,108,100,32,119,114,105,116,101,32,101,114,114,111,114,32,97,110,100,32,110,111,116,32,101,118,101,110,32,116,114,121,32,116,111,32,99,108,111,115,101,32,116,104,101,32,102,105,108,101,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,53,54>>,signature => [{attribute,{546,2},spec,{{close,1},[{type,{546,12},bounded_fun,[{type,{546,12},'fun',[{type,{546,12},product,[{var,{546,13},'IoDevice'}]},{type,{546,26},union,[{atom,{546,26},ok},{type,{546,31},tuple,[{atom,{546,32},error},{var,{546,39},'Reason'}]}]}]},[{type,{547,7},constraint,[{atom,{547,7},is_subtype},[{var,{547,7},'IoDevice'},{user_type,{547,19},io_device,[]}]]},{type,{548,7},constraint,[{atom,{548,7},is_subtype},[{var,{548,7},'Reason'},{type,{548,17},union,[{user_type,{548,17},posix,[]},{atom,{548,27},badarg},{atom,{548,36},terminated}]}]]}]]}]}}]}},{{function,consult,1},[{file,[102,105,108,101,46,101,114,108]},{location,1025}],[<<99,111,110,115,117,108,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,69,114,108,97,110,103,32,116,101,114,109,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,44,32,102,114,111,109,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,84,101,114,109,115,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,119,97,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,116,101,114,109,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,84,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,44,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<46>>]}]}]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<102,46,116,120,116,58,32,32,123,112,101,114,115,111,110,44,32,34,107,97,108,108,101,34,44,32,50,53,125,46,10,32,32,32,32,32,32,32,32,123,112,101,114,115,111,110,44,32,34,112,101,108,108,101,34,44,32,51,48,125,46>>]}]},{pre,[],[{code,[],[<<49,62,32,102,105,108,101,58,99,111,110,115,117,108,116,40,34,102,46,116,120,116,34,41,46,10,123,111,107,44,91,123,112,101,114,115,111,110,44,34,107,97,108,108,101,34,44,50,53,125,44,123,112,101,114,115,111,110,44,34,112,101,108,108,101,34,44,51,48,125,93,125>>]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,54,57>>,signature => [{attribute,{1025,2},spec,{{consult,1},[{type,{1025,14},bounded_fun,[{type,{1025,14},'fun',[{type,{1025,14},product,[{var,{1025,15},'Filename'}]},{type,{1025,28},union,[{type,{1025,28},tuple,[{atom,{1025,29},ok},{var,{1025,33},'Terms'}]},{type,{1025,42},tuple,[{atom,{1025,43},error},{var,{1025,50},'Reason'}]}]}]},[{type,{1026,7},constraint,[{atom,{1026,7},is_subtype},[{var,{1026,7},'Filename'},{user_type,{1026,19},name_all,[]}]]},{type,{1027,7},constraint,[{atom,{1027,7},is_subtype},[{var,{1027,7},'Terms'},{type,{1027,16},list,[{type,{1027,17},term,[]}]}]]},{type,{1028,7},constraint,[{atom,{1028,7},is_subtype},[{var,{1028,7},'Reason'},{type,{1028,17},union,[{user_type,{1028,17},posix,[]},{atom,{1028,27},badarg},{atom,{1028,36},terminated},{atom,{1028,49},system_limit},{type,{1029,17},tuple,[{ann_type,{1029,18},[{var,{1029,18},'Line'},{type,{1029,26},integer,[]}]},{ann_type,{1029,37},[{var,{1029,37},'Mod'},{type,{1029,44},module,[]}]},{ann_type,{1029,54},[{var,{1029,54},'Term'},{type,{1029,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,copy,3},[{file,[102,105,108,101,46,101,114,108]},{location,788}],[<<99,111,112,121,47,51>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,48,55>>,equiv => {function,copy,2},signature => [{attribute,{788,2},spec,{{copy,3},[{type,{788,11},bounded_fun,[{type,{788,11},'fun',[{type,{788,11},product,[{var,{788,12},'Source'},{var,{788,20},'Destination'},{var,{788,33},'ByteCount'}]},{type,{789,14},union,[{type,{789,14},tuple,[{atom,{789,15},ok},{var,{789,19},'BytesCopied'}]},{type,{789,34},tuple,[{atom,{789,35},error},{var,{789,42},'Reason'}]}]}]},[{type,{790,7},constraint,[{atom,{790,7},is_subtype},[{var,{790,7},'Source'},{type,{790,17},union,[{user_type,{790,17},io_device,[]},{var,{790,31},'Filename'},{type,{790,42},tuple,[{var,{790,43},'Filename'},{var,{790,53},'Modes'}]}]}]]},{type,{791,7},constraint,[{atom,{791,7},is_subtype},[{var,{791,7},'Destination'},{type,{791,22},union,[{user_type,{791,22},io_device,[]},{var,{791,36},'Filename'},{type,{791,47},tuple,[{var,{791,48},'Filename'},{var,{791,58},'Modes'}]}]}]]},{type,{792,7},constraint,[{atom,{792,7},is_subtype},[{var,{792,7},'Filename'},{user_type,{792,19},name_all,[]}]]},{type,{793,7},constraint,[{atom,{793,7},is_subtype},[{var,{793,7},'Modes'},{type,{793,16},list,[{user_type,{793,17},mode,[]}]}]]},{type,{794,7},constraint,[{atom,{794,7},is_subtype},[{var,{794,7},'ByteCount'},{type,{794,20},union,[{type,{794,20},non_neg_integer,[]},{atom,{794,40},infinity}]}]]},{type,{795,7},constraint,[{atom,{795,7},is_subtype},[{var,{795,7},'BytesCopied'},{type,{795,22},non_neg_integer,[]}]]},{type,{796,7},constraint,[{atom,{796,7},is_subtype},[{var,{796,7},'Reason'},{type,{796,17},union,[{user_type,{796,17},posix,[]},{atom,{796,27},badarg},{atom,{796,36},terminated}]}]]}]]}]}}]}},{{function,copy,2},[{file,[102,105,108,101,46,101,114,108]},{location,777}],[<<99,111,112,121,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,112,105,101,115,32>>,{code,[],[<<66,121,116,101,67,111,117,110,116>>]},<<32,98,121,116,101,115,32,102,114,111,109,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,116,111,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<46,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,114,101,102,101,114,32,116,111,32,101,105,116,104,101,114,32,102,105,108,101,110,97,109,101,115,32,111,114,32,73,79,32,100,101,118,105,99,101,115,32,102,114,111,109,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<111,112,101,110,47,50>>]},<<46,32>>,{code,[],[<<66,121,116,101,67,111,117,110,116>>]},<<32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<105,110,102,105,110,105,116,121>>]},<<44,32,100,101,110,111,116,105,110,103,32,97,110,32,105,110,102,105,110,105,116,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,46>>]},{p,[],[<<65,114,103,117,109,101,110,116,32>>,{code,[],[<<77,111,100,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,112,111,115,115,105,98,108,101,32,109,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<44,32,97,110,100,32,100,101,102,97,117,108,116,115,32,116,111,32>>,{code,[],[<<91,93>>]},<<46>>]},{p,[],[<<73,102,32,98,111,116,104,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,114,101,102,101,114,32,116,111,32,102,105,108,101,110,97,109,101,115,44,32,116,104,101,32,102,105,108,101,115,32,97,114,101,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<91,114,101,97,100,44,32,98,105,110,97,114,121,93>>]},<<32,97,110,100,32>>,{code,[],[<<91,119,114,105,116,101,44,32,98,105,110,97,114,121,93>>]},<<32,112,114,101,112,101,110,100,101,100,32,116,111,32,116,104,101,105,114,32,109,111,100,101,32,108,105,115,116,115,44,32,114,101,115,112,101,99,116,105,118,101,108,121,44,32,116,111,32,111,112,116,105,109,105,122,101,32,116,104,101,32,99,111,112,121,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,102,105,108,101,110,97,109,101,44,32,105,116,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<114,101,97,100>>]},<<32,109,111,100,101,32,112,114,101,112,101,110,100,101,100,32,116,111,32,116,104,101,32,109,111,100,101,32,108,105,115,116,32,98,101,102,111,114,101,32,116,104,101,32,99,111,112,121,44,32,97,110,100,32,99,108,111,115,101,100,32,119,104,101,110,32,100,111,110,101,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,102,105,108,101,110,97,109,101,44,32,105,116,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,109,111,100,101,32,112,114,101,112,101,110,100,101,100,32,116,111,32,116,104,101,32,109,111,100,101,32,108,105,115,116,32,98,101,102,111,114,101,32,116,104,101,32,99,111,112,121,44,32,97,110,100,32,99,108,111,115,101,100,32,119,104,101,110,32,100,111,110,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,121,116,101,115,67,111,112,105,101,100,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<66,121,116,101,115,67,111,112,105,101,100>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,116,104,97,116,32,119,97,115,32,99,111,112,105,101,100,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<66,121,116,101,67,111,117,110,116>>]},<<32,105,102,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,101,110,99,111,117,110,116,101,114,101,100,32,111,110,32,116,104,101,32,115,111,117,114,99,101,46,32,73,102,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,102,97,105,108,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58,32,97,115,32,102,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<32,105,102,32,97,32,102,105,108,101,32,104,97,100,32,116,111,32,98,101,32,111,112,101,110,101,100,44,32,97,110,100,32,97,115,32,102,111,114,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,48,55>>,signature => [{attribute,{777,2},spec,{{copy,2},[{type,{777,11},bounded_fun,[{type,{777,11},'fun',[{type,{777,11},product,[{var,{777,12},'Source'},{var,{777,20},'Destination'}]},{type,{777,36},union,[{type,{777,36},tuple,[{atom,{777,37},ok},{var,{777,41},'BytesCopied'}]},{type,{777,56},tuple,[{atom,{777,57},error},{var,{777,64},'Reason'}]}]}]},[{type,{778,7},constraint,[{atom,{778,7},is_subtype},[{var,{778,7},'Source'},{type,{778,17},union,[{user_type,{778,17},io_device,[]},{var,{778,31},'Filename'},{type,{778,42},tuple,[{var,{778,43},'Filename'},{var,{778,53},'Modes'}]}]}]]},{type,{779,7},constraint,[{atom,{779,7},is_subtype},[{var,{779,7},'Destination'},{type,{779,22},union,[{user_type,{779,22},io_device,[]},{var,{779,36},'Filename'},{type,{779,47},tuple,[{var,{779,48},'Filename'},{var,{779,58},'Modes'}]}]}]]},{type,{780,7},constraint,[{atom,{780,7},is_subtype},[{var,{780,7},'Filename'},{user_type,{780,19},name_all,[]}]]},{type,{781,7},constraint,[{atom,{781,7},is_subtype},[{var,{781,7},'Modes'},{type,{781,16},list,[{user_type,{781,17},mode,[]}]}]]},{type,{782,7},constraint,[{atom,{782,7},is_subtype},[{var,{782,7},'BytesCopied'},{type,{782,22},non_neg_integer,[]}]]},{type,{783,7},constraint,[{atom,{783,7},is_subtype},[{var,{783,7},'Reason'},{type,{783,17},union,[{user_type,{783,17},posix,[]},{atom,{783,27},badarg},{atom,{783,36},terminated}]}]]}]]}]}}]}},{{function,datasync,1},[{file,[102,105,108,101,46,101,114,108]},{location,731}],[<<100,97,116,97,115,121,110,99,47,49>>],#{<<101,110>> => [{p,[],[<<69,110,115,117,114,101,115,32,116,104,97,116,32,97,110,121,32,98,117,102,102,101,114,115,32,107,101,112,116,32,98,121,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,40,110,111,116,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,41,32,97,114,101,32,119,114,105,116,116,101,110,32,116,111,32,100,105,115,107,46,32,73,110,32,109,97,110,121,32,119,97,121,115,32,105,116,32,114,101,115,101,109,98,108,101,115,32>>,{code,[],[<<102,115,121,110,99>>]},<<32,98,117,116,32,105,116,32,100,111,101,115,32,110,111,116,32,117,112,100,97,116,101,32,115,111,109,101,32,111,102,32,116,104,101,32,109,101,116,97,100,97,116,97,32,111,102,32,116,104,101,32,102,105,108,101,44,32,115,117,99,104,32,97,115,32,116,104,101,32,97,99,99,101,115,115,32,116,105,109,101,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,104,97,115,32,110,111,32,101,102,102,101,99,116,46>>]},{p,[],[<<65,112,112,108,105,99,97,116,105,111,110,115,32,116,104,97,116,32,97,99,99,101,115,115,32,100,97,116,97,98,97,115,101,115,32,111,114,32,108,111,103,32,102,105,108,101,115,32,111,102,116,101,110,32,119,114,105,116,101,32,97,32,116,105,110,121,32,100,97,116,97,32,102,114,97,103,109,101,110,116,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,111,110,101,32,108,105,110,101,32,105,110,32,97,32,108,111,103,32,102,105,108,101,41,32,97,110,100,32,116,104,101,110,32,99,97,108,108,32>>,{code,[],[<<102,115,121,110,99,40,41>>]},<<32,105,109,109,101,100,105,97,116,101,108,121,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,116,104,101,32,119,114,105,116,116,101,110,32,100,97,116,97,32,105,115,32,112,104,121,115,105,99,97,108,108,121,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,104,97,114,100,32,100,105,115,107,46,32,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32>>,{code,[],[<<102,115,121,110,99,40,41>>]},<<32,97,108,119,97,121,115,32,105,110,105,116,105,97,116,101,115,32,116,119,111,32,119,114,105,116,101,32,111,112,101,114,97,116,105,111,110,115,58,32,111,110,101,32,102,111,114,32,116,104,101,32,110,101,119,108,121,32,119,114,105,116,116,101,110,32,100,97,116,97,32,97,110,100,32,97,110,111,116,104,101,114,32,111,110,101,32,116,111,32,117,112,100,97,116,101,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,115,116,111,114,101,100,32,105,110,32,116,104,101,32>>,{code,[],[<<105,110,111,100,101>>]},<<46,32,73,102,32,116,104,101,32,109,111,100,105,102,105,99,97,116,105,111,110,32,116,105,109,101,32,105,115,32,110,111,116,32,97,32,112,97,114,116,32,111,102,32,116,104,101,32,116,114,97,110,115,97,99,116,105,111,110,32,99,111,110,99,101,112,116,44,32>>,{code,[],[<<102,100,97,116,97,115,121,110,99,40,41>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,97,118,111,105,100,32,117,110,110,101,99,101,115,115,97,114,121,32>>,{code,[],[<<105,110,111,100,101>>]},<<32,100,105,115,107,32,119,114,105,116,101,32,111,112,101,114,97,116,105,111,110,115,46>>]},{p,[],[<<65,118,97,105,108,97,98,108,101,32,111,110,108,121,32,105,110,32,115,111,109,101,32,80,79,83,73,88,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,99,97,108,108,32,114,101,115,117,108,116,115,32,105,110,32,97,32,99,97,108,108,32,116,111,32>>,{code,[],[<<102,115,121,110,99,40,41>>]},<<44,32,111,114,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,105,110,32,115,121,115,116,101,109,115,32,110,111,116,32,112,114,111,118,105,100,105,110,103,32,116,104,101,32>>,{code,[],[<<102,100,97,116,97,115,121,110,99,40,41>>]},<<32,115,121,115,99,97,108,108,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,52,53>>,signature => [{attribute,{731,2},spec,{{datasync,1},[{type,{731,15},bounded_fun,[{type,{731,15},'fun',[{type,{731,15},product,[{var,{731,16},'IoDevice'}]},{type,{731,29},union,[{atom,{731,29},ok},{type,{731,34},tuple,[{atom,{731,35},error},{var,{731,42},'Reason'}]}]}]},[{type,{732,7},constraint,[{atom,{732,7},is_subtype},[{var,{732,7},'IoDevice'},{user_type,{732,19},io_device,[]}]]},{type,{733,7},constraint,[{atom,{733,7},is_subtype},[{var,{733,7},'Reason'},{type,{733,17},union,[{user_type,{733,17},posix,[]},{atom,{733,27},badarg},{atom,{733,36},terminated}]}]]}]]}]}}],since => <<79,84,80,32,82,49,52,66>>}},{{function,del_dir,1},[{file,[102,105,108,101,46,101,114,108]},{location,256}],[<<100,101,108,95,100,105,114,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,100,101,108,101,116,101,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<68,105,114>>]},<<46,32,84,104,101,32,100,105,114,101,99,116,111,114,121,32,109,117,115,116,32,98,101,32,101,109,112,116,121,32,98,101,102,111,114,101,32,105,116,32,99,97,110,32,98,101,32,100,101,108,101,116,101,100,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,105,115,32,110,111,116,32,101,109,112,116,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[<<65,116,116,101,109,112,116,32,116,111,32,100,101,108,101,116,101,32,116,104,101,32,99,117,114,114,101,110,116,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,97,99,99,101,115>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,51,54,56>>,signature => [{attribute,{256,2},spec,{{del_dir,1},[{type,{256,14},bounded_fun,[{type,{256,14},'fun',[{type,{256,14},product,[{var,{256,15},'Dir'}]},{type,{256,23},union,[{atom,{256,23},ok},{type,{256,28},tuple,[{atom,{256,29},error},{var,{256,36},'Reason'}]}]}]},[{type,{257,7},constraint,[{atom,{257,7},is_subtype},[{var,{257,7},'Dir'},{user_type,{257,14},name_all,[]}]]},{type,{258,7},constraint,[{atom,{258,7},is_subtype},[{var,{258,7},'Reason'},{type,{258,17},union,[{user_type,{258,17},posix,[]},{atom,{258,27},badarg}]}]]}]]}]}}]}},{{function,del_dir_r,1},[{file,[102,105,108,101,46,101,114,108]},{location,263}],[<<100,101,108,95,100,105,114,95,114,47,49>>],#{<<101,110>> => [{p,[],[<<68,101,108,101,116,101,115,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<70,105,108,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,105,108,101>>]},<<32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,44,32,105,116,115,32,99,111,110,116,101,110,116,115,32,105,115,32,102,105,114,115,116,32,114,101,99,117,114,115,105,118,101,108,121,32,100,101,108,101,116,101,100,46,32,82,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<111,107>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,101,114,97,116,105,111,110,32,99,111,109,112,108,101,116,101,100,32,119,105,116,104,111,117,116,32,101,114,114,111,114,115,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,112,111,115,105,120,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,97,99,99,101,115,115,105,110,103,32,111,114,32,100,101,108,101,116,105,110,103,32>>,{code,[],[<<70,105,108,101>>]},<<46,32,73,102,32,115,111,109,101,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32,117,110,100,101,114,32>>,{code,[],[<<70,105,108,101>>]},<<32,99,111,117,108,100,32,110,111,116,32,98,101,32,100,101,108,101,116,101,100,44,32>>,{code,[],[<<70,105,108,101>>]},<<32,99,97,110,110,111,116,32,98,101,32,100,101,108,101,116,101,100,32,97,115,32,105,116,32,105,115,32,110,111,110,45,101,109,112,116,121,44,32,97,110,100,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,101,120,105,115,116,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,48,52>>,signature => [{attribute,{263,2},spec,{{del_dir_r,1},[{type,{263,16},bounded_fun,[{type,{263,16},'fun',[{type,{263,16},product,[{var,{263,17},'File'}]},{type,{263,26},union,[{atom,{263,26},ok},{type,{263,31},tuple,[{atom,{263,32},error},{var,{263,39},'Reason'}]}]}]},[{type,{264,7},constraint,[{atom,{264,7},is_subtype},[{var,{264,7},'File'},{user_type,{264,15},name_all,[]}]]},{type,{265,7},constraint,[{atom,{265,7},is_subtype},[{var,{265,7},'Reason'},{type,{265,17},union,[{user_type,{265,17},posix,[]},{atom,{265,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,50,51,46,48>>}},{{function,delete,2},[{file,[102,105,108,101,46,101,114,108]},{location,221}],[<<100,101,108,101,116,101,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,50,54>>,equiv => {function,delete,1},signature => [{attribute,{221,2},spec,{{delete,2},[{type,{221,13},bounded_fun,[{type,{221,13},'fun',[{type,{221,13},product,[{var,{221,14},'Filename'},{var,{221,24},'Opts'}]},{type,{221,33},union,[{atom,{221,33},ok},{type,{221,38},tuple,[{atom,{221,39},error},{var,{221,46},'Reason'}]}]}]},[{type,{222,7},constraint,[{atom,{222,7},is_subtype},[{var,{222,7},'Filename'},{user_type,{222,19},name_all,[]}]]},{type,{223,7},constraint,[{atom,{223,7},is_subtype},[{var,{223,7},'Opts'},{type,{223,15},list,[{user_type,{223,16},delete_option,[]}]}]]},{type,{224,7},constraint,[{atom,{224,7},is_subtype},[{var,{224,7},'Reason'},{type,{224,17},union,[{user_type,{224,17},posix,[]},{atom,{224,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,delete,1},[{file,[102,105,108,101,46,101,114,108]},{location,214}],[<<100,101,108,101,116,101,47,49>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<100,101,108,101,116,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<84,114,105,101,115,32,116,111,32,100,101,108,101,116,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,46,32,84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,105,110,32,112,97,114,116,105,99,117,108,97,114,32,100,117,114,105,110,103,32,116,104,101,32,101,97,114,108,121,32,98,111,111,116,32,115,116,97,103,101,32,119,104,101,110,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,121,101,116,32,114,101,103,105,115,116,101,114,101,100,44,32,116,111,32,115,116,105,108,108,32,98,101,32,97,98,108,101,32,116,111,32,100,101,108,101,116,101,32,108,111,99,97,108,32,102,105,108,101,115,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,116,104,101,32,102,105,108,101,32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,115,46>>]}]},{dt,[],[{code,[],[<<101,112,101,114,109>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,32,97,110,100,32,116,104,101,32,117,115,101,114,32,105,115,32,110,111,116,32,115,117,112,101,114,117,115,101,114,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,104,97,115,32,97,110,32,105,109,112,114,111,112,101,114,32,116,121,112,101,44,32,115,117,99,104,32,97,115,32,116,117,112,108,101,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,44,32,97,32,98,97,100,32,116,121,112,101,32,102,111,114,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,119,105,108,108,32,112,114,111,98,97,98,108,121,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,50,54>>,signature => [{attribute,{214,2},spec,{{delete,1},[{type,{214,13},bounded_fun,[{type,{214,13},'fun',[{type,{214,13},product,[{var,{214,14},'Filename'}]},{type,{214,27},union,[{atom,{214,27},ok},{type,{214,32},tuple,[{atom,{214,33},error},{var,{214,40},'Reason'}]}]}]},[{type,{215,7},constraint,[{atom,{215,7},is_subtype},[{var,{215,7},'Filename'},{user_type,{215,19},name_all,[]}]]},{type,{216,7},constraint,[{atom,{216,7},is_subtype},[{var,{216,7},'Reason'},{type,{216,17},union,[{user_type,{216,17},posix,[]},{atom,{216,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,50,52,46,48>>}},{{function,eval,1},[{file,[102,105,108,101,46,101,114,108]},{location,1065}],[<<101,118,97,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,32,102,114,111,109,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,84,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,32,105,115,32,110,111,116,32,114,101,116,117,114,110,101,100,59,32,97,110,121,32,101,120,112,114,101,115,115,105,111,110,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,102,105,108,101,32,109,117,115,116,32,98,101,32,116,104,101,114,101,32,102,111,114,32,105,116,115,32,115,105,100,101,32,101,102,102,101,99,116,46,32,82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<111,107>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,119,97,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,84,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,44,32,117,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,52,54,57>>,signature => [{attribute,{1065,2},spec,{{eval,1},[{type,{1065,11},bounded_fun,[{type,{1065,11},'fun',[{type,{1065,11},product,[{var,{1065,12},'Filename'}]},{type,{1065,25},union,[{atom,{1065,25},ok},{type,{1065,30},tuple,[{atom,{1065,31},error},{var,{1065,38},'Reason'}]}]}]},[{type,{1066,7},constraint,[{atom,{1066,7},is_subtype},[{var,{1066,7},'Filename'},{user_type,{1066,19},name_all,[]}]]},{type,{1067,7},constraint,[{atom,{1067,7},is_subtype},[{var,{1067,7},'Reason'},{type,{1067,17},union,[{user_type,{1067,17},posix,[]},{atom,{1067,27},badarg},{atom,{1067,36},terminated},{atom,{1067,49},system_limit},{type,{1068,17},tuple,[{ann_type,{1068,18},[{var,{1068,18},'Line'},{type,{1068,26},integer,[]}]},{ann_type,{1068,37},[{var,{1068,37},'Mod'},{type,{1068,44},module,[]}]},{ann_type,{1068,54},[{var,{1068,54},'Term'},{type,{1068,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,eval,2},[{file,[102,105,108,101,46,101,114,108]},{location,1073}],[<<101,118,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<101,118,97,108,47,49>>]},<<44,32,98,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,32>>,{code,[],[<<66,105,110,100,105,110,103,115>>]},<<32,97,114,101,32,117,115,101,100,32,105,110,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,46,32,70,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,44,32,115,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,114,108,95,101,118,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,101,118,97,108,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,48,51>>,signature => [{attribute,{1073,2},spec,{{eval,2},[{type,{1073,11},bounded_fun,[{type,{1073,11},'fun',[{type,{1073,11},product,[{var,{1073,12},'Filename'},{var,{1073,22},'Bindings'}]},{type,{1073,35},union,[{atom,{1073,35},ok},{type,{1073,40},tuple,[{atom,{1073,41},error},{var,{1073,48},'Reason'}]}]}]},[{type,{1074,7},constraint,[{atom,{1074,7},is_subtype},[{var,{1074,7},'Filename'},{user_type,{1074,19},name_all,[]}]]},{type,{1075,7},constraint,[{atom,{1075,7},is_subtype},[{var,{1075,7},'Bindings'},{remote_type,{1075,19},[{atom,{1075,19},erl_eval},{atom,{1075,28},binding_struct},[]]}]]},{type,{1076,7},constraint,[{atom,{1076,7},is_subtype},[{var,{1076,7},'Reason'},{type,{1076,17},union,[{user_type,{1076,17},posix,[]},{atom,{1076,27},badarg},{atom,{1076,36},terminated},{atom,{1076,49},system_limit},{type,{1077,17},tuple,[{ann_type,{1077,18},[{var,{1077,18},'Line'},{type,{1077,26},integer,[]}]},{ann_type,{1077,37},[{var,{1077,37},'Mod'},{type,{1077,44},module,[]}]},{ann_type,{1077,54},[{var,{1077,54},'Term'},{type,{1077,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,format_error,1},[{file,[102,105,108,101,46,101,114,108]},{location,146}],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>],#{<<101,110>> => [{p,[],[<<71,105,118,101,110,32,116,104,101,32,101,114,114,111,114,32,114,101,97,115,111,110,32,114,101,116,117,114,110,101,100,32,98,121,32,97,110,121,32,102,117,110,99,116,105,111,110,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,114,101,116,117,114,110,115,32,97,32,100,101,115,99,114,105,112,116,105,118,101,32,115,116,114,105,110,103,32,111,102,32,116,104,101,32,101,114,114,111,114,32,105,110,32,69,110,103,108,105,115,104,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,49,51>>,signature => [{attribute,{146,2},spec,{{format_error,1},[{type,{146,19},bounded_fun,[{type,{146,19},'fun',[{type,{146,19},product,[{var,{146,20},'Reason'}]},{var,{146,31},'Chars'}]},[{type,{147,7},constraint,[{atom,{147,7},is_subtype},[{var,{147,7},'Reason'},{type,{147,17},union,[{user_type,{147,17},posix,[]},{atom,{147,27},badarg},{atom,{147,36},terminated},{atom,{147,49},system_limit},{type,{148,17},tuple,[{ann_type,{148,18},[{var,{148,18},'Line'},{type,{148,26},integer,[]}]},{ann_type,{148,37},[{var,{148,37},'Mod'},{type,{148,44},module,[]}]},{ann_type,{148,54},[{var,{148,54},'Term'},{type,{148,62},term,[]}]}]}]}]]},{type,{149,7},constraint,[{atom,{149,7},is_subtype},[{var,{149,7},'Chars'},{type,{149,16},string,[]}]]}]]}]}}]}},{{function,get_cwd,0},[{file,[102,105,108,101,46,101,114,108]},{location,191}],[<<103,101,116,95,99,119,100,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,68,105,114,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,114,97,114,101,32,99,105,114,99,117,109,115,116,97,110,99,101,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,110,32,102,97,105,108,32,111,110,32,85,110,105,120,46,32,73,116,32,99,97,110,32,111,99,99,117,114,32,105,102,32,114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,100,105,114,101,99,116,111,114,121,46>>]}]},{p,[],[<<65,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,115,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,100,105,114,101,99,116,111,114,121,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,50,49>>,signature => [{attribute,{191,2},spec,{{get_cwd,0},[{type,{191,14},bounded_fun,[{type,{191,14},'fun',[{type,{191,14},product,[]},{type,{191,20},union,[{type,{191,20},tuple,[{atom,{191,21},ok},{var,{191,25},'Dir'}]},{type,{191,32},tuple,[{atom,{191,33},error},{var,{191,40},'Reason'}]}]}]},[{type,{192,7},constraint,[{atom,{192,7},is_subtype},[{var,{192,7},'Dir'},{user_type,{192,14},filename,[]}]]},{type,{193,7},constraint,[{atom,{193,7},is_subtype},[{var,{193,7},'Reason'},{user_type,{193,17},posix,[]}]]}]]}]}}]}},{{function,get_cwd,1},[{file,[102,105,108,101,46,101,114,108]},{location,198}],[<<103,101,116,95,99,119,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,68,105,114,125>>]},<<32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,100,114,105,118,101,46>>]},{p,[],[{code,[],[<<68,114,105,118,101>>]},<<32,105,115,32,116,111,32,98,101,32,111,102,32,116,104,101,32,102,111,114,109,32,34>>,{code,[],[<<76,101,116,116,101,114>>]},{code,[],[<<58>>]},<<34,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,34,99,58,34,46>>]},{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,116,115,117,112,125>>]},<<32,111,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,104,97,118,101,32,110,111,32,99,111,110,99,101,112,116,32,111,102,32,99,117,114,114,101,110,116,32,100,114,105,118,101,32,40,85,110,105,120,44,32,102,111,114,32,101,120,97,109,112,108,101,41,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<84,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,104,97,115,32,110,111,32,99,111,110,99,101,112,116,32,111,102,32,100,114,105,118,101,115,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,114,105,118,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,111,114,109,97,116,32,111,102,32>>,{code,[],[<<68,114,105,118,101>>]},<<32,105,115,32,105,110,118,97,108,105,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,52,51>>,signature => [{attribute,{198,2},spec,{{get_cwd,1},[{type,{198,14},bounded_fun,[{type,{198,14},'fun',[{type,{198,14},product,[{var,{198,15},'Drive'}]},{type,{198,25},union,[{type,{198,25},tuple,[{atom,{198,26},ok},{var,{198,30},'Dir'}]},{type,{198,37},tuple,[{atom,{198,38},error},{var,{198,45},'Reason'}]}]}]},[{type,{199,7},constraint,[{atom,{199,7},is_subtype},[{var,{199,7},'Drive'},{type,{199,16},string,[]}]]},{type,{200,7},constraint,[{atom,{200,7},is_subtype},[{var,{200,7},'Dir'},{user_type,{200,14},filename,[]}]]},{type,{201,7},constraint,[{atom,{201,7},is_subtype},[{var,{201,7},'Reason'},{type,{201,17},union,[{user_type,{201,17},posix,[]},{atom,{201,27},badarg}]}]]}]]}]}}]}},{{function,list_dir,1},[{file,[102,105,108,101,46,101,114,108]},{location,401}],[<<108,105,115,116,95,100,105,114,47,49>>],#{<<101,110>> => [{p,[],[<<76,105,115,116,115,32,97,108,108,32,102,105,108,101,115,32,105,110,32,97,32,100,105,114,101,99,116,111,114,121,44,32>>,{em,[],[<<101,120,99,101,112,116>>]},<<32,102,105,108,101,115,32,119,105,116,104,32,114,97,119,32,102,105,108,101,110,97,109,101,115,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,115,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,110,97,109,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,116,104,101,32,102,105,108,101,115,32,105,110,32,116,104,101,32,100,105,114,101,99,116,111,114,121,46,32,84,104,101,32,110,97,109,101,115,32,97,114,101,32,110,111,116,32,115,111,114,116,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32>>,{code,[],[<<68,105,114>>]},<<32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<123,110,111,95,116,114,97,110,115,108,97,116,105,111,110,44,32,70,105,108,101,110,97,109,101,125>>]}]},{dd,[],[{p,[],[{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,32>>,{code,[],[<<98,105,110,97,114,121,40,41>>]},<<32,119,105,116,104,32,99,104,97,114,97,99,116,101,114,115,32,99,111,100,101,100,32,105,110,32,73,83,79,32,76,97,116,105,110,45,49,32,97,110,100,32,116,104,101,32,86,77,32,119,97,115,32,115,116,97,114,116,101,100,32,119,105,116,104,32,112,97,114,97,109,101,116,101,114,32>>,{code,[],[<<43,102,110,117,101>>]},<<46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,53,55,52>>,signature => [{attribute,{401,2},spec,{{list_dir,1},[{type,{401,15},bounded_fun,[{type,{401,15},'fun',[{type,{401,15},product,[{var,{401,16},'Dir'}]},{type,{401,24},union,[{type,{401,24},tuple,[{atom,{401,25},ok},{var,{401,29},'Filenames'}]},{type,{401,42},tuple,[{atom,{401,43},error},{var,{401,50},'Reason'}]}]}]},[{type,{402,7},constraint,[{atom,{402,7},is_subtype},[{var,{402,7},'Dir'},{user_type,{402,14},name_all,[]}]]},{type,{403,7},constraint,[{atom,{403,7},is_subtype},[{var,{403,7},'Filenames'},{type,{403,20},list,[{user_type,{403,21},filename,[]}]}]]},{type,{404,7},constraint,[{atom,{404,7},is_subtype},[{var,{404,7},'Reason'},{type,{404,17},union,[{user_type,{404,17},posix,[]},{atom,{405,17},badarg},{type,{406,17},tuple,[{atom,{406,18},no_translation},{ann_type,{406,34},[{var,{406,34},'Filename'},{remote_type,{406,46},[{atom,{406,46},unicode},{atom,{406,54},latin1_binary},[]]}]}]}]}]]}]]}]}}]}},{{function,list_dir_all,1},[{file,[102,105,108,101,46,101,114,108]},{location,411}],[<<108,105,115,116,95,100,105,114,95,97,108,108,47,49>>],#{<<101,110>> => [{p,[],[{a,[{id,<<108,105,115,116,95,100,105,114,95,97,108,108>>}],[]},<<76,105,115,116,115,32,97,108,108,32,116,104,101,32,102,105,108,101,115,32,105,110,32,97,32,100,105,114,101,99,116,111,114,121,44,32,105,110,99,108,117,100,105,110,103,32,102,105,108,101,115,32,119,105,116,104,32,114,97,119,32,102,105,108,101,110,97,109,101,115,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,115,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,110,97,109,101,115>>]},<<32,105,115,32,97,32,108,105,115,116,32,111,102,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,116,104,101,32,102,105,108,101,115,32,105,110,32,116,104,101,32,100,105,114,101,99,116,111,114,121,46,32,84,104,101,32,110,97,109,101,115,32,97,114,101,32,110,111,116,32,115,111,114,116,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32>>,{code,[],[<<68,105,114>>]},<<32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,48,53>>,signature => [{attribute,{411,2},spec,{{list_dir_all,1},[{type,{411,19},bounded_fun,[{type,{411,19},'fun',[{type,{411,19},product,[{var,{411,20},'Dir'}]},{type,{411,28},union,[{type,{411,28},tuple,[{atom,{411,29},ok},{var,{411,33},'Filenames'}]},{type,{411,46},tuple,[{atom,{411,47},error},{var,{411,54},'Reason'}]}]}]},[{type,{412,7},constraint,[{atom,{412,7},is_subtype},[{var,{412,7},'Dir'},{user_type,{412,14},name_all,[]}]]},{type,{413,7},constraint,[{atom,{413,7},is_subtype},[{var,{413,7},'Filenames'},{type,{413,20},list,[{user_type,{413,21},filename_all,[]}]}]]},{type,{414,7},constraint,[{atom,{414,7},is_subtype},[{var,{414,7},'Reason'},{type,{414,17},union,[{user_type,{414,17},posix,[]},{atom,{414,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,make_dir,1},[{file,[102,105,108,101,46,101,114,108]},{location,249}],[<<109,97,107,101,95,100,105,114,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,99,114,101,97,116,101,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<68,105,114>>]},<<46,32,77,105,115,115,105,110,103,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,99,114,101,97,116,101,100,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[<<65,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,100,32>>,{code,[],[<<68,105,114>>]},<<32,101,120,105,115,116,115,32,97,108,114,101,97,100,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,99,101,32,105,115,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,51,48>>,signature => [{attribute,{249,2},spec,{{make_dir,1},[{type,{249,15},bounded_fun,[{type,{249,15},'fun',[{type,{249,15},product,[{var,{249,16},'Dir'}]},{type,{249,24},union,[{atom,{249,24},ok},{type,{249,29},tuple,[{atom,{249,30},error},{var,{249,37},'Reason'}]}]}]},[{type,{250,7},constraint,[{atom,{250,7},is_subtype},[{var,{250,7},'Dir'},{user_type,{250,14},name_all,[]}]]},{type,{251,7},constraint,[{atom,{251,7},is_subtype},[{var,{251,7},'Reason'},{type,{251,17},union,[{user_type,{251,17},posix,[]},{atom,{251,27},badarg}]}]]}]]}]}}]}},{{function,make_link,2},[{file,[102,105,108,101,46,101,114,108]},{location,427}],[<<109,97,107,101,95,108,105,110,107,47,50>>],#{<<101,110>> => [{p,[],[<<77,97,107,101,115,32,97,32,104,97,114,100,32,108,105,110,107,32,102,114,111,109,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,116,111,32>>,{code,[],[<<78,101,119>>]},<<32,111,110,32,112,108,97,116,102,111,114,109,115,32,115,117,112,112,111,114,116,105,110,103,32,108,105,110,107,115,32,40,85,110,105,120,32,97,110,100,32,87,105,110,100,111,119,115,41,46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,116,104,101,32,108,105,110,107,32,119,97,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,99,114,101,97,116,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,110,111,116,32,115,117,112,112,111,114,116,105,110,103,32,108,105,110,107,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,101,110,111,116,115,117,112,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,111,114,32>>,{code,[],[<<78,101,119>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[{code,[],[<<78,101,119>>]},<<32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<72,97,114,100,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,54,52>>,signature => [{attribute,{427,2},spec,{{make_link,2},[{type,{427,16},bounded_fun,[{type,{427,16},'fun',[{type,{427,16},product,[{var,{427,17},'Existing'},{var,{427,27},'New'}]},{type,{427,35},union,[{atom,{427,35},ok},{type,{427,40},tuple,[{atom,{427,41},error},{var,{427,48},'Reason'}]}]}]},[{type,{428,7},constraint,[{atom,{428,7},is_subtype},[{var,{428,7},'Existing'},{user_type,{428,19},name_all,[]}]]},{type,{429,7},constraint,[{atom,{429,7},is_subtype},[{var,{429,7},'New'},{user_type,{429,14},name_all,[]}]]},{type,{430,7},constraint,[{atom,{430,7},is_subtype},[{var,{430,7},'Reason'},{type,{430,17},union,[{user_type,{430,17},posix,[]},{atom,{430,27},badarg}]}]]}]]}]}}]}},{{function,make_symlink,2},[{file,[102,105,108,101,46,101,114,108]},{location,435}],[<<109,97,107,101,95,115,121,109,108,105,110,107,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32>>,{code,[],[<<78,101,119>>]},<<32,116,111,32,116,104,101,32,102,105,108,101,32,111,114,32,100,105,114,101,99,116,111,114,121,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,111,110,32,112,108,97,116,102,111,114,109,115,32,115,117,112,112,111,114,116,105,110,103,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,32,40,109,111,115,116,32,85,110,105,120,32,115,121,115,116,101,109,115,32,97,110,100,32,87,105,110,100,111,119,115,44,32,98,101,103,105,110,110,105,110,103,32,119,105,116,104,32,86,105,115,116,97,41,46,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,100,111,101,115,32,110,111,116,32,110,101,101,100,32,116,111,32,101,120,105,115,116,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,116,104,101,32,108,105,110,107,32,105,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,99,114,101,97,116,101,100,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,110,111,116,32,115,117,112,112,111,114,116,105,110,103,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,116,115,117,112,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<69,120,105,115,116,105,110,103>>]},<<32,111,114,32>>,{code,[],[<<78,101,119>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[{code,[],[<<78,101,119>>]},<<32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]},{dt,[],[{code,[],[<<101,112,101,114,109>>]}]},{dd,[],[{p,[],[<<85,115,101,114,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,112,114,105,118,105,108,101,103,101,115,32,116,111,32,99,114,101,97,116,101,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,32,40>>,{code,[],[<<83,101,67,114,101,97,116,101,83,121,109,98,111,108,105,99,76,105,110,107,80,114,105,118,105,108,101,103,101>>]},<<32,111,110,32,87,105,110,100,111,119,115,41,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,54,57,51>>,signature => [{attribute,{435,2},spec,{{make_symlink,2},[{type,{435,19},bounded_fun,[{type,{435,19},'fun',[{type,{435,19},product,[{var,{435,20},'Existing'},{var,{435,30},'New'}]},{type,{435,38},union,[{atom,{435,38},ok},{type,{435,43},tuple,[{atom,{435,44},error},{var,{435,51},'Reason'}]}]}]},[{type,{436,7},constraint,[{atom,{436,7},is_subtype},[{var,{436,7},'Existing'},{user_type,{436,19},name_all,[]}]]},{type,{437,7},constraint,[{atom,{437,7},is_subtype},[{var,{437,7},'New'},{user_type,{437,14},name_all,[]}]]},{type,{438,7},constraint,[{atom,{438,7},is_subtype},[{var,{438,7},'Reason'},{type,{438,17},union,[{user_type,{438,17},posix,[]},{atom,{438,27},badarg}]}]]}]]}]}}]}},{{function,native_name_encoding,0},[{file,[102,105,108,101,46,101,114,108]},{location,135}],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>],#{<<101,110>> => [{p,[],[{a,[{id,<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103>>}],[]},<<82,101,116,117,114,110,115,32,116,104,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,109,111,100,101,46,32,73,102,32,105,116,32,105,115,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,116,104,101,32,115,121,115,116,101,109,32,116,114,97,110,115,108,97,116,101,115,32,110,111,32,102,105,108,101,110,97,109,101,115,46,32,73,102,32,105,116,32,105,115,32>>,{code,[],[<<117,116,102,56>>]},<<44,32,102,105,108,101,110,97,109,101,115,32,97,114,101,32,99,111,110,118,101,114,116,101,100,32,98,97,99,107,32,97,110,100,32,102,111,114,116,104,32,116,111,32,116,104,101,32,110,97,116,105,118,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,32,40,117,115,117,97,108,108,121,32,85,84,70,45,56,44,32,98,117,116,32,85,84,70,45,49,54,32,111,110,32,87,105,110,100,111,119,115,41,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,55,50,57>>,signature => [{attribute,{135,2},spec,{{native_name_encoding,0},[{type,{135,27},'fun',[{type,{135,27},product,[]},{type,{135,33},union,[{atom,{135,33},latin1},{atom,{135,42},utf8}]}]}]}}],since => <<79,84,80,32,82,49,52,66,48,49>>}},{{function,open,2},[{file,[102,105,108,101,46,101,114,108]},{location,510}],[<<111,112,101,110,47,50>>],#{<<101,110>> => [{p,[],[<<79,112,101,110,115,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101>>]},<<32,105,110,32,116,104,101,32,109,111,100,101,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32>>,{code,[],[<<77,111,100,101,115>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,99,111,110,116,97,105,110,32,111,110,101,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<114,101,97,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,44,32,119,104,105,99,104,32,109,117,115,116,32,101,120,105,115,116,44,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,114,101,97,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<119,114,105,116,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46,32,73,116,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,73,102,32,116,104,101,32,102,105,108,101,32,101,120,105,115,116,115,32,97,110,100,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,105,115,32,110,111,116,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{code,[],[<<114,101,97,100>>]},<<44,32,116,104,101,32,102,105,108,101,32,105,115,32,116,114,117,110,99,97,116,101,100,46>>]}]},{dt,[],[{code,[],[<<97,112,112,101,110,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46,32,73,116,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,69,118,101,114,121,32,119,114,105,116,101,32,111,112,101,114,97,116,105,111,110,32,116,111,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<97,112,112,101,110,100>>]},<<32,116,97,107,101,115,32,112,108,97,99,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<101,120,99,108,117,115,105,118,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46,32,73,116,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,73,102,32,116,104,101,32,102,105,108,101,32,101,120,105,115,116,115,44,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,101,120,105,115,116,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,100,111,101,115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,32,101,120,99,108,117,115,105,118,101,110,101,115,115,32,111,110,32,102,105,108,101,32,115,121,115,116,101,109,115,32,110,111,116,32,115,117,112,112,111,114,116,105,110,103,32>>,{code,[],[<<79,95,69,88,67,76>>]},<<32,112,114,111,112,101,114,108,121,44,32,115,117,99,104,32,97,115,32,78,70,83,46,32,68,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,116,104,105,115,32,111,112,116,105,111,110,32,117,110,108,101,115,115,32,121,111,117,32,107,110,111,119,32,116,104,97,116,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,115,117,112,112,111,114,116,115,32,105,116,32,40,105,110,32,103,101,110,101,114,97,108,44,32,108,111,99,97,108,32,102,105,108,101,32,115,121,115,116,101,109,115,32,97,114,101,32,115,97,102,101,41,46>>]}]}]},{dt,[],[{code,[],[<<114,97,119>>]}]},{dd,[],[{p,[],[{a,[{id,<<114,97,119>>}],[]},<<65,108,108,111,119,115,32,102,97,115,116,101,114,32,97,99,99,101,115,115,32,116,111,32,97,32,102,105,108,101,44,32,97,115,32,110,111,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,105,115,32,110,101,101,100,101,100,32,116,111,32,104,97,110,100,108,101,32,116,104,101,32,102,105,108,101,46,32,72,111,119,101,118,101,114,44,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32,116,104,105,115,32,119,97,121,32,104,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,108,105,109,105,116,97,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32>>,{code,[],[<<105,111>>]},<<32,109,111,100,117,108,101,32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,44,32,97,115,32,116,104,101,121,32,99,97,110,32,111,110,108,121,32,116,97,108,107,32,116,111,32,97,110,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,46,32,73,110,115,116,101,97,100,44,32,117,115,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<46>>]}]},{li,[],[{p,[],[<<69,115,112,101,99,105,97,108,108,121,32,105,102,32>>,{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]},<<32,105,115,32,116,111,32,98,101,32,117,115,101,100,32,111,110,32,97,32>>,{code,[],[<<114,97,119>>]},<<32,102,105,108,101,44,32,105,116,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,116,111,32,99,111,109,98,105,110,101,32,116,104,105,115,32,111,112,116,105,111,110,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,97,115,32,108,105,110,101,45,111,114,105,101,110,116,101,100,32,73,47,79,32,105,115,32,105,110,101,102,102,105,99,105,101,110,116,32,119,105,116,104,111,117,116,32,98,117,102,102,101,114,105,110,103,46>>]}]},{li,[],[{p,[],[<<79,110,108,121,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,116,104,97,116,32,111,112,101,110,101,100,32,116,104,101,32,102,105,108,101,32,99,97,110,32,117,115,101,32,105,116,46>>]}]},{li,[],[{p,[],[<<65,32,114,101,109,111,116,101,32,69,114,108,97,110,103,32,102,105,108,101,32,115,101,114,118,101,114,32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,46,32,84,104,101,32,99,111,109,112,117,116,101,114,32,111,110,32,119,104,105,99,104,32,116,104,101,32,69,114,108,97,110,103,32,110,111,100,101,32,105,115,32,114,117,110,110,105,110,103,32,109,117,115,116,32,104,97,118,101,32,97,99,99,101,115,115,32,116,111,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,40,100,105,114,101,99,116,108,121,32,111,114,32,116,104,114,111,117,103,104,32,78,70,83,41,46>>]}]}]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,111,112,101,114,97,116,105,111,110,115,32,111,110,32,116,104,101,32,102,105,108,101,32,114,101,116,117,114,110,32,98,105,110,97,114,105,101,115,32,114,97,116,104,101,114,32,116,104,97,110,32,108,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<123,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,83,105,122,101,44,32,68,101,108,97,121,125>>]}]},{dd,[],[{p,[],[<<68,97,116,97,32,105,110,32,115,117,98,115,101,113,117,101,110,116,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,32,105,115,32,98,117,102,102,101,114,101,100,32,117,110,116,105,108,32,97,116,32,108,101,97,115,116,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,32,97,114,101,32,98,117,102,102,101,114,101,100,44,32,111,114,32,117,110,116,105,108,32,116,104,101,32,111,108,100,101,115,116,32,98,117,102,102,101,114,101,100,32,100,97,116,97,32,105,115,32>>,{code,[],[<<68,101,108,97,121>>]},<<32,109,105,108,108,105,115,101,99,111,110,100,115,32,111,108,100,46,32,84,104,101,110,32,97,108,108,32,98,117,102,102,101,114,101,100,32,100,97,116,97,32,105,115,32,119,114,105,116,116,101,110,32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,46,32,84,104,101,32,98,117,102,102,101,114,101,100,32,100,97,116,97,32,105,115,32,97,108,115,111,32,102,108,117,115,104,101,100,32,98,101,102,111,114,101,32,115,111,109,101,32,111,116,104,101,114,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,32,116,104,97,110,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,105,115,32,101,120,101,99,117,116,101,100,46>>]},{p,[],[<<84,104,101,32,112,117,114,112,111,115,101,32,111,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,116,111,32,105,110,99,114,101,97,115,101,32,112,101,114,102,111,114,109,97,110,99,101,32,98,121,32,114,101,100,117,99,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,115,46,32,84,104,117,115,44,32,116,104,101,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,32,109,117,115,116,32,98,101,32,102,111,114,32,115,105,122,101,115,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<44,32,97,110,100,32,110,111,116,32,105,110,116,101,114,115,112,101,114,115,101,100,32,98,121,32,116,111,111,32,109,97,110,121,32,111,116,104,101,114,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,115,46>>]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,117,115,101,100,44,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,32,99,97,110,32,112,114,101,109,97,116,117,114,101,108,121,32,98,101,32,114,101,112,111,114,116,101,100,32,97,115,32,115,117,99,99,101,115,115,102,117,108,44,32,97,110,100,32,105,102,32,97,32,119,114,105,116,101,32,101,114,114,111,114,32,111,99,99,117,114,115,44,32,116,104,101,32,101,114,114,111,114,32,105,115,32,114,101,112,111,114,116,101,100,32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,110,101,120,116,32,102,105,108,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,110,111,116,32,101,120,101,99,117,116,101,100,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32>>,{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]},<<32,105,115,32,117,115,101,100,44,32,97,102,116,101,114,32,97,32,110,117,109,98,101,114,32,111,102,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,99,97,108,108,115,44,32>>,{code,[],[<<99,108,111,115,101,47,49>>]},<<32,99,97,110,32,114,101,116,117,114,110,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,115,112,99,125>>]},<<44,32,97,115,32,116,104,101,114,101,32,105,115,32,110,111,116,32,101,110,111,117,103,104,32,115,112,97,99,101,32,111,110,32,116,104,101,32,100,105,115,99,32,102,111,114,32,112,114,101,118,105,111,117,115,108,121,32,119,114,105,116,116,101,110,32,100,97,116,97,46,32>>,{code,[],[<<99,108,111,115,101,47,49>>]},<<32,109,117,115,116,32,112,114,111,98,97,98,108,121,32,98,101,32,99,97,108,108,101,100,32,97,103,97,105,110,44,32,97,115,32,116,104,101,32,102,105,108,101,32,105,115,32,115,116,105,108,108,32,111,112,101,110,46>>]}]},{dt,[],[{code,[],[<<100,101,108,97,121,101,100,95,119,114,105,116,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<123,100,101,108,97,121,101,100,95,119,114,105,116,101,44,32,83,105,122,101,44,32,68,101,108,97,121,125>>]},<<32,119,105,116,104,32,114,101,97,115,111,110,97,98,108,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<83,105,122,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,108,97,121>>]},<<32,40,114,111,117,103,104,108,121,32,115,111,109,101,32,54,52,32,75,66,44,32,50,32,115,101,99,111,110,100,115,41,46>>]}]},{dt,[],[{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]}]},{dd,[],[{p,[],[<<65,99,116,105,118,97,116,101,115,32,114,101,97,100,32,100,97,116,97,32,98,117,102,102,101,114,105,110,103,46,32,73,102,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,99,97,108,108,115,32,97,114,101,32,102,111,114,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,108,101,115,115,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,44,32,114,101,97,100,32,111,112,101,114,97,116,105,111,110,115,32,116,111,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,97,114,101,32,115,116,105,108,108,32,112,101,114,102,111,114,109,101,100,32,102,111,114,32,98,108,111,99,107,115,32,111,102,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,46,32,84,104,101,32,101,120,116,114,97,32,100,97,116,97,32,105,115,32,98,117,102,102,101,114,101,100,32,97,110,100,32,114,101,116,117,114,110,101,100,32,105,110,32,115,117,98,115,101,113,117,101,110,116,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,99,97,108,108,115,44,32,103,105,118,105,110,103,32,97,32,112,101,114,102,111,114,109,97,110,99,101,32,103,97,105,110,32,97,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,99,97,108,108,115,32,105,115,32,114,101,100,117,99,101,100,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<114,101,97,100,95,97,104,101,97,100>>]},<<32,98,117,102,102,101,114,32,105,115,32,97,108,115,111,32,104,105,103,104,108,121,32,117,115,101,100,32,98,121,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]},<<32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,44,32,116,104,101,114,101,102,111,114,101,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,40,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101,32,114,101,97,115,111,110,115,41,32,119,104,101,110,32,97,99,99,101,115,115,105,110,103,32,114,97,119,32,102,105,108,101,115,32,117,115,105,110,103,32,116,104,97,116,32,102,117,110,99,116,105,111,110,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,99,97,108,108,115,32,97,114,101,32,102,111,114,32,115,105,122,101,115,32,110,111,116,32,115,105,103,110,105,102,105,99,97,110,116,108,121,32,108,101,115,115,32,116,104,97,110,44,32,111,114,32,101,118,101,110,32,103,114,101,97,116,101,114,32,116,104,97,110,32>>,{code,[],[<<83,105,122,101>>]},<<32,98,121,116,101,115,44,32,110,111,32,112,101,114,102,111,114,109,97,110,99,101,32,103,97,105,110,32,99,97,110,32,98,101,32,101,120,112,101,99,116,101,100,46>>]}]},{dt,[],[{code,[],[<<114,101,97,100,95,97,104,101,97,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,119,105,116,104,32,97,32,114,101,97,115,111,110,97,98,108,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,102,111,114,32>>,{code,[],[<<83,105,122,101>>]},<<32,40,114,111,117,103,104,108,121,32,115,111,109,101,32,54,52,32,75,66,41,46>>]}]},{dt,[],[{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,103,122,105,112,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,115,46,32,79,112,116,105,111,110,32>>,{code,[],[<<99,111,109,112,114,101,115,115,101,100>>]},<<32,109,117,115,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32>>,{code,[],[<<114,101,97,100>>]},<<32,111,114,32>>,{code,[],[<<119,114,105,116,101>>]},<<44,32,98,117,116,32,110,111,116,32,98,111,116,104,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,102,105,108,101,32,115,105,122,101,32,111,98,116,97,105,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>]}]},<<32,100,111,101,115,32,112,114,111,98,97,98,108,121,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,97,100,32,102,114,111,109,32,97,32,99,111,109,112,114,101,115,115,101,100,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,110,99,111,100,105,110,103,44,32,69,110,99,111,100,105,110,103,125>>]}]},{dd,[],[{p,[],[<<77,97,107,101,115,32,116,104,101,32,102,105,108,101,32,112,101,114,102,111,114,109,32,97,117,116,111,109,97,116,105,99,32,116,114,97,110,115,108,97,116,105,111,110,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,111,32,97,110,100,32,102,114,111,109,32,97,32,115,112,101,99,105,102,105,99,32,40,85,110,105,99,111,100,101,41,32,101,110,99,111,100,105,110,103,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,100,97,116,97,32,115,117,112,112,108,105,101,100,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<32,111,114,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,115,116,105,108,108,32,105,115,32,98,121,116,101,45,111,114,105,101,110,116,101,100,59,32,116,104,105,115,32,111,112,116,105,111,110,32,100,101,110,111,116,101,115,32,111,110,108,121,32,104,111,119,32,100,97,116,97,32,105,115,32,115,116,111,114,101,100,32,105,110,32,116,104,101,32,100,105,115,107,32,102,105,108,101,46>>]},{p,[],[<<68,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,101,110,99,111,100,105,110,103,44,32,100,105,102,102,101,114,101,110,116,32,109,101,116,104,111,100,115,32,111,102,32,114,101,97,100,105,110,103,32,97,110,100,32,119,114,105,116,105,110,103,32,100,97,116,97,32,105,115,32,112,114,101,102,101,114,114,101,100,46,32,84,104,101,32,100,101,102,97,117,108,116,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,105,109,112,108,105,101,115,32,117,115,105,110,103,32,116,104,105,115,32,109,111,100,117,108,101,32,40>>,{code,[],[<<102,105,108,101>>]},<<41,32,102,111,114,32,114,101,97,100,105,110,103,32,97,110,100,32,119,114,105,116,105,110,103,32,100,97,116,97,32,97,115,32,116,104,101,32,105,110,116,101,114,102,97,99,101,115,32,112,114,111,118,105,100,101,100,32,104,101,114,101,32,119,111,114,107,32,119,105,116,104,32,98,121,116,101,45,111,114,105,101,110,116,101,100,32,100,97,116,97,46,32,85,115,105,110,103,32,111,116,104,101,114,32,40,85,110,105,99,111,100,101,41,32,101,110,99,111,100,105,110,103,115,32,109,97,107,101,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,102,117,110,99,116,105,111,110,115,32>>,{code,[],[<<103,101,116,95,99,104,97,114,115>>]},<<44,32>>,{code,[],[<<103,101,116,95,108,105,110,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<112,117,116,95,99,104,97,114,115>>]},<<32,109,111,114,101,32,115,117,105,116,97,98,108,101,44,32,97,115,32,116,104,101,121,32,99,97,110,32,119,111,114,107,32,119,105,116,104,32,116,104,101,32,102,117,108,108,32,85,110,105,99,111,100,101,32,114,97,110,103,101,46>>]},{p,[],[<<73,102,32,100,97,116,97,32,105,115,32,115,101,110,116,32,116,111,32,97,110,32>>,{code,[],[<<105,111,95,100,101,118,105,99,101,40,41>>]},<<32,105,110,32,97,32,102,111,114,109,97,116,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,99,111,110,118,101,114,116,101,100,32,116,111,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,101,110,99,111,100,105,110,103,44,32,111,114,32,105,102,32,100,97,116,97,32,105,115,32,114,101,97,100,32,98,121,32,97,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,114,101,116,117,114,110,115,32,100,97,116,97,32,105,110,32,97,32,102,111,114,109,97,116,32,116,104,97,116,32,99,97,110,110,111,116,32,99,111,112,101,32,119,105,116,104,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,114,97,110,103,101,32,111,102,32,116,104,101,32,100,97,116,97,44,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,32,97,110,100,32,116,104,101,32,102,105,108,101,32,105,115,32,99,108,111,115,101,100,46>>]},{p,[],[<<65,108,108,111,119,101,100,32,118,97,108,117,101,115,32,102,111,114,32>>,{code,[],[<<69,110,99,111,100,105,110,103>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<108,97,116,105,110,49>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,101,110,99,111,100,105,110,103,46,32,66,121,116,101,115,32,115,117,112,112,108,105,101,100,32,116,111,32,116,104,101,32,102,105,108,101,44,32,116,104,97,116,32,105,115,44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,47,50>>]}]},<<32,97,114,101,32,119,114,105,116,116,101,110,32,34,97,115,32,105,115,34,32,111,110,32,116,104,101,32,102,105,108,101,46,32,76,105,107,101,119,105,115,101,44,32,98,121,116,101,115,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,44,32,116,104,97,116,32,105,115,44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,97,114,101,32,114,101,116,117,114,110,101,100,32,34,97,115,32,105,115,34,46,32,73,102,32,109,111,100,117,108,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,105,115,32,117,115,101,100,32,102,111,114,32,119,114,105,116,105,110,103,44,32,116,104,101,32,102,105,108,101,32,99,97,110,32,111,110,108,121,32,99,111,112,101,32,119,105,116,104,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,117,112,32,116,111,32,99,111,100,101,32,112,111,105,110,116,32,50,53,53,32,40,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,114,97,110,103,101,41,46>>]}]},{dt,[],[{code,[],[<<117,110,105,99,111,100,101,32,111,114,32,117,116,102,56>>]}]},{dd,[],[{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,97,114,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,97,110,100,32,102,114,111,109,32,85,84,70,45,56,32,101,110,99,111,100,105,110,103,32,98,101,102,111,114,101,32,116,104,101,121,32,97,114,101,32,119,114,105,116,116,101,110,32,116,111,32,111,114,32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46,32,65,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32,116,104,105,115,32,119,97,121,32,99,97,110,32,98,101,32,114,101,97,100,97,98,108,101,32,117,115,105,110,103,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<44,32,97,115,32,108,111,110,103,32,97,115,32,110,111,32,100,97,116,97,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,102,105,108,101,32,108,105,101,115,32,98,101,121,111,110,100,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,114,97,110,103,101,32,40,48,46,46,50,53,53,41,44,32,98,117,116,32,102,97,105,108,117,114,101,32,111,99,99,117,114,115,32,105,102,32,116,104,101,32,100,97,116,97,32,99,111,110,116,97,105,110,115,32,85,110,105,99,111,100,101,32,99,111,100,101,32,112,111,105,110,116,115,32,98,101,121,111,110,100,32,116,104,97,116,32,114,97,110,103,101,46,32,84,104,101,32,102,105,108,101,32,105,115,32,98,101,115,116,32,114,101,97,100,32,119,105,116,104,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32,85,110,105,99,111,100,101,32,97,119,97,114,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<46>>]},{p,[],[<<66,121,116,101,115,32,119,114,105,116,116,101,110,32,116,111,32,116,104,101,32,102,105,108,101,32,98,121,32,97,110,121,32,109,101,97,110,115,32,97,114,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,85,84,70,45,56,32,101,110,99,111,100,105,110,103,32,98,101,102,111,114,101,32,98,101,105,110,103,32,115,116,111,114,101,100,32,111,110,32,116,104,101,32,100,105,115,107,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<117,116,102,49,54,32,111,114,32,123,117,116,102,49,54,44,98,105,103,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,98,105,103,32,101,110,100,105,97,110,32,85,84,70,45,49,54,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]},{dt,[],[{code,[],[<<123,117,116,102,49,54,44,108,105,116,116,108,101,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,108,105,116,116,108,101,32,101,110,100,105,97,110,32,85,84,70,45,49,54,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]},{dt,[],[{code,[],[<<117,116,102,51,50,32,111,114,32,123,117,116,102,51,50,44,98,105,103,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,98,105,103,32,101,110,100,105,97,110,32,85,84,70,45,51,50,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]},{dt,[],[{code,[],[<<123,117,116,102,51,50,44,108,105,116,116,108,101,125>>]}]},{dd,[],[{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,98,117,116,32,116,114,97,110,115,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,116,111,32,97,110,100,32,102,114,111,109,32,108,105,116,116,108,101,32,101,110,100,105,97,110,32,85,84,70,45,51,50,32,105,110,115,116,101,97,100,32,111,102,32,85,84,70,45,56,46>>]}]}]},{p,[],[<<84,104,101,32,69,110,99,111,100,105,110,103,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,102,111,114,32,97,32,102,105,108,101,32,34,111,110,32,116,104,101,32,102,108,121,34,32,98,121,32,117,115,105,110,103,32,102,117,110,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111,35,115,101,116,111,112,116,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,111,58,115,101,116,111,112,116,115,47,50>>]}]},<<46,32,83,111,32,97,32,102,105,108,101,32,99,97,110,32,98,101,32,97,110,97,108,121,122,101,100,32,105,110,32,108,97,116,105,110,49,32,101,110,99,111,100,105,110,103,32,102,111,114,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,66,79,77,44,32,112,111,115,105,116,105,111,110,101,100,32,98,101,121,111,110,100,32,116,104,101,32,66,79,77,32,97,110,100,32,116,104,101,110,32,98,101,32,115,101,116,32,102,111,114,32,116,104,101,32,114,105,103,104,116,32,101,110,99,111,100,105,110,103,32,98,101,102,111,114,101,32,102,117,114,116,104,101,114,32,114,101,97,100,105,110,103,46,32,70,111,114,32,102,117,110,99,116,105,111,110,115,32,105,100,101,110,116,105,102,121,105,110,103,32,66,79,77,115,44,32,115,101,101,32,109,111,100,117,108,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<117,110,105,99,111,100,101,40,51,41>>]}]},<<46>>]},{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,102,105,108,101,115,46>>]}]},{dt,[],[{code,[],[<<114,97,109>>]}]},{dd,[],[{p,[],[{code,[],[<<70,105,108,101>>]},<<32,109,117,115,116,32,98,101,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<46,32,82,101,116,117,114,110,115,32,97,110,32>>,{code,[],[<<102,100,40,41>>]},<<44,32,119,104,105,99,104,32,108,101,116,115,32,109,111,100,117,108,101,32>>,{code,[],[<<102,105,108,101>>]},<<32,111,112,101,114,97,116,101,32,111,110,32,116,104,101,32,100,97,116,97,32,105,110,45,109,101,109,111,114,121,32,97,115,32,105,102,32,105,116,32,105,115,32,97,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<115,121,110,99>>]}]},{dd,[],[{p,[],[<<79,110,32,112,108,97,116,102,111,114,109,115,32,115,117,112,112,111,114,116,105,110,103,32,105,116,44,32,101,110,97,98,108,101,115,32,116,104,101,32,80,79,83,73,88,32>>,{code,[],[<<79,95,83,89,78,67>>]},<<32,115,121,110,99,104,114,111,110,111,117,115,32,73,47,79,32,102,108,97,103,32,111,114,32,105,116,115,32,112,108,97,116,102,111,114,109,45,100,101,112,101,110,100,101,110,116,32,101,113,117,105,118,97,108,101,110,116,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<70,73,76,69,95,70,76,65,71,95,87,82,73,84,69,95,84,72,82,79,85,71,72>>]},<<32,111,110,32,87,105,110,100,111,119,115,41,32,115,111,32,116,104,97,116,32,119,114,105,116,101,115,32,116,111,32,116,104,101,32,102,105,108,101,32,98,108,111,99,107,32,117,110,116,105,108,32,116,104,101,32,100,97,116,97,32,105,115,32,112,104,121,115,105,99,97,108,108,121,32,119,114,105,116,116,101,110,32,116,111,32,100,105,115,107,46,32,72,111,119,101,118,101,114,44,32,98,101,32,97,119,97,114,101,32,116,104,97,116,32,116,104,101,32,101,120,97,99,116,32,115,101,109,97,110,116,105,99,115,32,111,102,32,116,104,105,115,32,102,108,97,103,32,100,105,102,102,101,114,32,102,114,111,109,32,112,108,97,116,102,111,114,109,32,116,111,32,112,108,97,116,102,111,114,109,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,110,111,110,101,32,111,102,32,76,105,110,117,120,32,111,114,32,87,105,110,100,111,119,115,32,103,117,97,114,97,110,116,101,101,115,32,116,104,97,116,32,97,108,108,32,102,105,108,101,32,109,101,116,97,100,97,116,97,32,97,114,101,32,97,108,115,111,32,119,114,105,116,116,101,110,32,98,101,102,111,114,101,32,116,104,101,32,99,97,108,108,32,114,101,116,117,114,110,115,46,32,70,111,114,32,112,114,101,99,105,115,101,32,115,101,109,97,110,116,105,99,115,44,32,99,104,101,99,107,32,116,104,101,32,100,101,116,97,105,108,115,32,111,102,32,121,111,117,114,32,112,108,97,116,102,111,114,109,32,100,111,99,117,109,101,110,116,97,116,105,111,110,46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,119,105,116,104,32,110,111,32,115,117,112,112,111,114,116,32,102,111,114,32,80,79,83,73,88,32>>,{code,[],[<<79,95,83,89,78,67>>]},<<32,111,114,32,101,113,117,105,118,97,108,101,110,116,44,32,117,115,101,32,111,102,32,116,104,101,32>>,{code,[],[<<115,121,110,99>>]},<<32,102,108,97,103,32,99,97,117,115,101,115,32>>,{code,[],[<<111,112,101,110>>]},<<32,116,111,32,114,101,116,117,114,110,32>>,{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,116,115,117,112,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<100,105,114,101,99,116,111,114,121>>]}]},{dd,[],[{p,[],[<<65,108,108,111,119,115,32>>,{code,[],[<<111,112,101,110>>]},<<32,116,111,32,119,111,114,107,32,111,110,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]}]},{p,[],[<<82,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,73,111,68,101,118,105,99,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,105,110,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,109,111,100,101,46,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,111,112,101,110,101,100,46>>]}]}]},{p,[],[{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,105,115,32,114,101,97,108,108,121,32,116,104,101,32,112,105,100,32,111,102,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,104,97,110,100,108,101,115,32,116,104,101,32,102,105,108,101,46,32,84,104,105,115,32,112,114,111,99,101,115,115,32,109,111,110,105,116,111,114,115,32,116,104,101,32,112,114,111,99,101,115,115,32,116,104,97,116,32,111,114,105,103,105,110,97,108,108,121,32,111,112,101,110,101,100,32,116,104,101,32,102,105,108,101,32,40,116,104,101,32,111,119,110,101,114,32,112,114,111,99,101,115,115,41,46,32,73,102,32,116,104,101,32,111,119,110,101,114,32,112,114,111,99,101,115,115,32,116,101,114,109,105,110,97,116,101,115,44,32,116,104,101,32,102,105,108,101,32,105,115,32,99,108,111,115,101,100,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,105,116,115,101,108,102,32,116,101,114,109,105,110,97,116,101,115,32,116,111,111,46,32,65,110,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,114,101,116,117,114,110,101,100,32,102,114,111,109,32,116,104,105,115,32,99,97,108,108,32,99,97,110,32,98,101,32,117,115,101,100,32,97,115,32,97,110,32,97,114,103,117,109,101,110,116,32,116,111,32,116,104,101,32,73,47,79,32,102,117,110,99,116,105,111,110,115,32,40,115,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<41,46>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<87,104,105,108,101,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,111,112,101,110,32,97,110,121,32,102,105,108,101,44,32,119,101,32,114,101,99,111,109,109,101,110,100,32,97,103,97,105,110,115,116,32,117,115,105,110,103,32,105,116,32,102,111,114,32,78,70,83,45,109,111,117,110,116,101,100,32,102,105,108,101,115,44,32,70,73,70,79,115,44,32,100,101,118,105,99,101,115,44,32,111,114,32,115,105,109,105,108,97,114,32,115,105,110,99,101,32,116,104,101,121,32,99,97,110,32,99,97,117,115,101,32,73,79,32,116,104,114,101,97,100,115,32,116,111,32,104,97,110,103,32,102,111,114,101,118,101,114,46>>]},{p,[],[<<73,102,32,121,111,117,114,32,97,112,112,108,105,99,97,116,105,111,110,32,110,101,101,100,115,32,116,111,32,105,110,116,101,114,97,99,116,32,119,105,116,104,32,116,104,101,115,101,32,107,105,110,100,115,32,111,102,32,102,105,108,101,115,32,119,101,32,114,101,99,111,109,109,101,110,100,32,98,114,101,97,107,105,110,103,32,111,117,116,32,116,104,111,115,101,32,112,97,114,116,115,32,116,111,32,97,32,112,111,114,116,32,112,114,111,103,114,97,109,32,105,110,115,116,101,97,100,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,112,114,101,118,105,111,117,115,32,118,101,114,115,105,111,110,115,32,111,102,32>>,{code,[],[<<102,105,108,101>>]},<<44,32,109,111,100,101,115,32,119,101,114,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,111,110,101,32,111,102,32,116,104,101,32,97,116,111,109,115,32>>,{code,[],[<<114,101,97,100>>]},<<44,32>>,{code,[],[<<119,114,105,116,101>>]},<<44,32,111,114,32>>,{code,[],[<<114,101,97,100,95,119,114,105,116,101>>]},<<32,105,110,115,116,101,97,100,32,111,102,32,97,32,108,105,115,116,46,32,84,104,105,115,32,105,115,32,115,116,105,108,108,32,97,108,108,111,119,101,100,32,102,111,114,32,114,101,97,115,111,110,115,32,111,102,32,98,97,99,107,119,97,114,100,115,32,99,111,109,112,97,116,105,98,105,108,105,116,121,44,32,98,117,116,32,105,115,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,32,102,111,114,32,110,101,119,32,99,111,100,101,46,32,65,108,115,111,32,110,111,116,101,32,116,104,97,116,32>>,{code,[],[<<114,101,97,100,95,119,114,105,116,101>>]},<<32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,105,110,32,97,32,109,111,100,101,32,108,105,115,116,46>>]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,114,101,97,100,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,115,101,97,114,99,104,105,110,103,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,97,109,101,100,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,44,32,111,114,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,116,115,101,108,102,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,32,105,102,32>>,{code,[],[<<100,105,114,101,99,116,111,114,121>>]},<<32,109,111,100,101,32,119,97,115,32,115,112,101,99,105,102,105,101,100,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<84,104,101,114,101,32,105,115,32,110,111,32,115,112,97,99,101,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,32,40,105,102,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,97,99,99,101,115,115,32,119,97,115,32,115,112,101,99,105,102,105,101,100,41,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,55,52,49>>,signature => [{attribute,{510,2},spec,{{open,2},[{type,{510,11},bounded_fun,[{type,{510,11},'fun',[{type,{510,11},product,[{var,{510,12},'File'},{var,{510,18},'Modes'}]},{type,{510,28},union,[{type,{510,28},tuple,[{atom,{510,29},ok},{var,{510,33},'IoDevice'}]},{type,{510,45},tuple,[{atom,{510,46},error},{var,{510,53},'Reason'}]}]}]},[{type,{511,7},constraint,[{atom,{511,7},is_subtype},[{var,{511,7},'File'},{type,{511,15},union,[{var,{511,15},'Filename'},{type,{511,26},iodata,[]}]}]]},{type,{512,7},constraint,[{atom,{512,7},is_subtype},[{var,{512,7},'Filename'},{user_type,{512,19},name_all,[]}]]},{type,{513,7},constraint,[{atom,{513,7},is_subtype},[{var,{513,7},'Modes'},{type,{513,16},list,[{type,{513,17},union,[{user_type,{513,17},mode,[]},{atom,{513,26},ram},{atom,{513,32},directory}]}]}]]},{type,{514,7},constraint,[{atom,{514,7},is_subtype},[{var,{514,7},'IoDevice'},{user_type,{514,19},io_device,[]}]]},{type,{515,7},constraint,[{atom,{515,7},is_subtype},[{var,{515,7},'Reason'},{type,{515,17},union,[{user_type,{515,17},posix,[]},{atom,{515,27},badarg},{atom,{515,36},system_limit}]}]]}]]}]}}]}},{{function,path_consult,2},[{file,[102,105,108,101,46,101,114,108]},{location,1041}],[<<112,97,116,104,95,99,111,110,115,117,108,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,114,101,97,100,115,32,69,114,108,97,110,103,32,116,101,114,109,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,84,101,114,109,115,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,115,117,99,99,101,115,115,102,117,108,108,121,32,114,101,97,100,46,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,116,101,114,109,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,48,51,54>>,signature => [{attribute,{1041,2},spec,{{path_consult,2},[{type,{1041,19},bounded_fun,[{type,{1041,19},'fun',[{type,{1041,19},product,[{var,{1041,20},'Path'},{var,{1041,26},'Filename'}]},{type,{1041,39},union,[{type,{1041,39},tuple,[{atom,{1041,40},ok},{var,{1041,44},'Terms'},{var,{1041,51},'FullName'}]},{type,{1041,63},tuple,[{atom,{1041,64},error},{var,{1041,71},'Reason'}]}]}]},[{type,{1042,7},constraint,[{atom,{1042,7},is_subtype},[{var,{1042,7},'Path'},{type,{1042,15},list,[{var,{1042,16},'Dir'}]}]]},{type,{1043,7},constraint,[{atom,{1043,7},is_subtype},[{var,{1043,7},'Dir'},{user_type,{1043,14},name_all,[]}]]},{type,{1044,7},constraint,[{atom,{1044,7},is_subtype},[{var,{1044,7},'Filename'},{user_type,{1044,19},name_all,[]}]]},{type,{1045,7},constraint,[{atom,{1045,7},is_subtype},[{var,{1045,7},'Terms'},{type,{1045,16},list,[{type,{1045,17},term,[]}]}]]},{type,{1046,7},constraint,[{atom,{1046,7},is_subtype},[{var,{1046,7},'FullName'},{user_type,{1046,19},filename_all,[]}]]},{type,{1047,7},constraint,[{atom,{1047,7},is_subtype},[{var,{1047,7},'Reason'},{type,{1047,17},union,[{user_type,{1047,17},posix,[]},{atom,{1047,27},badarg},{atom,{1047,36},terminated},{atom,{1047,49},system_limit},{type,{1048,17},tuple,[{ann_type,{1048,18},[{var,{1048,18},'Line'},{type,{1048,26},integer,[]}]},{ann_type,{1048,37},[{var,{1048,37},'Mod'},{type,{1048,44},module,[]}]},{ann_type,{1048,54},[{var,{1048,54},'Term'},{type,{1048,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,path_eval,2},[{file,[102,105,108,101,46,101,114,108]},{location,1089}],[<<112,97,116,104,95,101,118,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,114,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46,32,84,104,101,32,114,101,115,117,108,116,32,111,102,32,101,118,97,108,117,97,116,105,111,110,32,105,115,32,110,111,116,32,114,101,116,117,114,110,101,100,59,32,97,110,121,32,101,120,112,114,101,115,115,105,111,110,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,102,105,108,101,32,109,117,115,116,32,98,101,32,116,104,101,114,101,32,102,111,114,32,105,116,115,32,115,105,100,101,32,101,102,102,101,99,116,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,48,55,56>>,signature => [{attribute,{1089,2},spec,{{path_eval,2},[{type,{1089,16},bounded_fun,[{type,{1089,16},'fun',[{type,{1089,16},product,[{var,{1089,17},'Path'},{var,{1089,23},'Filename'}]},{type,{1089,36},union,[{type,{1089,36},tuple,[{atom,{1089,37},ok},{var,{1089,41},'FullName'}]},{type,{1089,53},tuple,[{atom,{1089,54},error},{var,{1089,61},'Reason'}]}]}]},[{type,{1090,7},constraint,[{atom,{1090,7},is_subtype},[{var,{1090,7},'Path'},{type,{1090,15},list,[{ann_type,{1090,16},[{var,{1090,16},'Dir'},{user_type,{1090,23},name_all,[]}]}]}]]},{type,{1091,7},constraint,[{atom,{1091,7},is_subtype},[{var,{1091,7},'Filename'},{user_type,{1091,19},name_all,[]}]]},{type,{1092,7},constraint,[{atom,{1092,7},is_subtype},[{var,{1092,7},'FullName'},{user_type,{1092,19},filename_all,[]}]]},{type,{1093,7},constraint,[{atom,{1093,7},is_subtype},[{var,{1093,7},'Reason'},{type,{1093,17},union,[{user_type,{1093,17},posix,[]},{atom,{1093,27},badarg},{atom,{1093,36},terminated},{atom,{1093,49},system_limit},{type,{1094,17},tuple,[{ann_type,{1094,18},[{var,{1094,18},'Line'},{type,{1094,26},integer,[]}]},{ann_type,{1094,37},[{var,{1094,37},'Mod'},{type,{1094,44},module,[]}]},{ann_type,{1094,54},[{var,{1094,54},'Term'},{type,{1094,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,path_open,3},[{file,[102,105,108,101,46,101,114,108]},{location,1194}],[<<112,97,116,104,95,111,112,101,110,47,51>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,111,112,101,110,115,32,116,104,101,32,102,105,108,101,32,105,110,32,116,104,101,32,109,111,100,101,32,100,101,116,101,114,109,105,110,101,100,32,98,121,32>>,{code,[],[<<77,111,100,101,115>>]},<<46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,73,111,68,101,118,105,99,101,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,105,110,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,109,111,100,101,46,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,102,105,108,101,32,97,110,100,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,111,112,101,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,49,50,52>>,signature => [{attribute,{1194,2},spec,{{path_open,3},[{type,{1194,16},bounded_fun,[{type,{1194,16},'fun',[{type,{1194,16},product,[{var,{1194,17},'Path'},{var,{1194,23},'Filename'},{var,{1194,33},'Modes'}]},{type,{1195,14},union,[{type,{1195,14},tuple,[{atom,{1195,15},ok},{var,{1195,19},'IoDevice'},{var,{1195,29},'FullName'}]},{type,{1195,41},tuple,[{atom,{1195,42},error},{var,{1195,49},'Reason'}]}]}]},[{type,{1196,7},constraint,[{atom,{1196,7},is_subtype},[{var,{1196,7},'Path'},{type,{1196,15},list,[{ann_type,{1196,16},[{var,{1196,16},'Dir'},{user_type,{1196,23},name_all,[]}]}]}]]},{type,{1197,7},constraint,[{atom,{1197,7},is_subtype},[{var,{1197,7},'Filename'},{user_type,{1197,19},name_all,[]}]]},{type,{1198,7},constraint,[{atom,{1198,7},is_subtype},[{var,{1198,7},'Modes'},{type,{1198,16},list,[{type,{1198,17},union,[{user_type,{1198,17},mode,[]},{atom,{1198,26},directory}]}]}]]},{type,{1199,7},constraint,[{atom,{1199,7},is_subtype},[{var,{1199,7},'IoDevice'},{user_type,{1199,19},io_device,[]}]]},{type,{1200,7},constraint,[{atom,{1200,7},is_subtype},[{var,{1200,7},'FullName'},{user_type,{1200,19},filename_all,[]}]]},{type,{1201,7},constraint,[{atom,{1201,7},is_subtype},[{var,{1201,7},'Reason'},{type,{1201,17},union,[{user_type,{1201,17},posix,[]},{atom,{1201,27},badarg},{atom,{1201,36},system_limit}]}]]}]]}]}}]}},{{function,path_script,2},[{file,[102,105,108,101,46,101,114,108]},{location,1149}],[<<112,97,116,104,95,115,99,114,105,112,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,97,114,99,104,101,115,32,116,104,101,32,112,97,116,104,32>>,{code,[],[<<80,97,116,104>>]},<<32,40,97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114,121,32,110,97,109,101,115,41,32,117,110,116,105,108,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,102,111,117,110,100,46,32,73,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,102,105,108,101,110,97,109,101,44,32>>,{code,[],[<<80,97,116,104>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,110,32,114,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,86,97,108,117,101,44,32,70,117,108,108,78,97,109,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46,32>>,{code,[],[<<70,117,108,108,78,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,32,97,110,100,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,108,97,115,116,32,101,120,112,114,101,115,115,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,101,110,111,101,110,116,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,102,111,117,110,100,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32>>,{code,[],[<<80,97,116,104>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,49,53,51>>,signature => [{attribute,{1149,2},spec,{{path_script,2},[{type,{1149,18},bounded_fun,[{type,{1149,18},'fun',[{type,{1149,18},product,[{var,{1149,19},'Path'},{var,{1149,25},'Filename'}]},{type,{1150,14},union,[{type,{1150,14},tuple,[{atom,{1150,15},ok},{var,{1150,19},'Value'},{var,{1150,26},'FullName'}]},{type,{1150,38},tuple,[{atom,{1150,39},error},{var,{1150,46},'Reason'}]}]}]},[{type,{1151,7},constraint,[{atom,{1151,7},is_subtype},[{var,{1151,7},'Path'},{type,{1151,15},list,[{ann_type,{1151,16},[{var,{1151,16},'Dir'},{user_type,{1151,23},name_all,[]}]}]}]]},{type,{1152,7},constraint,[{atom,{1152,7},is_subtype},[{var,{1152,7},'Filename'},{user_type,{1152,19},name_all,[]}]]},{type,{1153,7},constraint,[{atom,{1153,7},is_subtype},[{var,{1153,7},'Value'},{type,{1153,16},term,[]}]]},{type,{1154,7},constraint,[{atom,{1154,7},is_subtype},[{var,{1154,7},'FullName'},{user_type,{1154,19},filename_all,[]}]]},{type,{1155,7},constraint,[{atom,{1155,7},is_subtype},[{var,{1155,7},'Reason'},{type,{1155,17},union,[{user_type,{1155,17},posix,[]},{atom,{1155,27},badarg},{atom,{1155,36},terminated},{atom,{1155,49},system_limit},{type,{1156,17},tuple,[{ann_type,{1156,18},[{var,{1156,18},'Line'},{type,{1156,26},integer,[]}]},{ann_type,{1156,37},[{var,{1156,37},'Mod'},{type,{1156,44},module,[]}]},{ann_type,{1156,54},[{var,{1156,54},'Term'},{type,{1156,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,path_script,3},[{file,[102,105,108,101,46,101,114,108]},{location,1161}],[<<112,97,116,104,95,115,99,114,105,112,116,47,51>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<112,97,116,104,95,115,99,114,105,112,116,47,50>>]},<<32,98,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,32>>,{code,[],[<<66,105,110,100,105,110,103,115>>]},<<32,97,114,101,32,117,115,101,100,32,105,110,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,46,32,83,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,114,108,95,101,118,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,101,118,97,108,40,51,41>>]}]},<<32,97,98,111,117,116,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,49,57,55>>,signature => [{attribute,{1161,2},spec,{{path_script,3},[{type,{1161,18},bounded_fun,[{type,{1161,18},'fun',[{type,{1161,18},product,[{var,{1161,19},'Path'},{var,{1161,25},'Filename'},{var,{1161,35},'Bindings'}]},{type,{1162,11},union,[{type,{1162,11},tuple,[{atom,{1162,12},ok},{var,{1162,16},'Value'},{var,{1162,23},'FullName'}]},{type,{1162,35},tuple,[{atom,{1162,36},error},{var,{1162,43},'Reason'}]}]}]},[{type,{1163,7},constraint,[{atom,{1163,7},is_subtype},[{var,{1163,7},'Path'},{type,{1163,15},list,[{ann_type,{1163,16},[{var,{1163,16},'Dir'},{user_type,{1163,23},name_all,[]}]}]}]]},{type,{1164,7},constraint,[{atom,{1164,7},is_subtype},[{var,{1164,7},'Filename'},{user_type,{1164,19},name_all,[]}]]},{type,{1165,7},constraint,[{atom,{1165,7},is_subtype},[{var,{1165,7},'Bindings'},{remote_type,{1165,19},[{atom,{1165,19},erl_eval},{atom,{1165,28},binding_struct},[]]}]]},{type,{1166,7},constraint,[{atom,{1166,7},is_subtype},[{var,{1166,7},'Value'},{type,{1166,16},term,[]}]]},{type,{1167,7},constraint,[{atom,{1167,7},is_subtype},[{var,{1167,7},'FullName'},{user_type,{1167,19},filename_all,[]}]]},{type,{1168,7},constraint,[{atom,{1168,7},is_subtype},[{var,{1168,7},'Reason'},{type,{1168,17},union,[{user_type,{1168,17},posix,[]},{atom,{1168,27},badarg},{atom,{1168,36},terminated},{atom,{1168,49},system_limit},{type,{1169,17},tuple,[{ann_type,{1169,18},[{var,{1169,18},'Line'},{type,{1169,26},integer,[]}]},{ann_type,{1169,37},[{var,{1169,37},'Mod'},{type,{1169,44},module,[]}]},{ann_type,{1169,54},[{var,{1169,54},'Term'},{type,{1169,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,pid2name,1},[{file,[102,105,108,101,46,101,114,108]},{location,170}],[<<112,105,100,50,110,97,109,101,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<80,105,100>>]},<<32,105,115,32,97,110,32,73,47,79,32,100,101,118,105,99,101,44,32,116,104,97,116,32,105,115,44,32,97,32,112,105,100,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{code,[],[<<111,112,101,110,47,50>>]},<<44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,102,105,108,101,110,97,109,101,44,32,111,114,32,114,97,116,104,101,114,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,125>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,116,104,105,115,32,110,111,100,101,32,105,115,32,110,111,116,32,97,32,115,108,97,118,101,44,32,116,104,101,32,102,105,108,101,32,119,97,115,32,111,112,101,110,101,100,32,98,121,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,111,102,32,116,104,105,115,32,110,111,100,101,32,40,116,104,105,115,32,105,109,112,108,105,101,115,32,116,104,97,116,32>>,{code,[],[<<80,105,100>>]},<<32,109,117,115,116,32,98,101,32,97,32,108,111,99,97,108,32,112,105,100,41,32,97,110,100,32,116,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,99,108,111,115,101,100,46,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,105,115,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,110,32,102,108,97,116,32,115,116,114,105,110,103,32,102,111,114,109,97,116,46>>]}]},{dt,[],[{code,[],[<<117,110,100,101,102,105,110,101,100>>]}]},{dd,[],[{p,[],[<<73,110,32,97,108,108,32,111,116,104,101,114,32,99,97,115,101,115,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,105,110,116,101,110,100,101,100,32,102,111,114,32,100,101,98,117,103,103,105,110,103,32,111,110,108,121,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,48,55>>,signature => [{attribute,{170,2},spec,{{pid2name,1},[{type,{170,15},bounded_fun,[{type,{170,15},'fun',[{type,{170,15},product,[{var,{170,16},'Pid'}]},{type,{170,24},union,[{type,{170,24},tuple,[{atom,{170,25},ok},{var,{170,29},'Filename'}]},{atom,{170,41},undefined}]}]},[{type,{171,7},constraint,[{atom,{171,7},is_subtype},[{var,{171,7},'Filename'},{user_type,{171,19},filename_all,[]}]]},{type,{172,7},constraint,[{atom,{172,7},is_subtype},[{var,{172,7},'Pid'},{type,{172,14},pid,[]}]]}]]}]}}]}},{{function,position,2},[{file,[102,105,108,101,46,101,114,108]},{location,753}],[<<112,111,115,105,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,116,111,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,78,101,119,80,111,115,105,116,105,111,110,125>>]},<<32,40,97,115,32,97,98,115,111,108,117,116,101,32,111,102,102,115,101,116,41,32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<79,102,102,115,101,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<123,98,111,102,44,32,79,102,102,115,101,116,125>>]},<<46>>]}]},{dt,[],[{code,[],[<<123,98,111,102,44,32,79,102,102,115,101,116,125>>]}]},{dd,[],[{p,[],[<<65,98,115,111,108,117,116,101,32,111,102,102,115,101,116,46>>]}]},{dt,[],[{code,[],[<<123,99,117,114,44,32,79,102,102,115,101,116,125>>]}]},{dd,[],[{p,[],[<<79,102,102,115,101,116,32,102,114,111,109,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,101,111,102,44,32,79,102,102,115,101,116,125>>]}]},{dd,[],[{p,[],[<<79,102,102,115,101,116,32,102,114,111,109,32,116,104,101,32,101,110,100,32,111,102,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<98,111,102,32,124,32,99,117,114,32,124,32,101,111,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32,97,98,111,118,101,32,119,105,116,104,32>>,{code,[],[<<79,102,102,115,101,116>>]},<<32,48,46>>]}]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,111,102,102,115,101,116,115,32,97,114,101,32,99,111,117,110,116,101,100,32,105,110,32,98,121,116,101,115,44,32,110,111,116,32,105,110,32,99,104,97,114,97,99,116,101,114,115,46,32,73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,117,115,105,110,103,32,115,111,109,101,32,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,111,110,101,32,98,121,116,101,32,100,111,101,115,32,110,111,116,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,111,110,101,32,99,104,97,114,97,99,116,101,114,46,32,80,111,115,105,116,105,111,110,105,110,103,32,105,110,32,115,117,99,104,32,97,32,102,105,108,101,32,99,97,110,32,111,110,108,121,32,98,101,32,100,111,110,101,32,116,111,32,107,110,111,119,110,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,105,101,115,46,32,84,104,97,116,32,105,115,44,32,116,111,32,97,32,112,111,115,105,116,105,111,110,32,101,97,114,108,105,101,114,32,114,101,116,114,105,101,118,101,100,32,98,121,32,103,101,116,116,105,110,103,32,97,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,44,32,116,111,32,116,104,101,32,98,101,103,105,110,110,105,110,103,47,101,110,100,32,111,102,32,116,104,101,32,102,105,108,101,32,111,114,32,116,111,32,115,111,109,101,32,111,116,104,101,114,32,112,111,115,105,116,105,111,110,32>>,{em,[],[<<107,110,111,119,110>>]},<<32,116,111,32,98,101,32,111,110,32,97,32,99,111,114,114,101,99,116,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,32,98,121,32,115,111,109,101,32,111,116,104,101,114,32,109,101,97,110,115,32,40,116,121,112,105,99,97,108,108,121,32,98,101,121,111,110,100,32,97,32,98,121,116,101,32,111,114,100,101,114,32,109,97,114,107,32,105,110,32,116,104,101,32,102,105,108,101,44,32,119,104,105,99,104,32,104,97,115,32,97,32,107,110,111,119,110,32,98,121,116,101,45,115,105,122,101,41,46>>]},{p,[],[<<65,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,32,105,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[<<69,105,116,104,101,114,32>>,{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,105,108,108,101,103,97,108,44,32,111,114,32,105,116,32,105,115,32,101,118,97,108,117,97,116,101,100,32,116,111,32,97,32,110,101,103,97,116,105,118,101,32,111,102,102,115,101,116,32,105,110,32,116,104,101,32,102,105,108,101,46,32,78,111,116,105,99,101,32,116,104,97,116,32,105,102,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,112,111,115,105,116,105,111,110,32,105,115,32,97,32,110,101,103,97,116,105,118,101,32,118,97,108,117,101,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,110,32,101,114,114,111,114,44,32,97,110,100,32,97,102,116,101,114,32,116,104,101,32,99,97,108,108,32,116,104,101,32,102,105,108,101,32,112,111,115,105,116,105,111,110,32,105,115,32,117,110,100,101,102,105,110,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,51,50>>,signature => [{attribute,{753,2},spec,{{position,2},[{type,{753,15},bounded_fun,[{type,{753,15},'fun',[{type,{753,15},product,[{var,{753,16},'IoDevice'},{var,{753,26},'Location'}]},{type,{753,39},union,[{type,{753,39},tuple,[{atom,{753,40},ok},{var,{753,44},'NewPosition'}]},{type,{753,59},tuple,[{atom,{753,60},error},{var,{753,67},'Reason'}]}]}]},[{type,{754,7},constraint,[{atom,{754,7},is_subtype},[{var,{754,7},'IoDevice'},{user_type,{754,19},io_device,[]}]]},{type,{755,7},constraint,[{atom,{755,7},is_subtype},[{var,{755,7},'Location'},{user_type,{755,19},location,[]}]]},{type,{756,7},constraint,[{atom,{756,7},is_subtype},[{var,{756,7},'NewPosition'},{type,{756,22},integer,[]}]]},{type,{757,7},constraint,[{atom,{757,7},is_subtype},[{var,{757,7},'Reason'},{type,{757,17},union,[{user_type,{757,17},posix,[]},{atom,{757,27},badarg},{atom,{757,36},terminated}]}]]}]]}]}}]}},{{function,pread,2},[{file,[102,105,108,101,46,101,114,108]},{location,632}],[<<112,114,101,97,100,47,50>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32>>,{code,[],[<<112,114,101,97,100,47,51>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,91,68,97,116,97,44,32,46,46,46,93,125>>]},<<32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<44,32,119,104,101,114,101,32,101,97,99,104,32>>,{code,[],[<<68,97,116,97>>]},<<44,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32>>,{code,[],[<<112,114,101,97,100>>]},<<44,32,105,115,32,101,105,116,104,101,114,32,97,32,108,105,115,116,32,111,114,32,97,32,98,105,110,97,114,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109,111,100,101,32,111,102,32,116,104,101,32,102,105,108,101,44,32,111,114,32>>,{code,[],[<<101,111,102>>]},<<32,105,102,32,116,104,101,32,114,101,113,117,101,115,116,101,100,32,112,111,115,105,116,105,111,110,32,105,115,32,98,101,121,111,110,100,32,101,110,100,32,111,102,32,102,105,108,101,46>>]},{p,[],[<<65,115,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,121,116,101,45,111,102,102,115,101,116,44,32,116,97,107,101,32,115,112,101,99,105,97,108,32,99,97,117,116,105,111,110,32,119,104,101,110,32,119,111,114,107,105,110,103,32,119,105,116,104,32,102,105,108,101,115,32,119,104,101,114,101,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,97,115,32,110,111,116,32,101,118,101,114,121,32,98,121,116,101,32,112,111,115,105,116,105,111,110,32,105,115,32,97,32,118,97,108,105,100,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,32,111,110,32,115,117,99,104,32,97,32,102,105,108,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,50,56,52>>,signature => [{attribute,{632,2},spec,{{pread,2},[{type,{632,12},bounded_fun,[{type,{632,12},'fun',[{type,{632,12},product,[{var,{632,13},'IoDevice'},{var,{632,23},'LocNums'}]},{type,{632,35},union,[{type,{632,35},tuple,[{atom,{632,36},ok},{var,{632,40},'DataL'}]},{atom,{632,49},eof},{type,{632,55},tuple,[{atom,{632,56},error},{var,{632,63},'Reason'}]}]}]},[{type,{633,7},constraint,[{atom,{633,7},is_subtype},[{var,{633,7},'IoDevice'},{user_type,{633,19},io_device,[]}]]},{type,{634,7},constraint,[{atom,{634,7},is_subtype},[{var,{634,7},'LocNums'},{type,{634,18},list,[{type,{634,19},tuple,[{ann_type,{634,20},[{var,{634,20},'Location'},{user_type,{634,32},location,[]}]},{ann_type,{634,44},[{var,{634,44},'Number'},{type,{634,54},non_neg_integer,[]}]}]}]}]]},{type,{635,7},constraint,[{atom,{635,7},is_subtype},[{var,{635,7},'DataL'},{type,{635,16},list,[{var,{635,17},'Data'}]}]]},{type,{636,7},constraint,[{atom,{636,7},is_subtype},[{var,{636,7},'Data'},{type,{636,15},union,[{type,{636,15},string,[]},{type,{636,26},binary,[]},{atom,{636,37},eof}]}]]},{type,{637,7},constraint,[{atom,{637,7},is_subtype},[{var,{637,7},'Reason'},{type,{637,17},union,[{user_type,{637,17},posix,[]},{atom,{637,27},badarg},{atom,{637,36},terminated}]}]]}]]}]}}]}},{{function,pread,3},[{file,[102,105,108,101,46,101,114,108]},{location,660}],[<<112,114,101,97,100,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32>>,{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]},<<32,97,110,100,32>>,{code,[],[<<114,101,97,100,47,50>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46>>]},{p,[],[{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,111,110,108,121,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,97,110,32,105,110,116,101,103,101,114,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,97,110,100,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,115,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,111,102,32,116,104,101,32,102,105,108,101,32,97,102,116,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,97,110,100,32,117,110,99,104,97,110,103,101,100,32,102,111,114,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,46>>]},{p,[],[<<65,115,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,98,121,116,101,45,111,102,102,115,101,116,44,32,116,97,107,101,32,115,112,101,99,105,97,108,32,99,97,117,116,105,111,110,32,119,104,101,110,32,119,111,114,107,105,110,103,32,119,105,116,104,32,102,105,108,101,115,32,119,104,101,114,101,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,97,115,32,110,111,116,32,101,118,101,114,121,32,98,121,116,101,32,112,111,115,105,116,105,111,110,32,105,115,32,97,32,118,97,108,105,100,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,32,111,110,32,115,117,99,104,32,97,32,102,105,108,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,48,50>>,signature => [{attribute,{660,2},spec,{{pread,3},[{type,{660,12},bounded_fun,[{type,{660,12},'fun',[{type,{660,12},product,[{var,{660,13},'IoDevice'},{var,{660,23},'Location'},{var,{660,33},'Number'}]},{type,{661,14},union,[{type,{661,14},tuple,[{atom,{661,15},ok},{var,{661,19},'Data'}]},{atom,{661,27},eof},{type,{661,33},tuple,[{atom,{661,34},error},{var,{661,41},'Reason'}]}]}]},[{type,{662,7},constraint,[{atom,{662,7},is_subtype},[{var,{662,7},'IoDevice'},{user_type,{662,19},io_device,[]}]]},{type,{663,7},constraint,[{atom,{663,7},is_subtype},[{var,{663,7},'Location'},{user_type,{663,19},location,[]}]]},{type,{664,7},constraint,[{atom,{664,7},is_subtype},[{var,{664,7},'Number'},{type,{664,17},non_neg_integer,[]}]]},{type,{665,7},constraint,[{atom,{665,7},is_subtype},[{var,{665,7},'Data'},{type,{665,15},union,[{type,{665,15},string,[]},{type,{665,26},binary,[]}]}]]},{type,{666,7},constraint,[{atom,{666,7},is_subtype},[{var,{666,7},'Reason'},{type,{666,17},union,[{user_type,{666,17},posix,[]},{atom,{666,27},badarg},{atom,{666,36},terminated}]}]]}]]}]}}]}},{{function,pwrite,2},[{file,[102,105,108,101,46,101,114,108]},{location,693}],[<<112,119,114,105,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<80,101,114,102,111,114,109,115,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32>>,{code,[],[<<112,119,114,105,116,101,47,51>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,123,78,44,32,82,101,97,115,111,110,125,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<78>>]},<<32,105,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,115,117,99,99,101,115,115,102,117,108,32,119,114,105,116,101,115,32,100,111,110,101,32,98,101,102,111,114,101,32,116,104,101,32,102,97,105,108,117,114,101,46>>]},{p,[],[<<87,104,101,110,32,112,111,115,105,116,105,111,110,105,110,103,32,105,110,32,97,32,102,105,108,101,32,119,105,116,104,32,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,99,97,117,116,105,111,110,32,109,117,115,116,32,98,101,32,116,97,107,101,110,32,116,111,32,115,101,116,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,110,32,97,32,99,111,114,114,101,99,116,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,46,32,70,111,114,32,100,101,116,97,105,108,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,112,111,115,105,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,49,57>>,signature => [{attribute,{693,2},spec,{{pwrite,2},[{type,{693,13},bounded_fun,[{type,{693,13},'fun',[{type,{693,13},product,[{var,{693,14},'IoDevice'},{var,{693,24},'LocBytes'}]},{type,{693,37},union,[{atom,{693,37},ok},{type,{693,42},tuple,[{atom,{693,43},error},{type,{693,50},tuple,[{var,{693,51},'N'},{var,{693,54},'Reason'}]}]}]}]},[{type,{694,7},constraint,[{atom,{694,7},is_subtype},[{var,{694,7},'IoDevice'},{user_type,{694,19},io_device,[]}]]},{type,{695,7},constraint,[{atom,{695,7},is_subtype},[{var,{695,7},'LocBytes'},{type,{695,19},list,[{type,{695,20},tuple,[{ann_type,{695,21},[{var,{695,21},'Location'},{user_type,{695,33},location,[]}]},{ann_type,{695,45},[{var,{695,45},'Bytes'},{type,{695,54},iodata,[]}]}]}]}]]},{type,{696,7},constraint,[{atom,{696,7},is_subtype},[{var,{696,7},'N'},{type,{696,12},non_neg_integer,[]}]]},{type,{697,7},constraint,[{atom,{697,7},is_subtype},[{var,{697,7},'Reason'},{type,{697,17},union,[{user_type,{697,17},posix,[]},{atom,{697,27},badarg},{atom,{697,36},terminated}]}]]}]]}]}}]}},{{function,pwrite,3},[{file,[102,105,108,101,46,101,114,108]},{location,718}],[<<112,119,114,105,116,101,47,51>>],#{<<101,110>> => [{p,[],[<<67,111,109,98,105,110,101,115,32>>,{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]},<<32,97,110,100,32>>,{code,[],[<<119,114,105,116,101,47,50>>]},<<32,105,110,32,111,110,101,32,111,112,101,114,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,97,108,108,105,110,103,32,116,104,101,109,32,111,110,101,32,97,116,32,97,32,116,105,109,101,46>>]},{p,[],[{code,[],[<<76,111,99,97,116,105,111,110>>]},<<32,105,115,32,111,110,108,121,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,97,110,32,105,110,116,101,103,101,114,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,97,110,100,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,115,46>>]},{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,111,102,32,116,104,101,32,102,105,108,101,32,97,102,116,101,114,32,116,104,101,32,111,112,101,114,97,116,105,111,110,32,105,115,32,117,110,100,101,102,105,110,101,100,32,102,111,114,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,97,110,100,32,117,110,99,104,97,110,103,101,100,32,102,111,114,32>>,{code,[],[<<114,97,109>>]},<<32,109,111,100,101,46>>]},{p,[],[<<87,104,101,110,32,112,111,115,105,116,105,111,110,105,110,103,32,105,110,32,97,32,102,105,108,101,32,119,105,116,104,32,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,99,97,117,116,105,111,110,32,109,117,115,116,32,98,101,32,116,97,107,101,110,32,116,111,32,115,101,116,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,110,32,97,32,99,111,114,114,101,99,116,32,99,104,97,114,97,99,116,101,114,32,98,111,117,110,100,97,114,121,46,32,70,111,114,32,100,101,116,97,105,108,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,112,111,115,105,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,111,115,105,116,105,111,110,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,51,52>>,signature => [{attribute,{718,2},spec,{{pwrite,3},[{type,{718,13},bounded_fun,[{type,{718,13},'fun',[{type,{718,13},product,[{var,{718,14},'IoDevice'},{var,{718,24},'Location'},{var,{718,34},'Bytes'}]},{type,{718,44},union,[{atom,{718,44},ok},{type,{718,49},tuple,[{atom,{718,50},error},{var,{718,57},'Reason'}]}]}]},[{type,{719,7},constraint,[{atom,{719,7},is_subtype},[{var,{719,7},'IoDevice'},{user_type,{719,19},io_device,[]}]]},{type,{720,7},constraint,[{atom,{720,7},is_subtype},[{var,{720,7},'Location'},{user_type,{720,19},location,[]}]]},{type,{721,7},constraint,[{atom,{721,7},is_subtype},[{var,{721,7},'Bytes'},{type,{721,16},iodata,[]}]]},{type,{722,7},constraint,[{atom,{722,7},is_subtype},[{var,{722,7},'Reason'},{type,{722,17},union,[{user_type,{722,17},posix,[]},{atom,{722,27},badarg},{atom,{722,36},terminated}]}]]}]]}]}}]}},{{function,read,2},[{file,[102,105,108,101,46,101,114,108]},{location,590}],[<<114,101,97,100,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,98,121,116,101,115,47,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,84,104,101,32,102,117,110,99,116,105,111,110,115,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<44,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,112,114,101,97,100,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,101,97,100,47,51>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]}]},<<32,97,114,101,32,116,104,101,32,111,110,108,121,32,119,97,121,115,32,116,111,32,114,101,97,100,32,102,114,111,109,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,40,97,108,116,104,111,117,103,104,32,116,104,101,121,32,119,111,114,107,32,102,111,114,32,110,111,114,109,97,108,108,121,32,111,112,101,110,101,100,32,102,105,108,101,115,44,32,116,111,111,41,46>>]},{p,[],[<<70,111,114,32,102,105,108,101,115,32,119,104,101,114,101,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,111,110,101,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,121,116,101,32,111,110,32,116,104,101,32,102,105,108,101,46,32,84,104,101,32,112,97,114,97,109,101,116,101,114,32>>,{code,[],[<<78,117,109,98,101,114>>]},<<32,97,108,119,97,121,115,32,100,101,110,111,116,101,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32>>,{em,[],[<<99,104,97,114,97,99,116,101,114,115>>]},<<32,114,101,97,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,44,32,119,104,105,108,101,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,102,105,108,101,32,99,97,110,32,98,101,32,109,111,118,101,100,32,109,117,99,104,32,109,111,114,101,32,116,104,97,110,32,116,104,105,115,32,110,117,109,98,101,114,32,119,104,101,110,32,114,101,97,100,105,110,103,32,97,32,85,110,105,99,111,100,101,32,102,105,108,101,46>>]},{p,[],[<<65,108,115,111,44,32,105,102,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,116,104,101,32>>,{code,[],[<<114,101,97,100,47,51>>]},<<32,99,97,108,108,32,102,97,105,108,115,32,105,102,32,116,104,101,32,100,97,116,97,32,99,111,110,116,97,105,110,115,32,99,104,97,114,97,99,116,101,114,115,32,108,97,114,103,101,114,32,116,104,97,110,32,50,53,53,44,32,119,104,105,99,104,32,105,115,32,119,104,121,32,109,111,100,117,108,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,105,115,32,116,111,32,98,101,32,112,114,101,102,101,114,114,101,100,32,119,104,101,110,32,114,101,97,100,105,110,103,32,115,117,99,104,32,97,32,102,105,108,101,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,68,97,116,97,125>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,119,97,115,32,111,112,101,110,101,100,32,105,110,32,98,105,110,97,114,121,32,109,111,100,101,44,32,116,104,101,32,114,101,97,100,32,98,121,116,101,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,105,110,32,97,32,98,105,110,97,114,121,44,32,111,116,104,101,114,119,105,115,101,32,105,110,32,97,32,108,105,115,116,46,32,84,104,101,32,108,105,115,116,32,111,114,32,98,105,110,97,114,121,32,105,115,32,115,104,111,114,116,101,114,32,116,104,97,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,98,121,116,101,115,32,114,101,113,117,101,115,116,101,100,32,105,102,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,114,101,97,99,104,101,100,46>>]}]},{dt,[],[{code,[],[<<101,111,102>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,101,100,32,105,102,32>>,{code,[],[<<78,117,109,98,101,114,62,48>>]},<<32,97,110,100,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,114,101,97,99,104,101,100,32,98,101,102,111,114,101,32,97,110,121,116,104,105,110,103,32,97,116,32,97,108,108,32,99,111,117,108,100,32,98,101,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,98,97,100,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,102,111,114,32,114,101,97,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,110,111,95,116,114,97,110,115,108,97,116,105,111,110,44,32,117,110,105,99,111,100,101,44,32,108,97,116,105,110,49,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,97,110,100,32,116,104,101,32,100,97,116,97,32,105,110,32,116,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,116,104,101,32,98,121,116,101,45,111,114,105,101,110,116,101,100,32,100,97,116,97,32,116,104,97,116,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,51,53,49>>,signature => [{attribute,{590,2},spec,{{read,2},[{type,{590,11},bounded_fun,[{type,{590,11},'fun',[{type,{590,11},product,[{var,{590,12},'IoDevice'},{var,{590,22},'Number'}]},{type,{590,33},union,[{type,{590,33},tuple,[{atom,{590,34},ok},{var,{590,38},'Data'}]},{atom,{590,46},eof},{type,{590,52},tuple,[{atom,{590,53},error},{var,{590,60},'Reason'}]}]}]},[{type,{591,7},constraint,[{atom,{591,7},is_subtype},[{var,{591,7},'IoDevice'},{type,{591,19},union,[{user_type,{591,19},io_device,[]},{type,{591,33},atom,[]}]}]]},{type,{592,7},constraint,[{atom,{592,7},is_subtype},[{var,{592,7},'Number'},{type,{592,17},non_neg_integer,[]}]]},{type,{593,7},constraint,[{atom,{593,7},is_subtype},[{var,{593,7},'Data'},{type,{593,15},union,[{type,{593,15},string,[]},{type,{593,26},binary,[]}]}]]},{type,{594,7},constraint,[{atom,{594,7},is_subtype},[{var,{594,7},'Reason'},{type,{594,17},union,[{user_type,{594,17},posix,[]},{atom,{595,17},badarg},{atom,{596,17},terminated},{type,{597,17},tuple,[{atom,{597,18},no_translation},{atom,{597,34},unicode},{atom,{597,43},latin1}]}]}]]}]]}]}}]}},{{function,read_file,1},[{file,[102,105,108,101,46,101,114,108]},{location,419}],[<<114,101,97,100,95,102,105,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,105,110,97,114,121,125>>]},<<44,32,119,104,101,114,101,32>>,{code,[],[<<66,105,110,97,114,121>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,100,97,116,97,32,111,98,106,101,99,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,105,102,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,114,101,97,100,105,110,103,32,116,104,101,32,102,105,108,101,44,32,111,114,32,102,111,114,32,115,101,97,114,99,104,105,110,103,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,97,109,101,100,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,110,111,109,101,109>>]}]},{dd,[],[{p,[],[<<84,104,101,114,101,32,105,115,32,110,111,116,32,101,110,111,117,103,104,32,109,101,109,111,114,121,32,102,111,114,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,52,48,53>>,signature => [{attribute,{419,2},spec,{{read_file,1},[{type,{419,16},bounded_fun,[{type,{419,16},'fun',[{type,{419,16},product,[{var,{419,17},'Filename'}]},{type,{419,30},union,[{type,{419,30},tuple,[{atom,{419,31},ok},{var,{419,35},'Binary'}]},{type,{419,45},tuple,[{atom,{419,46},error},{var,{419,53},'Reason'}]}]}]},[{type,{420,7},constraint,[{atom,{420,7},is_subtype},[{var,{420,7},'Filename'},{user_type,{420,19},name_all,[]}]]},{type,{421,7},constraint,[{atom,{421,7},is_subtype},[{var,{421,7},'Binary'},{type,{421,17},binary,[]}]]},{type,{422,7},constraint,[{atom,{422,7},is_subtype},[{var,{422,7},'Reason'},{type,{422,17},union,[{user_type,{422,17},posix,[]},{atom,{422,27},badarg},{atom,{422,36},terminated},{atom,{422,49},system_limit}]}]]}]]}]}}]}},{{function,read_file_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,294}],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,52,52,49>>,equiv => {function,read_file_info,1},signature => [{attribute,{294,2},spec,{{read_file_info,2},[{type,{294,21},bounded_fun,[{type,{294,21},'fun',[{type,{294,21},product,[{var,{294,22},'File'},{var,{294,28},'Opts'}]},{type,{294,37},union,[{type,{294,37},tuple,[{atom,{294,38},ok},{var,{294,42},'FileInfo'}]},{type,{294,54},tuple,[{atom,{294,55},error},{var,{294,62},'Reason'}]}]}]},[{type,{295,7},constraint,[{atom,{295,7},is_subtype},[{var,{295,7},'File'},{type,{295,15},union,[{user_type,{295,15},name_all,[]},{user_type,{295,28},io_device,[]}]}]]},{type,{296,7},constraint,[{atom,{296,7},is_subtype},[{var,{296,7},'Opts'},{type,{296,15},list,[{user_type,{296,16},file_info_option,[]}]}]]},{type,{297,7},constraint,[{atom,{297,7},is_subtype},[{var,{297,7},'FileInfo'},{user_type,{297,19},file_info,[]}]]},{type,{298,7},constraint,[{atom,{298,7},is_subtype},[{var,{298,7},'Reason'},{type,{298,17},union,[{user_type,{298,17},posix,[]},{atom,{298,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,read_file_info,1},[{file,[102,105,108,101,46,101,114,108]},{location,282}],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,114,105,101,118,101,115,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,97,32,102,105,108,101,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,73,110,102,111,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,73,110,102,111>>]},<<32,105,115,32,97,32,114,101,99,111,114,100,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<44,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,75,101,114,110,101,108,32,105,110,99,108,117,100,101,32,102,105,108,101,32>>,{code,[],[<<102,105,108,101,46,104,114,108>>]},<<46,32,73,110,99,108,117,100,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,100,105,114,101,99,116,105,118,101,32,105,110,32,116,104,101,32,109,111,100,117,108,101,32,102,114,111,109,32,119,104,105,99,104,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<32,45,105,110,99,108,117,100,101,95,108,105,98,40,34,107,101,114,110,101,108,47,105,110,99,108,117,100,101,47,102,105,108,101,46,104,114,108,34,41,46>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,116,121,112,101,32,114,101,116,117,114,110,101,100,32,105,110,32>>,{code,[],[<<97,116,105,109,101>>]},<<44,32>>,{code,[],[<<109,116,105,109,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<99,116,105,109,101>>]},<<32,105,115,32,100,101,112,101,110,100,101,110,116,32,111,110,32,116,104,101,32,116,105,109,101,32,116,121,112,101,32,115,101,116,32,105,110,32>>,{code,[],[<<79,112,116,115,32,58,58,32,123,116,105,109,101,44,32,84,121,112,101,125>>]},<<32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,111,99,97,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,108,111,99,97,108,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<117,110,105,118,101,114,115,97,108>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,117,110,105,118,101,114,115,97,108,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<112,111,115,105,120>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,115,101,99,111,110,100,115,32,115,105,110,99,101,32,111,114,32,98,101,102,111,114,101,32,85,110,105,120,32,116,105,109,101,32,101,112,111,99,104,44,32,119,104,105,99,104,32,105,115,32,49,57,55,48,45,48,49,45,48,49,32,48,48,58,48,48,32,85,84,67,46>>]}]}]},{p,[],[<<68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<123,116,105,109,101,44,32,108,111,99,97,108,125>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,97,110,100,32,111,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,108,111,99,97,108,32,102,105,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46,32,78,111,116,101,32,116,104,97,116,32,116,104,105,115,32,119,105,108,108,32,98,114,101,97,107,32,116,104,105,115,32,109,111,100,117,108,101,39,115,32,97,116,111,109,105,99,105,116,121,32,103,117,97,114,97,110,116,101,101,115,32,97,115,32,105,116,32,99,97,110,32,114,97,99,101,32,119,105,116,104,32,97,32,99,111,110,99,117,114,114,101,110,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,49,44,50>>]},<<32>>]},<<46>>]},{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,104,97,115,32,110,111,32,101,102,102,101,99,116,32,119,104,101,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,103,105,118,101,110,32,97,110,32,73,47,79,32,100,101,118,105,99,101,32,105,110,115,116,101,97,100,32,111,102,32,97,32,102,105,108,101,32,110,97,109,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<32,119,105,116,104,32,116,104,101,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,116,111,32,111,98,116,97,105,110,32,97,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,102,105,114,115,116,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<65,115,32,102,105,108,101,32,116,105,109,101,115,32,97,114,101,32,115,116,111,114,101,100,32,105,110,32,80,79,83,73,88,32,116,105,109,101,32,111,110,32,109,111,115,116,32,79,83,44,32,105,116,32,105,115,32,102,97,115,116,101,114,32,116,111,32,113,117,101,114,121,32,102,105,108,101,32,105,110,102,111,114,109,97,116,105,111,110,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<112,111,115,105,120>>]},<<46>>]}]},{p,[],[<<84,104,101,32,114,101,99,111,114,100,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,101,108,100,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<115,105,122,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<83,105,122,101,32,111,102,32,102,105,108,101,32,105,110,32,98,121,116,101,115,46>>]}]},{dt,[],[{code,[],[<<116,121,112,101,32,61,32,100,101,118,105,99,101,32,124,32,100,105,114,101,99,116,111,114,121,32,124,32,111,116,104,101,114,32,124,32,114,101,103,117,108,97,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,102,105,108,101,46,32,67,97,110,32,97,108,115,111,32,99,111,110,116,97,105,110,32>>,{code,[],[<<115,121,109,108,105,110,107>>]},<<32,119,104,101,110,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,108,105,110,107,95,105,110,102,111,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[<<114,101,97,100,95,108,105,110,107,95,105,110,102,111,47,49,44,50>>]},<<46>>]}]},{dt,[],[{code,[],[<<97,99,99,101,115,115,32,61,32,114,101,97,100,32,124,32,119,114,105,116,101,32,124,32,114,101,97,100,95,119,114,105,116,101,32,124,32,110,111,110,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,99,117,114,114,101,110,116,32,115,121,115,116,101,109,32,97,99,99,101,115,115,32,116,111,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<97,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<109,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,119,114,105,116,116,101,110,46>>]}]},{dt,[],[{code,[],[<<99,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,111,102,32,116,104,105,115,32,116,105,109,101,32,102,105,101,108,100,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,46,32,79,110,32,85,110,105,120,44,32,105,116,32,105,115,32,116,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,111,114,32,116,104,101,32>>,{code,[],[<<105,110,111,100,101>>]},<<32,119,97,115,32,99,104,97,110,103,101,100,46,32,73,110,32,87,105,110,100,111,119,115,44,32,105,116,32,105,115,32,116,104,101,32,99,114,101,97,116,101,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<109,111,100,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,112,101,114,109,105,115,115,105,111,110,115,32,97,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,98,105,116,32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<56,35,48,48,52,48,48>>]}]},{dd,[],[{p,[],[<<114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,50,48,48>>]}]},{dd,[],[{p,[],[<<119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,49,48,48>>]}]},{dd,[],[{p,[],[<<101,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,52,48>>]}]},{dd,[],[{p,[],[<<114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,50,48>>]}]},{dd,[],[{p,[],[<<119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,49,48>>]}]},{dd,[],[{p,[],[<<101,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,52>>]}]},{dd,[],[{p,[],[<<114,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,50>>]}]},{dd,[],[{p,[],[<<119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,49>>]}]},{dd,[],[{p,[],[<<101,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<49,54,35,56,48,48>>]}]},{dd,[],[{p,[],[<<115,101,116,32,117,115,101,114,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]},{dt,[],[{code,[],[<<49,54,35,52,48,48>>]}]},{dd,[],[{p,[],[<<115,101,116,32,103,114,111,117,112,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]}]},{p,[],[<<79,110,32,85,110,105,120,32,112,108,97,116,102,111,114,109,115,44,32,111,116,104,101,114,32,98,105,116,115,32,116,104,97,110,32,116,104,111,115,101,32,108,105,115,116,101,100,32,97,98,111,118,101,32,109,97,121,32,98,101,32,115,101,116,46>>]}]},{dt,[],[{code,[],[<<108,105,110,107,115,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<78,117,109,98,101,114,32,111,102,32,108,105,110,107,115,32,116,111,32,116,104,101,32,102,105,108,101,32,40,116,104,105,115,32,105,115,32,97,108,119,97,121,115,32,49,32,102,111,114,32,102,105,108,101,32,115,121,115,116,101,109,115,32,116,104,97,116,32,104,97,118,101,32,110,111,32,99,111,110,99,101,112,116,32,111,102,32,108,105,110,107,115,41,46>>]}]},{dt,[],[{code,[],[<<109,97,106,111,114,95,100,101,118,105,99,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<73,100,101,110,116,105,102,105,101,115,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,119,104,101,114,101,32,116,104,101,32,102,105,108,101,32,105,115,32,108,111,99,97,116,101,100,46,32,73,110,32,87,105,110,100,111,119,115,44,32,116,104,101,32,110,117,109,98,101,114,32,105,110,100,105,99,97,116,101,115,32,97,32,100,114,105,118,101,32,97,115,32,102,111,108,108,111,119,115,58,32,48,32,109,101,97,110,115,32,65,58,44,32,49,32,109,101,97,110,115,32,66,58,44,32,97,110,100,32,115,111,32,111,110,46>>]}]},{dt,[],[{code,[],[<<109,105,110,111,114,95,100,101,118,105,99,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,118,97,108,105,100,32,102,111,114,32,99,104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,32,111,110,32,85,110,105,120,46,32,73,110,32,97,108,108,32,111,116,104,101,114,32,99,97,115,101,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]},{dt,[],[{code,[],[<<105,110,111,100,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,116,104,101,32>>,{code,[],[<<105,110,111,100,101>>]},<<32,110,117,109,98,101,114,46,32,79,110,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]},{dt,[],[{code,[],[<<117,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<73,110,100,105,99,97,116,101,115,32,116,104,101,32,111,119,110,101,114,32,111,102,32,116,104,101,32,102,105,108,101,46,32,79,110,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]},{dt,[],[{code,[],[<<103,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,116,104,101,32,103,114,111,117,112,32,116,104,97,116,32,116,104,101,32,111,119,110,101,114,32,111,102,32,116,104,101,32,102,105,108,101,32,98,101,108,111,110,103,115,32,116,111,46,32,79,110,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,122,101,114,111,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,52,52,49>>,signature => [{attribute,{282,2},spec,{{read_file_info,1},[{type,{282,21},bounded_fun,[{type,{282,21},'fun',[{type,{282,21},product,[{var,{282,22},'File'}]},{type,{282,31},union,[{type,{282,31},tuple,[{atom,{282,32},ok},{var,{282,36},'FileInfo'}]},{type,{282,48},tuple,[{atom,{282,49},error},{var,{282,56},'Reason'}]}]}]},[{type,{283,7},constraint,[{atom,{283,7},is_subtype},[{var,{283,7},'File'},{type,{283,15},union,[{user_type,{283,15},name_all,[]},{user_type,{283,28},io_device,[]}]}]]},{type,{284,7},constraint,[{atom,{284,7},is_subtype},[{var,{284,7},'FileInfo'},{user_type,{284,19},file_info,[]}]]},{type,{285,7},constraint,[{atom,{285,7},is_subtype},[{var,{285,7},'Reason'},{type,{285,17},union,[{user_type,{285,17},posix,[]},{atom,{285,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,read_line,1},[{file,[102,105,108,101,46,101,114,108]},{location,612}],[<<114,101,97,100,95,108,105,110,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,97,32,108,105,110,101,32,111,102,32,98,121,116,101,115,47,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,76,105,110,101,115,32,97,114,101,32,100,101,102,105,110,101,100,32,116,111,32,98,101,32,100,101,108,105,109,105,116,101,100,32,98,121,32,116,104,101,32,108,105,110,101,102,101,101,100,32,40,76,70,44,32>>,{code,[],[<<92,110>>]},<<41,32,99,104,97,114,97,99,116,101,114,44,32,98,117,116,32,97,110,121,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,40,67,82,44,32>>,{code,[],[<<92,114>>]},<<41,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,101,119,108,105,110,101,32,105,115,32,97,108,115,111,32,116,114,101,97,116,101,100,32,97,115,32,97,32,115,105,110,103,108,101,32,76,70,32,99,104,97,114,97,99,116,101,114,32,40,116,104,101,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,105,115,32,115,105,108,101,110,116,108,121,32,105,103,110,111,114,101,100,41,46,32,84,104,101,32,108,105,110,101,32,105,115,32,114,101,116,117,114,110,101,100,32>>,{em,[],[<<105,110,99,108,117,100,105,110,103>>]},<<32,116,104,101,32,76,70,44,32,98,117,116,32,101,120,99,108,117,100,105,110,103,32,97,110,121,32,67,82,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,76,70,46,32,84,104,105,115,32,98,101,104,97,118,105,111,117,114,32,105,115,32,99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,32,116,104,101,32,98,101,104,97,118,105,111,117,114,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111,35,103,101,116,95,108,105,110,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,111,58,103,101,116,95,108,105,110,101,47,50>>]}]},<<46,32,73,102,32,101,110,100,32,111,102,32,102,105,108,101,32,105,115,32,114,101,97,99,104,101,100,32,119,105,116,104,111,117,116,32,97,110,121,32,76,70,32,101,110,100,105,110,103,32,116,104,101,32,108,97,115,116,32,108,105,110,101,44,32,97,32,108,105,110,101,32,119,105,116,104,32,110,111,32,116,114,97,105,108,105,110,103,32,76,70,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,117,115,101,100,32,111,110,32,102,105,108,101,115,32,111,112,101,110,101,100,32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,46,32,72,111,119,101,118,101,114,44,32,105,116,32,105,115,32,105,110,101,102,102,105,99,105,101,110,116,32,116,111,32,117,115,101,32,105,116,32,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,102,105,108,101,115,32,105,102,32,116,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,115,112,101,99,105,102,105,101,100,46,32,84,104,117,115,44,32,99,111,109,98,105,110,105,110,103,32>>,{code,[],[<<114,97,119>>]},<<32,97,110,100,32>>,{code,[],[<<123,114,101,97,100,95,97,104,101,97,100,44,32,83,105,122,101,125>>]},<<32,105,115,32,104,105,103,104,108,121,32,114,101,99,111,109,109,101,110,100,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,97,32,116,101,120,116,32,102,105,108,101,32,102,111,114,32,114,97,119,32,108,105,110,101,45,111,114,105,101,110,116,101,100,32,114,101,97,100,105,110,103,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,105,115,32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,116,104,101,32>>,{code,[],[<<114,101,97,100,95,108,105,110,101,47,49>>]},<<32,99,97,108,108,32,102,97,105,108,115,32,105,102,32,116,104,101,32,100,97,116,97,32,99,111,110,116,97,105,110,115,32,99,104,97,114,97,99,116,101,114,115,32,108,97,114,103,101,114,32,116,104,97,110,32,50,53,53,44,32,119,104,121,32,109,111,100,117,108,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,105,111>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<105,111,40,51,41>>]}]},<<32,105,115,32,116,111,32,98,101,32,112,114,101,102,101,114,114,101,100,32,119,104,101,110,32,114,101,97,100,105,110,103,32,115,117,99,104,32,97,32,102,105,108,101,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,68,97,116,97,125>>]}]},{dd,[],[{p,[],[<<79,110,101,32,108,105,110,101,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,105,115,32,114,101,116,117,114,110,101,100,44,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,116,114,97,105,108,105,110,103,32,76,70,44,32,98,117,116,32,119,105,116,104,32,67,82,76,70,32,115,101,113,117,101,110,99,101,115,32,114,101,112,108,97,99,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,76,70,32,40,115,101,101,32,97,98,111,118,101,41,46>>]},{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,105,110,32,98,105,110,97,114,121,32,109,111,100,101,44,32,116,104,101,32,114,101,97,100,32,98,121,116,101,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,105,110,32,97,32,98,105,110,97,114,121,44,32,111,116,104,101,114,119,105,115,101,32,105,110,32,97,32,108,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,111,102>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,101,100,32,105,102,32,101,110,100,32,111,102,32,102,105,108,101,32,119,97,115,32,114,101,97,99,104,101,100,32,98,101,102,111,114,101,32,97,110,121,116,104,105,110,103,32,97,116,32,97,108,108,32,99,111,117,108,100,32,98,101,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,98,97,100,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,102,111,114,32,114,101,97,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<123,110,111,95,116,114,97,110,115,108,97,116,105,111,110,44,32,117,110,105,99,111,100,101,44,32,108,97,116,105,110,49,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32,97,110,111,116,104,101,114,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<32,97,110,100,32,116,104,101,32,100,97,116,97,32,111,110,32,116,104,101,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,116,114,97,110,115,108,97,116,101,100,32,116,111,32,116,104,101,32,98,121,116,101,45,111,114,105,101,110,116,101,100,32,100,97,116,97,32,116,104,97,116,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,54,48,49>>,signature => [{attribute,{612,2},spec,{{read_line,1},[{type,{612,16},bounded_fun,[{type,{612,16},'fun',[{type,{612,16},product,[{var,{612,17},'IoDevice'}]},{type,{612,30},union,[{type,{612,30},tuple,[{atom,{612,31},ok},{var,{612,35},'Data'}]},{atom,{612,43},eof},{type,{612,49},tuple,[{atom,{612,50},error},{var,{612,57},'Reason'}]}]}]},[{type,{613,7},constraint,[{atom,{613,7},is_subtype},[{var,{613,7},'IoDevice'},{type,{613,19},union,[{user_type,{613,19},io_device,[]},{type,{613,33},atom,[]}]}]]},{type,{614,7},constraint,[{atom,{614,7},is_subtype},[{var,{614,7},'Data'},{type,{614,15},union,[{type,{614,15},string,[]},{type,{614,26},binary,[]}]}]]},{type,{615,7},constraint,[{atom,{615,7},is_subtype},[{var,{615,7},'Reason'},{type,{615,17},union,[{user_type,{615,17},posix,[]},{atom,{616,17},badarg},{atom,{617,17},terminated},{type,{618,17},tuple,[{atom,{618,18},no_translation},{atom,{618,34},unicode},{atom,{618,43},latin1}]}]}]]}]]}]}}]}},{{function,read_link,1},[{file,[102,105,108,101,46,101,114,108]},{location,356}],[<<114,101,97,100,95,108,105,110,107,47,49>>],#{<<101,110>> => [{p,[],[{a,[{id,<<114,101,97,100,95,108,105,110,107,95,97,108,108>>}],[]},<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,125>>]},<<32,105,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,114,97,119,32,102,105,108,101,110,97,109,101,44,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,111,116,104,101,114,119,105,115,101,46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,100,111,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<123,101,114,114,111,114,44,101,110,111,116,115,117,112,125>>]},<<46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<78,97,109,101>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32,111,114,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,102,105,108,101,32,116,104,97,116,32,105,116,32,114,101,102,101,114,115,32,116,111,32,100,111,101,115,32,110,111,116,32,99,111,110,102,111,114,109,32,116,111,32,116,104,101,32,101,120,112,101,99,116,101,100,32,101,110,99,111,100,105,110,103,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,54,53,56>>,signature => [{attribute,{356,2},spec,{{read_link,1},[{type,{356,16},bounded_fun,[{type,{356,16},'fun',[{type,{356,16},product,[{var,{356,17},'Name'}]},{type,{356,26},union,[{type,{356,26},tuple,[{atom,{356,27},ok},{var,{356,31},'Filename'}]},{type,{356,43},tuple,[{atom,{356,44},error},{var,{356,51},'Reason'}]}]}]},[{type,{357,7},constraint,[{atom,{357,7},is_subtype},[{var,{357,7},'Name'},{user_type,{357,15},name_all,[]}]]},{type,{358,7},constraint,[{atom,{358,7},is_subtype},[{var,{358,7},'Filename'},{user_type,{358,19},filename,[]}]]},{type,{359,7},constraint,[{atom,{359,7},is_subtype},[{var,{359,7},'Reason'},{type,{359,17},union,[{user_type,{359,17},posix,[]},{atom,{359,27},badarg}]}]]}]]}]}}]}},{{function,read_link_all,1},[{file,[102,105,108,101,46,101,114,108]},{location,364}],[<<114,101,97,100,95,108,105,110,107,95,97,108,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,70,105,108,101,110,97,109,101,125>>]},<<32,105,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,114,101,102,101,114,115,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,32,111,114,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,111,116,104,101,114,119,105,115,101,46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,100,111,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32>>,{code,[],[<<123,101,114,114,111,114,44,101,110,111,116,115,117,112,125>>]},<<46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,101,105,116,104,101,114,32,97,32,108,105,115,116,32,111,114,32,97,32,98,105,110,97,114,121,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<78,97,109,101>>]},<<32,100,111,101,115,32,110,111,116,32,114,101,102,101,114,32,116,111,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,115,117,112>>]}]},{dd,[],[{p,[],[<<83,121,109,98,111,108,105,99,32,108,105,110,107,115,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,111,110,32,116,104,105,115,32,112,108,97,116,102,111,114,109,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,54,56,56>>,signature => [{attribute,{364,2},spec,{{read_link_all,1},[{type,{364,20},bounded_fun,[{type,{364,20},'fun',[{type,{364,20},product,[{var,{364,21},'Name'}]},{type,{364,30},union,[{type,{364,30},tuple,[{atom,{364,31},ok},{var,{364,35},'Filename'}]},{type,{364,47},tuple,[{atom,{364,48},error},{var,{364,55},'Reason'}]}]}]},[{type,{365,7},constraint,[{atom,{365,7},is_subtype},[{var,{365,7},'Name'},{user_type,{365,15},name_all,[]}]]},{type,{366,7},constraint,[{atom,{366,7},is_subtype},[{var,{366,7},'Filename'},{user_type,{366,19},filename_all,[]}]]},{type,{367,7},constraint,[{atom,{367,7},is_subtype},[{var,{367,7},'Reason'},{type,{367,17},union,[{user_type,{367,17},posix,[]},{atom,{367,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,54,66>>}},{{function,read_link_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,334}],[<<114,101,97,100,95,108,105,110,107,95,105,110,102,111,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,49,54>>,equiv => {function,read_link_info,1},signature => [{attribute,{334,2},spec,{{read_link_info,2},[{type,{334,21},bounded_fun,[{type,{334,21},'fun',[{type,{334,21},product,[{var,{334,22},'Name'},{var,{334,28},'Opts'}]},{type,{334,37},union,[{type,{334,37},tuple,[{atom,{334,38},ok},{var,{334,42},'FileInfo'}]},{type,{334,54},tuple,[{atom,{334,55},error},{var,{334,62},'Reason'}]}]}]},[{type,{335,7},constraint,[{atom,{335,7},is_subtype},[{var,{335,7},'Name'},{user_type,{335,15},name_all,[]}]]},{type,{336,7},constraint,[{atom,{336,7},is_subtype},[{var,{336,7},'Opts'},{type,{336,15},list,[{user_type,{336,16},file_info_option,[]}]}]]},{type,{337,7},constraint,[{atom,{337,7},is_subtype},[{var,{337,7},'FileInfo'},{user_type,{337,19},file_info,[]}]]},{type,{338,7},constraint,[{atom,{338,7},is_subtype},[{var,{338,7},'Reason'},{type,{338,17},union,[{user_type,{338,17},posix,[]},{atom,{338,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,read_link_info,1},[{file,[102,105,108,101,46,101,114,108]},{location,326}],[<<114,101,97,100,95,108,105,110,107,95,105,110,102,111,47,49>>],#{<<101,110>> => [{p,[],[<<87,111,114,107,115,32,108,105,107,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49,44,50>>]}]},<<32,101,120,99,101,112,116,32,116,104,97,116,32,105,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,44,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,108,105,110,107,32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,32,116,104,101,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<32,114,101,99,111,114,100,32,97,110,100,32,116,104,101,32>>,{code,[],[<<116,121,112,101>>]},<<32,102,105,101,108,100,32,111,102,32,116,104,101,32,114,101,99,111,114,100,32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<115,121,109,108,105,110,107>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,97,110,100,32,111,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,108,111,99,97,108,32,102,105,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46,32,78,111,116,101,32,116,104,97,116,32,116,104,105,115,32,119,105,108,108,32,98,114,101,97,107,32,116,104,105,115,32,109,111,100,117,108,101,39,115,32,97,116,111,109,105,99,105,116,121,32,103,117,97,114,97,110,116,101,101,115,32,97,115,32,105,116,32,99,97,110,32,114,97,99,101,32,119,105,116,104,32,97,32,99,111,110,99,117,114,114,101,110,116,32,99,97,108,108,32,116,111,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,49,44,50>>]}]}]},{p,[],[<<73,102,32>>,{code,[],[<<78,97,109,101>>]},<<32,105,115,32,110,111,116,32,97,32,115,121,109,98,111,108,105,99,32,108,105,110,107,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32>>,{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>]},<<46,32,79,110,32,112,108,97,116,102,111,114,109,115,32,116,104,97,116,32,100,111,32,110,111,116,32,115,117,112,112,111,114,116,32,115,121,109,98,111,108,105,99,32,108,105,110,107,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,97,108,119,97,121,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<114,101,97,100,95,102,105,108,101,95,105,110,102,111,47,49>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,49,54>>,signature => [{attribute,{326,2},spec,{{read_link_info,1},[{type,{326,21},bounded_fun,[{type,{326,21},'fun',[{type,{326,21},product,[{var,{326,22},'Name'}]},{type,{326,31},union,[{type,{326,31},tuple,[{atom,{326,32},ok},{var,{326,36},'FileInfo'}]},{type,{326,48},tuple,[{atom,{326,49},error},{var,{326,56},'Reason'}]}]}]},[{type,{327,7},constraint,[{atom,{327,7},is_subtype},[{var,{327,7},'Name'},{user_type,{327,15},name_all,[]}]]},{type,{328,7},constraint,[{atom,{328,7},is_subtype},[{var,{328,7},'FileInfo'},{user_type,{328,19},file_info,[]}]]},{type,{329,7},constraint,[{atom,{329,7},is_subtype},[{var,{329,7},'Reason'},{type,{329,17},union,[{user_type,{329,17},posix,[]},{atom,{329,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,rename,2},[{file,[102,105,108,101,46,101,114,108]},{location,241}],[<<114,101,110,97,109,101,47,50>>],#{<<101,110>> => [{p,[],[<<84,114,105,101,115,32,116,111,32,114,101,110,97,109,101,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,116,111,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<46,32,73,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,111,118,101,32,102,105,108,101,115,32,40,97,110,100,32,100,105,114,101,99,116,111,114,105,101,115,41,32,98,101,116,119,101,101,110,32,100,105,114,101,99,116,111,114,105,101,115,44,32,98,117,116,32,105,116,32,105,115,32,110,111,116,32,115,117,102,102,105,99,105,101,110,116,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,100,101,115,116,105,110,97,116,105,111,110,32,111,110,108,121,46,32,84,104,101,32,100,101,115,116,105,110,97,116,105,111,110,32,102,105,108,101,110,97,109,101,32,109,117,115,116,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32>>,{code,[],[<<98,97,114>>]},<<32,105,115,32,97,32,110,111,114,109,97,108,32,102,105,108,101,32,97,110,100,32>>,{code,[],[<<102,111,111>>]},<<32,97,110,100,32>>,{code,[],[<<98,97,122>>]},<<32,97,114,101,32,100,105,114,101,99,116,111,114,105,101,115,44,32>>,{code,[],[<<114,101,110,97,109,101,40,34,102,111,111,47,98,97,114,34,44,32,34,98,97,122,34,41>>]},<<32,114,101,116,117,114,110,115,32,97,110,32,101,114,114,111,114,44,32,98,117,116,32>>,{code,[],[<<114,101,110,97,109,101,40,34,102,111,111,47,98,97,114,34,44,32,34,98,97,122,47,98,97,114,34,41>>]},<<32,115,117,99,99,101,101,100,115,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,105,116,32,105,115,32,115,117,99,99,101,115,115,102,117,108,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<82,101,110,97,109,105,110,103,32,111,102,32,111,112,101,110,32,102,105,108,101,115,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,111,110,32,109,111,115,116,32,112,108,97,116,102,111,114,109,115,32,40,115,101,101,32>>,{code,[],[<<101,97,99,99,101,115>>]},<<32,98,101,108,111,119,41,46>>]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,114,101,97,100,32,111,114,32,119,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,115,32,102,111,114,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,111,114,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,101,114,114,111,114,32,105,115,32,103,105,118,101,110,32,105,102,32,101,105,116,104,101,114,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,111,114,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,111,112,101,110,46>>]}]},{dt,[],[{code,[],[<<101,101,120,105,115,116>>]}]},{dd,[],[{p,[],[{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,110,111,116,32,97,110,32,101,109,112,116,121,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,97,108,115,111,32,103,105,118,101,110,32,119,104,101,110,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,97,114,101,32,110,111,116,32,111,102,32,116,104,101,32,115,97,109,101,32,116,121,112,101,46>>]}]},{dt,[],[{code,[],[<<101,105,110,118,97,108>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,105,115,32,97,32,114,111,111,116,32,100,105,114,101,99,116,111,114,121,44,32,111,114,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,97,32,115,117,98,100,105,114,101,99,116,111,114,121,32,111,102,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,44,32,98,117,116,32>>,{code,[],[<<83,111,117,114,99,101>>]},<<32,105,115,32,110,111,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,44,32,98,117,116,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,105,115,32,110,111,116,46>>]}]},{dt,[],[{code,[],[<<101,120,100,101,118>>]}]},{dd,[],[{p,[],[{code,[],[<<83,111,117,114,99,101>>]},<<32,97,110,100,32>>,{code,[],[<<68,101,115,116,105,110,97,116,105,111,110>>]},<<32,97,114,101,32,111,110,32,100,105,102,102,101,114,101,110,116,32,102,105,108,101,32,115,121,115,116,101,109,115,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,55,51,56>>,signature => [{attribute,{241,2},spec,{{rename,2},[{type,{241,13},bounded_fun,[{type,{241,13},'fun',[{type,{241,13},product,[{var,{241,14},'Source'},{var,{241,22},'Destination'}]},{type,{241,38},union,[{atom,{241,38},ok},{type,{241,43},tuple,[{atom,{241,44},error},{var,{241,51},'Reason'}]}]}]},[{type,{242,7},constraint,[{atom,{242,7},is_subtype},[{var,{242,7},'Source'},{user_type,{242,17},name_all,[]}]]},{type,{243,7},constraint,[{atom,{243,7},is_subtype},[{var,{243,7},'Destination'},{user_type,{243,22},name_all,[]}]]},{type,{244,7},constraint,[{atom,{244,7},is_subtype},[{var,{244,7},'Reason'},{type,{244,17},union,[{user_type,{244,17},posix,[]},{atom,{244,27},badarg}]}]]}]]}]}}]}},{{function,script,1},[{file,[102,105,108,101,46,101,114,108]},{location,1123}],[<<115,99,114,105,112,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,97,100,115,32,97,110,100,32,101,118,97,108,117,97,116,101,115,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,39,46,39,32,40,111,114,32,39,44,39,44,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,97,108,115,111,32,97,110,32,101,120,112,114,101,115,115,105,111,110,41,44,32,102,114,111,109,32,116,104,101,32,102,105,108,101,46>>]},{p,[],[<<82,101,116,117,114,110,115,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<123,111,107,44,32,86,97,108,117,101,125>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,114,101,97,100,32,97,110,100,32,101,118,97,108,117,97,116,101,100,46,32>>,{code,[],[<<86,97,108,117,101>>]},<<32,105,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,108,97,115,116,32,101,120,112,114,101,115,115,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,97,116,111,109,40,41,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,111,112,101,110,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,114,101,97,100,105,110,103,32,105,116,46,32,70,111,114,32,97,32,108,105,115,116,32,111,102,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,99,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<123,101,114,114,111,114,44,32,123,76,105,110,101,44,32,77,111,100,44,32,84,101,114,109,125,125>>]}]},{dd,[],[{p,[],[<<65,110,32,101,114,114,111,114,32,111,99,99,117,114,114,101,100,32,119,104,101,110,32,105,110,116,101,114,112,114,101,116,105,110,103,32,116,104,101,32,69,114,108,97,110,103,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,116,104,101,32,102,105,108,101,46,32,85,115,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,102,111,114,109,97,116,95,101,114,114,111,114,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,111,114,109,97,116,95,101,114,114,111,114,47,49>>]}]},<<32,116,111,32,99,111,110,118,101,114,116,32,116,104,101,32,116,104,114,101,101,45,101,108,101,109,101,110,116,32,116,117,112,108,101,32,116,111,32,97,110,32,69,110,103,108,105,115,104,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,97,32,99,111,109,109,101,110,116,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,112,112,35,101,110,99,111,100,105,110,103>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,112,112,40,51,41>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,48,49>>,signature => [{attribute,{1123,2},spec,{{script,1},[{type,{1123,13},bounded_fun,[{type,{1123,13},'fun',[{type,{1123,13},product,[{var,{1123,14},'Filename'}]},{type,{1123,27},union,[{type,{1123,27},tuple,[{atom,{1123,28},ok},{var,{1123,32},'Value'}]},{type,{1123,41},tuple,[{atom,{1123,42},error},{var,{1123,49},'Reason'}]}]}]},[{type,{1124,7},constraint,[{atom,{1124,7},is_subtype},[{var,{1124,7},'Filename'},{user_type,{1124,19},name_all,[]}]]},{type,{1125,7},constraint,[{atom,{1125,7},is_subtype},[{var,{1125,7},'Value'},{type,{1125,16},term,[]}]]},{type,{1126,7},constraint,[{atom,{1126,7},is_subtype},[{var,{1126,7},'Reason'},{type,{1126,17},union,[{user_type,{1126,17},posix,[]},{atom,{1126,27},badarg},{atom,{1126,36},terminated},{atom,{1126,49},system_limit},{type,{1127,17},tuple,[{ann_type,{1127,18},[{var,{1127,18},'Line'},{type,{1127,26},integer,[]}]},{ann_type,{1127,37},[{var,{1127,37},'Mod'},{type,{1127,44},module,[]}]},{ann_type,{1127,54},[{var,{1127,54},'Term'},{type,{1127,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,script,2},[{file,[102,105,108,101,46,101,114,108]},{location,1132}],[<<115,99,114,105,112,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<115,99,114,105,112,116,47,49>>]},<<32,98,117,116,32,116,104,101,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,32>>,{code,[],[<<66,105,110,100,105,110,103,115>>]},<<32,97,114,101,32,117,115,101,100,32,105,110,32,116,104,101,32,101,118,97,108,117,97,116,105,111,110,46,32,83,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,101,114,108,95,101,118,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<101,114,108,95,101,118,97,108,40,51,41>>]}]},<<32,97,98,111,117,116,32,118,97,114,105,97,98,108,101,32,98,105,110,100,105,110,103,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,51,54>>,signature => [{attribute,{1132,2},spec,{{script,2},[{type,{1132,13},bounded_fun,[{type,{1132,13},'fun',[{type,{1132,13},product,[{var,{1132,14},'Filename'},{var,{1132,24},'Bindings'}]},{type,{1132,37},union,[{type,{1132,37},tuple,[{atom,{1132,38},ok},{var,{1132,42},'Value'}]},{type,{1132,51},tuple,[{atom,{1132,52},error},{var,{1132,59},'Reason'}]}]}]},[{type,{1133,7},constraint,[{atom,{1133,7},is_subtype},[{var,{1133,7},'Filename'},{user_type,{1133,19},name_all,[]}]]},{type,{1134,7},constraint,[{atom,{1134,7},is_subtype},[{var,{1134,7},'Bindings'},{remote_type,{1134,19},[{atom,{1134,19},erl_eval},{atom,{1134,28},binding_struct},[]]}]]},{type,{1135,7},constraint,[{atom,{1135,7},is_subtype},[{var,{1135,7},'Value'},{type,{1135,16},term,[]}]]},{type,{1136,7},constraint,[{atom,{1136,7},is_subtype},[{var,{1136,7},'Reason'},{type,{1136,17},union,[{user_type,{1136,17},posix,[]},{atom,{1136,27},badarg},{atom,{1136,36},terminated},{atom,{1136,49},system_limit},{type,{1137,17},tuple,[{ann_type,{1137,18},[{var,{1137,18},'Line'},{type,{1137,26},integer,[]}]},{ann_type,{1137,37},[{var,{1137,37},'Mod'},{type,{1137,44},module,[]}]},{ann_type,{1137,54},[{var,{1137,54},'Term'},{type,{1137,62},term,[]}]}]}]}]]}]]}]}}]}},{{function,sendfile,2},[{file,[102,105,108,101,46,101,114,108]},{location,1317}],[<<115,101,110,100,102,105,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<83,101,110,100,115,32,116,104,101,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<32,116,111,32>>,{code,[],[<<83,111,99,107,101,116>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,121,116,101,115,83,101,110,116,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,52,54>>,signature => [{attribute,{1317,2},spec,{{sendfile,2},[{type,{1317,15},bounded_fun,[{type,{1317,15},'fun',[{type,{1317,15},product,[{var,{1317,16},'Filename'},{var,{1317,26},'Socket'}]},{type,{1318,4},union,[{type,{1318,4},tuple,[{atom,{1318,5},ok},{type,{1318,11},non_neg_integer,[]}]},{type,{1318,32},tuple,[{atom,{1318,33},error},{type,{1318,42},union,[{remote_type,{1318,42},[{atom,{1318,42},inet},{atom,{1318,47},posix},[]]},{atom,{1319,5},closed},{atom,{1319,14},badarg},{atom,{1319,23},not_owner}]}]}]}]},[{type,{1320,7},constraint,[{atom,{1320,7},is_subtype},[{var,{1320,7},'Filename'},{user_type,{1320,19},name_all,[]}]]},{type,{1321,7},constraint,[{atom,{1321,7},is_subtype},[{var,{1321,7},'Socket'},{type,{1321,17},union,[{remote_type,{1321,17},[{atom,{1321,17},inet},{atom,{1321,22},socket},[]]},{remote_type,{1321,33},[{atom,{1321,33},socket},{atom,{1321,40},socket},[]]},{type,{1322,22},'fun',[{type,{1322,22},product,[{type,{1322,23},iolist,[]}]},{type,{1322,36},union,[{atom,{1322,36},ok},{type,{1322,41},tuple,[{atom,{1322,42},error},{type,{1322,49},union,[{remote_type,{1322,49},[{atom,{1322,49},inet},{atom,{1322,54},posix},[]]},{atom,{1322,64},closed}]}]}]}]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,sendfile,5},[{file,[102,105,108,101,46,101,114,108]},{location,1289}],[<<115,101,110,100,102,105,108,101,47,53>>],#{<<101,110>> => [{ul,[{class,<<116,121,112,101,115>>}],[{li,[{name,<<115,101,110,100,102,105,108,101,95,111,112,116,105,111,110>>}],[]}]},{p,[],[<<83,101,110,100,115,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<82,97,119,70,105,108,101>>]},<<32,98,101,103,105,110,110,105,110,103,32,97,116,32>>,{code,[],[<<79,102,102,115,101,116>>]},<<32,116,111,32>>,{code,[],[<<83,111,99,107,101,116>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<123,111,107,44,32,66,121,116,101,115,83,101,110,116,125>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32,73,102,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,105,115,32,115,101,116,32,116,111,32>>,{code,[],[<<48>>]},<<32,97,108,108,32,100,97,116,97,32,97,102,116,101,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32>>,{code,[],[<<79,102,102,115,101,116>>]},<<32,105,115,32,115,101,110,116,46>>]},{p,[],[<<84,104,101,32,102,105,108,101,32,117,115,101,100,32,109,117,115,116,32,98,101,32,111,112,101,110,101,100,32,117,115,105,110,103,32,116,104,101,32>>,{code,[],[<<114,97,119>>]},<<32,102,108,97,103,44,32,97,110,100,32,116,104,101,32,112,114,111,99,101,115,115,32,99,97,108,108,105,110,103,32>>,{code,[],[<<115,101,110,100,102,105,108,101>>]},<<32,109,117,115,116,32,98,101,32,116,104,101,32,99,111,110,116,114,111,108,108,105,110,103,32,112,114,111,99,101,115,115,32,111,102,32,116,104,101,32,115,111,99,107,101,116,46,32,83,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,103,101,110,95,116,99,112,35,99,111,110,116,114,111,108,108,105,110,103,95,112,114,111,99,101,115,115,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,101,110,95,116,99,112,58,99,111,110,116,114,111,108,108,105,110,103,95,112,114,111,99,101,115,115,47,50>>]}]},<<32,111,114,32,109,111,100,117,108,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,115,111,99,107,101,116,35,115,101,116,111,112,116,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,111,99,107,101,116>>]},<<39,115>>]},<<32>>,{a,[{href,<<107,101,114,110,101,108,58,115,111,99,107,101,116,35,111,116,112,95,115,111,99,107,101,116,95,111,112,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[<<108,101,118,101,108,32>>,{code,[],[<<111,116,112>>]},<<32,115,111,99,107,101,116,32,111,112,116,105,111,110,32>>]},{code,[],[<<99,111,110,116,114,111,108,108,105,110,103,95,112,114,111,99,101,115,115>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,79,83,32,117,115,101,100,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,110,111,110,45,98,108,111,99,107,105,110,103,32>>,{code,[],[<<115,101,110,100,102,105,108,101>>]},<<44,32,97,110,32,69,114,108,97,110,103,32,102,97,108,108,98,97,99,107,32,117,115,105,110,103,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,101,97,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,97,100,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<107,101,114,110,101,108,58,103,101,110,95,116,99,112,35,115,101,110,100,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<103,101,110,95,116,99,112,58,115,101,110,100,47,50>>]}]},<<32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,111,112,116,105,111,110,32,108,105,115,116,32,99,97,110,32,99,111,110,116,97,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<99,104,117,110,107,95,115,105,122,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,99,104,117,110,107,32,115,105,122,101,32,117,115,101,100,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,102,97,108,108,98,97,99,107,32,116,111,32,115,101,110,100,32,100,97,116,97,46,32,73,102,32,117,115,105,110,103,32,116,104,101,32,102,97,108,108,98,97,99,107,44,32,115,101,116,32,116,104,105,115,32,116,111,32,97,32,118,97,108,117,101,32,116,104,97,116,32,99,111,109,102,111,114,116,97,98,108,121,32,102,105,116,115,32,105,110,32,116,104,101,32,115,121,115,116,101,109,115,32,109,101,109,111,114,121,46,32,68,101,102,97,117,108,116,32,105,115,32,50,48,32,77,66,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,53,53>>,signature => [{attribute,{1289,2},spec,{{sendfile,5},[{type,{1289,15},bounded_fun,[{type,{1289,15},'fun',[{type,{1289,15},product,[{var,{1289,16},'RawFile'},{var,{1289,25},'Socket'},{var,{1289,33},'Offset'},{var,{1289,41},'Bytes'},{var,{1289,48},'Opts'}]},{type,{1290,4},union,[{type,{1290,4},tuple,[{atom,{1290,5},ok},{type,{1290,11},non_neg_integer,[]}]},{type,{1290,32},tuple,[{atom,{1290,33},error},{type,{1290,42},union,[{remote_type,{1290,42},[{atom,{1290,42},inet},{atom,{1290,47},posix},[]]},{atom,{1291,5},closed},{atom,{1291,14},badarg},{atom,{1291,23},not_owner}]}]}]}]},[{type,{1292,7},constraint,[{atom,{1292,7},is_subtype},[{var,{1292,7},'RawFile'},{user_type,{1292,18},fd,[]}]]},{type,{1293,7},constraint,[{atom,{1293,7},is_subtype},[{var,{1293,7},'Socket'},{type,{1293,17},union,[{remote_type,{1293,17},[{atom,{1293,17},inet},{atom,{1293,22},socket},[]]},{remote_type,{1293,33},[{atom,{1293,33},socket},{atom,{1293,40},socket},[]]},{type,{1294,22},'fun',[{type,{1294,22},product,[{type,{1294,23},iolist,[]}]},{type,{1294,36},union,[{atom,{1294,36},ok},{type,{1294,41},tuple,[{atom,{1294,42},error},{type,{1294,49},union,[{remote_type,{1294,49},[{atom,{1294,49},inet},{atom,{1294,54},posix},[]]},{atom,{1294,64},closed}]}]}]}]}]}]]},{type,{1295,7},constraint,[{atom,{1295,7},is_subtype},[{var,{1295,7},'Offset'},{type,{1295,17},non_neg_integer,[]}]]},{type,{1296,7},constraint,[{atom,{1296,7},is_subtype},[{var,{1296,7},'Bytes'},{type,{1296,16},non_neg_integer,[]}]]},{type,{1297,7},constraint,[{atom,{1297,7},is_subtype},[{var,{1297,7},'Opts'},{type,{1297,15},list,[{user_type,{1297,16},sendfile_option,[]}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,set_cwd,1},[{file,[102,105,108,101,46,101,114,108]},{location,206}],[<<115,101,116,95,99,119,100,47,49>>],#{<<101,110>> => [{p,[],[<<83,101,116,115,32,116,104,101,32,99,117,114,114,101,110,116,32,119,111,114,107,105,110,103,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,116,111,32>>,{code,[],[<<68,105,114>>]},<<46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,101,32,109,111,100,117,108,101,32>>,{code,[],[<<102,105,108,101>>]},<<32,117,115,117,97,108,108,121,32,116,114,101,97,116,32,98,105,110,97,114,105,101,115,32,97,115,32,114,97,119,32,102,105,108,101,110,97,109,101,115,44,32,116,104,97,116,32,105,115,44,32,116,104,101,121,32,97,114,101,32,112,97,115,115,101,100,32,34,97,115,32,105,115,34,32,101,118,101,110,32,119,104,101,110,32,116,104,101,32,101,110,99,111,100,105,110,103,32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,100,111,101,115,32,110,111,116,32,97,103,114,101,101,32,119,105,116,104,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,40,41>>]}]},<<46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,101,120,112,101,99,116,115,32,98,105,110,97,114,105,101,115,32,116,111,32,98,101,32,101,110,99,111,100,101,100,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,118,97,108,117,101,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{code,[],[<<110,97,116,105,118,101,95,110,97,109,101,95,101,110,99,111,100,105,110,103,40,41>>]},<<46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,32,97,114,101,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,100,105,114,101,99,116,111,114,121,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32>>,{code,[],[<<68,105,114>>]},<<32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,111,114,32,111,110,101,32,111,102,32,105,116,115,32,112,97,114,101,110,116,115,46>>]}]},{dt,[],[{code,[],[<<98,97,100,97,114,103>>]}]},{dd,[],[{p,[],[{code,[],[<<68,105,114>>]},<<32,104,97,115,32,97,110,32,105,109,112,114,111,112,101,114,32,116,121,112,101,44,32,115,117,99,104,32,97,115,32,116,117,112,108,101,46>>]}]},{dt,[],[{code,[],[<<110,111,95,116,114,97,110,115,108,97,116,105,111,110>>]}]},{dd,[],[{p,[],[{code,[],[<<68,105,114>>]},<<32,105,115,32,97,32>>,{code,[],[<<98,105,110,97,114,121,40,41>>]},<<32,119,105,116,104,32,99,104,97,114,97,99,116,101,114,115,32,99,111,100,101,100,32,105,110,32,73,83,79,45,108,97,116,105,110,45,49,32,97,110,100,32,116,104,101,32,86,77,32,105,115,32,111,112,101,114,97,116,105,110,103,32,119,105,116,104,32,117,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,101,110,99,111,100,105,110,103,46>>]}]}]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,110,32,97,32,102,117,116,117,114,101,32,114,101,108,101,97,115,101,44,32,97,32,98,97,100,32,116,121,112,101,32,102,111,114,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<68,105,114>>]},<<32,119,105,108,108,32,112,114,111,98,97,98,108,121,32,103,101,110,101,114,97,116,101,32,97,110,32,101,120,99,101,112,116,105,111,110,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,56,56,56>>,signature => [{attribute,{206,2},spec,{{set_cwd,1},[{type,{206,14},bounded_fun,[{type,{206,14},'fun',[{type,{206,14},product,[{var,{206,15},'Dir'}]},{type,{206,23},union,[{atom,{206,23},ok},{type,{206,28},tuple,[{atom,{206,29},error},{var,{206,36},'Reason'}]}]}]},[{type,{207,7},constraint,[{atom,{207,7},is_subtype},[{var,{207,7},'Dir'},{type,{207,14},union,[{user_type,{207,14},name,[]},{var,{207,23},'EncodedBinary'}]}]]},{type,{208,7},constraint,[{atom,{208,7},is_subtype},[{var,{208,7},'EncodedBinary'},{type,{208,24},binary,[]}]]},{type,{209,7},constraint,[{atom,{209,7},is_subtype},[{var,{209,7},'Reason'},{type,{209,17},union,[{user_type,{209,17},posix,[]},{atom,{209,27},badarg},{atom,{209,36},no_translation}]}]]}]]}]}}]}},{{function,sync,1},[{file,[102,105,108,101,46,101,114,108]},{location,742}],[<<115,121,110,99,47,49>>],#{<<101,110>> => [{p,[],[<<69,110,115,117,114,101,115,32,116,104,97,116,32,97,110,121,32,98,117,102,102,101,114,115,32,107,101,112,116,32,98,121,32,116,104,101,32,111,112,101,114,97,116,105,110,103,32,115,121,115,116,101,109,32,40,110,111,116,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,114,117,110,116,105,109,101,32,115,121,115,116,101,109,41,32,97,114,101,32,119,114,105,116,116,101,110,32,116,111,32,100,105,115,107,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,109,105,103,104,116,32,104,97,118,101,32,110,111,32,101,102,102,101,99,116,46>>]},{p,[],[<<65,32,116,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,32,105,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,116,32,101,110,111,117,103,104,32,115,112,97,99,101,32,108,101,102,116,32,116,111,32,119,114,105,116,101,32,116,104,101,32,102,105,108,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,51,53>>,signature => [{attribute,{742,2},spec,{{sync,1},[{type,{742,11},bounded_fun,[{type,{742,11},'fun',[{type,{742,11},product,[{var,{742,12},'IoDevice'}]},{type,{742,25},union,[{atom,{742,25},ok},{type,{742,30},tuple,[{atom,{742,31},error},{var,{742,38},'Reason'}]}]}]},[{type,{743,7},constraint,[{atom,{743,7},is_subtype},[{var,{743,7},'IoDevice'},{user_type,{743,19},io_device,[]}]]},{type,{744,7},constraint,[{atom,{744,7},is_subtype},[{var,{744,7},'Reason'},{type,{744,17},union,[{user_type,{744,17},posix,[]},{atom,{744,27},badarg},{atom,{744,36},terminated}]}]]}]]}]}}]}},{{function,truncate,1},[{file,[102,105,108,101,46,101,114,108]},{location,766}],[<<116,114,117,110,99,97,116,101,47,49>>],#{<<101,110>> => [{p,[],[<<84,114,117,110,99,97,116,101,115,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,53,49>>,signature => [{attribute,{766,2},spec,{{truncate,1},[{type,{766,15},bounded_fun,[{type,{766,15},'fun',[{type,{766,15},product,[{var,{766,16},'IoDevice'}]},{type,{766,29},union,[{atom,{766,29},ok},{type,{766,34},tuple,[{atom,{766,35},error},{var,{766,42},'Reason'}]}]}]},[{type,{767,7},constraint,[{atom,{767,7},is_subtype},[{var,{767,7},'IoDevice'},{user_type,{767,19},io_device,[]}]]},{type,{768,7},constraint,[{atom,{768,7},is_subtype},[{var,{768,7},'Reason'},{type,{768,17},union,[{user_type,{768,17},posix,[]},{atom,{768,27},badarg},{atom,{768,36},terminated}]}]]}]]}]}}]}},{{function,write,2},[{file,[102,105,108,101,46,101,114,108]},{location,676}],[<<119,114,105,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<87,114,105,116,101,115,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,116,111,32,116,104,101,32,102,105,108,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32>>,{code,[],[<<73,111,68,101,118,105,99,101>>]},<<46,32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,116,104,101,32,111,110,108,121,32,119,97,121,32,116,111,32,119,114,105,116,101,32,116,111,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32>>,{code,[],[<<114,97,119>>]},<<32,109,111,100,101,32,40,97,108,116,104,111,117,103,104,32,105,116,32,119,111,114,107,115,32,102,111,114,32,110,111,114,109,97,108,108,121,32,111,112,101,110,101,100,32,102,105,108,101,115,32,116,111,111,41,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,97,110,100,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<32,111,116,104,101,114,119,105,115,101,46>>]},{p,[],[<<73,102,32,116,104,101,32,102,105,108,101,32,105,115,32,111,112,101,110,101,100,32,119,105,116,104,32>>,{code,[],[<<101,110,99,111,100,105,110,103>>]},<<32,115,101,116,32,116,111,32,115,111,109,101,116,104,105,110,103,32,101,108,115,101,32,116,104,97,110,32>>,{code,[],[<<108,97,116,105,110,49>>]},<<44,32,101,97,99,104,32,98,121,116,101,32,119,114,105,116,116,101,110,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,109,97,110,121,32,98,121,116,101,115,32,98,101,105,110,103,32,119,114,105,116,116,101,110,32,116,111,32,116,104,101,32,102,105,108,101,44,32,97,115,32,116,104,101,32,98,121,116,101,32,114,97,110,103,101,32,48,46,46,50,53,53,32,99,97,110,32,114,101,112,114,101,115,101,110,116,32,97,110,121,116,104,105,110,103,32,98,101,116,119,101,101,110,32,111,110,101,32,97,110,100,32,102,111,117,114,32,98,121,116,101,115,32,100,101,112,101,110,100,105,110,103,32,111,110,32,118,97,108,117,101,32,97,110,100,32,85,84,70,32,101,110,99,111,100,105,110,103,32,116,121,112,101,46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,98,97,100,102>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,105,115,32,110,111,116,32,111,112,101,110,101,100,32,102,111,114,32,119,114,105,116,105,110,103,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,99,101,32,105,115,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,54,48>>,signature => [{attribute,{676,2},spec,{{write,2},[{type,{676,12},bounded_fun,[{type,{676,12},'fun',[{type,{676,12},product,[{var,{676,13},'IoDevice'},{var,{676,23},'Bytes'}]},{type,{676,33},union,[{atom,{676,33},ok},{type,{676,38},tuple,[{atom,{676,39},error},{var,{676,46},'Reason'}]}]}]},[{type,{677,7},constraint,[{atom,{677,7},is_subtype},[{var,{677,7},'IoDevice'},{type,{677,19},union,[{user_type,{677,19},io_device,[]},{type,{677,33},atom,[]}]}]]},{type,{678,7},constraint,[{atom,{678,7},is_subtype},[{var,{678,7},'Bytes'},{type,{678,16},iodata,[]}]]},{type,{679,7},constraint,[{atom,{679,7},is_subtype},[{var,{679,7},'Reason'},{type,{679,17},union,[{user_type,{679,17},posix,[]},{atom,{679,27},badarg},{atom,{679,36},terminated}]}]]}]]}]}}]}},{{function,write_file,2},[{file,[102,105,108,101,46,101,114,108]},{location,443}],[<<119,114,105,116,101,95,102,105,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<87,114,105,116,101,115,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,116,104,101,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<32,116,101,114,109,32>>,{code,[],[<<66,121,116,101,115>>]},<<32,116,111,32,102,105,108,101,32>>,{code,[],[<<70,105,108,101,110,97,109,101>>]},<<46,32,84,104,101,32,102,105,108,101,32,105,115,32,99,114,101,97,116,101,100,32,105,102,32,105,116,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46,32,73,102,32,105,116,32,101,120,105,115,116,115,44,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,111,110,116,101,110,116,115,32,97,114,101,32,111,118,101,114,119,114,105,116,116,101,110,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46>>]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]},{dt,[],[{code,[],[<<101,110,111,115,112,99>>]}]},{dd,[],[{p,[],[<<78,111,32,115,112,97,99,101,32,105,115,32,108,101,102,116,32,111,110,32,116,104,101,32,100,101,118,105,99,101,46>>]}]},{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,119,114,105,116,105,110,103,32,116,104,101,32,102,105,108,101,32,111,114,32,115,101,97,114,99,104,105,110,103,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<101,105,115,100,105,114>>]}]},{dd,[],[{p,[],[<<84,104,101,32,110,97,109,101,100,32,102,105,108,101,32,105,115,32,97,32,100,105,114,101,99,116,111,114,121,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,49,57,56,54>>,signature => [{attribute,{443,2},spec,{{write_file,2},[{type,{443,17},bounded_fun,[{type,{443,17},'fun',[{type,{443,17},product,[{var,{443,18},'Filename'},{var,{443,28},'Bytes'}]},{type,{443,38},union,[{atom,{443,38},ok},{type,{443,43},tuple,[{atom,{443,44},error},{var,{443,51},'Reason'}]}]}]},[{type,{444,7},constraint,[{atom,{444,7},is_subtype},[{var,{444,7},'Filename'},{user_type,{444,19},name_all,[]}]]},{type,{445,7},constraint,[{atom,{445,7},is_subtype},[{var,{445,7},'Bytes'},{type,{445,16},iodata,[]}]]},{type,{446,7},constraint,[{atom,{446,7},is_subtype},[{var,{446,7},'Reason'},{type,{446,17},union,[{user_type,{446,17},posix,[]},{atom,{446,27},badarg},{atom,{446,36},terminated},{atom,{446,49},system_limit}]}]]}]]}]}}]}},{{function,write_file,3},[{file,[102,105,108,101,46,101,114,108]},{location,455}],[<<119,114,105,116,101,95,102,105,108,101,47,51>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<119,114,105,116,101,95,102,105,108,101,47,50>>]},<<44,32,98,117,116,32,116,97,107,101,115,32,97,32,116,104,105,114,100,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<77,111,100,101,115>>]},<<44,32,97,32,108,105,115,116,32,111,102,32,112,111,115,115,105,98,108,101,32,109,111,100,101,115,44,32,115,101,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<46,32,84,104,101,32,109,111,100,101,32,102,108,97,103,115,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,97,110,100,32>>,{code,[],[<<119,114,105,116,101>>]},<<32,97,114,101,32,105,109,112,108,105,99,105,116,44,32,115,111,32,116,104,101,121,32,97,114,101,32,110,111,116,32,116,111,32,98,101,32,117,115,101,100,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,50,51>>,signature => [{attribute,{455,2},spec,{{write_file,3},[{type,{455,17},bounded_fun,[{type,{455,17},'fun',[{type,{455,17},product,[{var,{455,18},'Filename'},{var,{455,28},'Bytes'},{var,{455,35},'Modes'}]},{type,{455,45},union,[{atom,{455,45},ok},{type,{455,50},tuple,[{atom,{455,51},error},{var,{455,58},'Reason'}]}]}]},[{type,{456,7},constraint,[{atom,{456,7},is_subtype},[{var,{456,7},'Filename'},{user_type,{456,19},name_all,[]}]]},{type,{457,7},constraint,[{atom,{457,7},is_subtype},[{var,{457,7},'Bytes'},{type,{457,16},iodata,[]}]]},{type,{458,7},constraint,[{atom,{458,7},is_subtype},[{var,{458,7},'Modes'},{type,{458,16},list,[{user_type,{458,17},mode,[]}]}]]},{type,{459,7},constraint,[{atom,{459,7},is_subtype},[{var,{459,7},'Reason'},{type,{459,17},union,[{user_type,{459,17},posix,[]},{atom,{459,27},badarg},{atom,{459,36},terminated},{atom,{459,49},system_limit}]}]]}]]}]}}]}},{{function,write_file_info,3},[{file,[102,105,108,101,46,101,114,108]},{location,380}],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,51>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,51,52>>,equiv => {function,write_file_info,2},signature => [{attribute,{380,2},spec,{{write_file_info,3},[{type,{380,22},bounded_fun,[{type,{380,22},'fun',[{type,{380,22},product,[{var,{380,23},'Filename'},{var,{380,33},'FileInfo'},{var,{380,43},'Opts'}]},{type,{380,52},union,[{atom,{380,52},ok},{type,{380,57},tuple,[{atom,{380,58},error},{var,{380,65},'Reason'}]}]}]},[{type,{381,7},constraint,[{atom,{381,7},is_subtype},[{var,{381,7},'Filename'},{user_type,{381,19},name_all,[]}]]},{type,{382,7},constraint,[{atom,{382,7},is_subtype},[{var,{382,7},'Opts'},{type,{382,15},list,[{user_type,{382,16},file_info_option,[]}]}]]},{type,{383,7},constraint,[{atom,{383,7},is_subtype},[{var,{383,7},'FileInfo'},{user_type,{383,19},file_info,[]}]]},{type,{384,7},constraint,[{atom,{384,7},is_subtype},[{var,{384,7},'Reason'},{type,{384,17},union,[{user_type,{384,17},posix,[]},{atom,{384,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{function,write_file_info,2},[{file,[102,105,108,101,46,101,114,108]},{location,372}],[<<119,114,105,116,101,95,102,105,108,101,95,105,110,102,111,47,50>>],#{<<101,110>> => [{p,[],[<<67,104,97,110,103,101,115,32,102,105,108,101,32,105,110,102,111,114,109,97,116,105,111,110,46,32,82,101,116,117,114,110,115,32>>,{code,[],[<<111,107>>]},<<32,105,102,32,115,117,99,99,101,115,115,102,117,108,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<123,101,114,114,111,114,44,32,82,101,97,115,111,110,125>>]},<<46,32>>,{code,[],[<<70,105,108,101,73,110,102,111>>]},<<32,105,115,32,97,32,114,101,99,111,114,100,32>>,{code,[],[<<102,105,108,101,95,105,110,102,111>>]},<<44,32,100,101,102,105,110,101,100,32,105,110,32,116,104,101,32,75,101,114,110,101,108,32,105,110,99,108,117,100,101,32,102,105,108,101,32>>,{code,[],[<<102,105,108,101,46,104,114,108>>]},<<46,32,73,110,99,108,117,100,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,100,105,114,101,99,116,105,118,101,32,105,110,32,116,104,101,32,109,111,100,117,108,101,32,102,114,111,109,32,119,104,105,99,104,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<32,45,105,110,99,108,117,100,101,95,108,105,98,40,34,107,101,114,110,101,108,47,105,110,99,108,117,100,101,47,102,105,108,101,46,104,114,108,34,41,46>>]}]},{p,[],[<<84,104,101,32,116,105,109,101,32,116,121,112,101,32,115,101,116,32,105,110,32>>,{code,[],[<<97,116,105,109,101>>]},<<44,32>>,{code,[],[<<109,116,105,109,101>>]},<<44,32,97,110,100,32>>,{code,[],[<<99,116,105,109,101>>]},<<32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,116,105,109,101,32,116,121,112,101,32,115,101,116,32,105,110,32>>,{code,[],[<<79,112,116,115,32,58,58,32,123,116,105,109,101,44,32,84,121,112,101,125>>]},<<32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<108,111,99,97,108>>]}]},{dd,[],[{p,[],[<<73,110,116,101,114,112,114,101,116,115,32,116,104,101,32,116,105,109,101,32,115,101,116,32,97,115,32,108,111,99,97,108,46>>]}]},{dt,[],[{code,[],[<<117,110,105,118,101,114,115,97,108>>]}]},{dd,[],[{p,[],[<<73,110,116,101,114,112,114,101,116,115,32,105,116,32,97,115,32,117,110,105,118,101,114,115,97,108,32,116,105,109,101,46>>]}]},{dt,[],[{code,[],[<<112,111,115,105,120>>]}]},{dd,[],[{p,[],[<<77,117,115,116,32,98,101,32,115,101,99,111,110,100,115,32,115,105,110,99,101,32,111,114,32,98,101,102,111,114,101,32,85,110,105,120,32,116,105,109,101,32,101,112,111,99,104,44,32,119,104,105,99,104,32,105,115,32,49,57,55,48,45,48,49,45,48,49,32,48,48,58,48,48,32,85,84,67,46>>]}]}]},{p,[],[<<68,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<123,116,105,109,101,44,32,108,111,99,97,108,125>>]},<<46>>]},{p,[],[<<73,102,32,116,104,101,32,111,112,116,105,111,110,32>>,{code,[],[<<114,97,119>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,102,105,108,101,32,115,101,114,118,101,114,32,105,115,32,110,111,116,32,99,97,108,108,101,100,32,97,110,100,32,111,110,108,121,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,108,111,99,97,108,32,102,105,108,101,115,32,105,115,32,114,101,116,117,114,110,101,100,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,101,108,100,115,32,97,114,101,32,117,115,101,100,32,102,114,111,109,32,116,104,101,32,114,101,99,111,114,100,44,32,105,102,32,116,104,101,121,32,97,114,101,32,115,112,101,99,105,102,105,101,100,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,114,101,97,100,46>>]}]},{dt,[],[{code,[],[<<109,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,108,97,115,116,32,116,105,109,101,32,116,104,101,32,102,105,108,101,32,119,97,115,32,119,114,105,116,116,101,110,46>>]}]},{dt,[],[{code,[],[<<99,116,105,109,101,32,61,32>>]},{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,100,97,116,101,95,116,105,109,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<100,97,116,101,95,116,105,109,101,40,41>>]}]},{code,[],[<<32,124,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<79,110,32,85,110,105,120,44,32,97,110,121,32,118,97,108,117,101,32,115,112,101,99,105,102,105,101,100,32,102,111,114,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,105,103,110,111,114,101,100,32,40,116,104,101,32,34,99,116,105,109,101,34,32,102,111,114,32,116,104,101,32,102,105,108,101,32,105,115,32,115,101,116,32,116,111,32,116,104,101,32,99,117,114,114,101,110,116,32,116,105,109,101,41,46,32,79,110,32,87,105,110,100,111,119,115,44,32,116,104,105,115,32,102,105,101,108,100,32,105,115,32,116,104,101,32,110,101,119,32,99,114,101,97,116,105,111,110,32,116,105,109,101,32,116,111,32,115,101,116,32,102,111,114,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<109,111,100,101,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,112,101,114,109,105,115,115,105,111,110,115,32,97,115,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,98,105,116,32,118,97,108,117,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<56,35,48,48,52,48,48>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,50,48,48>>]}]},{dd,[],[{p,[],[<<87,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,49,48,48>>]}]},{dd,[],[{p,[],[<<69,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,119,110,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,52,48>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,50,48>>]}]},{dd,[],[{p,[],[<<87,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,49,48>>]}]},{dd,[],[{p,[],[<<69,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,103,114,111,117,112>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,52>>]}]},{dd,[],[{p,[],[<<82,101,97,100,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,50>>]}]},{dd,[],[{p,[],[<<87,114,105,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<56,35,48,48,48,48,49>>]}]},{dd,[],[{p,[],[<<69,120,101,99,117,116,101,32,112,101,114,109,105,115,115,105,111,110,58,32,111,116,104,101,114>>]}]},{dt,[],[{code,[],[<<49,54,35,56,48,48>>]}]},{dd,[],[{p,[],[<<83,101,116,32,117,115,101,114,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]},{dt,[],[{code,[],[<<49,54,35,52,48,48>>]}]},{dd,[],[{p,[],[<<83,101,116,32,103,114,111,117,112,32,105,100,32,111,110,32,101,120,101,99,117,116,105,111,110>>]}]}]},{p,[],[<<79,110,32,85,110,105,120,32,112,108,97,116,102,111,114,109,115,44,32,111,116,104,101,114,32,98,105,116,115,32,116,104,97,110,32,116,104,111,115,101,32,108,105,115,116,101,100,32,97,98,111,118,101,32,109,97,121,32,98,101,32,115,101,116,46>>]}]},{dt,[],[{code,[],[<<117,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<73,110,100,105,99,97,116,101,115,32,116,104,101,32,102,105,108,101,32,111,119,110,101,114,46,32,73,103,110,111,114,101,100,32,102,111,114,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,46>>]}]},{dt,[],[{code,[],[<<103,105,100,32,61,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,116,104,101,32,103,114,111,117,112,32,116,104,97,116,32,116,104,101,32,102,105,108,101,32,111,119,110,101,114,32,98,101,108,111,110,103,115,32,116,111,46,32,73,103,110,111,114,101,100,32,102,111,114,32,110,111,110,45,85,110,105,120,32,102,105,108,101,32,115,121,115,116,101,109,115,46>>]}]}]},{p,[],[<<84,121,112,105,99,97,108,32,101,114,114,111,114,32,114,101,97,115,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<101,97,99,99,101,115>>]}]},{dd,[],[{p,[],[<<77,105,115,115,105,110,103,32,115,101,97,114,99,104,32,112,101,114,109,105,115,115,105,111,110,32,102,111,114,32,111,110,101,32,111,102,32,116,104,101,32,112,97,114,101,110,116,32,100,105,114,101,99,116,111,114,105,101,115,32,111,102,32,116,104,101,32,102,105,108,101,46>>]}]},{dt,[],[{code,[],[<<101,110,111,101,110,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,102,105,108,101,32,100,111,101,115,32,110,111,116,32,101,120,105,115,116,46>>]}]},{dt,[],[{code,[],[<<101,110,111,116,100,105,114>>]}]},{dd,[],[{p,[],[<<65,32,99,111,109,112,111,110,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,110,97,109,101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,114,121,46,32,79,110,32,115,111,109,101,32,112,108,97,116,102,111,114,109,115,44,32>>,{code,[],[<<101,110,111,101,110,116>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,105,110,115,116,101,97,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,107,101,114,110,101,108,47,100,111,99,47,115,114,99,47,102,105,108,101,46,120,109,108,35,76,50,48,51,52>>,signature => [{attribute,{372,2},spec,{{write_file_info,2},[{type,{372,22},bounded_fun,[{type,{372,22},'fun',[{type,{372,22},product,[{var,{372,23},'Filename'},{var,{372,33},'FileInfo'}]},{type,{372,46},union,[{atom,{372,46},ok},{type,{372,51},tuple,[{atom,{372,52},error},{var,{372,59},'Reason'}]}]}]},[{type,{373,7},constraint,[{atom,{373,7},is_subtype},[{var,{373,7},'Filename'},{user_type,{373,19},name_all,[]}]]},{type,{374,7},constraint,[{atom,{374,7},is_subtype},[{var,{374,7},'FileInfo'},{user_type,{374,19},file_info,[]}]]},{type,{375,7},constraint,[{atom,{375,7},is_subtype},[{var,{375,7},'Reason'},{type,{375,17},union,[{user_type,{375,17},posix,[]},{atom,{375,27},badarg}]}]]}]]}]}}],since => <<79,84,80,32,82,49,53,66>>}},{{type,deep_list,0},[{file,[102,105,108,101,46,101,114,108]},{location,101}],[<<45,116,121,112,101,32,100,101,101,112,95,108,105,115,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{101,2},type,{deep_list,{type,{101,22},list,[{type,{101,23},union,[{type,{101,23},char,[]},{type,{101,32},atom,[]},{user_type,{101,41},deep_list,[]}]}]},[]}}]}},{{type,fd,0},[{file,[102,105,108,101,46,101,114,108]},{location,87}],[<<102,100,40,41>>],#{<<101,110>> => [{p,[],[<<65,32,102,105,108,101,32,100,101,115,99,114,105,112,116,111,114,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32,102,105,108,101,32,111,112,101,110,101,100,32,105,110,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,114,97,119>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<114,97,119>>]}]},<<32,109,111,100,101,46>>]}]},#{signature => [{attribute,{87,2},type,{fd,{type,{87,22},record,[{atom,{87,23},file_descriptor}]},[]}}]}},{{type,filename,0},[{file,[102,105,108,101,46,101,114,108]},{location,84}],[<<45,116,121,112,101,32,102,105,108,101,110,97,109,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32,97,108,115,111,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<110,97,109,101,95,97,108,108,40,41>>]}]},<<32,116,121,112,101,46>>]}]},#{signature => [{attribute,{84,2},type,{filename,{type,{84,22},string,[]},[]}}]}},{{type,filename_all,0},[{file,[102,105,108,101,46,101,114,108]},{location,85}],[<<45,116,121,112,101,32,102,105,108,101,110,97,109,101,95,97,108,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<83,101,101,32,97,108,115,111,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<110,97,109,101,95,97,108,108,40,41>>]}]},<<32,116,121,112,101,46>>]}]},#{signature => [{attribute,{85,2},type,{filename_all,{type,{85,25},union,[{type,{85,25},string,[]},{type,{85,36},binary,[]}]},[]}}]}},{{type,io_device,0},[{file,[102,105,108,101,46,101,114,108]},{location,88}],[<<45,116,121,112,101,32,105,111,95,100,101,118,105,99,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,115,32,114,101,116,117,114,110,101,100,32,98,121,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,111,112,101,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<111,112,101,110,47,50>>]}]},<<59,32>>,{code,[],[<<112,105,100,40,41>>]},<<32,105,115,32,97,32,112,114,111,99,101,115,115,32,104,97,110,100,108,105,110,103,32,73,47,79,45,112,114,111,116,111,99,111,108,115,46>>]}]},#{signature => [{attribute,{88,2},type,{io_device,{type,{88,22},union,[{type,{88,22},pid,[]},{user_type,{88,30},fd,[]}]},[]}}]}},{{type,name,0},[{file,[102,105,108,101,46,101,114,108]},{location,102}],[<<45,116,121,112,101,32,110,97,109,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<73,102,32,86,77,32,105,115,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,44,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<32,97,110,100,32>>,{code,[],[<<99,104,97,114,40,41>>]},<<32,97,114,101,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,62,32,50,53,53,46,32,83,101,101,32,97,108,115,111,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32>>,{a,[{href,<<107,101,114,110,101,108,58,102,105,108,101,35,110,97,109,101,95,97,108,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,116,121,112,101>>}],[{code,[],[<<110,97,109,101,95,97,108,108,40,41>>]}]},<<32,116,121,112,101,46>>]}]},#{signature => [{attribute,{102,2},type,{name,{type,{102,22},union,[{type,{102,22},string,[]},{type,{102,33},atom,[]},{user_type,{102,42},deep_list,[]}]},[]}}]}},{{type,name_all,0},[{file,[102,105,108,101,46,101,114,108]},{location,103}],[<<45,116,121,112,101,32,110,97,109,101,95,97,108,108,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<73,102,32,86,77,32,105,115,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,44,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,97,108,108,111,119,101,100,32,116,111,32,98,101,32,62,32,50,53,53,46,32>>,{code,[],[<<82,97,119,70,105,108,101,110,97,109,101>>]},<<32,105,115,32,97,32,102,105,108,101,110,97,109,101,32,110,111,116,32,115,117,98,106,101,99,116,32,116,111,32,85,110,105,99,111,100,101,32,116,114,97,110,115,108,97,116,105,111,110,44,32,109,101,97,110,105,110,103,32,116,104,97,116,32,105,116,32,99,97,110,32,99,111,110,116,97,105,110,32,99,104,97,114,97,99,116,101,114,115,32,110,111,116,32,99,111,110,102,111,114,109,105,110,103,32,116,111,32,116,104,101,32,85,110,105,99,111,100,101,32,101,110,99,111,100,105,110,103,32,101,120,112,101,99,116,101,100,32,102,114,111,109,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,32,40,116,104,97,116,32,105,115,44,32,110,111,110,45,85,84,70,45,56,32,99,104,97,114,97,99,116,101,114,115,32,97,108,116,104,111,117,103,104,32,116,104,101,32,86,77,32,105,115,32,115,116,97,114,116,101,100,32,105,110,32,85,110,105,99,111,100,101,32,102,105,108,101,110,97,109,101,32,109,111,100,101,41,46,32,78,117,108,108,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,116,101,103,101,114,32,118,97,108,117,101,32,122,101,114,111,41,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,97,108,108,111,119,101,100,32,105,110,32,102,105,108,101,110,97,109,101,115,32,40,110,111,116,32,101,118,101,110,32,97,116,32,116,104,101,32,101,110,100,41,46>>]}]},#{signature => [{attribute,{103,2},type,{name_all,{type,{103,22},union,[{type,{103,22},string,[]},{type,{103,33},atom,[]},{user_type,{103,42},deep_list,[]},{ann_type,{103,57},[{var,{103,57},'RawFilename'},{type,{103,72},binary,[]}]}]},[]}}]}},{{type,posix,0},[{file,[102,105,108,101,46,101,114,108]},{location,104}],[<<45,116,121,112,101,32,112,111,115,105,120,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32,97,116,111,109,32,116,104,97,116,32,105,115,32,110,97,109,101,100,32,102,114,111,109,32,116,104,101,32,80,79,83,73,88,32,101,114,114,111,114,32,99,111,100,101,115,32,117,115,101,100,32,105,110,32,85,110,105,120,44,32,97,110,100,32,105,110,32,116,104,101,32,114,117,110,116,105,109,101,32,108,105,98,114,97,114,105,101,115,32,111,102,32,109,111,115,116,32,67,32,99,111,109,112,105,108,101,114,115,46>>]}]},#{signature => [{attribute,{104,2},type,{posix,{type,{105,9},union,[{atom,{105,9},eacces},{atom,{105,20},eagain},{atom,{106,9},ebadf},{atom,{106,19},ebadmsg},{atom,{106,31},ebusy},{atom,{107,9},edeadlk},{atom,{107,21},edeadlock},{atom,{107,35},edquot},{atom,{108,9},eexist},{atom,{109,9},efault},{atom,{109,20},efbig},{atom,{109,30},eftype},{atom,{110,9},eintr},{atom,{110,19},einval},{atom,{110,30},eio},{atom,{110,38},eisdir},{atom,{111,9},eloop},{atom,{112,9},emfile},{atom,{112,20},emlink},{atom,{112,31},emultihop},{atom,{113,9},enametoolong},{atom,{113,26},enfile},{atom,{114,9},enobufs},{atom,{114,21},enodev},{atom,{114,32},enolck},{atom,{114,43},enolink},{atom,{114,55},enoent},{atom,{115,9},enomem},{atom,{115,20},enospc},{atom,{115,31},enosr},{atom,{115,41},enostr},{atom,{115,52},enosys},{atom,{116,9},enotblk},{atom,{116,21},enotdir},{atom,{116,33},enotsup},{atom,{116,45},enxio},{atom,{117,9},eopnotsupp},{atom,{117,24},eoverflow},{atom,{118,9},eperm},{atom,{118,19},epipe},{atom,{119,9},erange},{atom,{119,20},erofs},{atom,{120,9},espipe},{atom,{120,21},esrch},{atom,{120,32},estale},{atom,{121,9},etxtbsy},{atom,{122,9},exdev}]},[]}}]}},{{type,date_time,0},[{file,[102,105,108,101,46,101,114,108]},{location,123}],[<<45,116,121,112,101,32,100,97,116,101,95,116,105,109,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<77,117,115,116,32,100,101,110,111,116,101,32,97,32,118,97,108,105,100,32,100,97,116,101,32,97,110,100,32,116,105,109,101,46>>]}]},#{signature => [{attribute,{123,2},type,{date_time,{remote_type,{123,22},[{atom,{123,22},calendar},{atom,{123,31},datetime},[]]},[]}}]}},{{type,file_info,0},[{file,[102,105,108,101,46,101,114,108]},{location,86}],[<<45,116,121,112,101,32,102,105,108,101,95,105,110,102,111,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{86,2},type,{file_info,{type,{86,22},record,[{atom,{86,23},file_info}]},[]}}]}},{{type,location,0},[{file,[102,105,108,101,46,101,114,108]},{location,89}],[<<45,116,121,112,101,32,108,111,99,97,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{89,2},type,{location,{type,{89,22},union,[{type,{89,22},integer,[]},{type,{89,34},tuple,[{atom,{89,35},bof},{ann_type,{89,42},[{var,{89,42},'Offset'},{type,{89,52},integer,[]}]}]},{type,{90,22},tuple,[{atom,{90,23},cur},{ann_type,{90,30},[{var,{90,30},'Offset'},{type,{90,40},integer,[]}]}]},{type,{91,8},tuple,[{atom,{91,9},eof},{ann_type,{91,16},[{var,{91,16},'Offset'},{type,{91,26},integer,[]}]}]},{atom,{91,39},bof},{atom,{91,47},cur},{atom,{91,55},eof}]},[]}}]}},{{type,mode,0},[{file,[102,105,108,101,46,101,114,108]},{location,92}],[<<45,116,121,112,101,32,109,111,100,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{92,2},type,{mode,{type,{92,22},union,[{atom,{92,22},read},{atom,{92,31},write},{atom,{92,41},append},{atom,{93,22},exclusive},{atom,{93,36},raw},{atom,{93,44},binary},{type,{94,8},tuple,[{atom,{94,9},delayed_write},{ann_type,{95,23},[{var,{95,23},'Size'},{type,{95,31},non_neg_integer,[]}]},{ann_type,{96,23},[{var,{96,23},'Delay'},{type,{96,32},non_neg_integer,[]}]}]},{atom,{97,8},delayed_write},{type,{97,26},tuple,[{atom,{97,27},read_ahead},{ann_type,{97,41},[{var,{97,41},'Size'},{type,{97,49},pos_integer,[]}]}]},{atom,{98,8},read_ahead},{atom,{98,23},compressed},{type,{99,8},tuple,[{atom,{99,9},encoding},{remote_type,{99,21},[{atom,{99,21},unicode},{atom,{99,29},encoding},[]]}]},{atom,{100,8},sync}]},[]}}]}},{{type,file_info_option,0},[{file,[102,105,108,101,46,101,114,108]},{location,129}],[<<45,116,121,112,101,32,102,105,108,101,95,105,110,102,111,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{129,2},type,{file_info_option,{type,{129,29},union,[{type,{129,29},tuple,[{atom,{129,30},time},{atom,{129,38},local}]},{type,{129,49},tuple,[{atom,{129,50},time},{atom,{129,58},universal}]},{type,{130,8},tuple,[{atom,{130,9},time},{atom,{130,17},posix}]},{atom,{130,28},raw}]},[]}}]}}]}. \ No newline at end of file
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_altname_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_altname_1_func.txt
new file mode 100644
index 0000000000..7082445a78
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_altname_1_func.txt
@@ -0,0 +1,5 @@
+
+  altname/1
+
+ The documentation for altname/1 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_copy_opened_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_copy_opened_3_func.txt
new file mode 100644
index 0000000000..142c86eff4
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_copy_opened_3_func.txt
@@ -0,0 +1,6 @@
+
+  copy_opened/3
+
+ The documentation for copy_opened/3 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_1_func.txt
index 88be4438f6..5b66b4ba67 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_1_func.txt
@@ -2,6 +2,9 @@
-spec delete(Filename) -> ok | {error, Reason}
 when Filename :: name_all(), Reason :: posix() | badarg.
+Since:
+ OTP 24.0
+
Types:
-type delete_option() :: raw.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_2_func.txt
index 53c3185027..d8cc8befc7 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_delete_2_func.txt
@@ -5,6 +5,9 @@
 Opts :: [delete_option()],
 Reason :: posix() | badarg.
+Since:
+ OTP 24.0
+
Types:
-type delete_option() :: raw.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_3_func.txt
new file mode 100644
index 0000000000..85a88fa38f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_3_func.txt
@@ -0,0 +1,6 @@
+
+  ipread_s32bu_p32bu/3
+
+ The documentation for ipread_s32bu_p32bu/3 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_int_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_int_3_func.txt
new file mode 100644
index 0000000000..de346114dd
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_ipread_s32bu_p32bu_int_3_func.txt
@@ -0,0 +1,6 @@
+
+  ipread_s32bu_p32bu_int/3
+
+ The documentation for ipread_s32bu_p32bu_int/3 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_open_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_open_2_func.txt
index 24ca2b24d6..b89e725d7b 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_open_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_open_2_func.txt
@@ -217,6 +217,15 @@
returned from this call can be used as an argument to the I/O
functions (see io(3)).
+ Warning:
+ While this function can be used to open any file, we recommend
+ against using it for NFS-mounted files, FIFOs, devices, or
+ similar since they can cause IO threads to hang forever.
+
+ If your application needs to interact with these kinds of
+ files we recommend breaking out those parts to a port program
+ instead.
+
Note:
In previous versions of file, modes were specified as one of
the atoms read, write, or read_write instead of a list.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_path_eval_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_path_eval_3_func.txt
new file mode 100644
index 0000000000..828e8cf9f8
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_path_eval_3_func.txt
@@ -0,0 +1,5 @@
+
+  path_eval/3
+
+ The documentation for path_eval/3 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_read_file_info_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_read_file_info_1_func.txt
new file mode 100644
index 0000000000..88576426f9
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_read_file_info_1_func.txt
@@ -0,0 +1,6 @@
+
+  raw_read_file_info/1
+
+ The documentation for raw_read_file_info/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_write_file_info_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_write_file_info_2_func.txt
new file mode 100644
index 0000000000..5b9650666c
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_raw_write_file_info_2_func.txt
@@ -0,0 +1,6 @@
+
+  raw_write_file_info/2
+
+ The documentation for raw_write_file_info/2 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_1_func.txt
index d997bdf4f1..c5d25d6581 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_1_func.txt
@@ -50,8 +50,9 @@
size = integer() >= 0:
Size of file in bytes.
- type = device | directory | other | regular | symlink:
- The type of the file.
+ type = device | directory | other | regular:
+ The type of the file. Can also contain symlink when returned
+ from read_link_info/1,2.
access = read | write | read_write | none:
The current system access to the file.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_2_func.txt
index c8ad4f7215..53a644dea1 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_read_file_info_2_func.txt
@@ -51,8 +51,9 @@
size = integer() >= 0:
Size of file in bytes.
- type = device | directory | other | regular | symlink:
- The type of the file.
+ type = device | directory | other | regular:
+ The type of the file. Can also contain symlink when returned
+ from read_link_info/1,2.
access = read | write | read_write | none:
The current system access to the file.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_2_func.txt
index d22adad04f..0ccfaf7e01 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_2_func.txt
@@ -2,7 +2,13 @@
-spec sendfile(Filename, Socket) ->
 {ok, non_neg_integer()} |
 {error, inet:posix() | closed | badarg | not_owner}
-  when Filename :: name_all(), Socket :: inet:socket().
+  when
+  Filename :: name_all(),
+  Socket ::
+  inet:socket() |
+  socket:socket() |
+  fun((iolist()) ->
+  ok | {error, inet:posix() | closed}).
Since:
OTP R15B
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_5_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_5_func.txt
index ae2cc29578..991f012cb5 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_5_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_file_sendfile_5_func.txt
@@ -4,7 +4,11 @@
 {error, inet:posix() | closed | badarg | not_owner}
 when
 RawFile :: fd(),
-  Socket :: inet:socket(),
+  Socket ::
+  inet:socket() |
+  socket:socket() |
+  fun((iolist()) ->
+  ok | {error, inet:posix() | closed}),
 Offset :: non_neg_integer(),
 Bytes :: non_neg_integer(),
 Opts :: [sendfile_option()].
@@ -23,7 +27,8 @@
The file used must be opened using the raw flag, and the process
calling sendfile must be the controlling process of the socket.
- See gen_tcp:controlling_process/2.
+ See gen_tcp:controlling_process/2 or module socket's level 
+ otp socket option controlling_process.
If the OS used does not support non-blocking sendfile, an Erlang
fallback using read/2 and gen_tcp:send/2 is used.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv.txt
new file mode 100644
index 0000000000..2392dee3c3
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv.txt
@@ -0,0 +1,5 @@
+
+ user_drv
+
+ The documentation for user_drv is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_cb.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_cb.txt
new file mode 100644
index 0000000000..d6ddedfc1a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_cb.txt
@@ -0,0 +1,3 @@
+ user_drv
+
+There are no callbacks in this module
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_interfaces_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_interfaces_1_func.txt
new file mode 100644
index 0000000000..f693b67617
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_interfaces_1_func.txt
@@ -0,0 +1,6 @@
+
+  interfaces/1
+
+ The documentation for interfaces/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_2_func.txt
new file mode 100644
index 0000000000..a9c626e643
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_2_func.txt
@@ -0,0 +1,5 @@
+
+  server/2
+
+ The documentation for server/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_3_func.txt
new file mode 100644
index 0000000000..372628b879
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_server_3_func.txt
@@ -0,0 +1,5 @@
+
+  server/3
+
+ The documentation for server/3 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_0_func.txt
new file mode 100644
index 0000000000..7b93442257
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_0_func.txt
@@ -0,0 +1,5 @@
+
+  start/0
+
+ The documentation for start/0 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_1_func.txt
new file mode 100644
index 0000000000..123e70566a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_1_func.txt
@@ -0,0 +1,5 @@
+
+  start/1
+
+ The documentation for start/1 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_2_func.txt
new file mode 100644
index 0000000000..cb801a2351
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_2_func.txt
@@ -0,0 +1,5 @@
+
+  start/2
+
+ The documentation for start/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_3_func.txt
new file mode 100644
index 0000000000..91d7dae25a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_start_3_func.txt
@@ -0,0 +1,5 @@
+
+  start/3
+
+ The documentation for start/3 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_type.txt
new file mode 100644
index 0000000000..5d7d0ce012
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/kernel_user_drv_type.txt
@@ -0,0 +1,3 @@
+ user_drv
+
+There are no types in this module
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/re.docs_v1 b/lib/stdlib/test/shell_docs_SUITE_data/re.docs_v1
index 3d2107fdcf..b4a7ae3e4d 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/re.docs_v1
+++ b/lib/stdlib/test/shell_docs_SUITE_data/re.docs_v1
@@ -1 +1 @@
-{docs_v1,[{file,[114,101,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<84,104,105,115,32,109,111,100,117,108,101,32,99,111,110,116,97,105,110,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,32,102,111,114,32,115,116,114,105,110,103,115,32,97,110,100,32,98,105,110,97,114,105,101,115,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,101,103,101,120,112,95,115,121,110,116,97,120>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110>>]},<<32,115,121,110,116,97,120,32,97,110,100,32,115,101,109,97,110,116,105,99,115,32,114,101,115,101,109,98,108,101,32,116,104,97,116,32,111,102,32,80,101,114,108,46>>]},{p,[],[<<84,104,101,32,109,97,116,99,104,105,110,103,32,97,108,103,111,114,105,116,104,109,115,32,111,102,32,116,104,101,32,108,105,98,114,97,114,121,32,97,114,101,32,98,97,115,101,100,32,111,110,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,44,32,98,117,116,32,110,111,116,32,97,108,108,32,111,102,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,32,105,115,32,105,110,116,101,114,102,97,99,101,100,32,97,110,100,32,115,111,109,101,32,112,97,114,116,115,32,111,102,32,116,104,101,32,108,105,98,114,97,114,121,32,103,111,32,98,101,121,111,110,100,32,119,104,97,116,32,80,67,82,69,32,111,102,102,101,114,115,46,32,67,117,114,114,101,110,116,108,121,32,80,67,82,69,32,118,101,114,115,105,111,110,32,56,46,52,48,32,40,114,101,108,101,97,115,101,32,100,97,116,101,32,50,48,49,55,45,48,49,45,49,49,41,32,105,115,32,117,115,101,100,46,32,84,104,101,32,115,101,99,116,105,111,110,115,32,111,102,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,116,104,97,116,32,97,114,101,32,114,101,108,101,118,97,110,116,32,116,111,32,116,104,105,115,32,109,111,100,117,108,101,32,97,114,101,32,105,110,99,108,117,100,101,100,32,104,101,114,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,108,105,116,101,114,97,108,32,115,121,110,116,97,120,32,102,111,114,32,115,116,114,105,110,103,115,32,117,115,101,115,32,116,104,101,32,34,92,34,32,40,98,97,99,107,115,108,97,115,104,41,32,99,104,97,114,97,99,116,101,114,32,97,115,32,97,110,32,101,115,99,97,112,101,32,99,111,100,101,46,32,89,111,117,32,110,101,101,100,32,116,111,32,101,115,99,97,112,101,32,98,97,99,107,115,108,97,115,104,101,115,32,105,110,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,115,44,32,98,111,116,104,32,105,110,32,121,111,117,114,32,99,111,100,101,32,97,110,100,32,105,110,32,116,104,101,32,115,104,101,108,108,44,32,119,105,116,104,32,97,110,32,101,120,116,114,97,32,98,97,99,107,115,108,97,115,104,44,32,116,104,97,116,32,105,115,44,32,34,92,92,34,46>>]}]},{a,[{id,<<114,101,103,101,120,112,95,115,121,110,116,97,120>>}],[]},{h2,[],[<<80,101,114,108,45,76,105,107,101,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,32,83,121,110,116,97,120>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,32,99,111,110,116,97,105,110,32,114,101,102,101,114,101,110,99,101,32,109,97,116,101,114,105,97,108,32,102,111,114,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,117,115,101,100,32,98,121,32,116,104,105,115,32,109,111,100,117,108,101,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,44,32,119,105,116,104,32,99,104,97,110,103,101,115,32,119,104,101,114,101,32,116,104,105,115,32,109,111,100,117,108,101,32,98,101,104,97,118,101,115,32,100,105,102,102,101,114,101,110,116,108,121,32,116,111,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,46>>]},{a,[{id,<<114,101,103,101,120,112,95,115,121,110,116,97,120,95,100,101,116,97,105,108,115>>}],[]},{h2,[],[<<80,67,82,69,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,32,68,101,116,97,105,108,115>>]},{p,[],[<<84,104,101,32,115,121,110,116,97,120,32,97,110,100,32,115,101,109,97,110,116,105,99,115,32,111,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,67,82,69,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,100,101,116,97,105,108,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,46,32,80,101,114,108,39,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,105,116,115,32,111,119,110,32,100,111,99,117,109,101,110,116,97,116,105,111,110,44,32,97,110,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,103,101,110,101,114,97,108,32,97,114,101,32,99,111,118,101,114,101,100,32,105,110,32,109,97,110,121,32,98,111,111,107,115,44,32,115,111,109,101,32,119,105,116,104,32,99,111,112,105,111,117,115,32,101,120,97,109,112,108,101,115,46,32,74,101,102,102,114,101,121,32,70,114,105,101,100,108,39,115,32,34,77,97,115,116,101,114,105,110,103,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,115,34,44,32,112,117,98,108,105,115,104,101,100,32,98,121,32,79,39,82,101,105,108,108,121,44,32,99,111,118,101,114,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,103,114,101,97,116,32,100,101,116,97,105,108,46,32,84,104,105,115,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,80,67,82,69,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,105,110,116,101,110,100,101,100,32,97,115,32,114,101,102,101,114,101,110,99,101,32,109,97,116,101,114,105,97,108,46>>]},{p,[],[<<84,104,101,32,114,101,102,101,114,101,110,99,101,32,109,97,116,101,114,105,97,108,32,105,115,32,100,105,118,105,100,101,100,32,105,110,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,112,101,99,105,97,108,32,83,116,97,114,116,45,111,102,45,80,97,116,116,101,114,110,32,73,116,101,109,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,104,97,114,97,99,116,101,114,115,32,97,110,100,32,77,101,116,97,99,104,97,114,97,99,116,101,114,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<66,97,99,107,115,108,97,115,104>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,105,114,99,117,109,102,108,101,120,32,97,110,100,32,68,111,108,108,97,114>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<70,117,108,108,32,83,116,111,112,32,40,80,101,114,105,111,100,44,32,68,111,116,41,32,97,110,100,32,92,78>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,54>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<77,97,116,99,104,105,110,103,32,97,32,83,105,110,103,108,101,32,68,97,116,97,32,85,110,105,116>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,55>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,113,117,97,114,101,32,66,114,97,99,107,101,116,115,32,97,110,100,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,56>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,111,115,105,120,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,57>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<86,101,114,116,105,99,97,108,32,66,97,114>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<73,110,116,101,114,110,97,108,32,79,112,116,105,111,110,32,83,101,116,116,105,110,103>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,97,109,101,100,32,83,117,98,112,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<82,101,112,101,116,105,116,105,111,110>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<65,116,111,109,105,99,32,71,114,111,117,112,105,110,103,32,97,110,100,32,80,111,115,115,101,115,115,105,118,101,32,81,117,97,110,116,105,102,105,101,114,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,54>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,55>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<65,115,115,101,114,116,105,111,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,56>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,111,110,100,105,116,105,111,110,97,108,32,83,117,98,112,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,57>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,111,109,109,101,110,116,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<82,101,99,117,114,115,105,118,101,32,80,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115,32,97,115,32,83,117,98,114,111,117,116,105,110,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<79,110,105,103,117,114,117,109,97,32,83,117,98,114,111,117,116,105,110,101,32,83,121,110,116,97,120>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,67,111,110,116,114,111,108>>]}]}]},{a,[{id,<<115,101,99,116,49>>}],[]},{h2,[],[<<83,112,101,99,105,97,108,32,83,116,97,114,116,45,111,102,45,80,97,116,116,101,114,110,32,73,116,101,109,115>>]},{p,[],[<<83,111,109,101,32,111,112,116,105,111,110,115,32,116,104,97,116,32,99,97,110,32,98,101,32,112,97,115,115,101,100,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,115,112,101,99,105,97,108,32,105,116,101,109,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,46,32,84,104,101,115,101,32,97,114,101,32,110,111,116,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,44,32,98,117,116,32,97,114,101,32,112,114,111,118,105,100,101,100,32,116,111,32,109,97,107,101,32,116,104,101,115,101,32,111,112,116,105,111,110,115,32,97,99,99,101,115,115,105,98,108,101,32,116,111,32,112,97,116,116,101,114,110,32,119,114,105,116,101,114,115,32,119,104,111,32,97,114,101,32,110,111,116,32,97,98,108,101,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,112,114,111,103,114,97,109,32,116,104,97,116,32,112,114,111,99,101,115,115,101,115,32,116,104,101,32,112,97,116,116,101,114,110,46,32,65,110,121,32,110,117,109,98,101,114,32,111,102,32,116,104,101,115,101,32,105,116,101,109,115,32,99,97,110,32,97,112,112,101,97,114,44,32,98,117,116,32,116,104,101,121,32,109,117,115,116,32,97,108,108,32,98,101,32,116,111,103,101,116,104,101,114,32,114,105,103,104,116,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,115,116,114,105,110,103,44,32,97,110,100,32,116,104,101,32,108,101,116,116,101,114,115,32,109,117,115,116,32,98,101,32,105,110,32,117,112,112,101,114,32,99,97,115,101,46>>]},{p,[],[{em,[],[<<85,84,70,32,83,117,112,112,111,114,116>>]}]},{p,[],[<<85,110,105,99,111,100,101,32,115,117,112,112,111,114,116,32,105,115,32,98,97,115,105,99,97,108,108,121,32,85,84,70,45,56,32,98,97,115,101,100,46,32,84,111,32,117,115,101,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,44,32,121,111,117,32,101,105,116,104,101,114,32,99,97,108,108,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,111,114,32,116,104,101,32,112,97,116,116,101,114,110,32,109,117,115,116,32,115,116,97,114,116,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,115,101,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,115,58>>]},{pre,[],[{code,[],[<<40,42,85,84,70,56,41,10,40,42,85,84,70,41>>]}]},{p,[],[<<66,111,116,104,32,111,112,116,105,111,110,115,32,103,105,118,101,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,44,32,116,104,101,32,105,110,112,117,116,32,115,116,114,105,110,103,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,85,84,70,45,56,46,32,78,111,116,105,99,101,32,116,104,97,116,32,119,105,116,104,32,116,104,101,115,101,32,105,110,115,116,114,117,99,116,105,111,110,115,44,32,116,104,101,32,97,117,116,111,109,97,116,105,99,32,99,111,110,118,101,114,115,105,111,110,32,111,102,32,108,105,115,116,115,32,116,111,32,85,84,70,45,56,32,105,115,32,110,111,116,32,112,101,114,102,111,114,109,101,100,32,98,121,32,116,104,101,32>>,{code,[],[<<114,101>>]},<<32,102,117,110,99,116,105,111,110,115,46,32,84,104,101,114,101,102,111,114,101,44,32,117,115,105,110,103,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,105,115,32,110,111,116,32,114,101,99,111,109,109,101,110,100,101,100,46,32,65,100,100,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,119,104,101,110,32,114,117,110,110,105,110,103,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<83,111,109,101,32,97,112,112,108,105,99,97,116,105,111,110,115,32,116,104,97,116,32,97,108,108,111,119,32,116,104,101,105,114,32,117,115,101,114,115,32,116,111,32,115,117,112,112,108,121,32,112,97,116,116,101,114,110,115,32,99,97,110,32,119,105,115,104,32,116,111,32,114,101,115,116,114,105,99,116,32,116,104,101,109,32,116,111,32,110,111,110,45,85,84,70,32,100,97,116,97,32,102,111,114,32,115,101,99,117,114,105,116,121,32,114,101,97,115,111,110,115,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<110,101,118,101,114,95,117,116,102>>]},<<32,105,115,32,115,101,116,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,44,32,40,42,85,84,70,41,44,32,97,110,100,32,115,111,32,111,110,44,32,97,114,101,32,110,111,116,32,97,108,108,111,119,101,100,44,32,97,110,100,32,116,104,101,105,114,32,97,112,112,101,97,114,97,110,99,101,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,46>>]},{p,[],[{em,[],[<<85,110,105,99,111,100,101,32,80,114,111,112,101,114,116,121,32,83,117,112,112,111,114,116>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,97,110,111,116,104,101,114,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,32,116,104,97,116,32,99,97,110,32,97,112,112,101,97,114,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,42,85,67,80,41>>]}]},{p,[],[<<84,104,105,115,32,104,97,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<58,32,105,116,32,99,97,117,115,101,115,32,115,101,113,117,101,110,99,101,115,32,115,117,99,104,32,97,115,32,92,100,32,97,110,100,32,92,119,32,116,111,32,117,115,101,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,116,111,32,100,101,116,101,114,109,105,110,101,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,44,32,105,110,115,116,101,97,100,32,111,102,32,114,101,99,111,103,110,105,122,105,110,103,32,111,110,108,121,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,99,111,100,101,115,32,60,32,50,53,54,32,116,104,114,111,117,103,104,32,97,32,108,111,111,107,117,112,32,116,97,98,108,101,46>>]},{p,[],[{em,[],[<<68,105,115,97,98,108,105,110,103,32,83,116,97,114,116,117,112,32,79,112,116,105,109,105,122,97,116,105,111,110,115>>]}]},{p,[],[<<73,102,32,97,32,112,97,116,116,101,114,110,32,115,116,97,114,116,115,32,119,105,116,104,32>>,{code,[],[<<40,42,78,79,95,83,84,65,82,84,95,79,80,84,41>>]},<<44,32,105,116,32,104,97,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]},<<32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46>>]},{p,[],[{em,[],[<<78,101,119,108,105,110,101,32,67,111,110,118,101,110,116,105,111,110,115>>]}]},{a,[{id,<<110,101,119,108,105,110,101,95,99,111,110,118,101,110,116,105,111,110,115>>}],[]},{p,[],[<<80,67,82,69,32,115,117,112,112,111,114,116,115,32,102,105,118,101,32,99,111,110,118,101,110,116,105,111,110,115,32,102,111,114,32,105,110,100,105,99,97,116,105,110,103,32,108,105,110,101,32,98,114,101,97,107,115,32,105,110,32,115,116,114,105,110,103,115,58,32,97,32,115,105,110,103,108,101,32,67,82,32,40,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,41,32,99,104,97,114,97,99,116,101,114,44,32,97,32,115,105,110,103,108,101,32,76,70,32,40,108,105,110,101,32,102,101,101,100,41,32,99,104,97,114,97,99,116,101,114,44,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,44,32,97,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,112,114,101,99,101,100,105,110,103,44,32,97,110,100,32,97,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,46>>]},{p,[],[<<65,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,32,99,97,110,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,115,116,97,114,116,105,110,103,32,97,32,112,97,116,116,101,114,110,32,115,116,114,105,110,103,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,118,101,32,115,101,113,117,101,110,99,101,115,58>>]},{dl,[],[{dt,[],[<<40,42,67,82,41>>]},{dd,[],[<<67,97,114,114,105,97,103,101,32,114,101,116,117,114,110>>]},{dt,[],[<<40,42,76,70,41>>]},{dd,[],[<<76,105,110,101,32,102,101,101,100>>]},{dt,[],[<<40,42,67,82,76,70,41>>]},{dd,[],[<<62,67,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,102,111,108,108,111,119,101,100,32,98,121,32,108,105,110,101,32,102,101,101,100>>]},{dt,[],[<<40,42,65,78,89,67,82,76,70,41>>]},{dd,[],[<<65,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,97,98,111,118,101>>]},{dt,[],[<<40,42,65,78,89,41>>]},{dd,[],[<<65,108,108,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,115>>]}]},{p,[],[<<84,104,101,115,101,32,111,118,101,114,114,105,100,101,32,116,104,101,32,100,101,102,97,117,108,116,32,97,110,100,32,116,104,101,32,111,112,116,105,111,110,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,99,104,97,110,103,101,115,32,116,104,101,32,99,111,110,118,101,110,116,105,111,110,32,116,111,32,67,82,58>>]},{pre,[],[{code,[],[<<40,42,67,82,41,97,46,98>>]}]},{p,[],[<<84,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32>>,{code,[],[<<97,92,110,98>>]},<<44,32,97,115,32,76,70,32,105,115,32,110,111,32,108,111,110,103,101,114,32,97,32,110,101,119,108,105,110,101,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,111,102,32,116,104,101,109,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,32,108,97,115,116,32,111,110,101,32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,32,97,102,102,101,99,116,115,32,119,104,101,114,101,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,32,116,114,117,101,46,32,73,116,32,97,108,115,111,32,97,102,102,101,99,116,115,32,116,104,101,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,111,102,32,116,104,101,32,100,111,116,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,119,104,101,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,105,115,32,110,111,116,32,115,101,116,44,32,97,110,100,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,92,78,46,32,72,111,119,101,118,101,114,44,32,105,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,119,104,97,116,32,116,104,101,32,92,82,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,109,97,116,99,104,101,115,46,32,66,121,32,100,101,102,97,117,108,116,44,32,116,104,105,115,32,105,115,32,97,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,44,32,102,111,114,32,80,101,114,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,59,32,115,101,101,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,92,82,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,101,119,108,105,110,101,95,115,101,113,117,101,110,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,101,119,108,105,110,101,32,83,101,113,117,101,110,99,101,115>>]},<<46,32,65,32,99,104,97,110,103,101,32,111,102,32,116,104,101,32,92,82,32,115,101,116,116,105,110,103,32,99,97,110,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,97,32,99,104,97,110,103,101,32,111,102,32,116,104,101,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,46>>]},{p,[],[{em,[],[<<83,101,116,116,105,110,103,32,77,97,116,99,104,32,97,110,100,32,82,101,99,117,114,115,105,111,110,32,76,105,109,105,116,115>>]}]},{p,[],[<<84,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,99,97,110,32,115,101,116,32,97,32,108,105,109,105,116,32,111,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,116,104,101,32,105,110,116,101,114,110,97,108,32,109,97,116,99,104,40,41,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,97,110,100,32,111,110,32,116,104,101,32,109,97,120,105,109,117,109,32,100,101,112,116,104,32,111,102,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,115,46,32,84,104,101,115,101,32,102,97,99,105,108,105,116,105,101,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,116,111,32,99,97,116,99,104,32,114,117,110,97,119,97,121,32,109,97,116,99,104,101,115,32,116,104,97,116,32,97,114,101,32,112,114,111,118,111,107,101,100,32,98,121,32,112,97,116,116,101,114,110,115,32,119,105,116,104,32,104,117,103,101,32,109,97,116,99,104,105,110,103,32,116,114,101,101,115,32,40,97,32,116,121,112,105,99,97,108,32,101,120,97,109,112,108,101,32,105,115,32,97,32,112,97,116,116,101,114,110,32,119,105,116,104,32,110,101,115,116,101,100,32,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,115,41,32,97,110,100,32,116,111,32,97,118,111,105,100,32,114,117,110,110,105,110,103,32,111,117,116,32,111,102,32,115,121,115,116,101,109,32,115,116,97,99,107,32,98,121,32,116,111,111,32,109,117,99,104,32,114,101,99,117,114,115,105,111,110,46,32,87,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,108,105,109,105,116,115,32,105,115,32,114,101,97,99,104,101,100,44,32>>,{code,[],[<<112,99,114,101,95,101,120,101,99,40,41>>]},<<32,103,105,118,101,115,32,97,110,32,101,114,114,111,114,32,114,101,116,117,114,110,46,32,84,104,101,32,108,105,109,105,116,115,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,105,116,101,109,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{pre,[],[{code,[],[<<40,42,76,73,77,73,84,95,77,65,84,67,72,61,100,41,10,40,42,76,73,77,73,84,95,82,69,67,85,82,83,73,79,78,61,100,41>>]}]},{p,[],[<<72,101,114,101,32,100,32,105,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,100,101,99,105,109,97,108,32,100,105,103,105,116,115,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,115,101,116,116,105,110,103,32,109,117,115,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,116,104,101,32,118,97,108,117,101,32,115,101,116,32,98,121,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,102,111,114,32,105,116,32,116,111,32,104,97,118,101,32,97,110,121,32,101,102,102,101,99,116,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,112,97,116,116,101,114,110,32,119,114,105,116,101,114,32,99,97,110,32,108,111,119,101,114,32,116,104,101,32,108,105,109,105,116,32,115,101,116,32,98,121,32,116,104,101,32,112,114,111,103,114,97,109,109,101,114,44,32,98,117,116,32,110,111,116,32,114,97,105,115,101,32,105,116,46,32,73,102,32,116,104,101,114,101,32,105,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,101,116,116,105,110,103,32,111,102,32,111,110,101,32,111,102,32,116,104,101,115,101,32,108,105,109,105,116,115,44,32,116,104,101,32,108,111,119,101,114,32,118,97,108,117,101,32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,102,111,114,32,98,111,116,104,32,116,104,101,32,108,105,109,105,116,115,32,105,115,32,49,48,44,48,48,48,44,48,48,48,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,86,77,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,108,105,109,105,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,115,116,97,99,107,32,100,101,112,116,104,32,111,102,32,116,104,101,32,86,77,44,32,97,115,32,80,67,82,69,32,102,111,114,32,69,114,108,97,110,103,32,105,115,32,99,111,109,112,105,108,101,100,32,105,110,32,115,117,99,104,32,97,32,119,97,121,32,116,104,97,116,32,116,104,101,32,109,97,116,99,104,32,102,117,110,99,116,105,111,110,32,110,101,118,101,114,32,100,111,101,115,32,114,101,99,117,114,115,105,111,110,32,111,110,32,116,104,101,32,67,32,115,116,97,99,107,46>>]},{p,[],[<<78,111,116,101,32,116,104,97,116,32>>,{code,[],[<<76,73,77,73,84,95,77,65,84,67,72>>]},<<32,97,110,100,32>>,{code,[],[<<76,73,77,73,84,95,82,69,67,85,82,83,73,79,78>>]},<<32,99,97,110,32,111,110,108,121,32,114,101,100,117,99,101,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,108,105,109,105,116,115,32,115,101,116,32,98,121,32,116,104,101,32,99,97,108,108,101,114,44,32,110,111,116,32,105,110,99,114,101,97,115,101,32,116,104,101,109,46>>]},{a,[{id,<<115,101,99,116,50>>}],[]},{h2,[],[<<67,104,97,114,97,99,116,101,114,115,32,97,110,100,32,77,101,116,97,99,104,97,114,97,99,116,101,114,115>>]},{p,[],[<<65,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,97,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,46,32,77,111,115,116,32,99,104,97,114,97,99,116,101,114,115,32,115,116,97,110,100,32,102,111,114,32,116,104,101,109,115,101,108,118,101,115,32,105,110,32,97,32,112,97,116,116,101,114,110,32,97,110,100,32,109,97,116,99,104,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,65,115,32,97,32,116,114,105,118,105,97,108,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,32,112,111,114,116,105,111,110,32,111,102,32,97,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,116,104,97,116,32,105,115,32,105,100,101,110,116,105,99,97,108,32,116,111,32,105,116,115,101,108,102,58>>]},{pre,[],[{code,[],[<<84,104,101,32,113,117,105,99,107,32,98,114,111,119,110,32,102,111,120>>]}]},{p,[],[<<87,104,101,110,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,115,112,101,99,105,102,105,101,100,32,40,111,112,116,105,111,110,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<41,44,32,108,101,116,116,101,114,115,32,97,114,101,32,109,97,116,99,104,101,100,32,105,110,100,101,112,101,110,100,101,110,116,108,121,32,111,102,32,99,97,115,101,46>>]},{p,[],[<<84,104,101,32,112,111,119,101,114,32,111,102,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,99,111,109,101,115,32,102,114,111,109,32,116,104,101,32,97,98,105,108,105,116,121,32,116,111,32,105,110,99,108,117,100,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,110,100,32,114,101,112,101,116,105,116,105,111,110,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,101,115,101,32,97,114,101,32,101,110,99,111,100,101,100,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,98,121,32,116,104,101,32,117,115,101,32,111,102,32>>,{em,[],[<<109,101,116,97,99,104,97,114,97,99,116,101,114,115>>]},<<44,32,119,104,105,99,104,32,100,111,32,110,111,116,32,115,116,97,110,100,32,102,111,114,32,116,104,101,109,115,101,108,118,101,115,32,98,117,116,32,105,110,115,116,101,97,100,32,97,114,101,32,105,110,116,101,114,112,114,101,116,101,100,32,105,110,32,115,111,109,101,32,115,112,101,99,105,97,108,32,119,97,121,46>>]},{p,[],[<<84,119,111,32,115,101,116,115,32,111,102,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,101,120,105,115,116,58,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,97,110,121,119,104,101,114,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,101,120,99,101,112,116,32,119,105,116,104,105,110,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,44,32,97,110,100,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,119,105,116,104,105,110,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,46,32,79,117,116,115,105,100,101,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,44,32,116,104,101,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<92>>]},{dd,[],[<<71,101,110,101,114,97,108,32,101,115,99,97,112,101,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,109,97,110,121,32,117,115,101,115>>]},{dt,[],[<<94>>]},{dd,[],[<<65,115,115,101,114,116,32,115,116,97,114,116,32,111,102,32,115,116,114,105,110,103,32,40,111,114,32,108,105,110,101,44,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,41>>]},{dt,[],[<<36>>]},{dd,[],[<<65,115,115,101,114,116,32,101,110,100,32,111,102,32,115,116,114,105,110,103,32,40,111,114,32,108,105,110,101,44,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,41>>]},{dt,[],[<<46>>]},{dd,[],[<<77,97,116,99,104,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,101,120,99,101,112,116,32,110,101,119,108,105,110,101,32,40,98,121,32,100,101,102,97,117,108,116,41>>]},{dt,[],[<<91>>]},{dd,[],[<<83,116,97,114,116,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,100,101,102,105,110,105,116,105,111,110>>]},{dt,[],[<<124>>]},{dd,[],[<<83,116,97,114,116,32,111,102,32,97,108,116,101,114,110,97,116,105,118,101,32,98,114,97,110,99,104>>]},{dt,[],[<<40>>]},{dd,[],[<<83,116,97,114,116,32,115,117,98,112,97,116,116,101,114,110>>]},{dt,[],[<<41>>]},{dd,[],[<<69,110,100,32,115,117,98,112,97,116,116,101,114,110>>]},{dt,[],[<<63>>]},{dd,[],[<<69,120,116,101,110,100,115,32,116,104,101,32,109,101,97,110,105,110,103,32,111,102,32,40,44,32,97,108,115,111,32,48,32,111,114,32,49,32,113,117,97,110,116,105,102,105,101,114,44,32,97,108,115,111,32,113,117,97,110,116,105,102,105,101,114,32,109,105,110,105,109,105,122,101,114>>]},{dt,[],[<<42>>]},{dd,[],[<<48,32,111,114,32,109,111,114,101,32,113,117,97,110,116,105,102,105,101,114,115>>]},{dt,[],[<<43>>]},{dd,[],[<<49,32,111,114,32,109,111,114,101,32,113,117,97,110,116,105,102,105,101,114,44,32,97,108,115,111,32,34,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,34>>]},{dt,[],[<<123>>]},{dd,[],[<<83,116,97,114,116,32,109,105,110,47,109,97,120,32,113,117,97,110,116,105,102,105,101,114>>]}]},{p,[],[<<80,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,32,119,105,116,104,105,110,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,32,105,115,32,99,97,108,108,101,100,32,97,32,34,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,34,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,111,110,108,121,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,58>>]},{dl,[],[{dt,[],[<<92>>]},{dd,[],[<<71,101,110,101,114,97,108,32,101,115,99,97,112,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<94>>]},{dd,[],[<<78,101,103,97,116,101,32,116,104,101,32,99,108,97,115,115,44,32,98,117,116,32,111,110,108,121,32,105,102,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<45>>]},{dd,[],[<<73,110,100,105,99,97,116,101,115,32,99,104,97,114,97,99,116,101,114,32,114,97,110,103,101>>]},{dt,[],[<<91>>]},{dd,[],[<<80,111,115,105,120,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,40,111,110,108,121,32,105,102,32,102,111,108,108,111,119,101,100,32,98,121,32,80,111,115,105,120,32,115,121,110,116,97,120,41>>]},{dt,[],[<<93>>]},{dd,[],[<<84,101,114,109,105,110,97,116,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,32,100,101,115,99,114,105,98,101,32,116,104,101,32,117,115,101,32,111,102,32,101,97,99,104,32,109,101,116,97,99,104,97,114,97,99,116,101,114,46>>]},{a,[{id,<<115,101,99,116,51>>}],[]},{h2,[],[<<66,97,99,107,115,108,97,115,104>>]},{p,[],[<<84,104,101,32,98,97,99,107,115,108,97,115,104,32,99,104,97,114,97,99,116,101,114,32,104,97,115,32,109,97,110,121,32,117,115,101,115,46,32,70,105,114,115,116,44,32,105,102,32,105,116,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,110,117,109,98,101,114,32,111,114,32,97,32,108,101,116,116,101,114,44,32,105,116,32,116,97,107,101,115,32,97,119,97,121,32,97,110,121,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,116,104,97,116,32,97,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,104,97,118,101,46,32,84,104,105,115,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,97,115,32,97,110,32,101,115,99,97,112,101,32,99,104,97,114,97,99,116,101,114,32,97,112,112,108,105,101,115,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,97,32,42,32,99,104,97,114,97,99,116,101,114,44,32,121,111,117,32,119,114,105,116,101,32,92,42,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,105,115,32,101,115,99,97,112,105,110,103,32,97,99,116,105,111,110,32,97,112,112,108,105,101,115,32,105,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,104,97,114,97,99,116,101,114,32,119,111,117,108,100,32,111,116,104,101,114,119,105,115,101,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,109,101,116,97,99,104,97,114,97,99,116,101,114,44,32,115,111,32,105,116,32,105,115,32,97,108,119,97,121,115,32,115,97,102,101,32,116,111,32,112,114,101,99,101,100,101,32,97,32,110,111,110,45,97,108,112,104,97,110,117,109,101,114,105,99,32,119,105,116,104,32,98,97,99,107,115,108,97,115,104,32,116,111,32,115,112,101,99,105,102,121,32,116,104,97,116,32,105,116,32,115,116,97,110,100,115,32,102,111,114,32,105,116,115,101,108,102,46,32,73,110,32,112,97,114,116,105,99,117,108,97,114,44,32,105,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,97,32,98,97,99,107,115,108,97,115,104,44,32,119,114,105,116,101,32,92,92,46>>]},{p,[],[<<73,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,109,111,100,101,44,32,111,110,108,121,32,65,83,67,73,73,32,110,117,109,98,101,114,115,32,97,110,100,32,108,101,116,116,101,114,115,32,104,97,118,101,32,97,110,121,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,97,102,116,101,114,32,97,32,98,97,99,107,115,108,97,115,104,46,32,65,108,108,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,32,112,97,114,116,105,99,117,108,97,114,44,32,116,104,111,115,101,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,62,32,49,50,55,41,32,97,114,101,32,116,114,101,97,116,101,100,32,97,115,32,108,105,116,101,114,97,108,115,46>>]},{p,[],[<<73,102,32,97,32,112,97,116,116,101,114,110,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<44,32,119,104,105,116,101,115,112,97,99,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,40,111,116,104,101,114,32,116,104,97,110,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,41,32,97,110,100,32,99,104,97,114,97,99,116,101,114,115,32,98,101,116,119,101,101,110,32,97,32,35,32,111,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,97,110,100,32,116,104,101,32,110,101,120,116,32,110,101,119,108,105,110,101,32,97,114,101,32,105,103,110,111,114,101,100,46,32,65,110,32,101,115,99,97,112,105,110,103,32,98,97,99,107,115,108,97,115,104,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,105,110,99,108,117,100,101,32,97,32,119,104,105,116,101,115,112,97,99,101,32,111,114,32,35,32,99,104,97,114,97,99,116,101,114,32,97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<84,111,32,114,101,109,111,118,101,32,116,104,101,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,102,114,111,109,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,44,32,112,117,116,32,116,104,101,109,32,98,101,116,119,101,101,110,32,92,81,32,97,110,100,32,92,69,46,32,84,104,105,115,32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,80,101,114,108,32,105,110,32,116,104,97,116,32,36,32,97,110,100,32,64,32,97,114,101,32,104,97,110,100,108,101,100,32,97,115,32,108,105,116,101,114,97,108,115,32,105,110,32,92,81,46,46,46,92,69,32,115,101,113,117,101,110,99,101,115,32,105,110,32,80,67,82,69,44,32,119,104,105,108,101,32,36,32,97,110,100,32,64,32,99,97,117,115,101,32,118,97,114,105,97,98,108,101,32,105,110,116,101,114,112,111,108,97,116,105,111,110,32,105,110,32,80,101,114,108,46,32,78,111,116,105,99,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<80,97,116,116,101,114,110,32,32,32,32,32,32,32,32,32,32,32,32,80,67,82,69,32,109,97,116,99,104,101,115,32,32,32,80,101,114,108,32,109,97,116,99,104,101,115,10,10,92,81,97,98,99,36,120,121,122,92,69,32,32,32,32,32,32,32,32,97,98,99,36,120,121,122,32,32,32,32,32,32,32,32,97,98,99,32,102,111,108,108,111,119,101,100,32,98,121,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,36,120,121,122,10,92,81,97,98,99,92,36,120,121,122,92,69,32,32,32,32,32,32,32,97,98,99,92,36,120,121,122,32,32,32,32,32,32,32,97,98,99,92,36,120,121,122,10,92,81,97,98,99,92,69,92,36,92,81,120,121,122,92,69,32,32,32,97,98,99,36,120,121,122,32,32,32,32,32,32,32,32,97,98,99,36,120,121,122>>]}]},{p,[],[<<84,104,101,32,92,81,46,46,46,92,69,32,115,101,113,117,101,110,99,101,32,105,115,32,114,101,99,111,103,110,105,122,101,100,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,65,110,32,105,115,111,108,97,116,101,100,32,92,69,32,116,104,97,116,32,105,115,32,110,111,116,32,112,114,101,99,101,100,101,100,32,98,121,32,92,81,32,105,115,32,105,103,110,111,114,101,100,46,32,73,102,32,92,81,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32,92,69,32,108,97,116,101,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,44,32,116,104,101,32,108,105,116,101,114,97,108,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,99,111,110,116,105,110,117,101,115,32,116,111,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,40,116,104,97,116,32,105,115,44,32,92,69,32,105,115,32,97,115,115,117,109,101,100,32,97,116,32,116,104,101,32,101,110,100,41,46,32,73,102,32,116,104,101,32,105,115,111,108,97,116,101,100,32,92,81,32,105,115,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,104,105,115,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,44,32,97,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,105,115,32,110,111,116,32,116,101,114,109,105,110,97,116,101,100,46>>]},{p,[],[{em,[],[<<78,111,110,45,80,114,105,110,116,105,110,103,32,67,104,97,114,97,99,116,101,114,115>>]}]},{a,[{id,<<110,111,110,95,112,114,105,110,116,105,110,103,95,99,104,97,114,97,99,116,101,114,115>>}],[]},{p,[],[<<65,32,115,101,99,111,110,100,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,112,114,111,118,105,100,101,115,32,97,32,119,97,121,32,111,102,32,101,110,99,111,100,105,110,103,32,110,111,110,45,112,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,112,97,116,116,101,114,110,115,32,105,110,32,97,32,118,105,115,105,98,108,101,32,109,97,110,110,101,114,46,32,84,104,101,114,101,32,105,115,32,110,111,32,114,101,115,116,114,105,99,116,105,111,110,32,111,110,32,116,104,101,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,110,111,110,45,112,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,97,112,97,114,116,32,102,114,111,109,32,116,104,101,32,98,105,110,97,114,121,32,122,101,114,111,32,116,104,97,116,32,116,101,114,109,105,110,97,116,101,115,32,97,32,112,97,116,116,101,114,110,46,32,87,104,101,110,32,97,32,112,97,116,116,101,114,110,32,105,115,32,112,114,101,112,97,114,101,100,32,98,121,32,116,101,120,116,32,101,100,105,116,105,110,103,44,32,105,116,32,105,115,32,111,102,116,101,110,32,101,97,115,105,101,114,32,116,111,32,117,115,101,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,110,32,116,104,101,32,98,105,110,97,114,121,32,99,104,97,114,97,99,116,101,114,32,105,116,32,114,101,112,114,101,115,101,110,116,115,58>>]},{dl,[],[{dt,[],[<<92,97>>]},{dd,[],[<<65,108,97,114,109,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,66,69,76,32,99,104,97,114,97,99,116,101,114,32,40,104,101,120,32,48,55,41>>]},{dt,[],[<<92,99,120>>]},{dd,[],[<<34,67,111,110,116,114,111,108,45,120,34,44,32,119,104,101,114,101,32,120,32,105,115,32,97,110,121,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,101>>]},{dd,[],[<<69,115,99,97,112,101,32,40,104,101,120,32,49,66,41>>]},{dt,[],[<<92,102>>]},{dd,[],[<<70,111,114,109,32,102,101,101,100,32,40,104,101,120,32,48,67,41>>]},{dt,[],[<<92,110>>]},{dd,[],[<<76,105,110,101,32,102,101,101,100,32,40,104,101,120,32,48,65,41>>]},{dt,[],[<<92,114>>]},{dd,[],[<<67,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,40,104,101,120,32,48,68,41>>]},{dt,[],[<<92,116>>]},{dd,[],[<<84,97,98,32,40,104,101,120,32,48,57,41>>]},{dt,[],[<<92,48,100,100>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,48,100,100>>]},{dt,[],[<<92,100,100,100>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,100,100,100,44,32,111,114,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101>>]},{dt,[],[<<92,111,123,100,100,100,46,46,125>>]},{dd,[],[<<99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,100,100,100,46,46>>]},{dt,[],[<<92,120,104,104>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,104,101,120,32,99,111,100,101,32,104,104>>]},{dt,[],[<<92,120,123,104,104,104,46,46,125>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,104,101,120,32,99,111,100,101,32,104,104,104,46,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,92,48,100,100,32,105,115,32,97,108,119,97,121,115,32,97,110,32,111,99,116,97,108,32,99,111,100,101,44,32,97,110,100,32,116,104,97,116,32,92,56,32,97,110,100,32,92,57,32,97,114,101,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,56,34,32,97,110,100,32,34,57,34,46>>]}]},{p,[],[<<84,104,101,32,112,114,101,99,105,115,101,32,101,102,102,101,99,116,32,111,102,32,92,99,120,32,111,110,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,105,115,32,97,115,32,102,111,108,108,111,119,115,58,32,105,102,32,120,32,105,115,32,97,32,108,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,44,32,105,116,32,105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,117,112,112,101,114,32,99,97,115,101,46,32,84,104,101,110,32,98,105,116,32,54,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,40,104,101,120,32,52,48,41,32,105,115,32,105,110,118,101,114,116,101,100,46,32,84,104,117,115,32,92,99,65,32,116,111,32,92,99,90,32,98,101,99,111,109,101,32,104,101,120,32,48,49,32,116,111,32,104,101,120,32,49,65,32,40,65,32,105,115,32,52,49,44,32,90,32,105,115,32,53,65,41,44,32,98,117,116,32,92,99,123,32,98,101,99,111,109,101,115,32,104,101,120,32,51,66,32,40,123,32,105,115,32,55,66,41,44,32,97,110,100,32,92,99,59,32,98,101,99,111,109,101,115,32,104,101,120,32,55,66,32,40,59,32,105,115,32,51,66,41,46,32,73,102,32,116,104,101,32,100,97,116,97,32,105,116,101,109,32,40,98,121,116,101,32,111,114,32,49,54,45,98,105,116,32,118,97,108,117,101,41,32,102,111,108,108,111,119,105,110,103,32,92,99,32,104,97,115,32,97,32,118,97,108,117,101,32,62,32,49,50,55,44,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,32,111,99,99,117,114,115,46,32,84,104,105,115,32,108,111,99,107,115,32,111,117,116,32,110,111,110,45,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,97,108,108,32,109,111,100,101,115,46>>]},{p,[],[<<84,104,101,32,92,99,32,102,97,99,105,108,105,116,121,32,119,97,115,32,100,101,115,105,103,110,101,100,32,102,111,114,32,117,115,101,32,119,105,116,104,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,44,32,98,117,116,32,119,105,116,104,32,116,104,101,32,101,120,116,101,110,115,105,111,110,32,116,111,32,85,110,105,99,111,100,101,32,105,116,32,105,115,32,101,118,101,110,32,108,101,115,115,32,117,115,101,102,117,108,32,116,104,97,110,32,105,116,32,111,110,99,101,32,119,97,115,46>>]},{p,[],[<<65,102,116,101,114,32,92,48,32,117,112,32,116,111,32,116,119,111,32,102,117,114,116,104,101,114,32,111,99,116,97,108,32,100,105,103,105,116,115,32,97,114,101,32,114,101,97,100,46,32,73,102,32,116,104,101,114,101,32,97,114,101,32,102,101,119,101,114,32,116,104,97,110,32,116,119,111,32,100,105,103,105,116,115,44,32,106,117,115,116,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,112,114,101,115,101,110,116,32,97,114,101,32,117,115,101,100,46,32,84,104,117,115,32,116,104,101,32,115,101,113,117,101,110,99,101,32,92,48,92,120,92,48,49,53,32,115,112,101,99,105,102,105,101,115,32,116,119,111,32,98,105,110,97,114,121,32,122,101,114,111,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,67,82,32,99,104,97,114,97,99,116,101,114,32,40,99,111,100,101,32,118,97,108,117,101,32,49,51,41,46,32,77,97,107,101,32,115,117,114,101,32,121,111,117,32,115,117,112,112,108,121,32,116,119,111,32,100,105,103,105,116,115,32,97,102,116,101,114,32,116,104,101,32,105,110,105,116,105,97,108,32,122,101,114,111,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,102,111,108,108,111,119,115,32,105,115,32,105,116,115,101,108,102,32,97,110,32,111,99,116,97,108,32,100,105,103,105,116,46>>]},{p,[],[<<84,104,101,32,101,115,99,97,112,101,32,92,111,32,109,117,115,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,111,99,116,97,108,32,100,105,103,105,116,115,44,32,101,110,99,108,111,115,101,100,32,105,110,32,98,114,97,99,101,115,46,32,65,110,32,101,114,114,111,114,32,111,99,99,117,114,115,32,105,102,32,116,104,105,115,32,105,115,32,110,111,116,32,116,104,101,32,99,97,115,101,46,32,84,104,105,115,32,101,115,99,97,112,101,32,105,115,32,97,32,114,101,99,101,110,116,32,97,100,100,105,116,105,111,110,32,116,111,32,80,101,114,108,59,32,105,116,32,112,114,111,118,105,100,101,115,32,119,97,121,32,111,102,32,115,112,101,99,105,102,121,105,110,103,32,99,104,97,114,97,99,116,101,114,32,99,111,100,101,32,112,111,105,110,116,115,32,97,115,32,111,99,116,97,108,32,110,117,109,98,101,114,115,32,103,114,101,97,116,101,114,32,116,104,97,110,32,48,55,55,55,44,32,97,110,100,32,105,116,32,97,108,115,111,32,97,108,108,111,119,115,32,111,99,116,97,108,32,110,117,109,98,101,114,115,32,97,110,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,98,101,32,117,110,97,109,98,105,103,117,111,117,115,108,121,32,115,112,101,99,105,102,105,101,100,46>>]},{p,[],[<<70,111,114,32,103,114,101,97,116,101,114,32,99,108,97,114,105,116,121,32,97,110,100,32,117,110,97,109,98,105,103,117,105,116,121,44,32,105,116,32,105,115,32,98,101,115,116,32,116,111,32,97,118,111,105,100,32,102,111,108,108,111,119,105,110,103,32,92,32,98,121,32,97,32,100,105,103,105,116,32,103,114,101,97,116,101,114,32,116,104,97,110,32,122,101,114,111,46,32,73,110,115,116,101,97,100,44,32,117,115,101,32,92,111,123,125,32,111,114,32,92,120,123,125,32,116,111,32,115,112,101,99,105,102,121,32,99,104,97,114,97,99,116,101,114,32,110,117,109,98,101,114,115,44,32,97,110,100,32,92,103,123,125,32,116,111,32,115,112,101,99,105,102,121,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,114,97,103,114,97,112,104,115,32,100,101,115,99,114,105,98,101,32,116,104,101,32,111,108,100,44,32,97,109,98,105,103,117,111,117,115,32,115,121,110,116,97,120,46>>]},{p,[],[<<84,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,97,32,98,97,99,107,115,108,97,115,104,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,100,105,103,105,116,32,111,116,104,101,114,32,116,104,97,110,32,48,32,105,115,32,99,111,109,112,108,105,99,97,116,101,100,44,32,97,110,100,32,80,101,114,108,32,104,97,115,32,99,104,97,110,103,101,100,32,105,110,32,114,101,99,101,110,116,32,114,101,108,101,97,115,101,115,44,32,99,97,117,115,105,110,103,32,80,67,82,69,32,97,108,115,111,32,116,111,32,99,104,97,110,103,101,46,32,79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,80,67,82,69,32,114,101,97,100,115,32,116,104,101,32,100,105,103,105,116,32,97,110,100,32,97,110,121,32,102,111,108,108,111,119,105,110,103,32,100,105,103,105,116,115,32,97,115,32,97,32,100,101,99,105,109,97,108,32,110,117,109,98,101,114,46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,105,115,32,60,32,56,44,32,111,114,32,105,102,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,32,97,116,32,108,101,97,115,116,32,116,104,97,116,32,109,97,110,121,32,112,114,101,118,105,111,117,115,32,99,97,112,116,117,114,105,110,103,32,108,101,102,116,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,44,32,116,104,101,32,101,110,116,105,114,101,32,115,101,113,117,101,110,99,101,32,105,115,32,116,97,107,101,110,32,97,115,32,97,32>>,{em,[],[<<98,97,99,107,32,114,101,102,101,114,101,110,99,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,104,111,119,32,116,104,105,115,32,119,111,114,107,115,32,105,115,32,112,114,111,118,105,100,101,100,32,108,97,116,101,114,44,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,100,105,115,99,117,115,115,105,111,110,32,111,102,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46>>]},{p,[],[<<73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,111,114,32,105,102,32,116,104,101,32,100,101,99,105,109,97,108,32,110,117,109,98,101,114,32,102,111,108,108,111,119,105,110,103,32,92,32,105,115,32,62,32,55,32,97,110,100,32,116,104,101,114,101,32,104,97,118,101,32,110,111,116,32,98,101,101,110,32,116,104,97,116,32,109,97,110,121,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,80,67,82,69,32,104,97,110,100,108,101,115,32,92,56,32,97,110,100,32,92,57,32,97,115,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,56,34,32,97,110,100,32,34,57,34,44,32,97,110,100,32,111,116,104,101,114,119,105,115,101,32,114,101,45,114,101,97,100,115,32,117,112,32,116,111,32,116,104,114,101,101,32,111,99,116,97,108,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,98,97,99,107,115,108,97,115,104,44,32,97,110,100,32,117,115,105,110,103,32,116,104,101,109,32,116,111,32,103,101,110,101,114,97,116,101,32,97,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114,46,32,65,110,121,32,115,117,98,115,101,113,117,101,110,116,32,100,105,103,105,116,115,32,115,116,97,110,100,32,102,111,114,32,116,104,101,109,115,101,108,118,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{dl,[],[{dt,[],[<<92,48,52,48>>]},{dd,[],[<<65,110,111,116,104,101,114,32,119,97,121,32,111,102,32,119,114,105,116,105,110,103,32,97,110,32,65,83,67,73,73,32,115,112,97,99,101>>]},{dt,[],[<<92,52,48>>]},{dd,[],[<<84,104,101,32,115,97,109,101,44,32,112,114,111,118,105,100,101,100,32,116,104,101,114,101,32,97,114,101,32,60,32,52,48,32,112,114,101,118,105,111,117,115,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115>>]},{dt,[],[<<92,55>>]},{dd,[],[<<65,108,119,97,121,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101>>]},{dt,[],[<<92,49,49>>]},{dd,[],[<<67,97,110,32,98,101,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,114,32,97,110,111,116,104,101,114,32,119,97,121,32,111,102,32,119,114,105,116,105,110,103,32,97,32,116,97,98>>]},{dt,[],[<<92,48,49,49>>]},{dd,[],[<<65,108,119,97,121,115,32,97,32,116,97,98>>]},{dt,[],[<<92,48,49,49,51>>]},{dd,[],[<<65,32,116,97,98,32,102,111,108,108,111,119,101,100,32,98,121,32,99,104,97,114,97,99,116,101,114,32,34,51,34>>]},{dt,[],[<<92,49,49,51>>]},{dd,[],[<<67,97,110,32,98,101,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,49,49,51>>]},{dt,[],[<<92,51,55,55>>]},{dd,[],[<<67,97,110,32,98,101,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,116,104,101,114,119,105,115,101,32,118,97,108,117,101,32,50,53,53,32,40,100,101,99,105,109,97,108,41>>]},{dt,[],[<<92,56,49>>]},{dd,[],[<<69,105,116,104,101,114,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,114,32,116,104,101,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,32,34,56,34,32,97,110,100,32,34,49,34>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,111,99,116,97,108,32,118,97,108,117,101,115,32,62,61,32,49,48,48,32,116,104,97,116,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,117,115,105,110,103,32,116,104,105,115,32,115,121,110,116,97,120,32,109,117,115,116,32,110,111,116,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,98,121,32,97,32,108,101,97,100,105,110,103,32,122,101,114,111,44,32,97,115,32,110,111,32,109,111,114,101,32,116,104,97,110,32,116,104,114,101,101,32,111,99,116,97,108,32,100,105,103,105,116,115,32,97,114,101,32,101,118,101,114,32,114,101,97,100,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,97,102,116,101,114,32,92,120,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32,123,44,32,102,114,111,109,32,122,101,114,111,32,116,111,32,116,119,111,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,115,32,97,114,101,32,114,101,97,100,32,40,108,101,116,116,101,114,115,32,99,97,110,32,98,101,32,105,110,32,117,112,112,101,114,32,111,114,32,108,111,119,101,114,32,99,97,115,101,41,46,32,65,110,121,32,110,117,109,98,101,114,32,111,102,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,115,32,109,97,121,32,97,112,112,101,97,114,32,98,101,116,119,101,101,110,32,92,120,123,32,97,110,100,32,125,46,32,73,102,32,97,32,99,104,97,114,97,99,116,101,114,32,111,116,104,101,114,32,116,104,97,110,32,97,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,32,97,112,112,101,97,114,115,32,98,101,116,119,101,101,110,32,92,120,123,32,97,110,100,32,125,44,32,111,114,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,116,101,114,109,105,110,97,116,105,110,103,32,125,44,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46>>]},{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,118,97,108,117,101,32,105,115,32,108,101,115,115,32,116,104,97,110,32,50,53,54,32,99,97,110,32,98,101,32,100,101,102,105,110,101,100,32,98,121,32,101,105,116,104,101,114,32,111,102,32,116,104,101,32,116,119,111,32,115,121,110,116,97,120,101,115,32,102,111,114,32,92,120,46,32,84,104,101,114,101,32,105,115,32,110,111,32,100,105,102,102,101,114,101,110,99,101,32,105,110,32,116,104,101,32,119,97,121,32,116,104,101,121,32,97,114,101,32,104,97,110,100,108,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,92,120,100,99,32,105,115,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32,92,120,123,100,99,125,46>>]},{p,[],[{em,[],[<<67,111,110,115,116,114,97,105,110,116,115,32,111,110,32,99,104,97,114,97,99,116,101,114,32,118,97,108,117,101,115>>]}]},{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,117,115,105,110,103,32,111,99,116,97,108,32,111,114,32,104,101,120,97,100,101,99,105,109,97,108,32,110,117,109,98,101,114,115,32,97,114,101,32,108,105,109,105,116,101,100,32,116,111,32,99,101,114,116,97,105,110,32,118,97,108,117,101,115,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<56,45,98,105,116,32,110,111,110,45,85,84,70,32,109,111,100,101>>]},{dd,[],[{p,[],[<<60,32,48,120,49,48,48>>]}]},{dt,[],[<<56,45,98,105,116,32,85,84,70,45,56,32,109,111,100,101>>]},{dd,[],[{p,[],[<<60,32,48,120,49,48,102,102,102,102,32,97,110,100,32,97,32,118,97,108,105,100,32,99,111,100,101,112,111,105,110,116>>]}]}]},{p,[],[<<73,110,118,97,108,105,100,32,85,110,105,99,111,100,101,32,99,111,100,101,112,111,105,110,116,115,32,97,114,101,32,116,104,101,32,114,97,110,103,101,32,48,120,100,56,48,48,32,116,111,32,48,120,100,102,102,102,32,40,116,104,101,32,115,111,45,99,97,108,108,101,100,32,34,115,117,114,114,111,103,97,116,101,34,32,99,111,100,101,112,111,105,110,116,115,41,44,32,97,110,100,32,48,120,102,102,101,102,46>>]},{p,[],[{em,[],[<<69,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,105,110,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115>>]}]},{p,[],[<<65,108,108,32,116,104,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,116,32,100,101,102,105,110,101,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,118,97,108,117,101,32,99,97,110,32,98,101,32,117,115,101,100,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,65,108,115,111,44,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,92,98,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,116,104,101,32,98,97,99,107,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,32,40,104,101,120,32,48,56,41,46>>]},{p,[],[<<92,78,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,92,66,44,32,92,82,44,32,97,110,100,32,92,88,32,97,114,101,32,110,111,116,32,115,112,101,99,105,97,108,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,76,105,107,101,32,111,116,104,101,114,32,117,110,114,101,99,111,103,110,105,122,101,100,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,44,32,116,104,101,121,32,97,114,101,32,116,114,101,97,116,101,100,32,97,115,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,66,34,44,32,34,82,34,44,32,97,110,100,32,34,88,34,46,32,79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,115,46>>]},{p,[],[{em,[],[<<85,110,115,117,112,112,111,114,116,101,100,32,69,115,99,97,112,101,32,83,101,113,117,101,110,99,101,115>>]}]},{p,[],[<<73,110,32,80,101,114,108,44,32,116,104,101,32,115,101,113,117,101,110,99,101,115,32,92,108,44,32,92,76,44,32,92,117,44,32,97,110,100,32,92,85,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,98,121,32,105,116,115,32,115,116,114,105,110,103,32,104,97,110,100,108,101,114,32,97,110,100,32,117,115,101,100,32,116,111,32,109,111,100,105,102,121,32,116,104,101,32,99,97,115,101,32,111,102,32,102,111,108,108,111,119,105,110,103,32,99,104,97,114,97,99,116,101,114,115,46,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,115,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,46>>]},{p,[],[{em,[],[<<65,98,115,111,108,117,116,101,32,97,110,100,32,82,101,108,97,116,105,118,101,32,66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]}]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,32,92,103,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,117,110,115,105,103,110,101,100,32,111,114,32,97,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,44,32,111,112,116,105,111,110,97,108,108,121,32,101,110,99,108,111,115,101,100,32,105,110,32,98,114,97,99,101,115,44,32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,111,114,32,114,101,108,97,116,105,118,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,46,32,65,32,110,97,109,101,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,99,111,100,101,100,32,97,115,32,92,103,123,110,97,109,101,125,46,32,66,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,97,114,101,32,100,105,115,99,117,115,115,101,100,32,108,97,116,101,114,44,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,100,105,115,99,117,115,115,105,111,110,32,111,102,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46>>]},{p,[],[{em,[],[<<65,98,115,111,108,117,116,101,32,97,110,100,32,82,101,108,97,116,105,118,101,32,83,117,98,114,111,117,116,105,110,101,32,67,97,108,108,115>>]}]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,79,110,105,103,117,114,117,109,97,44,32,116,104,101,32,110,111,110,45,80,101,114,108,32,115,121,110,116,97,120,32,92,103,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,32,111,114,32,97,32,110,117,109,98,101,114,32,101,110,99,108,111,115,101,100,32,101,105,116,104,101,114,32,105,110,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115,32,111,114,32,115,105,110,103,108,101,32,113,117,111,116,101,115,44,32,105,115,32,97,108,116,101,114,110,97,116,105,118,101,32,115,121,110,116,97,120,32,102,111,114,32,114,101,102,101,114,101,110,99,105,110,103,32,97,32,115,117,98,112,97,116,116,101,114,110,32,97,115,32,97,32,34,115,117,98,114,111,117,116,105,110,101,34,46,32,68,101,116,97,105,108,115,32,97,114,101,32,100,105,115,99,117,115,115,101,100,32,108,97,116,101,114,46,32,78,111,116,105,99,101,32,116,104,97,116,32,92,103,123,46,46,46,125,32,40,80,101,114,108,32,115,121,110,116,97,120,41,32,97,110,100,32,92,103,60,46,46,46,62,32,40,79,110,105,103,117,114,117,109,97,32,115,121,110,116,97,120,41,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,115,121,110,111,110,121,109,111,117,115,46,32,84,104,101,32,102,111,114,109,101,114,32,105,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,97,110,100,32,116,104,101,32,108,97,116,116,101,114,32,105,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,46>>]},{p,[],[{em,[],[<<71,101,110,101,114,105,99,32,67,104,97,114,97,99,116,101,114,32,84,121,112,101,115>>]}]},{a,[{id,<<103,101,110,101,114,105,99,95,99,104,97,114,97,99,116,101,114,95,116,121,112,101,115>>}],[]},{p,[],[<<65,110,111,116,104,101,114,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,105,115,32,102,111,114,32,115,112,101,99,105,102,121,105,110,103,32,103,101,110,101,114,105,99,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,58>>]},{dl,[],[{dt,[],[<<92,100>>]},{dd,[],[<<65,110,121,32,100,101,99,105,109,97,108,32,100,105,103,105,116>>]},{dt,[],[<<92,68>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,100,101,99,105,109,97,108,32,100,105,103,105,116>>]},{dt,[],[<<92,104>>]},{dd,[],[<<65,110,121,32,104,111,114,105,122,111,110,116,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,72>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,104,111,114,105,122,111,110,116,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,115>>]},{dd,[],[<<65,110,121,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,83>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,118>>]},{dd,[],[<<65,110,121,32,118,101,114,116,105,99,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,86>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,118,101,114,116,105,99,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,119>>]},{dd,[],[<<65,110,121,32,34,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,87>>]},{dd,[],[<<65,110,121,32,34,110,111,110,45,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114>>]}]},{p,[],[<<84,104,101,114,101,32,105,115,32,97,108,115,111,32,116,104,101,32,115,105,110,103,108,101,32,115,101,113,117,101,110,99,101,32,92,78,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,32,110,111,110,45,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,34,46,34,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,119,104,101,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,105,115,32,110,111,116,32,115,101,116,46,32,80,101,114,108,32,97,108,115,111,32,117,115,101,115,32,92,78,32,116,111,32,109,97,116,99,104,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,110,97,109,101,44,32,98,117,116,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,105,115,46>>]},{p,[],[<<69,97,99,104,32,112,97,105,114,32,111,102,32,108,111,119,101,114,99,97,115,101,32,97,110,100,32,117,112,112,101,114,99,97,115,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,112,97,114,116,105,116,105,111,110,115,32,116,104,101,32,99,111,109,112,108,101,116,101,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,105,110,116,111,32,116,119,111,32,100,105,115,106,111,105,110,116,32,115,101,116,115,46,32,65,110,121,32,103,105,118,101,110,32,99,104,97,114,97,99,116,101,114,32,109,97,116,99,104,101,115,32,111,110,101,44,32,97,110,100,32,111,110,108,121,32,111,110,101,44,32,111,102,32,101,97,99,104,32,112,97,105,114,46,32,84,104,101,32,115,101,113,117,101,110,99,101,115,32,99,97,110,32,97,112,112,101,97,114,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,84,104,101,121,32,101,97,99,104,32,109,97,116,99,104,32,111,110,101,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,116,121,112,101,46,32,73,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,108,108,32,102,97,105,108,44,32,97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,99,104,97,114,97,99,116,101,114,32,116,111,32,109,97,116,99,104,46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,80,101,114,108,44,32,92,115,32,100,105,100,32,110,111,116,32,117,115,101,100,32,116,111,32,109,97,116,99,104,32,116,104,101,32,86,84,32,99,104,97,114,97,99,116,101,114,32,40,99,111,100,101,32,49,49,41,44,32,119,104,105,99,104,32,109,97,100,101,32,105,116,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,116,104,101,32,80,79,83,73,88,32,34,115,112,97,99,101,34,32,99,108,97,115,115,46,32,72,111,119,101,118,101,114,44,32,80,101,114,108,32,97,100,100,101,100,32,86,84,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,44,32,97,110,100,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,115,117,105,116,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46,32,84,104,101,32,100,101,102,97,117,108,116,32,92,115,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,110,111,119,32,72,84,32,40,57,41,44,32,76,70,32,40,49,48,41,44,32,86,84,32,40,49,49,41,44,32,70,70,32,40,49,50,41,44,32,67,82,32,40,49,51,41,44,32,97,110,100,32,115,112,97,99,101,32,40,51,50,41,44,32,119,104,105,99,104,32,97,114,101,32,100,101,102,105,110,101,100,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,32,105,110,32,116,104,101,32,34,67,34,32,108,111,99,97,108,101,46,32,84,104,105,115,32,108,105,115,116,32,109,97,121,32,118,97,114,121,32,105,102,32,108,111,99,97,108,101,45,115,112,101,99,105,102,105,99,32,109,97,116,99,104,105,110,103,32,105,115,32,116,97,107,105,110,103,32,112,108,97,99,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,115,111,109,101,32,108,111,99,97,108,101,115,32,116,104,101,32,34,110,111,110,45,98,114,101,97,107,105,110,103,32,115,112,97,99,101,34,32,99,104,97,114,97,99,116,101,114,32,40,92,120,65,48,41,32,105,115,32,114,101,99,111,103,110,105,122,101,100,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,44,32,97,110,100,32,105,110,32,111,116,104,101,114,115,32,116,104,101,32,86,84,32,99,104,97,114,97,99,116,101,114,32,105,115,32,110,111,116,46>>]},{p,[],[<<65,32,34,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114,32,105,115,32,97,110,32,117,110,100,101,114,115,99,111,114,101,32,111,114,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,97,32,108,101,116,116,101,114,32,111,114,32,97,32,100,105,103,105,116,46,32,66,121,32,100,101,102,97,117,108,116,44,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,108,101,116,116,101,114,115,32,97,110,100,32,100,105,103,105,116,115,32,105,115,32,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,32,80,67,82,69,32,108,111,119,45,118,97,108,117,101,100,32,99,104,97,114,97,99,116,101,114,32,116,97,98,108,101,115,44,32,105,110,32,69,114,108,97,110,103,39,115,32,99,97,115,101,32,40,97,110,100,32,119,105,116,104,111,117,116,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<41,44,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,105,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,109,111,100,101,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,44,32,116,104,97,116,32,105,115,44,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,111,117,116,115,105,100,101,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,44,32,110,101,118,101,114,32,109,97,116,99,104,32,92,100,44,32,92,115,44,32,111,114,32,92,119,44,32,97,110,100,32,97,108,119,97,121,115,32,109,97,116,99,104,32,92,68,44,32,92,83,44,32,97,110,100,32,92,87,46,32,84,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,114,101,116,97,105,110,32,116,104,101,105,114,32,111,114,105,103,105,110,97,108,32,109,101,97,110,105,110,103,115,32,102,114,111,109,32,98,101,102,111,114,101,32,85,84,70,32,115,117,112,112,111,114,116,32,119,97,115,32,97,118,97,105,108,97,98,108,101,44,32,109,97,105,110,108,121,32,102,111,114,32,101,102,102,105,99,105,101,110,99,121,32,114,101,97,115,111,110,115,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,98,101,104,97,118,105,111,114,32,105,115,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,117,115,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<92,100>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,92,112,123,78,100,125,32,109,97,116,99,104,101,115,32,40,100,101,99,105,109,97,108,32,100,105,103,105,116,41>>]},{dt,[],[<<92,115>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,92,112,123,90,125,32,111,114,32,92,104,32,111,114,32,92,118>>]},{dt,[],[<<92,119>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,109,97,116,99,104,101,115,32,92,112,123,76,125,32,111,114,32,92,112,123,78,125,32,109,97,116,99,104,101,115,44,32,112,108,117,115,32,117,110,100,101,114,115,99,111,114,101>>]}]},{p,[],[<<84,104,101,32,117,112,112,101,114,99,97,115,101,32,101,115,99,97,112,101,115,32,109,97,116,99,104,32,116,104,101,32,105,110,118,101,114,115,101,32,115,101,116,115,32,111,102,32,99,104,97,114,97,99,116,101,114,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,92,100,32,109,97,116,99,104,101,115,32,111,110,108,121,32,100,101,99,105,109,97,108,32,100,105,103,105,116,115,44,32,119,104,105,108,101,32,92,119,32,109,97,116,99,104,101,115,32,97,110,121,32,85,110,105,99,111,100,101,32,100,105,103,105,116,44,32,97,110,121,32,85,110,105,99,111,100,101,32,108,101,116,116,101,114,44,32,97,110,100,32,117,110,100,101,114,115,99,111,114,101,46,32,78,111,116,105,99,101,32,97,108,115,111,32,116,104,97,116,32>>,{code,[],[<<117,99,112>>]},<<32,97,102,102,101,99,116,115,32,92,98,32,97,110,100,32,92,66,44,32,97,115,32,116,104,101,121,32,97,114,101,32,100,101,102,105,110,101,100,32,105,110,32,116,101,114,109,115,32,111,102,32,92,119,32,97,110,100,32,92,87,46,32,77,97,116,99,104,105,110,103,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,105,115,32,110,111,116,105,99,101,97,98,108,121,32,115,108,111,119,101,114,32,119,104,101,110,32>>,{code,[],[<<117,99,112>>]},<<32,105,115,32,115,101,116,46>>]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,115,32,92,104,44,32,92,72,44,32,92,118,44,32,97,110,100,32,92,86,32,97,114,101,32,102,101,97,116,117,114,101,115,32,116,104,97,116,32,119,101,114,101,32,97,100,100,101,100,32,116,111,32,80,101,114,108,32,105,110,32,114,101,108,101,97,115,101,32,53,46,49,48,46,32,73,110,32,99,111,110,116,114,97,115,116,32,116,111,32,116,104,101,32,111,116,104,101,114,32,115,101,113,117,101,110,99,101,115,44,32,119,104,105,99,104,32,109,97,116,99,104,32,111,110,108,121,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,100,101,102,97,117,108,116,44,32,116,104,101,115,101,32,97,108,119,97,121,115,32,109,97,116,99,104,32,99,101,114,116,97,105,110,32,104,105,103,104,45,118,97,108,117,101,100,32,99,111,100,101,32,112,111,105,110,116,115,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32>>,{code,[],[<<117,99,112>>]},<<32,105,115,32,115,101,116,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,104,111,114,105,122,111,110,116,97,108,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,58>>]},{dl,[],[{dt,[],[<<85,43,48,48,48,57>>]},{dd,[],[<<72,111,114,105,122,111,110,116,97,108,32,116,97,98,32,40,72,84,41>>]},{dt,[],[<<85,43,48,48,50,48>>]},{dd,[],[<<83,112,97,99,101>>]},{dt,[],[<<85,43,48,48,65,48>>]},{dd,[],[<<78,111,110,45,98,114,101,97,107,32,115,112,97,99,101>>]},{dt,[],[<<85,43,49,54,56,48>>]},{dd,[],[<<79,103,104,97,109,32,115,112,97,99,101,32,109,97,114,107>>]},{dt,[],[<<85,43,49,56,48,69>>]},{dd,[],[<<77,111,110,103,111,108,105,97,110,32,118,111,119,101,108,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<85,43,50,48,48,48>>]},{dd,[],[<<69,110,32,113,117,97,100>>]},{dt,[],[<<85,43,50,48,48,49>>]},{dd,[],[<<69,109,32,113,117,97,100>>]},{dt,[],[<<85,43,50,48,48,50>>]},{dd,[],[<<69,110,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,51>>]},{dd,[],[<<69,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,52>>]},{dd,[],[<<84,104,114,101,101,45,112,101,114,45,101,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,53>>]},{dd,[],[<<70,111,117,114,45,112,101,114,45,101,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,54>>]},{dd,[],[<<83,105,120,45,112,101,114,45,101,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,55>>]},{dd,[],[<<70,105,103,117,114,101,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,56>>]},{dd,[],[<<80,117,110,99,116,117,97,116,105,111,110,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,57>>]},{dd,[],[<<84,104,105,110,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,65>>]},{dd,[],[<<72,97,105,114,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,50,70>>]},{dd,[],[<<78,97,114,114,111,119,32,110,111,45,98,114,101,97,107,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,53,70>>]},{dd,[],[<<77,101,100,105,117,109,32,109,97,116,104,101,109,97,116,105,99,97,108,32,115,112,97,99,101>>]},{dt,[],[<<85,43,51,48,48,48>>]},{dd,[],[<<73,100,101,111,103,114,97,112,104,105,99,32,115,112,97,99,101>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,118,101,114,116,105,99,97,108,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,58>>]},{dl,[],[{dt,[],[<<85,43,48,48,48,65>>]},{dd,[],[<<76,105,110,101,32,102,101,101,100,32,40,76,70,41>>]},{dt,[],[<<85,43,48,48,48,66>>]},{dd,[],[<<86,101,114,116,105,99,97,108,32,116,97,98,32,40,86,84,41>>]},{dt,[],[<<85,43,48,48,48,67>>]},{dd,[],[<<70,111,114,109,32,102,101,101,100,32,40,70,70,41>>]},{dt,[],[<<85,43,48,48,48,68>>]},{dd,[],[<<67,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,40,67,82,41>>]},{dt,[],[<<85,43,48,48,56,53>>]},{dd,[],[<<78,101,120,116,32,108,105,110,101,32,40,78,69,76,41>>]},{dt,[],[<<85,43,50,48,50,56>>]},{dd,[],[<<76,105,110,101,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<85,43,50,48,50,57>>]},{dd,[],[<<80,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114>>]}]},{p,[],[<<73,110,32,56,45,98,105,116,44,32,110,111,110,45,85,84,70,45,56,32,109,111,100,101,44,32,111,110,108,121,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,99,111,100,101,32,112,111,105,110,116,115,32,60,32,50,53,54,32,97,114,101,32,114,101,108,101,118,97,110,116,46>>]},{p,[],[{em,[],[<<78,101,119,108,105,110,101,32,83,101,113,117,101,110,99,101,115>>]}]},{a,[{id,<<110,101,119,108,105,110,101,95,115,101,113,117,101,110,99,101,115>>}],[]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,98,121,32,100,101,102,97,117,108,116,44,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,82,32,109,97,116,99,104,101,115,32,97,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,46,32,73,110,32,110,111,110,45,85,84,70,45,56,32,109,111,100,101,44,32,92,82,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{pre,[],[{code,[],[<<40,63,62,92,114,92,110,124,92,110,124,92,120,48,98,124,92,102,124,92,114,124,92,120,56,53,41>>]}]},{p,[],[<<84,104,105,115,32,105,115,32,97,110,32,101,120,97,109,112,108,101,32,111,102,32,97,110,32,34,97,116,111,109,105,99,32,103,114,111,117,112,34,44,32,100,101,116,97,105,108,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,98,101,108,111,119,46>>]},{p,[],[<<84,104,105,115,32,112,97,114,116,105,99,117,108,97,114,32,103,114,111,117,112,32,109,97,116,99,104,101,115,32,101,105,116,104,101,114,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,32,102,111,108,108,111,119,101,100,32,98,121,32,76,70,44,32,111,114,32,111,110,101,32,111,102,32,116,104,101,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,115,32,76,70,32,40,108,105,110,101,32,102,101,101,100,44,32,85,43,48,48,48,65,41,44,32,86,84,32,40,118,101,114,116,105,99,97,108,32,116,97,98,44,32,85,43,48,48,48,66,41,44,32,70,70,32,40,102,111,114,109,32,102,101,101,100,44,32,85,43,48,48,48,67,41,44,32,67,82,32,40,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,44,32,85,43,48,48,48,68,41,44,32,111,114,32,78,69,76,32,40,110,101,120,116,32,108,105,110,101,44,32,85,43,48,48,56,53,41,46,32,84,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,97,32,115,105,110,103,108,101,32,117,110,105,116,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,115,112,108,105,116,46>>]},{p,[],[<<73,110,32,85,110,105,99,111,100,101,32,109,111,100,101,44,32,116,119,111,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,62,32,50,53,53,32,97,114,101,32,97,100,100,101,100,58,32,76,83,32,40,108,105,110,101,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,56,41,32,97,110,100,32,80,83,32,40,112,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,57,41,46,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,32,105,115,32,110,111,116,32,110,101,101,100,101,100,32,102,111,114,32,116,104,101,115,101,32,99,104,97,114,97,99,116,101,114,115,32,116,111,32,98,101,32,114,101,99,111,103,110,105,122,101,100,46>>]},{p,[],[<<92,82,32,99,97,110,32,98,101,32,114,101,115,116,114,105,99,116,101,100,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,67,82,44,32,76,70,44,32,111,114,32,67,82,76,70,32,40,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,99,111,109,112,108,101,116,101,32,115,101,116,32,111,102,32,85,110,105,99,111,100,101,32,108,105,110,101,32,101,110,100,105,110,103,115,41,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<98,115,114,95,97,110,121,99,114,108,102>>]},<<32,101,105,116,104,101,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,32,111,114,32,119,104,101,110,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,109,97,116,99,104,101,100,46,32,40,66,83,82,32,105,115,32,97,110,32,97,99,114,111,110,121,109,32,102,111,114,32,34,98,97,99,107,115,108,97,115,104,32,82,34,46,41,32,84,104,105,115,32,99,97,110,32,98,101,32,109,97,100,101,32,116,104,101,32,100,101,102,97,117,108,116,32,119,104,101,110,32,80,67,82,69,32,105,115,32,98,117,105,108,116,59,32,105,102,32,115,111,44,32,116,104,101,32,111,116,104,101,114,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,114,101,113,117,101,115,116,101,100,32,116,104,114,111,117,103,104,32,111,112,116,105,111,110,32>>,{code,[],[<<98,115,114,95,117,110,105,99,111,100,101>>]},<<46,32,84,104,101,115,101,32,115,101,116,116,105,110,103,115,32,99,97,110,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,115,116,97,114,116,105,110,103,32,97,32,112,97,116,116,101,114,110,32,115,116,114,105,110,103,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,113,117,101,110,99,101,115,58>>]},{dl,[],[{dt,[],[<<40,42,66,83,82,95,65,78,89,67,82,76,70,41>>]},{dd,[],[<<67,82,44,32,76,70,44,32,111,114,32,67,82,76,70,32,111,110,108,121>>]},{dt,[],[<<40,42,66,83,82,95,85,78,73,67,79,68,69,41>>]},{dd,[],[<<65,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101>>]}]},{p,[],[<<84,104,101,115,101,32,111,118,101,114,114,105,100,101,32,116,104,101,32,100,101,102,97,117,108,116,32,97,110,100,32,116,104,101,32,111,112,116,105,111,110,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,116,104,101,32,99,111,109,112,105,108,105,110,103,32,102,117,110,99,116,105,111,110,44,32,98,117,116,32,116,104,101,121,32,99,97,110,32,116,104,101,109,115,101,108,118,101,115,32,98,101,32,111,118,101,114,114,105,100,100,101,110,32,98,121,32,111,112,116,105,111,110,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,97,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,115,101,32,115,112,101,99,105,97,108,32,115,101,116,116,105,110,103,115,44,32,119,104,105,99,104,32,97,114,101,32,110,111,116,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,44,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,111,110,108,121,32,97,116,32,116,104,101,32,118,101,114,121,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,44,32,97,110,100,32,116,104,97,116,32,116,104,101,121,32,109,117,115,116,32,98,101,32,105,110,32,117,112,112,101,114,32,99,97,115,101,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,111,102,32,116,104,101,109,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,32,108,97,115,116,32,111,110,101,32,105,115,32,117,115,101,100,46,32,84,104,101,121,32,99,97,110,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,97,32,99,104,97,110,103,101,32,111,102,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,59,32,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,112,97,116,116,101,114,110,32,99,97,110,32,115,116,97,114,116,32,119,105,116,104,58>>]},{pre,[],[{code,[],[<<40,42,65,78,89,41,40,42,66,83,82,95,65,78,89,67,82,76,70,41>>]}]},{p,[],[<<84,104,101,121,32,99,97,110,32,97,108,115,111,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,116,104,101,32,40,42,85,84,70,56,41,44,32,40,42,85,84,70,41,44,32,111,114,32,40,42,85,67,80,41,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,115,46,32,73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,92,82,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,117,110,114,101,99,111,103,110,105,122,101,100,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,44,32,97,110,100,32,115,111,32,109,97,116,99,104,101,115,32,116,104,101,32,108,101,116,116,101,114,32,34,82,34,32,98,121,32,100,101,102,97,117,108,116,46>>]},{p,[],[{em,[],[<<85,110,105,99,111,100,101,32,67,104,97,114,97,99,116,101,114,32,80,114,111,112,101,114,116,105,101,115>>]}]},{p,[],[<<84,104,114,101,101,32,109,111,114,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,116,32,109,97,116,99,104,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,115,112,101,99,105,102,105,99,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,97,118,97,105,108,97,98,108,101,46,32,87,104,101,110,32,105,110,32,56,45,98,105,116,32,110,111,110,45,85,84,70,45,56,32,109,111,100,101,44,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,97,114,101,32,108,105,109,105,116,101,100,32,116,111,32,116,101,115,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,60,32,50,53,54,44,32,98,117,116,32,116,104,101,121,32,100,111,32,119,111,114,107,32,105,110,32,116,104,105,115,32,109,111,100,101,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,101,120,116,114,97,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,58>>]},{dl,[],[{dt,[],[<<92,112,123>>,{em,[],[<<120,120>>]},<<125>>]},{dd,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,112,114,111,112,101,114,116,121,32>>,{em,[],[<<120,120>>]}]},{dt,[],[<<92,80,123>>,{em,[],[<<120,120>>]},<<125>>]},{dd,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,111,117,116,32,112,114,111,112,101,114,116,121,32>>,{em,[],[<<120,120>>]}]},{dt,[],[<<92,88>>]},{dd,[],[<<65,32,85,110,105,99,111,100,101,32,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114>>]}]},{p,[],[<<84,104,101,32,112,114,111,112,101,114,116,121,32,110,97,109,101,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32>>,{em,[],[<<120,120>>]},<<32,97,98,111,118,101,32,97,114,101,32,108,105,109,105,116,101,100,32,116,111,32,116,104,101,32,85,110,105,99,111,100,101,32,115,99,114,105,112,116,32,110,97,109,101,115,44,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,105,101,115,44,32,34,65,110,121,34,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,40,105,110,99,108,117,100,105,110,103,32,110,101,119,108,105,110,101,41,44,32,97,110,100,32,115,111,109,101,32,115,112,101,99,105,97,108,32,80,67,82,69,32,112,114,111,112,101,114,116,105,101,115,32,40,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41,46,32,79,116,104,101,114,32,80,101,114,108,32,112,114,111,112,101,114,116,105,101,115,44,32,115,117,99,104,32,97,115,32,34,73,110,77,117,115,105,99,97,108,83,121,109,98,111,108,115,34,44,32,97,114,101,32,99,117,114,114,101,110,116,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,67,82,69,46,32,78,111,116,105,99,101,32,116,104,97,116,32,92,80,123,65,110,121,125,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,97,110,100,32,97,108,119,97,121,115,32,99,97,117,115,101,115,32,97,32,109,97,116,99,104,32,102,97,105,108,117,114,101,46>>]},{p,[],[<<83,101,116,115,32,111,102,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,100,101,102,105,110,101,100,32,97,115,32,98,101,108,111,110,103,105,110,103,32,116,111,32,99,101,114,116,97,105,110,32,115,99,114,105,112,116,115,46,32,65,32,99,104,97,114,97,99,116,101,114,32,102,114,111,109,32,111,110,101,32,111,102,32,116,104,101,115,101,32,115,101,116,115,32,99,97,110,32,98,101,32,109,97,116,99,104,101,100,32,117,115,105,110,103,32,97,32,115,99,114,105,112,116,32,110,97,109,101,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<92,112,123,71,114,101,101,107,125,32,92,80,123,72,97,110,125>>]}]},{p,[],[<<84,104,111,115,101,32,116,104,97,116,32,97,114,101,32,110,111,116,32,112,97,114,116,32,111,102,32,97,110,32,105,100,101,110,116,105,102,105,101,100,32,115,99,114,105,112,116,32,97,114,101,32,108,117,109,112,101,100,32,116,111,103,101,116,104,101,114,32,97,115,32,34,67,111,109,109,111,110,34,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,108,105,115,116,32,111,102,32,115,99,114,105,112,116,115,58>>]},{ul,[],[{li,[],[<<65,114,97,98,105,99>>]},{li,[],[<<65,114,109,101,110,105,97,110>>]},{li,[],[<<65,118,101,115,116,97,110>>]},{li,[],[<<66,97,108,105,110,101,115,101>>]},{li,[],[<<66,97,109,117,109>>]},{li,[],[<<66,97,115,115,97,95,86,97,104>>]},{li,[],[<<66,97,116,97,107>>]},{li,[],[<<66,101,110,103,97,108,105>>]},{li,[],[<<66,111,112,111,109,111,102,111>>]},{li,[],[<<66,114,97,105,108,108,101>>]},{li,[],[<<66,117,103,105,110,101,115,101>>]},{li,[],[<<66,117,104,105,100>>]},{li,[],[<<67,97,110,97,100,105,97,110,95,65,98,111,114,105,103,105,110,97,108>>]},{li,[],[<<67,97,114,105,97,110>>]},{li,[],[<<67,97,117,99,97,115,105,97,110,95,65,108,98,97,110,105,97,110>>]},{li,[],[<<67,104,97,107,109,97>>]},{li,[],[<<67,104,97,109>>]},{li,[],[<<67,104,101,114,111,107,101,101>>]},{li,[],[<<67,111,109,109,111,110>>]},{li,[],[<<67,111,112,116,105,99>>]},{li,[],[<<67,117,110,101,105,102,111,114,109>>]},{li,[],[<<67,121,112,114,105,111,116>>]},{li,[],[<<67,121,114,105,108,108,105,99>>]},{li,[],[<<68,101,115,101,114,101,116>>]},{li,[],[<<68,101,118,97,110,97,103,97,114,105>>]},{li,[],[<<68,117,112,108,111,121,97,110>>]},{li,[],[<<69,103,121,112,116,105,97,110,95,72,105,101,114,111,103,108,121,112,104,115>>]},{li,[],[<<69,108,98,97,115,97,110>>]},{li,[],[<<69,116,104,105,111,112,105,99>>]},{li,[],[<<71,101,111,114,103,105,97,110>>]},{li,[],[<<71,108,97,103,111,108,105,116,105,99>>]},{li,[],[<<71,111,116,104,105,99>>]},{li,[],[<<71,114,97,110,116,104,97>>]},{li,[],[<<71,114,101,101,107>>]},{li,[],[<<71,117,106,97,114,97,116,105>>]},{li,[],[<<71,117,114,109,117,107,104,105>>]},{li,[],[<<72,97,110>>]},{li,[],[<<72,97,110,103,117,108>>]},{li,[],[<<72,97,110,117,110,111,111>>]},{li,[],[<<72,101,98,114,101,119>>]},{li,[],[<<72,105,114,97,103,97,110,97>>]},{li,[],[<<73,109,112,101,114,105,97,108,95,65,114,97,109,97,105,99>>]},{li,[],[<<73,110,104,101,114,105,116,101,100>>]},{li,[],[<<73,110,115,99,114,105,112,116,105,111,110,97,108,95,80,97,104,108,97,118,105>>]},{li,[],[<<73,110,115,99,114,105,112,116,105,111,110,97,108,95,80,97,114,116,104,105,97,110>>]},{li,[],[<<74,97,118,97,110,101,115,101>>]},{li,[],[<<75,97,105,116,104,105>>]},{li,[],[<<75,97,110,110,97,100,97>>]},{li,[],[<<75,97,116,97,107,97,110,97>>]},{li,[],[<<75,97,121,97,104,95,76,105>>]},{li,[],[<<75,104,97,114,111,115,104,116,104,105>>]},{li,[],[<<75,104,109,101,114>>]},{li,[],[<<75,104,111,106,107,105>>]},{li,[],[<<75,104,117,100,97,119,97,100,105>>]},{li,[],[<<76,97,111>>]},{li,[],[<<76,97,116,105,110>>]},{li,[],[<<76,101,112,99,104,97>>]},{li,[],[<<76,105,109,98,117>>]},{li,[],[<<76,105,110,101,97,114,95,65>>]},{li,[],[<<76,105,110,101,97,114,95,66>>]},{li,[],[<<76,105,115,117>>]},{li,[],[<<76,121,99,105,97,110>>]},{li,[],[<<76,121,100,105,97,110>>]},{li,[],[<<77,97,104,97,106,97,110,105>>]},{li,[],[<<77,97,108,97,121,97,108,97,109>>]},{li,[],[<<77,97,110,100,97,105,99>>]},{li,[],[<<77,97,110,105,99,104,97,101,97,110>>]},{li,[],[<<77,101,101,116,101,105,95,77,97,121,101,107>>]},{li,[],[<<77,101,110,100,101,95,75,105,107,97,107,117,105>>]},{li,[],[<<77,101,114,111,105,116,105,99,95,67,117,114,115,105,118,101>>]},{li,[],[<<77,101,114,111,105,116,105,99,95,72,105,101,114,111,103,108,121,112,104,115>>]},{li,[],[<<77,105,97,111>>]},{li,[],[<<77,111,100,105>>]},{li,[],[<<77,111,110,103,111,108,105,97,110>>]},{li,[],[<<77,114,111>>]},{li,[],[<<77,121,97,110,109,97,114>>]},{li,[],[<<78,97,98,97,116,97,101,97,110>>]},{li,[],[<<78,101,119,95,84,97,105,95,76,117,101>>]},{li,[],[<<78,107,111>>]},{li,[],[<<79,103,104,97,109>>]},{li,[],[<<79,108,95,67,104,105,107,105>>]},{li,[],[<<79,108,100,95,73,116,97,108,105,99>>]},{li,[],[<<79,108,100,95,78,111,114,116,104,95,65,114,97,98,105,97,110>>]},{li,[],[<<79,108,100,95,80,101,114,109,105,99>>]},{li,[],[<<79,108,100,95,80,101,114,115,105,97,110>>]},{li,[],[<<79,114,105,121,97>>]},{li,[],[<<79,108,100,95,83,111,117,116,104,95,65,114,97,98,105,97,110>>]},{li,[],[<<79,108,100,95,84,117,114,107,105,99>>]},{li,[],[<<79,115,109,97,110,121,97>>]},{li,[],[<<80,97,104,97,119,104,95,72,109,111,110,103>>]},{li,[],[<<80,97,108,109,121,114,101,110,101>>]},{li,[],[<<80,97,117,95,67,105,110,95,72,97,117>>]},{li,[],[<<80,104,97,103,115,95,80,97>>]},{li,[],[<<80,104,111,101,110,105,99,105,97,110>>]},{li,[],[<<80,115,97,108,116,101,114,95,80,97,104,108,97,118,105>>]},{li,[],[<<82,101,106,97,110,103>>]},{li,[],[<<82,117,110,105,99>>]},{li,[],[<<83,97,109,97,114,105,116,97,110>>]},{li,[],[<<83,97,117,114,97,115,104,116,114,97>>]},{li,[],[<<83,104,97,114,97,100,97>>]},{li,[],[<<83,104,97,118,105,97,110>>]},{li,[],[<<83,105,100,100,104,97,109>>]},{li,[],[<<83,105,110,104,97,108,97>>]},{li,[],[<<83,111,114,97,95,83,111,109,112,101,110,103>>]},{li,[],[<<83,117,110,100,97,110,101,115,101>>]},{li,[],[<<83,121,108,111,116,105,95,78,97,103,114,105>>]},{li,[],[<<83,121,114,105,97,99>>]},{li,[],[<<84,97,103,97,108,111,103>>]},{li,[],[<<84,97,103,98,97,110,119,97>>]},{li,[],[<<84,97,105,95,76,101>>]},{li,[],[<<84,97,105,95,84,104,97,109>>]},{li,[],[<<84,97,105,95,86,105,101,116>>]},{li,[],[<<84,97,107,114,105>>]},{li,[],[<<84,97,109,105,108>>]},{li,[],[<<84,101,108,117,103,117>>]},{li,[],[<<84,104,97,97,110,97>>]},{li,[],[<<84,104,97,105>>]},{li,[],[<<84,105,98,101,116,97,110>>]},{li,[],[<<84,105,102,105,110,97,103,104>>]},{li,[],[<<84,105,114,104,117,116,97>>]},{li,[],[<<85,103,97,114,105,116,105,99>>]},{li,[],[<<86,97,105>>]},{li,[],[<<87,97,114,97,110,103,95,67,105,116,105>>]},{li,[],[<<89,105>>]}]},{p,[],[<<69,97,99,104,32,99,104,97,114,97,99,116,101,114,32,104,97,115,32,101,120,97,99,116,108,121,32,111,110,101,32,85,110,105,99,111,100,101,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,121,44,32,115,112,101,99,105,102,105,101,100,32,98,121,32,97,32,116,119,111,45,108,101,116,116,101,114,32,97,99,114,111,110,121,109,46,32,70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,80,101,114,108,44,32,110,101,103,97,116,105,111,110,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,105,110,99,108,117,100,105,110,103,32,97,32,99,105,114,99,117,109,102,108,101,120,32,98,101,116,119,101,101,110,32,116,104,101,32,111,112,101,110,105,110,103,32,98,114,97,99,101,32,97,110,100,32,116,104,101,32,112,114,111,112,101,114,116,121,32,110,97,109,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,92,112,123,94,76,117,125,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,92,80,123,76,117,125,46>>]},{p,[],[<<73,102,32,111,110,108,121,32,111,110,101,32,108,101,116,116,101,114,32,105,115,32,115,112,101,99,105,102,105,101,100,32,119,105,116,104,32,92,112,32,111,114,32,92,80,44,32,105,116,32,105,110,99,108,117,100,101,115,32,97,108,108,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,105,101,115,32,116,104,97,116,32,115,116,97,114,116,32,119,105,116,104,32,116,104,97,116,32,108,101,116,116,101,114,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,105,110,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,32,110,101,103,97,116,105,111,110,44,32,116,104,101,32,99,117,114,108,121,32,98,114,97,99,107,101,116,115,32,105,110,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,97,114,101,32,111,112,116,105,111,110,97,108,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,116,119,111,32,101,120,97,109,112,108,101,115,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,58>>]},{pre,[],[{code,[],[<<92,112,123,76,125,10,92,112,76>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,121,32,99,111,100,101,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,58>>]},{dl,[],[{dt,[],[<<67>>]},{dd,[],[<<79,116,104,101,114>>]},{dt,[],[<<67,99>>]},{dd,[],[<<67,111,110,116,114,111,108>>]},{dt,[],[<<67,102>>]},{dd,[],[<<70,111,114,109,97,116>>]},{dt,[],[<<67,110>>]},{dd,[],[<<85,110,97,115,115,105,103,110,101,100>>]},{dt,[],[<<67,111>>]},{dd,[],[<<80,114,105,118,97,116,101,32,117,115,101>>]},{dt,[],[<<67,115>>]},{dd,[],[<<83,117,114,114,111,103,97,116,101>>]},{dt,[],[<<76>>]},{dd,[],[<<76,101,116,116,101,114>>]},{dt,[],[<<76,108>>]},{dd,[],[<<76,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114>>]},{dt,[],[<<76,109>>]},{dd,[],[<<77,111,100,105,102,105,101,114,32,108,101,116,116,101,114>>]},{dt,[],[<<76,111>>]},{dd,[],[<<79,116,104,101,114,32,108,101,116,116,101,114>>]},{dt,[],[<<76,116>>]},{dd,[],[<<84,105,116,108,101,32,99,97,115,101,32,108,101,116,116,101,114>>]},{dt,[],[<<76,117>>]},{dd,[],[<<85,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114>>]},{dt,[],[<<77>>]},{dd,[],[<<77,97,114,107>>]},{dt,[],[<<77,99>>]},{dd,[],[<<83,112,97,99,105,110,103,32,109,97,114,107>>]},{dt,[],[<<77,101>>]},{dd,[],[<<69,110,99,108,111,115,105,110,103,32,109,97,114,107>>]},{dt,[],[<<77,110>>]},{dd,[],[<<78,111,110,45,115,112,97,99,105,110,103,32,109,97,114,107>>]},{dt,[],[<<78>>]},{dd,[],[<<78,117,109,98,101,114>>]},{dt,[],[<<78,100>>]},{dd,[],[<<68,101,99,105,109,97,108,32,110,117,109,98,101,114>>]},{dt,[],[<<78,108>>]},{dd,[],[<<76,101,116,116,101,114,32,110,117,109,98,101,114>>]},{dt,[],[<<78,111>>]},{dd,[],[<<79,116,104,101,114,32,110,117,109,98,101,114>>]},{dt,[],[<<80>>]},{dd,[],[<<80,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,99>>]},{dd,[],[<<67,111,110,110,101,99,116,111,114,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,100>>]},{dd,[],[<<68,97,115,104,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,101>>]},{dd,[],[<<67,108,111,115,101,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,102>>]},{dd,[],[<<70,105,110,97,108,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,105>>]},{dd,[],[<<73,110,105,116,105,97,108,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,111>>]},{dd,[],[<<79,116,104,101,114,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,115>>]},{dd,[],[<<79,112,101,110,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<83>>]},{dd,[],[<<83,121,109,98,111,108>>]},{dt,[],[<<83,99>>]},{dd,[],[<<67,117,114,114,101,110,99,121,32,115,121,109,98,111,108>>]},{dt,[],[<<83,107>>]},{dd,[],[<<77,111,100,105,102,105,101,114,32,115,121,109,98,111,108>>]},{dt,[],[<<83,109>>]},{dd,[],[<<77,97,116,104,101,109,97,116,105,99,97,108,32,115,121,109,98,111,108>>]},{dt,[],[<<83,111>>]},{dd,[],[<<79,116,104,101,114,32,115,121,109,98,111,108>>]},{dt,[],[<<90>>]},{dd,[],[<<83,101,112,97,114,97,116,111,114>>]},{dt,[],[<<90,108>>]},{dd,[],[<<76,105,110,101,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<90,112>>]},{dd,[],[<<80,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<90,115>>]},{dd,[],[<<83,112,97,99,101,32,115,101,112,97,114,97,116,111,114>>]}]},{p,[],[<<84,104,101,32,115,112,101,99,105,97,108,32,112,114,111,112,101,114,116,121,32,76,38,32,105,115,32,97,108,115,111,32,115,117,112,112,111,114,116,101,100,46,32,73,116,32,109,97,116,99,104,101,115,32,97,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,104,97,115,32,116,104,101,32,76,117,44,32,76,108,44,32,111,114,32,76,116,32,112,114,111,112,101,114,116,121,44,32,116,104,97,116,32,105,115,44,32,97,32,108,101,116,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,99,108,97,115,115,105,102,105,101,100,32,97,115,32,97,32,109,111,100,105,102,105,101,114,32,111,114,32,34,111,116,104,101,114,34,46>>]},{p,[],[<<84,104,101,32,67,115,32,40,83,117,114,114,111,103,97,116,101,41,32,112,114,111,112,101,114,116,121,32,97,112,112,108,105,101,115,32,111,110,108,121,32,116,111,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,85,43,68,56,48,48,32,116,111,32,85,43,68,70,70,70,46,32,83,117,99,104,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,105,110,118,97,108,105,100,32,105,110,32,85,110,105,99,111,100,101,32,115,116,114,105,110,103,115,32,97,110,100,32,115,111,32,99,97,110,110,111,116,32,98,101,32,116,101,115,116,101,100,32,98,121,32,80,67,82,69,46,32,80,101,114,108,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,32,67,115,32,112,114,111,112,101,114,116,121,46>>]},{p,[],[<<84,104,101,32,108,111,110,103,32,115,121,110,111,110,121,109,115,32,102,111,114,32,112,114,111,112,101,114,116,121,32,110,97,109,101,115,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,101,114,108,32,40,115,117,99,104,32,97,115,32,92,112,123,76,101,116,116,101,114,125,41,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,67,82,69,46,32,73,116,32,105,115,32,110,111,116,32,112,101,114,109,105,116,116,101,100,32,116,111,32,112,114,101,102,105,120,32,97,110,121,32,111,102,32,116,104,101,115,101,32,112,114,111,112,101,114,116,105,101,115,32,119,105,116,104,32,34,73,115,34,46>>]},{p,[],[<<78,111,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,85,110,105,99,111,100,101,32,116,97,98,108,101,32,104,97,115,32,116,104,101,32,67,110,32,40,117,110,97,115,115,105,103,110,101,100,41,32,112,114,111,112,101,114,116,121,46,32,84,104,105,115,32,112,114,111,112,101,114,116,121,32,105,115,32,105,110,115,116,101,97,100,32,97,115,115,117,109,101,100,32,102,111,114,32,97,110,121,32,99,111,100,101,32,112,111,105,110,116,32,116,104,97,116,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32,85,110,105,99,111,100,101,32,116,97,98,108,101,46>>]},{p,[],[<<83,112,101,99,105,102,121,105,110,103,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,115,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,92,112,123,76,117,125,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,111,110,108,121,32,117,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114,115,46,32,84,104,105,115,32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,99,117,114,114,101,110,116,32,118,101,114,115,105,111,110,115,32,111,102,32,80,101,114,108,46>>]},{p,[],[<<77,97,116,99,104,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,105,115,32,110,111,116,32,102,97,115,116,44,32,97,115,32,80,67,82,69,32,109,117,115,116,32,100,111,32,97,32,109,117,108,116,105,115,116,97,103,101,32,116,97,98,108,101,32,108,111,111,107,117,112,32,116,111,32,102,105,110,100,32,97,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,121,46,32,84,104,97,116,32,105,115,32,119,104,121,32,116,104,101,32,116,114,97,100,105,116,105,111,110,97,108,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,115,117,99,104,32,97,115,32,92,100,32,97,110,100,32,92,119,32,100,111,32,110,111,116,32,117,115,101,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,105,110,32,80,67,82,69,32,98,121,32,100,101,102,97,117,108,116,46,32,72,111,119,101,118,101,114,44,32,121,111,117,32,99,97,110,32,109,97,107,101,32,116,104,101,109,32,100,111,32,115,111,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,111,114,32,98,121,32,115,116,97,114,116,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,119,105,116,104,32,40,42,85,67,80,41,46>>]},{p,[],[{em,[],[<<69,120,116,101,110,100,101,100,32,71,114,97,112,104,101,109,101,32,67,108,117,115,116,101,114,115>>]}]},{p,[],[<<84,104,101,32,92,88,32,101,115,99,97,112,101,32,109,97,116,99,104,101,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,102,111,114,109,32,97,110,32,34,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114,34,44,32,97,110,100,32,116,114,101,97,116,115,32,116,104,101,32,115,101,113,117,101,110,99,101,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,40,115,101,101,32,98,101,108,111,119,41,46,32,85,112,32,116,111,32,97,110,100,32,105,110,99,108,117,100,105,110,103,32,114,101,108,101,97,115,101,32,56,46,51,49,44,32,80,67,82,69,32,109,97,116,99,104,101,100,32,97,110,32,101,97,114,108,105,101,114,44,32,115,105,109,112,108,101,114,32,100,101,102,105,110,105,116,105,111,110,32,116,104,97,116,32,119,97,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<40,63,62,92,80,77,92,112,77,42,41>>]},<<46,32,84,104,97,116,32,105,115,44,32,105,116,32,109,97,116,99,104,101,100,32,97,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,111,117,116,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,44,32,102,111,108,108,111,119,101,100,32,98,121,32,122,101,114,111,32,111,114,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,46,32,67,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,32,97,114,101,32,116,121,112,105,99,97,108,108,121,32,110,111,110,45,115,112,97,99,105,110,103,32,97,99,99,101,110,116,115,32,116,104,97,116,32,97,102,102,101,99,116,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,99,104,97,114,97,99,116,101,114,46>>]},{p,[],[<<84,104,105,115,32,115,105,109,112,108,101,32,100,101,102,105,110,105,116,105,111,110,32,119,97,115,32,101,120,116,101,110,100,101,100,32,105,110,32,85,110,105,99,111,100,101,32,116,111,32,105,110,99,108,117,100,101,32,109,111,114,101,32,99,111,109,112,108,105,99,97,116,101,100,32,107,105,110,100,115,32,111,102,32,99,111,109,112,111,115,105,116,101,32,99,104,97,114,97,99,116,101,114,32,98,121,32,103,105,118,105,110,103,32,101,97,99,104,32,99,104,97,114,97,99,116,101,114,32,97,32,103,114,97,112,104,101,109,101,32,98,114,101,97,107,105,110,103,32,112,114,111,112,101,114,116,121,44,32,97,110,100,32,99,114,101,97,116,105,110,103,32,114,117,108,101,115,32,116,104,97,116,32,117,115,101,32,116,104,101,115,101,32,112,114,111,112,101,114,116,105,101,115,32,116,111,32,100,101,102,105,110,101,32,116,104,101,32,98,111,117,110,100,97,114,105,101,115,32,111,102,32,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114,115,46,32,73,110,32,80,67,82,69,32,114,101,108,101,97,115,101,115,32,108,97,116,101,114,32,116,104,97,110,32,56,46,51,49,44,32,92,88,32,109,97,116,99,104,101,115,32,111,110,101,32,111,102,32,116,104,101,115,101,32,99,108,117,115,116,101,114,115,46>>]},{p,[],[<<92,88,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,97,116,32,108,101,97,115,116,32,111,110,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,110,32,105,116,32,100,101,99,105,100,101,115,32,119,104,101,116,104,101,114,32,116,111,32,97,100,100,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,117,108,101,115,32,102,111,114,32,101,110,100,105,110,103,32,97,32,99,108,117,115,116,101,114,58>>]},{ol,[],[{li,[],[{p,[],[<<69,110,100,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,101,110,100,32,98,101,116,119,101,101,110,32,67,82,32,97,110,100,32,76,70,59,32,111,116,104,101,114,119,105,115,101,32,101,110,100,32,97,102,116,101,114,32,97,110,121,32,99,111,110,116,114,111,108,32,99,104,97,114,97,99,116,101,114,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,98,114,101,97,107,32,72,97,110,103,117,108,32,40,97,32,75,111,114,101,97,110,32,115,99,114,105,112,116,41,32,115,121,108,108,97,98,108,101,32,115,101,113,117,101,110,99,101,115,46,32,72,97,110,103,117,108,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,111,102,32,102,105,118,101,32,116,121,112,101,115,58,32,76,44,32,86,44,32,84,44,32,76,86,44,32,97,110,100,32,76,86,84,46,32,65,110,32,76,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,76,44,32,86,44,32,76,86,44,32,111,114,32,76,86,84,32,99,104,97,114,97,99,116,101,114,46,32,65,110,32,76,86,32,111,114,32,86,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,86,32,111,114,32,84,32,99,104,97,114,97,99,116,101,114,46,32,65,110,32,76,86,84,32,111,114,32,84,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,102,111,108,108,111,119,101,100,32,111,110,108,121,32,98,121,32,97,32,84,32,99,104,97,114,97,99,116,101,114,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,101,110,100,32,98,101,102,111,114,101,32,101,120,116,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,111,114,32,115,112,97,99,105,110,103,32,109,97,114,107,115,46,32,67,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,32,97,108,119,97,121,115,32,104,97,118,101,32,116,104,101,32,34,101,120,116,101,110,100,34,32,103,114,97,112,104,101,109,101,32,98,114,101,97,107,105,110,103,32,112,114,111,112,101,114,116,121,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,101,110,100,32,97,102,116,101,114,32,112,114,101,112,101,110,100,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},{li,[],[{p,[],[<<79,116,104,101,114,119,105,115,101,44,32,101,110,100,32,116,104,101,32,99,108,117,115,116,101,114,46>>]}]}]},{p,[],[{em,[],[<<80,67,82,69,32,65,100,100,105,116,105,111,110,97,108,32,80,114,111,112,101,114,116,105,101,115>>]}]},{p,[],[<<73,110,32,97,100,100,105,116,105,111,110,32,116,111,32,116,104,101,32,115,116,97,110,100,97,114,100,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,44,32,80,67,82,69,32,115,117,112,112,111,114,116,115,32,102,111,117,114,32,109,111,114,101,32,116,104,97,116,32,109,97,107,101,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,99,111,110,118,101,114,116,32,116,114,97,100,105,116,105,111,110,97,108,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,44,32,115,117,99,104,32,97,115,32,92,119,32,97,110,100,32,92,115,32,116,111,32,117,115,101,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,46,32,80,67,82,69,32,117,115,101,115,32,116,104,101,115,101,32,110,111,110,45,115,116,97,110,100,97,114,100,44,32,110,111,110,45,80,101,114,108,32,112,114,111,112,101,114,116,105,101,115,32,105,110,116,101,114,110,97,108,108,121,32,119,104,101,110,32,116,104,101,32>>,{code,[],[<<117,99,112>>]},<<32,111,112,116,105,111,110,32,105,115,32,112,97,115,115,101,100,46,32,72,111,119,101,118,101,114,44,32,116,104,101,121,32,99,97,110,32,97,108,115,111,32,98,101,32,117,115,101,100,32,101,120,112,108,105,99,105,116,108,121,46,32,84,104,101,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<88,97,110>>]},{dd,[],[{p,[],[<<65,110,121,32,97,108,112,104,97,110,117,109,101,114,105,99,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,101,105,116,104,101,114,32,116,104,101,32,76,32,40,108,101,116,116,101,114,41,32,111,114,32,116,104,101,32,78,32,40,110,117,109,98,101,114,41,32,112,114,111,112,101,114,116,121,46>>]}]},{dt,[],[<<88,112,115>>]},{dd,[],[{p,[],[<<65,110,121,32,80,111,115,105,120,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,97,98,44,32,108,105,110,101,32,102,101,101,100,44,32,118,101,114,116,105,99,97,108,32,116,97,98,44,32,102,111,114,109,32,102,101,101,100,44,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,44,32,97,110,100,32,97,110,121,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,104,97,115,32,116,104,101,32,90,32,40,115,101,112,97,114,97,116,111,114,41,32,112,114,111,112,101,114,116,121,46>>]}]},{dt,[],[<<88,115,112>>]},{dd,[],[{p,[],[<<65,110,121,32,80,101,114,108,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,97,115,32,88,112,115,44,32,101,120,99,101,112,116,32,116,104,97,116,32,118,101,114,116,105,99,97,108,32,116,97,98,32,105,115,32,101,120,99,108,117,100,101,100,46>>]}]},{dt,[],[<<88,119,100>>]},{dd,[],[{p,[],[<<65,110,121,32,80,101,114,108,32,34,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,88,97,110,44,32,112,108,117,115,32,117,110,100,101,114,115,99,111,114,101,46>>]}]}]},{p,[],[<<80,101,114,108,32,97,110,100,32,80,79,83,73,88,32,115,112,97,99,101,32,97,114,101,32,110,111,119,32,116,104,101,32,115,97,109,101,46,32,80,101,114,108,32,97,100,100,101,100,32,86,84,32,116,111,32,105,116,115,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,32,115,101,116,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,32,97,110,100,32,80,67,82,69,32,99,104,97,110,103,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46>>]},{p,[],[<<88,97,110,32,109,97,116,99,104,101,115,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,101,105,116,104,101,114,32,116,104,101,32,76,32,40,108,101,116,116,101,114,41,32,111,114,32,116,104,101,32,78,32,40,110,117,109,98,101,114,41,32,112,114,111,112,101,114,116,121,46,32,88,112,115,32,109,97,116,99,104,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,97,98,44,32,108,105,110,101,102,101,101,100,44,32,118,101,114,116,105,99,97,108,32,116,97,98,44,32,102,111,114,109,32,102,101,101,100,44,32,111,114,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,44,32,97,110,100,32,97,110,121,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,104,97,115,32,116,104,101,32,90,32,40,115,101,112,97,114,97,116,111,114,41,32,112,114,111,112,101,114,116,121,46,32,88,115,112,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,88,112,115,59,32,105,116,32,117,115,101,100,32,116,111,32,101,120,99,108,117,100,101,32,118,101,114,116,105,99,97,108,32,116,97,98,44,32,102,111,114,32,80,101,114,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,44,32,98,117,116,32,80,101,114,108,32,99,104,97,110,103,101,100,44,32,97,110,100,32,115,111,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46,32,88,119,100,32,109,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,88,97,110,44,32,112,108,117,115,32,117,110,100,101,114,115,99,111,114,101,46>>]},{p,[],[<<84,104,101,114,101,32,105,115,32,97,110,111,116,104,101,114,32,110,111,110,45,115,116,97,110,100,97,114,100,32,112,114,111,112,101,114,116,121,44,32,88,117,99,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,85,110,105,118,101,114,115,97,108,32,67,104,97,114,97,99,116,101,114,32,78,97,109,101,32,105,110,32,67,43,43,32,97,110,100,32,111,116,104,101,114,32,112,114,111,103,114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,115,46,32,84,104,101,115,101,32,97,114,101,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,36,44,32,64,44,32,96,32,40,103,114,97,118,101,32,97,99,99,101,110,116,41,44,32,97,110,100,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,85,110,105,99,111,100,101,32,99,111,100,101,32,112,111,105,110,116,115,32,62,61,32,85,43,48,48,65,48,44,32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,115,117,114,114,111,103,97,116,101,115,32,85,43,68,56,48,48,32,116,111,32,85,43,68,70,70,70,46,32,78,111,116,105,99,101,32,116,104,97,116,32,109,111,115,116,32,98,97,115,101,32,40,65,83,67,73,73,41,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,101,120,99,108,117,100,101,100,46,32,40,85,110,105,118,101,114,115,97,108,32,67,104,97,114,97,99,116,101,114,32,78,97,109,101,115,32,97,114,101,32,111,102,32,116,104,101,32,102,111,114,109,32,92,117,72,72,72,72,32,111,114,32,92,85,72,72,72,72,72,72,72,72,44,32,119,104,101,114,101,32,72,32,105,115,32,97,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,88,117,99,32,112,114,111,112,101,114,116,121,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,98,117,116,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,116,104,101,121,32,114,101,112,114,101,115,101,110,116,46,41>>]},{p,[],[{em,[],[<<82,101,115,101,116,116,105,110,103,32,116,104,101,32,77,97,116,99,104,32,83,116,97,114,116>>]}]},{p,[],[<<84,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,75,32,99,97,117,115,101,115,32,97,110,121,32,112,114,101,118,105,111,117,115,108,121,32,109,97,116,99,104,101,100,32,99,104,97,114,97,99,116,101,114,115,32,110,111,116,32,116,111,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,102,105,110,97,108,32,109,97,116,99,104,101,100,32,115,101,113,117,101,110,99,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,102,111,111,98,97,114,34,44,32,98,117,116,32,114,101,112,111,114,116,115,32,116,104,97,116,32,105,116,32,104,97,115,32,109,97,116,99,104,101,100,32,34,98,97,114,34,58>>]},{pre,[],[{code,[],[<<102,111,111,92,75,98,97,114>>]}]},{p,[],[<<84,104,105,115,32,102,101,97,116,117,114,101,32,105,115,32,115,105,109,105,108,97,114,32,116,111,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,40,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,41,46,32,72,111,119,101,118,101,114,44,32,105,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,98,101,102,111,114,101,32,116,104,101,32,114,101,97,108,32,109,97,116,99,104,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,116,111,32,98,101,32,111,102,32,102,105,120,101,100,32,108,101,110,103,116,104,44,32,97,115,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,100,111,46,32,84,104,101,32,117,115,101,32,111,102,32,92,75,32,100,111,101,115,32,110,111,116,32,105,110,116,101,114,102,101,114,101,32,119,105,116,104,32,116,104,101,32,115,101,116,116,105,110,103,32,111,102,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,102,111,111,98,97,114,34,44,32,116,104,101,32,102,105,114,115,116,32,115,117,98,115,116,114,105,110,103,32,105,115,32,115,116,105,108,108,32,115,101,116,32,116,111,32,34,102,111,111,34,58>>]},{pre,[],[{code,[],[<<40,102,111,111,41,92,75,98,97,114>>]}]},{p,[],[<<80,101,114,108,32,100,111,99,117,109,101,110,116,115,32,116,104,97,116,32,116,104,101,32,117,115,101,32,111,102,32,92,75,32,119,105,116,104,105,110,32,97,115,115,101,114,116,105,111,110,115,32,105,115,32,34,110,111,116,32,119,101,108,108,32,100,101,102,105,110,101,100,34,46,32,73,110,32,80,67,82,69,44,32,92,75,32,105,115,32,97,99,116,101,100,32,117,112,111,110,32,119,104,101,110,32,105,116,32,111,99,99,117,114,115,32,105,110,115,105,100,101,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,44,32,98,117,116,32,105,115,32,105,103,110,111,114,101,100,32,105,110,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,78,111,116,101,32,116,104,97,116,32,119,104,101,110,32,97,32,112,97,116,116,101,114,110,32,115,117,99,104,32,97,115,32,40,63,61,97,98,92,75,41,32,109,97,116,99,104,101,115,44,32,116,104,101,32,114,101,112,111,114,116,101,100,32,115,116,97,114,116,32,111,102,32,116,104,101,32,109,97,116,99,104,32,99,97,110,32,98,101,32,103,114,101,97,116,101,114,32,116,104,97,110,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,109,97,116,99,104,46>>]},{p,[],[{em,[],[<<83,105,109,112,108,101,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<84,104,101,32,102,105,110,97,108,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,105,115,32,102,111,114,32,99,101,114,116,97,105,110,32,115,105,109,112,108,101,32,97,115,115,101,114,116,105,111,110,115,46,32,65,110,32,97,115,115,101,114,116,105,111,110,32,115,112,101,99,105,102,105,101,115,32,97,32,99,111,110,100,105,116,105,111,110,32,116,104,97,116,32,109,117,115,116,32,98,101,32,109,101,116,32,97,116,32,97,32,112,97,114,116,105,99,117,108,97,114,32,112,111,105,110,116,32,105,110,32,97,32,109,97,116,99,104,44,32,119,105,116,104,111,117,116,32,99,111,110,115,117,109,105,110,103,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,84,104,101,32,117,115,101,32,111,102,32,115,117,98,112,97,116,116,101,114,110,115,32,102,111,114,32,109,111,114,101,32,99,111,109,112,108,105,99,97,116,101,100,32,97,115,115,101,114,116,105,111,110,115,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,98,97,99,107,115,108,97,115,104,101,100,32,97,115,115,101,114,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[<<92,98>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,97,32,119,111,114,100,32,98,111,117,110,100,97,114,121,46>>]},{dt,[],[<<92,66>>]},{dd,[],[<<77,97,116,99,104,101,115,32,119,104,101,110,32,110,111,116,32,97,116,32,97,32,119,111,114,100,32,98,111,117,110,100,97,114,121,46>>]},{dt,[],[<<92,65>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46>>]},{dt,[],[<<92,90>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,97,110,100,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46>>]},{dt,[],[<<92,122>>]},{dd,[],[<<77,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46>>]},{dt,[],[<<92,71>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46>>]}]},{p,[],[<<73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,92,98,32,104,97,115,32,97,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,59,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,98,97,99,107,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,73,102,32,97,110,121,32,111,116,104,101,114,32,111,102,32,116,104,101,115,101,32,97,115,115,101,114,116,105,111,110,115,32,97,112,112,101,97,114,115,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,98,121,32,100,101,102,97,117,108,116,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,92,66,32,109,97,116,99,104,101,115,32,116,104,101,32,108,101,116,116,101,114,32,66,41,46>>]},{p,[],[<<65,32,119,111,114,100,32,98,111,117,110,100,97,114,121,32,105,115,32,97,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,119,104,101,114,101,32,116,104,101,32,99,117,114,114,101,110,116,32,99,104,97,114,97,99,116,101,114,32,97,110,100,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,104,97,114,97,99,116,101,114,32,100,111,32,110,111,116,32,98,111,116,104,32,109,97,116,99,104,32,92,119,32,111,114,32,92,87,32,40,116,104,97,116,32,105,115,44,32,111,110,101,32,109,97,116,99,104,101,115,32,92,119,32,97,110,100,32,116,104,101,32,111,116,104,101,114,32,109,97,116,99,104,101,115,32,92,87,41,44,32,111,114,32,116,104,101,32,115,116,97,114,116,32,111,114,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,105,102,32,116,104,101,32,102,105,114,115,116,32,111,114,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,32,109,97,116,99,104,101,115,32,92,119,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,73,110,32,85,84,70,32,109,111,100,101,44,32,116,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,92,119,32,97,110,100,32,92,87,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<46,32,87,104,101,110,32,116,104,105,115,32,105,115,32,100,111,110,101,44,32,105,116,32,97,108,115,111,32,97,102,102,101,99,116,115,32,92,98,32,97,110,100,32,92,66,46,32,80,67,82,69,32,97,110,100,32,80,101,114,108,32,100,111,32,110,111,116,32,104,97,118,101,32,97,32,115,101,112,97,114,97,116,101,32,34,115,116,97,114,116,32,111,102,32,119,111,114,100,34,32,111,114,32,34,101,110,100,32,111,102,32,119,111,114,100,34,32,109,101,116,97,115,101,113,117,101,110,99,101,46,32,72,111,119,101,118,101,114,44,32,119,104,97,116,101,118,101,114,32,102,111,108,108,111,119,115,32,92,98,32,110,111,114,109,97,108,108,121,32,100,101,116,101,114,109,105,110,101,115,32,119,104,105,99,104,32,105,116,32,105,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,114,97,103,109,101,110,116,32,92,98,97,32,109,97,116,99,104,101,115,32,34,97,34,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,119,111,114,100,46>>]},{p,[],[<<84,104,101,32,92,65,44,32,92,90,44,32,97,110,100,32,92,122,32,97,115,115,101,114,116,105,111,110,115,32,100,105,102,102,101,114,32,102,114,111,109,32,116,104,101,32,116,114,97,100,105,116,105,111,110,97,108,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,40,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41,32,105,110,32,116,104,97,116,32,116,104,101,121,32,111,110,108,121,32,101,118,101,114,32,109,97,116,99,104,32,97,116,32,116,104,101,32,118,101,114,121,32,115,116,97,114,116,32,97,110,100,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,119,104,97,116,101,118,101,114,32,111,112,116,105,111,110,115,32,97,114,101,32,115,101,116,46,32,84,104,117,115,44,32,116,104,101,121,32,97,114,101,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,46,32,84,104,101,115,101,32,116,104,114,101,101,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,32,110,111,116,32,97,102,102,101,99,116,101,100,32,98,121,32,111,112,116,105,111,110,115,32>>,{code,[],[<<110,111,116,98,111,108>>]},<<32,111,114,32>>,{code,[],[<<110,111,116,101,111,108>>]},<<44,32,119,104,105,99,104,32,97,102,102,101,99,116,32,111,110,108,121,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,46,32,72,111,119,101,118,101,114,44,32,105,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,105,115,32,110,111,110,45,122,101,114,111,44,32,105,110,100,105,99,97,116,105,110,103,32,116,104,97,116,32,109,97,116,99,104,105,110,103,32,105,115,32,116,111,32,115,116,97,114,116,32,97,116,32,97,32,112,111,105,110,116,32,111,116,104,101,114,32,116,104,97,110,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,92,65,32,99,97,110,32,110,101,118,101,114,32,109,97,116,99,104,46,32,84,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,101,116,119,101,101,110,32,92,90,32,97,110,100,32,92,122,32,105,115,32,116,104,97,116,32,92,90,32,109,97,116,99,104,101,115,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,97,110,100,32,97,116,32,116,104,101,32,118,101,114,121,32,101,110,100,44,32,119,104,105,108,101,32,92,122,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,46>>]},{p,[],[<<84,104,101,32,92,71,32,97,115,115,101,114,116,105,111,110,32,105,115,32,116,114,117,101,32,111,110,108,121,32,119,104,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,32,105,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,112,111,105,110,116,32,111,102,32,116,104,101,32,109,97,116,99,104,44,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<46,32,73,116,32,100,105,102,102,101,114,115,32,102,114,111,109,32,92,65,32,119,104,101,110,32,116,104,101,32,118,97,108,117,101,32,111,102,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,105,115,32,110,111,110,45,122,101,114,111,46,32,66,121,32,99,97,108,108,105,110,103,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,119,105,116,104,32,97,112,112,114,111,112,114,105,97,116,101,32,97,114,103,117,109,101,110,116,115,44,32,121,111,117,32,99,97,110,32,109,105,109,105,99,32,116,104,101,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,103>>]},<<44,32,97,110,100,32,105,116,32,105,115,32,105,110,32,116,104,105,115,32,107,105,110,100,32,111,102,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,119,104,101,114,101,32,92,71,32,99,97,110,32,98,101,32,117,115,101,102,117,108,46>>]},{p,[],[<<78,111,116,105,99,101,44,32,104,111,119,101,118,101,114,44,32,116,104,97,116,32,116,104,101,32,80,67,82,69,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,111,102,32,92,71,44,32,97,115,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,44,32,105,115,32,115,117,98,116,108,121,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,80,101,114,108,44,32,119,104,105,99,104,32,100,101,102,105,110,101,115,32,105,116,32,97,115,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,112,114,101,118,105,111,117,115,32,109,97,116,99,104,46,32,73,110,32,80,101,114,108,44,32,116,104,101,115,101,32,99,97,110,32,98,101,32,100,105,102,102,101,114,101,110,116,32,119,104,101,110,32,116,104,101,32,112,114,101,118,105,111,117,115,108,121,32,109,97,116,99,104,101,100,32,115,116,114,105,110,103,32,119,97,115,32,101,109,112,116,121,46,32,65,115,32,80,67,82,69,32,100,111,101,115,32,111,110,108,121,32,111,110,101,32,109,97,116,99,104,32,97,116,32,97,32,116,105,109,101,44,32,105,116,32,99,97,110,110,111,116,32,114,101,112,114,111,100,117,99,101,32,116,104,105,115,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<73,102,32,97,108,108,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,111,102,32,97,32,112,97,116,116,101,114,110,32,98,101,103,105,110,32,119,105,116,104,32,92,71,44,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,97,110,99,104,111,114,101,100,32,116,111,32,116,104,101,32,115,116,97,114,116,105,110,103,32,109,97,116,99,104,32,112,111,115,105,116,105,111,110,44,32,97,110,100,32,116,104,101,32,34,97,110,99,104,111,114,101,100,34,32,102,108,97,103,32,105,115,32,115,101,116,32,105,110,32,116,104,101,32,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{a,[{id,<<115,101,99,116,52>>}],[]},{h2,[],[<<67,105,114,99,117,109,102,108,101,120,32,97,110,100,32,68,111,108,108,97,114>>]},{p,[],[<<84,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,122,101,114,111,45,119,105,100,116,104,32,97,115,115,101,114,116,105,111,110,115,46,32,84,104,97,116,32,105,115,44,32,116,104,101,121,32,116,101,115,116,32,102,111,114,32,97,32,112,97,114,116,105,99,117,108,97,114,32,99,111,110,100,105,116,105,111,110,32,116,111,32,98,101,32,116,114,117,101,32,119,105,116,104,111,117,116,32,99,111,110,115,117,109,105,110,103,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,105,110,32,116,104,101,32,100,101,102,97,117,108,116,32,109,97,116,99,104,105,110,103,32,109,111,100,101,44,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,99,104,97,114,97,99,116,101,114,32,105,115,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,32,111,110,108,121,32,105,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,73,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,105,115,32,110,111,110,45,122,101,114,111,44,32,99,105,114,99,117,109,102,108,101,120,32,99,97,110,32,110,101,118,101,114,32,109,97,116,99,104,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,117,110,115,101,116,46,32,73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,99,105,114,99,117,109,102,108,101,120,32,104,97,115,32,97,110,32,101,110,116,105,114,101,108,121,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,32,40,115,101,101,32,98,101,108,111,119,41,46>>]},{p,[],[<<67,105,114,99,117,109,102,108,101,120,32,110,101,101,100,115,32,110,111,116,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,102,32,115,111,109,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,105,110,118,111,108,118,101,100,44,32,98,117,116,32,105,116,32,105,115,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,116,104,105,110,103,32,105,110,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,119,104,105,99,104,32,105,116,32,97,112,112,101,97,114,115,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,101,118,101,114,32,116,111,32,109,97,116,99,104,32,116,104,97,116,32,98,114,97,110,99,104,46,32,73,102,32,97,108,108,32,112,111,115,115,105,98,108,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,115,116,97,114,116,32,119,105,116,104,32,97,32,99,105,114,99,117,109,102,108,101,120,44,32,116,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,99,111,110,115,116,114,97,105,110,101,100,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,105,116,32,105,115,32,115,97,105,100,32,116,111,32,98,101,32,97,110,32,34,97,110,99,104,111,114,101,100,34,32,112,97,116,116,101,114,110,46,32,40,84,104,101,114,101,32,97,114,101,32,97,108,115,111,32,111,116,104,101,114,32,99,111,110,115,116,114,117,99,116,115,32,116,104,97,116,32,99,97,110,32,99,97,117,115,101,32,97,32,112,97,116,116,101,114,110,32,116,111,32,98,101,32,97,110,99,104,111,114,101,100,46,41>>]},{p,[],[<<84,104,101,32,100,111,108,108,97,114,32,99,104,97,114,97,99,116,101,114,32,105,115,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,32,111,110,108,121,32,105,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,111,114,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,40,98,121,32,100,101,102,97,117,108,116,41,46,32,78,111,116,105,99,101,32,104,111,119,101,118,101,114,32,116,104,97,116,32,105,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,110,101,119,108,105,110,101,46,32,68,111,108,108,97,114,32,110,101,101,100,115,32,110,111,116,32,116,111,32,98,101,32,116,104,101,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,102,32,115,111,109,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,105,110,118,111,108,118,101,100,44,32,98,117,116,32,105,116,32,105,115,32,116,111,32,98,101,32,116,104,101,32,108,97,115,116,32,105,116,101,109,32,105,110,32,97,110,121,32,98,114,97,110,99,104,32,105,110,32,119,104,105,99,104,32,105,116,32,97,112,112,101,97,114,115,46,32,68,111,108,108,97,114,32,104,97,115,32,110,111,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46>>]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,100,111,108,108,97,114,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,105,116,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,118,101,114,121,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]},<<32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46,32,84,104,105,115,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,92,90,32,97,115,115,101,114,116,105,111,110,46>>]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,99,104,97,110,103,101,100,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46,32,87,104,101,110,32,116,104,105,115,32,105,115,32,116,104,101,32,99,97,115,101,44,32,97,32,99,105,114,99,117,109,102,108,101,120,32,109,97,116,99,104,101,115,32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,105,110,116,101,114,110,97,108,32,110,101,119,108,105,110,101,115,32,97,110,100,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,73,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,97,102,116,101,114,32,97,32,110,101,119,108,105,110,101,32,116,104,97,116,32,101,110,100,115,32,116,104,101,32,115,116,114,105,110,103,46,32,65,32,100,111,108,108,97,114,32,109,97,116,99,104,101,115,32,98,101,102,111,114,101,32,97,110,121,32,110,101,119,108,105,110,101,115,32,105,110,32,116,104,101,32,115,116,114,105,110,103,44,32,97,110,100,32,97,116,32,116,104,101,32,118,101,114,121,32,101,110,100,44,32,119,104,101,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46,32,87,104,101,110,32,110,101,119,108,105,110,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,44,32,105,115,111,108,97,116,101,100,32,67,82,32,97,110,100,32,76,70,32,99,104,97,114,97,99,116,101,114,115,32,100,111,32,110,111,116,32,105,110,100,105,99,97,116,101,32,110,101,119,108,105,110,101,115,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,112,97,116,116,101,114,110,32,47,94,97,98,99,36,47,32,109,97,116,99,104,101,115,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,34,100,101,102,92,110,97,98,99,34,32,40,119,104,101,114,101,32,92,110,32,114,101,112,114,101,115,101,110,116,115,32,97,32,110,101,119,108,105,110,101,41,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,44,32,98,117,116,32,110,111,116,32,111,116,104,101,114,119,105,115,101,46,32,83,111,44,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,97,110,99,104,111,114,101,100,32,105,110,32,115,105,110,103,108,101,45,108,105,110,101,32,109,111,100,101,32,98,101,99,97,117,115,101,32,97,108,108,32,98,114,97,110,99,104,101,115,32,115,116,97,114,116,32,119,105,116,104,32,94,32,97,114,101,32,110,111,116,32,97,110,99,104,111,114,101,100,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,44,32,97,110,100,32,97,32,109,97,116,99,104,32,102,111,114,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,112,111,115,115,105,98,108,101,32,119,104,101,110,32,97,114,103,117,109,101,110,116,32>>,{em,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,105,115,32,110,111,110,45,122,101,114,111,46,32,79,112,116,105,111,110,32>>,{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]},<<32,105,115,32,105,103,110,111,114,101,100,32,105,102,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,115,101,113,117,101,110,99,101,115,32,92,65,44,32,92,90,44,32,97,110,100,32,92,122,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,97,116,99,104,32,116,104,101,32,115,116,97,114,116,32,97,110,100,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,110,32,98,111,116,104,32,109,111,100,101,115,46,32,73,102,32,97,108,108,32,98,114,97,110,99,104,101,115,32,111,102,32,97,32,112,97,116,116,101,114,110,32,115,116,97,114,116,32,119,105,116,104,32,92,65,44,32,105,116,32,105,115,32,97,108,119,97,121,115,32,97,110,99,104,111,114,101,100,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46>>]},{a,[{id,<<115,101,99,116,53>>}],[]},{h2,[],[<<70,117,108,108,32,83,116,111,112,32,40,80,101,114,105,111,100,44,32,68,111,116,41,32,97,110,100,32,92,78>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,32,100,111,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,101,120,99,101,112,116,32,40,98,121,32,100,101,102,97,117,108,116,41,32,97,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,115,105,103,110,105,102,105,101,115,32,116,104,101,32,101,110,100,32,111,102,32,97,32,108,105,110,101,46>>]},{p,[],[<<87,104,101,110,32,97,32,108,105,110,101,32,101,110,100,105,110,103,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,44,32,100,111,116,32,110,101,118,101,114,32,109,97,116,99,104,101,115,32,116,104,97,116,32,99,104,97,114,97,99,116,101,114,46,32,87,104,101,110,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,32,105,115,32,117,115,101,100,44,32,100,111,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,67,82,32,105,102,32,105,116,32,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,101,100,32,98,121,32,76,70,44,32,111,116,104,101,114,119,105,115,101,32,105,116,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,99,108,117,100,105,110,103,32,105,115,111,108,97,116,101,100,32,67,82,115,32,97,110,100,32,76,70,115,41,46,32,87,104,101,110,32,97,110,121,32,85,110,105,99,111,100,101,32,108,105,110,101,32,101,110,100,105,110,103,115,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,44,32,100,111,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,67,82,44,32,76,70,44,32,111,114,32,97,110,121,32,111,102,32,116,104,101,32,111,116,104,101,114,32,108,105,110,101,45,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,100,111,116,32,114,101,103,97,114,100,105,110,103,32,110,101,119,108,105,110,101,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,105,115,32,115,101,116,44,32,97,32,100,111,116,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,44,32,119,105,116,104,111,117,116,32,101,120,99,101,112,116,105,111,110,46,32,73,102,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,32,105,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,105,116,32,116,97,107,101,115,32,116,119,111,32,100,111,116,115,32,116,111,32,109,97,116,99,104,32,105,116,46>>]},{p,[],[<<84,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,100,111,116,32,105,115,32,101,110,116,105,114,101,108,121,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,116,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,44,32,116,104,101,32,111,110,108,121,32,114,101,108,97,116,105,111,110,115,104,105,112,32,105,115,32,116,104,97,116,32,98,111,116,104,32,105,110,118,111,108,118,101,32,110,101,119,108,105,110,101,115,46,32,68,111,116,32,104,97,115,32,110,111,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46>>]},{p,[],[<<84,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,78,32,98,101,104,97,118,101,115,32,108,105,107,101,32,97,32,100,111,116,44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,105,115,32,110,111,116,32,97,102,102,101,99,116,101,100,32,98,121,32,111,112,116,105,111,110,32>>,{code,[],[<<80,67,82,69,95,68,79,84,65,76,76>>]},<<46,32,84,104,97,116,32,105,115,44,32,105,116,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,101,120,99,101,112,116,32,111,110,101,32,116,104,97,116,32,115,105,103,110,105,102,105,101,115,32,116,104,101,32,101,110,100,32,111,102,32,97,32,108,105,110,101,46,32,80,101,114,108,32,97,108,115,111,32,117,115,101,115,32,92,78,32,116,111,32,109,97,116,99,104,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,110,97,109,101,32,98,117,116,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,105,115,46>>]},{a,[{id,<<115,101,99,116,54>>}],[]},{h2,[],[<<77,97,116,99,104,105,110,103,32,97,32,83,105,110,103,108,101,32,68,97,116,97,32,85,110,105,116>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,67,32,109,97,116,99,104,101,115,32,97,110,121,32,100,97,116,97,32,117,110,105,116,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32,97,32,85,84,70,32,109,111,100,101,32,105,115,32,115,101,116,46,32,79,110,101,32,100,97,116,97,32,117,110,105,116,32,105,115,32,111,110,101,32,98,121,116,101,46,32,85,110,108,105,107,101,32,97,32,100,111,116,44,32,92,67,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,108,105,110,101,45,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,102,101,97,116,117,114,101,32,105,115,32,112,114,111,118,105,100,101,100,32,105,110,32,80,101,114,108,32,116,111,32,109,97,116,99,104,32,105,110,100,105,118,105,100,117,97,108,32,98,121,116,101,115,32,105,110,32,85,84,70,45,56,32,109,111,100,101,44,32,98,117,116,32,105,116,32,105,115,32,117,110,99,108,101,97,114,32,104,111,119,32,105,116,32,99,97,110,32,117,115,101,102,117,108,108,121,32,98,101,32,117,115,101,100,46,32,65,115,32,92,67,32,98,114,101,97,107,115,32,117,112,32,99,104,97,114,97,99,116,101,114,115,32,105,110,116,111,32,105,110,100,105,118,105,100,117,97,108,32,100,97,116,97,32,117,110,105,116,115,44,32,109,97,116,99,104,105,110,103,32,111,110,101,32,117,110,105,116,32,119,105,116,104,32,92,67,32,105,110,32,97,32,85,84,70,32,109,111,100,101,32,109,101,97,110,115,32,116,104,97,116,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,115,116,114,105,110,103,32,99,97,110,32,115,116,97,114,116,32,119,105,116,104,32,97,32,109,97,108,102,111,114,109,101,100,32,85,84,70,32,99,104,97,114,97,99,116,101,114,46,32,84,104,105,115,32,104,97,115,32,117,110,100,101,102,105,110,101,100,32,114,101,115,117,108,116,115,44,32,97,115,32,80,67,82,69,32,97,115,115,117,109,101,115,32,116,104,97,116,32,105,116,32,100,101,97,108,115,32,119,105,116,104,32,118,97,108,105,100,32,85,84,70,32,115,116,114,105,110,103,115,46>>]},{p,[],[<<80,67,82,69,32,100,111,101,115,32,110,111,116,32,97,108,108,111,119,32,92,67,32,116,111,32,97,112,112,101,97,114,32,105,110,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,40,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,41,32,105,110,32,97,32,85,84,70,32,109,111,100,101,44,32,97,115,32,116,104,105,115,32,119,111,117,108,100,32,109,97,107,101,32,105,116,32,105,109,112,111,115,115,105,98,108,101,32,116,111,32,99,97,108,99,117,108,97,116,101,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,108,111,111,107,98,101,104,105,110,100,46>>]},{p,[],[<<84,104,101,32,92,67,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,105,115,32,98,101,115,116,32,97,118,111,105,100,101,100,46,32,72,111,119,101,118,101,114,44,32,111,110,101,32,119,97,121,32,111,102,32,117,115,105,110,103,32,105,116,32,116,104,97,116,32,97,118,111,105,100,115,32,116,104,101,32,112,114,111,98,108,101,109,32,111,102,32,109,97,108,102,111,114,109,101,100,32,85,84,70,32,99,104,97,114,97,99,116,101,114,115,32,105,115,32,116,111,32,117,115,101,32,97,32,108,111,111,107,97,104,101,97,100,32,116,111,32,99,104,101,99,107,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,44,32,97,115,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,97,32,85,84,70,45,56,32,115,116,114,105,110,103,32,40,105,103,110,111,114,101,32,119,104,105,116,101,115,112,97,99,101,32,97,110,100,32,108,105,110,101,32,98,114,101,97,107,115,41,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<40,63,124,32,40,63,61,91,92,120,48,48,45,92,120,55,102,93,41,40,92,67,41,32,124,10,32,32,32,32,40,63,61,91,92,120,56,48,45,92,120,123,55,102,102,125,93,41,40,92,67,41,40,92,67,41,32,124,10,32,32,32,32,40,63,61,91,92,120,123,56,48,48,125,45,92,120,123,102,102,102,102,125,93,41,40,92,67,41,40,92,67,41,40,92,67,41,32,124,10,32,32,32,32,40,63,61,91,92,120,123,49,48,48,48,48,125,45,92,120,123,49,102,102,102,102,102,125,93,41,40,92,67,41,40,92,67,41,40,92,67,41,40,92,67,41,41>>]}]},{p,[],[<<65,32,103,114,111,117,112,32,116,104,97,116,32,115,116,97,114,116,115,32,119,105,116,104,32,40,63,124,32,114,101,115,101,116,115,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,110,117,109,98,101,114,115,32,105,110,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]},<<41,46,32,84,104,101,32,97,115,115,101,114,116,105,111,110,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,101,97,99,104,32,98,114,97,110,99,104,32,99,104,101,99,107,32,116,104,101,32,110,101,120,116,32,85,84,70,45,56,32,99,104,97,114,97,99,116,101,114,32,102,111,114,32,118,97,108,117,101,115,32,119,104,111,115,101,32,101,110,99,111,100,105,110,103,32,117,115,101,115,32,49,44,32,50,44,32,51,44,32,111,114,32,52,32,98,121,116,101,115,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,84,104,101,32,105,110,100,105,118,105,100,117,97,108,32,98,121,116,101,115,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,97,114,101,32,116,104,101,110,32,99,97,112,116,117,114,101,100,32,98,121,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,110,117,109,98,101,114,32,111,102,32,103,114,111,117,112,115,46>>]},{a,[{id,<<115,101,99,116,55>>}],[]},{h2,[],[<<83,113,117,97,114,101,32,66,114,97,99,107,101,116,115,32,97,110,100,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]},{p,[],[<<65,110,32,111,112,101,110,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,105,110,116,114,111,100,117,99,101,115,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,101,114,109,105,110,97,116,101,100,32,98,121,32,97,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,46,32,65,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,111,110,32,105,116,115,32,111,119,110,32,105,115,32,110,111,116,32,115,112,101,99,105,97,108,32,98,121,32,100,101,102,97,117,108,116,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<80,67,82,69,95,74,65,86,65,83,67,82,73,80,84,95,67,79,77,80,65,84>>]},<<32,105,115,32,115,101,116,44,32,97,32,108,111,110,101,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,99,97,117,115,101,115,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,46,32,73,102,32,97,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,105,115,32,114,101,113,117,105,114,101,100,32,97,115,32,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,99,108,97,115,115,44,32,105,116,32,105,115,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,99,108,97,115,115,32,40,97,102,116,101,114,32,97,110,32,105,110,105,116,105,97,108,32,99,105,114,99,117,109,102,108,101,120,44,32,105,102,32,112,114,101,115,101,110,116,41,32,111,114,32,101,115,99,97,112,101,100,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,46>>]},{p,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,73,110,32,97,32,85,84,70,32,109,111,100,101,44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,100,97,116,97,32,117,110,105,116,32,108,111,110,103,46,32,65,32,109,97,116,99,104,101,100,32,99,104,97,114,97,99,116,101,114,32,109,117,115,116,32,98,101,32,105,110,32,116,104,101,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,100,101,102,105,110,101,100,32,98,121,32,116,104,101,32,99,108,97,115,115,44,32,117,110,108,101,115,115,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,99,108,97,115,115,32,100,101,102,105,110,105,116,105,111,110,32,105,115,32,97,32,99,105,114,99,117,109,102,108,101,120,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,116,104,101,32,115,117,98,106,101,99,116,32,99,104,97,114,97,99,116,101,114,32,109,117,115,116,32,110,111,116,32,98,101,32,105,110,32,116,104,101,32,115,101,116,32,100,101,102,105,110,101,100,32,98,121,32,116,104,101,32,99,108,97,115,115,46,32,73,102,32,97,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,114,101,113,117,105,114,101,100,32,97,115,32,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,99,108,97,115,115,44,32,101,110,115,117,114,101,32,116,104,97,116,32,105,116,32,105,115,32,110,111,116,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,101,115,99,97,112,101,32,105,116,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32>>,{code,[],[<<91,97,101,105,111,117,93>>]},<<32,109,97,116,99,104,101,115,32,97,110,121,32,108,111,119,101,114,99,97,115,101,32,118,111,119,101,108,44,32,119,104,105,108,101,32>>,{code,[],[<<91,94,97,101,105,111,117,93>>]},<<32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,108,111,119,101,114,99,97,115,101,32,118,111,119,101,108,46,32,78,111,116,105,99,101,32,116,104,97,116,32,97,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,106,117,115,116,32,97,32,99,111,110,118,101,110,105,101,110,116,32,110,111,116,97,116,105,111,110,32,102,111,114,32,115,112,101,99,105,102,121,105,110,103,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,105,110,32,116,104,101,32,99,108,97,115,115,32,98,121,32,101,110,117,109,101,114,97,116,105,110,103,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,110,111,116,46,32,65,32,99,108,97,115,115,32,116,104,97,116,32,115,116,97,114,116,115,32,119,105,116,104,32,97,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,110,111,116,32,97,110,32,97,115,115,101,114,116,105,111,110,59,32,105,116,32,115,116,105,108,108,32,99,111,110,115,117,109,101,115,32,97,32,99,104,97,114,97,99,116,101,114,32,102,114,111,109,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,110,100,32,116,104,101,114,101,102,111,114,101,32,105,116,32,102,97,105,108,115,32,105,102,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,105,110,116,101,114,32,105,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,46>>]},{p,[],[<<73,110,32,85,84,70,45,56,32,109,111,100,101,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,32,40,48,120,102,102,102,102,41,32,99,97,110,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,32,99,108,97,115,115,32,97,115,32,97,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,32,111,102,32,100,97,116,97,32,117,110,105,116,115,44,32,111,114,32,98,121,32,117,115,105,110,103,32,116,104,101,32,92,120,123,32,101,115,99,97,112,105,110,103,32,109,101,99,104,97,110,105,115,109,46>>]},{p,[],[<<87,104,101,110,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,115,101,116,44,32,97,110,121,32,108,101,116,116,101,114,115,32,105,110,32,97,32,99,108,97,115,115,32,114,101,112,114,101,115,101,110,116,32,98,111,116,104,32,116,104,101,105,114,32,117,112,112,101,114,99,97,115,101,32,97,110,100,32,108,111,119,101,114,99,97,115,101,32,118,101,114,115,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,32,99,97,115,101,108,101,115,115,32>>,{code,[],[<<91,97,101,105,111,117,93>>]},<<32,109,97,116,99,104,101,115,32,34,65,34,32,97,110,100,32,34,97,34,44,32,97,110,100,32,97,32,99,97,115,101,108,101,115,115,32>>,{code,[],[<<91,94,97,101,105,111,117,93>>]},<<32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,34,65,34,44,32,98,117,116,32,97,32,99,97,115,101,102,117,108,32,118,101,114,115,105,111,110,32,119,111,117,108,100,46,32,73,110,32,97,32,85,84,70,32,109,111,100,101,44,32,80,67,82,69,32,97,108,119,97,121,115,32,117,110,100,101,114,115,116,97,110,100,115,32,116,104,101,32,99,111,110,99,101,112,116,32,111,102,32,99,97,115,101,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,118,97,108,117,101,115,32,97,114,101,32,60,32,50,53,54,44,32,115,111,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,97,108,119,97,121,115,32,112,111,115,115,105,98,108,101,46,32,70,111,114,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,104,105,103,104,101,114,32,118,97,108,117,101,115,44,32,116,104,101,32,99,111,110,99,101,112,116,32,111,102,32,99,97,115,101,32,105,115,32,115,117,112,112,111,114,116,101,100,32,111,110,108,121,32,105,102,32,80,67,82,69,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,46,32,73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,110,32,97,32,85,84,70,32,109,111,100,101,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,62,61,44,32,101,110,115,117,114,101,32,116,104,97,116,32,80,67,82,69,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,32,97,110,100,32,119,105,116,104,32,85,84,70,32,115,117,112,112,111,114,116,46>>]},{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,99,97,110,32,105,110,100,105,99,97,116,101,32,108,105,110,101,32,98,114,101,97,107,115,32,97,114,101,32,110,101,118,101,114,32,116,114,101,97,116,101,100,32,105,110,32,97,110,121,32,115,112,101,99,105,97,108,32,119,97,121,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,44,32,119,104,97,116,101,118,101,114,32,108,105,110,101,45,101,110,100,105,110,103,32,115,101,113,117,101,110,99,101,32,105,115,32,105,110,32,117,115,101,44,32,97,110,100,32,119,104,97,116,101,118,101,114,32,115,101,116,116,105,110,103,32,111,102,32,111,112,116,105,111,110,115,32>>,{code,[],[<<80,67,82,69,95,68,79,84,65,76,76>>]},<<32,97,110,100,32>>,{code,[],[<<80,67,82,69,95,77,85,76,84,73,76,73,78,69>>]},<<32,105,115,32,117,115,101,100,46,32,65,32,99,108,97,115,115,32,115,117,99,104,32,97,115,32,91,94,97,93,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,111,110,101,32,111,102,32,116,104,101,115,101,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,109,105,110,117,115,32,40,104,121,112,104,101,110,41,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,115,112,101,99,105,102,121,32,97,32,114,97,110,103,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,100,45,109,93,32,109,97,116,99,104,101,115,32,97,110,121,32,108,101,116,116,101,114,32,98,101,116,119,101,101,110,32,100,32,97,110,100,32,109,44,32,105,110,99,108,117,115,105,118,101,46,32,73,102,32,97,32,109,105,110,117,115,32,99,104,97,114,97,99,116,101,114,32,105,115,32,114,101,113,117,105,114,101,100,32,105,110,32,97,32,99,108,97,115,115,44,32,105,116,32,109,117,115,116,32,98,101,32,101,115,99,97,112,101,100,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,32,111,114,32,97,112,112,101,97,114,32,105,110,32,97,32,112,111,115,105,116,105,111,110,32,119,104,101,114,101,32,105,116,32,99,97,110,110,111,116,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,105,110,100,105,99,97,116,105,110,103,32,97,32,114,97,110,103,101,44,32,116,121,112,105,99,97,108,108,121,32,97,115,32,116,104,101,32,102,105,114,115,116,32,111,114,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,99,108,97,115,115,44,32,111,114,32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,97,32,114,97,110,103,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,98,45,100,45,122,93,32,109,97,116,99,104,101,115,32,108,101,116,116,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,98,32,116,111,32,100,44,32,97,32,104,121,112,104,101,110,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,122,46>>]},{p,[],[<<84,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,32,34,93,34,32,99,97,110,110,111,116,32,98,101,32,116,104,101,32,101,110,100,32,99,104,97,114,97,99,116,101,114,32,111,102,32,97,32,114,97,110,103,101,46,32,65,32,112,97,116,116,101,114,110,32,115,117,99,104,32,97,115,32,91,87,45,93,52,54,93,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,99,108,97,115,115,32,111,102,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,32,40,34,87,34,32,97,110,100,32,34,45,34,41,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,32,34,52,54,93,34,44,32,115,111,32,105,116,32,119,111,117,108,100,32,109,97,116,99,104,32,34,87,52,54,93,34,32,111,114,32,34,45,52,54,93,34,46,32,72,111,119,101,118,101,114,44,32,105,102,32,34,93,34,32,105,115,32,101,115,99,97,112,101,100,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,44,32,105,116,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,116,104,101,32,101,110,100,32,111,102,32,114,97,110,103,101,44,32,115,111,32,91,87,45,92,93,52,54,93,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,99,108,97,115,115,32,99,111,110,116,97,105,110,105,110,103,32,97,32,114,97,110,103,101,32,102,111,108,108,111,119,101,100,32,98,121,32,116,119,111,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,111,99,116,97,108,32,111,114,32,104,101,120,97,100,101,99,105,109,97,108,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,34,93,34,32,99,97,110,32,97,108,115,111,32,98,101,32,117,115,101,100,32,116,111,32,101,110,100,32,97,32,114,97,110,103,101,46>>]},{p,[],[<<65,110,32,101,114,114,111,114,32,105,115,32,103,101,110,101,114,97,116,101,100,32,105,102,32,97,32,80,79,83,73,88,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,40,115,101,101,32,98,101,108,111,119,41,32,111,114,32,97,110,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,111,116,104,101,114,32,116,104,97,110,32,111,110,101,32,116,104,97,116,32,100,101,102,105,110,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,97,112,112,101,97,114,115,32,97,116,32,97,32,112,111,105,110,116,32,119,104,101,114,101,32,97,32,114,97,110,103,101,32,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,32,105,115,32,101,120,112,101,99,116,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,122,45,92,120,102,102,93,32,105,115,32,118,97,108,105,100,44,32,98,117,116,32,91,65,45,92,100,93,32,97,110,100,32,91,65,45,91,58,100,105,103,105,116,58,93,93,32,97,114,101,32,110,111,116,46>>]},{p,[],[<<82,97,110,103,101,115,32,111,112,101,114,97,116,101,32,105,110,32,116,104,101,32,99,111,108,108,97,116,105,110,103,32,115,101,113,117,101,110,99,101,32,111,102,32,99,104,97,114,97,99,116,101,114,32,118,97,108,117,101,115,46,32,84,104,101,121,32,99,97,110,32,97,108,115,111,32,98,101,32,117,115,101,100,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,115,112,101,99,105,102,105,101,100,32,110,117,109,101,114,105,99,97,108,108,121,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,91,92,48,48,48,45,92,48,51,55,93,46,32,82,97,110,103,101,115,32,99,97,110,32,105,110,99,108,117,100,101,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,118,97,108,105,100,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,109,111,100,101,46>>]},{p,[],[<<73,102,32,97,32,114,97,110,103,101,32,116,104,97,116,32,105,110,99,108,117,100,101,115,32,108,101,116,116,101,114,115,32,105,115,32,117,115,101,100,32,119,104,101,110,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,115,101,116,44,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,108,101,116,116,101,114,115,32,105,110,32,101,105,116,104,101,114,32,99,97,115,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,87,45,99,93,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,91,93,91,92,92,94,95,96,119,120,121,122,97,98,99,93,44,32,109,97,116,99,104,101,100,32,99,97,115,101,108,101,115,115,108,121,46,32,73,110,32,97,32,110,111,110,45,85,84,70,32,109,111,100,101,44,32,105,102,32,99,104,97,114,97,99,116,101,114,32,116,97,98,108,101,115,32,102,111,114,32,97,32,70,114,101,110,99,104,32,108,111,99,97,108,101,32,97,114,101,32,105,110,32,117,115,101,44,32,91,92,120,99,56,45,92,120,99,98,93,32,109,97,116,99,104,101,115,32,97,99,99,101,110,116,101,100,32,69,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,98,111,116,104,32,99,97,115,101,115,46,32,73,110,32,85,84,70,32,109,111,100,101,115,44,32,80,67,82,69,32,115,117,112,112,111,114,116,115,32,116,104,101,32,99,111,110,99,101,112,116,32,111,102,32,99,97,115,101,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,32,111,110,108,121,32,119,104,101,110,32,105,116,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,46>>]},{p,[],[<<84,104,101,32,99,104,97,114,97,99,116,101,114,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,92,100,44,32,92,68,44,32,92,104,44,32,92,72,44,32,92,112,44,32,92,80,44,32,92,115,44,32,92,83,44,32,92,118,44,32,92,86,44,32,92,119,44,32,97,110,100,32,92,87,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,110,100,32,97,100,100,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,116,104,101,121,32,109,97,116,99,104,32,116,111,32,116,104,101,32,99,108,97,115,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,92,100,65,66,67,68,69,70,93,32,109,97,116,99,104,101,115,32,97,110,121,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,46,32,73,110,32,85,84,70,32,109,111,100,101,115,44,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,97,102,102,101,99,116,115,32,116,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,92,100,44,32,92,115,44,32,92,119,32,97,110,100,32,116,104,101,105,114,32,117,112,112,101,114,99,97,115,101,32,112,97,114,116,110,101,114,115,44,32,106,117,115,116,32,97,115,32,105,116,32,100,111,101,115,32,119,104,101,110,32,116,104,101,121,32,97,112,112,101,97,114,32,111,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,103,101,110,101,114,105,99,95,99,104,97,114,97,99,116,101,114,95,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<71,101,110,101,114,105,99,32,67,104,97,114,97,99,116,101,114,32,84,121,112,101,115>>]},<<32,101,97,114,108,105,101,114,46,32,84,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,98,32,104,97,115,32,97,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,59,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,98,97,99,107,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,115,101,113,117,101,110,99,101,115,32,92,66,44,32,92,78,44,32,92,82,44,32,97,110,100,32,92,88,32,97,114,101,32,110,111,116,32,115,112,101,99,105,97,108,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,76,105,107,101,32,97,110,121,32,111,116,104,101,114,32,117,110,114,101,99,111,103,110,105,122,101,100,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,44,32,116,104,101,121,32,97,114,101,32,116,114,101,97,116,101,100,32,97,115,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,66,34,44,32,34,78,34,44,32,34,82,34,44,32,97,110,100,32,34,88,34,46>>]},{p,[],[<<65,32,99,105,114,99,117,109,102,108,101,120,32,99,97,110,32,99,111,110,118,101,110,105,101,110,116,108,121,32,98,101,32,117,115,101,100,32,119,105,116,104,32,116,104,101,32,117,112,112,101,114,99,97,115,101,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,32,116,111,32,115,112,101,99,105,102,121,32,97,32,109,111,114,101,32,114,101,115,116,114,105,99,116,101,100,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,110,32,116,104,101,32,109,97,116,99,104,105,110,103,32,108,111,119,101,114,99,97,115,101,32,116,121,112,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,108,97,115,115,32,91,94,92,87,95,93,32,109,97,116,99,104,101,115,32,97,110,121,32,108,101,116,116,101,114,32,111,114,32,100,105,103,105,116,44,32,98,117,116,32,110,111,116,32,117,110,100,101,114,115,99,111,114,101,44,32,119,104,105,108,101,32,91,92,119,93,32,105,110,99,108,117,100,101,115,32,117,110,100,101,114,115,99,111,114,101,46,32,65,32,112,111,115,105,116,105,118,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,105,115,32,116,111,32,98,101,32,114,101,97,100,32,97,115,32,34,115,111,109,101,116,104,105,110,103,32,79,82,32,115,111,109,101,116,104,105,110,103,32,79,82,32,46,46,46,34,32,97,110,100,32,97,32,110,101,103,97,116,105,118,101,32,99,108,97,115,115,32,97,115,32,34,78,79,84,32,115,111,109,101,116,104,105,110,103,32,65,78,68,32,78,79,84,32,115,111,109,101,116,104,105,110,103,32,65,78,68,32,78,79,84,32,46,46,46,34,46>>]},{p,[],[<<79,110,108,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,105,110,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,58>>]},{ul,[],[{li,[],[<<66,97,99,107,115,108,97,115,104>>]},{li,[],[<<72,121,112,104,101,110,32,40,111,110,108,121,32,119,104,101,114,101,32,105,116,32,99,97,110,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,115,112,101,99,105,102,121,105,110,103,32,97,32,114,97,110,103,101,41>>]},{li,[],[<<67,105,114,99,117,109,102,108,101,120,32,40,111,110,108,121,32,97,116,32,116,104,101,32,115,116,97,114,116,41>>]},{li,[],[<<79,112,101,110,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,40,111,110,108,121,32,119,104,101,110,32,105,116,32,99,97,110,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,105,110,116,114,111,100,117,99,105,110,103,32,97,32,80,111,115,105,120,32,99,108,97,115,115,32,110,97,109,101,44,32,111,114,32,102,111,114,32,97,32,115,112,101,99,105,97,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,102,101,97,116,117,114,101,59,32,115,101,101,32,116,104,101,32,110,101,120,116,32,116,119,111,32,115,101,99,116,105,111,110,115,41>>]},{li,[],[<<84,101,114,109,105,110,97,116,105,110,103,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116>>]}]},{p,[],[<<72,111,119,101,118,101,114,44,32,101,115,99,97,112,105,110,103,32,111,116,104,101,114,32,110,111,110,45,97,108,112,104,97,110,117,109,101,114,105,99,32,99,104,97,114,97,99,116,101,114,115,32,100,111,101,115,32,110,111,32,104,97,114,109,46>>]},{a,[{id,<<115,101,99,116,56>>}],[]},{h2,[],[<<80,111,115,105,120,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]},{p,[],[<<80,101,114,108,32,115,117,112,112,111,114,116,115,32,116,104,101,32,80,111,115,105,120,32,110,111,116,97,116,105,111,110,32,102,111,114,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,84,104,105,115,32,117,115,101,115,32,110,97,109,101,115,32,101,110,99,108,111,115,101,100,32,98,121,32,91,58,32,97,110,100,32,58,93,32,119,105,116,104,105,110,32,116,104,101,32,101,110,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,46,32,80,67,82,69,32,97,108,115,111,32,115,117,112,112,111,114,116,115,32,116,104,105,115,32,110,111,116,97,116,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,48,34,44,32,34,49,34,44,32,97,110,121,32,97,108,112,104,97,98,101,116,105,99,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,34,37,34,58>>]},{pre,[],[{code,[],[<<91,48,49,91,58,97,108,112,104,97,58,93,37,93>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,115,117,112,112,111,114,116,101,100,32,99,108,97,115,115,32,110,97,109,101,115,58>>]},{dl,[],[{dt,[],[<<97,108,110,117,109>>]},{dd,[],[<<76,101,116,116,101,114,115,32,97,110,100,32,100,105,103,105,116,115>>]},{dt,[],[<<97,108,112,104,97>>]},{dd,[],[<<76,101,116,116,101,114,115>>]},{dt,[],[<<97,115,99,105,105>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,99,111,100,101,115,32,48,45,49,50,55>>]},{dt,[],[<<98,108,97,110,107>>]},{dd,[],[<<83,112,97,99,101,32,111,114,32,116,97,98,32,111,110,108,121>>]},{dt,[],[<<99,110,116,114,108>>]},{dd,[],[<<67,111,110,116,114,111,108,32,99,104,97,114,97,99,116,101,114,115>>]},{dt,[],[<<100,105,103,105,116>>]},{dd,[],[<<68,101,99,105,109,97,108,32,100,105,103,105,116,115,32,40,115,97,109,101,32,97,115,32,92,100,41>>]},{dt,[],[<<103,114,97,112,104>>]},{dd,[],[<<80,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,101,120,99,108,117,100,105,110,103,32,115,112,97,99,101>>]},{dt,[],[<<108,111,119,101,114>>]},{dd,[],[<<76,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,115>>]},{dt,[],[<<112,114,105,110,116>>]},{dd,[],[<<80,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,105,110,99,108,117,100,105,110,103,32,115,112,97,99,101>>]},{dt,[],[<<112,117,110,99,116>>]},{dd,[],[<<80,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,101,120,99,108,117,100,105,110,103,32,108,101,116,116,101,114,115,44,32,100,105,103,105,116,115,44,32,97,110,100,32,115,112,97,99,101>>]},{dt,[],[<<115,112,97,99,101>>]},{dd,[],[<<87,104,105,116,101,115,112,97,99,101,32,40,116,104,101,32,115,97,109,101,32,97,115,32,92,115,32,102,114,111,109,32,80,67,82,69,32,56,46,51,52,41>>]},{dt,[],[<<117,112,112,101,114>>]},{dd,[],[<<85,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114,115>>]},{dt,[],[<<119,111,114,100>>]},{dd,[],[<<34,87,111,114,100,34,32,99,104,97,114,97,99,116,101,114,115,32,40,115,97,109,101,32,97,115,32,92,119,41>>]},{dt,[],[<<120,100,105,103,105,116>>]},{dd,[],[<<72,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,115>>]}]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,34,115,112,97,99,101,34,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,72,84,32,40,57,41,44,32,76,70,32,40,49,48,41,44,32,86,84,32,40,49,49,41,44,32,70,70,32,40,49,50,41,44,32,67,82,32,40,49,51,41,44,32,97,110,100,32,115,112,97,99,101,32,40,51,50,41,46,32,73,102,32,108,111,99,97,108,101,45,115,112,101,99,105,102,105,99,32,109,97,116,99,104,105,110,103,32,105,115,32,116,97,107,105,110,103,32,112,108,97,99,101,44,32,116,104,101,32,108,105,115,116,32,111,102,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,98,101,32,100,105,102,102,101,114,101,110,116,59,32,116,104,101,114,101,32,109,97,121,32,98,101,32,102,101,119,101,114,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,109,46,32,34,83,112,97,99,101,34,32,117,115,101,100,32,116,111,32,98,101,32,100,105,102,102,101,114,101,110,116,32,116,111,32,92,115,44,32,119,104,105,99,104,32,100,105,100,32,110,111,116,32,105,110,99,108,117,100,101,32,86,84,44,32,102,111,114,32,80,101,114,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46,32,72,111,119,101,118,101,114,44,32,80,101,114,108,32,99,104,97,110,103,101,100,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,44,32,97,110,100,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46,32,34,83,112,97,99,101,34,32,97,110,100,32,92,115,32,110,111,119,32,109,97,116,99,104,32,116,104,101,32,115,97,109,101,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,110,97,109,101,32,34,119,111,114,100,34,32,105,115,32,97,32,80,101,114,108,32,101,120,116,101,110,115,105,111,110,44,32,97,110,100,32,34,98,108,97,110,107,34,32,105,115,32,97,32,71,78,85,32,101,120,116,101,110,115,105,111,110,32,102,114,111,109,32,80,101,114,108,32,53,46,56,46,32,65,110,111,116,104,101,114,32,80,101,114,108,32,101,120,116,101,110,115,105,111,110,32,105,115,32,110,101,103,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,94,32,99,104,97,114,97,99,116,101,114,32,97,102,116,101,114,32,116,104,101,32,99,111,108,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,49,34,44,32,34,50,34,44,32,111,114,32,97,110,121,32,110,111,110,45,100,105,103,105,116,58>>]},{pre,[],[{code,[],[<<91,49,50,91,58,94,100,105,103,105,116,58,93,93>>]}]},{p,[],[<<80,67,82,69,32,40,97,110,100,32,80,101,114,108,41,32,97,108,115,111,32,114,101,99,111,103,110,105,122,101,32,116,104,101,32,80,111,115,105,120,32,115,121,110,116,97,120,32,91,46,99,104,46,93,32,97,110,100,32,91,61,99,104,61,93,32,119,104,101,114,101,32,34,99,104,34,32,105,115,32,97,32,34,99,111,108,108,97,116,105,110,103,32,101,108,101,109,101,110,116,34,44,32,98,117,116,32,116,104,101,115,101,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,44,32,97,110,100,32,97,110,32,101,114,114,111,114,32,105,115,32,103,105,118,101,110,32,105,102,32,116,104,101,121,32,97,114,101,32,101,110,99,111,117,110,116,101,114,101,100,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,32,100,111,32,110,111,116,32,109,97,116,99,104,32,97,110,121,32,111,102,32,116,104,101,32,80,111,115,105,120,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<80,67,82,69,95,85,67,80>>]},<<32,105,115,32,112,97,115,115,101,100,32,116,111,32>>,{code,[],[<<112,99,114,101,95,99,111,109,112,105,108,101,40,41>>]},<<44,32,115,111,109,101,32,111,102,32,116,104,101,32,99,108,97,115,115,101,115,32,97,114,101,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,117,115,101,100,46,32,84,104,105,115,32,105,115,32,97,99,104,105,101,118,101,100,32,98,121,32,114,101,112,108,97,99,105,110,103,32,99,101,114,116,97,105,110,32,80,111,115,105,120,32,99,108,97,115,115,101,115,32,98,121,32,111,116,104,101,114,32,115,101,113,117,101,110,99,101,115,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<91,58,97,108,110,117,109,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,88,97,110,125>>]}]},{dt,[],[<<91,58,97,108,112,104,97,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,76,125>>]}]},{dt,[],[<<91,58,98,108,97,110,107,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,104>>]}]},{dt,[],[<<91,58,100,105,103,105,116,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,78,100,125>>]}]},{dt,[],[<<91,58,108,111,119,101,114,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,76,108,125>>]}]},{dt,[],[<<91,58,115,112,97,99,101,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,88,112,115,125>>]}]},{dt,[],[<<91,58,117,112,112,101,114,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,76,117,125>>]}]},{dt,[],[<<91,58,119,111,114,100,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,88,119,100,125>>]}]}]},{p,[],[<<78,101,103,97,116,101,100,32,118,101,114,115,105,111,110,115,44,32,115,117,99,104,32,97,115,32,91,58,94,97,108,112,104,97,58,93,44,32,117,115,101,32,92,80,32,105,110,115,116,101,97,100,32,111,102,32,92,112,46,32,84,104,114,101,101,32,111,116,104,101,114,32,80,79,83,73,88,32,99,108,97,115,115,101,115,32,97,114,101,32,104,97,110,100,108,101,100,32,115,112,101,99,105,97,108,108,121,32,105,110,32,85,67,80,32,109,111,100,101,58>>]},{dl,[],[{dt,[],[<<91,58,103,114,97,112,104,58,93>>]},{dd,[],[{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,103,108,121,112,104,115,32,116,104,97,116,32,109,97,114,107,32,116,104,101,32,112,97,103,101,32,119,104,101,110,32,112,114,105,110,116,101,100,46,32,73,110,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,116,101,114,109,115,44,32,105,116,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,76,44,32,77,44,32,78,44,32,80,44,32,83,44,32,111,114,32,67,102,32,112,114,111,112,101,114,116,105,101,115,44,32,101,120,99,101,112,116,32,102,111,114,58>>]},{dl,[],[{dt,[],[<<85,43,48,54,49,67>>]},{dd,[],[{p,[],[<<65,114,97,98,105,99,32,76,101,116,116,101,114,32,77,97,114,107>>]}]},{dt,[],[<<85,43,49,56,48,69>>]},{dd,[],[{p,[],[<<77,111,110,103,111,108,105,97,110,32,86,111,119,101,108,32,83,101,112,97,114,97,116,111,114>>]}]},{dt,[],[<<85,43,50,48,54,54,32,45,32,85,43,50,48,54,57>>]},{dd,[],[{p,[],[<<86,97,114,105,111,117,115,32,34,105,115,111,108,97,116,101,34,115>>]}]}]}]},{dt,[],[<<91,58,112,114,105,110,116,58,93>>]},{dd,[],[{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,91,58,103,114,97,112,104,58,93,32,112,108,117,115,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,99,111,110,116,114,111,108,115,44,32,116,104,97,116,32,105,115,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,90,115,32,112,114,111,112,101,114,116,121,46>>]}]},{dt,[],[<<91,58,112,117,110,99,116,58,93>>]},{dd,[],[{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,116,104,101,32,85,110,105,99,111,100,101,32,80,32,40,112,117,110,99,116,117,97,116,105,111,110,41,32,112,114,111,112,101,114,116,121,44,32,112,108,117,115,32,116,104,111,115,101,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,108,101,115,115,32,116,104,97,110,32,49,50,56,32,116,104,97,116,32,104,97,118,101,32,116,104,101,32,83,32,40,83,121,109,98,111,108,41,32,112,114,111,112,101,114,116,121,46>>]}]}]},{p,[],[<<84,104,101,32,111,116,104,101,114,32,80,79,83,73,88,32,99,108,97,115,115,101,115,32,97,114,101,32,117,110,99,104,97,110,103,101,100,44,32,97,110,100,32,109,97,116,99,104,32,111,110,108,121,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,99,111,100,101,32,112,111,105,110,116,115,32,108,101,115,115,32,116,104,97,110,32,49,50,56,46>>]},{p,[],[{em,[],[<<67,111,109,112,97,116,105,98,105,108,105,116,121,32,70,101,97,116,117,114,101,32,102,111,114,32,87,111,114,100,32,66,111,117,110,100,97,114,105,101,115>>]}]},{p,[],[<<73,110,32,116,104,101,32,80,79,83,73,88,46,50,32,99,111,109,112,108,105,97,110,116,32,108,105,98,114,97,114,121,32,116,104,97,116,32,119,97,115,32,105,110,99,108,117,100,101,100,32,105,110,32,52,46,52,66,83,68,32,85,110,105,120,44,32,116,104,101,32,117,103,108,121,32,115,121,110,116,97,120,32,91,91,58,60,58,93,93,32,97,110,100,32,91,91,58,62,58,93,93,32,105,115,32,117,115,101,100,32,102,111,114,32,109,97,116,99,104,105,110,103,32,34,115,116,97,114,116,32,111,102,32,119,111,114,100,34,32,97,110,100,32,34,101,110,100,32,111,102,32,119,111,114,100,34,46,32,80,67,82,69,32,116,114,101,97,116,115,32,116,104,101,115,101,32,105,116,101,109,115,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<91,91,58,60,58,93,93>>]},{dd,[],[{p,[],[<<105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,92,98,40,63,61,92,119,41>>]}]},{dt,[],[<<91,91,58,62,58,93,93>>]},{dd,[],[{p,[],[<<105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,92,98,40,63,60,61,92,119,41>>]}]}]},{p,[],[<<79,110,108,121,32,116,104,101,115,101,32,101,120,97,99,116,32,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,115,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,46,32,65,32,115,101,113,117,101,110,99,101,32,115,117,99,104,32,97,115,32,91,97,91,58,60,58,93,98,93,32,112,114,111,118,111,107,101,115,32,101,114,114,111,114,32,102,111,114,32,97,110,32,117,110,114,101,99,111,103,110,105,122,101,100,32,80,79,83,73,88,32,99,108,97,115,115,32,110,97,109,101,46,32,84,104,105,115,32,115,117,112,112,111,114,116,32,105,115,32,110,111,116,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,32,80,101,114,108,46,32,73,116,32,105,115,32,112,114,111,118,105,100,101,100,32,116,111,32,104,101,108,112,32,109,105,103,114,97,116,105,111,110,115,32,102,114,111,109,32,111,116,104,101,114,32,101,110,118,105,114,111,110,109,101,110,116,115,44,32,97,110,100,32,105,115,32,98,101,115,116,32,110,111,116,32,117,115,101,100,32,105,110,32,97,110,121,32,110,101,119,32,112,97,116,116,101,114,110,115,46,32,78,111,116,101,32,116,104,97,116,32,92,98,32,109,97,116,99,104,101,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,97,110,100,32,116,104,101,32,101,110,100,32,111,102,32,97,32,119,111,114,100,32,40,115,101,101,32,34,83,105,109,112,108,101,32,97,115,115,101,114,116,105,111,110,115,34,32,97,98,111,118,101,41,44,32,97,110,100,32,105,110,32,97,32,80,101,114,108,45,115,116,121,108,101,32,112,97,116,116,101,114,110,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,111,114,32,102,111,108,108,111,119,105,110,103,32,99,104,97,114,97,99,116,101,114,32,110,111,114,109,97,108,108,121,32,115,104,111,119,115,32,119,104,105,99,104,32,105,115,32,119,97,110,116,101,100,44,32,119,105,116,104,111,117,116,32,116,104,101,32,110,101,101,100,32,102,111,114,32,116,104,101,32,97,115,115,101,114,116,105,111,110,115,32,116,104,97,116,32,97,114,101,32,117,115,101,100,32,97,98,111,118,101,32,105,110,32,111,114,100,101,114,32,116,111,32,103,105,118,101,32,101,120,97,99,116,108,121,32,116,104,101,32,80,79,83,73,88,32,98,101,104,97,118,105,111,117,114,46>>]},{a,[{id,<<115,101,99,116,57>>}],[]},{h2,[],[<<86,101,114,116,105,99,97,108,32,66,97,114>>]},{p,[],[<<86,101,114,116,105,99,97,108,32,98,97,114,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,117,115,101,100,32,116,111,32,115,101,112,97,114,97,116,101,32,97,108,116,101,114,110,97,116,105,118,101,32,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,101,105,116,104,101,114,32,34,103,105,108,98,101,114,116,34,32,111,114,32,34,115,117,108,108,105,118,97,110,34,58>>]},{pre,[],[{code,[],[<<103,105,108,98,101,114,116,124,115,117,108,108,105,118,97,110>>]}]},{p,[],[<<65,110,121,32,110,117,109,98,101,114,32,111,102,32,97,108,116,101,114,110,97,116,105,118,101,115,32,99,97,110,32,97,112,112,101,97,114,44,32,97,110,100,32,97,110,32,101,109,112,116,121,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,112,101,114,109,105,116,116,101,100,32,40,109,97,116,99,104,105,110,103,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,41,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,115,115,32,116,114,105,101,115,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,117,114,110,44,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,44,32,97,110,100,32,116,104,101,32,102,105,114,115,116,32,116,104,97,116,32,115,117,99,99,101,101,100,115,32,105,115,32,117,115,101,100,46,32,73,102,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,119,105,116,104,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,100,101,102,105,110,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115>>]},<<41,44,32,34,115,117,99,99,101,101,100,115,34,32,109,101,97,110,115,32,109,97,116,99,104,105,110,103,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,109,97,105,110,32,112,97,116,116,101,114,110,32,97,110,100,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,46>>]},{a,[{id,<<115,101,99,116,49,48>>}],[]},{h2,[],[<<73,110,116,101,114,110,97,108,32,79,112,116,105,111,110,32,83,101,116,116,105,110,103>>]},{p,[],[<<84,104,101,32,115,101,116,116,105,110,103,115,32,111,102,32,116,104,101,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<44,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<44,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,102,114,111,109,32,119,105,116,104,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,98,121,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,80,101,114,108,32,111,112,116,105,111,110,32,108,101,116,116,101,114,115,32,101,110,99,108,111,115,101,100,32,98,101,116,119,101,101,110,32,34,40,63,34,32,97,110,100,32,34,41,34,46,32,84,104,101,32,111,112,116,105,111,110,32,108,101,116,116,101,114,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<105>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]}]},{dt,[],[<<109>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]}]},{dt,[],[<<115>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<100,111,116,97,108,108>>]}]},{dt,[],[<<120>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]}]}]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<40,63,105,109,41>>]},<<32,115,101,116,115,32,99,97,115,101,108,101,115,115,44,32,109,117,108,116,105,108,105,110,101,32,109,97,116,99,104,105,110,103,46,32,84,104,101,115,101,32,111,112,116,105,111,110,115,32,99,97,110,32,97,108,115,111,32,98,101,32,117,110,115,101,116,32,98,121,32,112,114,101,99,101,100,105,110,103,32,116,104,101,32,108,101,116,116,101,114,32,119,105,116,104,32,97,32,104,121,112,104,101,110,46,32,65,32,99,111,109,98,105,110,101,100,32,115,101,116,116,105,110,103,32,97,110,100,32,117,110,115,101,116,116,105,110,103,32,115,117,99,104,32,97,115,32>>,{code,[],[<<40,63,105,109,45,115,120,41>>]},<<44,32,119,104,105,99,104,32,115,101,116,115,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<32,97,110,100,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<44,32,119,104,105,108,101,32,117,110,115,101,116,116,105,110,103,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<44,32,105,115,32,97,108,115,111,32,112,101,114,109,105,116,116,101,100,46,32,73,102,32,97,32,108,101,116,116,101,114,32,97,112,112,101,97,114,115,32,98,111,116,104,32,98,101,102,111,114,101,32,97,110,100,32,97,102,116,101,114,32,116,104,101,32,104,121,112,104,101,110,44,32,116,104,101,32,111,112,116,105,111,110,32,105,115,32,117,110,115,101,116,46>>]},{p,[],[<<84,104,101,32,80,67,82,69,45,115,112,101,99,105,102,105,99,32,111,112,116,105,111,110,115,32>>,{code,[],[<<100,117,112,110,97,109,101,115>>]},<<44,32>>,{code,[],[<<117,110,103,114,101,101,100,121>>]},<<44,32,97,110,100,32>>,{code,[],[<<101,120,116,114,97>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,116,104,101,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,32,111,112,116,105,111,110,115,32,98,121,32,117,115,105,110,103,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,74,44,32,85,44,32,97,110,100,32,88,32,114,101,115,112,101,99,116,105,118,101,108,121,46>>]},{p,[],[<<87,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,111,112,116,105,111,110,32,99,104,97,110,103,101,115,32,111,99,99,117,114,115,32,97,116,32,116,111,112,45,108,101,118,101,108,32,40,116,104,97,116,32,105,115,44,32,110,111,116,32,105,110,115,105,100,101,32,115,117,98,112,97,116,116,101,114,110,32,112,97,114,101,110,116,104,101,115,101,115,41,44,32,116,104,101,32,99,104,97,110,103,101,32,97,112,112,108,105,101,115,32,116,111,32,116,104,101,32,114,101,109,97,105,110,100,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,116,104,97,116,32,102,111,108,108,111,119,115,46>>]},{p,[],[<<65,110,32,111,112,116,105,111,110,32,99,104,97,110,103,101,32,119,105,116,104,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115>>]},<<41,32,97,102,102,101,99,116,115,32,111,110,108,121,32,116,104,97,116,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,102,111,108,108,111,119,115,32,105,116,46,32,83,111,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,98,99,32,97,110,100,32,97,66,99,32,97,110,100,32,110,111,32,111,116,104,101,114,32,115,116,114,105,110,103,115,32,40,97,115,115,117,109,105,110,103,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<32,105,115,32,110,111,116,32,117,115,101,100,41,58>>]},{pre,[],[{code,[],[<<40,97,40,63,105,41,98,41,99>>]}]},{p,[],[<<66,121,32,116,104,105,115,32,109,101,97,110,115,44,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,109,97,100,101,32,116,111,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,115,101,116,116,105,110,103,115,32,105,110,32,100,105,102,102,101,114,101,110,116,32,112,97,114,116,115,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,46,32,65,110,121,32,99,104,97,110,103,101,115,32,109,97,100,101,32,105,110,32,111,110,101,32,97,108,116,101,114,110,97,116,105,118,101,32,100,111,32,99,97,114,114,121,32,111,110,32,105,110,116,111,32,115,117,98,115,101,113,117,101,110,116,32,98,114,97,110,99,104,101,115,32,119,105,116,104,105,110,32,116,104,101,32,115,97,109,101,32,115,117,98,112,97,116,116,101,114,110,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,40,63,105,41,98,124,99,41>>]}]},{p,[],[<<109,97,116,99,104,101,115,32,34,97,98,34,44,32,34,97,66,34,44,32,34,99,34,44,32,97,110,100,32,34,67,34,44,32,97,108,116,104,111,117,103,104,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,34,67,34,32,116,104,101,32,102,105,114,115,116,32,98,114,97,110,99,104,32,105,115,32,97,98,97,110,100,111,110,101,100,32,98,101,102,111,114,101,32,116,104,101,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,101,102,102,101,99,116,115,32,111,102,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,115,32,111,99,99,117,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46,32,84,104,101,114,101,32,119,111,117,108,100,32,98,101,32,115,111,109,101,32,119,101,105,114,100,32,98,101,104,97,118,105,111,114,32,111,116,104,101,114,119,105,115,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,116,104,101,114,32,80,67,82,69,45,115,112,101,99,105,102,105,99,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,119,104,101,110,32,116,104,101,32,99,111,109,112,105,108,105,110,103,32,111,114,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,99,97,108,108,101,100,46,32,83,111,109,101,116,105,109,101,115,32,116,104,101,32,112,97,116,116,101,114,110,32,99,97,110,32,99,111,110,116,97,105,110,32,115,112,101,99,105,97,108,32,108,101,97,100,105,110,103,32,115,101,113,117,101,110,99,101,115,44,32,115,117,99,104,32,97,115,32,40,42,67,82,76,70,41,44,32,116,111,32,111,118,101,114,114,105,100,101,32,119,104,97,116,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,104,97,115,32,115,101,116,32,111,114,32,119,104,97,116,32,104,97,115,32,98,101,101,110,32,100,101,102,97,117,108,116,101,100,46,32,68,101,116,97,105,108,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,101,119,108,105,110,101,95,115,101,113,117,101,110,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,101,119,108,105,110,101,32,83,101,113,117,101,110,99,101,115>>]},<<32,101,97,114,108,105,101,114,46>>]},{p,[],[<<84,104,101,32,40,42,85,84,70,56,41,32,97,110,100,32,40,42,85,67,80,41,32,108,101,97,100,105,110,103,32,115,101,113,117,101,110,99,101,115,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,115,101,116,32,85,84,70,32,97,110,100,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,109,111,100,101,115,46,32,84,104,101,121,32,97,114,101,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,115,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,97,110,100,32>>,{code,[],[<<117,99,112>>]},<<44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,84,104,101,32,40,42,85,84,70,41,32,115,101,113,117,101,110,99,101,32,105,115,32,97,32,103,101,110,101,114,105,99,32,118,101,114,115,105,111,110,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,97,110,121,32,111,102,32,116,104,101,32,108,105,98,114,97,114,105,101,115,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,99,97,110,32,115,101,116,32,111,112,116,105,111,110,32>>,{code,[],[<<110,101,118,101,114,95,117,116,102>>]},<<44,32,119,104,105,99,104,32,108,111,99,107,115,32,111,117,116,32,116,104,101,32,117,115,101,32,111,102,32,116,104,101,32,40,42,85,84,70,41,32,115,101,113,117,101,110,99,101,115,46>>]}]},{a,[{id,<<115,101,99,116,49,49>>}],[]},{h2,[],[<<83,117,98,112,97,116,116,101,114,110,115>>]},{p,[],[<<83,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,100,101,108,105,109,105,116,101,100,32,98,121,32,112,97,114,101,110,116,104,101,115,101,115,32,40,114,111,117,110,100,32,98,114,97,99,107,101,116,115,41,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,110,101,115,116,101,100,46,32,84,117,114,110,105,110,103,32,112,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,32,105,110,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,100,111,101,115,32,116,119,111,32,116,104,105,110,103,115,58>>]},{dl,[],[{dt,[],[<<49,46>>]},{dd,[],[{p,[],[<<73,116,32,108,111,99,97,108,105,122,101,115,32,97,32,115,101,116,32,111,102,32,97,108,116,101,114,110,97,116,105,118,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,99,97,116,97,114,97,99,116,34,44,32,34,99,97,116,101,114,112,105,108,108,97,114,34,44,32,111,114,32,34,99,97,116,34,58>>]},{pre,[],[{code,[],[<<99,97,116,40,97,114,97,99,116,124,101,114,112,105,108,108,97,114,124,41>>]}]},{p,[],[<<87,105,116,104,111,117,116,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,44,32,105,116,32,119,111,117,108,100,32,109,97,116,99,104,32,34,99,97,116,97,114,97,99,116,34,44,32,34,101,114,112,105,108,108,97,114,34,44,32,111,114,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,46>>]}]},{dt,[],[<<50,46>>]},{dd,[],[{p,[],[<<73,116,32,115,101,116,115,32,117,112,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,97,115,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,46,32,84,104,97,116,32,105,115,44,32,119,104,101,110,32,116,104,101,32,99,111,109,112,108,101,116,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,44,32,116,104,97,116,32,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,116,104,97,116,32,109,97,116,99,104,101,100,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,112,97,115,115,101,100,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,116,104,114,111,117,103,104,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<46>>]}]}]},{p,[],[<<79,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,99,111,117,110,116,101,100,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,32,40,115,116,97,114,116,105,110,103,32,102,114,111,109,32,49,41,32,116,111,32,111,98,116,97,105,110,32,110,117,109,98,101,114,115,32,102,111,114,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,116,104,101,32,115,116,114,105,110,103,32,34,116,104,101,32,114,101,100,32,107,105,110,103,34,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,34,114,101,100,32,107,105,110,103,34,44,32,34,114,101,100,34,44,32,97,110,100,32,34,107,105,110,103,34,44,32,97,110,100,32,97,114,101,32,110,117,109,98,101,114,101,100,32,49,44,32,50,44,32,97,110,100,32,51,44,32,114,101,115,112,101,99,116,105,118,101,108,121,58>>]},{pre,[],[{code,[],[<<116,104,101,32,40,40,114,101,100,124,119,104,105,116,101,41,32,40,107,105,110,103,124,113,117,101,101,110,41,41>>]}]},{p,[],[<<73,116,32,105,115,32,110,111,116,32,97,108,119,97,121,115,32,104,101,108,112,102,117,108,32,116,104,97,116,32,112,108,97,105,110,32,112,97,114,101,110,116,104,101,115,101,115,32,102,117,108,102,105,108,108,32,116,119,111,32,102,117,110,99,116,105,111,110,115,46,32,79,102,116,101,110,32,97,32,103,114,111,117,112,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,114,101,113,117,105,114,101,100,32,119,105,116,104,111,117,116,32,97,32,99,97,112,116,117,114,105,110,103,32,114,101,113,117,105,114,101,109,101,110,116,46,32,73,102,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,113,117,101,115,116,105,111,110,32,109,97,114,107,32,97,110,100,32,97,32,99,111,108,111,110,44,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,100,111,101,115,32,110,111,116,32,100,111,32,97,110,121,32,99,97,112,116,117,114,105,110,103,44,32,97,110,100,32,105,115,32,110,111,116,32,99,111,117,110,116,101,100,32,119,104,101,110,32,99,111,109,112,117,116,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,110,121,32,115,117,98,115,101,113,117,101,110,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,116,104,101,32,115,116,114,105,110,103,32,34,116,104,101,32,119,104,105,116,101,32,113,117,101,101,110,34,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,34,119,104,105,116,101,32,113,117,101,101,110,34,32,97,110,100,32,34,113,117,101,101,110,34,44,32,97,110,100,32,97,114,101,32,110,117,109,98,101,114,101,100,32,49,32,97,110,100,32,50,58>>]},{pre,[],[{code,[],[<<116,104,101,32,40,40,63,58,114,101,100,124,119,104,105,116,101,41,32,40,107,105,110,103,124,113,117,101,101,110,41,41>>]}]},{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,105,115,32,54,53,53,51,53,46>>]},{p,[],[<<65,115,32,97,32,99,111,110,118,101,110,105,101,110,116,32,115,104,111,114,116,104,97,110,100,44,32,105,102,32,97,110,121,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,115,32,97,114,101,32,114,101,113,117,105,114,101,100,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,110,111,110,45,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,44,32,116,104,101,32,111,112,116,105,111,110,32,108,101,116,116,101,114,115,32,99,97,110,32,97,112,112,101,97,114,32,98,101,116,119,101,101,110,32,34,63,34,32,97,110,100,32,34,58,34,46,32,84,104,117,115,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,116,119,111,32,112,97,116,116,101,114,110,115,32,109,97,116,99,104,32,116,104,101,32,115,97,109,101,32,115,101,116,32,111,102,32,115,116,114,105,110,103,115,58>>]},{pre,[],[{code,[],[<<40,63,105,58,115,97,116,117,114,100,97,121,124,115,117,110,100,97,121,41,10,40,63,58,40,63,105,41,115,97,116,117,114,100,97,121,124,115,117,110,100,97,121,41>>]}]},{p,[],[<<65,115,32,97,108,116,101,114,110,97,116,105,118,101,32,98,114,97,110,99,104,101,115,32,97,114,101,32,116,114,105,101,100,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,44,32,97,110,100,32,111,112,116,105,111,110,115,32,97,114,101,32,110,111,116,32,114,101,115,101,116,32,117,110,116,105,108,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,114,101,97,99,104,101,100,44,32,97,110,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,32,105,110,32,111,110,101,32,98,114,97,110,99,104,32,100,111,101,115,32,97,102,102,101,99,116,32,115,117,98,115,101,113,117,101,110,116,32,98,114,97,110,99,104,101,115,44,32,115,111,32,116,104,101,32,97,98,111,118,101,32,112,97,116,116,101,114,110,115,32,109,97,116,99,104,32,98,111,116,104,32,34,83,85,78,68,65,89,34,32,97,110,100,32,34,83,97,116,117,114,100,97,121,34,46>>]},{a,[{id,<<115,101,99,116,49,50>>}],[]},{h2,[],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]},{p,[],[<<80,101,114,108,32,53,46,49,48,32,105,110,116,114,111,100,117,99,101,100,32,97,32,102,101,97,116,117,114,101,32,119,104,101,114,101,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,117,115,101,115,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,115,32,102,111,114,32,105,116,115,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,46,32,83,117,99,104,32,97,32,115,117,98,112,97,116,116,101,114,110,32,115,116,97,114,116,115,32,119,105,116,104,32>>,{code,[],[<<40,63,124>>]},<<32,97,110,100,32,105,115,32,105,116,115,101,108,102,32,97,32,110,111,110,45,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,63,124,40,83,97,116,41,117,114,124,40,83,117,110,41,41,100,97,121>>]}]},{p,[],[<<65,115,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,105,110,115,105,100,101,32,97,32>>,{code,[],[<<40,63,124>>]},<<32,103,114,111,117,112,44,32,98,111,116,104,32,115,101,116,115,32,111,102,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,110,117,109,98,101,114,101,100,32,111,110,101,46,32,84,104,117,115,44,32,119,104,101,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,44,32,121,111,117,32,99,97,110,32,108,111,111,107,32,97,116,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,32,110,117,109,98,101,114,32,111,110,101,44,32,119,104,105,99,104,101,118,101,114,32,97,108,116,101,114,110,97,116,105,118,101,32,109,97,116,99,104,101,100,46,32,84,104,105,115,32,99,111,110,115,116,114,117,99,116,32,105,115,32,117,115,101,102,117,108,32,119,104,101,110,32,121,111,117,32,119,97,110,116,32,116,111,32,99,97,112,116,117,114,101,32,97,32,112,97,114,116,44,32,98,117,116,32,110,111,116,32,97,108,108,44,32,111,102,32,111,110,101,32,111,102,32,109,97,110,121,32,97,108,116,101,114,110,97,116,105,118,101,115,46,32,73,110,115,105,100,101,32,97,32>>,{code,[],[<<40,63,124>>]},<<32,103,114,111,117,112,44,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,110,117,109,98,101,114,101,100,32,97,115,32,117,115,117,97,108,44,32,98,117,116,32,116,104,101,32,110,117,109,98,101,114,32,105,115,32,114,101,115,101,116,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,101,97,99,104,32,98,114,97,110,99,104,46,32,84,104,101,32,110,117,109,98,101,114,115,32,111,102,32,97,110,121,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,102,111,108,108,111,119,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,115,116,97,114,116,32,97,102,116,101,114,32,116,104,101,32,104,105,103,104,101,115,116,32,110,117,109,98,101,114,32,117,115,101,100,32,105,110,32,97,110,121,32,98,114,97,110,99,104,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,105,115,32,102,114,111,109,32,116,104,101,32,80,101,114,108,32,100,111,99,117,109,101,110,116,97,116,105,111,110,59,32,116,104,101,32,110,117,109,98,101,114,115,32,117,110,100,101,114,110,101,97,116,104,32,115,104,111,119,32,105,110,32,119,104,105,99,104,32,98,117,102,102,101,114,32,116,104,101,32,99,97,112,116,117,114,101,100,32,99,111,110,116,101,110,116,32,105,115,32,115,116,111,114,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<35,32,98,101,102,111,114,101,32,32,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,98,114,97,110,99,104,45,114,101,115,101,116,45,45,45,45,45,45,45,45,45,45,45,32,97,102,116,101,114,10,47,32,40,32,97,32,41,32,32,40,63,124,32,120,32,40,32,121,32,41,32,122,32,124,32,40,112,32,40,113,41,32,114,41,32,124,32,40,116,41,32,117,32,40,118,41,32,41,32,40,32,122,32,41,32,47,120,10,35,32,49,32,32,32,32,32,32,32,32,32,32,32,32,50,32,32,32,32,32,32,32,32,32,50,32,32,51,32,32,32,32,32,32,32,32,50,32,32,32,32,32,51,32,32,32,32,32,52>>]}]},{p,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,97,32,110,117,109,98,101,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,117,115,101,115,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,118,97,108,117,101,32,116,104,97,116,32,105,115,32,115,101,116,32,102,111,114,32,116,104,97,116,32,110,117,109,98,101,114,32,98,121,32,97,110,121,32,115,117,98,112,97,116,116,101,114,110,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,97,98,99,97,98,99,34,32,111,114,32,34,100,101,102,100,101,102,34,58>>]},{pre,[],[{code,[],[<<47,40,63,124,40,97,98,99,41,124,40,100,101,102,41,41,92,49,47>>]}]},{p,[],[<<73,110,32,99,111,110,116,114,97,115,116,44,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,116,111,32,97,32,110,117,109,98,101,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,97,108,119,97,121,115,32,114,101,102,101,114,115,32,116,111,32,116,104,101,32,102,105,114,115,116,32,111,110,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,103,105,118,101,110,32,110,117,109,98,101,114,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,97,98,99,97,98,99,34,32,111,114,32,34,100,101,102,97,98,99,34,58>>]},{pre,[],[{code,[],[<<47,40,63,124,40,97,98,99,41,124,40,100,101,102,41,41,40,63,49,41,47>>]}]},{p,[],[<<73,102,32,97,32,99,111,110,100,105,116,105,111,110,32,116,101,115,116,32,102,111,114,32,97,32,115,117,98,112,97,116,116,101,114,110,32,104,97,118,105,110,103,32,109,97,116,99,104,101,100,32,114,101,102,101,114,115,32,116,111,32,97,32,110,111,110,45,117,110,105,113,117,101,32,110,117,109,98,101,114,44,32,116,104,101,32,116,101,115,116,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,116,104,97,116,32,110,117,109,98,101,114,32,104,97,118,101,32,109,97,116,99,104,101,100,46>>]},{p,[],[<<65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,97,112,112,114,111,97,99,104,32,117,115,105,110,103,32,116,104,105,115,32,34,98,114,97,110,99,104,32,114,101,115,101,116,34,32,102,101,97,116,117,114,101,32,105,115,32,116,111,32,117,115,101,32,100,117,112,108,105,99,97,116,101,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,46>>]},{a,[{id,<<115,101,99,116,49,51>>}],[]},{h2,[],[<<78,97,109,101,100,32,83,117,98,112,97,116,116,101,114,110,115>>]},{p,[],[<<73,100,101,110,116,105,102,121,105,110,103,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,98,121,32,110,117,109,98,101,114,32,105,115,32,115,105,109,112,108,101,44,32,98,117,116,32,105,116,32,99,97,110,32,98,101,32,104,97,114,100,32,116,111,32,107,101,101,112,32,116,114,97,99,107,32,111,102,32,116,104,101,32,110,117,109,98,101,114,115,32,105,110,32,99,111,109,112,108,105,99,97,116,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,46,32,65,108,115,111,44,32,105,102,32,97,110,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,109,111,100,105,102,105,101,100,44,32,116,104,101,32,110,117,109,98,101,114,115,32,99,97,110,32,99,104,97,110,103,101,46,32,84,111,32,104,101,108,112,32,119,105,116,104,32,116,104,105,115,32,100,105,102,102,105,99,117,108,116,121,44,32,80,67,82,69,32,115,117,112,112,111,114,116,115,32,116,104,101,32,110,97,109,105,110,103,32,111,102,32,115,117,98,112,97,116,116,101,114,110,115,46,32,84,104,105,115,32,102,101,97,116,117,114,101,32,119,97,115,32,110,111,116,32,97,100,100,101,100,32,116,111,32,80,101,114,108,32,117,110,116,105,108,32,114,101,108,101,97,115,101,32,53,46,49,48,46,32,80,121,116,104,111,110,32,104,97,100,32,116,104,101,32,102,101,97,116,117,114,101,32,101,97,114,108,105,101,114,44,32,97,110,100,32,80,67,82,69,32,105,110,116,114,111,100,117,99,101,100,32,105,116,32,97,116,32,114,101,108,101,97,115,101,32,52,46,48,44,32,117,115,105,110,103,32,116,104,101,32,80,121,116,104,111,110,32,115,121,110,116,97,120,46,32,80,67,82,69,32,110,111,119,32,115,117,112,112,111,114,116,115,32,98,111,116,104,32,116,104,101,32,80,101,114,108,32,97,110,100,32,116,104,101,32,80,121,116,104,111,110,32,115,121,110,116,97,120,46,32,80,101,114,108,32,97,108,108,111,119,115,32,105,100,101,110,116,105,99,97,108,108,121,32,110,117,109,98,101,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,115,44,32,98,117,116,32,80,67,82,69,32,100,111,101,115,32,110,111,116,46>>]},{p,[],[<<73,110,32,80,67,82,69,44,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,98,101,32,110,97,109,101,100,32,105,110,32,111,110,101,32,111,102,32,116,104,114,101,101,32,119,97,121,115,58,32>>,{code,[],[<<40,63,60,110,97,109,101,62,46,46,46,41>>]},<<32,111,114,32>>,{code,[],[<<40,63,39,110,97,109,101,39,46,46,46,41>>]},<<32,97,115,32,105,110,32,80,101,114,108,44,32,111,114,32>>,{code,[],[<<40,63,80,60,110,97,109,101,62,46,46,46,41>>]},<<32,97,115,32,105,110,32,80,121,116,104,111,110,46,32,82,101,102,101,114,101,110,99,101,115,32,116,111,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,102,114,111,109,32,111,116,104,101,114,32,112,97,114,116,115,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,44,32,115,117,99,104,32,97,115,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,44,32,114,101,99,117,114,115,105,111,110,44,32,97,110,100,32,99,111,110,100,105,116,105,111,110,115,44,32,99,97,110,32,98,101,32,109,97,100,101,32,98,121,32,110,97,109,101,32,97,110,100,32,98,121,32,110,117,109,98,101,114,46>>]},{p,[],[<<78,97,109,101,115,32,99,111,110,115,105,115,116,32,111,102,32,117,112,32,116,111,32,51,50,32,97,108,112,104,97,110,117,109,101,114,105,99,32,99,104,97,114,97,99,116,101,114,115,32,97,110,100,32,117,110,100,101,114,115,99,111,114,101,115,44,32,98,117,116,32,109,117,115,116,32,115,116,97,114,116,32,119,105,116,104,32,97,32,110,111,110,45,100,105,103,105,116,46,32,78,97,109,101,100,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,115,116,105,108,108,32,97,108,108,111,99,97,116,101,100,32,110,117,109,98,101,114,115,32,97,115,32,119,101,108,108,32,97,115,32,110,97,109,101,115,44,32,101,120,97,99,116,108,121,32,97,115,32,105,102,32,116,104,101,32,110,97,109,101,115,32,119,101,114,101,32,110,111,116,32,112,114,101,115,101,110,116,46,32,84,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,99,97,110,32,117,115,101,32,110,97,109,101,100,32,118,97,108,117,101,115,32,105,102,32,116,104,101,121,32,97,114,101,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,97,32,110,97,109,101,32,109,117,115,116,32,98,101,32,117,110,105,113,117,101,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,44,32,98,117,116,32,116,104,105,115,32,99,111,110,115,116,114,97,105,110,116,32,99,97,110,32,98,101,32,114,101,108,97,120,101,100,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<100,117,112,110,97,109,101,115>>]},<<32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46,32,40,68,117,112,108,105,99,97,116,101,32,110,97,109,101,115,32,97,114,101,32,97,108,115,111,32,97,108,119,97,121,115,32,112,101,114,109,105,116,116,101,100,32,102,111,114,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,44,32,115,101,116,32,117,112,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,101,99,116,105,111,110,46,41,32,68,117,112,108,105,99,97,116,101,32,110,97,109,101,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,102,111,114,32,112,97,116,116,101,114,110,115,32,119,104,101,114,101,32,111,110,108,121,32,111,110,101,32,105,110,115,116,97,110,99,101,32,111,102,32,116,104,101,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,109,97,116,99,104,46,32,83,117,112,112,111,115,101,32,116,104,97,116,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,119,101,101,107,100,97,121,44,32,101,105,116,104,101,114,32,97,115,32,97,32,51,45,108,101,116,116,101,114,32,97,98,98,114,101,118,105,97,116,105,111,110,32,111,114,32,97,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,44,32,97,110,100,32,105,110,32,98,111,116,104,32,99,97,115,101,115,32,121,111,117,32,119,97,110,116,32,116,111,32,101,120,116,114,97,99,116,32,116,104,101,32,97,98,98,114,101,118,105,97,116,105,111,110,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,40,105,103,110,111,114,105,110,103,32,116,104,101,32,108,105,110,101,32,98,114,101,97,107,115,41,32,100,111,101,115,32,116,104,101,32,106,111,98,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<40,63,60,68,78,62,77,111,110,124,70,114,105,124,83,117,110,41,40,63,58,100,97,121,41,63,124,10,40,63,60,68,78,62,84,117,101,41,40,63,58,115,100,97,121,41,63,124,10,40,63,60,68,78,62,87,101,100,41,40,63,58,110,101,115,100,97,121,41,63,124,10,40,63,60,68,78,62,84,104,117,41,40,63,58,114,115,100,97,121,41,63,124,10,40,63,60,68,78,62,83,97,116,41,40,63,58,117,114,100,97,121,41,63>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,102,105,118,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,115,116,114,105,110,103,115,44,32,98,117,116,32,111,110,108,121,32,111,110,101,32,105,115,32,101,118,101,114,32,115,101,116,32,97,102,116,101,114,32,97,32,109,97,116,99,104,46,32,40,65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,119,97,121,32,111,102,32,115,111,108,118,105,110,103,32,116,104,105,115,32,112,114,111,98,108,101,109,32,105,115,32,116,111,32,117,115,101,32,97,32,34,98,114,97,110,99,104,32,114,101,115,101,116,34,32,115,117,98,112,97,116,116,101,114,110,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,101,99,116,105,111,110,46,41>>]},{p,[],[<<70,111,114,32,99,97,112,116,117,114,105,110,103,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,119,104,105,99,104,32,110,97,109,101,115,32,97,114,101,32,110,111,116,32,117,110,105,113,117,101,44,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,111,99,99,117,114,114,101,110,99,101,32,40,99,111,117,110,116,101,100,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,41,32,105,115,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,105,102,32,116,104,101,32,110,97,109,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,101,32>>,{code,[],[<<118,97,108,117,101,115>>]},<<32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,115,116,97,116,101,109,101,110,116,46,32,84,104,101,32>>,{code,[],[<<97,108,108,95,110,97,109,101,115>>]},<<32,99,97,112,116,117,114,105,110,103,32,118,97,108,117,101,32,109,97,116,99,104,101,115,32,97,108,108,32,116,104,101,32,110,97,109,101,115,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<89,111,117,32,99,97,110,110,111,116,32,117,115,101,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,115,32,116,111,32,100,105,115,116,105,110,103,117,105,115,104,32,98,101,116,119,101,101,110,32,116,119,111,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,44,32,97,115,32,80,67,82,69,32,117,115,101,115,32,111,110,108,121,32,116,104,101,32,110,117,109,98,101,114,115,32,119,104,101,110,32,109,97,116,99,104,105,110,103,46,32,70,111,114,32,116,104,105,115,32,114,101,97,115,111,110,44,32,97,110,32,101,114,114,111,114,32,105,115,32,103,105,118,101,110,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,32,105,102,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,115,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,116,111,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,46,32,72,111,119,101,118,101,114,44,32,121,111,117,32,99,97,110,32,115,112,101,99,105,102,121,32,116,104,101,32,115,97,109,101,32,110,97,109,101,32,116,111,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,44,32,101,118,101,110,32,119,104,101,110,32>>,{code,[],[<<100,117,112,110,97,109,101,115>>]},<<32,105,115,32,110,111,116,32,115,101,116,46>>]}]},{a,[{id,<<115,101,99,116,49,52>>}],[]},{h2,[],[<<82,101,112,101,116,105,116,105,111,110>>]},{p,[],[<<82,101,112,101,116,105,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32,113,117,97,110,116,105,102,105,101,114,115,44,32,119,104,105,99,104,32,99,97,110,32,102,111,108,108,111,119,32,97,110,121,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,116,101,109,115,58>>]},{ul,[],[{li,[],[<<65,32,108,105,116,101,114,97,108,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114>>]},{li,[],[<<84,104,101,32,100,111,116,32,109,101,116,97,99,104,97,114,97,99,116,101,114>>]},{li,[],[<<84,104,101,32,92,67,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101>>]},{li,[],[<<84,104,101,32,92,88,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101>>]},{li,[],[<<84,104,101,32,92,82,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101>>]},{li,[],[<<65,110,32,101,115,99,97,112,101,32,115,117,99,104,32,97,115,32,92,100,32,111,114,32,92,112,76,32,116,104,97,116,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114>>]},{li,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115>>]},{li,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,40,115,101,101,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41>>]},{li,[],[<<65,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,32,40,105,110,99,108,117,100,105,110,103,32,97,115,115,101,114,116,105,111,110,115,41>>]},{li,[],[<<65,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,114,101,99,117,114,115,105,118,101,32,111,114,32,111,116,104,101,114,119,105,115,101,41>>]}]},{p,[],[<<84,104,101,32,103,101,110,101,114,97,108,32,114,101,112,101,116,105,116,105,111,110,32,113,117,97,110,116,105,102,105,101,114,32,115,112,101,99,105,102,105,101,115,32,97,32,109,105,110,105,109,117,109,32,97,110,100,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,101,114,109,105,116,116,101,100,32,109,97,116,99,104,101,115,44,32,98,121,32,103,105,118,105,110,103,32,116,104,101,32,116,119,111,32,110,117,109,98,101,114,115,32,105,110,32,99,117,114,108,121,32,98,114,97,99,107,101,116,115,32,40,98,114,97,99,101,115,41,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,97,32,99,111,109,109,97,46,32,84,104,101,32,110,117,109,98,101,114,115,32,109,117,115,116,32,98,101,32,60,32,54,53,53,51,54,44,32,97,110,100,32,116,104,101,32,102,105,114,115,116,32,109,117,115,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32,116,104,101,32,115,101,99,111,110,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,122,122,34,44,32,34,122,122,122,34,44,32,111,114,32,34,122,122,122,122,34,58>>]},{pre,[],[{code,[],[<<122,123,50,44,52,125>>]}]},{p,[],[<<65,32,99,108,111,115,105,110,103,32,98,114,97,99,101,32,111,110,32,105,116,115,32,111,119,110,32,105,115,32,110,111,116,32,97,32,115,112,101,99,105,97,108,32,99,104,97,114,97,99,116,101,114,46,32,73,102,32,116,104,101,32,115,101,99,111,110,100,32,110,117,109,98,101,114,32,105,115,32,111,109,105,116,116,101,100,44,32,98,117,116,32,116,104,101,32,99,111,109,109,97,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,114,101,32,105,115,32,110,111,32,117,112,112,101,114,32,108,105,109,105,116,46,32,73,102,32,116,104,101,32,115,101,99,111,110,100,32,110,117,109,98,101,114,32,97,110,100,32,116,104,101,32,99,111,109,109,97,32,97,114,101,32,98,111,116,104,32,111,109,105,116,116,101,100,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,115,112,101,99,105,102,105,101,115,32,97,110,32,101,120,97,99,116,32,110,117,109,98,101,114,32,111,102,32,114,101,113,117,105,114,101,100,32,109,97,116,99,104,101,115,46,32,84,104,117,115,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,116,32,108,101,97,115,116,32,116,104,114,101,101,32,115,117,99,99,101,115,115,105,118,101,32,118,111,119,101,108,115,44,32,98,117,116,32,99,97,110,32,109,97,116,99,104,32,109,97,110,121,32,109,111,114,101,58>>]},{pre,[],[{code,[],[<<91,97,101,105,111,117,93,123,51,44,125>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,101,120,97,99,116,108,121,32,101,105,103,104,116,32,100,105,103,105,116,115,58>>]},{pre,[],[{code,[],[<<92,100,123,56,125>>]}]},{p,[],[<<65,110,32,111,112,101,110,105,110,103,32,99,117,114,108,121,32,98,114,97,99,107,101,116,32,116,104,97,116,32,97,112,112,101,97,114,115,32,105,110,32,97,32,112,111,115,105,116,105,111,110,32,119,104,101,114,101,32,97,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,44,32,111,114,32,111,110,101,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,115,121,110,116,97,120,32,111,102,32,97,32,113,117,97,110,116,105,102,105,101,114,44,32,105,115,32,116,97,107,101,110,32,97,115,32,97,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,123,44,54,125,32,105,115,32,110,111,116,32,97,32,113,117,97,110,116,105,102,105,101,114,44,32,98,117,116,32,97,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,32,111,102,32,102,111,117,114,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<73,110,32,85,110,105,99,111,100,101,32,109,111,100,101,44,32,113,117,97,110,116,105,102,105,101,114,115,32,97,112,112,108,121,32,116,111,32,99,104,97,114,97,99,116,101,114,115,32,114,97,116,104,101,114,32,116,104,97,110,32,116,111,32,105,110,100,105,118,105,100,117,97,108,32,100,97,116,97,32,117,110,105,116,115,46,32,84,104,117,115,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,92,120,123,49,48,48,125,123,50,125,32,109,97,116,99,104,101,115,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,44,32,101,97,99,104,32,111,102,32,119,104,105,99,104,32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,50,45,98,121,116,101,32,115,101,113,117,101,110,99,101,32,105,110,32,97,32,85,84,70,45,56,32,115,116,114,105,110,103,46,32,83,105,109,105,108,97,114,108,121,44,32,92,88,123,51,125,32,109,97,116,99,104,101,115,32,116,104,114,101,101,32,85,110,105,99,111,100,101,32,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114,115,44,32,101,97,99,104,32,111,102,32,119,104,105,99,104,32,99,97,110,32,98,101,32,109,97,110,121,32,100,97,116,97,32,117,110,105,116,115,32,108,111,110,103,32,40,97,110,100,32,116,104,101,121,32,99,97,110,32,98,101,32,111,102,32,100,105,102,102,101,114,101,110,116,32,108,101,110,103,116,104,115,41,46>>]},{p,[],[<<84,104,101,32,113,117,97,110,116,105,102,105,101,114,32,123,48,125,32,105,115,32,112,101,114,109,105,116,116,101,100,44,32,99,97,117,115,105,110,103,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,116,111,32,98,101,104,97,118,101,32,97,115,32,105,102,32,116,104,101,32,112,114,101,118,105,111,117,115,32,105,116,101,109,32,97,110,100,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,119,101,114,101,32,110,111,116,32,112,114,101,115,101,110,116,46,32,84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,102,111,114,32,115,117,98,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,114,101,102,101,114,101,110,99,101,100,32,97,115,32,115,117,98,114,111,117,116,105,110,101,115,32,102,114,111,109,32,101,108,115,101,119,104,101,114,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,40,98,117,116,32,115,101,101,32,97,108,115,111,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,100,101,102,105,110,105,110,103,95,115,117,98,112,97,116,116,101,114,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,101,102,105,110,105,110,103,32,83,117,98,112,97,116,116,101,114,110,115,32,102,111,114,32,85,115,101,32,98,121,32,82,101,102,101,114,101,110,99,101,32,79,110,108,121>>]},<<41,46,32,73,116,101,109,115,32,111,116,104,101,114,32,116,104,97,110,32,115,117,98,112,97,116,116,101,114,110,115,32,116,104,97,116,32,104,97,118,101,32,97,32,123,48,125,32,113,117,97,110,116,105,102,105,101,114,32,97,114,101,32,111,109,105,116,116,101,100,32,102,114,111,109,32,116,104,101,32,99,111,109,112,105,108,101,100,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<70,111,114,32,99,111,110,118,101,110,105,101,110,99,101,44,32,116,104,101,32,116,104,114,101,101,32,109,111,115,116,32,99,111,109,109,111,110,32,113,117,97,110,116,105,102,105,101,114,115,32,104,97,118,101,32,115,105,110,103,108,101,45,99,104,97,114,97,99,116,101,114,32,97,98,98,114,101,118,105,97,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[<<42>>]},{dd,[],[<<69,113,117,105,118,97,108,101,110,116,32,116,111,32,123,48,44,125>>]},{dt,[],[<<43>>]},{dd,[],[<<69,113,117,105,118,97,108,101,110,116,32,116,111,32,123,49,44,125>>]},{dt,[],[<<63>>]},{dd,[],[<<69,113,117,105,118,97,108,101,110,116,32,116,111,32,123,48,44,49,125>>]}]},{p,[],[<<73,110,102,105,110,105,116,101,32,108,111,111,112,115,32,99,97,110,32,98,101,32,99,111,110,115,116,114,117,99,116,101,100,32,98,121,32,102,111,108,108,111,119,105,110,103,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,99,97,110,32,109,97,116,99,104,32,110,111,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,97,32,113,117,97,110,116,105,102,105,101,114,32,116,104,97,116,32,104,97,115,32,110,111,32,117,112,112,101,114,32,108,105,109,105,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,63,41,42>>]}]},{p,[],[<<69,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,111,102,32,80,101,114,108,32,97,110,100,32,80,67,82,69,32,117,115,101,100,32,116,111,32,103,105,118,101,32,97,110,32,101,114,114,111,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,32,102,111,114,32,115,117,99,104,32,112,97,116,116,101,114,110,115,46,32,72,111,119,101,118,101,114,44,32,97,115,32,116,104,101,114,101,32,97,114,101,32,99,97,115,101,115,32,119,104,101,114,101,32,116,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,44,32,115,117,99,104,32,112,97,116,116,101,114,110,115,32,97,114,101,32,110,111,119,32,97,99,99,101,112,116,101,100,46,32,72,111,119,101,118,101,114,44,32,105,102,32,97,110,121,32,114,101,112,101,116,105,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,110,111,32,99,104,97,114,97,99,116,101,114,115,44,32,116,104,101,32,108,111,111,112,32,105,115,32,102,111,114,99,105,98,108,121,32,98,114,111,107,101,110,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,34,103,114,101,101,100,121,34,44,32,116,104,97,116,32,105,115,44,32,116,104,101,121,32,109,97,116,99,104,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,32,40,117,112,32,116,111,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,101,114,109,105,116,116,101,100,32,116,105,109,101,115,41,44,32,119,105,116,104,111,117,116,32,99,97,117,115,105,110,103,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,116,111,32,102,97,105,108,46,32,84,104,101,32,99,108,97,115,115,105,99,32,101,120,97,109,112,108,101,32,111,102,32,119,104,101,114,101,32,116,104,105,115,32,103,105,118,101,115,32,112,114,111,98,108,101,109,115,32,105,115,32,105,110,32,116,114,121,105,110,103,32,116,111,32,109,97,116,99,104,32,99,111,109,109,101,110,116,115,32,105,110,32,67,32,112,114,111,103,114,97,109,115,46,32,84,104,101,115,101,32,97,112,112,101,97,114,32,98,101,116,119,101,101,110,32,47,42,32,97,110,100,32,42,47,46,32,87,105,116,104,105,110,32,116,104,101,32,99,111,109,109,101,110,116,44,32,105,110,100,105,118,105,100,117,97,108,32,42,32,97,110,100,32,47,32,99,104,97,114,97,99,116,101,114,115,32,99,97,110,32,97,112,112,101,97,114,46,32,65,110,32,97,116,116,101,109,112,116,32,116,111,32,109,97,116,99,104,32,67,32,99,111,109,109,101,110,116,115,32,98,121,32,97,112,112,108,121,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110>>]},{pre,[],[{code,[],[<<47,92,42,46,42,92,42,47>>]}]},{p,[],[<<116,111,32,116,104,101,32,115,116,114,105,110,103>>]},{pre,[],[{code,[],[<<47,42,32,102,105,114,115,116,32,99,111,109,109,101,110,116,32,42,47,32,32,110,111,116,32,99,111,109,109,101,110,116,32,32,47,42,32,115,101,99,111,110,100,32,99,111,109,109,101,110,116,32,42,47>>]}]},{p,[],[<<102,97,105,108,115,44,32,97,115,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,32,111,119,105,110,103,32,116,111,32,116,104,101,32,103,114,101,101,100,105,110,101,115,115,32,111,102,32,116,104,101,32,46,42,32,105,116,101,109,46>>]},{p,[],[<<72,111,119,101,118,101,114,44,32,105,102,32,97,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,113,117,101,115,116,105,111,110,32,109,97,114,107,44,32,105,116,32,99,101,97,115,101,115,32,116,111,32,98,101,32,103,114,101,101,100,121,44,32,97,110,100,32,105,110,115,116,101,97,100,32,109,97,116,99,104,101,115,32,116,104,101,32,109,105,110,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,112,111,115,115,105,98,108,101,44,32,115,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,100,111,101,115,32,116,104,101,32,114,105,103,104,116,32,116,104,105,110,103,32,119,105,116,104,32,116,104,101,32,67,32,99,111,109,109,101,110,116,115,58>>]},{pre,[],[{code,[],[<<47,92,42,46,42,63,92,42,47>>]}]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,116,104,101,32,118,97,114,105,111,117,115,32,113,117,97,110,116,105,102,105,101,114,115,32,105,115,32,110,111,116,32,111,116,104,101,114,119,105,115,101,32,99,104,97,110,103,101,100,44,32,111,110,108,121,32,116,104,101,32,112,114,101,102,101,114,114,101,100,32,110,117,109,98,101,114,32,111,102,32,109,97,116,99,104,101,115,46,32,68,111,32,110,111,116,32,99,111,110,102,117,115,101,32,116,104,105,115,32,117,115,101,32,111,102,32,113,117,101,115,116,105,111,110,32,109,97,114,107,32,119,105,116,104,32,105,116,115,32,117,115,101,32,97,115,32,97,32,113,117,97,110,116,105,102,105,101,114,32,105,110,32,105,116,115,32,111,119,110,32,114,105,103,104,116,46,32,65,115,32,105,116,32,104,97,115,32,116,119,111,32,117,115,101,115,44,32,105,116,32,99,97,110,32,115,111,109,101,116,105,109,101,115,32,97,112,112,101,97,114,32,100,111,117,98,108,101,100,44,32,97,115,32,105,110>>]},{pre,[],[{code,[],[<<92,100,63,63,92,100>>]}]},{p,[],[<<119,104,105,99,104,32,109,97,116,99,104,101,115,32,111,110,101,32,100,105,103,105,116,32,98,121,32,112,114,101,102,101,114,101,110,99,101,44,32,98,117,116,32,99,97,110,32,109,97,116,99,104,32,116,119,111,32,105,102,32,116,104,97,116,32,105,115,32,116,104,101,32,111,110,108,121,32,119,97,121,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,103,114,101,101,100,121>>]},<<32,105,115,32,115,101,116,32,40,97,110,32,111,112,116,105,111,110,32,116,104,97,116,32,105,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,105,110,32,80,101,114,108,41,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,110,111,116,32,103,114,101,101,100,121,32,98,121,32,100,101,102,97,117,108,116,44,32,98,117,116,32,105,110,100,105,118,105,100,117,97,108,32,111,110,101,115,32,99,97,110,32,98,101,32,109,97,100,101,32,103,114,101,101,100,121,32,98,121,32,102,111,108,108,111,119,105,110,103,32,116,104,101,109,32,119,105,116,104,32,97,32,113,117,101,115,116,105,111,110,32,109,97,114,107,46,32,84,104,97,116,32,105,115,44,32,105,116,32,105,110,118,101,114,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<87,104,101,110,32,97,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,113,117,97,110,116,105,102,105,101,100,32,119,105,116,104,32,97,32,109,105,110,105,109,117,109,32,114,101,112,101,97,116,32,99,111,117,110,116,32,116,104,97,116,32,105,115,32,62,32,49,32,111,114,32,119,105,116,104,32,97,32,108,105,109,105,116,101,100,32,109,97,120,105,109,117,109,44,32,109,111,114,101,32,109,101,109,111,114,121,32,105,115,32,114,101,113,117,105,114,101,100,32,102,111,114,32,116,104,101,32,99,111,109,112,105,108,101,100,32,112,97,116,116,101,114,110,44,32,105,110,32,112,114,111,112,111,114,116,105,111,110,32,116,111,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,105,110,105,109,117,109,32,111,114,32,109,97,120,105,109,117,109,46>>]},{p,[],[<<73,102,32,97,32,112,97,116,116,101,114,110,32,115,116,97,114,116,115,32,119,105,116,104,32,46,42,32,111,114,32,46,123,48,44,125,32,97,110,100,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,40,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,115>>]},<<41,32,105,115,32,115,101,116,44,32,116,104,117,115,32,97,108,108,111,119,105,110,103,32,116,104,101,32,100,111,116,32,116,111,32,109,97,116,99,104,32,110,101,119,108,105,110,101,115,44,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,105,109,112,108,105,99,105,116,108,121,32,97,110,99,104,111,114,101,100,44,32,98,101,99,97,117,115,101,32,119,104,97,116,101,118,101,114,32,102,111,108,108,111,119,115,32,105,115,32,116,114,105,101,100,32,97,103,97,105,110,115,116,32,101,118,101,114,121,32,99,104,97,114,97,99,116,101,114,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,83,111,44,32,116,104,101,114,101,32,105,115,32,110,111,32,112,111,105,110,116,32,105,110,32,114,101,116,114,121,105,110,103,32,116,104,101,32,111,118,101,114,97,108,108,32,109,97,116,99,104,32,97,116,32,97,110,121,32,112,111,115,105,116,105,111,110,32,97,102,116,101,114,32,116,104,101,32,102,105,114,115,116,46,32,80,67,82,69,32,110,111,114,109,97,108,108,121,32,116,114,101,97,116,115,32,115,117,99,104,32,97,32,112,97,116,116,101,114,110,32,97,115,32,105,102,32,105,116,32,119,97,115,32,112,114,101,99,101,100,101,100,32,98,121,32,92,65,46>>]},{p,[],[<<73,110,32,99,97,115,101,115,32,119,104,101,114,101,32,105,116,32,105,115,32,107,110,111,119,110,32,116,104,97,116,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,115,32,110,111,32,110,101,119,108,105,110,101,115,44,32,105,116,32,105,115,32,119,111,114,116,104,32,115,101,116,116,105,110,103,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,116,111,32,111,98,116,97,105,110,32,116,104,105,115,32,111,112,116,105,109,105,122,97,116,105,111,110,44,32,111,114,32,97,108,116,101,114,110,97,116,105,118,101,108,121,32,117,115,105,110,103,32,94,32,116,111,32,105,110,100,105,99,97,116,101,32,97,110,99,104,111,114,105,110,103,32,101,120,112,108,105,99,105,116,108,121,46>>]},{p,[],[<<72,111,119,101,118,101,114,44,32,116,104,101,114,101,32,97,114,101,32,115,111,109,101,32,99,97,115,101,115,32,119,104,101,114,101,32,116,104,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,46,32,87,104,101,110,32,46,42,32,105,115,32,105,110,115,105,100,101,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,116,104,101,32,115,117,98,106,101,99,116,32,111,102,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,101,108,115,101,119,104,101,114,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,44,32,97,32,109,97,116,99,104,32,97,116,32,116,104,101,32,115,116,97,114,116,32,99,97,110,32,102,97,105,108,32,119,104,101,114,101,32,97,32,108,97,116,101,114,32,111,110,101,32,115,117,99,99,101,101,100,115,46,32,67,111,110,115,105,100,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,46,42,41,97,98,99,92,49>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,120,121,122,49,50,51,97,98,99,49,50,51,34,44,32,116,104,101,32,109,97,116,99,104,32,112,111,105,110,116,32,105,115,32,116,104,101,32,102,111,117,114,116,104,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,114,101,102,111,114,101,44,32,115,117,99,104,32,97,32,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,105,109,112,108,105,99,105,116,108,121,32,97,110,99,104,111,114,101,100,46>>]},{p,[],[<<65,110,111,116,104,101,114,32,99,97,115,101,32,119,104,101,114,101,32,105,109,112,108,105,99,105,116,32,97,110,99,104,111,114,105,110,103,32,105,115,32,110,111,116,32,97,112,112,108,105,101,100,32,105,115,32,119,104,101,110,32,116,104,101,32,108,101,97,100,105,110,103,32,46,42,32,105,115,32,105,110,115,105,100,101,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,79,110,99,101,32,97,103,97,105,110,44,32,97,32,109,97,116,99,104,32,97,116,32,116,104,101,32,115,116,97,114,116,32,99,97,110,32,102,97,105,108,32,119,104,101,114,101,32,97,32,108,97,116,101,114,32,111,110,101,32,115,117,99,99,101,101,100,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,63,62,46,42,63,97,41,98>>]}]},{p,[],[<<73,116,32,109,97,116,99,104,101,115,32,34,97,98,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,34,97,97,98,34,46,32,84,104,101,32,117,115,101,32,111,102,32,116,104,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,111,110,116,114,111,108,32,118,101,114,98,115,32,40,42,80,82,85,78,69,41,32,97,110,100,32,40,42,83,75,73,80,41,32,97,108,115,111,32,100,105,115,97,98,108,101,32,116,104,105,115,32,111,112,116,105,109,105,122,97,116,105,111,110,46>>]},{p,[],[<<87,104,101,110,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,114,101,112,101,97,116,101,100,44,32,116,104,101,32,118,97,108,117,101,32,99,97,112,116,117,114,101,100,32,105,115,32,116,104,101,32,115,117,98,115,116,114,105,110,103,32,116,104,97,116,32,109,97,116,99,104,101,100,32,116,104,101,32,102,105,110,97,108,32,105,116,101,114,97,116,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,102,116,101,114>>]},{pre,[],[{code,[],[<<40,116,119,101,101,100,108,101,91,100,117,109,101,93,123,51,125,92,115,42,41,43>>]}]},{p,[],[<<104,97,115,32,109,97,116,99,104,101,100,32,34,116,119,101,101,100,108,101,100,117,109,32,116,119,101,101,100,108,101,100,101,101,34,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,32,105,115,32,34,116,119,101,101,100,108,101,100,101,101,34,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,114,101,32,97,114,101,32,110,101,115,116,101,100,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,99,97,112,116,117,114,101,100,32,118,97,108,117,101,115,32,99,97,110,32,104,97,118,101,32,98,101,101,110,32,115,101,116,32,105,110,32,112,114,101,118,105,111,117,115,32,105,116,101,114,97,116,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,102,116,101,114>>]},{pre,[],[{code,[],[<<47,40,97,124,40,98,41,41,43,47>>]}]},{p,[],[<<109,97,116,99,104,101,115,32,34,97,98,97,34,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,115,101,99,111,110,100,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,32,105,115,32,34,98,34,46>>]},{a,[{id,<<115,101,99,116,49,53>>}],[]},{h2,[],[<<65,116,111,109,105,99,32,71,114,111,117,112,105,110,103,32,97,110,100,32,80,111,115,115,101,115,115,105,118,101,32,81,117,97,110,116,105,102,105,101,114,115>>]},{p,[],[<<87,105,116,104,32,98,111,116,104,32,109,97,120,105,109,105,122,105,110,103,32,40,34,103,114,101,101,100,121,34,41,32,97,110,100,32,109,105,110,105,109,105,122,105,110,103,32,40,34,117,110,103,114,101,101,100,121,34,32,111,114,32,34,108,97,122,121,34,41,32,114,101,112,101,116,105,116,105,111,110,44,32,102,97,105,108,117,114,101,32,111,102,32,119,104,97,116,32,102,111,108,108,111,119,115,32,110,111,114,109,97,108,108,121,32,99,97,117,115,101,115,32,116,104,101,32,114,101,112,101,97,116,101,100,32,105,116,101,109,32,116,111,32,98,101,32,114,101,45,101,118,97,108,117,97,116,101,100,32,116,111,32,115,101,101,32,105,102,32,97,32,100,105,102,102,101,114,101,110,116,32,110,117,109,98,101,114,32,111,102,32,114,101,112,101,97,116,115,32,97,108,108,111,119,115,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,116,111,32,109,97,116,99,104,46,32,83,111,109,101,116,105,109,101,115,32,105,116,32,105,115,32,117,115,101,102,117,108,32,116,111,32,112,114,101,118,101,110,116,32,116,104,105,115,44,32,101,105,116,104,101,114,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,110,97,116,117,114,101,32,111,102,32,116,104,101,32,109,97,116,99,104,44,32,111,114,32,116,111,32,99,97,117,115,101,32,105,116,32,116,111,32,102,97,105,108,32,101,97,114,108,105,101,114,32,116,104,97,110,32,105,116,32,111,116,104,101,114,119,105,115,101,32,109,105,103,104,116,44,32,119,104,101,110,32,116,104,101,32,97,117,116,104,111,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,107,110,111,119,115,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,110,111,32,112,111,105,110,116,32,105,110,32,99,97,114,114,121,105,110,103,32,111,110,46>>]},{p,[],[<<67,111,110,115,105,100,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,112,97,116,116,101,114,110,32,92,100,43,102,111,111,32,119,104,101,110,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,117,98,106,101,99,116,32,108,105,110,101,58>>]},{pre,[],[{code,[],[<<49,50,51,52,53,54,98,97,114>>]}]},{p,[],[<<65,102,116,101,114,32,109,97,116,99,104,105,110,103,32,97,108,108,32,115,105,120,32,100,105,103,105,116,115,32,97,110,100,32,116,104,101,110,32,102,97,105,108,105,110,103,32,116,111,32,109,97,116,99,104,32,34,102,111,111,34,44,32,116,104,101,32,110,111,114,109,97,108,32,97,99,116,105,111,110,32,111,102,32,116,104,101,32,109,97,116,99,104,101,114,32,105,115,32,116,111,32,116,114,121,32,97,103,97,105,110,32,119,105,116,104,32,111,110,108,121,32,102,105,118,101,32,100,105,103,105,116,115,32,109,97,116,99,104,105,110,103,32,105,116,101,109,32,92,100,43,44,32,97,110,100,32,116,104,101,110,32,119,105,116,104,32,102,111,117,114,44,32,97,110,100,32,115,111,32,111,110,44,32,98,101,102,111,114,101,32,117,108,116,105,109,97,116,101,108,121,32,102,97,105,108,105,110,103,46,32,34,65,116,111,109,105,99,32,103,114,111,117,112,105,110,103,34,32,40,97,32,116,101,114,109,32,116,97,107,101,110,32,102,114,111,109,32,74,101,102,102,114,101,121,32,70,114,105,101,100,108,39,115,32,98,111,111,107,41,32,112,114,111,118,105,100,101,115,32,116,104,101,32,109,101,97,110,115,32,102,111,114,32,115,112,101,99,105,102,121,105,110,103,32,116,104,97,116,32,111,110,99,101,32,97,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,109,97,116,99,104,101,100,44,32,105,116,32,105,115,32,110,111,116,32,116,111,32,98,101,32,114,101,45,101,118,97,108,117,97,116,101,100,32,105,110,32,116,104,105,115,32,119,97,121,46>>]},{p,[],[<<73,102,32,97,116,111,109,105,99,32,103,114,111,117,112,105,110,103,32,105,115,32,117,115,101,100,32,102,111,114,32,116,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,44,32,116,104,101,32,109,97,116,99,104,101,114,32,103,105,118,101,115,32,117,112,32,105,109,109,101,100,105,97,116,101,108,121,32,111,110,32,102,97,105,108,105,110,103,32,116,111,32,109,97,116,99,104,32,34,102,111,111,34,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,46,32,84,104,101,32,110,111,116,97,116,105,111,110,32,105,115,32,97,32,107,105,110,100,32,111,102,32,115,112,101,99,105,97,108,32,112,97,114,101,110,116,104,101,115,105,115,44,32,115,116,97,114,116,105,110,103,32,119,105,116,104,32>>,{code,[],[<<40,63,62>>]},<<32,97,115,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,63,62,92,100,43,41,102,111,111>>]}]},{p,[],[<<84,104,105,115,32,107,105,110,100,32,111,102,32,112,97,114,101,110,116,104,101,115,105,115,32,34,108,111,99,107,115,32,117,112,34,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,116,32,99,111,110,116,97,105,110,115,32,111,110,99,101,32,105,116,32,104,97,115,32,109,97,116,99,104,101,100,44,32,97,110,100,32,97,32,102,97,105,108,117,114,101,32,102,117,114,116,104,101,114,32,105,110,116,111,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,112,114,101,118,101,110,116,101,100,32,102,114,111,109,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,105,116,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,112,97,115,116,32,105,116,32,116,111,32,112,114,101,118,105,111,117,115,32,105,116,101,109,115,44,32,104,111,119,101,118,101,114,44,32,119,111,114,107,115,32,97,115,32,110,111,114,109,97,108,46>>]},{p,[],[<<65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,101,115,99,114,105,112,116,105,111,110,32,105,115,32,116,104,97,116,32,97,32,115,117,98,112,97,116,116,101,114,110,32,111,102,32,116,104,105,115,32,116,121,112,101,32,109,97,116,99,104,101,115,32,116,104,101,32,115,116,114,105,110,103,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,110,32,105,100,101,110,116,105,99,97,108,32,115,116,97,110,100,97,108,111,110,101,32,112,97,116,116,101,114,110,32,119,111,117,108,100,32,109,97,116,99,104,44,32,105,102,32,97,110,99,104,111,114,101,100,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,105,110,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]},{p,[],[<<65,116,111,109,105,99,32,103,114,111,117,112,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,110,111,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,83,105,109,112,108,101,32,99,97,115,101,115,32,115,117,99,104,32,97,115,32,116,104,101,32,97,98,111,118,101,32,101,120,97,109,112,108,101,32,99,97,110,32,98,101,32,116,104,111,117,103,104,116,32,111,102,32,97,115,32,97,32,109,97,120,105,109,105,122,105,110,103,32,114,101,112,101,97,116,32,116,104,97,116,32,109,117,115,116,32,115,119,97,108,108,111,119,32,101,118,101,114,121,116,104,105,110,103,32,105,116,32,99,97,110,46,32,83,111,44,32,119,104,105,108,101,32,98,111,116,104,32,92,100,43,32,97,110,100,32,92,100,43,63,32,97,114,101,32,112,114,101,112,97,114,101,100,32,116,111,32,97,100,106,117,115,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,103,105,116,115,32,116,104,101,121,32,109,97,116,99,104,32,116,111,32,109,97,107,101,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,44,32>>,{code,[],[<<40,63,62,92,100,43,41>>]},<<32,99,97,110,32,111,110,108,121,32,109,97,116,99,104,32,97,110,32,101,110,116,105,114,101,32,115,101,113,117,101,110,99,101,32,111,102,32,100,105,103,105,116,115,46>>]},{p,[],[<<65,116,111,109,105,99,32,103,114,111,117,112,115,32,105,110,32,103,101,110,101,114,97,108,32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,99,111,109,112,108,105,99,97,116,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,97,110,100,32,99,97,110,32,98,101,32,110,101,115,116,101,100,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,102,111,114,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,105,115,32,106,117,115,116,32,97,32,115,105,110,103,108,101,32,114,101,112,101,97,116,101,100,32,105,116,101,109,44,32,97,115,32,105,110,32,116,104,101,32,101,120,97,109,112,108,101,32,97,98,111,118,101,44,32,97,32,115,105,109,112,108,101,114,32,110,111,116,97,116,105,111,110,44,32,99,97,108,108,101,100,32,97,32,34,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,34,32,99,97,110,32,98,101,32,117,115,101,100,46,32,84,104,105,115,32,99,111,110,115,105,115,116,115,32,111,102,32,97,110,32,101,120,116,114,97,32,43,32,99,104,97,114,97,99,116,101,114,32,102,111,108,108,111,119,105,110,103,32,97,32,113,117,97,110,116,105,102,105,101,114,46,32,85,115,105,110,103,32,116,104,105,115,32,110,111,116,97,116,105,111,110,44,32,116,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,32,99,97,110,32,98,101,32,114,101,119,114,105,116,116,101,110,32,97,115>>]},{pre,[],[{code,[],[<<92,100,43,43,102,111,111>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,97,110,32,101,110,116,105,114,101,32,103,114,111,117,112,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,98,99,124,120,121,122,41,123,50,44,51,125,43>>]}]},{p,[],[<<80,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,97,108,119,97,121,115,32,103,114,101,101,100,121,59,32,116,104,101,32,115,101,116,116,105,110,103,32,111,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,103,114,101,101,100,121>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,121,32,97,114,101,32,97,32,99,111,110,118,101,110,105,101,110,116,32,110,111,116,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,105,109,112,108,101,114,32,102,111,114,109,115,32,111,102,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,72,111,119,101,118,101,114,44,32,116,104,101,114,101,32,105,115,32,110,111,32,100,105,102,102,101,114,101,110,99,101,32,105,110,32,116,104,101,32,109,101,97,110,105,110,103,32,111,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,97,110,100,32,116,104,101,32,101,113,117,105,118,97,108,101,110,116,32,97,116,111,109,105,99,32,103,114,111,117,112,44,32,98,117,116,32,116,104,101,114,101,32,99,97,110,32,98,101,32,97,32,112,101,114,102,111,114,109,97,110,99,101,32,100,105,102,102,101,114,101,110,99,101,59,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,112,114,111,98,97,98,108,121,32,115,108,105,103,104,116,108,121,32,102,97,115,116,101,114,46>>]},{p,[],[<<84,104,101,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,115,121,110,116,97,120,32,105,115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,116,111,32,116,104,101,32,80,101,114,108,32,53,46,56,32,115,121,110,116,97,120,46,32,74,101,102,102,114,101,121,32,70,114,105,101,100,108,32,111,114,105,103,105,110,97,116,101,100,32,116,104,101,32,105,100,101,97,32,40,97,110,100,32,116,104,101,32,110,97,109,101,41,32,105,110,32,116,104,101,32,102,105,114,115,116,32,101,100,105,116,105,111,110,32,111,102,32,104,105,115,32,98,111,111,107,46,32,77,105,107,101,32,77,99,67,108,111,115,107,101,121,32,108,105,107,101,100,32,105,116,44,32,115,111,32,105,109,112,108,101,109,101,110,116,101,100,32,105,116,32,119,104,101,110,32,104,101,32,98,117,105,108,116,32,116,104,101,32,83,117,110,32,74,97,118,97,32,112,97,99,107,97,103,101,44,32,97,110,100,32,80,67,82,69,32,99,111,112,105,101,100,32,105,116,32,102,114,111,109,32,116,104,101,114,101,46,32,73,116,32,117,108,116,105,109,97,116,101,108,121,32,102,111,117,110,100,32,105,116,115,32,119,97,121,32,105,110,116,111,32,80,101,114,108,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,48,46>>]},{p,[],[<<80,67,82,69,32,104,97,115,32,97,110,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,34,112,111,115,115,101,115,115,105,102,105,101,115,34,32,99,101,114,116,97,105,110,32,115,105,109,112,108,101,32,112,97,116,116,101,114,110,32,99,111,110,115,116,114,117,99,116,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,115,101,113,117,101,110,99,101,32,65,43,66,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,65,43,43,66,44,32,97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,112,111,105,110,116,32,105,110,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,65,58,115,32,119,104,101,110,32,66,32,109,117,115,116,32,102,111,108,108,111,119,46>>]},{p,[],[<<87,104,101,110,32,97,32,112,97,116,116,101,114,110,32,99,111,110,116,97,105,110,115,32,97,110,32,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,32,105,110,115,105,100,101,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,99,97,110,32,105,116,115,101,108,102,32,98,101,32,114,101,112,101,97,116,101,100,32,97,110,32,117,110,108,105,109,105,116,101,100,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,44,32,116,104,101,32,117,115,101,32,111,102,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,105,115,32,116,104,101,32,111,110,108,121,32,119,97,121,32,116,111,32,97,118,111,105,100,32,115,111,109,101,32,102,97,105,108,105,110,103,32,109,97,116,99,104,101,115,32,116,97,107,105,110,103,32,97,32,108,111,110,103,32,116,105,109,101,46,32,84,104,101,32,112,97,116,116,101,114,110>>]},{pre,[],[{code,[],[<<40,92,68,43,124,60,92,100,43,62,41,42,91,33,63,93>>]}]},{p,[],[<<109,97,116,99,104,101,115,32,97,110,32,117,110,108,105,109,105,116,101,100,32,110,117,109,98,101,114,32,111,102,32,115,117,98,115,116,114,105,110,103,115,32,116,104,97,116,32,101,105,116,104,101,114,32,99,111,110,115,105,115,116,32,111,102,32,110,111,110,45,100,105,103,105,116,115,44,32,111,114,32,100,105,103,105,116,115,32,101,110,99,108,111,115,101,100,32,105,110,32,60,62,44,32,102,111,108,108,111,119,101,100,32,98,121,32,33,32,111,114,32,63,46,32,87,104,101,110,32,105,116,32,109,97,116,99,104,101,115,44,32,105,116,32,114,117,110,115,32,113,117,105,99,107,108,121,46,32,72,111,119,101,118,101,114,44,32,105,102,32,105,116,32,105,115,32,97,112,112,108,105,101,100,32,116,111>>]},{pre,[],[{code,[],[<<97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97>>]}]},{p,[],[<<105,116,32,116,97,107,101,115,32,97,32,108,111,110,103,32,116,105,109,101,32,98,101,102,111,114,101,32,114,101,112,111,114,116,105,110,103,32,102,97,105,108,117,114,101,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,115,116,114,105,110,103,32,99,97,110,32,98,101,32,100,105,118,105,100,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,105,110,116,101,114,110,97,108,32,92,68,43,32,114,101,112,101,97,116,32,97,110,100,32,116,104,101,32,101,120,116,101,114,110,97,108,32,42,32,114,101,112,101,97,116,32,105,110,32,109,97,110,121,32,119,97,121,115,44,32,97,110,100,32,97,108,108,32,109,117,115,116,32,98,101,32,116,114,105,101,100,46,32,40,84,104,101,32,101,120,97,109,112,108,101,32,117,115,101,115,32,91,33,63,93,32,114,97,116,104,101,114,32,116,104,97,110,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,97,116,32,116,104,101,32,101,110,100,44,32,97,115,32,98,111,116,104,32,80,67,82,69,32,97,110,100,32,80,101,114,108,32,104,97,118,101,32,97,110,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,97,108,108,111,119,115,32,102,111,114,32,102,97,115,116,32,102,97,105,108,117,114,101,32,119,104,101,110,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,105,115,32,117,115,101,100,46,32,84,104,101,121,32,114,101,109,101,109,98,101,114,32,116,104,101,32,108,97,115,116,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,114,101,113,117,105,114,101,100,32,102,111,114,32,97,32,109,97,116,99,104,44,32,97,110,100,32,102,97,105,108,32,101,97,114,108,121,32,105,102,32,105,116,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,115,116,114,105,110,103,46,41,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,105,116,32,117,115,101,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,44,32,108,105,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,115,101,113,117,101,110,99,101,115,32,111,102,32,110,111,110,45,100,105,103,105,116,115,32,99,97,110,110,111,116,32,98,101,32,98,114,111,107,101,110,44,32,97,110,100,32,102,97,105,108,117,114,101,32,104,97,112,112,101,110,115,32,113,117,105,99,107,108,121,58>>]},{pre,[],[{code,[],[<<40,40,63,62,92,68,43,41,124,60,92,100,43,62,41,42,91,33,63,93>>]}]},{a,[{id,<<115,101,99,116,49,54>>}],[]},{h2,[],[<<66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,32,98,97,99,107,115,108,97,115,104,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,100,105,103,105,116,32,62,32,48,32,40,97,110,100,32,112,111,115,115,105,98,108,121,32,102,117,114,116,104,101,114,32,100,105,103,105,116,115,41,32,105,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,101,97,114,108,105,101,114,32,40,116,104,97,116,32,105,115,44,32,116,111,32,105,116,115,32,108,101,102,116,41,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,44,32,112,114,111,118,105,100,101,100,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,32,116,104,97,116,32,109,97,110,121,32,112,114,101,118,105,111,117,115,32,99,97,112,116,117,114,105,110,103,32,108,101,102,116,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,100,101,99,105,109,97,108,32,110,117,109,98,101,114,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,98,97,99,107,115,108,97,115,104,32,105,115,32,60,32,49,48,44,32,105,116,32,105,115,32,97,108,119,97,121,115,32,116,97,107,101,110,32,97,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,97,110,100,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,97,114,101,32,110,111,116,32,116,104,97,116,32,109,97,110,121,32,99,97,112,116,117,114,105,110,103,32,108,101,102,116,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,101,110,116,105,114,101,32,112,97,116,116,101,114,110,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,114,101,102,101,114,101,110,99,101,100,32,100,111,32,110,101,101,100,32,110,111,116,32,98,101,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,116,104,101,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,110,117,109,98,101,114,115,32,60,32,49,48,46,32,65,32,34,102,111,114,119,97,114,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,34,32,111,102,32,116,104,105,115,32,116,121,112,101,32,99,97,110,32,109,97,107,101,32,115,101,110,115,101,32,119,104,101,110,32,97,32,114,101,112,101,116,105,116,105,111,110,32,105,115,32,105,110,118,111,108,118,101,100,32,97,110,100,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,116,111,32,116,104,101,32,114,105,103,104,116,32,104,97,115,32,112,97,114,116,105,99,105,112,97,116,101,100,32,105,110,32,97,110,32,101,97,114,108,105,101,114,32,105,116,101,114,97,116,105,111,110,46>>]},{p,[],[<<73,116,32,105,115,32,110,111,116,32,112,111,115,115,105,98,108,101,32,116,111,32,104,97,118,101,32,97,32,110,117,109,101,114,105,99,97,108,32,34,102,111,114,119,97,114,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,34,32,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,119,104,111,115,101,32,110,117,109,98,101,114,32,105,115,32,49,48,32,111,114,32,109,111,114,101,32,117,115,105,110,103,32,116,104,105,115,32,115,121,110,116,97,120,44,32,97,115,32,97,32,115,101,113,117,101,110,99,101,32,115,117,99,104,32,97,115,32,92,53,48,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,99,104,97,114,97,99,116,101,114,32,100,101,102,105,110,101,100,32,105,110,32,111,99,116,97,108,46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,111,102,32,116,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,97,32,98,97,99,107,115,108,97,115,104,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,111,110,95,112,114,105,110,116,105,110,103,95,99,104,97,114,97,99,116,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,111,110,45,80,114,105,110,116,105,110,103,32,67,104,97,114,97,99,116,101,114,115>>]},<<32,101,97,114,108,105,101,114,46,32,84,104,101,114,101,32,105,115,32,110,111,32,115,117,99,104,32,112,114,111,98,108,101,109,32,119,104,101,110,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,117,115,101,100,46,32,65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,97,110,121,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,112,111,115,115,105,98,108,101,32,117,115,105,110,103,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,40,115,101,101,32,98,101,108,111,119,41,46>>]},{p,[],[<<65,110,111,116,104,101,114,32,119,97,121,32,116,111,32,97,118,111,105,100,32,116,104,101,32,97,109,98,105,103,117,105,116,121,32,105,110,104,101,114,101,110,116,32,105,110,32,116,104,101,32,117,115,101,32,111,102,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,97,32,98,97,99,107,115,108,97,115,104,32,105,115,32,116,111,32,117,115,101,32,116,104,101,32,92,103,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,46,32,84,104,105,115,32,101,115,99,97,112,101,32,109,117,115,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,117,110,115,105,103,110,101,100,32,110,117,109,98,101,114,32,111,114,32,97,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,44,32,111,112,116,105,111,110,97,108,108,121,32,101,110,99,108,111,115,101,100,32,105,110,32,98,114,97,99,101,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,115,32,97,114,101,32,105,100,101,110,116,105,99,97,108,58>>]},{pre,[],[{code,[],[<<40,114,105,110,103,41,44,32,92,49,10,40,114,105,110,103,41,44,32,92,103,49,10,40,114,105,110,103,41,44,32,92,103,123,49,125>>]}]},{p,[],[<<65,110,32,117,110,115,105,103,110,101,100,32,110,117,109,98,101,114,32,115,112,101,99,105,102,105,101,115,32,97,110,32,97,98,115,111,108,117,116,101,32,114,101,102,101,114,101,110,99,101,32,119,105,116,104,111,117,116,32,116,104,101,32,97,109,98,105,103,117,105,116,121,32,116,104,97,116,32,105,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,111,108,100,101,114,32,115,121,110,116,97,120,46,32,73,116,32,105,115,32,97,108,115,111,32,117,115,101,102,117,108,32,119,104,101,110,32,108,105,116,101,114,97,108,32,100,105,103,105,116,115,32,102,111,108,108,111,119,32,116,104,101,32,114,101,102,101,114,101,110,99,101,46,32,65,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,32,105,115,32,97,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,98,99,40,100,101,102,41,103,104,105,41,92,103,123,45,49,125>>]}]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,32,92,103,123,45,49,125,32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,115,116,97,114,116,101,100,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,98,101,102,111,114,101,32,92,103,44,32,116,104,97,116,32,105,115,44,32,105,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,92,50,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,46,32,83,105,109,105,108,97,114,108,121,44,32,92,103,123,45,50,125,32,119,111,117,108,100,32,98,101,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,92,49,46,32,84,104,101,32,117,115,101,32,111,102,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,115,32,99,97,110,32,98,101,32,104,101,108,112,102,117,108,32,105,110,32,108,111,110,103,32,112,97,116,116,101,114,110,115,44,32,97,110,100,32,97,108,115,111,32,105,110,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,99,114,101,97,116,101,100,32,98,121,32,106,111,105,110,105,110,103,32,102,114,97,103,109,101,110,116,115,32,99,111,110,116,97,105,110,105,110,103,32,114,101,102,101,114,101,110,99,101,115,32,119,105,116,104,105,110,32,116,104,101,109,115,101,108,118,101,115,46>>]},{p,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,109,97,116,99,104,101,115,32,119,104,97,116,101,118,101,114,32,109,97,116,99,104,101,100,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,114,97,116,104,101,114,32,116,104,97,110,32,97,110,121,116,104,105,110,103,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,116,115,101,108,102,32,40,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,32,97,115,32,83,117,98,114,111,117,116,105,110,101,115>>]},<<32,100,101,115,99,114,105,98,101,115,32,97,32,119,97,121,32,111,102,32,100,111,105,110,103,32,116,104,97,116,41,46,32,83,111,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,115,101,110,115,101,32,97,110,100,32,115,101,110,115,105,98,105,108,105,116,121,34,32,97,110,100,32,34,114,101,115,112,111,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,44,32,98,117,116,32,110,111,116,32,34,115,101,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,58>>]},{pre,[],[{code,[],[<<40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,92,49,105,98,105,108,105,116,121>>]}]},{p,[],[<<73,102,32,99,97,115,101,102,117,108,32,109,97,116,99,104,105,110,103,32,105,115,32,105,110,32,102,111,114,99,101,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,116,104,101,32,99,97,115,101,32,111,102,32,108,101,116,116,101,114,115,32,105,115,32,114,101,108,101,118,97,110,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,114,97,104,32,114,97,104,34,32,97,110,100,32,34,82,65,72,32,82,65,72,34,44,32,98,117,116,32,110,111,116,32,34,82,65,72,32,114,97,104,34,44,32,97,108,116,104,111,117,103,104,32,116,104,101,32,111,114,105,103,105,110,97,108,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,109,97,116,99,104,101,100,32,99,97,115,101,108,101,115,115,108,121,58>>]},{pre,[],[{code,[],[<<40,40,63,105,41,114,97,104,41,92,115,43,92,49>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,32,111,102,32,119,114,105,116,105,110,103,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46,32,84,104,101,32,46,78,69,84,32,115,121,110,116,97,120,32>>,{code,[],[<<92,107,123,110,97,109,101,125>>]},<<32,97,110,100,32,116,104,101,32,80,101,114,108,32,115,121,110,116,97,120,32>>,{code,[],[<<92,107,60,110,97,109,101,62>>]},<<32,111,114,32>>,{code,[],[<<92,107,39,110,97,109,101,39>>]},<<32,97,114,101,32,115,117,112,112,111,114,116,101,100,44,32,97,115,32,105,115,32,116,104,101,32,80,121,116,104,111,110,32,115,121,110,116,97,120,32>>,{code,[],[<<40,63,80,61,110,97,109,101,41>>]},<<46,32,84,104,101,32,117,110,105,102,105,101,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,115,121,110,116,97,120,32,105,110,32,80,101,114,108,32,53,46,49,48,44,32,105,110,32,119,104,105,99,104,32,92,103,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,98,111,116,104,32,110,117,109,101,114,105,99,32,97,110,100,32,110,97,109,101,100,32,114,101,102,101,114,101,110,99,101,115,44,32,105,115,32,97,108,115,111,32,115,117,112,112,111,114,116,101,100,46,32,84,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,32,99,97,110,32,98,101,32,114,101,119,114,105,116,116,101,110,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,119,97,121,115,58>>]},{pre,[],[{code,[],[<<40,63,60,112,49,62,40,63,105,41,114,97,104,41,92,115,43,92,107,60,112,49,62,10,40,63,39,112,49,39,40,63,105,41,114,97,104,41,92,115,43,92,107,123,112,49,125,10,40,63,80,60,112,49,62,40,63,105,41,114,97,104,41,92,115,43,40,63,80,61,112,49,41,10,40,63,60,112,49,62,40,63,105,41,114,97,104,41,92,115,43,92,103,123,112,49,125>>]}]},{p,[],[<<65,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,105,115,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32,110,97,109,101,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,98,101,102,111,114,101,32,111,114,32,97,102,116,101,114,32,116,104,101,32,114,101,102,101,114,101,110,99,101,46>>]},{p,[],[<<84,104,101,114,101,32,99,97,110,32,98,101,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,115,97,109,101,32,115,117,98,112,97,116,116,101,114,110,46,32,73,102,32,97,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,110,111,116,32,98,101,101,110,32,117,115,101,100,32,105,110,32,97,32,112,97,114,116,105,99,117,108,97,114,32,109,97,116,99,104,44,32,97,110,121,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,105,116,32,97,108,119,97,121,115,32,102,97,105,108,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,97,108,119,97,121,115,32,102,97,105,108,115,32,105,102,32,105,116,32,115,116,97,114,116,115,32,116,111,32,109,97,116,99,104,32,34,97,34,32,114,97,116,104,101,114,32,116,104,97,110,32,34,98,99,34,58>>]},{pre,[],[{code,[],[<<40,97,124,40,98,99,41,41,92,50>>]}]},{p,[],[<<65,115,32,116,104,101,114,101,32,99,97,110,32,98,101,32,109,97,110,121,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,97,108,108,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,98,97,99,107,115,108,97,115,104,32,97,114,101,32,116,97,107,101,110,32,97,115,32,112,97,114,116,32,111,102,32,97,32,112,111,116,101,110,116,105,97,108,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,110,117,109,98,101,114,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,99,111,110,116,105,110,117,101,115,32,119,105,116,104,32,97,32,100,105,103,105,116,32,99,104,97,114,97,99,116,101,114,44,32,115,111,109,101,32,100,101,108,105,109,105,116,101,114,32,109,117,115,116,32,98,101,32,117,115,101,100,32,116,111,32,116,101,114,109,105,110,97,116,101,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,105,115,32,115,101,116,44,32,116,104,105,115,32,99,97,110,32,98,101,32,119,104,105,116,101,115,112,97,99,101,46,32,79,116,104,101,114,119,105,115,101,32,97,110,32,101,109,112,116,121,32,99,111,109,109,101,110,116,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,57>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,111,109,109,101,110,116,115>>]},<<41,32,99,97,110,32,98,101,32,117,115,101,100,46>>]},{p,[],[{em,[],[<<82,101,99,117,114,115,105,118,101,32,66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]}]},{p,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,104,97,116,32,111,99,99,117,114,115,32,105,110,115,105,100,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,111,32,119,104,105,99,104,32,105,116,32,114,101,102,101,114,115,32,102,97,105,108,115,32,119,104,101,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,102,105,114,115,116,32,117,115,101,100,44,32,115,111,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,40,97,92,49,41,32,110,101,118,101,114,32,109,97,116,99,104,101,115,46,32,72,111,119,101,118,101,114,44,32,115,117,99,104,32,114,101,102,101,114,101,110,99,101,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,105,110,115,105,100,101,32,114,101,112,101,97,116,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,34,97,34,115,32,97,110,100,32,97,108,115,111,32,34,97,98,97,34,44,32,34,97,98,97,98,98,97,97,34,44,32,97,110,100,32,115,111,32,111,110,58>>]},{pre,[],[{code,[],[<<40,97,124,98,92,49,41,43>>]}]},{p,[],[<<65,116,32,101,97,99,104,32,105,116,101,114,97,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,44,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,109,97,116,99,104,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,112,114,101,118,105,111,117,115,32,105,116,101,114,97,116,105,111,110,46,32,73,110,32,111,114,100,101,114,32,102,111,114,32,116,104,105,115,32,116,111,32,119,111,114,107,44,32,116,104,101,32,112,97,116,116,101,114,110,32,109,117,115,116,32,98,101,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,102,105,114,115,116,32,105,116,101,114,97,116,105,111,110,32,100,111,101,115,32,110,111,116,32,110,101,101,100,32,116,111,32,109,97,116,99,104,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,46,32,84,104,105,115,32,99,97,110,32,98,101,32,100,111,110,101,32,117,115,105,110,103,32,97,108,116,101,114,110,97,116,105,111,110,44,32,97,115,32,105,110,32,116,104,101,32,101,120,97,109,112,108,101,32,97,98,111,118,101,44,32,111,114,32,98,121,32,97,32,113,117,97,110,116,105,102,105,101,114,32,119,105,116,104,32,97,32,109,105,110,105,109,117,109,32,111,102,32,122,101,114,111,46>>]},{p,[],[<<66,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,111,102,32,116,104,105,115,32,116,121,112,101,32,99,97,117,115,101,32,116,104,101,32,103,114,111,117,112,32,116,104,97,116,32,116,104,101,121,32,114,101,102,101,114,101,110,99,101,32,116,111,32,98,101,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,79,110,99,101,32,116,104,101,32,119,104,111,108,101,32,103,114,111,117,112,32,104,97,115,32,98,101,101,110,32,109,97,116,99,104,101,100,44,32,97,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,99,97,110,110,111,116,32,99,97,117,115,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,116,104,101,32,109,105,100,100,108,101,32,111,102,32,116,104,101,32,103,114,111,117,112,46>>]},{a,[{id,<<115,101,99,116,49,55>>}],[]},{h2,[],[<<65,115,115,101,114,116,105,111,110,115>>]},{p,[],[<<65,110,32,97,115,115,101,114,116,105,111,110,32,105,115,32,97,32,116,101,115,116,32,111,110,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,102,111,108,108,111,119,105,110,103,32,111,114,32,112,114,101,99,101,100,105,110,103,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,99,111,110,115,117,109,101,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,115,105,109,112,108,101,32,97,115,115,101,114,116,105,111,110,115,32,99,111,100,101,100,32,97,115,32,92,98,44,32,92,66,44,32,92,65,44,32,92,71,44,32,92,90,44,32,92,122,44,32,94,44,32,97,110,100,32,36,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,101,99,116,105,111,110,115,46>>]},{p,[],[<<77,111,114,101,32,99,111,109,112,108,105,99,97,116,101,100,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,32,99,111,100,101,100,32,97,115,32,115,117,98,112,97,116,116,101,114,110,115,46,32,84,104,101,114,101,32,97,114,101,32,116,119,111,32,107,105,110,100,115,58,32,116,104,111,115,101,32,116,104,97,116,32,108,111,111,107,32,97,104,101,97,100,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,110,100,32,116,104,111,115,101,32,116,104,97,116,32,108,111,111,107,32,98,101,104,105,110,100,32,105,116,46,32,65,110,32,97,115,115,101,114,116,105,111,110,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,109,97,116,99,104,101,100,32,105,110,32,116,104,101,32,110,111,114,109,97,108,32,119,97,121,44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,100,111,101,115,32,110,111,116,32,99,97,117,115,101,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,32,116,111,32,98,101,32,99,104,97,110,103,101,100,46>>]},{p,[],[<<65,115,115,101,114,116,105,111,110,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,110,111,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,73,102,32,115,117,99,104,32,97,110,32,97,115,115,101,114,116,105,111,110,32,99,111,110,116,97,105,110,115,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,105,110,32,105,116,44,32,116,104,101,115,101,32,97,114,101,32,99,111,117,110,116,101,100,32,102,111,114,32,116,104,101,32,112,117,114,112,111,115,101,115,32,111,102,32,110,117,109,98,101,114,105,110,103,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,46,32,72,111,119,101,118,101,114,44,32,115,117,98,115,116,114,105,110,103,32,99,97,112,116,117,114,105,110,103,32,105,115,32,100,111,110,101,32,111,110,108,121,32,102,111,114,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,40,80,101,114,108,32,115,111,109,101,116,105,109,101,115,44,32,98,117,116,32,110,111,116,32,97,108,119,97,121,115,44,32,112,101,114,102,111,114,109,115,32,99,97,112,116,117,114,105,110,103,32,105,110,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,41>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,102,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,99,111,110,116,97,105,110,105,110,103,32,111,110,101,32,111,114,32,109,111,114,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,115,117,99,99,101,101,100,115,44,32,98,117,116,32,102,97,105,108,117,114,101,32,116,111,32,109,97,116,99,104,32,108,97,116,101,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,99,97,117,115,101,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,111,118,101,114,32,116,104,105,115,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,99,97,112,116,117,114,101,115,32,119,105,116,104,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,97,114,101,32,114,101,115,101,116,32,111,110,108,121,32,105,102,32,110,111,32,104,105,103,104,101,114,32,110,117,109,98,101,114,101,100,32,99,97,112,116,117,114,101,115,32,97,114,101,32,97,108,114,101,97,100,121,32,115,101,116,46,32,84,104,105,115,32,105,115,44,32,117,110,102,111,114,116,117,110,97,116,101,108,121,44,32,97,32,102,117,110,100,97,109,101,110,116,97,108,32,108,105,109,105,116,97,116,105,111,110,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,44,32,97,110,100,32,97,115,32,80,67,82,69,49,32,105,115,32,110,111,119,32,105,110,32,109,97,105,110,116,101,110,97,110,99,101,45,111,110,108,121,32,115,116,97,116,117,115,44,32,105,116,32,105,115,32,117,110,108,105,107,101,108,121,32,101,118,101,114,32,116,111,32,99,104,97,110,103,101,46>>]}]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,80,101,114,108,44,32,97,115,115,101,114,116,105,111,110,32,115,117,98,112,97,116,116,101,114,110,115,32,99,97,110,32,98,101,32,114,101,112,101,97,116,101,100,46,32,72,111,119,101,118,101,114,44,32,105,116,32,109,97,107,101,115,32,110,111,32,115,101,110,115,101,32,116,111,32,97,115,115,101,114,116,32,116,104,101,32,115,97,109,101,32,116,104,105,110,103,32,109,97,110,121,32,116,105,109,101,115,44,32,116,104,101,32,115,105,100,101,32,101,102,102,101,99,116,32,111,102,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,111,99,99,97,115,105,111,110,97,108,108,121,32,98,101,32,117,115,101,102,117,108,46,32,73,110,32,112,114,97,99,116,105,99,101,44,32,116,104,101,114,101,32,97,114,101,32,111,110,108,121,32,116,104,114,101,101,32,99,97,115,101,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,123,48,125,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,105,115,32,110,101,118,101,114,32,111,98,101,121,101,100,32,100,117,114,105,110,103,32,109,97,116,99,104,105,110,103,46,32,72,111,119,101,118,101,114,44,32,105,116,32,99,97,110,32,99,111,110,116,97,105,110,32,105,110,116,101,114,110,97,108,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,103,114,111,117,112,115,32,116,104,97,116,32,97,114,101,32,99,97,108,108,101,100,32,102,114,111,109,32,101,108,115,101,119,104,101,114,101,32,116,104,114,111,117,103,104,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,101,99,104,97,110,105,115,109,46>>]}]},{li,[],[{p,[],[<<73,102,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,123,48,44,110,125,44,32,119,104,101,114,101,32,110,32,62,32,48,44,32,105,116,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,105,102,32,105,116,32,119,97,115,32,123,48,44,49,125,46,32,65,116,32,114,117,110,116,105,109,101,44,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,32,105,115,32,116,114,105,101,100,32,119,105,116,104,32,97,110,100,32,119,105,116,104,111,117,116,32,116,104,101,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,111,114,100,101,114,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,103,114,101,101,100,105,110,101,115,115,32,111,102,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,46>>]}]},{li,[],[{p,[],[<<73,102,32,116,104,101,32,109,105,110,105,109,117,109,32,114,101,112,101,116,105,116,105,111,110,32,105,115,32,62,32,48,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,32,97,115,115,101,114,116,105,111,110,32,105,115,32,111,98,101,121,101,100,32,111,110,108,121,32,111,110,99,101,32,119,104,101,110,32,101,110,99,111,117,110,116,101,114,101,100,32,100,117,114,105,110,103,32,109,97,116,99,104,105,110,103,46>>]}]}]},{p,[],[{em,[],[<<76,111,111,107,97,104,101,97,100,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<76,111,111,107,97,104,101,97,100,32,97,115,115,101,114,116,105,111,110,115,32,115,116,97,114,116,32,119,105,116,104,32,40,63,61,32,102,111,114,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,97,110,100,32,40,63,33,32,102,111,114,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,32,119,111,114,100,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,115,101,109,105,99,111,108,111,110,44,32,98,117,116,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,116,104,101,32,115,101,109,105,99,111,108,111,110,32,105,110,32,116,104,101,32,109,97,116,99,104,58>>]},{pre,[],[{code,[],[<<92,119,43,40,63,61,59,41>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,110,121,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,102,111,111,34,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32,34,98,97,114,34,58>>]},{pre,[],[{code,[],[<<102,111,111,40,63,33,98,97,114,41>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,97,112,112,97,114,101,110,116,108,121,32,115,105,109,105,108,97,114,32,112,97,116,116,101,114,110>>]},{pre,[],[{code,[],[<<40,63,33,102,111,111,41,98,97,114>>]}]},{p,[],[<<100,111,101,115,32,110,111,116,32,102,105,110,100,32,97,110,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,114,34,32,116,104,97,116,32,105,115,32,112,114,101,99,101,100,101,100,32,98,121,32,115,111,109,101,116,104,105,110,103,32,111,116,104,101,114,32,116,104,97,110,32,34,102,111,111,34,46,32,73,116,32,102,105,110,100,115,32,97,110,121,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,114,34,32,119,104,97,116,115,111,101,118,101,114,44,32,97,115,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,40,63,33,102,111,111,41,32,105,115,32,97,108,119,97,121,115,32,116,114,117,101,32,119,104,101,110,32,116,104,101,32,110,101,120,116,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,34,98,97,114,34,46,32,65,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,105,115,32,110,101,101,100,101,100,32,116,111,32,97,99,104,105,101,118,101,32,116,104,101,32,111,116,104,101,114,32,101,102,102,101,99,116,46>>]},{p,[],[<<73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,102,111,114,99,101,32,97,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,97,116,32,115,111,109,101,32,112,111,105,110,116,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,116,104,101,32,109,111,115,116,32,99,111,110,118,101,110,105,101,110,116,32,119,97,121,32,116,111,32,100,111,32,105,116,32,105,115,32,119,105,116,104,32,40,63,33,41,44,32,97,115,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,46,32,83,111,44,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,114,101,113,117,105,114,101,115,32,116,104,101,114,101,32,105,115,32,110,111,116,32,116,111,32,98,101,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,109,117,115,116,32,97,108,119,97,121,115,32,102,97,105,108,46,32,84,104,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,111,110,116,114,111,108,32,118,101,114,98,32,40,42,70,65,73,76,41,32,111,114,32,40,42,70,41,32,105,115,32,97,32,115,121,110,111,110,121,109,32,102,111,114,32,40,63,33,41,46>>]},{p,[],[{em,[],[<<76,111,111,107,98,101,104,105,110,100,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<76,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,115,116,97,114,116,32,119,105,116,104,32,40,63,60,61,32,102,111,114,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,97,110,100,32,40,63,60,33,32,102,111,114,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,110,100,115,32,97,110,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,114,34,32,116,104,97,116,32,105,115,32,110,111,116,32,112,114,101,99,101,100,101,100,32,98,121,32,34,102,111,111,34,58>>]},{pre,[],[{code,[],[<<40,63,60,33,102,111,111,41,98,97,114>>]}]},{p,[],[<<84,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,97,114,101,32,114,101,115,116,114,105,99,116,101,100,32,115,117,99,104,32,116,104,97,116,32,97,108,108,32,116,104,101,32,115,116,114,105,110,103,115,32,105,116,32,109,97,116,99,104,101,115,32,109,117,115,116,32,104,97,118,101,32,97,32,102,105,120,101,100,32,108,101,110,103,116,104,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,114,101,32,97,114,101,32,109,97,110,121,32,116,111,112,45,108,101,118,101,108,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,116,104,101,121,32,100,111,32,110,111,116,32,97,108,108,32,104,97,118,101,32,116,111,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,102,105,120,101,100,32,108,101,110,103,116,104,46,32,84,104,117,115,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,112,101,114,109,105,116,116,101,100,58>>]},{pre,[],[{code,[],[<<40,63,60,61,98,117,108,108,111,99,107,124,100,111,110,107,101,121,41>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,58>>]},{pre,[],[{code,[],[<<40,63,60,33,100,111,103,115,63,124,99,97,116,115,63,41>>]}]},{p,[],[<<66,114,97,110,99,104,101,115,32,116,104,97,116,32,109,97,116,99,104,32,100,105,102,102,101,114,101,110,116,32,108,101,110,103,116,104,32,115,116,114,105,110,103,115,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,111,110,108,121,32,97,116,32,116,104,101,32,116,111,112,45,108,101,118,101,108,32,111,102,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,46,32,84,104,105,115,32,105,115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,99,111,109,112,97,114,101,100,32,119,105,116,104,32,80,101,114,108,44,32,119,104,105,99,104,32,114,101,113,117,105,114,101,115,32,97,108,108,32,98,114,97,110,99,104,101,115,32,116,111,32,109,97,116,99,104,32,116,104,101,32,115,97,109,101,32,108,101,110,103,116,104,32,111,102,32,115,116,114,105,110,103,46,32,65,110,32,97,115,115,101,114,116,105,111,110,32,115,117,99,104,32,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,110,111,116,32,112,101,114,109,105,116,116,101,100,44,32,97,115,32,105,116,115,32,115,105,110,103,108,101,32,116,111,112,45,108,101,118,101,108,32,98,114,97,110,99,104,32,99,97,110,32,109,97,116,99,104,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,108,101,110,103,116,104,115,58>>]},{pre,[],[{code,[],[<<40,63,60,61,97,98,40,99,124,100,101,41,41>>]}]},{p,[],[<<72,111,119,101,118,101,114,44,32,105,116,32,105,115,32,97,99,99,101,112,116,97,98,108,101,32,116,111,32,80,67,82,69,32,105,102,32,114,101,119,114,105,116,116,101,110,32,116,111,32,117,115,101,32,116,119,111,32,116,111,112,45,108,101,118,101,108,32,98,114,97,110,99,104,101,115,58>>]},{pre,[],[{code,[],[<<40,63,60,61,97,98,99,124,97,98,100,101,41>>]}]},{p,[],[<<83,111,109,101,116,105,109,101,115,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,75,32,40,115,101,101,32,97,98,111,118,101,41,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,111,102,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,116,111,32,103,101,116,32,114,111,117,110,100,32,116,104,101,32,102,105,120,101,100,45,108,101,110,103,116,104,32,114,101,115,116,114,105,99,116,105,111,110,46>>]},{p,[],[<<84,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,105,115,44,32,102,111,114,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,44,32,116,111,32,109,111,118,101,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,98,97,99,107,32,116,101,109,112,111,114,97,114,105,108,121,32,98,121,32,116,104,101,32,102,105,120,101,100,32,108,101,110,103,116,104,32,97,110,100,32,116,104,101,110,32,116,114,121,32,116,111,32,109,97,116,99,104,46,32,73,102,32,116,104,101,114,101,32,97,114,101,32,105,110,115,117,102,102,105,99,105,101,110,116,32,99,104,97,114,97,99,116,101,114,115,32,98,101,102,111,114,101,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,102,97,105,108,115,46>>]},{p,[],[<<73,110,32,97,32,85,84,70,32,109,111,100,101,44,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,97,108,108,111,119,32,116,104,101,32,92,67,32,101,115,99,97,112,101,32,40,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,100,97,116,97,32,117,110,105,116,32,101,118,101,110,32,105,110,32,97,32,85,84,70,32,109,111,100,101,41,32,116,111,32,97,112,112,101,97,114,32,105,110,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,44,32,97,115,32,105,116,32,109,97,107,101,115,32,105,116,32,105,109,112,111,115,115,105,98,108,101,32,116,111,32,99,97,108,99,117,108,97,116,101,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,108,111,111,107,98,101,104,105,110,100,46,32,84,104,101,32,92,88,32,97,110,100,32,92,82,32,101,115,99,97,112,101,115,44,32,119,104,105,99,104,32,99,97,110,32,109,97,116,99,104,32,100,105,102,102,101,114,101,110,116,32,110,117,109,98,101,114,115,32,111,102,32,100,97,116,97,32,117,110,105,116,115,44,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,32,101,105,116,104,101,114,46>>]},{p,[],[<<34,83,117,98,114,111,117,116,105,110,101,34,32,99,97,108,108,115,32,40,115,101,101,32,98,101,108,111,119,41,44,32,115,117,99,104,32,97,115,32,40,63,50,41,32,111,114,32,40,63,38,88,41,44,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,108,111,111,107,98,101,104,105,110,100,115,44,32,97,115,32,108,111,110,103,32,97,115,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,32,102,105,120,101,100,45,108,101,110,103,116,104,32,115,116,114,105,110,103,46,32,82,101,99,117,114,115,105,111,110,44,32,104,111,119,101,118,101,114,44,32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46>>]},{p,[],[<<80,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,115,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,116,111,32,115,112,101,99,105,102,121,32,101,102,102,105,99,105,101,110,116,32,109,97,116,99,104,105,110,103,32,111,102,32,102,105,120,101,100,45,108,101,110,103,116,104,32,115,116,114,105,110,103,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,105,109,112,108,101,32,112,97,116,116,101,114,110,32,119,104,101,110,32,97,112,112,108,105,101,100,32,116,111,32,97,32,108,111,110,103,32,115,116,114,105,110,103,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,58>>]},{pre,[],[{code,[],[<<97,98,99,100,36>>]}]},{p,[],[<<65,115,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,101,100,115,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,44,32,80,67,82,69,32,108,111,111,107,115,32,102,111,114,32,101,97,99,104,32,34,97,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,97,110,100,32,116,104,101,110,32,115,101,101,115,32,105,102,32,119,104,97,116,32,102,111,108,108,111,119,115,32,109,97,116,99,104,101,115,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115>>]},{pre,[],[{code,[],[<<94,46,42,97,98,99,100,36>>]}]},{p,[],[<<116,104,101,32,105,110,105,116,105,97,108,32,46,42,32,109,97,116,99,104,101,115,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,32,97,116,32,102,105,114,115,116,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,116,104,105,115,32,102,97,105,108,115,32,40,97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,102,111,108,108,111,119,105,110,103,32,34,97,34,41,44,32,105,116,32,98,97,99,107,116,114,97,99,107,115,32,116,111,32,109,97,116,99,104,32,97,108,108,32,98,117,116,32,116,104,101,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,44,32,116,104,101,110,32,97,108,108,32,98,117,116,32,116,104,101,32,108,97,115,116,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,44,32,97,110,100,32,115,111,32,111,110,46,32,79,110,99,101,32,97,103,97,105,110,32,116,104,101,32,115,101,97,114,99,104,32,102,111,114,32,34,97,34,32,99,111,118,101,114,115,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,44,32,102,114,111,109,32,114,105,103,104,116,32,116,111,32,108,101,102,116,44,32,115,111,32,119,101,32,97,114,101,32,110,111,32,98,101,116,116,101,114,32,111,102,102,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,119,114,105,116,116,101,110,32,97,115>>]},{pre,[],[{code,[],[<<94,46,42,43,40,63,60,61,97,98,99,100,41>>]}]},{p,[],[<<116,104,101,114,101,32,99,97,110,32,98,101,32,110,111,32,98,97,99,107,116,114,97,99,107,105,110,103,32,102,111,114,32,116,104,101,32,46,42,43,32,105,116,101,109,59,32,105,116,32,99,97,110,32,109,97,116,99,104,32,111,110,108,121,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,46,32,84,104,101,32,115,117,98,115,101,113,117,101,110,116,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,100,111,101,115,32,97,32,115,105,110,103,108,101,32,116,101,115,116,32,111,110,32,116,104,101,32,108,97,115,116,32,102,111,117,114,32,99,104,97,114,97,99,116,101,114,115,46,32,73,102,32,105,116,32,102,97,105,108,115,44,32,116,104,101,32,109,97,116,99,104,32,102,97,105,108,115,32,105,109,109,101,100,105,97,116,101,108,121,46,32,70,111,114,32,108,111,110,103,32,115,116,114,105,110,103,115,44,32,116,104,105,115,32,97,112,112,114,111,97,99,104,32,109,97,107,101,115,32,97,32,115,105,103,110,105,102,105,99,97,110,116,32,100,105,102,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,105,110,103,32,116,105,109,101,46>>]},{p,[],[{em,[],[<<85,115,105,110,103,32,77,117,108,116,105,112,108,101,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<77,97,110,121,32,97,115,115,101,114,116,105,111,110,115,32,40,111,102,32,97,110,121,32,115,111,114,116,41,32,99,97,110,32,111,99,99,117,114,32,105,110,32,115,117,99,99,101,115,115,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,102,111,111,34,32,112,114,101,99,101,100,101,100,32,98,121,32,116,104,114,101,101,32,100,105,103,105,116,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,34,57,57,57,34,58>>]},{pre,[],[{code,[],[<<40,63,60,61,92,100,123,51,125,41,40,63,60,33,57,57,57,41,102,111,111>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,101,97,99,104,32,111,102,32,116,104,101,32,97,115,115,101,114,116,105,111,110,115,32,105,115,32,97,112,112,108,105,101,100,32,105,110,100,101,112,101,110,100,101,110,116,108,121,32,97,116,32,116,104,101,32,115,97,109,101,32,112,111,105,110,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,70,105,114,115,116,32,116,104,101,114,101,32,105,115,32,97,32,99,104,101,99,107,32,116,104,97,116,32,116,104,101,32,112,114,101,118,105,111,117,115,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,97,108,108,32,100,105,103,105,116,115,44,32,97,110,100,32,116,104,101,110,32,116,104,101,114,101,32,105,115,32,97,32,99,104,101,99,107,32,116,104,97,116,32,116,104,101,32,115,97,109,101,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,110,111,116,32,34,57,57,57,34,46,32,84,104,105,115,32,112,97,116,116,101,114,110,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,109,97,116,99,104,32,34,102,111,111,34,32,112,114,101,99,101,100,101,100,32,98,121,32,115,105,120,32,99,104,97,114,97,99,116,101,114,115,44,32,116,104,101,32,102,105,114,115,116,32,111,102,32,119,104,105,99,104,32,97,114,101,32,100,105,103,105,116,115,32,97,110,100,32,116,104,101,32,108,97,115,116,32,116,104,114,101,101,32,111,102,32,119,104,105,99,104,32,97,114,101,32,110,111,116,32,34,57,57,57,34,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,34,49,50,51,97,98,99,102,111,111,34,46,32,65,32,112,97,116,116,101,114,110,32,116,111,32,100,111,32,116,104,97,116,32,105,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{pre,[],[{code,[],[<<40,63,60,61,92,100,123,51,125,46,46,46,41,40,63,60,33,57,57,57,41,102,111,111>>]}]},{p,[],[<<84,104,105,115,32,116,105,109,101,32,116,104,101,32,102,105,114,115,116,32,97,115,115,101,114,116,105,111,110,32,108,111,111,107,115,32,97,116,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,115,105,120,32,99,104,97,114,97,99,116,101,114,115,44,32,99,104,101,99,107,115,32,116,104,97,116,32,116,104,101,32,102,105,114,115,116,32,116,104,114,101,101,32,97,114,101,32,100,105,103,105,116,115,44,32,97,110,100,32,116,104,101,110,32,116,104,101,32,115,101,99,111,110,100,32,97,115,115,101,114,116,105,111,110,32,99,104,101,99,107,115,32,116,104,97,116,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,110,111,116,32,34,57,57,57,34,46>>]},{p,[],[<<65,115,115,101,114,116,105,111,110,115,32,99,97,110,32,98,101,32,110,101,115,116,101,100,32,105,110,32,97,110,121,32,99,111,109,98,105,110,97,116,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,110,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,122,34,32,116,104,97,116,32,105,115,32,112,114,101,99,101,100,101,100,32,98,121,32,34,98,97,114,34,44,32,119,104,105,99,104,32,105,110,32,116,117,114,110,32,105,115,32,110,111,116,32,112,114,101,99,101,100,101,100,32,98,121,32,34,102,111,111,34,58>>]},{pre,[],[{code,[],[<<40,63,60,61,40,63,60,33,102,111,111,41,98,97,114,41,98,97,122>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,102,111,111,34,32,112,114,101,99,101,100,101,100,32,98,121,32,116,104,114,101,101,32,100,105,103,105,116,115,32,97,110,100,32,97,110,121,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,34,57,57,57,34,58>>]},{pre,[],[{code,[],[<<40,63,60,61,92,100,123,51,125,40,63,33,57,57,57,41,46,46,46,41,102,111,111>>]}]},{a,[{id,<<115,101,99,116,49,56>>}],[]},{h2,[],[<<67,111,110,100,105,116,105,111,110,97,108,32,83,117,98,112,97,116,116,101,114,110,115>>]},{p,[],[<<73,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,99,97,117,115,101,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,115,115,32,116,111,32,111,98,101,121,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,111,110,100,105,116,105,111,110,97,108,108,121,32,111,114,32,116,111,32,99,104,111,111,115,101,32,98,101,116,119,101,101,110,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,32,115,117,98,112,97,116,116,101,114,110,115,44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,110,32,97,115,115,101,114,116,105,111,110,44,32,111,114,32,119,104,101,116,104,101,114,32,97,32,115,112,101,99,105,102,105,99,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,97,108,114,101,97,100,121,32,98,101,101,110,32,109,97,116,99,104,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,116,119,111,32,112,111,115,115,105,98,108,101,32,102,111,114,109,115,32,111,102,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,63,40,99,111,110,100,105,116,105,111,110,41,121,101,115,45,112,97,116,116,101,114,110,41,10,40,63,40,99,111,110,100,105,116,105,111,110,41,121,101,115,45,112,97,116,116,101,114,110,124,110,111,45,112,97,116,116,101,114,110,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,115,97,116,105,115,102,105,101,100,44,32,116,104,101,32,121,101,115,45,112,97,116,116,101,114,110,32,105,115,32,117,115,101,100,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,110,111,45,112,97,116,116,101,114,110,32,40,105,102,32,112,114,101,115,101,110,116,41,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,101,120,105,115,116,32,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,44,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,32,111,99,99,117,114,115,46,32,69,97,99,104,32,111,102,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,99,97,110,32,105,116,115,101,108,102,32,99,111,110,116,97,105,110,32,110,101,115,116,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,97,110,121,32,102,111,114,109,44,32,105,110,99,108,117,100,105,110,103,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,115,59,32,116,104,101,32,114,101,115,116,114,105,99,116,105,111,110,32,116,111,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,112,112,108,105,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,108,101,118,101,108,32,111,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,102,114,97,103,109,101,110,116,32,105,115,32,97,110,32,101,120,97,109,112,108,101,32,119,104,101,114,101,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,99,111,109,112,108,101,120,58>>]},{pre,[],[{code,[],[<<40,63,40,49,41,32,40,65,124,66,124,67,41,32,124,32,40,68,32,124,32,40,63,40,50,41,69,124,70,41,32,124,32,69,41,32,41>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,102,111,117,114,32,107,105,110,100,115,32,111,102,32,99,111,110,100,105,116,105,111,110,58,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,115,117,98,112,97,116,116,101,114,110,115,44,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,114,101,99,117,114,115,105,111,110,44,32,97,32,112,115,101,117,100,111,45,99,111,110,100,105,116,105,111,110,32,99,97,108,108,101,100,32,68,69,70,73,78,69,44,32,97,110,100,32,97,115,115,101,114,116,105,111,110,115,46>>]},{p,[],[{em,[],[<<67,104,101,99,107,105,110,103,32,102,111,114,32,97,32,85,115,101,100,32,83,117,98,112,97,116,116,101,114,110,32,66,121,32,78,117,109,98,101,114>>]}]},{p,[],[<<73,102,32,116,104,101,32,116,101,120,116,32,98,101,116,119,101,101,110,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,99,111,110,115,105,115,116,115,32,111,102,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,100,105,103,105,116,115,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,111,102,32,116,104,97,116,32,110,117,109,98,101,114,32,104,97,115,32,112,114,101,118,105,111,117,115,108,121,32,109,97,116,99,104,101,100,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,32,101,120,105,115,116,115,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]},<<32,101,97,114,108,105,101,114,41,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,102,32,116,104,101,109,32,104,97,118,101,32,109,97,116,99,104,101,100,46,32,65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,110,111,116,97,116,105,111,110,32,105,115,32,116,111,32,112,114,101,99,101,100,101,32,116,104,101,32,100,105,103,105,116,115,32,119,105,116,104,32,97,32,112,108,117,115,32,111,114,32,109,105,110,117,115,32,115,105,103,110,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,110,117,109,98,101,114,32,105,115,32,114,101,108,97,116,105,118,101,32,114,97,116,104,101,114,32,116,104,97,110,32,97,98,115,111,108,117,116,101,46,32,84,104,101,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,111,112,101,110,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32,40,63,40,45,49,41,44,32,116,104,101,32,110,101,120,116,32,109,111,115,116,32,114,101,99,101,110,116,32,98,121,32,40,63,40,45,50,41,44,32,97,110,100,32,115,111,32,111,110,46,32,73,110,115,105,100,101,32,108,111,111,112,115,44,32,105,116,32,99,97,110,32,97,108,115,111,32,109,97,107,101,32,115,101,110,115,101,32,116,111,32,114,101,102,101,114,32,116,111,32,115,117,98,115,101,113,117,101,110,116,32,103,114,111,117,112,115,46,32,84,104,101,32,110,101,120,116,32,112,97,114,101,110,116,104,101,115,101,115,32,116,111,32,98,101,32,111,112,101,110,101,100,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,32,97,115,32,40,63,40,43,49,41,44,32,97,110,100,32,115,111,32,111,110,46,32,40,84,104,101,32,118,97,108,117,101,32,122,101,114,111,32,105,110,32,97,110,121,32,111,102,32,116,104,101,115,101,32,102,111,114,109,115,32,105,115,32,110,111,116,32,117,115,101,100,59,32,105,116,32,112,114,111,118,111,107,101,115,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,46,41>>]},{p,[],[<<67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,99,111,110,116,97,105,110,115,32,110,111,110,45,115,105,103,110,105,102,105,99,97,110,116,32,119,104,105,116,101,115,112,97,99,101,32,116,111,32,109,97,107,101,32,105,116,32,109,111,114,101,32,114,101,97,100,97,98,108,101,32,40,97,115,115,117,109,101,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<41,32,97,110,100,32,116,111,32,100,105,118,105,100,101,32,105,116,32,105,110,116,111,32,116,104,114,101,101,32,112,97,114,116,115,32,102,111,114,32,101,97,115,101,32,111,102,32,100,105,115,99,117,115,115,105,111,110,58>>]},{pre,[],[{code,[],[<<40,32,92,40,32,41,63,32,32,32,32,91,94,40,41,93,43,32,32,32,32,40,63,40,49,41,32,92,41,32,41>>]}]},{p,[],[<<84,104,101,32,102,105,114,115,116,32,112,97,114,116,32,109,97,116,99,104,101,115,32,97,110,32,111,112,116,105,111,110,97,108,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,44,32,97,110,100,32,105,102,32,116,104,97,116,32,99,104,97,114,97,99,116,101,114,32,105,115,32,112,114,101,115,101,110,116,44,32,115,101,116,115,32,105,116,32,97,115,32,116,104,101,32,102,105,114,115,116,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,46,32,84,104,101,32,115,101,99,111,110,100,32,112,97,114,116,32,109,97,116,99,104,101,115,32,111,110,101,32,111,114,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,112,97,114,101,110,116,104,101,115,101,115,46,32,84,104,101,32,116,104,105,114,100,32,112,97,114,116,32,105,115,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,116,101,115,116,115,32,119,104,101,116,104,101,114,32,116,104,101,32,102,105,114,115,116,32,115,101,116,32,111,102,32,112,97,114,101,110,116,104,101,115,101,115,32,109,97,116,99,104,101,100,32,111,114,32,110,111,116,46,32,73,102,32,116,104,101,121,32,100,105,100,44,32,116,104,97,116,32,105,115,44,32,105,102,32,115,117,98,106,101,99,116,32,115,116,97,114,116,101,100,32,119,105,116,104,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,44,32,97,110,100,32,115,111,32,116,104,101,32,121,101,115,45,112,97,116,116,101,114,110,32,105,115,32,101,120,101,99,117,116,101,100,32,97,110,100,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,115,32,114,101,113,117,105,114,101,100,46,32,79,116,104,101,114,119,105,115,101,44,32,97,115,32,110,111,45,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,44,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,110,111,116,104,105,110,103,46,32,84,104,97,116,32,105,115,44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,44,32,111,112,116,105,111,110,97,108,108,121,32,101,110,99,108,111,115,101,100,32,105,110,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<73,102,32,116,104,105,115,32,112,97,116,116,101,114,110,32,105,115,32,101,109,98,101,100,100,101,100,32,105,110,32,97,32,108,97,114,103,101,114,32,111,110,101,44,32,97,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,117,115,101,100,58>>]},{pre,[],[{code,[],[<<46,46,46,111,116,104,101,114,32,115,116,117,102,102,46,46,46,32,40,32,92,40,32,41,63,32,32,32,32,91,94,40,41,93,43,32,32,32,32,40,63,40,45,49,41,32,92,41,32,41,32,46,46,46>>]}]},{p,[],[<<84,104,105,115,32,109,97,107,101,115,32,116,104,101,32,102,114,97,103,109,101,110,116,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,108,97,114,103,101,114,32,112,97,116,116,101,114,110,46>>]},{p,[],[{em,[],[<<67,104,101,99,107,105,110,103,32,102,111,114,32,97,32,85,115,101,100,32,83,117,98,112,97,116,116,101,114,110,32,66,121,32,78,97,109,101>>]}]},{p,[],[<<80,101,114,108,32,117,115,101,115,32,116,104,101,32,115,121,110,116,97,120,32,40,63,40,60,110,97,109,101,62,41,46,46,46,41,32,111,114,32,40,63,40,39,110,97,109,101,39,41,46,46,46,41,32,116,111,32,116,101,115,116,32,102,111,114,32,97,32,117,115,101,100,32,115,117,98,112,97,116,116,101,114,110,32,98,121,32,110,97,109,101,46,32,70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,101,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,111,102,32,80,67,82,69,44,32,119,104,105,99,104,32,104,97,100,32,116,104,105,115,32,102,97,99,105,108,105,116,121,32,98,101,102,111,114,101,32,80,101,114,108,44,32,116,104,101,32,115,121,110,116,97,120,32,40,63,40,110,97,109,101,41,46,46,46,41,32,105,115,32,97,108,115,111,32,114,101,99,111,103,110,105,122,101,100,46>>]},{p,[],[<<82,101,119,114,105,116,105,110,103,32,116,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,32,116,111,32,117,115,101,32,97,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,32,103,105,118,101,115,58>>]},{pre,[],[{code,[],[<<40,63,60,79,80,69,78,62,32,92,40,32,41,63,32,32,32,32,91,94,40,41,93,43,32,32,32,32,40,63,40,60,79,80,69,78,62,41,32,92,41,32,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,110,97,109,101,32,117,115,101,100,32,105,110,32,97,32,99,111,110,100,105,116,105,111,110,32,111,102,32,116,104,105,115,32,107,105,110,100,32,105,115,32,97,32,100,117,112,108,105,99,97,116,101,44,32,116,104,101,32,116,101,115,116,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,97,108,108,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,116,104,101,32,115,97,109,101,32,110,97,109,101,44,32,97,110,100,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,110,101,32,111,102,32,116,104,101,109,32,104,97,115,32,109,97,116,99,104,101,100,46>>]},{p,[],[{em,[],[<<67,104,101,99,107,105,110,103,32,102,111,114,32,80,97,116,116,101,114,110,32,82,101,99,117,114,115,105,111,110>>]}]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,104,101,32,115,116,114,105,110,103,32,40,82,41,44,32,97,110,100,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,110,97,109,101,32,82,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,97,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,116,111,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,32,111,114,32,97,110,121,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32,73,102,32,100,105,103,105,116,115,32,111,114,32,97,32,110,97,109,101,32,112,114,101,99,101,100,101,100,32,98,121,32,97,109,112,101,114,115,97,110,100,32,102,111,108,108,111,119,32,116,104,101,32,108,101,116,116,101,114,32,82,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,63,40,82,51,41,46,46,46,41,32,111,114,32,40,63,40,82,38,110,97,109,101,41,46,46,46,41>>]}]},{p,[],[<<116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,114,101,99,117,114,115,105,111,110,32,105,115,32,105,110,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,119,104,111,115,101,32,110,117,109,98,101,114,32,111,114,32,110,97,109,101,32,105,115,32,103,105,118,101,110,46,32,84,104,105,115,32,99,111,110,100,105,116,105,111,110,32,100,111,101,115,32,110,111,116,32,99,104,101,99,107,32,116,104,101,32,101,110,116,105,114,101,32,114,101,99,117,114,115,105,111,110,32,115,116,97,99,107,46,32,73,102,32,116,104,101,32,110,97,109,101,32,117,115,101,100,32,105,110,32,97,32,99,111,110,100,105,116,105,111,110,32,111,102,32,116,104,105,115,32,107,105,110,100,32,105,115,32,97,32,100,117,112,108,105,99,97,116,101,44,32,116,104,101,32,116,101,115,116,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,97,108,108,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,116,104,101,32,115,97,109,101,32,110,97,109,101,44,32,97,110,100,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,110,101,32,111,102,32,116,104,101,109,32,105,115,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,114,101,99,117,114,115,105,111,110,46>>]},{p,[],[<<65,116,32,34,116,111,112,45,108,101,118,101,108,34,44,32,97,108,108,32,116,104,101,115,101,32,114,101,99,117,114,115,105,111,110,32,116,101,115,116,32,99,111,110,100,105,116,105,111,110,115,32,97,114,101,32,102,97,108,115,101,46,32,84,104,101,32,115,121,110,116,97,120,32,102,111,114,32,114,101,99,117,114,115,105,118,101,32,112,97,116,116,101,114,110,115,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46>>]},{p,[],[{em,[],[<<68,101,102,105,110,105,110,103,32,83,117,98,112,97,116,116,101,114,110,115,32,102,111,114,32,85,115,101,32,66,121,32,82,101,102,101,114,101,110,99,101,32,79,110,108,121>>]}]},{a,[{id,<<100,101,102,105,110,105,110,103,95,115,117,98,112,97,116,116,101,114,110,115>>}],[]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,104,101,32,115,116,114,105,110,103,32,40,68,69,70,73,78,69,41,44,32,97,110,100,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,110,97,109,101,32,68,69,70,73,78,69,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,97,108,119,97,121,115,32,102,97,108,115,101,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,114,101,32,99,97,110,32,98,101,32,111,110,108,121,32,111,110,101,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,46,32,73,116,32,105,115,32,97,108,119,97,121,115,32,115,107,105,112,112,101,100,32,105,102,32,99,111,110,116,114,111,108,32,114,101,97,99,104,101,115,32,116,104,105,115,32,112,111,105,110,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,101,32,105,100,101,97,32,111,102,32,68,69,70,73,78,69,32,105,115,32,116,104,97,116,32,105,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,100,101,102,105,110,101,32,34,115,117,98,114,111,117,116,105,110,101,115,34,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,32,102,114,111,109,32,101,108,115,101,119,104,101,114,101,46,32,40,84,104,101,32,117,115,101,32,111,102,32,115,117,98,114,111,117,116,105,110,101,115,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46,41,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,32,112,97,116,116,101,114,110,32,116,111,32,109,97,116,99,104,32,97,110,32,73,80,118,52,32,97,100,100,114,101,115,115,44,32,115,117,99,104,32,97,115,32,34,49,57,50,46,49,54,56,46,50,51,46,50,52,53,34,44,32,99,97,110,32,98,101,32,119,114,105,116,116,101,110,32,108,105,107,101,32,116,104,105,115,32,40,105,103,110,111,114,101,32,119,104,105,116,101,115,112,97,99,101,32,97,110,100,32,108,105,110,101,32,98,114,101,97,107,115,41,58>>]},{pre,[],[{code,[],[<<40,63,40,68,69,70,73,78,69,41,32,40,63,60,98,121,116,101,62,32,50,91,48,45,52,93,92,100,32,124,32,50,53,91,48,45,53,93,32,124,32,49,92,100,92,100,32,124,32,91,49,45,57,93,63,92,100,41,32,41,32,92,98,32,40,63,38,98,121,116,101,41,32,40,92,46,40,63,38,98,121,116,101,41,41,123,51,125,32,92,98>>]}]},{p,[],[<<84,104,101,32,102,105,114,115,116,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,97,32,68,69,70,73,78,69,32,103,114,111,117,112,32,105,110,115,105,100,101,32,119,104,105,99,104,32,105,115,32,97,32,97,110,111,116,104,101,114,32,103,114,111,117,112,32,110,97,109,101,100,32,34,98,121,116,101,34,32,105,115,32,100,101,102,105,110,101,100,46,32,84,104,105,115,32,109,97,116,99,104,101,115,32,97,110,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109,112,111,110,101,110,116,32,111,102,32,97,110,32,73,80,118,52,32,97,100,100,114,101,115,115,32,40,97,32,110,117,109,98,101,114,32,60,32,50,53,54,41,46,32,87,104,101,110,32,109,97,116,99,104,105,110,103,32,116,97,107,101,115,32,112,108,97,99,101,44,32,116,104,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,115,107,105,112,112,101,100,44,32,97,115,32,68,69,70,73,78,69,32,97,99,116,115,32,108,105,107,101,32,97,32,102,97,108,115,101,32,99,111,110,100,105,116,105,111,110,46,32,84,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,117,115,101,115,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,116,104,101,32,110,97,109,101,100,32,103,114,111,117,112,32,116,111,32,109,97,116,99,104,32,116,104,101,32,102,111,117,114,32,100,111,116,45,115,101,112,97,114,97,116,101,100,32,99,111,109,112,111,110,101,110,116,115,32,111,102,32,97,110,32,73,80,118,52,32,97,100,100,114,101,115,115,44,32,105,110,115,105,115,116,105,110,103,32,111,110,32,97,32,119,111,114,100,32,98,111,117,110,100,97,114,121,32,97,116,32,101,97,99,104,32,101,110,100,46>>]},{p,[],[{em,[],[<<65,115,115,101,114,116,105,111,110,32,67,111,110,100,105,116,105,111,110,115>>]}]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,110,111,116,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,97,98,111,118,101,32,102,111,114,109,97,116,115,44,32,105,116,32,109,117,115,116,32,98,101,32,97,110,32,97,115,115,101,114,116,105,111,110,46,32,84,104,105,115,32,99,97,110,32,98,101,32,97,32,112,111,115,105,116,105,118,101,32,111,114,32,110,101,103,97,116,105,118,101,32,108,111,111,107,97,104,101,97,100,32,111,114,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,99,111,110,116,97,105,110,105,110,103,32,110,111,110,45,115,105,103,110,105,102,105,99,97,110,116,32,119,104,105,116,101,115,112,97,99,101,44,32,97,110,100,32,119,105,116,104,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,111,110,32,116,104,101,32,115,101,99,111,110,100,32,108,105,110,101,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<40,63,40,63,61,91,94,97,45,122,93,42,91,97,45,122,93,41,10,92,100,123,50,125,45,91,97,45,122,93,123,51,125,45,92,100,123,50,125,32,32,124,32,32,92,100,123,50,125,45,92,100,123,50,125,45,92,100,123,50,125,32,41>>]}]},{p,[],[<<84,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,108,111,111,107,97,104,101,97,100,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,97,110,32,111,112,116,105,111,110,97,108,32,115,101,113,117,101,110,99,101,32,111,102,32,110,111,110,45,108,101,116,116,101,114,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,108,101,116,116,101,114,46,32,84,104,97,116,32,105,115,44,32,105,116,32,116,101,115,116,115,32,102,111,114,32,116,104,101,32,112,114,101,115,101,110,99,101,32,111,102,32,97,116,32,108,101,97,115,116,32,111,110,101,32,108,101,116,116,101,114,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,73,102,32,97,32,108,101,116,116,101,114,32,105,115,32,102,111,117,110,100,44,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,105,114,115,116,32,97,108,116,101,114,110,97,116,105,118,101,44,32,111,116,104,101,114,119,105,115,101,32,105,116,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,115,101,99,111,110,100,46,32,84,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,115,116,114,105,110,103,115,32,105,110,32,111,110,101,32,111,102,32,116,104,101,32,116,119,111,32,102,111,114,109,115,32,100,100,45,97,97,97,45,100,100,32,111,114,32,100,100,45,100,100,45,100,100,44,32,119,104,101,114,101,32,97,97,97,32,97,114,101,32,108,101,116,116,101,114,115,32,97,110,100,32,100,100,32,97,114,101,32,100,105,103,105,116,115,46>>]},{a,[{id,<<115,101,99,116,49,57>>}],[]},{h2,[],[<<67,111,109,109,101,110,116,115>>]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,116,119,111,32,119,97,121,115,32,116,111,32,105,110,99,108,117,100,101,32,99,111,109,109,101,110,116,115,32,105,110,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,112,114,111,99,101,115,115,101,100,32,98,121,32,80,67,82,69,46,32,73,110,32,98,111,116,104,32,99,97,115,101,115,44,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,99,111,109,109,101,110,116,32,109,117,115,116,32,110,111,116,32,98,101,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,111,114,32,105,110,32,116,104,101,32,109,105,100,100,108,101,32,111,102,32,97,110,121,32,111,116,104,101,114,32,115,101,113,117,101,110,99,101,32,111,102,32,114,101,108,97,116,101,100,32,99,104,97,114,97,99,116,101,114,115,32,115,117,99,104,32,97,115,32,40,63,58,32,111,114,32,97,32,115,117,98,112,97,116,116,101,114,110,32,110,97,109,101,32,111,114,32,110,117,109,98,101,114,46,32,84,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,109,97,107,101,32,117,112,32,97,32,99,111,109,109,101,110,116,32,112,108,97,121,32,110,111,32,112,97,114,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,105,110,103,46>>]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,32,40,63,35,32,109,97,114,107,115,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,99,111,109,109,101,110,116,32,116,104,97,116,32,99,111,110,116,105,110,117,101,115,32,117,112,32,116,111,32,116,104,101,32,110,101,120,116,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,78,101,115,116,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,46,32,73,102,32,111,112,116,105,111,110,32,80,67,82,69,95,69,88,84,69,78,68,69,68,32,105,115,32,115,101,116,44,32,97,110,32,117,110,101,115,99,97,112,101,100,32,35,32,99,104,97,114,97,99,116,101,114,32,97,108,115,111,32,105,110,116,114,111,100,117,99,101,115,32,97,32,99,111,109,109,101,110,116,44,32,119,104,105,99,104,32,105,110,32,116,104,105,115,32,99,97,115,101,32,99,111,110,116,105,110,117,101,115,32,116,111,32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,116,104,101,32,110,101,120,116,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,32,111,114,32,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,87,104,105,99,104,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,110,101,119,108,105,110,101,115,32,105,115,32,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,32,111,112,116,105,111,110,115,32,112,97,115,115,101,100,32,116,111,32,97,32,99,111,109,112,105,108,105,110,103,32,102,117,110,99,116,105,111,110,32,111,114,32,98,121,32,97,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,101,119,108,105,110,101,95,99,111,110,118,101,110,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,101,119,108,105,110,101,32,67,111,110,118,101,110,116,105,111,110,115>>]},<<32,101,97,114,108,105,101,114,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,105,115,32,116,121,112,101,32,111,102,32,99,111,109,109,101,110,116,32,105,115,32,97,32,108,105,116,101,114,97,108,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,59,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,116,32,104,97,112,112,101,110,32,116,111,32,114,101,112,114,101,115,101,110,116,32,97,32,110,101,119,108,105,110,101,32,100,111,32,110,111,116,32,99,111,117,110,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,119,104,101,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,105,115,32,115,101,116,44,32,97,110,100,32,116,104,101,32,100,101,102,97,117,108,116,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,32,105,115,32,105,110,32,102,111,114,99,101,58>>]},{pre,[],[{code,[],[<<97,98,99,32,35,99,111,109,109,101,110,116,32,92,110,32,115,116,105,108,108,32,99,111,109,109,101,110,116>>]}]},{p,[],[<<79,110,32,101,110,99,111,117,110,116,101,114,105,110,103,32,99,104,97,114,97,99,116,101,114,32,35,44,32>>,{code,[],[<<112,99,114,101,95,99,111,109,112,105,108,101,40,41>>]},<<32,115,107,105,112,115,32,97,108,111,110,103,44,32,108,111,111,107,105,110,103,32,102,111,114,32,97,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,101,32,115,101,113,117,101,110,99,101,32,92,110,32,105,115,32,115,116,105,108,108,32,108,105,116,101,114,97,108,32,97,116,32,116,104,105,115,32,115,116,97,103,101,44,32,115,111,32,105,116,32,100,111,101,115,32,110,111,116,32,116,101,114,109,105,110,97,116,101,32,116,104,101,32,99,111,109,109,101,110,116,46,32,79,110,108,121,32,97,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,99,111,100,101,32,118,97,108,117,101,32,48,120,48,97,32,40,116,104,101,32,100,101,102,97,117,108,116,32,110,101,119,108,105,110,101,41,32,100,111,101,115,32,115,111,46>>]},{a,[{id,<<115,101,99,116,50,48>>}],[]},{h2,[],[<<82,101,99,117,114,115,105,118,101,32,80,97,116,116,101,114,110,115>>]},{p,[],[<<67,111,110,115,105,100,101,114,32,116,104,101,32,112,114,111,98,108,101,109,32,111,102,32,109,97,116,99,104,105,110,103,32,97,32,115,116,114,105,110,103,32,105,110,32,112,97,114,101,110,116,104,101,115,101,115,44,32,97,108,108,111,119,105,110,103,32,102,111,114,32,117,110,108,105,109,105,116,101,100,32,110,101,115,116,101,100,32,112,97,114,101,110,116,104,101,115,101,115,46,32,87,105,116,104,111,117,116,32,116,104,101,32,117,115,101,32,111,102,32,114,101,99,117,114,115,105,111,110,44,32,116,104,101,32,98,101,115,116,32,116,104,97,116,32,99,97,110,32,98,101,32,100,111,110,101,32,105,115,32,116,111,32,117,115,101,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,117,112,32,116,111,32,115,111,109,101,32,102,105,120,101,100,32,100,101,112,116,104,32,111,102,32,110,101,115,116,105,110,103,46,32,73,116,32,105,115,32,110,111,116,32,112,111,115,115,105,98,108,101,32,116,111,32,104,97,110,100,108,101,32,97,110,32,97,114,98,105,116,114,97,114,121,32,110,101,115,116,105,110,103,32,100,101,112,116,104,46>>]},{p,[],[<<70,111,114,32,115,111,109,101,32,116,105,109,101,44,32,80,101,114,108,32,104,97,115,32,112,114,111,118,105,100,101,100,32,97,32,102,97,99,105,108,105,116,121,32,116,104,97,116,32,97,108,108,111,119,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,116,111,32,114,101,99,117,114,115,101,32,40,97,109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,41,46,32,73,116,32,100,111,101,115,32,116,104,105,115,32,98,121,32,105,110,116,101,114,112,111,108,97,116,105,110,103,32,80,101,114,108,32,99,111,100,101,32,105,110,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,97,116,32,114,117,110,116,105,109,101,44,32,97,110,100,32,116,104,101,32,99,111,100,101,32,99,97,110,32,114,101,102,101,114,32,116,111,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,105,116,115,101,108,102,46,32,65,32,80,101,114,108,32,112,97,116,116,101,114,110,32,117,115,105,110,103,32,99,111,100,101,32,105,110,116,101,114,112,111,108,97,116,105,111,110,32,116,111,32,115,111,108,118,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,112,114,111,98,108,101,109,32,99,97,110,32,98,101,32,99,114,101,97,116,101,100,32,108,105,107,101,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<36,114,101,32,61,32,113,114,123,92,40,32,40,63,58,32,40,63,62,91,94,40,41,93,43,41,32,124,32,40,63,112,123,36,114,101,125,41,32,41,42,32,92,41,125,120,59>>]}]},{p,[],[<<73,116,101,109,32,40,63,112,123,46,46,46,125,41,32,105,110,116,101,114,112,111,108,97,116,101,115,32,80,101,114,108,32,99,111,100,101,32,97,116,32,114,117,110,116,105,109,101,44,32,97,110,100,32,105,110,32,116,104,105,115,32,99,97,115,101,32,114,101,102,101,114,115,32,114,101,99,117,114,115,105,118,101,108,121,32,116,111,32,116,104,101,32,112,97,116,116,101,114,110,32,105,110,32,119,104,105,99,104,32,105,116,32,97,112,112,101,97,114,115,46>>]},{p,[],[<<79,98,118,105,111,117,115,108,121,44,32,80,67,82,69,32,99,97,110,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,32,105,110,116,101,114,112,111,108,97,116,105,111,110,32,111,102,32,80,101,114,108,32,99,111,100,101,46,32,73,110,115,116,101,97,100,44,32,105,116,32,115,117,112,112,111,114,116,115,32,115,112,101,99,105,97,108,32,115,121,110,116,97,120,32,102,111,114,32,114,101,99,117,114,115,105,111,110,32,111,102,32,116,104,101,32,101,110,116,105,114,101,32,112,97,116,116,101,114,110,44,32,97,110,100,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,115,117,98,112,97,116,116,101,114,110,32,114,101,99,117,114,115,105,111,110,46,32,65,102,116,101,114,32,105,116,115,32,105,110,116,114,111,100,117,99,116,105,111,110,32,105,110,32,80,67,82,69,32,97,110,100,32,80,121,116,104,111,110,44,32,116,104,105,115,32,107,105,110,100,32,111,102,32,114,101,99,117,114,115,105,111,110,32,119,97,115,32,108,97,116,101,114,32,105,110,116,114,111,100,117,99,101,100,32,105,110,116,111,32,80,101,114,108,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,48,46>>]},{p,[],[<<65,32,115,112,101,99,105,97,108,32,105,116,101,109,32,116,104,97,116,32,99,111,110,115,105,115,116,115,32,111,102,32,40,63,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,117,109,98,101,114,32,62,32,48,32,97,110,100,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,115,32,97,32,114,101,99,117,114,115,105,118,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,111,102,32,116,104,101,32,103,105,118,101,110,32,110,117,109,98,101,114,44,32,105,102,32,105,116,32,111,99,99,117,114,115,32,105,110,115,105,100,101,32,116,104,97,116,32,115,117,98,112,97,116,116,101,114,110,46,32,40,73,102,32,110,111,116,44,32,105,116,32,105,115,32,97,32,110,111,110,45,114,101,99,117,114,115,105,118,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,44,32,119,104,105,99,104,32,105,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,46,41,32,84,104,101,32,115,112,101,99,105,97,108,32,105,116,101,109,32,40,63,82,41,32,111,114,32,40,63,48,41,32,105,115,32,97,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,111,102,32,116,104,101,32,101,110,116,105,114,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<84,104,105,115,32,80,67,82,69,32,112,97,116,116,101,114,110,32,115,111,108,118,101,115,32,116,104,101,32,110,101,115,116,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,112,114,111,98,108,101,109,32,40,97,115,115,117,109,101,32,116,104,97,116,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,105,115,32,115,101,116,32,115,111,32,116,104,97,116,32,119,104,105,116,101,115,112,97,99,101,32,105,115,32,105,103,110,111,114,101,100,41,58>>]},{pre,[],[{code,[],[<<92,40,32,40,32,91,94,40,41,93,43,43,32,124,32,40,63,82,41,32,41,42,32,92,41>>]}]},{p,[],[<<70,105,114,115,116,32,105,116,32,109,97,116,99,104,101,115,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,84,104,101,110,32,105,116,32,109,97,116,99,104,101,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,115,117,98,115,116,114,105,110,103,115,44,32,119,104,105,99,104,32,99,97,110,32,101,105,116,104,101,114,32,98,101,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,32,111,114,32,97,32,114,101,99,117,114,115,105,118,101,32,109,97,116,99,104,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,116,115,101,108,102,32,40,116,104,97,116,32,105,115,44,32,97,32,99,111,114,114,101,99,116,108,121,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,115,116,114,105,110,103,41,46,32,70,105,110,97,108,108,121,32,116,104,101,114,101,32,105,115,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,78,111,116,105,99,101,32,116,104,101,32,117,115,101,32,111,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,116,111,32,97,118,111,105,100,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,115,101,113,117,101,110,99,101,115,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<73,102,32,116,104,105,115,32,119,97,115,32,112,97,114,116,32,111,102,32,97,32,108,97,114,103,101,114,32,112,97,116,116,101,114,110,44,32,121,111,117,32,119,111,117,108,100,32,110,111,116,32,119,97,110,116,32,116,111,32,114,101,99,117,114,115,101,32,116,104,101,32,101,110,116,105,114,101,32,112,97,116,116,101,114,110,44,32,115,111,32,105,110,115,116,101,97,100,32,121,111,117,32,99,97,110,32,117,115,101,58>>]},{pre,[],[{code,[],[<<40,32,92,40,32,40,32,91,94,40,41,93,43,43,32,124,32,40,63,49,41,32,41,42,32,92,41,32,41>>]}]},{p,[],[<<84,104,101,32,112,97,116,116,101,114,110,32,105,115,32,104,101,114,101,32,119,105,116,104,105,110,32,112,97,114,101,110,116,104,101,115,101,115,32,115,111,32,116,104,97,116,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,114,101,102,101,114,115,32,116,111,32,116,104,101,109,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<73,110,32,97,32,108,97,114,103,101,114,32,112,97,116,116,101,114,110,44,32,107,101,101,112,105,110,103,32,116,114,97,99,107,32,111,102,32,112,97,114,101,110,116,104,101,115,105,115,32,110,117,109,98,101,114,115,32,99,97,110,32,98,101,32,116,114,105,99,107,121,46,32,84,104,105,115,32,105,115,32,109,97,100,101,32,101,97,115,105,101,114,32,98,121,32,116,104,101,32,117,115,101,32,111,102,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,115,46,32,73,110,115,116,101,97,100,32,111,102,32,40,63,49,41,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,97,98,111,118,101,44,32,121,111,117,32,99,97,110,32,119,114,105,116,101,32,40,63,45,50,41,32,116,111,32,114,101,102,101,114,32,116,111,32,116,104,101,32,115,101,99,111,110,100,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,111,112,101,110,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,112,114,101,99,101,100,105,110,103,32,116,104,101,32,114,101,99,117,114,115,105,111,110,46,32,84,104,97,116,32,105,115,44,32,97,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,32,99,111,117,110,116,115,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,108,101,102,116,119,97,114,100,115,32,102,114,111,109,32,116,104,101,32,112,111,105,110,116,32,97,116,32,119,104,105,99,104,32,105,116,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,46>>]},{p,[],[<<73,116,32,105,115,32,97,108,115,111,32,112,111,115,115,105,98,108,101,32,116,111,32,114,101,102,101,114,32,116,111,32,108,97,116,101,114,32,111,112,101,110,101,100,32,112,97,114,101,110,116,104,101,115,101,115,44,32,98,121,32,119,114,105,116,105,110,103,32,114,101,102,101,114,101,110,99,101,115,32,115,117,99,104,32,97,115,32,40,63,43,50,41,46,32,72,111,119,101,118,101,114,44,32,116,104,101,115,101,32,99,97,110,110,111,116,32,98,101,32,114,101,99,117,114,115,105,118,101,44,32,97,115,32,116,104,101,32,114,101,102,101,114,101,110,99,101,32,105,115,32,110,111,116,32,105,110,115,105,100,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,114,101,102,101,114,101,110,99,101,100,46,32,84,104,101,121,32,97,114,101,32,97,108,119,97,121,115,32,110,111,110,45,114,101,99,117,114,115,105,118,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,115,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,46>>]},{p,[],[<<65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,97,112,112,114,111,97,99,104,32,105,115,32,116,111,32,117,115,101,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,115,116,101,97,100,46,32,84,104,101,32,80,101,114,108,32,115,121,110,116,97,120,32,102,111,114,32,116,104,105,115,32,105,115,32,40,63,38,110,97,109,101,41,46,32,84,104,101,32,101,97,114,108,105,101,114,32,80,67,82,69,32,115,121,110,116,97,120,32,40,63,80,62,110,97,109,101,41,32,105,115,32,97,108,115,111,32,115,117,112,112,111,114,116,101,100,46,32,87,101,32,99,97,110,32,114,101,119,114,105,116,101,32,116,104,101,32,97,98,111,118,101,32,101,120,97,109,112,108,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{pre,[],[{code,[],[<<40,63,60,112,110,62,32,92,40,32,40,32,91,94,40,41,93,43,43,32,124,32,40,63,38,112,110,41,32,41,42,32,92,41,32,41>>]}]},{p,[],[<<73,102,32,116,104,101,114,101,32,105,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,97,109,101,44,32,116,104,101,32,101,97,114,108,105,101,115,116,32,111,110,101,32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,105,115,32,112,97,114,116,105,99,117,108,97,114,32,101,120,97,109,112,108,101,32,112,97,116,116,101,114,110,32,116,104,97,116,32,119,101,32,104,97,118,101,32,115,116,117,100,105,101,100,32,99,111,110,116,97,105,110,115,32,110,101,115,116,101,100,32,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,115,44,32,97,110,100,32,115,111,32,116,104,101,32,117,115,101,32,111,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,102,111,114,32,109,97,116,99,104,105,110,103,32,115,116,114,105,110,103,115,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,32,105,115,32,105,109,112,111,114,116,97,110,116,32,119,104,101,110,32,97,112,112,108,121,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,116,111,32,115,116,114,105,110,103,115,32,116,104,97,116,32,100,111,32,110,111,116,32,109,97,116,99,104,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32,116,104,105,115,32,112,97,116,116,101,114,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111>>]},{pre,[],[{code,[],[<<40,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,40,41>>]}]},{p,[],[<<105,116,32,103,105,118,101,115,32,34,110,111,32,109,97,116,99,104,34,32,113,117,105,99,107,108,121,46,32,72,111,119,101,118,101,114,44,32,105,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,110,111,116,32,117,115,101,100,44,32,116,104,101,32,109,97,116,99,104,32,114,117,110,115,32,102,111,114,32,97,32,108,111,110,103,32,116,105,109,101,44,32,97,115,32,116,104,101,114,101,32,97,114,101,32,115,111,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,32,116,104,101,32,43,32,97,110,100,32,42,32,114,101,112,101,97,116,115,32,99,97,110,32,99,97,114,118,101,32,117,112,32,116,104,101,32,115,117,98,106,101,99,116,44,32,97,110,100,32,97,108,108,32,109,117,115,116,32,98,101,32,116,101,115,116,101,100,32,98,101,102,111,114,101,32,102,97,105,108,117,114,101,32,99,97,110,32,98,101,32,114,101,112,111,114,116,101,100,46>>]},{p,[],[<<65,116,32,116,104,101,32,101,110,100,32,111,102,32,97,32,109,97,116,99,104,44,32,116,104,101,32,118,97,108,117,101,115,32,111,102,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,116,104,111,115,101,32,102,114,111,109,32,116,104,101,32,111,117,116,101,114,109,111,115,116,32,108,101,118,101,108,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,97,98,111,118,101,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116>>]},{pre,[],[{code,[],[<<40,97,98,40,99,100,41,101,102,41>>]}]},{p,[],[<<116,104,101,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,105,110,110,101,114,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,40,110,117,109,98,101,114,101,100,32,50,41,32,105,115,32,34,101,102,34,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,108,97,115,116,32,118,97,108,117,101,32,116,97,107,101,110,32,111,110,32,97,116,32,116,104,101,32,116,111,112,45,108,101,118,101,108,46,32,73,102,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,109,97,116,99,104,101,100,32,97,116,32,116,104,101,32,116,111,112,32,108,101,118,101,108,44,32,105,116,115,32,102,105,110,97,108,32,99,97,112,116,117,114,101,100,32,118,97,108,117,101,32,105,115,32,117,110,115,101,116,44,32,101,118,101,110,32,105,102,32,105,116,32,119,97,115,32,40,116,101,109,112,111,114,97,114,105,108,121,41,32,115,101,116,32,97,116,32,97,32,100,101,101,112,101,114,32,108,101,118,101,108,32,100,117,114,105,110,103,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<68,111,32,110,111,116,32,99,111,110,102,117,115,101,32,105,116,101,109,32,40,63,82,41,32,119,105,116,104,32,99,111,110,100,105,116,105,111,110,32,40,82,41,44,32,119,104,105,99,104,32,116,101,115,116,115,32,102,111,114,32,114,101,99,117,114,115,105,111,110,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,116,101,120,116,32,105,110,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115,44,32,97,108,108,111,119,105,110,103,32,102,111,114,32,97,114,98,105,116,114,97,114,121,32,110,101,115,116,105,110,103,46,32,79,110,108,121,32,100,105,103,105,116,115,32,97,114,101,32,97,108,108,111,119,101,100,32,105,110,32,110,101,115,116,101,100,32,98,114,97,99,107,101,116,115,32,40,116,104,97,116,32,105,115,44,32,119,104,101,110,32,114,101,99,117,114,115,105,110,103,41,44,32,119,104,105,108,101,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,97,116,32,116,104,101,32,111,117,116,101,114,32,108,101,118,101,108,46>>]},{pre,[],[{code,[],[<<60,32,40,63,58,32,40,63,40,82,41,32,92,100,43,43,32,32,124,32,91,94,60,62,93,42,43,41,32,124,32,40,63,82,41,41,32,42,32,62>>]}]},{p,[],[<<72,101,114,101,32,40,63,40,82,41,32,105,115,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,44,32,119,105,116,104,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,97,108,116,101,114,110,97,116,105,118,101,115,32,102,111,114,32,116,104,101,32,114,101,99,117,114,115,105,118,101,32,97,110,100,32,110,111,110,45,114,101,99,117,114,115,105,118,101,32,99,97,115,101,115,46,32,73,116,101,109,32,40,63,82,41,32,105,115,32,116,104,101,32,97,99,116,117,97,108,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,46>>]},{p,[],[{em,[],[<<68,105,102,102,101,114,101,110,99,101,115,32,105,110,32,82,101,99,117,114,115,105,111,110,32,80,114,111,99,101,115,115,105,110,103,32,98,101,116,119,101,101,110,32,80,67,82,69,32,97,110,100,32,80,101,114,108>>]}]},{p,[],[<<82,101,99,117,114,115,105,111,110,32,112,114,111,99,101,115,115,105,110,103,32,105,110,32,80,67,82,69,32,100,105,102,102,101,114,115,32,102,114,111,109,32,80,101,114,108,32,105,110,32,116,119,111,32,105,109,112,111,114,116,97,110,116,32,119,97,121,115,46,32,73,110,32,80,67,82,69,32,40,108,105,107,101,32,80,121,116,104,111,110,44,32,98,117,116,32,117,110,108,105,107,101,32,80,101,114,108,41,44,32,97,32,114,101,99,117,114,115,105,118,101,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,32,105,115,32,97,108,119,97,121,115,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,84,104,97,116,32,105,115,44,32,111,110,99,101,32,105,116,32,104,97,115,32,109,97,116,99,104,101,100,32,115,111,109,101,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,105,116,32,105,115,32,110,101,118,101,114,32,114,101,45,101,110,116,101,114,101,100,44,32,101,118,101,110,32,105,102,32,105,116,32,99,111,110,116,97,105,110,115,32,117,110,116,114,105,101,100,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,110,100,32,116,104,101,114,101,32,105,115,32,97,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,46,32,84,104,105,115,32,99,97,110,32,98,101,32,105,108,108,117,115,116,114,97,116,101,100,32,98,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,109,101,97,110,115,32,116,111,32,109,97,116,99,104,32,97,32,112,97,108,105,110,100,114,111,109,105,99,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,97,110,32,111,100,100,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,34,97,34,44,32,34,97,98,97,34,44,32,34,97,98,99,98,97,34,44,32,34,97,98,99,100,99,98,97,34,41,58>>]},{pre,[],[{code,[],[<<94,40,46,124,40,46,41,40,63,49,41,92,50,41,36>>]}]},{p,[],[<<84,104,101,32,105,100,101,97,32,105,115,32,116,104,97,116,32,105,116,32,101,105,116,104,101,114,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,116,119,111,32,105,100,101,110,116,105,99,97,108,32,99,104,97,114,97,99,116,101,114,115,32,115,117,114,114,111,117,110,100,105,110,103,32,97,32,115,117,98,112,97,108,105,110,100,114,111,109,101,46,32,73,110,32,80,101,114,108,44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,119,111,114,107,115,59,32,105,110,32,80,67,82,69,32,105,116,32,100,111,101,115,32,110,111,116,32,119,111,114,107,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,34,97,98,99,98,97,34,46>>]},{p,[],[<<65,116,32,116,104,101,32,116,111,112,32,108,101,118,101,108,44,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,105,115,32,109,97,116,99,104,101,100,44,32,98,117,116,32,97,115,32,105,116,32,105,115,32,110,111,116,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,116,104,101,32,102,105,114,115,116,32,97,108,116,101,114,110,97,116,105,118,101,32,102,97,105,108,115,44,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,116,97,107,101,110,44,32,97,110,100,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,107,105,99,107,115,32,105,110,46,32,84,104,101,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,116,111,32,115,117,98,112,97,116,116,101,114,110,32,49,32,115,117,99,99,101,115,115,102,117,108,108,121,32,109,97,116,99,104,101,115,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40,34,98,34,41,46,32,40,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,97,110,100,32,101,110,100,32,111,102,32,108,105,110,101,32,116,101,115,116,115,32,97,114,101,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,99,117,114,115,105,111,110,46,41>>]},{p,[],[<<66,97,99,107,32,97,116,32,116,104,101,32,116,111,112,32,108,101,118,101,108,44,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40,34,99,34,41,32,105,115,32,99,111,109,112,97,114,101,100,32,119,105,116,104,32,119,104,97,116,32,115,117,98,112,97,116,116,101,114,110,32,50,32,109,97,116,99,104,101,100,44,32,119,104,105,99,104,32,119,97,115,32,34,97,34,46,32,84,104,105,115,32,102,97,105,108,115,46,32,65,115,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,44,32,116,104,101,114,101,32,97,114,101,32,110,111,119,32,110,111,32,98,97,99,107,116,114,97,99,107,105,110,103,32,112,111,105,110,116,115,44,32,97,110,100,32,115,111,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,102,97,105,108,115,46,32,40,80,101,114,108,32,99,97,110,32,110,111,119,32,114,101,45,101,110,116,101,114,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,97,110,100,32,116,114,121,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,46,41,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,119,114,105,116,116,101,110,32,119,105,116,104,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,105,110,32,116,104,101,32,111,116,104,101,114,32,111,114,100,101,114,44,32,116,104,105,110,103,115,32,97,114,101,32,100,105,102,102,101,114,101,110,116,58>>]},{pre,[],[{code,[],[<<94,40,40,46,41,40,63,49,41,92,50,124,46,41,36>>]}]},{p,[],[<<84,104,105,115,32,116,105,109,101,44,32,116,104,101,32,114,101,99,117,114,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,116,114,105,101,100,32,102,105,114,115,116,44,32,97,110,100,32,99,111,110,116,105,110,117,101,115,32,116,111,32,114,101,99,117,114,115,101,32,117,110,116,105,108,32,105,116,32,114,117,110,115,32,111,117,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,44,32,97,116,32,119,104,105,99,104,32,112,111,105,110,116,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,102,97,105,108,115,46,32,66,117,116,32,116,104,105,115,32,116,105,109,101,32,119,101,32,104,97,118,101,32,97,110,111,116,104,101,114,32,97,108,116,101,114,110,97,116,105,118,101,32,116,111,32,116,114,121,32,97,116,32,116,104,101,32,104,105,103,104,101,114,32,108,101,118,101,108,46,32,84,104,97,116,32,105,115,32,116,104,101,32,115,105,103,110,105,102,105,99,97,110,116,32,100,105,102,102,101,114,101,110,99,101,58,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,97,115,101,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,97,116,32,97,32,100,101,101,112,101,114,32,114,101,99,117,114,115,105,111,110,32,108,101,118,101,108,44,32,119,104,105,99,104,32,80,67,82,69,32,99,97,110,110,111,116,32,117,115,101,46>>]},{p,[],[<<84,111,32,99,104,97,110,103,101,32,116,104,101,32,112,97,116,116,101,114,110,32,115,111,32,116,104,97,116,32,105,116,32,109,97,116,99,104,101,115,32,97,108,108,32,112,97,108,105,110,100,114,111,109,105,99,32,115,116,114,105,110,103,115,44,32,110,111,116,32,111,110,108,121,32,116,104,111,115,101,32,119,105,116,104,32,97,110,32,111,100,100,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,44,32,105,116,32,105,115,32,116,101,109,112,116,105,110,103,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,112,97,116,116,101,114,110,32,116,111,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<94,40,40,46,41,40,63,49,41,92,50,124,46,63,41,36>>]}]},{p,[],[<<65,103,97,105,110,44,32,116,104,105,115,32,119,111,114,107,115,32,105,110,32,80,101,114,108,44,32,98,117,116,32,110,111,116,32,105,110,32,80,67,82,69,44,32,97,110,100,32,102,111,114,32,116,104,101,32,115,97,109,101,32,114,101,97,115,111,110,46,32,87,104,101,110,32,97,32,100,101,101,112,101,114,32,114,101,99,117,114,115,105,111,110,32,104,97,115,32,109,97,116,99,104,101,100,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,44,32,105,116,32,99,97,110,110,111,116,32,98,101,32,101,110,116,101,114,101,100,32,97,103,97,105,110,32,116,111,32,109,97,116,99,104,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,46,32,84,104,101,32,115,111,108,117,116,105,111,110,32,105,115,32,116,111,32,115,101,112,97,114,97,116,101,32,116,104,101,32,116,119,111,32,99,97,115,101,115,44,32,97,110,100,32,119,114,105,116,101,32,111,117,116,32,116,104,101,32,111,100,100,32,97,110,100,32,101,118,101,110,32,99,97,115,101,115,32,97,115,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,116,32,116,104,101,32,104,105,103,104,101,114,32,108,101,118,101,108,58>>]},{pre,[],[{code,[],[<<94,40,63,58,40,40,46,41,40,63,49,41,92,50,124,41,124,40,40,46,41,40,63,51,41,92,52,124,46,41,41>>]}]},{p,[],[<<73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,116,121,112,105,99,97,108,32,112,97,108,105,110,100,114,111,109,105,99,32,112,104,114,97,115,101,115,44,32,116,104,101,32,112,97,116,116,101,114,110,32,109,117,115,116,32,105,103,110,111,114,101,32,97,108,108,32,110,111,110,45,119,111,114,100,32,99,104,97,114,97,99,116,101,114,115,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,100,111,110,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{pre,[],[{code,[],[<<94,92,87,42,43,40,63,58,40,40,46,41,92,87,42,43,40,63,49,41,92,87,42,43,92,50,124,41,124,40,40,46,41,92,87,42,43,40,63,51,41,92,87,42,43,92,52,124,92,87,42,43,46,92,87,42,43,41,41,92,87,42,43,36>>]}]},{p,[],[<<73,102,32,114,117,110,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,112,104,114,97,115,101,115,32,115,117,99,104,32,97,115,32,34,65,32,109,97,110,44,32,97,32,112,108,97,110,44,32,97,32,99,97,110,97,108,58,32,80,97,110,97,109,97,33,34,32,97,110,100,32,105,116,32,119,111,114,107,115,32,119,101,108,108,32,105,110,32,98,111,116,104,32,80,67,82,69,32,97,110,100,32,80,101,114,108,46,32,78,111,116,105,99,101,32,116,104,101,32,117,115,101,32,111,102,32,116,104,101,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,42,43,32,116,111,32,97,118,111,105,100,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,115,101,113,117,101,110,99,101,115,32,111,102,32,110,111,110,45,119,111,114,100,32,99,104,97,114,97,99,116,101,114,115,46,32,87,105,116,104,111,117,116,32,116,104,105,115,44,32,80,67,82,69,32,116,97,107,101,115,32,109,117,99,104,32,108,111,110,103,101,114,32,40,49,48,32,116,105,109,101,115,32,111,114,32,109,111,114,101,41,32,116,111,32,109,97,116,99,104,32,116,121,112,105,99,97,108,32,112,104,114,97,115,101,115,44,32,97,110,100,32,80,101,114,108,32,116,97,107,101,115,32,115,111,32,108,111,110,103,32,116,104,97,116,32,121,111,117,32,116,104,105,110,107,32,105,116,32,104,97,115,32,103,111,110,101,32,105,110,116,111,32,97,32,108,111,111,112,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,112,97,108,105,110,100,114,111,109,101,45,109,97,116,99,104,105,110,103,32,112,97,116,116,101,114,110,115,32,97,98,111,118,101,32,119,111,114,107,32,111,110,108,121,32,105,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,100,111,101,115,32,110,111,116,32,115,116,97,114,116,32,119,105,116,104,32,97,32,112,97,108,105,110,100,114,111,109,101,32,116,104,97,116,32,105,115,32,115,104,111,114,116,101,114,32,116,104,97,110,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,108,116,104,111,117,103,104,32,34,97,98,99,98,97,34,32,105,115,32,99,111,114,114,101,99,116,108,121,32,109,97,116,99,104,101,100,44,32,105,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,97,98,97,98,97,34,44,32,80,67,82,69,32,102,105,110,100,115,32,112,97,108,105,110,100,114,111,109,101,32,34,97,98,97,34,32,97,116,32,116,104,101,32,115,116,97,114,116,44,32,97,110,100,32,116,104,101,110,32,102,97,105,108,115,32,97,116,32,116,111,112,32,108,101,118,101,108,44,32,97,115,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,100,111,101,115,32,110,111,116,32,102,111,108,108,111,119,46,32,79,110,99,101,32,97,103,97,105,110,44,32,105,116,32,99,97,110,110,111,116,32,106,117,109,112,32,98,97,99,107,32,105,110,116,111,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,116,111,32,116,114,121,32,111,116,104,101,114,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,115,111,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,102,97,105,108,115,46>>]}]},{p,[],[<<84,104,101,32,115,101,99,111,110,100,32,119,97,121,32,105,110,32,119,104,105,99,104,32,80,67,82,69,32,97,110,100,32,80,101,114,108,32,100,105,102,102,101,114,32,105,110,32,116,104,101,105,114,32,114,101,99,117,114,115,105,111,110,32,112,114,111,99,101,115,115,105,110,103,32,105,115,32,105,110,32,116,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,99,97,112,116,117,114,101,100,32,118,97,108,117,101,115,46,32,73,110,32,80,101,114,108,44,32,119,104,101,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,99,97,108,108,101,100,32,114,101,99,117,114,115,105,118,101,108,121,32,111,114,32,97,115,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,115,101,101,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41,44,32,105,116,32,104,97,115,32,110,111,32,97,99,99,101,115,115,32,116,111,32,97,110,121,32,118,97,108,117,101,115,32,116,104,97,116,32,119,101,114,101,32,99,97,112,116,117,114,101,100,32,111,117,116,115,105,100,101,32,116,104,101,32,114,101,99,117,114,115,105,111,110,46,32,73,110,32,80,67,82,69,32,116,104,101,115,101,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<94,40,46,41,40,92,49,124,97,40,63,50,41,41>>]}]},{p,[],[<<73,110,32,80,67,82,69,44,32,105,116,32,109,97,116,99,104,101,115,32,34,98,97,98,34,46,32,84,104,101,32,102,105,114,115,116,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,109,97,116,99,104,32,34,98,34,44,32,116,104,101,110,32,105,110,32,116,104,101,32,115,101,99,111,110,100,32,103,114,111,117,112,44,32,119,104,101,110,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,92,49,32,102,97,105,108,115,32,116,111,32,109,97,116,99,104,32,34,98,34,44,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,32,109,97,116,99,104,101,115,32,34,97,34,44,32,97,110,100,32,116,104,101,110,32,114,101,99,117,114,115,101,115,46,32,73,110,32,116,104,101,32,114,101,99,117,114,115,105,111,110,44,32,92,49,32,100,111,101,115,32,110,111,119,32,109,97,116,99,104,32,34,98,34,32,97,110,100,32,115,111,32,116,104,101,32,119,104,111,108,101,32,109,97,116,99,104,32,115,117,99,99,101,101,100,115,46,32,73,110,32,80,101,114,108,44,32,116,104,101,32,112,97,116,116,101,114,110,32,102,97,105,108,115,32,116,111,32,109,97,116,99,104,32,98,101,99,97,117,115,101,32,105,110,115,105,100,101,32,116,104,101,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,92,49,32,99,97,110,110,111,116,32,97,99,99,101,115,115,32,116,104,101,32,101,120,116,101,114,110,97,108,108,121,32,115,101,116,32,118,97,108,117,101,46>>]},{a,[{id,<<115,101,99,116,50,49>>}],[]},{h2,[],[<<83,117,98,112,97,116,116,101,114,110,115,32,97,115,32,83,117,98,114,111,117,116,105,110,101,115>>]},{p,[],[<<73,102,32,116,104,101,32,115,121,110,116,97,120,32,102,111,114,32,97,32,114,101,99,117,114,115,105,118,101,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,32,40,101,105,116,104,101,114,32,98,121,32,110,117,109,98,101,114,32,111,114,32,98,121,32,110,97,109,101,41,32,105,115,32,117,115,101,100,32,111,117,116,115,105,100,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,111,32,119,104,105,99,104,32,105,116,32,114,101,102,101,114,115,44,32,105,116,32,111,112,101,114,97,116,101,115,32,108,105,107,101,32,97,32,115,117,98,114,111,117,116,105,110,101,32,105,110,32,97,32,112,114,111,103,114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,46,32,84,104,101,32,99,97,108,108,101,100,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,98,101,32,100,101,102,105,110,101,100,32,98,101,102,111,114,101,32,111,114,32,97,102,116,101,114,32,116,104,101,32,114,101,102,101,114,101,110,99,101,46,32,65,32,110,117,109,98,101,114,101,100,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,97,98,115,111,108,117,116,101,32,111,114,32,114,101,108,97,116,105,118,101,44,32,97,115,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<40,46,46,46,40,97,98,115,111,108,117,116,101,41,46,46,46,41,46,46,46,40,63,50,41,46,46,46,10,40,46,46,46,40,114,101,108,97,116,105,118,101,41,46,46,46,41,46,46,46,40,63,45,49,41,46,46,46,10,40,46,46,46,40,63,43,49,41,46,46,46,40,114,101,108,97,116,105,118,101,41,46,46,46>>]}]},{p,[],[<<65,110,32,101,97,114,108,105,101,114,32,101,120,97,109,112,108,101,32,112,111,105,110,116,101,100,32,111,117,116,32,116,104,97,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,115,101,110,115,101,32,97,110,100,32,115,101,110,115,105,98,105,108,105,116,121,34,32,97,110,100,32,34,114,101,115,112,111,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,44,32,98,117,116,32,110,111,116,32,34,115,101,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,58>>]},{pre,[],[{code,[],[<<40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,92,49,105,98,105,108,105,116,121>>]}]},{p,[],[<<73,102,32,105,110,115,116,101,97,100,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,105,115,32,117,115,101,100,44,32,105,116,32,109,97,116,99,104,101,115,32,34,115,101,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,32,97,110,100,32,116,104,101,32,111,116,104,101,114,32,116,119,111,32,115,116,114,105,110,103,115,58>>]},{pre,[],[{code,[],[<<40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,40,63,49,41,105,98,105,108,105,116,121>>]}]},{p,[],[<<65,110,111,116,104,101,114,32,101,120,97,109,112,108,101,32,105,115,32,112,114,111,118,105,100,101,100,32,105,110,32,116,104,101,32,100,105,115,99,117,115,115,105,111,110,32,111,102,32,68,69,70,73,78,69,32,101,97,114,108,105,101,114,46>>]},{p,[],[<<65,108,108,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,115,44,32,114,101,99,117,114,115,105,118,101,32,111,114,32,110,111,116,44,32,97,114,101,32,97,108,119,97,121,115,32,116,114,101,97,116,101,100,32,97,115,32,97,116,111,109,105,99,32,103,114,111,117,112,115,46,32,84,104,97,116,32,105,115,44,32,111,110,99,101,32,97,32,115,117,98,114,111,117,116,105,110,101,32,104,97,115,32,109,97,116,99,104,101,100,32,115,111,109,101,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,105,116,32,105,115,32,110,101,118,101,114,32,114,101,45,101,110,116,101,114,101,100,44,32,101,118,101,110,32,105,102,32,105,116,32,99,111,110,116,97,105,110,115,32,117,110,116,114,105,101,100,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,110,100,32,116,104,101,114,101,32,105,115,32,97,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,46,32,65,110,121,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,115,101,116,32,100,117,114,105,110,103,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,114,101,118,101,114,116,32,116,111,32,116,104,101,105,114,32,112,114,101,118,105,111,117,115,32,118,97,108,117,101,115,32,97,102,116,101,114,119,97,114,100,115,46>>]},{p,[],[<<80,114,111,99,101,115,115,105,110,103,32,111,112,116,105,111,110,115,32,115,117,99,104,32,97,115,32,99,97,115,101,45,105,110,100,101,112,101,110,100,101,110,99,101,32,97,114,101,32,102,105,120,101,100,32,119,104,101,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,100,101,102,105,110,101,100,44,32,115,111,32,105,102,32,105,116,32,105,115,32,117,115,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,44,32,115,117,99,104,32,111,112,116,105,111,110,115,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,102,111,114,32,100,105,102,102,101,114,101,110,116,32,99,97,108,108,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,97,98,99,97,98,99,34,32,98,117,116,32,110,111,116,32,34,97,98,99,65,66,67,34,44,32,97,115,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32,112,114,111,99,101,115,115,105,110,103,32,111,112,116,105,111,110,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,99,97,108,108,101,100,32,115,117,98,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,97,98,99,41,40,63,105,58,40,63,45,49,41,41>>]}]},{a,[{id,<<115,101,99,116,50,50>>}],[]},{h2,[],[<<79,110,105,103,117,114,117,109,97,32,83,117,98,114,111,117,116,105,110,101,32,83,121,110,116,97,120>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,79,110,105,103,117,114,117,109,97,44,32,116,104,101,32,110,111,110,45,80,101,114,108,32,115,121,110,116,97,120,32,92,103,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,32,111,114,32,97,32,110,117,109,98,101,114,32,101,110,99,108,111,115,101,100,32,101,105,116,104,101,114,32,105,110,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115,32,111,114,32,115,105,110,103,108,101,32,113,117,111,116,101,115,44,32,105,115,32,97,108,116,101,114,110,97,116,105,118,101,32,115,121,110,116,97,120,32,102,111,114,32,114,101,102,101,114,101,110,99,105,110,103,32,97,32,115,117,98,112,97,116,116,101,114,110,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,44,32,112,111,115,115,105,98,108,121,32,114,101,99,117,114,115,105,118,101,108,121,46,32,72,101,114,101,32,102,111,108,108,111,119,115,32,116,119,111,32,111,102,32,116,104,101,32,101,120,97,109,112,108,101,115,32,117,115,101,100,32,97,98,111,118,101,44,32,114,101,119,114,105,116,116,101,110,32,117,115,105,110,103,32,116,104,105,115,32,115,121,110,116,97,120,58>>]},{pre,[],[{code,[],[<<40,63,60,112,110,62,32,92,40,32,40,32,40,63,62,91,94,40,41,93,43,41,32,124,32,92,103,60,112,110,62,32,41,42,32,92,41,32,41,10,40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,92,103,39,49,39,105,98,105,108,105,116,121>>]}]},{p,[],[<<80,67,82,69,32,115,117,112,112,111,114,116,115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,116,111,32,79,110,105,103,117,114,117,109,97,58,32,105,102,32,97,32,110,117,109,98,101,114,32,105,115,32,112,114,101,99,101,100,101,100,32,98,121,32,97,32,112,108,117,115,32,111,114,32,109,105,110,117,115,32,115,105,103,110,44,32,105,116,32,105,115,32,116,97,107,101,110,32,97,115,32,97,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,98,99,41,40,63,105,58,92,103,60,45,49,62,41>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,92,103,123,46,46,46,125,32,40,80,101,114,108,32,115,121,110,116,97,120,41,32,97,110,100,32,92,103,60,46,46,46,62,32,40,79,110,105,103,117,114,117,109,97,32,115,121,110,116,97,120,41,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,115,121,110,111,110,121,109,111,117,115,46,32,84,104,101,32,102,111,114,109,101,114,32,105,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,59,32,116,104,101,32,108,97,116,116,101,114,32,105,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,46>>]},{a,[{id,<<115,101,99,116,50,51>>}],[]},{h2,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,67,111,110,116,114,111,108>>]},{p,[],[<<80,101,114,108,32,53,46,49,48,32,105,110,116,114,111,100,117,99,101,100,32,115,111,109,101,32,34,83,112,101,99,105,97,108,32,66,97,99,107,116,114,97,99,107,105,110,103,32,67,111,110,116,114,111,108,32,86,101,114,98,115,34,44,32,119,104,105,99,104,32,97,114,101,32,115,116,105,108,108,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,80,101,114,108,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,97,115,32,34,101,120,112,101,114,105,109,101,110,116,97,108,32,97,110,100,32,115,117,98,106,101,99,116,32,116,111,32,99,104,97,110,103,101,32,111,114,32,114,101,109,111,118,97,108,32,105,110,32,97,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,32,111,102,32,80,101,114,108,34,46,32,73,116,32,103,111,101,115,32,111,110,32,116,111,32,115,97,121,58,32,34,84,104,101,105,114,32,117,115,97,103,101,32,105,110,32,112,114,111,100,117,99,116,105,111,110,32,99,111,100,101,32,115,104,111,117,108,100,32,98,101,32,110,111,116,101,100,32,116,111,32,97,118,111,105,100,32,112,114,111,98,108,101,109,115,32,100,117,114,105,110,103,32,117,112,103,114,97,100,101,115,46,34,32,84,104,101,32,115,97,109,101,32,114,101,109,97,114,107,115,32,97,112,112,108,121,32,116,111,32,116,104,101,32,80,67,82,69,32,102,101,97,116,117,114,101,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,105,115,32,115,101,99,116,105,111,110,46>>]},{p,[],[<<84,104,101,32,110,101,119,32,118,101,114,98,115,32,109,97,107,101,32,117,115,101,32,111,102,32,119,104,97,116,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,105,110,118,97,108,105,100,32,115,121,110,116,97,120,58,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,97,115,116,101,114,105,115,107,46,32,84,104,101,121,32,97,114,101,32,103,101,110,101,114,97,108,108,121,32,111,102,32,116,104,101,32,102,111,114,109,32,40,42,86,69,82,66,41,32,111,114,32,40,42,86,69,82,66,58,78,65,77,69,41,46,32,83,111,109,101,32,99,97,110,32,116,97,107,101,32,101,105,116,104,101,114,32,102,111,114,109,44,32,112,111,115,115,105,98,108,121,32,98,101,104,97,118,105,110,103,32,100,105,102,102,101,114,101,110,116,108,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,119,104,101,116,104,101,114,32,97,32,110,97,109,101,32,105,115,32,112,114,101,115,101,110,116,46,32,65,32,110,97,109,101,32,105,115,32,97,110,121,32,115,101,113,117,101,110,99,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,84,104,101,32,109,97,120,105,109,117,109,32,110,97,109,101,32,108,101,110,103,116,104,32,105,115,32,50,53,53,32,105,110,32,116,104,101,32,56,45,98,105,116,32,108,105,98,114,97,114,121,32,97,110,100,32,54,53,53,51,53,32,105,110,32,116,104,101,32,49,54,45,98,105,116,32,97,110,100,32,51,50,45,98,105,116,32,108,105,98,114,97,114,105,101,115,46,32,73,102,32,116,104,101,32,110,97,109,101,32,105,115,32,101,109,112,116,121,44,32,116,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,115,32,116,104,101,32,99,111,108,111,110,44,32,116,104,101,32,101,102,102,101,99,116,32,105,115,32,97,115,32,105,102,32,116,104,101,32,99,111,108,111,110,32,119,97,115,32,110,111,116,32,116,104,101,114,101,46,32,65,110,121,32,110,117,109,98,101,114,32,111,102,32,116,104,101,115,101,32,118,101,114,98,115,32,99,97,110,32,111,99,99,117,114,32,105,110,32,97,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,115,101,32,118,101,114,98,115,32,105,110,32,114,101,112,101,97,116,101,100,32,103,114,111,117,112,115,44,32,97,115,115,101,114,116,105,111,110,115,44,32,97,110,100,32,105,110,32,115,117,98,112,97,116,116,101,114,110,115,32,99,97,108,108,101,100,32,97,115,32,115,117,98,114,111,117,116,105,110,101,115,32,40,119,104,101,116,104,101,114,32,111,114,32,110,111,116,32,114,101,99,117,114,115,105,118,101,108,121,41,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46>>]},{p,[],[{em,[],[<<79,112,116,105,109,105,122,97,116,105,111,110,115,32,84,104,97,116,32,65,102,102,101,99,116,32,66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115>>]}]},{p,[],[<<80,67,82,69,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,116,104,97,116,32,97,114,101,32,117,115,101,100,32,116,111,32,115,112,101,101,100,32,117,112,32,109,97,116,99,104,105,110,103,32,98,121,32,114,117,110,110,105,110,103,32,115,111,109,101,32,99,104,101,99,107,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,101,97,99,104,32,109,97,116,99,104,32,97,116,116,101,109,112,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,99,97,110,32,107,110,111,119,32,116,104,101,32,109,105,110,105,109,117,109,32,108,101,110,103,116,104,32,111,102,32,109,97,116,99,104,105,110,103,32,115,117,98,106,101,99,116,44,32,111,114,32,116,104,97,116,32,97,32,112,97,114,116,105,99,117,108,97,114,32,99,104,97,114,97,99,116,101,114,32,109,117,115,116,32,98,101,32,112,114,101,115,101,110,116,46,32,87,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,98,121,112,97,115,115,101,115,32,116,104,101,32,114,117,110,110,105,110,103,32,111,102,32,97,32,109,97,116,99,104,44,32,97,110,121,32,105,110,99,108,117,100,101,100,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,97,114,101,32,110,111,116,32,112,114,111,99,101,115,115,101,100,46,32,112,114,111,99,101,115,115,101,100,46,32,89,111,117,32,99,97,110,32,115,117,112,112,114,101,115,115,32,116,104,101,32,115,116,97,114,116,45,111,102,45,109,97,116,99,104,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]},<<32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,111,114,32,98,121,32,115,116,97,114,116,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,119,105,116,104,32,40,42,78,79,95,83,84,65,82,84,95,79,80,84,41,46>>]},{p,[],[<<69,120,112,101,114,105,109,101,110,116,115,32,119,105,116,104,32,80,101,114,108,32,115,117,103,103,101,115,116,32,116,104,97,116,32,105,116,32,116,111,111,32,104,97,115,32,115,105,109,105,108,97,114,32,111,112,116,105,109,105,122,97,116,105,111,110,115,44,32,115,111,109,101,116,105,109,101,115,32,108,101,97,100,105,110,103,32,116,111,32,97,110,111,109,97,108,111,117,115,32,114,101,115,117,108,116,115,46>>]},{p,[],[{em,[],[<<86,101,114,98,115,32,84,104,97,116,32,65,99,116,32,73,109,109,101,100,105,97,116,101,108,121>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,115,32,97,99,116,32,97,115,32,115,111,111,110,32,97,115,32,116,104,101,121,32,97,114,101,32,101,110,99,111,117,110,116,101,114,101,100,46,32,84,104,101,121,32,109,117,115,116,32,110,111,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,46>>]},{pre,[],[{code,[],[<<40,42,65,67,67,69,80,84,41>>]}]},{p,[],[<<84,104,105,115,32,118,101,114,98,32,99,97,117,115,101,115,32,116,104,101,32,109,97,116,99,104,32,116,111,32,101,110,100,32,115,117,99,99,101,115,115,102,117,108,108,121,44,32,115,107,105,112,112,105,110,103,32,116,104,101,32,114,101,109,97,105,110,100,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,105,116,32,105,115,32,105,110,115,105,100,101,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,105,115,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,44,32,111,110,108,121,32,116,104,97,116,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,101,110,100,101,100,32,115,117,99,99,101,115,115,102,117,108,108,121,46,32,77,97,116,99,104,105,110,103,32,116,104,101,110,32,99,111,110,116,105,110,117,101,115,32,97,116,32,116,104,101,32,111,117,116,101,114,32,108,101,118,101,108,46,32,73,102,32,40,42,65,67,67,69,80,84,41,32,105,115,32,116,114,105,103,103,101,114,101,100,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,115,117,99,99,101,101,100,115,59,32,105,110,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,102,97,105,108,115,46>>]},{p,[],[<<73,102,32,40,42,65,67,67,69,80,84,41,32,105,115,32,105,110,115,105,100,101,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,44,32,116,104,101,32,100,97,116,97,32,115,111,32,102,97,114,32,105,115,32,99,97,112,116,117,114,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,65,66,34,44,32,34,65,65,68,34,44,32,111,114,32,34,65,67,68,34,46,32,87,104,101,110,32,105,116,32,109,97,116,99,104,101,115,32,34,65,66,34,44,32,34,66,34,32,105,115,32,99,97,112,116,117,114,101,100,32,98,121,32,116,104,101,32,111,117,116,101,114,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{pre,[],[{code,[],[<<65,40,40,63,58,65,124,66,40,42,65,67,67,69,80,84,41,124,67,41,68,41>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,32,99,97,117,115,101,115,32,97,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,44,32,102,111,114,99,105,110,103,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,111,32,111,99,99,117,114,46,32,73,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,40,63,33,41,32,98,117,116,32,101,97,115,105,101,114,32,116,111,32,114,101,97,100,46>>]},{pre,[],[{code,[],[<<40,42,70,65,73,76,41,32,111,114,32,40,42,70,41>>]}]},{p,[],[<<84,104,101,32,80,101,114,108,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,115,116,97,116,101,115,32,116,104,97,116,32,105,116,32,105,115,32,112,114,111,98,97,98,108,121,32,117,115,101,102,117,108,32,111,110,108,121,32,119,104,101,110,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,40,63,123,125,41,32,111,114,32,40,63,63,123,125,41,46,32,84,104,111,115,101,32,97,114,101,32,80,101,114,108,32,102,101,97,116,117,114,101,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,80,67,82,69,46>>]},{p,[],[<<65,32,109,97,116,99,104,32,119,105,116,104,32,116,104,101,32,115,116,114,105,110,103,32,34,97,97,97,97,34,32,97,108,119,97,121,115,32,102,97,105,108,115,44,32,98,117,116,32,116,104,101,32,99,97,108,108,111,117,116,32,105,115,32,116,97,107,101,110,32,98,101,102,111,114,101,32,101,97,99,104,32,98,97,99,107,116,114,97,99,107,32,111,99,99,117,114,115,32,40,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,44,32,49,48,32,116,105,109,101,115,41,46>>]},{p,[],[{em,[],[<<82,101,99,111,114,100,105,110,103,32,87,104,105,99,104,32,80,97,116,104,32,87,97,115,32,84,97,107,101,110>>]}]},{p,[],[<<84,104,101,32,109,97,105,110,32,112,117,114,112,111,115,101,32,111,102,32,116,104,105,115,32,118,101,114,98,32,105,115,32,116,111,32,116,114,97,99,107,32,104,111,119,32,97,32,109,97,116,99,104,32,119,97,115,32,97,114,114,105,118,101,100,32,97,116,44,32,97,108,116,104,111,117,103,104,32,105,116,32,97,108,115,111,32,104,97,115,32,97,32,115,101,99,111,110,100,97,114,121,32,117,115,101,32,105,110,32,119,105,116,104,32,97,100,118,97,110,99,105,110,103,32,116,104,101,32,109,97,116,99,104,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,32,40,115,101,101,32,40,42,83,75,73,80,41,32,98,101,108,111,119,41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,69,114,108,97,110,103,44,32,116,104,101,114,101,32,105,115,32,110,111,32,105,110,116,101,114,102,97,99,101,32,116,111,32,114,101,116,114,105,101,118,101,32,97,32,109,97,114,107,32,119,105,116,104,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,50,44,51>>]}]},<<44,32,115,111,32,111,110,108,121,32,116,104,101,32,115,101,99,111,110,100,97,114,121,32,112,117,114,112,111,115,101,32,105,115,32,114,101,108,101,118,97,110,116,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,46>>]},{p,[],[<<84,104,101,32,114,101,115,116,32,111,102,32,116,104,105,115,32,115,101,99,116,105,111,110,32,105,115,32,116,104,101,114,101,102,111,114,101,32,100,101,108,105,98,101,114,97,116,101,108,121,32,110,111,116,32,97,100,97,112,116,101,100,32,102,111,114,32,114,101,97,100,105,110,103,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,44,32,98,117,116,32,116,104,101,32,101,120,97,109,112,108,101,115,32,99,97,110,32,104,101,108,112,32,105,110,32,117,110,100,101,114,115,116,97,110,100,105,110,103,32,78,65,77,69,83,32,97,115,32,116,104,101,121,32,99,97,110,32,98,101,32,117,115,101,100,32,98,121,32,40,42,83,75,73,80,41,46>>]}]},{pre,[],[{code,[],[<<40,42,77,65,82,75,58,78,65,77,69,41,32,111,114,32,40,42,58,78,65,77,69,41>>]}]},{p,[],[<<65,32,110,97,109,101,32,105,115,32,97,108,119,97,121,115,32,114,101,113,117,105,114,101,100,32,119,105,116,104,32,116,104,105,115,32,118,101,114,98,46,32,84,104,101,114,101,32,99,97,110,32,98,101,32,97,115,32,109,97,110,121,32,105,110,115,116,97,110,99,101,115,32,111,102,32,40,42,77,65,82,75,41,32,97,115,32,121,111,117,32,108,105,107,101,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,97,110,100,32,116,104,101,105,114,32,110,97,109,101,115,32,100,111,32,110,111,116,32,104,97,118,101,32,116,111,32,98,101,32,117,110,105,113,117,101,46>>]},{p,[],[<<87,104,101,110,32,97,32,109,97,116,99,104,32,115,117,99,99,101,101,100,115,44,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,108,97,115,116,32,101,110,99,111,117,110,116,101,114,101,100,32,40,42,77,65,82,75,58,78,65,77,69,41,44,32,40,42,80,82,85,78,69,58,78,65,77,69,41,44,32,111,114,32,40,42,84,72,69,78,58,78,65,77,69,41,32,111,110,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,97,116,104,32,105,115,32,112,97,115,115,101,100,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,115,101,99,116,105,111,110,32,34,69,120,116,114,97,32,100,97,116,97,32,102,111,114,32>>,{code,[],[<<112,99,114,101,95,101,120,101,99,40,41>>]},<<34,32,105,110,32,116,104,101,32>>,{code,[],[<<112,99,114,101,97,112,105>>]},<<32,100,111,99,117,109,101,110,116,97,116,105,111,110,46,32,73,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,111,102,32>>,{code,[],[<<112,99,114,101,116,101,115,116>>]},<<32,111,117,116,112,117,116,44,32,116,104,101,32,47,75,32,109,111,100,105,102,105,101,114,32,114,101,113,117,101,115,116,115,32,116,104,101,32,114,101,116,114,105,101,118,97,108,32,97,110,100,32,111,117,116,112,117,116,116,105,110,103,32,111,102,32,40,42,77,65,82,75,41,32,100,97,116,97,58>>]},{pre,[],[{code,[],[<<32,32,114,101,62,32,47,88,40,42,77,65,82,75,58,65,41,89,124,88,40,42,77,65,82,75,58,66,41,90,47,75,10,100,97,116,97,62,32,88,89,10,32,48,58,32,88,89,10,77,75,58,32,65,10,88,90,10,32,48,58,32,88,90,10,77,75,58,32,66>>]}]},{p,[],[<<84,104,101,32,40,42,77,65,82,75,41,32,110,97,109,101,32,105,115,32,116,97,103,103,101,100,32,119,105,116,104,32,34,77,75,58,34,32,105,110,32,116,104,105,115,32,111,117,116,112,117,116,44,32,97,110,100,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,32,105,116,32,105,110,100,105,99,97,116,101,115,32,119,104,105,99,104,32,111,102,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,109,97,116,99,104,101,100,46,32,84,104,105,115,32,105,115,32,97,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,119,97,121,32,111,102,32,111,98,116,97,105,110,105,110,103,32,116,104,105,115,32,105,110,102,111,114,109,97,116,105,111,110,32,116,104,97,110,32,112,117,116,116,105,110,103,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,105,116,115,32,111,119,110,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<73,102,32,97,32,118,101,114,98,32,119,105,116,104,32,97,32,110,97,109,101,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,44,32,116,104,101,32,110,97,109,101,32,105,115,32,114,101,99,111,114,100,101,100,32,97,110,100,32,112,97,115,115,101,100,32,98,97,99,107,32,105,102,32,105,116,32,105,115,32,116,104,101,32,108,97,115,116,32,101,110,99,111,117,110,116,101,114,101,100,46,32,84,104,105,115,32,100,111,101,115,32,110,111,116,32,111,99,99,117,114,32,102,111,114,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,111,114,32,102,97,105,108,105,110,103,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46>>]},{p,[],[<<65,102,116,101,114,32,97,32,112,97,114,116,105,97,108,32,109,97,116,99,104,32,111,114,32,97,32,102,97,105,108,101,100,32,109,97,116,99,104,44,32,116,104,101,32,108,97,115,116,32,101,110,99,111,117,110,116,101,114,101,100,32,110,97,109,101,32,105,110,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,112,114,111,99,101,115,115,32,105,115,32,114,101,116,117,114,110,101,100,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<32,32,114,101,62,32,47,88,40,42,77,65,82,75,58,65,41,89,124,88,40,42,77,65,82,75,58,66,41,90,47,75,10,100,97,116,97,62,32,88,80,10,78,111,32,109,97,116,99,104,44,32,109,97,114,107,32,61,32,66>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,105,110,32,116,104,105,115,32,117,110,97,110,99,104,111,114,101,100,32,101,120,97,109,112,108,101,44,32,116,104,101,32,109,97,114,107,32,105,115,32,114,101,116,97,105,110,101,100,32,102,114,111,109,32,116,104,101,32,109,97,116,99,104,32,97,116,116,101,109,112,116,32,116,104,97,116,32,115,116,97,114,116,101,100,32,97,116,32,108,101,116,116,101,114,32,34,88,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,83,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,32,97,116,116,101,109,112,116,115,32,115,116,97,114,116,105,110,103,32,97,116,32,34,80,34,32,97,110,100,32,116,104,101,110,32,119,105,116,104,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,100,111,32,110,111,116,32,103,101,116,32,97,115,32,102,97,114,32,97,115,32,116,104,101,32,40,42,77,65,82,75,41,32,105,116,101,109,44,32,110,101,118,101,114,116,104,101,108,101,115,115,32,100,111,32,110,111,116,32,114,101,115,101,116,32,105,116,46>>]},{p,[],[{em,[],[<<86,101,114,98,115,32,84,104,97,116,32,65,99,116,32,97,102,116,101,114,32,66,97,99,107,116,114,97,99,107,105,110,103>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,115,32,100,111,32,110,111,116,104,105,110,103,32,119,104,101,110,32,116,104,101,121,32,97,114,101,32,101,110,99,111,117,110,116,101,114,101,100,46,32,77,97,116,99,104,105,110,103,32,99,111,110,116,105,110,117,101,115,32,119,105,116,104,32,119,104,97,116,32,102,111,108,108,111,119,115,44,32,98,117,116,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,44,32,99,97,117,115,105,110,103,32,97,32,98,97,99,107,116,114,97,99,107,32,116,111,32,116,104,101,32,118,101,114,98,44,32,97,32,102,97,105,108,117,114,101,32,105,115,32,102,111,114,99,101,100,46,32,84,104,97,116,32,105,115,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,110,111,116,32,112,97,115,115,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,116,104,101,32,118,101,114,98,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,118,101,114,98,115,32,97,112,112,101,97,114,115,32,105,110,115,105,100,101,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,111,114,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,44,32,105,116,115,32,101,102,102,101,99,116,32,105,115,32,99,111,110,102,105,110,101,100,32,116,111,32,116,104,97,116,32,103,114,111,117,112,44,32,97,115,32,111,110,99,101,32,116,104,101,32,103,114,111,117,112,32,104,97,115,32,98,101,101,110,32,109,97,116,99,104,101,100,44,32,116,104,101,114,101,32,105,115,32,110,101,118,101,114,32,97,110,121,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,105,116,46,32,73,110,32,116,104,105,115,32,115,105,116,117,97,116,105,111,110,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,32,34,106,117,109,112,32,98,97,99,107,34,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,116,104,101,32,101,110,116,105,114,101,32,97,116,111,109,105,99,32,103,114,111,117,112,32,111,114,32,97,115,115,101,114,116,105,111,110,46,32,40,82,101,109,101,109,98,101,114,32,97,108,115,111,44,32,97,115,32,115,116,97,116,101,100,32,97,98,111,118,101,44,32,116,104,97,116,32,116,104,105,115,32,108,111,99,97,108,105,122,97,116,105,111,110,32,97,108,115,111,32,97,112,112,108,105,101,115,32,105,110,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,115,46,41>>]},{p,[],[<<84,104,101,115,101,32,118,101,114,98,115,32,100,105,102,102,101,114,32,105,110,32,101,120,97,99,116,108,121,32,119,104,97,116,32,107,105,110,100,32,111,102,32,102,97,105,108,117,114,101,32,111,99,99,117,114,115,32,119,104,101,110,32,98,97,99,107,116,114,97,99,107,105,110,103,32,114,101,97,99,104,101,115,32,116,104,101,109,46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,32,105,115,32,119,104,97,116,32,111,99,99,117,114,115,32,119,104,101,110,32,116,104,101,32,118,101,114,98,32,105,115,32,110,111,116,32,105,110,32,97,32,115,117,98,114,111,117,116,105,110,101,32,111,114,32,97,110,32,97,115,115,101,114,116,105,111,110,46,32,83,117,98,115,101,113,117,101,110,116,32,115,101,99,116,105,111,110,115,32,99,111,118,101,114,32,116,104,101,115,101,32,115,112,101,99,105,97,108,32,99,97,115,101,115,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,44,32,119,104,105,99,104,32,109,117,115,116,32,110,111,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,44,32,99,97,117,115,101,115,32,116,104,101,32,119,104,111,108,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,32,111,117,116,114,105,103,104,116,32,105,102,32,116,104,101,114,101,32,105,115,32,97,32,108,97,116,101,114,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,116,104,97,116,32,99,97,117,115,101,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,111,32,114,101,97,99,104,32,105,116,46,32,69,118,101,110,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,117,110,97,110,99,104,111,114,101,100,44,32,110,111,32,102,117,114,116,104,101,114,32,97,116,116,101,109,112,116,115,32,116,111,32,102,105,110,100,32,97,32,109,97,116,99,104,32,98,121,32,97,100,118,97,110,99,105,110,103,32,116,104,101,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,32,116,97,107,101,32,112,108,97,99,101,46>>]},{pre,[],[{code,[],[<<40,42,67,79,77,77,73,84,41>>]}]},{p,[],[<<73,102,32,40,42,67,79,77,77,73,84,41,32,105,115,32,116,104,101,32,111,110,108,121,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,32,116,104,97,116,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,44,32,111,110,99,101,32,105,116,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,50,44,51>>]}]},<<32,105,115,32,99,111,109,109,105,116,116,101,100,32,116,111,32,102,105,110,100,32,97,32,109,97,116,99,104,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,44,32,111,114,32,110,111,116,32,97,116,32,97,108,108,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<97,43,40,42,67,79,77,77,73,84,41,98>>]}]},{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,34,120,120,97,97,98,34,32,98,117,116,32,110,111,116,32,34,97,97,99,97,97,98,34,46,32,73,116,32,99,97,110,32,98,101,32,116,104,111,117,103,104,116,32,111,102,32,97,115,32,97,32,107,105,110,100,32,111,102,32,100,121,110,97,109,105,99,32,97,110,99,104,111,114,44,32,111,114,32,34,73,39,118,101,32,115,116,97,114,116,101,100,44,32,115,111,32,73,32,109,117,115,116,32,102,105,110,105,115,104,34,46,32,84,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,112,97,115,115,101,100,32,40,42,77,65,82,75,41,32,105,110,32,116,104,101,32,112,97,116,104,32,105,115,32,112,97,115,115,101,100,32,98,97,99,107,32,119,104,101,110,32,40,42,67,79,77,77,73,84,41,32,102,111,114,99,101,115,32,97,32,109,97,116,99,104,32,102,97,105,108,117,114,101,46>>]},{p,[],[<<73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,32,101,120,105,115,116,115,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,97,32,100,105,102,102,101,114,101,110,116,32,111,110,101,32,116,104,97,116,32,102,111,108,108,111,119,115,32,40,42,67,79,77,77,73,84,41,32,99,97,110,32,98,101,32,116,114,105,103,103,101,114,101,100,32,102,105,114,115,116,44,32,115,111,32,109,101,114,101,108,121,32,112,97,115,115,105,110,103,32,40,42,67,79,77,77,73,84,41,32,100,117,114,105,110,103,32,97,32,109,97,116,99,104,32,100,111,101,115,32,110,111,116,32,97,108,119,97,121,115,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,97,32,109,97,116,99,104,32,109,117,115,116,32,98,101,32,97,116,32,116,104,105,115,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,40,42,67,79,77,77,73,84,41,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,97,110,32,97,110,99,104,111,114,44,32,117,110,108,101,115,115,32,116,104,101,32,80,67,82,69,32,115,116,97,114,116,45,111,102,45,109,97,116,99,104,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,97,114,101,32,116,117,114,110,101,100,32,111,102,102,44,32,97,115,32,115,104,111,119,110,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<49,62,32,114,101,58,114,117,110,40,34,120,121,122,97,98,99,34,44,34,40,42,67,79,77,77,73,84,41,97,98,99,34,44,91,123,99,97,112,116,117,114,101,44,97,108,108,44,108,105,115,116,125,93,41,46,10,123,109,97,116,99,104,44,91,34,97,98,99,34,93,125,10,50,62,32,114,101,58,114,117,110,40,34,120,121,122,97,98,99,34,44,34,40,42,67,79,77,77,73,84,41,97,98,99,34,44,91,123,99,97,112,116,117,114,101,44,97,108,108,44,108,105,115,116,125,44,110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101,93,41,46,10,110,111,109,97,116,99,104>>]}]},{p,[],[<<70,111,114,32,116,104,105,115,32,112,97,116,116,101,114,110,44,32,80,67,82,69,32,107,110,111,119,115,32,116,104,97,116,32,97,110,121,32,109,97,116,99,104,32,109,117,115,116,32,115,116,97,114,116,32,119,105,116,104,32,34,97,34,44,32,115,111,32,116,104,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,115,107,105,112,115,32,97,108,111,110,103,32,116,104,101,32,115,117,98,106,101,99,116,32,116,111,32,34,97,34,32,98,101,102,111,114,101,32,97,112,112,108,121,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,116,111,32,116,104,101,32,102,105,114,115,116,32,115,101,116,32,111,102,32,100,97,116,97,46,32,84,104,101,32,109,97,116,99,104,32,97,116,116,101,109,112,116,32,116,104,101,110,32,115,117,99,99,101,101,100,115,46,32,73,110,32,116,104,101,32,115,101,99,111,110,100,32,99,97,108,108,32,116,104,101,32>>,{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]},<<32,100,105,115,97,98,108,101,115,32,116,104,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,115,107,105,112,115,32,97,108,111,110,103,32,116,111,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,112,97,116,116,101,114,110,32,105,115,32,110,111,119,32,97,112,112,108,105,101,100,32,115,116,97,114,116,105,110,103,32,97,116,32,34,120,34,44,32,97,110,100,32,115,111,32,116,104,101,32,40,42,67,79,77,77,73,84,41,32,99,97,117,115,101,115,32,116,104,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,32,119,105,116,104,111,117,116,32,116,114,121,105,110,103,32,97,110,121,32,111,116,104,101,114,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,115,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,32,99,97,117,115,101,115,32,116,104,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,114,116,105,110,103,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,105,102,32,116,104,101,114,101,32,105,115,32,97,32,108,97,116,101,114,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,116,104,97,116,32,99,97,117,115,101,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,111,32,114,101,97,99,104,32,105,116,58>>]},{pre,[],[{code,[],[<<40,42,80,82,85,78,69,41,32,111,114,32,40,42,80,82,85,78,69,58,78,65,77,69,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,117,110,97,110,99,104,111,114,101,100,44,32,116,104,101,32,110,111,114,109,97,108,32,34,98,117,109,112,97,108,111,110,103,34,32,97,100,118,97,110,99,101,32,116,111,32,116,104,101,32,110,101,120,116,32,115,116,97,114,116,105,110,103,32,99,104,97,114,97,99,116,101,114,32,116,104,101,110,32,111,99,99,117,114,115,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,32,111,99,99,117,114,32,97,115,32,117,115,117,97,108,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,40,42,80,82,85,78,69,41,44,32,98,101,102,111,114,101,32,105,116,32,105,115,32,114,101,97,99,104,101,100,44,32,111,114,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,116,111,32,116,104,101,32,114,105,103,104,116,32,111,102,32,40,42,80,82,85,78,69,41,44,32,98,117,116,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,109,97,116,99,104,32,116,111,32,116,104,101,32,114,105,103,104,116,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,110,111,116,32,99,114,111,115,115,32,40,42,80,82,85,78,69,41,46,32,73,110,32,115,105,109,112,108,101,32,99,97,115,101,115,44,32,116,104,101,32,117,115,101,32,111,102,32,40,42,80,82,85,78,69,41,32,105,115,32,106,117,115,116,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,116,111,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,111,114,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,44,32,98,117,116,32,116,104,101,114,101,32,97,114,101,32,115,111,109,101,32,117,115,101,115,32,111,102,32,40,42,80,82,85,78,69,41,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,101,120,112,114,101,115,115,101,100,32,105,110,32,97,110,121,32,111,116,104,101,114,32,119,97,121,46,32,73,110,32,97,110,32,97,110,99,104,111,114,101,100,32,112,97,116,116,101,114,110,44,32,40,42,80,82,85,78,69,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,40,42,67,79,77,77,73,84,41,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,40,42,80,82,85,78,69,58,78,65,77,69,41,32,105,115,32,116,104,101,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,40,42,77,65,82,75,58,78,65,77,69,41,40,42,80,82,85,78,69,41,46,32,73,116,32,105,115,32,108,105,107,101,32,40,42,77,65,82,75,58,78,65,77,69,41,32,105,110,32,116,104,97,116,32,116,104,101,32,110,97,109,101,32,105,115,32,114,101,109,101,109,98,101,114,101,100,32,102,111,114,32,112,97,115,115,105,110,103,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,46,32,72,111,119,101,118,101,114,44,32,40,42,83,75,73,80,58,78,65,77,69,41,32,115,101,97,114,99,104,101,115,32,111,110,108,121,32,102,111,114,32,110,97,109,101,115,32,115,101,116,32,119,105,116,104,32,40,42,77,65,82,75,41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,102,97,99,116,32,116,104,97,116,32,40,42,80,82,85,78,69,58,78,65,77,69,41,32,114,101,109,101,109,98,101,114,115,32,116,104,101,32,110,97,109,101,32,105,115,32,117,115,101,108,101,115,115,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,44,32,97,115,32,110,97,109,101,115,32,99,97,110,110,111,116,32,98,101,32,114,101,116,114,105,101,118,101,100,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,44,32,119,104,101,110,32,115,112,101,99,105,102,105,101,100,32,119,105,116,104,111,117,116,32,97,32,110,97,109,101,44,32,105,115,32,108,105,107,101,32,40,42,80,82,85,78,69,41,44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,117,110,97,110,99,104,111,114,101,100,44,32,116,104,101,32,34,98,117,109,112,97,108,111,110,103,34,32,97,100,118,97,110,99,101,32,105,115,32,110,111,116,32,116,111,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,44,32,98,117,116,32,116,111,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,119,104,101,114,101,32,40,42,83,75,73,80,41,32,119,97,115,32,101,110,99,111,117,110,116,101,114,101,100,46>>]},{pre,[],[{code,[],[<<40,42,83,75,73,80,41>>]}]},{p,[],[<<40,42,83,75,73,80,41,32,115,105,103,110,105,102,105,101,115,32,116,104,97,116,32,119,104,97,116,101,118,101,114,32,116,101,120,116,32,119,97,115,32,109,97,116,99,104,101,100,32,108,101,97,100,105,110,103,32,117,112,32,116,111,32,105,116,32,99,97,110,110,111,116,32,98,101,32,112,97,114,116,32,111,102,32,97,32,115,117,99,99,101,115,115,102,117,108,32,109,97,116,99,104,46,32,67,111,110,115,105,100,101,114,58>>]},{pre,[],[{code,[],[<<97,43,40,42,83,75,73,80,41,98>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,97,97,97,97,99,46,46,46,34,44,32,97,102,116,101,114,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,32,97,116,116,101,109,112,116,32,102,97,105,108,115,32,40,115,116,97,114,116,105,110,103,32,97,116,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,115,116,114,105,110,103,41,44,32,116,104,101,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,32,115,107,105,112,115,32,111,110,32,116,111,32,115,116,97,114,116,32,116,104,101,32,110,101,120,116,32,97,116,116,101,109,112,116,32,97,116,32,34,99,34,46,32,78,111,116,105,99,101,32,116,104,97,116,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,116,104,105,115,32,101,120,97,109,112,108,101,59,32,97,108,116,104,111,117,103,104,32,105,116,32,119,111,117,108,100,32,115,117,112,112,114,101,115,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,100,117,114,105,110,103,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,32,97,116,116,101,109,112,116,44,32,116,104,101,32,115,101,99,111,110,100,32,97,116,116,101,109,112,116,32,119,111,117,108,100,32,115,116,97,114,116,32,97,116,32,116,104,101,32,115,101,99,111,110,100,32,99,104,97,114,97,99,116,101,114,32,105,110,115,116,101,97,100,32,111,102,32,115,107,105,112,112,105,110,103,32,111,110,32,116,111,32,34,99,34,46>>]},{p,[],[<<87,104,101,110,32,40,42,83,75,73,80,41,32,104,97,115,32,97,110,32,97,115,115,111,99,105,97,116,101,100,32,110,97,109,101,44,32,105,116,115,32,98,101,104,97,118,105,111,114,32,105,115,32,109,111,100,105,102,105,101,100,58>>]},{pre,[],[{code,[],[<<40,42,83,75,73,80,58,78,65,77,69,41>>]}]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,105,115,32,116,114,105,103,103,101,114,101,100,44,32,116,104,101,32,112,114,101,118,105,111,117,115,32,112,97,116,104,32,116,104,114,111,117,103,104,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,115,101,97,114,99,104,101,100,32,102,111,114,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,40,42,77,65,82,75,41,32,116,104,97,116,32,104,97,115,32,116,104,101,32,115,97,109,101,32,110,97,109,101,46,32,73,102,32,111,110,101,32,105,115,32,102,111,117,110,100,44,32,116,104,101,32,34,98,117,109,112,97,108,111,110,103,34,32,97,100,118,97,110,99,101,32,105,115,32,116,111,32,116,104,101,32,115,117,98,106,101,99,116,32,112,111,115,105,116,105,111,110,32,116,104,97,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,97,116,32,40,42,77,65,82,75,41,32,105,110,115,116,101,97,100,32,111,102,32,116,111,32,119,104,101,114,101,32,40,42,83,75,73,80,41,32,119,97,115,32,101,110,99,111,117,110,116,101,114,101,100,46,32,73,102,32,110,111,32,40,42,77,65,82,75,41,32,119,105,116,104,32,97,32,109,97,116,99,104,105,110,103,32,110,97,109,101,32,105,115,32,102,111,117,110,100,44,32,40,42,83,75,73,80,41,32,105,115,32,105,103,110,111,114,101,100,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,40,42,83,75,73,80,58,78,65,77,69,41,32,115,101,97,114,99,104,101,115,32,111,110,108,121,32,102,111,114,32,110,97,109,101,115,32,115,101,116,32,98,121,32,40,42,77,65,82,75,58,78,65,77,69,41,46,32,73,116,32,105,103,110,111,114,101,115,32,110,97,109,101,115,32,116,104,97,116,32,97,114,101,32,115,101,116,32,98,121,32,40,42,80,82,85,78,69,58,78,65,77,69,41,32,111,114,32,40,42,84,72,69,78,58,78,65,77,69,41,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,32,99,97,117,115,101,115,32,97,32,115,107,105,112,32,116,111,32,116,104,101,32,110,101,120,116,32,105,110,110,101,114,109,111,115,116,32,97,108,116,101,114,110,97,116,105,118,101,32,119,104,101,110,32,98,97,99,107,116,114,97,99,107,105,110,103,32,114,101,97,99,104,101,115,32,105,116,46,32,84,104,97,116,32,105,115,44,32,105,116,32,99,97,110,99,101,108,115,32,97,110,121,32,102,117,114,116,104,101,114,32,98,97,99,107,116,114,97,99,107,105,110,103,32,119,105,116,104,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,97,108,116,101,114,110,97,116,105,118,101,46>>]},{pre,[],[{code,[],[<<40,42,84,72,69,78,41,32,111,114,32,40,42,84,72,69,78,58,78,65,77,69,41>>]}]},{p,[],[<<84,104,101,32,118,101,114,98,32,110,97,109,101,32,99,111,109,101,115,32,102,114,111,109,32,116,104,101,32,111,98,115,101,114,118,97,116,105,111,110,32,116,104,97,116,32,105,116,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,97,32,112,97,116,116,101,114,110,45,98,97,115,101,100,32,105,102,45,116,104,101,110,45,101,108,115,101,32,98,108,111,99,107,58>>]},{pre,[],[{code,[],[<<40,32,67,79,78,68,49,32,40,42,84,72,69,78,41,32,70,79,79,32,124,32,67,79,78,68,50,32,40,42,84,72,69,78,41,32,66,65,82,32,124,32,67,79,78,68,51,32,40,42,84,72,69,78,41,32,66,65,90,32,41,32,46,46,46>>]}]},{p,[],[<<73,102,32,116,104,101,32,67,79,78,68,49,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,44,32,70,79,79,32,105,115,32,116,114,105,101,100,32,40,97,110,100,32,112,111,115,115,105,98,108,121,32,102,117,114,116,104,101,114,32,105,116,101,109,115,32,97,102,116,101,114,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,103,114,111,117,112,32,105,102,32,70,79,79,32,115,117,99,99,101,101,100,115,41,46,32,79,110,32,102,97,105,108,117,114,101,44,32,116,104,101,32,109,97,116,99,104,101,114,32,115,107,105,112,115,32,116,111,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,32,97,110,100,32,116,114,105,101,115,32,67,79,78,68,50,44,32,119,105,116,104,111,117,116,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,67,79,78,68,49,46,32,73,102,32,116,104,97,116,32,115,117,99,99,101,101,100,115,32,97,110,100,32,66,65,82,32,102,97,105,108,115,44,32,67,79,78,68,51,32,105,115,32,116,114,105,101,100,46,32,73,102,32,66,65,90,32,116,104,101,110,32,102,97,105,108,115,44,32,116,104,101,114,101,32,97,114,101,32,110,111,32,109,111,114,101,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,115,111,32,116,104,101,114,101,32,105,115,32,97,32,98,97,99,107,116,114,97,99,107,32,116,111,32,119,104,97,116,101,118,101,114,32,99,97,109,101,32,98,101,102,111,114,101,32,116,104,101,32,101,110,116,105,114,101,32,103,114,111,117,112,46,32,73,102,32,40,42,84,72,69,78,41,32,105,115,32,110,111,116,32,105,110,115,105,100,101,32,97,110,32,97,108,116,101,114,110,97,116,105,111,110,44,32,105,116,32,97,99,116,115,32,108,105,107,101,32,40,42,80,82,85,78,69,41,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,40,42,84,72,69,78,58,78,65,77,69,41,32,105,115,32,116,104,101,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,40,42,77,65,82,75,58,78,65,77,69,41,40,42,84,72,69,78,41,46,32,73,116,32,105,115,32,108,105,107,101,32,40,42,77,65,82,75,58,78,65,77,69,41,32,105,110,32,116,104,97,116,32,116,104,101,32,110,97,109,101,32,105,115,32,114,101,109,101,109,98,101,114,101,100,32,102,111,114,32,112,97,115,115,105,110,103,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,46,32,72,111,119,101,118,101,114,44,32,40,42,83,75,73,80,58,78,65,77,69,41,32,115,101,97,114,99,104,101,115,32,111,110,108,121,32,102,111,114,32,110,97,109,101,115,32,115,101,116,32,119,105,116,104,32,40,42,77,65,82,75,41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,102,97,99,116,32,116,104,97,116,32,40,42,84,72,69,78,58,78,65,77,69,41,32,114,101,109,101,109,98,101,114,115,32,116,104,101,32,110,97,109,101,32,105,115,32,117,115,101,108,101,115,115,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,44,32,97,115,32,110,97,109,101,115,32,99,97,110,110,111,116,32,98,101,32,114,101,116,114,105,101,118,101,100,46>>]}]},{p,[],[<<65,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,99,111,110,116,97,105,110,32,97,32,124,32,99,104,97,114,97,99,116,101,114,32,105,115,32,106,117,115,116,32,97,32,112,97,114,116,32,111,102,32,116,104,101,32,101,110,99,108,111,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,59,32,105,116,32,105,115,32,110,111,116,32,97,32,110,101,115,116,101,100,32,97,108,116,101,114,110,97,116,105,111,110,32,119,105,116,104,32,111,110,108,121,32,111,110,101,32,97,108,116,101,114,110,97,116,105,118,101,46,32,84,104,101,32,101,102,102,101,99,116,32,111,102,32,40,42,84,72,69,78,41,32,101,120,116,101,110,100,115,32,98,101,121,111,110,100,32,115,117,99,104,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,111,32,116,104,101,32,101,110,99,108,111,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,101,114,101,32,65,44,32,66,44,32,97,110,100,32,115,111,32,111,110,44,32,97,114,101,32,99,111,109,112,108,101,120,32,112,97,116,116,101,114,110,32,102,114,97,103,109,101,110,116,115,32,116,104,97,116,32,100,111,32,110,111,116,32,99,111,110,116,97,105,110,32,97,110,121,32,124,32,99,104,97,114,97,99,116,101,114,115,32,97,116,32,116,104,105,115,32,108,101,118,101,108,58>>]},{pre,[],[{code,[],[<<65,32,40,66,40,42,84,72,69,78,41,67,41,32,124,32,68>>]}]},{p,[],[<<73,102,32,65,32,97,110,100,32,66,32,97,114,101,32,109,97,116,99,104,101,100,44,32,98,117,116,32,116,104,101,114,101,32,105,115,32,97,32,102,97,105,108,117,114,101,32,105,110,32,67,44,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,116,32,98,97,99,107,116,114,97,99,107,32,105,110,116,111,32,65,59,32,105,110,115,116,101,97,100,32,105,116,32,109,111,118,101,115,32,116,111,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,44,32,116,104,97,116,32,105,115,44,32,68,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,99,111,110,116,97,105,110,105,110,103,32,40,42,84,72,69,78,41,32,105,115,32,103,105,118,101,110,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,44,32,105,116,32,98,101,104,97,118,101,115,32,100,105,102,102,101,114,101,110,116,108,121,58>>]},{pre,[],[{code,[],[<<65,32,40,66,40,42,84,72,69,78,41,67,32,124,32,40,42,70,65,73,76,41,41,32,124,32,68>>]}]},{p,[],[<<84,104,101,32,101,102,102,101,99,116,32,111,102,32,40,42,84,72,69,78,41,32,105,115,32,110,111,119,32,99,111,110,102,105,110,101,100,32,116,111,32,116,104,101,32,105,110,110,101,114,32,115,117,98,112,97,116,116,101,114,110,46,32,65,102,116,101,114,32,97,32,102,97,105,108,117,114,101,32,105,110,32,67,44,32,109,97,116,99,104,105,110,103,32,109,111,118,101,115,32,116,111,32,40,42,70,65,73,76,41,44,32,119,104,105,99,104,32,99,97,117,115,101,115,32,116,104,101,32,119,104,111,108,101,32,115,117,98,112,97,116,116,101,114,110,32,116,111,32,102,97,105,108,44,32,97,115,32,116,104,101,114,101,32,97,114,101,32,110,111,32,109,111,114,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,116,111,32,116,114,121,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,119,32,98,97,99,107,116,114,97,99,107,32,105,110,116,111,32,65,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,99,111,110,115,105,100,101,114,101,100,32,97,115,32,104,97,118,105,110,103,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,97,115,32,111,110,108,121,32,111,110,101,32,105,115,32,101,118,101,114,32,117,115,101,100,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,124,32,99,104,97,114,97,99,116,101,114,32,105,110,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,97,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,46,32,73,103,110,111,114,105,110,103,32,119,104,105,116,101,115,112,97,99,101,44,32,99,111,110,115,105,100,101,114,58>>]},{pre,[],[{code,[],[<<94,46,42,63,32,40,63,40,63,61,97,41,32,97,32,124,32,98,40,42,84,72,69,78,41,99,32,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,98,97,34,44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,46,32,65,115,32,46,42,63,32,105,115,32,117,110,103,114,101,101,100,121,44,32,105,116,32,105,110,105,116,105,97,108,108,121,32,109,97,116,99,104,101,115,32,122,101,114,111,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,99,111,110,100,105,116,105,111,110,32,40,63,61,97,41,32,116,104,101,110,32,102,97,105,108,115,44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,34,98,34,32,105,115,32,109,97,116,99,104,101,100,44,32,98,117,116,32,34,99,34,32,105,115,32,110,111,116,46,32,65,116,32,116,104,105,115,32,112,111,105,110,116,44,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,116,32,98,97,99,107,116,114,97,99,107,32,116,111,32,46,42,63,32,97,115,32,99,97,110,32,112,101,114,104,97,112,115,32,98,101,32,101,120,112,101,99,116,101,100,32,102,114,111,109,32,116,104,101,32,112,114,101,115,101,110,99,101,32,111,102,32,116,104,101,32,124,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,115,105,110,103,108,101,32,97,108,116,101,114,110,97,116,105,118,101,32,116,104,97,116,32,99,111,109,112,114,105,115,101,115,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,44,32,97,110,100,32,115,111,32,116,104,101,32,109,97,116,99,104,32,102,97,105,108,115,46,32,40,73,102,32,116,104,101,114,101,32,119,97,115,32,97,32,98,97,99,107,116,114,97,99,107,32,105,110,116,111,32,46,42,63,44,32,97,108,108,111,119,105,110,103,32,105,116,32,116,111,32,109,97,116,99,104,32,34,98,34,44,32,116,104,101,32,109,97,116,99,104,32,119,111,117,108,100,32,115,117,99,99,101,101,100,46,41>>]},{p,[],[<<84,104,101,32,118,101,114,98,115,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,32,112,114,111,118,105,100,101,32,102,111,117,114,32,100,105,102,102,101,114,101,110,116,32,34,115,116,114,101,110,103,116,104,115,34,32,111,102,32,99,111,110,116,114,111,108,32,119,104,101,110,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,115,58>>]},{ul,[],[{li,[],[{p,[],[<<40,42,84,72,69,78,41,32,105,115,32,116,104,101,32,119,101,97,107,101,115,116,44,32,99,97,114,114,121,105,110,103,32,111,110,32,116,104,101,32,109,97,116,99,104,32,97,116,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,46>>]}]},{li,[],[{p,[],[<<40,42,80,82,85,78,69,41,32,99,111,109,101,115,32,110,101,120,116,44,32,102,97,105,108,115,32,116,104,101,32,109,97,116,99,104,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,114,116,105,110,103,32,112,111,115,105,116,105,111,110,44,32,98,117,116,32,97,108,108,111,119,115,32,97,110,32,97,100,118,97,110,99,101,32,116,111,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40,102,111,114,32,97,110,32,117,110,97,110,99,104,111,114,101,100,32,112,97,116,116,101,114,110,41,46>>]}]},{li,[],[{p,[],[<<40,42,83,75,73,80,41,32,105,115,32,115,105,109,105,108,97,114,44,32,101,120,99,101,112,116,32,116,104,97,116,32,116,104,101,32,97,100,118,97,110,99,101,32,99,97,110,32,98,101,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,99,104,97,114,97,99,116,101,114,46>>]}]},{li,[],[{p,[],[<<40,42,67,79,77,77,73,84,41,32,105,115,32,116,104,101,32,115,116,114,111,110,103,101,115,116,44,32,99,97,117,115,105,110,103,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46>>]}]}]},{p,[],[{em,[],[<<77,111,114,101,32,116,104,97,110,32,79,110,101,32,66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98>>]}]},{p,[],[<<73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,32,105,115,32,112,114,101,115,101,110,116,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,116,104,101,32,111,110,101,32,116,104,97,116,32,105,115,32,98,97,99,107,116,114,97,99,107,101,100,32,111,110,116,111,32,102,105,114,115,116,32,97,99,116,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,101,114,101,32,65,44,32,66,44,32,97,110,100,32,115,111,32,111,110,44,32,97,114,101,32,99,111,109,112,108,101,120,32,112,97,116,116,101,114,110,32,102,114,97,103,109,101,110,116,115,58>>]},{pre,[],[{code,[],[<<40,65,40,42,67,79,77,77,73,84,41,66,40,42,84,72,69,78,41,67,124,65,66,68,41>>]}]},{p,[],[<<73,102,32,65,32,109,97,116,99,104,101,115,32,98,117,116,32,66,32,102,97,105,108,115,44,32,116,104,101,32,98,97,99,107,116,114,97,99,107,32,116,111,32,40,42,67,79,77,77,73,84,41,32,99,97,117,115,101,115,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46,32,72,111,119,101,118,101,114,44,32,105,102,32,65,32,97,110,100,32,66,32,109,97,116,99,104,44,32,98,117,116,32,67,32,102,97,105,108,115,44,32,116,104,101,32,98,97,99,107,116,114,97,99,107,32,116,111,32,40,42,84,72,69,78,41,32,99,97,117,115,101,115,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,32,40,65,66,68,41,32,116,111,32,98,101,32,116,114,105,101,100,46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,105,115,32,99,111,110,115,105,115,116,101,110,116,44,32,98,117,116,32,105,115,32,110,111,116,32,97,108,119,97,121,115,32,116,104,101,32,115,97,109,101,32,97,115,32,105,110,32,80,101,114,108,46,32,73,116,32,109,101,97,110,115,32,116,104,97,116,32,105,102,32,116,119,111,32,111,114,32,109,111,114,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,97,112,112,101,97,114,32,105,110,32,115,117,99,99,101,115,115,105,111,110,44,32,116,104,101,32,108,97,115,116,32,111,102,32,116,104,101,109,32,104,97,115,32,110,111,32,101,102,102,101,99,116,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<46,46,46,40,42,67,79,77,77,73,84,41,40,42,80,82,85,78,69,41,46,46,46>>]}]},{p,[],[<<73,102,32,116,104,101,114,101,32,105,115,32,97,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,116,111,32,116,104,101,32,114,105,103,104,116,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,111,110,116,111,32,40,42,80,82,85,78,69,41,32,99,97,117,115,101,115,32,105,116,32,116,111,32,98,101,32,116,114,105,103,103,101,114,101,100,44,32,97,110,100,32,105,116,115,32,97,99,116,105,111,110,32,105,115,32,116,97,107,101,110,46,32,84,104,101,114,101,32,99,97,110,32,110,101,118,101,114,32,98,101,32,97,32,98,97,99,107,116,114,97,99,107,32,111,110,116,111,32,40,42,67,79,77,77,73,84,41,46>>]},{p,[],[{em,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115,32,105,110,32,82,101,112,101,97,116,101,100,32,71,114,111,117,112,115>>]}]},{p,[],[<<80,67,82,69,32,100,105,102,102,101,114,115,32,102,114,111,109,32,80,101,114,108,32,105,110,32,105,116,115,32,104,97,110,100,108,105,110,103,32,111,102,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,105,110,32,114,101,112,101,97,116,101,100,32,103,114,111,117,112,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,58>>]},{pre,[],[{code,[],[<<47,40,97,40,42,67,79,77,77,73,84,41,98,41,43,97,99,47>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,97,98,97,99,34,44,32,80,101,114,108,32,109,97,116,99,104,101,115,44,32,98,117,116,32,80,67,82,69,32,102,97,105,108,115,32,98,101,99,97,117,115,101,32,116,104,101,32,40,42,67,79,77,77,73,84,41,32,105,110,32,116,104,101,32,115,101,99,111,110,100,32,114,101,112,101,97,116,32,111,102,32,116,104,101,32,103,114,111,117,112,32,97,99,116,115,46>>]},{p,[],[{em,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115,32,105,110,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<40,42,70,65,73,76,41,32,105,110,32,97,110,32,97,115,115,101,114,116,105,111,110,32,104,97,115,32,105,116,115,32,110,111,114,109,97,108,32,101,102,102,101,99,116,58,32,105,116,32,102,111,114,99,101,115,32,97,110,32,105,109,109,101,100,105,97,116,101,32,98,97,99,107,116,114,97,99,107,46>>]},{p,[],[<<40,42,65,67,67,69,80,84,41,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,99,97,117,115,101,115,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,116,111,32,115,117,99,99,101,101,100,32,119,105,116,104,111,117,116,32,97,110,121,32,102,117,114,116,104,101,114,32,112,114,111,99,101,115,115,105,110,103,46,32,73,110,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,44,32,40,42,65,67,67,69,80,84,41,32,99,97,117,115,101,115,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,116,111,32,102,97,105,108,32,119,105,116,104,111,117,116,32,97,110,121,32,102,117,114,116,104,101,114,32,112,114,111,99,101,115,115,105,110,103,46>>]},{p,[],[<<84,104,101,32,111,116,104,101,114,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,97,114,101,32,110,111,116,32,116,114,101,97,116,101,100,32,115,112,101,99,105,97,108,108,121,32,105,102,32,116,104,101,121,32,97,112,112,101,97,114,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,46,32,73,110,32,112,97,114,116,105,99,117,108,97,114,44,32,40,42,84,72,69,78,41,32,115,107,105,112,115,32,116,111,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,105,110,110,101,114,109,111,115,116,32,101,110,99,108,111,115,105,110,103,32,103,114,111,117,112,32,116,104,97,116,32,104,97,115,32,97,108,116,101,114,110,97,116,105,111,110,115,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32,116,104,105,115,32,105,115,32,119,105,116,104,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,46>>]},{p,[],[<<78,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,44,32,104,111,119,101,118,101,114,44,32,100,105,102,102,101,114,101,110,116,44,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,99,104,97,110,103,105,110,103,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,105,110,116,111,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,99,104,97,110,103,101,115,32,105,116,115,32,114,101,115,117,108,116,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,40,42,67,79,77,77,73,84,41,44,32,40,42,83,75,73,80,41,44,32,111,114,32,40,42,80,82,85,78,69,41,32,99,97,117,115,101,115,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,116,111,32,98,101,32,116,114,117,101,44,32,119,105,116,104,111,117,116,32,99,111,110,115,105,100,101,114,105,110,103,32,97,110,121,32,102,117,114,116,104,101,114,32,97,108,116,101,114,110,97,116,105,118,101,32,98,114,97,110,99,104,101,115,32,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,40,42,84,72,69,78,41,32,99,97,117,115,101,115,32,105,116,32,116,111,32,115,107,105,112,32,116,111,32,116,104,101,32,110,101,120,116,32,101,110,99,108,111,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,32,119,105,116,104,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,40,116,104,101,32,110,111,114,109,97,108,32,98,101,104,97,118,105,111,114,41,44,32,98,117,116,32,105,102,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,115,117,99,104,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,44,32,40,42,84,72,69,78,41,32,98,101,104,97,118,101,115,32,108,105,107,101,32,40,42,80,82,85,78,69,41,46>>]},{p,[],[{em,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115,32,105,110,32,83,117,98,114,111,117,116,105,110,101,115>>]}]},{p,[],[<<84,104,101,115,101,32,98,101,104,97,118,105,111,114,115,32,111,99,99,117,114,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,99,97,108,108,101,100,32,114,101,99,117,114,115,105,118,101,108,121,46,32,84,104,101,32,116,114,101,97,116,109,101,110,116,32,111,102,32,115,117,98,114,111,117,116,105,110,101,115,32,105,110,32,80,101,114,108,32,105,115,32,100,105,102,102,101,114,101,110,116,32,105,110,32,115,111,109,101,32,99,97,115,101,115,46>>]},{ul,[],[{li,[],[{p,[],[<<40,42,70,65,73,76,41,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,104,97,115,32,105,116,115,32,110,111,114,109,97,108,32,101,102,102,101,99,116,58,32,105,116,32,102,111,114,99,101,115,32,97,110,32,105,109,109,101,100,105,97,116,101,32,98,97,99,107,116,114,97,99,107,46>>]}]},{li,[],[{p,[],[<<40,42,65,67,67,69,80,84,41,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,117,115,101,115,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,97,116,99,104,32,116,111,32,115,117,99,99,101,101,100,32,119,105,116,104,111,117,116,32,97,110,121,32,102,117,114,116,104,101,114,32,112,114,111,99,101,115,115,105,110,103,46,32,77,97,116,99,104,105,110,103,32,116,104,101,110,32,99,111,110,116,105,110,117,101,115,32,97,102,116,101,114,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,46>>]}]},{li,[],[{p,[],[<<40,42,67,79,77,77,73,84,41,44,32,40,42,83,75,73,80,41,44,32,97,110,100,32,40,42,80,82,85,78,69,41,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,117,115,101,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46>>]}]},{li,[],[{p,[],[<<40,42,84,72,69,78,41,32,115,107,105,112,115,32,116,111,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,105,110,110,101,114,109,111,115,116,32,101,110,99,108,111,115,105,110,103,32,103,114,111,117,112,32,119,105,116,104,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,104,97,115,32,97,108,116,101,114,110,97,116,105,118,101,115,46,32,73,102,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,99,104,32,103,114,111,117,112,32,119,105,116,104,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,44,32,40,42,84,72,69,78,41,32,99,97,117,115,101,115,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46>>]}]}]}]},#{name => <<114,101>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,114,101,46,120,109,108],types => #{{compile_option,0} => {attribute,27,type,{compile_option,{type,27,union,[{atom,27,unicode},{atom,27,anchored},{atom,27,caseless},{atom,27,dollar_endonly},{atom,28,dotall},{atom,28,extended},{atom,28,firstline},{atom,28,multiline},{atom,29,no_auto_capture},{atom,29,dupnames},{atom,29,ungreedy},{type,30,tuple,[{atom,30,newline},{user_type,30,nl_spec,[]}]},{atom,31,bsr_anycrlf},{atom,31,bsr_unicode},{atom,32,no_start_optimize},{atom,32,ucp},{atom,32,never_utf}]},[]}},{mp,0} => {attribute,23,type,{mp,{type,23,tuple,[{atom,23,re_pattern},{var,23,'_'},{var,23,'_'},{var,23,'_'},{var,23,'_'}]},[]}},{nl_spec,0} => {attribute,25,type,{nl_spec,{type,25,union,[{atom,25,cr},{atom,25,crlf},{atom,25,lf},{atom,25,anycrlf},{atom,25,any}]},[]}}}},[{{function,version,0},[{file,[114,101,46,101,114,108]},{location,40}],[<<118,101,114,115,105,111,110,47,48>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,97,32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,80,67,82,69,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,115,121,115,116,101,109,32,116,104,97,116,32,119,97,115,32,117,115,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,47,79,84,80,32,99,111,109,112,105,108,97,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,56,49>>,signature => [{attribute,40,spec,{{version,0},[{type,40,'fun',[{type,40,product,[]},{type,40,binary,[]}]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,compile,1},[{file,[114,101,46,101,114,108]},{location,49}],[<<99,111,109,112,105,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<99,111,109,112,105,108,101,40,82,101,103,101,120,112,44,91,93,41>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,56,57>>,signature => [{attribute,49,spec,{{compile,1},[{type,49,bounded_fun,[{type,49,'fun',[{type,49,product,[{var,49,'Regexp'}]},{type,49,union,[{type,49,tuple,[{atom,49,ok},{var,49,'MP'}]},{type,49,tuple,[{atom,49,error},{var,49,'ErrSpec'}]}]}]},[{type,50,constraint,[{atom,50,is_subtype},[{var,50,'Regexp'},{type,50,iodata,[]}]]},{type,51,constraint,[{atom,51,is_subtype},[{var,51,'MP'},{user_type,51,mp,[]}]]},{type,52,constraint,[{atom,52,is_subtype},[{var,52,'ErrSpec'},{type,52,tuple,[{ann_type,52,[{var,52,'ErrString'},{type,52,string,[]}]},{ann_type,52,[{var,52,'Position'},{type,52,non_neg_integer,[]}]}]}]]}]]}]}}]}},{{function,compile,2},[{file,[114,101,46,101,114,108]},{location,57}],[<<99,111,109,112,105,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,105,108,101,115,32,97,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,119,105,116,104,32,116,104,101,32,115,121,110,116,97,120,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,44,32,105,110,116,111,32,97,110,32,105,110,116,101,114,110,97,108,32,102,111,114,109,97,116,32,116,111,32,98,101,32,117,115,101,100,32,108,97,116,101,114,32,97,115,32,97,32,112,97,114,97,109,101,116,101,114,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<46>>]},{p,[],[<<67,111,109,112,105,108,105,110,103,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,98,101,102,111,114,101,32,109,97,116,99,104,105,110,103,32,105,115,32,117,115,101,102,117,108,32,105,102,32,116,104,101,32,115,97,109,101,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,109,97,116,99,104,105,110,103,32,97,103,97,105,110,115,116,32,109,117,108,116,105,112,108,101,32,115,117,98,106,101,99,116,115,32,100,117,114,105,110,103,32,116,104,101,32,108,105,102,101,116,105,109,101,32,111,102,32,116,104,101,32,112,114,111,103,114,97,109,46,32,67,111,109,112,105,108,105,110,103,32,111,110,99,101,32,97,110,100,32,101,120,101,99,117,116,105,110,103,32,109,97,110,121,32,116,105,109,101,115,32,105,115,32,102,97,114,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,111,109,112,105,108,105,110,103,32,101,97,99,104,32,116,105,109,101,32,111,110,101,32,119,97,110,116,115,32,116,111,32,109,97,116,99,104,46>>]},{p,[],[<<87,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<44,32,111,116,104,101,114,119,105,115,101,32,97,115,32,97,110,121,32,118,97,108,105,100,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<46>>]},{a,[{id,<<99,111,109,112,105,108,101,95,111,112,116,105,111,110,115>>}],[]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<117,110,105,99,111,100,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<32,97,110,100,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,99,111,100,101,32,105,115,32,116,111,32,98,101,32,114,117,110,32,97,103,97,105,110,115,116,32,97,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<32,115,117,98,106,101,99,116,46,32,65,108,115,111,32,99,111,110,115,105,100,101,114,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,119,104,101,110,32,117,115,105,110,103,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},{dt,[],[{code,[],[<<97,110,99,104,111,114,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,97,116,116,101,114,110,32,105,115,32,102,111,114,99,101,100,32,116,111,32,98,101,32,34,97,110,99,104,111,114,101,100,34,44,32,116,104,97,116,32,105,115,44,32,105,116,32,105,115,32,99,111,110,115,116,114,97,105,110,101,100,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,97,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,110,32,116,104,101,32,115,116,114,105,110,103,32,116,104,97,116,32,105,115,32,115,101,97,114,99,104,101,100,32,40,116,104,101,32,34,115,117,98,106,101,99,116,32,115,116,114,105,110,103,34,41,46,32,84,104,105,115,32,101,102,102,101,99,116,32,99,97,110,32,97,108,115,111,32,98,101,32,97,99,104,105,101,118,101,100,32,98,121,32,97,112,112,114,111,112,114,105,97,116,101,32,99,111,110,115,116,114,117,99,116,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,105,116,115,101,108,102,46>>]}]},{dt,[],[{code,[],[<<99,97,115,101,108,101,115,115>>]}]},{dd,[],[{p,[],[<<76,101,116,116,101,114,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,32,98,111,116,104,32,117,112,112,101,114,99,97,115,101,32,97,110,100,32,108,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,115,46,32,73,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,105>>]},<<32,97,110,100,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,105,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,85,112,112,101,114,99,97,115,101,32,97,110,100,32,108,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,115,32,97,114,101,32,100,101,102,105,110,101,100,32,97,115,32,105,110,32,116,104,101,32,73,83,79,32,56,56,53,57,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,46>>]}]},{dt,[],[{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]}]},{dd,[],[{p,[],[<<65,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,87,105,116,104,111,117,116,32,116,104,105,115,32,111,112,116,105,111,110,44,32,97,32,100,111,108,108,97,114,32,97,108,115,111,32,109,97,116,99,104,101,115,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,40,98,117,116,32,110,111,116,32,98,101,102,111,114,101,32,97,110,121,32,111,116,104,101,114,32,110,101,119,108,105,110,101,115,41,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,105,103,110,111,114,101,100,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,46,32,84,104,101,114,101,32,105,115,32,110,111,32,101,113,117,105,118,97,108,101,110,116,32,111,112,116,105,111,110,32,105,110,32,80,101,114,108,44,32,97,110,100,32,105,116,32,99,97,110,110,111,116,32,98,101,32,115,101,116,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,46>>]}]},{dt,[],[{code,[],[<<100,111,116,97,108,108>>]}]},{dd,[],[{p,[],[<<65,32,100,111,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,44,32,105,110,99,108,117,100,105,110,103,32,116,104,111,115,101,32,105,110,100,105,99,97,116,105,110,103,32,110,101,119,108,105,110,101,46,32,87,105,116,104,111,117,116,32,105,116,44,32,97,32,100,111,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,119,104,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,105,115,32,97,116,32,97,32,110,101,119,108,105,110,101,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,115>>]},<<32,97,110,100,32,105,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,115,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,65,32,110,101,103,97,116,105,118,101,32,99,108,97,115,115,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<91,94,97,93>>]},<<44,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,44,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,116,104,101,32,115,101,116,116,105,110,103,32,111,102,32,116,104,105,115,32,111,112,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<101,120,116,101,110,100,101,100>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,101,116,44,32,109,111,115,116,32,119,104,105,116,101,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,97,114,101,32,116,111,116,97,108,108,121,32,105,103,110,111,114,101,100,32,101,120,99,101,112,116,32,119,104,101,110,32,101,115,99,97,112,101,100,32,111,114,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,72,111,119,101,118,101,114,44,32,119,104,105,116,101,32,115,112,97,99,101,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,119,105,116,104,105,110,32,115,101,113,117,101,110,99,101,115,32,115,117,99,104,32,97,115,32>>,{code,[],[<<40,63,62>>]},<<32,116,104,97,116,32,105,110,116,114,111,100,117,99,101,32,118,97,114,105,111,117,115,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,110,111,114,32,119,105,116,104,105,110,32,97,32,110,117,109,101,114,105,99,97,108,32,113,117,97,110,116,105,102,105,101,114,32,115,117,99,104,32,97,115,32>>,{code,[],[<<123,49,44,51,125>>]},<<46,32,72,111,119,101,118,101,114,44,32,105,103,110,111,114,97,98,108,101,32,119,104,105,116,101,32,115,112,97,99,101,32,105,115,32,112,101,114,109,105,116,116,101,100,32,98,101,116,119,101,101,110,32,97,110,32,105,116,101,109,32,97,110,100,32,97,32,102,111,108,108,111,119,105,110,103,32,113,117,97,110,116,105,102,105,101,114,32,97,110,100,32,98,101,116,119,101,101,110,32,97,32,113,117,97,110,116,105,102,105,101,114,32,97,110,100,32,97,32,102,111,108,108,111,119,105,110,103,32,43,32,116,104,97,116,32,105,110,100,105,99,97,116,101,115,32,112,111,115,115,101,115,115,105,118,101,110,101,115,115,46>>]},{p,[],[<<87,104,105,116,101,32,115,112,97,99,101,32,100,105,100,32,110,111,116,32,117,115,101,100,32,116,111,32,105,110,99,108,117,100,101,32,116,104,101,32,86,84,32,99,104,97,114,97,99,116,101,114,32,40,99,111,100,101,32,49,49,41,44,32,98,101,99,97,117,115,101,32,80,101,114,108,32,100,105,100,32,110,111,116,32,116,114,101,97,116,32,116,104,105,115,32,99,104,97,114,97,99,116,101,114,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,46,32,72,111,119,101,118,101,114,44,32,80,101,114,108,32,99,104,97,110,103,101,100,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,44,32,115,111,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,44,32,97,110,100,32,86,84,32,105,115,32,110,111,119,32,116,114,101,97,116,101,100,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,46>>]},{p,[],[<<84,104,105,115,32,97,108,115,111,32,99,97,117,115,101,115,32,99,104,97,114,97,99,116,101,114,115,32,98,101,116,119,101,101,110,32,97,110,32,117,110,101,115,99,97,112,101,100,32,35,32,111,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,97,110,100,32,116,104,101,32,110,101,120,116,32,110,101,119,108,105,110,101,44,32,105,110,99,108,117,115,105,118,101,44,32,116,111,32,98,101,32,105,103,110,111,114,101,100,46,32,84,104,105,115,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,39,115,32>>,{code,[],[<<47,120>>]},<<32,111,112,116,105,111,110,44,32,97,110,100,32,105,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,120,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46>>]},{p,[],[<<87,105,116,104,32,116,104,105,115,32,111,112,116,105,111,110,44,32,99,111,109,109,101,110,116,115,32,105,110,115,105,100,101,32,99,111,109,112,108,105,99,97,116,101,100,32,112,97,116,116,101,114,110,115,32,99,97,110,32,98,101,32,105,110,99,108,117,100,101,100,46,32,72,111,119,101,118,101,114,44,32,110,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,97,112,112,108,105,101,115,32,111,110,108,121,32,116,111,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114,115,46,32,87,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,99,97,110,32,110,101,118,101,114,32,97,112,112,101,97,114,32,119,105,116,104,105,110,32,115,112,101,99,105,97,108,32,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,115,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,102,111,114,32,101,120,97,109,112,108,101,32,119,105,116,104,105,110,32,115,101,113,117,101,110,99,101,32>>,{code,[],[<<40,63,40>>]},<<32,116,104,97,116,32,105,110,116,114,111,100,117,99,101,115,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,46>>]}]},{dt,[],[{code,[],[<<102,105,114,115,116,108,105,110,101>>]}]},{dd,[],[{p,[],[<<65,110,32,117,110,97,110,99,104,111,114,101,100,32,112,97,116,116,101,114,110,32,105,115,32,114,101,113,117,105,114,101,100,32,116,111,32,109,97,116,99,104,32,98,101,102,111,114,101,32,111,114,32,97,116,32,116,104,101,32,102,105,114,115,116,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,108,116,104,111,117,103,104,32,116,104,101,32,109,97,116,99,104,101,100,32,116,101,120,116,32,99,97,110,32,99,111,110,116,105,110,117,101,32,111,118,101,114,32,116,104,101,32,110,101,119,108,105,110,101,46>>]}]},{dt,[],[{code,[],[<<109,117,108,116,105,108,105,110,101>>]}]},{dd,[],[{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,80,67,82,69,32,116,114,101,97,116,115,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,97,115,32,99,111,110,115,105,115,116,105,110,103,32,111,102,32,97,32,115,105,110,103,108,101,32,108,105,110,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,101,118,101,110,32,105,102,32,105,116,32,99,111,110,116,97,105,110,115,32,110,101,119,108,105,110,101,115,41,46,32,84,104,101,32,34,115,116,97,114,116,32,111,102,32,108,105,110,101,34,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,40>>,{code,[],[<<94>>]},<<41,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,119,104,105,108,101,32,116,104,101,32,34,101,110,100,32,111,102,32,108,105,110,101,34,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,40>>,{code,[],[<<36>>]},<<41,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,111,114,32,98,101,102,111,114,101,32,97,32,116,101,114,109,105,110,97,116,105,110,103,32,110,101,119,108,105,110,101,32,40,117,110,108,101,115,115,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,41,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,105,110,32,80,101,114,108,46>>]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,34,115,116,97,114,116,32,111,102,32,108,105,110,101,34,32,97,110,100,32,34,101,110,100,32,111,102,32,108,105,110,101,34,32,99,111,110,115,116,114,117,99,116,115,32,109,97,116,99,104,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,105,110,103,32,111,114,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,105,110,116,101,114,110,97,108,32,110,101,119,108,105,110,101,115,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,114,101,115,112,101,99,116,105,118,101,108,121,44,32,97,115,32,119,101,108,108,32,97,115,32,97,116,32,116,104,101,32,118,101,114,121,32,115,116,97,114,116,32,97,110,100,32,101,110,100,46,32,84,104,105,115,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,109>>]},<<32,97,110,100,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,109,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,73,102,32,116,104,101,114,101,32,97,114,101,32,110,111,32,110,101,119,108,105,110,101,115,32,105,110,32,97,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,111,114,32,110,111,32,111,99,99,117,114,114,101,110,99,101,115,32,111,102,32>>,{code,[],[<<94>>]},<<32,111,114,32>>,{code,[],[<<36>>]},<<32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,115,101,116,116,105,110,103,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,104,97,115,32,110,111,32,101,102,102,101,99,116,46>>]}]},{dt,[],[{code,[],[<<110,111,95,97,117,116,111,95,99,97,112,116,117,114,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,104,101,32,117,115,101,32,111,102,32,110,117,109,98,101,114,101,100,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,65,110,121,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32>>,{code,[],[<<63>>]},<<32,98,101,104,97,118,101,115,32,97,115,32,105,102,32,105,116,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32>>,{code,[],[<<63,58>>]},<<46,32,78,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,115,116,105,108,108,32,98,101,32,117,115,101,100,32,102,111,114,32,99,97,112,116,117,114,105,110,103,32,40,97,110,100,32,116,104,101,121,32,97,99,113,117,105,114,101,32,110,117,109,98,101,114,115,32,105,110,32,116,104,101,32,117,115,117,97,108,32,119,97,121,41,46,32,84,104,101,114,101,32,105,115,32,110,111,32,101,113,117,105,118,97,108,101,110,116,32,111,112,116,105,111,110,32,105,110,32,80,101,114,108,46>>]}]},{dt,[],[{code,[],[<<100,117,112,110,97,109,101,115>>]}]},{dd,[],[{p,[],[<<78,97,109,101,115,32,117,115,101,100,32,116,111,32,105,100,101,110,116,105,102,121,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,110,101,101,100,32,110,111,116,32,98,101,32,117,110,105,113,117,101,46,32,84,104,105,115,32,99,97,110,32,98,101,32,104,101,108,112,102,117,108,32,102,111,114,32,99,101,114,116,97,105,110,32,116,121,112,101,115,32,111,102,32,112,97,116,116,101,114,110,32,119,104,101,110,32,105,116,32,105,115,32,107,110,111,119,110,32,116,104,97,116,32,111,110,108,121,32,111,110,101,32,105,110,115,116,97,110,99,101,32,111,102,32,116,104,101,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,101,118,101,114,32,98,101,32,109,97,116,99,104,101,100,46,32,77,111,114,101,32,100,101,116,97,105,108,115,32,111,102,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,98,101,108,111,119,46>>]}]},{dt,[],[{code,[],[<<117,110,103,114,101,101,100,121>>]}]},{dd,[],[{p,[],[<<73,110,118,101,114,116,115,32,116,104,101,32,34,103,114,101,101,100,105,110,101,115,115,34,32,111,102,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,115,32,115,111,32,116,104,97,116,32,116,104,101,121,32,97,114,101,32,110,111,116,32,103,114,101,101,100,121,32,98,121,32,100,101,102,97,117,108,116,44,32,98,117,116,32,98,101,99,111,109,101,32,103,114,101,101,100,121,32,105,102,32,102,111,108,108,111,119,101,100,32,98,121,32,34,63,34,46,32,73,116,32,105,115,32,110,111,116,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,32,80,101,114,108,46,32,73,116,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,97,32>>,{code,[],[<<40,63,85,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,32,119,105,116,104,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]}]},{dd,[],[{p,[],[<<79,118,101,114,114,105,100,101,115,32,116,104,101,32,100,101,102,97,117,108,116,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,97,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,119,104,105,99,104,32,105,115,32,76,70,32,40,65,83,67,73,73,32,49,48,41,32,105,110,32,69,114,108,97,110,103,46>>]},{dl,[],[{dt,[],[{code,[],[<<99,114>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32>>,{code,[],[<<99,114>>]},<<32,40,65,83,67,73,73,32,49,51,41,46>>]}]},{dt,[],[{code,[],[<<108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,76,70,32,40,65,83,67,73,73,32,49,48,41,44,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<99,114,108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,67,82,76,70,32,40,65,83,67,73,73,32,49,51,32,102,111,108,108,111,119,101,100,32,98,121,32,65,83,67,73,73,32,49,48,41,32,115,101,113,117,101,110,99,101,46>>]}]},{dt,[],[{code,[],[<<97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,112,114,101,99,101,100,105,110,103,32,115,101,113,117,101,110,99,101,115,32,105,115,32,116,111,32,98,101,32,114,101,99,111,103,110,105,122,101,100,46>>]}]},{dt,[],[{code,[],[<<97,110,121>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,115,32,97,98,111,118,101,44,32,97,110,100,32,116,104,101,32,85,110,105,99,111,100,101,32,115,101,113,117,101,110,99,101,115,32,86,84,32,40,118,101,114,116,105,99,97,108,32,116,97,98,44,32,85,43,48,48,48,66,41,44,32,70,70,32,40,102,111,114,109,102,101,101,100,44,32,85,43,48,48,48,67,41,44,32,78,69,76,32,40,110,101,120,116,32,108,105,110,101,44,32,85,43,48,48,56,53,41,44,32,76,83,32,40,108,105,110,101,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,56,41,44,32,97,110,100,32,80,83,32,40,112,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,57,41,46>>]}]}]}]},{dt,[],[{code,[],[<<98,115,114,95,97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,116,104,101,32,67,82,44,32,76,70,44,32,111,114,32,67,82,76,70,32,115,101,113,117,101,110,99,101,115,44,32,110,111,116,32,116,104,101,32,85,110,105,99,111,100,101,45,115,112,101,99,105,102,105,99,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},{dt,[],[{code,[],[<<98,115,114,95,117,110,105,99,111,100,101>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,97,108,108,32,116,104,101,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,99,108,117,100,105,110,103,32,67,82,76,70,44,32,97,110,100,32,115,111,32,111,110,44,32,116,104,101,32,100,101,102,97,117,108,116,41,46>>]}]},{dt,[],[{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,99,97,110,32,109,97,108,102,117,110,99,116,105,111,110,32,105,102,32,34,83,112,101,99,105,97,108,32,115,116,97,114,116,45,111,102,45,112,97,116,116,101,114,110,32,105,116,101,109,115,34,32,97,114,101,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,65,32,116,121,112,105,99,97,108,32,101,120,97,109,112,108,101,32,119,111,117,108,100,32,98,101,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,34,68,69,70,65,66,67,34,32,97,103,97,105,110,115,116,32,34,40,42,67,79,77,77,73,84,41,65,66,67,34,44,32,119,104,101,114,101,32,116,104,101,32,115,116,97,114,116,32,111,112,116,105,109,105,122,97,116,105,111,110,32,111,102,32,80,67,82,69,32,119,111,117,108,100,32,115,107,105,112,32,116,104,101,32,115,117,98,106,101,99,116,32,117,112,32,116,111,32,34,65,34,32,97,110,100,32,110,101,118,101,114,32,114,101,97,108,105,122,101,32,116,104,97,116,32,116,104,101,32,40,42,67,79,77,77,73,84,41,32,105,110,115,116,114,117,99,116,105,111,110,32,105,115,32,116,111,32,104,97,118,101,32,109,97,100,101,32,116,104,101,32,109,97,116,99,104,105,110,103,32,102,97,105,108,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,111,110,108,121,32,114,101,108,101,118,97,110,116,32,105,102,32,121,111,117,32,117,115,101,32,34,115,116,97,114,116,45,111,102,45,112,97,116,116,101,114,110,32,105,116,101,109,115,34,44,32,97,115,32,100,105,115,99,117,115,115,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,101,103,101,120,112,95,115,121,110,116,97,120,95,100,101,116,97,105,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,67,82,69,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,32,68,101,116,97,105,108,115>>]},<<46>>]}]},{dt,[],[{code,[],[<<117,99,112>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,116,111,32,98,101,32,117,115,101,100,32,119,104,101,110,32,114,101,115,111,108,118,105,110,103,32,92,66,44,32,92,98,44,32,92,68,44,32,92,100,44,32,92,83,44,32,92,115,44,32,92,87,32,97,110,100,32,92,119,46,32,87,105,116,104,111,117,116,32,116,104,105,115,32,102,108,97,103,44,32,111,110,108,121,32,73,83,79,32,76,97,116,105,110,45,49,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,117,115,101,100,46,32,85,115,105,110,103,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,104,117,114,116,115,32,112,101,114,102,111,114,109,97,110,99,101,44,32,98,117,116,32,105,115,32,115,101,109,97,110,116,105,99,97,108,108,121,32,99,111,114,114,101,99,116,32,119,104,101,110,32,119,111,114,107,105,110,103,32,119,105,116,104,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,98,101,121,111,110,100,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,114,97,110,103,101,46>>]}]},{dt,[],[{code,[],[<<110,101,118,101,114,95,117,116,102>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,116,104,101,32,40,42,85,84,70,41,32,97,110,100,47,111,114,32,40,42,85,84,70,56,41,32,34,115,116,97,114,116,45,111,102,45,112,97,116,116,101,114,110,32,105,116,101,109,115,34,32,97,114,101,32,102,111,114,98,105,100,100,101,110,46,32,84,104,105,115,32,102,108,97,103,32,99,97,110,110,111,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<46,32,85,115,101,102,117,108,32,105,102,32,73,83,79,32,76,97,116,105,110,45,49,32,112,97,116,116,101,114,110,115,32,102,114,111,109,32,97,110,32,101,120,116,101,114,110,97,108,32,115,111,117,114,99,101,32,97,114,101,32,116,111,32,98,101,32,99,111,109,112,105,108,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,57,55>>,signature => [{attribute,57,spec,{{compile,2},[{type,57,bounded_fun,[{type,57,'fun',[{type,57,product,[{var,57,'Regexp'},{var,57,'Options'}]},{type,57,union,[{type,57,tuple,[{atom,57,ok},{var,57,'MP'}]},{type,57,tuple,[{atom,57,error},{var,57,'ErrSpec'}]}]}]},[{type,58,constraint,[{atom,58,is_subtype},[{var,58,'Regexp'},{type,58,union,[{type,58,iodata,[]},{remote_type,58,[{atom,58,unicode},{atom,58,charlist},[]]}]}]]},{type,59,constraint,[{atom,59,is_subtype},[{var,59,'Options'},{type,59,list,[{var,59,'Option'}]}]]},{type,60,constraint,[{atom,60,is_subtype},[{var,60,'Option'},{user_type,60,compile_option,[]}]]},{type,61,constraint,[{atom,61,is_subtype},[{var,61,'MP'},{user_type,61,mp,[]}]]},{type,62,constraint,[{atom,62,is_subtype},[{var,62,'ErrSpec'},{type,62,tuple,[{ann_type,62,[{var,62,'ErrString'},{type,62,string,[]}]},{ann_type,62,[{var,62,'Position'},{type,62,non_neg_integer,[]}]}]}]]}]]}]}}]}},{{function,inspect,2},[{file,[114,101,46,101,114,108]},{location,143}],[<<105,110,115,112,101,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,97,107,101,115,32,97,32,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,110,100,32,97,110,32,105,116,101,109,44,32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,114,101,108,101,118,97,110,116,32,100,97,116,97,32,102,114,111,109,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,84,104,101,32,111,110,108,121,32,115,117,112,112,111,114,116,101,100,32,105,116,101,109,32,105,115,32>>,{code,[],[<<110,97,109,101,108,105,115,116>>]},<<44,32,119,104,105,99,104,32,114,101,116,117,114,110,115,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,110,97,109,101,108,105,115,116,44,32,91,98,105,110,97,114,121,40,41,93,125>>]},<<44,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,40,117,110,105,113,117,101,41,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<49,62,32,123,111,107,44,77,80,125,32,61,32,114,101,58,99,111,109,112,105,108,101,40,34,40,63,60,65,62,65,41,124,40,63,60,66,62,66,41,124,40,63,60,67,62,67,41,34,41,46,10,123,111,107,44,123,114,101,95,112,97,116,116,101,114,110,44,51,44,48,44,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,60,54,57,44,56,50,44,54,55,44,56,48,44,49,49,57,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,49,44,48,44,48,44,48,44,50,53,53,44,50,53,53,44,50,53,53,44,50,53,53,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,53,53,44,50,53,53,44,46,46,46,62,62,125,125,10,50,62,32,114,101,58,105,110,115,112,101,99,116,40,77,80,44,110,97,109,101,108,105,115,116,41,46,10,123,110,97,109,101,108,105,115,116,44,91,60,60,34,65,34,62,62,44,60,60,34,66,34,62,62,44,60,60,34,67,34,62,62,93,125,10,51,62,32,123,111,107,44,77,80,68,125,32,61,32,114,101,58,99,111,109,112,105,108,101,40,34,40,63,60,67,62,65,41,124,40,63,60,66,62,66,41,124,40,63,60,67,62,67,41,34,44,91,100,117,112,110,97,109,101,115,93,41,46,10,123,111,107,44,123,114,101,95,112,97,116,116,101,114,110,44,51,44,48,44,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,60,54,57,44,56,50,44,54,55,44,56,48,44,49,49,57,44,48,44,48,44,48,44,48,44,48,44,56,44,48,44,49,44,48,44,48,44,48,44,50,53,53,44,50,53,53,44,50,53,53,44,50,53,53,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,53,53,44,50,53,53,44,46,46,46,62,62,125,125,10,52,62,32,114,101,58,105,110,115,112,101,99,116,40,77,80,68,44,110,97,109,101,108,105,115,116,41,46,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,10,123,110,97,109,101,108,105,115,116,44,91,60,60,34,66,34,62,62,44,60,60,34,67,34,62,62,93,125>>]}]},{p,[],[<<78,111,116,105,99,101,32,105,110,32,116,104,101,32,115,101,99,111,110,100,32,101,120,97,109,112,108,101,32,116,104,97,116,32,116,104,101,32,100,117,112,108,105,99,97,116,101,32,110,97,109,101,32,111,110,108,121,32,111,99,99,117,114,115,32,111,110,99,101,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,44,32,97,110,100,32,116,104,97,116,32,116,104,101,32,108,105,115,116,32,105,115,32,105,110,32,97,108,112,104,97,98,101,116,105,99,97,108,32,111,114,100,101,114,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,114,101,32,116,104,101,32,110,97,109,101,115,32,97,114,101,32,112,111,115,105,116,105,111,110,101,100,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,110,97,109,101,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,111,114,100,101,114,32,111,102,32,99,97,112,116,117,114,101,100,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,105,102,32>>,{code,[],[<<123,99,97,112,116,117,114,101,44,32,97,108,108,95,110,97,109,101,115,125>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,110,32,111,112,116,105,111,110,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<46,32,89,111,117,32,99,97,110,32,116,104,101,114,101,102,111,114,101,32,99,114,101,97,116,101,32,97,32,110,97,109,101,45,116,111,45,118,97,108,117,101,32,109,97,112,112,105,110,103,32,102,114,111,109,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,108,105,107,101,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<49,62,32,123,111,107,44,77,80,125,32,61,32,114,101,58,99,111,109,112,105,108,101,40,34,40,63,60,65,62,65,41,124,40,63,60,66,62,66,41,124,40,63,60,67,62,67,41,34,41,46,10,123,111,107,44,123,114,101,95,112,97,116,116,101,114,110,44,51,44,48,44,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,60,54,57,44,56,50,44,54,55,44,56,48,44,49,49,57,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,49,44,48,44,48,44,48,44,50,53,53,44,50,53,53,44,50,53,53,44,50,53,53,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,53,53,44,50,53,53,44,46,46,46,62,62,125,125,10,50,62,32,123,110,97,109,101,108,105,115,116,44,32,78,125,32,61,32,114,101,58,105,110,115,112,101,99,116,40,77,80,44,110,97,109,101,108,105,115,116,41,46,10,123,110,97,109,101,108,105,115,116,44,91,60,60,34,65,34,62,62,44,60,60,34,66,34,62,62,44,60,60,34,67,34,62,62,93,125,10,51,62,32,123,109,97,116,99,104,44,76,125,32,61,32,114,101,58,114,117,110,40,34,65,65,34,44,77,80,44,91,123,99,97,112,116,117,114,101,44,97,108,108,95,110,97,109,101,115,44,98,105,110,97,114,121,125,93,41,46,10,123,109,97,116,99,104,44,91,60,60,34,65,34,62,62,44,60,60,62,62,44,60,60,62,62,93,125,10,52,62,32,78,97,109,101,77,97,112,32,61,32,108,105,115,116,115,58,122,105,112,40,78,44,76,41,46,10,91,123,60,60,34,65,34,62,62,44,60,60,34,65,34,62,62,125,44,123,60,60,34,66,34,62,62,44,60,60,62,62,125,44,123,60,60,34,67,34,62,62,44,60,60,62,62,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,51,48,54>>,signature => [{attribute,143,spec,{{inspect,2},[{type,143,bounded_fun,[{type,143,'fun',[{type,143,product,[{var,143,'MP'},{var,143,'Item'}]},{type,143,tuple,[{atom,143,namelist},{type,143,list,[{type,143,binary,[]}]}]}]},[{type,144,constraint,[{atom,144,is_subtype},[{var,144,'MP'},{user_type,144,mp,[]}]]},{type,145,constraint,[{atom,145,is_subtype},[{var,145,'Item'},{atom,145,namelist}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,replace,3},[{file,[114,101,46,101,114,108]},{location,353}],[<<114,101,112,108,97,99,101,47,51>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<114,101,112,108,97,99,101,40,83,117,98,106,101,99,116,44,32,82,69,44,32,82,101,112,108,97,99,101,109,101,110,116,44,32,91,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,51,53,48>>,signature => [{attribute,353,spec,{{replace,3},[{type,353,bounded_fun,[{type,353,'fun',[{type,353,product,[{var,353,'Subject'},{var,353,'RE'},{var,353,'Replacement'}]},{type,353,union,[{type,353,iodata,[]},{remote_type,353,[{atom,353,unicode},{atom,353,charlist},[]]}]}]},[{type,354,constraint,[{atom,354,is_subtype},[{var,354,'Subject'},{type,354,union,[{type,354,iodata,[]},{remote_type,354,[{atom,354,unicode},{atom,354,charlist},[]]}]}]]},{type,355,constraint,[{atom,355,is_subtype},[{var,355,'RE'},{type,355,union,[{user_type,355,mp,[]},{type,355,iodata,[]}]}]]},{type,356,constraint,[{atom,356,is_subtype},[{var,356,'Replacement'},{type,356,union,[{type,356,iodata,[]},{remote_type,356,[{atom,356,unicode},{atom,356,charlist},[]]}]}]]}]]}]}}]}},{{function,replace,4},[{file,[114,101,46,101,114,108]},{location,366}],[<<114,101,112,108,97,99,101,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,112,108,97,99,101,115,32,116,104,101,32,109,97,116,99,104,101,100,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32>>,{code,[],[<<82,101,112,108,97,99,101,109,101,110,116>>]},<<46>>]},{p,[],[<<84,104,101,32,112,101,114,109,105,115,115,105,98,108,101,32,111,112,116,105,111,110,115,32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,102,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,111,112,116,105,111,110>>,{code,[],[<<32,99,97,112,116,117,114,101>>]},<<32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,46,32,73,110,115,116,101,97,100,32,97,32>>,{code,[],[<<123,114,101,116,117,114,110,44,32,82,101,116,117,114,110,84,121,112,101,125>>]},<<32,105,115,32,112,114,101,115,101,110,116,46,32,84,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<44,32,99,111,110,115,116,114,117,99,116,101,100,32,105,110,32,97,32,119,97,121,32,116,111,32,109,105,110,105,109,105,122,101,32,99,111,112,121,105,110,103,46,32,84,104,101,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<32,114,101,115,117,108,116,32,99,97,110,32,98,101,32,117,115,101,100,32,100,105,114,101,99,116,108,121,32,105,110,32,109,97,110,121,32,73,47,79,32,111,112,101,114,97,116,105,111,110,115,46,32,73,102,32,97,32,102,108,97,116,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,105,115,32,100,101,115,105,114,101,100,44,32,115,112,101,99,105,102,121,32>>,{code,[],[<<123,114,101,116,117,114,110,44,32,108,105,115,116,125>>]},<<46,32,73,102,32,97,32,98,105,110,97,114,121,32,105,115,32,100,101,115,105,114,101,100,44,32,115,112,101,99,105,102,121,32>>,{code,[],[<<123,114,101,116,117,114,110,44,32,98,105,110,97,114,121,125>>]},<<46>>]},{p,[],[<<65,115,32,105,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<114,117,110,47,51>>]},<<44,32,97,110,32>>,{code,[],[<<109,112,40,41>>]},<<32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,114,101,113,117,105,114,101,115,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,116,111,32,98,101,32,97,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<46,32,73,102,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,105,109,112,108,105,99,105,116,108,121,32,97,110,100,32,116,104,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,98,111,116,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,110,100,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,97,114,101,32,116,111,32,115,112,101,99,105,102,105,101,100,32,97,115,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<115,46>>]},{p,[],[<<84,104,101,32,114,101,112,108,97,99,101,109,101,110,116,32,115,116,114,105,110,103,32,99,97,110,32,99,111,110,116,97,105,110,32,116,104,101,32,115,112,101,99,105,97,108,32,99,104,97,114,97,99,116,101,114,32>>,{code,[],[<<38>>]},<<44,32,119,104,105,99,104,32,105,110,115,101,114,116,115,32,116,104,101,32,119,104,111,108,101,32,109,97,116,99,104,105,110,103,32,101,120,112,114,101,115,115,105,111,110,32,105,110,32,116,104,101,32,114,101,115,117,108,116,44,32,97,110,100,32,116,104,101,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,32>>,{code,[],[<<92>>]},<<78,32,40,119,104,101,114,101,32,78,32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,62,32,48,41,44,32>>,{code,[],[<<92,103>>]},<<78,44,32,111,114,32>>,{code,[],[<<92,103,123>>]},<<78>>,{code,[],[<<125>>]},<<44,32,114,101,115,117,108,116,105,110,103,32,105,110,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,110,117,109,98,101,114,32,78,44,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46,32,73,102,32,110,111,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,119,105,116,104,32,116,104,97,116,32,110,117,109,98,101,114,32,105,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,110,111,116,104,105,110,103,32,105,115,32,105,110,115,101,114,116,101,100,46>>]},{p,[],[<<84,111,32,105,110,115,101,114,116,32,97,110,32,38,32,111,114,32,97,32,92,32,105,110,32,116,104,101,32,114,101,115,117,108,116,44,32,112,114,101,99,101,100,101,32,105,116,32,119,105,116,104,32,97,32,92,46,32,78,111,116,105,99,101,32,116,104,97,116,32,69,114,108,97,110,103,32,97,108,114,101,97,100,121,32,103,105,118,101,115,32,97,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,116,111,32,92,32,105,110,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,115,44,32,115,111,32,97,32,115,105,110,103,108,101,32,92,32,109,117,115,116,32,98,101,32,119,114,105,116,116,101,110,32,97,115,32>>,{code,[],[<<34,92,92,34>>]},<<32,97,110,100,32,116,104,101,114,101,102,111,114,101,32,97,32,100,111,117,98,108,101,32,92,32,97,115,32>>,{code,[],[<<34,92,92,92,92,34>>]},<<46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[],[<<114,101,58,114,101,112,108,97,99,101,40,34,97,98,99,100,34,44,34,99,34,44,34,91,38,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<34,97,98,91,99,93,100,34>>]}]},{p,[],[<<119,104,105,108,101>>]},{pre,[],[{code,[],[<<114,101,58,114,101,112,108,97,99,101,40,34,97,98,99,100,34,44,34,99,34,44,34,91,92,92,38,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<34,97,98,91,38,93,100,34>>]}]},{p,[],[<<65,115,32,119,105,116,104,32>>,{code,[],[<<114,117,110,47,51>>]},<<44,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,115,32,114,97,105,115,101,32,116,104,101,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,46,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,103,101,116,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,101,114,114,111,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,51,54,48>>,signature => [{attribute,366,spec,{{replace,4},[{type,366,bounded_fun,[{type,366,'fun',[{type,366,product,[{var,366,'Subject'},{var,366,'RE'},{var,366,'Replacement'},{var,366,'Options'}]},{type,366,union,[{type,366,iodata,[]},{remote_type,366,[{atom,366,unicode},{atom,366,charlist},[]]}]}]},[{type,367,constraint,[{atom,367,is_subtype},[{var,367,'Subject'},{type,367,union,[{type,367,iodata,[]},{remote_type,367,[{atom,367,unicode},{atom,367,charlist},[]]}]}]]},{type,368,constraint,[{atom,368,is_subtype},[{var,368,'RE'},{type,368,union,[{user_type,368,mp,[]},{type,368,iodata,[]},{remote_type,368,[{atom,368,unicode},{atom,368,charlist},[]]}]}]]},{type,369,constraint,[{atom,369,is_subtype},[{var,369,'Replacement'},{type,369,union,[{type,369,iodata,[]},{remote_type,369,[{atom,369,unicode},{atom,369,charlist},[]]}]}]]},{type,370,constraint,[{atom,370,is_subtype},[{var,370,'Options'},{type,370,list,[{var,370,'Option'}]}]]},{type,371,constraint,[{atom,371,is_subtype},[{var,371,'Option'},{type,371,union,[{atom,371,anchored},{atom,371,global},{atom,371,notbol},{atom,371,noteol},{atom,371,notempty},{atom,372,notempty_atstart},{type,373,tuple,[{atom,373,offset},{type,373,non_neg_integer,[]}]},{type,373,tuple,[{atom,373,newline},{var,373,'NLSpec'}]},{atom,373,bsr_anycrlf},{type,374,tuple,[{atom,374,match_limit},{type,374,non_neg_integer,[]}]},{type,375,tuple,[{atom,375,match_limit_recursion},{type,375,non_neg_integer,[]}]},{atom,376,bsr_unicode},{type,376,tuple,[{atom,376,return},{var,376,'ReturnType'}]},{var,376,'CompileOpt'}]}]]},{type,377,constraint,[{atom,377,is_subtype},[{var,377,'ReturnType'},{type,377,union,[{atom,377,iodata},{atom,377,list},{atom,377,binary}]}]]},{type,378,constraint,[{atom,378,is_subtype},[{var,378,'CompileOpt'},{user_type,378,compile_option,[]}]]},{type,379,constraint,[{atom,379,is_subtype},[{var,379,'NLSpec'},{type,379,union,[{atom,379,cr},{atom,379,crlf},{atom,379,lf},{atom,379,anycrlf},{atom,379,any}]}]]}]]}]}}]}},{{function,run,2},[{file,[114,101,46,101,114,108]},{location,67}],[<<114,117,110,47,50>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<114,117,110,40,83,117,98,106,101,99,116,44,82,69,44,91,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,52,49,48>>,signature => [{attribute,67,spec,{{run,2},[{type,67,bounded_fun,[{type,67,'fun',[{type,67,product,[{var,67,'Subject'},{var,67,'RE'}]},{type,67,union,[{type,67,tuple,[{atom,67,match},{var,67,'Captured'}]},{atom,67,nomatch}]}]},[{type,68,constraint,[{atom,68,is_subtype},[{var,68,'Subject'},{type,68,union,[{type,68,iodata,[]},{remote_type,68,[{atom,68,unicode},{atom,68,charlist},[]]}]}]]},{type,69,constraint,[{atom,69,is_subtype},[{var,69,'RE'},{type,69,union,[{user_type,69,mp,[]},{type,69,iodata,[]}]}]]},{type,70,constraint,[{atom,70,is_subtype},[{var,70,'Captured'},{type,70,list,[{var,70,'CaptureData'}]}]]},{type,71,constraint,[{atom,71,is_subtype},[{var,71,'CaptureData'},{type,71,tuple,[{type,71,integer,[]},{type,71,integer,[]}]}]]}]]}]}}]}},{{function,run,3},[{file,[114,101,46,101,114,108]},{location,76}],[<<114,117,110,47,51>>],#{<<101,110>> => [{p,[],[<<69,120,101,99,117,116,101,115,32,97,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,105,110,103,44,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<109,97,116,99,104,47,123,109,97,116,99,104,44,32,67,97,112,116,117,114,101,100,125>>]},<<32,111,114,32>>,{code,[],[<<110,111,109,97,116,99,104>>]},<<46,32,84,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,101,105,116,104,101,114,32,97,115,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,111,109,112,105,108,101,100,32,40,97,115,32,98,121,32>>,{code,[],[<<99,111,109,112,105,108,101,47,50>>]},<<41,32,97,110,100,32,101,120,101,99,117,116,101,100,44,32,111,114,32,97,115,32,97,32,112,114,101,99,111,109,112,105,108,101,100,32>>,{code,[],[<<109,112,40,41>>]},<<32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,105,116,32,105,115,32,101,120,101,99,117,116,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,115,117,98,106,101,99,116,32,100,105,114,101,99,116,108,121,46>>]},{p,[],[<<87,104,101,110,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,105,110,118,111,108,118,101,100,44,32,101,120,99,101,112,116,105,111,110,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,115,32,116,104,114,111,119,110,32,105,102,32,97,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46,32,67,97,108,108,32>>,{code,[],[<<99,111,109,112,105,108,101,47,50>>]},<<32,116,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,108,111,99,97,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,105,108,101,100,44,32,116,104,101,32,111,112,116,105,111,110,32,108,105,115,116,32,99,97,110,32,111,110,108,121,32,99,111,110,116,97,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{code,[],[<<97,110,99,104,111,114,101,100>>]}]},{li,[],[{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,125,47,123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,44,32,84,121,112,101,125>>]}]},{li,[],[{code,[],[<<103,108,111,98,97,108>>]}]},{li,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{li,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{li,[],[{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]}]},{li,[],[{code,[],[<<110,111,116,98,111,108>>]}]},{li,[],[{code,[],[<<110,111,116,101,109,112,116,121>>]}]},{li,[],[{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]}]},{li,[],[{code,[],[<<110,111,116,101,111,108>>]}]},{li,[],[{code,[],[<<123,111,102,102,115,101,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{li,[],[{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]}]}]},{p,[],[<<79,116,104,101,114,119,105,115,101,32,97,108,108,32,111,112,116,105,111,110,115,32,118,97,108,105,100,32,102,111,114,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<99,111,109,112,105,108,101,47,50>>]},<<32,97,114,101,32,97,108,115,111,32,97,108,108,111,119,101,100,46,32,79,112,116,105,111,110,115,32,97,108,108,111,119,101,100,32,98,111,116,104,32,102,111,114,32,99,111,109,112,105,108,97,116,105,111,110,32,97,110,100,32,101,120,101,99,117,116,105,111,110,32,111,102,32,97,32,109,97,116,99,104,44,32,110,97,109,101,108,121,32>>,{code,[],[<<97,110,99,104,111,114,101,100>>]},<<32,97,110,100,32>>,{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]},<<44,32,97,102,102,101,99,116,32,98,111,116,104,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,97,110,100,32,101,120,101,99,117,116,105,111,110,32,105,102,32,112,114,101,115,101,110,116,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,97,32,110,111,110,45,112,114,101,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,105,115,32,116,111,32,98,101,32,112,114,111,118,105,100,101,100,32,97,115,32,97,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<44,32,111,116,104,101,114,119,105,115,101,32,97,110,121,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<32,119,105,108,108,32,100,111,46,32,73,102,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,105,110,118,111,108,118,101,100,32,97,110,100,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,98,111,116,104,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,97,110,100,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,114,101,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,115,40,41>>]},<<46>>]},{p,[],[{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,125,47,123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,44,32,84,121,112,101,125>>]},<<32,100,101,102,105,110,101,115,32,119,104,97,116,32,116,111,32,114,101,116,117,114,110,32,102,114,111,109,32,116,104,101,32,102,117,110,99,116,105,111,110,32,117,112,111,110,32,115,117,99,99,101,115,115,102,117,108,32,109,97,116,99,104,105,110,103,46,32,84,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,116,117,112,108,101,32,99,97,110,32,99,111,110,116,97,105,110,32,98,111,116,104,32,97,32,118,97,108,117,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,116,101,108,108,105,110,103,32,119,104,105,99,104,32,111,102,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,44,32,97,110,100,32,97,32,116,121,112,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,116,101,108,108,105,110,103,32,104,111,119,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,32,40,97,115,32,105,110,100,101,120,32,116,117,112,108,101,115,44,32,108,105,115,116,115,44,32,111,114,32,98,105,110,97,114,105,101,115,41,46,32,84,104,101,32,111,112,116,105,111,110,115,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,100,101,116,97,105,108,32,98,101,108,111,119,46>>]},{p,[],[<<73,102,32,116,104,101,32,99,97,112,116,117,114,101,32,111,112,116,105,111,110,115,32,100,101,115,99,114,105,98,101,32,116,104,97,116,32,110,111,32,115,117,98,115,116,114,105,110,103,32,99,97,112,116,117,114,105,110,103,32,105,115,32,116,111,32,98,101,32,100,111,110,101,32,40>>,{code,[],[<<123,99,97,112,116,117,114,101,44,32,110,111,110,101,125>>]},<<41,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,115,105,110,103,108,101,32,97,116,111,109,32>>,{code,[],[<<109,97,116,99,104>>]},<<32,117,112,111,110,32,115,117,99,99,101,115,115,102,117,108,32,109,97,116,99,104,105,110,103,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,109,97,116,99,104,44,32,86,97,108,117,101,76,105,115,116,125>>]},<<46,32,68,105,115,97,98,108,105,110,103,32,99,97,112,116,117,114,105,110,103,32,99,97,110,32,98,101,32,100,111,110,101,32,101,105,116,104,101,114,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<110,111,110,101>>]},<<32,111,114,32,97,110,32,101,109,112,116,121,32,108,105,115,116,32,97,115,32>>,{code,[],[<<86,97,108,117,101,83,112,101,99>>]},<<46>>]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]},<<32,97,100,100,115,32,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32,116,104,97,116,32,97,110,32,101,114,114,111,114,32,116,117,112,108,101,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,116,117,112,108,101,32,101,105,116,104,101,114,32,105,110,100,105,99,97,116,101,115,32,97,32,109,97,116,99,104,105,110,103,32,101,114,114,111,114,32,40>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,111,114,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]},<<41,44,32,111,114,32,97,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,44,32,119,104,101,114,101,32,116,104,101,32,101,114,114,111,114,32,116,117,112,108,101,32,104,97,115,32,116,104,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,101,114,114,111,114,44,32,123,99,111,109,112,105,108,101,44,32,67,111,109,112,105,108,101,69,114,114,125,125>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]},<<32,105,115,32,110,111,116,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,110,101,118,101,114,32,114,101,116,117,114,110,115,32,101,114,114,111,114,32,116,117,112,108,101,115,44,32,98,117,116,32,114,101,112,111,114,116,115,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,115,32,97,115,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,97,110,100,32,102,97,105,108,101,100,32,109,97,116,99,104,101,115,32,98,101,99,97,117,115,101,32,111,102,32,101,120,99,101,101,100,101,100,32,109,97,116,99,104,32,108,105,109,105,116,115,32,115,105,109,112,108,121,32,97,115,32>>,{code,[],[<<110,111,109,97,116,99,104>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,32,97,114,101,32,114,101,108,101,118,97,110,116,32,102,111,114,32,101,120,101,99,117,116,105,111,110,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,110,99,104,111,114,101,100>>]}]},{dd,[],[{p,[],[<<76,105,109,105,116,115,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,116,111,32,109,97,116,99,104,105,110,103,32,97,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,46,32,73,102,32,97,32,112,97,116,116,101,114,110,32,119,97,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32>>,{code,[],[<<97,110,99,104,111,114,101,100>>]},<<44,32,111,114,32,116,117,114,110,101,100,32,111,117,116,32,116,111,32,98,101,32,97,110,99,104,111,114,101,100,32,98,121,32,118,105,114,116,117,101,32,111,102,32,105,116,115,32,99,111,110,116,101,110,116,115,44,32,105,116,32,99,97,110,110,111,116,32,98,101,32,109,97,100,101,32,117,110,97,110,99,104,111,114,101,100,32,97,116,32,109,97,116,99,104,105,110,103,32,116,105,109,101,44,32,104,101,110,99,101,32,116,104,101,114,101,32,105,115,32,110,111,32>>,{code,[],[<<117,110,97,110,99,104,111,114,101,100>>]},<<32,111,112,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<103,108,111,98,97,108>>]}]},{dd,[],[{p,[],[<<73,109,112,108,101,109,101,110,116,115,32,103,108,111,98,97,108,32,40,114,101,112,101,116,105,116,105,118,101,41,32,115,101,97,114,99,104,32,40,102,108,97,103,32>>,{code,[],[<<103>>]},<<32,105,110,32,80,101,114,108,41,46,32,69,97,99,104,32,109,97,116,99,104,32,105,115,32,114,101,116,117,114,110,101,100,32,97,115,32,97,32,115,101,112,97,114,97,116,101,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,115,112,101,99,105,102,105,99,32,109,97,116,99,104,32,97,110,100,32,97,110,121,32,109,97,116,99,104,105,110,103,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,40,111,114,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32,111,112,116,105,111,110,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<46,32,84,104,101,32>>,{code,[],[<<67,97,112,116,117,114,101,100>>]},<<32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,104,101,110,99,101,32,97,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,111,102,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<115,32,119,104,101,110,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,46>>]},{p,[],[<<84,104,101,32,105,110,116,101,114,97,99,116,105,111,110,32,111,102,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,119,105,116,104,32,97,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,115,117,114,112,114,105,115,101,115,32,115,111,109,101,32,117,115,101,114,115,46,32,87,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,104,97,110,100,108,101,115,32,101,109,112,116,121,32,109,97,116,99,104,101,115,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,80,101,114,108,58,32,97,32,122,101,114,111,45,108,101,110,103,116,104,32,109,97,116,99,104,32,97,116,32,97,110,121,32,112,111,105,110,116,32,105,115,32,97,108,115,111,32,114,101,116,114,105,101,100,32,119,105,116,104,32,111,112,116,105,111,110,115,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]},<<46,32,73,102,32,116,104,97,116,32,115,101,97,114,99,104,32,103,105,118,101,115,32,97,32,114,101,115,117,108,116,32,111,102,32,108,101,110,103,116,104,32,62,32,48,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,105,110,99,108,117,100,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,99,97,116,34,44,34,40,124,97,116,41,34,44,91,103,108,111,98,97,108,93,41,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,105,110,103,115,32,97,114,101,32,112,101,114,102,111,114,109,101,100,58>>]},{dl,[],[{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32>>,{code,[],[<<40,124,97,116,41>>]},<<32,102,105,114,115,116,32,109,97,116,99,104,32,97,116,32,116,104,101,32,105,110,105,116,105,97,108,32,112,111,115,105,116,105,111,110,32,111,102,32,115,116,114,105,110,103,32>>,{code,[],[<<99,97,116>>]},<<44,32,103,105,118,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,115,101,116,32>>,{code,[],[<<91,123,48,44,48,125,44,123,48,44,48,125,93>>]},<<32,40,116,104,101,32,115,101,99,111,110,100,32>>,{code,[],[<<123,48,44,48,125>>]},<<32,105,115,32,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,109,97,114,107,101,100,32,98,121,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,41,46,32,65,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,109,97,116,99,104,32,105,115,32,48,44,32,119,101,32,100,111,32,110,111,116,32,97,100,118,97,110,99,101,32,116,111,32,116,104,101,32,110,101,120,116,32,112,111,115,105,116,105,111,110,32,121,101,116,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<48>>]},<<32,119,105,116,104,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,101,97,114,99,104,32,105,115,32,114,101,116,114,105,101,100,32,119,105,116,104,32,111,112,116,105,111,110,115,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]},<<32,97,116,32,116,104,101,32,115,97,109,101,32,112,111,115,105,116,105,111,110,44,32,119,104,105,99,104,32,100,111,101,115,32,110,111,116,32,103,105,118,101,32,97,110,121,32,105,110,116,101,114,101,115,116,105,110,103,32,114,101,115,117,108,116,32,111,102,32,108,111,110,103,101,114,32,108,101,110,103,116,104,44,32,115,111,32,116,104,101,32,115,101,97,114,99,104,32,112,111,115,105,116,105,111,110,32,105,115,32,97,100,118,97,110,99,101,100,32,116,111,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40>>,{code,[],[<<97>>]},<<41,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<49>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,101,97,114,99,104,32,114,101,115,117,108,116,115,32,105,110,32>>,{code,[],[<<91,123,49,44,48,125,44,123,49,44,48,125,93>>]},<<44,32,115,111,32,116,104,105,115,32,115,101,97,114,99,104,32,105,115,32,97,108,115,111,32,114,101,112,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,101,120,116,114,97,32,111,112,116,105,111,110,115,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<49>>]},<<32,119,105,116,104,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]}]},{dd,[],[{p,[],[<<65,108,116,101,114,110,97,116,105,118,101,32>>,{code,[],[<<97,98>>]},<<32,105,115,32,102,111,117,110,100,32,97,110,100,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,91,123,49,44,50,125,44,123,49,44,50,125,93,46,32,84,104,101,32,114,101,115,117,108,116,32,105,115,32,97,100,100,101,100,32,116,111,32,116,104,101,32,108,105,115,116,32,111,102,32,114,101,115,117,108,116,115,32,97,110,100,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,101,97,114,99,104,32,115,116,114,105,110,103,32,105,115,32,97,100,118,97,110,99,101,100,32,116,119,111,32,115,116,101,112,115,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<51>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,101,97,114,99,104,32,111,110,99,101,32,97,103,97,105,110,32,109,97,116,99,104,101,115,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,44,32,103,105,118,105,110,103,32>>,{code,[],[<<91,123,51,44,48,125,44,123,51,44,48,125,93>>]},<<46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<49>>]},<<32,119,105,116,104,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,103,105,118,101,115,32,110,111,32,114,101,115,117,108,116,32,111,102,32,108,101,110,103,116,104,32,62,32,48,32,97,110,100,32,119,101,32,97,114,101,32,97,116,32,116,104,101,32,108,97,115,116,32,112,111,115,105,116,105,111,110,44,32,115,111,32,116,104,101,32,103,108,111,98,97,108,32,115,101,97,114,99,104,32,105,115,32,99,111,109,112,108,101,116,101,46>>]}]}]},{p,[],[<<84,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,99,97,108,108,32,105,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,91,123,48,44,48,125,44,123,48,44,48,125,93,44,91,123,49,44,48,125,44,123,49,44,48,125,93,44,91,123,49,44,50,125,44,123,49,44,50,125,93,44,91,123,51,44,48,125,44,123,51,44,48,125,93,93,125>>]}]}]},{dt,[],[{code,[],[<<110,111,116,101,109,112,116,121>>]}]},{dd,[],[{p,[],[<<65,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,105,115,32,110,111,116,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,32,97,32,118,97,108,105,100,32,109,97,116,99,104,32,105,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,46,32,73,102,32,97,108,116,101,114,110,97,116,105,118,101,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,101,120,105,115,116,44,32,116,104,101,121,32,97,114,101,32,116,114,105,101,100,46,32,73,102,32,97,108,108,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,109,97,116,99,104,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,44,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,102,97,105,108,115,46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{p,[],[<<73,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,97,32,115,116,114,105,110,103,32,110,111,116,32,98,101,103,105,110,110,105,110,103,32,119,105,116,104,32,34,97,34,32,111,114,32,34,98,34,44,32,105,116,32,119,111,117,108,100,32,110,111,114,109,97,108,108,121,32,109,97,116,99,104,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,58>>]},{pre,[],[{code,[],[<<97,63,98,63>>]}]},{p,[],[<<87,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,116,101,109,112,116,121>>]},<<44,32,116,104,105,115,32,109,97,116,99,104,32,105,115,32,105,110,118,97,108,105,100,44,32,115,111,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,115,101,97,114,99,104,101,115,32,102,117,114,116,104,101,114,32,105,110,116,111,32,116,104,101,32,115,116,114,105,110,103,32,102,111,114,32,111,99,99,117,114,114,101,110,99,101,115,32,111,102,32,34,97,34,32,111,114,32,34,98,34,46>>]}]},{dt,[],[{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]}]},{dd,[],[{p,[],[<<76,105,107,101,32>>,{code,[],[<<110,111,116,101,109,112,116,121>>]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,109,97,116,99,104,32,116,104,97,116,32,105,115,32,110,111,116,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,112,101,114,109,105,116,116,101,100,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,97,110,99,104,111,114,101,100,44,32,115,117,99,104,32,97,32,109,97,116,99,104,32,99,97,110,32,111,99,99,117,114,32,111,110,108,121,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,99,111,110,116,97,105,110,115,32,92,75,46>>]},{p,[],[<<80,101,114,108,32,104,97,115,32,110,111,32,100,105,114,101,99,116,32,101,113,117,105,118,97,108,101,110,116,32,111,102,32>>,{code,[],[<<110,111,116,101,109,112,116,121>>]},<<32,111,114,32>>,{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]},<<44,32,98,117,116,32,105,116,32,100,111,101,115,32,109,97,107,101,32,97,32,115,112,101,99,105,97,108,32,99,97,115,101,32,111,102,32,97,32,112,97,116,116,101,114,110,32,109,97,116,99,104,32,111,102,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,32,119,105,116,104,105,110,32,105,116,115,32,115,112,108,105,116,40,41,32,102,117,110,99,116,105,111,110,44,32,97,110,100,32,119,104,101,110,32,117,115,105,110,103,32,109,111,100,105,102,105,101,114,32>>,{code,[],[<<47,103>>]},<<46,32,84,104,101,32,80,101,114,108,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,101,109,117,108,97,116,101,100,32,97,102,116,101,114,32,109,97,116,99,104,105,110,103,32,97,32,110,117,108,108,32,115,116,114,105,110,103,32,98,121,32,102,105,114,115,116,32,116,114,121,105,110,103,32,116,104,101,32,109,97,116,99,104,32,97,103,97,105,110,32,97,116,32,116,104,101,32,115,97,109,101,32,111,102,102,115,101,116,32,119,105,116,104,32>>,{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]},<<32,97,110,100,32>>,{code,[],[<<97,110,99,104,111,114,101,100>>]},<<44,32,97,110,100,32,116,104,101,110,44,32,105,102,32,116,104,97,116,32,102,97,105,108,115,44,32,98,121,32,97,100,118,97,110,99,105,110,103,32,116,104,101,32,115,116,97,114,116,105,110,103,32,111,102,102,115,101,116,32,40,115,101,101,32,98,101,108,111,119,41,32,97,110,100,32,116,114,121,105,110,103,32,97,110,32,111,114,100,105,110,97,114,121,32,109,97,116,99,104,32,97,103,97,105,110,46>>]}]},{dt,[],[{code,[],[<<110,111,116,98,111,108>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,105,115,32,110,111,116,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,97,32,108,105,110,101,44,32,115,111,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,105,115,32,110,111,116,32,116,111,32,109,97,116,99,104,32,98,101,102,111,114,101,32,105,116,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,119,105,116,104,111,117,116,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,40,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,41,32,99,97,117,115,101,115,32,99,105,114,99,117,109,102,108,101,120,32,110,101,118,101,114,32,116,111,32,109,97,116,99,104,46,32,84,104,105,115,32,111,112,116,105,111,110,32,111,110,108,121,32,97,102,102,101,99,116,115,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,109,101,116,97,99,104,97,114,97,99,116,101,114,46,32,73,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,92,65,46>>]}]},{dt,[],[{code,[],[<<110,111,116,101,111,108>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,105,115,32,110,111,116,32,116,104,101,32,101,110,100,32,111,102,32,97,32,108,105,110,101,44,32,115,111,32,116,104,101,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,105,115,32,110,111,116,32,116,111,32,109,97,116,99,104,32,105,116,32,110,111,114,32,40,101,120,99,101,112,116,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,41,32,97,32,110,101,119,108,105,110,101,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,105,116,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,119,105,116,104,111,117,116,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,40,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,41,32,99,97,117,115,101,115,32,100,111,108,108,97,114,32,110,101,118,101,114,32,116,111,32,109,97,116,99,104,46,32,84,104,105,115,32,111,112,116,105,111,110,32,97,102,102,101,99,116,115,32,111,110,108,121,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,46,32,73,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,92,90,32,111,114,32,92,122,46>>]}]},{dt,[],[{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,98,101,116,116,101,114,32,99,111,110,116,114,111,108,32,111,102,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103,32,105,110,32>>,{code,[],[<<114,117,110,47,51>>]},<<46,32,87,104,101,110,32,115,112,101,99,105,102,105,101,100,44,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,115,32,40,105,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,110,111,116,32,97,108,114,101,97,100,121,32,99,111,109,112,105,108,101,100,41,32,97,110,100,32,114,117,110,116,105,109,101,32,101,114,114,111,114,115,32,97,114,101,32,101,120,112,108,105,99,105,116,108,121,32,114,101,116,117,114,110,101,100,32,97,115,32,97,110,32,101,114,114,111,114,32,116,117,112,108,101,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,112,111,115,115,105,98,108,101,32,114,117,110,116,105,109,101,32,101,114,114,111,114,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,32,115,101,116,115,32,97,32,108,105,109,105,116,32,111,110,32,104,111,119,32,109,97,110,121,32,116,105,109,101,115,32,116,104,101,32,105,110,116,101,114,110,97,108,32,109,97,116,99,104,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,99,97,108,108,101,100,46,32,68,101,102,97,117,108,116,115,32,116,111,32,49,48,44,48,48,48,44,48,48,48,32,105,110,32,116,104,101,32,108,105,98,114,97,114,121,32,99,111,109,112,105,108,101,100,32,102,111,114,32,69,114,108,97,110,103,46,32,73,102,32>>,{code,[],[<<123,101,114,114,111,114,44,32,109,97,116,99,104,95,108,105,109,105,116,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,111,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,104,97,115,32,114,101,97,99,104,101,100,32,116,104,105,115,32,108,105,109,105,116,46,32,84,104,105,115,32,105,115,32,110,111,114,109,97,108,108,121,32,116,111,32,98,101,32,114,101,103,97,114,100,101,100,32,97,115,32,97,32>>,{code,[],[<<110,111,109,97,116,99,104>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,118,97,108,117,101,32,119,104,101,110,32,116,104,105,115,32,111,99,99,117,114,115,44,32,98,117,116,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]},<<44,32,121,111,117,32,97,114,101,32,105,110,102,111,114,109,101,100,32,119,104,101,110,32,116,104,101,32,109,97,116,99,104,32,102,97,105,108,115,32,98,101,99,97,117,115,101,32,111,102,32,116,111,111,32,109,97,110,121,32,105,110,116,101,114,110,97,108,32,99,97,108,108,115,46>>]}]},{dt,[],[{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,101,114,114,111,114,32,105,115,32,118,101,114,121,32,115,105,109,105,108,97,114,32,116,111,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<44,32,98,117,116,32,111,99,99,117,114,115,32,119,104,101,110,32,116,104,101,32,105,110,116,101,114,110,97,108,32,109,97,116,99,104,32,102,117,110,99,116,105,111,110,32,111,102,32,80,67,82,69,32,105,115,32,34,114,101,99,117,114,115,105,118,101,108,121,34,32,99,97,108,108,101,100,32,109,111,114,101,32,116,105,109,101,115,32,116,104,97,110,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]},<<32,108,105,109,105,116,44,32,119,104,105,99,104,32,100,101,102,97,117,108,116,115,32,116,111,32,49,48,44,48,48,48,44,48,48,48,32,97,115,32,119,101,108,108,46,32,78,111,116,105,99,101,32,116,104,97,116,32,97,115,32,108,111,110,103,32,97,115,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,97,110,100,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,100,101,102,97,117,108,116>>]},<<32,118,97,108,117,101,115,32,97,114,101,32,107,101,112,116,32,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,115,44,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]},<<32,101,114,114,111,114,32,99,97,110,110,111,116,32,111,99,99,117,114,44,32,97,115,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,101,114,114,111,114,32,111,99,99,117,114,115,32,98,101,102,111,114,101,32,116,104,97,116,32,40,101,97,99,104,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,105,115,32,97,108,115,111,32,97,32,99,97,108,108,44,32,98,117,116,32,110,111,116,32,99,111,110,118,101,114,115,101,108,121,41,46,32,66,111,116,104,32,108,105,109,105,116,115,32,99,97,110,32,104,111,119,101,118,101,114,32,98,101,32,99,104,97,110,103,101,100,44,32,101,105,116,104,101,114,32,98,121,32,115,101,116,116,105,110,103,32,108,105,109,105,116,115,32,100,105,114,101,99,116,108,121,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,115,116,114,105,110,103,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,101,103,101,120,112,95,115,121,110,116,97,120,95,100,101,116,97,105,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,67,82,69,32,82,101,103,117,108,97,114,32,69,101,120,112,114,101,115,115,105,111,110,32,68,101,116,97,105,108,115>>]},<<41,32,111,114,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32,111,112,116,105,111,110,115,32,116,111,32>>,{code,[],[<<114,117,110,47,51>>]},<<46>>]}]}]},{p,[],[<<73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32,116,111,32,117,110,100,101,114,115,116,97,110,100,32,116,104,97,116,32,119,104,97,116,32,105,115,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,34,114,101,99,117,114,115,105,111,110,34,32,119,104,101,110,32,108,105,109,105,116,105,110,103,32,109,97,116,99,104,101,115,32,105,115,32,110,111,116,32,114,101,99,117,114,115,105,111,110,32,111,110,32,116,104,101,32,67,32,115,116,97,99,107,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,109,97,99,104,105,110,101,32,111,114,32,111,110,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,115,116,97,99,107,46,32,84,104,101,32,80,67,82,69,32,118,101,114,115,105,111,110,32,99,111,109,112,105,108,101,100,32,105,110,116,111,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,117,115,101,115,32,109,97,99,104,105,110,101,32,34,104,101,97,112,34,32,109,101,109,111,114,121,32,116,111,32,115,116,111,114,101,32,118,97,108,117,101,115,32,116,104,97,116,32,109,117,115,116,32,98,101,32,107,101,112,116,32,111,118,101,114,32,114,101,99,117,114,115,105,111,110,32,105,110,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<76,105,109,105,116,115,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,111,102,32,97,32,109,97,116,99,104,32,105,110,32,97,110,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,115,112,101,99,105,102,105,99,32,119,97,121,46,32,73,116,32,105,115,32,100,101,115,99,114,105,98,101,100,32,97,115,32,102,111,108,108,111,119,115,32,98,121,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<84,104,101,32,109,97,116,99,104,95,108,105,109,105,116,32,102,105,101,108,100,32,112,114,111,118,105,100,101,115,32,97,32,109,101,97,110,115,32,111,102,32,112,114,101,118,101,110,116,105,110,103,32,80,67,82,69,32,102,114,111,109,32,117,115,105,110,103,10,117,112,32,97,32,118,97,115,116,32,97,109,111,117,110,116,32,111,102,32,114,101,115,111,117,114,99,101,115,32,119,104,101,110,32,114,117,110,110,105,110,103,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,103,111,105,110,103,10,116,111,32,109,97,116,99,104,44,32,98,117,116,32,119,104,105,99,104,32,104,97,118,101,32,97,32,118,101,114,121,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,112,111,115,115,105,98,105,108,105,116,105,101,115,32,105,110,32,116,104,101,105,114,10,115,101,97,114,99,104,32,116,114,101,101,115,46,32,84,104,101,32,99,108,97,115,115,105,99,32,101,120,97,109,112,108,101,32,105,115,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,117,115,101,115,32,110,101,115,116,101,100,10,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,115,46,10,10,73,110,116,101,114,110,97,108,108,121,44,32,112,99,114,101,95,101,120,101,99,40,41,32,117,115,101,115,32,97,32,102,117,110,99,116,105,111,110,32,99,97,108,108,101,100,32,109,97,116,99,104,40,41,44,32,119,104,105,99,104,32,105,116,32,99,97,108,108,115,10,114,101,112,101,97,116,101,100,108,121,32,40,115,111,109,101,116,105,109,101,115,32,114,101,99,117,114,115,105,118,101,108,121,41,46,32,84,104,101,32,108,105,109,105,116,32,115,101,116,32,98,121,32,109,97,116,99,104,95,108,105,109,105,116,32,105,115,10,105,109,112,111,115,101,100,32,111,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,100,117,114,105,110,103,32,97,32,109,97,116,99,104,44,10,119,104,105,99,104,32,104,97,115,32,116,104,101,32,101,102,102,101,99,116,32,111,102,32,108,105,109,105,116,105,110,103,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,104,97,116,32,99,97,110,10,116,97,107,101,32,112,108,97,99,101,46,32,70,111,114,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,97,110,99,104,111,114,101,100,44,32,116,104,101,32,99,111,117,110,116,32,114,101,115,116,97,114,116,115,10,102,114,111,109,32,122,101,114,111,32,102,111,114,32,101,97,99,104,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]}]},{p,[],[<<84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,114,117,110,97,119,97,121,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,115,32,99,97,110,32,102,97,105,108,32,102,97,115,116,101,114,32,105,102,32,116,104,101,32,108,105,109,105,116,32,105,115,32,108,111,119,101,114,101,100,32,117,115,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,46,32,84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,49,48,44,48,48,48,44,48,48,48,32,105,115,32,99,111,109,112,105,108,101,100,32,105,110,116,111,32,116,104,101,32,69,114,108,97,110,103,32,86,77,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,100,111,101,115,32,105,110,32,110,111,32,119,97,121,32,97,102,102,101,99,116,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,105,110,32,116,101,114,109,115,32,111,102,32,34,108,111,110,103,32,114,117,110,110,105,110,103,32,66,73,70,115,34,46,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,97,108,119,97,121,115,32,103,105,118,101,115,32,99,111,110,116,114,111,108,32,98,97,99,107,32,116,111,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,111,102,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,116,32,105,110,116,101,114,118,97,108,115,32,116,104,97,116,32,101,110,115,117,114,101,115,32,116,104,101,32,114,101,97,108,45,116,105,109,101,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,115,121,115,116,101,109,46>>]}]}]},{dt,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<76,105,109,105,116,115,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,97,110,100,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,32,111,102,32,97,32,109,97,116,99,104,32,105,110,32,97,110,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,115,112,101,99,105,102,105,99,32,119,97,121,44,32,118,101,114,121,32,115,105,109,105,108,97,114,32,116,111,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<46,32,73,116,32,105,115,32,100,101,115,99,114,105,98,101,100,32,97,115,32,102,111,108,108,111,119,115,32,98,121,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<84,104,101,32,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,32,102,105,101,108,100,32,105,115,32,115,105,109,105,108,97,114,32,116,111,32,109,97,116,99,104,95,108,105,109,105,116,44,32,98,117,116,32,105,110,115,116,101,97,100,10,111,102,32,108,105,109,105,116,105,110,103,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,116,104,97,116,32,109,97,116,99,104,40,41,32,105,115,32,99,97,108,108,101,100,44,32,105,116,10,108,105,109,105,116,115,32,116,104,101,32,100,101,112,116,104,32,111,102,32,114,101,99,117,114,115,105,111,110,46,32,84,104,101,32,114,101,99,117,114,115,105,111,110,32,100,101,112,116,104,32,105,115,32,97,32,115,109,97,108,108,101,114,32,110,117,109,98,101,114,10,116,104,97,110,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,99,97,108,108,115,44,32,98,101,99,97,117,115,101,32,110,111,116,32,97,108,108,32,99,97,108,108,115,32,116,111,32,109,97,116,99,104,40,41,32,97,114,101,10,114,101,99,117,114,115,105,118,101,46,32,84,104,105,115,32,108,105,109,105,116,32,105,115,32,111,102,32,117,115,101,32,111,110,108,121,32,105,102,32,105,116,32,105,115,32,115,101,116,32,115,109,97,108,108,101,114,32,116,104,97,110,10,109,97,116,99,104,95,108,105,109,105,116,46,10,10,76,105,109,105,116,105,110,103,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,100,101,112,116,104,32,108,105,109,105,116,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,109,97,99,104,105,110,101,32,115,116,97,99,107,32,116,104,97,116,10,99,97,110,32,98,101,32,117,115,101,100,44,32,111,114,44,32,119,104,101,110,32,80,67,82,69,32,104,97,115,32,98,101,101,110,32,99,111,109,112,105,108,101,100,32,116,111,32,117,115,101,32,109,101,109,111,114,121,32,111,110,32,116,104,101,32,104,101,97,112,10,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,115,116,97,99,107,44,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,104,101,97,112,32,109,101,109,111,114,121,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,46>>]}]},{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,86,77,32,117,115,101,115,32,97,32,80,67,82,69,32,108,105,98,114,97,114,121,32,119,104,101,114,101,32,104,101,97,112,32,109,101,109,111,114,121,32,105,115,32,117,115,101,100,32,119,104,101,110,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,32,114,101,99,117,114,115,105,111,110,32,111,99,99,117,114,115,46,32,84,104,105,115,32,116,104,101,114,101,102,111,114,101,32,108,105,109,105,116,115,32,116,104,101,32,117,115,101,32,111,102,32,109,97,99,104,105,110,101,32,104,101,97,112,44,32,110,111,116,32,67,32,115,116,97,99,107,46>>]},{p,[],[<<83,112,101,99,105,102,121,105,110,103,32,97,32,108,111,119,101,114,32,118,97,108,117,101,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,109,97,116,99,104,101,115,32,119,105,116,104,32,100,101,101,112,32,114,101,99,117,114,115,105,111,110,32,102,97,105,108,105,110,103,44,32,119,104,101,110,32,116,104,101,121,32,115,104,111,117,108,100,32,104,97,118,101,32,109,97,116,99,104,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<49,62,32,114,101,58,114,117,110,40,34,97,97,97,97,97,97,97,97,97,97,97,97,97,122,34,44,34,40,97,43,41,42,122,34,41,46,10,123,109,97,116,99,104,44,91,123,48,44,49,52,125,44,123,48,44,49,51,125,93,125,10,50,62,32,114,101,58,114,117,110,40,34,97,97,97,97,97,97,97,97,97,97,97,97,97,122,34,44,34,40,97,43,41,42,122,34,44,91,123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,53,125,93,41,46,10,110,111,109,97,116,99,104,10,51,62,32,114,101,58,114,117,110,40,34,97,97,97,97,97,97,97,97,97,97,97,97,97,122,34,44,34,40,97,43,41,42,122,34,44,91,123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,53,125,44,114,101,112,111,114,116,95,101,114,114,111,114,115,93,41,46,10,123,101,114,114,111,114,44,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,125>>]}]},{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,97,110,100,32,111,112,116,105,111,110,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,97,114,101,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,114,97,114,101,32,99,97,115,101,115,46,32,85,110,100,101,114,115,116,97,110,100,105,110,103,32,111,102,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,32,105,110,116,101,114,110,97,108,115,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,98,101,102,111,114,101,32,116,97,109,112,101,114,105,110,103,32,119,105,116,104,32,116,104,101,115,101,32,108,105,109,105,116,115,46>>]}]},{dt,[],[{code,[],[<<123,111,102,102,115,101,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,32,109,97,116,99,104,105,110,103,32,97,116,32,116,104,101,32,111,102,102,115,101,116,32,40,112,111,115,105,116,105,111,110,41,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,84,104,101,32,111,102,102,115,101,116,32,105,115,32,122,101,114,111,45,98,97,115,101,100,44,32,115,111,32,116,104,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<123,111,102,102,115,101,116,44,48,125>>]},<<32,40,97,108,108,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,41,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]}]},{dd,[],[{p,[],[<<79,118,101,114,114,105,100,101,115,32,116,104,101,32,100,101,102,97,117,108,116,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,97,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,119,104,105,99,104,32,105,115,32,76,70,32,40,65,83,67,73,73,32,49,48,41,32,105,110,32,69,114,108,97,110,103,46>>]},{dl,[],[{dt,[],[{code,[],[<<99,114>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,67,82,32,40,65,83,67,73,73,32,49,51,41,46>>]}]},{dt,[],[{code,[],[<<108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,76,70,32,40,65,83,67,73,73,32,49,48,41,44,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<99,114,108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,67,82,76,70,32,40,65,83,67,73,73,32,49,51,32,102,111,108,108,111,119,101,100,32,98,121,32,65,83,67,73,73,32,49,48,41,32,115,101,113,117,101,110,99,101,46>>]}]},{dt,[],[{code,[],[<<97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,112,114,101,99,101,100,105,110,103,32,115,101,113,117,101,110,99,101,115,32,105,115,32,98,101,32,114,101,99,111,103,110,105,122,101,100,46>>]}]},{dt,[],[{code,[],[<<97,110,121>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,115,32,97,98,111,118,101,44,32,97,110,100,32,116,104,101,32,85,110,105,99,111,100,101,32,115,101,113,117,101,110,99,101,115,32,86,84,32,40,118,101,114,116,105,99,97,108,32,116,97,98,44,32,85,43,48,48,48,66,41,44,32,70,70,32,40,102,111,114,109,102,101,101,100,44,32,85,43,48,48,48,67,41,44,32,78,69,76,32,40,110,101,120,116,32,108,105,110,101,44,32,85,43,48,48,56,53,41,44,32,76,83,32,40,108,105,110,101,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,56,41,44,32,97,110,100,32,80,83,32,40,112,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,57,41,46>>]}]}]}]},{dt,[],[{code,[],[<<98,115,114,95,97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,116,104,101,32,67,82,32,76,70,44,32,111,114,32,67,82,76,70,32,115,101,113,117,101,110,99,101,115,44,32,110,111,116,32,116,104,101,32,85,110,105,99,111,100,101,45,115,112,101,99,105,102,105,99,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,46,32,40,79,118,101,114,114,105,100,101,115,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,46,41>>]}]},{dt,[],[{code,[],[<<98,115,114,95,117,110,105,99,111,100,101>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,97,108,108,32,116,104,101,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,99,108,117,100,105,110,103,32,67,82,76,70,44,32,97,110,100,32,115,111,32,111,110,44,32,116,104,101,32,100,101,102,97,117,108,116,41,46,32,40,79,118,101,114,114,105,100,101,115,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,46,41>>]}]},{dt,[],[{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,125>>]},<<47>>,{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,44,32,84,121,112,101,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,119,104,105,99,104,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,110,100,32,105,110,32,119,104,97,116,32,102,111,114,109,97,116,46,32,66,121,32,100,101,102,97,117,108,116,44,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,99,97,112,116,117,114,101,115,32,97,108,108,32,111,102,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,115,116,114,105,110,103,32,97,110,100,32,97,108,108,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,40,97,108,108,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,97,112,116,117,114,101,100,41,46,32,84,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32,40,122,101,114,111,45,98,97,115,101,100,41,32,105,110,100,101,120,101,115,32,111,102,32,116,104,101,32,99,97,112,116,117,114,101,100,32,112,97,114,116,115,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,115,112,101,99,105,102,105,101,100,32,97,115,32>>,{code,[],[<<123,79,102,102,115,101,116,44,76,101,110,103,116,104,125>>]},<<32,112,97,105,114,115,32,40,116,104,101,32>>,{code,[],[<<105,110,100,101,120>>]},<<32>>,{code,[],[<<84,121,112,101>>]},<<32,111,102,32,99,97,112,116,117,114,105,110,103,41,46>>]},{p,[],[<<65,115,32,97,110,32,101,120,97,109,112,108,101,32,111,102,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,32,114,101,116,117,114,110,115,44,32,97,115,32,102,105,114,115,116,32,97,110,100,32,111,110,108,121,32,99,97,112,116,117,114,101,100,32,115,116,114,105,110,103,44,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,40,34,97,98,99,100,34,32,105,110,32,116,104,101,32,109,105,100,100,108,101,41,32,97,115,32,97,110,32,105,110,100,101,120,32,112,97,105,114,32>>,{code,[],[<<123,51,44,52,125>>]},<<44,32,119,104,101,114,101,32,99,104,97,114,97,99,116,101,114,32,112,111,115,105,116,105,111,110,115,32,97,114,101,32,122,101,114,111,45,98,97,115,101,100,44,32,106,117,115,116,32,97,115,32,105,110,32,111,102,102,115,101,116,115,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,97,98,99,100,34,44,91,93,41,46>>]}]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32,116,104,105,115,32,99,97,108,108,32,105,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,51,44,52,125,93,125>>]}]},{p,[],[<<65,110,111,116,104,101,114,32,40,97,110,100,32,113,117,105,116,101,32,99,111,109,109,111,110,41,32,99,97,115,101,32,105,115,32,119,104,101,114,101,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,115,32,97,108,108,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,97,98,99,100,46,42,34,44,91,93,41,46>>]}]},{p,[],[<<72,101,114,101,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,108,121,32,112,111,105,110,116,115,32,111,117,116,32,97,108,108,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,98,101,103,105,110,110,105,110,103,32,97,116,32,105,110,100,101,120,32,48,44,32,97,110,100,32,105,116,32,105,115,32,49,48,32,99,104,97,114,97,99,116,101,114,115,32,108,111,110,103,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,48,44,49,48,125,93,125>>]}]},{p,[],[<<73,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,99,111,110,116,97,105,110,115,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,108,105,107,101,32,105,110,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,97,98,99,100,41,46,42,34,44,91,93,41,46>>]}]},{p,[],[<<97,108,108,32,111,102,32,116,104,101,32,109,97,116,99,104,101,100,32,115,117,98,106,101,99,116,32,105,115,32,99,97,112,116,117,114,101,100,44,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,48,44,49,48,125,44,123,51,44,52,125,93,125>>]}]},{p,[],[<<84,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,112,97,116,116,101,114,110,32,97,108,119,97,121,115,32,103,105,118,101,115,32,116,104,101,32,102,105,114,115,116,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,110,32,116,104,101,32,108,105,115,116,32,97,110,100,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,111,114,100,101,114,32,116,104,101,121,32,111,99,99,117,114,114,101,100,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<84,104,101,32,99,97,112,116,117,114,101,32,116,117,112,108,101,32,105,115,32,98,117,105,108,116,32,117,112,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<86,97,108,117,101,83,112,101,99>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,119,104,105,99,104,32,99,97,112,116,117,114,101,100,32,40,115,117,98,41,112,97,116,116,101,114,110,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32>>,{code,[],[<<86,97,108,117,101,83,112,101,99>>]},<<32,99,97,110,32,101,105,116,104,101,114,32,98,101,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,97,32,112,114,101,100,101,102,105,110,101,100,32,115,101,116,32,111,102,32,114,101,116,117,114,110,32,118,97,108,117,101,115,44,32,111,114,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,105,110,100,101,120,101,115,32,111,114,32,116,104,101,32,110,97,109,101,115,32,111,102,32,115,112,101,99,105,102,105,99,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,114,101,116,117,114,110,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,112,114,101,100,101,102,105,110,101,100,32,115,101,116,115,32,111,102,32,115,117,98,112,97,116,116,101,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[{p,[],[<<65,108,108,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,115,116,114,105,110,103,46,32,84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<97,108,108,95,110,97,109,101,115>>]}]},{dd,[],[{p,[],[<<65,108,108,32>>,{em,[],[<<110,97,109,101,100>>]},<<32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,97,115,32,105,102,32,97,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,111,102,32,97,108,108,32,116,104,101,32,110,97,109,101,115,32>>,{em,[],[<<105,110,32,97,108,112,104,97,98,101,116,105,99,97,108,32,111,114,100,101,114>>]},<<32,119,97,115,32,115,112,101,99,105,102,105,101,100,46,32,84,104,101,32,108,105,115,116,32,111,102,32,97,108,108,32,110,97,109,101,115,32,99,97,110,32,97,108,115,111,32,98,101,32,114,101,116,114,105,101,118,101,100,32,119,105,116,104,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,105,110,115,112,101,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,110,115,112,101,99,116,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<102,105,114,115,116>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,116,104,101,32,102,105,114,115,116,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,105,115,32,97,108,119,97,121,115,32,116,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46,32,65,108,108,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,100,105,115,99,97,114,100,101,100,46>>]}]},{dt,[],[{code,[],[<<97,108,108,95,98,117,116,95,102,105,114,115,116>>]}]},{dd,[],[{p,[],[<<65,108,108,32,98,117,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,115,117,98,112,97,116,116,101,114,110,44,32,116,104,97,116,32,105,115,44,32,97,108,108,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,98,117,116,32,110,111,116,32,116,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,84,104,105,115,32,105,115,32,117,115,101,102,117,108,32,105,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,115,32,97,32,119,104,111,108,101,32,109,97,116,99,104,101,115,32,97,32,108,97,114,103,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,98,117,116,32,116,104,101,32,112,97,114,116,32,121,111,117,32,97,114,101,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,105,115,32,105,110,32,97,110,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,46,32,73,102,32,116,104,101,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32>>,{code,[],[<<108,105,115,116>>]},<<32,111,114,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<44,32,110,111,116,32,114,101,116,117,114,110,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,121,111,117,32,97,114,101,32,110,111,116,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,105,115,32,97,32,103,111,111,100,32,119,97,121,32,116,111,32,111,112,116,105,109,105,122,101,46>>]}]},{dt,[],[{code,[],[<<110,111,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,110,111,32,109,97,116,99,104,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,103,105,118,101,115,32,116,104,101,32,115,105,110,103,108,101,32,97,116,111,109,32>>,{code,[],[<<109,97,116,99,104>>]},<<32,97,115,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,115,117,99,99,101,115,115,102,117,108,108,121,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32>>,{code,[],[<<123,109,97,116,99,104,44,32,108,105,115,116,40,41,125>>]},<<32,114,101,116,117,114,110,46,32,83,112,101,99,105,102,121,105,110,103,32,97,110,32,101,109,112,116,121,32,108,105,115,116,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,98,101,104,97,118,105,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,118,97,108,117,101,32,108,105,115,116,32,105,115,32,97,32,108,105,115,116,32,111,102,32,105,110,100,101,120,101,115,32,102,111,114,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,114,101,116,117,114,110,44,32,119,104,101,114,101,32,105,110,100,101,120,32,48,32,105,115,32,102,111,114,32,97,108,108,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,44,32,97,110,100,32,49,32,105,115,32,102,111,114,32,116,104,101,32,102,105,114,115,116,32,101,120,112,108,105,99,105,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,97,110,100,32,115,111,32,111,110,46,32,87,104,101,110,32,117,115,105,110,103,32,110,97,109,101,100,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,40,115,101,101,32,98,101,108,111,119,41,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,111,110,101,32,99,97,110,32,117,115,101,32>>,{code,[],[<<97,116,111,109,40,41>>]},<<115,32,111,114,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<115,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,58>>]},{pre,[],[{code,[],[<<34,46,42,40,97,98,99,100,41,46,42,34>>]}]},{p,[],[<<109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,115,116,114,105,110,103,32,34,65,66,67,97,98,99,100,65,66,67,34,44,32,99,97,112,116,117,114,105,110,103,32,111,110,108,121,32,116,104,101,32,34,97,98,99,100,34,32,112,97,114,116,32,40,116,104,101,32,102,105,114,115,116,32,101,120,112,108,105,99,105,116,32,115,117,98,112,97,116,116,101,114,110,41,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,97,98,99,100,41,46,42,34,44,91,123,99,97,112,116,117,114,101,44,91,49,93,125,93,41,46>>]}]},{p,[],[<<84,104,101,32,99,97,108,108,32,103,105,118,101,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,101,115,117,108,116,44,32,97,115,32,116,104,101,32,102,105,114,115,116,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,34,40,97,98,99,100,41,34,44,32,109,97,116,99,104,105,110,103,32,34,97,98,99,100,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,44,32,97,116,32,40,122,101,114,111,45,98,97,115,101,100,41,32,112,111,115,105,116,105,111,110,32,51,44,32,111,102,32,108,101,110,103,116,104,32,52,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,51,44,52,125,93,125>>]}]},{p,[],[<<67,111,110,115,105,100,101,114,32,116,104,101,32,115,97,109,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,98,117,116,32,119,105,116,104,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,101,120,112,108,105,99,105,116,108,121,32,110,97,109,101,100,32,39,70,79,79,39,58>>]},{pre,[],[{code,[],[<<34,46,42,40,63,60,70,79,79,62,97,98,99,100,41,46,42,34>>]}]},{p,[],[<<87,105,116,104,32,116,104,105,115,32,101,120,112,114,101,115,115,105,111,110,44,32,119,101,32,99,111,117,108,100,32,115,116,105,108,108,32,103,105,118,101,32,116,104,101,32,105,110,100,101,120,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,63,60,70,79,79,62,97,98,99,100,41,46,42,34,44,91,123,99,97,112,116,117,114,101,44,91,49,93,125,93,41,46>>]}]},{p,[],[<<103,105,118,105,110,103,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,98,101,102,111,114,101,46,32,66,117,116,44,32,97,115,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,110,97,109,101,100,44,32,119,101,32,99,97,110,32,97,108,115,111,32,115,112,101,99,105,102,121,32,105,116,115,32,110,97,109,101,32,105,110,32,116,104,101,32,118,97,108,117,101,32,108,105,115,116,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,63,60,70,79,79,62,97,98,99,100,41,46,42,34,44,91,123,99,97,112,116,117,114,101,44,91,39,70,79,79,39,93,125,93,41,46>>]}]},{p,[],[<<84,104,105,115,32,119,111,117,108,100,32,103,105,118,101,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,116,104,101,32,101,97,114,108,105,101,114,32,101,120,97,109,112,108,101,115,44,32,110,97,109,101,108,121,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,51,44,52,125,93,125>>]}]},{p,[],[<<84,104,101,32,118,97,108,117,101,115,32,108,105,115,116,32,99,97,110,32,115,112,101,99,105,102,121,32,105,110,100,101,120,101,115,32,111,114,32,110,97,109,101,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,118,97,114,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,116,121,112,101,46,32,73,102,32,116,104,101,32,116,121,112,101,32,105,115,32>>,{code,[],[<<105,110,100,101,120>>]},<<44,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,45,49,44,48,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,102,111,114,32,118,97,108,117,101,115,32,119,105,116,104,32,110,111,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,98,117,116,32,102,111,114,32,116,104,101,32,111,116,104,101,114,32,116,121,112,101,115,32,40>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,97,110,100,32>>,{code,[],[<<108,105,115,116>>]},<<41,44,32,116,104,101,32,118,97,108,117,101,115,32,97,114,101,32,116,104,101,32,101,109,112,116,121,32,98,105,110,97,114,121,32,111,114,32,108,105,115,116,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46>>]}]},{dt,[],[{code,[],[<<84,121,112,101>>]}]},{dd,[],[{p,[],[<<79,112,116,105,111,110,97,108,108,121,32,115,112,101,99,105,102,105,101,115,32,104,111,119,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32,73,102,32,111,109,105,116,116,101,100,44,32,116,104,101,32,100,101,102,97,117,108,116,32,111,102,32>>,{code,[],[<<105,110,100,101,120>>]},<<32,105,115,32,117,115,101,100,46>>]},{p,[],[{code,[],[<<84,121,112,101>>]},<<32,99,97,110,32,98,101,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<105,110,100,101,120>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,115,32,112,97,105,114,115,32,111,102,32,98,121,116,101,32,105,110,100,101,120,101,115,32,105,110,116,111,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,97,110,100,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,116,114,105,110,103,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,40,97,115,32,105,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,119,97,115,32,102,108,97,116,116,101,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,35,99,104,97,114,97,99,116,101,114,115,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,105,99,111,100,101,58,99,104,97,114,97,99,116,101,114,115,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<32,98,101,102,111,114,101,32,109,97,116,99,104,105,110,103,41,46,32,78,111,116,105,99,101,32,116,104,97,116,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,114,101,115,117,108,116,115,32,105,110,32>>,{em,[],[<<98,121,116,101,45,111,114,105,101,110,116,101,100>>]},<<32,105,110,100,101,120,101,115,32,105,110,32,97,32,40,112,111,115,115,105,98,108,121,32,118,105,114,116,117,97,108,41,32>>,{em,[],[<<85,84,70,45,56,32,101,110,99,111,100,101,100>>]},<<32,98,105,110,97,114,121,46,32,65,32,98,121,116,101,32,105,110,100,101,120,32,116,117,112,108,101,32>>,{code,[],[<<123,48,44,50,125>>]},<<32,99,97,110,32,116,104,101,114,101,102,111,114,101,32,114,101,112,114,101,115,101,110,116,32,111,110,101,32,111,114,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,32,119,104,101,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,105,110,32,101,102,102,101,99,116,46,32,84,104,105,115,32,99,97,110,32,115,101,101,109,32,99,111,117,110,116,101,114,45,105,110,116,117,105,116,105,118,101,44,32,98,117,116,32,104,97,115,32,98,101,101,110,32,100,101,101,109,101,100,32,116,104,101,32,109,111,115,116,32,101,102,102,101,99,116,105,118,101,32,97,110,100,32,117,115,101,102,117,108,32,119,97,121,32,116,111,32,100,111,32,105,116,46,32,84,111,32,114,101,116,117,114,110,32,108,105,115,116,115,32,105,110,115,116,101,97,100,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,115,105,109,112,108,101,114,32,99,111,100,101,32,105,102,32,116,104,97,116,32,105,115,32,100,101,115,105,114,101,100,46,32,84,104,105,115,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<108,105,115,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,109,97,116,99,104,105,110,103,32,115,117,98,115,116,114,105,110,103,115,32,97,115,32,108,105,115,116,115,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,69,114,108,97,110,103,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<115,41,46,32,73,116,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,117,115,101,100,32,105,110,32,99,111,109,98,105,110,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,92,67,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,97,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,99,111,110,116,97,105,110,32,98,121,116,101,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,118,97,108,105,100,32,85,84,70,45,56,32,40,92,67,32,109,97,116,99,104,101,115,32,98,121,116,101,115,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,99,104,97,114,97,99,116,101,114,32,101,110,99,111,100,105,110,103,41,46,32,73,110,32,116,104,97,116,32,99,97,115,101,32,116,104,101,32>>,{code,[],[<<108,105,115,116>>]},<<32,99,97,112,116,117,114,105,110,103,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,116,104,101,32,115,97,109,101,32,116,121,112,101,115,32,111,102,32,116,117,112,108,101,115,32,116,104,97,116,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,35,99,104,97,114,97,99,116,101,114,115,95,116,111,95,108,105,115,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,105,99,111,100,101,58,99,104,97,114,97,99,116,101,114,115,95,116,111,95,108,105,115,116,47,50>>]}]},<<32,99,97,110,32,114,101,116,117,114,110,44,32,110,97,109,101,108,121,32,116,104,114,101,101,45,116,117,112,108,101,115,32,119,105,116,104,32,116,97,103,32>>,{code,[],[<<105,110,99,111,109,112,108,101,116,101>>]},<<32,111,114,32>>,{code,[],[<<101,114,114,111,114>>]},<<44,32,116,104,101,32,115,117,99,99,101,115,115,102,117,108,108,121,32,99,111,110,118,101,114,116,101,100,32,99,104,97,114,97,99,116,101,114,115,32,97,110,100,32,116,104,101,32,105,110,118,97,108,105,100,32,85,84,70,45,56,32,116,97,105,108,32,111,102,32,116,104,101,32,99,111,110,118,101,114,115,105,111,110,32,97,115,32,97,32,98,105,110,97,114,121,46,32,84,104,101,32,98,101,115,116,32,115,116,114,97,116,101,103,121,32,105,115,32,116,111,32,97,118,111,105,100,32,117,115,105,110,103,32,116,104,101,32,92,67,32,115,101,113,117,101,110,99,101,32,119,104,101,110,32,99,97,112,116,117,114,105,110,103,32,108,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,109,97,116,99,104,105,110,103,32,115,117,98,115,116,114,105,110,103,115,32,97,115,32,98,105,110,97,114,105,101,115,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,117,115,101,100,44,32,116,104,101,115,101,32,98,105,110,97,114,105,101,115,32,97,114,101,32,105,110,32,85,84,70,45,56,46,32,73,102,32,116,104,101,32,92,67,32,115,101,113,117,101,110,99,101,32,105,115,32,117,115,101,100,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,116,104,101,32,98,105,110,97,114,105,101,115,32,99,97,110,32,98,101,32,105,110,118,97,108,105,100,32,85,84,70,45,56,46>>]}]}]}]}]},{p,[],[<<73,110,32,103,101,110,101,114,97,108,44,32,115,117,98,112,97,116,116,101,114,110,115,32,116,104,97,116,32,119,101,114,101,32,110,111,116,32,97,115,115,105,103,110,101,100,32,97,32,118,97,108,117,101,32,105,110,32,116,104,101,32,109,97,116,99,104,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,45,49,44,48,125>>]},<<32,119,104,101,110,32>>,{code,[],[<<116,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<105,110,100,101,120>>]},<<46,32,85,110,97,115,115,105,103,110,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,116,104,101,32,101,109,112,116,121,32,98,105,110,97,114,121,32,111,114,32,108,105,115,116,44,32,114,101,115,112,101,99,116,105,118,101,108,121,44,32,102,111,114,32,111,116,104,101,114,32,114,101,116,117,114,110,32,116,121,112,101,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,58>>]},{pre,[],[{code,[],[<<34,46,42,40,40,63,60,70,79,79,62,97,98,100,100,41,124,97,40,46,46,100,41,41,46,42,34>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,116,104,114,101,101,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,119,104,101,114,101,32,116,104,101,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,112,111,115,105,116,105,111,110,32,100,101,116,101,114,109,105,110,101,115,32,116,104,101,32,111,114,100,101,114,32,105,110,32,116,104,101,32,114,101,115,117,108,116,44,32,104,101,110,99,101,32>>,{code,[],[<<40,40,63,60,70,79,79,62,97,98,100,100,41,124,97,40,46,46,100,41,41>>]},<<32,105,115,32,115,117,98,112,97,116,116,101,114,110,32,105,110,100,101,120,32,49,44,32>>,{code,[],[<<40,63,60,70,79,79,62,97,98,100,100,41>>]},<<32,105,115,32,115,117,98,112,97,116,116,101,114,110,32,105,110,100,101,120,32,50,44,32,97,110,100,32>>,{code,[],[<<40,46,46,100,41>>]},<<32,105,115,32,115,117,98,112,97,116,116,101,114,110,32,105,110,100,101,120,32,51,46,32,87,104,101,110,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,116,114,105,110,103,58>>]},{pre,[],[{code,[],[<<34,65,66,67,97,98,99,100,65,66,67,34>>]}]},{p,[],[<<116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,97,116,32,105,110,100,101,120,32,50,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,44,32,97,115,32,34,97,98,100,100,34,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,115,116,114,105,110,103,44,32,98,117,116,32,116,104,101,32,99,111,109,112,108,101,116,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,40,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,32>>,{code,[],[<<97,40,46,46,100,41>>]},<<41,46,32,84,104,101,32,115,117,98,112,97,116,116,101,114,110,32,97,116,32,105,110,100,101,120,32,50,32,105,115,32,116,104,101,114,101,102,111,114,101,32,117,110,97,115,115,105,103,110,101,100,32,97,110,100,32,116,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,48,44,49,48,125,44,123,51,44,52,125,44,123,45,49,44,48,125,44,123,52,44,51,125,93,125>>]}]},{p,[],[<<83,101,116,116,105,110,103,32,116,104,101,32,99,97,112,116,117,114,101,32>>,{code,[],[<<84,121,112,101>>]},<<32,116,111,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,103,105,118,101,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,60,60,34,65,66,67,97,98,99,100,65,66,67,34,62,62,44,60,60,34,97,98,99,100,34,62,62,44,60,60,62,62,44,60,60,34,98,99,100,34,62,62,93,125>>]}]},{p,[],[<<72,101,114,101,32,116,104,101,32,101,109,112,116,121,32,98,105,110,97,114,121,32,40>>,{code,[],[<<60,60,62,62>>]},<<41,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,117,110,97,115,115,105,103,110,101,100,32,115,117,98,112,97,116,116,101,114,110,46,32,73,110,32,116,104,101,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,99,97,115,101,44,32,115,111,109,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,97,116,99,104,105,110,103,32,105,115,32,116,104,101,114,101,102,111,114,101,32,108,111,115,116,44,32,97,115,32>>,{code,[],[<<60,60,62,62>>]},<<32,99,97,110,32,97,108,115,111,32,98,101,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,99,97,112,116,117,114,101,100,46>>]},{p,[],[<<73,102,32,100,105,102,102,101,114,101,110,116,105,97,116,105,111,110,32,98,101,116,119,101,101,110,32,101,109,112,116,121,32,109,97,116,99,104,101,115,32,97,110,100,32,110,111,110,45,101,120,105,115,116,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,105,115,32,110,101,99,101,115,115,97,114,121,44,32,117,115,101,32,116,104,101,32>>,{code,[],[<<116,121,112,101>>]},<<32>>,{code,[],[<<105,110,100,101,120>>]},<<32,97,110,100,32,100,111,32,116,104,101,32,99,111,110,118,101,114,115,105,111,110,32,116,111,32,116,104,101,32,102,105,110,97,108,32,116,121,112,101,32,105,110,32,69,114,108,97,110,103,32,99,111,100,101,46>>]},{p,[],[<<87,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,115,32,115,112,101,99,105,105,102,105,101,100,44,32,116,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,102,102,101,99,116,115,32,101,97,99,104,32,109,97,116,99,104,32,115,101,112,97,114,97,116,101,108,121,44,32,115,111,32,116,104,97,116,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,99,97,99,98,34,44,34,99,40,97,124,98,41,34,44,91,103,108,111,98,97,108,44,123,99,97,112,116,117,114,101,44,91,49,93,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,91,34,97,34,93,44,91,34,98,34,93,93,125>>]}]}]}]},{p,[],[<<70,111,114,32,97,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,111,112,116,105,111,110,115,32,111,110,108,121,32,97,102,102,101,99,116,105,110,103,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,115,116,101,112,44,32,115,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,52,49,57>>,signature => [{attribute,76,spec,{{run,3},[{type,76,bounded_fun,[{type,76,'fun',[{type,76,product,[{var,76,'Subject'},{var,76,'RE'},{var,76,'Options'}]},{type,76,union,[{type,76,tuple,[{atom,76,match},{var,76,'Captured'}]},{atom,77,match},{atom,78,nomatch},{type,79,tuple,[{atom,79,error},{var,79,'ErrType'}]}]}]},[{type,80,constraint,[{atom,80,is_subtype},[{var,80,'Subject'},{type,80,union,[{type,80,iodata,[]},{remote_type,80,[{atom,80,unicode},{atom,80,charlist},[]]}]}]]},{type,81,constraint,[{atom,81,is_subtype},[{var,81,'RE'},{type,81,union,[{user_type,81,mp,[]},{type,81,iodata,[]},{remote_type,81,[{atom,81,unicode},{atom,81,charlist},[]]}]}]]},{type,82,constraint,[{atom,82,is_subtype},[{var,82,'Options'},{type,82,list,[{var,82,'Option'}]}]]},{type,83,constraint,[{atom,83,is_subtype},[{var,83,'Option'},{type,83,union,[{atom,83,anchored},{atom,83,global},{atom,83,notbol},{atom,83,noteol},{atom,83,notempty},{atom,84,notempty_atstart},{atom,84,report_errors},{type,85,tuple,[{atom,85,offset},{type,85,non_neg_integer,[]}]},{type,86,tuple,[{atom,86,match_limit},{type,86,non_neg_integer,[]}]},{type,87,tuple,[{atom,87,match_limit_recursion},{type,87,non_neg_integer,[]}]},{type,88,tuple,[{atom,88,newline},{ann_type,88,[{var,88,'NLSpec'},{user_type,88,nl_spec,[]}]}]},{atom,89,bsr_anycrlf},{atom,89,bsr_unicode},{type,89,tuple,[{atom,89,capture},{var,89,'ValueSpec'}]},{type,90,tuple,[{atom,90,capture},{var,90,'ValueSpec'},{var,90,'Type'}]},{var,90,'CompileOpt'}]}]]},{type,91,constraint,[{atom,91,is_subtype},[{var,91,'Type'},{type,91,union,[{atom,91,index},{atom,91,list},{atom,91,binary}]}]]},{type,92,constraint,[{atom,92,is_subtype},[{var,92,'ValueSpec'},{type,92,union,[{atom,92,all},{atom,92,all_but_first},{atom,92,all_names},{atom,92,first},{atom,92,none},{var,92,'ValueList'}]}]]},{type,93,constraint,[{atom,93,is_subtype},[{var,93,'ValueList'},{type,93,list,[{var,93,'ValueID'}]}]]},{type,94,constraint,[{atom,94,is_subtype},[{var,94,'ValueID'},{type,94,union,[{type,94,integer,[]},{type,94,string,[]},{type,94,atom,[]}]}]]},{type,95,constraint,[{atom,95,is_subtype},[{var,95,'CompileOpt'},{user_type,95,compile_option,[]}]]},{type,96,constraint,[{atom,96,is_subtype},[{var,96,'Captured'},{type,96,union,[{type,96,list,[{var,96,'CaptureData'}]},{type,96,list,[{type,96,list,[{var,96,'CaptureData'}]}]}]}]]},{type,97,constraint,[{atom,97,is_subtype},[{var,97,'CaptureData'},{type,97,union,[{type,97,tuple,[{type,97,integer,[]},{type,97,integer,[]}]},{var,98,'ListConversionData'},{type,99,binary,[]}]}]]},{type,100,constraint,[{atom,100,is_subtype},[{var,100,'ListConversionData'},{type,100,union,[{type,100,string,[]},{type,101,tuple,[{atom,101,error},{type,101,string,[]},{type,101,binary,[]}]},{type,102,tuple,[{atom,102,incomplete},{type,102,string,[]},{type,102,binary,[]}]}]}]]},{type,103,constraint,[{atom,103,is_subtype},[{var,103,'ErrType'},{type,103,union,[{atom,103,match_limit},{atom,103,match_limit_recursion},{type,103,tuple,[{atom,103,compile},{var,103,'CompileErr'}]}]}]]},{type,104,constraint,[{atom,104,is_subtype},[{var,104,'CompileErr'},{type,104,tuple,[{ann_type,104,[{var,104,'ErrString'},{type,104,string,[]}]},{ann_type,104,[{var,104,'Position'},{type,104,non_neg_integer,[]}]}]}]]}]]}]}}]}},{{function,split,2},[{file,[114,101,46,101,114,108]},{location,153}],[<<115,112,108,105,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<115,112,108,105,116,40,83,117,98,106,101,99,116,44,32,82,69,44,32,91,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,57,57,52>>,signature => [{attribute,153,spec,{{split,2},[{type,153,bounded_fun,[{type,153,'fun',[{type,153,product,[{var,153,'Subject'},{var,153,'RE'}]},{var,153,'SplitList'}]},[{type,154,constraint,[{atom,154,is_subtype},[{var,154,'Subject'},{type,154,union,[{type,154,iodata,[]},{remote_type,154,[{atom,154,unicode},{atom,154,charlist},[]]}]}]]},{type,155,constraint,[{atom,155,is_subtype},[{var,155,'RE'},{type,155,union,[{user_type,155,mp,[]},{type,155,iodata,[]}]}]]},{type,156,constraint,[{atom,156,is_subtype},[{var,156,'SplitList'},{type,156,list,[{type,156,union,[{type,156,iodata,[]},{remote_type,156,[{atom,156,unicode},{atom,156,charlist},[]]}]}]}]]}]]}]}}]}},{{function,split,3},[{file,[114,101,46,101,114,108]},{location,166}],[<<115,112,108,105,116,47,51>>],#{<<101,110>> => [{p,[],[<<83,112,108,105,116,115,32,116,104,101,32,105,110,112,117,116,32,105,110,116,111,32,112,97,114,116,115,32,98,121,32,102,105,110,100,105,110,103,32,116,111,107,101,110,115,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,115,117,112,112,108,105,101,100,46,32,84,104,101,32,115,112,108,105,116,116,105,110,103,32,105,115,32,98,97,115,105,99,97,108,108,121,32,100,111,110,101,32,98,121,32,114,117,110,110,105,110,103,32,97,32,103,108,111,98,97,108,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,32,97,110,100,32,100,105,118,105,100,105,110,103,32,116,104,101,32,105,110,105,116,105,97,108,32,115,116,114,105,110,103,32,119,104,101,114,101,118,101,114,32,97,32,109,97,116,99,104,32,111,99,99,117,114,115,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,105,115,32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,104,101,32,111,117,116,112,117,116,46>>]},{p,[],[<<65,115,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,97,110,32>>,{code,[],[<<109,112,40,41>>]},<<32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,114,101,113,117,105,114,101,115,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,116,111,32,98,101,32,97,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<46,32,73,102,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,105,109,112,108,105,99,105,116,108,121,32,97,110,100,32,116,104,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,98,111,116,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,110,100,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,97,114,101,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<115,46>>]},{p,[],[<<84,104,101,32,114,101,115,117,108,116,32,105,115,32,103,105,118,101,110,32,97,115,32,97,32,108,105,115,116,32,111,102,32,34,115,116,114,105,110,103,115,34,44,32,116,104,101,32,112,114,101,102,101,114,114,101,100,32,100,97,116,97,32,116,121,112,101,32,115,112,101,99,105,102,105,101,100,32,105,110,32,111,112,116,105,111,110,32>>,{code,[],[<<114,101,116,117,114,110>>]},<<32,40,100,101,102,97,117,108,116,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<41,46>>]},{p,[],[<<73,102,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,32,97,115,32,119,101,108,108,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,110,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,34,44,34,103,34,93>>]}]},{p,[],[<<119,104,105,108,101>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,40,91,108,110,93,41,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,108,34,44,34,97,34,44,34,110,34,44,34,103,34,93>>]}]},{p,[],[<<84,104,101,32,116,101,120,116,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,40,109,97,114,107,101,100,32,98,121,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,41,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,108,105,115,116,32,119,104,101,114,101,32,105,116,32,119,97,115,32,102,111,117,110,100,46,32,84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,99,111,110,99,97,116,101,110,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,32,115,112,108,105,116,32,119,104,101,114,101,32,116,104,101,32,119,104,111,108,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,97,32,115,105,110,103,108,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,40,97,115,32,105,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,41,32,97,108,119,97,121,115,32,114,101,115,117,108,116,115,32,105,110,32,116,104,101,32,111,114,105,103,105,110,97,108,32,115,116,114,105,110,103,46>>]},{p,[],[<<65,115,32,116,104,101,114,101,32,105,115,32,110,111,32,109,97,116,99,104,105,110,103,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,102,111,114,32,116,104,101,32,108,97,115,116,32,112,97,114,116,32,105,110,32,116,104,101,32,101,120,97,109,112,108,101,32,40,116,104,101,32,34,103,34,41,44,32,110,111,116,104,105,110,103,32,105,115,32,105,110,115,101,114,116,101,100,32,97,102,116,101,114,32,116,104,97,116,46,32,84,111,32,109,97,107,101,32,116,104,101,32,103,114,111,117,112,32,111,102,32,115,116,114,105,110,103,115,32,97,110,100,32,116,104,101,32,112,97,114,116,115,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,109,111,114,101,32,111,98,118,105,111,117,115,44,32,111,110,101,32,99,97,110,32,117,115,101,32,111,112,116,105,111,110,32>>,{code,[],[<<103,114,111,117,112>>]},<<44,32,119,104,105,99,104,32,103,114,111,117,112,115,32,116,111,103,101,116,104,101,114,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,112,97,114,116,115,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,119,104,101,110,32,116,104,101,32,115,116,114,105,110,103,32,119,97,115,32,115,112,108,105,116,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,40,91,108,110,93,41,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,103,114,111,117,112,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,91,34,69,114,34,44,34,108,34,93,44,91,34,97,34,44,34,110,34,93,44,91,34,103,34,93,93>>]}]},{p,[],[<<72,101,114,101,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,102,105,114,115,116,32,109,97,116,99,104,101,100,32,116,104,101,32,34,108,34,44,32,99,97,117,115,105,110,103,32,34,69,114,34,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,112,97,114,116,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46,32,87,104,101,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,100,44,32,116,104,101,32,40,111,110,108,121,41,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,98,111,117,110,100,32,116,111,32,116,104,101,32,34,108,34,44,32,115,111,32,116,104,101,32,34,108,34,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,32,116,104,101,32,103,114,111,117,112,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,34,69,114,34,46,32,84,104,101,32,110,101,120,116,32,109,97,116,99,104,32,105,115,32,111,102,32,116,104,101,32,34,110,34,44,32,109,97,107,105,110,103,32,34,97,34,32,116,104,101,32,110,101,120,116,32,112,97,114,116,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32,65,115,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,105,115,32,98,111,117,110,100,32,116,111,32,115,117,98,115,116,114,105,110,103,32,34,110,34,32,105,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32,34,110,34,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,116,111,32,116,104,105,115,32,103,114,111,117,112,46,32,84,104,101,32,108,97,115,116,32,103,114,111,117,112,32,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,115,116,114,105,110,103,44,32,97,115,32,110,111,32,109,111,114,101,32,109,97,116,99,104,101,115,32,97,114,101,32,102,111,117,110,100,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,97,108,108,32,112,97,114,116,115,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,115,44,32,97,114,101,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32,116,104,101,32,102,117,110,99,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,110,34,44,91,93,93>>]}]},{p,[],[<<97,115,32,116,104,101,32,109,97,116,99,104,105,110,103,32,111,102,32,116,104,101,32,34,103,34,32,105,110,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,108,101,97,118,101,115,32,97,110,32,101,109,112,116,121,32,114,101,115,116,44,32,119,104,105,99,104,32,105,115,32,97,108,115,111,32,114,101,116,117,114,110,101,100,46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,100,105,102,102,101,114,115,32,102,114,111,109,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,115,112,108,105,116,32,102,117,110,99,116,105,111,110,32,105,110,32,80,101,114,108,44,32,119,104,101,114,101,32,101,109,112,116,121,32,115,116,114,105,110,103,115,32,97,116,32,116,104,101,32,101,110,100,32,97,114,101,32,98,121,32,100,101,102,97,117,108,116,32,114,101,109,111,118,101,100,46,32,84,111,32,103,101,116,32,116,104,101,32,34,116,114,105,109,109,105,110,103,34,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32,80,101,114,108,44,32,115,112,101,99,105,102,121,32>>,{code,[],[<<116,114,105,109>>]},<<32,97,115,32,97,110,32,111,112,116,105,111,110,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,116,114,105,109,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,110,34,93>>]}]},{p,[],[<<84,104,101,32,34,116,114,105,109,34,32,111,112,116,105,111,110,32,115,97,121,115,59,32,34,103,105,118,101,32,109,101,32,97,115,32,109,97,110,121,32,112,97,114,116,115,32,97,115,32,112,111,115,115,105,98,108,101,32,101,120,99,101,112,116,32,116,104,101,32,101,109,112,116,121,32,111,110,101,115,34,44,32,119,104,105,99,104,32,115,111,109,101,116,105,109,101,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,46,32,89,111,117,32,99,97,110,32,97,108,115,111,32,115,112,101,99,105,102,121,32,104,111,119,32,109,97,110,121,32,112,97,114,116,115,32,121,111,117,32,119,97,110,116,44,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,112,97,114,116,115,44>>]},<<78>>,{code,[],[<<125>>]},<<58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,123,112,97,114,116,115,44,50,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,110,103,34,93>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,108,97,115,116,32,112,97,114,116,32,105,115,32,34,97,110,103,34,44,32,110,111,116,32,34,97,110,34,44,32,97,115,32,115,112,108,105,116,116,105,110,103,32,119,97,115,32,115,112,101,99,105,102,105,101,100,32,105,110,116,111,32,116,119,111,32,112,97,114,116,115,44,32,97,110,100,32,116,104,101,32,115,112,108,105,116,116,105,110,103,32,115,116,111,112,115,32,119,104,101,110,32,101,110,111,117,103,104,32,112,97,114,116,115,32,97,114,101,32,103,105,118,101,110,44,32,119,104,105,99,104,32,105,115,32,119,104,121,32,116,104,101,32,114,101,115,117,108,116,32,100,105,102,102,101,114,115,32,102,114,111,109,32,116,104,97,116,32,111,102,32>>,{code,[],[<<116,114,105,109>>]},<<46>>]},{p,[],[<<77,111,114,101,32,116,104,97,110,32,116,104,114,101,101,32,112,97,114,116,115,32,97,114,101,32,110,111,116,32,112,111,115,115,105,98,108,101,32,119,105,116,104,32,116,104,105,115,32,105,110,100,97,116,97,44,32,115,111>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,123,112,97,114,116,115,44,52,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,116,104,101,32,100,101,102,97,117,108,116,44,32,119,104,105,99,104,32,105,115,32,116,111,32,98,101,32,118,105,101,119,101,100,32,97,115,32,34,97,110,32,105,110,102,105,110,105,116,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,34,46>>]},{p,[],[<<83,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<48>>]},<<32,97,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,111,112,116,105,111,110,32>>,{code,[],[<<116,114,105,109>>]},<<46,32,73,102,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,99,97,112,116,117,114,101,100,44,32,101,109,112,116,121,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,109,97,116,99,104,101,100,32,97,116,32,116,104,101,32,101,110,100,32,97,114,101,32,97,108,115,111,32,115,116,114,105,112,112,101,100,32,102,114,111,109,32,116,104,101,32,114,101,115,117,108,116,32,105,102,32>>,{code,[],[<<116,114,105,109>>]},<<32,111,114,32>>,{code,[],[<<123,112,97,114,116,115,44,48,125>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<116,114,105,109>>]},<<32,98,101,104,97,118,105,111,114,32,99,111,114,114,101,115,112,111,110,100,115,32,101,120,97,99,116,108,121,32,116,111,32,116,104,101,32,80,101,114,108,32,100,101,102,97,117,108,116,46,32>>,{code,[],[<<123,112,97,114,116,115,44,78,125>>]},<<44,32,119,104,101,114,101,32,78,32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,44,32,99,111,114,114,101,115,112,111,110,100,115,32,101,120,97,99,116,108,121,32,116,111,32,116,104,101,32,80,101,114,108,32,98,101,104,97,118,105,111,114,32,119,105,116,104,32,97,32,112,111,115,105,116,105,118,101,32,110,117,109,101,114,105,99,97,108,32,116,104,105,114,100,32,112,97,114,97,109,101,116,101,114,46,32,84,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32>>,{code,[],[<<115,112,108,105,116,47,51>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,80,101,114,108,32,98,101,104,97,118,105,111,114,32,119,104,101,110,32,97,32,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,116,104,101,32,116,104,105,114,100,32,112,97,114,97,109,101,116,101,114,32,102,111,114,32,116,104,101,32,80,101,114,108,32,114,111,117,116,105,110,101,46>>]},{p,[],[<<83,117,109,109,97,114,121,32,111,102,32,111,112,116,105,111,110,115,32,110,111,116,32,112,114,101,118,105,111,117,115,108,121,32,100,101,115,99,114,105,98,101,100,32,102,111,114,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<114,117,110,47,51>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<123,114,101,116,117,114,110,44,82,101,116,117,114,110,84,121,112,101,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,104,111,119,32,116,104,101,32,112,97,114,116,115,32,111,102,32,116,104,101,32,111,114,105,103,105,110,97,108,32,115,116,114,105,110,103,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,108,105,115,116,46,32,86,97,108,105,100,32,116,121,112,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<105,111,100,97,116,97>>]}]},{dd,[],[{p,[],[<<84,104,101,32,118,97,114,105,97,110,116,32,111,102,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<32,116,104,97,116,32,103,105,118,101,115,32,116,104,101,32,108,101,97,115,116,32,99,111,112,121,105,110,103,32,111,102,32,100,97,116,97,32,119,105,116,104,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,40,111,102,116,101,110,32,97,32,98,105,110,97,114,121,44,32,98,117,116,32,100,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,105,116,41,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<65,108,108,32,112,97,114,116,115,32,114,101,116,117,114,110,101,100,32,97,115,32,98,105,110,97,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<108,105,115,116>>]}]},{dd,[],[{p,[],[<<65,108,108,32,112,97,114,116,115,32,114,101,116,117,114,110,101,100,32,97,115,32,108,105,115,116,115,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,34,115,116,114,105,110,103,115,34,41,46>>]}]}]}]},{dt,[],[{code,[],[<<103,114,111,117,112>>]}]},{dd,[],[{p,[],[<<71,114,111,117,112,115,32,116,111,103,101,116,104,101,114,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,112,97,114,116,115,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,111,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,102,114,111,109,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,105,110,32,116,104,105,115,32,99,97,115,101,32,97,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,111,102,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<115,46,32,69,97,99,104,32,115,117,98,108,105,115,116,32,98,101,103,105,110,115,32,119,105,116,104,32,116,104,101,32,115,116,114,105,110,103,32,112,105,99,107,101,100,32,111,117,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,102,111,108,108,111,119,101,100,32,98,121,32,116,104,101,32,112,97,114,116,115,32,109,97,116,99,104,105,110,103,32,101,97,99,104,32,111,102,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,111,114,100,101,114,32,111,102,32,111,99,99,117,114,114,101,110,99,101,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,112,97,114,116,115,44,78,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,105,115,32,116,111,32,98,101,32,115,112,108,105,116,32,105,110,116,111,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,105,115,32,116,111,32,98,101,32,97,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,32,102,111,114,32,97,32,115,112,101,99,105,102,105,99,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,44,32,97,110,100,32>>,{code,[],[<<105,110,102,105,110,105,116,121>>]},<<32,102,111,114,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,112,111,115,115,105,98,108,101,32,40,116,104,101,32,100,101,102,97,117,108,116,41,46,32,83,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,112,97,114,116,115,44,48,125>>]},<<32,103,105,118,101,115,32,97,115,32,109,97,110,121,32,112,97,114,116,115,32,97,115,32,112,111,115,115,105,98,108,101,32,100,105,115,114,101,103,97,114,100,105,110,103,32,101,109,112,116,121,32,112,97,114,116,115,32,97,116,32,116,104,101,32,101,110,100,44,32,116,104,101,32,115,97,109,101,32,97,115,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<116,114,105,109>>]},<<46>>]}]},{dt,[],[{code,[],[<<116,114,105,109>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,101,109,112,116,121,32,112,97,114,116,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,114,101,115,117,108,116,32,108,105,115,116,32,97,114,101,32,116,111,32,98,101,32,100,105,115,114,101,103,97,114,100,101,100,46,32,84,104,101,32,115,97,109,101,32,97,115,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,112,97,114,116,115,44,48,125>>]},<<46,32,84,104,105,115,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32>>,{code,[],[<<115,112,108,105,116>>]},<<32,98,117,105,108,116,45,105,110,32,102,117,110,99,116,105,111,110,32,105,110,32,80,101,114,108,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,49,48,48,51>>,signature => [{attribute,166,spec,{{split,3},[{type,166,bounded_fun,[{type,166,'fun',[{type,166,product,[{var,166,'Subject'},{var,166,'RE'},{var,166,'Options'}]},{var,166,'SplitList'}]},[{type,167,constraint,[{atom,167,is_subtype},[{var,167,'Subject'},{type,167,union,[{type,167,iodata,[]},{remote_type,167,[{atom,167,unicode},{atom,167,charlist},[]]}]}]]},{type,168,constraint,[{atom,168,is_subtype},[{var,168,'RE'},{type,168,union,[{user_type,168,mp,[]},{type,168,iodata,[]},{remote_type,168,[{atom,168,unicode},{atom,168,charlist},[]]}]}]]},{type,169,constraint,[{atom,169,is_subtype},[{var,169,'Options'},{type,169,list,[{var,169,'Option'}]}]]},{type,170,constraint,[{atom,170,is_subtype},[{var,170,'Option'},{type,170,union,[{atom,170,anchored},{atom,170,notbol},{atom,170,noteol},{atom,170,notempty},{atom,170,notempty_atstart},{type,171,tuple,[{atom,171,offset},{type,171,non_neg_integer,[]}]},{type,171,tuple,[{atom,171,newline},{user_type,171,nl_spec,[]}]},{type,172,tuple,[{atom,172,match_limit},{type,172,non_neg_integer,[]}]},{type,173,tuple,[{atom,173,match_limit_recursion},{type,173,non_neg_integer,[]}]},{atom,174,bsr_anycrlf},{atom,174,bsr_unicode},{type,174,tuple,[{atom,174,return},{var,174,'ReturnType'}]},{type,175,tuple,[{atom,175,parts},{var,175,'NumParts'}]},{atom,175,group},{atom,175,trim},{var,175,'CompileOpt'}]}]]},{type,176,constraint,[{atom,176,is_subtype},[{var,176,'NumParts'},{type,176,union,[{type,176,non_neg_integer,[]},{atom,176,infinity}]}]]},{type,177,constraint,[{atom,177,is_subtype},[{var,177,'ReturnType'},{type,177,union,[{atom,177,iodata},{atom,177,list},{atom,177,binary}]}]]},{type,178,constraint,[{atom,178,is_subtype},[{var,178,'CompileOpt'},{user_type,178,compile_option,[]}]]},{type,179,constraint,[{atom,179,is_subtype},[{var,179,'SplitList'},{type,179,union,[{type,179,list,[{var,179,'RetData'}]},{type,179,list,[{var,179,'GroupedRetData'}]}]}]]},{type,180,constraint,[{atom,180,is_subtype},[{var,180,'GroupedRetData'},{type,180,list,[{var,180,'RetData'}]}]]},{type,181,constraint,[{atom,181,is_subtype},[{var,181,'RetData'},{type,181,union,[{type,181,iodata,[]},{remote_type,181,[{atom,181,unicode},{atom,181,charlist},[]]},{type,181,binary,[]},{type,181,list,[]}]}]]}]]}]}}]}},{{type,mp,0},[{file,[114,101,46,101,114,108]},{location,23}],[<<45,116,121,112,101,32,109,112,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<79,112,97,113,117,101,32,100,97,116,97,32,116,121,112,101,32,99,111,110,116,97,105,110,105,110,103,32,97,32,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32>>,{code,[],[<<109,112,40,41>>]},<<32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,97,32,116,117,112,108,101,40,41,32,104,97,118,105,110,103,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<114,101,95,112,97,116,116,101,114,110>>]},<<32,97,115,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,116,111,32,97,108,108,111,119,32,102,111,114,32,109,97,116,99,104,105,110,103,32,105,110,32,103,117,97,114,100,115,46,32,84,104,101,32,97,114,105,116,121,32,111,102,32,116,104,101,32,116,117,112,108,101,32,111,114,32,116,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,111,116,104,101,114,32,102,105,101,108,100,115,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,102,117,116,117,114,101,32,69,114,108,97,110,103,47,79,84,80,32,114,101,108,101,97,115,101,115,46>>]}]},#{signature => [{attribute,23,type,{mp,{type,23,tuple,[{atom,23,re_pattern},{var,23,'_'},{var,23,'_'},{var,23,'_'},{var,23,'_'}]},[]}}]}},{{type,nl_spec,0},[{file,[114,101,46,101,114,108]},{location,25}],[<<45,116,121,112,101,32,110,108,95,115,112,101,99,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,25,type,{nl_spec,{type,25,union,[{atom,25,cr},{atom,25,crlf},{atom,25,lf},{atom,25,anycrlf},{atom,25,any}]},[]}}]}},{{type,compile_option,0},[{file,[114,101,46,101,114,108]},{location,27}],[<<45,116,121,112,101,32,99,111,109,112,105,108,101,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,27,type,{compile_option,{type,27,union,[{atom,27,unicode},{atom,27,anchored},{atom,27,caseless},{atom,27,dollar_endonly},{atom,28,dotall},{atom,28,extended},{atom,28,firstline},{atom,28,multiline},{atom,29,no_auto_capture},{atom,29,dupnames},{atom,29,ungreedy},{type,30,tuple,[{atom,30,newline},{user_type,30,nl_spec,[]}]},{atom,31,bsr_anycrlf},{atom,31,bsr_unicode},{atom,32,no_start_optimize},{atom,32,ucp},{atom,32,never_utf}]},[]}}]}}]}. \ No newline at end of file
+{docs_v1,[{file,[114,101,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<84,104,105,115,32,109,111,100,117,108,101,32,99,111,110,116,97,105,110,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,32,102,111,114,32,115,116,114,105,110,103,115,32,97,110,100,32,98,105,110,97,114,105,101,115,46>>]},{p,[],[<<84,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,101,103,101,120,112,95,115,121,110,116,97,120>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110>>]},<<32,115,121,110,116,97,120,32,97,110,100,32,115,101,109,97,110,116,105,99,115,32,114,101,115,101,109,98,108,101,32,116,104,97,116,32,111,102,32,80,101,114,108,46>>]},{p,[],[<<84,104,101,32,109,97,116,99,104,105,110,103,32,97,108,103,111,114,105,116,104,109,115,32,111,102,32,116,104,101,32,108,105,98,114,97,114,121,32,97,114,101,32,98,97,115,101,100,32,111,110,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,44,32,98,117,116,32,110,111,116,32,97,108,108,32,111,102,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,32,105,115,32,105,110,116,101,114,102,97,99,101,100,32,97,110,100,32,115,111,109,101,32,112,97,114,116,115,32,111,102,32,116,104,101,32,108,105,98,114,97,114,121,32,103,111,32,98,101,121,111,110,100,32,119,104,97,116,32,80,67,82,69,32,111,102,102,101,114,115,46,32,67,117,114,114,101,110,116,108,121,32,80,67,82,69,32,118,101,114,115,105,111,110,32,56,46,52,48,32,40,114,101,108,101,97,115,101,32,100,97,116,101,32,50,48,49,55,45,48,49,45,49,49,41,32,105,115,32,117,115,101,100,46,32,84,104,101,32,115,101,99,116,105,111,110,115,32,111,102,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,116,104,97,116,32,97,114,101,32,114,101,108,101,118,97,110,116,32,116,111,32,116,104,105,115,32,109,111,100,117,108,101,32,97,114,101,32,105,110,99,108,117,100,101,100,32,104,101,114,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,108,105,116,101,114,97,108,32,115,121,110,116,97,120,32,102,111,114,32,115,116,114,105,110,103,115,32,117,115,101,115,32,116,104,101,32,34,92,34,32,40,98,97,99,107,115,108,97,115,104,41,32,99,104,97,114,97,99,116,101,114,32,97,115,32,97,110,32,101,115,99,97,112,101,32,99,111,100,101,46,32,89,111,117,32,110,101,101,100,32,116,111,32,101,115,99,97,112,101,32,98,97,99,107,115,108,97,115,104,101,115,32,105,110,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,115,44,32,98,111,116,104,32,105,110,32,121,111,117,114,32,99,111,100,101,32,97,110,100,32,105,110,32,116,104,101,32,115,104,101,108,108,44,32,119,105,116,104,32,97,110,32,101,120,116,114,97,32,98,97,99,107,115,108,97,115,104,44,32,116,104,97,116,32,105,115,44,32,34,92,92,34,46>>]}]},{a,[{id,<<114,101,103,101,120,112,95,115,121,110,116,97,120>>}],[]},{h2,[],[<<80,101,114,108,45,76,105,107,101,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,32,83,121,110,116,97,120>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,32,99,111,110,116,97,105,110,32,114,101,102,101,114,101,110,99,101,32,109,97,116,101,114,105,97,108,32,102,111,114,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,117,115,101,100,32,98,121,32,116,104,105,115,32,109,111,100,117,108,101,46,32,84,104,101,32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32,98,97,115,101,100,32,111,110,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,44,32,119,105,116,104,32,99,104,97,110,103,101,115,32,119,104,101,114,101,32,116,104,105,115,32,109,111,100,117,108,101,32,98,101,104,97,118,101,115,32,100,105,102,102,101,114,101,110,116,108,121,32,116,111,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,46>>]},{a,[{id,<<114,101,103,101,120,112,95,115,121,110,116,97,120,95,100,101,116,97,105,108,115>>}],[]},{h2,[],[<<80,67,82,69,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,32,68,101,116,97,105,108,115>>]},{p,[],[<<84,104,101,32,115,121,110,116,97,120,32,97,110,100,32,115,101,109,97,110,116,105,99,115,32,111,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,67,82,69,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,100,101,116,97,105,108,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,46,32,80,101,114,108,39,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,105,116,115,32,111,119,110,32,100,111,99,117,109,101,110,116,97,116,105,111,110,44,32,97,110,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,103,101,110,101,114,97,108,32,97,114,101,32,99,111,118,101,114,101,100,32,105,110,32,109,97,110,121,32,98,111,111,107,115,44,32,115,111,109,101,32,119,105,116,104,32,99,111,112,105,111,117,115,32,101,120,97,109,112,108,101,115,46,32,74,101,102,102,114,101,121,32,70,114,105,101,100,108,39,115,32,34,77,97,115,116,101,114,105,110,103,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,115,34,44,32,112,117,98,108,105,115,104,101,100,32,98,121,32,79,39,82,101,105,108,108,121,44,32,99,111,118,101,114,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,103,114,101,97,116,32,100,101,116,97,105,108,46,32,84,104,105,115,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,116,104,101,32,80,67,82,69,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,105,115,32,105,110,116,101,110,100,101,100,32,97,115,32,114,101,102,101,114,101,110,99,101,32,109,97,116,101,114,105,97,108,46>>]},{p,[],[<<84,104,101,32,114,101,102,101,114,101,110,99,101,32,109,97,116,101,114,105,97,108,32,105,115,32,100,105,118,105,100,101,100,32,105,110,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,112,101,99,105,97,108,32,83,116,97,114,116,45,111,102,45,80,97,116,116,101,114,110,32,73,116,101,109,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,104,97,114,97,99,116,101,114,115,32,97,110,100,32,77,101,116,97,99,104,97,114,97,99,116,101,114,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<66,97,99,107,115,108,97,115,104>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,105,114,99,117,109,102,108,101,120,32,97,110,100,32,68,111,108,108,97,114>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<70,117,108,108,32,83,116,111,112,32,40,80,101,114,105,111,100,44,32,68,111,116,41,32,97,110,100,32,92,78>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,54>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<77,97,116,99,104,105,110,103,32,97,32,83,105,110,103,108,101,32,68,97,116,97,32,85,110,105,116>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,55>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,113,117,97,114,101,32,66,114,97,99,107,101,116,115,32,97,110,100,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,56>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,111,115,105,120,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,57>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<86,101,114,116,105,99,97,108,32,66,97,114>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<73,110,116,101,114,110,97,108,32,79,112,116,105,111,110,32,83,101,116,116,105,110,103>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,97,109,101,100,32,83,117,98,112,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,52>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<82,101,112,101,116,105,116,105,111,110>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,53>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<65,116,111,109,105,99,32,71,114,111,117,112,105,110,103,32,97,110,100,32,80,111,115,115,101,115,115,105,118,101,32,81,117,97,110,116,105,102,105,101,114,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,54>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,55>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<65,115,115,101,114,116,105,111,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,56>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,111,110,100,105,116,105,111,110,97,108,32,83,117,98,112,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,57>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,111,109,109,101,110,116,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<82,101,99,117,114,115,105,118,101,32,80,97,116,116,101,114,110,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115,32,97,115,32,83,117,98,114,111,117,116,105,110,101,115>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<79,110,105,103,117,114,117,109,97,32,83,117,98,114,111,117,116,105,110,101,32,83,121,110,116,97,120>>]}]},{li,[],[{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,67,111,110,116,114,111,108>>]}]}]},{a,[{id,<<115,101,99,116,49>>}],[]},{h2,[],[<<83,112,101,99,105,97,108,32,83,116,97,114,116,45,111,102,45,80,97,116,116,101,114,110,32,73,116,101,109,115>>]},{p,[],[<<83,111,109,101,32,111,112,116,105,111,110,115,32,116,104,97,116,32,99,97,110,32,98,101,32,112,97,115,115,101,100,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,115,112,101,99,105,97,108,32,105,116,101,109,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,46,32,84,104,101,115,101,32,97,114,101,32,110,111,116,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,44,32,98,117,116,32,97,114,101,32,112,114,111,118,105,100,101,100,32,116,111,32,109,97,107,101,32,116,104,101,115,101,32,111,112,116,105,111,110,115,32,97,99,99,101,115,115,105,98,108,101,32,116,111,32,112,97,116,116,101,114,110,32,119,114,105,116,101,114,115,32,119,104,111,32,97,114,101,32,110,111,116,32,97,98,108,101,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,112,114,111,103,114,97,109,32,116,104,97,116,32,112,114,111,99,101,115,115,101,115,32,116,104,101,32,112,97,116,116,101,114,110,46,32,65,110,121,32,110,117,109,98,101,114,32,111,102,32,116,104,101,115,101,32,105,116,101,109,115,32,99,97,110,32,97,112,112,101,97,114,44,32,98,117,116,32,116,104,101,121,32,109,117,115,116,32,97,108,108,32,98,101,32,116,111,103,101,116,104,101,114,32,114,105,103,104,116,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,115,116,114,105,110,103,44,32,97,110,100,32,116,104,101,32,108,101,116,116,101,114,115,32,109,117,115,116,32,98,101,32,105,110,32,117,112,112,101,114,32,99,97,115,101,46>>]},{p,[],[{em,[],[<<85,84,70,32,83,117,112,112,111,114,116>>]}]},{p,[],[<<85,110,105,99,111,100,101,32,115,117,112,112,111,114,116,32,105,115,32,98,97,115,105,99,97,108,108,121,32,85,84,70,45,56,32,98,97,115,101,100,46,32,84,111,32,117,115,101,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,44,32,121,111,117,32,101,105,116,104,101,114,32,99,97,108,108,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,111,114,32,116,104,101,32,112,97,116,116,101,114,110,32,109,117,115,116,32,115,116,97,114,116,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,115,101,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,115,58>>]},{pre,[],[{code,[],[<<40,42,85,84,70,56,41,10,40,42,85,84,70,41>>]}]},{p,[],[<<66,111,116,104,32,111,112,116,105,111,110,115,32,103,105,118,101,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,44,32,116,104,101,32,105,110,112,117,116,32,115,116,114,105,110,103,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,85,84,70,45,56,46,32,78,111,116,105,99,101,32,116,104,97,116,32,119,105,116,104,32,116,104,101,115,101,32,105,110,115,116,114,117,99,116,105,111,110,115,44,32,116,104,101,32,97,117,116,111,109,97,116,105,99,32,99,111,110,118,101,114,115,105,111,110,32,111,102,32,108,105,115,116,115,32,116,111,32,85,84,70,45,56,32,105,115,32,110,111,116,32,112,101,114,102,111,114,109,101,100,32,98,121,32,116,104,101,32>>,{code,[],[<<114,101>>]},<<32,102,117,110,99,116,105,111,110,115,46,32,84,104,101,114,101,102,111,114,101,44,32,117,115,105,110,103,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,105,115,32,110,111,116,32,114,101,99,111,109,109,101,110,100,101,100,46,32,65,100,100,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,119,104,101,110,32,114,117,110,110,105,110,103,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<83,111,109,101,32,97,112,112,108,105,99,97,116,105,111,110,115,32,116,104,97,116,32,97,108,108,111,119,32,116,104,101,105,114,32,117,115,101,114,115,32,116,111,32,115,117,112,112,108,121,32,112,97,116,116,101,114,110,115,32,99,97,110,32,119,105,115,104,32,116,111,32,114,101,115,116,114,105,99,116,32,116,104,101,109,32,116,111,32,110,111,110,45,85,84,70,32,100,97,116,97,32,102,111,114,32,115,101,99,117,114,105,116,121,32,114,101,97,115,111,110,115,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<110,101,118,101,114,95,117,116,102>>]},<<32,105,115,32,115,101,116,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,44,32,40,42,85,84,70,41,44,32,97,110,100,32,115,111,32,111,110,44,32,97,114,101,32,110,111,116,32,97,108,108,111,119,101,100,44,32,97,110,100,32,116,104,101,105,114,32,97,112,112,101,97,114,97,110,99,101,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,46>>]},{p,[],[{em,[],[<<85,110,105,99,111,100,101,32,80,114,111,112,101,114,116,121,32,83,117,112,112,111,114,116>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,97,110,111,116,104,101,114,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,32,116,104,97,116,32,99,97,110,32,97,112,112,101,97,114,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,42,85,67,80,41>>]}]},{p,[],[<<84,104,105,115,32,104,97,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<58,32,105,116,32,99,97,117,115,101,115,32,115,101,113,117,101,110,99,101,115,32,115,117,99,104,32,97,115,32,92,100,32,97,110,100,32,92,119,32,116,111,32,117,115,101,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,116,111,32,100,101,116,101,114,109,105,110,101,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,44,32,105,110,115,116,101,97,100,32,111,102,32,114,101,99,111,103,110,105,122,105,110,103,32,111,110,108,121,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,99,111,100,101,115,32,60,32,50,53,54,32,116,104,114,111,117,103,104,32,97,32,108,111,111,107,117,112,32,116,97,98,108,101,46>>]},{p,[],[{em,[],[<<68,105,115,97,98,108,105,110,103,32,83,116,97,114,116,117,112,32,79,112,116,105,109,105,122,97,116,105,111,110,115>>]}]},{p,[],[<<73,102,32,97,32,112,97,116,116,101,114,110,32,115,116,97,114,116,115,32,119,105,116,104,32>>,{code,[],[<<40,42,78,79,95,83,84,65,82,84,95,79,80,84,41>>]},<<44,32,105,116,32,104,97,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]},<<32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46>>]},{p,[],[{em,[],[<<78,101,119,108,105,110,101,32,67,111,110,118,101,110,116,105,111,110,115>>]}]},{a,[{id,<<110,101,119,108,105,110,101,95,99,111,110,118,101,110,116,105,111,110,115>>}],[]},{p,[],[<<80,67,82,69,32,115,117,112,112,111,114,116,115,32,102,105,118,101,32,99,111,110,118,101,110,116,105,111,110,115,32,102,111,114,32,105,110,100,105,99,97,116,105,110,103,32,108,105,110,101,32,98,114,101,97,107,115,32,105,110,32,115,116,114,105,110,103,115,58,32,97,32,115,105,110,103,108,101,32,67,82,32,40,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,41,32,99,104,97,114,97,99,116,101,114,44,32,97,32,115,105,110,103,108,101,32,76,70,32,40,108,105,110,101,32,102,101,101,100,41,32,99,104,97,114,97,99,116,101,114,44,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,44,32,97,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,112,114,101,99,101,100,105,110,103,44,32,97,110,100,32,97,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,46>>]},{p,[],[<<65,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,32,99,97,110,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,115,116,97,114,116,105,110,103,32,97,32,112,97,116,116,101,114,110,32,115,116,114,105,110,103,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,118,101,32,115,101,113,117,101,110,99,101,115,58>>]},{dl,[],[{dt,[],[<<40,42,67,82,41>>]},{dd,[],[<<67,97,114,114,105,97,103,101,32,114,101,116,117,114,110>>]},{dt,[],[<<40,42,76,70,41>>]},{dd,[],[<<76,105,110,101,32,102,101,101,100>>]},{dt,[],[<<40,42,67,82,76,70,41>>]},{dd,[],[<<62,67,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,102,111,108,108,111,119,101,100,32,98,121,32,108,105,110,101,32,102,101,101,100>>]},{dt,[],[<<40,42,65,78,89,67,82,76,70,41>>]},{dd,[],[<<65,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,97,98,111,118,101>>]},{dt,[],[<<40,42,65,78,89,41>>]},{dd,[],[<<65,108,108,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,115>>]}]},{p,[],[<<84,104,101,115,101,32,111,118,101,114,114,105,100,101,32,116,104,101,32,100,101,102,97,117,108,116,32,97,110,100,32,116,104,101,32,111,112,116,105,111,110,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,99,104,97,110,103,101,115,32,116,104,101,32,99,111,110,118,101,110,116,105,111,110,32,116,111,32,67,82,58>>]},{pre,[],[{code,[],[<<40,42,67,82,41,97,46,98>>]}]},{p,[],[<<84,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32>>,{code,[],[<<97,92,110,98>>]},<<44,32,97,115,32,76,70,32,105,115,32,110,111,32,108,111,110,103,101,114,32,97,32,110,101,119,108,105,110,101,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,111,102,32,116,104,101,109,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,32,108,97,115,116,32,111,110,101,32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,32,97,102,102,101,99,116,115,32,119,104,101,114,101,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,32,116,114,117,101,46,32,73,116,32,97,108,115,111,32,97,102,102,101,99,116,115,32,116,104,101,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,111,102,32,116,104,101,32,100,111,116,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,119,104,101,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,105,115,32,110,111,116,32,115,101,116,44,32,97,110,100,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,92,78,46,32,72,111,119,101,118,101,114,44,32,105,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,119,104,97,116,32,116,104,101,32,92,82,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,109,97,116,99,104,101,115,46,32,66,121,32,100,101,102,97,117,108,116,44,32,116,104,105,115,32,105,115,32,97,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,44,32,102,111,114,32,80,101,114,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,59,32,115,101,101,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,92,82,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,101,119,108,105,110,101,95,115,101,113,117,101,110,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,101,119,108,105,110,101,32,83,101,113,117,101,110,99,101,115>>]},<<46,32,65,32,99,104,97,110,103,101,32,111,102,32,116,104,101,32,92,82,32,115,101,116,116,105,110,103,32,99,97,110,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,97,32,99,104,97,110,103,101,32,111,102,32,116,104,101,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,46>>]},{p,[],[{em,[],[<<83,101,116,116,105,110,103,32,77,97,116,99,104,32,97,110,100,32,82,101,99,117,114,115,105,111,110,32,76,105,109,105,116,115>>]}]},{p,[],[<<84,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,99,97,110,32,115,101,116,32,97,32,108,105,109,105,116,32,111,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,116,104,101,32,105,110,116,101,114,110,97,108,32,109,97,116,99,104,40,41,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,97,110,100,32,111,110,32,116,104,101,32,109,97,120,105,109,117,109,32,100,101,112,116,104,32,111,102,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,115,46,32,84,104,101,115,101,32,102,97,99,105,108,105,116,105,101,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,116,111,32,99,97,116,99,104,32,114,117,110,97,119,97,121,32,109,97,116,99,104,101,115,32,116,104,97,116,32,97,114,101,32,112,114,111,118,111,107,101,100,32,98,121,32,112,97,116,116,101,114,110,115,32,119,105,116,104,32,104,117,103,101,32,109,97,116,99,104,105,110,103,32,116,114,101,101,115,32,40,97,32,116,121,112,105,99,97,108,32,101,120,97,109,112,108,101,32,105,115,32,97,32,112,97,116,116,101,114,110,32,119,105,116,104,32,110,101,115,116,101,100,32,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,115,41,32,97,110,100,32,116,111,32,97,118,111,105,100,32,114,117,110,110,105,110,103,32,111,117,116,32,111,102,32,115,121,115,116,101,109,32,115,116,97,99,107,32,98,121,32,116,111,111,32,109,117,99,104,32,114,101,99,117,114,115,105,111,110,46,32,87,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,108,105,109,105,116,115,32,105,115,32,114,101,97,99,104,101,100,44,32>>,{code,[],[<<112,99,114,101,95,101,120,101,99,40,41>>]},<<32,103,105,118,101,115,32,97,110,32,101,114,114,111,114,32,114,101,116,117,114,110,46,32,84,104,101,32,108,105,109,105,116,115,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,105,116,101,109,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,111,114,109,115,58>>]},{pre,[],[{code,[],[<<40,42,76,73,77,73,84,95,77,65,84,67,72,61,100,41,10,40,42,76,73,77,73,84,95,82,69,67,85,82,83,73,79,78,61,100,41>>]}]},{p,[],[<<72,101,114,101,32,100,32,105,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,100,101,99,105,109,97,108,32,100,105,103,105,116,115,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,115,101,116,116,105,110,103,32,109,117,115,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,116,104,101,32,118,97,108,117,101,32,115,101,116,32,98,121,32,116,104,101,32,99,97,108,108,101,114,32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,102,111,114,32,105,116,32,116,111,32,104,97,118,101,32,97,110,121,32,101,102,102,101,99,116,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,112,97,116,116,101,114,110,32,119,114,105,116,101,114,32,99,97,110,32,108,111,119,101,114,32,116,104,101,32,108,105,109,105,116,32,115,101,116,32,98,121,32,116,104,101,32,112,114,111,103,114,97,109,109,101,114,44,32,98,117,116,32,110,111,116,32,114,97,105,115,101,32,105,116,46,32,73,102,32,116,104,101,114,101,32,105,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,101,116,116,105,110,103,32,111,102,32,111,110,101,32,111,102,32,116,104,101,115,101,32,108,105,109,105,116,115,44,32,116,104,101,32,108,111,119,101,114,32,118,97,108,117,101,32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,102,111,114,32,98,111,116,104,32,116,104,101,32,108,105,109,105,116,115,32,105,115,32,49,48,44,48,48,48,44,48,48,48,32,105,110,32,116,104,101,32,69,114,108,97,110,103,32,86,77,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,108,105,109,105,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,115,116,97,99,107,32,100,101,112,116,104,32,111,102,32,116,104,101,32,86,77,44,32,97,115,32,80,67,82,69,32,102,111,114,32,69,114,108,97,110,103,32,105,115,32,99,111,109,112,105,108,101,100,32,105,110,32,115,117,99,104,32,97,32,119,97,121,32,116,104,97,116,32,116,104,101,32,109,97,116,99,104,32,102,117,110,99,116,105,111,110,32,110,101,118,101,114,32,100,111,101,115,32,114,101,99,117,114,115,105,111,110,32,111,110,32,116,104,101,32,67,32,115,116,97,99,107,46>>]},{p,[],[<<78,111,116,101,32,116,104,97,116,32>>,{code,[],[<<76,73,77,73,84,95,77,65,84,67,72>>]},<<32,97,110,100,32>>,{code,[],[<<76,73,77,73,84,95,82,69,67,85,82,83,73,79,78>>]},<<32,99,97,110,32,111,110,108,121,32,114,101,100,117,99,101,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,108,105,109,105,116,115,32,115,101,116,32,98,121,32,116,104,101,32,99,97,108,108,101,114,44,32,110,111,116,32,105,110,99,114,101,97,115,101,32,116,104,101,109,46>>]},{a,[{id,<<115,101,99,116,50>>}],[]},{h2,[],[<<67,104,97,114,97,99,116,101,114,115,32,97,110,100,32,77,101,116,97,99,104,97,114,97,99,116,101,114,115>>]},{p,[],[<<65,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,97,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,46,32,77,111,115,116,32,99,104,97,114,97,99,116,101,114,115,32,115,116,97,110,100,32,102,111,114,32,116,104,101,109,115,101,108,118,101,115,32,105,110,32,97,32,112,97,116,116,101,114,110,32,97,110,100,32,109,97,116,99,104,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,65,115,32,97,32,116,114,105,118,105,97,108,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,32,112,111,114,116,105,111,110,32,111,102,32,97,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,116,104,97,116,32,105,115,32,105,100,101,110,116,105,99,97,108,32,116,111,32,105,116,115,101,108,102,58>>]},{pre,[],[{code,[],[<<84,104,101,32,113,117,105,99,107,32,98,114,111,119,110,32,102,111,120>>]}]},{p,[],[<<87,104,101,110,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,115,112,101,99,105,102,105,101,100,32,40,111,112,116,105,111,110,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<41,44,32,108,101,116,116,101,114,115,32,97,114,101,32,109,97,116,99,104,101,100,32,105,110,100,101,112,101,110,100,101,110,116,108,121,32,111,102,32,99,97,115,101,46>>]},{p,[],[<<84,104,101,32,112,111,119,101,114,32,111,102,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,99,111,109,101,115,32,102,114,111,109,32,116,104,101,32,97,98,105,108,105,116,121,32,116,111,32,105,110,99,108,117,100,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,110,100,32,114,101,112,101,116,105,116,105,111,110,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,101,115,101,32,97,114,101,32,101,110,99,111,100,101,100,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,98,121,32,116,104,101,32,117,115,101,32,111,102,32>>,{em,[],[<<109,101,116,97,99,104,97,114,97,99,116,101,114,115>>]},<<44,32,119,104,105,99,104,32,100,111,32,110,111,116,32,115,116,97,110,100,32,102,111,114,32,116,104,101,109,115,101,108,118,101,115,32,98,117,116,32,105,110,115,116,101,97,100,32,97,114,101,32,105,110,116,101,114,112,114,101,116,101,100,32,105,110,32,115,111,109,101,32,115,112,101,99,105,97,108,32,119,97,121,46>>]},{p,[],[<<84,119,111,32,115,101,116,115,32,111,102,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,101,120,105,115,116,58,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,97,110,121,119,104,101,114,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,101,120,99,101,112,116,32,119,105,116,104,105,110,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,44,32,97,110,100,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,119,105,116,104,105,110,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,46,32,79,117,116,115,105,100,101,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,44,32,116,104,101,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<92>>]},{dd,[],[<<71,101,110,101,114,97,108,32,101,115,99,97,112,101,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,109,97,110,121,32,117,115,101,115>>]},{dt,[],[<<94>>]},{dd,[],[<<65,115,115,101,114,116,32,115,116,97,114,116,32,111,102,32,115,116,114,105,110,103,32,40,111,114,32,108,105,110,101,44,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,41>>]},{dt,[],[<<36>>]},{dd,[],[<<65,115,115,101,114,116,32,101,110,100,32,111,102,32,115,116,114,105,110,103,32,40,111,114,32,108,105,110,101,44,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,41>>]},{dt,[],[<<46>>]},{dd,[],[<<77,97,116,99,104,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,101,120,99,101,112,116,32,110,101,119,108,105,110,101,32,40,98,121,32,100,101,102,97,117,108,116,41>>]},{dt,[],[<<91>>]},{dd,[],[<<83,116,97,114,116,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,100,101,102,105,110,105,116,105,111,110>>]},{dt,[],[<<124>>]},{dd,[],[<<83,116,97,114,116,32,111,102,32,97,108,116,101,114,110,97,116,105,118,101,32,98,114,97,110,99,104>>]},{dt,[],[<<40>>]},{dd,[],[<<83,116,97,114,116,32,115,117,98,112,97,116,116,101,114,110>>]},{dt,[],[<<41>>]},{dd,[],[<<69,110,100,32,115,117,98,112,97,116,116,101,114,110>>]},{dt,[],[<<63>>]},{dd,[],[<<69,120,116,101,110,100,115,32,116,104,101,32,109,101,97,110,105,110,103,32,111,102,32,40,44,32,97,108,115,111,32,48,32,111,114,32,49,32,113,117,97,110,116,105,102,105,101,114,44,32,97,108,115,111,32,113,117,97,110,116,105,102,105,101,114,32,109,105,110,105,109,105,122,101,114>>]},{dt,[],[<<42>>]},{dd,[],[<<48,32,111,114,32,109,111,114,101,32,113,117,97,110,116,105,102,105,101,114,115>>]},{dt,[],[<<43>>]},{dd,[],[<<49,32,111,114,32,109,111,114,101,32,113,117,97,110,116,105,102,105,101,114,44,32,97,108,115,111,32,34,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,34>>]},{dt,[],[<<123>>]},{dd,[],[<<83,116,97,114,116,32,109,105,110,47,109,97,120,32,113,117,97,110,116,105,102,105,101,114>>]}]},{p,[],[<<80,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,32,119,105,116,104,105,110,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,32,105,115,32,99,97,108,108,101,100,32,97,32,34,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,34,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,111,110,108,121,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,58>>]},{dl,[],[{dt,[],[<<92>>]},{dd,[],[<<71,101,110,101,114,97,108,32,101,115,99,97,112,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<94>>]},{dd,[],[<<78,101,103,97,116,101,32,116,104,101,32,99,108,97,115,115,44,32,98,117,116,32,111,110,108,121,32,105,102,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<45>>]},{dd,[],[<<73,110,100,105,99,97,116,101,115,32,99,104,97,114,97,99,116,101,114,32,114,97,110,103,101>>]},{dt,[],[<<91>>]},{dd,[],[<<80,111,115,105,120,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,40,111,110,108,121,32,105,102,32,102,111,108,108,111,119,101,100,32,98,121,32,80,111,115,105,120,32,115,121,110,116,97,120,41>>]},{dt,[],[<<93>>]},{dd,[],[<<84,101,114,109,105,110,97,116,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,99,116,105,111,110,115,32,100,101,115,99,114,105,98,101,32,116,104,101,32,117,115,101,32,111,102,32,101,97,99,104,32,109,101,116,97,99,104,97,114,97,99,116,101,114,46>>]},{a,[{id,<<115,101,99,116,51>>}],[]},{h2,[],[<<66,97,99,107,115,108,97,115,104>>]},{p,[],[<<84,104,101,32,98,97,99,107,115,108,97,115,104,32,99,104,97,114,97,99,116,101,114,32,104,97,115,32,109,97,110,121,32,117,115,101,115,46,32,70,105,114,115,116,44,32,105,102,32,105,116,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,110,117,109,98,101,114,32,111,114,32,97,32,108,101,116,116,101,114,44,32,105,116,32,116,97,107,101,115,32,97,119,97,121,32,97,110,121,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,116,104,97,116,32,97,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,104,97,118,101,46,32,84,104,105,115,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,97,115,32,97,110,32,101,115,99,97,112,101,32,99,104,97,114,97,99,116,101,114,32,97,112,112,108,105,101,115,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,97,32,42,32,99,104,97,114,97,99,116,101,114,44,32,121,111,117,32,119,114,105,116,101,32,92,42,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,105,115,32,101,115,99,97,112,105,110,103,32,97,99,116,105,111,110,32,97,112,112,108,105,101,115,32,105,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,104,97,114,97,99,116,101,114,32,119,111,117,108,100,32,111,116,104,101,114,119,105,115,101,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,109,101,116,97,99,104,97,114,97,99,116,101,114,44,32,115,111,32,105,116,32,105,115,32,97,108,119,97,121,115,32,115,97,102,101,32,116,111,32,112,114,101,99,101,100,101,32,97,32,110,111,110,45,97,108,112,104,97,110,117,109,101,114,105,99,32,119,105,116,104,32,98,97,99,107,115,108,97,115,104,32,116,111,32,115,112,101,99,105,102,121,32,116,104,97,116,32,105,116,32,115,116,97,110,100,115,32,102,111,114,32,105,116,115,101,108,102,46,32,73,110,32,112,97,114,116,105,99,117,108,97,114,44,32,105,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,97,32,98,97,99,107,115,108,97,115,104,44,32,119,114,105,116,101,32,92,92,46>>]},{p,[],[<<73,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,109,111,100,101,44,32,111,110,108,121,32,65,83,67,73,73,32,110,117,109,98,101,114,115,32,97,110,100,32,108,101,116,116,101,114,115,32,104,97,118,101,32,97,110,121,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,97,102,116,101,114,32,97,32,98,97,99,107,115,108,97,115,104,46,32,65,108,108,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,32,112,97,114,116,105,99,117,108,97,114,44,32,116,104,111,115,101,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,62,32,49,50,55,41,32,97,114,101,32,116,114,101,97,116,101,100,32,97,115,32,108,105,116,101,114,97,108,115,46>>]},{p,[],[<<73,102,32,97,32,112,97,116,116,101,114,110,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<44,32,119,104,105,116,101,115,112,97,99,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,40,111,116,104,101,114,32,116,104,97,110,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,41,32,97,110,100,32,99,104,97,114,97,99,116,101,114,115,32,98,101,116,119,101,101,110,32,97,32,35,32,111,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,97,110,100,32,116,104,101,32,110,101,120,116,32,110,101,119,108,105,110,101,32,97,114,101,32,105,103,110,111,114,101,100,46,32,65,110,32,101,115,99,97,112,105,110,103,32,98,97,99,107,115,108,97,115,104,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,105,110,99,108,117,100,101,32,97,32,119,104,105,116,101,115,112,97,99,101,32,111,114,32,35,32,99,104,97,114,97,99,116,101,114,32,97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<84,111,32,114,101,109,111,118,101,32,116,104,101,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,102,114,111,109,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,44,32,112,117,116,32,116,104,101,109,32,98,101,116,119,101,101,110,32,92,81,32,97,110,100,32,92,69,46,32,84,104,105,115,32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,80,101,114,108,32,105,110,32,116,104,97,116,32,36,32,97,110,100,32,64,32,97,114,101,32,104,97,110,100,108,101,100,32,97,115,32,108,105,116,101,114,97,108,115,32,105,110,32,92,81,46,46,46,92,69,32,115,101,113,117,101,110,99,101,115,32,105,110,32,80,67,82,69,44,32,119,104,105,108,101,32,36,32,97,110,100,32,64,32,99,97,117,115,101,32,118,97,114,105,97,98,108,101,32,105,110,116,101,114,112,111,108,97,116,105,111,110,32,105,110,32,80,101,114,108,46,32,78,111,116,105,99,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<80,97,116,116,101,114,110,32,32,32,32,32,32,32,32,32,32,32,32,80,67,82,69,32,109,97,116,99,104,101,115,32,32,32,80,101,114,108,32,109,97,116,99,104,101,115,10,10,92,81,97,98,99,36,120,121,122,92,69,32,32,32,32,32,32,32,32,97,98,99,36,120,121,122,32,32,32,32,32,32,32,32,97,98,99,32,102,111,108,108,111,119,101,100,32,98,121,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,36,120,121,122,10,92,81,97,98,99,92,36,120,121,122,92,69,32,32,32,32,32,32,32,97,98,99,92,36,120,121,122,32,32,32,32,32,32,32,97,98,99,92,36,120,121,122,10,92,81,97,98,99,92,69,92,36,92,81,120,121,122,92,69,32,32,32,97,98,99,36,120,121,122,32,32,32,32,32,32,32,32,97,98,99,36,120,121,122>>]}]},{p,[],[<<84,104,101,32,92,81,46,46,46,92,69,32,115,101,113,117,101,110,99,101,32,105,115,32,114,101,99,111,103,110,105,122,101,100,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,65,110,32,105,115,111,108,97,116,101,100,32,92,69,32,116,104,97,116,32,105,115,32,110,111,116,32,112,114,101,99,101,100,101,100,32,98,121,32,92,81,32,105,115,32,105,103,110,111,114,101,100,46,32,73,102,32,92,81,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32,92,69,32,108,97,116,101,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,44,32,116,104,101,32,108,105,116,101,114,97,108,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,99,111,110,116,105,110,117,101,115,32,116,111,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,40,116,104,97,116,32,105,115,44,32,92,69,32,105,115,32,97,115,115,117,109,101,100,32,97,116,32,116,104,101,32,101,110,100,41,46,32,73,102,32,116,104,101,32,105,115,111,108,97,116,101,100,32,92,81,32,105,115,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,104,105,115,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,44,32,97,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,105,115,32,110,111,116,32,116,101,114,109,105,110,97,116,101,100,46>>]},{p,[],[{em,[],[<<78,111,110,45,80,114,105,110,116,105,110,103,32,67,104,97,114,97,99,116,101,114,115>>]}]},{a,[{id,<<110,111,110,95,112,114,105,110,116,105,110,103,95,99,104,97,114,97,99,116,101,114,115>>}],[]},{p,[],[<<65,32,115,101,99,111,110,100,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,112,114,111,118,105,100,101,115,32,97,32,119,97,121,32,111,102,32,101,110,99,111,100,105,110,103,32,110,111,110,45,112,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,112,97,116,116,101,114,110,115,32,105,110,32,97,32,118,105,115,105,98,108,101,32,109,97,110,110,101,114,46,32,84,104,101,114,101,32,105,115,32,110,111,32,114,101,115,116,114,105,99,116,105,111,110,32,111,110,32,116,104,101,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,110,111,110,45,112,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,97,112,97,114,116,32,102,114,111,109,32,116,104,101,32,98,105,110,97,114,121,32,122,101,114,111,32,116,104,97,116,32,116,101,114,109,105,110,97,116,101,115,32,97,32,112,97,116,116,101,114,110,46,32,87,104,101,110,32,97,32,112,97,116,116,101,114,110,32,105,115,32,112,114,101,112,97,114,101,100,32,98,121,32,116,101,120,116,32,101,100,105,116,105,110,103,44,32,105,116,32,105,115,32,111,102,116,101,110,32,101,97,115,105,101,114,32,116,111,32,117,115,101,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,110,32,116,104,101,32,98,105,110,97,114,121,32,99,104,97,114,97,99,116,101,114,32,105,116,32,114,101,112,114,101,115,101,110,116,115,58>>]},{dl,[],[{dt,[],[<<92,97>>]},{dd,[],[<<65,108,97,114,109,44,32,116,104,97,116,32,105,115,44,32,116,104,101,32,66,69,76,32,99,104,97,114,97,99,116,101,114,32,40,104,101,120,32,48,55,41>>]},{dt,[],[<<92,99,120>>]},{dd,[],[<<34,67,111,110,116,114,111,108,45,120,34,44,32,119,104,101,114,101,32,120,32,105,115,32,97,110,121,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,101>>]},{dd,[],[<<69,115,99,97,112,101,32,40,104,101,120,32,49,66,41>>]},{dt,[],[<<92,102>>]},{dd,[],[<<70,111,114,109,32,102,101,101,100,32,40,104,101,120,32,48,67,41>>]},{dt,[],[<<92,110>>]},{dd,[],[<<76,105,110,101,32,102,101,101,100,32,40,104,101,120,32,48,65,41>>]},{dt,[],[<<92,114>>]},{dd,[],[<<67,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,40,104,101,120,32,48,68,41>>]},{dt,[],[<<92,116>>]},{dd,[],[<<84,97,98,32,40,104,101,120,32,48,57,41>>]},{dt,[],[<<92,48,100,100>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,48,100,100>>]},{dt,[],[<<92,100,100,100>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,100,100,100,44,32,111,114,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101>>]},{dt,[],[<<92,111,123,100,100,100,46,46,125>>]},{dd,[],[<<99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,100,100,100,46,46>>]},{dt,[],[<<92,120,104,104>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,104,101,120,32,99,111,100,101,32,104,104>>]},{dt,[],[<<92,120,123,104,104,104,46,46,125>>]},{dd,[],[<<67,104,97,114,97,99,116,101,114,32,119,105,116,104,32,104,101,120,32,99,111,100,101,32,104,104,104,46,46>>]}]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<78,111,116,101,32,116,104,97,116,32,92,48,100,100,32,105,115,32,97,108,119,97,121,115,32,97,110,32,111,99,116,97,108,32,99,111,100,101,44,32,97,110,100,32,116,104,97,116,32,92,56,32,97,110,100,32,92,57,32,97,114,101,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,56,34,32,97,110,100,32,34,57,34,46>>]}]},{p,[],[<<84,104,101,32,112,114,101,99,105,115,101,32,101,102,102,101,99,116,32,111,102,32,92,99,120,32,111,110,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,105,115,32,97,115,32,102,111,108,108,111,119,115,58,32,105,102,32,120,32,105,115,32,97,32,108,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,44,32,105,116,32,105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,117,112,112,101,114,32,99,97,115,101,46,32,84,104,101,110,32,98,105,116,32,54,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,40,104,101,120,32,52,48,41,32,105,115,32,105,110,118,101,114,116,101,100,46,32,84,104,117,115,32,92,99,65,32,116,111,32,92,99,90,32,98,101,99,111,109,101,32,104,101,120,32,48,49,32,116,111,32,104,101,120,32,49,65,32,40,65,32,105,115,32,52,49,44,32,90,32,105,115,32,53,65,41,44,32,98,117,116,32,92,99,123,32,98,101,99,111,109,101,115,32,104,101,120,32,51,66,32,40,123,32,105,115,32,55,66,41,44,32,97,110,100,32,92,99,59,32,98,101,99,111,109,101,115,32,104,101,120,32,55,66,32,40,59,32,105,115,32,51,66,41,46,32,73,102,32,116,104,101,32,100,97,116,97,32,105,116,101,109,32,40,98,121,116,101,32,111,114,32,49,54,45,98,105,116,32,118,97,108,117,101,41,32,102,111,108,108,111,119,105,110,103,32,92,99,32,104,97,115,32,97,32,118,97,108,117,101,32,62,32,49,50,55,44,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,32,111,99,99,117,114,115,46,32,84,104,105,115,32,108,111,99,107,115,32,111,117,116,32,110,111,110,45,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,97,108,108,32,109,111,100,101,115,46>>]},{p,[],[<<84,104,101,32,92,99,32,102,97,99,105,108,105,116,121,32,119,97,115,32,100,101,115,105,103,110,101,100,32,102,111,114,32,117,115,101,32,119,105,116,104,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,44,32,98,117,116,32,119,105,116,104,32,116,104,101,32,101,120,116,101,110,115,105,111,110,32,116,111,32,85,110,105,99,111,100,101,32,105,116,32,105,115,32,101,118,101,110,32,108,101,115,115,32,117,115,101,102,117,108,32,116,104,97,110,32,105,116,32,111,110,99,101,32,119,97,115,46>>]},{p,[],[<<65,102,116,101,114,32,92,48,32,117,112,32,116,111,32,116,119,111,32,102,117,114,116,104,101,114,32,111,99,116,97,108,32,100,105,103,105,116,115,32,97,114,101,32,114,101,97,100,46,32,73,102,32,116,104,101,114,101,32,97,114,101,32,102,101,119,101,114,32,116,104,97,110,32,116,119,111,32,100,105,103,105,116,115,44,32,106,117,115,116,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,112,114,101,115,101,110,116,32,97,114,101,32,117,115,101,100,46,32,84,104,117,115,32,116,104,101,32,115,101,113,117,101,110,99,101,32,92,48,92,120,92,48,49,53,32,115,112,101,99,105,102,105,101,115,32,116,119,111,32,98,105,110,97,114,121,32,122,101,114,111,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,67,82,32,99,104,97,114,97,99,116,101,114,32,40,99,111,100,101,32,118,97,108,117,101,32,49,51,41,46,32,77,97,107,101,32,115,117,114,101,32,121,111,117,32,115,117,112,112,108,121,32,116,119,111,32,100,105,103,105,116,115,32,97,102,116,101,114,32,116,104,101,32,105,110,105,116,105,97,108,32,122,101,114,111,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,102,111,108,108,111,119,115,32,105,115,32,105,116,115,101,108,102,32,97,110,32,111,99,116,97,108,32,100,105,103,105,116,46>>]},{p,[],[<<84,104,101,32,101,115,99,97,112,101,32,92,111,32,109,117,115,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,111,99,116,97,108,32,100,105,103,105,116,115,44,32,101,110,99,108,111,115,101,100,32,105,110,32,98,114,97,99,101,115,46,32,65,110,32,101,114,114,111,114,32,111,99,99,117,114,115,32,105,102,32,116,104,105,115,32,105,115,32,110,111,116,32,116,104,101,32,99,97,115,101,46,32,84,104,105,115,32,101,115,99,97,112,101,32,105,115,32,97,32,114,101,99,101,110,116,32,97,100,100,105,116,105,111,110,32,116,111,32,80,101,114,108,59,32,105,116,32,112,114,111,118,105,100,101,115,32,119,97,121,32,111,102,32,115,112,101,99,105,102,121,105,110,103,32,99,104,97,114,97,99,116,101,114,32,99,111,100,101,32,112,111,105,110,116,115,32,97,115,32,111,99,116,97,108,32,110,117,109,98,101,114,115,32,103,114,101,97,116,101,114,32,116,104,97,110,32,48,55,55,55,44,32,97,110,100,32,105,116,32,97,108,115,111,32,97,108,108,111,119,115,32,111,99,116,97,108,32,110,117,109,98,101,114,115,32,97,110,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,98,101,32,117,110,97,109,98,105,103,117,111,117,115,108,121,32,115,112,101,99,105,102,105,101,100,46>>]},{p,[],[<<70,111,114,32,103,114,101,97,116,101,114,32,99,108,97,114,105,116,121,32,97,110,100,32,117,110,97,109,98,105,103,117,105,116,121,44,32,105,116,32,105,115,32,98,101,115,116,32,116,111,32,97,118,111,105,100,32,102,111,108,108,111,119,105,110,103,32,92,32,98,121,32,97,32,100,105,103,105,116,32,103,114,101,97,116,101,114,32,116,104,97,110,32,122,101,114,111,46,32,73,110,115,116,101,97,100,44,32,117,115,101,32,92,111,123,125,32,111,114,32,92,120,123,125,32,116,111,32,115,112,101,99,105,102,121,32,99,104,97,114,97,99,116,101,114,32,110,117,109,98,101,114,115,44,32,97,110,100,32,92,103,123,125,32,116,111,32,115,112,101,99,105,102,121,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,114,97,103,114,97,112,104,115,32,100,101,115,99,114,105,98,101,32,116,104,101,32,111,108,100,44,32,97,109,98,105,103,117,111,117,115,32,115,121,110,116,97,120,46>>]},{p,[],[<<84,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,97,32,98,97,99,107,115,108,97,115,104,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,100,105,103,105,116,32,111,116,104,101,114,32,116,104,97,110,32,48,32,105,115,32,99,111,109,112,108,105,99,97,116,101,100,44,32,97,110,100,32,80,101,114,108,32,104,97,115,32,99,104,97,110,103,101,100,32,105,110,32,114,101,99,101,110,116,32,114,101,108,101,97,115,101,115,44,32,99,97,117,115,105,110,103,32,80,67,82,69,32,97,108,115,111,32,116,111,32,99,104,97,110,103,101,46,32,79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,80,67,82,69,32,114,101,97,100,115,32,116,104,101,32,100,105,103,105,116,32,97,110,100,32,97,110,121,32,102,111,108,108,111,119,105,110,103,32,100,105,103,105,116,115,32,97,115,32,97,32,100,101,99,105,109,97,108,32,110,117,109,98,101,114,46,32,73,102,32,116,104,101,32,110,117,109,98,101,114,32,105,115,32,60,32,56,44,32,111,114,32,105,102,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,32,97,116,32,108,101,97,115,116,32,116,104,97,116,32,109,97,110,121,32,112,114,101,118,105,111,117,115,32,99,97,112,116,117,114,105,110,103,32,108,101,102,116,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,44,32,116,104,101,32,101,110,116,105,114,101,32,115,101,113,117,101,110,99,101,32,105,115,32,116,97,107,101,110,32,97,115,32,97,32>>,{em,[],[<<98,97,99,107,32,114,101,102,101,114,101,110,99,101>>]},<<46,32,65,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,32,104,111,119,32,116,104,105,115,32,119,111,114,107,115,32,105,115,32,112,114,111,118,105,100,101,100,32,108,97,116,101,114,44,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,100,105,115,99,117,115,115,105,111,110,32,111,102,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46>>]},{p,[],[<<73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,111,114,32,105,102,32,116,104,101,32,100,101,99,105,109,97,108,32,110,117,109,98,101,114,32,102,111,108,108,111,119,105,110,103,32,92,32,105,115,32,62,32,55,32,97,110,100,32,116,104,101,114,101,32,104,97,118,101,32,110,111,116,32,98,101,101,110,32,116,104,97,116,32,109,97,110,121,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,80,67,82,69,32,104,97,110,100,108,101,115,32,92,56,32,97,110,100,32,92,57,32,97,115,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,56,34,32,97,110,100,32,34,57,34,44,32,97,110,100,32,111,116,104,101,114,119,105,115,101,32,114,101,45,114,101,97,100,115,32,117,112,32,116,111,32,116,104,114,101,101,32,111,99,116,97,108,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,98,97,99,107,115,108,97,115,104,44,32,97,110,100,32,117,115,105,110,103,32,116,104,101,109,32,116,111,32,103,101,110,101,114,97,116,101,32,97,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114,46,32,65,110,121,32,115,117,98,115,101,113,117,101,110,116,32,100,105,103,105,116,115,32,115,116,97,110,100,32,102,111,114,32,116,104,101,109,115,101,108,118,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{dl,[],[{dt,[],[<<92,48,52,48>>]},{dd,[],[<<65,110,111,116,104,101,114,32,119,97,121,32,111,102,32,119,114,105,116,105,110,103,32,97,110,32,65,83,67,73,73,32,115,112,97,99,101>>]},{dt,[],[<<92,52,48>>]},{dd,[],[<<84,104,101,32,115,97,109,101,44,32,112,114,111,118,105,100,101,100,32,116,104,101,114,101,32,97,114,101,32,60,32,52,48,32,112,114,101,118,105,111,117,115,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115>>]},{dt,[],[<<92,55>>]},{dd,[],[<<65,108,119,97,121,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101>>]},{dt,[],[<<92,49,49>>]},{dd,[],[<<67,97,110,32,98,101,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,114,32,97,110,111,116,104,101,114,32,119,97,121,32,111,102,32,119,114,105,116,105,110,103,32,97,32,116,97,98>>]},{dt,[],[<<92,48,49,49>>]},{dd,[],[<<65,108,119,97,121,115,32,97,32,116,97,98>>]},{dt,[],[<<92,48,49,49,51>>]},{dd,[],[<<65,32,116,97,98,32,102,111,108,108,111,119,101,100,32,98,121,32,99,104,97,114,97,99,116,101,114,32,34,51,34>>]},{dt,[],[<<92,49,49,51>>]},{dd,[],[<<67,97,110,32,98,101,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,111,99,116,97,108,32,99,111,100,101,32,49,49,51>>]},{dt,[],[<<92,51,55,55>>]},{dd,[],[<<67,97,110,32,98,101,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,116,104,101,114,119,105,115,101,32,118,97,108,117,101,32,50,53,53,32,40,100,101,99,105,109,97,108,41>>]},{dt,[],[<<92,56,49>>]},{dd,[],[<<69,105,116,104,101,114,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,111,114,32,116,104,101,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,32,34,56,34,32,97,110,100,32,34,49,34>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,111,99,116,97,108,32,118,97,108,117,101,115,32,62,61,32,49,48,48,32,116,104,97,116,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,117,115,105,110,103,32,116,104,105,115,32,115,121,110,116,97,120,32,109,117,115,116,32,110,111,116,32,98,101,32,105,110,116,114,111,100,117,99,101,100,32,98,121,32,97,32,108,101,97,100,105,110,103,32,122,101,114,111,44,32,97,115,32,110,111,32,109,111,114,101,32,116,104,97,110,32,116,104,114,101,101,32,111,99,116,97,108,32,100,105,103,105,116,115,32,97,114,101,32,101,118,101,114,32,114,101,97,100,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,97,102,116,101,114,32,92,120,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32,123,44,32,102,114,111,109,32,122,101,114,111,32,116,111,32,116,119,111,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,115,32,97,114,101,32,114,101,97,100,32,40,108,101,116,116,101,114,115,32,99,97,110,32,98,101,32,105,110,32,117,112,112,101,114,32,111,114,32,108,111,119,101,114,32,99,97,115,101,41,46,32,65,110,121,32,110,117,109,98,101,114,32,111,102,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,115,32,109,97,121,32,97,112,112,101,97,114,32,98,101,116,119,101,101,110,32,92,120,123,32,97,110,100,32,125,46,32,73,102,32,97,32,99,104,97,114,97,99,116,101,114,32,111,116,104,101,114,32,116,104,97,110,32,97,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,32,97,112,112,101,97,114,115,32,98,101,116,119,101,101,110,32,92,120,123,32,97,110,100,32,125,44,32,111,114,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,116,101,114,109,105,110,97,116,105,110,103,32,125,44,32,97,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46>>]},{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,118,97,108,117,101,32,105,115,32,108,101,115,115,32,116,104,97,110,32,50,53,54,32,99,97,110,32,98,101,32,100,101,102,105,110,101,100,32,98,121,32,101,105,116,104,101,114,32,111,102,32,116,104,101,32,116,119,111,32,115,121,110,116,97,120,101,115,32,102,111,114,32,92,120,46,32,84,104,101,114,101,32,105,115,32,110,111,32,100,105,102,102,101,114,101,110,99,101,32,105,110,32,116,104,101,32,119,97,121,32,116,104,101,121,32,97,114,101,32,104,97,110,100,108,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,92,120,100,99,32,105,115,32,101,120,97,99,116,108,121,32,116,104,101,32,115,97,109,101,32,97,115,32,92,120,123,100,99,125,46>>]},{p,[],[{em,[],[<<67,111,110,115,116,114,97,105,110,116,115,32,111,110,32,99,104,97,114,97,99,116,101,114,32,118,97,108,117,101,115>>]}]},{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,117,115,105,110,103,32,111,99,116,97,108,32,111,114,32,104,101,120,97,100,101,99,105,109,97,108,32,110,117,109,98,101,114,115,32,97,114,101,32,108,105,109,105,116,101,100,32,116,111,32,99,101,114,116,97,105,110,32,118,97,108,117,101,115,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<56,45,98,105,116,32,110,111,110,45,85,84,70,32,109,111,100,101>>]},{dd,[],[{p,[],[<<60,32,48,120,49,48,48>>]}]},{dt,[],[<<56,45,98,105,116,32,85,84,70,45,56,32,109,111,100,101>>]},{dd,[],[{p,[],[<<60,32,48,120,49,48,102,102,102,102,32,97,110,100,32,97,32,118,97,108,105,100,32,99,111,100,101,112,111,105,110,116>>]}]}]},{p,[],[<<73,110,118,97,108,105,100,32,85,110,105,99,111,100,101,32,99,111,100,101,112,111,105,110,116,115,32,97,114,101,32,116,104,101,32,114,97,110,103,101,32,48,120,100,56,48,48,32,116,111,32,48,120,100,102,102,102,32,40,116,104,101,32,115,111,45,99,97,108,108,101,100,32,34,115,117,114,114,111,103,97,116,101,34,32,99,111,100,101,112,111,105,110,116,115,41,44,32,97,110,100,32,48,120,102,102,101,102,46>>]},{p,[],[{em,[],[<<69,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,105,110,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115>>]}]},{p,[],[<<65,108,108,32,116,104,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,116,32,100,101,102,105,110,101,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,118,97,108,117,101,32,99,97,110,32,98,101,32,117,115,101,100,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,65,108,115,111,44,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,92,98,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,116,104,101,32,98,97,99,107,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,32,40,104,101,120,32,48,56,41,46>>]},{p,[],[<<92,78,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,92,66,44,32,92,82,44,32,97,110,100,32,92,88,32,97,114,101,32,110,111,116,32,115,112,101,99,105,97,108,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,76,105,107,101,32,111,116,104,101,114,32,117,110,114,101,99,111,103,110,105,122,101,100,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,44,32,116,104,101,121,32,97,114,101,32,116,114,101,97,116,101,100,32,97,115,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,66,34,44,32,34,82,34,44,32,97,110,100,32,34,88,34,46,32,79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,115,46>>]},{p,[],[{em,[],[<<85,110,115,117,112,112,111,114,116,101,100,32,69,115,99,97,112,101,32,83,101,113,117,101,110,99,101,115>>]}]},{p,[],[<<73,110,32,80,101,114,108,44,32,116,104,101,32,115,101,113,117,101,110,99,101,115,32,92,108,44,32,92,76,44,32,92,117,44,32,97,110,100,32,92,85,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,98,121,32,105,116,115,32,115,116,114,105,110,103,32,104,97,110,100,108,101,114,32,97,110,100,32,117,115,101,100,32,116,111,32,109,111,100,105,102,121,32,116,104,101,32,99,97,115,101,32,111,102,32,102,111,108,108,111,119,105,110,103,32,99,104,97,114,97,99,116,101,114,115,46,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,115,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,46>>]},{p,[],[{em,[],[<<65,98,115,111,108,117,116,101,32,97,110,100,32,82,101,108,97,116,105,118,101,32,66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]}]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,32,92,103,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,117,110,115,105,103,110,101,100,32,111,114,32,97,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,44,32,111,112,116,105,111,110,97,108,108,121,32,101,110,99,108,111,115,101,100,32,105,110,32,98,114,97,99,101,115,44,32,105,115,32,97,110,32,97,98,115,111,108,117,116,101,32,111,114,32,114,101,108,97,116,105,118,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,46,32,65,32,110,97,109,101,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,99,111,100,101,100,32,97,115,32,92,103,123,110,97,109,101,125,46,32,66,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,97,114,101,32,100,105,115,99,117,115,115,101,100,32,108,97,116,101,114,44,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,100,105,115,99,117,115,115,105,111,110,32,111,102,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46>>]},{p,[],[{em,[],[<<65,98,115,111,108,117,116,101,32,97,110,100,32,82,101,108,97,116,105,118,101,32,83,117,98,114,111,117,116,105,110,101,32,67,97,108,108,115>>]}]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,79,110,105,103,117,114,117,109,97,44,32,116,104,101,32,110,111,110,45,80,101,114,108,32,115,121,110,116,97,120,32,92,103,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,32,111,114,32,97,32,110,117,109,98,101,114,32,101,110,99,108,111,115,101,100,32,101,105,116,104,101,114,32,105,110,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115,32,111,114,32,115,105,110,103,108,101,32,113,117,111,116,101,115,44,32,105,115,32,97,108,116,101,114,110,97,116,105,118,101,32,115,121,110,116,97,120,32,102,111,114,32,114,101,102,101,114,101,110,99,105,110,103,32,97,32,115,117,98,112,97,116,116,101,114,110,32,97,115,32,97,32,34,115,117,98,114,111,117,116,105,110,101,34,46,32,68,101,116,97,105,108,115,32,97,114,101,32,100,105,115,99,117,115,115,101,100,32,108,97,116,101,114,46,32,78,111,116,105,99,101,32,116,104,97,116,32,92,103,123,46,46,46,125,32,40,80,101,114,108,32,115,121,110,116,97,120,41,32,97,110,100,32,92,103,60,46,46,46,62,32,40,79,110,105,103,117,114,117,109,97,32,115,121,110,116,97,120,41,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,115,121,110,111,110,121,109,111,117,115,46,32,84,104,101,32,102,111,114,109,101,114,32,105,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,97,110,100,32,116,104,101,32,108,97,116,116,101,114,32,105,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,46>>]},{p,[],[{em,[],[<<71,101,110,101,114,105,99,32,67,104,97,114,97,99,116,101,114,32,84,121,112,101,115>>]}]},{a,[{id,<<103,101,110,101,114,105,99,95,99,104,97,114,97,99,116,101,114,95,116,121,112,101,115>>}],[]},{p,[],[<<65,110,111,116,104,101,114,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,105,115,32,102,111,114,32,115,112,101,99,105,102,121,105,110,103,32,103,101,110,101,114,105,99,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,58>>]},{dl,[],[{dt,[],[<<92,100>>]},{dd,[],[<<65,110,121,32,100,101,99,105,109,97,108,32,100,105,103,105,116>>]},{dt,[],[<<92,68>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,100,101,99,105,109,97,108,32,100,105,103,105,116>>]},{dt,[],[<<92,104>>]},{dd,[],[<<65,110,121,32,104,111,114,105,122,111,110,116,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,72>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,104,111,114,105,122,111,110,116,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,115>>]},{dd,[],[<<65,110,121,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,83>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,118>>]},{dd,[],[<<65,110,121,32,118,101,114,116,105,99,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,86>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,118,101,114,116,105,99,97,108,32,119,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,119>>]},{dd,[],[<<65,110,121,32,34,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114>>]},{dt,[],[<<92,87>>]},{dd,[],[<<65,110,121,32,34,110,111,110,45,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114>>]}]},{p,[],[<<84,104,101,114,101,32,105,115,32,97,108,115,111,32,116,104,101,32,115,105,110,103,108,101,32,115,101,113,117,101,110,99,101,32,92,78,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,32,110,111,110,45,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,34,46,34,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,119,104,101,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,105,115,32,110,111,116,32,115,101,116,46,32,80,101,114,108,32,97,108,115,111,32,117,115,101,115,32,92,78,32,116,111,32,109,97,116,99,104,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,110,97,109,101,44,32,98,117,116,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,105,115,46>>]},{p,[],[<<69,97,99,104,32,112,97,105,114,32,111,102,32,108,111,119,101,114,99,97,115,101,32,97,110,100,32,117,112,112,101,114,99,97,115,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,112,97,114,116,105,116,105,111,110,115,32,116,104,101,32,99,111,109,112,108,101,116,101,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,105,110,116,111,32,116,119,111,32,100,105,115,106,111,105,110,116,32,115,101,116,115,46,32,65,110,121,32,103,105,118,101,110,32,99,104,97,114,97,99,116,101,114,32,109,97,116,99,104,101,115,32,111,110,101,44,32,97,110,100,32,111,110,108,121,32,111,110,101,44,32,111,102,32,101,97,99,104,32,112,97,105,114,46,32,84,104,101,32,115,101,113,117,101,110,99,101,115,32,99,97,110,32,97,112,112,101,97,114,32,98,111,116,104,32,105,110,115,105,100,101,32,97,110,100,32,111,117,116,115,105,100,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,84,104,101,121,32,101,97,99,104,32,109,97,116,99,104,32,111,110,101,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,116,121,112,101,46,32,73,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,108,108,32,102,97,105,108,44,32,97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,99,104,97,114,97,99,116,101,114,32,116,111,32,109,97,116,99,104,46>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,80,101,114,108,44,32,92,115,32,100,105,100,32,110,111,116,32,117,115,101,100,32,116,111,32,109,97,116,99,104,32,116,104,101,32,86,84,32,99,104,97,114,97,99,116,101,114,32,40,99,111,100,101,32,49,49,41,44,32,119,104,105,99,104,32,109,97,100,101,32,105,116,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,116,104,101,32,80,79,83,73,88,32,34,115,112,97,99,101,34,32,99,108,97,115,115,46,32,72,111,119,101,118,101,114,44,32,80,101,114,108,32,97,100,100,101,100,32,86,84,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,44,32,97,110,100,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,115,117,105,116,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46,32,84,104,101,32,100,101,102,97,117,108,116,32,92,115,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,110,111,119,32,72,84,32,40,57,41,44,32,76,70,32,40,49,48,41,44,32,86,84,32,40,49,49,41,44,32,70,70,32,40,49,50,41,44,32,67,82,32,40,49,51,41,44,32,97,110,100,32,115,112,97,99,101,32,40,51,50,41,44,32,119,104,105,99,104,32,97,114,101,32,100,101,102,105,110,101,100,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,32,105,110,32,116,104,101,32,34,67,34,32,108,111,99,97,108,101,46,32,84,104,105,115,32,108,105,115,116,32,109,97,121,32,118,97,114,121,32,105,102,32,108,111,99,97,108,101,45,115,112,101,99,105,102,105,99,32,109,97,116,99,104,105,110,103,32,105,115,32,116,97,107,105,110,103,32,112,108,97,99,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,115,111,109,101,32,108,111,99,97,108,101,115,32,116,104,101,32,34,110,111,110,45,98,114,101,97,107,105,110,103,32,115,112,97,99,101,34,32,99,104,97,114,97,99,116,101,114,32,40,92,120,65,48,41,32,105,115,32,114,101,99,111,103,110,105,122,101,100,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,44,32,97,110,100,32,105,110,32,111,116,104,101,114,115,32,116,104,101,32,86,84,32,99,104,97,114,97,99,116,101,114,32,105,115,32,110,111,116,46>>]},{p,[],[<<65,32,34,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114,32,105,115,32,97,110,32,117,110,100,101,114,115,99,111,114,101,32,111,114,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,97,32,108,101,116,116,101,114,32,111,114,32,97,32,100,105,103,105,116,46,32,66,121,32,100,101,102,97,117,108,116,44,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,108,101,116,116,101,114,115,32,97,110,100,32,100,105,103,105,116,115,32,105,115,32,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,32,80,67,82,69,32,108,111,119,45,118,97,108,117,101,100,32,99,104,97,114,97,99,116,101,114,32,116,97,98,108,101,115,44,32,105,110,32,69,114,108,97,110,103,39,115,32,99,97,115,101,32,40,97,110,100,32,119,105,116,104,111,117,116,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<41,44,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,105,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,109,111,100,101,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,44,32,116,104,97,116,32,105,115,44,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,111,117,116,115,105,100,101,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,44,32,110,101,118,101,114,32,109,97,116,99,104,32,92,100,44,32,92,115,44,32,111,114,32,92,119,44,32,97,110,100,32,97,108,119,97,121,115,32,109,97,116,99,104,32,92,68,44,32,92,83,44,32,97,110,100,32,92,87,46,32,84,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,114,101,116,97,105,110,32,116,104,101,105,114,32,111,114,105,103,105,110,97,108,32,109,101,97,110,105,110,103,115,32,102,114,111,109,32,98,101,102,111,114,101,32,85,84,70,32,115,117,112,112,111,114,116,32,119,97,115,32,97,118,97,105,108,97,98,108,101,44,32,109,97,105,110,108,121,32,102,111,114,32,101,102,102,105,99,105,101,110,99,121,32,114,101,97,115,111,110,115,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,105,115,32,115,101,116,44,32,116,104,101,32,98,101,104,97,118,105,111,114,32,105,115,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,117,115,101,100,32,116,111,32,100,101,116,101,114,109,105,110,101,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<92,100>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,92,112,123,78,100,125,32,109,97,116,99,104,101,115,32,40,100,101,99,105,109,97,108,32,100,105,103,105,116,41>>]},{dt,[],[<<92,115>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,92,112,123,90,125,32,111,114,32,92,104,32,111,114,32,92,118>>]},{dt,[],[<<92,119>>]},{dd,[],[<<65,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,109,97,116,99,104,101,115,32,92,112,123,76,125,32,111,114,32,92,112,123,78,125,32,109,97,116,99,104,101,115,44,32,112,108,117,115,32,117,110,100,101,114,115,99,111,114,101>>]}]},{p,[],[<<84,104,101,32,117,112,112,101,114,99,97,115,101,32,101,115,99,97,112,101,115,32,109,97,116,99,104,32,116,104,101,32,105,110,118,101,114,115,101,32,115,101,116,115,32,111,102,32,99,104,97,114,97,99,116,101,114,115,46,32,78,111,116,105,99,101,32,116,104,97,116,32,92,100,32,109,97,116,99,104,101,115,32,111,110,108,121,32,100,101,99,105,109,97,108,32,100,105,103,105,116,115,44,32,119,104,105,108,101,32,92,119,32,109,97,116,99,104,101,115,32,97,110,121,32,85,110,105,99,111,100,101,32,100,105,103,105,116,44,32,97,110,121,32,85,110,105,99,111,100,101,32,108,101,116,116,101,114,44,32,97,110,100,32,117,110,100,101,114,115,99,111,114,101,46,32,78,111,116,105,99,101,32,97,108,115,111,32,116,104,97,116,32>>,{code,[],[<<117,99,112>>]},<<32,97,102,102,101,99,116,115,32,92,98,32,97,110,100,32,92,66,44,32,97,115,32,116,104,101,121,32,97,114,101,32,100,101,102,105,110,101,100,32,105,110,32,116,101,114,109,115,32,111,102,32,92,119,32,97,110,100,32,92,87,46,32,77,97,116,99,104,105,110,103,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,105,115,32,110,111,116,105,99,101,97,98,108,121,32,115,108,111,119,101,114,32,119,104,101,110,32>>,{code,[],[<<117,99,112>>]},<<32,105,115,32,115,101,116,46>>]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,115,32,92,104,44,32,92,72,44,32,92,118,44,32,97,110,100,32,92,86,32,97,114,101,32,102,101,97,116,117,114,101,115,32,116,104,97,116,32,119,101,114,101,32,97,100,100,101,100,32,116,111,32,80,101,114,108,32,105,110,32,114,101,108,101,97,115,101,32,53,46,49,48,46,32,73,110,32,99,111,110,116,114,97,115,116,32,116,111,32,116,104,101,32,111,116,104,101,114,32,115,101,113,117,101,110,99,101,115,44,32,119,104,105,99,104,32,109,97,116,99,104,32,111,110,108,121,32,65,83,67,73,73,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,100,101,102,97,117,108,116,44,32,116,104,101,115,101,32,97,108,119,97,121,115,32,109,97,116,99,104,32,99,101,114,116,97,105,110,32,104,105,103,104,45,118,97,108,117,101,100,32,99,111,100,101,32,112,111,105,110,116,115,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32>>,{code,[],[<<117,99,112>>]},<<32,105,115,32,115,101,116,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,104,111,114,105,122,111,110,116,97,108,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,58>>]},{dl,[],[{dt,[],[<<85,43,48,48,48,57>>]},{dd,[],[<<72,111,114,105,122,111,110,116,97,108,32,116,97,98,32,40,72,84,41>>]},{dt,[],[<<85,43,48,48,50,48>>]},{dd,[],[<<83,112,97,99,101>>]},{dt,[],[<<85,43,48,48,65,48>>]},{dd,[],[<<78,111,110,45,98,114,101,97,107,32,115,112,97,99,101>>]},{dt,[],[<<85,43,49,54,56,48>>]},{dd,[],[<<79,103,104,97,109,32,115,112,97,99,101,32,109,97,114,107>>]},{dt,[],[<<85,43,49,56,48,69>>]},{dd,[],[<<77,111,110,103,111,108,105,97,110,32,118,111,119,101,108,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<85,43,50,48,48,48>>]},{dd,[],[<<69,110,32,113,117,97,100>>]},{dt,[],[<<85,43,50,48,48,49>>]},{dd,[],[<<69,109,32,113,117,97,100>>]},{dt,[],[<<85,43,50,48,48,50>>]},{dd,[],[<<69,110,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,51>>]},{dd,[],[<<69,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,52>>]},{dd,[],[<<84,104,114,101,101,45,112,101,114,45,101,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,53>>]},{dd,[],[<<70,111,117,114,45,112,101,114,45,101,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,54>>]},{dd,[],[<<83,105,120,45,112,101,114,45,101,109,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,55>>]},{dd,[],[<<70,105,103,117,114,101,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,56>>]},{dd,[],[<<80,117,110,99,116,117,97,116,105,111,110,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,57>>]},{dd,[],[<<84,104,105,110,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,48,65>>]},{dd,[],[<<72,97,105,114,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,50,70>>]},{dd,[],[<<78,97,114,114,111,119,32,110,111,45,98,114,101,97,107,32,115,112,97,99,101>>]},{dt,[],[<<85,43,50,48,53,70>>]},{dd,[],[<<77,101,100,105,117,109,32,109,97,116,104,101,109,97,116,105,99,97,108,32,115,112,97,99,101>>]},{dt,[],[<<85,43,51,48,48,48>>]},{dd,[],[<<73,100,101,111,103,114,97,112,104,105,99,32,115,112,97,99,101>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,118,101,114,116,105,99,97,108,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,58>>]},{dl,[],[{dt,[],[<<85,43,48,48,48,65>>]},{dd,[],[<<76,105,110,101,32,102,101,101,100,32,40,76,70,41>>]},{dt,[],[<<85,43,48,48,48,66>>]},{dd,[],[<<86,101,114,116,105,99,97,108,32,116,97,98,32,40,86,84,41>>]},{dt,[],[<<85,43,48,48,48,67>>]},{dd,[],[<<70,111,114,109,32,102,101,101,100,32,40,70,70,41>>]},{dt,[],[<<85,43,48,48,48,68>>]},{dd,[],[<<67,97,114,114,105,97,103,101,32,114,101,116,117,114,110,32,40,67,82,41>>]},{dt,[],[<<85,43,48,48,56,53>>]},{dd,[],[<<78,101,120,116,32,108,105,110,101,32,40,78,69,76,41>>]},{dt,[],[<<85,43,50,48,50,56>>]},{dd,[],[<<76,105,110,101,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<85,43,50,48,50,57>>]},{dd,[],[<<80,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114>>]}]},{p,[],[<<73,110,32,56,45,98,105,116,44,32,110,111,110,45,85,84,70,45,56,32,109,111,100,101,44,32,111,110,108,121,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,99,111,100,101,32,112,111,105,110,116,115,32,60,32,50,53,54,32,97,114,101,32,114,101,108,101,118,97,110,116,46>>]},{p,[],[{em,[],[<<78,101,119,108,105,110,101,32,83,101,113,117,101,110,99,101,115>>]}]},{a,[{id,<<110,101,119,108,105,110,101,95,115,101,113,117,101,110,99,101,115>>}],[]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,98,121,32,100,101,102,97,117,108,116,44,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,82,32,109,97,116,99,104,101,115,32,97,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,46,32,73,110,32,110,111,110,45,85,84,70,45,56,32,109,111,100,101,44,32,92,82,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{pre,[],[{code,[],[<<40,63,62,92,114,92,110,124,92,110,124,92,120,48,98,124,92,102,124,92,114,124,92,120,56,53,41>>]}]},{p,[],[<<84,104,105,115,32,105,115,32,97,110,32,101,120,97,109,112,108,101,32,111,102,32,97,110,32,34,97,116,111,109,105,99,32,103,114,111,117,112,34,44,32,100,101,116,97,105,108,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,98,101,108,111,119,46>>]},{p,[],[<<84,104,105,115,32,112,97,114,116,105,99,117,108,97,114,32,103,114,111,117,112,32,109,97,116,99,104,101,115,32,101,105,116,104,101,114,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,32,102,111,108,108,111,119,101,100,32,98,121,32,76,70,44,32,111,114,32,111,110,101,32,111,102,32,116,104,101,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,115,32,76,70,32,40,108,105,110,101,32,102,101,101,100,44,32,85,43,48,48,48,65,41,44,32,86,84,32,40,118,101,114,116,105,99,97,108,32,116,97,98,44,32,85,43,48,48,48,66,41,44,32,70,70,32,40,102,111,114,109,32,102,101,101,100,44,32,85,43,48,48,48,67,41,44,32,67,82,32,40,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,44,32,85,43,48,48,48,68,41,44,32,111,114,32,78,69,76,32,40,110,101,120,116,32,108,105,110,101,44,32,85,43,48,48,56,53,41,46,32,84,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,97,32,115,105,110,103,108,101,32,117,110,105,116,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,115,112,108,105,116,46>>]},{p,[],[<<73,110,32,85,110,105,99,111,100,101,32,109,111,100,101,44,32,116,119,111,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,62,32,50,53,53,32,97,114,101,32,97,100,100,101,100,58,32,76,83,32,40,108,105,110,101,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,56,41,32,97,110,100,32,80,83,32,40,112,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,57,41,46,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,32,105,115,32,110,111,116,32,110,101,101,100,101,100,32,102,111,114,32,116,104,101,115,101,32,99,104,97,114,97,99,116,101,114,115,32,116,111,32,98,101,32,114,101,99,111,103,110,105,122,101,100,46>>]},{p,[],[<<92,82,32,99,97,110,32,98,101,32,114,101,115,116,114,105,99,116,101,100,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,67,82,44,32,76,70,44,32,111,114,32,67,82,76,70,32,40,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,99,111,109,112,108,101,116,101,32,115,101,116,32,111,102,32,85,110,105,99,111,100,101,32,108,105,110,101,32,101,110,100,105,110,103,115,41,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<98,115,114,95,97,110,121,99,114,108,102>>]},<<32,101,105,116,104,101,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,32,111,114,32,119,104,101,110,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,109,97,116,99,104,101,100,46,32,40,66,83,82,32,105,115,32,97,110,32,97,99,114,111,110,121,109,32,102,111,114,32,34,98,97,99,107,115,108,97,115,104,32,82,34,46,41,32,84,104,105,115,32,99,97,110,32,98,101,32,109,97,100,101,32,116,104,101,32,100,101,102,97,117,108,116,32,119,104,101,110,32,80,67,82,69,32,105,115,32,98,117,105,108,116,59,32,105,102,32,115,111,44,32,116,104,101,32,111,116,104,101,114,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,114,101,113,117,101,115,116,101,100,32,116,104,114,111,117,103,104,32,111,112,116,105,111,110,32>>,{code,[],[<<98,115,114,95,117,110,105,99,111,100,101>>]},<<46,32,84,104,101,115,101,32,115,101,116,116,105,110,103,115,32,99,97,110,32,97,108,115,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,115,116,97,114,116,105,110,103,32,97,32,112,97,116,116,101,114,110,32,115,116,114,105,110,103,32,119,105,116,104,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,101,113,117,101,110,99,101,115,58>>]},{dl,[],[{dt,[],[<<40,42,66,83,82,95,65,78,89,67,82,76,70,41>>]},{dd,[],[<<67,82,44,32,76,70,44,32,111,114,32,67,82,76,70,32,111,110,108,121>>]},{dt,[],[<<40,42,66,83,82,95,85,78,73,67,79,68,69,41>>]},{dd,[],[<<65,110,121,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101>>]}]},{p,[],[<<84,104,101,115,101,32,111,118,101,114,114,105,100,101,32,116,104,101,32,100,101,102,97,117,108,116,32,97,110,100,32,116,104,101,32,111,112,116,105,111,110,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,116,104,101,32,99,111,109,112,105,108,105,110,103,32,102,117,110,99,116,105,111,110,44,32,98,117,116,32,116,104,101,121,32,99,97,110,32,116,104,101,109,115,101,108,118,101,115,32,98,101,32,111,118,101,114,114,105,100,100,101,110,32,98,121,32,111,112,116,105,111,110,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,97,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,115,101,32,115,112,101,99,105,97,108,32,115,101,116,116,105,110,103,115,44,32,119,104,105,99,104,32,97,114,101,32,110,111,116,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,44,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,111,110,108,121,32,97,116,32,116,104,101,32,118,101,114,121,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,44,32,97,110,100,32,116,104,97,116,32,116,104,101,121,32,109,117,115,116,32,98,101,32,105,110,32,117,112,112,101,114,32,99,97,115,101,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,111,102,32,116,104,101,109,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,32,108,97,115,116,32,111,110,101,32,105,115,32,117,115,101,100,46,32,84,104,101,121,32,99,97,110,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,97,32,99,104,97,110,103,101,32,111,102,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,59,32,102,111,114,32,101,120,97,109,112,108,101,44,32,97,32,112,97,116,116,101,114,110,32,99,97,110,32,115,116,97,114,116,32,119,105,116,104,58>>]},{pre,[],[{code,[],[<<40,42,65,78,89,41,40,42,66,83,82,95,65,78,89,67,82,76,70,41>>]}]},{p,[],[<<84,104,101,121,32,99,97,110,32,97,108,115,111,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,116,104,101,32,40,42,85,84,70,56,41,44,32,40,42,85,84,70,41,44,32,111,114,32,40,42,85,67,80,41,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,115,46,32,73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,92,82,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,117,110,114,101,99,111,103,110,105,122,101,100,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,44,32,97,110,100,32,115,111,32,109,97,116,99,104,101,115,32,116,104,101,32,108,101,116,116,101,114,32,34,82,34,32,98,121,32,100,101,102,97,117,108,116,46>>]},{p,[],[{em,[],[<<85,110,105,99,111,100,101,32,67,104,97,114,97,99,116,101,114,32,80,114,111,112,101,114,116,105,101,115>>]}]},{p,[],[<<84,104,114,101,101,32,109,111,114,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,116,32,109,97,116,99,104,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,115,112,101,99,105,102,105,99,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,97,118,97,105,108,97,98,108,101,46,32,87,104,101,110,32,105,110,32,56,45,98,105,116,32,110,111,110,45,85,84,70,45,56,32,109,111,100,101,44,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,97,114,101,32,108,105,109,105,116,101,100,32,116,111,32,116,101,115,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,60,32,50,53,54,44,32,98,117,116,32,116,104,101,121,32,100,111,32,119,111,114,107,32,105,110,32,116,104,105,115,32,109,111,100,101,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,101,120,116,114,97,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,58>>]},{dl,[],[{dt,[],[<<92,112,123>>,{em,[],[<<120,120>>]},<<125>>]},{dd,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,112,114,111,112,101,114,116,121,32>>,{em,[],[<<120,120>>]}]},{dt,[],[<<92,80,123>>,{em,[],[<<120,120>>]},<<125>>]},{dd,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,111,117,116,32,112,114,111,112,101,114,116,121,32>>,{em,[],[<<120,120>>]}]},{dt,[],[<<92,88>>]},{dd,[],[<<65,32,85,110,105,99,111,100,101,32,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114>>]}]},{p,[],[<<84,104,101,32,112,114,111,112,101,114,116,121,32,110,97,109,101,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32>>,{em,[],[<<120,120>>]},<<32,97,98,111,118,101,32,97,114,101,32,108,105,109,105,116,101,100,32,116,111,32,116,104,101,32,85,110,105,99,111,100,101,32,115,99,114,105,112,116,32,110,97,109,101,115,44,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,105,101,115,44,32,34,65,110,121,34,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,40,105,110,99,108,117,100,105,110,103,32,110,101,119,108,105,110,101,41,44,32,97,110,100,32,115,111,109,101,32,115,112,101,99,105,97,108,32,80,67,82,69,32,112,114,111,112,101,114,116,105,101,115,32,40,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41,46,32,79,116,104,101,114,32,80,101,114,108,32,112,114,111,112,101,114,116,105,101,115,44,32,115,117,99,104,32,97,115,32,34,73,110,77,117,115,105,99,97,108,83,121,109,98,111,108,115,34,44,32,97,114,101,32,99,117,114,114,101,110,116,108,121,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,67,82,69,46,32,78,111,116,105,99,101,32,116,104,97,116,32,92,80,123,65,110,121,125,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,97,110,100,32,97,108,119,97,121,115,32,99,97,117,115,101,115,32,97,32,109,97,116,99,104,32,102,97,105,108,117,114,101,46>>]},{p,[],[<<83,101,116,115,32,111,102,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,100,101,102,105,110,101,100,32,97,115,32,98,101,108,111,110,103,105,110,103,32,116,111,32,99,101,114,116,97,105,110,32,115,99,114,105,112,116,115,46,32,65,32,99,104,97,114,97,99,116,101,114,32,102,114,111,109,32,111,110,101,32,111,102,32,116,104,101,115,101,32,115,101,116,115,32,99,97,110,32,98,101,32,109,97,116,99,104,101,100,32,117,115,105,110,103,32,97,32,115,99,114,105,112,116,32,110,97,109,101,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<92,112,123,71,114,101,101,107,125,32,92,80,123,72,97,110,125>>]}]},{p,[],[<<84,104,111,115,101,32,116,104,97,116,32,97,114,101,32,110,111,116,32,112,97,114,116,32,111,102,32,97,110,32,105,100,101,110,116,105,102,105,101,100,32,115,99,114,105,112,116,32,97,114,101,32,108,117,109,112,101,100,32,116,111,103,101,116,104,101,114,32,97,115,32,34,67,111,109,109,111,110,34,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,116,104,101,32,99,117,114,114,101,110,116,32,108,105,115,116,32,111,102,32,115,99,114,105,112,116,115,58>>]},{ul,[],[{li,[],[<<65,114,97,98,105,99>>]},{li,[],[<<65,114,109,101,110,105,97,110>>]},{li,[],[<<65,118,101,115,116,97,110>>]},{li,[],[<<66,97,108,105,110,101,115,101>>]},{li,[],[<<66,97,109,117,109>>]},{li,[],[<<66,97,115,115,97,95,86,97,104>>]},{li,[],[<<66,97,116,97,107>>]},{li,[],[<<66,101,110,103,97,108,105>>]},{li,[],[<<66,111,112,111,109,111,102,111>>]},{li,[],[<<66,114,97,105,108,108,101>>]},{li,[],[<<66,117,103,105,110,101,115,101>>]},{li,[],[<<66,117,104,105,100>>]},{li,[],[<<67,97,110,97,100,105,97,110,95,65,98,111,114,105,103,105,110,97,108>>]},{li,[],[<<67,97,114,105,97,110>>]},{li,[],[<<67,97,117,99,97,115,105,97,110,95,65,108,98,97,110,105,97,110>>]},{li,[],[<<67,104,97,107,109,97>>]},{li,[],[<<67,104,97,109>>]},{li,[],[<<67,104,101,114,111,107,101,101>>]},{li,[],[<<67,111,109,109,111,110>>]},{li,[],[<<67,111,112,116,105,99>>]},{li,[],[<<67,117,110,101,105,102,111,114,109>>]},{li,[],[<<67,121,112,114,105,111,116>>]},{li,[],[<<67,121,114,105,108,108,105,99>>]},{li,[],[<<68,101,115,101,114,101,116>>]},{li,[],[<<68,101,118,97,110,97,103,97,114,105>>]},{li,[],[<<68,117,112,108,111,121,97,110>>]},{li,[],[<<69,103,121,112,116,105,97,110,95,72,105,101,114,111,103,108,121,112,104,115>>]},{li,[],[<<69,108,98,97,115,97,110>>]},{li,[],[<<69,116,104,105,111,112,105,99>>]},{li,[],[<<71,101,111,114,103,105,97,110>>]},{li,[],[<<71,108,97,103,111,108,105,116,105,99>>]},{li,[],[<<71,111,116,104,105,99>>]},{li,[],[<<71,114,97,110,116,104,97>>]},{li,[],[<<71,114,101,101,107>>]},{li,[],[<<71,117,106,97,114,97,116,105>>]},{li,[],[<<71,117,114,109,117,107,104,105>>]},{li,[],[<<72,97,110>>]},{li,[],[<<72,97,110,103,117,108>>]},{li,[],[<<72,97,110,117,110,111,111>>]},{li,[],[<<72,101,98,114,101,119>>]},{li,[],[<<72,105,114,97,103,97,110,97>>]},{li,[],[<<73,109,112,101,114,105,97,108,95,65,114,97,109,97,105,99>>]},{li,[],[<<73,110,104,101,114,105,116,101,100>>]},{li,[],[<<73,110,115,99,114,105,112,116,105,111,110,97,108,95,80,97,104,108,97,118,105>>]},{li,[],[<<73,110,115,99,114,105,112,116,105,111,110,97,108,95,80,97,114,116,104,105,97,110>>]},{li,[],[<<74,97,118,97,110,101,115,101>>]},{li,[],[<<75,97,105,116,104,105>>]},{li,[],[<<75,97,110,110,97,100,97>>]},{li,[],[<<75,97,116,97,107,97,110,97>>]},{li,[],[<<75,97,121,97,104,95,76,105>>]},{li,[],[<<75,104,97,114,111,115,104,116,104,105>>]},{li,[],[<<75,104,109,101,114>>]},{li,[],[<<75,104,111,106,107,105>>]},{li,[],[<<75,104,117,100,97,119,97,100,105>>]},{li,[],[<<76,97,111>>]},{li,[],[<<76,97,116,105,110>>]},{li,[],[<<76,101,112,99,104,97>>]},{li,[],[<<76,105,109,98,117>>]},{li,[],[<<76,105,110,101,97,114,95,65>>]},{li,[],[<<76,105,110,101,97,114,95,66>>]},{li,[],[<<76,105,115,117>>]},{li,[],[<<76,121,99,105,97,110>>]},{li,[],[<<76,121,100,105,97,110>>]},{li,[],[<<77,97,104,97,106,97,110,105>>]},{li,[],[<<77,97,108,97,121,97,108,97,109>>]},{li,[],[<<77,97,110,100,97,105,99>>]},{li,[],[<<77,97,110,105,99,104,97,101,97,110>>]},{li,[],[<<77,101,101,116,101,105,95,77,97,121,101,107>>]},{li,[],[<<77,101,110,100,101,95,75,105,107,97,107,117,105>>]},{li,[],[<<77,101,114,111,105,116,105,99,95,67,117,114,115,105,118,101>>]},{li,[],[<<77,101,114,111,105,116,105,99,95,72,105,101,114,111,103,108,121,112,104,115>>]},{li,[],[<<77,105,97,111>>]},{li,[],[<<77,111,100,105>>]},{li,[],[<<77,111,110,103,111,108,105,97,110>>]},{li,[],[<<77,114,111>>]},{li,[],[<<77,121,97,110,109,97,114>>]},{li,[],[<<78,97,98,97,116,97,101,97,110>>]},{li,[],[<<78,101,119,95,84,97,105,95,76,117,101>>]},{li,[],[<<78,107,111>>]},{li,[],[<<79,103,104,97,109>>]},{li,[],[<<79,108,95,67,104,105,107,105>>]},{li,[],[<<79,108,100,95,73,116,97,108,105,99>>]},{li,[],[<<79,108,100,95,78,111,114,116,104,95,65,114,97,98,105,97,110>>]},{li,[],[<<79,108,100,95,80,101,114,109,105,99>>]},{li,[],[<<79,108,100,95,80,101,114,115,105,97,110>>]},{li,[],[<<79,114,105,121,97>>]},{li,[],[<<79,108,100,95,83,111,117,116,104,95,65,114,97,98,105,97,110>>]},{li,[],[<<79,108,100,95,84,117,114,107,105,99>>]},{li,[],[<<79,115,109,97,110,121,97>>]},{li,[],[<<80,97,104,97,119,104,95,72,109,111,110,103>>]},{li,[],[<<80,97,108,109,121,114,101,110,101>>]},{li,[],[<<80,97,117,95,67,105,110,95,72,97,117>>]},{li,[],[<<80,104,97,103,115,95,80,97>>]},{li,[],[<<80,104,111,101,110,105,99,105,97,110>>]},{li,[],[<<80,115,97,108,116,101,114,95,80,97,104,108,97,118,105>>]},{li,[],[<<82,101,106,97,110,103>>]},{li,[],[<<82,117,110,105,99>>]},{li,[],[<<83,97,109,97,114,105,116,97,110>>]},{li,[],[<<83,97,117,114,97,115,104,116,114,97>>]},{li,[],[<<83,104,97,114,97,100,97>>]},{li,[],[<<83,104,97,118,105,97,110>>]},{li,[],[<<83,105,100,100,104,97,109>>]},{li,[],[<<83,105,110,104,97,108,97>>]},{li,[],[<<83,111,114,97,95,83,111,109,112,101,110,103>>]},{li,[],[<<83,117,110,100,97,110,101,115,101>>]},{li,[],[<<83,121,108,111,116,105,95,78,97,103,114,105>>]},{li,[],[<<83,121,114,105,97,99>>]},{li,[],[<<84,97,103,97,108,111,103>>]},{li,[],[<<84,97,103,98,97,110,119,97>>]},{li,[],[<<84,97,105,95,76,101>>]},{li,[],[<<84,97,105,95,84,104,97,109>>]},{li,[],[<<84,97,105,95,86,105,101,116>>]},{li,[],[<<84,97,107,114,105>>]},{li,[],[<<84,97,109,105,108>>]},{li,[],[<<84,101,108,117,103,117>>]},{li,[],[<<84,104,97,97,110,97>>]},{li,[],[<<84,104,97,105>>]},{li,[],[<<84,105,98,101,116,97,110>>]},{li,[],[<<84,105,102,105,110,97,103,104>>]},{li,[],[<<84,105,114,104,117,116,97>>]},{li,[],[<<85,103,97,114,105,116,105,99>>]},{li,[],[<<86,97,105>>]},{li,[],[<<87,97,114,97,110,103,95,67,105,116,105>>]},{li,[],[<<89,105>>]}]},{p,[],[<<69,97,99,104,32,99,104,97,114,97,99,116,101,114,32,104,97,115,32,101,120,97,99,116,108,121,32,111,110,101,32,85,110,105,99,111,100,101,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,121,44,32,115,112,101,99,105,102,105,101,100,32,98,121,32,97,32,116,119,111,45,108,101,116,116,101,114,32,97,99,114,111,110,121,109,46,32,70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,80,101,114,108,44,32,110,101,103,97,116,105,111,110,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,105,110,99,108,117,100,105,110,103,32,97,32,99,105,114,99,117,109,102,108,101,120,32,98,101,116,119,101,101,110,32,116,104,101,32,111,112,101,110,105,110,103,32,98,114,97,99,101,32,97,110,100,32,116,104,101,32,112,114,111,112,101,114,116,121,32,110,97,109,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,92,112,123,94,76,117,125,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,92,80,123,76,117,125,46>>]},{p,[],[<<73,102,32,111,110,108,121,32,111,110,101,32,108,101,116,116,101,114,32,105,115,32,115,112,101,99,105,102,105,101,100,32,119,105,116,104,32,92,112,32,111,114,32,92,80,44,32,105,116,32,105,110,99,108,117,100,101,115,32,97,108,108,32,116,104,101,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,105,101,115,32,116,104,97,116,32,115,116,97,114,116,32,119,105,116,104,32,116,104,97,116,32,108,101,116,116,101,114,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,105,110,32,116,104,101,32,97,98,115,101,110,99,101,32,111,102,32,110,101,103,97,116,105,111,110,44,32,116,104,101,32,99,117,114,108,121,32,98,114,97,99,107,101,116,115,32,105,110,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,97,114,101,32,111,112,116,105,111,110,97,108,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,116,119,111,32,101,120,97,109,112,108,101,115,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,58>>]},{pre,[],[{code,[],[<<92,112,123,76,125,10,92,112,76>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,103,101,110,101,114,97,108,32,99,97,116,101,103,111,114,121,32,112,114,111,112,101,114,116,121,32,99,111,100,101,115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,58>>]},{dl,[],[{dt,[],[<<67>>]},{dd,[],[<<79,116,104,101,114>>]},{dt,[],[<<67,99>>]},{dd,[],[<<67,111,110,116,114,111,108>>]},{dt,[],[<<67,102>>]},{dd,[],[<<70,111,114,109,97,116>>]},{dt,[],[<<67,110>>]},{dd,[],[<<85,110,97,115,115,105,103,110,101,100>>]},{dt,[],[<<67,111>>]},{dd,[],[<<80,114,105,118,97,116,101,32,117,115,101>>]},{dt,[],[<<67,115>>]},{dd,[],[<<83,117,114,114,111,103,97,116,101>>]},{dt,[],[<<76>>]},{dd,[],[<<76,101,116,116,101,114>>]},{dt,[],[<<76,108>>]},{dd,[],[<<76,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114>>]},{dt,[],[<<76,109>>]},{dd,[],[<<77,111,100,105,102,105,101,114,32,108,101,116,116,101,114>>]},{dt,[],[<<76,111>>]},{dd,[],[<<79,116,104,101,114,32,108,101,116,116,101,114>>]},{dt,[],[<<76,116>>]},{dd,[],[<<84,105,116,108,101,32,99,97,115,101,32,108,101,116,116,101,114>>]},{dt,[],[<<76,117>>]},{dd,[],[<<85,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114>>]},{dt,[],[<<77>>]},{dd,[],[<<77,97,114,107>>]},{dt,[],[<<77,99>>]},{dd,[],[<<83,112,97,99,105,110,103,32,109,97,114,107>>]},{dt,[],[<<77,101>>]},{dd,[],[<<69,110,99,108,111,115,105,110,103,32,109,97,114,107>>]},{dt,[],[<<77,110>>]},{dd,[],[<<78,111,110,45,115,112,97,99,105,110,103,32,109,97,114,107>>]},{dt,[],[<<78>>]},{dd,[],[<<78,117,109,98,101,114>>]},{dt,[],[<<78,100>>]},{dd,[],[<<68,101,99,105,109,97,108,32,110,117,109,98,101,114>>]},{dt,[],[<<78,108>>]},{dd,[],[<<76,101,116,116,101,114,32,110,117,109,98,101,114>>]},{dt,[],[<<78,111>>]},{dd,[],[<<79,116,104,101,114,32,110,117,109,98,101,114>>]},{dt,[],[<<80>>]},{dd,[],[<<80,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,99>>]},{dd,[],[<<67,111,110,110,101,99,116,111,114,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,100>>]},{dd,[],[<<68,97,115,104,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,101>>]},{dd,[],[<<67,108,111,115,101,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,102>>]},{dd,[],[<<70,105,110,97,108,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,105>>]},{dd,[],[<<73,110,105,116,105,97,108,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,111>>]},{dd,[],[<<79,116,104,101,114,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<80,115>>]},{dd,[],[<<79,112,101,110,32,112,117,110,99,116,117,97,116,105,111,110>>]},{dt,[],[<<83>>]},{dd,[],[<<83,121,109,98,111,108>>]},{dt,[],[<<83,99>>]},{dd,[],[<<67,117,114,114,101,110,99,121,32,115,121,109,98,111,108>>]},{dt,[],[<<83,107>>]},{dd,[],[<<77,111,100,105,102,105,101,114,32,115,121,109,98,111,108>>]},{dt,[],[<<83,109>>]},{dd,[],[<<77,97,116,104,101,109,97,116,105,99,97,108,32,115,121,109,98,111,108>>]},{dt,[],[<<83,111>>]},{dd,[],[<<79,116,104,101,114,32,115,121,109,98,111,108>>]},{dt,[],[<<90>>]},{dd,[],[<<83,101,112,97,114,97,116,111,114>>]},{dt,[],[<<90,108>>]},{dd,[],[<<76,105,110,101,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<90,112>>]},{dd,[],[<<80,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114>>]},{dt,[],[<<90,115>>]},{dd,[],[<<83,112,97,99,101,32,115,101,112,97,114,97,116,111,114>>]}]},{p,[],[<<84,104,101,32,115,112,101,99,105,97,108,32,112,114,111,112,101,114,116,121,32,76,38,32,105,115,32,97,108,115,111,32,115,117,112,112,111,114,116,101,100,46,32,73,116,32,109,97,116,99,104,101,115,32,97,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,104,97,115,32,116,104,101,32,76,117,44,32,76,108,44,32,111,114,32,76,116,32,112,114,111,112,101,114,116,121,44,32,116,104,97,116,32,105,115,44,32,97,32,108,101,116,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,99,108,97,115,115,105,102,105,101,100,32,97,115,32,97,32,109,111,100,105,102,105,101,114,32,111,114,32,34,111,116,104,101,114,34,46>>]},{p,[],[<<84,104,101,32,67,115,32,40,83,117,114,114,111,103,97,116,101,41,32,112,114,111,112,101,114,116,121,32,97,112,112,108,105,101,115,32,111,110,108,121,32,116,111,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,85,43,68,56,48,48,32,116,111,32,85,43,68,70,70,70,46,32,83,117,99,104,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,105,110,118,97,108,105,100,32,105,110,32,85,110,105,99,111,100,101,32,115,116,114,105,110,103,115,32,97,110,100,32,115,111,32,99,97,110,110,111,116,32,98,101,32,116,101,115,116,101,100,32,98,121,32,80,67,82,69,46,32,80,101,114,108,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,32,67,115,32,112,114,111,112,101,114,116,121,46>>]},{p,[],[<<84,104,101,32,108,111,110,103,32,115,121,110,111,110,121,109,115,32,102,111,114,32,112,114,111,112,101,114,116,121,32,110,97,109,101,115,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,101,114,108,32,40,115,117,99,104,32,97,115,32,92,112,123,76,101,116,116,101,114,125,41,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,98,121,32,80,67,82,69,46,32,73,116,32,105,115,32,110,111,116,32,112,101,114,109,105,116,116,101,100,32,116,111,32,112,114,101,102,105,120,32,97,110,121,32,111,102,32,116,104,101,115,101,32,112,114,111,112,101,114,116,105,101,115,32,119,105,116,104,32,34,73,115,34,46>>]},{p,[],[<<78,111,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,85,110,105,99,111,100,101,32,116,97,98,108,101,32,104,97,115,32,116,104,101,32,67,110,32,40,117,110,97,115,115,105,103,110,101,100,41,32,112,114,111,112,101,114,116,121,46,32,84,104,105,115,32,112,114,111,112,101,114,116,121,32,105,115,32,105,110,115,116,101,97,100,32,97,115,115,117,109,101,100,32,102,111,114,32,97,110,121,32,99,111,100,101,32,112,111,105,110,116,32,116,104,97,116,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32,85,110,105,99,111,100,101,32,116,97,98,108,101,46>>]},{p,[],[<<83,112,101,99,105,102,121,105,110,103,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,115,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,92,112,123,76,117,125,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,111,110,108,121,32,117,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114,115,46,32,84,104,105,115,32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,99,117,114,114,101,110,116,32,118,101,114,115,105,111,110,115,32,111,102,32,80,101,114,108,46>>]},{p,[],[<<77,97,116,99,104,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,105,115,32,110,111,116,32,102,97,115,116,44,32,97,115,32,80,67,82,69,32,109,117,115,116,32,100,111,32,97,32,109,117,108,116,105,115,116,97,103,101,32,116,97,98,108,101,32,108,111,111,107,117,112,32,116,111,32,102,105,110,100,32,97,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,121,46,32,84,104,97,116,32,105,115,32,119,104,121,32,116,104,101,32,116,114,97,100,105,116,105,111,110,97,108,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,115,117,99,104,32,97,115,32,92,100,32,97,110,100,32,92,119,32,100,111,32,110,111,116,32,117,115,101,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,105,110,32,80,67,82,69,32,98,121,32,100,101,102,97,117,108,116,46,32,72,111,119,101,118,101,114,44,32,121,111,117,32,99,97,110,32,109,97,107,101,32,116,104,101,109,32,100,111,32,115,111,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,111,114,32,98,121,32,115,116,97,114,116,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,119,105,116,104,32,40,42,85,67,80,41,46>>]},{p,[],[{em,[],[<<69,120,116,101,110,100,101,100,32,71,114,97,112,104,101,109,101,32,67,108,117,115,116,101,114,115>>]}]},{p,[],[<<84,104,101,32,92,88,32,101,115,99,97,112,101,32,109,97,116,99,104,101,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,102,111,114,109,32,97,110,32,34,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114,34,44,32,97,110,100,32,116,114,101,97,116,115,32,116,104,101,32,115,101,113,117,101,110,99,101,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,40,115,101,101,32,98,101,108,111,119,41,46,32,85,112,32,116,111,32,97,110,100,32,105,110,99,108,117,100,105,110,103,32,114,101,108,101,97,115,101,32,56,46,51,49,44,32,80,67,82,69,32,109,97,116,99,104,101,100,32,97,110,32,101,97,114,108,105,101,114,44,32,115,105,109,112,108,101,114,32,100,101,102,105,110,105,116,105,111,110,32,116,104,97,116,32,119,97,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<40,63,62,92,80,77,92,112,77,42,41>>]},<<46,32,84,104,97,116,32,105,115,44,32,105,116,32,109,97,116,99,104,101,100,32,97,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,111,117,116,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,44,32,102,111,108,108,111,119,101,100,32,98,121,32,122,101,114,111,32,111,114,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,46,32,67,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,32,97,114,101,32,116,121,112,105,99,97,108,108,121,32,110,111,110,45,115,112,97,99,105,110,103,32,97,99,99,101,110,116,115,32,116,104,97,116,32,97,102,102,101,99,116,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,99,104,97,114,97,99,116,101,114,46>>]},{p,[],[<<84,104,105,115,32,115,105,109,112,108,101,32,100,101,102,105,110,105,116,105,111,110,32,119,97,115,32,101,120,116,101,110,100,101,100,32,105,110,32,85,110,105,99,111,100,101,32,116,111,32,105,110,99,108,117,100,101,32,109,111,114,101,32,99,111,109,112,108,105,99,97,116,101,100,32,107,105,110,100,115,32,111,102,32,99,111,109,112,111,115,105,116,101,32,99,104,97,114,97,99,116,101,114,32,98,121,32,103,105,118,105,110,103,32,101,97,99,104,32,99,104,97,114,97,99,116,101,114,32,97,32,103,114,97,112,104,101,109,101,32,98,114,101,97,107,105,110,103,32,112,114,111,112,101,114,116,121,44,32,97,110,100,32,99,114,101,97,116,105,110,103,32,114,117,108,101,115,32,116,104,97,116,32,117,115,101,32,116,104,101,115,101,32,112,114,111,112,101,114,116,105,101,115,32,116,111,32,100,101,102,105,110,101,32,116,104,101,32,98,111,117,110,100,97,114,105,101,115,32,111,102,32,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114,115,46,32,73,110,32,80,67,82,69,32,114,101,108,101,97,115,101,115,32,108,97,116,101,114,32,116,104,97,110,32,56,46,51,49,44,32,92,88,32,109,97,116,99,104,101,115,32,111,110,101,32,111,102,32,116,104,101,115,101,32,99,108,117,115,116,101,114,115,46>>]},{p,[],[<<92,88,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,97,116,32,108,101,97,115,116,32,111,110,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,110,32,105,116,32,100,101,99,105,100,101,115,32,119,104,101,116,104,101,114,32,116,111,32,97,100,100,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,117,108,101,115,32,102,111,114,32,101,110,100,105,110,103,32,97,32,99,108,117,115,116,101,114,58>>]},{ol,[],[{li,[],[{p,[],[<<69,110,100,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,101,110,100,32,98,101,116,119,101,101,110,32,67,82,32,97,110,100,32,76,70,59,32,111,116,104,101,114,119,105,115,101,32,101,110,100,32,97,102,116,101,114,32,97,110,121,32,99,111,110,116,114,111,108,32,99,104,97,114,97,99,116,101,114,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,98,114,101,97,107,32,72,97,110,103,117,108,32,40,97,32,75,111,114,101,97,110,32,115,99,114,105,112,116,41,32,115,121,108,108,97,98,108,101,32,115,101,113,117,101,110,99,101,115,46,32,72,97,110,103,117,108,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,111,102,32,102,105,118,101,32,116,121,112,101,115,58,32,76,44,32,86,44,32,84,44,32,76,86,44,32,97,110,100,32,76,86,84,46,32,65,110,32,76,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,76,44,32,86,44,32,76,86,44,32,111,114,32,76,86,84,32,99,104,97,114,97,99,116,101,114,46,32,65,110,32,76,86,32,111,114,32,86,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,86,32,111,114,32,84,32,99,104,97,114,97,99,116,101,114,46,32,65,110,32,76,86,84,32,111,114,32,84,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,102,111,108,108,111,119,101,100,32,111,110,108,121,32,98,121,32,97,32,84,32,99,104,97,114,97,99,116,101,114,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,101,110,100,32,98,101,102,111,114,101,32,101,120,116,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,32,111,114,32,115,112,97,99,105,110,103,32,109,97,114,107,115,46,32,67,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,34,109,97,114,107,34,32,112,114,111,112,101,114,116,121,32,97,108,119,97,121,115,32,104,97,118,101,32,116,104,101,32,34,101,120,116,101,110,100,34,32,103,114,97,112,104,101,109,101,32,98,114,101,97,107,105,110,103,32,112,114,111,112,101,114,116,121,46>>]}]},{li,[],[{p,[],[<<68,111,32,110,111,116,32,101,110,100,32,97,102,116,101,114,32,112,114,101,112,101,110,100,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},{li,[],[{p,[],[<<79,116,104,101,114,119,105,115,101,44,32,101,110,100,32,116,104,101,32,99,108,117,115,116,101,114,46>>]}]}]},{p,[],[{em,[],[<<80,67,82,69,32,65,100,100,105,116,105,111,110,97,108,32,80,114,111,112,101,114,116,105,101,115>>]}]},{p,[],[<<73,110,32,97,100,100,105,116,105,111,110,32,116,111,32,116,104,101,32,115,116,97,110,100,97,114,100,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,100,101,115,99,114,105,98,101,100,32,101,97,114,108,105,101,114,44,32,80,67,82,69,32,115,117,112,112,111,114,116,115,32,102,111,117,114,32,109,111,114,101,32,116,104,97,116,32,109,97,107,101,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,99,111,110,118,101,114,116,32,116,114,97,100,105,116,105,111,110,97,108,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,44,32,115,117,99,104,32,97,115,32,92,119,32,97,110,100,32,92,115,32,116,111,32,117,115,101,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,46,32,80,67,82,69,32,117,115,101,115,32,116,104,101,115,101,32,110,111,110,45,115,116,97,110,100,97,114,100,44,32,110,111,110,45,80,101,114,108,32,112,114,111,112,101,114,116,105,101,115,32,105,110,116,101,114,110,97,108,108,121,32,119,104,101,110,32,116,104,101,32>>,{code,[],[<<117,99,112>>]},<<32,111,112,116,105,111,110,32,105,115,32,112,97,115,115,101,100,46,32,72,111,119,101,118,101,114,44,32,116,104,101,121,32,99,97,110,32,97,108,115,111,32,98,101,32,117,115,101,100,32,101,120,112,108,105,99,105,116,108,121,46,32,84,104,101,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<88,97,110>>]},{dd,[],[{p,[],[<<65,110,121,32,97,108,112,104,97,110,117,109,101,114,105,99,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,101,105,116,104,101,114,32,116,104,101,32,76,32,40,108,101,116,116,101,114,41,32,111,114,32,116,104,101,32,78,32,40,110,117,109,98,101,114,41,32,112,114,111,112,101,114,116,121,46>>]}]},{dt,[],[<<88,112,115>>]},{dd,[],[{p,[],[<<65,110,121,32,80,111,115,105,120,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,97,98,44,32,108,105,110,101,32,102,101,101,100,44,32,118,101,114,116,105,99,97,108,32,116,97,98,44,32,102,111,114,109,32,102,101,101,100,44,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,44,32,97,110,100,32,97,110,121,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,104,97,115,32,116,104,101,32,90,32,40,115,101,112,97,114,97,116,111,114,41,32,112,114,111,112,101,114,116,121,46>>]}]},{dt,[],[<<88,115,112>>]},{dd,[],[{p,[],[<<65,110,121,32,80,101,114,108,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,97,115,32,88,112,115,44,32,101,120,99,101,112,116,32,116,104,97,116,32,118,101,114,116,105,99,97,108,32,116,97,98,32,105,115,32,101,120,99,108,117,100,101,100,46>>]}]},{dt,[],[<<88,119,100>>]},{dd,[],[{p,[],[<<65,110,121,32,80,101,114,108,32,34,119,111,114,100,34,32,99,104,97,114,97,99,116,101,114,46,32,77,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,88,97,110,44,32,112,108,117,115,32,117,110,100,101,114,115,99,111,114,101,46>>]}]}]},{p,[],[<<80,101,114,108,32,97,110,100,32,80,79,83,73,88,32,115,112,97,99,101,32,97,114,101,32,110,111,119,32,116,104,101,32,115,97,109,101,46,32,80,101,114,108,32,97,100,100,101,100,32,86,84,32,116,111,32,105,116,115,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,32,115,101,116,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,32,97,110,100,32,80,67,82,69,32,99,104,97,110,103,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46>>]},{p,[],[<<88,97,110,32,109,97,116,99,104,101,115,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,101,105,116,104,101,114,32,116,104,101,32,76,32,40,108,101,116,116,101,114,41,32,111,114,32,116,104,101,32,78,32,40,110,117,109,98,101,114,41,32,112,114,111,112,101,114,116,121,46,32,88,112,115,32,109,97,116,99,104,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,97,98,44,32,108,105,110,101,102,101,101,100,44,32,118,101,114,116,105,99,97,108,32,116,97,98,44,32,102,111,114,109,32,102,101,101,100,44,32,111,114,32,99,97,114,114,105,97,103,101,32,114,101,116,117,114,110,44,32,97,110,100,32,97,110,121,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,104,97,115,32,116,104,101,32,90,32,40,115,101,112,97,114,97,116,111,114,41,32,112,114,111,112,101,114,116,121,46,32,88,115,112,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,88,112,115,59,32,105,116,32,117,115,101,100,32,116,111,32,101,120,99,108,117,100,101,32,118,101,114,116,105,99,97,108,32,116,97,98,44,32,102,111,114,32,80,101,114,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,44,32,98,117,116,32,80,101,114,108,32,99,104,97,110,103,101,100,44,32,97,110,100,32,115,111,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46,32,88,119,100,32,109,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,88,97,110,44,32,112,108,117,115,32,117,110,100,101,114,115,99,111,114,101,46>>]},{p,[],[<<84,104,101,114,101,32,105,115,32,97,110,111,116,104,101,114,32,110,111,110,45,115,116,97,110,100,97,114,100,32,112,114,111,112,101,114,116,121,44,32,88,117,99,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,85,110,105,118,101,114,115,97,108,32,67,104,97,114,97,99,116,101,114,32,78,97,109,101,32,105,110,32,67,43,43,32,97,110,100,32,111,116,104,101,114,32,112,114,111,103,114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,115,46,32,84,104,101,115,101,32,97,114,101,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,36,44,32,64,44,32,96,32,40,103,114,97,118,101,32,97,99,99,101,110,116,41,44,32,97,110,100,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,85,110,105,99,111,100,101,32,99,111,100,101,32,112,111,105,110,116,115,32,62,61,32,85,43,48,48,65,48,44,32,101,120,99,101,112,116,32,102,111,114,32,116,104,101,32,115,117,114,114,111,103,97,116,101,115,32,85,43,68,56,48,48,32,116,111,32,85,43,68,70,70,70,46,32,78,111,116,105,99,101,32,116,104,97,116,32,109,111,115,116,32,98,97,115,101,32,40,65,83,67,73,73,41,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,101,120,99,108,117,100,101,100,46,32,40,85,110,105,118,101,114,115,97,108,32,67,104,97,114,97,99,116,101,114,32,78,97,109,101,115,32,97,114,101,32,111,102,32,116,104,101,32,102,111,114,109,32,92,117,72,72,72,72,32,111,114,32,92,85,72,72,72,72,72,72,72,72,44,32,119,104,101,114,101,32,72,32,105,115,32,97,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,46,32,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,88,117,99,32,112,114,111,112,101,114,116,121,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,115,101,32,115,101,113,117,101,110,99,101,115,32,98,117,116,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,116,104,101,121,32,114,101,112,114,101,115,101,110,116,46,41>>]},{p,[],[{em,[],[<<82,101,115,101,116,116,105,110,103,32,116,104,101,32,77,97,116,99,104,32,83,116,97,114,116>>]}]},{p,[],[<<84,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,75,32,99,97,117,115,101,115,32,97,110,121,32,112,114,101,118,105,111,117,115,108,121,32,109,97,116,99,104,101,100,32,99,104,97,114,97,99,116,101,114,115,32,110,111,116,32,116,111,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,116,104,101,32,102,105,110,97,108,32,109,97,116,99,104,101,100,32,115,101,113,117,101,110,99,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,102,111,111,98,97,114,34,44,32,98,117,116,32,114,101,112,111,114,116,115,32,116,104,97,116,32,105,116,32,104,97,115,32,109,97,116,99,104,101,100,32,34,98,97,114,34,58>>]},{pre,[],[{code,[],[<<102,111,111,92,75,98,97,114>>]}]},{p,[],[<<84,104,105,115,32,102,101,97,116,117,114,101,32,105,115,32,115,105,109,105,108,97,114,32,116,111,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,40,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,41,46,32,72,111,119,101,118,101,114,44,32,105,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,98,101,102,111,114,101,32,116,104,101,32,114,101,97,108,32,109,97,116,99,104,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,116,111,32,98,101,32,111,102,32,102,105,120,101,100,32,108,101,110,103,116,104,44,32,97,115,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,100,111,46,32,84,104,101,32,117,115,101,32,111,102,32,92,75,32,100,111,101,115,32,110,111,116,32,105,110,116,101,114,102,101,114,101,32,119,105,116,104,32,116,104,101,32,115,101,116,116,105,110,103,32,111,102,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,102,111,111,98,97,114,34,44,32,116,104,101,32,102,105,114,115,116,32,115,117,98,115,116,114,105,110,103,32,105,115,32,115,116,105,108,108,32,115,101,116,32,116,111,32,34,102,111,111,34,58>>]},{pre,[],[{code,[],[<<40,102,111,111,41,92,75,98,97,114>>]}]},{p,[],[<<80,101,114,108,32,100,111,99,117,109,101,110,116,115,32,116,104,97,116,32,116,104,101,32,117,115,101,32,111,102,32,92,75,32,119,105,116,104,105,110,32,97,115,115,101,114,116,105,111,110,115,32,105,115,32,34,110,111,116,32,119,101,108,108,32,100,101,102,105,110,101,100,34,46,32,73,110,32,80,67,82,69,44,32,92,75,32,105,115,32,97,99,116,101,100,32,117,112,111,110,32,119,104,101,110,32,105,116,32,111,99,99,117,114,115,32,105,110,115,105,100,101,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,44,32,98,117,116,32,105,115,32,105,103,110,111,114,101,100,32,105,110,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,78,111,116,101,32,116,104,97,116,32,119,104,101,110,32,97,32,112,97,116,116,101,114,110,32,115,117,99,104,32,97,115,32,40,63,61,97,98,92,75,41,32,109,97,116,99,104,101,115,44,32,116,104,101,32,114,101,112,111,114,116,101,100,32,115,116,97,114,116,32,111,102,32,116,104,101,32,109,97,116,99,104,32,99,97,110,32,98,101,32,103,114,101,97,116,101,114,32,116,104,97,110,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,109,97,116,99,104,46>>]},{p,[],[{em,[],[<<83,105,109,112,108,101,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<84,104,101,32,102,105,110,97,108,32,117,115,101,32,111,102,32,98,97,99,107,115,108,97,115,104,32,105,115,32,102,111,114,32,99,101,114,116,97,105,110,32,115,105,109,112,108,101,32,97,115,115,101,114,116,105,111,110,115,46,32,65,110,32,97,115,115,101,114,116,105,111,110,32,115,112,101,99,105,102,105,101,115,32,97,32,99,111,110,100,105,116,105,111,110,32,116,104,97,116,32,109,117,115,116,32,98,101,32,109,101,116,32,97,116,32,97,32,112,97,114,116,105,99,117,108,97,114,32,112,111,105,110,116,32,105,110,32,97,32,109,97,116,99,104,44,32,119,105,116,104,111,117,116,32,99,111,110,115,117,109,105,110,103,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,84,104,101,32,117,115,101,32,111,102,32,115,117,98,112,97,116,116,101,114,110,115,32,102,111,114,32,109,111,114,101,32,99,111,109,112,108,105,99,97,116,101,100,32,97,115,115,101,114,116,105,111,110,115,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,98,97,99,107,115,108,97,115,104,101,100,32,97,115,115,101,114,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[<<92,98>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,97,32,119,111,114,100,32,98,111,117,110,100,97,114,121,46>>]},{dt,[],[<<92,66>>]},{dd,[],[<<77,97,116,99,104,101,115,32,119,104,101,110,32,110,111,116,32,97,116,32,97,32,119,111,114,100,32,98,111,117,110,100,97,114,121,46>>]},{dt,[],[<<92,65>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46>>]},{dt,[],[<<92,90>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,97,110,100,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46>>]},{dt,[],[<<92,122>>]},{dd,[],[<<77,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46>>]},{dt,[],[<<92,71>>]},{dd,[],[<<77,97,116,99,104,101,115,32,97,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46>>]}]},{p,[],[<<73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,92,98,32,104,97,115,32,97,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,59,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,98,97,99,107,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,73,102,32,97,110,121,32,111,116,104,101,114,32,111,102,32,116,104,101,115,101,32,97,115,115,101,114,116,105,111,110,115,32,97,112,112,101,97,114,115,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,98,121,32,100,101,102,97,117,108,116,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,92,66,32,109,97,116,99,104,101,115,32,116,104,101,32,108,101,116,116,101,114,32,66,41,46>>]},{p,[],[<<65,32,119,111,114,100,32,98,111,117,110,100,97,114,121,32,105,115,32,97,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,119,104,101,114,101,32,116,104,101,32,99,117,114,114,101,110,116,32,99,104,97,114,97,99,116,101,114,32,97,110,100,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,104,97,114,97,99,116,101,114,32,100,111,32,110,111,116,32,98,111,116,104,32,109,97,116,99,104,32,92,119,32,111,114,32,92,87,32,40,116,104,97,116,32,105,115,44,32,111,110,101,32,109,97,116,99,104,101,115,32,92,119,32,97,110,100,32,116,104,101,32,111,116,104,101,114,32,109,97,116,99,104,101,115,32,92,87,41,44,32,111,114,32,116,104,101,32,115,116,97,114,116,32,111,114,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,105,102,32,116,104,101,32,102,105,114,115,116,32,111,114,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,32,109,97,116,99,104,101,115,32,92,119,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,73,110,32,85,84,70,32,109,111,100,101,44,32,116,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,92,119,32,97,110,100,32,92,87,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<46,32,87,104,101,110,32,116,104,105,115,32,105,115,32,100,111,110,101,44,32,105,116,32,97,108,115,111,32,97,102,102,101,99,116,115,32,92,98,32,97,110,100,32,92,66,46,32,80,67,82,69,32,97,110,100,32,80,101,114,108,32,100,111,32,110,111,116,32,104,97,118,101,32,97,32,115,101,112,97,114,97,116,101,32,34,115,116,97,114,116,32,111,102,32,119,111,114,100,34,32,111,114,32,34,101,110,100,32,111,102,32,119,111,114,100,34,32,109,101,116,97,115,101,113,117,101,110,99,101,46,32,72,111,119,101,118,101,114,44,32,119,104,97,116,101,118,101,114,32,102,111,108,108,111,119,115,32,92,98,32,110,111,114,109,97,108,108,121,32,100,101,116,101,114,109,105,110,101,115,32,119,104,105,99,104,32,105,116,32,105,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,114,97,103,109,101,110,116,32,92,98,97,32,109,97,116,99,104,101,115,32,34,97,34,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,119,111,114,100,46>>]},{p,[],[<<84,104,101,32,92,65,44,32,92,90,44,32,97,110,100,32,92,122,32,97,115,115,101,114,116,105,111,110,115,32,100,105,102,102,101,114,32,102,114,111,109,32,116,104,101,32,116,114,97,100,105,116,105,111,110,97,108,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,40,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41,32,105,110,32,116,104,97,116,32,116,104,101,121,32,111,110,108,121,32,101,118,101,114,32,109,97,116,99,104,32,97,116,32,116,104,101,32,118,101,114,121,32,115,116,97,114,116,32,97,110,100,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,119,104,97,116,101,118,101,114,32,111,112,116,105,111,110,115,32,97,114,101,32,115,101,116,46,32,84,104,117,115,44,32,116,104,101,121,32,97,114,101,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,46,32,84,104,101,115,101,32,116,104,114,101,101,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,32,110,111,116,32,97,102,102,101,99,116,101,100,32,98,121,32,111,112,116,105,111,110,115,32>>,{code,[],[<<110,111,116,98,111,108>>]},<<32,111,114,32>>,{code,[],[<<110,111,116,101,111,108>>]},<<44,32,119,104,105,99,104,32,97,102,102,101,99,116,32,111,110,108,121,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,46,32,72,111,119,101,118,101,114,44,32,105,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,105,115,32,110,111,110,45,122,101,114,111,44,32,105,110,100,105,99,97,116,105,110,103,32,116,104,97,116,32,109,97,116,99,104,105,110,103,32,105,115,32,116,111,32,115,116,97,114,116,32,97,116,32,97,32,112,111,105,110,116,32,111,116,104,101,114,32,116,104,97,110,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,92,65,32,99,97,110,32,110,101,118,101,114,32,109,97,116,99,104,46,32,84,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,101,116,119,101,101,110,32,92,90,32,97,110,100,32,92,122,32,105,115,32,116,104,97,116,32,92,90,32,109,97,116,99,104,101,115,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,97,110,100,32,97,116,32,116,104,101,32,118,101,114,121,32,101,110,100,44,32,119,104,105,108,101,32,92,122,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,46>>]},{p,[],[<<84,104,101,32,92,71,32,97,115,115,101,114,116,105,111,110,32,105,115,32,116,114,117,101,32,111,110,108,121,32,119,104,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,32,105,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,112,111,105,110,116,32,111,102,32,116,104,101,32,109,97,116,99,104,44,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<46,32,73,116,32,100,105,102,102,101,114,115,32,102,114,111,109,32,92,65,32,119,104,101,110,32,116,104,101,32,118,97,108,117,101,32,111,102,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,105,115,32,110,111,110,45,122,101,114,111,46,32,66,121,32,99,97,108,108,105,110,103,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,109,117,108,116,105,112,108,101,32,116,105,109,101,115,32,119,105,116,104,32,97,112,112,114,111,112,114,105,97,116,101,32,97,114,103,117,109,101,110,116,115,44,32,121,111,117,32,99,97,110,32,109,105,109,105,99,32,116,104,101,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,103>>]},<<44,32,97,110,100,32,105,116,32,105,115,32,105,110,32,116,104,105,115,32,107,105,110,100,32,111,102,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,119,104,101,114,101,32,92,71,32,99,97,110,32,98,101,32,117,115,101,102,117,108,46>>]},{p,[],[<<78,111,116,105,99,101,44,32,104,111,119,101,118,101,114,44,32,116,104,97,116,32,116,104,101,32,80,67,82,69,32,105,110,116,101,114,112,114,101,116,97,116,105,111,110,32,111,102,32,92,71,44,32,97,115,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,44,32,105,115,32,115,117,98,116,108,121,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32,80,101,114,108,44,32,119,104,105,99,104,32,100,101,102,105,110,101,115,32,105,116,32,97,115,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,112,114,101,118,105,111,117,115,32,109,97,116,99,104,46,32,73,110,32,80,101,114,108,44,32,116,104,101,115,101,32,99,97,110,32,98,101,32,100,105,102,102,101,114,101,110,116,32,119,104,101,110,32,116,104,101,32,112,114,101,118,105,111,117,115,108,121,32,109,97,116,99,104,101,100,32,115,116,114,105,110,103,32,119,97,115,32,101,109,112,116,121,46,32,65,115,32,80,67,82,69,32,100,111,101,115,32,111,110,108,121,32,111,110,101,32,109,97,116,99,104,32,97,116,32,97,32,116,105,109,101,44,32,105,116,32,99,97,110,110,111,116,32,114,101,112,114,111,100,117,99,101,32,116,104,105,115,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<73,102,32,97,108,108,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,111,102,32,97,32,112,97,116,116,101,114,110,32,98,101,103,105,110,32,119,105,116,104,32,92,71,44,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,97,110,99,104,111,114,101,100,32,116,111,32,116,104,101,32,115,116,97,114,116,105,110,103,32,109,97,116,99,104,32,112,111,115,105,116,105,111,110,44,32,97,110,100,32,116,104,101,32,34,97,110,99,104,111,114,101,100,34,32,102,108,97,103,32,105,115,32,115,101,116,32,105,110,32,116,104,101,32,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{a,[{id,<<115,101,99,116,52>>}],[]},{h2,[],[<<67,105,114,99,117,109,102,108,101,120,32,97,110,100,32,68,111,108,108,97,114>>]},{p,[],[<<84,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,122,101,114,111,45,119,105,100,116,104,32,97,115,115,101,114,116,105,111,110,115,46,32,84,104,97,116,32,105,115,44,32,116,104,101,121,32,116,101,115,116,32,102,111,114,32,97,32,112,97,114,116,105,99,117,108,97,114,32,99,111,110,100,105,116,105,111,110,32,116,111,32,98,101,32,116,114,117,101,32,119,105,116,104,111,117,116,32,99,111,110,115,117,109,105,110,103,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,102,114,111,109,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,105,110,32,116,104,101,32,100,101,102,97,117,108,116,32,109,97,116,99,104,105,110,103,32,109,111,100,101,44,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,99,104,97,114,97,99,116,101,114,32,105,115,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,32,111,110,108,121,32,105,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,73,102,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,105,115,32,110,111,110,45,122,101,114,111,44,32,99,105,114,99,117,109,102,108,101,120,32,99,97,110,32,110,101,118,101,114,32,109,97,116,99,104,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,117,110,115,101,116,46,32,73,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,99,105,114,99,117,109,102,108,101,120,32,104,97,115,32,97,110,32,101,110,116,105,114,101,108,121,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,32,40,115,101,101,32,98,101,108,111,119,41,46>>]},{p,[],[<<67,105,114,99,117,109,102,108,101,120,32,110,101,101,100,115,32,110,111,116,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,102,32,115,111,109,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,105,110,118,111,108,118,101,100,44,32,98,117,116,32,105,116,32,105,115,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,116,104,105,110,103,32,105,110,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,119,104,105,99,104,32,105,116,32,97,112,112,101,97,114,115,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,101,118,101,114,32,116,111,32,109,97,116,99,104,32,116,104,97,116,32,98,114,97,110,99,104,46,32,73,102,32,97,108,108,32,112,111,115,115,105,98,108,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,115,116,97,114,116,32,119,105,116,104,32,97,32,99,105,114,99,117,109,102,108,101,120,44,32,116,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,99,111,110,115,116,114,97,105,110,101,100,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,105,116,32,105,115,32,115,97,105,100,32,116,111,32,98,101,32,97,110,32,34,97,110,99,104,111,114,101,100,34,32,112,97,116,116,101,114,110,46,32,40,84,104,101,114,101,32,97,114,101,32,97,108,115,111,32,111,116,104,101,114,32,99,111,110,115,116,114,117,99,116,115,32,116,104,97,116,32,99,97,110,32,99,97,117,115,101,32,97,32,112,97,116,116,101,114,110,32,116,111,32,98,101,32,97,110,99,104,111,114,101,100,46,41>>]},{p,[],[<<84,104,101,32,100,111,108,108,97,114,32,99,104,97,114,97,99,116,101,114,32,105,115,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,32,111,110,108,121,32,105,102,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,111,114,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,40,98,121,32,100,101,102,97,117,108,116,41,46,32,78,111,116,105,99,101,32,104,111,119,101,118,101,114,32,116,104,97,116,32,105,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,110,101,119,108,105,110,101,46,32,68,111,108,108,97,114,32,110,101,101,100,115,32,110,111,116,32,116,111,32,98,101,32,116,104,101,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,102,32,115,111,109,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,105,110,118,111,108,118,101,100,44,32,98,117,116,32,105,116,32,105,115,32,116,111,32,98,101,32,116,104,101,32,108,97,115,116,32,105,116,101,109,32,105,110,32,97,110,121,32,98,114,97,110,99,104,32,105,110,32,119,104,105,99,104,32,105,116,32,97,112,112,101,97,114,115,46,32,68,111,108,108,97,114,32,104,97,115,32,110,111,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46>>]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,100,111,108,108,97,114,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,105,116,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,118,101,114,121,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]},<<32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46,32,84,104,105,115,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,92,90,32,97,115,115,101,114,116,105,111,110,46>>]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,99,104,97,110,103,101,100,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46,32,87,104,101,110,32,116,104,105,115,32,105,115,32,116,104,101,32,99,97,115,101,44,32,97,32,99,105,114,99,117,109,102,108,101,120,32,109,97,116,99,104,101,115,32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,105,110,116,101,114,110,97,108,32,110,101,119,108,105,110,101,115,32,97,110,100,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,73,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,97,102,116,101,114,32,97,32,110,101,119,108,105,110,101,32,116,104,97,116,32,101,110,100,115,32,116,104,101,32,115,116,114,105,110,103,46,32,65,32,100,111,108,108,97,114,32,109,97,116,99,104,101,115,32,98,101,102,111,114,101,32,97,110,121,32,110,101,119,108,105,110,101,115,32,105,110,32,116,104,101,32,115,116,114,105,110,103,44,32,97,110,100,32,97,116,32,116,104,101,32,118,101,114,121,32,101,110,100,44,32,119,104,101,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46,32,87,104,101,110,32,110,101,119,108,105,110,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,44,32,105,115,111,108,97,116,101,100,32,67,82,32,97,110,100,32,76,70,32,99,104,97,114,97,99,116,101,114,115,32,100,111,32,110,111,116,32,105,110,100,105,99,97,116,101,32,110,101,119,108,105,110,101,115,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,112,97,116,116,101,114,110,32,47,94,97,98,99,36,47,32,109,97,116,99,104,101,115,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,34,100,101,102,92,110,97,98,99,34,32,40,119,104,101,114,101,32,92,110,32,114,101,112,114,101,115,101,110,116,115,32,97,32,110,101,119,108,105,110,101,41,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,44,32,98,117,116,32,110,111,116,32,111,116,104,101,114,119,105,115,101,46,32,83,111,44,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,97,110,99,104,111,114,101,100,32,105,110,32,115,105,110,103,108,101,45,108,105,110,101,32,109,111,100,101,32,98,101,99,97,117,115,101,32,97,108,108,32,98,114,97,110,99,104,101,115,32,115,116,97,114,116,32,119,105,116,104,32,94,32,97,114,101,32,110,111,116,32,97,110,99,104,111,114,101,100,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,44,32,97,110,100,32,97,32,109,97,116,99,104,32,102,111,114,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,112,111,115,115,105,98,108,101,32,119,104,101,110,32,97,114,103,117,109,101,110,116,32>>,{em,[],[<<115,116,97,114,116,111,102,102,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,105,115,32,110,111,110,45,122,101,114,111,46,32,79,112,116,105,111,110,32>>,{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]},<<32,105,115,32,105,103,110,111,114,101,100,32,105,102,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,115,101,113,117,101,110,99,101,115,32,92,65,44,32,92,90,44,32,97,110,100,32,92,122,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,109,97,116,99,104,32,116,104,101,32,115,116,97,114,116,32,97,110,100,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,110,32,98,111,116,104,32,109,111,100,101,115,46,32,73,102,32,97,108,108,32,98,114,97,110,99,104,101,115,32,111,102,32,97,32,112,97,116,116,101,114,110,32,115,116,97,114,116,32,119,105,116,104,32,92,65,44,32,105,116,32,105,115,32,97,108,119,97,121,115,32,97,110,99,104,111,114,101,100,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,101,116,46>>]},{a,[{id,<<115,101,99,116,53>>}],[]},{h2,[],[<<70,117,108,108,32,83,116,111,112,32,40,80,101,114,105,111,100,44,32,68,111,116,41,32,97,110,100,32,92,78>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,32,100,111,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,101,120,99,101,112,116,32,40,98,121,32,100,101,102,97,117,108,116,41,32,97,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,115,105,103,110,105,102,105,101,115,32,116,104,101,32,101,110,100,32,111,102,32,97,32,108,105,110,101,46>>]},{p,[],[<<87,104,101,110,32,97,32,108,105,110,101,32,101,110,100,105,110,103,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,44,32,100,111,116,32,110,101,118,101,114,32,109,97,116,99,104,101,115,32,116,104,97,116,32,99,104,97,114,97,99,116,101,114,46,32,87,104,101,110,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,32,105,115,32,117,115,101,100,44,32,100,111,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,67,82,32,105,102,32,105,116,32,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,101,100,32,98,121,32,76,70,44,32,111,116,104,101,114,119,105,115,101,32,105,116,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,99,108,117,100,105,110,103,32,105,115,111,108,97,116,101,100,32,67,82,115,32,97,110,100,32,76,70,115,41,46,32,87,104,101,110,32,97,110,121,32,85,110,105,99,111,100,101,32,108,105,110,101,32,101,110,100,105,110,103,115,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,44,32,100,111,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,67,82,44,32,76,70,44,32,111,114,32,97,110,121,32,111,102,32,116,104,101,32,111,116,104,101,114,32,108,105,110,101,45,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,100,111,116,32,114,101,103,97,114,100,105,110,103,32,110,101,119,108,105,110,101,115,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,105,115,32,115,101,116,44,32,97,32,100,111,116,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,44,32,119,105,116,104,111,117,116,32,101,120,99,101,112,116,105,111,110,46,32,73,102,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,67,82,76,70,32,105,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,105,116,32,116,97,107,101,115,32,116,119,111,32,100,111,116,115,32,116,111,32,109,97,116,99,104,32,105,116,46>>]},{p,[],[<<84,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,100,111,116,32,105,115,32,101,110,116,105,114,101,108,121,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,116,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,99,105,114,99,117,109,102,108,101,120,32,97,110,100,32,100,111,108,108,97,114,44,32,116,104,101,32,111,110,108,121,32,114,101,108,97,116,105,111,110,115,104,105,112,32,105,115,32,116,104,97,116,32,98,111,116,104,32,105,110,118,111,108,118,101,32,110,101,119,108,105,110,101,115,46,32,68,111,116,32,104,97,115,32,110,111,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46>>]},{p,[],[<<84,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,78,32,98,101,104,97,118,101,115,32,108,105,107,101,32,97,32,100,111,116,44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,105,115,32,110,111,116,32,97,102,102,101,99,116,101,100,32,98,121,32,111,112,116,105,111,110,32>>,{code,[],[<<80,67,82,69,95,68,79,84,65,76,76>>]},<<46,32,84,104,97,116,32,105,115,44,32,105,116,32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,101,120,99,101,112,116,32,111,110,101,32,116,104,97,116,32,115,105,103,110,105,102,105,101,115,32,116,104,101,32,101,110,100,32,111,102,32,97,32,108,105,110,101,46,32,80,101,114,108,32,97,108,115,111,32,117,115,101,115,32,92,78,32,116,111,32,109,97,116,99,104,32,99,104,97,114,97,99,116,101,114,115,32,98,121,32,110,97,109,101,32,98,117,116,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,105,115,46>>]},{a,[{id,<<115,101,99,116,54>>}],[]},{h2,[],[<<77,97,116,99,104,105,110,103,32,97,32,83,105,110,103,108,101,32,68,97,116,97,32,85,110,105,116>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,67,32,109,97,116,99,104,101,115,32,97,110,121,32,100,97,116,97,32,117,110,105,116,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32,97,32,85,84,70,32,109,111,100,101,32,105,115,32,115,101,116,46,32,79,110,101,32,100,97,116,97,32,117,110,105,116,32,105,115,32,111,110,101,32,98,121,116,101,46,32,85,110,108,105,107,101,32,97,32,100,111,116,44,32,92,67,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,108,105,110,101,45,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,102,101,97,116,117,114,101,32,105,115,32,112,114,111,118,105,100,101,100,32,105,110,32,80,101,114,108,32,116,111,32,109,97,116,99,104,32,105,110,100,105,118,105,100,117,97,108,32,98,121,116,101,115,32,105,110,32,85,84,70,45,56,32,109,111,100,101,44,32,98,117,116,32,105,116,32,105,115,32,117,110,99,108,101,97,114,32,104,111,119,32,105,116,32,99,97,110,32,117,115,101,102,117,108,108,121,32,98,101,32,117,115,101,100,46,32,65,115,32,92,67,32,98,114,101,97,107,115,32,117,112,32,99,104,97,114,97,99,116,101,114,115,32,105,110,116,111,32,105,110,100,105,118,105,100,117,97,108,32,100,97,116,97,32,117,110,105,116,115,44,32,109,97,116,99,104,105,110,103,32,111,110,101,32,117,110,105,116,32,119,105,116,104,32,92,67,32,105,110,32,97,32,85,84,70,32,109,111,100,101,32,109,101,97,110,115,32,116,104,97,116,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,115,116,114,105,110,103,32,99,97,110,32,115,116,97,114,116,32,119,105,116,104,32,97,32,109,97,108,102,111,114,109,101,100,32,85,84,70,32,99,104,97,114,97,99,116,101,114,46,32,84,104,105,115,32,104,97,115,32,117,110,100,101,102,105,110,101,100,32,114,101,115,117,108,116,115,44,32,97,115,32,80,67,82,69,32,97,115,115,117,109,101,115,32,116,104,97,116,32,105,116,32,100,101,97,108,115,32,119,105,116,104,32,118,97,108,105,100,32,85,84,70,32,115,116,114,105,110,103,115,46>>]},{p,[],[<<80,67,82,69,32,100,111,101,115,32,110,111,116,32,97,108,108,111,119,32,92,67,32,116,111,32,97,112,112,101,97,114,32,105,110,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,40,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,41,32,105,110,32,97,32,85,84,70,32,109,111,100,101,44,32,97,115,32,116,104,105,115,32,119,111,117,108,100,32,109,97,107,101,32,105,116,32,105,109,112,111,115,115,105,98,108,101,32,116,111,32,99,97,108,99,117,108,97,116,101,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,108,111,111,107,98,101,104,105,110,100,46>>]},{p,[],[<<84,104,101,32,92,67,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,105,115,32,98,101,115,116,32,97,118,111,105,100,101,100,46,32,72,111,119,101,118,101,114,44,32,111,110,101,32,119,97,121,32,111,102,32,117,115,105,110,103,32,105,116,32,116,104,97,116,32,97,118,111,105,100,115,32,116,104,101,32,112,114,111,98,108,101,109,32,111,102,32,109,97,108,102,111,114,109,101,100,32,85,84,70,32,99,104,97,114,97,99,116,101,114,115,32,105,115,32,116,111,32,117,115,101,32,97,32,108,111,111,107,97,104,101,97,100,32,116,111,32,99,104,101,99,107,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,44,32,97,115,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,97,32,85,84,70,45,56,32,115,116,114,105,110,103,32,40,105,103,110,111,114,101,32,119,104,105,116,101,115,112,97,99,101,32,97,110,100,32,108,105,110,101,32,98,114,101,97,107,115,41,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<40,63,124,32,40,63,61,91,92,120,48,48,45,92,120,55,102,93,41,40,92,67,41,32,124,10,32,32,32,32,40,63,61,91,92,120,56,48,45,92,120,123,55,102,102,125,93,41,40,92,67,41,40,92,67,41,32,124,10,32,32,32,32,40,63,61,91,92,120,123,56,48,48,125,45,92,120,123,102,102,102,102,125,93,41,40,92,67,41,40,92,67,41,40,92,67,41,32,124,10,32,32,32,32,40,63,61,91,92,120,123,49,48,48,48,48,125,45,92,120,123,49,102,102,102,102,102,125,93,41,40,92,67,41,40,92,67,41,40,92,67,41,40,92,67,41,41>>]}]},{p,[],[<<65,32,103,114,111,117,112,32,116,104,97,116,32,115,116,97,114,116,115,32,119,105,116,104,32,40,63,124,32,114,101,115,101,116,115,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,110,117,109,98,101,114,115,32,105,110,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]},<<41,46,32,84,104,101,32,97,115,115,101,114,116,105,111,110,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,101,97,99,104,32,98,114,97,110,99,104,32,99,104,101,99,107,32,116,104,101,32,110,101,120,116,32,85,84,70,45,56,32,99,104,97,114,97,99,116,101,114,32,102,111,114,32,118,97,108,117,101,115,32,119,104,111,115,101,32,101,110,99,111,100,105,110,103,32,117,115,101,115,32,49,44,32,50,44,32,51,44,32,111,114,32,52,32,98,121,116,101,115,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,84,104,101,32,105,110,100,105,118,105,100,117,97,108,32,98,121,116,101,115,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,97,114,101,32,116,104,101,110,32,99,97,112,116,117,114,101,100,32,98,121,32,116,104,101,32,97,112,112,114,111,112,114,105,97,116,101,32,110,117,109,98,101,114,32,111,102,32,103,114,111,117,112,115,46>>]},{a,[{id,<<115,101,99,116,55>>}],[]},{h2,[],[<<83,113,117,97,114,101,32,66,114,97,99,107,101,116,115,32,97,110,100,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]},{p,[],[<<65,110,32,111,112,101,110,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,105,110,116,114,111,100,117,99,101,115,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,116,101,114,109,105,110,97,116,101,100,32,98,121,32,97,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,46,32,65,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,111,110,32,105,116,115,32,111,119,110,32,105,115,32,110,111,116,32,115,112,101,99,105,97,108,32,98,121,32,100,101,102,97,117,108,116,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<80,67,82,69,95,74,65,86,65,83,67,82,73,80,84,95,67,79,77,80,65,84>>]},<<32,105,115,32,115,101,116,44,32,97,32,108,111,110,101,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,99,97,117,115,101,115,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,46,32,73,102,32,97,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,105,115,32,114,101,113,117,105,114,101,100,32,97,115,32,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,99,108,97,115,115,44,32,105,116,32,105,115,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,99,108,97,115,115,32,40,97,102,116,101,114,32,97,110,32,105,110,105,116,105,97,108,32,99,105,114,99,117,109,102,108,101,120,44,32,105,102,32,112,114,101,115,101,110,116,41,32,111,114,32,101,115,99,97,112,101,100,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,46>>]},{p,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,73,110,32,97,32,85,84,70,32,109,111,100,101,44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,100,97,116,97,32,117,110,105,116,32,108,111,110,103,46,32,65,32,109,97,116,99,104,101,100,32,99,104,97,114,97,99,116,101,114,32,109,117,115,116,32,98,101,32,105,110,32,116,104,101,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,100,101,102,105,110,101,100,32,98,121,32,116,104,101,32,99,108,97,115,115,44,32,117,110,108,101,115,115,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,99,108,97,115,115,32,100,101,102,105,110,105,116,105,111,110,32,105,115,32,97,32,99,105,114,99,117,109,102,108,101,120,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,116,104,101,32,115,117,98,106,101,99,116,32,99,104,97,114,97,99,116,101,114,32,109,117,115,116,32,110,111,116,32,98,101,32,105,110,32,116,104,101,32,115,101,116,32,100,101,102,105,110,101,100,32,98,121,32,116,104,101,32,99,108,97,115,115,46,32,73,102,32,97,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,114,101,113,117,105,114,101,100,32,97,115,32,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,99,108,97,115,115,44,32,101,110,115,117,114,101,32,116,104,97,116,32,105,116,32,105,115,32,110,111,116,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,101,115,99,97,112,101,32,105,116,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,46>>]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32>>,{code,[],[<<91,97,101,105,111,117,93>>]},<<32,109,97,116,99,104,101,115,32,97,110,121,32,108,111,119,101,114,99,97,115,101,32,118,111,119,101,108,44,32,119,104,105,108,101,32>>,{code,[],[<<91,94,97,101,105,111,117,93>>]},<<32,109,97,116,99,104,101,115,32,97,110,121,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,110,111,116,32,97,32,108,111,119,101,114,99,97,115,101,32,118,111,119,101,108,46,32,78,111,116,105,99,101,32,116,104,97,116,32,97,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,106,117,115,116,32,97,32,99,111,110,118,101,110,105,101,110,116,32,110,111,116,97,116,105,111,110,32,102,111,114,32,115,112,101,99,105,102,121,105,110,103,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,105,110,32,116,104,101,32,99,108,97,115,115,32,98,121,32,101,110,117,109,101,114,97,116,105,110,103,32,116,104,111,115,101,32,116,104,97,116,32,97,114,101,32,110,111,116,46,32,65,32,99,108,97,115,115,32,116,104,97,116,32,115,116,97,114,116,115,32,119,105,116,104,32,97,32,99,105,114,99,117,109,102,108,101,120,32,105,115,32,110,111,116,32,97,110,32,97,115,115,101,114,116,105,111,110,59,32,105,116,32,115,116,105,108,108,32,99,111,110,115,117,109,101,115,32,97,32,99,104,97,114,97,99,116,101,114,32,102,114,111,109,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,110,100,32,116,104,101,114,101,102,111,114,101,32,105,116,32,102,97,105,108,115,32,105,102,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,105,110,116,101,114,32,105,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,46>>]},{p,[],[<<73,110,32,85,84,70,45,56,32,109,111,100,101,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,32,40,48,120,102,102,102,102,41,32,99,97,110,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,32,99,108,97,115,115,32,97,115,32,97,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,32,111,102,32,100,97,116,97,32,117,110,105,116,115,44,32,111,114,32,98,121,32,117,115,105,110,103,32,116,104,101,32,92,120,123,32,101,115,99,97,112,105,110,103,32,109,101,99,104,97,110,105,115,109,46>>]},{p,[],[<<87,104,101,110,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,115,101,116,44,32,97,110,121,32,108,101,116,116,101,114,115,32,105,110,32,97,32,99,108,97,115,115,32,114,101,112,114,101,115,101,110,116,32,98,111,116,104,32,116,104,101,105,114,32,117,112,112,101,114,99,97,115,101,32,97,110,100,32,108,111,119,101,114,99,97,115,101,32,118,101,114,115,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,32,99,97,115,101,108,101,115,115,32>>,{code,[],[<<91,97,101,105,111,117,93>>]},<<32,109,97,116,99,104,101,115,32,34,65,34,32,97,110,100,32,34,97,34,44,32,97,110,100,32,97,32,99,97,115,101,108,101,115,115,32>>,{code,[],[<<91,94,97,101,105,111,117,93>>]},<<32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,34,65,34,44,32,98,117,116,32,97,32,99,97,115,101,102,117,108,32,118,101,114,115,105,111,110,32,119,111,117,108,100,46,32,73,110,32,97,32,85,84,70,32,109,111,100,101,44,32,80,67,82,69,32,97,108,119,97,121,115,32,117,110,100,101,114,115,116,97,110,100,115,32,116,104,101,32,99,111,110,99,101,112,116,32,111,102,32,99,97,115,101,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,118,97,108,117,101,115,32,97,114,101,32,60,32,50,53,54,44,32,115,111,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,97,108,119,97,121,115,32,112,111,115,115,105,98,108,101,46,32,70,111,114,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,104,105,103,104,101,114,32,118,97,108,117,101,115,44,32,116,104,101,32,99,111,110,99,101,112,116,32,111,102,32,99,97,115,101,32,105,115,32,115,117,112,112,111,114,116,101,100,32,111,110,108,121,32,105,102,32,80,67,82,69,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,46,32,73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,110,32,97,32,85,84,70,32,109,111,100,101,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,62,61,44,32,101,110,115,117,114,101,32,116,104,97,116,32,80,67,82,69,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,32,97,110,100,32,119,105,116,104,32,85,84,70,32,115,117,112,112,111,114,116,46>>]},{p,[],[<<67,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,99,97,110,32,105,110,100,105,99,97,116,101,32,108,105,110,101,32,98,114,101,97,107,115,32,97,114,101,32,110,101,118,101,114,32,116,114,101,97,116,101,100,32,105,110,32,97,110,121,32,115,112,101,99,105,97,108,32,119,97,121,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,44,32,119,104,97,116,101,118,101,114,32,108,105,110,101,45,101,110,100,105,110,103,32,115,101,113,117,101,110,99,101,32,105,115,32,105,110,32,117,115,101,44,32,97,110,100,32,119,104,97,116,101,118,101,114,32,115,101,116,116,105,110,103,32,111,102,32,111,112,116,105,111,110,115,32>>,{code,[],[<<80,67,82,69,95,68,79,84,65,76,76>>]},<<32,97,110,100,32>>,{code,[],[<<80,67,82,69,95,77,85,76,84,73,76,73,78,69>>]},<<32,105,115,32,117,115,101,100,46,32,65,32,99,108,97,115,115,32,115,117,99,104,32,97,115,32,91,94,97,93,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,111,110,101,32,111,102,32,116,104,101,115,101,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,109,105,110,117,115,32,40,104,121,112,104,101,110,41,32,99,104,97,114,97,99,116,101,114,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,115,112,101,99,105,102,121,32,97,32,114,97,110,103,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,100,45,109,93,32,109,97,116,99,104,101,115,32,97,110,121,32,108,101,116,116,101,114,32,98,101,116,119,101,101,110,32,100,32,97,110,100,32,109,44,32,105,110,99,108,117,115,105,118,101,46,32,73,102,32,97,32,109,105,110,117,115,32,99,104,97,114,97,99,116,101,114,32,105,115,32,114,101,113,117,105,114,101,100,32,105,110,32,97,32,99,108,97,115,115,44,32,105,116,32,109,117,115,116,32,98,101,32,101,115,99,97,112,101,100,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,32,111,114,32,97,112,112,101,97,114,32,105,110,32,97,32,112,111,115,105,116,105,111,110,32,119,104,101,114,101,32,105,116,32,99,97,110,110,111,116,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,105,110,100,105,99,97,116,105,110,103,32,97,32,114,97,110,103,101,44,32,116,121,112,105,99,97,108,108,121,32,97,115,32,116,104,101,32,102,105,114,115,116,32,111,114,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,99,108,97,115,115,44,32,111,114,32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,97,32,114,97,110,103,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,98,45,100,45,122,93,32,109,97,116,99,104,101,115,32,108,101,116,116,101,114,115,32,105,110,32,116,104,101,32,114,97,110,103,101,32,98,32,116,111,32,100,44,32,97,32,104,121,112,104,101,110,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,122,46>>]},{p,[],[<<84,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,32,34,93,34,32,99,97,110,110,111,116,32,98,101,32,116,104,101,32,101,110,100,32,99,104,97,114,97,99,116,101,114,32,111,102,32,97,32,114,97,110,103,101,46,32,65,32,112,97,116,116,101,114,110,32,115,117,99,104,32,97,115,32,91,87,45,93,52,54,93,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,99,108,97,115,115,32,111,102,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,32,40,34,87,34,32,97,110,100,32,34,45,34,41,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,32,34,52,54,93,34,44,32,115,111,32,105,116,32,119,111,117,108,100,32,109,97,116,99,104,32,34,87,52,54,93,34,32,111,114,32,34,45,52,54,93,34,46,32,72,111,119,101,118,101,114,44,32,105,102,32,34,93,34,32,105,115,32,101,115,99,97,112,101,100,32,119,105,116,104,32,97,32,98,97,99,107,115,108,97,115,104,44,32,105,116,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,116,104,101,32,101,110,100,32,111,102,32,114,97,110,103,101,44,32,115,111,32,91,87,45,92,93,52,54,93,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,99,108,97,115,115,32,99,111,110,116,97,105,110,105,110,103,32,97,32,114,97,110,103,101,32,102,111,108,108,111,119,101,100,32,98,121,32,116,119,111,32,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,111,99,116,97,108,32,111,114,32,104,101,120,97,100,101,99,105,109,97,108,32,114,101,112,114,101,115,101,110,116,97,116,105,111,110,32,111,102,32,34,93,34,32,99,97,110,32,97,108,115,111,32,98,101,32,117,115,101,100,32,116,111,32,101,110,100,32,97,32,114,97,110,103,101,46>>]},{p,[],[<<65,110,32,101,114,114,111,114,32,105,115,32,103,101,110,101,114,97,116,101,100,32,105,102,32,97,32,80,79,83,73,88,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,40,115,101,101,32,98,101,108,111,119,41,32,111,114,32,97,110,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,111,116,104,101,114,32,116,104,97,110,32,111,110,101,32,116,104,97,116,32,100,101,102,105,110,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,97,112,112,101,97,114,115,32,97,116,32,97,32,112,111,105,110,116,32,119,104,101,114,101,32,97,32,114,97,110,103,101,32,101,110,100,105,110,103,32,99,104,97,114,97,99,116,101,114,32,105,115,32,101,120,112,101,99,116,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,122,45,92,120,102,102,93,32,105,115,32,118,97,108,105,100,44,32,98,117,116,32,91,65,45,92,100,93,32,97,110,100,32,91,65,45,91,58,100,105,103,105,116,58,93,93,32,97,114,101,32,110,111,116,46>>]},{p,[],[<<82,97,110,103,101,115,32,111,112,101,114,97,116,101,32,105,110,32,116,104,101,32,99,111,108,108,97,116,105,110,103,32,115,101,113,117,101,110,99,101,32,111,102,32,99,104,97,114,97,99,116,101,114,32,118,97,108,117,101,115,46,32,84,104,101,121,32,99,97,110,32,97,108,115,111,32,98,101,32,117,115,101,100,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,115,112,101,99,105,102,105,101,100,32,110,117,109,101,114,105,99,97,108,108,121,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,91,92,48,48,48,45,92,48,51,55,93,46,32,82,97,110,103,101,115,32,99,97,110,32,105,110,99,108,117,100,101,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,118,97,108,105,100,32,102,111,114,32,116,104,101,32,99,117,114,114,101,110,116,32,109,111,100,101,46>>]},{p,[],[<<73,102,32,97,32,114,97,110,103,101,32,116,104,97,116,32,105,110,99,108,117,100,101,115,32,108,101,116,116,101,114,115,32,105,115,32,117,115,101,100,32,119,104,101,110,32,99,97,115,101,108,101,115,115,32,109,97,116,99,104,105,110,103,32,105,115,32,115,101,116,44,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,108,101,116,116,101,114,115,32,105,110,32,101,105,116,104,101,114,32,99,97,115,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,87,45,99,93,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,91,93,91,92,92,94,95,96,119,120,121,122,97,98,99,93,44,32,109,97,116,99,104,101,100,32,99,97,115,101,108,101,115,115,108,121,46,32,73,110,32,97,32,110,111,110,45,85,84,70,32,109,111,100,101,44,32,105,102,32,99,104,97,114,97,99,116,101,114,32,116,97,98,108,101,115,32,102,111,114,32,97,32,70,114,101,110,99,104,32,108,111,99,97,108,101,32,97,114,101,32,105,110,32,117,115,101,44,32,91,92,120,99,56,45,92,120,99,98,93,32,109,97,116,99,104,101,115,32,97,99,99,101,110,116,101,100,32,69,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,98,111,116,104,32,99,97,115,101,115,46,32,73,110,32,85,84,70,32,109,111,100,101,115,44,32,80,67,82,69,32,115,117,112,112,111,114,116,115,32,116,104,101,32,99,111,110,99,101,112,116,32,111,102,32,99,97,115,101,32,102,111,114,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,32,111,110,108,121,32,119,104,101,110,32,105,116,32,105,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,115,117,112,112,111,114,116,46>>]},{p,[],[<<84,104,101,32,99,104,97,114,97,99,116,101,114,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,92,100,44,32,92,68,44,32,92,104,44,32,92,72,44,32,92,112,44,32,92,80,44,32,92,115,44,32,92,83,44,32,92,118,44,32,92,86,44,32,92,119,44,32,97,110,100,32,92,87,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,110,100,32,97,100,100,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,116,104,101,121,32,109,97,116,99,104,32,116,111,32,116,104,101,32,99,108,97,115,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,91,92,100,65,66,67,68,69,70,93,32,109,97,116,99,104,101,115,32,97,110,121,32,104,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,46,32,73,110,32,85,84,70,32,109,111,100,101,115,44,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,97,102,102,101,99,116,115,32,116,104,101,32,109,101,97,110,105,110,103,115,32,111,102,32,92,100,44,32,92,115,44,32,92,119,32,97,110,100,32,116,104,101,105,114,32,117,112,112,101,114,99,97,115,101,32,112,97,114,116,110,101,114,115,44,32,106,117,115,116,32,97,115,32,105,116,32,100,111,101,115,32,119,104,101,110,32,116,104,101,121,32,97,112,112,101,97,114,32,111,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,103,101,110,101,114,105,99,95,99,104,97,114,97,99,116,101,114,95,116,121,112,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<71,101,110,101,114,105,99,32,67,104,97,114,97,99,116,101,114,32,84,121,112,101,115>>]},<<32,101,97,114,108,105,101,114,46,32,84,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,98,32,104,97,115,32,97,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,59,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,98,97,99,107,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,115,101,113,117,101,110,99,101,115,32,92,66,44,32,92,78,44,32,92,82,44,32,97,110,100,32,92,88,32,97,114,101,32,110,111,116,32,115,112,101,99,105,97,108,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,76,105,107,101,32,97,110,121,32,111,116,104,101,114,32,117,110,114,101,99,111,103,110,105,122,101,100,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,44,32,116,104,101,121,32,97,114,101,32,116,114,101,97,116,101,100,32,97,115,32,116,104,101,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,115,32,34,66,34,44,32,34,78,34,44,32,34,82,34,44,32,97,110,100,32,34,88,34,46>>]},{p,[],[<<65,32,99,105,114,99,117,109,102,108,101,120,32,99,97,110,32,99,111,110,118,101,110,105,101,110,116,108,121,32,98,101,32,117,115,101,100,32,119,105,116,104,32,116,104,101,32,117,112,112,101,114,99,97,115,101,32,99,104,97,114,97,99,116,101,114,32,116,121,112,101,115,32,116,111,32,115,112,101,99,105,102,121,32,97,32,109,111,114,101,32,114,101,115,116,114,105,99,116,101,100,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,110,32,116,104,101,32,109,97,116,99,104,105,110,103,32,108,111,119,101,114,99,97,115,101,32,116,121,112,101,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,108,97,115,115,32,91,94,92,87,95,93,32,109,97,116,99,104,101,115,32,97,110,121,32,108,101,116,116,101,114,32,111,114,32,100,105,103,105,116,44,32,98,117,116,32,110,111,116,32,117,110,100,101,114,115,99,111,114,101,44,32,119,104,105,108,101,32,91,92,119,93,32,105,110,99,108,117,100,101,115,32,117,110,100,101,114,115,99,111,114,101,46,32,65,32,112,111,115,105,116,105,118,101,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,105,115,32,116,111,32,98,101,32,114,101,97,100,32,97,115,32,34,115,111,109,101,116,104,105,110,103,32,79,82,32,115,111,109,101,116,104,105,110,103,32,79,82,32,46,46,46,34,32,97,110,100,32,97,32,110,101,103,97,116,105,118,101,32,99,108,97,115,115,32,97,115,32,34,78,79,84,32,115,111,109,101,116,104,105,110,103,32,65,78,68,32,78,79,84,32,115,111,109,101,116,104,105,110,103,32,65,78,68,32,78,79,84,32,46,46,46,34,46>>]},{p,[],[<<79,110,108,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,101,116,97,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,32,105,110,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,58>>]},{ul,[],[{li,[],[<<66,97,99,107,115,108,97,115,104>>]},{li,[],[<<72,121,112,104,101,110,32,40,111,110,108,121,32,119,104,101,114,101,32,105,116,32,99,97,110,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,115,112,101,99,105,102,121,105,110,103,32,97,32,114,97,110,103,101,41>>]},{li,[],[<<67,105,114,99,117,109,102,108,101,120,32,40,111,110,108,121,32,97,116,32,116,104,101,32,115,116,97,114,116,41>>]},{li,[],[<<79,112,101,110,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,32,40,111,110,108,121,32,119,104,101,110,32,105,116,32,99,97,110,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,105,110,116,114,111,100,117,99,105,110,103,32,97,32,80,111,115,105,120,32,99,108,97,115,115,32,110,97,109,101,44,32,111,114,32,102,111,114,32,97,32,115,112,101,99,105,97,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,102,101,97,116,117,114,101,59,32,115,101,101,32,116,104,101,32,110,101,120,116,32,116,119,111,32,115,101,99,116,105,111,110,115,41>>]},{li,[],[<<84,101,114,109,105,110,97,116,105,110,103,32,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116>>]}]},{p,[],[<<72,111,119,101,118,101,114,44,32,101,115,99,97,112,105,110,103,32,111,116,104,101,114,32,110,111,110,45,97,108,112,104,97,110,117,109,101,114,105,99,32,99,104,97,114,97,99,116,101,114,115,32,100,111,101,115,32,110,111,32,104,97,114,109,46>>]},{a,[{id,<<115,101,99,116,56>>}],[]},{h2,[],[<<80,111,115,105,120,32,67,104,97,114,97,99,116,101,114,32,67,108,97,115,115,101,115>>]},{p,[],[<<80,101,114,108,32,115,117,112,112,111,114,116,115,32,116,104,101,32,80,111,115,105,120,32,110,111,116,97,116,105,111,110,32,102,111,114,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,84,104,105,115,32,117,115,101,115,32,110,97,109,101,115,32,101,110,99,108,111,115,101,100,32,98,121,32,91,58,32,97,110,100,32,58,93,32,119,105,116,104,105,110,32,116,104,101,32,101,110,99,108,111,115,105,110,103,32,115,113,117,97,114,101,32,98,114,97,99,107,101,116,115,46,32,80,67,82,69,32,97,108,115,111,32,115,117,112,112,111,114,116,115,32,116,104,105,115,32,110,111,116,97,116,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,48,34,44,32,34,49,34,44,32,97,110,121,32,97,108,112,104,97,98,101,116,105,99,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,34,37,34,58>>]},{pre,[],[{code,[],[<<91,48,49,91,58,97,108,112,104,97,58,93,37,93>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,115,117,112,112,111,114,116,101,100,32,99,108,97,115,115,32,110,97,109,101,115,58>>]},{dl,[],[{dt,[],[<<97,108,110,117,109>>]},{dd,[],[<<76,101,116,116,101,114,115,32,97,110,100,32,100,105,103,105,116,115>>]},{dt,[],[<<97,108,112,104,97>>]},{dd,[],[<<76,101,116,116,101,114,115>>]},{dt,[],[<<98,108,97,110,107>>]},{dd,[],[<<83,112,97,99,101,32,111,114,32,116,97,98,32,111,110,108,121>>]},{dt,[],[<<99,110,116,114,108>>]},{dd,[],[<<67,111,110,116,114,111,108,32,99,104,97,114,97,99,116,101,114,115>>]},{dt,[],[<<100,105,103,105,116>>]},{dd,[],[<<68,101,99,105,109,97,108,32,100,105,103,105,116,115,32,40,115,97,109,101,32,97,115,32,92,100,41>>]},{dt,[],[<<103,114,97,112,104>>]},{dd,[],[<<80,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,101,120,99,108,117,100,105,110,103,32,115,112,97,99,101>>]},{dt,[],[<<108,111,119,101,114>>]},{dd,[],[<<76,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,115>>]},{dt,[],[<<112,114,105,110,116>>]},{dd,[],[<<80,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,105,110,99,108,117,100,105,110,103,32,115,112,97,99,101>>]},{dt,[],[<<112,117,110,99,116>>]},{dd,[],[<<80,114,105,110,116,105,110,103,32,99,104,97,114,97,99,116,101,114,115,44,32,101,120,99,108,117,100,105,110,103,32,108,101,116,116,101,114,115,44,32,100,105,103,105,116,115,44,32,97,110,100,32,115,112,97,99,101>>]},{dt,[],[<<115,112,97,99,101>>]},{dd,[],[<<87,104,105,116,101,115,112,97,99,101,32,40,116,104,101,32,115,97,109,101,32,97,115,32,92,115,32,102,114,111,109,32,80,67,82,69,32,56,46,51,52,41>>]},{dt,[],[<<117,112,112,101,114>>]},{dd,[],[<<85,112,112,101,114,99,97,115,101,32,108,101,116,116,101,114,115>>]},{dt,[],[<<119,111,114,100>>]},{dd,[],[<<34,87,111,114,100,34,32,99,104,97,114,97,99,116,101,114,115,32,40,115,97,109,101,32,97,115,32,92,119,41>>]},{dt,[],[<<120,100,105,103,105,116>>]},{dd,[],[<<72,101,120,97,100,101,99,105,109,97,108,32,100,105,103,105,116,115>>]}]},{p,[],[<<84,104,101,114,101,32,105,115,32,97,110,111,116,104,101,114,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32>>,{code,[],[<<97,115,99,105,105>>]},<<44,32,116,104,97,116,32,101,114,114,111,110,101,111,117,115,108,121,32,109,97,116,99,104,101,115,32,76,97,116,105,110,45,49,32,99,104,97,114,97,99,116,101,114,115,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,48,45,49,50,55,32,114,97,110,103,101,32,115,112,101,99,105,102,105,101,100,32,98,121,32,80,79,83,73,88,46,32,84,104,105,115,32,99,97,110,110,111,116,32,98,101,32,102,105,120,101,100,32,119,105,116,104,111,117,116,32,97,108,116,101,114,105,110,103,32,116,104,101,32,98,101,104,97,118,105,111,117,114,32,111,102,32,111,116,104,101,114,32,99,108,97,115,115,101,115,44,32,115,111,32,119,101,32,114,101,99,111,109,109,101,110,100,32,109,97,116,99,104,105,110,103,32,116,104,101,32,114,97,110,103,101,32,119,105,116,104,32>>,{code,[],[<<91,92,92,48,45,92,120,55,102,93>>]},<<32,105,110,115,116,101,97,100,46>>]},{p,[],[<<84,104,101,32,100,101,102,97,117,108,116,32,34,115,112,97,99,101,34,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,72,84,32,40,57,41,44,32,76,70,32,40,49,48,41,44,32,86,84,32,40,49,49,41,44,32,70,70,32,40,49,50,41,44,32,67,82,32,40,49,51,41,44,32,97,110,100,32,115,112,97,99,101,32,40,51,50,41,46,32,73,102,32,108,111,99,97,108,101,45,115,112,101,99,105,102,105,99,32,109,97,116,99,104,105,110,103,32,105,115,32,116,97,107,105,110,103,32,112,108,97,99,101,44,32,116,104,101,32,108,105,115,116,32,111,102,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,109,97,121,32,98,101,32,100,105,102,102,101,114,101,110,116,59,32,116,104,101,114,101,32,109,97,121,32,98,101,32,102,101,119,101,114,32,111,114,32,109,111,114,101,32,111,102,32,116,104,101,109,46,32,34,83,112,97,99,101,34,32,117,115,101,100,32,116,111,32,98,101,32,100,105,102,102,101,114,101,110,116,32,116,111,32,92,115,44,32,119,104,105,99,104,32,100,105,100,32,110,111,116,32,105,110,99,108,117,100,101,32,86,84,44,32,102,111,114,32,80,101,114,108,32,99,111,109,112,97,116,105,98,105,108,105,116,121,46,32,72,111,119,101,118,101,114,44,32,80,101,114,108,32,99,104,97,110,103,101,100,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,44,32,97,110,100,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,46,32,34,83,112,97,99,101,34,32,97,110,100,32,92,115,32,110,111,119,32,109,97,116,99,104,32,116,104,101,32,115,97,109,101,32,115,101,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<84,104,101,32,110,97,109,101,32,34,119,111,114,100,34,32,105,115,32,97,32,80,101,114,108,32,101,120,116,101,110,115,105,111,110,44,32,97,110,100,32,34,98,108,97,110,107,34,32,105,115,32,97,32,71,78,85,32,101,120,116,101,110,115,105,111,110,32,102,114,111,109,32,80,101,114,108,32,53,46,56,46,32,65,110,111,116,104,101,114,32,80,101,114,108,32,101,120,116,101,110,115,105,111,110,32,105,115,32,110,101,103,97,116,105,111,110,44,32,119,104,105,99,104,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,94,32,99,104,97,114,97,99,116,101,114,32,97,102,116,101,114,32,116,104,101,32,99,111,108,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,49,34,44,32,34,50,34,44,32,111,114,32,97,110,121,32,110,111,110,45,100,105,103,105,116,58>>]},{pre,[],[{code,[],[<<91,49,50,91,58,94,100,105,103,105,116,58,93,93>>]}]},{p,[],[<<80,67,82,69,32,40,97,110,100,32,80,101,114,108,41,32,97,108,115,111,32,114,101,99,111,103,110,105,122,101,32,116,104,101,32,80,111,115,105,120,32,115,121,110,116,97,120,32,91,46,99,104,46,93,32,97,110,100,32,91,61,99,104,61,93,32,119,104,101,114,101,32,34,99,104,34,32,105,115,32,97,32,34,99,111,108,108,97,116,105,110,103,32,101,108,101,109,101,110,116,34,44,32,98,117,116,32,116,104,101,115,101,32,97,114,101,32,110,111,116,32,115,117,112,112,111,114,116,101,100,44,32,97,110,100,32,97,110,32,101,114,114,111,114,32,105,115,32,103,105,118,101,110,32,105,102,32,116,104,101,121,32,97,114,101,32,101,110,99,111,117,110,116,101,114,101,100,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,118,97,108,117,101,115,32,62,32,50,53,53,32,100,111,32,110,111,116,32,109,97,116,99,104,32,97,110,121,32,111,102,32,116,104,101,32,80,111,115,105,120,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,101,115,46,32,72,111,119,101,118,101,114,44,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<80,67,82,69,95,85,67,80>>]},<<32,105,115,32,112,97,115,115,101,100,32,116,111,32>>,{code,[],[<<112,99,114,101,95,99,111,109,112,105,108,101,40,41>>]},<<44,32,115,111,109,101,32,111,102,32,116,104,101,32,99,108,97,115,115,101,115,32,97,114,101,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,117,115,101,100,46,32,84,104,105,115,32,105,115,32,97,99,104,105,101,118,101,100,32,98,121,32,114,101,112,108,97,99,105,110,103,32,99,101,114,116,97,105,110,32,80,111,115,105,120,32,99,108,97,115,115,101,115,32,98,121,32,111,116,104,101,114,32,115,101,113,117,101,110,99,101,115,44,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<91,58,97,108,110,117,109,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,88,97,110,125>>]}]},{dt,[],[<<91,58,97,108,112,104,97,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,76,125>>]}]},{dt,[],[<<91,58,98,108,97,110,107,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,104>>]}]},{dt,[],[<<91,58,100,105,103,105,116,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,78,100,125>>]}]},{dt,[],[<<91,58,108,111,119,101,114,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,76,108,125>>]}]},{dt,[],[<<91,58,115,112,97,99,101,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,88,112,115,125>>]}]},{dt,[],[<<91,58,117,112,112,101,114,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,76,117,125>>]}]},{dt,[],[<<91,58,119,111,114,100,58,93>>]},{dd,[],[<<66,101,99,111,109,101,115,32>>,{em,[],[<<92,112,123,88,119,100,125>>]}]}]},{p,[],[<<78,101,103,97,116,101,100,32,118,101,114,115,105,111,110,115,44,32,115,117,99,104,32,97,115,32,91,58,94,97,108,112,104,97,58,93,44,32,117,115,101,32,92,80,32,105,110,115,116,101,97,100,32,111,102,32,92,112,46,32,84,104,114,101,101,32,111,116,104,101,114,32,80,79,83,73,88,32,99,108,97,115,115,101,115,32,97,114,101,32,104,97,110,100,108,101,100,32,115,112,101,99,105,97,108,108,121,32,105,110,32,85,67,80,32,109,111,100,101,58>>]},{dl,[],[{dt,[],[<<91,58,103,114,97,112,104,58,93>>]},{dd,[],[{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,103,108,121,112,104,115,32,116,104,97,116,32,109,97,114,107,32,116,104,101,32,112,97,103,101,32,119,104,101,110,32,112,114,105,110,116,101,100,46,32,73,110,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,116,101,114,109,115,44,32,105,116,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,76,44,32,77,44,32,78,44,32,80,44,32,83,44,32,111,114,32,67,102,32,112,114,111,112,101,114,116,105,101,115,44,32,101,120,99,101,112,116,32,102,111,114,58>>]},{dl,[],[{dt,[],[<<85,43,48,54,49,67>>]},{dd,[],[{p,[],[<<65,114,97,98,105,99,32,76,101,116,116,101,114,32,77,97,114,107>>]}]},{dt,[],[<<85,43,49,56,48,69>>]},{dd,[],[{p,[],[<<77,111,110,103,111,108,105,97,110,32,86,111,119,101,108,32,83,101,112,97,114,97,116,111,114>>]}]},{dt,[],[<<85,43,50,48,54,54,32,45,32,85,43,50,48,54,57>>]},{dd,[],[{p,[],[<<86,97,114,105,111,117,115,32,34,105,115,111,108,97,116,101,34,115>>]}]}]}]},{dt,[],[<<91,58,112,114,105,110,116,58,93>>]},{dd,[],[{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,116,104,101,32,115,97,109,101,32,99,104,97,114,97,99,116,101,114,115,32,97,115,32,91,58,103,114,97,112,104,58,93,32,112,108,117,115,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,99,111,110,116,114,111,108,115,44,32,116,104,97,116,32,105,115,44,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,116,104,101,32,90,115,32,112,114,111,112,101,114,116,121,46>>]}]},{dt,[],[<<91,58,112,117,110,99,116,58,93>>]},{dd,[],[{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,104,97,118,101,32,116,104,101,32,85,110,105,99,111,100,101,32,80,32,40,112,117,110,99,116,117,97,116,105,111,110,41,32,112,114,111,112,101,114,116,121,44,32,112,108,117,115,32,116,104,111,115,101,32,99,104,97,114,97,99,116,101,114,115,32,119,104,111,115,101,32,99,111,100,101,32,112,111,105,110,116,115,32,97,114,101,32,108,101,115,115,32,116,104,97,110,32,49,50,56,32,116,104,97,116,32,104,97,118,101,32,116,104,101,32,83,32,40,83,121,109,98,111,108,41,32,112,114,111,112,101,114,116,121,46>>]}]}]},{p,[],[<<84,104,101,32,111,116,104,101,114,32,80,79,83,73,88,32,99,108,97,115,115,101,115,32,97,114,101,32,117,110,99,104,97,110,103,101,100,44,32,97,110,100,32,109,97,116,99,104,32,111,110,108,121,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,99,111,100,101,32,112,111,105,110,116,115,32,108,101,115,115,32,116,104,97,110,32,49,50,56,46>>]},{p,[],[{em,[],[<<67,111,109,112,97,116,105,98,105,108,105,116,121,32,70,101,97,116,117,114,101,32,102,111,114,32,87,111,114,100,32,66,111,117,110,100,97,114,105,101,115>>]}]},{p,[],[<<73,110,32,116,104,101,32,80,79,83,73,88,46,50,32,99,111,109,112,108,105,97,110,116,32,108,105,98,114,97,114,121,32,116,104,97,116,32,119,97,115,32,105,110,99,108,117,100,101,100,32,105,110,32,52,46,52,66,83,68,32,85,110,105,120,44,32,116,104,101,32,117,103,108,121,32,115,121,110,116,97,120,32,91,91,58,60,58,93,93,32,97,110,100,32,91,91,58,62,58,93,93,32,105,115,32,117,115,101,100,32,102,111,114,32,109,97,116,99,104,105,110,103,32,34,115,116,97,114,116,32,111,102,32,119,111,114,100,34,32,97,110,100,32,34,101,110,100,32,111,102,32,119,111,114,100,34,46,32,80,67,82,69,32,116,114,101,97,116,115,32,116,104,101,115,101,32,105,116,101,109,115,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<91,91,58,60,58,93,93>>]},{dd,[],[{p,[],[<<105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,92,98,40,63,61,92,119,41>>]}]},{dt,[],[<<91,91,58,62,58,93,93>>]},{dd,[],[{p,[],[<<105,115,32,99,111,110,118,101,114,116,101,100,32,116,111,32,92,98,40,63,60,61,92,119,41>>]}]}]},{p,[],[<<79,110,108,121,32,116,104,101,115,101,32,101,120,97,99,116,32,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,115,32,97,114,101,32,114,101,99,111,103,110,105,122,101,100,46,32,65,32,115,101,113,117,101,110,99,101,32,115,117,99,104,32,97,115,32,91,97,91,58,60,58,93,98,93,32,112,114,111,118,111,107,101,115,32,101,114,114,111,114,32,102,111,114,32,97,110,32,117,110,114,101,99,111,103,110,105,122,101,100,32,80,79,83,73,88,32,99,108,97,115,115,32,110,97,109,101,46,32,84,104,105,115,32,115,117,112,112,111,114,116,32,105,115,32,110,111,116,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,32,80,101,114,108,46,32,73,116,32,105,115,32,112,114,111,118,105,100,101,100,32,116,111,32,104,101,108,112,32,109,105,103,114,97,116,105,111,110,115,32,102,114,111,109,32,111,116,104,101,114,32,101,110,118,105,114,111,110,109,101,110,116,115,44,32,97,110,100,32,105,115,32,98,101,115,116,32,110,111,116,32,117,115,101,100,32,105,110,32,97,110,121,32,110,101,119,32,112,97,116,116,101,114,110,115,46,32,78,111,116,101,32,116,104,97,116,32,92,98,32,109,97,116,99,104,101,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,97,110,100,32,116,104,101,32,101,110,100,32,111,102,32,97,32,119,111,114,100,32,40,115,101,101,32,34,83,105,109,112,108,101,32,97,115,115,101,114,116,105,111,110,115,34,32,97,98,111,118,101,41,44,32,97,110,100,32,105,110,32,97,32,80,101,114,108,45,115,116,121,108,101,32,112,97,116,116,101,114,110,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,111,114,32,102,111,108,108,111,119,105,110,103,32,99,104,97,114,97,99,116,101,114,32,110,111,114,109,97,108,108,121,32,115,104,111,119,115,32,119,104,105,99,104,32,105,115,32,119,97,110,116,101,100,44,32,119,105,116,104,111,117,116,32,116,104,101,32,110,101,101,100,32,102,111,114,32,116,104,101,32,97,115,115,101,114,116,105,111,110,115,32,116,104,97,116,32,97,114,101,32,117,115,101,100,32,97,98,111,118,101,32,105,110,32,111,114,100,101,114,32,116,111,32,103,105,118,101,32,101,120,97,99,116,108,121,32,116,104,101,32,80,79,83,73,88,32,98,101,104,97,118,105,111,117,114,46>>]},{a,[{id,<<115,101,99,116,57>>}],[]},{h2,[],[<<86,101,114,116,105,99,97,108,32,66,97,114>>]},{p,[],[<<86,101,114,116,105,99,97,108,32,98,97,114,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,117,115,101,100,32,116,111,32,115,101,112,97,114,97,116,101,32,97,108,116,101,114,110,97,116,105,118,101,32,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,101,105,116,104,101,114,32,34,103,105,108,98,101,114,116,34,32,111,114,32,34,115,117,108,108,105,118,97,110,34,58>>]},{pre,[],[{code,[],[<<103,105,108,98,101,114,116,124,115,117,108,108,105,118,97,110>>]}]},{p,[],[<<65,110,121,32,110,117,109,98,101,114,32,111,102,32,97,108,116,101,114,110,97,116,105,118,101,115,32,99,97,110,32,97,112,112,101,97,114,44,32,97,110,100,32,97,110,32,101,109,112,116,121,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,112,101,114,109,105,116,116,101,100,32,40,109,97,116,99,104,105,110,103,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,41,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,115,115,32,116,114,105,101,115,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,117,114,110,44,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,44,32,97,110,100,32,116,104,101,32,102,105,114,115,116,32,116,104,97,116,32,115,117,99,99,101,101,100,115,32,105,115,32,117,115,101,100,46,32,73,102,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,119,105,116,104,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,100,101,102,105,110,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115>>]},<<41,44,32,34,115,117,99,99,101,101,100,115,34,32,109,101,97,110,115,32,109,97,116,99,104,105,110,103,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,109,97,105,110,32,112,97,116,116,101,114,110,32,97,110,100,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,46>>]},{a,[{id,<<115,101,99,116,49,48>>}],[]},{h2,[],[<<73,110,116,101,114,110,97,108,32,79,112,116,105,111,110,32,83,101,116,116,105,110,103>>]},{p,[],[<<84,104,101,32,115,101,116,116,105,110,103,115,32,111,102,32,116,104,101,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,32,111,112,116,105,111,110,115,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<44,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<44,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,102,114,111,109,32,119,105,116,104,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,98,121,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,80,101,114,108,32,111,112,116,105,111,110,32,108,101,116,116,101,114,115,32,101,110,99,108,111,115,101,100,32,98,101,116,119,101,101,110,32,34,40,63,34,32,97,110,100,32,34,41,34,46,32,84,104,101,32,111,112,116,105,111,110,32,108,101,116,116,101,114,115,32,97,114,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[<<105>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]}]},{dt,[],[<<109>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]}]},{dt,[],[<<115>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<100,111,116,97,108,108>>]}]},{dt,[],[<<120>>]},{dd,[],[<<70,111,114,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]}]}]},{p,[],[<<70,111,114,32,101,120,97,109,112,108,101,44,32>>,{code,[],[<<40,63,105,109,41>>]},<<32,115,101,116,115,32,99,97,115,101,108,101,115,115,44,32,109,117,108,116,105,108,105,110,101,32,109,97,116,99,104,105,110,103,46,32,84,104,101,115,101,32,111,112,116,105,111,110,115,32,99,97,110,32,97,108,115,111,32,98,101,32,117,110,115,101,116,32,98,121,32,112,114,101,99,101,100,105,110,103,32,116,104,101,32,108,101,116,116,101,114,32,119,105,116,104,32,97,32,104,121,112,104,101,110,46,32,65,32,99,111,109,98,105,110,101,100,32,115,101,116,116,105,110,103,32,97,110,100,32,117,110,115,101,116,116,105,110,103,32,115,117,99,104,32,97,115,32>>,{code,[],[<<40,63,105,109,45,115,120,41>>]},<<44,32,119,104,105,99,104,32,115,101,116,115,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<32,97,110,100,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<44,32,119,104,105,108,101,32,117,110,115,101,116,116,105,110,103,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,97,110,100,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<44,32,105,115,32,97,108,115,111,32,112,101,114,109,105,116,116,101,100,46,32,73,102,32,97,32,108,101,116,116,101,114,32,97,112,112,101,97,114,115,32,98,111,116,104,32,98,101,102,111,114,101,32,97,110,100,32,97,102,116,101,114,32,116,104,101,32,104,121,112,104,101,110,44,32,116,104,101,32,111,112,116,105,111,110,32,105,115,32,117,110,115,101,116,46>>]},{p,[],[<<84,104,101,32,80,67,82,69,45,115,112,101,99,105,102,105,99,32,111,112,116,105,111,110,115,32>>,{code,[],[<<100,117,112,110,97,109,101,115>>]},<<44,32>>,{code,[],[<<117,110,103,114,101,101,100,121>>]},<<44,32,97,110,100,32>>,{code,[],[<<101,120,116,114,97>>]},<<32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,116,104,101,32,80,101,114,108,45,99,111,109,112,97,116,105,98,108,101,32,111,112,116,105,111,110,115,32,98,121,32,117,115,105,110,103,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,74,44,32,85,44,32,97,110,100,32,88,32,114,101,115,112,101,99,116,105,118,101,108,121,46>>]},{p,[],[<<87,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,111,112,116,105,111,110,32,99,104,97,110,103,101,115,32,111,99,99,117,114,115,32,97,116,32,116,111,112,45,108,101,118,101,108,32,40,116,104,97,116,32,105,115,44,32,110,111,116,32,105,110,115,105,100,101,32,115,117,98,112,97,116,116,101,114,110,32,112,97,114,101,110,116,104,101,115,101,115,41,44,32,116,104,101,32,99,104,97,110,103,101,32,97,112,112,108,105,101,115,32,116,111,32,116,104,101,32,114,101,109,97,105,110,100,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,116,104,97,116,32,102,111,108,108,111,119,115,46>>]},{p,[],[<<65,110,32,111,112,116,105,111,110,32,99,104,97,110,103,101,32,119,105,116,104,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,115>>]},<<41,32,97,102,102,101,99,116,115,32,111,110,108,121,32,116,104,97,116,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,102,111,108,108,111,119,115,32,105,116,46,32,83,111,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,98,99,32,97,110,100,32,97,66,99,32,97,110,100,32,110,111,32,111,116,104,101,114,32,115,116,114,105,110,103,115,32,40,97,115,115,117,109,105,110,103,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<32,105,115,32,110,111,116,32,117,115,101,100,41,58>>]},{pre,[],[{code,[],[<<40,97,40,63,105,41,98,41,99>>]}]},{p,[],[<<66,121,32,116,104,105,115,32,109,101,97,110,115,44,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,109,97,100,101,32,116,111,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,115,101,116,116,105,110,103,115,32,105,110,32,100,105,102,102,101,114,101,110,116,32,112,97,114,116,115,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,46,32,65,110,121,32,99,104,97,110,103,101,115,32,109,97,100,101,32,105,110,32,111,110,101,32,97,108,116,101,114,110,97,116,105,118,101,32,100,111,32,99,97,114,114,121,32,111,110,32,105,110,116,111,32,115,117,98,115,101,113,117,101,110,116,32,98,114,97,110,99,104,101,115,32,119,105,116,104,105,110,32,116,104,101,32,115,97,109,101,32,115,117,98,112,97,116,116,101,114,110,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,40,63,105,41,98,124,99,41>>]}]},{p,[],[<<109,97,116,99,104,101,115,32,34,97,98,34,44,32,34,97,66,34,44,32,34,99,34,44,32,97,110,100,32,34,67,34,44,32,97,108,116,104,111,117,103,104,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,34,67,34,32,116,104,101,32,102,105,114,115,116,32,98,114,97,110,99,104,32,105,115,32,97,98,97,110,100,111,110,101,100,32,98,101,102,111,114,101,32,116,104,101,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,101,102,102,101,99,116,115,32,111,102,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,115,32,111,99,99,117,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46,32,84,104,101,114,101,32,119,111,117,108,100,32,98,101,32,115,111,109,101,32,119,101,105,114,100,32,98,101,104,97,118,105,111,114,32,111,116,104,101,114,119,105,115,101,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<79,116,104,101,114,32,80,67,82,69,45,115,112,101,99,105,102,105,99,32,111,112,116,105,111,110,115,32,99,97,110,32,98,101,32,115,101,116,32,98,121,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,119,104,101,110,32,116,104,101,32,99,111,109,112,105,108,105,110,103,32,111,114,32,109,97,116,99,104,105,110,103,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,99,97,108,108,101,100,46,32,83,111,109,101,116,105,109,101,115,32,116,104,101,32,112,97,116,116,101,114,110,32,99,97,110,32,99,111,110,116,97,105,110,32,115,112,101,99,105,97,108,32,108,101,97,100,105,110,103,32,115,101,113,117,101,110,99,101,115,44,32,115,117,99,104,32,97,115,32,40,42,67,82,76,70,41,44,32,116,111,32,111,118,101,114,114,105,100,101,32,119,104,97,116,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,104,97,115,32,115,101,116,32,111,114,32,119,104,97,116,32,104,97,115,32,98,101,101,110,32,100,101,102,97,117,108,116,101,100,46,32,68,101,116,97,105,108,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,101,119,108,105,110,101,95,115,101,113,117,101,110,99,101,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,101,119,108,105,110,101,32,83,101,113,117,101,110,99,101,115>>]},<<32,101,97,114,108,105,101,114,46>>]},{p,[],[<<84,104,101,32,40,42,85,84,70,56,41,32,97,110,100,32,40,42,85,67,80,41,32,108,101,97,100,105,110,103,32,115,101,113,117,101,110,99,101,115,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,115,101,116,32,85,84,70,32,97,110,100,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,121,32,109,111,100,101,115,46,32,84,104,101,121,32,97,114,101,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,115,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,97,110,100,32>>,{code,[],[<<117,99,112>>]},<<44,32,114,101,115,112,101,99,116,105,118,101,108,121,46,32,84,104,101,32,40,42,85,84,70,41,32,115,101,113,117,101,110,99,101,32,105,115,32,97,32,103,101,110,101,114,105,99,32,118,101,114,115,105,111,110,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,97,110,121,32,111,102,32,116,104,101,32,108,105,98,114,97,114,105,101,115,46,32,72,111,119,101,118,101,114,44,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,99,97,110,32,115,101,116,32,111,112,116,105,111,110,32>>,{code,[],[<<110,101,118,101,114,95,117,116,102>>]},<<44,32,119,104,105,99,104,32,108,111,99,107,115,32,111,117,116,32,116,104,101,32,117,115,101,32,111,102,32,116,104,101,32,40,42,85,84,70,41,32,115,101,113,117,101,110,99,101,115,46>>]}]},{a,[{id,<<115,101,99,116,49,49>>}],[]},{h2,[],[<<83,117,98,112,97,116,116,101,114,110,115>>]},{p,[],[<<83,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,100,101,108,105,109,105,116,101,100,32,98,121,32,112,97,114,101,110,116,104,101,115,101,115,32,40,114,111,117,110,100,32,98,114,97,99,107,101,116,115,41,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,110,101,115,116,101,100,46,32,84,117,114,110,105,110,103,32,112,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,32,105,110,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,100,111,101,115,32,116,119,111,32,116,104,105,110,103,115,58>>]},{dl,[],[{dt,[],[<<49,46>>]},{dd,[],[{p,[],[<<73,116,32,108,111,99,97,108,105,122,101,115,32,97,32,115,101,116,32,111,102,32,97,108,116,101,114,110,97,116,105,118,101,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,99,97,116,97,114,97,99,116,34,44,32,34,99,97,116,101,114,112,105,108,108,97,114,34,44,32,111,114,32,34,99,97,116,34,58>>]},{pre,[],[{code,[],[<<99,97,116,40,97,114,97,99,116,124,101,114,112,105,108,108,97,114,124,41>>]}]},{p,[],[<<87,105,116,104,111,117,116,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,44,32,105,116,32,119,111,117,108,100,32,109,97,116,99,104,32,34,99,97,116,97,114,97,99,116,34,44,32,34,101,114,112,105,108,108,97,114,34,44,32,111,114,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,46>>]}]},{dt,[],[<<50,46>>]},{dd,[],[{p,[],[<<73,116,32,115,101,116,115,32,117,112,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,97,115,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,46,32,84,104,97,116,32,105,115,44,32,119,104,101,110,32,116,104,101,32,99,111,109,112,108,101,116,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,44,32,116,104,97,116,32,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,116,104,97,116,32,109,97,116,99,104,101,100,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,112,97,115,115,101,100,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,116,104,114,111,117,103,104,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<46>>]}]}]},{p,[],[<<79,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,99,111,117,110,116,101,100,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,32,40,115,116,97,114,116,105,110,103,32,102,114,111,109,32,49,41,32,116,111,32,111,98,116,97,105,110,32,110,117,109,98,101,114,115,32,102,111,114,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,116,104,101,32,115,116,114,105,110,103,32,34,116,104,101,32,114,101,100,32,107,105,110,103,34,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,34,114,101,100,32,107,105,110,103,34,44,32,34,114,101,100,34,44,32,97,110,100,32,34,107,105,110,103,34,44,32,97,110,100,32,97,114,101,32,110,117,109,98,101,114,101,100,32,49,44,32,50,44,32,97,110,100,32,51,44,32,114,101,115,112,101,99,116,105,118,101,108,121,58>>]},{pre,[],[{code,[],[<<116,104,101,32,40,40,114,101,100,124,119,104,105,116,101,41,32,40,107,105,110,103,124,113,117,101,101,110,41,41>>]}]},{p,[],[<<73,116,32,105,115,32,110,111,116,32,97,108,119,97,121,115,32,104,101,108,112,102,117,108,32,116,104,97,116,32,112,108,97,105,110,32,112,97,114,101,110,116,104,101,115,101,115,32,102,117,108,102,105,108,108,32,116,119,111,32,102,117,110,99,116,105,111,110,115,46,32,79,102,116,101,110,32,97,32,103,114,111,117,112,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,114,101,113,117,105,114,101,100,32,119,105,116,104,111,117,116,32,97,32,99,97,112,116,117,114,105,110,103,32,114,101,113,117,105,114,101,109,101,110,116,46,32,73,102,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,113,117,101,115,116,105,111,110,32,109,97,114,107,32,97,110,100,32,97,32,99,111,108,111,110,44,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,100,111,101,115,32,110,111,116,32,100,111,32,97,110,121,32,99,97,112,116,117,114,105,110,103,44,32,97,110,100,32,105,115,32,110,111,116,32,99,111,117,110,116,101,100,32,119,104,101,110,32,99,111,109,112,117,116,105,110,103,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,97,110,121,32,115,117,98,115,101,113,117,101,110,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,116,104,101,32,115,116,114,105,110,103,32,34,116,104,101,32,119,104,105,116,101,32,113,117,101,101,110,34,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,34,119,104,105,116,101,32,113,117,101,101,110,34,32,97,110,100,32,34,113,117,101,101,110,34,44,32,97,110,100,32,97,114,101,32,110,117,109,98,101,114,101,100,32,49,32,97,110,100,32,50,58>>]},{pre,[],[{code,[],[<<116,104,101,32,40,40,63,58,114,101,100,124,119,104,105,116,101,41,32,40,107,105,110,103,124,113,117,101,101,110,41,41>>]}]},{p,[],[<<84,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,105,115,32,54,53,53,51,53,46>>]},{p,[],[<<65,115,32,97,32,99,111,110,118,101,110,105,101,110,116,32,115,104,111,114,116,104,97,110,100,44,32,105,102,32,97,110,121,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,115,32,97,114,101,32,114,101,113,117,105,114,101,100,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,110,111,110,45,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,44,32,116,104,101,32,111,112,116,105,111,110,32,108,101,116,116,101,114,115,32,99,97,110,32,97,112,112,101,97,114,32,98,101,116,119,101,101,110,32,34,63,34,32,97,110,100,32,34,58,34,46,32,84,104,117,115,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,116,119,111,32,112,97,116,116,101,114,110,115,32,109,97,116,99,104,32,116,104,101,32,115,97,109,101,32,115,101,116,32,111,102,32,115,116,114,105,110,103,115,58>>]},{pre,[],[{code,[],[<<40,63,105,58,115,97,116,117,114,100,97,121,124,115,117,110,100,97,121,41,10,40,63,58,40,63,105,41,115,97,116,117,114,100,97,121,124,115,117,110,100,97,121,41>>]}]},{p,[],[<<65,115,32,97,108,116,101,114,110,97,116,105,118,101,32,98,114,97,110,99,104,101,115,32,97,114,101,32,116,114,105,101,100,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,44,32,97,110,100,32,111,112,116,105,111,110,115,32,97,114,101,32,110,111,116,32,114,101,115,101,116,32,117,110,116,105,108,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,114,101,97,99,104,101,100,44,32,97,110,32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,32,105,110,32,111,110,101,32,98,114,97,110,99,104,32,100,111,101,115,32,97,102,102,101,99,116,32,115,117,98,115,101,113,117,101,110,116,32,98,114,97,110,99,104,101,115,44,32,115,111,32,116,104,101,32,97,98,111,118,101,32,112,97,116,116,101,114,110,115,32,109,97,116,99,104,32,98,111,116,104,32,34,83,85,78,68,65,89,34,32,97,110,100,32,34,83,97,116,117,114,100,97,121,34,46>>]},{a,[{id,<<115,101,99,116,49,50>>}],[]},{h2,[],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]},{p,[],[<<80,101,114,108,32,53,46,49,48,32,105,110,116,114,111,100,117,99,101,100,32,97,32,102,101,97,116,117,114,101,32,119,104,101,114,101,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,117,115,101,115,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,115,32,102,111,114,32,105,116,115,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,46,32,83,117,99,104,32,97,32,115,117,98,112,97,116,116,101,114,110,32,115,116,97,114,116,115,32,119,105,116,104,32>>,{code,[],[<<40,63,124>>]},<<32,97,110,100,32,105,115,32,105,116,115,101,108,102,32,97,32,110,111,110,45,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,63,124,40,83,97,116,41,117,114,124,40,83,117,110,41,41,100,97,121>>]}]},{p,[],[<<65,115,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,105,110,115,105,100,101,32,97,32>>,{code,[],[<<40,63,124>>]},<<32,103,114,111,117,112,44,32,98,111,116,104,32,115,101,116,115,32,111,102,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,110,117,109,98,101,114,101,100,32,111,110,101,46,32,84,104,117,115,44,32,119,104,101,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,44,32,121,111,117,32,99,97,110,32,108,111,111,107,32,97,116,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,32,110,117,109,98,101,114,32,111,110,101,44,32,119,104,105,99,104,101,118,101,114,32,97,108,116,101,114,110,97,116,105,118,101,32,109,97,116,99,104,101,100,46,32,84,104,105,115,32,99,111,110,115,116,114,117,99,116,32,105,115,32,117,115,101,102,117,108,32,119,104,101,110,32,121,111,117,32,119,97,110,116,32,116,111,32,99,97,112,116,117,114,101,32,97,32,112,97,114,116,44,32,98,117,116,32,110,111,116,32,97,108,108,44,32,111,102,32,111,110,101,32,111,102,32,109,97,110,121,32,97,108,116,101,114,110,97,116,105,118,101,115,46,32,73,110,115,105,100,101,32,97,32>>,{code,[],[<<40,63,124>>]},<<32,103,114,111,117,112,44,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,110,117,109,98,101,114,101,100,32,97,115,32,117,115,117,97,108,44,32,98,117,116,32,116,104,101,32,110,117,109,98,101,114,32,105,115,32,114,101,115,101,116,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,101,97,99,104,32,98,114,97,110,99,104,46,32,84,104,101,32,110,117,109,98,101,114,115,32,111,102,32,97,110,121,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,102,111,108,108,111,119,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,115,116,97,114,116,32,97,102,116,101,114,32,116,104,101,32,104,105,103,104,101,115,116,32,110,117,109,98,101,114,32,117,115,101,100,32,105,110,32,97,110,121,32,98,114,97,110,99,104,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,105,115,32,102,114,111,109,32,116,104,101,32,80,101,114,108,32,100,111,99,117,109,101,110,116,97,116,105,111,110,59,32,116,104,101,32,110,117,109,98,101,114,115,32,117,110,100,101,114,110,101,97,116,104,32,115,104,111,119,32,105,110,32,119,104,105,99,104,32,98,117,102,102,101,114,32,116,104,101,32,99,97,112,116,117,114,101,100,32,99,111,110,116,101,110,116,32,105,115,32,115,116,111,114,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<35,32,98,101,102,111,114,101,32,32,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,98,114,97,110,99,104,45,114,101,115,101,116,45,45,45,45,45,45,45,45,45,45,45,32,97,102,116,101,114,10,47,32,40,32,97,32,41,32,32,40,63,124,32,120,32,40,32,121,32,41,32,122,32,124,32,40,112,32,40,113,41,32,114,41,32,124,32,40,116,41,32,117,32,40,118,41,32,41,32,40,32,122,32,41,32,47,120,10,35,32,49,32,32,32,32,32,32,32,32,32,32,32,32,50,32,32,32,32,32,32,32,32,32,50,32,32,51,32,32,32,32,32,32,32,32,50,32,32,32,32,32,51,32,32,32,32,32,52>>]}]},{p,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,97,32,110,117,109,98,101,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,117,115,101,115,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,118,97,108,117,101,32,116,104,97,116,32,105,115,32,115,101,116,32,102,111,114,32,116,104,97,116,32,110,117,109,98,101,114,32,98,121,32,97,110,121,32,115,117,98,112,97,116,116,101,114,110,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,97,98,99,97,98,99,34,32,111,114,32,34,100,101,102,100,101,102,34,58>>]},{pre,[],[{code,[],[<<47,40,63,124,40,97,98,99,41,124,40,100,101,102,41,41,92,49,47>>]}]},{p,[],[<<73,110,32,99,111,110,116,114,97,115,116,44,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,116,111,32,97,32,110,117,109,98,101,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,97,108,119,97,121,115,32,114,101,102,101,114,115,32,116,111,32,116,104,101,32,102,105,114,115,116,32,111,110,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,103,105,118,101,110,32,110,117,109,98,101,114,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,97,98,99,97,98,99,34,32,111,114,32,34,100,101,102,97,98,99,34,58>>]},{pre,[],[{code,[],[<<47,40,63,124,40,97,98,99,41,124,40,100,101,102,41,41,40,63,49,41,47>>]}]},{p,[],[<<73,102,32,97,32,99,111,110,100,105,116,105,111,110,32,116,101,115,116,32,102,111,114,32,97,32,115,117,98,112,97,116,116,101,114,110,32,104,97,118,105,110,103,32,109,97,116,99,104,101,100,32,114,101,102,101,114,115,32,116,111,32,97,32,110,111,110,45,117,110,105,113,117,101,32,110,117,109,98,101,114,44,32,116,104,101,32,116,101,115,116,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,116,104,97,116,32,110,117,109,98,101,114,32,104,97,118,101,32,109,97,116,99,104,101,100,46>>]},{p,[],[<<65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,97,112,112,114,111,97,99,104,32,117,115,105,110,103,32,116,104,105,115,32,34,98,114,97,110,99,104,32,114,101,115,101,116,34,32,102,101,97,116,117,114,101,32,105,115,32,116,111,32,117,115,101,32,100,117,112,108,105,99,97,116,101,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,46>>]},{a,[{id,<<115,101,99,116,49,51>>}],[]},{h2,[],[<<78,97,109,101,100,32,83,117,98,112,97,116,116,101,114,110,115>>]},{p,[],[<<73,100,101,110,116,105,102,121,105,110,103,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,98,121,32,110,117,109,98,101,114,32,105,115,32,115,105,109,112,108,101,44,32,98,117,116,32,105,116,32,99,97,110,32,98,101,32,104,97,114,100,32,116,111,32,107,101,101,112,32,116,114,97,99,107,32,111,102,32,116,104,101,32,110,117,109,98,101,114,115,32,105,110,32,99,111,109,112,108,105,99,97,116,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,46,32,65,108,115,111,44,32,105,102,32,97,110,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,109,111,100,105,102,105,101,100,44,32,116,104,101,32,110,117,109,98,101,114,115,32,99,97,110,32,99,104,97,110,103,101,46,32,84,111,32,104,101,108,112,32,119,105,116,104,32,116,104,105,115,32,100,105,102,102,105,99,117,108,116,121,44,32,80,67,82,69,32,115,117,112,112,111,114,116,115,32,116,104,101,32,110,97,109,105,110,103,32,111,102,32,115,117,98,112,97,116,116,101,114,110,115,46,32,84,104,105,115,32,102,101,97,116,117,114,101,32,119,97,115,32,110,111,116,32,97,100,100,101,100,32,116,111,32,80,101,114,108,32,117,110,116,105,108,32,114,101,108,101,97,115,101,32,53,46,49,48,46,32,80,121,116,104,111,110,32,104,97,100,32,116,104,101,32,102,101,97,116,117,114,101,32,101,97,114,108,105,101,114,44,32,97,110,100,32,80,67,82,69,32,105,110,116,114,111,100,117,99,101,100,32,105,116,32,97,116,32,114,101,108,101,97,115,101,32,52,46,48,44,32,117,115,105,110,103,32,116,104,101,32,80,121,116,104,111,110,32,115,121,110,116,97,120,46,32,80,67,82,69,32,110,111,119,32,115,117,112,112,111,114,116,115,32,98,111,116,104,32,116,104,101,32,80,101,114,108,32,97,110,100,32,116,104,101,32,80,121,116,104,111,110,32,115,121,110,116,97,120,46,32,80,101,114,108,32,97,108,108,111,119,115,32,105,100,101,110,116,105,99,97,108,108,121,32,110,117,109,98,101,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,104,97,118,101,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,115,44,32,98,117,116,32,80,67,82,69,32,100,111,101,115,32,110,111,116,46>>]},{p,[],[<<73,110,32,80,67,82,69,44,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,98,101,32,110,97,109,101,100,32,105,110,32,111,110,101,32,111,102,32,116,104,114,101,101,32,119,97,121,115,58,32>>,{code,[],[<<40,63,60,110,97,109,101,62,46,46,46,41>>]},<<32,111,114,32>>,{code,[],[<<40,63,39,110,97,109,101,39,46,46,46,41>>]},<<32,97,115,32,105,110,32,80,101,114,108,44,32,111,114,32>>,{code,[],[<<40,63,80,60,110,97,109,101,62,46,46,46,41>>]},<<32,97,115,32,105,110,32,80,121,116,104,111,110,46,32,82,101,102,101,114,101,110,99,101,115,32,116,111,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,102,114,111,109,32,111,116,104,101,114,32,112,97,114,116,115,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,44,32,115,117,99,104,32,97,115,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,44,32,114,101,99,117,114,115,105,111,110,44,32,97,110,100,32,99,111,110,100,105,116,105,111,110,115,44,32,99,97,110,32,98,101,32,109,97,100,101,32,98,121,32,110,97,109,101,32,97,110,100,32,98,121,32,110,117,109,98,101,114,46>>]},{p,[],[<<78,97,109,101,115,32,99,111,110,115,105,115,116,32,111,102,32,117,112,32,116,111,32,51,50,32,97,108,112,104,97,110,117,109,101,114,105,99,32,99,104,97,114,97,99,116,101,114,115,32,97,110,100,32,117,110,100,101,114,115,99,111,114,101,115,44,32,98,117,116,32,109,117,115,116,32,115,116,97,114,116,32,119,105,116,104,32,97,32,110,111,110,45,100,105,103,105,116,46,32,78,97,109,101,100,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,115,116,105,108,108,32,97,108,108,111,99,97,116,101,100,32,110,117,109,98,101,114,115,32,97,115,32,119,101,108,108,32,97,115,32,110,97,109,101,115,44,32,101,120,97,99,116,108,121,32,97,115,32,105,102,32,116,104,101,32,110,97,109,101,115,32,119,101,114,101,32,110,111,116,32,112,114,101,115,101,110,116,46,32,84,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<32,99,97,110,32,117,115,101,32,110,97,109,101,100,32,118,97,108,117,101,115,32,105,102,32,116,104,101,121,32,97,114,101,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,97,32,110,97,109,101,32,109,117,115,116,32,98,101,32,117,110,105,113,117,101,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,44,32,98,117,116,32,116,104,105,115,32,99,111,110,115,116,114,97,105,110,116,32,99,97,110,32,98,101,32,114,101,108,97,120,101,100,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<100,117,112,110,97,109,101,115>>]},<<32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,46,32,40,68,117,112,108,105,99,97,116,101,32,110,97,109,101,115,32,97,114,101,32,97,108,115,111,32,97,108,119,97,121,115,32,112,101,114,109,105,116,116,101,100,32,102,111,114,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,44,32,115,101,116,32,117,112,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,101,99,116,105,111,110,46,41,32,68,117,112,108,105,99,97,116,101,32,110,97,109,101,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,102,111,114,32,112,97,116,116,101,114,110,115,32,119,104,101,114,101,32,111,110,108,121,32,111,110,101,32,105,110,115,116,97,110,99,101,32,111,102,32,116,104,101,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,109,97,116,99,104,46,32,83,117,112,112,111,115,101,32,116,104,97,116,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,116,104,101,32,110,97,109,101,32,111,102,32,97,32,119,101,101,107,100,97,121,44,32,101,105,116,104,101,114,32,97,115,32,97,32,51,45,108,101,116,116,101,114,32,97,98,98,114,101,118,105,97,116,105,111,110,32,111,114,32,97,115,32,116,104,101,32,102,117,108,108,32,110,97,109,101,44,32,97,110,100,32,105,110,32,98,111,116,104,32,99,97,115,101,115,32,121,111,117,32,119,97,110,116,32,116,111,32,101,120,116,114,97,99,116,32,116,104,101,32,97,98,98,114,101,118,105,97,116,105,111,110,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,40,105,103,110,111,114,105,110,103,32,116,104,101,32,108,105,110,101,32,98,114,101,97,107,115,41,32,100,111,101,115,32,116,104,101,32,106,111,98,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<40,63,60,68,78,62,77,111,110,124,70,114,105,124,83,117,110,41,40,63,58,100,97,121,41,63,124,10,40,63,60,68,78,62,84,117,101,41,40,63,58,115,100,97,121,41,63,124,10,40,63,60,68,78,62,87,101,100,41,40,63,58,110,101,115,100,97,121,41,63,124,10,40,63,60,68,78,62,84,104,117,41,40,63,58,114,115,100,97,121,41,63,124,10,40,63,60,68,78,62,83,97,116,41,40,63,58,117,114,100,97,121,41,63>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,102,105,118,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,115,116,114,105,110,103,115,44,32,98,117,116,32,111,110,108,121,32,111,110,101,32,105,115,32,101,118,101,114,32,115,101,116,32,97,102,116,101,114,32,97,32,109,97,116,99,104,46,32,40,65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,119,97,121,32,111,102,32,115,111,108,118,105,110,103,32,116,104,105,115,32,112,114,111,98,108,101,109,32,105,115,32,116,111,32,117,115,101,32,97,32,34,98,114,97,110,99,104,32,114,101,115,101,116,34,32,115,117,98,112,97,116,116,101,114,110,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,101,99,116,105,111,110,46,41>>]},{p,[],[<<70,111,114,32,99,97,112,116,117,114,105,110,103,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,119,104,105,99,104,32,110,97,109,101,115,32,97,114,101,32,110,111,116,32,117,110,105,113,117,101,44,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,111,99,99,117,114,114,101,110,99,101,32,40,99,111,117,110,116,101,100,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,41,32,105,115,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,105,102,32,116,104,101,32,110,97,109,101,32,105,115,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,101,32>>,{code,[],[<<118,97,108,117,101,115>>]},<<32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,115,116,97,116,101,109,101,110,116,46,32,84,104,101,32>>,{code,[],[<<97,108,108,95,110,97,109,101,115>>]},<<32,99,97,112,116,117,114,105,110,103,32,118,97,108,117,101,32,109,97,116,99,104,101,115,32,97,108,108,32,116,104,101,32,110,97,109,101,115,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<89,111,117,32,99,97,110,110,111,116,32,117,115,101,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,115,32,116,111,32,100,105,115,116,105,110,103,117,105,115,104,32,98,101,116,119,101,101,110,32,116,119,111,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,44,32,97,115,32,80,67,82,69,32,117,115,101,115,32,111,110,108,121,32,116,104,101,32,110,117,109,98,101,114,115,32,119,104,101,110,32,109,97,116,99,104,105,110,103,46,32,70,111,114,32,116,104,105,115,32,114,101,97,115,111,110,44,32,97,110,32,101,114,114,111,114,32,105,115,32,103,105,118,101,110,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,32,105,102,32,100,105,102,102,101,114,101,110,116,32,110,97,109,101,115,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,116,111,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,46,32,72,111,119,101,118,101,114,44,32,121,111,117,32,99,97,110,32,115,112,101,99,105,102,121,32,116,104,101,32,115,97,109,101,32,110,97,109,101,32,116,111,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,44,32,101,118,101,110,32,119,104,101,110,32>>,{code,[],[<<100,117,112,110,97,109,101,115>>]},<<32,105,115,32,110,111,116,32,115,101,116,46>>]}]},{a,[{id,<<115,101,99,116,49,52>>}],[]},{h2,[],[<<82,101,112,101,116,105,116,105,111,110>>]},{p,[],[<<82,101,112,101,116,105,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32,113,117,97,110,116,105,102,105,101,114,115,44,32,119,104,105,99,104,32,99,97,110,32,102,111,108,108,111,119,32,97,110,121,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,116,101,109,115,58>>]},{ul,[],[{li,[],[<<65,32,108,105,116,101,114,97,108,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114>>]},{li,[],[<<84,104,101,32,100,111,116,32,109,101,116,97,99,104,97,114,97,99,116,101,114>>]},{li,[],[<<84,104,101,32,92,67,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101>>]},{li,[],[<<84,104,101,32,92,88,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101>>]},{li,[],[<<84,104,101,32,92,82,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101>>]},{li,[],[<<65,110,32,101,115,99,97,112,101,32,115,117,99,104,32,97,115,32,92,100,32,111,114,32,92,112,76,32,116,104,97,116,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114>>]},{li,[],[<<65,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115>>]},{li,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,40,115,101,101,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41>>]},{li,[],[<<65,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,32,40,105,110,99,108,117,100,105,110,103,32,97,115,115,101,114,116,105,111,110,115,41>>]},{li,[],[<<65,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,114,101,99,117,114,115,105,118,101,32,111,114,32,111,116,104,101,114,119,105,115,101,41>>]}]},{p,[],[<<84,104,101,32,103,101,110,101,114,97,108,32,114,101,112,101,116,105,116,105,111,110,32,113,117,97,110,116,105,102,105,101,114,32,115,112,101,99,105,102,105,101,115,32,97,32,109,105,110,105,109,117,109,32,97,110,100,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,101,114,109,105,116,116,101,100,32,109,97,116,99,104,101,115,44,32,98,121,32,103,105,118,105,110,103,32,116,104,101,32,116,119,111,32,110,117,109,98,101,114,115,32,105,110,32,99,117,114,108,121,32,98,114,97,99,107,101,116,115,32,40,98,114,97,99,101,115,41,44,32,115,101,112,97,114,97,116,101,100,32,98,121,32,97,32,99,111,109,109,97,46,32,84,104,101,32,110,117,109,98,101,114,115,32,109,117,115,116,32,98,101,32,60,32,54,53,53,51,54,44,32,97,110,100,32,116,104,101,32,102,105,114,115,116,32,109,117,115,116,32,98,101,32,108,101,115,115,32,116,104,97,110,32,111,114,32,101,113,117,97,108,32,116,111,32,116,104,101,32,115,101,99,111,110,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,122,122,34,44,32,34,122,122,122,34,44,32,111,114,32,34,122,122,122,122,34,58>>]},{pre,[],[{code,[],[<<122,123,50,44,52,125>>]}]},{p,[],[<<65,32,99,108,111,115,105,110,103,32,98,114,97,99,101,32,111,110,32,105,116,115,32,111,119,110,32,105,115,32,110,111,116,32,97,32,115,112,101,99,105,97,108,32,99,104,97,114,97,99,116,101,114,46,32,73,102,32,116,104,101,32,115,101,99,111,110,100,32,110,117,109,98,101,114,32,105,115,32,111,109,105,116,116,101,100,44,32,98,117,116,32,116,104,101,32,99,111,109,109,97,32,105,115,32,112,114,101,115,101,110,116,44,32,116,104,101,114,101,32,105,115,32,110,111,32,117,112,112,101,114,32,108,105,109,105,116,46,32,73,102,32,116,104,101,32,115,101,99,111,110,100,32,110,117,109,98,101,114,32,97,110,100,32,116,104,101,32,99,111,109,109,97,32,97,114,101,32,98,111,116,104,32,111,109,105,116,116,101,100,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,115,112,101,99,105,102,105,101,115,32,97,110,32,101,120,97,99,116,32,110,117,109,98,101,114,32,111,102,32,114,101,113,117,105,114,101,100,32,109,97,116,99,104,101,115,46,32,84,104,117,115,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,116,32,108,101,97,115,116,32,116,104,114,101,101,32,115,117,99,99,101,115,115,105,118,101,32,118,111,119,101,108,115,44,32,98,117,116,32,99,97,110,32,109,97,116,99,104,32,109,97,110,121,32,109,111,114,101,58>>]},{pre,[],[{code,[],[<<91,97,101,105,111,117,93,123,51,44,125>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,101,120,97,99,116,108,121,32,101,105,103,104,116,32,100,105,103,105,116,115,58>>]},{pre,[],[{code,[],[<<92,100,123,56,125>>]}]},{p,[],[<<65,110,32,111,112,101,110,105,110,103,32,99,117,114,108,121,32,98,114,97,99,107,101,116,32,116,104,97,116,32,97,112,112,101,97,114,115,32,105,110,32,97,32,112,111,115,105,116,105,111,110,32,119,104,101,114,101,32,97,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,44,32,111,114,32,111,110,101,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,116,104,101,32,115,121,110,116,97,120,32,111,102,32,97,32,113,117,97,110,116,105,102,105,101,114,44,32,105,115,32,116,97,107,101,110,32,97,115,32,97,32,108,105,116,101,114,97,108,32,99,104,97,114,97,99,116,101,114,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,123,44,54,125,32,105,115,32,110,111,116,32,97,32,113,117,97,110,116,105,102,105,101,114,44,32,98,117,116,32,97,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,32,111,102,32,102,111,117,114,32,99,104,97,114,97,99,116,101,114,115,46>>]},{p,[],[<<73,110,32,85,110,105,99,111,100,101,32,109,111,100,101,44,32,113,117,97,110,116,105,102,105,101,114,115,32,97,112,112,108,121,32,116,111,32,99,104,97,114,97,99,116,101,114,115,32,114,97,116,104,101,114,32,116,104,97,110,32,116,111,32,105,110,100,105,118,105,100,117,97,108,32,100,97,116,97,32,117,110,105,116,115,46,32,84,104,117,115,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,92,120,123,49,48,48,125,123,50,125,32,109,97,116,99,104,101,115,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,44,32,101,97,99,104,32,111,102,32,119,104,105,99,104,32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,50,45,98,121,116,101,32,115,101,113,117,101,110,99,101,32,105,110,32,97,32,85,84,70,45,56,32,115,116,114,105,110,103,46,32,83,105,109,105,108,97,114,108,121,44,32,92,88,123,51,125,32,109,97,116,99,104,101,115,32,116,104,114,101,101,32,85,110,105,99,111,100,101,32,101,120,116,101,110,100,101,100,32,103,114,97,112,104,101,109,101,32,99,108,117,115,116,101,114,115,44,32,101,97,99,104,32,111,102,32,119,104,105,99,104,32,99,97,110,32,98,101,32,109,97,110,121,32,100,97,116,97,32,117,110,105,116,115,32,108,111,110,103,32,40,97,110,100,32,116,104,101,121,32,99,97,110,32,98,101,32,111,102,32,100,105,102,102,101,114,101,110,116,32,108,101,110,103,116,104,115,41,46>>]},{p,[],[<<84,104,101,32,113,117,97,110,116,105,102,105,101,114,32,123,48,125,32,105,115,32,112,101,114,109,105,116,116,101,100,44,32,99,97,117,115,105,110,103,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,116,111,32,98,101,104,97,118,101,32,97,115,32,105,102,32,116,104,101,32,112,114,101,118,105,111,117,115,32,105,116,101,109,32,97,110,100,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,119,101,114,101,32,110,111,116,32,112,114,101,115,101,110,116,46,32,84,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,102,111,114,32,115,117,98,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,114,101,102,101,114,101,110,99,101,100,32,97,115,32,115,117,98,114,111,117,116,105,110,101,115,32,102,114,111,109,32,101,108,115,101,119,104,101,114,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,40,98,117,116,32,115,101,101,32,97,108,115,111,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,100,101,102,105,110,105,110,103,95,115,117,98,112,97,116,116,101,114,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,101,102,105,110,105,110,103,32,83,117,98,112,97,116,116,101,114,110,115,32,102,111,114,32,85,115,101,32,98,121,32,82,101,102,101,114,101,110,99,101,32,79,110,108,121>>]},<<41,46,32,73,116,101,109,115,32,111,116,104,101,114,32,116,104,97,110,32,115,117,98,112,97,116,116,101,114,110,115,32,116,104,97,116,32,104,97,118,101,32,97,32,123,48,125,32,113,117,97,110,116,105,102,105,101,114,32,97,114,101,32,111,109,105,116,116,101,100,32,102,114,111,109,32,116,104,101,32,99,111,109,112,105,108,101,100,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<70,111,114,32,99,111,110,118,101,110,105,101,110,99,101,44,32,116,104,101,32,116,104,114,101,101,32,109,111,115,116,32,99,111,109,109,111,110,32,113,117,97,110,116,105,102,105,101,114,115,32,104,97,118,101,32,115,105,110,103,108,101,45,99,104,97,114,97,99,116,101,114,32,97,98,98,114,101,118,105,97,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[<<42>>]},{dd,[],[<<69,113,117,105,118,97,108,101,110,116,32,116,111,32,123,48,44,125>>]},{dt,[],[<<43>>]},{dd,[],[<<69,113,117,105,118,97,108,101,110,116,32,116,111,32,123,49,44,125>>]},{dt,[],[<<63>>]},{dd,[],[<<69,113,117,105,118,97,108,101,110,116,32,116,111,32,123,48,44,49,125>>]}]},{p,[],[<<73,110,102,105,110,105,116,101,32,108,111,111,112,115,32,99,97,110,32,98,101,32,99,111,110,115,116,114,117,99,116,101,100,32,98,121,32,102,111,108,108,111,119,105,110,103,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,99,97,110,32,109,97,116,99,104,32,110,111,32,99,104,97,114,97,99,116,101,114,115,32,119,105,116,104,32,97,32,113,117,97,110,116,105,102,105,101,114,32,116,104,97,116,32,104,97,115,32,110,111,32,117,112,112,101,114,32,108,105,109,105,116,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,63,41,42>>]}]},{p,[],[<<69,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,111,102,32,80,101,114,108,32,97,110,100,32,80,67,82,69,32,117,115,101,100,32,116,111,32,103,105,118,101,32,97,110,32,101,114,114,111,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,32,102,111,114,32,115,117,99,104,32,112,97,116,116,101,114,110,115,46,32,72,111,119,101,118,101,114,44,32,97,115,32,116,104,101,114,101,32,97,114,101,32,99,97,115,101,115,32,119,104,101,114,101,32,116,104,105,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,44,32,115,117,99,104,32,112,97,116,116,101,114,110,115,32,97,114,101,32,110,111,119,32,97,99,99,101,112,116,101,100,46,32,72,111,119,101,118,101,114,44,32,105,102,32,97,110,121,32,114,101,112,101,116,105,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,110,111,32,99,104,97,114,97,99,116,101,114,115,44,32,116,104,101,32,108,111,111,112,32,105,115,32,102,111,114,99,105,98,108,121,32,98,114,111,107,101,110,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,34,103,114,101,101,100,121,34,44,32,116,104,97,116,32,105,115,44,32,116,104,101,121,32,109,97,116,99,104,32,97,115,32,109,117,99,104,32,97,115,32,112,111,115,115,105,98,108,101,32,40,117,112,32,116,111,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,101,114,109,105,116,116,101,100,32,116,105,109,101,115,41,44,32,119,105,116,104,111,117,116,32,99,97,117,115,105,110,103,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,116,111,32,102,97,105,108,46,32,84,104,101,32,99,108,97,115,115,105,99,32,101,120,97,109,112,108,101,32,111,102,32,119,104,101,114,101,32,116,104,105,115,32,103,105,118,101,115,32,112,114,111,98,108,101,109,115,32,105,115,32,105,110,32,116,114,121,105,110,103,32,116,111,32,109,97,116,99,104,32,99,111,109,109,101,110,116,115,32,105,110,32,67,32,112,114,111,103,114,97,109,115,46,32,84,104,101,115,101,32,97,112,112,101,97,114,32,98,101,116,119,101,101,110,32,47,42,32,97,110,100,32,42,47,46,32,87,105,116,104,105,110,32,116,104,101,32,99,111,109,109,101,110,116,44,32,105,110,100,105,118,105,100,117,97,108,32,42,32,97,110,100,32,47,32,99,104,97,114,97,99,116,101,114,115,32,99,97,110,32,97,112,112,101,97,114,46,32,65,110,32,97,116,116,101,109,112,116,32,116,111,32,109,97,116,99,104,32,67,32,99,111,109,109,101,110,116,115,32,98,121,32,97,112,112,108,121,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110>>]},{pre,[],[{code,[],[<<47,92,42,46,42,92,42,47>>]}]},{p,[],[<<116,111,32,116,104,101,32,115,116,114,105,110,103>>]},{pre,[],[{code,[],[<<47,42,32,102,105,114,115,116,32,99,111,109,109,101,110,116,32,42,47,32,32,110,111,116,32,99,111,109,109,101,110,116,32,32,47,42,32,115,101,99,111,110,100,32,99,111,109,109,101,110,116,32,42,47>>]}]},{p,[],[<<102,97,105,108,115,44,32,97,115,32,105,116,32,109,97,116,99,104,101,115,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,32,111,119,105,110,103,32,116,111,32,116,104,101,32,103,114,101,101,100,105,110,101,115,115,32,111,102,32,116,104,101,32,46,42,32,105,116,101,109,46>>]},{p,[],[<<72,111,119,101,118,101,114,44,32,105,102,32,97,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,113,117,101,115,116,105,111,110,32,109,97,114,107,44,32,105,116,32,99,101,97,115,101,115,32,116,111,32,98,101,32,103,114,101,101,100,121,44,32,97,110,100,32,105,110,115,116,101,97,100,32,109,97,116,99,104,101,115,32,116,104,101,32,109,105,110,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,112,111,115,115,105,98,108,101,44,32,115,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,100,111,101,115,32,116,104,101,32,114,105,103,104,116,32,116,104,105,110,103,32,119,105,116,104,32,116,104,101,32,67,32,99,111,109,109,101,110,116,115,58>>]},{pre,[],[{code,[],[<<47,92,42,46,42,63,92,42,47>>]}]},{p,[],[<<84,104,101,32,109,101,97,110,105,110,103,32,111,102,32,116,104,101,32,118,97,114,105,111,117,115,32,113,117,97,110,116,105,102,105,101,114,115,32,105,115,32,110,111,116,32,111,116,104,101,114,119,105,115,101,32,99,104,97,110,103,101,100,44,32,111,110,108,121,32,116,104,101,32,112,114,101,102,101,114,114,101,100,32,110,117,109,98,101,114,32,111,102,32,109,97,116,99,104,101,115,46,32,68,111,32,110,111,116,32,99,111,110,102,117,115,101,32,116,104,105,115,32,117,115,101,32,111,102,32,113,117,101,115,116,105,111,110,32,109,97,114,107,32,119,105,116,104,32,105,116,115,32,117,115,101,32,97,115,32,97,32,113,117,97,110,116,105,102,105,101,114,32,105,110,32,105,116,115,32,111,119,110,32,114,105,103,104,116,46,32,65,115,32,105,116,32,104,97,115,32,116,119,111,32,117,115,101,115,44,32,105,116,32,99,97,110,32,115,111,109,101,116,105,109,101,115,32,97,112,112,101,97,114,32,100,111,117,98,108,101,100,44,32,97,115,32,105,110>>]},{pre,[],[{code,[],[<<92,100,63,63,92,100>>]}]},{p,[],[<<119,104,105,99,104,32,109,97,116,99,104,101,115,32,111,110,101,32,100,105,103,105,116,32,98,121,32,112,114,101,102,101,114,101,110,99,101,44,32,98,117,116,32,99,97,110,32,109,97,116,99,104,32,116,119,111,32,105,102,32,116,104,97,116,32,105,115,32,116,104,101,32,111,110,108,121,32,119,97,121,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,46>>]},{p,[],[<<73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,103,114,101,101,100,121>>]},<<32,105,115,32,115,101,116,32,40,97,110,32,111,112,116,105,111,110,32,116,104,97,116,32,105,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,32,105,110,32,80,101,114,108,41,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,110,111,116,32,103,114,101,101,100,121,32,98,121,32,100,101,102,97,117,108,116,44,32,98,117,116,32,105,110,100,105,118,105,100,117,97,108,32,111,110,101,115,32,99,97,110,32,98,101,32,109,97,100,101,32,103,114,101,101,100,121,32,98,121,32,102,111,108,108,111,119,105,110,103,32,116,104,101,109,32,119,105,116,104,32,97,32,113,117,101,115,116,105,111,110,32,109,97,114,107,46,32,84,104,97,116,32,105,115,44,32,105,116,32,105,110,118,101,114,116,115,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,46>>]},{p,[],[<<87,104,101,110,32,97,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,113,117,97,110,116,105,102,105,101,100,32,119,105,116,104,32,97,32,109,105,110,105,109,117,109,32,114,101,112,101,97,116,32,99,111,117,110,116,32,116,104,97,116,32,105,115,32,62,32,49,32,111,114,32,119,105,116,104,32,97,32,108,105,109,105,116,101,100,32,109,97,120,105,109,117,109,44,32,109,111,114,101,32,109,101,109,111,114,121,32,105,115,32,114,101,113,117,105,114,101,100,32,102,111,114,32,116,104,101,32,99,111,109,112,105,108,101,100,32,112,97,116,116,101,114,110,44,32,105,110,32,112,114,111,112,111,114,116,105,111,110,32,116,111,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,109,105,110,105,109,117,109,32,111,114,32,109,97,120,105,109,117,109,46>>]},{p,[],[<<73,102,32,97,32,112,97,116,116,101,114,110,32,115,116,97,114,116,115,32,119,105,116,104,32,46,42,32,111,114,32,46,123,48,44,125,32,97,110,100,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,40,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,115>>]},<<41,32,105,115,32,115,101,116,44,32,116,104,117,115,32,97,108,108,111,119,105,110,103,32,116,104,101,32,100,111,116,32,116,111,32,109,97,116,99,104,32,110,101,119,108,105,110,101,115,44,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,105,109,112,108,105,99,105,116,108,121,32,97,110,99,104,111,114,101,100,44,32,98,101,99,97,117,115,101,32,119,104,97,116,101,118,101,114,32,102,111,108,108,111,119,115,32,105,115,32,116,114,105,101,100,32,97,103,97,105,110,115,116,32,101,118,101,114,121,32,99,104,97,114,97,99,116,101,114,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,83,111,44,32,116,104,101,114,101,32,105,115,32,110,111,32,112,111,105,110,116,32,105,110,32,114,101,116,114,121,105,110,103,32,116,104,101,32,111,118,101,114,97,108,108,32,109,97,116,99,104,32,97,116,32,97,110,121,32,112,111,115,105,116,105,111,110,32,97,102,116,101,114,32,116,104,101,32,102,105,114,115,116,46,32,80,67,82,69,32,110,111,114,109,97,108,108,121,32,116,114,101,97,116,115,32,115,117,99,104,32,97,32,112,97,116,116,101,114,110,32,97,115,32,105,102,32,105,116,32,119,97,115,32,112,114,101,99,101,100,101,100,32,98,121,32,92,65,46>>]},{p,[],[<<73,110,32,99,97,115,101,115,32,119,104,101,114,101,32,105,116,32,105,115,32,107,110,111,119,110,32,116,104,97,116,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,115,32,110,111,32,110,101,119,108,105,110,101,115,44,32,105,116,32,105,115,32,119,111,114,116,104,32,115,101,116,116,105,110,103,32>>,{code,[],[<<100,111,116,97,108,108>>]},<<32,116,111,32,111,98,116,97,105,110,32,116,104,105,115,32,111,112,116,105,109,105,122,97,116,105,111,110,44,32,111,114,32,97,108,116,101,114,110,97,116,105,118,101,108,121,32,117,115,105,110,103,32,94,32,116,111,32,105,110,100,105,99,97,116,101,32,97,110,99,104,111,114,105,110,103,32,101,120,112,108,105,99,105,116,108,121,46>>]},{p,[],[<<72,111,119,101,118,101,114,44,32,116,104,101,114,101,32,97,114,101,32,115,111,109,101,32,99,97,115,101,115,32,119,104,101,114,101,32,116,104,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,99,97,110,110,111,116,32,98,101,32,117,115,101,100,46,32,87,104,101,110,32,46,42,32,105,115,32,105,110,115,105,100,101,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,116,104,101,32,115,117,98,106,101,99,116,32,111,102,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,101,108,115,101,119,104,101,114,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,44,32,97,32,109,97,116,99,104,32,97,116,32,116,104,101,32,115,116,97,114,116,32,99,97,110,32,102,97,105,108,32,119,104,101,114,101,32,97,32,108,97,116,101,114,32,111,110,101,32,115,117,99,99,101,101,100,115,46,32,67,111,110,115,105,100,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,46,42,41,97,98,99,92,49>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,120,121,122,49,50,51,97,98,99,49,50,51,34,44,32,116,104,101,32,109,97,116,99,104,32,112,111,105,110,116,32,105,115,32,116,104,101,32,102,111,117,114,116,104,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,114,101,102,111,114,101,44,32,115,117,99,104,32,97,32,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,105,109,112,108,105,99,105,116,108,121,32,97,110,99,104,111,114,101,100,46>>]},{p,[],[<<65,110,111,116,104,101,114,32,99,97,115,101,32,119,104,101,114,101,32,105,109,112,108,105,99,105,116,32,97,110,99,104,111,114,105,110,103,32,105,115,32,110,111,116,32,97,112,112,108,105,101,100,32,105,115,32,119,104,101,110,32,116,104,101,32,108,101,97,100,105,110,103,32,46,42,32,105,115,32,105,110,115,105,100,101,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,79,110,99,101,32,97,103,97,105,110,44,32,97,32,109,97,116,99,104,32,97,116,32,116,104,101,32,115,116,97,114,116,32,99,97,110,32,102,97,105,108,32,119,104,101,114,101,32,97,32,108,97,116,101,114,32,111,110,101,32,115,117,99,99,101,101,100,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,63,62,46,42,63,97,41,98>>]}]},{p,[],[<<73,116,32,109,97,116,99,104,101,115,32,34,97,98,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,34,97,97,98,34,46,32,84,104,101,32,117,115,101,32,111,102,32,116,104,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,111,110,116,114,111,108,32,118,101,114,98,115,32,40,42,80,82,85,78,69,41,32,97,110,100,32,40,42,83,75,73,80,41,32,97,108,115,111,32,100,105,115,97,98,108,101,32,116,104,105,115,32,111,112,116,105,109,105,122,97,116,105,111,110,46>>]},{p,[],[<<87,104,101,110,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,114,101,112,101,97,116,101,100,44,32,116,104,101,32,118,97,108,117,101,32,99,97,112,116,117,114,101,100,32,105,115,32,116,104,101,32,115,117,98,115,116,114,105,110,103,32,116,104,97,116,32,109,97,116,99,104,101,100,32,116,104,101,32,102,105,110,97,108,32,105,116,101,114,97,116,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,102,116,101,114>>]},{pre,[],[{code,[],[<<40,116,119,101,101,100,108,101,91,100,117,109,101,93,123,51,125,92,115,42,41,43>>]}]},{p,[],[<<104,97,115,32,109,97,116,99,104,101,100,32,34,116,119,101,101,100,108,101,100,117,109,32,116,119,101,101,100,108,101,100,101,101,34,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,32,105,115,32,34,116,119,101,101,100,108,101,100,101,101,34,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,114,101,32,97,114,101,32,110,101,115,116,101,100,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,116,104,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,99,97,112,116,117,114,101,100,32,118,97,108,117,101,115,32,99,97,110,32,104,97,118,101,32,98,101,101,110,32,115,101,116,32,105,110,32,112,114,101,118,105,111,117,115,32,105,116,101,114,97,116,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,102,116,101,114>>]},{pre,[],[{code,[],[<<47,40,97,124,40,98,41,41,43,47>>]}]},{p,[],[<<109,97,116,99,104,101,115,32,34,97,98,97,34,44,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,115,101,99,111,110,100,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,32,105,115,32,34,98,34,46>>]},{a,[{id,<<115,101,99,116,49,53>>}],[]},{h2,[],[<<65,116,111,109,105,99,32,71,114,111,117,112,105,110,103,32,97,110,100,32,80,111,115,115,101,115,115,105,118,101,32,81,117,97,110,116,105,102,105,101,114,115>>]},{p,[],[<<87,105,116,104,32,98,111,116,104,32,109,97,120,105,109,105,122,105,110,103,32,40,34,103,114,101,101,100,121,34,41,32,97,110,100,32,109,105,110,105,109,105,122,105,110,103,32,40,34,117,110,103,114,101,101,100,121,34,32,111,114,32,34,108,97,122,121,34,41,32,114,101,112,101,116,105,116,105,111,110,44,32,102,97,105,108,117,114,101,32,111,102,32,119,104,97,116,32,102,111,108,108,111,119,115,32,110,111,114,109,97,108,108,121,32,99,97,117,115,101,115,32,116,104,101,32,114,101,112,101,97,116,101,100,32,105,116,101,109,32,116,111,32,98,101,32,114,101,45,101,118,97,108,117,97,116,101,100,32,116,111,32,115,101,101,32,105,102,32,97,32,100,105,102,102,101,114,101,110,116,32,110,117,109,98,101,114,32,111,102,32,114,101,112,101,97,116,115,32,97,108,108,111,119,115,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,116,111,32,109,97,116,99,104,46,32,83,111,109,101,116,105,109,101,115,32,105,116,32,105,115,32,117,115,101,102,117,108,32,116,111,32,112,114,101,118,101,110,116,32,116,104,105,115,44,32,101,105,116,104,101,114,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,110,97,116,117,114,101,32,111,102,32,116,104,101,32,109,97,116,99,104,44,32,111,114,32,116,111,32,99,97,117,115,101,32,105,116,32,116,111,32,102,97,105,108,32,101,97,114,108,105,101,114,32,116,104,97,110,32,105,116,32,111,116,104,101,114,119,105,115,101,32,109,105,103,104,116,44,32,119,104,101,110,32,116,104,101,32,97,117,116,104,111,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,107,110,111,119,115,32,116,104,97,116,32,116,104,101,114,101,32,105,115,32,110,111,32,112,111,105,110,116,32,105,110,32,99,97,114,114,121,105,110,103,32,111,110,46>>]},{p,[],[<<67,111,110,115,105,100,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,112,97,116,116,101,114,110,32,92,100,43,102,111,111,32,119,104,101,110,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,117,98,106,101,99,116,32,108,105,110,101,58>>]},{pre,[],[{code,[],[<<49,50,51,52,53,54,98,97,114>>]}]},{p,[],[<<65,102,116,101,114,32,109,97,116,99,104,105,110,103,32,97,108,108,32,115,105,120,32,100,105,103,105,116,115,32,97,110,100,32,116,104,101,110,32,102,97,105,108,105,110,103,32,116,111,32,109,97,116,99,104,32,34,102,111,111,34,44,32,116,104,101,32,110,111,114,109,97,108,32,97,99,116,105,111,110,32,111,102,32,116,104,101,32,109,97,116,99,104,101,114,32,105,115,32,116,111,32,116,114,121,32,97,103,97,105,110,32,119,105,116,104,32,111,110,108,121,32,102,105,118,101,32,100,105,103,105,116,115,32,109,97,116,99,104,105,110,103,32,105,116,101,109,32,92,100,43,44,32,97,110,100,32,116,104,101,110,32,119,105,116,104,32,102,111,117,114,44,32,97,110,100,32,115,111,32,111,110,44,32,98,101,102,111,114,101,32,117,108,116,105,109,97,116,101,108,121,32,102,97,105,108,105,110,103,46,32,34,65,116,111,109,105,99,32,103,114,111,117,112,105,110,103,34,32,40,97,32,116,101,114,109,32,116,97,107,101,110,32,102,114,111,109,32,74,101,102,102,114,101,121,32,70,114,105,101,100,108,39,115,32,98,111,111,107,41,32,112,114,111,118,105,100,101,115,32,116,104,101,32,109,101,97,110,115,32,102,111,114,32,115,112,101,99,105,102,121,105,110,103,32,116,104,97,116,32,111,110,99,101,32,97,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,109,97,116,99,104,101,100,44,32,105,116,32,105,115,32,110,111,116,32,116,111,32,98,101,32,114,101,45,101,118,97,108,117,97,116,101,100,32,105,110,32,116,104,105,115,32,119,97,121,46>>]},{p,[],[<<73,102,32,97,116,111,109,105,99,32,103,114,111,117,112,105,110,103,32,105,115,32,117,115,101,100,32,102,111,114,32,116,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,44,32,116,104,101,32,109,97,116,99,104,101,114,32,103,105,118,101,115,32,117,112,32,105,109,109,101,100,105,97,116,101,108,121,32,111,110,32,102,97,105,108,105,110,103,32,116,111,32,109,97,116,99,104,32,34,102,111,111,34,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,46,32,84,104,101,32,110,111,116,97,116,105,111,110,32,105,115,32,97,32,107,105,110,100,32,111,102,32,115,112,101,99,105,97,108,32,112,97,114,101,110,116,104,101,115,105,115,44,32,115,116,97,114,116,105,110,103,32,119,105,116,104,32>>,{code,[],[<<40,63,62>>]},<<32,97,115,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,63,62,92,100,43,41,102,111,111>>]}]},{p,[],[<<84,104,105,115,32,107,105,110,100,32,111,102,32,112,97,114,101,110,116,104,101,115,105,115,32,34,108,111,99,107,115,32,117,112,34,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,116,32,99,111,110,116,97,105,110,115,32,111,110,99,101,32,105,116,32,104,97,115,32,109,97,116,99,104,101,100,44,32,97,110,100,32,97,32,102,97,105,108,117,114,101,32,102,117,114,116,104,101,114,32,105,110,116,111,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,112,114,101,118,101,110,116,101,100,32,102,114,111,109,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,105,116,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,112,97,115,116,32,105,116,32,116,111,32,112,114,101,118,105,111,117,115,32,105,116,101,109,115,44,32,104,111,119,101,118,101,114,44,32,119,111,114,107,115,32,97,115,32,110,111,114,109,97,108,46>>]},{p,[],[<<65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,100,101,115,99,114,105,112,116,105,111,110,32,105,115,32,116,104,97,116,32,97,32,115,117,98,112,97,116,116,101,114,110,32,111,102,32,116,104,105,115,32,116,121,112,101,32,109,97,116,99,104,101,115,32,116,104,101,32,115,116,114,105,110,103,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,110,32,105,100,101,110,116,105,99,97,108,32,115,116,97,110,100,97,108,111,110,101,32,112,97,116,116,101,114,110,32,119,111,117,108,100,32,109,97,116,99,104,44,32,105,102,32,97,110,99,104,111,114,101,100,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,105,110,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]},{p,[],[<<65,116,111,109,105,99,32,103,114,111,117,112,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,110,111,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,83,105,109,112,108,101,32,99,97,115,101,115,32,115,117,99,104,32,97,115,32,116,104,101,32,97,98,111,118,101,32,101,120,97,109,112,108,101,32,99,97,110,32,98,101,32,116,104,111,117,103,104,116,32,111,102,32,97,115,32,97,32,109,97,120,105,109,105,122,105,110,103,32,114,101,112,101,97,116,32,116,104,97,116,32,109,117,115,116,32,115,119,97,108,108,111,119,32,101,118,101,114,121,116,104,105,110,103,32,105,116,32,99,97,110,46,32,83,111,44,32,119,104,105,108,101,32,98,111,116,104,32,92,100,43,32,97,110,100,32,92,100,43,63,32,97,114,101,32,112,114,101,112,97,114,101,100,32,116,111,32,97,100,106,117,115,116,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,100,105,103,105,116,115,32,116,104,101,121,32,109,97,116,99,104,32,116,111,32,109,97,107,101,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,44,32>>,{code,[],[<<40,63,62,92,100,43,41>>]},<<32,99,97,110,32,111,110,108,121,32,109,97,116,99,104,32,97,110,32,101,110,116,105,114,101,32,115,101,113,117,101,110,99,101,32,111,102,32,100,105,103,105,116,115,46>>]},{p,[],[<<65,116,111,109,105,99,32,103,114,111,117,112,115,32,105,110,32,103,101,110,101,114,97,108,32,99,97,110,32,99,111,110,116,97,105,110,32,97,110,121,32,99,111,109,112,108,105,99,97,116,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,97,110,100,32,99,97,110,32,98,101,32,110,101,115,116,101,100,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,102,111,114,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,105,115,32,106,117,115,116,32,97,32,115,105,110,103,108,101,32,114,101,112,101,97,116,101,100,32,105,116,101,109,44,32,97,115,32,105,110,32,116,104,101,32,101,120,97,109,112,108,101,32,97,98,111,118,101,44,32,97,32,115,105,109,112,108,101,114,32,110,111,116,97,116,105,111,110,44,32,99,97,108,108,101,100,32,97,32,34,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,34,32,99,97,110,32,98,101,32,117,115,101,100,46,32,84,104,105,115,32,99,111,110,115,105,115,116,115,32,111,102,32,97,110,32,101,120,116,114,97,32,43,32,99,104,97,114,97,99,116,101,114,32,102,111,108,108,111,119,105,110,103,32,97,32,113,117,97,110,116,105,102,105,101,114,46,32,85,115,105,110,103,32,116,104,105,115,32,110,111,116,97,116,105,111,110,44,32,116,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,32,99,97,110,32,98,101,32,114,101,119,114,105,116,116,101,110,32,97,115>>]},{pre,[],[{code,[],[<<92,100,43,43,102,111,111>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,97,110,32,101,110,116,105,114,101,32,103,114,111,117,112,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,98,99,124,120,121,122,41,123,50,44,51,125,43>>]}]},{p,[],[<<80,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,97,108,119,97,121,115,32,103,114,101,101,100,121,59,32,116,104,101,32,115,101,116,116,105,110,103,32,111,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,103,114,101,101,100,121>>]},<<32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,121,32,97,114,101,32,97,32,99,111,110,118,101,110,105,101,110,116,32,110,111,116,97,116,105,111,110,32,102,111,114,32,116,104,101,32,115,105,109,112,108,101,114,32,102,111,114,109,115,32,111,102,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,72,111,119,101,118,101,114,44,32,116,104,101,114,101,32,105,115,32,110,111,32,100,105,102,102,101,114,101,110,99,101,32,105,110,32,116,104,101,32,109,101,97,110,105,110,103,32,111,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,97,110,100,32,116,104,101,32,101,113,117,105,118,97,108,101,110,116,32,97,116,111,109,105,99,32,103,114,111,117,112,44,32,98,117,116,32,116,104,101,114,101,32,99,97,110,32,98,101,32,97,32,112,101,114,102,111,114,109,97,110,99,101,32,100,105,102,102,101,114,101,110,99,101,59,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,115,32,97,114,101,32,112,114,111,98,97,98,108,121,32,115,108,105,103,104,116,108,121,32,102,97,115,116,101,114,46>>]},{p,[],[<<84,104,101,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,115,121,110,116,97,120,32,105,115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,116,111,32,116,104,101,32,80,101,114,108,32,53,46,56,32,115,121,110,116,97,120,46,32,74,101,102,102,114,101,121,32,70,114,105,101,100,108,32,111,114,105,103,105,110,97,116,101,100,32,116,104,101,32,105,100,101,97,32,40,97,110,100,32,116,104,101,32,110,97,109,101,41,32,105,110,32,116,104,101,32,102,105,114,115,116,32,101,100,105,116,105,111,110,32,111,102,32,104,105,115,32,98,111,111,107,46,32,77,105,107,101,32,77,99,67,108,111,115,107,101,121,32,108,105,107,101,100,32,105,116,44,32,115,111,32,105,109,112,108,101,109,101,110,116,101,100,32,105,116,32,119,104,101,110,32,104,101,32,98,117,105,108,116,32,116,104,101,32,83,117,110,32,74,97,118,97,32,112,97,99,107,97,103,101,44,32,97,110,100,32,80,67,82,69,32,99,111,112,105,101,100,32,105,116,32,102,114,111,109,32,116,104,101,114,101,46,32,73,116,32,117,108,116,105,109,97,116,101,108,121,32,102,111,117,110,100,32,105,116,115,32,119,97,121,32,105,110,116,111,32,80,101,114,108,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,48,46>>]},{p,[],[<<80,67,82,69,32,104,97,115,32,97,110,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,34,112,111,115,115,101,115,115,105,102,105,101,115,34,32,99,101,114,116,97,105,110,32,115,105,109,112,108,101,32,112,97,116,116,101,114,110,32,99,111,110,115,116,114,117,99,116,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,115,101,113,117,101,110,99,101,32,65,43,66,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,65,43,43,66,44,32,97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,112,111,105,110,116,32,105,110,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,65,58,115,32,119,104,101,110,32,66,32,109,117,115,116,32,102,111,108,108,111,119,46>>]},{p,[],[<<87,104,101,110,32,97,32,112,97,116,116,101,114,110,32,99,111,110,116,97,105,110,115,32,97,110,32,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,32,105,110,115,105,100,101,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,99,97,110,32,105,116,115,101,108,102,32,98,101,32,114,101,112,101,97,116,101,100,32,97,110,32,117,110,108,105,109,105,116,101,100,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,44,32,116,104,101,32,117,115,101,32,111,102,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,105,115,32,116,104,101,32,111,110,108,121,32,119,97,121,32,116,111,32,97,118,111,105,100,32,115,111,109,101,32,102,97,105,108,105,110,103,32,109,97,116,99,104,101,115,32,116,97,107,105,110,103,32,97,32,108,111,110,103,32,116,105,109,101,46,32,84,104,101,32,112,97,116,116,101,114,110>>]},{pre,[],[{code,[],[<<40,92,68,43,124,60,92,100,43,62,41,42,91,33,63,93>>]}]},{p,[],[<<109,97,116,99,104,101,115,32,97,110,32,117,110,108,105,109,105,116,101,100,32,110,117,109,98,101,114,32,111,102,32,115,117,98,115,116,114,105,110,103,115,32,116,104,97,116,32,101,105,116,104,101,114,32,99,111,110,115,105,115,116,32,111,102,32,110,111,110,45,100,105,103,105,116,115,44,32,111,114,32,100,105,103,105,116,115,32,101,110,99,108,111,115,101,100,32,105,110,32,60,62,44,32,102,111,108,108,111,119,101,100,32,98,121,32,33,32,111,114,32,63,46,32,87,104,101,110,32,105,116,32,109,97,116,99,104,101,115,44,32,105,116,32,114,117,110,115,32,113,117,105,99,107,108,121,46,32,72,111,119,101,118,101,114,44,32,105,102,32,105,116,32,105,115,32,97,112,112,108,105,101,100,32,116,111>>]},{pre,[],[{code,[],[<<97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97>>]}]},{p,[],[<<105,116,32,116,97,107,101,115,32,97,32,108,111,110,103,32,116,105,109,101,32,98,101,102,111,114,101,32,114,101,112,111,114,116,105,110,103,32,102,97,105,108,117,114,101,46,32,84,104,105,115,32,105,115,32,98,101,99,97,117,115,101,32,116,104,101,32,115,116,114,105,110,103,32,99,97,110,32,98,101,32,100,105,118,105,100,101,100,32,98,101,116,119,101,101,110,32,116,104,101,32,105,110,116,101,114,110,97,108,32,92,68,43,32,114,101,112,101,97,116,32,97,110,100,32,116,104,101,32,101,120,116,101,114,110,97,108,32,42,32,114,101,112,101,97,116,32,105,110,32,109,97,110,121,32,119,97,121,115,44,32,97,110,100,32,97,108,108,32,109,117,115,116,32,98,101,32,116,114,105,101,100,46,32,40,84,104,101,32,101,120,97,109,112,108,101,32,117,115,101,115,32,91,33,63,93,32,114,97,116,104,101,114,32,116,104,97,110,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,97,116,32,116,104,101,32,101,110,100,44,32,97,115,32,98,111,116,104,32,80,67,82,69,32,97,110,100,32,80,101,114,108,32,104,97,118,101,32,97,110,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,97,108,108,111,119,115,32,102,111,114,32,102,97,115,116,32,102,97,105,108,117,114,101,32,119,104,101,110,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,105,115,32,117,115,101,100,46,32,84,104,101,121,32,114,101,109,101,109,98,101,114,32,116,104,101,32,108,97,115,116,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,116,104,97,116,32,105,115,32,114,101,113,117,105,114,101,100,32,102,111,114,32,97,32,109,97,116,99,104,44,32,97,110,100,32,102,97,105,108,32,101,97,114,108,121,32,105,102,32,105,116,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,115,116,114,105,110,103,46,41,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,99,104,97,110,103,101,100,32,115,111,32,116,104,97,116,32,105,116,32,117,115,101,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,44,32,108,105,107,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,115,101,113,117,101,110,99,101,115,32,111,102,32,110,111,110,45,100,105,103,105,116,115,32,99,97,110,110,111,116,32,98,101,32,98,114,111,107,101,110,44,32,97,110,100,32,102,97,105,108,117,114,101,32,104,97,112,112,101,110,115,32,113,117,105,99,107,108,121,58>>]},{pre,[],[{code,[],[<<40,40,63,62,92,68,43,41,124,60,92,100,43,62,41,42,91,33,63,93>>]}]},{a,[{id,<<115,101,99,116,49,54>>}],[]},{h2,[],[<<66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]},{p,[],[<<79,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,97,32,98,97,99,107,115,108,97,115,104,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,100,105,103,105,116,32,62,32,48,32,40,97,110,100,32,112,111,115,115,105,98,108,121,32,102,117,114,116,104,101,114,32,100,105,103,105,116,115,41,32,105,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,101,97,114,108,105,101,114,32,40,116,104,97,116,32,105,115,44,32,116,111,32,105,116,115,32,108,101,102,116,41,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,44,32,112,114,111,118,105,100,101,100,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,32,116,104,97,116,32,109,97,110,121,32,112,114,101,118,105,111,117,115,32,99,97,112,116,117,114,105,110,103,32,108,101,102,116,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,100,101,99,105,109,97,108,32,110,117,109,98,101,114,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,98,97,99,107,115,108,97,115,104,32,105,115,32,60,32,49,48,44,32,105,116,32,105,115,32,97,108,119,97,121,115,32,116,97,107,101,110,32,97,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,97,110,100,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,97,114,101,32,110,111,116,32,116,104,97,116,32,109,97,110,121,32,99,97,112,116,117,114,105,110,103,32,108,101,102,116,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,101,110,116,105,114,101,32,112,97,116,116,101,114,110,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,114,101,102,101,114,101,110,99,101,100,32,100,111,32,110,101,101,100,32,110,111,116,32,98,101,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,116,104,101,32,114,101,102,101,114,101,110,99,101,32,102,111,114,32,110,117,109,98,101,114,115,32,60,32,49,48,46,32,65,32,34,102,111,114,119,97,114,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,34,32,111,102,32,116,104,105,115,32,116,121,112,101,32,99,97,110,32,109,97,107,101,32,115,101,110,115,101,32,119,104,101,110,32,97,32,114,101,112,101,116,105,116,105,111,110,32,105,115,32,105,110,118,111,108,118,101,100,32,97,110,100,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,116,111,32,116,104,101,32,114,105,103,104,116,32,104,97,115,32,112,97,114,116,105,99,105,112,97,116,101,100,32,105,110,32,97,110,32,101,97,114,108,105,101,114,32,105,116,101,114,97,116,105,111,110,46>>]},{p,[],[<<73,116,32,105,115,32,110,111,116,32,112,111,115,115,105,98,108,101,32,116,111,32,104,97,118,101,32,97,32,110,117,109,101,114,105,99,97,108,32,34,102,111,114,119,97,114,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,34,32,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,119,104,111,115,101,32,110,117,109,98,101,114,32,105,115,32,49,48,32,111,114,32,109,111,114,101,32,117,115,105,110,103,32,116,104,105,115,32,115,121,110,116,97,120,44,32,97,115,32,97,32,115,101,113,117,101,110,99,101,32,115,117,99,104,32,97,115,32,92,53,48,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,97,32,99,104,97,114,97,99,116,101,114,32,100,101,102,105,110,101,100,32,105,110,32,111,99,116,97,108,46,32,70,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,32,111,102,32,116,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,97,32,98,97,99,107,115,108,97,115,104,44,32,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,111,110,95,112,114,105,110,116,105,110,103,95,99,104,97,114,97,99,116,101,114,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,111,110,45,80,114,105,110,116,105,110,103,32,67,104,97,114,97,99,116,101,114,115>>]},<<32,101,97,114,108,105,101,114,46,32,84,104,101,114,101,32,105,115,32,110,111,32,115,117,99,104,32,112,114,111,98,108,101,109,32,119,104,101,110,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,117,115,101,100,46,32,65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,97,110,121,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,112,111,115,115,105,98,108,101,32,117,115,105,110,103,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,40,115,101,101,32,98,101,108,111,119,41,46>>]},{p,[],[<<65,110,111,116,104,101,114,32,119,97,121,32,116,111,32,97,118,111,105,100,32,116,104,101,32,97,109,98,105,103,117,105,116,121,32,105,110,104,101,114,101,110,116,32,105,110,32,116,104,101,32,117,115,101,32,111,102,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,97,32,98,97,99,107,115,108,97,115,104,32,105,115,32,116,111,32,117,115,101,32,116,104,101,32,92,103,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,46,32,84,104,105,115,32,101,115,99,97,112,101,32,109,117,115,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,117,110,115,105,103,110,101,100,32,110,117,109,98,101,114,32,111,114,32,97,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,44,32,111,112,116,105,111,110,97,108,108,121,32,101,110,99,108,111,115,101,100,32,105,110,32,98,114,97,99,101,115,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,115,32,97,114,101,32,105,100,101,110,116,105,99,97,108,58>>]},{pre,[],[{code,[],[<<40,114,105,110,103,41,44,32,92,49,10,40,114,105,110,103,41,44,32,92,103,49,10,40,114,105,110,103,41,44,32,92,103,123,49,125>>]}]},{p,[],[<<65,110,32,117,110,115,105,103,110,101,100,32,110,117,109,98,101,114,32,115,112,101,99,105,102,105,101,115,32,97,110,32,97,98,115,111,108,117,116,101,32,114,101,102,101,114,101,110,99,101,32,119,105,116,104,111,117,116,32,116,104,101,32,97,109,98,105,103,117,105,116,121,32,116,104,97,116,32,105,115,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,111,108,100,101,114,32,115,121,110,116,97,120,46,32,73,116,32,105,115,32,97,108,115,111,32,117,115,101,102,117,108,32,119,104,101,110,32,108,105,116,101,114,97,108,32,100,105,103,105,116,115,32,102,111,108,108,111,119,32,116,104,101,32,114,101,102,101,114,101,110,99,101,46,32,65,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,32,105,115,32,97,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,98,99,40,100,101,102,41,103,104,105,41,92,103,123,45,49,125>>]}]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,32,92,103,123,45,49,125,32,105,115,32,97,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,115,116,97,114,116,101,100,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,98,101,102,111,114,101,32,92,103,44,32,116,104,97,116,32,105,115,44,32,105,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,92,50,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,46,32,83,105,109,105,108,97,114,108,121,44,32,92,103,123,45,50,125,32,119,111,117,108,100,32,98,101,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,92,49,46,32,84,104,101,32,117,115,101,32,111,102,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,115,32,99,97,110,32,98,101,32,104,101,108,112,102,117,108,32,105,110,32,108,111,110,103,32,112,97,116,116,101,114,110,115,44,32,97,110,100,32,97,108,115,111,32,105,110,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,99,114,101,97,116,101,100,32,98,121,32,106,111,105,110,105,110,103,32,102,114,97,103,109,101,110,116,115,32,99,111,110,116,97,105,110,105,110,103,32,114,101,102,101,114,101,110,99,101,115,32,119,105,116,104,105,110,32,116,104,101,109,115,101,108,118,101,115,46>>]},{p,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,109,97,116,99,104,101,115,32,119,104,97,116,101,118,101,114,32,109,97,116,99,104,101,100,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,114,97,116,104,101,114,32,116,104,97,110,32,97,110,121,116,104,105,110,103,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,116,115,101,108,102,32,40,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,50,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,117,98,112,97,116,116,101,114,110,32,97,115,32,83,117,98,114,111,117,116,105,110,101,115>>]},<<32,100,101,115,99,114,105,98,101,115,32,97,32,119,97,121,32,111,102,32,100,111,105,110,103,32,116,104,97,116,41,46,32,83,111,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,115,101,110,115,101,32,97,110,100,32,115,101,110,115,105,98,105,108,105,116,121,34,32,97,110,100,32,34,114,101,115,112,111,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,44,32,98,117,116,32,110,111,116,32,34,115,101,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,58>>]},{pre,[],[{code,[],[<<40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,92,49,105,98,105,108,105,116,121>>]}]},{p,[],[<<73,102,32,99,97,115,101,102,117,108,32,109,97,116,99,104,105,110,103,32,105,115,32,105,110,32,102,111,114,99,101,32,97,116,32,116,104,101,32,116,105,109,101,32,111,102,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,44,32,116,104,101,32,99,97,115,101,32,111,102,32,108,101,116,116,101,114,115,32,105,115,32,114,101,108,101,118,97,110,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,114,97,104,32,114,97,104,34,32,97,110,100,32,34,82,65,72,32,82,65,72,34,44,32,98,117,116,32,110,111,116,32,34,82,65,72,32,114,97,104,34,44,32,97,108,116,104,111,117,103,104,32,116,104,101,32,111,114,105,103,105,110,97,108,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,109,97,116,99,104,101,100,32,99,97,115,101,108,101,115,115,108,121,58>>]},{pre,[],[{code,[],[<<40,40,63,105,41,114,97,104,41,92,115,43,92,49>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,32,111,102,32,119,114,105,116,105,110,103,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46,32,84,104,101,32,46,78,69,84,32,115,121,110,116,97,120,32>>,{code,[],[<<92,107,123,110,97,109,101,125>>]},<<32,97,110,100,32,116,104,101,32,80,101,114,108,32,115,121,110,116,97,120,32>>,{code,[],[<<92,107,60,110,97,109,101,62>>]},<<32,111,114,32>>,{code,[],[<<92,107,39,110,97,109,101,39>>]},<<32,97,114,101,32,115,117,112,112,111,114,116,101,100,44,32,97,115,32,105,115,32,116,104,101,32,80,121,116,104,111,110,32,115,121,110,116,97,120,32>>,{code,[],[<<40,63,80,61,110,97,109,101,41>>]},<<46,32,84,104,101,32,117,110,105,102,105,101,100,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,115,121,110,116,97,120,32,105,110,32,80,101,114,108,32,53,46,49,48,44,32,105,110,32,119,104,105,99,104,32,92,103,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,98,111,116,104,32,110,117,109,101,114,105,99,32,97,110,100,32,110,97,109,101,100,32,114,101,102,101,114,101,110,99,101,115,44,32,105,115,32,97,108,115,111,32,115,117,112,112,111,114,116,101,100,46,32,84,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,32,99,97,110,32,98,101,32,114,101,119,114,105,116,116,101,110,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,119,97,121,115,58>>]},{pre,[],[{code,[],[<<40,63,60,112,49,62,40,63,105,41,114,97,104,41,92,115,43,92,107,60,112,49,62,10,40,63,39,112,49,39,40,63,105,41,114,97,104,41,92,115,43,92,107,123,112,49,125,10,40,63,80,60,112,49,62,40,63,105,41,114,97,104,41,92,115,43,40,63,80,61,112,49,41,10,40,63,60,112,49,62,40,63,105,41,114,97,104,41,92,115,43,92,103,123,112,49,125>>]}]},{p,[],[<<65,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,105,115,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32,110,97,109,101,32,99,97,110,32,97,112,112,101,97,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,98,101,102,111,114,101,32,111,114,32,97,102,116,101,114,32,116,104,101,32,114,101,102,101,114,101,110,99,101,46>>]},{p,[],[<<84,104,101,114,101,32,99,97,110,32,98,101,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,115,97,109,101,32,115,117,98,112,97,116,116,101,114,110,46,32,73,102,32,97,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,110,111,116,32,98,101,101,110,32,117,115,101,100,32,105,110,32,97,32,112,97,114,116,105,99,117,108,97,114,32,109,97,116,99,104,44,32,97,110,121,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,105,116,32,97,108,119,97,121,115,32,102,97,105,108,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,97,108,119,97,121,115,32,102,97,105,108,115,32,105,102,32,105,116,32,115,116,97,114,116,115,32,116,111,32,109,97,116,99,104,32,34,97,34,32,114,97,116,104,101,114,32,116,104,97,110,32,34,98,99,34,58>>]},{pre,[],[{code,[],[<<40,97,124,40,98,99,41,41,92,50>>]}]},{p,[],[<<65,115,32,116,104,101,114,101,32,99,97,110,32,98,101,32,109,97,110,121,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,97,108,108,32,100,105,103,105,116,115,32,102,111,108,108,111,119,105,110,103,32,116,104,101,32,98,97,99,107,115,108,97,115,104,32,97,114,101,32,116,97,107,101,110,32,97,115,32,112,97,114,116,32,111,102,32,97,32,112,111,116,101,110,116,105,97,108,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,110,117,109,98,101,114,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,99,111,110,116,105,110,117,101,115,32,119,105,116,104,32,97,32,100,105,103,105,116,32,99,104,97,114,97,99,116,101,114,44,32,115,111,109,101,32,100,101,108,105,109,105,116,101,114,32,109,117,115,116,32,98,101,32,117,115,101,100,32,116,111,32,116,101,114,109,105,110,97,116,101,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,105,115,32,115,101,116,44,32,116,104,105,115,32,99,97,110,32,98,101,32,119,104,105,116,101,115,112,97,99,101,46,32,79,116,104,101,114,119,105,115,101,32,97,110,32,101,109,112,116,121,32,99,111,109,109,101,110,116,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,57>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,111,109,109,101,110,116,115>>]},<<41,32,99,97,110,32,98,101,32,117,115,101,100,46>>]},{p,[],[{em,[],[<<82,101,99,117,114,115,105,118,101,32,66,97,99,107,32,82,101,102,101,114,101,110,99,101,115>>]}]},{p,[],[<<65,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,116,104,97,116,32,111,99,99,117,114,115,32,105,110,115,105,100,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,111,32,119,104,105,99,104,32,105,116,32,114,101,102,101,114,115,32,102,97,105,108,115,32,119,104,101,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,102,105,114,115,116,32,117,115,101,100,44,32,115,111,44,32,102,111,114,32,101,120,97,109,112,108,101,44,32,40,97,92,49,41,32,110,101,118,101,114,32,109,97,116,99,104,101,115,46,32,72,111,119,101,118,101,114,44,32,115,117,99,104,32,114,101,102,101,114,101,110,99,101,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,32,105,110,115,105,100,101,32,114,101,112,101,97,116,101,100,32,115,117,98,112,97,116,116,101,114,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,34,97,34,115,32,97,110,100,32,97,108,115,111,32,34,97,98,97,34,44,32,34,97,98,97,98,98,97,97,34,44,32,97,110,100,32,115,111,32,111,110,58>>]},{pre,[],[{code,[],[<<40,97,124,98,92,49,41,43>>]}]},{p,[],[<<65,116,32,101,97,99,104,32,105,116,101,114,97,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,44,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,109,97,116,99,104,101,115,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,115,116,114,105,110,103,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,112,114,101,118,105,111,117,115,32,105,116,101,114,97,116,105,111,110,46,32,73,110,32,111,114,100,101,114,32,102,111,114,32,116,104,105,115,32,116,111,32,119,111,114,107,44,32,116,104,101,32,112,97,116,116,101,114,110,32,109,117,115,116,32,98,101,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,102,105,114,115,116,32,105,116,101,114,97,116,105,111,110,32,100,111,101,115,32,110,111,116,32,110,101,101,100,32,116,111,32,109,97,116,99,104,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,46,32,84,104,105,115,32,99,97,110,32,98,101,32,100,111,110,101,32,117,115,105,110,103,32,97,108,116,101,114,110,97,116,105,111,110,44,32,97,115,32,105,110,32,116,104,101,32,101,120,97,109,112,108,101,32,97,98,111,118,101,44,32,111,114,32,98,121,32,97,32,113,117,97,110,116,105,102,105,101,114,32,119,105,116,104,32,97,32,109,105,110,105,109,117,109,32,111,102,32,122,101,114,111,46>>]},{p,[],[<<66,97,99,107,32,114,101,102,101,114,101,110,99,101,115,32,111,102,32,116,104,105,115,32,116,121,112,101,32,99,97,117,115,101,32,116,104,101,32,103,114,111,117,112,32,116,104,97,116,32,116,104,101,121,32,114,101,102,101,114,101,110,99,101,32,116,111,32,98,101,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,79,110,99,101,32,116,104,101,32,119,104,111,108,101,32,103,114,111,117,112,32,104,97,115,32,98,101,101,110,32,109,97,116,99,104,101,100,44,32,97,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,99,97,110,110,111,116,32,99,97,117,115,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,116,104,101,32,109,105,100,100,108,101,32,111,102,32,116,104,101,32,103,114,111,117,112,46>>]},{a,[{id,<<115,101,99,116,49,55>>}],[]},{h2,[],[<<65,115,115,101,114,116,105,111,110,115>>]},{p,[],[<<65,110,32,97,115,115,101,114,116,105,111,110,32,105,115,32,97,32,116,101,115,116,32,111,110,32,116,104,101,32,99,104,97,114,97,99,116,101,114,115,32,102,111,108,108,111,119,105,110,103,32,111,114,32,112,114,101,99,101,100,105,110,103,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,99,111,110,115,117,109,101,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,115,105,109,112,108,101,32,97,115,115,101,114,116,105,111,110,115,32,99,111,100,101,100,32,97,115,32,92,98,44,32,92,66,44,32,92,65,44,32,92,71,44,32,92,90,44,32,92,122,44,32,94,44,32,97,110,100,32,36,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,115,101,99,116,105,111,110,115,46>>]},{p,[],[<<77,111,114,101,32,99,111,109,112,108,105,99,97,116,101,100,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,32,99,111,100,101,100,32,97,115,32,115,117,98,112,97,116,116,101,114,110,115,46,32,84,104,101,114,101,32,97,114,101,32,116,119,111,32,107,105,110,100,115,58,32,116,104,111,115,101,32,116,104,97,116,32,108,111,111,107,32,97,104,101,97,100,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,110,100,32,116,104,111,115,101,32,116,104,97,116,32,108,111,111,107,32,98,101,104,105,110,100,32,105,116,46,32,65,110,32,97,115,115,101,114,116,105,111,110,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,109,97,116,99,104,101,100,32,105,110,32,116,104,101,32,110,111,114,109,97,108,32,119,97,121,44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,116,32,100,111,101,115,32,110,111,116,32,99,97,117,115,101,32,116,104,101,32,99,117,114,114,101,110,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,32,116,111,32,98,101,32,99,104,97,110,103,101,100,46>>]},{p,[],[<<65,115,115,101,114,116,105,111,110,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,110,111,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,46,32,73,102,32,115,117,99,104,32,97,110,32,97,115,115,101,114,116,105,111,110,32,99,111,110,116,97,105,110,115,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,119,105,116,104,105,110,32,105,116,44,32,116,104,101,115,101,32,97,114,101,32,99,111,117,110,116,101,100,32,102,111,114,32,116,104,101,32,112,117,114,112,111,115,101,115,32,111,102,32,110,117,109,98,101,114,105,110,103,32,116,104,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,46,32,72,111,119,101,118,101,114,44,32,115,117,98,115,116,114,105,110,103,32,99,97,112,116,117,114,105,110,103,32,105,115,32,100,111,110,101,32,111,110,108,121,32,102,111,114,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,40,80,101,114,108,32,115,111,109,101,116,105,109,101,115,44,32,98,117,116,32,110,111,116,32,97,108,119,97,121,115,44,32,112,101,114,102,111,114,109,115,32,99,97,112,116,117,114,105,110,103,32,105,110,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,41>>]},{'div',[{class,<<119,97,114,110,105,110,103>>}],[{p,[],[<<73,102,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,99,111,110,116,97,105,110,105,110,103,32,111,110,101,32,111,114,32,109,111,114,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,115,117,99,99,101,101,100,115,44,32,98,117,116,32,102,97,105,108,117,114,101,32,116,111,32,109,97,116,99,104,32,108,97,116,101,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,99,97,117,115,101,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,111,118,101,114,32,116,104,105,115,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,99,97,112,116,117,114,101,115,32,119,105,116,104,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,97,114,101,32,114,101,115,101,116,32,111,110,108,121,32,105,102,32,110,111,32,104,105,103,104,101,114,32,110,117,109,98,101,114,101,100,32,99,97,112,116,117,114,101,115,32,97,114,101,32,97,108,114,101,97,100,121,32,115,101,116,46,32,84,104,105,115,32,105,115,44,32,117,110,102,111,114,116,117,110,97,116,101,108,121,44,32,97,32,102,117,110,100,97,109,101,110,116,97,108,32,108,105,109,105,116,97,116,105,111,110,32,111,102,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,44,32,97,110,100,32,97,115,32,80,67,82,69,49,32,105,115,32,110,111,119,32,105,110,32,109,97,105,110,116,101,110,97,110,99,101,45,111,110,108,121,32,115,116,97,116,117,115,44,32,105,116,32,105,115,32,117,110,108,105,107,101,108,121,32,101,118,101,114,32,116,111,32,99,104,97,110,103,101,46>>]}]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,80,101,114,108,44,32,97,115,115,101,114,116,105,111,110,32,115,117,98,112,97,116,116,101,114,110,115,32,99,97,110,32,98,101,32,114,101,112,101,97,116,101,100,46,32,72,111,119,101,118,101,114,44,32,105,116,32,109,97,107,101,115,32,110,111,32,115,101,110,115,101,32,116,111,32,97,115,115,101,114,116,32,116,104,101,32,115,97,109,101,32,116,104,105,110,103,32,109,97,110,121,32,116,105,109,101,115,44,32,116,104,101,32,115,105,100,101,32,101,102,102,101,99,116,32,111,102,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,111,99,99,97,115,105,111,110,97,108,108,121,32,98,101,32,117,115,101,102,117,108,46,32,73,110,32,112,114,97,99,116,105,99,101,44,32,116,104,101,114,101,32,97,114,101,32,111,110,108,121,32,116,104,114,101,101,32,99,97,115,101,115,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,123,48,125,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,105,115,32,110,101,118,101,114,32,111,98,101,121,101,100,32,100,117,114,105,110,103,32,109,97,116,99,104,105,110,103,46,32,72,111,119,101,118,101,114,44,32,105,116,32,99,97,110,32,99,111,110,116,97,105,110,32,105,110,116,101,114,110,97,108,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,103,114,111,117,112,115,32,116,104,97,116,32,97,114,101,32,99,97,108,108,101,100,32,102,114,111,109,32,101,108,115,101,119,104,101,114,101,32,116,104,114,111,117,103,104,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,101,99,104,97,110,105,115,109,46>>]}]},{li,[],[{p,[],[<<73,102,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,123,48,44,110,125,44,32,119,104,101,114,101,32,110,32,62,32,48,44,32,105,116,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,105,102,32,105,116,32,119,97,115,32,123,48,44,49,125,46,32,65,116,32,114,117,110,116,105,109,101,44,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,32,105,115,32,116,114,105,101,100,32,119,105,116,104,32,97,110,100,32,119,105,116,104,111,117,116,32,116,104,101,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,111,114,100,101,114,32,100,101,112,101,110,100,115,32,111,110,32,116,104,101,32,103,114,101,101,100,105,110,101,115,115,32,111,102,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,46>>]}]},{li,[],[{p,[],[<<73,102,32,116,104,101,32,109,105,110,105,109,117,109,32,114,101,112,101,116,105,116,105,111,110,32,105,115,32,62,32,48,44,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,32,97,115,115,101,114,116,105,111,110,32,105,115,32,111,98,101,121,101,100,32,111,110,108,121,32,111,110,99,101,32,119,104,101,110,32,101,110,99,111,117,110,116,101,114,101,100,32,100,117,114,105,110,103,32,109,97,116,99,104,105,110,103,46>>]}]}]},{p,[],[{em,[],[<<76,111,111,107,97,104,101,97,100,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<76,111,111,107,97,104,101,97,100,32,97,115,115,101,114,116,105,111,110,115,32,115,116,97,114,116,32,119,105,116,104,32,40,63,61,32,102,111,114,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,97,110,100,32,40,63,33,32,102,111,114,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,32,119,111,114,100,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,115,101,109,105,99,111,108,111,110,44,32,98,117,116,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,116,104,101,32,115,101,109,105,99,111,108,111,110,32,105,110,32,116,104,101,32,109,97,116,99,104,58>>]},{pre,[],[{code,[],[<<92,119,43,40,63,61,59,41>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,110,121,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,102,111,111,34,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32,34,98,97,114,34,58>>]},{pre,[],[{code,[],[<<102,111,111,40,63,33,98,97,114,41>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,97,112,112,97,114,101,110,116,108,121,32,115,105,109,105,108,97,114,32,112,97,116,116,101,114,110>>]},{pre,[],[{code,[],[<<40,63,33,102,111,111,41,98,97,114>>]}]},{p,[],[<<100,111,101,115,32,110,111,116,32,102,105,110,100,32,97,110,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,114,34,32,116,104,97,116,32,105,115,32,112,114,101,99,101,100,101,100,32,98,121,32,115,111,109,101,116,104,105,110,103,32,111,116,104,101,114,32,116,104,97,110,32,34,102,111,111,34,46,32,73,116,32,102,105,110,100,115,32,97,110,121,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,114,34,32,119,104,97,116,115,111,101,118,101,114,44,32,97,115,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,40,63,33,102,111,111,41,32,105,115,32,97,108,119,97,121,115,32,116,114,117,101,32,119,104,101,110,32,116,104,101,32,110,101,120,116,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,34,98,97,114,34,46,32,65,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,105,115,32,110,101,101,100,101,100,32,116,111,32,97,99,104,105,101,118,101,32,116,104,101,32,111,116,104,101,114,32,101,102,102,101,99,116,46>>]},{p,[],[<<73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,102,111,114,99,101,32,97,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,97,116,32,115,111,109,101,32,112,111,105,110,116,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,116,104,101,32,109,111,115,116,32,99,111,110,118,101,110,105,101,110,116,32,119,97,121,32,116,111,32,100,111,32,105,116,32,105,115,32,119,105,116,104,32,40,63,33,41,44,32,97,115,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,46,32,83,111,44,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,114,101,113,117,105,114,101,115,32,116,104,101,114,101,32,105,115,32,110,111,116,32,116,111,32,98,101,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,109,117,115,116,32,97,108,119,97,121,115,32,102,97,105,108,46,32,84,104,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,111,110,116,114,111,108,32,118,101,114,98,32,40,42,70,65,73,76,41,32,111,114,32,40,42,70,41,32,105,115,32,97,32,115,121,110,111,110,121,109,32,102,111,114,32,40,63,33,41,46>>]},{p,[],[{em,[],[<<76,111,111,107,98,101,104,105,110,100,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<76,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,115,116,97,114,116,32,119,105,116,104,32,40,63,60,61,32,102,111,114,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,97,110,100,32,40,63,60,33,32,102,111,114,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,110,100,115,32,97,110,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,114,34,32,116,104,97,116,32,105,115,32,110,111,116,32,112,114,101,99,101,100,101,100,32,98,121,32,34,102,111,111,34,58>>]},{pre,[],[{code,[],[<<40,63,60,33,102,111,111,41,98,97,114>>]}]},{p,[],[<<84,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,97,114,101,32,114,101,115,116,114,105,99,116,101,100,32,115,117,99,104,32,116,104,97,116,32,97,108,108,32,116,104,101,32,115,116,114,105,110,103,115,32,105,116,32,109,97,116,99,104,101,115,32,109,117,115,116,32,104,97,118,101,32,97,32,102,105,120,101,100,32,108,101,110,103,116,104,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,114,101,32,97,114,101,32,109,97,110,121,32,116,111,112,45,108,101,118,101,108,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,116,104,101,121,32,100,111,32,110,111,116,32,97,108,108,32,104,97,118,101,32,116,111,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,102,105,120,101,100,32,108,101,110,103,116,104,46,32,84,104,117,115,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,112,101,114,109,105,116,116,101,100,58>>]},{pre,[],[{code,[],[<<40,63,60,61,98,117,108,108,111,99,107,124,100,111,110,107,101,121,41>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,117,115,101,115,32,97,110,32,101,114,114,111,114,32,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,58>>]},{pre,[],[{code,[],[<<40,63,60,33,100,111,103,115,63,124,99,97,116,115,63,41>>]}]},{p,[],[<<66,114,97,110,99,104,101,115,32,116,104,97,116,32,109,97,116,99,104,32,100,105,102,102,101,114,101,110,116,32,108,101,110,103,116,104,32,115,116,114,105,110,103,115,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,111,110,108,121,32,97,116,32,116,104,101,32,116,111,112,45,108,101,118,101,108,32,111,102,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,46,32,84,104,105,115,32,105,115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,99,111,109,112,97,114,101,100,32,119,105,116,104,32,80,101,114,108,44,32,119,104,105,99,104,32,114,101,113,117,105,114,101,115,32,97,108,108,32,98,114,97,110,99,104,101,115,32,116,111,32,109,97,116,99,104,32,116,104,101,32,115,97,109,101,32,108,101,110,103,116,104,32,111,102,32,115,116,114,105,110,103,46,32,65,110,32,97,115,115,101,114,116,105,111,110,32,115,117,99,104,32,97,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,105,115,32,110,111,116,32,112,101,114,109,105,116,116,101,100,44,32,97,115,32,105,116,115,32,115,105,110,103,108,101,32,116,111,112,45,108,101,118,101,108,32,98,114,97,110,99,104,32,99,97,110,32,109,97,116,99,104,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,108,101,110,103,116,104,115,58>>]},{pre,[],[{code,[],[<<40,63,60,61,97,98,40,99,124,100,101,41,41>>]}]},{p,[],[<<72,111,119,101,118,101,114,44,32,105,116,32,105,115,32,97,99,99,101,112,116,97,98,108,101,32,116,111,32,80,67,82,69,32,105,102,32,114,101,119,114,105,116,116,101,110,32,116,111,32,117,115,101,32,116,119,111,32,116,111,112,45,108,101,118,101,108,32,98,114,97,110,99,104,101,115,58>>]},{pre,[],[{code,[],[<<40,63,60,61,97,98,99,124,97,98,100,101,41>>]}]},{p,[],[<<83,111,109,101,116,105,109,101,115,32,116,104,101,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,32,92,75,32,40,115,101,101,32,97,98,111,118,101,41,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,111,102,32,97,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,116,111,32,103,101,116,32,114,111,117,110,100,32,116,104,101,32,102,105,120,101,100,45,108,101,110,103,116,104,32,114,101,115,116,114,105,99,116,105,111,110,46>>]},{p,[],[<<84,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,105,115,44,32,102,111,114,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,44,32,116,111,32,109,111,118,101,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,98,97,99,107,32,116,101,109,112,111,114,97,114,105,108,121,32,98,121,32,116,104,101,32,102,105,120,101,100,32,108,101,110,103,116,104,32,97,110,100,32,116,104,101,110,32,116,114,121,32,116,111,32,109,97,116,99,104,46,32,73,102,32,116,104,101,114,101,32,97,114,101,32,105,110,115,117,102,102,105,99,105,101,110,116,32,99,104,97,114,97,99,116,101,114,115,32,98,101,102,111,114,101,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,102,97,105,108,115,46>>]},{p,[],[<<73,110,32,97,32,85,84,70,32,109,111,100,101,44,32,80,67,82,69,32,100,111,101,115,32,110,111,116,32,97,108,108,111,119,32,116,104,101,32,92,67,32,101,115,99,97,112,101,32,40,119,104,105,99,104,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,100,97,116,97,32,117,110,105,116,32,101,118,101,110,32,105,110,32,97,32,85,84,70,32,109,111,100,101,41,32,116,111,32,97,112,112,101,97,114,32,105,110,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,44,32,97,115,32,105,116,32,109,97,107,101,115,32,105,116,32,105,109,112,111,115,115,105,98,108,101,32,116,111,32,99,97,108,99,117,108,97,116,101,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,108,111,111,107,98,101,104,105,110,100,46,32,84,104,101,32,92,88,32,97,110,100,32,92,82,32,101,115,99,97,112,101,115,44,32,119,104,105,99,104,32,99,97,110,32,109,97,116,99,104,32,100,105,102,102,101,114,101,110,116,32,110,117,109,98,101,114,115,32,111,102,32,100,97,116,97,32,117,110,105,116,115,44,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,32,101,105,116,104,101,114,46>>]},{p,[],[<<34,83,117,98,114,111,117,116,105,110,101,34,32,99,97,108,108,115,32,40,115,101,101,32,98,101,108,111,119,41,44,32,115,117,99,104,32,97,115,32,40,63,50,41,32,111,114,32,40,63,38,88,41,44,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,105,110,32,108,111,111,107,98,101,104,105,110,100,115,44,32,97,115,32,108,111,110,103,32,97,115,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,32,102,105,120,101,100,45,108,101,110,103,116,104,32,115,116,114,105,110,103,46,32,82,101,99,117,114,115,105,111,110,44,32,104,111,119,101,118,101,114,44,32,105,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,46>>]},{p,[],[<<80,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,115,32,99,97,110,32,98,101,32,117,115,101,100,32,119,105,116,104,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,115,32,116,111,32,115,112,101,99,105,102,121,32,101,102,102,105,99,105,101,110,116,32,109,97,116,99,104,105,110,103,32,111,102,32,102,105,120,101,100,45,108,101,110,103,116,104,32,115,116,114,105,110,103,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,105,109,112,108,101,32,112,97,116,116,101,114,110,32,119,104,101,110,32,97,112,112,108,105,101,100,32,116,111,32,97,32,108,111,110,103,32,115,116,114,105,110,103,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,58>>]},{pre,[],[{code,[],[<<97,98,99,100,36>>]}]},{p,[],[<<65,115,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,101,100,115,32,102,114,111,109,32,108,101,102,116,32,116,111,32,114,105,103,104,116,44,32,80,67,82,69,32,108,111,111,107,115,32,102,111,114,32,101,97,99,104,32,34,97,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,97,110,100,32,116,104,101,110,32,115,101,101,115,32,105,102,32,119,104,97,116,32,102,111,108,108,111,119,115,32,109,97,116,99,104,101,115,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115>>]},{pre,[],[{code,[],[<<94,46,42,97,98,99,100,36>>]}]},{p,[],[<<116,104,101,32,105,110,105,116,105,97,108,32,46,42,32,109,97,116,99,104,101,115,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,32,97,116,32,102,105,114,115,116,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,116,104,105,115,32,102,97,105,108,115,32,40,97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,102,111,108,108,111,119,105,110,103,32,34,97,34,41,44,32,105,116,32,98,97,99,107,116,114,97,99,107,115,32,116,111,32,109,97,116,99,104,32,97,108,108,32,98,117,116,32,116,104,101,32,108,97,115,116,32,99,104,97,114,97,99,116,101,114,44,32,116,104,101,110,32,97,108,108,32,98,117,116,32,116,104,101,32,108,97,115,116,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,44,32,97,110,100,32,115,111,32,111,110,46,32,79,110,99,101,32,97,103,97,105,110,32,116,104,101,32,115,101,97,114,99,104,32,102,111,114,32,34,97,34,32,99,111,118,101,114,115,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,44,32,102,114,111,109,32,114,105,103,104,116,32,116,111,32,108,101,102,116,44,32,115,111,32,119,101,32,97,114,101,32,110,111,32,98,101,116,116,101,114,32,111,102,102,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,119,114,105,116,116,101,110,32,97,115>>]},{pre,[],[{code,[],[<<94,46,42,43,40,63,60,61,97,98,99,100,41>>]}]},{p,[],[<<116,104,101,114,101,32,99,97,110,32,98,101,32,110,111,32,98,97,99,107,116,114,97,99,107,105,110,103,32,102,111,114,32,116,104,101,32,46,42,43,32,105,116,101,109,59,32,105,116,32,99,97,110,32,109,97,116,99,104,32,111,110,108,121,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,46,32,84,104,101,32,115,117,98,115,101,113,117,101,110,116,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,32,100,111,101,115,32,97,32,115,105,110,103,108,101,32,116,101,115,116,32,111,110,32,116,104,101,32,108,97,115,116,32,102,111,117,114,32,99,104,97,114,97,99,116,101,114,115,46,32,73,102,32,105,116,32,102,97,105,108,115,44,32,116,104,101,32,109,97,116,99,104,32,102,97,105,108,115,32,105,109,109,101,100,105,97,116,101,108,121,46,32,70,111,114,32,108,111,110,103,32,115,116,114,105,110,103,115,44,32,116,104,105,115,32,97,112,112,114,111,97,99,104,32,109,97,107,101,115,32,97,32,115,105,103,110,105,102,105,99,97,110,116,32,100,105,102,102,101,114,101,110,99,101,32,116,111,32,116,104,101,32,112,114,111,99,101,115,115,105,110,103,32,116,105,109,101,46>>]},{p,[],[{em,[],[<<85,115,105,110,103,32,77,117,108,116,105,112,108,101,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<77,97,110,121,32,97,115,115,101,114,116,105,111,110,115,32,40,111,102,32,97,110,121,32,115,111,114,116,41,32,99,97,110,32,111,99,99,117,114,32,105,110,32,115,117,99,99,101,115,115,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,102,111,111,34,32,112,114,101,99,101,100,101,100,32,98,121,32,116,104,114,101,101,32,100,105,103,105,116,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,34,57,57,57,34,58>>]},{pre,[],[{code,[],[<<40,63,60,61,92,100,123,51,125,41,40,63,60,33,57,57,57,41,102,111,111>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,101,97,99,104,32,111,102,32,116,104,101,32,97,115,115,101,114,116,105,111,110,115,32,105,115,32,97,112,112,108,105,101,100,32,105,110,100,101,112,101,110,100,101,110,116,108,121,32,97,116,32,116,104,101,32,115,97,109,101,32,112,111,105,110,116,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,70,105,114,115,116,32,116,104,101,114,101,32,105,115,32,97,32,99,104,101,99,107,32,116,104,97,116,32,116,104,101,32,112,114,101,118,105,111,117,115,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,97,108,108,32,100,105,103,105,116,115,44,32,97,110,100,32,116,104,101,110,32,116,104,101,114,101,32,105,115,32,97,32,99,104,101,99,107,32,116,104,97,116,32,116,104,101,32,115,97,109,101,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,110,111,116,32,34,57,57,57,34,46,32,84,104,105,115,32,112,97,116,116,101,114,110,32,100,111,101,115,32>>,{em,[],[<<110,111,116>>]},<<32,109,97,116,99,104,32,34,102,111,111,34,32,112,114,101,99,101,100,101,100,32,98,121,32,115,105,120,32,99,104,97,114,97,99,116,101,114,115,44,32,116,104,101,32,102,105,114,115,116,32,111,102,32,119,104,105,99,104,32,97,114,101,32,100,105,103,105,116,115,32,97,110,100,32,116,104,101,32,108,97,115,116,32,116,104,114,101,101,32,111,102,32,119,104,105,99,104,32,97,114,101,32,110,111,116,32,34,57,57,57,34,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,34,49,50,51,97,98,99,102,111,111,34,46,32,65,32,112,97,116,116,101,114,110,32,116,111,32,100,111,32,116,104,97,116,32,105,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{pre,[],[{code,[],[<<40,63,60,61,92,100,123,51,125,46,46,46,41,40,63,60,33,57,57,57,41,102,111,111>>]}]},{p,[],[<<84,104,105,115,32,116,105,109,101,32,116,104,101,32,102,105,114,115,116,32,97,115,115,101,114,116,105,111,110,32,108,111,111,107,115,32,97,116,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,115,105,120,32,99,104,97,114,97,99,116,101,114,115,44,32,99,104,101,99,107,115,32,116,104,97,116,32,116,104,101,32,102,105,114,115,116,32,116,104,114,101,101,32,97,114,101,32,100,105,103,105,116,115,44,32,97,110,100,32,116,104,101,110,32,116,104,101,32,115,101,99,111,110,100,32,97,115,115,101,114,116,105,111,110,32,99,104,101,99,107,115,32,116,104,97,116,32,116,104,101,32,112,114,101,99,101,100,105,110,103,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,110,111,116,32,34,57,57,57,34,46>>]},{p,[],[<<65,115,115,101,114,116,105,111,110,115,32,99,97,110,32,98,101,32,110,101,115,116,101,100,32,105,110,32,97,110,121,32,99,111,109,98,105,110,97,116,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,97,110,32,111,99,99,117,114,114,101,110,99,101,32,111,102,32,34,98,97,122,34,32,116,104,97,116,32,105,115,32,112,114,101,99,101,100,101,100,32,98,121,32,34,98,97,114,34,44,32,119,104,105,99,104,32,105,110,32,116,117,114,110,32,105,115,32,110,111,116,32,112,114,101,99,101,100,101,100,32,98,121,32,34,102,111,111,34,58>>]},{pre,[],[{code,[],[<<40,63,60,61,40,63,60,33,102,111,111,41,98,97,114,41,98,97,122>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,102,111,111,34,32,112,114,101,99,101,100,101,100,32,98,121,32,116,104,114,101,101,32,100,105,103,105,116,115,32,97,110,100,32,97,110,121,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,34,57,57,57,34,58>>]},{pre,[],[{code,[],[<<40,63,60,61,92,100,123,51,125,40,63,33,57,57,57,41,46,46,46,41,102,111,111>>]}]},{a,[{id,<<115,101,99,116,49,56>>}],[]},{h2,[],[<<67,111,110,100,105,116,105,111,110,97,108,32,83,117,98,112,97,116,116,101,114,110,115>>]},{p,[],[<<73,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,99,97,117,115,101,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,115,115,32,116,111,32,111,98,101,121,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,111,110,100,105,116,105,111,110,97,108,108,121,32,111,114,32,116,111,32,99,104,111,111,115,101,32,98,101,116,119,101,101,110,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,32,115,117,98,112,97,116,116,101,114,110,115,44,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,110,32,97,115,115,101,114,116,105,111,110,44,32,111,114,32,119,104,101,116,104,101,114,32,97,32,115,112,101,99,105,102,105,99,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,97,108,114,101,97,100,121,32,98,101,101,110,32,109,97,116,99,104,101,100,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,116,119,111,32,112,111,115,115,105,98,108,101,32,102,111,114,109,115,32,111,102,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,63,40,99,111,110,100,105,116,105,111,110,41,121,101,115,45,112,97,116,116,101,114,110,41,10,40,63,40,99,111,110,100,105,116,105,111,110,41,121,101,115,45,112,97,116,116,101,114,110,124,110,111,45,112,97,116,116,101,114,110,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,115,97,116,105,115,102,105,101,100,44,32,116,104,101,32,121,101,115,45,112,97,116,116,101,114,110,32,105,115,32,117,115,101,100,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,110,111,45,112,97,116,116,101,114,110,32,40,105,102,32,112,114,101,115,101,110,116,41,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,101,120,105,115,116,32,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,44,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,32,111,99,99,117,114,115,46,32,69,97,99,104,32,111,102,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,99,97,110,32,105,116,115,101,108,102,32,99,111,110,116,97,105,110,32,110,101,115,116,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,97,110,121,32,102,111,114,109,44,32,105,110,99,108,117,100,105,110,103,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,115,59,32,116,104,101,32,114,101,115,116,114,105,99,116,105,111,110,32,116,111,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,112,112,108,105,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,108,101,118,101,108,32,111,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,102,114,97,103,109,101,110,116,32,105,115,32,97,110,32,101,120,97,109,112,108,101,32,119,104,101,114,101,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,114,101,32,99,111,109,112,108,101,120,58>>]},{pre,[],[{code,[],[<<40,63,40,49,41,32,40,65,124,66,124,67,41,32,124,32,40,68,32,124,32,40,63,40,50,41,69,124,70,41,32,124,32,69,41,32,41>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,102,111,117,114,32,107,105,110,100,115,32,111,102,32,99,111,110,100,105,116,105,111,110,58,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,115,117,98,112,97,116,116,101,114,110,115,44,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,114,101,99,117,114,115,105,111,110,44,32,97,32,112,115,101,117,100,111,45,99,111,110,100,105,116,105,111,110,32,99,97,108,108,101,100,32,68,69,70,73,78,69,44,32,97,110,100,32,97,115,115,101,114,116,105,111,110,115,46>>]},{p,[],[{em,[],[<<67,104,101,99,107,105,110,103,32,102,111,114,32,97,32,85,115,101,100,32,83,117,98,112,97,116,116,101,114,110,32,66,121,32,78,117,109,98,101,114>>]}]},{p,[],[<<73,102,32,116,104,101,32,116,101,120,116,32,98,101,116,119,101,101,110,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,99,111,110,115,105,115,116,115,32,111,102,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,100,105,103,105,116,115,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,111,102,32,116,104,97,116,32,110,117,109,98,101,114,32,104,97,115,32,112,114,101,118,105,111,117,115,108,121,32,109,97,116,99,104,101,100,46,32,73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,32,101,120,105,115,116,115,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,115,101,99,116,49,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<68,117,112,108,105,99,97,116,101,32,83,117,98,112,97,116,116,101,114,110,32,78,117,109,98,101,114,115>>]},<<32,101,97,114,108,105,101,114,41,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,102,32,116,104,101,109,32,104,97,118,101,32,109,97,116,99,104,101,100,46,32,65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,110,111,116,97,116,105,111,110,32,105,115,32,116,111,32,112,114,101,99,101,100,101,32,116,104,101,32,100,105,103,105,116,115,32,119,105,116,104,32,97,32,112,108,117,115,32,111,114,32,109,105,110,117,115,32,115,105,103,110,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,110,117,109,98,101,114,32,105,115,32,114,101,108,97,116,105,118,101,32,114,97,116,104,101,114,32,116,104,97,110,32,97,98,115,111,108,117,116,101,46,32,84,104,101,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,111,112,101,110,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,32,98,121,32,40,63,40,45,49,41,44,32,116,104,101,32,110,101,120,116,32,109,111,115,116,32,114,101,99,101,110,116,32,98,121,32,40,63,40,45,50,41,44,32,97,110,100,32,115,111,32,111,110,46,32,73,110,115,105,100,101,32,108,111,111,112,115,44,32,105,116,32,99,97,110,32,97,108,115,111,32,109,97,107,101,32,115,101,110,115,101,32,116,111,32,114,101,102,101,114,32,116,111,32,115,117,98,115,101,113,117,101,110,116,32,103,114,111,117,112,115,46,32,84,104,101,32,110,101,120,116,32,112,97,114,101,110,116,104,101,115,101,115,32,116,111,32,98,101,32,111,112,101,110,101,100,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,32,97,115,32,40,63,40,43,49,41,44,32,97,110,100,32,115,111,32,111,110,46,32,40,84,104,101,32,118,97,108,117,101,32,122,101,114,111,32,105,110,32,97,110,121,32,111,102,32,116,104,101,115,101,32,102,111,114,109,115,32,105,115,32,110,111,116,32,117,115,101,100,59,32,105,116,32,112,114,111,118,111,107,101,115,32,97,32,99,111,109,112,105,108,101,45,116,105,109,101,32,101,114,114,111,114,46,41>>]},{p,[],[<<67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,99,111,110,116,97,105,110,115,32,110,111,110,45,115,105,103,110,105,102,105,99,97,110,116,32,119,104,105,116,101,115,112,97,99,101,32,116,111,32,109,97,107,101,32,105,116,32,109,111,114,101,32,114,101,97,100,97,98,108,101,32,40,97,115,115,117,109,101,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<41,32,97,110,100,32,116,111,32,100,105,118,105,100,101,32,105,116,32,105,110,116,111,32,116,104,114,101,101,32,112,97,114,116,115,32,102,111,114,32,101,97,115,101,32,111,102,32,100,105,115,99,117,115,115,105,111,110,58>>]},{pre,[],[{code,[],[<<40,32,92,40,32,41,63,32,32,32,32,91,94,40,41,93,43,32,32,32,32,40,63,40,49,41,32,92,41,32,41>>]}]},{p,[],[<<84,104,101,32,102,105,114,115,116,32,112,97,114,116,32,109,97,116,99,104,101,115,32,97,110,32,111,112,116,105,111,110,97,108,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,44,32,97,110,100,32,105,102,32,116,104,97,116,32,99,104,97,114,97,99,116,101,114,32,105,115,32,112,114,101,115,101,110,116,44,32,115,101,116,115,32,105,116,32,97,115,32,116,104,101,32,102,105,114,115,116,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,46,32,84,104,101,32,115,101,99,111,110,100,32,112,97,114,116,32,109,97,116,99,104,101,115,32,111,110,101,32,111,114,32,109,111,114,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,112,97,114,101,110,116,104,101,115,101,115,46,32,84,104,101,32,116,104,105,114,100,32,112,97,114,116,32,105,115,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,116,101,115,116,115,32,119,104,101,116,104,101,114,32,116,104,101,32,102,105,114,115,116,32,115,101,116,32,111,102,32,112,97,114,101,110,116,104,101,115,101,115,32,109,97,116,99,104,101,100,32,111,114,32,110,111,116,46,32,73,102,32,116,104,101,121,32,100,105,100,44,32,116,104,97,116,32,105,115,44,32,105,102,32,115,117,98,106,101,99,116,32,115,116,97,114,116,101,100,32,119,105,116,104,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,44,32,97,110,100,32,115,111,32,116,104,101,32,121,101,115,45,112,97,116,116,101,114,110,32,105,115,32,101,120,101,99,117,116,101,100,32,97,110,100,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,115,32,114,101,113,117,105,114,101,100,46,32,79,116,104,101,114,119,105,115,101,44,32,97,115,32,110,111,45,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,44,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,110,111,116,104,105,110,103,46,32,84,104,97,116,32,105,115,44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,44,32,111,112,116,105,111,110,97,108,108,121,32,101,110,99,108,111,115,101,100,32,105,110,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<73,102,32,116,104,105,115,32,112,97,116,116,101,114,110,32,105,115,32,101,109,98,101,100,100,101,100,32,105,110,32,97,32,108,97,114,103,101,114,32,111,110,101,44,32,97,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,117,115,101,100,58>>]},{pre,[],[{code,[],[<<46,46,46,111,116,104,101,114,32,115,116,117,102,102,46,46,46,32,40,32,92,40,32,41,63,32,32,32,32,91,94,40,41,93,43,32,32,32,32,40,63,40,45,49,41,32,92,41,32,41,32,46,46,46>>]}]},{p,[],[<<84,104,105,115,32,109,97,107,101,115,32,116,104,101,32,102,114,97,103,109,101,110,116,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,108,97,114,103,101,114,32,112,97,116,116,101,114,110,46>>]},{p,[],[{em,[],[<<67,104,101,99,107,105,110,103,32,102,111,114,32,97,32,85,115,101,100,32,83,117,98,112,97,116,116,101,114,110,32,66,121,32,78,97,109,101>>]}]},{p,[],[<<80,101,114,108,32,117,115,101,115,32,116,104,101,32,115,121,110,116,97,120,32,40,63,40,60,110,97,109,101,62,41,46,46,46,41,32,111,114,32,40,63,40,39,110,97,109,101,39,41,46,46,46,41,32,116,111,32,116,101,115,116,32,102,111,114,32,97,32,117,115,101,100,32,115,117,98,112,97,116,116,101,114,110,32,98,121,32,110,97,109,101,46,32,70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,101,97,114,108,105,101,114,32,118,101,114,115,105,111,110,115,32,111,102,32,80,67,82,69,44,32,119,104,105,99,104,32,104,97,100,32,116,104,105,115,32,102,97,99,105,108,105,116,121,32,98,101,102,111,114,101,32,80,101,114,108,44,32,116,104,101,32,115,121,110,116,97,120,32,40,63,40,110,97,109,101,41,46,46,46,41,32,105,115,32,97,108,115,111,32,114,101,99,111,103,110,105,122,101,100,46>>]},{p,[],[<<82,101,119,114,105,116,105,110,103,32,116,104,101,32,112,114,101,118,105,111,117,115,32,101,120,97,109,112,108,101,32,116,111,32,117,115,101,32,97,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,32,103,105,118,101,115,58>>]},{pre,[],[{code,[],[<<40,63,60,79,80,69,78,62,32,92,40,32,41,63,32,32,32,32,91,94,40,41,93,43,32,32,32,32,40,63,40,60,79,80,69,78,62,41,32,92,41,32,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,110,97,109,101,32,117,115,101,100,32,105,110,32,97,32,99,111,110,100,105,116,105,111,110,32,111,102,32,116,104,105,115,32,107,105,110,100,32,105,115,32,97,32,100,117,112,108,105,99,97,116,101,44,32,116,104,101,32,116,101,115,116,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,97,108,108,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,116,104,101,32,115,97,109,101,32,110,97,109,101,44,32,97,110,100,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,110,101,32,111,102,32,116,104,101,109,32,104,97,115,32,109,97,116,99,104,101,100,46>>]},{p,[],[{em,[],[<<67,104,101,99,107,105,110,103,32,102,111,114,32,80,97,116,116,101,114,110,32,82,101,99,117,114,115,105,111,110>>]}]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,104,101,32,115,116,114,105,110,103,32,40,82,41,44,32,97,110,100,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,110,97,109,101,32,82,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,97,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,116,111,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,32,111,114,32,97,110,121,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,98,101,101,110,32,109,97,100,101,46,32,73,102,32,100,105,103,105,116,115,32,111,114,32,97,32,110,97,109,101,32,112,114,101,99,101,100,101,100,32,98,121,32,97,109,112,101,114,115,97,110,100,32,102,111,108,108,111,119,32,116,104,101,32,108,101,116,116,101,114,32,82,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,63,40,82,51,41,46,46,46,41,32,111,114,32,40,63,40,82,38,110,97,109,101,41,46,46,46,41>>]}]},{p,[],[<<116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,114,117,101,32,105,102,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,114,101,99,117,114,115,105,111,110,32,105,115,32,105,110,116,111,32,97,32,115,117,98,112,97,116,116,101,114,110,32,119,104,111,115,101,32,110,117,109,98,101,114,32,111,114,32,110,97,109,101,32,105,115,32,103,105,118,101,110,46,32,84,104,105,115,32,99,111,110,100,105,116,105,111,110,32,100,111,101,115,32,110,111,116,32,99,104,101,99,107,32,116,104,101,32,101,110,116,105,114,101,32,114,101,99,117,114,115,105,111,110,32,115,116,97,99,107,46,32,73,102,32,116,104,101,32,110,97,109,101,32,117,115,101,100,32,105,110,32,97,32,99,111,110,100,105,116,105,111,110,32,111,102,32,116,104,105,115,32,107,105,110,100,32,105,115,32,97,32,100,117,112,108,105,99,97,116,101,44,32,116,104,101,32,116,101,115,116,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,97,108,108,32,115,117,98,112,97,116,116,101,114,110,115,32,111,102,32,116,104,101,32,115,97,109,101,32,110,97,109,101,44,32,97,110,100,32,105,115,32,116,114,117,101,32,105,102,32,97,110,121,32,111,110,101,32,111,102,32,116,104,101,109,32,105,115,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,114,101,99,117,114,115,105,111,110,46>>]},{p,[],[<<65,116,32,34,116,111,112,45,108,101,118,101,108,34,44,32,97,108,108,32,116,104,101,115,101,32,114,101,99,117,114,115,105,111,110,32,116,101,115,116,32,99,111,110,100,105,116,105,111,110,115,32,97,114,101,32,102,97,108,115,101,46,32,84,104,101,32,115,121,110,116,97,120,32,102,111,114,32,114,101,99,117,114,115,105,118,101,32,112,97,116,116,101,114,110,115,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46>>]},{p,[],[{em,[],[<<68,101,102,105,110,105,110,103,32,83,117,98,112,97,116,116,101,114,110,115,32,102,111,114,32,85,115,101,32,66,121,32,82,101,102,101,114,101,110,99,101,32,79,110,108,121>>]}]},{a,[{id,<<100,101,102,105,110,105,110,103,95,115,117,98,112,97,116,116,101,114,110,115>>}],[]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,116,104,101,32,115,116,114,105,110,103,32,40,68,69,70,73,78,69,41,44,32,97,110,100,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,110,97,109,101,32,68,69,70,73,78,69,44,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,97,108,119,97,121,115,32,102,97,108,115,101,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,114,101,32,99,97,110,32,98,101,32,111,110,108,121,32,111,110,101,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,46,32,73,116,32,105,115,32,97,108,119,97,121,115,32,115,107,105,112,112,101,100,32,105,102,32,99,111,110,116,114,111,108,32,114,101,97,99,104,101,115,32,116,104,105,115,32,112,111,105,110,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,101,32,105,100,101,97,32,111,102,32,68,69,70,73,78,69,32,105,115,32,116,104,97,116,32,105,116,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,100,101,102,105,110,101,32,34,115,117,98,114,111,117,116,105,110,101,115,34,32,116,104,97,116,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,32,102,114,111,109,32,101,108,115,101,119,104,101,114,101,46,32,40,84,104,101,32,117,115,101,32,111,102,32,115,117,98,114,111,117,116,105,110,101,115,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46,41,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,32,112,97,116,116,101,114,110,32,116,111,32,109,97,116,99,104,32,97,110,32,73,80,118,52,32,97,100,100,114,101,115,115,44,32,115,117,99,104,32,97,115,32,34,49,57,50,46,49,54,56,46,50,51,46,50,52,53,34,44,32,99,97,110,32,98,101,32,119,114,105,116,116,101,110,32,108,105,107,101,32,116,104,105,115,32,40,105,103,110,111,114,101,32,119,104,105,116,101,115,112,97,99,101,32,97,110,100,32,108,105,110,101,32,98,114,101,97,107,115,41,58>>]},{pre,[],[{code,[],[<<40,63,40,68,69,70,73,78,69,41,32,40,63,60,98,121,116,101,62,32,50,91,48,45,52,93,92,100,32,124,32,50,53,91,48,45,53,93,32,124,32,49,92,100,92,100,32,124,32,91,49,45,57,93,63,92,100,41,32,41,32,92,98,32,40,63,38,98,121,116,101,41,32,40,92,46,40,63,38,98,121,116,101,41,41,123,51,125,32,92,98>>]}]},{p,[],[<<84,104,101,32,102,105,114,115,116,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,97,32,68,69,70,73,78,69,32,103,114,111,117,112,32,105,110,115,105,100,101,32,119,104,105,99,104,32,105,115,32,97,32,97,110,111,116,104,101,114,32,103,114,111,117,112,32,110,97,109,101,100,32,34,98,121,116,101,34,32,105,115,32,100,101,102,105,110,101,100,46,32,84,104,105,115,32,109,97,116,99,104,101,115,32,97,110,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109,112,111,110,101,110,116,32,111,102,32,97,110,32,73,80,118,52,32,97,100,100,114,101,115,115,32,40,97,32,110,117,109,98,101,114,32,60,32,50,53,54,41,46,32,87,104,101,110,32,109,97,116,99,104,105,110,103,32,116,97,107,101,115,32,112,108,97,99,101,44,32,116,104,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,115,107,105,112,112,101,100,44,32,97,115,32,68,69,70,73,78,69,32,97,99,116,115,32,108,105,107,101,32,97,32,102,97,108,115,101,32,99,111,110,100,105,116,105,111,110,46,32,84,104,101,32,114,101,109,97,105,110,105,110,103,32,112,97,116,116,101,114,110,32,117,115,101,115,32,114,101,102,101,114,101,110,99,101,115,32,116,111,32,116,104,101,32,110,97,109,101,100,32,103,114,111,117,112,32,116,111,32,109,97,116,99,104,32,116,104,101,32,102,111,117,114,32,100,111,116,45,115,101,112,97,114,97,116,101,100,32,99,111,109,112,111,110,101,110,116,115,32,111,102,32,97,110,32,73,80,118,52,32,97,100,100,114,101,115,115,44,32,105,110,115,105,115,116,105,110,103,32,111,110,32,97,32,119,111,114,100,32,98,111,117,110,100,97,114,121,32,97,116,32,101,97,99,104,32,101,110,100,46>>]},{p,[],[{em,[],[<<65,115,115,101,114,116,105,111,110,32,67,111,110,100,105,116,105,111,110,115>>]}]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,110,111,116,32,105,110,32,97,110,121,32,111,102,32,116,104,101,32,97,98,111,118,101,32,102,111,114,109,97,116,115,44,32,105,116,32,109,117,115,116,32,98,101,32,97,110,32,97,115,115,101,114,116,105,111,110,46,32,84,104,105,115,32,99,97,110,32,98,101,32,97,32,112,111,115,105,116,105,118,101,32,111,114,32,110,101,103,97,116,105,118,101,32,108,111,111,107,97,104,101,97,100,32,111,114,32,108,111,111,107,98,101,104,105,110,100,32,97,115,115,101,114,116,105,111,110,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,99,111,110,116,97,105,110,105,110,103,32,110,111,110,45,115,105,103,110,105,102,105,99,97,110,116,32,119,104,105,116,101,115,112,97,99,101,44,32,97,110,100,32,119,105,116,104,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,111,110,32,116,104,101,32,115,101,99,111,110,100,32,108,105,110,101,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<40,63,40,63,61,91,94,97,45,122,93,42,91,97,45,122,93,41,10,92,100,123,50,125,45,91,97,45,122,93,123,51,125,45,92,100,123,50,125,32,32,124,32,32,92,100,123,50,125,45,92,100,123,50,125,45,92,100,123,50,125,32,41>>]}]},{p,[],[<<84,104,101,32,99,111,110,100,105,116,105,111,110,32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,108,111,111,107,97,104,101,97,100,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,97,110,32,111,112,116,105,111,110,97,108,32,115,101,113,117,101,110,99,101,32,111,102,32,110,111,110,45,108,101,116,116,101,114,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,108,101,116,116,101,114,46,32,84,104,97,116,32,105,115,44,32,105,116,32,116,101,115,116,115,32,102,111,114,32,116,104,101,32,112,114,101,115,101,110,99,101,32,111,102,32,97,116,32,108,101,97,115,116,32,111,110,101,32,108,101,116,116,101,114,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,73,102,32,97,32,108,101,116,116,101,114,32,105,115,32,102,111,117,110,100,44,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,105,114,115,116,32,97,108,116,101,114,110,97,116,105,118,101,44,32,111,116,104,101,114,119,105,115,101,32,105,116,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,115,101,99,111,110,100,46,32,84,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,115,116,114,105,110,103,115,32,105,110,32,111,110,101,32,111,102,32,116,104,101,32,116,119,111,32,102,111,114,109,115,32,100,100,45,97,97,97,45,100,100,32,111,114,32,100,100,45,100,100,45,100,100,44,32,119,104,101,114,101,32,97,97,97,32,97,114,101,32,108,101,116,116,101,114,115,32,97,110,100,32,100,100,32,97,114,101,32,100,105,103,105,116,115,46>>]},{a,[{id,<<115,101,99,116,49,57>>}],[]},{h2,[],[<<67,111,109,109,101,110,116,115>>]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,116,119,111,32,119,97,121,115,32,116,111,32,105,110,99,108,117,100,101,32,99,111,109,109,101,110,116,115,32,105,110,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,112,114,111,99,101,115,115,101,100,32,98,121,32,80,67,82,69,46,32,73,110,32,98,111,116,104,32,99,97,115,101,115,44,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,99,111,109,109,101,110,116,32,109,117,115,116,32,110,111,116,32,98,101,32,105,110,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,44,32,111,114,32,105,110,32,116,104,101,32,109,105,100,100,108,101,32,111,102,32,97,110,121,32,111,116,104,101,114,32,115,101,113,117,101,110,99,101,32,111,102,32,114,101,108,97,116,101,100,32,99,104,97,114,97,99,116,101,114,115,32,115,117,99,104,32,97,115,32,40,63,58,32,111,114,32,97,32,115,117,98,112,97,116,116,101,114,110,32,110,97,109,101,32,111,114,32,110,117,109,98,101,114,46,32,84,104,101,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,109,97,107,101,32,117,112,32,97,32,99,111,109,109,101,110,116,32,112,108,97,121,32,110,111,32,112,97,114,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,105,110,103,46>>]},{p,[],[<<84,104,101,32,115,101,113,117,101,110,99,101,32,40,63,35,32,109,97,114,107,115,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,99,111,109,109,101,110,116,32,116,104,97,116,32,99,111,110,116,105,110,117,101,115,32,117,112,32,116,111,32,116,104,101,32,110,101,120,116,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,78,101,115,116,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,110,111,116,32,112,101,114,109,105,116,116,101,100,46,32,73,102,32,111,112,116,105,111,110,32,80,67,82,69,95,69,88,84,69,78,68,69,68,32,105,115,32,115,101,116,44,32,97,110,32,117,110,101,115,99,97,112,101,100,32,35,32,99,104,97,114,97,99,116,101,114,32,97,108,115,111,32,105,110,116,114,111,100,117,99,101,115,32,97,32,99,111,109,109,101,110,116,44,32,119,104,105,99,104,32,105,110,32,116,104,105,115,32,99,97,115,101,32,99,111,110,116,105,110,117,101,115,32,116,111,32,105,109,109,101,100,105,97,116,101,108,121,32,97,102,116,101,114,32,116,104,101,32,110,101,120,116,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,32,111,114,32,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,87,104,105,99,104,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,110,101,119,108,105,110,101,115,32,105,115,32,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,32,111,112,116,105,111,110,115,32,112,97,115,115,101,100,32,116,111,32,97,32,99,111,109,112,105,108,105,110,103,32,102,117,110,99,116,105,111,110,32,111,114,32,98,121,32,97,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,110,101,119,108,105,110,101,95,99,111,110,118,101,110,116,105,111,110,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<78,101,119,108,105,110,101,32,67,111,110,118,101,110,116,105,111,110,115>>]},<<32,101,97,114,108,105,101,114,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,105,115,32,116,121,112,101,32,111,102,32,99,111,109,109,101,110,116,32,105,115,32,97,32,108,105,116,101,114,97,108,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,59,32,101,115,99,97,112,101,32,115,101,113,117,101,110,99,101,115,32,116,104,97,116,32,104,97,112,112,101,110,32,116,111,32,114,101,112,114,101,115,101,110,116,32,97,32,110,101,119,108,105,110,101,32,100,111,32,110,111,116,32,99,111,117,110,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,119,104,101,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,105,115,32,115,101,116,44,32,97,110,100,32,116,104,101,32,100,101,102,97,117,108,116,32,110,101,119,108,105,110,101,32,99,111,110,118,101,110,116,105,111,110,32,105,115,32,105,110,32,102,111,114,99,101,58>>]},{pre,[],[{code,[],[<<97,98,99,32,35,99,111,109,109,101,110,116,32,92,110,32,115,116,105,108,108,32,99,111,109,109,101,110,116>>]}]},{p,[],[<<79,110,32,101,110,99,111,117,110,116,101,114,105,110,103,32,99,104,97,114,97,99,116,101,114,32,35,44,32>>,{code,[],[<<112,99,114,101,95,99,111,109,112,105,108,101,40,41>>]},<<32,115,107,105,112,115,32,97,108,111,110,103,44,32,108,111,111,107,105,110,103,32,102,111,114,32,97,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,84,104,101,32,115,101,113,117,101,110,99,101,32,92,110,32,105,115,32,115,116,105,108,108,32,108,105,116,101,114,97,108,32,97,116,32,116,104,105,115,32,115,116,97,103,101,44,32,115,111,32,105,116,32,100,111,101,115,32,110,111,116,32,116,101,114,109,105,110,97,116,101,32,116,104,101,32,99,111,109,109,101,110,116,46,32,79,110,108,121,32,97,32,99,104,97,114,97,99,116,101,114,32,119,105,116,104,32,99,111,100,101,32,118,97,108,117,101,32,48,120,48,97,32,40,116,104,101,32,100,101,102,97,117,108,116,32,110,101,119,108,105,110,101,41,32,100,111,101,115,32,115,111,46>>]},{a,[{id,<<115,101,99,116,50,48>>}],[]},{h2,[],[<<82,101,99,117,114,115,105,118,101,32,80,97,116,116,101,114,110,115>>]},{p,[],[<<67,111,110,115,105,100,101,114,32,116,104,101,32,112,114,111,98,108,101,109,32,111,102,32,109,97,116,99,104,105,110,103,32,97,32,115,116,114,105,110,103,32,105,110,32,112,97,114,101,110,116,104,101,115,101,115,44,32,97,108,108,111,119,105,110,103,32,102,111,114,32,117,110,108,105,109,105,116,101,100,32,110,101,115,116,101,100,32,112,97,114,101,110,116,104,101,115,101,115,46,32,87,105,116,104,111,117,116,32,116,104,101,32,117,115,101,32,111,102,32,114,101,99,117,114,115,105,111,110,44,32,116,104,101,32,98,101,115,116,32,116,104,97,116,32,99,97,110,32,98,101,32,100,111,110,101,32,105,115,32,116,111,32,117,115,101,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,117,112,32,116,111,32,115,111,109,101,32,102,105,120,101,100,32,100,101,112,116,104,32,111,102,32,110,101,115,116,105,110,103,46,32,73,116,32,105,115,32,110,111,116,32,112,111,115,115,105,98,108,101,32,116,111,32,104,97,110,100,108,101,32,97,110,32,97,114,98,105,116,114,97,114,121,32,110,101,115,116,105,110,103,32,100,101,112,116,104,46>>]},{p,[],[<<70,111,114,32,115,111,109,101,32,116,105,109,101,44,32,80,101,114,108,32,104,97,115,32,112,114,111,118,105,100,101,100,32,97,32,102,97,99,105,108,105,116,121,32,116,104,97,116,32,97,108,108,111,119,115,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,115,32,116,111,32,114,101,99,117,114,115,101,32,40,97,109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,41,46,32,73,116,32,100,111,101,115,32,116,104,105,115,32,98,121,32,105,110,116,101,114,112,111,108,97,116,105,110,103,32,80,101,114,108,32,99,111,100,101,32,105,110,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,97,116,32,114,117,110,116,105,109,101,44,32,97,110,100,32,116,104,101,32,99,111,100,101,32,99,97,110,32,114,101,102,101,114,32,116,111,32,116,104,101,32,101,120,112,114,101,115,115,105,111,110,32,105,116,115,101,108,102,46,32,65,32,80,101,114,108,32,112,97,116,116,101,114,110,32,117,115,105,110,103,32,99,111,100,101,32,105,110,116,101,114,112,111,108,97,116,105,111,110,32,116,111,32,115,111,108,118,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,112,114,111,98,108,101,109,32,99,97,110,32,98,101,32,99,114,101,97,116,101,100,32,108,105,107,101,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<36,114,101,32,61,32,113,114,123,92,40,32,40,63,58,32,40,63,62,91,94,40,41,93,43,41,32,124,32,40,63,112,123,36,114,101,125,41,32,41,42,32,92,41,125,120,59>>]}]},{p,[],[<<73,116,101,109,32,40,63,112,123,46,46,46,125,41,32,105,110,116,101,114,112,111,108,97,116,101,115,32,80,101,114,108,32,99,111,100,101,32,97,116,32,114,117,110,116,105,109,101,44,32,97,110,100,32,105,110,32,116,104,105,115,32,99,97,115,101,32,114,101,102,101,114,115,32,114,101,99,117,114,115,105,118,101,108,121,32,116,111,32,116,104,101,32,112,97,116,116,101,114,110,32,105,110,32,119,104,105,99,104,32,105,116,32,97,112,112,101,97,114,115,46>>]},{p,[],[<<79,98,118,105,111,117,115,108,121,44,32,80,67,82,69,32,99,97,110,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,32,105,110,116,101,114,112,111,108,97,116,105,111,110,32,111,102,32,80,101,114,108,32,99,111,100,101,46,32,73,110,115,116,101,97,100,44,32,105,116,32,115,117,112,112,111,114,116,115,32,115,112,101,99,105,97,108,32,115,121,110,116,97,120,32,102,111,114,32,114,101,99,117,114,115,105,111,110,32,111,102,32,116,104,101,32,101,110,116,105,114,101,32,112,97,116,116,101,114,110,44,32,97,110,100,32,102,111,114,32,105,110,100,105,118,105,100,117,97,108,32,115,117,98,112,97,116,116,101,114,110,32,114,101,99,117,114,115,105,111,110,46,32,65,102,116,101,114,32,105,116,115,32,105,110,116,114,111,100,117,99,116,105,111,110,32,105,110,32,80,67,82,69,32,97,110,100,32,80,121,116,104,111,110,44,32,116,104,105,115,32,107,105,110,100,32,111,102,32,114,101,99,117,114,115,105,111,110,32,119,97,115,32,108,97,116,101,114,32,105,110,116,114,111,100,117,99,101,100,32,105,110,116,111,32,80,101,114,108,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,48,46>>]},{p,[],[<<65,32,115,112,101,99,105,97,108,32,105,116,101,109,32,116,104,97,116,32,99,111,110,115,105,115,116,115,32,111,102,32,40,63,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,117,109,98,101,114,32,62,32,48,32,97,110,100,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,115,32,97,32,114,101,99,117,114,115,105,118,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,111,102,32,116,104,101,32,103,105,118,101,110,32,110,117,109,98,101,114,44,32,105,102,32,105,116,32,111,99,99,117,114,115,32,105,110,115,105,100,101,32,116,104,97,116,32,115,117,98,112,97,116,116,101,114,110,46,32,40,73,102,32,110,111,116,44,32,105,116,32,105,115,32,97,32,110,111,110,45,114,101,99,117,114,115,105,118,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,44,32,119,104,105,99,104,32,105,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,46,41,32,84,104,101,32,115,112,101,99,105,97,108,32,105,116,101,109,32,40,63,82,41,32,111,114,32,40,63,48,41,32,105,115,32,97,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,111,102,32,116,104,101,32,101,110,116,105,114,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<84,104,105,115,32,80,67,82,69,32,112,97,116,116,101,114,110,32,115,111,108,118,101,115,32,116,104,101,32,110,101,115,116,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,112,114,111,98,108,101,109,32,40,97,115,115,117,109,101,32,116,104,97,116,32,111,112,116,105,111,110,32>>,{code,[],[<<101,120,116,101,110,100,101,100>>]},<<32,105,115,32,115,101,116,32,115,111,32,116,104,97,116,32,119,104,105,116,101,115,112,97,99,101,32,105,115,32,105,103,110,111,114,101,100,41,58>>]},{pre,[],[{code,[],[<<92,40,32,40,32,91,94,40,41,93,43,43,32,124,32,40,63,82,41,32,41,42,32,92,41>>]}]},{p,[],[<<70,105,114,115,116,32,105,116,32,109,97,116,99,104,101,115,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,84,104,101,110,32,105,116,32,109,97,116,99,104,101,115,32,97,110,121,32,110,117,109,98,101,114,32,111,102,32,115,117,98,115,116,114,105,110,103,115,44,32,119,104,105,99,104,32,99,97,110,32,101,105,116,104,101,114,32,98,101,32,97,32,115,101,113,117,101,110,99,101,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,32,111,114,32,97,32,114,101,99,117,114,115,105,118,101,32,109,97,116,99,104,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,116,115,101,108,102,32,40,116,104,97,116,32,105,115,44,32,97,32,99,111,114,114,101,99,116,108,121,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,115,116,114,105,110,103,41,46,32,70,105,110,97,108,108,121,32,116,104,101,114,101,32,105,115,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,78,111,116,105,99,101,32,116,104,101,32,117,115,101,32,111,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,116,111,32,97,118,111,105,100,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,115,101,113,117,101,110,99,101,115,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<73,102,32,116,104,105,115,32,119,97,115,32,112,97,114,116,32,111,102,32,97,32,108,97,114,103,101,114,32,112,97,116,116,101,114,110,44,32,121,111,117,32,119,111,117,108,100,32,110,111,116,32,119,97,110,116,32,116,111,32,114,101,99,117,114,115,101,32,116,104,101,32,101,110,116,105,114,101,32,112,97,116,116,101,114,110,44,32,115,111,32,105,110,115,116,101,97,100,32,121,111,117,32,99,97,110,32,117,115,101,58>>]},{pre,[],[{code,[],[<<40,32,92,40,32,40,32,91,94,40,41,93,43,43,32,124,32,40,63,49,41,32,41,42,32,92,41,32,41>>]}]},{p,[],[<<84,104,101,32,112,97,116,116,101,114,110,32,105,115,32,104,101,114,101,32,119,105,116,104,105,110,32,112,97,114,101,110,116,104,101,115,101,115,32,115,111,32,116,104,97,116,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,114,101,102,101,114,115,32,116,111,32,116,104,101,109,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<73,110,32,97,32,108,97,114,103,101,114,32,112,97,116,116,101,114,110,44,32,107,101,101,112,105,110,103,32,116,114,97,99,107,32,111,102,32,112,97,114,101,110,116,104,101,115,105,115,32,110,117,109,98,101,114,115,32,99,97,110,32,98,101,32,116,114,105,99,107,121,46,32,84,104,105,115,32,105,115,32,109,97,100,101,32,101,97,115,105,101,114,32,98,121,32,116,104,101,32,117,115,101,32,111,102,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,115,46,32,73,110,115,116,101,97,100,32,111,102,32,40,63,49,41,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,97,98,111,118,101,44,32,121,111,117,32,99,97,110,32,119,114,105,116,101,32,40,63,45,50,41,32,116,111,32,114,101,102,101,114,32,116,111,32,116,104,101,32,115,101,99,111,110,100,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,111,112,101,110,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,112,114,101,99,101,100,105,110,103,32,116,104,101,32,114,101,99,117,114,115,105,111,110,46,32,84,104,97,116,32,105,115,44,32,97,32,110,101,103,97,116,105,118,101,32,110,117,109,98,101,114,32,99,111,117,110,116,115,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,108,101,102,116,119,97,114,100,115,32,102,114,111,109,32,116,104,101,32,112,111,105,110,116,32,97,116,32,119,104,105,99,104,32,105,116,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,46>>]},{p,[],[<<73,116,32,105,115,32,97,108,115,111,32,112,111,115,115,105,98,108,101,32,116,111,32,114,101,102,101,114,32,116,111,32,108,97,116,101,114,32,111,112,101,110,101,100,32,112,97,114,101,110,116,104,101,115,101,115,44,32,98,121,32,119,114,105,116,105,110,103,32,114,101,102,101,114,101,110,99,101,115,32,115,117,99,104,32,97,115,32,40,63,43,50,41,46,32,72,111,119,101,118,101,114,44,32,116,104,101,115,101,32,99,97,110,110,111,116,32,98,101,32,114,101,99,117,114,115,105,118,101,44,32,97,115,32,116,104,101,32,114,101,102,101,114,101,110,99,101,32,105,115,32,110,111,116,32,105,110,115,105,100,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,114,101,102,101,114,101,110,99,101,100,46,32,84,104,101,121,32,97,114,101,32,97,108,119,97,121,115,32,110,111,110,45,114,101,99,117,114,115,105,118,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,115,44,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,46>>]},{p,[],[<<65,110,32,97,108,116,101,114,110,97,116,105,118,101,32,97,112,112,114,111,97,99,104,32,105,115,32,116,111,32,117,115,101,32,110,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,115,116,101,97,100,46,32,84,104,101,32,80,101,114,108,32,115,121,110,116,97,120,32,102,111,114,32,116,104,105,115,32,105,115,32,40,63,38,110,97,109,101,41,46,32,84,104,101,32,101,97,114,108,105,101,114,32,80,67,82,69,32,115,121,110,116,97,120,32,40,63,80,62,110,97,109,101,41,32,105,115,32,97,108,115,111,32,115,117,112,112,111,114,116,101,100,46,32,87,101,32,99,97,110,32,114,101,119,114,105,116,101,32,116,104,101,32,97,98,111,118,101,32,101,120,97,109,112,108,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{pre,[],[{code,[],[<<40,63,60,112,110,62,32,92,40,32,40,32,91,94,40,41,93,43,43,32,124,32,40,63,38,112,110,41,32,41,42,32,92,41,32,41>>]}]},{p,[],[<<73,102,32,116,104,101,114,101,32,105,115,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,110,97,109,101,44,32,116,104,101,32,101,97,114,108,105,101,115,116,32,111,110,101,32,105,115,32,117,115,101,100,46>>]},{p,[],[<<84,104,105,115,32,112,97,114,116,105,99,117,108,97,114,32,101,120,97,109,112,108,101,32,112,97,116,116,101,114,110,32,116,104,97,116,32,119,101,32,104,97,118,101,32,115,116,117,100,105,101,100,32,99,111,110,116,97,105,110,115,32,110,101,115,116,101,100,32,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,115,44,32,97,110,100,32,115,111,32,116,104,101,32,117,115,101,32,111,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,102,111,114,32,109,97,116,99,104,105,110,103,32,115,116,114,105,110,103,115,32,111,102,32,110,111,110,45,112,97,114,101,110,116,104,101,115,101,115,32,105,115,32,105,109,112,111,114,116,97,110,116,32,119,104,101,110,32,97,112,112,108,121,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,116,111,32,115,116,114,105,110,103,115,32,116,104,97,116,32,100,111,32,110,111,116,32,109,97,116,99,104,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,119,104,101,110,32,116,104,105,115,32,112,97,116,116,101,114,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111>>]},{pre,[],[{code,[],[<<40,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,40,41>>]}]},{p,[],[<<105,116,32,103,105,118,101,115,32,34,110,111,32,109,97,116,99,104,34,32,113,117,105,99,107,108,121,46,32,72,111,119,101,118,101,114,44,32,105,102,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,105,115,32,110,111,116,32,117,115,101,100,44,32,116,104,101,32,109,97,116,99,104,32,114,117,110,115,32,102,111,114,32,97,32,108,111,110,103,32,116,105,109,101,44,32,97,115,32,116,104,101,114,101,32,97,114,101,32,115,111,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,119,97,121,115,32,116,104,101,32,43,32,97,110,100,32,42,32,114,101,112,101,97,116,115,32,99,97,110,32,99,97,114,118,101,32,117,112,32,116,104,101,32,115,117,98,106,101,99,116,44,32,97,110,100,32,97,108,108,32,109,117,115,116,32,98,101,32,116,101,115,116,101,100,32,98,101,102,111,114,101,32,102,97,105,108,117,114,101,32,99,97,110,32,98,101,32,114,101,112,111,114,116,101,100,46>>]},{p,[],[<<65,116,32,116,104,101,32,101,110,100,32,111,102,32,97,32,109,97,116,99,104,44,32,116,104,101,32,118,97,108,117,101,115,32,111,102,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,116,104,111,115,101,32,102,114,111,109,32,116,104,101,32,111,117,116,101,114,109,111,115,116,32,108,101,118,101,108,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,97,98,111,118,101,32,105,115,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116>>]},{pre,[],[{code,[],[<<40,97,98,40,99,100,41,101,102,41>>]}]},{p,[],[<<116,104,101,32,118,97,108,117,101,32,102,111,114,32,116,104,101,32,105,110,110,101,114,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,40,110,117,109,98,101,114,101,100,32,50,41,32,105,115,32,34,101,102,34,44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,108,97,115,116,32,118,97,108,117,101,32,116,97,107,101,110,32,111,110,32,97,116,32,116,104,101,32,116,111,112,45,108,101,118,101,108,46,32,73,102,32,97,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,109,97,116,99,104,101,100,32,97,116,32,116,104,101,32,116,111,112,32,108,101,118,101,108,44,32,105,116,115,32,102,105,110,97,108,32,99,97,112,116,117,114,101,100,32,118,97,108,117,101,32,105,115,32,117,110,115,101,116,44,32,101,118,101,110,32,105,102,32,105,116,32,119,97,115,32,40,116,101,109,112,111,114,97,114,105,108,121,41,32,115,101,116,32,97,116,32,97,32,100,101,101,112,101,114,32,108,101,118,101,108,32,100,117,114,105,110,103,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,114,111,99,101,115,115,46>>]},{p,[],[<<68,111,32,110,111,116,32,99,111,110,102,117,115,101,32,105,116,101,109,32,40,63,82,41,32,119,105,116,104,32,99,111,110,100,105,116,105,111,110,32,40,82,41,44,32,119,104,105,99,104,32,116,101,115,116,115,32,102,111,114,32,114,101,99,117,114,115,105,111,110,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,109,97,116,99,104,101,115,32,116,101,120,116,32,105,110,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115,44,32,97,108,108,111,119,105,110,103,32,102,111,114,32,97,114,98,105,116,114,97,114,121,32,110,101,115,116,105,110,103,46,32,79,110,108,121,32,100,105,103,105,116,115,32,97,114,101,32,97,108,108,111,119,101,100,32,105,110,32,110,101,115,116,101,100,32,98,114,97,99,107,101,116,115,32,40,116,104,97,116,32,105,115,44,32,119,104,101,110,32,114,101,99,117,114,115,105,110,103,41,44,32,119,104,105,108,101,32,97,110,121,32,99,104,97,114,97,99,116,101,114,115,32,97,114,101,32,112,101,114,109,105,116,116,101,100,32,97,116,32,116,104,101,32,111,117,116,101,114,32,108,101,118,101,108,46>>]},{pre,[],[{code,[],[<<60,32,40,63,58,32,40,63,40,82,41,32,92,100,43,43,32,32,124,32,91,94,60,62,93,42,43,41,32,124,32,40,63,82,41,41,32,42,32,62>>]}]},{p,[],[<<72,101,114,101,32,40,63,40,82,41,32,105,115,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,44,32,119,105,116,104,32,116,119,111,32,100,105,102,102,101,114,101,110,116,32,97,108,116,101,114,110,97,116,105,118,101,115,32,102,111,114,32,116,104,101,32,114,101,99,117,114,115,105,118,101,32,97,110,100,32,110,111,110,45,114,101,99,117,114,115,105,118,101,32,99,97,115,101,115,46,32,73,116,101,109,32,40,63,82,41,32,105,115,32,116,104,101,32,97,99,116,117,97,108,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,46>>]},{p,[],[{em,[],[<<68,105,102,102,101,114,101,110,99,101,115,32,105,110,32,82,101,99,117,114,115,105,111,110,32,80,114,111,99,101,115,115,105,110,103,32,98,101,116,119,101,101,110,32,80,67,82,69,32,97,110,100,32,80,101,114,108>>]}]},{p,[],[<<82,101,99,117,114,115,105,111,110,32,112,114,111,99,101,115,115,105,110,103,32,105,110,32,80,67,82,69,32,100,105,102,102,101,114,115,32,102,114,111,109,32,80,101,114,108,32,105,110,32,116,119,111,32,105,109,112,111,114,116,97,110,116,32,119,97,121,115,46,32,73,110,32,80,67,82,69,32,40,108,105,107,101,32,80,121,116,104,111,110,44,32,98,117,116,32,117,110,108,105,107,101,32,80,101,114,108,41,44,32,97,32,114,101,99,117,114,115,105,118,101,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,32,105,115,32,97,108,119,97,121,115,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,46,32,84,104,97,116,32,105,115,44,32,111,110,99,101,32,105,116,32,104,97,115,32,109,97,116,99,104,101,100,32,115,111,109,101,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,105,116,32,105,115,32,110,101,118,101,114,32,114,101,45,101,110,116,101,114,101,100,44,32,101,118,101,110,32,105,102,32,105,116,32,99,111,110,116,97,105,110,115,32,117,110,116,114,105,101,100,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,110,100,32,116,104,101,114,101,32,105,115,32,97,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,46,32,84,104,105,115,32,99,97,110,32,98,101,32,105,108,108,117,115,116,114,97,116,101,100,32,98,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,109,101,97,110,115,32,116,111,32,109,97,116,99,104,32,97,32,112,97,108,105,110,100,114,111,109,105,99,32,115,116,114,105,110,103,32,99,111,110,116,97,105,110,105,110,103,32,97,110,32,111,100,100,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,102,111,114,32,101,120,97,109,112,108,101,44,32,34,97,34,44,32,34,97,98,97,34,44,32,34,97,98,99,98,97,34,44,32,34,97,98,99,100,99,98,97,34,41,58>>]},{pre,[],[{code,[],[<<94,40,46,124,40,46,41,40,63,49,41,92,50,41,36>>]}]},{p,[],[<<84,104,101,32,105,100,101,97,32,105,115,32,116,104,97,116,32,105,116,32,101,105,116,104,101,114,32,109,97,116,99,104,101,115,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,44,32,111,114,32,116,119,111,32,105,100,101,110,116,105,99,97,108,32,99,104,97,114,97,99,116,101,114,115,32,115,117,114,114,111,117,110,100,105,110,103,32,97,32,115,117,98,112,97,108,105,110,100,114,111,109,101,46,32,73,110,32,80,101,114,108,44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,119,111,114,107,115,59,32,105,110,32,80,67,82,69,32,105,116,32,100,111,101,115,32,110,111,116,32,119,111,114,107,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,108,111,110,103,101,114,32,116,104,97,110,32,116,104,114,101,101,32,99,104,97,114,97,99,116,101,114,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,34,97,98,99,98,97,34,46>>]},{p,[],[<<65,116,32,116,104,101,32,116,111,112,32,108,101,118,101,108,44,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,105,115,32,109,97,116,99,104,101,100,44,32,98,117,116,32,97,115,32,105,116,32,105,115,32,110,111,116,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,116,104,101,32,102,105,114,115,116,32,97,108,116,101,114,110,97,116,105,118,101,32,102,97,105,108,115,44,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,116,97,107,101,110,44,32,97,110,100,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,107,105,99,107,115,32,105,110,46,32,84,104,101,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,116,111,32,115,117,98,112,97,116,116,101,114,110,32,49,32,115,117,99,99,101,115,115,102,117,108,108,121,32,109,97,116,99,104,101,115,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40,34,98,34,41,46,32,40,78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,97,110,100,32,101,110,100,32,111,102,32,108,105,110,101,32,116,101,115,116,115,32,97,114,101,32,110,111,116,32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,99,117,114,115,105,111,110,46,41>>]},{p,[],[<<66,97,99,107,32,97,116,32,116,104,101,32,116,111,112,32,108,101,118,101,108,44,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40,34,99,34,41,32,105,115,32,99,111,109,112,97,114,101,100,32,119,105,116,104,32,119,104,97,116,32,115,117,98,112,97,116,116,101,114,110,32,50,32,109,97,116,99,104,101,100,44,32,119,104,105,99,104,32,119,97,115,32,34,97,34,46,32,84,104,105,115,32,102,97,105,108,115,46,32,65,115,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,105,115,32,116,114,101,97,116,101,100,32,97,115,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,44,32,116,104,101,114,101,32,97,114,101,32,110,111,119,32,110,111,32,98,97,99,107,116,114,97,99,107,105,110,103,32,112,111,105,110,116,115,44,32,97,110,100,32,115,111,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,102,97,105,108,115,46,32,40,80,101,114,108,32,99,97,110,32,110,111,119,32,114,101,45,101,110,116,101,114,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,97,110,100,32,116,114,121,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,46,41,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,119,114,105,116,116,101,110,32,119,105,116,104,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,105,110,32,116,104,101,32,111,116,104,101,114,32,111,114,100,101,114,44,32,116,104,105,110,103,115,32,97,114,101,32,100,105,102,102,101,114,101,110,116,58>>]},{pre,[],[{code,[],[<<94,40,40,46,41,40,63,49,41,92,50,124,46,41,36>>]}]},{p,[],[<<84,104,105,115,32,116,105,109,101,44,32,116,104,101,32,114,101,99,117,114,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,116,114,105,101,100,32,102,105,114,115,116,44,32,97,110,100,32,99,111,110,116,105,110,117,101,115,32,116,111,32,114,101,99,117,114,115,101,32,117,110,116,105,108,32,105,116,32,114,117,110,115,32,111,117,116,32,111,102,32,99,104,97,114,97,99,116,101,114,115,44,32,97,116,32,119,104,105,99,104,32,112,111,105,110,116,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,102,97,105,108,115,46,32,66,117,116,32,116,104,105,115,32,116,105,109,101,32,119,101,32,104,97,118,101,32,97,110,111,116,104,101,114,32,97,108,116,101,114,110,97,116,105,118,101,32,116,111,32,116,114,121,32,97,116,32,116,104,101,32,104,105,103,104,101,114,32,108,101,118,101,108,46,32,84,104,97,116,32,105,115,32,116,104,101,32,115,105,103,110,105,102,105,99,97,110,116,32,100,105,102,102,101,114,101,110,99,101,58,32,105,110,32,116,104,101,32,112,114,101,118,105,111,117,115,32,99,97,115,101,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,32,105,115,32,97,116,32,97,32,100,101,101,112,101,114,32,114,101,99,117,114,115,105,111,110,32,108,101,118,101,108,44,32,119,104,105,99,104,32,80,67,82,69,32,99,97,110,110,111,116,32,117,115,101,46>>]},{p,[],[<<84,111,32,99,104,97,110,103,101,32,116,104,101,32,112,97,116,116,101,114,110,32,115,111,32,116,104,97,116,32,105,116,32,109,97,116,99,104,101,115,32,97,108,108,32,112,97,108,105,110,100,114,111,109,105,99,32,115,116,114,105,110,103,115,44,32,110,111,116,32,111,110,108,121,32,116,104,111,115,101,32,119,105,116,104,32,97,110,32,111,100,100,32,110,117,109,98,101,114,32,111,102,32,99,104,97,114,97,99,116,101,114,115,44,32,105,116,32,105,115,32,116,101,109,112,116,105,110,103,32,116,111,32,99,104,97,110,103,101,32,116,104,101,32,112,97,116,116,101,114,110,32,116,111,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<94,40,40,46,41,40,63,49,41,92,50,124,46,63,41,36>>]}]},{p,[],[<<65,103,97,105,110,44,32,116,104,105,115,32,119,111,114,107,115,32,105,110,32,80,101,114,108,44,32,98,117,116,32,110,111,116,32,105,110,32,80,67,82,69,44,32,97,110,100,32,102,111,114,32,116,104,101,32,115,97,109,101,32,114,101,97,115,111,110,46,32,87,104,101,110,32,97,32,100,101,101,112,101,114,32,114,101,99,117,114,115,105,111,110,32,104,97,115,32,109,97,116,99,104,101,100,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,44,32,105,116,32,99,97,110,110,111,116,32,98,101,32,101,110,116,101,114,101,100,32,97,103,97,105,110,32,116,111,32,109,97,116,99,104,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,46,32,84,104,101,32,115,111,108,117,116,105,111,110,32,105,115,32,116,111,32,115,101,112,97,114,97,116,101,32,116,104,101,32,116,119,111,32,99,97,115,101,115,44,32,97,110,100,32,119,114,105,116,101,32,111,117,116,32,116,104,101,32,111,100,100,32,97,110,100,32,101,118,101,110,32,99,97,115,101,115,32,97,115,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,116,32,116,104,101,32,104,105,103,104,101,114,32,108,101,118,101,108,58>>]},{pre,[],[{code,[],[<<94,40,63,58,40,40,46,41,40,63,49,41,92,50,124,41,124,40,40,46,41,40,63,51,41,92,52,124,46,41,41>>]}]},{p,[],[<<73,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,116,99,104,32,116,121,112,105,99,97,108,32,112,97,108,105,110,100,114,111,109,105,99,32,112,104,114,97,115,101,115,44,32,116,104,101,32,112,97,116,116,101,114,110,32,109,117,115,116,32,105,103,110,111,114,101,32,97,108,108,32,110,111,110,45,119,111,114,100,32,99,104,97,114,97,99,116,101,114,115,44,32,119,104,105,99,104,32,99,97,110,32,98,101,32,100,111,110,101,32,97,115,32,102,111,108,108,111,119,115,58>>]},{pre,[],[{code,[],[<<94,92,87,42,43,40,63,58,40,40,46,41,92,87,42,43,40,63,49,41,92,87,42,43,92,50,124,41,124,40,40,46,41,92,87,42,43,40,63,51,41,92,87,42,43,92,52,124,92,87,42,43,46,92,87,42,43,41,41,92,87,42,43,36>>]}]},{p,[],[<<73,102,32,114,117,110,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<99,97,115,101,108,101,115,115>>]},<<44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,112,104,114,97,115,101,115,32,115,117,99,104,32,97,115,32,34,65,32,109,97,110,44,32,97,32,112,108,97,110,44,32,97,32,99,97,110,97,108,58,32,80,97,110,97,109,97,33,34,32,97,110,100,32,105,116,32,119,111,114,107,115,32,119,101,108,108,32,105,110,32,98,111,116,104,32,80,67,82,69,32,97,110,100,32,80,101,114,108,46,32,78,111,116,105,99,101,32,116,104,101,32,117,115,101,32,111,102,32,116,104,101,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,42,43,32,116,111,32,97,118,111,105,100,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,115,101,113,117,101,110,99,101,115,32,111,102,32,110,111,110,45,119,111,114,100,32,99,104,97,114,97,99,116,101,114,115,46,32,87,105,116,104,111,117,116,32,116,104,105,115,44,32,80,67,82,69,32,116,97,107,101,115,32,109,117,99,104,32,108,111,110,103,101,114,32,40,49,48,32,116,105,109,101,115,32,111,114,32,109,111,114,101,41,32,116,111,32,109,97,116,99,104,32,116,121,112,105,99,97,108,32,112,104,114,97,115,101,115,44,32,97,110,100,32,80,101,114,108,32,116,97,107,101,115,32,115,111,32,108,111,110,103,32,116,104,97,116,32,121,111,117,32,116,104,105,110,107,32,105,116,32,104,97,115,32,103,111,110,101,32,105,110,116,111,32,97,32,108,111,111,112,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,112,97,108,105,110,100,114,111,109,101,45,109,97,116,99,104,105,110,103,32,112,97,116,116,101,114,110,115,32,97,98,111,118,101,32,119,111,114,107,32,111,110,108,121,32,105,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,100,111,101,115,32,110,111,116,32,115,116,97,114,116,32,119,105,116,104,32,97,32,112,97,108,105,110,100,114,111,109,101,32,116,104,97,116,32,105,115,32,115,104,111,114,116,101,114,32,116,104,97,110,32,116,104,101,32,101,110,116,105,114,101,32,115,116,114,105,110,103,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,97,108,116,104,111,117,103,104,32,34,97,98,99,98,97,34,32,105,115,32,99,111,114,114,101,99,116,108,121,32,109,97,116,99,104,101,100,44,32,105,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,97,98,97,98,97,34,44,32,80,67,82,69,32,102,105,110,100,115,32,112,97,108,105,110,100,114,111,109,101,32,34,97,98,97,34,32,97,116,32,116,104,101,32,115,116,97,114,116,44,32,97,110,100,32,116,104,101,110,32,102,97,105,108,115,32,97,116,32,116,111,112,32,108,101,118,101,108,44,32,97,115,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,100,111,101,115,32,110,111,116,32,102,111,108,108,111,119,46,32,79,110,99,101,32,97,103,97,105,110,44,32,105,116,32,99,97,110,110,111,116,32,106,117,109,112,32,98,97,99,107,32,105,110,116,111,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,116,111,32,116,114,121,32,111,116,104,101,114,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,115,111,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,102,97,105,108,115,46>>]}]},{p,[],[<<84,104,101,32,115,101,99,111,110,100,32,119,97,121,32,105,110,32,119,104,105,99,104,32,80,67,82,69,32,97,110,100,32,80,101,114,108,32,100,105,102,102,101,114,32,105,110,32,116,104,101,105,114,32,114,101,99,117,114,115,105,111,110,32,112,114,111,99,101,115,115,105,110,103,32,105,115,32,105,110,32,116,104,101,32,104,97,110,100,108,105,110,103,32,111,102,32,99,97,112,116,117,114,101,100,32,118,97,108,117,101,115,46,32,73,110,32,80,101,114,108,44,32,119,104,101,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,99,97,108,108,101,100,32,114,101,99,117,114,115,105,118,101,108,121,32,111,114,32,97,115,32,97,32,115,117,98,112,97,116,116,101,114,110,32,40,115,101,101,32,116,104,101,32,110,101,120,116,32,115,101,99,116,105,111,110,41,44,32,105,116,32,104,97,115,32,110,111,32,97,99,99,101,115,115,32,116,111,32,97,110,121,32,118,97,108,117,101,115,32,116,104,97,116,32,119,101,114,101,32,99,97,112,116,117,114,101,100,32,111,117,116,115,105,100,101,32,116,104,101,32,114,101,99,117,114,115,105,111,110,46,32,73,110,32,80,67,82,69,32,116,104,101,115,101,32,118,97,108,117,101,115,32,99,97,110,32,98,101,32,114,101,102,101,114,101,110,99,101,100,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<94,40,46,41,40,92,49,124,97,40,63,50,41,41>>]}]},{p,[],[<<73,110,32,80,67,82,69,44,32,105,116,32,109,97,116,99,104,101,115,32,34,98,97,98,34,46,32,84,104,101,32,102,105,114,115,116,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,109,97,116,99,104,32,34,98,34,44,32,116,104,101,110,32,105,110,32,116,104,101,32,115,101,99,111,110,100,32,103,114,111,117,112,44,32,119,104,101,110,32,116,104,101,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,32,92,49,32,102,97,105,108,115,32,116,111,32,109,97,116,99,104,32,34,98,34,44,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,32,109,97,116,99,104,101,115,32,34,97,34,44,32,97,110,100,32,116,104,101,110,32,114,101,99,117,114,115,101,115,46,32,73,110,32,116,104,101,32,114,101,99,117,114,115,105,111,110,44,32,92,49,32,100,111,101,115,32,110,111,119,32,109,97,116,99,104,32,34,98,34,32,97,110,100,32,115,111,32,116,104,101,32,119,104,111,108,101,32,109,97,116,99,104,32,115,117,99,99,101,101,100,115,46,32,73,110,32,80,101,114,108,44,32,116,104,101,32,112,97,116,116,101,114,110,32,102,97,105,108,115,32,116,111,32,109,97,116,99,104,32,98,101,99,97,117,115,101,32,105,110,115,105,100,101,32,116,104,101,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,92,49,32,99,97,110,110,111,116,32,97,99,99,101,115,115,32,116,104,101,32,101,120,116,101,114,110,97,108,108,121,32,115,101,116,32,118,97,108,117,101,46>>]},{a,[{id,<<115,101,99,116,50,49>>}],[]},{h2,[],[<<83,117,98,112,97,116,116,101,114,110,115,32,97,115,32,83,117,98,114,111,117,116,105,110,101,115>>]},{p,[],[<<73,102,32,116,104,101,32,115,121,110,116,97,120,32,102,111,114,32,97,32,114,101,99,117,114,115,105,118,101,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,32,40,101,105,116,104,101,114,32,98,121,32,110,117,109,98,101,114,32,111,114,32,98,121,32,110,97,109,101,41,32,105,115,32,117,115,101,100,32,111,117,116,115,105,100,101,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,116,111,32,119,104,105,99,104,32,105,116,32,114,101,102,101,114,115,44,32,105,116,32,111,112,101,114,97,116,101,115,32,108,105,107,101,32,97,32,115,117,98,114,111,117,116,105,110,101,32,105,110,32,97,32,112,114,111,103,114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,46,32,84,104,101,32,99,97,108,108,101,100,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,98,101,32,100,101,102,105,110,101,100,32,98,101,102,111,114,101,32,111,114,32,97,102,116,101,114,32,116,104,101,32,114,101,102,101,114,101,110,99,101,46,32,65,32,110,117,109,98,101,114,101,100,32,114,101,102,101,114,101,110,99,101,32,99,97,110,32,98,101,32,97,98,115,111,108,117,116,101,32,111,114,32,114,101,108,97,116,105,118,101,44,32,97,115,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,115,58>>]},{pre,[],[{code,[],[<<40,46,46,46,40,97,98,115,111,108,117,116,101,41,46,46,46,41,46,46,46,40,63,50,41,46,46,46,10,40,46,46,46,40,114,101,108,97,116,105,118,101,41,46,46,46,41,46,46,46,40,63,45,49,41,46,46,46,10,40,46,46,46,40,63,43,49,41,46,46,46,40,114,101,108,97,116,105,118,101,41,46,46,46>>]}]},{p,[],[<<65,110,32,101,97,114,108,105,101,114,32,101,120,97,109,112,108,101,32,112,111,105,110,116,101,100,32,111,117,116,32,116,104,97,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,115,101,110,115,101,32,97,110,100,32,115,101,110,115,105,98,105,108,105,116,121,34,32,97,110,100,32,34,114,101,115,112,111,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,44,32,98,117,116,32,110,111,116,32,34,115,101,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,58>>]},{pre,[],[{code,[],[<<40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,92,49,105,98,105,108,105,116,121>>]}]},{p,[],[<<73,102,32,105,110,115,116,101,97,100,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,105,115,32,117,115,101,100,44,32,105,116,32,109,97,116,99,104,101,115,32,34,115,101,110,115,101,32,97,110,100,32,114,101,115,112,111,110,115,105,98,105,108,105,116,121,34,32,97,110,100,32,116,104,101,32,111,116,104,101,114,32,116,119,111,32,115,116,114,105,110,103,115,58>>]},{pre,[],[{code,[],[<<40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,40,63,49,41,105,98,105,108,105,116,121>>]}]},{p,[],[<<65,110,111,116,104,101,114,32,101,120,97,109,112,108,101,32,105,115,32,112,114,111,118,105,100,101,100,32,105,110,32,116,104,101,32,100,105,115,99,117,115,115,105,111,110,32,111,102,32,68,69,70,73,78,69,32,101,97,114,108,105,101,114,46>>]},{p,[],[<<65,108,108,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,115,44,32,114,101,99,117,114,115,105,118,101,32,111,114,32,110,111,116,44,32,97,114,101,32,97,108,119,97,121,115,32,116,114,101,97,116,101,100,32,97,115,32,97,116,111,109,105,99,32,103,114,111,117,112,115,46,32,84,104,97,116,32,105,115,44,32,111,110,99,101,32,97,32,115,117,98,114,111,117,116,105,110,101,32,104,97,115,32,109,97,116,99,104,101,100,32,115,111,109,101,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,105,116,32,105,115,32,110,101,118,101,114,32,114,101,45,101,110,116,101,114,101,100,44,32,101,118,101,110,32,105,102,32,105,116,32,99,111,110,116,97,105,110,115,32,117,110,116,114,105,101,100,32,97,108,116,101,114,110,97,116,105,118,101,115,32,97,110,100,32,116,104,101,114,101,32,105,115,32,97,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,46,32,65,110,121,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,116,104,97,116,32,97,114,101,32,115,101,116,32,100,117,114,105,110,103,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,32,114,101,118,101,114,116,32,116,111,32,116,104,101,105,114,32,112,114,101,118,105,111,117,115,32,118,97,108,117,101,115,32,97,102,116,101,114,119,97,114,100,115,46>>]},{p,[],[<<80,114,111,99,101,115,115,105,110,103,32,111,112,116,105,111,110,115,32,115,117,99,104,32,97,115,32,99,97,115,101,45,105,110,100,101,112,101,110,100,101,110,99,101,32,97,114,101,32,102,105,120,101,100,32,119,104,101,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,100,101,102,105,110,101,100,44,32,115,111,32,105,102,32,105,116,32,105,115,32,117,115,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,44,32,115,117,99,104,32,111,112,116,105,111,110,115,32,99,97,110,110,111,116,32,98,101,32,99,104,97,110,103,101,100,32,102,111,114,32,100,105,102,102,101,114,101,110,116,32,99,97,108,108,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,34,97,98,99,97,98,99,34,32,98,117,116,32,110,111,116,32,34,97,98,99,65,66,67,34,44,32,97,115,32,116,104,101,32,99,104,97,110,103,101,32,111,102,32,112,114,111,99,101,115,115,105,110,103,32,111,112,116,105,111,110,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,116,104,101,32,99,97,108,108,101,100,32,115,117,98,112,97,116,116,101,114,110,58>>]},{pre,[],[{code,[],[<<40,97,98,99,41,40,63,105,58,40,63,45,49,41,41>>]}]},{a,[{id,<<115,101,99,116,50,50>>}],[]},{h2,[],[<<79,110,105,103,117,114,117,109,97,32,83,117,98,114,111,117,116,105,110,101,32,83,121,110,116,97,120>>]},{p,[],[<<70,111,114,32,99,111,109,112,97,116,105,98,105,108,105,116,121,32,119,105,116,104,32,79,110,105,103,117,114,117,109,97,44,32,116,104,101,32,110,111,110,45,80,101,114,108,32,115,121,110,116,97,120,32,92,103,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,32,111,114,32,97,32,110,117,109,98,101,114,32,101,110,99,108,111,115,101,100,32,101,105,116,104,101,114,32,105,110,32,97,110,103,108,101,32,98,114,97,99,107,101,116,115,32,111,114,32,115,105,110,103,108,101,32,113,117,111,116,101,115,44,32,105,115,32,97,108,116,101,114,110,97,116,105,118,101,32,115,121,110,116,97,120,32,102,111,114,32,114,101,102,101,114,101,110,99,105,110,103,32,97,32,115,117,98,112,97,116,116,101,114,110,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,44,32,112,111,115,115,105,98,108,121,32,114,101,99,117,114,115,105,118,101,108,121,46,32,72,101,114,101,32,102,111,108,108,111,119,115,32,116,119,111,32,111,102,32,116,104,101,32,101,120,97,109,112,108,101,115,32,117,115,101,100,32,97,98,111,118,101,44,32,114,101,119,114,105,116,116,101,110,32,117,115,105,110,103,32,116,104,105,115,32,115,121,110,116,97,120,58>>]},{pre,[],[{code,[],[<<40,63,60,112,110,62,32,92,40,32,40,32,40,63,62,91,94,40,41,93,43,41,32,124,32,92,103,60,112,110,62,32,41,42,32,92,41,32,41,10,40,115,101,110,115,124,114,101,115,112,111,110,115,41,101,32,97,110,100,32,92,103,39,49,39,105,98,105,108,105,116,121>>]}]},{p,[],[<<80,67,82,69,32,115,117,112,112,111,114,116,115,32,97,110,32,101,120,116,101,110,115,105,111,110,32,116,111,32,79,110,105,103,117,114,117,109,97,58,32,105,102,32,97,32,110,117,109,98,101,114,32,105,115,32,112,114,101,99,101,100,101,100,32,98,121,32,97,32,112,108,117,115,32,111,114,32,109,105,110,117,115,32,115,105,103,110,44,32,105,116,32,105,115,32,116,97,107,101,110,32,97,115,32,97,32,114,101,108,97,116,105,118,101,32,114,101,102,101,114,101,110,99,101,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<40,97,98,99,41,40,63,105,58,92,103,60,45,49,62,41>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,92,103,123,46,46,46,125,32,40,80,101,114,108,32,115,121,110,116,97,120,41,32,97,110,100,32,92,103,60,46,46,46,62,32,40,79,110,105,103,117,114,117,109,97,32,115,121,110,116,97,120,41,32,97,114,101,32>>,{em,[],[<<110,111,116>>]},<<32,115,121,110,111,110,121,109,111,117,115,46,32,84,104,101,32,102,111,114,109,101,114,32,105,115,32,97,32,98,97,99,107,32,114,101,102,101,114,101,110,99,101,59,32,116,104,101,32,108,97,116,116,101,114,32,105,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,46>>]},{a,[{id,<<115,101,99,116,50,51>>}],[]},{h2,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,67,111,110,116,114,111,108>>]},{p,[],[<<80,101,114,108,32,53,46,49,48,32,105,110,116,114,111,100,117,99,101,100,32,115,111,109,101,32,34,83,112,101,99,105,97,108,32,66,97,99,107,116,114,97,99,107,105,110,103,32,67,111,110,116,114,111,108,32,86,101,114,98,115,34,44,32,119,104,105,99,104,32,97,114,101,32,115,116,105,108,108,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,101,32,80,101,114,108,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,97,115,32,34,101,120,112,101,114,105,109,101,110,116,97,108,32,97,110,100,32,115,117,98,106,101,99,116,32,116,111,32,99,104,97,110,103,101,32,111,114,32,114,101,109,111,118,97,108,32,105,110,32,97,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,32,111,102,32,80,101,114,108,34,46,32,73,116,32,103,111,101,115,32,111,110,32,116,111,32,115,97,121,58,32,34,84,104,101,105,114,32,117,115,97,103,101,32,105,110,32,112,114,111,100,117,99,116,105,111,110,32,99,111,100,101,32,115,104,111,117,108,100,32,98,101,32,110,111,116,101,100,32,116,111,32,97,118,111,105,100,32,112,114,111,98,108,101,109,115,32,100,117,114,105,110,103,32,117,112,103,114,97,100,101,115,46,34,32,84,104,101,32,115,97,109,101,32,114,101,109,97,114,107,115,32,97,112,112,108,121,32,116,111,32,116,104,101,32,80,67,82,69,32,102,101,97,116,117,114,101,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,116,104,105,115,32,115,101,99,116,105,111,110,46>>]},{p,[],[<<84,104,101,32,110,101,119,32,118,101,114,98,115,32,109,97,107,101,32,117,115,101,32,111,102,32,119,104,97,116,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,105,110,118,97,108,105,100,32,115,121,110,116,97,120,58,32,97,110,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32,97,110,32,97,115,116,101,114,105,115,107,46,32,84,104,101,121,32,97,114,101,32,103,101,110,101,114,97,108,108,121,32,111,102,32,116,104,101,32,102,111,114,109,32,40,42,86,69,82,66,41,32,111,114,32,40,42,86,69,82,66,58,78,65,77,69,41,46,32,83,111,109,101,32,99,97,110,32,116,97,107,101,32,101,105,116,104,101,114,32,102,111,114,109,44,32,112,111,115,115,105,98,108,121,32,98,101,104,97,118,105,110,103,32,100,105,102,102,101,114,101,110,116,108,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,119,104,101,116,104,101,114,32,97,32,110,97,109,101,32,105,115,32,112,114,101,115,101,110,116,46,32,65,32,110,97,109,101,32,105,115,32,97,110,121,32,115,101,113,117,101,110,99,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,105,110,99,108,117,100,101,32,97,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,46,32,84,104,101,32,109,97,120,105,109,117,109,32,110,97,109,101,32,108,101,110,103,116,104,32,105,115,32,50,53,53,32,105,110,32,116,104,101,32,56,45,98,105,116,32,108,105,98,114,97,114,121,32,97,110,100,32,54,53,53,51,53,32,105,110,32,116,104,101,32,49,54,45,98,105,116,32,97,110,100,32,51,50,45,98,105,116,32,108,105,98,114,97,114,105,101,115,46,32,73,102,32,116,104,101,32,110,97,109,101,32,105,115,32,101,109,112,116,121,44,32,116,104,97,116,32,105,115,44,32,105,102,32,116,104,101,32,99,108,111,115,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,115,32,116,104,101,32,99,111,108,111,110,44,32,116,104,101,32,101,102,102,101,99,116,32,105,115,32,97,115,32,105,102,32,116,104,101,32,99,111,108,111,110,32,119,97,115,32,110,111,116,32,116,104,101,114,101,46,32,65,110,121,32,110,117,109,98,101,114,32,111,102,32,116,104,101,115,101,32,118,101,114,98,115,32,99,97,110,32,111,99,99,117,114,32,105,110,32,97,32,112,97,116,116,101,114,110,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,115,101,32,118,101,114,98,115,32,105,110,32,114,101,112,101,97,116,101,100,32,103,114,111,117,112,115,44,32,97,115,115,101,114,116,105,111,110,115,44,32,97,110,100,32,105,110,32,115,117,98,112,97,116,116,101,114,110,115,32,99,97,108,108,101,100,32,97,115,32,115,117,98,114,111,117,116,105,110,101,115,32,40,119,104,101,116,104,101,114,32,111,114,32,110,111,116,32,114,101,99,117,114,115,105,118,101,108,121,41,32,105,115,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,46>>]},{p,[],[{em,[],[<<79,112,116,105,109,105,122,97,116,105,111,110,115,32,84,104,97,116,32,65,102,102,101,99,116,32,66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115>>]}]},{p,[],[<<80,67,82,69,32,99,111,110,116,97,105,110,115,32,115,111,109,101,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,116,104,97,116,32,97,114,101,32,117,115,101,100,32,116,111,32,115,112,101,101,100,32,117,112,32,109,97,116,99,104,105,110,103,32,98,121,32,114,117,110,110,105,110,103,32,115,111,109,101,32,99,104,101,99,107,115,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,101,97,99,104,32,109,97,116,99,104,32,97,116,116,101,109,112,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,116,32,99,97,110,32,107,110,111,119,32,116,104,101,32,109,105,110,105,109,117,109,32,108,101,110,103,116,104,32,111,102,32,109,97,116,99,104,105,110,103,32,115,117,98,106,101,99,116,44,32,111,114,32,116,104,97,116,32,97,32,112,97,114,116,105,99,117,108,97,114,32,99,104,97,114,97,99,116,101,114,32,109,117,115,116,32,98,101,32,112,114,101,115,101,110,116,46,32,87,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,98,121,112,97,115,115,101,115,32,116,104,101,32,114,117,110,110,105,110,103,32,111,102,32,97,32,109,97,116,99,104,44,32,97,110,121,32,105,110,99,108,117,100,101,100,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,97,114,101,32,110,111,116,32,112,114,111,99,101,115,115,101,100,46,32,112,114,111,99,101,115,115,101,100,46,32,89,111,117,32,99,97,110,32,115,117,112,112,114,101,115,115,32,116,104,101,32,115,116,97,114,116,45,111,102,45,109,97,116,99,104,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,98,121,32,115,101,116,116,105,110,103,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]},<<32,119,104,101,110,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,111,114,32,98,121,32,115,116,97,114,116,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,119,105,116,104,32,40,42,78,79,95,83,84,65,82,84,95,79,80,84,41,46>>]},{p,[],[<<69,120,112,101,114,105,109,101,110,116,115,32,119,105,116,104,32,80,101,114,108,32,115,117,103,103,101,115,116,32,116,104,97,116,32,105,116,32,116,111,111,32,104,97,115,32,115,105,109,105,108,97,114,32,111,112,116,105,109,105,122,97,116,105,111,110,115,44,32,115,111,109,101,116,105,109,101,115,32,108,101,97,100,105,110,103,32,116,111,32,97,110,111,109,97,108,111,117,115,32,114,101,115,117,108,116,115,46>>]},{p,[],[{em,[],[<<86,101,114,98,115,32,84,104,97,116,32,65,99,116,32,73,109,109,101,100,105,97,116,101,108,121>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,115,32,97,99,116,32,97,115,32,115,111,111,110,32,97,115,32,116,104,101,121,32,97,114,101,32,101,110,99,111,117,110,116,101,114,101,100,46,32,84,104,101,121,32,109,117,115,116,32,110,111,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,46>>]},{pre,[],[{code,[],[<<40,42,65,67,67,69,80,84,41>>]}]},{p,[],[<<84,104,105,115,32,118,101,114,98,32,99,97,117,115,101,115,32,116,104,101,32,109,97,116,99,104,32,116,111,32,101,110,100,32,115,117,99,99,101,115,115,102,117,108,108,121,44,32,115,107,105,112,112,105,110,103,32,116,104,101,32,114,101,109,97,105,110,100,101,114,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,105,116,32,105,115,32,105,110,115,105,100,101,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,105,115,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,44,32,111,110,108,121,32,116,104,97,116,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,101,110,100,101,100,32,115,117,99,99,101,115,115,102,117,108,108,121,46,32,77,97,116,99,104,105,110,103,32,116,104,101,110,32,99,111,110,116,105,110,117,101,115,32,97,116,32,116,104,101,32,111,117,116,101,114,32,108,101,118,101,108,46,32,73,102,32,40,42,65,67,67,69,80,84,41,32,105,115,32,116,114,105,103,103,101,114,101,100,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,115,117,99,99,101,101,100,115,59,32,105,110,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,44,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,102,97,105,108,115,46>>]},{p,[],[<<73,102,32,40,42,65,67,67,69,80,84,41,32,105,115,32,105,110,115,105,100,101,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,44,32,116,104,101,32,100,97,116,97,32,115,111,32,102,97,114,32,105,115,32,99,97,112,116,117,114,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,101,115,32,34,65,66,34,44,32,34,65,65,68,34,44,32,111,114,32,34,65,67,68,34,46,32,87,104,101,110,32,105,116,32,109,97,116,99,104,101,115,32,34,65,66,34,44,32,34,66,34,32,105,115,32,99,97,112,116,117,114,101,100,32,98,121,32,116,104,101,32,111,117,116,101,114,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{pre,[],[{code,[],[<<65,40,40,63,58,65,124,66,40,42,65,67,67,69,80,84,41,124,67,41,68,41>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,32,99,97,117,115,101,115,32,97,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,44,32,102,111,114,99,105,110,103,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,111,32,111,99,99,117,114,46,32,73,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,40,63,33,41,32,98,117,116,32,101,97,115,105,101,114,32,116,111,32,114,101,97,100,46>>]},{pre,[],[{code,[],[<<40,42,70,65,73,76,41,32,111,114,32,40,42,70,41>>]}]},{p,[],[<<84,104,101,32,80,101,114,108,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,115,116,97,116,101,115,32,116,104,97,116,32,105,116,32,105,115,32,112,114,111,98,97,98,108,121,32,117,115,101,102,117,108,32,111,110,108,121,32,119,104,101,110,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,40,63,123,125,41,32,111,114,32,40,63,63,123,125,41,46,32,84,104,111,115,101,32,97,114,101,32,80,101,114,108,32,102,101,97,116,117,114,101,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,80,67,82,69,46>>]},{p,[],[<<65,32,109,97,116,99,104,32,119,105,116,104,32,116,104,101,32,115,116,114,105,110,103,32,34,97,97,97,97,34,32,97,108,119,97,121,115,32,102,97,105,108,115,44,32,98,117,116,32,116,104,101,32,99,97,108,108,111,117,116,32,105,115,32,116,97,107,101,110,32,98,101,102,111,114,101,32,101,97,99,104,32,98,97,99,107,116,114,97,99,107,32,111,99,99,117,114,115,32,40,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,44,32,49,48,32,116,105,109,101,115,41,46>>]},{p,[],[{em,[],[<<82,101,99,111,114,100,105,110,103,32,87,104,105,99,104,32,80,97,116,104,32,87,97,115,32,84,97,107,101,110>>]}]},{p,[],[<<84,104,101,32,109,97,105,110,32,112,117,114,112,111,115,101,32,111,102,32,116,104,105,115,32,118,101,114,98,32,105,115,32,116,111,32,116,114,97,99,107,32,104,111,119,32,97,32,109,97,116,99,104,32,119,97,115,32,97,114,114,105,118,101,100,32,97,116,44,32,97,108,116,104,111,117,103,104,32,105,116,32,97,108,115,111,32,104,97,115,32,97,32,115,101,99,111,110,100,97,114,121,32,117,115,101,32,105,110,32,119,105,116,104,32,97,100,118,97,110,99,105,110,103,32,116,104,101,32,109,97,116,99,104,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,32,40,115,101,101,32,40,42,83,75,73,80,41,32,98,101,108,111,119,41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<73,110,32,69,114,108,97,110,103,44,32,116,104,101,114,101,32,105,115,32,110,111,32,105,110,116,101,114,102,97,99,101,32,116,111,32,114,101,116,114,105,101,118,101,32,97,32,109,97,114,107,32,119,105,116,104,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,50,44,51>>]}]},<<44,32,115,111,32,111,110,108,121,32,116,104,101,32,115,101,99,111,110,100,97,114,121,32,112,117,114,112,111,115,101,32,105,115,32,114,101,108,101,118,97,110,116,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,46>>]},{p,[],[<<84,104,101,32,114,101,115,116,32,111,102,32,116,104,105,115,32,115,101,99,116,105,111,110,32,105,115,32,116,104,101,114,101,102,111,114,101,32,100,101,108,105,98,101,114,97,116,101,108,121,32,110,111,116,32,97,100,97,112,116,101,100,32,102,111,114,32,114,101,97,100,105,110,103,32,98,121,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,44,32,98,117,116,32,116,104,101,32,101,120,97,109,112,108,101,115,32,99,97,110,32,104,101,108,112,32,105,110,32,117,110,100,101,114,115,116,97,110,100,105,110,103,32,78,65,77,69,83,32,97,115,32,116,104,101,121,32,99,97,110,32,98,101,32,117,115,101,100,32,98,121,32,40,42,83,75,73,80,41,46>>]}]},{pre,[],[{code,[],[<<40,42,77,65,82,75,58,78,65,77,69,41,32,111,114,32,40,42,58,78,65,77,69,41>>]}]},{p,[],[<<65,32,110,97,109,101,32,105,115,32,97,108,119,97,121,115,32,114,101,113,117,105,114,101,100,32,119,105,116,104,32,116,104,105,115,32,118,101,114,98,46,32,84,104,101,114,101,32,99,97,110,32,98,101,32,97,115,32,109,97,110,121,32,105,110,115,116,97,110,99,101,115,32,111,102,32,40,42,77,65,82,75,41,32,97,115,32,121,111,117,32,108,105,107,101,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,97,110,100,32,116,104,101,105,114,32,110,97,109,101,115,32,100,111,32,110,111,116,32,104,97,118,101,32,116,111,32,98,101,32,117,110,105,113,117,101,46>>]},{p,[],[<<87,104,101,110,32,97,32,109,97,116,99,104,32,115,117,99,99,101,101,100,115,44,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,108,97,115,116,32,101,110,99,111,117,110,116,101,114,101,100,32,40,42,77,65,82,75,58,78,65,77,69,41,44,32,40,42,80,82,85,78,69,58,78,65,77,69,41,44,32,111,114,32,40,42,84,72,69,78,58,78,65,77,69,41,32,111,110,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,97,116,104,32,105,115,32,112,97,115,115,101,100,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,32,97,115,32,100,101,115,99,114,105,98,101,100,32,105,110,32,115,101,99,116,105,111,110,32,34,69,120,116,114,97,32,100,97,116,97,32,102,111,114,32>>,{code,[],[<<112,99,114,101,95,101,120,101,99,40,41>>]},<<34,32,105,110,32,116,104,101,32>>,{code,[],[<<112,99,114,101,97,112,105>>]},<<32,100,111,99,117,109,101,110,116,97,116,105,111,110,46,32,73,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,111,102,32>>,{code,[],[<<112,99,114,101,116,101,115,116>>]},<<32,111,117,116,112,117,116,44,32,116,104,101,32,47,75,32,109,111,100,105,102,105,101,114,32,114,101,113,117,101,115,116,115,32,116,104,101,32,114,101,116,114,105,101,118,97,108,32,97,110,100,32,111,117,116,112,117,116,116,105,110,103,32,111,102,32,40,42,77,65,82,75,41,32,100,97,116,97,58>>]},{pre,[],[{code,[],[<<32,32,114,101,62,32,47,88,40,42,77,65,82,75,58,65,41,89,124,88,40,42,77,65,82,75,58,66,41,90,47,75,10,100,97,116,97,62,32,88,89,10,32,48,58,32,88,89,10,77,75,58,32,65,10,88,90,10,32,48,58,32,88,90,10,77,75,58,32,66>>]}]},{p,[],[<<84,104,101,32,40,42,77,65,82,75,41,32,110,97,109,101,32,105,115,32,116,97,103,103,101,100,32,119,105,116,104,32,34,77,75,58,34,32,105,110,32,116,104,105,115,32,111,117,116,112,117,116,44,32,97,110,100,32,105,110,32,116,104,105,115,32,101,120,97,109,112,108,101,32,105,116,32,105,110,100,105,99,97,116,101,115,32,119,104,105,99,104,32,111,102,32,116,104,101,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,32,109,97,116,99,104,101,100,46,32,84,104,105,115,32,105,115,32,97,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,119,97,121,32,111,102,32,111,98,116,97,105,110,105,110,103,32,116,104,105,115,32,105,110,102,111,114,109,97,116,105,111,110,32,116,104,97,110,32,112,117,116,116,105,110,103,32,101,97,99,104,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,105,116,115,32,111,119,110,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,46>>]},{p,[],[<<73,102,32,97,32,118,101,114,98,32,119,105,116,104,32,97,32,110,97,109,101,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,44,32,116,104,101,32,110,97,109,101,32,105,115,32,114,101,99,111,114,100,101,100,32,97,110,100,32,112,97,115,115,101,100,32,98,97,99,107,32,105,102,32,105,116,32,105,115,32,116,104,101,32,108,97,115,116,32,101,110,99,111,117,110,116,101,114,101,100,46,32,84,104,105,115,32,100,111,101,115,32,110,111,116,32,111,99,99,117,114,32,102,111,114,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,111,114,32,102,97,105,108,105,110,103,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,46>>]},{p,[],[<<65,102,116,101,114,32,97,32,112,97,114,116,105,97,108,32,109,97,116,99,104,32,111,114,32,97,32,102,97,105,108,101,100,32,109,97,116,99,104,44,32,116,104,101,32,108,97,115,116,32,101,110,99,111,117,110,116,101,114,101,100,32,110,97,109,101,32,105,110,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,112,114,111,99,101,115,115,32,105,115,32,114,101,116,117,114,110,101,100,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<32,32,114,101,62,32,47,88,40,42,77,65,82,75,58,65,41,89,124,88,40,42,77,65,82,75,58,66,41,90,47,75,10,100,97,116,97,62,32,88,80,10,78,111,32,109,97,116,99,104,44,32,109,97,114,107,32,61,32,66>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,105,110,32,116,104,105,115,32,117,110,97,110,99,104,111,114,101,100,32,101,120,97,109,112,108,101,44,32,116,104,101,32,109,97,114,107,32,105,115,32,114,101,116,97,105,110,101,100,32,102,114,111,109,32,116,104,101,32,109,97,116,99,104,32,97,116,116,101,109,112,116,32,116,104,97,116,32,115,116,97,114,116,101,100,32,97,116,32,108,101,116,116,101,114,32,34,88,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,46,32,83,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,32,97,116,116,101,109,112,116,115,32,115,116,97,114,116,105,110,103,32,97,116,32,34,80,34,32,97,110,100,32,116,104,101,110,32,119,105,116,104,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,100,111,32,110,111,116,32,103,101,116,32,97,115,32,102,97,114,32,97,115,32,116,104,101,32,40,42,77,65,82,75,41,32,105,116,101,109,44,32,110,101,118,101,114,116,104,101,108,101,115,115,32,100,111,32,110,111,116,32,114,101,115,101,116,32,105,116,46>>]},{p,[],[{em,[],[<<86,101,114,98,115,32,84,104,97,116,32,65,99,116,32,97,102,116,101,114,32,66,97,99,107,116,114,97,99,107,105,110,103>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,115,32,100,111,32,110,111,116,104,105,110,103,32,119,104,101,110,32,116,104,101,121,32,97,114,101,32,101,110,99,111,117,110,116,101,114,101,100,46,32,77,97,116,99,104,105,110,103,32,99,111,110,116,105,110,117,101,115,32,119,105,116,104,32,119,104,97,116,32,102,111,108,108,111,119,115,44,32,98,117,116,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,44,32,99,97,117,115,105,110,103,32,97,32,98,97,99,107,116,114,97,99,107,32,116,111,32,116,104,101,32,118,101,114,98,44,32,97,32,102,97,105,108,117,114,101,32,105,115,32,102,111,114,99,101,100,46,32,84,104,97,116,32,105,115,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,110,111,116,32,112,97,115,115,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,116,104,101,32,118,101,114,98,46,32,72,111,119,101,118,101,114,44,32,119,104,101,110,32,111,110,101,32,111,102,32,116,104,101,115,101,32,118,101,114,98,115,32,97,112,112,101,97,114,115,32,105,110,115,105,100,101,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,111,114,32,97,110,32,97,115,115,101,114,116,105,111,110,32,116,104,97,116,32,105,115,32,116,114,117,101,44,32,105,116,115,32,101,102,102,101,99,116,32,105,115,32,99,111,110,102,105,110,101,100,32,116,111,32,116,104,97,116,32,103,114,111,117,112,44,32,97,115,32,111,110,99,101,32,116,104,101,32,103,114,111,117,112,32,104,97,115,32,98,101,101,110,32,109,97,116,99,104,101,100,44,32,116,104,101,114,101,32,105,115,32,110,101,118,101,114,32,97,110,121,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,105,116,46,32,73,110,32,116,104,105,115,32,115,105,116,117,97,116,105,111,110,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,32,34,106,117,109,112,32,98,97,99,107,34,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,116,104,101,32,101,110,116,105,114,101,32,97,116,111,109,105,99,32,103,114,111,117,112,32,111,114,32,97,115,115,101,114,116,105,111,110,46,32,40,82,101,109,101,109,98,101,114,32,97,108,115,111,44,32,97,115,32,115,116,97,116,101,100,32,97,98,111,118,101,44,32,116,104,97,116,32,116,104,105,115,32,108,111,99,97,108,105,122,97,116,105,111,110,32,97,108,115,111,32,97,112,112,108,105,101,115,32,105,110,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,115,46,41>>]},{p,[],[<<84,104,101,115,101,32,118,101,114,98,115,32,100,105,102,102,101,114,32,105,110,32,101,120,97,99,116,108,121,32,119,104,97,116,32,107,105,110,100,32,111,102,32,102,97,105,108,117,114,101,32,111,99,99,117,114,115,32,119,104,101,110,32,98,97,99,107,116,114,97,99,107,105,110,103,32,114,101,97,99,104,101,115,32,116,104,101,109,46,32,84,104,101,32,98,101,104,97,118,105,111,114,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,32,105,115,32,119,104,97,116,32,111,99,99,117,114,115,32,119,104,101,110,32,116,104,101,32,118,101,114,98,32,105,115,32,110,111,116,32,105,110,32,97,32,115,117,98,114,111,117,116,105,110,101,32,111,114,32,97,110,32,97,115,115,101,114,116,105,111,110,46,32,83,117,98,115,101,113,117,101,110,116,32,115,101,99,116,105,111,110,115,32,99,111,118,101,114,32,116,104,101,115,101,32,115,112,101,99,105,97,108,32,99,97,115,101,115,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,44,32,119,104,105,99,104,32,109,117,115,116,32,110,111,116,32,98,101,32,102,111,108,108,111,119,101,100,32,98,121,32,97,32,110,97,109,101,44,32,99,97,117,115,101,115,32,116,104,101,32,119,104,111,108,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,32,111,117,116,114,105,103,104,116,32,105,102,32,116,104,101,114,101,32,105,115,32,97,32,108,97,116,101,114,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,116,104,97,116,32,99,97,117,115,101,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,111,32,114,101,97,99,104,32,105,116,46,32,69,118,101,110,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,117,110,97,110,99,104,111,114,101,100,44,32,110,111,32,102,117,114,116,104,101,114,32,97,116,116,101,109,112,116,115,32,116,111,32,102,105,110,100,32,97,32,109,97,116,99,104,32,98,121,32,97,100,118,97,110,99,105,110,103,32,116,104,101,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,32,116,97,107,101,32,112,108,97,99,101,46>>]},{pre,[],[{code,[],[<<40,42,67,79,77,77,73,84,41>>]}]},{p,[],[<<73,102,32,40,42,67,79,77,77,73,84,41,32,105,115,32,116,104,101,32,111,110,108,121,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,32,116,104,97,116,32,105,115,32,101,110,99,111,117,110,116,101,114,101,100,44,32,111,110,99,101,32,105,116,32,104,97,115,32,98,101,101,110,32,112,97,115,115,101,100,44,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,50,44,51>>]}]},<<32,105,115,32,99,111,109,109,105,116,116,101,100,32,116,111,32,102,105,110,100,32,97,32,109,97,116,99,104,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,44,32,111,114,32,110,111,116,32,97,116,32,97,108,108,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<97,43,40,42,67,79,77,77,73,84,41,98>>]}]},{p,[],[<<84,104,105,115,32,109,97,116,99,104,101,115,32,34,120,120,97,97,98,34,32,98,117,116,32,110,111,116,32,34,97,97,99,97,97,98,34,46,32,73,116,32,99,97,110,32,98,101,32,116,104,111,117,103,104,116,32,111,102,32,97,115,32,97,32,107,105,110,100,32,111,102,32,100,121,110,97,109,105,99,32,97,110,99,104,111,114,44,32,111,114,32,34,73,39,118,101,32,115,116,97,114,116,101,100,44,32,115,111,32,73,32,109,117,115,116,32,102,105,110,105,115,104,34,46,32,84,104,101,32,110,97,109,101,32,111,102,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,108,121,32,112,97,115,115,101,100,32,40,42,77,65,82,75,41,32,105,110,32,116,104,101,32,112,97,116,104,32,105,115,32,112,97,115,115,101,100,32,98,97,99,107,32,119,104,101,110,32,40,42,67,79,77,77,73,84,41,32,102,111,114,99,101,115,32,97,32,109,97,116,99,104,32,102,97,105,108,117,114,101,46>>]},{p,[],[<<73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,32,101,120,105,115,116,115,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,97,32,100,105,102,102,101,114,101,110,116,32,111,110,101,32,116,104,97,116,32,102,111,108,108,111,119,115,32,40,42,67,79,77,77,73,84,41,32,99,97,110,32,98,101,32,116,114,105,103,103,101,114,101,100,32,102,105,114,115,116,44,32,115,111,32,109,101,114,101,108,121,32,112,97,115,115,105,110,103,32,40,42,67,79,77,77,73,84,41,32,100,117,114,105,110,103,32,97,32,109,97,116,99,104,32,100,111,101,115,32,110,111,116,32,97,108,119,97,121,115,32,103,117,97,114,97,110,116,101,101,32,116,104,97,116,32,97,32,109,97,116,99,104,32,109,117,115,116,32,98,101,32,97,116,32,116,104,105,115,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,40,42,67,79,77,77,73,84,41,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,97,32,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,97,110,32,97,110,99,104,111,114,44,32,117,110,108,101,115,115,32,116,104,101,32,80,67,82,69,32,115,116,97,114,116,45,111,102,45,109,97,116,99,104,32,111,112,116,105,109,105,122,97,116,105,111,110,115,32,97,114,101,32,116,117,114,110,101,100,32,111,102,102,44,32,97,115,32,115,104,111,119,110,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<49,62,32,114,101,58,114,117,110,40,34,120,121,122,97,98,99,34,44,34,40,42,67,79,77,77,73,84,41,97,98,99,34,44,91,123,99,97,112,116,117,114,101,44,97,108,108,44,108,105,115,116,125,93,41,46,10,123,109,97,116,99,104,44,91,34,97,98,99,34,93,125,10,50,62,32,114,101,58,114,117,110,40,34,120,121,122,97,98,99,34,44,34,40,42,67,79,77,77,73,84,41,97,98,99,34,44,91,123,99,97,112,116,117,114,101,44,97,108,108,44,108,105,115,116,125,44,110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101,93,41,46,10,110,111,109,97,116,99,104>>]}]},{p,[],[<<70,111,114,32,116,104,105,115,32,112,97,116,116,101,114,110,44,32,80,67,82,69,32,107,110,111,119,115,32,116,104,97,116,32,97,110,121,32,109,97,116,99,104,32,109,117,115,116,32,115,116,97,114,116,32,119,105,116,104,32,34,97,34,44,32,115,111,32,116,104,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,115,107,105,112,115,32,97,108,111,110,103,32,116,104,101,32,115,117,98,106,101,99,116,32,116,111,32,34,97,34,32,98,101,102,111,114,101,32,97,112,112,108,121,105,110,103,32,116,104,101,32,112,97,116,116,101,114,110,32,116,111,32,116,104,101,32,102,105,114,115,116,32,115,101,116,32,111,102,32,100,97,116,97,46,32,84,104,101,32,109,97,116,99,104,32,97,116,116,101,109,112,116,32,116,104,101,110,32,115,117,99,99,101,101,100,115,46,32,73,110,32,116,104,101,32,115,101,99,111,110,100,32,99,97,108,108,32,116,104,101,32>>,{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]},<<32,100,105,115,97,98,108,101,115,32,116,104,101,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,115,107,105,112,115,32,97,108,111,110,103,32,116,111,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,112,97,116,116,101,114,110,32,105,115,32,110,111,119,32,97,112,112,108,105,101,100,32,115,116,97,114,116,105,110,103,32,97,116,32,34,120,34,44,32,97,110,100,32,115,111,32,116,104,101,32,40,42,67,79,77,77,73,84,41,32,99,97,117,115,101,115,32,116,104,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,32,119,105,116,104,111,117,116,32,116,114,121,105,110,103,32,97,110,121,32,111,116,104,101,114,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,115,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,32,99,97,117,115,101,115,32,116,104,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,114,116,105,110,103,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,105,102,32,116,104,101,114,101,32,105,115,32,97,32,108,97,116,101,114,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,116,104,97,116,32,99,97,117,115,101,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,111,32,114,101,97,99,104,32,105,116,58>>]},{pre,[],[{code,[],[<<40,42,80,82,85,78,69,41,32,111,114,32,40,42,80,82,85,78,69,58,78,65,77,69,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,117,110,97,110,99,104,111,114,101,100,44,32,116,104,101,32,110,111,114,109,97,108,32,34,98,117,109,112,97,108,111,110,103,34,32,97,100,118,97,110,99,101,32,116,111,32,116,104,101,32,110,101,120,116,32,115,116,97,114,116,105,110,103,32,99,104,97,114,97,99,116,101,114,32,116,104,101,110,32,111,99,99,117,114,115,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,32,111,99,99,117,114,32,97,115,32,117,115,117,97,108,32,116,111,32,116,104,101,32,108,101,102,116,32,111,102,32,40,42,80,82,85,78,69,41,44,32,98,101,102,111,114,101,32,105,116,32,105,115,32,114,101,97,99,104,101,100,44,32,111,114,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,116,111,32,116,104,101,32,114,105,103,104,116,32,111,102,32,40,42,80,82,85,78,69,41,44,32,98,117,116,32,105,102,32,116,104,101,114,101,32,105,115,32,110,111,32,109,97,116,99,104,32,116,111,32,116,104,101,32,114,105,103,104,116,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,99,97,110,110,111,116,32,99,114,111,115,115,32,40,42,80,82,85,78,69,41,46,32,73,110,32,115,105,109,112,108,101,32,99,97,115,101,115,44,32,116,104,101,32,117,115,101,32,111,102,32,40,42,80,82,85,78,69,41,32,105,115,32,106,117,115,116,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,32,116,111,32,97,110,32,97,116,111,109,105,99,32,103,114,111,117,112,32,111,114,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,44,32,98,117,116,32,116,104,101,114,101,32,97,114,101,32,115,111,109,101,32,117,115,101,115,32,111,102,32,40,42,80,82,85,78,69,41,32,116,104,97,116,32,99,97,110,110,111,116,32,98,101,32,101,120,112,114,101,115,115,101,100,32,105,110,32,97,110,121,32,111,116,104,101,114,32,119,97,121,46,32,73,110,32,97,110,32,97,110,99,104,111,114,101,100,32,112,97,116,116,101,114,110,44,32,40,42,80,82,85,78,69,41,32,104,97,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,40,42,67,79,77,77,73,84,41,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,40,42,80,82,85,78,69,58,78,65,77,69,41,32,105,115,32,116,104,101,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,40,42,77,65,82,75,58,78,65,77,69,41,40,42,80,82,85,78,69,41,46,32,73,116,32,105,115,32,108,105,107,101,32,40,42,77,65,82,75,58,78,65,77,69,41,32,105,110,32,116,104,97,116,32,116,104,101,32,110,97,109,101,32,105,115,32,114,101,109,101,109,98,101,114,101,100,32,102,111,114,32,112,97,115,115,105,110,103,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,46,32,72,111,119,101,118,101,114,44,32,40,42,83,75,73,80,58,78,65,77,69,41,32,115,101,97,114,99,104,101,115,32,111,110,108,121,32,102,111,114,32,110,97,109,101,115,32,115,101,116,32,119,105,116,104,32,40,42,77,65,82,75,41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,102,97,99,116,32,116,104,97,116,32,40,42,80,82,85,78,69,58,78,65,77,69,41,32,114,101,109,101,109,98,101,114,115,32,116,104,101,32,110,97,109,101,32,105,115,32,117,115,101,108,101,115,115,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,44,32,97,115,32,110,97,109,101,115,32,99,97,110,110,111,116,32,98,101,32,114,101,116,114,105,101,118,101,100,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,44,32,119,104,101,110,32,115,112,101,99,105,102,105,101,100,32,119,105,116,104,111,117,116,32,97,32,110,97,109,101,44,32,105,115,32,108,105,107,101,32,40,42,80,82,85,78,69,41,44,32,101,120,99,101,112,116,32,116,104,97,116,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,117,110,97,110,99,104,111,114,101,100,44,32,116,104,101,32,34,98,117,109,112,97,108,111,110,103,34,32,97,100,118,97,110,99,101,32,105,115,32,110,111,116,32,116,111,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,44,32,98,117,116,32,116,111,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,119,104,101,114,101,32,40,42,83,75,73,80,41,32,119,97,115,32,101,110,99,111,117,110,116,101,114,101,100,46>>]},{pre,[],[{code,[],[<<40,42,83,75,73,80,41>>]}]},{p,[],[<<40,42,83,75,73,80,41,32,115,105,103,110,105,102,105,101,115,32,116,104,97,116,32,119,104,97,116,101,118,101,114,32,116,101,120,116,32,119,97,115,32,109,97,116,99,104,101,100,32,108,101,97,100,105,110,103,32,117,112,32,116,111,32,105,116,32,99,97,110,110,111,116,32,98,101,32,112,97,114,116,32,111,102,32,97,32,115,117,99,99,101,115,115,102,117,108,32,109,97,116,99,104,46,32,67,111,110,115,105,100,101,114,58>>]},{pre,[],[{code,[],[<<97,43,40,42,83,75,73,80,41,98>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,97,97,97,97,99,46,46,46,34,44,32,97,102,116,101,114,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,32,97,116,116,101,109,112,116,32,102,97,105,108,115,32,40,115,116,97,114,116,105,110,103,32,97,116,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,115,116,114,105,110,103,41,44,32,116,104,101,32,115,116,97,114,116,105,110,103,32,112,111,105,110,116,32,115,107,105,112,115,32,111,110,32,116,111,32,115,116,97,114,116,32,116,104,101,32,110,101,120,116,32,97,116,116,101,109,112,116,32,97,116,32,34,99,34,46,32,78,111,116,105,99,101,32,116,104,97,116,32,97,32,112,111,115,115,101,115,115,105,118,101,32,113,117,97,110,116,105,102,105,101,114,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,116,104,105,115,32,101,120,97,109,112,108,101,59,32,97,108,116,104,111,117,103,104,32,105,116,32,119,111,117,108,100,32,115,117,112,112,114,101,115,115,32,98,97,99,107,116,114,97,99,107,105,110,103,32,100,117,114,105,110,103,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,32,97,116,116,101,109,112,116,44,32,116,104,101,32,115,101,99,111,110,100,32,97,116,116,101,109,112,116,32,119,111,117,108,100,32,115,116,97,114,116,32,97,116,32,116,104,101,32,115,101,99,111,110,100,32,99,104,97,114,97,99,116,101,114,32,105,110,115,116,101,97,100,32,111,102,32,115,107,105,112,112,105,110,103,32,111,110,32,116,111,32,34,99,34,46>>]},{p,[],[<<87,104,101,110,32,40,42,83,75,73,80,41,32,104,97,115,32,97,110,32,97,115,115,111,99,105,97,116,101,100,32,110,97,109,101,44,32,105,116,115,32,98,101,104,97,118,105,111,114,32,105,115,32,109,111,100,105,102,105,101,100,58>>]},{pre,[],[{code,[],[<<40,42,83,75,73,80,58,78,65,77,69,41>>]}]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,105,115,32,116,114,105,103,103,101,114,101,100,44,32,116,104,101,32,112,114,101,118,105,111,117,115,32,112,97,116,104,32,116,104,114,111,117,103,104,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,115,101,97,114,99,104,101,100,32,102,111,114,32,116,104,101,32,109,111,115,116,32,114,101,99,101,110,116,32,40,42,77,65,82,75,41,32,116,104,97,116,32,104,97,115,32,116,104,101,32,115,97,109,101,32,110,97,109,101,46,32,73,102,32,111,110,101,32,105,115,32,102,111,117,110,100,44,32,116,104,101,32,34,98,117,109,112,97,108,111,110,103,34,32,97,100,118,97,110,99,101,32,105,115,32,116,111,32,116,104,101,32,115,117,98,106,101,99,116,32,112,111,115,105,116,105,111,110,32,116,104,97,116,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,97,116,32,40,42,77,65,82,75,41,32,105,110,115,116,101,97,100,32,111,102,32,116,111,32,119,104,101,114,101,32,40,42,83,75,73,80,41,32,119,97,115,32,101,110,99,111,117,110,116,101,114,101,100,46,32,73,102,32,110,111,32,40,42,77,65,82,75,41,32,119,105,116,104,32,97,32,109,97,116,99,104,105,110,103,32,110,97,109,101,32,105,115,32,102,111,117,110,100,44,32,40,42,83,75,73,80,41,32,105,115,32,105,103,110,111,114,101,100,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,40,42,83,75,73,80,58,78,65,77,69,41,32,115,101,97,114,99,104,101,115,32,111,110,108,121,32,102,111,114,32,110,97,109,101,115,32,115,101,116,32,98,121,32,40,42,77,65,82,75,58,78,65,77,69,41,46,32,73,116,32,105,103,110,111,114,101,115,32,110,97,109,101,115,32,116,104,97,116,32,97,114,101,32,115,101,116,32,98,121,32,40,42,80,82,85,78,69,58,78,65,77,69,41,32,111,114,32,40,42,84,72,69,78,58,78,65,77,69,41,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,118,101,114,98,32,99,97,117,115,101,115,32,97,32,115,107,105,112,32,116,111,32,116,104,101,32,110,101,120,116,32,105,110,110,101,114,109,111,115,116,32,97,108,116,101,114,110,97,116,105,118,101,32,119,104,101,110,32,98,97,99,107,116,114,97,99,107,105,110,103,32,114,101,97,99,104,101,115,32,105,116,46,32,84,104,97,116,32,105,115,44,32,105,116,32,99,97,110,99,101,108,115,32,97,110,121,32,102,117,114,116,104,101,114,32,98,97,99,107,116,114,97,99,107,105,110,103,32,119,105,116,104,105,110,32,116,104,101,32,99,117,114,114,101,110,116,32,97,108,116,101,114,110,97,116,105,118,101,46>>]},{pre,[],[{code,[],[<<40,42,84,72,69,78,41,32,111,114,32,40,42,84,72,69,78,58,78,65,77,69,41>>]}]},{p,[],[<<84,104,101,32,118,101,114,98,32,110,97,109,101,32,99,111,109,101,115,32,102,114,111,109,32,116,104,101,32,111,98,115,101,114,118,97,116,105,111,110,32,116,104,97,116,32,105,116,32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,97,32,112,97,116,116,101,114,110,45,98,97,115,101,100,32,105,102,45,116,104,101,110,45,101,108,115,101,32,98,108,111,99,107,58>>]},{pre,[],[{code,[],[<<40,32,67,79,78,68,49,32,40,42,84,72,69,78,41,32,70,79,79,32,124,32,67,79,78,68,50,32,40,42,84,72,69,78,41,32,66,65,82,32,124,32,67,79,78,68,51,32,40,42,84,72,69,78,41,32,66,65,90,32,41,32,46,46,46>>]}]},{p,[],[<<73,102,32,116,104,101,32,67,79,78,68,49,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,44,32,70,79,79,32,105,115,32,116,114,105,101,100,32,40,97,110,100,32,112,111,115,115,105,98,108,121,32,102,117,114,116,104,101,114,32,105,116,101,109,115,32,97,102,116,101,114,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,103,114,111,117,112,32,105,102,32,70,79,79,32,115,117,99,99,101,101,100,115,41,46,32,79,110,32,102,97,105,108,117,114,101,44,32,116,104,101,32,109,97,116,99,104,101,114,32,115,107,105,112,115,32,116,111,32,116,104,101,32,115,101,99,111,110,100,32,97,108,116,101,114,110,97,116,105,118,101,32,97,110,100,32,116,114,105,101,115,32,67,79,78,68,50,44,32,119,105,116,104,111,117,116,32,98,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,67,79,78,68,49,46,32,73,102,32,116,104,97,116,32,115,117,99,99,101,101,100,115,32,97,110,100,32,66,65,82,32,102,97,105,108,115,44,32,67,79,78,68,51,32,105,115,32,116,114,105,101,100,46,32,73,102,32,66,65,90,32,116,104,101,110,32,102,97,105,108,115,44,32,116,104,101,114,101,32,97,114,101,32,110,111,32,109,111,114,101,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,115,111,32,116,104,101,114,101,32,105,115,32,97,32,98,97,99,107,116,114,97,99,107,32,116,111,32,119,104,97,116,101,118,101,114,32,99,97,109,101,32,98,101,102,111,114,101,32,116,104,101,32,101,110,116,105,114,101,32,103,114,111,117,112,46,32,73,102,32,40,42,84,72,69,78,41,32,105,115,32,110,111,116,32,105,110,115,105,100,101,32,97,110,32,97,108,116,101,114,110,97,116,105,111,110,44,32,105,116,32,97,99,116,115,32,108,105,107,101,32,40,42,80,82,85,78,69,41,46>>]},{p,[],[<<84,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,40,42,84,72,69,78,58,78,65,77,69,41,32,105,115,32,116,104,101,32,110,111,116,32,116,104,101,32,115,97,109,101,32,97,115,32,40,42,77,65,82,75,58,78,65,77,69,41,40,42,84,72,69,78,41,46,32,73,116,32,105,115,32,108,105,107,101,32,40,42,77,65,82,75,58,78,65,77,69,41,32,105,110,32,116,104,97,116,32,116,104,101,32,110,97,109,101,32,105,115,32,114,101,109,101,109,98,101,114,101,100,32,102,111,114,32,112,97,115,115,105,110,103,32,98,97,99,107,32,116,111,32,116,104,101,32,99,97,108,108,101,114,46,32,72,111,119,101,118,101,114,44,32,40,42,83,75,73,80,58,78,65,77,69,41,32,115,101,97,114,99,104,101,115,32,111,110,108,121,32,102,111,114,32,110,97,109,101,115,32,115,101,116,32,119,105,116,104,32,40,42,77,65,82,75,41,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,101,32,102,97,99,116,32,116,104,97,116,32,40,42,84,72,69,78,58,78,65,77,69,41,32,114,101,109,101,109,98,101,114,115,32,116,104,101,32,110,97,109,101,32,105,115,32,117,115,101,108,101,115,115,32,116,111,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,103,114,97,109,109,101,114,44,32,97,115,32,110,97,109,101,115,32,99,97,110,110,111,116,32,98,101,32,114,101,116,114,105,101,118,101,100,46>>]}]},{p,[],[<<65,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,99,111,110,116,97,105,110,32,97,32,124,32,99,104,97,114,97,99,116,101,114,32,105,115,32,106,117,115,116,32,97,32,112,97,114,116,32,111,102,32,116,104,101,32,101,110,99,108,111,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,59,32,105,116,32,105,115,32,110,111,116,32,97,32,110,101,115,116,101,100,32,97,108,116,101,114,110,97,116,105,111,110,32,119,105,116,104,32,111,110,108,121,32,111,110,101,32,97,108,116,101,114,110,97,116,105,118,101,46,32,84,104,101,32,101,102,102,101,99,116,32,111,102,32,40,42,84,72,69,78,41,32,101,120,116,101,110,100,115,32,98,101,121,111,110,100,32,115,117,99,104,32,97,32,115,117,98,112,97,116,116,101,114,110,32,116,111,32,116,104,101,32,101,110,99,108,111,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,101,114,101,32,65,44,32,66,44,32,97,110,100,32,115,111,32,111,110,44,32,97,114,101,32,99,111,109,112,108,101,120,32,112,97,116,116,101,114,110,32,102,114,97,103,109,101,110,116,115,32,116,104,97,116,32,100,111,32,110,111,116,32,99,111,110,116,97,105,110,32,97,110,121,32,124,32,99,104,97,114,97,99,116,101,114,115,32,97,116,32,116,104,105,115,32,108,101,118,101,108,58>>]},{pre,[],[{code,[],[<<65,32,40,66,40,42,84,72,69,78,41,67,41,32,124,32,68>>]}]},{p,[],[<<73,102,32,65,32,97,110,100,32,66,32,97,114,101,32,109,97,116,99,104,101,100,44,32,98,117,116,32,116,104,101,114,101,32,105,115,32,97,32,102,97,105,108,117,114,101,32,105,110,32,67,44,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,116,32,98,97,99,107,116,114,97,99,107,32,105,110,116,111,32,65,59,32,105,110,115,116,101,97,100,32,105,116,32,109,111,118,101,115,32,116,111,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,44,32,116,104,97,116,32,105,115,44,32,68,46,32,72,111,119,101,118,101,114,44,32,105,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,99,111,110,116,97,105,110,105,110,103,32,40,42,84,72,69,78,41,32,105,115,32,103,105,118,101,110,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,44,32,105,116,32,98,101,104,97,118,101,115,32,100,105,102,102,101,114,101,110,116,108,121,58>>]},{pre,[],[{code,[],[<<65,32,40,66,40,42,84,72,69,78,41,67,32,124,32,40,42,70,65,73,76,41,41,32,124,32,68>>]}]},{p,[],[<<84,104,101,32,101,102,102,101,99,116,32,111,102,32,40,42,84,72,69,78,41,32,105,115,32,110,111,119,32,99,111,110,102,105,110,101,100,32,116,111,32,116,104,101,32,105,110,110,101,114,32,115,117,98,112,97,116,116,101,114,110,46,32,65,102,116,101,114,32,97,32,102,97,105,108,117,114,101,32,105,110,32,67,44,32,109,97,116,99,104,105,110,103,32,109,111,118,101,115,32,116,111,32,40,42,70,65,73,76,41,44,32,119,104,105,99,104,32,99,97,117,115,101,115,32,116,104,101,32,119,104,111,108,101,32,115,117,98,112,97,116,116,101,114,110,32,116,111,32,102,97,105,108,44,32,97,115,32,116,104,101,114,101,32,97,114,101,32,110,111,32,109,111,114,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,116,111,32,116,114,121,46,32,73,110,32,116,104,105,115,32,99,97,115,101,44,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,119,32,98,97,99,107,116,114,97,99,107,32,105,110,116,111,32,65,46>>]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,110,111,116,32,99,111,110,115,105,100,101,114,101,100,32,97,115,32,104,97,118,105,110,103,32,116,119,111,32,97,108,116,101,114,110,97,116,105,118,101,115,44,32,97,115,32,111,110,108,121,32,111,110,101,32,105,115,32,101,118,101,114,32,117,115,101,100,46,32,84,104,97,116,32,105,115,44,32,116,104,101,32,124,32,99,104,97,114,97,99,116,101,114,32,105,110,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,104,97,115,32,97,32,100,105,102,102,101,114,101,110,116,32,109,101,97,110,105,110,103,46,32,73,103,110,111,114,105,110,103,32,119,104,105,116,101,115,112,97,99,101,44,32,99,111,110,115,105,100,101,114,58>>]},{pre,[],[{code,[],[<<94,46,42,63,32,40,63,40,63,61,97,41,32,97,32,124,32,98,40,42,84,72,69,78,41,99,32,41>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,98,97,34,44,32,116,104,105,115,32,112,97,116,116,101,114,110,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,46,32,65,115,32,46,42,63,32,105,115,32,117,110,103,114,101,101,100,121,44,32,105,116,32,105,110,105,116,105,97,108,108,121,32,109,97,116,99,104,101,115,32,122,101,114,111,32,99,104,97,114,97,99,116,101,114,115,46,32,84,104,101,32,99,111,110,100,105,116,105,111,110,32,40,63,61,97,41,32,116,104,101,110,32,102,97,105,108,115,44,32,116,104,101,32,99,104,97,114,97,99,116,101,114,32,34,98,34,32,105,115,32,109,97,116,99,104,101,100,44,32,98,117,116,32,34,99,34,32,105,115,32,110,111,116,46,32,65,116,32,116,104,105,115,32,112,111,105,110,116,44,32,109,97,116,99,104,105,110,103,32,100,111,101,115,32,110,111,116,32,98,97,99,107,116,114,97,99,107,32,116,111,32,46,42,63,32,97,115,32,99,97,110,32,112,101,114,104,97,112,115,32,98,101,32,101,120,112,101,99,116,101,100,32,102,114,111,109,32,116,104,101,32,112,114,101,115,101,110,99,101,32,111,102,32,116,104,101,32,124,32,99,104,97,114,97,99,116,101,114,46,32,84,104,101,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,112,97,114,116,32,111,102,32,116,104,101,32,115,105,110,103,108,101,32,97,108,116,101,114,110,97,116,105,118,101,32,116,104,97,116,32,99,111,109,112,114,105,115,101,115,32,116,104,101,32,119,104,111,108,101,32,112,97,116,116,101,114,110,44,32,97,110,100,32,115,111,32,116,104,101,32,109,97,116,99,104,32,102,97,105,108,115,46,32,40,73,102,32,116,104,101,114,101,32,119,97,115,32,97,32,98,97,99,107,116,114,97,99,107,32,105,110,116,111,32,46,42,63,44,32,97,108,108,111,119,105,110,103,32,105,116,32,116,111,32,109,97,116,99,104,32,34,98,34,44,32,116,104,101,32,109,97,116,99,104,32,119,111,117,108,100,32,115,117,99,99,101,101,100,46,41>>]},{p,[],[<<84,104,101,32,118,101,114,98,115,32,100,101,115,99,114,105,98,101,100,32,97,98,111,118,101,32,112,114,111,118,105,100,101,32,102,111,117,114,32,100,105,102,102,101,114,101,110,116,32,34,115,116,114,101,110,103,116,104,115,34,32,111,102,32,99,111,110,116,114,111,108,32,119,104,101,110,32,115,117,98,115,101,113,117,101,110,116,32,109,97,116,99,104,105,110,103,32,102,97,105,108,115,58>>]},{ul,[],[{li,[],[{p,[],[<<40,42,84,72,69,78,41,32,105,115,32,116,104,101,32,119,101,97,107,101,115,116,44,32,99,97,114,114,121,105,110,103,32,111,110,32,116,104,101,32,109,97,116,99,104,32,97,116,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,46>>]}]},{li,[],[{p,[],[<<40,42,80,82,85,78,69,41,32,99,111,109,101,115,32,110,101,120,116,44,32,102,97,105,108,115,32,116,104,101,32,109,97,116,99,104,32,97,116,32,116,104,101,32,99,117,114,114,101,110,116,32,115,116,97,114,116,105,110,103,32,112,111,115,105,116,105,111,110,44,32,98,117,116,32,97,108,108,111,119,115,32,97,110,32,97,100,118,97,110,99,101,32,116,111,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40,102,111,114,32,97,110,32,117,110,97,110,99,104,111,114,101,100,32,112,97,116,116,101,114,110,41,46>>]}]},{li,[],[{p,[],[<<40,42,83,75,73,80,41,32,105,115,32,115,105,109,105,108,97,114,44,32,101,120,99,101,112,116,32,116,104,97,116,32,116,104,101,32,97,100,118,97,110,99,101,32,99,97,110,32,98,101,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,99,104,97,114,97,99,116,101,114,46>>]}]},{li,[],[{p,[],[<<40,42,67,79,77,77,73,84,41,32,105,115,32,116,104,101,32,115,116,114,111,110,103,101,115,116,44,32,99,97,117,115,105,110,103,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46>>]}]}]},{p,[],[{em,[],[<<77,111,114,101,32,116,104,97,110,32,79,110,101,32,66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98>>]}]},{p,[],[<<73,102,32,109,111,114,101,32,116,104,97,110,32,111,110,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,32,105,115,32,112,114,101,115,101,110,116,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,116,104,101,32,111,110,101,32,116,104,97,116,32,105,115,32,98,97,99,107,116,114,97,99,107,101,100,32,111,110,116,111,32,102,105,114,115,116,32,97,99,116,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,44,32,119,104,101,114,101,32,65,44,32,66,44,32,97,110,100,32,115,111,32,111,110,44,32,97,114,101,32,99,111,109,112,108,101,120,32,112,97,116,116,101,114,110,32,102,114,97,103,109,101,110,116,115,58>>]},{pre,[],[{code,[],[<<40,65,40,42,67,79,77,77,73,84,41,66,40,42,84,72,69,78,41,67,124,65,66,68,41>>]}]},{p,[],[<<73,102,32,65,32,109,97,116,99,104,101,115,32,98,117,116,32,66,32,102,97,105,108,115,44,32,116,104,101,32,98,97,99,107,116,114,97,99,107,32,116,111,32,40,42,67,79,77,77,73,84,41,32,99,97,117,115,101,115,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46,32,72,111,119,101,118,101,114,44,32,105,102,32,65,32,97,110,100,32,66,32,109,97,116,99,104,44,32,98,117,116,32,67,32,102,97,105,108,115,44,32,116,104,101,32,98,97,99,107,116,114,97,99,107,32,116,111,32,40,42,84,72,69,78,41,32,99,97,117,115,101,115,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,32,40,65,66,68,41,32,116,111,32,98,101,32,116,114,105,101,100,46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,105,115,32,99,111,110,115,105,115,116,101,110,116,44,32,98,117,116,32,105,115,32,110,111,116,32,97,108,119,97,121,115,32,116,104,101,32,115,97,109,101,32,97,115,32,105,110,32,80,101,114,108,46,32,73,116,32,109,101,97,110,115,32,116,104,97,116,32,105,102,32,116,119,111,32,111,114,32,109,111,114,101,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,97,112,112,101,97,114,32,105,110,32,115,117,99,99,101,115,115,105,111,110,44,32,116,104,101,32,108,97,115,116,32,111,102,32,116,104,101,109,32,104,97,115,32,110,111,32,101,102,102,101,99,116,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<46,46,46,40,42,67,79,77,77,73,84,41,40,42,80,82,85,78,69,41,46,46,46>>]}]},{p,[],[<<73,102,32,116,104,101,114,101,32,105,115,32,97,32,109,97,116,99,104,105,110,103,32,102,97,105,108,117,114,101,32,116,111,32,116,104,101,32,114,105,103,104,116,44,32,98,97,99,107,116,114,97,99,107,105,110,103,32,111,110,116,111,32,40,42,80,82,85,78,69,41,32,99,97,117,115,101,115,32,105,116,32,116,111,32,98,101,32,116,114,105,103,103,101,114,101,100,44,32,97,110,100,32,105,116,115,32,97,99,116,105,111,110,32,105,115,32,116,97,107,101,110,46,32,84,104,101,114,101,32,99,97,110,32,110,101,118,101,114,32,98,101,32,97,32,98,97,99,107,116,114,97,99,107,32,111,110,116,111,32,40,42,67,79,77,77,73,84,41,46>>]},{p,[],[{em,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115,32,105,110,32,82,101,112,101,97,116,101,100,32,71,114,111,117,112,115>>]}]},{p,[],[<<80,67,82,69,32,100,105,102,102,101,114,115,32,102,114,111,109,32,80,101,114,108,32,105,110,32,105,116,115,32,104,97,110,100,108,105,110,103,32,111,102,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,105,110,32,114,101,112,101,97,116,101,100,32,103,114,111,117,112,115,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,58>>]},{pre,[],[{code,[],[<<47,40,97,40,42,67,79,77,77,73,84,41,98,41,43,97,99,47>>]}]},{p,[],[<<73,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,34,97,98,97,99,34,44,32,80,101,114,108,32,109,97,116,99,104,101,115,44,32,98,117,116,32,80,67,82,69,32,102,97,105,108,115,32,98,101,99,97,117,115,101,32,116,104,101,32,40,42,67,79,77,77,73,84,41,32,105,110,32,116,104,101,32,115,101,99,111,110,100,32,114,101,112,101,97,116,32,111,102,32,116,104,101,32,103,114,111,117,112,32,97,99,116,115,46>>]},{p,[],[{em,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115,32,105,110,32,65,115,115,101,114,116,105,111,110,115>>]}]},{p,[],[<<40,42,70,65,73,76,41,32,105,110,32,97,110,32,97,115,115,101,114,116,105,111,110,32,104,97,115,32,105,116,115,32,110,111,114,109,97,108,32,101,102,102,101,99,116,58,32,105,116,32,102,111,114,99,101,115,32,97,110,32,105,109,109,101,100,105,97,116,101,32,98,97,99,107,116,114,97,99,107,46>>]},{p,[],[<<40,42,65,67,67,69,80,84,41,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,99,97,117,115,101,115,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,116,111,32,115,117,99,99,101,101,100,32,119,105,116,104,111,117,116,32,97,110,121,32,102,117,114,116,104,101,114,32,112,114,111,99,101,115,115,105,110,103,46,32,73,110,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,44,32,40,42,65,67,67,69,80,84,41,32,99,97,117,115,101,115,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,116,111,32,102,97,105,108,32,119,105,116,104,111,117,116,32,97,110,121,32,102,117,114,116,104,101,114,32,112,114,111,99,101,115,115,105,110,103,46>>]},{p,[],[<<84,104,101,32,111,116,104,101,114,32,98,97,99,107,116,114,97,99,107,105,110,103,32,118,101,114,98,115,32,97,114,101,32,110,111,116,32,116,114,101,97,116,101,100,32,115,112,101,99,105,97,108,108,121,32,105,102,32,116,104,101,121,32,97,112,112,101,97,114,32,105,110,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,46,32,73,110,32,112,97,114,116,105,99,117,108,97,114,44,32,40,42,84,72,69,78,41,32,115,107,105,112,115,32,116,111,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,105,110,110,101,114,109,111,115,116,32,101,110,99,108,111,115,105,110,103,32,103,114,111,117,112,32,116,104,97,116,32,104,97,115,32,97,108,116,101,114,110,97,116,105,111,110,115,44,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32,116,104,105,115,32,105,115,32,119,105,116,104,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,46>>]},{p,[],[<<78,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,115,32,97,114,101,44,32,104,111,119,101,118,101,114,44,32,100,105,102,102,101,114,101,110,116,44,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,99,104,97,110,103,105,110,103,32,97,32,112,111,115,105,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,105,110,116,111,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,99,104,97,110,103,101,115,32,105,116,115,32,114,101,115,117,108,116,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,40,42,67,79,77,77,73,84,41,44,32,40,42,83,75,73,80,41,44,32,111,114,32,40,42,80,82,85,78,69,41,32,99,97,117,115,101,115,32,97,32,110,101,103,97,116,105,118,101,32,97,115,115,101,114,116,105,111,110,32,116,111,32,98,101,32,116,114,117,101,44,32,119,105,116,104,111,117,116,32,99,111,110,115,105,100,101,114,105,110,103,32,97,110,121,32,102,117,114,116,104,101,114,32,97,108,116,101,114,110,97,116,105,118,101,32,98,114,97,110,99,104,101,115,32,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,46,32,66,97,99,107,116,114,97,99,107,105,110,103,32,105,110,116,111,32,40,42,84,72,69,78,41,32,99,97,117,115,101,115,32,105,116,32,116,111,32,115,107,105,112,32,116,111,32,116,104,101,32,110,101,120,116,32,101,110,99,108,111,115,105,110,103,32,97,108,116,101,114,110,97,116,105,118,101,32,119,105,116,104,105,110,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,40,116,104,101,32,110,111,114,109,97,108,32,98,101,104,97,118,105,111,114,41,44,32,98,117,116,32,105,102,32,116,104,101,32,97,115,115,101,114,116,105,111,110,32,100,111,101,115,32,110,111,116,32,104,97,118,101,32,115,117,99,104,32,97,110,32,97,108,116,101,114,110,97,116,105,118,101,44,32,40,42,84,72,69,78,41,32,98,101,104,97,118,101,115,32,108,105,107,101,32,40,42,80,82,85,78,69,41,46>>]},{p,[],[{em,[],[<<66,97,99,107,116,114,97,99,107,105,110,103,32,86,101,114,98,115,32,105,110,32,83,117,98,114,111,117,116,105,110,101,115>>]}]},{p,[],[<<84,104,101,115,101,32,98,101,104,97,118,105,111,114,115,32,111,99,99,117,114,32,114,101,103,97,114,100,108,101,115,115,32,105,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,99,97,108,108,101,100,32,114,101,99,117,114,115,105,118,101,108,121,46,32,84,104,101,32,116,114,101,97,116,109,101,110,116,32,111,102,32,115,117,98,114,111,117,116,105,110,101,115,32,105,110,32,80,101,114,108,32,105,115,32,100,105,102,102,101,114,101,110,116,32,105,110,32,115,111,109,101,32,99,97,115,101,115,46>>]},{ul,[],[{li,[],[{p,[],[<<40,42,70,65,73,76,41,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,104,97,115,32,105,116,115,32,110,111,114,109,97,108,32,101,102,102,101,99,116,58,32,105,116,32,102,111,114,99,101,115,32,97,110,32,105,109,109,101,100,105,97,116,101,32,98,97,99,107,116,114,97,99,107,46>>]}]},{li,[],[{p,[],[<<40,42,65,67,67,69,80,84,41,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,117,115,101,115,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,97,116,99,104,32,116,111,32,115,117,99,99,101,101,100,32,119,105,116,104,111,117,116,32,97,110,121,32,102,117,114,116,104,101,114,32,112,114,111,99,101,115,115,105,110,103,46,32,77,97,116,99,104,105,110,103,32,116,104,101,110,32,99,111,110,116,105,110,117,101,115,32,97,102,116,101,114,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,99,97,108,108,46>>]}]},{li,[],[{p,[],[<<40,42,67,79,77,77,73,84,41,44,32,40,42,83,75,73,80,41,44,32,97,110,100,32,40,42,80,82,85,78,69,41,32,105,110,32,97,32,115,117,98,112,97,116,116,101,114,110,32,99,97,108,108,101,100,32,97,115,32,97,32,115,117,98,114,111,117,116,105,110,101,32,99,97,117,115,101,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46>>]}]},{li,[],[{p,[],[<<40,42,84,72,69,78,41,32,115,107,105,112,115,32,116,111,32,116,104,101,32,110,101,120,116,32,97,108,116,101,114,110,97,116,105,118,101,32,105,110,32,116,104,101,32,105,110,110,101,114,109,111,115,116,32,101,110,99,108,111,115,105,110,103,32,103,114,111,117,112,32,119,105,116,104,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,116,104,97,116,32,104,97,115,32,97,108,116,101,114,110,97,116,105,118,101,115,46,32,73,102,32,116,104,101,114,101,32,105,115,32,110,111,32,115,117,99,104,32,103,114,111,117,112,32,119,105,116,104,105,110,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,44,32,40,42,84,72,69,78,41,32,99,97,117,115,101,115,32,116,104,101,32,115,117,98,114,111,117,116,105,110,101,32,109,97,116,99,104,32,116,111,32,102,97,105,108,46>>]}]}]}]},#{name => <<114,101>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,114,101,46,120,109,108],types => #{{compile_option,0} => {attribute,{27,2},type,{compile_option,{type,{27,27},union,[{atom,{27,27},unicode},{atom,{27,37},anchored},{atom,{27,48},caseless},{atom,{27,59},dollar_endonly},{atom,{28,27},dotall},{atom,{28,36},extended},{atom,{28,47},firstline},{atom,{28,59},multiline},{atom,{29,27},no_auto_capture},{atom,{29,45},dupnames},{atom,{29,56},ungreedy},{type,{30,27},tuple,[{atom,{30,28},newline},{user_type,{30,37},nl_spec,[]}]},{atom,{31,27},bsr_anycrlf},{atom,{31,41},bsr_unicode},{atom,{32,27},no_start_optimize},{atom,{32,47},ucp},{atom,{32,53},never_utf}]},[]}},{mp,0} => {attribute,{23,2},type,{mp,{type,{23,15},tuple,[{atom,{23,16},re_pattern},{var,{23,28},'_'},{var,{23,31},'_'},{var,{23,34},'_'},{var,{23,37},'_'}]},[]}},{nl_spec,0} => {attribute,{25,2},type,{nl_spec,{type,{25,20},union,[{atom,{25,20},cr},{atom,{25,25},crlf},{atom,{25,32},lf},{atom,{25,37},anycrlf},{atom,{25,47},any}]},[]}}}},[{{function,grun,3},[{file,[114,101,46,101,114,108]},{location,0}],[<<103,114,117,110,47,51>>],hidden,#{}},{{function,internal_run,4},[{file,[114,101,46,101,114,108]},{location,0}],[<<105,110,116,101,114,110,97,108,95,114,117,110,47,52>>],hidden,#{}},{{function,ucompile,2},[{file,[114,101,46,101,114,108]},{location,0}],[<<117,99,111,109,112,105,108,101,47,50>>],hidden,#{}},{{function,urun,3},[{file,[114,101,46,101,114,108]},{location,0}],[<<117,114,117,110,47,51>>],hidden,#{}},{{function,version,0},[{file,[114,101,46,101,114,108]},{location,40}],[<<118,101,114,115,105,111,110,47,48>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,111,102,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,97,32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,80,67,82,69,32,118,101,114,115,105,111,110,32,111,102,32,116,104,101,32,115,121,115,116,101,109,32,116,104,97,116,32,119,97,115,32,117,115,101,100,32,105,110,32,116,104,101,32,69,114,108,97,110,103,47,79,84,80,32,99,111,109,112,105,108,97,116,105,111,110,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,56,49>>,signature => [{attribute,{40,2},spec,{{version,0},[{type,{40,14},'fun',[{type,{40,14},product,[]},{type,{40,20},binary,[]}]}]}}],since => <<79,84,80,32,50,48,46,48>>}},{{function,compile,1},[{file,[114,101,46,101,114,108]},{location,49}],[<<99,111,109,112,105,108,101,47,49>>],#{<<101,110>> => [{p,[],[<<84,104,101,32,115,97,109,101,32,97,115,32>>,{code,[],[<<99,111,109,112,105,108,101,40,82,101,103,101,120,112,44,91,93,41>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,56,57>>,signature => [{attribute,{49,2},spec,{{compile,1},[{type,{49,14},bounded_fun,[{type,{49,14},'fun',[{type,{49,14},product,[{var,{49,15},'Regexp'}]},{type,{49,26},union,[{type,{49,26},tuple,[{atom,{49,27},ok},{var,{49,31},'MP'}]},{type,{49,37},tuple,[{atom,{49,38},error},{var,{49,45},'ErrSpec'}]}]}]},[{type,{50,7},constraint,[{atom,{50,7},is_subtype},[{var,{50,7},'Regexp'},{type,{50,17},iodata,[]}]]},{type,{51,7},constraint,[{atom,{51,7},is_subtype},[{var,{51,7},'MP'},{user_type,{51,13},mp,[]}]]},{type,{52,7},constraint,[{atom,{52,7},is_subtype},[{var,{52,7},'ErrSpec'},{type,{52,18},tuple,[{ann_type,{52,19},[{var,{52,19},'ErrString'},{type,{52,32},string,[]}]},{ann_type,{52,42},[{var,{52,42},'Position'},{type,{52,54},non_neg_integer,[]}]}]}]]}]]}]}}]}},{{function,compile,2},[{file,[114,101,46,101,114,108]},{location,57}],[<<99,111,109,112,105,108,101,47,50>>],#{<<101,110>> => [{p,[],[<<67,111,109,112,105,108,101,115,32,97,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,119,105,116,104,32,116,104,101,32,115,121,110,116,97,120,32,100,101,115,99,114,105,98,101,100,32,98,101,108,111,119,44,32,105,110,116,111,32,97,110,32,105,110,116,101,114,110,97,108,32,102,111,114,109,97,116,32,116,111,32,98,101,32,117,115,101,100,32,108,97,116,101,114,32,97,115,32,97,32,112,97,114,97,109,101,116,101,114,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<46>>]},{p,[],[<<67,111,109,112,105,108,105,110,103,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,98,101,102,111,114,101,32,109,97,116,99,104,105,110,103,32,105,115,32,117,115,101,102,117,108,32,105,102,32,116,104,101,32,115,97,109,101,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,109,97,116,99,104,105,110,103,32,97,103,97,105,110,115,116,32,109,117,108,116,105,112,108,101,32,115,117,98,106,101,99,116,115,32,100,117,114,105,110,103,32,116,104,101,32,108,105,102,101,116,105,109,101,32,111,102,32,116,104,101,32,112,114,111,103,114,97,109,46,32,67,111,109,112,105,108,105,110,103,32,111,110,99,101,32,97,110,100,32,101,120,101,99,117,116,105,110,103,32,109,97,110,121,32,116,105,109,101,115,32,105,115,32,102,97,114,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,99,111,109,112,105,108,105,110,103,32,101,97,99,104,32,116,105,109,101,32,111,110,101,32,119,97,110,116,115,32,116,111,32,109,97,116,99,104,46>>]},{p,[],[<<87,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<44,32,111,116,104,101,114,119,105,115,101,32,97,115,32,97,110,121,32,118,97,108,105,100,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<46>>]},{a,[{id,<<99,111,109,112,105,108,101,95,111,112,116,105,111,110,115>>}],[]},{p,[],[<<79,112,116,105,111,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<117,110,105,99,111,100,101>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<32,97,110,100,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,99,111,100,101,32,105,115,32,116,111,32,98,101,32,114,117,110,32,97,103,97,105,110,115,116,32,97,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<32,115,117,98,106,101,99,116,46,32,65,108,115,111,32,99,111,110,115,105,100,101,114,32,111,112,116,105,111,110,32>>,{code,[],[<<117,99,112>>]},<<32,119,104,101,110,32,117,115,105,110,103,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},{dt,[],[{code,[],[<<97,110,99,104,111,114,101,100>>]}]},{dd,[],[{p,[],[<<84,104,101,32,112,97,116,116,101,114,110,32,105,115,32,102,111,114,99,101,100,32,116,111,32,98,101,32,34,97,110,99,104,111,114,101,100,34,44,32,116,104,97,116,32,105,115,44,32,105,116,32,105,115,32,99,111,110,115,116,114,97,105,110,101,100,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,97,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,112,111,105,110,116,32,105,110,32,116,104,101,32,115,116,114,105,110,103,32,116,104,97,116,32,105,115,32,115,101,97,114,99,104,101,100,32,40,116,104,101,32,34,115,117,98,106,101,99,116,32,115,116,114,105,110,103,34,41,46,32,84,104,105,115,32,101,102,102,101,99,116,32,99,97,110,32,97,108,115,111,32,98,101,32,97,99,104,105,101,118,101,100,32,98,121,32,97,112,112,114,111,112,114,105,97,116,101,32,99,111,110,115,116,114,117,99,116,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,105,116,115,101,108,102,46>>]}]},{dt,[],[{code,[],[<<99,97,115,101,108,101,115,115>>]}]},{dd,[],[{p,[],[<<76,101,116,116,101,114,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,32,98,111,116,104,32,117,112,112,101,114,99,97,115,101,32,97,110,100,32,108,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,115,46,32,73,116,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,105>>]},<<32,97,110,100,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,105,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,85,112,112,101,114,99,97,115,101,32,97,110,100,32,108,111,119,101,114,99,97,115,101,32,108,101,116,116,101,114,115,32,97,114,101,32,100,101,102,105,110,101,100,32,97,115,32,105,110,32,116,104,101,32,73,83,79,32,56,56,53,57,45,49,32,99,104,97,114,97,99,116,101,114,32,115,101,116,46>>]}]},{dt,[],[{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]}]},{dd,[],[{p,[],[<<65,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,87,105,116,104,111,117,116,32,116,104,105,115,32,111,112,116,105,111,110,44,32,97,32,100,111,108,108,97,114,32,97,108,115,111,32,109,97,116,99,104,101,115,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,97,32,110,101,119,108,105,110,101,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,40,98,117,116,32,110,111,116,32,98,101,102,111,114,101,32,97,110,121,32,111,116,104,101,114,32,110,101,119,108,105,110,101,115,41,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,105,103,110,111,114,101,100,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,46,32,84,104,101,114,101,32,105,115,32,110,111,32,101,113,117,105,118,97,108,101,110,116,32,111,112,116,105,111,110,32,105,110,32,80,101,114,108,44,32,97,110,100,32,105,116,32,99,97,110,110,111,116,32,98,101,32,115,101,116,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,46>>]}]},{dt,[],[{code,[],[<<100,111,116,97,108,108>>]}]},{dd,[],[{p,[],[<<65,32,100,111,116,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,97,108,108,32,99,104,97,114,97,99,116,101,114,115,44,32,105,110,99,108,117,100,105,110,103,32,116,104,111,115,101,32,105,110,100,105,99,97,116,105,110,103,32,110,101,119,108,105,110,101,46,32,87,105,116,104,111,117,116,32,105,116,44,32,97,32,100,111,116,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,32,119,104,101,110,32,116,104,101,32,99,117,114,114,101,110,116,32,112,111,115,105,116,105,111,110,32,105,115,32,97,116,32,97,32,110,101,119,108,105,110,101,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,115>>]},<<32,97,110,100,32,105,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,115,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,65,32,110,101,103,97,116,105,118,101,32,99,108,97,115,115,44,32,115,117,99,104,32,97,115,32>>,{code,[],[<<91,94,97,93>>]},<<44,32,97,108,119,97,121,115,32,109,97,116,99,104,101,115,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,44,32,105,110,100,101,112,101,110,100,101,110,116,32,111,102,32,116,104,101,32,115,101,116,116,105,110,103,32,111,102,32,116,104,105,115,32,111,112,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<101,120,116,101,110,100,101,100>>]}]},{dd,[],[{p,[],[<<73,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,101,116,44,32,109,111,115,116,32,119,104,105,116,101,32,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,97,114,101,32,116,111,116,97,108,108,121,32,105,103,110,111,114,101,100,32,101,120,99,101,112,116,32,119,104,101,110,32,101,115,99,97,112,101,100,32,111,114,32,105,110,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,46,32,72,111,119,101,118,101,114,44,32,119,104,105,116,101,32,115,112,97,99,101,32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,32,119,105,116,104,105,110,32,115,101,113,117,101,110,99,101,115,32,115,117,99,104,32,97,115,32>>,{code,[],[<<40,63,62>>]},<<32,116,104,97,116,32,105,110,116,114,111,100,117,99,101,32,118,97,114,105,111,117,115,32,112,97,114,101,110,116,104,101,115,105,122,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,110,111,114,32,119,105,116,104,105,110,32,97,32,110,117,109,101,114,105,99,97,108,32,113,117,97,110,116,105,102,105,101,114,32,115,117,99,104,32,97,115,32>>,{code,[],[<<123,49,44,51,125>>]},<<46,32,72,111,119,101,118,101,114,44,32,105,103,110,111,114,97,98,108,101,32,119,104,105,116,101,32,115,112,97,99,101,32,105,115,32,112,101,114,109,105,116,116,101,100,32,98,101,116,119,101,101,110,32,97,110,32,105,116,101,109,32,97,110,100,32,97,32,102,111,108,108,111,119,105,110,103,32,113,117,97,110,116,105,102,105,101,114,32,97,110,100,32,98,101,116,119,101,101,110,32,97,32,113,117,97,110,116,105,102,105,101,114,32,97,110,100,32,97,32,102,111,108,108,111,119,105,110,103,32,43,32,116,104,97,116,32,105,110,100,105,99,97,116,101,115,32,112,111,115,115,101,115,115,105,118,101,110,101,115,115,46>>]},{p,[],[<<87,104,105,116,101,32,115,112,97,99,101,32,100,105,100,32,110,111,116,32,117,115,101,100,32,116,111,32,105,110,99,108,117,100,101,32,116,104,101,32,86,84,32,99,104,97,114,97,99,116,101,114,32,40,99,111,100,101,32,49,49,41,44,32,98,101,99,97,117,115,101,32,80,101,114,108,32,100,105,100,32,110,111,116,32,116,114,101,97,116,32,116,104,105,115,32,99,104,97,114,97,99,116,101,114,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,46,32,72,111,119,101,118,101,114,44,32,80,101,114,108,32,99,104,97,110,103,101,100,32,97,116,32,114,101,108,101,97,115,101,32,53,46,49,56,44,32,115,111,32,80,67,82,69,32,102,111,108,108,111,119,101,100,32,97,116,32,114,101,108,101,97,115,101,32,56,46,51,52,44,32,97,110,100,32,86,84,32,105,115,32,110,111,119,32,116,114,101,97,116,101,100,32,97,115,32,119,104,105,116,101,32,115,112,97,99,101,46>>]},{p,[],[<<84,104,105,115,32,97,108,115,111,32,99,97,117,115,101,115,32,99,104,97,114,97,99,116,101,114,115,32,98,101,116,119,101,101,110,32,97,110,32,117,110,101,115,99,97,112,101,100,32,35,32,111,117,116,115,105,100,101,32,97,32,99,104,97,114,97,99,116,101,114,32,99,108,97,115,115,32,97,110,100,32,116,104,101,32,110,101,120,116,32,110,101,119,108,105,110,101,44,32,105,110,99,108,117,115,105,118,101,44,32,116,111,32,98,101,32,105,103,110,111,114,101,100,46,32,84,104,105,115,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,39,115,32>>,{code,[],[<<47,120>>]},<<32,111,112,116,105,111,110,44,32,97,110,100,32,105,116,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,120,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46>>]},{p,[],[<<87,105,116,104,32,116,104,105,115,32,111,112,116,105,111,110,44,32,99,111,109,109,101,110,116,115,32,105,110,115,105,100,101,32,99,111,109,112,108,105,99,97,116,101,100,32,112,97,116,116,101,114,110,115,32,99,97,110,32,98,101,32,105,110,99,108,117,100,101,100,46,32,72,111,119,101,118,101,114,44,32,110,111,116,105,99,101,32,116,104,97,116,32,116,104,105,115,32,97,112,112,108,105,101,115,32,111,110,108,121,32,116,111,32,100,97,116,97,32,99,104,97,114,97,99,116,101,114,115,46,32,87,104,105,116,101,115,112,97,99,101,32,99,104,97,114,97,99,116,101,114,115,32,99,97,110,32,110,101,118,101,114,32,97,112,112,101,97,114,32,119,105,116,104,105,110,32,115,112,101,99,105,97,108,32,99,104,97,114,97,99,116,101,114,32,115,101,113,117,101,110,99,101,115,32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,102,111,114,32,101,120,97,109,112,108,101,32,119,105,116,104,105,110,32,115,101,113,117,101,110,99,101,32>>,{code,[],[<<40,63,40>>]},<<32,116,104,97,116,32,105,110,116,114,111,100,117,99,101,115,32,97,32,99,111,110,100,105,116,105,111,110,97,108,32,115,117,98,112,97,116,116,101,114,110,46>>]}]},{dt,[],[{code,[],[<<102,105,114,115,116,108,105,110,101>>]}]},{dd,[],[{p,[],[<<65,110,32,117,110,97,110,99,104,111,114,101,100,32,112,97,116,116,101,114,110,32,105,115,32,114,101,113,117,105,114,101,100,32,116,111,32,109,97,116,99,104,32,98,101,102,111,114,101,32,111,114,32,97,116,32,116,104,101,32,102,105,114,115,116,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,97,108,116,104,111,117,103,104,32,116,104,101,32,109,97,116,99,104,101,100,32,116,101,120,116,32,99,97,110,32,99,111,110,116,105,110,117,101,32,111,118,101,114,32,116,104,101,32,110,101,119,108,105,110,101,46>>]}]},{dt,[],[{code,[],[<<109,117,108,116,105,108,105,110,101>>]}]},{dd,[],[{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,80,67,82,69,32,116,114,101,97,116,115,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,97,115,32,99,111,110,115,105,115,116,105,110,103,32,111,102,32,97,32,115,105,110,103,108,101,32,108,105,110,101,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,101,118,101,110,32,105,102,32,105,116,32,99,111,110,116,97,105,110,115,32,110,101,119,108,105,110,101,115,41,46,32,84,104,101,32,34,115,116,97,114,116,32,111,102,32,108,105,110,101,34,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,40>>,{code,[],[<<94>>]},<<41,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,119,104,105,108,101,32,116,104,101,32,34,101,110,100,32,111,102,32,108,105,110,101,34,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,40>>,{code,[],[<<36>>]},<<41,32,109,97,116,99,104,101,115,32,111,110,108,121,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,111,114,32,98,101,102,111,114,101,32,97,32,116,101,114,109,105,110,97,116,105,110,103,32,110,101,119,108,105,110,101,32,40,117,110,108,101,115,115,32,111,112,116,105,111,110,32>>,{code,[],[<<100,111,108,108,97,114,95,101,110,100,111,110,108,121>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,41,46,32,84,104,105,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,105,110,32,80,101,114,108,46>>]},{p,[],[<<87,104,101,110,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,34,115,116,97,114,116,32,111,102,32,108,105,110,101,34,32,97,110,100,32,34,101,110,100,32,111,102,32,108,105,110,101,34,32,99,111,110,115,116,114,117,99,116,115,32,109,97,116,99,104,32,105,109,109,101,100,105,97,116,101,108,121,32,102,111,108,108,111,119,105,110,103,32,111,114,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,105,110,116,101,114,110,97,108,32,110,101,119,108,105,110,101,115,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,114,101,115,112,101,99,116,105,118,101,108,121,44,32,97,115,32,119,101,108,108,32,97,115,32,97,116,32,116,104,101,32,118,101,114,121,32,115,116,97,114,116,32,97,110,100,32,101,110,100,46,32,84,104,105,115,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,80,101,114,108,32,111,112,116,105,111,110,32>>,{code,[],[<<47,109>>]},<<32,97,110,100,32,99,97,110,32,98,101,32,99,104,97,110,103,101,100,32,119,105,116,104,105,110,32,97,32,112,97,116,116,101,114,110,32,98,121,32,97,32>>,{code,[],[<<40,63,109,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,46,32,73,102,32,116,104,101,114,101,32,97,114,101,32,110,111,32,110,101,119,108,105,110,101,115,32,105,110,32,97,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,111,114,32,110,111,32,111,99,99,117,114,114,101,110,99,101,115,32,111,102,32>>,{code,[],[<<94>>]},<<32,111,114,32>>,{code,[],[<<36>>]},<<32,105,110,32,97,32,112,97,116,116,101,114,110,44,32,115,101,116,116,105,110,103,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,104,97,115,32,110,111,32,101,102,102,101,99,116,46>>]}]},{dt,[],[{code,[],[<<110,111,95,97,117,116,111,95,99,97,112,116,117,114,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,116,104,101,32,117,115,101,32,111,102,32,110,117,109,98,101,114,101,100,32,99,97,112,116,117,114,105,110,103,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46,32,65,110,121,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,116,104,97,116,32,105,115,32,110,111,116,32,102,111,108,108,111,119,101,100,32,98,121,32>>,{code,[],[<<63>>]},<<32,98,101,104,97,118,101,115,32,97,115,32,105,102,32,105,116,32,105,115,32,102,111,108,108,111,119,101,100,32,98,121,32>>,{code,[],[<<63,58>>]},<<46,32,78,97,109,101,100,32,112,97,114,101,110,116,104,101,115,101,115,32,99,97,110,32,115,116,105,108,108,32,98,101,32,117,115,101,100,32,102,111,114,32,99,97,112,116,117,114,105,110,103,32,40,97,110,100,32,116,104,101,121,32,97,99,113,117,105,114,101,32,110,117,109,98,101,114,115,32,105,110,32,116,104,101,32,117,115,117,97,108,32,119,97,121,41,46,32,84,104,101,114,101,32,105,115,32,110,111,32,101,113,117,105,118,97,108,101,110,116,32,111,112,116,105,111,110,32,105,110,32,80,101,114,108,46>>]}]},{dt,[],[{code,[],[<<100,117,112,110,97,109,101,115>>]}]},{dd,[],[{p,[],[<<78,97,109,101,115,32,117,115,101,100,32,116,111,32,105,100,101,110,116,105,102,121,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,110,101,101,100,32,110,111,116,32,98,101,32,117,110,105,113,117,101,46,32,84,104,105,115,32,99,97,110,32,98,101,32,104,101,108,112,102,117,108,32,102,111,114,32,99,101,114,116,97,105,110,32,116,121,112,101,115,32,111,102,32,112,97,116,116,101,114,110,32,119,104,101,110,32,105,116,32,105,115,32,107,110,111,119,110,32,116,104,97,116,32,111,110,108,121,32,111,110,101,32,105,110,115,116,97,110,99,101,32,111,102,32,116,104,101,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,101,118,101,114,32,98,101,32,109,97,116,99,104,101,100,46,32,77,111,114,101,32,100,101,116,97,105,108,115,32,111,102,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,112,114,111,118,105,100,101,100,32,98,101,108,111,119,46>>]}]},{dt,[],[{code,[],[<<117,110,103,114,101,101,100,121>>]}]},{dd,[],[{p,[],[<<73,110,118,101,114,116,115,32,116,104,101,32,34,103,114,101,101,100,105,110,101,115,115,34,32,111,102,32,116,104,101,32,113,117,97,110,116,105,102,105,101,114,115,32,115,111,32,116,104,97,116,32,116,104,101,121,32,97,114,101,32,110,111,116,32,103,114,101,101,100,121,32,98,121,32,100,101,102,97,117,108,116,44,32,98,117,116,32,98,101,99,111,109,101,32,103,114,101,101,100,121,32,105,102,32,102,111,108,108,111,119,101,100,32,98,121,32,34,63,34,46,32,73,116,32,105,115,32,110,111,116,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,32,80,101,114,108,46,32,73,116,32,99,97,110,32,97,108,115,111,32,98,101,32,115,101,116,32,98,121,32,97,32>>,{code,[],[<<40,63,85,41>>]},<<32,111,112,116,105,111,110,32,115,101,116,116,105,110,103,32,119,105,116,104,105,110,32,116,104,101,32,112,97,116,116,101,114,110,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]}]},{dd,[],[{p,[],[<<79,118,101,114,114,105,100,101,115,32,116,104,101,32,100,101,102,97,117,108,116,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,97,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,119,104,105,99,104,32,105,115,32,76,70,32,40,65,83,67,73,73,32,49,48,41,32,105,110,32,69,114,108,97,110,103,46>>]},{dl,[],[{dt,[],[{code,[],[<<99,114>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32>>,{code,[],[<<99,114>>]},<<32,40,65,83,67,73,73,32,49,51,41,46>>]}]},{dt,[],[{code,[],[<<108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,76,70,32,40,65,83,67,73,73,32,49,48,41,44,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<99,114,108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,67,82,76,70,32,40,65,83,67,73,73,32,49,51,32,102,111,108,108,111,119,101,100,32,98,121,32,65,83,67,73,73,32,49,48,41,32,115,101,113,117,101,110,99,101,46>>]}]},{dt,[],[{code,[],[<<97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,112,114,101,99,101,100,105,110,103,32,115,101,113,117,101,110,99,101,115,32,105,115,32,116,111,32,98,101,32,114,101,99,111,103,110,105,122,101,100,46>>]}]},{dt,[],[{code,[],[<<97,110,121>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,115,32,97,98,111,118,101,44,32,97,110,100,32,116,104,101,32,85,110,105,99,111,100,101,32,115,101,113,117,101,110,99,101,115,32,86,84,32,40,118,101,114,116,105,99,97,108,32,116,97,98,44,32,85,43,48,48,48,66,41,44,32,70,70,32,40,102,111,114,109,102,101,101,100,44,32,85,43,48,48,48,67,41,44,32,78,69,76,32,40,110,101,120,116,32,108,105,110,101,44,32,85,43,48,48,56,53,41,44,32,76,83,32,40,108,105,110,101,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,56,41,44,32,97,110,100,32,80,83,32,40,112,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,57,41,46>>]}]}]}]},{dt,[],[{code,[],[<<98,115,114,95,97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,116,104,101,32,67,82,44,32,76,70,44,32,111,114,32,67,82,76,70,32,115,101,113,117,101,110,99,101,115,44,32,110,111,116,32,116,104,101,32,85,110,105,99,111,100,101,45,115,112,101,99,105,102,105,99,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,46>>]}]},{dt,[],[{code,[],[<<98,115,114,95,117,110,105,99,111,100,101>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,97,108,108,32,116,104,101,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,99,108,117,100,105,110,103,32,67,82,76,70,44,32,97,110,100,32,115,111,32,111,110,44,32,116,104,101,32,100,101,102,97,117,108,116,41,46>>]}]},{dt,[],[{code,[],[<<110,111,95,115,116,97,114,116,95,111,112,116,105,109,105,122,101>>]}]},{dd,[],[{p,[],[<<68,105,115,97,98,108,101,115,32,111,112,116,105,109,105,122,97,116,105,111,110,32,116,104,97,116,32,99,97,110,32,109,97,108,102,117,110,99,116,105,111,110,32,105,102,32,34,83,112,101,99,105,97,108,32,115,116,97,114,116,45,111,102,45,112,97,116,116,101,114,110,32,105,116,101,109,115,34,32,97,114,101,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,65,32,116,121,112,105,99,97,108,32,101,120,97,109,112,108,101,32,119,111,117,108,100,32,98,101,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,34,68,69,70,65,66,67,34,32,97,103,97,105,110,115,116,32,34,40,42,67,79,77,77,73,84,41,65,66,67,34,44,32,119,104,101,114,101,32,116,104,101,32,115,116,97,114,116,32,111,112,116,105,109,105,122,97,116,105,111,110,32,111,102,32,80,67,82,69,32,119,111,117,108,100,32,115,107,105,112,32,116,104,101,32,115,117,98,106,101,99,116,32,117,112,32,116,111,32,34,65,34,32,97,110,100,32,110,101,118,101,114,32,114,101,97,108,105,122,101,32,116,104,97,116,32,116,104,101,32,40,42,67,79,77,77,73,84,41,32,105,110,115,116,114,117,99,116,105,111,110,32,105,115,32,116,111,32,104,97,118,101,32,109,97,100,101,32,116,104,101,32,109,97,116,99,104,105,110,103,32,102,97,105,108,46,32,84,104,105,115,32,111,112,116,105,111,110,32,105,115,32,111,110,108,121,32,114,101,108,101,118,97,110,116,32,105,102,32,121,111,117,32,117,115,101,32,34,115,116,97,114,116,45,111,102,45,112,97,116,116,101,114,110,32,105,116,101,109,115,34,44,32,97,115,32,100,105,115,99,117,115,115,101,100,32,105,110,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,101,103,101,120,112,95,115,121,110,116,97,120,95,100,101,116,97,105,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,67,82,69,32,82,101,103,117,108,97,114,32,69,120,112,114,101,115,115,105,111,110,32,68,101,116,97,105,108,115>>]},<<46>>]}]},{dt,[],[{code,[],[<<117,99,112>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,116,111,32,98,101,32,117,115,101,100,32,119,104,101,110,32,114,101,115,111,108,118,105,110,103,32,92,66,44,32,92,98,44,32,92,68,44,32,92,100,44,32,92,83,44,32,92,115,44,32,92,87,32,97,110,100,32,92,119,46,32,87,105,116,104,111,117,116,32,116,104,105,115,32,102,108,97,103,44,32,111,110,108,121,32,73,83,79,32,76,97,116,105,110,45,49,32,112,114,111,112,101,114,116,105,101,115,32,97,114,101,32,117,115,101,100,46,32,85,115,105,110,103,32,85,110,105,99,111,100,101,32,112,114,111,112,101,114,116,105,101,115,32,104,117,114,116,115,32,112,101,114,102,111,114,109,97,110,99,101,44,32,98,117,116,32,105,115,32,115,101,109,97,110,116,105,99,97,108,108,121,32,99,111,114,114,101,99,116,32,119,104,101,110,32,119,111,114,107,105,110,103,32,119,105,116,104,32,85,110,105,99,111,100,101,32,99,104,97,114,97,99,116,101,114,115,32,98,101,121,111,110,100,32,116,104,101,32,73,83,79,32,76,97,116,105,110,45,49,32,114,97,110,103,101,46>>]}]},{dt,[],[{code,[],[<<110,101,118,101,114,95,117,116,102>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,116,104,101,32,40,42,85,84,70,41,32,97,110,100,47,111,114,32,40,42,85,84,70,56,41,32,34,115,116,97,114,116,45,111,102,45,112,97,116,116,101,114,110,32,105,116,101,109,115,34,32,97,114,101,32,102,111,114,98,105,100,100,101,110,46,32,84,104,105,115,32,102,108,97,103,32,99,97,110,110,111,116,32,98,101,32,99,111,109,98,105,110,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<46,32,85,115,101,102,117,108,32,105,102,32,73,83,79,32,76,97,116,105,110,45,49,32,112,97,116,116,101,114,110,115,32,102,114,111,109,32,97,110,32,101,120,116,101,114,110,97,108,32,115,111,117,114,99,101,32,97,114,101,32,116,111,32,98,101,32,99,111,109,112,105,108,101,100,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,57,55>>,signature => [{attribute,{57,2},spec,{{compile,2},[{type,{57,14},bounded_fun,[{type,{57,14},'fun',[{type,{57,14},product,[{var,{57,15},'Regexp'},{var,{57,23},'Options'}]},{type,{57,35},union,[{type,{57,35},tuple,[{atom,{57,36},ok},{var,{57,40},'MP'}]},{type,{57,46},tuple,[{atom,{57,47},error},{var,{57,54},'ErrSpec'}]}]}]},[{type,{58,7},constraint,[{atom,{58,7},is_subtype},[{var,{58,7},'Regexp'},{type,{58,17},union,[{type,{58,17},iodata,[]},{remote_type,{58,28},[{atom,{58,28},unicode},{atom,{58,36},charlist},[]]}]}]]},{type,{59,7},constraint,[{atom,{59,7},is_subtype},[{var,{59,7},'Options'},{type,{59,18},list,[{var,{59,19},'Option'}]}]]},{type,{60,7},constraint,[{atom,{60,7},is_subtype},[{var,{60,7},'Option'},{user_type,{60,17},compile_option,[]}]]},{type,{61,7},constraint,[{atom,{61,7},is_subtype},[{var,{61,7},'MP'},{user_type,{61,13},mp,[]}]]},{type,{62,7},constraint,[{atom,{62,7},is_subtype},[{var,{62,7},'ErrSpec'},{type,{62,18},tuple,[{ann_type,{62,19},[{var,{62,19},'ErrString'},{type,{62,32},string,[]}]},{ann_type,{62,42},[{var,{62,42},'Position'},{type,{62,54},non_neg_integer,[]}]}]}]]}]]}]}}]}},{{function,inspect,2},[{file,[114,101,46,101,114,108]},{location,143}],[<<105,110,115,112,101,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<84,97,107,101,115,32,97,32,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,110,100,32,97,110,32,105,116,101,109,44,32,97,110,100,32,114,101,116,117,114,110,115,32,116,104,101,32,114,101,108,101,118,97,110,116,32,100,97,116,97,32,102,114,111,109,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,84,104,101,32,111,110,108,121,32,115,117,112,112,111,114,116,101,100,32,105,116,101,109,32,105,115,32>>,{code,[],[<<110,97,109,101,108,105,115,116>>]},<<44,32,119,104,105,99,104,32,114,101,116,117,114,110,115,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,110,97,109,101,108,105,115,116,44,32,91,98,105,110,97,114,121,40,41,93,125>>]},<<44,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,110,97,109,101,115,32,111,102,32,97,108,108,32,40,117,110,105,113,117,101,41,32,110,97,109,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<49,62,32,123,111,107,44,77,80,125,32,61,32,114,101,58,99,111,109,112,105,108,101,40,34,40,63,60,65,62,65,41,124,40,63,60,66,62,66,41,124,40,63,60,67,62,67,41,34,41,46,10,123,111,107,44,123,114,101,95,112,97,116,116,101,114,110,44,51,44,48,44,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,60,54,57,44,56,50,44,54,55,44,56,48,44,49,49,57,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,49,44,48,44,48,44,48,44,50,53,53,44,50,53,53,44,50,53,53,44,50,53,53,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,53,53,44,50,53,53,44,46,46,46,62,62,125,125,10,50,62,32,114,101,58,105,110,115,112,101,99,116,40,77,80,44,110,97,109,101,108,105,115,116,41,46,10,123,110,97,109,101,108,105,115,116,44,91,60,60,34,65,34,62,62,44,60,60,34,66,34,62,62,44,60,60,34,67,34,62,62,93,125,10,51,62,32,123,111,107,44,77,80,68,125,32,61,32,114,101,58,99,111,109,112,105,108,101,40,34,40,63,60,67,62,65,41,124,40,63,60,66,62,66,41,124,40,63,60,67,62,67,41,34,44,91,100,117,112,110,97,109,101,115,93,41,46,10,123,111,107,44,123,114,101,95,112,97,116,116,101,114,110,44,51,44,48,44,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,60,54,57,44,56,50,44,54,55,44,56,48,44,49,49,57,44,48,44,48,44,48,44,48,44,48,44,56,44,48,44,49,44,48,44,48,44,48,44,50,53,53,44,50,53,53,44,50,53,53,44,50,53,53,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,53,53,44,50,53,53,44,46,46,46,62,62,125,125,10,52,62,32,114,101,58,105,110,115,112,101,99,116,40,77,80,68,44,110,97,109,101,108,105,115,116,41,46,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,10,123,110,97,109,101,108,105,115,116,44,91,60,60,34,66,34,62,62,44,60,60,34,67,34,62,62,93,125>>]}]},{p,[],[<<78,111,116,105,99,101,32,105,110,32,116,104,101,32,115,101,99,111,110,100,32,101,120,97,109,112,108,101,32,116,104,97,116,32,116,104,101,32,100,117,112,108,105,99,97,116,101,32,110,97,109,101,32,111,110,108,121,32,111,99,99,117,114,115,32,111,110,99,101,32,105,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,108,105,115,116,44,32,97,110,100,32,116,104,97,116,32,116,104,101,32,108,105,115,116,32,105,115,32,105,110,32,97,108,112,104,97,98,101,116,105,99,97,108,32,111,114,100,101,114,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,119,104,101,114,101,32,116,104,101,32,110,97,109,101,115,32,97,114,101,32,112,111,115,105,116,105,111,110,101,100,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32,84,104,101,32,111,114,100,101,114,32,111,102,32,116,104,101,32,110,97,109,101,115,32,105,115,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,111,114,100,101,114,32,111,102,32,99,97,112,116,117,114,101,100,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,105,102,32>>,{code,[],[<<123,99,97,112,116,117,114,101,44,32,97,108,108,95,110,97,109,101,115,125>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,110,32,111,112,116,105,111,110,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<46,32,89,111,117,32,99,97,110,32,116,104,101,114,101,102,111,114,101,32,99,114,101,97,116,101,32,97,32,110,97,109,101,45,116,111,45,118,97,108,117,101,32,109,97,112,112,105,110,103,32,102,114,111,109,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,108,105,107,101,32,116,104,105,115,58>>]},{pre,[],[{code,[],[<<49,62,32,123,111,107,44,77,80,125,32,61,32,114,101,58,99,111,109,112,105,108,101,40,34,40,63,60,65,62,65,41,124,40,63,60,66,62,66,41,124,40,63,60,67,62,67,41,34,41,46,10,123,111,107,44,123,114,101,95,112,97,116,116,101,114,110,44,51,44,48,44,48,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,60,54,57,44,56,50,44,54,55,44,56,48,44,49,49,57,44,48,44,48,44,48,44,48,44,48,44,48,44,48,44,49,44,48,44,48,44,48,44,50,53,53,44,50,53,53,44,50,53,53,44,50,53,53,44,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,50,53,53,44,50,53,53,44,46,46,46,62,62,125,125,10,50,62,32,123,110,97,109,101,108,105,115,116,44,32,78,125,32,61,32,114,101,58,105,110,115,112,101,99,116,40,77,80,44,110,97,109,101,108,105,115,116,41,46,10,123,110,97,109,101,108,105,115,116,44,91,60,60,34,65,34,62,62,44,60,60,34,66,34,62,62,44,60,60,34,67,34,62,62,93,125,10,51,62,32,123,109,97,116,99,104,44,76,125,32,61,32,114,101,58,114,117,110,40,34,65,65,34,44,77,80,44,91,123,99,97,112,116,117,114,101,44,97,108,108,95,110,97,109,101,115,44,98,105,110,97,114,121,125,93,41,46,10,123,109,97,116,99,104,44,91,60,60,34,65,34,62,62,44,60,60,62,62,44,60,60,62,62,93,125,10,52,62,32,78,97,109,101,77,97,112,32,61,32,108,105,115,116,115,58,122,105,112,40,78,44,76,41,46,10,91,123,60,60,34,65,34,62,62,44,60,60,34,65,34,62,62,125,44,123,60,60,34,66,34,62,62,44,60,60,62,62,125,44,123,60,60,34,67,34,62,62,44,60,60,62,62,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,51,48,54>>,signature => [{attribute,{143,2},spec,{{inspect,2},[{type,{143,14},bounded_fun,[{type,{143,14},'fun',[{type,{143,14},product,[{var,{143,15},'MP'},{var,{143,18},'Item'}]},{type,{143,27},tuple,[{atom,{143,28},namelist},{type,{143,38},list,[{type,{143,40},binary,[]}]}]}]},[{type,{144,7},constraint,[{atom,{144,7},is_subtype},[{var,{144,7},'MP'},{user_type,{144,13},mp,[]}]]},{type,{145,7},constraint,[{atom,{145,7},is_subtype},[{var,{145,7},'Item'},{atom,{145,15},namelist}]]}]]}]}}],since => <<79,84,80,32,49,55,46,48>>}},{{function,replace,3},[{file,[114,101,46,101,114,108]},{location,353}],[<<114,101,112,108,97,99,101,47,51>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<114,101,112,108,97,99,101,40,83,117,98,106,101,99,116,44,32,82,69,44,32,82,101,112,108,97,99,101,109,101,110,116,44,32,91,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,51,53,48>>,signature => [{attribute,{353,2},spec,{{replace,3},[{type,{353,14},bounded_fun,[{type,{353,14},'fun',[{type,{353,14},product,[{var,{353,15},'Subject'},{var,{353,24},'RE'},{var,{353,28},'Replacement'}]},{type,{353,44},union,[{type,{353,44},iodata,[]},{remote_type,{353,55},[{atom,{353,55},unicode},{atom,{353,63},charlist},[]]}]}]},[{type,{354,7},constraint,[{atom,{354,7},is_subtype},[{var,{354,7},'Subject'},{type,{354,18},union,[{type,{354,18},iodata,[]},{remote_type,{354,29},[{atom,{354,29},unicode},{atom,{354,37},charlist},[]]}]}]]},{type,{355,7},constraint,[{atom,{355,7},is_subtype},[{var,{355,7},'RE'},{type,{355,13},union,[{user_type,{355,13},mp,[]},{type,{355,20},iodata,[]}]}]]},{type,{356,7},constraint,[{atom,{356,7},is_subtype},[{var,{356,7},'Replacement'},{type,{356,22},union,[{type,{356,22},iodata,[]},{remote_type,{356,33},[{atom,{356,33},unicode},{atom,{356,41},charlist},[]]}]}]]}]]}]}}]}},{{function,replace,4},[{file,[114,101,46,101,114,108]},{location,366}],[<<114,101,112,108,97,99,101,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,112,108,97,99,101,115,32,116,104,101,32,109,97,116,99,104,101,100,32,112,97,114,116,32,111,102,32,116,104,101,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,99,111,110,116,101,110,116,115,32,111,102,32>>,{code,[],[<<82,101,112,108,97,99,101,109,101,110,116>>]},<<46>>]},{p,[],[<<84,104,101,32,112,101,114,109,105,115,115,105,98,108,101,32,111,112,116,105,111,110,115,32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,102,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,111,112,116,105,111,110>>,{code,[],[<<32,99,97,112,116,117,114,101>>]},<<32,105,115,32,110,111,116,32,97,108,108,111,119,101,100,46,32,73,110,115,116,101,97,100,32,97,32>>,{code,[],[<<123,114,101,116,117,114,110,44,32,82,101,116,117,114,110,84,121,112,101,125>>]},<<32,105,115,32,112,114,101,115,101,110,116,46,32,84,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<44,32,99,111,110,115,116,114,117,99,116,101,100,32,105,110,32,97,32,119,97,121,32,116,111,32,109,105,110,105,109,105,122,101,32,99,111,112,121,105,110,103,46,32,84,104,101,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<32,114,101,115,117,108,116,32,99,97,110,32,98,101,32,117,115,101,100,32,100,105,114,101,99,116,108,121,32,105,110,32,109,97,110,121,32,73,47,79,32,111,112,101,114,97,116,105,111,110,115,46,32,73,102,32,97,32,102,108,97,116,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,105,115,32,100,101,115,105,114,101,100,44,32,115,112,101,99,105,102,121,32>>,{code,[],[<<123,114,101,116,117,114,110,44,32,108,105,115,116,125>>]},<<46,32,73,102,32,97,32,98,105,110,97,114,121,32,105,115,32,100,101,115,105,114,101,100,44,32,115,112,101,99,105,102,121,32>>,{code,[],[<<123,114,101,116,117,114,110,44,32,98,105,110,97,114,121,125>>]},<<46>>]},{p,[],[<<65,115,32,105,110,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<114,117,110,47,51>>]},<<44,32,97,110,32>>,{code,[],[<<109,112,40,41>>]},<<32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,114,101,113,117,105,114,101,115,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,116,111,32,98,101,32,97,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<46,32,73,102,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,105,109,112,108,105,99,105,116,108,121,32,97,110,100,32,116,104,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,98,111,116,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,110,100,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,97,114,101,32,116,111,32,115,112,101,99,105,102,105,101,100,32,97,115,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<115,46>>]},{p,[],[<<84,104,101,32,114,101,112,108,97,99,101,109,101,110,116,32,115,116,114,105,110,103,32,99,97,110,32,99,111,110,116,97,105,110,32,116,104,101,32,115,112,101,99,105,97,108,32,99,104,97,114,97,99,116,101,114,32>>,{code,[],[<<38>>]},<<44,32,119,104,105,99,104,32,105,110,115,101,114,116,115,32,116,104,101,32,119,104,111,108,101,32,109,97,116,99,104,105,110,103,32,101,120,112,114,101,115,115,105,111,110,32,105,110,32,116,104,101,32,114,101,115,117,108,116,44,32,97,110,100,32,116,104,101,32,115,112,101,99,105,97,108,32,115,101,113,117,101,110,99,101,32>>,{code,[],[<<92>>]},<<78,32,40,119,104,101,114,101,32,78,32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,62,32,48,41,44,32>>,{code,[],[<<92,103>>]},<<78,44,32,111,114,32>>,{code,[],[<<92,103,123>>]},<<78>>,{code,[],[<<125>>]},<<44,32,114,101,115,117,108,116,105,110,103,32,105,110,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,110,117,109,98,101,114,32,78,44,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46,32,73,102,32,110,111,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,119,105,116,104,32,116,104,97,116,32,110,117,109,98,101,114,32,105,115,32,103,101,110,101,114,97,116,101,100,32,98,121,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,110,111,116,104,105,110,103,32,105,115,32,105,110,115,101,114,116,101,100,46>>]},{p,[],[<<84,111,32,105,110,115,101,114,116,32,97,110,32,38,32,111,114,32,97,32,92,32,105,110,32,116,104,101,32,114,101,115,117,108,116,44,32,112,114,101,99,101,100,101,32,105,116,32,119,105,116,104,32,97,32,92,46,32,78,111,116,105,99,101,32,116,104,97,116,32,69,114,108,97,110,103,32,97,108,114,101,97,100,121,32,103,105,118,101,115,32,97,32,115,112,101,99,105,97,108,32,109,101,97,110,105,110,103,32,116,111,32,92,32,105,110,32,108,105,116,101,114,97,108,32,115,116,114,105,110,103,115,44,32,115,111,32,97,32,115,105,110,103,108,101,32,92,32,109,117,115,116,32,98,101,32,119,114,105,116,116,101,110,32,97,115,32>>,{code,[],[<<34,92,92,34>>]},<<32,97,110,100,32,116,104,101,114,101,102,111,114,101,32,97,32,100,111,117,98,108,101,32,92,32,97,115,32>>,{code,[],[<<34,92,92,92,92,34>>]},<<46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{pre,[],[{code,[],[<<114,101,58,114,101,112,108,97,99,101,40,34,97,98,99,100,34,44,34,99,34,44,34,91,38,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<34,97,98,91,99,93,100,34>>]}]},{p,[],[<<119,104,105,108,101>>]},{pre,[],[{code,[],[<<114,101,58,114,101,112,108,97,99,101,40,34,97,98,99,100,34,44,34,99,34,44,34,91,92,92,38,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<34,97,98,91,38,93,100,34>>]}]},{p,[],[<<65,115,32,119,105,116,104,32>>,{code,[],[<<114,117,110,47,51>>]},<<44,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,115,32,114,97,105,115,101,32,116,104,101,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,46,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,103,101,116,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,101,114,114,111,114,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,51,54,48>>,signature => [{attribute,{366,2},spec,{{replace,4},[{type,{366,14},bounded_fun,[{type,{366,14},'fun',[{type,{366,14},product,[{var,{366,15},'Subject'},{var,{366,24},'RE'},{var,{366,28},'Replacement'},{var,{366,41},'Options'}]},{type,{366,53},union,[{type,{366,53},iodata,[]},{remote_type,{366,64},[{atom,{366,64},unicode},{atom,{366,72},charlist},[]]}]}]},[{type,{367,7},constraint,[{atom,{367,7},is_subtype},[{var,{367,7},'Subject'},{type,{367,18},union,[{type,{367,18},iodata,[]},{remote_type,{367,29},[{atom,{367,29},unicode},{atom,{367,37},charlist},[]]}]}]]},{type,{368,7},constraint,[{atom,{368,7},is_subtype},[{var,{368,7},'RE'},{type,{368,13},union,[{user_type,{368,13},mp,[]},{type,{368,20},iodata,[]},{remote_type,{368,31},[{atom,{368,31},unicode},{atom,{368,39},charlist},[]]}]}]]},{type,{369,7},constraint,[{atom,{369,7},is_subtype},[{var,{369,7},'Replacement'},{type,{369,22},union,[{type,{369,22},iodata,[]},{remote_type,{369,33},[{atom,{369,33},unicode},{atom,{369,41},charlist},[]]}]}]]},{type,{370,7},constraint,[{atom,{370,7},is_subtype},[{var,{370,7},'Options'},{type,{370,18},list,[{var,{370,19},'Option'}]}]]},{type,{371,7},constraint,[{atom,{371,7},is_subtype},[{var,{371,7},'Option'},{type,{371,17},union,[{atom,{371,17},anchored},{atom,{371,28},global},{atom,{371,37},notbol},{atom,{371,46},noteol},{atom,{371,55},notempty},{atom,{372,10},notempty_atstart},{type,{373,17},tuple,[{atom,{373,18},offset},{type,{373,26},non_neg_integer,[]}]},{type,{373,47},tuple,[{atom,{373,48},newline},{var,{373,57},'NLSpec'}]},{atom,{373,67},bsr_anycrlf},{type,{374,17},tuple,[{atom,{374,18},match_limit},{type,{374,31},non_neg_integer,[]}]},{type,{375,17},tuple,[{atom,{375,18},match_limit_recursion},{type,{375,41},non_neg_integer,[]}]},{atom,{376,17},bsr_unicode},{type,{376,31},tuple,[{atom,{376,32},return},{var,{376,40},'ReturnType'}]},{var,{376,54},'CompileOpt'}]}]]},{type,{377,7},constraint,[{atom,{377,7},is_subtype},[{var,{377,7},'ReturnType'},{type,{377,21},union,[{atom,{377,21},iodata},{atom,{377,30},list},{atom,{377,37},binary}]}]]},{type,{378,7},constraint,[{atom,{378,7},is_subtype},[{var,{378,7},'CompileOpt'},{user_type,{378,21},compile_option,[]}]]},{type,{379,7},constraint,[{atom,{379,7},is_subtype},[{var,{379,7},'NLSpec'},{type,{379,17},union,[{atom,{379,17},cr},{atom,{379,22},crlf},{atom,{379,29},lf},{atom,{379,34},anycrlf},{atom,{379,44},any}]}]]}]]}]}}]}},{{function,run,2},[{file,[114,101,46,101,114,108]},{location,67}],[<<114,117,110,47,50>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<114,117,110,40,83,117,98,106,101,99,116,44,82,69,44,91,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,52,49,48>>,signature => [{attribute,{67,2},spec,{{run,2},[{type,{67,10},bounded_fun,[{type,{67,10},'fun',[{type,{67,10},product,[{var,{67,11},'Subject'},{var,{67,20},'RE'}]},{type,{67,27},union,[{type,{67,27},tuple,[{atom,{67,28},match},{var,{67,35},'Captured'}]},{atom,{67,47},nomatch}]}]},[{type,{68,7},constraint,[{atom,{68,7},is_subtype},[{var,{68,7},'Subject'},{type,{68,18},union,[{type,{68,18},iodata,[]},{remote_type,{68,29},[{atom,{68,29},unicode},{atom,{68,37},charlist},[]]}]}]]},{type,{69,7},constraint,[{atom,{69,7},is_subtype},[{var,{69,7},'RE'},{type,{69,13},union,[{user_type,{69,13},mp,[]},{type,{69,20},iodata,[]}]}]]},{type,{70,7},constraint,[{atom,{70,7},is_subtype},[{var,{70,7},'Captured'},{type,{70,19},list,[{var,{70,20},'CaptureData'}]}]]},{type,{71,7},constraint,[{atom,{71,7},is_subtype},[{var,{71,7},'CaptureData'},{type,{71,22},tuple,[{type,{71,23},integer,[]},{type,{71,34},integer,[]}]}]]}]]}]}}]}},{{function,run,3},[{file,[114,101,46,101,114,108]},{location,76}],[<<114,117,110,47,51>>],#{<<101,110>> => [{p,[],[<<69,120,101,99,117,116,101,115,32,97,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,105,110,103,44,32,97,110,100,32,114,101,116,117,114,110,115,32>>,{code,[],[<<109,97,116,99,104,47,123,109,97,116,99,104,44,32,67,97,112,116,117,114,101,100,125>>]},<<32,111,114,32>>,{code,[],[<<110,111,109,97,116,99,104>>]},<<46,32,84,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,101,105,116,104,101,114,32,97,115,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,105,116,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,111,109,112,105,108,101,100,32,40,97,115,32,98,121,32>>,{code,[],[<<99,111,109,112,105,108,101,47,50>>]},<<41,32,97,110,100,32,101,120,101,99,117,116,101,100,44,32,111,114,32,97,115,32,97,32,112,114,101,99,111,109,112,105,108,101,100,32>>,{code,[],[<<109,112,40,41>>]},<<32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,105,116,32,105,115,32,101,120,101,99,117,116,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,115,117,98,106,101,99,116,32,100,105,114,101,99,116,108,121,46>>]},{p,[],[<<87,104,101,110,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,105,110,118,111,108,118,101,100,44,32,101,120,99,101,112,116,105,111,110,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,105,115,32,116,104,114,111,119,110,32,105,102,32,97,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,32,111,99,99,117,114,115,46,32,67,97,108,108,32>>,{code,[],[<<99,111,109,112,105,108,101,47,50>>]},<<32,116,111,32,103,101,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,108,111,99,97,116,105,111,110,32,111,102,32,116,104,101,32,101,114,114,111,114,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,105,108,101,100,44,32,116,104,101,32,111,112,116,105,111,110,32,108,105,115,116,32,99,97,110,32,111,110,108,121,32,99,111,110,116,97,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,58>>]},{ul,[],[{li,[],[{code,[],[<<97,110,99,104,111,114,101,100>>]}]},{li,[],[{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,125,47,123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,44,32,84,121,112,101,125>>]}]},{li,[],[{code,[],[<<103,108,111,98,97,108>>]}]},{li,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{li,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{li,[],[{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]}]},{li,[],[{code,[],[<<110,111,116,98,111,108>>]}]},{li,[],[{code,[],[<<110,111,116,101,109,112,116,121>>]}]},{li,[],[{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]}]},{li,[],[{code,[],[<<110,111,116,101,111,108>>]}]},{li,[],[{code,[],[<<123,111,102,102,115,101,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{li,[],[{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]}]}]},{p,[],[<<79,116,104,101,114,119,105,115,101,32,97,108,108,32,111,112,116,105,111,110,115,32,118,97,108,105,100,32,102,111,114,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<99,111,109,112,105,108,101,47,50>>]},<<32,97,114,101,32,97,108,115,111,32,97,108,108,111,119,101,100,46,32,79,112,116,105,111,110,115,32,97,108,108,111,119,101,100,32,98,111,116,104,32,102,111,114,32,99,111,109,112,105,108,97,116,105,111,110,32,97,110,100,32,101,120,101,99,117,116,105,111,110,32,111,102,32,97,32,109,97,116,99,104,44,32,110,97,109,101,108,121,32>>,{code,[],[<<97,110,99,104,111,114,101,100>>]},<<32,97,110,100,32>>,{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]},<<44,32,97,102,102,101,99,116,32,98,111,116,104,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,97,110,100,32,101,120,101,99,117,116,105,111,110,32,105,102,32,112,114,101,115,101,110,116,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,97,32,110,111,110,45,112,114,101,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<73,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,112,114,101,118,105,111,117,115,108,121,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,105,115,32,116,111,32,98,101,32,112,114,111,118,105,100,101,100,32,97,115,32,97,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<44,32,111,116,104,101,114,119,105,115,101,32,97,110,121,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<32,119,105,108,108,32,100,111,46,32,73,102,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,105,110,118,111,108,118,101,100,32,97,110,100,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32,98,111,116,104,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,97,110,100,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,114,101,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,115,40,41>>]},<<46>>]},{p,[],[{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,125,47,123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,44,32,84,121,112,101,125>>]},<<32,100,101,102,105,110,101,115,32,119,104,97,116,32,116,111,32,114,101,116,117,114,110,32,102,114,111,109,32,116,104,101,32,102,117,110,99,116,105,111,110,32,117,112,111,110,32,115,117,99,99,101,115,115,102,117,108,32,109,97,116,99,104,105,110,103,46,32,84,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,116,117,112,108,101,32,99,97,110,32,99,111,110,116,97,105,110,32,98,111,116,104,32,97,32,118,97,108,117,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,116,101,108,108,105,110,103,32,119,104,105,99,104,32,111,102,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,44,32,97,110,100,32,97,32,116,121,112,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110,44,32,116,101,108,108,105,110,103,32,104,111,119,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,32,40,97,115,32,105,110,100,101,120,32,116,117,112,108,101,115,44,32,108,105,115,116,115,44,32,111,114,32,98,105,110,97,114,105,101,115,41,46,32,84,104,101,32,111,112,116,105,111,110,115,32,97,114,101,32,100,101,115,99,114,105,98,101,100,32,105,110,32,100,101,116,97,105,108,32,98,101,108,111,119,46>>]},{p,[],[<<73,102,32,116,104,101,32,99,97,112,116,117,114,101,32,111,112,116,105,111,110,115,32,100,101,115,99,114,105,98,101,32,116,104,97,116,32,110,111,32,115,117,98,115,116,114,105,110,103,32,99,97,112,116,117,114,105,110,103,32,105,115,32,116,111,32,98,101,32,100,111,110,101,32,40>>,{code,[],[<<123,99,97,112,116,117,114,101,44,32,110,111,110,101,125>>]},<<41,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,114,101,116,117,114,110,115,32,116,104,101,32,115,105,110,103,108,101,32,97,116,111,109,32>>,{code,[],[<<109,97,116,99,104>>]},<<32,117,112,111,110,32,115,117,99,99,101,115,115,102,117,108,32,109,97,116,99,104,105,110,103,44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,109,97,116,99,104,44,32,86,97,108,117,101,76,105,115,116,125>>]},<<46,32,68,105,115,97,98,108,105,110,103,32,99,97,112,116,117,114,105,110,103,32,99,97,110,32,98,101,32,100,111,110,101,32,101,105,116,104,101,114,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<110,111,110,101>>]},<<32,111,114,32,97,110,32,101,109,112,116,121,32,108,105,115,116,32,97,115,32>>,{code,[],[<<86,97,108,117,101,83,112,101,99>>]},<<46>>]},{p,[],[<<79,112,116,105,111,110,32>>,{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]},<<32,97,100,100,115,32,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32,116,104,97,116,32,97,110,32,101,114,114,111,114,32,116,117,112,108,101,32,105,115,32,114,101,116,117,114,110,101,100,46,32,84,104,101,32,116,117,112,108,101,32,101,105,116,104,101,114,32,105,110,100,105,99,97,116,101,115,32,97,32,109,97,116,99,104,105,110,103,32,101,114,114,111,114,32,40>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,111,114,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]},<<41,44,32,111,114,32,97,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,44,32,119,104,101,114,101,32,116,104,101,32,101,114,114,111,114,32,116,117,112,108,101,32,104,97,115,32,116,104,101,32,102,111,114,109,97,116,32>>,{code,[],[<<123,101,114,114,111,114,44,32,123,99,111,109,112,105,108,101,44,32,67,111,109,112,105,108,101,69,114,114,125,125>>]},<<46,32,78,111,116,105,99,101,32,116,104,97,116,32,105,102,32,111,112,116,105,111,110,32>>,{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]},<<32,105,115,32,110,111,116,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,110,101,118,101,114,32,114,101,116,117,114,110,115,32,101,114,114,111,114,32,116,117,112,108,101,115,44,32,98,117,116,32,114,101,112,111,114,116,115,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,115,32,97,115,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,101,120,99,101,112,116,105,111,110,32,97,110,100,32,102,97,105,108,101,100,32,109,97,116,99,104,101,115,32,98,101,99,97,117,115,101,32,111,102,32,101,120,99,101,101,100,101,100,32,109,97,116,99,104,32,108,105,109,105,116,115,32,115,105,109,112,108,121,32,97,115,32>>,{code,[],[<<110,111,109,97,116,99,104>>]},<<46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,111,112,116,105,111,110,115,32,97,114,101,32,114,101,108,101,118,97,110,116,32,102,111,114,32,101,120,101,99,117,116,105,111,110,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,110,99,104,111,114,101,100>>]}]},{dd,[],[{p,[],[<<76,105,109,105,116,115,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,116,111,32,109,97,116,99,104,105,110,103,32,97,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,112,111,115,105,116,105,111,110,46,32,73,102,32,97,32,112,97,116,116,101,114,110,32,119,97,115,32,99,111,109,112,105,108,101,100,32,119,105,116,104,32>>,{code,[],[<<97,110,99,104,111,114,101,100>>]},<<44,32,111,114,32,116,117,114,110,101,100,32,111,117,116,32,116,111,32,98,101,32,97,110,99,104,111,114,101,100,32,98,121,32,118,105,114,116,117,101,32,111,102,32,105,116,115,32,99,111,110,116,101,110,116,115,44,32,105,116,32,99,97,110,110,111,116,32,98,101,32,109,97,100,101,32,117,110,97,110,99,104,111,114,101,100,32,97,116,32,109,97,116,99,104,105,110,103,32,116,105,109,101,44,32,104,101,110,99,101,32,116,104,101,114,101,32,105,115,32,110,111,32>>,{code,[],[<<117,110,97,110,99,104,111,114,101,100>>]},<<32,111,112,116,105,111,110,46>>]}]},{dt,[],[{code,[],[<<103,108,111,98,97,108>>]}]},{dd,[],[{p,[],[<<73,109,112,108,101,109,101,110,116,115,32,103,108,111,98,97,108,32,40,114,101,112,101,116,105,116,105,118,101,41,32,115,101,97,114,99,104,32,40,102,108,97,103,32>>,{code,[],[<<103>>]},<<32,105,110,32,80,101,114,108,41,46,32,69,97,99,104,32,109,97,116,99,104,32,105,115,32,114,101,116,117,114,110,101,100,32,97,115,32,97,32,115,101,112,97,114,97,116,101,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,115,112,101,99,105,102,105,99,32,109,97,116,99,104,32,97,110,100,32,97,110,121,32,109,97,116,99,104,105,110,103,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,40,111,114,32,97,115,32,115,112,101,99,105,102,105,101,100,32,98,121,32,111,112,116,105,111,110,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<46,32,84,104,101,32>>,{code,[],[<<67,97,112,116,117,114,101,100>>]},<<32,112,97,114,116,32,111,102,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,104,101,110,99,101,32,97,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,111,102,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<115,32,119,104,101,110,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,46>>]},{p,[],[<<84,104,101,32,105,110,116,101,114,97,99,116,105,111,110,32,111,102,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,119,105,116,104,32,97,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,115,117,114,112,114,105,115,101,115,32,115,111,109,101,32,117,115,101,114,115,46,32,87,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,104,97,110,100,108,101,115,32,101,109,112,116,121,32,109,97,116,99,104,101,115,32,105,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,97,115,32,80,101,114,108,58,32,97,32,122,101,114,111,45,108,101,110,103,116,104,32,109,97,116,99,104,32,97,116,32,97,110,121,32,112,111,105,110,116,32,105,115,32,97,108,115,111,32,114,101,116,114,105,101,100,32,119,105,116,104,32,111,112,116,105,111,110,115,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]},<<46,32,73,102,32,116,104,97,116,32,115,101,97,114,99,104,32,103,105,118,101,115,32,97,32,114,101,115,117,108,116,32,111,102,32,108,101,110,103,116,104,32,62,32,48,44,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,105,110,99,108,117,100,101,100,46,32,69,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,99,97,116,34,44,34,40,124,97,116,41,34,44,91,103,108,111,98,97,108,93,41,46>>]}]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,109,97,116,99,104,105,110,103,115,32,97,114,101,32,112,101,114,102,111,114,109,101,100,58>>]},{dl,[],[{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<48>>]}]},{dd,[],[{p,[],[<<84,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32>>,{code,[],[<<40,124,97,116,41>>]},<<32,102,105,114,115,116,32,109,97,116,99,104,32,97,116,32,116,104,101,32,105,110,105,116,105,97,108,32,112,111,115,105,116,105,111,110,32,111,102,32,115,116,114,105,110,103,32>>,{code,[],[<<99,97,116>>]},<<44,32,103,105,118,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,115,101,116,32>>,{code,[],[<<91,123,48,44,48,125,44,123,48,44,48,125,93>>]},<<32,40,116,104,101,32,115,101,99,111,110,100,32>>,{code,[],[<<123,48,44,48,125>>]},<<32,105,115,32,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,109,97,114,107,101,100,32,98,121,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,41,46,32,65,115,32,116,104,101,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,109,97,116,99,104,32,105,115,32,48,44,32,119,101,32,100,111,32,110,111,116,32,97,100,118,97,110,99,101,32,116,111,32,116,104,101,32,110,101,120,116,32,112,111,115,105,116,105,111,110,32,121,101,116,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<48>>]},<<32,119,105,116,104,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,101,97,114,99,104,32,105,115,32,114,101,116,114,105,101,100,32,119,105,116,104,32,111,112,116,105,111,110,115,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]},<<32,97,116,32,116,104,101,32,115,97,109,101,32,112,111,115,105,116,105,111,110,44,32,119,104,105,99,104,32,100,111,101,115,32,110,111,116,32,103,105,118,101,32,97,110,121,32,105,110,116,101,114,101,115,116,105,110,103,32,114,101,115,117,108,116,32,111,102,32,108,111,110,103,101,114,32,108,101,110,103,116,104,44,32,115,111,32,116,104,101,32,115,101,97,114,99,104,32,112,111,115,105,116,105,111,110,32,105,115,32,97,100,118,97,110,99,101,100,32,116,111,32,116,104,101,32,110,101,120,116,32,99,104,97,114,97,99,116,101,114,32,40>>,{code,[],[<<97>>]},<<41,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<49>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,101,97,114,99,104,32,114,101,115,117,108,116,115,32,105,110,32>>,{code,[],[<<91,123,49,44,48,125,44,123,49,44,48,125,93>>]},<<44,32,115,111,32,116,104,105,115,32,115,101,97,114,99,104,32,105,115,32,97,108,115,111,32,114,101,112,101,97,116,101,100,32,119,105,116,104,32,116,104,101,32,101,120,116,114,97,32,111,112,116,105,111,110,115,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<49>>]},<<32,119,105,116,104,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]}]},{dd,[],[{p,[],[<<65,108,116,101,114,110,97,116,105,118,101,32>>,{code,[],[<<97,98>>]},<<32,105,115,32,102,111,117,110,100,32,97,110,100,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,91,123,49,44,50,125,44,123,49,44,50,125,93,46,32,84,104,101,32,114,101,115,117,108,116,32,105,115,32,97,100,100,101,100,32,116,111,32,116,104,101,32,108,105,115,116,32,111,102,32,114,101,115,117,108,116,115,32,97,110,100,32,116,104,101,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,101,97,114,99,104,32,115,116,114,105,110,103,32,105,115,32,97,100,118,97,110,99,101,100,32,116,119,111,32,115,116,101,112,115,46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<51>>]}]},{dd,[],[{p,[],[<<84,104,101,32,115,101,97,114,99,104,32,111,110,99,101,32,97,103,97,105,110,32,109,97,116,99,104,101,115,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,44,32,103,105,118,105,110,103,32>>,{code,[],[<<91,123,51,44,48,125,44,123,51,44,48,125,93>>]},<<46>>]}]},{dt,[],[<<65,116,32,111,102,102,115,101,116,32>>,{code,[],[<<49>>]},<<32,119,105,116,104,32>>,{code,[],[<<91,97,110,99,104,111,114,101,100,44,32,110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116,93>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,103,105,118,101,115,32,110,111,32,114,101,115,117,108,116,32,111,102,32,108,101,110,103,116,104,32,62,32,48,32,97,110,100,32,119,101,32,97,114,101,32,97,116,32,116,104,101,32,108,97,115,116,32,112,111,115,105,116,105,111,110,44,32,115,111,32,116,104,101,32,103,108,111,98,97,108,32,115,101,97,114,99,104,32,105,115,32,99,111,109,112,108,101,116,101,46>>]}]}]},{p,[],[<<84,104,101,32,114,101,115,117,108,116,32,111,102,32,116,104,101,32,99,97,108,108,32,105,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,91,123,48,44,48,125,44,123,48,44,48,125,93,44,91,123,49,44,48,125,44,123,49,44,48,125,93,44,91,123,49,44,50,125,44,123,49,44,50,125,93,44,91,123,51,44,48,125,44,123,51,44,48,125,93,93,125>>]}]}]},{dt,[],[{code,[],[<<110,111,116,101,109,112,116,121>>]}]},{dd,[],[{p,[],[<<65,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,105,115,32,110,111,116,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,32,97,32,118,97,108,105,100,32,109,97,116,99,104,32,105,102,32,116,104,105,115,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,46,32,73,102,32,97,108,116,101,114,110,97,116,105,118,101,115,32,105,110,32,116,104,101,32,112,97,116,116,101,114,110,32,101,120,105,115,116,44,32,116,104,101,121,32,97,114,101,32,116,114,105,101,100,46,32,73,102,32,97,108,108,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,115,32,109,97,116,99,104,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,44,32,116,104,101,32,101,110,116,105,114,101,32,109,97,116,99,104,32,102,97,105,108,115,46>>]},{p,[],[{em,[],[<<69,120,97,109,112,108,101,58>>]}]},{p,[],[<<73,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,112,97,116,116,101,114,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,97,32,115,116,114,105,110,103,32,110,111,116,32,98,101,103,105,110,110,105,110,103,32,119,105,116,104,32,34,97,34,32,111,114,32,34,98,34,44,32,105,116,32,119,111,117,108,100,32,110,111,114,109,97,108,108,121,32,109,97,116,99,104,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,58>>]},{pre,[],[{code,[],[<<97,63,98,63>>]}]},{p,[],[<<87,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<110,111,116,101,109,112,116,121>>]},<<44,32,116,104,105,115,32,109,97,116,99,104,32,105,115,32,105,110,118,97,108,105,100,44,32,115,111,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,115,101,97,114,99,104,101,115,32,102,117,114,116,104,101,114,32,105,110,116,111,32,116,104,101,32,115,116,114,105,110,103,32,102,111,114,32,111,99,99,117,114,114,101,110,99,101,115,32,111,102,32,34,97,34,32,111,114,32,34,98,34,46>>]}]},{dt,[],[{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]}]},{dd,[],[{p,[],[<<76,105,107,101,32>>,{code,[],[<<110,111,116,101,109,112,116,121>>]},<<44,32,101,120,99,101,112,116,32,116,104,97,116,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,109,97,116,99,104,32,116,104,97,116,32,105,115,32,110,111,116,32,97,116,32,116,104,101,32,115,116,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,105,115,32,112,101,114,109,105,116,116,101,100,46,32,73,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,97,110,99,104,111,114,101,100,44,32,115,117,99,104,32,97,32,109,97,116,99,104,32,99,97,110,32,111,99,99,117,114,32,111,110,108,121,32,105,102,32,116,104,101,32,112,97,116,116,101,114,110,32,99,111,110,116,97,105,110,115,32,92,75,46>>]},{p,[],[<<80,101,114,108,32,104,97,115,32,110,111,32,100,105,114,101,99,116,32,101,113,117,105,118,97,108,101,110,116,32,111,102,32>>,{code,[],[<<110,111,116,101,109,112,116,121>>]},<<32,111,114,32>>,{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]},<<44,32,98,117,116,32,105,116,32,100,111,101,115,32,109,97,107,101,32,97,32,115,112,101,99,105,97,108,32,99,97,115,101,32,111,102,32,97,32,112,97,116,116,101,114,110,32,109,97,116,99,104,32,111,102,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,32,119,105,116,104,105,110,32,105,116,115,32,115,112,108,105,116,40,41,32,102,117,110,99,116,105,111,110,44,32,97,110,100,32,119,104,101,110,32,117,115,105,110,103,32,109,111,100,105,102,105,101,114,32>>,{code,[],[<<47,103>>]},<<46,32,84,104,101,32,80,101,114,108,32,98,101,104,97,118,105,111,114,32,99,97,110,32,98,101,32,101,109,117,108,97,116,101,100,32,97,102,116,101,114,32,109,97,116,99,104,105,110,103,32,97,32,110,117,108,108,32,115,116,114,105,110,103,32,98,121,32,102,105,114,115,116,32,116,114,121,105,110,103,32,116,104,101,32,109,97,116,99,104,32,97,103,97,105,110,32,97,116,32,116,104,101,32,115,97,109,101,32,111,102,102,115,101,116,32,119,105,116,104,32>>,{code,[],[<<110,111,116,101,109,112,116,121,95,97,116,115,116,97,114,116>>]},<<32,97,110,100,32>>,{code,[],[<<97,110,99,104,111,114,101,100>>]},<<44,32,97,110,100,32,116,104,101,110,44,32,105,102,32,116,104,97,116,32,102,97,105,108,115,44,32,98,121,32,97,100,118,97,110,99,105,110,103,32,116,104,101,32,115,116,97,114,116,105,110,103,32,111,102,102,115,101,116,32,40,115,101,101,32,98,101,108,111,119,41,32,97,110,100,32,116,114,121,105,110,103,32,97,110,32,111,114,100,105,110,97,114,121,32,109,97,116,99,104,32,97,103,97,105,110,46>>]}]},{dt,[],[{code,[],[<<110,111,116,98,111,108>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,116,104,101,32,102,105,114,115,116,32,99,104,97,114,97,99,116,101,114,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,105,115,32,110,111,116,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,97,32,108,105,110,101,44,32,115,111,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,105,115,32,110,111,116,32,116,111,32,109,97,116,99,104,32,98,101,102,111,114,101,32,105,116,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,119,105,116,104,111,117,116,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,40,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,41,32,99,97,117,115,101,115,32,99,105,114,99,117,109,102,108,101,120,32,110,101,118,101,114,32,116,111,32,109,97,116,99,104,46,32,84,104,105,115,32,111,112,116,105,111,110,32,111,110,108,121,32,97,102,102,101,99,116,115,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,99,105,114,99,117,109,102,108,101,120,32,109,101,116,97,99,104,97,114,97,99,116,101,114,46,32,73,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,92,65,46>>]}]},{dt,[],[{code,[],[<<110,111,116,101,111,108>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,105,115,32,110,111,116,32,116,104,101,32,101,110,100,32,111,102,32,97,32,108,105,110,101,44,32,115,111,32,116,104,101,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,32,105,115,32,110,111,116,32,116,111,32,109,97,116,99,104,32,105,116,32,110,111,114,32,40,101,120,99,101,112,116,32,105,110,32,109,117,108,116,105,108,105,110,101,32,109,111,100,101,41,32,97,32,110,101,119,108,105,110,101,32,105,109,109,101,100,105,97,116,101,108,121,32,98,101,102,111,114,101,32,105,116,46,32,83,101,116,116,105,110,103,32,116,104,105,115,32,119,105,116,104,111,117,116,32>>,{code,[],[<<109,117,108,116,105,108,105,110,101>>]},<<32,40,97,116,32,99,111,109,112,105,108,101,32,116,105,109,101,41,32,99,97,117,115,101,115,32,100,111,108,108,97,114,32,110,101,118,101,114,32,116,111,32,109,97,116,99,104,46,32,84,104,105,115,32,111,112,116,105,111,110,32,97,102,102,101,99,116,115,32,111,110,108,121,32,116,104,101,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,100,111,108,108,97,114,32,109,101,116,97,99,104,97,114,97,99,116,101,114,46,32,73,116,32,100,111,101,115,32,110,111,116,32,97,102,102,101,99,116,32,92,90,32,111,114,32,92,122,46>>]}]},{dt,[],[{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]}]},{dd,[],[{p,[],[<<71,105,118,101,115,32,98,101,116,116,101,114,32,99,111,110,116,114,111,108,32,111,102,32,116,104,101,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103,32,105,110,32>>,{code,[],[<<114,117,110,47,51>>]},<<46,32,87,104,101,110,32,115,112,101,99,105,102,105,101,100,44,32,99,111,109,112,105,108,97,116,105,111,110,32,101,114,114,111,114,115,32,40,105,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,110,111,116,32,97,108,114,101,97,100,121,32,99,111,109,112,105,108,101,100,41,32,97,110,100,32,114,117,110,116,105,109,101,32,101,114,114,111,114,115,32,97,114,101,32,101,120,112,108,105,99,105,116,108,121,32,114,101,116,117,114,110,101,100,32,97,115,32,97,110,32,101,114,114,111,114,32,116,117,112,108,101,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,112,111,115,115,105,98,108,101,32,114,117,110,116,105,109,101,32,101,114,114,111,114,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]}]},{dd,[],[{p,[],[<<84,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,32,115,101,116,115,32,97,32,108,105,109,105,116,32,111,110,32,104,111,119,32,109,97,110,121,32,116,105,109,101,115,32,116,104,101,32,105,110,116,101,114,110,97,108,32,109,97,116,99,104,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,99,97,108,108,101,100,46,32,68,101,102,97,117,108,116,115,32,116,111,32,49,48,44,48,48,48,44,48,48,48,32,105,110,32,116,104,101,32,108,105,98,114,97,114,121,32,99,111,109,112,105,108,101,100,32,102,111,114,32,69,114,108,97,110,103,46,32,73,102,32>>,{code,[],[<<123,101,114,114,111,114,44,32,109,97,116,99,104,95,108,105,109,105,116,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,44,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,111,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,104,97,115,32,114,101,97,99,104,101,100,32,116,104,105,115,32,108,105,109,105,116,46,32,84,104,105,115,32,105,115,32,110,111,114,109,97,108,108,121,32,116,111,32,98,101,32,114,101,103,97,114,100,101,100,32,97,115,32,97,32>>,{code,[],[<<110,111,109,97,116,99,104>>]},<<44,32,119,104,105,99,104,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,118,97,108,117,101,32,119,104,101,110,32,116,104,105,115,32,111,99,99,117,114,115,44,32,98,117,116,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<114,101,112,111,114,116,95,101,114,114,111,114,115>>]},<<44,32,121,111,117,32,97,114,101,32,105,110,102,111,114,109,101,100,32,119,104,101,110,32,116,104,101,32,109,97,116,99,104,32,102,97,105,108,115,32,98,101,99,97,117,115,101,32,111,102,32,116,111,111,32,109,97,110,121,32,105,110,116,101,114,110,97,108,32,99,97,108,108,115,46>>]}]},{dt,[],[{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]}]},{dd,[],[{p,[],[<<84,104,105,115,32,101,114,114,111,114,32,105,115,32,118,101,114,121,32,115,105,109,105,108,97,114,32,116,111,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<44,32,98,117,116,32,111,99,99,117,114,115,32,119,104,101,110,32,116,104,101,32,105,110,116,101,114,110,97,108,32,109,97,116,99,104,32,102,117,110,99,116,105,111,110,32,111,102,32,80,67,82,69,32,105,115,32,34,114,101,99,117,114,115,105,118,101,108,121,34,32,99,97,108,108,101,100,32,109,111,114,101,32,116,105,109,101,115,32,116,104,97,110,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]},<<32,108,105,109,105,116,44,32,119,104,105,99,104,32,100,101,102,97,117,108,116,115,32,116,111,32,49,48,44,48,48,48,44,48,48,48,32,97,115,32,119,101,108,108,46,32,78,111,116,105,99,101,32,116,104,97,116,32,97,115,32,108,111,110,103,32,97,115,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,97,110,100,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,100,101,102,97,117,108,116>>]},<<32,118,97,108,117,101,115,32,97,114,101,32,107,101,112,116,32,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,115,44,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110>>]},<<32,101,114,114,111,114,32,99,97,110,110,111,116,32,111,99,99,117,114,44,32,97,115,32,116,104,101,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,101,114,114,111,114,32,111,99,99,117,114,115,32,98,101,102,111,114,101,32,116,104,97,116,32,40,101,97,99,104,32,114,101,99,117,114,115,105,118,101,32,99,97,108,108,32,105,115,32,97,108,115,111,32,97,32,99,97,108,108,44,32,98,117,116,32,110,111,116,32,99,111,110,118,101,114,115,101,108,121,41,46,32,66,111,116,104,32,108,105,109,105,116,115,32,99,97,110,32,104,111,119,101,118,101,114,32,98,101,32,99,104,97,110,103,101,100,44,32,101,105,116,104,101,114,32,98,121,32,115,101,116,116,105,110,103,32,108,105,109,105,116,115,32,100,105,114,101,99,116,108,121,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,115,116,114,105,110,103,32,40,115,101,101,32,115,101,99,116,105,111,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,101,103,101,120,112,95,115,121,110,116,97,120,95,100,101,116,97,105,108,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<80,67,82,69,32,82,101,103,117,108,97,114,32,69,101,120,112,114,101,115,115,105,111,110,32,68,101,116,97,105,108,115>>]},<<41,32,111,114,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32,111,112,116,105,111,110,115,32,116,111,32>>,{code,[],[<<114,117,110,47,51>>]},<<46>>]}]}]},{p,[],[<<73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32,116,111,32,117,110,100,101,114,115,116,97,110,100,32,116,104,97,116,32,119,104,97,116,32,105,115,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,34,114,101,99,117,114,115,105,111,110,34,32,119,104,101,110,32,108,105,109,105,116,105,110,103,32,109,97,116,99,104,101,115,32,105,115,32,110,111,116,32,114,101,99,117,114,115,105,111,110,32,111,110,32,116,104,101,32,67,32,115,116,97,99,107,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,109,97,99,104,105,110,101,32,111,114,32,111,110,32,116,104,101,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,32,115,116,97,99,107,46,32,84,104,101,32,80,67,82,69,32,118,101,114,115,105,111,110,32,99,111,109,112,105,108,101,100,32,105,110,116,111,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,117,115,101,115,32,109,97,99,104,105,110,101,32,34,104,101,97,112,34,32,109,101,109,111,114,121,32,116,111,32,115,116,111,114,101,32,118,97,108,117,101,115,32,116,104,97,116,32,109,117,115,116,32,98,101,32,107,101,112,116,32,111,118,101,114,32,114,101,99,117,114,115,105,111,110,32,105,110,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,115,46>>]}]},{dt,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<76,105,109,105,116,115,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,111,102,32,97,32,109,97,116,99,104,32,105,110,32,97,110,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,115,112,101,99,105,102,105,99,32,119,97,121,46,32,73,116,32,105,115,32,100,101,115,99,114,105,98,101,100,32,97,115,32,102,111,108,108,111,119,115,32,98,121,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<84,104,101,32,109,97,116,99,104,95,108,105,109,105,116,32,102,105,101,108,100,32,112,114,111,118,105,100,101,115,32,97,32,109,101,97,110,115,32,111,102,32,112,114,101,118,101,110,116,105,110,103,32,80,67,82,69,32,102,114,111,109,32,117,115,105,110,103,10,117,112,32,97,32,118,97,115,116,32,97,109,111,117,110,116,32,111,102,32,114,101,115,111,117,114,99,101,115,32,119,104,101,110,32,114,117,110,110,105,110,103,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,103,111,105,110,103,10,116,111,32,109,97,116,99,104,44,32,98,117,116,32,119,104,105,99,104,32,104,97,118,101,32,97,32,118,101,114,121,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,112,111,115,115,105,98,105,108,105,116,105,101,115,32,105,110,32,116,104,101,105,114,10,115,101,97,114,99,104,32,116,114,101,101,115,46,32,84,104,101,32,99,108,97,115,115,105,99,32,101,120,97,109,112,108,101,32,105,115,32,97,32,112,97,116,116,101,114,110,32,116,104,97,116,32,117,115,101,115,32,110,101,115,116,101,100,10,117,110,108,105,109,105,116,101,100,32,114,101,112,101,97,116,115,46,10,10,73,110,116,101,114,110,97,108,108,121,44,32,112,99,114,101,95,101,120,101,99,40,41,32,117,115,101,115,32,97,32,102,117,110,99,116,105,111,110,32,99,97,108,108,101,100,32,109,97,116,99,104,40,41,44,32,119,104,105,99,104,32,105,116,32,99,97,108,108,115,10,114,101,112,101,97,116,101,100,108,121,32,40,115,111,109,101,116,105,109,101,115,32,114,101,99,117,114,115,105,118,101,108,121,41,46,32,84,104,101,32,108,105,109,105,116,32,115,101,116,32,98,121,32,109,97,116,99,104,95,108,105,109,105,116,32,105,115,10,105,109,112,111,115,101,100,32,111,110,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,116,104,105,115,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,100,117,114,105,110,103,32,97,32,109,97,116,99,104,44,10,119,104,105,99,104,32,104,97,115,32,116,104,101,32,101,102,102,101,99,116,32,111,102,32,108,105,109,105,116,105,110,103,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,98,97,99,107,116,114,97,99,107,105,110,103,32,116,104,97,116,32,99,97,110,10,116,97,107,101,32,112,108,97,99,101,46,32,70,111,114,32,112,97,116,116,101,114,110,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,97,110,99,104,111,114,101,100,44,32,116,104,101,32,99,111,117,110,116,32,114,101,115,116,97,114,116,115,10,102,114,111,109,32,122,101,114,111,32,102,111,114,32,101,97,99,104,32,112,111,115,105,116,105,111,110,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46>>]}]},{p,[],[<<84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,114,117,110,97,119,97,121,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,115,32,99,97,110,32,102,97,105,108,32,102,97,115,116,101,114,32,105,102,32,116,104,101,32,108,105,109,105,116,32,105,115,32,108,111,119,101,114,101,100,32,117,115,105,110,103,32,116,104,105,115,32,111,112,116,105,111,110,46,32,84,104,101,32,100,101,102,97,117,108,116,32,118,97,108,117,101,32,49,48,44,48,48,48,44,48,48,48,32,105,115,32,99,111,109,112,105,108,101,100,32,105,110,116,111,32,116,104,101,32,69,114,108,97,110,103,32,86,77,46>>]},{'div',[{class,<<110,111,116,101>>}],[{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,100,111,101,115,32,105,110,32,110,111,32,119,97,121,32,97,102,102,101,99,116,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,86,77,32,105,110,32,116,101,114,109,115,32,111,102,32,34,108,111,110,103,32,114,117,110,110,105,110,103,32,66,73,70,115,34,46,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,97,108,119,97,121,115,32,103,105,118,101,115,32,99,111,110,116,114,111,108,32,98,97,99,107,32,116,111,32,116,104,101,32,115,99,104,101,100,117,108,101,114,32,111,102,32,69,114,108,97,110,103,32,112,114,111,99,101,115,115,101,115,32,97,116,32,105,110,116,101,114,118,97,108,115,32,116,104,97,116,32,101,110,115,117,114,101,115,32,116,104,101,32,114,101,97,108,45,116,105,109,101,32,112,114,111,112,101,114,116,105,101,115,32,111,102,32,116,104,101,32,69,114,108,97,110,103,32,115,121,115,116,101,109,46>>]}]}]},{dt,[],[{code,[],[<<123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<76,105,109,105,116,115,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,97,110,100,32,109,101,109,111,114,121,32,99,111,110,115,117,109,112,116,105,111,110,32,111,102,32,97,32,109,97,116,99,104,32,105,110,32,97,110,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,45,115,112,101,99,105,102,105,99,32,119,97,121,44,32,118,101,114,121,32,115,105,109,105,108,97,114,32,116,111,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<46,32,73,116,32,105,115,32,100,101,115,99,114,105,98,101,100,32,97,115,32,102,111,108,108,111,119,115,32,98,121,32,116,104,101,32,80,67,82,69,32,100,111,99,117,109,101,110,116,97,116,105,111,110,58>>]},{pre,[],[{code,[],[<<84,104,101,32,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,32,102,105,101,108,100,32,105,115,32,115,105,109,105,108,97,114,32,116,111,32,109,97,116,99,104,95,108,105,109,105,116,44,32,98,117,116,32,105,110,115,116,101,97,100,10,111,102,32,108,105,109,105,116,105,110,103,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,116,105,109,101,115,32,116,104,97,116,32,109,97,116,99,104,40,41,32,105,115,32,99,97,108,108,101,100,44,32,105,116,10,108,105,109,105,116,115,32,116,104,101,32,100,101,112,116,104,32,111,102,32,114,101,99,117,114,115,105,111,110,46,32,84,104,101,32,114,101,99,117,114,115,105,111,110,32,100,101,112,116,104,32,105,115,32,97,32,115,109,97,108,108,101,114,32,110,117,109,98,101,114,10,116,104,97,110,32,116,104,101,32,116,111,116,97,108,32,110,117,109,98,101,114,32,111,102,32,99,97,108,108,115,44,32,98,101,99,97,117,115,101,32,110,111,116,32,97,108,108,32,99,97,108,108,115,32,116,111,32,109,97,116,99,104,40,41,32,97,114,101,10,114,101,99,117,114,115,105,118,101,46,32,84,104,105,115,32,108,105,109,105,116,32,105,115,32,111,102,32,117,115,101,32,111,110,108,121,32,105,102,32,105,116,32,105,115,32,115,101,116,32,115,109,97,108,108,101,114,32,116,104,97,110,10,109,97,116,99,104,95,108,105,109,105,116,46,10,10,76,105,109,105,116,105,110,103,32,116,104,101,32,114,101,99,117,114,115,105,111,110,32,100,101,112,116,104,32,108,105,109,105,116,115,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,109,97,99,104,105,110,101,32,115,116,97,99,107,32,116,104,97,116,10,99,97,110,32,98,101,32,117,115,101,100,44,32,111,114,44,32,119,104,101,110,32,80,67,82,69,32,104,97,115,32,98,101,101,110,32,99,111,109,112,105,108,101,100,32,116,111,32,117,115,101,32,109,101,109,111,114,121,32,111,110,32,116,104,101,32,104,101,97,112,10,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32,115,116,97,99,107,44,32,116,104,101,32,97,109,111,117,110,116,32,111,102,32,104,101,97,112,32,109,101,109,111,114,121,32,116,104,97,116,32,99,97,110,32,98,101,32,117,115,101,100,46>>]}]},{p,[],[<<84,104,101,32,69,114,108,97,110,103,32,86,77,32,117,115,101,115,32,97,32,80,67,82,69,32,108,105,98,114,97,114,121,32,119,104,101,114,101,32,104,101,97,112,32,109,101,109,111,114,121,32,105,115,32,117,115,101,100,32,119,104,101,110,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,32,114,101,99,117,114,115,105,111,110,32,111,99,99,117,114,115,46,32,84,104,105,115,32,116,104,101,114,101,102,111,114,101,32,108,105,109,105,116,115,32,116,104,101,32,117,115,101,32,111,102,32,109,97,99,104,105,110,101,32,104,101,97,112,44,32,110,111,116,32,67,32,115,116,97,99,107,46>>]},{p,[],[<<83,112,101,99,105,102,121,105,110,103,32,97,32,108,111,119,101,114,32,118,97,108,117,101,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,109,97,116,99,104,101,115,32,119,105,116,104,32,100,101,101,112,32,114,101,99,117,114,115,105,111,110,32,102,97,105,108,105,110,103,44,32,119,104,101,110,32,116,104,101,121,32,115,104,111,117,108,100,32,104,97,118,101,32,109,97,116,99,104,101,100,58>>]},{pre,[],[{code,[{type,<<110,111,110,101>>}],[<<49,62,32,114,101,58,114,117,110,40,34,97,97,97,97,97,97,97,97,97,97,97,97,97,122,34,44,34,40,97,43,41,42,122,34,41,46,10,123,109,97,116,99,104,44,91,123,48,44,49,52,125,44,123,48,44,49,51,125,93,125,10,50,62,32,114,101,58,114,117,110,40,34,97,97,97,97,97,97,97,97,97,97,97,97,97,122,34,44,34,40,97,43,41,42,122,34,44,91,123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,53,125,93,41,46,10,110,111,109,97,116,99,104,10,51,62,32,114,101,58,114,117,110,40,34,97,97,97,97,97,97,97,97,97,97,97,97,97,122,34,44,34,40,97,43,41,42,122,34,44,91,123,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,44,53,125,44,114,101,112,111,114,116,95,101,114,114,111,114,115,93,41,46,10,123,101,114,114,111,114,44,109,97,116,99,104,95,108,105,109,105,116,95,114,101,99,117,114,115,105,111,110,125>>]}]},{p,[],[<<84,104,105,115,32,111,112,116,105,111,110,32,97,110,100,32,111,112,116,105,111,110,32>>,{code,[],[<<109,97,116,99,104,95,108,105,109,105,116>>]},<<32,97,114,101,32,111,110,108,121,32,116,111,32,98,101,32,117,115,101,100,32,105,110,32,114,97,114,101,32,99,97,115,101,115,46,32,85,110,100,101,114,115,116,97,110,100,105,110,103,32,111,102,32,116,104,101,32,80,67,82,69,32,108,105,98,114,97,114,121,32,105,110,116,101,114,110,97,108,115,32,105,115,32,114,101,99,111,109,109,101,110,100,101,100,32,98,101,102,111,114,101,32,116,97,109,112,101,114,105,110,103,32,119,105,116,104,32,116,104,101,115,101,32,108,105,109,105,116,115,46>>]}]},{dt,[],[{code,[],[<<123,111,102,102,115,101,116,44,32,105,110,116,101,103,101,114,40,41,32,62,61,32,48,125>>]}]},{dd,[],[{p,[],[<<83,116,97,114,116,32,109,97,116,99,104,105,110,103,32,97,116,32,116,104,101,32,111,102,102,115,101,116,32,40,112,111,115,105,116,105,111,110,41,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,84,104,101,32,111,102,102,115,101,116,32,105,115,32,122,101,114,111,45,98,97,115,101,100,44,32,115,111,32,116,104,97,116,32,116,104,101,32,100,101,102,97,117,108,116,32,105,115,32>>,{code,[],[<<123,111,102,102,115,101,116,44,48,125>>]},<<32,40,97,108,108,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,41,46>>]}]},{dt,[],[{code,[],[<<123,110,101,119,108,105,110,101,44,32,78,76,83,112,101,99,125>>]}]},{dd,[],[{p,[],[<<79,118,101,114,114,105,100,101,115,32,116,104,101,32,100,101,102,97,117,108,116,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,97,32,110,101,119,108,105,110,101,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,119,104,105,99,104,32,105,115,32,76,70,32,40,65,83,67,73,73,32,49,48,41,32,105,110,32,69,114,108,97,110,103,46>>]},{dl,[],[{dt,[],[{code,[],[<<99,114>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,67,82,32,40,65,83,67,73,73,32,49,51,41,46>>]}]},{dt,[],[{code,[],[<<108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,97,32,115,105,110,103,108,101,32,99,104,97,114,97,99,116,101,114,32,76,70,32,40,65,83,67,73,73,32,49,48,41,44,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<99,114,108,102>>]}]},{dd,[],[{p,[],[<<78,101,119,108,105,110,101,32,105,115,32,105,110,100,105,99,97,116,101,100,32,98,121,32,116,104,101,32,116,119,111,45,99,104,97,114,97,99,116,101,114,32,67,82,76,70,32,40,65,83,67,73,73,32,49,51,32,102,111,108,108,111,119,101,100,32,98,121,32,65,83,67,73,73,32,49,48,41,32,115,101,113,117,101,110,99,101,46>>]}]},{dt,[],[{code,[],[<<97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,116,104,114,101,101,32,112,114,101,99,101,100,105,110,103,32,115,101,113,117,101,110,99,101,115,32,105,115,32,98,101,32,114,101,99,111,103,110,105,122,101,100,46>>]}]},{dt,[],[{code,[],[<<97,110,121>>]}]},{dd,[],[{p,[],[<<65,110,121,32,111,102,32,116,104,101,32,110,101,119,108,105,110,101,32,115,101,113,117,101,110,99,101,115,32,97,98,111,118,101,44,32,97,110,100,32,116,104,101,32,85,110,105,99,111,100,101,32,115,101,113,117,101,110,99,101,115,32,86,84,32,40,118,101,114,116,105,99,97,108,32,116,97,98,44,32,85,43,48,48,48,66,41,44,32,70,70,32,40,102,111,114,109,102,101,101,100,44,32,85,43,48,48,48,67,41,44,32,78,69,76,32,40,110,101,120,116,32,108,105,110,101,44,32,85,43,48,48,56,53,41,44,32,76,83,32,40,108,105,110,101,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,56,41,44,32,97,110,100,32,80,83,32,40,112,97,114,97,103,114,97,112,104,32,115,101,112,97,114,97,116,111,114,44,32,85,43,50,48,50,57,41,46>>]}]}]}]},{dt,[],[{code,[],[<<98,115,114,95,97,110,121,99,114,108,102>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,111,110,108,121,32,116,104,101,32,67,82,32,76,70,44,32,111,114,32,67,82,76,70,32,115,101,113,117,101,110,99,101,115,44,32,110,111,116,32,116,104,101,32,85,110,105,99,111,100,101,45,115,112,101,99,105,102,105,99,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,46,32,40,79,118,101,114,114,105,100,101,115,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,46,41>>]}]},{dt,[],[{code,[],[<<98,115,114,95,117,110,105,99,111,100,101>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,115,112,101,99,105,102,105,99,97,108,108,121,32,116,104,97,116,32,92,82,32,105,115,32,116,111,32,109,97,116,99,104,32,97,108,108,32,116,104,101,32,85,110,105,99,111,100,101,32,110,101,119,108,105,110,101,32,99,104,97,114,97,99,116,101,114,115,32,40,105,110,99,108,117,100,105,110,103,32,67,82,76,70,44,32,97,110,100,32,115,111,32,111,110,44,32,116,104,101,32,100,101,102,97,117,108,116,41,46,32,40,79,118,101,114,114,105,100,101,115,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,46,41>>]}]},{dt,[],[{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,125>>]},<<47>>,{code,[],[<<123,99,97,112,116,117,114,101,44,32,86,97,108,117,101,83,112,101,99,44,32,84,121,112,101,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,119,104,105,99,104,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,110,100,32,105,110,32,119,104,97,116,32,102,111,114,109,97,116,46,32,66,121,32,100,101,102,97,117,108,116,44,32>>,{code,[],[<<114,117,110,47,51>>]},<<32,99,97,112,116,117,114,101,115,32,97,108,108,32,111,102,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,115,116,114,105,110,103,32,97,110,100,32,97,108,108,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,40,97,108,108,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,32,105,115,32,97,117,116,111,109,97,116,105,99,97,108,108,121,32,99,97,112,116,117,114,101,100,41,46,32,84,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32,40,122,101,114,111,45,98,97,115,101,100,41,32,105,110,100,101,120,101,115,32,111,102,32,116,104,101,32,99,97,112,116,117,114,101,100,32,112,97,114,116,115,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,115,112,101,99,105,102,105,101,100,32,97,115,32>>,{code,[],[<<123,79,102,102,115,101,116,44,76,101,110,103,116,104,125>>]},<<32,112,97,105,114,115,32,40,116,104,101,32>>,{code,[],[<<105,110,100,101,120>>]},<<32>>,{code,[],[<<84,121,112,101>>]},<<32,111,102,32,99,97,112,116,117,114,105,110,103,41,46>>]},{p,[],[<<65,115,32,97,110,32,101,120,97,109,112,108,101,32,111,102,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,44,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,32,114,101,116,117,114,110,115,44,32,97,115,32,102,105,114,115,116,32,97,110,100,32,111,110,108,121,32,99,97,112,116,117,114,101,100,32,115,116,114,105,110,103,44,32,116,104,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,40,34,97,98,99,100,34,32,105,110,32,116,104,101,32,109,105,100,100,108,101,41,32,97,115,32,97,110,32,105,110,100,101,120,32,112,97,105,114,32>>,{code,[],[<<123,51,44,52,125>>]},<<44,32,119,104,101,114,101,32,99,104,97,114,97,99,116,101,114,32,112,111,115,105,116,105,111,110,115,32,97,114,101,32,122,101,114,111,45,98,97,115,101,100,44,32,106,117,115,116,32,97,115,32,105,110,32,111,102,102,115,101,116,115,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,97,98,99,100,34,44,91,93,41,46>>]}]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32,116,104,105,115,32,99,97,108,108,32,105,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,51,44,52,125,93,125>>]}]},{p,[],[<<65,110,111,116,104,101,114,32,40,97,110,100,32,113,117,105,116,101,32,99,111,109,109,111,110,41,32,99,97,115,101,32,105,115,32,119,104,101,114,101,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,115,32,97,108,108,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,97,98,99,100,46,42,34,44,91,93,41,46>>]}]},{p,[],[<<72,101,114,101,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,99,111,114,114,101,115,112,111,110,100,105,110,103,108,121,32,112,111,105,110,116,115,32,111,117,116,32,97,108,108,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,98,101,103,105,110,110,105,110,103,32,97,116,32,105,110,100,101,120,32,48,44,32,97,110,100,32,105,116,32,105,115,32,49,48,32,99,104,97,114,97,99,116,101,114,115,32,108,111,110,103,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,48,44,49,48,125,93,125>>]}]},{p,[],[<<73,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,99,111,110,116,97,105,110,115,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,108,105,107,101,32,105,110,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,97,98,99,100,41,46,42,34,44,91,93,41,46>>]}]},{p,[],[<<97,108,108,32,111,102,32,116,104,101,32,109,97,116,99,104,101,100,32,115,117,98,106,101,99,116,32,105,115,32,99,97,112,116,117,114,101,100,44,32,97,115,32,119,101,108,108,32,97,115,32,116,104,101,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,48,44,49,48,125,44,123,51,44,52,125,93,125>>]}]},{p,[],[<<84,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,112,97,116,116,101,114,110,32,97,108,119,97,121,115,32,103,105,118,101,115,32,116,104,101,32,102,105,114,115,116,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,110,32,116,104,101,32,108,105,115,116,32,97,110,100,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,97,100,100,101,100,32,105,110,32,116,104,101,32,111,114,100,101,114,32,116,104,101,121,32,111,99,99,117,114,114,101,100,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<84,104,101,32,99,97,112,116,117,114,101,32,116,117,112,108,101,32,105,115,32,98,117,105,108,116,32,117,112,32,97,115,32,102,111,108,108,111,119,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<86,97,108,117,101,83,112,101,99>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,119,104,105,99,104,32,99,97,112,116,117,114,101,100,32,40,115,117,98,41,112,97,116,116,101,114,110,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32>>,{code,[],[<<86,97,108,117,101,83,112,101,99>>]},<<32,99,97,110,32,101,105,116,104,101,114,32,98,101,32,97,110,32,97,116,111,109,32,100,101,115,99,114,105,98,105,110,103,32,97,32,112,114,101,100,101,102,105,110,101,100,32,115,101,116,32,111,102,32,114,101,116,117,114,110,32,118,97,108,117,101,115,44,32,111,114,32,97,32,108,105,115,116,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,105,110,100,101,120,101,115,32,111,114,32,116,104,101,32,110,97,109,101,115,32,111,102,32,115,112,101,99,105,102,105,99,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,114,101,116,117,114,110,46>>]},{p,[],[<<84,104,101,32,102,111,108,108,111,119,105,110,103,32,97,114,101,32,116,104,101,32,112,114,101,100,101,102,105,110,101,100,32,115,101,116,115,32,111,102,32,115,117,98,112,97,116,116,101,114,110,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<97,108,108>>]}]},{dd,[],[{p,[],[<<65,108,108,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,115,116,114,105,110,103,46,32,84,104,105,115,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<97,108,108,95,110,97,109,101,115>>]}]},{dd,[],[{p,[],[<<65,108,108,32>>,{em,[],[<<110,97,109,101,100>>]},<<32,115,117,98,112,97,116,116,101,114,110,115,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,97,115,32,105,102,32,97,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,111,102,32,97,108,108,32,116,104,101,32,110,97,109,101,115,32>>,{em,[],[<<105,110,32,97,108,112,104,97,98,101,116,105,99,97,108,32,111,114,100,101,114>>]},<<32,119,97,115,32,115,112,101,99,105,102,105,101,100,46,32,84,104,101,32,108,105,115,116,32,111,102,32,97,108,108,32,110,97,109,101,115,32,99,97,110,32,97,108,115,111,32,98,101,32,114,101,116,114,105,101,118,101,100,32,119,105,116,104,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,105,110,115,112,101,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,110,115,112,101,99,116,47,50>>]}]},<<46>>]}]},{dt,[],[{code,[],[<<102,105,114,115,116>>]}]},{dd,[],[{p,[],[<<79,110,108,121,32,116,104,101,32,102,105,114,115,116,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,44,32,119,104,105,99,104,32,105,115,32,97,108,119,97,121,115,32,116,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,46,32,65,108,108,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,100,105,115,99,97,114,100,101,100,46>>]}]},{dt,[],[{code,[],[<<97,108,108,95,98,117,116,95,102,105,114,115,116>>]}]},{dd,[],[{p,[],[<<65,108,108,32,98,117,116,32,116,104,101,32,102,105,114,115,116,32,109,97,116,99,104,105,110,103,32,115,117,98,112,97,116,116,101,114,110,44,32,116,104,97,116,32,105,115,44,32,97,108,108,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,44,32,98,117,116,32,110,111,116,32,116,104,101,32,99,111,109,112,108,101,116,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,46,32,84,104,105,115,32,105,115,32,117,115,101,102,117,108,32,105,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,115,32,97,32,119,104,111,108,101,32,109,97,116,99,104,101,115,32,97,32,108,97,114,103,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,44,32,98,117,116,32,116,104,101,32,112,97,114,116,32,121,111,117,32,97,114,101,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,105,115,32,105,110,32,97,110,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,46,32,73,102,32,116,104,101,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32>>,{code,[],[<<108,105,115,116>>]},<<32,111,114,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<44,32,110,111,116,32,114,101,116,117,114,110,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,121,111,117,32,97,114,101,32,110,111,116,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,105,115,32,97,32,103,111,111,100,32,119,97,121,32,116,111,32,111,112,116,105,109,105,122,101,46>>]}]},{dt,[],[{code,[],[<<110,111,110,101>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,110,111,32,109,97,116,99,104,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,103,105,118,101,115,32,116,104,101,32,115,105,110,103,108,101,32,97,116,111,109,32>>,{code,[],[<<109,97,116,99,104>>]},<<32,97,115,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,119,104,101,110,32,109,97,116,99,104,105,110,103,32,115,117,99,99,101,115,115,102,117,108,108,121,32,105,110,115,116,101,97,100,32,111,102,32,116,104,101,32>>,{code,[],[<<123,109,97,116,99,104,44,32,108,105,115,116,40,41,125>>]},<<32,114,101,116,117,114,110,46,32,83,112,101,99,105,102,121,105,110,103,32,97,110,32,101,109,112,116,121,32,108,105,115,116,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,98,101,104,97,118,105,111,114,46>>]}]}]},{p,[],[<<84,104,101,32,118,97,108,117,101,32,108,105,115,116,32,105,115,32,97,32,108,105,115,116,32,111,102,32,105,110,100,101,120,101,115,32,102,111,114,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,114,101,116,117,114,110,44,32,119,104,101,114,101,32,105,110,100,101,120,32,48,32,105,115,32,102,111,114,32,97,108,108,32,111,102,32,116,104,101,32,112,97,116,116,101,114,110,44,32,97,110,100,32,49,32,105,115,32,102,111,114,32,116,104,101,32,102,105,114,115,116,32,101,120,112,108,105,99,105,116,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,97,110,100,32,115,111,32,111,110,46,32,87,104,101,110,32,117,115,105,110,103,32,110,97,109,101,100,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,40,115,101,101,32,98,101,108,111,119,41,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,111,110,101,32,99,97,110,32,117,115,101,32>>,{code,[],[<<97,116,111,109,40,41>>]},<<115,32,111,114,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<115,32,116,111,32,115,112,101,99,105,102,121,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,115,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,58>>]},{pre,[],[{code,[],[<<34,46,42,40,97,98,99,100,41,46,42,34>>]}]},{p,[],[<<109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,115,116,114,105,110,103,32,34,65,66,67,97,98,99,100,65,66,67,34,44,32,99,97,112,116,117,114,105,110,103,32,111,110,108,121,32,116,104,101,32,34,97,98,99,100,34,32,112,97,114,116,32,40,116,104,101,32,102,105,114,115,116,32,101,120,112,108,105,99,105,116,32,115,117,98,112,97,116,116,101,114,110,41,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,97,98,99,100,41,46,42,34,44,91,123,99,97,112,116,117,114,101,44,91,49,93,125,93,41,46>>]}]},{p,[],[<<84,104,101,32,99,97,108,108,32,103,105,118,101,115,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,101,115,117,108,116,44,32,97,115,32,116,104,101,32,102,105,114,115,116,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,34,40,97,98,99,100,41,34,44,32,109,97,116,99,104,105,110,103,32,34,97,98,99,100,34,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,44,32,97,116,32,40,122,101,114,111,45,98,97,115,101,100,41,32,112,111,115,105,116,105,111,110,32,51,44,32,111,102,32,108,101,110,103,116,104,32,52,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,51,44,52,125,93,125>>]}]},{p,[],[<<67,111,110,115,105,100,101,114,32,116,104,101,32,115,97,109,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,98,117,116,32,119,105,116,104,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,101,120,112,108,105,99,105,116,108,121,32,110,97,109,101,100,32,39,70,79,79,39,58>>]},{pre,[],[{code,[],[<<34,46,42,40,63,60,70,79,79,62,97,98,99,100,41,46,42,34>>]}]},{p,[],[<<87,105,116,104,32,116,104,105,115,32,101,120,112,114,101,115,115,105,111,110,44,32,119,101,32,99,111,117,108,100,32,115,116,105,108,108,32,103,105,118,101,32,116,104,101,32,105,110,100,101,120,32,111,102,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,119,105,116,104,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,97,108,108,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,63,60,70,79,79,62,97,98,99,100,41,46,42,34,44,91,123,99,97,112,116,117,114,101,44,91,49,93,125,93,41,46>>]}]},{p,[],[<<103,105,118,105,110,103,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,98,101,102,111,114,101,46,32,66,117,116,44,32,97,115,32,116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,105,115,32,110,97,109,101,100,44,32,119,101,32,99,97,110,32,97,108,115,111,32,115,112,101,99,105,102,121,32,105,116,115,32,110,97,109,101,32,105,110,32,116,104,101,32,118,97,108,117,101,32,108,105,115,116,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,65,66,67,97,98,99,100,65,66,67,34,44,34,46,42,40,63,60,70,79,79,62,97,98,99,100,41,46,42,34,44,91,123,99,97,112,116,117,114,101,44,91,39,70,79,79,39,93,125,93,41,46>>]}]},{p,[],[<<84,104,105,115,32,119,111,117,108,100,32,103,105,118,101,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,116,104,101,32,101,97,114,108,105,101,114,32,101,120,97,109,112,108,101,115,44,32,110,97,109,101,108,121,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,51,44,52,125,93,125>>]}]},{p,[],[<<84,104,101,32,118,97,108,117,101,115,32,108,105,115,116,32,99,97,110,32,115,112,101,99,105,102,121,32,105,110,100,101,120,101,115,32,111,114,32,110,97,109,101,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,105,110,32,119,104,105,99,104,32,99,97,115,101,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,115,32,118,97,114,121,32,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,116,121,112,101,46,32,73,102,32,116,104,101,32,116,121,112,101,32,105,115,32>>,{code,[],[<<105,110,100,101,120>>]},<<44,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,45,49,44,48,125>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,102,111,114,32,118,97,108,117,101,115,32,119,105,116,104,32,110,111,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,115,117,98,112,97,116,116,101,114,110,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,98,117,116,32,102,111,114,32,116,104,101,32,111,116,104,101,114,32,116,121,112,101,115,32,40>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,97,110,100,32>>,{code,[],[<<108,105,115,116>>]},<<41,44,32,116,104,101,32,118,97,108,117,101,115,32,97,114,101,32,116,104,101,32,101,109,112,116,121,32,98,105,110,97,114,121,32,111,114,32,108,105,115,116,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46>>]}]},{dt,[],[{code,[],[<<84,121,112,101>>]}]},{dd,[],[{p,[],[<<79,112,116,105,111,110,97,108,108,121,32,115,112,101,99,105,102,105,101,115,32,104,111,119,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,114,101,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32,73,102,32,111,109,105,116,116,101,100,44,32,116,104,101,32,100,101,102,97,117,108,116,32,111,102,32>>,{code,[],[<<105,110,100,101,120>>]},<<32,105,115,32,117,115,101,100,46>>]},{p,[],[{code,[],[<<84,121,112,101>>]},<<32,99,97,110,32,98,101,32,111,110,101,32,111,102,32,116,104,101,32,102,111,108,108,111,119,105,110,103,58>>]},{dl,[],[{dt,[],[{code,[],[<<105,110,100,101,120>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,99,97,112,116,117,114,101,100,32,115,117,98,115,116,114,105,110,103,115,32,97,115,32,112,97,105,114,115,32,111,102,32,98,121,116,101,32,105,110,100,101,120,101,115,32,105,110,116,111,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,97,110,100,32,108,101,110,103,116,104,32,111,102,32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,116,114,105,110,103,32,105,110,32,116,104,101,32,115,117,98,106,101,99,116,32,40,97,115,32,105,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,119,97,115,32,102,108,97,116,116,101,110,101,100,32,119,105,116,104,32>>,{a,[{href,<<101,114,116,115,58,101,114,108,97,110,103,35,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,114,108,97,110,103,58,105,111,108,105,115,116,95,116,111,95,98,105,110,97,114,121,47,49>>]}]},<<32,111,114,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,35,99,104,97,114,97,99,116,101,114,115,95,116,111,95,98,105,110,97,114,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,105,99,111,100,101,58,99,104,97,114,97,99,116,101,114,115,95,116,111,95,98,105,110,97,114,121,47,50>>]}]},<<32,98,101,102,111,114,101,32,109,97,116,99,104,105,110,103,41,46,32,78,111,116,105,99,101,32,116,104,97,116,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,114,101,115,117,108,116,115,32,105,110,32>>,{em,[],[<<98,121,116,101,45,111,114,105,101,110,116,101,100>>]},<<32,105,110,100,101,120,101,115,32,105,110,32,97,32,40,112,111,115,115,105,98,108,121,32,118,105,114,116,117,97,108,41,32>>,{em,[],[<<85,84,70,45,56,32,101,110,99,111,100,101,100>>]},<<32,98,105,110,97,114,121,46,32,65,32,98,121,116,101,32,105,110,100,101,120,32,116,117,112,108,101,32>>,{code,[],[<<123,48,44,50,125>>]},<<32,99,97,110,32,116,104,101,114,101,102,111,114,101,32,114,101,112,114,101,115,101,110,116,32,111,110,101,32,111,114,32,116,119,111,32,99,104,97,114,97,99,116,101,114,115,32,119,104,101,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,105,110,32,101,102,102,101,99,116,46,32,84,104,105,115,32,99,97,110,32,115,101,101,109,32,99,111,117,110,116,101,114,45,105,110,116,117,105,116,105,118,101,44,32,98,117,116,32,104,97,115,32,98,101,101,110,32,100,101,101,109,101,100,32,116,104,101,32,109,111,115,116,32,101,102,102,101,99,116,105,118,101,32,97,110,100,32,117,115,101,102,117,108,32,119,97,121,32,116,111,32,100,111,32,105,116,46,32,84,111,32,114,101,116,117,114,110,32,108,105,115,116,115,32,105,110,115,116,101,97,100,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,115,105,109,112,108,101,114,32,99,111,100,101,32,105,102,32,116,104,97,116,32,105,115,32,100,101,115,105,114,101,100,46,32,84,104,105,115,32,114,101,116,117,114,110,32,116,121,112,101,32,105,115,32,116,104,101,32,100,101,102,97,117,108,116,46>>]}]},{dt,[],[{code,[],[<<108,105,115,116>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,109,97,116,99,104,105,110,103,32,115,117,98,115,116,114,105,110,103,115,32,97,115,32,108,105,115,116,115,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,69,114,108,97,110,103,32>>,{code,[],[<<115,116,114,105,110,103,40,41>>]},<<115,41,46,32,73,116,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,117,115,101,100,32,105,110,32,99,111,109,98,105,110,97,116,105,111,110,32,119,105,116,104,32,116,104,101,32,92,67,32,115,101,113,117,101,110,99,101,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,97,32,99,97,112,116,117,114,101,100,32,115,117,98,112,97,116,116,101,114,110,32,99,97,110,32,99,111,110,116,97,105,110,32,98,121,116,101,115,32,116,104,97,116,32,97,114,101,32,110,111,116,32,118,97,108,105,100,32,85,84,70,45,56,32,40,92,67,32,109,97,116,99,104,101,115,32,98,121,116,101,115,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32,99,104,97,114,97,99,116,101,114,32,101,110,99,111,100,105,110,103,41,46,32,73,110,32,116,104,97,116,32,99,97,115,101,32,116,104,101,32>>,{code,[],[<<108,105,115,116>>]},<<32,99,97,112,116,117,114,105,110,103,32,99,97,110,32,114,101,115,117,108,116,32,105,110,32,116,104,101,32,115,97,109,101,32,116,121,112,101,115,32,111,102,32,116,117,112,108,101,115,32,116,104,97,116,32>>,{a,[{href,<<115,116,100,108,105,98,58,117,110,105,99,111,100,101,35,99,104,97,114,97,99,116,101,114,115,95,116,111,95,108,105,115,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,105,99,111,100,101,58,99,104,97,114,97,99,116,101,114,115,95,116,111,95,108,105,115,116,47,50>>]}]},<<32,99,97,110,32,114,101,116,117,114,110,44,32,110,97,109,101,108,121,32,116,104,114,101,101,45,116,117,112,108,101,115,32,119,105,116,104,32,116,97,103,32>>,{code,[],[<<105,110,99,111,109,112,108,101,116,101>>]},<<32,111,114,32>>,{code,[],[<<101,114,114,111,114>>]},<<44,32,116,104,101,32,115,117,99,99,101,115,115,102,117,108,108,121,32,99,111,110,118,101,114,116,101,100,32,99,104,97,114,97,99,116,101,114,115,32,97,110,100,32,116,104,101,32,105,110,118,97,108,105,100,32,85,84,70,45,56,32,116,97,105,108,32,111,102,32,116,104,101,32,99,111,110,118,101,114,115,105,111,110,32,97,115,32,97,32,98,105,110,97,114,121,46,32,84,104,101,32,98,101,115,116,32,115,116,114,97,116,101,103,121,32,105,115,32,116,111,32,97,118,111,105,100,32,117,115,105,110,103,32,116,104,101,32,92,67,32,115,101,113,117,101,110,99,101,32,119,104,101,110,32,99,97,112,116,117,114,105,110,103,32,108,105,115,116,115,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<82,101,116,117,114,110,115,32,109,97,116,99,104,105,110,103,32,115,117,98,115,116,114,105,110,103,115,32,97,115,32,98,105,110,97,114,105,101,115,46,32,73,102,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,105,115,32,117,115,101,100,44,32,116,104,101,115,101,32,98,105,110,97,114,105,101,115,32,97,114,101,32,105,110,32,85,84,70,45,56,46,32,73,102,32,116,104,101,32,92,67,32,115,101,113,117,101,110,99,101,32,105,115,32,117,115,101,100,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<44,32,116,104,101,32,98,105,110,97,114,105,101,115,32,99,97,110,32,98,101,32,105,110,118,97,108,105,100,32,85,84,70,45,56,46>>]}]}]}]}]},{p,[],[<<73,110,32,103,101,110,101,114,97,108,44,32,115,117,98,112,97,116,116,101,114,110,115,32,116,104,97,116,32,119,101,114,101,32,110,111,116,32,97,115,115,105,103,110,101,100,32,97,32,118,97,108,117,101,32,105,110,32,116,104,101,32,109,97,116,99,104,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,116,104,101,32,116,117,112,108,101,32>>,{code,[],[<<123,45,49,44,48,125>>]},<<32,119,104,101,110,32>>,{code,[],[<<116,121,112,101>>]},<<32,105,115,32>>,{code,[],[<<105,110,100,101,120>>]},<<46,32,85,110,97,115,115,105,103,110,101,100,32,115,117,98,112,97,116,116,101,114,110,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,97,115,32,116,104,101,32,101,109,112,116,121,32,98,105,110,97,114,121,32,111,114,32,108,105,115,116,44,32,114,101,115,112,101,99,116,105,118,101,108,121,44,32,102,111,114,32,111,116,104,101,114,32,114,101,116,117,114,110,32,116,121,112,101,115,46,32,67,111,110,115,105,100,101,114,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,58>>]},{pre,[],[{code,[],[<<34,46,42,40,40,63,60,70,79,79,62,97,98,100,100,41,124,97,40,46,46,100,41,41,46,42,34>>]}]},{p,[],[<<84,104,101,114,101,32,97,114,101,32,116,104,114,101,101,32,101,120,112,108,105,99,105,116,108,121,32,99,97,112,116,117,114,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,44,32,119,104,101,114,101,32,116,104,101,32,111,112,101,110,105,110,103,32,112,97,114,101,110,116,104,101,115,105,115,32,112,111,115,105,116,105,111,110,32,100,101,116,101,114,109,105,110,101,115,32,116,104,101,32,111,114,100,101,114,32,105,110,32,116,104,101,32,114,101,115,117,108,116,44,32,104,101,110,99,101,32>>,{code,[],[<<40,40,63,60,70,79,79,62,97,98,100,100,41,124,97,40,46,46,100,41,41>>]},<<32,105,115,32,115,117,98,112,97,116,116,101,114,110,32,105,110,100,101,120,32,49,44,32>>,{code,[],[<<40,63,60,70,79,79,62,97,98,100,100,41>>]},<<32,105,115,32,115,117,98,112,97,116,116,101,114,110,32,105,110,100,101,120,32,50,44,32,97,110,100,32>>,{code,[],[<<40,46,46,100,41>>]},<<32,105,115,32,115,117,98,112,97,116,116,101,114,110,32,105,110,100,101,120,32,51,46,32,87,104,101,110,32,109,97,116,99,104,101,100,32,97,103,97,105,110,115,116,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,115,116,114,105,110,103,58>>]},{pre,[],[{code,[],[<<34,65,66,67,97,98,99,100,65,66,67,34>>]}]},{p,[],[<<116,104,101,32,115,117,98,112,97,116,116,101,114,110,32,97,116,32,105,110,100,101,120,32,50,32,100,111,101,115,32,110,111,116,32,109,97,116,99,104,44,32,97,115,32,34,97,98,100,100,34,32,105,115,32,110,111,116,32,112,114,101,115,101,110,116,32,105,110,32,116,104,101,32,115,116,114,105,110,103,44,32,98,117,116,32,116,104,101,32,99,111,109,112,108,101,116,101,32,112,97,116,116,101,114,110,32,109,97,116,99,104,101,115,32,40,98,101,99,97,117,115,101,32,111,102,32,116,104,101,32,97,108,116,101,114,110,97,116,105,118,101,32>>,{code,[],[<<97,40,46,46,100,41>>]},<<41,46,32,84,104,101,32,115,117,98,112,97,116,116,101,114,110,32,97,116,32,105,110,100,101,120,32,50,32,105,115,32,116,104,101,114,101,102,111,114,101,32,117,110,97,115,115,105,103,110,101,100,32,97,110,100,32,116,104,101,32,100,101,102,97,117,108,116,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,123,48,44,49,48,125,44,123,51,44,52,125,44,123,45,49,44,48,125,44,123,52,44,51,125,93,125>>]}]},{p,[],[<<83,101,116,116,105,110,103,32,116,104,101,32,99,97,112,116,117,114,101,32>>,{code,[],[<<84,121,112,101>>]},<<32,116,111,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,103,105,118,101,115,58>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,60,60,34,65,66,67,97,98,99,100,65,66,67,34,62,62,44,60,60,34,97,98,99,100,34,62,62,44,60,60,62,62,44,60,60,34,98,99,100,34,62,62,93,125>>]}]},{p,[],[<<72,101,114,101,32,116,104,101,32,101,109,112,116,121,32,98,105,110,97,114,121,32,40>>,{code,[],[<<60,60,62,62>>]},<<41,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32,117,110,97,115,115,105,103,110,101,100,32,115,117,98,112,97,116,116,101,114,110,46,32,73,110,32,116,104,101,32>>,{code,[],[<<98,105,110,97,114,121>>]},<<32,99,97,115,101,44,32,115,111,109,101,32,105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,97,116,99,104,105,110,103,32,105,115,32,116,104,101,114,101,102,111,114,101,32,108,111,115,116,44,32,97,115,32>>,{code,[],[<<60,60,62,62>>]},<<32,99,97,110,32,97,108,115,111,32,98,101,32,97,110,32,101,109,112,116,121,32,115,116,114,105,110,103,32,99,97,112,116,117,114,101,100,46>>]},{p,[],[<<73,102,32,100,105,102,102,101,114,101,110,116,105,97,116,105,111,110,32,98,101,116,119,101,101,110,32,101,109,112,116,121,32,109,97,116,99,104,101,115,32,97,110,100,32,110,111,110,45,101,120,105,115,116,105,110,103,32,115,117,98,112,97,116,116,101,114,110,115,32,105,115,32,110,101,99,101,115,115,97,114,121,44,32,117,115,101,32,116,104,101,32>>,{code,[],[<<116,121,112,101>>]},<<32>>,{code,[],[<<105,110,100,101,120>>]},<<32,97,110,100,32,100,111,32,116,104,101,32,99,111,110,118,101,114,115,105,111,110,32,116,111,32,116,104,101,32,102,105,110,97,108,32,116,121,112,101,32,105,110,32,69,114,108,97,110,103,32,99,111,100,101,46>>]},{p,[],[<<87,104,101,110,32,111,112,116,105,111,110,32>>,{code,[],[<<103,108,111,98,97,108>>]},<<32,105,115,32,115,112,101,99,105,105,102,105,101,100,44,32,116,104,101,32>>,{code,[],[<<99,97,112,116,117,114,101>>]},<<32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,97,102,102,101,99,116,115,32,101,97,99,104,32,109,97,116,99,104,32,115,101,112,97,114,97,116,101,108,121,44,32,115,111,32,116,104,97,116,58>>]},{pre,[],[{code,[],[<<114,101,58,114,117,110,40,34,99,97,99,98,34,44,34,99,40,97,124,98,41,34,44,91,103,108,111,98,97,108,44,123,99,97,112,116,117,114,101,44,91,49,93,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<123,109,97,116,99,104,44,91,91,34,97,34,93,44,91,34,98,34,93,93,125>>]}]}]}]},{p,[],[<<70,111,114,32,97,32,100,101,115,99,114,105,112,116,105,111,110,115,32,111,102,32,111,112,116,105,111,110,115,32,111,110,108,121,32,97,102,102,101,99,116,105,110,103,32,116,104,101,32,99,111,109,112,105,108,97,116,105,111,110,32,115,116,101,112,44,32,115,101,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,99,111,109,112,105,108,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<99,111,109,112,105,108,101,47,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,52,49,57>>,signature => [{attribute,{76,2},spec,{{run,3},[{type,{76,10},bounded_fun,[{type,{76,10},'fun',[{type,{76,10},product,[{var,{76,11},'Subject'},{var,{76,20},'RE'},{var,{76,24},'Options'}]},{type,{76,36},union,[{type,{76,36},tuple,[{atom,{76,37},match},{var,{76,44},'Captured'}]},{atom,{77,36},match},{atom,{78,36},nomatch},{type,{79,8},tuple,[{atom,{79,9},error},{var,{79,16},'ErrType'}]}]}]},[{type,{80,7},constraint,[{atom,{80,7},is_subtype},[{var,{80,7},'Subject'},{type,{80,18},union,[{type,{80,18},iodata,[]},{remote_type,{80,29},[{atom,{80,29},unicode},{atom,{80,37},charlist},[]]}]}]]},{type,{81,7},constraint,[{atom,{81,7},is_subtype},[{var,{81,7},'RE'},{type,{81,13},union,[{user_type,{81,13},mp,[]},{type,{81,20},iodata,[]},{remote_type,{81,31},[{atom,{81,31},unicode},{atom,{81,39},charlist},[]]}]}]]},{type,{82,7},constraint,[{atom,{82,7},is_subtype},[{var,{82,7},'Options'},{type,{82,18},list,[{var,{82,19},'Option'}]}]]},{type,{83,7},constraint,[{atom,{83,7},is_subtype},[{var,{83,7},'Option'},{type,{83,17},union,[{atom,{83,17},anchored},{atom,{83,28},global},{atom,{83,37},notbol},{atom,{83,46},noteol},{atom,{83,55},notempty},{atom,{84,10},notempty_atstart},{atom,{84,29},report_errors},{type,{85,17},tuple,[{atom,{85,18},offset},{type,{85,26},non_neg_integer,[]}]},{type,{86,3},tuple,[{atom,{86,4},match_limit},{type,{86,17},non_neg_integer,[]}]},{type,{87,3},tuple,[{atom,{87,4},match_limit_recursion},{type,{87,27},non_neg_integer,[]}]},{type,{88,17},tuple,[{atom,{88,18},newline},{ann_type,{88,27},[{var,{88,27},'NLSpec'},{user_type,{88,37},nl_spec,[]}]}]},{atom,{89,17},bsr_anycrlf},{atom,{89,31},bsr_unicode},{type,{89,45},tuple,[{atom,{89,46},capture},{var,{89,55},'ValueSpec'}]},{type,{90,17},tuple,[{atom,{90,18},capture},{var,{90,27},'ValueSpec'},{var,{90,38},'Type'}]},{var,{90,46},'CompileOpt'}]}]]},{type,{91,7},constraint,[{atom,{91,7},is_subtype},[{var,{91,7},'Type'},{type,{91,15},union,[{atom,{91,15},index},{atom,{91,23},list},{atom,{91,30},binary}]}]]},{type,{92,7},constraint,[{atom,{92,7},is_subtype},[{var,{92,7},'ValueSpec'},{type,{92,20},union,[{atom,{92,20},all},{atom,{92,26},all_but_first},{atom,{92,42},all_names},{atom,{92,54},first},{atom,{92,62},none},{var,{92,69},'ValueList'}]}]]},{type,{93,7},constraint,[{atom,{93,7},is_subtype},[{var,{93,7},'ValueList'},{type,{93,20},list,[{var,{93,21},'ValueID'}]}]]},{type,{94,7},constraint,[{atom,{94,7},is_subtype},[{var,{94,7},'ValueID'},{type,{94,18},union,[{type,{94,18},integer,[]},{type,{94,30},string,[]},{type,{94,41},atom,[]}]}]]},{type,{95,7},constraint,[{atom,{95,7},is_subtype},[{var,{95,7},'CompileOpt'},{user_type,{95,21},compile_option,[]}]]},{type,{96,7},constraint,[{atom,{96,7},is_subtype},[{var,{96,7},'Captured'},{type,{96,19},union,[{type,{96,19},list,[{var,{96,20},'CaptureData'}]},{type,{96,35},list,[{type,{96,36},list,[{var,{96,37},'CaptureData'}]}]}]}]]},{type,{97,7},constraint,[{atom,{97,7},is_subtype},[{var,{97,7},'CaptureData'},{type,{97,22},union,[{type,{97,22},tuple,[{type,{97,23},integer,[]},{type,{97,34},integer,[]}]},{var,{98,22},'ListConversionData'},{type,{99,22},binary,[]}]}]]},{type,{100,7},constraint,[{atom,{100,7},is_subtype},[{var,{100,7},'ListConversionData'},{type,{100,29},union,[{type,{100,29},string,[]},{type,{101,29},tuple,[{atom,{101,30},error},{type,{101,37},string,[]},{type,{101,47},binary,[]}]},{type,{102,29},tuple,[{atom,{102,30},incomplete},{type,{102,42},string,[]},{type,{102,52},binary,[]}]}]}]]},{type,{103,7},constraint,[{atom,{103,7},is_subtype},[{var,{103,7},'ErrType'},{type,{103,18},union,[{atom,{103,18},match_limit},{atom,{103,32},match_limit_recursion},{type,{103,56},tuple,[{atom,{103,57},compile},{var,{103,67},'CompileErr'}]}]}]]},{type,{104,7},constraint,[{atom,{104,7},is_subtype},[{var,{104,7},'CompileErr'},{type,{104,21},tuple,[{ann_type,{104,22},[{var,{104,22},'ErrString'},{type,{104,35},string,[]}]},{ann_type,{104,45},[{var,{104,45},'Position'},{type,{104,57},non_neg_integer,[]}]}]}]]}]]}]}}]}},{{function,split,2},[{file,[114,101,46,101,114,108]},{location,153}],[<<115,112,108,105,116,47,50>>],#{<<101,110>> => [{p,[],[<<83,97,109,101,32,97,115,32>>,{code,[],[<<115,112,108,105,116,40,83,117,98,106,101,99,116,44,32,82,69,44,32,91,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,57,57,52>>,signature => [{attribute,{153,2},spec,{{split,2},[{type,{153,12},bounded_fun,[{type,{153,12},'fun',[{type,{153,12},product,[{var,{153,13},'Subject'},{var,{153,22},'RE'}]},{var,{153,29},'SplitList'}]},[{type,{154,7},constraint,[{atom,{154,7},is_subtype},[{var,{154,7},'Subject'},{type,{154,18},union,[{type,{154,18},iodata,[]},{remote_type,{154,29},[{atom,{154,29},unicode},{atom,{154,37},charlist},[]]}]}]]},{type,{155,7},constraint,[{atom,{155,7},is_subtype},[{var,{155,7},'RE'},{type,{155,13},union,[{user_type,{155,13},mp,[]},{type,{155,20},iodata,[]}]}]]},{type,{156,7},constraint,[{atom,{156,7},is_subtype},[{var,{156,7},'SplitList'},{type,{156,20},list,[{type,{156,21},union,[{type,{156,21},iodata,[]},{remote_type,{156,32},[{atom,{156,32},unicode},{atom,{156,40},charlist},[]]}]}]}]]}]]}]}}]}},{{function,split,3},[{file,[114,101,46,101,114,108]},{location,166}],[<<115,112,108,105,116,47,51>>],#{<<101,110>> => [{p,[],[<<83,112,108,105,116,115,32,116,104,101,32,105,110,112,117,116,32,105,110,116,111,32,112,97,114,116,115,32,98,121,32,102,105,110,100,105,110,103,32,116,111,107,101,110,115,32,97,99,99,111,114,100,105,110,103,32,116,111,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,115,117,112,112,108,105,101,100,46,32,84,104,101,32,115,112,108,105,116,116,105,110,103,32,105,115,32,98,97,115,105,99,97,108,108,121,32,100,111,110,101,32,98,121,32,114,117,110,110,105,110,103,32,97,32,103,108,111,98,97,108,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,32,97,110,100,32,100,105,118,105,100,105,110,103,32,116,104,101,32,105,110,105,116,105,97,108,32,115,116,114,105,110,103,32,119,104,101,114,101,118,101,114,32,97,32,109,97,116,99,104,32,111,99,99,117,114,115,46,32,84,104,101,32,109,97,116,99,104,105,110,103,32,112,97,114,116,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,105,115,32,114,101,109,111,118,101,100,32,102,114,111,109,32,116,104,101,32,111,117,116,112,117,116,46>>]},{p,[],[<<65,115,32,105,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,114,101,35,114,117,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,117,110,47,51>>]}]},<<44,32,97,110,32>>,{code,[],[<<109,112,40,41>>]},<<32,99,111,109,112,105,108,101,100,32,119,105,116,104,32,111,112,116,105,111,110,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,114,101,113,117,105,114,101,115,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,116,111,32,98,101,32,97,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<46,32,73,102,32,99,111,109,112,105,108,97,116,105,111,110,32,105,115,32,100,111,110,101,32,105,109,112,108,105,99,105,116,108,121,32,97,110,100,32,116,104,101,32>>,{code,[],[<<117,110,105,99,111,100,101>>]},<<32,99,111,109,112,105,108,97,116,105,111,110,32,111,112,116,105,111,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111,110,44,32,98,111,116,104,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,97,110,100,32>>,{code,[],[<<83,117,98,106,101,99,116>>]},<<32,97,114,101,32,116,111,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,118,97,108,105,100,32,85,110,105,99,111,100,101,32>>,{code,[],[<<99,104,97,114,108,105,115,116,40,41>>]},<<115,46>>]},{p,[],[<<84,104,101,32,114,101,115,117,108,116,32,105,115,32,103,105,118,101,110,32,97,115,32,97,32,108,105,115,116,32,111,102,32,34,115,116,114,105,110,103,115,34,44,32,116,104,101,32,112,114,101,102,101,114,114,101,100,32,100,97,116,97,32,116,121,112,101,32,115,112,101,99,105,102,105,101,100,32,105,110,32,111,112,116,105,111,110,32>>,{code,[],[<<114,101,116,117,114,110>>]},<<32,40,100,101,102,97,117,108,116,32>>,{code,[],[<<105,111,100,97,116,97>>]},<<41,46>>]},{p,[],[<<73,102,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,115,112,101,99,105,102,105,101,100,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,44,32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,114,101,116,117,114,110,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,105,110,103,32,108,105,115,116,32,97,115,32,119,101,108,108,46,32,70,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,110,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,34,44,34,103,34,93>>]}]},{p,[],[<<119,104,105,108,101>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,40,91,108,110,93,41,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,108,34,44,34,97,34,44,34,110,34,44,34,103,34,93>>]}]},{p,[],[<<84,104,101,32,116,101,120,116,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,40,109,97,114,107,101,100,32,98,121,32,116,104,101,32,112,97,114,101,110,116,104,101,115,101,115,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,41,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,108,105,115,116,32,119,104,101,114,101,32,105,116,32,119,97,115,32,102,111,117,110,100,46,32,84,104,105,115,32,109,101,97,110,115,32,116,104,97,116,32,99,111,110,99,97,116,101,110,97,116,105,110,103,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,32,115,112,108,105,116,32,119,104,101,114,101,32,116,104,101,32,119,104,111,108,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,105,115,32,97,32,115,105,110,103,108,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,40,97,115,32,105,110,32,116,104,101,32,108,97,115,116,32,101,120,97,109,112,108,101,41,32,97,108,119,97,121,115,32,114,101,115,117,108,116,115,32,105,110,32,116,104,101,32,111,114,105,103,105,110,97,108,32,115,116,114,105,110,103,46>>]},{p,[],[<<65,115,32,116,104,101,114,101,32,105,115,32,110,111,32,109,97,116,99,104,105,110,103,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,102,111,114,32,116,104,101,32,108,97,115,116,32,112,97,114,116,32,105,110,32,116,104,101,32,101,120,97,109,112,108,101,32,40,116,104,101,32,34,103,34,41,44,32,110,111,116,104,105,110,103,32,105,115,32,105,110,115,101,114,116,101,100,32,97,102,116,101,114,32,116,104,97,116,46,32,84,111,32,109,97,107,101,32,116,104,101,32,103,114,111,117,112,32,111,102,32,115,116,114,105,110,103,115,32,97,110,100,32,116,104,101,32,112,97,114,116,115,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,109,111,114,101,32,111,98,118,105,111,117,115,44,32,111,110,101,32,99,97,110,32,117,115,101,32,111,112,116,105,111,110,32>>,{code,[],[<<103,114,111,117,112>>]},<<44,32,119,104,105,99,104,32,103,114,111,117,112,115,32,116,111,103,101,116,104,101,114,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,112,97,114,116,115,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,119,104,101,110,32,116,104,101,32,115,116,114,105,110,103,32,119,97,115,32,115,112,108,105,116,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,40,91,108,110,93,41,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,103,114,111,117,112,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,91,34,69,114,34,44,34,108,34,93,44,91,34,97,34,44,34,110,34,93,44,91,34,103,34,93,93>>]}]},{p,[],[<<72,101,114,101,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,102,105,114,115,116,32,109,97,116,99,104,101,100,32,116,104,101,32,34,108,34,44,32,99,97,117,115,105,110,103,32,34,69,114,34,32,116,111,32,98,101,32,116,104,101,32,102,105,114,115,116,32,112,97,114,116,32,105,110,32,116,104,101,32,114,101,115,117,108,116,46,32,87,104,101,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,32,109,97,116,99,104,101,100,44,32,116,104,101,32,40,111,110,108,121,41,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,119,97,115,32,98,111,117,110,100,32,116,111,32,116,104,101,32,34,108,34,44,32,115,111,32,116,104,101,32,34,108,34,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,32,116,104,101,32,103,114,111,117,112,32,116,111,103,101,116,104,101,114,32,119,105,116,104,32,34,69,114,34,46,32,84,104,101,32,110,101,120,116,32,109,97,116,99,104,32,105,115,32,111,102,32,116,104,101,32,34,110,34,44,32,109,97,107,105,110,103,32,34,97,34,32,116,104,101,32,110,101,120,116,32,112,97,114,116,32,116,111,32,98,101,32,114,101,116,117,114,110,101,100,46,32,65,115,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,32,105,115,32,98,111,117,110,100,32,116,111,32,115,117,98,115,116,114,105,110,103,32,34,110,34,32,105,110,32,116,104,105,115,32,99,97,115,101,44,32,116,104,101,32,34,110,34,32,105,115,32,105,110,115,101,114,116,101,100,32,105,110,116,111,32,116,104,105,115,32,103,114,111,117,112,46,32,84,104,101,32,108,97,115,116,32,103,114,111,117,112,32,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,32,114,101,109,97,105,110,105,110,103,32,115,116,114,105,110,103,44,32,97,115,32,110,111,32,109,111,114,101,32,109,97,116,99,104,101,115,32,97,114,101,32,102,111,117,110,100,46>>]},{p,[],[<<66,121,32,100,101,102,97,117,108,116,44,32,97,108,108,32,112,97,114,116,115,32,111,102,32,116,104,101,32,115,116,114,105,110,103,44,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,101,109,112,116,121,32,115,116,114,105,110,103,115,44,32,97,114,101,32,114,101,116,117,114,110,101,100,32,102,114,111,109,32,116,104,101,32,102,117,110,99,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,110,34,44,91,93,93>>]}]},{p,[],[<<97,115,32,116,104,101,32,109,97,116,99,104,105,110,103,32,111,102,32,116,104,101,32,34,103,34,32,105,110,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,108,101,97,118,101,115,32,97,110,32,101,109,112,116,121,32,114,101,115,116,44,32,119,104,105,99,104,32,105,115,32,97,108,115,111,32,114,101,116,117,114,110,101,100,46,32,84,104,105,115,32,98,101,104,97,118,105,111,114,32,100,105,102,102,101,114,115,32,102,114,111,109,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32,115,112,108,105,116,32,102,117,110,99,116,105,111,110,32,105,110,32,80,101,114,108,44,32,119,104,101,114,101,32,101,109,112,116,121,32,115,116,114,105,110,103,115,32,97,116,32,116,104,101,32,101,110,100,32,97,114,101,32,98,121,32,100,101,102,97,117,108,116,32,114,101,109,111,118,101,100,46,32,84,111,32,103,101,116,32,116,104,101,32,34,116,114,105,109,109,105,110,103,34,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32,80,101,114,108,44,32,115,112,101,99,105,102,121,32>>,{code,[],[<<116,114,105,109>>]},<<32,97,115,32,97,110,32,111,112,116,105,111,110,58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,116,114,105,109,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,110,34,93>>]}]},{p,[],[<<84,104,101,32,34,116,114,105,109,34,32,111,112,116,105,111,110,32,115,97,121,115,59,32,34,103,105,118,101,32,109,101,32,97,115,32,109,97,110,121,32,112,97,114,116,115,32,97,115,32,112,111,115,115,105,98,108,101,32,101,120,99,101,112,116,32,116,104,101,32,101,109,112,116,121,32,111,110,101,115,34,44,32,119,104,105,99,104,32,115,111,109,101,116,105,109,101,115,32,99,97,110,32,98,101,32,117,115,101,102,117,108,46,32,89,111,117,32,99,97,110,32,97,108,115,111,32,115,112,101,99,105,102,121,32,104,111,119,32,109,97,110,121,32,112,97,114,116,115,32,121,111,117,32,119,97,110,116,44,32,98,121,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,112,97,114,116,115,44>>]},<<78>>,{code,[],[<<125>>]},<<58>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,123,112,97,114,116,115,44,50,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115>>]},{pre,[],[{code,[],[<<91,34,69,114,34,44,34,97,110,103,34,93>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32,116,104,101,32,108,97,115,116,32,112,97,114,116,32,105,115,32,34,97,110,103,34,44,32,110,111,116,32,34,97,110,34,44,32,97,115,32,115,112,108,105,116,116,105,110,103,32,119,97,115,32,115,112,101,99,105,102,105,101,100,32,105,110,116,111,32,116,119,111,32,112,97,114,116,115,44,32,97,110,100,32,116,104,101,32,115,112,108,105,116,116,105,110,103,32,115,116,111,112,115,32,119,104,101,110,32,101,110,111,117,103,104,32,112,97,114,116,115,32,97,114,101,32,103,105,118,101,110,44,32,119,104,105,99,104,32,105,115,32,119,104,121,32,116,104,101,32,114,101,115,117,108,116,32,100,105,102,102,101,114,115,32,102,114,111,109,32,116,104,97,116,32,111,102,32>>,{code,[],[<<116,114,105,109>>]},<<46>>]},{p,[],[<<77,111,114,101,32,116,104,97,110,32,116,104,114,101,101,32,112,97,114,116,115,32,97,114,101,32,110,111,116,32,112,111,115,115,105,98,108,101,32,119,105,116,104,32,116,104,105,115,32,105,110,100,97,116,97,44,32,115,111>>]},{pre,[],[{code,[],[<<114,101,58,115,112,108,105,116,40,34,69,114,108,97,110,103,34,44,34,91,108,103,93,34,44,91,123,114,101,116,117,114,110,44,108,105,115,116,125,44,123,112,97,114,116,115,44,52,125,93,41,46>>]}]},{p,[],[<<103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,114,101,115,117,108,116,32,97,115,32,116,104,101,32,100,101,102,97,117,108,116,44,32,119,104,105,99,104,32,105,115,32,116,111,32,98,101,32,118,105,101,119,101,100,32,97,115,32,34,97,110,32,105,110,102,105,110,105,116,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,34,46>>]},{p,[],[<<83,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<48>>]},<<32,97,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,103,105,118,101,115,32,116,104,101,32,115,97,109,101,32,101,102,102,101,99,116,32,97,115,32,111,112,116,105,111,110,32>>,{code,[],[<<116,114,105,109>>]},<<46,32,73,102,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,97,114,101,32,99,97,112,116,117,114,101,100,44,32,101,109,112,116,121,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,109,97,116,99,104,101,100,32,97,116,32,116,104,101,32,101,110,100,32,97,114,101,32,97,108,115,111,32,115,116,114,105,112,112,101,100,32,102,114,111,109,32,116,104,101,32,114,101,115,117,108,116,32,105,102,32>>,{code,[],[<<116,114,105,109>>]},<<32,111,114,32>>,{code,[],[<<123,112,97,114,116,115,44,48,125>>]},<<32,105,115,32,115,112,101,99,105,102,105,101,100,46>>]},{p,[],[<<84,104,101,32>>,{code,[],[<<116,114,105,109>>]},<<32,98,101,104,97,118,105,111,114,32,99,111,114,114,101,115,112,111,110,100,115,32,101,120,97,99,116,108,121,32,116,111,32,116,104,101,32,80,101,114,108,32,100,101,102,97,117,108,116,46,32>>,{code,[],[<<123,112,97,114,116,115,44,78,125>>]},<<44,32,119,104,101,114,101,32,78,32,105,115,32,97,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,44,32,99,111,114,114,101,115,112,111,110,100,115,32,101,120,97,99,116,108,121,32,116,111,32,116,104,101,32,80,101,114,108,32,98,101,104,97,118,105,111,114,32,119,105,116,104,32,97,32,112,111,115,105,116,105,118,101,32,110,117,109,101,114,105,99,97,108,32,116,104,105,114,100,32,112,97,114,97,109,101,116,101,114,46,32,84,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32>>,{code,[],[<<115,112,108,105,116,47,51>>]},<<32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,80,101,114,108,32,98,101,104,97,118,105,111,114,32,119,104,101,110,32,97,32,110,101,103,97,116,105,118,101,32,105,110,116,101,103,101,114,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,116,104,101,32,116,104,105,114,100,32,112,97,114,97,109,101,116,101,114,32,102,111,114,32,116,104,101,32,80,101,114,108,32,114,111,117,116,105,110,101,46>>]},{p,[],[<<83,117,109,109,97,114,121,32,111,102,32,111,112,116,105,111,110,115,32,110,111,116,32,112,114,101,118,105,111,117,115,108,121,32,100,101,115,99,114,105,98,101,100,32,102,111,114,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<114,117,110,47,51>>]},<<58>>]},{dl,[],[{dt,[],[{code,[],[<<123,114,101,116,117,114,110,44,82,101,116,117,114,110,84,121,112,101,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,104,111,119,32,116,104,101,32,112,97,114,116,115,32,111,102,32,116,104,101,32,111,114,105,103,105,110,97,108,32,115,116,114,105,110,103,32,97,114,101,32,112,114,101,115,101,110,116,101,100,32,105,110,32,116,104,101,32,114,101,115,117,108,116,32,108,105,115,116,46,32,86,97,108,105,100,32,116,121,112,101,115,58>>]},{dl,[],[{dt,[],[{code,[],[<<105,111,100,97,116,97>>]}]},{dd,[],[{p,[],[<<84,104,101,32,118,97,114,105,97,110,116,32,111,102,32>>,{code,[],[<<105,111,100,97,116,97,40,41>>]},<<32,116,104,97,116,32,103,105,118,101,115,32,116,104,101,32,108,101,97,115,116,32,99,111,112,121,105,110,103,32,111,102,32,100,97,116,97,32,119,105,116,104,32,116,104,101,32,99,117,114,114,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,40,111,102,116,101,110,32,97,32,98,105,110,97,114,121,44,32,98,117,116,32,100,111,32,110,111,116,32,100,101,112,101,110,100,32,111,110,32,105,116,41,46>>]}]},{dt,[],[{code,[],[<<98,105,110,97,114,121>>]}]},{dd,[],[{p,[],[<<65,108,108,32,112,97,114,116,115,32,114,101,116,117,114,110,101,100,32,97,115,32,98,105,110,97,114,105,101,115,46>>]}]},{dt,[],[{code,[],[<<108,105,115,116>>]}]},{dd,[],[{p,[],[<<65,108,108,32,112,97,114,116,115,32,114,101,116,117,114,110,101,100,32,97,115,32,108,105,115,116,115,32,111,102,32,99,104,97,114,97,99,116,101,114,115,32,40,34,115,116,114,105,110,103,115,34,41,46>>]}]}]}]},{dt,[],[{code,[],[<<103,114,111,117,112>>]}]},{dd,[],[{p,[],[<<71,114,111,117,112,115,32,116,111,103,101,116,104,101,114,32,116,104,101,32,112,97,114,116,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,119,105,116,104,32,116,104,101,32,112,97,114,116,115,32,111,102,32,116,104,101,32,115,116,114,105,110,103,32,109,97,116,99,104,105,110,103,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,111,102,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]},{p,[],[<<84,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,102,114,111,109,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,105,110,32,116,104,105,115,32,99,97,115,101,32,97,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<32,111,102,32>>,{code,[],[<<108,105,115,116,40,41>>]},<<115,46,32,69,97,99,104,32,115,117,98,108,105,115,116,32,98,101,103,105,110,115,32,119,105,116,104,32,116,104,101,32,115,116,114,105,110,103,32,112,105,99,107,101,100,32,111,117,116,32,111,102,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,44,32,102,111,108,108,111,119,101,100,32,98,121,32,116,104,101,32,112,97,114,116,115,32,109,97,116,99,104,105,110,103,32,101,97,99,104,32,111,102,32,116,104,101,32,115,117,98,101,120,112,114,101,115,115,105,111,110,115,32,105,110,32,111,114,100,101,114,32,111,102,32,111,99,99,117,114,114,101,110,99,101,32,105,110,32,116,104,101,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46>>]}]},{dt,[],[{code,[],[<<123,112,97,114,116,115,44,78,125>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,116,104,101,32,115,117,98,106,101,99,116,32,115,116,114,105,110,103,32,105,115,32,116,111,32,98,101,32,115,112,108,105,116,32,105,110,116,111,46>>]},{p,[],[<<84,104,101,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,105,115,32,116,111,32,98,101,32,97,32,112,111,115,105,116,105,118,101,32,105,110,116,101,103,101,114,32,102,111,114,32,97,32,115,112,101,99,105,102,105,99,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,44,32,97,110,100,32>>,{code,[],[<<105,110,102,105,110,105,116,121>>]},<<32,102,111,114,32,116,104,101,32,109,97,120,105,109,117,109,32,110,117,109,98,101,114,32,111,102,32,112,97,114,116,115,32,112,111,115,115,105,98,108,101,32,40,116,104,101,32,100,101,102,97,117,108,116,41,46,32,83,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,112,97,114,116,115,44,48,125>>]},<<32,103,105,118,101,115,32,97,115,32,109,97,110,121,32,112,97,114,116,115,32,97,115,32,112,111,115,115,105,98,108,101,32,100,105,115,114,101,103,97,114,100,105,110,103,32,101,109,112,116,121,32,112,97,114,116,115,32,97,116,32,116,104,101,32,101,110,100,44,32,116,104,101,32,115,97,109,101,32,97,115,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<116,114,105,109>>]},<<46>>]}]},{dt,[],[{code,[],[<<116,114,105,109>>]}]},{dd,[],[{p,[],[<<83,112,101,99,105,102,105,101,115,32,116,104,97,116,32,101,109,112,116,121,32,112,97,114,116,115,32,97,116,32,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,114,101,115,117,108,116,32,108,105,115,116,32,97,114,101,32,116,111,32,98,101,32,100,105,115,114,101,103,97,114,100,101,100,46,32,84,104,101,32,115,97,109,101,32,97,115,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,112,97,114,116,115,44,48,125>>]},<<46,32,84,104,105,115,32,99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,100,101,102,97,117,108,116,32,98,101,104,97,118,105,111,114,32,111,102,32,116,104,101,32>>,{code,[],[<<115,112,108,105,116>>]},<<32,98,117,105,108,116,45,105,110,32,102,117,110,99,116,105,111,110,32,105,110,32,80,101,114,108,46>>]}]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,114,101,46,120,109,108,35,76,49,48,48,51>>,signature => [{attribute,{166,2},spec,{{split,3},[{type,{166,12},bounded_fun,[{type,{166,12},'fun',[{type,{166,12},product,[{var,{166,13},'Subject'},{var,{166,22},'RE'},{var,{166,26},'Options'}]},{var,{166,38},'SplitList'}]},[{type,{167,7},constraint,[{atom,{167,7},is_subtype},[{var,{167,7},'Subject'},{type,{167,18},union,[{type,{167,18},iodata,[]},{remote_type,{167,29},[{atom,{167,29},unicode},{atom,{167,37},charlist},[]]}]}]]},{type,{168,7},constraint,[{atom,{168,7},is_subtype},[{var,{168,7},'RE'},{type,{168,13},union,[{user_type,{168,13},mp,[]},{type,{168,20},iodata,[]},{remote_type,{168,31},[{atom,{168,31},unicode},{atom,{168,39},charlist},[]]}]}]]},{type,{169,7},constraint,[{atom,{169,7},is_subtype},[{var,{169,7},'Options'},{type,{169,18},list,[{var,{169,20},'Option'}]}]]},{type,{170,7},constraint,[{atom,{170,7},is_subtype},[{var,{170,7},'Option'},{type,{170,17},union,[{atom,{170,17},anchored},{atom,{170,28},notbol},{atom,{170,37},noteol},{atom,{170,46},notempty},{atom,{170,57},notempty_atstart},{type,{171,17},tuple,[{atom,{171,18},offset},{type,{171,26},non_neg_integer,[]}]},{type,{171,47},tuple,[{atom,{171,48},newline},{user_type,{171,57},nl_spec,[]}]},{type,{172,17},tuple,[{atom,{172,18},match_limit},{type,{172,31},non_neg_integer,[]}]},{type,{173,17},tuple,[{atom,{173,18},match_limit_recursion},{type,{173,41},non_neg_integer,[]}]},{atom,{174,17},bsr_anycrlf},{atom,{174,31},bsr_unicode},{type,{174,45},tuple,[{atom,{174,46},return},{var,{174,54},'ReturnType'}]},{type,{175,17},tuple,[{atom,{175,18},parts},{var,{175,25},'NumParts'}]},{atom,{175,37},group},{atom,{175,45},trim},{var,{175,52},'CompileOpt'}]}]]},{type,{176,7},constraint,[{atom,{176,7},is_subtype},[{var,{176,7},'NumParts'},{type,{176,19},union,[{type,{176,19},non_neg_integer,[]},{atom,{176,39},infinity}]}]]},{type,{177,7},constraint,[{atom,{177,7},is_subtype},[{var,{177,7},'ReturnType'},{type,{177,21},union,[{atom,{177,21},iodata},{atom,{177,30},list},{atom,{177,37},binary}]}]]},{type,{178,7},constraint,[{atom,{178,7},is_subtype},[{var,{178,7},'CompileOpt'},{user_type,{178,21},compile_option,[]}]]},{type,{179,7},constraint,[{atom,{179,7},is_subtype},[{var,{179,7},'SplitList'},{type,{179,20},union,[{type,{179,20},list,[{var,{179,21},'RetData'}]},{type,{179,32},list,[{var,{179,33},'GroupedRetData'}]}]}]]},{type,{180,7},constraint,[{atom,{180,7},is_subtype},[{var,{180,7},'GroupedRetData'},{type,{180,25},list,[{var,{180,26},'RetData'}]}]]},{type,{181,7},constraint,[{atom,{181,7},is_subtype},[{var,{181,7},'RetData'},{type,{181,18},union,[{type,{181,18},iodata,[]},{remote_type,{181,29},[{atom,{181,29},unicode},{atom,{181,37},charlist},[]]},{type,{181,50},binary,[]},{type,{181,61},list,[]}]}]]}]]}]}}]}},{{type,mp,0},[{file,[114,101,46,101,114,108]},{location,23}],[<<45,116,121,112,101,32,109,112,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<79,112,97,113,117,101,32,100,97,116,97,32,116,121,112,101,32,99,111,110,116,97,105,110,105,110,103,32,97,32,99,111,109,112,105,108,101,100,32,114,101,103,117,108,97,114,32,101,120,112,114,101,115,115,105,111,110,46,32>>,{code,[],[<<109,112,40,41>>]},<<32,105,115,32,103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,97,32,116,117,112,108,101,40,41,32,104,97,118,105,110,103,32,116,104,101,32,97,116,111,109,32>>,{code,[],[<<114,101,95,112,97,116,116,101,114,110>>]},<<32,97,115,32,105,116,115,32,102,105,114,115,116,32,101,108,101,109,101,110,116,44,32,116,111,32,97,108,108,111,119,32,102,111,114,32,109,97,116,99,104,105,110,103,32,105,110,32,103,117,97,114,100,115,46,32,84,104,101,32,97,114,105,116,121,32,111,102,32,116,104,101,32,116,117,112,108,101,32,111,114,32,116,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,111,116,104,101,114,32,102,105,101,108,100,115,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,102,117,116,117,114,101,32,69,114,108,97,110,103,47,79,84,80,32,114,101,108,101,97,115,101,115,46>>]}]},#{signature => [{attribute,{23,2},type,{mp,{type,{23,15},tuple,[{atom,{23,16},re_pattern},{var,{23,28},'_'},{var,{23,31},'_'},{var,{23,34},'_'},{var,{23,37},'_'}]},[]}}]}},{{type,nl_spec,0},[{file,[114,101,46,101,114,108]},{location,25}],[<<45,116,121,112,101,32,110,108,95,115,112,101,99,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{25,2},type,{nl_spec,{type,{25,20},union,[{atom,{25,20},cr},{atom,{25,25},crlf},{atom,{25,32},lf},{atom,{25,37},anycrlf},{atom,{25,47},any}]},[]}}]}},{{type,compile_option,0},[{file,[114,101,46,101,114,108]},{location,27}],[<<45,116,121,112,101,32,99,111,109,112,105,108,101,95,111,112,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{27,2},type,{compile_option,{type,{27,27},union,[{atom,{27,27},unicode},{atom,{27,37},anchored},{atom,{27,48},caseless},{atom,{27,59},dollar_endonly},{atom,{28,27},dotall},{atom,{28,36},extended},{atom,{28,47},firstline},{atom,{28,59},multiline},{atom,{29,27},no_auto_capture},{atom,{29,45},dupnames},{atom,{29,56},ungreedy},{type,{30,27},tuple,[{atom,{30,28},newline},{user_type,{30,37},nl_spec,[]}]},{atom,{31,27},bsr_anycrlf},{atom,{31,41},bsr_unicode},{atom,{32,27},no_start_optimize},{atom,{32,47},ucp},{atom,{32,53},never_utf}]},[]}}]}}]}. \ No newline at end of file
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/shell_docs_SUITE.docs_v1 b/lib/stdlib/test/shell_docs_SUITE_data/shell_docs_SUITE.docs_v1
new file mode 100644
index 0000000000..4c3f53de9d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/shell_docs_SUITE.docs_v1
@@ -0,0 +1 @@
+{docs_v1,0,erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,none,#{generated => true,otp_doc_vsn => {1,0,0}},[{{function,suite,0},{32,1},[<<115,117,105,116,101,47,48>>],none,#{}},{{function,all,0},{35,1},[<<97,108,108,47,48>>],none,#{}},{{function,groups,0},{38,1},[<<103,114,111,117,112,115,47,48>>],none,#{}},{{function,init_per_suite,1},{46,1},[<<105,110,105,116,95,112,101,114,95,115,117,105,116,101,47,49>>],none,#{signature => [{attribute,{43,2},spec,{{init_per_suite,1},[{type,{43,21},bounded_fun,[{type,{43,21},'fun',[{type,{43,21},product,[{var,{43,22},'Config1'}]},{var,{43,34},'Config2'}]},[{type,{44,7},constraint,[{atom,{44,7},is_subtype},[{var,{44,7},'Config1'},{type,{44,18},list,[{type,{44,23},tuple,[{type,{44,24},atom,[]},{type,{44,31},term,[]}]}]}]]},{type,{45,7},constraint,[{atom,{45,7},is_subtype},[{var,{45,7},'Config2'},{type,{45,18},list,[{type,{45,23},tuple,[{type,{45,24},atom,[]},{type,{45,31},term,[]}]}]}]]}]]}]}}]}},{{function,end_per_suite,1},{50,1},[<<101,110,100,95,112,101,114,95,115,117,105,116,101,47,49>>],none,#{}},{{function,init_per_group,2},{53,1},[<<105,110,105,116,95,112,101,114,95,103,114,111,117,112,47,50>>],none,#{}},{{function,end_per_group,2},{58,1},[<<101,110,100,95,112,101,114,95,103,114,111,117,112,47,50>>],none,#{}},{{function,render,1},{76,1},[<<114,101,110,100,101,114,47,49>>],none,#{}},{{function,update_render,0},{101,1},[<<117,112,100,97,116,101,95,114,101,110,100,101,114,47,48>>],none,#{}},{{function,update_render,1},{105,1},[<<117,112,100,97,116,101,95,114,101,110,100,101,114,47,49>>],none,#{}},{{function,render_smoke,1},{122,1},[<<114,101,110,100,101,114,95,115,109,111,107,101,47,49>>],none,#{}},{{function,render_prop,1},{175,1},[<<114,101,110,100,101,114,95,112,114,111,112,47,49>>],none,#{}},{{function,links,1},{180,1},[<<108,105,110,107,115,47,49>>],none,#{}},{{function,check_links,2},{199,1},[<<99,104,101,99,107,95,108,105,110,107,115,47,50>>],none,#{}},{{function,normalize,1},{233,1},[<<110,111,114,109,97,108,105,122,101,47,49>>],none,#{}},{{function,b2a,1},{245,1},[<<98,50,97,47,49>>],none,#{}},{{function,render_non_native,1},{252,1},[<<114,101,110,100,101,114,95,110,111,110,95,110,97,116,105,118,101,47,49>>],none,#{}},{{function,render_all,1},{270,1},[<<114,101,110,100,101,114,95,97,108,108,47,49>>],none,#{}},{{function,render_module,2},{289,1},[<<114,101,110,100,101,114,95,109,111,100,117,108,101,47,50>>],none,#{}},{{function,sanitize,1},{324,1},[<<115,97,110,105,116,105,122,101,47,49>>],none,#{}},{{function,docsmap,1},{331,1},[<<100,111,99,115,109,97,112,47,49>>],none,#{}}]}. \ No newline at end of file
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/sofs.docs_v1 b/lib/stdlib/test/shell_docs_SUITE_data/sofs.docs_v1
index e4a4c4cfb7..f1aecb2830 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/sofs.docs_v1
+++ b/lib/stdlib/test/shell_docs_SUITE_data/sofs.docs_v1
@@ -1 +1 @@
-{docs_v1,[{file,[115,111,102,115,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<84,104,105,115,32,109,111,100,117,108,101,32,112,114,111,118,105,100,101,115,32,111,112,101,114,97,116,105,111,110,115,32,111,110,32,102,105,110,105,116,101,32,115,101,116,115,32,97,110,100,32,114,101,108,97,116,105,111,110,115,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32,115,101,116,115,46,32,73,110,116,117,105,116,105,118,101,108,121,44,32,97,32,115,101,116,32,105,115,32,97,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,101,108,101,109,101,110,116,115,59,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,98,101,108,111,110,103,115,32,116,111,32,116,104,101,32,115,101,116,44,32,97,110,100,32,116,104,101,32,115,101,116,32,99,111,110,116,97,105,110,115,32,101,118,101,114,121,32,101,108,101,109,101,110,116,46>>]},{p,[],[<<71,105,118,101,110,32,97,32,115,101,116,32,65,32,97,110,100,32,97,32,115,101,110,116,101,110,99,101,32,83,40,120,41,44,32,119,104,101,114,101,32,120,32,105,115,32,97,32,102,114,101,101,32,118,97,114,105,97,98,108,101,44,32,97,32,110,101,119,32,115,101,116,32,66,32,119,104,111,115,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,101,120,97,99,116,108,121,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,102,111,114,32,119,104,105,99,104,32,83,40,120,41,32,104,111,108,100,115,32,99,97,110,32,98,101,32,102,111,114,109,101,100,44,32,116,104,105,115,32,105,115,32,100,101,110,111,116,101,100,32,66,194,160,61,32,123,120,194,160,105,110,194,160,65,194,160,58,32,83,40,120,41,125,46,32,83,101,110,116,101,110,99,101,115,32,97,114,101,32,101,120,112,114,101,115,115,101,100,32,117,115,105,110,103,32,116,104,101,32,108,111,103,105,99,97,108,32,111,112,101,114,97,116,111,114,115,32,34,102,111,114,32,115,111,109,101,34,32,40,111,114,32,34,116,104,101,114,101,32,101,120,105,115,116,115,34,41,44,32,34,102,111,114,32,97,108,108,34,44,32,34,97,110,100,34,44,32,34,111,114,34,44,32,34,110,111,116,34,46,32,73,102,32,116,104,101,32,101,120,105,115,116,101,110,99,101,32,111,102,32,97,32,115,101,116,32,99,111,110,116,97,105,110,105,110,103,32,97,108,108,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,101,108,101,109,101,110,116,115,32,105,115,32,107,110,111,119,110,32,40,97,115,32,105,115,32,97,108,119,97,121,115,32,116,104,101,32,99,97,115,101,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,41,44,32,116,104,105,115,32,105,115,32,100,101,110,111,116,101,100,32,66,194,160,61,32,123,120,194,160,58,32,83,40,120,41,125,46>>]},{ul,[],[{li,[],[{p,[],[<<84,104,101,32>>,{em,[],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,97,44,32,98,44,32,97,110,100,32,99,32,105,115,32,100,101,110,111,116,101,100,32,123,97,44,194,160,98,44,194,160,99,125,46,32,84,104,105,115,32,110,111,116,97,116,105,111,110,32,105,115,32,110,111,116,32,116,111,32,98,101,32,99,111,110,102,117,115,101,100,32,119,105,116,104,32,116,117,112,108,101,115,46>>]},{p,[],[<<84,104,101,32>>,{em,[],[<<111,114,100,101,114,101,100,32,112,97,105,114>>]},<<32,111,102,32,97,32,97,110,100,32,98,44,32,119,105,116,104,32,102,105,114,115,116,32>>,{em,[],[<<99,111,111,114,100,105,110,97,116,101>>]},<<32,97,32,97,110,100,32,115,101,99,111,110,100,32,99,111,111,114,100,105,110,97,116,101,32,98,44,32,105,115,32,100,101,110,111,116,101,100,32,40,97,44,194,160,98,41,46,32,65,110,32,111,114,100,101,114,101,100,32,112,97,105,114,32,105,115,32,97,110,32>>,{em,[],[<<111,114,100,101,114,101,100,32,115,101,116>>]},<<32,111,102,32,116,119,111,32,101,108,101,109,101,110,116,115,46,32,73,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,111,114,100,101,114,101,100,32,115,101,116,115,32,99,97,110,32,99,111,110,116,97,105,110,32,111,110,101,44,32,116,119,111,44,32,111,114,32,109,111,114,101,32,101,108,101,109,101,110,116,115,44,32,97,110,100,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,117,115,101,100,32,116,111,32,101,110,99,108,111,115,101,32,116,104,101,32,101,108,101,109,101,110,116,115,46>>]},{p,[],[<<85,110,111,114,100,101,114,101,100,32,115,101,116,115,32,97,110,100,32,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,111,114,116,104,111,103,111,110,97,108,44,32,97,103,97,105,110,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,59,32,116,104,101,114,101,32,105,115,32,110,111,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,101,113,117,97,108,32,116,111,32,97,110,121,32,111,114,100,101,114,101,100,32,115,101,116,46>>]}]},{li,[],[{p,[],[<<84,104,101,32>>,{em,[],[<<101,109,112,116,121,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,115,32,110,111,32,101,108,101,109,101,110,116,115,46>>]},{p,[],[<<83,101,116,32,65,32,105,115,32>>,{a,[{id,<<101,113,117,97,108>>}],[]},{em,[],[<<101,113,117,97,108>>]},<<32,116,111,32,115,101,116,32,66,32,105,102,32,116,104,101,121,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32,101,108,101,109,101,110,116,115,44,32,119,104,105,99,104,32,105,115,32,100,101,110,111,116,101,100,32,65,194,160,61,194,160,66,46,32,84,119,111,32,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,101,113,117,97,108,32,105,102,32,116,104,101,121,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,97,110,100,32,104,97,118,101,32,101,113,117,97,108,32,101,108,101,109,101,110,116,115,32,97,116,32,101,97,99,104,32,99,111,111,114,100,105,110,97,116,101,46>>]},{p,[],[<<83,101,116,32,66,32,105,115,32,97,32>>,{a,[{id,<<115,117,98,115,101,116>>}],[]},{em,[],[<<115,117,98,115,101,116>>]},<<32,111,102,32,115,101,116,32,65,32,105,102,32,65,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,66,32,99,111,110,116,97,105,110,115,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<117,110,105,111,110>>}],[]},{em,[],[<<117,110,105,111,110>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,65,32,97,110,100,32,66,32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,97,110,100,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,66,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<105,110,116,101,114,115,101,99,116,105,111,110>>}],[]},{em,[],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,65,32,97,110,100,32,66,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,66,46>>]},{p,[],[<<84,119,111,32,115,101,116,115,32,97,114,101,32>>,{a,[{id,<<100,105,115,106,111,105,110,116>>}],[]},{em,[],[<<100,105,115,106,111,105,110,116>>]},<<32,105,102,32,116,104,101,105,114,32,105,110,116,101,114,115,101,99,116,105,111,110,32,105,115,32,116,104,101,32,101,109,112,116,121,32,115,101,116,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<100,105,102,102,101,114,101,110,99,101>>}],[]},{em,[],[<<100,105,102,102,101,114,101,110,99,101>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,65,32,97,110,100,32,66,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,116,104,97,116,32,100,111,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32,66,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<115,121,109,109,101,116,114,105,99,95,100,105,102,102,101,114,101,110,99,101>>}],[]},{em,[],[<<115,121,109,109,101,116,114,105,99,32,100,105,102,102,101,114,101,110,99,101>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,116,104,111,115,101,32,101,108,101,109,101,110,116,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,101,105,116,104,101,114,32,111,102,32,116,104,101,32,116,119,111,32,115,101,116,115,44,32,98,117,116,32,110,111,116,32,98,111,116,104,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<117,110,105,111,110,95,110>>}],[]},{em,[],[<<117,110,105,111,110>>]},<<32,111,102,32,97,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,115,101,116,115,32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,116,104,101,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,97,116,32,108,101,97,115,116,32,111,110,101,32,115,101,116,32,111,102,32,116,104,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<105,110,116,101,114,115,101,99,116,105,111,110,95,110>>}],[]},{em,[],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32,97,32,110,111,110,45,101,109,112,116,121,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,115,101,116,115,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,101,118,101,114,121,32,115,101,116,32,111,102,32,116,104,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]},{li,[],[{p,[],[<<84,104,101,32>>,{a,[{id,<<67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,88,32,97,110,100,32,89,44,32,100,101,110,111,116,101,100,32,88,194,160,195,151,194,160,89,44,32,105,115,32,116,104,101,32,115,101,116,32,123,97,194,160,58,32,97,194,160,61,32,40,120,44,194,160,121,41,32,102,111,114,32,115,111,109,101,32,120,194,160,105,110,194,160,88,32,97,110,100,32,102,111,114,32,115,111,109,101,32,121,194,160,105,110,194,160,89,125,46>>]},{p,[],[<<65,32>>,{a,[{id,<<114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<114,101,108,97,116,105,111,110>>]},<<32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,88,194,160,195,151,194,160,89,46,32,76,101,116,32,82,32,98,101,32,97,32,114,101,108,97,116,105,111,110,46,32,84,104,101,32,102,97,99,116,32,116,104,97,116,32,40,120,44,194,160,121,41,32,98,101,108,111,110,103,115,32,116,111,32,82,32,105,115,32,119,114,105,116,116,101,110,32,97,115,32,120,194,160,82,194,160,121,46,32,65,115,32,114,101,108,97,116,105,111,110,115,32,97,114,101,32,115,101,116,115,44,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,115,32,111,102,32,116,104,101,32,108,97,115,116,32,105,116,101,109,32,40,115,117,98,115,101,116,44,32,117,110,105,111,110,44,32,97,110,100,32,115,111,32,111,110,41,32,97,112,112,108,121,32,116,111,32,114,101,108,97,116,105,111,110,115,32,97,115,32,119,101,108,108,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<100,111,109,97,105,110>>}],[]},{em,[],[<<100,111,109,97,105,110>>]},<<32,111,102,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,120,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,121,194,160,105,110,194,160,89,125,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<114,97,110,103,101>>}],[]},{em,[],[<<114,97,110,103,101>>]},<<32,111,102,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,121,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,120,194,160,105,110,194,160,88,125,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<99,111,110,118,101,114,115,101>>}],[]},{em,[],[<<99,111,110,118,101,114,115,101>>]},<<32,111,102,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,97,194,160,58,32,97,194,160,61,32,40,121,44,194,160,120,41,32,102,111,114,32,115,111,109,101,32,40,120,44,194,160,121,41,194,160,105,110,194,160,82,125,46>>]},{p,[],[<<73,102,32,65,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,88,44,32,116,104,101,32>>,{a,[{id,<<105,109,97,103,101>>}],[]},{em,[],[<<105,109,97,103,101>>]},<<32,111,102,32,65,32,117,110,100,101,114,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,121,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,120,194,160,105,110,194,160,65,125,46,32,73,102,32,66,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,89,44,32,116,104,101,32>>,{a,[{id,<<105,110,118,101,114,115,101,95,105,109,97,103,101>>}],[]},{em,[],[<<105,110,118,101,114,115,101,32,105,109,97,103,101>>]},<<32,111,102,32,66,32,105,115,32,116,104,101,32,115,101,116,32,123,120,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,121,194,160,105,110,194,160,66,125,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,88,32,116,111,32,89,44,32,97,110,100,32,83,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,89,32,116,111,32,90,44,32,116,104,101,32>>,{a,[{id,<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,82,32,97,110,100,32,83,32,105,115,32,116,104,101,32,114,101,108,97,116,105,111,110,32,84,32,102,114,111,109,32,88,32,116,111,32,90,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,84,194,160,122,32,105,102,32,97,110,100,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,101,120,105,115,116,115,32,97,110,32,101,108,101,109,101,110,116,32,121,32,105,110,32,89,32,115,117,99,104,32,116,104,97,116,32,120,194,160,82,194,160,121,32,97,110,100,32,121,194,160,83,194,160,122,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<114,101,115,116,114,105,99,116,105,111,110>>}],[]},{em,[],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32,82,32,116,111,32,65,32,105,115,32,116,104,101,32,115,101,116,32,83,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,83,194,160,121,32,105,102,32,97,110,100,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,101,120,105,115,116,115,32,97,110,32,101,108,101,109,101,110,116,32,120,32,105,110,32,65,32,115,117,99,104,32,116,104,97,116,32,120,194,160,82,194,160,121,46>>]},{p,[],[<<73,102,32,83,32,105,115,32,97,32,114,101,115,116,114,105,99,116,105,111,110,32,111,102,32,82,32,116,111,32,65,44,32,116,104,101,110,32,82,32,105,115,32,97,110,32>>,{a,[{id,<<101,120,116,101,110,115,105,111,110>>}],[]},{em,[],[<<101,120,116,101,110,115,105,111,110>>]},<<32,111,102,32,83,32,116,111,32,88,46>>]},{p,[],[<<73,102,32,88,194,160,61,194,160,89,44,32,116,104,101,110,32,82,32,105,115,32,99,97,108,108,101,100,32,97,32,114,101,108,97,116,105,111,110,32>>,{em,[],[<<105,110>>]},<<32,88,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<102,105,101,108,100>>}],[]},{em,[],[<<102,105,101,108,100>>]},<<32,111,102,32,97,32,114,101,108,97,116,105,111,110,32,82,32,105,110,32,88,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,82,32,97,110,100,32,116,104,101,32,114,97,110,103,101,32,111,102,32,82,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,97,110,100,32,105,102,32,83,32,105,115,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,83,194,160,121,32,105,102,32,120,194,160,82,194,160,121,32,97,110,100,32,110,111,116,32,120,194,160,61,194,160,121,44,32,116,104,101,110,32,83,32,105,115,32,116,104,101,32>>,{a,[{id,<<115,116,114,105,99,116,95,114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<115,116,114,105,99,116>>]},<<32,114,101,108,97,116,105,111,110,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,82,46,32,67,111,110,118,101,114,115,101,108,121,44,32,105,102,32,83,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,97,110,100,32,105,102,32,82,32,105,115,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,82,194,160,121,32,105,102,32,120,194,160,83,194,160,121,32,111,114,32,120,194,160,61,194,160,121,44,32,116,104,101,110,32,82,32,105,115,32,116,104,101,32>>,{a,[{id,<<119,101,97,107,95,114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<119,101,97,107>>]},<<32,114,101,108,97,116,105,111,110,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,83,46>>]},{p,[],[<<65,32,114,101,108,97,116,105,111,110,32,82,32,105,110,32,88,32,105,115,32>>,{em,[],[<<114,101,102,108,101,120,105,118,101>>]},<<32,105,102,32,120,194,160,82,194,160,120,32,102,111,114,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,120,32,111,102,32,88,44,32,105,116,32,105,115,32>>,{em,[],[<<115,121,109,109,101,116,114,105,99>>]},<<32,105,102,32,120,194,160,82,194,160,121,32,105,109,112,108,105,101,115,32,116,104,97,116,32,121,194,160,82,194,160,120,44,32,97,110,100,32,105,116,32,105,115,32>>,{em,[],[<<116,114,97,110,115,105,116,105,118,101>>]},<<32,105,102,32,120,194,160,82,194,160,121,32,97,110,100,32,121,194,160,82,194,160,122,32,105,109,112,108,121,32,116,104,97,116,32,120,194,160,82,194,160,122,46>>]}]},{li,[],[{p,[],[<<65,32>>,{a,[{id,<<102,117,110,99,116,105,111,110>>}],[]},{em,[],[<<102,117,110,99,116,105,111,110>>]},<<32,70,32,105,115,32,97,32,114,101,108,97,116,105,111,110,44,32,97,32,115,117,98,115,101,116,32,111,102,32,88,194,160,195,151,194,160,89,44,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,70,32,105,115,32,101,113,117,97,108,32,116,111,32,88,32,97,110,100,32,115,117,99,104,32,116,104,97,116,32,102,111,114,32,101,118,101,114,121,32,120,32,105,110,32,88,32,116,104,101,114,101,32,105,115,32,97,32,117,110,105,113,117,101,32,101,108,101,109,101,110,116,32,121,32,105,110,32,89,32,119,105,116,104,32,40,120,44,194,160,121,41,32,105,110,32,70,46,32,84,104,101,32,108,97,116,116,101,114,32,99,111,110,100,105,116,105,111,110,32,99,97,110,32,98,101,32,102,111,114,109,117,108,97,116,101,100,32,97,115,32,102,111,108,108,111,119,115,58,32,105,102,32,120,194,160,70,194,160,121,32,97,110,100,32,120,194,160,70,194,160,122,44,32,116,104,101,110,32,121,194,160,61,194,160,122,46,32,73,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,105,116,32,105,115,32,110,111,116,32,114,101,113,117,105,114,101,100,32,116,104,97,116,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,70,32,105,115,32,101,113,117,97,108,32,116,111,32,88,32,102,111,114,32,97,32,114,101,108,97,116,105,111,110,32,116,111,32,98,101,32,99,111,110,115,105,100,101,114,101,100,32,97,32,102,117,110,99,116,105,111,110,46>>]},{p,[],[<<73,110,115,116,101,97,100,32,111,102,32,119,114,105,116,105,110,103,32,40,120,44,194,160,121,41,194,160,105,110,194,160,70,32,111,114,32,120,194,160,70,194,160,121,44,32,119,101,32,119,114,105,116,101,32,70,40,120,41,194,160,61,194,160,121,32,119,104,101,110,32,70,32,105,115,32,97,32,102,117,110,99,116,105,111,110,44,32,97,110,100,32,115,97,121,32,116,104,97,116,32,70,32,109,97,112,115,32,120,32,111,110,116,111,32,121,44,32,111,114,32,116,104,97,116,32,116,104,101,32,118,97,108,117,101,32,111,102,32,70,32,97,116,32,120,32,105,115,32,121,46>>]},{p,[],[<<65,115,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,114,101,108,97,116,105,111,110,115,44,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,115,32,111,102,32,116,104,101,32,108,97,115,116,32,105,116,101,109,32,40,100,111,109,97,105,110,44,32,114,97,110,103,101,44,32,97,110,100,32,115,111,32,111,110,41,32,97,112,112,108,121,32,116,111,32,102,117,110,99,116,105,111,110,115,32,97,115,32,119,101,108,108,46>>]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,118,101,114,115,101,32,111,102,32,97,32,102,117,110,99,116,105,111,110,32,70,32,105,115,32,97,32,102,117,110,99,116,105,111,110,32,70,39,44,32,116,104,101,110,32,70,39,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{a,[{id,<<105,110,118,101,114,115,101>>}],[]},{em,[],[<<105,110,118,101,114,115,101>>]},<<32,111,102,32,70,46>>]},{p,[],[<<84,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,116,119,111,32,102,117,110,99,116,105,111,110,115,32,70,49,32,97,110,100,32,70,50,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{a,[{id,<<99,111,109,112,111,115,105,116,101>>}],[]},{em,[],[<<99,111,109,112,111,115,105,116,101>>]},<<32,111,102,32,70,49,32,97,110,100,32,70,50,32,105,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,70,49,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,70,50,46>>]}]},{li,[],[{p,[],[<<83,111,109,101,116,105,109,101,115,44,32,119,104,101,110,32,116,104,101,32,114,97,110,103,101,32,111,102,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,109,111,114,101,32,105,109,112,111,114,116,97,110,116,32,116,104,97,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,116,115,101,108,102,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,97,32>>,{em,[],[<<102,97,109,105,108,121>>]},<<46>>]},{p,[],[<<84,104,101,32,100,111,109,97,105,110,32,111,102,32,97,32,102,97,109,105,108,121,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{em,[],[<<105,110,100,101,120,32,115,101,116>>]},<<44,32,97,110,100,32,116,104,101,32,114,97,110,103,101,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{em,[],[<<105,110,100,101,120,101,100,32,115,101,116>>]},<<46>>]},{p,[],[<<73,102,32,120,32,105,115,32,97,32,102,97,109,105,108,121,32,102,114,111,109,32,73,32,116,111,32,88,44,32,116,104,101,110,32,120,91,105,93,32,100,101,110,111,116,101,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,116,32,105,110,100,101,120,32,105,46,32,84,104,101,32,110,111,116,97,116,105,111,110,32,34,97,32,102,97,109,105,108,121,32,105,110,32,88,34,32,105,115,32,117,115,101,100,32,102,111,114,32,115,117,99,104,32,97,32,102,97,109,105,108,121,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,105,110,100,101,120,101,100,32,115,101,116,32,105,115,32,97,32,115,101,116,32,111,102,32,115,117,98,115,101,116,115,32,111,102,32,97,32,115,101,116,32,88,44,32,119,101,32,99,97,108,108,32,120,32,97,32>>,{a,[{id,<<102,97,109,105,108,121>>}],[]},{em,[],[<<102,97,109,105,108,121,32,111,102,32,115,117,98,115,101,116,115>>]},<<32,111,102,32,88,46>>]},{p,[],[<<73,102,32,120,32,105,115,32,97,32,102,97,109,105,108,121,32,111,102,32,115,117,98,115,101,116,115,32,111,102,32,88,44,32,116,104,101,32,117,110,105,111,110,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,120,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{em,[],[<<117,110,105,111,110,32,111,102,32,116,104,101,32,102,97,109,105,108,121>>]},<<32,120,46>>]},{p,[],[<<73,102,32,120,32,105,115,32,110,111,110,45,101,109,112,116,121,32,40,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,110,111,110,45,101,109,112,116,121,41,44,32,116,104,101,32>>,{em,[],[<<105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32,102,97,109,105,108,121>>]},<<32,120,32,105,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,120,46>>]},{p,[],[<<73,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,116,104,101,32,111,110,108,121,32,102,97,109,105,108,105,101,115,32,116,104,97,116,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,97,114,101,32,102,97,109,105,108,105,101,115,32,111,102,32,115,117,98,115,101,116,115,32,111,102,32,115,111,109,101,32,115,101,116,32,88,59,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,116,104,101,32,119,111,114,100,32,34,102,97,109,105,108,121,34,32,105,115,32,117,115,101,100,32,102,111,114,32,115,117,99,104,32,102,97,109,105,108,105,101,115,32,111,102,32,115,117,98,115,101,116,115,46>>]}]},{li,[],[{p,[],[<<65,32>>,{a,[{id,<<112,97,114,116,105,116,105,111,110>>}],[]},{em,[],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32,97,32,115,101,116,32,88,32,105,115,32,97,32,99,111,108,108,101,99,116,105,111,110,32,83,32,111,102,32,110,111,110,45,101,109,112,116,121,32,115,117,98,115,101,116,115,32,111,102,32,88,32,119,104,111,115,101,32,117,110,105,111,110,32,105,115,32,88,32,97,110,100,32,119,104,111,115,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,112,97,105,114,119,105,115,101,32,100,105,115,106,111,105,110,116,46>>]},{p,[],[<<65,32,114,101,108,97,116,105,111,110,32,105,110,32,97,32,115,101,116,32,105,115,32,97,110,32>>,{em,[],[<<101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110>>]},<<32,105,102,32,105,116,32,105,115,32,114,101,102,108,101,120,105,118,101,44,32,115,121,109,109,101,116,114,105,99,44,32,97,110,100,32,116,114,97,110,115,105,116,105,118,101,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,110,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,97,110,100,32,120,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,88,44,32,116,104,101,32>>,{a,[{id,<<101,113,117,105,118,97,108,101,110,99,101,95,99,108,97,115,115>>}],[]},{em,[],[<<101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115>>]},<<32,111,102,32,120,32,119,105,116,104,32,114,101,115,112,101,99,116,32,116,111,32,82,32,105,115,32,116,104,101,32,115,101,116,32,111,102,32,97,108,108,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,121,32,111,102,32,88,32,102,111,114,32,119,104,105,99,104,32,120,194,160,82,194,160,121,32,104,111,108,100,115,46,32,84,104,101,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,101,115,32,99,111,110,115,116,105,116,117,116,101,32,97,32,112,97,114,116,105,116,105,111,110,105,110,103,32,111,102,32,88,46,32,67,111,110,118,101,114,115,101,108,121,44,32,105,102,32,67,32,105,115,32,97,32,112,97,114,116,105,116,105,111,110,32,111,102,32,88,44,32,116,104,101,32,114,101,108,97,116,105,111,110,32,116,104,97,116,32,104,111,108,100,115,32,102,111,114,32,97,110,121,32,116,119,111,32,101,108,101,109,101,110,116,115,32,111,102,32,88,32,105,102,32,116,104,101,121,32,98,101,108,111,110,103,32,116,111,32,116,104,101,32,115,97,109,101,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,44,32,105,115,32,97,110,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,100,117,99,101,100,32,98,121,32,116,104,101,32,112,97,114,116,105,116,105,111,110,32,67,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,110,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,116,104,101,32>>,{a,[{id,<<99,97,110,111,110,105,99,97,108,95,109,97,112>>}],[]},{em,[],[<<99,97,110,111,110,105,99,97,108,32,109,97,112>>]},<<32,105,115,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,109,97,112,115,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,111,102,32,88,32,111,110,116,111,32,105,116,115,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,46>>]}]},{li,[],[{p,[],[{a,[{id,<<98,105,110,97,114,121,95,114,101,108,97,116,105,111,110>>}],[]},<<82,101,108,97,116,105,111,110,115,32,97,115,32,100,101,102,105,110,101,100,32,97,98,111,118,101,32,40,97,115,32,115,101,116,115,32,111,102,32,111,114,100,101,114,101,100,32,112,97,105,114,115,41,32,97,114,101,32,102,114,111,109,32,110,111,119,32,111,110,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32>>,{em,[],[<<98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115>>]},<<46>>]},{p,[],[<<87,101,32,99,97,108,108,32,97,32,115,101,116,32,111,102,32,111,114,100,101,114,101,100,32,115,101,116,115,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,32,97,110,32>>,{a,[{id,<<110,95,97,114,121,95,114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<40,110,45,97,114,121,41,32,114,101,108,97,116,105,111,110>>]},<<44,32,97,110,100,32,115,97,121,32,116,104,97,116,32,116,104,101,32,114,101,108,97,116,105,111,110,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,101,32>>,{a,[{id,<<67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116,95,116,117,112,108,101>>}],[]},<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116,32,88,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,88,91,110,93,44,32,119,104,101,114,101,32,120,91,105,93,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,88,91,105,93,44,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<112,114,111,106,101,99,116,105,111,110>>}],[]},{em,[],[<<112,114,111,106,101,99,116,105,111,110>>]},<<32,111,102,32,97,110,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,32,82,32,111,110,116,111,32,99,111,111,114,100,105,110,97,116,101,32,105,32,105,115,32,116,104,101,32,115,101,116,32,123,120,91,105,93,194,160,58,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,105,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,32,105,110,32,82,32,102,111,114,32,115,111,109,101,32,120,91,106,93,194,160,105,110,194,160,88,91,106,93,44,32,49,194,160,60,61,194,160,106,194,160,60,61,194,160,110,32,97,110,100,32,110,111,116,32,105,194,160,61,194,160,106,125,46,32,84,104,101,32,112,114,111,106,101,99,116,105,111,110,115,32,111,102,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,82,32,111,110,116,111,32,116,104,101,32,102,105,114,115,116,32,97,110,100,32,115,101,99,111,110,100,32,99,111,111,114,100,105,110,97,116,101,115,32,97,114,101,32,116,104,101,32,100,111,109,97,105,110,32,97,110,100,32,116,104,101,32,114,97,110,103,101,32,111,102,32,82,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46>>]},{p,[],[<<84,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,99,97,110,32,98,101,32,103,101,110,101,114,97,108,105,122,101,100,32,116,111,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,115,32,97,115,32,102,111,108,108,111,119,115,46,32,76,101,116,32,84,82,32,98,101,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,102,114,111,109,32,88,32,116,111,32,89,91,105,93,32,97,110,100,32,83,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,40,89,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,89,91,110,93,41,32,116,111,32,90,46,32,84,104,101,32>>,{a,[{id,<<116,117,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,84,82,32,97,110,100,32,83,32,105,115,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,84,32,102,114,111,109,32,88,32,116,111,32,90,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,84,194,160,122,32,105,102,32,97,110,100,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,101,120,105,115,116,115,32,97,110,32,101,108,101,109,101,110,116,32,121,91,105,93,32,105,110,32,89,91,105,93,32,102,111,114,32,101,97,99,104,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,32,115,117,99,104,32,116,104,97,116,32,120,194,160,82,91,105,93,194,160,121,91,105,93,32,97,110,100,32,40,121,91,49,93,44,194,160,46,46,46,44,194,160,121,91,110,93,41,194,160,83,194,160,122,46,32,78,111,119,32,108,101,116,32,84,82,32,98,101,32,97,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,102,114,111,109,32,88,91,105,93,32,116,111,32,89,91,105,93,32,97,110,100,32,83,32,97,32,115,117,98,115,101,116,32,111,102,32,88,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,88,91,110,93,46,32,84,104,101,32>>,{a,[{id,<<109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<109,117,108,116,105,112,108,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,84,82,32,97,110,100,32,83,32,105,115,32,100,101,102,105,110,101,100,32,116,111,32,98,101,32,116,104,101,32,115,101,116,32,123,122,194,160,58,32,122,194,160,61,32,40,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,44,32,40,121,91,49,93,44,46,46,46,44,121,91,110,93,41,41,32,102,111,114,32,115,111,109,101,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,194,160,105,110,194,160,83,32,97,110,100,32,102,111,114,32,115,111,109,101,32,40,120,91,105,93,44,194,160,121,91,105,93,41,32,105,110,32,82,91,105,93,44,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,125,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<110,97,116,117,114,97,108,95,106,111,105,110>>}],[]},{em,[],[<<110,97,116,117,114,97,108,32,106,111,105,110>>]},<<32,111,102,32,97,110,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,32,82,32,97,110,100,32,97,110,32,109,45,97,114,121,32,114,101,108,97,116,105,111,110,32,83,32,111,110,32,99,111,111,114,100,105,110,97,116,101,32,105,32,97,110,100,32,106,32,105,115,32,100,101,102,105,110,101,100,32,116,111,32,98,101,32,116,104,101,32,115,101,116,32,123,122,194,160,58,32,122,194,160,61,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,44,194,160,32,121,91,49,93,44,194,160,46,46,46,44,194,160,121,91,106,45,49,93,44,194,160,121,91,106,43,49,93,44,194,160,46,46,46,44,194,160,121,91,109,93,41,32,102,111,114,32,115,111,109,101,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,194,160,105,110,194,160,82,32,97,110,100,32,102,111,114,32,115,111,109,101,32,40,121,91,49,93,44,194,160,46,46,46,44,194,160,121,91,109,93,41,194,160,105,110,194,160,83,32,115,117,99,104,32,116,104,97,116,32,120,91,105,93,194,160,61,194,160,121,91,106,93,125,46>>]}]},{li,[],[{p,[],[{a,[{id,<<115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>}],[]},<<84,104,101,32,115,101,116,115,32,114,101,99,111,103,110,105,122,101,100,32,98,121,32,116,104,105,115,32,109,111,100,117,108,101,32,97,114,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,114,101,108,97,116,105,111,110,32,83,101,116,115,44,32,119,104,105,99,104,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,115,101,116,32,115,117,99,104,32,116,104,97,116,58>>]},{ul,[],[{li,[],[{p,[],[<<70,111,114,32,101,118,101,114,121,32,97,116,111,109,32,84,44,32,101,120,99,101,112,116,32,39,95,39,44,32,97,110,100,32,102,111,114,32,101,118,101,114,121,32,116,101,114,109,32,88,44,32,40,84,44,194,160,88,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40>>,{em,[],[<<97,116,111,109,105,99,32,115,101,116,115>>]},<<41,46>>]}]},{li,[],[{p,[],[<<40,91,39,95,39,93,44,194,160,91,93,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40,116,104,101,32>>,{em,[],[<<117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116>>]},<<41,46>>]}]},{li,[],[{p,[],[<<70,111,114,32,101,118,101,114,121,32,116,117,112,108,101,32,84,194,160,61,32,123,84,91,49,93,44,194,160,46,46,46,44,194,160,84,91,110,93,125,32,97,110,100,32,102,111,114,32,101,118,101,114,121,32,116,117,112,108,101,32,88,194,160,61,32,123,88,91,49,93,44,194,160,46,46,46,44,194,160,88,91,110,93,125,44,32,105,102,32,40,84,91,105,93,44,194,160,88,91,105,93,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,102,111,114,32,101,118,101,114,121,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,44,32,116,104,101,110,32,40,84,44,194,160,88,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40>>,{em,[],[<<111,114,100,101,114,101,100,32,115,101,116,115>>]},<<41,46>>]}]},{li,[],[{p,[],[<<70,111,114,32,101,118,101,114,121,32,116,101,114,109,32,84,44,32,105,102,32,88,32,105,115,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32,111,114,32,97,32,110,111,110,45,101,109,112,116,121,32,115,111,114,116,101,100,32,108,105,115,116,32,91,88,91,49,93,44,194,160,46,46,46,44,194,160,88,91,110,93,93,32,119,105,116,104,111,117,116,32,100,117,112,108,105,99,97,116,101,115,32,115,117,99,104,32,116,104,97,116,32,40,84,44,194,160,88,91,105,93,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,102,111,114,32,101,118,101,114,121,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,44,32,116,104,101,110,32,40,91,84,93,44,194,160,88,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40>>,{em,[],[<<116,121,112,101,100,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115>>]},<<41,46>>]}]}]},{p,[],[<<65,110,32>>,{a,[{id,<<101,120,116,101,114,110,97,108,95,115,101,116>>}],[]},{em,[],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,83,101,116,115,46>>]},{p,[],[<<65,32>>,{a,[{id,<<116,121,112,101>>}],[]},{em,[],[<<116,121,112,101>>]},<<32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,83,101,116,115,46>>]},{p,[],[<<73,102,32,83,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,40,84,44,194,160,88,41,32,111,102,32,83,101,116,115,44,32,116,104,101,110,32,84,32,105,115,32,97,32>>,{a,[{id,<<118,97,108,105,100,95,116,121,112,101>>}],[]},{em,[],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,111,102,32,88,44,32,84,32,105,115,32,116,104,101,32,116,121,112,101,32,111,102,32,83,44,32,97,110,100,32,88,32,105,115,32,116,104,101,32,101,120,116,101,114,110,97,108,32,115,101,116,32,111,102,32,83,46,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,116,101,114,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,116,101,114,109,47,50>>]}]},<<32,99,114,101,97,116,101,115,32,97,32,115,101,116,32,102,114,111,109,32,97,32,116,121,112,101,32,97,110,100,32,97,110,32,69,114,108,97,110,103,32,116,101,114,109,32,116,117,114,110,101,100,32,105,110,116,111,32,97,110,32,101,120,116,101,114,110,97,108,32,115,101,116,46>>]},{p,[],[<<84,104,101,32,115,101,116,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,83,101,116,115,32,97,114,101,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,102,117,110,99,116,105,111,110,32,83,101,116,32,102,114,111,109,32,83,101,116,115,32,116,111,32,69,114,108,97,110,103,32,116,101,114,109,115,32,97,110,100,32,115,101,116,115,32,111,102,32,69,114,108,97,110,103,32,116,101,114,109,115,58>>]},{ul,[],[{li,[],[<<83,101,116,40,84,44,84,101,114,109,41,194,160,61,32,84,101,114,109,44,32,119,104,101,114,101,32,84,32,105,115,32,97,110,32,97,116,111,109>>]},{li,[],[<<83,101,116,40,123,84,91,49,93,44,194,160,46,46,46,44,194,160,84,91,110,93,125,44,194,160,123,88,91,49,93,44,194,160,46,46,46,44,32,194,160,88,91,110,93,125,41,194,160,61,32,40,83,101,116,40,84,91,49,93,44,194,160,88,91,49,93,41,44,194,160,46,46,46,44,194,160,32,83,101,116,40,84,91,110,93,44,194,160,88,91,110,93,41,41>>]},{li,[],[<<83,101,116,40,91,84,93,44,194,160,91,88,91,49,93,44,194,160,46,46,46,44,194,160,88,91,110,93,93,41,194,160,61,32,123,83,101,116,40,84,44,194,160,88,91,49,93,41,44,194,160,46,46,46,44,194,160,83,101,116,40,84,44,194,160,88,91,110,93,41,125>>]},{li,[],[<<83,101,116,40,91,84,93,44,194,160,91,93,41,194,160,61,32,123,125>>]}]},{p,[],[<<87,104,101,110,32,116,104,101,114,101,32,105,115,32,110,111,32,114,105,115,107,32,111,102,32,99,111,110,102,117,115,105,111,110,44,32,101,108,101,109,101,110,116,115,32,111,102,32,83,101,116,115,32,97,114,101,32,105,100,101,110,116,105,102,105,101,100,32,119,105,116,104,32,116,104,101,32,115,101,116,115,32,116,104,101,121,32,114,101,112,114,101,115,101,110,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,85,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,105,111,110,47,50>>]}]},<<32,119,105,116,104,32,83,49,32,97,110,100,32,83,50,32,97,115,32,97,114,103,117,109,101,110,116,115,44,32,116,104,101,110,32,85,32,105,115,32,115,97,105,100,32,116,111,32,98,101,32,116,104,101,32,117,110,105,111,110,32,111,102,32,83,49,32,97,110,100,32,83,50,46,32,65,32,109,111,114,101,32,112,114,101,99,105,115,101,32,102,111,114,109,117,108,97,116,105,111,110,32,105,115,32,116,104,97,116,32,83,101,116,40,85,41,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32,83,101,116,40,83,49,41,32,97,110,100,32,83,101,116,40,83,50,41,46>>]}]}]},{p,[],[<<84,104,101,32,116,121,112,101,115,32,97,114,101,32,117,115,101,100,32,116,111,32,105,109,112,108,101,109,101,110,116,32,116,104,101,32,118,97,114,105,111,117,115,32,99,111,110,100,105,116,105,111,110,115,32,116,104,97,116,32,115,101,116,115,32,109,117,115,116,32,102,117,108,102,105,108,108,46,32,65,115,32,97,110,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,116,119,111,32,115,101,116,115,32,82,32,97,110,100,32,83,44,32,97,110,100,32,114,101,99,97,108,108,32,116,104,97,116,32,116,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,82,32,97,110,100,32,83,32,105,115,32,100,101,102,105,110,101,100,32,105,102,32,82,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,116,111,32,89,32,97,110,100,32,83,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,89,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,105,109,112,108,101,109,101,110,116,115,32,116,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>]}]},<<44,32,99,104,101,99,107,115,32,116,104,97,116,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,114,101,112,114,101,115,101,110,116,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,98,121,32,109,97,116,99,104,105,110,103,32,91,123,65,44,66,125,93,32,97,103,97,105,110,115,116,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,32,40,65,114,103,49,32,115,97,121,41,44,32,97,110,100,32,91,123,67,44,68,125,93,32,97,103,97,105,110,115,116,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,40,65,114,103,50,32,115,97,121,41,46,32,84,104,101,32,102,97,99,116,32,116,104,97,116,32,91,123,65,44,66,125,93,32,109,97,116,99,104,101,115,32,116,104,101,32,116,121,112,101,32,111,102,32,65,114,103,49,32,105,115,32,116,111,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,65,114,103,49,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,88,32,116,111,32,89,44,32,119,104,101,114,101,32,88,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,97,108,108,32,115,101,116,115,32,83,101,116,40,120,41,32,102,111,114,32,115,111,109,101,32,101,108,101,109,101,110,116,32,120,32,105,110,32,83,101,116,115,32,116,104,101,32,116,121,112,101,32,111,102,32,119,104,105,99,104,32,105,115,32,65,44,32,97,110,100,32,115,105,109,105,108,97,114,108,121,32,102,111,114,32,89,46,32,73,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,65,114,103,50,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,87,32,116,111,32,90,46,32,70,105,110,97,108,108,121,32,105,116,32,105,115,32,99,104,101,99,107,101,100,32,116,104,97,116,32,66,32,109,97,116,99,104,101,115,32,67,44,32,119,104,105,99,104,32,105,115,32,115,117,102,102,105,99,105,101,110,116,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,87,32,105,115,32,101,113,117,97,108,32,116,111,32,89,46,32,84,104,101,32,117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116,32,105,115,32,104,97,110,100,108,101,100,32,115,101,112,97,114,97,116,101,108,121,58,32,105,116,115,32,116,121,112,101,44,32,91,39,95,39,93,44,32,109,97,116,99,104,101,115,32,116,104,101,32,116,121,112,101,32,111,102,32,97,110,121,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46>>]},{p,[],[<<65,32,102,101,119,32,102,117,110,99,116,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,32,40>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,114,101,115,116,114,105,99,116,105,111,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,114,101,115,116,114,105,99,116,105,111,110,47,51>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,97,114,116,105,116,105,111,110,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,114,111,106,101,99,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,106,101,99,116,105,111,110,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,115,116,114,105,99,116,105,111,110,47,51>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,117,98,115,116,105,116,117,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,117,98,115,116,105,116,117,116,105,111,110,47,50>>]}]},<<41,32,97,99,99,101,112,116,32,97,110,32,69,114,108,97,110,103,32,102,117,110,99,116,105,111,110,32,97,115,32,97,32,109,101,97,110,115,32,116,111,32,109,111,100,105,102,121,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,97,32,103,105,118,101,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46,32>>,{a,[{id,<<115,101,116,95,102,117,110>>}],[]},<<83,117,99,104,32,97,32,102,117,110,99,116,105,111,110,44,32,99,97,108,108,101,100,32,83,101,116,70,117,110,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,102,117,110,99,116,105,111,110,97,108,32,111,98,106,101,99,116,32,40,102,117,110,41,44,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,194,160,70,117,110,125>>]},<<44,32,111,114,32,97,110,32,105,110,116,101,103,101,114,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,83,101,116,70,117,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,102,117,110,44,32,116,104,101,32,102,117,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,103,105,118,101,110,32,115,101,116,32,97,110,100,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,115,115,117,109,101,100,32,116,111,32,98,101,32,97,32,115,101,116,46>>]}]},{li,[],[{p,[],[<<73,102,32,83,101,116,70,117,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,32,70,117,110,125>>]},<<44,32,70,117,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32,101,120,116,101,114,110,97,108,32,115,101,116,32,111,102,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,103,105,118,101,110,32,115,101,116,32,97,110,100,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,115,115,117,109,101,100,32,116,111,32,98,101,32,97,110,32,101,120,116,101,114,110,97,108,32,115,101,116,46,32,83,101,108,101,99,116,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,97,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,97,115,32,101,120,116,101,114,110,97,108,32,115,101,116,115,32,97,110,100,32,97,115,115,101,109,98,108,105,110,103,32,97,32,110,101,119,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,102,114,111,109,32,97,32,108,105,115,116,32,111,102,32,101,120,116,101,114,110,97,108,32,115,101,116,115,32,105,115,32,105,110,32,116,104,101,32,112,114,101,115,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,109,111,100,105,102,121,105,110,103,32,101,97,99,104,32,101,108,101,109,101,110,116,32,97,115,32,97,32,115,101,116,46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,111,112,116,105,109,105,122,97,116,105,111,110,32,99,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,97,114,101,32,97,116,111,109,105,99,32,111,114,32,111,114,100,101,114,101,100,32,115,101,116,115,46,32,73,116,32,109,117,115,116,32,97,108,115,111,32,98,101,32,116,104,101,32,99,97,115,101,32,116,104,97,116,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,101,108,101,109,101,110,116,115,32,109,97,116,99,104,101,115,32,115,111,109,101,32,99,108,97,117,115,101,32,111,102,32,70,117,110,32,40,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,99,114,101,97,116,101,100,32,115,101,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32,70,117,110,32,116,111,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,103,105,118,101,110,32,115,101,116,41,44,32,97,110,100,32,116,104,97,116,32,70,117,110,32,100,111,101,115,32,110,111,116,104,105,110,103,32,98,117,116,32,115,101,108,101,99,116,105,110,103,44,32,100,117,112,108,105,99,97,116,105,110,103,44,32,111,114,32,114,101,97,114,114,97,110,103,105,110,103,32,112,97,114,116,115,32,111,102,32,116,104,101,32,101,108,101,109,101,110,116,115,46>>]}]},{li,[],[{p,[],[<<83,112,101,99,105,102,121,105,110,103,32,97,32,83,101,116,70,117,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,32,73,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,88,41,194,160,45,62,32,101,108,101,109,101,110,116,40,73,44,194,160,88,41,194,160,101,110,100,125>>]},<<44,32,98,117,116,32,105,115,32,116,111,32,98,101,32,112,114,101,102,101,114,114,101,100,44,32,97,115,32,105,116,32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,104,97,110,100,108,101,32,116,104,105,115,32,99,97,115,101,32,101,118,101,110,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,108,121,46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,115,32,111,102,32,83,101,116,70,117,110,115,58>>]},{pre,[],[{code,[],[<<102,117,110,32,115,111,102,115,58,117,110,105,111,110,47,49,10,102,117,110,40,83,41,32,45,62,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,49,44,32,83,41,32,101,110,100,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,65,41,32,45,62,32,65,32,101,110,100,125,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,65,44,95,44,67,125,41,32,45,62,32,123,67,44,65,125,32,101,110,100,125,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,95,44,123,95,44,67,125,125,41,32,45,62,32,67,32,101,110,100,125,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,95,44,123,95,44,123,95,44,69,125,61,67,125,125,41,32,45,62,32,123,69,44,123,69,44,67,125,125,32,101,110,100,125,10,50>>]}]},{p,[],[<<84,104,101,32,111,114,100,101,114,32,105,110,32,119,104,105,99,104,32,97,32,83,101,116,70,117,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,97,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,105,115,32,110,111,116,32,115,112,101,99,105,102,105,101,100,44,32,97,110,100,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,46>>]},{p,[],[<<84,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,32,105,115,32,100,111,109,105,110,97,116,101,100,32,98,121,32,116,104,101,32,116,105,109,101,32,105,116,32,116,97,107,101,115,32,116,111,32,115,111,114,116,32,108,105,115,116,115,46,32,87,104,101,110,32,110,111,32,115,111,114,116,105,110,103,32,105,115,32,110,101,101,100,101,100,44,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,105,115,32,105,110,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,112,114,111,112,111,114,116,105,111,110,97,108,32,116,111,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,115,105,122,101,115,32,111,102,32,116,104,101,32,105,110,112,117,116,32,97,114,103,117,109,101,110,116,115,32,97,110,100,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,46,32,65,32,102,101,119,32,102,117,110,99,116,105,111,110,115,32,101,120,101,99,117,116,101,32,105,110,32,99,111,110,115,116,97,110,116,32,116,105,109,101,58,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,115,95,101,109,112,116,121,95,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,101,109,112,116,121,95,115,101,116,47,49>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,115,95,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,115,101,116,47,49>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,115,95,115,111,102,115,95,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,115,111,102,115,95,115,101,116,47,49>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,111,95,101,120,116,101,114,110,97,108,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,111,95,101,120,116,101,114,110,97,108,47,49>>]}]},<<32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,121,112,101,47,49>>]}]},<<46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,32,101,120,105,116,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<44,32>>,{code,[],[<<98,97,100,95,102,117,110,99,116,105,111,110>>]},<<44,32,111,114,32>>,{code,[],[<<116,121,112,101,95,109,105,115,109,97,116,99,104>>]},<<32,109,101,115,115,97,103,101,32,119,104,101,110,32,103,105,118,101,110,32,98,97,100,108,121,32,102,111,114,109,101,100,32,97,114,103,117,109,101,110,116,115,32,111,114,32,115,101,116,115,32,116,104,101,32,116,121,112,101,115,32,111,102,32,119,104,105,99,104,32,97,114,101,32,110,111,116,32,99,111,109,112,97,116,105,98,108,101,46>>]},{p,[],[<<87,104,101,110,32,99,111,109,112,97,114,105,110,103,32,101,120,116,101,114,110,97,108,32,115,101,116,115,44,32,111,112,101,114,97,116,111,114,32>>,{code,[],[<<61,61,47,50>>]},<<32,105,115,32,117,115,101,100,46>>]},{h2,[],[<<83,101,101,32,65,108,115,111>>]},{p,[],[{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,105,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,99,116,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,105,103,114,97,112,104>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,103,114,97,112,104,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,111,114,100,100,105,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,114,100,100,105,99,116,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,111,114,100,115,101,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,114,100,115,101,116,115,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,116,115,40,51,41>>]}]}]}]},#{name => <<115,111,102,115>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,115,111,102,115,46,120,109,108],types => #{{a_function,0} => {attribute,120,type,{a_function,{user_type,120,relation,[]},[]}},{a_set,0} => {attribute,124,opaque,{a_set,{type,124,record,[{atom,124,'Set'}]},[]}},{anyset,0} => {attribute,117,type,{anyset,{type,117,union,[{user_type,117,ordset,[]},{user_type,117,a_set,[]}]},[]}},{binary_relation,0} => {attribute,118,type,{binary_relation,{user_type,118,relation,[]},[]}},{external_set,0} => {attribute,119,type,{external_set,{type,119,term,[]},[]}},{family,0} => {attribute,121,type,{family,{user_type,121,a_function,[]},[]}},{ordset,0} => {attribute,122,opaque,{ordset,{type,122,record,[{atom,122,'OrdSet'}]},[]}},{relation,0} => {attribute,123,type,{relation,{user_type,123,a_set,[]},[]}},{set_fun,0} => {attribute,126,type,{set_fun,{type,126,union,[{type,126,pos_integer,[]},{type,127,tuple,[{atom,127,external},{type,127,'fun',[{type,127,product,[{user_type,127,external_set,[]}]},{user_type,127,external_set,[]}]}]},{type,128,'fun',[{type,128,product,[{user_type,128,anyset,[]}]},{user_type,128,anyset,[]}]}]},[]}},{set_of_sets,0} => {attribute,125,type,{set_of_sets,{user_type,125,a_set,[]},[]}},{spec_fun,0} => {attribute,129,type,{spec_fun,{type,129,union,[{type,129,tuple,[{atom,129,external},{type,129,'fun',[{type,129,product,[{user_type,129,external_set,[]}]},{type,129,boolean,[]}]}]},{type,130,'fun',[{type,130,product,[{user_type,130,anyset,[]}]},{type,130,boolean,[]}]}]},[]}},{tuple_of,1} => {attribute,133,type,{tuple_of,{type,133,tuple,any},[{var,133,'_T'}]}},{type,0} => {attribute,131,type,{type,{type,131,term,[]},[]}}}},[{{function,a_function,2},[{file,[115,111,102,115,46,101,114,108]},{location,277}],[<<97,95,102,117,110,99,116,105,111,110,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,53,56>>,equiv => {function,a_function,1},signature => [{attribute,277,spec,{{a_function,2},[{type,277,bounded_fun,[{type,277,'fun',[{type,277,product,[{var,277,'Tuples'},{var,277,'Type'}]},{var,277,'Function'}]},[{type,278,constraint,[{atom,278,is_subtype},[{var,278,'Function'},{user_type,278,a_function,[]}]]},{type,279,constraint,[{atom,279,is_subtype},[{var,279,'Tuples'},{type,279,list,[{type,279,tuple,any}]}]]},{type,280,constraint,[{atom,280,is_subtype},[{var,280,'Type'},{user_type,280,type,[]}]]}]]}]}}]}},{{function,a_function,1},[{file,[115,111,102,115,46,101,114,108]},{location,265}],[<<97,95,102,117,110,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<46,32>>,{code,[],[<<97,95,102,117,110,99,116,105,111,110,40,70,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,70,44,194,160,84,41>>]},<<32,105,102,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,102,117,110,99,116,105,111,110,46,32,73,102,32,110,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<91,123,97,116,111,109,44,194,160,97,116,111,109,125,93>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,121,112,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,53,56>>,signature => [{attribute,265,spec,{{a_function,1},[{type,265,bounded_fun,[{type,265,'fun',[{type,265,product,[{var,265,'Tuples'}]},{var,265,'Function'}]},[{type,266,constraint,[{atom,266,is_subtype},[{var,266,'Function'},{user_type,266,a_function,[]}]]},{type,267,constraint,[{atom,267,is_subtype},[{var,267,'Tuples'},{type,267,list,[{type,267,tuple,any}]}]]}]]}]}}]}},{{function,canonical_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,577}],[<<99,97,110,111,110,105,99,97,108,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,40,69,44,194,160,83,101,116,41,32,115,117,99,104,32,116,104,97,116,32,83,101,116,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,97,110,100,32,69,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,46,32,73,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32,97,32,115,101,116,32,88,32,97,110,100,32,82,32,105,115,32,116,104,101,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,32,88,32,105,110,100,117,99,101,100,32,98,121,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<44,32,116,104,101,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,114,101,108,97,116,105,111,110,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,97,110,111,110,105,99,97,108,95,109,97,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,97,110,111,110,105,99,97,108,32,109,97,112>>]},<<32,102,114,111,109,32,88,32,111,110,116,111,32,116,104,101,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,101,115,32,119,105,116,104,32,114,101,115,112,101,99,116,32,116,111,32,82,46>>]},{pre,[],[{code,[],[<<49,62,32,83,115,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,97,44,98,93,44,91,98,44,99,93,93,41,44,10,67,82,32,61,32,115,111,102,115,58,99,97,110,111,110,105,99,97,108,95,114,101,108,97,116,105,111,110,40,83,115,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,67,82,41,46,10,91,123,97,44,91,97,44,98,93,125,44,123,98,44,91,97,44,98,93,125,44,123,98,44,91,98,44,99,93,125,44,123,99,44,91,98,44,99,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,55,50>>,signature => [{attribute,577,spec,{{canonical_relation,1},[{type,577,bounded_fun,[{type,577,'fun',[{type,577,product,[{var,577,'SetOfSets'}]},{var,577,'BinRel'}]},[{type,578,constraint,[{atom,578,is_subtype},[{var,578,'BinRel'},{user_type,578,binary_relation,[]}]]},{type,579,constraint,[{atom,579,is_subtype},[{var,579,'SetOfSets'},{user_type,579,set_of_sets,[]}]]}]]}]}}]}},{{function,composite,2},[{file,[115,111,102,115,46,101,114,108]},{location,844}],[<<99,111,109,112,111,115,105,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,111,109,112,111,115,105,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,109,112,111,115,105,116,101>>]},<<32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32>>,{code,[],[<<70,117,110,99,116,105,111,110,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,117,110,99,116,105,111,110,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,97,95,102,117,110,99,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,44,123,99,44,50,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,97,95,102,117,110,99,116,105,111,110,40,91,123,49,44,120,125,44,123,50,44,121,125,44,123,51,44,122,125,93,41,44,10,70,32,61,32,115,111,102,115,58,99,111,109,112,111,115,105,116,101,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,120,125,44,123,98,44,121,125,44,123,99,44,121,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,57,50>>,signature => [{attribute,844,spec,{{composite,2},[{type,844,bounded_fun,[{type,844,'fun',[{type,844,product,[{var,844,'Function1'},{var,844,'Function2'}]},{var,844,'Function3'}]},[{type,845,constraint,[{atom,845,is_subtype},[{var,845,'Function1'},{user_type,845,a_function,[]}]]},{type,846,constraint,[{atom,846,is_subtype},[{var,846,'Function2'},{user_type,846,a_function,[]}]]},{type,847,constraint,[{atom,847,is_subtype},[{var,847,'Function3'},{user_type,847,a_function,[]}]]}]]}]}}]}},{{function,constant_function,2},[{file,[115,111,102,115,46,101,114,108]},{location,465}],[<<99,111,110,115,116,97,110,116,95,102,117,110,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<32,116,104,97,116,32,109,97,112,115,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,115,101,116,32>>,{code,[],[<<83,101,116>>]},<<32,111,110,116,111,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,115,101,116,40,91,97,44,98,93,41,44,10,69,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,49,41,44,10,82,32,61,32,115,111,102,115,58,99,111,110,115,116,97,110,116,95,102,117,110,99,116,105,111,110,40,83,44,32,69,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,41,46,10,91,123,97,44,49,125,44,123,98,44,49,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,48,56>>,signature => [{attribute,465,spec,{{constant_function,2},[{type,465,bounded_fun,[{type,465,'fun',[{type,465,product,[{var,465,'Set'},{var,465,'AnySet'}]},{var,465,'Function'}]},[{type,466,constraint,[{atom,466,is_subtype},[{var,466,'AnySet'},{user_type,466,anyset,[]}]]},{type,467,constraint,[{atom,467,is_subtype},[{var,467,'Function'},{user_type,467,a_function,[]}]]},{type,468,constraint,[{atom,468,is_subtype},[{var,468,'Set'},{user_type,468,a_set,[]}]]}]]}]}}]}},{{function,converse,1},[{file,[115,111,102,115,46,101,114,108]},{location,707}],[<<99,111,110,118,101,114,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,111,110,118,101,114,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,110,118,101,114,115,101>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,97,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,99,111,110,118,101,114,115,101,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,97,44,49,125,44,123,97,44,51,125,44,123,98,44,50,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,50,52>>,signature => [{attribute,707,spec,{{converse,1},[{type,707,bounded_fun,[{type,707,'fun',[{type,707,product,[{var,707,'BinRel1'}]},{var,707,'BinRel2'}]},[{type,708,constraint,[{atom,708,is_subtype},[{var,708,'BinRel1'},{user_type,708,binary_relation,[]}]]},{type,709,constraint,[{atom,709,is_subtype},[{var,709,'BinRel2'},{user_type,709,binary_relation,[]}]]}]]}]}}]}},{{function,difference,2},[{file,[115,111,102,115,46,101,114,108]},{location,398}],[<<100,105,102,102,101,114,101,110,99,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,105,102,102,101,114,101,110,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,102,102,101,114,101,110,99,101>>]},<<32,111,102,32,116,104,101,32,115,101,116,115,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,51,56>>,signature => [{attribute,398,spec,{{difference,2},[{type,398,bounded_fun,[{type,398,'fun',[{type,398,product,[{var,398,'Set1'},{var,398,'Set2'}]},{var,398,'Set3'}]},[{type,399,constraint,[{atom,399,is_subtype},[{var,399,'Set1'},{user_type,399,a_set,[]}]]},{type,400,constraint,[{atom,400,is_subtype},[{var,400,'Set2'},{user_type,400,a_set,[]}]]},{type,401,constraint,[{atom,401,is_subtype},[{var,401,'Set3'},{user_type,401,a_set,[]}]]}]]}]}}]}},{{function,digraph_to_family,2},[{file,[115,111,102,115,46,101,114,108]},{location,1520}],[<<100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,52,55>>,equiv => {function,digraph_to_family,1},signature => [{attribute,1520,spec,{{digraph_to_family,2},[{type,1520,bounded_fun,[{type,1520,'fun',[{type,1520,product,[{var,1520,'Graph'},{var,1520,'Type'}]},{var,1520,'Family'}]},[{type,1521,constraint,[{atom,1521,is_subtype},[{var,1521,'Graph'},{remote_type,1521,[{atom,1521,digraph},{atom,1521,graph},[]]}]]},{type,1522,constraint,[{atom,1522,is_subtype},[{var,1522,'Family'},{user_type,1522,family,[]}]]},{type,1523,constraint,[{atom,1523,is_subtype},[{var,1523,'Type'},{user_type,1523,type,[]}]]}]]}]}}]}},{{function,digraph_to_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,1511}],[<<100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,102,114,111,109,32,116,104,101,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,32>>,{code,[],[<<71,114,97,112,104>>]},<<46,32,69,97,99,104,32,118,101,114,116,101,120,32,97,32,111,102,32>>,{code,[],[<<71,114,97,112,104>>]},<<32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,112,97,105,114,32,40,97,44,194,160,123,98,91,49,93,44,194,160,46,46,46,44,194,160,98,91,110,93,125,41,44,32,119,104,101,114,101,32,116,104,101,32,98,91,105,93,58,115,32,97,114,101,32,116,104,101,32,111,117,116,45,110,101,105,103,104,98,111,114,115,32,111,102,32,97,46,32,73,102,32,110,111,32,116,121,112,101,32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32,91,123,97,116,111,109,44,194,160,91,97,116,111,109,93,125,93,32,105,115,32,117,115,101,100,32,97,115,32,116,121,112,101,32,111,102,32,116,104,101,32,102,97,109,105,108,121,46,32,73,116,32,105,115,32,97,115,115,117,109,101,100,32,116,104,97,116,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,118,97,108,105,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,111,102,32,116,104,101,32,101,120,116,101,114,110,97,108,32,115,101,116,32,111,102,32,116,104,101,32,102,97,109,105,108,121,46>>]},{p,[],[<<73,102,32,71,32,105,115,32,97,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,44,32,105,116,32,104,111,108,100,115,32,116,104,97,116,32,116,104,101,32,118,101,114,116,105,99,101,115,32,97,110,100,32,101,100,103,101,115,32,111,102,32,71,32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,118,101,114,116,105,99,101,115,32,97,110,100,32,101,100,103,101,115,32,111,102,32>>,{code,[],[<<102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,40,100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,40,71,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,52,55>>,signature => [{attribute,1511,spec,{{digraph_to_family,1},[{type,1511,bounded_fun,[{type,1511,'fun',[{type,1511,product,[{var,1511,'Graph'}]},{var,1511,'Family'}]},[{type,1512,constraint,[{atom,1512,is_subtype},[{var,1512,'Graph'},{remote_type,1512,[{atom,1512,digraph},{atom,1512,graph},[]]}]]},{type,1513,constraint,[{atom,1513,is_subtype},[{var,1513,'Family'},{user_type,1513,family,[]}]]}]]}]}}]}},{{function,domain,1},[{file,[115,111,102,115,46,101,114,108]},{location,612}],[<<100,111,109,97,105,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,98,125,44,123,50,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,100,111,109,97,105,110,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,49,44,50,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,54,55>>,signature => [{attribute,612,spec,{{domain,1},[{type,612,bounded_fun,[{type,612,'fun',[{type,612,product,[{var,612,'BinRel'}]},{var,612,'Set'}]},[{type,613,constraint,[{atom,613,is_subtype},[{var,613,'BinRel'},{user_type,613,binary_relation,[]}]]},{type,614,constraint,[{atom,614,is_subtype},[{var,614,'Set'},{user_type,614,a_set,[]}]]}]]}]}}]}},{{function,drestriction,2},[{file,[115,111,102,115,46,101,114,108]},{location,833}],[<<100,114,101,115,116,114,105,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,101,116,119,101,101,110,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,97,110,100,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,116,111,32>>,{code,[],[<<83,101,116>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,50,44,52,44,54,93,41,44,10,82,50,32,61,32,115,111,102,115,58,100,114,101,115,116,114,105,99,116,105,111,110,40,82,49,44,32,83,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,97,125,44,123,51,44,99,125,93>>]}]},{p,[],[{code,[],[<<100,114,101,115,116,114,105,99,116,105,111,110,40,82,44,194,160,83,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<100,105,102,102,101,114,101,110,99,101,40,82,44,194,160,114,101,115,116,114,105,99,116,105,111,110,40,82,44,194,160,83,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,56,49>>,signature => [{attribute,833,spec,{{drestriction,2},[{type,833,bounded_fun,[{type,833,'fun',[{type,833,product,[{var,833,'BinRel1'},{var,833,'Set'}]},{var,833,'BinRel2'}]},[{type,834,constraint,[{atom,834,is_subtype},[{var,834,'BinRel1'},{user_type,834,binary_relation,[]}]]},{type,835,constraint,[{atom,835,is_subtype},[{var,835,'BinRel2'},{user_type,835,binary_relation,[]}]]},{type,836,constraint,[{atom,836,is_subtype},[{var,836,'Set'},{user_type,836,a_set,[]}]]}]]}]}}]}},{{function,drestriction,3},[{file,[115,111,102,115,46,101,114,108]},{location,960}],[<<100,114,101,115,116,114,105,99,116,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,100,111,32,110,111,116,32,103,105,118,101,32,97,110,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<83,101,116,50>>]},<<32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,101,116,70,117,110,32,61,32,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,95,65,44,66,44,67,125,41,32,45,62,32,123,66,44,67,125,32,101,110,100,125,44,10,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,97,97,44,49,125,44,123,98,44,98,98,44,50,125,44,123,99,44,99,99,44,51,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,98,98,44,50,125,44,123,99,99,44,51,125,44,123,100,100,44,52,125,93,41,44,10,82,51,32,61,32,115,111,102,115,58,100,114,101,115,116,114,105,99,116,105,111,110,40,83,101,116,70,117,110,44,32,82,49,44,32,82,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,51,41,46,10,91,123,97,44,97,97,44,49,125,93>>]}]},{p,[],[{code,[],[<<100,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<100,105,102,102,101,114,101,110,99,101,40,83,49,44,194,160,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,48,48>>,signature => [{attribute,960,spec,{{drestriction,3},[{type,960,bounded_fun,[{type,960,'fun',[{type,960,product,[{var,960,'SetFun'},{var,960,'Set1'},{var,960,'Set2'}]},{var,960,'Set3'}]},[{type,961,constraint,[{atom,961,is_subtype},[{var,961,'SetFun'},{user_type,961,set_fun,[]}]]},{type,962,constraint,[{atom,962,is_subtype},[{var,962,'Set1'},{user_type,962,a_set,[]}]]},{type,963,constraint,[{atom,963,is_subtype},[{var,963,'Set2'},{user_type,963,a_set,[]}]]},{type,964,constraint,[{atom,964,is_subtype},[{var,964,'Set3'},{user_type,964,a_set,[]}]]}]]}]}}]}},{{function,empty_set,0},[{file,[115,111,102,115,46,101,114,108]},{location,178}],[<<101,109,112,116,121,95,115,101,116,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116>>]},<<46,32>>,{code,[],[<<101,109,112,116,121,95,115,101,116,40,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,91,93,44,194,160,91,39,95,39,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,50,48>>,signature => [{attribute,178,spec,{{empty_set,0},[{type,178,bounded_fun,[{type,178,'fun',[{type,178,product,[]},{var,178,'Set'}]},[{type,179,constraint,[{atom,179,is_subtype},[{var,179,'Set'},{user_type,179,a_set,[]}]]}]]}]}}]}},{{function,extension,3},[{file,[115,111,102,115,46,101,114,108]},{location,779}],[<<101,120,116,101,110,115,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,110,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,110,115,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,115,117,99,104,32,116,104,97,116,32,102,111,114,32,101,97,99,104,32,101,108,101,109,101,110,116,32,69,32,105,110,32>>,{code,[],[<<83,101,116>>]},<<32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<44,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,112,97,105,114,32,40,69,44,194,160>>,{code,[],[<<65,110,121,83,101,116>>]},<<41,46>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,115,101,116,40,91,98,44,99,93,41,44,10,65,32,61,32,115,111,102,115,58,101,109,112,116,121,95,115,101,116,40,41,44,10,82,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,93,125,93,41,44,10,88,32,61,32,115,111,102,115,58,101,120,116,101,110,115,105,111,110,40,82,44,32,83,44,32,65,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,88,41,46,10,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,93,125,44,123,99,44,91,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,51,48>>,signature => [{attribute,779,spec,{{extension,3},[{type,779,bounded_fun,[{type,779,'fun',[{type,779,product,[{var,779,'BinRel1'},{var,779,'Set'},{var,779,'AnySet'}]},{var,779,'BinRel2'}]},[{type,780,constraint,[{atom,780,is_subtype},[{var,780,'AnySet'},{user_type,780,anyset,[]}]]},{type,781,constraint,[{atom,781,is_subtype},[{var,781,'BinRel1'},{user_type,781,binary_relation,[]}]]},{type,782,constraint,[{atom,782,is_subtype},[{var,782,'BinRel2'},{user_type,782,binary_relation,[]}]]},{type,783,constraint,[{atom,783,is_subtype},[{var,783,'Set'},{user_type,783,a_set,[]}]]}]]}]}}]}},{{function,family,2},[{file,[115,111,102,115,46,101,114,108]},{location,302}],[<<102,97,109,105,108,121,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,53,48>>,equiv => {function,family,1},signature => [{attribute,302,spec,{{family,2},[{type,302,bounded_fun,[{type,302,'fun',[{type,302,product,[{var,302,'Tuples'},{var,302,'Type'}]},{var,302,'Family'}]},[{type,303,constraint,[{atom,303,is_subtype},[{var,303,'Family'},{user_type,303,family,[]}]]},{type,304,constraint,[{atom,304,is_subtype},[{var,304,'Tuples'},{type,304,list,[{type,304,tuple,any}]}]]},{type,305,constraint,[{atom,305,is_subtype},[{var,305,'Type'},{user_type,305,type,[]}]]}]]}]}}]}},{{function,family,1},[{file,[115,111,102,115,46,101,114,108]},{location,290}],[<<102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121,32,111,102,32,115,117,98,115,101,116,115>>]},<<46,32>>,{code,[],[<<102,97,109,105,108,121,40,70,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,70,44,194,160,84,41>>]},<<32,105,102,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,102,97,109,105,108,121,46,32,73,102,32,110,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<91,123,97,116,111,109,44,194,160,91,97,116,111,109,93,125,93>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,102,97,109,105,108,121,32,116,121,112,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,53,48>>,signature => [{attribute,290,spec,{{family,1},[{type,290,bounded_fun,[{type,290,'fun',[{type,290,product,[{var,290,'Tuples'}]},{var,290,'Family'}]},[{type,291,constraint,[{atom,291,is_subtype},[{var,291,'Family'},{user_type,291,family,[]}]]},{type,292,constraint,[{atom,292,is_subtype},[{var,292,'Tuples'},{type,292,list,[{type,292,tuple,any}]}]]}]]}]}}]}},{{function,family_difference,2},[{file,[115,111,102,115,46,101,114,108]},{location,1385}],[<<102,97,109,105,108,121,95,100,105,102,102,101,114,101,110,99,101,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,105,101,115>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,101,113,117,97,108,32,116,111,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<91,105,93,32,105,115,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,101,116,119,101,101,110,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,102,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,109,97,112,115,32,105,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,97,109,105,108,121,49,91,105,93>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,98,44,91,52,44,53,93,125,44,123,99,44,91,54,44,55,93,125,93,41,44,10,70,51,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,100,105,102,102,101,114,101,110,99,101,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,51,41,46,10,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,54,52>>,signature => [{attribute,1385,spec,{{family_difference,2},[{type,1385,bounded_fun,[{type,1385,'fun',[{type,1385,product,[{var,1385,'Family1'},{var,1385,'Family2'}]},{var,1385,'Family3'}]},[{type,1386,constraint,[{atom,1386,is_subtype},[{var,1386,'Family1'},{user_type,1386,family,[]}]]},{type,1387,constraint,[{atom,1387,is_subtype},[{var,1387,'Family2'},{user_type,1387,family,[]}]]},{type,1388,constraint,[{atom,1388,is_subtype},[{var,1388,'Family3'},{user_type,1388,family,[]}]]}]]}]}}]}},{{function,family_domain,1},[{file,[115,111,102,115,46,101,114,108]},{location,1341}],[<<102,97,109,105,108,121,95,100,111,109,97,105,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49,91,105,93>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,82,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,125,44,123,98,44,91,93,125,44,123,99,44,91,123,52,44,100,125,44,123,53,44,101,125,93,125,93,41,44,10,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,100,111,109,97,105,110,40,70,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,93,125,44,123,99,44,91,52,44,53,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,56,53>>,signature => [{attribute,1341,spec,{{family_domain,1},[{type,1341,bounded_fun,[{type,1341,'fun',[{type,1341,product,[{var,1341,'Family1'}]},{var,1341,'Family2'}]},[{type,1342,constraint,[{atom,1342,is_subtype},[{var,1342,'Family1'},{user_type,1342,family,[]}]]},{type,1343,constraint,[{atom,1343,is_subtype},[{var,1343,'Family2'},{user_type,1343,family,[]}]]}]]}]}}]}},{{function,family_field,1},[{file,[115,111,102,115,46,101,114,108]},{location,1365}],[<<102,97,109,105,108,121,95,102,105,101,108,100,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,105,101,108,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,101,108,100>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,82,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,125,44,123,98,44,91,93,125,44,123,99,44,91,123,52,44,100,125,44,123,53,44,101,125,93,125,93,41,44,10,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,102,105,101,108,100,40,70,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,91,49,44,50,44,51,44,97,44,98,44,99,93,125,44,123,98,44,91,93,125,44,123,99,44,91,52,44,53,44,100,44,101,93,125,93>>]}]},{p,[],[{code,[],[<<102,97,109,105,108,121,95,102,105,101,108,100,40,70,97,109,105,108,121,49,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,97,109,105,108,121,95,117,110,105,111,110,40,102,97,109,105,108,121,95,100,111,109,97,105,110,40,70,97,109,105,108,121,49,41,44,32,102,97,109,105,108,121,95,114,97,110,103,101,40,70,97,109,105,108,121,49,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,48,54>>,signature => [{attribute,1365,spec,{{family_field,1},[{type,1365,bounded_fun,[{type,1365,'fun',[{type,1365,product,[{var,1365,'Family1'}]},{var,1365,'Family2'}]},[{type,1366,constraint,[{atom,1366,is_subtype},[{var,1366,'Family1'},{user_type,1366,family,[]}]]},{type,1367,constraint,[{atom,1367,is_subtype},[{var,1367,'Family2'},{user_type,1367,family,[]}]]}]]}]}}]}},{{function,family_intersection,1},[{file,[115,111,102,115,46,101,114,108]},{location,1325}],[<<102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,115,101,116,32,111,102,32,115,101,116,115,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,116,101,114,115,101,99,116,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,110,32,101,109,112,116,121,32,115,101,116,32,102,111,114,32,115,111,109,101,32,105,44,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,109,101,115,115,97,103,101,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,91,49,44,50,44,51,93,44,91,50,44,51,44,52,93,93,125,44,123,98,44,91,91,120,44,121,44,122,93,44,91,120,44,121,93,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,40,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,97,44,91,50,44,51,93,125,44,123,98,44,91,120,44,121,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,51,48>>,signature => [{attribute,1325,spec,{{family_intersection,1},[{type,1325,bounded_fun,[{type,1325,'fun',[{type,1325,product,[{var,1325,'Family1'}]},{var,1325,'Family2'}]},[{type,1326,constraint,[{atom,1326,is_subtype},[{var,1326,'Family1'},{user_type,1326,family,[]}]]},{type,1327,constraint,[{atom,1327,is_subtype},[{var,1327,'Family2'},{user_type,1327,family,[]}]]}]]}]}}]}},{{function,family_intersection,2},[{file,[115,111,102,115,46,101,114,108]},{location,1378}],[<<102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,105,101,115>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<58,115,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<58,115,32,105,110,100,101,120,32,115,101,116,115,44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<91,105,93,32,105,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,93,125,44,123,99,44,91,53,44,54,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,98,44,91,52,44,53,93,125,44,123,99,44,91,55,44,56,93,125,44,123,100,44,91,57,44,49,48,93,125,93,41,44,10,70,51,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,51,41,46,10,91,123,98,44,91,52,93,125,44,123,99,44,91,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,53,52>>,signature => [{attribute,1378,spec,{{family_intersection,2},[{type,1378,bounded_fun,[{type,1378,'fun',[{type,1378,product,[{var,1378,'Family1'},{var,1378,'Family2'}]},{var,1378,'Family3'}]},[{type,1379,constraint,[{atom,1379,is_subtype},[{var,1379,'Family1'},{user_type,1379,family,[]}]]},{type,1380,constraint,[{atom,1380,is_subtype},[{var,1380,'Family2'},{user_type,1380,family,[]}]]},{type,1381,constraint,[{atom,1381,is_subtype},[{var,1381,'Family3'},{user_type,1381,family,[]}]]}]]}]}}]}},{{function,family_projection,2},[{file,[115,111,102,115,46,101,114,108]},{location,1451}],[<<102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,99,97,108,108,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,119,105,116,104,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,91,49,44,50,93,44,91,50,44,51,93,93,125,44,123,98,44,91,91,93,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,40,102,117,110,32,115,111,102,115,58,117,110,105,111,110,47,49,44,32,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,55,52>>,signature => [{attribute,1451,spec,{{family_projection,2},[{type,1451,bounded_fun,[{type,1451,'fun',[{type,1451,product,[{var,1451,'SetFun'},{var,1451,'Family1'}]},{var,1451,'Family2'}]},[{type,1452,constraint,[{atom,1452,is_subtype},[{var,1452,'SetFun'},{user_type,1452,set_fun,[]}]]},{type,1453,constraint,[{atom,1453,is_subtype},[{var,1453,'Family1'},{user_type,1453,family,[]}]]},{type,1454,constraint,[{atom,1454,is_subtype},[{var,1454,'Family2'},{user_type,1454,family,[]}]]}]]}]}}]}},{{function,family_range,1},[{file,[115,111,102,115,46,101,114,108]},{location,1353}],[<<102,97,109,105,108,121,95,114,97,110,103,101,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,97,110,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,97,110,103,101>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,82,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,125,44,123,98,44,91,93,125,44,123,99,44,91,123,52,44,100,125,44,123,53,44,101,125,93,125,93,41,44,10,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,114,97,110,103,101,40,70,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,91,97,44,98,44,99,93,125,44,123,98,44,91,93,125,44,123,99,44,91,100,44,101,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,57,51>>,signature => [{attribute,1353,spec,{{family_range,1},[{type,1353,bounded_fun,[{type,1353,'fun',[{type,1353,product,[{var,1353,'Family1'}]},{var,1353,'Family2'}]},[{type,1354,constraint,[{atom,1354,is_subtype},[{var,1354,'Family1'},{user_type,1354,family,[]}]]},{type,1355,constraint,[{atom,1355,is_subtype},[{var,1355,'Family2'},{user_type,1355,family,[]}]]}]]}]}}]}},{{function,family_specification,2},[{file,[115,111,102,115,46,101,114,108]},{location,1265}],[<<102,97,109,105,108,121,95,115,112,101,99,105,102,105,99,97,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,116,111,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,105,32,111,102,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,102,111,114,32,119,104,105,99,104,32>>,{code,[],[<<70,117,110>>]},<<32,97,112,112,108,105,101,100,32,116,111,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,194,160,70,117,110,50,125>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,117,110,50>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,49,44,50,93,125,44,123,99,44,91,49,93,125,93,41,44,10,83,112,101,99,70,117,110,32,61,32,102,117,110,40,83,41,32,45,62,32,115,111,102,115,58,110,111,95,101,108,101,109,101,110,116,115,40,83,41,32,61,58,61,32,50,32,101,110,100,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,115,112,101,99,105,102,105,99,97,116,105,111,110,40,83,112,101,99,70,117,110,44,32,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,98,44,91,49,44,50,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,49,52>>,signature => [{attribute,1265,spec,{{family_specification,2},[{type,1265,bounded_fun,[{type,1265,'fun',[{type,1265,product,[{var,1265,'Fun'},{var,1265,'Family1'}]},{var,1265,'Family2'}]},[{type,1266,constraint,[{atom,1266,is_subtype},[{var,1266,'Fun'},{user_type,1266,spec_fun,[]}]]},{type,1267,constraint,[{atom,1267,is_subtype},[{var,1267,'Family1'},{user_type,1267,family,[]}]]},{type,1268,constraint,[{atom,1268,is_subtype},[{var,1268,'Family2'},{user_type,1268,family,[]}]]}]]}]}}]}},{{function,family_to_digraph,2},[{file,[115,111,102,115,46,101,114,108]},{location,1489}],[<<102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,51,57>>,equiv => {function,family_to_digraph,1},signature => [{attribute,1489,spec,{{family_to_digraph,2},[{type,1489,bounded_fun,[{type,1489,'fun',[{type,1489,product,[{var,1489,'Family'},{var,1489,'GraphType'}]},{var,1489,'Graph'}]},[{type,1490,constraint,[{atom,1490,is_subtype},[{var,1490,'Graph'},{remote_type,1490,[{atom,1490,digraph},{atom,1490,graph},[]]}]]},{type,1491,constraint,[{atom,1491,is_subtype},[{var,1491,'Family'},{user_type,1491,family,[]}]]},{type,1492,constraint,[{atom,1492,is_subtype},[{var,1492,'GraphType'},{type,1492,list,[{remote_type,1492,[{atom,1492,digraph},{atom,1492,d_type},[]]}]}]]}]]}]}}]}},{{function,family_to_digraph,1},[{file,[115,111,102,115,46,101,114,108]},{location,1479}],[<<102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,32,102,114,111,109,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<46,32,70,111,114,32,101,97,99,104,32,112,97,105,114,32,40,97,44,194,160,123,98,91,49,93,44,194,160,46,46,46,44,194,160,98,91,110,93,125,41,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<44,32,118,101,114,116,101,120,32,97,32,97,110,100,32,116,104,101,32,101,100,103,101,115,32,40,97,44,194,160,98,91,105,93,41,32,102,111,114,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,32,97,114,101,32,97,100,100,101,100,32,116,111,32,97,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,46>>]},{p,[],[<<73,102,32,110,111,32,103,114,97,112,104,32,116,121,112,101,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32>>,{a,[{href,<<115,116,100,108,105,98,58,100,105,103,114,97,112,104,35,110,101,119,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,105,103,114,97,112,104,58,110,101,119,47,48>>]}]},<<32,105,115,32,117,115,101,100,32,102,111,114,32,99,114,101,97,116,105,110,103,32,116,104,101,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,44,32,111,116,104,101,114,119,105,115,101,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<71,114,97,112,104,84,121,112,101>>]},<<32,105,115,32,112,97,115,115,101,100,32,111,110,32,97,115,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,100,105,103,114,97,112,104,35,110,101,119,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,105,103,114,97,112,104,58,110,101,119,47,49>>]}]},<<46>>]},{p,[],[<<73,116,32,70,32,105,115,32,97,32,102,97,109,105,108,121,44,32,105,116,32,104,111,108,100,115,32,116,104,97,116,32,70,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,40,102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,40,70,41,44,194,160,116,121,112,101,40,70,41,41>>]},<<46,32,69,113,117,97,108,105,116,121,32,104,111,108,100,115,32,105,102,32>>,{code,[],[<<117,110,105,111,110,95,111,102,95,102,97,109,105,108,121,40,70,41>>]},<<32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<100,111,109,97,105,110,40,70,41>>]},<<46>>]},{p,[],[<<67,114,101,97,116,105,110,103,32,97,32,99,121,99,108,101,32,105,110,32,97,110,32,97,99,121,99,108,105,99,32,103,114,97,112,104,32,101,120,105,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<99,121,99,108,105,99>>]},<<32,109,101,115,115,97,103,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,51,57>>,signature => [{attribute,1479,spec,{{family_to_digraph,1},[{type,1479,bounded_fun,[{type,1479,'fun',[{type,1479,product,[{var,1479,'Family'}]},{var,1479,'Graph'}]},[{type,1480,constraint,[{atom,1480,is_subtype},[{var,1480,'Graph'},{remote_type,1480,[{atom,1480,digraph},{atom,1480,graph},[]]}]]},{type,1481,constraint,[{atom,1481,is_subtype},[{var,1481,'Family'},{user_type,1481,family,[]}]]}]]}]}}]}},{{function,family_to_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,1253}],[<<102,97,109,105,108,121,95,116,111,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,99,111,110,116,97,105,110,105,110,103,32,97,108,108,32,112,97,105,114,115,32,40,105,44,194,160,120,41,32,115,117,99,104,32,116,104,97,116,32,105,32,98,101,108,111,110,103,115,32,116,111,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,97,110,100,32,120,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,93,125,44,32,123,98,44,91,49,93,125,44,32,123,99,44,91,50,44,51,93,125,93,41,44,10,82,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,116,111,95,114,101,108,97,116,105,111,110,40,70,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,41,46,10,91,123,98,44,49,125,44,123,99,44,50,125,44,123,99,44,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,54,53>>,signature => [{attribute,1253,spec,{{family_to_relation,1},[{type,1253,bounded_fun,[{type,1253,'fun',[{type,1253,product,[{var,1253,'Family'}]},{var,1253,'BinRel'}]},[{type,1254,constraint,[{atom,1254,is_subtype},[{var,1254,'Family'},{user_type,1254,family,[]}]]},{type,1255,constraint,[{atom,1255,is_subtype},[{var,1255,'BinRel'},{user_type,1255,binary_relation,[]}]]}]]}]}}]}},{{function,family_union,1},[{file,[115,111,102,115,46,101,114,108]},{location,1314}],[<<102,97,109,105,108,121,95,117,110,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,115,101,116,32,111,102,32,115,101,116,115,32,102,111,114,32,101,97,99,104,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,91,49,44,50,93,44,91,50,44,51,93,93,125,44,123,98,44,91,91,93,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,117,110,105,111,110,40,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,93,125,93>>]}]},{p,[],[{code,[],[<<102,97,109,105,108,121,95,117,110,105,111,110,40,70,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,40,102,117,110,32,115,111,102,115,58,117,110,105,111,110,47,49,44,194,160,70,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,56,51>>,signature => [{attribute,1314,spec,{{family_union,1},[{type,1314,bounded_fun,[{type,1314,'fun',[{type,1314,product,[{var,1314,'Family1'}]},{var,1314,'Family2'}]},[{type,1315,constraint,[{atom,1315,is_subtype},[{var,1315,'Family1'},{user_type,1315,family,[]}]]},{type,1316,constraint,[{atom,1316,is_subtype},[{var,1316,'Family2'},{user_type,1316,family,[]}]]}]]}]}}]}},{{function,family_union,2},[{file,[115,111,102,115,46,101,114,108]},{location,1371}],[<<102,97,109,105,108,121,95,117,110,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,105,101,115>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<58,115,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<58,115,32,105,110,100,101,120,32,115,101,116,115,44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<91,105,93,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,102,32,98,111,116,104,32,109,97,112,32,105,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,111,114,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,93,125,44,123,99,44,91,53,44,54,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,98,44,91,52,44,53,93,125,44,123,99,44,91,55,44,56,93,125,44,123,100,44,91,57,44,49,48,93,125,93,41,44,10,70,51,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,117,110,105,111,110,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,51,41,46,10,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,44,53,93,125,44,123,99,44,91,53,44,54,44,55,44,56,93,125,44,123,100,44,91,57,44,49,48,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,48,54>>,signature => [{attribute,1371,spec,{{family_union,2},[{type,1371,bounded_fun,[{type,1371,'fun',[{type,1371,product,[{var,1371,'Family1'},{var,1371,'Family2'}]},{var,1371,'Family3'}]},[{type,1372,constraint,[{atom,1372,is_subtype},[{var,1372,'Family1'},{user_type,1372,family,[]}]]},{type,1373,constraint,[{atom,1373,is_subtype},[{var,1373,'Family2'},{user_type,1373,family,[]}]]},{type,1374,constraint,[{atom,1374,is_subtype},[{var,1374,'Family3'},{user_type,1374,family,[]}]]}]]}]}}]}},{{function,field,1},[{file,[115,111,102,115,46,101,114,108]},{location,632}],[<<102,105,101,108,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,105,101,108,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,101,108,100>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,98,125,44,123,50,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,102,105,101,108,100,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,49,44,50,44,97,44,98,44,99,93>>]}]},{p,[],[{code,[],[<<102,105,101,108,100,40,82,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<117,110,105,111,110,40,100,111,109,97,105,110,40,82,41,44,32,114,97,110,103,101,40,82,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,50,56>>,signature => [{attribute,632,spec,{{field,1},[{type,632,bounded_fun,[{type,632,'fun',[{type,632,product,[{var,632,'BinRel'}]},{var,632,'Set'}]},[{type,633,constraint,[{atom,633,is_subtype},[{var,633,'BinRel'},{user_type,633,binary_relation,[]}]]},{type,634,constraint,[{atom,634,is_subtype},[{var,634,'Set'},{user_type,634,a_set,[]}]]}]]}]}}]}},{{function,from_external,2},[{file,[115,111,102,115,46,101,114,108]},{location,169}],[<<102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,115,101,116,32,102,114,111,109,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32>>,{code,[],[<<69,120,116,101,114,110,97,108,83,101,116>>]},<<32,97,110,100,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32>>,{code,[],[<<84,121,112,101>>]},<<46,32,73,116,32,105,115,32,97,115,115,117,109,101,100,32,116,104,97,116,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,118,97,108,105,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,111,102,32>>,{code,[],[<<69,120,116,101,114,110,97,108,83,101,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,52,52>>,signature => [{attribute,169,spec,{{from_external,2},[{type,169,bounded_fun,[{type,169,'fun',[{type,169,product,[{var,169,'ExternalSet'},{var,169,'Type'}]},{var,169,'AnySet'}]},[{type,170,constraint,[{atom,170,is_subtype},[{var,170,'ExternalSet'},{user_type,170,external_set,[]}]]},{type,171,constraint,[{atom,171,is_subtype},[{var,171,'AnySet'},{user_type,171,anyset,[]}]]},{type,172,constraint,[{atom,172,is_subtype},[{var,172,'Type'},{user_type,172,type,[]}]]}]]}]}}]}},{{function,from_sets,1},[{file,[115,111,102,115,46,101,114,108]},{location,220}],[<<102,114,111,109,95,115,101,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,115,101,116,115,32,111,102,32,108,105,115,116,32>>,{code,[],[<<76,105,115,116,79,102,83,101,116,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,93,41,44,10,83,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,120,44,51,125,44,123,121,44,52,125,93,41,44,10,83,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,91,83,49,44,83,50,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,91,123,97,44,49,125,44,123,98,44,50,125,93,44,91,123,120,44,51,125,44,123,121,44,52,125,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,53,55>>,signature => [{attribute,220,spec,{{from_sets,1},[{type,220,bounded_fun,[{type,220,'fun',[{type,220,product,[{var,220,'ListOfSets'}]},{var,220,'Set'}]},[{type,221,constraint,[{atom,221,is_subtype},[{var,221,'Set'},{user_type,221,a_set,[]}]]},{type,222,constraint,[{atom,222,is_subtype},[{var,222,'ListOfSets'},{type,222,list,[{user_type,222,anyset,[]}]}]]}]]}]}}]}},{{function,from_sets,1},[{file,[115,111,102,115,46,101,114,108]},{location,220}],[<<102,114,111,109,95,115,101,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<111,114,100,101,114,101,100,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,115,101,116,115,32,111,102,32,116,104,101,32,110,111,110,45,101,109,112,116,121,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,79,102,83,101,116,115>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,55,51>>,signature => [{attribute,220,spec,{{from_sets,1},[{type,223,bounded_fun,[{type,223,'fun',[{type,223,product,[{var,223,'TupleOfSets'}]},{var,223,'Ordset'}]},[{type,224,constraint,[{atom,224,is_subtype},[{var,224,'Ordset'},{user_type,224,ordset,[]}]]},{type,225,constraint,[{atom,225,is_subtype},[{var,225,'TupleOfSets'},{user_type,225,tuple_of,[{user_type,225,anyset,[]}]}]]}]]}]}}]}},{{function,from_term,2},[{file,[115,111,102,115,46,101,114,108]},{location,155}],[<<102,114,111,109,95,116,101,114,109,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,56,51>>,equiv => {function,from_term,1},signature => [{attribute,155,spec,{{from_term,2},[{type,155,bounded_fun,[{type,155,'fun',[{type,155,product,[{var,155,'Term'},{var,155,'Type'}]},{var,155,'AnySet'}]},[{type,156,constraint,[{atom,156,is_subtype},[{var,156,'AnySet'},{user_type,156,anyset,[]}]]},{type,157,constraint,[{atom,157,is_subtype},[{var,157,'Term'},{type,157,term,[]}]]},{type,158,constraint,[{atom,158,is_subtype},[{var,158,'Type'},{user_type,158,type,[]}]]}]]}]}}]}},{{function,from_term,1},[{file,[115,111,102,115,46,101,114,108]},{location,143}],[<<102,114,111,109,95,116,101,114,109,47,49>>],#{<<101,110>> => [{p,[],[{a,[{id,<<102,114,111,109,95,116,101,114,109>>}],[]},<<67,114,101,97,116,101,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,101,116,115>>]},<<32,98,121,32,116,114,97,118,101,114,115,105,110,103,32,116,101,114,109,32>>,{code,[],[<<84,101,114,109>>]},<<44,32,115,111,114,116,105,110,103,32,108,105,115,116,115,44,32,114,101,109,111,118,105,110,103,32,100,117,112,108,105,99,97,116,101,115,44,32,97,110,100,32,100,101,114,105,118,105,110,103,32,111,114,32,118,101,114,105,102,121,105,110,103,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,118,97,108,105,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,102,111,114,32,116,104,101,32,115,111,32,111,98,116,97,105,110,101,100,32,101,120,116,101,114,110,97,108,32,115,101,116,46,32,65,110,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32>>,{code,[],[<<84,121,112,101>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,108,105,109,105,116,32,116,104,101,32,100,101,112,116,104,32,111,102,32,116,104,101,32,116,114,97,118,101,114,115,97,108,59,32,97,110,32,97,116,111,109,105,99,32,116,121,112,101,32,115,116,111,112,115,32,116,104,101,32,116,114,97,118,101,114,115,97,108,44,32,97,115,32,115,104,111,119,110,32,98,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,119,104,101,114,101,32>>,{code,[],[<<34,102,111,111,34>>]},<<32,97,110,100,32>>,{code,[],[<<123,34,102,111,111,34,125>>]},<<32,97,114,101,32,108,101,102,116,32,117,110,109,111,100,105,102,105,101,100,58>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,123,34,102,111,111,34,125,44,91,49,44,49,93,125,44,123,34,102,111,111,34,44,91,50,44,50,93,125,93,44,10,91,123,97,116,111,109,44,91,97,116,111,109,93,125,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,123,123,34,102,111,111,34,125,44,91,49,93,125,44,123,34,102,111,111,34,44,91,50,93,125,93>>]}]},{p,[],[{code,[],[<<102,114,111,109,95,116,101,114,109>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,99,114,101,97,116,105,110,103,32,97,116,111,109,105,99,32,111,114,32,111,114,100,101,114,101,100,32,115,101,116,115,46,32,84,104,101,32,111,110,108,121,32,112,117,114,112,111,115,101,32,111,102,32,115,117,99,104,32,97,32,115,101,116,32,105,115,32,116,104,97,116,32,111,102,32,108,97,116,101,114,32,98,117,105,108,100,105,110,103,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,44,32,97,115,32,97,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,32,116,104,97,116,32>>,{em,[],[<<100,111>>]},<<32,97,110,121,116,104,105,110,103,32,111,112,101,114,97,116,101,32,111,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,46,32,67,114,101,97,116,105,110,103,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,32,102,114,111,109,32,97,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,111,114,100,101,114,101,100,32,115,101,116,115,32,99,97,110,32,98,101,32,116,104,101,32,119,97,121,32,116,111,32,103,111,32,105,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,98,105,103,32,97,110,100,32,111,110,101,32,100,111,101,115,32,110,111,116,32,119,97,110,116,32,116,111,32,119,97,115,116,101,32,104,101,97,112,32,98,121,32,114,101,98,117,105,108,100,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,115,104,111,119,115,32,116,104,97,116,32,97,32,115,101,116,32,99,97,110,32,98,101,32,98,117,105,108,116,32,34,108,97,121,101,114,32,98,121,32,108,97,121,101,114,34,58>>]},{pre,[],[{code,[],[<<49,62,32,65,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,97,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,44,51,93,41,44,10,80,49,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,123,65,44,83,125,41,44,10,80,50,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,123,98,44,91,54,44,53,44,52,93,125,41,44,10,83,115,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,91,80,49,44,80,50,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,115,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,52,44,53,44,54,93,125,93>>]}]},{p,[],[<<79,116,104,101,114,32,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,99,114,101,97,116,101,32,115,101,116,115,32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,115,101,116,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,115,101,116,115,47,49>>]}]},<<46,32,83,112,101,99,105,97,108,32,99,97,115,101,115,32,111,102,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,47,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,97,95,102,117,110,99,116,105,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,95,102,117,110,99,116,105,111,110,47,49,44,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,109,112,116,121,95,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,109,112,116,121,95,115,101,116,47,48>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,97,109,105,108,121,47,49,44,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,108,97,116,105,111,110,47,49,44,50>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,101,116,47,49,44,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,56,51>>,signature => [{attribute,143,spec,{{from_term,1},[{type,143,bounded_fun,[{type,143,'fun',[{type,143,product,[{var,143,'Term'}]},{var,143,'AnySet'}]},[{type,144,constraint,[{atom,144,is_subtype},[{var,144,'AnySet'},{user_type,144,anyset,[]}]]},{type,145,constraint,[{atom,145,is_subtype},[{var,145,'Term'},{type,145,term,[]}]]}]]}]}}]}},{{function,image,2},[{file,[115,111,102,115,46,101,114,108]},{location,717}],[<<105,109,97,103,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,109,97,103,101>>]},<<32,111,102,32,115,101,116,32>>,{code,[],[<<83,101,116,49>>]},<<32,117,110,100,101,114,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,50,44,99,125,44,123,51,44,100,125,93,41,44,10,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,93,41,44,10,83,50,32,61,32,115,111,102,115,58,105,109,97,103,101,40,82,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,97,44,98,44,99,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,51,51>>,signature => [{attribute,717,spec,{{image,2},[{type,717,bounded_fun,[{type,717,'fun',[{type,717,product,[{var,717,'BinRel'},{var,717,'Set1'}]},{var,717,'Set2'}]},[{type,718,constraint,[{atom,718,is_subtype},[{var,718,'BinRel'},{user_type,718,binary_relation,[]}]]},{type,719,constraint,[{atom,719,is_subtype},[{var,719,'Set1'},{user_type,719,a_set,[]}]]},{type,720,constraint,[{atom,720,is_subtype},[{var,720,'Set2'},{user_type,720,a_set,[]}]]}]]}]}}]}},{{function,intersection,1},[{file,[115,111,102,115,46,101,114,108]},{location,563}],[<<105,110,116,101,114,115,101,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,116,101,114,115,101,99,116,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,115,101,116,115,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<46>>]},{p,[],[<<73,110,116,101,114,115,101,99,116,105,110,103,32,97,110,32,101,109,112,116,121,32,115,101,116,32,111,102,32,115,101,116,115,32,101,120,105,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,109,101,115,115,97,103,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,52,57>>,signature => [{attribute,563,spec,{{intersection,1},[{type,563,bounded_fun,[{type,563,'fun',[{type,563,product,[{var,563,'SetOfSets'}]},{var,563,'Set'}]},[{type,564,constraint,[{atom,564,is_subtype},[{var,564,'Set'},{user_type,564,a_set,[]}]]},{type,565,constraint,[{atom,565,is_subtype},[{var,565,'SetOfSets'},{user_type,565,set_of_sets,[]}]]}]]}]}}]}},{{function,intersection,2},[{file,[115,111,102,115,46,101,114,108]},{location,388}],[<<105,110,116,101,114,115,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,116,101,114,115,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,54,49>>,signature => [{attribute,388,spec,{{intersection,2},[{type,388,bounded_fun,[{type,388,'fun',[{type,388,product,[{var,388,'Set1'},{var,388,'Set2'}]},{var,388,'Set3'}]},[{type,389,constraint,[{atom,389,is_subtype},[{var,389,'Set1'},{user_type,389,a_set,[]}]]},{type,390,constraint,[{atom,390,is_subtype},[{var,390,'Set2'},{user_type,390,a_set,[]}]]},{type,391,constraint,[{atom,391,is_subtype},[{var,391,'Set3'},{user_type,391,a_set,[]}]]}]]}]}}]}},{{function,intersection_of_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,1299}],[<<105,110,116,101,114,115,101,99,116,105,111,110,95,111,102,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<46>>]},{p,[],[<<73,110,116,101,114,115,101,99,116,105,110,103,32,97,110,32,101,109,112,116,121,32,102,97,109,105,108,121,32,101,120,105,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,109,101,115,115,97,103,101,46>>]},{pre,[],[{code,[],[<<49,62,32,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,48,44,50,44,52,93,125,44,123,98,44,91,48,44,49,44,50,93,125,44,123,99,44,91,50,44,51,93,125,93,41,44,10,83,32,61,32,115,111,102,115,58,105,110,116,101,114,115,101,99,116,105,111,110,95,111,102,95,102,97,109,105,108,121,40,70,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,50,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,55,49>>,signature => [{attribute,1299,spec,{{intersection_of_family,1},[{type,1299,bounded_fun,[{type,1299,'fun',[{type,1299,product,[{var,1299,'Family'}]},{var,1299,'Set'}]},[{type,1300,constraint,[{atom,1300,is_subtype},[{var,1300,'Family'},{user_type,1300,family,[]}]]},{type,1301,constraint,[{atom,1301,is_subtype},[{var,1301,'Set'},{user_type,1301,a_set,[]}]]}]]}]}}]}},{{function,inverse,1},[{file,[115,111,102,115,46,101,114,108]},{location,872}],[<<105,110,118,101,114,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,118,101,114,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,118,101,114,115,101>>]},<<32,111,102,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<70,117,110,99,116,105,111,110,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,105,110,118,101,114,115,101,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,97,44,49,125,44,123,98,44,50,125,44,123,99,44,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,56,56>>,signature => [{attribute,872,spec,{{inverse,1},[{type,872,bounded_fun,[{type,872,'fun',[{type,872,product,[{var,872,'Function1'}]},{var,872,'Function2'}]},[{type,873,constraint,[{atom,873,is_subtype},[{var,873,'Function1'},{user_type,873,a_function,[]}]]},{type,874,constraint,[{atom,874,is_subtype},[{var,874,'Function2'},{user_type,874,a_function,[]}]]}]]}]}}]}},{{function,inverse_image,2},[{file,[115,111,102,115,46,101,114,108]},{location,734}],[<<105,110,118,101,114,115,101,95,105,109,97,103,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,118,101,114,115,101,95,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,118,101,114,115,101,32,105,109,97,103,101>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,117,110,100,101,114,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,50,44,99,125,44,123,51,44,100,125,93,41,44,10,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,99,44,100,44,101,93,41,44,10,83,50,32,61,32,115,111,102,115,58,105,110,118,101,114,115,101,95,105,109,97,103,101,40,82,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,50,44,51,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,48,50>>,signature => [{attribute,734,spec,{{inverse_image,2},[{type,734,bounded_fun,[{type,734,'fun',[{type,734,product,[{var,734,'BinRel'},{var,734,'Set1'}]},{var,734,'Set2'}]},[{type,735,constraint,[{atom,735,is_subtype},[{var,735,'BinRel'},{user_type,735,binary_relation,[]}]]},{type,736,constraint,[{atom,736,is_subtype},[{var,736,'Set1'},{user_type,736,a_set,[]}]]},{type,737,constraint,[{atom,737,is_subtype},[{var,737,'Set2'},{user_type,737,a_set,[]}]]}]]}]}}]}},{{function,is_a_function,1},[{file,[115,111,102,115,46,101,114,108]},{location,812}],[<<105,115,95,97,95,102,117,110,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<32,111,114,32,116,104,101,32,117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,49,57>>,signature => [{attribute,812,spec,{{is_a_function,1},[{type,812,bounded_fun,[{type,812,'fun',[{type,812,product,[{var,812,'BinRel'}]},{var,812,'Bool'}]},[{type,813,constraint,[{atom,813,is_subtype},[{var,813,'Bool'},{type,813,boolean,[]}]]},{type,814,constraint,[{atom,814,is_subtype},[{var,814,'BinRel'},{user_type,814,binary_relation,[]}]]}]]}]}}]}},{{function,is_disjoint,2},[{file,[115,111,102,115,46,101,114,108]},{location,535}],[<<105,115,95,100,105,115,106,111,105,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,105,115,106,111,105,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,115,106,111,105,110,116>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,50,57>>,signature => [{attribute,535,spec,{{is_disjoint,2},[{type,535,bounded_fun,[{type,535,'fun',[{type,535,product,[{var,535,'Set1'},{var,535,'Set2'}]},{var,535,'Bool'}]},[{type,536,constraint,[{atom,536,is_subtype},[{var,536,'Bool'},{type,536,boolean,[]}]]},{type,537,constraint,[{atom,537,is_subtype},[{var,537,'Set1'},{user_type,537,a_set,[]}]]},{type,538,constraint,[{atom,538,is_subtype},[{var,538,'Set2'},{user_type,538,a_set,[]}]]}]]}]}}]}},{{function,is_empty_set,1},[{file,[115,111,102,115,46,101,114,108]},{location,527}],[<<105,115,95,101,109,112,116,121,95,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<32,105,115,32,97,110,32,101,109,112,116,121,32,117,110,111,114,100,101,114,101,100,32,115,101,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,52,48>>,signature => [{attribute,527,spec,{{is_empty_set,1},[{type,527,bounded_fun,[{type,527,'fun',[{type,527,product,[{var,527,'AnySet'}]},{var,527,'Bool'}]},[{type,528,constraint,[{atom,528,is_subtype},[{var,528,'AnySet'},{user_type,528,anyset,[]}]]},{type,529,constraint,[{atom,529,is_subtype},[{var,529,'Bool'},{type,529,boolean,[]}]]}]]}]}}]}},{{function,is_equal,2},[{file,[115,111,102,115,46,101,114,108]},{location,480}],[<<105,115,95,101,113,117,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<65,110,121,83,101,116,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,113,117,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,113,117,97,108>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,115,104,111,119,115,32,116,104,97,116,32>>,{code,[],[<<61,61,47,50>>]},<<32,105,115,32,117,115,101,100,32,119,104,101,110,32,99,111,109,112,97,114,105,110,103,32,115,101,116,115,32,102,111,114,32,101,113,117,97,108,105,116,121,58>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,46,48,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,49,93,41,44,10,115,111,102,115,58,105,115,95,101,113,117,97,108,40,83,49,44,32,83,50,41,46,10,116,114,117,101>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,52,57>>,signature => [{attribute,480,spec,{{is_equal,2},[{type,480,bounded_fun,[{type,480,'fun',[{type,480,product,[{var,480,'AnySet1'},{var,480,'AnySet2'}]},{var,480,'Bool'}]},[{type,481,constraint,[{atom,481,is_subtype},[{var,481,'AnySet1'},{user_type,481,anyset,[]}]]},{type,482,constraint,[{atom,482,is_subtype},[{var,482,'AnySet2'},{user_type,482,anyset,[]}]]},{type,483,constraint,[{atom,483,is_subtype},[{var,483,'Bool'},{type,483,boolean,[]}]]}]]}]}}]}},{{function,is_set,1},[{file,[115,111,102,115,46,101,114,108]},{location,519}],[<<105,115,95,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<32,105,115,32,97,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<32,105,115,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,32,111,114,32,97,110,32,97,116,111,109,105,99,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,54,54>>,signature => [{attribute,519,spec,{{is_set,1},[{type,519,bounded_fun,[{type,519,'fun',[{type,519,product,[{var,519,'AnySet'}]},{var,519,'Bool'}]},[{type,520,constraint,[{atom,520,is_subtype},[{var,520,'AnySet'},{user_type,520,anyset,[]}]]},{type,521,constraint,[{atom,521,is_subtype},[{var,521,'Bool'},{type,521,boolean,[]}]]}]]}]}}]}},{{function,is_sofs_set,1},[{file,[115,111,102,115,46,101,114,108]},{location,509}],[<<105,115,95,115,111,102,115,95,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<44,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,44,32,111,114,32,97,110,32,97,116,111,109,105,99,32,115,101,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,55,55>>,signature => [{attribute,509,spec,{{is_sofs_set,1},[{type,509,bounded_fun,[{type,509,'fun',[{type,509,product,[{var,509,'Term'}]},{var,509,'Bool'}]},[{type,510,constraint,[{atom,510,is_subtype},[{var,510,'Bool'},{type,510,boolean,[]}]]},{type,511,constraint,[{atom,511,is_subtype},[{var,511,'Term'},{type,511,term,[]}]]}]]}]}}]}},{{function,is_subset,2},[{file,[115,111,102,115,46,101,114,108]},{location,499}],[<<105,115,95,115,117,98,115,101,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,117,98,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,117,98,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,50>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,56,55>>,signature => [{attribute,499,spec,{{is_subset,2},[{type,499,bounded_fun,[{type,499,'fun',[{type,499,product,[{var,499,'Set1'},{var,499,'Set2'}]},{var,499,'Bool'}]},[{type,500,constraint,[{atom,500,is_subtype},[{var,500,'Bool'},{type,500,boolean,[]}]]},{type,501,constraint,[{atom,501,is_subtype},[{var,501,'Set1'},{user_type,501,a_set,[]}]]},{type,502,constraint,[{atom,502,is_subtype},[{var,502,'Set2'},{user_type,502,a_set,[]}]]}]]}]}}]}},{{function,is_type,1},[{file,[115,111,102,115,46,101,114,108]},{location,183}],[<<105,115,95,116,121,112,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,101,114,109,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,57,55>>,signature => [{attribute,183,spec,{{is_type,1},[{type,183,bounded_fun,[{type,183,'fun',[{type,183,product,[{var,183,'Term'}]},{var,183,'Bool'}]},[{type,184,constraint,[{atom,184,is_subtype},[{var,184,'Bool'},{type,184,boolean,[]}]]},{type,185,constraint,[{atom,185,is_subtype},[{var,185,'Term'},{type,185,term,[]}]]}]]}]}}]}},{{function,join,4},[{file,[115,111,102,115,46,101,114,108]},{location,1206}],[<<106,111,105,110,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,110,97,116,117,114,97,108,95,106,111,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,97,116,117,114,97,108,32,106,111,105,110>>]},<<32,111,102,32,116,104,101,32,114,101,108,97,116,105,111,110,115,32>>,{code,[],[<<82,101,108,97,116,105,111,110,49>>]},<<32,97,110,100,32>>,{code,[],[<<82,101,108,97,116,105,111,110,50>>]},<<32,111,110,32,99,111,111,114,100,105,110,97,116,101,115,32>>,{code,[],[<<73>>]},<<32,97,110,100,32>>,{code,[],[<<74>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,120,44,49,125,44,123,98,44,121,44,50,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,102,44,103,125,44,123,49,44,104,44,105,125,44,123,50,44,51,44,52,125,93,41,44,10,74,32,61,32,115,111,102,115,58,106,111,105,110,40,82,49,44,32,51,44,32,82,50,44,32,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,74,41,46,10,91,123,97,44,120,44,49,44,102,44,103,125,44,123,97,44,120,44,49,44,104,44,105,125,44,123,98,44,121,44,50,44,51,44,52,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,48,54>>,signature => [{attribute,1206,spec,{{join,4},[{type,1206,bounded_fun,[{type,1206,'fun',[{type,1206,product,[{var,1206,'Relation1'},{var,1206,'I'},{var,1206,'Relation2'},{var,1206,'J'}]},{var,1206,'Relation3'}]},[{type,1207,constraint,[{atom,1207,is_subtype},[{var,1207,'Relation1'},{user_type,1207,relation,[]}]]},{type,1208,constraint,[{atom,1208,is_subtype},[{var,1208,'Relation2'},{user_type,1208,relation,[]}]]},{type,1209,constraint,[{atom,1209,is_subtype},[{var,1209,'Relation3'},{user_type,1209,relation,[]}]]},{type,1210,constraint,[{atom,1210,is_subtype},[{var,1210,'I'},{type,1210,pos_integer,[]}]]},{type,1211,constraint,[{atom,1211,is_subtype},[{var,1211,'J'},{type,1211,pos_integer,[]}]]}]]}]}}]}},{{function,multiple_relative_product,2},[{file,[115,111,102,115,46,101,114,108]},{location,1190}],[<<109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<84,117,112,108,101,79,102,66,105,110,82,101,108,115>>]},<<32,105,115,32,97,32,110,111,110,45,101,109,112,116,121,32,116,117,112,108,101,32,123,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,125,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,44,32,116,104,101,110,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,117,108,116,105,112,108,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,105,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,105,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,44,123,99,44,51,125,93,41,44,10,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,98,125,44,123,98,44,99,125,44,123,99,44,97,125,93,41,44,10,77,80,32,61,32,115,111,102,115,58,109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,123,82,105,44,32,82,105,125,44,32,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,114,97,110,103,101,40,77,80,41,41,46,10,91,123,49,44,50,125,44,123,50,44,51,125,44,123,51,44,49,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,50,51>>,signature => [{attribute,1190,spec,{{multiple_relative_product,2},[{type,1190,bounded_fun,[{type,1190,'fun',[{type,1190,product,[{var,1190,'TupleOfBinRels'},{var,1190,'BinRel1'}]},{var,1190,'BinRel2'}]},[{type,1191,constraint,[{atom,1191,is_subtype},[{var,1191,'TupleOfBinRels'},{user_type,1191,tuple_of,[{var,1191,'BinRel'}]}]]},{type,1192,constraint,[{atom,1192,is_subtype},[{var,1192,'BinRel'},{user_type,1192,binary_relation,[]}]]},{type,1193,constraint,[{atom,1193,is_subtype},[{var,1193,'BinRel1'},{user_type,1193,binary_relation,[]}]]},{type,1194,constraint,[{atom,1194,is_subtype},[{var,1194,'BinRel2'},{user_type,1194,binary_relation,[]}]]}]]}]}}]}},{{function,no_elements,1},[{file,[115,111,102,115,46,101,114,108]},{location,349}],[<<110,111,95,101,108,101,109,101,110,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,111,114,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32>>,{code,[],[<<65,83,101,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,52,52>>,signature => [{attribute,349,spec,{{no_elements,1},[{type,349,bounded_fun,[{type,349,'fun',[{type,349,product,[{var,349,'ASet'}]},{var,349,'NoElements'}]},[{type,350,constraint,[{atom,350,is_subtype},[{var,350,'ASet'},{type,350,union,[{user_type,350,a_set,[]},{user_type,350,ordset,[]}]}]]},{type,351,constraint,[{atom,351,is_subtype},[{var,351,'NoElements'},{type,351,non_neg_integer,[]}]]}]]}]}}]}},{{function,partition,1},[{file,[115,111,102,115,46,101,114,108]},{location,1091}],[<<112,97,114,116,105,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32,116,104,101,32,117,110,105,111,110,32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,115,101,116,115,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,119,111,32,101,108,101,109,101,110,116,115,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,101,113,117,97,108,32,105,102,32,116,104,101,121,32,98,101,108,111,110,103,32,116,111,32,116,104,101,32,115,97,109,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,101,116,115,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,97,44,98,44,99,93,44,91,100,44,101,44,102,93,44,91,103,44,104,44,105,93,93,41,44,10,83,101,116,115,50,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,98,44,99,44,100,93,44,91,101,44,102,44,103,93,44,91,104,44,105,44,106,93,93,41,44,10,80,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,115,111,102,115,58,117,110,105,111,110,40,83,101,116,115,49,44,32,83,101,116,115,50,41,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,41,46,10,91,91,97,93,44,91,98,44,99,93,44,91,100,93,44,91,101,44,102,93,44,91,103,93,44,91,104,44,105,93,44,91,106,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,53,51>>,signature => [{attribute,1091,spec,{{partition,1},[{type,1091,bounded_fun,[{type,1091,'fun',[{type,1091,product,[{var,1091,'SetOfSets'}]},{var,1091,'Partition'}]},[{type,1092,constraint,[{atom,1092,is_subtype},[{var,1092,'SetOfSets'},{user_type,1092,set_of_sets,[]}]]},{type,1093,constraint,[{atom,1093,is_subtype},[{var,1093,'Partition'},{user_type,1093,a_set,[]}]]}]]}]}}]}},{{function,partition,2},[{file,[115,111,102,115,46,101,114,108]},{location,1099}],[<<112,97,114,116,105,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,119,111,32,101,108,101,109,101,110,116,115,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,101,113,117,97,108,32,105,102,32,116,104,101,32,114,101,115,117,108,116,115,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,97,114,101,32,101,113,117,97,108,46>>]},{pre,[],[{code,[],[<<49,62,32,83,115,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,97,93,44,91,98,93,44,91,99,44,100,93,44,91,101,44,102,93,93,41,44,10,83,101,116,70,117,110,32,61,32,102,117,110,40,83,41,32,45,62,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,115,111,102,115,58,110,111,95,101,108,101,109,101,110,116,115,40,83,41,41,32,101,110,100,44,10,80,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,83,101,116,70,117,110,44,32,83,115,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,41,46,10,91,91,91,97,93,44,91,98,93,93,44,91,91,99,44,100,93,44,91,101,44,102,93,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,55,48>>,signature => [{attribute,1099,spec,{{partition,2},[{type,1099,bounded_fun,[{type,1099,'fun',[{type,1099,product,[{var,1099,'SetFun'},{var,1099,'Set'}]},{var,1099,'Partition'}]},[{type,1100,constraint,[{atom,1100,is_subtype},[{var,1100,'SetFun'},{user_type,1100,set_fun,[]}]]},{type,1101,constraint,[{atom,1101,is_subtype},[{var,1101,'Partition'},{user_type,1101,a_set,[]}]]},{type,1102,constraint,[{atom,1102,is_subtype},[{var,1102,'Set'},{user_type,1102,a_set,[]}]]}]]}]}}]}},{{function,partition,3},[{file,[115,111,102,115,46,101,114,108]},{location,1118}],[<<112,97,114,116,105,116,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,97,105,114,32,111,102,32,115,101,116,115,32,116,104,97,116,44,32,114,101,103,97,114,100,101,100,32,97,115,32,99,111,110,115,116,105,116,117,116,105,110,103,32,97,32,115,101,116,44,32,102,111,114,109,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<46,32,73,102,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,116,111,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,103,105,118,101,115,32,97,110,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<83,101,116,50>>]},<<44,32,116,104,101,32,101,108,101,109,101,110,116,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<83,101,116,51>>]},<<44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,101,108,101,109,101,110,116,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<83,101,116,52>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,50,44,52,44,54,93,41,44,10,123,82,50,44,82,51,125,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,49,44,32,82,49,44,32,83,41,44,10,123,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,44,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,51,41,125,46,10,123,91,123,50,44,98,125,93,44,91,123,49,44,97,125,44,123,51,44,99,125,93,125>>]}]},{p,[],[{code,[],[<<112,97,114,116,105,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<123,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41,44,32,100,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41,125>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,56,54>>,signature => [{attribute,1118,spec,{{partition,3},[{type,1118,bounded_fun,[{type,1118,'fun',[{type,1118,product,[{var,1118,'SetFun'},{var,1118,'Set1'},{var,1118,'Set2'}]},{type,1118,tuple,[{var,1118,'Set3'},{var,1118,'Set4'}]}]},[{type,1119,constraint,[{atom,1119,is_subtype},[{var,1119,'SetFun'},{user_type,1119,set_fun,[]}]]},{type,1120,constraint,[{atom,1120,is_subtype},[{var,1120,'Set1'},{user_type,1120,a_set,[]}]]},{type,1121,constraint,[{atom,1121,is_subtype},[{var,1121,'Set2'},{user_type,1121,a_set,[]}]]},{type,1122,constraint,[{atom,1122,is_subtype},[{var,1122,'Set3'},{user_type,1122,a_set,[]}]]},{type,1123,constraint,[{atom,1123,is_subtype},[{var,1123,'Set4'},{user_type,1123,a_set,[]}]]}]]}]}}]}},{{function,partition_family,2},[{file,[115,111,102,115,46,101,114,108]},{location,1404}],[<<112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,119,104,101,114,101,32,116,104,101,32,105,110,100,101,120,101,100,32,115,101,116,32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,119,111,32,101,108,101,109,101,110,116,115,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,101,113,117,97,108,32,105,102,32,116,104,101,32,114,101,115,117,108,116,115,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,105,46,32,84,104,105,115,32,105,32,105,115,32,116,104,101,32,105,110,100,101,120,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,109,97,112,115,32,111,110,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,113,117,105,118,97,108,101,110,99,101,95,99,108,97,115,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,97,44,97,44,97,125,44,123,97,44,97,44,98,44,98,125,44,123,97,44,98,44,98,44,98,125,93,41,44,10,83,101,116,70,117,110,32,61,32,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,65,44,95,44,67,44,95,125,41,32,45,62,32,123,65,44,67,125,32,101,110,100,125,44,10,70,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,40,83,101,116,70,117,110,44,32,83,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,123,97,44,97,125,44,91,123,97,44,97,44,97,44,97,125,93,125,44,123,123,97,44,98,125,44,91,123,97,44,97,44,98,44,98,125,44,123,97,44,98,44,98,44,98,125,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,48,57>>,signature => [{attribute,1404,spec,{{partition_family,2},[{type,1404,bounded_fun,[{type,1404,'fun',[{type,1404,product,[{var,1404,'SetFun'},{var,1404,'Set'}]},{var,1404,'Family'}]},[{type,1405,constraint,[{atom,1405,is_subtype},[{var,1405,'Family'},{user_type,1405,family,[]}]]},{type,1406,constraint,[{atom,1406,is_subtype},[{var,1406,'SetFun'},{user_type,1406,set_fun,[]}]]},{type,1407,constraint,[{atom,1407,is_subtype},[{var,1407,'Set'},{user_type,1407,a_set,[]}]]}]]}]}}]}},{{function,product,1},[{file,[115,111,102,115,46,101,114,108]},{location,444}],[<<112,114,111,100,117,99,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116,95,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,110,111,110,45,101,109,112,116,121,32,116,117,112,108,101,32,111,102,32,115,101,116,115,32>>,{code,[],[<<84,117,112,108,101,79,102,83,101,116,115>>]},<<46,32,73,102,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<82,101,108,97,116,105,111,110>>]},<<44,32,116,104,101,110,32,120,91,105,93,32,105,115,32,100,114,97,119,110,32,102,114,111,109,32,101,108,101,109,101,110,116,32,105,32,111,102,32>>,{code,[],[<<84,117,112,108,101,79,102,83,101,116,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,97,44,98,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,93,41,44,10,83,51,32,61,32,115,111,102,115,58,115,101,116,40,91,120,44,121,93,41,44,10,80,51,32,61,32,115,111,102,115,58,112,114,111,100,117,99,116,40,123,83,49,44,83,50,44,83,51,125,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,51,41,46,10,91,123,97,44,49,44,120,125,44,123,97,44,49,44,121,125,44,123,97,44,50,44,120,125,44,123,97,44,50,44,121,125,44,123,98,44,49,44,120,125,44,123,98,44,49,44,121,125,44,123,98,44,50,44,120,125,44,123,98,44,50,44,121,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,51,48>>,signature => [{attribute,444,spec,{{product,1},[{type,444,bounded_fun,[{type,444,'fun',[{type,444,product,[{var,444,'TupleOfSets'}]},{var,444,'Relation'}]},[{type,445,constraint,[{atom,445,is_subtype},[{var,445,'Relation'},{user_type,445,relation,[]}]]},{type,446,constraint,[{atom,446,is_subtype},[{var,446,'TupleOfSets'},{user_type,446,tuple_of,[{user_type,446,a_set,[]}]}]]}]]}]}}]}},{{function,product,2},[{file,[115,111,102,115,46,101,114,108]},{location,430}],[<<112,114,111,100,117,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,97,44,98,93,41,44,10,82,32,61,32,115,111,102,115,58,112,114,111,100,117,99,116,40,83,49,44,32,83,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,41,46,10,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,97,125,44,123,50,44,98,125,93>>]}]},{p,[],[{code,[],[<<112,114,111,100,117,99,116,40,83,49,44,194,160,83,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<112,114,111,100,117,99,116,40,123,83,49,44,194,160,83,50,125,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,52,57>>,signature => [{attribute,430,spec,{{product,2},[{type,430,bounded_fun,[{type,430,'fun',[{type,430,product,[{var,430,'Set1'},{var,430,'Set2'}]},{var,430,'BinRel'}]},[{type,431,constraint,[{atom,431,is_subtype},[{var,431,'BinRel'},{user_type,431,binary_relation,[]}]]},{type,432,constraint,[{atom,432,is_subtype},[{var,432,'Set1'},{user_type,432,a_set,[]}]]},{type,433,constraint,[{atom,433,is_subtype},[{var,433,'Set2'},{user_type,433,a_set,[]}]]}]]}]}}]}},{{function,projection,2},[{file,[115,111,102,115,46,101,114,108]},{location,1029}],[<<112,114,111,106,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,101,116,32,99,114,101,97,116,101,100,32,98,121,32,115,117,98,115,116,105,116,117,116,105,110,103,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,98,121,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,116,111,32,116,104,101,32,101,108,101,109,101,110,116,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,105,115,32,97,32,110,117,109,98,101,114,32,105,194,160,62,61,194,160,49,32,97,110,100,32>>,{code,[],[<<83,101,116,49>>]},<<32,105,115,32,97,32,114,101,108,97,116,105,111,110,44,32,116,104,101,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,115,101,116,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,114,111,106,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,114,111,106,101,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,111,110,116,111,32,99,111,111,114,100,105,110,97,116,101,32,105,46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,97,125,93,41,44,10,83,50,32,61,32,115,111,102,115,58,112,114,111,106,101,99,116,105,111,110,40,50,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,97,44,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,54,55>>,signature => [{attribute,1029,spec,{{projection,2},[{type,1029,bounded_fun,[{type,1029,'fun',[{type,1029,product,[{var,1029,'SetFun'},{var,1029,'Set1'}]},{var,1029,'Set2'}]},[{type,1030,constraint,[{atom,1030,is_subtype},[{var,1030,'SetFun'},{user_type,1030,set_fun,[]}]]},{type,1031,constraint,[{atom,1031,is_subtype},[{var,1031,'Set1'},{user_type,1031,a_set,[]}]]},{type,1032,constraint,[{atom,1032,is_subtype},[{var,1032,'Set2'},{user_type,1032,a_set,[]}]]}]]}]}}]}},{{function,range,1},[{file,[115,111,102,115,46,101,114,108]},{location,622}],[<<114,97,110,103,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,97,110,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,97,110,103,101>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,98,125,44,123,50,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,114,97,110,103,101,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,97,44,98,44,99,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,56,54>>,signature => [{attribute,622,spec,{{range,1},[{type,622,bounded_fun,[{type,622,'fun',[{type,622,product,[{var,622,'BinRel'}]},{var,622,'Set'}]},[{type,623,constraint,[{atom,623,is_subtype},[{var,623,'BinRel'},{user_type,623,binary_relation,[]}]]},{type,624,constraint,[{atom,624,is_subtype},[{var,624,'Set'},{user_type,624,a_set,[]}]]}]]}]}}]}},{{function,relation,2},[{file,[115,111,102,115,46,101,114,108]},{location,255}],[<<114,101,108,97,116,105,111,110,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,48,48>>,equiv => {function,relation,1},signature => [{attribute,255,spec,{{relation,2},[{type,255,bounded_fun,[{type,255,'fun',[{type,255,product,[{var,255,'Tuples'},{var,255,'Type'}]},{var,255,'Relation'}]},[{type,256,constraint,[{atom,256,is_subtype},[{var,256,'N'},{type,256,integer,[]}]]},{type,257,constraint,[{atom,257,is_subtype},[{var,257,'Type'},{type,257,union,[{var,257,'N'},{user_type,257,type,[]}]}]]},{type,258,constraint,[{atom,258,is_subtype},[{var,258,'Relation'},{user_type,258,relation,[]}]]},{type,259,constraint,[{atom,259,is_subtype},[{var,259,'Tuples'},{type,259,list,[{type,259,tuple,any}]}]]}]]}]}}]}},{{function,relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,243}],[<<114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,111,110>>]},<<46,32>>,{code,[],[<<114,101,108,97,116,105,111,110,40,82,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,82,44,194,160,84,41>>]},<<44,32,105,102,32,84,32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,97,110,100,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,114,101,108,97,116,105,111,110,46,32,73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,78,44,32,116,104,101,110,32>>,{code,[],[<<91,123,97,116,111,109,44,194,160,46,46,46,44,194,160,97,116,111,109,125,93,41>>]},<<44,32,119,104,101,114,101,32,116,104,101,32,116,117,112,108,101,32,115,105,122,101,32,105,115,32,78,44,32,105,115,32,117,115,101,100,32,97,115,32,116,121,112,101,32,111,102,32,116,104,101,32,114,101,108,97,116,105,111,110,46,32,73,102,32,110,111,32,116,121,112,101,32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,102,105,114,115,116,32,116,117,112,108,101,32,111,102,32>>,{code,[],[<<84,117,112,108,101,115>>]},<<32,105,115,32,117,115,101,100,32,105,102,32,116,104,101,114,101,32,105,115,32,115,117,99,104,32,97,32,116,117,112,108,101,46,32>>,{code,[],[<<114,101,108,97,116,105,111,110,40,91,93,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<114,101,108,97,116,105,111,110,40,91,93,44,194,160,50,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,48,48>>,signature => [{attribute,243,spec,{{relation,1},[{type,243,bounded_fun,[{type,243,'fun',[{type,243,product,[{var,243,'Tuples'}]},{var,243,'Relation'}]},[{type,244,constraint,[{atom,244,is_subtype},[{var,244,'Relation'},{user_type,244,relation,[]}]]},{type,245,constraint,[{atom,245,is_subtype},[{var,245,'Tuples'},{type,245,list,[{type,245,tuple,any}]}]]}]]}]}}]}},{{function,relation_to_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,600}],[<<114,101,108,97,116,105,111,110,95,116,111,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,101,113,117,97,108,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,109,97,103,101>>]},<<32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,105,32,117,110,100,101,114,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,98,44,49,125,44,123,99,44,50,125,44,123,99,44,51,125,93,41,44,10,70,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,95,116,111,95,102,97,109,105,108,121,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,98,44,91,49,93,125,44,123,99,44,91,50,44,51,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,49,57>>,signature => [{attribute,600,spec,{{relation_to_family,1},[{type,600,bounded_fun,[{type,600,'fun',[{type,600,product,[{var,600,'BinRel'}]},{var,600,'Family'}]},[{type,601,constraint,[{atom,601,is_subtype},[{var,601,'Family'},{user_type,601,family,[]}]]},{type,602,constraint,[{atom,602,is_subtype},[{var,602,'BinRel'},{user_type,602,binary_relation,[]}]]}]]}]}}]}},{{function,relative_product,2},[{file,[115,111,102,115,46,101,114,108]},{location,657}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,51,55>>,equiv => {function,relative_product,1},signature => [{attribute,657,spec,{{relative_product,2},[{type,657,bounded_fun,[{type,657,'fun',[{type,657,product,[{var,657,'ListOfBinRels'},{var,657,'BinRel1'}]},{var,657,'BinRel2'}]},[{type,658,constraint,[{atom,658,is_subtype},[{var,658,'ListOfBinRels'},{type,658,nonempty_list,[{var,658,'BinRel'}]}]]},{type,659,constraint,[{atom,659,is_subtype},[{var,659,'BinRel'},{user_type,659,binary_relation,[]}]]},{type,660,constraint,[{atom,660,is_subtype},[{var,660,'BinRel1'},{user_type,660,binary_relation,[]}]]},{type,661,constraint,[{atom,661,is_subtype},[{var,661,'BinRel2'},{user_type,661,binary_relation,[]}]]}]]}]}}]}},{{function,relative_product,1},[{file,[115,111,102,115,46,101,114,108]},{location,641}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<76,105,115,116,79,102,66,105,110,82,101,108,115>>]},<<32,105,115,32,97,32,110,111,110,45,101,109,112,116,121,32,108,105,115,116,32,91,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,93,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,44,32,116,104,101,110,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,117,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,105,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,105,115,32,111,109,105,116,116,101,100,44,32,116,104,101,32,114,101,108,97,116,105,111,110,32,111,102,32,101,113,117,97,108,105,116,121,32,98,101,116,119,101,101,110,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116,95,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,114,97,110,103,101,115,32,111,102,32,82,91,105,93,44,32,114,97,110,103,101,194,160,82,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,114,97,110,103,101,194,160,82,91,110,93,44,32,105,115,32,117,115,101,100,32,105,110,115,116,101,97,100,32,40,105,110,116,117,105,116,105,118,101,108,121,44,32,110,111,116,104,105,110,103,32,105,115,32,34,108,111,115,116,34,41,46>>]},{pre,[],[{code,[],[<<49,62,32,84,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,97,97,125,44,123,50,44,98,125,93,41,44,10,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,117,125,44,123,50,44,118,125,44,123,51,44,99,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,91,84,82,44,32,82,49,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,123,97,44,117,125,125,44,123,49,44,123,97,97,44,117,125,125,44,123,50,44,123,98,44,118,125,125,93>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,91,82,49,93,44,194,160,82,50,41>>]},<<32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32>>,{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,82,49,44,194,160,82,50,41>>]},<<59,32,116,104,101,32,108,105,115,116,32,111,102,32,111,110,101,32,101,108,101,109,101,110,116,32,105,115,32,110,111,116,32,105,100,101,110,116,105,102,105,101,100,32,119,105,116,104,32,116,104,101,32,101,108,101,109,101,110,116,32,105,116,115,101,108,102,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,51,55>>,signature => [{attribute,641,spec,{{relative_product,1},[{type,641,bounded_fun,[{type,641,'fun',[{type,641,product,[{var,641,'ListOfBinRels'}]},{var,641,'BinRel2'}]},[{type,642,constraint,[{atom,642,is_subtype},[{var,642,'ListOfBinRels'},{type,642,nonempty_list,[{var,642,'BinRel'}]}]]},{type,643,constraint,[{atom,643,is_subtype},[{var,643,'BinRel'},{user_type,643,binary_relation,[]}]]},{type,644,constraint,[{atom,644,is_subtype},[{var,644,'BinRel2'},{user_type,644,binary_relation,[]}]]}]]}]}}]}},{{function,relative_product,2},[{file,[115,111,102,115,46,101,114,108]},{location,657}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,54,56>>,signature => [{attribute,657,spec,{{relative_product,2},[{type,662,bounded_fun,[{type,662,'fun',[{type,662,product,[{var,662,'BinRel1'},{var,662,'BinRel2'}]},{var,662,'BinRel3'}]},[{type,663,constraint,[{atom,663,is_subtype},[{var,663,'BinRel1'},{user_type,663,binary_relation,[]}]]},{type,664,constraint,[{atom,664,is_subtype},[{var,664,'BinRel2'},{user_type,664,binary_relation,[]}]]},{type,665,constraint,[{atom,665,is_subtype},[{var,665,'BinRel3'},{user_type,665,binary_relation,[]}]]}]]}]}}]}},{{function,relative_product1,2},[{file,[115,111,102,115,46,101,114,108]},{location,685}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,111,110,118,101,114,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,110,118,101,114,115,101>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,97,110,100,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,97,97,125,44,123,50,44,98,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,117,125,44,123,50,44,118,125,44,123,51,44,99,125,93,41,44,10,82,51,32,61,32,115,111,102,115,58,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,40,82,49,44,32,82,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,51,41,46,10,91,123,97,44,117,125,44,123,97,97,44,117,125,44,123,98,44,118,125,93>>]}]},{p,[],[{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,40,82,49,44,194,160,82,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,99,111,110,118,101,114,115,101,40,82,49,41,44,194,160,82,50,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,55,57>>,signature => [{attribute,685,spec,{{relative_product1,2},[{type,685,bounded_fun,[{type,685,'fun',[{type,685,product,[{var,685,'BinRel1'},{var,685,'BinRel2'}]},{var,685,'BinRel3'}]},[{type,686,constraint,[{atom,686,is_subtype},[{var,686,'BinRel1'},{user_type,686,binary_relation,[]}]]},{type,687,constraint,[{atom,687,is_subtype},[{var,687,'BinRel2'},{user_type,687,binary_relation,[]}]]},{type,688,constraint,[{atom,688,is_subtype},[{var,688,'BinRel3'},{user_type,688,binary_relation,[]}]]}]]}]}}]}},{{function,restriction,2},[{file,[115,111,102,115,46,101,114,108]},{location,826}],[<<114,101,115,116,114,105,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,116,111,32>>,{code,[],[<<83,101,116>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,44,52,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,115,116,114,105,99,116,105,111,110,40,82,49,44,32,83,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,97,125,44,123,50,44,98,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,48,48>>,signature => [{attribute,826,spec,{{restriction,2},[{type,826,bounded_fun,[{type,826,'fun',[{type,826,product,[{var,826,'BinRel1'},{var,826,'Set'}]},{var,826,'BinRel2'}]},[{type,827,constraint,[{atom,827,is_subtype},[{var,827,'BinRel1'},{user_type,827,binary_relation,[]}]]},{type,828,constraint,[{atom,828,is_subtype},[{var,828,'BinRel2'},{user_type,828,binary_relation,[]}]]},{type,829,constraint,[{atom,829,is_subtype},[{var,829,'Set'},{user_type,829,a_set,[]}]]}]]}]}}]}},{{function,restriction,3},[{file,[115,111,102,115,46,101,114,108]},{location,892}],[<<114,101,115,116,114,105,99,116,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,103,105,118,101,115,32,97,110,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<83,101,116,50>>]},<<32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,98,44,99,44,100,93,41,44,10,83,51,32,61,32,115,111,102,115,58,114,101,115,116,114,105,99,116,105,111,110,40,50,44,32,83,49,44,32,83,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,51,41,46,10,91,123,50,44,98,125,44,123,51,44,99,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,49,54>>,signature => [{attribute,892,spec,{{restriction,3},[{type,892,bounded_fun,[{type,892,'fun',[{type,892,product,[{var,892,'SetFun'},{var,892,'Set1'},{var,892,'Set2'}]},{var,892,'Set3'}]},[{type,893,constraint,[{atom,893,is_subtype},[{var,893,'SetFun'},{user_type,893,set_fun,[]}]]},{type,894,constraint,[{atom,894,is_subtype},[{var,894,'Set1'},{user_type,894,a_set,[]}]]},{type,895,constraint,[{atom,895,is_subtype},[{var,895,'Set2'},{user_type,895,a_set,[]}]]},{type,896,constraint,[{atom,896,is_subtype},[{var,896,'Set3'},{user_type,896,a_set,[]}]]}]]}]}}]}},{{function,set,2},[{file,[115,111,102,115,46,101,114,108]},{location,204}],[<<115,101,116,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,51,50>>,equiv => {function,set,1},signature => [{attribute,204,spec,{{set,2},[{type,204,bounded_fun,[{type,204,'fun',[{type,204,product,[{var,204,'Terms'},{var,204,'Type'}]},{var,204,'Set'}]},[{type,205,constraint,[{atom,205,is_subtype},[{var,205,'Set'},{user_type,205,a_set,[]}]]},{type,206,constraint,[{atom,206,is_subtype},[{var,206,'Terms'},{type,206,list,[{type,206,term,[]}]}]]},{type,207,constraint,[{atom,207,is_subtype},[{var,207,'Type'},{user_type,207,type,[]}]]}]]}]}}]}},{{function,set,1},[{file,[115,111,102,115,46,101,114,108]},{location,195}],[<<115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<46,32>>,{code,[],[<<115,101,116,40,76,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,76,44,194,160,84,41>>]},<<44,32,105,102,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46,32,73,102,32,110,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<91,97,116,111,109,93>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,115,101,116,32,116,121,112,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,51,50>>,signature => [{attribute,195,spec,{{set,1},[{type,195,bounded_fun,[{type,195,'fun',[{type,195,product,[{var,195,'Terms'}]},{var,195,'Set'}]},[{type,196,constraint,[{atom,196,is_subtype},[{var,196,'Set'},{user_type,196,a_set,[]}]]},{type,197,constraint,[{atom,197,is_subtype},[{var,197,'Terms'},{type,197,list,[{type,197,term,[]}]}]]}]]}]}}]}},{{function,specification,2},[{file,[115,111,102,115,46,101,114,108]},{location,359}],[<<115,112,101,99,105,102,105,99,97,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,101,116,32,99,111,110,116,97,105,110,105,110,103,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,102,111,114,32,119,104,105,99,104,32>>,{code,[],[<<70,117,110>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,194,160,70,117,110,50,125>>]},<<44,32>>,{code,[],[<<70,117,110,50>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,111,102,32,101,97,99,104,32,101,108,101,109,101,110,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,101,97,99,104,32,101,108,101,109,101,110,116,46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,120,44,49,125,44,123,120,44,50,125,44,123,121,44,51,125,93,41,44,10,83,49,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,91,82,49,44,82,50,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,112,101,99,105,102,105,99,97,116,105,111,110,40,102,117,110,32,115,111,102,115,58,105,115,95,97,95,102,117,110,99,116,105,111,110,47,49,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,91,123,97,44,49,125,44,123,98,44,50,125,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,52,53>>,signature => [{attribute,359,spec,{{specification,2},[{type,359,bounded_fun,[{type,359,'fun',[{type,359,product,[{var,359,'Fun'},{var,359,'Set1'}]},{var,359,'Set2'}]},[{type,360,constraint,[{atom,360,is_subtype},[{var,360,'Fun'},{user_type,360,spec_fun,[]}]]},{type,361,constraint,[{atom,361,is_subtype},[{var,361,'Set1'},{user_type,361,a_set,[]}]]},{type,362,constraint,[{atom,362,is_subtype},[{var,362,'Set2'},{user_type,362,a_set,[]}]]}]]}]}}]}},{{function,strict_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,752}],[<<115,116,114,105,99,116,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,116,114,105,99,116,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,116,114,105,99,116,32,114,101,108,97,116,105,111,110>>]},<<32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,49,125,44,123,49,44,50,125,44,123,50,44,49,125,44,123,50,44,50,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,115,116,114,105,99,116,95,114,101,108,97,116,105,111,110,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,50,125,44,123,50,44,49,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,54,54>>,signature => [{attribute,752,spec,{{strict_relation,1},[{type,752,bounded_fun,[{type,752,'fun',[{type,752,product,[{var,752,'BinRel1'}]},{var,752,'BinRel2'}]},[{type,753,constraint,[{atom,753,is_subtype},[{var,753,'BinRel1'},{user_type,753,binary_relation,[]}]]},{type,754,constraint,[{atom,754,is_subtype},[{var,754,'BinRel2'},{user_type,754,binary_relation,[]}]]}]]}]}}]}},{{function,substitution,2},[{file,[115,111,102,115,46,101,114,108]},{location,1048}],[<<115,117,98,115,116,105,116,117,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,102,117,110,99,116,105,111,110,44,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,119,104,105,99,104,32,105,115,32>>,{code,[],[<<83,101,116,49>>]},<<46,32,84,104,101,32,118,97,108,117,101,32,111,102,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,116,111,32,116,104,101,32,101,108,101,109,101,110,116,46>>]},{pre,[],[{code,[],[<<49,62,32,76,32,61,32,91,123,97,44,49,125,44,123,98,44,50,125,93,46,10,91,123,97,44,49,125,44,123,98,44,50,125,93,10,50,62,32,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,112,114,111,106,101,99,116,105,111,110,40,49,44,115,111,102,115,58,114,101,108,97,116,105,111,110,40,76,41,41,41,46,10,91,97,44,98,93,10,51,62,32,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,115,117,98,115,116,105,116,117,116,105,111,110,40,49,44,115,111,102,115,58,114,101,108,97,116,105,111,110,40,76,41,41,41,46,10,91,123,123,97,44,49,125,44,97,125,44,123,123,98,44,50,125,44,98,125,93,10,52,62,32,83,101,116,70,117,110,32,61,32,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,65,44,95,125,61,69,41,32,45,62,32,123,69,44,65,125,32,101,110,100,125,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,112,114,111,106,101,99,116,105,111,110,40,83,101,116,70,117,110,44,115,111,102,115,58,114,101,108,97,116,105,111,110,40,76,41,41,41,46,10,91,123,123,97,44,49,125,44,97,125,44,123,123,98,44,50,125,44,98,125,93>>]}]},{p,[],[<<84,104,101,32,114,101,108,97,116,105,111,110,32,111,102,32,101,113,117,97,108,105,116,121,32,98,101,116,119,101,101,110,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,123,97,44,98,44,99,125,58>>]},{pre,[],[{code,[],[<<49,62,32,73,32,61,32,115,111,102,115,58,115,117,98,115,116,105,116,117,116,105,111,110,40,102,117,110,40,65,41,32,45,62,32,65,32,101,110,100,44,32,115,111,102,115,58,115,101,116,40,91,97,44,98,44,99,93,41,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,73,41,46,10,91,123,97,44,97,125,44,123,98,44,98,125,44,123,99,44,99,125,93>>]}]},{p,[],[<<76,101,116,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,98,101,32,97,32,115,101,116,32,111,102,32,115,101,116,115,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,109,97,112,115,32,101,97,99,104,32,101,108,101,109,101,110,116,32>>,{code,[],[<<83,101,116>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,111,110,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,109,97,103,101>>]},<<32,111,102,32>>,{code,[],[<<83,101,116>>]},<<32,117,110,100,101,114,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,98,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,117,110,99,116,105,111,110,58>>]},{pre,[],[{code,[],[<<105,109,97,103,101,115,40,83,101,116,79,102,83,101,116,115,44,32,66,105,110,82,101,108,41,32,45,62,10,32,32,32,70,117,110,32,61,32,102,117,110,40,83,101,116,41,32,45,62,32,115,111,102,115,58,105,109,97,103,101,40,66,105,110,82,101,108,44,32,83,101,116,41,32,101,110,100,44,10,32,32,32,115,111,102,115,58,115,117,98,115,116,105,116,117,116,105,111,110,40,70,117,110,44,32,83,101,116,79,102,83,101,116,115,41,46>>]}]},{p,[],[<<69,120,116,101,114,110,97,108,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32,115,111,114,116,101,100,32,108,105,115,116,115,46,32,83,111,44,32,99,114,101,97,116,105,110,103,32,116,104,101,32,105,109,97,103,101,32,111,102,32,97,32,115,101,116,32,117,110,100,101,114,32,97,32,114,101,108,97,116,105,111,110,32,82,32,99,97,110,32,116,114,97,118,101,114,115,101,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,82,32,40,116,111,32,116,104,97,116,32,99,111,109,101,115,32,116,104,101,32,115,111,114,116,105,110,103,32,111,102,32,114,101,115,117,108,116,115,44,32,116,104,101,32,105,109,97,103,101,41,46,32,73,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,109,97,103,101,47,50>>]}]},<<44,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,116,114,97,118,101,114,115,101,100,32,111,110,99,101,32,102,111,114,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,116,97,107,101,32,116,111,111,32,108,111,110,103,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,102,102,105,99,105,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,117,110,100,101,114,32,116,104,101,32,97,115,115,117,109,112,116,105,111,110,32,116,104,97,116,32,116,104,101,32,105,109,97,103,101,32,111,102,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,117,110,100,101,114,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,110,111,110,45,101,109,112,116,121,58>>]},{pre,[],[{code,[],[<<105,109,97,103,101,115,50,40,83,101,116,79,102,83,101,116,115,44,32,66,105,110,82,101,108,41,32,45,62,10,32,32,32,67,82,32,61,32,115,111,102,115,58,99,97,110,111,110,105,99,97,108,95,114,101,108,97,116,105,111,110,40,83,101,116,79,102,83,101,116,115,41,44,10,32,32,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,40,67,82,44,32,66,105,110,82,101,108,41,44,10,32,32,32,115,111,102,115,58,114,101,108,97,116,105,111,110,95,116,111,95,102,97,109,105,108,121,40,82,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,56,50>>,signature => [{attribute,1048,spec,{{substitution,2},[{type,1048,bounded_fun,[{type,1048,'fun',[{type,1048,product,[{var,1048,'SetFun'},{var,1048,'Set1'}]},{var,1048,'Set2'}]},[{type,1049,constraint,[{atom,1049,is_subtype},[{var,1049,'SetFun'},{user_type,1049,set_fun,[]}]]},{type,1050,constraint,[{atom,1050,is_subtype},[{var,1050,'Set1'},{user_type,1050,a_set,[]}]]},{type,1051,constraint,[{atom,1051,is_subtype},[{var,1051,'Set2'},{user_type,1051,a_set,[]}]]}]]}]}}]}},{{function,symdiff,2},[{file,[115,111,102,115,46,101,114,108]},{location,408}],[<<115,121,109,100,105,102,102,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,121,109,109,101,116,114,105,99,95,100,105,102,102,101,114,101,110,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,121,109,109,101,116,114,105,99,32,100,105,102,102,101,114,101,110,99,101>>]},<<32,40,111,114,32,116,104,101,32,66,111,111,108,101,97,110,32,115,117,109,41,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,44,51,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,50,44,51,44,52,93,41,44,10,80,32,61,32,115,111,102,115,58,115,121,109,100,105,102,102,40,83,49,44,32,83,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,41,46,10,91,49,44,52,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,51,49>>,signature => [{attribute,408,spec,{{symdiff,2},[{type,408,bounded_fun,[{type,408,'fun',[{type,408,product,[{var,408,'Set1'},{var,408,'Set2'}]},{var,408,'Set3'}]},[{type,409,constraint,[{atom,409,is_subtype},[{var,409,'Set1'},{user_type,409,a_set,[]}]]},{type,410,constraint,[{atom,410,is_subtype},[{var,410,'Set2'},{user_type,410,a_set,[]}]]},{type,411,constraint,[{atom,411,is_subtype},[{var,411,'Set3'},{user_type,411,a_set,[]}]]}]]}]}}]}},{{function,symmetric_partition,2},[{file,[115,111,102,115,46,101,114,108]},{location,418}],[<<115,121,109,109,101,116,114,105,99,95,112,97,114,116,105,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,114,105,112,108,101,32,111,102,32,115,101,116,115,58>>]},{ul,[],[{li,[],[{code,[],[<<83,101,116,51>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,116,104,97,116,32,100,111,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{li,[],[{code,[],[<<83,101,116,52>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{li,[],[{code,[],[<<83,101,116,53>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,50>>]},<<32,116,104,97,116,32,100,111,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32>>,{code,[],[<<83,101,116,49>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,52,55>>,signature => [{attribute,418,spec,{{symmetric_partition,2},[{type,418,bounded_fun,[{type,418,'fun',[{type,418,product,[{var,418,'Set1'},{var,418,'Set2'}]},{type,418,tuple,[{var,418,'Set3'},{var,418,'Set4'},{var,418,'Set5'}]}]},[{type,419,constraint,[{atom,419,is_subtype},[{var,419,'Set1'},{user_type,419,a_set,[]}]]},{type,420,constraint,[{atom,420,is_subtype},[{var,420,'Set2'},{user_type,420,a_set,[]}]]},{type,421,constraint,[{atom,421,is_subtype},[{var,421,'Set3'},{user_type,421,a_set,[]}]]},{type,422,constraint,[{atom,422,is_subtype},[{var,422,'Set4'},{user_type,422,a_set,[]}]]},{type,423,constraint,[{atom,423,is_subtype},[{var,423,'Set5'},{user_type,423,a_set,[]}]]}]]}]}}]}},{{function,to_external,1},[{file,[115,111,102,115,46,101,114,108]},{location,319}],[<<116,111,95,101,120,116,101,114,110,97,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,111,102,32,97,110,32,97,116,111,109,105,99,44,32,111,114,100,101,114,101,100,44,32,111,114,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,54,56>>,signature => [{attribute,319,spec,{{to_external,1},[{type,319,bounded_fun,[{type,319,'fun',[{type,319,product,[{var,319,'AnySet'}]},{var,319,'ExternalSet'}]},[{type,320,constraint,[{atom,320,is_subtype},[{var,320,'ExternalSet'},{user_type,320,external_set,[]}]]},{type,321,constraint,[{atom,321,is_subtype},[{var,321,'AnySet'},{user_type,321,anyset,[]}]]}]]}]}}]}},{{function,to_sets,1},[{file,[115,111,102,115,46,101,114,108]},{location,335}],[<<116,111,95,115,101,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,32>>,{code,[],[<<65,83,101,116>>]},<<32,97,115,32,97,32,116,117,112,108,101,32,111,102,32,115,101,116,115,44,32,97,110,100,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32>>,{code,[],[<<65,83,101,116>>]},<<32,97,115,32,97,32,115,111,114,116,101,100,32,108,105,115,116,32,111,102,32,115,101,116,115,32,119,105,116,104,111,117,116,32,100,117,112,108,105,99,97,116,101,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,55,55>>,signature => [{attribute,335,spec,{{to_sets,1},[{type,335,bounded_fun,[{type,335,'fun',[{type,335,product,[{var,335,'ASet'}]},{var,335,'Sets'}]},[{type,336,constraint,[{atom,336,is_subtype},[{var,336,'ASet'},{type,336,union,[{user_type,336,a_set,[]},{user_type,336,ordset,[]}]}]]},{type,337,constraint,[{atom,337,is_subtype},[{var,337,'Sets'},{type,337,union,[{user_type,337,tuple_of,[{var,337,'AnySet'}]},{type,337,list,[{var,337,'AnySet'}]}]}]]},{type,338,constraint,[{atom,338,is_subtype},[{var,338,'AnySet'},{user_type,338,anyset,[]}]]}]]}]}}]}},{{function,type,1},[{file,[115,111,102,115,46,101,114,108]},{location,327}],[<<116,121,112,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,111,102,32,97,110,32,97,116,111,109,105,99,44,32,111,114,100,101,114,101,100,44,32,111,114,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,56,56>>,signature => [{attribute,327,spec,{{type,1},[{type,327,bounded_fun,[{type,327,'fun',[{type,327,product,[{var,327,'AnySet'}]},{var,327,'Type'}]},[{type,328,constraint,[{atom,328,is_subtype},[{var,328,'AnySet'},{user_type,328,anyset,[]}]]},{type,329,constraint,[{atom,329,is_subtype},[{var,329,'Type'},{user_type,329,type,[]}]]}]]}]}}]}},{{function,union,1},[{file,[115,111,102,115,46,101,114,108]},{location,553}],[<<117,110,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,111,110>>]},<<32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,115,101,116,115,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,57,55>>,signature => [{attribute,553,spec,{{union,1},[{type,553,bounded_fun,[{type,553,'fun',[{type,553,product,[{var,553,'SetOfSets'}]},{var,553,'Set'}]},[{type,554,constraint,[{atom,554,is_subtype},[{var,554,'Set'},{user_type,554,a_set,[]}]]},{type,555,constraint,[{atom,555,is_subtype},[{var,555,'SetOfSets'},{user_type,555,set_of_sets,[]}]]}]]}]}}]}},{{function,union,2},[{file,[115,111,102,115,46,101,114,108]},{location,378}],[<<117,110,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,55,48,54>>,signature => [{attribute,378,spec,{{union,2},[{type,378,bounded_fun,[{type,378,'fun',[{type,378,product,[{var,378,'Set1'},{var,378,'Set2'}]},{var,378,'Set3'}]},[{type,379,constraint,[{atom,379,is_subtype},[{var,379,'Set1'},{user_type,379,a_set,[]}]]},{type,380,constraint,[{atom,380,is_subtype},[{var,380,'Set2'},{user_type,380,a_set,[]}]]},{type,381,constraint,[{atom,381,is_subtype},[{var,381,'Set3'},{user_type,381,a_set,[]}]]}]]}]}}]}},{{function,union_of_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,1288}],[<<117,110,105,111,110,95,111,102,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,48,44,50,44,52,93,125,44,123,98,44,91,48,44,49,44,50,93,125,44,123,99,44,91,50,44,51,93,125,93,41,44,10,83,32,61,32,115,111,102,115,58,117,110,105,111,110,95,111,102,95,102,97,109,105,108,121,40,70,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,48,44,49,44,50,44,51,44,52,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,55,49,53>>,signature => [{attribute,1288,spec,{{union_of_family,1},[{type,1288,bounded_fun,[{type,1288,'fun',[{type,1288,product,[{var,1288,'Family'}]},{var,1288,'Set'}]},[{type,1289,constraint,[{atom,1289,is_subtype},[{var,1289,'Family'},{user_type,1289,family,[]}]]},{type,1290,constraint,[{atom,1290,is_subtype},[{var,1290,'Set'},{user_type,1290,a_set,[]}]]}]]}]}}]}},{{function,weak_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,763}],[<<119,101,97,107,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,117,98,115,101,116,32,83,32,111,102,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,119,101,97,107,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<119,101,97,107,32,114,101,108,97,116,105,111,110>>]},<<32,87,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46,32,76,101,116,32,70,32,98,101,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,105,101,108,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,101,108,100>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46,32,84,104,101,32,115,117,98,115,101,116,32,83,32,105,115,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,32,83,32,121,32,105,102,32,120,32,87,32,121,32,102,111,114,32,115,111,109,101,32,120,32,105,110,32,70,32,97,110,100,32,102,111,114,32,115,111,109,101,32,121,32,105,110,32,70,46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,49,125,44,123,49,44,50,125,44,123,51,44,49,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,119,101,97,107,95,114,101,108,97,116,105,111,110,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,49,125,44,123,49,44,50,125,44,123,50,44,50,125,44,123,51,44,49,125,44,123,51,44,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,55,50,57>>,signature => [{attribute,763,spec,{{weak_relation,1},[{type,763,bounded_fun,[{type,763,'fun',[{type,763,product,[{var,763,'BinRel1'}]},{var,763,'BinRel2'}]},[{type,764,constraint,[{atom,764,is_subtype},[{var,764,'BinRel1'},{user_type,764,binary_relation,[]}]]},{type,765,constraint,[{atom,765,is_subtype},[{var,765,'BinRel2'},{user_type,765,binary_relation,[]}]]}]]}]}}]}},{{type,anyset,0},[{file,[115,111,102,115,46,101,114,108]},{location,117}],[<<45,116,121,112,101,32,97,110,121,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,121,32,107,105,110,100,32,111,102,32,115,101,116,32,40,97,108,115,111,32,105,110,99,108,117,100,101,100,32,97,114,101,32,116,104,101,32,97,116,111,109,105,99,32,115,101,116,115,41,46>>]}]},#{signature => [{attribute,117,type,{anyset,{type,117,union,[{user_type,117,ordset,[]},{user_type,117,a_set,[]}]},[]}}]}},{{type,binary_relation,0},[{file,[115,111,102,115,46,101,114,108]},{location,118}],[<<45,116,121,112,101,32,98,105,110,97,114,121,95,114,101,108,97,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,98,105,110,97,114,121,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<98,105,110,97,114,121,32,114,101,108,97,116,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,118,type,{binary_relation,{user_type,118,relation,[]},[]}}]}},{{type,external_set,0},[{file,[115,111,102,115,46,101,114,108]},{location,119}],[<<45,116,121,112,101,32,101,120,116,101,114,110,97,108,95,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<46>>]}]},#{signature => [{attribute,119,type,{external_set,{type,119,term,[]},[]}}]}},{{type,family,0},[{file,[115,111,102,115,46,101,114,108]},{location,121}],[<<45,116,121,112,101,32,102,97,109,105,108,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,40,111,102,32,115,117,98,115,101,116,115,41,46>>]}]},#{signature => [{attribute,121,type,{family,{user_type,121,a_function,[]},[]}}]}},{{type,a_function,0},[{file,[115,111,102,115,46,101,114,108]},{location,120}],[<<45,116,121,112,101,32,97,95,102,117,110,99,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,120,type,{a_function,{user_type,120,relation,[]},[]}}]}},{{type,ordset,0},[{file,[115,111,102,115,46,101,114,108]},{location,122}],[<<45,116,121,112,101,32,111,114,100,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<111,114,100,101,114,101,100,32,115,101,116>>]},<<46>>]}]},#{signature => [{attribute,122,opaque,{ordset,{type,122,record,[{atom,122,'OrdSet'}]},[]}}]}},{{type,relation,0},[{file,[115,111,102,115,46,101,114,108]},{location,123}],[<<45,116,121,112,101,32,114,101,108,97,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,110,95,97,114,121,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,45,97,114,121,32,114,101,108,97,116,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,123,type,{relation,{user_type,123,a_set,[]},[]}}]}},{{type,a_set,0},[{file,[115,111,102,115,46,101,114,108]},{location,124}],[<<45,116,121,112,101,32,97,95,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<46>>]}]},#{signature => [{attribute,124,opaque,{a_set,{type,124,record,[{atom,124,'Set'}]},[]}}]}},{{type,set_of_sets,0},[{file,[115,111,102,115,46,101,114,108]},{location,125}],[<<45,116,121,112,101,32,115,101,116,95,111,102,95,115,101,116,115,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<32,111,102,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,46>>]}]},#{signature => [{attribute,125,type,{set_of_sets,{user_type,125,a_set,[]},[]}}]}},{{type,set_fun,0},[{file,[115,111,102,115,46,101,114,108]},{location,126}],[<<45,116,121,112,101,32,115,101,116,95,102,117,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,95,102,117,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,101,116,70,117,110>>]},<<46>>]}]},#{signature => [{attribute,126,type,{set_fun,{type,126,union,[{type,126,pos_integer,[]},{type,127,tuple,[{atom,127,external},{type,127,'fun',[{type,127,product,[{user_type,127,external_set,[]}]},{user_type,127,external_set,[]}]}]},{type,128,'fun',[{type,128,product,[{user_type,128,anyset,[]}]},{user_type,128,anyset,[]}]}]},[]}}]}},{{type,spec_fun,0},[{file,[115,111,102,115,46,101,114,108]},{location,129}],[<<45,116,121,112,101,32,115,112,101,99,95,102,117,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,129,type,{spec_fun,{type,129,union,[{type,129,tuple,[{atom,129,external},{type,129,'fun',[{type,129,product,[{user_type,129,external_set,[]}]},{type,129,boolean,[]}]}]},{type,130,'fun',[{type,130,product,[{user_type,130,anyset,[]}]},{type,130,boolean,[]}]}]},[]}}]}},{{type,type,0},[{file,[115,111,102,115,46,101,114,108]},{location,131}],[<<45,116,121,112,101,32,116,121,112,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<46>>]}]},#{signature => [{attribute,131,type,{type,{type,131,term,[]},[]}}]}},{{type,tuple_of,1},[{file,[115,111,102,115,46,101,114,108]},{location,133}],[<<116,117,112,108,101,95,111,102,40,84,41>>],#{<<101,110>> => [{p,[],[<<65,32,116,117,112,108,101,32,119,104,101,114,101,32,116,104,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,111,102,32,116,121,112,101,32>>,{code,[],[<<84>>]},<<46>>]}]},#{signature => [{attribute,133,type,{tuple_of,{type,133,tuple,any},[{var,133,'_T'}]}}]}}]}. \ No newline at end of file
+{docs_v1,[{file,[115,111,102,115,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,#{<<101,110>> => [{p,[],[<<84,104,105,115,32,109,111,100,117,108,101,32,112,114,111,118,105,100,101,115,32,111,112,101,114,97,116,105,111,110,115,32,111,110,32,102,105,110,105,116,101,32,115,101,116,115,32,97,110,100,32,114,101,108,97,116,105,111,110,115,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32,115,101,116,115,46,32,73,110,116,117,105,116,105,118,101,108,121,44,32,97,32,115,101,116,32,105,115,32,97,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,101,108,101,109,101,110,116,115,59,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,98,101,108,111,110,103,115,32,116,111,32,116,104,101,32,115,101,116,44,32,97,110,100,32,116,104,101,32,115,101,116,32,99,111,110,116,97,105,110,115,32,101,118,101,114,121,32,101,108,101,109,101,110,116,46>>]},{p,[],[<<71,105,118,101,110,32,97,32,115,101,116,32,65,32,97,110,100,32,97,32,115,101,110,116,101,110,99,101,32,83,40,120,41,44,32,119,104,101,114,101,32,120,32,105,115,32,97,32,102,114,101,101,32,118,97,114,105,97,98,108,101,44,32,97,32,110,101,119,32,115,101,116,32,66,32,119,104,111,115,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,101,120,97,99,116,108,121,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,102,111,114,32,119,104,105,99,104,32,83,40,120,41,32,104,111,108,100,115,32,99,97,110,32,98,101,32,102,111,114,109,101,100,44,32,116,104,105,115,32,105,115,32,100,101,110,111,116,101,100,32,66,194,160,61,32,123,120,194,160,105,110,194,160,65,194,160,58,32,83,40,120,41,125,46,32,83,101,110,116,101,110,99,101,115,32,97,114,101,32,101,120,112,114,101,115,115,101,100,32,117,115,105,110,103,32,116,104,101,32,108,111,103,105,99,97,108,32,111,112,101,114,97,116,111,114,115,32,34,102,111,114,32,115,111,109,101,34,32,40,111,114,32,34,116,104,101,114,101,32,101,120,105,115,116,115,34,41,44,32,34,102,111,114,32,97,108,108,34,44,32,34,97,110,100,34,44,32,34,111,114,34,44,32,34,110,111,116,34,46,32,73,102,32,116,104,101,32,101,120,105,115,116,101,110,99,101,32,111,102,32,97,32,115,101,116,32,99,111,110,116,97,105,110,105,110,103,32,97,108,108,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,101,108,101,109,101,110,116,115,32,105,115,32,107,110,111,119,110,32,40,97,115,32,105,115,32,97,108,119,97,121,115,32,116,104,101,32,99,97,115,101,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,41,44,32,116,104,105,115,32,105,115,32,100,101,110,111,116,101,100,32,66,194,160,61,32,123,120,194,160,58,32,83,40,120,41,125,46>>]},{ul,[],[{li,[],[{p,[],[<<84,104,101,32>>,{em,[],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,97,44,32,98,44,32,97,110,100,32,99,32,105,115,32,100,101,110,111,116,101,100,32,123,97,44,194,160,98,44,194,160,99,125,46,32,84,104,105,115,32,110,111,116,97,116,105,111,110,32,105,115,32,110,111,116,32,116,111,32,98,101,32,99,111,110,102,117,115,101,100,32,119,105,116,104,32,116,117,112,108,101,115,46>>]},{p,[],[<<84,104,101,32>>,{em,[],[<<111,114,100,101,114,101,100,32,112,97,105,114>>]},<<32,111,102,32,97,32,97,110,100,32,98,44,32,119,105,116,104,32,102,105,114,115,116,32>>,{em,[],[<<99,111,111,114,100,105,110,97,116,101>>]},<<32,97,32,97,110,100,32,115,101,99,111,110,100,32,99,111,111,114,100,105,110,97,116,101,32,98,44,32,105,115,32,100,101,110,111,116,101,100,32,40,97,44,194,160,98,41,46,32,65,110,32,111,114,100,101,114,101,100,32,112,97,105,114,32,105,115,32,97,110,32>>,{em,[],[<<111,114,100,101,114,101,100,32,115,101,116>>]},<<32,111,102,32,116,119,111,32,101,108,101,109,101,110,116,115,46,32,73,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,111,114,100,101,114,101,100,32,115,101,116,115,32,99,97,110,32,99,111,110,116,97,105,110,32,111,110,101,44,32,116,119,111,44,32,111,114,32,109,111,114,101,32,101,108,101,109,101,110,116,115,44,32,97,110,100,32,112,97,114,101,110,116,104,101,115,101,115,32,97,114,101,32,117,115,101,100,32,116,111,32,101,110,99,108,111,115,101,32,116,104,101,32,101,108,101,109,101,110,116,115,46>>]},{p,[],[<<85,110,111,114,100,101,114,101,100,32,115,101,116,115,32,97,110,100,32,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,111,114,116,104,111,103,111,110,97,108,44,32,97,103,97,105,110,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,59,32,116,104,101,114,101,32,105,115,32,110,111,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,101,113,117,97,108,32,116,111,32,97,110,121,32,111,114,100,101,114,101,100,32,115,101,116,46>>]}]},{li,[],[{p,[],[<<84,104,101,32>>,{em,[],[<<101,109,112,116,121,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,115,32,110,111,32,101,108,101,109,101,110,116,115,46>>]},{p,[],[<<83,101,116,32,65,32,105,115,32>>,{a,[{id,<<101,113,117,97,108>>}],[]},{em,[],[<<101,113,117,97,108>>]},<<32,116,111,32,115,101,116,32,66,32,105,102,32,116,104,101,121,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32,101,108,101,109,101,110,116,115,44,32,119,104,105,99,104,32,105,115,32,100,101,110,111,116,101,100,32,65,194,160,61,194,160,66,46,32,84,119,111,32,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,101,113,117,97,108,32,105,102,32,116,104,101,121,32,99,111,110,116,97,105,110,32,116,104,101,32,115,97,109,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,97,110,100,32,104,97,118,101,32,101,113,117,97,108,32,101,108,101,109,101,110,116,115,32,97,116,32,101,97,99,104,32,99,111,111,114,100,105,110,97,116,101,46>>]},{p,[],[<<83,101,116,32,66,32,105,115,32,97,32>>,{a,[{id,<<115,117,98,115,101,116>>}],[]},{em,[],[<<115,117,98,115,101,116>>]},<<32,111,102,32,115,101,116,32,65,32,105,102,32,65,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,66,32,99,111,110,116,97,105,110,115,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<117,110,105,111,110>>}],[]},{em,[],[<<117,110,105,111,110>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,65,32,97,110,100,32,66,32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,97,110,100,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,66,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<105,110,116,101,114,115,101,99,116,105,111,110>>}],[]},{em,[],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,65,32,97,110,100,32,66,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,66,46>>]},{p,[],[<<84,119,111,32,115,101,116,115,32,97,114,101,32>>,{a,[{id,<<100,105,115,106,111,105,110,116>>}],[]},{em,[],[<<100,105,115,106,111,105,110,116>>]},<<32,105,102,32,116,104,101,105,114,32,105,110,116,101,114,115,101,99,116,105,111,110,32,105,115,32,116,104,101,32,101,109,112,116,121,32,115,101,116,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<100,105,102,102,101,114,101,110,99,101>>}],[]},{em,[],[<<100,105,102,102,101,114,101,110,99,101>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,65,32,97,110,100,32,66,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,65,32,116,104,97,116,32,100,111,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32,66,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<115,121,109,109,101,116,114,105,99,95,100,105,102,102,101,114,101,110,99,101>>}],[]},{em,[],[<<115,121,109,109,101,116,114,105,99,32,100,105,102,102,101,114,101,110,99,101>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,116,104,111,115,101,32,101,108,101,109,101,110,116,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,101,105,116,104,101,114,32,111,102,32,116,104,101,32,116,119,111,32,115,101,116,115,44,32,98,117,116,32,110,111,116,32,98,111,116,104,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<117,110,105,111,110,95,110>>}],[]},{em,[],[<<117,110,105,111,110>>]},<<32,111,102,32,97,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,115,101,116,115,32,105,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,116,104,101,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,97,116,32,108,101,97,115,116,32,111,110,101,32,115,101,116,32,111,102,32,116,104,101,32,99,111,108,108,101,99,116,105,111,110,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<105,110,116,101,114,115,101,99,116,105,111,110,95,110>>}],[]},{em,[],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32,97,32,110,111,110,45,101,109,112,116,121,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,115,101,116,115,32,105,115,32,116,104,101,32,115,101,116,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32,101,118,101,114,121,32,115,101,116,32,111,102,32,116,104,101,32,99,111,108,108,101,99,116,105,111,110,46>>]}]},{li,[],[{p,[],[<<84,104,101,32>>,{a,[{id,<<67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,119,111,32,115,101,116,115,32,88,32,97,110,100,32,89,44,32,100,101,110,111,116,101,100,32,88,194,160,195,151,194,160,89,44,32,105,115,32,116,104,101,32,115,101,116,32,123,97,194,160,58,32,97,194,160,61,32,40,120,44,194,160,121,41,32,102,111,114,32,115,111,109,101,32,120,194,160,105,110,194,160,88,32,97,110,100,32,102,111,114,32,115,111,109,101,32,121,194,160,105,110,194,160,89,125,46>>]},{p,[],[<<65,32>>,{a,[{id,<<114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<114,101,108,97,116,105,111,110>>]},<<32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,88,194,160,195,151,194,160,89,46,32,76,101,116,32,82,32,98,101,32,97,32,114,101,108,97,116,105,111,110,46,32,84,104,101,32,102,97,99,116,32,116,104,97,116,32,40,120,44,194,160,121,41,32,98,101,108,111,110,103,115,32,116,111,32,82,32,105,115,32,119,114,105,116,116,101,110,32,97,115,32,120,194,160,82,194,160,121,46,32,65,115,32,114,101,108,97,116,105,111,110,115,32,97,114,101,32,115,101,116,115,44,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,115,32,111,102,32,116,104,101,32,108,97,115,116,32,105,116,101,109,32,40,115,117,98,115,101,116,44,32,117,110,105,111,110,44,32,97,110,100,32,115,111,32,111,110,41,32,97,112,112,108,121,32,116,111,32,114,101,108,97,116,105,111,110,115,32,97,115,32,119,101,108,108,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<100,111,109,97,105,110>>}],[]},{em,[],[<<100,111,109,97,105,110>>]},<<32,111,102,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,120,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,121,194,160,105,110,194,160,89,125,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<114,97,110,103,101>>}],[]},{em,[],[<<114,97,110,103,101>>]},<<32,111,102,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,121,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,120,194,160,105,110,194,160,88,125,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<99,111,110,118,101,114,115,101>>}],[]},{em,[],[<<99,111,110,118,101,114,115,101>>]},<<32,111,102,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,97,194,160,58,32,97,194,160,61,32,40,121,44,194,160,120,41,32,102,111,114,32,115,111,109,101,32,40,120,44,194,160,121,41,194,160,105,110,194,160,82,125,46>>]},{p,[],[<<73,102,32,65,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,88,44,32,116,104,101,32>>,{a,[{id,<<105,109,97,103,101>>}],[]},{em,[],[<<105,109,97,103,101>>]},<<32,111,102,32,65,32,117,110,100,101,114,32,82,32,105,115,32,116,104,101,32,115,101,116,32,123,121,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,120,194,160,105,110,194,160,65,125,46,32,73,102,32,66,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,89,44,32,116,104,101,32>>,{a,[{id,<<105,110,118,101,114,115,101,95,105,109,97,103,101>>}],[]},{em,[],[<<105,110,118,101,114,115,101,32,105,109,97,103,101>>]},<<32,111,102,32,66,32,105,115,32,116,104,101,32,115,101,116,32,123,120,194,160,58,32,120,194,160,82,194,160,121,32,102,111,114,32,115,111,109,101,32,121,194,160,105,110,194,160,66,125,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,88,32,116,111,32,89,44,32,97,110,100,32,83,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,89,32,116,111,32,90,44,32,116,104,101,32>>,{a,[{id,<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,82,32,97,110,100,32,83,32,105,115,32,116,104,101,32,114,101,108,97,116,105,111,110,32,84,32,102,114,111,109,32,88,32,116,111,32,90,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,84,194,160,122,32,105,102,32,97,110,100,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,101,120,105,115,116,115,32,97,110,32,101,108,101,109,101,110,116,32,121,32,105,110,32,89,32,115,117,99,104,32,116,104,97,116,32,120,194,160,82,194,160,121,32,97,110,100,32,121,194,160,83,194,160,122,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<114,101,115,116,114,105,99,116,105,111,110>>}],[]},{em,[],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32,82,32,116,111,32,65,32,105,115,32,116,104,101,32,115,101,116,32,83,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,83,194,160,121,32,105,102,32,97,110,100,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,101,120,105,115,116,115,32,97,110,32,101,108,101,109,101,110,116,32,120,32,105,110,32,65,32,115,117,99,104,32,116,104,97,116,32,120,194,160,82,194,160,121,46>>]},{p,[],[<<73,102,32,83,32,105,115,32,97,32,114,101,115,116,114,105,99,116,105,111,110,32,111,102,32,82,32,116,111,32,65,44,32,116,104,101,110,32,82,32,105,115,32,97,110,32>>,{a,[{id,<<101,120,116,101,110,115,105,111,110>>}],[]},{em,[],[<<101,120,116,101,110,115,105,111,110>>]},<<32,111,102,32,83,32,116,111,32,88,46>>]},{p,[],[<<73,102,32,88,194,160,61,194,160,89,44,32,116,104,101,110,32,82,32,105,115,32,99,97,108,108,101,100,32,97,32,114,101,108,97,116,105,111,110,32>>,{em,[],[<<105,110>>]},<<32,88,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<102,105,101,108,100>>}],[]},{em,[],[<<102,105,101,108,100>>]},<<32,111,102,32,97,32,114,101,108,97,116,105,111,110,32,82,32,105,110,32,88,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,82,32,97,110,100,32,116,104,101,32,114,97,110,103,101,32,111,102,32,82,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,97,110,100,32,105,102,32,83,32,105,115,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,83,194,160,121,32,105,102,32,120,194,160,82,194,160,121,32,97,110,100,32,110,111,116,32,120,194,160,61,194,160,121,44,32,116,104,101,110,32,83,32,105,115,32,116,104,101,32>>,{a,[{id,<<115,116,114,105,99,116,95,114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<115,116,114,105,99,116>>]},<<32,114,101,108,97,116,105,111,110,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,82,46,32,67,111,110,118,101,114,115,101,108,121,44,32,105,102,32,83,32,105,115,32,97,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,97,110,100,32,105,102,32,82,32,105,115,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,82,194,160,121,32,105,102,32,120,194,160,83,194,160,121,32,111,114,32,120,194,160,61,194,160,121,44,32,116,104,101,110,32,82,32,105,115,32,116,104,101,32>>,{a,[{id,<<119,101,97,107,95,114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<119,101,97,107>>]},<<32,114,101,108,97,116,105,111,110,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,83,46>>]},{p,[],[<<65,32,114,101,108,97,116,105,111,110,32,82,32,105,110,32,88,32,105,115,32>>,{em,[],[<<114,101,102,108,101,120,105,118,101>>]},<<32,105,102,32,120,194,160,82,194,160,120,32,102,111,114,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,120,32,111,102,32,88,44,32,105,116,32,105,115,32>>,{em,[],[<<115,121,109,109,101,116,114,105,99>>]},<<32,105,102,32,120,194,160,82,194,160,121,32,105,109,112,108,105,101,115,32,116,104,97,116,32,121,194,160,82,194,160,120,44,32,97,110,100,32,105,116,32,105,115,32>>,{em,[],[<<116,114,97,110,115,105,116,105,118,101>>]},<<32,105,102,32,120,194,160,82,194,160,121,32,97,110,100,32,121,194,160,82,194,160,122,32,105,109,112,108,121,32,116,104,97,116,32,120,194,160,82,194,160,122,46>>]}]},{li,[],[{p,[],[<<65,32>>,{a,[{id,<<102,117,110,99,116,105,111,110>>}],[]},{em,[],[<<102,117,110,99,116,105,111,110>>]},<<32,70,32,105,115,32,97,32,114,101,108,97,116,105,111,110,44,32,97,32,115,117,98,115,101,116,32,111,102,32,88,194,160,195,151,194,160,89,44,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,70,32,105,115,32,101,113,117,97,108,32,116,111,32,88,32,97,110,100,32,115,117,99,104,32,116,104,97,116,32,102,111,114,32,101,118,101,114,121,32,120,32,105,110,32,88,32,116,104,101,114,101,32,105,115,32,97,32,117,110,105,113,117,101,32,101,108,101,109,101,110,116,32,121,32,105,110,32,89,32,119,105,116,104,32,40,120,44,194,160,121,41,32,105,110,32,70,46,32,84,104,101,32,108,97,116,116,101,114,32,99,111,110,100,105,116,105,111,110,32,99,97,110,32,98,101,32,102,111,114,109,117,108,97,116,101,100,32,97,115,32,102,111,108,108,111,119,115,58,32,105,102,32,120,194,160,70,194,160,121,32,97,110,100,32,120,194,160,70,194,160,122,44,32,116,104,101,110,32,121,194,160,61,194,160,122,46,32,73,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,105,116,32,105,115,32,110,111,116,32,114,101,113,117,105,114,101,100,32,116,104,97,116,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,70,32,105,115,32,101,113,117,97,108,32,116,111,32,88,32,102,111,114,32,97,32,114,101,108,97,116,105,111,110,32,116,111,32,98,101,32,99,111,110,115,105,100,101,114,101,100,32,97,32,102,117,110,99,116,105,111,110,46>>]},{p,[],[<<73,110,115,116,101,97,100,32,111,102,32,119,114,105,116,105,110,103,32,40,120,44,194,160,121,41,194,160,105,110,194,160,70,32,111,114,32,120,194,160,70,194,160,121,44,32,119,101,32,119,114,105,116,101,32,70,40,120,41,194,160,61,194,160,121,32,119,104,101,110,32,70,32,105,115,32,97,32,102,117,110,99,116,105,111,110,44,32,97,110,100,32,115,97,121,32,116,104,97,116,32,70,32,109,97,112,115,32,120,32,111,110,116,111,32,121,44,32,111,114,32,116,104,97,116,32,116,104,101,32,118,97,108,117,101,32,111,102,32,70,32,97,116,32,120,32,105,115,32,121,46>>]},{p,[],[<<65,115,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,114,101,108,97,116,105,111,110,115,44,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,115,32,111,102,32,116,104,101,32,108,97,115,116,32,105,116,101,109,32,40,100,111,109,97,105,110,44,32,114,97,110,103,101,44,32,97,110,100,32,115,111,32,111,110,41,32,97,112,112,108,121,32,116,111,32,102,117,110,99,116,105,111,110,115,32,97,115,32,119,101,108,108,46>>]},{p,[],[<<73,102,32,116,104,101,32,99,111,110,118,101,114,115,101,32,111,102,32,97,32,102,117,110,99,116,105,111,110,32,70,32,105,115,32,97,32,102,117,110,99,116,105,111,110,32,70,39,44,32,116,104,101,110,32,70,39,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{a,[{id,<<105,110,118,101,114,115,101>>}],[]},{em,[],[<<105,110,118,101,114,115,101>>]},<<32,111,102,32,70,46>>]},{p,[],[<<84,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,116,119,111,32,102,117,110,99,116,105,111,110,115,32,70,49,32,97,110,100,32,70,50,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{a,[{id,<<99,111,109,112,111,115,105,116,101>>}],[]},{em,[],[<<99,111,109,112,111,115,105,116,101>>]},<<32,111,102,32,70,49,32,97,110,100,32,70,50,32,105,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,70,49,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,70,50,46>>]}]},{li,[],[{p,[],[<<83,111,109,101,116,105,109,101,115,44,32,119,104,101,110,32,116,104,101,32,114,97,110,103,101,32,111,102,32,97,32,102,117,110,99,116,105,111,110,32,105,115,32,109,111,114,101,32,105,109,112,111,114,116,97,110,116,32,116,104,97,110,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,116,115,101,108,102,44,32,116,104,101,32,102,117,110,99,116,105,111,110,32,105,115,32,99,97,108,108,101,100,32,97,32>>,{em,[],[<<102,97,109,105,108,121>>]},<<46>>]},{p,[],[<<84,104,101,32,100,111,109,97,105,110,32,111,102,32,97,32,102,97,109,105,108,121,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{em,[],[<<105,110,100,101,120,32,115,101,116>>]},<<44,32,97,110,100,32,116,104,101,32,114,97,110,103,101,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{em,[],[<<105,110,100,101,120,101,100,32,115,101,116>>]},<<46>>]},{p,[],[<<73,102,32,120,32,105,115,32,97,32,102,97,109,105,108,121,32,102,114,111,109,32,73,32,116,111,32,88,44,32,116,104,101,110,32,120,91,105,93,32,100,101,110,111,116,101,115,32,116,104,101,32,118,97,108,117,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,32,97,116,32,105,110,100,101,120,32,105,46,32,84,104,101,32,110,111,116,97,116,105,111,110,32,34,97,32,102,97,109,105,108,121,32,105,110,32,88,34,32,105,115,32,117,115,101,100,32,102,111,114,32,115,117,99,104,32,97,32,102,97,109,105,108,121,46>>]},{p,[],[<<87,104,101,110,32,116,104,101,32,105,110,100,101,120,101,100,32,115,101,116,32,105,115,32,97,32,115,101,116,32,111,102,32,115,117,98,115,101,116,115,32,111,102,32,97,32,115,101,116,32,88,44,32,119,101,32,99,97,108,108,32,120,32,97,32>>,{a,[{id,<<102,97,109,105,108,121>>}],[]},{em,[],[<<102,97,109,105,108,121,32,111,102,32,115,117,98,115,101,116,115>>]},<<32,111,102,32,88,46>>]},{p,[],[<<73,102,32,120,32,105,115,32,97,32,102,97,109,105,108,121,32,111,102,32,115,117,98,115,101,116,115,32,111,102,32,88,44,32,116,104,101,32,117,110,105,111,110,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,120,32,105,115,32,99,97,108,108,101,100,32,116,104,101,32>>,{em,[],[<<117,110,105,111,110,32,111,102,32,116,104,101,32,102,97,109,105,108,121>>]},<<32,120,46>>]},{p,[],[<<73,102,32,120,32,105,115,32,110,111,110,45,101,109,112,116,121,32,40,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,110,111,110,45,101,109,112,116,121,41,44,32,116,104,101,32>>,{em,[],[<<105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32,102,97,109,105,108,121>>]},<<32,120,32,105,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,120,46>>]},{p,[],[<<73,110,32,116,104,105,115,32,109,111,100,117,108,101,44,32,116,104,101,32,111,110,108,121,32,102,97,109,105,108,105,101,115,32,116,104,97,116,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,97,114,101,32,102,97,109,105,108,105,101,115,32,111,102,32,115,117,98,115,101,116,115,32,111,102,32,115,111,109,101,32,115,101,116,32,88,59,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,116,104,101,32,119,111,114,100,32,34,102,97,109,105,108,121,34,32,105,115,32,117,115,101,100,32,102,111,114,32,115,117,99,104,32,102,97,109,105,108,105,101,115,32,111,102,32,115,117,98,115,101,116,115,46>>]}]},{li,[],[{p,[],[<<65,32>>,{a,[{id,<<112,97,114,116,105,116,105,111,110>>}],[]},{em,[],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32,97,32,115,101,116,32,88,32,105,115,32,97,32,99,111,108,108,101,99,116,105,111,110,32,83,32,111,102,32,110,111,110,45,101,109,112,116,121,32,115,117,98,115,101,116,115,32,111,102,32,88,32,119,104,111,115,101,32,117,110,105,111,110,32,105,115,32,88,32,97,110,100,32,119,104,111,115,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,112,97,105,114,119,105,115,101,32,100,105,115,106,111,105,110,116,46>>]},{p,[],[<<65,32,114,101,108,97,116,105,111,110,32,105,110,32,97,32,115,101,116,32,105,115,32,97,110,32>>,{em,[],[<<101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110>>]},<<32,105,102,32,105,116,32,105,115,32,114,101,102,108,101,120,105,118,101,44,32,115,121,109,109,101,116,114,105,99,44,32,97,110,100,32,116,114,97,110,115,105,116,105,118,101,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,110,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,97,110,100,32,120,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,88,44,32,116,104,101,32>>,{a,[{id,<<101,113,117,105,118,97,108,101,110,99,101,95,99,108,97,115,115>>}],[]},{em,[],[<<101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115>>]},<<32,111,102,32,120,32,119,105,116,104,32,114,101,115,112,101,99,116,32,116,111,32,82,32,105,115,32,116,104,101,32,115,101,116,32,111,102,32,97,108,108,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,121,32,111,102,32,88,32,102,111,114,32,119,104,105,99,104,32,120,194,160,82,194,160,121,32,104,111,108,100,115,46,32,84,104,101,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,101,115,32,99,111,110,115,116,105,116,117,116,101,32,97,32,112,97,114,116,105,116,105,111,110,105,110,103,32,111,102,32,88,46,32,67,111,110,118,101,114,115,101,108,121,44,32,105,102,32,67,32,105,115,32,97,32,112,97,114,116,105,116,105,111,110,32,111,102,32,88,44,32,116,104,101,32,114,101,108,97,116,105,111,110,32,116,104,97,116,32,104,111,108,100,115,32,102,111,114,32,97,110,121,32,116,119,111,32,101,108,101,109,101,110,116,115,32,111,102,32,88,32,105,102,32,116,104,101,121,32,98,101,108,111,110,103,32,116,111,32,116,104,101,32,115,97,109,101,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,44,32,105,115,32,97,110,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,100,117,99,101,100,32,98,121,32,116,104,101,32,112,97,114,116,105,116,105,111,110,32,67,46>>]},{p,[],[<<73,102,32,82,32,105,115,32,97,110,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,32,88,44,32,116,104,101,32>>,{a,[{id,<<99,97,110,111,110,105,99,97,108,95,109,97,112>>}],[]},{em,[],[<<99,97,110,111,110,105,99,97,108,32,109,97,112>>]},<<32,105,115,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,109,97,112,115,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,111,102,32,88,32,111,110,116,111,32,105,116,115,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,46>>]}]},{li,[],[{p,[],[{a,[{id,<<98,105,110,97,114,121,95,114,101,108,97,116,105,111,110>>}],[]},<<82,101,108,97,116,105,111,110,115,32,97,115,32,100,101,102,105,110,101,100,32,97,98,111,118,101,32,40,97,115,32,115,101,116,115,32,111,102,32,111,114,100,101,114,101,100,32,112,97,105,114,115,41,32,97,114,101,32,102,114,111,109,32,110,111,119,32,111,110,32,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32>>,{em,[],[<<98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115>>]},<<46>>]},{p,[],[<<87,101,32,99,97,108,108,32,97,32,115,101,116,32,111,102,32,111,114,100,101,114,101,100,32,115,101,116,115,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,32,97,110,32>>,{a,[{id,<<110,95,97,114,121,95,114,101,108,97,116,105,111,110>>}],[]},{em,[],[<<40,110,45,97,114,121,41,32,114,101,108,97,116,105,111,110>>]},<<44,32,97,110,100,32,115,97,121,32,116,104,97,116,32,116,104,101,32,114,101,108,97,116,105,111,110,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32,116,104,101,32>>,{a,[{id,<<67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116,95,116,117,112,108,101>>}],[]},<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116,32,88,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,88,91,110,93,44,32,119,104,101,114,101,32,120,91,105,93,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,88,91,105,93,44,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<112,114,111,106,101,99,116,105,111,110>>}],[]},{em,[],[<<112,114,111,106,101,99,116,105,111,110>>]},<<32,111,102,32,97,110,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,32,82,32,111,110,116,111,32,99,111,111,114,100,105,110,97,116,101,32,105,32,105,115,32,116,104,101,32,115,101,116,32,123,120,91,105,93,194,160,58,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,105,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,32,105,110,32,82,32,102,111,114,32,115,111,109,101,32,120,91,106,93,194,160,105,110,194,160,88,91,106,93,44,32,49,194,160,60,61,194,160,106,194,160,60,61,194,160,110,32,97,110,100,32,110,111,116,32,105,194,160,61,194,160,106,125,46,32,84,104,101,32,112,114,111,106,101,99,116,105,111,110,115,32,111,102,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,82,32,111,110,116,111,32,116,104,101,32,102,105,114,115,116,32,97,110,100,32,115,101,99,111,110,100,32,99,111,111,114,100,105,110,97,116,101,115,32,97,114,101,32,116,104,101,32,100,111,109,97,105,110,32,97,110,100,32,116,104,101,32,114,97,110,103,101,32,111,102,32,82,44,32,114,101,115,112,101,99,116,105,118,101,108,121,46>>]},{p,[],[<<84,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,99,97,110,32,98,101,32,103,101,110,101,114,97,108,105,122,101,100,32,116,111,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,115,32,97,115,32,102,111,108,108,111,119,115,46,32,76,101,116,32,84,82,32,98,101,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,102,114,111,109,32,88,32,116,111,32,89,91,105,93,32,97,110,100,32,83,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,40,89,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,89,91,110,93,41,32,116,111,32,90,46,32,84,104,101,32>>,{a,[{id,<<116,117,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,84,82,32,97,110,100,32,83,32,105,115,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,84,32,102,114,111,109,32,88,32,116,111,32,90,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,194,160,84,194,160,122,32,105,102,32,97,110,100,32,111,110,108,121,32,105,102,32,116,104,101,114,101,32,101,120,105,115,116,115,32,97,110,32,101,108,101,109,101,110,116,32,121,91,105,93,32,105,110,32,89,91,105,93,32,102,111,114,32,101,97,99,104,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,32,115,117,99,104,32,116,104,97,116,32,120,194,160,82,91,105,93,194,160,121,91,105,93,32,97,110,100,32,40,121,91,49,93,44,194,160,46,46,46,44,194,160,121,91,110,93,41,194,160,83,194,160,122,46,32,78,111,119,32,108,101,116,32,84,82,32,98,101,32,97,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,102,114,111,109,32,88,91,105,93,32,116,111,32,89,91,105,93,32,97,110,100,32,83,32,97,32,115,117,98,115,101,116,32,111,102,32,88,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,88,91,110,93,46,32,84,104,101,32>>,{a,[{id,<<109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>}],[]},{em,[],[<<109,117,108,116,105,112,108,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,84,82,32,97,110,100,32,83,32,105,115,32,100,101,102,105,110,101,100,32,116,111,32,98,101,32,116,104,101,32,115,101,116,32,123,122,194,160,58,32,122,194,160,61,32,40,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,44,32,40,121,91,49,93,44,46,46,46,44,121,91,110,93,41,41,32,102,111,114,32,115,111,109,101,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,194,160,105,110,194,160,83,32,97,110,100,32,102,111,114,32,115,111,109,101,32,40,120,91,105,93,44,194,160,121,91,105,93,41,32,105,110,32,82,91,105,93,44,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,125,46>>]},{p,[],[<<84,104,101,32>>,{a,[{id,<<110,97,116,117,114,97,108,95,106,111,105,110>>}],[]},{em,[],[<<110,97,116,117,114,97,108,32,106,111,105,110>>]},<<32,111,102,32,97,110,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,32,82,32,97,110,100,32,97,110,32,109,45,97,114,121,32,114,101,108,97,116,105,111,110,32,83,32,111,110,32,99,111,111,114,100,105,110,97,116,101,32,105,32,97,110,100,32,106,32,105,115,32,100,101,102,105,110,101,100,32,116,111,32,98,101,32,116,104,101,32,115,101,116,32,123,122,194,160,58,32,122,194,160,61,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,44,194,160,32,121,91,49,93,44,194,160,46,46,46,44,194,160,121,91,106,45,49,93,44,194,160,121,91,106,43,49,93,44,194,160,46,46,46,44,194,160,121,91,109,93,41,32,102,111,114,32,115,111,109,101,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,194,160,105,110,194,160,82,32,97,110,100,32,102,111,114,32,115,111,109,101,32,40,121,91,49,93,44,194,160,46,46,46,44,194,160,121,91,109,93,41,194,160,105,110,194,160,83,32,115,117,99,104,32,116,104,97,116,32,120,91,105,93,194,160,61,194,160,121,91,106,93,125,46>>]}]},{li,[],[{p,[],[{a,[{id,<<115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>}],[]},<<84,104,101,32,115,101,116,115,32,114,101,99,111,103,110,105,122,101,100,32,98,121,32,116,104,105,115,32,109,111,100,117,108,101,32,97,114,101,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,114,101,108,97,116,105,111,110,32,83,101,116,115,44,32,119,104,105,99,104,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,116,104,101,32,115,109,97,108,108,101,115,116,32,115,101,116,32,115,117,99,104,32,116,104,97,116,58>>]},{ul,[],[{li,[],[{p,[],[<<70,111,114,32,101,118,101,114,121,32,97,116,111,109,32,84,44,32,101,120,99,101,112,116,32,39,95,39,44,32,97,110,100,32,102,111,114,32,101,118,101,114,121,32,116,101,114,109,32,88,44,32,40,84,44,194,160,88,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40>>,{em,[],[<<97,116,111,109,105,99,32,115,101,116,115>>]},<<41,46>>]}]},{li,[],[{p,[],[<<40,91,39,95,39,93,44,194,160,91,93,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40,116,104,101,32>>,{em,[],[<<117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116>>]},<<41,46>>]}]},{li,[],[{p,[],[<<70,111,114,32,101,118,101,114,121,32,116,117,112,108,101,32,84,194,160,61,32,123,84,91,49,93,44,194,160,46,46,46,44,194,160,84,91,110,93,125,32,97,110,100,32,102,111,114,32,101,118,101,114,121,32,116,117,112,108,101,32,88,194,160,61,32,123,88,91,49,93,44,194,160,46,46,46,44,194,160,88,91,110,93,125,44,32,105,102,32,40,84,91,105,93,44,194,160,88,91,105,93,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,102,111,114,32,101,118,101,114,121,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,44,32,116,104,101,110,32,40,84,44,194,160,88,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40>>,{em,[],[<<111,114,100,101,114,101,100,32,115,101,116,115>>]},<<41,46>>]}]},{li,[],[{p,[],[<<70,111,114,32,101,118,101,114,121,32,116,101,114,109,32,84,44,32,105,102,32,88,32,105,115,32,116,104,101,32,101,109,112,116,121,32,108,105,115,116,32,111,114,32,97,32,110,111,110,45,101,109,112,116,121,32,115,111,114,116,101,100,32,108,105,115,116,32,91,88,91,49,93,44,194,160,46,46,46,44,194,160,88,91,110,93,93,32,119,105,116,104,111,117,116,32,100,117,112,108,105,99,97,116,101,115,32,115,117,99,104,32,116,104,97,116,32,40,84,44,194,160,88,91,105,93,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,102,111,114,32,101,118,101,114,121,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,44,32,116,104,101,110,32,40,91,84,93,44,194,160,88,41,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,115,32,40>>,{em,[],[<<116,121,112,101,100,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115>>]},<<41,46>>]}]}]},{p,[],[<<65,110,32>>,{a,[{id,<<101,120,116,101,114,110,97,108,95,115,101,116>>}],[]},{em,[],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,83,101,116,115,46>>]},{p,[],[<<65,32>>,{a,[{id,<<116,121,112,101>>}],[]},{em,[],[<<116,121,112,101>>]},<<32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,83,101,116,115,46>>]},{p,[],[<<73,102,32,83,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,40,84,44,194,160,88,41,32,111,102,32,83,101,116,115,44,32,116,104,101,110,32,84,32,105,115,32,97,32>>,{a,[{id,<<118,97,108,105,100,95,116,121,112,101>>}],[]},{em,[],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,111,102,32,88,44,32,84,32,105,115,32,116,104,101,32,116,121,112,101,32,111,102,32,83,44,32,97,110,100,32,88,32,105,115,32,116,104,101,32,101,120,116,101,114,110,97,108,32,115,101,116,32,111,102,32,83,46,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,116,101,114,109,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,116,101,114,109,47,50>>]}]},<<32,99,114,101,97,116,101,115,32,97,32,115,101,116,32,102,114,111,109,32,97,32,116,121,112,101,32,97,110,100,32,97,110,32,69,114,108,97,110,103,32,116,101,114,109,32,116,117,114,110,101,100,32,105,110,116,111,32,97,110,32,101,120,116,101,114,110,97,108,32,115,101,116,46>>]},{p,[],[<<84,104,101,32,115,101,116,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,83,101,116,115,32,97,114,101,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,114,97,110,103,101,32,111,102,32,102,117,110,99,116,105,111,110,32,83,101,116,32,102,114,111,109,32,83,101,116,115,32,116,111,32,69,114,108,97,110,103,32,116,101,114,109,115,32,97,110,100,32,115,101,116,115,32,111,102,32,69,114,108,97,110,103,32,116,101,114,109,115,58>>]},{ul,[],[{li,[],[<<83,101,116,40,84,44,84,101,114,109,41,194,160,61,32,84,101,114,109,44,32,119,104,101,114,101,32,84,32,105,115,32,97,110,32,97,116,111,109>>]},{li,[],[<<83,101,116,40,123,84,91,49,93,44,194,160,46,46,46,44,194,160,84,91,110,93,125,44,194,160,123,88,91,49,93,44,194,160,46,46,46,44,32,194,160,88,91,110,93,125,41,194,160,61,32,40,83,101,116,40,84,91,49,93,44,194,160,88,91,49,93,41,44,194,160,46,46,46,44,194,160,32,83,101,116,40,84,91,110,93,44,194,160,88,91,110,93,41,41>>]},{li,[],[<<83,101,116,40,91,84,93,44,194,160,91,88,91,49,93,44,194,160,46,46,46,44,194,160,88,91,110,93,93,41,194,160,61,32,123,83,101,116,40,84,44,194,160,88,91,49,93,41,44,194,160,46,46,46,44,194,160,83,101,116,40,84,44,194,160,88,91,110,93,41,125>>]},{li,[],[<<83,101,116,40,91,84,93,44,194,160,91,93,41,194,160,61,32,123,125>>]}]},{p,[],[<<87,104,101,110,32,116,104,101,114,101,32,105,115,32,110,111,32,114,105,115,107,32,111,102,32,99,111,110,102,117,115,105,111,110,44,32,101,108,101,109,101,110,116,115,32,111,102,32,83,101,116,115,32,97,114,101,32,105,100,101,110,116,105,102,105,101,100,32,119,105,116,104,32,116,104,101,32,115,101,116,115,32,116,104,101,121,32,114,101,112,114,101,115,101,110,116,46,32,70,111,114,32,101,120,97,109,112,108,101,44,32,105,102,32,85,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,99,97,108,108,105,110,103,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<117,110,105,111,110,47,50>>]}]},<<32,119,105,116,104,32,83,49,32,97,110,100,32,83,50,32,97,115,32,97,114,103,117,109,101,110,116,115,44,32,116,104,101,110,32,85,32,105,115,32,115,97,105,100,32,116,111,32,98,101,32,116,104,101,32,117,110,105,111,110,32,111,102,32,83,49,32,97,110,100,32,83,50,46,32,65,32,109,111,114,101,32,112,114,101,99,105,115,101,32,102,111,114,109,117,108,97,116,105,111,110,32,105,115,32,116,104,97,116,32,83,101,116,40,85,41,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32,83,101,116,40,83,49,41,32,97,110,100,32,83,101,116,40,83,50,41,46>>]}]}]},{p,[],[<<84,104,101,32,116,121,112,101,115,32,97,114,101,32,117,115,101,100,32,116,111,32,105,109,112,108,101,109,101,110,116,32,116,104,101,32,118,97,114,105,111,117,115,32,99,111,110,100,105,116,105,111,110,115,32,116,104,97,116,32,115,101,116,115,32,109,117,115,116,32,102,117,108,102,105,108,108,46,32,65,115,32,97,110,32,101,120,97,109,112,108,101,44,32,99,111,110,115,105,100,101,114,32,116,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,116,119,111,32,115,101,116,115,32,82,32,97,110,100,32,83,44,32,97,110,100,32,114,101,99,97,108,108,32,116,104,97,116,32,116,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,32,111,102,32,82,32,97,110,100,32,83,32,105,115,32,100,101,102,105,110,101,100,32,105,102,32,82,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,116,111,32,89,32,97,110,100,32,83,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,89,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,105,109,112,108,101,109,101,110,116,115,32,116,104,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116,44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>]}]},<<44,32,99,104,101,99,107,115,32,116,104,97,116,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,114,101,112,114,101,115,101,110,116,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,98,121,32,109,97,116,99,104,105,110,103,32,91,123,65,44,66,125,93,32,97,103,97,105,110,115,116,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,32,40,65,114,103,49,32,115,97,121,41,44,32,97,110,100,32,91,123,67,44,68,125,93,32,97,103,97,105,110,115,116,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,40,65,114,103,50,32,115,97,121,41,46,32,84,104,101,32,102,97,99,116,32,116,104,97,116,32,91,123,65,44,66,125,93,32,109,97,116,99,104,101,115,32,116,104,101,32,116,121,112,101,32,111,102,32,65,114,103,49,32,105,115,32,116,111,32,98,101,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,65,114,103,49,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,88,32,116,111,32,89,44,32,119,104,101,114,101,32,88,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,97,108,108,32,115,101,116,115,32,83,101,116,40,120,41,32,102,111,114,32,115,111,109,101,32,101,108,101,109,101,110,116,32,120,32,105,110,32,83,101,116,115,32,116,104,101,32,116,121,112,101,32,111,102,32,119,104,105,99,104,32,105,115,32,65,44,32,97,110,100,32,115,105,109,105,108,97,114,108,121,32,102,111,114,32,89,46,32,73,110,32,116,104,101,32,115,97,109,101,32,119,97,121,32,65,114,103,50,32,105,115,32,105,110,116,101,114,112,114,101,116,101,100,32,97,115,32,114,101,112,114,101,115,101,110,116,105,110,103,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,114,111,109,32,87,32,116,111,32,90,46,32,70,105,110,97,108,108,121,32,105,116,32,105,115,32,99,104,101,99,107,101,100,32,116,104,97,116,32,66,32,109,97,116,99,104,101,115,32,67,44,32,119,104,105,99,104,32,105,115,32,115,117,102,102,105,99,105,101,110,116,32,116,111,32,101,110,115,117,114,101,32,116,104,97,116,32,87,32,105,115,32,101,113,117,97,108,32,116,111,32,89,46,32,84,104,101,32,117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116,32,105,115,32,104,97,110,100,108,101,100,32,115,101,112,97,114,97,116,101,108,121,58,32,105,116,115,32,116,121,112,101,44,32,91,39,95,39,93,44,32,109,97,116,99,104,101,115,32,116,104,101,32,116,121,112,101,32,111,102,32,97,110,121,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46>>]},{p,[],[<<65,32,102,101,119,32,102,117,110,99,116,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,32,40>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,114,101,115,116,114,105,99,116,105,111,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,114,101,115,116,114,105,99,116,105,111,110,47,51>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,97,114,116,105,116,105,111,110,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,114,111,106,101,99,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<112,114,111,106,101,99,116,105,111,110,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110,47,51>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,115,116,114,105,99,116,105,111,110,47,51>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,117,98,115,116,105,116,117,116,105,111,110,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,117,98,115,116,105,116,117,116,105,111,110,47,50>>]}]},<<41,32,97,99,99,101,112,116,32,97,110,32,69,114,108,97,110,103,32,102,117,110,99,116,105,111,110,32,97,115,32,97,32,109,101,97,110,115,32,116,111,32,109,111,100,105,102,121,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,97,32,103,105,118,101,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46,32>>,{a,[{id,<<115,101,116,95,102,117,110>>}],[]},<<83,117,99,104,32,97,32,102,117,110,99,116,105,111,110,44,32,99,97,108,108,101,100,32,83,101,116,70,117,110,32,105,110,32,116,104,101,32,102,111,108,108,111,119,105,110,103,44,32,99,97,110,32,98,101,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,102,117,110,99,116,105,111,110,97,108,32,111,98,106,101,99,116,32,40,102,117,110,41,44,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,194,160,70,117,110,125>>]},<<44,32,111,114,32,97,110,32,105,110,116,101,103,101,114,58>>]},{ul,[],[{li,[],[{p,[],[<<73,102,32,83,101,116,70,117,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,102,117,110,44,32,116,104,101,32,102,117,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,103,105,118,101,110,32,115,101,116,32,97,110,100,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,115,115,117,109,101,100,32,116,111,32,98,101,32,97,32,115,101,116,46>>]}]},{li,[],[{p,[],[<<73,102,32,83,101,116,70,117,110,32,105,115,32,115,112,101,99,105,102,105,101,100,32,97,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,32,70,117,110,125>>]},<<44,32,70,117,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32,101,120,116,101,114,110,97,108,32,115,101,116,32,111,102,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,103,105,118,101,110,32,115,101,116,32,97,110,100,32,116,104,101,32,114,101,116,117,114,110,32,118,97,108,117,101,32,105,115,32,97,115,115,117,109,101,100,32,116,111,32,98,101,32,97,110,32,101,120,116,101,114,110,97,108,32,115,101,116,46,32,83,101,108,101,99,116,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,97,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,97,115,32,101,120,116,101,114,110,97,108,32,115,101,116,115,32,97,110,100,32,97,115,115,101,109,98,108,105,110,103,32,97,32,110,101,119,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,102,114,111,109,32,97,32,108,105,115,116,32,111,102,32,101,120,116,101,114,110,97,108,32,115,101,116,115,32,105,115,32,105,110,32,116,104,101,32,112,114,101,115,101,110,116,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,32,116,104,97,110,32,109,111,100,105,102,121,105,110,103,32,101,97,99,104,32,101,108,101,109,101,110,116,32,97,115,32,97,32,115,101,116,46,32,72,111,119,101,118,101,114,44,32,116,104,105,115,32,111,112,116,105,109,105,122,97,116,105,111,110,32,99,97,110,32,111,110,108,121,32,98,101,32,117,115,101,100,32,119,104,101,110,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,97,114,101,32,97,116,111,109,105,99,32,111,114,32,111,114,100,101,114,101,100,32,115,101,116,115,46,32,73,116,32,109,117,115,116,32,97,108,115,111,32,98,101,32,116,104,101,32,99,97,115,101,32,116,104,97,116,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,101,108,101,109,101,110,116,115,32,109,97,116,99,104,101,115,32,115,111,109,101,32,99,108,97,117,115,101,32,111,102,32,70,117,110,32,40,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,99,114,101,97,116,101,100,32,115,101,116,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32,70,117,110,32,116,111,32,116,104,101,32,116,121,112,101,32,111,102,32,116,104,101,32,103,105,118,101,110,32,115,101,116,41,44,32,97,110,100,32,116,104,97,116,32,70,117,110,32,100,111,101,115,32,110,111,116,104,105,110,103,32,98,117,116,32,115,101,108,101,99,116,105,110,103,44,32,100,117,112,108,105,99,97,116,105,110,103,44,32,111,114,32,114,101,97,114,114,97,110,103,105,110,103,32,112,97,114,116,115,32,111,102,32,116,104,101,32,101,108,101,109,101,110,116,115,46>>]}]},{li,[],[{p,[],[<<83,112,101,99,105,102,121,105,110,103,32,97,32,83,101,116,70,117,110,32,97,115,32,97,110,32,105,110,116,101,103,101,114,32,73,32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115,112,101,99,105,102,121,105,110,103,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,88,41,194,160,45,62,32,101,108,101,109,101,110,116,40,73,44,194,160,88,41,194,160,101,110,100,125>>]},<<44,32,98,117,116,32,105,115,32,116,111,32,98,101,32,112,114,101,102,101,114,114,101,100,44,32,97,115,32,105,116,32,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,108,101,32,116,111,32,104,97,110,100,108,101,32,116,104,105,115,32,99,97,115,101,32,101,118,101,110,32,109,111,114,101,32,101,102,102,105,99,105,101,110,116,108,121,46>>]}]}]},{p,[],[<<69,120,97,109,112,108,101,115,32,111,102,32,83,101,116,70,117,110,115,58>>]},{pre,[],[{code,[],[<<102,117,110,32,115,111,102,115,58,117,110,105,111,110,47,49,10,102,117,110,40,83,41,32,45,62,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,49,44,32,83,41,32,101,110,100,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,65,41,32,45,62,32,65,32,101,110,100,125,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,65,44,95,44,67,125,41,32,45,62,32,123,67,44,65,125,32,101,110,100,125,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,95,44,123,95,44,67,125,125,41,32,45,62,32,67,32,101,110,100,125,10,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,95,44,123,95,44,123,95,44,69,125,61,67,125,125,41,32,45,62,32,123,69,44,123,69,44,67,125,125,32,101,110,100,125,10,50>>]}]},{p,[],[<<84,104,101,32,111,114,100,101,114,32,105,110,32,119,104,105,99,104,32,97,32,83,101,116,70,117,110,32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,97,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32,105,115,32,110,111,116,32,115,112,101,99,105,102,105,101,100,44,32,97,110,100,32,99,97,110,32,99,104,97,110,103,101,32,105,110,32,102,117,116,117,114,101,32,118,101,114,115,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,46>>]},{p,[],[<<84,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,32,105,115,32,100,111,109,105,110,97,116,101,100,32,98,121,32,116,104,101,32,116,105,109,101,32,105,116,32,116,97,107,101,115,32,116,111,32,115,111,114,116,32,108,105,115,116,115,46,32,87,104,101,110,32,110,111,32,115,111,114,116,105,110,103,32,105,115,32,110,101,101,100,101,100,44,32,116,104,101,32,101,120,101,99,117,116,105,111,110,32,116,105,109,101,32,105,115,32,105,110,32,116,104,101,32,119,111,114,115,116,32,99,97,115,101,32,112,114,111,112,111,114,116,105,111,110,97,108,32,116,111,32,116,104,101,32,115,117,109,32,111,102,32,116,104,101,32,115,105,122,101,115,32,111,102,32,116,104,101,32,105,110,112,117,116,32,97,114,103,117,109,101,110,116,115,32,97,110,100,32,116,104,101,32,114,101,116,117,114,110,101,100,32,118,97,108,117,101,46,32,65,32,102,101,119,32,102,117,110,99,116,105,111,110,115,32,101,120,101,99,117,116,101,32,105,110,32,99,111,110,115,116,97,110,116,32,116,105,109,101,58,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,115,95,101,109,112,116,121,95,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,101,109,112,116,121,95,115,101,116,47,49>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,115,95,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,115,101,116,47,49>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,115,95,115,111,102,115,95,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,115,95,115,111,102,115,95,115,101,116,47,49>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,111,95,101,120,116,101,114,110,97,108,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,111,95,101,120,116,101,114,110,97,108,47,49>>]}]},<<32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<116,121,112,101,47,49>>]}]},<<46>>]},{p,[],[<<84,104,101,32,102,117,110,99,116,105,111,110,115,32,111,102,32,116,104,105,115,32,109,111,100,117,108,101,32,101,120,105,116,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<44,32>>,{code,[],[<<98,97,100,95,102,117,110,99,116,105,111,110>>]},<<44,32,111,114,32>>,{code,[],[<<116,121,112,101,95,109,105,115,109,97,116,99,104>>]},<<32,109,101,115,115,97,103,101,32,119,104,101,110,32,103,105,118,101,110,32,98,97,100,108,121,32,102,111,114,109,101,100,32,97,114,103,117,109,101,110,116,115,32,111,114,32,115,101,116,115,32,116,104,101,32,116,121,112,101,115,32,111,102,32,119,104,105,99,104,32,97,114,101,32,110,111,116,32,99,111,109,112,97,116,105,98,108,101,46>>]},{p,[],[<<87,104,101,110,32,99,111,109,112,97,114,105,110,103,32,101,120,116,101,114,110,97,108,32,115,101,116,115,44,32,111,112,101,114,97,116,111,114,32>>,{code,[],[<<61,61,47,50>>]},<<32,105,115,32,117,115,101,100,46>>]},{h2,[],[<<83,101,101,32,65,108,115,111>>]},{p,[],[{a,[{href,<<115,116,100,108,105,98,58,100,105,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,99,116,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,100,105,103,114,97,112,104>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<100,105,103,114,97,112,104,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,111,114,100,100,105,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,114,100,100,105,99,116,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,111,114,100,115,101,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<111,114,100,115,101,116,115,40,51,41>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,101,116,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[{code,[],[<<115,101,116,115,40,51,41>>]}]}]}]},#{name => <<115,111,102,115>>,otp_doc_vsn => {1,0,0},source => [46,46,47,120,109,108,47,115,111,102,115,46,120,109,108],types => #{{a_function,0} => {attribute,{120,2},type,{a_function,{user_type,{120,23},relation,[]},[]}},{a_set,0} => {attribute,{124,2},opaque,{a_set,{type,{124,20},record,[{atom,{124,22},'Set'}]},[]}},{anyset,0} => {attribute,{117,2},type,{anyset,{type,{117,19},union,[{user_type,{117,19},ordset,[]},{user_type,{117,30},a_set,[]}]},[]}},{binary_relation,0} => {attribute,{118,2},type,{binary_relation,{user_type,{118,28},relation,[]},[]}},{external_set,0} => {attribute,{119,2},type,{external_set,{type,{119,25},term,[]},[]}},{family,0} => {attribute,{121,2},type,{family,{user_type,{121,19},a_function,[]},[]}},{ordset,0} => {attribute,{122,2},opaque,{ordset,{type,{122,21},record,[{atom,{122,23},'OrdSet'}]},[]}},{relation,0} => {attribute,{123,2},type,{relation,{user_type,{123,21},a_set,[]},[]}},{set_fun,0} => {attribute,{126,2},type,{set_fun,{type,{126,20},union,[{type,{126,20},pos_integer,[]},{type,{127,20},tuple,[{atom,{127,21},external},{type,{127,35},'fun',[{type,{127,35},product,[{user_type,{127,36},external_set,[]}]},{user_type,{127,55},external_set,[]}]}]},{type,{128,24},'fun',[{type,{128,24},product,[{user_type,{128,25},anyset,[]}]},{user_type,{128,38},anyset,[]}]}]},[]}},{set_of_sets,0} => {attribute,{125,2},type,{set_of_sets,{user_type,{125,24},a_set,[]},[]}},{spec_fun,0} => {attribute,{129,2},type,{spec_fun,{type,{129,21},union,[{type,{129,21},tuple,[{atom,{129,22},external},{type,{129,36},'fun',[{type,{129,36},product,[{user_type,{129,37},external_set,[]}]},{type,{129,56},boolean,[]}]}]},{type,{130,25},'fun',[{type,{130,25},product,[{user_type,{130,26},anyset,[]}]},{type,{130,39},boolean,[]}]}]},[]}},{tuple_of,1} => {attribute,{133,2},type,{tuple_of,{type,{133,23},tuple,any},[{var,{133,16},'_T'}]}},{type,0} => {attribute,{131,2},type,{type,{type,{131,17},term,[]},[]}}}},[{{function,fam2rel,1},[{file,[115,111,102,115,46,101,114,108]},{location,0}],[<<102,97,109,50,114,101,108,47,49>>],hidden,#{}},{{function,rel2fam,1},[{file,[115,111,102,115,46,101,114,108]},{location,0}],[<<114,101,108,50,102,97,109,47,49>>],hidden,#{}},{{function,a_function,2},[{file,[115,111,102,115,46,101,114,108]},{location,277}],[<<97,95,102,117,110,99,116,105,111,110,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,53,56>>,equiv => {function,a_function,1},signature => [{attribute,{277,2},spec,{{a_function,2},[{type,{277,17},bounded_fun,[{type,{277,17},'fun',[{type,{277,17},product,[{var,{277,18},'Tuples'},{var,{277,26},'Type'}]},{var,{277,35},'Function'}]},[{type,{278,7},constraint,[{atom,{278,7},is_subtype},[{var,{278,7},'Function'},{user_type,{278,19},a_function,[]}]]},{type,{279,7},constraint,[{atom,{279,7},is_subtype},[{var,{279,7},'Tuples'},{type,{279,17},list,[{type,{279,18},tuple,any}]}]]},{type,{280,7},constraint,[{atom,{280,7},is_subtype},[{var,{280,7},'Type'},{user_type,{280,15},type,[]}]]}]]}]}}]}},{{function,a_function,1},[{file,[115,111,102,115,46,101,114,108]},{location,265}],[<<97,95,102,117,110,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<46,32>>,{code,[],[<<97,95,102,117,110,99,116,105,111,110,40,70,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,70,44,194,160,84,41>>]},<<32,105,102,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,102,117,110,99,116,105,111,110,46,32,73,102,32,110,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<91,123,97,116,111,109,44,194,160,97,116,111,109,125,93>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,121,112,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,53,56>>,signature => [{attribute,{265,2},spec,{{a_function,1},[{type,{265,17},bounded_fun,[{type,{265,17},'fun',[{type,{265,17},product,[{var,{265,18},'Tuples'}]},{var,{265,29},'Function'}]},[{type,{266,7},constraint,[{atom,{266,7},is_subtype},[{var,{266,7},'Function'},{user_type,{266,19},a_function,[]}]]},{type,{267,7},constraint,[{atom,{267,7},is_subtype},[{var,{267,7},'Tuples'},{type,{267,17},list,[{type,{267,18},tuple,any}]}]]}]]}]}}]}},{{function,canonical_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,577}],[<<99,97,110,111,110,105,99,97,108,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,40,69,44,194,160,83,101,116,41,32,115,117,99,104,32,116,104,97,116,32,83,101,116,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,97,110,100,32,69,32,98,101,108,111,110,103,115,32,116,111,32,83,101,116,46,32,73,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32,97,32,115,101,116,32,88,32,97,110,100,32,82,32,105,115,32,116,104,101,32,101,113,117,105,118,97,108,101,110,99,101,32,114,101,108,97,116,105,111,110,32,105,110,32,88,32,105,110,100,117,99,101,100,32,98,121,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<44,32,116,104,101,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,114,101,108,97,116,105,111,110,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,97,110,111,110,105,99,97,108,95,109,97,112>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,97,110,111,110,105,99,97,108,32,109,97,112>>]},<<32,102,114,111,109,32,88,32,111,110,116,111,32,116,104,101,32,101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115,101,115,32,119,105,116,104,32,114,101,115,112,101,99,116,32,116,111,32,82,46>>]},{pre,[],[{code,[],[<<49,62,32,83,115,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,97,44,98,93,44,91,98,44,99,93,93,41,44,10,67,82,32,61,32,115,111,102,115,58,99,97,110,111,110,105,99,97,108,95,114,101,108,97,116,105,111,110,40,83,115,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,67,82,41,46,10,91,123,97,44,91,97,44,98,93,125,44,123,98,44,91,97,44,98,93,125,44,123,98,44,91,98,44,99,93,125,44,123,99,44,91,98,44,99,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,55,50>>,signature => [{attribute,{577,2},spec,{{canonical_relation,1},[{type,{577,25},bounded_fun,[{type,{577,25},'fun',[{type,{577,25},product,[{var,{577,26},'SetOfSets'}]},{var,{577,40},'BinRel'}]},[{type,{578,7},constraint,[{atom,{578,7},is_subtype},[{var,{578,7},'BinRel'},{user_type,{578,17},binary_relation,[]}]]},{type,{579,7},constraint,[{atom,{579,7},is_subtype},[{var,{579,7},'SetOfSets'},{user_type,{579,20},set_of_sets,[]}]]}]]}]}}]}},{{function,composite,2},[{file,[115,111,102,115,46,101,114,108]},{location,844}],[<<99,111,109,112,111,115,105,116,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,111,109,112,111,115,105,116,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,109,112,111,115,105,116,101>>]},<<32,111,102,32,116,104,101,32,102,117,110,99,116,105,111,110,115,32>>,{code,[],[<<70,117,110,99,116,105,111,110,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,117,110,99,116,105,111,110,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,97,95,102,117,110,99,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,44,123,99,44,50,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,97,95,102,117,110,99,116,105,111,110,40,91,123,49,44,120,125,44,123,50,44,121,125,44,123,51,44,122,125,93,41,44,10,70,32,61,32,115,111,102,115,58,99,111,109,112,111,115,105,116,101,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,120,125,44,123,98,44,121,125,44,123,99,44,121,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,52,57,50>>,signature => [{attribute,{844,2},spec,{{composite,2},[{type,{844,16},bounded_fun,[{type,{844,16},'fun',[{type,{844,16},product,[{var,{844,17},'Function1'},{var,{844,28},'Function2'}]},{var,{844,42},'Function3'}]},[{type,{845,7},constraint,[{atom,{845,7},is_subtype},[{var,{845,7},'Function1'},{user_type,{845,20},a_function,[]}]]},{type,{846,7},constraint,[{atom,{846,7},is_subtype},[{var,{846,7},'Function2'},{user_type,{846,20},a_function,[]}]]},{type,{847,7},constraint,[{atom,{847,7},is_subtype},[{var,{847,7},'Function3'},{user_type,{847,20},a_function,[]}]]}]]}]}}]}},{{function,constant_function,2},[{file,[115,111,102,115,46,101,114,108]},{location,465}],[<<99,111,110,115,116,97,110,116,95,102,117,110,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<32,116,104,97,116,32,109,97,112,115,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32,115,101,116,32>>,{code,[],[<<83,101,116>>]},<<32,111,110,116,111,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,115,101,116,40,91,97,44,98,93,41,44,10,69,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,49,41,44,10,82,32,61,32,115,111,102,115,58,99,111,110,115,116,97,110,116,95,102,117,110,99,116,105,111,110,40,83,44,32,69,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,41,46,10,91,123,97,44,49,125,44,123,98,44,49,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,48,56>>,signature => [{attribute,{465,2},spec,{{constant_function,2},[{type,{465,24},bounded_fun,[{type,{465,24},'fun',[{type,{465,24},product,[{var,{465,25},'Set'},{var,{465,30},'AnySet'}]},{var,{465,41},'Function'}]},[{type,{466,7},constraint,[{atom,{466,7},is_subtype},[{var,{466,7},'AnySet'},{user_type,{466,17},anyset,[]}]]},{type,{467,7},constraint,[{atom,{467,7},is_subtype},[{var,{467,7},'Function'},{user_type,{467,19},a_function,[]}]]},{type,{468,7},constraint,[{atom,{468,7},is_subtype},[{var,{468,7},'Set'},{user_type,{468,14},a_set,[]}]]}]]}]}}]}},{{function,converse,1},[{file,[115,111,102,115,46,101,114,108]},{location,707}],[<<99,111,110,118,101,114,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,111,110,118,101,114,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,110,118,101,114,115,101>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,97,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,99,111,110,118,101,114,115,101,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,97,44,49,125,44,123,97,44,51,125,44,123,98,44,50,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,50,52>>,signature => [{attribute,{707,2},spec,{{converse,1},[{type,{707,15},bounded_fun,[{type,{707,15},'fun',[{type,{707,15},product,[{var,{707,16},'BinRel1'}]},{var,{707,28},'BinRel2'}]},[{type,{708,7},constraint,[{atom,{708,7},is_subtype},[{var,{708,7},'BinRel1'},{user_type,{708,18},binary_relation,[]}]]},{type,{709,7},constraint,[{atom,{709,7},is_subtype},[{var,{709,7},'BinRel2'},{user_type,{709,18},binary_relation,[]}]]}]]}]}}]}},{{function,difference,2},[{file,[115,111,102,115,46,101,114,108]},{location,398}],[<<100,105,102,102,101,114,101,110,99,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,105,102,102,101,114,101,110,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,102,102,101,114,101,110,99,101>>]},<<32,111,102,32,116,104,101,32,115,101,116,115,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,51,56>>,signature => [{attribute,{398,2},spec,{{difference,2},[{type,{398,17},bounded_fun,[{type,{398,17},'fun',[{type,{398,17},product,[{var,{398,18},'Set1'},{var,{398,24},'Set2'}]},{var,{398,33},'Set3'}]},[{type,{399,7},constraint,[{atom,{399,7},is_subtype},[{var,{399,7},'Set1'},{user_type,{399,15},a_set,[]}]]},{type,{400,7},constraint,[{atom,{400,7},is_subtype},[{var,{400,7},'Set2'},{user_type,{400,15},a_set,[]}]]},{type,{401,7},constraint,[{atom,{401,7},is_subtype},[{var,{401,7},'Set3'},{user_type,{401,15},a_set,[]}]]}]]}]}}]}},{{function,digraph_to_family,2},[{file,[115,111,102,115,46,101,114,108]},{location,1520}],[<<100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,52,55>>,equiv => {function,digraph_to_family,1},signature => [{attribute,{1520,2},spec,{{digraph_to_family,2},[{type,{1520,24},bounded_fun,[{type,{1520,24},'fun',[{type,{1520,24},product,[{var,{1520,25},'Graph'},{var,{1520,32},'Type'}]},{var,{1520,41},'Family'}]},[{type,{1521,7},constraint,[{atom,{1521,7},is_subtype},[{var,{1521,7},'Graph'},{remote_type,{1521,16},[{atom,{1521,16},digraph},{atom,{1521,24},graph},[]]}]]},{type,{1522,7},constraint,[{atom,{1522,7},is_subtype},[{var,{1522,7},'Family'},{user_type,{1522,17},family,[]}]]},{type,{1523,7},constraint,[{atom,{1523,7},is_subtype},[{var,{1523,7},'Type'},{user_type,{1523,15},type,[]}]]}]]}]}}]}},{{function,digraph_to_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,1511}],[<<100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,102,114,111,109,32,116,104,101,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,32>>,{code,[],[<<71,114,97,112,104>>]},<<46,32,69,97,99,104,32,118,101,114,116,101,120,32,97,32,111,102,32>>,{code,[],[<<71,114,97,112,104>>]},<<32,105,115,32,114,101,112,114,101,115,101,110,116,101,100,32,98,121,32,97,32,112,97,105,114,32,40,97,44,194,160,123,98,91,49,93,44,194,160,46,46,46,44,194,160,98,91,110,93,125,41,44,32,119,104,101,114,101,32,116,104,101,32,98,91,105,93,58,115,32,97,114,101,32,116,104,101,32,111,117,116,45,110,101,105,103,104,98,111,114,115,32,111,102,32,97,46,32,73,102,32,110,111,32,116,121,112,101,32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32,91,123,97,116,111,109,44,194,160,91,97,116,111,109,93,125,93,32,105,115,32,117,115,101,100,32,97,115,32,116,121,112,101,32,111,102,32,116,104,101,32,102,97,109,105,108,121,46,32,73,116,32,105,115,32,97,115,115,117,109,101,100,32,116,104,97,116,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,118,97,108,105,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,111,102,32,116,104,101,32,101,120,116,101,114,110,97,108,32,115,101,116,32,111,102,32,116,104,101,32,102,97,109,105,108,121,46>>]},{p,[],[<<73,102,32,71,32,105,115,32,97,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,44,32,105,116,32,104,111,108,100,115,32,116,104,97,116,32,116,104,101,32,118,101,114,116,105,99,101,115,32,97,110,100,32,101,100,103,101,115,32,111,102,32,71,32,97,114,101,32,116,104,101,32,115,97,109,101,32,97,115,32,116,104,101,32,118,101,114,116,105,99,101,115,32,97,110,100,32,101,100,103,101,115,32,111,102,32>>,{code,[],[<<102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,40,100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,40,71,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,52,55>>,signature => [{attribute,{1511,2},spec,{{digraph_to_family,1},[{type,{1511,24},bounded_fun,[{type,{1511,24},'fun',[{type,{1511,24},product,[{var,{1511,25},'Graph'}]},{var,{1511,35},'Family'}]},[{type,{1512,7},constraint,[{atom,{1512,7},is_subtype},[{var,{1512,7},'Graph'},{remote_type,{1512,16},[{atom,{1512,16},digraph},{atom,{1512,24},graph},[]]}]]},{type,{1513,7},constraint,[{atom,{1513,7},is_subtype},[{var,{1513,7},'Family'},{user_type,{1513,17},family,[]}]]}]]}]}}]}},{{function,domain,1},[{file,[115,111,102,115,46,101,114,108]},{location,612}],[<<100,111,109,97,105,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,98,125,44,123,50,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,100,111,109,97,105,110,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,49,44,50,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,54,55>>,signature => [{attribute,{612,2},spec,{{domain,1},[{type,{612,13},bounded_fun,[{type,{612,13},'fun',[{type,{612,13},product,[{var,{612,14},'BinRel'}]},{var,{612,25},'Set'}]},[{type,{613,7},constraint,[{atom,{613,7},is_subtype},[{var,{613,7},'BinRel'},{user_type,{613,17},binary_relation,[]}]]},{type,{614,7},constraint,[{atom,{614,7},is_subtype},[{var,{614,7},'Set'},{user_type,{614,14},a_set,[]}]]}]]}]}}]}},{{function,drestriction,2},[{file,[115,111,102,115,46,101,114,108]},{location,833}],[<<100,114,101,115,116,114,105,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,101,116,119,101,101,110,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,97,110,100,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,116,111,32>>,{code,[],[<<83,101,116>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,50,44,52,44,54,93,41,44,10,82,50,32,61,32,115,111,102,115,58,100,114,101,115,116,114,105,99,116,105,111,110,40,82,49,44,32,83,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,97,125,44,123,51,44,99,125,93>>]}]},{p,[],[{code,[],[<<100,114,101,115,116,114,105,99,116,105,111,110,40,82,44,194,160,83,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<100,105,102,102,101,114,101,110,99,101,40,82,44,194,160,114,101,115,116,114,105,99,116,105,111,110,40,82,44,194,160,83,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,53,56,49>>,signature => [{attribute,{833,2},spec,{{drestriction,2},[{type,{833,19},bounded_fun,[{type,{833,19},'fun',[{type,{833,19},product,[{var,{833,20},'BinRel1'},{var,{833,29},'Set'}]},{var,{833,37},'BinRel2'}]},[{type,{834,7},constraint,[{atom,{834,7},is_subtype},[{var,{834,7},'BinRel1'},{user_type,{834,18},binary_relation,[]}]]},{type,{835,7},constraint,[{atom,{835,7},is_subtype},[{var,{835,7},'BinRel2'},{user_type,{835,18},binary_relation,[]}]]},{type,{836,7},constraint,[{atom,{836,7},is_subtype},[{var,{836,7},'Set'},{user_type,{836,14},a_set,[]}]]}]]}]}}]}},{{function,drestriction,3},[{file,[115,111,102,115,46,101,114,108]},{location,960}],[<<100,114,101,115,116,114,105,99,116,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,100,111,32,110,111,116,32,103,105,118,101,32,97,110,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<83,101,116,50>>]},<<32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,101,116,70,117,110,32,61,32,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,95,65,44,66,44,67,125,41,32,45,62,32,123,66,44,67,125,32,101,110,100,125,44,10,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,97,97,44,49,125,44,123,98,44,98,98,44,50,125,44,123,99,44,99,99,44,51,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,98,98,44,50,125,44,123,99,99,44,51,125,44,123,100,100,44,52,125,93,41,44,10,82,51,32,61,32,115,111,102,115,58,100,114,101,115,116,114,105,99,116,105,111,110,40,83,101,116,70,117,110,44,32,82,49,44,32,82,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,51,41,46,10,91,123,97,44,97,97,44,49,125,93>>]}]},{p,[],[{code,[],[<<100,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<100,105,102,102,101,114,101,110,99,101,40,83,49,44,194,160,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,48,48>>,signature => [{attribute,{960,2},spec,{{drestriction,3},[{type,{960,19},bounded_fun,[{type,{960,19},'fun',[{type,{960,19},product,[{var,{960,20},'SetFun'},{var,{960,28},'Set1'},{var,{960,34},'Set2'}]},{var,{960,43},'Set3'}]},[{type,{961,7},constraint,[{atom,{961,7},is_subtype},[{var,{961,7},'SetFun'},{user_type,{961,17},set_fun,[]}]]},{type,{962,7},constraint,[{atom,{962,7},is_subtype},[{var,{962,7},'Set1'},{user_type,{962,15},a_set,[]}]]},{type,{963,7},constraint,[{atom,{963,7},is_subtype},[{var,{963,7},'Set2'},{user_type,{963,15},a_set,[]}]]},{type,{964,7},constraint,[{atom,{964,7},is_subtype},[{var,{964,7},'Set3'},{user_type,{964,15},a_set,[]}]]}]]}]}}]}},{{function,empty_set,0},[{file,[115,111,102,115,46,101,114,108]},{location,178}],[<<101,109,112,116,121,95,115,101,116,47,48>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116>>]},<<46,32>>,{code,[],[<<101,109,112,116,121,95,115,101,116,40,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,91,93,44,194,160,91,39,95,39,93,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,50,48>>,signature => [{attribute,{178,2},spec,{{empty_set,0},[{type,{178,16},bounded_fun,[{type,{178,16},'fun',[{type,{178,16},product,[]},{var,{178,22},'Set'}]},[{type,{179,7},constraint,[{atom,{179,7},is_subtype},[{var,{179,7},'Set'},{user_type,{179,14},a_set,[]}]]}]]}]}}]}},{{function,extension,3},[{file,[115,111,102,115,46,101,114,108]},{location,779}],[<<101,120,116,101,110,115,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,110,115,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,110,115,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,115,117,99,104,32,116,104,97,116,32,102,111,114,32,101,97,99,104,32,101,108,101,109,101,110,116,32,69,32,105,110,32>>,{code,[],[<<83,101,116>>]},<<32,116,104,97,116,32,100,111,101,115,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<44,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,112,97,105,114,32,40,69,44,194,160>>,{code,[],[<<65,110,121,83,101,116>>]},<<41,46>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,115,101,116,40,91,98,44,99,93,41,44,10,65,32,61,32,115,111,102,115,58,101,109,112,116,121,95,115,101,116,40,41,44,10,82,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,93,125,93,41,44,10,88,32,61,32,115,111,102,115,58,101,120,116,101,110,115,105,111,110,40,82,44,32,83,44,32,65,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,88,41,46,10,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,93,125,44,123,99,44,91,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,51,48>>,signature => [{attribute,{779,2},spec,{{extension,3},[{type,{779,16},bounded_fun,[{type,{779,16},'fun',[{type,{779,16},product,[{var,{779,17},'BinRel1'},{var,{779,26},'Set'},{var,{779,31},'AnySet'}]},{var,{779,42},'BinRel2'}]},[{type,{780,7},constraint,[{atom,{780,7},is_subtype},[{var,{780,7},'AnySet'},{user_type,{780,17},anyset,[]}]]},{type,{781,7},constraint,[{atom,{781,7},is_subtype},[{var,{781,7},'BinRel1'},{user_type,{781,18},binary_relation,[]}]]},{type,{782,7},constraint,[{atom,{782,7},is_subtype},[{var,{782,7},'BinRel2'},{user_type,{782,18},binary_relation,[]}]]},{type,{783,7},constraint,[{atom,{783,7},is_subtype},[{var,{783,7},'Set'},{user_type,{783,14},a_set,[]}]]}]]}]}}]}},{{function,family,2},[{file,[115,111,102,115,46,101,114,108]},{location,302}],[<<102,97,109,105,108,121,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,53,48>>,equiv => {function,family,1},signature => [{attribute,{302,2},spec,{{family,2},[{type,{302,13},bounded_fun,[{type,{302,13},'fun',[{type,{302,13},product,[{var,{302,14},'Tuples'},{var,{302,22},'Type'}]},{var,{302,31},'Family'}]},[{type,{303,7},constraint,[{atom,{303,7},is_subtype},[{var,{303,7},'Family'},{user_type,{303,17},family,[]}]]},{type,{304,7},constraint,[{atom,{304,7},is_subtype},[{var,{304,7},'Tuples'},{type,{304,17},list,[{type,{304,18},tuple,any}]}]]},{type,{305,7},constraint,[{atom,{305,7},is_subtype},[{var,{305,7},'Type'},{user_type,{305,15},type,[]}]]}]]}]}}]}},{{function,family,1},[{file,[115,111,102,115,46,101,114,108]},{location,290}],[<<102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121,32,111,102,32,115,117,98,115,101,116,115>>]},<<46,32>>,{code,[],[<<102,97,109,105,108,121,40,70,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,70,44,194,160,84,41>>]},<<32,105,102,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,102,97,109,105,108,121,46,32,73,102,32,110,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<91,123,97,116,111,109,44,194,160,91,97,116,111,109,93,125,93>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,102,97,109,105,108,121,32,116,121,112,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,53,48>>,signature => [{attribute,{290,2},spec,{{family,1},[{type,{290,13},bounded_fun,[{type,{290,13},'fun',[{type,{290,13},product,[{var,{290,14},'Tuples'}]},{var,{290,25},'Family'}]},[{type,{291,7},constraint,[{atom,{291,7},is_subtype},[{var,{291,7},'Family'},{user_type,{291,17},family,[]}]]},{type,{292,7},constraint,[{atom,{292,7},is_subtype},[{var,{292,7},'Tuples'},{type,{292,17},list,[{type,{292,18},tuple,any}]}]]}]]}]}}]}},{{function,family_difference,2},[{file,[115,111,102,115,46,101,114,108]},{location,1385}],[<<102,97,109,105,108,121,95,100,105,102,102,101,114,101,110,99,101,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,105,101,115>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,101,113,117,97,108,32,116,111,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<91,105,93,32,105,115,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,101,116,119,101,101,110,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,102,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,109,97,112,115,32,105,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,97,109,105,108,121,49,91,105,93>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,98,44,91,52,44,53,93,125,44,123,99,44,91,54,44,55,93,125,93,41,44,10,70,51,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,100,105,102,102,101,114,101,110,99,101,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,51,41,46,10,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,54,52>>,signature => [{attribute,{1385,2},spec,{{family_difference,2},[{type,{1385,24},bounded_fun,[{type,{1385,24},'fun',[{type,{1385,24},product,[{var,{1385,25},'Family1'},{var,{1385,34},'Family2'}]},{var,{1385,46},'Family3'}]},[{type,{1386,7},constraint,[{atom,{1386,7},is_subtype},[{var,{1386,7},'Family1'},{user_type,{1386,18},family,[]}]]},{type,{1387,7},constraint,[{atom,{1387,7},is_subtype},[{var,{1387,7},'Family2'},{user_type,{1387,18},family,[]}]]},{type,{1388,7},constraint,[{atom,{1388,7},is_subtype},[{var,{1388,7},'Family3'},{user_type,{1388,18},family,[]}]]}]]}]}}]}},{{function,family_domain,1},[{file,[115,111,102,115,46,101,114,108]},{location,1341}],[<<102,97,109,105,108,121,95,100,111,109,97,105,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49,91,105,93>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,82,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,125,44,123,98,44,91,93,125,44,123,99,44,91,123,52,44,100,125,44,123,53,44,101,125,93,125,93,41,44,10,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,100,111,109,97,105,110,40,70,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,93,125,44,123,99,44,91,52,44,53,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,54,56,53>>,signature => [{attribute,{1341,2},spec,{{family_domain,1},[{type,{1341,20},bounded_fun,[{type,{1341,20},'fun',[{type,{1341,20},product,[{var,{1341,21},'Family1'}]},{var,{1341,33},'Family2'}]},[{type,{1342,7},constraint,[{atom,{1342,7},is_subtype},[{var,{1342,7},'Family1'},{user_type,{1342,18},family,[]}]]},{type,{1343,7},constraint,[{atom,{1343,7},is_subtype},[{var,{1343,7},'Family2'},{user_type,{1343,18},family,[]}]]}]]}]}}]}},{{function,family_field,1},[{file,[115,111,102,115,46,101,114,108]},{location,1365}],[<<102,97,109,105,108,121,95,102,105,101,108,100,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,105,101,108,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,101,108,100>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,82,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,125,44,123,98,44,91,93,125,44,123,99,44,91,123,52,44,100,125,44,123,53,44,101,125,93,125,93,41,44,10,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,102,105,101,108,100,40,70,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,91,49,44,50,44,51,44,97,44,98,44,99,93,125,44,123,98,44,91,93,125,44,123,99,44,91,52,44,53,44,100,44,101,93,125,93>>]}]},{p,[],[{code,[],[<<102,97,109,105,108,121,95,102,105,101,108,100,40,70,97,109,105,108,121,49,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,97,109,105,108,121,95,117,110,105,111,110,40,102,97,109,105,108,121,95,100,111,109,97,105,110,40,70,97,109,105,108,121,49,41,44,32,102,97,109,105,108,121,95,114,97,110,103,101,40,70,97,109,105,108,121,49,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,48,54>>,signature => [{attribute,{1365,2},spec,{{family_field,1},[{type,{1365,19},bounded_fun,[{type,{1365,19},'fun',[{type,{1365,19},product,[{var,{1365,20},'Family1'}]},{var,{1365,32},'Family2'}]},[{type,{1366,7},constraint,[{atom,{1366,7},is_subtype},[{var,{1366,7},'Family1'},{user_type,{1366,18},family,[]}]]},{type,{1367,7},constraint,[{atom,{1367,7},is_subtype},[{var,{1367,7},'Family2'},{user_type,{1367,18},family,[]}]]}]]}]}}]}},{{function,family_intersection,1},[{file,[115,111,102,115,46,101,114,108]},{location,1325}],[<<102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,115,101,116,32,111,102,32,115,101,116,115,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,116,101,114,115,101,99,116,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,110,32,101,109,112,116,121,32,115,101,116,32,102,111,114,32,115,111,109,101,32,105,44,32,116,104,101,32,112,114,111,99,101,115,115,32,101,120,105,116,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,109,101,115,115,97,103,101,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,91,49,44,50,44,51,93,44,91,50,44,51,44,52,93,93,125,44,123,98,44,91,91,120,44,121,44,122,93,44,91,120,44,121,93,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,40,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,97,44,91,50,44,51,93,125,44,123,98,44,91,120,44,121,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,51,48>>,signature => [{attribute,{1325,2},spec,{{family_intersection,1},[{type,{1325,26},bounded_fun,[{type,{1325,26},'fun',[{type,{1325,26},product,[{var,{1325,27},'Family1'}]},{var,{1325,39},'Family2'}]},[{type,{1326,7},constraint,[{atom,{1326,7},is_subtype},[{var,{1326,7},'Family1'},{user_type,{1326,18},family,[]}]]},{type,{1327,7},constraint,[{atom,{1327,7},is_subtype},[{var,{1327,7},'Family2'},{user_type,{1327,18},family,[]}]]}]]}]}}]}},{{function,family_intersection,2},[{file,[115,111,102,115,46,101,114,108]},{location,1378}],[<<102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,105,101,115>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<58,115,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<58,115,32,105,110,100,101,120,32,115,101,116,115,44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<91,105,93,32,105,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,93,125,44,123,99,44,91,53,44,54,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,98,44,91,52,44,53,93,125,44,123,99,44,91,55,44,56,93,125,44,123,100,44,91,57,44,49,48,93,125,93,41,44,10,70,51,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,105,110,116,101,114,115,101,99,116,105,111,110,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,51,41,46,10,91,123,98,44,91,52,93,125,44,123,99,44,91,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,53,52>>,signature => [{attribute,{1378,2},spec,{{family_intersection,2},[{type,{1378,26},bounded_fun,[{type,{1378,26},'fun',[{type,{1378,26},product,[{var,{1378,27},'Family1'},{var,{1378,36},'Family2'}]},{var,{1378,48},'Family3'}]},[{type,{1379,7},constraint,[{atom,{1379,7},is_subtype},[{var,{1379,7},'Family1'},{user_type,{1379,18},family,[]}]]},{type,{1380,7},constraint,[{atom,{1380,7},is_subtype},[{var,{1380,7},'Family2'},{user_type,{1380,18},family,[]}]]},{type,{1381,7},constraint,[{atom,{1381,7},is_subtype},[{var,{1381,7},'Family3'},{user_type,{1381,18},family,[]}]]}]]}]}}]}},{{function,family_projection,2},[{file,[115,111,102,115,46,101,114,108]},{location,1451}],[<<102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,99,97,108,108,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,119,105,116,104,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,115,32,97,114,103,117,109,101,110,116,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,91,49,44,50,93,44,91,50,44,51,93,93,125,44,123,98,44,91,91,93,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,40,102,117,110,32,115,111,102,115,58,117,110,105,111,110,47,49,44,32,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,55,52>>,signature => [{attribute,{1451,2},spec,{{family_projection,2},[{type,{1451,24},bounded_fun,[{type,{1451,24},'fun',[{type,{1451,24},product,[{var,{1451,25},'SetFun'},{var,{1451,33},'Family1'}]},{var,{1451,45},'Family2'}]},[{type,{1452,7},constraint,[{atom,{1452,7},is_subtype},[{var,{1452,7},'SetFun'},{user_type,{1452,17},set_fun,[]}]]},{type,{1453,7},constraint,[{atom,{1453,7},is_subtype},[{var,{1453,7},'Family1'},{user_type,{1453,18},family,[]}]]},{type,{1454,7},constraint,[{atom,{1454,7},is_subtype},[{var,{1454,7},'Family2'},{user_type,{1454,18},family,[]}]]}]]}]}}]}},{{function,family_range,1},[{file,[115,111,102,115,46,101,114,108]},{location,1353}],[<<102,97,109,105,108,121,95,114,97,110,103,101,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,102,111,114,32,101,118,101,114,121,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,97,110,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,97,110,103,101>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,82,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,125,44,123,98,44,91,93,125,44,123,99,44,91,123,52,44,100,125,44,123,53,44,101,125,93,125,93,41,44,10,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,114,97,110,103,101,40,70,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,97,44,91,97,44,98,44,99,93,125,44,123,98,44,91,93,125,44,123,99,44,91,100,44,101,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,55,57,51>>,signature => [{attribute,{1353,2},spec,{{family_range,1},[{type,{1353,19},bounded_fun,[{type,{1353,19},'fun',[{type,{1353,19},product,[{var,{1353,20},'Family1'}]},{var,{1353,32},'Family2'}]},[{type,{1354,7},constraint,[{atom,{1354,7},is_subtype},[{var,{1354,7},'Family1'},{user_type,{1354,18},family,[]}]]},{type,{1355,7},constraint,[{atom,{1355,7},is_subtype},[{var,{1355,7},'Family2'},{user_type,{1355,18},family,[]}]]}]]}]}}]}},{{function,family_specification,2},[{file,[115,111,102,115,46,101,114,108]},{location,1265}],[<<102,97,109,105,108,121,95,115,112,101,99,105,102,105,99,97,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,116,111,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,105,32,111,102,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,102,111,114,32,119,104,105,99,104,32>>,{code,[],[<<70,117,110>>]},<<32,97,112,112,108,105,101,100,32,116,111,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,194,160,70,117,110,50,125>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,117,110,50>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,49,44,50,93,125,44,123,99,44,91,49,93,125,93,41,44,10,83,112,101,99,70,117,110,32,61,32,102,117,110,40,83,41,32,45,62,32,115,111,102,115,58,110,111,95,101,108,101,109,101,110,116,115,40,83,41,32,61,58,61,32,50,32,101,110,100,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,115,112,101,99,105,102,105,99,97,116,105,111,110,40,83,112,101,99,70,117,110,44,32,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,98,44,91,49,44,50,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,49,52>>,signature => [{attribute,{1265,2},spec,{{family_specification,2},[{type,{1265,27},bounded_fun,[{type,{1265,27},'fun',[{type,{1265,27},product,[{var,{1265,28},'Fun'},{var,{1265,33},'Family1'}]},{var,{1265,45},'Family2'}]},[{type,{1266,7},constraint,[{atom,{1266,7},is_subtype},[{var,{1266,7},'Fun'},{user_type,{1266,14},spec_fun,[]}]]},{type,{1267,7},constraint,[{atom,{1267,7},is_subtype},[{var,{1267,7},'Family1'},{user_type,{1267,18},family,[]}]]},{type,{1268,7},constraint,[{atom,{1268,7},is_subtype},[{var,{1268,7},'Family2'},{user_type,{1268,18},family,[]}]]}]]}]}}]}},{{function,family_to_digraph,2},[{file,[115,111,102,115,46,101,114,108]},{location,1489}],[<<102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,51,57>>,equiv => {function,family_to_digraph,1},signature => [{attribute,{1489,2},spec,{{family_to_digraph,2},[{type,{1489,24},bounded_fun,[{type,{1489,24},'fun',[{type,{1489,24},product,[{var,{1489,25},'Family'},{var,{1489,33},'GraphType'}]},{var,{1489,47},'Graph'}]},[{type,{1490,7},constraint,[{atom,{1490,7},is_subtype},[{var,{1490,7},'Graph'},{remote_type,{1490,16},[{atom,{1490,16},digraph},{atom,{1490,24},graph},[]]}]]},{type,{1491,7},constraint,[{atom,{1491,7},is_subtype},[{var,{1491,7},'Family'},{user_type,{1491,17},family,[]}]]},{type,{1492,7},constraint,[{atom,{1492,7},is_subtype},[{var,{1492,7},'GraphType'},{type,{1492,20},list,[{remote_type,{1492,21},[{atom,{1492,21},digraph},{atom,{1492,29},d_type},[]]}]}]]}]]}]}}]}},{{function,family_to_digraph,1},[{file,[115,111,102,115,46,101,114,108]},{location,1479}],[<<102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,32,102,114,111,109,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<46,32,70,111,114,32,101,97,99,104,32,112,97,105,114,32,40,97,44,194,160,123,98,91,49,93,44,194,160,46,46,46,44,194,160,98,91,110,93,125,41,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<44,32,118,101,114,116,101,120,32,97,32,97,110,100,32,116,104,101,32,101,100,103,101,115,32,40,97,44,194,160,98,91,105,93,41,32,102,111,114,32,49,194,160,60,61,194,160,105,194,160,60,61,194,160,110,32,97,114,101,32,97,100,100,101,100,32,116,111,32,97,32,110,101,119,108,121,32,99,114,101,97,116,101,100,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,46>>]},{p,[],[<<73,102,32,110,111,32,103,114,97,112,104,32,116,121,112,101,32,105,115,32,115,112,101,99,105,102,105,101,100,44,32>>,{a,[{href,<<115,116,100,108,105,98,58,100,105,103,114,97,112,104,35,110,101,119,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,105,103,114,97,112,104,58,110,101,119,47,48>>]}]},<<32,105,115,32,117,115,101,100,32,102,111,114,32,99,114,101,97,116,105,110,103,32,116,104,101,32,100,105,114,101,99,116,101,100,32,103,114,97,112,104,44,32,111,116,104,101,114,119,105,115,101,32,97,114,103,117,109,101,110,116,32>>,{code,[],[<<71,114,97,112,104,84,121,112,101>>]},<<32,105,115,32,112,97,115,115,101,100,32,111,110,32,97,115,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,32,116,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,100,105,103,114,97,112,104,35,110,101,119,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<100,105,103,114,97,112,104,58,110,101,119,47,49>>]}]},<<46>>]},{p,[],[<<73,116,32,70,32,105,115,32,97,32,102,97,109,105,108,121,44,32,105,116,32,104,111,108,100,115,32,116,104,97,116,32,70,32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<100,105,103,114,97,112,104,95,116,111,95,102,97,109,105,108,121,40,102,97,109,105,108,121,95,116,111,95,100,105,103,114,97,112,104,40,70,41,44,194,160,116,121,112,101,40,70,41,41>>]},<<46,32,69,113,117,97,108,105,116,121,32,104,111,108,100,115,32,105,102,32>>,{code,[],[<<117,110,105,111,110,95,111,102,95,102,97,109,105,108,121,40,70,41>>]},<<32,105,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<100,111,109,97,105,110,40,70,41>>]},<<46>>]},{p,[],[<<67,114,101,97,116,105,110,103,32,97,32,99,121,99,108,101,32,105,110,32,97,110,32,97,99,121,99,108,105,99,32,103,114,97,112,104,32,101,120,105,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<99,121,99,108,105,99>>]},<<32,109,101,115,115,97,103,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,51,57>>,signature => [{attribute,{1479,2},spec,{{family_to_digraph,1},[{type,{1479,24},bounded_fun,[{type,{1479,24},'fun',[{type,{1479,24},product,[{var,{1479,25},'Family'}]},{var,{1479,36},'Graph'}]},[{type,{1480,7},constraint,[{atom,{1480,7},is_subtype},[{var,{1480,7},'Graph'},{remote_type,{1480,16},[{atom,{1480,16},digraph},{atom,{1480,24},graph},[]]}]]},{type,{1481,7},constraint,[{atom,{1481,7},is_subtype},[{var,{1481,7},'Family'},{user_type,{1481,17},family,[]}]]}]]}]}}]}},{{function,family_to_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,1253}],[<<102,97,109,105,108,121,95,116,111,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32,99,111,110,116,97,105,110,105,110,103,32,97,108,108,32,112,97,105,114,115,32,40,105,44,194,160,120,41,32,115,117,99,104,32,116,104,97,116,32,105,32,98,101,108,111,110,103,115,32,116,111,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,97,110,100,32,120,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,93,125,44,32,123,98,44,91,49,93,125,44,32,123,99,44,91,50,44,51,93,125,93,41,44,10,82,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,116,111,95,114,101,108,97,116,105,111,110,40,70,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,41,46,10,91,123,98,44,49,125,44,123,99,44,50,125,44,123,99,44,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,54,53>>,signature => [{attribute,{1253,2},spec,{{family_to_relation,1},[{type,{1253,25},bounded_fun,[{type,{1253,25},'fun',[{type,{1253,25},product,[{var,{1253,26},'Family'}]},{var,{1253,37},'BinRel'}]},[{type,{1254,7},constraint,[{atom,{1254,7},is_subtype},[{var,{1254,7},'Family'},{user_type,{1254,17},family,[]}]]},{type,{1255,7},constraint,[{atom,{1255,7},is_subtype},[{var,{1255,7},'BinRel'},{user_type,{1255,17},binary_relation,[]}]]}]]}]}}]}},{{function,family_union,1},[{file,[115,111,102,115,46,101,114,108]},{location,1314}],[<<102,97,109,105,108,121,95,117,110,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,105,115,32,97,32,115,101,116,32,111,102,32,115,101,116,115,32,102,111,114,32,101,97,99,104,32,105,32,105,110,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,119,105,116,104,32,116,104,101,32,115,97,109,101,32,105,110,100,101,120,32,115,101,116,32,97,115,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,115,117,99,104,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,97,44,91,91,49,44,50,93,44,91,50,44,51,93,93,125,44,123,98,44,91,91,93,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,117,110,105,111,110,40,70,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,50,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,93,125,93>>]}]},{p,[],[{code,[],[<<102,97,109,105,108,121,95,117,110,105,111,110,40,70,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,97,109,105,108,121,95,112,114,111,106,101,99,116,105,111,110,40,102,117,110,32,115,111,102,115,58,117,110,105,111,110,47,49,44,194,160,70,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,56,56,51>>,signature => [{attribute,{1314,2},spec,{{family_union,1},[{type,{1314,19},bounded_fun,[{type,{1314,19},'fun',[{type,{1314,19},product,[{var,{1314,20},'Family1'}]},{var,{1314,32},'Family2'}]},[{type,{1315,7},constraint,[{atom,{1315,7},is_subtype},[{var,{1315,7},'Family1'},{user_type,{1315,18},family,[]}]]},{type,{1316,7},constraint,[{atom,{1316,7},is_subtype},[{var,{1316,7},'Family2'},{user_type,{1316,18},family,[]}]]}]]}]}}]}},{{function,family_union,2},[{file,[115,111,102,115,46,101,114,108]},{location,1371}],[<<102,97,109,105,108,121,95,117,110,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,105,101,115>>]},<<44,32,116,104,101,110,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<32,105,115,32,116,104,101,32,102,97,109,105,108,121,32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<58,115,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<58,115,32,105,110,100,101,120,32,115,101,116,115,44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,51>>]},<<91,105,93,32,105,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,32,105,102,32,98,111,116,104,32,109,97,112,32,105,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,97,109,105,108,121,49>>]},<<91,105,93,32,111,114,32>>,{code,[],[<<70,97,109,105,108,121,50>>]},<<91,105,93,46>>]},{pre,[],[{code,[],[<<49,62,32,70,49,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,93,125,44,123,99,44,91,53,44,54,93,125,93,41,44,10,70,50,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,98,44,91,52,44,53,93,125,44,123,99,44,91,55,44,56,93,125,44,123,100,44,91,57,44,49,48,93,125,93,41,44,10,70,51,32,61,32,115,111,102,115,58,102,97,109,105,108,121,95,117,110,105,111,110,40,70,49,44,32,70,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,51,41,46,10,91,123,97,44,91,49,44,50,93,125,44,123,98,44,91,51,44,52,44,53,93,125,44,123,99,44,91,53,44,54,44,55,44,56,93,125,44,123,100,44,91,57,44,49,48,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,48,54>>,signature => [{attribute,{1371,2},spec,{{family_union,2},[{type,{1371,19},bounded_fun,[{type,{1371,19},'fun',[{type,{1371,19},product,[{var,{1371,20},'Family1'},{var,{1371,29},'Family2'}]},{var,{1371,41},'Family3'}]},[{type,{1372,7},constraint,[{atom,{1372,7},is_subtype},[{var,{1372,7},'Family1'},{user_type,{1372,18},family,[]}]]},{type,{1373,7},constraint,[{atom,{1373,7},is_subtype},[{var,{1373,7},'Family2'},{user_type,{1373,18},family,[]}]]},{type,{1374,7},constraint,[{atom,{1374,7},is_subtype},[{var,{1374,7},'Family3'},{user_type,{1374,18},family,[]}]]}]]}]}}]}},{{function,field,1},[{file,[115,111,102,115,46,101,114,108]},{location,632}],[<<102,105,101,108,100,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,105,101,108,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,101,108,100>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,98,125,44,123,50,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,102,105,101,108,100,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,49,44,50,44,97,44,98,44,99,93>>]}]},{p,[],[{code,[],[<<102,105,101,108,100,40,82,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<117,110,105,111,110,40,100,111,109,97,105,110,40,82,41,44,32,114,97,110,103,101,40,82,41,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,50,56>>,signature => [{attribute,{632,2},spec,{{field,1},[{type,{632,12},bounded_fun,[{type,{632,12},'fun',[{type,{632,12},product,[{var,{632,13},'BinRel'}]},{var,{632,24},'Set'}]},[{type,{633,7},constraint,[{atom,{633,7},is_subtype},[{var,{633,7},'BinRel'},{user_type,{633,17},binary_relation,[]}]]},{type,{634,7},constraint,[{atom,{634,7},is_subtype},[{var,{634,7},'Set'},{user_type,{634,14},a_set,[]}]]}]]}]}}]}},{{function,from_external,2},[{file,[115,111,102,115,46,101,114,108]},{location,169}],[<<102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32,115,101,116,32,102,114,111,109,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32>>,{code,[],[<<69,120,116,101,114,110,97,108,83,101,116>>]},<<32,97,110,100,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32>>,{code,[],[<<84,121,112,101>>]},<<46,32,73,116,32,105,115,32,97,115,115,117,109,101,100,32,116,104,97,116,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,118,97,108,105,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,111,102,32>>,{code,[],[<<69,120,116,101,114,110,97,108,83,101,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,52,52>>,signature => [{attribute,{169,2},spec,{{from_external,2},[{type,{169,20},bounded_fun,[{type,{169,20},'fun',[{type,{169,20},product,[{var,{169,21},'ExternalSet'},{var,{169,34},'Type'}]},{var,{169,43},'AnySet'}]},[{type,{170,7},constraint,[{atom,{170,7},is_subtype},[{var,{170,7},'ExternalSet'},{user_type,{170,22},external_set,[]}]]},{type,{171,7},constraint,[{atom,{171,7},is_subtype},[{var,{171,7},'AnySet'},{user_type,{171,17},anyset,[]}]]},{type,{172,7},constraint,[{atom,{172,7},is_subtype},[{var,{172,7},'Type'},{user_type,{172,15},type,[]}]]}]]}]}}]}},{{function,from_sets,1},[{file,[115,111,102,115,46,101,114,108]},{location,220}],[<<102,114,111,109,95,115,101,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,115,101,116,115,32,111,102,32,108,105,115,116,32>>,{code,[],[<<76,105,115,116,79,102,83,101,116,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,93,41,44,10,83,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,120,44,51,125,44,123,121,44,52,125,93,41,44,10,83,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,91,83,49,44,83,50,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,91,123,97,44,49,125,44,123,98,44,50,125,93,44,91,123,120,44,51,125,44,123,121,44,52,125,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,53,55>>,signature => [{attribute,{220,2},spec,{{from_sets,1},[{type,{220,16},bounded_fun,[{type,{220,16},'fun',[{type,{220,16},product,[{var,{220,17},'ListOfSets'}]},{var,{220,32},'Set'}]},[{type,{221,7},constraint,[{atom,{221,7},is_subtype},[{var,{221,7},'Set'},{user_type,{221,14},a_set,[]}]]},{type,{222,7},constraint,[{atom,{222,7},is_subtype},[{var,{222,7},'ListOfSets'},{type,{222,21},list,[{user_type,{222,22},anyset,[]}]}]]}]]}]}}]}},{{function,from_sets,1},[{file,[115,111,102,115,46,101,114,108]},{location,220}],[<<102,114,111,109,95,115,101,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<111,114,100,101,114,101,100,32,115,101,116>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,115,101,116,115,32,111,102,32,116,104,101,32,110,111,110,45,101,109,112,116,121,32,116,117,112,108,101,32>>,{code,[],[<<84,117,112,108,101,79,102,83,101,116,115>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,55,51>>,signature => [{attribute,{220,2},spec,{{from_sets,1},[{type,{223,16},bounded_fun,[{type,{223,16},'fun',[{type,{223,16},product,[{var,{223,17},'TupleOfSets'}]},{var,{223,33},'Ordset'}]},[{type,{224,7},constraint,[{atom,{224,7},is_subtype},[{var,{224,7},'Ordset'},{user_type,{224,17},ordset,[]}]]},{type,{225,7},constraint,[{atom,{225,7},is_subtype},[{var,{225,7},'TupleOfSets'},{user_type,{225,22},tuple_of,[{user_type,{225,31},anyset,[]}]}]]}]]}]}}]}},{{function,from_term,2},[{file,[115,111,102,115,46,101,114,108]},{location,155}],[<<102,114,111,109,95,116,101,114,109,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,56,51>>,equiv => {function,from_term,1},signature => [{attribute,{155,2},spec,{{from_term,2},[{type,{155,16},bounded_fun,[{type,{155,16},'fun',[{type,{155,16},product,[{var,{155,17},'Term'},{var,{155,23},'Type'}]},{var,{155,32},'AnySet'}]},[{type,{156,7},constraint,[{atom,{156,7},is_subtype},[{var,{156,7},'AnySet'},{user_type,{156,17},anyset,[]}]]},{type,{157,7},constraint,[{atom,{157,7},is_subtype},[{var,{157,7},'Term'},{type,{157,15},term,[]}]]},{type,{158,7},constraint,[{atom,{158,7},is_subtype},[{var,{158,7},'Type'},{user_type,{158,15},type,[]}]]}]]}]}}]}},{{function,from_term,1},[{file,[115,111,102,115,46,101,114,108]},{location,143}],[<<102,114,111,109,95,116,101,114,109,47,49>>],#{<<101,110>> => [{p,[],[{a,[{id,<<102,114,111,109,95,116,101,114,109>>}],[]},<<67,114,101,97,116,101,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,101,116,115>>]},<<32,98,121,32,116,114,97,118,101,114,115,105,110,103,32,116,101,114,109,32>>,{code,[],[<<84,101,114,109>>]},<<44,32,115,111,114,116,105,110,103,32,108,105,115,116,115,44,32,114,101,109,111,118,105,110,103,32,100,117,112,108,105,99,97,116,101,115,44,32,97,110,100,32,100,101,114,105,118,105,110,103,32,111,114,32,118,101,114,105,102,121,105,110,103,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,118,97,108,105,100,95,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<118,97,108,105,100,32,116,121,112,101>>]},<<32,102,111,114,32,116,104,101,32,115,111,32,111,98,116,97,105,110,101,100,32,101,120,116,101,114,110,97,108,32,115,101,116,46,32,65,110,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32>>,{code,[],[<<84,121,112,101>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,108,105,109,105,116,32,116,104,101,32,100,101,112,116,104,32,111,102,32,116,104,101,32,116,114,97,118,101,114,115,97,108,59,32,97,110,32,97,116,111,109,105,99,32,116,121,112,101,32,115,116,111,112,115,32,116,104,101,32,116,114,97,118,101,114,115,97,108,44,32,97,115,32,115,104,111,119,110,32,98,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,119,104,101,114,101,32>>,{code,[],[<<34,102,111,111,34>>]},<<32,97,110,100,32>>,{code,[],[<<123,34,102,111,111,34,125>>]},<<32,97,114,101,32,108,101,102,116,32,117,110,109,111,100,105,102,105,101,100,58>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,123,34,102,111,111,34,125,44,91,49,44,49,93,125,44,123,34,102,111,111,34,44,91,50,44,50,93,125,93,44,10,91,123,97,116,111,109,44,91,97,116,111,109,93,125,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,123,123,34,102,111,111,34,125,44,91,49,93,125,44,123,34,102,111,111,34,44,91,50,93,125,93>>]}]},{p,[],[{code,[],[<<102,114,111,109,95,116,101,114,109>>]},<<32,99,97,110,32,98,101,32,117,115,101,100,32,102,111,114,32,99,114,101,97,116,105,110,103,32,97,116,111,109,105,99,32,111,114,32,111,114,100,101,114,101,100,32,115,101,116,115,46,32,84,104,101,32,111,110,108,121,32,112,117,114,112,111,115,101,32,111,102,32,115,117,99,104,32,97,32,115,101,116,32,105,115,32,116,104,97,116,32,111,102,32,108,97,116,101,114,32,98,117,105,108,100,105,110,103,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,44,32,97,115,32,97,108,108,32,102,117,110,99,116,105,111,110,115,32,105,110,32,116,104,105,115,32,109,111,100,117,108,101,32,116,104,97,116,32>>,{em,[],[<<100,111>>]},<<32,97,110,121,116,104,105,110,103,32,111,112,101,114,97,116,101,32,111,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,46,32,67,114,101,97,116,105,110,103,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,32,102,114,111,109,32,97,32,99,111,108,108,101,99,116,105,111,110,32,111,102,32,111,114,100,101,114,101,100,32,115,101,116,115,32,99,97,110,32,98,101,32,116,104,101,32,119,97,121,32,116,111,32,103,111,32,105,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,98,105,103,32,97,110,100,32,111,110,101,32,100,111,101,115,32,110,111,116,32,119,97,110,116,32,116,111,32,119,97,115,116,101,32,104,101,97,112,32,98,121,32,114,101,98,117,105,108,100,105,110,103,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,115,104,111,119,115,32,116,104,97,116,32,97,32,115,101,116,32,99,97,110,32,98,101,32,98,117,105,108,116,32,34,108,97,121,101,114,32,98,121,32,108,97,121,101,114,34,58>>]},{pre,[],[{code,[],[<<49,62,32,65,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,97,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,44,51,93,41,44,10,80,49,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,123,65,44,83,125,41,44,10,80,50,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,123,98,44,91,54,44,53,44,52,93,125,41,44,10,83,115,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,91,80,49,44,80,50,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,115,41,46,10,91,123,97,44,91,49,44,50,44,51,93,125,44,123,98,44,91,52,44,53,44,54,93,125,93>>]}]},{p,[],[<<79,116,104,101,114,32,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,99,114,101,97,116,101,32,115,101,116,115,32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,101,120,116,101,114,110,97,108,47,50>>]}]},<<32,97,110,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,114,111,109,95,115,101,116,115,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,114,111,109,95,115,101,116,115,47,49>>]}]},<<46,32,83,112,101,99,105,97,108,32,99,97,115,101,115,32,111,102,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,47,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,97,95,102,117,110,99,116,105,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<97,95,102,117,110,99,116,105,111,110,47,49,44,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,109,112,116,121,95,115,101,116,47,48>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<101,109,112,116,121,95,115,101,116,47,48>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<102,97,109,105,108,121,47,49,44,50>>]}]},<<44,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,111,110,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<114,101,108,97,116,105,111,110,47,49,44,50>>]}]},<<44,32,97,110,100,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,47,49>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<115,101,116,47,49,44,50>>]}]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,57,56,51>>,signature => [{attribute,{143,2},spec,{{from_term,1},[{type,{143,16},bounded_fun,[{type,{143,16},'fun',[{type,{143,16},product,[{var,{143,17},'Term'}]},{var,{143,26},'AnySet'}]},[{type,{144,7},constraint,[{atom,{144,7},is_subtype},[{var,{144,7},'AnySet'},{user_type,{144,17},anyset,[]}]]},{type,{145,7},constraint,[{atom,{145,7},is_subtype},[{var,{145,7},'Term'},{type,{145,15},term,[]}]]}]]}]}}]}},{{function,image,2},[{file,[115,111,102,115,46,101,114,108]},{location,717}],[<<105,109,97,103,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,109,97,103,101>>]},<<32,111,102,32,115,101,116,32>>,{code,[],[<<83,101,116,49>>]},<<32,117,110,100,101,114,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,50,44,99,125,44,123,51,44,100,125,93,41,44,10,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,93,41,44,10,83,50,32,61,32,115,111,102,115,58,105,109,97,103,101,40,82,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,97,44,98,44,99,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,51,51>>,signature => [{attribute,{717,2},spec,{{image,2},[{type,{717,12},bounded_fun,[{type,{717,12},'fun',[{type,{717,12},product,[{var,{717,13},'BinRel'},{var,{717,21},'Set1'}]},{var,{717,30},'Set2'}]},[{type,{718,7},constraint,[{atom,{718,7},is_subtype},[{var,{718,7},'BinRel'},{user_type,{718,17},binary_relation,[]}]]},{type,{719,7},constraint,[{atom,{719,7},is_subtype},[{var,{719,7},'Set1'},{user_type,{719,15},a_set,[]}]]},{type,{720,7},constraint,[{atom,{720,7},is_subtype},[{var,{720,7},'Set2'},{user_type,{720,15},a_set,[]}]]}]]}]}}]}},{{function,intersection,1},[{file,[115,111,102,115,46,101,114,108]},{location,563}],[<<105,110,116,101,114,115,101,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,116,101,114,115,101,99,116,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,115,101,116,115,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<46>>]},{p,[],[<<73,110,116,101,114,115,101,99,116,105,110,103,32,97,110,32,101,109,112,116,121,32,115,101,116,32,111,102,32,115,101,116,115,32,101,120,105,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,109,101,115,115,97,103,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,52,57>>,signature => [{attribute,{563,2},spec,{{intersection,1},[{type,{563,19},bounded_fun,[{type,{563,19},'fun',[{type,{563,19},product,[{var,{563,20},'SetOfSets'}]},{var,{563,34},'Set'}]},[{type,{564,7},constraint,[{atom,{564,7},is_subtype},[{var,{564,7},'Set'},{user_type,{564,14},a_set,[]}]]},{type,{565,7},constraint,[{atom,{565,7},is_subtype},[{var,{565,7},'SetOfSets'},{user_type,{565,20},set_of_sets,[]}]]}]]}]}}]}},{{function,intersection,2},[{file,[115,111,102,115,46,101,114,108]},{location,388}],[<<105,110,116,101,114,115,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,116,101,114,115,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,116,101,114,115,101,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,54,49>>,signature => [{attribute,{388,2},spec,{{intersection,2},[{type,{388,19},bounded_fun,[{type,{388,19},'fun',[{type,{388,19},product,[{var,{388,20},'Set1'},{var,{388,26},'Set2'}]},{var,{388,35},'Set3'}]},[{type,{389,7},constraint,[{atom,{389,7},is_subtype},[{var,{389,7},'Set1'},{user_type,{389,15},a_set,[]}]]},{type,{390,7},constraint,[{atom,{390,7},is_subtype},[{var,{390,7},'Set2'},{user_type,{390,15},a_set,[]}]]},{type,{391,7},constraint,[{atom,{391,7},is_subtype},[{var,{391,7},'Set3'},{user_type,{391,15},a_set,[]}]]}]]}]}}]}},{{function,intersection_of_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,1299}],[<<105,110,116,101,114,115,101,99,116,105,111,110,95,111,102,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,105,110,116,101,114,115,101,99,116,105,111,110,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<46>>]},{p,[],[<<73,110,116,101,114,115,101,99,116,105,110,103,32,97,110,32,101,109,112,116,121,32,102,97,109,105,108,121,32,101,120,105,116,115,32,116,104,101,32,112,114,111,99,101,115,115,32,119,105,116,104,32,97,32>>,{code,[],[<<98,97,100,97,114,103>>]},<<32,109,101,115,115,97,103,101,46>>]},{pre,[],[{code,[],[<<49,62,32,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,48,44,50,44,52,93,125,44,123,98,44,91,48,44,49,44,50,93,125,44,123,99,44,91,50,44,51,93,125,93,41,44,10,83,32,61,32,115,111,102,115,58,105,110,116,101,114,115,101,99,116,105,111,110,95,111,102,95,102,97,109,105,108,121,40,70,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,50,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,55,49>>,signature => [{attribute,{1299,2},spec,{{intersection_of_family,1},[{type,{1299,29},bounded_fun,[{type,{1299,29},'fun',[{type,{1299,29},product,[{var,{1299,30},'Family'}]},{var,{1299,41},'Set'}]},[{type,{1300,7},constraint,[{atom,{1300,7},is_subtype},[{var,{1300,7},'Family'},{user_type,{1300,17},family,[]}]]},{type,{1301,7},constraint,[{atom,{1301,7},is_subtype},[{var,{1301,7},'Set'},{user_type,{1301,14},a_set,[]}]]}]]}]}}]}},{{function,inverse,1},[{file,[115,111,102,115,46,101,114,108]},{location,872}],[<<105,110,118,101,114,115,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,118,101,114,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,118,101,114,115,101>>]},<<32,111,102,32,102,117,110,99,116,105,111,110,32>>,{code,[],[<<70,117,110,99,116,105,111,110,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,105,110,118,101,114,115,101,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,97,44,49,125,44,123,98,44,50,125,44,123,99,44,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,48,56,56>>,signature => [{attribute,{872,2},spec,{{inverse,1},[{type,{872,14},bounded_fun,[{type,{872,14},'fun',[{type,{872,14},product,[{var,{872,15},'Function1'}]},{var,{872,29},'Function2'}]},[{type,{873,7},constraint,[{atom,{873,7},is_subtype},[{var,{873,7},'Function1'},{user_type,{873,20},a_function,[]}]]},{type,{874,7},constraint,[{atom,{874,7},is_subtype},[{var,{874,7},'Function2'},{user_type,{874,20},a_function,[]}]]}]]}]}}]}},{{function,inverse_image,2},[{file,[115,111,102,115,46,101,114,108]},{location,734}],[<<105,110,118,101,114,115,101,95,105,109,97,103,101,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,110,118,101,114,115,101,95,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,110,118,101,114,115,101,32,105,109,97,103,101>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,117,110,100,101,114,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,50,44,99,125,44,123,51,44,100,125,93,41,44,10,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,99,44,100,44,101,93,41,44,10,83,50,32,61,32,115,111,102,115,58,105,110,118,101,114,115,101,95,105,109,97,103,101,40,82,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,50,44,51,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,48,50>>,signature => [{attribute,{734,2},spec,{{inverse_image,2},[{type,{734,20},bounded_fun,[{type,{734,20},'fun',[{type,{734,20},product,[{var,{734,21},'BinRel'},{var,{734,29},'Set1'}]},{var,{734,38},'Set2'}]},[{type,{735,7},constraint,[{atom,{735,7},is_subtype},[{var,{735,7},'BinRel'},{user_type,{735,17},binary_relation,[]}]]},{type,{736,7},constraint,[{atom,{736,7},is_subtype},[{var,{736,7},'Set1'},{user_type,{736,15},a_set,[]}]]},{type,{737,7},constraint,[{atom,{737,7},is_subtype},[{var,{737,7},'Set2'},{user_type,{737,15},a_set,[]}]]}]]}]}}]}},{{function,is_a_function,1},[{file,[115,111,102,115,46,101,114,108]},{location,812}],[<<105,115,95,97,95,102,117,110,99,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<32,111,114,32,116,104,101,32,117,110,116,121,112,101,100,32,101,109,112,116,121,32,115,101,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,49,57>>,signature => [{attribute,{812,2},spec,{{is_a_function,1},[{type,{812,20},bounded_fun,[{type,{812,20},'fun',[{type,{812,20},product,[{var,{812,21},'BinRel'}]},{var,{812,32},'Bool'}]},[{type,{813,7},constraint,[{atom,{813,7},is_subtype},[{var,{813,7},'Bool'},{type,{813,15},boolean,[]}]]},{type,{814,7},constraint,[{atom,{814,7},is_subtype},[{var,{814,7},'BinRel'},{user_type,{814,17},binary_relation,[]}]]}]]}]}}]}},{{function,is_disjoint,2},[{file,[115,111,102,115,46,101,114,108]},{location,535}],[<<105,115,95,100,105,115,106,111,105,110,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,105,115,106,111,105,110,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,105,115,106,111,105,110,116>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,50,57>>,signature => [{attribute,{535,2},spec,{{is_disjoint,2},[{type,{535,18},bounded_fun,[{type,{535,18},'fun',[{type,{535,18},product,[{var,{535,19},'Set1'},{var,{535,25},'Set2'}]},{var,{535,34},'Bool'}]},[{type,{536,7},constraint,[{atom,{536,7},is_subtype},[{var,{536,7},'Bool'},{type,{536,15},boolean,[]}]]},{type,{537,7},constraint,[{atom,{537,7},is_subtype},[{var,{537,7},'Set1'},{user_type,{537,15},a_set,[]}]]},{type,{538,7},constraint,[{atom,{538,7},is_subtype},[{var,{538,7},'Set2'},{user_type,{538,15},a_set,[]}]]}]]}]}}]}},{{function,is_empty_set,1},[{file,[115,111,102,115,46,101,114,108]},{location,527}],[<<105,115,95,101,109,112,116,121,95,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<32,105,115,32,97,110,32,101,109,112,116,121,32,117,110,111,114,100,101,114,101,100,32,115,101,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,52,48>>,signature => [{attribute,{527,2},spec,{{is_empty_set,1},[{type,{527,19},bounded_fun,[{type,{527,19},'fun',[{type,{527,19},product,[{var,{527,20},'AnySet'}]},{var,{527,31},'Bool'}]},[{type,{528,7},constraint,[{atom,{528,7},is_subtype},[{var,{528,7},'AnySet'},{user_type,{528,17},anyset,[]}]]},{type,{529,7},constraint,[{atom,{529,7},is_subtype},[{var,{529,7},'Bool'},{type,{529,15},boolean,[]}]]}]]}]}}]}},{{function,is_equal,2},[{file,[115,111,102,115,46,101,114,108]},{location,480}],[<<105,115,95,101,113,117,97,108,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<65,110,121,83,101,116,50>>]},<<32,97,114,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,113,117,97,108>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,113,117,97,108>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,120,97,109,112,108,101,32,115,104,111,119,115,32,116,104,97,116,32>>,{code,[],[<<61,61,47,50>>]},<<32,105,115,32,117,115,101,100,32,119,104,101,110,32,99,111,109,112,97,114,105,110,103,32,115,101,116,115,32,102,111,114,32,101,113,117,97,108,105,116,121,58>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,46,48,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,49,93,41,44,10,115,111,102,115,58,105,115,95,101,113,117,97,108,40,83,49,44,32,83,50,41,46,10,116,114,117,101>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,52,57>>,signature => [{attribute,{480,2},spec,{{is_equal,2},[{type,{480,15},bounded_fun,[{type,{480,15},'fun',[{type,{480,15},product,[{var,{480,16},'AnySet1'},{var,{480,25},'AnySet2'}]},{var,{480,37},'Bool'}]},[{type,{481,7},constraint,[{atom,{481,7},is_subtype},[{var,{481,7},'AnySet1'},{user_type,{481,18},anyset,[]}]]},{type,{482,7},constraint,[{atom,{482,7},is_subtype},[{var,{482,7},'AnySet2'},{user_type,{482,18},anyset,[]}]]},{type,{483,7},constraint,[{atom,{483,7},is_subtype},[{var,{483,7},'Bool'},{type,{483,15},boolean,[]}]]}]]}]}}]}},{{function,is_set,1},[{file,[115,111,102,115,46,101,114,108]},{location,519}],[<<105,115,95,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<32,105,115,32,97,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<44,32,97,110,100,32>>,{code,[],[<<102,97,108,115,101>>]},<<32,105,102,32>>,{code,[],[<<65,110,121,83,101,116>>]},<<32,105,115,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,32,111,114,32,97,110,32,97,116,111,109,105,99,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,54,54>>,signature => [{attribute,{519,2},spec,{{is_set,1},[{type,{519,13},bounded_fun,[{type,{519,13},'fun',[{type,{519,13},product,[{var,{519,14},'AnySet'}]},{var,{519,25},'Bool'}]},[{type,{520,7},constraint,[{atom,{520,7},is_subtype},[{var,{520,7},'AnySet'},{user_type,{520,17},anyset,[]}]]},{type,{521,7},constraint,[{atom,{521,7},is_subtype},[{var,{521,7},'Bool'},{type,{521,15},boolean,[]}]]}]]}]}}]}},{{function,is_sofs_set,1},[{file,[115,111,102,115,46,101,114,108]},{location,509}],[<<105,115,95,115,111,102,115,95,115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<44,32,97,110,32,111,114,100,101,114,101,100,32,115,101,116,44,32,111,114,32,97,110,32,97,116,111,109,105,99,32,115,101,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,55,55>>,signature => [{attribute,{509,2},spec,{{is_sofs_set,1},[{type,{509,18},bounded_fun,[{type,{509,18},'fun',[{type,{509,18},product,[{var,{509,19},'Term'}]},{var,{509,28},'Bool'}]},[{type,{510,7},constraint,[{atom,{510,7},is_subtype},[{var,{510,7},'Bool'},{type,{510,15},boolean,[]}]]},{type,{511,7},constraint,[{atom,{511,7},is_subtype},[{var,{511,7},'Term'},{type,{511,15},term,[]}]]}]]}]}}]}},{{function,is_subset,2},[{file,[115,111,102,115,46,101,114,108]},{location,499}],[<<105,115,95,115,117,98,115,101,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,117,98,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,117,98,115,101,116>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,50>>]},<<44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<102,97,108,115,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,56,55>>,signature => [{attribute,{499,2},spec,{{is_subset,2},[{type,{499,16},bounded_fun,[{type,{499,16},'fun',[{type,{499,16},product,[{var,{499,17},'Set1'},{var,{499,23},'Set2'}]},{var,{499,32},'Bool'}]},[{type,{500,7},constraint,[{atom,{500,7},is_subtype},[{var,{500,7},'Bool'},{type,{500,15},boolean,[]}]]},{type,{501,7},constraint,[{atom,{501,7},is_subtype},[{var,{501,7},'Set1'},{user_type,{501,15},a_set,[]}]]},{type,{502,7},constraint,[{atom,{502,7},is_subtype},[{var,{502,7},'Set2'},{user_type,{502,15},a_set,[]}]]}]]}]}}]}},{{function,is_type,1},[{file,[115,111,102,115,46,101,114,108]},{location,183}],[<<105,115,95,116,121,112,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<32,105,102,32,116,101,114,109,32>>,{code,[],[<<84,101,114,109>>]},<<32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,49,57,55>>,signature => [{attribute,{183,2},spec,{{is_type,1},[{type,{183,14},bounded_fun,[{type,{183,14},'fun',[{type,{183,14},product,[{var,{183,15},'Term'}]},{var,{183,24},'Bool'}]},[{type,{184,7},constraint,[{atom,{184,7},is_subtype},[{var,{184,7},'Bool'},{type,{184,15},boolean,[]}]]},{type,{185,7},constraint,[{atom,{185,7},is_subtype},[{var,{185,7},'Term'},{type,{185,15},term,[]}]]}]]}]}}]}},{{function,join,4},[{file,[115,111,102,115,46,101,114,108]},{location,1206}],[<<106,111,105,110,47,52>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,110,97,116,117,114,97,108,95,106,111,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,97,116,117,114,97,108,32,106,111,105,110>>]},<<32,111,102,32,116,104,101,32,114,101,108,97,116,105,111,110,115,32>>,{code,[],[<<82,101,108,97,116,105,111,110,49>>]},<<32,97,110,100,32>>,{code,[],[<<82,101,108,97,116,105,111,110,50>>]},<<32,111,110,32,99,111,111,114,100,105,110,97,116,101,115,32>>,{code,[],[<<73>>]},<<32,97,110,100,32>>,{code,[],[<<74>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,120,44,49,125,44,123,98,44,121,44,50,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,102,44,103,125,44,123,49,44,104,44,105,125,44,123,50,44,51,44,52,125,93,41,44,10,74,32,61,32,115,111,102,115,58,106,111,105,110,40,82,49,44,32,51,44,32,82,50,44,32,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,74,41,46,10,91,123,97,44,120,44,49,44,102,44,103,125,44,123,97,44,120,44,49,44,104,44,105,125,44,123,98,44,121,44,50,44,51,44,52,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,48,54>>,signature => [{attribute,{1206,2},spec,{{join,4},[{type,{1206,11},bounded_fun,[{type,{1206,11},'fun',[{type,{1206,11},product,[{var,{1206,12},'Relation1'},{var,{1206,23},'I'},{var,{1206,26},'Relation2'},{var,{1206,37},'J'}]},{var,{1206,43},'Relation3'}]},[{type,{1207,7},constraint,[{atom,{1207,7},is_subtype},[{var,{1207,7},'Relation1'},{user_type,{1207,20},relation,[]}]]},{type,{1208,7},constraint,[{atom,{1208,7},is_subtype},[{var,{1208,7},'Relation2'},{user_type,{1208,20},relation,[]}]]},{type,{1209,7},constraint,[{atom,{1209,7},is_subtype},[{var,{1209,7},'Relation3'},{user_type,{1209,20},relation,[]}]]},{type,{1210,7},constraint,[{atom,{1210,7},is_subtype},[{var,{1210,7},'I'},{type,{1210,12},pos_integer,[]}]]},{type,{1211,7},constraint,[{atom,{1211,7},is_subtype},[{var,{1211,7},'J'},{type,{1211,12},pos_integer,[]}]]}]]}]}}]}},{{function,multiple_relative_product,2},[{file,[115,111,102,115,46,101,114,108]},{location,1190}],[<<109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<84,117,112,108,101,79,102,66,105,110,82,101,108,115>>]},<<32,105,115,32,97,32,110,111,110,45,101,109,112,116,121,32,116,117,112,108,101,32,123,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,125,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,44,32,116,104,101,110,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<109,117,108,116,105,112,108,101,32,114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,105,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,105,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,44,123,99,44,51,125,93,41,44,10,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,98,125,44,123,98,44,99,125,44,123,99,44,97,125,93,41,44,10,77,80,32,61,32,115,111,102,115,58,109,117,108,116,105,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,123,82,105,44,32,82,105,125,44,32,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,114,97,110,103,101,40,77,80,41,41,46,10,91,123,49,44,50,125,44,123,50,44,51,125,44,123,51,44,49,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,50,51>>,signature => [{attribute,{1190,2},spec,{{multiple_relative_product,2},[{type,{1190,32},bounded_fun,[{type,{1190,32},'fun',[{type,{1190,32},product,[{var,{1190,33},'TupleOfBinRels'},{var,{1190,49},'BinRel1'}]},{var,{1190,61},'BinRel2'}]},[{type,{1191,7},constraint,[{atom,{1191,7},is_subtype},[{var,{1191,7},'TupleOfBinRels'},{user_type,{1191,25},tuple_of,[{var,{1191,34},'BinRel'}]}]]},{type,{1192,7},constraint,[{atom,{1192,7},is_subtype},[{var,{1192,7},'BinRel'},{user_type,{1192,17},binary_relation,[]}]]},{type,{1193,7},constraint,[{atom,{1193,7},is_subtype},[{var,{1193,7},'BinRel1'},{user_type,{1193,18},binary_relation,[]}]]},{type,{1194,7},constraint,[{atom,{1194,7},is_subtype},[{var,{1194,7},'BinRel2'},{user_type,{1194,18},binary_relation,[]}]]}]]}]}}]}},{{function,no_elements,1},[{file,[115,111,102,115,46,101,114,108]},{location,349}],[<<110,111,95,101,108,101,109,101,110,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,110,117,109,98,101,114,32,111,102,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,111,114,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32>>,{code,[],[<<65,83,101,116>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,52,52>>,signature => [{attribute,{349,2},spec,{{no_elements,1},[{type,{349,18},bounded_fun,[{type,{349,18},'fun',[{type,{349,18},product,[{var,{349,19},'ASet'}]},{var,{349,28},'NoElements'}]},[{type,{350,7},constraint,[{atom,{350,7},is_subtype},[{var,{350,7},'ASet'},{type,{350,15},union,[{user_type,{350,15},a_set,[]},{user_type,{350,25},ordset,[]}]}]]},{type,{351,7},constraint,[{atom,{351,7},is_subtype},[{var,{351,7},'NoElements'},{type,{351,21},non_neg_integer,[]}]]}]]}]}}]}},{{function,partition,1},[{file,[115,111,102,115,46,101,114,108]},{location,1091}],[<<112,97,114,116,105,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32,116,104,101,32,117,110,105,111,110,32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,115,101,116,115,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,119,111,32,101,108,101,109,101,110,116,115,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,101,113,117,97,108,32,105,102,32,116,104,101,121,32,98,101,108,111,110,103,32,116,111,32,116,104,101,32,115,97,109,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,101,116,115,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,97,44,98,44,99,93,44,91,100,44,101,44,102,93,44,91,103,44,104,44,105,93,93,41,44,10,83,101,116,115,50,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,98,44,99,44,100,93,44,91,101,44,102,44,103,93,44,91,104,44,105,44,106,93,93,41,44,10,80,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,115,111,102,115,58,117,110,105,111,110,40,83,101,116,115,49,44,32,83,101,116,115,50,41,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,41,46,10,91,91,97,93,44,91,98,44,99,93,44,91,100,93,44,91,101,44,102,93,44,91,103,93,44,91,104,44,105,93,44,91,106,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,53,51>>,signature => [{attribute,{1091,2},spec,{{partition,1},[{type,{1091,16},bounded_fun,[{type,{1091,16},'fun',[{type,{1091,16},product,[{var,{1091,17},'SetOfSets'}]},{var,{1091,31},'Partition'}]},[{type,{1092,7},constraint,[{atom,{1092,7},is_subtype},[{var,{1092,7},'SetOfSets'},{user_type,{1092,20},set_of_sets,[]}]]},{type,{1093,7},constraint,[{atom,{1093,7},is_subtype},[{var,{1093,7},'Partition'},{user_type,{1093,20},a_set,[]}]]}]]}]}}]}},{{function,partition,2},[{file,[115,111,102,115,46,101,114,108]},{location,1099}],[<<112,97,114,116,105,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,119,111,32,101,108,101,109,101,110,116,115,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,101,113,117,97,108,32,105,102,32,116,104,101,32,114,101,115,117,108,116,115,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,97,114,101,32,101,113,117,97,108,46>>]},{pre,[],[{code,[],[<<49,62,32,83,115,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,91,97,93,44,91,98,93,44,91,99,44,100,93,44,91,101,44,102,93,93,41,44,10,83,101,116,70,117,110,32,61,32,102,117,110,40,83,41,32,45,62,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,115,111,102,115,58,110,111,95,101,108,101,109,101,110,116,115,40,83,41,41,32,101,110,100,44,10,80,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,83,101,116,70,117,110,44,32,83,115,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,41,46,10,91,91,91,97,93,44,91,98,93,93,44,91,91,99,44,100,93,44,91,101,44,102,93,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,55,48>>,signature => [{attribute,{1099,2},spec,{{partition,2},[{type,{1099,16},bounded_fun,[{type,{1099,16},'fun',[{type,{1099,16},product,[{var,{1099,17},'SetFun'},{var,{1099,25},'Set'}]},{var,{1099,33},'Partition'}]},[{type,{1100,7},constraint,[{atom,{1100,7},is_subtype},[{var,{1100,7},'SetFun'},{user_type,{1100,17},set_fun,[]}]]},{type,{1101,7},constraint,[{atom,{1101,7},is_subtype},[{var,{1101,7},'Partition'},{user_type,{1101,20},a_set,[]}]]},{type,{1102,7},constraint,[{atom,{1102,7},is_subtype},[{var,{1102,7},'Set'},{user_type,{1102,14},a_set,[]}]]}]]}]}}]}},{{function,partition,3},[{file,[115,111,102,115,46,101,114,108]},{location,1118}],[<<112,97,114,116,105,116,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,112,97,105,114,32,111,102,32,115,101,116,115,32,116,104,97,116,44,32,114,101,103,97,114,100,101,100,32,97,115,32,99,111,110,115,116,105,116,117,116,105,110,103,32,97,32,115,101,116,44,32,102,111,114,109,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<46,32,73,102,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,116,111,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,103,105,118,101,115,32,97,110,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<83,101,116,50>>]},<<44,32,116,104,101,32,101,108,101,109,101,110,116,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<83,101,116,51>>]},<<44,32,111,116,104,101,114,119,105,115,101,32,116,104,101,32,101,108,101,109,101,110,116,32,98,101,108,111,110,103,115,32,116,111,32>>,{code,[],[<<83,101,116,52>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,50,44,52,44,54,93,41,44,10,123,82,50,44,82,51,125,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,40,49,44,32,82,49,44,32,83,41,44,10,123,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,44,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,51,41,125,46,10,123,91,123,50,44,98,125,93,44,91,123,49,44,97,125,44,123,51,44,99,125,93,125>>]}]},{p,[],[{code,[],[<<112,97,114,116,105,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<123,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41,44,32,100,114,101,115,116,114,105,99,116,105,111,110,40,70,44,194,160,83,49,44,194,160,83,50,41,125>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,50,56,54>>,signature => [{attribute,{1118,2},spec,{{partition,3},[{type,{1118,16},bounded_fun,[{type,{1118,16},'fun',[{type,{1118,16},product,[{var,{1118,17},'SetFun'},{var,{1118,25},'Set1'},{var,{1118,31},'Set2'}]},{type,{1118,40},tuple,[{var,{1118,41},'Set3'},{var,{1118,47},'Set4'}]}]},[{type,{1119,7},constraint,[{atom,{1119,7},is_subtype},[{var,{1119,7},'SetFun'},{user_type,{1119,17},set_fun,[]}]]},{type,{1120,7},constraint,[{atom,{1120,7},is_subtype},[{var,{1120,7},'Set1'},{user_type,{1120,15},a_set,[]}]]},{type,{1121,7},constraint,[{atom,{1121,7},is_subtype},[{var,{1121,7},'Set2'},{user_type,{1121,15},a_set,[]}]]},{type,{1122,7},constraint,[{atom,{1122,7},is_subtype},[{var,{1122,7},'Set3'},{user_type,{1122,15},a_set,[]}]]},{type,{1123,7},constraint,[{atom,{1123,7},is_subtype},[{var,{1123,7},'Set4'},{user_type,{1123,15},a_set,[]}]]}]]}]}}]}},{{function,partition_family,2},[{file,[115,111,102,115,46,101,114,108]},{location,1404}],[<<112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,119,104,101,114,101,32,116,104,101,32,105,110,100,101,120,101,100,32,115,101,116,32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,97,114,116,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,97,114,116,105,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,119,111,32,101,108,101,109,101,110,116,115,32,97,114,101,32,99,111,110,115,105,100,101,114,101,100,32,101,113,117,97,108,32,105,102,32,116,104,101,32,114,101,115,117,108,116,115,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,97,114,101,32,116,104,101,32,115,97,109,101,32,118,97,108,117,101,32,105,46,32,84,104,105,115,32,105,32,105,115,32,116,104,101,32,105,110,100,101,120,32,116,104,97,116,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,109,97,112,115,32,111,110,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,113,117,105,118,97,108,101,110,99,101,95,99,108,97,115,115>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,113,117,105,118,97,108,101,110,99,101,32,99,108,97,115,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,97,44,97,44,97,125,44,123,97,44,97,44,98,44,98,125,44,123,97,44,98,44,98,44,98,125,93,41,44,10,83,101,116,70,117,110,32,61,32,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,65,44,95,44,67,44,95,125,41,32,45,62,32,123,65,44,67,125,32,101,110,100,125,44,10,70,32,61,32,115,111,102,115,58,112,97,114,116,105,116,105,111,110,95,102,97,109,105,108,121,40,83,101,116,70,117,110,44,32,83,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,123,97,44,97,125,44,91,123,97,44,97,44,97,44,97,125,93,125,44,123,123,97,44,98,125,44,91,123,97,44,97,44,98,44,98,125,44,123,97,44,98,44,98,44,98,125,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,48,57>>,signature => [{attribute,{1404,2},spec,{{partition_family,2},[{type,{1404,23},bounded_fun,[{type,{1404,23},'fun',[{type,{1404,23},product,[{var,{1404,24},'SetFun'},{var,{1404,32},'Set'}]},{var,{1404,40},'Family'}]},[{type,{1405,7},constraint,[{atom,{1405,7},is_subtype},[{var,{1405,7},'Family'},{user_type,{1405,17},family,[]}]]},{type,{1406,7},constraint,[{atom,{1406,7},is_subtype},[{var,{1406,7},'SetFun'},{user_type,{1406,17},set_fun,[]}]]},{type,{1407,7},constraint,[{atom,{1407,7},is_subtype},[{var,{1407,7},'Set'},{user_type,{1407,14},a_set,[]}]]}]]}]}}]}},{{function,product,1},[{file,[115,111,102,115,46,101,114,108]},{location,444}],[<<112,114,111,100,117,99,116,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116,95,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,110,111,110,45,101,109,112,116,121,32,116,117,112,108,101,32,111,102,32,115,101,116,115,32>>,{code,[],[<<84,117,112,108,101,79,102,83,101,116,115>>]},<<46,32,73,102,32,40,120,91,49,93,44,194,160,46,46,46,44,194,160,120,91,110,93,41,32,105,115,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,110,45,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<82,101,108,97,116,105,111,110>>]},<<44,32,116,104,101,110,32,120,91,105,93,32,105,115,32,100,114,97,119,110,32,102,114,111,109,32,101,108,101,109,101,110,116,32,105,32,111,102,32>>,{code,[],[<<84,117,112,108,101,79,102,83,101,116,115>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,97,44,98,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,93,41,44,10,83,51,32,61,32,115,111,102,115,58,115,101,116,40,91,120,44,121,93,41,44,10,80,51,32,61,32,115,111,102,115,58,112,114,111,100,117,99,116,40,123,83,49,44,83,50,44,83,51,125,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,51,41,46,10,91,123,97,44,49,44,120,125,44,123,97,44,49,44,121,125,44,123,97,44,50,44,120,125,44,123,97,44,50,44,121,125,44,123,98,44,49,44,120,125,44,123,98,44,49,44,121,125,44,123,98,44,50,44,120,125,44,123,98,44,50,44,121,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,51,48>>,signature => [{attribute,{444,2},spec,{{product,1},[{type,{444,14},bounded_fun,[{type,{444,14},'fun',[{type,{444,14},product,[{var,{444,15},'TupleOfSets'}]},{var,{444,31},'Relation'}]},[{type,{445,7},constraint,[{atom,{445,7},is_subtype},[{var,{445,7},'Relation'},{user_type,{445,19},relation,[]}]]},{type,{446,7},constraint,[{atom,{446,7},is_subtype},[{var,{446,7},'TupleOfSets'},{user_type,{446,22},tuple_of,[{user_type,{446,31},a_set,[]}]}]]}]]}]}}]}},{{function,product,2},[{file,[115,111,102,115,46,101,114,108]},{location,430}],[<<112,114,111,100,117,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,97,44,98,93,41,44,10,82,32,61,32,115,111,102,115,58,112,114,111,100,117,99,116,40,83,49,44,32,83,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,41,46,10,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,97,125,44,123,50,44,98,125,93>>]}]},{p,[],[{code,[],[<<112,114,111,100,117,99,116,40,83,49,44,194,160,83,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<112,114,111,100,117,99,116,40,123,83,49,44,194,160,83,50,125,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,52,57>>,signature => [{attribute,{430,2},spec,{{product,2},[{type,{430,14},bounded_fun,[{type,{430,14},'fun',[{type,{430,14},product,[{var,{430,15},'Set1'},{var,{430,21},'Set2'}]},{var,{430,30},'BinRel'}]},[{type,{431,7},constraint,[{atom,{431,7},is_subtype},[{var,{431,7},'BinRel'},{user_type,{431,17},binary_relation,[]}]]},{type,{432,7},constraint,[{atom,{432,7},is_subtype},[{var,{432,7},'Set1'},{user_type,{432,15},a_set,[]}]]},{type,{433,7},constraint,[{atom,{433,7},is_subtype},[{var,{433,7},'Set2'},{user_type,{433,15},a_set,[]}]]}]]}]}}]}},{{function,projection,2},[{file,[115,111,102,115,46,101,114,108]},{location,1029}],[<<112,114,111,106,101,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,101,116,32,99,114,101,97,116,101,100,32,98,121,32,115,117,98,115,116,105,116,117,116,105,110,103,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,98,121,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,116,111,32,116,104,101,32,101,108,101,109,101,110,116,46>>]},{p,[],[<<73,102,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,105,115,32,97,32,110,117,109,98,101,114,32,105,194,160,62,61,194,160,49,32,97,110,100,32>>,{code,[],[<<83,101,116,49>>]},<<32,105,115,32,97,32,114,101,108,97,116,105,111,110,44,32,116,104,101,110,32,116,104,101,32,114,101,116,117,114,110,101,100,32,115,101,116,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,112,114,111,106,101,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<112,114,111,106,101,99,116,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,111,110,116,111,32,99,111,111,114,100,105,110,97,116,101,32,105,46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,102,114,111,109,95,116,101,114,109,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,97,125,93,41,44,10,83,50,32,61,32,115,111,102,115,58,112,114,111,106,101,99,116,105,111,110,40,50,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,97,44,98,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,54,55>>,signature => [{attribute,{1029,2},spec,{{projection,2},[{type,{1029,17},bounded_fun,[{type,{1029,17},'fun',[{type,{1029,17},product,[{var,{1029,18},'SetFun'},{var,{1029,26},'Set1'}]},{var,{1029,35},'Set2'}]},[{type,{1030,7},constraint,[{atom,{1030,7},is_subtype},[{var,{1030,7},'SetFun'},{user_type,{1030,17},set_fun,[]}]]},{type,{1031,7},constraint,[{atom,{1031,7},is_subtype},[{var,{1031,7},'Set1'},{user_type,{1031,15},a_set,[]}]]},{type,{1032,7},constraint,[{atom,{1032,7},is_subtype},[{var,{1032,7},'Set2'},{user_type,{1032,15},a_set,[]}]]}]]}]}}]}},{{function,range,1},[{file,[115,111,102,115,46,101,114,108]},{location,622}],[<<114,97,110,103,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,97,110,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,97,110,103,101>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,98,125,44,123,50,44,98,125,44,123,50,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,114,97,110,103,101,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,97,44,98,44,99,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,51,56,54>>,signature => [{attribute,{622,2},spec,{{range,1},[{type,{622,12},bounded_fun,[{type,{622,12},'fun',[{type,{622,12},product,[{var,{622,13},'BinRel'}]},{var,{622,24},'Set'}]},[{type,{623,7},constraint,[{atom,{623,7},is_subtype},[{var,{623,7},'BinRel'},{user_type,{623,17},binary_relation,[]}]]},{type,{624,7},constraint,[{atom,{624,7},is_subtype},[{var,{624,7},'Set'},{user_type,{624,14},a_set,[]}]]}]]}]}}]}},{{function,relation,2},[{file,[115,111,102,115,46,101,114,108]},{location,255}],[<<114,101,108,97,116,105,111,110,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,48,48>>,equiv => {function,relation,1},signature => [{attribute,{255,2},spec,{{relation,2},[{type,{255,15},bounded_fun,[{type,{255,15},'fun',[{type,{255,15},product,[{var,{255,16},'Tuples'},{var,{255,24},'Type'}]},{var,{255,33},'Relation'}]},[{type,{256,7},constraint,[{atom,{256,7},is_subtype},[{var,{256,7},'N'},{type,{256,12},integer,[]}]]},{type,{257,7},constraint,[{atom,{257,7},is_subtype},[{var,{257,7},'Type'},{type,{257,15},union,[{var,{257,15},'N'},{user_type,{257,19},type,[]}]}]]},{type,{258,7},constraint,[{atom,{258,7},is_subtype},[{var,{258,7},'Relation'},{user_type,{258,19},relation,[]}]]},{type,{259,7},constraint,[{atom,{259,7},is_subtype},[{var,{259,7},'Tuples'},{type,{259,17},list,[{type,{259,18},tuple,any}]}]]}]]}]}}]}},{{function,relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,243}],[<<114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,111,110>>]},<<46,32>>,{code,[],[<<114,101,108,97,116,105,111,110,40,82,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,82,44,194,160,84,41>>]},<<44,32,105,102,32,84,32,105,115,32,97,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,97,110,100,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,32,114,101,108,97,116,105,111,110,46,32,73,102,32>>,{code,[],[<<84,121,112,101>>]},<<32,105,115,32,97,110,32,105,110,116,101,103,101,114,32,78,44,32,116,104,101,110,32>>,{code,[],[<<91,123,97,116,111,109,44,194,160,46,46,46,44,194,160,97,116,111,109,125,93,41>>]},<<44,32,119,104,101,114,101,32,116,104,101,32,116,117,112,108,101,32,115,105,122,101,32,105,115,32,78,44,32,105,115,32,117,115,101,100,32,97,115,32,116,121,112,101,32,111,102,32,116,104,101,32,114,101,108,97,116,105,111,110,46,32,73,102,32,110,111,32,116,121,112,101,32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,102,105,114,115,116,32,116,117,112,108,101,32,111,102,32>>,{code,[],[<<84,117,112,108,101,115>>]},<<32,105,115,32,117,115,101,100,32,105,102,32,116,104,101,114,101,32,105,115,32,115,117,99,104,32,97,32,116,117,112,108,101,46,32>>,{code,[],[<<114,101,108,97,116,105,111,110,40,91,93,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<114,101,108,97,116,105,111,110,40,91,93,44,194,160,50,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,48,48>>,signature => [{attribute,{243,2},spec,{{relation,1},[{type,{243,15},bounded_fun,[{type,{243,15},'fun',[{type,{243,15},product,[{var,{243,16},'Tuples'}]},{var,{243,27},'Relation'}]},[{type,{244,7},constraint,[{atom,{244,7},is_subtype},[{var,{244,7},'Relation'},{user_type,{244,19},relation,[]}]]},{type,{245,7},constraint,[{atom,{245,7},is_subtype},[{var,{245,7},'Tuples'},{type,{245,17},list,[{type,{245,18},tuple,any}]}]]}]]}]}}]}},{{function,relation_to_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,600}],[<<114,101,108,97,116,105,111,110,95,116,111,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<32,115,117,99,104,32,116,104,97,116,32,116,104,101,32,105,110,100,101,120,32,115,101,116,32,105,115,32,101,113,117,97,108,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,100,111,109,97,105,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<100,111,109,97,105,110>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<44,32,97,110,100,32>>,{code,[],[<<70,97,109,105,108,121>>]},<<91,105,93,32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,109,97,103,101>>]},<<32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,105,32,117,110,100,101,114,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,98,44,49,125,44,123,99,44,50,125,44,123,99,44,51,125,93,41,44,10,70,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,95,116,111,95,102,97,109,105,108,121,40,82,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,70,41,46,10,91,123,98,44,91,49,93,125,44,123,99,44,91,50,44,51,93,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,49,57>>,signature => [{attribute,{600,2},spec,{{relation_to_family,1},[{type,{600,25},bounded_fun,[{type,{600,25},'fun',[{type,{600,25},product,[{var,{600,26},'BinRel'}]},{var,{600,37},'Family'}]},[{type,{601,7},constraint,[{atom,{601,7},is_subtype},[{var,{601,7},'Family'},{user_type,{601,17},family,[]}]]},{type,{602,7},constraint,[{atom,{602,7},is_subtype},[{var,{602,7},'BinRel'},{user_type,{602,17},binary_relation,[]}]]}]]}]}}]}},{{function,relative_product,2},[{file,[115,111,102,115,46,101,114,108]},{location,657}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,51,55>>,equiv => {function,relative_product,1},signature => [{attribute,{657,2},spec,{{relative_product,2},[{type,{657,23},bounded_fun,[{type,{657,23},'fun',[{type,{657,23},product,[{var,{657,24},'ListOfBinRels'},{var,{657,39},'BinRel1'}]},{var,{657,51},'BinRel2'}]},[{type,{658,7},constraint,[{atom,{658,7},is_subtype},[{var,{658,7},'ListOfBinRels'},{type,{658,24},nonempty_list,[{var,{658,25},'BinRel'}]}]]},{type,{659,7},constraint,[{atom,{659,7},is_subtype},[{var,{659,7},'BinRel'},{user_type,{659,17},binary_relation,[]}]]},{type,{660,7},constraint,[{atom,{660,7},is_subtype},[{var,{660,7},'BinRel1'},{user_type,{660,18},binary_relation,[]}]]},{type,{661,7},constraint,[{atom,{661,7},is_subtype},[{var,{661,7},'BinRel2'},{user_type,{661,18},binary_relation,[]}]]}]]}]}}]}},{{function,relative_product,1},[{file,[115,111,102,115,46,101,114,108]},{location,641}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,49>>],#{<<101,110>> => [{p,[],[<<73,102,32>>,{code,[],[<<76,105,115,116,79,102,66,105,110,82,101,108,115>>]},<<32,105,115,32,97,32,110,111,110,45,101,109,112,116,121,32,108,105,115,116,32,91,82,91,49,93,44,194,160,46,46,46,44,194,160,82,91,110,93,93,32,111,102,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,105,115,32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,44,32,116,104,101,110,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<32,105,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,117,112,108,101,95,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,32,40,82,91,105,93,44,194,160,46,46,46,44,194,160,82,91,110,93,41,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{p,[],[<<73,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,105,115,32,111,109,105,116,116,101,100,44,32,116,104,101,32,114,101,108,97,116,105,111,110,32,111,102,32,101,113,117,97,108,105,116,121,32,98,101,116,119,101,101,110,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,67,97,114,116,101,115,105,97,110,95,112,114,111,100,117,99,116,95,116,117,112,108,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<67,97,114,116,101,115,105,97,110,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,114,97,110,103,101,115,32,111,102,32,82,91,105,93,44,32,114,97,110,103,101,194,160,82,91,49,93,194,160,195,151,194,160,46,46,46,194,160,195,151,194,160,114,97,110,103,101,194,160,82,91,110,93,44,32,105,115,32,117,115,101,100,32,105,110,115,116,101,97,100,32,40,105,110,116,117,105,116,105,118,101,108,121,44,32,110,111,116,104,105,110,103,32,105,115,32,34,108,111,115,116,34,41,46>>]},{pre,[],[{code,[],[<<49,62,32,84,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,97,97,125,44,123,50,44,98,125,93,41,44,10,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,117,125,44,123,50,44,118,125,44,123,51,44,99,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,91,84,82,44,32,82,49,93,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,123,97,44,117,125,125,44,123,49,44,123,97,97,44,117,125,125,44,123,50,44,123,98,44,118,125,125,93>>]}]},{p,[],[<<78,111,116,105,99,101,32,116,104,97,116,32>>,{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,91,82,49,93,44,194,160,82,50,41>>]},<<32,105,115,32,100,105,102,102,101,114,101,110,116,32,102,114,111,109,32>>,{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,82,49,44,194,160,82,50,41>>]},<<59,32,116,104,101,32,108,105,115,116,32,111,102,32,111,110,101,32,101,108,101,109,101,110,116,32,105,115,32,110,111,116,32,105,100,101,110,116,105,102,105,101,100,32,119,105,116,104,32,116,104,101,32,101,108,101,109,101,110,116,32,105,116,115,101,108,102,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,51,55>>,signature => [{attribute,{641,2},spec,{{relative_product,1},[{type,{641,23},bounded_fun,[{type,{641,23},'fun',[{type,{641,23},product,[{var,{641,24},'ListOfBinRels'}]},{var,{641,42},'BinRel2'}]},[{type,{642,7},constraint,[{atom,{642,7},is_subtype},[{var,{642,7},'ListOfBinRels'},{type,{642,24},nonempty_list,[{var,{642,25},'BinRel'}]}]]},{type,{643,7},constraint,[{atom,{643,7},is_subtype},[{var,{643,7},'BinRel'},{user_type,{643,17},binary_relation,[]}]]},{type,{644,7},constraint,[{atom,{644,7},is_subtype},[{var,{644,7},'BinRel2'},{user_type,{644,18},binary_relation,[]}]]}]]}]}}]}},{{function,relative_product,2},[{file,[115,111,102,115,46,101,114,108]},{location,657}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,115,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,54,56>>,signature => [{attribute,{657,2},spec,{{relative_product,2},[{type,{662,23},bounded_fun,[{type,{662,23},'fun',[{type,{662,23},product,[{var,{662,24},'BinRel1'},{var,{662,33},'BinRel2'}]},{var,{662,45},'BinRel3'}]},[{type,{663,7},constraint,[{atom,{663,7},is_subtype},[{var,{663,7},'BinRel1'},{user_type,{663,18},binary_relation,[]}]]},{type,{664,7},constraint,[{atom,{664,7},is_subtype},[{var,{664,7},'BinRel2'},{user_type,{664,18},binary_relation,[]}]]},{type,{665,7},constraint,[{atom,{665,7},is_subtype},[{var,{665,7},'BinRel3'},{user_type,{665,18},binary_relation,[]}]]}]]}]}}]}},{{function,relative_product1,2},[{file,[115,111,102,115,46,101,114,108]},{location,685}],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,108,97,116,105,118,101,32,112,114,111,100,117,99,116>>]},<<32,111,102,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,99,111,110,118,101,114,115,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<99,111,110,118,101,114,115,101>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,97,110,100,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,49,44,97,97,125,44,123,50,44,98,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,117,125,44,123,50,44,118,125,44,123,51,44,99,125,93,41,44,10,82,51,32,61,32,115,111,102,115,58,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,40,82,49,44,32,82,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,51,41,46,10,91,123,97,44,117,125,44,123,97,97,44,117,125,44,123,98,44,118,125,93>>]}]},{p,[],[{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,40,82,49,44,194,160,82,50,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,40,99,111,110,118,101,114,115,101,40,82,49,41,44,194,160,82,50,41>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,52,55,57>>,signature => [{attribute,{685,2},spec,{{relative_product1,2},[{type,{685,24},bounded_fun,[{type,{685,24},'fun',[{type,{685,24},product,[{var,{685,25},'BinRel1'},{var,{685,34},'BinRel2'}]},{var,{685,46},'BinRel3'}]},[{type,{686,7},constraint,[{atom,{686,7},is_subtype},[{var,{686,7},'BinRel1'},{user_type,{686,18},binary_relation,[]}]]},{type,{687,7},constraint,[{atom,{687,7},is_subtype},[{var,{687,7},'BinRel2'},{user_type,{687,18},binary_relation,[]}]]},{type,{688,7},constraint,[{atom,{688,7},is_subtype},[{var,{688,7},'BinRel3'},{user_type,{688,18},binary_relation,[]}]]}]]}]}}]}},{{function,restriction,2},[{file,[115,111,102,115,46,101,114,108]},{location,826}],[<<114,101,115,116,114,105,99,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,114,101,115,116,114,105,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<114,101,115,116,114,105,99,116,105,111,110>>]},<<32,111,102,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<32,116,111,32>>,{code,[],[<<83,101,116>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,44,52,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,115,116,114,105,99,116,105,111,110,40,82,49,44,32,83,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,97,125,44,123,50,44,98,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,48,48>>,signature => [{attribute,{826,2},spec,{{restriction,2},[{type,{826,18},bounded_fun,[{type,{826,18},'fun',[{type,{826,18},product,[{var,{826,19},'BinRel1'},{var,{826,28},'Set'}]},{var,{826,36},'BinRel2'}]},[{type,{827,7},constraint,[{atom,{827,7},is_subtype},[{var,{827,7},'BinRel1'},{user_type,{827,18},binary_relation,[]}]]},{type,{828,7},constraint,[{atom,{828,7},is_subtype},[{var,{828,7},'BinRel2'},{user_type,{828,18},binary_relation,[]}]]},{type,{829,7},constraint,[{atom,{829,7},is_subtype},[{var,{829,7},'Set'},{user_type,{829,14},a_set,[]}]]}]]}]}}]}},{{function,restriction,3},[{file,[115,111,102,115,46,101,114,108]},{location,892}],[<<114,101,115,116,114,105,99,116,105,111,110,47,51>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,117,98,115,101,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,99,111,110,116,97,105,110,105,110,103,32,116,104,111,115,101,32,101,108,101,109,101,110,116,115,32,116,104,97,116,32,103,105,118,101,115,32,97,110,32,101,108,101,109,101,110,116,32,105,110,32>>,{code,[],[<<83,101,116,50>>]},<<32,97,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,97,125,44,123,50,44,98,125,44,123,51,44,99,125,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,98,44,99,44,100,93,41,44,10,83,51,32,61,32,115,111,102,115,58,114,101,115,116,114,105,99,116,105,111,110,40,50,44,32,83,49,44,32,83,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,51,41,46,10,91,123,50,44,98,125,44,123,51,44,99,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,49,54>>,signature => [{attribute,{892,2},spec,{{restriction,3},[{type,{892,18},bounded_fun,[{type,{892,18},'fun',[{type,{892,18},product,[{var,{892,19},'SetFun'},{var,{892,27},'Set1'},{var,{892,33},'Set2'}]},{var,{892,42},'Set3'}]},[{type,{893,7},constraint,[{atom,{893,7},is_subtype},[{var,{893,7},'SetFun'},{user_type,{893,17},set_fun,[]}]]},{type,{894,7},constraint,[{atom,{894,7},is_subtype},[{var,{894,7},'Set1'},{user_type,{894,15},a_set,[]}]]},{type,{895,7},constraint,[{atom,{895,7},is_subtype},[{var,{895,7},'Set2'},{user_type,{895,15},a_set,[]}]]},{type,{896,7},constraint,[{atom,{896,7},is_subtype},[{var,{896,7},'Set3'},{user_type,{896,15},a_set,[]}]]}]]}]}}]}},{{function,set,2},[{file,[115,111,102,115,46,101,114,108]},{location,204}],[<<115,101,116,47,50>>],#{},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,51,50>>,equiv => {function,set,1},signature => [{attribute,{204,2},spec,{{set,2},[{type,{204,10},bounded_fun,[{type,{204,10},'fun',[{type,{204,10},product,[{var,{204,11},'Terms'},{var,{204,18},'Type'}]},{var,{204,27},'Set'}]},[{type,{205,7},constraint,[{atom,{205,7},is_subtype},[{var,{205,7},'Set'},{user_type,{205,14},a_set,[]}]]},{type,{206,7},constraint,[{atom,{206,7},is_subtype},[{var,{206,7},'Terms'},{type,{206,16},list,[{type,{206,17},term,[]}]}]]},{type,{207,7},constraint,[{atom,{207,7},is_subtype},[{var,{207,7},'Type'},{user_type,{207,15},type,[]}]]}]]}]}}]}},{{function,set,1},[{file,[115,111,102,115,46,101,114,108]},{location,195}],[<<115,101,116,47,49>>],#{<<101,110>> => [{p,[],[<<67,114,101,97,116,101,115,32,97,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<46,32>>,{code,[],[<<115,101,116,40,76,44,194,160,84,41>>]},<<32,105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111,32>>,{code,[],[<<102,114,111,109,95,116,101,114,109,40,76,44,194,160,84,41>>]},<<44,32,105,102,32,116,104,101,32,114,101,115,117,108,116,32,105,115,32,97,110,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46,32,73,102,32,110,111,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,105,115,32,101,120,112,108,105,99,105,116,108,121,32,115,112,101,99,105,102,105,101,100,44,32>>,{code,[],[<<91,97,116,111,109,93>>]},<<32,105,115,32,117,115,101,100,32,97,115,32,116,104,101,32,115,101,116,32,116,121,112,101,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,51,50>>,signature => [{attribute,{195,2},spec,{{set,1},[{type,{195,10},bounded_fun,[{type,{195,10},'fun',[{type,{195,10},product,[{var,{195,11},'Terms'}]},{var,{195,21},'Set'}]},[{type,{196,7},constraint,[{atom,{196,7},is_subtype},[{var,{196,7},'Set'},{user_type,{196,14},a_set,[]}]]},{type,{197,7},constraint,[{atom,{197,7},is_subtype},[{var,{197,7},'Terms'},{type,{197,16},list,[{type,{197,17},term,[]}]}]]}]]}]}}]}},{{function,specification,2},[{file,[115,111,102,115,46,101,114,108]},{location,359}],[<<115,112,101,99,105,102,105,99,97,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,115,101,116,32,99,111,110,116,97,105,110,105,110,103,32,101,118,101,114,121,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,102,111,114,32,119,104,105,99,104,32>>,{code,[],[<<70,117,110>>]},<<32,114,101,116,117,114,110,115,32>>,{code,[],[<<116,114,117,101>>]},<<46,32,73,102,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,32,116,117,112,108,101,32>>,{code,[],[<<123,101,120,116,101,114,110,97,108,44,194,160,70,117,110,50,125>>]},<<44,32>>,{code,[],[<<70,117,110,50>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,111,102,32,101,97,99,104,32,101,108,101,109,101,110,116,44,32,111,116,104,101,114,119,105,115,101,32>>,{code,[],[<<70,117,110>>]},<<32,105,115,32,97,112,112,108,105,101,100,32,116,111,32,101,97,99,104,32,101,108,101,109,101,110,116,46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,97,44,49,125,44,123,98,44,50,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,120,44,49,125,44,123,120,44,50,125,44,123,121,44,51,125,93,41,44,10,83,49,32,61,32,115,111,102,115,58,102,114,111,109,95,115,101,116,115,40,91,82,49,44,82,50,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,112,101,99,105,102,105,99,97,116,105,111,110,40,102,117,110,32,115,111,102,115,58,105,115,95,97,95,102,117,110,99,116,105,111,110,47,49,44,32,83,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,50,41,46,10,91,91,123,97,44,49,125,44,123,98,44,50,125,93,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,52,53>>,signature => [{attribute,{359,2},spec,{{specification,2},[{type,{359,20},bounded_fun,[{type,{359,20},'fun',[{type,{359,20},product,[{var,{359,21},'Fun'},{var,{359,26},'Set1'}]},{var,{359,35},'Set2'}]},[{type,{360,7},constraint,[{atom,{360,7},is_subtype},[{var,{360,7},'Fun'},{user_type,{360,14},spec_fun,[]}]]},{type,{361,7},constraint,[{atom,{361,7},is_subtype},[{var,{361,7},'Set1'},{user_type,{361,15},a_set,[]}]]},{type,{362,7},constraint,[{atom,{362,7},is_subtype},[{var,{362,7},'Set2'},{user_type,{362,15},a_set,[]}]]}]]}]}}]}},{{function,strict_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,752}],[<<115,116,114,105,99,116,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,116,114,105,99,116,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,116,114,105,99,116,32,114,101,108,97,116,105,111,110>>]},<<32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,49,125,44,123,49,44,50,125,44,123,50,44,49,125,44,123,50,44,50,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,115,116,114,105,99,116,95,114,101,108,97,116,105,111,110,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,50,125,44,123,50,44,49,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,54,54>>,signature => [{attribute,{752,2},spec,{{strict_relation,1},[{type,{752,22},bounded_fun,[{type,{752,22},'fun',[{type,{752,22},product,[{var,{752,23},'BinRel1'}]},{var,{752,35},'BinRel2'}]},[{type,{753,7},constraint,[{atom,{753,7},is_subtype},[{var,{753,7},'BinRel1'},{user_type,{753,18},binary_relation,[]}]]},{type,{754,7},constraint,[{atom,{754,7},is_subtype},[{var,{754,7},'BinRel2'},{user_type,{754,18},binary_relation,[]}]]}]]}]}}]}},{{function,substitution,2},[{file,[115,111,102,115,46,101,114,108]},{location,1048}],[<<115,117,98,115,116,105,116,117,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,102,117,110,99,116,105,111,110,44,32,116,104,101,32,100,111,109,97,105,110,32,111,102,32,119,104,105,99,104,32,105,115,32>>,{code,[],[<<83,101,116,49>>]},<<46,32,84,104,101,32,118,97,108,117,101,32,111,102,32,97,110,32,101,108,101,109,101,110,116,32,111,102,32,116,104,101,32,100,111,109,97,105,110,32,105,115,32,116,104,101,32,114,101,115,117,108,116,32,111,102,32,97,112,112,108,121,105,110,103,32>>,{code,[],[<<83,101,116,70,117,110>>]},<<32,116,111,32,116,104,101,32,101,108,101,109,101,110,116,46>>]},{pre,[],[{code,[],[<<49,62,32,76,32,61,32,91,123,97,44,49,125,44,123,98,44,50,125,93,46,10,91,123,97,44,49,125,44,123,98,44,50,125,93,10,50,62,32,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,112,114,111,106,101,99,116,105,111,110,40,49,44,115,111,102,115,58,114,101,108,97,116,105,111,110,40,76,41,41,41,46,10,91,97,44,98,93,10,51,62,32,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,115,117,98,115,116,105,116,117,116,105,111,110,40,49,44,115,111,102,115,58,114,101,108,97,116,105,111,110,40,76,41,41,41,46,10,91,123,123,97,44,49,125,44,97,125,44,123,123,98,44,50,125,44,98,125,93,10,52,62,32,83,101,116,70,117,110,32,61,32,123,101,120,116,101,114,110,97,108,44,32,102,117,110,40,123,65,44,95,125,61,69,41,32,45,62,32,123,69,44,65,125,32,101,110,100,125,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,115,111,102,115,58,112,114,111,106,101,99,116,105,111,110,40,83,101,116,70,117,110,44,115,111,102,115,58,114,101,108,97,116,105,111,110,40,76,41,41,41,46,10,91,123,123,97,44,49,125,44,97,125,44,123,123,98,44,50,125,44,98,125,93>>]}]},{p,[],[<<84,104,101,32,114,101,108,97,116,105,111,110,32,111,102,32,101,113,117,97,108,105,116,121,32,98,101,116,119,101,101,110,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,123,97,44,98,44,99,125,58>>]},{pre,[],[{code,[],[<<49,62,32,73,32,61,32,115,111,102,115,58,115,117,98,115,116,105,116,117,116,105,111,110,40,102,117,110,40,65,41,32,45,62,32,65,32,101,110,100,44,32,115,111,102,115,58,115,101,116,40,91,97,44,98,44,99,93,41,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,73,41,46,10,91,123,97,44,97,125,44,123,98,44,98,125,44,123,99,44,99,125,93>>]}]},{p,[],[<<76,101,116,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,98,101,32,97,32,115,101,116,32,111,102,32,115,101,116,115,32,97,110,100,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,97,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,109,97,112,115,32,101,97,99,104,32,101,108,101,109,101,110,116,32>>,{code,[],[<<83,101,116>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,111,110,116,111,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<105,109,97,103,101>>]},<<32,111,102,32>>,{code,[],[<<83,101,116>>]},<<32,117,110,100,101,114,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,114,101,116,117,114,110,101,100,32,98,121,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,117,110,99,116,105,111,110,58>>]},{pre,[],[{code,[],[<<105,109,97,103,101,115,40,83,101,116,79,102,83,101,116,115,44,32,66,105,110,82,101,108,41,32,45,62,10,32,32,32,70,117,110,32,61,32,102,117,110,40,83,101,116,41,32,45,62,32,115,111,102,115,58,105,109,97,103,101,40,66,105,110,82,101,108,44,32,83,101,116,41,32,101,110,100,44,10,32,32,32,115,111,102,115,58,115,117,98,115,116,105,116,117,116,105,111,110,40,70,117,110,44,32,83,101,116,79,102,83,101,116,115,41,46>>]}]},{p,[],[<<69,120,116,101,114,110,97,108,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,32,97,114,101,32,114,101,112,114,101,115,101,110,116,101,100,32,97,115,32,115,111,114,116,101,100,32,108,105,115,116,115,46,32,83,111,44,32,99,114,101,97,116,105,110,103,32,116,104,101,32,105,109,97,103,101,32,111,102,32,97,32,115,101,116,32,117,110,100,101,114,32,97,32,114,101,108,97,116,105,111,110,32,82,32,99,97,110,32,116,114,97,118,101,114,115,101,32,97,108,108,32,101,108,101,109,101,110,116,115,32,111,102,32,82,32,40,116,111,32,116,104,97,116,32,99,111,109,101,115,32,116,104,101,32,115,111,114,116,105,110,103,32,111,102,32,114,101,115,117,108,116,115,44,32,116,104,101,32,105,109,97,103,101,41,46,32,73,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,105,109,97,103,101,47,50>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,109,102,97>>}],[{code,[],[<<105,109,97,103,101,47,50>>]}]},<<44,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,116,114,97,118,101,114,115,101,100,32,111,110,99,101,32,102,111,114,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<44,32,119,104,105,99,104,32,99,97,110,32,116,97,107,101,32,116,111,111,32,108,111,110,103,46,32,84,104,101,32,102,111,108,108,111,119,105,110,103,32,101,102,102,105,99,105,101,110,116,32,102,117,110,99,116,105,111,110,32,99,97,110,32,98,101,32,117,115,101,100,32,105,110,115,116,101,97,100,32,117,110,100,101,114,32,116,104,101,32,97,115,115,117,109,112,116,105,111,110,32,116,104,97,116,32,116,104,101,32,105,109,97,103,101,32,111,102,32,101,97,99,104,32,101,108,101,109,101,110,116,32,111,102,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<32,117,110,100,101,114,32>>,{code,[],[<<66,105,110,82,101,108>>]},<<32,105,115,32,110,111,110,45,101,109,112,116,121,58>>]},{pre,[],[{code,[],[<<105,109,97,103,101,115,50,40,83,101,116,79,102,83,101,116,115,44,32,66,105,110,82,101,108,41,32,45,62,10,32,32,32,67,82,32,61,32,115,111,102,115,58,99,97,110,111,110,105,99,97,108,95,114,101,108,97,116,105,111,110,40,83,101,116,79,102,83,101,116,115,41,44,10,32,32,32,82,32,61,32,115,111,102,115,58,114,101,108,97,116,105,118,101,95,112,114,111,100,117,99,116,49,40,67,82,44,32,66,105,110,82,101,108,41,44,10,32,32,32,115,111,102,115,58,114,101,108,97,116,105,111,110,95,116,111,95,102,97,109,105,108,121,40,82,41,46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,53,56,50>>,signature => [{attribute,{1048,2},spec,{{substitution,2},[{type,{1048,19},bounded_fun,[{type,{1048,19},'fun',[{type,{1048,19},product,[{var,{1048,20},'SetFun'},{var,{1048,28},'Set1'}]},{var,{1048,37},'Set2'}]},[{type,{1049,7},constraint,[{atom,{1049,7},is_subtype},[{var,{1049,7},'SetFun'},{user_type,{1049,17},set_fun,[]}]]},{type,{1050,7},constraint,[{atom,{1050,7},is_subtype},[{var,{1050,7},'Set1'},{user_type,{1050,15},a_set,[]}]]},{type,{1051,7},constraint,[{atom,{1051,7},is_subtype},[{var,{1051,7},'Set2'},{user_type,{1051,15},a_set,[]}]]}]]}]}}]}},{{function,symdiff,2},[{file,[115,111,102,115,46,101,114,108]},{location,408}],[<<115,121,109,100,105,102,102,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,121,109,109,101,116,114,105,99,95,100,105,102,102,101,114,101,110,99,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<115,121,109,109,101,116,114,105,99,32,100,105,102,102,101,114,101,110,99,101>>]},<<32,40,111,114,32,116,104,101,32,66,111,111,108,101,97,110,32,115,117,109,41,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,83,49,32,61,32,115,111,102,115,58,115,101,116,40,91,49,44,50,44,51,93,41,44,10,83,50,32,61,32,115,111,102,115,58,115,101,116,40,91,50,44,51,44,52,93,41,44,10,80,32,61,32,115,111,102,115,58,115,121,109,100,105,102,102,40,83,49,44,32,83,50,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,80,41,46,10,91,49,44,52,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,51,49>>,signature => [{attribute,{408,2},spec,{{symdiff,2},[{type,{408,14},bounded_fun,[{type,{408,14},'fun',[{type,{408,14},product,[{var,{408,15},'Set1'},{var,{408,21},'Set2'}]},{var,{408,30},'Set3'}]},[{type,{409,7},constraint,[{atom,{409,7},is_subtype},[{var,{409,7},'Set1'},{user_type,{409,15},a_set,[]}]]},{type,{410,7},constraint,[{atom,{410,7},is_subtype},[{var,{410,7},'Set2'},{user_type,{410,15},a_set,[]}]]},{type,{411,7},constraint,[{atom,{411,7},is_subtype},[{var,{411,7},'Set3'},{user_type,{411,15},a_set,[]}]]}]]}]}}]}},{{function,symmetric_partition,2},[{file,[115,111,102,115,46,101,114,108]},{location,418}],[<<115,121,109,109,101,116,114,105,99,95,112,97,114,116,105,116,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,116,114,105,112,108,101,32,111,102,32,115,101,116,115,58>>]},{ul,[],[{li,[],[{code,[],[<<83,101,116,51>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,116,104,97,116,32,100,111,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{li,[],[{code,[],[<<83,101,116,52>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,116,104,97,116,32,98,101,108,111,110,103,32,116,111,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]},{li,[],[{code,[],[<<83,101,116,53>>]},<<32,99,111,110,116,97,105,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32>>,{code,[],[<<83,101,116,50>>]},<<32,116,104,97,116,32,100,111,32,110,111,116,32,98,101,108,111,110,103,32,116,111,32>>,{code,[],[<<83,101,116,49>>]},<<46>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,52,55>>,signature => [{attribute,{418,2},spec,{{symmetric_partition,2},[{type,{418,26},bounded_fun,[{type,{418,26},'fun',[{type,{418,26},product,[{var,{418,27},'Set1'},{var,{418,33},'Set2'}]},{type,{418,42},tuple,[{var,{418,43},'Set3'},{var,{418,49},'Set4'},{var,{418,55},'Set5'}]}]},[{type,{419,7},constraint,[{atom,{419,7},is_subtype},[{var,{419,7},'Set1'},{user_type,{419,15},a_set,[]}]]},{type,{420,7},constraint,[{atom,{420,7},is_subtype},[{var,{420,7},'Set2'},{user_type,{420,15},a_set,[]}]]},{type,{421,7},constraint,[{atom,{421,7},is_subtype},[{var,{421,7},'Set3'},{user_type,{421,15},a_set,[]}]]},{type,{422,7},constraint,[{atom,{422,7},is_subtype},[{var,{422,7},'Set4'},{user_type,{422,15},a_set,[]}]]},{type,{423,7},constraint,[{atom,{423,7},is_subtype},[{var,{423,7},'Set5'},{user_type,{423,15},a_set,[]}]]}]]}]}}]}},{{function,to_external,1},[{file,[115,111,102,115,46,101,114,108]},{location,319}],[<<116,111,95,101,120,116,101,114,110,97,108,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<32,111,102,32,97,110,32,97,116,111,109,105,99,44,32,111,114,100,101,114,101,100,44,32,111,114,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,54,56>>,signature => [{attribute,{319,2},spec,{{to_external,1},[{type,{319,18},bounded_fun,[{type,{319,18},'fun',[{type,{319,18},product,[{var,{319,19},'AnySet'}]},{var,{319,30},'ExternalSet'}]},[{type,{320,7},constraint,[{atom,{320,7},is_subtype},[{var,{320,7},'ExternalSet'},{user_type,{320,22},external_set,[]}]]},{type,{321,7},constraint,[{atom,{321,7},is_subtype},[{var,{321,7},'AnySet'},{user_type,{321,17},anyset,[]}]]}]]}]}}]}},{{function,to_sets,1},[{file,[115,111,102,115,46,101,114,108]},{location,335}],[<<116,111,95,115,101,116,115,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,111,114,100,101,114,101,100,32,115,101,116,32>>,{code,[],[<<65,83,101,116>>]},<<32,97,115,32,97,32,116,117,112,108,101,32,111,102,32,115,101,116,115,44,32,97,110,100,32,116,104,101,32,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,32,117,110,111,114,100,101,114,101,100,32,115,101,116,32>>,{code,[],[<<65,83,101,116>>]},<<32,97,115,32,97,32,115,111,114,116,101,100,32,108,105,115,116,32,111,102,32,115,101,116,115,32,119,105,116,104,111,117,116,32,100,117,112,108,105,99,97,116,101,115,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,55,55>>,signature => [{attribute,{335,2},spec,{{to_sets,1},[{type,{335,14},bounded_fun,[{type,{335,14},'fun',[{type,{335,14},product,[{var,{335,15},'ASet'}]},{var,{335,24},'Sets'}]},[{type,{336,7},constraint,[{atom,{336,7},is_subtype},[{var,{336,7},'ASet'},{type,{336,15},union,[{user_type,{336,15},a_set,[]},{user_type,{336,25},ordset,[]}]}]]},{type,{337,7},constraint,[{atom,{337,7},is_subtype},[{var,{337,7},'Sets'},{type,{337,15},union,[{user_type,{337,15},tuple_of,[{var,{337,24},'AnySet'}]},{type,{337,34},list,[{var,{337,35},'AnySet'}]}]}]]},{type,{338,7},constraint,[{atom,{338,7},is_subtype},[{var,{338,7},'AnySet'},{user_type,{338,17},anyset,[]}]]}]]}]}}]}},{{function,type,1},[{file,[115,111,102,115,46,101,114,108]},{location,327}],[<<116,121,112,101,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<32,111,102,32,97,110,32,97,116,111,109,105,99,44,32,111,114,100,101,114,101,100,44,32,111,114,32,117,110,111,114,100,101,114,101,100,32,115,101,116,46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,56,56>>,signature => [{attribute,{327,2},spec,{{type,1},[{type,{327,11},bounded_fun,[{type,{327,11},'fun',[{type,{327,11},product,[{var,{327,12},'AnySet'}]},{var,{327,23},'Type'}]},[{type,{328,7},constraint,[{atom,{328,7},is_subtype},[{var,{328,7},'AnySet'},{user_type,{328,17},anyset,[]}]]},{type,{329,7},constraint,[{atom,{329,7},is_subtype},[{var,{329,7},'Type'},{user_type,{329,15},type,[]}]]}]]}]}}]}},{{function,union,1},[{file,[115,111,102,115,46,101,114,108]},{location,553}],[<<117,110,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110,95,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,111,110>>]},<<32,111,102,32,116,104,101,32,115,101,116,32,111,102,32,115,101,116,115,32>>,{code,[],[<<83,101,116,79,102,83,101,116,115>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,54,57,55>>,signature => [{attribute,{553,2},spec,{{union,1},[{type,{553,12},bounded_fun,[{type,{553,12},'fun',[{type,{553,12},product,[{var,{553,13},'SetOfSets'}]},{var,{553,27},'Set'}]},[{type,{554,7},constraint,[{atom,{554,7},is_subtype},[{var,{554,7},'Set'},{user_type,{554,14},a_set,[]}]]},{type,{555,7},constraint,[{atom,{555,7},is_subtype},[{var,{555,7},'SetOfSets'},{user_type,{555,20},set_of_sets,[]}]]}]]}]}}]}},{{function,union,2},[{file,[115,111,102,115,46,101,114,108]},{location,378}],[<<117,110,105,111,110,47,50>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,117,110,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,105,111,110>>]},<<32,111,102,32>>,{code,[],[<<83,101,116,49>>]},<<32,97,110,100,32>>,{code,[],[<<83,101,116,50>>]},<<46>>]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,55,48,54>>,signature => [{attribute,{378,2},spec,{{union,2},[{type,{378,12},bounded_fun,[{type,{378,12},'fun',[{type,{378,12},product,[{var,{378,13},'Set1'},{var,{378,19},'Set2'}]},{var,{378,28},'Set3'}]},[{type,{379,7},constraint,[{atom,{379,7},is_subtype},[{var,{379,7},'Set1'},{user_type,{379,15},a_set,[]}]]},{type,{380,7},constraint,[{atom,{380,7},is_subtype},[{var,{380,7},'Set2'},{user_type,{380,15},a_set,[]}]]},{type,{381,7},constraint,[{atom,{381,7},is_subtype},[{var,{381,7},'Set3'},{user_type,{381,15},a_set,[]}]]}]]}]}}]}},{{function,union_of_family,1},[{file,[115,111,102,115,46,101,114,108]},{location,1288}],[<<117,110,105,111,110,95,111,102,95,102,97,109,105,108,121,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,116,104,101,32,117,110,105,111,110,32,111,102,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32>>,{code,[],[<<70,97,109,105,108,121>>]},<<46>>]},{pre,[],[{code,[],[<<49,62,32,70,32,61,32,115,111,102,115,58,102,97,109,105,108,121,40,91,123,97,44,91,48,44,50,44,52,93,125,44,123,98,44,91,48,44,49,44,50,93,125,44,123,99,44,91,50,44,51,93,125,93,41,44,10,83,32,61,32,115,111,102,115,58,117,110,105,111,110,95,111,102,95,102,97,109,105,108,121,40,70,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,83,41,46,10,91,48,44,49,44,50,44,51,44,52,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,55,49,53>>,signature => [{attribute,{1288,2},spec,{{union_of_family,1},[{type,{1288,22},bounded_fun,[{type,{1288,22},'fun',[{type,{1288,22},product,[{var,{1288,23},'Family'}]},{var,{1288,34},'Set'}]},[{type,{1289,7},constraint,[{atom,{1289,7},is_subtype},[{var,{1289,7},'Family'},{user_type,{1289,17},family,[]}]]},{type,{1290,7},constraint,[{atom,{1290,7},is_subtype},[{var,{1290,7},'Set'},{user_type,{1290,14},a_set,[]}]]}]]}]}}]}},{{function,weak_relation,1},[{file,[115,111,102,115,46,101,114,108]},{location,763}],[<<119,101,97,107,95,114,101,108,97,116,105,111,110,47,49>>],#{<<101,110>> => [{p,[],[<<82,101,116,117,114,110,115,32,97,32,115,117,98,115,101,116,32,83,32,111,102,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,119,101,97,107,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<119,101,97,107,32,114,101,108,97,116,105,111,110>>]},<<32,87,32,99,111,114,114,101,115,112,111,110,100,105,110,103,32,116,111,32,116,104,101,32,98,105,110,97,114,121,32,114,101,108,97,116,105,111,110,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46,32,76,101,116,32,70,32,98,101,32,116,104,101,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,105,101,108,100>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,105,101,108,100>>]},<<32,111,102,32>>,{code,[],[<<66,105,110,82,101,108,49>>]},<<46,32,84,104,101,32,115,117,98,115,101,116,32,83,32,105,115,32,100,101,102,105,110,101,100,32,115,111,32,116,104,97,116,32,120,32,83,32,121,32,105,102,32,120,32,87,32,121,32,102,111,114,32,115,111,109,101,32,120,32,105,110,32,70,32,97,110,100,32,102,111,114,32,115,111,109,101,32,121,32,105,110,32,70,46>>]},{pre,[],[{code,[],[<<49,62,32,82,49,32,61,32,115,111,102,115,58,114,101,108,97,116,105,111,110,40,91,123,49,44,49,125,44,123,49,44,50,125,44,123,51,44,49,125,93,41,44,10,82,50,32,61,32,115,111,102,115,58,119,101,97,107,95,114,101,108,97,116,105,111,110,40,82,49,41,44,10,115,111,102,115,58,116,111,95,101,120,116,101,114,110,97,108,40,82,50,41,46,10,91,123,49,44,49,125,44,123,49,44,50,125,44,123,50,44,50,125,44,123,51,44,49,125,44,123,51,44,51,125,93>>]}]}]},#{edit_url => <<104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,101,114,108,97,110,103,47,111,116,112,47,101,100,105,116,47,109,97,105,110,116,47,108,105,98,47,115,116,100,108,105,98,47,100,111,99,47,115,114,99,47,115,111,102,115,46,120,109,108,35,76,49,55,50,57>>,signature => [{attribute,{763,2},spec,{{weak_relation,1},[{type,{763,20},bounded_fun,[{type,{763,20},'fun',[{type,{763,20},product,[{var,{763,21},'BinRel1'}]},{var,{763,33},'BinRel2'}]},[{type,{764,7},constraint,[{atom,{764,7},is_subtype},[{var,{764,7},'BinRel1'},{user_type,{764,18},binary_relation,[]}]]},{type,{765,7},constraint,[{atom,{765,7},is_subtype},[{var,{765,7},'BinRel2'},{user_type,{765,18},binary_relation,[]}]]}]]}]}}]}},{{type,anyset,0},[{file,[115,111,102,115,46,101,114,108]},{location,117}],[<<45,116,121,112,101,32,97,110,121,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,121,32,107,105,110,100,32,111,102,32,115,101,116,32,40,97,108,115,111,32,105,110,99,108,117,100,101,100,32,97,114,101,32,116,104,101,32,97,116,111,109,105,99,32,115,101,116,115,41,46>>]}]},#{signature => [{attribute,{117,2},type,{anyset,{type,{117,19},union,[{user_type,{117,19},ordset,[]},{user_type,{117,30},a_set,[]}]},[]}}]}},{{type,binary_relation,0},[{file,[115,111,102,115,46,101,114,108]},{location,118}],[<<45,116,121,112,101,32,98,105,110,97,114,121,95,114,101,108,97,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,98,105,110,97,114,121,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<98,105,110,97,114,121,32,114,101,108,97,116,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,{118,2},type,{binary_relation,{user_type,{118,28},relation,[]},[]}}]}},{{type,external_set,0},[{file,[115,111,102,115,46,101,114,108]},{location,119}],[<<45,116,121,112,101,32,101,120,116,101,114,110,97,108,95,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,101,120,116,101,114,110,97,108,95,115,101,116>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<101,120,116,101,114,110,97,108,32,115,101,116>>]},<<46>>]}]},#{signature => [{attribute,{119,2},type,{external_set,{type,{119,25},term,[]},[]}}]}},{{type,family,0},[{file,[115,111,102,115,46,101,114,108]},{location,121}],[<<45,116,121,112,101,32,102,97,109,105,108,121,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,97,109,105,108,121>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,97,109,105,108,121>>]},<<32,40,111,102,32,115,117,98,115,101,116,115,41,46>>]}]},#{signature => [{attribute,{121,2},type,{family,{user_type,{121,19},a_function,[]},[]}}]}},{{type,a_function,0},[{file,[115,111,102,115,46,101,114,108]},{location,120}],[<<45,116,121,112,101,32,97,95,102,117,110,99,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,102,117,110,99,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<102,117,110,99,116,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,{120,2},type,{a_function,{user_type,{120,23},relation,[]},[]}}]}},{{type,ordset,0},[{file,[115,111,102,115,46,101,114,108]},{location,122}],[<<45,116,121,112,101,32,111,114,100,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<111,114,100,101,114,101,100,32,115,101,116>>]},<<46>>]}]},#{signature => [{attribute,{122,2},opaque,{ordset,{type,{122,21},record,[{atom,{122,23},'OrdSet'}]},[]}}]}},{{type,relation,0},[{file,[115,111,102,115,46,101,114,108]},{location,123}],[<<45,116,121,112,101,32,114,101,108,97,116,105,111,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,110,95,97,114,121,95,114,101,108,97,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<110,45,97,114,121,32,114,101,108,97,116,105,111,110>>]},<<46>>]}]},#{signature => [{attribute,{123,2},type,{relation,{user_type,{123,21},a_set,[]},[]}}]}},{{type,a_set,0},[{file,[115,111,102,115,46,101,114,108]},{location,124}],[<<45,116,121,112,101,32,97,95,115,101,116,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<46>>]}]},#{signature => [{attribute,{124,2},opaque,{a_set,{type,{124,20},record,[{atom,{124,22},'Set'}]},[]}}]}},{{type,set_of_sets,0},[{file,[115,111,102,115,46,101,114,108]},{location,125}],[<<45,116,121,112,101,32,115,101,116,95,111,102,95,115,101,116,115,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,110,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,115,95,100,101,102,105,110,105,116,105,111,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<117,110,111,114,100,101,114,101,100,32,115,101,116>>]},<<32,111,102,32,117,110,111,114,100,101,114,101,100,32,115,101,116,115,46>>]}]},#{signature => [{attribute,{125,2},type,{set_of_sets,{user_type,{125,24},a_set,[]},[]}}]}},{{type,set_fun,0},[{file,[115,111,102,115,46,101,114,108]},{location,126}],[<<45,116,121,112,101,32,115,101,116,95,102,117,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,115,101,116,95,102,117,110>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<83,101,116,70,117,110>>]},<<46>>]}]},#{signature => [{attribute,{126,2},type,{set_fun,{type,{126,20},union,[{type,{126,20},pos_integer,[]},{type,{127,20},tuple,[{atom,{127,21},external},{type,{127,35},'fun',[{type,{127,35},product,[{user_type,{127,36},external_set,[]}]},{user_type,{127,55},external_set,[]}]}]},{type,{128,24},'fun',[{type,{128,24},product,[{user_type,{128,25},anyset,[]}]},{user_type,{128,38},anyset,[]}]}]},[]}}]}},{{type,spec_fun,0},[{file,[115,111,102,115,46,101,114,108]},{location,129}],[<<45,116,121,112,101,32,115,112,101,99,95,102,117,110,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{},#{signature => [{attribute,{129,2},type,{spec_fun,{type,{129,21},union,[{type,{129,21},tuple,[{atom,{129,22},external},{type,{129,36},'fun',[{type,{129,36},product,[{user_type,{129,37},external_set,[]}]},{type,{129,56},boolean,[]}]}]},{type,{130,25},'fun',[{type,{130,25},product,[{user_type,{130,26},anyset,[]}]},{type,{130,39},boolean,[]}]}]},[]}}]}},{{type,type,0},[{file,[115,111,102,115,46,101,114,108]},{location,131}],[<<45,116,121,112,101,32,116,121,112,101,40,41,32,58,58,32,116,101,114,109,40,41,46>>],#{<<101,110>> => [{p,[],[<<65,32>>,{a,[{href,<<115,116,100,108,105,98,58,115,111,102,115,35,116,121,112,101>>},{rel,<<104,116,116,112,115,58,47,47,101,114,108,97,110,103,46,111,114,103,47,100,111,99,47,108,105,110,107,47,115,101,101,101,114,108>>}],[<<116,121,112,101>>]},<<46>>]}]},#{signature => [{attribute,{131,2},type,{type,{type,{131,17},term,[]},[]}}]}},{{type,tuple_of,1},[{file,[115,111,102,115,46,101,114,108]},{location,133}],[<<116,117,112,108,101,95,111,102,40,84,41>>],#{<<101,110>> => [{p,[],[<<65,32,116,117,112,108,101,32,119,104,101,114,101,32,116,104,101,32,101,108,101,109,101,110,116,115,32,97,114,101,32,111,102,32,116,121,112,101,32>>,{code,[],[<<84>>]},<<46>>]}]},#{signature => [{attribute,{133,2},type,{tuple_of,{type,{133,23},tuple,any},[{var,{133,16},'_T'}]}}]}}]}. \ No newline at end of file
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re.txt
index 21a3dbf487..2d8a293de2 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re.txt
@@ -1645,9 +1645,6 @@
alpha:
Letters
- ascii:
- Character codes 0-127
-
blank:
Space or tab only
@@ -1681,6 +1678,12 @@
xdigit:
Hexadecimal digits
+ There is another character class, ascii, that erroneously
+ matches Latin-1 characters instead of the 0-127 range specified by
+ POSIX. This cannot be fixed without altering the behaviour of
+ other classes, so we recommend matching the range with [\\0-\x7f]
+ instead.
+
The default "space" characters are HT (9), LF (10), VT (11), FF
(12), CR (13), and space (32). If locale-specific matching is
taking place, the list of space characters may be different; there
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_grun_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_grun_3_func.txt
new file mode 100644
index 0000000000..6f0af3fc67
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_grun_3_func.txt
@@ -0,0 +1,5 @@
+
+  grun/3
+
+ The documentation for grun/3 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_internal_run_4_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_internal_run_4_func.txt
new file mode 100644
index 0000000000..d896aabce3
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_internal_run_4_func.txt
@@ -0,0 +1,6 @@
+
+  internal_run/4
+
+ The documentation for internal_run/4 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_ucompile_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_ucompile_2_func.txt
new file mode 100644
index 0000000000..148c48a4b0
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_ucompile_2_func.txt
@@ -0,0 +1,5 @@
+
+  ucompile/2
+
+ The documentation for ucompile/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_urun_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_urun_3_func.txt
new file mode 100644
index 0000000000..ddfb951486
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_re_urun_3_func.txt
@@ -0,0 +1,5 @@
+
+  urun/3
+
+ The documentation for urun/3 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_fam2rel_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_fam2rel_1_func.txt
new file mode 100644
index 0000000000..1eafcb4078
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_fam2rel_1_func.txt
@@ -0,0 +1,5 @@
+
+  fam2rel/1
+
+ The documentation for fam2rel/1 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_rel2fam_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_rel2fam_1_func.txt
new file mode 100644
index 0000000000..d41d2c6c18
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/stdlib_sofs_rel2fam_1_func.txt
@@ -0,0 +1,5 @@
+
+  rel2fam/1
+
+ The documentation for rel2fam/1 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang.txt
index a2fb62f0d0..b275eb19da 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang.txt
@@ -1,16 +1,21 @@
 erlang
- By convention, most Built-In Functions (BIFs) are included in this
- module. Some of the BIFs are viewed more or less as part of the
- Erlang programming language and are auto-imported. Thus, it is
- not necessary to specify the module name. For example, the calls 
+ By convention, most Built-In Functions (BIFs) and all predefined
+ types are included in this module. Some of the BIFs and all of the
+ predefined types are viewed more or less as part of the Erlang
+ programming language and are auto-imported. Thus, it is not
+ necessary to specify the module name. For example, the calls 
atom_to_list(erlang) and erlang:atom_to_list(erlang) are
identical.
Auto-imported BIFs are listed without module prefix. BIFs listed
with module prefix are not auto-imported.
+ Predefined types are listed in the Predefined datatypes section
+ of this reference manual and in the Types and Function
+ Specifications section of the Erlang Reference Manual.
+
BIFs can fail for various reasons. All BIFs fail with reason 
badarg if they are called with arguments of an incorrect type.
The other reasons are described in the description of each
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_!_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_!_2_func.txt
new file mode 100644
index 0000000000..222e852764
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_!_2_func.txt
@@ -0,0 +1,5 @@
+
+  '!'/2
+
+ The documentation for '!'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_++_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_++_2_func.txt
new file mode 100644
index 0000000000..5dcd568da5
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_++_2_func.txt
@@ -0,0 +1,5 @@
+
+  '++'/2
+
+ The documentation for '++'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_1_func.txt
new file mode 100644
index 0000000000..e3ecf4bf3c
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_1_func.txt
@@ -0,0 +1,5 @@
+
+  '+'/1
+
+ The documentation for '+'/1 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_2_func.txt
new file mode 100644
index 0000000000..bf738628fc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_+_2_func.txt
@@ -0,0 +1,5 @@
+
+  '+'/2
+
+ The documentation for '+'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_--_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_--_2_func.txt
new file mode 100644
index 0000000000..797d1d5b45
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_--_2_func.txt
@@ -0,0 +1,5 @@
+
+  '--'/2
+
+ The documentation for '--'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_1_func.txt
new file mode 100644
index 0000000000..51cf374386
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_1_func.txt
@@ -0,0 +1,5 @@
+
+  '-'/1
+
+ The documentation for '-'/1 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_2_func.txt
new file mode 100644
index 0000000000..797a700c86
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_-_2_func.txt
@@ -0,0 +1,5 @@
+
+  '-'/2
+
+ The documentation for '-'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_0_func.txt
index 0b0446302f..150c8604b9 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_0_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_0_func.txt
@@ -2,7 +2,7 @@
-spec alias() -> Alias when Alias :: reference().
Since:
- OTP @OTP-16718@
+ OTP 24.0
Create an alias which can be used when sending messages to the
process that created the alias. When the alias has been
@@ -19,3 +19,36 @@
The alias will be automatically deactivated when a reply
message sent via the alias is received. The alias can also
still be deactivated via a call to unalias/1.
+
+ Example:
+
+ server() ->
+ receive
+ {request, AliasReqId, Request} ->
+ Result = perform_request(Request),
+ AliasReqId ! {reply, AliasReqId, Result}
+ end,
+ server().
+
+ client(ServerPid, Request) ->
+ AliasReqId = alias([reply]),
+ ServerPid ! {request, AliasReqId, Request},
+ %% Alias will be automatically deactivated if we receive a reply
+ %% since we used the 'reply' option...
+ receive
+ {reply, AliasReqId, Result} -> Result
+ after 5000 ->
+ unalias(AliasReqId),
+ %% Flush message queue in case the reply arrived
+ %% just before the alias was deactivated...
+ receive {reply, AliasReqId, Result} -> Result
+ after 0 -> exit(timeout)
+ end
+ end.
+
+
+ Note that both the server and the client in this example must be
+ executing on at least OTP 24 systems in order for this to work.
+
+ For more information on process aliases see the Process Aliases
+ section of the Erlang Reference Manual.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_1_func.txt
index 291db25ac3..03aa38c1cd 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alias_1_func.txt
@@ -5,7 +5,7 @@
 Opts :: [explicit_unalias | reply].
Since:
- OTP @OTP-16718@
+ OTP 24.0
Create an alias which can be used when sending messages to the
process that created the alias. When the alias has been
@@ -22,3 +22,36 @@
The alias will be automatically deactivated when a reply
message sent via the alias is received. The alias can also
still be deactivated via a call to unalias/1.
+
+ Example:
+
+ server() ->
+ receive
+ {request, AliasReqId, Request} ->
+ Result = perform_request(Request),
+ AliasReqId ! {reply, AliasReqId, Result}
+ end,
+ server().
+
+ client(ServerPid, Request) ->
+ AliasReqId = alias([reply]),
+ ServerPid ! {request, AliasReqId, Request},
+ %% Alias will be automatically deactivated if we receive a reply
+ %% since we used the 'reply' option...
+ receive
+ {reply, AliasReqId, Result} -> Result
+ after 5000 ->
+ unalias(AliasReqId),
+ %% Flush message queue in case the reply arrived
+ %% just before the alias was deactivated...
+ receive {reply, AliasReqId, Result} -> Result
+ after 0 -> exit(timeout)
+ end
+ end.
+
+
+ Note that both the server and the client in this example must be
+ executing on at least OTP 24 systems in order for this to work.
+
+ For more information on process aliases see the Process Aliases
+ section of the Erlang Reference Manual.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_info_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_info_1_func.txt
new file mode 100644
index 0000000000..110bd44e53
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_info_1_func.txt
@@ -0,0 +1,6 @@
+
+  alloc_info/1
+
+ The documentation for alloc_info/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_sizes_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_sizes_1_func.txt
new file mode 100644
index 0000000000..e2abffaa6e
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_alloc_sizes_1_func.txt
@@ -0,0 +1,6 @@
+
+  alloc_sizes/1
+
+ The documentation for alloc_sizes/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_and_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_and_2_func.txt
new file mode 100644
index 0000000000..820cf83475
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_and_2_func.txt
@@ -0,0 +1,5 @@
+
+  'and'/2
+
+ The documentation for 'and'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_any_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_any_0_type.txt
new file mode 100644
index 0000000000..99d9f7affa
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_any_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type any() :: any().
+
+ All possible Erlang terms. Synonym for term().
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_append_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_append_2_func.txt
new file mode 100644
index 0000000000..a65746afaf
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_append_2_func.txt
@@ -0,0 +1,5 @@
+
+  append/2
+
+ The documentation for append/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_arity_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_arity_0_type.txt
new file mode 100644
index 0000000000..0ff062f3dc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_arity_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type arity() :: arity().
+
+ The arity of a function or type.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_atom_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_atom_0_type.txt
new file mode 100644
index 0000000000..44e92c9560
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_atom_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type atom() :: atom().
+
+ An Erlang atom.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_band_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_band_2_func.txt
new file mode 100644
index 0000000000..f3781ac0e0
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_band_2_func.txt
@@ -0,0 +1,5 @@
+
+  'band'/2
+
+ The documentation for 'band'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_0_type.txt
new file mode 100644
index 0000000000..25e2353a9a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type binary() :: <<_:_*8>>.
+
+ An Erlang binary, that is, a bitstring with a size divisible by
+ 8.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_atom_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_atom_2_func.txt
index e86900006d..cf0eb33859 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_atom_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_atom_2_func.txt
@@ -10,11 +10,8 @@
Note:
As from Erlang/OTP 20, binary_to_atom(Binary, utf8) is
- capable of encoding any Unicode character. Earlier versions
+ capable of decoding any Unicode character. Earlier versions
would fail if the binary contained Unicode characters > 255.
- For more information about Unicode support in atoms, see the
- note on UTF-8 encoded atoms in section "External Term Format"
- in the User's Guide.
Note:
The number of characters that are permitted in an atom name is
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_1_func.txt
index 53488792d3..413260f6a8 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_1_func.txt
@@ -11,7 +11,10 @@
hello
Warning:
- When decoding binaries from untrusted sources, consider using 
- binary_to_term/2 to prevent Denial of Service attacks.
+ When decoding binaries from untrusted sources, the untrusted
+ source may submit data in a way to create resources, such as
+ atoms and remote references, that cannot be garbage collected
+ and lead to Denial of Service attack. In such cases, consider
+ using binary_to_term/2 with the safe option.
See also term_to_binary/1 and binary_to_term/2.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_2_func.txt
index 026b8d18cb..60e6109348 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_binary_to_term_2_func.txt
@@ -16,7 +16,7 @@
source.
When enabled, it prevents decoding data that can be used to
- attack the Erlang system. In the event of receiving unsafe
+ attack the Erlang runtime. In the event of receiving unsafe
data, decoding fails with a badarg error.
This prevents creation of new atoms directly, creation of new
@@ -33,6 +33,14 @@
> binary_to_term(<<131,100,0,5,"hello">>, [safe]).
hello
+ Warning:
+ The safe option ensures the data is safely processed by
+ the Erlang runtime but it does not guarantee the data is
+ safe to your application. You must always validate data
+ from untrusted sources. If the binary is stored or
+ transits through untrusted sources, you should also
+ consider cryptographically signing it.
+
used:
Changes the return value to {Term, Used} where Used is the
number of bytes actually read from Binary.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bitstring_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bitstring_0_type.txt
new file mode 100644
index 0000000000..71ffcc1f02
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bitstring_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type bitstring() :: <<_:_*1>>.
+
+ An Erlang bitstring.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bnot_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bnot_1_func.txt
new file mode 100644
index 0000000000..7fb3acadcc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bnot_1_func.txt
@@ -0,0 +1,5 @@
+
+  'bnot'/1
+
+ The documentation for 'bnot'/1 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_boolean_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_boolean_0_type.txt
new file mode 100644
index 0000000000..1cda883d3b
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_boolean_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type boolean() :: true | false.
+
+ A boolean value.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bor_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bor_2_func.txt
new file mode 100644
index 0000000000..698de2bfe3
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bor_2_func.txt
@@ -0,0 +1,5 @@
+
+  'bor'/2
+
+ The documentation for 'bor'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsl_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsl_2_func.txt
new file mode 100644
index 0000000000..65b26f4c03
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsl_2_func.txt
@@ -0,0 +1,5 @@
+
+  'bsl'/2
+
+ The documentation for 'bsl'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsr_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsr_2_func.txt
new file mode 100644
index 0000000000..6b6849672f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bsr_2_func.txt
@@ -0,0 +1,5 @@
+
+  'bsr'/2
+
+ The documentation for 'bsr'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bxor_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bxor_2_func.txt
new file mode 100644
index 0000000000..76aa3fbe7e
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_bxor_2_func.txt
@@ -0,0 +1,5 @@
+
+  'bxor'/2
+
+ The documentation for 'bxor'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_byte_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_byte_0_type.txt
new file mode 100644
index 0000000000..6f6c6b4b28
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_byte_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type byte() :: 0..255.
+
+ A byte of data represented by an integer.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_call_on_load_function_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_call_on_load_function_1_func.txt
new file mode 100644
index 0000000000..abf49640cc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_call_on_load_function_1_func.txt
@@ -0,0 +1,6 @@
+
+  call_on_load_function/1
+
+ The documentation for call_on_load_function/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_char_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_char_0_type.txt
new file mode 100644
index 0000000000..e0c2f2333f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_char_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type char() :: 0..1114111.
+
+ An ASCII character or a unicode codepoint presented by an
+ integer.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_delay_trap_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_delay_trap_2_func.txt
new file mode 100644
index 0000000000..6e1f78dcaa
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_delay_trap_2_func.txt
@@ -0,0 +1,6 @@
+
+  delay_trap/2
+
+ The documentation for delay_trap/2 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_nl_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_nl_0_func.txt
new file mode 100644
index 0000000000..4378ba670f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_nl_0_func.txt
@@ -0,0 +1,6 @@
+
+  display_nl/0
+
+ The documentation for display_nl/0 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_string_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_string_1_func.txt
new file mode 100644
index 0000000000..2d5267009a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_display_string_1_func.txt
@@ -0,0 +1,6 @@
+
+  display_string/1
+
+ The documentation for display_string/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_1_func.txt
index 93228fd6e0..182a8e0ef1 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_1_func.txt
@@ -28,7 +28,7 @@
This function is used when implementing an alternative
distribution carrier using processes as distribution controllers. 
- DHandle is retrived via the callback f_handshake_complete. More
- information can be found in the documentation of ERTS User's
+ DHandle is retrieved via the callback f_handshake_complete.
+ More information can be found in the documentation of ERTS User's
Guide ➜ How to implement an Alternative Carrier for the Erlang
Distribution ➜ Distribution Module.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_notification_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_notification_1_func.txt
index 5f2e5b7212..02197ca805 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_notification_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_data_notification_1_func.txt
@@ -21,7 +21,7 @@
This function is used when implementing an alternative
distribution carrier using processes as distribution controllers. 
- DHandle is retrived via the callback f_handshake_complete. More
- information can be found in the documentation of ERTS User's
+ DHandle is retrieved via the callback f_handshake_complete.
+ More information can be found in the documentation of ERTS User's
Guide ➜ How to implement an Alternative Carrier for the Erlang
Distribution ➜ Distribution Module.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_opt_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_opt_2_func.txt
index 1f7cf3782f..7e9050f105 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_opt_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_get_opt_2_func.txt
@@ -19,7 +19,7 @@
This function is used when implementing an alternative
distribution carrier using processes as distribution controllers. 
- DHandle is retrived via the callback f_handshake_complete. More
- information can be found in the documentation of ERTS User's
+ DHandle is retrieved via the callback f_handshake_complete.
+ More information can be found in the documentation of ERTS User's
Guide ➜ How to implement an Alternative Carrier for the Erlang
Distribution ➜ Distribution Module.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_input_handler_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_input_handler_2_func.txt
index 05201a2dc0..0e8202aa10 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_input_handler_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_input_handler_2_func.txt
@@ -11,7 +11,7 @@
channel identified by DHandle. Once this function has been
called, InputHandler is the only process allowed to call 
erlang:dist_ctrl_put_data(DHandle, Data) with the DHandle
- identifing this distribution channel.
+ identifying this distribution channel.
Note:
Only the process registered as distribution controller for the
@@ -20,7 +20,7 @@
This function is used when implementing an alternative
distribution carrier using processes as distribution controllers. 
- DHandle is retrived via the callback f_handshake_complete. More
- information can be found in the documentation of ERTS User's
+ DHandle is retrieved via the callback f_handshake_complete.
+ More information can be found in the documentation of ERTS User's
Guide ➜ How to implement an Alternative Carrier for the Erlang
Distribution ➜ Distribution Module.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_put_data_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_put_data_2_func.txt
index 65c6b53d10..1279f67fa3 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_put_data_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_put_data_2_func.txt
@@ -22,7 +22,7 @@
This function is used when implementing an alternative
distribution carrier using processes as distribution controllers. 
- DHandle is retrived via the callback f_handshake_complete. More
- information can be found in the documentation of ERTS User's
+ DHandle is retrieved via the callback f_handshake_complete.
+ More information can be found in the documentation of ERTS User's
Guide ➜ How to implement an Alternative Carrier for the Erlang
Distribution ➜ Distribution Module.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_set_opt_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_set_opt_3_func.txt
index 355a006814..70c5a44334 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_set_opt_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_ctrl_set_opt_3_func.txt
@@ -35,7 +35,7 @@
This function is used when implementing an alternative
distribution carrier using processes as distribution controllers. 
- DHandle is retrived via the callback f_handshake_complete. More
- information can be found in the documentation of ERTS User's
+ DHandle is retrieved via the callback f_handshake_complete.
+ More information can be found in the documentation of ERTS User's
Guide ➜ How to implement an Alternative Carrier for the Erlang
Distribution ➜ Distribution Module.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_get_stat_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_get_stat_1_func.txt
new file mode 100644
index 0000000000..141fe118ae
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_get_stat_1_func.txt
@@ -0,0 +1,6 @@
+
+  dist_get_stat/1
+
+ The documentation for dist_get_stat/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_handle_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_handle_0_type.txt
index 9bcad3af74..e2a5c64265 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_handle_0_type.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dist_handle_0_type.txt
@@ -1,4 +1,4 @@
-opaque dist_handle() 
- An opaque handle identifing a distribution channel.
+ An opaque handle identifying a distribution channel.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_div_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_div_2_func.txt
new file mode 100644
index 0000000000..1b349e7ecf
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_div_2_func.txt
@@ -0,0 +1,5 @@
+
+  'div'/2
+
+ The documentation for 'div'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dmonitor_node_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dmonitor_node_3_func.txt
new file mode 100644
index 0000000000..a8ae905063
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dmonitor_node_3_func.txt
@@ -0,0 +1,6 @@
+
+  dmonitor_node/3
+
+ The documentation for dmonitor_node/3 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_append_vm_tag_data_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_append_vm_tag_data_1_func.txt
new file mode 100644
index 0000000000..456b93faba
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_append_vm_tag_data_1_func.txt
@@ -0,0 +1,6 @@
+
+  dt_append_vm_tag_data/1
+
+ The documentation for dt_append_vm_tag_data/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_0_func.txt
new file mode 100644
index 0000000000..0b06a2134f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_0_func.txt
@@ -0,0 +1,6 @@
+
+  dt_get_tag/0
+
+ The documentation for dt_get_tag/0 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_data_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_data_0_func.txt
new file mode 100644
index 0000000000..b7f39991ef
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_get_tag_data_0_func.txt
@@ -0,0 +1,6 @@
+
+  dt_get_tag_data/0
+
+ The documentation for dt_get_tag_data/0 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_prepend_vm_tag_data_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_prepend_vm_tag_data_1_func.txt
new file mode 100644
index 0000000000..59c1834649
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_prepend_vm_tag_data_1_func.txt
@@ -0,0 +1,6 @@
+
+  dt_prepend_vm_tag_data/1
+
+ The documentation for dt_prepend_vm_tag_data/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_put_tag_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_put_tag_1_func.txt
new file mode 100644
index 0000000000..83906151a7
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_put_tag_1_func.txt
@@ -0,0 +1,6 @@
+
+  dt_put_tag/1
+
+ The documentation for dt_put_tag/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_restore_tag_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_restore_tag_1_func.txt
new file mode 100644
index 0000000000..bf52d2f5d2
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_restore_tag_1_func.txt
@@ -0,0 +1,6 @@
+
+  dt_restore_tag/1
+
+ The documentation for dt_restore_tag/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_spread_tag_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_spread_tag_1_func.txt
new file mode 100644
index 0000000000..6a8496bc58
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_dt_spread_tag_1_func.txt
@@ -0,0 +1,6 @@
+
+  dt_spread_tag/1
+
+ The documentation for dt_spread_tag/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqcoloneq_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqcoloneq_2_func.txt
new file mode 100644
index 0000000000..00c8120ad8
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqcoloneq_2_func.txt
@@ -0,0 +1,5 @@
+
+  '=:='/2
+
+ The documentation for '=:='/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqeq_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqeq_2_func.txt
new file mode 100644
index 0000000000..eab30981c2
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqeq_2_func.txt
@@ -0,0 +1,5 @@
+
+  '=='/2
+
+ The documentation for '=='/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqlt_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqlt_2_func.txt
new file mode 100644
index 0000000000..fce7453bc2
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqlt_2_func.txt
@@ -0,0 +1,5 @@
+
+  '=<'/2
+
+ The documentation for '=<'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqslasheq_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqslasheq_2_func.txt
new file mode 100644
index 0000000000..69dfca83fc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_eqslasheq_2_func.txt
@@ -0,0 +1,5 @@
+
+  '=/='/2
+
+ The documentation for '=/='/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_1_func.txt
index 6324d2884e..18c0010a75 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_1_func.txt
@@ -1,15 +1,14 @@
-spec error(Reason) -> no_return() when Reason :: term().
- Raises an exception of class error with the reason Reason,
- where Reason is any term. The error reason is {Reason, Where},
- where Where is a list of the functions most recently called (the
- current function first). As evaluating this function causes an
- exception to be thrown, it has no return value. The intent of the
- exception class error is to signal that an unexpected error has
- happened (for example, a function is called with a parameter that
- has an incorrect type). See the guide about errors and error
- handling for additional information. Example:
+ Raises an exception of class error with the reason Reason. As
+ evaluating this function causes an exception to be thrown, it has
+ no return value.
+
+ The intent of the exception class error is to signal that an
+ unexpected error has happened (for example, a function is called
+ with a parameter that has an incorrect type). See the guide about
+ errors and error handling for additional information. Example:
> catch error(foobar).
{'EXIT',{foobar,[{shell,apply_fun,3,
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_2_func.txt
index 0b91e45030..9a87a345bb 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_2_func.txt
@@ -1,19 +1,19 @@
-spec error(Reason, Args) -> no_return()
-  when Reason :: term(), Args :: [term()].
+  when Reason :: term(), Args :: [term()] | none.
- Raises an exception of class error with the reason Reason,
- where Reason is any term. The error reason is {Reason, Where},
- where Where is a list of the functions most recently called (the
- current function first). Args is expected to be the list of
- arguments for the current function; it is used to provide the
- arguments for the current function in the term Where. As
- evaluating this function causes an exception to be raised, it has
- no return value. The intent of the exception class error is to
- signal that an unexpected error has happened (for example, a
- function is called with a parameter that has an incorrect type).
- See the guide about errors and error handling for additional
- information. Example:
+ Raises an exception of class error with the reason Reason. 
+ Args is expected to be the list of arguments for the current
+ function or the atom none. If it is a list, it is used to
+ provide the arguments for the current function in the stack
+ back-trace. If it is none, the arity of the calling function is
+ used in the stacktrace. As evaluating this function causes an
+ exception to be raised, it has no return value.
+
+ The intent of the exception class error is to signal that an
+ unexpected error has happened (for example, a function is called
+ with a parameter that has an incorrect type). See the guide about
+ errors and error handling for additional information. Example:
test.erl:
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_3_func.txt
index 0af05f72c5..73f183013f 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_error_3_func.txt
@@ -2,7 +2,7 @@
-spec error(Reason, Args, Options) -> no_return()
 when
 Reason :: term(),
-  Args :: [term()],
+  Args :: [term()] | none,
 Options :: [Option],
 Option :: {error_info, ErrorInfoMap},
 ErrorInfoMap ::
@@ -11,18 +11,27 @@
 function => atom()}.
Since:
- 24.0
+ OTP 24.0
- Raises an exception of class error with the reason Reason,
- where Reason is any term. Args is expected to be the list of
- arguments for the current function; it is used to provide the
- arguments for the current function in the stack back-trace. If the 
- {error_info, ErrorInfoMap} option is given, it will be injected
- into the stacktrace.
+ Raises an exception of class error with the reason Reason. 
+ Args is expected to be the list of arguments for the current
+ function or the atom none. If it is a list, it is used to
+ provide the arguments for the current function in the stack
+ back-trace. If it is none, the arity of the calling function is
+ used in the stacktrace. As evaluating this function causes an
+ exception to be raised, it has no return value.
- As evaluating this function causes an exception to be raised, it
- has no return value. The intent of the exception class error is
- to signal that an unexpected error has happened (for example, a
- function is called with a parameter that has an incorrect type).
- See the guide about errors and error handling for additional
- information.
+ If the error_info option is given, the ErrorInfoMap will be
+ inserted into the stacktrace. The information given in the 
+ ErrorInfoMap is to be used by error formatters such as erl_error
+ to provide more context around an error.
+
+ The default module of the ErrorInfoMap is the module that the
+ call to error/3 is made. The default function is format_error.
+ See format_error/2 for more details on how this
+ Module:Function/2 is to be used
+
+ The intent of the exception class error is to signal that an
+ unexpected error has happened (for example, a function is called
+ with a parameter that has an incorrect type). See the guide about
+ errors and error handling for additional information.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_1_func.txt
index f97e38039c..481fd9f793 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_1_func.txt
@@ -1,13 +1,17 @@
-spec exit(Reason) -> no_return() when Reason :: term().
- Raises an exception of class exit with exit reason Reason,
- where Reason is any term. As evaluating this function causes an
- exception to be raised, it has no return value. This function
- should be used when the intent is to stop the current process.
- This function differ from erlang:error/1 and erlang:error/2 by
- causing an exception of a different class and by having a reason
- that does not include the list of functions from the call stack.
+ Raises an exception of class exit with exit reason Reason. As
+ evaluating this function causes an exception to be raised, it has
+ no return value.
+
+ The intent of the exception class exit is that the current
+ process should be stopped (for example when a message telling a
+ process to stop is received).
+
+ This function differ from error/1,2,3 by causing an exception of
+ a different class and by having a reason that does not include the
+ list of functions from the call stack.
See the guide about errors and error handling for additional
information.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_signal_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_signal_2_func.txt
new file mode 100644
index 0000000000..e952dad6a8
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_exit_signal_2_func.txt
@@ -0,0 +1,6 @@
+
+  exit_signal/2
+
+ The documentation for exit_signal/2 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_after_on_load_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_after_on_load_2_func.txt
new file mode 100644
index 0000000000..63b677da23
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_after_on_load_2_func.txt
@@ -0,0 +1,6 @@
+
+  finish_after_on_load/2
+
+ The documentation for finish_after_on_load/2 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_loading_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_loading_1_func.txt
new file mode 100644
index 0000000000..c22cf49f7d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_finish_loading_1_func.txt
@@ -0,0 +1,6 @@
+
+  finish_loading/1
+
+ The documentation for finish_loading/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_0_type.txt
new file mode 100644
index 0000000000..e1df49edf4
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type float() :: float().
+
+ An Erlang float.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_binary_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_binary_2_func.txt
index b7a690fee9..2f7a559f77 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_binary_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_binary_2_func.txt
@@ -6,7 +6,7 @@
 Option ::
 {decimals, Decimals :: 0..253} |
 {scientific, Decimals :: 0..249} |
-  compact.
+  compact | short.
Since:
OTP R16B
@@ -21,3 +21,9 @@
<<"7.12">>
> float_to_binary(7.12, [{scientific, 3}]).
<<"7.120e+00">>
+ > float_to_binary(7.12, [short]).
+ <<"7.12">>
+ > float_to_binary(0.1+0.2, [short]).
+ <<"0.30000000000000004">>
+ > float_to_binary(0.1+0.2)
+ <<"3.00000000000000044409e-01">>
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_list_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_list_2_func.txt
index bfe4abe53a..14dbc3763e 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_list_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_float_to_list_2_func.txt
@@ -6,7 +6,7 @@
 Option ::
 {decimals, Decimals :: 0..253} |
 {scientific, Decimals :: 0..249} |
-  compact.
+  compact | short.
Since:
OTP R16B
@@ -29,6 +29,16 @@
using scientific notation with Decimals digits of
precision.
+ • If option short is specified, the float is formatted with
+ the smallest number of digits that still guarantees that F
+ =:= list_to_float(float_to_list(F, [short])). When the
+ float is inside the range (-2âµÂ³, 2âµÂ³), the notation that
+ yields the smallest number of characters is used (scientific
+ notation or normal decimal notation). Floats outside the
+ range (-2âµÂ³, 2âµÂ³) are always formatted using scientific
+ notation to avoid confusing results when doing arithmetic
+ operations.
+
• If Options is [], the function behaves as 
float_to_list/1.
@@ -40,6 +50,10 @@
"7.12"
> float_to_list(7.12, [{scientific, 3}]).
"7.120e+00"
+ > float_to_list(7.12, [short]).
+ "7.12"
+ > float_to_list(0.1+0.2, [short]).
+ "0.30000000000000004"
> float_to_list(0.1+0.2)
"3.00000000000000044409e-01"
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_format_cpu_topology_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_format_cpu_topology_1_func.txt
new file mode 100644
index 0000000000..7ef9f0481c
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_format_cpu_topology_1_func.txt
@@ -0,0 +1,6 @@
+
+  format_cpu_topology/1
+
+ The documentation for format_cpu_topology/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_info_mfa_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_info_mfa_1_func.txt
new file mode 100644
index 0000000000..26bd5c979a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_info_mfa_1_func.txt
@@ -0,0 +1,6 @@
+
+  fun_info_mfa/1
+
+ The documentation for fun_info_mfa/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_to_list_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_to_list_1_func.txt
index 259eafe909..ecd103b496 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_to_list_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_fun_to_list_1_func.txt
@@ -59,7 +59,7 @@
{#Fun<test.2.107738983>,#Fun<test.3.107738983>}
Explanation: The string representations differ because the funs
- come from different fun experssions.
+ come from different fun expressions.
> {fun() -> 1 end, fun() -> 1 end}. >
{#Fun<erl_eval.45.97283095>,#Fun<erl_eval.45.97283095>}
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_0_type.txt
new file mode 100644
index 0000000000..0c3d189c7d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type function() :: fun().
+
+ An Erlang fun.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_exported_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_exported_3_func.txt
index 4ea9703aa4..0b7f45f6fb 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_exported_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_function_exported_3_func.txt
@@ -5,11 +5,7 @@
 Function :: atom(),
 Arity :: arity().
- Returns true if the module Module is loaded and contains an
+ Returns true if the module Module is current and contains an
exported function Function/Arity, or if there is a BIF (a
built-in function implemented in C) with the specified name,
otherwise returns false.
-
- Note:
- This function used to return false for BIFs before
- Erlang/OTP 18.0.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_garbage_collect_message_area_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_garbage_collect_message_area_0_func.txt
new file mode 100644
index 0000000000..4ffd915f60
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_garbage_collect_message_area_0_func.txt
@@ -0,0 +1,6 @@
+
+  garbage_collect_message_area/0
+
+ The documentation for garbage_collect_message_area/0 is hidden.
+ This probably means that it is internal and not to be used by
+ other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gather_gc_info_result_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gather_gc_info_result_1_func.txt
new file mode 100644
index 0000000000..594193be73
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gather_gc_info_result_1_func.txt
@@ -0,0 +1,6 @@
+
+  gather_gc_info_result/1
+
+ The documentation for gather_gc_info_result/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_cookie_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_cookie_1_func.txt
new file mode 100644
index 0000000000..7e85ffdbc6
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_cookie_1_func.txt
@@ -0,0 +1,9 @@
+
+ -spec erlang:get_cookie(Node) -> Cookie | nocookie
+  when Node :: node(), Cookie :: atom().
+
+Since:
+ OTP 24.1
+
+ Returns the magic cookie for node Node if the local node is
+ alive, otherwise the atom nocookie.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_1_func.txt
new file mode 100644
index 0000000000..15653bba3e
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_1_func.txt
@@ -0,0 +1,6 @@
+
+  get_module_info/1
+
+ The documentation for get_module_info/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_2_func.txt
new file mode 100644
index 0000000000..831a63cadb
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_get_module_info_2_func.txt
@@ -0,0 +1,6 @@
+
+  get_module_info/2
+
+ The documentation for get_module_info/2 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_group_leader_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_group_leader_2_func.txt
index 592d6bd6e5..e5268acd80 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_group_leader_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_group_leader_2_func.txt
@@ -10,5 +10,9 @@
supervision tree, because OTP assumes the group leader of their
processes is their application master.
+ Setting the group leader follows the signal ordering guarantees
+ described in the Processes Chapter in the Erlang Reference
+ Manual.
+
See also group_leader/0 and OTP design principles related to
starting and stopping applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gt_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gt_2_func.txt
new file mode 100644
index 0000000000..013f679ceb
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gt_2_func.txt
@@ -0,0 +1,5 @@
+
+  '>'/2
+
+ The documentation for '>'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gteq_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gteq_2_func.txt
new file mode 100644
index 0000000000..16f4e2b4e5
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_gteq_2_func.txt
@@ -0,0 +1,5 @@
+
+  '>='/2
+
+ The documentation for '>='/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_has_prepared_code_on_load_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_has_prepared_code_on_load_1_func.txt
new file mode 100644
index 0000000000..c012053e6d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_has_prepared_code_on_load_1_func.txt
@@ -0,0 +1,6 @@
+
+  has_prepared_code_on_load/1
+
+ The documentation for has_prepared_code_on_load/1 is hidden.
+ This probably means that it is internal and not to be used by
+ other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_hibernate_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_hibernate_3_func.txt
index bc61de77bd..92b9b0302b 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_hibernate_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_hibernate_3_func.txt
@@ -13,7 +13,8 @@
resumes in Module:Function with the arguments specified by Args
with the call stack emptied, meaning that the process terminates
when that function returns. Thus erlang:hibernate/3 never
- returns to its caller.
+ returns to its caller. The resume function Module:Function/Arity
+ must be exported (Arity =:= length(Args)).
If the process has any message in its message queue, the process
is awakened immediately in the same way as described earlier.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_identifier_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_identifier_0_type.txt
new file mode 100644
index 0000000000..f7f5ac6876
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_identifier_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type identifier() :: pid() | port() | reference().
+
+ An unique identifier for some entity, for example a process,
+ port or monitor.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_integer_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_integer_0_type.txt
new file mode 100644
index 0000000000..2b9b3bab4a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_integer_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type integer() :: integer().
+
+ An Erlang integer.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iodata_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iodata_0_type.txt
new file mode 100644
index 0000000000..ba46c3331d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iodata_0_type.txt
@@ -0,0 +1,11 @@
+
+ -type iodata() :: iolist() | binary().
+
+ A binary or list containing bytes and/or iodata. This datatype is
+ used to represent data that is meant to be output using any I/O
+ module. For example: file:write/2 or gen_tcp:send/2.
+
+ To convert an iodata() term to binary() you can use
+ iolist_to_binary/2. To transcode a string() or
+ unicode:chardata() to iodata() you can use
+ unicode:characters_to_binary/1.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_0_type.txt
new file mode 100644
index 0000000000..aa17b96ab8
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_0_type.txt
@@ -0,0 +1,10 @@
+
+ -type iolist() ::
+  maybe_improper_list(byte() | binary() | iolist(),
+  binary() | []).
+
+ A list containing bytes and/or iodata. This datatype is used to
+ represent data that is meant to be output using any I/O module.
+ For example: file:write/2 or gen_tcp:send/2.
+
+ In most use cases you want to use iodata() instead of this type.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_to_iovec_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_to_iovec_1_func.txt
index e362ef610a..83cb5ad81c 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_to_iovec_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_iolist_to_iovec_1_func.txt
@@ -8,4 +8,27 @@
OTP 20.1
Returns an iovec that is made from the integers and binaries in 
- IoListOrBinary.
+ IoListOrBinary. This function is useful when you want to flatten
+ an iolist but you do not need a single binary. This can be useful
+ for passing the data to nif functions such as enif_inspect_iovec
+ or do more efficient message passing. The advantage of using this
+ function over iolist_to_binary/1 is that it does not have to
+ copy off-heap binaries. Example:
+
+ > Bin1 = <<1,2,3>>.
+ <<1,2,3>>
+ > Bin2 = <<4,5>>.
+ <<4,5>>
+ > Bin3 = <<6>>.
+ <<6>>
+ %% If you pass small binaries and integers it works as iolist_to_binary
+ > erlang:iolist_to_iovec([Bin1,1,[2,3,Bin2],4|Bin3]).
+ [<<1,2,3,1,2,3,4,5,4,6>>]
+ %% If you pass larger binaries, they are split and returned in a form
+ %% optimized for calling the C function writev.
+ > erlang:iolist_to_iovec([<<1>>,<<2:8096>>,<<3:8096>>]).
+ [<<1,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...>>]
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_is_process_alive_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_is_process_alive_1_func.txt
index 919d6b4f68..e8a9970a4d 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_is_process_alive_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_is_process_alive_1_func.txt
@@ -19,6 +19,5 @@
is_process_alive(P2Pid),
% P2 is not alive (the call above always return false)
- See the documentation about communication in Erlang and
- erlang:exit/2 for more information about signals and exit
- singnals.
+ See the documentation about signals and erlang:exit/2 for more
+ information about signals and exit signals.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_link_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_link_1_func.txt
index 6286448237..407d8c7fa7 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_link_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_link_1_func.txt
@@ -1,25 +1,51 @@
-spec link(PidOrPort) -> true when PidOrPort :: pid() | port().
- Creates a link between the calling process and another process (or
- port) PidOrPort. If the link already exists or a process
- attempts to create a link to itself, nothing is done. Returns 
- true if the link is set up.
+ Sets up and activates a link between the calling process and
+ another process or a port identified by PidOrPort. We will from
+ here on call the identified process or port linkee. If the linkee
+ is a port, it must reside on the same node as the caller.
- If PidOrPort does not exist and checking it is cheap, a noproc
- error is raised. Currently, checking is cheap if the PidOrPort
- is local and the caller does not trap exits (see process_flag/2 
- ).
+ If one of the participants of a link terminates, it will send an
+ exit signal to the other participant. The exit signal will
+ contain the exit reason of the terminated participant. Other
+ cases when exit signals are triggered due to a link are when no
+ linkee exist (noproc exit reason) and when the connection
+ between linked processes on different nodes is lost or cannot be
+ established (noconnection exit reason).
- Apart from any exit signals from the linked process itself, two
- special exit signals may be sent to the calling process:
+ An existing link can be removed by calling unlink/1. For more
+ information on links and exit signals due to links, see the
+ Processes chapter in the Erlang Reference Manual:
- • noproc is sent immediately if PidOrPort does not exist at
- the time of linking (if the caller is trapping exits or 
- PidOrPort is remote).
+ • Links
- • noconnection if PidOrPort is remote and a connection
- between the nodes could not be established or was severed.
+ • Sending Exit Signals
- See Processes ➜ Links in the Erlang Reference Manual for more
- details.
+ • Receiving Exit Signals
+
+ For historical reasons, link/1 has a strange semi-synchronous
+ behavior when it is "cheap" to check if the linkee exists or not,
+ and the caller does not trap exits. If the above is true and the
+ linkee does not exist, link/1 will raise a noproc error
+ exception. The expected behavior would instead have been that 
+ link/1 returned true, and the caller later was sent an exit
+ signal with noproc exit reason, but this is unfortunately not
+ the case. The noproc exception is not to be confused with an
+ exit signal with exit reason noproc. Currently it is "cheap" to
+ check if the linkee exists when it is supposed to reside on the
+ same node as the calling process.
+
+ The link setup and activation is performed asynchronously. If the
+ link already exists, or if the caller attempts to create a link to
+ itself, nothing is done. A detailed description of the link
+ protocol can be found in the Distribution Protocol chapter of
+ the ERTS User's Guide.
+
+ Failure:
+
+ • badarg if PidOrPort does not identify a process or a node
+ local port.
+
+ • noproc linkee does not exist and it is "cheap" to check if
+ it exists as described above.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_0_type.txt
new file mode 100644
index 0000000000..dccc26b30f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type list() :: list().
+
+ An Erlang list containing terms of any type.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_1_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_1_type.txt
new file mode 100644
index 0000000000..3fdedd543b
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_1_type.txt
@@ -0,0 +1,4 @@
+
+ -type list(ContentType) :: [ContentType].
+
+ An Erlang list containing terms of the type ContentType.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_atom_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_atom_1_func.txt
index 30a6bb2b2a..c77d5233d4 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_atom_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_atom_1_func.txt
@@ -5,10 +5,7 @@
As from Erlang/OTP 20, String may contain any Unicode character.
Earlier versions allowed only ISO-latin-1 characters as the
- implementation did not allow Unicode characters above 255. For
- more information on Unicode support in atoms, see note on UTF-8
- encoded atoms in section "External Term Format" in the User's
- Guide.
+ implementation did not allow Unicode characters above 255.
Note:
The number of characters that are permitted in an atom name is
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_existing_atom_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_existing_atom_1_func.txt
index d89f63af15..315d160be9 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_existing_atom_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_list_to_existing_atom_1_func.txt
@@ -2,7 +2,9 @@
-spec list_to_existing_atom(String) -> atom() when String :: string().
Returns the atom whose text representation is String, but only
- if there already exists such atom.
+ if there already exists such atom. An atom exists if it has been
+ created by the run-time system by either loading code or creating
+ a term in which the atom is part.
Failure: badarg if there does not already exist an atom whose
text representation is String.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_load_module_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_load_module_2_func.txt
index 6b3d2b5a1f..b9368aba59 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_load_module_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_load_module_2_func.txt
@@ -23,6 +23,12 @@
Binary contains a module that cannot be loaded because old
code for this module already exists.
+ on_load:
+ The code in Binary contains an on_load declaration that
+ must be executed before Binary can become the current code.
+ Any previous current code for Module will remain until the 
+ on_load call has finished.
+
Warning:
This BIF is intended for the code server (see code(3)) and
is not to be used elsewhere.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_lt_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_lt_2_func.txt
new file mode 100644
index 0000000000..64323d56c2
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_lt_2_func.txt
@@ -0,0 +1,5 @@
+
+  '<'/2
+
+ The documentation for '<'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_fun_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_fun_3_func.txt
new file mode 100644
index 0000000000..b88f7a06ac
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_fun_3_func.txt
@@ -0,0 +1,5 @@
+
+  make_fun/3
+
+ The documentation for make_fun/3 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_ref_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_ref_0_func.txt
index b282e3b375..64f347e9c3 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_ref_0_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_make_ref_0_func.txt
@@ -5,7 +5,7 @@
connected nodes.
Warning:
- Known issue: When a node is restarted multiple times with the
+ Before OTP-23 when a node is restarted multiple times with the
same node name, references created on a newer node can be
mistaken for a reference created on an older node with the
same node name.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_map_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_map_0_type.txt
new file mode 100644
index 0000000000..33cd36bd08
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_map_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type map() :: #{any() => any()}.
+
+ An Erlang map containing any number of key and value
+ associations.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_0_type.txt
new file mode 100644
index 0000000000..f432632fd9
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type maybe_improper_list() :: maybe_improper_list(any(), any()).
+
+ An Erlang list that is not guaranteed to end with a [], and
+ where the list elements can be of any type.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_2_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_2_type.txt
new file mode 100644
index 0000000000..b7aaf7bc2c
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_maybe_improper_list_2_type.txt
@@ -0,0 +1,6 @@
+
+ -type maybe_improper_list(ContentType, TerminationType) ::
+  maybe_improper_list(ContentType, TerminationType).
+
+ An Erlang list, that is not guaranteed to end with a [], and
+ where the list elements are of the type ContentType.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_memory_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_memory_0_func.txt
index e440dfd550..d87777c8de 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_memory_0_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_memory_0_func.txt
@@ -59,13 +59,6 @@
This memory is part of the memory presented as system
memory.
- low:
- Only on 64-bit halfword emulator. The total amount of memory
- allocated in low memory areas that are restricted to < 4 GB,
- although the system can have more memory.
-
- Can be removed in a future release of the halfword emulator.
-
maximum:
The maximum total amount of memory allocated since the
emulator was started. This tuple is only present when the
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_message_queue_data_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_message_queue_data_0_type.txt
index c4789ef677..5799c41b4d 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_message_queue_data_0_type.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_message_queue_data_0_type.txt
@@ -5,5 +5,5 @@
-type message_queue_data() :: off_heap | on_heap.
- Process message queue data configuration. For more info see 
- process_flag(message_queue_data, MQD)
+ Process message queue data configuration. For more information,
+ see process_flag(message_queue_data, MQD)
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_mfa_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_mfa_0_type.txt
new file mode 100644
index 0000000000..acc57bebf0
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_mfa_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type mfa() :: {module(), atom(), arity()}.
+
+ A three-tuple representing a Module:Function/Arity function
+ signature.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_module_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_module_0_type.txt
new file mode 100644
index 0000000000..f7274e1ffc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_module_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type module() :: atom().
+
+ An Erlang module represented by an atom.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_2_func.txt
index c88c266702..f569717945 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_2_func.txt
@@ -54,8 +54,8 @@
Object:
The monitored entity, which triggered the event. When
- monitoring a local process or port, Object will be equal to
- the pid() or port() that was being monitored. When
+ monitoring a process or a local port, Object will be equal
+ to the pid() or port() that was being monitored. When
monitoring process or port by name, Object will have format 
{RegisteredName, Node} where RegisteredName is the name
which has been used with monitor/2 call and Node is local
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_3_func.txt
index 35cab15b0d..d2568b9d01 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_3_func.txt
@@ -10,7 +10,7 @@
 when MonitorRef :: reference().
Since:
- OTP @OTP-16718@
+ OTP 24.0
Types:
-type monitor_port_identifier() :: port() | registered_name().
@@ -59,8 +59,86 @@
removed using the unalias/1 BIF, the monitor will still
be left active.
+ Example:
+
+ server() ->
+ receive
+ {request, AliasReqId, Request} ->
+ Result = perform_request(Request),
+ AliasReqId ! {reply, AliasReqId, Result}
+ end,
+ server().
+
+ client(ServerPid, Request) ->
+ AliasMonReqId = monitor(process, ServerPid, [{alias, reply_demonitor}]),
+ ServerPid ! {request, AliasMonReqId, Request},
+ %% Alias as well as monitor will be automatically deactivated if we
+ %% receive a reply or a 'DOWN' message since we used 'reply_demonitor'
+ %% as unalias option...
+ receive
+ {reply, AliasMonReqId, Result} ->
+ Result;
+ {'DOWN', AliasMonReqId, process, ServerPid, ExitReason} ->
+ error(ExitReason)
+ end.
+
+
+ Note that both the server and the client in this example must
+ be executing on at least OTP 24 systems in order for this to
+ work.
+
+ For more information on process aliases see the Process
+ Aliases section of the Erlang Reference Manual.
+
{tag, UserDefinedTag}:
Replace the default Tag with UserDefinedTag in the
monitor message delivered when the monitor is triggered. For
example, when monitoring a process, the 'DOWN' tag in the
down message will be replaced by UserDefinedTag.
+
+ An example of how the {tag, UserDefinedTag} option can be
+ used in order to enable the new selective receive
+ optimization, introduced in OTP 24, when making multiple
+ requests to different servers:
+
+ server() ->
+ receive
+ {request, From, ReqId, Request} ->
+ Result = perform_request(Request),
+ From ! {reply, self(), ReqId, Result}
+ end,
+ server().
+
+ client(ServerPids, Request) when is_list(ServerPids) ->
+ ReqId = make_ref(),
+ lists:foreach(fun (ServerPid) ->
+ _ = monitor(process, ServerPid,
+ [{tag, {'DOWN', ReqId}}]),
+ ServerPid ! {request, self(), ReqId, Request}
+ end,
+ ServerPids),
+ receive_replies(ReqId, length(ServerPids), []).
+
+ receive_replies(_ReqId, 0, Acc) ->
+ Acc;
+ receive_replies(ReqId, N, Acc) ->
+ %% The compiler will detect that we match on the 'ReqId'
+ %% reference in all clauses, and will enable the selective
+ %% receive optimization which makes the receive able to
+ %% skip past all messages present in the message queue at
+ %% the time when the 'ReqId' reference was created...
+ Res = receive
+ {reply, ServerPid, ReqId, Result} ->
+ %% Here we typically would have deactivated the
+ %% monitor by a call to demonitor(Mon, [flush]) but
+ %% we ignore this in this example for simplicity...
+ {ok, ServerPid, Result};
+ {{'DOWN', ReqId}, _Mon, process, ServerPid, ExitReason} ->
+ {error, ServerPid, ExitReason}
+ end,
+ receive_replies(ReqId, N-1, [Res | Acc]).
+
+
+ In order for this example to work as intended, the client must
+ be executing on at least an OTP 24 system, but the servers may
+ execute on older systems.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_node_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_node_2_func.txt
index c137ca38fd..89561c41ad 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_node_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_monitor_node_2_func.txt
@@ -17,6 +17,12 @@
to Node, an attempt is made to create one. If this fails, a 
nodedown message is delivered.
+ The delivery of the nodedown signal is not ordered with respect
+ to other link or monitor signals from the node that goes down. If
+ you need a guarantee that all signals from the remote node has
+ been delivered before the nodedown signal is sent, you should
+ use net_kernel:monitor_nodes/1.
+
Nodes connected through hidden connections can be monitored as any
other nodes.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_neg_integer_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_neg_integer_0_type.txt
new file mode 100644
index 0000000000..bce7a55517
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_neg_integer_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type neg_integer() :: neg_integer().
+
+ A negative integer.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nif_resource_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nif_resource_0_type.txt
index 7cc1f2598b..6c2cf4ced7 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nif_resource_0_type.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nif_resource_0_type.txt
@@ -1,4 +1,4 @@
-opaque nif_resource() 
- An opaque handle identifing a NIF resource object .
+ An opaque handle identifying a NIF resource object .
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nil_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nil_0_type.txt
new file mode 100644
index 0000000000..3f20bcd23d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nil_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type nil() :: [].
+
+ The empty list().
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_no_return_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_no_return_0_type.txt
new file mode 100644
index 0000000000..660047e345
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_no_return_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type no_return() :: none().
+
+ The type used to show that a function will never return a value,
+ that is it will always throw an exception.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_node_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_node_0_type.txt
new file mode 100644
index 0000000000..b6d6364aca
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_node_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type node() :: atom().
+
+ An Erlang node represented by an atom.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_non_neg_integer_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_non_neg_integer_0_type.txt
new file mode 100644
index 0000000000..f07d7a4ee5
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_non_neg_integer_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type non_neg_integer() :: non_neg_integer().
+
+ A non-negative integer, that is any positive integer or 0.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_none_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_none_0_type.txt
new file mode 100644
index 0000000000..bcefabd355
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_none_0_type.txt
@@ -0,0 +1,6 @@
+
+ -type none() :: none().
+
+ This type is used to show that a function will never return a
+ value; that is it will always throw an exception. In a spec, use 
+ no_return() for the sake of clarity.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_binary_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_binary_0_type.txt
new file mode 100644
index 0000000000..9df59ae11a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_binary_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type nonempty_binary() :: <<_:8, _:_*8>>.
+
+ A binary() that contains some data.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_bitstring_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_bitstring_0_type.txt
new file mode 100644
index 0000000000..e25e9fda6b
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_bitstring_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type nonempty_bitstring() :: <<_:1, _:_*1>>.
+
+ A bitstring() that contains some data.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_improper_list_2_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_improper_list_2_type.txt
new file mode 100644
index 0000000000..6c6cef0861
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_improper_list_2_type.txt
@@ -0,0 +1,5 @@
+
+ -type nonempty_improper_list(ContentType, TerminationType) ::
+  nonempty_improper_list(ContentType, TerminationType).
+
+ A maybe_improper_list/2 that contains some items.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_0_type.txt
new file mode 100644
index 0000000000..266d82dc9b
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type nonempty_list() :: [any(), ...].
+
+ A list() that contains some items.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_1_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_1_type.txt
new file mode 100644
index 0000000000..4184648089
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_list_1_type.txt
@@ -0,0 +1,4 @@
+
+ -type nonempty_list(ContentType) :: [ContentType, ...].
+
+ A list(ContentType) that contains some items.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_0_type.txt
new file mode 100644
index 0000000000..ea43e2683a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type nonempty_maybe_improper_list() ::
+  nonempty_maybe_improper_list(any(), any()).
+
+ A maybe_improper_list() that contains some items.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_2_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_2_type.txt
new file mode 100644
index 0000000000..49d5acbb14
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_maybe_improper_list_2_type.txt
@@ -0,0 +1,6 @@
+
+ -type nonempty_maybe_improper_list(ContentType, TerminationType) ::
+  nonempty_maybe_improper_list(ContentType, TerminationType).
+
+ A maybe_improper_list(ContentType, TerminationType) that
+ contains some items.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_string_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_string_0_type.txt
new file mode 100644
index 0000000000..05e01446b3
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_nonempty_string_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type nonempty_string() :: [char(), ...].
+
+ A string() that contains some characters.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_not_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_not_1_func.txt
new file mode 100644
index 0000000000..bc2eb81305
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_not_1_func.txt
@@ -0,0 +1,5 @@
+
+  'not'/1
+
+ The documentation for 'not'/1 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_number_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_number_0_type.txt
new file mode 100644
index 0000000000..ead7a9e2dd
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_number_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type number() :: integer() | float().
+
+ An Erlang number.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_open_port_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_open_port_2_func.txt
index 06de905786..1c8a625bb5 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_open_port_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_open_port_2_func.txt
@@ -36,7 +36,7 @@
Returns a port identifier as the result of opening a new Erlang
port. A port can be seen as an external Erlang process.
- The name of the executable as well as the arguments specifed in 
+ The name of the executable as well as the arguments specified in 
cd, env, args, and arg0 are subject to Unicode filename
translation if the system is running in Unicode filename mode. To
avoid translation or to force, for example UTF-8, supply the
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_or_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_or_2_func.txt
new file mode 100644
index 0000000000..5d8fcc2497
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_or_2_func.txt
@@ -0,0 +1,5 @@
+
+  'or'/2
+
+ The documentation for 'or'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pid_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pid_0_type.txt
new file mode 100644
index 0000000000..0a2d75b259
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pid_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type pid() :: pid().
+
+ An Erlang process identifier.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_0_type.txt
new file mode 100644
index 0000000000..5484e96380
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type port() :: port().
+
+ An Erlang port identifier.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_call_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_call_2_func.txt
new file mode 100644
index 0000000000..bb00bda40f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_call_2_func.txt
@@ -0,0 +1,5 @@
+
+  port_call/2
+
+ The documentation for port_call/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_get_data_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_get_data_1_func.txt
new file mode 100644
index 0000000000..090db5838b
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_get_data_1_func.txt
@@ -0,0 +1,6 @@
+
+  port_get_data/1
+
+ The documentation for port_get_data/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_set_data_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_set_data_2_func.txt
new file mode 100644
index 0000000000..d27a36b7e8
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_port_set_data_2_func.txt
@@ -0,0 +1,6 @@
+
+  port_set_data/2
+
+ The documentation for port_set_data/2 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pos_integer_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pos_integer_0_type.txt
new file mode 100644
index 0000000000..a8cfd39cc8
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pos_integer_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type pos_integer() :: pos_integer().
+
+ An integer greater than zero.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_posixtime_to_universaltime_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_posixtime_to_universaltime_1_func.txt
new file mode 100644
index 0000000000..6f39b81c43
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_posixtime_to_universaltime_1_func.txt
@@ -0,0 +1,6 @@
+
+  posixtime_to_universaltime/1
+
+ The documentation for posixtime_to_universaltime/1 is hidden.
+ This probably means that it is internal and not to be used by
+ other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pre_loaded_0_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pre_loaded_0_func.txt
index 795a78ef0e..efaf2aaba9 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pre_loaded_0_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_pre_loaded_0_func.txt
@@ -1,7 +1,7 @@
-spec pre_loaded() -> [module()].
- Returns a list of Erlang modules that are preloaded in the system.
- As all loading of code is done through the file system, the file
- system must have been loaded previously. Hence, at least the
- module init must be preloaded.
+ Returns a list of Erlang modules that are preloaded in the
+ run-time system. Pre-loaded modules are Erlang modules that are
+ needed to bootstrap the system to load the first Erlang modules
+ from either disk or by using erl_boot_server.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_prepare_loading_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_prepare_loading_2_func.txt
new file mode 100644
index 0000000000..4b551a5b91
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_prepare_loading_2_func.txt
@@ -0,0 +1,6 @@
+
+  prepare_loading/2
+
+ The documentation for prepare_loading/2 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_flag_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_flag_2_func.txt
index dac53ad065..8c7b6640dd 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_flag_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_flag_2_func.txt
@@ -2,6 +2,14 @@
-spec process_flag(save_calls, N) -> OldN
 when N :: 0..10000, OldN :: 0..10000.
+ -spec process_flag(fullsweep_after, FullsweepAfter) -> OldFullsweepAfter
+  when
+  FullsweepAfter :: non_neg_integer(),
+  OldFullsweepAfter :: non_neg_integer().
+
+Since:
+ OTP 24.0
+
-spec process_flag(min_bin_vheap_size, MinBinVHeapSize) ->
 OldMinBinVHeapSize
 when
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_info_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_info_2_func.txt
index 8a5af38f1c..7df3d29d68 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_info_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_process_info_2_func.txt
@@ -117,6 +117,10 @@
Items in the same order as the Items were included in ItemList.
Valid Items can be included multiple times in ItemList.
+ Getting process information follows the signal ordering guarantees
+ described in the Processes Chapter in the Erlang Reference
+ Manual.
+
Note:
If registered_name is part of ItemList and the process has
no name registered, a {registered_name, []}, InfoTuple
@@ -138,8 +142,8 @@
implementation BinInfo is a list of tuples. The tuples
contain; BinaryId, BinarySize, BinaryRefcCount.
- The message queue is on the heap depending on the process flag 
- message_queue_data.
+ Depending on the value of the message_queue_data process
+ flag the message queue may be stored on the heap.
{catchlevel, CatchLevel}:
CatchLevel is the number of currently active catches in this
@@ -251,10 +255,10 @@
the local node name.
{message_queue_data, MQD}:
- Returns the current state of process flag message_queue_data. 
- MQD is either off_heap or on_heap. For more information,
- see the documentation of process_flag(message_queue_data,
- MQD).
+ MQD is the current value of the message_queue_data process
+ flag, which can be either off_heap or on_heap. For more
+ information, see the documentation of 
+ process_flag(message_queue_data, MQD).
{priority, Level}:
Level is the current priority level for the process. For more
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_raise_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_raise_3_func.txt
index 407a06aab4..e661585ba6 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_raise_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_raise_3_func.txt
@@ -3,14 +3,13 @@
 when
 Class :: error | exit | throw,
 Reason :: term(),
-  Stacktrace :: raise_stacktrace().
+  Stacktrace ::
+  raise_stacktrace() | stacktrace().
Types:
-type raise_stacktrace() ::
[{module(), atom(), arity() | [term()]} |
- {function(), [term()]}] |
- [{module(), atom(), arity() | [term()], [{atom(), term()}]} |
- {function(), [term()], [{atom(), term()}]}].
+ {function(), arity() | [term()]}].
Raises an exception of the specified class, reason, and call stack
backtrace (stacktrace).
@@ -31,12 +30,12 @@
end
That is, a list of four-tuples {Module, Function, Arity | Args,
- Location}, where Module and Function are atoms, and the third
- element is an integer arity or an argument list. The stacktrace
- can also contain {Fun, Args, Location} tuples, where Fun is a
- local fun and Args is an argument list.
+ ExtraInfo}, where Module and Function are atoms, and the
+ third element is an integer arity or an argument list. The
+ stacktrace can also contain {Fun, Args, ExtraInfo} tuples, where 
+ Fun is a local fun and Args is an argument list.
- Element Location at the end is optional. Omitting it is
+ Element ExtraInfo at the end is optional. Omitting it is
equivalent to specifying an empty list.
The stacktrace is used as the exception stacktrace for the calling
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_reference_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_reference_0_type.txt
new file mode 100644
index 0000000000..e2ded8970e
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_reference_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type reference() :: reference().
+
+ An Erlang reference.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_register_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_register_2_func.txt
index aa1ea7ef8d..b4b5c8a543 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_register_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_register_2_func.txt
@@ -2,14 +2,19 @@
-spec register(RegName, PidOrPort) -> true
 when RegName :: atom(), PidOrPort :: port() | pid().
- Associates the name RegName with a process identifier (pid) or a
- port identifier. RegName, which must be an atom, can be used
- instead of the pid or port identifier in send operator (RegName !
- Message). Example:
+ Registers the name RegName with a process identifier (pid) or a
+ port identifier in the name registry. RegName, which must be
+ an atom, can be used instead of the pid or port identifier in send
+ operator (RegName ! Message) and most other BIFs that take a pid
+ or port identifies as an argument. Example:
> register(db, Pid).
true
+ The registered name is considered a Directly Visible Erlang
+ Resource and is automatically unregistered when the process
+ terminates.
+
Failures:
badarg:
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_rem_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_rem_2_func.txt
new file mode 100644
index 0000000000..d1f2d8eb5e
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_rem_2_func.txt
@@ -0,0 +1,5 @@
+
+  'rem'/2
+
+ The documentation for 'rem'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_send_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_send_2_func.txt
index 67721a962c..08871de4ea 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_send_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_send_2_func.txt
@@ -12,9 +12,9 @@
Sends a message and returns Msg. This is the same as using the
send operator: Dest ! Msg.
- Dest can be a remote or local process identifier, a (local) port,
- a locally registered name, or a tuple {RegName, Node} for a
- registered name at another node.
+ Dest can be a remote or local process identifier, an alias, a
+ (local) port, a locally registered name, or a tuple {RegName,
+ Node} for a registered name at another node.
The function fails with a badarg run-time error if Dest is an
atom name, but this name is not registered. This is the only case
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_2_func.txt
new file mode 100644
index 0000000000..eac7f6352c
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_2_func.txt
@@ -0,0 +1,5 @@
+
+  seq_trace/2
+
+ The documentation for seq_trace/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_info_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_info_1_func.txt
new file mode 100644
index 0000000000..6dc372826e
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_info_1_func.txt
@@ -0,0 +1,6 @@
+
+  seq_trace_info/1
+
+ The documentation for seq_trace_info/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_1_func.txt
new file mode 100644
index 0000000000..d0ae337121
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_1_func.txt
@@ -0,0 +1,6 @@
+
+  seq_trace_print/1
+
+ The documentation for seq_trace_print/1 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_2_func.txt
new file mode 100644
index 0000000000..54905aa1a9
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_seq_trace_print_2_func.txt
@@ -0,0 +1,6 @@
+
+  seq_trace_print/2
+
+ The documentation for seq_trace_print/2 is hidden. This probably
+ means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_1_func.txt
new file mode 100644
index 0000000000..d775c2ca6f
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_1_func.txt
@@ -0,0 +1,12 @@
+
+ -spec erlang:set_cookie(Cookie) -> true when Cookie :: atom().
+
+Since:
+ OTP 24.1
+
+ Sets the magic cookie of the local node to the atom Cookie,
+ which is also the cookie for all nodes that have no explicit
+ cookie set with set_cookie/2 Cookie (see section Distributed
+ Erlang in the Erlang Reference Manual in System Documentation).
+
+ Failure: function_clause if the local node is not alive.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_2_func.txt
index 841be9c7cd..571d771ae8 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cookie_2_func.txt
@@ -2,9 +2,10 @@
-spec erlang:set_cookie(Node, Cookie) -> true
 when Node :: node(), Cookie :: atom().
- Sets the magic cookie of Node to the atom Cookie. If Node is
- the local node, the function also sets the cookie of all other
- unknown nodes to Cookie (see section Distributed Erlang in the
- Erlang Reference Manual in System Documentation).
+ Sets the magic cookie for Node to the atom Cookie. If Node
+ is the local node, the function sets the cookie of all other nodes
+ (that have no explicit cookie set with this function) to Cookie
+ (see section Distributed Erlang in the Erlang Reference Manual
+ in System Documentation).
Failure: function_clause if the local node is not alive.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cpu_topology_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cpu_topology_1_func.txt
new file mode 100644
index 0000000000..1b44778f1a
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_set_cpu_topology_1_func.txt
@@ -0,0 +1,6 @@
+
+  set_cpu_topology/1
+
+ The documentation for set_cpu_topology/1 is hidden. This
+ probably means that it is internal and not to be used by other
+ applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_2_func.txt
new file mode 100644
index 0000000000..93491f7786
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_2_func.txt
@@ -0,0 +1,5 @@
+
+  setnode/2
+
+ The documentation for setnode/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_3_func.txt
new file mode 100644
index 0000000000..0e2112a100
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_setnode_3_func.txt
@@ -0,0 +1,5 @@
+
+  setnode/3
+
+ The documentation for setnode/3 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slash_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slash_2_func.txt
new file mode 100644
index 0000000000..688a861491
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slash_2_func.txt
@@ -0,0 +1,5 @@
+
+  '/'/2
+
+ The documentation for '/'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slasheq_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slasheq_2_func.txt
new file mode 100644
index 0000000000..37d8260593
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_slasheq_2_func.txt
@@ -0,0 +1,5 @@
+
+  '/='/2
+
+ The documentation for '/='/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_spawn_opt_4_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_spawn_opt_4_func.txt
index 7a7ab7a819..22956f6ce9 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_spawn_opt_4_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_spawn_opt_4_func.txt
@@ -125,8 +125,9 @@
process_flag(max_heap_size, Size).
{message_queue_data, MQD}:
- Sets the state of the message_queue_data process flag. MQD
- is to be either off_heap or on_heap. The default 
- message_queue_data process flag is determined by command-line
- argument +hmqd in erl(1). For more information, see the
- documentation of process_flag(message_queue_data, MQD).
+ Sets the value of the message_queue_data process flag. MQD
+ can be either off_heap or on_heap. The default value of
+ the message_queue_data process flag is determined by the
+ command-line argument +hmqd in erl(1). For more
+ information, see the documentation of 
+ process_flag(message_queue_data, MQD).
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_0_type.txt
new file mode 100644
index 0000000000..9d02af6aa5
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_0_type.txt
@@ -0,0 +1,10 @@
+
+ -type stacktrace() ::
+  [{module(),
+  atom(),
+  arity() | [term()],
+  [stacktrace_extrainfo()]} |
+  {function(), arity() | [term()], [stacktrace_extrainfo()]}].
+
+ An Erlang stacktrace as described by Errors and Error Handling
+ section in the Erlang Reference Manual.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_extrainfo_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_extrainfo_0_type.txt
new file mode 100644
index 0000000000..acdcdd1eb4
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_stacktrace_extrainfo_0_type.txt
@@ -0,0 +1,10 @@
+
+ -type stacktrace_extrainfo() ::
+  {line, pos_integer()} |
+  {file, unicode:chardata()} |
+  {error_info,
+  #{module => module(), function => atom(), cause => term()}} |
+  {atom(), term()}.
+
+ An Erlang stacktrace as described by Errors and Error Handling
+ section in the Erlang Reference Manual.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_star_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_star_2_func.txt
new file mode 100644
index 0000000000..ff7f8595a1
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_star_2_func.txt
@@ -0,0 +1,5 @@
+
+  '*'/2
+
+ The documentation for '*'/2 is hidden. This probably means that
+ it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_statistics_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_statistics_1_func.txt
index e54fa13ce6..f9bb276f72 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_statistics_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_statistics_1_func.txt
@@ -24,16 +24,6 @@
 Input :: non_neg_integer(),
 Output :: non_neg_integer().
- -spec statistics(scheduler_wall_time) ->
-  [{SchedulerId, ActiveTime, TotalTime}] | undefined
-  when
-  SchedulerId :: pos_integer(),
-  ActiveTime :: non_neg_integer(),
-  TotalTime :: non_neg_integer().
-
-Since:
- OTP R15B01
-
-spec statistics(active_tasks_all) -> [ActiveTasks]
 when ActiveTasks :: non_neg_integer().
@@ -71,6 +61,16 @@
 Wallclock_Time_Since_Last_Call ::
 non_neg_integer().
+ -spec statistics(scheduler_wall_time) ->
+  [{SchedulerId, ActiveTime, TotalTime}] | undefined
+  when
+  SchedulerId :: pos_integer(),
+  ActiveTime :: non_neg_integer(),
+  TotalTime :: non_neg_integer().
+
+Since:
+ OTP R15B01
+
-spec statistics(exact_reductions) ->
 {Total_Exact_Reductions,
 Exact_Reductions_Since_Last_Call}
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_string_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_string_0_type.txt
new file mode 100644
index 0000000000..fee694adbc
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_string_0_type.txt
@@ -0,0 +1,5 @@
+
+ -type string() :: [char()].
+
+ A character string represented by a list of ASCII characters or
+ unicode codepoints.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_subtract_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_subtract_2_func.txt
new file mode 100644
index 0000000000..b3e9734abf
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_subtract_2_func.txt
@@ -0,0 +1,5 @@
+
+  subtract/2
+
+ The documentation for subtract/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_suspend_process_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_suspend_process_2_func.txt
index 7f22bae23c..8b604b5025 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_suspend_process_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_suspend_process_2_func.txt
@@ -55,7 +55,7 @@
process that issued this request, have called 
resume_process(Suspendee) before getting the reply.
- Appart from the reply message, the {asynchronous, ReplyTag}
+ Apart from the reply message, the {asynchronous, ReplyTag}
option behaves exactly the same as the asynchronous option
without reply tag.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_system_info_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_system_info_1_func.txt
index 958bee44a1..1015fbac90 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_system_info_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_system_info_1_func.txt
@@ -198,10 +198,10 @@
message_queue_data:
Returns the default value of the message_queue_data process
- flag, which is either off_heap or on_heap. This default is
- set by command-line argument +hmqd in erl(1). For more
- information on the message_queue_data process flag, see
- documentation of process_flag(message_queue_data, MQD).
+ flag, which can be either off_heap or on_heap. The default
+ value is set by the command-line argument +hmqd in erl(1).
+ For more information, see the documentation of 
+ process_flag(message_queue_data, MQD).
min_heap_size:
Returns {min_heap_size, MinHeapSize}, where MinHeapSize is
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_0_type.txt
new file mode 100644
index 0000000000..275c5aa8c3
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type term() :: any().
+
+ All possible Erlang terms. Synonym for any().
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_binary_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_binary_2_func.txt
index 5c2cc9e708..f72b5be32c 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_binary_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_binary_2_func.txt
@@ -5,6 +5,7 @@
 Options ::
 [compressed |
 {compressed, Level :: 0..9} |
+  deterministic |
 {minor_version, Version :: 0..2}].
Returns a binary data object that is the result of encoding Term
@@ -57,8 +58,18 @@
2:
Drops usage of the latin1 atom encoding and unconditionally
- use utf8 encoding for all atoms. This will be changed to the
- default in a future major release of Erlang/OTP. Erlang/OTP
- systems as of R16B can decode this representation.
+ use utf8 encoding for all atoms. Erlang/OTP systems as of R16B
+ can decode this representation.
+
+ Note:
+ In Erlang/OTP 26, the default minor_version is planned
+ to change from 1 to 2. See Upcoming Potential
+ Incompatibilities .
+
+ Option deterministic (introduced in OTP 24.1) can be used to
+ ensure that within the same major release of Erlang/OTP, the same
+ encoded representation is returned for the same term. There is
+ still no guarantee that the encoded representation remains the
+ same between major releases of Erlang/OTP.
See also binary_to_term/1.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_iovec_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_iovec_2_func.txt
index 176c8eef09..1379c95c36 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_iovec_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_term_to_iovec_2_func.txt
@@ -5,6 +5,7 @@
 Options ::
 [compressed |
 {compressed, Level :: 0..9} |
+  deterministic |
 {minor_version, Version :: 0..2}].
Since:
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_timeout_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_timeout_0_type.txt
new file mode 100644
index 0000000000..df22bfd787
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_timeout_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type timeout() :: infinity | non_neg_integer().
+
+ A timeout value that can be passed to a receive expression.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_3_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_3_func.txt
index 1712d8dca3..46b04a1c4a 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_3_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_3_func.txt
@@ -328,9 +328,6 @@
{trace, PidPort, getting_unlinked, Pid2}:
When PidPort gets unlinked from a process Pid2.
- {trace, Pid, exit, Reason}:
- When Pid exits with reason Reason.
-
{trace, Port, open, Pid, Driver}:
When Pid opens a new port Port with the running Driver.
@@ -412,6 +409,12 @@
The total size of binaries allowed in the virtual old heap
in the process before doing a garbage collection.
+ wordsize:
+ For the gc_minor_start event it is the size of the need
+ that triggered the GC. For the corresponding gc_minor_end
+ event it is the size of reclaimed memory = start 
+ heap_size - end heap_size.
+
All sizes are in words.
{trace, Pid, gc_max_heap_size, Info}:
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_info_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_info_2_func.txt
index eb15ee6787..978e3bb1c7 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_info_2_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_trace_info_2_func.txt
@@ -63,7 +63,7 @@
flags:
Returns a list of atoms indicating what kind of traces is
enabled for the process. The list is empty if no traces are
- enabled, and one or more of the followings atoms if traces are
+ enabled, and one or more of the following atoms if traces are
enabled: send, 'receive', set_on_spawn, call, 
return_to, procs, ports, set_on_first_spawn, 
set_on_link, running, running_procs, running_ports, 
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_tuple_0_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_tuple_0_type.txt
new file mode 100644
index 0000000000..c077d1d4ba
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_tuple_0_type.txt
@@ -0,0 +1,4 @@
+
+ -type tuple() :: tuple().
+
+ An Erlang tuple.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_type.txt
index 89aa1c4acc..e18a340c2b 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_type.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_type.txt
@@ -2,6 +2,100 @@
These types are documented in this module:
+ -type any() :: any().
+
+ -type arity() :: arity().
+
+ -type atom() :: atom().
+
+ -type binary() :: <<_:_*8>>.
+
+ -type bitstring() :: <<_:_*1>>.
+
+ -type boolean() :: true | false.
+
+ -type byte() :: 0..255.
+
+ -type char() :: 0..1114111.
+
+ -type float() :: float().
+
+ -type function() :: fun().
+
+ -type identifier() :: pid() | port() | reference().
+
+ -type integer() :: integer().
+
+ -type iodata() :: iolist() | binary().
+
+ -type iolist() ::
+  maybe_improper_list(byte() | binary() | iolist(),
+  binary() | []).
+
+ -type list() :: list().
+
+ -type list(ContentType) :: [ContentType].
+
+ -type map() :: #{any() => any()}.
+
+ -type maybe_improper_list() :: maybe_improper_list(any(), any()).
+
+ -type maybe_improper_list(ContentType, TerminationType) ::
+  maybe_improper_list(ContentType, TerminationType).
+
+ -type mfa() :: {module(), atom(), arity()}.
+
+ -type module() :: atom().
+
+ -type neg_integer() :: neg_integer().
+
+ -type nil() :: [].
+
+ -type no_return() :: none().
+
+ -type node() :: atom().
+
+ -type non_neg_integer() :: non_neg_integer().
+
+ -type none() :: none().
+
+ -type nonempty_binary() :: <<_:8, _:_*8>>.
+
+ -type nonempty_bitstring() :: <<_:1, _:_*1>>.
+
+ -type nonempty_improper_list(ContentType, TerminationType) ::
+  nonempty_improper_list(ContentType, TerminationType).
+
+ -type nonempty_list() :: [any(), ...].
+
+ -type nonempty_list(ContentType) :: [ContentType, ...].
+
+ -type nonempty_maybe_improper_list() ::
+  nonempty_maybe_improper_list(any(), any()).
+
+ -type nonempty_maybe_improper_list(ContentType, TerminationType) ::
+  nonempty_maybe_improper_list(ContentType, TerminationType).
+
+ -type nonempty_string() :: [char(), ...].
+
+ -type number() :: integer() | float().
+
+ -type pid() :: pid().
+
+ -type port() :: port().
+
+ -type pos_integer() :: pos_integer().
+
+ -type reference() :: reference().
+
+ -type string() :: [char()].
+
+ -type term() :: any().
+
+ -type timeout() :: infinity | non_neg_integer().
+
+ -type tuple() :: tuple().
+
-type ext_binary() :: binary().
-type ext_iovec() :: iovec().
@@ -52,3 +146,17 @@ These types are documented in this module:
 error_logger => boolean()}.
-type message_queue_data() :: off_heap | on_heap.
+
+ -type stacktrace_extrainfo() ::
+  {line, pos_integer()} |
+  {file, unicode:chardata()} |
+  {error_info,
+  #{module => module(), function => atom(), cause => term()}} |
+  {atom(), term()}.
+
+ -type stacktrace() ::
+  [{module(),
+  atom(),
+  arity() | [term()],
+  [stacktrace_extrainfo()]} |
+  {function(), arity() | [term()], [stacktrace_extrainfo()]}].
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unalias_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unalias_1_func.txt
index d4e54f4156..308c28a1e4 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unalias_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unalias_1_func.txt
@@ -2,7 +2,7 @@
-spec unalias(Alias) -> boolean() when Alias :: reference().
Since:
- OTP @OTP-16718@
+ OTP 24.0
Deactivate the alias Alias previously created by the calling
process. An alias can for example be created via alias/0, or 
@@ -11,3 +11,6 @@
Returns true if Alias was a currently active alias for current
processes; otherwise, false.
+
+ For more information on process aliases see the Process Aliases
+ section of the Erlang Reference Manual.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_universaltime_to_posixtime_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_universaltime_to_posixtime_1_func.txt
new file mode 100644
index 0000000000..a749876149
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_universaltime_to_posixtime_1_func.txt
@@ -0,0 +1,6 @@
+
+  universaltime_to_posixtime/1
+
+ The documentation for universaltime_to_posixtime/1 is hidden.
+ This probably means that it is internal and not to be used by
+ other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unlink_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unlink_1_func.txt
index 23fecba59c..9668d64fe3 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unlink_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unlink_1_func.txt
@@ -1,23 +1,31 @@
-spec unlink(Id) -> true when Id :: pid() | port().
- Removes the link, if there is one, between the calling process and
- the process or port referred to by Id.
+ Removes a link between the calling process and another process or
+ a port identified by Id. We will from here on call the
+ identified process or port unlinkee.
- Returns true and does not fail, even if there is no link to Id,
- or if Id does not exist.
+ A link can be set up using the link/1 BIF. For more information
+ on links and exit signals due to links, see the Processes
+ chapter in the Erlang Reference Manual:
- Once unlink(Id) has returned, it is guaranteed that the link
- between the caller and the entity referred to by Id has no
- effect on the caller in the future (unless the link is setup
- again). If the caller is trapping exits, an {'EXIT', Id, _}
- message from the link can have been placed in the caller's message
- queue before the call.
+ • Links
+
+ • Sending Exit Signals
- Notice that the {'EXIT', Id, _} message can be the result of the
- link, but can also be the result of Id calling exit/2.
- Therefore, it can be appropriate to clean up the message queue
- when trapping exits after the call to unlink(Id), as follows:
+ • Receiving Exit Signals
+
+ Once unlink(Id) has returned, it is guaranteed that the link
+ between the caller and the unlinkee has no effect on the caller in
+ the future (unless the link is setup again). Note that if the
+ caller is trapping exits, an {'EXIT', Id, ExitReason} message
+ due to the link may have been placed in the message queue of the
+ caller before the unlink(Id) call completed. Also note that the 
+ {'EXIT', Id, ExitReason} message may be the result of the link,
+ but may also be the result of the unlikee sending the caller an
+ exit signal by calling the exit/2 BIF. Therefore, it may or may
+ not be appropriate to clean up the message queue after a call to 
+ unlink(Id) as follows, when trapping exits:
unlink(Id),
receive
@@ -27,13 +35,10 @@
true
end
- Note:
- Before Erlang/OTP R11B (ERTS 5.5) unlink/1 behaved
- completely asynchronously, that is, the link was active until
- the "unlink signal" reached the linked entity. This had an
- undesirable effect, as you could never know when you were
- guaranteed not to be effected by the link.
+ The link removal is performed asynchronously. If such a link does
+ not exist, nothing is done. A detailed description of the link
+ protocol can be found in the Distribution Protocol chapter of
+ the ERTS User's Guide.
- The current behavior can be viewed as two combined operations:
- asynchronously send an "unlink signal" to the linked entity
- and ignore any future results of the link.
+ Failure: badarg if Id does not identify a process or a node
+ local port.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unregister_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unregister_1_func.txt
index 4e25c97d02..3697bac815 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unregister_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_unregister_1_func.txt
@@ -1,12 +1,17 @@
-spec unregister(RegName) -> true when RegName :: atom().
- Removes the registered name RegName associated with a process
- identifier or a port identifier, for example:
+ Removes the registered name RegName associated with a process
+ identifier or a port identifier from the name registry. For
+ example:
> unregister(db).
true
+ Keep in mind that you can still receive signals associated with
+ the registered name after it has been unregistered as the sender
+ may have looked up the name before sending to it.
+
Users are advised not to unregister system processes.
Failure: badarg if RegName is not a registered name.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_whereis_1_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_whereis_1_func.txt
index 757ec8a7e1..6a432f954c 100644
--- a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_whereis_1_func.txt
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_whereis_1_func.txt
@@ -2,9 +2,9 @@
-spec whereis(RegName) -> pid() | port() | undefined
 when RegName :: atom().
- Returns the process identifier or port identifier with the
- registered name RegName. Returns undefined if the name is not
- registered. Example:
+ Returns the process identifier or port identifier with the 
+ registered name RegName from the name registry. Returns 
+ undefined if the name is not registered. Example:
> whereis(db).
<0.43.0>
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_xor_2_func.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_xor_2_func.txt
new file mode 100644
index 0000000000..3a833a1dfb
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_erlang_xor_2_func.txt
@@ -0,0 +1,5 @@
+
+  'xor'/2
+
+ The documentation for 'xor'/2 is hidden. This probably means
+ that it is internal and not to be used by other applications.
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE.txt
new file mode 100644
index 0000000000..3c3f49196d
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE.txt
@@ -0,0 +1,4 @@
+
+ shell_docs_SUITE
+
+ There is no documentation for shell_docs_SUITE
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_cb.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_cb.txt
new file mode 100644
index 0000000000..917fb3b6a7
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_cb.txt
@@ -0,0 +1,3 @@
+ shell_docs_SUITE
+
+There are no callbacks in this module
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_type.txt b/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_type.txt
new file mode 100644
index 0000000000..ad4b506280
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/unknown_shell_docs_SUITE_type.txt
@@ -0,0 +1,3 @@
+ shell_docs_SUITE
+
+There are no types in this module
diff --git a/lib/stdlib/test/shell_docs_SUITE_data/user_drv.docs_v1 b/lib/stdlib/test/shell_docs_SUITE_data/user_drv.docs_v1
new file mode 100644
index 0000000000..43ca532712
--- /dev/null
+++ b/lib/stdlib/test/shell_docs_SUITE_data/user_drv.docs_v1
@@ -0,0 +1 @@
+{docs_v1,[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],erlang,<<97,112,112,108,105,99,97,116,105,111,110,47,101,114,108,97,110,103,43,104,116,109,108>>,hidden,#{otp_doc_vsn => {1,0,0}},[{{function,interfaces,1},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<105,110,116,101,114,102,97,99,101,115,47,49>>],hidden,#{}},{{function,server,2},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<115,101,114,118,101,114,47,50>>],hidden,#{}},{{function,server,3},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<115,101,114,118,101,114,47,51>>],hidden,#{}},{{function,start,0},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<115,116,97,114,116,47,48>>],hidden,#{}},{{function,start,1},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<115,116,97,114,116,47,49>>],hidden,#{}},{{function,start,2},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<115,116,97,114,116,47,50>>],hidden,#{}},{{function,start,3},[{file,[117,115,101,114,95,100,114,118,46,101,114,108]},{location,0}],[<<115,116,97,114,116,47,51>>],hidden,#{}}]}. \ No newline at end of file
diff --git a/lib/stdlib/test/stdlib_SUITE.erl b/lib/stdlib/test/stdlib_SUITE.erl
index 7e05723036..938b6ba3e3 100644
--- a/lib/stdlib/test/stdlib_SUITE.erl
+++ b/lib/stdlib/test/stdlib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
init_per_testcase/2, end_per_testcase/2,
app_test/1, appup_test/1, assert_test/1]).
--compile(r21).
+-compile(r22).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -46,7 +46,19 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
+init_per_testcase(appup_test, Config) ->
+ %% We check if the test results were released using a version
+ %% of Erlang/OTP that was a tagged version or not. On a non-tagged
+ %% version this testcase most likely will fail.
+ case file:read_file(
+ filename:join(
+ proplists:get_value(data_dir,Config), "otp_version_tickets")) of
+ {ok,<<"DEVELOPMENT",_/binary>>} ->
+ {skip, "This is a development version, test might fail "
+ "because of incorrect version numbers"};
+ {ok,S} ->
+ Config
+ end;
init_per_testcase(_Case, Config) ->
Config.
end_per_testcase(_Case, _Config) ->
@@ -65,8 +77,6 @@ app_test(Config) when is_list(Config) ->
appup_test(_Config) ->
appup_tests(stdlib,create_test_vsns(stdlib)).
-appup_tests(_App,{[],[]}) ->
- {skip,"no previous releases available"};
appup_tests(App,{OkVsns0,NokVsns}) ->
application:load(App),
{_,_,Vsn} = lists:keyfind(App,1,application:loaded_applications()),
@@ -79,8 +89,7 @@ appup_tests(App,{OkVsns0,NokVsns}) ->
OkVsns0 ->
OkVsns0;
Ok ->
- ct:log("Current version, ~p, is same as in previous release.~n"
- "Removing this from the list of ok versions.",
+ ct:log("Removed current version ~p from the list of ok versions to test.",
[Vsn]),
Ok
end,
@@ -95,57 +104,46 @@ appup_tests(App,{OkVsns0,NokVsns}) ->
ok.
create_test_vsns(App) ->
- ThisMajor = erlang:system_info(otp_release),
- FirstMajor = previous_major(ThisMajor),
- SecondMajor = previous_major(previous_major(FirstMajor)),
- Ok = app_vsn(App,[ThisMajor,FirstMajor]),
- Nok0 = app_vsn(App,[SecondMajor]),
+ S = otp_vsns:read_state(),
+ Rel = list_to_integer(erlang:system_info(otp_release)),
+ AppStr = atom_to_list(App),
+ Ok = ok_app_vsns(S, Rel, AppStr),
+ Nok0 = nok_app_vsns(S, Rel, AppStr, hd(Ok)),
Nok = case Ok of
- [Ok1|_] ->
- [Ok1 ++ ",1" | Nok0]; % illegal
- _ ->
- Nok0
- end,
- {Ok,Nok}.
-
-previous_major("17") ->
- "r16b";
-previous_major("r16b") ->
- "r15b";
-previous_major(Rel) ->
- integer_to_list(list_to_integer(Rel)-1).
-
-app_vsn(App,[R|Rs]) ->
- OldRel =
- case test_server:is_release_available(R) of
- true ->
- {release,R};
- false ->
- case ct:get_config({otp_releases,list_to_atom(R)}) of
- undefined ->
- false;
- Prog0 ->
- case os:find_executable(Prog0) of
- false ->
- false;
- Prog ->
- {prog,Prog}
- end
- end
- end,
- case OldRel of
- false ->
- app_vsn(App,Rs);
- _ ->
- {ok,N} = test_server:start_node(prevrel,peer,[{erl,[OldRel]}]),
- _ = rpc:call(N,application,load,[App]),
- As = rpc:call(N,application,loaded_applications,[]),
- {_,_,V} = lists:keyfind(App,1,As),
- test_server:stop_node(N),
- [V|app_vsn(App,Rs)]
- end;
-app_vsn(_App,[]) ->
- [].
+ [Ok1|_] ->
+ [Ok1 ++ ",1" | Nok0]; % illegal
+ _ ->
+ Nok0
+ end,
+ {Ok, Nok}.
+
+ok_app_vsns(S, Rel, AppStr) ->
+ AppVsns0 = get_rel_app_vsns(S, Rel-2, AppStr),
+ AppVsns1 = get_rel_app_vsns(S, Rel-1, AppStr),
+ AppVsns2 = try
+ get_rel_app_vsns(S, Rel, AppStr)
+ catch
+ _:_ -> []
+ end,
+ lists:usort(AppVsns2 ++ AppVsns1 ++ AppVsns0).
+
+nok_app_vsns(S, Rel, AppStr, EarliestOkVsn) ->
+ AppVsns0 = get_rel_app_vsns(S, Rel-4, AppStr),
+ AppVsns1 = get_rel_app_vsns(S, Rel-3, AppStr),
+ %% Earliest OK version may exist in not OK versions
+ %% as well if there were no application version bump
+ %% between two releases, so we need to remove it
+ %% if that is the case...
+ lists:usort(AppVsns1 ++ AppVsns0) -- EarliestOkVsn.
+
+get_rel_app_vsns(S, Rel, App) ->
+ RelStr = integer_to_list(Rel),
+ OtpVsns = otp_vsns:branch_vsns(S, "maint-"++RelStr),
+ lists:map(fun (OtpVsn) ->
+ AppVsn = otp_vsns:app_vsn(S, OtpVsn, App),
+ [_, Vsn] = string:lexemes(AppVsn, "-"),
+ Vsn
+ end, OtpVsns).
check_appup([Vsn|Vsns],Instrs,Expected) ->
case systools_relup:appup_search_for_version(Vsn, Instrs) of
diff --git a/lib/stdlib/test/stdlib_bench_SUITE.erl b/lib/stdlib/test/stdlib_bench_SUITE.erl
index 81764a5913..4ccbdb9b57 100644
--- a/lib/stdlib/test/stdlib_bench_SUITE.erl
+++ b/lib/stdlib/test/stdlib_bench_SUITE.erl
@@ -52,7 +52,7 @@ groups() ->
encode_list, encode_list_to_string,
mime_binary_decode, mime_binary_decode_to_string,
mime_list_decode, mime_list_decode_to_string]},
- {io, [{repeat, 5}], [double_random_to_list]},
+ {io, [{repeat, 5}], [double_random_to_list, double_random_to_list_array]},
{gen_server, [{repeat,5}], cases(gen_server)},
{gen_statem, [{repeat,3}], cases(gen_statem)},
{gen_server_comparison, [],
@@ -283,14 +283,17 @@ mbb(N, Acc) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(MAX_DOUBLE, (1 bsl 62) - 1).
--define(DOUBLE_SAMPLE, 10000).
+-define(DOUBLE_SAMPLE, 100000).
-define(SMALL_DIGITS, 6).
double_random_to_list(_Config) ->
- comment(test_double(io_lib_format, fwrite_g, 0)).
+ comment(test_double(0)).
+
+double_random_to_list_array(_Config) ->
+ comment(test_double_array(0)).
double_small_digit_to_list(_Config) ->
- comment(test_double(io_lib_format, fwrite_g, ?SMALL_DIGITS)).
+ comment(test_double(?SMALL_DIGITS)).
double(0) ->
Int = rand:uniform(?MAX_DOUBLE),
@@ -319,17 +322,34 @@ exp10(Acc, 0) ->
exp10(Acc, X) ->
exp10(Acc, X - 1).
-test_double(Mod, Fun, SmallDigits) ->
- test_double(?DOUBLE_SAMPLE, Mod, Fun, SmallDigits).
-test_double(Iter, Mod, Fun, SmallDigits) ->
- F = fun() -> loop_double(Iter, Mod, Fun, SmallDigits) end,
+test_double(Samples) when is_list(Samples) ->
+ F = fun() -> loop_double(Samples) end,
{Time, ok} = timer:tc(fun() -> lspawn(F) end),
- report_mfa(Iter, Time, Mod).
+ report_mfa(?DOUBLE_SAMPLE, Time, io_lib_format);
+test_double(SmallDigits) when is_integer(SmallDigits) ->
+ rand:seed(exsplus, {1201,855653,380975}),
+ Samples = [double(SmallDigits) || _ <- lists:seq(1, ?DOUBLE_SAMPLE)],
+ test_double(Samples).
+
+loop_double([]) -> garbage_collect(), ok;
+loop_double([Sample | Rest]) ->
+ _ = io_lib_format:fwrite_g(Sample),
+ loop_double(Rest).
+
+test_double_array(SmallDigits) when is_integer(SmallDigits) ->
+ rand:seed(exsplus, {1201,855653,380975}),
+ Samples = [double(SmallDigits) || _ <- lists:seq(1, ?DOUBLE_SAMPLE)],
+ Samples_array = array:from_list(Samples),
+ test_double_array(?DOUBLE_SAMPLE - 1, Samples_array).
+test_double_array(Iter, Samples_array) ->
+ F = fun() -> loop_double_array(Iter, Samples_array) end,
+ {Time, ok} = timer:tc(fun() -> lspawn(F) end),
+ report_mfa(?DOUBLE_SAMPLE, Time, io_lib_format).
-loop_double(0, _M, _F, _SmallDigits) -> garbage_collect(), ok;
-loop_double(N, M, F, SmallDigits) ->
- _ = apply(M, F, [double(SmallDigits)]),
- loop_double(N - 1, M, F, SmallDigits).
+loop_double_array(0, _Samples_array) -> garbage_collect(), ok;
+loop_double_array(Iter, Samples_array) ->
+ _ = io_lib_format:fwrite_g(array:get(Iter, Samples_array)),
+ loop_double_array(Iter - 1, Samples_array).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index 4475d7c06e..c6bba4be8b 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2019. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -643,21 +643,33 @@ cd_gc(_) ->
[] = string:next_codepoint(""),
[] = string:next_codepoint(<<>>),
[] = string:next_codepoint([<<>>]),
+ [$a|""] = string:next_codepoint("a"),
+ [$a|<<>>] = string:next_codepoint(<<"a">>),
+ [$a|[<<>>,$b]] = string:next_codepoint([<<"a">>,$b]),
"abcd" = string:next_codepoint("abcd"),
- [$e,778] = string:next_codepoint([$e,778]),
+ [$e|[778]] = string:next_codepoint([$e,778]),
[$e|<<204,138>>] = string:next_codepoint(<<$e,778/utf8>>),
- [778|_] = string:next_codepoint(tl(string:next_codepoint(<<$e,778/utf8>>))),
+ [778|<<>>] = string:next_codepoint(tl(string:next_codepoint(<<$e,778/utf8>>))),
[0|<<128,1>>] = string:next_codepoint(<<0,128,1>>),
{error,<<128,1>>} = string:next_codepoint(<<128,1>>),
+ [128021|<<>>] = string:next_codepoint(<<128021/utf8>>), %% Dog
+ [128021|<<8205/utf8>>] = string:next_codepoint(<<128021/utf8,8205/utf8>>), %% Dog + ZWJ
+ [128021|<<8205/utf8,129466/utf8>>] = string:next_codepoint(<<128021/utf8,8205/utf8,129466/utf8>>), %% Dog + ZWJ + Service vest == Service dog
[] = string:next_grapheme(""),
[] = string:next_grapheme(<<>>),
[] = string:next_grapheme([<<>>]),
+ [$a|""] = string:next_grapheme("a"),
+ [$a|<<>>] = string:next_grapheme(<<"a">>),
+ [$a|[<<>>,$b]] = string:next_grapheme([<<"a">>,$b]),
"abcd" = string:next_grapheme("abcd"),
- [[$e,778]] = string:next_grapheme([$e,778]),
- [[$e,778]] = string:next_grapheme(<<$e,778/utf8>>),
+ [[$e,778]|""] = string:next_grapheme([$e,778]),
+ [[$e,778]|<<>>] = string:next_grapheme(<<$e,778/utf8>>),
[0|<<128,1>>] = string:next_grapheme(<<0,128,1>>),
{error,<<128,1>>} = string:next_grapheme(<<128,1>>),
+ [128021|<<>>] = string:next_grapheme(<<128021/utf8>>), %% Dog
+ [[128021,8205]|<<>>] = string:next_grapheme(<<128021/utf8,8205/utf8>>), %% Dog + ZWJ
+ [[128021,8205,129466]|<<>>] = string:next_grapheme(<<128021/utf8,8205/utf8,129466/utf8>>), %% Dog + ZWJ + Service vest == Service dog
ok.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index a52c5b1b44..78d7e7d7bc 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -904,7 +904,7 @@ child_specs_map(Config) when is_list(Config) ->
B7 = CS0#{type => wrker},
B8 = CS0#{modules => dy},
B9 = CS0#{modules => [1,2,3]},
- B10 = CS0#{significant => maybe},
+ B10 = CS0#{significant => 'maybe'},
{error, missing_id} = supervisor:start_child(sup_test, B1),
{error, missing_start} = supervisor:start_child(sup_test, B2),
@@ -932,7 +932,7 @@ child_specs_map(Config) when is_list(Config) ->
{error, {invalid_modules,dy}} = supervisor:check_childspecs([B8]),
{error, {invalid_module, 1}} =
supervisor:check_childspecs([B9]),
- {error, {invalid_significant, maybe}} =
+ {error, {invalid_significant, 'maybe'}} =
supervisor:check_childspecs([B10]),
CSFilter = fun (CS) -> maps:filter(fun (_, V) -> V =/= undefined end, CS) end,
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index d055eb88cc..294741574c 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
create_long_names/1, bad_tar/1, errors/1, extract_from_binary/1,
extract_from_binary_compressed/1, extract_filtered/1,
extract_from_open_file/1, symlinks/1, open_add_close/1, cooked_compressed/1,
- memory/1,unicode/1,read_other_implementations/1,
+ memory/1,unicode/1,read_other_implementations/1,bsdtgz/1,
sparse/1, init/1, leading_slash/1, dotdot/1,
roundtrip_metadata/1, apply_file_info_opts/1,
incompatible_options/1]).
@@ -42,7 +42,7 @@ all() ->
extract_from_binary_compressed, extract_from_open_file,
extract_filtered,
symlinks, open_add_close, cooked_compressed, memory, unicode,
- read_other_implementations,
+ read_other_implementations, bsdtgz,
sparse,init,leading_slash,dotdot,roundtrip_metadata,
apply_file_info_opts,incompatible_options].
@@ -113,8 +113,8 @@ borderline_test(Size, TempDir, IsUstar) ->
Name = filename:join(TempDir, Prefix++SizeList),
%% Create a file and archive it.
- X0 = erlang:monotonic_time(),
- ok = file:write_file(Name, random_byte_list(X0, Size)),
+ RandomBytes = rand:bytes(Size),
+ ok = file:write_file(Name, RandomBytes),
ok = erl_tar:create(Archive, [Name]),
ok = file:delete(Name),
@@ -125,7 +125,7 @@ borderline_test(Size, TempDir, IsUstar) ->
%% Verify contents of extracted file.
{ok, Bin} = file:read_file(Name),
- true = match_byte_list(X0, binary_to_list(Bin)),
+ RandomBytes = Bin,
%% Verify that Unix tar can read it.
case IsUstar of
@@ -199,34 +199,6 @@ make_cmd(Cmd) ->
{unix, _} -> lists:concat(["sh -c '", Cmd, "'"])
end.
-%% Verifies a random byte list.
-
-match_byte_list(X0, [Byte|Rest]) ->
- X = next_random(X0),
- case (X bsr 26) band 16#ff of
- Byte -> match_byte_list(X, Rest);
- _ -> false
- end;
-match_byte_list(_, []) ->
- true.
-
-%% Generates a random byte list.
-
-random_byte_list(X0, Count) ->
- random_byte_list(X0, Count, []).
-
-random_byte_list(X0, Count, Result) when Count > 0->
- X = next_random(X0),
- random_byte_list(X, Count-1, [(X bsr 26) band 16#ff|Result]);
-random_byte_list(_X, 0, Result) ->
- lists:reverse(Result).
-
-%% This RNG is from line 21 on page 102 in Knuth: The Art of Computer Programming,
-%% Volume II, Seminumerical Algorithms.
-
-next_random(X) ->
- (X*17059465+1) band 16#fffffffff.
-
%% Test the 'atomic' operations: create/extract/table, on compressed
%% and uncompressed archives.
%% Also test the 'cooked' option.
@@ -891,6 +863,17 @@ do_read_other_implementations([File|Rest], DataDir) ->
{ok, _} = erl_tar:extract(Full, [memory]),
do_read_other_implementations(Rest, DataDir).
+%% test block padding with compressed tar from bsdtar or tape
+bsdtgz(Config) when is_list(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ File = "example_pad.tgz",
+ Full = filename:join(DataDir, File),
+ io:format("~nTrying ~s", [File]),
+ Table = ["autofs.conf","rpc"],
+ {ok, Table} = erl_tar:table(Full, [compressed]),
+ {ok, Bin} = file:read_file(Full),
+ {ok, Table} = erl_tar:table({binary, Bin}, [compressed]),
+ verify_ports(Config).
%% Test handling of sparse files
sparse(Config) when is_list(Config) ->
@@ -914,23 +897,20 @@ do_sparse([Name|Rest], DataDir, PrivDir) ->
%% Test filenames with characters outside the US ASCII range.
unicode(Config) when is_list(Config) ->
- run_unicode_node(Config, "+fnu"),
+ run_unicode_node(Config, ["+fnu"]),
case has_transparent_naming() of
true ->
- run_unicode_node(Config, "+fnl");
+ run_unicode_node(Config, ["+fnl"]);
false ->
ok
end.
-run_unicode_node(Config, Option) ->
+run_unicode_node(Config, Args) ->
PrivDir = proplists:get_value(priv_dir, Config),
- Pa = filename:dirname(code:which(?MODULE)),
- Args = Option ++ " -pa "++Pa,
- io:format("~s\n", [Args]),
- Node = start_node(unicode, Args),
+ {ok, Peer, Node} = ?CT_PEER(Args),
ok = rpc:call(Node, erlang, apply,
[fun() -> do_unicode(PrivDir) end,[]]),
- true = test_server:stop_node(Node),
+ peer:stop(Peer),
ok.
has_transparent_naming() ->
@@ -942,21 +922,25 @@ has_transparent_naming() ->
do_unicode(PrivDir) ->
ok = file:set_cwd(PrivDir),
- ok = file:make_dir("unicöde"),
-
- Names = lists:sort(unicode_create_files()),
- Tar = "unicöde.tar",
- ok = erl_tar:create(Tar, ["unicöde"], []),
-
- %% Unicode filenames require PAX format.
- false = is_ustar(Tar),
- {ok,Names0} = erl_tar:table(Tar, []),
- Names = lists:sort(Names0),
- _ = [ok = file:delete(Name) || Name <- Names],
- ok = erl_tar:extract(Tar),
- _ = [{ok,_} = file:read_file(Name) || Name <- Names],
- _ = [ok = file:delete(Name) || Name <- Names],
- ok = file:del_dir("unicöde"),
+ case file:make_dir("unicöde") of
+ ok ->
+ Names = lists:sort(unicode_create_files()),
+ Tar = "unicöde.tar",
+ ok = erl_tar:create(Tar, ["unicöde"], []),
+
+ %% Unicode filenames require PAX format.
+ false = is_ustar(Tar),
+ {ok,Names0} = erl_tar:table(Tar, []),
+ Names = lists:sort(Names0),
+ _ = [ok = file:delete(Name) || Name <- Names],
+ ok = erl_tar:extract(Tar),
+ _ = [{ok,_} = file:read_file(Name) || Name <- Names],
+ _ = [ok = file:delete(Name) || Name <- Names],
+ ok = file:del_dir("unicöde");
+ {error,eilseq} ->
+ %% The FS (eg zfs) does not support transparent naming
+ ok
+ end,
ok.
unicode_create_files() ->
@@ -1014,7 +998,7 @@ roundtrip_metadata(Config) ->
do_roundtrip_metadata(Dir, File) ->
Tar = filename:join(Dir, atom_to_list(?FUNCTION_NAME)++".tar"),
- BeamFile = code:which(compile),
+ BeamFile = code:which(?MODULE),
{ok,Fd} = erl_tar:open(Tar, [write]),
ok = erl_tar:add(Fd, BeamFile, File, []),
ok = erl_tar:close(Fd),
@@ -1131,17 +1115,6 @@ make_temp_dir(Base, I) ->
{error,eexist} -> make_temp_dir(Base, I+1)
end.
-start_node(Name, Args) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
- ct:log("Trying to start ~w@~s~n", [Name,Host]),
- case test_server:start_node(Name, peer, [{args,Args}]) of
- {error,Reason} ->
- ct:fail(Reason);
- {ok,Node} ->
- ct:log("Node ~p started~n", [Node]),
- Node
- end.
-
%% Test that the given tar file is a plain USTAR archive,
%% without any PAX extensions.
is_ustar(File) ->
diff --git a/lib/stdlib/test/tar_SUITE_data/example_pad.tgz b/lib/stdlib/test/tar_SUITE_data/example_pad.tgz
new file mode 100644
index 0000000000..508ab1b461
--- /dev/null
+++ b/lib/stdlib/test/tar_SUITE_data/example_pad.tgz
Binary files differ
diff --git a/lib/stdlib/test/timer_SUITE.erl b/lib/stdlib/test/timer_SUITE.erl
index 9062cbae80..d6211acf9d 100644
--- a/lib/stdlib/test/timer_SUITE.erl
+++ b/lib/stdlib/test/timer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -132,7 +132,7 @@ big_loop(C, N, Pids) ->
%%Pids2=Pids1,
%% wait a little while
- timer:sleep(rand:uniform(200)*3),
+ ok = timer:sleep(rand:uniform(200)*3),
%% spawn zero, one or two nrev to get some load ;-/
Pids3 = start_nrev(Pids2, rand:uniform(100)),
@@ -168,7 +168,7 @@ s_a_t(C, TimeOut) ->
a_t(C, TimeOut) ->
start_watchdog(self(), TimeOut),
Start = system_time(),
- timer:send_after(TimeOut, self(), now),
+ {ok, _} = timer:send_after(TimeOut, self(), now),
receive
now ->
Stop = system_time(),
@@ -202,12 +202,12 @@ i_wait(Start, Prev, Times, TimeOut, Times, Ref, C) ->
interval ->
Now = system_time(),
report_interval(C, {final,Times}, Start, Prev, Now, TimeOut),
- timer:cancel(Ref),
+ {ok, cancel} = timer:cancel(Ref),
exit(done);
watchdog ->
Now = system_time(),
report_interval(C, {final,Times}, Start, Prev, Now, TimeOut),
- timer:cancel(Ref),
+ {ok, cancel} = timer:cancel(Ref),
ok = io:format("Internal watchdog timeout (i), not good!!~n",
[]),
exit(done)
@@ -358,7 +358,7 @@ system_time() ->
%% ------------------------------------------------------- %%
do_nrev(Sleep) ->
- timer:sleep(Sleep),
+ ok = timer:sleep(Sleep),
test(1000,"abcdefghijklmnopqrstuvxyz1234"),
exit(done).
diff --git a/lib/stdlib/test/timer_simple_SUITE.erl b/lib/stdlib/test/timer_simple_SUITE.erl
index 1a582ae95a..98a8dd408d 100644
--- a/lib/stdlib/test/timer_simple_SUITE.erl
+++ b/lib/stdlib/test/timer_simple_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,54 +21,187 @@
-module(timer_simple_SUITE).
+%% This test suite matches on opaque tref() return values from the *_after
+%% and *_interval functions, namely {instant, _}, {send_local, _}, {once, _}
+%% and {interval, _}.
+%% If the implementation changes, the test suite has to be changed accordingly.
+
%% external
-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,
- apply_after/1,
- send_after1/1,
- send_after2/1,
- send_after3/1,
- exit_after1/1,
- exit_after2/1,
- kill_after1/1,
- kill_after2/1,
- apply_interval/1,
- send_interval1/1,
- send_interval2/1,
- send_interval3/1,
- send_interval4/1,
- cancel1/1,
- cancel2/1,
- tc/1,
- unique_refs/1,
- timer_perf/1]).
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2,
+ apply_after1/1,
+ apply_after2/1,
+ apply_after3/1,
+ apply_after4/1,
+ apply_after_invalid_args/1,
+ send_after1/1,
+ send_after2/1,
+ send_after3/1,
+ send_after4/1,
+ send_after5/1,
+ send_after6/1,
+ send_after7/1,
+ send_after_invalid_args/1,
+ exit_after1/1,
+ exit_after2/1,
+ exit_after3/1,
+ exit_after4/1,
+ kill_after1/1,
+ kill_after2/1,
+ kill_after3/1,
+ apply_interval1/1,
+ apply_interval_invalid_args/1,
+ send_interval1/1,
+ send_interval2/1,
+ send_interval3/1,
+ send_interval4/1,
+ send_interval5/1,
+ send_interval_invalid_args/1,
+ cancel1/1,
+ cancel2/1,
+ cancel3/1,
+ cancel4/1,
+ cancel5/1,
+ cancel6/1,
+ cancel_invalid_args/1,
+ sleep1/1,
+ sleep2/1,
+ tc/1,
+ unexpected1/1,
+ unexpected2/1,
+ unexpected3/1,
+ nonexistent1/1,
+ nonexistent2/1,
+ timer_perf/1]).
%% internal
-export([forever/0,
- do_nrev/2,
- send/2,
- timer/4,
- timer/5]).
+ do_nrev/2,
+ send/2,
+ timer/4,
+ timer/5]).
-include_lib("common_test/include/ct.hrl").
--define(MAXREF, (1 bsl 18)).
--define(REFMARG, 30).
-
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,10}}].
-all() ->
- [apply_after, send_after1, send_after2, send_after3,
- exit_after1, exit_after2, kill_after1, kill_after2,
- apply_interval, send_interval1, send_interval2,
- send_interval3, send_interval4, cancel1, cancel2, tc,
- unique_refs, timer_perf].
+all() ->
+ [
+ {group, apply_after},
+ {group, send_after},
+ {group, exit_after},
+ {group, kill_after},
+ {group, apply_interval},
+ {group, send_interval},
+ {group, cancel},
+ {group, sleep},
+ {group, misc}
+ ].
groups() ->
- [].
+ [
+ {
+ apply_after,
+ [],
+ [
+ apply_after1,
+ apply_after2,
+ apply_after3,
+ apply_after4,
+ apply_after_invalid_args
+ ]
+ },
+ {
+ send_after,
+ [],
+ [
+ send_after1,
+ send_after2,
+ send_after3,
+ send_after4,
+ send_after5,
+ send_after6,
+ send_after7,
+ send_after_invalid_args
+ ]
+ },
+ {
+ exit_after,
+ [],
+ [
+ exit_after1,
+ exit_after2,
+ exit_after3,
+ exit_after4
+ ]
+ },
+ {
+ kill_after,
+ [],
+ [
+ kill_after1,
+ kill_after2,
+ kill_after3
+ ]
+ },
+ {
+ apply_interval,
+ [],
+ [
+ apply_interval1,
+ apply_interval_invalid_args
+ ]
+ },
+ {
+ send_interval,
+ [],
+ [
+ send_interval1,
+ send_interval2,
+ send_interval3,
+ send_interval4,
+ send_interval5,
+ send_interval_invalid_args
+ ]
+ },
+ {
+ cancel,
+ [],
+ [
+ cancel1,
+ cancel2,
+ cancel3,
+ cancel4,
+ cancel5,
+ cancel6,
+ cancel_invalid_args
+ ]
+ },
+ {
+ sleep,
+ [],
+ [
+ sleep1,
+ sleep2
+ ]
+ },
+ {
+ misc,
+ [],
+ [
+ tc,
+ unexpected1,
+ unexpected2,
+ unexpected3,
+ nonexistent1,
+ nonexistent2,
+ timer_perf
+ ]
+ }
+ ].
init_per_suite(Config) ->
Config.
@@ -84,57 +217,162 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_, Config) when is_list(Config) ->
- timer:start(),
+ ok = timer:start(),
Config.
%% Testing timer interface!!
-%% Test of apply_after, with sending of message.
-apply_after(Config) when is_list(Config) ->
- timer:apply_after(500, ?MODULE, send, [self(), ok_apply]),
- ok = get_mess(1000, ok_apply).
+%% Test of apply_after with time = 0, with sending of message.
+apply_after1(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ {ok, {instant, _}} = timer:apply_after(0, ?MODULE, send, [self(), Msg]),
+ ok = get_mess(1000, Msg).
+
+%% Test of apply_after with time = 500, with sending of message.
+apply_after2(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ {ok, {once, _}} = timer:apply_after(500, ?MODULE, send, [self(), Msg]),
+ ok = get_mess(1000, Msg).
+
+%% Test that a request starts the timer server if it is not running.
+apply_after3(Config) when is_list(Config) ->
+ ok = supervisor:terminate_child(kernel_sup, timer_server),
+ Msg = make_ref(),
+ timer:apply_after(100, erlang, send, [self(), Msg]),
+ ok = get_mess(500, Msg),
+ {timer_server, Pid, worker, [timer]} = lists:keyfind(timer_server, 1, supervisor:which_children(kernel_sup)),
+ true = is_pid(Pid).
+
+%% Test that a request starts the timer server if it is not running.
+apply_after4(Config) when is_list(Config) ->
+ ok = supervisor:terminate_child(kernel_sup, timer_server),
+ ok = supervisor:delete_child(kernel_sup, timer_server),
+ Msg = make_ref(),
+ timer:apply_after(100, erlang, send, [self(), Msg]),
+ ok = get_mess(500, Msg),
+ {timer_server, Pid, worker, [timer]} = lists:keyfind(timer_server, 1, supervisor:which_children(kernel_sup)),
+ true = is_pid(Pid).
+
+%% Test that apply_after rejects invalid arguments.
+apply_after_invalid_args(Config) when is_list(Config) ->
+ {error, badarg} = timer:apply_after(-1, foo, bar, []),
+ {error, badarg} = timer:apply_after(0, "foo", bar, []),
+ {error, badarg} = timer:apply_after(0, foo, "bar", []),
+ {error, badarg} = timer:apply_after(0, foo, bar, baz),
+ ok.
%% Test of send_after with time = 0.
send_after1(Config) when is_list(Config) ->
- timer:send_after(0, ok_send1),
- ok = get_mess(1000, ok_send1).
+ Msg = make_ref(),
+ {ok, {instant, _}} = timer:send_after(0, Msg),
+ ok = get_mess(1000, Msg).
-%% Test of send_after with time = 500.
+%% Test of send_after with time = 0 using a registered name.
send_after2(Config) when is_list(Config) ->
- timer:send_after(500, self(), ok_send2),
- ok = get_mess(2000, ok_send2).
+ Msg = make_ref(),
+ Name = register_name(self()),
+ {ok, {instant, _}} = timer:send_after(0, Name, Msg),
+ ok = get_mess(1000, Msg),
+ unregister(Name).
+
+%% Test of send_after with time = 0 using a registered name
+%% and node.
+send_after3(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ Name = register_name(self()),
+ {ok, {instant, _}} = timer:send_after(0, {Name, node()}, Msg),
+ ok = get_mess(1000, Msg),
+ unregister(Name).
+
+%% Test of send_after with time = 500.
+send_after4(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ {ok, {send_local, _}} = timer:send_after(500, self(), Msg),
+ ok = get_mess(2000, Msg).
%% Test of send_after with time = 500, with receiver a registered
%% process. [OTP-2735]
-send_after3(Config) when is_list(Config) ->
- Name = list_to_atom(pid_to_list(self())),
+send_after5(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ Name = register_name(self()),
+ {ok, {once, _}} = timer:send_after(500, Name, Msg),
+ ok = get_mess(2000, Msg),
+ unregister(Name).
+
+%% Test of send_after with time = 500 using a registered process
+%% and node.
+send_after6(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ Name = register_name(self()),
+ {ok, {once, _}} = timer:send_after(500, {Name, node()}, Msg),
+ ok = get_mess(2000, Msg),
+ unregister(Name).
+
+%% Test that send_after works if the destination is a registered
+%% name which gets registered after the timer is started.
+send_after7(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ Name = make_name(),
+ {ok, {once, _}} = timer:send_after(500, Name, Msg),
register(Name, self()),
- timer:send_after(500, Name, ok_send3),
- ok = get_mess(2000, ok_send3),
+ ok = get_mess(2000, Msg),
unregister(Name).
+%% Test that send_after rejects invalid arguments.
+send_after_invalid_args(Config) when is_list(Config) ->
+ {error, badarg} = timer:send_after(-1, test),
+ {error, badarg} = timer:send_after(-1, self(), test),
+ {error, badarg} = timer:send_after(-1, ?MODULE, test),
+ {error, badarg} = timer:send_after(0, "", test),
+ ok.
+
%% Test of exit_after with time = 1000.
exit_after1(Config) when is_list(Config) ->
+ Msg = make_ref(),
process_flag(trap_exit, true),
Pid = spawn_link(?MODULE, forever, []),
- timer:exit_after(1000, Pid, exit_test1),
- ok = get_mess(5000, {'EXIT', Pid, exit_test1}).
+ {ok, {once, _}} = timer:exit_after(1000, Pid, Msg),
+ ok = get_mess(5000, {'EXIT', Pid, Msg}).
%% Test of exit_after with time = 1000. The process to exit is the
%% name of a registered process. [OTP-2735]
exit_after2(Config) when is_list(Config) ->
+ Msg = make_ref(),
process_flag(trap_exit, true),
Pid = spawn_link(?MODULE, forever, []),
- Name = list_to_atom(pid_to_list(Pid)),
- register(Name, Pid),
- timer:exit_after(1000, Name, exit_test2),
- ok = get_mess(2000, {'EXIT', Pid, exit_test2}).
+ Name = register_name(Pid),
+ {ok, {once, _}} = timer:exit_after(1000, Name, Msg),
+ ok = get_mess(2000, {'EXIT', Pid, Msg}).
+
+%% Test of exit_after for sending an exit to self.
+exit_after3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Msg = make_ref(),
+ Pid = spawn_link(
+ fun () ->
+ {ok, {once, _}} = timer:exit_after(1000, Msg),
+ forever()
+ end
+ ),
+ ok = get_mess(2000, {'EXIT', Pid, Msg}).
+
+%% Test that using exit_after to a non-existent
+%% process does not crash the timer server.
+exit_after4(Config) when is_list(Config) ->
+ Mon = monitor(process, timer_server),
+ timer:exit_after(0, make_name(), make_ref()),
+ receive
+ {'DOWN', Mon, process, _, _} ->
+ error(timer_server_crashed)
+ after 1000 ->
+ ok
+ end.
%% Test of kill_after with time = 1000.
kill_after1(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Pid = spawn_link(?MODULE, forever, []),
- timer:kill_after(1000, Pid),
+ {ok, {once, _}} = timer:kill_after(1000, Pid),
ok = get_mess(2000, {'EXIT', Pid, killed}).
%% Test of kill_after with time = 1000. The process to exit is the
@@ -142,111 +380,299 @@ kill_after1(Config) when is_list(Config) ->
kill_after2(Config) when is_list(Config) ->
process_flag(trap_exit, true),
Pid = spawn_link(?MODULE, forever, []),
- Name = list_to_atom(pid_to_list(Pid)),
- register(Name, Pid),
- timer:kill_after(1000, Name),
+ Name = register_name(Pid),
+ {ok, {once, _}} = timer:kill_after(1000, Name),
+ ok = get_mess(2000, {'EXIT', Pid, killed}).
+
+%% Test of kill_after for self-killing.
+kill_after3(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Pid = spawn_link(
+ fun () ->
+ {ok, {once, _}} = timer:kill_after(1000),
+ forever()
+ end
+ ),
ok = get_mess(2000, {'EXIT', Pid, killed}).
%% Test of apply_interval by sending messages. Receive
%% 3 messages, cancel the timer, and check that we do
%% not get any more messages.
-apply_interval(Config) when is_list(Config) ->
+apply_interval1(Config) when is_list(Config) ->
+ Msg = make_ref(),
{ok, Ref} = timer:apply_interval(1000, ?MODULE, send,
- [self(), apply_int]),
- ok = get_mess(1500, apply_int, 3),
- timer:cancel(Ref),
- nor = get_mess(1000, apply_int).
+ [self(), Msg]),
+ ok = get_mess(1500, Msg, 3),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(1000, Msg).
+
+%% Test that apply_interval rejects invalid arguments.
+apply_interval_invalid_args(Config) when is_list(Config) ->
+ {error, badarg} = timer:apply_interval(-1, foo, bar, []),
+ {error, badarg} = timer:apply_interval(0, "foo", bar, []),
+ {error, badarg} = timer:apply_interval(0, foo, "bar", []),
+ {error, badarg} = timer:apply_interval(0, foo, bar, baz),
+ ok.
%% Test of send_interval/2. Receive 5 messages, cancel the timer, and
%% check that we do not get any more messages.
send_interval1(Config) when is_list(Config) ->
- {ok, Ref} = timer:send_interval(1000, send_int),
- ok = get_mess(1500, send_int, 5),
- timer:cancel(Ref),
- nor = get_mess(1000, send_int). % We should receive only five
+ Msg = make_ref(),
+ {ok, Ref} = timer:send_interval(1000, Msg),
+ ok = get_mess(1500, Msg, 5),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(1000, Msg). % We should receive only five
%% Test of send_interval/3. Receive 2 messages, cancel the timer, and
%% check that we do not get any more messages.
send_interval2(Config) when is_list(Config) ->
- {ok, Ref} = timer:send_interval(1000, self(), send_int2),
- ok = get_mess(1500, send_int2, 2),
- timer:cancel(Ref),
- nor = get_mess(1000, send_int2). % We should receive only two
+ Msg = make_ref(),
+ {ok, Ref} = timer:send_interval(1000, self(), Msg),
+ ok = get_mess(1500, Msg, 2),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(1000, Msg). % We should receive only two
%% Test of send_interval/3. Receive 2 messages, cancel the timer, and
%% check that we do not get any more messages. The receiver is the
%% name of a registered process. [OTP-2735]
send_interval3(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- Name = list_to_atom(pid_to_list(self())),
- register(Name, self()),
- {ok, Ref} = timer:send_interval(1000, Name, send_int3),
- ok = get_mess(1500, send_int3, 2),
- timer:cancel(Ref),
- nor = get_mess(1000, send_int3), % We should receive only two
+ Msg = make_ref(),
+ Name = register_name(self()),
+ {ok, Ref} = timer:send_interval(1000, Name, Msg),
+ ok = get_mess(1500, Msg, 2),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(1000, Msg), % We should receive only two
+ unregister(Name).
+
+%% Test of send_interval/3 using a registered name and node.
+send_interval4(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Msg = make_ref(),
+ Name = register_name(self()),
+ {ok, Ref} = timer:send_interval(1000, {Name, node()}, Msg),
+ ok = get_mess(1500, Msg, 2),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(1000, Msg), % We should receive only two
unregister(Name).
%% Test that send interval stops sending msg when the receiving
%% process terminates.
-send_interval4(Config) when is_list(Config) ->
- timer:send_interval(500, one_time_only),
+send_interval5(Config) when is_list(Config) ->
+ Msg1 = make_ref(),
+ {ok, {interval, Ref}} = timer:send_interval(500, Msg1),
receive
- one_time_only -> ok
+ Msg1 -> ok
end,
- timer_server ! {'EXIT', self(), normal}, % Should remove the timer
- timer:send_after(600, send_intv_ok),
- send_intv_ok = receive
- Msg -> Msg
- end.
+ timer_server ! {'DOWN', Ref, process, self(), test},
+ Msg2 = make_ref(),
+ {ok, {send_local, _}} = timer:send_after(600, Msg2),
+ Msg2 = receive
+ TmpMsg -> TmpMsg
+ end.
+
+%% Test that send_interval rejects invalid arguments.
+send_interval_invalid_args(Config) when is_list(Config) ->
+ {error, badarg} = timer:send_interval(-1, test),
+ {error, badarg} = timer:send_interval(-1, self(), test),
+ {error, badarg} = timer:send_interval(-1, ?MODULE, test),
+ {error, badarg} = timer:send_interval(0, "", test),
+ ok.
-%% Test that we can cancel a timer.
+%% Test that we can cancel an instant timer
cancel1(Config) when is_list(Config) ->
- {ok, Ref} = timer:send_after(1000, this_should_be_canceled),
- timer:cancel(Ref),
- nor = get_mess(2000, this_should_be_canceled). % We should rec 0 msgs
+ Msg = make_ref(),
+ {ok, Ref} = timer:send_after(0, Msg),
+ {ok, cancel} = timer:cancel(Ref),
+ ok = get_mess(0, Msg). % We should rec 1 msg as it got sent immediately
-%% Test cancel/1 with bad argument.
+%% Test that we can cancel a send-once timer.
cancel2(Config) when is_list(Config) ->
- {error, badarg} = timer:cancel(no_reference).
+ Msg = make_ref(),
+ {ok, Ref} = timer:send_after(1000, Msg),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(2000, Msg). % We should rec 0 msgs
+
+%% Test that we can cancel an apply-once timer.
+cancel3(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ {ok, Ref} = timer:apply_after(1000, erlang, send, [self(), Msg]),
+ {ok, cancel} = timer:cancel(Ref),
+ nor = get_mess(2000, Msg).
+
+%% Test that we can cancel a send-interval timer.
+cancel4(Config) when is_list(Config) ->
+ Msg1 = make_ref(),
+ {ok, Ref} = timer:send_interval(500, Msg1),
+ receive
+ Msg1 -> ok
+ end,
+ {ok, cancel} = timer:cancel(Ref),
+ Msg2 = make_ref(),
+ {ok, {send_local, _}} = timer:send_after(600, Msg2),
+ Msg2 = receive
+ TmpMsg -> TmpMsg
+ end.
+
+%% Test that we can cancel an apply-interval timer.
+cancel5(Config) when is_list(Config) ->
+ Msg1 = make_ref(),
+ {ok, Ref} = timer:apply_interval(500, erlang, send, [self(), Msg1]),
+ receive
+ Msg1 -> ok
+ end,
+ {ok, cancel} = timer:cancel(Ref),
+ Msg2 = make_ref(),
+ {ok, {send_local, _}} = timer:send_after(600, Msg2),
+ Msg2 = receive
+ TmpMsg -> TmpMsg
+ end.
+
+%% Test that cancelling non-existent timers does not crash the
+%% timer server.
+cancel6(Config) when is_list(Config) ->
+ lists:foreach(
+ fun (TimerType) ->
+ Mon = monitor(process, timer_server),
+ {ok, cancel} = timer:cancel({TimerType, make_ref()}),
+ receive
+ {'DOWN', Mon, process, _, _} ->
+ error({timer_server_crashed, {cancel, TimerType}})
+ after 500 ->
+ ok
+ end,
+ demonitor(Mon)
+ end,
+ [once, instant, interval, send_local]
+ ).
+
+%% Test that cancel rejects invalid arguments.
+cancel_invalid_args(Config) when is_list(Config) ->
+ {error, badarg} = timer:cancel(no_reference),
+ {error, badarg} = timer:cancel({foo, make_ref()}),
+ {error, badarg} = timer:cancel({once, foo}),
+ {error, badarg} = timer:cancel({interval, foo}),
+ {error, badarg} = timer:cancel({instant, foo}),
+ ok.
+
+%% Test that sleep pauses the calling process for
+%% at least the given time.
+sleep1(Config) when is_list(Config) ->
+ T0 = erlang:monotonic_time(millisecond),
+ ok = timer:sleep(1000),
+ T1 = erlang:monotonic_time(millisecond),
+ true = T1 - T0 >= 1000,
+ ok.
+
+%% Test that sleep accepts times >(2^32)-1, which is
+%% the maximum time for the after clause of a receive
+%% operation, at the time of this writing.
+sleep2(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ Pid = spawn_link(
+ fun () ->
+ {ok, {once, _}} = timer:kill_after(1000),
+ ok = timer:sleep(16#ffffffff+1)
+ end
+ ),
+ ok = get_mess(2000, {'EXIT', Pid, killed}).
+
+%% Test that unexpected calls do not crash the timer server.
+unexpected1(Config) when is_list(Config) ->
+ Mon = monitor(process, timer_server),
+ try
+ gen_server:call(timer_server, foo, 100)
+ of
+ _ ->
+ error(timeout_expected)
+ catch
+ exit:{timeout, _} ->
+ ok
+ end,
+ receive
+ {'DOWN', Mon, process, _, _} ->
+ error(timer_server_crashed)
+ after 500 ->
+ ok
+ end,
+ demonitor(Mon).
+
+%% Test that unexpected casts do not crash the timer server.
+unexpected2(Config) when is_list(Config) ->
+ Mon = monitor(process, timer_server),
+ gen_server:cast(timer_server, foo),
+ receive
+ {'DOWN', Mon, process, _, _} ->
+ error(timer_server_crashed)
+ after 500 ->
+ ok
+ end,
+ demonitor(Mon).
+
+%% Test that unexpected info messages do not crash the timer server.
+unexpected3(Config) when is_list(Config) ->
+ Mon = monitor(process, timer_server),
+ timer_server ! foo,
+ receive
+ {'DOWN', Mon, process, _, _} ->
+ error(timer_server_crashed)
+ after 500 ->
+ ok
+ end,
+ demonitor(Mon).
+
+%% Test that timeouts of one-shot timers the timer server does not
+%% know are not executed.
+nonexistent1(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ timer_server ! {timeout, make_ref(), {apply_once, {erlang, send, [self(), Msg]}}},
+ nor = get_mess(1000, Msg).
+
+%% Test that timeouts of interval timers the timer server does not
+%% know are not executed.
+nonexistent2(Config) when is_list(Config) ->
+ Msg = make_ref(),
+ timer_server ! {timeout, make_ref, {apply_interval, erlang:monotonic_time(millisecond), 1000, make_ref(), {erlang, send, [self(), Msg]}}},
+ nor = get_mess(1000, Msg).
%% Test sleep/1 and tc/3.
tc(Config) when is_list(Config) ->
%% This should test both sleep and tc/3
{Res1, ok} = timer:tc(timer, sleep, [500]),
- ok = if
- Res1 < 500*1000 -> {too_early, Res1}; % Too early
- Res1 > 800*1000 -> {too_late, Res1}; % Too much time
- true -> ok
- end,
+ ok = if
+ Res1 < 500*1000 -> {too_early, Res1}; % Too early
+ Res1 > 800*1000 -> {too_late, Res1}; % Too much time
+ true -> ok
+ end,
%% tc/2
- {Res2, ok} = timer:tc(fun(T) -> timer:sleep(T) end, [500]),
- ok = if
- Res2 < 500*1000 -> {too_early, Res2}; % Too early
- Res2 > 800*1000 -> {too_late, Res2}; % Too much time
- true -> ok
- end,
+ {Res2, ok} = timer:tc(fun(T) -> ok = timer:sleep(T) end, [500]),
+ ok = if
+ Res2 < 500*1000 -> {too_early, Res2}; % Too early
+ Res2 > 800*1000 -> {too_late, Res2}; % Too much time
+ true -> ok
+ end,
%% tc/1
- {Res3, ok} = timer:tc(fun() -> timer:sleep(500) end),
- ok = if
- Res3 < 500*1000 -> {too_early, Res3}; % Too early
- Res3 > 800*1000 -> {too_late, Res3}; % Too much time
- true -> ok
- end,
+ {Res3, ok} = timer:tc(fun() -> ok = timer:sleep(500) end),
+ ok = if
+ Res3 < 500*1000 -> {too_early, Res3}; % Too early
+ Res3 > 800*1000 -> {too_late, Res3}; % Too much time
+ true -> ok
+ end,
%% Check that timer:tc don't catch errors
ok = try timer:tc(erlang, exit, [foo])
- catch exit:foo -> ok
- end,
+ catch exit:foo -> ok
+ end,
ok = try timer:tc(fun(Reason) -> 1 = Reason end, [foo])
- catch error:{badmatch,_} -> ok
- end,
+ catch error:{badmatch,_} -> ok
+ end,
ok = try timer:tc(fun() -> throw(foo) end)
- catch foo -> ok
- end,
+ catch foo -> ok
+ end,
%% Check that return values are propageted
Self = self(),
@@ -263,70 +689,17 @@ tc(Config) when is_list(Config) ->
if MyRes == TimerRes -> ok end,
ok.
-%% Test that cancellations of one-shot timers do not accidentally
-%% cancel interval timers. [OTP-2771].
-unique_refs(Config) when is_list(Config) ->
- ITimers = repeat_send_interval(10), % 10 interval timers
- eat_refs(?MAXREF - ?REFMARG),
- set_and_cancel_one_shots(?REFMARG),
- NumLeft = num_timers(),
- io:format("~w timers left, should be 10\n", [NumLeft]),
- cancel(ITimers),
- receive_nisse(),
- 10 = NumLeft.
-
-
-repeat_send_interval(0) ->
- [];
-repeat_send_interval(M) ->
- {ok, Ref} = timer:send_interval(6000,self(), nisse),
- [Ref| repeat_send_interval(M - 1)].
-
-eat_refs(0) ->
- 0;
-eat_refs(N) ->
- _ = make_ref(),
- eat_refs(N-1).
-
-set_and_cancel_one_shots(0) ->
- 0;
-set_and_cancel_one_shots(N) ->
- {ok, Ref} = timer:send_after(7000, self(), kalle),
- %% Cancel twice
- timer:cancel(Ref),
- timer:cancel(Ref),
- set_and_cancel_one_shots(N-1).
-
-cancel([T| Ts]) ->
- timer:cancel(T),
- cancel(Ts);
-cancel([]) ->
- ok.
-
-num_timers() ->
- {{_, TotalTimers},{_, _IntervalTimers}} = timer:get_status(),
- TotalTimers.
-
-receive_nisse() ->
- receive
- nisse ->
- receive_nisse()
- after 0 ->
- ok
- end.
-
-
get_mess(Time, Mess) -> get_mess(Time, Mess, 1).
get_mess(_, _, 0) -> ok; % Received
get_mess(Time, Mess, N) ->
receive
- Mess -> get_mess(Time, Mess, N-1)
- after Time
- -> nor % Not Received
+ Mess -> get_mess(Time, Mess, N-1)
+ after Time ->
+ nor % Not Received
end.
forever() ->
- timer:sleep(1000),
+ ok = timer:sleep(1000),
forever().
@@ -343,7 +716,7 @@ performance(Mod) ->
{Y,Mo,D} = date(),
{H,M,S} = time(),
io:format("Testing module '~p' Date: ~w/~w/~w ~w:~w:~w~n",
- [Mod,Y,Mo,D,H,M,S]),
+ [Mod,Y,Mo,D,H,M,S]),
Result = big_test(Mod),
report_result(Result).
@@ -367,15 +740,15 @@ wait([], Res, N, _) ->
{Res, N};
wait(Pids, ResList, N, M) ->
receive
- {Pid, ok, Res, T} ->
- wait(lists:delete(Pid, Pids), [{T, Res} | ResList], N, M);
- {Pid, Error}->
- ct:fail(Error),
- wait(lists:delete(Pid, Pids), ResList, N+1, M);
- {'EXIT', Pid, normal} ->
- wait(lists:delete(Pid, Pids), ResList, N, M);
- {'EXIT', Pid, Reason} ->
- ct:fail({Pid,Reason})
+ {Pid, ok, Res, T} ->
+ wait(lists:delete(Pid, Pids), [{T, Res} | ResList], N, M);
+ {Pid, Error}->
+ ct:fail(Error),
+ wait(lists:delete(Pid, Pids), ResList, N+1, M);
+ {'EXIT', Pid, normal} ->
+ wait(lists:delete(Pid, Pids), ResList, N, M);
+ {'EXIT', Pid, Reason} ->
+ ct:fail({Pid,Reason})
end.
spawn_timers(0, _, _, _) ->
@@ -390,13 +763,13 @@ timer(apply, Mod, T, Pid) ->
Before = system_time(),
{ok, Ref} = apply(Mod, apply_after, [T, ?MODULE, send, [self(), done]]),
receive
- done ->
- After = system_time(),
- Pid ! {self(), ok, (After-Before) div 1000, T}
+ done ->
+ After = system_time(),
+ Pid ! {self(), ok, (After-Before) div 1000, T}
after T*3 + 300 -> % Watch dog
- io:format("WARNING TIMER WATCHDOG timed out: ~w ~n", [T]),
- timer:cancel(Ref),
- Pid ! {self(), watch_dog_timed_out}
+ io:format("WARNING TIMER WATCHDOG timed out: ~w ~n", [T]),
+ {ok, cancel} = timer:cancel(Ref),
+ Pid ! {self(), watch_dog_timed_out}
end.
timer(interval, Mod, T, Pid, NumIter) ->
@@ -412,17 +785,17 @@ timer_irec(_Start, T, {N, N}, Res, {Pid, Mod, Ref}) ->
Pid ! {self(), ok, {N, Tot, Tot div N, Min, Max}, T};
timer_irec(Start, T, {N, Max}, Res, {Pid, Mod, Ref}) ->
receive
- done ->
- Now = system_time(),
- Elapsed = (Now - (Start + (N*T*1000))) div 1000,
- timer_irec(Start, T,
- {N+1, Max},
- [Elapsed | Res],
- {Pid, Mod, Ref})
+ done ->
+ Now = system_time(),
+ Elapsed = (Now - (Start + (N*T*1000))) div 1000,
+ timer_irec(Start, T,
+ {N+1, Max},
+ [Elapsed | Res],
+ {Pid, Mod, Ref})
after T*3 + 300 ->
- apply(Mod, cancel, [Ref]),
- io:format("WARNING: TIMER WATCHDOG timed out <Interval>~w~n",[T]),
- Pid ! {self(), timer_watchdog_timed_out_in_interlval_test}
+ apply(Mod, cancel, [Ref]),
+ io:format("WARNING: TIMER WATCHDOG timed out <Interval>~w~n",[T]),
+ Pid ! {self(), timer_watchdog_timed_out_in_interlval_test}
end.
%% ------------------------------------------------------- %%
@@ -498,11 +871,11 @@ calc_a_val(List) ->
New = lists:sort(List),
{{T1, S}, {T2, M}, {T3, L}} = split(New),
S2 = {length(S), lists:max(S), lists:min(S),
- lists:sum(S) div length(S)},
+ lists:sum(S) div length(S)},
M2 = {length(M), lists:max(M), lists:min(M),
- lists:sum(M) div length(M)},
+ lists:sum(M) div length(M)},
L2 = {length(L), lists:max(L), lists:min(L),
- lists:sum(L) div length(L)},
+ lists:sum(L) div length(L)},
[{T1, S2}, {T2, M2}, {T3, L2}].
calc_i_val(List) ->
@@ -547,17 +920,27 @@ print_aval([]) ->
io:format("~n~n", []);
print_aval([{T, {L, Max, Min, Aver}}|R]) ->
io:format("~5w ~8w ~6w ~6w ~8w ~n",
- [T,L,Max,Min,Aver]),
+ [T,L,Max,Min,Aver]),
print_aval(R).
print_ival([]) ->
io:format("~n", []);
print_ival([{T, {Len, Num,
- {MaxT, MinT, AverT},
- {MaxI, MinI, AverI}}}|R]) ->
+ {MaxT, MinT, AverT},
+ {MaxI, MinI, AverI}}}|R]) ->
io:format("~5w ~6w ~10w ~8w ~6w ~6w ~6w ~6w ~6w~n",
- [T,Len,Num,MaxT,MinT,AverT, MaxI, MinI, AverI]),
+ [T,Len,Num,MaxT,MinT,AverT, MaxI, MinI, AverI]),
print_ival(R).
send(Pid, Msg) ->
Pid ! Msg.
+
+%% Create a unique name and register it to the given process.
+register_name(Pid) ->
+ Name = make_name(),
+ register(Name, Pid),
+ Name.
+
+%% Create a unique name.
+make_name() ->
+ list_to_atom(ref_to_list(make_ref())).
diff --git a/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt b/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt
index 5baf292a07..eff2fd33b0 100644
--- a/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt
+++ b/lib/stdlib/test/unicode_util_SUITE_data/GraphemeBreakTest.txt
@@ -1,6 +1,6 @@
-# GraphemeBreakTest-13.0.0.txt
-# Date: 2019-11-15, 19:49:10 GMT
-# © 2019 Unicode®, Inc.
+# GraphemeBreakTest-14.0.0.txt
+# Date: 2021-03-08, 06:22:32 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
diff --git a/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt b/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt
index d8666c458f..8d1cef0f78 100644
--- a/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt
+++ b/lib/stdlib/test/unicode_util_SUITE_data/LineBreakTest.txt
@@ -1,6 +1,6 @@
-# LineBreakTest-13.0.0.txt
-# Date: 2019-11-21, 16:13:36 GMT
-# © 2019 Unicode®, Inc.
+# LineBreakTest-14.0.0.txt
+# Date: 2021-08-20, 21:08:45 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -1846,9 +1846,9 @@
× AC00 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× AC00 × 0308 ÷ 2329 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [9.0] COMBINING DIAERESIS (CM1_CM) ÷ [999.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× AC00 × 0308 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
-× AC00 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× AC00 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× AC00 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
-× AC00 × 0308 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× AC00 × 0308 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× AC00 × 0308 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
× AC00 ÷ 0024 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) ÷ [999.0] DOLLAR SIGN (PR) ÷ [0.3]
× AC00 × 0020 ÷ 0024 ÷ # × [0.3] HANGUL SYLLABLE GA (H2) × [7.01] SPACE (SP) ÷ [18.0] DOLLAR SIGN (PR) ÷ [0.3]
@@ -2018,9 +2018,9 @@
× AC01 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× AC01 × 0308 ÷ 2329 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [9.0] COMBINING DIAERESIS (CM1_CM) ÷ [999.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× AC01 × 0308 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
-× AC01 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× AC01 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× AC01 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
-× AC01 × 0308 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× AC01 × 0308 × 0025 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× AC01 × 0308 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
× AC01 ÷ 0024 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) ÷ [999.0] DOLLAR SIGN (PR) ÷ [0.3]
× AC01 × 0020 ÷ 0024 ÷ # × [0.3] HANGUL SYLLABLE GAG (H3) × [7.01] SPACE (SP) ÷ [18.0] DOLLAR SIGN (PR) ÷ [0.3]
@@ -3050,9 +3050,9 @@
× 1100 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× 1100 × 0308 ÷ 2329 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [9.0] COMBINING DIAERESIS (CM1_CM) ÷ [999.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× 1100 × 0308 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
-× 1100 × 0025 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× 1100 × 0025 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× 1100 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
-× 1100 × 0308 × 0025 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× 1100 × 0308 × 0025 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× 1100 × 0308 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
× 1100 ÷ 0024 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) ÷ [999.0] DOLLAR SIGN (PR) ÷ [0.3]
× 1100 × 0020 ÷ 0024 ÷ # × [0.3] HANGUL CHOSEONG KIYEOK (JL) × [7.01] SPACE (SP) ÷ [18.0] DOLLAR SIGN (PR) ÷ [0.3]
@@ -3222,9 +3222,9 @@
× 11A8 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× 11A8 × 0308 ÷ 2329 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [9.0] COMBINING DIAERESIS (CM1_CM) ÷ [999.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× 11A8 × 0308 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
-× 11A8 × 0025 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× 11A8 × 0025 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× 11A8 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
-× 11A8 × 0308 × 0025 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× 11A8 × 0308 × 0025 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× 11A8 × 0308 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
× 11A8 ÷ 0024 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) ÷ [999.0] DOLLAR SIGN (PR) ÷ [0.3]
× 11A8 × 0020 ÷ 0024 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [7.01] SPACE (SP) ÷ [18.0] DOLLAR SIGN (PR) ÷ [0.3]
@@ -3394,9 +3394,9 @@
× 1160 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× 1160 × 0308 ÷ 2329 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [9.0] COMBINING DIAERESIS (CM1_CM) ÷ [999.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
× 1160 × 0308 × 0020 ÷ 2329 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] LEFT-POINTING ANGLE BRACKET (OP) ÷ [0.3]
-× 1160 × 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× 1160 × 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× 1160 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
-× 1160 × 0308 × 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
+× 1160 × 0308 × 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
× 1160 × 0308 × 0020 ÷ 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] PERCENT SIGN (PO) ÷ [0.3]
× 1160 ÷ 0024 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) ÷ [999.0] DOLLAR SIGN (PR) ÷ [0.3]
× 1160 × 0020 ÷ 0024 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [7.01] SPACE (SP) ÷ [18.0] DOLLAR SIGN (PR) ÷ [0.3]
@@ -4538,13 +4538,13 @@
× 0024 × 0020 ÷ 00A0 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] NO-BREAK SPACE (GL) ÷ [0.3]
× 0024 × 0308 × 00A0 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [12.2] NO-BREAK SPACE (GL) ÷ [0.3]
× 0024 × 0308 × 0020 ÷ 00A0 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] NO-BREAK SPACE (GL) ÷ [0.3]
-× 0024 × AC00 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.03] HANGUL SYLLABLE GA (H2) ÷ [0.3]
+× 0024 × AC00 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.02] HANGUL SYLLABLE GA (H2) ÷ [0.3]
× 0024 × 0020 ÷ AC00 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] HANGUL SYLLABLE GA (H2) ÷ [0.3]
-× 0024 × 0308 × AC00 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.03] HANGUL SYLLABLE GA (H2) ÷ [0.3]
+× 0024 × 0308 × AC00 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] HANGUL SYLLABLE GA (H2) ÷ [0.3]
× 0024 × 0308 × 0020 ÷ AC00 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] HANGUL SYLLABLE GA (H2) ÷ [0.3]
-× 0024 × AC01 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.03] HANGUL SYLLABLE GAG (H3) ÷ [0.3]
+× 0024 × AC01 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.02] HANGUL SYLLABLE GAG (H3) ÷ [0.3]
× 0024 × 0020 ÷ AC01 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] HANGUL SYLLABLE GAG (H3) ÷ [0.3]
-× 0024 × 0308 × AC01 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.03] HANGUL SYLLABLE GAG (H3) ÷ [0.3]
+× 0024 × 0308 × AC01 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] HANGUL SYLLABLE GAG (H3) ÷ [0.3]
× 0024 × 0308 × 0020 ÷ AC01 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] HANGUL SYLLABLE GAG (H3) ÷ [0.3]
× 0024 × 05D0 ÷ # × [0.3] DOLLAR SIGN (PR) × [24.02] HEBREW LETTER ALEF (HL) ÷ [0.3]
× 0024 × 0020 ÷ 05D0 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] HEBREW LETTER ALEF (HL) ÷ [0.3]
@@ -4566,17 +4566,17 @@
× 0024 × 0020 × 002C ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) × [13.02] COMMA (IS) ÷ [0.3]
× 0024 × 0308 × 002C ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [13.03] COMMA (IS) ÷ [0.3]
× 0024 × 0308 × 0020 × 002C ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) × [13.02] COMMA (IS) ÷ [0.3]
-× 0024 × 1100 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.03] HANGUL CHOSEONG KIYEOK (JL) ÷ [0.3]
+× 0024 × 1100 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.02] HANGUL CHOSEONG KIYEOK (JL) ÷ [0.3]
× 0024 × 0020 ÷ 1100 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] HANGUL CHOSEONG KIYEOK (JL) ÷ [0.3]
-× 0024 × 0308 × 1100 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.03] HANGUL CHOSEONG KIYEOK (JL) ÷ [0.3]
+× 0024 × 0308 × 1100 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] HANGUL CHOSEONG KIYEOK (JL) ÷ [0.3]
× 0024 × 0308 × 0020 ÷ 1100 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] HANGUL CHOSEONG KIYEOK (JL) ÷ [0.3]
-× 0024 × 11A8 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.03] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
+× 0024 × 11A8 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.02] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
× 0024 × 0020 ÷ 11A8 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
-× 0024 × 0308 × 11A8 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.03] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
+× 0024 × 0308 × 11A8 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
× 0024 × 0308 × 0020 ÷ 11A8 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
-× 0024 × 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.03] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
+× 0024 × 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.02] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
× 0024 × 0020 ÷ 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) ÷ [18.0] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
-× 0024 × 0308 × 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.03] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
+× 0024 × 0308 × 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [27.02] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
× 0024 × 0308 × 0020 ÷ 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
× 0024 × 000A ÷ # × [0.3] DOLLAR SIGN (PR) × [6.0] <LINE FEED (LF)> (LF) ÷ [0.3]
× 0024 × 0020 × 000A ÷ # × [0.3] DOLLAR SIGN (PR) × [7.01] SPACE (SP) × [6.0] <LINE FEED (LF)> (LF) ÷ [0.3]
@@ -5838,9 +5838,9 @@
× 261D × 0020 ÷ 261D ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [7.01] SPACE (SP) ÷ [18.0] WHITE UP POINTING INDEX (EB) ÷ [0.3]
× 261D × 0308 ÷ 261D ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [9.0] COMBINING DIAERESIS (CM1_CM) ÷ [999.0] WHITE UP POINTING INDEX (EB) ÷ [0.3]
× 261D × 0308 × 0020 ÷ 261D ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] WHITE UP POINTING INDEX (EB) ÷ [0.3]
-× 261D × 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [30.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
+× 261D × 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [30.21] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
× 261D × 0020 ÷ 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [7.01] SPACE (SP) ÷ [18.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
-× 261D × 0308 × 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [9.0] COMBINING DIAERESIS (CM1_CM) × [30.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
+× 261D × 0308 × 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [9.0] COMBINING DIAERESIS (CM1_CM) × [30.21] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
× 261D × 0308 × 0020 ÷ 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [9.0] COMBINING DIAERESIS (CM1_CM) × [7.01] SPACE (SP) ÷ [18.0] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
× 261D × 0029 ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [13.02] RIGHT PARENTHESIS (CP_CP30) ÷ [0.3]
× 261D × 0020 × 0029 ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [7.01] SPACE (SP) × [13.02] RIGHT PARENTHESIS (CP_CP30) ÷ [0.3]
@@ -7452,9 +7452,9 @@
× 1160 × 1160 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [26.02] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
× 11A8 × 11A8 ÷ # × [0.3] HANGUL JONGSEONG KIYEOK (JT) × [26.03] HANGUL JONGSEONG KIYEOK (JT) ÷ [0.3]
× 1160 × 2024 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [22.0] ONE DOT LEADER (IN) ÷ [0.3]
-× 1160 × 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [27.02] PERCENT SIGN (PO) ÷ [0.3]
-× 0024 × 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.03] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
-× 261D × 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [30.2] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
+× 1160 × 0025 ÷ # × [0.3] HANGUL JUNGSEONG FILLER (JV) × [27.01] PERCENT SIGN (PO) ÷ [0.3]
+× 0024 × 1160 ÷ # × [0.3] DOLLAR SIGN (PR) × [27.02] HANGUL JUNGSEONG FILLER (JV) ÷ [0.3]
+× 261D × 1F3FB ÷ # × [0.3] WHITE UP POINTING INDEX (EB) × [30.21] EMOJI MODIFIER FITZPATRICK TYPE-1-2 (EM) ÷ [0.3]
× 0066 × 0069 × 006E × 0061 × 006C ÷ # × [0.3] LATIN SMALL LETTER F (AL) × [28.0] LATIN SMALL LETTER I (AL) × [28.0] LATIN SMALL LETTER N (AL) × [28.0] LATIN SMALL LETTER A (AL) × [28.0] LATIN SMALL LETTER L (AL) ÷ [0.3]
× 0063 × 0061 × 006E × 0027 × 0074 ÷ # × [0.3] LATIN SMALL LETTER C (AL) × [28.0] LATIN SMALL LETTER A (AL) × [28.0] LATIN SMALL LETTER N (AL) × [19.01] APOSTROPHE (QU) × [19.02] LATIN SMALL LETTER T (AL) ÷ [0.3]
× 0063 × 0061 × 006E × 2019 × 0074 ÷ # × [0.3] LATIN SMALL LETTER C (AL) × [28.0] LATIN SMALL LETTER A (AL) × [28.0] LATIN SMALL LETTER N (AL) × [19.01] RIGHT SINGLE QUOTATION MARK (QU) × [19.02] LATIN SMALL LETTER T (AL) ÷ [0.3]
@@ -7678,7 +7678,9 @@
× 1F1F7 × 1F1FA ÷ 1F1F8 × 1F1EA ÷ # × [0.3] REGIONAL INDICATOR SYMBOL LETTER R (RI) × [30.11] REGIONAL INDICATOR SYMBOL LETTER U (RI) ÷ [30.13] REGIONAL INDICATOR SYMBOL LETTER S (RI) × [30.11] REGIONAL INDICATOR SYMBOL LETTER E (RI) ÷ [0.3]
× 1F1F7 × 1F1FA × 200B ÷ 1F1F8 × 1F1EA ÷ # × [0.3] REGIONAL INDICATOR SYMBOL LETTER R (RI) × [30.11] REGIONAL INDICATOR SYMBOL LETTER U (RI) × [7.02] ZERO WIDTH SPACE (ZW) ÷ [8.0] REGIONAL INDICATOR SYMBOL LETTER S (RI) × [30.12] REGIONAL INDICATOR SYMBOL LETTER E (RI) ÷ [0.3]
× 05D0 × 002D × 05D0 ÷ # × [0.3] HEBREW LETTER ALEF (HL) × [21.02] HYPHEN-MINUS (HY) × [21.1] HEBREW LETTER ALEF (HL) ÷ [0.3]
+× 1F02C × 1F3FF ÷ # × [0.3] <reserved-1F02C> (Other) × [30.22] EMOJI MODIFIER FITZPATRICK TYPE-6 (EM) ÷ [0.3]
+× 00A9 ÷ 1F3FF ÷ # × [0.3] COPYRIGHT SIGN (AL) ÷ [999.0] EMOJI MODIFIER FITZPATRICK TYPE-6 (EM) ÷ [0.3]
#
-# Lines: 7652
+# Lines: 7654
#
# EOF
diff --git a/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt b/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt
index fa9b0d954c..302c35f37c 100644
--- a/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt
+++ b/lib/stdlib/test/unicode_util_SUITE_data/NormalizationTest.txt
@@ -1,6 +1,6 @@
-# NormalizationTest-13.0.0.txt
-# Date: 2019-09-08, 23:31:12 GMT
-# © 2019 Unicode®, Inc.
+# NormalizationTest-14.0.0.txt
+# Date: 2021-05-28, 21:49:12 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -2409,6 +2409,9 @@
A69C;A69C;A69C;044A;044A; # (ꚜ; ꚜ; ꚜ; ъ; ъ; ) MODIFIER LETTER CYRILLIC HARD SIGN
A69D;A69D;A69D;044C;044C; # (êš; êš; êš; ÑŒ; ÑŒ; ) MODIFIER LETTER CYRILLIC SOFT SIGN
A770;A770;A770;A76F;A76F; # (ê°; ê°; ê°; ê¯; ê¯; ) MODIFIER LETTER US
+A7F2;A7F2;A7F2;0043;0043; # (ꟲ; ꟲ; ꟲ; C; C; ) MODIFIER LETTER CAPITAL C
+A7F3;A7F3;A7F3;0046;0046; # (ꟳ; ꟳ; ꟳ; F; F; ) MODIFIER LETTER CAPITAL F
+A7F4;A7F4;A7F4;0051;0051; # (ꟴ; ꟴ; ꟴ; Q; Q; ) MODIFIER LETTER CAPITAL Q
A7F8;A7F8;A7F8;0126;0126; # (ꟸ; ꟸ; ꟸ; Ħ; Ħ; ) MODIFIER LETTER CAPITAL H WITH STROKE
A7F9;A7F9;A7F9;0153;0153; # (ꟹ; ꟹ; ꟹ; œ; œ; ) MODIFIER LETTER SMALL LIGATURE OE
AB5C;AB5C;AB5C;A727;A727; # (ꭜ; ꭜ; ꭜ; ꜧ; ꜧ; ) MODIFIER LETTER SMALL HENG
@@ -15127,6 +15130,62 @@ FFEB;FFEB;FFEB;2192;2192; # (→; →; →; →; →; ) HALFWIDTH RIGHTWARDS ARR
FFEC;FFEC;FFEC;2193;2193; # (↓; ↓; ↓; ↓; ↓; ) HALFWIDTH DOWNWARDS ARROW
FFED;FFED;FFED;25A0;25A0; # (ï¿­; ï¿­; ï¿­; â– ; â– ; ) HALFWIDTH BLACK SQUARE
FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
+10781;10781;10781;02D0;02D0; # (ðž; ðž; ðž; Ë; Ë; ) MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON
+10782;10782;10782;02D1;02D1; # (ðž‚; ðž‚; ðž‚; Ë‘; Ë‘; ) MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON
+10783;10783;10783;00E6;00E6; # (ðžƒ; ðžƒ; ðžƒ; æ; æ; ) MODIFIER LETTER SMALL AE
+10784;10784;10784;0299;0299; # (ðž„; ðž„; ðž„; Ê™; Ê™; ) MODIFIER LETTER SMALL CAPITAL B
+10785;10785;10785;0253;0253; # (ðž…; ðž…; ðž…; É“; É“; ) MODIFIER LETTER SMALL B WITH HOOK
+10787;10787;10787;02A3;02A3; # (ðž‡; ðž‡; ðž‡; Ê£; Ê£; ) MODIFIER LETTER SMALL DZ DIGRAPH
+10788;10788;10788;AB66;AB66; # (ðžˆ; ðžˆ; ðžˆ; ê­¦; ê­¦; ) MODIFIER LETTER SMALL DZ DIGRAPH WITH RETROFLEX HOOK
+10789;10789;10789;02A5;02A5; # (ðž‰; ðž‰; ðž‰; Ê¥; Ê¥; ) MODIFIER LETTER SMALL DZ DIGRAPH WITH CURL
+1078A;1078A;1078A;02A4;02A4; # (ðžŠ; ðžŠ; ðžŠ; ʤ; ʤ; ) MODIFIER LETTER SMALL DEZH DIGRAPH
+1078B;1078B;1078B;0256;0256; # (ðž‹; ðž‹; ðž‹; É–; É–; ) MODIFIER LETTER SMALL D WITH TAIL
+1078C;1078C;1078C;0257;0257; # (ðžŒ; ðžŒ; ðžŒ; É—; É—; ) MODIFIER LETTER SMALL D WITH HOOK
+1078D;1078D;1078D;1D91;1D91; # (ðž; ðž; ðž; ᶑ; ᶑ; ) MODIFIER LETTER SMALL D WITH HOOK AND TAIL
+1078E;1078E;1078E;0258;0258; # (ðžŽ; ðžŽ; ðžŽ; ɘ; ɘ; ) MODIFIER LETTER SMALL REVERSED E
+1078F;1078F;1078F;025E;025E; # (ðž; ðž; ðž; Éž; Éž; ) MODIFIER LETTER SMALL CLOSED REVERSED OPEN E
+10790;10790;10790;02A9;02A9; # (ðž; ðž; ðž; Ê©; Ê©; ) MODIFIER LETTER SMALL FENG DIGRAPH
+10791;10791;10791;0264;0264; # (ðž‘; ðž‘; ðž‘; ɤ; ɤ; ) MODIFIER LETTER SMALL RAMS HORN
+10792;10792;10792;0262;0262; # (ðž’; ðž’; ðž’; É¢; É¢; ) MODIFIER LETTER SMALL CAPITAL G
+10793;10793;10793;0260;0260; # (ðž“; ðž“; ðž“; É ; É ; ) MODIFIER LETTER SMALL G WITH HOOK
+10794;10794;10794;029B;029B; # (ðž”; ðž”; ðž”; Ê›; Ê›; ) MODIFIER LETTER SMALL CAPITAL G WITH HOOK
+10795;10795;10795;0127;0127; # (ðž•; ðž•; ðž•; ħ; ħ; ) MODIFIER LETTER SMALL H WITH STROKE
+10796;10796;10796;029C;029C; # (ðž–; ðž–; ðž–; Êœ; Êœ; ) MODIFIER LETTER SMALL CAPITAL H
+10797;10797;10797;0267;0267; # (ðž—; ðž—; ðž—; ɧ; ɧ; ) MODIFIER LETTER SMALL HENG WITH HOOK
+10798;10798;10798;0284;0284; # (ðž˜; ðž˜; ðž˜; Ê„; Ê„; ) MODIFIER LETTER SMALL DOTLESS J WITH STROKE AND HOOK
+10799;10799;10799;02AA;02AA; # (ðž™; ðž™; ðž™; ʪ; ʪ; ) MODIFIER LETTER SMALL LS DIGRAPH
+1079A;1079A;1079A;02AB;02AB; # (ðžš; ðžš; ðžš; Ê«; Ê«; ) MODIFIER LETTER SMALL LZ DIGRAPH
+1079B;1079B;1079B;026C;026C; # (ðž›; ðž›; ðž›; ɬ; ɬ; ) MODIFIER LETTER SMALL L WITH BELT
+1079C;1079C;1079C;1DF04;1DF04; # (ðžœ; ðžœ; ðžœ; ð¼„; ð¼„; ) MODIFIER LETTER SMALL CAPITAL L WITH BELT
+1079D;1079D;1079D;A78E;A78E; # (ðž; ðž; ðž; ꞎ; ꞎ; ) MODIFIER LETTER SMALL L WITH RETROFLEX HOOK AND BELT
+1079E;1079E;1079E;026E;026E; # (ðžž; ðžž; ðžž; É®; É®; ) MODIFIER LETTER SMALL LEZH
+1079F;1079F;1079F;1DF05;1DF05; # (ðžŸ; ðžŸ; ðžŸ; ð¼…; ð¼…; ) MODIFIER LETTER SMALL LEZH WITH RETROFLEX HOOK
+107A0;107A0;107A0;028E;028E; # (ðž ; ðž ; ðž ; ÊŽ; ÊŽ; ) MODIFIER LETTER SMALL TURNED Y
+107A1;107A1;107A1;1DF06;1DF06; # (ðž¡; ðž¡; ðž¡; ð¼†; ð¼†; ) MODIFIER LETTER SMALL TURNED Y WITH BELT
+107A2;107A2;107A2;00F8;00F8; # (ðž¢; ðž¢; ðž¢; ø; ø; ) MODIFIER LETTER SMALL O WITH STROKE
+107A3;107A3;107A3;0276;0276; # (ðž£; ðž£; ðž£; ɶ; ɶ; ) MODIFIER LETTER SMALL CAPITAL OE
+107A4;107A4;107A4;0277;0277; # (ðž¤; ðž¤; ðž¤; É·; É·; ) MODIFIER LETTER SMALL CLOSED OMEGA
+107A5;107A5;107A5;0071;0071; # (ðž¥; ðž¥; ðž¥; q; q; ) MODIFIER LETTER SMALL Q
+107A6;107A6;107A6;027A;027A; # (ðž¦; ðž¦; ðž¦; ɺ; ɺ; ) MODIFIER LETTER SMALL TURNED R WITH LONG LEG
+107A7;107A7;107A7;1DF08;1DF08; # (ðž§; ðž§; ðž§; ð¼ˆ; ð¼ˆ; ) MODIFIER LETTER SMALL TURNED R WITH LONG LEG AND RETROFLEX HOOK
+107A8;107A8;107A8;027D;027D; # (ðž¨; ðž¨; ðž¨; ɽ; ɽ; ) MODIFIER LETTER SMALL R WITH TAIL
+107A9;107A9;107A9;027E;027E; # (ðž©; ðž©; ðž©; ɾ; ɾ; ) MODIFIER LETTER SMALL R WITH FISHHOOK
+107AA;107AA;107AA;0280;0280; # (ðžª; ðžª; ðžª; Ê€; Ê€; ) MODIFIER LETTER SMALL CAPITAL R
+107AB;107AB;107AB;02A8;02A8; # (ðž«; ðž«; ðž«; ʨ; ʨ; ) MODIFIER LETTER SMALL TC DIGRAPH WITH CURL
+107AC;107AC;107AC;02A6;02A6; # (ðž¬; ðž¬; ðž¬; ʦ; ʦ; ) MODIFIER LETTER SMALL TS DIGRAPH
+107AD;107AD;107AD;AB67;AB67; # (ðž­; ðž­; ðž­; ê­§; ê­§; ) MODIFIER LETTER SMALL TS DIGRAPH WITH RETROFLEX HOOK
+107AE;107AE;107AE;02A7;02A7; # (ðž®; ðž®; ðž®; ʧ; ʧ; ) MODIFIER LETTER SMALL TESH DIGRAPH
+107AF;107AF;107AF;0288;0288; # (ðž¯; ðž¯; ðž¯; ʈ; ʈ; ) MODIFIER LETTER SMALL T WITH RETROFLEX HOOK
+107B0;107B0;107B0;2C71;2C71; # (ðž°; ðž°; ðž°; â±±; â±±; ) MODIFIER LETTER SMALL V WITH RIGHT HOOK
+107B2;107B2;107B2;028F;028F; # (ðž²; ðž²; ðž²; Ê; Ê; ) MODIFIER LETTER SMALL CAPITAL Y
+107B3;107B3;107B3;02A1;02A1; # (ðž³; ðž³; ðž³; Ê¡; Ê¡; ) MODIFIER LETTER GLOTTAL STOP WITH STROKE
+107B4;107B4;107B4;02A2;02A2; # (ðž´; ðž´; ðž´; Ê¢; Ê¢; ) MODIFIER LETTER REVERSED GLOTTAL STOP WITH STROKE
+107B5;107B5;107B5;0298;0298; # (ðžµ; ðžµ; ðžµ; ʘ; ʘ; ) MODIFIER LETTER BILABIAL CLICK
+107B6;107B6;107B6;01C0;01C0; # (ðž¶; ðž¶; ðž¶; Ç€; Ç€; ) MODIFIER LETTER DENTAL CLICK
+107B7;107B7;107B7;01C1;01C1; # (ðž·; ðž·; ðž·; Ç; Ç; ) MODIFIER LETTER LATERAL CLICK
+107B8;107B8;107B8;01C2;01C2; # (ðž¸; ðž¸; ðž¸; Ç‚; Ç‚; ) MODIFIER LETTER ALVEOLAR CLICK
+107B9;107B9;107B9;1DF0A;1DF0A; # (ðž¹; ðž¹; ðž¹; ð¼Š; ð¼Š; ) MODIFIER LETTER RETROFLEX CLICK WITH RETROFLEX HOOK
+107BA;107BA;107BA;1DF1E;1DF1E; # (ðžº; ðžº; ðžº; ð¼ž; ð¼ž; ) MODIFIER LETTER SMALL S WITH CURL
1109A;1109A;11099 110BA;1109A;11099 110BA; # (𑂚; 𑂚; 𑂙◌𑂺; 𑂚; 𑂙◌𑂺; ) KAITHI LETTER DDDHA
1109C;1109C;1109B 110BA;1109C;1109B 110BA; # (𑂜; 𑂜; 𑂛◌𑂺; 𑂜; 𑂛◌𑂺; ) KAITHI LETTER RHA
110AB;110AB;110A5 110BA;110AB;110A5 110BA; # (𑂫; 𑂫; 𑂥◌𑂺; 𑂫; 𑂥◌𑂺; ) KAITHI LETTER VA
@@ -17025,66 +17084,66 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0314 0315 0300 05AE 0062;0061 05AE 0314 0300 0315 0062;0061 05AE 0314 0300 0315 0062;0061 05AE 0314 0300 0315 0062;0061 05AE 0314 0300 0315 0062; # (a◌̔◌̕◌̀◌֮b; a◌֮◌̔◌̀◌̕b; a◌֮◌̔◌̀◌̕b; a◌֮◌̔◌̀◌̕b; a◌֮◌̔◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING REVERSED COMMA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 035C 0315 0300 0315 0062;00E0 0315 0315 035C 0062;0061 0300 0315 0315 035C 0062;00E0 0315 0315 035C 0062;0061 0300 0315 0315 035C 0062; # (a◌͜◌̕◌̀◌̕b; à◌̕◌̕◌͜b; a◌̀◌̕◌̕◌͜b; à◌̕◌̕◌͜b; a◌̀◌̕◌̕◌͜b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, COMBINING COMMA ABOVE RIGHT, LATIN SMALL LETTER B
0061 0315 035C 0315 0300 0062;00E0 0315 0315 035C 0062;0061 0300 0315 0315 035C 0062;00E0 0315 0315 035C 0062;0061 0300 0315 0315 035C 0062; # (a◌̕◌͜◌̕◌̀b; à◌̕◌̕◌͜b; a◌̀◌̕◌̕◌͜b; à◌̕◌̕◌͜b; a◌̀◌̕◌̕◌͜b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B
-0061 059A 0316 302A 0316 0062;0061 302A 0316 0316 059A 0062;0061 302A 0316 0316 059A 0062;0061 302A 0316 0316 059A 0062;0061 302A 0316 0316 059A 0062; # (a◌֚◌̖◌〪◌̖b; a◌〪◌̖◌̖◌֚b; a◌〪◌̖◌̖◌֚b; a◌〪◌̖◌̖◌֚b; a◌〪◌̖◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING GRAVE ACCENT BELOW, LATIN SMALL LETTER B
-0061 0316 059A 0316 302A 0062;0061 302A 0316 0316 059A 0062;0061 302A 0316 0316 059A 0062;0061 302A 0316 0316 059A 0062;0061 302A 0316 0316 059A 0062; # (a◌̖◌֚◌̖◌〪b; a◌〪◌̖◌̖◌֚b; a◌〪◌̖◌̖◌֚b; a◌〪◌̖◌̖◌֚b; a◌〪◌̖◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0317 0062;0061 302A 0316 0317 059A 0062;0061 302A 0316 0317 059A 0062;0061 302A 0316 0317 059A 0062;0061 302A 0316 0317 059A 0062; # (a◌֚◌̖◌〪◌̗b; a◌〪◌̖◌̗◌֚b; a◌〪◌̖◌̗◌֚b; a◌〪◌̖◌̗◌֚b; a◌〪◌̖◌̗◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING ACUTE ACCENT BELOW, LATIN SMALL LETTER B
-0061 0317 059A 0316 302A 0062;0061 302A 0317 0316 059A 0062;0061 302A 0317 0316 059A 0062;0061 302A 0317 0316 059A 0062;0061 302A 0317 0316 059A 0062; # (a◌̗◌֚◌̖◌〪b; a◌〪◌̗◌̖◌֚b; a◌〪◌̗◌̖◌֚b; a◌〪◌̗◌̖◌֚b; a◌〪◌̗◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING ACUTE ACCENT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0318 0062;0061 302A 0316 0318 059A 0062;0061 302A 0316 0318 059A 0062;0061 302A 0316 0318 059A 0062;0061 302A 0316 0318 059A 0062; # (a◌֚◌̖◌〪◌̘b; a◌〪◌̖◌̘◌֚b; a◌〪◌̖◌̘◌֚b; a◌〪◌̖◌̘◌֚b; a◌〪◌̖◌̘◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFT TACK BELOW, LATIN SMALL LETTER B
-0061 0318 059A 0316 302A 0062;0061 302A 0318 0316 059A 0062;0061 302A 0318 0316 059A 0062;0061 302A 0318 0316 059A 0062;0061 302A 0318 0316 059A 0062; # (a◌̘◌֚◌̖◌〪b; a◌〪◌̘◌̖◌֚b; a◌〪◌̘◌̖◌֚b; a◌〪◌̘◌̖◌֚b; a◌〪◌̘◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0319 0062;0061 302A 0316 0319 059A 0062;0061 302A 0316 0319 059A 0062;0061 302A 0316 0319 059A 0062;0061 302A 0316 0319 059A 0062; # (a◌֚◌̖◌〪◌̙b; a◌〪◌̖◌̙◌֚b; a◌〪◌̖◌̙◌֚b; a◌〪◌̖◌̙◌֚b; a◌〪◌̖◌̙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHT TACK BELOW, LATIN SMALL LETTER B
-0061 0319 059A 0316 302A 0062;0061 302A 0319 0316 059A 0062;0061 302A 0319 0316 059A 0062;0061 302A 0319 0316 059A 0062;0061 302A 0319 0316 059A 0062; # (a◌̙◌֚◌̖◌〪b; a◌〪◌̙◌̖◌֚b; a◌〪◌̙◌̖◌֚b; a◌〪◌̙◌̖◌֚b; a◌〪◌̙◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0316 0062;0061 1DFA 0316 0316 059A 0062;0061 1DFA 0316 0316 059A 0062;0061 1DFA 0316 0316 059A 0062;0061 1DFA 0316 0316 059A 0062; # (a◌֚◌̖◌᷺◌̖b; a◌᷺◌̖◌̖◌֚b; a◌᷺◌̖◌̖◌֚b; a◌᷺◌̖◌̖◌֚b; a◌᷺◌̖◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING GRAVE ACCENT BELOW, LATIN SMALL LETTER B
+0061 0316 059A 0316 1DFA 0062;0061 1DFA 0316 0316 059A 0062;0061 1DFA 0316 0316 059A 0062;0061 1DFA 0316 0316 059A 0062;0061 1DFA 0316 0316 059A 0062; # (a◌̖◌֚◌̖◌᷺b; a◌᷺◌̖◌̖◌֚b; a◌᷺◌̖◌̖◌֚b; a◌᷺◌̖◌̖◌֚b; a◌᷺◌̖◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0317 0062;0061 1DFA 0316 0317 059A 0062;0061 1DFA 0316 0317 059A 0062;0061 1DFA 0316 0317 059A 0062;0061 1DFA 0316 0317 059A 0062; # (a◌֚◌̖◌᷺◌̗b; a◌᷺◌̖◌̗◌֚b; a◌᷺◌̖◌̗◌֚b; a◌᷺◌̖◌̗◌֚b; a◌᷺◌̖◌̗◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING ACUTE ACCENT BELOW, LATIN SMALL LETTER B
+0061 0317 059A 0316 1DFA 0062;0061 1DFA 0317 0316 059A 0062;0061 1DFA 0317 0316 059A 0062;0061 1DFA 0317 0316 059A 0062;0061 1DFA 0317 0316 059A 0062; # (a◌̗◌֚◌̖◌᷺b; a◌᷺◌̗◌̖◌֚b; a◌᷺◌̗◌̖◌֚b; a◌᷺◌̗◌̖◌֚b; a◌᷺◌̗◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING ACUTE ACCENT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0318 0062;0061 1DFA 0316 0318 059A 0062;0061 1DFA 0316 0318 059A 0062;0061 1DFA 0316 0318 059A 0062;0061 1DFA 0316 0318 059A 0062; # (a◌֚◌̖◌᷺◌̘b; a◌᷺◌̖◌̘◌֚b; a◌᷺◌̖◌̘◌֚b; a◌᷺◌̖◌̘◌֚b; a◌᷺◌̖◌̘◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT TACK BELOW, LATIN SMALL LETTER B
+0061 0318 059A 0316 1DFA 0062;0061 1DFA 0318 0316 059A 0062;0061 1DFA 0318 0316 059A 0062;0061 1DFA 0318 0316 059A 0062;0061 1DFA 0318 0316 059A 0062; # (a◌̘◌֚◌̖◌᷺b; a◌᷺◌̘◌̖◌֚b; a◌᷺◌̘◌̖◌֚b; a◌᷺◌̘◌̖◌֚b; a◌᷺◌̘◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0319 0062;0061 1DFA 0316 0319 059A 0062;0061 1DFA 0316 0319 059A 0062;0061 1DFA 0316 0319 059A 0062;0061 1DFA 0316 0319 059A 0062; # (a◌֚◌̖◌᷺◌̙b; a◌᷺◌̖◌̙◌֚b; a◌᷺◌̖◌̙◌֚b; a◌᷺◌̖◌̙◌֚b; a◌᷺◌̖◌̙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT TACK BELOW, LATIN SMALL LETTER B
+0061 0319 059A 0316 1DFA 0062;0061 1DFA 0319 0316 059A 0062;0061 1DFA 0319 0316 059A 0062;0061 1DFA 0319 0316 059A 0062;0061 1DFA 0319 0316 059A 0062; # (a◌̙◌֚◌̖◌᷺b; a◌᷺◌̙◌̖◌֚b; a◌᷺◌̙◌̖◌֚b; a◌᷺◌̙◌̖◌֚b; a◌᷺◌̙◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 035C 0315 0300 031A 0062;00E0 0315 031A 035C 0062;0061 0300 0315 031A 035C 0062;00E0 0315 031A 035C 0062;0061 0300 0315 031A 035C 0062; # (a◌͜◌̕◌̀◌̚b; à◌̕◌̚◌͜b; a◌̀◌̕◌̚◌͜b; à◌̕◌̚◌͜b; a◌̀◌̕◌̚◌͜b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, COMBINING LEFT ANGLE ABOVE, LATIN SMALL LETTER B
0061 031A 035C 0315 0300 0062;00E0 031A 0315 035C 0062;0061 0300 031A 0315 035C 0062;00E0 031A 0315 035C 0062;0061 0300 031A 0315 035C 0062; # (a◌̚◌͜◌̕◌̀b; à◌̚◌̕◌͜b; a◌̀◌̚◌̕◌͜b; à◌̚◌̕◌͜b; a◌̀◌̚◌̕◌͜b; ) LATIN SMALL LETTER A, COMBINING LEFT ANGLE ABOVE, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 031B 0062;0061 1DCE 031B 031B 302A 0062;0061 1DCE 031B 031B 302A 0062;0061 1DCE 031B 031B 302A 0062;0061 1DCE 031B 031B 302A 0062; # (a◌〪◌̛◌᷎◌̛b; a◌᷎◌̛◌̛◌〪b; a◌᷎◌̛◌̛◌〪b; a◌᷎◌̛◌̛◌〪b; a◌᷎◌̛◌̛◌〪b; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, COMBINING HORN, LATIN SMALL LETTER B
-0061 031B 302A 031B 1DCE 0062;0061 1DCE 031B 031B 302A 0062;0061 1DCE 031B 031B 302A 0062;0061 1DCE 031B 031B 302A 0062;0061 1DCE 031B 031B 302A 0062; # (a◌̛◌〪◌̛◌᷎b; a◌᷎◌̛◌̛◌〪b; a◌᷎◌̛◌̛◌〪b; a◌᷎◌̛◌̛◌〪b; a◌᷎◌̛◌̛◌〪b; ) LATIN SMALL LETTER A, COMBINING HORN, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 059A 0316 302A 031C 0062;0061 302A 0316 031C 059A 0062;0061 302A 0316 031C 059A 0062;0061 302A 0316 031C 059A 0062;0061 302A 0316 031C 059A 0062; # (a◌֚◌̖◌〪◌̜b; a◌〪◌̖◌̜◌֚b; a◌〪◌̖◌̜◌֚b; a◌〪◌̖◌̜◌֚b; a◌〪◌̖◌̜◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFT HALF RING BELOW, LATIN SMALL LETTER B
-0061 031C 059A 0316 302A 0062;0061 302A 031C 0316 059A 0062;0061 302A 031C 0316 059A 0062;0061 302A 031C 0316 059A 0062;0061 302A 031C 0316 059A 0062; # (a◌̜◌֚◌̖◌〪b; a◌〪◌̜◌̖◌֚b; a◌〪◌̜◌̖◌֚b; a◌〪◌̜◌̖◌֚b; a◌〪◌̜◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT HALF RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 031D 0062;0061 302A 0316 031D 059A 0062;0061 302A 0316 031D 059A 0062;0061 302A 0316 031D 059A 0062;0061 302A 0316 031D 059A 0062; # (a◌֚◌̖◌〪◌Ìb; a◌〪◌̖◌Ì◌֚b; a◌〪◌̖◌Ì◌֚b; a◌〪◌̖◌Ì◌֚b; a◌〪◌̖◌Ì◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING UP TACK BELOW, LATIN SMALL LETTER B
-0061 031D 059A 0316 302A 0062;0061 302A 031D 0316 059A 0062;0061 302A 031D 0316 059A 0062;0061 302A 031D 0316 059A 0062;0061 302A 031D 0316 059A 0062; # (aâ—ŒÌ◌֚◌̖◌〪b; a◌〪◌Ì◌̖◌֚b; a◌〪◌Ì◌̖◌֚b; a◌〪◌Ì◌̖◌֚b; a◌〪◌Ì◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING UP TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 031E 0062;0061 302A 0316 031E 059A 0062;0061 302A 0316 031E 059A 0062;0061 302A 0316 031E 059A 0062;0061 302A 0316 031E 059A 0062; # (a◌֚◌̖◌〪◌̞b; a◌〪◌̖◌̞◌֚b; a◌〪◌̖◌̞◌֚b; a◌〪◌̖◌̞◌֚b; a◌〪◌̖◌̞◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DOWN TACK BELOW, LATIN SMALL LETTER B
-0061 031E 059A 0316 302A 0062;0061 302A 031E 0316 059A 0062;0061 302A 031E 0316 059A 0062;0061 302A 031E 0316 059A 0062;0061 302A 031E 0316 059A 0062; # (a◌̞◌֚◌̖◌〪b; a◌〪◌̞◌̖◌֚b; a◌〪◌̞◌̖◌֚b; a◌〪◌̞◌̖◌֚b; a◌〪◌̞◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOWN TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 031F 0062;0061 302A 0316 031F 059A 0062;0061 302A 0316 031F 059A 0062;0061 302A 0316 031F 059A 0062;0061 302A 0316 031F 059A 0062; # (a◌֚◌̖◌〪◌̟b; a◌〪◌̖◌̟◌֚b; a◌〪◌̖◌̟◌֚b; a◌〪◌̖◌̟◌֚b; a◌〪◌̖◌̟◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING PLUS SIGN BELOW, LATIN SMALL LETTER B
-0061 031F 059A 0316 302A 0062;0061 302A 031F 0316 059A 0062;0061 302A 031F 0316 059A 0062;0061 302A 031F 0316 059A 0062;0061 302A 031F 0316 059A 0062; # (a◌̟◌֚◌̖◌〪b; a◌〪◌̟◌̖◌֚b; a◌〪◌̟◌̖◌֚b; a◌〪◌̟◌̖◌֚b; a◌〪◌̟◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING PLUS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0320 0062;0061 302A 0316 0320 059A 0062;0061 302A 0316 0320 059A 0062;0061 302A 0316 0320 059A 0062;0061 302A 0316 0320 059A 0062; # (a◌֚◌̖◌〪◌̠b; a◌〪◌̖◌̠◌֚b; a◌〪◌̖◌̠◌֚b; a◌〪◌̖◌̠◌֚b; a◌〪◌̖◌̠◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING MINUS SIGN BELOW, LATIN SMALL LETTER B
-0061 0320 059A 0316 302A 0062;0061 302A 0320 0316 059A 0062;0061 302A 0320 0316 059A 0062;0061 302A 0320 0316 059A 0062;0061 302A 0320 0316 059A 0062; # (a◌̠◌֚◌̖◌〪b; a◌〪◌̠◌̖◌֚b; a◌〪◌̠◌̖◌֚b; a◌〪◌̠◌̖◌֚b; a◌〪◌̠◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MINUS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 031B 0062;0061 1DCE 031B 031B 1DFA 0062;0061 1DCE 031B 031B 1DFA 0062;0061 1DCE 031B 031B 1DFA 0062;0061 1DCE 031B 031B 1DFA 0062; # (a◌᷺◌̛◌᷎◌̛b; a◌᷎◌̛◌̛◌᷺b; a◌᷎◌̛◌̛◌᷺b; a◌᷎◌̛◌̛◌᷺b; a◌᷎◌̛◌̛◌᷺b; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, COMBINING HORN, LATIN SMALL LETTER B
+0061 031B 1DFA 031B 1DCE 0062;0061 1DCE 031B 031B 1DFA 0062;0061 1DCE 031B 031B 1DFA 0062;0061 1DCE 031B 031B 1DFA 0062;0061 1DCE 031B 031B 1DFA 0062; # (a◌̛◌᷺◌̛◌᷎b; a◌᷎◌̛◌̛◌᷺b; a◌᷎◌̛◌̛◌᷺b; a◌᷎◌̛◌̛◌᷺b; a◌᷎◌̛◌̛◌᷺b; ) LATIN SMALL LETTER A, COMBINING HORN, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 031C 0062;0061 1DFA 0316 031C 059A 0062;0061 1DFA 0316 031C 059A 0062;0061 1DFA 0316 031C 059A 0062;0061 1DFA 0316 031C 059A 0062; # (a◌֚◌̖◌᷺◌̜b; a◌᷺◌̖◌̜◌֚b; a◌᷺◌̖◌̜◌֚b; a◌᷺◌̖◌̜◌֚b; a◌᷺◌̖◌̜◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT HALF RING BELOW, LATIN SMALL LETTER B
+0061 031C 059A 0316 1DFA 0062;0061 1DFA 031C 0316 059A 0062;0061 1DFA 031C 0316 059A 0062;0061 1DFA 031C 0316 059A 0062;0061 1DFA 031C 0316 059A 0062; # (a◌̜◌֚◌̖◌᷺b; a◌᷺◌̜◌̖◌֚b; a◌᷺◌̜◌̖◌֚b; a◌᷺◌̜◌̖◌֚b; a◌᷺◌̜◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT HALF RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 031D 0062;0061 1DFA 0316 031D 059A 0062;0061 1DFA 0316 031D 059A 0062;0061 1DFA 0316 031D 059A 0062;0061 1DFA 0316 031D 059A 0062; # (a◌֚◌̖◌᷺◌Ìb; a◌᷺◌̖◌Ì◌֚b; a◌᷺◌̖◌Ì◌֚b; a◌᷺◌̖◌Ì◌֚b; a◌᷺◌̖◌Ì◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING UP TACK BELOW, LATIN SMALL LETTER B
+0061 031D 059A 0316 1DFA 0062;0061 1DFA 031D 0316 059A 0062;0061 1DFA 031D 0316 059A 0062;0061 1DFA 031D 0316 059A 0062;0061 1DFA 031D 0316 059A 0062; # (aâ—ŒÌ◌֚◌̖◌᷺b; a◌᷺◌Ì◌̖◌֚b; a◌᷺◌Ì◌̖◌֚b; a◌᷺◌Ì◌̖◌֚b; a◌᷺◌Ì◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING UP TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 031E 0062;0061 1DFA 0316 031E 059A 0062;0061 1DFA 0316 031E 059A 0062;0061 1DFA 0316 031E 059A 0062;0061 1DFA 0316 031E 059A 0062; # (a◌֚◌̖◌᷺◌̞b; a◌᷺◌̖◌̞◌֚b; a◌᷺◌̖◌̞◌֚b; a◌᷺◌̖◌̞◌֚b; a◌᷺◌̖◌̞◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOWN TACK BELOW, LATIN SMALL LETTER B
+0061 031E 059A 0316 1DFA 0062;0061 1DFA 031E 0316 059A 0062;0061 1DFA 031E 0316 059A 0062;0061 1DFA 031E 0316 059A 0062;0061 1DFA 031E 0316 059A 0062; # (a◌̞◌֚◌̖◌᷺b; a◌᷺◌̞◌̖◌֚b; a◌᷺◌̞◌̖◌֚b; a◌᷺◌̞◌̖◌֚b; a◌᷺◌̞◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOWN TACK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 031F 0062;0061 1DFA 0316 031F 059A 0062;0061 1DFA 0316 031F 059A 0062;0061 1DFA 0316 031F 059A 0062;0061 1DFA 0316 031F 059A 0062; # (a◌֚◌̖◌᷺◌̟b; a◌᷺◌̖◌̟◌֚b; a◌᷺◌̖◌̟◌֚b; a◌᷺◌̖◌̟◌֚b; a◌᷺◌̖◌̟◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING PLUS SIGN BELOW, LATIN SMALL LETTER B
+0061 031F 059A 0316 1DFA 0062;0061 1DFA 031F 0316 059A 0062;0061 1DFA 031F 0316 059A 0062;0061 1DFA 031F 0316 059A 0062;0061 1DFA 031F 0316 059A 0062; # (a◌̟◌֚◌̖◌᷺b; a◌᷺◌̟◌̖◌֚b; a◌᷺◌̟◌̖◌֚b; a◌᷺◌̟◌̖◌֚b; a◌᷺◌̟◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING PLUS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0320 0062;0061 1DFA 0316 0320 059A 0062;0061 1DFA 0316 0320 059A 0062;0061 1DFA 0316 0320 059A 0062;0061 1DFA 0316 0320 059A 0062; # (a◌֚◌̖◌᷺◌̠b; a◌᷺◌̖◌̠◌֚b; a◌᷺◌̖◌̠◌֚b; a◌᷺◌̖◌̠◌֚b; a◌᷺◌̖◌̠◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING MINUS SIGN BELOW, LATIN SMALL LETTER B
+0061 0320 059A 0316 1DFA 0062;0061 1DFA 0320 0316 059A 0062;0061 1DFA 0320 0316 059A 0062;0061 1DFA 0320 0316 059A 0062;0061 1DFA 0320 0316 059A 0062; # (a◌̠◌֚◌̖◌᷺b; a◌᷺◌̠◌̖◌֚b; a◌᷺◌̠◌̖◌֚b; a◌᷺◌̠◌̖◌֚b; a◌᷺◌̠◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MINUS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 1DCE 0321 0F74 0321 0062;0061 0F74 0321 0321 1DCE 0062;0061 0F74 0321 0321 1DCE 0062;0061 0F74 0321 0321 1DCE 0062;0061 0F74 0321 0321 1DCE 0062; # (a◌᷎◌̡◌ུ◌̡b; a◌ུ◌̡◌̡◌᷎b; a◌ུ◌̡◌̡◌᷎b; a◌ུ◌̡◌̡◌᷎b; a◌ུ◌̡◌̡◌᷎b; ) LATIN SMALL LETTER A, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, COMBINING PALATALIZED HOOK BELOW, LATIN SMALL LETTER B
0061 0321 1DCE 0321 0F74 0062;0061 0F74 0321 0321 1DCE 0062;0061 0F74 0321 0321 1DCE 0062;0061 0F74 0321 0321 1DCE 0062;0061 0F74 0321 0321 1DCE 0062; # (a◌̡◌᷎◌̡◌ུb; a◌ུ◌̡◌̡◌᷎b; a◌ུ◌̡◌̡◌᷎b; a◌ུ◌̡◌̡◌᷎b; a◌ུ◌̡◌̡◌᷎b; ) LATIN SMALL LETTER A, COMBINING PALATALIZED HOOK BELOW, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, LATIN SMALL LETTER B
0061 1DCE 0321 0F74 0322 0062;0061 0F74 0321 0322 1DCE 0062;0061 0F74 0321 0322 1DCE 0062;0061 0F74 0321 0322 1DCE 0062;0061 0F74 0321 0322 1DCE 0062; # (a◌᷎◌̡◌ུ◌̢b; a◌ུ◌̡◌̢◌᷎b; a◌ུ◌̡◌̢◌᷎b; a◌ུ◌̡◌̢◌᷎b; a◌ུ◌̡◌̢◌᷎b; ) LATIN SMALL LETTER A, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, COMBINING RETROFLEX HOOK BELOW, LATIN SMALL LETTER B
0061 0322 1DCE 0321 0F74 0062;0061 0F74 0322 0321 1DCE 0062;0061 0F74 0322 0321 1DCE 0062;0061 0F74 0322 0321 1DCE 0062;0061 0F74 0322 0321 1DCE 0062; # (a◌̢◌᷎◌̡◌ུb; a◌ུ◌̢◌̡◌᷎b; a◌ུ◌̢◌̡◌᷎b; a◌ུ◌̢◌̡◌᷎b; a◌ུ◌̢◌̡◌᷎b; ) LATIN SMALL LETTER A, COMBINING RETROFLEX HOOK BELOW, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, LATIN SMALL LETTER B
-0061 059A 0316 302A 0323 0062;0061 302A 0316 0323 059A 0062;0061 302A 0316 0323 059A 0062;0061 302A 0316 0323 059A 0062;0061 302A 0316 0323 059A 0062; # (a◌֚◌̖◌〪◌̣b; a◌〪◌̖◌̣◌֚b; a◌〪◌̖◌̣◌֚b; a◌〪◌̖◌̣◌֚b; a◌〪◌̖◌̣◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DOT BELOW, LATIN SMALL LETTER B
-0061 0323 059A 0316 302A 0062;1EA1 302A 0316 059A 0062;0061 302A 0323 0316 059A 0062;1EA1 302A 0316 059A 0062;0061 302A 0323 0316 059A 0062; # (a◌̣◌֚◌̖◌〪b; ạ◌〪◌̖◌֚b; a◌〪◌̣◌̖◌֚b; ạ◌〪◌̖◌֚b; a◌〪◌̣◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0324 0062;0061 302A 0316 0324 059A 0062;0061 302A 0316 0324 059A 0062;0061 302A 0316 0324 059A 0062;0061 302A 0316 0324 059A 0062; # (a◌֚◌̖◌〪◌̤b; a◌〪◌̖◌̤◌֚b; a◌〪◌̖◌̤◌֚b; a◌〪◌̖◌̤◌֚b; a◌〪◌̖◌̤◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DIAERESIS BELOW, LATIN SMALL LETTER B
-0061 0324 059A 0316 302A 0062;0061 302A 0324 0316 059A 0062;0061 302A 0324 0316 059A 0062;0061 302A 0324 0316 059A 0062;0061 302A 0324 0316 059A 0062; # (a◌̤◌֚◌̖◌〪b; a◌〪◌̤◌̖◌֚b; a◌〪◌̤◌̖◌֚b; a◌〪◌̤◌̖◌֚b; a◌〪◌̤◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DIAERESIS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0325 0062;0061 302A 0316 0325 059A 0062;0061 302A 0316 0325 059A 0062;0061 302A 0316 0325 059A 0062;0061 302A 0316 0325 059A 0062; # (a◌֚◌̖◌〪◌̥b; a◌〪◌̖◌̥◌֚b; a◌〪◌̖◌̥◌֚b; a◌〪◌̖◌̥◌֚b; a◌〪◌̖◌̥◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RING BELOW, LATIN SMALL LETTER B
-0061 0325 059A 0316 302A 0062;1E01 302A 0316 059A 0062;0061 302A 0325 0316 059A 0062;1E01 302A 0316 059A 0062;0061 302A 0325 0316 059A 0062; # (a◌̥◌֚◌̖◌〪b; á¸â—Œã€ªâ—ŒÌ–◌֚b; a◌〪◌̥◌̖◌֚b; á¸â—Œã€ªâ—ŒÌ–◌֚b; a◌〪◌̥◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0326 0062;0061 302A 0316 0326 059A 0062;0061 302A 0316 0326 059A 0062;0061 302A 0316 0326 059A 0062;0061 302A 0316 0326 059A 0062; # (a◌֚◌̖◌〪◌̦b; a◌〪◌̖◌̦◌֚b; a◌〪◌̖◌̦◌֚b; a◌〪◌̖◌̦◌֚b; a◌〪◌̖◌̦◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING COMMA BELOW, LATIN SMALL LETTER B
-0061 0326 059A 0316 302A 0062;0061 302A 0326 0316 059A 0062;0061 302A 0326 0316 059A 0062;0061 302A 0326 0316 059A 0062;0061 302A 0326 0316 059A 0062; # (a◌̦◌֚◌̖◌〪b; a◌〪◌̦◌̖◌֚b; a◌〪◌̦◌̖◌֚b; a◌〪◌̦◌̖◌֚b; a◌〪◌̦◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING COMMA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0323 0062;0061 1DFA 0316 0323 059A 0062;0061 1DFA 0316 0323 059A 0062;0061 1DFA 0316 0323 059A 0062;0061 1DFA 0316 0323 059A 0062; # (a◌֚◌̖◌᷺◌̣b; a◌᷺◌̖◌̣◌֚b; a◌᷺◌̖◌̣◌֚b; a◌᷺◌̖◌̣◌֚b; a◌᷺◌̖◌̣◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOT BELOW, LATIN SMALL LETTER B
+0061 0323 059A 0316 1DFA 0062;1EA1 1DFA 0316 059A 0062;0061 1DFA 0323 0316 059A 0062;1EA1 1DFA 0316 059A 0062;0061 1DFA 0323 0316 059A 0062; # (a◌̣◌֚◌̖◌᷺b; ạ◌᷺◌̖◌֚b; a◌᷺◌̣◌̖◌֚b; ạ◌᷺◌̖◌֚b; a◌᷺◌̣◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0324 0062;0061 1DFA 0316 0324 059A 0062;0061 1DFA 0316 0324 059A 0062;0061 1DFA 0316 0324 059A 0062;0061 1DFA 0316 0324 059A 0062; # (a◌֚◌̖◌᷺◌̤b; a◌᷺◌̖◌̤◌֚b; a◌᷺◌̖◌̤◌֚b; a◌᷺◌̖◌̤◌֚b; a◌᷺◌̖◌̤◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DIAERESIS BELOW, LATIN SMALL LETTER B
+0061 0324 059A 0316 1DFA 0062;0061 1DFA 0324 0316 059A 0062;0061 1DFA 0324 0316 059A 0062;0061 1DFA 0324 0316 059A 0062;0061 1DFA 0324 0316 059A 0062; # (a◌̤◌֚◌̖◌᷺b; a◌᷺◌̤◌̖◌֚b; a◌᷺◌̤◌̖◌֚b; a◌᷺◌̤◌̖◌֚b; a◌᷺◌̤◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DIAERESIS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0325 0062;0061 1DFA 0316 0325 059A 0062;0061 1DFA 0316 0325 059A 0062;0061 1DFA 0316 0325 059A 0062;0061 1DFA 0316 0325 059A 0062; # (a◌֚◌̖◌᷺◌̥b; a◌᷺◌̖◌̥◌֚b; a◌᷺◌̖◌̥◌֚b; a◌᷺◌̖◌̥◌֚b; a◌᷺◌̖◌̥◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RING BELOW, LATIN SMALL LETTER B
+0061 0325 059A 0316 1DFA 0062;1E01 1DFA 0316 059A 0062;0061 1DFA 0325 0316 059A 0062;1E01 1DFA 0316 059A 0062;0061 1DFA 0325 0316 059A 0062; # (a◌̥◌֚◌̖◌᷺b; á¸â—Œá·ºâ—ŒÌ–◌֚b; a◌᷺◌̥◌̖◌֚b; á¸â—Œá·ºâ—ŒÌ–◌֚b; a◌᷺◌̥◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0326 0062;0061 1DFA 0316 0326 059A 0062;0061 1DFA 0316 0326 059A 0062;0061 1DFA 0316 0326 059A 0062;0061 1DFA 0316 0326 059A 0062; # (a◌֚◌̖◌᷺◌̦b; a◌᷺◌̖◌̦◌֚b; a◌᷺◌̖◌̦◌֚b; a◌᷺◌̖◌̦◌֚b; a◌᷺◌̖◌̦◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING COMMA BELOW, LATIN SMALL LETTER B
+0061 0326 059A 0316 1DFA 0062;0061 1DFA 0326 0316 059A 0062;0061 1DFA 0326 0316 059A 0062;0061 1DFA 0326 0316 059A 0062;0061 1DFA 0326 0316 059A 0062; # (a◌̦◌֚◌̖◌᷺b; a◌᷺◌̦◌̖◌֚b; a◌᷺◌̦◌̖◌֚b; a◌᷺◌̦◌̖◌֚b; a◌᷺◌̦◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING COMMA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 1DCE 0321 0F74 0327 0062;0061 0F74 0321 0327 1DCE 0062;0061 0F74 0321 0327 1DCE 0062;0061 0F74 0321 0327 1DCE 0062;0061 0F74 0321 0327 1DCE 0062; # (a◌᷎◌̡◌ུ◌̧b; a◌ུ◌̡◌̧◌᷎b; a◌ུ◌̡◌̧◌᷎b; a◌ུ◌̡◌̧◌᷎b; a◌ུ◌̡◌̧◌᷎b; ) LATIN SMALL LETTER A, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, COMBINING CEDILLA, LATIN SMALL LETTER B
0061 0327 1DCE 0321 0F74 0062;0061 0F74 0327 0321 1DCE 0062;0061 0F74 0327 0321 1DCE 0062;0061 0F74 0327 0321 1DCE 0062;0061 0F74 0327 0321 1DCE 0062; # (a◌̧◌᷎◌̡◌ུb; a◌ུ◌̧◌̡◌᷎b; a◌ུ◌̧◌̡◌᷎b; a◌ུ◌̧◌̡◌᷎b; a◌ུ◌̧◌̡◌᷎b; ) LATIN SMALL LETTER A, COMBINING CEDILLA, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, LATIN SMALL LETTER B
0061 1DCE 0321 0F74 0328 0062;0061 0F74 0321 0328 1DCE 0062;0061 0F74 0321 0328 1DCE 0062;0061 0F74 0321 0328 1DCE 0062;0061 0F74 0321 0328 1DCE 0062; # (a◌᷎◌̡◌ུ◌̨b; a◌ུ◌̡◌̨◌᷎b; a◌ུ◌̡◌̨◌᷎b; a◌ུ◌̡◌̨◌᷎b; a◌ུ◌̡◌̨◌᷎b; ) LATIN SMALL LETTER A, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, COMBINING OGONEK, LATIN SMALL LETTER B
0061 0328 1DCE 0321 0F74 0062;0105 0F74 0321 1DCE 0062;0061 0F74 0328 0321 1DCE 0062;0105 0F74 0321 1DCE 0062;0061 0F74 0328 0321 1DCE 0062; # (a◌̨◌᷎◌̡◌ུb; ą◌ུ◌̡◌᷎b; a◌ུ◌̨◌̡◌᷎b; ą◌ུ◌̡◌᷎b; a◌ུ◌̨◌̡◌᷎b; ) LATIN SMALL LETTER A, COMBINING OGONEK, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, LATIN SMALL LETTER B
-0061 059A 0316 302A 0329 0062;0061 302A 0316 0329 059A 0062;0061 302A 0316 0329 059A 0062;0061 302A 0316 0329 059A 0062;0061 302A 0316 0329 059A 0062; # (a◌֚◌̖◌〪◌̩b; a◌〪◌̖◌̩◌֚b; a◌〪◌̖◌̩◌֚b; a◌〪◌̖◌̩◌֚b; a◌〪◌̖◌̩◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING VERTICAL LINE BELOW, LATIN SMALL LETTER B
-0061 0329 059A 0316 302A 0062;0061 302A 0329 0316 059A 0062;0061 302A 0329 0316 059A 0062;0061 302A 0329 0316 059A 0062;0061 302A 0329 0316 059A 0062; # (a◌̩◌֚◌̖◌〪b; a◌〪◌̩◌̖◌֚b; a◌〪◌̩◌̖◌֚b; a◌〪◌̩◌̖◌֚b; a◌〪◌̩◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING VERTICAL LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 032A 0062;0061 302A 0316 032A 059A 0062;0061 302A 0316 032A 059A 0062;0061 302A 0316 032A 059A 0062;0061 302A 0316 032A 059A 0062; # (a◌֚◌̖◌〪◌̪b; a◌〪◌̖◌̪◌֚b; a◌〪◌̖◌̪◌֚b; a◌〪◌̖◌̪◌֚b; a◌〪◌̖◌̪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING BRIDGE BELOW, LATIN SMALL LETTER B
-0061 032A 059A 0316 302A 0062;0061 302A 032A 0316 059A 0062;0061 302A 032A 0316 059A 0062;0061 302A 032A 0316 059A 0062;0061 302A 032A 0316 059A 0062; # (a◌̪◌֚◌̖◌〪b; a◌〪◌̪◌̖◌֚b; a◌〪◌̪◌̖◌֚b; a◌〪◌̪◌̖◌֚b; a◌〪◌̪◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 032B 0062;0061 302A 0316 032B 059A 0062;0061 302A 0316 032B 059A 0062;0061 302A 0316 032B 059A 0062;0061 302A 0316 032B 059A 0062; # (a◌֚◌̖◌〪◌̫b; a◌〪◌̖◌̫◌֚b; a◌〪◌̖◌̫◌֚b; a◌〪◌̖◌̫◌֚b; a◌〪◌̖◌̫◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING INVERTED DOUBLE ARCH BELOW, LATIN SMALL LETTER B
-0061 032B 059A 0316 302A 0062;0061 302A 032B 0316 059A 0062;0061 302A 032B 0316 059A 0062;0061 302A 032B 0316 059A 0062;0061 302A 032B 0316 059A 0062; # (a◌̫◌֚◌̖◌〪b; a◌〪◌̫◌̖◌֚b; a◌〪◌̫◌̖◌֚b; a◌〪◌̫◌̖◌֚b; a◌〪◌̫◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING INVERTED DOUBLE ARCH BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 032C 0062;0061 302A 0316 032C 059A 0062;0061 302A 0316 032C 059A 0062;0061 302A 0316 032C 059A 0062;0061 302A 0316 032C 059A 0062; # (a◌֚◌̖◌〪◌̬b; a◌〪◌̖◌̬◌֚b; a◌〪◌̖◌̬◌֚b; a◌〪◌̖◌̬◌֚b; a◌〪◌̖◌̬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING CARON BELOW, LATIN SMALL LETTER B
-0061 032C 059A 0316 302A 0062;0061 302A 032C 0316 059A 0062;0061 302A 032C 0316 059A 0062;0061 302A 032C 0316 059A 0062;0061 302A 032C 0316 059A 0062; # (a◌̬◌֚◌̖◌〪b; a◌〪◌̬◌̖◌֚b; a◌〪◌̬◌̖◌֚b; a◌〪◌̬◌̖◌֚b; a◌〪◌̬◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING CARON BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 032D 0062;0061 302A 0316 032D 059A 0062;0061 302A 0316 032D 059A 0062;0061 302A 0316 032D 059A 0062;0061 302A 0316 032D 059A 0062; # (a◌֚◌̖◌〪◌̭b; a◌〪◌̖◌̭◌֚b; a◌〪◌̖◌̭◌֚b; a◌〪◌̖◌̭◌֚b; a◌〪◌̖◌̭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING CIRCUMFLEX ACCENT BELOW, LATIN SMALL LETTER B
-0061 032D 059A 0316 302A 0062;0061 302A 032D 0316 059A 0062;0061 302A 032D 0316 059A 0062;0061 302A 032D 0316 059A 0062;0061 302A 032D 0316 059A 0062; # (a◌̭◌֚◌̖◌〪b; a◌〪◌̭◌̖◌֚b; a◌〪◌̭◌̖◌֚b; a◌〪◌̭◌̖◌֚b; a◌〪◌̭◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING CIRCUMFLEX ACCENT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 032E 0062;0061 302A 0316 032E 059A 0062;0061 302A 0316 032E 059A 0062;0061 302A 0316 032E 059A 0062;0061 302A 0316 032E 059A 0062; # (a◌֚◌̖◌〪◌̮b; a◌〪◌̖◌̮◌֚b; a◌〪◌̖◌̮◌֚b; a◌〪◌̖◌̮◌֚b; a◌〪◌̖◌̮◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING BREVE BELOW, LATIN SMALL LETTER B
-0061 032E 059A 0316 302A 0062;0061 302A 032E 0316 059A 0062;0061 302A 032E 0316 059A 0062;0061 302A 032E 0316 059A 0062;0061 302A 032E 0316 059A 0062; # (a◌̮◌֚◌̖◌〪b; a◌〪◌̮◌̖◌֚b; a◌〪◌̮◌̖◌֚b; a◌〪◌̮◌̖◌֚b; a◌〪◌̮◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING BREVE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 032F 0062;0061 302A 0316 032F 059A 0062;0061 302A 0316 032F 059A 0062;0061 302A 0316 032F 059A 0062;0061 302A 0316 032F 059A 0062; # (a◌֚◌̖◌〪◌̯b; a◌〪◌̖◌̯◌֚b; a◌〪◌̖◌̯◌֚b; a◌〪◌̖◌̯◌֚b; a◌〪◌̖◌̯◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING INVERTED BREVE BELOW, LATIN SMALL LETTER B
-0061 032F 059A 0316 302A 0062;0061 302A 032F 0316 059A 0062;0061 302A 032F 0316 059A 0062;0061 302A 032F 0316 059A 0062;0061 302A 032F 0316 059A 0062; # (a◌̯◌֚◌̖◌〪b; a◌〪◌̯◌̖◌֚b; a◌〪◌̯◌̖◌֚b; a◌〪◌̯◌̖◌֚b; a◌〪◌̯◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING INVERTED BREVE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0330 0062;0061 302A 0316 0330 059A 0062;0061 302A 0316 0330 059A 0062;0061 302A 0316 0330 059A 0062;0061 302A 0316 0330 059A 0062; # (a◌֚◌̖◌〪◌̰b; a◌〪◌̖◌̰◌֚b; a◌〪◌̖◌̰◌֚b; a◌〪◌̖◌̰◌֚b; a◌〪◌̖◌̰◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING TILDE BELOW, LATIN SMALL LETTER B
-0061 0330 059A 0316 302A 0062;0061 302A 0330 0316 059A 0062;0061 302A 0330 0316 059A 0062;0061 302A 0330 0316 059A 0062;0061 302A 0330 0316 059A 0062; # (a◌̰◌֚◌̖◌〪b; a◌〪◌̰◌̖◌֚b; a◌〪◌̰◌̖◌֚b; a◌〪◌̰◌̖◌֚b; a◌〪◌̰◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TILDE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0331 0062;0061 302A 0316 0331 059A 0062;0061 302A 0316 0331 059A 0062;0061 302A 0316 0331 059A 0062;0061 302A 0316 0331 059A 0062; # (a◌֚◌̖◌〪◌̱b; a◌〪◌̖◌̱◌֚b; a◌〪◌̖◌̱◌֚b; a◌〪◌̖◌̱◌֚b; a◌〪◌̖◌̱◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING MACRON BELOW, LATIN SMALL LETTER B
-0061 0331 059A 0316 302A 0062;0061 302A 0331 0316 059A 0062;0061 302A 0331 0316 059A 0062;0061 302A 0331 0316 059A 0062;0061 302A 0331 0316 059A 0062; # (a◌̱◌֚◌̖◌〪b; a◌〪◌̱◌̖◌֚b; a◌〪◌̱◌̖◌֚b; a◌〪◌̱◌̖◌֚b; a◌〪◌̱◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MACRON BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0332 0062;0061 302A 0316 0332 059A 0062;0061 302A 0316 0332 059A 0062;0061 302A 0316 0332 059A 0062;0061 302A 0316 0332 059A 0062; # (a◌֚◌̖◌〪◌̲b; a◌〪◌̖◌̲◌֚b; a◌〪◌̖◌̲◌֚b; a◌〪◌̖◌̲◌֚b; a◌〪◌̖◌̲◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LOW LINE, LATIN SMALL LETTER B
-0061 0332 059A 0316 302A 0062;0061 302A 0332 0316 059A 0062;0061 302A 0332 0316 059A 0062;0061 302A 0332 0316 059A 0062;0061 302A 0332 0316 059A 0062; # (a◌̲◌֚◌̖◌〪b; a◌〪◌̲◌̖◌֚b; a◌〪◌̲◌̖◌֚b; a◌〪◌̲◌̖◌֚b; a◌〪◌̲◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LOW LINE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0333 0062;0061 302A 0316 0333 059A 0062;0061 302A 0316 0333 059A 0062;0061 302A 0316 0333 059A 0062;0061 302A 0316 0333 059A 0062; # (a◌֚◌̖◌〪◌̳b; a◌〪◌̖◌̳◌֚b; a◌〪◌̖◌̳◌֚b; a◌〪◌̖◌̳◌֚b; a◌〪◌̖◌̳◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DOUBLE LOW LINE, LATIN SMALL LETTER B
-0061 0333 059A 0316 302A 0062;0061 302A 0333 0316 059A 0062;0061 302A 0333 0316 059A 0062;0061 302A 0333 0316 059A 0062;0061 302A 0333 0316 059A 0062; # (a◌̳◌֚◌̖◌〪b; a◌〪◌̳◌̖◌֚b; a◌〪◌̳◌̖◌֚b; a◌〪◌̳◌̖◌֚b; a◌〪◌̳◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE LOW LINE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0329 0062;0061 1DFA 0316 0329 059A 0062;0061 1DFA 0316 0329 059A 0062;0061 1DFA 0316 0329 059A 0062;0061 1DFA 0316 0329 059A 0062; # (a◌֚◌̖◌᷺◌̩b; a◌᷺◌̖◌̩◌֚b; a◌᷺◌̖◌̩◌֚b; a◌᷺◌̖◌̩◌֚b; a◌᷺◌̖◌̩◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING VERTICAL LINE BELOW, LATIN SMALL LETTER B
+0061 0329 059A 0316 1DFA 0062;0061 1DFA 0329 0316 059A 0062;0061 1DFA 0329 0316 059A 0062;0061 1DFA 0329 0316 059A 0062;0061 1DFA 0329 0316 059A 0062; # (a◌̩◌֚◌̖◌᷺b; a◌᷺◌̩◌̖◌֚b; a◌᷺◌̩◌̖◌֚b; a◌᷺◌̩◌̖◌֚b; a◌᷺◌̩◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING VERTICAL LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 032A 0062;0061 1DFA 0316 032A 059A 0062;0061 1DFA 0316 032A 059A 0062;0061 1DFA 0316 032A 059A 0062;0061 1DFA 0316 032A 059A 0062; # (a◌֚◌̖◌᷺◌̪b; a◌᷺◌̖◌̪◌֚b; a◌᷺◌̖◌̪◌֚b; a◌᷺◌̖◌̪◌֚b; a◌᷺◌̖◌̪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING BRIDGE BELOW, LATIN SMALL LETTER B
+0061 032A 059A 0316 1DFA 0062;0061 1DFA 032A 0316 059A 0062;0061 1DFA 032A 0316 059A 0062;0061 1DFA 032A 0316 059A 0062;0061 1DFA 032A 0316 059A 0062; # (a◌̪◌֚◌̖◌᷺b; a◌᷺◌̪◌̖◌֚b; a◌᷺◌̪◌̖◌֚b; a◌᷺◌̪◌̖◌֚b; a◌᷺◌̪◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 032B 0062;0061 1DFA 0316 032B 059A 0062;0061 1DFA 0316 032B 059A 0062;0061 1DFA 0316 032B 059A 0062;0061 1DFA 0316 032B 059A 0062; # (a◌֚◌̖◌᷺◌̫b; a◌᷺◌̖◌̫◌֚b; a◌᷺◌̖◌̫◌֚b; a◌᷺◌̖◌̫◌֚b; a◌᷺◌̖◌̫◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING INVERTED DOUBLE ARCH BELOW, LATIN SMALL LETTER B
+0061 032B 059A 0316 1DFA 0062;0061 1DFA 032B 0316 059A 0062;0061 1DFA 032B 0316 059A 0062;0061 1DFA 032B 0316 059A 0062;0061 1DFA 032B 0316 059A 0062; # (a◌̫◌֚◌̖◌᷺b; a◌᷺◌̫◌̖◌֚b; a◌᷺◌̫◌̖◌֚b; a◌᷺◌̫◌̖◌֚b; a◌᷺◌̫◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING INVERTED DOUBLE ARCH BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 032C 0062;0061 1DFA 0316 032C 059A 0062;0061 1DFA 0316 032C 059A 0062;0061 1DFA 0316 032C 059A 0062;0061 1DFA 0316 032C 059A 0062; # (a◌֚◌̖◌᷺◌̬b; a◌᷺◌̖◌̬◌֚b; a◌᷺◌̖◌̬◌֚b; a◌᷺◌̖◌̬◌֚b; a◌᷺◌̖◌̬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING CARON BELOW, LATIN SMALL LETTER B
+0061 032C 059A 0316 1DFA 0062;0061 1DFA 032C 0316 059A 0062;0061 1DFA 032C 0316 059A 0062;0061 1DFA 032C 0316 059A 0062;0061 1DFA 032C 0316 059A 0062; # (a◌̬◌֚◌̖◌᷺b; a◌᷺◌̬◌̖◌֚b; a◌᷺◌̬◌̖◌֚b; a◌᷺◌̬◌̖◌֚b; a◌᷺◌̬◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING CARON BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 032D 0062;0061 1DFA 0316 032D 059A 0062;0061 1DFA 0316 032D 059A 0062;0061 1DFA 0316 032D 059A 0062;0061 1DFA 0316 032D 059A 0062; # (a◌֚◌̖◌᷺◌̭b; a◌᷺◌̖◌̭◌֚b; a◌᷺◌̖◌̭◌֚b; a◌᷺◌̖◌̭◌֚b; a◌᷺◌̖◌̭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING CIRCUMFLEX ACCENT BELOW, LATIN SMALL LETTER B
+0061 032D 059A 0316 1DFA 0062;0061 1DFA 032D 0316 059A 0062;0061 1DFA 032D 0316 059A 0062;0061 1DFA 032D 0316 059A 0062;0061 1DFA 032D 0316 059A 0062; # (a◌̭◌֚◌̖◌᷺b; a◌᷺◌̭◌̖◌֚b; a◌᷺◌̭◌̖◌֚b; a◌᷺◌̭◌̖◌֚b; a◌᷺◌̭◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING CIRCUMFLEX ACCENT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 032E 0062;0061 1DFA 0316 032E 059A 0062;0061 1DFA 0316 032E 059A 0062;0061 1DFA 0316 032E 059A 0062;0061 1DFA 0316 032E 059A 0062; # (a◌֚◌̖◌᷺◌̮b; a◌᷺◌̖◌̮◌֚b; a◌᷺◌̖◌̮◌֚b; a◌᷺◌̖◌̮◌֚b; a◌᷺◌̖◌̮◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING BREVE BELOW, LATIN SMALL LETTER B
+0061 032E 059A 0316 1DFA 0062;0061 1DFA 032E 0316 059A 0062;0061 1DFA 032E 0316 059A 0062;0061 1DFA 032E 0316 059A 0062;0061 1DFA 032E 0316 059A 0062; # (a◌̮◌֚◌̖◌᷺b; a◌᷺◌̮◌̖◌֚b; a◌᷺◌̮◌̖◌֚b; a◌᷺◌̮◌̖◌֚b; a◌᷺◌̮◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING BREVE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 032F 0062;0061 1DFA 0316 032F 059A 0062;0061 1DFA 0316 032F 059A 0062;0061 1DFA 0316 032F 059A 0062;0061 1DFA 0316 032F 059A 0062; # (a◌֚◌̖◌᷺◌̯b; a◌᷺◌̖◌̯◌֚b; a◌᷺◌̖◌̯◌֚b; a◌᷺◌̖◌̯◌֚b; a◌᷺◌̖◌̯◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING INVERTED BREVE BELOW, LATIN SMALL LETTER B
+0061 032F 059A 0316 1DFA 0062;0061 1DFA 032F 0316 059A 0062;0061 1DFA 032F 0316 059A 0062;0061 1DFA 032F 0316 059A 0062;0061 1DFA 032F 0316 059A 0062; # (a◌̯◌֚◌̖◌᷺b; a◌᷺◌̯◌̖◌֚b; a◌᷺◌̯◌̖◌֚b; a◌᷺◌̯◌̖◌֚b; a◌᷺◌̯◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING INVERTED BREVE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0330 0062;0061 1DFA 0316 0330 059A 0062;0061 1DFA 0316 0330 059A 0062;0061 1DFA 0316 0330 059A 0062;0061 1DFA 0316 0330 059A 0062; # (a◌֚◌̖◌᷺◌̰b; a◌᷺◌̖◌̰◌֚b; a◌᷺◌̖◌̰◌֚b; a◌᷺◌̖◌̰◌֚b; a◌᷺◌̖◌̰◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING TILDE BELOW, LATIN SMALL LETTER B
+0061 0330 059A 0316 1DFA 0062;0061 1DFA 0330 0316 059A 0062;0061 1DFA 0330 0316 059A 0062;0061 1DFA 0330 0316 059A 0062;0061 1DFA 0330 0316 059A 0062; # (a◌̰◌֚◌̖◌᷺b; a◌᷺◌̰◌̖◌֚b; a◌᷺◌̰◌̖◌֚b; a◌᷺◌̰◌̖◌֚b; a◌᷺◌̰◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TILDE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0331 0062;0061 1DFA 0316 0331 059A 0062;0061 1DFA 0316 0331 059A 0062;0061 1DFA 0316 0331 059A 0062;0061 1DFA 0316 0331 059A 0062; # (a◌֚◌̖◌᷺◌̱b; a◌᷺◌̖◌̱◌֚b; a◌᷺◌̖◌̱◌֚b; a◌᷺◌̖◌̱◌֚b; a◌᷺◌̖◌̱◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING MACRON BELOW, LATIN SMALL LETTER B
+0061 0331 059A 0316 1DFA 0062;0061 1DFA 0331 0316 059A 0062;0061 1DFA 0331 0316 059A 0062;0061 1DFA 0331 0316 059A 0062;0061 1DFA 0331 0316 059A 0062; # (a◌̱◌֚◌̖◌᷺b; a◌᷺◌̱◌̖◌֚b; a◌᷺◌̱◌̖◌֚b; a◌᷺◌̱◌̖◌֚b; a◌᷺◌̱◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MACRON BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0332 0062;0061 1DFA 0316 0332 059A 0062;0061 1DFA 0316 0332 059A 0062;0061 1DFA 0316 0332 059A 0062;0061 1DFA 0316 0332 059A 0062; # (a◌֚◌̖◌᷺◌̲b; a◌᷺◌̖◌̲◌֚b; a◌᷺◌̖◌̲◌֚b; a◌᷺◌̖◌̲◌֚b; a◌᷺◌̖◌̲◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LOW LINE, LATIN SMALL LETTER B
+0061 0332 059A 0316 1DFA 0062;0061 1DFA 0332 0316 059A 0062;0061 1DFA 0332 0316 059A 0062;0061 1DFA 0332 0316 059A 0062;0061 1DFA 0332 0316 059A 0062; # (a◌̲◌֚◌̖◌᷺b; a◌᷺◌̲◌̖◌֚b; a◌᷺◌̲◌̖◌֚b; a◌᷺◌̲◌̖◌֚b; a◌᷺◌̲◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LOW LINE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0333 0062;0061 1DFA 0316 0333 059A 0062;0061 1DFA 0316 0333 059A 0062;0061 1DFA 0316 0333 059A 0062;0061 1DFA 0316 0333 059A 0062; # (a◌֚◌̖◌᷺◌̳b; a◌᷺◌̖◌̳◌֚b; a◌᷺◌̖◌̳◌֚b; a◌᷺◌̖◌̳◌֚b; a◌᷺◌̖◌̳◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOUBLE LOW LINE, LATIN SMALL LETTER B
+0061 0333 059A 0316 1DFA 0062;0061 1DFA 0333 0316 059A 0062;0061 1DFA 0333 0316 059A 0062;0061 1DFA 0333 0316 059A 0062;0061 1DFA 0333 0316 059A 0062; # (a◌̳◌֚◌̖◌᷺b; a◌᷺◌̳◌̖◌֚b; a◌᷺◌̳◌̖◌֚b; a◌᷺◌̳◌̖◌֚b; a◌᷺◌̳◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE LOW LINE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 16FF0 0334 0334 0062;0061 0334 0334 16FF0 0062;0061 0334 0334 16FF0 0062;0061 0334 0334 16FF0 0062;0061 0334 0334 16FF0 0062; # (a𖿰◌̴◌̴b; a◌̴◌̴𖿰b; a◌̴◌̴𖿰b; a◌̴◌̴𖿰b; a◌̴◌̴𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 0334 16FF0 0334 0062;0061 0334 0334 16FF0 0062;0061 0334 0334 16FF0 0062;0061 0334 0334 16FF0 0062;0061 0334 0334 16FF0 0062; # (a◌̴𖿰◌̴b; a◌̴◌̴𖿰b; a◌̴◌̴𖿰b; a◌̴◌̴𖿰b; a◌̴◌̴𖿰b; ) LATIN SMALL LETTER A, COMBINING TILDE OVERLAY, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 0335 0062;0061 0334 0335 16FF0 0062;0061 0334 0335 16FF0 0062;0061 0334 0335 16FF0 0062;0061 0334 0335 16FF0 0062; # (a𖿰◌̴◌̵b; a◌̴◌̵𖿰b; a◌̴◌̵𖿰b; a◌̴◌̵𖿰b; a◌̴◌̵𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, COMBINING SHORT STROKE OVERLAY, LATIN SMALL LETTER B
@@ -17095,14 +17154,14 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0337 16FF0 0334 0062;0061 0337 0334 16FF0 0062;0061 0337 0334 16FF0 0062;0061 0337 0334 16FF0 0062;0061 0337 0334 16FF0 0062; # (a◌̷𖿰◌̴b; a◌̷◌̴𖿰b; a◌̷◌̴𖿰b; a◌̷◌̴𖿰b; a◌̷◌̴𖿰b; ) LATIN SMALL LETTER A, COMBINING SHORT SOLIDUS OVERLAY, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 0338 0062;0061 0334 0338 16FF0 0062;0061 0334 0338 16FF0 0062;0061 0334 0338 16FF0 0062;0061 0334 0338 16FF0 0062; # (a𖿰◌̴◌̸b; a◌̴◌̸𖿰b; a◌̴◌̸𖿰b; a◌̴◌̸𖿰b; a◌̴◌̸𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, COMBINING LONG SOLIDUS OVERLAY, LATIN SMALL LETTER B
0061 0338 16FF0 0334 0062;0061 0338 0334 16FF0 0062;0061 0338 0334 16FF0 0062;0061 0338 0334 16FF0 0062;0061 0338 0334 16FF0 0062; # (a◌̸𖿰◌̴b; a◌̸◌̴𖿰b; a◌̸◌̴𖿰b; a◌̸◌̴𖿰b; a◌̸◌̴𖿰b; ) LATIN SMALL LETTER A, COMBINING LONG SOLIDUS OVERLAY, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
-0061 059A 0316 302A 0339 0062;0061 302A 0316 0339 059A 0062;0061 302A 0316 0339 059A 0062;0061 302A 0316 0339 059A 0062;0061 302A 0316 0339 059A 0062; # (a◌֚◌̖◌〪◌̹b; a◌〪◌̖◌̹◌֚b; a◌〪◌̖◌̹◌֚b; a◌〪◌̖◌̹◌֚b; a◌〪◌̖◌̹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHT HALF RING BELOW, LATIN SMALL LETTER B
-0061 0339 059A 0316 302A 0062;0061 302A 0339 0316 059A 0062;0061 302A 0339 0316 059A 0062;0061 302A 0339 0316 059A 0062;0061 302A 0339 0316 059A 0062; # (a◌̹◌֚◌̖◌〪b; a◌〪◌̹◌̖◌֚b; a◌〪◌̹◌̖◌֚b; a◌〪◌̹◌̖◌֚b; a◌〪◌̹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT HALF RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 033A 0062;0061 302A 0316 033A 059A 0062;0061 302A 0316 033A 059A 0062;0061 302A 0316 033A 059A 0062;0061 302A 0316 033A 059A 0062; # (a◌֚◌̖◌〪◌̺b; a◌〪◌̖◌̺◌֚b; a◌〪◌̖◌̺◌֚b; a◌〪◌̖◌̺◌֚b; a◌〪◌̖◌̺◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING INVERTED BRIDGE BELOW, LATIN SMALL LETTER B
-0061 033A 059A 0316 302A 0062;0061 302A 033A 0316 059A 0062;0061 302A 033A 0316 059A 0062;0061 302A 033A 0316 059A 0062;0061 302A 033A 0316 059A 0062; # (a◌̺◌֚◌̖◌〪b; a◌〪◌̺◌̖◌֚b; a◌〪◌̺◌̖◌֚b; a◌〪◌̺◌̖◌֚b; a◌〪◌̺◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING INVERTED BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 033B 0062;0061 302A 0316 033B 059A 0062;0061 302A 0316 033B 059A 0062;0061 302A 0316 033B 059A 0062;0061 302A 0316 033B 059A 0062; # (a◌֚◌̖◌〪◌̻b; a◌〪◌̖◌̻◌֚b; a◌〪◌̖◌̻◌֚b; a◌〪◌̖◌̻◌֚b; a◌〪◌̖◌̻◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING SQUARE BELOW, LATIN SMALL LETTER B
-0061 033B 059A 0316 302A 0062;0061 302A 033B 0316 059A 0062;0061 302A 033B 0316 059A 0062;0061 302A 033B 0316 059A 0062;0061 302A 033B 0316 059A 0062; # (a◌̻◌֚◌̖◌〪b; a◌〪◌̻◌̖◌֚b; a◌〪◌̻◌̖◌֚b; a◌〪◌̻◌̖◌֚b; a◌〪◌̻◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING SQUARE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 033C 0062;0061 302A 0316 033C 059A 0062;0061 302A 0316 033C 059A 0062;0061 302A 0316 033C 059A 0062;0061 302A 0316 033C 059A 0062; # (a◌֚◌̖◌〪◌̼b; a◌〪◌̖◌̼◌֚b; a◌〪◌̖◌̼◌֚b; a◌〪◌̖◌̼◌֚b; a◌〪◌̖◌̼◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING SEAGULL BELOW, LATIN SMALL LETTER B
-0061 033C 059A 0316 302A 0062;0061 302A 033C 0316 059A 0062;0061 302A 033C 0316 059A 0062;0061 302A 033C 0316 059A 0062;0061 302A 033C 0316 059A 0062; # (a◌̼◌֚◌̖◌〪b; a◌〪◌̼◌̖◌֚b; a◌〪◌̼◌̖◌֚b; a◌〪◌̼◌̖◌֚b; a◌〪◌̼◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING SEAGULL BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0339 0062;0061 1DFA 0316 0339 059A 0062;0061 1DFA 0316 0339 059A 0062;0061 1DFA 0316 0339 059A 0062;0061 1DFA 0316 0339 059A 0062; # (a◌֚◌̖◌᷺◌̹b; a◌᷺◌̖◌̹◌֚b; a◌᷺◌̖◌̹◌֚b; a◌᷺◌̖◌̹◌֚b; a◌᷺◌̖◌̹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT HALF RING BELOW, LATIN SMALL LETTER B
+0061 0339 059A 0316 1DFA 0062;0061 1DFA 0339 0316 059A 0062;0061 1DFA 0339 0316 059A 0062;0061 1DFA 0339 0316 059A 0062;0061 1DFA 0339 0316 059A 0062; # (a◌̹◌֚◌̖◌᷺b; a◌᷺◌̹◌̖◌֚b; a◌᷺◌̹◌̖◌֚b; a◌᷺◌̹◌̖◌֚b; a◌᷺◌̹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT HALF RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 033A 0062;0061 1DFA 0316 033A 059A 0062;0061 1DFA 0316 033A 059A 0062;0061 1DFA 0316 033A 059A 0062;0061 1DFA 0316 033A 059A 0062; # (a◌֚◌̖◌᷺◌̺b; a◌᷺◌̖◌̺◌֚b; a◌᷺◌̖◌̺◌֚b; a◌᷺◌̖◌̺◌֚b; a◌᷺◌̖◌̺◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING INVERTED BRIDGE BELOW, LATIN SMALL LETTER B
+0061 033A 059A 0316 1DFA 0062;0061 1DFA 033A 0316 059A 0062;0061 1DFA 033A 0316 059A 0062;0061 1DFA 033A 0316 059A 0062;0061 1DFA 033A 0316 059A 0062; # (a◌̺◌֚◌̖◌᷺b; a◌᷺◌̺◌̖◌֚b; a◌᷺◌̺◌̖◌֚b; a◌᷺◌̺◌̖◌֚b; a◌᷺◌̺◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING INVERTED BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 033B 0062;0061 1DFA 0316 033B 059A 0062;0061 1DFA 0316 033B 059A 0062;0061 1DFA 0316 033B 059A 0062;0061 1DFA 0316 033B 059A 0062; # (a◌֚◌̖◌᷺◌̻b; a◌᷺◌̖◌̻◌֚b; a◌᷺◌̖◌̻◌֚b; a◌᷺◌̖◌̻◌֚b; a◌᷺◌̖◌̻◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING SQUARE BELOW, LATIN SMALL LETTER B
+0061 033B 059A 0316 1DFA 0062;0061 1DFA 033B 0316 059A 0062;0061 1DFA 033B 0316 059A 0062;0061 1DFA 033B 0316 059A 0062;0061 1DFA 033B 0316 059A 0062; # (a◌̻◌֚◌̖◌᷺b; a◌᷺◌̻◌̖◌֚b; a◌᷺◌̻◌̖◌֚b; a◌᷺◌̻◌̖◌֚b; a◌᷺◌̻◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING SQUARE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 033C 0062;0061 1DFA 0316 033C 059A 0062;0061 1DFA 0316 033C 059A 0062;0061 1DFA 0316 033C 059A 0062;0061 1DFA 0316 033C 059A 0062; # (a◌֚◌̖◌᷺◌̼b; a◌᷺◌̖◌̼◌֚b; a◌᷺◌̖◌̼◌֚b; a◌᷺◌̖◌̼◌֚b; a◌᷺◌̖◌̼◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING SEAGULL BELOW, LATIN SMALL LETTER B
+0061 033C 059A 0316 1DFA 0062;0061 1DFA 033C 0316 059A 0062;0061 1DFA 033C 0316 059A 0062;0061 1DFA 033C 0316 059A 0062;0061 1DFA 033C 0316 059A 0062; # (a◌̼◌֚◌̖◌᷺b; a◌᷺◌̼◌̖◌֚b; a◌᷺◌̼◌̖◌֚b; a◌᷺◌̼◌̖◌֚b; a◌᷺◌̼◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING SEAGULL BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 033D 0062;00E0 05AE 033D 0315 0062;0061 05AE 0300 033D 0315 0062;00E0 05AE 033D 0315 0062;0061 05AE 0300 033D 0315 0062; # (a◌̕◌̀◌֮◌̽b; à◌֮◌̽◌̕b; a◌֮◌̀◌̽◌̕b; à◌֮◌̽◌̕b; a◌֮◌̀◌̽◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING X ABOVE, LATIN SMALL LETTER B
0061 033D 0315 0300 05AE 0062;0061 05AE 033D 0300 0315 0062;0061 05AE 033D 0300 0315 0062;0061 05AE 033D 0300 0315 0062;0061 05AE 033D 0300 0315 0062; # (a◌̽◌̕◌̀◌֮b; a◌֮◌̽◌̀◌̕b; a◌֮◌̽◌̀◌̕b; a◌֮◌̽◌̀◌̕b; a◌֮◌̽◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING X ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 033E 0062;00E0 05AE 033E 0315 0062;0061 05AE 0300 033E 0315 0062;00E0 05AE 033E 0315 0062;0061 05AE 0300 033E 0315 0062; # (a◌̕◌̀◌֮◌̾b; à◌֮◌̾◌̕b; a◌֮◌̀◌̾◌̕b; à◌֮◌̾◌̕b; a◌֮◌̀◌̾◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING VERTICAL TILDE, LATIN SMALL LETTER B
@@ -17123,44 +17182,44 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0345 0345 035D 0062;0061 035D 0345 0345 0062;0061 035D 0345 0345 0062;0061 035D 0345 0345 0062;0061 035D 0345 0345 0062; # (a◌ͅ◌ͅ◌Íb; aâ—ŒÍ◌ͅ◌ͅb; aâ—ŒÍ◌ͅ◌ͅb; aâ—ŒÍ◌ͅ◌ͅb; aâ—ŒÍ◌ͅ◌ͅb; ) LATIN SMALL LETTER A, COMBINING GREEK YPOGEGRAMMENI, COMBINING GREEK YPOGEGRAMMENI, COMBINING DOUBLE BREVE, LATIN SMALL LETTER B
0061 0315 0300 05AE 0346 0062;00E0 05AE 0346 0315 0062;0061 05AE 0300 0346 0315 0062;00E0 05AE 0346 0315 0062;0061 05AE 0300 0346 0315 0062; # (a◌̕◌̀◌֮◌͆b; à◌֮◌͆◌̕b; a◌֮◌̀◌͆◌̕b; à◌֮◌͆◌̕b; a◌֮◌̀◌͆◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING BRIDGE ABOVE, LATIN SMALL LETTER B
0061 0346 0315 0300 05AE 0062;0061 05AE 0346 0300 0315 0062;0061 05AE 0346 0300 0315 0062;0061 05AE 0346 0300 0315 0062;0061 05AE 0346 0300 0315 0062; # (a◌͆◌̕◌̀◌֮b; a◌֮◌͆◌̀◌̕b; a◌֮◌͆◌̀◌̕b; a◌֮◌͆◌̀◌̕b; a◌֮◌͆◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING BRIDGE ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0347 0062;0061 302A 0316 0347 059A 0062;0061 302A 0316 0347 059A 0062;0061 302A 0316 0347 059A 0062;0061 302A 0316 0347 059A 0062; # (a◌֚◌̖◌〪◌͇b; a◌〪◌̖◌͇◌֚b; a◌〪◌̖◌͇◌֚b; a◌〪◌̖◌͇◌֚b; a◌〪◌̖◌͇◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING EQUALS SIGN BELOW, LATIN SMALL LETTER B
-0061 0347 059A 0316 302A 0062;0061 302A 0347 0316 059A 0062;0061 302A 0347 0316 059A 0062;0061 302A 0347 0316 059A 0062;0061 302A 0347 0316 059A 0062; # (a◌͇◌֚◌̖◌〪b; a◌〪◌͇◌̖◌֚b; a◌〪◌͇◌̖◌֚b; a◌〪◌͇◌̖◌֚b; a◌〪◌͇◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING EQUALS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0348 0062;0061 302A 0316 0348 059A 0062;0061 302A 0316 0348 059A 0062;0061 302A 0316 0348 059A 0062;0061 302A 0316 0348 059A 0062; # (a◌֚◌̖◌〪◌͈b; a◌〪◌̖◌͈◌֚b; a◌〪◌̖◌͈◌֚b; a◌〪◌̖◌͈◌֚b; a◌〪◌̖◌͈◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DOUBLE VERTICAL LINE BELOW, LATIN SMALL LETTER B
-0061 0348 059A 0316 302A 0062;0061 302A 0348 0316 059A 0062;0061 302A 0348 0316 059A 0062;0061 302A 0348 0316 059A 0062;0061 302A 0348 0316 059A 0062; # (a◌͈◌֚◌̖◌〪b; a◌〪◌͈◌̖◌֚b; a◌〪◌͈◌̖◌֚b; a◌〪◌͈◌̖◌֚b; a◌〪◌͈◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE VERTICAL LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0349 0062;0061 302A 0316 0349 059A 0062;0061 302A 0316 0349 059A 0062;0061 302A 0316 0349 059A 0062;0061 302A 0316 0349 059A 0062; # (a◌֚◌̖◌〪◌͉b; a◌〪◌̖◌͉◌֚b; a◌〪◌̖◌͉◌֚b; a◌〪◌̖◌͉◌֚b; a◌〪◌̖◌͉◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFT ANGLE BELOW, LATIN SMALL LETTER B
-0061 0349 059A 0316 302A 0062;0061 302A 0349 0316 059A 0062;0061 302A 0349 0316 059A 0062;0061 302A 0349 0316 059A 0062;0061 302A 0349 0316 059A 0062; # (a◌͉◌֚◌̖◌〪b; a◌〪◌͉◌̖◌֚b; a◌〪◌͉◌̖◌֚b; a◌〪◌͉◌̖◌֚b; a◌〪◌͉◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT ANGLE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0347 0062;0061 1DFA 0316 0347 059A 0062;0061 1DFA 0316 0347 059A 0062;0061 1DFA 0316 0347 059A 0062;0061 1DFA 0316 0347 059A 0062; # (a◌֚◌̖◌᷺◌͇b; a◌᷺◌̖◌͇◌֚b; a◌᷺◌̖◌͇◌֚b; a◌᷺◌̖◌͇◌֚b; a◌᷺◌̖◌͇◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING EQUALS SIGN BELOW, LATIN SMALL LETTER B
+0061 0347 059A 0316 1DFA 0062;0061 1DFA 0347 0316 059A 0062;0061 1DFA 0347 0316 059A 0062;0061 1DFA 0347 0316 059A 0062;0061 1DFA 0347 0316 059A 0062; # (a◌͇◌֚◌̖◌᷺b; a◌᷺◌͇◌̖◌֚b; a◌᷺◌͇◌̖◌֚b; a◌᷺◌͇◌̖◌֚b; a◌᷺◌͇◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING EQUALS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0348 0062;0061 1DFA 0316 0348 059A 0062;0061 1DFA 0316 0348 059A 0062;0061 1DFA 0316 0348 059A 0062;0061 1DFA 0316 0348 059A 0062; # (a◌֚◌̖◌᷺◌͈b; a◌᷺◌̖◌͈◌֚b; a◌᷺◌̖◌͈◌֚b; a◌᷺◌̖◌͈◌֚b; a◌᷺◌̖◌͈◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOUBLE VERTICAL LINE BELOW, LATIN SMALL LETTER B
+0061 0348 059A 0316 1DFA 0062;0061 1DFA 0348 0316 059A 0062;0061 1DFA 0348 0316 059A 0062;0061 1DFA 0348 0316 059A 0062;0061 1DFA 0348 0316 059A 0062; # (a◌͈◌֚◌̖◌᷺b; a◌᷺◌͈◌̖◌֚b; a◌᷺◌͈◌̖◌֚b; a◌᷺◌͈◌̖◌֚b; a◌᷺◌͈◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE VERTICAL LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0349 0062;0061 1DFA 0316 0349 059A 0062;0061 1DFA 0316 0349 059A 0062;0061 1DFA 0316 0349 059A 0062;0061 1DFA 0316 0349 059A 0062; # (a◌֚◌̖◌᷺◌͉b; a◌᷺◌̖◌͉◌֚b; a◌᷺◌̖◌͉◌֚b; a◌᷺◌̖◌͉◌֚b; a◌᷺◌̖◌͉◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT ANGLE BELOW, LATIN SMALL LETTER B
+0061 0349 059A 0316 1DFA 0062;0061 1DFA 0349 0316 059A 0062;0061 1DFA 0349 0316 059A 0062;0061 1DFA 0349 0316 059A 0062;0061 1DFA 0349 0316 059A 0062; # (a◌͉◌֚◌̖◌᷺b; a◌᷺◌͉◌̖◌֚b; a◌᷺◌͉◌̖◌֚b; a◌᷺◌͉◌̖◌֚b; a◌᷺◌͉◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT ANGLE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 034A 0062;00E0 05AE 034A 0315 0062;0061 05AE 0300 034A 0315 0062;00E0 05AE 034A 0315 0062;0061 05AE 0300 034A 0315 0062; # (a◌̕◌̀◌֮◌͊b; à◌֮◌͊◌̕b; a◌֮◌̀◌͊◌̕b; à◌֮◌͊◌̕b; a◌֮◌̀◌͊◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING NOT TILDE ABOVE, LATIN SMALL LETTER B
0061 034A 0315 0300 05AE 0062;0061 05AE 034A 0300 0315 0062;0061 05AE 034A 0300 0315 0062;0061 05AE 034A 0300 0315 0062;0061 05AE 034A 0300 0315 0062; # (a◌͊◌̕◌̀◌֮b; a◌֮◌͊◌̀◌̕b; a◌֮◌͊◌̀◌̕b; a◌֮◌͊◌̀◌̕b; a◌֮◌͊◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING NOT TILDE ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 034B 0062;00E0 05AE 034B 0315 0062;0061 05AE 0300 034B 0315 0062;00E0 05AE 034B 0315 0062;0061 05AE 0300 034B 0315 0062; # (a◌̕◌̀◌֮◌͋b; à◌֮◌͋◌̕b; a◌֮◌̀◌͋◌̕b; à◌֮◌͋◌̕b; a◌֮◌̀◌͋◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING HOMOTHETIC ABOVE, LATIN SMALL LETTER B
0061 034B 0315 0300 05AE 0062;0061 05AE 034B 0300 0315 0062;0061 05AE 034B 0300 0315 0062;0061 05AE 034B 0300 0315 0062;0061 05AE 034B 0300 0315 0062; # (a◌͋◌̕◌̀◌֮b; a◌֮◌͋◌̀◌̕b; a◌֮◌͋◌̀◌̕b; a◌֮◌͋◌̀◌̕b; a◌֮◌͋◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING HOMOTHETIC ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 034C 0062;00E0 05AE 034C 0315 0062;0061 05AE 0300 034C 0315 0062;00E0 05AE 034C 0315 0062;0061 05AE 0300 034C 0315 0062; # (a◌̕◌̀◌֮◌͌b; à◌֮◌͌◌̕b; a◌֮◌̀◌͌◌̕b; à◌֮◌͌◌̕b; a◌֮◌̀◌͌◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING ALMOST EQUAL TO ABOVE, LATIN SMALL LETTER B
0061 034C 0315 0300 05AE 0062;0061 05AE 034C 0300 0315 0062;0061 05AE 034C 0300 0315 0062;0061 05AE 034C 0300 0315 0062;0061 05AE 034C 0300 0315 0062; # (a◌͌◌̕◌̀◌֮b; a◌֮◌͌◌̀◌̕b; a◌֮◌͌◌̀◌̕b; a◌֮◌͌◌̀◌̕b; a◌֮◌͌◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING ALMOST EQUAL TO ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 034D 0062;0061 302A 0316 034D 059A 0062;0061 302A 0316 034D 059A 0062;0061 302A 0316 034D 059A 0062;0061 302A 0316 034D 059A 0062; # (a◌֚◌̖◌〪◌Íb; a◌〪◌̖◌Í◌֚b; a◌〪◌̖◌Í◌֚b; a◌〪◌̖◌Í◌֚b; a◌〪◌̖◌Í◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFT RIGHT ARROW BELOW, LATIN SMALL LETTER B
-0061 034D 059A 0316 302A 0062;0061 302A 034D 0316 059A 0062;0061 302A 034D 0316 059A 0062;0061 302A 034D 0316 059A 0062;0061 302A 034D 0316 059A 0062; # (aâ—ŒÍ◌֚◌̖◌〪b; a◌〪◌Í◌̖◌֚b; a◌〪◌Í◌̖◌֚b; a◌〪◌Í◌̖◌֚b; a◌〪◌Í◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT RIGHT ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 034E 0062;0061 302A 0316 034E 059A 0062;0061 302A 0316 034E 059A 0062;0061 302A 0316 034E 059A 0062;0061 302A 0316 034E 059A 0062; # (a◌֚◌̖◌〪◌͎b; a◌〪◌̖◌͎◌֚b; a◌〪◌̖◌͎◌֚b; a◌〪◌̖◌͎◌֚b; a◌〪◌̖◌͎◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING UPWARDS ARROW BELOW, LATIN SMALL LETTER B
-0061 034E 059A 0316 302A 0062;0061 302A 034E 0316 059A 0062;0061 302A 034E 0316 059A 0062;0061 302A 034E 0316 059A 0062;0061 302A 034E 0316 059A 0062; # (a◌͎◌֚◌̖◌〪b; a◌〪◌͎◌̖◌֚b; a◌〪◌͎◌̖◌֚b; a◌〪◌͎◌̖◌֚b; a◌〪◌͎◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING UPWARDS ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 034D 0062;0061 1DFA 0316 034D 059A 0062;0061 1DFA 0316 034D 059A 0062;0061 1DFA 0316 034D 059A 0062;0061 1DFA 0316 034D 059A 0062; # (a◌֚◌̖◌᷺◌Íb; a◌᷺◌̖◌Í◌֚b; a◌᷺◌̖◌Í◌֚b; a◌᷺◌̖◌Í◌֚b; a◌᷺◌̖◌Í◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT RIGHT ARROW BELOW, LATIN SMALL LETTER B
+0061 034D 059A 0316 1DFA 0062;0061 1DFA 034D 0316 059A 0062;0061 1DFA 034D 0316 059A 0062;0061 1DFA 034D 0316 059A 0062;0061 1DFA 034D 0316 059A 0062; # (aâ—ŒÍ◌֚◌̖◌᷺b; a◌᷺◌Í◌̖◌֚b; a◌᷺◌Í◌̖◌֚b; a◌᷺◌Í◌̖◌֚b; a◌᷺◌Í◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT RIGHT ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 034E 0062;0061 1DFA 0316 034E 059A 0062;0061 1DFA 0316 034E 059A 0062;0061 1DFA 0316 034E 059A 0062;0061 1DFA 0316 034E 059A 0062; # (a◌֚◌̖◌᷺◌͎b; a◌᷺◌̖◌͎◌֚b; a◌᷺◌̖◌͎◌֚b; a◌᷺◌̖◌͎◌֚b; a◌᷺◌̖◌͎◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING UPWARDS ARROW BELOW, LATIN SMALL LETTER B
+0061 034E 059A 0316 1DFA 0062;0061 1DFA 034E 0316 059A 0062;0061 1DFA 034E 0316 059A 0062;0061 1DFA 034E 0316 059A 0062;0061 1DFA 034E 0316 059A 0062; # (a◌͎◌֚◌̖◌᷺b; a◌᷺◌͎◌̖◌֚b; a◌᷺◌͎◌̖◌֚b; a◌᷺◌͎◌̖◌֚b; a◌᷺◌͎◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING UPWARDS ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0350 0062;00E0 05AE 0350 0315 0062;0061 05AE 0300 0350 0315 0062;00E0 05AE 0350 0315 0062;0061 05AE 0300 0350 0315 0062; # (a◌̕◌̀◌֮◌Íb; à◌֮◌Í◌̕b; a◌֮◌̀◌Í◌̕b; à◌֮◌Í◌̕b; a◌֮◌̀◌Í◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING RIGHT ARROWHEAD ABOVE, LATIN SMALL LETTER B
0061 0350 0315 0300 05AE 0062;0061 05AE 0350 0300 0315 0062;0061 05AE 0350 0300 0315 0062;0061 05AE 0350 0300 0315 0062;0061 05AE 0350 0300 0315 0062; # (aâ—ŒÍ◌̕◌̀◌֮b; a◌֮◌Í◌̀◌̕b; a◌֮◌Í◌̀◌̕b; a◌֮◌Í◌̀◌̕b; a◌֮◌Í◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0351 0062;00E0 05AE 0351 0315 0062;0061 05AE 0300 0351 0315 0062;00E0 05AE 0351 0315 0062;0061 05AE 0300 0351 0315 0062; # (a◌̕◌̀◌֮◌͑b; à◌֮◌͑◌̕b; a◌֮◌̀◌͑◌̕b; à◌֮◌͑◌̕b; a◌֮◌̀◌͑◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LEFT HALF RING ABOVE, LATIN SMALL LETTER B
0061 0351 0315 0300 05AE 0062;0061 05AE 0351 0300 0315 0062;0061 05AE 0351 0300 0315 0062;0061 05AE 0351 0300 0315 0062;0061 05AE 0351 0300 0315 0062; # (a◌͑◌̕◌̀◌֮b; a◌֮◌͑◌̀◌̕b; a◌֮◌͑◌̀◌̕b; a◌֮◌͑◌̀◌̕b; a◌֮◌͑◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING LEFT HALF RING ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0352 0062;00E0 05AE 0352 0315 0062;0061 05AE 0300 0352 0315 0062;00E0 05AE 0352 0315 0062;0061 05AE 0300 0352 0315 0062; # (a◌̕◌̀◌֮◌͒b; à◌֮◌͒◌̕b; a◌֮◌̀◌͒◌̕b; à◌֮◌͒◌̕b; a◌֮◌̀◌͒◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING FERMATA, LATIN SMALL LETTER B
0061 0352 0315 0300 05AE 0062;0061 05AE 0352 0300 0315 0062;0061 05AE 0352 0300 0315 0062;0061 05AE 0352 0300 0315 0062;0061 05AE 0352 0300 0315 0062; # (a◌͒◌̕◌̀◌֮b; a◌֮◌͒◌̀◌̕b; a◌֮◌͒◌̀◌̕b; a◌֮◌͒◌̀◌̕b; a◌֮◌͒◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING FERMATA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0353 0062;0061 302A 0316 0353 059A 0062;0061 302A 0316 0353 059A 0062;0061 302A 0316 0353 059A 0062;0061 302A 0316 0353 059A 0062; # (a◌֚◌̖◌〪◌͓b; a◌〪◌̖◌͓◌֚b; a◌〪◌̖◌͓◌֚b; a◌〪◌̖◌͓◌֚b; a◌〪◌̖◌͓◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING X BELOW, LATIN SMALL LETTER B
-0061 0353 059A 0316 302A 0062;0061 302A 0353 0316 059A 0062;0061 302A 0353 0316 059A 0062;0061 302A 0353 0316 059A 0062;0061 302A 0353 0316 059A 0062; # (a◌͓◌֚◌̖◌〪b; a◌〪◌͓◌̖◌֚b; a◌〪◌͓◌̖◌֚b; a◌〪◌͓◌̖◌֚b; a◌〪◌͓◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING X BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0354 0062;0061 302A 0316 0354 059A 0062;0061 302A 0316 0354 059A 0062;0061 302A 0316 0354 059A 0062;0061 302A 0316 0354 059A 0062; # (a◌֚◌̖◌〪◌͔b; a◌〪◌̖◌͔◌֚b; a◌〪◌̖◌͔◌֚b; a◌〪◌̖◌͔◌֚b; a◌〪◌̖◌͔◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFT ARROWHEAD BELOW, LATIN SMALL LETTER B
-0061 0354 059A 0316 302A 0062;0061 302A 0354 0316 059A 0062;0061 302A 0354 0316 059A 0062;0061 302A 0354 0316 059A 0062;0061 302A 0354 0316 059A 0062; # (a◌͔◌֚◌̖◌〪b; a◌〪◌͔◌̖◌֚b; a◌〪◌͔◌̖◌֚b; a◌〪◌͔◌̖◌֚b; a◌〪◌͔◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0355 0062;0061 302A 0316 0355 059A 0062;0061 302A 0316 0355 059A 0062;0061 302A 0316 0355 059A 0062;0061 302A 0316 0355 059A 0062; # (a◌֚◌̖◌〪◌͕b; a◌〪◌̖◌͕◌֚b; a◌〪◌̖◌͕◌֚b; a◌〪◌̖◌͕◌֚b; a◌〪◌̖◌͕◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHT ARROWHEAD BELOW, LATIN SMALL LETTER B
-0061 0355 059A 0316 302A 0062;0061 302A 0355 0316 059A 0062;0061 302A 0355 0316 059A 0062;0061 302A 0355 0316 059A 0062;0061 302A 0355 0316 059A 0062; # (a◌͕◌֚◌̖◌〪b; a◌〪◌͕◌̖◌֚b; a◌〪◌͕◌̖◌֚b; a◌〪◌͕◌̖◌֚b; a◌〪◌͕◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0356 0062;0061 302A 0316 0356 059A 0062;0061 302A 0316 0356 059A 0062;0061 302A 0316 0356 059A 0062;0061 302A 0316 0356 059A 0062; # (a◌֚◌̖◌〪◌͖b; a◌〪◌̖◌͖◌֚b; a◌〪◌̖◌͖◌֚b; a◌〪◌̖◌͖◌֚b; a◌〪◌̖◌͖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW, LATIN SMALL LETTER B
-0061 0356 059A 0316 302A 0062;0061 302A 0356 0316 059A 0062;0061 302A 0356 0316 059A 0062;0061 302A 0356 0316 059A 0062;0061 302A 0356 0316 059A 0062; # (a◌͖◌֚◌̖◌〪b; a◌〪◌͖◌̖◌֚b; a◌〪◌͖◌̖◌֚b; a◌〪◌͖◌̖◌֚b; a◌〪◌͖◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0353 0062;0061 1DFA 0316 0353 059A 0062;0061 1DFA 0316 0353 059A 0062;0061 1DFA 0316 0353 059A 0062;0061 1DFA 0316 0353 059A 0062; # (a◌֚◌̖◌᷺◌͓b; a◌᷺◌̖◌͓◌֚b; a◌᷺◌̖◌͓◌֚b; a◌᷺◌̖◌͓◌֚b; a◌᷺◌̖◌͓◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING X BELOW, LATIN SMALL LETTER B
+0061 0353 059A 0316 1DFA 0062;0061 1DFA 0353 0316 059A 0062;0061 1DFA 0353 0316 059A 0062;0061 1DFA 0353 0316 059A 0062;0061 1DFA 0353 0316 059A 0062; # (a◌͓◌֚◌̖◌᷺b; a◌᷺◌͓◌̖◌֚b; a◌᷺◌͓◌̖◌֚b; a◌᷺◌͓◌̖◌֚b; a◌᷺◌͓◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING X BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0354 0062;0061 1DFA 0316 0354 059A 0062;0061 1DFA 0316 0354 059A 0062;0061 1DFA 0316 0354 059A 0062;0061 1DFA 0316 0354 059A 0062; # (a◌֚◌̖◌᷺◌͔b; a◌᷺◌̖◌͔◌֚b; a◌᷺◌̖◌͔◌֚b; a◌᷺◌̖◌͔◌֚b; a◌᷺◌̖◌͔◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT ARROWHEAD BELOW, LATIN SMALL LETTER B
+0061 0354 059A 0316 1DFA 0062;0061 1DFA 0354 0316 059A 0062;0061 1DFA 0354 0316 059A 0062;0061 1DFA 0354 0316 059A 0062;0061 1DFA 0354 0316 059A 0062; # (a◌͔◌֚◌̖◌᷺b; a◌᷺◌͔◌̖◌֚b; a◌᷺◌͔◌̖◌֚b; a◌᷺◌͔◌̖◌֚b; a◌᷺◌͔◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0355 0062;0061 1DFA 0316 0355 059A 0062;0061 1DFA 0316 0355 059A 0062;0061 1DFA 0316 0355 059A 0062;0061 1DFA 0316 0355 059A 0062; # (a◌֚◌̖◌᷺◌͕b; a◌᷺◌̖◌͕◌֚b; a◌᷺◌̖◌͕◌֚b; a◌᷺◌̖◌͕◌֚b; a◌᷺◌̖◌͕◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT ARROWHEAD BELOW, LATIN SMALL LETTER B
+0061 0355 059A 0316 1DFA 0062;0061 1DFA 0355 0316 059A 0062;0061 1DFA 0355 0316 059A 0062;0061 1DFA 0355 0316 059A 0062;0061 1DFA 0355 0316 059A 0062; # (a◌͕◌֚◌̖◌᷺b; a◌᷺◌͕◌̖◌֚b; a◌᷺◌͕◌̖◌֚b; a◌᷺◌͕◌̖◌֚b; a◌᷺◌͕◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0356 0062;0061 1DFA 0316 0356 059A 0062;0061 1DFA 0316 0356 059A 0062;0061 1DFA 0316 0356 059A 0062;0061 1DFA 0316 0356 059A 0062; # (a◌֚◌̖◌᷺◌͖b; a◌᷺◌̖◌͖◌֚b; a◌᷺◌̖◌͖◌֚b; a◌᷺◌̖◌͖◌֚b; a◌᷺◌̖◌͖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW, LATIN SMALL LETTER B
+0061 0356 059A 0316 1DFA 0062;0061 1DFA 0356 0316 059A 0062;0061 1DFA 0356 0316 059A 0062;0061 1DFA 0356 0316 059A 0062;0061 1DFA 0356 0316 059A 0062; # (a◌͖◌֚◌̖◌᷺b; a◌᷺◌͖◌̖◌֚b; a◌᷺◌͖◌̖◌֚b; a◌᷺◌͖◌̖◌֚b; a◌᷺◌͖◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0357 0062;00E0 05AE 0357 0315 0062;0061 05AE 0300 0357 0315 0062;00E0 05AE 0357 0315 0062;0061 05AE 0300 0357 0315 0062; # (a◌̕◌̀◌֮◌͗b; à◌֮◌͗◌̕b; a◌֮◌̀◌͗◌̕b; à◌֮◌͗◌̕b; a◌֮◌̀◌͗◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING RIGHT HALF RING ABOVE, LATIN SMALL LETTER B
0061 0357 0315 0300 05AE 0062;0061 05AE 0357 0300 0315 0062;0061 05AE 0357 0300 0315 0062;0061 05AE 0357 0300 0315 0062;0061 05AE 0357 0300 0315 0062; # (a◌͗◌̕◌̀◌֮b; a◌֮◌͗◌̀◌̕b; a◌֮◌͗◌̀◌̕b; a◌֮◌͗◌̀◌̕b; a◌֮◌͗◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING RIGHT HALF RING ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 035C 0315 0300 0358 0062;00E0 0315 0358 035C 0062;0061 0300 0315 0358 035C 0062;00E0 0315 0358 035C 0062;0061 0300 0315 0358 035C 0062; # (a◌͜◌̕◌̀◌͘b; à◌̕◌͘◌͜b; a◌̀◌̕◌͘◌͜b; à◌̕◌͘◌͜b; a◌̀◌̕◌͘◌͜b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, COMBINING DOT ABOVE RIGHT, LATIN SMALL LETTER B
0061 0358 035C 0315 0300 0062;00E0 0358 0315 035C 0062;0061 0300 0358 0315 035C 0062;00E0 0358 0315 035C 0062;0061 0300 0358 0315 035C 0062; # (a◌͘◌͜◌̕◌̀b; à◌͘◌̕◌͜b; a◌̀◌͘◌̕◌͜b; à◌͘◌̕◌͜b; a◌̀◌͘◌̕◌͜b; ) LATIN SMALL LETTER A, COMBINING DOT ABOVE RIGHT, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, LATIN SMALL LETTER B
-0061 059A 0316 302A 0359 0062;0061 302A 0316 0359 059A 0062;0061 302A 0316 0359 059A 0062;0061 302A 0316 0359 059A 0062;0061 302A 0316 0359 059A 0062; # (a◌֚◌̖◌〪◌͙b; a◌〪◌̖◌͙◌֚b; a◌〪◌̖◌͙◌֚b; a◌〪◌̖◌͙◌֚b; a◌〪◌̖◌͙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING ASTERISK BELOW, LATIN SMALL LETTER B
-0061 0359 059A 0316 302A 0062;0061 302A 0359 0316 059A 0062;0061 302A 0359 0316 059A 0062;0061 302A 0359 0316 059A 0062;0061 302A 0359 0316 059A 0062; # (a◌͙◌֚◌̖◌〪b; a◌〪◌͙◌̖◌֚b; a◌〪◌͙◌̖◌֚b; a◌〪◌͙◌̖◌֚b; a◌〪◌͙◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING ASTERISK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 035A 0062;0061 302A 0316 035A 059A 0062;0061 302A 0316 035A 059A 0062;0061 302A 0316 035A 059A 0062;0061 302A 0316 035A 059A 0062; # (a◌֚◌̖◌〪◌͚b; a◌〪◌̖◌͚◌֚b; a◌〪◌̖◌͚◌֚b; a◌〪◌̖◌͚◌֚b; a◌〪◌̖◌͚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DOUBLE RING BELOW, LATIN SMALL LETTER B
-0061 035A 059A 0316 302A 0062;0061 302A 035A 0316 059A 0062;0061 302A 035A 0316 059A 0062;0061 302A 035A 0316 059A 0062;0061 302A 035A 0316 059A 0062; # (a◌͚◌֚◌̖◌〪b; a◌〪◌͚◌̖◌֚b; a◌〪◌͚◌̖◌֚b; a◌〪◌͚◌̖◌֚b; a◌〪◌͚◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0359 0062;0061 1DFA 0316 0359 059A 0062;0061 1DFA 0316 0359 059A 0062;0061 1DFA 0316 0359 059A 0062;0061 1DFA 0316 0359 059A 0062; # (a◌֚◌̖◌᷺◌͙b; a◌᷺◌̖◌͙◌֚b; a◌᷺◌̖◌͙◌֚b; a◌᷺◌̖◌͙◌֚b; a◌᷺◌̖◌͙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING ASTERISK BELOW, LATIN SMALL LETTER B
+0061 0359 059A 0316 1DFA 0062;0061 1DFA 0359 0316 059A 0062;0061 1DFA 0359 0316 059A 0062;0061 1DFA 0359 0316 059A 0062;0061 1DFA 0359 0316 059A 0062; # (a◌͙◌֚◌̖◌᷺b; a◌᷺◌͙◌̖◌֚b; a◌᷺◌͙◌̖◌֚b; a◌᷺◌͙◌̖◌֚b; a◌᷺◌͙◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING ASTERISK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 035A 0062;0061 1DFA 0316 035A 059A 0062;0061 1DFA 0316 035A 059A 0062;0061 1DFA 0316 035A 059A 0062;0061 1DFA 0316 035A 059A 0062; # (a◌֚◌̖◌᷺◌͚b; a◌᷺◌̖◌͚◌֚b; a◌᷺◌̖◌͚◌֚b; a◌᷺◌̖◌͚◌֚b; a◌᷺◌̖◌͚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOUBLE RING BELOW, LATIN SMALL LETTER B
+0061 035A 059A 0316 1DFA 0062;0061 1DFA 035A 0316 059A 0062;0061 1DFA 035A 0316 059A 0062;0061 1DFA 035A 0316 059A 0062;0061 1DFA 035A 0316 059A 0062; # (a◌͚◌֚◌̖◌᷺b; a◌᷺◌͚◌̖◌֚b; a◌᷺◌͚◌̖◌֚b; a◌᷺◌͚◌̖◌֚b; a◌᷺◌͚◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 035B 0062;00E0 05AE 035B 0315 0062;0061 05AE 0300 035B 0315 0062;00E0 05AE 035B 0315 0062;0061 05AE 0300 035B 0315 0062; # (a◌̕◌̀◌֮◌͛b; à◌֮◌͛◌̕b; a◌֮◌̀◌͛◌̕b; à◌֮◌͛◌̕b; a◌֮◌̀◌͛◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING ZIGZAG ABOVE, LATIN SMALL LETTER B
0061 035B 0315 0300 05AE 0062;0061 05AE 035B 0300 0315 0062;0061 05AE 035B 0300 0315 0062;0061 05AE 035B 0300 0315 0062;0061 05AE 035B 0300 0315 0062; # (a◌͛◌̕◌̀◌֮b; a◌֮◌͛◌̀◌̕b; a◌֮◌͛◌̀◌̕b; a◌֮◌͛◌̀◌̕b; a◌֮◌͛◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING ZIGZAG ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 035D 035C 0315 035C 0062;0061 0315 035C 035C 035D 0062;0061 0315 035C 035C 035D 0062;0061 0315 035C 035C 035D 0062;0061 0315 035C 035C 035D 0062; # (aâ—ŒÍ◌͜◌̕◌͜b; a◌̕◌͜◌͜◌Íb; a◌̕◌͜◌͜◌Íb; a◌̕◌͜◌͜◌Íb; a◌̕◌͜◌͜◌Íb; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING DOUBLE BREVE BELOW, LATIN SMALL LETTER B
@@ -17213,8 +17272,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0486 0315 0300 05AE 0062;0061 05AE 0486 0300 0315 0062;0061 05AE 0486 0300 0315 0062;0061 05AE 0486 0300 0315 0062;0061 05AE 0486 0300 0315 0062; # (a◌҆◌̕◌̀◌֮b; a◌֮◌҆◌̀◌̕b; a◌֮◌҆◌̀◌̕b; a◌֮◌҆◌̀◌̕b; a◌֮◌҆◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC PSILI PNEUMATA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0487 0062;00E0 05AE 0487 0315 0062;0061 05AE 0300 0487 0315 0062;00E0 05AE 0487 0315 0062;0061 05AE 0300 0487 0315 0062; # (a◌̕◌̀◌֮◌҇b; à◌֮◌҇◌̕b; a◌֮◌̀◌҇◌̕b; à◌֮◌҇◌̕b; a◌֮◌̀◌҇◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING CYRILLIC POKRYTIE, LATIN SMALL LETTER B
0061 0487 0315 0300 05AE 0062;0061 05AE 0487 0300 0315 0062;0061 05AE 0487 0300 0315 0062;0061 05AE 0487 0300 0315 0062;0061 05AE 0487 0300 0315 0062; # (a◌҇◌̕◌̀◌֮b; a◌֮◌҇◌̀◌̕b; a◌֮◌҇◌̀◌̕b; a◌֮◌҇◌̀◌̕b; a◌֮◌҇◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC POKRYTIE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0591 0062;0061 302A 0316 0591 059A 0062;0061 302A 0316 0591 059A 0062;0061 302A 0316 0591 059A 0062;0061 302A 0316 0591 059A 0062; # (a◌֚◌̖◌〪◌֑b; a◌〪◌̖◌֑◌֚b; a◌〪◌̖◌֑◌֚b; a◌〪◌̖◌֑◌֚b; a◌〪◌̖◌֑◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT ETNAHTA, LATIN SMALL LETTER B
-0061 0591 059A 0316 302A 0062;0061 302A 0591 0316 059A 0062;0061 302A 0591 0316 059A 0062;0061 302A 0591 0316 059A 0062;0061 302A 0591 0316 059A 0062; # (a◌֑◌֚◌̖◌〪b; a◌〪◌֑◌̖◌֚b; a◌〪◌֑◌̖◌֚b; a◌〪◌֑◌̖◌֚b; a◌〪◌֑◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT ETNAHTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0591 0062;0061 1DFA 0316 0591 059A 0062;0061 1DFA 0316 0591 059A 0062;0061 1DFA 0316 0591 059A 0062;0061 1DFA 0316 0591 059A 0062; # (a◌֚◌̖◌᷺◌֑b; a◌᷺◌̖◌֑◌֚b; a◌᷺◌̖◌֑◌֚b; a◌᷺◌̖◌֑◌֚b; a◌᷺◌̖◌֑◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT ETNAHTA, LATIN SMALL LETTER B
+0061 0591 059A 0316 1DFA 0062;0061 1DFA 0591 0316 059A 0062;0061 1DFA 0591 0316 059A 0062;0061 1DFA 0591 0316 059A 0062;0061 1DFA 0591 0316 059A 0062; # (a◌֑◌֚◌̖◌᷺b; a◌᷺◌֑◌̖◌֚b; a◌᷺◌֑◌̖◌֚b; a◌᷺◌֑◌̖◌֚b; a◌᷺◌֑◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT ETNAHTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0592 0062;00E0 05AE 0592 0315 0062;0061 05AE 0300 0592 0315 0062;00E0 05AE 0592 0315 0062;0061 05AE 0300 0592 0315 0062; # (a◌̕◌̀◌֮◌֒b; à◌֮◌֒◌̕b; a◌֮◌̀◌֒◌̕b; à◌֮◌֒◌̕b; a◌֮◌̀◌֒◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT SEGOL, LATIN SMALL LETTER B
0061 0592 0315 0300 05AE 0062;0061 05AE 0592 0300 0315 0062;0061 05AE 0592 0300 0315 0062;0061 05AE 0592 0300 0315 0062;0061 05AE 0592 0300 0315 0062; # (a◌֒◌̕◌̀◌֮b; a◌֮◌֒◌̀◌̕b; a◌֮◌֒◌̀◌̕b; a◌֮◌֒◌̀◌̕b; a◌֮◌֒◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT SEGOL, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0593 0062;00E0 05AE 0593 0315 0062;0061 05AE 0300 0593 0315 0062;00E0 05AE 0593 0315 0062;0061 05AE 0300 0593 0315 0062; # (a◌̕◌̀◌֮◌֓b; à◌֮◌֓◌̕b; a◌֮◌̀◌֓◌̕b; à◌֮◌֓◌̕b; a◌֮◌̀◌֓◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT SHALSHELET, LATIN SMALL LETTER B
@@ -17223,8 +17282,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0594 0315 0300 05AE 0062;0061 05AE 0594 0300 0315 0062;0061 05AE 0594 0300 0315 0062;0061 05AE 0594 0300 0315 0062;0061 05AE 0594 0300 0315 0062; # (a◌֔◌̕◌̀◌֮b; a◌֮◌֔◌̀◌̕b; a◌֮◌֔◌̀◌̕b; a◌֮◌֔◌̀◌̕b; a◌֮◌֔◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT ZAQEF QATAN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0595 0062;00E0 05AE 0595 0315 0062;0061 05AE 0300 0595 0315 0062;00E0 05AE 0595 0315 0062;0061 05AE 0300 0595 0315 0062; # (a◌̕◌̀◌֮◌֕b; à◌֮◌֕◌̕b; a◌֮◌̀◌֕◌̕b; à◌֮◌֕◌̕b; a◌֮◌̀◌֕◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT ZAQEF GADOL, LATIN SMALL LETTER B
0061 0595 0315 0300 05AE 0062;0061 05AE 0595 0300 0315 0062;0061 05AE 0595 0300 0315 0062;0061 05AE 0595 0300 0315 0062;0061 05AE 0595 0300 0315 0062; # (a◌֕◌̕◌̀◌֮b; a◌֮◌֕◌̀◌̕b; a◌֮◌֕◌̀◌̕b; a◌֮◌֕◌̀◌̕b; a◌֮◌֕◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT ZAQEF GADOL, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0596 0062;0061 302A 0316 0596 059A 0062;0061 302A 0316 0596 059A 0062;0061 302A 0316 0596 059A 0062;0061 302A 0316 0596 059A 0062; # (a◌֚◌̖◌〪◌֖b; a◌〪◌̖◌֖◌֚b; a◌〪◌̖◌֖◌֚b; a◌〪◌̖◌֖◌֚b; a◌〪◌̖◌֖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT TIPEHA, LATIN SMALL LETTER B
-0061 0596 059A 0316 302A 0062;0061 302A 0596 0316 059A 0062;0061 302A 0596 0316 059A 0062;0061 302A 0596 0316 059A 0062;0061 302A 0596 0316 059A 0062; # (a◌֖◌֚◌̖◌〪b; a◌〪◌֖◌̖◌֚b; a◌〪◌֖◌̖◌֚b; a◌〪◌֖◌̖◌֚b; a◌〪◌֖◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT TIPEHA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0596 0062;0061 1DFA 0316 0596 059A 0062;0061 1DFA 0316 0596 059A 0062;0061 1DFA 0316 0596 059A 0062;0061 1DFA 0316 0596 059A 0062; # (a◌֚◌̖◌᷺◌֖b; a◌᷺◌̖◌֖◌֚b; a◌᷺◌̖◌֖◌֚b; a◌᷺◌̖◌֖◌֚b; a◌᷺◌̖◌֖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT TIPEHA, LATIN SMALL LETTER B
+0061 0596 059A 0316 1DFA 0062;0061 1DFA 0596 0316 059A 0062;0061 1DFA 0596 0316 059A 0062;0061 1DFA 0596 0316 059A 0062;0061 1DFA 0596 0316 059A 0062; # (a◌֖◌֚◌̖◌᷺b; a◌᷺◌֖◌̖◌֚b; a◌᷺◌֖◌̖◌֚b; a◌᷺◌֖◌̖◌֚b; a◌᷺◌֖◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT TIPEHA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0597 0062;00E0 05AE 0597 0315 0062;0061 05AE 0300 0597 0315 0062;00E0 05AE 0597 0315 0062;0061 05AE 0300 0597 0315 0062; # (a◌̕◌̀◌֮◌֗b; à◌֮◌֗◌̕b; a◌֮◌̀◌֗◌̕b; à◌֮◌֗◌̕b; a◌֮◌̀◌֗◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT REVIA, LATIN SMALL LETTER B
0061 0597 0315 0300 05AE 0062;0061 05AE 0597 0300 0315 0062;0061 05AE 0597 0300 0315 0062;0061 05AE 0597 0300 0315 0062;0061 05AE 0597 0300 0315 0062; # (a◌֗◌̕◌̀◌֮b; a◌֮◌֗◌̀◌̕b; a◌֮◌֗◌̀◌̕b; a◌֮◌֗◌̀◌̕b; a◌֮◌֗◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT REVIA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0598 0062;00E0 05AE 0598 0315 0062;0061 05AE 0300 0598 0315 0062;00E0 05AE 0598 0315 0062;0061 05AE 0300 0598 0315 0062; # (a◌̕◌̀◌֮◌֘b; à◌֮◌֘◌̕b; a◌֮◌̀◌֘◌̕b; à◌֮◌֘◌̕b; a◌֮◌̀◌֘◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT ZARQA, LATIN SMALL LETTER B
@@ -17233,8 +17292,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0599 0315 0300 05AE 0062;0061 05AE 0599 0300 0315 0062;0061 05AE 0599 0300 0315 0062;0061 05AE 0599 0300 0315 0062;0061 05AE 0599 0300 0315 0062; # (a◌֙◌̕◌̀◌֮b; a◌֮◌֙◌̀◌̕b; a◌֮◌֙◌̀◌̕b; a◌֮◌֙◌̀◌̕b; a◌֮◌֙◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT PASHTA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 302E 059A 0316 059A 0062;0061 0316 059A 059A 302E 0062;0061 0316 059A 059A 302E 0062;0061 0316 059A 059A 302E 0062;0061 0316 059A 059A 302E 0062; # (a〮◌֚◌̖◌֚b; a◌̖◌֚◌֚〮b; a◌̖◌֚◌֚〮b; a◌̖◌֚◌֚〮b; a◌̖◌֚◌֚〮b; ) LATIN SMALL LETTER A, HANGUL SINGLE DOT TONE MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, HEBREW ACCENT YETIV, LATIN SMALL LETTER B
0061 059A 302E 059A 0316 0062;0061 0316 059A 059A 302E 0062;0061 0316 059A 059A 302E 0062;0061 0316 059A 059A 302E 0062;0061 0316 059A 059A 302E 0062; # (a◌֚〮◌֚◌̖b; a◌̖◌֚◌֚〮b; a◌̖◌֚◌֚〮b; a◌̖◌֚◌֚〮b; a◌̖◌֚◌֚〮b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, HANGUL SINGLE DOT TONE MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, LATIN SMALL LETTER B
-0061 059A 0316 302A 059B 0062;0061 302A 0316 059B 059A 0062;0061 302A 0316 059B 059A 0062;0061 302A 0316 059B 059A 0062;0061 302A 0316 059B 059A 0062; # (a◌֚◌̖◌〪◌֛b; a◌〪◌̖◌֛◌֚b; a◌〪◌̖◌֛◌֚b; a◌〪◌̖◌֛◌֚b; a◌〪◌̖◌֛◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT TEVIR, LATIN SMALL LETTER B
-0061 059B 059A 0316 302A 0062;0061 302A 059B 0316 059A 0062;0061 302A 059B 0316 059A 0062;0061 302A 059B 0316 059A 0062;0061 302A 059B 0316 059A 0062; # (a◌֛◌֚◌̖◌〪b; a◌〪◌֛◌̖◌֚b; a◌〪◌֛◌̖◌֚b; a◌〪◌֛◌̖◌֚b; a◌〪◌֛◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT TEVIR, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 059B 0062;0061 1DFA 0316 059B 059A 0062;0061 1DFA 0316 059B 059A 0062;0061 1DFA 0316 059B 059A 0062;0061 1DFA 0316 059B 059A 0062; # (a◌֚◌̖◌᷺◌֛b; a◌᷺◌̖◌֛◌֚b; a◌᷺◌̖◌֛◌֚b; a◌᷺◌̖◌֛◌֚b; a◌᷺◌̖◌֛◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT TEVIR, LATIN SMALL LETTER B
+0061 059B 059A 0316 1DFA 0062;0061 1DFA 059B 0316 059A 0062;0061 1DFA 059B 0316 059A 0062;0061 1DFA 059B 0316 059A 0062;0061 1DFA 059B 0316 059A 0062; # (a◌֛◌֚◌̖◌᷺b; a◌᷺◌֛◌̖◌֚b; a◌᷺◌֛◌̖◌֚b; a◌᷺◌֛◌̖◌֚b; a◌᷺◌֛◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT TEVIR, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 059C 0062;00E0 05AE 059C 0315 0062;0061 05AE 0300 059C 0315 0062;00E0 05AE 059C 0315 0062;0061 05AE 0300 059C 0315 0062; # (a◌̕◌̀◌֮◌֜b; à◌֮◌֜◌̕b; a◌֮◌̀◌֜◌̕b; à◌֮◌֜◌̕b; a◌֮◌̀◌֜◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT GERESH, LATIN SMALL LETTER B
0061 059C 0315 0300 05AE 0062;0061 05AE 059C 0300 0315 0062;0061 05AE 059C 0300 0315 0062;0061 05AE 059C 0300 0315 0062;0061 05AE 059C 0300 0315 0062; # (a◌֜◌̕◌̀◌֮b; a◌֮◌֜◌̀◌̕b; a◌֮◌֜◌̀◌̕b; a◌֮◌֜◌̀◌̕b; a◌֮◌֜◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT GERESH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 059D 0062;00E0 05AE 059D 0315 0062;0061 05AE 0300 059D 0315 0062;00E0 05AE 059D 0315 0062;0061 05AE 0300 059D 0315 0062; # (a◌̕◌̀◌֮◌Öb; à◌֮◌Ö◌̕b; a◌֮◌̀◌Ö◌̕b; à◌֮◌Ö◌̕b; a◌֮◌̀◌Ö◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT GERESH MUQDAM, LATIN SMALL LETTER B
@@ -17247,24 +17306,24 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 05A0 0315 0300 05AE 0062;0061 05AE 05A0 0300 0315 0062;0061 05AE 05A0 0300 0315 0062;0061 05AE 05A0 0300 0315 0062;0061 05AE 05A0 0300 0315 0062; # (a◌֠◌̕◌̀◌֮b; a◌֮◌֠◌̀◌̕b; a◌֮◌֠◌̀◌̕b; a◌֮◌֠◌̀◌̕b; a◌֮◌֠◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT TELISHA GEDOLA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 05A1 0062;00E0 05AE 05A1 0315 0062;0061 05AE 0300 05A1 0315 0062;00E0 05AE 05A1 0315 0062;0061 05AE 0300 05A1 0315 0062; # (a◌̕◌̀◌֮◌֡b; à◌֮◌֡◌̕b; a◌֮◌̀◌֡◌̕b; à◌֮◌֡◌̕b; a◌֮◌̀◌֡◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT PAZER, LATIN SMALL LETTER B
0061 05A1 0315 0300 05AE 0062;0061 05AE 05A1 0300 0315 0062;0061 05AE 05A1 0300 0315 0062;0061 05AE 05A1 0300 0315 0062;0061 05AE 05A1 0300 0315 0062; # (a◌֡◌̕◌̀◌֮b; a◌֮◌֡◌̀◌̕b; a◌֮◌֡◌̀◌̕b; a◌֮◌֡◌̀◌̕b; a◌֮◌֡◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT PAZER, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 05A2 0062;0061 302A 0316 05A2 059A 0062;0061 302A 0316 05A2 059A 0062;0061 302A 0316 05A2 059A 0062;0061 302A 0316 05A2 059A 0062; # (a◌֚◌̖◌〪◌֢b; a◌〪◌̖◌֢◌֚b; a◌〪◌̖◌֢◌֚b; a◌〪◌̖◌֢◌֚b; a◌〪◌̖◌֢◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT ATNAH HAFUKH, LATIN SMALL LETTER B
-0061 05A2 059A 0316 302A 0062;0061 302A 05A2 0316 059A 0062;0061 302A 05A2 0316 059A 0062;0061 302A 05A2 0316 059A 0062;0061 302A 05A2 0316 059A 0062; # (a◌֢◌֚◌̖◌〪b; a◌〪◌֢◌̖◌֚b; a◌〪◌֢◌̖◌֚b; a◌〪◌֢◌̖◌֚b; a◌〪◌֢◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT ATNAH HAFUKH, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 05A3 0062;0061 302A 0316 05A3 059A 0062;0061 302A 0316 05A3 059A 0062;0061 302A 0316 05A3 059A 0062;0061 302A 0316 05A3 059A 0062; # (a◌֚◌̖◌〪◌֣b; a◌〪◌̖◌֣◌֚b; a◌〪◌̖◌֣◌֚b; a◌〪◌̖◌֣◌֚b; a◌〪◌̖◌֣◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT MUNAH, LATIN SMALL LETTER B
-0061 05A3 059A 0316 302A 0062;0061 302A 05A3 0316 059A 0062;0061 302A 05A3 0316 059A 0062;0061 302A 05A3 0316 059A 0062;0061 302A 05A3 0316 059A 0062; # (a◌֣◌֚◌̖◌〪b; a◌〪◌֣◌̖◌֚b; a◌〪◌֣◌̖◌֚b; a◌〪◌֣◌̖◌֚b; a◌〪◌֣◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MUNAH, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 05A4 0062;0061 302A 0316 05A4 059A 0062;0061 302A 0316 05A4 059A 0062;0061 302A 0316 05A4 059A 0062;0061 302A 0316 05A4 059A 0062; # (a◌֚◌̖◌〪◌֤b; a◌〪◌̖◌֤◌֚b; a◌〪◌̖◌֤◌֚b; a◌〪◌̖◌֤◌֚b; a◌〪◌̖◌֤◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT MAHAPAKH, LATIN SMALL LETTER B
-0061 05A4 059A 0316 302A 0062;0061 302A 05A4 0316 059A 0062;0061 302A 05A4 0316 059A 0062;0061 302A 05A4 0316 059A 0062;0061 302A 05A4 0316 059A 0062; # (a◌֤◌֚◌̖◌〪b; a◌〪◌֤◌̖◌֚b; a◌〪◌֤◌̖◌֚b; a◌〪◌֤◌̖◌֚b; a◌〪◌֤◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MAHAPAKH, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 05A5 0062;0061 302A 0316 05A5 059A 0062;0061 302A 0316 05A5 059A 0062;0061 302A 0316 05A5 059A 0062;0061 302A 0316 05A5 059A 0062; # (a◌֚◌̖◌〪◌֥b; a◌〪◌̖◌֥◌֚b; a◌〪◌̖◌֥◌֚b; a◌〪◌̖◌֥◌֚b; a◌〪◌̖◌֥◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT MERKHA, LATIN SMALL LETTER B
-0061 05A5 059A 0316 302A 0062;0061 302A 05A5 0316 059A 0062;0061 302A 05A5 0316 059A 0062;0061 302A 05A5 0316 059A 0062;0061 302A 05A5 0316 059A 0062; # (a◌֥◌֚◌̖◌〪b; a◌〪◌֥◌̖◌֚b; a◌〪◌֥◌̖◌֚b; a◌〪◌֥◌̖◌֚b; a◌〪◌֥◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MERKHA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 05A6 0062;0061 302A 0316 05A6 059A 0062;0061 302A 0316 05A6 059A 0062;0061 302A 0316 05A6 059A 0062;0061 302A 0316 05A6 059A 0062; # (a◌֚◌̖◌〪◌֦b; a◌〪◌̖◌֦◌֚b; a◌〪◌̖◌֦◌֚b; a◌〪◌̖◌֦◌֚b; a◌〪◌̖◌֦◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT MERKHA KEFULA, LATIN SMALL LETTER B
-0061 05A6 059A 0316 302A 0062;0061 302A 05A6 0316 059A 0062;0061 302A 05A6 0316 059A 0062;0061 302A 05A6 0316 059A 0062;0061 302A 05A6 0316 059A 0062; # (a◌֦◌֚◌̖◌〪b; a◌〪◌֦◌̖◌֚b; a◌〪◌֦◌̖◌֚b; a◌〪◌֦◌̖◌֚b; a◌〪◌֦◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MERKHA KEFULA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 05A7 0062;0061 302A 0316 05A7 059A 0062;0061 302A 0316 05A7 059A 0062;0061 302A 0316 05A7 059A 0062;0061 302A 0316 05A7 059A 0062; # (a◌֚◌̖◌〪◌֧b; a◌〪◌̖◌֧◌֚b; a◌〪◌̖◌֧◌֚b; a◌〪◌̖◌֧◌֚b; a◌〪◌̖◌֧◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT DARGA, LATIN SMALL LETTER B
-0061 05A7 059A 0316 302A 0062;0061 302A 05A7 0316 059A 0062;0061 302A 05A7 0316 059A 0062;0061 302A 05A7 0316 059A 0062;0061 302A 05A7 0316 059A 0062; # (a◌֧◌֚◌̖◌〪b; a◌〪◌֧◌̖◌֚b; a◌〪◌֧◌̖◌֚b; a◌〪◌֧◌̖◌֚b; a◌〪◌֧◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT DARGA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05A2 0062;0061 1DFA 0316 05A2 059A 0062;0061 1DFA 0316 05A2 059A 0062;0061 1DFA 0316 05A2 059A 0062;0061 1DFA 0316 05A2 059A 0062; # (a◌֚◌̖◌᷺◌֢b; a◌᷺◌̖◌֢◌֚b; a◌᷺◌̖◌֢◌֚b; a◌᷺◌̖◌֢◌֚b; a◌᷺◌̖◌֢◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT ATNAH HAFUKH, LATIN SMALL LETTER B
+0061 05A2 059A 0316 1DFA 0062;0061 1DFA 05A2 0316 059A 0062;0061 1DFA 05A2 0316 059A 0062;0061 1DFA 05A2 0316 059A 0062;0061 1DFA 05A2 0316 059A 0062; # (a◌֢◌֚◌̖◌᷺b; a◌᷺◌֢◌̖◌֚b; a◌᷺◌֢◌̖◌֚b; a◌᷺◌֢◌̖◌֚b; a◌᷺◌֢◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT ATNAH HAFUKH, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05A3 0062;0061 1DFA 0316 05A3 059A 0062;0061 1DFA 0316 05A3 059A 0062;0061 1DFA 0316 05A3 059A 0062;0061 1DFA 0316 05A3 059A 0062; # (a◌֚◌̖◌᷺◌֣b; a◌᷺◌̖◌֣◌֚b; a◌᷺◌̖◌֣◌֚b; a◌᷺◌̖◌֣◌֚b; a◌᷺◌̖◌֣◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT MUNAH, LATIN SMALL LETTER B
+0061 05A3 059A 0316 1DFA 0062;0061 1DFA 05A3 0316 059A 0062;0061 1DFA 05A3 0316 059A 0062;0061 1DFA 05A3 0316 059A 0062;0061 1DFA 05A3 0316 059A 0062; # (a◌֣◌֚◌̖◌᷺b; a◌᷺◌֣◌̖◌֚b; a◌᷺◌֣◌̖◌֚b; a◌᷺◌֣◌̖◌֚b; a◌᷺◌֣◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MUNAH, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05A4 0062;0061 1DFA 0316 05A4 059A 0062;0061 1DFA 0316 05A4 059A 0062;0061 1DFA 0316 05A4 059A 0062;0061 1DFA 0316 05A4 059A 0062; # (a◌֚◌̖◌᷺◌֤b; a◌᷺◌̖◌֤◌֚b; a◌᷺◌̖◌֤◌֚b; a◌᷺◌̖◌֤◌֚b; a◌᷺◌̖◌֤◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT MAHAPAKH, LATIN SMALL LETTER B
+0061 05A4 059A 0316 1DFA 0062;0061 1DFA 05A4 0316 059A 0062;0061 1DFA 05A4 0316 059A 0062;0061 1DFA 05A4 0316 059A 0062;0061 1DFA 05A4 0316 059A 0062; # (a◌֤◌֚◌̖◌᷺b; a◌᷺◌֤◌̖◌֚b; a◌᷺◌֤◌̖◌֚b; a◌᷺◌֤◌̖◌֚b; a◌᷺◌֤◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MAHAPAKH, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05A5 0062;0061 1DFA 0316 05A5 059A 0062;0061 1DFA 0316 05A5 059A 0062;0061 1DFA 0316 05A5 059A 0062;0061 1DFA 0316 05A5 059A 0062; # (a◌֚◌̖◌᷺◌֥b; a◌᷺◌̖◌֥◌֚b; a◌᷺◌̖◌֥◌֚b; a◌᷺◌̖◌֥◌֚b; a◌᷺◌̖◌֥◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT MERKHA, LATIN SMALL LETTER B
+0061 05A5 059A 0316 1DFA 0062;0061 1DFA 05A5 0316 059A 0062;0061 1DFA 05A5 0316 059A 0062;0061 1DFA 05A5 0316 059A 0062;0061 1DFA 05A5 0316 059A 0062; # (a◌֥◌֚◌̖◌᷺b; a◌᷺◌֥◌̖◌֚b; a◌᷺◌֥◌̖◌֚b; a◌᷺◌֥◌̖◌֚b; a◌᷺◌֥◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MERKHA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05A6 0062;0061 1DFA 0316 05A6 059A 0062;0061 1DFA 0316 05A6 059A 0062;0061 1DFA 0316 05A6 059A 0062;0061 1DFA 0316 05A6 059A 0062; # (a◌֚◌̖◌᷺◌֦b; a◌᷺◌̖◌֦◌֚b; a◌᷺◌̖◌֦◌֚b; a◌᷺◌̖◌֦◌֚b; a◌᷺◌̖◌֦◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT MERKHA KEFULA, LATIN SMALL LETTER B
+0061 05A6 059A 0316 1DFA 0062;0061 1DFA 05A6 0316 059A 0062;0061 1DFA 05A6 0316 059A 0062;0061 1DFA 05A6 0316 059A 0062;0061 1DFA 05A6 0316 059A 0062; # (a◌֦◌֚◌̖◌᷺b; a◌᷺◌֦◌̖◌֚b; a◌᷺◌֦◌̖◌֚b; a◌᷺◌֦◌̖◌֚b; a◌᷺◌֦◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT MERKHA KEFULA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05A7 0062;0061 1DFA 0316 05A7 059A 0062;0061 1DFA 0316 05A7 059A 0062;0061 1DFA 0316 05A7 059A 0062;0061 1DFA 0316 05A7 059A 0062; # (a◌֚◌̖◌᷺◌֧b; a◌᷺◌̖◌֧◌֚b; a◌᷺◌̖◌֧◌֚b; a◌᷺◌̖◌֧◌֚b; a◌᷺◌̖◌֧◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT DARGA, LATIN SMALL LETTER B
+0061 05A7 059A 0316 1DFA 0062;0061 1DFA 05A7 0316 059A 0062;0061 1DFA 05A7 0316 059A 0062;0061 1DFA 05A7 0316 059A 0062;0061 1DFA 05A7 0316 059A 0062; # (a◌֧◌֚◌̖◌᷺b; a◌᷺◌֧◌̖◌֚b; a◌᷺◌֧◌̖◌֚b; a◌᷺◌֧◌̖◌֚b; a◌᷺◌֧◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT DARGA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 05A8 0062;00E0 05AE 05A8 0315 0062;0061 05AE 0300 05A8 0315 0062;00E0 05AE 05A8 0315 0062;0061 05AE 0300 05A8 0315 0062; # (a◌̕◌̀◌֮◌֨b; à◌֮◌֨◌̕b; a◌֮◌̀◌֨◌̕b; à◌֮◌֨◌̕b; a◌֮◌̀◌֨◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT QADMA, LATIN SMALL LETTER B
0061 05A8 0315 0300 05AE 0062;0061 05AE 05A8 0300 0315 0062;0061 05AE 05A8 0300 0315 0062;0061 05AE 05A8 0300 0315 0062;0061 05AE 05A8 0300 0315 0062; # (a◌֨◌̕◌̀◌֮b; a◌֮◌֨◌̀◌̕b; a◌֮◌֨◌̀◌̕b; a◌֮◌֨◌̀◌̕b; a◌֮◌֨◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT QADMA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 05A9 0062;00E0 05AE 05A9 0315 0062;0061 05AE 0300 05A9 0315 0062;00E0 05AE 05A9 0315 0062;0061 05AE 0300 05A9 0315 0062; # (a◌̕◌̀◌֮◌֩b; à◌֮◌֩◌̕b; a◌֮◌̀◌֩◌̕b; à◌֮◌֩◌̕b; a◌֮◌̀◌֩◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT TELISHA QETANA, LATIN SMALL LETTER B
0061 05A9 0315 0300 05AE 0062;0061 05AE 05A9 0300 0315 0062;0061 05AE 05A9 0300 0315 0062;0061 05AE 05A9 0300 0315 0062;0061 05AE 05A9 0300 0315 0062; # (a◌֩◌̕◌̀◌֮b; a◌֮◌֩◌̀◌̕b; a◌֮◌֩◌̀◌̕b; a◌֮◌֩◌̀◌̕b; a◌֮◌֩◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT TELISHA QETANA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 05AA 0062;0061 302A 0316 05AA 059A 0062;0061 302A 0316 05AA 059A 0062;0061 302A 0316 05AA 059A 0062;0061 302A 0316 05AA 059A 0062; # (a◌֚◌̖◌〪◌֪b; a◌〪◌̖◌֪◌֚b; a◌〪◌̖◌֪◌֚b; a◌〪◌̖◌֪◌֚b; a◌〪◌̖◌֪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW ACCENT YERAH BEN YOMO, LATIN SMALL LETTER B
-0061 05AA 059A 0316 302A 0062;0061 302A 05AA 0316 059A 0062;0061 302A 05AA 0316 059A 0062;0061 302A 05AA 0316 059A 0062;0061 302A 05AA 0316 059A 0062; # (a◌֪◌֚◌̖◌〪b; a◌〪◌֪◌̖◌֚b; a◌〪◌֪◌̖◌֚b; a◌〪◌֪◌̖◌֚b; a◌〪◌֪◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YERAH BEN YOMO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05AA 0062;0061 1DFA 0316 05AA 059A 0062;0061 1DFA 0316 05AA 059A 0062;0061 1DFA 0316 05AA 059A 0062;0061 1DFA 0316 05AA 059A 0062; # (a◌֚◌̖◌᷺◌֪b; a◌᷺◌̖◌֪◌֚b; a◌᷺◌̖◌֪◌֚b; a◌᷺◌̖◌֪◌֚b; a◌᷺◌̖◌֪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW ACCENT YERAH BEN YOMO, LATIN SMALL LETTER B
+0061 05AA 059A 0316 1DFA 0062;0061 1DFA 05AA 0316 059A 0062;0061 1DFA 05AA 0316 059A 0062;0061 1DFA 05AA 0316 059A 0062;0061 1DFA 05AA 0316 059A 0062; # (a◌֪◌֚◌̖◌᷺b; a◌᷺◌֪◌̖◌֚b; a◌᷺◌֪◌̖◌֚b; a◌᷺◌֪◌̖◌֚b; a◌᷺◌֪◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YERAH BEN YOMO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 05AB 0062;00E0 05AE 05AB 0315 0062;0061 05AE 0300 05AB 0315 0062;00E0 05AE 05AB 0315 0062;0061 05AE 0300 05AB 0315 0062; # (a◌̕◌̀◌֮◌֫b; à◌֮◌֫◌̕b; a◌֮◌̀◌֫◌̕b; à◌֮◌֫◌̕b; a◌֮◌̀◌֫◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT OLE, LATIN SMALL LETTER B
0061 05AB 0315 0300 05AE 0062;0061 05AE 05AB 0300 0315 0062;0061 05AE 05AB 0300 0315 0062;0061 05AE 05AB 0300 0315 0062;0061 05AE 05AB 0300 0315 0062; # (a◌֫◌̕◌̀◌֮b; a◌֮◌֫◌̀◌̕b; a◌֮◌֫◌̀◌̕b; a◌֮◌֫◌̀◌̕b; a◌֮◌֫◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW ACCENT OLE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 05AC 0062;00E0 05AE 05AC 0315 0062;0061 05AE 0300 05AC 0315 0062;00E0 05AE 05AC 0315 0062;0061 05AE 0300 05AC 0315 0062; # (a◌̕◌̀◌֮◌֬b; à◌֮◌֬◌̕b; a◌֮◌̀◌֬◌̕b; à◌֮◌֬◌̕b; a◌֮◌̀◌֬◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW ACCENT ILUY, LATIN SMALL LETTER B
@@ -17311,8 +17370,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 05C2 FB1E 05C2 05C1 0062;0061 05C1 05C2 05C2 FB1E 0062;0061 05C1 05C2 05C2 FB1E 0062;0061 05C1 05C2 05C2 FB1E 0062;0061 05C1 05C2 05C2 FB1E 0062; # (a◌ׂ◌ﬞ◌ׂ◌×b; aâ—Œ×◌ׂ◌ׂ◌ﬞb; aâ—Œ×◌ׂ◌ׂ◌ﬞb; aâ—Œ×◌ׂ◌ׂ◌ﬞb; aâ—Œ×◌ׂ◌ׂ◌ﬞb; ) LATIN SMALL LETTER A, HEBREW POINT SIN DOT, HEBREW POINT JUDEO-SPANISH VARIKA, HEBREW POINT SIN DOT, HEBREW POINT SHIN DOT, LATIN SMALL LETTER B
0061 0315 0300 05AE 05C4 0062;00E0 05AE 05C4 0315 0062;0061 05AE 0300 05C4 0315 0062;00E0 05AE 05C4 0315 0062;0061 05AE 0300 05C4 0315 0062; # (a◌̕◌̀◌֮◌ׄb; à◌֮◌ׄ◌̕b; a◌֮◌̀◌ׄ◌̕b; à◌֮◌ׄ◌̕b; a◌֮◌̀◌ׄ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HEBREW MARK UPPER DOT, LATIN SMALL LETTER B
0061 05C4 0315 0300 05AE 0062;0061 05AE 05C4 0300 0315 0062;0061 05AE 05C4 0300 0315 0062;0061 05AE 05C4 0300 0315 0062;0061 05AE 05C4 0300 0315 0062; # (a◌ׄ◌̕◌̀◌֮b; a◌֮◌ׄ◌̀◌̕b; a◌֮◌ׄ◌̀◌̕b; a◌֮◌ׄ◌̀◌̕b; a◌֮◌ׄ◌̀◌̕b; ) LATIN SMALL LETTER A, HEBREW MARK UPPER DOT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 05C5 0062;0061 302A 0316 05C5 059A 0062;0061 302A 0316 05C5 059A 0062;0061 302A 0316 05C5 059A 0062;0061 302A 0316 05C5 059A 0062; # (a◌֚◌̖◌〪◌ׅb; a◌〪◌̖◌ׅ◌֚b; a◌〪◌̖◌ׅ◌֚b; a◌〪◌̖◌ׅ◌֚b; a◌〪◌̖◌ׅ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, HEBREW MARK LOWER DOT, LATIN SMALL LETTER B
-0061 05C5 059A 0316 302A 0062;0061 302A 05C5 0316 059A 0062;0061 302A 05C5 0316 059A 0062;0061 302A 05C5 0316 059A 0062;0061 302A 05C5 0316 059A 0062; # (a◌ׅ◌֚◌̖◌〪b; a◌〪◌ׅ◌̖◌֚b; a◌〪◌ׅ◌̖◌֚b; a◌〪◌ׅ◌̖◌֚b; a◌〪◌ׅ◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW MARK LOWER DOT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 05C5 0062;0061 1DFA 0316 05C5 059A 0062;0061 1DFA 0316 05C5 059A 0062;0061 1DFA 0316 05C5 059A 0062;0061 1DFA 0316 05C5 059A 0062; # (a◌֚◌̖◌᷺◌ׅb; a◌᷺◌̖◌ׅ◌֚b; a◌᷺◌̖◌ׅ◌֚b; a◌᷺◌̖◌ׅ◌֚b; a◌᷺◌̖◌ׅ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, HEBREW MARK LOWER DOT, LATIN SMALL LETTER B
+0061 05C5 059A 0316 1DFA 0062;0061 1DFA 05C5 0316 059A 0062;0061 1DFA 05C5 0316 059A 0062;0061 1DFA 05C5 0316 059A 0062;0061 1DFA 05C5 0316 059A 0062; # (a◌ׅ◌֚◌̖◌᷺b; a◌᷺◌ׅ◌̖◌֚b; a◌᷺◌ׅ◌̖◌֚b; a◌᷺◌ׅ◌̖◌֚b; a◌᷺◌ׅ◌̖◌֚b; ) LATIN SMALL LETTER A, HEBREW MARK LOWER DOT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 05B9 05B8 05B7 05C7 0062;0061 05B7 05B8 05C7 05B9 0062;0061 05B7 05B8 05C7 05B9 0062;0061 05B7 05B8 05C7 05B9 0062;0061 05B7 05B8 05C7 05B9 0062; # (a◌ֹ◌ָ◌ַ◌ׇb; a◌ַ◌ָ◌ׇ◌ֹb; a◌ַ◌ָ◌ׇ◌ֹb; a◌ַ◌ָ◌ׇ◌ֹb; a◌ַ◌ָ◌ׇ◌ֹb; ) LATIN SMALL LETTER A, HEBREW POINT HOLAM, HEBREW POINT QAMATS, HEBREW POINT PATAH, HEBREW POINT QAMATS QATAN, LATIN SMALL LETTER B
0061 05C7 05B9 05B8 05B7 0062;0061 05B7 05C7 05B8 05B9 0062;0061 05B7 05C7 05B8 05B9 0062;0061 05B7 05C7 05B8 05B9 0062;0061 05B7 05C7 05B8 05B9 0062; # (a◌ׇ◌ֹ◌ָ◌ַb; a◌ַ◌ׇ◌ָ◌ֹb; a◌ַ◌ׇ◌ָ◌ֹb; a◌ַ◌ׇ◌ָ◌ֹb; a◌ַ◌ׇ◌ָ◌ֹb; ) LATIN SMALL LETTER A, HEBREW POINT QAMATS QATAN, HEBREW POINT HOLAM, HEBREW POINT QAMATS, HEBREW POINT PATAH, LATIN SMALL LETTER B
0061 0315 0300 05AE 0610 0062;00E0 05AE 0610 0315 0062;0061 05AE 0300 0610 0315 0062;00E0 05AE 0610 0315 0062;0061 05AE 0300 0610 0315 0062; # (a◌̕◌̀◌֮◌Øb; à◌֮◌Ø◌̕b; a◌֮◌̀◌Ø◌̕b; à◌֮◌Ø◌̕b; a◌֮◌̀◌Ø◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM, LATIN SMALL LETTER B
@@ -17357,10 +17416,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0653 0315 0300 05AE 0062;0061 05AE 0653 0300 0315 0062;0061 05AE 0653 0300 0315 0062;0061 05AE 0653 0300 0315 0062;0061 05AE 0653 0300 0315 0062; # (a◌ٓ◌̕◌̀◌֮b; a◌֮◌ٓ◌̀◌̕b; a◌֮◌ٓ◌̀◌̕b; a◌֮◌ٓ◌̀◌̕b; a◌֮◌ٓ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC MADDAH ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0654 0062;00E0 05AE 0654 0315 0062;0061 05AE 0300 0654 0315 0062;00E0 05AE 0654 0315 0062;0061 05AE 0300 0654 0315 0062; # (a◌̕◌̀◌֮◌ٔb; à◌֮◌ٔ◌̕b; a◌֮◌̀◌ٔ◌̕b; à◌֮◌ٔ◌̕b; a◌֮◌̀◌ٔ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC HAMZA ABOVE, LATIN SMALL LETTER B
0061 0654 0315 0300 05AE 0062;0061 05AE 0654 0300 0315 0062;0061 05AE 0654 0300 0315 0062;0061 05AE 0654 0300 0315 0062;0061 05AE 0654 0300 0315 0062; # (a◌ٔ◌̕◌̀◌֮b; a◌֮◌ٔ◌̀◌̕b; a◌֮◌ٔ◌̀◌̕b; a◌֮◌ٔ◌̀◌̕b; a◌֮◌ٔ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC HAMZA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0655 0062;0061 302A 0316 0655 059A 0062;0061 302A 0316 0655 059A 0062;0061 302A 0316 0655 059A 0062;0061 302A 0316 0655 059A 0062; # (a◌֚◌̖◌〪◌ٕb; a◌〪◌̖◌ٕ◌֚b; a◌〪◌̖◌ٕ◌֚b; a◌〪◌̖◌ٕ◌֚b; a◌〪◌̖◌ٕ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC HAMZA BELOW, LATIN SMALL LETTER B
-0061 0655 059A 0316 302A 0062;0061 302A 0655 0316 059A 0062;0061 302A 0655 0316 059A 0062;0061 302A 0655 0316 059A 0062;0061 302A 0655 0316 059A 0062; # (a◌ٕ◌֚◌̖◌〪b; a◌〪◌ٕ◌̖◌֚b; a◌〪◌ٕ◌̖◌֚b; a◌〪◌ٕ◌̖◌֚b; a◌〪◌ٕ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC HAMZA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0656 0062;0061 302A 0316 0656 059A 0062;0061 302A 0316 0656 059A 0062;0061 302A 0316 0656 059A 0062;0061 302A 0316 0656 059A 0062; # (a◌֚◌̖◌〪◌ٖb; a◌〪◌̖◌ٖ◌֚b; a◌〪◌̖◌ٖ◌֚b; a◌〪◌̖◌ٖ◌֚b; a◌〪◌̖◌ٖ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC SUBSCRIPT ALEF, LATIN SMALL LETTER B
-0061 0656 059A 0316 302A 0062;0061 302A 0656 0316 059A 0062;0061 302A 0656 0316 059A 0062;0061 302A 0656 0316 059A 0062;0061 302A 0656 0316 059A 0062; # (a◌ٖ◌֚◌̖◌〪b; a◌〪◌ٖ◌̖◌֚b; a◌〪◌ٖ◌̖◌֚b; a◌〪◌ٖ◌̖◌֚b; a◌〪◌ٖ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SUBSCRIPT ALEF, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0655 0062;0061 1DFA 0316 0655 059A 0062;0061 1DFA 0316 0655 059A 0062;0061 1DFA 0316 0655 059A 0062;0061 1DFA 0316 0655 059A 0062; # (a◌֚◌̖◌᷺◌ٕb; a◌᷺◌̖◌ٕ◌֚b; a◌᷺◌̖◌ٕ◌֚b; a◌᷺◌̖◌ٕ◌֚b; a◌᷺◌̖◌ٕ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC HAMZA BELOW, LATIN SMALL LETTER B
+0061 0655 059A 0316 1DFA 0062;0061 1DFA 0655 0316 059A 0062;0061 1DFA 0655 0316 059A 0062;0061 1DFA 0655 0316 059A 0062;0061 1DFA 0655 0316 059A 0062; # (a◌ٕ◌֚◌̖◌᷺b; a◌᷺◌ٕ◌̖◌֚b; a◌᷺◌ٕ◌̖◌֚b; a◌᷺◌ٕ◌̖◌֚b; a◌᷺◌ٕ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC HAMZA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0656 0062;0061 1DFA 0316 0656 059A 0062;0061 1DFA 0316 0656 059A 0062;0061 1DFA 0316 0656 059A 0062;0061 1DFA 0316 0656 059A 0062; # (a◌֚◌̖◌᷺◌ٖb; a◌᷺◌̖◌ٖ◌֚b; a◌᷺◌̖◌ٖ◌֚b; a◌᷺◌̖◌ٖ◌֚b; a◌᷺◌̖◌ٖ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SUBSCRIPT ALEF, LATIN SMALL LETTER B
+0061 0656 059A 0316 1DFA 0062;0061 1DFA 0656 0316 059A 0062;0061 1DFA 0656 0316 059A 0062;0061 1DFA 0656 0316 059A 0062;0061 1DFA 0656 0316 059A 0062; # (a◌ٖ◌֚◌̖◌᷺b; a◌᷺◌ٖ◌̖◌֚b; a◌᷺◌ٖ◌̖◌֚b; a◌᷺◌ٖ◌̖◌֚b; a◌᷺◌ٖ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SUBSCRIPT ALEF, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0657 0062;00E0 05AE 0657 0315 0062;0061 05AE 0300 0657 0315 0062;00E0 05AE 0657 0315 0062;0061 05AE 0300 0657 0315 0062; # (a◌̕◌̀◌֮◌ٗb; à◌֮◌ٗ◌̕b; a◌֮◌̀◌ٗ◌̕b; à◌֮◌ٗ◌̕b; a◌֮◌̀◌ٗ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC INVERTED DAMMA, LATIN SMALL LETTER B
0061 0657 0315 0300 05AE 0062;0061 05AE 0657 0300 0315 0062;0061 05AE 0657 0300 0315 0062;0061 05AE 0657 0300 0315 0062;0061 05AE 0657 0300 0315 0062; # (a◌ٗ◌̕◌̀◌֮b; a◌֮◌ٗ◌̀◌̕b; a◌֮◌ٗ◌̀◌̕b; a◌֮◌ٗ◌̀◌̕b; a◌֮◌ٗ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC INVERTED DAMMA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0658 0062;00E0 05AE 0658 0315 0062;0061 05AE 0300 0658 0315 0062;00E0 05AE 0658 0315 0062;0061 05AE 0300 0658 0315 0062; # (a◌̕◌̀◌֮◌٘b; à◌֮◌٘◌̕b; a◌֮◌̀◌٘◌̕b; à◌֮◌٘◌̕b; a◌֮◌̀◌٘◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC MARK NOON GHUNNA, LATIN SMALL LETTER B
@@ -17371,14 +17430,14 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 065A 0315 0300 05AE 0062;0061 05AE 065A 0300 0315 0062;0061 05AE 065A 0300 0315 0062;0061 05AE 065A 0300 0315 0062;0061 05AE 065A 0300 0315 0062; # (a◌ٚ◌̕◌̀◌֮b; a◌֮◌ٚ◌̀◌̕b; a◌֮◌ٚ◌̀◌̕b; a◌֮◌ٚ◌̀◌̕b; a◌֮◌ٚ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC VOWEL SIGN SMALL V ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 065B 0062;00E0 05AE 065B 0315 0062;0061 05AE 0300 065B 0315 0062;00E0 05AE 065B 0315 0062;0061 05AE 0300 065B 0315 0062; # (a◌̕◌̀◌֮◌ٛb; à◌֮◌ٛ◌̕b; a◌֮◌̀◌ٛ◌̕b; à◌֮◌ٛ◌̕b; a◌֮◌̀◌ٛ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC VOWEL SIGN INVERTED SMALL V ABOVE, LATIN SMALL LETTER B
0061 065B 0315 0300 05AE 0062;0061 05AE 065B 0300 0315 0062;0061 05AE 065B 0300 0315 0062;0061 05AE 065B 0300 0315 0062;0061 05AE 065B 0300 0315 0062; # (a◌ٛ◌̕◌̀◌֮b; a◌֮◌ٛ◌̀◌̕b; a◌֮◌ٛ◌̀◌̕b; a◌֮◌ٛ◌̀◌̕b; a◌֮◌ٛ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC VOWEL SIGN INVERTED SMALL V ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 065C 0062;0061 302A 0316 065C 059A 0062;0061 302A 0316 065C 059A 0062;0061 302A 0316 065C 059A 0062;0061 302A 0316 065C 059A 0062; # (a◌֚◌̖◌〪◌ٜb; a◌〪◌̖◌ٜ◌֚b; a◌〪◌̖◌ٜ◌֚b; a◌〪◌̖◌ٜ◌֚b; a◌〪◌̖◌ٜ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC VOWEL SIGN DOT BELOW, LATIN SMALL LETTER B
-0061 065C 059A 0316 302A 0062;0061 302A 065C 0316 059A 0062;0061 302A 065C 0316 059A 0062;0061 302A 065C 0316 059A 0062;0061 302A 065C 0316 059A 0062; # (a◌ٜ◌֚◌̖◌〪b; a◌〪◌ٜ◌̖◌֚b; a◌〪◌ٜ◌̖◌֚b; a◌〪◌ٜ◌̖◌֚b; a◌〪◌ٜ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC VOWEL SIGN DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 065C 0062;0061 1DFA 0316 065C 059A 0062;0061 1DFA 0316 065C 059A 0062;0061 1DFA 0316 065C 059A 0062;0061 1DFA 0316 065C 059A 0062; # (a◌֚◌̖◌᷺◌ٜb; a◌᷺◌̖◌ٜ◌֚b; a◌᷺◌̖◌ٜ◌֚b; a◌᷺◌̖◌ٜ◌֚b; a◌᷺◌̖◌ٜ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC VOWEL SIGN DOT BELOW, LATIN SMALL LETTER B
+0061 065C 059A 0316 1DFA 0062;0061 1DFA 065C 0316 059A 0062;0061 1DFA 065C 0316 059A 0062;0061 1DFA 065C 0316 059A 0062;0061 1DFA 065C 0316 059A 0062; # (a◌ٜ◌֚◌̖◌᷺b; a◌᷺◌ٜ◌̖◌֚b; a◌᷺◌ٜ◌̖◌֚b; a◌᷺◌ٜ◌̖◌֚b; a◌᷺◌ٜ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC VOWEL SIGN DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 065D 0062;00E0 05AE 065D 0315 0062;0061 05AE 0300 065D 0315 0062;00E0 05AE 065D 0315 0062;0061 05AE 0300 065D 0315 0062; # (a◌̕◌̀◌֮◌Ùb; à◌֮◌Ù◌̕b; a◌֮◌̀◌Ù◌̕b; à◌֮◌Ù◌̕b; a◌֮◌̀◌Ù◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC REVERSED DAMMA, LATIN SMALL LETTER B
0061 065D 0315 0300 05AE 0062;0061 05AE 065D 0300 0315 0062;0061 05AE 065D 0300 0315 0062;0061 05AE 065D 0300 0315 0062;0061 05AE 065D 0300 0315 0062; # (aâ—ŒÙ◌̕◌̀◌֮b; a◌֮◌Ù◌̀◌̕b; a◌֮◌Ù◌̀◌̕b; a◌֮◌Ù◌̀◌̕b; a◌֮◌Ù◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC REVERSED DAMMA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 065E 0062;00E0 05AE 065E 0315 0062;0061 05AE 0300 065E 0315 0062;00E0 05AE 065E 0315 0062;0061 05AE 0300 065E 0315 0062; # (a◌̕◌̀◌֮◌ٞb; à◌֮◌ٞ◌̕b; a◌֮◌̀◌ٞ◌̕b; à◌֮◌ٞ◌̕b; a◌֮◌̀◌ٞ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC FATHA WITH TWO DOTS, LATIN SMALL LETTER B
0061 065E 0315 0300 05AE 0062;0061 05AE 065E 0300 0315 0062;0061 05AE 065E 0300 0315 0062;0061 05AE 065E 0300 0315 0062;0061 05AE 065E 0300 0315 0062; # (a◌ٞ◌̕◌̀◌֮b; a◌֮◌ٞ◌̀◌̕b; a◌֮◌ٞ◌̀◌̕b; a◌֮◌ٞ◌̀◌̕b; a◌֮◌ٞ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC FATHA WITH TWO DOTS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 065F 0062;0061 302A 0316 065F 059A 0062;0061 302A 0316 065F 059A 0062;0061 302A 0316 065F 059A 0062;0061 302A 0316 065F 059A 0062; # (a◌֚◌̖◌〪◌ٟb; a◌〪◌̖◌ٟ◌֚b; a◌〪◌̖◌ٟ◌֚b; a◌〪◌̖◌ٟ◌֚b; a◌〪◌̖◌ٟ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC WAVY HAMZA BELOW, LATIN SMALL LETTER B
-0061 065F 059A 0316 302A 0062;0061 302A 065F 0316 059A 0062;0061 302A 065F 0316 059A 0062;0061 302A 065F 0316 059A 0062;0061 302A 065F 0316 059A 0062; # (a◌ٟ◌֚◌̖◌〪b; a◌〪◌ٟ◌̖◌֚b; a◌〪◌ٟ◌̖◌֚b; a◌〪◌ٟ◌̖◌֚b; a◌〪◌ٟ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC WAVY HAMZA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 065F 0062;0061 1DFA 0316 065F 059A 0062;0061 1DFA 0316 065F 059A 0062;0061 1DFA 0316 065F 059A 0062;0061 1DFA 0316 065F 059A 0062; # (a◌֚◌̖◌᷺◌ٟb; a◌᷺◌̖◌ٟ◌֚b; a◌᷺◌̖◌ٟ◌֚b; a◌᷺◌̖◌ٟ◌֚b; a◌᷺◌̖◌ٟ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC WAVY HAMZA BELOW, LATIN SMALL LETTER B
+0061 065F 059A 0316 1DFA 0062;0061 1DFA 065F 0316 059A 0062;0061 1DFA 065F 0316 059A 0062;0061 1DFA 065F 0316 059A 0062;0061 1DFA 065F 0316 059A 0062; # (a◌ٟ◌֚◌̖◌᷺b; a◌᷺◌ٟ◌̖◌֚b; a◌᷺◌ٟ◌̖◌֚b; a◌᷺◌ٟ◌̖◌֚b; a◌᷺◌ٟ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC WAVY HAMZA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0711 0670 0652 0670 0062;0061 0652 0670 0670 0711 0062;0061 0652 0670 0670 0711 0062;0061 0652 0670 0670 0711 0062;0061 0652 0670 0670 0711 0062; # (a◌ܑ◌ٰ◌ْ◌ٰb; a◌ْ◌ٰ◌ٰ◌ܑb; a◌ْ◌ٰ◌ٰ◌ܑb; a◌ْ◌ٰ◌ٰ◌ܑb; a◌ْ◌ٰ◌ٰ◌ܑb; ) LATIN SMALL LETTER A, SYRIAC LETTER SUPERSCRIPT ALAPH, ARABIC LETTER SUPERSCRIPT ALEF, ARABIC SUKUN, ARABIC LETTER SUPERSCRIPT ALEF, LATIN SMALL LETTER B
0061 0670 0711 0670 0652 0062;0061 0652 0670 0670 0711 0062;0061 0652 0670 0670 0711 0062;0061 0652 0670 0670 0711 0062;0061 0652 0670 0670 0711 0062; # (a◌ٰ◌ܑ◌ٰ◌ْb; a◌ْ◌ٰ◌ٰ◌ܑb; a◌ْ◌ٰ◌ٰ◌ܑb; a◌ْ◌ٰ◌ٰ◌ܑb; a◌ْ◌ٰ◌ٰ◌ܑb; ) LATIN SMALL LETTER A, ARABIC LETTER SUPERSCRIPT ALEF, SYRIAC LETTER SUPERSCRIPT ALAPH, ARABIC LETTER SUPERSCRIPT ALEF, ARABIC SUKUN, LATIN SMALL LETTER B
0061 0315 0300 05AE 06D6 0062;00E0 05AE 06D6 0315 0062;0061 05AE 0300 06D6 0315 0062;00E0 05AE 06D6 0315 0062;0061 05AE 0300 06D6 0315 0062; # (a◌̕◌̀◌֮◌ۖb; à◌֮◌ۖ◌̕b; a◌֮◌̀◌ۖ◌̕b; à◌֮◌ۖ◌̕b; a◌֮◌̀◌ۖ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA, LATIN SMALL LETTER B
@@ -17403,74 +17462,74 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 06E1 0315 0300 05AE 0062;0061 05AE 06E1 0300 0315 0062;0061 05AE 06E1 0300 0315 0062;0061 05AE 06E1 0300 0315 0062;0061 05AE 06E1 0300 0315 0062; # (a◌ۡ◌̕◌̀◌֮b; a◌֮◌ۡ◌̀◌̕b; a◌֮◌ۡ◌̀◌̕b; a◌֮◌ۡ◌̀◌̕b; a◌֮◌ۡ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH DOTLESS HEAD OF KHAH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 06E2 0062;00E0 05AE 06E2 0315 0062;0061 05AE 0300 06E2 0315 0062;00E0 05AE 06E2 0315 0062;0061 05AE 0300 06E2 0315 0062; # (a◌̕◌̀◌֮◌ۢb; à◌֮◌ۢ◌̕b; a◌֮◌̀◌ۢ◌̕b; à◌֮◌ۢ◌̕b; a◌֮◌̀◌ۢ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH MEEM ISOLATED FORM, LATIN SMALL LETTER B
0061 06E2 0315 0300 05AE 0062;0061 05AE 06E2 0300 0315 0062;0061 05AE 06E2 0300 0315 0062;0061 05AE 06E2 0300 0315 0062;0061 05AE 06E2 0300 0315 0062; # (a◌ۢ◌̕◌̀◌֮b; a◌֮◌ۢ◌̀◌̕b; a◌֮◌ۢ◌̀◌̕b; a◌֮◌ۢ◌̀◌̕b; a◌֮◌ۢ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH MEEM ISOLATED FORM, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 06E3 0062;0061 302A 0316 06E3 059A 0062;0061 302A 0316 06E3 059A 0062;0061 302A 0316 06E3 059A 0062;0061 302A 0316 06E3 059A 0062; # (a◌֚◌̖◌〪◌ۣb; a◌〪◌̖◌ۣ◌֚b; a◌〪◌̖◌ۣ◌֚b; a◌〪◌̖◌ۣ◌֚b; a◌〪◌̖◌ۣ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC SMALL LOW SEEN, LATIN SMALL LETTER B
-0061 06E3 059A 0316 302A 0062;0061 302A 06E3 0316 059A 0062;0061 302A 06E3 0316 059A 0062;0061 302A 06E3 0316 059A 0062;0061 302A 06E3 0316 059A 0062; # (a◌ۣ◌֚◌̖◌〪b; a◌〪◌ۣ◌̖◌֚b; a◌〪◌ۣ◌̖◌֚b; a◌〪◌ۣ◌̖◌֚b; a◌〪◌ۣ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW SEEN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 06E3 0062;0061 1DFA 0316 06E3 059A 0062;0061 1DFA 0316 06E3 059A 0062;0061 1DFA 0316 06E3 059A 0062;0061 1DFA 0316 06E3 059A 0062; # (a◌֚◌̖◌᷺◌ۣb; a◌᷺◌̖◌ۣ◌֚b; a◌᷺◌̖◌ۣ◌֚b; a◌᷺◌̖◌ۣ◌֚b; a◌᷺◌̖◌ۣ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW SEEN, LATIN SMALL LETTER B
+0061 06E3 059A 0316 1DFA 0062;0061 1DFA 06E3 0316 059A 0062;0061 1DFA 06E3 0316 059A 0062;0061 1DFA 06E3 0316 059A 0062;0061 1DFA 06E3 0316 059A 0062; # (a◌ۣ◌֚◌̖◌᷺b; a◌᷺◌ۣ◌̖◌֚b; a◌᷺◌ۣ◌̖◌֚b; a◌᷺◌ۣ◌̖◌֚b; a◌᷺◌ۣ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW SEEN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 06E4 0062;00E0 05AE 06E4 0315 0062;0061 05AE 0300 06E4 0315 0062;00E0 05AE 06E4 0315 0062;0061 05AE 0300 06E4 0315 0062; # (a◌̕◌̀◌֮◌ۤb; à◌֮◌ۤ◌̕b; a◌֮◌̀◌ۤ◌̕b; à◌֮◌ۤ◌̕b; a◌֮◌̀◌ۤ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH MADDA, LATIN SMALL LETTER B
0061 06E4 0315 0300 05AE 0062;0061 05AE 06E4 0300 0315 0062;0061 05AE 06E4 0300 0315 0062;0061 05AE 06E4 0300 0315 0062;0061 05AE 06E4 0300 0315 0062; # (a◌ۤ◌̕◌̀◌֮b; a◌֮◌ۤ◌̀◌̕b; a◌֮◌ۤ◌̀◌̕b; a◌֮◌ۤ◌̀◌̕b; a◌֮◌ۤ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH MADDA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 06E7 0062;00E0 05AE 06E7 0315 0062;0061 05AE 0300 06E7 0315 0062;00E0 05AE 06E7 0315 0062;0061 05AE 0300 06E7 0315 0062; # (a◌̕◌̀◌֮◌ۧb; à◌֮◌ۧ◌̕b; a◌֮◌̀◌ۧ◌̕b; à◌֮◌ۧ◌̕b; a◌֮◌̀◌ۧ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH YEH, LATIN SMALL LETTER B
0061 06E7 0315 0300 05AE 0062;0061 05AE 06E7 0300 0315 0062;0061 05AE 06E7 0300 0315 0062;0061 05AE 06E7 0300 0315 0062;0061 05AE 06E7 0300 0315 0062; # (a◌ۧ◌̕◌̀◌֮b; a◌֮◌ۧ◌̀◌̕b; a◌֮◌ۧ◌̀◌̕b; a◌֮◌ۧ◌̀◌̕b; a◌֮◌ۧ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH YEH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 06E8 0062;00E0 05AE 06E8 0315 0062;0061 05AE 0300 06E8 0315 0062;00E0 05AE 06E8 0315 0062;0061 05AE 0300 06E8 0315 0062; # (a◌̕◌̀◌֮◌ۨb; à◌֮◌ۨ◌̕b; a◌֮◌̀◌ۨ◌̕b; à◌֮◌ۨ◌̕b; a◌֮◌̀◌ۨ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH NOON, LATIN SMALL LETTER B
0061 06E8 0315 0300 05AE 0062;0061 05AE 06E8 0300 0315 0062;0061 05AE 06E8 0300 0315 0062;0061 05AE 06E8 0300 0315 0062;0061 05AE 06E8 0300 0315 0062; # (a◌ۨ◌̕◌̀◌֮b; a◌֮◌ۨ◌̀◌̕b; a◌֮◌ۨ◌̀◌̕b; a◌֮◌ۨ◌̀◌̕b; a◌֮◌ۨ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH NOON, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 06EA 0062;0061 302A 0316 06EA 059A 0062;0061 302A 0316 06EA 059A 0062;0061 302A 0316 06EA 059A 0062;0061 302A 0316 06EA 059A 0062; # (a◌֚◌̖◌〪◌۪b; a◌〪◌̖◌۪◌֚b; a◌〪◌̖◌۪◌֚b; a◌〪◌̖◌۪◌֚b; a◌〪◌̖◌۪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC EMPTY CENTRE LOW STOP, LATIN SMALL LETTER B
-0061 06EA 059A 0316 302A 0062;0061 302A 06EA 0316 059A 0062;0061 302A 06EA 0316 059A 0062;0061 302A 06EA 0316 059A 0062;0061 302A 06EA 0316 059A 0062; # (a◌۪◌֚◌̖◌〪b; a◌〪◌۪◌̖◌֚b; a◌〪◌۪◌̖◌֚b; a◌〪◌۪◌̖◌֚b; a◌〪◌۪◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC EMPTY CENTRE LOW STOP, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 06EA 0062;0061 1DFA 0316 06EA 059A 0062;0061 1DFA 0316 06EA 059A 0062;0061 1DFA 0316 06EA 059A 0062;0061 1DFA 0316 06EA 059A 0062; # (a◌֚◌̖◌᷺◌۪b; a◌᷺◌̖◌۪◌֚b; a◌᷺◌̖◌۪◌֚b; a◌᷺◌̖◌۪◌֚b; a◌᷺◌̖◌۪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC EMPTY CENTRE LOW STOP, LATIN SMALL LETTER B
+0061 06EA 059A 0316 1DFA 0062;0061 1DFA 06EA 0316 059A 0062;0061 1DFA 06EA 0316 059A 0062;0061 1DFA 06EA 0316 059A 0062;0061 1DFA 06EA 0316 059A 0062; # (a◌۪◌֚◌̖◌᷺b; a◌᷺◌۪◌̖◌֚b; a◌᷺◌۪◌̖◌֚b; a◌᷺◌۪◌̖◌֚b; a◌᷺◌۪◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC EMPTY CENTRE LOW STOP, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 06EB 0062;00E0 05AE 06EB 0315 0062;0061 05AE 0300 06EB 0315 0062;00E0 05AE 06EB 0315 0062;0061 05AE 0300 06EB 0315 0062; # (a◌̕◌̀◌֮◌۫b; à◌֮◌۫◌̕b; a◌֮◌̀◌۫◌̕b; à◌֮◌۫◌̕b; a◌֮◌̀◌۫◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC EMPTY CENTRE HIGH STOP, LATIN SMALL LETTER B
0061 06EB 0315 0300 05AE 0062;0061 05AE 06EB 0300 0315 0062;0061 05AE 06EB 0300 0315 0062;0061 05AE 06EB 0300 0315 0062;0061 05AE 06EB 0300 0315 0062; # (a◌۫◌̕◌̀◌֮b; a◌֮◌۫◌̀◌̕b; a◌֮◌۫◌̀◌̕b; a◌֮◌۫◌̀◌̕b; a◌֮◌۫◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC EMPTY CENTRE HIGH STOP, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 06EC 0062;00E0 05AE 06EC 0315 0062;0061 05AE 0300 06EC 0315 0062;00E0 05AE 06EC 0315 0062;0061 05AE 0300 06EC 0315 0062; # (a◌̕◌̀◌֮◌۬b; à◌֮◌۬◌̕b; a◌֮◌̀◌۬◌̕b; à◌֮◌۬◌̕b; a◌֮◌̀◌۬◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE, LATIN SMALL LETTER B
0061 06EC 0315 0300 05AE 0062;0061 05AE 06EC 0300 0315 0062;0061 05AE 06EC 0300 0315 0062;0061 05AE 06EC 0300 0315 0062;0061 05AE 06EC 0300 0315 0062; # (a◌۬◌̕◌̀◌֮b; a◌֮◌۬◌̀◌̕b; a◌֮◌۬◌̀◌̕b; a◌֮◌۬◌̀◌̕b; a◌֮◌۬◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 06ED 0062;0061 302A 0316 06ED 059A 0062;0061 302A 0316 06ED 059A 0062;0061 302A 0316 06ED 059A 0062;0061 302A 0316 06ED 059A 0062; # (a◌֚◌̖◌〪◌ۭb; a◌〪◌̖◌ۭ◌֚b; a◌〪◌̖◌ۭ◌֚b; a◌〪◌̖◌ۭ◌֚b; a◌〪◌̖◌ۭ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC SMALL LOW MEEM, LATIN SMALL LETTER B
-0061 06ED 059A 0316 302A 0062;0061 302A 06ED 0316 059A 0062;0061 302A 06ED 0316 059A 0062;0061 302A 06ED 0316 059A 0062;0061 302A 06ED 0316 059A 0062; # (a◌ۭ◌֚◌̖◌〪b; a◌〪◌ۭ◌̖◌֚b; a◌〪◌ۭ◌̖◌֚b; a◌〪◌ۭ◌̖◌֚b; a◌〪◌ۭ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW MEEM, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 06ED 0062;0061 1DFA 0316 06ED 059A 0062;0061 1DFA 0316 06ED 059A 0062;0061 1DFA 0316 06ED 059A 0062;0061 1DFA 0316 06ED 059A 0062; # (a◌֚◌̖◌᷺◌ۭb; a◌᷺◌̖◌ۭ◌֚b; a◌᷺◌̖◌ۭ◌֚b; a◌᷺◌̖◌ۭ◌֚b; a◌᷺◌̖◌ۭ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW MEEM, LATIN SMALL LETTER B
+0061 06ED 059A 0316 1DFA 0062;0061 1DFA 06ED 0316 059A 0062;0061 1DFA 06ED 0316 059A 0062;0061 1DFA 06ED 0316 059A 0062;0061 1DFA 06ED 0316 059A 0062; # (a◌ۭ◌֚◌̖◌᷺b; a◌᷺◌ۭ◌̖◌֚b; a◌᷺◌ۭ◌̖◌֚b; a◌᷺◌ۭ◌̖◌֚b; a◌᷺◌ۭ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW MEEM, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0C55 0711 0670 0711 0062;0061 0670 0711 0711 0C55 0062;0061 0670 0711 0711 0C55 0062;0061 0670 0711 0711 0C55 0062;0061 0670 0711 0711 0C55 0062; # (a◌ౕ◌ܑ◌ٰ◌ܑb; a◌ٰ◌ܑ◌ܑ◌ౕb; a◌ٰ◌ܑ◌ܑ◌ౕb; a◌ٰ◌ܑ◌ܑ◌ౕb; a◌ٰ◌ܑ◌ܑ◌ౕb; ) LATIN SMALL LETTER A, TELUGU LENGTH MARK, SYRIAC LETTER SUPERSCRIPT ALAPH, ARABIC LETTER SUPERSCRIPT ALEF, SYRIAC LETTER SUPERSCRIPT ALAPH, LATIN SMALL LETTER B
0061 0711 0C55 0711 0670 0062;0061 0670 0711 0711 0C55 0062;0061 0670 0711 0711 0C55 0062;0061 0670 0711 0711 0C55 0062;0061 0670 0711 0711 0C55 0062; # (a◌ܑ◌ౕ◌ܑ◌ٰb; a◌ٰ◌ܑ◌ܑ◌ౕb; a◌ٰ◌ܑ◌ܑ◌ౕb; a◌ٰ◌ܑ◌ܑ◌ౕb; a◌ٰ◌ܑ◌ܑ◌ౕb; ) LATIN SMALL LETTER A, SYRIAC LETTER SUPERSCRIPT ALAPH, TELUGU LENGTH MARK, SYRIAC LETTER SUPERSCRIPT ALAPH, ARABIC LETTER SUPERSCRIPT ALEF, LATIN SMALL LETTER B
0061 0315 0300 05AE 0730 0062;00E0 05AE 0730 0315 0062;0061 05AE 0300 0730 0315 0062;00E0 05AE 0730 0315 0062;0061 05AE 0300 0730 0315 0062; # (a◌̕◌̀◌֮◌ܰb; à◌֮◌ܰ◌̕b; a◌֮◌̀◌ܰ◌̕b; à◌֮◌ܰ◌̕b; a◌֮◌̀◌ܰ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC PTHAHA ABOVE, LATIN SMALL LETTER B
0061 0730 0315 0300 05AE 0062;0061 05AE 0730 0300 0315 0062;0061 05AE 0730 0300 0315 0062;0061 05AE 0730 0300 0315 0062;0061 05AE 0730 0300 0315 0062; # (a◌ܰ◌̕◌̀◌֮b; a◌֮◌ܰ◌̀◌̕b; a◌֮◌ܰ◌̀◌̕b; a◌֮◌ܰ◌̀◌̕b; a◌֮◌ܰ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC PTHAHA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0731 0062;0061 302A 0316 0731 059A 0062;0061 302A 0316 0731 059A 0062;0061 302A 0316 0731 059A 0062;0061 302A 0316 0731 059A 0062; # (a◌֚◌̖◌〪◌ܱb; a◌〪◌̖◌ܱ◌֚b; a◌〪◌̖◌ܱ◌֚b; a◌〪◌̖◌ܱ◌֚b; a◌〪◌̖◌ܱ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC PTHAHA BELOW, LATIN SMALL LETTER B
-0061 0731 059A 0316 302A 0062;0061 302A 0731 0316 059A 0062;0061 302A 0731 0316 059A 0062;0061 302A 0731 0316 059A 0062;0061 302A 0731 0316 059A 0062; # (a◌ܱ◌֚◌̖◌〪b; a◌〪◌ܱ◌̖◌֚b; a◌〪◌ܱ◌̖◌֚b; a◌〪◌ܱ◌̖◌֚b; a◌〪◌ܱ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC PTHAHA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0731 0062;0061 1DFA 0316 0731 059A 0062;0061 1DFA 0316 0731 059A 0062;0061 1DFA 0316 0731 059A 0062;0061 1DFA 0316 0731 059A 0062; # (a◌֚◌̖◌᷺◌ܱb; a◌᷺◌̖◌ܱ◌֚b; a◌᷺◌̖◌ܱ◌֚b; a◌᷺◌̖◌ܱ◌֚b; a◌᷺◌̖◌ܱ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC PTHAHA BELOW, LATIN SMALL LETTER B
+0061 0731 059A 0316 1DFA 0062;0061 1DFA 0731 0316 059A 0062;0061 1DFA 0731 0316 059A 0062;0061 1DFA 0731 0316 059A 0062;0061 1DFA 0731 0316 059A 0062; # (a◌ܱ◌֚◌̖◌᷺b; a◌᷺◌ܱ◌̖◌֚b; a◌᷺◌ܱ◌̖◌֚b; a◌᷺◌ܱ◌̖◌֚b; a◌᷺◌ܱ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC PTHAHA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0732 0062;00E0 05AE 0732 0315 0062;0061 05AE 0300 0732 0315 0062;00E0 05AE 0732 0315 0062;0061 05AE 0300 0732 0315 0062; # (a◌̕◌̀◌֮◌ܲb; à◌֮◌ܲ◌̕b; a◌֮◌̀◌ܲ◌̕b; à◌֮◌ܲ◌̕b; a◌֮◌̀◌ܲ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC PTHAHA DOTTED, LATIN SMALL LETTER B
0061 0732 0315 0300 05AE 0062;0061 05AE 0732 0300 0315 0062;0061 05AE 0732 0300 0315 0062;0061 05AE 0732 0300 0315 0062;0061 05AE 0732 0300 0315 0062; # (a◌ܲ◌̕◌̀◌֮b; a◌֮◌ܲ◌̀◌̕b; a◌֮◌ܲ◌̀◌̕b; a◌֮◌ܲ◌̀◌̕b; a◌֮◌ܲ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC PTHAHA DOTTED, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0733 0062;00E0 05AE 0733 0315 0062;0061 05AE 0300 0733 0315 0062;00E0 05AE 0733 0315 0062;0061 05AE 0300 0733 0315 0062; # (a◌̕◌̀◌֮◌ܳb; à◌֮◌ܳ◌̕b; a◌֮◌̀◌ܳ◌̕b; à◌֮◌ܳ◌̕b; a◌֮◌̀◌ܳ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC ZQAPHA ABOVE, LATIN SMALL LETTER B
0061 0733 0315 0300 05AE 0062;0061 05AE 0733 0300 0315 0062;0061 05AE 0733 0300 0315 0062;0061 05AE 0733 0300 0315 0062;0061 05AE 0733 0300 0315 0062; # (a◌ܳ◌̕◌̀◌֮b; a◌֮◌ܳ◌̀◌̕b; a◌֮◌ܳ◌̀◌̕b; a◌֮◌ܳ◌̀◌̕b; a◌֮◌ܳ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC ZQAPHA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0734 0062;0061 302A 0316 0734 059A 0062;0061 302A 0316 0734 059A 0062;0061 302A 0316 0734 059A 0062;0061 302A 0316 0734 059A 0062; # (a◌֚◌̖◌〪◌ܴb; a◌〪◌̖◌ܴ◌֚b; a◌〪◌̖◌ܴ◌֚b; a◌〪◌̖◌ܴ◌֚b; a◌〪◌̖◌ܴ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC ZQAPHA BELOW, LATIN SMALL LETTER B
-0061 0734 059A 0316 302A 0062;0061 302A 0734 0316 059A 0062;0061 302A 0734 0316 059A 0062;0061 302A 0734 0316 059A 0062;0061 302A 0734 0316 059A 0062; # (a◌ܴ◌֚◌̖◌〪b; a◌〪◌ܴ◌̖◌֚b; a◌〪◌ܴ◌̖◌֚b; a◌〪◌ܴ◌̖◌֚b; a◌〪◌ܴ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC ZQAPHA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0734 0062;0061 1DFA 0316 0734 059A 0062;0061 1DFA 0316 0734 059A 0062;0061 1DFA 0316 0734 059A 0062;0061 1DFA 0316 0734 059A 0062; # (a◌֚◌̖◌᷺◌ܴb; a◌᷺◌̖◌ܴ◌֚b; a◌᷺◌̖◌ܴ◌֚b; a◌᷺◌̖◌ܴ◌֚b; a◌᷺◌̖◌ܴ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC ZQAPHA BELOW, LATIN SMALL LETTER B
+0061 0734 059A 0316 1DFA 0062;0061 1DFA 0734 0316 059A 0062;0061 1DFA 0734 0316 059A 0062;0061 1DFA 0734 0316 059A 0062;0061 1DFA 0734 0316 059A 0062; # (a◌ܴ◌֚◌̖◌᷺b; a◌᷺◌ܴ◌̖◌֚b; a◌᷺◌ܴ◌̖◌֚b; a◌᷺◌ܴ◌̖◌֚b; a◌᷺◌ܴ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC ZQAPHA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0735 0062;00E0 05AE 0735 0315 0062;0061 05AE 0300 0735 0315 0062;00E0 05AE 0735 0315 0062;0061 05AE 0300 0735 0315 0062; # (a◌̕◌̀◌֮◌ܵb; à◌֮◌ܵ◌̕b; a◌֮◌̀◌ܵ◌̕b; à◌֮◌ܵ◌̕b; a◌֮◌̀◌ܵ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC ZQAPHA DOTTED, LATIN SMALL LETTER B
0061 0735 0315 0300 05AE 0062;0061 05AE 0735 0300 0315 0062;0061 05AE 0735 0300 0315 0062;0061 05AE 0735 0300 0315 0062;0061 05AE 0735 0300 0315 0062; # (a◌ܵ◌̕◌̀◌֮b; a◌֮◌ܵ◌̀◌̕b; a◌֮◌ܵ◌̀◌̕b; a◌֮◌ܵ◌̀◌̕b; a◌֮◌ܵ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC ZQAPHA DOTTED, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0736 0062;00E0 05AE 0736 0315 0062;0061 05AE 0300 0736 0315 0062;00E0 05AE 0736 0315 0062;0061 05AE 0300 0736 0315 0062; # (a◌̕◌̀◌֮◌ܶb; à◌֮◌ܶ◌̕b; a◌֮◌̀◌ܶ◌̕b; à◌֮◌ܶ◌̕b; a◌֮◌̀◌ܶ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC RBASA ABOVE, LATIN SMALL LETTER B
0061 0736 0315 0300 05AE 0062;0061 05AE 0736 0300 0315 0062;0061 05AE 0736 0300 0315 0062;0061 05AE 0736 0300 0315 0062;0061 05AE 0736 0300 0315 0062; # (a◌ܶ◌̕◌̀◌֮b; a◌֮◌ܶ◌̀◌̕b; a◌֮◌ܶ◌̀◌̕b; a◌֮◌ܶ◌̀◌̕b; a◌֮◌ܶ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC RBASA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0737 0062;0061 302A 0316 0737 059A 0062;0061 302A 0316 0737 059A 0062;0061 302A 0316 0737 059A 0062;0061 302A 0316 0737 059A 0062; # (a◌֚◌̖◌〪◌ܷb; a◌〪◌̖◌ܷ◌֚b; a◌〪◌̖◌ܷ◌֚b; a◌〪◌̖◌ܷ◌֚b; a◌〪◌̖◌ܷ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC RBASA BELOW, LATIN SMALL LETTER B
-0061 0737 059A 0316 302A 0062;0061 302A 0737 0316 059A 0062;0061 302A 0737 0316 059A 0062;0061 302A 0737 0316 059A 0062;0061 302A 0737 0316 059A 0062; # (a◌ܷ◌֚◌̖◌〪b; a◌〪◌ܷ◌̖◌֚b; a◌〪◌ܷ◌̖◌֚b; a◌〪◌ܷ◌̖◌֚b; a◌〪◌ܷ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC RBASA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0738 0062;0061 302A 0316 0738 059A 0062;0061 302A 0316 0738 059A 0062;0061 302A 0316 0738 059A 0062;0061 302A 0316 0738 059A 0062; # (a◌֚◌̖◌〪◌ܸb; a◌〪◌̖◌ܸ◌֚b; a◌〪◌̖◌ܸ◌֚b; a◌〪◌̖◌ܸ◌֚b; a◌〪◌̖◌ܸ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC DOTTED ZLAMA HORIZONTAL, LATIN SMALL LETTER B
-0061 0738 059A 0316 302A 0062;0061 302A 0738 0316 059A 0062;0061 302A 0738 0316 059A 0062;0061 302A 0738 0316 059A 0062;0061 302A 0738 0316 059A 0062; # (a◌ܸ◌֚◌̖◌〪b; a◌〪◌ܸ◌̖◌֚b; a◌〪◌ܸ◌̖◌֚b; a◌〪◌ܸ◌̖◌֚b; a◌〪◌ܸ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC DOTTED ZLAMA HORIZONTAL, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0739 0062;0061 302A 0316 0739 059A 0062;0061 302A 0316 0739 059A 0062;0061 302A 0316 0739 059A 0062;0061 302A 0316 0739 059A 0062; # (a◌֚◌̖◌〪◌ܹb; a◌〪◌̖◌ܹ◌֚b; a◌〪◌̖◌ܹ◌֚b; a◌〪◌̖◌ܹ◌֚b; a◌〪◌̖◌ܹ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC DOTTED ZLAMA ANGULAR, LATIN SMALL LETTER B
-0061 0739 059A 0316 302A 0062;0061 302A 0739 0316 059A 0062;0061 302A 0739 0316 059A 0062;0061 302A 0739 0316 059A 0062;0061 302A 0739 0316 059A 0062; # (a◌ܹ◌֚◌̖◌〪b; a◌〪◌ܹ◌̖◌֚b; a◌〪◌ܹ◌̖◌֚b; a◌〪◌ܹ◌̖◌֚b; a◌〪◌ܹ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC DOTTED ZLAMA ANGULAR, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0737 0062;0061 1DFA 0316 0737 059A 0062;0061 1DFA 0316 0737 059A 0062;0061 1DFA 0316 0737 059A 0062;0061 1DFA 0316 0737 059A 0062; # (a◌֚◌̖◌᷺◌ܷb; a◌᷺◌̖◌ܷ◌֚b; a◌᷺◌̖◌ܷ◌֚b; a◌᷺◌̖◌ܷ◌֚b; a◌᷺◌̖◌ܷ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC RBASA BELOW, LATIN SMALL LETTER B
+0061 0737 059A 0316 1DFA 0062;0061 1DFA 0737 0316 059A 0062;0061 1DFA 0737 0316 059A 0062;0061 1DFA 0737 0316 059A 0062;0061 1DFA 0737 0316 059A 0062; # (a◌ܷ◌֚◌̖◌᷺b; a◌᷺◌ܷ◌̖◌֚b; a◌᷺◌ܷ◌̖◌֚b; a◌᷺◌ܷ◌̖◌֚b; a◌᷺◌ܷ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC RBASA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0738 0062;0061 1DFA 0316 0738 059A 0062;0061 1DFA 0316 0738 059A 0062;0061 1DFA 0316 0738 059A 0062;0061 1DFA 0316 0738 059A 0062; # (a◌֚◌̖◌᷺◌ܸb; a◌᷺◌̖◌ܸ◌֚b; a◌᷺◌̖◌ܸ◌֚b; a◌᷺◌̖◌ܸ◌֚b; a◌᷺◌̖◌ܸ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC DOTTED ZLAMA HORIZONTAL, LATIN SMALL LETTER B
+0061 0738 059A 0316 1DFA 0062;0061 1DFA 0738 0316 059A 0062;0061 1DFA 0738 0316 059A 0062;0061 1DFA 0738 0316 059A 0062;0061 1DFA 0738 0316 059A 0062; # (a◌ܸ◌֚◌̖◌᷺b; a◌᷺◌ܸ◌̖◌֚b; a◌᷺◌ܸ◌̖◌֚b; a◌᷺◌ܸ◌̖◌֚b; a◌᷺◌ܸ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC DOTTED ZLAMA HORIZONTAL, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0739 0062;0061 1DFA 0316 0739 059A 0062;0061 1DFA 0316 0739 059A 0062;0061 1DFA 0316 0739 059A 0062;0061 1DFA 0316 0739 059A 0062; # (a◌֚◌̖◌᷺◌ܹb; a◌᷺◌̖◌ܹ◌֚b; a◌᷺◌̖◌ܹ◌֚b; a◌᷺◌̖◌ܹ◌֚b; a◌᷺◌̖◌ܹ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC DOTTED ZLAMA ANGULAR, LATIN SMALL LETTER B
+0061 0739 059A 0316 1DFA 0062;0061 1DFA 0739 0316 059A 0062;0061 1DFA 0739 0316 059A 0062;0061 1DFA 0739 0316 059A 0062;0061 1DFA 0739 0316 059A 0062; # (a◌ܹ◌֚◌̖◌᷺b; a◌᷺◌ܹ◌̖◌֚b; a◌᷺◌ܹ◌̖◌֚b; a◌᷺◌ܹ◌̖◌֚b; a◌᷺◌ܹ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC DOTTED ZLAMA ANGULAR, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 073A 0062;00E0 05AE 073A 0315 0062;0061 05AE 0300 073A 0315 0062;00E0 05AE 073A 0315 0062;0061 05AE 0300 073A 0315 0062; # (a◌̕◌̀◌֮◌ܺb; à◌֮◌ܺ◌̕b; a◌֮◌̀◌ܺ◌̕b; à◌֮◌ܺ◌̕b; a◌֮◌̀◌ܺ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC HBASA ABOVE, LATIN SMALL LETTER B
0061 073A 0315 0300 05AE 0062;0061 05AE 073A 0300 0315 0062;0061 05AE 073A 0300 0315 0062;0061 05AE 073A 0300 0315 0062;0061 05AE 073A 0300 0315 0062; # (a◌ܺ◌̕◌̀◌֮b; a◌֮◌ܺ◌̀◌̕b; a◌֮◌ܺ◌̀◌̕b; a◌֮◌ܺ◌̀◌̕b; a◌֮◌ܺ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC HBASA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 073B 0062;0061 302A 0316 073B 059A 0062;0061 302A 0316 073B 059A 0062;0061 302A 0316 073B 059A 0062;0061 302A 0316 073B 059A 0062; # (a◌֚◌̖◌〪◌ܻb; a◌〪◌̖◌ܻ◌֚b; a◌〪◌̖◌ܻ◌֚b; a◌〪◌̖◌ܻ◌֚b; a◌〪◌̖◌ܻ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC HBASA BELOW, LATIN SMALL LETTER B
-0061 073B 059A 0316 302A 0062;0061 302A 073B 0316 059A 0062;0061 302A 073B 0316 059A 0062;0061 302A 073B 0316 059A 0062;0061 302A 073B 0316 059A 0062; # (a◌ܻ◌֚◌̖◌〪b; a◌〪◌ܻ◌̖◌֚b; a◌〪◌ܻ◌̖◌֚b; a◌〪◌ܻ◌̖◌֚b; a◌〪◌ܻ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC HBASA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 073C 0062;0061 302A 0316 073C 059A 0062;0061 302A 0316 073C 059A 0062;0061 302A 0316 073C 059A 0062;0061 302A 0316 073C 059A 0062; # (a◌֚◌̖◌〪◌ܼb; a◌〪◌̖◌ܼ◌֚b; a◌〪◌̖◌ܼ◌֚b; a◌〪◌̖◌ܼ◌֚b; a◌〪◌̖◌ܼ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC HBASA-ESASA DOTTED, LATIN SMALL LETTER B
-0061 073C 059A 0316 302A 0062;0061 302A 073C 0316 059A 0062;0061 302A 073C 0316 059A 0062;0061 302A 073C 0316 059A 0062;0061 302A 073C 0316 059A 0062; # (a◌ܼ◌֚◌̖◌〪b; a◌〪◌ܼ◌̖◌֚b; a◌〪◌ܼ◌̖◌֚b; a◌〪◌ܼ◌̖◌֚b; a◌〪◌ܼ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC HBASA-ESASA DOTTED, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 073B 0062;0061 1DFA 0316 073B 059A 0062;0061 1DFA 0316 073B 059A 0062;0061 1DFA 0316 073B 059A 0062;0061 1DFA 0316 073B 059A 0062; # (a◌֚◌̖◌᷺◌ܻb; a◌᷺◌̖◌ܻ◌֚b; a◌᷺◌̖◌ܻ◌֚b; a◌᷺◌̖◌ܻ◌֚b; a◌᷺◌̖◌ܻ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC HBASA BELOW, LATIN SMALL LETTER B
+0061 073B 059A 0316 1DFA 0062;0061 1DFA 073B 0316 059A 0062;0061 1DFA 073B 0316 059A 0062;0061 1DFA 073B 0316 059A 0062;0061 1DFA 073B 0316 059A 0062; # (a◌ܻ◌֚◌̖◌᷺b; a◌᷺◌ܻ◌̖◌֚b; a◌᷺◌ܻ◌̖◌֚b; a◌᷺◌ܻ◌̖◌֚b; a◌᷺◌ܻ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC HBASA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 073C 0062;0061 1DFA 0316 073C 059A 0062;0061 1DFA 0316 073C 059A 0062;0061 1DFA 0316 073C 059A 0062;0061 1DFA 0316 073C 059A 0062; # (a◌֚◌̖◌᷺◌ܼb; a◌᷺◌̖◌ܼ◌֚b; a◌᷺◌̖◌ܼ◌֚b; a◌᷺◌̖◌ܼ◌֚b; a◌᷺◌̖◌ܼ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC HBASA-ESASA DOTTED, LATIN SMALL LETTER B
+0061 073C 059A 0316 1DFA 0062;0061 1DFA 073C 0316 059A 0062;0061 1DFA 073C 0316 059A 0062;0061 1DFA 073C 0316 059A 0062;0061 1DFA 073C 0316 059A 0062; # (a◌ܼ◌֚◌̖◌᷺b; a◌᷺◌ܼ◌̖◌֚b; a◌᷺◌ܼ◌̖◌֚b; a◌᷺◌ܼ◌̖◌֚b; a◌᷺◌ܼ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC HBASA-ESASA DOTTED, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 073D 0062;00E0 05AE 073D 0315 0062;0061 05AE 0300 073D 0315 0062;00E0 05AE 073D 0315 0062;0061 05AE 0300 073D 0315 0062; # (a◌̕◌̀◌֮◌ܽb; à◌֮◌ܽ◌̕b; a◌֮◌̀◌ܽ◌̕b; à◌֮◌ܽ◌̕b; a◌֮◌̀◌ܽ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC ESASA ABOVE, LATIN SMALL LETTER B
0061 073D 0315 0300 05AE 0062;0061 05AE 073D 0300 0315 0062;0061 05AE 073D 0300 0315 0062;0061 05AE 073D 0300 0315 0062;0061 05AE 073D 0300 0315 0062; # (a◌ܽ◌̕◌̀◌֮b; a◌֮◌ܽ◌̀◌̕b; a◌֮◌ܽ◌̀◌̕b; a◌֮◌ܽ◌̀◌̕b; a◌֮◌ܽ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC ESASA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 073E 0062;0061 302A 0316 073E 059A 0062;0061 302A 0316 073E 059A 0062;0061 302A 0316 073E 059A 0062;0061 302A 0316 073E 059A 0062; # (a◌֚◌̖◌〪◌ܾb; a◌〪◌̖◌ܾ◌֚b; a◌〪◌̖◌ܾ◌֚b; a◌〪◌̖◌ܾ◌֚b; a◌〪◌̖◌ܾ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC ESASA BELOW, LATIN SMALL LETTER B
-0061 073E 059A 0316 302A 0062;0061 302A 073E 0316 059A 0062;0061 302A 073E 0316 059A 0062;0061 302A 073E 0316 059A 0062;0061 302A 073E 0316 059A 0062; # (a◌ܾ◌֚◌̖◌〪b; a◌〪◌ܾ◌̖◌֚b; a◌〪◌ܾ◌̖◌֚b; a◌〪◌ܾ◌̖◌֚b; a◌〪◌ܾ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC ESASA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 073E 0062;0061 1DFA 0316 073E 059A 0062;0061 1DFA 0316 073E 059A 0062;0061 1DFA 0316 073E 059A 0062;0061 1DFA 0316 073E 059A 0062; # (a◌֚◌̖◌᷺◌ܾb; a◌᷺◌̖◌ܾ◌֚b; a◌᷺◌̖◌ܾ◌֚b; a◌᷺◌̖◌ܾ◌֚b; a◌᷺◌̖◌ܾ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC ESASA BELOW, LATIN SMALL LETTER B
+0061 073E 059A 0316 1DFA 0062;0061 1DFA 073E 0316 059A 0062;0061 1DFA 073E 0316 059A 0062;0061 1DFA 073E 0316 059A 0062;0061 1DFA 073E 0316 059A 0062; # (a◌ܾ◌֚◌̖◌᷺b; a◌᷺◌ܾ◌̖◌֚b; a◌᷺◌ܾ◌̖◌֚b; a◌᷺◌ܾ◌̖◌֚b; a◌᷺◌ܾ◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC ESASA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 073F 0062;00E0 05AE 073F 0315 0062;0061 05AE 0300 073F 0315 0062;00E0 05AE 073F 0315 0062;0061 05AE 0300 073F 0315 0062; # (a◌̕◌̀◌֮◌ܿb; à◌֮◌ܿ◌̕b; a◌֮◌̀◌ܿ◌̕b; à◌֮◌ܿ◌̕b; a◌֮◌̀◌ܿ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC RWAHA, LATIN SMALL LETTER B
0061 073F 0315 0300 05AE 0062;0061 05AE 073F 0300 0315 0062;0061 05AE 073F 0300 0315 0062;0061 05AE 073F 0300 0315 0062;0061 05AE 073F 0300 0315 0062; # (a◌ܿ◌̕◌̀◌֮b; a◌֮◌ܿ◌̀◌̕b; a◌֮◌ܿ◌̀◌̕b; a◌֮◌ܿ◌̀◌̕b; a◌֮◌ܿ◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC RWAHA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0740 0062;00E0 05AE 0740 0315 0062;0061 05AE 0300 0740 0315 0062;00E0 05AE 0740 0315 0062;0061 05AE 0300 0740 0315 0062; # (a◌̕◌̀◌֮◌݀b; à◌֮◌݀◌̕b; a◌֮◌̀◌݀◌̕b; à◌֮◌݀◌̕b; a◌֮◌̀◌݀◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC FEMININE DOT, LATIN SMALL LETTER B
0061 0740 0315 0300 05AE 0062;0061 05AE 0740 0300 0315 0062;0061 05AE 0740 0300 0315 0062;0061 05AE 0740 0300 0315 0062;0061 05AE 0740 0300 0315 0062; # (a◌݀◌̕◌̀◌֮b; a◌֮◌݀◌̀◌̕b; a◌֮◌݀◌̀◌̕b; a◌֮◌݀◌̀◌̕b; a◌֮◌݀◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC FEMININE DOT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0741 0062;00E0 05AE 0741 0315 0062;0061 05AE 0300 0741 0315 0062;00E0 05AE 0741 0315 0062;0061 05AE 0300 0741 0315 0062; # (a◌̕◌̀◌֮◌Ýb; à◌֮◌Ý◌̕b; a◌֮◌̀◌Ý◌̕b; à◌֮◌Ý◌̕b; a◌֮◌̀◌Ý◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC QUSHSHAYA, LATIN SMALL LETTER B
0061 0741 0315 0300 05AE 0062;0061 05AE 0741 0300 0315 0062;0061 05AE 0741 0300 0315 0062;0061 05AE 0741 0300 0315 0062;0061 05AE 0741 0300 0315 0062; # (aâ—ŒÝ◌̕◌̀◌֮b; a◌֮◌Ý◌̀◌̕b; a◌֮◌Ý◌̀◌̕b; a◌֮◌Ý◌̀◌̕b; a◌֮◌Ý◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC QUSHSHAYA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0742 0062;0061 302A 0316 0742 059A 0062;0061 302A 0316 0742 059A 0062;0061 302A 0316 0742 059A 0062;0061 302A 0316 0742 059A 0062; # (a◌֚◌̖◌〪◌݂b; a◌〪◌̖◌݂◌֚b; a◌〪◌̖◌݂◌֚b; a◌〪◌̖◌݂◌֚b; a◌〪◌̖◌݂◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC RUKKAKHA, LATIN SMALL LETTER B
-0061 0742 059A 0316 302A 0062;0061 302A 0742 0316 059A 0062;0061 302A 0742 0316 059A 0062;0061 302A 0742 0316 059A 0062;0061 302A 0742 0316 059A 0062; # (a◌݂◌֚◌̖◌〪b; a◌〪◌݂◌̖◌֚b; a◌〪◌݂◌̖◌֚b; a◌〪◌݂◌̖◌֚b; a◌〪◌݂◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC RUKKAKHA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0742 0062;0061 1DFA 0316 0742 059A 0062;0061 1DFA 0316 0742 059A 0062;0061 1DFA 0316 0742 059A 0062;0061 1DFA 0316 0742 059A 0062; # (a◌֚◌̖◌᷺◌݂b; a◌᷺◌̖◌݂◌֚b; a◌᷺◌̖◌݂◌֚b; a◌᷺◌̖◌݂◌֚b; a◌᷺◌̖◌݂◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC RUKKAKHA, LATIN SMALL LETTER B
+0061 0742 059A 0316 1DFA 0062;0061 1DFA 0742 0316 059A 0062;0061 1DFA 0742 0316 059A 0062;0061 1DFA 0742 0316 059A 0062;0061 1DFA 0742 0316 059A 0062; # (a◌݂◌֚◌̖◌᷺b; a◌᷺◌݂◌̖◌֚b; a◌᷺◌݂◌̖◌֚b; a◌᷺◌݂◌̖◌֚b; a◌᷺◌݂◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC RUKKAKHA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0743 0062;00E0 05AE 0743 0315 0062;0061 05AE 0300 0743 0315 0062;00E0 05AE 0743 0315 0062;0061 05AE 0300 0743 0315 0062; # (a◌̕◌̀◌֮◌݃b; à◌֮◌݃◌̕b; a◌֮◌̀◌݃◌̕b; à◌֮◌݃◌̕b; a◌֮◌̀◌݃◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC TWO VERTICAL DOTS ABOVE, LATIN SMALL LETTER B
0061 0743 0315 0300 05AE 0062;0061 05AE 0743 0300 0315 0062;0061 05AE 0743 0300 0315 0062;0061 05AE 0743 0300 0315 0062;0061 05AE 0743 0300 0315 0062; # (a◌݃◌̕◌̀◌֮b; a◌֮◌݃◌̀◌̕b; a◌֮◌݃◌̀◌̕b; a◌֮◌݃◌̀◌̕b; a◌֮◌݃◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC TWO VERTICAL DOTS ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0744 0062;0061 302A 0316 0744 059A 0062;0061 302A 0316 0744 059A 0062;0061 302A 0316 0744 059A 0062;0061 302A 0316 0744 059A 0062; # (a◌֚◌̖◌〪◌݄b; a◌〪◌̖◌݄◌֚b; a◌〪◌̖◌݄◌֚b; a◌〪◌̖◌݄◌֚b; a◌〪◌̖◌݄◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC TWO VERTICAL DOTS BELOW, LATIN SMALL LETTER B
-0061 0744 059A 0316 302A 0062;0061 302A 0744 0316 059A 0062;0061 302A 0744 0316 059A 0062;0061 302A 0744 0316 059A 0062;0061 302A 0744 0316 059A 0062; # (a◌݄◌֚◌̖◌〪b; a◌〪◌݄◌̖◌֚b; a◌〪◌݄◌̖◌֚b; a◌〪◌݄◌̖◌֚b; a◌〪◌݄◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC TWO VERTICAL DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0744 0062;0061 1DFA 0316 0744 059A 0062;0061 1DFA 0316 0744 059A 0062;0061 1DFA 0316 0744 059A 0062;0061 1DFA 0316 0744 059A 0062; # (a◌֚◌̖◌᷺◌݄b; a◌᷺◌̖◌݄◌֚b; a◌᷺◌̖◌݄◌֚b; a◌᷺◌̖◌݄◌֚b; a◌᷺◌̖◌݄◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC TWO VERTICAL DOTS BELOW, LATIN SMALL LETTER B
+0061 0744 059A 0316 1DFA 0062;0061 1DFA 0744 0316 059A 0062;0061 1DFA 0744 0316 059A 0062;0061 1DFA 0744 0316 059A 0062;0061 1DFA 0744 0316 059A 0062; # (a◌݄◌֚◌̖◌᷺b; a◌᷺◌݄◌̖◌֚b; a◌᷺◌݄◌̖◌֚b; a◌᷺◌݄◌̖◌֚b; a◌᷺◌݄◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC TWO VERTICAL DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0745 0062;00E0 05AE 0745 0315 0062;0061 05AE 0300 0745 0315 0062;00E0 05AE 0745 0315 0062;0061 05AE 0300 0745 0315 0062; # (a◌̕◌̀◌֮◌݅b; à◌֮◌݅◌̕b; a◌֮◌̀◌݅◌̕b; à◌֮◌݅◌̕b; a◌֮◌̀◌݅◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC THREE DOTS ABOVE, LATIN SMALL LETTER B
0061 0745 0315 0300 05AE 0062;0061 05AE 0745 0300 0315 0062;0061 05AE 0745 0300 0315 0062;0061 05AE 0745 0300 0315 0062;0061 05AE 0745 0300 0315 0062; # (a◌݅◌̕◌̀◌֮b; a◌֮◌݅◌̀◌̕b; a◌֮◌݅◌̀◌̕b; a◌֮◌݅◌̀◌̕b; a◌֮◌݅◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC THREE DOTS ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0746 0062;0061 302A 0316 0746 059A 0062;0061 302A 0316 0746 059A 0062;0061 302A 0316 0746 059A 0062;0061 302A 0316 0746 059A 0062; # (a◌֚◌̖◌〪◌݆b; a◌〪◌̖◌݆◌֚b; a◌〪◌̖◌݆◌֚b; a◌〪◌̖◌݆◌֚b; a◌〪◌̖◌݆◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC THREE DOTS BELOW, LATIN SMALL LETTER B
-0061 0746 059A 0316 302A 0062;0061 302A 0746 0316 059A 0062;0061 302A 0746 0316 059A 0062;0061 302A 0746 0316 059A 0062;0061 302A 0746 0316 059A 0062; # (a◌݆◌֚◌̖◌〪b; a◌〪◌݆◌̖◌֚b; a◌〪◌݆◌̖◌֚b; a◌〪◌݆◌̖◌֚b; a◌〪◌݆◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC THREE DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0746 0062;0061 1DFA 0316 0746 059A 0062;0061 1DFA 0316 0746 059A 0062;0061 1DFA 0316 0746 059A 0062;0061 1DFA 0316 0746 059A 0062; # (a◌֚◌̖◌᷺◌݆b; a◌᷺◌̖◌݆◌֚b; a◌᷺◌̖◌݆◌֚b; a◌᷺◌̖◌݆◌֚b; a◌᷺◌̖◌݆◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC THREE DOTS BELOW, LATIN SMALL LETTER B
+0061 0746 059A 0316 1DFA 0062;0061 1DFA 0746 0316 059A 0062;0061 1DFA 0746 0316 059A 0062;0061 1DFA 0746 0316 059A 0062;0061 1DFA 0746 0316 059A 0062; # (a◌݆◌֚◌̖◌᷺b; a◌᷺◌݆◌̖◌֚b; a◌᷺◌݆◌̖◌֚b; a◌᷺◌݆◌̖◌֚b; a◌᷺◌݆◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC THREE DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0747 0062;00E0 05AE 0747 0315 0062;0061 05AE 0300 0747 0315 0062;00E0 05AE 0747 0315 0062;0061 05AE 0300 0747 0315 0062; # (a◌̕◌̀◌֮◌݇b; à◌֮◌݇◌̕b; a◌֮◌̀◌݇◌̕b; à◌֮◌݇◌̕b; a◌֮◌̀◌݇◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC OBLIQUE LINE ABOVE, LATIN SMALL LETTER B
0061 0747 0315 0300 05AE 0062;0061 05AE 0747 0300 0315 0062;0061 05AE 0747 0300 0315 0062;0061 05AE 0747 0300 0315 0062;0061 05AE 0747 0300 0315 0062; # (a◌݇◌̕◌̀◌֮b; a◌֮◌݇◌̀◌̕b; a◌֮◌݇◌̀◌̕b; a◌֮◌݇◌̀◌̕b; a◌֮◌݇◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC OBLIQUE LINE ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0748 0062;0061 302A 0316 0748 059A 0062;0061 302A 0316 0748 059A 0062;0061 302A 0316 0748 059A 0062;0061 302A 0316 0748 059A 0062; # (a◌֚◌̖◌〪◌݈b; a◌〪◌̖◌݈◌֚b; a◌〪◌̖◌݈◌֚b; a◌〪◌̖◌݈◌֚b; a◌〪◌̖◌݈◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SYRIAC OBLIQUE LINE BELOW, LATIN SMALL LETTER B
-0061 0748 059A 0316 302A 0062;0061 302A 0748 0316 059A 0062;0061 302A 0748 0316 059A 0062;0061 302A 0748 0316 059A 0062;0061 302A 0748 0316 059A 0062; # (a◌݈◌֚◌̖◌〪b; a◌〪◌݈◌̖◌֚b; a◌〪◌݈◌̖◌֚b; a◌〪◌݈◌̖◌֚b; a◌〪◌݈◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC OBLIQUE LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0748 0062;0061 1DFA 0316 0748 059A 0062;0061 1DFA 0316 0748 059A 0062;0061 1DFA 0316 0748 059A 0062;0061 1DFA 0316 0748 059A 0062; # (a◌֚◌̖◌᷺◌݈b; a◌᷺◌̖◌݈◌֚b; a◌᷺◌̖◌݈◌֚b; a◌᷺◌̖◌݈◌֚b; a◌᷺◌̖◌݈◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SYRIAC OBLIQUE LINE BELOW, LATIN SMALL LETTER B
+0061 0748 059A 0316 1DFA 0062;0061 1DFA 0748 0316 059A 0062;0061 1DFA 0748 0316 059A 0062;0061 1DFA 0748 0316 059A 0062;0061 1DFA 0748 0316 059A 0062; # (a◌݈◌֚◌̖◌᷺b; a◌᷺◌݈◌̖◌֚b; a◌᷺◌݈◌̖◌֚b; a◌᷺◌݈◌̖◌֚b; a◌᷺◌݈◌̖◌֚b; ) LATIN SMALL LETTER A, SYRIAC OBLIQUE LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0749 0062;00E0 05AE 0749 0315 0062;0061 05AE 0300 0749 0315 0062;00E0 05AE 0749 0315 0062;0061 05AE 0300 0749 0315 0062; # (a◌̕◌̀◌֮◌݉b; à◌֮◌݉◌̕b; a◌֮◌̀◌݉◌̕b; à◌֮◌݉◌̕b; a◌֮◌̀◌݉◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC MUSIC, LATIN SMALL LETTER B
0061 0749 0315 0300 05AE 0062;0061 05AE 0749 0300 0315 0062;0061 05AE 0749 0300 0315 0062;0061 05AE 0749 0300 0315 0062;0061 05AE 0749 0300 0315 0062; # (a◌݉◌̕◌̀◌֮b; a◌֮◌݉◌̀◌̕b; a◌֮◌݉◌̀◌̕b; a◌֮◌݉◌̀◌̕b; a◌֮◌݉◌̀◌̕b; ) LATIN SMALL LETTER A, SYRIAC MUSIC, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 074A 0062;00E0 05AE 074A 0315 0062;0061 05AE 0300 074A 0315 0062;00E0 05AE 074A 0315 0062;0061 05AE 0300 074A 0315 0062; # (a◌̕◌̀◌֮◌݊b; à◌֮◌݊◌̕b; a◌֮◌̀◌݊◌̕b; à◌֮◌݊◌̕b; a◌֮◌̀◌݊◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SYRIAC BARREKH, LATIN SMALL LETTER B
@@ -17489,12 +17548,12 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 07F0 0315 0300 05AE 0062;0061 05AE 07F0 0300 0315 0062;0061 05AE 07F0 0300 0315 0062;0061 05AE 07F0 0300 0315 0062;0061 05AE 07F0 0300 0315 0062; # (a◌߰◌̕◌̀◌֮b; a◌֮◌߰◌̀◌̕b; a◌֮◌߰◌̀◌̕b; a◌֮◌߰◌̀◌̕b; a◌֮◌߰◌̀◌̕b; ) LATIN SMALL LETTER A, NKO COMBINING LONG LOW TONE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 07F1 0062;00E0 05AE 07F1 0315 0062;0061 05AE 0300 07F1 0315 0062;00E0 05AE 07F1 0315 0062;0061 05AE 0300 07F1 0315 0062; # (a◌̕◌̀◌֮◌߱b; à◌֮◌߱◌̕b; a◌֮◌̀◌߱◌̕b; à◌֮◌߱◌̕b; a◌֮◌̀◌߱◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, NKO COMBINING LONG RISING TONE, LATIN SMALL LETTER B
0061 07F1 0315 0300 05AE 0062;0061 05AE 07F1 0300 0315 0062;0061 05AE 07F1 0300 0315 0062;0061 05AE 07F1 0300 0315 0062;0061 05AE 07F1 0300 0315 0062; # (a◌߱◌̕◌̀◌֮b; a◌֮◌߱◌̀◌̕b; a◌֮◌߱◌̀◌̕b; a◌֮◌߱◌̀◌̕b; a◌֮◌߱◌̀◌̕b; ) LATIN SMALL LETTER A, NKO COMBINING LONG RISING TONE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 07F2 0062;0061 302A 0316 07F2 059A 0062;0061 302A 0316 07F2 059A 0062;0061 302A 0316 07F2 059A 0062;0061 302A 0316 07F2 059A 0062; # (a◌֚◌̖◌〪◌߲b; a◌〪◌̖◌߲◌֚b; a◌〪◌̖◌߲◌֚b; a◌〪◌̖◌߲◌֚b; a◌〪◌̖◌߲◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, NKO COMBINING NASALIZATION MARK, LATIN SMALL LETTER B
-0061 07F2 059A 0316 302A 0062;0061 302A 07F2 0316 059A 0062;0061 302A 07F2 0316 059A 0062;0061 302A 07F2 0316 059A 0062;0061 302A 07F2 0316 059A 0062; # (a◌߲◌֚◌̖◌〪b; a◌〪◌߲◌̖◌֚b; a◌〪◌߲◌̖◌֚b; a◌〪◌߲◌̖◌֚b; a◌〪◌߲◌̖◌֚b; ) LATIN SMALL LETTER A, NKO COMBINING NASALIZATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 07F2 0062;0061 1DFA 0316 07F2 059A 0062;0061 1DFA 0316 07F2 059A 0062;0061 1DFA 0316 07F2 059A 0062;0061 1DFA 0316 07F2 059A 0062; # (a◌֚◌̖◌᷺◌߲b; a◌᷺◌̖◌߲◌֚b; a◌᷺◌̖◌߲◌֚b; a◌᷺◌̖◌߲◌֚b; a◌᷺◌̖◌߲◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, NKO COMBINING NASALIZATION MARK, LATIN SMALL LETTER B
+0061 07F2 059A 0316 1DFA 0062;0061 1DFA 07F2 0316 059A 0062;0061 1DFA 07F2 0316 059A 0062;0061 1DFA 07F2 0316 059A 0062;0061 1DFA 07F2 0316 059A 0062; # (a◌߲◌֚◌̖◌᷺b; a◌᷺◌߲◌̖◌֚b; a◌᷺◌߲◌̖◌֚b; a◌᷺◌߲◌̖◌֚b; a◌᷺◌߲◌̖◌֚b; ) LATIN SMALL LETTER A, NKO COMBINING NASALIZATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 07F3 0062;00E0 05AE 07F3 0315 0062;0061 05AE 0300 07F3 0315 0062;00E0 05AE 07F3 0315 0062;0061 05AE 0300 07F3 0315 0062; # (a◌̕◌̀◌֮◌߳b; à◌֮◌߳◌̕b; a◌֮◌̀◌߳◌̕b; à◌֮◌߳◌̕b; a◌֮◌̀◌߳◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, NKO COMBINING DOUBLE DOT ABOVE, LATIN SMALL LETTER B
0061 07F3 0315 0300 05AE 0062;0061 05AE 07F3 0300 0315 0062;0061 05AE 07F3 0300 0315 0062;0061 05AE 07F3 0300 0315 0062;0061 05AE 07F3 0300 0315 0062; # (a◌߳◌̕◌̀◌֮b; a◌֮◌߳◌̀◌̕b; a◌֮◌߳◌̀◌̕b; a◌֮◌߳◌̀◌̕b; a◌֮◌߳◌̀◌̕b; ) LATIN SMALL LETTER A, NKO COMBINING DOUBLE DOT ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 07FD 0062;0061 302A 0316 07FD 059A 0062;0061 302A 0316 07FD 059A 0062;0061 302A 0316 07FD 059A 0062;0061 302A 0316 07FD 059A 0062; # (a◌֚◌̖◌〪◌߽b; a◌〪◌̖◌߽◌֚b; a◌〪◌̖◌߽◌֚b; a◌〪◌̖◌߽◌֚b; a◌〪◌̖◌߽◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, NKO DANTAYALAN, LATIN SMALL LETTER B
-0061 07FD 059A 0316 302A 0062;0061 302A 07FD 0316 059A 0062;0061 302A 07FD 0316 059A 0062;0061 302A 07FD 0316 059A 0062;0061 302A 07FD 0316 059A 0062; # (a◌߽◌֚◌̖◌〪b; a◌〪◌߽◌̖◌֚b; a◌〪◌߽◌̖◌֚b; a◌〪◌߽◌̖◌֚b; a◌〪◌߽◌̖◌֚b; ) LATIN SMALL LETTER A, NKO DANTAYALAN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 07FD 0062;0061 1DFA 0316 07FD 059A 0062;0061 1DFA 0316 07FD 059A 0062;0061 1DFA 0316 07FD 059A 0062;0061 1DFA 0316 07FD 059A 0062; # (a◌֚◌̖◌᷺◌߽b; a◌᷺◌̖◌߽◌֚b; a◌᷺◌̖◌߽◌֚b; a◌᷺◌̖◌߽◌֚b; a◌᷺◌̖◌߽◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, NKO DANTAYALAN, LATIN SMALL LETTER B
+0061 07FD 059A 0316 1DFA 0062;0061 1DFA 07FD 0316 059A 0062;0061 1DFA 07FD 0316 059A 0062;0061 1DFA 07FD 0316 059A 0062;0061 1DFA 07FD 0316 059A 0062; # (a◌߽◌֚◌̖◌᷺b; a◌᷺◌߽◌̖◌֚b; a◌᷺◌߽◌̖◌֚b; a◌᷺◌߽◌̖◌֚b; a◌᷺◌߽◌̖◌֚b; ) LATIN SMALL LETTER A, NKO DANTAYALAN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0816 0062;00E0 05AE 0816 0315 0062;0061 05AE 0300 0816 0315 0062;00E0 05AE 0816 0315 0062;0061 05AE 0300 0816 0315 0062; # (a◌̕◌̀◌֮◌ࠖb; à◌֮◌ࠖ◌̕b; a◌֮◌̀◌ࠖ◌̕b; à◌֮◌ࠖ◌̕b; a◌֮◌̀◌ࠖ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SAMARITAN MARK IN, LATIN SMALL LETTER B
0061 0816 0315 0300 05AE 0062;0061 05AE 0816 0300 0315 0062;0061 05AE 0816 0300 0315 0062;0061 05AE 0816 0300 0315 0062;0061 05AE 0816 0300 0315 0062; # (a◌ࠖ◌̕◌̀◌֮b; a◌֮◌ࠖ◌̀◌̕b; a◌֮◌ࠖ◌̀◌̕b; a◌֮◌ࠖ◌̀◌̕b; a◌֮◌ࠖ◌̀◌̕b; ) LATIN SMALL LETTER A, SAMARITAN MARK IN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0817 0062;00E0 05AE 0817 0315 0062;0061 05AE 0300 0817 0315 0062;00E0 05AE 0817 0315 0062;0061 05AE 0300 0817 0315 0062; # (a◌̕◌̀◌֮◌ࠗb; à◌֮◌ࠗ◌̕b; a◌֮◌̀◌ࠗ◌̕b; à◌֮◌ࠗ◌̕b; a◌֮◌̀◌ࠗ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SAMARITAN MARK IN-ALAF, LATIN SMALL LETTER B
@@ -17537,14 +17596,48 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 082C 0315 0300 05AE 0062;0061 05AE 082C 0300 0315 0062;0061 05AE 082C 0300 0315 0062;0061 05AE 082C 0300 0315 0062;0061 05AE 082C 0300 0315 0062; # (a◌ࠬ◌̕◌̀◌֮b; a◌֮◌ࠬ◌̀◌̕b; a◌֮◌ࠬ◌̀◌̕b; a◌֮◌ࠬ◌̀◌̕b; a◌֮◌ࠬ◌̀◌̕b; ) LATIN SMALL LETTER A, SAMARITAN VOWEL SIGN SUKUN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 082D 0062;00E0 05AE 082D 0315 0062;0061 05AE 0300 082D 0315 0062;00E0 05AE 082D 0315 0062;0061 05AE 0300 082D 0315 0062; # (a◌̕◌̀◌֮◌࠭b; à◌֮◌࠭◌̕b; a◌֮◌̀◌࠭◌̕b; à◌֮◌࠭◌̕b; a◌֮◌̀◌࠭◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SAMARITAN MARK NEQUDAA, LATIN SMALL LETTER B
0061 082D 0315 0300 05AE 0062;0061 05AE 082D 0300 0315 0062;0061 05AE 082D 0300 0315 0062;0061 05AE 082D 0300 0315 0062;0061 05AE 082D 0300 0315 0062; # (a◌࠭◌̕◌̀◌֮b; a◌֮◌࠭◌̀◌̕b; a◌֮◌࠭◌̀◌̕b; a◌֮◌࠭◌̀◌̕b; a◌֮◌࠭◌̀◌̕b; ) LATIN SMALL LETTER A, SAMARITAN MARK NEQUDAA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0859 0062;0061 302A 0316 0859 059A 0062;0061 302A 0316 0859 059A 0062;0061 302A 0316 0859 059A 0062;0061 302A 0316 0859 059A 0062; # (a◌֚◌̖◌〪◌࡙b; a◌〪◌̖◌࡙◌֚b; a◌〪◌̖◌࡙◌֚b; a◌〪◌̖◌࡙◌֚b; a◌〪◌̖◌࡙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MANDAIC AFFRICATION MARK, LATIN SMALL LETTER B
-0061 0859 059A 0316 302A 0062;0061 302A 0859 0316 059A 0062;0061 302A 0859 0316 059A 0062;0061 302A 0859 0316 059A 0062;0061 302A 0859 0316 059A 0062; # (a◌࡙◌֚◌̖◌〪b; a◌〪◌࡙◌̖◌֚b; a◌〪◌࡙◌̖◌֚b; a◌〪◌࡙◌̖◌֚b; a◌〪◌࡙◌̖◌֚b; ) LATIN SMALL LETTER A, MANDAIC AFFRICATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 085A 0062;0061 302A 0316 085A 059A 0062;0061 302A 0316 085A 059A 0062;0061 302A 0316 085A 059A 0062;0061 302A 0316 085A 059A 0062; # (a◌֚◌̖◌〪◌࡚b; a◌〪◌̖◌࡚◌֚b; a◌〪◌̖◌࡚◌֚b; a◌〪◌̖◌࡚◌֚b; a◌〪◌̖◌࡚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MANDAIC VOCALIZATION MARK, LATIN SMALL LETTER B
-0061 085A 059A 0316 302A 0062;0061 302A 085A 0316 059A 0062;0061 302A 085A 0316 059A 0062;0061 302A 085A 0316 059A 0062;0061 302A 085A 0316 059A 0062; # (a◌࡚◌֚◌̖◌〪b; a◌〪◌࡚◌̖◌֚b; a◌〪◌࡚◌̖◌֚b; a◌〪◌࡚◌̖◌֚b; a◌〪◌࡚◌̖◌֚b; ) LATIN SMALL LETTER A, MANDAIC VOCALIZATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 085B 0062;0061 302A 0316 085B 059A 0062;0061 302A 0316 085B 059A 0062;0061 302A 0316 085B 059A 0062;0061 302A 0316 085B 059A 0062; # (a◌֚◌̖◌〪◌࡛b; a◌〪◌̖◌࡛◌֚b; a◌〪◌̖◌࡛◌֚b; a◌〪◌̖◌࡛◌֚b; a◌〪◌̖◌࡛◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MANDAIC GEMINATION MARK, LATIN SMALL LETTER B
-0061 085B 059A 0316 302A 0062;0061 302A 085B 0316 059A 0062;0061 302A 085B 0316 059A 0062;0061 302A 085B 0316 059A 0062;0061 302A 085B 0316 059A 0062; # (a◌࡛◌֚◌̖◌〪b; a◌〪◌࡛◌̖◌֚b; a◌〪◌࡛◌̖◌֚b; a◌〪◌࡛◌̖◌֚b; a◌〪◌࡛◌̖◌֚b; ) LATIN SMALL LETTER A, MANDAIC GEMINATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 08D3 0062;0061 302A 0316 08D3 059A 0062;0061 302A 0316 08D3 059A 0062;0061 302A 0316 08D3 059A 0062;0061 302A 0316 08D3 059A 0062; # (a◌֚◌̖◌〪◌࣓b; a◌〪◌̖◌࣓◌֚b; a◌〪◌̖◌࣓◌֚b; a◌〪◌̖◌࣓◌֚b; a◌〪◌̖◌࣓◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC SMALL LOW WAW, LATIN SMALL LETTER B
-0061 08D3 059A 0316 302A 0062;0061 302A 08D3 0316 059A 0062;0061 302A 08D3 0316 059A 0062;0061 302A 08D3 0316 059A 0062;0061 302A 08D3 0316 059A 0062; # (a◌࣓◌֚◌̖◌〪b; a◌〪◌࣓◌̖◌֚b; a◌〪◌࣓◌̖◌֚b; a◌〪◌࣓◌̖◌֚b; a◌〪◌࣓◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WAW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0859 0062;0061 1DFA 0316 0859 059A 0062;0061 1DFA 0316 0859 059A 0062;0061 1DFA 0316 0859 059A 0062;0061 1DFA 0316 0859 059A 0062; # (a◌֚◌̖◌᷺◌࡙b; a◌᷺◌̖◌࡙◌֚b; a◌᷺◌̖◌࡙◌֚b; a◌᷺◌̖◌࡙◌֚b; a◌᷺◌̖◌࡙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MANDAIC AFFRICATION MARK, LATIN SMALL LETTER B
+0061 0859 059A 0316 1DFA 0062;0061 1DFA 0859 0316 059A 0062;0061 1DFA 0859 0316 059A 0062;0061 1DFA 0859 0316 059A 0062;0061 1DFA 0859 0316 059A 0062; # (a◌࡙◌֚◌̖◌᷺b; a◌᷺◌࡙◌̖◌֚b; a◌᷺◌࡙◌̖◌֚b; a◌᷺◌࡙◌̖◌֚b; a◌᷺◌࡙◌̖◌֚b; ) LATIN SMALL LETTER A, MANDAIC AFFRICATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 085A 0062;0061 1DFA 0316 085A 059A 0062;0061 1DFA 0316 085A 059A 0062;0061 1DFA 0316 085A 059A 0062;0061 1DFA 0316 085A 059A 0062; # (a◌֚◌̖◌᷺◌࡚b; a◌᷺◌̖◌࡚◌֚b; a◌᷺◌̖◌࡚◌֚b; a◌᷺◌̖◌࡚◌֚b; a◌᷺◌̖◌࡚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MANDAIC VOCALIZATION MARK, LATIN SMALL LETTER B
+0061 085A 059A 0316 1DFA 0062;0061 1DFA 085A 0316 059A 0062;0061 1DFA 085A 0316 059A 0062;0061 1DFA 085A 0316 059A 0062;0061 1DFA 085A 0316 059A 0062; # (a◌࡚◌֚◌̖◌᷺b; a◌᷺◌࡚◌̖◌֚b; a◌᷺◌࡚◌̖◌֚b; a◌᷺◌࡚◌̖◌֚b; a◌᷺◌࡚◌̖◌֚b; ) LATIN SMALL LETTER A, MANDAIC VOCALIZATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 085B 0062;0061 1DFA 0316 085B 059A 0062;0061 1DFA 0316 085B 059A 0062;0061 1DFA 0316 085B 059A 0062;0061 1DFA 0316 085B 059A 0062; # (a◌֚◌̖◌᷺◌࡛b; a◌᷺◌̖◌࡛◌֚b; a◌᷺◌̖◌࡛◌֚b; a◌᷺◌̖◌࡛◌֚b; a◌᷺◌̖◌࡛◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MANDAIC GEMINATION MARK, LATIN SMALL LETTER B
+0061 085B 059A 0316 1DFA 0062;0061 1DFA 085B 0316 059A 0062;0061 1DFA 085B 0316 059A 0062;0061 1DFA 085B 0316 059A 0062;0061 1DFA 085B 0316 059A 0062; # (a◌࡛◌֚◌̖◌᷺b; a◌᷺◌࡛◌̖◌֚b; a◌᷺◌࡛◌̖◌֚b; a◌᷺◌࡛◌̖◌֚b; a◌᷺◌࡛◌̖◌֚b; ) LATIN SMALL LETTER A, MANDAIC GEMINATION MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 0898 0062;00E0 05AE 0898 0315 0062;0061 05AE 0300 0898 0315 0062;00E0 05AE 0898 0315 0062;0061 05AE 0300 0898 0315 0062; # (a◌̕◌̀◌֮◌࢘b; à◌֮◌࢘◌̕b; a◌֮◌̀◌࢘◌̕b; à◌֮◌࢘◌̕b; a◌֮◌̀◌࢘◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH WORD AL-JUZ, LATIN SMALL LETTER B
+0061 0898 0315 0300 05AE 0062;0061 05AE 0898 0300 0315 0062;0061 05AE 0898 0300 0315 0062;0061 05AE 0898 0300 0315 0062;0061 05AE 0898 0300 0315 0062; # (a◌࢘◌̕◌̀◌֮b; a◌֮◌࢘◌̀◌̕b; a◌֮◌࢘◌̀◌̕b; a◌֮◌࢘◌̀◌̕b; a◌֮◌࢘◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH WORD AL-JUZ, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0899 0062;0061 1DFA 0316 0899 059A 0062;0061 1DFA 0316 0899 059A 0062;0061 1DFA 0316 0899 059A 0062;0061 1DFA 0316 0899 059A 0062; # (a◌֚◌̖◌᷺◌࢙b; a◌᷺◌̖◌࢙◌֚b; a◌᷺◌̖◌࢙◌֚b; a◌᷺◌̖◌࢙◌֚b; a◌᷺◌̖◌࢙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WORD ISHMAAM, LATIN SMALL LETTER B
+0061 0899 059A 0316 1DFA 0062;0061 1DFA 0899 0316 059A 0062;0061 1DFA 0899 0316 059A 0062;0061 1DFA 0899 0316 059A 0062;0061 1DFA 0899 0316 059A 0062; # (a◌࢙◌֚◌̖◌᷺b; a◌᷺◌࢙◌̖◌֚b; a◌᷺◌࢙◌̖◌֚b; a◌᷺◌࢙◌̖◌֚b; a◌᷺◌࢙◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WORD ISHMAAM, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 089A 0062;0061 1DFA 0316 089A 059A 0062;0061 1DFA 0316 089A 059A 0062;0061 1DFA 0316 089A 059A 0062;0061 1DFA 0316 089A 059A 0062; # (a◌֚◌̖◌᷺◌࢚b; a◌᷺◌̖◌࢚◌֚b; a◌᷺◌̖◌࢚◌֚b; a◌᷺◌̖◌࢚◌֚b; a◌᷺◌̖◌࢚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WORD IMAALA, LATIN SMALL LETTER B
+0061 089A 059A 0316 1DFA 0062;0061 1DFA 089A 0316 059A 0062;0061 1DFA 089A 0316 059A 0062;0061 1DFA 089A 0316 059A 0062;0061 1DFA 089A 0316 059A 0062; # (a◌࢚◌֚◌̖◌᷺b; a◌᷺◌࢚◌̖◌֚b; a◌᷺◌࢚◌̖◌֚b; a◌᷺◌࢚◌̖◌֚b; a◌᷺◌࢚◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WORD IMAALA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 089B 0062;0061 1DFA 0316 089B 059A 0062;0061 1DFA 0316 089B 059A 0062;0061 1DFA 0316 089B 059A 0062;0061 1DFA 0316 089B 059A 0062; # (a◌֚◌̖◌᷺◌࢛b; a◌᷺◌̖◌࢛◌֚b; a◌᷺◌̖◌࢛◌֚b; a◌᷺◌̖◌࢛◌֚b; a◌᷺◌̖◌࢛◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WORD TASHEEL, LATIN SMALL LETTER B
+0061 089B 059A 0316 1DFA 0062;0061 1DFA 089B 0316 059A 0062;0061 1DFA 089B 0316 059A 0062;0061 1DFA 089B 0316 059A 0062;0061 1DFA 089B 0316 059A 0062; # (a◌࢛◌֚◌̖◌᷺b; a◌᷺◌࢛◌̖◌֚b; a◌᷺◌࢛◌̖◌֚b; a◌᷺◌࢛◌̖◌֚b; a◌᷺◌࢛◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WORD TASHEEL, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 089C 0062;00E0 05AE 089C 0315 0062;0061 05AE 0300 089C 0315 0062;00E0 05AE 089C 0315 0062;0061 05AE 0300 089C 0315 0062; # (a◌̕◌̀◌֮◌࢜b; à◌֮◌࢜◌̕b; a◌֮◌̀◌࢜◌̕b; à◌֮◌࢜◌̕b; a◌֮◌̀◌࢜◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC MADDA WAAJIB, LATIN SMALL LETTER B
+0061 089C 0315 0300 05AE 0062;0061 05AE 089C 0300 0315 0062;0061 05AE 089C 0300 0315 0062;0061 05AE 089C 0300 0315 0062;0061 05AE 089C 0300 0315 0062; # (a◌࢜◌̕◌̀◌֮b; a◌֮◌࢜◌̀◌̕b; a◌֮◌࢜◌̀◌̕b; a◌֮◌࢜◌̀◌̕b; a◌֮◌࢜◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC MADDA WAAJIB, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 089D 0062;00E0 05AE 089D 0315 0062;0061 05AE 0300 089D 0315 0062;00E0 05AE 089D 0315 0062;0061 05AE 0300 089D 0315 0062; # (a◌̕◌̀◌֮◌à¢b; à◌֮◌à¢â—ŒÌ•b; a◌֮◌̀◌à¢â—ŒÌ•b; à◌֮◌à¢â—ŒÌ•b; a◌֮◌̀◌à¢â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SUPERSCRIPT ALEF MOKHASSAS, LATIN SMALL LETTER B
+0061 089D 0315 0300 05AE 0062;0061 05AE 089D 0300 0315 0062;0061 05AE 089D 0300 0315 0062;0061 05AE 089D 0300 0315 0062;0061 05AE 089D 0300 0315 0062; # (aâ—Œà¢â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌à¢â—ŒÌ€â—ŒÌ•b; a◌֮◌à¢â—ŒÌ€â—ŒÌ•b; a◌֮◌à¢â—ŒÌ€â—ŒÌ•b; a◌֮◌à¢â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, ARABIC SUPERSCRIPT ALEF MOKHASSAS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 089E 0062;00E0 05AE 089E 0315 0062;0061 05AE 0300 089E 0315 0062;00E0 05AE 089E 0315 0062;0061 05AE 0300 089E 0315 0062; # (a◌̕◌̀◌֮◌࢞b; à◌֮◌࢞◌̕b; a◌֮◌̀◌࢞◌̕b; à◌֮◌࢞◌̕b; a◌֮◌̀◌࢞◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC DOUBLED MADDA, LATIN SMALL LETTER B
+0061 089E 0315 0300 05AE 0062;0061 05AE 089E 0300 0315 0062;0061 05AE 089E 0300 0315 0062;0061 05AE 089E 0300 0315 0062;0061 05AE 089E 0300 0315 0062; # (a◌࢞◌̕◌̀◌֮b; a◌֮◌࢞◌̀◌̕b; a◌֮◌࢞◌̀◌̕b; a◌֮◌࢞◌̀◌̕b; a◌֮◌࢞◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC DOUBLED MADDA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 089F 0062;00E0 05AE 089F 0315 0062;0061 05AE 0300 089F 0315 0062;00E0 05AE 089F 0315 0062;0061 05AE 0300 089F 0315 0062; # (a◌̕◌̀◌֮◌࢟b; à◌֮◌࢟◌̕b; a◌֮◌̀◌࢟◌̕b; à◌֮◌࢟◌̕b; a◌֮◌̀◌࢟◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC HALF MADDA OVER MADDA, LATIN SMALL LETTER B
+0061 089F 0315 0300 05AE 0062;0061 05AE 089F 0300 0315 0062;0061 05AE 089F 0300 0315 0062;0061 05AE 089F 0300 0315 0062;0061 05AE 089F 0300 0315 0062; # (a◌࢟◌̕◌̀◌֮b; a◌֮◌࢟◌̀◌̕b; a◌֮◌࢟◌̀◌̕b; a◌֮◌࢟◌̀◌̕b; a◌֮◌࢟◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC HALF MADDA OVER MADDA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 08CA 0062;00E0 05AE 08CA 0315 0062;0061 05AE 0300 08CA 0315 0062;00E0 05AE 08CA 0315 0062;0061 05AE 0300 08CA 0315 0062; # (a◌̕◌̀◌֮◌࣊b; à◌֮◌࣊◌̕b; a◌֮◌̀◌࣊◌̕b; à◌֮◌࣊◌̕b; a◌֮◌̀◌࣊◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH FARSI YEH, LATIN SMALL LETTER B
+0061 08CA 0315 0300 05AE 0062;0061 05AE 08CA 0300 0315 0062;0061 05AE 08CA 0300 0315 0062;0061 05AE 08CA 0300 0315 0062;0061 05AE 08CA 0300 0315 0062; # (a◌࣊◌̕◌̀◌֮b; a◌֮◌࣊◌̀◌̕b; a◌֮◌࣊◌̀◌̕b; a◌֮◌࣊◌̀◌̕b; a◌֮◌࣊◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH FARSI YEH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 08CB 0062;00E0 05AE 08CB 0315 0062;0061 05AE 0300 08CB 0315 0062;00E0 05AE 08CB 0315 0062;0061 05AE 0300 08CB 0315 0062; # (a◌̕◌̀◌֮◌࣋b; à◌֮◌࣋◌̕b; a◌֮◌̀◌࣋◌̕b; à◌֮◌࣋◌̕b; a◌֮◌̀◌࣋◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW, LATIN SMALL LETTER B
+0061 08CB 0315 0300 05AE 0062;0061 05AE 08CB 0300 0315 0062;0061 05AE 08CB 0300 0315 0062;0061 05AE 08CB 0300 0315 0062;0061 05AE 08CB 0300 0315 0062; # (a◌࣋◌̕◌̀◌֮b; a◌֮◌࣋◌̀◌̕b; a◌֮◌࣋◌̀◌̕b; a◌֮◌࣋◌̀◌̕b; a◌֮◌࣋◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 08CC 0062;00E0 05AE 08CC 0315 0062;0061 05AE 0300 08CC 0315 0062;00E0 05AE 08CC 0315 0062;0061 05AE 0300 08CC 0315 0062; # (a◌̕◌̀◌֮◌࣌b; à◌֮◌࣌◌̕b; a◌֮◌̀◌࣌◌̕b; à◌֮◌࣌◌̕b; a◌֮◌̀◌࣌◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH WORD SAH, LATIN SMALL LETTER B
+0061 08CC 0315 0300 05AE 0062;0061 05AE 08CC 0300 0315 0062;0061 05AE 08CC 0300 0315 0062;0061 05AE 08CC 0300 0315 0062;0061 05AE 08CC 0300 0315 0062; # (a◌࣌◌̕◌̀◌֮b; a◌֮◌࣌◌̀◌̕b; a◌֮◌࣌◌̀◌̕b; a◌֮◌࣌◌̀◌̕b; a◌֮◌࣌◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH WORD SAH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 08CD 0062;00E0 05AE 08CD 0315 0062;0061 05AE 0300 08CD 0315 0062;00E0 05AE 08CD 0315 0062;0061 05AE 0300 08CD 0315 0062; # (a◌̕◌̀◌֮◌à£b; à◌֮◌à£â—ŒÌ•b; a◌֮◌̀◌à£â—ŒÌ•b; à◌֮◌à£â—ŒÌ•b; a◌֮◌̀◌à£â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH ZAH, LATIN SMALL LETTER B
+0061 08CD 0315 0300 05AE 0062;0061 05AE 08CD 0300 0315 0062;0061 05AE 08CD 0300 0315 0062;0061 05AE 08CD 0300 0315 0062;0061 05AE 08CD 0300 0315 0062; # (aâ—Œà£â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌à£â—ŒÌ€â—ŒÌ•b; a◌֮◌à£â—ŒÌ€â—ŒÌ•b; a◌֮◌à£â—ŒÌ€â—ŒÌ•b; a◌֮◌à£â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH ZAH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 08CE 0062;00E0 05AE 08CE 0315 0062;0061 05AE 0300 08CE 0315 0062;00E0 05AE 08CE 0315 0062;0061 05AE 0300 08CE 0315 0062; # (a◌̕◌̀◌֮◌࣎b; à◌֮◌࣎◌̕b; a◌֮◌̀◌࣎◌̕b; à◌֮◌࣎◌̕b; a◌֮◌̀◌࣎◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC LARGE ROUND DOT ABOVE, LATIN SMALL LETTER B
+0061 08CE 0315 0300 05AE 0062;0061 05AE 08CE 0300 0315 0062;0061 05AE 08CE 0300 0315 0062;0061 05AE 08CE 0300 0315 0062;0061 05AE 08CE 0300 0315 0062; # (a◌࣎◌̕◌̀◌֮b; a◌֮◌࣎◌̀◌̕b; a◌֮◌࣎◌̀◌̕b; a◌֮◌࣎◌̀◌̕b; a◌֮◌࣎◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC LARGE ROUND DOT ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08CF 0062;0061 1DFA 0316 08CF 059A 0062;0061 1DFA 0316 08CF 059A 0062;0061 1DFA 0316 08CF 059A 0062;0061 1DFA 0316 08CF 059A 0062; # (a◌֚◌̖◌᷺◌à£b; a◌᷺◌̖◌à£â—ŒÖšb; a◌᷺◌̖◌à£â—ŒÖšb; a◌᷺◌̖◌à£â—ŒÖšb; a◌᷺◌̖◌à£â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC LARGE ROUND DOT BELOW, LATIN SMALL LETTER B
+0061 08CF 059A 0316 1DFA 0062;0061 1DFA 08CF 0316 059A 0062;0061 1DFA 08CF 0316 059A 0062;0061 1DFA 08CF 0316 059A 0062;0061 1DFA 08CF 0316 059A 0062; # (aâ—Œà£â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌à£â—ŒÌ–◌֚b; a◌᷺◌à£â—ŒÌ–◌֚b; a◌᷺◌à£â—ŒÌ–◌֚b; a◌᷺◌à£â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, ARABIC LARGE ROUND DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08D0 0062;0061 1DFA 0316 08D0 059A 0062;0061 1DFA 0316 08D0 059A 0062;0061 1DFA 0316 08D0 059A 0062;0061 1DFA 0316 08D0 059A 0062; # (a◌֚◌̖◌᷺◌à£b; a◌᷺◌̖◌à£â—ŒÖšb; a◌᷺◌̖◌à£â—ŒÖšb; a◌᷺◌̖◌à£â—ŒÖšb; a◌᷺◌̖◌à£â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SUKUN BELOW, LATIN SMALL LETTER B
+0061 08D0 059A 0316 1DFA 0062;0061 1DFA 08D0 0316 059A 0062;0061 1DFA 08D0 0316 059A 0062;0061 1DFA 08D0 0316 059A 0062;0061 1DFA 08D0 0316 059A 0062; # (aâ—Œà£â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌à£â—ŒÌ–◌֚b; a◌᷺◌à£â—ŒÌ–◌֚b; a◌᷺◌à£â—ŒÌ–◌֚b; a◌᷺◌à£â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, ARABIC SUKUN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08D1 0062;0061 1DFA 0316 08D1 059A 0062;0061 1DFA 0316 08D1 059A 0062;0061 1DFA 0316 08D1 059A 0062;0061 1DFA 0316 08D1 059A 0062; # (a◌֚◌̖◌᷺◌࣑b; a◌᷺◌̖◌࣑◌֚b; a◌᷺◌̖◌࣑◌֚b; a◌᷺◌̖◌࣑◌֚b; a◌᷺◌̖◌࣑◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC LARGE CIRCLE BELOW, LATIN SMALL LETTER B
+0061 08D1 059A 0316 1DFA 0062;0061 1DFA 08D1 0316 059A 0062;0061 1DFA 08D1 0316 059A 0062;0061 1DFA 08D1 0316 059A 0062;0061 1DFA 08D1 0316 059A 0062; # (a◌࣑◌֚◌̖◌᷺b; a◌᷺◌࣑◌̖◌֚b; a◌᷺◌࣑◌̖◌֚b; a◌᷺◌࣑◌̖◌֚b; a◌᷺◌࣑◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC LARGE CIRCLE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08D2 0062;0061 1DFA 0316 08D2 059A 0062;0061 1DFA 0316 08D2 059A 0062;0061 1DFA 0316 08D2 059A 0062;0061 1DFA 0316 08D2 059A 0062; # (a◌֚◌̖◌᷺◌࣒b; a◌᷺◌̖◌࣒◌֚b; a◌᷺◌̖◌࣒◌֚b; a◌᷺◌̖◌࣒◌֚b; a◌᷺◌̖◌࣒◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW, LATIN SMALL LETTER B
+0061 08D2 059A 0316 1DFA 0062;0061 1DFA 08D2 0316 059A 0062;0061 1DFA 08D2 0316 059A 0062;0061 1DFA 08D2 0316 059A 0062;0061 1DFA 08D2 0316 059A 0062; # (a◌࣒◌֚◌̖◌᷺b; a◌᷺◌࣒◌̖◌֚b; a◌᷺◌࣒◌̖◌֚b; a◌᷺◌࣒◌̖◌֚b; a◌᷺◌࣒◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08D3 0062;0061 1DFA 0316 08D3 059A 0062;0061 1DFA 0316 08D3 059A 0062;0061 1DFA 0316 08D3 059A 0062;0061 1DFA 0316 08D3 059A 0062; # (a◌֚◌̖◌᷺◌࣓b; a◌᷺◌̖◌࣓◌֚b; a◌᷺◌̖◌࣓◌֚b; a◌᷺◌̖◌࣓◌֚b; a◌᷺◌̖◌࣓◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC SMALL LOW WAW, LATIN SMALL LETTER B
+0061 08D3 059A 0316 1DFA 0062;0061 1DFA 08D3 0316 059A 0062;0061 1DFA 08D3 0316 059A 0062;0061 1DFA 08D3 0316 059A 0062;0061 1DFA 08D3 0316 059A 0062; # (a◌࣓◌֚◌̖◌᷺b; a◌᷺◌࣓◌̖◌֚b; a◌᷺◌࣓◌̖◌֚b; a◌᷺◌࣓◌̖◌֚b; a◌᷺◌࣓◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC SMALL LOW WAW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 08D4 0062;00E0 05AE 08D4 0315 0062;0061 05AE 0300 08D4 0315 0062;00E0 05AE 08D4 0315 0062;0061 05AE 0300 08D4 0315 0062; # (a◌̕◌̀◌֮◌ࣔb; à◌֮◌ࣔ◌̕b; a◌֮◌̀◌ࣔ◌̕b; à◌֮◌ࣔ◌̕b; a◌֮◌̀◌ࣔ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH WORD AR-RUB, LATIN SMALL LETTER B
0061 08D4 0315 0300 05AE 0062;0061 05AE 08D4 0300 0315 0062;0061 05AE 08D4 0300 0315 0062;0061 05AE 08D4 0300 0315 0062;0061 05AE 08D4 0300 0315 0062; # (a◌ࣔ◌̕◌̀◌֮b; a◌֮◌ࣔ◌̀◌̕b; a◌֮◌ࣔ◌̀◌̕b; a◌֮◌ࣔ◌̀◌̕b; a◌֮◌ࣔ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH WORD AR-RUB, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08D5 0062;00E0 05AE 08D5 0315 0062;0061 05AE 0300 08D5 0315 0062;00E0 05AE 08D5 0315 0062;0061 05AE 0300 08D5 0315 0062; # (a◌̕◌̀◌֮◌ࣕb; à◌֮◌ࣕ◌̕b; a◌֮◌̀◌ࣕ◌̕b; à◌֮◌ࣕ◌̕b; a◌֮◌̀◌ࣕ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH SAD, LATIN SMALL LETTER B
@@ -17573,32 +17666,32 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 08E0 0315 0300 05AE 0062;0061 05AE 08E0 0300 0315 0062;0061 05AE 08E0 0300 0315 0062;0061 05AE 08E0 0300 0315 0062;0061 05AE 08E0 0300 0315 0062; # (a◌࣠◌̕◌̀◌֮b; a◌֮◌࣠◌̀◌̕b; a◌֮◌࣠◌̀◌̕b; a◌֮◌࣠◌̀◌̕b; a◌֮◌࣠◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH FOOTNOTE MARKER, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08E1 0062;00E0 05AE 08E1 0315 0062;0061 05AE 0300 08E1 0315 0062;00E0 05AE 08E1 0315 0062;0061 05AE 0300 08E1 0315 0062; # (a◌̕◌̀◌֮◌࣡b; à◌֮◌࣡◌̕b; a◌֮◌̀◌࣡◌̕b; à◌֮◌࣡◌̕b; a◌֮◌̀◌࣡◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC SMALL HIGH SIGN SAFHA, LATIN SMALL LETTER B
0061 08E1 0315 0300 05AE 0062;0061 05AE 08E1 0300 0315 0062;0061 05AE 08E1 0300 0315 0062;0061 05AE 08E1 0300 0315 0062;0061 05AE 08E1 0300 0315 0062; # (a◌࣡◌̕◌̀◌֮b; a◌֮◌࣡◌̀◌̕b; a◌֮◌࣡◌̀◌̕b; a◌֮◌࣡◌̀◌̕b; a◌֮◌࣡◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC SMALL HIGH SIGN SAFHA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 08E3 0062;0061 302A 0316 08E3 059A 0062;0061 302A 0316 08E3 059A 0062;0061 302A 0316 08E3 059A 0062;0061 302A 0316 08E3 059A 0062; # (a◌֚◌̖◌〪◌ࣣb; a◌〪◌̖◌ࣣ◌֚b; a◌〪◌̖◌ࣣ◌֚b; a◌〪◌̖◌ࣣ◌֚b; a◌〪◌̖◌ࣣ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC TURNED DAMMA BELOW, LATIN SMALL LETTER B
-0061 08E3 059A 0316 302A 0062;0061 302A 08E3 0316 059A 0062;0061 302A 08E3 0316 059A 0062;0061 302A 08E3 0316 059A 0062;0061 302A 08E3 0316 059A 0062; # (a◌ࣣ◌֚◌̖◌〪b; a◌〪◌ࣣ◌̖◌֚b; a◌〪◌ࣣ◌̖◌֚b; a◌〪◌ࣣ◌̖◌֚b; a◌〪◌ࣣ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TURNED DAMMA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08E3 0062;0061 1DFA 0316 08E3 059A 0062;0061 1DFA 0316 08E3 059A 0062;0061 1DFA 0316 08E3 059A 0062;0061 1DFA 0316 08E3 059A 0062; # (a◌֚◌̖◌᷺◌ࣣb; a◌᷺◌̖◌ࣣ◌֚b; a◌᷺◌̖◌ࣣ◌֚b; a◌᷺◌̖◌ࣣ◌֚b; a◌᷺◌̖◌ࣣ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC TURNED DAMMA BELOW, LATIN SMALL LETTER B
+0061 08E3 059A 0316 1DFA 0062;0061 1DFA 08E3 0316 059A 0062;0061 1DFA 08E3 0316 059A 0062;0061 1DFA 08E3 0316 059A 0062;0061 1DFA 08E3 0316 059A 0062; # (a◌ࣣ◌֚◌̖◌᷺b; a◌᷺◌ࣣ◌̖◌֚b; a◌᷺◌ࣣ◌̖◌֚b; a◌᷺◌ࣣ◌̖◌֚b; a◌᷺◌ࣣ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TURNED DAMMA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 08E4 0062;00E0 05AE 08E4 0315 0062;0061 05AE 0300 08E4 0315 0062;00E0 05AE 08E4 0315 0062;0061 05AE 0300 08E4 0315 0062; # (a◌̕◌̀◌֮◌ࣤb; à◌֮◌ࣤ◌̕b; a◌֮◌̀◌ࣤ◌̕b; à◌֮◌ࣤ◌̕b; a◌֮◌̀◌ࣤ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC CURLY FATHA, LATIN SMALL LETTER B
0061 08E4 0315 0300 05AE 0062;0061 05AE 08E4 0300 0315 0062;0061 05AE 08E4 0300 0315 0062;0061 05AE 08E4 0300 0315 0062;0061 05AE 08E4 0300 0315 0062; # (a◌ࣤ◌̕◌̀◌֮b; a◌֮◌ࣤ◌̀◌̕b; a◌֮◌ࣤ◌̀◌̕b; a◌֮◌ࣤ◌̀◌̕b; a◌֮◌ࣤ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC CURLY FATHA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08E5 0062;00E0 05AE 08E5 0315 0062;0061 05AE 0300 08E5 0315 0062;00E0 05AE 08E5 0315 0062;0061 05AE 0300 08E5 0315 0062; # (a◌̕◌̀◌֮◌ࣥb; à◌֮◌ࣥ◌̕b; a◌֮◌̀◌ࣥ◌̕b; à◌֮◌ࣥ◌̕b; a◌֮◌̀◌ࣥ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC CURLY DAMMA, LATIN SMALL LETTER B
0061 08E5 0315 0300 05AE 0062;0061 05AE 08E5 0300 0315 0062;0061 05AE 08E5 0300 0315 0062;0061 05AE 08E5 0300 0315 0062;0061 05AE 08E5 0300 0315 0062; # (a◌ࣥ◌̕◌̀◌֮b; a◌֮◌ࣥ◌̀◌̕b; a◌֮◌ࣥ◌̀◌̕b; a◌֮◌ࣥ◌̀◌̕b; a◌֮◌ࣥ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC CURLY DAMMA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 08E6 0062;0061 302A 0316 08E6 059A 0062;0061 302A 0316 08E6 059A 0062;0061 302A 0316 08E6 059A 0062;0061 302A 0316 08E6 059A 0062; # (a◌֚◌̖◌〪◌ࣦb; a◌〪◌̖◌ࣦ◌֚b; a◌〪◌̖◌ࣦ◌֚b; a◌〪◌̖◌ࣦ◌֚b; a◌〪◌̖◌ࣦ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC CURLY KASRA, LATIN SMALL LETTER B
-0061 08E6 059A 0316 302A 0062;0061 302A 08E6 0316 059A 0062;0061 302A 08E6 0316 059A 0062;0061 302A 08E6 0316 059A 0062;0061 302A 08E6 0316 059A 0062; # (a◌ࣦ◌֚◌̖◌〪b; a◌〪◌ࣦ◌̖◌֚b; a◌〪◌ࣦ◌̖◌֚b; a◌〪◌ࣦ◌̖◌֚b; a◌〪◌ࣦ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC CURLY KASRA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08E6 0062;0061 1DFA 0316 08E6 059A 0062;0061 1DFA 0316 08E6 059A 0062;0061 1DFA 0316 08E6 059A 0062;0061 1DFA 0316 08E6 059A 0062; # (a◌֚◌̖◌᷺◌ࣦb; a◌᷺◌̖◌ࣦ◌֚b; a◌᷺◌̖◌ࣦ◌֚b; a◌᷺◌̖◌ࣦ◌֚b; a◌᷺◌̖◌ࣦ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC CURLY KASRA, LATIN SMALL LETTER B
+0061 08E6 059A 0316 1DFA 0062;0061 1DFA 08E6 0316 059A 0062;0061 1DFA 08E6 0316 059A 0062;0061 1DFA 08E6 0316 059A 0062;0061 1DFA 08E6 0316 059A 0062; # (a◌ࣦ◌֚◌̖◌᷺b; a◌᷺◌ࣦ◌̖◌֚b; a◌᷺◌ࣦ◌̖◌֚b; a◌᷺◌ࣦ◌̖◌֚b; a◌᷺◌ࣦ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC CURLY KASRA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 08E7 0062;00E0 05AE 08E7 0315 0062;0061 05AE 0300 08E7 0315 0062;00E0 05AE 08E7 0315 0062;0061 05AE 0300 08E7 0315 0062; # (a◌̕◌̀◌֮◌ࣧb; à◌֮◌ࣧ◌̕b; a◌֮◌̀◌ࣧ◌̕b; à◌֮◌ࣧ◌̕b; a◌֮◌̀◌ࣧ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC CURLY FATHATAN, LATIN SMALL LETTER B
0061 08E7 0315 0300 05AE 0062;0061 05AE 08E7 0300 0315 0062;0061 05AE 08E7 0300 0315 0062;0061 05AE 08E7 0300 0315 0062;0061 05AE 08E7 0300 0315 0062; # (a◌ࣧ◌̕◌̀◌֮b; a◌֮◌ࣧ◌̀◌̕b; a◌֮◌ࣧ◌̀◌̕b; a◌֮◌ࣧ◌̀◌̕b; a◌֮◌ࣧ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC CURLY FATHATAN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08E8 0062;00E0 05AE 08E8 0315 0062;0061 05AE 0300 08E8 0315 0062;00E0 05AE 08E8 0315 0062;0061 05AE 0300 08E8 0315 0062; # (a◌̕◌̀◌֮◌ࣨb; à◌֮◌ࣨ◌̕b; a◌֮◌̀◌ࣨ◌̕b; à◌֮◌ࣨ◌̕b; a◌֮◌̀◌ࣨ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC CURLY DAMMATAN, LATIN SMALL LETTER B
0061 08E8 0315 0300 05AE 0062;0061 05AE 08E8 0300 0315 0062;0061 05AE 08E8 0300 0315 0062;0061 05AE 08E8 0300 0315 0062;0061 05AE 08E8 0300 0315 0062; # (a◌ࣨ◌̕◌̀◌֮b; a◌֮◌ࣨ◌̀◌̕b; a◌֮◌ࣨ◌̀◌̕b; a◌֮◌ࣨ◌̀◌̕b; a◌֮◌ࣨ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC CURLY DAMMATAN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 08E9 0062;0061 302A 0316 08E9 059A 0062;0061 302A 0316 08E9 059A 0062;0061 302A 0316 08E9 059A 0062;0061 302A 0316 08E9 059A 0062; # (a◌֚◌̖◌〪◌ࣩb; a◌〪◌̖◌ࣩ◌֚b; a◌〪◌̖◌ࣩ◌֚b; a◌〪◌̖◌ࣩ◌֚b; a◌〪◌̖◌ࣩ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC CURLY KASRATAN, LATIN SMALL LETTER B
-0061 08E9 059A 0316 302A 0062;0061 302A 08E9 0316 059A 0062;0061 302A 08E9 0316 059A 0062;0061 302A 08E9 0316 059A 0062;0061 302A 08E9 0316 059A 0062; # (a◌ࣩ◌֚◌̖◌〪b; a◌〪◌ࣩ◌̖◌֚b; a◌〪◌ࣩ◌̖◌֚b; a◌〪◌ࣩ◌̖◌֚b; a◌〪◌ࣩ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC CURLY KASRATAN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08E9 0062;0061 1DFA 0316 08E9 059A 0062;0061 1DFA 0316 08E9 059A 0062;0061 1DFA 0316 08E9 059A 0062;0061 1DFA 0316 08E9 059A 0062; # (a◌֚◌̖◌᷺◌ࣩb; a◌᷺◌̖◌ࣩ◌֚b; a◌᷺◌̖◌ࣩ◌֚b; a◌᷺◌̖◌ࣩ◌֚b; a◌᷺◌̖◌ࣩ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC CURLY KASRATAN, LATIN SMALL LETTER B
+0061 08E9 059A 0316 1DFA 0062;0061 1DFA 08E9 0316 059A 0062;0061 1DFA 08E9 0316 059A 0062;0061 1DFA 08E9 0316 059A 0062;0061 1DFA 08E9 0316 059A 0062; # (a◌ࣩ◌֚◌̖◌᷺b; a◌᷺◌ࣩ◌̖◌֚b; a◌᷺◌ࣩ◌̖◌֚b; a◌᷺◌ࣩ◌̖◌֚b; a◌᷺◌ࣩ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC CURLY KASRATAN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 08EA 0062;00E0 05AE 08EA 0315 0062;0061 05AE 0300 08EA 0315 0062;00E0 05AE 08EA 0315 0062;0061 05AE 0300 08EA 0315 0062; # (a◌̕◌̀◌֮◌࣪b; à◌֮◌࣪◌̕b; a◌֮◌̀◌࣪◌̕b; à◌֮◌࣪◌̕b; a◌֮◌̀◌࣪◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC TONE ONE DOT ABOVE, LATIN SMALL LETTER B
0061 08EA 0315 0300 05AE 0062;0061 05AE 08EA 0300 0315 0062;0061 05AE 08EA 0300 0315 0062;0061 05AE 08EA 0300 0315 0062;0061 05AE 08EA 0300 0315 0062; # (a◌࣪◌̕◌̀◌֮b; a◌֮◌࣪◌̀◌̕b; a◌֮◌࣪◌̀◌̕b; a◌֮◌࣪◌̀◌̕b; a◌֮◌࣪◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC TONE ONE DOT ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08EB 0062;00E0 05AE 08EB 0315 0062;0061 05AE 0300 08EB 0315 0062;00E0 05AE 08EB 0315 0062;0061 05AE 0300 08EB 0315 0062; # (a◌̕◌̀◌֮◌࣫b; à◌֮◌࣫◌̕b; a◌֮◌̀◌࣫◌̕b; à◌֮◌࣫◌̕b; a◌֮◌̀◌࣫◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC TONE TWO DOTS ABOVE, LATIN SMALL LETTER B
0061 08EB 0315 0300 05AE 0062;0061 05AE 08EB 0300 0315 0062;0061 05AE 08EB 0300 0315 0062;0061 05AE 08EB 0300 0315 0062;0061 05AE 08EB 0300 0315 0062; # (a◌࣫◌̕◌̀◌֮b; a◌֮◌࣫◌̀◌̕b; a◌֮◌࣫◌̀◌̕b; a◌֮◌࣫◌̀◌̕b; a◌֮◌࣫◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC TONE TWO DOTS ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08EC 0062;00E0 05AE 08EC 0315 0062;0061 05AE 0300 08EC 0315 0062;00E0 05AE 08EC 0315 0062;0061 05AE 0300 08EC 0315 0062; # (a◌̕◌̀◌֮◌࣬b; à◌֮◌࣬◌̕b; a◌֮◌̀◌࣬◌̕b; à◌֮◌࣬◌̕b; a◌֮◌̀◌࣬◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC TONE LOOP ABOVE, LATIN SMALL LETTER B
0061 08EC 0315 0300 05AE 0062;0061 05AE 08EC 0300 0315 0062;0061 05AE 08EC 0300 0315 0062;0061 05AE 08EC 0300 0315 0062;0061 05AE 08EC 0300 0315 0062; # (a◌࣬◌̕◌̀◌֮b; a◌֮◌࣬◌̀◌̕b; a◌֮◌࣬◌̀◌̕b; a◌֮◌࣬◌̀◌̕b; a◌֮◌࣬◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC TONE LOOP ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 08ED 0062;0061 302A 0316 08ED 059A 0062;0061 302A 0316 08ED 059A 0062;0061 302A 0316 08ED 059A 0062;0061 302A 0316 08ED 059A 0062; # (a◌֚◌̖◌〪◌࣭b; a◌〪◌̖◌࣭◌֚b; a◌〪◌̖◌࣭◌֚b; a◌〪◌̖◌࣭◌֚b; a◌〪◌̖◌࣭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC TONE ONE DOT BELOW, LATIN SMALL LETTER B
-0061 08ED 059A 0316 302A 0062;0061 302A 08ED 0316 059A 0062;0061 302A 08ED 0316 059A 0062;0061 302A 08ED 0316 059A 0062;0061 302A 08ED 0316 059A 0062; # (a◌࣭◌֚◌̖◌〪b; a◌〪◌࣭◌̖◌֚b; a◌〪◌࣭◌̖◌֚b; a◌〪◌࣭◌̖◌֚b; a◌〪◌࣭◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TONE ONE DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 08EE 0062;0061 302A 0316 08EE 059A 0062;0061 302A 0316 08EE 059A 0062;0061 302A 0316 08EE 059A 0062;0061 302A 0316 08EE 059A 0062; # (a◌֚◌̖◌〪◌࣮b; a◌〪◌̖◌࣮◌֚b; a◌〪◌̖◌࣮◌֚b; a◌〪◌̖◌࣮◌֚b; a◌〪◌̖◌࣮◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC TONE TWO DOTS BELOW, LATIN SMALL LETTER B
-0061 08EE 059A 0316 302A 0062;0061 302A 08EE 0316 059A 0062;0061 302A 08EE 0316 059A 0062;0061 302A 08EE 0316 059A 0062;0061 302A 08EE 0316 059A 0062; # (a◌࣮◌֚◌̖◌〪b; a◌〪◌࣮◌̖◌֚b; a◌〪◌࣮◌̖◌֚b; a◌〪◌࣮◌̖◌֚b; a◌〪◌࣮◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TONE TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 08EF 0062;0061 302A 0316 08EF 059A 0062;0061 302A 0316 08EF 059A 0062;0061 302A 0316 08EF 059A 0062;0061 302A 0316 08EF 059A 0062; # (a◌֚◌̖◌〪◌࣯b; a◌〪◌̖◌࣯◌֚b; a◌〪◌̖◌࣯◌֚b; a◌〪◌̖◌࣯◌֚b; a◌〪◌̖◌࣯◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC TONE LOOP BELOW, LATIN SMALL LETTER B
-0061 08EF 059A 0316 302A 0062;0061 302A 08EF 0316 059A 0062;0061 302A 08EF 0316 059A 0062;0061 302A 08EF 0316 059A 0062;0061 302A 08EF 0316 059A 0062; # (a◌࣯◌֚◌̖◌〪b; a◌〪◌࣯◌̖◌֚b; a◌〪◌࣯◌̖◌֚b; a◌〪◌࣯◌̖◌֚b; a◌〪◌࣯◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TONE LOOP BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08ED 0062;0061 1DFA 0316 08ED 059A 0062;0061 1DFA 0316 08ED 059A 0062;0061 1DFA 0316 08ED 059A 0062;0061 1DFA 0316 08ED 059A 0062; # (a◌֚◌̖◌᷺◌࣭b; a◌᷺◌̖◌࣭◌֚b; a◌᷺◌̖◌࣭◌֚b; a◌᷺◌̖◌࣭◌֚b; a◌᷺◌̖◌࣭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC TONE ONE DOT BELOW, LATIN SMALL LETTER B
+0061 08ED 059A 0316 1DFA 0062;0061 1DFA 08ED 0316 059A 0062;0061 1DFA 08ED 0316 059A 0062;0061 1DFA 08ED 0316 059A 0062;0061 1DFA 08ED 0316 059A 0062; # (a◌࣭◌֚◌̖◌᷺b; a◌᷺◌࣭◌̖◌֚b; a◌᷺◌࣭◌̖◌֚b; a◌᷺◌࣭◌̖◌֚b; a◌᷺◌࣭◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TONE ONE DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08EE 0062;0061 1DFA 0316 08EE 059A 0062;0061 1DFA 0316 08EE 059A 0062;0061 1DFA 0316 08EE 059A 0062;0061 1DFA 0316 08EE 059A 0062; # (a◌֚◌̖◌᷺◌࣮b; a◌᷺◌̖◌࣮◌֚b; a◌᷺◌̖◌࣮◌֚b; a◌᷺◌̖◌࣮◌֚b; a◌᷺◌̖◌࣮◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC TONE TWO DOTS BELOW, LATIN SMALL LETTER B
+0061 08EE 059A 0316 1DFA 0062;0061 1DFA 08EE 0316 059A 0062;0061 1DFA 08EE 0316 059A 0062;0061 1DFA 08EE 0316 059A 0062;0061 1DFA 08EE 0316 059A 0062; # (a◌࣮◌֚◌̖◌᷺b; a◌᷺◌࣮◌̖◌֚b; a◌᷺◌࣮◌̖◌֚b; a◌᷺◌࣮◌̖◌֚b; a◌᷺◌࣮◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TONE TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08EF 0062;0061 1DFA 0316 08EF 059A 0062;0061 1DFA 0316 08EF 059A 0062;0061 1DFA 0316 08EF 059A 0062;0061 1DFA 0316 08EF 059A 0062; # (a◌֚◌̖◌᷺◌࣯b; a◌᷺◌̖◌࣯◌֚b; a◌᷺◌̖◌࣯◌֚b; a◌᷺◌̖◌࣯◌֚b; a◌᷺◌̖◌࣯◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC TONE LOOP BELOW, LATIN SMALL LETTER B
+0061 08EF 059A 0316 1DFA 0062;0061 1DFA 08EF 0316 059A 0062;0061 1DFA 08EF 0316 059A 0062;0061 1DFA 08EF 0316 059A 0062;0061 1DFA 08EF 0316 059A 0062; # (a◌࣯◌֚◌̖◌᷺b; a◌᷺◌࣯◌̖◌֚b; a◌᷺◌࣯◌̖◌֚b; a◌᷺◌࣯◌̖◌֚b; a◌᷺◌࣯◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC TONE LOOP BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 064C 064B FB1E 08F0 0062;0061 FB1E 064B 08F0 064C 0062;0061 FB1E 064B 08F0 064C 0062;0061 FB1E 064B 08F0 064C 0062;0061 FB1E 064B 08F0 064C 0062; # (a◌ٌ◌ً◌ﬞ◌ࣰb; a◌ﬞ◌ً◌ࣰ◌ٌb; a◌ﬞ◌ً◌ࣰ◌ٌb; a◌ﬞ◌ً◌ࣰ◌ٌb; a◌ﬞ◌ً◌ࣰ◌ٌb; ) LATIN SMALL LETTER A, ARABIC DAMMATAN, ARABIC FATHATAN, HEBREW POINT JUDEO-SPANISH VARIKA, ARABIC OPEN FATHATAN, LATIN SMALL LETTER B
0061 08F0 064C 064B FB1E 0062;0061 FB1E 08F0 064B 064C 0062;0061 FB1E 08F0 064B 064C 0062;0061 FB1E 08F0 064B 064C 0062;0061 FB1E 08F0 064B 064C 0062; # (a◌ࣰ◌ٌ◌ً◌ﬞb; a◌ﬞ◌ࣰ◌ً◌ٌb; a◌ﬞ◌ࣰ◌ً◌ٌb; a◌ﬞ◌ࣰ◌ً◌ٌb; a◌ﬞ◌ࣰ◌ً◌ٌb; ) LATIN SMALL LETTER A, ARABIC OPEN FATHATAN, ARABIC DAMMATAN, ARABIC FATHATAN, HEBREW POINT JUDEO-SPANISH VARIKA, LATIN SMALL LETTER B
0061 064D 064C 064B 08F1 0062;0061 064B 064C 08F1 064D 0062;0061 064B 064C 08F1 064D 0062;0061 064B 064C 08F1 064D 0062;0061 064B 064C 08F1 064D 0062; # (aâ—ŒÙ◌ٌ◌ً◌ࣱb; a◌ً◌ٌ◌ࣱ◌Ùb; a◌ً◌ٌ◌ࣱ◌Ùb; a◌ً◌ٌ◌ࣱ◌Ùb; a◌ً◌ٌ◌ࣱ◌Ùb; ) LATIN SMALL LETTER A, ARABIC KASRATAN, ARABIC DAMMATAN, ARABIC FATHATAN, ARABIC OPEN DAMMATAN, LATIN SMALL LETTER B
@@ -17611,16 +17704,16 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 08F4 0315 0300 05AE 0062;0061 05AE 08F4 0300 0315 0062;0061 05AE 08F4 0300 0315 0062;0061 05AE 08F4 0300 0315 0062;0061 05AE 08F4 0300 0315 0062; # (a◌ࣴ◌̕◌̀◌֮b; a◌֮◌ࣴ◌̀◌̕b; a◌֮◌ࣴ◌̀◌̕b; a◌֮◌ࣴ◌̀◌̕b; a◌֮◌ࣴ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC FATHA WITH RING, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08F5 0062;00E0 05AE 08F5 0315 0062;0061 05AE 0300 08F5 0315 0062;00E0 05AE 08F5 0315 0062;0061 05AE 0300 08F5 0315 0062; # (a◌̕◌̀◌֮◌ࣵb; à◌֮◌ࣵ◌̕b; a◌֮◌̀◌ࣵ◌̕b; à◌֮◌ࣵ◌̕b; a◌֮◌̀◌ࣵ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC FATHA WITH DOT ABOVE, LATIN SMALL LETTER B
0061 08F5 0315 0300 05AE 0062;0061 05AE 08F5 0300 0315 0062;0061 05AE 08F5 0300 0315 0062;0061 05AE 08F5 0300 0315 0062;0061 05AE 08F5 0300 0315 0062; # (a◌ࣵ◌̕◌̀◌֮b; a◌֮◌ࣵ◌̀◌̕b; a◌֮◌ࣵ◌̀◌̕b; a◌֮◌ࣵ◌̀◌̕b; a◌֮◌ࣵ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC FATHA WITH DOT ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 08F6 0062;0061 302A 0316 08F6 059A 0062;0061 302A 0316 08F6 059A 0062;0061 302A 0316 08F6 059A 0062;0061 302A 0316 08F6 059A 0062; # (a◌֚◌̖◌〪◌ࣶb; a◌〪◌̖◌ࣶ◌֚b; a◌〪◌̖◌ࣶ◌֚b; a◌〪◌̖◌ࣶ◌֚b; a◌〪◌̖◌ࣶ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC KASRA WITH DOT BELOW, LATIN SMALL LETTER B
-0061 08F6 059A 0316 302A 0062;0061 302A 08F6 0316 059A 0062;0061 302A 08F6 0316 059A 0062;0061 302A 08F6 0316 059A 0062;0061 302A 08F6 0316 059A 0062; # (a◌ࣶ◌֚◌̖◌〪b; a◌〪◌ࣶ◌̖◌֚b; a◌〪◌ࣶ◌̖◌֚b; a◌〪◌ࣶ◌̖◌֚b; a◌〪◌ࣶ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC KASRA WITH DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08F6 0062;0061 1DFA 0316 08F6 059A 0062;0061 1DFA 0316 08F6 059A 0062;0061 1DFA 0316 08F6 059A 0062;0061 1DFA 0316 08F6 059A 0062; # (a◌֚◌̖◌᷺◌ࣶb; a◌᷺◌̖◌ࣶ◌֚b; a◌᷺◌̖◌ࣶ◌֚b; a◌᷺◌̖◌ࣶ◌֚b; a◌᷺◌̖◌ࣶ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC KASRA WITH DOT BELOW, LATIN SMALL LETTER B
+0061 08F6 059A 0316 1DFA 0062;0061 1DFA 08F6 0316 059A 0062;0061 1DFA 08F6 0316 059A 0062;0061 1DFA 08F6 0316 059A 0062;0061 1DFA 08F6 0316 059A 0062; # (a◌ࣶ◌֚◌̖◌᷺b; a◌᷺◌ࣶ◌̖◌֚b; a◌᷺◌ࣶ◌̖◌֚b; a◌᷺◌ࣶ◌̖◌֚b; a◌᷺◌ࣶ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC KASRA WITH DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 08F7 0062;00E0 05AE 08F7 0315 0062;0061 05AE 0300 08F7 0315 0062;00E0 05AE 08F7 0315 0062;0061 05AE 0300 08F7 0315 0062; # (a◌̕◌̀◌֮◌ࣷb; à◌֮◌ࣷ◌̕b; a◌֮◌̀◌ࣷ◌̕b; à◌֮◌ࣷ◌̕b; a◌֮◌̀◌ࣷ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC LEFT ARROWHEAD ABOVE, LATIN SMALL LETTER B
0061 08F7 0315 0300 05AE 0062;0061 05AE 08F7 0300 0315 0062;0061 05AE 08F7 0300 0315 0062;0061 05AE 08F7 0300 0315 0062;0061 05AE 08F7 0300 0315 0062; # (a◌ࣷ◌̕◌̀◌֮b; a◌֮◌ࣷ◌̀◌̕b; a◌֮◌ࣷ◌̀◌̕b; a◌֮◌ࣷ◌̀◌̕b; a◌֮◌ࣷ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC LEFT ARROWHEAD ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08F8 0062;00E0 05AE 08F8 0315 0062;0061 05AE 0300 08F8 0315 0062;00E0 05AE 08F8 0315 0062;0061 05AE 0300 08F8 0315 0062; # (a◌̕◌̀◌֮◌ࣸb; à◌֮◌ࣸ◌̕b; a◌֮◌̀◌ࣸ◌̕b; à◌֮◌ࣸ◌̕b; a◌֮◌̀◌ࣸ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC RIGHT ARROWHEAD ABOVE, LATIN SMALL LETTER B
0061 08F8 0315 0300 05AE 0062;0061 05AE 08F8 0300 0315 0062;0061 05AE 08F8 0300 0315 0062;0061 05AE 08F8 0300 0315 0062;0061 05AE 08F8 0300 0315 0062; # (a◌ࣸ◌̕◌̀◌֮b; a◌֮◌ࣸ◌̀◌̕b; a◌֮◌ࣸ◌̀◌̕b; a◌֮◌ࣸ◌̀◌̕b; a◌֮◌ࣸ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC RIGHT ARROWHEAD ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 08F9 0062;0061 302A 0316 08F9 059A 0062;0061 302A 0316 08F9 059A 0062;0061 302A 0316 08F9 059A 0062;0061 302A 0316 08F9 059A 0062; # (a◌֚◌̖◌〪◌ࣹb; a◌〪◌̖◌ࣹ◌֚b; a◌〪◌̖◌ࣹ◌֚b; a◌〪◌̖◌ࣹ◌֚b; a◌〪◌̖◌ࣹ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC LEFT ARROWHEAD BELOW, LATIN SMALL LETTER B
-0061 08F9 059A 0316 302A 0062;0061 302A 08F9 0316 059A 0062;0061 302A 08F9 0316 059A 0062;0061 302A 08F9 0316 059A 0062;0061 302A 08F9 0316 059A 0062; # (a◌ࣹ◌֚◌̖◌〪b; a◌〪◌ࣹ◌̖◌֚b; a◌〪◌ࣹ◌̖◌֚b; a◌〪◌ࣹ◌̖◌֚b; a◌〪◌ࣹ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC LEFT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 08FA 0062;0061 302A 0316 08FA 059A 0062;0061 302A 0316 08FA 059A 0062;0061 302A 0316 08FA 059A 0062;0061 302A 0316 08FA 059A 0062; # (a◌֚◌̖◌〪◌ࣺb; a◌〪◌̖◌ࣺ◌֚b; a◌〪◌̖◌ࣺ◌֚b; a◌〪◌̖◌ࣺ◌֚b; a◌〪◌̖◌ࣺ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, ARABIC RIGHT ARROWHEAD BELOW, LATIN SMALL LETTER B
-0061 08FA 059A 0316 302A 0062;0061 302A 08FA 0316 059A 0062;0061 302A 08FA 0316 059A 0062;0061 302A 08FA 0316 059A 0062;0061 302A 08FA 0316 059A 0062; # (a◌ࣺ◌֚◌̖◌〪b; a◌〪◌ࣺ◌̖◌֚b; a◌〪◌ࣺ◌̖◌֚b; a◌〪◌ࣺ◌̖◌֚b; a◌〪◌ࣺ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC RIGHT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08F9 0062;0061 1DFA 0316 08F9 059A 0062;0061 1DFA 0316 08F9 059A 0062;0061 1DFA 0316 08F9 059A 0062;0061 1DFA 0316 08F9 059A 0062; # (a◌֚◌̖◌᷺◌ࣹb; a◌᷺◌̖◌ࣹ◌֚b; a◌᷺◌̖◌ࣹ◌֚b; a◌᷺◌̖◌ࣹ◌֚b; a◌᷺◌̖◌ࣹ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC LEFT ARROWHEAD BELOW, LATIN SMALL LETTER B
+0061 08F9 059A 0316 1DFA 0062;0061 1DFA 08F9 0316 059A 0062;0061 1DFA 08F9 0316 059A 0062;0061 1DFA 08F9 0316 059A 0062;0061 1DFA 08F9 0316 059A 0062; # (a◌ࣹ◌֚◌̖◌᷺b; a◌᷺◌ࣹ◌̖◌֚b; a◌᷺◌ࣹ◌̖◌֚b; a◌᷺◌ࣹ◌̖◌֚b; a◌᷺◌ࣹ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC LEFT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 08FA 0062;0061 1DFA 0316 08FA 059A 0062;0061 1DFA 0316 08FA 059A 0062;0061 1DFA 0316 08FA 059A 0062;0061 1DFA 0316 08FA 059A 0062; # (a◌֚◌̖◌᷺◌ࣺb; a◌᷺◌̖◌ࣺ◌֚b; a◌᷺◌̖◌ࣺ◌֚b; a◌᷺◌̖◌ࣺ◌֚b; a◌᷺◌̖◌ࣺ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, ARABIC RIGHT ARROWHEAD BELOW, LATIN SMALL LETTER B
+0061 08FA 059A 0316 1DFA 0062;0061 1DFA 08FA 0316 059A 0062;0061 1DFA 08FA 0316 059A 0062;0061 1DFA 08FA 0316 059A 0062;0061 1DFA 08FA 0316 059A 0062; # (a◌ࣺ◌֚◌̖◌᷺b; a◌᷺◌ࣺ◌̖◌֚b; a◌᷺◌ࣺ◌̖◌֚b; a◌᷺◌ࣺ◌̖◌֚b; a◌᷺◌ࣺ◌̖◌֚b; ) LATIN SMALL LETTER A, ARABIC RIGHT ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 08FB 0062;00E0 05AE 08FB 0315 0062;0061 05AE 0300 08FB 0315 0062;00E0 05AE 08FB 0315 0062;0061 05AE 0300 08FB 0315 0062; # (a◌̕◌̀◌֮◌ࣻb; à◌֮◌ࣻ◌̕b; a◌֮◌̀◌ࣻ◌̕b; à◌֮◌ࣻ◌̕b; a◌֮◌̀◌ࣻ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC DOUBLE RIGHT ARROWHEAD ABOVE, LATIN SMALL LETTER B
0061 08FB 0315 0300 05AE 0062;0061 05AE 08FB 0300 0315 0062;0061 05AE 08FB 0300 0315 0062;0061 05AE 08FB 0300 0315 0062;0061 05AE 08FB 0300 0315 0062; # (a◌ࣻ◌̕◌̀◌֮b; a◌֮◌ࣻ◌̀◌̕b; a◌֮◌ࣻ◌̀◌̕b; a◌֮◌ࣻ◌̀◌̕b; a◌֮◌ࣻ◌̀◌̕b; ) LATIN SMALL LETTER A, ARABIC DOUBLE RIGHT ARROWHEAD ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 08FC 0062;00E0 05AE 08FC 0315 0062;0061 05AE 0300 08FC 0315 0062;00E0 05AE 08FC 0315 0062;0061 05AE 0300 08FC 0315 0062; # (a◌̕◌̀◌֮◌ࣼb; à◌֮◌ࣼ◌̕b; a◌֮◌̀◌ࣼ◌̕b; à◌֮◌ࣼ◌̕b; a◌֮◌̀◌ࣼ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT, LATIN SMALL LETTER B
@@ -17637,8 +17730,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 094D 05B0 094D 3099 0062;0061 3099 094D 094D 05B0 0062;0061 3099 094D 094D 05B0 0062;0061 3099 094D 094D 05B0 0062;0061 3099 094D 094D 05B0 0062; # (aâ—Œà¥â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌à¥â—Œà¥â—ŒÖ°b; a◌゙◌à¥â—Œà¥â—ŒÖ°b; a◌゙◌à¥â—Œà¥â—ŒÖ°b; a◌゙◌à¥â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, DEVANAGARI SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 0315 0300 05AE 0951 0062;00E0 05AE 0951 0315 0062;0061 05AE 0300 0951 0315 0062;00E0 05AE 0951 0315 0062;0061 05AE 0300 0951 0315 0062; # (a◌̕◌̀◌֮◌॑b; à◌֮◌॑◌̕b; a◌֮◌̀◌॑◌̕b; à◌֮◌॑◌̕b; a◌֮◌̀◌॑◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, DEVANAGARI STRESS SIGN UDATTA, LATIN SMALL LETTER B
0061 0951 0315 0300 05AE 0062;0061 05AE 0951 0300 0315 0062;0061 05AE 0951 0300 0315 0062;0061 05AE 0951 0300 0315 0062;0061 05AE 0951 0300 0315 0062; # (a◌॑◌̕◌̀◌֮b; a◌֮◌॑◌̀◌̕b; a◌֮◌॑◌̀◌̕b; a◌֮◌॑◌̀◌̕b; a◌֮◌॑◌̀◌̕b; ) LATIN SMALL LETTER A, DEVANAGARI STRESS SIGN UDATTA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0952 0062;0061 302A 0316 0952 059A 0062;0061 302A 0316 0952 059A 0062;0061 302A 0316 0952 059A 0062;0061 302A 0316 0952 059A 0062; # (a◌֚◌̖◌〪◌॒b; a◌〪◌̖◌॒◌֚b; a◌〪◌̖◌॒◌֚b; a◌〪◌̖◌॒◌֚b; a◌〪◌̖◌॒◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, DEVANAGARI STRESS SIGN ANUDATTA, LATIN SMALL LETTER B
-0061 0952 059A 0316 302A 0062;0061 302A 0952 0316 059A 0062;0061 302A 0952 0316 059A 0062;0061 302A 0952 0316 059A 0062;0061 302A 0952 0316 059A 0062; # (a◌॒◌֚◌̖◌〪b; a◌〪◌॒◌̖◌֚b; a◌〪◌॒◌̖◌֚b; a◌〪◌॒◌̖◌֚b; a◌〪◌॒◌̖◌֚b; ) LATIN SMALL LETTER A, DEVANAGARI STRESS SIGN ANUDATTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0952 0062;0061 1DFA 0316 0952 059A 0062;0061 1DFA 0316 0952 059A 0062;0061 1DFA 0316 0952 059A 0062;0061 1DFA 0316 0952 059A 0062; # (a◌֚◌̖◌᷺◌॒b; a◌᷺◌̖◌॒◌֚b; a◌᷺◌̖◌॒◌֚b; a◌᷺◌̖◌॒◌֚b; a◌᷺◌̖◌॒◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, DEVANAGARI STRESS SIGN ANUDATTA, LATIN SMALL LETTER B
+0061 0952 059A 0316 1DFA 0062;0061 1DFA 0952 0316 059A 0062;0061 1DFA 0952 0316 059A 0062;0061 1DFA 0952 0316 059A 0062;0061 1DFA 0952 0316 059A 0062; # (a◌॒◌֚◌̖◌᷺b; a◌᷺◌॒◌̖◌֚b; a◌᷺◌॒◌̖◌֚b; a◌᷺◌॒◌̖◌֚b; a◌᷺◌॒◌̖◌֚b; ) LATIN SMALL LETTER A, DEVANAGARI STRESS SIGN ANUDATTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 0953 0062;00E0 05AE 0953 0315 0062;0061 05AE 0300 0953 0315 0062;00E0 05AE 0953 0315 0062;0061 05AE 0300 0953 0315 0062; # (a◌̕◌̀◌֮◌॓b; à◌֮◌॓◌̕b; a◌֮◌̀◌॓◌̕b; à◌֮◌॓◌̕b; a◌֮◌̀◌॓◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, DEVANAGARI GRAVE ACCENT, LATIN SMALL LETTER B
0061 0953 0315 0300 05AE 0062;0061 05AE 0953 0300 0315 0062;0061 05AE 0953 0300 0315 0062;0061 05AE 0953 0300 0315 0062;0061 05AE 0953 0300 0315 0062; # (a◌॓◌̕◌̀◌֮b; a◌֮◌॓◌̀◌̕b; a◌֮◌॓◌̀◌̕b; a◌֮◌॓◌̀◌̕b; a◌֮◌॓◌̀◌̕b; ) LATIN SMALL LETTER A, DEVANAGARI GRAVE ACCENT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0954 0062;00E0 05AE 0954 0315 0062;0061 05AE 0300 0954 0315 0062;00E0 05AE 0954 0315 0062;0061 05AE 0300 0954 0315 0062; # (a◌̕◌̀◌֮◌॔b; à◌֮◌॔◌̕b; a◌֮◌̀◌॔◌̕b; à◌֮◌॔◌̕b; a◌֮◌̀◌॔◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, DEVANAGARI ACUTE ACCENT, LATIN SMALL LETTER B
@@ -17663,6 +17756,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0B4D 05B0 094D 3099 0062;0061 3099 0B4D 094D 05B0 0062;0061 3099 0B4D 094D 05B0 0062;0061 3099 0B4D 094D 05B0 0062;0061 3099 0B4D 094D 05B0 0062; # (aâ—Œà­â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌à­â—Œà¥â—ŒÖ°b; a◌゙◌à­â—Œà¥â—ŒÖ°b; a◌゙◌à­â—Œà¥â—ŒÖ°b; a◌゙◌à­â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, ORIYA SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 0BCD 0062;0061 3099 094D 0BCD 05B0 0062;0061 3099 094D 0BCD 05B0 0062;0061 3099 094D 0BCD 05B0 0062;0061 3099 094D 0BCD 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œà¯b; a◌゙◌à¥â—Œà¯â—ŒÖ°b; a◌゙◌à¥â—Œà¯â—ŒÖ°b; a◌゙◌à¥â—Œà¯â—ŒÖ°b; a◌゙◌à¥â—Œà¯â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, TAMIL SIGN VIRAMA, LATIN SMALL LETTER B
0061 0BCD 05B0 094D 3099 0062;0061 3099 0BCD 094D 05B0 0062;0061 3099 0BCD 094D 05B0 0062;0061 3099 0BCD 094D 05B0 0062;0061 3099 0BCD 094D 05B0 0062; # (aâ—Œà¯â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌à¯â—Œà¥â—ŒÖ°b; a◌゙◌à¯â—Œà¥â—ŒÖ°b; a◌゙◌à¯â—Œà¥â—ŒÖ°b; a◌゙◌à¯â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, TAMIL SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 3099 093C 16FF0 0C3C 0062;0061 16FF0 093C 0C3C 3099 0062;0061 16FF0 093C 0C3C 3099 0062;0061 16FF0 093C 0C3C 3099 0062;0061 16FF0 093C 0C3C 3099 0062; # (a◌゙◌𖿰़◌఼b; a𖿰◌़◌఼◌゙b; a𖿰◌़◌఼◌゙b; a𖿰◌़◌఼◌゙b; a𖿰◌़◌఼◌゙b; ) LATIN SMALL LETTER A, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, TELUGU SIGN NUKTA, LATIN SMALL LETTER B
+0061 0C3C 3099 093C 16FF0 0062;0061 16FF0 0C3C 093C 3099 0062;0061 16FF0 0C3C 093C 3099 0062;0061 16FF0 0C3C 093C 3099 0062;0061 16FF0 0C3C 093C 3099 0062; # (a◌఼◌゙◌𖿰़b; a𖿰◌఼◌़◌゙b; a𖿰◌఼◌़◌゙b; a𖿰◌఼◌़◌゙b; a𖿰◌఼◌़◌゙b; ) LATIN SMALL LETTER A, TELUGU SIGN NUKTA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, LATIN SMALL LETTER B
0061 05B0 094D 3099 0C4D 0062;0061 3099 094D 0C4D 05B0 0062;0061 3099 094D 0C4D 05B0 0062;0061 3099 094D 0C4D 05B0 0062;0061 3099 094D 0C4D 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œà±b; a◌゙◌à¥â—Œà±â—ŒÖ°b; a◌゙◌à¥â—Œà±â—ŒÖ°b; a◌゙◌à¥â—Œà±â—ŒÖ°b; a◌゙◌à¥â—Œà±â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, TELUGU SIGN VIRAMA, LATIN SMALL LETTER B
0061 0C4D 05B0 094D 3099 0062;0061 3099 0C4D 094D 05B0 0062;0061 3099 0C4D 094D 05B0 0062;0061 3099 0C4D 094D 05B0 0062;0061 3099 0C4D 094D 05B0 0062; # (aâ—Œà±â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌à±â—Œà¥â—ŒÖ°b; a◌゙◌à±â—Œà¥â—ŒÖ°b; a◌゙◌à±â—Œà¥â—ŒÖ°b; a◌゙◌à±â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, TELUGU SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 0C56 0C55 0711 0C55 0062;0061 0711 0C55 0C55 0C56 0062;0061 0711 0C55 0C55 0C56 0062;0061 0711 0C55 0C55 0C56 0062;0061 0711 0C55 0C55 0C56 0062; # (a◌ౖ◌ౕ◌ܑ◌ౕb; a◌ܑ◌ౕ◌ౕ◌ౖb; a◌ܑ◌ౕ◌ౕ◌ౖb; a◌ܑ◌ౕ◌ౕ◌ౖb; a◌ܑ◌ౕ◌ౕ◌ౖb; ) LATIN SMALL LETTER A, TELUGU AI LENGTH MARK, TELUGU LENGTH MARK, SYRIAC LETTER SUPERSCRIPT ALAPH, TELUGU LENGTH MARK, LATIN SMALL LETTER B
@@ -17709,16 +17804,16 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0ECA 0F71 0EC8 0EB8 0062;0061 0EB8 0ECA 0EC8 0F71 0062;0061 0EB8 0ECA 0EC8 0F71 0062;0061 0EB8 0ECA 0EC8 0F71 0062;0061 0EB8 0ECA 0EC8 0F71 0062; # (a◌໊◌ཱ◌່◌ຸb; a◌ຸ◌໊◌່◌ཱb; a◌ຸ◌໊◌່◌ཱb; a◌ຸ◌໊◌່◌ཱb; a◌ຸ◌໊◌່◌ཱb; ) LATIN SMALL LETTER A, LAO TONE MAI TI, TIBETAN VOWEL SIGN AA, LAO TONE MAI EK, LAO VOWEL SIGN U, LATIN SMALL LETTER B
0061 0F71 0EC8 0EB8 0ECB 0062;0061 0EB8 0EC8 0ECB 0F71 0062;0061 0EB8 0EC8 0ECB 0F71 0062;0061 0EB8 0EC8 0ECB 0F71 0062;0061 0EB8 0EC8 0ECB 0F71 0062; # (a◌ཱ◌່◌ຸ◌໋b; a◌ຸ◌່◌໋◌ཱb; a◌ຸ◌່◌໋◌ཱb; a◌ຸ◌່◌໋◌ཱb; a◌ຸ◌່◌໋◌ཱb; ) LATIN SMALL LETTER A, TIBETAN VOWEL SIGN AA, LAO TONE MAI EK, LAO VOWEL SIGN U, LAO TONE MAI CATAWA, LATIN SMALL LETTER B
0061 0ECB 0F71 0EC8 0EB8 0062;0061 0EB8 0ECB 0EC8 0F71 0062;0061 0EB8 0ECB 0EC8 0F71 0062;0061 0EB8 0ECB 0EC8 0F71 0062;0061 0EB8 0ECB 0EC8 0F71 0062; # (a◌໋◌ཱ◌່◌ຸb; a◌ຸ◌໋◌່◌ཱb; a◌ຸ◌໋◌່◌ཱb; a◌ຸ◌໋◌່◌ཱb; a◌ຸ◌໋◌່◌ཱb; ) LATIN SMALL LETTER A, LAO TONE MAI CATAWA, TIBETAN VOWEL SIGN AA, LAO TONE MAI EK, LAO VOWEL SIGN U, LATIN SMALL LETTER B
-0061 059A 0316 302A 0F18 0062;0061 302A 0316 0F18 059A 0062;0061 302A 0316 0F18 059A 0062;0061 302A 0316 0F18 059A 0062;0061 302A 0316 0F18 059A 0062; # (a◌֚◌̖◌〪◌༘b; a◌〪◌̖◌༘◌֚b; a◌〪◌̖◌༘◌֚b; a◌〪◌̖◌༘◌֚b; a◌〪◌̖◌༘◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TIBETAN ASTROLOGICAL SIGN -KHYUD PA, LATIN SMALL LETTER B
-0061 0F18 059A 0316 302A 0062;0061 302A 0F18 0316 059A 0062;0061 302A 0F18 0316 059A 0062;0061 302A 0F18 0316 059A 0062;0061 302A 0F18 0316 059A 0062; # (a◌༘◌֚◌̖◌〪b; a◌〪◌༘◌̖◌֚b; a◌〪◌༘◌̖◌֚b; a◌〪◌༘◌̖◌֚b; a◌〪◌༘◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN ASTROLOGICAL SIGN -KHYUD PA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0F19 0062;0061 302A 0316 0F19 059A 0062;0061 302A 0316 0F19 059A 0062;0061 302A 0316 0F19 059A 0062;0061 302A 0316 0F19 059A 0062; # (a◌֚◌̖◌〪◌༙b; a◌〪◌̖◌༙◌֚b; a◌〪◌̖◌༙◌֚b; a◌〪◌̖◌༙◌֚b; a◌〪◌̖◌༙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS, LATIN SMALL LETTER B
-0061 0F19 059A 0316 302A 0062;0061 302A 0F19 0316 059A 0062;0061 302A 0F19 0316 059A 0062;0061 302A 0F19 0316 059A 0062;0061 302A 0F19 0316 059A 0062; # (a◌༙◌֚◌̖◌〪b; a◌〪◌༙◌̖◌֚b; a◌〪◌༙◌̖◌֚b; a◌〪◌༙◌̖◌֚b; a◌〪◌༙◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0F35 0062;0061 302A 0316 0F35 059A 0062;0061 302A 0316 0F35 059A 0062;0061 302A 0316 0F35 059A 0062;0061 302A 0316 0F35 059A 0062; # (a◌֚◌̖◌〪◌༵b; a◌〪◌̖◌༵◌֚b; a◌〪◌̖◌༵◌֚b; a◌〪◌̖◌༵◌֚b; a◌〪◌̖◌༵◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TIBETAN MARK NGAS BZUNG NYI ZLA, LATIN SMALL LETTER B
-0061 0F35 059A 0316 302A 0062;0061 302A 0F35 0316 059A 0062;0061 302A 0F35 0316 059A 0062;0061 302A 0F35 0316 059A 0062;0061 302A 0F35 0316 059A 0062; # (a◌༵◌֚◌̖◌〪b; a◌〪◌༵◌̖◌֚b; a◌〪◌༵◌̖◌֚b; a◌〪◌༵◌̖◌֚b; a◌〪◌༵◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN MARK NGAS BZUNG NYI ZLA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 0F37 0062;0061 302A 0316 0F37 059A 0062;0061 302A 0316 0F37 059A 0062;0061 302A 0316 0F37 059A 0062;0061 302A 0316 0F37 059A 0062; # (a◌֚◌̖◌〪◌༷b; a◌〪◌̖◌༷◌֚b; a◌〪◌̖◌༷◌֚b; a◌〪◌̖◌༷◌֚b; a◌〪◌̖◌༷◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TIBETAN MARK NGAS BZUNG SGOR RTAGS, LATIN SMALL LETTER B
-0061 0F37 059A 0316 302A 0062;0061 302A 0F37 0316 059A 0062;0061 302A 0F37 0316 059A 0062;0061 302A 0F37 0316 059A 0062;0061 302A 0F37 0316 059A 0062; # (a◌༷◌֚◌̖◌〪b; a◌〪◌༷◌̖◌֚b; a◌〪◌༷◌̖◌֚b; a◌〪◌༷◌̖◌֚b; a◌〪◌༷◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN MARK NGAS BZUNG SGOR RTAGS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 0F39 0062;0061 1DCE 031B 0F39 302A 0062;0061 1DCE 031B 0F39 302A 0062;0061 1DCE 031B 0F39 302A 0062;0061 1DCE 031B 0F39 302A 0062; # (a◌〪◌̛◌᷎◌༹b; a◌᷎◌̛◌༹◌〪b; a◌᷎◌̛◌༹◌〪b; a◌᷎◌̛◌༹◌〪b; a◌᷎◌̛◌༹◌〪b; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, TIBETAN MARK TSA -PHRU, LATIN SMALL LETTER B
-0061 0F39 302A 031B 1DCE 0062;0061 1DCE 0F39 031B 302A 0062;0061 1DCE 0F39 031B 302A 0062;0061 1DCE 0F39 031B 302A 0062;0061 1DCE 0F39 031B 302A 0062; # (a◌༹◌〪◌̛◌᷎b; a◌᷎◌༹◌̛◌〪b; a◌᷎◌༹◌̛◌〪b; a◌᷎◌༹◌̛◌〪b; a◌᷎◌༹◌̛◌〪b; ) LATIN SMALL LETTER A, TIBETAN MARK TSA -PHRU, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0F18 0062;0061 1DFA 0316 0F18 059A 0062;0061 1DFA 0316 0F18 059A 0062;0061 1DFA 0316 0F18 059A 0062;0061 1DFA 0316 0F18 059A 0062; # (a◌֚◌̖◌᷺◌༘b; a◌᷺◌̖◌༘◌֚b; a◌᷺◌̖◌༘◌֚b; a◌᷺◌̖◌༘◌֚b; a◌᷺◌̖◌༘◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TIBETAN ASTROLOGICAL SIGN -KHYUD PA, LATIN SMALL LETTER B
+0061 0F18 059A 0316 1DFA 0062;0061 1DFA 0F18 0316 059A 0062;0061 1DFA 0F18 0316 059A 0062;0061 1DFA 0F18 0316 059A 0062;0061 1DFA 0F18 0316 059A 0062; # (a◌༘◌֚◌̖◌᷺b; a◌᷺◌༘◌̖◌֚b; a◌᷺◌༘◌̖◌֚b; a◌᷺◌༘◌̖◌֚b; a◌᷺◌༘◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN ASTROLOGICAL SIGN -KHYUD PA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0F19 0062;0061 1DFA 0316 0F19 059A 0062;0061 1DFA 0316 0F19 059A 0062;0061 1DFA 0316 0F19 059A 0062;0061 1DFA 0316 0F19 059A 0062; # (a◌֚◌̖◌᷺◌༙b; a◌᷺◌̖◌༙◌֚b; a◌᷺◌̖◌༙◌֚b; a◌᷺◌̖◌༙◌֚b; a◌᷺◌̖◌༙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS, LATIN SMALL LETTER B
+0061 0F19 059A 0316 1DFA 0062;0061 1DFA 0F19 0316 059A 0062;0061 1DFA 0F19 0316 059A 0062;0061 1DFA 0F19 0316 059A 0062;0061 1DFA 0F19 0316 059A 0062; # (a◌༙◌֚◌̖◌᷺b; a◌᷺◌༙◌̖◌֚b; a◌᷺◌༙◌̖◌֚b; a◌᷺◌༙◌̖◌֚b; a◌᷺◌༙◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0F35 0062;0061 1DFA 0316 0F35 059A 0062;0061 1DFA 0316 0F35 059A 0062;0061 1DFA 0316 0F35 059A 0062;0061 1DFA 0316 0F35 059A 0062; # (a◌֚◌̖◌᷺◌༵b; a◌᷺◌̖◌༵◌֚b; a◌᷺◌̖◌༵◌֚b; a◌᷺◌̖◌༵◌֚b; a◌᷺◌̖◌༵◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TIBETAN MARK NGAS BZUNG NYI ZLA, LATIN SMALL LETTER B
+0061 0F35 059A 0316 1DFA 0062;0061 1DFA 0F35 0316 059A 0062;0061 1DFA 0F35 0316 059A 0062;0061 1DFA 0F35 0316 059A 0062;0061 1DFA 0F35 0316 059A 0062; # (a◌༵◌֚◌̖◌᷺b; a◌᷺◌༵◌̖◌֚b; a◌᷺◌༵◌̖◌֚b; a◌᷺◌༵◌̖◌֚b; a◌᷺◌༵◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN MARK NGAS BZUNG NYI ZLA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0F37 0062;0061 1DFA 0316 0F37 059A 0062;0061 1DFA 0316 0F37 059A 0062;0061 1DFA 0316 0F37 059A 0062;0061 1DFA 0316 0F37 059A 0062; # (a◌֚◌̖◌᷺◌༷b; a◌᷺◌̖◌༷◌֚b; a◌᷺◌̖◌༷◌֚b; a◌᷺◌̖◌༷◌֚b; a◌᷺◌̖◌༷◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TIBETAN MARK NGAS BZUNG SGOR RTAGS, LATIN SMALL LETTER B
+0061 0F37 059A 0316 1DFA 0062;0061 1DFA 0F37 0316 059A 0062;0061 1DFA 0F37 0316 059A 0062;0061 1DFA 0F37 0316 059A 0062;0061 1DFA 0F37 0316 059A 0062; # (a◌༷◌֚◌̖◌᷺b; a◌᷺◌༷◌̖◌֚b; a◌᷺◌༷◌̖◌֚b; a◌᷺◌༷◌̖◌֚b; a◌᷺◌༷◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN MARK NGAS BZUNG SGOR RTAGS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 0F39 0062;0061 1DCE 031B 0F39 1DFA 0062;0061 1DCE 031B 0F39 1DFA 0062;0061 1DCE 031B 0F39 1DFA 0062;0061 1DCE 031B 0F39 1DFA 0062; # (a◌᷺◌̛◌᷎◌༹b; a◌᷎◌̛◌༹◌᷺b; a◌᷎◌̛◌༹◌᷺b; a◌᷎◌̛◌༹◌᷺b; a◌᷎◌̛◌༹◌᷺b; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, TIBETAN MARK TSA -PHRU, LATIN SMALL LETTER B
+0061 0F39 1DFA 031B 1DCE 0062;0061 1DCE 0F39 031B 1DFA 0062;0061 1DCE 0F39 031B 1DFA 0062;0061 1DCE 0F39 031B 1DFA 0062;0061 1DCE 0F39 031B 1DFA 0062; # (a◌༹◌᷺◌̛◌᷎b; a◌᷎◌༹◌̛◌᷺b; a◌᷎◌༹◌̛◌᷺b; a◌᷎◌༹◌̛◌᷺b; a◌᷎◌༹◌̛◌᷺b; ) LATIN SMALL LETTER A, TIBETAN MARK TSA -PHRU, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
0061 0F72 0F71 0EC8 0F71 0062;0061 0EC8 0F71 0F71 0F72 0062;0061 0EC8 0F71 0F71 0F72 0062;0061 0EC8 0F71 0F71 0F72 0062;0061 0EC8 0F71 0F71 0F72 0062; # (a◌ི◌ཱ◌່◌ཱb; a◌່◌ཱ◌ཱ◌ིb; a◌່◌ཱ◌ཱ◌ིb; a◌່◌ཱ◌ཱ◌ིb; a◌່◌ཱ◌ཱ◌ིb; ) LATIN SMALL LETTER A, TIBETAN VOWEL SIGN I, TIBETAN VOWEL SIGN AA, LAO TONE MAI EK, TIBETAN VOWEL SIGN AA, LATIN SMALL LETTER B
0061 0F71 0F72 0F71 0EC8 0062;0061 0EC8 0F71 0F71 0F72 0062;0061 0EC8 0F71 0F71 0F72 0062;0061 0EC8 0F71 0F71 0F72 0062;0061 0EC8 0F71 0F71 0F72 0062; # (a◌ཱ◌ི◌ཱ◌່b; a◌່◌ཱ◌ཱ◌ིb; a◌່◌ཱ◌ཱ◌ིb; a◌່◌ཱ◌ཱ◌ིb; a◌່◌ཱ◌ཱ◌ིb; ) LATIN SMALL LETTER A, TIBETAN VOWEL SIGN AA, TIBETAN VOWEL SIGN I, TIBETAN VOWEL SIGN AA, LAO TONE MAI EK, LATIN SMALL LETTER B
0061 0F74 0F72 0F71 0F72 0062;0061 0F71 0F72 0F72 0F74 0062;0061 0F71 0F72 0F72 0F74 0062;0061 0F71 0F72 0F72 0F74 0062;0061 0F71 0F72 0F72 0F74 0062; # (a◌ུ◌ི◌ཱ◌ིb; a◌ཱ◌ི◌ི◌ུb; a◌ཱ◌ི◌ི◌ུb; a◌ཱ◌ི◌ི◌ུb; a◌ཱ◌ི◌ི◌ུb; ) LATIN SMALL LETTER A, TIBETAN VOWEL SIGN U, TIBETAN VOWEL SIGN I, TIBETAN VOWEL SIGN AA, TIBETAN VOWEL SIGN I, LATIN SMALL LETTER B
@@ -17745,16 +17840,16 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 0F86 0315 0300 05AE 0062;0061 05AE 0F86 0300 0315 0062;0061 05AE 0F86 0300 0315 0062;0061 05AE 0F86 0300 0315 0062;0061 05AE 0F86 0300 0315 0062; # (a◌྆◌̕◌̀◌֮b; a◌֮◌྆◌̀◌̕b; a◌֮◌྆◌̀◌̕b; a◌֮◌྆◌̀◌̕b; a◌֮◌྆◌̀◌̕b; ) LATIN SMALL LETTER A, TIBETAN SIGN LCI RTAGS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 0F87 0062;00E0 05AE 0F87 0315 0062;0061 05AE 0300 0F87 0315 0062;00E0 05AE 0F87 0315 0062;0061 05AE 0300 0F87 0315 0062; # (a◌̕◌̀◌֮◌྇b; à◌֮◌྇◌̕b; a◌֮◌̀◌྇◌̕b; à◌֮◌྇◌̕b; a◌֮◌̀◌྇◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TIBETAN SIGN YANG RTAGS, LATIN SMALL LETTER B
0061 0F87 0315 0300 05AE 0062;0061 05AE 0F87 0300 0315 0062;0061 05AE 0F87 0300 0315 0062;0061 05AE 0F87 0300 0315 0062;0061 05AE 0F87 0300 0315 0062; # (a◌྇◌̕◌̀◌֮b; a◌֮◌྇◌̀◌̕b; a◌֮◌྇◌̀◌̕b; a◌֮◌྇◌̀◌̕b; a◌֮◌྇◌̀◌̕b; ) LATIN SMALL LETTER A, TIBETAN SIGN YANG RTAGS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 0FC6 0062;0061 302A 0316 0FC6 059A 0062;0061 302A 0316 0FC6 059A 0062;0061 302A 0316 0FC6 059A 0062;0061 302A 0316 0FC6 059A 0062; # (a◌֚◌̖◌〪◌࿆b; a◌〪◌̖◌࿆◌֚b; a◌〪◌̖◌࿆◌֚b; a◌〪◌̖◌࿆◌֚b; a◌〪◌̖◌࿆◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TIBETAN SYMBOL PADMA GDAN, LATIN SMALL LETTER B
-0061 0FC6 059A 0316 302A 0062;0061 302A 0FC6 0316 059A 0062;0061 302A 0FC6 0316 059A 0062;0061 302A 0FC6 0316 059A 0062;0061 302A 0FC6 0316 059A 0062; # (a◌࿆◌֚◌̖◌〪b; a◌〪◌࿆◌̖◌֚b; a◌〪◌࿆◌̖◌֚b; a◌〪◌࿆◌̖◌֚b; a◌〪◌࿆◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN SYMBOL PADMA GDAN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 0FC6 0062;0061 1DFA 0316 0FC6 059A 0062;0061 1DFA 0316 0FC6 059A 0062;0061 1DFA 0316 0FC6 059A 0062;0061 1DFA 0316 0FC6 059A 0062; # (a◌֚◌̖◌᷺◌࿆b; a◌᷺◌̖◌࿆◌֚b; a◌᷺◌̖◌࿆◌֚b; a◌᷺◌̖◌࿆◌֚b; a◌᷺◌̖◌࿆◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TIBETAN SYMBOL PADMA GDAN, LATIN SMALL LETTER B
+0061 0FC6 059A 0316 1DFA 0062;0061 1DFA 0FC6 0316 059A 0062;0061 1DFA 0FC6 0316 059A 0062;0061 1DFA 0FC6 0316 059A 0062;0061 1DFA 0FC6 0316 059A 0062; # (a◌࿆◌֚◌̖◌᷺b; a◌᷺◌࿆◌̖◌֚b; a◌᷺◌࿆◌̖◌֚b; a◌᷺◌࿆◌̖◌֚b; a◌᷺◌࿆◌̖◌֚b; ) LATIN SMALL LETTER A, TIBETAN SYMBOL PADMA GDAN, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 3099 093C 16FF0 1037 0062;0061 16FF0 093C 1037 3099 0062;0061 16FF0 093C 1037 3099 0062;0061 16FF0 093C 1037 3099 0062;0061 16FF0 093C 1037 3099 0062; # (a◌゙◌𖿰़◌့b; a𖿰◌़◌့◌゙b; a𖿰◌़◌့◌゙b; a𖿰◌़◌့◌゙b; a𖿰◌़◌့◌゙b; ) LATIN SMALL LETTER A, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, MYANMAR SIGN DOT BELOW, LATIN SMALL LETTER B
0061 1037 3099 093C 16FF0 0062;0061 16FF0 1037 093C 3099 0062;0061 16FF0 1037 093C 3099 0062;0061 16FF0 1037 093C 3099 0062;0061 16FF0 1037 093C 3099 0062; # (a◌့◌゙◌𖿰़b; a𖿰◌့◌़◌゙b; a𖿰◌့◌़◌゙b; a𖿰◌့◌़◌゙b; a𖿰◌့◌़◌゙b; ) LATIN SMALL LETTER A, MYANMAR SIGN DOT BELOW, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, LATIN SMALL LETTER B
0061 05B0 094D 3099 1039 0062;0061 3099 094D 1039 05B0 0062;0061 3099 094D 1039 05B0 0062;0061 3099 094D 1039 05B0 0062;0061 3099 094D 1039 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œá€¹b; a◌゙◌à¥â—Œá€¹â—ŒÖ°b; a◌゙◌à¥â—Œá€¹â—ŒÖ°b; a◌゙◌à¥â—Œá€¹â—ŒÖ°b; a◌゙◌à¥â—Œá€¹â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MYANMAR SIGN VIRAMA, LATIN SMALL LETTER B
0061 1039 05B0 094D 3099 0062;0061 3099 1039 094D 05B0 0062;0061 3099 1039 094D 05B0 0062;0061 3099 1039 094D 05B0 0062;0061 3099 1039 094D 05B0 0062; # (a◌္◌ְ◌à¥â—Œã‚™b; a◌゙◌္◌à¥â—ŒÖ°b; a◌゙◌္◌à¥â—ŒÖ°b; a◌゙◌္◌à¥â—ŒÖ°b; a◌゙◌္◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, MYANMAR SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 103A 0062;0061 3099 094D 103A 05B0 0062;0061 3099 094D 103A 05B0 0062;0061 3099 094D 103A 05B0 0062;0061 3099 094D 103A 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œá€ºb; a◌゙◌à¥â—Œá€ºâ—ŒÖ°b; a◌゙◌à¥â—Œá€ºâ—ŒÖ°b; a◌゙◌à¥â—Œá€ºâ—ŒÖ°b; a◌゙◌à¥â—Œá€ºâ—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, MYANMAR SIGN ASAT, LATIN SMALL LETTER B
0061 103A 05B0 094D 3099 0062;0061 3099 103A 094D 05B0 0062;0061 3099 103A 094D 05B0 0062;0061 3099 103A 094D 05B0 0062;0061 3099 103A 094D 05B0 0062; # (a◌်◌ְ◌à¥â—Œã‚™b; a◌゙◌်◌à¥â—ŒÖ°b; a◌゙◌်◌à¥â—ŒÖ°b; a◌゙◌်◌à¥â—ŒÖ°b; a◌゙◌်◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, MYANMAR SIGN ASAT, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 108D 0062;0061 302A 0316 108D 059A 0062;0061 302A 0316 108D 059A 0062;0061 302A 0316 108D 059A 0062;0061 302A 0316 108D 059A 0062; # (a◌֚◌̖◌〪◌á‚b; a◌〪◌̖◌á‚◌֚b; a◌〪◌̖◌á‚◌֚b; a◌〪◌̖◌á‚◌֚b; a◌〪◌̖◌á‚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE, LATIN SMALL LETTER B
-0061 108D 059A 0316 302A 0062;0061 302A 108D 0316 059A 0062;0061 302A 108D 0316 059A 0062;0061 302A 108D 0316 059A 0062;0061 302A 108D 0316 059A 0062; # (aâ—Œá‚◌֚◌̖◌〪b; a◌〪◌á‚◌̖◌֚b; a◌〪◌á‚◌̖◌֚b; a◌〪◌á‚◌̖◌֚b; a◌〪◌á‚◌̖◌֚b; ) LATIN SMALL LETTER A, MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 108D 0062;0061 1DFA 0316 108D 059A 0062;0061 1DFA 0316 108D 059A 0062;0061 1DFA 0316 108D 059A 0062;0061 1DFA 0316 108D 059A 0062; # (a◌֚◌̖◌᷺◌á‚b; a◌᷺◌̖◌á‚◌֚b; a◌᷺◌̖◌á‚◌֚b; a◌᷺◌̖◌á‚◌֚b; a◌᷺◌̖◌á‚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE, LATIN SMALL LETTER B
+0061 108D 059A 0316 1DFA 0062;0061 1DFA 108D 0316 059A 0062;0061 1DFA 108D 0316 059A 0062;0061 1DFA 108D 0316 059A 0062;0061 1DFA 108D 0316 059A 0062; # (aâ—Œá‚◌֚◌̖◌᷺b; a◌᷺◌á‚◌̖◌֚b; a◌᷺◌á‚◌̖◌֚b; a◌᷺◌á‚◌̖◌֚b; a◌᷺◌á‚◌̖◌֚b; ) LATIN SMALL LETTER A, MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 135D 0062;00E0 05AE 135D 0315 0062;0061 05AE 0300 135D 0315 0062;00E0 05AE 135D 0315 0062;0061 05AE 0300 135D 0315 0062; # (a◌̕◌̀◌֮◌áb; à◌֮◌á◌̕b; a◌֮◌̀◌á◌̕b; à◌֮◌á◌̕b; a◌֮◌̀◌á◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK, LATIN SMALL LETTER B
0061 135D 0315 0300 05AE 0062;0061 05AE 135D 0300 0315 0062;0061 05AE 135D 0300 0315 0062;0061 05AE 135D 0300 0315 0062;0061 05AE 135D 0300 0315 0062; # (aâ—Œá◌̕◌̀◌֮b; a◌֮◌á◌̀◌̕b; a◌֮◌á◌̀◌̕b; a◌֮◌á◌̀◌̕b; a◌֮◌á◌̀◌̕b; ) LATIN SMALL LETTER A, ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 135E 0062;00E0 05AE 135E 0315 0062;0061 05AE 0300 135E 0315 0062;00E0 05AE 135E 0315 0062;0061 05AE 0300 135E 0315 0062; # (a◌̕◌̀◌֮◌ážb; à◌֮◌ážâ—ŒÌ•b; a◌֮◌̀◌ážâ—ŒÌ•b; à◌֮◌ážâ—ŒÌ•b; a◌֮◌̀◌ážâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ETHIOPIC COMBINING VOWEL LENGTH MARK, LATIN SMALL LETTER B
@@ -17763,8 +17858,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 135F 0315 0300 05AE 0062;0061 05AE 135F 0300 0315 0062;0061 05AE 135F 0300 0315 0062;0061 05AE 135F 0300 0315 0062;0061 05AE 135F 0300 0315 0062; # (aâ—ŒáŸâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌áŸâ—ŒÌ€â—ŒÌ•b; a◌֮◌áŸâ—ŒÌ€â—ŒÌ•b; a◌֮◌áŸâ—ŒÌ€â—ŒÌ•b; a◌֮◌áŸâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, ETHIOPIC COMBINING GEMINATION MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 05B0 094D 3099 1714 0062;0061 3099 094D 1714 05B0 0062;0061 3099 094D 1714 05B0 0062;0061 3099 094D 1714 05B0 0062;0061 3099 094D 1714 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œáœ”b; a◌゙◌à¥â—Œáœ”◌ְb; a◌゙◌à¥â—Œáœ”◌ְb; a◌゙◌à¥â—Œáœ”◌ְb; a◌゙◌à¥â—Œáœ”◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, TAGALOG SIGN VIRAMA, LATIN SMALL LETTER B
0061 1714 05B0 094D 3099 0062;0061 3099 1714 094D 05B0 0062;0061 3099 1714 094D 05B0 0062;0061 3099 1714 094D 05B0 0062;0061 3099 1714 094D 05B0 0062; # (a◌᜔◌ְ◌à¥â—Œã‚™b; a◌゙◌᜔◌à¥â—ŒÖ°b; a◌゙◌᜔◌à¥â—ŒÖ°b; a◌゙◌᜔◌à¥â—ŒÖ°b; a◌゙◌᜔◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, TAGALOG SIGN VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
-0061 05B0 094D 3099 1734 0062;0061 3099 094D 1734 05B0 0062;0061 3099 094D 1734 05B0 0062;0061 3099 094D 1734 05B0 0062;0061 3099 094D 1734 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œáœ´b; a◌゙◌à¥â—Œáœ´â—ŒÖ°b; a◌゙◌à¥â—Œáœ´â—ŒÖ°b; a◌゙◌à¥â—Œáœ´â—ŒÖ°b; a◌゙◌à¥â—Œáœ´â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, HANUNOO SIGN PAMUDPOD, LATIN SMALL LETTER B
-0061 1734 05B0 094D 3099 0062;0061 3099 1734 094D 05B0 0062;0061 3099 1734 094D 05B0 0062;0061 3099 1734 094D 05B0 0062;0061 3099 1734 094D 05B0 0062; # (a◌᜴◌ְ◌à¥â—Œã‚™b; a◌゙◌᜴◌à¥â—ŒÖ°b; a◌゙◌᜴◌à¥â—ŒÖ°b; a◌゙◌᜴◌à¥â—ŒÖ°b; a◌゙◌᜴◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, HANUNOO SIGN PAMUDPOD, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 1715 0062;0061 3099 094D 1715 05B0 0062;0061 3099 094D 1715 05B0 0062;0061 3099 094D 1715 05B0 0062;0061 3099 094D 1715 05B0 0062; # (a◌ְ◌à¥â—Œã‚™áœ•b; a◌゙◌à¥áœ•â—ŒÖ°b; a◌゙◌à¥áœ•â—ŒÖ°b; a◌゙◌à¥áœ•â—ŒÖ°b; a◌゙◌à¥áœ•â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, TAGALOG SIGN PAMUDPOD, LATIN SMALL LETTER B
+0061 1715 05B0 094D 3099 0062;0061 3099 1715 094D 05B0 0062;0061 3099 1715 094D 05B0 0062;0061 3099 1715 094D 05B0 0062;0061 3099 1715 094D 05B0 0062; # (a᜕◌ְ◌à¥â—Œã‚™b; a◌゙᜕◌à¥â—ŒÖ°b; a◌゙᜕◌à¥â—ŒÖ°b; a◌゙᜕◌à¥â—ŒÖ°b; a◌゙᜕◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, TAGALOG SIGN PAMUDPOD, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 1734 0062;0061 3099 094D 1734 05B0 0062;0061 3099 094D 1734 05B0 0062;0061 3099 094D 1734 05B0 0062;0061 3099 094D 1734 05B0 0062; # (a◌ְ◌à¥â—Œã‚™áœ´b; a◌゙◌à¥áœ´â—ŒÖ°b; a◌゙◌à¥áœ´â—ŒÖ°b; a◌゙◌à¥áœ´â—ŒÖ°b; a◌゙◌à¥áœ´â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, HANUNOO SIGN PAMUDPOD, LATIN SMALL LETTER B
+0061 1734 05B0 094D 3099 0062;0061 3099 1734 094D 05B0 0062;0061 3099 1734 094D 05B0 0062;0061 3099 1734 094D 05B0 0062;0061 3099 1734 094D 05B0 0062; # (a᜴◌ְ◌à¥â—Œã‚™b; a◌゙᜴◌à¥â—ŒÖ°b; a◌゙᜴◌à¥â—ŒÖ°b; a◌゙᜴◌à¥â—ŒÖ°b; a◌゙᜴◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, HANUNOO SIGN PAMUDPOD, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 17D2 0062;0061 3099 094D 17D2 05B0 0062;0061 3099 094D 17D2 05B0 0062;0061 3099 094D 17D2 05B0 0062;0061 3099 094D 17D2 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—ŒáŸ’b; a◌゙◌à¥â—ŒáŸ’◌ְb; a◌゙◌à¥â—ŒáŸ’◌ְb; a◌゙◌à¥â—ŒáŸ’◌ְb; a◌゙◌à¥â—ŒáŸ’◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KHMER SIGN COENG, LATIN SMALL LETTER B
0061 17D2 05B0 094D 3099 0062;0061 3099 17D2 094D 05B0 0062;0061 3099 17D2 094D 05B0 0062;0061 3099 17D2 094D 05B0 0062;0061 3099 17D2 094D 05B0 0062; # (a◌្◌ְ◌à¥â—Œã‚™b; a◌゙◌្◌à¥â—ŒÖ°b; a◌゙◌្◌à¥â—ŒÖ°b; a◌゙◌្◌à¥â—ŒÖ°b; a◌゙◌្◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, KHMER SIGN COENG, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 0315 0300 05AE 17DD 0062;00E0 05AE 17DD 0315 0062;0061 05AE 0300 17DD 0315 0062;00E0 05AE 17DD 0315 0062;0061 05AE 0300 17DD 0315 0062; # (a◌̕◌̀◌֮◌áŸb; à◌֮◌áŸâ—ŒÌ•b; a◌֮◌̀◌áŸâ—ŒÌ•b; à◌֮◌áŸâ—ŒÌ•b; a◌֮◌̀◌áŸâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, KHMER SIGN ATTHACAN, LATIN SMALL LETTER B
@@ -17775,12 +17872,12 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1939 302E 059A 0316 0062;0061 0316 1939 059A 302E 0062;0061 0316 1939 059A 302E 0062;0061 0316 1939 059A 302E 0062;0061 0316 1939 059A 302E 0062; # (a◌᤹〮◌֚◌̖b; a◌̖◌᤹◌֚〮b; a◌̖◌᤹◌֚〮b; a◌̖◌᤹◌֚〮b; a◌̖◌᤹◌֚〮b; ) LATIN SMALL LETTER A, LIMBU SIGN MUKPHRENG, HANGUL SINGLE DOT TONE MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, LATIN SMALL LETTER B
0061 0315 0300 05AE 193A 0062;00E0 05AE 193A 0315 0062;0061 05AE 0300 193A 0315 0062;00E0 05AE 193A 0315 0062;0061 05AE 0300 193A 0315 0062; # (a◌̕◌̀◌֮◌᤺b; à◌֮◌᤺◌̕b; a◌֮◌̀◌᤺◌̕b; à◌֮◌᤺◌̕b; a◌֮◌̀◌᤺◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LIMBU SIGN KEMPHRENG, LATIN SMALL LETTER B
0061 193A 0315 0300 05AE 0062;0061 05AE 193A 0300 0315 0062;0061 05AE 193A 0300 0315 0062;0061 05AE 193A 0300 0315 0062;0061 05AE 193A 0300 0315 0062; # (a◌᤺◌̕◌̀◌֮b; a◌֮◌᤺◌̀◌̕b; a◌֮◌᤺◌̀◌̕b; a◌֮◌᤺◌̀◌̕b; a◌֮◌᤺◌̀◌̕b; ) LATIN SMALL LETTER A, LIMBU SIGN KEMPHRENG, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 193B 0062;0061 302A 0316 193B 059A 0062;0061 302A 0316 193B 059A 0062;0061 302A 0316 193B 059A 0062;0061 302A 0316 193B 059A 0062; # (a◌֚◌̖◌〪◌᤻b; a◌〪◌̖◌᤻◌֚b; a◌〪◌̖◌᤻◌֚b; a◌〪◌̖◌᤻◌֚b; a◌〪◌̖◌᤻◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LIMBU SIGN SA-I, LATIN SMALL LETTER B
-0061 193B 059A 0316 302A 0062;0061 302A 193B 0316 059A 0062;0061 302A 193B 0316 059A 0062;0061 302A 193B 0316 059A 0062;0061 302A 193B 0316 059A 0062; # (a◌᤻◌֚◌̖◌〪b; a◌〪◌᤻◌̖◌֚b; a◌〪◌᤻◌̖◌֚b; a◌〪◌᤻◌̖◌֚b; a◌〪◌᤻◌̖◌֚b; ) LATIN SMALL LETTER A, LIMBU SIGN SA-I, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 193B 0062;0061 1DFA 0316 193B 059A 0062;0061 1DFA 0316 193B 059A 0062;0061 1DFA 0316 193B 059A 0062;0061 1DFA 0316 193B 059A 0062; # (a◌֚◌̖◌᷺◌᤻b; a◌᷺◌̖◌᤻◌֚b; a◌᷺◌̖◌᤻◌֚b; a◌᷺◌̖◌᤻◌֚b; a◌᷺◌̖◌᤻◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LIMBU SIGN SA-I, LATIN SMALL LETTER B
+0061 193B 059A 0316 1DFA 0062;0061 1DFA 193B 0316 059A 0062;0061 1DFA 193B 0316 059A 0062;0061 1DFA 193B 0316 059A 0062;0061 1DFA 193B 0316 059A 0062; # (a◌᤻◌֚◌̖◌᷺b; a◌᷺◌᤻◌̖◌֚b; a◌᷺◌᤻◌̖◌֚b; a◌᷺◌᤻◌̖◌֚b; a◌᷺◌᤻◌̖◌֚b; ) LATIN SMALL LETTER A, LIMBU SIGN SA-I, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1A17 0062;00E0 05AE 1A17 0315 0062;0061 05AE 0300 1A17 0315 0062;00E0 05AE 1A17 0315 0062;0061 05AE 0300 1A17 0315 0062; # (a◌̕◌̀◌֮◌ᨗb; à◌֮◌ᨗ◌̕b; a◌֮◌̀◌ᨗ◌̕b; à◌֮◌ᨗ◌̕b; a◌֮◌̀◌ᨗ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, BUGINESE VOWEL SIGN I, LATIN SMALL LETTER B
0061 1A17 0315 0300 05AE 0062;0061 05AE 1A17 0300 0315 0062;0061 05AE 1A17 0300 0315 0062;0061 05AE 1A17 0300 0315 0062;0061 05AE 1A17 0300 0315 0062; # (a◌ᨗ◌̕◌̀◌֮b; a◌֮◌ᨗ◌̀◌̕b; a◌֮◌ᨗ◌̀◌̕b; a◌֮◌ᨗ◌̀◌̕b; a◌֮◌ᨗ◌̀◌̕b; ) LATIN SMALL LETTER A, BUGINESE VOWEL SIGN I, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1A18 0062;0061 302A 0316 1A18 059A 0062;0061 302A 0316 1A18 059A 0062;0061 302A 0316 1A18 059A 0062;0061 302A 0316 1A18 059A 0062; # (a◌֚◌̖◌〪◌ᨘb; a◌〪◌̖◌ᨘ◌֚b; a◌〪◌̖◌ᨘ◌֚b; a◌〪◌̖◌ᨘ◌֚b; a◌〪◌̖◌ᨘ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, BUGINESE VOWEL SIGN U, LATIN SMALL LETTER B
-0061 1A18 059A 0316 302A 0062;0061 302A 1A18 0316 059A 0062;0061 302A 1A18 0316 059A 0062;0061 302A 1A18 0316 059A 0062;0061 302A 1A18 0316 059A 0062; # (a◌ᨘ◌֚◌̖◌〪b; a◌〪◌ᨘ◌̖◌֚b; a◌〪◌ᨘ◌̖◌֚b; a◌〪◌ᨘ◌̖◌֚b; a◌〪◌ᨘ◌̖◌֚b; ) LATIN SMALL LETTER A, BUGINESE VOWEL SIGN U, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1A18 0062;0061 1DFA 0316 1A18 059A 0062;0061 1DFA 0316 1A18 059A 0062;0061 1DFA 0316 1A18 059A 0062;0061 1DFA 0316 1A18 059A 0062; # (a◌֚◌̖◌᷺◌ᨘb; a◌᷺◌̖◌ᨘ◌֚b; a◌᷺◌̖◌ᨘ◌֚b; a◌᷺◌̖◌ᨘ◌֚b; a◌᷺◌̖◌ᨘ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, BUGINESE VOWEL SIGN U, LATIN SMALL LETTER B
+0061 1A18 059A 0316 1DFA 0062;0061 1DFA 1A18 0316 059A 0062;0061 1DFA 1A18 0316 059A 0062;0061 1DFA 1A18 0316 059A 0062;0061 1DFA 1A18 0316 059A 0062; # (a◌ᨘ◌֚◌̖◌᷺b; a◌᷺◌ᨘ◌̖◌֚b; a◌᷺◌ᨘ◌̖◌֚b; a◌᷺◌ᨘ◌̖◌֚b; a◌᷺◌ᨘ◌̖◌֚b; ) LATIN SMALL LETTER A, BUGINESE VOWEL SIGN U, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 05B0 094D 3099 1A60 0062;0061 3099 094D 1A60 05B0 0062;0061 3099 094D 1A60 05B0 0062;0061 3099 094D 1A60 05B0 0062;0061 3099 094D 1A60 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œá© b; a◌゙◌à¥â—Œá© â—ŒÖ°b; a◌゙◌à¥â—Œá© â—ŒÖ°b; a◌゙◌à¥â—Œá© â—ŒÖ°b; a◌゙◌à¥â—Œá© â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, TAI THAM SIGN SAKOT, LATIN SMALL LETTER B
0061 1A60 05B0 094D 3099 0062;0061 3099 1A60 094D 05B0 0062;0061 3099 1A60 094D 05B0 0062;0061 3099 1A60 094D 05B0 0062;0061 3099 1A60 094D 05B0 0062; # (a◌᩠◌ְ◌à¥â—Œã‚™b; a◌゙◌᩠◌à¥â—ŒÖ°b; a◌゙◌᩠◌à¥â—ŒÖ°b; a◌゙◌᩠◌à¥â—ŒÖ°b; a◌゙◌᩠◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, TAI THAM SIGN SAKOT, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 0315 0300 05AE 1A75 0062;00E0 05AE 1A75 0315 0062;0061 05AE 0300 1A75 0315 0062;00E0 05AE 1A75 0315 0062;0061 05AE 0300 1A75 0315 0062; # (a◌̕◌̀◌֮◌᩵b; à◌֮◌᩵◌̕b; a◌֮◌̀◌᩵◌̕b; à◌֮◌᩵◌̕b; a◌֮◌̀◌᩵◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TAI THAM SIGN TONE-1, LATIN SMALL LETTER B
@@ -17799,8 +17896,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1A7B 0315 0300 05AE 0062;0061 05AE 1A7B 0300 0315 0062;0061 05AE 1A7B 0300 0315 0062;0061 05AE 1A7B 0300 0315 0062;0061 05AE 1A7B 0300 0315 0062; # (a◌᩻◌̕◌̀◌֮b; a◌֮◌᩻◌̀◌̕b; a◌֮◌᩻◌̀◌̕b; a◌֮◌᩻◌̀◌̕b; a◌֮◌᩻◌̀◌̕b; ) LATIN SMALL LETTER A, TAI THAM SIGN MAI SAM, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1A7C 0062;00E0 05AE 1A7C 0315 0062;0061 05AE 0300 1A7C 0315 0062;00E0 05AE 1A7C 0315 0062;0061 05AE 0300 1A7C 0315 0062; # (a◌̕◌̀◌֮◌᩼b; à◌֮◌᩼◌̕b; a◌֮◌̀◌᩼◌̕b; à◌֮◌᩼◌̕b; a◌֮◌̀◌᩼◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TAI THAM SIGN KHUEN-LUE KARAN, LATIN SMALL LETTER B
0061 1A7C 0315 0300 05AE 0062;0061 05AE 1A7C 0300 0315 0062;0061 05AE 1A7C 0300 0315 0062;0061 05AE 1A7C 0300 0315 0062;0061 05AE 1A7C 0300 0315 0062; # (a◌᩼◌̕◌̀◌֮b; a◌֮◌᩼◌̀◌̕b; a◌֮◌᩼◌̀◌̕b; a◌֮◌᩼◌̀◌̕b; a◌֮◌᩼◌̀◌̕b; ) LATIN SMALL LETTER A, TAI THAM SIGN KHUEN-LUE KARAN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1A7F 0062;0061 302A 0316 1A7F 059A 0062;0061 302A 0316 1A7F 059A 0062;0061 302A 0316 1A7F 059A 0062;0061 302A 0316 1A7F 059A 0062; # (a◌֚◌̖◌〪◌᩿b; a◌〪◌̖◌᩿◌֚b; a◌〪◌̖◌᩿◌֚b; a◌〪◌̖◌᩿◌֚b; a◌〪◌̖◌᩿◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TAI THAM COMBINING CRYPTOGRAMMIC DOT, LATIN SMALL LETTER B
-0061 1A7F 059A 0316 302A 0062;0061 302A 1A7F 0316 059A 0062;0061 302A 1A7F 0316 059A 0062;0061 302A 1A7F 0316 059A 0062;0061 302A 1A7F 0316 059A 0062; # (a◌᩿◌֚◌̖◌〪b; a◌〪◌᩿◌̖◌֚b; a◌〪◌᩿◌̖◌֚b; a◌〪◌᩿◌̖◌֚b; a◌〪◌᩿◌̖◌֚b; ) LATIN SMALL LETTER A, TAI THAM COMBINING CRYPTOGRAMMIC DOT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1A7F 0062;0061 1DFA 0316 1A7F 059A 0062;0061 1DFA 0316 1A7F 059A 0062;0061 1DFA 0316 1A7F 059A 0062;0061 1DFA 0316 1A7F 059A 0062; # (a◌֚◌̖◌᷺◌᩿b; a◌᷺◌̖◌᩿◌֚b; a◌᷺◌̖◌᩿◌֚b; a◌᷺◌̖◌᩿◌֚b; a◌᷺◌̖◌᩿◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TAI THAM COMBINING CRYPTOGRAMMIC DOT, LATIN SMALL LETTER B
+0061 1A7F 059A 0316 1DFA 0062;0061 1DFA 1A7F 0316 059A 0062;0061 1DFA 1A7F 0316 059A 0062;0061 1DFA 1A7F 0316 059A 0062;0061 1DFA 1A7F 0316 059A 0062; # (a◌᩿◌֚◌̖◌᷺b; a◌᷺◌᩿◌̖◌֚b; a◌᷺◌᩿◌̖◌֚b; a◌᷺◌᩿◌̖◌֚b; a◌᷺◌᩿◌̖◌֚b; ) LATIN SMALL LETTER A, TAI THAM COMBINING CRYPTOGRAMMIC DOT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1AB0 0062;00E0 05AE 1AB0 0315 0062;0061 05AE 0300 1AB0 0315 0062;00E0 05AE 1AB0 0315 0062;0061 05AE 0300 1AB0 0315 0062; # (a◌̕◌̀◌֮◌᪰b; à◌֮◌᪰◌̕b; a◌֮◌̀◌᪰◌̕b; à◌֮◌᪰◌̕b; a◌֮◌̀◌᪰◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DOUBLED CIRCUMFLEX ACCENT, LATIN SMALL LETTER B
0061 1AB0 0315 0300 05AE 0062;0061 05AE 1AB0 0300 0315 0062;0061 05AE 1AB0 0300 0315 0062;0061 05AE 1AB0 0300 0315 0062;0061 05AE 1AB0 0300 0315 0062; # (a◌᪰◌̕◌̀◌֮b; a◌֮◌᪰◌̀◌̕b; a◌֮◌᪰◌̀◌̕b; a◌֮◌᪰◌̀◌̕b; a◌֮◌᪰◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DOUBLED CIRCUMFLEX ACCENT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1AB1 0062;00E0 05AE 1AB1 0315 0062;0061 05AE 0300 1AB1 0315 0062;00E0 05AE 1AB1 0315 0062;0061 05AE 0300 1AB1 0315 0062; # (a◌̕◌̀◌֮◌᪱b; à◌֮◌᪱◌̕b; a◌֮◌̀◌᪱◌̕b; à◌֮◌᪱◌̕b; a◌֮◌̀◌᪱◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DIAERESIS-RING, LATIN SMALL LETTER B
@@ -17811,36 +17908,64 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1AB3 0315 0300 05AE 0062;0061 05AE 1AB3 0300 0315 0062;0061 05AE 1AB3 0300 0315 0062;0061 05AE 1AB3 0300 0315 0062;0061 05AE 1AB3 0300 0315 0062; # (a◌᪳◌̕◌̀◌֮b; a◌֮◌᪳◌̀◌̕b; a◌֮◌᪳◌̀◌̕b; a◌֮◌᪳◌̀◌̕b; a◌֮◌᪳◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DOWNWARDS ARROW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1AB4 0062;00E0 05AE 1AB4 0315 0062;0061 05AE 0300 1AB4 0315 0062;00E0 05AE 1AB4 0315 0062;0061 05AE 0300 1AB4 0315 0062; # (a◌̕◌̀◌֮◌᪴b; à◌֮◌᪴◌̕b; a◌֮◌̀◌᪴◌̕b; à◌֮◌᪴◌̕b; a◌֮◌̀◌᪴◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING TRIPLE DOT, LATIN SMALL LETTER B
0061 1AB4 0315 0300 05AE 0062;0061 05AE 1AB4 0300 0315 0062;0061 05AE 1AB4 0300 0315 0062;0061 05AE 1AB4 0300 0315 0062;0061 05AE 1AB4 0300 0315 0062; # (a◌᪴◌̕◌̀◌֮b; a◌֮◌᪴◌̀◌̕b; a◌֮◌᪴◌̀◌̕b; a◌֮◌᪴◌̀◌̕b; a◌֮◌᪴◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING TRIPLE DOT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1AB5 0062;0061 302A 0316 1AB5 059A 0062;0061 302A 0316 1AB5 059A 0062;0061 302A 0316 1AB5 059A 0062;0061 302A 0316 1AB5 059A 0062; # (a◌֚◌̖◌〪◌᪵b; a◌〪◌̖◌᪵◌֚b; a◌〪◌̖◌᪵◌֚b; a◌〪◌̖◌᪵◌֚b; a◌〪◌̖◌᪵◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING X-X BELOW, LATIN SMALL LETTER B
-0061 1AB5 059A 0316 302A 0062;0061 302A 1AB5 0316 059A 0062;0061 302A 1AB5 0316 059A 0062;0061 302A 1AB5 0316 059A 0062;0061 302A 1AB5 0316 059A 0062; # (a◌᪵◌֚◌̖◌〪b; a◌〪◌᪵◌̖◌֚b; a◌〪◌᪵◌̖◌֚b; a◌〪◌᪵◌̖◌֚b; a◌〪◌᪵◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING X-X BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1AB6 0062;0061 302A 0316 1AB6 059A 0062;0061 302A 0316 1AB6 059A 0062;0061 302A 0316 1AB6 059A 0062;0061 302A 0316 1AB6 059A 0062; # (a◌֚◌̖◌〪◌᪶b; a◌〪◌̖◌᪶◌֚b; a◌〪◌̖◌᪶◌֚b; a◌〪◌̖◌᪶◌֚b; a◌〪◌̖◌᪶◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING WIGGLY LINE BELOW, LATIN SMALL LETTER B
-0061 1AB6 059A 0316 302A 0062;0061 302A 1AB6 0316 059A 0062;0061 302A 1AB6 0316 059A 0062;0061 302A 1AB6 0316 059A 0062;0061 302A 1AB6 0316 059A 0062; # (a◌᪶◌֚◌̖◌〪b; a◌〪◌᪶◌̖◌֚b; a◌〪◌᪶◌̖◌֚b; a◌〪◌᪶◌̖◌֚b; a◌〪◌᪶◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING WIGGLY LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1AB7 0062;0061 302A 0316 1AB7 059A 0062;0061 302A 0316 1AB7 059A 0062;0061 302A 0316 1AB7 059A 0062;0061 302A 0316 1AB7 059A 0062; # (a◌֚◌̖◌〪◌᪷b; a◌〪◌̖◌᪷◌֚b; a◌〪◌̖◌᪷◌֚b; a◌〪◌̖◌᪷◌֚b; a◌〪◌̖◌᪷◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING OPEN MARK BELOW, LATIN SMALL LETTER B
-0061 1AB7 059A 0316 302A 0062;0061 302A 1AB7 0316 059A 0062;0061 302A 1AB7 0316 059A 0062;0061 302A 1AB7 0316 059A 0062;0061 302A 1AB7 0316 059A 0062; # (a◌᪷◌֚◌̖◌〪b; a◌〪◌᪷◌̖◌֚b; a◌〪◌᪷◌̖◌֚b; a◌〪◌᪷◌̖◌֚b; a◌〪◌᪷◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING OPEN MARK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1AB8 0062;0061 302A 0316 1AB8 059A 0062;0061 302A 0316 1AB8 059A 0062;0061 302A 0316 1AB8 059A 0062;0061 302A 0316 1AB8 059A 0062; # (a◌֚◌̖◌〪◌᪸b; a◌〪◌̖◌᪸◌֚b; a◌〪◌̖◌᪸◌֚b; a◌〪◌̖◌᪸◌֚b; a◌〪◌̖◌᪸◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING DOUBLE OPEN MARK BELOW, LATIN SMALL LETTER B
-0061 1AB8 059A 0316 302A 0062;0061 302A 1AB8 0316 059A 0062;0061 302A 1AB8 0316 059A 0062;0061 302A 1AB8 0316 059A 0062;0061 302A 1AB8 0316 059A 0062; # (a◌᪸◌֚◌̖◌〪b; a◌〪◌᪸◌̖◌֚b; a◌〪◌᪸◌̖◌֚b; a◌〪◌᪸◌̖◌֚b; a◌〪◌᪸◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE OPEN MARK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1AB9 0062;0061 302A 0316 1AB9 059A 0062;0061 302A 0316 1AB9 059A 0062;0061 302A 0316 1AB9 059A 0062;0061 302A 0316 1AB9 059A 0062; # (a◌֚◌̖◌〪◌᪹b; a◌〪◌̖◌᪹◌֚b; a◌〪◌̖◌᪹◌֚b; a◌〪◌̖◌᪹◌֚b; a◌〪◌̖◌᪹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LIGHT CENTRALIZATION STROKE BELOW, LATIN SMALL LETTER B
-0061 1AB9 059A 0316 302A 0062;0061 302A 1AB9 0316 059A 0062;0061 302A 1AB9 0316 059A 0062;0061 302A 1AB9 0316 059A 0062;0061 302A 1AB9 0316 059A 0062; # (a◌᪹◌֚◌̖◌〪b; a◌〪◌᪹◌̖◌֚b; a◌〪◌᪹◌̖◌֚b; a◌〪◌᪹◌̖◌֚b; a◌〪◌᪹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LIGHT CENTRALIZATION STROKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1ABA 0062;0061 302A 0316 1ABA 059A 0062;0061 302A 0316 1ABA 059A 0062;0061 302A 0316 1ABA 059A 0062;0061 302A 0316 1ABA 059A 0062; # (a◌֚◌̖◌〪◌᪺b; a◌〪◌̖◌᪺◌֚b; a◌〪◌̖◌᪺◌֚b; a◌〪◌̖◌᪺◌֚b; a◌〪◌̖◌᪺◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING STRONG CENTRALIZATION STROKE BELOW, LATIN SMALL LETTER B
-0061 1ABA 059A 0316 302A 0062;0061 302A 1ABA 0316 059A 0062;0061 302A 1ABA 0316 059A 0062;0061 302A 1ABA 0316 059A 0062;0061 302A 1ABA 0316 059A 0062; # (a◌᪺◌֚◌̖◌〪b; a◌〪◌᪺◌̖◌֚b; a◌〪◌᪺◌̖◌֚b; a◌〪◌᪺◌̖◌֚b; a◌〪◌᪺◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING STRONG CENTRALIZATION STROKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AB5 0062;0061 1DFA 0316 1AB5 059A 0062;0061 1DFA 0316 1AB5 059A 0062;0061 1DFA 0316 1AB5 059A 0062;0061 1DFA 0316 1AB5 059A 0062; # (a◌֚◌̖◌᷺◌᪵b; a◌᷺◌̖◌᪵◌֚b; a◌᷺◌̖◌᪵◌֚b; a◌᷺◌̖◌᪵◌֚b; a◌᷺◌̖◌᪵◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING X-X BELOW, LATIN SMALL LETTER B
+0061 1AB5 059A 0316 1DFA 0062;0061 1DFA 1AB5 0316 059A 0062;0061 1DFA 1AB5 0316 059A 0062;0061 1DFA 1AB5 0316 059A 0062;0061 1DFA 1AB5 0316 059A 0062; # (a◌᪵◌֚◌̖◌᷺b; a◌᷺◌᪵◌̖◌֚b; a◌᷺◌᪵◌̖◌֚b; a◌᷺◌᪵◌̖◌֚b; a◌᷺◌᪵◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING X-X BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AB6 0062;0061 1DFA 0316 1AB6 059A 0062;0061 1DFA 0316 1AB6 059A 0062;0061 1DFA 0316 1AB6 059A 0062;0061 1DFA 0316 1AB6 059A 0062; # (a◌֚◌̖◌᷺◌᪶b; a◌᷺◌̖◌᪶◌֚b; a◌᷺◌̖◌᪶◌֚b; a◌᷺◌̖◌᪶◌֚b; a◌᷺◌̖◌᪶◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING WIGGLY LINE BELOW, LATIN SMALL LETTER B
+0061 1AB6 059A 0316 1DFA 0062;0061 1DFA 1AB6 0316 059A 0062;0061 1DFA 1AB6 0316 059A 0062;0061 1DFA 1AB6 0316 059A 0062;0061 1DFA 1AB6 0316 059A 0062; # (a◌᪶◌֚◌̖◌᷺b; a◌᷺◌᪶◌̖◌֚b; a◌᷺◌᪶◌̖◌֚b; a◌᷺◌᪶◌̖◌֚b; a◌᷺◌᪶◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING WIGGLY LINE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AB7 0062;0061 1DFA 0316 1AB7 059A 0062;0061 1DFA 0316 1AB7 059A 0062;0061 1DFA 0316 1AB7 059A 0062;0061 1DFA 0316 1AB7 059A 0062; # (a◌֚◌̖◌᷺◌᪷b; a◌᷺◌̖◌᪷◌֚b; a◌᷺◌̖◌᪷◌֚b; a◌᷺◌̖◌᪷◌֚b; a◌᷺◌̖◌᪷◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING OPEN MARK BELOW, LATIN SMALL LETTER B
+0061 1AB7 059A 0316 1DFA 0062;0061 1DFA 1AB7 0316 059A 0062;0061 1DFA 1AB7 0316 059A 0062;0061 1DFA 1AB7 0316 059A 0062;0061 1DFA 1AB7 0316 059A 0062; # (a◌᪷◌֚◌̖◌᷺b; a◌᷺◌᪷◌̖◌֚b; a◌᷺◌᪷◌̖◌֚b; a◌᷺◌᪷◌̖◌֚b; a◌᷺◌᪷◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING OPEN MARK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AB8 0062;0061 1DFA 0316 1AB8 059A 0062;0061 1DFA 0316 1AB8 059A 0062;0061 1DFA 0316 1AB8 059A 0062;0061 1DFA 0316 1AB8 059A 0062; # (a◌֚◌̖◌᷺◌᪸b; a◌᷺◌̖◌᪸◌֚b; a◌᷺◌̖◌᪸◌֚b; a◌᷺◌̖◌᪸◌֚b; a◌᷺◌̖◌᪸◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOUBLE OPEN MARK BELOW, LATIN SMALL LETTER B
+0061 1AB8 059A 0316 1DFA 0062;0061 1DFA 1AB8 0316 059A 0062;0061 1DFA 1AB8 0316 059A 0062;0061 1DFA 1AB8 0316 059A 0062;0061 1DFA 1AB8 0316 059A 0062; # (a◌᪸◌֚◌̖◌᷺b; a◌᷺◌᪸◌̖◌֚b; a◌᷺◌᪸◌̖◌֚b; a◌᷺◌᪸◌̖◌֚b; a◌᷺◌᪸◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE OPEN MARK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AB9 0062;0061 1DFA 0316 1AB9 059A 0062;0061 1DFA 0316 1AB9 059A 0062;0061 1DFA 0316 1AB9 059A 0062;0061 1DFA 0316 1AB9 059A 0062; # (a◌֚◌̖◌᷺◌᪹b; a◌᷺◌̖◌᪹◌֚b; a◌᷺◌̖◌᪹◌֚b; a◌᷺◌̖◌᪹◌֚b; a◌᷺◌̖◌᪹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LIGHT CENTRALIZATION STROKE BELOW, LATIN SMALL LETTER B
+0061 1AB9 059A 0316 1DFA 0062;0061 1DFA 1AB9 0316 059A 0062;0061 1DFA 1AB9 0316 059A 0062;0061 1DFA 1AB9 0316 059A 0062;0061 1DFA 1AB9 0316 059A 0062; # (a◌᪹◌֚◌̖◌᷺b; a◌᷺◌᪹◌̖◌֚b; a◌᷺◌᪹◌̖◌֚b; a◌᷺◌᪹◌̖◌֚b; a◌᷺◌᪹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LIGHT CENTRALIZATION STROKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1ABA 0062;0061 1DFA 0316 1ABA 059A 0062;0061 1DFA 0316 1ABA 059A 0062;0061 1DFA 0316 1ABA 059A 0062;0061 1DFA 0316 1ABA 059A 0062; # (a◌֚◌̖◌᷺◌᪺b; a◌᷺◌̖◌᪺◌֚b; a◌᷺◌̖◌᪺◌֚b; a◌᷺◌̖◌᪺◌֚b; a◌᷺◌̖◌᪺◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING STRONG CENTRALIZATION STROKE BELOW, LATIN SMALL LETTER B
+0061 1ABA 059A 0316 1DFA 0062;0061 1DFA 1ABA 0316 059A 0062;0061 1DFA 1ABA 0316 059A 0062;0061 1DFA 1ABA 0316 059A 0062;0061 1DFA 1ABA 0316 059A 0062; # (a◌᪺◌֚◌̖◌᷺b; a◌᷺◌᪺◌̖◌֚b; a◌᷺◌᪺◌̖◌֚b; a◌᷺◌᪺◌̖◌֚b; a◌᷺◌᪺◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING STRONG CENTRALIZATION STROKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1ABB 0062;00E0 05AE 1ABB 0315 0062;0061 05AE 0300 1ABB 0315 0062;00E0 05AE 1ABB 0315 0062;0061 05AE 0300 1ABB 0315 0062; # (a◌̕◌̀◌֮◌᪻b; à◌֮◌᪻◌̕b; a◌֮◌̀◌᪻◌̕b; à◌֮◌᪻◌̕b; a◌֮◌̀◌᪻◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING PARENTHESES ABOVE, LATIN SMALL LETTER B
0061 1ABB 0315 0300 05AE 0062;0061 05AE 1ABB 0300 0315 0062;0061 05AE 1ABB 0300 0315 0062;0061 05AE 1ABB 0300 0315 0062;0061 05AE 1ABB 0300 0315 0062; # (a◌᪻◌̕◌̀◌֮b; a◌֮◌᪻◌̀◌̕b; a◌֮◌᪻◌̀◌̕b; a◌֮◌᪻◌̀◌̕b; a◌֮◌᪻◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING PARENTHESES ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1ABC 0062;00E0 05AE 1ABC 0315 0062;0061 05AE 0300 1ABC 0315 0062;00E0 05AE 1ABC 0315 0062;0061 05AE 0300 1ABC 0315 0062; # (a◌̕◌̀◌֮◌᪼b; à◌֮◌᪼◌̕b; a◌֮◌̀◌᪼◌̕b; à◌֮◌᪼◌̕b; a◌֮◌̀◌᪼◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DOUBLE PARENTHESES ABOVE, LATIN SMALL LETTER B
0061 1ABC 0315 0300 05AE 0062;0061 05AE 1ABC 0300 0315 0062;0061 05AE 1ABC 0300 0315 0062;0061 05AE 1ABC 0300 0315 0062;0061 05AE 1ABC 0300 0315 0062; # (a◌᪼◌̕◌̀◌֮b; a◌֮◌᪼◌̀◌̕b; a◌֮◌᪼◌̀◌̕b; a◌֮◌᪼◌̀◌̕b; a◌֮◌᪼◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DOUBLE PARENTHESES ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1ABD 0062;0061 302A 0316 1ABD 059A 0062;0061 302A 0316 1ABD 059A 0062;0061 302A 0316 1ABD 059A 0062;0061 302A 0316 1ABD 059A 0062; # (a◌֚◌̖◌〪◌᪽b; a◌〪◌̖◌᪽◌֚b; a◌〪◌̖◌᪽◌֚b; a◌〪◌̖◌᪽◌֚b; a◌〪◌̖◌᪽◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING PARENTHESES BELOW, LATIN SMALL LETTER B
-0061 1ABD 059A 0316 302A 0062;0061 302A 1ABD 0316 059A 0062;0061 302A 1ABD 0316 059A 0062;0061 302A 1ABD 0316 059A 0062;0061 302A 1ABD 0316 059A 0062; # (a◌᪽◌֚◌̖◌〪b; a◌〪◌᪽◌̖◌֚b; a◌〪◌᪽◌̖◌֚b; a◌〪◌᪽◌̖◌֚b; a◌〪◌᪽◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING PARENTHESES BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1ABF 0062;0061 302A 0316 1ABF 059A 0062;0061 302A 0316 1ABF 059A 0062;0061 302A 0316 1ABF 059A 0062;0061 302A 0316 1ABF 059A 0062; # (a◌֚◌̖◌〪◌ᪿb; a◌〪◌̖◌ᪿ◌֚b; a◌〪◌̖◌ᪿ◌֚b; a◌〪◌̖◌ᪿ◌֚b; a◌〪◌̖◌ᪿ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LATIN SMALL LETTER W BELOW, LATIN SMALL LETTER B
-0061 1ABF 059A 0316 302A 0062;0061 302A 1ABF 0316 059A 0062;0061 302A 1ABF 0316 059A 0062;0061 302A 1ABF 0316 059A 0062;0061 302A 1ABF 0316 059A 0062; # (a◌ᪿ◌֚◌̖◌〪b; a◌〪◌ᪿ◌̖◌֚b; a◌〪◌ᪿ◌̖◌֚b; a◌〪◌ᪿ◌̖◌֚b; a◌〪◌ᪿ◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER W BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1AC0 0062;0061 302A 0316 1AC0 059A 0062;0061 302A 0316 1AC0 059A 0062;0061 302A 0316 1AC0 059A 0062;0061 302A 0316 1AC0 059A 0062; # (a◌֚◌̖◌〪◌ᫀb; a◌〪◌̖◌ᫀ◌֚b; a◌〪◌̖◌ᫀ◌֚b; a◌〪◌̖◌ᫀ◌֚b; a◌〪◌̖◌ᫀ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LATIN SMALL LETTER TURNED W BELOW, LATIN SMALL LETTER B
-0061 1AC0 059A 0316 302A 0062;0061 302A 1AC0 0316 059A 0062;0061 302A 1AC0 0316 059A 0062;0061 302A 1AC0 0316 059A 0062;0061 302A 1AC0 0316 059A 0062; # (a◌ᫀ◌֚◌̖◌〪b; a◌〪◌ᫀ◌̖◌֚b; a◌〪◌ᫀ◌̖◌֚b; a◌〪◌ᫀ◌̖◌֚b; a◌〪◌ᫀ◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER TURNED W BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1ABD 0062;0061 1DFA 0316 1ABD 059A 0062;0061 1DFA 0316 1ABD 059A 0062;0061 1DFA 0316 1ABD 059A 0062;0061 1DFA 0316 1ABD 059A 0062; # (a◌֚◌̖◌᷺◌᪽b; a◌᷺◌̖◌᪽◌֚b; a◌᷺◌̖◌᪽◌֚b; a◌᷺◌̖◌᪽◌֚b; a◌᷺◌̖◌᪽◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING PARENTHESES BELOW, LATIN SMALL LETTER B
+0061 1ABD 059A 0316 1DFA 0062;0061 1DFA 1ABD 0316 059A 0062;0061 1DFA 1ABD 0316 059A 0062;0061 1DFA 1ABD 0316 059A 0062;0061 1DFA 1ABD 0316 059A 0062; # (a◌᪽◌֚◌̖◌᷺b; a◌᷺◌᪽◌̖◌֚b; a◌᷺◌᪽◌̖◌֚b; a◌᷺◌᪽◌̖◌֚b; a◌᷺◌᪽◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING PARENTHESES BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1ABF 0062;0061 1DFA 0316 1ABF 059A 0062;0061 1DFA 0316 1ABF 059A 0062;0061 1DFA 0316 1ABF 059A 0062;0061 1DFA 0316 1ABF 059A 0062; # (a◌֚◌̖◌᷺◌ᪿb; a◌᷺◌̖◌ᪿ◌֚b; a◌᷺◌̖◌ᪿ◌֚b; a◌᷺◌̖◌ᪿ◌֚b; a◌᷺◌̖◌ᪿ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LATIN SMALL LETTER W BELOW, LATIN SMALL LETTER B
+0061 1ABF 059A 0316 1DFA 0062;0061 1DFA 1ABF 0316 059A 0062;0061 1DFA 1ABF 0316 059A 0062;0061 1DFA 1ABF 0316 059A 0062;0061 1DFA 1ABF 0316 059A 0062; # (a◌ᪿ◌֚◌̖◌᷺b; a◌᷺◌ᪿ◌̖◌֚b; a◌᷺◌ᪿ◌̖◌֚b; a◌᷺◌ᪿ◌̖◌֚b; a◌᷺◌ᪿ◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER W BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AC0 0062;0061 1DFA 0316 1AC0 059A 0062;0061 1DFA 0316 1AC0 059A 0062;0061 1DFA 0316 1AC0 059A 0062;0061 1DFA 0316 1AC0 059A 0062; # (a◌֚◌̖◌᷺◌ᫀb; a◌᷺◌̖◌ᫀ◌֚b; a◌᷺◌̖◌ᫀ◌֚b; a◌᷺◌̖◌ᫀ◌֚b; a◌᷺◌̖◌ᫀ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LATIN SMALL LETTER TURNED W BELOW, LATIN SMALL LETTER B
+0061 1AC0 059A 0316 1DFA 0062;0061 1DFA 1AC0 0316 059A 0062;0061 1DFA 1AC0 0316 059A 0062;0061 1DFA 1AC0 0316 059A 0062;0061 1DFA 1AC0 0316 059A 0062; # (a◌ᫀ◌֚◌̖◌᷺b; a◌᷺◌ᫀ◌̖◌֚b; a◌᷺◌ᫀ◌̖◌֚b; a◌᷺◌ᫀ◌̖◌֚b; a◌᷺◌ᫀ◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER TURNED W BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC1 0062;00E0 05AE 1AC1 0315 0062;0061 05AE 0300 1AC1 0315 0062;00E0 05AE 1AC1 0315 0062;0061 05AE 0300 1AC1 0315 0062; # (a◌̕◌̀◌֮◌á«b; à◌֮◌á«â—ŒÌ•b; a◌֮◌̀◌á«â—ŒÌ•b; à◌֮◌á«â—ŒÌ•b; a◌֮◌̀◌á«â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LEFT PARENTHESIS ABOVE LEFT, LATIN SMALL LETTER B
+0061 1AC1 0315 0300 05AE 0062;0061 05AE 1AC1 0300 0315 0062;0061 05AE 1AC1 0300 0315 0062;0061 05AE 1AC1 0300 0315 0062;0061 05AE 1AC1 0300 0315 0062; # (aâ—Œá«â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING LEFT PARENTHESIS ABOVE LEFT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC2 0062;00E0 05AE 1AC2 0315 0062;0061 05AE 0300 1AC2 0315 0062;00E0 05AE 1AC2 0315 0062;0061 05AE 0300 1AC2 0315 0062; # (a◌̕◌̀◌֮◌᫂b; à◌֮◌᫂◌̕b; a◌֮◌̀◌᫂◌̕b; à◌֮◌᫂◌̕b; a◌֮◌̀◌᫂◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING RIGHT PARENTHESIS ABOVE RIGHT, LATIN SMALL LETTER B
+0061 1AC2 0315 0300 05AE 0062;0061 05AE 1AC2 0300 0315 0062;0061 05AE 1AC2 0300 0315 0062;0061 05AE 1AC2 0300 0315 0062;0061 05AE 1AC2 0300 0315 0062; # (a◌᫂◌̕◌̀◌֮b; a◌֮◌᫂◌̀◌̕b; a◌֮◌᫂◌̀◌̕b; a◌֮◌᫂◌̀◌̕b; a◌֮◌᫂◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING RIGHT PARENTHESIS ABOVE RIGHT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AC3 0062;0061 1DFA 0316 1AC3 059A 0062;0061 1DFA 0316 1AC3 059A 0062;0061 1DFA 0316 1AC3 059A 0062;0061 1DFA 0316 1AC3 059A 0062; # (a◌֚◌̖◌᷺◌᫃b; a◌᷺◌̖◌᫃◌֚b; a◌᷺◌̖◌᫃◌֚b; a◌᷺◌̖◌᫃◌֚b; a◌᷺◌̖◌᫃◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT PARENTHESIS BELOW LEFT, LATIN SMALL LETTER B
+0061 1AC3 059A 0316 1DFA 0062;0061 1DFA 1AC3 0316 059A 0062;0061 1DFA 1AC3 0316 059A 0062;0061 1DFA 1AC3 0316 059A 0062;0061 1DFA 1AC3 0316 059A 0062; # (a◌᫃◌֚◌̖◌᷺b; a◌᷺◌᫃◌̖◌֚b; a◌᷺◌᫃◌̖◌֚b; a◌᷺◌᫃◌̖◌֚b; a◌᷺◌᫃◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT PARENTHESIS BELOW LEFT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1AC4 0062;0061 1DFA 0316 1AC4 059A 0062;0061 1DFA 0316 1AC4 059A 0062;0061 1DFA 0316 1AC4 059A 0062;0061 1DFA 0316 1AC4 059A 0062; # (a◌֚◌̖◌᷺◌᫄b; a◌᷺◌̖◌᫄◌֚b; a◌᷺◌̖◌᫄◌֚b; a◌᷺◌̖◌᫄◌֚b; a◌᷺◌̖◌᫄◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT PARENTHESIS BELOW RIGHT, LATIN SMALL LETTER B
+0061 1AC4 059A 0316 1DFA 0062;0061 1DFA 1AC4 0316 059A 0062;0061 1DFA 1AC4 0316 059A 0062;0061 1DFA 1AC4 0316 059A 0062;0061 1DFA 1AC4 0316 059A 0062; # (a◌᫄◌֚◌̖◌᷺b; a◌᷺◌᫄◌̖◌֚b; a◌᷺◌᫄◌̖◌֚b; a◌᷺◌᫄◌̖◌֚b; a◌᷺◌᫄◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT PARENTHESIS BELOW RIGHT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC5 0062;00E0 05AE 1AC5 0315 0062;0061 05AE 0300 1AC5 0315 0062;00E0 05AE 1AC5 0315 0062;0061 05AE 0300 1AC5 0315 0062; # (a◌̕◌̀◌֮◌᫅b; à◌֮◌᫅◌̕b; a◌֮◌̀◌᫅◌̕b; à◌֮◌᫅◌̕b; a◌֮◌̀◌᫅◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING SQUARE BRACKETS ABOVE, LATIN SMALL LETTER B
+0061 1AC5 0315 0300 05AE 0062;0061 05AE 1AC5 0300 0315 0062;0061 05AE 1AC5 0300 0315 0062;0061 05AE 1AC5 0300 0315 0062;0061 05AE 1AC5 0300 0315 0062; # (a◌᫅◌̕◌̀◌֮b; a◌֮◌᫅◌̀◌̕b; a◌֮◌᫅◌̀◌̕b; a◌֮◌᫅◌̀◌̕b; a◌֮◌᫅◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING SQUARE BRACKETS ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC6 0062;00E0 05AE 1AC6 0315 0062;0061 05AE 0300 1AC6 0315 0062;00E0 05AE 1AC6 0315 0062;0061 05AE 0300 1AC6 0315 0062; # (a◌̕◌̀◌֮◌᫆b; à◌֮◌᫆◌̕b; a◌֮◌̀◌᫆◌̕b; à◌֮◌᫆◌̕b; a◌֮◌̀◌᫆◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING NUMBER SIGN ABOVE, LATIN SMALL LETTER B
+0061 1AC6 0315 0300 05AE 0062;0061 05AE 1AC6 0300 0315 0062;0061 05AE 1AC6 0300 0315 0062;0061 05AE 1AC6 0300 0315 0062;0061 05AE 1AC6 0300 0315 0062; # (a◌᫆◌̕◌̀◌֮b; a◌֮◌᫆◌̀◌̕b; a◌֮◌᫆◌̀◌̕b; a◌֮◌᫆◌̀◌̕b; a◌֮◌᫆◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING NUMBER SIGN ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC7 0062;00E0 05AE 1AC7 0315 0062;0061 05AE 0300 1AC7 0315 0062;00E0 05AE 1AC7 0315 0062;0061 05AE 0300 1AC7 0315 0062; # (a◌̕◌̀◌֮◌᫇b; à◌֮◌᫇◌̕b; a◌֮◌̀◌᫇◌̕b; à◌֮◌᫇◌̕b; a◌֮◌̀◌᫇◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING INVERTED DOUBLE ARCH ABOVE, LATIN SMALL LETTER B
+0061 1AC7 0315 0300 05AE 0062;0061 05AE 1AC7 0300 0315 0062;0061 05AE 1AC7 0300 0315 0062;0061 05AE 1AC7 0300 0315 0062;0061 05AE 1AC7 0300 0315 0062; # (a◌᫇◌̕◌̀◌֮b; a◌֮◌᫇◌̀◌̕b; a◌֮◌᫇◌̀◌̕b; a◌֮◌᫇◌̀◌̕b; a◌֮◌᫇◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING INVERTED DOUBLE ARCH ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC8 0062;00E0 05AE 1AC8 0315 0062;0061 05AE 0300 1AC8 0315 0062;00E0 05AE 1AC8 0315 0062;0061 05AE 0300 1AC8 0315 0062; # (a◌̕◌̀◌֮◌᫈b; à◌֮◌᫈◌̕b; a◌֮◌̀◌᫈◌̕b; à◌֮◌᫈◌̕b; a◌֮◌̀◌᫈◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING PLUS SIGN ABOVE, LATIN SMALL LETTER B
+0061 1AC8 0315 0300 05AE 0062;0061 05AE 1AC8 0300 0315 0062;0061 05AE 1AC8 0300 0315 0062;0061 05AE 1AC8 0300 0315 0062;0061 05AE 1AC8 0300 0315 0062; # (a◌᫈◌̕◌̀◌֮b; a◌֮◌᫈◌̀◌̕b; a◌֮◌᫈◌̀◌̕b; a◌֮◌᫈◌̀◌̕b; a◌֮◌᫈◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING PLUS SIGN ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1AC9 0062;00E0 05AE 1AC9 0315 0062;0061 05AE 0300 1AC9 0315 0062;00E0 05AE 1AC9 0315 0062;0061 05AE 0300 1AC9 0315 0062; # (a◌̕◌̀◌֮◌᫉b; à◌֮◌᫉◌̕b; a◌֮◌̀◌᫉◌̕b; à◌֮◌᫉◌̕b; a◌֮◌̀◌᫉◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DOUBLE PLUS SIGN ABOVE, LATIN SMALL LETTER B
+0061 1AC9 0315 0300 05AE 0062;0061 05AE 1AC9 0300 0315 0062;0061 05AE 1AC9 0300 0315 0062;0061 05AE 1AC9 0300 0315 0062;0061 05AE 1AC9 0300 0315 0062; # (a◌᫉◌̕◌̀◌֮b; a◌֮◌᫉◌̀◌̕b; a◌֮◌᫉◌̀◌̕b; a◌֮◌᫉◌̀◌̕b; a◌֮◌᫉◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DOUBLE PLUS SIGN ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1ACA 0062;0061 1DFA 0316 1ACA 059A 0062;0061 1DFA 0316 1ACA 059A 0062;0061 1DFA 0316 1ACA 059A 0062;0061 1DFA 0316 1ACA 059A 0062; # (a◌֚◌̖◌᷺◌᫊b; a◌᷺◌̖◌᫊◌֚b; a◌᷺◌̖◌᫊◌֚b; a◌᷺◌̖◌᫊◌֚b; a◌᷺◌̖◌᫊◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING DOUBLE PLUS SIGN BELOW, LATIN SMALL LETTER B
+0061 1ACA 059A 0316 1DFA 0062;0061 1DFA 1ACA 0316 059A 0062;0061 1DFA 1ACA 0316 059A 0062;0061 1DFA 1ACA 0316 059A 0062;0061 1DFA 1ACA 0316 059A 0062; # (a◌᫊◌֚◌̖◌᷺b; a◌᷺◌᫊◌̖◌֚b; a◌᷺◌᫊◌̖◌֚b; a◌᷺◌᫊◌̖◌֚b; a◌᷺◌᫊◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING DOUBLE PLUS SIGN BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1ACB 0062;00E0 05AE 1ACB 0315 0062;0061 05AE 0300 1ACB 0315 0062;00E0 05AE 1ACB 0315 0062;0061 05AE 0300 1ACB 0315 0062; # (a◌̕◌̀◌֮◌᫋b; à◌֮◌᫋◌̕b; a◌֮◌̀◌᫋◌̕b; à◌֮◌᫋◌̕b; a◌֮◌̀◌᫋◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING TRIPLE ACUTE ACCENT, LATIN SMALL LETTER B
+0061 1ACB 0315 0300 05AE 0062;0061 05AE 1ACB 0300 0315 0062;0061 05AE 1ACB 0300 0315 0062;0061 05AE 1ACB 0300 0315 0062;0061 05AE 1ACB 0300 0315 0062; # (a◌᫋◌̕◌̀◌֮b; a◌֮◌᫋◌̀◌̕b; a◌֮◌᫋◌̀◌̕b; a◌֮◌᫋◌̀◌̕b; a◌֮◌᫋◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING TRIPLE ACUTE ACCENT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1ACC 0062;00E0 05AE 1ACC 0315 0062;0061 05AE 0300 1ACC 0315 0062;00E0 05AE 1ACC 0315 0062;0061 05AE 0300 1ACC 0315 0062; # (a◌̕◌̀◌֮◌ᫌb; à◌֮◌ᫌ◌̕b; a◌֮◌̀◌ᫌ◌̕b; à◌֮◌ᫌ◌̕b; a◌֮◌̀◌ᫌ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LATIN SMALL LETTER INSULAR G, LATIN SMALL LETTER B
+0061 1ACC 0315 0300 05AE 0062;0061 05AE 1ACC 0300 0315 0062;0061 05AE 1ACC 0300 0315 0062;0061 05AE 1ACC 0300 0315 0062;0061 05AE 1ACC 0300 0315 0062; # (a◌ᫌ◌̕◌̀◌֮b; a◌֮◌ᫌ◌̀◌̕b; a◌֮◌ᫌ◌̀◌̕b; a◌֮◌ᫌ◌̀◌̕b; a◌֮◌ᫌ◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER INSULAR G, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1ACD 0062;00E0 05AE 1ACD 0315 0062;0061 05AE 0300 1ACD 0315 0062;00E0 05AE 1ACD 0315 0062;0061 05AE 0300 1ACD 0315 0062; # (a◌̕◌̀◌֮◌á«b; à◌֮◌á«â—ŒÌ•b; a◌֮◌̀◌á«â—ŒÌ•b; à◌֮◌á«â—ŒÌ•b; a◌֮◌̀◌á«â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LATIN SMALL LETTER INSULAR R, LATIN SMALL LETTER B
+0061 1ACD 0315 0300 05AE 0062;0061 05AE 1ACD 0300 0315 0062;0061 05AE 1ACD 0300 0315 0062;0061 05AE 1ACD 0300 0315 0062;0061 05AE 1ACD 0300 0315 0062; # (aâ—Œá«â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; a◌֮◌á«â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER INSULAR R, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1ACE 0062;00E0 05AE 1ACE 0315 0062;0061 05AE 0300 1ACE 0315 0062;00E0 05AE 1ACE 0315 0062;0061 05AE 0300 1ACE 0315 0062; # (a◌̕◌̀◌֮◌ᫎb; à◌֮◌ᫎ◌̕b; a◌֮◌̀◌ᫎ◌̕b; à◌֮◌ᫎ◌̕b; a◌֮◌̀◌ᫎ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LATIN SMALL LETTER INSULAR T, LATIN SMALL LETTER B
+0061 1ACE 0315 0300 05AE 0062;0061 05AE 1ACE 0300 0315 0062;0061 05AE 1ACE 0300 0315 0062;0061 05AE 1ACE 0300 0315 0062;0061 05AE 1ACE 0300 0315 0062; # (a◌ᫎ◌̕◌̀◌֮b; a◌֮◌ᫎ◌̀◌̕b; a◌֮◌ᫎ◌̀◌̕b; a◌֮◌ᫎ◌̀◌̕b; a◌֮◌ᫎ◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER INSULAR T, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 3099 093C 16FF0 1B34 0062;0061 16FF0 093C 1B34 3099 0062;0061 16FF0 093C 1B34 3099 0062;0061 16FF0 093C 1B34 3099 0062;0061 16FF0 093C 1B34 3099 0062; # (a◌゙◌𖿰़◌᬴b; a𖿰◌़◌᬴◌゙b; a𖿰◌़◌᬴◌゙b; a𖿰◌़◌᬴◌゙b; a𖿰◌़◌᬴◌゙b; ) LATIN SMALL LETTER A, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, BALINESE SIGN REREKAN, LATIN SMALL LETTER B
0061 1B34 3099 093C 16FF0 0062;0061 16FF0 1B34 093C 3099 0062;0061 16FF0 1B34 093C 3099 0062;0061 16FF0 1B34 093C 3099 0062;0061 16FF0 1B34 093C 3099 0062; # (a◌᬴◌゙◌𖿰़b; a𖿰◌᬴◌़◌゙b; a𖿰◌᬴◌़◌゙b; a𖿰◌᬴◌़◌゙b; a𖿰◌᬴◌़◌゙b; ) LATIN SMALL LETTER A, BALINESE SIGN REREKAN, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, LATIN SMALL LETTER B
0061 05B0 094D 3099 1B44 0062;0061 3099 094D 1B44 05B0 0062;0061 3099 094D 1B44 05B0 0062;0061 3099 094D 1B44 05B0 0062;0061 3099 094D 1B44 05B0 0062; # (a◌ְ◌à¥â—Œã‚™á­„b; a◌゙◌à¥á­„◌ְb; a◌゙◌à¥á­„◌ְb; a◌゙◌à¥á­„◌ְb; a◌゙◌à¥á­„◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, BALINESE ADEG ADEG, LATIN SMALL LETTER B
0061 1B44 05B0 094D 3099 0062;0061 3099 1B44 094D 05B0 0062;0061 3099 1B44 094D 05B0 0062;0061 3099 1B44 094D 05B0 0062;0061 3099 1B44 094D 05B0 0062; # (a᭄◌ְ◌à¥â—Œã‚™b; a◌゙᭄◌à¥â—ŒÖ°b; a◌゙᭄◌à¥â—ŒÖ°b; a◌゙᭄◌à¥â—ŒÖ°b; a◌゙᭄◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, BALINESE ADEG ADEG, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 0315 0300 05AE 1B6B 0062;00E0 05AE 1B6B 0315 0062;0061 05AE 0300 1B6B 0315 0062;00E0 05AE 1B6B 0315 0062;0061 05AE 0300 1B6B 0315 0062; # (a◌̕◌̀◌֮◌᭫b; à◌֮◌᭫◌̕b; a◌֮◌̀◌᭫◌̕b; à◌֮◌᭫◌̕b; a◌֮◌̀◌᭫◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, BALINESE MUSICAL SYMBOL COMBINING TEGEH, LATIN SMALL LETTER B
0061 1B6B 0315 0300 05AE 0062;0061 05AE 1B6B 0300 0315 0062;0061 05AE 1B6B 0300 0315 0062;0061 05AE 1B6B 0300 0315 0062;0061 05AE 1B6B 0300 0315 0062; # (a◌᭫◌̕◌̀◌֮b; a◌֮◌᭫◌̀◌̕b; a◌֮◌᭫◌̀◌̕b; a◌֮◌᭫◌̀◌̕b; a◌֮◌᭫◌̀◌̕b; ) LATIN SMALL LETTER A, BALINESE MUSICAL SYMBOL COMBINING TEGEH, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1B6C 0062;0061 302A 0316 1B6C 059A 0062;0061 302A 0316 1B6C 059A 0062;0061 302A 0316 1B6C 059A 0062;0061 302A 0316 1B6C 059A 0062; # (a◌֚◌̖◌〪◌᭬b; a◌〪◌̖◌᭬◌֚b; a◌〪◌̖◌᭬◌֚b; a◌〪◌̖◌᭬◌֚b; a◌〪◌̖◌᭬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, BALINESE MUSICAL SYMBOL COMBINING ENDEP, LATIN SMALL LETTER B
-0061 1B6C 059A 0316 302A 0062;0061 302A 1B6C 0316 059A 0062;0061 302A 1B6C 0316 059A 0062;0061 302A 1B6C 0316 059A 0062;0061 302A 1B6C 0316 059A 0062; # (a◌᭬◌֚◌̖◌〪b; a◌〪◌᭬◌̖◌֚b; a◌〪◌᭬◌̖◌֚b; a◌〪◌᭬◌̖◌֚b; a◌〪◌᭬◌̖◌֚b; ) LATIN SMALL LETTER A, BALINESE MUSICAL SYMBOL COMBINING ENDEP, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1B6C 0062;0061 1DFA 0316 1B6C 059A 0062;0061 1DFA 0316 1B6C 059A 0062;0061 1DFA 0316 1B6C 059A 0062;0061 1DFA 0316 1B6C 059A 0062; # (a◌֚◌̖◌᷺◌᭬b; a◌᷺◌̖◌᭬◌֚b; a◌᷺◌̖◌᭬◌֚b; a◌᷺◌̖◌᭬◌֚b; a◌᷺◌̖◌᭬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, BALINESE MUSICAL SYMBOL COMBINING ENDEP, LATIN SMALL LETTER B
+0061 1B6C 059A 0316 1DFA 0062;0061 1DFA 1B6C 0316 059A 0062;0061 1DFA 1B6C 0316 059A 0062;0061 1DFA 1B6C 0316 059A 0062;0061 1DFA 1B6C 0316 059A 0062; # (a◌᭬◌֚◌̖◌᷺b; a◌᷺◌᭬◌̖◌֚b; a◌᷺◌᭬◌̖◌֚b; a◌᷺◌᭬◌̖◌֚b; a◌᷺◌᭬◌̖◌֚b; ) LATIN SMALL LETTER A, BALINESE MUSICAL SYMBOL COMBINING ENDEP, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1B6D 0062;00E0 05AE 1B6D 0315 0062;0061 05AE 0300 1B6D 0315 0062;00E0 05AE 1B6D 0315 0062;0061 05AE 0300 1B6D 0315 0062; # (a◌̕◌̀◌֮◌᭭b; à◌֮◌᭭◌̕b; a◌֮◌̀◌᭭◌̕b; à◌֮◌᭭◌̕b; a◌֮◌̀◌᭭◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, BALINESE MUSICAL SYMBOL COMBINING KEMPUL, LATIN SMALL LETTER B
0061 1B6D 0315 0300 05AE 0062;0061 05AE 1B6D 0300 0315 0062;0061 05AE 1B6D 0300 0315 0062;0061 05AE 1B6D 0300 0315 0062;0061 05AE 1B6D 0300 0315 0062; # (a◌᭭◌̕◌̀◌֮b; a◌֮◌᭭◌̀◌̕b; a◌֮◌᭭◌̀◌̕b; a◌֮◌᭭◌̀◌̕b; a◌֮◌᭭◌̀◌̕b; ) LATIN SMALL LETTER A, BALINESE MUSICAL SYMBOL COMBINING KEMPUL, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1B6E 0062;00E0 05AE 1B6E 0315 0062;0061 05AE 0300 1B6E 0315 0062;00E0 05AE 1B6E 0315 0062;0061 05AE 0300 1B6E 0315 0062; # (a◌̕◌̀◌֮◌᭮b; à◌֮◌᭮◌̕b; a◌֮◌̀◌᭮◌̕b; à◌֮◌᭮◌̕b; a◌֮◌̀◌᭮◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, BALINESE MUSICAL SYMBOL COMBINING KEMPLI, LATIN SMALL LETTER B
@@ -17875,28 +18000,28 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1CD2 0315 0300 05AE 0062;0061 05AE 1CD2 0300 0315 0062;0061 05AE 1CD2 0300 0315 0062;0061 05AE 1CD2 0300 0315 0062;0061 05AE 1CD2 0300 0315 0062; # (a◌᳒◌̕◌̀◌֮b; a◌֮◌᳒◌̀◌̕b; a◌֮◌᳒◌̀◌̕b; a◌֮◌᳒◌̀◌̕b; a◌֮◌᳒◌̀◌̕b; ) LATIN SMALL LETTER A, VEDIC TONE PRENKHA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 16FF0 0334 1CD4 0062;0061 0334 1CD4 16FF0 0062;0061 0334 1CD4 16FF0 0062;0061 0334 1CD4 16FF0 0062;0061 0334 1CD4 16FF0 0062; # (a𖿰◌̴◌᳔b; a◌̴◌᳔𖿰b; a◌̴◌᳔𖿰b; a◌̴◌᳔𖿰b; a◌̴◌᳔𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, VEDIC SIGN YAJURVEDIC MIDLINE SVARITA, LATIN SMALL LETTER B
0061 1CD4 16FF0 0334 0062;0061 1CD4 0334 16FF0 0062;0061 1CD4 0334 16FF0 0062;0061 1CD4 0334 16FF0 0062;0061 1CD4 0334 16FF0 0062; # (a◌᳔𖿰◌̴b; a◌᳔◌̴𖿰b; a◌᳔◌̴𖿰b; a◌᳔◌̴𖿰b; a◌᳔◌̴𖿰b; ) LATIN SMALL LETTER A, VEDIC SIGN YAJURVEDIC MIDLINE SVARITA, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CD5 0062;0061 302A 0316 1CD5 059A 0062;0061 302A 0316 1CD5 059A 0062;0061 302A 0316 1CD5 059A 0062;0061 302A 0316 1CD5 059A 0062; # (a◌֚◌̖◌〪◌᳕b; a◌〪◌̖◌᳕◌֚b; a◌〪◌̖◌᳕◌֚b; a◌〪◌̖◌᳕◌֚b; a◌〪◌̖◌᳕◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA, LATIN SMALL LETTER B
-0061 1CD5 059A 0316 302A 0062;0061 302A 1CD5 0316 059A 0062;0061 302A 1CD5 0316 059A 0062;0061 302A 1CD5 0316 059A 0062;0061 302A 1CD5 0316 059A 0062; # (a◌᳕◌֚◌̖◌〪b; a◌〪◌᳕◌̖◌֚b; a◌〪◌᳕◌̖◌֚b; a◌〪◌᳕◌̖◌֚b; a◌〪◌᳕◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CD6 0062;0061 302A 0316 1CD6 059A 0062;0061 302A 0316 1CD6 059A 0062;0061 302A 0316 1CD6 059A 0062;0061 302A 0316 1CD6 059A 0062; # (a◌֚◌̖◌〪◌᳖b; a◌〪◌̖◌᳖◌֚b; a◌〪◌̖◌᳖◌֚b; a◌〪◌̖◌᳖◌֚b; a◌〪◌̖◌᳖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA, LATIN SMALL LETTER B
-0061 1CD6 059A 0316 302A 0062;0061 302A 1CD6 0316 059A 0062;0061 302A 1CD6 0316 059A 0062;0061 302A 1CD6 0316 059A 0062;0061 302A 1CD6 0316 059A 0062; # (a◌᳖◌֚◌̖◌〪b; a◌〪◌᳖◌̖◌֚b; a◌〪◌᳖◌̖◌֚b; a◌〪◌᳖◌̖◌֚b; a◌〪◌᳖◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CD7 0062;0061 302A 0316 1CD7 059A 0062;0061 302A 0316 1CD7 059A 0062;0061 302A 0316 1CD7 059A 0062;0061 302A 0316 1CD7 059A 0062; # (a◌֚◌̖◌〪◌᳗b; a◌〪◌̖◌᳗◌֚b; a◌〪◌̖◌᳗◌֚b; a◌〪◌̖◌᳗◌֚b; a◌〪◌̖◌᳗◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA, LATIN SMALL LETTER B
-0061 1CD7 059A 0316 302A 0062;0061 302A 1CD7 0316 059A 0062;0061 302A 1CD7 0316 059A 0062;0061 302A 1CD7 0316 059A 0062;0061 302A 1CD7 0316 059A 0062; # (a◌᳗◌֚◌̖◌〪b; a◌〪◌᳗◌̖◌֚b; a◌〪◌᳗◌̖◌֚b; a◌〪◌᳗◌̖◌֚b; a◌〪◌᳗◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CD8 0062;0061 302A 0316 1CD8 059A 0062;0061 302A 0316 1CD8 059A 0062;0061 302A 0316 1CD8 059A 0062;0061 302A 0316 1CD8 059A 0062; # (a◌֚◌̖◌〪◌᳘b; a◌〪◌̖◌᳘◌֚b; a◌〪◌̖◌᳘◌֚b; a◌〪◌̖◌᳘◌֚b; a◌〪◌̖◌᳘◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE CANDRA BELOW, LATIN SMALL LETTER B
-0061 1CD8 059A 0316 302A 0062;0061 302A 1CD8 0316 059A 0062;0061 302A 1CD8 0316 059A 0062;0061 302A 1CD8 0316 059A 0062;0061 302A 1CD8 0316 059A 0062; # (a◌᳘◌֚◌̖◌〪b; a◌〪◌᳘◌̖◌֚b; a◌〪◌᳘◌̖◌֚b; a◌〪◌᳘◌̖◌֚b; a◌〪◌᳘◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE CANDRA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CD9 0062;0061 302A 0316 1CD9 059A 0062;0061 302A 0316 1CD9 059A 0062;0061 302A 0316 1CD9 059A 0062;0061 302A 0316 1CD9 059A 0062; # (a◌֚◌̖◌〪◌᳙b; a◌〪◌̖◌᳙◌֚b; a◌〪◌̖◌᳙◌֚b; a◌〪◌̖◌᳙◌֚b; a◌〪◌̖◌᳙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER, LATIN SMALL LETTER B
-0061 1CD9 059A 0316 302A 0062;0061 302A 1CD9 0316 059A 0062;0061 302A 1CD9 0316 059A 0062;0061 302A 1CD9 0316 059A 0062;0061 302A 1CD9 0316 059A 0062; # (a◌᳙◌֚◌̖◌〪b; a◌〪◌᳙◌̖◌֚b; a◌〪◌᳙◌̖◌֚b; a◌〪◌᳙◌̖◌֚b; a◌〪◌᳙◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CD5 0062;0061 1DFA 0316 1CD5 059A 0062;0061 1DFA 0316 1CD5 059A 0062;0061 1DFA 0316 1CD5 059A 0062;0061 1DFA 0316 1CD5 059A 0062; # (a◌֚◌̖◌᷺◌᳕b; a◌᷺◌̖◌᳕◌֚b; a◌᷺◌̖◌᳕◌֚b; a◌᷺◌̖◌᳕◌֚b; a◌᷺◌̖◌᳕◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA, LATIN SMALL LETTER B
+0061 1CD5 059A 0316 1DFA 0062;0061 1DFA 1CD5 0316 059A 0062;0061 1DFA 1CD5 0316 059A 0062;0061 1DFA 1CD5 0316 059A 0062;0061 1DFA 1CD5 0316 059A 0062; # (a◌᳕◌֚◌̖◌᷺b; a◌᷺◌᳕◌̖◌֚b; a◌᷺◌᳕◌̖◌֚b; a◌᷺◌᳕◌̖◌֚b; a◌᷺◌᳕◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CD6 0062;0061 1DFA 0316 1CD6 059A 0062;0061 1DFA 0316 1CD6 059A 0062;0061 1DFA 0316 1CD6 059A 0062;0061 1DFA 0316 1CD6 059A 0062; # (a◌֚◌̖◌᷺◌᳖b; a◌᷺◌̖◌᳖◌֚b; a◌᷺◌̖◌᳖◌֚b; a◌᷺◌̖◌᳖◌֚b; a◌᷺◌̖◌᳖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA, LATIN SMALL LETTER B
+0061 1CD6 059A 0316 1DFA 0062;0061 1DFA 1CD6 0316 059A 0062;0061 1DFA 1CD6 0316 059A 0062;0061 1DFA 1CD6 0316 059A 0062;0061 1DFA 1CD6 0316 059A 0062; # (a◌᳖◌֚◌̖◌᷺b; a◌᷺◌᳖◌̖◌֚b; a◌᷺◌᳖◌̖◌֚b; a◌᷺◌᳖◌̖◌֚b; a◌᷺◌᳖◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CD7 0062;0061 1DFA 0316 1CD7 059A 0062;0061 1DFA 0316 1CD7 059A 0062;0061 1DFA 0316 1CD7 059A 0062;0061 1DFA 0316 1CD7 059A 0062; # (a◌֚◌̖◌᷺◌᳗b; a◌᷺◌̖◌᳗◌֚b; a◌᷺◌̖◌᳗◌֚b; a◌᷺◌̖◌᳗◌֚b; a◌᷺◌̖◌᳗◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA, LATIN SMALL LETTER B
+0061 1CD7 059A 0316 1DFA 0062;0061 1DFA 1CD7 0316 059A 0062;0061 1DFA 1CD7 0316 059A 0062;0061 1DFA 1CD7 0316 059A 0062;0061 1DFA 1CD7 0316 059A 0062; # (a◌᳗◌֚◌̖◌᷺b; a◌᷺◌᳗◌̖◌֚b; a◌᷺◌᳗◌̖◌֚b; a◌᷺◌᳗◌̖◌֚b; a◌᷺◌᳗◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CD8 0062;0061 1DFA 0316 1CD8 059A 0062;0061 1DFA 0316 1CD8 059A 0062;0061 1DFA 0316 1CD8 059A 0062;0061 1DFA 0316 1CD8 059A 0062; # (a◌֚◌̖◌᷺◌᳘b; a◌᷺◌̖◌᳘◌֚b; a◌᷺◌̖◌᳘◌֚b; a◌᷺◌̖◌᳘◌֚b; a◌᷺◌̖◌᳘◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE CANDRA BELOW, LATIN SMALL LETTER B
+0061 1CD8 059A 0316 1DFA 0062;0061 1DFA 1CD8 0316 059A 0062;0061 1DFA 1CD8 0316 059A 0062;0061 1DFA 1CD8 0316 059A 0062;0061 1DFA 1CD8 0316 059A 0062; # (a◌᳘◌֚◌̖◌᷺b; a◌᷺◌᳘◌̖◌֚b; a◌᷺◌᳘◌̖◌֚b; a◌᷺◌᳘◌̖◌֚b; a◌᷺◌᳘◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE CANDRA BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CD9 0062;0061 1DFA 0316 1CD9 059A 0062;0061 1DFA 0316 1CD9 059A 0062;0061 1DFA 0316 1CD9 059A 0062;0061 1DFA 0316 1CD9 059A 0062; # (a◌֚◌̖◌᷺◌᳙b; a◌᷺◌̖◌᳙◌֚b; a◌᷺◌̖◌᳙◌֚b; a◌᷺◌̖◌᳙◌֚b; a◌᷺◌̖◌᳙◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER, LATIN SMALL LETTER B
+0061 1CD9 059A 0316 1DFA 0062;0061 1DFA 1CD9 0316 059A 0062;0061 1DFA 1CD9 0316 059A 0062;0061 1DFA 1CD9 0316 059A 0062;0061 1DFA 1CD9 0316 059A 0062; # (a◌᳙◌֚◌̖◌᷺b; a◌᷺◌᳙◌̖◌֚b; a◌᷺◌᳙◌̖◌֚b; a◌᷺◌᳙◌̖◌֚b; a◌᷺◌᳙◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1CDA 0062;00E0 05AE 1CDA 0315 0062;0061 05AE 0300 1CDA 0315 0062;00E0 05AE 1CDA 0315 0062;0061 05AE 0300 1CDA 0315 0062; # (a◌̕◌̀◌֮◌᳚b; à◌֮◌᳚◌̕b; a◌֮◌̀◌᳚◌̕b; à◌֮◌᳚◌̕b; a◌֮◌̀◌᳚◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, VEDIC TONE DOUBLE SVARITA, LATIN SMALL LETTER B
0061 1CDA 0315 0300 05AE 0062;0061 05AE 1CDA 0300 0315 0062;0061 05AE 1CDA 0300 0315 0062;0061 05AE 1CDA 0300 0315 0062;0061 05AE 1CDA 0300 0315 0062; # (a◌᳚◌̕◌̀◌֮b; a◌֮◌᳚◌̀◌̕b; a◌֮◌᳚◌̀◌̕b; a◌֮◌᳚◌̀◌̕b; a◌֮◌᳚◌̀◌̕b; ) LATIN SMALL LETTER A, VEDIC TONE DOUBLE SVARITA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1CDB 0062;00E0 05AE 1CDB 0315 0062;0061 05AE 0300 1CDB 0315 0062;00E0 05AE 1CDB 0315 0062;0061 05AE 0300 1CDB 0315 0062; # (a◌̕◌̀◌֮◌᳛b; à◌֮◌᳛◌̕b; a◌֮◌̀◌᳛◌̕b; à◌֮◌᳛◌̕b; a◌֮◌̀◌᳛◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, VEDIC TONE TRIPLE SVARITA, LATIN SMALL LETTER B
0061 1CDB 0315 0300 05AE 0062;0061 05AE 1CDB 0300 0315 0062;0061 05AE 1CDB 0300 0315 0062;0061 05AE 1CDB 0300 0315 0062;0061 05AE 1CDB 0300 0315 0062; # (a◌᳛◌̕◌̀◌֮b; a◌֮◌᳛◌̀◌̕b; a◌֮◌᳛◌̀◌̕b; a◌֮◌᳛◌̀◌̕b; a◌֮◌᳛◌̀◌̕b; ) LATIN SMALL LETTER A, VEDIC TONE TRIPLE SVARITA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CDC 0062;0061 302A 0316 1CDC 059A 0062;0061 302A 0316 1CDC 059A 0062;0061 302A 0316 1CDC 059A 0062;0061 302A 0316 1CDC 059A 0062; # (a◌֚◌̖◌〪◌᳜b; a◌〪◌̖◌᳜◌֚b; a◌〪◌̖◌᳜◌֚b; a◌〪◌̖◌᳜◌֚b; a◌〪◌̖◌᳜◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE KATHAKA ANUDATTA, LATIN SMALL LETTER B
-0061 1CDC 059A 0316 302A 0062;0061 302A 1CDC 0316 059A 0062;0061 302A 1CDC 0316 059A 0062;0061 302A 1CDC 0316 059A 0062;0061 302A 1CDC 0316 059A 0062; # (a◌᳜◌֚◌̖◌〪b; a◌〪◌᳜◌̖◌֚b; a◌〪◌᳜◌̖◌֚b; a◌〪◌᳜◌̖◌֚b; a◌〪◌᳜◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE KATHAKA ANUDATTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CDD 0062;0061 302A 0316 1CDD 059A 0062;0061 302A 0316 1CDD 059A 0062;0061 302A 0316 1CDD 059A 0062;0061 302A 0316 1CDD 059A 0062; # (a◌֚◌̖◌〪◌á³b; a◌〪◌̖◌á³â—ŒÖšb; a◌〪◌̖◌á³â—ŒÖšb; a◌〪◌̖◌á³â—ŒÖšb; a◌〪◌̖◌á³â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE DOT BELOW, LATIN SMALL LETTER B
-0061 1CDD 059A 0316 302A 0062;0061 302A 1CDD 0316 059A 0062;0061 302A 1CDD 0316 059A 0062;0061 302A 1CDD 0316 059A 0062;0061 302A 1CDD 0316 059A 0062; # (aâ—Œá³â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌á³â—ŒÌ–◌֚b; a◌〪◌á³â—ŒÌ–◌֚b; a◌〪◌á³â—ŒÌ–◌֚b; a◌〪◌á³â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CDE 0062;0061 302A 0316 1CDE 059A 0062;0061 302A 0316 1CDE 059A 0062;0061 302A 0316 1CDE 059A 0062;0061 302A 0316 1CDE 059A 0062; # (a◌֚◌̖◌〪◌᳞b; a◌〪◌̖◌᳞◌֚b; a◌〪◌̖◌᳞◌֚b; a◌〪◌̖◌᳞◌֚b; a◌〪◌̖◌᳞◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE TWO DOTS BELOW, LATIN SMALL LETTER B
-0061 1CDE 059A 0316 302A 0062;0061 302A 1CDE 0316 059A 0062;0061 302A 1CDE 0316 059A 0062;0061 302A 1CDE 0316 059A 0062;0061 302A 1CDE 0316 059A 0062; # (a◌᳞◌֚◌̖◌〪b; a◌〪◌᳞◌̖◌֚b; a◌〪◌᳞◌̖◌֚b; a◌〪◌᳞◌̖◌֚b; a◌〪◌᳞◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CDF 0062;0061 302A 0316 1CDF 059A 0062;0061 302A 0316 1CDF 059A 0062;0061 302A 0316 1CDF 059A 0062;0061 302A 0316 1CDF 059A 0062; # (a◌֚◌̖◌〪◌᳟b; a◌〪◌̖◌᳟◌֚b; a◌〪◌̖◌᳟◌֚b; a◌〪◌̖◌᳟◌֚b; a◌〪◌̖◌᳟◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC TONE THREE DOTS BELOW, LATIN SMALL LETTER B
-0061 1CDF 059A 0316 302A 0062;0061 302A 1CDF 0316 059A 0062;0061 302A 1CDF 0316 059A 0062;0061 302A 1CDF 0316 059A 0062;0061 302A 1CDF 0316 059A 0062; # (a◌᳟◌֚◌̖◌〪b; a◌〪◌᳟◌̖◌֚b; a◌〪◌᳟◌̖◌֚b; a◌〪◌᳟◌̖◌֚b; a◌〪◌᳟◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE THREE DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CDC 0062;0061 1DFA 0316 1CDC 059A 0062;0061 1DFA 0316 1CDC 059A 0062;0061 1DFA 0316 1CDC 059A 0062;0061 1DFA 0316 1CDC 059A 0062; # (a◌֚◌̖◌᷺◌᳜b; a◌᷺◌̖◌᳜◌֚b; a◌᷺◌̖◌᳜◌֚b; a◌᷺◌̖◌᳜◌֚b; a◌᷺◌̖◌᳜◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE KATHAKA ANUDATTA, LATIN SMALL LETTER B
+0061 1CDC 059A 0316 1DFA 0062;0061 1DFA 1CDC 0316 059A 0062;0061 1DFA 1CDC 0316 059A 0062;0061 1DFA 1CDC 0316 059A 0062;0061 1DFA 1CDC 0316 059A 0062; # (a◌᳜◌֚◌̖◌᷺b; a◌᷺◌᳜◌̖◌֚b; a◌᷺◌᳜◌̖◌֚b; a◌᷺◌᳜◌̖◌֚b; a◌᷺◌᳜◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE KATHAKA ANUDATTA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CDD 0062;0061 1DFA 0316 1CDD 059A 0062;0061 1DFA 0316 1CDD 059A 0062;0061 1DFA 0316 1CDD 059A 0062;0061 1DFA 0316 1CDD 059A 0062; # (a◌֚◌̖◌᷺◌á³b; a◌᷺◌̖◌á³â—ŒÖšb; a◌᷺◌̖◌á³â—ŒÖšb; a◌᷺◌̖◌á³â—ŒÖšb; a◌᷺◌̖◌á³â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE DOT BELOW, LATIN SMALL LETTER B
+0061 1CDD 059A 0316 1DFA 0062;0061 1DFA 1CDD 0316 059A 0062;0061 1DFA 1CDD 0316 059A 0062;0061 1DFA 1CDD 0316 059A 0062;0061 1DFA 1CDD 0316 059A 0062; # (aâ—Œá³â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌á³â—ŒÌ–◌֚b; a◌᷺◌á³â—ŒÌ–◌֚b; a◌᷺◌á³â—ŒÌ–◌֚b; a◌᷺◌á³â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CDE 0062;0061 1DFA 0316 1CDE 059A 0062;0061 1DFA 0316 1CDE 059A 0062;0061 1DFA 0316 1CDE 059A 0062;0061 1DFA 0316 1CDE 059A 0062; # (a◌֚◌̖◌᷺◌᳞b; a◌᷺◌̖◌᳞◌֚b; a◌᷺◌̖◌᳞◌֚b; a◌᷺◌̖◌᳞◌֚b; a◌᷺◌̖◌᳞◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE TWO DOTS BELOW, LATIN SMALL LETTER B
+0061 1CDE 059A 0316 1DFA 0062;0061 1DFA 1CDE 0316 059A 0062;0061 1DFA 1CDE 0316 059A 0062;0061 1DFA 1CDE 0316 059A 0062;0061 1DFA 1CDE 0316 059A 0062; # (a◌᳞◌֚◌̖◌᷺b; a◌᷺◌᳞◌̖◌֚b; a◌᷺◌᳞◌̖◌֚b; a◌᷺◌᳞◌̖◌֚b; a◌᷺◌᳞◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CDF 0062;0061 1DFA 0316 1CDF 059A 0062;0061 1DFA 0316 1CDF 059A 0062;0061 1DFA 0316 1CDF 059A 0062;0061 1DFA 0316 1CDF 059A 0062; # (a◌֚◌̖◌᷺◌᳟b; a◌᷺◌̖◌᳟◌֚b; a◌᷺◌̖◌᳟◌֚b; a◌᷺◌̖◌᳟◌֚b; a◌᷺◌̖◌᳟◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC TONE THREE DOTS BELOW, LATIN SMALL LETTER B
+0061 1CDF 059A 0316 1DFA 0062;0061 1DFA 1CDF 0316 059A 0062;0061 1DFA 1CDF 0316 059A 0062;0061 1DFA 1CDF 0316 059A 0062;0061 1DFA 1CDF 0316 059A 0062; # (a◌᳟◌֚◌̖◌᷺b; a◌᷺◌᳟◌̖◌֚b; a◌᷺◌᳟◌̖◌֚b; a◌᷺◌᳟◌̖◌֚b; a◌᷺◌᳟◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC TONE THREE DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1CE0 0062;00E0 05AE 1CE0 0315 0062;0061 05AE 0300 1CE0 0315 0062;00E0 05AE 1CE0 0315 0062;0061 05AE 0300 1CE0 0315 0062; # (a◌̕◌̀◌֮◌᳠b; à◌֮◌᳠◌̕b; a◌֮◌̀◌᳠◌̕b; à◌֮◌᳠◌̕b; a◌֮◌̀◌᳠◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA, LATIN SMALL LETTER B
0061 1CE0 0315 0300 05AE 0062;0061 05AE 1CE0 0300 0315 0062;0061 05AE 1CE0 0300 0315 0062;0061 05AE 1CE0 0300 0315 0062;0061 05AE 1CE0 0300 0315 0062; # (a◌᳠◌̕◌̀◌֮b; a◌֮◌᳠◌̀◌̕b; a◌֮◌᳠◌̀◌̕b; a◌֮◌᳠◌̀◌̕b; a◌֮◌᳠◌̀◌̕b; ) LATIN SMALL LETTER A, VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 16FF0 0334 1CE2 0062;0061 0334 1CE2 16FF0 0062;0061 0334 1CE2 16FF0 0062;0061 0334 1CE2 16FF0 0062;0061 0334 1CE2 16FF0 0062; # (a𖿰◌̴◌᳢b; a◌̴◌᳢𖿰b; a◌̴◌᳢𖿰b; a◌̴◌᳢𖿰b; a◌̴◌᳢𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, VEDIC SIGN VISARGA SVARITA, LATIN SMALL LETTER B
@@ -17913,8 +18038,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1CE7 16FF0 0334 0062;0061 1CE7 0334 16FF0 0062;0061 1CE7 0334 16FF0 0062;0061 1CE7 0334 16FF0 0062;0061 1CE7 0334 16FF0 0062; # (a◌᳧𖿰◌̴b; a◌᳧◌̴𖿰b; a◌᳧◌̴𖿰b; a◌᳧◌̴𖿰b; a◌᳧◌̴𖿰b; ) LATIN SMALL LETTER A, VEDIC SIGN VISARGA UDATTA WITH TAIL, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 1CE8 0062;0061 0334 1CE8 16FF0 0062;0061 0334 1CE8 16FF0 0062;0061 0334 1CE8 16FF0 0062;0061 0334 1CE8 16FF0 0062; # (a𖿰◌̴◌᳨b; a◌̴◌᳨𖿰b; a◌̴◌᳨𖿰b; a◌̴◌᳨𖿰b; a◌̴◌᳨𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, VEDIC SIGN VISARGA ANUDATTA WITH TAIL, LATIN SMALL LETTER B
0061 1CE8 16FF0 0334 0062;0061 1CE8 0334 16FF0 0062;0061 1CE8 0334 16FF0 0062;0061 1CE8 0334 16FF0 0062;0061 1CE8 0334 16FF0 0062; # (a◌᳨𖿰◌̴b; a◌᳨◌̴𖿰b; a◌᳨◌̴𖿰b; a◌᳨◌̴𖿰b; a◌᳨◌̴𖿰b; ) LATIN SMALL LETTER A, VEDIC SIGN VISARGA ANUDATTA WITH TAIL, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
-0061 059A 0316 302A 1CED 0062;0061 302A 0316 1CED 059A 0062;0061 302A 0316 1CED 059A 0062;0061 302A 0316 1CED 059A 0062;0061 302A 0316 1CED 059A 0062; # (a◌֚◌̖◌〪◌᳭b; a◌〪◌̖◌᳭◌֚b; a◌〪◌̖◌᳭◌֚b; a◌〪◌̖◌᳭◌֚b; a◌〪◌̖◌᳭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, VEDIC SIGN TIRYAK, LATIN SMALL LETTER B
-0061 1CED 059A 0316 302A 0062;0061 302A 1CED 0316 059A 0062;0061 302A 1CED 0316 059A 0062;0061 302A 1CED 0316 059A 0062;0061 302A 1CED 0316 059A 0062; # (a◌᳭◌֚◌̖◌〪b; a◌〪◌᳭◌̖◌֚b; a◌〪◌᳭◌̖◌֚b; a◌〪◌᳭◌̖◌֚b; a◌〪◌᳭◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC SIGN TIRYAK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1CED 0062;0061 1DFA 0316 1CED 059A 0062;0061 1DFA 0316 1CED 059A 0062;0061 1DFA 0316 1CED 059A 0062;0061 1DFA 0316 1CED 059A 0062; # (a◌֚◌̖◌᷺◌᳭b; a◌᷺◌̖◌᳭◌֚b; a◌᷺◌̖◌᳭◌֚b; a◌᷺◌̖◌᳭◌֚b; a◌᷺◌̖◌᳭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, VEDIC SIGN TIRYAK, LATIN SMALL LETTER B
+0061 1CED 059A 0316 1DFA 0062;0061 1DFA 1CED 0316 059A 0062;0061 1DFA 1CED 0316 059A 0062;0061 1DFA 1CED 0316 059A 0062;0061 1DFA 1CED 0316 059A 0062; # (a◌᳭◌֚◌̖◌᷺b; a◌᷺◌᳭◌̖◌֚b; a◌᷺◌᳭◌̖◌֚b; a◌᷺◌᳭◌̖◌֚b; a◌᷺◌᳭◌̖◌֚b; ) LATIN SMALL LETTER A, VEDIC SIGN TIRYAK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1CF4 0062;00E0 05AE 1CF4 0315 0062;0061 05AE 0300 1CF4 0315 0062;00E0 05AE 1CF4 0315 0062;0061 05AE 0300 1CF4 0315 0062; # (a◌̕◌̀◌֮◌᳴b; à◌֮◌᳴◌̕b; a◌֮◌̀◌᳴◌̕b; à◌֮◌᳴◌̕b; a◌֮◌̀◌᳴◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, VEDIC TONE CANDRA ABOVE, LATIN SMALL LETTER B
0061 1CF4 0315 0300 05AE 0062;0061 05AE 1CF4 0300 0315 0062;0061 05AE 1CF4 0300 0315 0062;0061 05AE 1CF4 0300 0315 0062;0061 05AE 1CF4 0300 0315 0062; # (a◌᳴◌̕◌̀◌֮b; a◌֮◌᳴◌̀◌̕b; a◌֮◌᳴◌̀◌̕b; a◌֮◌᳴◌̀◌̕b; a◌֮◌᳴◌̀◌̕b; ) LATIN SMALL LETTER A, VEDIC TONE CANDRA ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1CF8 0062;00E0 05AE 1CF8 0315 0062;0061 05AE 0300 1CF8 0315 0062;00E0 05AE 1CF8 0315 0062;0061 05AE 0300 1CF8 0315 0062; # (a◌̕◌̀◌֮◌᳸b; à◌֮◌᳸◌̕b; a◌֮◌̀◌᳸◌̕b; à◌֮◌᳸◌̕b; a◌֮◌̀◌᳸◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, VEDIC TONE RING ABOVE, LATIN SMALL LETTER B
@@ -17925,8 +18050,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1DC0 0315 0300 05AE 0062;0061 05AE 1DC0 0300 0315 0062;0061 05AE 1DC0 0300 0315 0062;0061 05AE 1DC0 0300 0315 0062;0061 05AE 1DC0 0300 0315 0062; # (a◌᷀◌̕◌̀◌֮b; a◌֮◌᷀◌̀◌̕b; a◌֮◌᷀◌̀◌̕b; a◌֮◌᷀◌̀◌̕b; a◌֮◌᷀◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DOTTED GRAVE ACCENT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DC1 0062;00E0 05AE 1DC1 0315 0062;0061 05AE 0300 1DC1 0315 0062;00E0 05AE 1DC1 0315 0062;0061 05AE 0300 1DC1 0315 0062; # (a◌̕◌̀◌֮◌á·b; à◌֮◌á·â—ŒÌ•b; a◌֮◌̀◌á·â—ŒÌ•b; à◌֮◌á·â—ŒÌ•b; a◌֮◌̀◌á·â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DOTTED ACUTE ACCENT, LATIN SMALL LETTER B
0061 1DC1 0315 0300 05AE 0062;0061 05AE 1DC1 0300 0315 0062;0061 05AE 1DC1 0300 0315 0062;0061 05AE 1DC1 0300 0315 0062;0061 05AE 1DC1 0300 0315 0062; # (aâ—Œá·â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌á·â—ŒÌ€â—ŒÌ•b; a◌֮◌á·â—ŒÌ€â—ŒÌ•b; a◌֮◌á·â—ŒÌ€â—ŒÌ•b; a◌֮◌á·â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING DOTTED ACUTE ACCENT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1DC2 0062;0061 302A 0316 1DC2 059A 0062;0061 302A 0316 1DC2 059A 0062;0061 302A 0316 1DC2 059A 0062;0061 302A 0316 1DC2 059A 0062; # (a◌֚◌̖◌〪◌᷂b; a◌〪◌̖◌᷂◌֚b; a◌〪◌̖◌᷂◌֚b; a◌〪◌̖◌᷂◌֚b; a◌〪◌̖◌᷂◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING SNAKE BELOW, LATIN SMALL LETTER B
-0061 1DC2 059A 0316 302A 0062;0061 302A 1DC2 0316 059A 0062;0061 302A 1DC2 0316 059A 0062;0061 302A 1DC2 0316 059A 0062;0061 302A 1DC2 0316 059A 0062; # (a◌᷂◌֚◌̖◌〪b; a◌〪◌᷂◌̖◌֚b; a◌〪◌᷂◌̖◌֚b; a◌〪◌᷂◌̖◌֚b; a◌〪◌᷂◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING SNAKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1DC2 0062;0061 1DFA 0316 1DC2 059A 0062;0061 1DFA 0316 1DC2 059A 0062;0061 1DFA 0316 1DC2 059A 0062;0061 1DFA 0316 1DC2 059A 0062; # (a◌֚◌̖◌᷺◌᷂b; a◌᷺◌̖◌᷂◌֚b; a◌᷺◌̖◌᷂◌֚b; a◌᷺◌̖◌᷂◌֚b; a◌᷺◌̖◌᷂◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING SNAKE BELOW, LATIN SMALL LETTER B
+0061 1DC2 059A 0316 1DFA 0062;0061 1DFA 1DC2 0316 059A 0062;0061 1DFA 1DC2 0316 059A 0062;0061 1DFA 1DC2 0316 059A 0062;0061 1DFA 1DC2 0316 059A 0062; # (a◌᷂◌֚◌̖◌᷺b; a◌᷺◌᷂◌̖◌֚b; a◌᷺◌᷂◌̖◌֚b; a◌᷺◌᷂◌̖◌֚b; a◌᷺◌᷂◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING SNAKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DC3 0062;00E0 05AE 1DC3 0315 0062;0061 05AE 0300 1DC3 0315 0062;00E0 05AE 1DC3 0315 0062;0061 05AE 0300 1DC3 0315 0062; # (a◌̕◌̀◌֮◌᷃b; à◌֮◌᷃◌̕b; a◌֮◌̀◌᷃◌̕b; à◌֮◌᷃◌̕b; a◌֮◌̀◌᷃◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING SUSPENSION MARK, LATIN SMALL LETTER B
0061 1DC3 0315 0300 05AE 0062;0061 05AE 1DC3 0300 0315 0062;0061 05AE 1DC3 0300 0315 0062;0061 05AE 1DC3 0300 0315 0062;0061 05AE 1DC3 0300 0315 0062; # (a◌᷃◌̕◌̀◌֮b; a◌֮◌᷃◌̀◌̕b; a◌֮◌᷃◌̀◌̕b; a◌֮◌᷃◌̀◌̕b; a◌֮◌᷃◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING SUSPENSION MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DC4 0062;00E0 05AE 1DC4 0315 0062;0061 05AE 0300 1DC4 0315 0062;00E0 05AE 1DC4 0315 0062;0061 05AE 0300 1DC4 0315 0062; # (a◌̕◌̀◌֮◌᷄b; à◌֮◌᷄◌̕b; a◌֮◌̀◌᷄◌̕b; à◌֮◌᷄◌̕b; a◌֮◌̀◌᷄◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING MACRON-ACUTE, LATIN SMALL LETTER B
@@ -17941,8 +18066,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1DC8 0315 0300 05AE 0062;0061 05AE 1DC8 0300 0315 0062;0061 05AE 1DC8 0300 0315 0062;0061 05AE 1DC8 0300 0315 0062;0061 05AE 1DC8 0300 0315 0062; # (a◌᷈◌̕◌̀◌֮b; a◌֮◌᷈◌̀◌̕b; a◌֮◌᷈◌̀◌̕b; a◌֮◌᷈◌̀◌̕b; a◌֮◌᷈◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING GRAVE-ACUTE-GRAVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DC9 0062;00E0 05AE 1DC9 0315 0062;0061 05AE 0300 1DC9 0315 0062;00E0 05AE 1DC9 0315 0062;0061 05AE 0300 1DC9 0315 0062; # (a◌̕◌̀◌֮◌᷉b; à◌֮◌᷉◌̕b; a◌֮◌̀◌᷉◌̕b; à◌֮◌᷉◌̕b; a◌֮◌̀◌᷉◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING ACUTE-GRAVE-ACUTE, LATIN SMALL LETTER B
0061 1DC9 0315 0300 05AE 0062;0061 05AE 1DC9 0300 0315 0062;0061 05AE 1DC9 0300 0315 0062;0061 05AE 1DC9 0300 0315 0062;0061 05AE 1DC9 0300 0315 0062; # (a◌᷉◌̕◌̀◌֮b; a◌֮◌᷉◌̀◌̕b; a◌֮◌᷉◌̀◌̕b; a◌֮◌᷉◌̀◌̕b; a◌֮◌᷉◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING ACUTE-GRAVE-ACUTE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1DCA 0062;0061 302A 0316 1DCA 059A 0062;0061 302A 0316 1DCA 059A 0062;0061 302A 0316 1DCA 059A 0062;0061 302A 0316 1DCA 059A 0062; # (a◌֚◌̖◌〪◌᷊b; a◌〪◌̖◌᷊◌֚b; a◌〪◌̖◌᷊◌֚b; a◌〪◌̖◌᷊◌֚b; a◌〪◌̖◌᷊◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LATIN SMALL LETTER R BELOW, LATIN SMALL LETTER B
-0061 1DCA 059A 0316 302A 0062;0061 302A 1DCA 0316 059A 0062;0061 302A 1DCA 0316 059A 0062;0061 302A 1DCA 0316 059A 0062;0061 302A 1DCA 0316 059A 0062; # (a◌᷊◌֚◌̖◌〪b; a◌〪◌᷊◌̖◌֚b; a◌〪◌᷊◌̖◌֚b; a◌〪◌᷊◌̖◌֚b; a◌〪◌᷊◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER R BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1DCA 0062;0061 1DFA 0316 1DCA 059A 0062;0061 1DFA 0316 1DCA 059A 0062;0061 1DFA 0316 1DCA 059A 0062;0061 1DFA 0316 1DCA 059A 0062; # (a◌֚◌̖◌᷺◌᷊b; a◌᷺◌̖◌᷊◌֚b; a◌᷺◌̖◌᷊◌֚b; a◌᷺◌̖◌᷊◌֚b; a◌᷺◌̖◌᷊◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LATIN SMALL LETTER R BELOW, LATIN SMALL LETTER B
+0061 1DCA 059A 0316 1DFA 0062;0061 1DFA 1DCA 0316 059A 0062;0061 1DFA 1DCA 0316 059A 0062;0061 1DFA 1DCA 0316 059A 0062;0061 1DFA 1DCA 0316 059A 0062; # (a◌᷊◌֚◌̖◌᷺b; a◌᷺◌᷊◌̖◌֚b; a◌᷺◌᷊◌̖◌֚b; a◌᷺◌᷊◌̖◌֚b; a◌᷺◌᷊◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LATIN SMALL LETTER R BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DCB 0062;00E0 05AE 1DCB 0315 0062;0061 05AE 0300 1DCB 0315 0062;00E0 05AE 1DCB 0315 0062;0061 05AE 0300 1DCB 0315 0062; # (a◌̕◌̀◌֮◌᷋b; à◌֮◌᷋◌̕b; a◌֮◌̀◌᷋◌̕b; à◌֮◌᷋◌̕b; a◌֮◌̀◌᷋◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING BREVE-MACRON, LATIN SMALL LETTER B
0061 1DCB 0315 0300 05AE 0062;0061 05AE 1DCB 0300 0315 0062;0061 05AE 1DCB 0300 0315 0062;0061 05AE 1DCB 0300 0315 0062;0061 05AE 1DCB 0300 0315 0062; # (a◌᷋◌̕◌̀◌֮b; a◌֮◌᷋◌̀◌̕b; a◌֮◌᷋◌̀◌̕b; a◌֮◌᷋◌̀◌̕b; a◌֮◌᷋◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING BREVE-MACRON, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DCC 0062;00E0 05AE 1DCC 0315 0062;0061 05AE 0300 1DCC 0315 0062;00E0 05AE 1DCC 0315 0062;0061 05AE 0300 1DCC 0315 0062; # (a◌̕◌̀◌֮◌᷌b; à◌֮◌᷌◌̕b; a◌֮◌̀◌᷌◌̕b; à◌֮◌᷌◌̕b; a◌֮◌̀◌᷌◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING MACRON-BREVE, LATIN SMALL LETTER B
@@ -17951,8 +18076,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1DCD 0345 035D 035C 0062;0061 035C 1DCD 035D 0345 0062;0061 035C 1DCD 035D 0345 0062;0061 035C 1DCD 035D 0345 0062;0061 035C 1DCD 035D 0345 0062; # (aâ—Œá·â—ŒÍ…â—ŒÍ◌͜b; a◌͜◌á·â—ŒÍ◌ͅb; a◌͜◌á·â—ŒÍ◌ͅb; a◌͜◌á·â—ŒÍ◌ͅb; a◌͜◌á·â—ŒÍ◌ͅb; ) LATIN SMALL LETTER A, COMBINING DOUBLE CIRCUMFLEX ABOVE, COMBINING GREEK YPOGEGRAMMENI, COMBINING DOUBLE BREVE, COMBINING DOUBLE BREVE BELOW, LATIN SMALL LETTER B
0061 031B 1DCE 0321 1DCE 0062;0061 0321 1DCE 1DCE 031B 0062;0061 0321 1DCE 1DCE 031B 0062;0061 0321 1DCE 1DCE 031B 0062;0061 0321 1DCE 1DCE 031B 0062; # (a◌̛◌᷎◌̡◌᷎b; a◌̡◌᷎◌᷎◌̛b; a◌̡◌᷎◌᷎◌̛b; a◌̡◌᷎◌᷎◌̛b; a◌̡◌᷎◌᷎◌̛b; ) LATIN SMALL LETTER A, COMBINING HORN, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
0061 1DCE 031B 1DCE 0321 0062;0061 0321 1DCE 1DCE 031B 0062;0061 0321 1DCE 1DCE 031B 0062;0061 0321 1DCE 1DCE 031B 0062;0061 0321 1DCE 1DCE 031B 0062; # (a◌᷎◌̛◌᷎◌̡b; a◌̡◌᷎◌᷎◌̛b; a◌̡◌᷎◌᷎◌̛b; a◌̡◌᷎◌᷎◌̛b; a◌̡◌᷎◌᷎◌̛b; ) LATIN SMALL LETTER A, COMBINING OGONEK ABOVE, COMBINING HORN, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, LATIN SMALL LETTER B
-0061 059A 0316 302A 1DCF 0062;0061 302A 0316 1DCF 059A 0062;0061 302A 0316 1DCF 059A 0062;0061 302A 0316 1DCF 059A 0062;0061 302A 0316 1DCF 059A 0062; # (a◌֚◌̖◌〪◌á·b; a◌〪◌̖◌á·â—ŒÖšb; a◌〪◌̖◌á·â—ŒÖšb; a◌〪◌̖◌á·â—ŒÖšb; a◌〪◌̖◌á·â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING ZIGZAG BELOW, LATIN SMALL LETTER B
-0061 1DCF 059A 0316 302A 0062;0061 302A 1DCF 0316 059A 0062;0061 302A 1DCF 0316 059A 0062;0061 302A 1DCF 0316 059A 0062;0061 302A 1DCF 0316 059A 0062; # (aâ—Œá·â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌á·â—ŒÌ–◌֚b; a◌〪◌á·â—ŒÌ–◌֚b; a◌〪◌á·â—ŒÌ–◌֚b; a◌〪◌á·â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, COMBINING ZIGZAG BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1DCF 0062;0061 1DFA 0316 1DCF 059A 0062;0061 1DFA 0316 1DCF 059A 0062;0061 1DFA 0316 1DCF 059A 0062;0061 1DFA 0316 1DCF 059A 0062; # (a◌֚◌̖◌᷺◌á·b; a◌᷺◌̖◌á·â—ŒÖšb; a◌᷺◌̖◌á·â—ŒÖšb; a◌᷺◌̖◌á·â—ŒÖšb; a◌᷺◌̖◌á·â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING ZIGZAG BELOW, LATIN SMALL LETTER B
+0061 1DCF 059A 0316 1DFA 0062;0061 1DFA 1DCF 0316 059A 0062;0061 1DFA 1DCF 0316 059A 0062;0061 1DFA 1DCF 0316 059A 0062;0061 1DFA 1DCF 0316 059A 0062; # (aâ—Œá·â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌á·â—ŒÌ–◌֚b; a◌᷺◌á·â—ŒÌ–◌֚b; a◌᷺◌á·â—ŒÌ–◌֚b; a◌᷺◌á·â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, COMBINING ZIGZAG BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 1DCE 0321 0F74 1DD0 0062;0061 0F74 0321 1DD0 1DCE 0062;0061 0F74 0321 1DD0 1DCE 0062;0061 0F74 0321 1DD0 1DCE 0062;0061 0F74 0321 1DD0 1DCE 0062; # (a◌᷎◌̡◌ུ◌á·b; a◌ུ◌̡◌á·â—Œá·Žb; a◌ུ◌̡◌á·â—Œá·Žb; a◌ུ◌̡◌á·â—Œá·Žb; a◌ུ◌̡◌á·â—Œá·Žb; ) LATIN SMALL LETTER A, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, COMBINING IS BELOW, LATIN SMALL LETTER B
0061 1DD0 1DCE 0321 0F74 0062;0061 0F74 1DD0 0321 1DCE 0062;0061 0F74 1DD0 0321 1DCE 0062;0061 0F74 1DD0 0321 1DCE 0062;0061 0F74 1DD0 0321 1DCE 0062; # (aâ—Œá·â—Œá·Žâ—ŒÌ¡â—Œà½´b; a◌ུ◌á·â—ŒÌ¡â—Œá·Žb; a◌ུ◌á·â—ŒÌ¡â—Œá·Žb; a◌ུ◌á·â—ŒÌ¡â—Œá·Žb; a◌ུ◌á·â—ŒÌ¡â—Œá·Žb; ) LATIN SMALL LETTER A, COMBINING IS BELOW, COMBINING OGONEK ABOVE, COMBINING PALATALIZED HOOK BELOW, TIBETAN VOWEL SIGN U, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DD1 0062;00E0 05AE 1DD1 0315 0062;0061 05AE 0300 1DD1 0315 0062;00E0 05AE 1DD1 0315 0062;0061 05AE 0300 1DD1 0315 0062; # (a◌̕◌̀◌֮◌᷑b; à◌֮◌᷑◌̕b; a◌֮◌̀◌᷑◌̕b; à◌֮◌᷑◌̕b; a◌֮◌̀◌᷑◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING UR ABOVE, LATIN SMALL LETTER B
@@ -18035,18 +18160,20 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1DF7 0300 05AE 1D16D 0062;00E0 1D16D 1DF7 05AE 0062;0061 1D16D 1DF7 05AE 0300 0062;00E0 1D16D 1DF7 05AE 0062;0061 1D16D 1DF7 05AE 0300 0062; # (a◌᷷◌̀◌֮ð…­b; àð…­â—Œá··â—ŒÖ®b; að…­â—Œá··â—ŒÖ®â—ŒÌ€b; àð…­â—Œá··â—ŒÖ®b; að…­â—Œá··â—ŒÖ®â—ŒÌ€b; ) LATIN SMALL LETTER A, COMBINING KAVYKA ABOVE LEFT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B
0061 0300 05AE 1D16D 1DF8 0062;00E0 1D16D 05AE 1DF8 0062;0061 1D16D 05AE 1DF8 0300 0062;00E0 1D16D 05AE 1DF8 0062;0061 1D16D 05AE 1DF8 0300 0062; # (a◌̀◌֮ð…­â—Œá·¸b; àð…­â—ŒÖ®â—Œá·¸b; að…­â—ŒÖ®â—Œá·¸â—ŒÌ€b; àð…­â—ŒÖ®â—Œá·¸b; að…­â—ŒÖ®â—Œá·¸â—ŒÌ€b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, COMBINING DOT ABOVE LEFT, LATIN SMALL LETTER B
0061 1DF8 0300 05AE 1D16D 0062;00E0 1D16D 1DF8 05AE 0062;0061 1D16D 1DF8 05AE 0300 0062;00E0 1D16D 1DF8 05AE 0062;0061 1D16D 1DF8 05AE 0300 0062; # (a◌᷸◌̀◌֮ð…­b; àð…­â—Œá·¸â—ŒÖ®b; að…­â—Œá·¸â—ŒÖ®â—ŒÌ€b; àð…­â—Œá·¸â—ŒÖ®b; að…­â—Œá·¸â—ŒÖ®â—ŒÌ€b; ) LATIN SMALL LETTER A, COMBINING DOT ABOVE LEFT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B
-0061 059A 0316 302A 1DF9 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062;0061 302A 0316 1DF9 059A 0062; # (a◌֚◌̖◌〪◌᷹b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; a◌〪◌̖◌᷹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING WIDE INVERTED BRIDGE BELOW, LATIN SMALL LETTER B
-0061 1DF9 059A 0316 302A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062;0061 302A 1DF9 0316 059A 0062; # (a◌᷹◌֚◌̖◌〪b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; a◌〪◌᷹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING WIDE INVERTED BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1DF9 0062;0061 1DFA 0316 1DF9 059A 0062;0061 1DFA 0316 1DF9 059A 0062;0061 1DFA 0316 1DF9 059A 0062;0061 1DFA 0316 1DF9 059A 0062; # (a◌֚◌̖◌᷺◌᷹b; a◌᷺◌̖◌᷹◌֚b; a◌᷺◌̖◌᷹◌֚b; a◌᷺◌̖◌᷹◌֚b; a◌᷺◌̖◌᷹◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING WIDE INVERTED BRIDGE BELOW, LATIN SMALL LETTER B
+0061 1DF9 059A 0316 1DFA 0062;0061 1DFA 1DF9 0316 059A 0062;0061 1DFA 1DF9 0316 059A 0062;0061 1DFA 1DF9 0316 059A 0062;0061 1DFA 1DF9 0316 059A 0062; # (a◌᷹◌֚◌̖◌᷺b; a◌᷺◌᷹◌̖◌֚b; a◌᷺◌᷹◌̖◌֚b; a◌᷺◌᷹◌̖◌֚b; a◌᷺◌᷹◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING WIDE INVERTED BRIDGE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0316 1DFA 031B 1DFA 0062;0061 031B 1DFA 1DFA 0316 0062;0061 031B 1DFA 1DFA 0316 0062;0061 031B 1DFA 1DFA 0316 0062;0061 031B 1DFA 1DFA 0316 0062; # (a◌̖◌᷺◌̛◌᷺b; a◌̛◌᷺◌᷺◌̖b; a◌̛◌᷺◌᷺◌̖b; a◌̛◌᷺◌᷺◌̖b; a◌̛◌᷺◌᷺◌̖b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 1DFA 0316 1DFA 031B 0062;0061 031B 1DFA 1DFA 0316 0062;0061 031B 1DFA 1DFA 0316 0062;0061 031B 1DFA 1DFA 0316 0062;0061 031B 1DFA 1DFA 0316 0062; # (a◌᷺◌̖◌᷺◌̛b; a◌̛◌᷺◌᷺◌̖b; a◌̛◌᷺◌᷺◌̖b; a◌̛◌᷺◌᷺◌̖b; a◌̛◌᷺◌᷺◌̖b; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING HORN, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DFB 0062;00E0 05AE 1DFB 0315 0062;0061 05AE 0300 1DFB 0315 0062;00E0 05AE 1DFB 0315 0062;0061 05AE 0300 1DFB 0315 0062; # (a◌̕◌̀◌֮◌᷻b; à◌֮◌᷻◌̕b; a◌֮◌̀◌᷻◌̕b; à◌֮◌᷻◌̕b; a◌֮◌̀◌᷻◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DELETION MARK, LATIN SMALL LETTER B
0061 1DFB 0315 0300 05AE 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062;0061 05AE 1DFB 0300 0315 0062; # (a◌᷻◌̕◌̀◌֮b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; a◌֮◌᷻◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DELETION MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 035D 035C 0315 1DFC 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062;0061 0315 035C 1DFC 035D 0062; # (aâ—ŒÍ◌͜◌̕◌᷼b; a◌̕◌͜◌᷼◌Íb; a◌̕◌͜◌᷼◌Íb; a◌̕◌͜◌᷼◌Íb; a◌̕◌͜◌᷼◌Íb; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING DOUBLE INVERTED BREVE BELOW, LATIN SMALL LETTER B
0061 1DFC 035D 035C 0315 0062;0061 0315 1DFC 035C 035D 0062;0061 0315 1DFC 035C 035D 0062;0061 0315 1DFC 035C 035D 0062;0061 0315 1DFC 035C 035D 0062; # (a◌᷼◌Í◌͜◌̕b; a◌̕◌᷼◌͜◌Íb; a◌̕◌᷼◌͜◌Íb; a◌̕◌᷼◌͜◌Íb; a◌̕◌᷼◌͜◌Íb; ) LATIN SMALL LETTER A, COMBINING DOUBLE INVERTED BREVE BELOW, COMBINING DOUBLE BREVE, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, LATIN SMALL LETTER B
-0061 059A 0316 302A 1DFD 0062;0061 302A 0316 1DFD 059A 0062;0061 302A 0316 1DFD 059A 0062;0061 302A 0316 1DFD 059A 0062;0061 302A 0316 1DFD 059A 0062; # (a◌֚◌̖◌〪◌᷽b; a◌〪◌̖◌᷽◌֚b; a◌〪◌̖◌᷽◌֚b; a◌〪◌̖◌᷽◌֚b; a◌〪◌̖◌᷽◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING ALMOST EQUAL TO BELOW, LATIN SMALL LETTER B
-0061 1DFD 059A 0316 302A 0062;0061 302A 1DFD 0316 059A 0062;0061 302A 1DFD 0316 059A 0062;0061 302A 1DFD 0316 059A 0062;0061 302A 1DFD 0316 059A 0062; # (a◌᷽◌֚◌̖◌〪b; a◌〪◌᷽◌̖◌֚b; a◌〪◌᷽◌̖◌֚b; a◌〪◌᷽◌̖◌֚b; a◌〪◌᷽◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING ALMOST EQUAL TO BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1DFD 0062;0061 1DFA 0316 1DFD 059A 0062;0061 1DFA 0316 1DFD 059A 0062;0061 1DFA 0316 1DFD 059A 0062;0061 1DFA 0316 1DFD 059A 0062; # (a◌֚◌̖◌᷺◌᷽b; a◌᷺◌̖◌᷽◌֚b; a◌᷺◌̖◌᷽◌֚b; a◌᷺◌̖◌᷽◌֚b; a◌᷺◌̖◌᷽◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING ALMOST EQUAL TO BELOW, LATIN SMALL LETTER B
+0061 1DFD 059A 0316 1DFA 0062;0061 1DFA 1DFD 0316 059A 0062;0061 1DFA 1DFD 0316 059A 0062;0061 1DFA 1DFD 0316 059A 0062;0061 1DFA 1DFD 0316 059A 0062; # (a◌᷽◌֚◌̖◌᷺b; a◌᷺◌᷽◌̖◌֚b; a◌᷺◌᷽◌̖◌֚b; a◌᷺◌᷽◌̖◌֚b; a◌᷺◌᷽◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING ALMOST EQUAL TO BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1DFE 0062;00E0 05AE 1DFE 0315 0062;0061 05AE 0300 1DFE 0315 0062;00E0 05AE 1DFE 0315 0062;0061 05AE 0300 1DFE 0315 0062; # (a◌̕◌̀◌֮◌᷾b; à◌֮◌᷾◌̕b; a◌֮◌̀◌᷾◌̕b; à◌֮◌᷾◌̕b; a◌֮◌̀◌᷾◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LEFT ARROWHEAD ABOVE, LATIN SMALL LETTER B
0061 1DFE 0315 0300 05AE 0062;0061 05AE 1DFE 0300 0315 0062;0061 05AE 1DFE 0300 0315 0062;0061 05AE 1DFE 0300 0315 0062;0061 05AE 1DFE 0300 0315 0062; # (a◌᷾◌̕◌̀◌֮b; a◌֮◌᷾◌̀◌̕b; a◌֮◌᷾◌̀◌̕b; a◌֮◌᷾◌̀◌̕b; a◌֮◌᷾◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING LEFT ARROWHEAD ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1DFF 0062;0061 302A 0316 1DFF 059A 0062;0061 302A 0316 1DFF 059A 0062;0061 302A 0316 1DFF 059A 0062;0061 302A 0316 1DFF 059A 0062; # (a◌֚◌̖◌〪◌᷿b; a◌〪◌̖◌᷿◌֚b; a◌〪◌̖◌᷿◌֚b; a◌〪◌̖◌᷿◌֚b; a◌〪◌̖◌᷿◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW, LATIN SMALL LETTER B
-0061 1DFF 059A 0316 302A 0062;0061 302A 1DFF 0316 059A 0062;0061 302A 1DFF 0316 059A 0062;0061 302A 1DFF 0316 059A 0062;0061 302A 1DFF 0316 059A 0062; # (a◌᷿◌֚◌̖◌〪b; a◌〪◌᷿◌̖◌֚b; a◌〪◌᷿◌̖◌֚b; a◌〪◌᷿◌̖◌֚b; a◌〪◌᷿◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1DFF 0062;0061 1DFA 0316 1DFF 059A 0062;0061 1DFA 0316 1DFF 059A 0062;0061 1DFA 0316 1DFF 059A 0062;0061 1DFA 0316 1DFF 059A 0062; # (a◌֚◌̖◌᷺◌᷿b; a◌᷺◌̖◌᷿◌֚b; a◌᷺◌̖◌᷿◌֚b; a◌᷺◌̖◌᷿◌֚b; a◌᷺◌̖◌᷿◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW, LATIN SMALL LETTER B
+0061 1DFF 059A 0316 1DFA 0062;0061 1DFA 1DFF 0316 059A 0062;0061 1DFA 1DFF 0316 059A 0062;0061 1DFA 1DFF 0316 059A 0062;0061 1DFA 1DFF 0316 059A 0062; # (a◌᷿◌֚◌̖◌᷺b; a◌᷺◌᷿◌̖◌֚b; a◌᷺◌᷿◌̖◌֚b; a◌᷺◌᷿◌̖◌֚b; a◌᷺◌᷿◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 20D0 0062;00E0 05AE 20D0 0315 0062;0061 05AE 0300 20D0 0315 0062;00E0 05AE 20D0 0315 0062;0061 05AE 0300 20D0 0315 0062; # (a◌̕◌̀◌֮◌âƒb; à◌֮◌âƒâ—ŒÌ•b; a◌֮◌̀◌âƒâ—ŒÌ•b; à◌֮◌âƒâ—ŒÌ•b; a◌֮◌̀◌âƒâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING LEFT HARPOON ABOVE, LATIN SMALL LETTER B
0061 20D0 0315 0300 05AE 0062;0061 05AE 20D0 0300 0315 0062;0061 05AE 20D0 0300 0315 0062;0061 05AE 20D0 0300 0315 0062;0061 05AE 20D0 0300 0315 0062; # (aâ—Œâƒâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌âƒâ—ŒÌ€â—ŒÌ•b; a◌֮◌âƒâ—ŒÌ€â—ŒÌ•b; a◌֮◌âƒâ—ŒÌ€â—ŒÌ•b; a◌֮◌âƒâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING LEFT HARPOON ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 20D1 0062;00E0 05AE 20D1 0315 0062;0061 05AE 0300 20D1 0315 0062;00E0 05AE 20D1 0315 0062;0061 05AE 0300 20D1 0315 0062; # (a◌̕◌̀◌֮◌⃑b; à◌֮◌⃑◌̕b; a◌֮◌̀◌⃑◌̕b; à◌֮◌⃑◌̕b; a◌֮◌̀◌⃑◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING RIGHT HARPOON ABOVE, LATIN SMALL LETTER B
@@ -18081,22 +18208,22 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 20E6 16FF0 0334 0062;0061 20E6 0334 16FF0 0062;0061 20E6 0334 16FF0 0062;0061 20E6 0334 16FF0 0062;0061 20E6 0334 16FF0 0062; # (a◌⃦𖿰◌̴b; a◌⃦◌̴𖿰b; a◌⃦◌̴𖿰b; a◌⃦◌̴𖿰b; a◌⃦◌̴𖿰b; ) LATIN SMALL LETTER A, COMBINING DOUBLE VERTICAL STROKE OVERLAY, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 0315 0300 05AE 20E7 0062;00E0 05AE 20E7 0315 0062;0061 05AE 0300 20E7 0315 0062;00E0 05AE 20E7 0315 0062;0061 05AE 0300 20E7 0315 0062; # (a◌̕◌̀◌֮◌⃧b; à◌֮◌⃧◌̕b; a◌֮◌̀◌⃧◌̕b; à◌֮◌⃧◌̕b; a◌֮◌̀◌⃧◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING ANNUITY SYMBOL, LATIN SMALL LETTER B
0061 20E7 0315 0300 05AE 0062;0061 05AE 20E7 0300 0315 0062;0061 05AE 20E7 0300 0315 0062;0061 05AE 20E7 0300 0315 0062;0061 05AE 20E7 0300 0315 0062; # (a◌⃧◌̕◌̀◌֮b; a◌֮◌⃧◌̀◌̕b; a◌֮◌⃧◌̀◌̕b; a◌֮◌⃧◌̀◌̕b; a◌֮◌⃧◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING ANNUITY SYMBOL, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 20E8 0062;0061 302A 0316 20E8 059A 0062;0061 302A 0316 20E8 059A 0062;0061 302A 0316 20E8 059A 0062;0061 302A 0316 20E8 059A 0062; # (a◌֚◌̖◌〪◌⃨b; a◌〪◌̖◌⃨◌֚b; a◌〪◌̖◌⃨◌֚b; a◌〪◌̖◌⃨◌֚b; a◌〪◌̖◌⃨◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING TRIPLE UNDERDOT, LATIN SMALL LETTER B
-0061 20E8 059A 0316 302A 0062;0061 302A 20E8 0316 059A 0062;0061 302A 20E8 0316 059A 0062;0061 302A 20E8 0316 059A 0062;0061 302A 20E8 0316 059A 0062; # (a◌⃨◌֚◌̖◌〪b; a◌〪◌⃨◌̖◌֚b; a◌〪◌⃨◌̖◌֚b; a◌〪◌⃨◌̖◌֚b; a◌〪◌⃨◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TRIPLE UNDERDOT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 20E8 0062;0061 1DFA 0316 20E8 059A 0062;0061 1DFA 0316 20E8 059A 0062;0061 1DFA 0316 20E8 059A 0062;0061 1DFA 0316 20E8 059A 0062; # (a◌֚◌̖◌᷺◌⃨b; a◌᷺◌̖◌⃨◌֚b; a◌᷺◌̖◌⃨◌֚b; a◌᷺◌̖◌⃨◌֚b; a◌᷺◌̖◌⃨◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING TRIPLE UNDERDOT, LATIN SMALL LETTER B
+0061 20E8 059A 0316 1DFA 0062;0061 1DFA 20E8 0316 059A 0062;0061 1DFA 20E8 0316 059A 0062;0061 1DFA 20E8 0316 059A 0062;0061 1DFA 20E8 0316 059A 0062; # (a◌⃨◌֚◌̖◌᷺b; a◌᷺◌⃨◌̖◌֚b; a◌᷺◌⃨◌̖◌֚b; a◌᷺◌⃨◌̖◌֚b; a◌᷺◌⃨◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TRIPLE UNDERDOT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 20E9 0062;00E0 05AE 20E9 0315 0062;0061 05AE 0300 20E9 0315 0062;00E0 05AE 20E9 0315 0062;0061 05AE 0300 20E9 0315 0062; # (a◌̕◌̀◌֮◌⃩b; à◌֮◌⃩◌̕b; a◌֮◌̀◌⃩◌̕b; à◌֮◌⃩◌̕b; a◌֮◌̀◌⃩◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING WIDE BRIDGE ABOVE, LATIN SMALL LETTER B
0061 20E9 0315 0300 05AE 0062;0061 05AE 20E9 0300 0315 0062;0061 05AE 20E9 0300 0315 0062;0061 05AE 20E9 0300 0315 0062;0061 05AE 20E9 0300 0315 0062; # (a◌⃩◌̕◌̀◌֮b; a◌֮◌⃩◌̀◌̕b; a◌֮◌⃩◌̀◌̕b; a◌֮◌⃩◌̀◌̕b; a◌֮◌⃩◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING WIDE BRIDGE ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 16FF0 0334 20EA 0062;0061 0334 20EA 16FF0 0062;0061 0334 20EA 16FF0 0062;0061 0334 20EA 16FF0 0062;0061 0334 20EA 16FF0 0062; # (a𖿰◌̴◌⃪b; a◌̴◌⃪𖿰b; a◌̴◌⃪𖿰b; a◌̴◌⃪𖿰b; a◌̴◌⃪𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, COMBINING LEFTWARDS ARROW OVERLAY, LATIN SMALL LETTER B
0061 20EA 16FF0 0334 0062;0061 20EA 0334 16FF0 0062;0061 20EA 0334 16FF0 0062;0061 20EA 0334 16FF0 0062;0061 20EA 0334 16FF0 0062; # (a◌⃪𖿰◌̴b; a◌⃪◌̴𖿰b; a◌⃪◌̴𖿰b; a◌⃪◌̴𖿰b; a◌⃪◌̴𖿰b; ) LATIN SMALL LETTER A, COMBINING LEFTWARDS ARROW OVERLAY, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 20EB 0062;0061 0334 20EB 16FF0 0062;0061 0334 20EB 16FF0 0062;0061 0334 20EB 16FF0 0062;0061 0334 20EB 16FF0 0062; # (a𖿰◌̴◌⃫b; a◌̴◌⃫𖿰b; a◌̴◌⃫𖿰b; a◌̴◌⃫𖿰b; a◌̴◌⃫𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, COMBINING LONG DOUBLE SOLIDUS OVERLAY, LATIN SMALL LETTER B
0061 20EB 16FF0 0334 0062;0061 20EB 0334 16FF0 0062;0061 20EB 0334 16FF0 0062;0061 20EB 0334 16FF0 0062;0061 20EB 0334 16FF0 0062; # (a◌⃫𖿰◌̴b; a◌⃫◌̴𖿰b; a◌⃫◌̴𖿰b; a◌⃫◌̴𖿰b; a◌⃫◌̴𖿰b; ) LATIN SMALL LETTER A, COMBINING LONG DOUBLE SOLIDUS OVERLAY, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
-0061 059A 0316 302A 20EC 0062;0061 302A 0316 20EC 059A 0062;0061 302A 0316 20EC 059A 0062;0061 302A 0316 20EC 059A 0062;0061 302A 0316 20EC 059A 0062; # (a◌֚◌̖◌〪◌⃬b; a◌〪◌̖◌⃬◌֚b; a◌〪◌̖◌⃬◌֚b; a◌〪◌̖◌⃬◌֚b; a◌〪◌̖◌⃬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS, LATIN SMALL LETTER B
-0061 20EC 059A 0316 302A 0062;0061 302A 20EC 0316 059A 0062;0061 302A 20EC 0316 059A 0062;0061 302A 20EC 0316 059A 0062;0061 302A 20EC 0316 059A 0062; # (a◌⃬◌֚◌̖◌〪b; a◌〪◌⃬◌̖◌֚b; a◌〪◌⃬◌̖◌֚b; a◌〪◌⃬◌̖◌֚b; a◌〪◌⃬◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 20ED 0062;0061 302A 0316 20ED 059A 0062;0061 302A 0316 20ED 059A 0062;0061 302A 0316 20ED 059A 0062;0061 302A 0316 20ED 059A 0062; # (a◌֚◌̖◌〪◌⃭b; a◌〪◌̖◌⃭◌֚b; a◌〪◌̖◌⃭◌֚b; a◌〪◌̖◌⃭◌֚b; a◌〪◌̖◌⃭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS, LATIN SMALL LETTER B
-0061 20ED 059A 0316 302A 0062;0061 302A 20ED 0316 059A 0062;0061 302A 20ED 0316 059A 0062;0061 302A 20ED 0316 059A 0062;0061 302A 20ED 0316 059A 0062; # (a◌⃭◌֚◌̖◌〪b; a◌〪◌⃭◌̖◌֚b; a◌〪◌⃭◌̖◌֚b; a◌〪◌⃭◌̖◌֚b; a◌〪◌⃭◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 20EE 0062;0061 302A 0316 20EE 059A 0062;0061 302A 0316 20EE 059A 0062;0061 302A 0316 20EE 059A 0062;0061 302A 0316 20EE 059A 0062; # (a◌֚◌̖◌〪◌⃮b; a◌〪◌̖◌⃮◌֚b; a◌〪◌̖◌⃮◌֚b; a◌〪◌̖◌⃮◌֚b; a◌〪◌̖◌⃮◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LEFT ARROW BELOW, LATIN SMALL LETTER B
-0061 20EE 059A 0316 302A 0062;0061 302A 20EE 0316 059A 0062;0061 302A 20EE 0316 059A 0062;0061 302A 20EE 0316 059A 0062;0061 302A 20EE 0316 059A 0062; # (a◌⃮◌֚◌̖◌〪b; a◌〪◌⃮◌̖◌֚b; a◌〪◌⃮◌̖◌֚b; a◌〪◌⃮◌̖◌֚b; a◌〪◌⃮◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 20EF 0062;0061 302A 0316 20EF 059A 0062;0061 302A 0316 20EF 059A 0062;0061 302A 0316 20EF 059A 0062;0061 302A 0316 20EF 059A 0062; # (a◌֚◌̖◌〪◌⃯b; a◌〪◌̖◌⃯◌֚b; a◌〪◌̖◌⃯◌֚b; a◌〪◌̖◌⃯◌֚b; a◌〪◌̖◌⃯◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING RIGHT ARROW BELOW, LATIN SMALL LETTER B
-0061 20EF 059A 0316 302A 0062;0061 302A 20EF 0316 059A 0062;0061 302A 20EF 0316 059A 0062;0061 302A 20EF 0316 059A 0062;0061 302A 20EF 0316 059A 0062; # (a◌⃯◌֚◌̖◌〪b; a◌〪◌⃯◌̖◌֚b; a◌〪◌⃯◌̖◌֚b; a◌〪◌⃯◌̖◌֚b; a◌〪◌⃯◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 20EC 0062;0061 1DFA 0316 20EC 059A 0062;0061 1DFA 0316 20EC 059A 0062;0061 1DFA 0316 20EC 059A 0062;0061 1DFA 0316 20EC 059A 0062; # (a◌֚◌̖◌᷺◌⃬b; a◌᷺◌̖◌⃬◌֚b; a◌᷺◌̖◌⃬◌֚b; a◌᷺◌̖◌⃬◌֚b; a◌᷺◌̖◌⃬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS, LATIN SMALL LETTER B
+0061 20EC 059A 0316 1DFA 0062;0061 1DFA 20EC 0316 059A 0062;0061 1DFA 20EC 0316 059A 0062;0061 1DFA 20EC 0316 059A 0062;0061 1DFA 20EC 0316 059A 0062; # (a◌⃬◌֚◌̖◌᷺b; a◌᷺◌⃬◌̖◌֚b; a◌᷺◌⃬◌̖◌֚b; a◌᷺◌⃬◌̖◌֚b; a◌᷺◌⃬◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 20ED 0062;0061 1DFA 0316 20ED 059A 0062;0061 1DFA 0316 20ED 059A 0062;0061 1DFA 0316 20ED 059A 0062;0061 1DFA 0316 20ED 059A 0062; # (a◌֚◌̖◌᷺◌⃭b; a◌᷺◌̖◌⃭◌֚b; a◌᷺◌̖◌⃭◌֚b; a◌᷺◌̖◌⃭◌֚b; a◌᷺◌̖◌⃭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS, LATIN SMALL LETTER B
+0061 20ED 059A 0316 1DFA 0062;0061 1DFA 20ED 0316 059A 0062;0061 1DFA 20ED 0316 059A 0062;0061 1DFA 20ED 0316 059A 0062;0061 1DFA 20ED 0316 059A 0062; # (a◌⃭◌֚◌̖◌᷺b; a◌᷺◌⃭◌̖◌֚b; a◌᷺◌⃭◌̖◌֚b; a◌᷺◌⃭◌̖◌֚b; a◌᷺◌⃭◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 20EE 0062;0061 1DFA 0316 20EE 059A 0062;0061 1DFA 0316 20EE 059A 0062;0061 1DFA 0316 20EE 059A 0062;0061 1DFA 0316 20EE 059A 0062; # (a◌֚◌̖◌᷺◌⃮b; a◌᷺◌̖◌⃮◌֚b; a◌᷺◌̖◌⃮◌֚b; a◌᷺◌̖◌⃮◌֚b; a◌᷺◌̖◌⃮◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LEFT ARROW BELOW, LATIN SMALL LETTER B
+0061 20EE 059A 0316 1DFA 0062;0061 1DFA 20EE 0316 059A 0062;0061 1DFA 20EE 0316 059A 0062;0061 1DFA 20EE 0316 059A 0062;0061 1DFA 20EE 0316 059A 0062; # (a◌⃮◌֚◌̖◌᷺b; a◌᷺◌⃮◌̖◌֚b; a◌᷺◌⃮◌̖◌֚b; a◌᷺◌⃮◌̖◌֚b; a◌᷺◌⃮◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LEFT ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 20EF 0062;0061 1DFA 0316 20EF 059A 0062;0061 1DFA 0316 20EF 059A 0062;0061 1DFA 0316 20EF 059A 0062;0061 1DFA 0316 20EF 059A 0062; # (a◌֚◌̖◌᷺◌⃯b; a◌᷺◌̖◌⃯◌֚b; a◌᷺◌̖◌⃯◌֚b; a◌᷺◌̖◌⃯◌֚b; a◌᷺◌̖◌⃯◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING RIGHT ARROW BELOW, LATIN SMALL LETTER B
+0061 20EF 059A 0316 1DFA 0062;0061 1DFA 20EF 0316 059A 0062;0061 1DFA 20EF 0316 059A 0062;0061 1DFA 20EF 0316 059A 0062;0061 1DFA 20EF 0316 059A 0062; # (a◌⃯◌֚◌̖◌᷺b; a◌᷺◌⃯◌̖◌֚b; a◌᷺◌⃯◌̖◌֚b; a◌᷺◌⃯◌̖◌֚b; a◌᷺◌⃯◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING RIGHT ARROW BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 20F0 0062;00E0 05AE 20F0 0315 0062;0061 05AE 0300 20F0 0315 0062;00E0 05AE 20F0 0315 0062;0061 05AE 0300 20F0 0315 0062; # (a◌̕◌̀◌֮◌⃰b; à◌֮◌⃰◌̕b; a◌֮◌̀◌⃰◌̕b; à◌֮◌⃰◌̕b; a◌֮◌̀◌⃰◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING ASTERISK ABOVE, LATIN SMALL LETTER B
0061 20F0 0315 0300 05AE 0062;0061 05AE 20F0 0300 0315 0062;0061 05AE 20F0 0300 0315 0062;0061 05AE 20F0 0300 0315 0062;0061 05AE 20F0 0300 0315 0062; # (a◌⃰◌̕◌̀◌֮b; a◌֮◌⃰◌̀◌̕b; a◌֮◌⃰◌̀◌̕b; a◌֮◌⃰◌̀◌̕b; a◌֮◌⃰◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING ASTERISK ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 2CEF 0062;00E0 05AE 2CEF 0315 0062;0061 05AE 0300 2CEF 0315 0062;00E0 05AE 2CEF 0315 0062;0061 05AE 0300 2CEF 0315 0062; # (a◌̕◌̀◌֮◌⳯b; à◌֮◌⳯◌̕b; a◌֮◌̀◌⳯◌̕b; à◌֮◌⳯◌̕b; a◌֮◌̀◌⳯◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COPTIC COMBINING NI ABOVE, LATIN SMALL LETTER B
@@ -18171,8 +18298,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 2DFE 0315 0300 05AE 0062;0061 05AE 2DFE 0300 0315 0062;0061 05AE 2DFE 0300 0315 0062;0061 05AE 2DFE 0300 0315 0062;0061 05AE 2DFE 0300 0315 0062; # (a◌ⷾ◌̕◌̀◌֮b; a◌֮◌ⷾ◌̀◌̕b; a◌֮◌ⷾ◌̀◌̕b; a◌֮◌ⷾ◌̀◌̕b; a◌֮◌ⷾ◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC LETTER BIG YUS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 2DFF 0062;00E0 05AE 2DFF 0315 0062;0061 05AE 0300 2DFF 0315 0062;00E0 05AE 2DFF 0315 0062;0061 05AE 0300 2DFF 0315 0062; # (a◌̕◌̀◌֮◌ⷿb; à◌֮◌ⷿ◌̕b; a◌֮◌̀◌ⷿ◌̕b; à◌֮◌ⷿ◌̕b; a◌֮◌̀◌ⷿ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING CYRILLIC LETTER IOTIFIED BIG YUS, LATIN SMALL LETTER B
0061 2DFF 0315 0300 05AE 0062;0061 05AE 2DFF 0300 0315 0062;0061 05AE 2DFF 0300 0315 0062;0061 05AE 2DFF 0300 0315 0062;0061 05AE 2DFF 0300 0315 0062; # (a◌ⷿ◌̕◌̀◌֮b; a◌֮◌ⷿ◌̀◌̕b; a◌֮◌ⷿ◌̀◌̕b; a◌֮◌ⷿ◌̀◌̕b; a◌֮◌ⷿ◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC LETTER IOTIFIED BIG YUS, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 0316 302A 031B 302A 0062;0061 031B 302A 302A 0316 0062;0061 031B 302A 302A 0316 0062;0061 031B 302A 302A 0316 0062;0061 031B 302A 302A 0316 0062; # (a◌̖◌〪◌̛◌〪b; a◌̛◌〪◌〪◌̖b; a◌̛◌〪◌〪◌̖b; a◌̛◌〪◌〪◌̖b; a◌̛◌〪◌〪◌̖b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 302A 0316 302A 031B 0062;0061 031B 302A 302A 0316 0062;0061 031B 302A 302A 0316 0062;0061 031B 302A 302A 0316 0062;0061 031B 302A 302A 0316 0062; # (a◌〪◌̖◌〪◌̛b; a◌̛◌〪◌〪◌̖b; a◌̛◌〪◌〪◌̖b; a◌̛◌〪◌〪◌̖b; a◌̛◌〪◌〪◌̖b; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, LATIN SMALL LETTER B
+0061 0316 1DFA 031B 302A 0062;0061 031B 1DFA 302A 0316 0062;0061 031B 1DFA 302A 0316 0062;0061 031B 1DFA 302A 0316 0062;0061 031B 1DFA 302A 0316 0062; # (a◌̖◌᷺◌̛◌〪b; a◌̛◌᷺◌〪◌̖b; a◌̛◌᷺◌〪◌̖b; a◌̛◌᷺◌〪◌̖b; a◌̛◌᷺◌〪◌̖b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING HORN, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 302A 0316 1DFA 031B 0062;0061 031B 302A 1DFA 0316 0062;0061 031B 302A 1DFA 0316 0062;0061 031B 302A 1DFA 0316 0062;0061 031B 302A 1DFA 0316 0062; # (a◌〪◌̖◌᷺◌̛b; a◌̛◌〪◌᷺◌̖b; a◌̛◌〪◌᷺◌̖b; a◌̛◌〪◌᷺◌̖b; a◌̛◌〪◌᷺◌̖b; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING HORN, LATIN SMALL LETTER B
0061 0300 05AE 1D16D 302B 0062;00E0 1D16D 05AE 302B 0062;0061 1D16D 05AE 302B 0300 0062;00E0 1D16D 05AE 302B 0062;0061 1D16D 05AE 302B 0300 0062; # (a◌̀◌֮ð…­â—Œã€«b; àð…­â—ŒÖ®â—Œã€«b; að…­â—ŒÖ®â—Œã€«â—ŒÌ€b; àð…­â—ŒÖ®â—Œã€«b; að…­â—ŒÖ®â—Œã€«â—ŒÌ€b; ) LATIN SMALL LETTER A, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, IDEOGRAPHIC RISING TONE MARK, LATIN SMALL LETTER B
0061 302B 0300 05AE 1D16D 0062;00E0 1D16D 302B 05AE 0062;0061 1D16D 302B 05AE 0300 0062;00E0 1D16D 302B 05AE 0062;0061 1D16D 302B 05AE 0300 0062; # (a◌〫◌̀◌֮ð…­b; àð…­â—Œã€«â—ŒÖ®b; að…­â—Œã€«â—ŒÖ®â—ŒÌ€b; àð…­â—Œã€«â—ŒÖ®b; að…­â—Œã€«â—ŒÖ®â—ŒÌ€b; ) LATIN SMALL LETTER A, IDEOGRAPHIC RISING TONE MARK, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B
0061 035C 0315 0300 302C 0062;00E0 0315 302C 035C 0062;0061 0300 0315 302C 035C 0062;00E0 0315 302C 035C 0062;0061 0300 0315 302C 035C 0062; # (a◌͜◌̕◌̀◌〬b; à◌̕◌〬◌͜b; a◌̀◌̕◌〬◌͜b; à◌̕◌〬◌͜b; a◌̀◌̕◌〬◌͜b; ) LATIN SMALL LETTER A, COMBINING DOUBLE BREVE BELOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, IDEOGRAPHIC DEPARTING TONE MARK, LATIN SMALL LETTER B
@@ -18259,12 +18386,12 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 A8F0 0315 0300 05AE 0062;0061 05AE A8F0 0300 0315 0062;0061 05AE A8F0 0300 0315 0062;0061 05AE A8F0 0300 0315 0062;0061 05AE A8F0 0300 0315 0062; # (a◌꣰◌̕◌̀◌֮b; a◌֮◌꣰◌̀◌̕b; a◌֮◌꣰◌̀◌̕b; a◌֮◌꣰◌̀◌̕b; a◌֮◌꣰◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DEVANAGARI LETTER VI, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE A8F1 0062;00E0 05AE A8F1 0315 0062;0061 05AE 0300 A8F1 0315 0062;00E0 05AE A8F1 0315 0062;0061 05AE 0300 A8F1 0315 0062; # (a◌̕◌̀◌֮◌꣱b; à◌֮◌꣱◌̕b; a◌֮◌̀◌꣱◌̕b; à◌֮◌꣱◌̕b; a◌֮◌̀◌꣱◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING DEVANAGARI SIGN AVAGRAHA, LATIN SMALL LETTER B
0061 A8F1 0315 0300 05AE 0062;0061 05AE A8F1 0300 0315 0062;0061 05AE A8F1 0300 0315 0062;0061 05AE A8F1 0300 0315 0062;0061 05AE A8F1 0300 0315 0062; # (a◌꣱◌̕◌̀◌֮b; a◌֮◌꣱◌̀◌̕b; a◌֮◌꣱◌̀◌̕b; a◌֮◌꣱◌̀◌̕b; a◌֮◌꣱◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING DEVANAGARI SIGN AVAGRAHA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A A92B 0062;0061 302A 0316 A92B 059A 0062;0061 302A 0316 A92B 059A 0062;0061 302A 0316 A92B 059A 0062;0061 302A 0316 A92B 059A 0062; # (a◌֚◌̖◌〪◌꤫b; a◌〪◌̖◌꤫◌֚b; a◌〪◌̖◌꤫◌֚b; a◌〪◌̖◌꤫◌֚b; a◌〪◌̖◌꤫◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, KAYAH LI TONE PLOPHU, LATIN SMALL LETTER B
-0061 A92B 059A 0316 302A 0062;0061 302A A92B 0316 059A 0062;0061 302A A92B 0316 059A 0062;0061 302A A92B 0316 059A 0062;0061 302A A92B 0316 059A 0062; # (a◌꤫◌֚◌̖◌〪b; a◌〪◌꤫◌̖◌֚b; a◌〪◌꤫◌̖◌֚b; a◌〪◌꤫◌̖◌֚b; a◌〪◌꤫◌̖◌֚b; ) LATIN SMALL LETTER A, KAYAH LI TONE PLOPHU, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A A92C 0062;0061 302A 0316 A92C 059A 0062;0061 302A 0316 A92C 059A 0062;0061 302A 0316 A92C 059A 0062;0061 302A 0316 A92C 059A 0062; # (a◌֚◌̖◌〪◌꤬b; a◌〪◌̖◌꤬◌֚b; a◌〪◌̖◌꤬◌֚b; a◌〪◌̖◌꤬◌֚b; a◌〪◌̖◌꤬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, KAYAH LI TONE CALYA, LATIN SMALL LETTER B
-0061 A92C 059A 0316 302A 0062;0061 302A A92C 0316 059A 0062;0061 302A A92C 0316 059A 0062;0061 302A A92C 0316 059A 0062;0061 302A A92C 0316 059A 0062; # (a◌꤬◌֚◌̖◌〪b; a◌〪◌꤬◌̖◌֚b; a◌〪◌꤬◌̖◌֚b; a◌〪◌꤬◌̖◌֚b; a◌〪◌꤬◌̖◌֚b; ) LATIN SMALL LETTER A, KAYAH LI TONE CALYA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A A92D 0062;0061 302A 0316 A92D 059A 0062;0061 302A 0316 A92D 059A 0062;0061 302A 0316 A92D 059A 0062;0061 302A 0316 A92D 059A 0062; # (a◌֚◌̖◌〪◌꤭b; a◌〪◌̖◌꤭◌֚b; a◌〪◌̖◌꤭◌֚b; a◌〪◌̖◌꤭◌֚b; a◌〪◌̖◌꤭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, KAYAH LI TONE CALYA PLOPHU, LATIN SMALL LETTER B
-0061 A92D 059A 0316 302A 0062;0061 302A A92D 0316 059A 0062;0061 302A A92D 0316 059A 0062;0061 302A A92D 0316 059A 0062;0061 302A A92D 0316 059A 0062; # (a◌꤭◌֚◌̖◌〪b; a◌〪◌꤭◌̖◌֚b; a◌〪◌꤭◌̖◌֚b; a◌〪◌꤭◌̖◌֚b; a◌〪◌꤭◌̖◌֚b; ) LATIN SMALL LETTER A, KAYAH LI TONE CALYA PLOPHU, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA A92B 0062;0061 1DFA 0316 A92B 059A 0062;0061 1DFA 0316 A92B 059A 0062;0061 1DFA 0316 A92B 059A 0062;0061 1DFA 0316 A92B 059A 0062; # (a◌֚◌̖◌᷺◌꤫b; a◌᷺◌̖◌꤫◌֚b; a◌᷺◌̖◌꤫◌֚b; a◌᷺◌̖◌꤫◌֚b; a◌᷺◌̖◌꤫◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, KAYAH LI TONE PLOPHU, LATIN SMALL LETTER B
+0061 A92B 059A 0316 1DFA 0062;0061 1DFA A92B 0316 059A 0062;0061 1DFA A92B 0316 059A 0062;0061 1DFA A92B 0316 059A 0062;0061 1DFA A92B 0316 059A 0062; # (a◌꤫◌֚◌̖◌᷺b; a◌᷺◌꤫◌̖◌֚b; a◌᷺◌꤫◌̖◌֚b; a◌᷺◌꤫◌̖◌֚b; a◌᷺◌꤫◌̖◌֚b; ) LATIN SMALL LETTER A, KAYAH LI TONE PLOPHU, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA A92C 0062;0061 1DFA 0316 A92C 059A 0062;0061 1DFA 0316 A92C 059A 0062;0061 1DFA 0316 A92C 059A 0062;0061 1DFA 0316 A92C 059A 0062; # (a◌֚◌̖◌᷺◌꤬b; a◌᷺◌̖◌꤬◌֚b; a◌᷺◌̖◌꤬◌֚b; a◌᷺◌̖◌꤬◌֚b; a◌᷺◌̖◌꤬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, KAYAH LI TONE CALYA, LATIN SMALL LETTER B
+0061 A92C 059A 0316 1DFA 0062;0061 1DFA A92C 0316 059A 0062;0061 1DFA A92C 0316 059A 0062;0061 1DFA A92C 0316 059A 0062;0061 1DFA A92C 0316 059A 0062; # (a◌꤬◌֚◌̖◌᷺b; a◌᷺◌꤬◌̖◌֚b; a◌᷺◌꤬◌̖◌֚b; a◌᷺◌꤬◌̖◌֚b; a◌᷺◌꤬◌̖◌֚b; ) LATIN SMALL LETTER A, KAYAH LI TONE CALYA, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA A92D 0062;0061 1DFA 0316 A92D 059A 0062;0061 1DFA 0316 A92D 059A 0062;0061 1DFA 0316 A92D 059A 0062;0061 1DFA 0316 A92D 059A 0062; # (a◌֚◌̖◌᷺◌꤭b; a◌᷺◌̖◌꤭◌֚b; a◌᷺◌̖◌꤭◌֚b; a◌᷺◌̖◌꤭◌֚b; a◌᷺◌̖◌꤭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, KAYAH LI TONE CALYA PLOPHU, LATIN SMALL LETTER B
+0061 A92D 059A 0316 1DFA 0062;0061 1DFA A92D 0316 059A 0062;0061 1DFA A92D 0316 059A 0062;0061 1DFA A92D 0316 059A 0062;0061 1DFA A92D 0316 059A 0062; # (a◌꤭◌֚◌̖◌᷺b; a◌᷺◌꤭◌̖◌֚b; a◌᷺◌꤭◌̖◌֚b; a◌᷺◌꤭◌̖◌֚b; a◌᷺◌꤭◌̖◌֚b; ) LATIN SMALL LETTER A, KAYAH LI TONE CALYA PLOPHU, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 05B0 094D 3099 A953 0062;0061 3099 094D A953 05B0 0062;0061 3099 094D A953 05B0 0062;0061 3099 094D A953 05B0 0062;0061 3099 094D A953 05B0 0062; # (a◌ְ◌à¥â—Œã‚™ê¥“b; a◌゙◌à¥ê¥“◌ְb; a◌゙◌à¥ê¥“◌ְb; a◌゙◌à¥ê¥“◌ְb; a◌゙◌à¥ê¥“◌ְb; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, REJANG VIRAMA, LATIN SMALL LETTER B
0061 A953 05B0 094D 3099 0062;0061 3099 A953 094D 05B0 0062;0061 3099 A953 094D 05B0 0062;0061 3099 A953 094D 05B0 0062;0061 3099 A953 094D 05B0 0062; # (a꥓◌ְ◌à¥â—Œã‚™b; a◌゙꥓◌à¥â—ŒÖ°b; a◌゙꥓◌à¥â—ŒÖ°b; a◌゙꥓◌à¥â—ŒÖ°b; a◌゙꥓◌à¥â—ŒÖ°b; ) LATIN SMALL LETTER A, REJANG VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 3099 093C 16FF0 A9B3 0062;0061 16FF0 093C A9B3 3099 0062;0061 16FF0 093C A9B3 3099 0062;0061 16FF0 093C A9B3 3099 0062;0061 16FF0 093C A9B3 3099 0062; # (a◌゙◌𖿰़◌꦳b; a𖿰◌़◌꦳◌゙b; a𖿰◌़◌꦳◌゙b; a𖿰◌़◌꦳◌゙b; a𖿰◌़◌꦳◌゙b; ) LATIN SMALL LETTER A, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, JAVANESE SIGN CECAK TELU, LATIN SMALL LETTER B
@@ -18277,8 +18404,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 AAB2 0315 0300 05AE 0062;0061 05AE AAB2 0300 0315 0062;0061 05AE AAB2 0300 0315 0062;0061 05AE AAB2 0300 0315 0062;0061 05AE AAB2 0300 0315 0062; # (a◌ꪲ◌̕◌̀◌֮b; a◌֮◌ꪲ◌̀◌̕b; a◌֮◌ꪲ◌̀◌̕b; a◌֮◌ꪲ◌̀◌̕b; a◌֮◌ꪲ◌̀◌̕b; ) LATIN SMALL LETTER A, TAI VIET VOWEL I, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE AAB3 0062;00E0 05AE AAB3 0315 0062;0061 05AE 0300 AAB3 0315 0062;00E0 05AE AAB3 0315 0062;0061 05AE 0300 AAB3 0315 0062; # (a◌̕◌̀◌֮◌ꪳb; à◌֮◌ꪳ◌̕b; a◌֮◌̀◌ꪳ◌̕b; à◌֮◌ꪳ◌̕b; a◌֮◌̀◌ꪳ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TAI VIET VOWEL UE, LATIN SMALL LETTER B
0061 AAB3 0315 0300 05AE 0062;0061 05AE AAB3 0300 0315 0062;0061 05AE AAB3 0300 0315 0062;0061 05AE AAB3 0300 0315 0062;0061 05AE AAB3 0300 0315 0062; # (a◌ꪳ◌̕◌̀◌֮b; a◌֮◌ꪳ◌̀◌̕b; a◌֮◌ꪳ◌̀◌̕b; a◌֮◌ꪳ◌̀◌̕b; a◌֮◌ꪳ◌̀◌̕b; ) LATIN SMALL LETTER A, TAI VIET VOWEL UE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A AAB4 0062;0061 302A 0316 AAB4 059A 0062;0061 302A 0316 AAB4 059A 0062;0061 302A 0316 AAB4 059A 0062;0061 302A 0316 AAB4 059A 0062; # (a◌֚◌̖◌〪◌ꪴb; a◌〪◌̖◌ꪴ◌֚b; a◌〪◌̖◌ꪴ◌֚b; a◌〪◌̖◌ꪴ◌֚b; a◌〪◌̖◌ꪴ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, TAI VIET VOWEL U, LATIN SMALL LETTER B
-0061 AAB4 059A 0316 302A 0062;0061 302A AAB4 0316 059A 0062;0061 302A AAB4 0316 059A 0062;0061 302A AAB4 0316 059A 0062;0061 302A AAB4 0316 059A 0062; # (a◌ꪴ◌֚◌̖◌〪b; a◌〪◌ꪴ◌̖◌֚b; a◌〪◌ꪴ◌̖◌֚b; a◌〪◌ꪴ◌̖◌֚b; a◌〪◌ꪴ◌̖◌֚b; ) LATIN SMALL LETTER A, TAI VIET VOWEL U, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA AAB4 0062;0061 1DFA 0316 AAB4 059A 0062;0061 1DFA 0316 AAB4 059A 0062;0061 1DFA 0316 AAB4 059A 0062;0061 1DFA 0316 AAB4 059A 0062; # (a◌֚◌̖◌᷺◌ꪴb; a◌᷺◌̖◌ꪴ◌֚b; a◌᷺◌̖◌ꪴ◌֚b; a◌᷺◌̖◌ꪴ◌֚b; a◌᷺◌̖◌ꪴ◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, TAI VIET VOWEL U, LATIN SMALL LETTER B
+0061 AAB4 059A 0316 1DFA 0062;0061 1DFA AAB4 0316 059A 0062;0061 1DFA AAB4 0316 059A 0062;0061 1DFA AAB4 0316 059A 0062;0061 1DFA AAB4 0316 059A 0062; # (a◌ꪴ◌֚◌̖◌᷺b; a◌᷺◌ꪴ◌̖◌֚b; a◌᷺◌ꪴ◌̖◌֚b; a◌᷺◌ꪴ◌̖◌֚b; a◌᷺◌ꪴ◌̖◌֚b; ) LATIN SMALL LETTER A, TAI VIET VOWEL U, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE AAB7 0062;00E0 05AE AAB7 0315 0062;0061 05AE 0300 AAB7 0315 0062;00E0 05AE AAB7 0315 0062;0061 05AE 0300 AAB7 0315 0062; # (a◌̕◌̀◌֮◌ꪷb; à◌֮◌ꪷ◌̕b; a◌֮◌̀◌ꪷ◌̕b; à◌֮◌ꪷ◌̕b; a◌֮◌̀◌ꪷ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TAI VIET MAI KHIT, LATIN SMALL LETTER B
0061 AAB7 0315 0300 05AE 0062;0061 05AE AAB7 0300 0315 0062;0061 05AE AAB7 0300 0315 0062;0061 05AE AAB7 0300 0315 0062;0061 05AE AAB7 0300 0315 0062; # (a◌ꪷ◌̕◌̀◌֮b; a◌֮◌ꪷ◌̀◌̕b; a◌֮◌ꪷ◌̀◌̕b; a◌֮◌ꪷ◌̀◌̕b; a◌֮◌ꪷ◌̀◌̕b; ) LATIN SMALL LETTER A, TAI VIET MAI KHIT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE AAB8 0062;00E0 05AE AAB8 0315 0062;0061 05AE 0300 AAB8 0315 0062;00E0 05AE AAB8 0315 0062;0061 05AE 0300 AAB8 0315 0062; # (a◌̕◌̀◌֮◌ꪸb; à◌֮◌ꪸ◌̕b; a◌֮◌̀◌ꪸ◌̕b; à◌֮◌ꪸ◌̕b; a◌֮◌̀◌ꪸ◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TAI VIET VOWEL IA, LATIN SMALL LETTER B
@@ -18309,28 +18436,28 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 FE25 0315 0300 05AE 0062;0061 05AE FE25 0300 0315 0062;0061 05AE FE25 0300 0315 0062;0061 05AE FE25 0300 0315 0062;0061 05AE FE25 0300 0315 0062; # (a◌︥◌̕◌̀◌֮b; a◌֮◌︥◌̀◌̕b; a◌֮◌︥◌̀◌̕b; a◌֮◌︥◌̀◌̕b; a◌֮◌︥◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING MACRON RIGHT HALF, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE FE26 0062;00E0 05AE FE26 0315 0062;0061 05AE 0300 FE26 0315 0062;00E0 05AE FE26 0315 0062;0061 05AE 0300 FE26 0315 0062; # (a◌̕◌̀◌֮◌︦b; à◌֮◌︦◌̕b; a◌֮◌̀◌︦◌̕b; à◌֮◌︦◌̕b; a◌֮◌̀◌︦◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING CONJOINING MACRON, LATIN SMALL LETTER B
0061 FE26 0315 0300 05AE 0062;0061 05AE FE26 0300 0315 0062;0061 05AE FE26 0300 0315 0062;0061 05AE FE26 0300 0315 0062;0061 05AE FE26 0300 0315 0062; # (a◌︦◌̕◌̀◌֮b; a◌֮◌︦◌̀◌̕b; a◌֮◌︦◌̀◌̕b; a◌֮◌︦◌̀◌̕b; a◌֮◌︦◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CONJOINING MACRON, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A FE27 0062;0061 302A 0316 FE27 059A 0062;0061 302A 0316 FE27 059A 0062;0061 302A 0316 FE27 059A 0062;0061 302A 0316 FE27 059A 0062; # (a◌֚◌̖◌〪◌︧b; a◌〪◌̖◌︧◌֚b; a◌〪◌̖◌︧◌֚b; a◌〪◌̖◌︧◌֚b; a◌〪◌̖◌︧◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LIGATURE LEFT HALF BELOW, LATIN SMALL LETTER B
-0061 FE27 059A 0316 302A 0062;0061 302A FE27 0316 059A 0062;0061 302A FE27 0316 059A 0062;0061 302A FE27 0316 059A 0062;0061 302A FE27 0316 059A 0062; # (a◌︧◌֚◌̖◌〪b; a◌〪◌︧◌̖◌֚b; a◌〪◌︧◌̖◌֚b; a◌〪◌︧◌̖◌֚b; a◌〪◌︧◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LIGATURE LEFT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A FE28 0062;0061 302A 0316 FE28 059A 0062;0061 302A 0316 FE28 059A 0062;0061 302A 0316 FE28 059A 0062;0061 302A 0316 FE28 059A 0062; # (a◌֚◌̖◌〪◌︨b; a◌〪◌̖◌︨◌֚b; a◌〪◌̖◌︨◌֚b; a◌〪◌̖◌︨◌֚b; a◌〪◌̖◌︨◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING LIGATURE RIGHT HALF BELOW, LATIN SMALL LETTER B
-0061 FE28 059A 0316 302A 0062;0061 302A FE28 0316 059A 0062;0061 302A FE28 0316 059A 0062;0061 302A FE28 0316 059A 0062;0061 302A FE28 0316 059A 0062; # (a◌︨◌֚◌̖◌〪b; a◌〪◌︨◌̖◌֚b; a◌〪◌︨◌̖◌֚b; a◌〪◌︨◌̖◌֚b; a◌〪◌︨◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LIGATURE RIGHT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A FE29 0062;0061 302A 0316 FE29 059A 0062;0061 302A 0316 FE29 059A 0062;0061 302A 0316 FE29 059A 0062;0061 302A 0316 FE29 059A 0062; # (a◌֚◌̖◌〪◌︩b; a◌〪◌̖◌︩◌֚b; a◌〪◌̖◌︩◌֚b; a◌〪◌̖◌︩◌֚b; a◌〪◌̖◌︩◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING TILDE LEFT HALF BELOW, LATIN SMALL LETTER B
-0061 FE29 059A 0316 302A 0062;0061 302A FE29 0316 059A 0062;0061 302A FE29 0316 059A 0062;0061 302A FE29 0316 059A 0062;0061 302A FE29 0316 059A 0062; # (a◌︩◌֚◌̖◌〪b; a◌〪◌︩◌̖◌֚b; a◌〪◌︩◌̖◌֚b; a◌〪◌︩◌̖◌֚b; a◌〪◌︩◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TILDE LEFT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A FE2A 0062;0061 302A 0316 FE2A 059A 0062;0061 302A 0316 FE2A 059A 0062;0061 302A 0316 FE2A 059A 0062;0061 302A 0316 FE2A 059A 0062; # (a◌֚◌̖◌〪◌︪b; a◌〪◌̖◌︪◌֚b; a◌〪◌̖◌︪◌֚b; a◌〪◌̖◌︪◌֚b; a◌〪◌̖◌︪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING TILDE RIGHT HALF BELOW, LATIN SMALL LETTER B
-0061 FE2A 059A 0316 302A 0062;0061 302A FE2A 0316 059A 0062;0061 302A FE2A 0316 059A 0062;0061 302A FE2A 0316 059A 0062;0061 302A FE2A 0316 059A 0062; # (a◌︪◌֚◌̖◌〪b; a◌〪◌︪◌̖◌֚b; a◌〪◌︪◌̖◌֚b; a◌〪◌︪◌̖◌֚b; a◌〪◌︪◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TILDE RIGHT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A FE2B 0062;0061 302A 0316 FE2B 059A 0062;0061 302A 0316 FE2B 059A 0062;0061 302A 0316 FE2B 059A 0062;0061 302A 0316 FE2B 059A 0062; # (a◌֚◌̖◌〪◌︫b; a◌〪◌̖◌︫◌֚b; a◌〪◌̖◌︫◌֚b; a◌〪◌̖◌︫◌֚b; a◌〪◌̖◌︫◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING MACRON LEFT HALF BELOW, LATIN SMALL LETTER B
-0061 FE2B 059A 0316 302A 0062;0061 302A FE2B 0316 059A 0062;0061 302A FE2B 0316 059A 0062;0061 302A FE2B 0316 059A 0062;0061 302A FE2B 0316 059A 0062; # (a◌︫◌֚◌̖◌〪b; a◌〪◌︫◌̖◌֚b; a◌〪◌︫◌̖◌֚b; a◌〪◌︫◌̖◌֚b; a◌〪◌︫◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MACRON LEFT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A FE2C 0062;0061 302A 0316 FE2C 059A 0062;0061 302A 0316 FE2C 059A 0062;0061 302A 0316 FE2C 059A 0062;0061 302A 0316 FE2C 059A 0062; # (a◌֚◌̖◌〪◌︬b; a◌〪◌̖◌︬◌֚b; a◌〪◌̖◌︬◌֚b; a◌〪◌̖◌︬◌֚b; a◌〪◌̖◌︬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING MACRON RIGHT HALF BELOW, LATIN SMALL LETTER B
-0061 FE2C 059A 0316 302A 0062;0061 302A FE2C 0316 059A 0062;0061 302A FE2C 0316 059A 0062;0061 302A FE2C 0316 059A 0062;0061 302A FE2C 0316 059A 0062; # (a◌︬◌֚◌̖◌〪b; a◌〪◌︬◌̖◌֚b; a◌〪◌︬◌̖◌֚b; a◌〪◌︬◌̖◌֚b; a◌〪◌︬◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MACRON RIGHT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A FE2D 0062;0061 302A 0316 FE2D 059A 0062;0061 302A 0316 FE2D 059A 0062;0061 302A 0316 FE2D 059A 0062;0061 302A 0316 FE2D 059A 0062; # (a◌֚◌̖◌〪◌︭b; a◌〪◌̖◌︭◌֚b; a◌〪◌̖◌︭◌֚b; a◌〪◌̖◌︭◌֚b; a◌〪◌̖◌︭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COMBINING CONJOINING MACRON BELOW, LATIN SMALL LETTER B
-0061 FE2D 059A 0316 302A 0062;0061 302A FE2D 0316 059A 0062;0061 302A FE2D 0316 059A 0062;0061 302A FE2D 0316 059A 0062;0061 302A FE2D 0316 059A 0062; # (a◌︭◌֚◌̖◌〪b; a◌〪◌︭◌̖◌֚b; a◌〪◌︭◌̖◌֚b; a◌〪◌︭◌̖◌֚b; a◌〪◌︭◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING CONJOINING MACRON BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE27 0062;0061 1DFA 0316 FE27 059A 0062;0061 1DFA 0316 FE27 059A 0062;0061 1DFA 0316 FE27 059A 0062;0061 1DFA 0316 FE27 059A 0062; # (a◌֚◌̖◌᷺◌︧b; a◌᷺◌̖◌︧◌֚b; a◌᷺◌̖◌︧◌֚b; a◌᷺◌̖◌︧◌֚b; a◌᷺◌̖◌︧◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LIGATURE LEFT HALF BELOW, LATIN SMALL LETTER B
+0061 FE27 059A 0316 1DFA 0062;0061 1DFA FE27 0316 059A 0062;0061 1DFA FE27 0316 059A 0062;0061 1DFA FE27 0316 059A 0062;0061 1DFA FE27 0316 059A 0062; # (a◌︧◌֚◌̖◌᷺b; a◌᷺◌︧◌̖◌֚b; a◌᷺◌︧◌̖◌֚b; a◌᷺◌︧◌̖◌֚b; a◌᷺◌︧◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LIGATURE LEFT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE28 0062;0061 1DFA 0316 FE28 059A 0062;0061 1DFA 0316 FE28 059A 0062;0061 1DFA 0316 FE28 059A 0062;0061 1DFA 0316 FE28 059A 0062; # (a◌֚◌̖◌᷺◌︨b; a◌᷺◌̖◌︨◌֚b; a◌᷺◌̖◌︨◌֚b; a◌᷺◌̖◌︨◌֚b; a◌᷺◌̖◌︨◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING LIGATURE RIGHT HALF BELOW, LATIN SMALL LETTER B
+0061 FE28 059A 0316 1DFA 0062;0061 1DFA FE28 0316 059A 0062;0061 1DFA FE28 0316 059A 0062;0061 1DFA FE28 0316 059A 0062;0061 1DFA FE28 0316 059A 0062; # (a◌︨◌֚◌̖◌᷺b; a◌᷺◌︨◌̖◌֚b; a◌᷺◌︨◌̖◌֚b; a◌᷺◌︨◌̖◌֚b; a◌᷺◌︨◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING LIGATURE RIGHT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE29 0062;0061 1DFA 0316 FE29 059A 0062;0061 1DFA 0316 FE29 059A 0062;0061 1DFA 0316 FE29 059A 0062;0061 1DFA 0316 FE29 059A 0062; # (a◌֚◌̖◌᷺◌︩b; a◌᷺◌̖◌︩◌֚b; a◌᷺◌̖◌︩◌֚b; a◌᷺◌̖◌︩◌֚b; a◌᷺◌̖◌︩◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING TILDE LEFT HALF BELOW, LATIN SMALL LETTER B
+0061 FE29 059A 0316 1DFA 0062;0061 1DFA FE29 0316 059A 0062;0061 1DFA FE29 0316 059A 0062;0061 1DFA FE29 0316 059A 0062;0061 1DFA FE29 0316 059A 0062; # (a◌︩◌֚◌̖◌᷺b; a◌᷺◌︩◌̖◌֚b; a◌᷺◌︩◌̖◌֚b; a◌᷺◌︩◌̖◌֚b; a◌᷺◌︩◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TILDE LEFT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE2A 0062;0061 1DFA 0316 FE2A 059A 0062;0061 1DFA 0316 FE2A 059A 0062;0061 1DFA 0316 FE2A 059A 0062;0061 1DFA 0316 FE2A 059A 0062; # (a◌֚◌̖◌᷺◌︪b; a◌᷺◌̖◌︪◌֚b; a◌᷺◌̖◌︪◌֚b; a◌᷺◌̖◌︪◌֚b; a◌᷺◌̖◌︪◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING TILDE RIGHT HALF BELOW, LATIN SMALL LETTER B
+0061 FE2A 059A 0316 1DFA 0062;0061 1DFA FE2A 0316 059A 0062;0061 1DFA FE2A 0316 059A 0062;0061 1DFA FE2A 0316 059A 0062;0061 1DFA FE2A 0316 059A 0062; # (a◌︪◌֚◌̖◌᷺b; a◌᷺◌︪◌̖◌֚b; a◌᷺◌︪◌̖◌֚b; a◌᷺◌︪◌̖◌֚b; a◌᷺◌︪◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING TILDE RIGHT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE2B 0062;0061 1DFA 0316 FE2B 059A 0062;0061 1DFA 0316 FE2B 059A 0062;0061 1DFA 0316 FE2B 059A 0062;0061 1DFA 0316 FE2B 059A 0062; # (a◌֚◌̖◌᷺◌︫b; a◌᷺◌̖◌︫◌֚b; a◌᷺◌̖◌︫◌֚b; a◌᷺◌̖◌︫◌֚b; a◌᷺◌̖◌︫◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING MACRON LEFT HALF BELOW, LATIN SMALL LETTER B
+0061 FE2B 059A 0316 1DFA 0062;0061 1DFA FE2B 0316 059A 0062;0061 1DFA FE2B 0316 059A 0062;0061 1DFA FE2B 0316 059A 0062;0061 1DFA FE2B 0316 059A 0062; # (a◌︫◌֚◌̖◌᷺b; a◌᷺◌︫◌̖◌֚b; a◌᷺◌︫◌̖◌֚b; a◌᷺◌︫◌̖◌֚b; a◌᷺◌︫◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MACRON LEFT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE2C 0062;0061 1DFA 0316 FE2C 059A 0062;0061 1DFA 0316 FE2C 059A 0062;0061 1DFA 0316 FE2C 059A 0062;0061 1DFA 0316 FE2C 059A 0062; # (a◌֚◌̖◌᷺◌︬b; a◌᷺◌̖◌︬◌֚b; a◌᷺◌̖◌︬◌֚b; a◌᷺◌̖◌︬◌֚b; a◌᷺◌̖◌︬◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING MACRON RIGHT HALF BELOW, LATIN SMALL LETTER B
+0061 FE2C 059A 0316 1DFA 0062;0061 1DFA FE2C 0316 059A 0062;0061 1DFA FE2C 0316 059A 0062;0061 1DFA FE2C 0316 059A 0062;0061 1DFA FE2C 0316 059A 0062; # (a◌︬◌֚◌̖◌᷺b; a◌᷺◌︬◌̖◌֚b; a◌᷺◌︬◌̖◌֚b; a◌᷺◌︬◌̖◌֚b; a◌᷺◌︬◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING MACRON RIGHT HALF BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA FE2D 0062;0061 1DFA 0316 FE2D 059A 0062;0061 1DFA 0316 FE2D 059A 0062;0061 1DFA 0316 FE2D 059A 0062;0061 1DFA 0316 FE2D 059A 0062; # (a◌֚◌̖◌᷺◌︭b; a◌᷺◌̖◌︭◌֚b; a◌᷺◌̖◌︭◌֚b; a◌᷺◌̖◌︭◌֚b; a◌᷺◌̖◌︭◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COMBINING CONJOINING MACRON BELOW, LATIN SMALL LETTER B
+0061 FE2D 059A 0316 1DFA 0062;0061 1DFA FE2D 0316 059A 0062;0061 1DFA FE2D 0316 059A 0062;0061 1DFA FE2D 0316 059A 0062;0061 1DFA FE2D 0316 059A 0062; # (a◌︭◌֚◌̖◌᷺b; a◌᷺◌︭◌̖◌֚b; a◌᷺◌︭◌̖◌֚b; a◌᷺◌︭◌̖◌֚b; a◌᷺◌︭◌̖◌֚b; ) LATIN SMALL LETTER A, COMBINING CONJOINING MACRON BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE FE2E 0062;00E0 05AE FE2E 0315 0062;0061 05AE 0300 FE2E 0315 0062;00E0 05AE FE2E 0315 0062;0061 05AE 0300 FE2E 0315 0062; # (a◌̕◌̀◌֮◌︮b; à◌֮◌︮◌̕b; a◌֮◌̀◌︮◌̕b; à◌֮◌︮◌̕b; a◌֮◌̀◌︮◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING CYRILLIC TITLO LEFT HALF, LATIN SMALL LETTER B
0061 FE2E 0315 0300 05AE 0062;0061 05AE FE2E 0300 0315 0062;0061 05AE FE2E 0300 0315 0062;0061 05AE FE2E 0300 0315 0062;0061 05AE FE2E 0300 0315 0062; # (a◌︮◌̕◌̀◌֮b; a◌֮◌︮◌̀◌̕b; a◌֮◌︮◌̀◌̕b; a◌֮◌︮◌̀◌̕b; a◌֮◌︮◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC TITLO LEFT HALF, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE FE2F 0062;00E0 05AE FE2F 0315 0062;0061 05AE 0300 FE2F 0315 0062;00E0 05AE FE2F 0315 0062;0061 05AE 0300 FE2F 0315 0062; # (a◌̕◌̀◌֮◌︯b; à◌֮◌︯◌̕b; a◌֮◌̀◌︯◌̕b; à◌֮◌︯◌̕b; a◌֮◌̀◌︯◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING CYRILLIC TITLO RIGHT HALF, LATIN SMALL LETTER B
0061 FE2F 0315 0300 05AE 0062;0061 05AE FE2F 0300 0315 0062;0061 05AE FE2F 0300 0315 0062;0061 05AE FE2F 0300 0315 0062;0061 05AE FE2F 0300 0315 0062; # (a◌︯◌̕◌̀◌֮b; a◌֮◌︯◌̀◌̕b; a◌֮◌︯◌̀◌̕b; a◌֮◌︯◌̀◌̕b; a◌֮◌︯◌̀◌̕b; ) LATIN SMALL LETTER A, COMBINING CYRILLIC TITLO RIGHT HALF, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 101FD 0062;0061 302A 0316 101FD 059A 0062;0061 302A 0316 101FD 059A 0062;0061 302A 0316 101FD 059A 0062;0061 302A 0316 101FD 059A 0062; # (a◌֚◌̖◌〪◌ð‡½b; a◌〪◌̖◌ð‡½â—ŒÖšb; a◌〪◌̖◌ð‡½â—ŒÖšb; a◌〪◌̖◌ð‡½â—ŒÖšb; a◌〪◌̖◌ð‡½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, LATIN SMALL LETTER B
-0061 101FD 059A 0316 302A 0062;0061 302A 101FD 0316 059A 0062;0061 302A 101FD 0316 059A 0062;0061 302A 101FD 0316 059A 0062;0061 302A 101FD 0316 059A 0062; # (aâ—Œð‡½â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð‡½â—ŒÌ–◌֚b; a◌〪◌ð‡½â—ŒÌ–◌֚b; a◌〪◌ð‡½â—ŒÌ–◌֚b; a◌〪◌ð‡½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 102E0 0062;0061 302A 0316 102E0 059A 0062;0061 302A 0316 102E0 059A 0062;0061 302A 0316 102E0 059A 0062;0061 302A 0316 102E0 059A 0062; # (a◌֚◌̖◌〪◌ð‹ b; a◌〪◌̖◌ð‹ â—ŒÖšb; a◌〪◌̖◌ð‹ â—ŒÖšb; a◌〪◌̖◌ð‹ â—ŒÖšb; a◌〪◌̖◌ð‹ â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, COPTIC EPACT THOUSANDS MARK, LATIN SMALL LETTER B
-0061 102E0 059A 0316 302A 0062;0061 302A 102E0 0316 059A 0062;0061 302A 102E0 0316 059A 0062;0061 302A 102E0 0316 059A 0062;0061 302A 102E0 0316 059A 0062; # (aâ—Œð‹ â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð‹ â—ŒÌ–◌֚b; a◌〪◌ð‹ â—ŒÌ–◌֚b; a◌〪◌ð‹ â—ŒÌ–◌֚b; a◌〪◌ð‹ â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, COPTIC EPACT THOUSANDS MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 101FD 0062;0061 1DFA 0316 101FD 059A 0062;0061 1DFA 0316 101FD 059A 0062;0061 1DFA 0316 101FD 059A 0062;0061 1DFA 0316 101FD 059A 0062; # (a◌֚◌̖◌᷺◌ð‡½b; a◌᷺◌̖◌ð‡½â—ŒÖšb; a◌᷺◌̖◌ð‡½â—ŒÖšb; a◌᷺◌̖◌ð‡½â—ŒÖšb; a◌᷺◌̖◌ð‡½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, LATIN SMALL LETTER B
+0061 101FD 059A 0316 1DFA 0062;0061 1DFA 101FD 0316 059A 0062;0061 1DFA 101FD 0316 059A 0062;0061 1DFA 101FD 0316 059A 0062;0061 1DFA 101FD 0316 059A 0062; # (aâ—Œð‡½â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð‡½â—ŒÌ–◌֚b; a◌᷺◌ð‡½â—ŒÌ–◌֚b; a◌᷺◌ð‡½â—ŒÌ–◌֚b; a◌᷺◌ð‡½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 102E0 0062;0061 1DFA 0316 102E0 059A 0062;0061 1DFA 0316 102E0 059A 0062;0061 1DFA 0316 102E0 059A 0062;0061 1DFA 0316 102E0 059A 0062; # (a◌֚◌̖◌᷺◌ð‹ b; a◌᷺◌̖◌ð‹ â—ŒÖšb; a◌᷺◌̖◌ð‹ â—ŒÖšb; a◌᷺◌̖◌ð‹ â—ŒÖšb; a◌᷺◌̖◌ð‹ â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, COPTIC EPACT THOUSANDS MARK, LATIN SMALL LETTER B
+0061 102E0 059A 0316 1DFA 0062;0061 1DFA 102E0 0316 059A 0062;0061 1DFA 102E0 0316 059A 0062;0061 1DFA 102E0 0316 059A 0062;0061 1DFA 102E0 0316 059A 0062; # (aâ—Œð‹ â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð‹ â—ŒÌ–◌֚b; a◌᷺◌ð‹ â—ŒÌ–◌֚b; a◌᷺◌ð‹ â—ŒÌ–◌֚b; a◌᷺◌ð‹ â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, COPTIC EPACT THOUSANDS MARK, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 10376 0062;00E0 05AE 10376 0315 0062;0061 05AE 0300 10376 0315 0062;00E0 05AE 10376 0315 0062;0061 05AE 0300 10376 0315 0062; # (a◌̕◌̀◌֮◌ð¶b; à◌֮◌ð¶â—ŒÌ•b; a◌֮◌̀◌ð¶â—ŒÌ•b; à◌֮◌ð¶â—ŒÌ•b; a◌֮◌̀◌ð¶â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING OLD PERMIC LETTER AN, LATIN SMALL LETTER B
0061 10376 0315 0300 05AE 0062;0061 05AE 10376 0300 0315 0062;0061 05AE 10376 0300 0315 0062;0061 05AE 10376 0300 0315 0062;0061 05AE 10376 0300 0315 0062; # (aâ—Œð¶â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð¶â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¶â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¶â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¶â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING OLD PERMIC LETTER AN, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10377 0062;00E0 05AE 10377 0315 0062;0061 05AE 0300 10377 0315 0062;00E0 05AE 10377 0315 0062;0061 05AE 0300 10377 0315 0062; # (a◌̕◌̀◌֮◌ð·b; à◌֮◌ð·â—ŒÌ•b; a◌֮◌̀◌ð·â—ŒÌ•b; à◌֮◌ð·â—ŒÌ•b; a◌֮◌̀◌ð·â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING OLD PERMIC LETTER DOI, LATIN SMALL LETTER B
@@ -18341,22 +18468,22 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 10379 0315 0300 05AE 0062;0061 05AE 10379 0300 0315 0062;0061 05AE 10379 0300 0315 0062;0061 05AE 10379 0300 0315 0062;0061 05AE 10379 0300 0315 0062; # (aâ—Œð¹â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð¹â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¹â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¹â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¹â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING OLD PERMIC LETTER NENOE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1037A 0062;00E0 05AE 1037A 0315 0062;0061 05AE 0300 1037A 0315 0062;00E0 05AE 1037A 0315 0062;0061 05AE 0300 1037A 0315 0062; # (a◌̕◌̀◌֮◌ðºb; à◌֮◌ðºâ—ŒÌ•b; a◌֮◌̀◌ðºâ—ŒÌ•b; à◌֮◌ðºâ—ŒÌ•b; a◌֮◌̀◌ðºâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, COMBINING OLD PERMIC LETTER SII, LATIN SMALL LETTER B
0061 1037A 0315 0300 05AE 0062;0061 05AE 1037A 0300 0315 0062;0061 05AE 1037A 0300 0315 0062;0061 05AE 1037A 0300 0315 0062;0061 05AE 1037A 0300 0315 0062; # (aâ—Œðºâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ðºâ—ŒÌ€â—ŒÌ•b; a◌֮◌ðºâ—ŒÌ€â—ŒÌ•b; a◌֮◌ðºâ—ŒÌ€â—ŒÌ•b; a◌֮◌ðºâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING OLD PERMIC LETTER SII, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 10A0D 0062;0061 302A 0316 10A0D 059A 0062;0061 302A 0316 10A0D 059A 0062;0061 302A 0316 10A0D 059A 0062;0061 302A 0316 10A0D 059A 0062; # (a◌֚◌̖◌〪◌ð¨b; a◌〪◌̖◌ð¨â—ŒÖšb; a◌〪◌̖◌ð¨â—ŒÖšb; a◌〪◌̖◌ð¨â—ŒÖšb; a◌〪◌̖◌ð¨â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, KHAROSHTHI SIGN DOUBLE RING BELOW, LATIN SMALL LETTER B
-0061 10A0D 059A 0316 302A 0062;0061 302A 10A0D 0316 059A 0062;0061 302A 10A0D 0316 059A 0062;0061 302A 10A0D 0316 059A 0062;0061 302A 10A0D 0316 059A 0062; # (aâ—Œð¨â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð¨â—ŒÌ–◌֚b; a◌〪◌ð¨â—ŒÌ–◌֚b; a◌〪◌ð¨â—ŒÌ–◌֚b; a◌〪◌ð¨â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN DOUBLE RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10A0D 0062;0061 1DFA 0316 10A0D 059A 0062;0061 1DFA 0316 10A0D 059A 0062;0061 1DFA 0316 10A0D 059A 0062;0061 1DFA 0316 10A0D 059A 0062; # (a◌֚◌̖◌᷺◌ð¨b; a◌᷺◌̖◌ð¨â—ŒÖšb; a◌᷺◌̖◌ð¨â—ŒÖšb; a◌᷺◌̖◌ð¨â—ŒÖšb; a◌᷺◌̖◌ð¨â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, KHAROSHTHI SIGN DOUBLE RING BELOW, LATIN SMALL LETTER B
+0061 10A0D 059A 0316 1DFA 0062;0061 1DFA 10A0D 0316 059A 0062;0061 1DFA 10A0D 0316 059A 0062;0061 1DFA 10A0D 0316 059A 0062;0061 1DFA 10A0D 0316 059A 0062; # (aâ—Œð¨â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð¨â—ŒÌ–◌֚b; a◌᷺◌ð¨â—ŒÌ–◌֚b; a◌᷺◌ð¨â—ŒÌ–◌֚b; a◌᷺◌ð¨â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN DOUBLE RING BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 10A0F 0062;00E0 05AE 10A0F 0315 0062;0061 05AE 0300 10A0F 0315 0062;00E0 05AE 10A0F 0315 0062;0061 05AE 0300 10A0F 0315 0062; # (a◌̕◌̀◌֮◌ð¨b; à◌֮◌ð¨â—ŒÌ•b; a◌֮◌̀◌ð¨â—ŒÌ•b; à◌֮◌ð¨â—ŒÌ•b; a◌֮◌̀◌ð¨â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, KHAROSHTHI SIGN VISARGA, LATIN SMALL LETTER B
0061 10A0F 0315 0300 05AE 0062;0061 05AE 10A0F 0300 0315 0062;0061 05AE 10A0F 0300 0315 0062;0061 05AE 10A0F 0300 0315 0062;0061 05AE 10A0F 0300 0315 0062; # (aâ—Œð¨â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð¨â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¨â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¨â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¨â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN VISARGA, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10A38 0062;00E0 05AE 10A38 0315 0062;0061 05AE 0300 10A38 0315 0062;00E0 05AE 10A38 0315 0062;0061 05AE 0300 10A38 0315 0062; # (a◌̕◌̀◌֮◌ð¨¸b; à◌֮◌ð¨¸â—ŒÌ•b; a◌֮◌̀◌ð¨¸â—ŒÌ•b; à◌֮◌ð¨¸â—ŒÌ•b; a◌֮◌̀◌ð¨¸â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, KHAROSHTHI SIGN BAR ABOVE, LATIN SMALL LETTER B
0061 10A38 0315 0300 05AE 0062;0061 05AE 10A38 0300 0315 0062;0061 05AE 10A38 0300 0315 0062;0061 05AE 10A38 0300 0315 0062;0061 05AE 10A38 0300 0315 0062; # (aâ—Œð¨¸â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð¨¸â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¨¸â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¨¸â—ŒÌ€â—ŒÌ•b; a◌֮◌ð¨¸â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN BAR ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 16FF0 0334 10A39 0062;0061 0334 10A39 16FF0 0062;0061 0334 10A39 16FF0 0062;0061 0334 10A39 16FF0 0062;0061 0334 10A39 16FF0 0062; # (a𖿰◌̴◌ð¨¹b; a◌̴◌ð¨¹ð–¿°b; a◌̴◌ð¨¹ð–¿°b; a◌̴◌ð¨¹ð–¿°b; a◌̴◌ð¨¹ð–¿°b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, KHAROSHTHI SIGN CAUDA, LATIN SMALL LETTER B
0061 10A39 16FF0 0334 0062;0061 10A39 0334 16FF0 0062;0061 10A39 0334 16FF0 0062;0061 10A39 0334 16FF0 0062;0061 10A39 0334 16FF0 0062; # (aâ—Œð¨¹ð–¿°â—ŒÌ´b; aâ—Œð¨¹â—ŒÌ´ð–¿°b; aâ—Œð¨¹â—ŒÌ´ð–¿°b; aâ—Œð¨¹â—ŒÌ´ð–¿°b; aâ—Œð¨¹â—ŒÌ´ð–¿°b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN CAUDA, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
-0061 059A 0316 302A 10A3A 0062;0061 302A 0316 10A3A 059A 0062;0061 302A 0316 10A3A 059A 0062;0061 302A 0316 10A3A 059A 0062;0061 302A 0316 10A3A 059A 0062; # (a◌֚◌̖◌〪◌ð¨ºb; a◌〪◌̖◌ð¨ºâ—ŒÖšb; a◌〪◌̖◌ð¨ºâ—ŒÖšb; a◌〪◌̖◌ð¨ºâ—ŒÖšb; a◌〪◌̖◌ð¨ºâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, KHAROSHTHI SIGN DOT BELOW, LATIN SMALL LETTER B
-0061 10A3A 059A 0316 302A 0062;0061 302A 10A3A 0316 059A 0062;0061 302A 10A3A 0316 059A 0062;0061 302A 10A3A 0316 059A 0062;0061 302A 10A3A 0316 059A 0062; # (aâ—Œð¨ºâ—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð¨ºâ—ŒÌ–◌֚b; a◌〪◌ð¨ºâ—ŒÌ–◌֚b; a◌〪◌ð¨ºâ—ŒÌ–◌֚b; a◌〪◌ð¨ºâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10A3A 0062;0061 1DFA 0316 10A3A 059A 0062;0061 1DFA 0316 10A3A 059A 0062;0061 1DFA 0316 10A3A 059A 0062;0061 1DFA 0316 10A3A 059A 0062; # (a◌֚◌̖◌᷺◌ð¨ºb; a◌᷺◌̖◌ð¨ºâ—ŒÖšb; a◌᷺◌̖◌ð¨ºâ—ŒÖšb; a◌᷺◌̖◌ð¨ºâ—ŒÖšb; a◌᷺◌̖◌ð¨ºâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, KHAROSHTHI SIGN DOT BELOW, LATIN SMALL LETTER B
+0061 10A3A 059A 0316 1DFA 0062;0061 1DFA 10A3A 0316 059A 0062;0061 1DFA 10A3A 0316 059A 0062;0061 1DFA 10A3A 0316 059A 0062;0061 1DFA 10A3A 0316 059A 0062; # (aâ—Œð¨ºâ—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð¨ºâ—ŒÌ–◌֚b; a◌᷺◌ð¨ºâ—ŒÌ–◌֚b; a◌᷺◌ð¨ºâ—ŒÌ–◌֚b; a◌᷺◌ð¨ºâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, KHAROSHTHI SIGN DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 05B0 094D 3099 10A3F 0062;0061 3099 094D 10A3F 05B0 0062;0061 3099 094D 10A3F 05B0 0062;0061 3099 094D 10A3F 05B0 0062;0061 3099 094D 10A3F 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œð¨¿b; a◌゙◌à¥â—Œð¨¿â—ŒÖ°b; a◌゙◌à¥â—Œð¨¿â—ŒÖ°b; a◌゙◌à¥â—Œð¨¿â—ŒÖ°b; a◌゙◌à¥â—Œð¨¿â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KHAROSHTHI VIRAMA, LATIN SMALL LETTER B
0061 10A3F 05B0 094D 3099 0062;0061 3099 10A3F 094D 05B0 0062;0061 3099 10A3F 094D 05B0 0062;0061 3099 10A3F 094D 05B0 0062;0061 3099 10A3F 094D 05B0 0062; # (aâ—Œð¨¿â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌ð¨¿â—Œà¥â—ŒÖ°b; a◌゙◌ð¨¿â—Œà¥â—ŒÖ°b; a◌゙◌ð¨¿â—Œà¥â—ŒÖ°b; a◌゙◌ð¨¿â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, KHAROSHTHI VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 0315 0300 05AE 10AE5 0062;00E0 05AE 10AE5 0315 0062;0061 05AE 0300 10AE5 0315 0062;00E0 05AE 10AE5 0315 0062;0061 05AE 0300 10AE5 0315 0062; # (a◌̕◌̀◌֮◌ð«¥b; à◌֮◌ð«¥â—ŒÌ•b; a◌֮◌̀◌ð«¥â—ŒÌ•b; à◌֮◌ð«¥â—ŒÌ•b; a◌֮◌̀◌ð«¥â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MANICHAEAN ABBREVIATION MARK ABOVE, LATIN SMALL LETTER B
0061 10AE5 0315 0300 05AE 0062;0061 05AE 10AE5 0300 0315 0062;0061 05AE 10AE5 0300 0315 0062;0061 05AE 10AE5 0300 0315 0062;0061 05AE 10AE5 0300 0315 0062; # (aâ—Œð«¥â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð«¥â—ŒÌ€â—ŒÌ•b; a◌֮◌ð«¥â—ŒÌ€â—ŒÌ•b; a◌֮◌ð«¥â—ŒÌ€â—ŒÌ•b; a◌֮◌ð«¥â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, MANICHAEAN ABBREVIATION MARK ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 10AE6 0062;0061 302A 0316 10AE6 059A 0062;0061 302A 0316 10AE6 059A 0062;0061 302A 0316 10AE6 059A 0062;0061 302A 0316 10AE6 059A 0062; # (a◌֚◌̖◌〪◌ð«¦b; a◌〪◌̖◌ð«¦â—ŒÖšb; a◌〪◌̖◌ð«¦â—ŒÖšb; a◌〪◌̖◌ð«¦â—ŒÖšb; a◌〪◌̖◌ð«¦â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MANICHAEAN ABBREVIATION MARK BELOW, LATIN SMALL LETTER B
-0061 10AE6 059A 0316 302A 0062;0061 302A 10AE6 0316 059A 0062;0061 302A 10AE6 0316 059A 0062;0061 302A 10AE6 0316 059A 0062;0061 302A 10AE6 0316 059A 0062; # (aâ—Œð«¦â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð«¦â—ŒÌ–◌֚b; a◌〪◌ð«¦â—ŒÌ–◌֚b; a◌〪◌ð«¦â—ŒÌ–◌֚b; a◌〪◌ð«¦â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MANICHAEAN ABBREVIATION MARK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10AE6 0062;0061 1DFA 0316 10AE6 059A 0062;0061 1DFA 0316 10AE6 059A 0062;0061 1DFA 0316 10AE6 059A 0062;0061 1DFA 0316 10AE6 059A 0062; # (a◌֚◌̖◌᷺◌ð«¦b; a◌᷺◌̖◌ð«¦â—ŒÖšb; a◌᷺◌̖◌ð«¦â—ŒÖšb; a◌᷺◌̖◌ð«¦â—ŒÖšb; a◌᷺◌̖◌ð«¦â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MANICHAEAN ABBREVIATION MARK BELOW, LATIN SMALL LETTER B
+0061 10AE6 059A 0316 1DFA 0062;0061 1DFA 10AE6 0316 059A 0062;0061 1DFA 10AE6 0316 059A 0062;0061 1DFA 10AE6 0316 059A 0062;0061 1DFA 10AE6 0316 059A 0062; # (aâ—Œð«¦â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð«¦â—ŒÌ–◌֚b; a◌᷺◌ð«¦â—ŒÌ–◌֚b; a◌᷺◌ð«¦â—ŒÌ–◌֚b; a◌᷺◌ð«¦â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MANICHAEAN ABBREVIATION MARK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 10D24 0062;00E0 05AE 10D24 0315 0062;0061 05AE 0300 10D24 0315 0062;00E0 05AE 10D24 0315 0062;0061 05AE 0300 10D24 0315 0062; # (a◌̕◌̀◌֮◌ð´¤b; à◌֮◌ð´¤â—ŒÌ•b; a◌֮◌̀◌ð´¤â—ŒÌ•b; à◌֮◌ð´¤â—ŒÌ•b; a◌֮◌̀◌ð´¤â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HANIFI ROHINGYA SIGN HARBAHAY, LATIN SMALL LETTER B
0061 10D24 0315 0300 05AE 0062;0061 05AE 10D24 0300 0315 0062;0061 05AE 10D24 0300 0315 0062;0061 05AE 10D24 0300 0315 0062;0061 05AE 10D24 0300 0315 0062; # (aâ—Œð´¤â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð´¤â—ŒÌ€â—ŒÌ•b; a◌֮◌ð´¤â—ŒÌ€â—ŒÌ•b; a◌֮◌ð´¤â—ŒÌ€â—ŒÌ•b; a◌֮◌ð´¤â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, HANIFI ROHINGYA SIGN HARBAHAY, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10D25 0062;00E0 05AE 10D25 0315 0062;0061 05AE 0300 10D25 0315 0062;00E0 05AE 10D25 0315 0062;0061 05AE 0300 10D25 0315 0062; # (a◌̕◌̀◌֮◌ð´¥b; à◌֮◌ð´¥â—ŒÌ•b; a◌֮◌̀◌ð´¥â—ŒÌ•b; à◌֮◌ð´¥â—ŒÌ•b; a◌֮◌̀◌ð´¥â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, HANIFI ROHINGYA SIGN TAHALA, LATIN SMALL LETTER B
@@ -18369,30 +18496,40 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 10EAB 0315 0300 05AE 0062;0061 05AE 10EAB 0300 0315 0062;0061 05AE 10EAB 0300 0315 0062;0061 05AE 10EAB 0300 0315 0062;0061 05AE 10EAB 0300 0315 0062; # (aâ—Œðº«â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ðº«â—ŒÌ€â—ŒÌ•b; a◌֮◌ðº«â—ŒÌ€â—ŒÌ•b; a◌֮◌ðº«â—ŒÌ€â—ŒÌ•b; a◌֮◌ðº«â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, YEZIDI COMBINING HAMZA MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10EAC 0062;00E0 05AE 10EAC 0315 0062;0061 05AE 0300 10EAC 0315 0062;00E0 05AE 10EAC 0315 0062;0061 05AE 0300 10EAC 0315 0062; # (a◌̕◌̀◌֮◌ðº¬b; à◌֮◌ðº¬â—ŒÌ•b; a◌֮◌̀◌ðº¬â—ŒÌ•b; à◌֮◌ðº¬â—ŒÌ•b; a◌֮◌̀◌ðº¬â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, YEZIDI COMBINING MADDA MARK, LATIN SMALL LETTER B
0061 10EAC 0315 0300 05AE 0062;0061 05AE 10EAC 0300 0315 0062;0061 05AE 10EAC 0300 0315 0062;0061 05AE 10EAC 0300 0315 0062;0061 05AE 10EAC 0300 0315 0062; # (aâ—Œðº¬â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ðº¬â—ŒÌ€â—ŒÌ•b; a◌֮◌ðº¬â—ŒÌ€â—ŒÌ•b; a◌֮◌ðº¬â—ŒÌ€â—ŒÌ•b; a◌֮◌ðº¬â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, YEZIDI COMBINING MADDA MARK, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F46 0062;0061 302A 0316 10F46 059A 0062;0061 302A 0316 10F46 059A 0062;0061 302A 0316 10F46 059A 0062;0061 302A 0316 10F46 059A 0062; # (a◌֚◌̖◌〪◌ð½†b; a◌〪◌̖◌ð½†â—ŒÖšb; a◌〪◌̖◌ð½†â—ŒÖšb; a◌〪◌̖◌ð½†â—ŒÖšb; a◌〪◌̖◌ð½†â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING DOT BELOW, LATIN SMALL LETTER B
-0061 10F46 059A 0316 302A 0062;0061 302A 10F46 0316 059A 0062;0061 302A 10F46 0316 059A 0062;0061 302A 10F46 0316 059A 0062;0061 302A 10F46 0316 059A 0062; # (aâ—Œð½†â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½†â—ŒÌ–◌֚b; a◌〪◌ð½†â—ŒÌ–◌֚b; a◌〪◌ð½†â—ŒÌ–◌֚b; a◌〪◌ð½†â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F47 0062;0061 302A 0316 10F47 059A 0062;0061 302A 0316 10F47 059A 0062;0061 302A 0316 10F47 059A 0062;0061 302A 0316 10F47 059A 0062; # (a◌֚◌̖◌〪◌ð½‡b; a◌〪◌̖◌ð½‡â—ŒÖšb; a◌〪◌̖◌ð½‡â—ŒÖšb; a◌〪◌̖◌ð½‡â—ŒÖšb; a◌〪◌̖◌ð½‡â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING TWO DOTS BELOW, LATIN SMALL LETTER B
-0061 10F47 059A 0316 302A 0062;0061 302A 10F47 0316 059A 0062;0061 302A 10F47 0316 059A 0062;0061 302A 10F47 0316 059A 0062;0061 302A 10F47 0316 059A 0062; # (aâ—Œð½‡â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½‡â—ŒÌ–◌֚b; a◌〪◌ð½‡â—ŒÌ–◌֚b; a◌〪◌ð½‡â—ŒÌ–◌֚b; a◌〪◌ð½‡â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F46 0062;0061 1DFA 0316 10F46 059A 0062;0061 1DFA 0316 10F46 059A 0062;0061 1DFA 0316 10F46 059A 0062;0061 1DFA 0316 10F46 059A 0062; # (a◌֚◌̖◌᷺◌ð½†b; a◌᷺◌̖◌ð½†â—ŒÖšb; a◌᷺◌̖◌ð½†â—ŒÖšb; a◌᷺◌̖◌ð½†â—ŒÖšb; a◌᷺◌̖◌ð½†â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING DOT BELOW, LATIN SMALL LETTER B
+0061 10F46 059A 0316 1DFA 0062;0061 1DFA 10F46 0316 059A 0062;0061 1DFA 10F46 0316 059A 0062;0061 1DFA 10F46 0316 059A 0062;0061 1DFA 10F46 0316 059A 0062; # (aâ—Œð½†â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½†â—ŒÌ–◌֚b; a◌᷺◌ð½†â—ŒÌ–◌֚b; a◌᷺◌ð½†â—ŒÌ–◌֚b; a◌᷺◌ð½†â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F47 0062;0061 1DFA 0316 10F47 059A 0062;0061 1DFA 0316 10F47 059A 0062;0061 1DFA 0316 10F47 059A 0062;0061 1DFA 0316 10F47 059A 0062; # (a◌֚◌̖◌᷺◌ð½‡b; a◌᷺◌̖◌ð½‡â—ŒÖšb; a◌᷺◌̖◌ð½‡â—ŒÖšb; a◌᷺◌̖◌ð½‡â—ŒÖšb; a◌᷺◌̖◌ð½‡â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING TWO DOTS BELOW, LATIN SMALL LETTER B
+0061 10F47 059A 0316 1DFA 0062;0061 1DFA 10F47 0316 059A 0062;0061 1DFA 10F47 0316 059A 0062;0061 1DFA 10F47 0316 059A 0062;0061 1DFA 10F47 0316 059A 0062; # (aâ—Œð½‡â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½‡â—ŒÌ–◌֚b; a◌᷺◌ð½‡â—ŒÌ–◌֚b; a◌᷺◌ð½‡â—ŒÌ–◌֚b; a◌᷺◌ð½‡â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 10F48 0062;00E0 05AE 10F48 0315 0062;0061 05AE 0300 10F48 0315 0062;00E0 05AE 10F48 0315 0062;0061 05AE 0300 10F48 0315 0062; # (a◌̕◌̀◌֮◌ð½ˆb; à◌֮◌ð½ˆâ—ŒÌ•b; a◌֮◌̀◌ð½ˆâ—ŒÌ•b; à◌֮◌ð½ˆâ—ŒÌ•b; a◌֮◌̀◌ð½ˆâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SOGDIAN COMBINING DOT ABOVE, LATIN SMALL LETTER B
0061 10F48 0315 0300 05AE 0062;0061 05AE 10F48 0300 0315 0062;0061 05AE 10F48 0300 0315 0062;0061 05AE 10F48 0300 0315 0062;0061 05AE 10F48 0300 0315 0062; # (aâ—Œð½ˆâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð½ˆâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½ˆâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½ˆâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½ˆâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING DOT ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10F49 0062;00E0 05AE 10F49 0315 0062;0061 05AE 0300 10F49 0315 0062;00E0 05AE 10F49 0315 0062;0061 05AE 0300 10F49 0315 0062; # (a◌̕◌̀◌֮◌ð½‰b; à◌֮◌ð½‰â—ŒÌ•b; a◌֮◌̀◌ð½‰â—ŒÌ•b; à◌֮◌ð½‰â—ŒÌ•b; a◌֮◌̀◌ð½‰â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SOGDIAN COMBINING TWO DOTS ABOVE, LATIN SMALL LETTER B
0061 10F49 0315 0300 05AE 0062;0061 05AE 10F49 0300 0315 0062;0061 05AE 10F49 0300 0315 0062;0061 05AE 10F49 0300 0315 0062;0061 05AE 10F49 0300 0315 0062; # (aâ—Œð½‰â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð½‰â—ŒÌ€â—ŒÌ•b; a◌֮◌ð½‰â—ŒÌ€â—ŒÌ•b; a◌֮◌ð½‰â—ŒÌ€â—ŒÌ•b; a◌֮◌ð½‰â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING TWO DOTS ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 10F4A 0062;00E0 05AE 10F4A 0315 0062;0061 05AE 0300 10F4A 0315 0062;00E0 05AE 10F4A 0315 0062;0061 05AE 0300 10F4A 0315 0062; # (a◌̕◌̀◌֮◌ð½Šb; à◌֮◌ð½Šâ—ŒÌ•b; a◌֮◌̀◌ð½Šâ—ŒÌ•b; à◌֮◌ð½Šâ—ŒÌ•b; a◌֮◌̀◌ð½Šâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SOGDIAN COMBINING CURVE ABOVE, LATIN SMALL LETTER B
0061 10F4A 0315 0300 05AE 0062;0061 05AE 10F4A 0300 0315 0062;0061 05AE 10F4A 0300 0315 0062;0061 05AE 10F4A 0300 0315 0062;0061 05AE 10F4A 0300 0315 0062; # (aâ—Œð½Šâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð½Šâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½Šâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½Šâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½Šâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING CURVE ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F4B 0062;0061 302A 0316 10F4B 059A 0062;0061 302A 0316 10F4B 059A 0062;0061 302A 0316 10F4B 059A 0062;0061 302A 0316 10F4B 059A 0062; # (a◌֚◌̖◌〪◌ð½‹b; a◌〪◌̖◌ð½‹â—ŒÖšb; a◌〪◌̖◌ð½‹â—ŒÖšb; a◌〪◌̖◌ð½‹â—ŒÖšb; a◌〪◌̖◌ð½‹â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING CURVE BELOW, LATIN SMALL LETTER B
-0061 10F4B 059A 0316 302A 0062;0061 302A 10F4B 0316 059A 0062;0061 302A 10F4B 0316 059A 0062;0061 302A 10F4B 0316 059A 0062;0061 302A 10F4B 0316 059A 0062; # (aâ—Œð½‹â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½‹â—ŒÌ–◌֚b; a◌〪◌ð½‹â—ŒÌ–◌֚b; a◌〪◌ð½‹â—ŒÌ–◌֚b; a◌〪◌ð½‹â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING CURVE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F4B 0062;0061 1DFA 0316 10F4B 059A 0062;0061 1DFA 0316 10F4B 059A 0062;0061 1DFA 0316 10F4B 059A 0062;0061 1DFA 0316 10F4B 059A 0062; # (a◌֚◌̖◌᷺◌ð½‹b; a◌᷺◌̖◌ð½‹â—ŒÖšb; a◌᷺◌̖◌ð½‹â—ŒÖšb; a◌᷺◌̖◌ð½‹â—ŒÖšb; a◌᷺◌̖◌ð½‹â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING CURVE BELOW, LATIN SMALL LETTER B
+0061 10F4B 059A 0316 1DFA 0062;0061 1DFA 10F4B 0316 059A 0062;0061 1DFA 10F4B 0316 059A 0062;0061 1DFA 10F4B 0316 059A 0062;0061 1DFA 10F4B 0316 059A 0062; # (aâ—Œð½‹â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½‹â—ŒÌ–◌֚b; a◌᷺◌ð½‹â—ŒÌ–◌֚b; a◌᷺◌ð½‹â—ŒÌ–◌֚b; a◌᷺◌ð½‹â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING CURVE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 10F4C 0062;00E0 05AE 10F4C 0315 0062;0061 05AE 0300 10F4C 0315 0062;00E0 05AE 10F4C 0315 0062;0061 05AE 0300 10F4C 0315 0062; # (a◌̕◌̀◌֮◌ð½Œb; à◌֮◌ð½Œâ—ŒÌ•b; a◌֮◌̀◌ð½Œâ—ŒÌ•b; à◌֮◌ð½Œâ—ŒÌ•b; a◌֮◌̀◌ð½Œâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, SOGDIAN COMBINING HOOK ABOVE, LATIN SMALL LETTER B
0061 10F4C 0315 0300 05AE 0062;0061 05AE 10F4C 0300 0315 0062;0061 05AE 10F4C 0300 0315 0062;0061 05AE 10F4C 0300 0315 0062;0061 05AE 10F4C 0300 0315 0062; # (aâ—Œð½Œâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð½Œâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½Œâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½Œâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð½Œâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING HOOK ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F4D 0062;0061 302A 0316 10F4D 059A 0062;0061 302A 0316 10F4D 059A 0062;0061 302A 0316 10F4D 059A 0062;0061 302A 0316 10F4D 059A 0062; # (a◌֚◌̖◌〪◌ð½b; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING HOOK BELOW, LATIN SMALL LETTER B
-0061 10F4D 059A 0316 302A 0062;0061 302A 10F4D 0316 059A 0062;0061 302A 10F4D 0316 059A 0062;0061 302A 10F4D 0316 059A 0062;0061 302A 10F4D 0316 059A 0062; # (aâ—Œð½â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING HOOK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F4E 0062;0061 302A 0316 10F4E 059A 0062;0061 302A 0316 10F4E 059A 0062;0061 302A 0316 10F4E 059A 0062;0061 302A 0316 10F4E 059A 0062; # (a◌֚◌̖◌〪◌ð½Žb; a◌〪◌̖◌ð½Žâ—ŒÖšb; a◌〪◌̖◌ð½Žâ—ŒÖšb; a◌〪◌̖◌ð½Žâ—ŒÖšb; a◌〪◌̖◌ð½Žâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING LONG HOOK BELOW, LATIN SMALL LETTER B
-0061 10F4E 059A 0316 302A 0062;0061 302A 10F4E 0316 059A 0062;0061 302A 10F4E 0316 059A 0062;0061 302A 10F4E 0316 059A 0062;0061 302A 10F4E 0316 059A 0062; # (aâ—Œð½Žâ—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½Žâ—ŒÌ–◌֚b; a◌〪◌ð½Žâ—ŒÌ–◌֚b; a◌〪◌ð½Žâ—ŒÌ–◌֚b; a◌〪◌ð½Žâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING LONG HOOK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F4F 0062;0061 302A 0316 10F4F 059A 0062;0061 302A 0316 10F4F 059A 0062;0061 302A 0316 10F4F 059A 0062;0061 302A 0316 10F4F 059A 0062; # (a◌֚◌̖◌〪◌ð½b; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING RESH BELOW, LATIN SMALL LETTER B
-0061 10F4F 059A 0316 302A 0062;0061 302A 10F4F 0316 059A 0062;0061 302A 10F4F 0316 059A 0062;0061 302A 10F4F 0316 059A 0062;0061 302A 10F4F 0316 059A 0062; # (aâ—Œð½â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING RESH BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 10F50 0062;0061 302A 0316 10F50 059A 0062;0061 302A 0316 10F50 059A 0062;0061 302A 0316 10F50 059A 0062;0061 302A 0316 10F50 059A 0062; # (a◌֚◌̖◌〪◌ð½b; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; a◌〪◌̖◌ð½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, SOGDIAN COMBINING STROKE BELOW, LATIN SMALL LETTER B
-0061 10F50 059A 0316 302A 0062;0061 302A 10F50 0316 059A 0062;0061 302A 10F50 0316 059A 0062;0061 302A 10F50 0316 059A 0062;0061 302A 10F50 0316 059A 0062; # (aâ—Œð½â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; a◌〪◌ð½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING STROKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F4D 0062;0061 1DFA 0316 10F4D 059A 0062;0061 1DFA 0316 10F4D 059A 0062;0061 1DFA 0316 10F4D 059A 0062;0061 1DFA 0316 10F4D 059A 0062; # (a◌֚◌̖◌᷺◌ð½b; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING HOOK BELOW, LATIN SMALL LETTER B
+0061 10F4D 059A 0316 1DFA 0062;0061 1DFA 10F4D 0316 059A 0062;0061 1DFA 10F4D 0316 059A 0062;0061 1DFA 10F4D 0316 059A 0062;0061 1DFA 10F4D 0316 059A 0062; # (aâ—Œð½â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING HOOK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F4E 0062;0061 1DFA 0316 10F4E 059A 0062;0061 1DFA 0316 10F4E 059A 0062;0061 1DFA 0316 10F4E 059A 0062;0061 1DFA 0316 10F4E 059A 0062; # (a◌֚◌̖◌᷺◌ð½Žb; a◌᷺◌̖◌ð½Žâ—ŒÖšb; a◌᷺◌̖◌ð½Žâ—ŒÖšb; a◌᷺◌̖◌ð½Žâ—ŒÖšb; a◌᷺◌̖◌ð½Žâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING LONG HOOK BELOW, LATIN SMALL LETTER B
+0061 10F4E 059A 0316 1DFA 0062;0061 1DFA 10F4E 0316 059A 0062;0061 1DFA 10F4E 0316 059A 0062;0061 1DFA 10F4E 0316 059A 0062;0061 1DFA 10F4E 0316 059A 0062; # (aâ—Œð½Žâ—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½Žâ—ŒÌ–◌֚b; a◌᷺◌ð½Žâ—ŒÌ–◌֚b; a◌᷺◌ð½Žâ—ŒÌ–◌֚b; a◌᷺◌ð½Žâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING LONG HOOK BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F4F 0062;0061 1DFA 0316 10F4F 059A 0062;0061 1DFA 0316 10F4F 059A 0062;0061 1DFA 0316 10F4F 059A 0062;0061 1DFA 0316 10F4F 059A 0062; # (a◌֚◌̖◌᷺◌ð½b; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING RESH BELOW, LATIN SMALL LETTER B
+0061 10F4F 059A 0316 1DFA 0062;0061 1DFA 10F4F 0316 059A 0062;0061 1DFA 10F4F 0316 059A 0062;0061 1DFA 10F4F 0316 059A 0062;0061 1DFA 10F4F 0316 059A 0062; # (aâ—Œð½â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING RESH BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F50 0062;0061 1DFA 0316 10F50 059A 0062;0061 1DFA 0316 10F50 059A 0062;0061 1DFA 0316 10F50 059A 0062;0061 1DFA 0316 10F50 059A 0062; # (a◌֚◌̖◌᷺◌ð½b; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; a◌᷺◌̖◌ð½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, SOGDIAN COMBINING STROKE BELOW, LATIN SMALL LETTER B
+0061 10F50 059A 0316 1DFA 0062;0061 1DFA 10F50 0316 059A 0062;0061 1DFA 10F50 0316 059A 0062;0061 1DFA 10F50 0316 059A 0062;0061 1DFA 10F50 0316 059A 0062; # (aâ—Œð½â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; a◌᷺◌ð½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, SOGDIAN COMBINING STROKE BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 10F82 0062;00E0 05AE 10F82 0315 0062;0061 05AE 0300 10F82 0315 0062;00E0 05AE 10F82 0315 0062;0061 05AE 0300 10F82 0315 0062; # (a◌̕◌̀◌֮◌ð¾‚b; à◌֮◌ð¾‚◌̕b; a◌֮◌̀◌ð¾‚◌̕b; à◌֮◌ð¾‚◌̕b; a◌֮◌̀◌ð¾‚◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, OLD UYGHUR COMBINING DOT ABOVE, LATIN SMALL LETTER B
+0061 10F82 0315 0300 05AE 0062;0061 05AE 10F82 0300 0315 0062;0061 05AE 10F82 0300 0315 0062;0061 05AE 10F82 0300 0315 0062;0061 05AE 10F82 0300 0315 0062; # (aâ—Œð¾‚◌̕◌̀◌֮b; a◌֮◌ð¾‚◌̀◌̕b; a◌֮◌ð¾‚◌̀◌̕b; a◌֮◌ð¾‚◌̀◌̕b; a◌֮◌ð¾‚◌̀◌̕b; ) LATIN SMALL LETTER A, OLD UYGHUR COMBINING DOT ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F83 0062;0061 1DFA 0316 10F83 059A 0062;0061 1DFA 0316 10F83 059A 0062;0061 1DFA 0316 10F83 059A 0062;0061 1DFA 0316 10F83 059A 0062; # (a◌֚◌̖◌᷺◌ð¾ƒb; a◌᷺◌̖◌ð¾ƒâ—ŒÖšb; a◌᷺◌̖◌ð¾ƒâ—ŒÖšb; a◌᷺◌̖◌ð¾ƒâ—ŒÖšb; a◌᷺◌̖◌ð¾ƒâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, OLD UYGHUR COMBINING DOT BELOW, LATIN SMALL LETTER B
+0061 10F83 059A 0316 1DFA 0062;0061 1DFA 10F83 0316 059A 0062;0061 1DFA 10F83 0316 059A 0062;0061 1DFA 10F83 0316 059A 0062;0061 1DFA 10F83 0316 059A 0062; # (aâ—Œð¾ƒâ—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð¾ƒâ—ŒÌ–◌֚b; a◌᷺◌ð¾ƒâ—ŒÌ–◌֚b; a◌᷺◌ð¾ƒâ—ŒÌ–◌֚b; a◌᷺◌ð¾ƒâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, OLD UYGHUR COMBINING DOT BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 0315 0300 05AE 10F84 0062;00E0 05AE 10F84 0315 0062;0061 05AE 0300 10F84 0315 0062;00E0 05AE 10F84 0315 0062;0061 05AE 0300 10F84 0315 0062; # (a◌̕◌̀◌֮◌ð¾„b; à◌֮◌ð¾„◌̕b; a◌֮◌̀◌ð¾„◌̕b; à◌֮◌ð¾„◌̕b; a◌֮◌̀◌ð¾„◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, OLD UYGHUR COMBINING TWO DOTS ABOVE, LATIN SMALL LETTER B
+0061 10F84 0315 0300 05AE 0062;0061 05AE 10F84 0300 0315 0062;0061 05AE 10F84 0300 0315 0062;0061 05AE 10F84 0300 0315 0062;0061 05AE 10F84 0300 0315 0062; # (aâ—Œð¾„◌̕◌̀◌֮b; a◌֮◌ð¾„◌̀◌̕b; a◌֮◌ð¾„◌̀◌̕b; a◌֮◌ð¾„◌̀◌̕b; a◌֮◌ð¾„◌̀◌̕b; ) LATIN SMALL LETTER A, OLD UYGHUR COMBINING TWO DOTS ABOVE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 10F85 0062;0061 1DFA 0316 10F85 059A 0062;0061 1DFA 0316 10F85 059A 0062;0061 1DFA 0316 10F85 059A 0062;0061 1DFA 0316 10F85 059A 0062; # (a◌֚◌̖◌᷺◌ð¾…b; a◌᷺◌̖◌ð¾…◌֚b; a◌᷺◌̖◌ð¾…◌֚b; a◌᷺◌̖◌ð¾…◌֚b; a◌᷺◌̖◌ð¾…◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, OLD UYGHUR COMBINING TWO DOTS BELOW, LATIN SMALL LETTER B
+0061 10F85 059A 0316 1DFA 0062;0061 1DFA 10F85 0316 059A 0062;0061 1DFA 10F85 0316 059A 0062;0061 1DFA 10F85 0316 059A 0062;0061 1DFA 10F85 0316 059A 0062; # (aâ—Œð¾…◌֚◌̖◌᷺b; a◌᷺◌ð¾…◌̖◌֚b; a◌᷺◌ð¾…◌̖◌֚b; a◌᷺◌ð¾…◌̖◌֚b; a◌᷺◌ð¾…◌̖◌֚b; ) LATIN SMALL LETTER A, OLD UYGHUR COMBINING TWO DOTS BELOW, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 05B0 094D 3099 11046 0062;0061 3099 094D 11046 05B0 0062;0061 3099 094D 11046 05B0 0062;0061 3099 094D 11046 05B0 0062;0061 3099 094D 11046 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œð‘†b; a◌゙◌à¥â—Œð‘†â—ŒÖ°b; a◌゙◌à¥â—Œð‘†â—ŒÖ°b; a◌゙◌à¥â—Œð‘†â—ŒÖ°b; a◌゙◌à¥â—Œð‘†â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, BRAHMI VIRAMA, LATIN SMALL LETTER B
0061 11046 05B0 094D 3099 0062;0061 3099 11046 094D 05B0 0062;0061 3099 11046 094D 05B0 0062;0061 3099 11046 094D 05B0 0062;0061 3099 11046 094D 05B0 0062; # (aâ—Œð‘†â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌ð‘†â—Œà¥â—ŒÖ°b; a◌゙◌ð‘†â—Œà¥â—ŒÖ°b; a◌゙◌ð‘†â—Œà¥â—ŒÖ°b; a◌゙◌ð‘†â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, BRAHMI VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
+0061 05B0 094D 3099 11070 0062;0061 3099 094D 11070 05B0 0062;0061 3099 094D 11070 05B0 0062;0061 3099 094D 11070 05B0 0062;0061 3099 094D 11070 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œð‘°b; a◌゙◌à¥â—Œð‘°â—ŒÖ°b; a◌゙◌à¥â—Œð‘°â—ŒÖ°b; a◌゙◌à¥â—Œð‘°â—ŒÖ°b; a◌゙◌à¥â—Œð‘°â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, BRAHMI SIGN OLD TAMIL VIRAMA, LATIN SMALL LETTER B
+0061 11070 05B0 094D 3099 0062;0061 3099 11070 094D 05B0 0062;0061 3099 11070 094D 05B0 0062;0061 3099 11070 094D 05B0 0062;0061 3099 11070 094D 05B0 0062; # (aâ—Œð‘°â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌ð‘°â—Œà¥â—ŒÖ°b; a◌゙◌ð‘°â—Œà¥â—ŒÖ°b; a◌゙◌ð‘°â—Œà¥â—ŒÖ°b; a◌゙◌ð‘°â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, BRAHMI SIGN OLD TAMIL VIRAMA, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 1107F 0062;0061 3099 094D 1107F 05B0 0062;0061 3099 094D 1107F 05B0 0062;0061 3099 094D 1107F 05B0 0062;0061 3099 094D 1107F 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œð‘¿b; a◌゙◌à¥â—Œð‘¿â—ŒÖ°b; a◌゙◌à¥â—Œð‘¿â—ŒÖ°b; a◌゙◌à¥â—Œð‘¿â—ŒÖ°b; a◌゙◌à¥â—Œð‘¿â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, BRAHMI NUMBER JOINER, LATIN SMALL LETTER B
0061 1107F 05B0 094D 3099 0062;0061 3099 1107F 094D 05B0 0062;0061 3099 1107F 094D 05B0 0062;0061 3099 1107F 094D 05B0 0062;0061 3099 1107F 094D 05B0 0062; # (aâ—Œð‘¿â—ŒÖ°â—Œà¥â—Œã‚™b; a◌゙◌ð‘¿â—Œà¥â—ŒÖ°b; a◌゙◌ð‘¿â—Œà¥â—ŒÖ°b; a◌゙◌ð‘¿â—Œà¥â—ŒÖ°b; a◌゙◌ð‘¿â—Œà¥â—ŒÖ°b; ) LATIN SMALL LETTER A, BRAHMI NUMBER JOINER, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, LATIN SMALL LETTER B
0061 05B0 094D 3099 110B9 0062;0061 3099 094D 110B9 05B0 0062;0061 3099 094D 110B9 05B0 0062;0061 3099 094D 110B9 05B0 0062;0061 3099 094D 110B9 05B0 0062; # (a◌ְ◌à¥â—Œã‚™â—Œð‘‚¹b; a◌゙◌à¥â—Œð‘‚¹â—ŒÖ°b; a◌゙◌à¥â—Œð‘‚¹â—ŒÖ°b; a◌゙◌à¥â—Œð‘‚¹â—ŒÖ°b; a◌゙◌à¥â—Œð‘‚¹â—ŒÖ°b; ) LATIN SMALL LETTER A, HEBREW POINT SHEVA, DEVANAGARI SIGN VIRAMA, COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK, KAITHI SIGN VIRAMA, LATIN SMALL LETTER B
@@ -18533,10 +18670,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 16FF1 093C 16FF0 0334 0062;0061 0334 16FF1 16FF0 093C 0062;0061 0334 16FF1 16FF0 093C 0062;0061 0334 16FF1 16FF0 093C 0062;0061 0334 16FF1 16FF0 093C 0062; # (a𖿱◌𖿰़◌̴b; a◌̴𖿱𖿰◌़b; a◌̴𖿱𖿰◌़b; a◌̴𖿱𖿰◌़b; a◌̴𖿱𖿰◌़b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK NHAY, DEVANAGARI SIGN NUKTA, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 1BC9E 0062;0061 0334 1BC9E 16FF0 0062;0061 0334 1BC9E 16FF0 0062;0061 0334 1BC9E 16FF0 0062;0061 0334 1BC9E 16FF0 0062; # (a𖿰◌̴◌𛲞b; a◌̴◌𛲞𖿰b; a◌̴◌𛲞𖿰b; a◌̴◌𛲞𖿰b; a◌̴◌𛲞𖿰b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, DUPLOYAN DOUBLE MARK, LATIN SMALL LETTER B
0061 1BC9E 16FF0 0334 0062;0061 1BC9E 0334 16FF0 0062;0061 1BC9E 0334 16FF0 0062;0061 1BC9E 0334 16FF0 0062;0061 1BC9E 0334 16FF0 0062; # (a◌𛲞𖿰◌̴b; a◌𛲞◌̴𖿰b; a◌𛲞◌̴𖿰b; a◌𛲞◌̴𖿰b; a◌𛲞◌̴𖿰b; ) LATIN SMALL LETTER A, DUPLOYAN DOUBLE MARK, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D165 0062;0061 1DCE 031B 1D165 302A 0062;0061 1DCE 031B 1D165 302A 0062;0061 1DCE 031B 1D165 302A 0062;0061 1DCE 031B 1D165 302A 0062; # (a◌〪◌̛◌᷎ð…¥b; a◌᷎◌̛ð…¥â—Œã€ªb; a◌᷎◌̛ð…¥â—Œã€ªb; a◌᷎◌̛ð…¥â—Œã€ªb; a◌᷎◌̛ð…¥â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING STEM, LATIN SMALL LETTER B
-0061 1D165 302A 031B 1DCE 0062;0061 1DCE 1D165 031B 302A 0062;0061 1DCE 1D165 031B 302A 0062;0061 1DCE 1D165 031B 302A 0062;0061 1DCE 1D165 031B 302A 0062; # (að…¥â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…¥â—ŒÌ›â—Œã€ªb; a◌᷎ð…¥â—ŒÌ›â—Œã€ªb; a◌᷎ð…¥â—ŒÌ›â—Œã€ªb; a◌᷎ð…¥â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING STEM, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D166 0062;0061 1DCE 031B 1D166 302A 0062;0061 1DCE 031B 1D166 302A 0062;0061 1DCE 031B 1D166 302A 0062;0061 1DCE 031B 1D166 302A 0062; # (a◌〪◌̛◌᷎ð…¦b; a◌᷎◌̛ð…¦â—Œã€ªb; a◌᷎◌̛ð…¦â—Œã€ªb; a◌᷎◌̛ð…¦â—Œã€ªb; a◌᷎◌̛ð…¦â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING SPRECHGESANG STEM, LATIN SMALL LETTER B
-0061 1D166 302A 031B 1DCE 0062;0061 1DCE 1D166 031B 302A 0062;0061 1DCE 1D166 031B 302A 0062;0061 1DCE 1D166 031B 302A 0062;0061 1DCE 1D166 031B 302A 0062; # (að…¦â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…¦â—ŒÌ›â—Œã€ªb; a◌᷎ð…¦â—ŒÌ›â—Œã€ªb; a◌᷎ð…¦â—ŒÌ›â—Œã€ªb; a◌᷎ð…¦â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING SPRECHGESANG STEM, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D165 0062;0061 1DCE 031B 1D165 1DFA 0062;0061 1DCE 031B 1D165 1DFA 0062;0061 1DCE 031B 1D165 1DFA 0062;0061 1DCE 031B 1D165 1DFA 0062; # (a◌᷺◌̛◌᷎ð…¥b; a◌᷎◌̛ð…¥â—Œá·ºb; a◌᷎◌̛ð…¥â—Œá·ºb; a◌᷎◌̛ð…¥â—Œá·ºb; a◌᷎◌̛ð…¥â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING STEM, LATIN SMALL LETTER B
+0061 1D165 1DFA 031B 1DCE 0062;0061 1DCE 1D165 031B 1DFA 0062;0061 1DCE 1D165 031B 1DFA 0062;0061 1DCE 1D165 031B 1DFA 0062;0061 1DCE 1D165 031B 1DFA 0062; # (að…¥â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…¥â—ŒÌ›â—Œá·ºb; a◌᷎ð…¥â—ŒÌ›â—Œá·ºb; a◌᷎ð…¥â—ŒÌ›â—Œá·ºb; a◌᷎ð…¥â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING STEM, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D166 0062;0061 1DCE 031B 1D166 1DFA 0062;0061 1DCE 031B 1D166 1DFA 0062;0061 1DCE 031B 1D166 1DFA 0062;0061 1DCE 031B 1D166 1DFA 0062; # (a◌᷺◌̛◌᷎ð…¦b; a◌᷎◌̛ð…¦â—Œá·ºb; a◌᷎◌̛ð…¦â—Œá·ºb; a◌᷎◌̛ð…¦â—Œá·ºb; a◌᷎◌̛ð…¦â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING SPRECHGESANG STEM, LATIN SMALL LETTER B
+0061 1D166 1DFA 031B 1DCE 0062;0061 1DCE 1D166 031B 1DFA 0062;0061 1DCE 1D166 031B 1DFA 0062;0061 1DCE 1D166 031B 1DFA 0062;0061 1DCE 1D166 031B 1DFA 0062; # (að…¦â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…¦â—ŒÌ›â—Œá·ºb; a◌᷎ð…¦â—ŒÌ›â—Œá·ºb; a◌᷎ð…¦â—ŒÌ›â—Œá·ºb; a◌᷎ð…¦â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING SPRECHGESANG STEM, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
0061 16FF0 0334 1D167 0062;0061 0334 1D167 16FF0 0062;0061 0334 1D167 16FF0 0062;0061 0334 1D167 16FF0 0062;0061 0334 1D167 16FF0 0062; # (a𖿰◌̴◌ð…§b; a◌̴◌ð…§ð–¿°b; a◌̴◌ð…§ð–¿°b; a◌̴◌ð…§ð–¿°b; a◌̴◌ð…§ð–¿°b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, MUSICAL SYMBOL COMBINING TREMOLO-1, LATIN SMALL LETTER B
0061 1D167 16FF0 0334 0062;0061 1D167 0334 16FF0 0062;0061 1D167 0334 16FF0 0062;0061 1D167 0334 16FF0 0062;0061 1D167 0334 16FF0 0062; # (aâ—Œð…§ð–¿°â—ŒÌ´b; aâ—Œð…§â—ŒÌ´ð–¿°b; aâ—Œð…§â—ŒÌ´ð–¿°b; aâ—Œð…§â—ŒÌ´ð–¿°b; aâ—Œð…§â—ŒÌ´ð–¿°b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING TREMOLO-1, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 16FF0 0334 1D168 0062;0061 0334 1D168 16FF0 0062;0061 0334 1D168 16FF0 0062;0061 0334 1D168 16FF0 0062;0061 0334 1D168 16FF0 0062; # (a𖿰◌̴◌ð…¨b; a◌̴◌ð…¨ð–¿°b; a◌̴◌ð…¨ð–¿°b; a◌̴◌ð…¨ð–¿°b; a◌̴◌ð…¨ð–¿°b; ) LATIN SMALL LETTER A, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, MUSICAL SYMBOL COMBINING TREMOLO-2, LATIN SMALL LETTER B
@@ -18545,32 +18682,32 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1D169 16FF0 0334 0062;0061 1D169 0334 16FF0 0062;0061 1D169 0334 16FF0 0062;0061 1D169 0334 16FF0 0062;0061 1D169 0334 16FF0 0062; # (aâ—Œð…©ð–¿°â—ŒÌ´b; aâ—Œð…©â—ŒÌ´ð–¿°b; aâ—Œð…©â—ŒÌ´ð–¿°b; aâ—Œð…©â—ŒÌ´ð–¿°b; aâ—Œð…©â—ŒÌ´ð–¿°b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING TREMOLO-3, VIETNAMESE ALTERNATE READING MARK CA, COMBINING TILDE OVERLAY, LATIN SMALL LETTER B
0061 05AE 1D16D 302E 1D16D 0062;0061 302E 1D16D 1D16D 05AE 0062;0061 302E 1D16D 1D16D 05AE 0062;0061 302E 1D16D 1D16D 05AE 0062;0061 302E 1D16D 1D16D 05AE 0062; # (a◌֮ð…­ã€®ð…­b; a〮ð…­ð…­â—ŒÖ®b; a〮ð…­ð…­â—ŒÖ®b; a〮ð…­ð…­â—ŒÖ®b; a〮ð…­ð…­â—ŒÖ®b; ) LATIN SMALL LETTER A, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, HANGUL SINGLE DOT TONE MARK, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, LATIN SMALL LETTER B
0061 1D16D 05AE 1D16D 302E 0062;0061 302E 1D16D 1D16D 05AE 0062;0061 302E 1D16D 1D16D 05AE 0062;0061 302E 1D16D 1D16D 05AE 0062;0061 302E 1D16D 1D16D 05AE 0062; # (að…­â—ŒÖ®ð…­ã€®b; a〮ð…­ð…­â—ŒÖ®b; a〮ð…­ð…­â—ŒÖ®b; a〮ð…­ð…­â—ŒÖ®b; a〮ð…­ð…­â—ŒÖ®b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING AUGMENTATION DOT, HANGUL SINGLE DOT TONE MARK, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D16E 0062;0061 1DCE 031B 1D16E 302A 0062;0061 1DCE 031B 1D16E 302A 0062;0061 1DCE 031B 1D16E 302A 0062;0061 1DCE 031B 1D16E 302A 0062; # (a◌〪◌̛◌᷎ð…®b; a◌᷎◌̛ð…®â—Œã€ªb; a◌᷎◌̛ð…®â—Œã€ªb; a◌᷎◌̛ð…®â—Œã€ªb; a◌᷎◌̛ð…®â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-1, LATIN SMALL LETTER B
-0061 1D16E 302A 031B 1DCE 0062;0061 1DCE 1D16E 031B 302A 0062;0061 1DCE 1D16E 031B 302A 0062;0061 1DCE 1D16E 031B 302A 0062;0061 1DCE 1D16E 031B 302A 0062; # (að…®â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…®â—ŒÌ›â—Œã€ªb; a◌᷎ð…®â—ŒÌ›â—Œã€ªb; a◌᷎ð…®â—ŒÌ›â—Œã€ªb; a◌᷎ð…®â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-1, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D16F 0062;0061 1DCE 031B 1D16F 302A 0062;0061 1DCE 031B 1D16F 302A 0062;0061 1DCE 031B 1D16F 302A 0062;0061 1DCE 031B 1D16F 302A 0062; # (a◌〪◌̛◌᷎ð…¯b; a◌᷎◌̛ð…¯â—Œã€ªb; a◌᷎◌̛ð…¯â—Œã€ªb; a◌᷎◌̛ð…¯â—Œã€ªb; a◌᷎◌̛ð…¯â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-2, LATIN SMALL LETTER B
-0061 1D16F 302A 031B 1DCE 0062;0061 1DCE 1D16F 031B 302A 0062;0061 1DCE 1D16F 031B 302A 0062;0061 1DCE 1D16F 031B 302A 0062;0061 1DCE 1D16F 031B 302A 0062; # (að…¯â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…¯â—ŒÌ›â—Œã€ªb; a◌᷎ð…¯â—ŒÌ›â—Œã€ªb; a◌᷎ð…¯â—ŒÌ›â—Œã€ªb; a◌᷎ð…¯â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-2, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D170 0062;0061 1DCE 031B 1D170 302A 0062;0061 1DCE 031B 1D170 302A 0062;0061 1DCE 031B 1D170 302A 0062;0061 1DCE 031B 1D170 302A 0062; # (a◌〪◌̛◌᷎ð…°b; a◌᷎◌̛ð…°â—Œã€ªb; a◌᷎◌̛ð…°â—Œã€ªb; a◌᷎◌̛ð…°â—Œã€ªb; a◌᷎◌̛ð…°â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-3, LATIN SMALL LETTER B
-0061 1D170 302A 031B 1DCE 0062;0061 1DCE 1D170 031B 302A 0062;0061 1DCE 1D170 031B 302A 0062;0061 1DCE 1D170 031B 302A 0062;0061 1DCE 1D170 031B 302A 0062; # (að…°â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…°â—ŒÌ›â—Œã€ªb; a◌᷎ð…°â—ŒÌ›â—Œã€ªb; a◌᷎ð…°â—ŒÌ›â—Œã€ªb; a◌᷎ð…°â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-3, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D171 0062;0061 1DCE 031B 1D171 302A 0062;0061 1DCE 031B 1D171 302A 0062;0061 1DCE 031B 1D171 302A 0062;0061 1DCE 031B 1D171 302A 0062; # (a◌〪◌̛◌᷎ð…±b; a◌᷎◌̛ð…±â—Œã€ªb; a◌᷎◌̛ð…±â—Œã€ªb; a◌᷎◌̛ð…±â—Œã€ªb; a◌᷎◌̛ð…±â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-4, LATIN SMALL LETTER B
-0061 1D171 302A 031B 1DCE 0062;0061 1DCE 1D171 031B 302A 0062;0061 1DCE 1D171 031B 302A 0062;0061 1DCE 1D171 031B 302A 0062;0061 1DCE 1D171 031B 302A 0062; # (að…±â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…±â—ŒÌ›â—Œã€ªb; a◌᷎ð…±â—ŒÌ›â—Œã€ªb; a◌᷎ð…±â—ŒÌ›â—Œã€ªb; a◌᷎ð…±â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-4, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 302A 031B 1DCE 1D172 0062;0061 1DCE 031B 1D172 302A 0062;0061 1DCE 031B 1D172 302A 0062;0061 1DCE 031B 1D172 302A 0062;0061 1DCE 031B 1D172 302A 0062; # (a◌〪◌̛◌᷎ð…²b; a◌᷎◌̛ð…²â—Œã€ªb; a◌᷎◌̛ð…²â—Œã€ªb; a◌᷎◌̛ð…²â—Œã€ªb; a◌᷎◌̛ð…²â—Œã€ªb; ) LATIN SMALL LETTER A, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-5, LATIN SMALL LETTER B
-0061 1D172 302A 031B 1DCE 0062;0061 1DCE 1D172 031B 302A 0062;0061 1DCE 1D172 031B 302A 0062;0061 1DCE 1D172 031B 302A 0062;0061 1DCE 1D172 031B 302A 0062; # (að…²â—Œã€ªâ—ŒÌ›â—Œá·Žb; a◌᷎ð…²â—ŒÌ›â—Œã€ªb; a◌᷎ð…²â—ŒÌ›â—Œã€ªb; a◌᷎ð…²â—ŒÌ›â—Œã€ªb; a◌᷎ð…²â—ŒÌ›â—Œã€ªb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-5, IDEOGRAPHIC LEVEL TONE MARK, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D17B 0062;0061 302A 0316 1D17B 059A 0062;0061 302A 0316 1D17B 059A 0062;0061 302A 0316 1D17B 059A 0062;0061 302A 0316 1D17B 059A 0062; # (a◌֚◌̖◌〪◌ð…»b; a◌〪◌̖◌ð…»â—ŒÖšb; a◌〪◌̖◌ð…»â—ŒÖšb; a◌〪◌̖◌ð…»â—ŒÖšb; a◌〪◌̖◌ð…»â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING ACCENT, LATIN SMALL LETTER B
-0061 1D17B 059A 0316 302A 0062;0061 302A 1D17B 0316 059A 0062;0061 302A 1D17B 0316 059A 0062;0061 302A 1D17B 0316 059A 0062;0061 302A 1D17B 0316 059A 0062; # (aâ—Œð…»â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð…»â—ŒÌ–◌֚b; a◌〪◌ð…»â—ŒÌ–◌֚b; a◌〪◌ð…»â—ŒÌ–◌֚b; a◌〪◌ð…»â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING ACCENT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D17C 0062;0061 302A 0316 1D17C 059A 0062;0061 302A 0316 1D17C 059A 0062;0061 302A 0316 1D17C 059A 0062;0061 302A 0316 1D17C 059A 0062; # (a◌֚◌̖◌〪◌ð…¼b; a◌〪◌̖◌ð…¼â—ŒÖšb; a◌〪◌̖◌ð…¼â—ŒÖšb; a◌〪◌̖◌ð…¼â—ŒÖšb; a◌〪◌̖◌ð…¼â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING STACCATO, LATIN SMALL LETTER B
-0061 1D17C 059A 0316 302A 0062;0061 302A 1D17C 0316 059A 0062;0061 302A 1D17C 0316 059A 0062;0061 302A 1D17C 0316 059A 0062;0061 302A 1D17C 0316 059A 0062; # (aâ—Œð…¼â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð…¼â—ŒÌ–◌֚b; a◌〪◌ð…¼â—ŒÌ–◌֚b; a◌〪◌ð…¼â—ŒÌ–◌֚b; a◌〪◌ð…¼â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING STACCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D17D 0062;0061 302A 0316 1D17D 059A 0062;0061 302A 0316 1D17D 059A 0062;0061 302A 0316 1D17D 059A 0062;0061 302A 0316 1D17D 059A 0062; # (a◌֚◌̖◌〪◌ð…½b; a◌〪◌̖◌ð…½â—ŒÖšb; a◌〪◌̖◌ð…½â—ŒÖšb; a◌〪◌̖◌ð…½â—ŒÖšb; a◌〪◌̖◌ð…½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING TENUTO, LATIN SMALL LETTER B
-0061 1D17D 059A 0316 302A 0062;0061 302A 1D17D 0316 059A 0062;0061 302A 1D17D 0316 059A 0062;0061 302A 1D17D 0316 059A 0062;0061 302A 1D17D 0316 059A 0062; # (aâ—Œð…½â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð…½â—ŒÌ–◌֚b; a◌〪◌ð…½â—ŒÌ–◌֚b; a◌〪◌ð…½â—ŒÌ–◌֚b; a◌〪◌ð…½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING TENUTO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D17E 0062;0061 302A 0316 1D17E 059A 0062;0061 302A 0316 1D17E 059A 0062;0061 302A 0316 1D17E 059A 0062;0061 302A 0316 1D17E 059A 0062; # (a◌֚◌̖◌〪◌ð…¾b; a◌〪◌̖◌ð…¾â—ŒÖšb; a◌〪◌̖◌ð…¾â—ŒÖšb; a◌〪◌̖◌ð…¾â—ŒÖšb; a◌〪◌̖◌ð…¾â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING STACCATISSIMO, LATIN SMALL LETTER B
-0061 1D17E 059A 0316 302A 0062;0061 302A 1D17E 0316 059A 0062;0061 302A 1D17E 0316 059A 0062;0061 302A 1D17E 0316 059A 0062;0061 302A 1D17E 0316 059A 0062; # (aâ—Œð…¾â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð…¾â—ŒÌ–◌֚b; a◌〪◌ð…¾â—ŒÌ–◌֚b; a◌〪◌ð…¾â—ŒÌ–◌֚b; a◌〪◌ð…¾â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING STACCATISSIMO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D17F 0062;0061 302A 0316 1D17F 059A 0062;0061 302A 0316 1D17F 059A 0062;0061 302A 0316 1D17F 059A 0062;0061 302A 0316 1D17F 059A 0062; # (a◌֚◌̖◌〪◌ð…¿b; a◌〪◌̖◌ð…¿â—ŒÖšb; a◌〪◌̖◌ð…¿â—ŒÖšb; a◌〪◌̖◌ð…¿â—ŒÖšb; a◌〪◌̖◌ð…¿â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING MARCATO, LATIN SMALL LETTER B
-0061 1D17F 059A 0316 302A 0062;0061 302A 1D17F 0316 059A 0062;0061 302A 1D17F 0316 059A 0062;0061 302A 1D17F 0316 059A 0062;0061 302A 1D17F 0316 059A 0062; # (aâ—Œð…¿â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð…¿â—ŒÌ–◌֚b; a◌〪◌ð…¿â—ŒÌ–◌֚b; a◌〪◌ð…¿â—ŒÌ–◌֚b; a◌〪◌ð…¿â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING MARCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D180 0062;0061 302A 0316 1D180 059A 0062;0061 302A 0316 1D180 059A 0062;0061 302A 0316 1D180 059A 0062;0061 302A 0316 1D180 059A 0062; # (a◌֚◌̖◌〪◌ð†€b; a◌〪◌̖◌ð†€â—ŒÖšb; a◌〪◌̖◌ð†€â—ŒÖšb; a◌〪◌̖◌ð†€â—ŒÖšb; a◌〪◌̖◌ð†€â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING MARCATO-STACCATO, LATIN SMALL LETTER B
-0061 1D180 059A 0316 302A 0062;0061 302A 1D180 0316 059A 0062;0061 302A 1D180 0316 059A 0062;0061 302A 1D180 0316 059A 0062;0061 302A 1D180 0316 059A 0062; # (aâ—Œð†€â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð†€â—ŒÌ–◌֚b; a◌〪◌ð†€â—ŒÌ–◌֚b; a◌〪◌ð†€â—ŒÌ–◌֚b; a◌〪◌ð†€â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING MARCATO-STACCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D181 0062;0061 302A 0316 1D181 059A 0062;0061 302A 0316 1D181 059A 0062;0061 302A 0316 1D181 059A 0062;0061 302A 0316 1D181 059A 0062; # (a◌֚◌̖◌〪◌ð†b; a◌〪◌̖◌ð†â—ŒÖšb; a◌〪◌̖◌ð†â—ŒÖšb; a◌〪◌̖◌ð†â—ŒÖšb; a◌〪◌̖◌ð†â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING ACCENT-STACCATO, LATIN SMALL LETTER B
-0061 1D181 059A 0316 302A 0062;0061 302A 1D181 0316 059A 0062;0061 302A 1D181 0316 059A 0062;0061 302A 1D181 0316 059A 0062;0061 302A 1D181 0316 059A 0062; # (aâ—Œð†â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð†â—ŒÌ–◌֚b; a◌〪◌ð†â—ŒÌ–◌֚b; a◌〪◌ð†â—ŒÌ–◌֚b; a◌〪◌ð†â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING ACCENT-STACCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D182 0062;0061 302A 0316 1D182 059A 0062;0061 302A 0316 1D182 059A 0062;0061 302A 0316 1D182 059A 0062;0061 302A 0316 1D182 059A 0062; # (a◌֚◌̖◌〪◌ð†‚b; a◌〪◌̖◌ð†‚◌֚b; a◌〪◌̖◌ð†‚◌֚b; a◌〪◌̖◌ð†‚◌֚b; a◌〪◌̖◌ð†‚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING LOURE, LATIN SMALL LETTER B
-0061 1D182 059A 0316 302A 0062;0061 302A 1D182 0316 059A 0062;0061 302A 1D182 0316 059A 0062;0061 302A 1D182 0316 059A 0062;0061 302A 1D182 0316 059A 0062; # (aâ—Œð†‚◌֚◌̖◌〪b; a◌〪◌ð†‚◌̖◌֚b; a◌〪◌ð†‚◌̖◌֚b; a◌〪◌ð†‚◌̖◌֚b; a◌〪◌ð†‚◌̖◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING LOURE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D16E 0062;0061 1DCE 031B 1D16E 1DFA 0062;0061 1DCE 031B 1D16E 1DFA 0062;0061 1DCE 031B 1D16E 1DFA 0062;0061 1DCE 031B 1D16E 1DFA 0062; # (a◌᷺◌̛◌᷎ð…®b; a◌᷎◌̛ð…®â—Œá·ºb; a◌᷎◌̛ð…®â—Œá·ºb; a◌᷎◌̛ð…®â—Œá·ºb; a◌᷎◌̛ð…®â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-1, LATIN SMALL LETTER B
+0061 1D16E 1DFA 031B 1DCE 0062;0061 1DCE 1D16E 031B 1DFA 0062;0061 1DCE 1D16E 031B 1DFA 0062;0061 1DCE 1D16E 031B 1DFA 0062;0061 1DCE 1D16E 031B 1DFA 0062; # (að…®â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…®â—ŒÌ›â—Œá·ºb; a◌᷎ð…®â—ŒÌ›â—Œá·ºb; a◌᷎ð…®â—ŒÌ›â—Œá·ºb; a◌᷎ð…®â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-1, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D16F 0062;0061 1DCE 031B 1D16F 1DFA 0062;0061 1DCE 031B 1D16F 1DFA 0062;0061 1DCE 031B 1D16F 1DFA 0062;0061 1DCE 031B 1D16F 1DFA 0062; # (a◌᷺◌̛◌᷎ð…¯b; a◌᷎◌̛ð…¯â—Œá·ºb; a◌᷎◌̛ð…¯â—Œá·ºb; a◌᷎◌̛ð…¯â—Œá·ºb; a◌᷎◌̛ð…¯â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-2, LATIN SMALL LETTER B
+0061 1D16F 1DFA 031B 1DCE 0062;0061 1DCE 1D16F 031B 1DFA 0062;0061 1DCE 1D16F 031B 1DFA 0062;0061 1DCE 1D16F 031B 1DFA 0062;0061 1DCE 1D16F 031B 1DFA 0062; # (að…¯â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…¯â—ŒÌ›â—Œá·ºb; a◌᷎ð…¯â—ŒÌ›â—Œá·ºb; a◌᷎ð…¯â—ŒÌ›â—Œá·ºb; a◌᷎ð…¯â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-2, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D170 0062;0061 1DCE 031B 1D170 1DFA 0062;0061 1DCE 031B 1D170 1DFA 0062;0061 1DCE 031B 1D170 1DFA 0062;0061 1DCE 031B 1D170 1DFA 0062; # (a◌᷺◌̛◌᷎ð…°b; a◌᷎◌̛ð…°â—Œá·ºb; a◌᷎◌̛ð…°â—Œá·ºb; a◌᷎◌̛ð…°â—Œá·ºb; a◌᷎◌̛ð…°â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-3, LATIN SMALL LETTER B
+0061 1D170 1DFA 031B 1DCE 0062;0061 1DCE 1D170 031B 1DFA 0062;0061 1DCE 1D170 031B 1DFA 0062;0061 1DCE 1D170 031B 1DFA 0062;0061 1DCE 1D170 031B 1DFA 0062; # (að…°â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…°â—ŒÌ›â—Œá·ºb; a◌᷎ð…°â—ŒÌ›â—Œá·ºb; a◌᷎ð…°â—ŒÌ›â—Œá·ºb; a◌᷎ð…°â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-3, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D171 0062;0061 1DCE 031B 1D171 1DFA 0062;0061 1DCE 031B 1D171 1DFA 0062;0061 1DCE 031B 1D171 1DFA 0062;0061 1DCE 031B 1D171 1DFA 0062; # (a◌᷺◌̛◌᷎ð…±b; a◌᷎◌̛ð…±â—Œá·ºb; a◌᷎◌̛ð…±â—Œá·ºb; a◌᷎◌̛ð…±â—Œá·ºb; a◌᷎◌̛ð…±â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-4, LATIN SMALL LETTER B
+0061 1D171 1DFA 031B 1DCE 0062;0061 1DCE 1D171 031B 1DFA 0062;0061 1DCE 1D171 031B 1DFA 0062;0061 1DCE 1D171 031B 1DFA 0062;0061 1DCE 1D171 031B 1DFA 0062; # (að…±â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…±â—ŒÌ›â—Œá·ºb; a◌᷎ð…±â—ŒÌ›â—Œá·ºb; a◌᷎ð…±â—ŒÌ›â—Œá·ºb; a◌᷎ð…±â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-4, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 1DFA 031B 1DCE 1D172 0062;0061 1DCE 031B 1D172 1DFA 0062;0061 1DCE 031B 1D172 1DFA 0062;0061 1DCE 031B 1D172 1DFA 0062;0061 1DCE 031B 1D172 1DFA 0062; # (a◌᷺◌̛◌᷎ð…²b; a◌᷎◌̛ð…²â—Œá·ºb; a◌᷎◌̛ð…²â—Œá·ºb; a◌᷎◌̛ð…²â—Œá·ºb; a◌᷎◌̛ð…²â—Œá·ºb; ) LATIN SMALL LETTER A, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, MUSICAL SYMBOL COMBINING FLAG-5, LATIN SMALL LETTER B
+0061 1D172 1DFA 031B 1DCE 0062;0061 1DCE 1D172 031B 1DFA 0062;0061 1DCE 1D172 031B 1DFA 0062;0061 1DCE 1D172 031B 1DFA 0062;0061 1DCE 1D172 031B 1DFA 0062; # (að…²â—Œá·ºâ—ŒÌ›â—Œá·Žb; a◌᷎ð…²â—ŒÌ›â—Œá·ºb; a◌᷎ð…²â—ŒÌ›â—Œá·ºb; a◌᷎ð…²â—ŒÌ›â—Œá·ºb; a◌᷎ð…²â—ŒÌ›â—Œá·ºb; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING FLAG-5, COMBINING DOT BELOW LEFT, COMBINING HORN, COMBINING OGONEK ABOVE, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D17B 0062;0061 1DFA 0316 1D17B 059A 0062;0061 1DFA 0316 1D17B 059A 0062;0061 1DFA 0316 1D17B 059A 0062;0061 1DFA 0316 1D17B 059A 0062; # (a◌֚◌̖◌᷺◌ð…»b; a◌᷺◌̖◌ð…»â—ŒÖšb; a◌᷺◌̖◌ð…»â—ŒÖšb; a◌᷺◌̖◌ð…»â—ŒÖšb; a◌᷺◌̖◌ð…»â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING ACCENT, LATIN SMALL LETTER B
+0061 1D17B 059A 0316 1DFA 0062;0061 1DFA 1D17B 0316 059A 0062;0061 1DFA 1D17B 0316 059A 0062;0061 1DFA 1D17B 0316 059A 0062;0061 1DFA 1D17B 0316 059A 0062; # (aâ—Œð…»â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð…»â—ŒÌ–◌֚b; a◌᷺◌ð…»â—ŒÌ–◌֚b; a◌᷺◌ð…»â—ŒÌ–◌֚b; a◌᷺◌ð…»â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING ACCENT, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D17C 0062;0061 1DFA 0316 1D17C 059A 0062;0061 1DFA 0316 1D17C 059A 0062;0061 1DFA 0316 1D17C 059A 0062;0061 1DFA 0316 1D17C 059A 0062; # (a◌֚◌̖◌᷺◌ð…¼b; a◌᷺◌̖◌ð…¼â—ŒÖšb; a◌᷺◌̖◌ð…¼â—ŒÖšb; a◌᷺◌̖◌ð…¼â—ŒÖšb; a◌᷺◌̖◌ð…¼â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING STACCATO, LATIN SMALL LETTER B
+0061 1D17C 059A 0316 1DFA 0062;0061 1DFA 1D17C 0316 059A 0062;0061 1DFA 1D17C 0316 059A 0062;0061 1DFA 1D17C 0316 059A 0062;0061 1DFA 1D17C 0316 059A 0062; # (aâ—Œð…¼â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð…¼â—ŒÌ–◌֚b; a◌᷺◌ð…¼â—ŒÌ–◌֚b; a◌᷺◌ð…¼â—ŒÌ–◌֚b; a◌᷺◌ð…¼â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING STACCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D17D 0062;0061 1DFA 0316 1D17D 059A 0062;0061 1DFA 0316 1D17D 059A 0062;0061 1DFA 0316 1D17D 059A 0062;0061 1DFA 0316 1D17D 059A 0062; # (a◌֚◌̖◌᷺◌ð…½b; a◌᷺◌̖◌ð…½â—ŒÖšb; a◌᷺◌̖◌ð…½â—ŒÖšb; a◌᷺◌̖◌ð…½â—ŒÖšb; a◌᷺◌̖◌ð…½â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING TENUTO, LATIN SMALL LETTER B
+0061 1D17D 059A 0316 1DFA 0062;0061 1DFA 1D17D 0316 059A 0062;0061 1DFA 1D17D 0316 059A 0062;0061 1DFA 1D17D 0316 059A 0062;0061 1DFA 1D17D 0316 059A 0062; # (aâ—Œð…½â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð…½â—ŒÌ–◌֚b; a◌᷺◌ð…½â—ŒÌ–◌֚b; a◌᷺◌ð…½â—ŒÌ–◌֚b; a◌᷺◌ð…½â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING TENUTO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D17E 0062;0061 1DFA 0316 1D17E 059A 0062;0061 1DFA 0316 1D17E 059A 0062;0061 1DFA 0316 1D17E 059A 0062;0061 1DFA 0316 1D17E 059A 0062; # (a◌֚◌̖◌᷺◌ð…¾b; a◌᷺◌̖◌ð…¾â—ŒÖšb; a◌᷺◌̖◌ð…¾â—ŒÖšb; a◌᷺◌̖◌ð…¾â—ŒÖšb; a◌᷺◌̖◌ð…¾â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING STACCATISSIMO, LATIN SMALL LETTER B
+0061 1D17E 059A 0316 1DFA 0062;0061 1DFA 1D17E 0316 059A 0062;0061 1DFA 1D17E 0316 059A 0062;0061 1DFA 1D17E 0316 059A 0062;0061 1DFA 1D17E 0316 059A 0062; # (aâ—Œð…¾â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð…¾â—ŒÌ–◌֚b; a◌᷺◌ð…¾â—ŒÌ–◌֚b; a◌᷺◌ð…¾â—ŒÌ–◌֚b; a◌᷺◌ð…¾â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING STACCATISSIMO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D17F 0062;0061 1DFA 0316 1D17F 059A 0062;0061 1DFA 0316 1D17F 059A 0062;0061 1DFA 0316 1D17F 059A 0062;0061 1DFA 0316 1D17F 059A 0062; # (a◌֚◌̖◌᷺◌ð…¿b; a◌᷺◌̖◌ð…¿â—ŒÖšb; a◌᷺◌̖◌ð…¿â—ŒÖšb; a◌᷺◌̖◌ð…¿â—ŒÖšb; a◌᷺◌̖◌ð…¿â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING MARCATO, LATIN SMALL LETTER B
+0061 1D17F 059A 0316 1DFA 0062;0061 1DFA 1D17F 0316 059A 0062;0061 1DFA 1D17F 0316 059A 0062;0061 1DFA 1D17F 0316 059A 0062;0061 1DFA 1D17F 0316 059A 0062; # (aâ—Œð…¿â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð…¿â—ŒÌ–◌֚b; a◌᷺◌ð…¿â—ŒÌ–◌֚b; a◌᷺◌ð…¿â—ŒÌ–◌֚b; a◌᷺◌ð…¿â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING MARCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D180 0062;0061 1DFA 0316 1D180 059A 0062;0061 1DFA 0316 1D180 059A 0062;0061 1DFA 0316 1D180 059A 0062;0061 1DFA 0316 1D180 059A 0062; # (a◌֚◌̖◌᷺◌ð†€b; a◌᷺◌̖◌ð†€â—ŒÖšb; a◌᷺◌̖◌ð†€â—ŒÖšb; a◌᷺◌̖◌ð†€â—ŒÖšb; a◌᷺◌̖◌ð†€â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING MARCATO-STACCATO, LATIN SMALL LETTER B
+0061 1D180 059A 0316 1DFA 0062;0061 1DFA 1D180 0316 059A 0062;0061 1DFA 1D180 0316 059A 0062;0061 1DFA 1D180 0316 059A 0062;0061 1DFA 1D180 0316 059A 0062; # (aâ—Œð†€â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð†€â—ŒÌ–◌֚b; a◌᷺◌ð†€â—ŒÌ–◌֚b; a◌᷺◌ð†€â—ŒÌ–◌֚b; a◌᷺◌ð†€â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING MARCATO-STACCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D181 0062;0061 1DFA 0316 1D181 059A 0062;0061 1DFA 0316 1D181 059A 0062;0061 1DFA 0316 1D181 059A 0062;0061 1DFA 0316 1D181 059A 0062; # (a◌֚◌̖◌᷺◌ð†b; a◌᷺◌̖◌ð†â—ŒÖšb; a◌᷺◌̖◌ð†â—ŒÖšb; a◌᷺◌̖◌ð†â—ŒÖšb; a◌᷺◌̖◌ð†â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING ACCENT-STACCATO, LATIN SMALL LETTER B
+0061 1D181 059A 0316 1DFA 0062;0061 1DFA 1D181 0316 059A 0062;0061 1DFA 1D181 0316 059A 0062;0061 1DFA 1D181 0316 059A 0062;0061 1DFA 1D181 0316 059A 0062; # (aâ—Œð†â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð†â—ŒÌ–◌֚b; a◌᷺◌ð†â—ŒÌ–◌֚b; a◌᷺◌ð†â—ŒÌ–◌֚b; a◌᷺◌ð†â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING ACCENT-STACCATO, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D182 0062;0061 1DFA 0316 1D182 059A 0062;0061 1DFA 0316 1D182 059A 0062;0061 1DFA 0316 1D182 059A 0062;0061 1DFA 0316 1D182 059A 0062; # (a◌֚◌̖◌᷺◌ð†‚b; a◌᷺◌̖◌ð†‚◌֚b; a◌᷺◌̖◌ð†‚◌֚b; a◌᷺◌̖◌ð†‚◌֚b; a◌᷺◌̖◌ð†‚◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING LOURE, LATIN SMALL LETTER B
+0061 1D182 059A 0316 1DFA 0062;0061 1DFA 1D182 0316 059A 0062;0061 1DFA 1D182 0316 059A 0062;0061 1DFA 1D182 0316 059A 0062;0061 1DFA 1D182 0316 059A 0062; # (aâ—Œð†‚◌֚◌̖◌᷺b; a◌᷺◌ð†‚◌̖◌֚b; a◌᷺◌ð†‚◌̖◌֚b; a◌᷺◌ð†‚◌̖◌֚b; a◌᷺◌ð†‚◌̖◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING LOURE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1D185 0062;00E0 05AE 1D185 0315 0062;0061 05AE 0300 1D185 0315 0062;00E0 05AE 1D185 0315 0062;0061 05AE 0300 1D185 0315 0062; # (a◌̕◌̀◌֮◌ð†…b; à◌֮◌ð†…◌̕b; a◌֮◌̀◌ð†…◌̕b; à◌֮◌ð†…◌̕b; a◌֮◌̀◌ð†…◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING DOIT, LATIN SMALL LETTER B
0061 1D185 0315 0300 05AE 0062;0061 05AE 1D185 0300 0315 0062;0061 05AE 1D185 0300 0315 0062;0061 05AE 1D185 0300 0315 0062;0061 05AE 1D185 0300 0315 0062; # (aâ—Œð†…◌̕◌̀◌֮b; a◌֮◌ð†…◌̀◌̕b; a◌֮◌ð†…◌̀◌̕b; a◌֮◌ð†…◌̀◌̕b; a◌֮◌ð†…◌̀◌̕b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING DOIT, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1D186 0062;00E0 05AE 1D186 0315 0062;0061 05AE 0300 1D186 0315 0062;00E0 05AE 1D186 0315 0062;0061 05AE 0300 1D186 0315 0062; # (a◌̕◌̀◌֮◌ð††b; à◌֮◌ð††â—ŒÌ•b; a◌֮◌̀◌ð††â—ŒÌ•b; à◌֮◌ð††â—ŒÌ•b; a◌֮◌̀◌ð††â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING RIP, LATIN SMALL LETTER B
@@ -18581,10 +18718,10 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1D188 0315 0300 05AE 0062;0061 05AE 1D188 0300 0315 0062;0061 05AE 1D188 0300 0315 0062;0061 05AE 1D188 0300 0315 0062;0061 05AE 1D188 0300 0315 0062; # (aâ—Œð†ˆâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð†ˆâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð†ˆâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð†ˆâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð†ˆâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING SMEAR, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1D189 0062;00E0 05AE 1D189 0315 0062;0061 05AE 0300 1D189 0315 0062;00E0 05AE 1D189 0315 0062;0061 05AE 0300 1D189 0315 0062; # (a◌̕◌̀◌֮◌ð†‰b; à◌֮◌ð†‰â—ŒÌ•b; a◌֮◌̀◌ð†‰â—ŒÌ•b; à◌֮◌ð†‰â—ŒÌ•b; a◌֮◌̀◌ð†‰â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING BEND, LATIN SMALL LETTER B
0061 1D189 0315 0300 05AE 0062;0061 05AE 1D189 0300 0315 0062;0061 05AE 1D189 0300 0315 0062;0061 05AE 1D189 0300 0315 0062;0061 05AE 1D189 0300 0315 0062; # (aâ—Œð†‰â—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð†‰â—ŒÌ€â—ŒÌ•b; a◌֮◌ð†‰â—ŒÌ€â—ŒÌ•b; a◌֮◌ð†‰â—ŒÌ€â—ŒÌ•b; a◌֮◌ð†‰â—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING BEND, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D18A 0062;0061 302A 0316 1D18A 059A 0062;0061 302A 0316 1D18A 059A 0062;0061 302A 0316 1D18A 059A 0062;0061 302A 0316 1D18A 059A 0062; # (a◌֚◌̖◌〪◌ð†Šb; a◌〪◌̖◌ð†Šâ—ŒÖšb; a◌〪◌̖◌ð†Šâ—ŒÖšb; a◌〪◌̖◌ð†Šâ—ŒÖšb; a◌〪◌̖◌ð†Šâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING DOUBLE TONGUE, LATIN SMALL LETTER B
-0061 1D18A 059A 0316 302A 0062;0061 302A 1D18A 0316 059A 0062;0061 302A 1D18A 0316 059A 0062;0061 302A 1D18A 0316 059A 0062;0061 302A 1D18A 0316 059A 0062; # (aâ—Œð†Šâ—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð†Šâ—ŒÌ–◌֚b; a◌〪◌ð†Šâ—ŒÌ–◌֚b; a◌〪◌ð†Šâ—ŒÌ–◌֚b; a◌〪◌ð†Šâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING DOUBLE TONGUE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1D18B 0062;0061 302A 0316 1D18B 059A 0062;0061 302A 0316 1D18B 059A 0062;0061 302A 0316 1D18B 059A 0062;0061 302A 0316 1D18B 059A 0062; # (a◌֚◌̖◌〪◌ð†‹b; a◌〪◌̖◌ð†‹â—ŒÖšb; a◌〪◌̖◌ð†‹â—ŒÖšb; a◌〪◌̖◌ð†‹â—ŒÖšb; a◌〪◌̖◌ð†‹â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MUSICAL SYMBOL COMBINING TRIPLE TONGUE, LATIN SMALL LETTER B
-0061 1D18B 059A 0316 302A 0062;0061 302A 1D18B 0316 059A 0062;0061 302A 1D18B 0316 059A 0062;0061 302A 1D18B 0316 059A 0062;0061 302A 1D18B 0316 059A 0062; # (aâ—Œð†‹â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ð†‹â—ŒÌ–◌֚b; a◌〪◌ð†‹â—ŒÌ–◌֚b; a◌〪◌ð†‹â—ŒÌ–◌֚b; a◌〪◌ð†‹â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING TRIPLE TONGUE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D18A 0062;0061 1DFA 0316 1D18A 059A 0062;0061 1DFA 0316 1D18A 059A 0062;0061 1DFA 0316 1D18A 059A 0062;0061 1DFA 0316 1D18A 059A 0062; # (a◌֚◌̖◌᷺◌ð†Šb; a◌᷺◌̖◌ð†Šâ—ŒÖšb; a◌᷺◌̖◌ð†Šâ—ŒÖšb; a◌᷺◌̖◌ð†Šâ—ŒÖšb; a◌᷺◌̖◌ð†Šâ—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING DOUBLE TONGUE, LATIN SMALL LETTER B
+0061 1D18A 059A 0316 1DFA 0062;0061 1DFA 1D18A 0316 059A 0062;0061 1DFA 1D18A 0316 059A 0062;0061 1DFA 1D18A 0316 059A 0062;0061 1DFA 1D18A 0316 059A 0062; # (aâ—Œð†Šâ—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð†Šâ—ŒÌ–◌֚b; a◌᷺◌ð†Šâ—ŒÌ–◌֚b; a◌᷺◌ð†Šâ—ŒÌ–◌֚b; a◌᷺◌ð†Šâ—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING DOUBLE TONGUE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1D18B 0062;0061 1DFA 0316 1D18B 059A 0062;0061 1DFA 0316 1D18B 059A 0062;0061 1DFA 0316 1D18B 059A 0062;0061 1DFA 0316 1D18B 059A 0062; # (a◌֚◌̖◌᷺◌ð†‹b; a◌᷺◌̖◌ð†‹â—ŒÖšb; a◌᷺◌̖◌ð†‹â—ŒÖšb; a◌᷺◌̖◌ð†‹â—ŒÖšb; a◌᷺◌̖◌ð†‹â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MUSICAL SYMBOL COMBINING TRIPLE TONGUE, LATIN SMALL LETTER B
+0061 1D18B 059A 0316 1DFA 0062;0061 1DFA 1D18B 0316 059A 0062;0061 1DFA 1D18B 0316 059A 0062;0061 1DFA 1D18B 0316 059A 0062;0061 1DFA 1D18B 0316 059A 0062; # (aâ—Œð†‹â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ð†‹â—ŒÌ–◌֚b; a◌᷺◌ð†‹â—ŒÌ–◌֚b; a◌᷺◌ð†‹â—ŒÌ–◌֚b; a◌᷺◌ð†‹â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING TRIPLE TONGUE, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1D1AA 0062;00E0 05AE 1D1AA 0315 0062;0061 05AE 0300 1D1AA 0315 0062;00E0 05AE 1D1AA 0315 0062;0061 05AE 0300 1D1AA 0315 0062; # (a◌̕◌̀◌֮◌ð†ªb; à◌֮◌ð†ªâ—ŒÌ•b; a◌֮◌̀◌ð†ªâ—ŒÌ•b; à◌֮◌ð†ªâ—ŒÌ•b; a◌֮◌̀◌ð†ªâ—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING DOWN BOW, LATIN SMALL LETTER B
0061 1D1AA 0315 0300 05AE 0062;0061 05AE 1D1AA 0300 0315 0062;0061 05AE 1D1AA 0300 0315 0062;0061 05AE 1D1AA 0300 0315 0062;0061 05AE 1D1AA 0300 0315 0062; # (aâ—Œð†ªâ—ŒÌ•â—ŒÌ€â—ŒÖ®b; a◌֮◌ð†ªâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð†ªâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð†ªâ—ŒÌ€â—ŒÌ•b; a◌֮◌ð†ªâ—ŒÌ€â—ŒÌ•b; ) LATIN SMALL LETTER A, MUSICAL SYMBOL COMBINING DOWN BOW, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1D1AB 0062;00E0 05AE 1D1AB 0315 0062;0061 05AE 0300 1D1AB 0315 0062;00E0 05AE 1D1AB 0315 0062;0061 05AE 0300 1D1AB 0315 0062; # (a◌̕◌̀◌֮◌ð†«b; à◌֮◌ð†«â—ŒÌ•b; a◌֮◌̀◌ð†«â—ŒÌ•b; à◌֮◌ð†«â—ŒÌ•b; a◌֮◌̀◌ð†«â—ŒÌ•b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, MUSICAL SYMBOL COMBINING UP BOW, LATIN SMALL LETTER B
@@ -18689,6 +18826,8 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1E135 0315 0300 05AE 0062;0061 05AE 1E135 0300 0315 0062;0061 05AE 1E135 0300 0315 0062;0061 05AE 1E135 0300 0315 0062;0061 05AE 1E135 0300 0315 0062; # (a◌𞄵◌̕◌̀◌֮b; a◌֮◌𞄵◌̀◌̕b; a◌֮◌𞄵◌̀◌̕b; a◌֮◌𞄵◌̀◌̕b; a◌֮◌𞄵◌̀◌̕b; ) LATIN SMALL LETTER A, NYIAKENG PUACHUE HMONG TONE-G, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E136 0062;00E0 05AE 1E136 0315 0062;0061 05AE 0300 1E136 0315 0062;00E0 05AE 1E136 0315 0062;0061 05AE 0300 1E136 0315 0062; # (a◌̕◌̀◌֮◌𞄶b; à◌֮◌𞄶◌̕b; a◌֮◌̀◌𞄶◌̕b; à◌֮◌𞄶◌̕b; a◌֮◌̀◌𞄶◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, NYIAKENG PUACHUE HMONG TONE-D, LATIN SMALL LETTER B
0061 1E136 0315 0300 05AE 0062;0061 05AE 1E136 0300 0315 0062;0061 05AE 1E136 0300 0315 0062;0061 05AE 1E136 0300 0315 0062;0061 05AE 1E136 0300 0315 0062; # (a◌𞄶◌̕◌̀◌֮b; a◌֮◌𞄶◌̀◌̕b; a◌֮◌𞄶◌̀◌̕b; a◌֮◌𞄶◌̀◌̕b; a◌֮◌𞄶◌̀◌̕b; ) LATIN SMALL LETTER A, NYIAKENG PUACHUE HMONG TONE-D, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
+0061 0315 0300 05AE 1E2AE 0062;00E0 05AE 1E2AE 0315 0062;0061 05AE 0300 1E2AE 0315 0062;00E0 05AE 1E2AE 0315 0062;0061 05AE 0300 1E2AE 0315 0062; # (a◌̕◌̀◌֮◌𞊮b; à◌֮◌𞊮◌̕b; a◌֮◌̀◌𞊮◌̕b; à◌֮◌𞊮◌̕b; a◌֮◌̀◌𞊮◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, TOTO SIGN RISING TONE, LATIN SMALL LETTER B
+0061 1E2AE 0315 0300 05AE 0062;0061 05AE 1E2AE 0300 0315 0062;0061 05AE 1E2AE 0300 0315 0062;0061 05AE 1E2AE 0300 0315 0062;0061 05AE 1E2AE 0300 0315 0062; # (a◌𞊮◌̕◌̀◌֮b; a◌֮◌𞊮◌̀◌̕b; a◌֮◌𞊮◌̀◌̕b; a◌֮◌𞊮◌̀◌̕b; a◌֮◌𞊮◌̀◌̕b; ) LATIN SMALL LETTER A, TOTO SIGN RISING TONE, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E2EC 0062;00E0 05AE 1E2EC 0315 0062;0061 05AE 0300 1E2EC 0315 0062;00E0 05AE 1E2EC 0315 0062;0061 05AE 0300 1E2EC 0315 0062; # (a◌̕◌̀◌֮◌𞋬b; à◌֮◌𞋬◌̕b; a◌֮◌̀◌𞋬◌̕b; à◌֮◌𞋬◌̕b; a◌֮◌̀◌𞋬◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, WANCHO TONE TUP, LATIN SMALL LETTER B
0061 1E2EC 0315 0300 05AE 0062;0061 05AE 1E2EC 0300 0315 0062;0061 05AE 1E2EC 0300 0315 0062;0061 05AE 1E2EC 0300 0315 0062;0061 05AE 1E2EC 0300 0315 0062; # (a◌𞋬◌̕◌̀◌֮b; a◌֮◌𞋬◌̀◌̕b; a◌֮◌𞋬◌̀◌̕b; a◌֮◌𞋬◌̀◌̕b; a◌֮◌𞋬◌̀◌̕b; ) LATIN SMALL LETTER A, WANCHO TONE TUP, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E2ED 0062;00E0 05AE 1E2ED 0315 0062;0061 05AE 0300 1E2ED 0315 0062;00E0 05AE 1E2ED 0315 0062;0061 05AE 0300 1E2ED 0315 0062; # (a◌̕◌̀◌֮◌𞋭b; à◌֮◌𞋭◌̕b; a◌֮◌̀◌𞋭◌̕b; à◌֮◌𞋭◌̕b; a◌֮◌̀◌𞋭◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, WANCHO TONE TUPNI, LATIN SMALL LETTER B
@@ -18697,20 +18836,20 @@ FFEE;FFEE;FFEE;25CB;25CB; # (ï¿®; ï¿®; ï¿®; â—‹; â—‹; ) HALFWIDTH WHITE CIRCLE
0061 1E2EE 0315 0300 05AE 0062;0061 05AE 1E2EE 0300 0315 0062;0061 05AE 1E2EE 0300 0315 0062;0061 05AE 1E2EE 0300 0315 0062;0061 05AE 1E2EE 0300 0315 0062; # (a◌𞋮◌̕◌̀◌֮b; a◌֮◌𞋮◌̀◌̕b; a◌֮◌𞋮◌̀◌̕b; a◌֮◌𞋮◌̀◌̕b; a◌֮◌𞋮◌̀◌̕b; ) LATIN SMALL LETTER A, WANCHO TONE KOI, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E2EF 0062;00E0 05AE 1E2EF 0315 0062;0061 05AE 0300 1E2EF 0315 0062;00E0 05AE 1E2EF 0315 0062;0061 05AE 0300 1E2EF 0315 0062; # (a◌̕◌̀◌֮◌𞋯b; à◌֮◌𞋯◌̕b; a◌֮◌̀◌𞋯◌̕b; à◌֮◌𞋯◌̕b; a◌֮◌̀◌𞋯◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, WANCHO TONE KOINI, LATIN SMALL LETTER B
0061 1E2EF 0315 0300 05AE 0062;0061 05AE 1E2EF 0300 0315 0062;0061 05AE 1E2EF 0300 0315 0062;0061 05AE 1E2EF 0300 0315 0062;0061 05AE 1E2EF 0300 0315 0062; # (a◌𞋯◌̕◌̀◌֮b; a◌֮◌𞋯◌̀◌̕b; a◌֮◌𞋯◌̀◌̕b; a◌֮◌𞋯◌̀◌̕b; a◌֮◌𞋯◌̀◌̕b; ) LATIN SMALL LETTER A, WANCHO TONE KOINI, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D0 0062;0061 302A 0316 1E8D0 059A 0062;0061 302A 0316 1E8D0 059A 0062;0061 302A 0316 1E8D0 059A 0062;0061 302A 0316 1E8D0 059A 0062; # (a◌֚◌̖◌〪◌ðž£b; a◌〪◌̖◌ðž£â—ŒÖšb; a◌〪◌̖◌ðž£â—ŒÖšb; a◌〪◌̖◌ðž£â—ŒÖšb; a◌〪◌̖◌ðž£â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER TEENS, LATIN SMALL LETTER B
-0061 1E8D0 059A 0316 302A 0062;0061 302A 1E8D0 0316 059A 0062;0061 302A 1E8D0 0316 059A 0062;0061 302A 1E8D0 0316 059A 0062;0061 302A 1E8D0 0316 059A 0062; # (aâ—Œðž£â—ŒÖšâ—ŒÌ–◌〪b; a◌〪◌ðž£â—ŒÌ–◌֚b; a◌〪◌ðž£â—ŒÌ–◌֚b; a◌〪◌ðž£â—ŒÌ–◌֚b; a◌〪◌ðž£â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TEENS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D1 0062;0061 302A 0316 1E8D1 059A 0062;0061 302A 0316 1E8D1 059A 0062;0061 302A 0316 1E8D1 059A 0062;0061 302A 0316 1E8D1 059A 0062; # (a◌֚◌̖◌〪◌𞣑b; a◌〪◌̖◌𞣑◌֚b; a◌〪◌̖◌𞣑◌֚b; a◌〪◌̖◌𞣑◌֚b; a◌〪◌̖◌𞣑◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER TENS, LATIN SMALL LETTER B
-0061 1E8D1 059A 0316 302A 0062;0061 302A 1E8D1 0316 059A 0062;0061 302A 1E8D1 0316 059A 0062;0061 302A 1E8D1 0316 059A 0062;0061 302A 1E8D1 0316 059A 0062; # (a◌𞣑◌֚◌̖◌〪b; a◌〪◌𞣑◌̖◌֚b; a◌〪◌𞣑◌̖◌֚b; a◌〪◌𞣑◌̖◌֚b; a◌〪◌𞣑◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TENS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D2 0062;0061 302A 0316 1E8D2 059A 0062;0061 302A 0316 1E8D2 059A 0062;0061 302A 0316 1E8D2 059A 0062;0061 302A 0316 1E8D2 059A 0062; # (a◌֚◌̖◌〪◌𞣒b; a◌〪◌̖◌𞣒◌֚b; a◌〪◌̖◌𞣒◌֚b; a◌〪◌̖◌𞣒◌֚b; a◌〪◌̖◌𞣒◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER HUNDREDS, LATIN SMALL LETTER B
-0061 1E8D2 059A 0316 302A 0062;0061 302A 1E8D2 0316 059A 0062;0061 302A 1E8D2 0316 059A 0062;0061 302A 1E8D2 0316 059A 0062;0061 302A 1E8D2 0316 059A 0062; # (a◌𞣒◌֚◌̖◌〪b; a◌〪◌𞣒◌̖◌֚b; a◌〪◌𞣒◌̖◌֚b; a◌〪◌𞣒◌̖◌֚b; a◌〪◌𞣒◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER HUNDREDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D3 0062;0061 302A 0316 1E8D3 059A 0062;0061 302A 0316 1E8D3 059A 0062;0061 302A 0316 1E8D3 059A 0062;0061 302A 0316 1E8D3 059A 0062; # (a◌֚◌̖◌〪◌𞣓b; a◌〪◌̖◌𞣓◌֚b; a◌〪◌̖◌𞣓◌֚b; a◌〪◌̖◌𞣓◌֚b; a◌〪◌̖◌𞣓◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER THOUSANDS, LATIN SMALL LETTER B
-0061 1E8D3 059A 0316 302A 0062;0061 302A 1E8D3 0316 059A 0062;0061 302A 1E8D3 0316 059A 0062;0061 302A 1E8D3 0316 059A 0062;0061 302A 1E8D3 0316 059A 0062; # (a◌𞣓◌֚◌̖◌〪b; a◌〪◌𞣓◌̖◌֚b; a◌〪◌𞣓◌̖◌֚b; a◌〪◌𞣓◌̖◌֚b; a◌〪◌𞣓◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER THOUSANDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D4 0062;0061 302A 0316 1E8D4 059A 0062;0061 302A 0316 1E8D4 059A 0062;0061 302A 0316 1E8D4 059A 0062;0061 302A 0316 1E8D4 059A 0062; # (a◌֚◌̖◌〪◌𞣔b; a◌〪◌̖◌𞣔◌֚b; a◌〪◌̖◌𞣔◌֚b; a◌〪◌̖◌𞣔◌֚b; a◌〪◌̖◌𞣔◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS, LATIN SMALL LETTER B
-0061 1E8D4 059A 0316 302A 0062;0061 302A 1E8D4 0316 059A 0062;0061 302A 1E8D4 0316 059A 0062;0061 302A 1E8D4 0316 059A 0062;0061 302A 1E8D4 0316 059A 0062; # (a◌𞣔◌֚◌̖◌〪b; a◌〪◌𞣔◌̖◌֚b; a◌〪◌𞣔◌̖◌֚b; a◌〪◌𞣔◌̖◌֚b; a◌〪◌𞣔◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D5 0062;0061 302A 0316 1E8D5 059A 0062;0061 302A 0316 1E8D5 059A 0062;0061 302A 0316 1E8D5 059A 0062;0061 302A 0316 1E8D5 059A 0062; # (a◌֚◌̖◌〪◌𞣕b; a◌〪◌̖◌𞣕◌֚b; a◌〪◌̖◌𞣕◌֚b; a◌〪◌̖◌𞣕◌֚b; a◌〪◌̖◌𞣕◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS, LATIN SMALL LETTER B
-0061 1E8D5 059A 0316 302A 0062;0061 302A 1E8D5 0316 059A 0062;0061 302A 1E8D5 0316 059A 0062;0061 302A 1E8D5 0316 059A 0062;0061 302A 1E8D5 0316 059A 0062; # (a◌𞣕◌֚◌̖◌〪b; a◌〪◌𞣕◌̖◌֚b; a◌〪◌𞣕◌̖◌֚b; a◌〪◌𞣕◌̖◌֚b; a◌〪◌𞣕◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
-0061 059A 0316 302A 1E8D6 0062;0061 302A 0316 1E8D6 059A 0062;0061 302A 0316 1E8D6 059A 0062;0061 302A 0316 1E8D6 059A 0062;0061 302A 0316 1E8D6 059A 0062; # (a◌֚◌̖◌〪◌𞣖b; a◌〪◌̖◌𞣖◌֚b; a◌〪◌̖◌𞣖◌֚b; a◌〪◌̖◌𞣖◌֚b; a◌〪◌̖◌𞣖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, MENDE KIKAKUI COMBINING NUMBER MILLIONS, LATIN SMALL LETTER B
-0061 1E8D6 059A 0316 302A 0062;0061 302A 1E8D6 0316 059A 0062;0061 302A 1E8D6 0316 059A 0062;0061 302A 1E8D6 0316 059A 0062;0061 302A 1E8D6 0316 059A 0062; # (a◌𞣖◌֚◌̖◌〪b; a◌〪◌𞣖◌̖◌֚b; a◌〪◌𞣖◌̖◌֚b; a◌〪◌𞣖◌̖◌֚b; a◌〪◌𞣖◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER MILLIONS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, IDEOGRAPHIC LEVEL TONE MARK, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D0 0062;0061 1DFA 0316 1E8D0 059A 0062;0061 1DFA 0316 1E8D0 059A 0062;0061 1DFA 0316 1E8D0 059A 0062;0061 1DFA 0316 1E8D0 059A 0062; # (a◌֚◌̖◌᷺◌ðž£b; a◌᷺◌̖◌ðž£â—ŒÖšb; a◌᷺◌̖◌ðž£â—ŒÖšb; a◌᷺◌̖◌ðž£â—ŒÖšb; a◌᷺◌̖◌ðž£â—ŒÖšb; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER TEENS, LATIN SMALL LETTER B
+0061 1E8D0 059A 0316 1DFA 0062;0061 1DFA 1E8D0 0316 059A 0062;0061 1DFA 1E8D0 0316 059A 0062;0061 1DFA 1E8D0 0316 059A 0062;0061 1DFA 1E8D0 0316 059A 0062; # (aâ—Œðž£â—ŒÖšâ—ŒÌ–◌᷺b; a◌᷺◌ðž£â—ŒÌ–◌֚b; a◌᷺◌ðž£â—ŒÌ–◌֚b; a◌᷺◌ðž£â—ŒÌ–◌֚b; a◌᷺◌ðž£â—ŒÌ–◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TEENS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D1 0062;0061 1DFA 0316 1E8D1 059A 0062;0061 1DFA 0316 1E8D1 059A 0062;0061 1DFA 0316 1E8D1 059A 0062;0061 1DFA 0316 1E8D1 059A 0062; # (a◌֚◌̖◌᷺◌𞣑b; a◌᷺◌̖◌𞣑◌֚b; a◌᷺◌̖◌𞣑◌֚b; a◌᷺◌̖◌𞣑◌֚b; a◌᷺◌̖◌𞣑◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER TENS, LATIN SMALL LETTER B
+0061 1E8D1 059A 0316 1DFA 0062;0061 1DFA 1E8D1 0316 059A 0062;0061 1DFA 1E8D1 0316 059A 0062;0061 1DFA 1E8D1 0316 059A 0062;0061 1DFA 1E8D1 0316 059A 0062; # (a◌𞣑◌֚◌̖◌᷺b; a◌᷺◌𞣑◌̖◌֚b; a◌᷺◌𞣑◌̖◌֚b; a◌᷺◌𞣑◌̖◌֚b; a◌᷺◌𞣑◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TENS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D2 0062;0061 1DFA 0316 1E8D2 059A 0062;0061 1DFA 0316 1E8D2 059A 0062;0061 1DFA 0316 1E8D2 059A 0062;0061 1DFA 0316 1E8D2 059A 0062; # (a◌֚◌̖◌᷺◌𞣒b; a◌᷺◌̖◌𞣒◌֚b; a◌᷺◌̖◌𞣒◌֚b; a◌᷺◌̖◌𞣒◌֚b; a◌᷺◌̖◌𞣒◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER HUNDREDS, LATIN SMALL LETTER B
+0061 1E8D2 059A 0316 1DFA 0062;0061 1DFA 1E8D2 0316 059A 0062;0061 1DFA 1E8D2 0316 059A 0062;0061 1DFA 1E8D2 0316 059A 0062;0061 1DFA 1E8D2 0316 059A 0062; # (a◌𞣒◌֚◌̖◌᷺b; a◌᷺◌𞣒◌̖◌֚b; a◌᷺◌𞣒◌̖◌֚b; a◌᷺◌𞣒◌̖◌֚b; a◌᷺◌𞣒◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER HUNDREDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D3 0062;0061 1DFA 0316 1E8D3 059A 0062;0061 1DFA 0316 1E8D3 059A 0062;0061 1DFA 0316 1E8D3 059A 0062;0061 1DFA 0316 1E8D3 059A 0062; # (a◌֚◌̖◌᷺◌𞣓b; a◌᷺◌̖◌𞣓◌֚b; a◌᷺◌̖◌𞣓◌֚b; a◌᷺◌̖◌𞣓◌֚b; a◌᷺◌̖◌𞣓◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER THOUSANDS, LATIN SMALL LETTER B
+0061 1E8D3 059A 0316 1DFA 0062;0061 1DFA 1E8D3 0316 059A 0062;0061 1DFA 1E8D3 0316 059A 0062;0061 1DFA 1E8D3 0316 059A 0062;0061 1DFA 1E8D3 0316 059A 0062; # (a◌𞣓◌֚◌̖◌᷺b; a◌᷺◌𞣓◌̖◌֚b; a◌᷺◌𞣓◌̖◌֚b; a◌᷺◌𞣓◌̖◌֚b; a◌᷺◌𞣓◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER THOUSANDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D4 0062;0061 1DFA 0316 1E8D4 059A 0062;0061 1DFA 0316 1E8D4 059A 0062;0061 1DFA 0316 1E8D4 059A 0062;0061 1DFA 0316 1E8D4 059A 0062; # (a◌֚◌̖◌᷺◌𞣔b; a◌᷺◌̖◌𞣔◌֚b; a◌᷺◌̖◌𞣔◌֚b; a◌᷺◌̖◌𞣔◌֚b; a◌᷺◌̖◌𞣔◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS, LATIN SMALL LETTER B
+0061 1E8D4 059A 0316 1DFA 0062;0061 1DFA 1E8D4 0316 059A 0062;0061 1DFA 1E8D4 0316 059A 0062;0061 1DFA 1E8D4 0316 059A 0062;0061 1DFA 1E8D4 0316 059A 0062; # (a◌𞣔◌֚◌̖◌᷺b; a◌᷺◌𞣔◌̖◌֚b; a◌᷺◌𞣔◌̖◌֚b; a◌᷺◌𞣔◌̖◌֚b; a◌᷺◌𞣔◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER TEN THOUSANDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D5 0062;0061 1DFA 0316 1E8D5 059A 0062;0061 1DFA 0316 1E8D5 059A 0062;0061 1DFA 0316 1E8D5 059A 0062;0061 1DFA 0316 1E8D5 059A 0062; # (a◌֚◌̖◌᷺◌𞣕b; a◌᷺◌̖◌𞣕◌֚b; a◌᷺◌̖◌𞣕◌֚b; a◌᷺◌̖◌𞣕◌֚b; a◌᷺◌̖◌𞣕◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS, LATIN SMALL LETTER B
+0061 1E8D5 059A 0316 1DFA 0062;0061 1DFA 1E8D5 0316 059A 0062;0061 1DFA 1E8D5 0316 059A 0062;0061 1DFA 1E8D5 0316 059A 0062;0061 1DFA 1E8D5 0316 059A 0062; # (a◌𞣕◌֚◌̖◌᷺b; a◌᷺◌𞣕◌̖◌֚b; a◌᷺◌𞣕◌̖◌֚b; a◌᷺◌𞣕◌̖◌֚b; a◌᷺◌𞣕◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER HUNDRED THOUSANDS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
+0061 059A 0316 1DFA 1E8D6 0062;0061 1DFA 0316 1E8D6 059A 0062;0061 1DFA 0316 1E8D6 059A 0062;0061 1DFA 0316 1E8D6 059A 0062;0061 1DFA 0316 1E8D6 059A 0062; # (a◌֚◌̖◌᷺◌𞣖b; a◌᷺◌̖◌𞣖◌֚b; a◌᷺◌̖◌𞣖◌֚b; a◌᷺◌̖◌𞣖◌֚b; a◌᷺◌̖◌𞣖◌֚b; ) LATIN SMALL LETTER A, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, MENDE KIKAKUI COMBINING NUMBER MILLIONS, LATIN SMALL LETTER B
+0061 1E8D6 059A 0316 1DFA 0062;0061 1DFA 1E8D6 0316 059A 0062;0061 1DFA 1E8D6 0316 059A 0062;0061 1DFA 1E8D6 0316 059A 0062;0061 1DFA 1E8D6 0316 059A 0062; # (a◌𞣖◌֚◌̖◌᷺b; a◌᷺◌𞣖◌̖◌֚b; a◌᷺◌𞣖◌̖◌֚b; a◌᷺◌𞣖◌̖◌֚b; a◌᷺◌𞣖◌̖◌֚b; ) LATIN SMALL LETTER A, MENDE KIKAKUI COMBINING NUMBER MILLIONS, HEBREW ACCENT YETIV, COMBINING GRAVE ACCENT BELOW, COMBINING DOT BELOW LEFT, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E944 0062;00E0 05AE 1E944 0315 0062;0061 05AE 0300 1E944 0315 0062;00E0 05AE 1E944 0315 0062;0061 05AE 0300 1E944 0315 0062; # (a◌̕◌̀◌֮◌𞥄b; à◌֮◌𞥄◌̕b; a◌֮◌̀◌𞥄◌̕b; à◌֮◌𞥄◌̕b; a◌֮◌̀◌𞥄◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ADLAM ALIF LENGTHENER, LATIN SMALL LETTER B
0061 1E944 0315 0300 05AE 0062;0061 05AE 1E944 0300 0315 0062;0061 05AE 1E944 0300 0315 0062;0061 05AE 1E944 0300 0315 0062;0061 05AE 1E944 0300 0315 0062; # (a◌𞥄◌̕◌̀◌֮b; a◌֮◌𞥄◌̀◌̕b; a◌֮◌𞥄◌̀◌̕b; a◌֮◌𞥄◌̀◌̕b; a◌֮◌𞥄◌̀◌̕b; ) LATIN SMALL LETTER A, ADLAM ALIF LENGTHENER, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, LATIN SMALL LETTER B
0061 0315 0300 05AE 1E945 0062;00E0 05AE 1E945 0315 0062;0061 05AE 0300 1E945 0315 0062;00E0 05AE 1E945 0315 0062;0061 05AE 0300 1E945 0315 0062; # (a◌̕◌̀◌֮◌𞥅b; à◌֮◌𞥅◌̕b; a◌֮◌̀◌𞥅◌̕b; à◌֮◌𞥅◌̕b; a◌֮◌̀◌𞥅◌̕b; ) LATIN SMALL LETTER A, COMBINING COMMA ABOVE RIGHT, COMBINING GRAVE ACCENT, HEBREW ACCENT ZINOR, ADLAM VOWEL LENGTHENER, LATIN SMALL LETTER B
diff --git a/lib/stdlib/test/uri_string_SUITE.erl b/lib/stdlib/test/uri_string_SUITE.erl
index 96e4a9d41b..6a6bff2688 100644
--- a/lib/stdlib/test/uri_string_SUITE.erl
+++ b/lib/stdlib/test/uri_string_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
-module(uri_string_SUITE).
-include_lib("common_test/include/ct.hrl").
+-compile({nowarn_deprecated_function, [{http_uri, encode, 1}]}).
+-compile({nowarn_deprecated_function, [{http_uri, decode, 1}]}).
-export([all/0, suite/0,groups/0,
normalize/1, normalize_map/1, normalize_return_map/1, normalize_negative/1,
@@ -53,7 +55,8 @@
interop_query_latin1/1, interop_query_utf8/1,
regression_parse/1, regression_recompose/1, regression_normalize/1,
recompose_host_relative_path/1,
- recompose_host_absolute_path/1
+ recompose_host_absolute_path/1,
+ quote/1
]).
@@ -148,7 +151,8 @@ all() ->
regression_recompose,
regression_normalize,
recompose_host_relative_path,
- recompose_host_absolute_path
+ recompose_host_absolute_path,
+ quote
].
groups() ->
@@ -587,18 +591,22 @@ parse_host_ipv6(_Config) ->
{error,invalid_uri,"G"} = uri_string:parse("//[2001:0db8:0000:0000:0000:0000:1428:G7ab]").
parse_port(_Config) ->
- #{path:= "/:8042"} =
- uri_string:parse("/:8042"),
- #{host:= "", port := 8042} =
- uri_string:parse("//:8042"),
- #{host := "example.com", port:= 8042} =
- uri_string:parse("//example.com:8042"),
- #{scheme := "foo", path := "/:8042"} =
- uri_string:parse("foo:/:8042"),
- #{scheme := "foo", host := "", port := 8042} =
- uri_string:parse("foo://:8042"),
- #{scheme := "foo", host := "example.com", port := 8042} =
- uri_string:parse("foo://example.com:8042").
+ parse_port_with_param("8042", 8042),
+ parse_port_with_param("", undefined).
+
+parse_port_with_param(PortString, Expected) ->
+ #{path:= "/:" ++ PortString} =
+ uri_string:parse("/:" ++ PortString),
+ #{host:= "", port := Expected} =
+ uri_string:parse("//:" ++ PortString),
+ #{host := "example.com", port:= Expected} =
+ uri_string:parse("//example.com:" ++ PortString),
+ #{scheme := "foo", path := "/:" ++ PortString} =
+ uri_string:parse("foo:/:" ++ PortString),
+ #{scheme := "foo", host := "", port := Expected} =
+ uri_string:parse("foo://:" ++ PortString),
+ #{scheme := "foo", host := "example.com", port := Expected} =
+ uri_string:parse("foo://example.com:" ++ PortString).
parse_path(_Config) ->
#{path := "over/there"} = uri_string:parse("over/there"),
@@ -1016,7 +1024,19 @@ normalize(_Config) ->
<<"tftp://localhost">> =
uri_string:normalize(<<"tftp://localhost:69">>),
<<"/foo/%2F/bar">> =
- uri_string:normalize(<<"/foo/%2f/%62ar">>).
+ uri_string:normalize(<<"/foo/%2f/%62ar">>),
+ <<"https://localhost/">> =
+ uri_string:normalize(<<"https://localhost">>),
+ <<"https://localhost/">> =
+ uri_string:normalize(<<"https://localhost/">>),
+ <<"https://localhost/">> =
+ uri_string:normalize(<<"https://localhost:/">>),
+ <<"https://localhost/">> =
+ uri_string:normalize(<<"https://localhost:">>),
+ <<"yeti://localhost/">> =
+ uri_string:normalize(<<"yeti://localhost:/">>),
+ <<"yeti://localhost">> =
+ uri_string:normalize(<<"yeti://localhost:">>).
normalize_map(_Config) ->
"/a/g" = uri_string:normalize(#{path => "/a/b/c/./../../g"}),
@@ -1047,7 +1067,13 @@ normalize_map(_Config) ->
uri_string:normalize(#{scheme => <<"tftp">>,port => 69,path => <<>>,
host => <<"localhost">>}),
"/foo/%2F/bar" =
- uri_string:normalize(#{path => "/foo/%2f/%62ar"}).
+ uri_string:normalize(#{path => "/foo/%2f/%62ar"}),
+ <<"https://localhost/">> =
+ uri_string:normalize(#{scheme => <<"https">>,port => undefined,path => <<>>,
+ host => <<"localhost">>}),
+ <<"yeti://localhost">> =
+ uri_string:normalize(#{scheme => <<"yeti">>,port => undefined,path => <<>>,
+ host => <<"localhost">>}).
normalize_return_map(_Config) ->
#{scheme := "http",path := "/a/g",host := "localhost-örebro"} =
@@ -1332,3 +1358,132 @@ recompose_host_absolute_path(_Config) ->
path => [<<"/f">>,<<"oo">>]}),
ok.
+%%-------------------------------------------------------------------------
+%% Quote tests
+%%-------------------------------------------------------------------------
+quote(_Config) ->
+ TestQuote =
+ fun(Unquoted, Quoted) ->
+ Quoted = uri_string:quote(Unquoted)
+ end,
+
+ [TestQuote(U, Q) || #{unquoted := U, quoted := Q} <- get_quote_data()],
+ [TestQuote(U, Q) || #{unquoted_b := U, quoted_b := Q} <- get_quote_data()],
+
+ Head = fun([H | _]) -> H;
+ (<<H, _/binary>>) -> H
+ end,
+
+ TestQuoteUnquote =
+ fun(Unquoted) ->
+ %% case below should be removed when functions used are removed
+ case Head(Unquoted) =< 127 of
+ true ->
+ Unquoted = http_uri:decode(http_uri:encode(Unquoted));
+ _ ->
+ ok
+ end,
+ Unquoted = uri_string:unquote(uri_string:quote(Unquoted))
+ end,
+ [TestQuoteUnquote(U) || #{unquoted := U} <- get_quote_data()],
+ [TestQuoteUnquote(U) || #{unquoted_b := U} <- get_quote_data()],
+
+ TestQuoteWithSafeList =
+ fun(Unquoted, Quoted) ->
+ Safe = "!$()*", %% characters not encoded by old http_uri:encode
+ Result = uri_string:quote(Unquoted, Safe),
+ %% case below should be removed when function used are removed
+ case Head(Unquoted) =< 127 of
+ true ->
+ Result = http_uri:encode(Unquoted);
+ _ ->
+ ok
+ end,
+ case lists:member(Head(Unquoted), Safe) of
+ true ->
+ Unquoted = Result;
+ false ->
+ Quoted = Result
+ end
+ end,
+ [TestQuoteWithSafeList(U, Q) || #{unquoted := U, quoted := Q} <- get_quote_data()],
+ [TestQuoteWithSafeList(U, Q) || #{unquoted_b := U, quoted_b := Q} <- get_quote_data()],
+
+
+ ComposePath = fun (PathSegments, Safe) ->
+ lists:join("/", [uri_string:quote(S, Safe) ||
+ S <- PathSegments])
+ end,
+
+ %% / used as data see GH-5368
+ ExampleURI1 = "https://internal.api.com/devices/Ethernet0%2F4",
+ ExampleURI1 = uri_string:recompose(
+ #{scheme => "https",
+ host => "internal.api.com",
+ path => ComposePath(["devices", "Ethernet0/4"],
+ "")}),
+
+ %% sub-delims as data
+ %% in this example ComposePath must treat sub-delims and '%' as safe character
+ %% to avoid re-encoding encoded characters
+ ExampleURI2 = "yeti://localhost/folder/file.txt,version=1%2C1",
+ ExampleURI2 = uri_string:recompose(
+ #{scheme => "yeti",
+ host => "localhost",
+ path => ComposePath(["folder", "file.txt,version=" ++
+ uri_string:quote("1,1")],
+ ",=%")}),
+
+ %% percent character as data
+ ExampleURI3 = "yeti://localhost/folder/file_with_%25.txt",
+ ExampleURI3 = uri_string:recompose(
+ #{scheme => "yeti",
+ host => "localhost",
+ path => ComposePath(["folder", "file_with_" ++
+ uri_string:quote("%") ++ ".txt"],
+ "%")}),
+ ok.
+
+get_quote_data() ->
+ [%% reserved/gen-delims
+ #{unquoted => ":", quoted => "%3A", unquoted_b =><<":">>, quoted_b=> <<"%3A">>},
+ #{unquoted => "/", quoted => "%2F", unquoted_b =><<"/">>, quoted_b=> <<"%2F">>},
+ #{unquoted => "?", quoted => "%3F", unquoted_b =><<"?">>, quoted_b=> <<"%3F">>},
+ #{unquoted => "#", quoted => "%23", unquoted_b =><<"#">>, quoted_b=> <<"%23">>},
+ #{unquoted => "[", quoted => "%5B", unquoted_b =><<"[">>, quoted_b=> <<"%5B">>},
+ #{unquoted => "]", quoted => "%5D", unquoted_b =><<"]">>, quoted_b=> <<"%5D">>},
+ #{unquoted => "@", quoted => "%40", unquoted_b =><<"@">>, quoted_b=> <<"%40">>},
+ %% reserved/sub-delims
+ #{unquoted => "!", quoted => "%21", unquoted_b =><<"!">>, quoted_b=> <<"%21">>},
+ #{unquoted => "$", quoted => "%24", unquoted_b =><<"$">>, quoted_b=> <<"%24">>},
+ #{unquoted => "&", quoted => "%26", unquoted_b =><<"&">>, quoted_b=> <<"%26">>},
+ #{unquoted => "'", quoted => "%27", unquoted_b =><<"'">>, quoted_b=> <<"%27">>},
+ #{unquoted => "(", quoted => "%28", unquoted_b =><<"(">>, quoted_b=> <<"%28">>},
+ #{unquoted => ")", quoted => "%29", unquoted_b =><<")">>, quoted_b=> <<"%29">>},
+ #{unquoted => "*", quoted => "%2A", unquoted_b =><<"*">>, quoted_b=> <<"%2A">>},
+ #{unquoted => "+", quoted => "%2B", unquoted_b =><<"+">>, quoted_b=> <<"%2B">>},
+ #{unquoted => ",", quoted => "%2C", unquoted_b =><<",">>, quoted_b=> <<"%2C">>},
+ #{unquoted => ";", quoted => "%3B", unquoted_b =><<";">>, quoted_b=> <<"%3B">>},
+ #{unquoted => "=", quoted => "%3D", unquoted_b =><<"=">>, quoted_b=> <<"%3D">>},
+ %% other not unreserved
+ #{unquoted => "<", quoted => "%3C", unquoted_b =><<"<">>, quoted_b=> <<"%3C">>},
+ #{unquoted => ">", quoted => "%3E", unquoted_b =><<">">>, quoted_b=> <<"%3E">>},
+ #{unquoted => "\"", quoted => "%22", unquoted_b =><<"\"">>, quoted_b=> <<"%22">>},
+ #{unquoted => "{", quoted => "%7B", unquoted_b =><<"{">>, quoted_b=> <<"%7B">>},
+ #{unquoted => "}", quoted => "%7D", unquoted_b =><<"}">>, quoted_b=> <<"%7D">>},
+ #{unquoted => "|", quoted => "%7C", unquoted_b =><<"|">>, quoted_b=> <<"%7C">>},
+ #{unquoted => "\\", quoted => "%5C", unquoted_b =><<"\\">>, quoted_b=> <<"%5C">>},
+ #{unquoted => "^", quoted => "%5E", unquoted_b =><<"^">>, quoted_b=> <<"%5E">>},
+ #{unquoted => "%", quoted => "%25", unquoted_b =><<"%">>, quoted_b=> <<"%25">>},
+ #{unquoted => " ", quoted => "%20", unquoted_b =><<" ">>, quoted_b=> <<"%20">>},
+ %% non-ASCII
+ #{unquoted => "örebro", quoted => "%C3%B6rebro",
+ unquoted_b =><<"örebro"/utf8>>, quoted_b=> <<"%C3%B6rebro">>},
+ #{unquoted => "Åódź", quoted => "%C5%81%C3%B3d%C5%BA",
+ unquoted_b =><<"Åódź"/utf8>>, quoted_b=> <<"%C5%81%C3%B3d%C5%BA">>},
+ %% unreserved non alpha, non digit characters
+ #{unquoted => "-", quoted => "-", unquoted_b =><<"-">>, quoted_b=> <<"-">>},
+ #{unquoted => ".", quoted => ".", unquoted_b =><<".">>, quoted_b=> <<".">>},
+ #{unquoted => "_", quoted => "_", unquoted_b =><<"_">>, quoted_b=> <<"_">>},
+ #{unquoted => "~", quoted => "~", unquoted_b =><<"~">>, quoted_b=> <<"~">>}
+ ].
diff --git a/lib/stdlib/uc_spec/CaseFolding.txt b/lib/stdlib/uc_spec/CaseFolding.txt
index 033788b253..932ace29e6 100644
--- a/lib/stdlib/uc_spec/CaseFolding.txt
+++ b/lib/stdlib/uc_spec/CaseFolding.txt
@@ -1,6 +1,6 @@
-# CaseFolding-13.0.0.txt
-# Date: 2019-09-08, 23:30:59 GMT
-# © 2019 Unicode®, Inc.
+# CaseFolding-14.0.0.txt
+# Date: 2021-03-08, 19:35:41 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -1050,6 +1050,7 @@
2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC
2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A
2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
+2C2F; C; 2C5F; # GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI
2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR
2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE
2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE
@@ -1230,12 +1231,16 @@ A7B8; C; A7B9; # LATIN CAPITAL LETTER U WITH STROKE
A7BA; C; A7BB; # LATIN CAPITAL LETTER GLOTTAL A
A7BC; C; A7BD; # LATIN CAPITAL LETTER GLOTTAL I
A7BE; C; A7BF; # LATIN CAPITAL LETTER GLOTTAL U
+A7C0; C; A7C1; # LATIN CAPITAL LETTER OLD POLISH O
A7C2; C; A7C3; # LATIN CAPITAL LETTER ANGLICANA W
A7C4; C; A794; # LATIN CAPITAL LETTER C WITH PALATAL HOOK
A7C5; C; 0282; # LATIN CAPITAL LETTER S WITH HOOK
A7C6; C; 1D8E; # LATIN CAPITAL LETTER Z WITH PALATAL HOOK
A7C7; C; A7C8; # LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY
A7C9; C; A7CA; # LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY
+A7D0; C; A7D1; # LATIN CAPITAL LETTER CLOSED INSULAR G
+A7D6; C; A7D7; # LATIN CAPITAL LETTER MIDDLE SCOTS S
+A7D8; C; A7D9; # LATIN CAPITAL LETTER SIGMOID S
A7F5; C; A7F6; # LATIN CAPITAL LETTER REVERSED HALF H
AB70; C; 13A0; # CHEROKEE SMALL LETTER A
AB71; C; 13A1; # CHEROKEE SMALL LETTER E
@@ -1431,6 +1436,41 @@ FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z
104D1; C; 104F9; # OSAGE CAPITAL LETTER GHA
104D2; C; 104FA; # OSAGE CAPITAL LETTER ZA
104D3; C; 104FB; # OSAGE CAPITAL LETTER ZHA
+10570; C; 10597; # VITHKUQI CAPITAL LETTER A
+10571; C; 10598; # VITHKUQI CAPITAL LETTER BBE
+10572; C; 10599; # VITHKUQI CAPITAL LETTER BE
+10573; C; 1059A; # VITHKUQI CAPITAL LETTER CE
+10574; C; 1059B; # VITHKUQI CAPITAL LETTER CHE
+10575; C; 1059C; # VITHKUQI CAPITAL LETTER DE
+10576; C; 1059D; # VITHKUQI CAPITAL LETTER DHE
+10577; C; 1059E; # VITHKUQI CAPITAL LETTER EI
+10578; C; 1059F; # VITHKUQI CAPITAL LETTER E
+10579; C; 105A0; # VITHKUQI CAPITAL LETTER FE
+1057A; C; 105A1; # VITHKUQI CAPITAL LETTER GA
+1057C; C; 105A3; # VITHKUQI CAPITAL LETTER HA
+1057D; C; 105A4; # VITHKUQI CAPITAL LETTER HHA
+1057E; C; 105A5; # VITHKUQI CAPITAL LETTER I
+1057F; C; 105A6; # VITHKUQI CAPITAL LETTER IJE
+10580; C; 105A7; # VITHKUQI CAPITAL LETTER JE
+10581; C; 105A8; # VITHKUQI CAPITAL LETTER KA
+10582; C; 105A9; # VITHKUQI CAPITAL LETTER LA
+10583; C; 105AA; # VITHKUQI CAPITAL LETTER LLA
+10584; C; 105AB; # VITHKUQI CAPITAL LETTER ME
+10585; C; 105AC; # VITHKUQI CAPITAL LETTER NE
+10586; C; 105AD; # VITHKUQI CAPITAL LETTER NJE
+10587; C; 105AE; # VITHKUQI CAPITAL LETTER O
+10588; C; 105AF; # VITHKUQI CAPITAL LETTER PE
+10589; C; 105B0; # VITHKUQI CAPITAL LETTER QA
+1058A; C; 105B1; # VITHKUQI CAPITAL LETTER RE
+1058C; C; 105B3; # VITHKUQI CAPITAL LETTER SE
+1058D; C; 105B4; # VITHKUQI CAPITAL LETTER SHE
+1058E; C; 105B5; # VITHKUQI CAPITAL LETTER TE
+1058F; C; 105B6; # VITHKUQI CAPITAL LETTER THE
+10590; C; 105B7; # VITHKUQI CAPITAL LETTER U
+10591; C; 105B8; # VITHKUQI CAPITAL LETTER VE
+10592; C; 105B9; # VITHKUQI CAPITAL LETTER XE
+10594; C; 105BB; # VITHKUQI CAPITAL LETTER Y
+10595; C; 105BC; # VITHKUQI CAPITAL LETTER ZE
10C80; C; 10CC0; # OLD HUNGARIAN CAPITAL LETTER A
10C81; C; 10CC1; # OLD HUNGARIAN CAPITAL LETTER AA
10C82; C; 10CC2; # OLD HUNGARIAN CAPITAL LETTER EB
diff --git a/lib/stdlib/uc_spec/CompositionExclusions.txt b/lib/stdlib/uc_spec/CompositionExclusions.txt
index 52bbb465bc..74e425e2a0 100644
--- a/lib/stdlib/uc_spec/CompositionExclusions.txt
+++ b/lib/stdlib/uc_spec/CompositionExclusions.txt
@@ -1,10 +1,10 @@
-# CompositionExclusions-13.0.0.txt
-# Date: 2019-10-15, 18:27:00 GMT [KW, LI]
-# © 2019 Unicode®, Inc.
-# For terms of use, see http://www.unicode.org/terms_of_use.html
+# CompositionExclusions-14.0.0.txt
+# Date: 2021-03-30, 23:59:00 GMT [KW, LI]
+# © 2021 Unicode®, Inc.
+# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
-# For documentation, see http://www.unicode.org/reports/tr44/
+# For documentation, see https://www.unicode.org/reports/tr44/
#
# This file lists the characters for the Composition Exclusion Table
# defined in UAX #15, Unicode Normalization Forms.
@@ -13,7 +13,7 @@
# Unicode Character Database.
#
# For more information, see
-# http://www.unicode.org/unicode/reports/tr15/#Primary_Exclusion_List_Table
+# https://www.unicode.org/reports/tr15/#Primary_Exclusion_List_Table
#
# For a full derivation of composition exclusions, see the derived property
# Full_Composition_Exclusion in DerivedNormalizationProps.txt
diff --git a/lib/stdlib/uc_spec/GraphemeBreakProperty.txt b/lib/stdlib/uc_spec/GraphemeBreakProperty.txt
index 6ee92f6eec..dd2569064a 100644
--- a/lib/stdlib/uc_spec/GraphemeBreakProperty.txt
+++ b/lib/stdlib/uc_spec/GraphemeBreakProperty.txt
@@ -1,6 +1,6 @@
-# GraphemeBreakProperty-13.0.0.txt
-# Date: 2019-10-21, 14:30:35 GMT
-# © 2019 Unicode®, Inc.
+# GraphemeBreakProperty-14.0.0.txt
+# Date: 2021-08-12, 23:13:02 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -21,6 +21,7 @@
0600..0605 ; Prepend # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE
06DD ; Prepend # Cf ARABIC END OF AYAH
070F ; Prepend # Cf SYRIAC ABBREVIATION MARK
+0890..0891 ; Prepend # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
08E2 ; Prepend # Cf ARABIC DISPUTED END OF AYAH
0D4E ; Prepend # Lo MALAYALAM LETTER DOT REPH
110BD ; Prepend # Cf KAITHI NUMBER SIGN
@@ -32,7 +33,7 @@
11A84..11A89 ; Prepend # Lo [6] SOYOMBO SIGN JIHVAMULIYA..SOYOMBO CLUSTER-INITIAL LETTER SA
11D46 ; Prepend # Lo MASARAM GONDI REPHA
-# Total code points: 24
+# Total code points: 26
# ================================================
@@ -104,7 +105,8 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
0825..0827 ; Extend # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
0829..082D ; Extend # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
0859..085B ; Extend # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
-08D3..08E1 ; Extend # Mn [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA
+0898..089F ; Extend # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
+08CA..08E1 ; Extend # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA
08E3..0902 ; Extend # Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA
093A ; Extend # Mn DEVANAGARI VOWEL SIGN OE
093C ; Extend # Mn DEVANAGARI SIGN NUKTA
@@ -151,6 +153,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
0BD7 ; Extend # Mc TAMIL AU LENGTH MARK
0C00 ; Extend # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE
0C04 ; Extend # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE
+0C3C ; Extend # Mn TELUGU SIGN NUKTA
0C3E..0C40 ; Extend # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
0C46..0C48 ; Extend # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
0C4A..0C4D ; Extend # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
@@ -206,7 +209,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
109D ; Extend # Mn MYANMAR VOWEL SIGN AITON AI
135D..135F ; Extend # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
1712..1714 ; Extend # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
-1732..1734 ; Extend # Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD
+1732..1733 ; Extend # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U
1752..1753 ; Extend # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
1772..1773 ; Extend # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
17B4..17B5 ; Extend # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
@@ -215,6 +218,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
17C9..17D3 ; Extend # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
17DD ; Extend # Mn KHMER SIGN ATTHACAN
180B..180D ; Extend # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+180F ; Extend # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
1885..1886 ; Extend # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
18A9 ; Extend # Mn MONGOLIAN LETTER ALI GALI DAGALGA
1920..1922 ; Extend # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
@@ -232,7 +236,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
1A7F ; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
1AB0..1ABD ; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
1ABE ; Extend # Me COMBINING PARENTHESES OVERLAY
-1ABF..1AC0 ; Extend # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW
+1ABF..1ACE ; Extend # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
1B00..1B03 ; Extend # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
1B34 ; Extend # Mn BALINESE SIGN REREKAN
1B35 ; Extend # Mc BALINESE VOWEL SIGN TEDUNG
@@ -256,8 +260,7 @@ E01F0..E0FFF ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
1CED ; Extend # Mn VEDIC SIGN TIRYAK
1CF4 ; Extend # Mn VEDIC TONE CANDRA ABOVE
1CF8..1CF9 ; Extend # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
-1DC0..1DF9 ; Extend # Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW
-1DFB..1DFF ; Extend # Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+1DC0..1DFF ; Extend # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
200C ; Extend # Cf ZERO WIDTH NON-JOINER
20D0..20DC ; Extend # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
20DD..20E0 ; Extend # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH
@@ -322,11 +325,15 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
10D24..10D27 ; Extend # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
10EAB..10EAC ; Extend # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
10F46..10F50 ; Extend # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
+10F82..10F85 ; Extend # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
11001 ; Extend # Mn BRAHMI SIGN ANUSVARA
11038..11046 ; Extend # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
+11070 ; Extend # Mn BRAHMI SIGN OLD TAMIL VIRAMA
+11073..11074 ; Extend # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O
1107F..11081 ; Extend # Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA
110B3..110B6 ; Extend # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
110B9..110BA ; Extend # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
+110C2 ; Extend # Mn KAITHI VOWEL SIGN VOCALIC R
11100..11102 ; Extend # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
11127..1112B ; Extend # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
1112D..11134 ; Extend # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
@@ -412,6 +419,8 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
16F8F..16F92 ; Extend # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16FE4 ; Extend # Mn KHITAN SMALL SCRIPT FILLER
1BC9D..1BC9E ; Extend # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1CF00..1CF2D ; Extend # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
+1CF30..1CF46 ; Extend # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
1D165 ; Extend # Mc MUSICAL SYMBOL COMBINING STEM
1D167..1D169 ; Extend # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
1D16E..1D172 ; Extend # Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5
@@ -431,6 +440,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
1E023..1E024 ; Extend # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
1E026..1E02A ; Extend # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
1E130..1E136 ; Extend # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
+1E2AE ; Extend # Mn TOTO SIGN RISING TONE
1E2EC..1E2EF ; Extend # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
1E8D0..1E8D6 ; Extend # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
1E944..1E94A ; Extend # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
@@ -438,7 +448,7 @@ FF9E..FF9F ; Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDT
E0020..E007F ; Extend # Cf [96] TAG SPACE..CANCEL TAG
E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-# Total code points: 1984
+# Total code points: 2095
# ================================================
@@ -495,6 +505,8 @@ E0100..E01EF ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
103B..103C ; SpacingMark # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA
1056..1057 ; SpacingMark # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR
1084 ; SpacingMark # Mc MYANMAR VOWEL SIGN SHAN E
+1715 ; SpacingMark # Mc TAGALOG SIGN PAMUDPOD
+1734 ; SpacingMark # Mc HANUNOO SIGN PAMUDPOD
17B6 ; SpacingMark # Mc KHMER VOWEL SIGN AA
17BE..17C5 ; SpacingMark # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU
17C7..17C8 ; SpacingMark # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU
@@ -579,7 +591,6 @@ ABEC ; SpacingMark # Mc MEETEI MAYEK LUM IYEK
116AC ; SpacingMark # Mc TAKRI SIGN VISARGA
116AE..116AF ; SpacingMark # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
116B6 ; SpacingMark # Mc TAKRI SIGN VIRAMA
-11720..11721 ; SpacingMark # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
11726 ; SpacingMark # Mc AHOM VOWEL SIGN E
1182C..1182E ; SpacingMark # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
11838 ; SpacingMark # Mc DOGRA SIGN VISARGA
diff --git a/lib/stdlib/uc_spec/PropList.txt b/lib/stdlib/uc_spec/PropList.txt
index 7d2f44c56f..0a5a934682 100644
--- a/lib/stdlib/uc_spec/PropList.txt
+++ b/lib/stdlib/uc_spec/PropList.txt
@@ -1,6 +1,6 @@
-# PropList-13.0.0.txt
-# Date: 2019-11-27, 03:13:28 GMT
-# © 2019 Unicode®, Inc.
+# PropList-14.0.0.txt
+# Date: 2021-08-12, 23:13:05 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
@@ -54,6 +54,7 @@
2E1A ; Dash # Pd HYPHEN WITH DIAERESIS
2E3A..2E3B ; Dash # Pd [2] TWO-EM DASH..THREE-EM DASH
2E40 ; Dash # Pd DOUBLE HYPHEN
+2E5D ; Dash # Pd OBLIQUE HYPHEN
301C ; Dash # Pd WAVE DASH
3030 ; Dash # Pd WAVY DASH
30A0 ; Dash # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN
@@ -63,7 +64,7 @@ FE63 ; Dash # Pd SMALL HYPHEN-MINUS
FF0D ; Dash # Pd FULLWIDTH HYPHEN-MINUS
10EAD ; Dash # Pd YEZIDI HYPHENATION MARK
-# Total code points: 29
+# Total code points: 30
# ================================================
@@ -126,7 +127,7 @@ FF63 ; Quotation_Mark # Pe HALFWIDTH RIGHT CORNER BRACKET
05C3 ; Terminal_Punctuation # Po HEBREW PUNCTUATION SOF PASUQ
060C ; Terminal_Punctuation # Po ARABIC COMMA
061B ; Terminal_Punctuation # Po ARABIC SEMICOLON
-061E..061F ; Terminal_Punctuation # Po [2] ARABIC TRIPLE DOT PUNCTUATION MARK..ARABIC QUESTION MARK
+061D..061F ; Terminal_Punctuation # Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK
06D4 ; Terminal_Punctuation # Po ARABIC FULL STOP
0700..070A ; Terminal_Punctuation # Po [11] SYRIAC END OF PARAGRAPH..SYRIAC CONTRACTION
070C ; Terminal_Punctuation # Po SYRIAC HARKLEAN METOBELUS
@@ -150,6 +151,7 @@ FF63 ; Quotation_Mark # Pe HALFWIDTH RIGHT CORNER BRACKET
1AA8..1AAB ; Terminal_Punctuation # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU
1B5A..1B5B ; Terminal_Punctuation # Po [2] BALINESE PANTI..BALINESE PAMADA
1B5D..1B5F ; Terminal_Punctuation # Po [3] BALINESE CARIK PAMUNGKAH..BALINESE CARIK PAREREN
+1B7D..1B7E ; Terminal_Punctuation # Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG
1C3B..1C3F ; Terminal_Punctuation # Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
1C7E..1C7F ; Terminal_Punctuation # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
203C..203D ; Terminal_Punctuation # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG
@@ -159,6 +161,7 @@ FF63 ; Quotation_Mark # Pe HALFWIDTH RIGHT CORNER BRACKET
2E41 ; Terminal_Punctuation # Po REVERSED COMMA
2E4C ; Terminal_Punctuation # Po MEDIEVAL COMMA
2E4E..2E4F ; Terminal_Punctuation # Po [2] PUNCTUS ELEVATUS MARK..CORNISH VERSE DIVIDER
+2E53..2E54 ; Terminal_Punctuation # Po [2] MEDIEVAL EXCLAMATION MARK..MEDIEVAL QUESTION MARK
3001..3002 ; Terminal_Punctuation # Po [2] IDEOGRAPHIC COMMA..IDEOGRAPHIC FULL STOP
A4FE..A4FF ; Terminal_Punctuation # Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
A60D..A60F ; Terminal_Punctuation # Po [3] VAI COMMA..VAI QUESTION MARK
@@ -189,6 +192,7 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA
10B3A..10B3F ; Terminal_Punctuation # Po [6] TINY TWO DOTS OVER ONE DOT PUNCTUATION..LARGE ONE RING OVER TWO RINGS PUNCTUATION
10B99..10B9C ; Terminal_Punctuation # Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
10F55..10F59 ; Terminal_Punctuation # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
+10F86..10F89 ; Terminal_Punctuation # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS
11047..1104D ; Terminal_Punctuation # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
110BE..110C1 ; Terminal_Punctuation # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA
11141..11143 ; Terminal_Punctuation # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK
@@ -220,7 +224,7 @@ FF64 ; Terminal_Punctuation # Po HALFWIDTH IDEOGRAPHIC COMMA
1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON
-# Total code points: 267
+# Total code points: 276
# ================================================
@@ -600,6 +604,7 @@ FF41..FF46 ; Hex_Digit # L& [6] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH L
1A6D..1A72 ; Other_Alphabetic # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
1A73..1A74 ; Other_Alphabetic # Mn [2] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN MAI KANG
1ABF..1AC0 ; Other_Alphabetic # Mn [2] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER TURNED W BELOW
+1ACC..1ACE ; Other_Alphabetic # Mn [3] COMBINING LATIN SMALL LETTER INSULAR G..COMBINING LATIN SMALL LETTER INSULAR T
1B00..1B03 ; Other_Alphabetic # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
1B04 ; Other_Alphabetic # Mc BALINESE SIGN BISAH
1B35 ; Other_Alphabetic # Mc BALINESE VOWEL SIGN TEDUNG
@@ -686,10 +691,12 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
11001 ; Other_Alphabetic # Mn BRAHMI SIGN ANUSVARA
11002 ; Other_Alphabetic # Mc BRAHMI SIGN VISARGA
11038..11045 ; Other_Alphabetic # Mn [14] BRAHMI VOWEL SIGN AA..BRAHMI VOWEL SIGN AU
+11073..11074 ; Other_Alphabetic # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O
11082 ; Other_Alphabetic # Mc KAITHI SIGN VISARGA
110B0..110B2 ; Other_Alphabetic # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II
110B3..110B6 ; Other_Alphabetic # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
110B7..110B8 ; Other_Alphabetic # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU
+110C2 ; Other_Alphabetic # Mn KAITHI VOWEL SIGN VOCALIC R
11100..11102 ; Other_Alphabetic # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
11127..1112B ; Other_Alphabetic # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
1112C ; Other_Alphabetic # Mc CHAKMA VOWEL SIGN E
@@ -815,7 +822,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
1F150..1F169 ; Other_Alphabetic # So [26] NEGATIVE CIRCLED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
1F170..1F189 ; Other_Alphabetic # So [26] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED LATIN CAPITAL LETTER Z
-# Total code points: 1398
+# Total code points: 1404
# ================================================
@@ -824,7 +831,7 @@ FB1E ; Other_Alphabetic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
3400..4DBF ; Ideographic # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
-4E00..9FFC ; Ideographic # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC
+4E00..9FFF ; Ideographic # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF
F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
16FE4 ; Ideographic # Mn KHITAN SMALL SCRIPT FILLER
@@ -832,15 +839,15 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
18800..18CD5 ; Ideographic # Lo [1238] TANGUT COMPONENT-001..KHITAN SMALL SCRIPT CHARACTER-18CD5
18D00..18D08 ; Ideographic # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08
1B170..1B2FB ; Ideographic # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
-20000..2A6DD ; Ideographic # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD
-2A700..2B734 ; Ideographic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
+20000..2A6DF ; Ideographic # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF
+2A700..2B738 ; Ideographic # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738
2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEB0..2EBE0 ; Ideographic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
30000..3134A ; Ideographic # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
-# Total code points: 101652
+# Total code points: 101661
# ================================================
@@ -885,6 +892,9 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
07EB..07F3 ; Diacritic # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
07F4..07F5 ; Diacritic # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
0818..0819 ; Diacritic # Mn [2] SAMARITAN MARK OCCLUSION..SAMARITAN MARK DAGESH
+0898..089F ; Diacritic # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
+08C9 ; Diacritic # Lm ARABIC SMALL FARSI YEH
+08CA..08D2 ; Diacritic # Mn [9] ARABIC SMALL HIGH FARSI YEH..ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW
08E3..08FE ; Diacritic # Mn [28] ARABIC TURNED DAMMA BELOW..ARABIC DAMMA WITH DOT
093C ; Diacritic # Mn DEVANAGARI SIGN NUKTA
094D ; Diacritic # Mn DEVANAGARI SIGN VIRAMA
@@ -901,6 +911,7 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
0B4D ; Diacritic # Mn ORIYA SIGN VIRAMA
0B55 ; Diacritic # Mn ORIYA SIGN OVERLINE
0BCD ; Diacritic # Mn TAMIL SIGN VIRAMA
+0C3C ; Diacritic # Mn TELUGU SIGN NUKTA
0C4D ; Diacritic # Mn TELUGU SIGN VIRAMA
0CBC ; Diacritic # Mn KANNADA SIGN NUKTA
0CCD ; Diacritic # Mn KANNADA SIGN VIRAMA
@@ -928,12 +939,16 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
108F ; Diacritic # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5
109A..109B ; Diacritic # Mc [2] MYANMAR SIGN KHAMTI TONE-1..MYANMAR SIGN KHAMTI TONE-3
135D..135F ; Diacritic # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
+1714 ; Diacritic # Mn TAGALOG SIGN VIRAMA
+1715 ; Diacritic # Mc TAGALOG SIGN PAMUDPOD
17C9..17D3 ; Diacritic # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
17DD ; Diacritic # Mn KHMER SIGN ATTHACAN
1939..193B ; Diacritic # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
1A75..1A7C ; Diacritic # Mn [8] TAI THAM SIGN TONE-1..TAI THAM SIGN KHUEN-LUE KARAN
1A7F ; Diacritic # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
1AB0..1ABD ; Diacritic # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
+1ABE ; Diacritic # Me COMBINING PARENTHESES OVERLAY
+1AC1..1ACB ; Diacritic # Mn [11] COMBINING LEFT PARENTHESIS ABOVE LEFT..COMBINING TRIPLE ACUTE ACCENT
1B34 ; Diacritic # Mn BALINESE SIGN REREKAN
1B44 ; Diacritic # Mc BALINESE ADEG ADEG
1B6B..1B73 ; Diacritic # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
@@ -952,8 +967,7 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
1CF8..1CF9 ; Diacritic # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
1D2C..1D6A ; Diacritic # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI
1DC4..1DCF ; Diacritic # Mn [12] COMBINING MACRON-ACUTE..COMBINING ZIGZAG BELOW
-1DF5..1DF9 ; Diacritic # Mn [5] COMBINING UP TACK ABOVE..COMBINING WIDE INVERTED BRIDGE BELOW
-1DFD..1DFF ; Diacritic # Mn [3] COMBINING ALMOST EQUAL TO BELOW..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+1DF5..1DFF ; Diacritic # Mn [11] COMBINING UP TACK ABOVE..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
1FBD ; Diacritic # Sk GREEK KORONIS
1FBF..1FC1 ; Diacritic # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI
1FCD..1FCF ; Diacritic # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI
@@ -1008,10 +1022,16 @@ FF70 ; Diacritic # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND
FF9E..FF9F ; Diacritic # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
FFE3 ; Diacritic # Sk FULLWIDTH MACRON
102E0 ; Diacritic # Mn COPTIC EPACT THOUSANDS MARK
+10780..10785 ; Diacritic # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK
+10787..107B0 ; Diacritic # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK
+107B2..107BA ; Diacritic # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL
10AE5..10AE6 ; Diacritic # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
10D22..10D23 ; Diacritic # Lo [2] HANIFI ROHINGYA MARK SAKIN..HANIFI ROHINGYA MARK NA KHONNA
10D24..10D27 ; Diacritic # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
10F46..10F50 ; Diacritic # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
+10F82..10F85 ; Diacritic # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
+11046 ; Diacritic # Mn BRAHMI VIRAMA
+11070 ; Diacritic # Mn BRAHMI SIGN OLD TAMIL VIRAMA
110B9..110BA ; Diacritic # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
11133..11134 ; Diacritic # Mn [2] CHAKMA VIRAMA..CHAKMA MAAYYAA
11173 ; Diacritic # Mn MAHAJANI SIGN NUKTA
@@ -1049,18 +1069,24 @@ FFE3 ; Diacritic # Sk FULLWIDTH MACRON
16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
16FF0..16FF1 ; Diacritic # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
+1AFF0..1AFF3 ; Diacritic # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5
+1AFF5..1AFFB ; Diacritic # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5
+1AFFD..1AFFE ; Diacritic # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8
+1CF00..1CF2D ; Diacritic # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
+1CF30..1CF46 ; Diacritic # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
1D167..1D169 ; Diacritic # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
1D16D..1D172 ; Diacritic # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5
1D17B..1D182 ; Diacritic # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
1D185..1D18B ; Diacritic # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
1D1AA..1D1AD ; Diacritic # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
1E130..1E136 ; Diacritic # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
+1E2AE ; Diacritic # Mn TOTO SIGN RISING TONE
1E2EC..1E2EF ; Diacritic # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
1E8D0..1E8D6 ; Diacritic # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
1E944..1E946 ; Diacritic # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK
1E948..1E94A ; Diacritic # Mn [3] ADLAM CONSONANT MODIFIER..ADLAM NUKTA
-# Total code points: 882
+# Total code points: 1064
# ================================================
@@ -1088,6 +1114,7 @@ AA70 ; Extender # Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION
AADD ; Extender # Lm TAI VIET SYMBOL SAM
AAF3..AAF4 ; Extender # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK
FF70 ; Extender # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+10781..10782 ; Extender # Lm [2] MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON..MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON
1135D ; Extender # Lo GRANTHA SIGN PLUTA
115C6..115C8 ; Extender # Po [3] SIDDHAM REPETITION MARK-1..SIDDHAM REPETITION MARK-3
11A98 ; Extender # Mn SOYOMBO GEMINATION MARK
@@ -1097,7 +1124,7 @@ FF70 ; Extender # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND
1E13C..1E13D ; Extender # Lm [2] NYIAKENG PUACHUE HMONG SIGN XW XW..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
1E944..1E946 ; Extender # Mn [3] ADLAM ALIF LENGTHENER..ADLAM GEMINATION MARK
-# Total code points: 48
+# Total code points: 50
# ================================================
@@ -1121,8 +1148,12 @@ A69C..A69D ; Other_Lowercase # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..M
A770 ; Other_Lowercase # Lm MODIFIER LETTER US
A7F8..A7F9 ; Other_Lowercase # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
AB5C..AB5F ; Other_Lowercase # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
+10780 ; Other_Lowercase # Lm MODIFIER LETTER SMALL CAPITAL AA
+10783..10785 ; Other_Lowercase # Lm [3] MODIFIER LETTER SMALL AE..MODIFIER LETTER SMALL B WITH HOOK
+10787..107B0 ; Other_Lowercase # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK
+107B2..107BA ; Other_Lowercase # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL
-# Total code points: 189
+# Total code points: 244
# ================================================
@@ -1211,7 +1242,7 @@ E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
# ================================================
3400..4DBF ; Unified_Ideograph # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
-4E00..9FFC ; Unified_Ideograph # Lo [20989] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFC
+4E00..9FFF ; Unified_Ideograph # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF
FA0E..FA0F ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
FA11 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA11
FA13..FA14 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
@@ -1219,14 +1250,14 @@ FA1F ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA1F
FA21 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA21
FA23..FA24 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA23..CJK COMPATIBILITY IDEOGRAPH-FA24
FA27..FA29 ; Unified_Ideograph # Lo [3] CJK COMPATIBILITY IDEOGRAPH-FA27..CJK COMPATIBILITY IDEOGRAPH-FA29
-20000..2A6DD ; Unified_Ideograph # Lo [42718] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DD
-2A700..2B734 ; Unified_Ideograph # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
+20000..2A6DF ; Unified_Ideograph # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF
+2A700..2B738 ; Unified_Ideograph # Lo [4153] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B738
2B740..2B81D ; Unified_Ideograph # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Unified_Ideograph # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEB0..2EBE0 ; Unified_Ideograph # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
30000..3134A ; Unified_Ideograph # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
-# Total code points: 92856
+# Total code points: 92865
# ================================================
@@ -1291,8 +1322,9 @@ E0001 ; Deprecated # Cf LANGUAGE TAG
1D62A..1D62B ; Soft_Dotted # L& [2] MATHEMATICAL SANS-SERIF ITALIC SMALL I..MATHEMATICAL SANS-SERIF ITALIC SMALL J
1D65E..1D65F ; Soft_Dotted # L& [2] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J
1D692..1D693 ; Soft_Dotted # L& [2] MATHEMATICAL MONOSPACE SMALL I..MATHEMATICAL MONOSPACE SMALL J
+1DF1A ; Soft_Dotted # L& LATIN SMALL LETTER I WITH STROKE AND RETROFLEX HOOK
-# Total code points: 46
+# Total code points: 47
# ================================================
@@ -1330,7 +1362,7 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET
002E ; Sentence_Terminal # Po FULL STOP
003F ; Sentence_Terminal # Po QUESTION MARK
0589 ; Sentence_Terminal # Po ARMENIAN FULL STOP
-061E..061F ; Sentence_Terminal # Po [2] ARABIC TRIPLE DOT PUNCTUATION MARK..ARABIC QUESTION MARK
+061D..061F ; Sentence_Terminal # Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK
06D4 ; Sentence_Terminal # Po ARABIC FULL STOP
0700..0702 ; Sentence_Terminal # Po [3] SYRIAC END OF PARAGRAPH..SYRIAC SUBLINEAR FULL STOP
07F9 ; Sentence_Terminal # Po NKO EXCLAMATION MARK
@@ -1349,12 +1381,14 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET
1AA8..1AAB ; Sentence_Terminal # Po [4] TAI THAM SIGN KAAN..TAI THAM SIGN SATKAANKUU
1B5A..1B5B ; Sentence_Terminal # Po [2] BALINESE PANTI..BALINESE PAMADA
1B5E..1B5F ; Sentence_Terminal # Po [2] BALINESE CARIK SIKI..BALINESE CARIK PAREREN
+1B7D..1B7E ; Sentence_Terminal # Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG
1C3B..1C3C ; Sentence_Terminal # Po [2] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION NYET THYOOM TA-ROL
1C7E..1C7F ; Sentence_Terminal # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
203C..203D ; Sentence_Terminal # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG
2047..2049 ; Sentence_Terminal # Po [3] DOUBLE QUESTION MARK..EXCLAMATION QUESTION MARK
2E2E ; Sentence_Terminal # Po REVERSED QUESTION MARK
2E3C ; Sentence_Terminal # Po STENOGRAPHIC FULL STOP
+2E53..2E54 ; Sentence_Terminal # Po [2] MEDIEVAL EXCLAMATION MARK..MEDIEVAL QUESTION MARK
3002 ; Sentence_Terminal # Po IDEOGRAPHIC FULL STOP
A4FF ; Sentence_Terminal # Po LISU PUNCTUATION FULL STOP
A60E..A60F ; Sentence_Terminal # Po [2] VAI FULL STOP..VAI QUESTION MARK
@@ -1375,6 +1409,7 @@ FF1F ; Sentence_Terminal # Po FULLWIDTH QUESTION MARK
FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
10A56..10A57 ; Sentence_Terminal # Po [2] KHAROSHTHI PUNCTUATION DANDA..KHAROSHTHI PUNCTUATION DOUBLE DANDA
10F55..10F59 ; Sentence_Terminal # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
+10F86..10F89 ; Sentence_Terminal # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS
11047..11048 ; Sentence_Terminal # Po [2] BRAHMI DANDA..BRAHMI DOUBLE DANDA
110BE..110C1 ; Sentence_Terminal # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA
11141..11143 ; Sentence_Terminal # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK
@@ -1403,15 +1438,16 @@ FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP
-# Total code points: 143
+# Total code points: 152
# ================================================
180B..180D ; Variation_Selector # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+180F ; Variation_Selector # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
FE00..FE0F ; Variation_Selector # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-# Total code points: 259
+# Total code points: 260
# ================================================
@@ -1644,8 +1680,17 @@ E0100..E01EF ; Variation_Selector # Mn [240] VARIATION SELECTOR-17..VARIATION S
2E42 ; Pattern_Syntax # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK
2E43..2E4F ; Pattern_Syntax # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER
2E50..2E51 ; Pattern_Syntax # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR
-2E52 ; Pattern_Syntax # Po TIRONIAN SIGN CAPITAL ET
-2E53..2E7F ; Pattern_Syntax # Cn [45] <reserved-2E53>..<reserved-2E7F>
+2E52..2E54 ; Pattern_Syntax # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK
+2E55 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH STROKE
+2E56 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH STROKE
+2E57 ; Pattern_Syntax # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE
+2E58 ; Pattern_Syntax # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE
+2E59 ; Pattern_Syntax # Ps TOP HALF LEFT PARENTHESIS
+2E5A ; Pattern_Syntax # Pe TOP HALF RIGHT PARENTHESIS
+2E5B ; Pattern_Syntax # Ps BOTTOM HALF LEFT PARENTHESIS
+2E5C ; Pattern_Syntax # Pe BOTTOM HALF RIGHT PARENTHESIS
+2E5D ; Pattern_Syntax # Pd OBLIQUE HYPHEN
+2E5E..2E7F ; Pattern_Syntax # Cn [34] <reserved-2E5E>..<reserved-2E7F>
3001..3003 ; Pattern_Syntax # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
3008 ; Pattern_Syntax # Ps LEFT ANGLE BRACKET
3009 ; Pattern_Syntax # Pe RIGHT ANGLE BRACKET
@@ -1682,11 +1727,12 @@ FE45..FE46 ; Pattern_Syntax # Po [2] SESAME DOT..WHITE SESAME DOT
0600..0605 ; Prepended_Concatenation_Mark # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE
06DD ; Prepended_Concatenation_Mark # Cf ARABIC END OF AYAH
070F ; Prepended_Concatenation_Mark # Cf SYRIAC ABBREVIATION MARK
+0890..0891 ; Prepended_Concatenation_Mark # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
08E2 ; Prepended_Concatenation_Mark # Cf ARABIC DISPUTED END OF AYAH
110BD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN
110CD ; Prepended_Concatenation_Mark # Cf KAITHI NUMBER SIGN ABOVE
-# Total code points: 11
+# Total code points: 13
# ================================================
diff --git a/lib/stdlib/uc_spec/README-UPDATE.txt b/lib/stdlib/uc_spec/README-UPDATE.txt
index 57fe885b5b..8af7b54a07 100644
--- a/lib/stdlib/uc_spec/README-UPDATE.txt
+++ b/lib/stdlib/uc_spec/README-UPDATE.txt
@@ -1,11 +1,45 @@
-When updating the unicode version copy the necessary files to this
-directory.
-And update the test files in stdlib/test/unicode_util_SUITE_data/*
+Unicode 14.0.0 was updated from:
+- https://www.unicode.org/Public/14.0.0/ucd/
+- https://www.unicode.org/Public/14.0.0/ucd/auxiliary/
+- https://www.unicode.org/Public/14.0.0/ucd/emoji/
-Unicode 13.0.0 was updated from:
-https://www.unicode.org/Public/13.0.0/ucd/
-https://www.unicode.org/Public/13.0.0/ucd/auxiliary/
-https://www.unicode.org/Public/13.0.0/ucd/emoji/
+When updating the Unicode version please follow these steps:
-Update the spec_version(..) function in the generator,
-gen_unicode_mod.escript
+The latest vesrion of the Unicode Character Database can be found at
+https://www.unicode.org/Public/UCD/latest/ucd/
+
+1. Copy the following files to lib/stdlib/uc_spec/ replacing existing ones.
+No subfolder should be created.
+ - CaseFolding.txt
+ - CompositionExclusions.txt
+ - PropList.txt
+ - SpecialCasing.txt
+ - UnicodeData.txt
+ - auxiliary/GraphemeBreakProperty.txt
+ - emoji/emoji-data.txt
+
+2. Copy the following test files to lib/stdlib/test/unicode_util_SUITE_data/
+replacing existing ones. No subfolder should be created.
+ - NormalizationTest.txt
+ - auxiliary/GraphemeBreakTest.txt
+ - auxiliary/LineBreakTest.txt
+
+3. Update the "spec_version()" function in the generator by replacing the Unicode
+version in lib/stdlib/uc_spec/gen_unicode_mod.escript
+
+4. Read the release notes by visiting https://www.unicode.org/versions/latest/
+and assess if additional changes are necessary in the Erlang code.
+
+5. Replace all ocurrences of previous version of Unicode with the new one in
+this very same file (lib/stdlib/uc_spec/README-UPDATE.txt).
+Remember to update these instructions if a new file is added or any other change
+is required for future version updates.
+
+6. Run the test for the Unicode suite from the OTP repository root dir.
+ $ export ERL_TOP=$PWD
+ $ export PATH=$ERL_TOP/bin:$PATH
+ $ ./otp_build all -a && ./otp_build tests
+ $ cd release/tests/test_server
+ $ erl
+ erl> ts:install().
+ erl> ts:run(stdlib, unicode_SUITE, [batch]).
diff --git a/lib/stdlib/uc_spec/SpecialCasing.txt b/lib/stdlib/uc_spec/SpecialCasing.txt
index 2a1a5a1d6b..1c2e968a8c 100644
--- a/lib/stdlib/uc_spec/SpecialCasing.txt
+++ b/lib/stdlib/uc_spec/SpecialCasing.txt
@@ -1,6 +1,6 @@
-# SpecialCasing-13.0.0.txt
-# Date: 2019-09-08, 23:31:24 GMT
-# © 2019 Unicode®, Inc.
+# SpecialCasing-14.0.0.txt
+# Date: 2021-03-08, 19:35:55 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
diff --git a/lib/stdlib/uc_spec/UnicodeData.txt b/lib/stdlib/uc_spec/UnicodeData.txt
index e22f967bba..b5abef7ed4 100644
--- a/lib/stdlib/uc_spec/UnicodeData.txt
+++ b/lib/stdlib/uc_spec/UnicodeData.txt
@@ -1525,6 +1525,7 @@
061A;ARABIC SMALL KASRA;Mn;32;NSM;;;;;N;;;;;
061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;;
061C;ARABIC LETTER MARK;Cf;0;AL;;;;;N;;;;;
+061D;ARABIC END OF TEXT MARK;Po;0;AL;;;;;N;;;;;
061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;;
061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;;
0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;;
@@ -2089,6 +2090,47 @@
0868;SYRIAC LETTER MALAYALAM LLA;Lo;0;AL;;;;;N;;;;;
0869;SYRIAC LETTER MALAYALAM LLLA;Lo;0;AL;;;;;N;;;;;
086A;SYRIAC LETTER MALAYALAM SSA;Lo;0;AL;;;;;N;;;;;
+0870;ARABIC LETTER ALEF WITH ATTACHED FATHA;Lo;0;AL;;;;;N;;;;;
+0871;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA;Lo;0;AL;;;;;N;;;;;
+0872;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE;Lo;0;AL;;;;;N;;;;;
+0873;ARABIC LETTER ALEF WITH LEFT MIDDLE STROKE;Lo;0;AL;;;;;N;;;;;
+0874;ARABIC LETTER ALEF WITH ATTACHED KASRA;Lo;0;AL;;;;;N;;;;;
+0875;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA;Lo;0;AL;;;;;N;;;;;
+0876;ARABIC LETTER ALEF WITH ATTACHED ROUND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+0877;ARABIC LETTER ALEF WITH ATTACHED RIGHT ROUND DOT;Lo;0;AL;;;;;N;;;;;
+0878;ARABIC LETTER ALEF WITH ATTACHED LEFT ROUND DOT;Lo;0;AL;;;;;N;;;;;
+0879;ARABIC LETTER ALEF WITH ATTACHED ROUND DOT BELOW;Lo;0;AL;;;;;N;;;;;
+087A;ARABIC LETTER ALEF WITH DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+087B;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+087C;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+087D;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA AND DOT ABOVE;Lo;0;AL;;;;;N;;;;;
+087E;ARABIC LETTER ALEF WITH ATTACHED TOP RIGHT FATHA AND LEFT RING;Lo;0;AL;;;;;N;;;;;
+087F;ARABIC LETTER ALEF WITH RIGHT MIDDLE STROKE AND LEFT RING;Lo;0;AL;;;;;N;;;;;
+0880;ARABIC LETTER ALEF WITH ATTACHED BOTTOM RIGHT KASRA AND LEFT RING;Lo;0;AL;;;;;N;;;;;
+0881;ARABIC LETTER ALEF WITH ATTACHED RIGHT HAMZA;Lo;0;AL;;;;;N;;;;;
+0882;ARABIC LETTER ALEF WITH ATTACHED LEFT HAMZA;Lo;0;AL;;;;;N;;;;;
+0883;ARABIC TATWEEL WITH OVERSTRUCK HAMZA;Lo;0;AL;;;;;N;;;;;
+0884;ARABIC TATWEEL WITH OVERSTRUCK WAW;Lo;0;AL;;;;;N;;;;;
+0885;ARABIC TATWEEL WITH TWO DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+0886;ARABIC LETTER THIN YEH;Lo;0;AL;;;;;N;;;;;
+0887;ARABIC BASELINE ROUND DOT;Lo;0;AL;;;;;N;;;;;
+0888;ARABIC RAISED ROUND DOT;Sk;0;AL;;;;;N;;;;;
+0889;ARABIC LETTER NOON WITH INVERTED SMALL V;Lo;0;AL;;;;;N;;;;;
+088A;ARABIC LETTER HAH WITH INVERTED SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
+088B;ARABIC LETTER TAH WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+088C;ARABIC LETTER TAH WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+088D;ARABIC LETTER KEHEH WITH TWO DOTS VERTICALLY BELOW;Lo;0;AL;;;;;N;;;;;
+088E;ARABIC VERTICAL TAIL;Lo;0;AL;;;;;N;;;;;
+0890;ARABIC POUND MARK ABOVE;Cf;0;AN;;;;;N;;;;;
+0891;ARABIC PIASTRE MARK ABOVE;Cf;0;AN;;;;;N;;;;;
+0898;ARABIC SMALL HIGH WORD AL-JUZ;Mn;230;NSM;;;;;N;;;;;
+0899;ARABIC SMALL LOW WORD ISHMAAM;Mn;220;NSM;;;;;N;;;;;
+089A;ARABIC SMALL LOW WORD IMAALA;Mn;220;NSM;;;;;N;;;;;
+089B;ARABIC SMALL LOW WORD TASHEEL;Mn;220;NSM;;;;;N;;;;;
+089C;ARABIC MADDA WAAJIB;Mn;230;NSM;;;;;N;;;;;
+089D;ARABIC SUPERSCRIPT ALEF MOKHASSAS;Mn;230;NSM;;;;;N;;;;;
+089E;ARABIC DOUBLED MADDA;Mn;230;NSM;;;;;N;;;;;
+089F;ARABIC HALF MADDA OVER MADDA;Mn;230;NSM;;;;;N;;;;;
08A0;ARABIC LETTER BEH WITH SMALL V BELOW;Lo;0;AL;;;;;N;;;;;
08A1;ARABIC LETTER BEH WITH HAMZA ABOVE;Lo;0;AL;;;;;N;;;;;
08A2;ARABIC LETTER JEEM WITH TWO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
@@ -2110,6 +2152,7 @@
08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;;
08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+08B5;ARABIC LETTER QAF WITH DOT BELOW AND NO DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
08B6;ARABIC LETTER BEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;;
08B7;ARABIC LETTER PEH WITH SMALL MEEM ABOVE;Lo;0;AL;;;;;N;;;;;
08B8;ARABIC LETTER TEH WITH SMALL TEH ABOVE;Lo;0;AL;;;;;N;;;;;
@@ -2128,6 +2171,17 @@
08C5;ARABIC LETTER JEEM WITH THREE DOTS ABOVE;Lo;0;AL;;;;;N;;;;;
08C6;ARABIC LETTER JEEM WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
08C7;ARABIC LETTER LAM WITH SMALL ARABIC LETTER TAH ABOVE;Lo;0;AL;;;;;N;;;;;
+08C8;ARABIC LETTER GRAF;Lo;0;AL;;;;;N;;;;;
+08C9;ARABIC SMALL FARSI YEH;Lm;0;AL;;;;;N;;;;;
+08CA;ARABIC SMALL HIGH FARSI YEH;Mn;230;NSM;;;;;N;;;;;
+08CB;ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW;Mn;230;NSM;;;;;N;;;;;
+08CC;ARABIC SMALL HIGH WORD SAH;Mn;230;NSM;;;;;N;;;;;
+08CD;ARABIC SMALL HIGH ZAH;Mn;230;NSM;;;;;N;;;;;
+08CE;ARABIC LARGE ROUND DOT ABOVE;Mn;230;NSM;;;;;N;;;;;
+08CF;ARABIC LARGE ROUND DOT BELOW;Mn;220;NSM;;;;;N;;;;;
+08D0;ARABIC SUKUN BELOW;Mn;220;NSM;;;;;N;;;;;
+08D1;ARABIC LARGE CIRCLE BELOW;Mn;220;NSM;;;;;N;;;;;
+08D2;ARABIC LARGE ROUND DOT INSIDE CIRCLE BELOW;Mn;220;NSM;;;;;N;;;;;
08D3;ARABIC SMALL LOW WAW;Mn;220;NSM;;;;;N;;;;;
08D4;ARABIC SMALL HIGH WORD AR-RUB;Mn;230;NSM;;;;;N;;;;;
08D5;ARABIC SMALL HIGH SAD;Mn;230;NSM;;;;;N;;;;;
@@ -2786,6 +2840,7 @@
0C37;TELUGU LETTER SSA;Lo;0;L;;;;;N;;;;;
0C38;TELUGU LETTER SA;Lo;0;L;;;;;N;;;;;
0C39;TELUGU LETTER HA;Lo;0;L;;;;;N;;;;;
+0C3C;TELUGU SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
0C3D;TELUGU SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;;
0C3E;TELUGU VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;;
0C3F;TELUGU VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
@@ -2806,6 +2861,7 @@
0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;;
0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;;
0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;;
+0C5D;TELUGU LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;;
0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
@@ -2901,6 +2957,7 @@
0CCD;KANNADA SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
0CD5;KANNADA LENGTH MARK;Mc;0;L;;;;;N;;;;;
0CD6;KANNADA AI LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0CDD;KANNADA LETTER NAKAARA POLLU;Lo;0;L;;;;;N;;;;;
0CDE;KANNADA LETTER FA;Lo;0;L;;;;;N;;;;;
0CE0;KANNADA LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
0CE1;KANNADA LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
@@ -5258,6 +5315,7 @@
170A;TAGALOG LETTER BA;Lo;0;L;;;;;N;;;;;
170B;TAGALOG LETTER MA;Lo;0;L;;;;;N;;;;;
170C;TAGALOG LETTER YA;Lo;0;L;;;;;N;;;;;
+170D;TAGALOG LETTER RA;Lo;0;L;;;;;N;;;;;
170E;TAGALOG LETTER LA;Lo;0;L;;;;;N;;;;;
170F;TAGALOG LETTER WA;Lo;0;L;;;;;N;;;;;
1710;TAGALOG LETTER SA;Lo;0;L;;;;;N;;;;;
@@ -5265,6 +5323,8 @@
1712;TAGALOG VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
1713;TAGALOG VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
1714;TAGALOG SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
+1715;TAGALOG SIGN PAMUDPOD;Mc;9;L;;;;;N;;;;;
+171F;TAGALOG LETTER ARCHAIC RA;Lo;0;L;;;;;N;;;;;
1720;HANUNOO LETTER A;Lo;0;L;;;;;N;;;;;
1721;HANUNOO LETTER I;Lo;0;L;;;;;N;;;;;
1722;HANUNOO LETTER U;Lo;0;L;;;;;N;;;;;
@@ -5285,7 +5345,7 @@
1731;HANUNOO LETTER HA;Lo;0;L;;;;;N;;;;;
1732;HANUNOO VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
1733;HANUNOO VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
-1734;HANUNOO SIGN PAMUDPOD;Mn;9;NSM;;;;;N;;;;;
+1734;HANUNOO SIGN PAMUDPOD;Mc;9;L;;;;;N;;;;;
1735;PHILIPPINE SINGLE PUNCTUATION;Po;0;L;;;;;N;;;;;
1736;PHILIPPINE DOUBLE PUNCTUATION;Po;0;L;;;;;N;;;;;
1740;BUHID LETTER A;Lo;0;L;;;;;N;;;;;
@@ -5455,6 +5515,7 @@
180C;MONGOLIAN FREE VARIATION SELECTOR TWO;Mn;0;NSM;;;;;N;;;;;
180D;MONGOLIAN FREE VARIATION SELECTOR THREE;Mn;0;NSM;;;;;N;;;;;
180E;MONGOLIAN VOWEL SEPARATOR;Cf;0;BN;;;;;N;;;;;
+180F;MONGOLIAN FREE VARIATION SELECTOR FOUR;Mn;0;NSM;;;;;N;;;;;
1810;MONGOLIAN DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
1811;MONGOLIAN DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
1812;MONGOLIAN DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
@@ -6059,6 +6120,20 @@
1ABE;COMBINING PARENTHESES OVERLAY;Me;0;NSM;;;;;N;;;;;
1ABF;COMBINING LATIN SMALL LETTER W BELOW;Mn;220;NSM;;;;;N;;;;;
1AC0;COMBINING LATIN SMALL LETTER TURNED W BELOW;Mn;220;NSM;;;;;N;;;;;
+1AC1;COMBINING LEFT PARENTHESIS ABOVE LEFT;Mn;230;NSM;;;;;N;;;;;
+1AC2;COMBINING RIGHT PARENTHESIS ABOVE RIGHT;Mn;230;NSM;;;;;N;;;;;
+1AC3;COMBINING LEFT PARENTHESIS BELOW LEFT;Mn;220;NSM;;;;;N;;;;;
+1AC4;COMBINING RIGHT PARENTHESIS BELOW RIGHT;Mn;220;NSM;;;;;N;;;;;
+1AC5;COMBINING SQUARE BRACKETS ABOVE;Mn;230;NSM;;;;;N;;;;;
+1AC6;COMBINING NUMBER SIGN ABOVE;Mn;230;NSM;;;;;N;;;;;
+1AC7;COMBINING INVERTED DOUBLE ARCH ABOVE;Mn;230;NSM;;;;;N;;;;;
+1AC8;COMBINING PLUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;;
+1AC9;COMBINING DOUBLE PLUS SIGN ABOVE;Mn;230;NSM;;;;;N;;;;;
+1ACA;COMBINING DOUBLE PLUS SIGN BELOW;Mn;220;NSM;;;;;N;;;;;
+1ACB;COMBINING TRIPLE ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;;
+1ACC;COMBINING LATIN SMALL LETTER INSULAR G;Mn;230;NSM;;;;;N;;;;;
+1ACD;COMBINING LATIN SMALL LETTER INSULAR R;Mn;230;NSM;;;;;N;;;;;
+1ACE;COMBINING LATIN SMALL LETTER INSULAR T;Mn;230;NSM;;;;;N;;;;;
1B00;BALINESE SIGN ULU RICEM;Mn;0;NSM;;;;;N;;;;;
1B01;BALINESE SIGN ULU CANDRA;Mn;0;NSM;;;;;N;;;;;
1B02;BALINESE SIGN CECEK;Mn;0;NSM;;;;;N;;;;;
@@ -6135,6 +6210,7 @@
1B49;BALINESE LETTER VE SASAK;Lo;0;L;;;;;N;;;;;
1B4A;BALINESE LETTER ZAL SASAK;Lo;0;L;;;;;N;;;;;
1B4B;BALINESE LETTER ASYURA SASAK;Lo;0;L;;;;;N;;;;;
+1B4C;BALINESE LETTER ARCHAIC JNYA;Lo;0;L;;;;;N;;;;;
1B50;BALINESE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
1B51;BALINESE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
1B52;BALINESE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
@@ -6180,6 +6256,8 @@
1B7A;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK;So;0;L;;;;;N;;;;;
1B7B;BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK;So;0;L;;;;;N;;;;;
1B7C;BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING;So;0;L;;;;;N;;;;;
+1B7D;BALINESE PANTI LANTANG;Po;0;L;;;;;N;;;;;
+1B7E;BALINESE PAMADA LANTANG;Po;0;L;;;;;N;;;;;
1B80;SUNDANESE SIGN PANYECEK;Mn;0;NSM;;;;;N;;;;;
1B81;SUNDANESE SIGN PANGLAYAR;Mn;0;NSM;;;;;N;;;;;
1B82;SUNDANESE SIGN PANGWISAD;Mc;0;L;;;;;N;;;;;
@@ -6778,6 +6856,7 @@
1DF7;COMBINING KAVYKA ABOVE LEFT;Mn;228;NSM;;;;;N;;;;;
1DF8;COMBINING DOT ABOVE LEFT;Mn;228;NSM;;;;;N;;;;;
1DF9;COMBINING WIDE INVERTED BRIDGE BELOW;Mn;220;NSM;;;;;N;;;;;
+1DFA;COMBINING DOT BELOW LEFT;Mn;218;NSM;;;;;N;;;;;
1DFB;COMBINING DELETION MARK;Mn;230;NSM;;;;;N;;;;;
1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;;
1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;;
@@ -7457,6 +7536,7 @@
20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;;
20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;;
20BF;BITCOIN SIGN;Sc;0;ET;;;;;N;;;;;
+20C0;SOM SIGN;Sc;0;ET;;;;;N;;;;;
20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
@@ -10300,6 +10380,7 @@
2C2C;GLAGOLITIC CAPITAL LETTER SHTAPIC;Lu;0;L;;;;;N;;;;2C5C;
2C2D;GLAGOLITIC CAPITAL LETTER TROKUTASTI A;Lu;0;L;;;;;N;;;;2C5D;
2C2E;GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE;Lu;0;L;;;;;N;;;;2C5E;
+2C2F;GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI;Lu;0;L;;;;;N;;;;2C5F;
2C30;GLAGOLITIC SMALL LETTER AZU;Ll;0;L;;;;;N;;;2C00;;2C00
2C31;GLAGOLITIC SMALL LETTER BUKY;Ll;0;L;;;;;N;;;2C01;;2C01
2C32;GLAGOLITIC SMALL LETTER VEDE;Ll;0;L;;;;;N;;;2C02;;2C02
@@ -10347,6 +10428,7 @@
2C5C;GLAGOLITIC SMALL LETTER SHTAPIC;Ll;0;L;;;;;N;;;2C2C;;2C2C
2C5D;GLAGOLITIC SMALL LETTER TROKUTASTI A;Ll;0;L;;;;;N;;;2C2D;;2C2D
2C5E;GLAGOLITIC SMALL LETTER LATINATE MYSLITE;Ll;0;L;;;;;N;;;2C2E;;2C2E
+2C5F;GLAGOLITIC SMALL LETTER CAUDATE CHRIVI;Ll;0;L;;;;;N;;;2C2F;;2C2F
2C60;LATIN CAPITAL LETTER L WITH DOUBLE BAR;Lu;0;L;;;;;N;;;;2C61;
2C61;LATIN SMALL LETTER L WITH DOUBLE BAR;Ll;0;L;;;;;N;;;2C60;;2C60
2C62;LATIN CAPITAL LETTER L WITH MIDDLE TILDE;Lu;0;L;;;;;N;;;;026B;
@@ -10795,6 +10877,17 @@
2E50;CROSS PATTY WITH RIGHT CROSSBAR;So;0;ON;;;;;N;;;;;
2E51;CROSS PATTY WITH LEFT CROSSBAR;So;0;ON;;;;;N;;;;;
2E52;TIRONIAN SIGN CAPITAL ET;Po;0;ON;;;;;N;;;;;
+2E53;MEDIEVAL EXCLAMATION MARK;Po;0;ON;;;;;N;;;;;
+2E54;MEDIEVAL QUESTION MARK;Po;0;ON;;;;;N;;;;;
+2E55;LEFT SQUARE BRACKET WITH STROKE;Ps;0;ON;;;;;Y;;;;;
+2E56;RIGHT SQUARE BRACKET WITH STROKE;Pe;0;ON;;;;;Y;;;;;
+2E57;LEFT SQUARE BRACKET WITH DOUBLE STROKE;Ps;0;ON;;;;;Y;;;;;
+2E58;RIGHT SQUARE BRACKET WITH DOUBLE STROKE;Pe;0;ON;;;;;Y;;;;;
+2E59;TOP HALF LEFT PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
+2E5A;TOP HALF RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
+2E5B;BOTTOM HALF LEFT PARENTHESIS;Ps;0;ON;;;;;Y;;;;;
+2E5C;BOTTOM HALF RIGHT PARENTHESIS;Pe;0;ON;;;;;Y;;;;;
+2E5D;OBLIQUE HYPHEN;Pd;0;ON;;;;;N;;;;;
2E80;CJK RADICAL REPEAT;So;0;ON;;;;;N;;;;;
2E81;CJK RADICAL CLIFF;So;0;ON;;;;;N;;;;;
2E82;CJK RADICAL SECOND ONE;So;0;ON;;;;;N;;;;;
@@ -12204,7 +12297,7 @@
4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;;
4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;;
4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;;
-9FFC;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
+9FFF;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;;
A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;;
A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;;
@@ -14149,6 +14242,8 @@ A7BC;LATIN CAPITAL LETTER GLOTTAL I;Lu;0;L;;;;;N;;;;A7BD;
A7BD;LATIN SMALL LETTER GLOTTAL I;Ll;0;L;;;;;N;;;A7BC;;A7BC
A7BE;LATIN CAPITAL LETTER GLOTTAL U;Lu;0;L;;;;;N;;;;A7BF;
A7BF;LATIN SMALL LETTER GLOTTAL U;Ll;0;L;;;;;N;;;A7BE;;A7BE
+A7C0;LATIN CAPITAL LETTER OLD POLISH O;Lu;0;L;;;;;N;;;;A7C1;
+A7C1;LATIN SMALL LETTER OLD POLISH O;Ll;0;L;;;;;N;;;A7C0;;A7C0
A7C2;LATIN CAPITAL LETTER ANGLICANA W;Lu;0;L;;;;;N;;;;A7C3;
A7C3;LATIN SMALL LETTER ANGLICANA W;Ll;0;L;;;;;N;;;A7C2;;A7C2
A7C4;LATIN CAPITAL LETTER C WITH PALATAL HOOK;Lu;0;L;;;;;N;;;;A794;
@@ -14158,6 +14253,17 @@ A7C7;LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY;Lu;0;L;;;;;N;;;;A7C8;
A7C8;LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C7;;A7C7
A7C9;LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY;Lu;0;L;;;;;N;;;;A7CA;
A7CA;LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY;Ll;0;L;;;;;N;;;A7C9;;A7C9
+A7D0;LATIN CAPITAL LETTER CLOSED INSULAR G;Lu;0;L;;;;;N;;;;A7D1;
+A7D1;LATIN SMALL LETTER CLOSED INSULAR G;Ll;0;L;;;;;N;;;A7D0;;A7D0
+A7D3;LATIN SMALL LETTER DOUBLE THORN;Ll;0;L;;;;;N;;;;;
+A7D5;LATIN SMALL LETTER DOUBLE WYNN;Ll;0;L;;;;;N;;;;;
+A7D6;LATIN CAPITAL LETTER MIDDLE SCOTS S;Lu;0;L;;;;;N;;;;A7D7;
+A7D7;LATIN SMALL LETTER MIDDLE SCOTS S;Ll;0;L;;;;;N;;;A7D6;;A7D6
+A7D8;LATIN CAPITAL LETTER SIGMOID S;Lu;0;L;;;;;N;;;;A7D9;
+A7D9;LATIN SMALL LETTER SIGMOID S;Ll;0;L;;;;;N;;;A7D8;;A7D8
+A7F2;MODIFIER LETTER CAPITAL C;Lm;0;L;<super> 0043;;;;N;;;;;
+A7F3;MODIFIER LETTER CAPITAL F;Lm;0;L;<super> 0046;;;;N;;;;;
+A7F4;MODIFIER LETTER CAPITAL Q;Lm;0;L;<super> 0051;;;;N;;;;;
A7F5;LATIN CAPITAL LETTER REVERSED HALF H;Lu;0;L;;;;;N;;;;A7F6;
A7F6;LATIN SMALL LETTER REVERSED HALF H;Ll;0;L;;;;;N;;;A7F5;;A7F5
A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;;
@@ -15794,6 +15900,7 @@ FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;;
FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;;
FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;;
FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;;
+FBC2;ARABIC SYMBOL WASLA ABOVE;Sk;0;AL;;;;;N;;;;;
FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL;<isolated> 06AD;;;;N;;;;;
FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL;<final> 06AD;;;;N;;;;;
FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL;<initial> 06AD;;;;N;;;;;
@@ -16159,6 +16266,22 @@ FD3C;ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM;Lo;0;AL;<final> 0627 064B;;;;
FD3D;ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM;Lo;0;AL;<isolated> 0627 064B;;;;N;;;;;
FD3E;ORNATE LEFT PARENTHESIS;Pe;0;ON;;;;;N;;;;;
FD3F;ORNATE RIGHT PARENTHESIS;Ps;0;ON;;;;;N;;;;;
+FD40;ARABIC LIGATURE RAHIMAHU ALLAAH;So;0;ON;;;;;N;;;;;
+FD41;ARABIC LIGATURE RADI ALLAAHU ANH;So;0;ON;;;;;N;;;;;
+FD42;ARABIC LIGATURE RADI ALLAAHU ANHAA;So;0;ON;;;;;N;;;;;
+FD43;ARABIC LIGATURE RADI ALLAAHU ANHUM;So;0;ON;;;;;N;;;;;
+FD44;ARABIC LIGATURE RADI ALLAAHU ANHUMAA;So;0;ON;;;;;N;;;;;
+FD45;ARABIC LIGATURE RADI ALLAAHU ANHUNNA;So;0;ON;;;;;N;;;;;
+FD46;ARABIC LIGATURE SALLALLAAHU ALAYHI WA-AALIH;So;0;ON;;;;;N;;;;;
+FD47;ARABIC LIGATURE ALAYHI AS-SALAAM;So;0;ON;;;;;N;;;;;
+FD48;ARABIC LIGATURE ALAYHIM AS-SALAAM;So;0;ON;;;;;N;;;;;
+FD49;ARABIC LIGATURE ALAYHIMAA AS-SALAAM;So;0;ON;;;;;N;;;;;
+FD4A;ARABIC LIGATURE ALAYHI AS-SALAATU WAS-SALAAM;So;0;ON;;;;;N;;;;;
+FD4B;ARABIC LIGATURE QUDDISA SIRRAH;So;0;ON;;;;;N;;;;;
+FD4C;ARABIC LIGATURE SALLALLAHU ALAYHI WAAALIHEE WA-SALLAM;So;0;ON;;;;;N;;;;;
+FD4D;ARABIC LIGATURE ALAYHAA AS-SALAAM;So;0;ON;;;;;N;;;;;
+FD4E;ARABIC LIGATURE TABAARAKA WA-TAAALAA;So;0;ON;;;;;N;;;;;
+FD4F;ARABIC LIGATURE RAHIMAHUM ALLAAH;So;0;ON;;;;;N;;;;;
FD50;ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062C 0645;;;;N;;;;;
FD51;ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM;Lo;0;AL;<final> 062A 062D 062C;;;;N;;;;;
FD52;ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM;Lo;0;AL;<initial> 062A 062D 062C;;;;N;;;;;
@@ -16277,6 +16400,7 @@ FDC4;ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0639
FDC5;ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM;Lo;0;AL;<initial> 0635 0645 0645;;;;N;;;;;
FDC6;ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM;Lo;0;AL;<final> 0633 062E 064A;;;;N;;;;;
FDC7;ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM;Lo;0;AL;<final> 0646 062C 064A;;;;N;;;;;
+FDCF;ARABIC LIGATURE SALAAMUHU ALAYNAA;So;0;ON;;;;;N;;;;;
FDF0;ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0635 0644 06D2;;;;N;;;;;
FDF1;ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM;Lo;0;AL;<isolated> 0642 0644 06D2;;;;N;;;;;
FDF2;ARABIC LIGATURE ALLAH ISOLATED FORM;Lo;0;AL;<isolated> 0627 0644 0644 0647;;;;N;;;;;
@@ -16291,6 +16415,8 @@ FDFA;ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM;Lo;0;AL;<isolated> 0635 0644 06
FDFB;ARABIC LIGATURE JALLAJALALOUHOU;Lo;0;AL;<isolated> 062C 0644 0020 062C 0644 0627 0644 0647;;;;N;ARABIC LETTER JALLAJALALOUHOU;;;;
FDFC;RIAL SIGN;Sc;0;AL;<isolated> 0631 06CC 0627 0644;;;;N;;;;;
FDFD;ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM;So;0;ON;;;;;N;;;;;
+FDFE;ARABIC LIGATURE SUBHAANAHU WA TAAALAA;So;0;ON;;;;;N;;;;;
+FDFF;ARABIC LIGATURE AZZA WA JALL;So;0;ON;;;;;N;;;;;
FE00;VARIATION SELECTOR-1;Mn;0;NSM;;;;;N;;;;;
FE01;VARIATION SELECTOR-2;Mn;0;NSM;;;;;N;;;;;
FE02;VARIATION SELECTOR-3;Mn;0;NSM;;;;;N;;;;;
@@ -17798,6 +17924,76 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
10562;CAUCASIAN ALBANIAN LETTER PIWR;Lo;0;L;;;;;N;;;;;
10563;CAUCASIAN ALBANIAN LETTER KIW;Lo;0;L;;;;;N;;;;;
1056F;CAUCASIAN ALBANIAN CITATION MARK;Po;0;L;;;;;N;;;;;
+10570;VITHKUQI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;10597;
+10571;VITHKUQI CAPITAL LETTER BBE;Lu;0;L;;;;;N;;;;10598;
+10572;VITHKUQI CAPITAL LETTER BE;Lu;0;L;;;;;N;;;;10599;
+10573;VITHKUQI CAPITAL LETTER CE;Lu;0;L;;;;;N;;;;1059A;
+10574;VITHKUQI CAPITAL LETTER CHE;Lu;0;L;;;;;N;;;;1059B;
+10575;VITHKUQI CAPITAL LETTER DE;Lu;0;L;;;;;N;;;;1059C;
+10576;VITHKUQI CAPITAL LETTER DHE;Lu;0;L;;;;;N;;;;1059D;
+10577;VITHKUQI CAPITAL LETTER EI;Lu;0;L;;;;;N;;;;1059E;
+10578;VITHKUQI CAPITAL LETTER E;Lu;0;L;;;;;N;;;;1059F;
+10579;VITHKUQI CAPITAL LETTER FE;Lu;0;L;;;;;N;;;;105A0;
+1057A;VITHKUQI CAPITAL LETTER GA;Lu;0;L;;;;;N;;;;105A1;
+1057C;VITHKUQI CAPITAL LETTER HA;Lu;0;L;;;;;N;;;;105A3;
+1057D;VITHKUQI CAPITAL LETTER HHA;Lu;0;L;;;;;N;;;;105A4;
+1057E;VITHKUQI CAPITAL LETTER I;Lu;0;L;;;;;N;;;;105A5;
+1057F;VITHKUQI CAPITAL LETTER IJE;Lu;0;L;;;;;N;;;;105A6;
+10580;VITHKUQI CAPITAL LETTER JE;Lu;0;L;;;;;N;;;;105A7;
+10581;VITHKUQI CAPITAL LETTER KA;Lu;0;L;;;;;N;;;;105A8;
+10582;VITHKUQI CAPITAL LETTER LA;Lu;0;L;;;;;N;;;;105A9;
+10583;VITHKUQI CAPITAL LETTER LLA;Lu;0;L;;;;;N;;;;105AA;
+10584;VITHKUQI CAPITAL LETTER ME;Lu;0;L;;;;;N;;;;105AB;
+10585;VITHKUQI CAPITAL LETTER NE;Lu;0;L;;;;;N;;;;105AC;
+10586;VITHKUQI CAPITAL LETTER NJE;Lu;0;L;;;;;N;;;;105AD;
+10587;VITHKUQI CAPITAL LETTER O;Lu;0;L;;;;;N;;;;105AE;
+10588;VITHKUQI CAPITAL LETTER PE;Lu;0;L;;;;;N;;;;105AF;
+10589;VITHKUQI CAPITAL LETTER QA;Lu;0;L;;;;;N;;;;105B0;
+1058A;VITHKUQI CAPITAL LETTER RE;Lu;0;L;;;;;N;;;;105B1;
+1058C;VITHKUQI CAPITAL LETTER SE;Lu;0;L;;;;;N;;;;105B3;
+1058D;VITHKUQI CAPITAL LETTER SHE;Lu;0;L;;;;;N;;;;105B4;
+1058E;VITHKUQI CAPITAL LETTER TE;Lu;0;L;;;;;N;;;;105B5;
+1058F;VITHKUQI CAPITAL LETTER THE;Lu;0;L;;;;;N;;;;105B6;
+10590;VITHKUQI CAPITAL LETTER U;Lu;0;L;;;;;N;;;;105B7;
+10591;VITHKUQI CAPITAL LETTER VE;Lu;0;L;;;;;N;;;;105B8;
+10592;VITHKUQI CAPITAL LETTER XE;Lu;0;L;;;;;N;;;;105B9;
+10594;VITHKUQI CAPITAL LETTER Y;Lu;0;L;;;;;N;;;;105BB;
+10595;VITHKUQI CAPITAL LETTER ZE;Lu;0;L;;;;;N;;;;105BC;
+10597;VITHKUQI SMALL LETTER A;Ll;0;L;;;;;N;;;10570;;10570
+10598;VITHKUQI SMALL LETTER BBE;Ll;0;L;;;;;N;;;10571;;10571
+10599;VITHKUQI SMALL LETTER BE;Ll;0;L;;;;;N;;;10572;;10572
+1059A;VITHKUQI SMALL LETTER CE;Ll;0;L;;;;;N;;;10573;;10573
+1059B;VITHKUQI SMALL LETTER CHE;Ll;0;L;;;;;N;;;10574;;10574
+1059C;VITHKUQI SMALL LETTER DE;Ll;0;L;;;;;N;;;10575;;10575
+1059D;VITHKUQI SMALL LETTER DHE;Ll;0;L;;;;;N;;;10576;;10576
+1059E;VITHKUQI SMALL LETTER EI;Ll;0;L;;;;;N;;;10577;;10577
+1059F;VITHKUQI SMALL LETTER E;Ll;0;L;;;;;N;;;10578;;10578
+105A0;VITHKUQI SMALL LETTER FE;Ll;0;L;;;;;N;;;10579;;10579
+105A1;VITHKUQI SMALL LETTER GA;Ll;0;L;;;;;N;;;1057A;;1057A
+105A3;VITHKUQI SMALL LETTER HA;Ll;0;L;;;;;N;;;1057C;;1057C
+105A4;VITHKUQI SMALL LETTER HHA;Ll;0;L;;;;;N;;;1057D;;1057D
+105A5;VITHKUQI SMALL LETTER I;Ll;0;L;;;;;N;;;1057E;;1057E
+105A6;VITHKUQI SMALL LETTER IJE;Ll;0;L;;;;;N;;;1057F;;1057F
+105A7;VITHKUQI SMALL LETTER JE;Ll;0;L;;;;;N;;;10580;;10580
+105A8;VITHKUQI SMALL LETTER KA;Ll;0;L;;;;;N;;;10581;;10581
+105A9;VITHKUQI SMALL LETTER LA;Ll;0;L;;;;;N;;;10582;;10582
+105AA;VITHKUQI SMALL LETTER LLA;Ll;0;L;;;;;N;;;10583;;10583
+105AB;VITHKUQI SMALL LETTER ME;Ll;0;L;;;;;N;;;10584;;10584
+105AC;VITHKUQI SMALL LETTER NE;Ll;0;L;;;;;N;;;10585;;10585
+105AD;VITHKUQI SMALL LETTER NJE;Ll;0;L;;;;;N;;;10586;;10586
+105AE;VITHKUQI SMALL LETTER O;Ll;0;L;;;;;N;;;10587;;10587
+105AF;VITHKUQI SMALL LETTER PE;Ll;0;L;;;;;N;;;10588;;10588
+105B0;VITHKUQI SMALL LETTER QA;Ll;0;L;;;;;N;;;10589;;10589
+105B1;VITHKUQI SMALL LETTER RE;Ll;0;L;;;;;N;;;1058A;;1058A
+105B3;VITHKUQI SMALL LETTER SE;Ll;0;L;;;;;N;;;1058C;;1058C
+105B4;VITHKUQI SMALL LETTER SHE;Ll;0;L;;;;;N;;;1058D;;1058D
+105B5;VITHKUQI SMALL LETTER TE;Ll;0;L;;;;;N;;;1058E;;1058E
+105B6;VITHKUQI SMALL LETTER THE;Ll;0;L;;;;;N;;;1058F;;1058F
+105B7;VITHKUQI SMALL LETTER U;Ll;0;L;;;;;N;;;10590;;10590
+105B8;VITHKUQI SMALL LETTER VE;Ll;0;L;;;;;N;;;10591;;10591
+105B9;VITHKUQI SMALL LETTER XE;Ll;0;L;;;;;N;;;10592;;10592
+105BB;VITHKUQI SMALL LETTER Y;Ll;0;L;;;;;N;;;10594;;10594
+105BC;VITHKUQI SMALL LETTER ZE;Ll;0;L;;;;;N;;;10595;;10595
10600;LINEAR A SIGN AB001;Lo;0;L;;;;;N;;;;;
10601;LINEAR A SIGN AB002;Lo;0;L;;;;;N;;;;;
10602;LINEAR A SIGN AB003;Lo;0;L;;;;;N;;;;;
@@ -18139,6 +18335,63 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
10765;LINEAR A SIGN A805;Lo;0;L;;;;;N;;;;;
10766;LINEAR A SIGN A806;Lo;0;L;;;;;N;;;;;
10767;LINEAR A SIGN A807;Lo;0;L;;;;;N;;;;;
+10780;MODIFIER LETTER SMALL CAPITAL AA;Lm;0;L;;;;;N;;;;;
+10781;MODIFIER LETTER SUPERSCRIPT TRIANGULAR COLON;Lm;0;L;<super> 02D0;;;;N;;;;;
+10782;MODIFIER LETTER SUPERSCRIPT HALF TRIANGULAR COLON;Lm;0;L;<super> 02D1;;;;N;;;;;
+10783;MODIFIER LETTER SMALL AE;Lm;0;L;<super> 00E6;;;;N;;;;;
+10784;MODIFIER LETTER SMALL CAPITAL B;Lm;0;L;<super> 0299;;;;N;;;;;
+10785;MODIFIER LETTER SMALL B WITH HOOK;Lm;0;L;<super> 0253;;;;N;;;;;
+10787;MODIFIER LETTER SMALL DZ DIGRAPH;Lm;0;L;<super> 02A3;;;;N;;;;;
+10788;MODIFIER LETTER SMALL DZ DIGRAPH WITH RETROFLEX HOOK;Lm;0;L;<super> AB66;;;;N;;;;;
+10789;MODIFIER LETTER SMALL DZ DIGRAPH WITH CURL;Lm;0;L;<super> 02A5;;;;N;;;;;
+1078A;MODIFIER LETTER SMALL DEZH DIGRAPH;Lm;0;L;<super> 02A4;;;;N;;;;;
+1078B;MODIFIER LETTER SMALL D WITH TAIL;Lm;0;L;<super> 0256;;;;N;;;;;
+1078C;MODIFIER LETTER SMALL D WITH HOOK;Lm;0;L;<super> 0257;;;;N;;;;;
+1078D;MODIFIER LETTER SMALL D WITH HOOK AND TAIL;Lm;0;L;<super> 1D91;;;;N;;;;;
+1078E;MODIFIER LETTER SMALL REVERSED E;Lm;0;L;<super> 0258;;;;N;;;;;
+1078F;MODIFIER LETTER SMALL CLOSED REVERSED OPEN E;Lm;0;L;<super> 025E;;;;N;;;;;
+10790;MODIFIER LETTER SMALL FENG DIGRAPH;Lm;0;L;<super> 02A9;;;;N;;;;;
+10791;MODIFIER LETTER SMALL RAMS HORN;Lm;0;L;<super> 0264;;;;N;;;;;
+10792;MODIFIER LETTER SMALL CAPITAL G;Lm;0;L;<super> 0262;;;;N;;;;;
+10793;MODIFIER LETTER SMALL G WITH HOOK;Lm;0;L;<super> 0260;;;;N;;;;;
+10794;MODIFIER LETTER SMALL CAPITAL G WITH HOOK;Lm;0;L;<super> 029B;;;;N;;;;;
+10795;MODIFIER LETTER SMALL H WITH STROKE;Lm;0;L;<super> 0127;;;;N;;;;;
+10796;MODIFIER LETTER SMALL CAPITAL H;Lm;0;L;<super> 029C;;;;N;;;;;
+10797;MODIFIER LETTER SMALL HENG WITH HOOK;Lm;0;L;<super> 0267;;;;N;;;;;
+10798;MODIFIER LETTER SMALL DOTLESS J WITH STROKE AND HOOK;Lm;0;L;<super> 0284;;;;N;;;;;
+10799;MODIFIER LETTER SMALL LS DIGRAPH;Lm;0;L;<super> 02AA;;;;N;;;;;
+1079A;MODIFIER LETTER SMALL LZ DIGRAPH;Lm;0;L;<super> 02AB;;;;N;;;;;
+1079B;MODIFIER LETTER SMALL L WITH BELT;Lm;0;L;<super> 026C;;;;N;;;;;
+1079C;MODIFIER LETTER SMALL CAPITAL L WITH BELT;Lm;0;L;<super> 1DF04;;;;N;;;;;
+1079D;MODIFIER LETTER SMALL L WITH RETROFLEX HOOK AND BELT;Lm;0;L;<super> A78E;;;;N;;;;;
+1079E;MODIFIER LETTER SMALL LEZH;Lm;0;L;<super> 026E;;;;N;;;;;
+1079F;MODIFIER LETTER SMALL LEZH WITH RETROFLEX HOOK;Lm;0;L;<super> 1DF05;;;;N;;;;;
+107A0;MODIFIER LETTER SMALL TURNED Y;Lm;0;L;<super> 028E;;;;N;;;;;
+107A1;MODIFIER LETTER SMALL TURNED Y WITH BELT;Lm;0;L;<super> 1DF06;;;;N;;;;;
+107A2;MODIFIER LETTER SMALL O WITH STROKE;Lm;0;L;<super> 00F8;;;;N;;;;;
+107A3;MODIFIER LETTER SMALL CAPITAL OE;Lm;0;L;<super> 0276;;;;N;;;;;
+107A4;MODIFIER LETTER SMALL CLOSED OMEGA;Lm;0;L;<super> 0277;;;;N;;;;;
+107A5;MODIFIER LETTER SMALL Q;Lm;0;L;<super> 0071;;;;N;;;;;
+107A6;MODIFIER LETTER SMALL TURNED R WITH LONG LEG;Lm;0;L;<super> 027A;;;;N;;;;;
+107A7;MODIFIER LETTER SMALL TURNED R WITH LONG LEG AND RETROFLEX HOOK;Lm;0;L;<super> 1DF08;;;;N;;;;;
+107A8;MODIFIER LETTER SMALL R WITH TAIL;Lm;0;L;<super> 027D;;;;N;;;;;
+107A9;MODIFIER LETTER SMALL R WITH FISHHOOK;Lm;0;L;<super> 027E;;;;N;;;;;
+107AA;MODIFIER LETTER SMALL CAPITAL R;Lm;0;L;<super> 0280;;;;N;;;;;
+107AB;MODIFIER LETTER SMALL TC DIGRAPH WITH CURL;Lm;0;L;<super> 02A8;;;;N;;;;;
+107AC;MODIFIER LETTER SMALL TS DIGRAPH;Lm;0;L;<super> 02A6;;;;N;;;;;
+107AD;MODIFIER LETTER SMALL TS DIGRAPH WITH RETROFLEX HOOK;Lm;0;L;<super> AB67;;;;N;;;;;
+107AE;MODIFIER LETTER SMALL TESH DIGRAPH;Lm;0;L;<super> 02A7;;;;N;;;;;
+107AF;MODIFIER LETTER SMALL T WITH RETROFLEX HOOK;Lm;0;L;<super> 0288;;;;N;;;;;
+107B0;MODIFIER LETTER SMALL V WITH RIGHT HOOK;Lm;0;L;<super> 2C71;;;;N;;;;;
+107B2;MODIFIER LETTER SMALL CAPITAL Y;Lm;0;L;<super> 028F;;;;N;;;;;
+107B3;MODIFIER LETTER GLOTTAL STOP WITH STROKE;Lm;0;L;<super> 02A1;;;;N;;;;;
+107B4;MODIFIER LETTER REVERSED GLOTTAL STOP WITH STROKE;Lm;0;L;<super> 02A2;;;;N;;;;;
+107B5;MODIFIER LETTER BILABIAL CLICK;Lm;0;L;<super> 0298;;;;N;;;;;
+107B6;MODIFIER LETTER DENTAL CLICK;Lm;0;L;<super> 01C0;;;;N;;;;;
+107B7;MODIFIER LETTER LATERAL CLICK;Lm;0;L;<super> 01C1;;;;N;;;;;
+107B8;MODIFIER LETTER ALVEOLAR CLICK;Lm;0;L;<super> 01C2;;;;N;;;;;
+107B9;MODIFIER LETTER RETROFLEX CLICK WITH RETROFLEX HOOK;Lm;0;L;<super> 1DF0A;;;;N;;;;;
+107BA;MODIFIER LETTER SMALL S WITH CURL;Lm;0;L;<super> 1DF1E;;;;N;;;;;
10800;CYPRIOT SYLLABLE A;Lo;0;R;;;;;N;;;;;
10801;CYPRIOT SYLLABLE E;Lo;0;R;;;;;N;;;;;
10802;CYPRIOT SYLLABLE I;Lo;0;R;;;;;N;;;;;
@@ -19222,6 +19475,32 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
10F57;SOGDIAN PUNCTUATION CIRCLE WITH DOT;Po;0;AL;;;;;N;;;;;
10F58;SOGDIAN PUNCTUATION TWO CIRCLES WITH DOTS;Po;0;AL;;;;;N;;;;;
10F59;SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT;Po;0;AL;;;;;N;;;;;
+10F70;OLD UYGHUR LETTER ALEPH;Lo;0;R;;;;;N;;;;;
+10F71;OLD UYGHUR LETTER BETH;Lo;0;R;;;;;N;;;;;
+10F72;OLD UYGHUR LETTER GIMEL-HETH;Lo;0;R;;;;;N;;;;;
+10F73;OLD UYGHUR LETTER WAW;Lo;0;R;;;;;N;;;;;
+10F74;OLD UYGHUR LETTER ZAYIN;Lo;0;R;;;;;N;;;;;
+10F75;OLD UYGHUR LETTER FINAL HETH;Lo;0;R;;;;;N;;;;;
+10F76;OLD UYGHUR LETTER YODH;Lo;0;R;;;;;N;;;;;
+10F77;OLD UYGHUR LETTER KAPH;Lo;0;R;;;;;N;;;;;
+10F78;OLD UYGHUR LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
+10F79;OLD UYGHUR LETTER MEM;Lo;0;R;;;;;N;;;;;
+10F7A;OLD UYGHUR LETTER NUN;Lo;0;R;;;;;N;;;;;
+10F7B;OLD UYGHUR LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+10F7C;OLD UYGHUR LETTER PE;Lo;0;R;;;;;N;;;;;
+10F7D;OLD UYGHUR LETTER SADHE;Lo;0;R;;;;;N;;;;;
+10F7E;OLD UYGHUR LETTER RESH;Lo;0;R;;;;;N;;;;;
+10F7F;OLD UYGHUR LETTER SHIN;Lo;0;R;;;;;N;;;;;
+10F80;OLD UYGHUR LETTER TAW;Lo;0;R;;;;;N;;;;;
+10F81;OLD UYGHUR LETTER LESH;Lo;0;R;;;;;N;;;;;
+10F82;OLD UYGHUR COMBINING DOT ABOVE;Mn;230;NSM;;;;;N;;;;;
+10F83;OLD UYGHUR COMBINING DOT BELOW;Mn;220;NSM;;;;;N;;;;;
+10F84;OLD UYGHUR COMBINING TWO DOTS ABOVE;Mn;230;NSM;;;;;N;;;;;
+10F85;OLD UYGHUR COMBINING TWO DOTS BELOW;Mn;220;NSM;;;;;N;;;;;
+10F86;OLD UYGHUR PUNCTUATION BAR;Po;0;R;;;;;N;;;;;
+10F87;OLD UYGHUR PUNCTUATION TWO BARS;Po;0;R;;;;;N;;;;;
+10F88;OLD UYGHUR PUNCTUATION TWO DOTS;Po;0;R;;;;;N;;;;;
+10F89;OLD UYGHUR PUNCTUATION FOUR DOTS;Po;0;R;;;;;N;;;;;
10FB0;CHORASMIAN LETTER ALEPH;Lo;0;R;;;;;N;;;;;
10FB1;CHORASMIAN LETTER SMALL ALEPH;Lo;0;R;;;;;N;;;;;
10FB2;CHORASMIAN LETTER BETH;Lo;0;R;;;;;N;;;;;
@@ -19381,6 +19660,12 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+11070;BRAHMI SIGN OLD TAMIL VIRAMA;Mn;9;NSM;;;;;N;;;;;
+11071;BRAHMI LETTER OLD TAMIL SHORT E;Lo;0;L;;;;;N;;;;;
+11072;BRAHMI LETTER OLD TAMIL SHORT O;Lo;0;L;;;;;N;;;;;
+11073;BRAHMI VOWEL SIGN OLD TAMIL SHORT E;Mn;0;NSM;;;;;N;;;;;
+11074;BRAHMI VOWEL SIGN OLD TAMIL SHORT O;Mn;0;NSM;;;;;N;;;;;
+11075;BRAHMI LETTER OLD TAMIL LLA;Lo;0;L;;;;;N;;;;;
1107F;BRAHMI NUMBER JOINER;Mn;9;NSM;;;;;N;;;;;
11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;;
@@ -19448,6 +19733,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
110BF;KAITHI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;;
110C0;KAITHI DANDA;Po;0;L;;;;;N;;;;;
110C1;KAITHI DOUBLE DANDA;Po;0;L;;;;;N;;;;;
+110C2;KAITHI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;;
110CD;KAITHI NUMBER SIGN ABOVE;Cf;0;L;;;;;N;;;;;
110D0;SORA SOMPENG LETTER SAH;Lo;0;L;;;;;N;;;;;
110D1;SORA SOMPENG LETTER TAH;Lo;0;L;;;;;N;;;;;
@@ -20385,6 +20671,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
116B6;TAKRI SIGN VIRAMA;Mc;9;L;;;;;N;;;;;
116B7;TAKRI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
116B8;TAKRI LETTER ARCHAIC KHA;Lo;0;L;;;;;N;;;;;
+116B9;TAKRI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
116C0;TAKRI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
116C1;TAKRI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
116C2;TAKRI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
@@ -20453,6 +20740,13 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1173D;AHOM SIGN SECTION;Po;0;L;;;;;N;;;;;
1173E;AHOM SIGN RULAI;Po;0;L;;;;;N;;;;;
1173F;AHOM SYMBOL VI;So;0;L;;;;;N;;;;;
+11740;AHOM LETTER CA;Lo;0;L;;;;;N;;;;;
+11741;AHOM LETTER TTA;Lo;0;L;;;;;N;;;;;
+11742;AHOM LETTER TTHA;Lo;0;L;;;;;N;;;;;
+11743;AHOM LETTER DDA;Lo;0;L;;;;;N;;;;;
+11744;AHOM LETTER DDHA;Lo;0;L;;;;;N;;;;;
+11745;AHOM LETTER NNA;Lo;0;L;;;;;N;;;;;
+11746;AHOM LETTER LLA;Lo;0;L;;;;;N;;;;;
11800;DOGRA LETTER A;Lo;0;L;;;;;N;;;;;
11801;DOGRA LETTER AA;Lo;0;L;;;;;N;;;;;
11802;DOGRA LETTER I;Lo;0;L;;;;;N;;;;;
@@ -20889,6 +21183,22 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
11AA0;SOYOMBO HEAD MARK WITH MOON AND SUN;Po;0;L;;;;;N;;;;;
11AA1;SOYOMBO TERMINAL MARK-1;Po;0;L;;;;;N;;;;;
11AA2;SOYOMBO TERMINAL MARK-2;Po;0;L;;;;;N;;;;;
+11AB0;CANADIAN SYLLABICS NATTILIK HI;Lo;0;L;;;;;N;;;;;
+11AB1;CANADIAN SYLLABICS NATTILIK HII;Lo;0;L;;;;;N;;;;;
+11AB2;CANADIAN SYLLABICS NATTILIK HO;Lo;0;L;;;;;N;;;;;
+11AB3;CANADIAN SYLLABICS NATTILIK HOO;Lo;0;L;;;;;N;;;;;
+11AB4;CANADIAN SYLLABICS NATTILIK HA;Lo;0;L;;;;;N;;;;;
+11AB5;CANADIAN SYLLABICS NATTILIK HAA;Lo;0;L;;;;;N;;;;;
+11AB6;CANADIAN SYLLABICS NATTILIK SHRI;Lo;0;L;;;;;N;;;;;
+11AB7;CANADIAN SYLLABICS NATTILIK SHRII;Lo;0;L;;;;;N;;;;;
+11AB8;CANADIAN SYLLABICS NATTILIK SHRO;Lo;0;L;;;;;N;;;;;
+11AB9;CANADIAN SYLLABICS NATTILIK SHROO;Lo;0;L;;;;;N;;;;;
+11ABA;CANADIAN SYLLABICS NATTILIK SHRA;Lo;0;L;;;;;N;;;;;
+11ABB;CANADIAN SYLLABICS NATTILIK SHRAA;Lo;0;L;;;;;N;;;;;
+11ABC;CANADIAN SYLLABICS SPE;Lo;0;L;;;;;N;;;;;
+11ABD;CANADIAN SYLLABICS SPI;Lo;0;L;;;;;N;;;;;
+11ABE;CANADIAN SYLLABICS SPO;Lo;0;L;;;;;N;;;;;
+11ABF;CANADIAN SYLLABICS SPA;Lo;0;L;;;;;N;;;;;
11AC0;PAU CIN HAU LETTER PA;Lo;0;L;;;;;N;;;;;
11AC1;PAU CIN HAU LETTER KA;Lo;0;L;;;;;N;;;;;
11AC2;PAU CIN HAU LETTER LA;Lo;0;L;;;;;N;;;;;
@@ -22560,6 +22870,105 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
12541;CUNEIFORM SIGN ZA7;Lo;0;L;;;;;N;;;;;
12542;CUNEIFORM SIGN ZU OVER ZU PLUS SAR;Lo;0;L;;;;;N;;;;;
12543;CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU;Lo;0;L;;;;;N;;;;;
+12F90;CYPRO-MINOAN SIGN CM001;Lo;0;L;;;;;N;;;;;
+12F91;CYPRO-MINOAN SIGN CM002;Lo;0;L;;;;;N;;;;;
+12F92;CYPRO-MINOAN SIGN CM004;Lo;0;L;;;;;N;;;;;
+12F93;CYPRO-MINOAN SIGN CM005;Lo;0;L;;;;;N;;;;;
+12F94;CYPRO-MINOAN SIGN CM006;Lo;0;L;;;;;N;;;;;
+12F95;CYPRO-MINOAN SIGN CM007;Lo;0;L;;;;;N;;;;;
+12F96;CYPRO-MINOAN SIGN CM008;Lo;0;L;;;;;N;;;;;
+12F97;CYPRO-MINOAN SIGN CM009;Lo;0;L;;;;;N;;;;;
+12F98;CYPRO-MINOAN SIGN CM010;Lo;0;L;;;;;N;;;;;
+12F99;CYPRO-MINOAN SIGN CM011;Lo;0;L;;;;;N;;;;;
+12F9A;CYPRO-MINOAN SIGN CM012;Lo;0;L;;;;;N;;;;;
+12F9B;CYPRO-MINOAN SIGN CM012B;Lo;0;L;;;;;N;;;;;
+12F9C;CYPRO-MINOAN SIGN CM013;Lo;0;L;;;;;N;;;;;
+12F9D;CYPRO-MINOAN SIGN CM015;Lo;0;L;;;;;N;;;;;
+12F9E;CYPRO-MINOAN SIGN CM017;Lo;0;L;;;;;N;;;;;
+12F9F;CYPRO-MINOAN SIGN CM019;Lo;0;L;;;;;N;;;;;
+12FA0;CYPRO-MINOAN SIGN CM021;Lo;0;L;;;;;N;;;;;
+12FA1;CYPRO-MINOAN SIGN CM023;Lo;0;L;;;;;N;;;;;
+12FA2;CYPRO-MINOAN SIGN CM024;Lo;0;L;;;;;N;;;;;
+12FA3;CYPRO-MINOAN SIGN CM025;Lo;0;L;;;;;N;;;;;
+12FA4;CYPRO-MINOAN SIGN CM026;Lo;0;L;;;;;N;;;;;
+12FA5;CYPRO-MINOAN SIGN CM027;Lo;0;L;;;;;N;;;;;
+12FA6;CYPRO-MINOAN SIGN CM028;Lo;0;L;;;;;N;;;;;
+12FA7;CYPRO-MINOAN SIGN CM029;Lo;0;L;;;;;N;;;;;
+12FA8;CYPRO-MINOAN SIGN CM030;Lo;0;L;;;;;N;;;;;
+12FA9;CYPRO-MINOAN SIGN CM033;Lo;0;L;;;;;N;;;;;
+12FAA;CYPRO-MINOAN SIGN CM034;Lo;0;L;;;;;N;;;;;
+12FAB;CYPRO-MINOAN SIGN CM035;Lo;0;L;;;;;N;;;;;
+12FAC;CYPRO-MINOAN SIGN CM036;Lo;0;L;;;;;N;;;;;
+12FAD;CYPRO-MINOAN SIGN CM037;Lo;0;L;;;;;N;;;;;
+12FAE;CYPRO-MINOAN SIGN CM038;Lo;0;L;;;;;N;;;;;
+12FAF;CYPRO-MINOAN SIGN CM039;Lo;0;L;;;;;N;;;;;
+12FB0;CYPRO-MINOAN SIGN CM040;Lo;0;L;;;;;N;;;;;
+12FB1;CYPRO-MINOAN SIGN CM041;Lo;0;L;;;;;N;;;;;
+12FB2;CYPRO-MINOAN SIGN CM044;Lo;0;L;;;;;N;;;;;
+12FB3;CYPRO-MINOAN SIGN CM046;Lo;0;L;;;;;N;;;;;
+12FB4;CYPRO-MINOAN SIGN CM047;Lo;0;L;;;;;N;;;;;
+12FB5;CYPRO-MINOAN SIGN CM049;Lo;0;L;;;;;N;;;;;
+12FB6;CYPRO-MINOAN SIGN CM050;Lo;0;L;;;;;N;;;;;
+12FB7;CYPRO-MINOAN SIGN CM051;Lo;0;L;;;;;N;;;;;
+12FB8;CYPRO-MINOAN SIGN CM052;Lo;0;L;;;;;N;;;;;
+12FB9;CYPRO-MINOAN SIGN CM053;Lo;0;L;;;;;N;;;;;
+12FBA;CYPRO-MINOAN SIGN CM054;Lo;0;L;;;;;N;;;;;
+12FBB;CYPRO-MINOAN SIGN CM055;Lo;0;L;;;;;N;;;;;
+12FBC;CYPRO-MINOAN SIGN CM056;Lo;0;L;;;;;N;;;;;
+12FBD;CYPRO-MINOAN SIGN CM058;Lo;0;L;;;;;N;;;;;
+12FBE;CYPRO-MINOAN SIGN CM059;Lo;0;L;;;;;N;;;;;
+12FBF;CYPRO-MINOAN SIGN CM060;Lo;0;L;;;;;N;;;;;
+12FC0;CYPRO-MINOAN SIGN CM061;Lo;0;L;;;;;N;;;;;
+12FC1;CYPRO-MINOAN SIGN CM062;Lo;0;L;;;;;N;;;;;
+12FC2;CYPRO-MINOAN SIGN CM063;Lo;0;L;;;;;N;;;;;
+12FC3;CYPRO-MINOAN SIGN CM064;Lo;0;L;;;;;N;;;;;
+12FC4;CYPRO-MINOAN SIGN CM066;Lo;0;L;;;;;N;;;;;
+12FC5;CYPRO-MINOAN SIGN CM067;Lo;0;L;;;;;N;;;;;
+12FC6;CYPRO-MINOAN SIGN CM068;Lo;0;L;;;;;N;;;;;
+12FC7;CYPRO-MINOAN SIGN CM069;Lo;0;L;;;;;N;;;;;
+12FC8;CYPRO-MINOAN SIGN CM070;Lo;0;L;;;;;N;;;;;
+12FC9;CYPRO-MINOAN SIGN CM071;Lo;0;L;;;;;N;;;;;
+12FCA;CYPRO-MINOAN SIGN CM072;Lo;0;L;;;;;N;;;;;
+12FCB;CYPRO-MINOAN SIGN CM073;Lo;0;L;;;;;N;;;;;
+12FCC;CYPRO-MINOAN SIGN CM074;Lo;0;L;;;;;N;;;;;
+12FCD;CYPRO-MINOAN SIGN CM075;Lo;0;L;;;;;N;;;;;
+12FCE;CYPRO-MINOAN SIGN CM075B;Lo;0;L;;;;;N;;;;;
+12FCF;CYPRO-MINOAN SIGN CM076;Lo;0;L;;;;;N;;;;;
+12FD0;CYPRO-MINOAN SIGN CM078;Lo;0;L;;;;;N;;;;;
+12FD1;CYPRO-MINOAN SIGN CM079;Lo;0;L;;;;;N;;;;;
+12FD2;CYPRO-MINOAN SIGN CM080;Lo;0;L;;;;;N;;;;;
+12FD3;CYPRO-MINOAN SIGN CM081;Lo;0;L;;;;;N;;;;;
+12FD4;CYPRO-MINOAN SIGN CM082;Lo;0;L;;;;;N;;;;;
+12FD5;CYPRO-MINOAN SIGN CM083;Lo;0;L;;;;;N;;;;;
+12FD6;CYPRO-MINOAN SIGN CM084;Lo;0;L;;;;;N;;;;;
+12FD7;CYPRO-MINOAN SIGN CM085;Lo;0;L;;;;;N;;;;;
+12FD8;CYPRO-MINOAN SIGN CM086;Lo;0;L;;;;;N;;;;;
+12FD9;CYPRO-MINOAN SIGN CM087;Lo;0;L;;;;;N;;;;;
+12FDA;CYPRO-MINOAN SIGN CM088;Lo;0;L;;;;;N;;;;;
+12FDB;CYPRO-MINOAN SIGN CM089;Lo;0;L;;;;;N;;;;;
+12FDC;CYPRO-MINOAN SIGN CM090;Lo;0;L;;;;;N;;;;;
+12FDD;CYPRO-MINOAN SIGN CM091;Lo;0;L;;;;;N;;;;;
+12FDE;CYPRO-MINOAN SIGN CM092;Lo;0;L;;;;;N;;;;;
+12FDF;CYPRO-MINOAN SIGN CM094;Lo;0;L;;;;;N;;;;;
+12FE0;CYPRO-MINOAN SIGN CM095;Lo;0;L;;;;;N;;;;;
+12FE1;CYPRO-MINOAN SIGN CM096;Lo;0;L;;;;;N;;;;;
+12FE2;CYPRO-MINOAN SIGN CM097;Lo;0;L;;;;;N;;;;;
+12FE3;CYPRO-MINOAN SIGN CM098;Lo;0;L;;;;;N;;;;;
+12FE4;CYPRO-MINOAN SIGN CM099;Lo;0;L;;;;;N;;;;;
+12FE5;CYPRO-MINOAN SIGN CM100;Lo;0;L;;;;;N;;;;;
+12FE6;CYPRO-MINOAN SIGN CM101;Lo;0;L;;;;;N;;;;;
+12FE7;CYPRO-MINOAN SIGN CM102;Lo;0;L;;;;;N;;;;;
+12FE8;CYPRO-MINOAN SIGN CM103;Lo;0;L;;;;;N;;;;;
+12FE9;CYPRO-MINOAN SIGN CM104;Lo;0;L;;;;;N;;;;;
+12FEA;CYPRO-MINOAN SIGN CM105;Lo;0;L;;;;;N;;;;;
+12FEB;CYPRO-MINOAN SIGN CM107;Lo;0;L;;;;;N;;;;;
+12FEC;CYPRO-MINOAN SIGN CM108;Lo;0;L;;;;;N;;;;;
+12FED;CYPRO-MINOAN SIGN CM109;Lo;0;L;;;;;N;;;;;
+12FEE;CYPRO-MINOAN SIGN CM110;Lo;0;L;;;;;N;;;;;
+12FEF;CYPRO-MINOAN SIGN CM112;Lo;0;L;;;;;N;;;;;
+12FF0;CYPRO-MINOAN SIGN CM114;Lo;0;L;;;;;N;;;;;
+12FF1;CYPRO-MINOAN SIGN CM301;Po;0;L;;;;;N;;;;;
+12FF2;CYPRO-MINOAN SIGN CM302;Po;0;L;;;;;N;;;;;
13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;;
13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;;
13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;;
@@ -24835,6 +25244,95 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
16A69;MRO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
16A6E;MRO DANDA;Po;0;L;;;;;N;;;;;
16A6F;MRO DOUBLE DANDA;Po;0;L;;;;;N;;;;;
+16A70;TANGSA LETTER OZ;Lo;0;L;;;;;N;;;;;
+16A71;TANGSA LETTER OC;Lo;0;L;;;;;N;;;;;
+16A72;TANGSA LETTER OQ;Lo;0;L;;;;;N;;;;;
+16A73;TANGSA LETTER OX;Lo;0;L;;;;;N;;;;;
+16A74;TANGSA LETTER AZ;Lo;0;L;;;;;N;;;;;
+16A75;TANGSA LETTER AC;Lo;0;L;;;;;N;;;;;
+16A76;TANGSA LETTER AQ;Lo;0;L;;;;;N;;;;;
+16A77;TANGSA LETTER AX;Lo;0;L;;;;;N;;;;;
+16A78;TANGSA LETTER VZ;Lo;0;L;;;;;N;;;;;
+16A79;TANGSA LETTER VC;Lo;0;L;;;;;N;;;;;
+16A7A;TANGSA LETTER VQ;Lo;0;L;;;;;N;;;;;
+16A7B;TANGSA LETTER VX;Lo;0;L;;;;;N;;;;;
+16A7C;TANGSA LETTER EZ;Lo;0;L;;;;;N;;;;;
+16A7D;TANGSA LETTER EC;Lo;0;L;;;;;N;;;;;
+16A7E;TANGSA LETTER EQ;Lo;0;L;;;;;N;;;;;
+16A7F;TANGSA LETTER EX;Lo;0;L;;;;;N;;;;;
+16A80;TANGSA LETTER IZ;Lo;0;L;;;;;N;;;;;
+16A81;TANGSA LETTER IC;Lo;0;L;;;;;N;;;;;
+16A82;TANGSA LETTER IQ;Lo;0;L;;;;;N;;;;;
+16A83;TANGSA LETTER IX;Lo;0;L;;;;;N;;;;;
+16A84;TANGSA LETTER UZ;Lo;0;L;;;;;N;;;;;
+16A85;TANGSA LETTER UC;Lo;0;L;;;;;N;;;;;
+16A86;TANGSA LETTER UQ;Lo;0;L;;;;;N;;;;;
+16A87;TANGSA LETTER UX;Lo;0;L;;;;;N;;;;;
+16A88;TANGSA LETTER AWZ;Lo;0;L;;;;;N;;;;;
+16A89;TANGSA LETTER AWC;Lo;0;L;;;;;N;;;;;
+16A8A;TANGSA LETTER AWQ;Lo;0;L;;;;;N;;;;;
+16A8B;TANGSA LETTER AWX;Lo;0;L;;;;;N;;;;;
+16A8C;TANGSA LETTER UIZ;Lo;0;L;;;;;N;;;;;
+16A8D;TANGSA LETTER UIC;Lo;0;L;;;;;N;;;;;
+16A8E;TANGSA LETTER UIQ;Lo;0;L;;;;;N;;;;;
+16A8F;TANGSA LETTER UIX;Lo;0;L;;;;;N;;;;;
+16A90;TANGSA LETTER FINAL NG;Lo;0;L;;;;;N;;;;;
+16A91;TANGSA LETTER LONG UEX;Lo;0;L;;;;;N;;;;;
+16A92;TANGSA LETTER SHORT UEZ;Lo;0;L;;;;;N;;;;;
+16A93;TANGSA LETTER SHORT AWX;Lo;0;L;;;;;N;;;;;
+16A94;TANGSA LETTER UEC;Lo;0;L;;;;;N;;;;;
+16A95;TANGSA LETTER UEZ;Lo;0;L;;;;;N;;;;;
+16A96;TANGSA LETTER UEQ;Lo;0;L;;;;;N;;;;;
+16A97;TANGSA LETTER UEX;Lo;0;L;;;;;N;;;;;
+16A98;TANGSA LETTER UIUZ;Lo;0;L;;;;;N;;;;;
+16A99;TANGSA LETTER UIUC;Lo;0;L;;;;;N;;;;;
+16A9A;TANGSA LETTER UIUQ;Lo;0;L;;;;;N;;;;;
+16A9B;TANGSA LETTER UIUX;Lo;0;L;;;;;N;;;;;
+16A9C;TANGSA LETTER MZ;Lo;0;L;;;;;N;;;;;
+16A9D;TANGSA LETTER MC;Lo;0;L;;;;;N;;;;;
+16A9E;TANGSA LETTER MQ;Lo;0;L;;;;;N;;;;;
+16A9F;TANGSA LETTER MX;Lo;0;L;;;;;N;;;;;
+16AA0;TANGSA LETTER KA;Lo;0;L;;;;;N;;;;;
+16AA1;TANGSA LETTER KHA;Lo;0;L;;;;;N;;;;;
+16AA2;TANGSA LETTER GA;Lo;0;L;;;;;N;;;;;
+16AA3;TANGSA LETTER NGA;Lo;0;L;;;;;N;;;;;
+16AA4;TANGSA LETTER SA;Lo;0;L;;;;;N;;;;;
+16AA5;TANGSA LETTER YA;Lo;0;L;;;;;N;;;;;
+16AA6;TANGSA LETTER WA;Lo;0;L;;;;;N;;;;;
+16AA7;TANGSA LETTER PA;Lo;0;L;;;;;N;;;;;
+16AA8;TANGSA LETTER NYA;Lo;0;L;;;;;N;;;;;
+16AA9;TANGSA LETTER PHA;Lo;0;L;;;;;N;;;;;
+16AAA;TANGSA LETTER BA;Lo;0;L;;;;;N;;;;;
+16AAB;TANGSA LETTER MA;Lo;0;L;;;;;N;;;;;
+16AAC;TANGSA LETTER NA;Lo;0;L;;;;;N;;;;;
+16AAD;TANGSA LETTER HA;Lo;0;L;;;;;N;;;;;
+16AAE;TANGSA LETTER LA;Lo;0;L;;;;;N;;;;;
+16AAF;TANGSA LETTER HTA;Lo;0;L;;;;;N;;;;;
+16AB0;TANGSA LETTER TA;Lo;0;L;;;;;N;;;;;
+16AB1;TANGSA LETTER DA;Lo;0;L;;;;;N;;;;;
+16AB2;TANGSA LETTER RA;Lo;0;L;;;;;N;;;;;
+16AB3;TANGSA LETTER NHA;Lo;0;L;;;;;N;;;;;
+16AB4;TANGSA LETTER SHA;Lo;0;L;;;;;N;;;;;
+16AB5;TANGSA LETTER CA;Lo;0;L;;;;;N;;;;;
+16AB6;TANGSA LETTER TSA;Lo;0;L;;;;;N;;;;;
+16AB7;TANGSA LETTER GHA;Lo;0;L;;;;;N;;;;;
+16AB8;TANGSA LETTER HTTA;Lo;0;L;;;;;N;;;;;
+16AB9;TANGSA LETTER THA;Lo;0;L;;;;;N;;;;;
+16ABA;TANGSA LETTER XA;Lo;0;L;;;;;N;;;;;
+16ABB;TANGSA LETTER FA;Lo;0;L;;;;;N;;;;;
+16ABC;TANGSA LETTER DHA;Lo;0;L;;;;;N;;;;;
+16ABD;TANGSA LETTER CHA;Lo;0;L;;;;;N;;;;;
+16ABE;TANGSA LETTER ZA;Lo;0;L;;;;;N;;;;;
+16AC0;TANGSA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+16AC1;TANGSA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+16AC2;TANGSA DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+16AC3;TANGSA DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+16AC4;TANGSA DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+16AC5;TANGSA DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+16AC6;TANGSA DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+16AC7;TANGSA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+16AC8;TANGSA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+16AC9;TANGSA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
16AD0;BASSA VAH LETTER ENNI;Lo;0;L;;;;;N;;;;;
16AD1;BASSA VAH LETTER KA;Lo;0;L;;;;;N;;;;;
16AD2;BASSA VAH LETTER SE;Lo;0;L;;;;;N;;;;;
@@ -26487,6 +26985,19 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
18CD5;KHITAN SMALL SCRIPT CHARACTER-18CD5;Lo;0;L;;;;;N;;;;;
18D00;<Tangut Ideograph Supplement, First>;Lo;0;L;;;;;N;;;;;
18D08;<Tangut Ideograph Supplement, Last>;Lo;0;L;;;;;N;;;;;
+1AFF0;KATAKANA LETTER MINNAN TONE-2;Lm;0;L;;;;;N;;;;;
+1AFF1;KATAKANA LETTER MINNAN TONE-3;Lm;0;L;;;;;N;;;;;
+1AFF2;KATAKANA LETTER MINNAN TONE-4;Lm;0;L;;;;;N;;;;;
+1AFF3;KATAKANA LETTER MINNAN TONE-5;Lm;0;L;;;;;N;;;;;
+1AFF5;KATAKANA LETTER MINNAN TONE-7;Lm;0;L;;;;;N;;;;;
+1AFF6;KATAKANA LETTER MINNAN TONE-8;Lm;0;L;;;;;N;;;;;
+1AFF7;KATAKANA LETTER MINNAN NASALIZED TONE-1;Lm;0;L;;;;;N;;;;;
+1AFF8;KATAKANA LETTER MINNAN NASALIZED TONE-2;Lm;0;L;;;;;N;;;;;
+1AFF9;KATAKANA LETTER MINNAN NASALIZED TONE-3;Lm;0;L;;;;;N;;;;;
+1AFFA;KATAKANA LETTER MINNAN NASALIZED TONE-4;Lm;0;L;;;;;N;;;;;
+1AFFB;KATAKANA LETTER MINNAN NASALIZED TONE-5;Lm;0;L;;;;;N;;;;;
+1AFFD;KATAKANA LETTER MINNAN NASALIZED TONE-7;Lm;0;L;;;;;N;;;;;
+1AFFE;KATAKANA LETTER MINNAN NASALIZED TONE-8;Lm;0;L;;;;;N;;;;;
1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;;
1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;;
1B002;HENTAIGANA LETTER A-1;Lo;0;L;;;;;N;;;;;
@@ -26774,6 +27285,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1B11C;HENTAIGANA LETTER WO-7;Lo;0;L;;;;;N;;;;;
1B11D;HENTAIGANA LETTER N-MU-MO-1;Lo;0;L;;;;;N;;;;;
1B11E;HENTAIGANA LETTER N-MU-MO-2;Lo;0;L;;;;;N;;;;;
+1B11F;HIRAGANA LETTER ARCHAIC WU;Lo;0;L;;;;;N;;;;;
+1B120;KATAKANA LETTER ARCHAIC YI;Lo;0;L;;;;;N;;;;;
+1B121;KATAKANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;;
+1B122;KATAKANA LETTER ARCHAIC WU;Lo;0;L;;;;;N;;;;;
1B150;HIRAGANA LETTER SMALL WI;Lo;0;L;;;;;N;;;;;
1B151;HIRAGANA LETTER SMALL WE;Lo;0;L;;;;;N;;;;;
1B152;HIRAGANA LETTER SMALL WO;Lo;0;L;;;;;N;;;;;
@@ -27324,6 +27839,191 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1BCA1;SHORTHAND FORMAT CONTINUING OVERLAP;Cf;0;BN;;;;;N;;;;;
1BCA2;SHORTHAND FORMAT DOWN STEP;Cf;0;BN;;;;;N;;;;;
1BCA3;SHORTHAND FORMAT UP STEP;Cf;0;BN;;;;;N;;;;;
+1CF00;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF01;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF02;ZNAMENNY COMBINING MARK TSATA ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF03;ZNAMENNY COMBINING MARK GORAZDO NIZKO ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF04;ZNAMENNY COMBINING MARK NIZKO ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF05;ZNAMENNY COMBINING MARK SREDNE ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF06;ZNAMENNY COMBINING MARK MALO POVYSHE ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF07;ZNAMENNY COMBINING MARK POVYSHE ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF08;ZNAMENNY COMBINING MARK VYSOKO ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF09;ZNAMENNY COMBINING MARK MALO POVYSHE S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF0A;ZNAMENNY COMBINING MARK POVYSHE S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF0B;ZNAMENNY COMBINING MARK VYSOKO S KHOKHLOM ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF0C;ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF0D;ZNAMENNY COMBINING MARK NIZKO S KRYZHEM ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF0E;ZNAMENNY COMBINING MARK TSATA ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF0F;ZNAMENNY COMBINING MARK GORAZDO NIZKO ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF10;ZNAMENNY COMBINING MARK NIZKO ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF11;ZNAMENNY COMBINING MARK SREDNE ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF12;ZNAMENNY COMBINING MARK MALO POVYSHE ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF13;ZNAMENNY COMBINING MARK POVYSHE ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF14;ZNAMENNY COMBINING MARK VYSOKO ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF15;ZNAMENNY COMBINING MARK MALO POVYSHE S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF16;ZNAMENNY COMBINING MARK POVYSHE S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF17;ZNAMENNY COMBINING MARK VYSOKO S KHOKHLOM ON RIGHT;Mn;0;NSM;;;;;N;;;;;
+1CF18;ZNAMENNY COMBINING MARK TSATA S KRYZHEM;Mn;0;NSM;;;;;N;;;;;
+1CF19;ZNAMENNY COMBINING MARK MALO POVYSHE S KRYZHEM;Mn;0;NSM;;;;;N;;;;;
+1CF1A;ZNAMENNY COMBINING MARK STRANNO MALO POVYSHE;Mn;0;NSM;;;;;N;;;;;
+1CF1B;ZNAMENNY COMBINING MARK POVYSHE S KRYZHEM;Mn;0;NSM;;;;;N;;;;;
+1CF1C;ZNAMENNY COMBINING MARK POVYSHE STRANNO;Mn;0;NSM;;;;;N;;;;;
+1CF1D;ZNAMENNY COMBINING MARK VYSOKO S KRYZHEM;Mn;0;NSM;;;;;N;;;;;
+1CF1E;ZNAMENNY COMBINING MARK MALO POVYSHE STRANNO;Mn;0;NSM;;;;;N;;;;;
+1CF1F;ZNAMENNY COMBINING MARK GORAZDO VYSOKO;Mn;0;NSM;;;;;N;;;;;
+1CF20;ZNAMENNY COMBINING MARK ZELO;Mn;0;NSM;;;;;N;;;;;
+1CF21;ZNAMENNY COMBINING MARK ON;Mn;0;NSM;;;;;N;;;;;
+1CF22;ZNAMENNY COMBINING MARK RAVNO;Mn;0;NSM;;;;;N;;;;;
+1CF23;ZNAMENNY COMBINING MARK TIKHAYA;Mn;0;NSM;;;;;N;;;;;
+1CF24;ZNAMENNY COMBINING MARK BORZAYA;Mn;0;NSM;;;;;N;;;;;
+1CF25;ZNAMENNY COMBINING MARK UDARKA;Mn;0;NSM;;;;;N;;;;;
+1CF26;ZNAMENNY COMBINING MARK PODVERTKA;Mn;0;NSM;;;;;N;;;;;
+1CF27;ZNAMENNY COMBINING MARK LOMKA;Mn;0;NSM;;;;;N;;;;;
+1CF28;ZNAMENNY COMBINING MARK KUPNAYA;Mn;0;NSM;;;;;N;;;;;
+1CF29;ZNAMENNY COMBINING MARK KACHKA;Mn;0;NSM;;;;;N;;;;;
+1CF2A;ZNAMENNY COMBINING MARK ZEVOK;Mn;0;NSM;;;;;N;;;;;
+1CF2B;ZNAMENNY COMBINING MARK SKOBA;Mn;0;NSM;;;;;N;;;;;
+1CF2C;ZNAMENNY COMBINING MARK RAZSEKA;Mn;0;NSM;;;;;N;;;;;
+1CF2D;ZNAMENNY COMBINING MARK KRYZH ON LEFT;Mn;0;NSM;;;;;N;;;;;
+1CF30;ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO;Mn;0;NSM;;;;;N;;;;;
+1CF31;ZNAMENNY COMBINING TONAL RANGE MARK SVETLO;Mn;0;NSM;;;;;N;;;;;
+1CF32;ZNAMENNY COMBINING TONAL RANGE MARK TRESVETLO;Mn;0;NSM;;;;;N;;;;;
+1CF33;ZNAMENNY COMBINING MARK ZADERZHKA;Mn;0;NSM;;;;;N;;;;;
+1CF34;ZNAMENNY COMBINING MARK DEMESTVENNY ZADERZHKA;Mn;0;NSM;;;;;N;;;;;
+1CF35;ZNAMENNY COMBINING MARK OTSECHKA;Mn;0;NSM;;;;;N;;;;;
+1CF36;ZNAMENNY COMBINING MARK PODCHASHIE;Mn;0;NSM;;;;;N;;;;;
+1CF37;ZNAMENNY COMBINING MARK PODCHASHIE WITH VERTICAL STROKE;Mn;0;NSM;;;;;N;;;;;
+1CF38;ZNAMENNY COMBINING MARK CHASHKA;Mn;0;NSM;;;;;N;;;;;
+1CF39;ZNAMENNY COMBINING MARK CHASHKA POLNAYA;Mn;0;NSM;;;;;N;;;;;
+1CF3A;ZNAMENNY COMBINING MARK OBLACHKO;Mn;0;NSM;;;;;N;;;;;
+1CF3B;ZNAMENNY COMBINING MARK SOROCHYA NOZHKA;Mn;0;NSM;;;;;N;;;;;
+1CF3C;ZNAMENNY COMBINING MARK TOCHKA;Mn;0;NSM;;;;;N;;;;;
+1CF3D;ZNAMENNY COMBINING MARK DVOETOCHIE;Mn;0;NSM;;;;;N;;;;;
+1CF3E;ZNAMENNY COMBINING ATTACHING VERTICAL OMET;Mn;0;NSM;;;;;N;;;;;
+1CF3F;ZNAMENNY COMBINING MARK CURVED OMET;Mn;0;NSM;;;;;N;;;;;
+1CF40;ZNAMENNY COMBINING MARK KRYZH;Mn;0;NSM;;;;;N;;;;;
+1CF41;ZNAMENNY COMBINING LOWER TONAL RANGE INDICATOR;Mn;0;NSM;;;;;N;;;;;
+1CF42;ZNAMENNY PRIZNAK MODIFIER LEVEL-2;Mn;0;NSM;;;;;N;;;;;
+1CF43;ZNAMENNY PRIZNAK MODIFIER LEVEL-3;Mn;0;NSM;;;;;N;;;;;
+1CF44;ZNAMENNY PRIZNAK MODIFIER DIRECTION FLIP;Mn;0;NSM;;;;;N;;;;;
+1CF45;ZNAMENNY PRIZNAK MODIFIER KRYZH;Mn;0;NSM;;;;;N;;;;;
+1CF46;ZNAMENNY PRIZNAK MODIFIER ROG;Mn;0;NSM;;;;;N;;;;;
+1CF50;ZNAMENNY NEUME KRYUK;So;0;L;;;;;N;;;;;
+1CF51;ZNAMENNY NEUME KRYUK TIKHY;So;0;L;;;;;N;;;;;
+1CF52;ZNAMENNY NEUME PARAKLIT;So;0;L;;;;;N;;;;;
+1CF53;ZNAMENNY NEUME DVA V CHELNU;So;0;L;;;;;N;;;;;
+1CF54;ZNAMENNY NEUME KLYUCH;So;0;L;;;;;N;;;;;
+1CF55;ZNAMENNY NEUME ZANOZHEK;So;0;L;;;;;N;;;;;
+1CF56;ZNAMENNY NEUME STOPITSA;So;0;L;;;;;N;;;;;
+1CF57;ZNAMENNY NEUME STOPITSA S OCHKOM;So;0;L;;;;;N;;;;;
+1CF58;ZNAMENNY NEUME PEREVODKA;So;0;L;;;;;N;;;;;
+1CF59;ZNAMENNY NEUME PEREVODKA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CF5A;ZNAMENNY NEUME STOPITSA WITH SOROCHYA NOZHKA;So;0;L;;;;;N;;;;;
+1CF5B;ZNAMENNY NEUME CHELYUSTKA;So;0;L;;;;;N;;;;;
+1CF5C;ZNAMENNY NEUME PALKA;So;0;L;;;;;N;;;;;
+1CF5D;ZNAMENNY NEUME ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CF5E;ZNAMENNY NEUME GOLUBCHIK BORZY;So;0;L;;;;;N;;;;;
+1CF5F;ZNAMENNY NEUME GOLUBCHIK TIKHY;So;0;L;;;;;N;;;;;
+1CF60;ZNAMENNY NEUME GOLUBCHIK MRACHNY;So;0;L;;;;;N;;;;;
+1CF61;ZNAMENNY NEUME GOLUBCHIK SVETLY;So;0;L;;;;;N;;;;;
+1CF62;ZNAMENNY NEUME GOLUBCHIK TRESVETLY;So;0;L;;;;;N;;;;;
+1CF63;ZNAMENNY NEUME VRAKHIYA PROSTAYA;So;0;L;;;;;N;;;;;
+1CF64;ZNAMENNY NEUME VRAKHIYA MRACHNAYA;So;0;L;;;;;N;;;;;
+1CF65;ZNAMENNY NEUME VRAKHIYA SVETLAYA;So;0;L;;;;;N;;;;;
+1CF66;ZNAMENNY NEUME VRAKHIYA TRESVETLAYA;So;0;L;;;;;N;;;;;
+1CF67;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA PROSTAYA;So;0;L;;;;;N;;;;;
+1CF68;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA MRACHNAYA;So;0;L;;;;;N;;;;;
+1CF69;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;;
+1CF6A;ZNAMENNY NEUME VRAKHIYA KLYUCHEVAYA TRESVETLAYA;So;0;L;;;;;N;;;;;
+1CF6B;ZNAMENNY NEUME DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CF6C;ZNAMENNY NEUME REVERSED CHELYUSTKA;So;0;L;;;;;N;;;;;
+1CF6D;ZNAMENNY NEUME DERBITSA;So;0;L;;;;;N;;;;;
+1CF6E;ZNAMENNY NEUME KHAMILO;So;0;L;;;;;N;;;;;
+1CF6F;ZNAMENNY NEUME CHASHKA;So;0;L;;;;;N;;;;;
+1CF70;ZNAMENNY NEUME PODCHASHIE;So;0;L;;;;;N;;;;;
+1CF71;ZNAMENNY NEUME SKAMEYTSA MRACHNAYA;So;0;L;;;;;N;;;;;
+1CF72;ZNAMENNY NEUME SKAMEYTSA SVETLAYA;So;0;L;;;;;N;;;;;
+1CF73;ZNAMENNY NEUME SKAMEYTSA TRESVETLAYA;So;0;L;;;;;N;;;;;
+1CF74;ZNAMENNY NEUME SKAMEYTSA TIKHAYA;So;0;L;;;;;N;;;;;
+1CF75;ZNAMENNY NEUME DEMESTVENNY KLYUCH;So;0;L;;;;;N;;;;;
+1CF76;ZNAMENNY NEUME SKAMEYTSA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;;
+1CF77;ZNAMENNY NEUME SKAMEYTSA KLYUCHENEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CF78;ZNAMENNY NEUME SKAMEYTSA KLYUCHEVAYA TIKHAYA;So;0;L;;;;;N;;;;;
+1CF79;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA PROSTAYA;So;0;L;;;;;N;;;;;
+1CF7A;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA SVETLAYA;So;0;L;;;;;N;;;;;
+1CF7B;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CF7C;ZNAMENNY NEUME SKAMEYTSA DVOECHELNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;;
+1CF7D;ZNAMENNY NEUME SLOZHITIE;So;0;L;;;;;N;;;;;
+1CF7E;ZNAMENNY NEUME SLOZHITIE S ZAPYATOY;So;0;L;;;;;N;;;;;
+1CF7F;ZNAMENNY NEUME SLOZHITIE ZAKRYTOE;So;0;L;;;;;N;;;;;
+1CF80;ZNAMENNY NEUME SLOZHITIE S KRYZHEM;So;0;L;;;;;N;;;;;
+1CF81;ZNAMENNY NEUME KRYZH;So;0;L;;;;;N;;;;;
+1CF82;ZNAMENNY NEUME ROG;So;0;L;;;;;N;;;;;
+1CF83;ZNAMENNY NEUME FITA;So;0;L;;;;;N;;;;;
+1CF84;ZNAMENNY NEUME KOBYLA;So;0;L;;;;;N;;;;;
+1CF85;ZNAMENNY NEUME ZMEYTSA;So;0;L;;;;;N;;;;;
+1CF86;ZNAMENNY NEUME STATYA;So;0;L;;;;;N;;;;;
+1CF87;ZNAMENNY NEUME STATYA S ZAPYATOY;So;0;L;;;;;N;;;;;
+1CF88;ZNAMENNY NEUME STATYA S KRYZHEM;So;0;L;;;;;N;;;;;
+1CF89;ZNAMENNY NEUME STATYA S ZAPYATOY I KRYZHEM;So;0;L;;;;;N;;;;;
+1CF8A;ZNAMENNY NEUME STATYA S KRYZHEM I ZAPYATOY;So;0;L;;;;;N;;;;;
+1CF8B;ZNAMENNY NEUME STATYA ZAKRYTAYA;So;0;L;;;;;N;;;;;
+1CF8C;ZNAMENNY NEUME STATYA ZAKRYTAYA S ZAPYATOY;So;0;L;;;;;N;;;;;
+1CF8D;ZNAMENNY NEUME STATYA S ROGOM;So;0;L;;;;;N;;;;;
+1CF8E;ZNAMENNY NEUME STATYA S DVUMYA ZAPYATYMI;So;0;L;;;;;N;;;;;
+1CF8F;ZNAMENNY NEUME STATYA S ZAPYATOY I PODCHASHIEM;So;0;L;;;;;N;;;;;
+1CF90;ZNAMENNY NEUME POLKULIZMY;So;0;L;;;;;N;;;;;
+1CF91;ZNAMENNY NEUME STATYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CF92;ZNAMENNY NEUME STRELA PROSTAYA;So;0;L;;;;;N;;;;;
+1CF93;ZNAMENNY NEUME STRELA MRACHNOTIKHAYA;So;0;L;;;;;N;;;;;
+1CF94;ZNAMENNY NEUME STRELA KRYZHEVAYA;So;0;L;;;;;N;;;;;
+1CF95;ZNAMENNY NEUME STRELA POLUPOVODNAYA;So;0;L;;;;;N;;;;;
+1CF96;ZNAMENNY NEUME STRELA POVODNAYA;So;0;L;;;;;N;;;;;
+1CF97;ZNAMENNY NEUME STRELA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CF98;ZNAMENNY NEUME STRELA KLYUCHEPOVODNAYA;So;0;L;;;;;N;;;;;
+1CF99;ZNAMENNY NEUME STRELA KLYUCHENEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CF9A;ZNAMENNY NEUME STRELA TIKHAYA PUTNAYA;So;0;L;;;;;N;;;;;
+1CF9B;ZNAMENNY NEUME STRELA DVOECHELNAYA;So;0;L;;;;;N;;;;;
+1CF9C;ZNAMENNY NEUME STRELA DVOECHELNOKRYZHEVAYA;So;0;L;;;;;N;;;;;
+1CF9D;ZNAMENNY NEUME STRELA DVOECHELNOPOVODNAYA;So;0;L;;;;;N;;;;;
+1CF9E;ZNAMENNY NEUME STRELA DVOECHELNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;;
+1CF9F;ZNAMENNY NEUME STRELA DVOECHELNOPOVODNAYA KLYUCHEVAYA;So;0;L;;;;;N;;;;;
+1CFA0;ZNAMENNY NEUME STRELA GROMNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CFA1;ZNAMENNY NEUME STRELA GROMOPOVODNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CFA2;ZNAMENNY NEUME STRELA GROMNAYA;So;0;L;;;;;N;;;;;
+1CFA3;ZNAMENNY NEUME STRELA GROMOPOVODNAYA;So;0;L;;;;;N;;;;;
+1CFA4;ZNAMENNY NEUME STRELA GROMOPOVODNAYA WITH DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CFA5;ZNAMENNY NEUME STRELA GROMOKRYZHEVAYA;So;0;L;;;;;N;;;;;
+1CFA6;ZNAMENNY NEUME STRELA GROMOKRYZHEVAYA POVODNAYA;So;0;L;;;;;N;;;;;
+1CFA7;ZNAMENNY NEUME MECHIK;So;0;L;;;;;N;;;;;
+1CFA8;ZNAMENNY NEUME MECHIK POVODNY;So;0;L;;;;;N;;;;;
+1CFA9;ZNAMENNY NEUME MECHIK KLYUCHEVOY;So;0;L;;;;;N;;;;;
+1CFAA;ZNAMENNY NEUME MECHIK KLYUCHEPOVODNY;So;0;L;;;;;N;;;;;
+1CFAB;ZNAMENNY NEUME MECHIK KLYUCHENEPOSTOYANNY;So;0;L;;;;;N;;;;;
+1CFAC;ZNAMENNY NEUME STRELA TRYASOGLASNAYA;So;0;L;;;;;N;;;;;
+1CFAD;ZNAMENNY NEUME STRELA TRYASOPOVODNAYA;So;0;L;;;;;N;;;;;
+1CFAE;ZNAMENNY NEUME STRELA TRYASOSTRELNAYA;So;0;L;;;;;N;;;;;
+1CFAF;ZNAMENNY NEUME OSOKA;So;0;L;;;;;N;;;;;
+1CFB0;ZNAMENNY NEUME OSOKA SVETLAYA;So;0;L;;;;;N;;;;;
+1CFB1;ZNAMENNY NEUME OSOKA TRESVETLAYA;So;0;L;;;;;N;;;;;
+1CFB2;ZNAMENNY NEUME OSOKA KRYUKOVAYA SVETLAYA;So;0;L;;;;;N;;;;;
+1CFB3;ZNAMENNY NEUME OSOKA KLYUCHEVAYA SVETLAYA;So;0;L;;;;;N;;;;;
+1CFB4;ZNAMENNY NEUME OSOKA KLYUCHEVAYA NEPOSTOYANNAYA;So;0;L;;;;;N;;;;;
+1CFB5;ZNAMENNY NEUME STRELA KRYUKOVAYA;So;0;L;;;;;N;;;;;
+1CFB6;ZNAMENNY NEUME STRELA KRYUKOVAYA POVODNAYA;So;0;L;;;;;N;;;;;
+1CFB7;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CFB8;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA WITH SINGLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CFB9;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMNAYA;So;0;L;;;;;N;;;;;
+1CFBA;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA;So;0;L;;;;;N;;;;;
+1CFBB;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOPOVODNAYA WITH DOUBLE ZAPYATAYA;So;0;L;;;;;N;;;;;
+1CFBC;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOKRYZHEVAYA;So;0;L;;;;;N;;;;;
+1CFBD;ZNAMENNY NEUME STRELA KRYUKOVAYA GROMOKRYZHEVAYA POVODNAYA;So;0;L;;;;;N;;;;;
+1CFBE;ZNAMENNY NEUME STRELA KRYUKOVAYA TRYASKA;So;0;L;;;;;N;;;;;
+1CFBF;ZNAMENNY NEUME KUFISMA;So;0;L;;;;;N;;;;;
+1CFC0;ZNAMENNY NEUME OBLAKO;So;0;L;;;;;N;;;;;
+1CFC1;ZNAMENNY NEUME DUDA;So;0;L;;;;;N;;;;;
+1CFC2;ZNAMENNY NEUME NEMKA;So;0;L;;;;;N;;;;;
+1CFC3;ZNAMENNY NEUME PAUK;So;0;L;;;;;N;;;;;
1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;;
1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;;
1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;;
@@ -27801,6 +28501,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1D1E6;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN;So;0;L;;;;;N;;;;;
1D1E7;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP;So;0;L;;;;;N;;;;;
1D1E8;MUSICAL SYMBOL KIEVAN FLAT SIGN;So;0;L;;;;;N;;;;;
+1D1E9;MUSICAL SYMBOL SORI;So;0;ON;;;;;N;;;;;
+1D1EA;MUSICAL SYMBOL KORON;So;0;ON;;;;;N;;;;;
1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;;
1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;;
1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;;
@@ -29671,6 +30373,37 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;;
1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;;
1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;;
+1DF00;LATIN SMALL LETTER FENG DIGRAPH WITH TRILL;Ll;0;L;;;;;N;;;;;
+1DF01;LATIN SMALL LETTER REVERSED SCRIPT G;Ll;0;L;;;;;N;;;;;
+1DF02;LATIN LETTER SMALL CAPITAL TURNED G;Ll;0;L;;;;;N;;;;;
+1DF03;LATIN SMALL LETTER REVERSED K;Ll;0;L;;;;;N;;;;;
+1DF04;LATIN LETTER SMALL CAPITAL L WITH BELT;Ll;0;L;;;;;N;;;;;
+1DF05;LATIN SMALL LETTER LEZH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF06;LATIN SMALL LETTER TURNED Y WITH BELT;Ll;0;L;;;;;N;;;;;
+1DF07;LATIN SMALL LETTER REVERSED ENG;Ll;0;L;;;;;N;;;;;
+1DF08;LATIN SMALL LETTER TURNED R WITH LONG LEG AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF09;LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF0A;LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK;Lo;0;L;;;;;N;;;;;
+1DF0B;LATIN SMALL LETTER ESH WITH DOUBLE BAR;Ll;0;L;;;;;N;;;;;
+1DF0C;LATIN SMALL LETTER ESH WITH DOUBLE BAR AND CURL;Ll;0;L;;;;;N;;;;;
+1DF0D;LATIN SMALL LETTER TURNED T WITH CURL;Ll;0;L;;;;;N;;;;;
+1DF0E;LATIN LETTER INVERTED GLOTTAL STOP WITH CURL;Ll;0;L;;;;;N;;;;;
+1DF0F;LATIN LETTER STRETCHED C WITH CURL;Ll;0;L;;;;;N;;;;;
+1DF10;LATIN LETTER SMALL CAPITAL TURNED K;Ll;0;L;;;;;N;;;;;
+1DF11;LATIN SMALL LETTER L WITH FISHHOOK;Ll;0;L;;;;;N;;;;;
+1DF12;LATIN SMALL LETTER DEZH DIGRAPH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF13;LATIN SMALL LETTER L WITH BELT AND PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF14;LATIN SMALL LETTER ENG WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF15;LATIN SMALL LETTER TURNED R WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF16;LATIN SMALL LETTER R WITH FISHHOOK AND PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF17;LATIN SMALL LETTER TESH DIGRAPH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF18;LATIN SMALL LETTER EZH WITH PALATAL HOOK;Ll;0;L;;;;;N;;;;;
+1DF19;LATIN SMALL LETTER DEZH DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF1A;LATIN SMALL LETTER I WITH STROKE AND RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF1B;LATIN SMALL LETTER O WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF1C;LATIN SMALL LETTER TESH DIGRAPH WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF1D;LATIN SMALL LETTER C WITH RETROFLEX HOOK;Ll;0;L;;;;;N;;;;;
+1DF1E;LATIN SMALL LETTER S WITH CURL;Ll;0;L;;;;;N;;;;;
1E000;COMBINING GLAGOLITIC LETTER AZU;Mn;230;NSM;;;;;N;;;;;
1E001;COMBINING GLAGOLITIC LETTER BUKY;Mn;230;NSM;;;;;N;;;;;
1E002;COMBINING GLAGOLITIC LETTER VEDE;Mn;230;NSM;;;;;N;;;;;
@@ -29780,6 +30513,37 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1E149;NYIAKENG PUACHUE HMONG DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
1E14E;NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ;Lo;0;L;;;;;N;;;;;
1E14F;NYIAKENG PUACHUE HMONG CIRCLED CA;So;0;L;;;;;N;;;;;
+1E290;TOTO LETTER PA;Lo;0;L;;;;;N;;;;;
+1E291;TOTO LETTER BA;Lo;0;L;;;;;N;;;;;
+1E292;TOTO LETTER TA;Lo;0;L;;;;;N;;;;;
+1E293;TOTO LETTER DA;Lo;0;L;;;;;N;;;;;
+1E294;TOTO LETTER KA;Lo;0;L;;;;;N;;;;;
+1E295;TOTO LETTER GA;Lo;0;L;;;;;N;;;;;
+1E296;TOTO LETTER MA;Lo;0;L;;;;;N;;;;;
+1E297;TOTO LETTER NA;Lo;0;L;;;;;N;;;;;
+1E298;TOTO LETTER NGA;Lo;0;L;;;;;N;;;;;
+1E299;TOTO LETTER SA;Lo;0;L;;;;;N;;;;;
+1E29A;TOTO LETTER CHA;Lo;0;L;;;;;N;;;;;
+1E29B;TOTO LETTER YA;Lo;0;L;;;;;N;;;;;
+1E29C;TOTO LETTER WA;Lo;0;L;;;;;N;;;;;
+1E29D;TOTO LETTER JA;Lo;0;L;;;;;N;;;;;
+1E29E;TOTO LETTER HA;Lo;0;L;;;;;N;;;;;
+1E29F;TOTO LETTER RA;Lo;0;L;;;;;N;;;;;
+1E2A0;TOTO LETTER LA;Lo;0;L;;;;;N;;;;;
+1E2A1;TOTO LETTER I;Lo;0;L;;;;;N;;;;;
+1E2A2;TOTO LETTER BREATHY I;Lo;0;L;;;;;N;;;;;
+1E2A3;TOTO LETTER IU;Lo;0;L;;;;;N;;;;;
+1E2A4;TOTO LETTER BREATHY IU;Lo;0;L;;;;;N;;;;;
+1E2A5;TOTO LETTER U;Lo;0;L;;;;;N;;;;;
+1E2A6;TOTO LETTER E;Lo;0;L;;;;;N;;;;;
+1E2A7;TOTO LETTER BREATHY E;Lo;0;L;;;;;N;;;;;
+1E2A8;TOTO LETTER EO;Lo;0;L;;;;;N;;;;;
+1E2A9;TOTO LETTER BREATHY EO;Lo;0;L;;;;;N;;;;;
+1E2AA;TOTO LETTER O;Lo;0;L;;;;;N;;;;;
+1E2AB;TOTO LETTER AE;Lo;0;L;;;;;N;;;;;
+1E2AC;TOTO LETTER BREATHY AE;Lo;0;L;;;;;N;;;;;
+1E2AD;TOTO LETTER A;Lo;0;L;;;;;N;;;;;
+1E2AE;TOTO SIGN RISING TONE;Mn;230;NSM;;;;;N;;;;;
1E2C0;WANCHO LETTER AA;Lo;0;L;;;;;N;;;;;
1E2C1;WANCHO LETTER A;Lo;0;L;;;;;N;;;;;
1E2C2;WANCHO LETTER BA;Lo;0;L;;;;;N;;;;;
@@ -29839,6 +30603,34 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1E2F8;WANCHO DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
1E2F9;WANCHO DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
1E2FF;WANCHO NGUN SIGN;Sc;0;ET;;;;;N;;;;;
+1E7E0;ETHIOPIC SYLLABLE HHYA;Lo;0;L;;;;;N;;;;;
+1E7E1;ETHIOPIC SYLLABLE HHYU;Lo;0;L;;;;;N;;;;;
+1E7E2;ETHIOPIC SYLLABLE HHYI;Lo;0;L;;;;;N;;;;;
+1E7E3;ETHIOPIC SYLLABLE HHYAA;Lo;0;L;;;;;N;;;;;
+1E7E4;ETHIOPIC SYLLABLE HHYEE;Lo;0;L;;;;;N;;;;;
+1E7E5;ETHIOPIC SYLLABLE HHYE;Lo;0;L;;;;;N;;;;;
+1E7E6;ETHIOPIC SYLLABLE HHYO;Lo;0;L;;;;;N;;;;;
+1E7E8;ETHIOPIC SYLLABLE GURAGE HHWA;Lo;0;L;;;;;N;;;;;
+1E7E9;ETHIOPIC SYLLABLE HHWI;Lo;0;L;;;;;N;;;;;
+1E7EA;ETHIOPIC SYLLABLE HHWEE;Lo;0;L;;;;;N;;;;;
+1E7EB;ETHIOPIC SYLLABLE HHWE;Lo;0;L;;;;;N;;;;;
+1E7ED;ETHIOPIC SYLLABLE GURAGE MWI;Lo;0;L;;;;;N;;;;;
+1E7EE;ETHIOPIC SYLLABLE GURAGE MWEE;Lo;0;L;;;;;N;;;;;
+1E7F0;ETHIOPIC SYLLABLE GURAGE QWI;Lo;0;L;;;;;N;;;;;
+1E7F1;ETHIOPIC SYLLABLE GURAGE QWEE;Lo;0;L;;;;;N;;;;;
+1E7F2;ETHIOPIC SYLLABLE GURAGE QWE;Lo;0;L;;;;;N;;;;;
+1E7F3;ETHIOPIC SYLLABLE GURAGE BWI;Lo;0;L;;;;;N;;;;;
+1E7F4;ETHIOPIC SYLLABLE GURAGE BWEE;Lo;0;L;;;;;N;;;;;
+1E7F5;ETHIOPIC SYLLABLE GURAGE KWI;Lo;0;L;;;;;N;;;;;
+1E7F6;ETHIOPIC SYLLABLE GURAGE KWEE;Lo;0;L;;;;;N;;;;;
+1E7F7;ETHIOPIC SYLLABLE GURAGE KWE;Lo;0;L;;;;;N;;;;;
+1E7F8;ETHIOPIC SYLLABLE GURAGE GWI;Lo;0;L;;;;;N;;;;;
+1E7F9;ETHIOPIC SYLLABLE GURAGE GWEE;Lo;0;L;;;;;N;;;;;
+1E7FA;ETHIOPIC SYLLABLE GURAGE GWE;Lo;0;L;;;;;N;;;;;
+1E7FB;ETHIOPIC SYLLABLE GURAGE FWI;Lo;0;L;;;;;N;;;;;
+1E7FC;ETHIOPIC SYLLABLE GURAGE FWEE;Lo;0;L;;;;;N;;;;;
+1E7FD;ETHIOPIC SYLLABLE GURAGE PWI;Lo;0;L;;;;;N;;;;;
+1E7FE;ETHIOPIC SYLLABLE GURAGE PWEE;Lo;0;L;;;;;N;;;;;
1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;;
1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;;
1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;;
@@ -31886,6 +32678,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F6D5;HINDU TEMPLE;So;0;ON;;;;;N;;;;;
1F6D6;HUT;So;0;ON;;;;;N;;;;;
1F6D7;ELEVATOR;So;0;ON;;;;;N;;;;;
+1F6DD;PLAYGROUND SLIDE;So;0;ON;;;;;N;;;;;
+1F6DE;WHEEL;So;0;ON;;;;;N;;;;;
+1F6DF;RING BUOY;So;0;ON;;;;;N;;;;;
1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;;
1F6E1;SHIELD;So;0;ON;;;;;N;;;;;
1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;;
@@ -32129,6 +32924,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F7E9;LARGE GREEN SQUARE;So;0;ON;;;;;N;;;;;
1F7EA;LARGE PURPLE SQUARE;So;0;ON;;;;;N;;;;;
1F7EB;LARGE BROWN SQUARE;So;0;ON;;;;;N;;;;;
+1F7F0;HEAVY EQUALS SIGN;So;0;ON;;;;;N;;;;;
1F800;LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;;
1F801;UPWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;;
1F802;RIGHTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD;So;0;ON;;;;;N;;;;;
@@ -32400,6 +33196,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F976;FREEZING FACE;So;0;ON;;;;;N;;;;;
1F977;NINJA;So;0;ON;;;;;N;;;;;
1F978;DISGUISED FACE;So;0;ON;;;;;N;;;;;
+1F979;FACE HOLDING BACK TEARS;So;0;ON;;;;;N;;;;;
1F97A;FACE WITH PLEADING EYES;So;0;ON;;;;;N;;;;;
1F97B;SARI;So;0;ON;;;;;N;;;;;
1F97C;LAB COAT;So;0;ON;;;;;N;;;;;
@@ -32482,6 +33279,7 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1F9C9;MATE DRINK;So;0;ON;;;;;N;;;;;
1F9CA;ICE CUBE;So;0;ON;;;;;N;;;;;
1F9CB;BUBBLE TEA;So;0;ON;;;;;N;;;;;
+1F9CC;TROLL;So;0;ON;;;;;N;;;;;
1F9CD;STANDING PERSON;So;0;ON;;;;;N;;;;;
1F9CE;KNEELING PERSON;So;0;ON;;;;;N;;;;;
1F9CF;DEAF PERSON;So;0;ON;;;;;N;;;;;
@@ -32639,6 +33437,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1FA78;DROP OF BLOOD;So;0;ON;;;;;N;;;;;
1FA79;ADHESIVE BANDAGE;So;0;ON;;;;;N;;;;;
1FA7A;STETHOSCOPE;So;0;ON;;;;;N;;;;;
+1FA7B;X-RAY;So;0;ON;;;;;N;;;;;
+1FA7C;CRUTCH;So;0;ON;;;;;N;;;;;
1FA80;YO-YO;So;0;ON;;;;;N;;;;;
1FA81;KITE;So;0;ON;;;;;N;;;;;
1FA82;PARACHUTE;So;0;ON;;;;;N;;;;;
@@ -32671,6 +33471,10 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1FAA6;HEADSTONE;So;0;ON;;;;;N;;;;;
1FAA7;PLACARD;So;0;ON;;;;;N;;;;;
1FAA8;ROCK;So;0;ON;;;;;N;;;;;
+1FAA9;MIRROR BALL;So;0;ON;;;;;N;;;;;
+1FAAA;IDENTIFICATION CARD;So;0;ON;;;;;N;;;;;
+1FAAB;LOW BATTERY;So;0;ON;;;;;N;;;;;
+1FAAC;HAMSA;So;0;ON;;;;;N;;;;;
1FAB0;FLY;So;0;ON;;;;;N;;;;;
1FAB1;WORM;So;0;ON;;;;;N;;;;;
1FAB2;BEETLE;So;0;ON;;;;;N;;;;;
@@ -32678,9 +33482,16 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1FAB4;POTTED PLANT;So;0;ON;;;;;N;;;;;
1FAB5;WOOD;So;0;ON;;;;;N;;;;;
1FAB6;FEATHER;So;0;ON;;;;;N;;;;;
+1FAB7;LOTUS;So;0;ON;;;;;N;;;;;
+1FAB8;CORAL;So;0;ON;;;;;N;;;;;
+1FAB9;EMPTY NEST;So;0;ON;;;;;N;;;;;
+1FABA;NEST WITH EGGS;So;0;ON;;;;;N;;;;;
1FAC0;ANATOMICAL HEART;So;0;ON;;;;;N;;;;;
1FAC1;LUNGS;So;0;ON;;;;;N;;;;;
1FAC2;PEOPLE HUGGING;So;0;ON;;;;;N;;;;;
+1FAC3;PREGNANT MAN;So;0;ON;;;;;N;;;;;
+1FAC4;PREGNANT PERSON;So;0;ON;;;;;N;;;;;
+1FAC5;PERSON WITH CROWN;So;0;ON;;;;;N;;;;;
1FAD0;BLUEBERRIES;So;0;ON;;;;;N;;;;;
1FAD1;BELL PEPPER;So;0;ON;;;;;N;;;;;
1FAD2;OLIVE;So;0;ON;;;;;N;;;;;
@@ -32688,6 +33499,24 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1FAD4;TAMALE;So;0;ON;;;;;N;;;;;
1FAD5;FONDUE;So;0;ON;;;;;N;;;;;
1FAD6;TEAPOT;So;0;ON;;;;;N;;;;;
+1FAD7;POURING LIQUID;So;0;ON;;;;;N;;;;;
+1FAD8;BEANS;So;0;ON;;;;;N;;;;;
+1FAD9;JAR;So;0;ON;;;;;N;;;;;
+1FAE0;MELTING FACE;So;0;ON;;;;;N;;;;;
+1FAE1;SALUTING FACE;So;0;ON;;;;;N;;;;;
+1FAE2;FACE WITH OPEN EYES AND HAND OVER MOUTH;So;0;ON;;;;;N;;;;;
+1FAE3;FACE WITH PEEKING EYE;So;0;ON;;;;;N;;;;;
+1FAE4;FACE WITH DIAGONAL MOUTH;So;0;ON;;;;;N;;;;;
+1FAE5;DOTTED LINE FACE;So;0;ON;;;;;N;;;;;
+1FAE6;BITING LIP;So;0;ON;;;;;N;;;;;
+1FAE7;BUBBLES;So;0;ON;;;;;N;;;;;
+1FAF0;HAND WITH INDEX FINGER AND THUMB CROSSED;So;0;ON;;;;;N;;;;;
+1FAF1;RIGHTWARDS HAND;So;0;ON;;;;;N;;;;;
+1FAF2;LEFTWARDS HAND;So;0;ON;;;;;N;;;;;
+1FAF3;PALM DOWN HAND;So;0;ON;;;;;N;;;;;
+1FAF4;PALM UP HAND;So;0;ON;;;;;N;;;;;
+1FAF5;INDEX POINTING AT THE VIEWER;So;0;ON;;;;;N;;;;;
+1FAF6;HEART HANDS;So;0;ON;;;;;N;;;;;
1FB00;BLOCK SEXTANT-1;So;0;ON;;;;;N;;;;;
1FB01;BLOCK SEXTANT-2;So;0;ON;;;;;N;;;;;
1FB02;BLOCK SEXTANT-12;So;0;ON;;;;;N;;;;;
@@ -32901,9 +33730,9 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
1FBF8;SEGMENTED DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
1FBF9;SEGMENTED DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;;
-2A6DD;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
+2A6DF;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;;
-2B734;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
+2B738;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
2B740;<CJK Ideograph Extension D, First>;Lo;0;L;;;;;N;;;;;
2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;;
2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;;
diff --git a/lib/stdlib/uc_spec/emoji-data.txt b/lib/stdlib/uc_spec/emoji-data.txt
index 5d7dc1b156..7806c7ab53 100644
--- a/lib/stdlib/uc_spec/emoji-data.txt
+++ b/lib/stdlib/uc_spec/emoji-data.txt
@@ -1,11 +1,11 @@
-# emoji-data.txt
-# Date: 2020-01-28, 20:52:38 GMT
-# © 2020 Unicode®, Inc.
+# emoji-data-14.0.0.txt
+# Date: 2021-08-26, 17:22:22 GMT
+# © 2021 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Emoji Data for UTS #51
-# Version: 13.0
+# Used with Emoji Version 14.0 and subsequent minor revisions (if any)
#
# For documentation and usage, see http://www.unicode.org/reports/tr51
#
@@ -22,7 +22,7 @@
# All omitted code points have Emoji=No
# @missing: 0000..10FFFF ; Emoji ; No
-0023 ; Emoji # E0.0 [1] (#ï¸) number sign
+0023 ; Emoji # E0.0 [1] (#ï¸) hash sign
002A ; Emoji # E0.0 [1] (*ï¸) asterisk
0030..0039 ; Emoji # E0.0 [10] (0ï¸..9ï¸) digit zero..digit nine
00A9 ; Emoji # E0.6 [1] (©ï¸) copyright
@@ -119,8 +119,8 @@
2747 ; Emoji # E0.6 [1] (â‡ï¸) sparkle
274C ; Emoji # E0.6 [1] (âŒ) cross mark
274E ; Emoji # E0.6 [1] (âŽ) cross mark button
-2753..2755 ; Emoji # E0.6 [3] (â“..â•) question mark..white exclamation mark
-2757 ; Emoji # E0.6 [1] (â—) exclamation mark
+2753..2755 ; Emoji # E0.6 [3] (â“..â•) red question mark..white exclamation mark
+2757 ; Emoji # E0.6 [1] (â—) red exclamation mark
2763 ; Emoji # E1.0 [1] (â£ï¸) heart exclamation
2764 ; Emoji # E0.6 [1] (â¤ï¸) red heart
2795..2797 ; Emoji # E0.6 [3] (âž•..âž—) plus..divide
@@ -239,7 +239,7 @@
1F509 ; Emoji # E1.0 [1] (🔉) speaker medium volume
1F50A..1F514 ; Emoji # E0.6 [11] (🔊..🔔) speaker high volume..bell
1F515 ; Emoji # E1.0 [1] (🔕) bell with slash
-1F516..1F52B ; Emoji # E0.6 [22] (🔖..🔫) bookmark..pistol
+1F516..1F52B ; Emoji # E0.6 [22] (🔖..🔫) bookmark..water pistol
1F52C..1F52D ; Emoji # E1.0 [2] (🔬..🔭) microscope..telescope
1F52E..1F53D ; Emoji # E0.6 [16] (🔮..🔽) crystal ball..downwards button
1F549..1F54A ; Emoji # E0.7 [2] (🕉ï¸..🕊ï¸) om..dove
@@ -294,7 +294,7 @@
1F62E..1F62F ; Emoji # E1.0 [2] (😮..😯) face with open mouth..hushed face
1F630..1F633 ; Emoji # E0.6 [4] (😰..😳) anxious face with sweat..flushed face
1F634 ; Emoji # E1.0 [1] (😴) sleeping face
-1F635 ; Emoji # E0.6 [1] (😵) dizzy face
+1F635 ; Emoji # E0.6 [1] (😵) face with crossed-out eyes
1F636 ; Emoji # E1.0 [1] (😶) face without mouth
1F637..1F640 ; Emoji # E0.6 [10] (😷..🙀) face with medical mask..weary cat
1F641..1F644 ; Emoji # E1.0 [4] (ðŸ™..🙄) slightly frowning face..face with rolling eyes
@@ -341,6 +341,7 @@
1F6D1..1F6D2 ; Emoji # E3.0 [2] (🛑..🛒) stop sign..shopping cart
1F6D5 ; Emoji # E12.0 [1] (🛕) hindu temple
1F6D6..1F6D7 ; Emoji # E13.0 [2] (🛖..🛗) hut..elevator
+1F6DD..1F6DF ; Emoji # E14.0 [3] (ðŸ›..🛟) playground slide..ring buoy
1F6E0..1F6E5 ; Emoji # E0.7 [6] (🛠ï¸..🛥ï¸) hammer and wrench..motor boat
1F6E9 ; Emoji # E0.7 [1] (🛩ï¸) small airplane
1F6EB..1F6EC ; Emoji # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival
@@ -352,6 +353,7 @@
1F6FA ; Emoji # E12.0 [1] (🛺) auto rickshaw
1F6FB..1F6FC ; Emoji # E13.0 [2] (🛻..🛼) pickup truck..roller skate
1F7E0..1F7EB ; Emoji # E12.0 [12] (🟠..🟫) orange circle..brown square
+1F7F0 ; Emoji # E14.0 [1] (🟰) heavy equals sign
1F90C ; Emoji # E13.0 [1] (🤌) pinched fingers
1F90D..1F90F ; Emoji # E12.0 [3] (ðŸ¤..ðŸ¤) white heart..pinching hand
1F910..1F918 ; Emoji # E1.0 [9] (ðŸ¤..🤘) zipper-mouth face..sign of the horns
@@ -375,6 +377,7 @@
1F972 ; Emoji # E13.0 [1] (🥲) smiling face with tear
1F973..1F976 ; Emoji # E11.0 [4] (🥳..🥶) partying face..cold face
1F977..1F978 ; Emoji # E13.0 [2] (🥷..🥸) ninja..disguised face
+1F979 ; Emoji # E14.0 [1] (🥹) face holding back tears
1F97A ; Emoji # E11.0 [1] (🥺) pleading face
1F97B ; Emoji # E12.0 [1] (🥻) sari
1F97C..1F97F ; Emoji # E11.0 [4] (🥼..🥿) lab coat..flat shoe
@@ -392,21 +395,29 @@
1F9C1..1F9C2 ; Emoji # E11.0 [2] (ðŸ§..🧂) cupcake..salt
1F9C3..1F9CA ; Emoji # E12.0 [8] (🧃..🧊) beverage box..ice
1F9CB ; Emoji # E13.0 [1] (🧋) bubble tea
+1F9CC ; Emoji # E14.0 [1] (🧌) troll
1F9CD..1F9CF ; Emoji # E12.0 [3] (ðŸ§..ðŸ§) person standing..deaf person
1F9D0..1F9E6 ; Emoji # E5.0 [23] (ðŸ§..🧦) face with monocle..socks
1F9E7..1F9FF ; Emoji # E11.0 [25] (🧧..🧿) red envelope..nazar amulet
1FA70..1FA73 ; Emoji # E12.0 [4] (🩰..🩳) ballet shoes..shorts
1FA74 ; Emoji # E13.0 [1] (🩴) thong sandal
1FA78..1FA7A ; Emoji # E12.0 [3] (🩸..🩺) drop of blood..stethoscope
+1FA7B..1FA7C ; Emoji # E14.0 [2] (🩻..🩼) x-ray..crutch
1FA80..1FA82 ; Emoji # E12.0 [3] (🪀..🪂) yo-yo..parachute
1FA83..1FA86 ; Emoji # E13.0 [4] (🪃..🪆) boomerang..nesting dolls
1FA90..1FA95 ; Emoji # E12.0 [6] (ðŸª..🪕) ringed planet..banjo
1FA96..1FAA8 ; Emoji # E13.0 [19] (🪖..🪨) military helmet..rock
+1FAA9..1FAAC ; Emoji # E14.0 [4] (🪩..🪬) mirror ball..hamsa
1FAB0..1FAB6 ; Emoji # E13.0 [7] (🪰..🪶) fly..feather
+1FAB7..1FABA ; Emoji # E14.0 [4] (🪷..🪺) lotus..nest with eggs
1FAC0..1FAC2 ; Emoji # E13.0 [3] (🫀..🫂) anatomical heart..people hugging
+1FAC3..1FAC5 ; Emoji # E14.0 [3] (🫃..🫅) pregnant man..person with crown
1FAD0..1FAD6 ; Emoji # E13.0 [7] (ðŸ«..🫖) blueberries..teapot
+1FAD7..1FAD9 ; Emoji # E14.0 [3] (🫗..🫙) pouring liquid..jar
+1FAE0..1FAE7 ; Emoji # E14.0 [8] (🫠..🫧) melting face..bubbles
+1FAF0..1FAF6 ; Emoji # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
-# Total elements: 1367
+# Total elements: 1404
# ================================================
@@ -438,8 +449,8 @@
2728 ; Emoji_Presentation # E0.6 [1] (✨) sparkles
274C ; Emoji_Presentation # E0.6 [1] (âŒ) cross mark
274E ; Emoji_Presentation # E0.6 [1] (âŽ) cross mark button
-2753..2755 ; Emoji_Presentation # E0.6 [3] (â“..â•) question mark..white exclamation mark
-2757 ; Emoji_Presentation # E0.6 [1] (â—) exclamation mark
+2753..2755 ; Emoji_Presentation # E0.6 [3] (â“..â•) red question mark..white exclamation mark
+2757 ; Emoji_Presentation # E0.6 [1] (â—) red exclamation mark
2795..2797 ; Emoji_Presentation # E0.6 [3] (âž•..âž—) plus..divide
27B0 ; Emoji_Presentation # E0.6 [1] (âž°) curly loop
27BF ; Emoji_Presentation # E1.0 [1] (âž¿) double curly loop
@@ -533,7 +544,7 @@
1F509 ; Emoji_Presentation # E1.0 [1] (🔉) speaker medium volume
1F50A..1F514 ; Emoji_Presentation # E0.6 [11] (🔊..🔔) speaker high volume..bell
1F515 ; Emoji_Presentation # E1.0 [1] (🔕) bell with slash
-1F516..1F52B ; Emoji_Presentation # E0.6 [22] (🔖..🔫) bookmark..pistol
+1F516..1F52B ; Emoji_Presentation # E0.6 [22] (🔖..🔫) bookmark..water pistol
1F52C..1F52D ; Emoji_Presentation # E1.0 [2] (🔬..🔭) microscope..telescope
1F52E..1F53D ; Emoji_Presentation # E0.6 [16] (🔮..🔽) crystal ball..downwards button
1F54B..1F54E ; Emoji_Presentation # E1.0 [4] (🕋..🕎) kaaba..menorah
@@ -569,7 +580,7 @@
1F62E..1F62F ; Emoji_Presentation # E1.0 [2] (😮..😯) face with open mouth..hushed face
1F630..1F633 ; Emoji_Presentation # E0.6 [4] (😰..😳) anxious face with sweat..flushed face
1F634 ; Emoji_Presentation # E1.0 [1] (😴) sleeping face
-1F635 ; Emoji_Presentation # E0.6 [1] (😵) dizzy face
+1F635 ; Emoji_Presentation # E0.6 [1] (😵) face with crossed-out eyes
1F636 ; Emoji_Presentation # E1.0 [1] (😶) face without mouth
1F637..1F640 ; Emoji_Presentation # E0.6 [10] (😷..🙀) face with medical mask..weary cat
1F641..1F644 ; Emoji_Presentation # E1.0 [4] (ðŸ™..🙄) slightly frowning face..face with rolling eyes
@@ -614,6 +625,7 @@
1F6D1..1F6D2 ; Emoji_Presentation # E3.0 [2] (🛑..🛒) stop sign..shopping cart
1F6D5 ; Emoji_Presentation # E12.0 [1] (🛕) hindu temple
1F6D6..1F6D7 ; Emoji_Presentation # E13.0 [2] (🛖..🛗) hut..elevator
+1F6DD..1F6DF ; Emoji_Presentation # E14.0 [3] (ðŸ›..🛟) playground slide..ring buoy
1F6EB..1F6EC ; Emoji_Presentation # E1.0 [2] (🛫..🛬) airplane departure..airplane arrival
1F6F4..1F6F6 ; Emoji_Presentation # E3.0 [3] (🛴..🛶) kick scooter..canoe
1F6F7..1F6F8 ; Emoji_Presentation # E5.0 [2] (🛷..🛸) sled..flying saucer
@@ -621,6 +633,7 @@
1F6FA ; Emoji_Presentation # E12.0 [1] (🛺) auto rickshaw
1F6FB..1F6FC ; Emoji_Presentation # E13.0 [2] (🛻..🛼) pickup truck..roller skate
1F7E0..1F7EB ; Emoji_Presentation # E12.0 [12] (🟠..🟫) orange circle..brown square
+1F7F0 ; Emoji_Presentation # E14.0 [1] (🟰) heavy equals sign
1F90C ; Emoji_Presentation # E13.0 [1] (🤌) pinched fingers
1F90D..1F90F ; Emoji_Presentation # E12.0 [3] (ðŸ¤..ðŸ¤) white heart..pinching hand
1F910..1F918 ; Emoji_Presentation # E1.0 [9] (ðŸ¤..🤘) zipper-mouth face..sign of the horns
@@ -644,6 +657,7 @@
1F972 ; Emoji_Presentation # E13.0 [1] (🥲) smiling face with tear
1F973..1F976 ; Emoji_Presentation # E11.0 [4] (🥳..🥶) partying face..cold face
1F977..1F978 ; Emoji_Presentation # E13.0 [2] (🥷..🥸) ninja..disguised face
+1F979 ; Emoji_Presentation # E14.0 [1] (🥹) face holding back tears
1F97A ; Emoji_Presentation # E11.0 [1] (🥺) pleading face
1F97B ; Emoji_Presentation # E12.0 [1] (🥻) sari
1F97C..1F97F ; Emoji_Presentation # E11.0 [4] (🥼..🥿) lab coat..flat shoe
@@ -661,21 +675,29 @@
1F9C1..1F9C2 ; Emoji_Presentation # E11.0 [2] (ðŸ§..🧂) cupcake..salt
1F9C3..1F9CA ; Emoji_Presentation # E12.0 [8] (🧃..🧊) beverage box..ice
1F9CB ; Emoji_Presentation # E13.0 [1] (🧋) bubble tea
+1F9CC ; Emoji_Presentation # E14.0 [1] (🧌) troll
1F9CD..1F9CF ; Emoji_Presentation # E12.0 [3] (ðŸ§..ðŸ§) person standing..deaf person
1F9D0..1F9E6 ; Emoji_Presentation # E5.0 [23] (ðŸ§..🧦) face with monocle..socks
1F9E7..1F9FF ; Emoji_Presentation # E11.0 [25] (🧧..🧿) red envelope..nazar amulet
1FA70..1FA73 ; Emoji_Presentation # E12.0 [4] (🩰..🩳) ballet shoes..shorts
1FA74 ; Emoji_Presentation # E13.0 [1] (🩴) thong sandal
1FA78..1FA7A ; Emoji_Presentation # E12.0 [3] (🩸..🩺) drop of blood..stethoscope
+1FA7B..1FA7C ; Emoji_Presentation # E14.0 [2] (🩻..🩼) x-ray..crutch
1FA80..1FA82 ; Emoji_Presentation # E12.0 [3] (🪀..🪂) yo-yo..parachute
1FA83..1FA86 ; Emoji_Presentation # E13.0 [4] (🪃..🪆) boomerang..nesting dolls
1FA90..1FA95 ; Emoji_Presentation # E12.0 [6] (ðŸª..🪕) ringed planet..banjo
1FA96..1FAA8 ; Emoji_Presentation # E13.0 [19] (🪖..🪨) military helmet..rock
+1FAA9..1FAAC ; Emoji_Presentation # E14.0 [4] (🪩..🪬) mirror ball..hamsa
1FAB0..1FAB6 ; Emoji_Presentation # E13.0 [7] (🪰..🪶) fly..feather
+1FAB7..1FABA ; Emoji_Presentation # E14.0 [4] (🪷..🪺) lotus..nest with eggs
1FAC0..1FAC2 ; Emoji_Presentation # E13.0 [3] (🫀..🫂) anatomical heart..people hugging
+1FAC3..1FAC5 ; Emoji_Presentation # E14.0 [3] (🫃..🫅) pregnant man..person with crown
1FAD0..1FAD6 ; Emoji_Presentation # E13.0 [7] (ðŸ«..🫖) blueberries..teapot
+1FAD7..1FAD9 ; Emoji_Presentation # E14.0 [3] (🫗..🫙) pouring liquid..jar
+1FAE0..1FAE7 ; Emoji_Presentation # E14.0 [8] (🫠..🫧) melting face..bubbles
+1FAF0..1FAF6 ; Emoji_Presentation # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
-# Total elements: 1148
+# Total elements: 1185
# ================================================
@@ -738,15 +760,17 @@
1F9BB ; Emoji_Modifier_Base # E12.0 [1] (🦻) ear with hearing aid
1F9CD..1F9CF ; Emoji_Modifier_Base # E12.0 [3] (ðŸ§..ðŸ§) person standing..deaf person
1F9D1..1F9DD ; Emoji_Modifier_Base # E5.0 [13] (🧑..ðŸ§) person..elf
+1FAC3..1FAC5 ; Emoji_Modifier_Base # E14.0 [3] (🫃..🫅) pregnant man..person with crown
+1FAF0..1FAF6 ; Emoji_Modifier_Base # E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
-# Total elements: 122
+# Total elements: 132
# ================================================
# All omitted code points have Emoji_Component=No
# @missing: 0000..10FFFF ; Emoji_Component ; No
-0023 ; Emoji_Component # E0.0 [1] (#ï¸) number sign
+0023 ; Emoji_Component # E0.0 [1] (#ï¸) hash sign
002A ; Emoji_Component # E0.0 [1] (*ï¸) asterisk
0030..0039 ; Emoji_Component # E0.0 [10] (0ï¸..9ï¸) digit zero..digit nine
200D ; Emoji_Component # E0.0 [1] (â€) zero width joiner
@@ -902,8 +926,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
2747 ; Extended_Pictographic# E0.6 [1] (â‡ï¸) sparkle
274C ; Extended_Pictographic# E0.6 [1] (âŒ) cross mark
274E ; Extended_Pictographic# E0.6 [1] (âŽ) cross mark button
-2753..2755 ; Extended_Pictographic# E0.6 [3] (â“..â•) question mark..white exclamation mark
-2757 ; Extended_Pictographic# E0.6 [1] (â—) exclamation mark
+2753..2755 ; Extended_Pictographic# E0.6 [3] (â“..â•) red question mark..white exclamation mark
+2757 ; Extended_Pictographic# E0.6 [1] (â—) red exclamation mark
2763 ; Extended_Pictographic# E1.0 [1] (â£ï¸) heart exclamation
2764 ; Extended_Pictographic# E0.6 [1] (â¤ï¸) red heart
2765..2767 ; Extended_Pictographic# E0.0 [3] (â¥..â§) ROTATED HEAVY BLACK HEART BULLET..ROTATED FLORAL HEART BULLET
@@ -1041,7 +1065,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1F509 ; Extended_Pictographic# E1.0 [1] (🔉) speaker medium volume
1F50A..1F514 ; Extended_Pictographic# E0.6 [11] (🔊..🔔) speaker high volume..bell
1F515 ; Extended_Pictographic# E1.0 [1] (🔕) bell with slash
-1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..pistol
+1F516..1F52B ; Extended_Pictographic# E0.6 [22] (🔖..🔫) bookmark..water pistol
1F52C..1F52D ; Extended_Pictographic# E1.0 [2] (🔬..🔭) microscope..telescope
1F52E..1F53D ; Extended_Pictographic# E0.6 [16] (🔮..🔽) crystal ball..downwards button
1F546..1F548 ; Extended_Pictographic# E0.0 [3] (🕆..🕈) WHITE LATIN CROSS..CELTIC CROSS
@@ -1117,7 +1141,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1F62E..1F62F ; Extended_Pictographic# E1.0 [2] (😮..😯) face with open mouth..hushed face
1F630..1F633 ; Extended_Pictographic# E0.6 [4] (😰..😳) anxious face with sweat..flushed face
1F634 ; Extended_Pictographic# E1.0 [1] (😴) sleeping face
-1F635 ; Extended_Pictographic# E0.6 [1] (😵) dizzy face
+1F635 ; Extended_Pictographic# E0.6 [1] (😵) face with crossed-out eyes
1F636 ; Extended_Pictographic# E1.0 [1] (😶) face without mouth
1F637..1F640 ; Extended_Pictographic# E0.6 [10] (😷..🙀) face with medical mask..weary cat
1F641..1F644 ; Extended_Pictographic# E1.0 [4] (ðŸ™..🙄) slightly frowning face..face with rolling eyes
@@ -1166,7 +1190,8 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1F6D3..1F6D4 ; Extended_Pictographic# E0.0 [2] (🛓..🛔) STUPA..PAGODA
1F6D5 ; Extended_Pictographic# E12.0 [1] (🛕) hindu temple
1F6D6..1F6D7 ; Extended_Pictographic# E13.0 [2] (🛖..🛗) hut..elevator
-1F6D8..1F6DF ; Extended_Pictographic# E0.0 [8] (🛘..🛟) <reserved-1F6D8>..<reserved-1F6DF>
+1F6D8..1F6DC ; Extended_Pictographic# E0.0 [5] (🛘..🛜) <reserved-1F6D8>..<reserved-1F6DC>
+1F6DD..1F6DF ; Extended_Pictographic# E14.0 [3] (ðŸ›..🛟) playground slide..ring buoy
1F6E0..1F6E5 ; Extended_Pictographic# E0.7 [6] (🛠ï¸..🛥ï¸) hammer and wrench..motor boat
1F6E6..1F6E8 ; Extended_Pictographic# E0.0 [3] (🛦..🛨) UP-POINTING MILITARY AIRPLANE..UP-POINTING SMALL AIRPLANE
1F6E9 ; Extended_Pictographic# E0.7 [1] (🛩ï¸) small airplane
@@ -1185,7 +1210,9 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1F774..1F77F ; Extended_Pictographic# E0.0 [12] (ðŸ´..ðŸ¿) <reserved-1F774>..<reserved-1F77F>
1F7D5..1F7DF ; Extended_Pictographic# E0.0 [11] (🟕..🟟) CIRCLED TRIANGLE..<reserved-1F7DF>
1F7E0..1F7EB ; Extended_Pictographic# E12.0 [12] (🟠..🟫) orange circle..brown square
-1F7EC..1F7FF ; Extended_Pictographic# E0.0 [20] (🟬..🟿) <reserved-1F7EC>..<reserved-1F7FF>
+1F7EC..1F7EF ; Extended_Pictographic# E0.0 [4] (🟬..🟯) <reserved-1F7EC>..<reserved-1F7EF>
+1F7F0 ; Extended_Pictographic# E14.0 [1] (🟰) heavy equals sign
+1F7F1..1F7FF ; Extended_Pictographic# E0.0 [15] (🟱..🟿) <reserved-1F7F1>..<reserved-1F7FF>
1F80C..1F80F ; Extended_Pictographic# E0.0 [4] (🠌..ðŸ ) <reserved-1F80C>..<reserved-1F80F>
1F848..1F84F ; Extended_Pictographic# E0.0 [8] (🡈..ðŸ¡) <reserved-1F848>..<reserved-1F84F>
1F85A..1F85F ; Extended_Pictographic# E0.0 [6] (🡚..🡟) <reserved-1F85A>..<reserved-1F85F>
@@ -1214,7 +1241,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1F972 ; Extended_Pictographic# E13.0 [1] (🥲) smiling face with tear
1F973..1F976 ; Extended_Pictographic# E11.0 [4] (🥳..🥶) partying face..cold face
1F977..1F978 ; Extended_Pictographic# E13.0 [2] (🥷..🥸) ninja..disguised face
-1F979 ; Extended_Pictographic# E0.0 [1] (🥹) <reserved-1F979>
+1F979 ; Extended_Pictographic# E14.0 [1] (🥹) face holding back tears
1F97A ; Extended_Pictographic# E11.0 [1] (🥺) pleading face
1F97B ; Extended_Pictographic# E12.0 [1] (🥻) sari
1F97C..1F97F ; Extended_Pictographic# E11.0 [4] (🥼..🥿) lab coat..flat shoe
@@ -1232,7 +1259,7 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1F9C1..1F9C2 ; Extended_Pictographic# E11.0 [2] (ðŸ§..🧂) cupcake..salt
1F9C3..1F9CA ; Extended_Pictographic# E12.0 [8] (🧃..🧊) beverage box..ice
1F9CB ; Extended_Pictographic# E13.0 [1] (🧋) bubble tea
-1F9CC ; Extended_Pictographic# E0.0 [1] (🧌) <reserved-1F9CC>
+1F9CC ; Extended_Pictographic# E14.0 [1] (🧌) troll
1F9CD..1F9CF ; Extended_Pictographic# E12.0 [3] (ðŸ§..ðŸ§) person standing..deaf person
1F9D0..1F9E6 ; Extended_Pictographic# E5.0 [23] (ðŸ§..🧦) face with monocle..socks
1F9E7..1F9FF ; Extended_Pictographic# E11.0 [25] (🧧..🧿) red envelope..nazar amulet
@@ -1241,19 +1268,28 @@ E0020..E007F ; Emoji_Component # E0.0 [96] (ó € ..ó ¿) tag space..c
1FA74 ; Extended_Pictographic# E13.0 [1] (🩴) thong sandal
1FA75..1FA77 ; Extended_Pictographic# E0.0 [3] (🩵..🩷) <reserved-1FA75>..<reserved-1FA77>
1FA78..1FA7A ; Extended_Pictographic# E12.0 [3] (🩸..🩺) drop of blood..stethoscope
-1FA7B..1FA7F ; Extended_Pictographic# E0.0 [5] (🩻..🩿) <reserved-1FA7B>..<reserved-1FA7F>
+1FA7B..1FA7C ; Extended_Pictographic# E14.0 [2] (🩻..🩼) x-ray..crutch
+1FA7D..1FA7F ; Extended_Pictographic# E0.0 [3] (🩽..🩿) <reserved-1FA7D>..<reserved-1FA7F>
1FA80..1FA82 ; Extended_Pictographic# E12.0 [3] (🪀..🪂) yo-yo..parachute
1FA83..1FA86 ; Extended_Pictographic# E13.0 [4] (🪃..🪆) boomerang..nesting dolls
1FA87..1FA8F ; Extended_Pictographic# E0.0 [9] (🪇..ðŸª) <reserved-1FA87>..<reserved-1FA8F>
1FA90..1FA95 ; Extended_Pictographic# E12.0 [6] (ðŸª..🪕) ringed planet..banjo
1FA96..1FAA8 ; Extended_Pictographic# E13.0 [19] (🪖..🪨) military helmet..rock
-1FAA9..1FAAF ; Extended_Pictographic# E0.0 [7] (🪩..🪯) <reserved-1FAA9>..<reserved-1FAAF>
+1FAA9..1FAAC ; Extended_Pictographic# E14.0 [4] (🪩..🪬) mirror ball..hamsa
+1FAAD..1FAAF ; Extended_Pictographic# E0.0 [3] (🪭..🪯) <reserved-1FAAD>..<reserved-1FAAF>
1FAB0..1FAB6 ; Extended_Pictographic# E13.0 [7] (🪰..🪶) fly..feather
-1FAB7..1FABF ; Extended_Pictographic# E0.0 [9] (🪷..🪿) <reserved-1FAB7>..<reserved-1FABF>
+1FAB7..1FABA ; Extended_Pictographic# E14.0 [4] (🪷..🪺) lotus..nest with eggs
+1FABB..1FABF ; Extended_Pictographic# E0.0 [5] (🪻..🪿) <reserved-1FABB>..<reserved-1FABF>
1FAC0..1FAC2 ; Extended_Pictographic# E13.0 [3] (🫀..🫂) anatomical heart..people hugging
-1FAC3..1FACF ; Extended_Pictographic# E0.0 [13] (🫃..ðŸ«) <reserved-1FAC3>..<reserved-1FACF>
+1FAC3..1FAC5 ; Extended_Pictographic# E14.0 [3] (🫃..🫅) pregnant man..person with crown
+1FAC6..1FACF ; Extended_Pictographic# E0.0 [10] (🫆..ðŸ«) <reserved-1FAC6>..<reserved-1FACF>
1FAD0..1FAD6 ; Extended_Pictographic# E13.0 [7] (ðŸ«..🫖) blueberries..teapot
-1FAD7..1FAFF ; Extended_Pictographic# E0.0 [41] (🫗..🫿) <reserved-1FAD7>..<reserved-1FAFF>
+1FAD7..1FAD9 ; Extended_Pictographic# E14.0 [3] (🫗..🫙) pouring liquid..jar
+1FADA..1FADF ; Extended_Pictographic# E0.0 [6] (🫚..🫟) <reserved-1FADA>..<reserved-1FADF>
+1FAE0..1FAE7 ; Extended_Pictographic# E14.0 [8] (🫠..🫧) melting face..bubbles
+1FAE8..1FAEF ; Extended_Pictographic# E0.0 [8] (🫨..🫯) <reserved-1FAE8>..<reserved-1FAEF>
+1FAF0..1FAF6 ; Extended_Pictographic# E14.0 [7] (🫰..🫶) hand with index finger and thumb crossed..heart hands
+1FAF7..1FAFF ; Extended_Pictographic# E0.0 [9] (🫷..🫿) <reserved-1FAF7>..<reserved-1FAFF>
1FC00..1FFFD ; Extended_Pictographic# E0.0[1022] (🰀..🿽) <reserved-1FC00>..<reserved-1FFFD>
# Total elements: 3537
diff --git a/lib/stdlib/uc_spec/gen_unicode_mod.escript b/lib/stdlib/uc_spec/gen_unicode_mod.escript
index 8239b0d5a1..ecc30b40c6 100644
--- a/lib/stdlib/uc_spec/gen_unicode_mod.escript
+++ b/lib/stdlib/uc_spec/gen_unicode_mod.escript
@@ -4,7 +4,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2017-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2017-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -191,7 +191,7 @@ gen_static(Fd) ->
" {U,L} -> #{upper=>U,lower=>L,title=>U,fold=>L};\n"
" {U,L,T,F} -> #{upper=>U,lower=>L,title=>T,fold=>F}\n"
" end.\n\n"),
- io:put_chars(Fd, "spec_version() -> {13,0}.\n\n\n"),
+ io:put_chars(Fd, "spec_version() -> {14,0}.\n\n\n"),
io:put_chars(Fd, "class(Codepoint) -> {CCC,_,_} = unicode_table(Codepoint),\n CCC.\n\n"),
io:put_chars(Fd, "-spec uppercase(unicode:chardata()) -> "
"maybe_improper_list(gc(),unicode:chardata()).\n"),
@@ -671,7 +671,7 @@ gen_gc(Fd, GBP) ->
" false -> [CP0|T0]; % losing work done on T\n"
" _TrueOrZWJ -> gc_extend2(cp(T), T, [CP,CP0])\n"
" end;\n"
- "gc_extend([], _, CP) -> [CP];\n"
+ "gc_extend([], T0, CP) -> [CP|T0];\n"
"gc_extend({error,R}, _, CP) -> [CP|R].\n\n"),
io:put_chars(Fd,
"gc_extend2([CP|T], T0, Acc) ->\n"
@@ -679,8 +679,8 @@ gen_gc(Fd, GBP) ->
" false -> [lists:reverse(Acc)|T0]; % losing work done on T\n"
" _TrueOrZWJ -> gc_extend2(cp(T), T, [CP|Acc])\n"
" end;\n"
- "gc_extend2([], _, Acc) ->\n"
- " [lists:reverse(Acc)];\n"
+ "gc_extend2([], T0, Acc) ->\n"
+ " [lists:reverse(Acc)|T0];\n"
"gc_extend2({error,R}, _, Acc) ->\n"
" [lists:reverse(Acc)] ++ [R].\n\n"
),
@@ -705,10 +705,10 @@ gen_gc(Fd, GBP) ->
" _ -> [lists:reverse(Acc)|T0]\n"
" end\n"
" end;\n"
- "gc_ext_pict([], _T0, Acc) ->\n"
+ "gc_ext_pict([], T0, Acc) ->\n"
" case Acc of\n"
- " [A] -> [A];\n"
- " _ -> [lists:reverse(Acc)]\n"
+ " [A] -> [A|T0];\n"
+ " _ -> [lists:reverse(Acc)|T0]\n"
" end;\n"
"gc_ext_pict({error,R}, T, Acc) ->\n"
" gc_ext_pict([], T, Acc) ++ [R].\n\n"),
@@ -722,10 +722,10 @@ gen_gc(Fd, GBP) ->
" _ -> [lists:reverse(Acc)|T0]\n"
" end\n"
" end;\n"
- "gc_ext_pict_zwj([], _, Acc) ->\n"
+ "gc_ext_pict_zwj([], T0, Acc) ->\n"
" case Acc of\n"
- " [A] -> [A];\n"
- " _ -> [lists:reverse(Acc)]\n"
+ " [A] -> [A|T0];\n"
+ " _ -> [lists:reverse(Acc)|T0]\n"
" end;\n"
"gc_ext_pict_zwj({error,R}, T, Acc) ->\n"
" gc_ext_pict_zwj([], T, Acc) ++ [R].\n\n"),
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index c68e00fd12..cd81d52182 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.17.2
+STDLIB_VSN = 4.3
diff --git a/lib/syntax_tools/doc/Makefile b/lib/syntax_tools/doc/Makefile
index 87604c4e7f..87b7660c26 100644
--- a/lib/syntax_tools/doc/Makefile
+++ b/lib/syntax_tools/doc/Makefile
@@ -57,7 +57,7 @@ info:
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index b3629d4477..a4633065d0 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2021</year>
+ <year>2007</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,64 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 3.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p><c>erl_syntax_lib:annotate_bindings/1,2</c> will now
+ properly annotate named functions and their
+ arguments.</p>
+ <p>
+ Own Id: OTP-18380 Aux Id: PR-6523, GH-4733 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 3.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The <c>erl_syntax_lib:analyze_attribute/1</c> function
+ would return <c>{Name, {Name, Value}}</c> instead of
+ <c>{Name, Value}</c> (which is the documented return
+ value).</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17894 Aux Id: PR-5509 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added support for configurable features as described in
+ EEP-60. Features can be enabled/disabled during
+ compilation with options (<c>-enable-feature Feature</c>,
+ <c>-disable-feature Feature</c> and <c>+{feature,
+ Feature, enable|disable}</c>) to <c>erlc</c> as well as
+ with directives (<c>-feature(Feature,
+ enable|disable).</c>) in the file. Similar options can be
+ used to <c>erl</c> for enabling/disabling features
+ allowed at runtime. The new <c>maybe</c> expression
+ (EEP-49) is fully supported as the feature
+ <c>maybe_expr</c>. The features support is documented in
+ the reference manual.</p>
+ <p>
+ Own Id: OTP-17988</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -860,7 +918,7 @@
<list>
<item>
<p>
- Miscellanous updates.</p>
+ Miscellaneous updates.</p>
<p>
Own Id: OTP-8038</p>
</item>
diff --git a/lib/syntax_tools/examples/Makefile b/lib/syntax_tools/examples/Makefile
index f5e96a8285..0712898f65 100644
--- a/lib/syntax_tools/examples/Makefile
+++ b/lib/syntax_tools/examples/Makefile
@@ -37,7 +37,7 @@ EXAMPLE_FILES = demo.erl
# ----------------------------------------------------
# Make Rules
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile
index af6a472f3d..dc0ac61734 100644
--- a/lib/syntax_tools/src/Makefile
+++ b/lib/syntax_tools/src/Makefile
@@ -50,7 +50,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
# Targets
# ----------------------------------------------------
-debug opt: $(OBJECTS)
+$(TYPES): $(OBJECTS)
all: $(OBJECTS)
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index eacfbc5d6b..2e0694c2cf 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -430,7 +430,14 @@ quick_parse_form(Dev, L0, Options) ->
parse_form(Dev, L0, Parser, Options) ->
NoFail = proplists:get_bool(no_fail, Options),
Opt = #opt{clever = proplists:get_bool(clever, Options)},
- case io:scan_erl_form(Dev, "", L0) of
+
+ %% This as the *potential* to read options for enabling/disabling
+ %% features for the parsing of the file.
+ {ok, {_Ftrs, ResWordFun}} =
+ erl_features:keyword_fun(Options,
+ fun erl_scan:f_reserved_word/1),
+
+ case io:scan_erl_form(Dev, "", L0, [{reserved_word_fun,ResWordFun}]) of
{ok, Ts, L1} ->
case catch {ok, Parser(Ts, Opt)} of
{'EXIT', Term} ->
@@ -504,7 +511,9 @@ quickscan_form([{'-', _Anno}, {'if', AnnoA} | _Ts]) ->
kill_form(AnnoA);
quickscan_form([{'-', _Anno}, {atom, AnnoA, elif} | _Ts]) ->
kill_form(AnnoA);
-quickscan_form([{'-', _Anno}, {atom, AnnoA, else} | _Ts]) ->
+quickscan_form([{'-', _Anno}, {atom, AnnoA, 'else'} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {'else', AnnoA} | _Ts]) ->
kill_form(AnnoA);
quickscan_form([{'-', _Anno}, {atom, AnnoA, endif} | _Ts]) ->
kill_form(AnnoA);
@@ -648,9 +657,12 @@ scan_form([{'-', _Anno}, {'if', AnnoA} | Ts], Opt) ->
scan_form([{'-', _Anno}, {atom, AnnoA, elif} | Ts], Opt) ->
[{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA},
{atom, AnnoA, 'elif'} | scan_macros(Ts, Opt)];
-scan_form([{'-', _Anno}, {atom, AnnoA, else} | Ts], Opt) ->
+scan_form([{'-', _Anno}, {atom, AnnoA, 'else'} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA},
+ {atom, AnnoA, 'else'} | scan_macros(Ts, Opt)];
+scan_form([{'-', _Anno}, {'else', AnnoA} | Ts], Opt) ->
[{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA},
- {atom, AnnoA, else} | scan_macros(Ts, Opt)];
+ {atom, AnnoA, 'else'} | scan_macros(Ts, Opt)];
scan_form([{'-', _Anno}, {atom, AnnoA, endif} | Ts], Opt) ->
[{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA},
{atom, AnnoA, endif} | scan_macros(Ts, Opt)];
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index af1f2b4d11..d6c1c1e005 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -54,7 +54,7 @@
-type hook() :: 'none'
| fun((erl_syntax:syntaxTree(), _, _) -> prettypr:document()).
-type clause_t() :: 'case_expr' | 'fun_expr'
- | 'if_expr' | 'receive_expr' | 'try_expr'
+ | 'if_expr' | 'maybe_expr' | 'receive_expr' | 'try_expr'
| {'function', prettypr:document()}
| 'spec'.
@@ -588,6 +588,8 @@ lay_2(Node, Ctxt) ->
make_if_clause(D1, D2, D3, Ctxt);
case_expr ->
make_case_clause(D1, D2, D3, Ctxt);
+ maybe_expr ->
+ make_case_clause(D1, D2, D3, Ctxt);
receive_expr ->
make_case_clause(D1, D2, D3, Ctxt);
try_expr ->
@@ -648,6 +650,34 @@ lay_2(Node, Ctxt) ->
set_prec(Ctxt, PrecR)),
beside(D1, beside(text(":"), D2));
+ maybe_expr ->
+ Ctxt1 = reset_prec(Ctxt),
+ D1 = vertical(seq(erl_syntax:maybe_expr_body(Node),
+ floating(text(",")), Ctxt1, fun lay/2)),
+ Es0 = [text("end")],
+ Es1 = case erl_syntax:maybe_expr_else(Node) of
+ none -> Es0;
+ ElseNode ->
+ ElseCs = erl_syntax:else_expr_clauses(ElseNode),
+ D3 = lay_clauses(ElseCs, maybe_expr, Ctxt1),
+ [text("else"),
+ nest(Ctxt1#ctxt.break_indent, D3)
+ | Es0]
+ end,
+ sep([par([text("maybe"), nest(Ctxt1#ctxt.break_indent, D1),
+ hd(Es1)]) | tl(Es1)]);
+
+ maybe_match_expr ->
+ {PrecL, Prec, PrecR} = inop_prec('='),
+ D1 = lay(erl_syntax:maybe_match_expr_pattern(Node),
+ set_prec(Ctxt, PrecL)),
+ D2 = lay(erl_syntax:maybe_match_expr_body(Node),
+ set_prec(Ctxt, PrecR)),
+ D3 = follow(beside(D1, floating(text(" ?="))), D2,
+ Ctxt#ctxt.break_indent),
+ maybe_parentheses(D3, Prec, Ctxt);
+
+
%%
%% The rest is in alphabetical order (except map and types)
%%
@@ -759,7 +789,7 @@ lay_2(Node, Ctxt) ->
nest(Ctxt1#ctxt.break_indent, sep(Es)),
text("end")]);
- catch_expr ->
+ 'catch_expr' -> %Quoted to help Emacs.
{Prec, PrecR} = preop_prec('catch'),
D = lay(erl_syntax:catch_expr_body(Node),
set_prec(Ctxt, PrecR)),
@@ -801,7 +831,7 @@ lay_2(Node, Ctxt) ->
sep(seq(erl_syntax:disjunction_body(Node),
floating(text(";")), reset_prec(Ctxt),
fun lay/2));
-
+
error_marker ->
E = erl_syntax:error_marker_info(Node),
beside(text("** "),
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 354b65c9a3..4da1635aec 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -193,6 +193,8 @@
constraint_body/1,
disjunction/1,
disjunction_body/1,
+ else_expr/1,
+ else_expr_clauses/1,
eof_marker/0,
error_marker/1,
error_marker_info/1,
@@ -266,6 +268,13 @@
match_expr/2,
match_expr_body/1,
match_expr_pattern/1,
+ maybe_expr/1,
+ maybe_expr/2,
+ maybe_expr_body/1,
+ maybe_expr_else/1,
+ maybe_match_expr/2,
+ maybe_match_expr_pattern/1,
+ maybe_match_expr_body/1,
module_qualifier/2,
module_qualifier_argument/1,
module_qualifier_body/1,
@@ -505,13 +514,14 @@
%% <td>constrained_function_type</td>
%% <td>constraint</td>
%% <td>disjunction</td>
-%% <td>eof_marker</td>
%% </tr><tr>
+%% <td>else_expr</td>
+%% <td>eof_marker</td>
%% <td>error_marker</td>
+%% </tr><tr>
%% <td>float</td>
%% <td>form_list</td>
%% <td>fun_expr</td>
-%% </tr><tr>
%% <td>fun_type</td>
%% <td>function</td>
%% <td>function_type</td>
@@ -535,6 +545,9 @@
%% <td>map_type_assoc</td>
%% <td>map_type_exact</td>
%% <td>match_expr</td>
+%% </tr><tr>
+%% <td>maybe_expr</td>
+%% <td>maybe_match_expr</td>
%% <td>module_qualifier</td>
%% </tr><tr>
%% <td>named_fun_expr</td>
@@ -597,6 +610,7 @@
%% @see constrained_function_type/2
%% @see constraint/2
%% @see disjunction/1
+%% @see else_expr/1
%% @see eof_marker/0
%% @see error_marker/1
%% @see float/1
@@ -623,6 +637,9 @@
%% @see map_type_assoc/2
%% @see map_type_exact/2
%% @see match_expr/2
+%% @see maybe_expr/1
+%% @see maybe_expr/2
+%% @see maybe_match_expr/2
%% @see module_qualifier/2
%% @see named_fun_expr/2
%% @see nil/0
@@ -683,6 +700,9 @@ type(Node) ->
{'fun', _, {function, _, _}} -> implicit_fun;
{'fun', _, {function, _, _, _}} -> implicit_fun;
{'if', _, _} -> if_expr;
+ {'maybe', _, _} -> maybe_expr;
+ {'maybe', _, _, _} -> maybe_expr;
+ {'else', _, _} -> else_expr;
{'receive', _, _, _, _} -> receive_expr;
{'receive', _, _} -> receive_expr;
{attribute, _, _, _} -> attribute;
@@ -702,6 +722,7 @@ type(Node) ->
{map, _, _} -> map_expr;
{map_field_assoc, _, _, _} -> map_field_assoc;
{map_field_exact, _, _, _} -> map_field_exact;
+ {maybe_match, _, _, _} -> maybe_match_expr;
{op, _, _, _, _} -> infix_expr;
{op, _, _, _} -> prefix_expr;
{record, _, _, _, _} -> record_expr;
@@ -4135,6 +4156,71 @@ match_expr_body(Node) ->
%% =====================================================================
+%% @doc Creates an abstract maybe-expression, as used in <code>maybe</code>
+%% blocks. The result represents
+%% "<code><em>Pattern</em> ?= <em>Body</em></code>".
+%%
+%% @see maybe_match_expr_pattern/1
+%% @see maybe_match_expr_body/1
+%% @see maybe_expr/2
+
+-record(maybe_match_expr, {pattern :: syntaxTree(), body :: syntaxTree()}).
+
+%% type(Node) = maybe_expr
+%% data(Node) = #maybe_expr{pattern :: Pattern, body :: Body}
+%%
+%% Pattern = Body = syntaxTree()
+%%
+%% `erl_parse' representation:
+%%
+%% {maybe_match, Pos, Pattern, Body}
+%%
+%% Pattern = Body = erl_parse()
+%%
+
+-spec maybe_match_expr(syntaxTree(), syntaxTree()) -> syntaxTree().
+
+maybe_match_expr(Pattern, Body) ->
+ tree(maybe_match_expr, #maybe_match_expr{pattern = Pattern, body = Body}).
+
+revert_maybe_match_expr(Node) ->
+ Pos = get_pos(Node),
+ Pattern = maybe_match_expr_pattern(Node),
+ Body = maybe_match_expr_body(Node),
+ {maybe_match, Pos, Pattern, Body}.
+
+%% =====================================================================
+%% @doc Returns the pattern subtree of a `maybe_expr' node.
+%%
+%% @see maybe_match_expr/2
+
+-spec maybe_match_expr_pattern(syntaxTree()) -> syntaxTree().
+
+maybe_match_expr_pattern(Node) ->
+ case unwrap(Node) of
+ {maybe_match, _, Pattern, _} ->
+ Pattern;
+ Node1 ->
+ (data(Node1))#maybe_match_expr.pattern
+ end.
+
+
+%% =====================================================================
+%% @doc Returns the body subtree of a `maybe_expr' node.
+%%
+%% @see maybe_match_expr/2
+
+-spec maybe_match_expr_body(syntaxTree()) -> syntaxTree().
+
+maybe_match_expr_body(Node) ->
+ case unwrap(Node) of
+ {maybe_match, _, _, Body} ->
+ Body;
+ Node1 ->
+ (data(Node1))#maybe_match_expr.body
+ end.
+
+%% =====================================================================
%% @doc Creates an abstract operator. The name of the operator is the
%% character sequence represented by `Name'. This is
%% analogous to the print name of an atom, but an operator is never
@@ -6361,6 +6447,130 @@ case_expr_clauses(Node) ->
(data(Node1))#case_expr.clauses
end.
+%% =====================================================================
+%% @doc Creates an abstract else-expression. If `Clauses' is `[C1,
+%% ..., Cn]', the result represents "<code>else <em>C1</em>; ...; <em>Cn</em>
+%% end</code>". More exactly, if each `Ci' represents
+%% "<code>(<em>Pi</em>) <em>Gi</em> -> <em>Bi</em></code>", then the
+%% result represents "<code>else <em>G1</em> -> <em>B1</em>; ...;
+%% <em>Pn</em> <em>Gn</em> -> <em>Bn</em> end</code>".
+%%
+%% @see maybe_expr/2
+%% @see else_expr_clauses/1
+%% @see clause/3
+
+else_expr(Clauses) ->
+ tree(else_expr, Clauses).
+
+revert_else_expr(Node) ->
+ Pos = get_pos(Node),
+ Clauses = else_expr_clauses(Node),
+ {'else', Pos, Clauses}.
+
+%% =====================================================================
+%% @doc Returns the list of clause subtrees of an `else_expr' node.
+%%
+%% @see else_expr/1
+
+-spec else_expr_clauses(syntaxTree()) -> [syntaxTree()].
+
+else_expr_clauses(Node) ->
+ case unwrap(Node) of
+ {'else', _, Clauses} ->
+ Clauses;
+ Node1 ->
+ data(Node1)
+ end.
+
+%% =====================================================================
+%% @equiv maybe_expr(Body, none)
+
+-spec maybe_expr([syntaxTree()]) -> syntaxTree().
+
+maybe_expr(Body) ->
+ maybe_expr(Body, none).
+
+%% =====================================================================
+%% @doc Creates an abstract maybe-expression. If `Body' is `[B1, ...,
+%% Bn]', and `OptionalElse' is `none', the result represents
+%% "<code>maybe <em>B1</em>, ..., <em>Bn</em> end</code>". If `Body'
+%% is `[B1, ..., Bn]', and `OptionalElse' reprsents an `else_expr' node
+%% with clauses `[C1, ..., Cn]', the result represents "<code>maybe
+%% <em>B1</em>, ..., <em>Bn</em> else <em>C1</em>; ..., <em>Cn</em>
+%% end</code>".
+%%
+%% See `clause' for documentation on `erl_parse' clauses.
+%%
+%% @see maybe_expr_body/1
+%% @see maybe_expr_else/1
+
+-record(maybe_expr, {body :: [syntaxTree()],
+ 'else' = none :: 'none' | syntaxTree()}).
+
+%% type(Node) = maybe_expr
+%% data(Node) = #maybe_expr{body :: Body, 'else' :: 'none' | Else}
+%%
+%% Body = [syntaxTree()]
+%% Else = syntaxTree()
+%%
+%% `erl_parse' representation:
+%%
+%% {block, Pos, Body}
+%% {block, Pos, Body, Else}
+%%
+%% Body = [erl_parse()] \ []
+%% Else = {'else', Pos, Clauses}
+%% Clauses = [Clause] \ []
+%% Clause = {clause, ...}
+
+-spec maybe_expr([syntaxTree()], 'none' | syntaxTree()) -> syntaxTree().
+
+maybe_expr(Body, OptionalElse) ->
+ tree(maybe_expr, #maybe_expr{body = Body,
+ 'else' = OptionalElse}).
+revert_maybe_expr(Node) ->
+ Pos = get_pos(Node),
+ Body = maybe_expr_body(Node),
+ case maybe_expr_else(Node) of
+ none ->
+ {'maybe', Pos, Body};
+ Else ->
+ {'maybe', Pos, Body, Else}
+ end.
+
+%% =====================================================================
+%% @doc Returns the list of body subtrees of a `maybe_expr' node.
+%%
+%% @see maybe_expr/2
+
+-spec maybe_expr_body(syntaxTree()) -> [syntaxTree()].
+
+maybe_expr_body(Node) ->
+ case unwrap(Node) of
+ {'maybe', _, Body} ->
+ Body;
+ {'maybe', _, Body, _Else} ->
+ Body;
+ Node1 ->
+ (data(Node1))#maybe_expr.body
+ end.
+
+%% =====================================================================
+%% @doc Returns the else subtree of a `maybe_expr' node.
+%%
+%% @see maybe_expr/2
+
+-spec maybe_expr_else(syntaxTree()) -> 'none' | syntaxTree().
+
+maybe_expr_else(Node) ->
+ case unwrap(Node) of
+ {'maybe', _, _Body} ->
+ none;
+ {'maybe', _, _Body, Else} ->
+ Else;
+ Node1 ->
+ (data(Node1))#maybe_expr.'else'
+ end.
%% =====================================================================
%% @equiv receive_expr(Clauses, none, [])
@@ -7310,7 +7520,7 @@ concrete(Node) ->
eval_bits:expr_grp(Fs, [],
fun(F, _) ->
{value, concrete(F), []}
- end, [], true),
+ end),
B;
arity_qualifier ->
A = erl_syntax:arity_qualifier_argument(Node),
@@ -7470,9 +7680,9 @@ revert_root(Node) ->
revert_bitstring_type(Node);
block_expr ->
revert_block_expr(Node);
- case_expr ->
+ 'case_expr' -> %Quoted to help Emacs.
revert_case_expr(Node);
- catch_expr ->
+ 'catch_expr' -> %Quoted to help Emacs.
revert_catch_expr(Node);
char ->
revert_char(Node);
@@ -7482,6 +7692,8 @@ revert_root(Node) ->
revert_constrained_function_type(Node);
constraint ->
revert_constraint(Node);
+ else_expr ->
+ revert_else_expr(Node);
eof_marker ->
revert_eof_marker(Node);
error_marker ->
@@ -7526,6 +7738,10 @@ revert_root(Node) ->
revert_map_type_exact(Node);
match_expr ->
revert_match_expr(Node);
+ maybe_match_expr ->
+ revert_maybe_match_expr(Node);
+ maybe_expr ->
+ revert_maybe_expr(Node);
module_qualifier ->
revert_module_qualifier(Node);
named_fun_expr ->
@@ -7730,7 +7946,7 @@ subtrees(T) ->
case_expr ->
[[case_expr_argument(T)],
case_expr_clauses(T)];
- catch_expr ->
+ 'catch_expr' -> %Quoted to help Emacs.
[[catch_expr_body(T)]];
class_qualifier ->
[[class_qualifier_argument(T)],
@@ -7755,6 +7971,8 @@ subtrees(T) ->
constraint_body(T)];
disjunction ->
[disjunction_body(T)];
+ else_expr ->
+ [else_expr_clauses(T)];
form_list ->
[form_list_elements(T)];
fun_expr ->
@@ -7823,6 +8041,17 @@ subtrees(T) ->
match_expr ->
[[match_expr_pattern(T)],
[match_expr_body(T)]];
+ maybe_expr ->
+ case maybe_expr_else(T) of
+ none ->
+ [maybe_expr_body(T)];
+ E ->
+ [maybe_expr_body(T),
+ [E]]
+ end;
+ maybe_match_expr ->
+ [[maybe_match_expr_pattern(T)],
+ [maybe_match_expr_body(T)]];
module_qualifier ->
[[module_qualifier_argument(T)],
[module_qualifier_body(T)]];
@@ -7962,6 +8191,7 @@ make_tree(constrained_function_type, [[F],C]) ->
constrained_function_type(F, C);
make_tree(constraint, [[N], Ts]) -> constraint(N, Ts);
make_tree(disjunction, [E]) -> disjunction(E);
+make_tree(else_expr, [E]) -> else_expr(E);
make_tree(form_list, [E]) -> form_list(E);
make_tree(fun_expr, [C]) -> fun_expr(C);
make_tree(function, [[N], C]) -> function(N, C);
@@ -7985,6 +8215,9 @@ make_tree(map_type, [Fs]) -> map_type(Fs);
make_tree(map_type_assoc, [[N],[V]]) -> map_type_assoc(N, V);
make_tree(map_type_exact, [[N],[V]]) -> map_type_exact(N, V);
make_tree(match_expr, [[P], [E]]) -> match_expr(P, E);
+make_tree(maybe_expr, [Body]) -> maybe_expr(Body);
+make_tree(maybe_expr, [Body, [Else]]) -> maybe_expr(Body, Else);
+make_tree(maybe_match_expr, [[P], [E]]) -> maybe_match_expr(P, E);
make_tree(named_fun_expr, [[N], C]) -> named_fun_expr(N, C);
make_tree(module_qualifier, [[M], [N]]) -> module_qualifier(M, N);
make_tree(parentheses, [[E]]) -> parentheses(E);
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 6185007235..caaa322dfb 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -332,8 +332,8 @@ variables_2([], S) ->
-define(MINIMUM_RANGE, 100).
-define(START_RANGE_FACTOR, 100).
-define(MAX_RETRIES, 3). % retries before enlarging range
--define(ENLARGE_ENUM, 8). % range enlargment enumerator
--define(ENLARGE_DENOM, 1). % range enlargment denominator
+-define(ENLARGE_ENUM, 8). % range enlargement enumerator
+-define(ENLARGE_DENOM, 1). % range enlargement denominator
default_variable_name(N) ->
list_to_atom("V" ++ integer_to_list(N)).
@@ -538,6 +538,8 @@ vann(Tree, Env) ->
vann_function(Tree, Env);
fun_expr ->
vann_fun_expr(Tree, Env);
+ named_fun_expr ->
+ vann_named_fun_expr(Tree, Env);
list_comp ->
vann_list_comp(Tree, Env);
binary_comp ->
@@ -583,6 +585,18 @@ vann_fun_expr(Tree, Env) ->
Bound = [],
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+vann_named_fun_expr(Tree, Env) ->
+ N = erl_syntax:named_fun_expr_name(Tree),
+ NBound = [erl_syntax:variable_name(N)],
+ NFree = [],
+ N1 = ann_bindings(N, Env, NBound, NFree),
+ Env1 = ordsets:union(Env, NBound),
+ Cs = erl_syntax:named_fun_expr_clauses(Tree),
+ {Cs1, {_, Free}} = vann_clauses(Cs, Env1),
+ Tree1 = rewrite(Tree, erl_syntax:named_fun_expr(N1,Cs1)),
+ Bound = [],
+ {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+
vann_match_expr(Tree, Env) ->
E = erl_syntax:match_expr_body(Tree),
{E1, Bound1, Free1} = vann(E, Env),
@@ -1106,7 +1120,7 @@ collect_attribute(file, _, Info) ->
Info;
collect_attribute(record, {R, L}, Info) ->
finfo_add_record(R, L, Info);
-collect_attribute(_, {N, V}, Info) ->
+collect_attribute(N, V, Info) ->
finfo_add_attribute(N, V, Info).
%% Abstract datatype for collecting module information.
@@ -1254,7 +1268,7 @@ analyze_form(Node) ->
%% @doc Analyzes an attribute node. If `Node' represents a
%% preprocessor directive, the atom `preprocessor' is
%% returned. Otherwise, if `Node' represents a module
-%% attribute "`-<em>Name</em>...'", a tuple `{Name,
+%% attribute "`-Name...'", a tuple `{Name,
%% Info}' is returned, where `Info' depends on
%% `Name', as follows:
%% <dl>
@@ -1314,7 +1328,7 @@ analyze_attribute(Node) ->
ifndef -> preprocessor;
'if' -> preprocessor;
elif -> preprocessor;
- else -> preprocessor;
+ 'else' -> preprocessor;
endif -> preprocessor;
A ->
{A, analyze_attribute(A, Node)}
@@ -1335,7 +1349,8 @@ analyze_attribute(record, Node) ->
analyze_record_attribute(Node);
analyze_attribute(_, Node) ->
%% A "wild" attribute (such as e.g. a `compile' directive).
- analyze_wild_attribute(Node).
+ {_, Info} = analyze_wild_attribute(Node),
+ Info.
%% =====================================================================
@@ -1632,8 +1647,8 @@ analyze_wild_attribute(Node) ->
%% `Node' represents "`-record(Name, {...}).'",
%% where `Fields' is a list of pairs `{Label,
%% {Default, Type}}' for each field "`Label'", "`Label =
-%% <em>Default</em>'", "`Label :: <em>Type</em>'", or
-%% "`Label = <em>Default</em> :: <em>Type</em>'" in the declaration,
+%% Default'", "`Label :: Type'", or
+%% "`Label = Default :: Type'" in the declaration,
%% listed in left-to-right
%% order. If the field has no default-value declaration, the value for
%% `Default' will be the atom `none'. If the field has no type declaration,
@@ -1708,7 +1723,7 @@ analyze_record_attribute_tuple(Node) ->
%% For a `record_expr' node, `Info' represents
%% the record name and the list of descriptors for the involved fields,
%% listed in the order they appear. A field descriptor is a pair
-%% `{Label, Value}', if `Node' represents "`Label = <em>Value</em>'".
+%% `{Label, Value}', if `Node' represents "`Label = Value'".
%% For a `record_access' node,
%% `Info' represents the record name and the field name. For a
%% `record_index_expr' node, `Info' represents the
@@ -1783,9 +1798,8 @@ analyze_record_expr(Node) ->
%%
%% @doc Returns the label, value-expression, and type of a record field
%% specifier. The result is a pair `{Label, {Default, Type}}', if
-%% `Node' represents "`Label'", "`Label = <em>Default</em>'",
-%% "`Label :: <em>Type</em>'", or
-%% "`Label = <em>Default</em> :: <em>Type</em>'".
+%% `Node' represents "`Label'", "`Label = Default'",
+%% "`Label :: Type'", or "`Label = Default :: Type'".
%% If the field has no value-expression, the value for
%% `Default' will be the atom `none'. If the field has no type,
%% the value for `Type' will be the atom `none'.
@@ -1862,7 +1876,7 @@ analyze_file_attribute(Node) ->
%%
%% @doc Returns the name and arity of a function definition. The result
%% is a pair `{Name, A}' if `Node' represents a
-%% function definition "`Name(<em>P_1</em>, ..., <em>P_A</em>) ->
+%% function definition "`Name(P_1, ..., P_A) ->
%% ...'".
%%
%% The evaluation throws `syntax_error' if
@@ -1895,7 +1909,7 @@ analyze_function(Node) ->
%% ModuleName = atom()
%%
%% @doc Returns the name of an implicit fun expression "`fun
-%% <em>F</em>'". The result is a representation of the function
+%% F'". The result is a representation of the function
%% name `F'. (Cf. `analyze_function_name/1'.)
%%
%% The evaluation throws `syntax_error' if
@@ -1925,7 +1939,7 @@ analyze_implicit_fun(Node) ->
%% @doc Returns the name of a called function. The result is a
%% representation of the name of the applied function `F/A',
%% if `Node' represents a function application
-%% "`<em>F</em>(<em>X_1</em>, ..., <em>X_A</em>)'". If the
+%% "`F(X_1, ..., X_A)'". If the
%% function is not explicitly named (i.e., `F' is given by
%% some expression), only the arity `A' is returned.
%%
@@ -1966,10 +1980,10 @@ analyze_application(Node) ->
%% @doc Returns the name of a used type. The result is a
%% representation of the name of the used pre-defined or local type `N/A',
%% if `Node' represents a local (user) type application
-%% "`<em>N</em>(<em>T_1</em>, ..., <em>T_A</em>)'", or
+%% "`N(T_1, ..., T_A)'", or
%% a representation of the name of the used remote type `M:N/A'
%% if `Node' represents a remote user type application
-%% "`<em>M</em>:<em>N</em>(<em>T_1</em>, ..., <em>T_A</em>)'".
+%% "`M:N(T_1, ..., T_A)'".
%%
%% The evaluation throws `syntax_error' if `Node' does not represent a
%% well-formed (user) type application expression.
diff --git a/lib/syntax_tools/src/merl.erl b/lib/syntax_tools/src/merl.erl
index 97ef68ce4c..28cd1283e9 100644
--- a/lib/syntax_tools/src/merl.erl
+++ b/lib/syntax_tools/src/merl.erl
@@ -467,7 +467,7 @@ quote(Text) ->
%% @doc Parse text. Takes an initial scanner starting position as first
%% argument.
%%
-%% The macro `?Q(Text)' expands to `merl:quote(?LINE, Text, Env)'.
+%% The macro `?Q(Text)' expands to `merl:quote(?LINE, Text)'.
%%
%% @see quote/1
diff --git a/lib/syntax_tools/src/prettypr.erl b/lib/syntax_tools/src/prettypr.erl
index 1f2dfffbdb..caafa9b8b9 100644
--- a/lib/syntax_tools/src/prettypr.erl
+++ b/lib/syntax_tools/src/prettypr.erl
@@ -432,7 +432,7 @@ follow(D1, D2) ->
%% document()
%%
%% @doc Separates two documents by either a single space, or a line
-%% break and intentation. In other words, one of the layouts
+%% break and indentation. In other words, one of the layouts
%% ```abc def'''
%% or
%% ```abc
diff --git a/lib/syntax_tools/src/syntax_tools.app.src b/lib/syntax_tools/src/syntax_tools.app.src
index 9bbf20d5a5..a6eeeba5dc 100644
--- a/lib/syntax_tools/src/syntax_tools.app.src
+++ b/lib/syntax_tools/src/syntax_tools.app.src
@@ -16,4 +16,4 @@
{applications, [stdlib]},
{env, []},
{runtime_dependencies,
- ["compiler-7.0","erts-9.0","kernel-5.0","stdlib-3.4"]}]}.
+ ["compiler-7.0","erts-9.0","kernel-5.0","stdlib-4.0"]}]}.
diff --git a/lib/syntax_tools/test/Makefile b/lib/syntax_tools/test/Makefile
index 4ace860223..deee5ab814 100644
--- a/lib/syntax_tools/test/Makefile
+++ b/lib/syntax_tools/test/Makefile
@@ -27,6 +27,7 @@ RELSYSDIR = $(RELEASE_PATH)/syntax_tools_test
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -40,7 +41,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' \
>> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index 3246ce7010..3553f7a71f 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -27,7 +27,7 @@
revert_map_type/1,wrapped_subtrees/1,
t_abstract_type/1,t_erl_parse_type/1,t_type/1,
t_epp_dodger/1,t_epp_dodger_clever/1,
- t_comment_scan/1,t_prettypr/1]).
+ t_comment_scan/1,t_prettypr/1,test_named_fun_bind_ann/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -36,7 +36,7 @@ all() ->
wrapped_subtrees,
t_abstract_type,t_erl_parse_type,t_type,
t_epp_dodger,t_epp_dodger_clever,
- t_comment_scan,t_prettypr].
+ t_comment_scan,t_prettypr,test_named_fun_bind_ann].
groups() ->
[].
@@ -106,7 +106,8 @@ revert(Config) when is_list(Config) ->
test_server:timetrap_cancel(Dog).
revert_file(File, Path) ->
- case epp:parse_file(File, Path, []) of
+ case epp:parse_file(File, [{includes,Path},
+ res_word_option()]) of
{ok,Fs0} ->
Fs1 = erl_syntax:form_list(Fs0),
Fs2 = erl_syntax_lib:map(fun (Node) -> Node end, Fs1),
@@ -350,11 +351,37 @@ t_comment_scan(Config) when is_list(Config) ->
t_prettypr(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
- Filenames = ["type_specs.erl",
- "specs_and_funs.erl"],
+ Filenames = test_files(),
ok = test_prettypr(Filenames,DataDir,PrivDir),
ok.
+%% Test bug (#4733) fix for annotating bindings for named fun expressions
+test_named_fun_bind_ann(Config) when is_list(Config) ->
+ Fn = {named_fun,{6,5},
+ 'F',
+ [{clause,{6,9},
+ [{var,{6,11},'Test'}],
+ [],
+ [{var,{7,13},'Test'}]}]},
+ AnnT = erl_syntax_lib:annotate_bindings(Fn, []),
+ [Env, Bound, Free] = erl_syntax:get_ann(AnnT),
+ {'env',[]} = Env,
+ {'bound',[]} = Bound,
+ {'free',[]} = Free,
+
+ NameVar = erl_syntax:named_fun_expr_name(AnnT),
+ Name = erl_syntax:variable_name(NameVar),
+ [NEnv, NBound, NFree] = erl_syntax:get_ann(NameVar),
+ {'env',[]} = NEnv,
+ {'bound',[Name]} = NBound,
+ {'free',[]} = NFree,
+
+ [Clause] = erl_syntax:named_fun_expr_clauses(AnnT),
+ [CEnv, CBound, CFree] = erl_syntax:get_ann(Clause),
+ {'env',[Name]} = CEnv,
+ {'bound',['Test']} = CBound,
+ {'free', []} = CFree.
+
test_files(Config) ->
DataDir = ?config(data_dir, Config),
[ filename:join(DataDir,Filename) || Filename <- test_files() ].
@@ -391,15 +418,16 @@ test_comment_scan([File|Files],DataDir) ->
test_prettypr([],_,_) -> ok;
test_prettypr([File|Files],DataDir,PrivDir) ->
Filename = filename:join(DataDir,File),
+ Options = [res_word_option()],
io:format("Parsing ~p~n", [Filename]),
- {ok, Fs0} = epp:parse_file(Filename, [], []),
+ {ok, Fs0} = epp:parse_file(Filename, Options),
Fs = erl_syntax:form_list(Fs0),
PP = erl_prettypr:format(Fs, [{paper, 120}, {ribbon, 110}]),
io:put_chars(PP),
OutFile = filename:join(PrivDir, File),
ok = file:write_file(OutFile,unicode:characters_to_binary(PP)),
io:format("Parsing OutFile: ~ts~n", [OutFile]),
- {ok, Fs2} = epp:parse_file(OutFile, [], []),
+ {ok, Fs2} = epp:parse_file(OutFile, Options),
case [Error || {error, _} = Error <- Fs2] of
[] ->
ok;
@@ -408,22 +436,23 @@ test_prettypr([File|Files],DataDir,PrivDir) ->
end,
test_prettypr(Files,DataDir,PrivDir).
-
test_epp_dodger([], _, _) -> ok;
test_epp_dodger([Filename|Files],DataDir,PrivDir) ->
io:format("Parsing ~p~n", [Filename]),
+ Options = [{feature, maybe_expr, enable}],
InFile = filename:join(DataDir, Filename),
- Parsers = [{fun epp_dodger:parse_file/1,parse_file},
- {fun epp_dodger:quick_parse_file/1,quick_parse_file},
+ Parsers = [{fun(File) -> epp_dodger:parse_file(File, Options) end,parse_file},
+ {fun(File) -> epp_dodger:quick_parse_file(File,
+ Options) end,quick_parse_file},
{fun (File) ->
{ok,Dev} = file:open(File,[read]),
- Res = epp_dodger:parse(Dev),
+ Res = epp_dodger:parse(Dev, Options),
file:close(File),
Res
end, parse},
{fun (File) ->
{ok,Dev} = file:open(File,[read]),
- Res = epp_dodger:quick_parse(Dev),
+ Res = epp_dodger:quick_parse(Dev, Options),
file:close(File),
Res
end, quick_parse}],
@@ -617,3 +646,9 @@ p_run_loop(Test, List, N, Refs0, Errors0) ->
Refs = Refs0 -- [Ref],
p_run_loop(Test, List, N, Refs, Errors)
end.
+
+res_word_option() ->
+ Options = [{feature, maybe_expr, enable}],
+ {ok, {_Ftrs, ResWordFun}} =
+ erl_features:keyword_fun(Options, fun erl_scan:f_reserved_word/1),
+ {reserved_word_fun, ResWordFun}.
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl b/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl
index 07c419b4b7..9035139fea 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl
@@ -8,6 +8,7 @@
sub_word/2,sub_word/3,left/2,left/3,right/2,right/3,
sub_string/2,sub_string/3,centre/2,centre/3, join/2]).
-export([to_upper/1, to_lower/1]).
+-export([eep49/0]).
-import(lists,[reverse/1,member/2]).
@@ -235,8 +236,8 @@ substr1(String, _L) when is_list(String) -> []. %Be nice!
substr2(String, 1) when is_list(String) -> String;
substr2([_|String], S) -> substr2(String, S-1).
-%% tokens(String, Seperators).
-%% Return a list of tokens seperated by characters in Seperators.
+%% tokens(String, Separators).
+%% Return a list of tokens separated by characters in Separators.
-spec tokens(String, SeparatorList) -> Tokens when
String :: string(),
@@ -538,3 +539,45 @@ join([], Sep) when is_list(Sep) ->
[];
join([H|T], Sep) ->
H ++ lists:append([Sep ++ X || X <- T]).
+
+eep49() ->
+ maybe ok ?= ok end,
+
+ {a,b} =
+ maybe
+ {ok,A} ?= {ok,a},
+ {ok,B} ?= {ok,b},
+ {A,B}
+ end,
+
+ maybe
+ ok ?= {ok,x}
+ else
+ error -> error;
+ {error,_} -> error
+ end,
+
+ maybe
+ ok ?= {ok,x}
+ else
+ error -> error
+ end,
+
+ maybe
+ {ok,X} ?= {ok,x},
+ {ok,Y} ?= {ok,y},
+ {X,Y}
+ else
+ error -> error;
+ {error,_} -> error
+ end,
+
+ maybe
+ {ok,X2} ?= {ok,x},
+ {ok,Y2} ?= {ok,y},
+ {X2,Y2}
+ else
+ error -> error
+ end,
+
+ ok.
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 87a6cb0158..1955fbdbc1 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.6
+SYNTAX_TOOLS_VSN = 3.0.1
diff --git a/lib/tftp/doc/src/notes.xml b/lib/tftp/doc/src/notes.xml
index 71d22fbd97..e74800639b 100644
--- a/lib/tftp/doc/src/notes.xml
+++ b/lib/tftp/doc/src/notes.xml
@@ -33,7 +33,41 @@
<file>notes.xml</file>
</header>
- <section><title>Tftp 1.0.3</title>
+ <section><title>Tftp 1.0.4</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Tftp 1.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/tftp/src/Makefile b/lib/tftp/src/Makefile
index 4ece9ffe28..cfcb1ea134 100644
--- a/lib/tftp/src/Makefile
+++ b/lib/tftp/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2005-2021. All Rights Reserved.
+# Copyright Ericsson AB 2005-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -80,7 +80,7 @@ ERL_COMPILE_FLAGS += \
$(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES)
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(BEHAVIOUR_TARGET_FILES)
diff --git a/lib/tftp/src/tftp.erl b/lib/tftp/src/tftp.erl
index 31e4c651e8..a32d0dca9c 100644
--- a/lib/tftp/src/tftp.erl
+++ b/lib/tftp/src/tftp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -79,7 +79,7 @@
%%% setuid_socket_wrap. Then the command line argument
%%% "-tftpd_69 22" will trigger the prebound file
%%% descriptor 22 to be used instead of opening port 69.
-%%% The UDP option {udp, [{fd, 22}]} autmatically be added.
+%%% The UDP option {udp, [{fd, 22}]} automatically be added.
%%% See init:get_argument/ about command line arguments and
%%% gen_udp:open/2 about UDP options.
%%%
@@ -107,7 +107,7 @@
%%% usage is when used in conjunction with setuid_socket_wrap
%%% to be able to open privileged sockets. For example if the
%%% file descriptor 22 has been opened by setuid_socket_wrap
-%%% and you have choosen my_tftp_fd as init argument, the
+%%% and you have chosen my_tftp_fd as init argument, the
%%% command line should like this "erl -my_tftp_fd 22" and
%%% FileDesc should be set to my_tftpd_fd. This would
%%% automatically imply {fd, 22} to be set as UDP option.
diff --git a/lib/tftp/src/tftp_binary.erl b/lib/tftp/src/tftp_binary.erl
index 3438ba235b..dda64b4252 100644
--- a/lib/tftp/src/tftp_binary.erl
+++ b/lib/tftp/src/tftp_binary.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(I
blksize = lookup_blksize(AcceptedOptions),
bin = Filename,
is_network_ascii = IsNetworkAscii,
- count = size(Filename),
+ count = byte_size(Filename),
is_native_ascii = IsNativeAscii},
{ok, AcceptedOptions, State};
{ok, IsNetworkAscii, AcceptedOptions} when Access =:= write, Filename =:= binary ->
@@ -115,11 +115,11 @@ open(Peer, Access, Filename, Mode, NegotiatedOptions, State) ->
read(#read_state{bin = Bin} = State) when is_binary(Bin) ->
BlkSize = State#read_state.blksize,
if
- size(Bin) >= BlkSize ->
+ byte_size(Bin) >= BlkSize ->
<<Block:BlkSize/binary, Bin2/binary>> = Bin,
State2 = State#read_state{bin = Bin2},
{more, Block, State2};
- size(Bin) < BlkSize ->
+ byte_size(Bin) < BlkSize ->
{last, Bin, State#read_state.count}
end;
read(State) ->
@@ -132,7 +132,7 @@ read(State) ->
%%-------------------------------------------------------------------
write(Bin, #write_state{list = List} = State) when is_binary(Bin), is_list(List) ->
- Size = size(Bin),
+ Size = byte_size(Bin),
BlkSize = State#write_state.blksize,
if
Size =:= BlkSize ->
@@ -182,7 +182,7 @@ do_handle_options(Access, Bin, [{Key, Val} | T]) ->
"tsize" ->
case Access of
read when Val =:= "0", is_binary(Bin) ->
- Tsize = integer_to_list(size(Bin)),
+ Tsize = integer_to_list(byte_size(Bin)),
[{Key, Tsize} | do_handle_options(Access, Bin, T)];
_ ->
handle_integer(Access, Bin, Key, Val, T, 0, infinity)
diff --git a/lib/tftp/src/tftp_engine.erl b/lib/tftp/src/tftp_engine.erl
index 811f91b8bd..f9e5e40d34 100644
--- a/lib/tftp/src/tftp_engine.erl
+++ b/lib/tftp/src/tftp_engine.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1001,7 +1001,7 @@ do_callback(read = Fun, Config, Callback, Req)
NextBlockNo = Callback#callback.block_no + 1,
case catch safe_apply(Callback#callback.module, Fun, Args) of
{more, Bin, NewState} when is_binary(Bin) ->
- Count = Callback#callback.count + size(Bin),
+ Count = Callback#callback.count + byte_size(Bin),
Callback2 = Callback#callback{state = NewState,
block_no = NextBlockNo,
count = Count},
@@ -1035,7 +1035,7 @@ do_callback({write = Fun, Bin}, Config, Callback, Req)
NextBlockNo = Callback#callback.block_no + 1,
case catch safe_apply(Callback#callback.module, Fun, Args) of
{more, NewState} ->
- Count = Callback#callback.count + size(Bin),
+ Count = Callback#callback.count + byte_size(Bin),
Callback2 = Callback#callback{state = NewState,
block_no = NextBlockNo,
count = Count},
@@ -1112,9 +1112,9 @@ do_callback({abort, Error}, _Config, undefined, _Req) when is_record(Error, tftp
peer_info(#config{udp_host = Host, udp_port = Port}) ->
if
- is_tuple(Host), size(Host) =:= 4 ->
+ tuple_size(Host) =:= 4 ->
{inet, tftp_lib:host_to_string(Host), Port};
- is_tuple(Host), size(Host) =:= 8 ->
+ tuple_size(Host) =:= 8 ->
{inet6, tftp_lib:host_to_string(Host), Port};
true ->
{undefined, Host, Port}
@@ -1336,7 +1336,7 @@ print_debug_info(#config{debug_level = Level} = Config, Who, Where, Data) ->
end.
do_print_debug_info(Config, Who, Where, #tftp_msg_data{data = Bin} = Msg) when is_binary(Bin) ->
- Msg2 = Msg#tftp_msg_data{data = {bytes, size(Bin)}},
+ Msg2 = Msg#tftp_msg_data{data = {bytes, byte_size(Bin)}},
do_print_debug_info(Config, Who, Where, Msg2);
do_print_debug_info(Config, Who, Where, #tftp_msg_req{local_filename = Filename} = Msg) when is_binary(Filename) ->
Msg2 = Msg#tftp_msg_req{local_filename = binary},
diff --git a/lib/tftp/src/tftp_file.erl b/lib/tftp/src/tftp_file.erl
index 5922fc9418..b6fb97bfb5 100644
--- a/lib/tftp/src/tftp_file.erl
+++ b/lib/tftp/src/tftp_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@
%% PeerType = inet | inet6
%% PeerHost = ip_address()
%% PeerPort = integer()
-%% Acess = read | write
+%% Access = read | write
%% Filename = string()
%% Mode = string()
%% SuggestedOptions = [{Key, Value}]
@@ -118,7 +118,7 @@ prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(I
%% PeerType = inet | inet6
%% PeerHost = ip_address()
%% PeerPort = integer()
-%% Acess = read | write
+%% Access = read | write
%% Filename = string()
%% Mode = string()
%% SuggestedOptions = [{Key, Value}]
@@ -135,10 +135,10 @@ prepare(_Peer, Access, Filename, Mode, SuggestedOptions, Initial) when is_list(I
%%
%% Opens a file for read or write access.
%%
-%% On the client side where the open/4 call has been preceeded by a
+%% On the client side where the open/4 call has been preceded by a
%% call to prepare/4, all options must be accepted or rejected.
-%% On the server side, where there are no preceeding prepare/4 call,
-%% noo new options may be added, but the ones that are present as
+%% On the server side, where there are no preceding prepare/4 call,
+%% no new options may be added, but the ones that are present as
%% SuggestedOptions may be omitted or replaced with new values
%% in the AcceptedOptions.
%%-------------------------------------------------------------------
@@ -211,12 +211,12 @@ file_error(Reason) when is_atom(Reason) ->
read(#state{access = read} = State) ->
BlkSize = State#state.blksize,
case file:read(State#state.fd, BlkSize) of
- {ok, Bin} when is_binary(Bin), size(Bin) =:= BlkSize ->
- Count = State#state.count + size(Bin),
+ {ok, Bin} when is_binary(Bin), byte_size(Bin) =:= BlkSize ->
+ Count = State#state.count + byte_size(Bin),
{more, Bin, State#state{count = Count}};
- {ok, Bin} when is_binary(Bin), size(Bin) < BlkSize ->
+ {ok, Bin} when is_binary(Bin), byte_size(Bin) < BlkSize ->
_ = file:close(State#state.fd),
- Count = State#state.count + size(Bin),
+ Count = State#state.count + byte_size(Bin),
{last, Bin, Count};
eof ->
{last, <<>>, State#state.count};
@@ -248,7 +248,7 @@ read(State) ->
%%-------------------------------------------------------------------
write(Bin, #state{access = write} = State) when is_binary(Bin) ->
- Size = size(Bin),
+ Size = byte_size(Bin),
BlkSize = State#state.blksize,
case file:write(State#state.fd, Bin) of
ok when Size =:= BlkSize->
diff --git a/lib/tftp/src/tftp_lib.erl b/lib/tftp/src/tftp_lib.erl
index 407a273f58..7c55462c48 100644
--- a/lib/tftp/src/tftp_lib.erl
+++ b/lib/tftp/src/tftp_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -94,9 +94,9 @@ do_parse_config([{Key, Val} | Tail], Config) when is_record(Config, config) ->
if
is_list(Val) ->
do_parse_config(Tail, Config#config{udp_host = Val});
- is_tuple(Val), size(Val) =:= 4 ->
+ tuple_size(Val) =:= 4 ->
do_parse_config(Tail, Config#config{udp_host = Val});
- is_tuple(Val), size(Val) =:= 8 ->
+ tuple_size(Val) =:= 8 ->
do_parse_config(Tail, Config#config{udp_host = Val});
true ->
exit({badarg, {Key, Val}})
diff --git a/lib/tftp/test/Makefile b/lib/tftp/test/Makefile
index 77ec425bac..a3caf45321 100644
--- a/lib/tftp/test/Makefile
+++ b/lib/tftp/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -152,6 +152,7 @@ RELTESTSYSBINDIR = $(RELTESTSYSALLDATADIR)/bin
ERL_COMPILE_FLAGS += \
$(INCLUDES) \
$(TFTP_FLAGS)
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
@@ -161,7 +162,7 @@ ERL_COMPILE_FLAGS += \
# 1) TFTP_PRIV_DIR must be created
# ----------------------------------------------------
-tests debug opt: $(BUILDTARGET)
+tests $(TYPES): $(BUILDTARGET)
targets: $(TARGET_FILES)
diff --git a/lib/tftp/vsn.mk b/lib/tftp/vsn.mk
index d762b85845..d1a14b4255 100644
--- a/lib/tftp/vsn.mk
+++ b/lib/tftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = tftp
-TFTP_VSN = 1.0.3
+TFTP_VSN = 1.0.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(TFTP_VSN)$(PRE_VSN)"
diff --git a/lib/tools/Makefile b/lib/tools/Makefile
index b8625d8074..ebdac6156d 100644
--- a/lib/tools/Makefile
+++ b/lib/tools/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2021. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
# ----------------------------------------------------
-SUB_DIRECTORIES = c_src src doc/src examples emacs
+SUB_DIRECTORIES = src doc/src examples emacs
include vsn.mk
VSN = $(TOOLS_VSN)
@@ -37,5 +37,6 @@ SPECIAL_TARGETS =
include $(ERL_TOP)/make/otp_subdir.mk
DIA_PLT_APPS=compiler runtime_tools
+TEST_NEEDS_RELEASE=true
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/tools/bin/.gitignore b/lib/tools/bin/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/tools/bin/.gitignore
+++ /dev/null
diff --git a/lib/tools/c_src/Makefile b/lib/tools/c_src/Makefile
deleted file mode 100644
index 0cdc50e6f5..0000000000
--- a/lib/tools/c_src/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Invoke with GNU make or clearmake -C gnu.
-#
-
-include $(ERL_TOP)/make/run_make.mk
-
diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in
deleted file mode 100644
index 878aa2cde6..0000000000
--- a/lib/tools/c_src/Makefile.in
+++ /dev/null
@@ -1,221 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 2009-2020. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-
-include $(ERL_TOP)/make/output.mk
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/erts/include/internal/$(TARGET)/ethread.mk
-
-USING_VC=@MIXED_VC@
-
-CC=@CC@
-LD=@LD@
-AR=@AR@
-RANLIB=@RANLIB@
-MKDIR=@MKDIR@
-INSTALL=@INSTALL@
-INSTALL_DIR=@INSTALL_DIR@
-INSTALL_DATA=@INSTALL_DATA@
-INSTALL_PROGRAM=@INSTALL_PROGRAM@
-LDFLAGS=@LDFLAGS@
-
-ifeq ($(TYPE),debug)
-CFLAGS = @DEBUG_CFLAGS@ -DDEBUG
-TYPEMARKER=.debug
-PRE_LD =
-ifeq ($(TARGET),win32)
-LDFLAGS += -g
-endif
-else
-override TYPE=opt
-CFLAGS = @CFLAGS@
-PRE_LD =
-TYPEMARKER =
-endif
-
-ifeq ($(findstring -D_GNU_SOURCE,$(CFLAGS)),)
-THR_DEFS = $(ETHR_DEFS)
-else
-# Remove duplicate -D_GNU_SOURCE
-THR_DEFS = $(filter-out -D_GNU_SOURCE%, $(ETHR_DEFS))
-endif
-
-LIBS=@LIBS@
-CREATE_DIRS=
-
-TT_DIR=$(TARGET)/$(TYPE)
-
-BIN_DIR=../bin/$(TARGET)
-OBJ_DIR=../obj/$(TT_DIR)
-
-CREATE_DIRS += $(BIN_DIR) $(OBJ_DIR)
-
-PROGS=
-DRIVERS=
-
-
-#
-# emem sources, objects, includes, libs, etc...
-#
-
-
-ifneq ($(strip $(ETHR_LIB_NAME)),)
-# Need ethread package for emem
-PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@
-endif
-
-EMEM_OBJ_DIR=$(OBJ_DIR)/emem
-CREATE_DIRS += $(EMEM_OBJ_DIR)
-
-EMEM_INCLUDES = -I$(ERL_TOP)/erts/include \
- -I$(ERL_TOP)/erts/include/$(TARGET) \
- -I$(ERL_TOP)/erts/include/internal \
- -I$(ERL_TOP)/erts/include/internal/$(TARGET)
-
-EMEM_HEADERS = erl_memory_trace_block_table.h
-EMEM_SRCS = erl_memory.c erl_memory_trace_block_table.c
-
-EMEM_CFLAGS = $(THR_DEFS) $(subst O2,O3, $(CFLAGS)) $(EMEM_INCLUDES)
-EMEM_LDFLAGS = $(LDFLAGS)
-
-ifeq ($(USING_VC), yes)
-ifeq ($(TYPE),debug)
-MT_LIB=MDd
-else
-MT_LIB=MD
-endif
-
-EMEM_CFLAGS += -$(MT_LIB)
-EMEM_LDFLAGS += -$(MT_LIB)
-EMEM_ERTS_LIB=erts_$(MT_LIB)$(TYPEMARKER)
-
-else
-
-EMEM_ERTS_LIB=erts_r$(TYPEMARKER)
-
-endif
-
-EMEM_ETHR_LIBS=$(subst -l$(ETHR_LIB_NAME),-l$(ETHR_LIB_NAME)$(TYPEMARKER),$(subst -lerts_internal_r,-lerts_internal_r$(TYPEMARKER),$(ETHR_LIBS)))
-
-EMEM_LIBS = $(LIBS) \
- -L$(ERL_TOP)/erts/lib/$(TARGET) \
- -L$(ERL_TOP)/erts/lib/internal/$(TARGET) \
- -l$(EMEM_ERTS_LIB) \
- $(EMEM_ETHR_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: $(PROGS) $(DRIVERS)
-
-$(ERTS_LIB):
- $(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE)
-
-
-docs:
-
-clean:
- $(RM) -r ../obj/*
- $(RM) -r ../bin/*
- $(RM) ./*~
-
-.PHONY: all erts_lib docs clean
-
-#
-# Object targets
-#
-
-$(EMEM_OBJ_DIR)/%.o: %.c
- $(V_CC) $(EMEM_CFLAGS) -o $@ -c $<
-
-#
-# Driver targets
-#
-
-#
-# Program targets
-#
-
-$(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@: $(EMEM_OBJS) $(ERTS_LIB)
- $(ld_verbose)$(PRE_LD) $(LD) $(EMEM_LDFLAGS) -o $@ $(EMEM_OBJS) $(EMEM_LIBS)
-
-#
-# Release targets
-#
-include $(ERL_TOP)/make/otp_release_targets.mk
-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"
-ifneq ($(PROGS),)
- $(INSTALL_DIR) "$(RELSYSDIR)/bin"
- $(INSTALL_PROGRAM) $(PROGS) "$(RELSYSDIR)/bin"
-endif
-
-release_docs_spec:
-
-.PHONY: release_spec release_docs_spec
-
-#
-# Make dependencies
-#
-
-ifeq ($(USING_VC), yes)
-DEP_CC=@EMU_CC@
-else
-DEP_CC=$(CC)
-endif
-
-SED_REPL_EMEM_OBJ_DIR=s|^\([^:]*\)\.o:|$$(EMEM_OBJ_DIR)/\1.o:|g
-SED_REPL_OBJ_DIR=s|^\([^:]*\)\.o:|$$(OBJ_DIR)/\1.o:|g
-SED_REPL_TT_DIR=s|$(TT_DIR)/|$$(TT_DIR)/|g
-SED_REPL_TARGET=s|$(TARGET)/|$$(TARGET)/|g
-SED_REPL_ERL_TOP=s|$(ERL_TOP)/|$$(ERL_TOP)/|g
-
-SED_EMEM_DEPEND=sed '$(SED_REPL_EMEM_OBJ_DIR);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET);$(SED_REPL_ERL_TOP)'
-SED_DEPEND=sed '$(SED_REPL_OBJ_DIR);$(SED_REPL_TT_DIR);$(SED_REPL_TARGET);$(SED_REPL_ERL_TOP)'
-
-DEPEND_MK=depend.mk
-
-dep depend:
- [ $(v_p) == 0 ] && echo " GEN "$(DEPEND_MK)
- $(V_colon)@echo "Generating dependency file $(DEPEND_MK)..."
- @echo "# Generated dependency rules." > $(DEPEND_MK);
- @echo "# Do *not* edit this file; instead, run 'make depend'." \
- >> $(DEPEND_MK);
- @echo "# " >> $(DEPEND_MK);
- @echo "# emem objects..." >> $(DEPEND_MK);
- $(DEP_CC) -MM $(EMEM_CFLAGS) $(EMEM_SRCS) \
- | $(SED_EMEM_DEPEND) >> $(DEPEND_MK)
- @echo "# EOF" >> $(DEPEND_MK);
-
-.PHONY: dep depend
-
-include $(DEPEND_MK)
-
-# eof
diff --git a/lib/tools/c_src/depend.mk b/lib/tools/c_src/depend.mk
deleted file mode 100644
index 01da30e7c6..0000000000
--- a/lib/tools/c_src/depend.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated dependency rules.
-# Do *not* edit this file; instead, run 'make depend'.
-#
-# emem objects...
-$(EMEM_OBJ_DIR)/erl_memory.o: erl_memory.c \
- $(ERL_TOP)/erts/include/erl_fixed_size_int_types.h \
- $(ERL_TOP)/erts/include/$(TARGET)/erl_int_sizes_config.h \
- $(ERL_TOP)/erts/include/erl_memory_trace_parser.h \
- erl_memory_trace_block_table.h \
- $(ERL_TOP)/erts/include/internal/ethread.h \
- $(ERL_TOP)/erts/include/internal/$(TARGET)/ethread_header_config.h
-$(EMEM_OBJ_DIR)/erl_memory_trace_block_table.o: erl_memory_trace_block_table.c \
- erl_memory_trace_block_table.h \
- $(ERL_TOP)/erts/include/erl_fixed_size_int_types.h \
- $(ERL_TOP)/erts/include/$(TARGET)/erl_int_sizes_config.h \
- $(ERL_TOP)/erts/include/erl_memory_trace_parser.h
-# EOF
diff --git a/lib/tools/c_src/erl_memory.c b/lib/tools/c_src/erl_memory.c
deleted file mode 100644
index bbd4b3f2ef..0000000000
--- a/lib/tools/c_src/erl_memory.c
+++ /dev/null
@@ -1,2947 +0,0 @@
-/*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2003-2021. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
-
-/*
- * Description:
- *
- * Author: Rickard Green
- */
-
-/* Headers to include ... */
-
-#ifdef __WIN32__
-# include <winsock2.h>
-# undef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-typedef int socklen_t;
-#else
-# if defined(__linux__) && defined(__GNUC__)
-# define _GNU_SOURCE 1
-# endif
-# include <unistd.h>
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <fcntl.h>
-# include <netdb.h>
-# include <arpa/inet.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-
-#include "erl_fixed_size_int_types.h"
-#include "erl_memory_trace_parser.h"
-#include "erl_memory_trace_block_table.h"
-#include "ethread.h"
-
-/* Increment when changes are made */
-#define EMEM_VSN_STR "0.9"
-
-/* Features not fully implemented yet */
-#define EMEM_A_SWITCH 0
-#define EMEM_C_SWITCH 0
-#define EMEM_c_SWITCH 0
-#define EMEM_d_SWITCH 0
-
-/* Some system specific defines ... */
-#ifdef __WIN32__
-# define ssize_t int
-# define GET_SOCK_ERRNO() (WSAGetLastError() - WSABASEERR)
-# define IS_INVALID_SOCKET(X) ((X) == INVALID_SOCKET)
-# ifdef __GNUC__
-# define INLINE __inline__
-# else
-# define INLINE __forceinline
-# endif
-# define DIR_SEP_CHAR '\\'
-#else
-# define SOCKET int
-# define closesocket close
-# define GET_SOCK_ERRNO() (errno ? errno : INT_MAX)
-# define INVALID_SOCKET (-1)
-# define IS_INVALID_SOCKET(X) ((X) < 0)
-# ifdef __GNUC__
-# define INLINE __inline__
-# else
-# define INLINE
-# endif
-# define DIR_SEP_CHAR '/'
-#endif
-
-#define EM_ERL_CMD_FILE_NAME "erl_cmd.txt"
-#define EM_OUTPUT_FILE_SUFFIX ".emem"
-
-#define PRINT_OPERATIONS 0
-
-/* In VC++, noreturn is a declspec that has to be before the types,
- * but in GNUC it is an attribute to be placed between return type
- * and function name, hence __decl_noreturn <types> __noreturn <function name>
- *
- * at some platforms (e.g. Android) __noreturn is defined at sys/cdef.h
- */
-#if __GNUC__
-# define __decl_noreturn
-# ifndef __noreturn
-# define __noreturn __attribute__((noreturn))
-# endif
-#else
-# if defined(__WIN32__) && defined(_MSC_VER)
-# define __noreturn
-# define __decl_noreturn __declspec(noreturn)
-# else
-# define __noreturn
-# define __decl_noreturn
-# endif
-#endif
-
-/* Our own assert() ... */
-#ifdef DEBUG
-#define ASSERT(A) ((A) ? (void)1 : assert_failed(__FILE__, __LINE__, #A))
-#include <stdio.h>
-__decl_noreturn static void __noreturn assert_failed(char *f, int l, char *a)
-{
- fprintf(stderr, "%s:%d: Assertion failed: %s\n", f, l, a);
- abort();
-}
-
-#else
-#define ASSERT(A) ((void) 1)
-#endif
-
-#define ERR_RET(X) return (X)
-#if 1
-# undef ERR_RET
-# define ERR_RET(X) abort()
-#endif
-
-/* #define HARD_DEBUG */
-
-
-#define EM_EXIT_RESULT (EMTBT_MIN_ERROR - 1)
-#define EM_TRUNCATED_TRACE_ERROR (EMTBT_MIN_ERROR - 2)
-#define EM_INTERNAL_ERROR (EMTBT_MIN_ERROR - 3)
-
-#define EM_DEFAULT_BUF_SZ 8192
-
-#define EM_LINES_UNTIL_HEADER 20
-#define EM_NO_OF_OPS 400
-#define EM_MAX_CONSECUTIVE_TRACE_READS 10
-#define EM_MAX_NO_OF_TRACE_BUFS 1280
-#define EM_MIN_TRACE_READ_SIZE (EM_DEFAULT_BUF_SZ/20)
-#define EM_TIME_FIELD_WIDTH 11
-
-__decl_noreturn static void __noreturn error(int res);
-__decl_noreturn static void __noreturn error_msg(int res, char *msg);
-
-typedef struct {
- usgnd_int_max size;
- usgnd_int_max min_size;
- usgnd_int_max max_size;
- usgnd_int_max max_ever_size;
- usgnd_int_max no;
- usgnd_int_max min_no;
- usgnd_int_max max_no;
- usgnd_int_max max_ever_no;
- usgnd_int_max allocs;
- usgnd_int_max reallocs;
- usgnd_int_max frees;
-} em_mem_info;
-
-typedef struct em_buffer_ {
- struct em_buffer_ *next;
- int write;
- char *data;
- char *data_end;
- char *end;
- size_t size;
- char start[EM_DEFAULT_BUF_SZ];
-} em_buffer;
-
-typedef struct {
- int no_writer;
- int no_reader;
- size_t tot_buf_size;
- size_t max_buf_size;
- char *name;
- em_buffer *first;
- em_buffer *last;
- ethr_mutex mutex;
- ethr_cond cond;
- int used_def_buf_a;
- em_buffer def_buf_a;
- int used_def_buf_b;
- em_buffer def_buf_b;
-} em_buf_queue;
-
-typedef struct {
- char *ptr;
- size_t size;
-} em_area;
-
-typedef struct {
- char *name;
- int ix;
-} em_output_types;
-
-typedef struct {
-
- /* Memory allocation functions */
- void * (*alloc)(size_t);
- void * (*realloc)(void *, size_t);
- void (*free)(void *);
-
- emtbt_table *block_table;
- emtbt_table **carrier_table;
-
- struct {
- em_mem_info total;
- em_mem_info *btype;
- em_mem_info *allctr;
- em_mem_info **allctr_prv_crr;
- em_mem_info **allctr_usd_crr;
-
- struct {
- usgnd_int_32 secs;
- usgnd_int_32 usecs;
- } stop_time;
- emtp_op_type stop_reason;
- usgnd_int_32 exit_status;
- } info;
-
- /* Input ... */
- struct {
- usgnd_int_16 listen_port;
- SOCKET socket;
- usgnd_int_max total_trace_size;
- int error;
- char *error_descr;
- em_buf_queue queue;
- } input;
-
- /* Output ... */
- struct {
- usgnd_int_32 next_print;
- usgnd_int_32 next_print_inc;
- char *header;
- size_t header_size;
- size_t values_per_object;
- size_t values_per_line;
- size_t field_width;
- int verbose;
- int total;
- int all_allctrs;
- int no_allctrs;
- em_output_types *allctrs;
- int all_btypes;
- int no_btypes;
- em_output_types *btypes;
- int max_min_values;
- int block_counts;
- int op_counts;
- int lines_until_header;
- FILE *stream;
- char *file_name;
-#if EMEM_d_SWITCH
- char *dir_name;
- FILE *erl_cmd_file;
- struct {
- ethr_mutex *mutex;
- ethr_cond *cond;
- } go;
-#endif
- em_buf_queue queue;
- } output;
-
- /* Trace info */
- emtp_state *trace_state;
- emtp_info trace_info;
-
-} em_state;
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * Threads... *
- * *
-\* */
-
-static INLINE void
-mutex_init(ethr_mutex *mtx)
-{
- int res = ethr_mutex_init(mtx);
- if (res)
- error_msg(res, "Mutex init");
-}
-
-static INLINE void
-mutex_destroy(ethr_mutex *mtx)
-{
- int res = ethr_mutex_destroy(mtx);
- if (res)
- error_msg(res, "Mutex destroy");
-}
-
-static INLINE void
-mutex_lock(ethr_mutex *mtx)
-{
- ethr_mutex_lock(mtx);
-}
-
-static INLINE void
-mutex_unlock(ethr_mutex *mtx)
-{
- ethr_mutex_unlock(mtx);
-}
-
-static INLINE void
-cond_init(ethr_cond *cnd)
-{
- int res = ethr_cond_init(cnd);
- if (res)
- error_msg(res, "Cond init");
-}
-
-static INLINE void
-cond_destroy(ethr_cond *cnd)
-{
- int res = ethr_cond_destroy(cnd);
- if (res)
- error_msg(res, "Cond destroy");
-}
-
-static INLINE void
-cond_wait(ethr_cond *cnd, ethr_mutex *mtx)
-{
- int res = ethr_cond_wait(cnd, mtx);
- if (res != 0 && res != EINTR)
- error_msg(res, "Cond wait");
-}
-
-static INLINE void
-cond_signal(ethr_cond *cnd)
-{
- ethr_cond_signal(cnd);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * Buffer queues *
- * *
-\* */
-
-static INLINE void
-reset_buffer(em_buffer *b, size_t size)
-{
- b->write = 1;
- b->next = NULL;
- if (size) {
- b->size = size;
- b->end = b->start + size;
- }
- b->data_end = b->data = b->start;
-}
-
-static void
-init_queue(em_state *state, em_buf_queue *queue)
-{
- reset_buffer(&queue->def_buf_a, EM_DEFAULT_BUF_SZ);
- reset_buffer(&queue->def_buf_b, EM_DEFAULT_BUF_SZ);
- queue->first = NULL;
- queue->last = NULL;
- queue->no_writer = 0;
- queue->no_reader = 0;
- queue->tot_buf_size = 0;
- queue->max_buf_size = ~0;
- queue->name = "";
- queue->used_def_buf_a = 0;
- queue->used_def_buf_b = 0;
- mutex_init(&queue->mutex);
- cond_init(&queue->cond);
-}
-
-static void
-destroy_queue(em_state *state, em_buf_queue *queue)
-{
- while (queue->first) {
- em_buffer *buf = queue->first;
- queue->first = queue->first->next;
- if (buf != &queue->def_buf_a && buf != &queue->def_buf_b)
- (*state->free)((void *) buf);
- }
- mutex_destroy(&queue->mutex);
- cond_destroy(&queue->cond);
-}
-
-static void
-disconnect_queue_writer(em_buf_queue *queue)
-{
- mutex_lock(&queue->mutex);
- queue->no_writer = 1;
- cond_signal(&queue->cond);
- mutex_unlock(&queue->mutex);
-}
-
-static void
-disconnect_queue_reader(em_buf_queue *queue)
-{
- mutex_lock(&queue->mutex);
- queue->no_reader = 1;
- cond_signal(&queue->cond);
- mutex_unlock(&queue->mutex);
-}
-
-static int
-is_queue_writer_disconnected(em_buf_queue *queue)
-{
- int res;
- mutex_lock(&queue->mutex);
- res = queue->no_writer;
- mutex_unlock(&queue->mutex);
- return res;
-}
-
-static int
-is_queue_reader_disconnected(em_buf_queue *queue)
-{
- int res;
- mutex_lock(&queue->mutex);
- res = queue->no_reader;
- mutex_unlock(&queue->mutex);
- return res;
-}
-
-static INLINE void
-dequeue(em_state *state, em_buf_queue *queue)
-{
- em_buffer *buf;
-
- ASSERT(queue->first);
- ASSERT(queue->tot_buf_size > 0);
-
- buf = queue->first;
- queue->first = buf->next;
- if (!queue->first)
- queue->last = NULL;
-
- ASSERT(queue->tot_buf_size >= buf->size);
- queue->tot_buf_size -= buf->size;
-
- if (buf == &queue->def_buf_a)
- queue->used_def_buf_a = 0;
- else if (buf == &queue->def_buf_b)
- queue->used_def_buf_b = 0;
- else
- (*state->free)((void *) buf);
-
-}
-
-
-static INLINE em_buffer *
-enqueue(em_state *state, em_buf_queue *queue, size_t min_size)
-{
- em_buffer *buf;
-
- if (min_size > EM_DEFAULT_BUF_SZ)
- goto alloc_buf;
-
- if (!queue->used_def_buf_a) {
- buf = &queue->def_buf_a;
- queue->used_def_buf_a = 1;
- reset_buffer(buf, 0);
- }
- else if (!queue->used_def_buf_b) {
- buf = &queue->def_buf_b;
- queue->used_def_buf_b = 1;
- reset_buffer(buf, 0);
- }
- else {
- size_t bsize;
- alloc_buf:
-
- bsize = EM_DEFAULT_BUF_SZ;
- if (bsize < min_size)
- bsize = min_size;
-
- buf = (em_buffer *) (*state->alloc)(sizeof(em_buffer)
- + (sizeof(char)
- * (bsize-EM_DEFAULT_BUF_SZ)));
- if (!buf)
- error(ENOMEM);
- buf->size = bsize;
- reset_buffer(buf, bsize);
- }
-
- if (queue->last) {
- ASSERT(queue->first);
- queue->last->write = 0;
- queue->last->next = buf;
- }
- else {
- ASSERT(!queue->first);
- queue->first = buf;
- }
-
- queue->tot_buf_size += buf->size;
- queue->last = buf;
-
- return buf;
-}
-
-static void
-get_next_read_area(em_area *area, em_state *state, em_buf_queue *queue)
-{
- mutex_lock(&queue->mutex);
-
- while (!queue->first || queue->first->data == queue->first->data_end) {
- if (queue->first && (!queue->first->write
- || queue->first->data == queue->first->end)) {
- dequeue(state, queue);
- continue;
- }
-
- if (queue->no_writer) {
- area->ptr = NULL;
- area->size = 0;
- mutex_unlock(&queue->mutex);
- return;
- }
- cond_wait(&queue->cond, &queue->mutex);
- }
-
- ASSERT(queue->first->data < queue->first->data_end);
-
- area->ptr = queue->first->data;
- area->size = queue->first->data_end - queue->first->data;
-
- queue->first->data = queue->first->data_end;
-
- mutex_unlock(&queue->mutex);
-}
-
-static INLINE void
-wrote_area_aux(em_area *area, em_state *state, em_buf_queue *queue, int do_lock)
-{
- em_buffer *buf;
-
- if (do_lock)
- mutex_lock(&queue->mutex);
-
- buf = queue->last;
-
- ASSERT(area->ptr);
- ASSERT(area->size);
-
- ASSERT(buf);
- ASSERT(buf->data_end == area->ptr);
- ASSERT(buf->end >= area->ptr + area->size);
-
- buf->data_end = area->ptr + area->size;
-
- area->ptr = NULL;
- area->size = 0;
-
- cond_signal(&queue->cond);
-
- if (do_lock)
- mutex_unlock(&queue->mutex);
-}
-
-static INLINE void
-wrote_area(em_area *area, em_state *state, em_buf_queue *queue)
-{
- wrote_area_aux(area, state, queue, 1);
-}
-
-static void
-get_next_write_area(em_area *area, em_state *state, em_buf_queue *queue,
- size_t size)
-{
- em_buffer *buf;
-
- mutex_lock(&queue->mutex);
-
- ASSERT(!area->size || area->ptr);
-
- if (area->size)
- wrote_area_aux(area, state, queue, 0);
-
- buf = ((queue->last && queue->last->end - queue->last->data_end >= size)
- ? queue->last
- : enqueue(state, queue, size));
-
- ASSERT(buf);
- ASSERT(buf->end - buf->data_end >= size);
- area->ptr = buf->data_end;
- area->size = buf->end - buf->data_end;
-
- if (queue->tot_buf_size > queue->max_buf_size) {
- fprintf(stderr,
- "emem: Maximum %s buffer size (%lu) exceeded. "
- "Terminating...\n",
- queue->name,
- (unsigned long) queue->max_buf_size);
- exit(1);
- }
-
- mutex_unlock(&queue->mutex);
-
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * Output *
- * *
-\* */
-
-static INLINE size_t
-write_str(char **dstpp, char *srcp)
-{
- size_t i = 0;
- if (dstpp)
- while (srcp[i])
- *((*dstpp)++) = srcp[i++];
- else
- while (srcp[i]) i++;
- return i;
-}
-
-
-static size_t
-write_strings(char **ptr,
- char **strings,
- char *first_line_prefix,
- char *line_prefix,
- size_t max_line_size)
-{
- size_t size;
- size_t tot_size = 0;
- size_t line_size = 0;
- size_t line_prefix_size;
- sgnd_int_32 ix;
-
- tot_size = line_size = line_prefix_size = write_str(ptr, first_line_prefix);
-
- for (ix = 0; strings[ix]; ix++) {
- size = write_str(NULL, strings[ix]);
- if (line_size + 1 + size > max_line_size) {
- tot_size += write_str(ptr, "\n");
- tot_size += write_str(ptr, line_prefix);
- line_size = line_prefix_size;
- }
- tot_size += write_str(ptr, " ");
- tot_size += ptr ? write_str(ptr, strings[ix]) : size;
- line_size += 1 + size;
- }
-
- tot_size += write_str(ptr, "\n");
-
- return tot_size;
-}
-
-static size_t
-write_title(char **bufp, size_t *overflow, size_t width, char *str)
-{
- size_t i, sz, ws;
- char *p, *endp;
-
- /*
- * Writes at least one '|' character at the beginning.
- * Right aligns "str".
- * If "str" is larger than "width - 1" and overflow is NULL,
- * then "str" is trucated; otherwise, string is not truncated.
- */
-
- if (width <= 0)
- return 0;
-
- if (!bufp && !overflow)
- return width;
-
- sz = strlen(str) + 1;
- if (sz > width) {
- ws = 0;
- if (overflow)
- *overflow += sz - width;
- else
- sz = width;
- }
- else {
- ws = width - sz;
- if (overflow) {
- if (ws >= *overflow) {
- ws -= *overflow;
- *overflow = 0;
- }
- else {
- *overflow -= ws;
- ws = 0;
- }
- }
- sz += ws;
- }
- if (!bufp)
- return sz;
-
- p = *bufp;
- endp = p + width;
-
- *(p++) = '|';
- while (ws > 1) {
- ws--;
- *(p++) = ' ';
- }
-
- i = 0;
- while (str[i] && (overflow || p < endp))
- *(p++) = str[i++];
-
- while (ws) {
- ws--;
- *(p++) = ' ';
- }
-
- ASSERT(overflow || p == endp);
- ASSERT(sz == (size_t) (p - *bufp));
- *bufp = p;
- return sz;
-}
-
-static size_t
-write_obj_sub_titles(em_state *state, char **bufp, size_t *overflow)
-{
- size_t field_width = state->output.field_width;
- size_t size = write_title(bufp, overflow, field_width, "size");
- if (state->output.max_min_values) {
- size += write_title(bufp, overflow, field_width, "min size");
- size += write_title(bufp, overflow, field_width, "max size");
- }
- if (state->output.block_counts) {
- size += write_title(bufp, overflow, field_width, "no");
- if (state->output.max_min_values) {
- size += write_title(bufp, overflow, field_width, "min no");
- size += write_title(bufp, overflow, field_width, "max no");
- }
- }
- if (state->output.op_counts) {
- size += write_title(bufp, overflow, field_width, "alloc()");
- size += write_title(bufp, overflow, field_width, "realloc()");
- size += write_title(bufp, overflow, field_width, "free()");
- }
-
- return size;
-}
-
-static size_t
-write_header(em_state *state, char *ptr, int trunc)
-{
-#define MIN_LTEXT_SZ 18
-#define HEADER_EOL_STR "|\n"
- char *p;
- char **pp;
- int i;
- size_t overflow;
- size_t *ofp;
- size_t obj_size = state->output.values_per_object*state->output.field_width;
- size_t size = 0;
- int have_seg_crr = state->trace_info.have_segment_carrier_info;
-
- if (ptr) {
- p = ptr;
- pp = &p;
- }
- else {
- p = NULL;
- pp = NULL;
- }
-
- overflow = 0;
- ofp = trunc ? NULL : &overflow;
-
- size += write_title(pp, ofp, EM_TIME_FIELD_WIDTH, "time");
-
- if (state->output.total) {
- int no = 1;
- if (have_seg_crr) {
- if (state->info.allctr_prv_crr[state->trace_info.segment_ix])
- no++;
- if (state->info.allctr_usd_crr[state->trace_info.segment_ix])
- no++;
- }
- size += write_title(pp, ofp, (have_seg_crr ? 3 : 1)*obj_size, "total");
- }
-
- for (i = 0; i < state->output.no_allctrs; i++) {
- int no = 1;
- if (state->info.allctr_prv_crr[state->output.allctrs[i].ix])
- no++;
- if (state->info.allctr_usd_crr[state->output.allctrs[i].ix])
- no++;
- size += write_title(pp, ofp, no*obj_size, state->output.allctrs[i].name);
- }
-
- for (i = 0; i < state->output.no_btypes; i++)
- size += write_title(pp, ofp, obj_size, state->output.btypes[i].name);
-
- size += write_str(pp, HEADER_EOL_STR);
-
- overflow = 0;
- size += write_title(pp, ofp, EM_TIME_FIELD_WIDTH, "");
-
- if (state->output.total) {
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "alcd blks"
- : "allocated blocks"));
- if (have_seg_crr) {
- if (state->info.allctr_prv_crr[state->trace_info.segment_ix])
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "mpd segs"
- : "mapped segments"));
- if (state->info.allctr_usd_crr[state->trace_info.segment_ix])
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "chd segs"
- : "cached segments"));
- }
- }
-
- for (i = 0; i < state->output.no_allctrs; i++) {
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "alcd blks"
- : "allocated blocks"));
- if (state->info.allctr_prv_crr[state->output.allctrs[i].ix])
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "prvd crrs"
- : "provided carriers"));
- if (state->info.allctr_usd_crr[state->output.allctrs[i].ix])
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "usd crrs"
- : "used carriers"));
- }
- for (i = 0; i < state->output.no_btypes; i++)
- size += write_title(pp, ofp, obj_size, (obj_size <= MIN_LTEXT_SZ
- ? "alcd blks"
- : "allocated blocks"));
-
-
- size += write_str(pp, HEADER_EOL_STR);
- overflow = 0;
- size += write_title(pp, ofp, EM_TIME_FIELD_WIDTH, "");
-
- if (state->output.total) {
- size += write_obj_sub_titles(state, pp, ofp);
- if (have_seg_crr) {
- if (state->info.allctr_prv_crr[state->trace_info.segment_ix])
- size += write_obj_sub_titles(state, pp, ofp);
- if (state->info.allctr_usd_crr[state->trace_info.segment_ix])
- size += write_obj_sub_titles(state, pp, ofp);
- }
- }
-
- for (i = 0; i < state->output.no_allctrs; i++) {
- size += write_obj_sub_titles(state, pp, ofp);
- if (state->info.allctr_prv_crr[state->output.allctrs[i].ix])
- size += write_obj_sub_titles(state, pp, ofp);
- if (state->info.allctr_usd_crr[state->output.allctrs[i].ix])
- size += write_obj_sub_titles(state, pp, ofp);
- }
-
- for (i = 0; i < state->output.no_btypes; i++)
- size += write_obj_sub_titles(state, pp, ofp);
-
- size += write_str(pp, HEADER_EOL_STR);
-#undef MIN_LTEXT_SZ
-#undef HEADER_EOL_STR
- return size;
-}
-
-static INLINE void
-write_mem_info(em_state *state, char **p, em_mem_info *mi)
-{
- int fw = state->output.field_width - 1;
- *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->size);
- if (state->output.max_min_values)
- *p += sprintf(*p,
- "%*" USGND_INT_MAX_FSTR
- " %*" USGND_INT_MAX_FSTR " ",
- fw, mi->min_size,
- fw, mi->max_size);
- if (state->output.block_counts) {
- *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->no);
- if (state->output.max_min_values)
- *p += sprintf(*p,
- "%*" USGND_INT_MAX_FSTR
- " %*" USGND_INT_MAX_FSTR " ",
- fw, mi->min_no,
- fw, mi->max_no);
- }
- if (state->output.op_counts)
- *p += sprintf(*p,
- "%*" USGND_INT_MAX_FSTR
- " %*" USGND_INT_MAX_FSTR
- " %*" USGND_INT_MAX_FSTR " ",
- fw, mi->allocs,
- fw, mi->reallocs,
- fw, mi->frees);
-
- /* Update max ever values */
- if (mi->max_ever_size < mi->max_size)
- mi->max_ever_size = mi->max_size;
- if (mi->max_ever_no < mi->max_no)
- mi->max_ever_no = mi->max_no;
- /* Reset max/min values */
- mi->max_size = mi->min_size = mi->size;
- mi->max_no = mi->min_no = mi->no;
-}
-
-static INLINE void
-write_max_ever_mem_info(em_state *state, char **p, em_mem_info *mi)
-{
- int fw = state->output.field_width - 1;
- *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->max_ever_size);
- if (state->output.max_min_values)
- *p += sprintf(*p, "%*s %*s ", fw, "", fw, "");
- if (state->output.block_counts) {
- *p += sprintf(*p, "%*" USGND_INT_MAX_FSTR " ", fw, mi->max_ever_no);
- if (state->output.max_min_values)
- *p += sprintf(*p, "%*s %*s ", fw, "", fw, "");
- }
- if (state->output.op_counts)
- *p += sprintf(*p, "%*s %*s %*s ", fw, "", fw, "", fw, "");
-}
-
-static void
-print_string(em_state *state, char *str)
-{
- em_area area = {NULL, 0};
- char *p;
-
- /* Get area */
-
- get_next_write_area(&area,state,&state->output.queue,write_str(NULL,str));
-
- p = area.ptr;
- area.size = write_str(&p, str);
-
- /* Leave area */
-
- wrote_area(&area, state, &state->output.queue);
-
-}
-
-static int
-print_emu_arg(em_state *state)
-{
- em_area area = {NULL, 0};
- char hostname[100];
- char carg[22];
- struct sockaddr_in saddr;
- struct hostent *hp;
- struct in_addr iaddr;
- usgnd_int_16 port;
- socklen_t saddr_size = sizeof(saddr);
- size_t size;
- char *format = "> Emulator command line argument: +Mit %s\n";
-
-#ifdef __clang_analyzer__
- /* CodeChecker does not seem to understand getsockname writes to saddr */
- memset(&saddr, 0, sizeof(saddr));
-#endif
- if (getsockname(state->input.socket,
- (struct sockaddr *) &saddr,
- &saddr_size) != 0)
- goto error;
-
- port = ntohs(saddr.sin_port);
-
- ASSERT(state->input.listen_port == 0 || state->input.listen_port == port);
-
- state->input.listen_port = port;
-
- if (gethostname(hostname, sizeof(hostname)) != 0)
- goto error;
-
- hp = gethostbyname(hostname);
- if (!hp)
- goto error;
-
- if (hp->h_addr_list) {
- (void) memcpy(&iaddr.s_addr, *hp->h_addr_list, sizeof(iaddr.s_addr));
- (void) sprintf(carg, "%s:%d", inet_ntoa(iaddr), (int) port);
- }
- else
- (void) sprintf(carg, "127.0.0.1:%d", (int) port);
-
-#if EMEM_d_SWITCH
-
- if (state->output.erl_cmd_file) {
- fprintf(state->output.erl_cmd_file, "+Mit %s\n", carg);
- fclose(state->output.erl_cmd_file);
- state->output.erl_cmd_file = NULL;
- }
-
-#endif
-
- size = strlen(format) + strlen(carg);
-
- /* Get area */
-
- get_next_write_area(&area, state, &state->output.queue, size);
-
- area.size = sprintf(area.ptr, format, carg);
-
- /* Leave area */
-
- wrote_area(&area, state, &state->output.queue);
-
- return 0;
-
- error:
- return GET_SOCK_ERRNO();
-}
-
-static size_t
-write_allocator_info(em_state *state, char *ptr)
-{
- usgnd_int_32 aix, i, j;
- char *header = "> Allocator information:\n";
- char *allctr_str = "> * Allocator:";
- char *crr_prv_str = "> * Carrier providers:";
- char *blk_tp_str = "> * Block types:";
- char *line_prefix = "> ";
- size_t size = 0;
- char **strings;
- size_t strings_size;
- size_t max_line_size = 80;
- char *p = ptr;
- char **pp = ptr ? &p : NULL;
-
- strings_size = state->trace_info.max_block_type_ix + 1;
- if (strings_size < state->trace_info.max_allocator_ix + 1)
- strings_size = state->trace_info.max_allocator_ix + 1;
-
- strings = (char **) (*state->alloc)((strings_size + 1)*sizeof(char *));
- if (!strings)
- error(ENOMEM);
-
- size += write_str(pp, header);
-
- for (aix = 0; aix <= state->trace_info.max_allocator_ix; aix++) {
- emtp_allocator *allctr = state->trace_info.allocator[aix];
- if (!allctr->valid)
- continue;
-
- strings[0] = allctr->name;
- strings[1] = NULL;
- size += write_strings(pp,strings,allctr_str,line_prefix,max_line_size);
-
- i = 0;
- if (allctr->carrier.provider)
- for (j = 0; j < allctr->carrier.no_providers; j++) {
- usgnd_int_32 cpix = allctr->carrier.provider[j];
- if (cpix == state->trace_info.segment_ix)
- strings[i++] = "segment";
- else
- strings[i++] = state->trace_info.allocator[cpix]->name;
- }
- strings[i] = NULL;
- size += write_strings(pp,strings,crr_prv_str,line_prefix,max_line_size);
-
- i = 0;
- for (j = 0; j <= state->trace_info.max_block_type_ix; j++)
- if (state->trace_info.block_type[j]->allocator == aix)
- strings[i++] = state->trace_info.block_type[j]->name;
- strings[i] = NULL;
- size += write_strings(pp,strings,blk_tp_str,line_prefix,max_line_size);
- }
-
- (*state->free)((void *) strings);
-
- return size;
-}
-
-static void
-print_main_header(em_state *state)
-{
-#if HAVE_INT_64
-#define MAX_WORD_SZ_STR "64"
-#else
-#define MAX_WORD_SZ_STR "32"
-#endif
- em_area area = {NULL, 0};
- char *format1 =
- "> emem version: " EMEM_VSN_STR "\n"
- "> Nodename: %s\n"
- "> Hostname: %s\n"
- "> Pid: %s\n"
- "> Start time (UTC): ";
- char *format2 = "%4.4" USGND_INT_32_FSTR
- "-%2.2" USGND_INT_32_FSTR "-%2.2" USGND_INT_32_FSTR
- " %2.2" USGND_INT_32_FSTR ":%2.2" USGND_INT_32_FSTR
- ":%2.2" USGND_INT_32_FSTR ".%6.6" USGND_INT_32_FSTR "\n";
- char *format3 =
- "> Trace parser version: %" USGND_INT_32_FSTR ".%" USGND_INT_32_FSTR
- "\n"
- "> Actual trace version: %" USGND_INT_32_FSTR ".%" USGND_INT_32_FSTR
- "\n"
- "> Maximum trace word size: " MAX_WORD_SZ_STR " bits\n"
- "> Actual trace word size: %d bits\n";
- size_t size = (strlen(format1) +
- (state->trace_info.start_time.month
- ? (strlen(format2) + 7*10)
- : 1)
- + strlen(format3)
- + strlen(state->trace_info.nodename)
- + strlen(state->trace_info.hostname)
- + strlen(state->trace_info.pid)
- + 5*10 + 1);
-
- if (state->output.verbose) {
- size += write_allocator_info(state, NULL);
- }
-
- size += write_header(state, NULL, 0);
-
- /* Get area */
- get_next_write_area(&area, state, &state->output.queue, size);
-
- area.size = sprintf(area.ptr,
- format1,
- state->trace_info.nodename,
- state->trace_info.hostname,
- state->trace_info.pid);
- if (state->trace_info.start_time.month)
- area.size += sprintf(area.ptr + area.size,
- format2,
- state->trace_info.start_time.year,
- state->trace_info.start_time.month,
- state->trace_info.start_time.day,
- state->trace_info.start_time.hour,
- state->trace_info.start_time.minute,
- state->trace_info.start_time.second,
- state->trace_info.start_time.micro_second);
- else
- *(area.ptr + area.size++) = '\n';
- area.size += sprintf(area.ptr + area.size,
- format3,
- state->trace_info.version.parser.major,
- state->trace_info.version.parser.minor,
- state->trace_info.version.trace.major,
- state->trace_info.version.trace.minor,
- state->trace_info.bits);
-
- if (state->output.verbose) {
- area.size += write_allocator_info(state, area.ptr + area.size);
- }
-
- area.size += write_header(state, area.ptr + area.size, 0);
-
- /* Leave area */
- wrote_area(&area, state, &state->output.queue);
-#undef MAX_WORD_SZ_STR
-}
-
-static void
-print_main_footer(em_state *state)
-{
- em_area area = {NULL, 0};
- char *p;
- int i;
- char *stop_str =
- "> Trace stopped\n";
- char *exit_str =
- "> Emulator exited with code: %" USGND_INT_32_FSTR "\n";
- char *format =
- "> Total trace size: %" USGND_INT_MAX_FSTR " bytes\n"
- "> Average band width used: %" USGND_INT_MAX_FSTR " Kbit/s\n";
- size_t size;
- usgnd_int_max tsz = state->input.total_trace_size;
- usgnd_int_32 secs = state->info.stop_time.secs;
- usgnd_int_32 usecs = state->info.stop_time.usecs;
- usgnd_int_max bw;
-
- /* Max size of the max value line. Each value can at most use 21
- characters: largest possible usgnd_int_64 (20 digits) and one
- white space. */
- size = state->output.values_per_line*21 + 1;
-
- switch (state->info.stop_reason) {
- case EMTP_STOP:
- size += strlen(stop_str) + 1;
- break;
- case EMTP_EXIT:
- size += strlen(exit_str);
- size += 10; /* Enough for one unsgn_int_32 */
- size++;
- break;
- default:
- break;
- }
- size += strlen(format);
- size += 2*20; /* Enough for two unsgn_int_64 */
- size += 2;
-
- bw = (tsz + 1023)/1024;
- bw *= 1000;
- bw /= secs*1000 + usecs/1000;
- bw *= 8;
-
- /* Get area */
-
- get_next_write_area(&area, state, &state->output.queue, size);
-
- p = area.ptr;
-
- p += sprintf(p, "> %-*s", EM_TIME_FIELD_WIDTH - 2, "Maximum:");
-
- if (state->output.total) {
- int six = state->trace_info.segment_ix;
- write_max_ever_mem_info(state, &p, &state->info.total);
- if (state->trace_info.have_segment_carrier_info) {
- if (state->info.allctr_prv_crr[six])
- write_max_ever_mem_info(state,
- &p,
- state->info.allctr_prv_crr[six]);
- if (state->info.allctr_usd_crr[six])
- write_max_ever_mem_info(state,
- &p,
- state->info.allctr_usd_crr[six]);
- }
- }
- for (i = 0; i < state->output.no_allctrs; i++) {
- int ix = state->output.allctrs[i].ix;
- write_max_ever_mem_info(state, &p, &state->info.allctr[ix]);
- if (state->info.allctr_prv_crr[ix])
- write_max_ever_mem_info(state,
- &p,
- state->info.allctr_prv_crr[ix]);
- if (state->info.allctr_usd_crr[ix])
- write_max_ever_mem_info(state,
- &p,
- state->info.allctr_usd_crr[ix]);
- }
- for (i = 0; i < state->output.no_btypes; i++)
- write_max_ever_mem_info(state,
- &p,
- &state->info.btype[state->output.btypes[i].ix]);
-
- p += sprintf(p, "\n");
-
- switch (state->info.stop_reason) {
- case EMTP_STOP:
- p += sprintf(p, "%s", stop_str);
- break;
- case EMTP_EXIT:
- p += sprintf(p, exit_str, state->info.exit_status);
- break;
- default:
- break;
- }
-
- p += sprintf(p, format, tsz, bw);
-
- area.size = p - area.ptr;
-
- ASSERT(area.size <= size);
-
- /* Leave area */
-
- wrote_area(&area, state, &state->output.queue);
-
-}
-
-static void
-print_info(em_state *state, usgnd_int_32 secs, char *extra)
-{
- char *p;
- int i;
- size_t size;
- em_area area = {NULL, 0};
-
- /* Get area */
-
- size = 0;
- if (!state->output.lines_until_header)
- size += state->output.header_size;
-
- /* Max size of one line of values. Each value can at most use 21
- characters: largest possible usgnd_int_64 (20 digits) and one white
- space. */
- size += state->output.values_per_line*21 + 1;
-
- if (extra)
- size += write_str(NULL, extra);
-
- get_next_write_area(&area, state, &state->output.queue, size);
-
- /* Write to area */
-
- p = area.ptr;
-
- if (!state->output.lines_until_header) {
- memcpy((void *) area.ptr,
- (void *) state->output.header,
- state->output.header_size);
- p += state->output.header_size;
- state->output.lines_until_header = EM_LINES_UNTIL_HEADER;
- }
- else
- state->output.lines_until_header--;
-
- p += sprintf(p, "%*" USGND_INT_32_FSTR " ", EM_TIME_FIELD_WIDTH - 1, secs);
-
- if (state->output.total) {
- int six = state->trace_info.segment_ix;
- write_mem_info(state, &p, &state->info.total);
- if (state->trace_info.have_segment_carrier_info) {
- if (state->info.allctr_prv_crr[six])
- write_mem_info(state, &p, state->info.allctr_prv_crr[six]);
- if (state->info.allctr_usd_crr[six])
- write_mem_info(state, &p, state->info.allctr_usd_crr[six]);
- }
- }
- for (i = 0; i < state->output.no_allctrs; i++) {
- int ix = state->output.allctrs[i].ix;
- write_mem_info(state, &p, &state->info.allctr[ix]);
- if (state->info.allctr_prv_crr[ix])
- write_mem_info(state, &p, state->info.allctr_prv_crr[ix]);
- if (state->info.allctr_usd_crr[ix])
- write_mem_info(state, &p, state->info.allctr_usd_crr[ix]);
- }
- for (i = 0; i < state->output.no_btypes; i++)
- write_mem_info(state,
- &p,
- &state->info.btype[state->output.btypes[i].ix]);
-
- p += sprintf(p, "\n");
-
- if (extra)
- p += write_str(&p, extra);
-
- ASSERT(area.size >= p - area.ptr);
- area.size = p - area.ptr;
-
- /* Leave area */
-
- wrote_area(&area, state, &state->output.queue);
-}
-
-static void
-reset_mem_info(em_mem_info *mi)
-{
- mi->size = 0;
- mi->min_size = 0;
- mi->max_size = 0;
- mi->max_ever_size = 0;
- mi->no = 0;
- mi->min_no = 0;
- mi->max_no = 0;
- mi->max_ever_no = 0;
- mi->allocs = 0;
- mi->reallocs = 0;
- mi->frees = 0;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * State creation and destruction *
- * *
-\* */
-
-static void
-destroy_state(em_state *state)
-{
- int i;
- void (*freep)(void *);
-
- freep = state->free;
-
- if (state->block_table)
- emtbt_destroy_table(state->block_table);
-
- if (state->carrier_table) {
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++)
- if (state->carrier_table[i])
- emtbt_destroy_table(state->carrier_table[i]);
- state->carrier_table--;
- (*freep)((void *) state->carrier_table);
- }
-
- if (state->info.btype) {
- state->info.btype--;
- (*freep)((void *) state->info.btype);
- }
-
- if (state->info.allctr) {
- state->info.allctr--;
- (*freep)((void *) state->info.allctr);
- }
-
- if (state->info.allctr_prv_crr) {
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++)
- if (state->info.allctr_prv_crr[i])
- (*freep)((void *) state->info.allctr_prv_crr[i]);
- state->info.allctr_prv_crr--;
- (*freep)((void *) state->info.allctr_prv_crr);
- }
-
-
- if (state->info.allctr_usd_crr) {
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++)
- if (state->info.allctr_usd_crr[i])
- (*freep)((void *) state->info.allctr_usd_crr[i]);
- state->info.allctr_usd_crr--;
- (*freep)((void *) state->info.allctr_usd_crr);
- }
-
- emtp_state_destroy(state->trace_state);
- destroy_queue(state, &state->input.queue);
-
- if (state->output.btypes)
- (*freep)((void *) state->output.btypes);
- if (state->output.allctrs)
- (*freep)((void *) state->output.allctrs);
- destroy_queue(state, &state->output.queue);
-
-#if EMEM_d_SWITCH
-
- if (state->output.go.mutex) {
- mutex_destroy(state->output.go.mutex);
- (*state->free)((void *) state->output.go.mutex);
- state->output.go.mutex = NULL;
- }
- if (state->output.go.cond) {
- cond_destroy(state->output.go.cond);
- (*state->free)((void *) state->output.go.cond);
- state->output.go.cond = NULL;
- }
-
-#endif
-
- if (!IS_INVALID_SOCKET(state->input.socket)) {
- closesocket(state->input.socket);
- state->input.socket = INVALID_SOCKET;
- }
-
- (*freep)((void *) state);
-}
-
-static em_state *
-new_state(void * (*alloc)(size_t),
- void * (*realloc)(void *, size_t),
- void (*free)(void *))
-{
- em_state *state = NULL;
-
- state = (*alloc)(sizeof(em_state));
- if (!state)
- goto error;
-
- /* Stuff that might fail (used after the error label) */
-
- state->trace_state = NULL;
-
- /* Init state ... */
-
- state->alloc = alloc;
- state->realloc = realloc;
- state->free = free;
-
- state->block_table = NULL;
- state->carrier_table = NULL;
-
- reset_mem_info(&state->info.total);
- state->info.btype = NULL;
- state->info.allctr = NULL;
-
- state->info.allctr_prv_crr = NULL;
- state->info.allctr_usd_crr = NULL;
-
- state->info.stop_time.secs = 0;
- state->info.stop_time.usecs = 0;
- state->info.stop_reason = EMTP_UNDEF;
- state->info.exit_status = 0;
-
- state->output.next_print = 0;
- state->output.next_print_inc = 10;
- state->output.header = NULL;
- state->output.header_size = 0;
- state->output.values_per_object = 0;
- state->output.values_per_line = 0;
- state->output.field_width = 11;
- state->output.verbose = 0;
- state->output.total = 0;
- state->output.all_allctrs = 0;
- state->output.no_allctrs = 0;
- state->output.allctrs = NULL;
- state->output.all_btypes = 0;
- state->output.no_btypes = 0;
- state->output.btypes = NULL;
- state->output.max_min_values = 0;
- state->output.block_counts = 0;
- state->output.op_counts = 0;
- state->output.lines_until_header = EM_LINES_UNTIL_HEADER;
-
-#if PRINT_OPERATIONS
- state->output.stream = stderr;
-#else
- state->output.stream = stdout;
-#endif
- state->output.file_name = NULL;
-#if EMEM_d_SWITCH
- state->output.dir_name = NULL;
- state->output.erl_cmd_file = NULL;
- state->output.go.mutex = NULL;
- state->output.go.cond = NULL;
-#endif
-
- init_queue(state, &state->output.queue);
- state->output.queue.max_buf_size = 10*1024*1024;
- state->output.queue.name = "output";
-
- state->trace_state = emtp_state_new(alloc, realloc, free);
- if (!state->trace_state)
- goto error;
-
- state->trace_info.version.parser.major = 0;
- state->trace_info.version.parser.minor = 0;
- state->trace_info.version.trace.major = 0;
- state->trace_info.version.trace.minor = 0;
- state->trace_info.bits = 0;
- state->trace_info.max_allocator_ix = 0;
- state->trace_info.allocator = NULL;
- state->trace_info.max_block_type_ix = 0;
- state->trace_info.block_type = NULL;
-
- state->input.listen_port = 0;
- state->input.socket = INVALID_SOCKET;
- state->input.total_trace_size = 0;
- state->input.error = 0;
- state->input.error_descr = NULL;
-
- init_queue(state, &state->input.queue);
- state->input.queue.max_buf_size = 10*1024*1024;
- state->input.queue.name = "input";
-
- return state;
-
- error:
- if (state) {
- if (state->trace_state)
- emtp_state_destroy(state->trace_state);
- (*free)(state);
- }
- return NULL;
-}
-
-
-static emtbt_table *
-mk_block_table(em_state *state)
-{
- return emtbt_new_table(state->trace_info.bits == 64,
- state->alloc,
- state->realloc,
- state->free);
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * *
- * *
-\* */
-#if PRINT_OPERATIONS
-void print_op(em_state *state, emtp_operation *op);
-#endif
-
-static INLINE void
-update_max_values(em_mem_info *mi)
-{
- if (mi->max_size < mi->size)
- mi->max_size = mi->size;
- if (mi->max_no < mi->no)
- mi->max_no = mi->no;
-}
-
-static INLINE void
-update_min_values(em_mem_info *mi)
-{
- if (mi->min_size > mi->size)
- mi->min_size = mi->size;
- if (mi->min_no > mi->no)
- mi->min_no = mi->no;
-}
-
-static INLINE void
-update_alloc_op(em_mem_info *mi, usgnd_int_max size)
-{
- mi->allocs++;
- mi->size += size;
- mi->no++;
- update_max_values(mi);
-}
-
-static INLINE void
-update_realloc_op(em_mem_info *mi,
- usgnd_int_max size,
- usgnd_int_max prev_size,
- int no_change)
-{
- mi->reallocs++;
- ASSERT(mi->size >= prev_size);
- mi->size -= prev_size;
- mi->size += size;
- if (no_change) {
- if (no_change > 0)
- mi->no++;
- else {
- ASSERT(mi->no > 0);
- mi->no--;
- }
- }
- update_max_values(mi);
- update_min_values(mi);
-}
-
-static INLINE void
-update_free_op(em_mem_info *mi, usgnd_int_max prev_size)
-{
- mi->frees++;
- ASSERT(mi->size >= prev_size);
- mi->size -= prev_size;
- ASSERT(mi->no > 0);
- mi->no--;
- update_min_values(mi);
-}
-
-static int
-insert_operations(em_state *state, emtp_operation ops[], size_t len)
-{
- emtbt_table *crr_table;
- emtbt_block old_blk;
- usgnd_int_32 prev_size;
- usgnd_int_max size;
- size_t i;
- int res;
- int aix, btix, crrix;
-
- for (i = 0; i < len; i++) {
-
- while (state->output.next_print <= ops[i].time.secs) {
- print_info(state, state->output.next_print, NULL);
- state->output.next_print += state->output.next_print_inc;
- }
-
- switch (ops[i].type) {
-
- case EMTP_ALLOC:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
- btix = (int) ops[i].u.block.type;
- aix = state->trace_info.block_type[btix]->allocator;
-
- if (!ops[i].u.block.new_ptr)
- continue;
-
- res = emtbt_alloc_op(state->block_table, &ops[i]);
- if (res != 0)
- ERR_RET(res);
-
- size = ops[i].u.block.new_size;
-
- update_alloc_op(&state->info.btype[btix], size);
- update_alloc_op(&state->info.allctr[aix], size);
- update_alloc_op(&state->info.total, size);
- break;
-
- case EMTP_REALLOC: {
- int no;
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
-
- res = emtbt_realloc_op(state->block_table, &ops[i], &old_blk);
- if (res != 0)
- ERR_RET(res);
-
- size = ops[i].u.block.new_size;
- prev_size = old_blk.size;
-
- if (!ops[i].u.block.prev_ptr)
- btix = (int) ops[i].u.block.type;
- else
- btix = (int) old_blk.type;
- aix = state->trace_info.block_type[btix]->allocator;
-
- no = ((!old_blk.pointer && ops[i].u.block.new_ptr)
- ? 1
- : ((old_blk.pointer && !ops[i].u.block.new_size)
- ? -1
- : 0));
-
- update_realloc_op(&state->info.btype[btix], size, prev_size, no);
- update_realloc_op(&state->info.allctr[aix], size, prev_size, no);
- update_realloc_op(&state->info.total, size, prev_size, no);
-
- break;
- }
- case EMTP_FREE:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
-
- if (!ops[i].u.block.prev_ptr)
- continue;
-
- res = emtbt_free_op(state->block_table, &ops[i], &old_blk);
- if (res != 0)
- ERR_RET(res);
-
- prev_size = old_blk.size;
- btix = (int) old_blk.type;
- aix = state->trace_info.block_type[btix]->allocator;
-
-
- update_free_op(&state->info.btype[btix], prev_size);
- update_free_op(&state->info.allctr[aix], prev_size);
- update_free_op(&state->info.total, prev_size);
-
- break;
-
- case EMTP_CARRIER_ALLOC:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
-
- aix = (int) ops[i].u.block.type;
-
- crrix = (int) ops[i].u.block.carrier_type;
- if (!state->carrier_table[crrix]) {
- state->carrier_table[crrix] = mk_block_table(state);
- if (!state->carrier_table[crrix])
- ERR_RET(ENOMEM);
- }
- crr_table = state->carrier_table[crrix];
-
- if (!ops[i].u.block.new_ptr)
- continue;
-
- res = emtbt_alloc_op(crr_table, &ops[i]);
- if (res != 0)
- ERR_RET(res);
-
- size = ops[i].u.block.new_size;
-
- if (state->info.allctr_usd_crr[aix])
- update_alloc_op(state->info.allctr_usd_crr[aix], size);
- if (state->info.allctr_prv_crr[crrix])
- update_alloc_op(state->info.allctr_prv_crr[crrix], size);
- update_alloc_op(&state->info.allctr[crrix], size);
-
- break;
-
- case EMTP_CARRIER_REALLOC: {
- int no;
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
-
- crrix = (int) ops[i].u.block.carrier_type;
- if (!state->carrier_table[crrix]) {
- state->carrier_table[crrix] = mk_block_table(state);
- if (!state->carrier_table[crrix])
- ERR_RET(ENOMEM);
- }
- crr_table = state->carrier_table[crrix];
-
- res = emtbt_realloc_op(crr_table, &ops[i], &old_blk);
- if (res != 0)
- ERR_RET(res);
-
- size = ops[i].u.block.new_size;
- prev_size = old_blk.size;
-
- if (!ops[i].u.block.prev_ptr)
- aix = (int) ops[i].u.block.type;
- else
- aix = (int) old_blk.type;
-
-
- no = ((!old_blk.pointer && ops[i].u.block.new_ptr)
- ? 1
- : ((old_blk.pointer && !ops[i].u.block.new_size)
- ? -1
- : 0));
-
- if (state->info.allctr_usd_crr[aix])
- update_realloc_op(state->info.allctr_usd_crr[aix],
- size,
- prev_size,
- no);
- if (state->info.allctr_prv_crr[crrix])
- update_realloc_op(state->info.allctr_prv_crr[crrix],
- size,
- prev_size,
- no);
- update_realloc_op(&state->info.allctr[crrix],
- size,
- prev_size,
- no);
- break;
- }
- case EMTP_CARRIER_FREE:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
-
- crrix = (int) ops[i].u.block.carrier_type;
- crr_table = state->carrier_table[crrix];
- if (!crr_table)
- ERR_RET(EMTBT_FREE_NOBLK_ERROR);
-
- if (!ops[i].u.block.prev_ptr)
- continue;
-
- res = emtbt_free_op(crr_table, &ops[i], &old_blk);
- if (res != 0)
- ERR_RET(res);
-
- prev_size = old_blk.size;
- aix = (int) old_blk.type;
-
- if (state->info.allctr_usd_crr[aix])
- update_free_op(state->info.allctr_usd_crr[aix], prev_size);
- if (state->info.allctr_prv_crr[crrix])
- update_free_op(state->info.allctr_prv_crr[crrix], prev_size);
- update_free_op(&state->info.allctr[crrix], prev_size);
-
- break;
-
- case EMTP_STOP:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
- state->info.stop_reason = EMTP_STOP;
- state->info.stop_time.secs = ops[i].time.secs;
- state->info.stop_time.usecs = ops[i].time.usecs;
- print_info(state, ops[i].time.secs, NULL);
- return EM_EXIT_RESULT;
- case EMTP_EXIT:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
- state->info.stop_reason = EMTP_EXIT;
- state->info.exit_status = ops[i].u.exit_status;
- state->info.stop_time.secs = ops[i].time.secs;
- state->info.stop_time.usecs = ops[i].time.usecs;
- print_info(state, ops[i].time.secs, NULL);
- return EM_EXIT_RESULT;
- default:
-#if PRINT_OPERATIONS
- print_op(state, &ops[i]);
-#endif
- /* Ignore not understood operation */
- break;
- }
- }
- return 0;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * *
- * *
-\* */
-
-static const char *
-error_string(int error)
-{
- const char *str;
- const char *error_str;
- static const char unknown_error[] = "Unknown error";
-
- error_str = unknown_error;
-
- if (error > 0) {
- const char *str = strerror(error);
- if (str)
- error_str = str;
- }
- else if (error < 0) {
- str = emtp_error_string(error);
- if (!str) {
- str = emtbt_error_string(error);
- if (!str) {
- switch (error) {
- case EM_TRUNCATED_TRACE_ERROR:
- error_str = "Truncated trace";
- break;
- case EM_INTERNAL_ERROR:
- error_str = "emem internal error";
- break;
- default:
- break;
- }
- }
- }
-
- if (str)
- error_str = str;
- }
-
- return error_str;
-}
-
-__decl_noreturn static void __noreturn
-error(int res)
-{
- error_msg(res, NULL);
-}
-
-__decl_noreturn static void __noreturn
-error_msg(int res, char *msg)
-{
- fprintf(stderr,
- "emem: %s%sFatal error: %s (%d)\n",
- msg ? msg : "",
- msg ? ": ": "",
- error_string(res),
- res);
- exit(1);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * *
- * *
-\* */
-
-#if EMEM_d_SWITCH
-
-static size_t
-write_output_filename(char *ptr,
- char *dirname,
- char *nodename,
- char *hostname,
- char *datetime,
- char *pid)
-{
- size_t sz = 0;
- char *p = ptr;
- char **pp = ptr ? &p : NULL;
- sz += write_str(pp, dirname);
- if (pp) *((*pp)++) = DIR_SEP_CHAR;
- sz++;
- sz += write_str(pp, nodename);
- sz += write_str(pp, "_");
- sz += write_str(pp, hostname);
- sz += write_str(pp, "_");
- sz += write_str(pp, datetime);
- sz += write_str(pp, "_");
- sz += write_str(pp, pid);
- sz += write_str(pp, EM_OUTPUT_FILE_SUFFIX);
- if (pp) *((*pp)++) = '\0';
- sz++;
- return sz;
-}
-
-static char *
-make_output_filename(em_state *state)
-{
- char *fname;
- size_t fname_size;
- char *nodename = state->trace_info.nodename;
- char *hostname = state->trace_info.hostname;
- char *pid = state->trace_info.pid;
- char dt_buf[20];
- char *date_time = NULL;
-
- if (*nodename == '\0')
- nodename = "nonode";
- if (*hostname == '\0')
- hostname = "nohost";
- if (!state->trace_info.start_time.day)
- date_time = "notime";
- else {
- sprintf(dt_buf,
- "%d-%2.2d-%2.2d_%2.2d.%2.2d.%2.2d",
- state->trace_info.start_time.year % 10000,
- state->trace_info.start_time.month % 100,
- state->trace_info.start_time.day % 100,
- state->trace_info.start_time.hour % 100,
- state->trace_info.start_time.minute % 100,
- state->trace_info.start_time.second % 100);
- date_time = &dt_buf[0];
- }
- if (*pid == '\0')
- pid = "nopid";
-
- fname = (*state->alloc)(write_output_filename(NULL,
- state->output.dir_name,
- nodename,
- hostname,
- date_time,
- pid));
- if (!fname)
- return NULL;
-
- (void) write_output_filename(fname,
- state->output.dir_name,
- nodename,
- hostname,
- date_time,
- pid);
- return fname;
-}
-
-#endif
-
-static int
-complete_state(em_state *state)
-{
- int i, j, vpo, vpl;
- void * (*allocp)(size_t);
- void * (*reallocp)(void *, size_t);
- size_t size = sizeof(emtp_info);
-
- if (!emtp_get_info(&state->trace_info, &size, state->trace_state)
- || size < sizeof(emtp_info))
- return EM_INTERNAL_ERROR;
-
-#if EMEM_d_SWITCH
-
- if (!state->output.stream) {
- char *fname = make_filename(state);
- mutex_lock(state->output.go.mutex);
- state->output.stream = fopen(fname, "w");
- if (!state->output.stream) {
- disconnect_queue_reader(&state->input.queue);
- disconnect_queue_writer(&state->output.queue);
- }
- cond_signal(state->output.go.cond);
- mutex_unlock(state->output.go.mutex);
- (*state->free)((void *) fname);
- if (!state->output.stream)
- return EIO;
- }
-
-#endif
-
- allocp = state->alloc;
- reallocp = state->realloc;
-
- state->carrier_table = (*allocp)((state->trace_info.max_allocator_ix+2)
- * sizeof(emtbt_table *));
- if (!state->carrier_table)
- return ENOMEM;
- state->carrier_table++;
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++)
- state->carrier_table[i] = NULL;
-
-
- state->block_table = mk_block_table(state);
- state->info.btype = (*allocp)((state->trace_info.max_block_type_ix+2)
- * sizeof(em_mem_info));
- state->info.allctr = (*allocp)((state->trace_info.max_allocator_ix+2)
- * sizeof(em_mem_info));
- if (!state->block_table || !state->info.btype || !state->info.allctr)
- return ENOMEM;
-
- state->info.btype++;
- state->info.allctr++;
-
- state->info.allctr_prv_crr
- = (*allocp)((state->trace_info.max_allocator_ix+2)
- * sizeof(em_mem_info *));
- if (!state->info.allctr_prv_crr)
- return ENOMEM;
- state->info.allctr_prv_crr++;
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++)
- state->info.allctr_prv_crr[i] = NULL;
-
- state->info.allctr_usd_crr
- = (*allocp)((state->trace_info.max_allocator_ix+2)
- * sizeof(em_mem_info *));
- if (!state->info.allctr_usd_crr)
- return ENOMEM;
- state->info.allctr_usd_crr++;
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++)
- state->info.allctr_usd_crr[i] = NULL;
-
- if (state->output.all_btypes) {
- if (state->output.btypes)
- (*state->free)((void *) state->output.btypes);
- state->output.no_btypes = state->trace_info.max_block_type_ix + 2;
- state->output.btypes = (*allocp)(state->output.no_btypes
- * sizeof(em_output_types));
- if (!state->output.btypes)
- return ENOMEM;
- }
-
- if (state->output.all_allctrs) {
- if (state->output.allctrs)
- (*state->free)((void *) state->output.allctrs);
- state->output.no_allctrs = state->trace_info.max_allocator_ix + 2;
- state->output.allctrs = (*allocp)(state->output.no_allctrs
- * sizeof(em_output_types));
- if (!state->output.allctrs)
- return ENOMEM;
- }
-
- for (i = -1; i <= state->trace_info.max_block_type_ix; i++) {
- /* Save block type if we should print info about it */
- emtp_block_type *btp = state->trace_info.block_type[i];
- reset_mem_info(&state->info.btype[i]);
- if (state->output.no_btypes) {
- if (state->output.all_btypes) {
- state->output.btypes[i+1].name = btp->name;
- state->output.btypes[i+1].ix = btp->valid ? i : -1;
- }
- else {
- for (j = 0; j < state->output.no_btypes; j++)
- if (strcmp(btp->name, state->output.btypes[j].name) == 0) {
- state->output.btypes[j].ix = i;
- break;
- }
- }
- }
- }
-
- /* Remove invalid block types */
- if (state->output.no_btypes) {
- for (i = 0, j = 0; i < state->output.no_btypes; i++) {
- if (state->output.btypes[i].ix >= 0) {
- state->output.btypes[j].name = state->output.btypes[i].name;
- state->output.btypes[j].ix = state->output.btypes[i].ix;
- j++;
- }
- }
- state->output.no_btypes = j;
- }
-
- for (i = -1; i <= state->trace_info.max_allocator_ix; i++) {
- /* Save allocator if we should print info about it */
- emtp_allocator *ap = state->trace_info.allocator[i];
- reset_mem_info(&state->info.allctr[i]);
- if (state->output.no_allctrs) {
- if (state->output.all_allctrs) {
- state->output.allctrs[i+1].name = ap->name;
- state->output.allctrs[i+1].ix = ap->valid ? i : -1;
- }
- else {
- for (j = 0; j < state->output.no_allctrs; j++)
- if (strcmp(ap->name, state->output.allctrs[j].name) == 0) {
- state->output.allctrs[j].ix = i;
- break;
- }
- }
- }
-
- /* Allocate em_mem_info if used carrier info is available */
- if (ap->flags & EMTP_ALLOCATOR_FLAG_HAVE_USED_CARRIERS_INFO
- || (i == state->trace_info.segment_ix
- && state->trace_info.have_segment_carrier_info)) {
- state->info.allctr_usd_crr[i]
- = (em_mem_info *) (*allocp)(sizeof(em_mem_info));
- if (!state->info.allctr_usd_crr[i])
- return ENOMEM;
- reset_mem_info(state->info.allctr_usd_crr[i]);
- }
-
- /* Allocate em_mem_info for carrier providers */
- if (ap->carrier.provider) {
- sgnd_int_32 j;
- for (j = 0; j < ap->carrier.no_providers; j++) {
- sgnd_int_32 crr_prvdr = ap->carrier.provider[j];
- if (!state->info.allctr_prv_crr[crr_prvdr]) {
- state->info.allctr_prv_crr[crr_prvdr]
- = (em_mem_info *) (*allocp)(sizeof(em_mem_info));
- if (!state->info.allctr_prv_crr[crr_prvdr])
- return ENOMEM;
- reset_mem_info(state->info.allctr_prv_crr[crr_prvdr]);
- }
- }
- }
- }
-
- /* Remove invalid allocators */
- if (state->output.no_allctrs) {
- for (i = 0, j = 0; i < state->output.no_allctrs; i++) {
- if (state->output.allctrs[i].ix >= 0) {
- state->output.allctrs[j].name = state->output.allctrs[i].name;
- state->output.allctrs[j].ix = state->output.allctrs[i].ix;
- j++;
- }
- }
- state->output.no_allctrs = j;
- }
-
- if (state->output.no_btypes) {
- state->output.btypes = (*reallocp)(state->output.btypes,
- sizeof(em_output_types)
- * state->output.no_btypes);
- if (!state->output.btypes)
- return ENOMEM;
- }
-
- if (state->output.no_allctrs) {
- state->output.allctrs = (*reallocp)(state->output.allctrs,
- sizeof(em_output_types)
- * state->output.no_allctrs);
- if (!state->output.allctrs)
- return ENOMEM;
- }
-
-
- vpo = 1;
- if (state->output.max_min_values)
- vpo += 2;
- if (state->output.block_counts) {
- vpo++;
- if (state->output.max_min_values)
- vpo += 2;
- }
- if (state->output.op_counts)
- vpo += 3;
-
- state->output.values_per_object = vpo;
-
- vpl = 0;
- vpl++; /* time */
- if (state->output.total) {
- vpl += vpo; /* total allocated */
- if (state->trace_info.have_segment_carrier_info) {
- vpl += vpo; /* total carriers */
- vpl += vpo; /* cached carriers */
- }
- }
- for (i = 0; i < state->output.no_allctrs; i++) {
- vpl += vpo; /* allocated */
- if (state->trace_info.have_carrier_info) {
- if (state->info.allctr_prv_crr[state->output.allctrs[i].ix])
- vpl += vpo; /* provided carriers */
- vpl += vpo; /* used carriers */
- }
- }
- vpl += state->output.no_btypes*vpo; /* allocated */
-
- state->output.values_per_line = vpl;
-
- state->output.header_size = write_header(state, NULL, 1);
- state->output.header = (*state->alloc)(state->output.header_size + 1);
- if (!state->output.header)
- return ENOMEM;
- size = write_header(state, state->output.header, 1);
- ASSERT(state->output.header_size == size);
- return 0;
-}
-
-static int
-process_trace(em_state *state)
-{
- emtp_operation ops[EM_NO_OF_OPS];
- int res;
- size_t ops_len;
- em_area area;
-
- while (1) {
- get_next_read_area(&area, state, &state->input.queue);
- if (!area.size)
- return EM_TRUNCATED_TRACE_ERROR;
- res = emtp_parse(state->trace_state,
- (usgnd_int_8 **)&area.ptr, &area.size,
- NULL, 0, NULL);
- if (res == EMTP_HEADER_PARSED)
- break;
- if (res == EMTP_NEED_MORE_TRACE)
- continue;
-
- if (res < 0)
- return res;
- else
- return EM_TRUNCATED_TRACE_ERROR;
- }
-
- res = complete_state(state);
- if (res != 0)
- return res;
-
- print_main_header(state);
-
- while (1) {
- if (!area.size) {
- get_next_read_area(&area, state, &state->input.queue);
- if (!area.size)
- return EM_TRUNCATED_TRACE_ERROR;
-
- }
-
-
- while (area.size) {
- ops_len = EM_NO_OF_OPS;
- res = emtp_parse(state->trace_state,
- (usgnd_int_8 **)&area.ptr, &area.size,
- ops, sizeof(emtp_operation), &ops_len);
- if (res < 0)
- return res;
-
- res = insert_operations(state, ops, ops_len);
- if (res != 0)
- return res;
-
- }
-
- }
-
-}
-
-static void
-usage(char *sw, char *error)
-{
- FILE *filep = stdout;
-#ifdef __WIN32__
-#define SW_CHAR "/"
-#else
-#define SW_CHAR "-"
-#endif
-
- if (error) {
- ASSERT(sw);
- filep = stderr;
- fprintf(filep, "emem: %s: %s\n", sw, error);
- }
- fprintf(filep,
- "Usage: emem "
-#if EMEM_A_SWITCH
- "[" SW_CHAR "A <ALLOCATOR>] "
-#endif
- "[" SW_CHAR "a <ALLOCATOR>] "
- "[" SW_CHAR "b <BLOCK TYPE>] "
-#if EMEM_C_SWITCH
- "[" SW_CHAR "C <CLASS>] "
-#endif
-#if EMEM_c_SWITCH
- "[" SW_CHAR "c <CLASS>] "
-#endif
- "{"
-#if EMEM_d_SWITCH
- SW_CHAR "d <DIRNAME>|"
-#endif
- SW_CHAR "f <FILENAME>} "
- "[" SW_CHAR "h] "
- "[" SW_CHAR "i <SECONDS>] "
- "[" SW_CHAR "m] "
- "[" SW_CHAR "n] "
- "[" SW_CHAR "o] "
- "{" SW_CHAR "p <PORT>} "
- "[" SW_CHAR "t] "
- "[" SW_CHAR "v] "
- "\n");
- if (error)
- exit(1);
- else {
- fprintf(filep,
- "\n"
- " [] - switch is allowed any number of times\n"
- " {} - switch is allowed at most one time\n"
-#if EMEM_d_SWITCH
- " | - exclusive or\n"
-#endif
- "\n"
- " Switches:\n"
-#if EMEM_A_SWITCH
- " " SW_CHAR "a <A> - display info about Allocator <A> and all block types using <A>\n"
-#endif
- " " SW_CHAR "a <A> - display info about allocator <A>\n"
- " " SW_CHAR "b <B> - display info about block type <B>\n"
-#if EMEM_C_SWITCH
- " " SW_CHAR "C <C> - display info about class <C> and all block types in class <C>\n"
-#endif
-#if EMEM_c_SWITCH
- " " SW_CHAR "b <B> - display info about class <C>\n"
-#endif
-#if EMEM_d_SWITCH
- " " SW_CHAR "d <D> - run as daemon and set output directory to <D>\n"
-#endif
- " " SW_CHAR "f <F> - set output file to <F>\n"
- " " SW_CHAR "h - display help and exit\n"
- " " SW_CHAR "i <I> - set display interval to <I> seconds\n"
- " " SW_CHAR "m - display max/min values\n"
- " " SW_CHAR "n - display block/carrier/segment count values\n"
- " " 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");
- exit(0);
- }
-
-#undef SW_CHAR
-}
-
-
-static void
-parse_args(em_state *state, int argc, char *argv[])
-{
- int port;
- int i;
-
- i = 1;
- while (i < argc) {
- if ((argv[i][0] != '-' && argv[i][0] != '/') || argv[i][2] != '\0') {
- unknown_switch:
- usage(argv[i], "unknown switch");
- }
-
- switch (argv[i][1]) {
-#if EMEM_A_SWITCH
- case 'A': /* TODO: Allocator + blocktypes using allocator */
-#endif
- case 'a':
- if (i + 1 >= argc)
- usage(argv[i], "missing allocator");
- i++;
- if (state->output.all_allctrs || strcmp(argv[i],"all") == 0) {
- state->output.all_allctrs = 1;
- break;
- }
-
- if (!state->output.allctrs)
- state->output.allctrs
- = (*state->alloc)(sizeof(em_output_types)*argc/2);
- if (!state->output.allctrs)
- error(ENOMEM);
- state->output.allctrs[state->output.no_allctrs].name = argv[i];
- state->output.allctrs[state->output.no_allctrs].ix = -1;
- state->output.no_allctrs++;
- break;
- case 'b':
- if (i + 1 >= argc)
- usage(argv[i], "missing block type");
- i++;
- if (state->output.all_btypes || strcmp(argv[i],"all") == 0) {
- state->output.all_btypes = 1;
- break;
- }
-
- if (!state->output.btypes)
- state->output.btypes
- = (*state->alloc)(sizeof(em_output_types)*argc/2);
- if (!state->output.btypes)
- error(ENOMEM);
- state->output.btypes[state->output.no_btypes].name = argv[i];
- state->output.btypes[state->output.no_btypes].ix = -1;
- state->output.no_btypes++;
- break;
-#if EMEM_C_SWITCH
-#endif
-#if EMEM_c_SWITCH
- case 'c':
- break;
-#endif
-#if EMEM_d_SWITCH
- case 'd': {
- char *p;
- char *fname;
- if (state->output.dir_name)
- usage(argv[i], "directory already set");
- if (state->output.file_name)
- usage(argv[i], "file name already set");
- if (i + 1 >= argc)
- usage(argv[i], "missing directory name");
- state->output.dir_name = argv[i+1];
- fname = (*state->alloc)(strlen(state->output.dir_name)
- + 1
- + strlen(EM_ERL_CMD_FILE_NAME)
- + 1);
- state->output.go.mutex = (*state->alloc)(sizeof(ethr_mutex));
- state->output.go.cond = (*state->alloc)(sizeof(ethr_cond));
- if (!fname || !state->output.go.mutex || !state->output.go.cond)
- error(ENOMEM);
- p = fname;
- (void) write_str(&p, state->output.dir_name);
- *(p++) = DIR_SEP_CHAR;
- (void) write_str(&p, EM_ERL_CMD_FILE_NAME);
- *(p++) = '\0';
- state->output.erl_cmd_file = fopen(fname, "w");
- if (!state->output.erl_cmd_file)
- usage(argv[i], "cannot create files in directory");
- (*state->free)((void *) fname);
- state->output.stream = NULL;
- mutex_init(state->output.go.mutex);
- cond_init(state->output.go.cond);
- i++;
- break;
- }
-#endif
- case 'f':
-#if EMEM_d_SWITCH
- if (state->output.dir_name)
- usage(argv[i], "directory already set");
-#endif
- if (state->output.file_name)
- usage(argv[i], "file name already set");
- if (i + 1 >= argc)
- usage(argv[i], "missing file name");
- state->output.file_name = argv[i+1];
- state->output.stream = fopen(state->output.file_name, "w");
- if (!state->output.stream)
- usage(argv[i], "cannot create file");
- if (setvbuf(state->output.stream, NULL, _IONBF, 0) != 0) {
- fprintf(stderr,
- "emem: failed to set file %s in unbuffered mode\n",
- state->output.file_name);
- exit(1);
- }
- i++;
- break;
- case 'h':
- usage(NULL, NULL);
- break;
- case 'i': {
- int interval;
- if (argv[i][2])
- goto unknown_switch;
-
- if (i + 1 >= argc)
- usage(argv[i], "missing interval");
- interval = atoi(argv[i+1]);
- if (interval < 1)
- usage(argv[i], "bad interval");
- i++;
- state->output.next_print_inc = interval;
- break;
- }
- case 'm':
- state->output.max_min_values = 1;
- break;
- case 'n':
- state->output.block_counts = 1;
- break;
- case 'o':
- state->output.op_counts = 1;
- break;
- case 'p':
- if (state->input.listen_port)
- usage(argv[i], "port already set");
- if (i + 1 >= argc)
- usage(argv[i], "missing port number");
- port = atoi(argv[i+1]);
- if (port <= 1024 || port >= (1 << 16))
- usage(argv[i], "bad port number");
- i++;
- state->input.listen_port = (usgnd_int_16) port;
- break;
- case 't':
- state->output.total = 1;
- break;
- case 'v':
- state->output.verbose = 1;
- break;
- default:
- goto unknown_switch;
- }
- i++;
- }
-
- if (!state->output.allctrs && !state->output.btypes)
- state->output.total = 1;
-}
-
-static int
-init_connection(em_state *state)
-{
- int res;
- SOCKET lsock;
- SOCKET sock = INVALID_SOCKET;
- struct sockaddr_in my_addr;
- socklen_t oth_addr_len;
- struct sockaddr_in oth_addr;
-#ifdef __WIN32__
- WORD wVersionRequested = MAKEWORD(2,0);
- WSADATA wsaData;
-
- if (WSAStartup(wVersionRequested, &wsaData) != 0)
- return EIO;
-
- if ((LOBYTE(wsaData.wVersion) != 2) || (HIBYTE(wsaData.wVersion) != 0))
- return EIO;
-#endif
-
- do_socket:
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (IS_INVALID_SOCKET(sock)) {
- res = GET_SOCK_ERRNO();
- if (res == EINTR)
- goto do_socket;
- goto error;
- }
-
- memset((void *) &my_addr, 0, sizeof(struct sockaddr_in));
-
- my_addr.sin_family = AF_INET;
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- my_addr.sin_port = htons(state->input.listen_port);
-
- do_bind:
- if (bind(sock, (struct sockaddr*) &my_addr, sizeof(my_addr)) < 0) {
- res = GET_SOCK_ERRNO();
- if (res == EINTR)
- goto do_bind;
- goto error;
- }
-
- do_listen:
- if (listen(sock, 1) < 0) {
- res = GET_SOCK_ERRNO();
- if (res == EINTR)
- goto do_listen;
- goto error;
- }
-
- lsock = sock;
- state->input.socket = sock;
-
- res = print_emu_arg(state);
- if (res != 0)
- goto error;
-
- print_string(state, "> Waiting for emulator to connect... ");
-
- do_accept:
- oth_addr_len = sizeof(oth_addr);
- sock = accept(lsock, (struct sockaddr *) &oth_addr, &oth_addr_len);
- if (IS_INVALID_SOCKET(sock)) {
- res = GET_SOCK_ERRNO();
- if (res == EINTR)
- goto do_accept;
- sock = lsock;
- goto error;
- }
-
- print_string(state, "connected\n");
-
- closesocket(lsock);
- state->input.socket = sock;
-
- return 0;
-
- error:
- if (!IS_INVALID_SOCKET(sock)) {
- closesocket(sock);
- state->input.socket = INVALID_SOCKET;
- }
- return res;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * IO threads *
- * *
-\* */
-
-/*
- * The input thread reads from a socket and puts the received data
- * in the input buffer queue.
- *
- * Note: There is intentionally no flow control. If the emem program
- * cannot process data as fast as it arrives, it is supposed
- * to crash when hitting the maximum buffersize; otherwise,
- * the traced emulator would be slowed down.
- */
-static void *
-input_thread_func(void *arg)
-{
- int res;
- char *edescr = NULL;
- ssize_t recv_sz;
- usgnd_int_max total_trace_size = 0;
- em_state *state = (em_state *) arg;
- em_area area = {NULL, 0};
- SOCKET sock = state->input.socket;
- em_buf_queue *queue = &state->input.queue;
-
- while(1) {
- get_next_write_area(&area,
- state,
- queue,
- EM_MIN_TRACE_READ_SIZE);
-
- if (!area.ptr) {
- res = ENOMEM;
- edescr = "Input alloc";
- goto stop;
- }
-
- do_recv:
- if (is_queue_reader_disconnected(queue)) {
- res = 0;
- edescr = "Input";
- goto stop;
- }
- recv_sz = recv(sock, (void *) area.ptr, area.size, 0);
- if (recv_sz <= 0) {
- res = GET_SOCK_ERRNO();
- if (res == EINTR)
- goto do_recv;
- edescr = "Input recv";
- goto stop;
- }
- area.size = (size_t) recv_sz;
- total_trace_size += (usgnd_int_max) recv_sz;
- }
-
- stop:
- state->input.error = res;
- state->input.error_descr = edescr;
- state->input.total_trace_size = total_trace_size;
- disconnect_queue_writer(queue);
- if (!IS_INVALID_SOCKET(state->input.socket)) {
- closesocket(sock);
- state->input.socket = INVALID_SOCKET;
- }
- return NULL;
-}
-
-
-static void *
-output_thread_func(void *arg)
-{
- em_state *state = (em_state *) arg;
- em_area area = {NULL, 0};
-
-#if EMEM_d_SWITCH
-
- if (state->output.go.mutex) {
- mutex_lock(state->output.go.mutex);
- while (!state->output.stream
- && !is_queue_writer_disconnected(&state->output.queue))
- cond_wait(state->output.go.cond, state->output.go.mutex);
- mutex_unlock(state->output.go.mutex);
-
- mutex_destroy(state->output.go.mutex);
- (*state->free)((void *) state->output.go.mutex);
- state->output.go.mutex = NULL;
- cond_destroy(state->output.go.cond);
- (*state->free)((void *) state->output.go.cond);
- state->output.go.cond = NULL;
- }
-
-#endif
-
- while (1) {
- get_next_read_area(&area, state, &state->output.queue);
- if (!area.size) {
- disconnect_queue_reader(&state->output.queue);
- if (is_queue_writer_disconnected(&state->output.queue))
- goto stop;
- else
- error_msg(EIO, "Output queue");
- }
- if (fwrite((void *) area.ptr,
- sizeof(char),
- area.size,
- state->output.stream) != area.size) {
- disconnect_queue_reader(&state->output.queue);
- error_msg(0, "Write");
- }
- }
-
- stop:
- if (state->output.stream != stdout && state->output.stream != stderr)
- fclose(state->output.stream);
- return NULL;
-}
-
-
-int
-main(int argc, char *argv[])
-{
- int res, ires, jres;
- ethr_tid input_tid;
- ethr_tid output_tid;
- em_state *state;
-
- /* set stdout in unbuffered mode */
- if (setvbuf(stdout, NULL, _IONBF, 0) != 0) {
- fprintf(stderr, "emem: failed to set stdout in unbuffered mode\n");
- exit(1);
- }
-
- if (ethr_init(NULL) != 0 || ethr_late_init(NULL) != 0) {
- fprintf(stderr, "emem: failed to initialize thread package\n");
- exit(1);
- }
-
- state = new_state(malloc, realloc, free);
- if (!state)
- error(ENOMEM);
-
- parse_args(state, argc, argv);
-
- res = ethr_thr_create(&output_tid,
- output_thread_func,
- (void *) state,
- NULL);
- if (res != 0)
- error_msg(res, "Output thread create");
-
-#ifdef DEBUG
- print_string(state, "> [debug]\n");
-#endif
-
- res = init_connection(state);
- if (res != 0)
- error_msg(res, "Initialize connection");
-
- res = ethr_thr_create(&input_tid,
- input_thread_func,
- (void *) state,
- NULL);
- if (res != 0)
- error_msg(res, "Input thread create");
-
- res = process_trace(state);
-
- disconnect_queue_reader(&state->input.queue);
-
- jres = ethr_thr_join(input_tid, NULL);
- if (jres != 0)
- error_msg(jres, "Input thread join");
-
- if (res == EM_EXIT_RESULT)
- print_main_footer(state);
- disconnect_queue_writer(&state->output.queue);
-
- jres = ethr_thr_join(output_tid, NULL);
- if (jres != 0)
- error_msg(jres, "Output thread join");
-
- ires = state->input.error;
-
- destroy_state(state);
-
-#ifdef __WIN32__
- WSACleanup();
-#endif
-
- switch (res) {
- case EM_EXIT_RESULT:
- break;
- case EM_TRUNCATED_TRACE_ERROR:
- error_msg(ires, state->input.error_descr);
- break;
- default:
- error(res);
- break;
- }
-
- return 0;
-}
-
-
-#if PRINT_OPERATIONS
-void
-print_op(em_state *state, emtp_operation *op)
-{
-
-#if 0
- printf("%5" USGND_INT_32_FSTR ":%6.6" USGND_INT_32_FSTR " ",
- op->time.secs, op->time.usecs);
-#endif
- if (state->trace_info.version.parser.major >= 2) {
-
- switch (op->type) {
- case EMTP_ALLOC:
- printf(" %" USGND_INT_MAX_FSTR " = alloc(%" USGND_INT_16_FSTR
- ", %" USGND_INT_MAX_FSTR ")\n",
- op->u.block.new_ptr,
- op->u.block.type,
- op->u.block.new_size);
- break;
- case EMTP_REALLOC:
- printf(" %" USGND_INT_MAX_FSTR " = realloc(%" USGND_INT_16_FSTR
- ", %" USGND_INT_MAX_FSTR ", %" USGND_INT_MAX_FSTR ")\n",
- op->u.block.new_ptr,
- op->u.block.type,
- op->u.block.prev_ptr,
- op->u.block.new_size);
- break;
- case EMTP_FREE:
- printf(" free(%" USGND_INT_16_FSTR ", %" USGND_INT_MAX_FSTR ")"
- "\n",
- op->u.block.type,
- op->u.block.prev_ptr);
- break;
- case EMTP_CARRIER_ALLOC:
- printf(" %" USGND_INT_MAX_FSTR " = carrier_alloc(%"
- USGND_INT_16_FSTR ", %" USGND_INT_16_FSTR ", %"
- USGND_INT_MAX_FSTR ")\n",
- op->u.block.new_ptr,
- op->u.block.carrier_type,
- op->u.block.type,
- op->u.block.new_size);
- break;
- case EMTP_CARRIER_REALLOC:
- printf(" %" USGND_INT_MAX_FSTR " = carrier_realloc(%"
- USGND_INT_16_FSTR ", %" USGND_INT_16_FSTR ", %"
- USGND_INT_MAX_FSTR ", %" USGND_INT_MAX_FSTR ")\n",
- op->u.block.new_ptr,
- op->u.block.carrier_type,
- op->u.block.type,
- op->u.block.prev_ptr,
- op->u.block.new_size);
- case EMTP_CARRIER_FREE:
- printf(" carrier_free(%" USGND_INT_16_FSTR ", %" USGND_INT_16_FSTR
- ", %" USGND_INT_MAX_FSTR ")\n",
- op->u.block.carrier_type,
- op->u.block.type,
- op->u.block.prev_ptr);
- break;
- default:
- printf(" op = %d\n", op->type);
- break;
- }
-
- }
- else {
-
- switch (op->type) {
- case EMTP_ALLOC:
- printf(" %" USGND_INT_MAX_FSTR " = alloc(%" USGND_INT_MAX_FSTR ")"
- "\n",
- op->u.block.new_ptr,
- op->u.block.new_size);
- break;
- case EMTP_REALLOC:
- printf(" %" USGND_INT_MAX_FSTR " = realloc(%" USGND_INT_MAX_FSTR
- ", %" USGND_INT_MAX_FSTR ")\n",
- op->u.block.new_ptr,
- op->u.block.prev_ptr,
- op->u.block.new_size);
- break;
- case EMTP_FREE:
- printf(" free(%" USGND_INT_MAX_FSTR ")\n",
- op->u.block.prev_ptr);
- break;
- default:
- printf(" op = %d\n", op->type);
- break;
- }
- }
- fflush(stdout);
-}
-#endif
diff --git a/lib/tools/c_src/erl_memory_trace_block_table.c b/lib/tools/c_src/erl_memory_trace_block_table.c
deleted file mode 100644
index ca7cb45a0e..0000000000
--- a/lib/tools/c_src/erl_memory_trace_block_table.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/* ``Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- * AB. All Rights Reserved.''
- *
- * $Id$
- */
-
-
-/*
- * Description:
- *
- * Author: Rickard Green
- */
-
-/* Headers to include ... */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "erl_memory_trace_block_table.h"
-#include <errno.h>
-
-#undef HARD_DEBUG
-#undef REALLY_HARD_DEBUG
-#ifdef DEBUG
-# define HARD_DEBUG 0
-# define REALLY_HARD_DEBUG 0
-#else
-# define HARD_DEBUG 0
-# define REALLY_HARD_DEBUG 0
-#endif
-
-/* Some system specific defines ... */
-#if defined(__WIN32__) && !defined(__GNUC__)
-# define INLINE __forceinline
-#else
-# ifdef __GNUC__
-# define INLINE __inline__
-# else
-# define INLINE
-# endif
-#endif
-
-/* Our own assert() ... */
-#ifdef DEBUG
-#define ASSERT(A) ((void) ((A) ? 1 : assert_failed(__FILE__, __LINE__, #A)))
-#include <stdio.h>
-static int assert_failed(char *f, int l, char *a)
-{
- fprintf(stderr, "%s:%d: Assertion failed: %s\n", f, l, a);
- abort();
- return 0;
-}
-
-#else
-#define ASSERT(A) ((void) 1)
-#endif
-
-
-#define EMTBT_BLOCKS_PER_POOL 1000
-
-typedef struct emtbt_block_pool_ {
- struct emtbt_block_pool_ *next;
- emtbt_block blocks[1];
-} emtbt_block_pool;
-
-struct emtbt_table_ {
- void * (*alloc)(size_t);
- void * (*realloc)(void *, size_t);
- void (*free)(void *);
- int is_64_bit;
- int no_blocks;
- int no_of_buckets;
- int max_used_buckets;
- int min_used_buckets;
- int used_buckets;
- int current_size_index;
- emtbt_block *blocks;
- emtbt_block ** buckets;
-
-
- /* Fixed size allocation of blocks */
- emtbt_block_pool *block_pools;
- emtbt_block *free_blocks;
- int blocks_per_pool;
-
-};
-
-
-static emtbt_block null_blk = {0};
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * Block table *
- * *
-\* */
-
-#if HARD_DEBUG
-static void check_table(emtbt_table *table);
-#endif
-
-static emtbt_block *
-block_alloc_new_pool(emtbt_table *tab)
-{
- size_t size;
- emtbt_block_pool *poolp;
-
- size = sizeof(emtbt_block_pool) - sizeof(emtbt_block);
- size += tab->blocks_per_pool*sizeof(emtbt_block);
-
- poolp = (*tab->alloc)(size);
-
- if (poolp) {
- int i;
- emtbt_block *blks;
-
- poolp->next = tab->block_pools;
- tab->block_pools = poolp;
-
- blks = (emtbt_block *) poolp->blocks;
-
- for (i = 1; i < tab->blocks_per_pool - 1; i++)
- blks[i].next = &blks[i + 1];
- blks[tab->blocks_per_pool - 1].next = NULL;
- tab->free_blocks = &blks[1];
-
- return &blks[0];
- }
- return NULL;
-}
-
-static INLINE emtbt_block *
-block_alloc(emtbt_table *tab)
-{
- emtbt_block *res;
-#if HARD_DEBUG
- check_table(tab);
-#endif
-
- if (tab->free_blocks) {
- res = tab->free_blocks;
- tab->free_blocks = tab->free_blocks->next;
- }
- else {
- res = block_alloc_new_pool(tab);
- }
-
-#ifdef DEBUG
- res->next = ((emtbt_block *) 0xfffffff0);
- res->prev = ((emtbt_block *) 0xfffffff0);
- res->bucket = ((emtbt_block **) 0xfffffff0);
-#endif
-
-#if HARD_DEBUG
- check_table(tab);
-#endif
-
- return res;
-}
-
-static INLINE void
-block_free(emtbt_table *tab, emtbt_block *bp)
-{
-
-#if HARD_DEBUG
- check_table(tab);
-#endif
-
- bp->next = tab->free_blocks;
- tab->free_blocks = bp;
-
-#if HARD_DEBUG
- check_table(tab);
-#endif
-
-
-}
-
-#define PRIME0 ((usgnd_int_32) 268438039)
-#define PRIME1 ((usgnd_int_32) 268440479)
-#define PRIME2 ((usgnd_int_32) 268439161)
-#define PRIME3 ((usgnd_int_32) 268437017)
-
-#define MK_HASH(H, P, IS64) \
-do { \
- (H) = (P) & 0xff; \
- (H) *= PRIME0; \
- (H) += ((P) >> 8) & 0xff; \
- (H) *= PRIME1; \
- (H) += ((P) >> 16) & 0xff; \
- (H) *= PRIME2; \
- (H) += ((P) >> 24) & 0xff; \
- (H) *= PRIME3; \
- if ((IS64)) { \
- (H) += ((P) >> 32) & 0xff; \
- (H) *= PRIME0; \
- (H) += ((P) >> 40) & 0xff; \
- (H) *= PRIME1; \
- (H) += ((P) >> 48) & 0xff; \
- (H) *= PRIME2; \
- (H) += ((P) >> 56) & 0xff; \
- (H) *= PRIME3; \
- } \
-} while (0)
-
-static const int table_sizes[] = {
- 3203,
- 4813,
- 6421,
- 9643,
- 12853,
- 19289,
- 25717,
- 51437,
- 102877,
- 205759,
- 411527,
- 823117,
- 1646237,
- 3292489,
- 6584983,
- 13169977,
- 26339969,
- 52679969
-};
-
-#if HARD_DEBUG
-
-static void
-check_table(emtbt_table *table)
-{
- int no_blocks;
- emtbt_block *block, *prev_block;
-
- no_blocks = 0;
- block = table->blocks;
- ASSERT(!block || !block->prev);
- prev_block = NULL;
- while (block) {
- usgnd_int_32 hash;
- MK_HASH(hash, block->pointer, table->is_64_bit);
- ASSERT(hash == block->hash);
- ASSERT(block->bucket - table->buckets
- == hash % table->no_of_buckets);
- ASSERT(!prev_block || prev_block == block->prev);
- prev_block = block;
- block = block->next;
- no_blocks++;
- ASSERT(table->no_blocks >= no_blocks);
- }
-
- ASSERT(table->no_blocks == no_blocks);
-
-#if REALLY_HARD_DEBUG
- {
- int i;
- for (i = 0; i < table->no_of_buckets; i++) {
- int bucket_end_found;
- emtbt_block **bucket;
- if (!table->buckets[i])
- continue;
- bucket_end_found = 0;
- bucket = &table->buckets[i];
- for (block = table->blocks; block; block = block->next) {
- if (block->bucket == bucket) {
- if (!block->prev || block->prev->bucket != bucket)
- ASSERT(*bucket == block);
- if (!block->next || block->next->bucket != bucket)
- bucket_end_found++;
- }
- }
- ASSERT(bucket_end_found);
- }
- }
-#endif
-
-}
-
-#endif
-
-static INLINE void
-link_block(emtbt_table *table, emtbt_block **bucket, emtbt_block *block)
-{
- ASSERT(bucket);
-
- block->bucket = bucket;
- if (*bucket) {
- block->next = *bucket;
- block->prev = (*bucket)->prev;
- if (block->prev)
- block->prev->next = block;
- else
- table->blocks = block;
- block->next->prev = block;
- }
- else {
- block->next = table->blocks;
- block->prev = NULL;
- if (table->blocks)
- table->blocks->prev = block;
- table->blocks = block;
- table->used_buckets++;
-
- }
- *bucket = block;
- table->no_blocks++;
-
-#if HARD_DEBUG
- check_table(table);
-#endif
-
-}
-
-static int
-resize_table(emtbt_table *table, int new_no_of_buckets)
-{
-#ifdef DEBUG
- int org_no_blocks;
-#endif
- int i;
- emtbt_block *block;
- emtbt_block **buckets;
-
- if (new_no_of_buckets < table->no_of_buckets) {
- /* shrink never fails */
- buckets = (emtbt_block **) (*table->realloc)(table->buckets,
- (sizeof(emtbt_block *)
- * new_no_of_buckets));
- if (!buckets)
- return 1;
- }
- else if (new_no_of_buckets > table->no_of_buckets) {
- (*table->free)((void *) table->buckets);
- buckets = (emtbt_block **) (*table->alloc)((sizeof(emtbt_block *)
- * new_no_of_buckets));
- if (!buckets)
- return 0;
- }
- else
- return 1;
-
- table->buckets = buckets;
- table->no_of_buckets = new_no_of_buckets;
- table->max_used_buckets = (4*new_no_of_buckets)/5;
- table->min_used_buckets = new_no_of_buckets/5;
- table->used_buckets = 0;
-
-#ifdef DEBUG
- org_no_blocks = table->no_blocks;
-#endif
-
- table->no_blocks = 0;
-
-
- for (i = 0; i < new_no_of_buckets; i++)
- buckets[i] = NULL;
-
- block = table->blocks;
- table->blocks = NULL;
-
- while (block) {
- emtbt_block *next_block = block->next;
- link_block(table,&table->buckets[block->hash%new_no_of_buckets],block);
- block = next_block;
- }
-
- ASSERT(org_no_blocks == table->no_blocks);
-
- return 1;
-}
-
-static INLINE int
-grow_table(emtbt_table *table)
-{
- if (table->current_size_index < sizeof(table_sizes)/sizeof(int)) {
- int new_size;
- table->current_size_index++;
- new_size = table_sizes[table->current_size_index];
- ASSERT(new_size > 0);
- return resize_table(table, new_size);
- }
- return 1;
-}
-
-static INLINE void
-shrink_table(emtbt_table *table)
-{
- if (table->current_size_index > 0) {
- int new_size;
- table->current_size_index--;
- new_size = table_sizes[table->current_size_index];
- ASSERT(new_size > 0);
- (void) resize_table(table, new_size);
- }
-}
-
-static INLINE emtbt_block *
-peek_block(emtbt_table *table, usgnd_int_max ptr)
-{
- emtbt_block **bucket;
- emtbt_block *block;
- usgnd_int_32 hash;
-
- MK_HASH(hash, ptr, table->is_64_bit);
-
- bucket = &table->buckets[hash % table->no_of_buckets];
- block = *bucket;
- if (!block)
- return NULL;
-
- while (block->bucket == bucket) {
- ASSERT(block);
- if (block->pointer == ptr)
- return block;
- if (!block->next)
- break;
- block = block->next;
- }
- return NULL;
-}
-
-static INLINE int
-insert_block(emtbt_table *table, emtbt_block *block)
-{
- emtbt_block **bucket;
- emtbt_block *tmp_block;
- usgnd_int_32 hash;
- usgnd_int_max p;
-
-#if HARD_DEBUG
- check_table(table);
-#endif
-
- if (table->used_buckets >= table->max_used_buckets) {
- if(!grow_table(table))
- return -1;
- }
-
- p = block->pointer;
-
- MK_HASH(hash, p, table->is_64_bit);
- block->hash = hash;
-
- bucket = &table->buckets[hash % table->no_of_buckets];
- tmp_block = *bucket;
- if (tmp_block) {
- while (tmp_block->bucket == bucket) {
- if (tmp_block->pointer == p)
- return 0;
- if (!tmp_block->next)
- break;
- tmp_block = tmp_block->next;
- }
- }
-
- link_block(table, bucket, block);
-
- ASSERT(block == peek_block(table, p));
-
-
- return 1;
-}
-
-static INLINE void
-delete_block(emtbt_table *table, emtbt_block *block)
-{
- emtbt_block **bucket;
-
- if (!block)
- return;
-
-#if HARD_DEBUG
- check_table(table);
-#endif
-
- bucket = block->bucket;
- ASSERT(bucket);
-
- if (block->prev)
- block->prev->next = block->next;
- else
- table->blocks = block->next;
-
- if (block->next)
- block->next->prev = block->prev;
-
- if (block == *bucket) {
- ASSERT(!block->prev || block->prev->bucket != bucket);
- if (block->next && block->next->bucket == bucket)
- *bucket = block->next;
- else {
- ASSERT(table->used_buckets > 0);
- *bucket = NULL;
- table->used_buckets--;
- }
- }
-#ifdef DEBUG
-
- block->next = ((emtbt_block *) 0xfffffff0);
- block->prev = ((emtbt_block *) 0xfffffff0);
- block->bucket = ((emtbt_block **) 0xfffffff0);
-#endif
-
- ASSERT(table->no_blocks > 0);
- table->no_blocks--;
-
- if (table->used_buckets < table->min_used_buckets)
- shrink_table(table);
-
-#if HARD_DEBUG
- check_table(table);
-#endif
-
-}
-
-static INLINE emtbt_block *
-fetch_block(emtbt_table *table, usgnd_int_max ptr)
-{
- emtbt_block *block;
-
- block = peek_block(table, ptr);
- delete_block(table, block);
- return block;
-}
-
-
-const char *emtbt_error_string(int error)
-{
- switch (error) {
- case EMTBT_ALLOC_XBLK_ERROR:
- return "Allocation to an already existing block";
- case EMTBT_REALLOC_NOBLK_ERROR:
- return "Reallocation of non-existing block";
- case EMTBT_REALLOC_XBLK_ERROR:
- return "Reallocation to an already existing block";
- case EMTBT_REALLOC_BLK_TYPE_MISMATCH:
- return "Block types mismatch when reallocating";
- case EMTBT_FREE_NOBLK_ERROR:
- return "Deallocation of non-existing block";
- case EMTBT_FREE_BLK_TYPE_MISMATCH:
- return "Block types mismatch when deallocating";
- case EMTBT_INTERNAL_ERROR:
- return "Block table internal error";
- default:
- return NULL;
- }
-
-
-}
-
-
-emtbt_table *
-emtbt_new_table(int is_64_bit,
- void * (*alloc)(size_t),
- void * (*realloc)(void *, size_t),
- void (*free)(void *))
-{
- emtbt_table *tab = (*alloc)(sizeof(emtbt_table));
- if (tab) {
- tab->alloc = alloc;
- tab->realloc = realloc;
- tab->free = free;
- tab->is_64_bit = is_64_bit;
- tab->no_blocks = 0;
- tab->no_of_buckets = 0;
- tab->max_used_buckets = 0;
- tab->min_used_buckets = 0;
- tab->used_buckets = 0;
- tab->current_size_index = 0;
- tab->blocks = NULL;
- tab->buckets = NULL;
-
- tab->block_pools = NULL;
- tab->free_blocks = NULL;
- tab->blocks_per_pool = EMTBT_BLOCKS_PER_POOL;
-
- }
- return tab;
-}
-
-void
-emtbt_destroy_table(emtbt_table *tab)
-{
- void (*freep)(void *);
- emtbt_block_pool *poolp1, *poolp2;
-
- freep = tab->free;
-
- /* Free block pools */
- poolp1 = tab->block_pools;
- while (poolp1) {
- poolp2 = poolp1;
- poolp1 = poolp1->next;
- (*freep)((void *) poolp2);
- }
-
- if (tab->buckets)
- (*freep)((void *) tab->buckets);
-
- (*freep)((void *) tab);
-}
-
-
-#define CP_BLK(TO, FROM) \
-do { \
- (TO)->time.secs = (FROM)->time.secs; \
- (TO)->time.usecs = (FROM)->time.usecs; \
- (TO)->type = (FROM)->type; \
- (TO)->pointer = (FROM)->pointer; \
- (TO)->size = (FROM)->size; \
-} while (0)
-
-int
-emtbt_alloc_op(emtbt_table *tab, emtp_operation *op)
-{
- int res;
- emtbt_block *blk;
-
- blk = block_alloc(tab);
- if (!blk)
- return ENOMEM;
-
- blk->time.secs = op->time.secs;
- blk->time.usecs = op->time.usecs;
- blk->type = op->u.block.type;
- blk->pointer = op->u.block.new_ptr;
- blk->size = op->u.block.new_size;
-
- res = insert_block(tab, blk);
- if (res < 0)
- return ENOMEM;
- else if (res == 0)
- return EMTBT_ALLOC_XBLK_ERROR;
- return 0;
-}
-
-int
-emtbt_realloc_op(emtbt_table *tab, emtp_operation *op, emtbt_block *old_blk)
-{
- int res;
- emtbt_block *blk;
-
- if (!op->u.block.new_size) {
- /* freed block */
-
- blk = fetch_block(tab, op->u.block.prev_ptr);
- if (!blk)
- return EMTBT_REALLOC_NOBLK_ERROR;
-
- CP_BLK(old_blk, blk);
- block_free(tab, blk);
- }
- else {
-
- if (!op->u.block.new_ptr) {
- /* failed operation */
- if (!op->u.block.prev_ptr)
- CP_BLK(old_blk, &null_blk);
- else {
- blk = peek_block(tab, op->u.block.prev_ptr);
- if (!blk)
- return EMTBT_REALLOC_NOBLK_ERROR;
- CP_BLK(old_blk, blk);
-#if 0
- if (blk->type != op->u.block.type)
- return EMTBT_REALLOC_BLK_TYPE_MISMATCH;
-#endif
- }
- }
- else if (!op->u.block.prev_ptr) {
- /* new block */
-
- CP_BLK(old_blk, &null_blk);
- blk = block_alloc(tab);
- if (!blk)
- return ENOMEM;
- blk->type = op->u.block.type;
- blk->pointer = op->u.block.new_ptr;
- blk->time.secs = op->time.secs;
- blk->time.usecs = op->time.usecs;
- blk->size = op->u.block.new_size;
-
- res = insert_block(tab, blk);
- if (res < 0)
- return ENOMEM;
- else if (res == 0)
- return EMTBT_REALLOC_XBLK_ERROR;
- }
- else if (op->u.block.new_ptr == op->u.block.prev_ptr) {
- /* resized block */
- blk = peek_block(tab, op->u.block.prev_ptr);
- if (!blk)
- return EMTBT_REALLOC_NOBLK_ERROR;
- CP_BLK(old_blk, blk);
- blk->time.secs = op->time.secs;
- blk->time.usecs = op->time.usecs;
- blk->size = op->u.block.new_size;
-#if 0
- if (blk->type != op->u.block.type)
- return EMTBT_REALLOC_BLK_TYPE_MISMATCH;
-#endif
- }
- else {
- /* moved block */
- blk = fetch_block(tab, op->u.block.prev_ptr);
- if (!blk)
- return EMTBT_REALLOC_NOBLK_ERROR;
- CP_BLK(old_blk, blk);
- blk->time.secs = op->time.secs;
- blk->time.usecs = op->time.usecs;
- blk->pointer = op->u.block.new_ptr;
- blk->size = op->u.block.new_size;
- res = insert_block(tab, blk);
- if (res < 0)
- return ENOMEM;
- else if (res == 0)
- return EMTBT_REALLOC_XBLK_ERROR;
-#if 0
- if (blk->type != op->u.block.type)
- return EMTBT_REALLOC_BLK_TYPE_MISMATCH;
-#endif
- }
- }
- return 0;
-
-}
-
-
-int
-emtbt_free_op(emtbt_table *tab, emtp_operation *op, emtbt_block *old_blk)
-{
- emtbt_block *blk;
-
- if (!op->u.block.prev_ptr)
- CP_BLK(old_blk, &null_blk);
- else {
-
- blk = fetch_block(tab, op->u.block.prev_ptr);
- if (!blk)
- return EMTBT_FREE_NOBLK_ERROR;
-
- CP_BLK(old_blk, blk);
- block_free(tab, blk);
-#if 0
- if (blk->type != op->u.block.type)
- return EMTBT_FREE_BLK_TYPE_MISMATCH;
-#endif
- }
- return 0;
-}
diff --git a/lib/tools/c_src/erl_memory_trace_block_table.h b/lib/tools/c_src/erl_memory_trace_block_table.h
deleted file mode 100644
index ead3afc8fb..0000000000
--- a/lib/tools/c_src/erl_memory_trace_block_table.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ``Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
- * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
- * AB. All Rights Reserved.''
- *
- * $Id$
- */
-
-
-/*
- * Description:
- *
- * Author: Rickard Green
- */
-
-#ifndef ERL_MEMORY_TRACE_BLOCK_TABLE_H__
-#define ERL_MEMORY_TRACE_BLOCK_TABLE_H__
-
-#include <stdlib.h>
-#include "erl_fixed_size_int_types.h"
-#include "erl_memory_trace_parser.h"
-
-
-#define EMTBT_ALLOC_XBLK_ERROR (EMTP_MIN_ERROR - 1)
-#define EMTBT_REALLOC_NOBLK_ERROR (EMTP_MIN_ERROR - 2)
-#define EMTBT_REALLOC_XBLK_ERROR (EMTP_MIN_ERROR - 3)
-#define EMTBT_REALLOC_BLK_TYPE_MISMATCH (EMTP_MIN_ERROR - 4)
-#define EMTBT_FREE_NOBLK_ERROR (EMTP_MIN_ERROR - 5)
-#define EMTBT_FREE_BLK_TYPE_MISMATCH (EMTP_MIN_ERROR - 6)
-#define EMTBT_INTERNAL_ERROR (EMTP_MIN_ERROR - 7)
-
-#define EMTBT_MIN_ERROR EMTBT_INTERNAL_ERROR
-
-
-typedef struct emtbt_block_ {
-
- struct emtbt_block_ * next;
- struct emtbt_block_ * prev;
- usgnd_int_32 hash;
- struct emtbt_block_ ** bucket;
-
- struct {
- usgnd_int_32 secs;
- usgnd_int_32 usecs;
- } time;
- usgnd_int_16 type;
- usgnd_int_max pointer;
- usgnd_int_max size;
-} emtbt_block;
-
-typedef struct emtbt_table_ emtbt_table;
-
-const char *emtbt_error_string(int);
-emtbt_table *emtbt_new_table(int,
- void * (*)(size_t),
- void * (*)(void *, size_t),
- void (*)(void *));
-void emtbt_destroy_table(emtbt_table *);
-int emtbt_alloc_op(emtbt_table *tab, emtp_operation *op);
-int emtbt_realloc_op(emtbt_table *, emtp_operation *, emtbt_block *);
-int emtbt_free_op(emtbt_table *, emtp_operation *, emtbt_block *);
-
-#endif
diff --git a/lib/tools/doc/src/cover.xml b/lib/tools/doc/src/cover.xml
index 9bcaa9227d..c9c7d2e6fc 100644
--- a/lib/tools/doc/src/cover.xml
+++ b/lib/tools/doc/src/cover.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2001</year>
- <year>2020</year>
+ <year>2022</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -110,7 +110,7 @@
<p>If the connection to a remote node goes down, the main node
will mark it as lost. If the node comes back it will be added
again. If the remote node was alive during the disconnected
- periode, cover data from before and during this periode will be
+ period, cover data from before and during this period will be
included in the analysis.</p>
</description>
<funcs>
diff --git a/lib/tools/doc/src/cprof_chapter.xml b/lib/tools/doc/src/cprof_chapter.xml
index af13b8d8d7..671f9717a6 100644
--- a/lib/tools/doc/src/cprof_chapter.xml
+++ b/lib/tools/doc/src/cprof_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2021</year>
+ <year>2002</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,7 +37,7 @@
</p>
<p><c>cprof</c> uses breakpoints similar to local call trace,
but containing counters, to collect profiling
- data. Therfore there is no need for special compilation of any
+ data. Therefore there is no need for special compilation of any
module to be profiled.
</p>
<p><c>cprof</c> presents all profiled modules in decreasing total
@@ -96,33 +96,38 @@
<p>From the Erlang shell:</p>
<pre>
1> <input>cprof:start(), cprof:pause(). % Stop counters just after start</input>
-3476
+8492
2> <input>cprof:analyse().</input>
-{30,
- [{erl_eval,11,
- [{{erl_eval,expr,3},3},
- {{erl_eval,'-merge_bindings/2-fun-0-',2},2},
- {{erl_eval,expand_module_name,2},1},
- {{erl_eval,merge_bindings,2},1},
- {{erl_eval,binding,2},1},
- {{erl_eval,expr_list,5},1},
- {{erl_eval,expr_list,3},1},
- {{erl_eval,exprs,4},1}]},
- {orddict,8,
- [{{orddict,find,2},6},
- {{orddict,dict_to_list,1},1},
- {{orddict,to_list,1},1}]},
- {packages,7,[{{packages,is_segmented_1,1},6},
- {{packages,is_segmented,1},1}]},
- {lists,4,[{{lists,foldl,3},3},{{lists,reverse,1},1}]}]}
+{539,
+ [{shell,155,
+ [{{shell,prep_check,1},55},
+ {{shell,used_records,4},45},
+ {{shell,used_records,1},45},
+ {{shell,used_record_defs,2},1},
+ {{shell,record_defs,2},1},
+ {{shell,record_bindings,2},1},
+ {{shell,exprs,7},1},
+ {{shell,expr,4},1},
+ {{shell,expand_records,2},1},
+ {{shell,check_command,2},1},
+ {{shell,apply_fun,3},1},
+ {{shell,'-exprs/7-lc$^0/1-0-',1},1},
+ {{shell,'-eval_loop/3-fun-0-',3},1}]},
+ %% Information about many modules omitted.
+ .
+ .
+ .
+ %% Here is the last part.
+ {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]},
+ {otp_internal,1,[{{otp_internal,obsolete,3},1}]},
+ {maps,1,[{{maps,from_list,1},1}]},
+ {erl_internal,1,[{{erl_internal,bif,3},1}]}]}
3> <input>cprof:analyse(cprof).</input>
{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]}
4> <input>cprof:stop().</input>
-3476</pre>
- <p>The example showed the background work that the shell performs
- just to interpret the first command line. Most work is done by
- <c>erl_eval</c> and <c>orddict</c>.
- </p>
+8586</pre>
+ <p>The example showed some of the background work that the shell
+ performs just to interpret the first command line.</p>
<p>What is captured in this example is the part of the work the
shell does while interpreting the command line that occurs
between the actual calls to <c>cprof:start()</c> and
@@ -138,17 +143,17 @@
1
2> <input>cprof:analyse(calendar).</input>
{calendar,9,
- [{{calendar,df,2},1},
- {{calendar,dm,1},1},
- {{calendar,dy,1},1},
- {{calendar,last_day_of_the_month1,2},1},
+ [{{calendar,last_day_of_the_month1,2},1},
{{calendar,last_day_of_the_month,2},1},
{{calendar,is_leap_year1,1},1},
{{calendar,is_leap_year,1},1},
+ {{calendar,dy,1},1},
+ {{calendar,dm,1},1},
+ {{calendar,df,2},1},
{{calendar,day_of_the_week,3},1},
{{calendar,date_to_gregorian_days,3},1}]}
3> <input>cprof:stop().</input>
-3271</pre>
+8648</pre>
<p>The example tells us that "Aktiebolaget LM Ericsson &amp; Co"
was registered on a Monday (since the return value
of the first command is 1), and that the <c>calendar</c> module
@@ -164,66 +169,70 @@
<p>Write a module:</p>
<pre>
-module(sort).
-
-export([do/1]).
-
+
do(N) ->
cprof:stop(),
cprof:start(),
do(N, []).
-
+
do(0, L) ->
R = lists:sort(L),
cprof:pause(),
R;
do(N, L) ->
- do(N-1, [random:uniform(256)-1 | L]).</pre>
+ do(N-1, [rand:uniform(256)-1 | L]).</pre>
<p>From the Erlang shell:</p>
<pre>
1> <input>c(sort).</input>
{ok,sort}
-2> <input>l(random).</input>
-{module,random}
+2> <input>rand:seed(default, 42), ok.</input>
+ok.
3> <input>sort:do(1000).</input>
-[0,0,1,1,1,1,1,1,2,2,2,3,3,3,3,3,4,4,4,5,5,5,5,6,6,6,6,6,6|...]
+[0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,5,5,5,6,6,6,6,7,7,7,7,7,8,8|...]
4> <input>cprof:analyse().</input>
-{9050,
- [{lists_sort,6047,
- [{{lists_sort,merge3_2,6},923},
- {{lists_sort,merge3_1,6},879},
- {{lists_sort,split_2,5},661},
- {{lists_sort,rmerge3_1,6},580},
- {{lists_sort,rmerge3_2,6},543},
- {{lists_sort,merge3_12_3,6},531},
- {{lists_sort,merge3_21_3,6},383},
- {{lists_sort,split_2_1,6},338},
- {{lists_sort,rmerge3_21_3,6},299},
- {{lists_sort,rmerge3_12_3,6},205},
- {{lists_sort,rmerge2_2,4},180},
- {{lists_sort,rmerge2_1,4},171},
- {{lists_sort,merge2_1,4},127},
- {{lists_sort,merge2_2,4},121},
- {{lists_sort,mergel,2},79},
- {{lists_sort,rmergel,2},27}]},
- {random,2001,
- [{{random,uniform,1},1000},
- {{random,uniform,0},1000},
- {{random,seed0,0},1}]},
+{13180,
+ [{lists,6173,
+ [{{lists,rmerge3_1,6},1045},
+ {{lists,rmerge3_2,6},977},
+ {{lists,split_1,5},652},
+ {{lists,merge3_1,6},579},
+ {{lists,merge3_2,6},577},
+ {{lists,rmerge3_12_3,6},511},
+ {{lists,split_1_1,6},347},
+ {{lists,merge3_12_3,6},310},
+ {{lists,rmerge3_21_3,6},282},
+ {{lists,merge3_21_3,6},221},
+ {{lists,merge2_1,4},154},
+ {{lists,merge2_2,5},138},
+ {{lists,reverse,2},106},
+ {{lists,rmerge2_2,5},87},
+ {{lists,rmergel,2},81},
+ {{lists,rmerge2_1,4},75},
+ {{lists,mergel,2},28},
+ {{lists,keyfind,3},2},
+ {{lists,sort,1},1}]},
+ {rand,5000,
+ [{{rand,uniform_s,2},1000},
+ {{rand,uniform,1},1000},
+ {{rand,seed_put,1},1000},
+ {{rand,seed_get,0},1000},
+ {{rand,exsss_uniform,2},1000}]},
+ {erlang,1004,
+ [{{erlang,put,2},1000},
+ {{erlang,trace_pattern,3},2},
+ {{erlang,ensure_tracer_module_loaded,2},2}]},
{sort,1001,[{{sort,do,2},1001}]},
- {lists,1,[{{lists,sort,1},1}]}]}
+ {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]}]}
5> <input>cprof:stop().</input>
-5369</pre>
+12625</pre>
<p>The example shows some details of how <c>lists:sort/1</c>
- works. It used 6047 function calls in the module
- <c>lists_sort</c> to complete the work.
- </p>
- <p>This time, since the shell was not involved, no other work was
- done in the system during the profiling. If you retry the same
- example with a freshly started Erlang emulator, but omit the
- command <c>l(random)</c>, the analysis will show a lot more
- function calls done by <c>code_server</c> and others to
- automatically load the module <c>random</c>.
+ works. It used 6173 function calls in the module
+ <c>lists</c> to complete the work.
</p>
+ <p>This time, since the shell was not involved in starting and
+ stopping <c>cprof</c>, no other work was done in the system during
+ the profiling.</p>
</section>
</chapter>
diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml
index b10624751f..a1e25b5505 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>2020</year>
+ <year>1996</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -74,7 +74,7 @@
<p>Stops profiling started with
<seemfa marker="#start_profiling/1"><c>start_profiling/1</c></seemfa>
or
- <seemfa marker="#profile/1"><c>prifile/1</c></seemfa>.</p>
+ <seemfa marker="#profile/1"><c>profile/1</c></seemfa>.</p>
</desc>
</func>
<func>
diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml
index e7e7ad69f3..4e4e466fc7 100644
--- a/lib/tools/doc/src/fprof.xml
+++ b/lib/tools/doc/src/fprof.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2021</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -485,7 +485,7 @@
<item>Includes a section containing call statistics
for all calls regardless of process, in the analysis.</item>
<tag><c>{totals, false}</c></tag>
- <item>Supresses the totals section in the analysis, which is
+ <item>Suppresses the totals section in the analysis, which is
the default.</item>
<tag><c>details</c> | <c>{details, true}</c></tag>
<item>Prints call statistics for each process in the
@@ -686,7 +686,7 @@ create_file_slow(FD, M, N) ->
{{fprof,apply_start_stop,4}, 1, 0.000, 0.000}],
{ suspend, 299, 32.002, 0.000}, %
[ ]}.</pre>
- <p>We find no particulary long suspend times, so no function seems
+ <p>We find no particularly long suspend times, so no function seems
to have waited in a receive statement. Actually,
<c>prim_file:drv_command/4</c> contains a receive statement, but
in this test program, the message lies in the process receive
diff --git a/lib/tools/doc/src/fprof_chapter.xml b/lib/tools/doc/src/fprof_chapter.xml
index 65ffcede1a..b07eef2637 100644
--- a/lib/tools/doc/src/fprof_chapter.xml
+++ b/lib/tools/doc/src/fprof_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2021</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,7 +37,7 @@
processes.
</p>
<p><c>fprof</c> uses tracing with timestamps to collect profiling
- data. Therfore there is no need for special compilation of any
+ data. Therefore there is no need for special compilation of any
module to be profiled.
</p>
<p><c>fprof</c> presents wall clock times from the host machine OS,
diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml
index 4305bad599..80a5e8c3ba 100644
--- a/lib/tools/doc/src/instrument.xml
+++ b/lib/tools/doc/src/instrument.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2021</year>
+ <year>1998</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,11 +36,12 @@
<modulesummary>Analysis and Utility Functions for Instrumentation</modulesummary>
<description>
<p>The module <c>instrument</c> contains support for studying the resource
- usage in an Erlang runtime system. Currently, only the allocation of memory can
- be studied.</p>
+ usage in an Erlang runtime system. Currently, only the allocation of
+ memory can be studied.</p>
<note>
- <p>Note that this whole module is experimental, and the representations
- used as well as the functionality is likely to change in the future.</p>
+ <p>Since this module inspects internal details of the runtime system it
+ may differ greatly from one version to another. We make no compatibility
+ guarantees in this module.</p>
</note>
</description>
<datatypes>
@@ -52,6 +53,13 @@
<p>The upper bound of the first interval is provided by the function
that returned the histogram, and the last interval has no upper
bound.</p>
+ <p>For example, the histogram below has 40 (<c>message</c>) blocks
+ between 256-512 bytes in size, 78 blocks between 512-1024 bytes,2
+ blocks between 1-2KB, and 2 blocks between 2-4KB.</p>
+ <code type="none"><![CDATA[
+> instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
+{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}
+ ]]></code>
</desc>
</datatype>
<datatype>
@@ -62,7 +70,10 @@
<p><c><anno>Origin</anno></c> is generally which NIF or driver that
allocated the blocks, or 'system' if it could not be determined.</p>
<p><c><anno>Type</anno></c> is the allocation category that the blocks
- belong to, e.g. <c>db_term</c>, <c>message</c> or <c>binary</c>.</p>
+ belong to, e.g. <c>db_term</c>, <c>message</c> or <c>binary</c>. The
+ categories correspond to those in
+ <url href="https://github.com/erlang/otp/blob/master/erts/emulator/beam/erl_alloc.types">
+ erl_alloc.types</url>.</p>
<p>If one or more carriers could not be scanned in full without harming
the responsiveness of the system, <c><anno>UnscannedSize</anno></c>
is the number of bytes that had to be skipped.</p>
@@ -78,7 +89,10 @@
<p><c><anno>TotalSize</anno></c> is the total size of the carrier,
including its header.</p>
<p><c><anno>Allocations</anno></c> is a summary of the allocated blocks
- in the carrier.</p>
+ in the carrier. Note that carriers may contain multiple different
+ block types when carrier pools are shared between different allocator
+ types (see the <seecref marker="erts:erts_alloc#M_cp"><c>erts_alloc</c>
+ </seecref> documentation for more details).</p>
<p><c><anno>FreeBlocks</anno></c> is a histogram of the free block
sizes in the carrier.</p>
<p>If the carrier could not be scanned in full without harming the
@@ -115,11 +129,13 @@
<taglist>
<tag><c>allocator_types</c></tag>
<item>
- <p>The allocator types that will be searched. Note that blocks can
- move freely between allocator types, so restricting the search to
- certain allocators may return unexpected types (e.g. process
- heaps when searching binary_alloc), or hide blocks that were
- migrated out.</p>
+ <p>The allocator types that will be searched.</p>
+ <p>Specifying a specific allocator type may lead to strange results
+ when carrier migration between different allocator types has been
+ enabled: you may see unexpected types (e.g. process heaps when
+ searching binary_alloc), or fewer blocks than expected if the
+ carriers the blocks are on have been migrated out to an allocator
+ of a different type.</p>
<p>Defaults to all <c>alloc_util</c> allocators.</p>
</item>
<tag><c>scheduler_ids</c></tag>
@@ -217,10 +233,12 @@
<code type="none"><![CDATA[
> instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
{ok,{512,
- [{ll_alloc,1048576,0,1048344,71,false,{0,0,0,0,0,0,0,0}},
- {binary_alloc,1048576,0,324640,13,false,{3,0,0,1,0,0,0,2}},
- {eheap_alloc,2097152,0,1037200,45,false,{2,1,1,3,4,3,2,2}},
- {fix_alloc,32768,0,29544,82,false,{22,0,0,0,0,0,0,0}},
+ [{driver_alloc,false,262144,0,
+ [{driver_alloc,1,32784}],
+ {0,0,0,0,0,0,0,1}},
+ {binary_alloc,false,32768,0,
+ [{binary_alloc,15,4304}],
+ {3,0,0,0,1,0,0,0}},
{...}|...]}}
]]></code>
</desc>
diff --git a/lib/tools/doc/src/lcnt_chapter.xml b/lib/tools/doc/src/lcnt_chapter.xml
index c8afd7063d..a9628525c9 100644
--- a/lib/tools/doc/src/lcnt_chapter.xml
+++ b/lib/tools/doc/src/lcnt_chapter.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2009</year><year>2021</year>
+ <year>2009</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,7 +42,7 @@
completed its access to the resource and unlocked it. The <c>lcnt</c> tool measures these lock conflicts.
</p>
<p>
- Locks have an inherent cost in execution time and memory space. It takes time initialize, destroy, aquiring or releasing locks. To decrease lock contention it
+ Locks have an inherent cost in execution time and memory space. It takes time initialize, destroy, acquiring or releasing locks. To decrease lock contention it
some times necessary to use finer grained locking strategies. This will usually also increase the locking overhead and hence there is a tradeoff
between lock contention and overhead. In general, lock contention increases with the number of threads running concurrently. The <c>lcnt</c> tool does not measure locking overhead.
</p>
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 0680f28f71..84a6019e57 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -31,6 +31,22 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 3.5.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Removed the previously undocumented and unsupported
+ <c>emem</c> tool.</p>
+ <p>
+ Own Id: OTP-17892 Aux Id: PR-5591 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 3.5.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/doc/src/notes_history.xml b/lib/tools/doc/src/notes_history.xml
index d955cbde69..7ef93d6fbf 100644
--- a/lib/tools/doc/src/notes_history.xml
+++ b/lib/tools/doc/src/notes_history.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2016</year>
+ <year>2006</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -91,7 +91,7 @@
<p>Own Id: OTP-4594</p>
</item>
<item>
- <p>Improvments for support of Emacs 21 contributed by Dave
+ <p>Improvements for support of Emacs 21 contributed by Dave
Love. The bulk of the changes are actually cosmetic
commentary/doc fixes. The significant ones make it play
better with Emacs 21 with up-to-date facilities. In
diff --git a/lib/tools/emacs/Makefile b/lib/tools/emacs/Makefile
index c19ad3668c..279ae5f805 100644
--- a/lib/tools/emacs/Makefile
+++ b/lib/tools/emacs/Makefile
@@ -59,7 +59,7 @@ ELC_FILES = $(EMACS_FILES:%=%.elc)
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(EL_FILES)
+$(TYPES): $(TARGET_FILES) $(EL_FILES)
clean:
rm -f $(TARGET_FILES) $(ELC_FILES)
diff --git a/lib/tools/emacs/README b/lib/tools/emacs/README
index cc107dcd41..8916e65250 100644
--- a/lib/tools/emacs/README
+++ b/lib/tools/emacs/README
@@ -34,13 +34,13 @@ variable. If HOME is not set, Emacs will look for the .emacs file in
C:\.
Below is a complete example of what should be added to a user's .emacs
-provided that OTP is installed in the directory C:\Program
-Files\erl-<Ver>:
+provided that OTP is installed in the directory "C:\Program
+Files\Erlang OTP":
(setq load-path (cons "C:/Program Files/erl<Ver>/lib/tools-<ToolsVer>/emacs"
load-path))
- (setq erlang-root-dir "C:/Program Files/erl<Ver>")
- (setq exec-path (cons "C:/Program Files/erl<Ver>/bin" exec-path))
+ (setq erlang-root-dir "C:/Program Files/Erlang OTP")
+ (setq exec-path (cons "C:/Program Files/Erlang OTP/bin" exec-path))
(require 'erlang-start)
diff --git a/lib/tools/emacs/erlang-eunit.el b/lib/tools/emacs/erlang-eunit.el
index 1130bc0cde..f7c69daaa1 100644
--- a/lib/tools/emacs/erlang-eunit.el
+++ b/lib/tools/emacs/erlang-eunit.el
@@ -1,7 +1,7 @@
;;
;; %CopyrightBegin%
;;
-;; Copyright Ericsson AB 2009-2021. All Rights Reserved.
+;; Copyright Ericsson AB 2009-2022. All Rights Reserved.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ a source file. The first directory in the list will be used,
if there is no match.")
(defvar erlang-eunit-autosave nil
- "*Set to non-nil to automtically save unsaved buffers before running tests.
+ "*Set to non-nil to automatically save unsaved buffers before running tests.
This is useful, reducing the save-compile-load-test cycle to one keychord.")
(defvar erlang-eunit-recent-info '((mode . nil) (module . nil) (test . nil) (cover . nil))
diff --git a/lib/tools/emacs/erlang-skels-old.el b/lib/tools/emacs/erlang-skels-old.el
index 4087bc3013..7d503c4bc1 100644
--- a/lib/tools/emacs/erlang-skels-old.el
+++ b/lib/tools/emacs/erlang-skels-old.el
@@ -1,7 +1,7 @@
;;
;; %CopyrightBegin%
;;
-;; Copyright Ericsson AB 2010-2016. All Rights Reserved.
+;; Copyright Ericsson AB 2010-2022. All Rights Reserved.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
@@ -368,7 +368,7 @@ Please see the function `tempo-define-template'.")
"%% supervisor_bridge callbacks" n
(erlang-skel-double-separator 2)
(erlang-skel-separator 2)
- "%% Funcion: init(Args) -> {ok, Pid, State} |" n
+ "%% Function: init(Args) -> {ok, Pid, State} |" n
"%% ignore |" n
"%% {error, Reason} " n
"%% Description:Creates a supervisor_bridge process, linked to the calling" n
diff --git a/lib/tools/emacs/erlang-start.el b/lib/tools/emacs/erlang-start.el
index c35f280bf4..a19f72e243 100644
--- a/lib/tools/emacs/erlang-start.el
+++ b/lib/tools/emacs/erlang-start.el
@@ -74,9 +74,9 @@
"Find manual page for NAME, where NAME is module:function." t)
(autoload 'erlang-find-tag "erlang"
- "Like `find-tag'. Capable of retreiving Erlang modules.")
+ "Like `find-tag'. Capable of retrieving Erlang modules.")
(autoload 'erlang-find-tag-other-window "erlang"
- "Like `find-tag-other-window'. Capable of retreiving Erlang modules.")
+ "Like `find-tag-other-window'. Capable of retrieving Erlang modules.")
;;
;; Declare functions in "erlang-edoc.el".
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 7216d6b6fd..065e180804 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -678,6 +678,8 @@ resulting regexp is surrounded by \\_< and \\_>."
"of"
"receive"
"try"
+ "maybe"
+ "else"
"when")
"Erlang reserved keywords"))
@@ -1466,8 +1468,8 @@ Other commands:
(modify-syntax-entry ?\n ">" table)
(modify-syntax-entry ?\" "\"" table)
(modify-syntax-entry ?# "." table)
- ;; (modify-syntax-entry ?$ "\\" table) ;; Creates problems with indention afterwards
- ;; (modify-syntax-entry ?$ "'" table) ;; Creates syntax highlighting and indention problems
+ ;; (modify-syntax-entry ?$ "\\" table) ;; Creates problems with indentation afterwards
+ ;; (modify-syntax-entry ?$ "'" table) ;; Creates syntax highlighting and indentation problems
(modify-syntax-entry ?$ "/" table) ;; Misses the corner case "string that ends with $"
;; we have to live with that for now..it is the best alternative
;; that can be worked around with "string that ends with \$"
@@ -2730,13 +2732,13 @@ Value is list (stack token-start token-type in-what)."
;; Word constituent: check and handle keywords.
((= cs ?w)
- (cond ((looking-at "\\(end\\|after\\)[^_a-zA-Z0-9]")
+ (cond ((looking-at "\\(end\\|after\\|else\\)[^_a-zA-Z0-9]")
;; Must pop top icr layer, `after' will push a new
;; layer next.
(progn
(while (and stack (eq (car (car stack)) '->))
(erlang-pop stack))
- (if (and stack (memq (car (car stack)) '(icr begin fun try)))
+ (if (and stack (memq (car (car stack)) '(icr begin fun try maybe)))
(erlang-pop stack))))
((looking-at "catch\\b.*of")
t)
@@ -2746,7 +2748,7 @@ Value is list (stack token-start token-type in-what)."
(progn
(while (and stack (eq (car (car stack)) '->))
(erlang-pop stack))
- (if (and stack (memq (car (car stack)) '(icr begin try)))
+ (if (and stack (memq (car (car stack)) '(icr begin try maybe)))
(erlang-pop stack))))
)
(cond ((looking-at "\\(if\\|case\\|receive\\)[^_a-zA-Z0-9]")
@@ -2768,7 +2770,7 @@ Value is list (stack token-start token-type in-what)."
((looking-at "\\(fun\\)[^_a-zA-Z0-9]")
;; Push a new layer if we are defining a `fun'
- ;; expression, not when we are refering an existing
+ ;; expression, not when we are referring an existing
;; function. 'fun's defines are only indented one level now.
(if (save-excursion
(goto-char (match-end 1))
@@ -2783,6 +2785,11 @@ Value is list (stack token-start token-type in-what)."
(erlang-push (list 'fun token (current-column)) stack)))
((looking-at "\\(begin\\)[^_a-zA-Z0-9]")
(erlang-push (list 'begin token (current-column)) stack))
+ ((looking-at "\\(maybe\\)[^_a-zA-Z0-9]")
+ (erlang-push (list 'begin token (current-column)) stack))
+ ((looking-at "\\(else\\)[^_a-zA-Z0-9]")
+ (erlang-push (list 'icr token (current-column)) stack))
+
;; Normal when case
;;((looking-at "when\\s ")
;;((looking-at "when\\s *\\($\\|%\\)")
@@ -2820,7 +2827,7 @@ Value is list (stack token-start token-type in-what)."
(forward-char 1))
(t
;; Maybe a character literal, quote the next char to avoid
- ;; situations as $" being seen as the begining of a string.
+ ;; situations as $" being seen as the beginning of a string.
;; Note the quoting something in the middle of a string is harmless.
(quote (following-char))
(forward-char 1))))
@@ -2875,7 +2882,7 @@ Value is list (stack token-start token-type in-what)."
(erlang-pop stack))
(cond ((eq (car (car stack)) '<<)
(erlang-pop stack))
- ((memq (car (car stack)) '(icr begin fun))
+ ((memq (car (car stack)) '(icr begin maybe fun))
(error "Missing `end'"))
(t
(error "Unbalanced parentheses")))
@@ -2947,6 +2954,8 @@ Value is list (stack token-start token-type in-what)."
))
((eq (car (car stack)) 'begin)
(error "Missing `end'"))
+ ((eq (car (car stack)) 'maybe)
+ (error "Missing `end'"))
(t
(error "Unbalanced parenthesis"))
)
@@ -3048,7 +3057,7 @@ Return nil if inside string, t if in a comment."
((and (eq (car stack-top) '||) (looking-at "\\(]\\|>>\\)[^_a-zA-Z0-9]"))
(nth 2 (car (cdr stack))))
;; Real indentation, where operators create extra indentation etc.
- ((memq (car stack-top) '(-> || try begin))
+ ((memq (car stack-top) '(-> || try begin maybe))
(if (looking-at "\\(of\\)[^_a-zA-Z0-9]")
(nth 2 stack-top)
(goto-char (nth 1 stack-top))
@@ -3060,6 +3069,8 @@ Return nil if inside string, t if in a comment."
(cond ((null (cdr stack))) ; Top level in function.
((eq (car stack-top) 'begin)
(setq skip 5))
+ ((eq (car stack-top) 'maybe)
+ (setq skip 5))
((eq (car stack-top) 'try)
(setq skip 5))
((eq (car stack-top) '->)
@@ -3073,7 +3084,7 @@ Return nil if inside string, t if in a comment."
(let ((base (erlang-indent-find-base stack indent-point off skip)))
;; Special cases
(goto-char indent-point)
- (cond ((looking-at "\\(;\\|end\\|after\\)\\($\\|[^_a-zA-Z0-9]\\)")
+ (cond ((looking-at "\\(;\\|end\\|after\\|else\\)\\($\\|[^_a-zA-Z0-9]\\)")
(if (eq (car stack-top) '->)
(erlang-pop stack))
(cond ((and stack (looking-at ";"))
@@ -3222,7 +3233,7 @@ Return nil if inside string, t if in a comment."
(progn
(if (memq (car stack-top) '(-> ||))
(erlang-pop stack))
- ;; Take parent identation + offset,
+ ;; Take parent indentation + offset,
;; else just erlang-indent-level if no parent
(if stack
(+ (caddr (car stack))
@@ -3324,8 +3335,8 @@ This assumes that the preceding expression is either simple
(defun erlang-at-keyword ()
"Are we looking at an Erlang keyword which will increase indentation?"
- (looking-at (concat "\\(when\\|if\\|fun\\|case\\|begin\\|"
- "of\\|receive\\|after\\|catch\\|try\\)\\b")))
+ (looking-at (concat "\\(when\\|if\\|fun\\|case\\|begin\\|maybe\\|"
+ "of\\|receive\\|after\\|catch\\|try\\|else\\)\\b")))
(defun erlang-at-operator ()
"Are we looking at an Erlang operator?"
@@ -6068,7 +6079,7 @@ unless the optional NO-DISPLAY is non-nil."
erlang-compile-erlang-function
module-name
(inferior-erlang-format-comma-opts opts))
- (let (;; Hopefully, noone else will ever use these...
+ (let (;; Hopefully, no one else will ever use these...
(tmpvar "Tmp7236")
(tmpvar2 "Tmp8742"))
(format
diff --git a/lib/tools/emacs/erlang_appwiz.el b/lib/tools/emacs/erlang_appwiz.el
index b71c180739..1928ea0279 100644
--- a/lib/tools/emacs/erlang_appwiz.el
+++ b/lib/tools/emacs/erlang_appwiz.el
@@ -23,7 +23,7 @@
;;(defvar erlang-skel-makefile-src
;; '((erlang-skel-include erlang-skel-nomodule-header)
;; "CC_ROOT := $(shell pwd | sed 's/erts.*$$//')" n
-;; "AUTOCONF := $(CC_ROOT)/erts/autoconf" n
+;; "AUTOCONF := $(CC_ROOT)/make/autoconf" n
;; "TARGET := $(shell $(AUTOCONF)/config.guess)"
;; "include $(CC_ROOT)/internal_tools/make/$(TARGET)/otp.mk" n
;; n
@@ -272,7 +272,7 @@ creating the root directory and for naming application files."
erlang-skel-normal-header erlang-skel-header)
("Large Header" "large-header"
erlang-skel-large-header erlang-skel-header)
- ("No Moudle Header" "nomodule-header"
+ ("No Module Header" "nomodule-header"
erlang-skel-nomodule-header erlang-skel-header)
()
("Small Server" "small-server"
@@ -302,7 +302,7 @@ The first element is the name which shows up in the menu. The second
is the `tempo' identfier (The string \"erlang-\" will be added in
front of it). The third is the skeleton descriptor, a variable
containing `tempo' attributes as described in the function
-`tempo-define-template'. The optinal fourth elements denotes a
+`tempo-define-template'. The optional fourth elements denotes a
function which should be called when the menu is selected.
Functions corresponding to every template will be created. The name
@@ -310,7 +310,7 @@ of the function will be `tempo-template-erlang-X' where `X' is the
tempo identifier as specified in the second argument of the elements
in this list.
-A list with zero elemets means that the a horisontal line should
+A list with zero elements means that the a horisontal line should
be placed in the menu.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -451,7 +451,7 @@ Example:
((\"Yellow\" function-yellow)
(\"Blue\" function-blue)))
nil
- (\"Region Funtion\" spook-function midnight-variable))
+ (\"Region Function\" spook-function midnight-variable))
Call the function `erlang-menu-init' after modifying this variable.")
diff --git a/lib/tools/examples/Makefile b/lib/tools/examples/Makefile
index 0fcc66d874..a5e0473f64 100644
--- a/lib/tools/examples/Makefile
+++ b/lib/tools/examples/Makefile
@@ -39,7 +39,7 @@ EXAMPLE_FILES = xref_examples.erl
# Targets
# ----------------------------------------------------
-debug opt:
+$(TYPES):
clean:
diff --git a/lib/tools/obj/.gitignore b/lib/tools/obj/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/tools/obj/.gitignore
+++ /dev/null
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index cc5bee9a8f..b05ce883ec 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2018. All Rights Reserved.
+# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -84,7 +84,7 @@ ERL_COMPILE_FLAGS += -Werror
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+$(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
clean:
rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 83ccde524f..1f7a518dfe 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -336,6 +336,8 @@ filter_options(Options) ->
{d, _Macro, _Value} -> true;
export_all -> true;
tuple_calls -> true;
+ {feature,_,enable} -> true; %FIXME: To be removed.
+ {feature,_,disable} -> true; %FIXME: To be removed.
_ -> false
end
end,
@@ -430,7 +432,7 @@ get_mods_and_beams([{Module,File}|ModFiles],Acc) ->
%% Duplicate, but same file so ignore
get_mods_and_beams(ModFiles,Acc);
{ok,Module,_OtherFile} ->
- %% Duplicate and differnet file - error
+ %% Duplicate and different file - error
get_mods_and_beams(ModFiles,[{error,{duplicate,Module}}|Acc]);
_ ->
get_mods_and_beams(ModFiles,[{ok,Module,File}|Acc])
@@ -1958,7 +1960,7 @@ munge({function,Anno,Function,Arity,Clauses},Vars,_MainFile,on) ->
{MungedClauses, Vars3} = munge_clauses(Clauses, Vars2),
{{function,Anno,Function,Arity,MungedClauses},Vars3,on};
munge(Form={attribute,_,file,{MainFile,_}},Vars,MainFile,_Switch) ->
- {Form,Vars,on}; % Switch on tranformation!
+ {Form,Vars,on}; % Switch on transformation!
munge(Form={attribute,_,file,{_InclFile,_}},Vars,_MainFile,_Switch) ->
{Form,Vars,off}; % Switch off transformation!
munge({attribute,_,compile,{parse_transform,_}},_Vars,_MainFile,_Switch) ->
@@ -2169,6 +2171,10 @@ munge_expr({match,Anno,ExprL,ExprR}, Vars) ->
{MungedExprL, Vars2} = munge_expr(ExprL, Vars),
{MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
{{match,Anno,MungedExprL,MungedExprR}, Vars3};
+munge_expr({maybe_match,Anno,ExprL,ExprR}, Vars) ->
+ {MungedExprL, Vars2} = munge_expr(ExprL, Vars),
+ {MungedExprR, Vars3} = munge_expr(ExprR, Vars2),
+ {{maybe_match,Anno,MungedExprL,MungedExprR}, Vars3};
munge_expr({tuple,Anno,Exprs}, Vars) ->
{MungedExprs, Vars2} = munge_exprs(Exprs, Vars, []),
{{tuple,Anno,MungedExprs}, Vars2};
@@ -2260,6 +2266,13 @@ munge_expr({'try',Anno,Body,Clauses,CatchClauses,After}, Vars) ->
{MungedAfter, Vars4} = munge_body(After, Vars3),
{{'try',Anno,MungedBody,MungedClauses,MungedCatchClauses,MungedAfter},
Vars4};
+munge_expr({'maybe',Anno,Exprs}, Vars) ->
+ {MungedExprs, Vars2} = munge_body(Exprs, Vars),
+ {{'maybe',Anno,MungedExprs}, Vars2};
+munge_expr({'maybe',MaybeAnno,Exprs,{'else',ElseAnno,Clauses}}, Vars) ->
+ {MungedExprs, Vars2} = munge_body(Exprs, Vars),
+ {MungedClauses, Vars3} = munge_clauses(Clauses, Vars2),
+ {{'maybe',MaybeAnno,MungedExprs,{'else',ElseAnno,MungedClauses}}, Vars3};
munge_expr({'fun',Anno,{clauses,Clauses}}, Vars) ->
{MungedClauses,Vars2}=munge_clauses(Clauses, Vars),
{{'fun',Anno,{clauses,MungedClauses}}, Vars2};
diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl
index 0d24120b83..bc2a0a3ac4 100644
--- a/lib/tools/src/fprof.erl
+++ b/lib/tools/src/fprof.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
%%%----------------------------------------------------------------------
%%% File : fprof.erl
%%% Author : Raimo Niskanen <raimo@erix.ericsson.se>
-%%% Purpose : File tracing profiling tool wich accumulated times.
+%%% Purpose : File tracing profiling tool which accumulated times.
%%% Created : 18 Jun 2001 by Raimo Niskanen <raimo@erix.ericsson.se>
%%%----------------------------------------------------------------------
diff --git a/lib/tools/src/tags.erl b/lib/tools/src/tags.erl
index df110185a2..2287196484 100644
--- a/lib/tools/src/tags.erl
+++ b/lib/tools/src/tags.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@
%% directories in `DirList'.
%%
%% subdir(Dir [, Options]) -- Descend recursively down `Dir' and create
-%% a TAGS file convering all files found.
+%% a TAGS file covering all files found.
%% subdirs(DirList [, Options])
%% -- Dito, for all directories in `DirList'.
%%
diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile
index 350b936978..984568e4c5 100644
--- a/lib/tools/test/Makefile
+++ b/lib/tools/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2020. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ MODULES = \
cover_SUITE \
eprof_SUITE \
emacs_SUITE \
- emem_SUITE \
fprof_SUITE \
cprof_SUITE \
instrument_SUITE \
@@ -55,6 +54,7 @@ RELSYSDIR = $(RELEASE_PATH)/tools_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
EBIN = .
@@ -67,7 +67,7 @@ make_emakefile:
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
> $(EMAKEFILE)
-tests debug opt: make_emakefile
+tests $(TYPES): make_emakefile
erl $(ERL_MAKE_FLAGS) -make
clean:
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 1393c9d1e1..9977fa8763 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,14 +25,15 @@
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,5}}].
+ {timetrap,{minutes,2}}].
all() ->
NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273,
otp_8340,otp_8188,compile_beam_opts,eep37,
analyse_no_beam, line_0, compile_beam_no_file,
compile_beam_missing_backend,
- otp_13277, otp_13289, guard_in_lc, gh_4796],
+ otp_13277, otp_13289, guard_in_lc, gh_4796,
+ eep49],
StartStop = [start, compile, analyse, misc, stop,
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
@@ -440,14 +441,14 @@ distribution(Config) when is_list(Config) ->
DataDir = proplists:get_value(data_dir, Config),
ok = file:set_cwd(DataDir),
- {ok,N1} = test_server:start_node(cover_SUITE_distribution1,slave,[]),
- {ok,N2} = test_server:start_node(cover_SUITE_distribution2,slave,[]),
- {ok,N3} = test_server:start_node(cover_SUITE_distribution3,slave,[]),
- {ok,N4} = test_server:start_node(cover_SUITE_distribution4,slave,[]),
+ {ok,P1,N1} = ?CT_PEER(),
+ {ok,P2,N2} = ?CT_PEER(),
+ {ok,P3,N3} = ?CT_PEER(),
+ {ok,P4,N4} = ?CT_PEER(),
%% Check that an already compiled module is loaded on new nodes
{ok,f} = cover:compile(f),
- {ok,[_,_,_,_]} = cover:start(nodes()),
+ {ok,[_,_,_,_]} = cover:start([N1,N2,N3,N4]),
cover_compiled = code:which(f),
cover_compiled = rpc:call(N1,code,which,[f]),
cover_compiled = rpc:call(N2,code,which,[f]),
@@ -474,7 +475,7 @@ distribution(Config) when is_list(Config) ->
%% this is lost when the node is killed
rpc:call(N3,f,f2,[]),
- rpc:call(N3,erlang,halt,[]),
+ peer:stop(P3),
%% this should be visible in analyse
rpc:call(N1,f,f1,[]),
@@ -514,7 +515,7 @@ distribution(Config) when is_list(Config) ->
%% Check that flush collects data so calls are not lost if node is killed
rpc:call(N4,f,f2,[]),
ok = cover:flush(N4),
- rpc:call(N4,erlang,halt,[]),
+ peer:stop(P4),
check_f_calls(1,3),
%% Check that stop() unloads on all nodes
@@ -535,8 +536,8 @@ distribution(Config) when is_list(Config) ->
%% Cleanup
Files = lsfiles(),
remove(files(Files, ".beam")),
- test_server:stop_node(N1),
- test_server:stop_node(N2).
+ peer:stop(P1),
+ peer:stop(P2).
%% Test that a lost node is reconnected
reconnect(Config) ->
@@ -547,19 +548,17 @@ reconnect(Config) ->
{ok,b} = compile:file(b),
{ok,f} = compile:file(f),
- {ok,N1} = test_server:start_node(cover_SUITE_reconnect,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok,P1,N1} = ?CT_PEER(#{connection => 0, args => ["-pa", DataDir]}),
{ok,a} = cover:compile(a),
{ok,f} = cover:compile(f),
- {ok,[N1]} = cover:start(nodes()),
+ {ok,[N1]} = cover:start([N1]),
%% Some calls to check later
rpc:call(N1,f,f1,[]),
cover:flush(N1),
rpc:call(N1,f,f1,[]),
- %% This will cause first casue the N1 node to initiate a
+ %% This will cause first cause the N1 node to initiate a
%% disconnect and then call f:f2() when nodes() =:= [] on N1.
rpc:cast(N1,f,call_f2_when_isolated,[]),
timer:sleep(500), % allow some to detect disconnect and for f:f2() call
@@ -590,7 +589,7 @@ reconnect(Config) ->
check_f_calls(2,1),
cover:stop(),
- test_server:stop_node(N1),
+ peer:stop(P1),
ok.
%% Test that a lost node is reconnected - also if it has been dead
@@ -600,13 +599,10 @@ die_and_reconnect(Config) ->
{ok,f} = compile:file(f),
- NodeName = cover_SUITE_die_and_reconnect,
- {ok,N1} = test_server:start_node(NodeName,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok, P1, N1} = ?CT_PEER(#{name => ?CT_PEER_NAME(), args => ["-pa", DataDir]}),
%% {ok,a} = cover:compile(a),
{ok,f} = cover:compile(f),
- {ok,[N1]} = cover:start(nodes()),
+ {ok,[N1]} = cover:start([N1]),
%% Some calls to check later
rpc:call(N1,f,f1,[]),
@@ -614,15 +610,13 @@ die_and_reconnect(Config) ->
rpc:call(N1,f,f1,[]),
%% Kill the node
- rpc:call(N1,erlang,halt,[]),
+ peer:stop(P1),
cover_which_nodes([]),
check_f_calls(1,0), % only the first call - before the flush
%% Restart the node and check that cover reconnects
- {ok,N1} = test_server:start_node(NodeName,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok,P2,N1} = ?CT_PEER(#{name => N1, args => ["-pa", DataDir]}),
timer:sleep(100),
[N1] = cover:which_nodes(), % we are reconnected
cover_compiled = rpc:call(N1,code,which,[f]),
@@ -634,7 +628,7 @@ die_and_reconnect(Config) ->
check_f_calls(2,0),
cover:stop(),
- test_server:stop_node(N1),
+ peer:stop(P2),
ok.
%% Test that a stopped node is not marked as lost, i.e. that it is not
@@ -645,27 +639,23 @@ dont_reconnect_after_stop(Config) ->
{ok,f} = compile:file(f),
- NodeName = cover_SUITE_dont_reconnect_after_stop,
- {ok,N1} = test_server:start_node(NodeName,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok, P1, N1} = ?CT_PEER(#{name => ?CT_PEER_NAME(), args => ["-pa", DataDir],
+ start_cover => false}),
{ok,f} = cover:compile(f),
- {ok,[N1]} = cover:start(nodes()),
+ {ok,[N1]} = cover:start([N1]),
%% A call to check later
rpc:call(N1,f,f1,[]),
%% Stop cover on the node, then terminate the node
cover:stop(N1),
- rpc:call(N1,erlang,halt,[]),
+ peer:stop(P1),
cover_which_nodes([]),
check_f_calls(1,0),
%% Restart the node and check that cover does not reconnect
- {ok,N1} = test_server:start_node(NodeName,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok, P2, N1} = ?CT_PEER(#{name => N1, args => ["-pa", DataDir], start_cover => false}),
timer:sleep(300),
cover_which_nodes([]),
Beam = rpc:call(N1,code,which,[f]),
@@ -679,7 +669,7 @@ dont_reconnect_after_stop(Config) ->
check_f_calls(1,0),
cover:stop(),
- test_server:stop_node(N1),
+ peer:stop(P2),
ok.
%% Test that a node which is stopped while it is marked as lost is not
@@ -690,19 +680,17 @@ stop_node_after_disconnect(Config) ->
{ok,f} = compile:file(f),
- NodeName = cover_SUITE_stop_node_after_disconnect,
- {ok,N1} = test_server:start_node(NodeName,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok, P1, N1} = ?CT_PEER(#{name => ?CT_PEER_NAME(), args => ["-pa", DataDir],
+ start_cover => false}),
{ok,f} = cover:compile(f),
- {ok,[N1]} = cover:start(nodes()),
+ {ok,[N1]} = cover:start([N1]),
%% A call to check later
rpc:call(N1,f,f1,[]),
%% Flush the node, then terminate the node to make it marked as lost
cover:flush(N1),
- rpc:call(N1,erlang,halt,[]),
+ peer:stop(P1),
check_f_calls(1,0),
@@ -710,9 +698,7 @@ stop_node_after_disconnect(Config) ->
cover:stop(N1),
%% Restart the node and check that cover does not reconnect
- {ok,N1} = test_server:start_node(NodeName,peer,
- [{args," -pa " ++ DataDir},
- {start_cover,false}]),
+ {ok, P2, N1} = ?CT_PEER(#{name => N1, args => ["-pa", DataDir], start_cover => false}),
timer:sleep(300),
cover_which_nodes([]),
Beam = rpc:call(N1,code,which,[f]),
@@ -726,7 +712,7 @@ stop_node_after_disconnect(Config) ->
check_f_calls(1,0),
cover:stop(),
- test_server:stop_node(N1),
+ peer:stop(P2),
ok.
distribution_performance(Config) ->
@@ -742,18 +728,14 @@ distribution_performance(Config) ->
% test_server:break(""),
- NodeName = cover_SUITE_distribution_performance,
- {ok,N1} = test_server:start_node(NodeName,peer,[{start_cover,false}]),
+ {ok, P1, N1} = ?CT_PEER(),
%% CFun = fun() ->
%% [{ok,_} = cover:compile_beam(Mod) || Mod <- Mods]
%% end,
CFun = fun() -> cover:compile_beam(Mods) end,
- {CT,_CA} = timer:tc(CFun),
- % erlang:display(_CA),
- erlang:display({compile,CT}),
+ {_CT, _CA} = timer:tc(CFun),
- {SNT,_} = timer:tc(fun() -> {ok,[N1]} = cover:start(nodes()) end),
- erlang:display({start_node,SNT}),
+ {ok,[N1]} = cover:start([N1]),
[1 = rpc:call(N1,Mod,f1,[1]) || Mod <- Mods],
@@ -769,16 +751,14 @@ distribution_performance(Config) ->
% Fun = fun() -> cover:reset() end,
- {AT,_A} = timer:tc(Fun),
- erlang:display({analyse,AT}),
+ {_AT, _A} = timer:tc(Fun),
% erlang:display(lists:sort([X || X={_MFA,N} <- lists:append([L || {ok,L}<-A]), N=/=0])),
%% fprof:apply(Fun, [],[{procs,[whereis(cover_server)]}]),
%% fprof:profile(),
%% fprof:analyse(dest,[]),
- {SNT2,_} = timer:tc(fun() -> test_server:stop_node(N1) end),
- erlang:display({stop_node,SNT2}),
+ peer:stop(P1),
code:del_path(Dir),
Files = filelib:wildcard(AllFiles),
@@ -861,7 +841,7 @@ export_import(Config) when is_list(Config) ->
ok = cover:stop(),
%% Check that same data exists after import and that info is written about
- %% data comming from imported file
+ %% data coming from imported file
ok = cover:import("f_exported"),
test_server:capture_start(),
check_f_calls(1,0),
@@ -946,11 +926,11 @@ export_import(Config) when is_list(Config) ->
otp_5031(Config) when is_list(Config) ->
ct:timetrap({seconds, 10}),
- {ok,N1} = test_server:start_node(cover_SUITE_otp_5031,slave,[]),
+ {ok,Peer,N1} = ?CT_PEER(),
{ok,[N1]} = cover:start(N1),
{error,not_main_node} = rpc:call(N1,cover,modules,[]),
cover:stop(),
- test_server:stop_node(N1),
+ peer:stop(Peer),
ok.
%% Test the \'Exclude Included Functions\' functionality
@@ -1005,7 +985,7 @@ otp_6115(Config) when is_list(Config) ->
{ok, f1} = cover:compile(f1),
%% This test used to ensure that a process containing a
- %% fun refering to cover compiled code was killed.
+ %% fun referring to cover compiled code was killed.
%% check_process_code may however ignore funs as of ERTS
%% version 8.1. The test has therefore been rewritten to
%% check that a process with a direct reference (in this
@@ -1159,13 +1139,13 @@ otp_8270(Config) when is_list(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- As = [{args," -pa " ++ PrivDir}],
- {ok,N1} = test_server:start_node(cover_n1,slave,As),
- {ok,N2} = test_server:start_node(cover_n2,slave,As),
- {ok,N3} = test_server:start_node(cover_n3,slave,As),
+ As = ["-pa", PrivDir],
+ {ok,P1,N1} = ?CT_PEER(As),
+ {ok,P2,N2} = ?CT_PEER(As),
+ {ok,P3,N3} = ?CT_PEER(As),
timer:sleep(500),
- {ok,[_,_,_]} = cover:start(nodes()),
+ {ok,[_,_,_]} = cover:start([N1,N2,N3]),
Test = <<"-module(m).\n"
"-compile(export_all).\n"
@@ -1203,9 +1183,9 @@ otp_8270(Config) when is_list(Config) ->
{N3,true} = {N3,is_list(N3_info)},
exit(Pid1,kill),
- test_server:stop_node(N1),
- test_server:stop_node(N2),
- test_server:stop_node(N3),
+ peer:stop(P1),
+ peer:stop(P2),
+ peer:stop(P3),
ok.
%% OTP-8273. Bug.
@@ -1607,7 +1587,7 @@ cover_clauses(Config) when is_list(Config) ->
-export([clauses/0]).
clauses() -> ok.
">>,
- File = cc_mod(cover_clauses, Test, Config),
+ _File = cc_mod(cover_clauses, Test, Config),
ok.
%% Take compiler options from beam in cover:compile_beam
@@ -1835,9 +1815,9 @@ local_only(Config) ->
%% Make sure that it is not possible to run cover on
%% slave nodes.
- {ok,Name} = test_server:start_node(?FUNCTION_NAME, slave, []),
+ {ok,Peer,Name} = ?CT_PEER(),
{error,local_only} = cover:start([Name]),
- test_server:stop_node(Name),
+ peer:stop(Peer),
ok.
%% ERL-943; We should not crash on startup when multiple servers race to
@@ -1895,6 +1875,63 @@ gh_4796(Config) ->
ok = file:delete(File),
ok = gh_4796:test().
+%% Test the maybe ... else ... end construct.
+eep49(Config) ->
+ ok = file:set_cwd(proplists:get_value(priv_dir, Config)),
+
+ File = "t.erl",
+ Test = <<"-module(t).
+ -feature(maybe_expr,enable).
+ -export([t/0]).
+
+ t() ->
+ t1(), %6
+
+ {a,b} = t2({ok,a}, {ok,b}), %8
+ error = t2({ok,a}, error), %9
+ whatever = t2(whatever, thing), %10
+
+ {a,b} = t3({ok,a}, {ok,b}), %12
+ error = t3({ok,a}, {error,wrong}), %13
+ {'EXIT',{{else_clause,whatever},_}} = catch t3(whatever, thing), %14
+
+ ok. %16
+
+ t1() ->
+ maybe %19
+ ok %20
+ end.
+
+ t2(X, Y) ->
+ maybe %24
+ {ok,A} ?= X, %25
+ {ok,B} ?= Y, %26
+ {A,B} %27
+ end.
+
+ t3(X, Y) ->
+ maybe %31
+ {ok,A} ?= X, %32
+ {ok,B} ?= Y, %33
+ {A,B} %34
+ else
+ {error,_} ->
+ error %37
+ end.
+ ">>,
+ ok = file:write_file(File, Test),
+ {ok, t} = cover:compile(File),
+ ok = t:t(),
+ {ok,[{{t,6},1}, {{t,8},1}, {{t,9},1}, {{t,10},1}, {{t,12},1},
+ {{t,13},1}, {{t,14},1}, {{t,16},1},
+ {{t,19},1}, {{t,20},1},
+ {{t,24},3}, {{t,25},3}, {{t,26},2}, {{t,27},1},
+ {{t,31},3}, {{t,32},3}, {{t,33},2}, {{t,34},1}, {{t,37},1}
+ ]} = cover:analyse(t, calls, line),
+ ok = file:delete(File),
+ ok.
+
+
%%--Auxiliary------------------------------------------------------------
analyse_expr(Expr, Config) ->
diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl
index 8eb7476f57..d27371414a 100644
--- a/lib/tools/test/cprof_SUITE.erl
+++ b/lib/tools/test/cprof_SUITE.erl
@@ -203,9 +203,8 @@ on_load_test(Config) ->
N2 = cprof:pause(),
{Module,0,[]} = cprof:analyse(Module),
M4__4 = M*4 - 4,
- M10_7 = M*10 - 7,
- {?MODULE,M10_7,[{{?MODULE,succ,1},M4__4},
- {{?MODULE,'-fun.succ/1-',1},M4__4},
+ M6_3 = M*6 - 3,
+ {?MODULE,M6_3,[{{?MODULE,succ,1},M4__4},
{{?MODULE,seq_r,4},M},
{{?MODULE,seq,3},M},
{{?MODULE,seq_r,3},1}]}
@@ -234,11 +233,10 @@ modules_test(Config) ->
N = cprof:pause(),
Lr = lists:reverse(L),
M4_4 = M*4 - 4,
- M10_7 = M*10 - 7,
+ M6_3 = M*6 - 3,
M2__1 = M*2 + 1,
{Tot,ModList} = cprof:analyse(),
- {value,{?MODULE,M10_7,[{{?MODULE,succ,1},M4_4},
- {{?MODULE,'-fun.succ/1-',1},M4_4},
+ {value,{?MODULE,M6_3,[{{?MODULE,succ,1},M4_4},
{{?MODULE,seq_r,4},M},
{{?MODULE,seq,3},M},
{{?MODULE,seq_r,3},1}]}} =
diff --git a/lib/tools/test/emacs_SUITE_data/comments b/lib/tools/test/emacs_SUITE_data/comments
index ff974ca295..b16d398643 100644
--- a/lib/tools/test/emacs_SUITE_data/comments
+++ b/lib/tools/test/emacs_SUITE_data/comments
@@ -3,11 +3,11 @@
%%% 3 comment chars: always left indented
%%% 2 comment chars: Context indented
-%%% 1 comment char: Rigth indented
+%%% 1 comment char: Right indented
%%% left
%% context dependent
- % rigth
+ % right
func() ->
%%% left
@@ -15,7 +15,7 @@ func() ->
% right indented
case get(foo) of
undefined ->
- %% Testing indention
+ %% Testing indentation
ok;
%% Catch all
Other ->
diff --git a/lib/tools/test/emacs_SUITE_data/funcs b/lib/tools/test/emacs_SUITE_data/funcs
index 877f982005..820905687d 100644
--- a/lib/tools/test/emacs_SUITE_data/funcs
+++ b/lib/tools/test/emacs_SUITE_data/funcs
@@ -128,7 +128,7 @@ match6(M6A,
funs(1)
when
X ->
- %% Changed fun to one indention level
+ %% Changed fun to one indentation level
%% 'when' and several clause forces a depth of '4'
Var = spawn(fun(X, _)
when X == 2;
diff --git a/lib/tools/test/emacs_SUITE_data/highlight b/lib/tools/test/emacs_SUITE_data/highlight
index 0719f6516a..58d6bd9c0d 100644
--- a/lib/tools/test/emacs_SUITE_data/highlight
+++ b/lib/tools/test/emacs_SUITE_data/highlight
@@ -69,10 +69,10 @@ highlighting(X) % Function definitions should be highlighted
not_a_guard:is_list([]),
%% Other Types
- atom, % not (currently) hightlighted
+ atom, % not (currently) highlighted
234234,
234.43,
- [list, are, not, higlighted],
+ [list, are, not, highlighted],
{nor, is, tuple},
ok.
diff --git a/lib/tools/test/emacs_SUITE_data/icr b/lib/tools/test/emacs_SUITE_data/icr
index 8445c1a74d..ecfe23c5a1 100644
--- a/lib/tools/test/emacs_SUITE_data/icr
+++ b/lib/tools/test/emacs_SUITE_data/icr
@@ -155,3 +155,42 @@ indent_receive() ->
5*43
end,
ok.
+
+indent_maybe(1) ->
+ begin
+ maybe_should_be_indented_as_begin,
+ end,
+ maybe
+ 1 = foo(X),
+ 2 ?= asd(X),
+ line_with_break =
+ foo(X+1),
+ line_with_break ?=
+ foo(X+1)
+ end,
+ ok;
+indent_maybe(1) ->
+ maybe
+ 2 ?= foo(X),
+ 3 ?= bar(Y)
+ else
+ %% else indented as a standard icr (if-case-receive)
+ {error, Z} when Z == 1 ->
+ error1;
+ {error, Z}
+ when Z == 2 ->
+ error2
+ end;
+indent_maybe(3) ->
+ maybe
+ 2 ?= foo(x),
+ maybe
+ nested ?= foo(y)
+ else
+ error ->
+ ok
+ end
+ else
+ error -> ok
+ end.
+
diff --git a/lib/tools/test/emem_SUITE.erl b/lib/tools/test/emem_SUITE.erl
deleted file mode 100644
index 968b360883..0000000000
--- a/lib/tools/test/emem_SUITE.erl
+++ /dev/null
@@ -1,654 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2021. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(emem_SUITE).
-
--export([all/0, suite/0,
- init_per_testcase/2, end_per_testcase/2,
- init_per_suite/1, end_per_suite/1,
- receive_and_save_trace/2, send_trace/2]).
-
--export([live_node/1,
- 'sparc_sunos5.8_32b_emt2.0'/1,
- 'pc_win2000_32b_emt2.0'/1,
- 'pc.smp_linux2.2.19pre17_32b_emt2.0'/1,
- 'powerpc_darwin7.7.0_32b_emt2.0'/1,
- 'alpha_osf1v5.1_64b_emt2.0'/1,
- 'sparc_sunos5.8_64b_emt2.0'/1,
- 'sparc_sunos5.8_32b_emt1.0'/1,
- 'pc_win2000_32b_emt1.0'/1,
- 'powerpc_darwin7.7.0_32b_emt1.0'/1,
- 'alpha_osf1v5.1_64b_emt1.0'/1,
- 'sparc_sunos5.8_64b_emt1.0'/1]).
-
--include_lib("kernel/include/file.hrl").
--include_lib("common_test/include/ct.hrl").
-
--define(EMEM_64_32_COMMENT,
- "64 bit trace; this build of emem can only handle 32 bit traces").
-
--record(emem_res, {nodename,
- hostname,
- pid,
- start_time,
- trace_version,
- max_word_size,
- word_size,
- last_values,
- maximum,
- exit_code}).
-
-%%
-%% Exported suite functions
-%%
-
-suite() ->
- [{ct_hooks,[ts_install_cth]},
- {timetrap,{minutes,5}}].
-
-all() ->
- case test_server:is_debug() of
- true -> {skip, "Not run when debug compiled"};
- false -> test_cases()
- end.
-
-
-test_cases() ->
- [live_node, 'sparc_sunos5.8_32b_emt2.0',
- 'pc_win2000_32b_emt2.0',
- 'pc.smp_linux2.2.19pre17_32b_emt2.0',
- 'powerpc_darwin7.7.0_32b_emt2.0',
- 'alpha_osf1v5.1_64b_emt2.0',
- 'sparc_sunos5.8_64b_emt2.0',
- 'sparc_sunos5.8_32b_emt1.0', 'pc_win2000_32b_emt1.0',
- 'powerpc_darwin7.7.0_32b_emt1.0',
- 'alpha_osf1v5.1_64b_emt1.0',
- 'sparc_sunos5.8_64b_emt1.0'].
-
-init_per_testcase(Case, Config) when is_list(Config) ->
- case maybe_skip(Config) of
- {skip, _}=Skip ->
- Skip;
- ok ->
- %% Until emem is completely stable we run these tests in a working
- %% directory with an ignore_core_files file which will make the
- %% search for core files ignore cores generated by this suite.
- ignore_cores:setup(?MODULE, Case, [{testcase, Case}|Config])
- end.
-
-end_per_testcase(_Case, Config) when is_list(Config) ->
- ignore_cores:restore(Config),
- ok.
-
-maybe_skip(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- case filelib:is_dir(DataDir) of
- false ->
- {skip, "No data directory"};
- true ->
- case proplists:get_value(emem, Config) of
- undefined ->
- {skip, "emem not found"};
- _ ->
- ok
- end
- end.
-
-init_per_suite(Config) when is_list(Config) ->
- BinDir = filename:join([code:lib_dir(tools), "bin"]),
- Target = erlang:system_info(system_architecture),
- Res = (catch begin
- case check_dir(filename:join([BinDir, Target])) of
- not_found -> ok;
- TDir ->
- check_emem(TDir, debug),
- check_emem(TDir, opt)
- end,
- check_emem(BinDir, opt),
- ""
- end),
- Res ++ ignore_cores:init(Config).
-
-end_per_suite(Config) when is_list(Config) ->
- Config1 = lists:keydelete(emem, 1, Config),
- Config2 = lists:keydelete(emem_comment, 1, Config1),
- ignore_cores:fini(Config2).
-
-%%
-%%
-%% Test cases
-%%
-%%
-
-live_node(Config) when is_list(Config) ->
- {ok, EmuFlag, Port} = start_emem(Config),
- Nodename = mk_nodename(Config),
- {ok, Node} = start_node(Nodename, EmuFlag),
- NP = spawn(Node,
- fun () ->
- receive go -> ok end,
- I = spawn(fun () -> ignorer end),
- GC = fun () ->
- GCP = fun (P) ->
- garbage_collect(P)
- end,
- lists:foreach(GCP, processes())
- end,
- Seq = fun () -> I ! lists:seq(1, 1000000) end,
- spawn_link(Seq),
- B1 = <<0:10000000>>,
- spawn_link(Seq),
- B2 = <<0:10000000>>,
- spawn_link(Seq),
- B3 = <<0:10000000>>,
- I ! {B1, B2, B3},
- GC(),
- GC(),
- GC()
- end),
- MRef = erlang:monitor(process, NP),
- NP ! go,
- receive
- {'DOWN', MRef, process, NP, Reason} ->
- spawn(Node, fun () -> halt(17) end),
- normal = Reason
- end,
- Res = get_emem_result(Port),
- {ok, Hostname} = inet:gethostname(),
- ShortHostname = short_hostname(Hostname),
- {true, _} = has_prefix(Nodename, Res#emem_res.nodename),
- ShortHostname = short_hostname(Res#emem_res.hostname),
- Bits = case erlang:system_info(wordsize) of
- 4 -> "32 bits";
- 8 -> "64 bits"
- end,
- Bits = Res#emem_res.word_size,
- "17" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-'sparc_sunos5.8_32b_emt2.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "test_server" = Res#emem_res.nodename,
- "gorbag" = Res#emem_res.hostname,
- "17074" = Res#emem_res.pid,
- "2005-01-14 17:28:37.881980" = Res#emem_res.start_time,
- "2.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["15", "2665739", "8992", "548986", "16131", "539994",
- "4334192", "1", "99", "15", "98",
- "0", "0", "49", "0", "49"] = Res#emem_res.last_values,
- ["5972061", "9662", "7987824", "5",
- "2375680", "3"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-'pc_win2000_32b_emt2.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "test_server" = Res#emem_res.nodename,
- "E-788FCF5191B54" = Res#emem_res.hostname,
- "504" = Res#emem_res.pid,
- "2005-01-24 17:27:28.224000" = Res#emem_res.start_time,
- "2.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["11", "2932575", "8615", "641087", "68924", "632472"]
- = Res#emem_res.last_values,
- ["5434206", "9285"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-'pc.smp_linux2.2.19pre17_32b_emt2.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "test_server" = Res#emem_res.nodename,
- "four-roses" = Res#emem_res.hostname,
- "20689" = Res#emem_res.pid,
- "2005-01-20 13:11:26.143077" = Res#emem_res.start_time,
- "2.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["49", "2901817", "9011", "521610", "10875", "512599",
- "5392096", "2", "120", "10", "118",
- "0", "0", "59", "0", "59"] = Res#emem_res.last_values,
- ["6182918", "9681",
- "9062112", "6",
- "2322432", "3"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-
-'powerpc_darwin7.7.0_32b_emt2.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "test_server" = Res#emem_res.nodename,
- "grima" = Res#emem_res.hostname,
- "13021" = Res#emem_res.pid,
- "2005-01-20 15:08:17.568668" = Res#emem_res.start_time,
- "2.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["9", "2784323", "8641", "531105", "15893", "522464"]
- = Res#emem_res.last_values,
- ["6150376", "9311"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-'alpha_osf1v5.1_64b_emt2.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "test_server" = Res#emem_res.nodename,
- "thorin" = Res#emem_res.hostname,
- "224630" = Res#emem_res.pid,
- "2005-01-20 22:38:01.299632" = Res#emem_res.start_time,
- "2.0" = Res#emem_res.trace_version,
- "64 bits" = Res#emem_res.word_size,
- case Res#emem_res.max_word_size of
- "32 bits" ->
- emem_comment(Config, ?EMEM_64_32_COMMENT);
- "64 bits" ->
- ["22",
- "6591992", "8625", "516785", "14805", "508160",
- "11429184", "5", "127", "254", "122",
- "0", "0", "61", "0", "61"] = Res#emem_res.last_values,
- ["7041775", "9295",
- "11593024", "7",
- "2097152", "3"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config)
- end.
-
-'sparc_sunos5.8_64b_emt2.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "test_server" = Res#emem_res.nodename,
- "gorbag" = Res#emem_res.hostname,
- "10907" = Res#emem_res.pid,
- "2005-01-20 13:48:34.677068" = Res#emem_res.start_time,
- "2.0" = Res#emem_res.trace_version,
- "64 bits" = Res#emem_res.word_size,
- case Res#emem_res.max_word_size of
- "32 bits" ->
- emem_comment(Config, ?EMEM_64_32_COMMENT);
- "64 bits" ->
- ["16",
- "5032887", "8657", "530635", "14316", "521978",
- "8627140", "5", "139", "19", "134",
- "0", "0", "67", "0", "67"] = Res#emem_res.last_values,
- ["11695070", "9324",
- "16360388", "10",
- "4136960", "3"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config)
- end.
-
-'sparc_sunos5.8_32b_emt1.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "" = Res#emem_res.nodename,
- "" = Res#emem_res.hostname,
- "" = Res#emem_res.pid,
- "" = Res#emem_res.start_time,
- "1.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["11", "2558261", "8643", "560610", "15325", "551967"]
- = Res#emem_res.last_values,
- ["2791121", "9317"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-'pc_win2000_32b_emt1.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "" = Res#emem_res.nodename,
- "" = Res#emem_res.hostname,
- "" = Res#emem_res.pid,
- "" = Res#emem_res.start_time,
- "1.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["6", "2965248", "8614", "640897", "68903", "632283"]
- = Res#emem_res.last_values,
- ["3147090", "9283"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-
-'powerpc_darwin7.7.0_32b_emt1.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "" = Res#emem_res.nodename,
- "" = Res#emem_res.hostname,
- "" = Res#emem_res.pid,
- "" = Res#emem_res.start_time,
- "1.0" = Res#emem_res.trace_version,
- "32 bits" = Res#emem_res.word_size,
- ["8", "2852991", "8608", "529662", "15875", "521054"]
- = Res#emem_res.last_values,
- ["3173335", "9278"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config).
-
-'alpha_osf1v5.1_64b_emt1.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "" = Res#emem_res.nodename,
- "" = Res#emem_res.hostname,
- "" = Res#emem_res.pid,
- "" = Res#emem_res.start_time,
- "1.0" = Res#emem_res.trace_version,
- "64 bits" = Res#emem_res.word_size,
- case Res#emem_res.max_word_size of
- "32 bits" ->
- emem_comment(Config, ?EMEM_64_32_COMMENT);
- "64 bits" ->
- ["22",
- "6820094", "8612", "515518", "14812", "506906"]
- = Res#emem_res.last_values,
- ["7292413", "9282"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config)
- end.
-
-'sparc_sunos5.8_64b_emt1.0'(Config) when is_list(Config) ->
- Res = run_emem_on_casefile(Config),
- "" = Res#emem_res.nodename,
- "" = Res#emem_res.hostname,
- "" = Res#emem_res.pid,
- "" = Res#emem_res.start_time,
- "1.0" = Res#emem_res.trace_version,
- "64 bits" = Res#emem_res.word_size,
- case Res#emem_res.max_word_size of
- "32 bits" ->
- emem_comment(Config, ?EMEM_64_32_COMMENT);
- "64 bits" ->
- ["15",
- "4965746", "8234", "543940", "14443", "535706"]
- = Res#emem_res.last_values,
- ["11697645", "8908"] = Res#emem_res.maximum,
- "0" = Res#emem_res.exit_code,
- emem_comment(Config)
- end.
-
-%%
-%%
-%% Auxiliary functions
-%%
-%%
-
-receive_and_save_trace(PortNumber, FileName) when is_integer(PortNumber),
- is_list(FileName) ->
- {ok, F} = file:open(FileName, [write, compressed]),
- {ok, LS} = gen_tcp:listen(PortNumber, [inet, {reuseaddr,true}, binary]),
- {ok, S} = gen_tcp:accept(LS),
- gen_tcp:close(LS),
- receive_loop(S,F).
-
-receive_loop(Socket, File) ->
- receive
- {tcp, Socket, Data} ->
- ok = file:write(File, Data),
- receive_loop(Socket, File);
- {tcp_closed, Socket} ->
- file:close(File),
- ok;
- {tcp_error, Socket, Reason} ->
- file:close(File),
- {error, Reason}
- end.
-
-send_trace({Host, PortNumber}, FileName) when is_list(Host),
- is_integer(PortNumber),
- is_list(FileName) ->
- {ok, F} = file:open(FileName, [read, compressed]),
- {ok, S} = gen_tcp:connect(Host, PortNumber, [inet,{packet, 0}]),
- send_loop(S, F);
-send_trace(EmuFlag, FileName) when is_list(EmuFlag),
- is_list(FileName) ->
- ["+Mit", IpAddrStr, PortNoStr] = string:tokens(EmuFlag, " :"),
- send_trace({IpAddrStr, list_to_integer(PortNoStr)}, FileName).
-
-send_loop(Socket, File) ->
- case file:read(File, 128) of
- {ok, Data} ->
- case gen_tcp:send(Socket, Data) of
- ok -> send_loop(Socket, File);
- Error ->
- gen_tcp:close(Socket),
- file:close(File),
- Error
- end;
- eof ->
- gen_tcp:close(Socket),
- file:close(File),
- ok;
- Error ->
- gen_tcp:close(Socket),
- file:close(File),
- Error
- end.
-
-check_emem(Dir, Type) when is_atom(Type) ->
- ExeSuffix = case os:type() of
- {win32, _} -> ".exe";
- _ -> ""
- end,
- TypeSuffix = case Type of
- opt -> "";
- _ -> "." ++ atom_to_list(Type)
- end,
- Emem = "emem" ++ TypeSuffix ++ ExeSuffix,
- case check_file(filename:join([Dir, Emem])) of
- not_found -> ok;
- File ->
- Comment = case Type of
- opt -> "";
- _ -> "[emem " ++ atom_to_list(Type) ++ " compiled]"
- end,
- throw([{emem, File}, {emem_comment, Comment}])
- end.
-
-check_dir(DirName) ->
- case file:read_file_info(DirName) of
- {ok, #file_info {type = directory, access = A}} when A == read;
- A == read_write ->
- DirName;
- _ ->
- not_found
- end.
-
-check_file(FileName) ->
- case file:read_file_info(FileName) of
- {ok, #file_info {type = regular, access = A}} when A == read;
- A == read_write ->
- FileName;
- _ ->
- not_found
- end.
-
-emem_comment(Config) when is_list(Config) ->
- emem_comment(Config, "").
-
-emem_comment(Config, ExtraComment)
- when is_list(Config), is_list(ExtraComment) ->
- case {proplists:get_value(emem_comment, Config), ExtraComment} of
- {"", ""} -> ok;
- {"", XC} -> {comment, XC};
- {EmemC, ""} -> {comment, EmemC};
- {EmemC, XC} -> {comment, EmemC ++ " " ++ XC}
- end.
-
-run_emem_on_casefile(Config) ->
- CaseName = atom_to_list(proplists:get_value(testcase, Config)),
- File = filename:join([proplists:get_value(data_dir, Config), CaseName ++ ".gz"]),
- case check_file(File) of
- not_found ->
- ct:fail({error, {filenotfound, File}});
- _ ->
- ok
- end,
- {ok, EmuFlag, Port} = start_emem(Config),
- Parent = self(),
- Ref = make_ref(),
- spawn_link(fun () ->
- SRes = send_trace(EmuFlag, File),
- Parent ! {Ref, SRes}
- end),
- Res = get_emem_result(Port),
- receive
- {Ref, ok} ->
- ok;
- {Ref, SendError} ->
- io:format("Send result: ~p~n", [SendError])
- end,
- Res.
-
-get_emem_result(Port) ->
- {Res, LV} = get_emem_result(Port, {#emem_res{}, []}),
- Res#emem_res{last_values = string:tokens(LV, " ")}.
-
-get_emem_result(Port, {_EmemRes, _LastValues} = Res) ->
- case get_emem_line(Port) of
- eof ->
- Res;
- Line ->
- get_emem_result(Port, parse_emem_line(Line, Res))
- end.
-
-parse_emem_main_header_footer_line(Line, {ER, LV} = Res) ->
-
- %% Header
- case has_prefix("> Nodename:", Line) of
- {true, NN} ->
- throw({ER#emem_res{nodename = strip(NN)}, LV});
- false -> ok
- end,
- case has_prefix("> Hostname:", Line) of
- {true, HN} ->
- throw({ER#emem_res{hostname = strip(HN)}, LV});
- false -> ok
- end,
- case has_prefix("> Pid:", Line) of
- {true, P} ->
- throw({ER#emem_res{pid = strip(P)}, LV});
- false -> ok
- end,
- case has_prefix("> Start time (UTC):", Line) of
- {true, ST} ->
- throw({ER#emem_res{start_time = strip(ST)}, LV});
- false -> ok
- end,
- case has_prefix("> Actual trace version:", Line) of
- {true, TV} ->
- throw({ER#emem_res{trace_version = strip(TV)}, LV});
- false -> ok
- end,
- case has_prefix("> Maximum trace word size:", Line) of
- {true, MWS} ->
- throw({ER#emem_res{max_word_size = strip(MWS)}, LV});
- false -> ok
- end,
- case has_prefix("> Actual trace word size:", Line) of
- {true, WS} ->
- throw({ER#emem_res{word_size = strip(WS)}, LV});
- false -> ok
- end,
-
- %% Footer
- case has_prefix("> Maximum:", Line) of
- {true, M} ->
- throw({ER#emem_res{maximum = string:tokens(M," ")}, LV});
- false -> ok
- end,
- case has_prefix("> Emulator exited with code:", Line) of
- {true, EC} ->
- throw({ER#emem_res{exit_code = strip(EC)}, LV});
- false -> ok
- end,
- Res.
-
-parse_emem_header_line(_Line, {_ER, _LV} = Res) ->
- Res.
-
-parse_emem_value_line(Line, {EmemRes, _OldLastValues}) ->
- {EmemRes, Line}.
-
-parse_emem_line("", Res) ->
- Res;
-parse_emem_line(Line, Res) ->
- [Prefix | _] = Line,
- case Prefix of
- $> -> catch parse_emem_main_header_footer_line(Line, Res);
- $| -> catch parse_emem_header_line(Line, Res);
- _ -> catch parse_emem_value_line(Line, Res)
- end.
-
-start_emem(Config) when is_list(Config) ->
- Emem = proplists:get_value(emem, Config),
- Cd = case ignore_cores:dir(Config) of
- false -> [];
- Dir -> [{cd, Dir}]
- end,
- case open_port({spawn, Emem ++ " -t -n -o -i 1"},
- Cd ++ [{line, 1024}, eof]) of
- Port when is_port(Port) -> {ok, read_emu_flag(Port), Port};
- Error -> ct:fail(Error)
- end.
-
-read_emu_flag(Port) ->
- Line = case get_emem_line(Port) of
- eof -> ct:fail(unexpected_end_of_file);
- L -> L
- end,
- case has_prefix("> Emulator command line argument:", Line) of
- {true, EmuFlag} -> EmuFlag;
- false -> read_emu_flag(Port)
- end.
-
-get_emem_line(Port, Acc) ->
- receive
- {Port, {data, {eol, Data}}} ->
- Res = case Acc of
- [] -> Data;
- _ -> lists:flatten([Acc|Data])
- end,
- io:format("~s", [Res]),
- Res;
- {Port, {data, {noeol, Data}}} ->
- get_emem_line(Port, [Acc|Data]);
- {Port, eof} ->
- port_close(Port),
- eof
- end.
-
-get_emem_line(Port) ->
- get_emem_line(Port, []).
-
-short_hostname([]) ->
- [];
-short_hostname([$.|_]) ->
- [];
-short_hostname([C|Cs]) ->
- [C | short_hostname(Cs)].
-
-has_prefix([], List) when is_list(List) ->
- {true, List};
-has_prefix([P|Xs], [P|Ys]) ->
- has_prefix(Xs, Ys);
-has_prefix(_, _) ->
- false.
-
-strip(Str) -> string:strip(Str).
-
-mk_nodename(Config) ->
- Us = erlang:monotonic_time(),
- atom_to_list(?MODULE)
- ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config))
- ++ integer_to_list(Us).
-
-start_node(Name, Args) ->
- Pa = filename:dirname(code:which(?MODULE)),
- test_server:start_node(Name, peer, [{args, Args ++ " -pa " ++ Pa}]).
diff --git a/lib/tools/test/eprof_SUITE_data/eprof_suite_test.erl b/lib/tools/test/eprof_SUITE_data/eprof_suite_test.erl
index 4e0c4d3118..89eb81f7cf 100644
--- a/lib/tools/test/eprof_SUITE_data/eprof_suite_test.erl
+++ b/lib/tools/test/eprof_SUITE_data/eprof_suite_test.erl
@@ -22,10 +22,10 @@
%%% This module implements a priority queue as defined in
%%% "Priority Queues and the STL" by Mark Nelson in Dr.Dobb's Journal, Jan 1996
%%% see http://web2.airmail.net/markn/articles/pq_stl/priority.htm for more
-%%% information. (A heap implementation is planned aswell)
+%%% information. (A heap implementation is planned as well)
%%%----------------------------------------------------------------------
%%% The items of the queue is kept priority sorted, and because of that,
-%%% a push() operation costs more than a pop() operation (wich only
+%%% a push() operation costs more than a pop() operation (which only
%%% needs to return the top item of the queue(read: list)).
%%%----------------------------------------------------------------------
%%% The priority queue can be deceptively nice to use when creating for
diff --git a/lib/tools/test/instrument_SUITE.erl b/lib/tools/test/instrument_SUITE.erl
index 755739c94e..616bc5a895 100644
--- a/lib/tools/test/instrument_SUITE.erl
+++ b/lib/tools/test/instrument_SUITE.erl
@@ -73,17 +73,17 @@ allocations_test(Args, Plain, PerAlloc) ->
end).
allocations_enabled(Config) when is_list(Config) ->
- allocations_test("+Meamax +Muatags true",
+ allocations_test(["+Meamax", "+Muatags", "true"],
fun verify_allocations_enabled/1,
fun verify_allocations_enabled/2).
allocations_disabled(Config) when is_list(Config) ->
- allocations_test("+Meamax +Muatags false",
+ allocations_test(["+Meamax", "+Muatags", "false"],
fun verify_allocations_disabled/1,
fun verify_allocations_disabled/2).
allocations_ramv(Config) when is_list(Config) ->
- allocations_test("+Meamax +Muatags true +Muramv true",
+ allocations_test(["+Meamax", "+Muatags","true", "+Muramv","true"],
fun verify_allocations_enabled/1,
fun verify_allocations_enabled/2).
@@ -165,12 +165,12 @@ carriers_test(Args, Plain, PerAlloc) ->
end).
carriers_enabled(Config) when is_list(Config) ->
- carriers_test("+Meamax",
+ carriers_test(["+Meamax"],
fun verify_carriers_enabled/1,
fun verify_carriers_enabled/2).
carriers_disabled(Config) when is_list(Config) ->
- carriers_test("+Meamin",
+ carriers_test(["+Meamin"],
fun verify_carriers_disabled/1,
fun verify_carriers_disabled/2).
@@ -300,8 +300,8 @@ run_test(Args0, Test) ->
%%
%% We also set the abandon carrier threshold to 70% to provoke more
%% activity in the carrier pool.
- Args = Args0 ++ " +MBsbct 1 +Muacul 70",
- Node = start_slave(Args),
+ Args = Args0 ++ ["+MBsbct", "1", "+Muacul", "70"],
+ {ok, Peer, Node} = ?CT_PEER(Args),
ok = rpc:call(Node, ?MODULE, generate_test_blocks, []),
ok = Test(Node),
@@ -309,26 +309,7 @@ run_test(Args0, Test) ->
ok = rpc:call(Node, ?MODULE, churn_memory, []),
ok = Test(Node),
- true = test_server:stop_node(Node).
-
-start_slave(Args) ->
- MicroSecs = erlang:monotonic_time(),
- Name = "instr" ++ integer_to_list(MicroSecs),
- Pa = filename:dirname(code:which(?MODULE)),
-
- %% We pass arguments through ZFLAGS as the nightly tests rotate
- %% +Meamax/+Meamin which breaks the _enabled and _disabled tests unless
- %% overridden.
- ZFlags = os:getenv("ERL_ZFLAGS", ""),
- {ok, Node} = try
- os:putenv("ERL_ZFLAGS", ZFlags ++ [" " | Args]),
- test_server:start_node(list_to_atom(Name),
- slave,
- [{args, "-pa " ++ Pa}])
- after
- os:putenv("ERL_ZFLAGS", ZFlags)
- end,
- Node.
+ peer:stop(Peer).
generate_test_blocks() ->
Runner = self(),
diff --git a/lib/tools/test/make_SUITE.erl b/lib/tools/test/make_SUITE.erl
index 02da4f4ace..8d8e5d7559 100644
--- a/lib/tools/test/make_SUITE.erl
+++ b/lib/tools/test/make_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,16 +58,6 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(_,Config) ->
Config.
-end_per_testcase(netload,_Config) ->
- %% Stop slave - in case of failure
- Nodes = nodes(),
- case [N || N <- Nodes,
- "make_SUITE_netload" == hd(string:lexemes(atom_to_list(N),"@"))] of
- [Node] ->
- ct_slave:stop(Node);
- _ ->
- ok
- end;
end_per_testcase(_,_Config) ->
ok.
@@ -114,12 +104,12 @@ netload(Config) ->
code:purge(test1),
code:delete(test1),
false = code:is_loaded(test1),
- {ok,Node} = ct_slave:start(make_SUITE_netload),
+ {ok,Peer,Node} = ?CT_PEER(),
up_to_date = make:files([test1], [netload]),
timer:sleep(1000), % async, so give some time
{file,F} = code:is_loaded(test1),
{file,F} = rpc:call(Node,code,is_loaded,[test1]),
- ct_slave:stop(Node),
+ peer:stop(Peer),
file:set_cwd(Current),
ensure_no_messages(),
ok.
diff --git a/lib/tools/test/prof_bench_SUITE.erl b/lib/tools/test/prof_bench_SUITE.erl
index 28473872bd..798f2b7dab 100644
--- a/lib/tools/test/prof_bench_SUITE.erl
+++ b/lib/tools/test/prof_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,18 +32,28 @@
suite() ->
- [{timetrap,{minutes,15}}].
+ [{timetrap,{minutes,30}}].
all() ->
[overhead].
init_per_suite(Config) ->
- case {whereis(cover_server) =/= undefined,
- erlang:system_info(wordsize)}
- of
- {true, _} -> {skip, "Cover is running"};
- {_, 4} -> {skip, "Can't run on 32-bit as files will be large"};
- {false, 8} -> Config
+ case whereis(cover_server) of
+ undefined ->
+ application:ensure_all_started(os_mon),
+ Free = disk_free(proplists:get_value(priv_dir, Config)),
+ if
+ Free >= 16_000_000 ->
+ %% The size of the log files is about 4 Gb.
+ %% The disk has at least 4 times that amount free.
+ Config;
+ true ->
+ %% There might not be sufficient disk space free.
+ io:format("Free disk space: ~p Kb\n", [Free]),
+ {skip, "Insufficient free disk space"}
+ end;
+ Pid when is_pid(Pid) ->
+ {skip, "Cover is running"}
end.
end_per_suite(Config) ->
@@ -51,6 +61,23 @@ end_per_suite(Config) ->
file:delete(LogFile),
ok.
+%% Return amount disk space free in Kbs for the disk that Path
+%% is located on.
+disk_free(Path) ->
+ Data = disksup:get_disk_data(),
+
+ %% What partitions could Data be mounted on?
+ Partitions =
+ [D || {P, _Tot, _Perc}=D <- Data,
+ lists:prefix(filename:nativename(P), filename:nativename(Path))],
+
+ %% Sorting in descending order places the partition with the most specific
+ %% path first.
+ case lists:sort(fun erlang:'>='/2, Partitions) of
+ [{_,Tot, Perc} | _] -> round(Tot * (1-(Perc/100)));
+ [] -> error
+ end.
+
%%%---------------------------------------------------------------------
%% ct:run_test([{suite, prof_bench_SUITE}]).
@@ -83,20 +110,6 @@ overhead(Config) ->
data = [{name, cover_overhead},
{value, NormTime / CoverTime * 100}]}).
-%% overhead(Config) ->
-%% LogFile = filename:join(proplists:get_value(priv_dir, Config), "fprof.trace"),
-%% SofsCopy = filename:join(proplists:get_value(data_dir, Config), "sofs_copy.erl"),
-%% TC = fun() -> compile:file(SofsCopy, [binary]) end,
-%% _Warmup = timer:tc(TC),
-
-%% [{ok,{EProfTime,{ok,sofs_copy,_}}} = eprof:profile([], timer, tc, [TC])
-%% || _ <- lists:seq(1,10)],
-%% %% [fprof:apply(timer, tc, [TC], [{file, LogFile}]) || _ <- lists:seq(1,10)],
-%% {FProfTime,{ok,sofs_copy,_}} = fprof:apply(timer, tc, [TC], [{file, LogFile}]),
-%% {NormTime,{ok, sofs_copy, _}} = timer:tc(TC),
-
- %% ct:pal("FProf: ~p Norm: ~p Ratio: ~p",[FProfTime, NormTime, FProfTime / NormTime]).
-
cprof_apply(M, F, A) ->
cprof:start(),
Res = apply(M, F, A),
diff --git a/lib/tools/test/tools.spec.win b/lib/tools/test/tools.spec.win
index b43d542ff1..93d5930472 100644
--- a/lib/tools/test/tools.spec.win
+++ b/lib/tools/test/tools.spec.win
@@ -1,2 +1 @@
{topcase, {dir, "../tools_test"}}.
-{skip, {emem_SUITE, "Not on windows, yet. FIXME!!!"}}.
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 75ad7a6ff1..3824b54b52 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1679,7 +1679,7 @@ fun_mfa(Conf) when is_list(Conf) ->
ok = file:delete(Beam),
ok.
-%% fun M:F/A with varibles.
+%% fun M:F/A with variables.
fun_mfa_vars(Conf) when is_list(Conf) ->
Dir = ?copydir,
File = fname(Dir, "fun_mfa_vars.erl"),
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 4d10ec0d2a..2d58c23e21 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 3.5.2
+TOOLS_VSN = 3.5.3
diff --git a/lib/wx/Makefile b/lib/wx/Makefile
index c73baa9f6e..f471824a14 100644
--- a/lib/wx/Makefile
+++ b/lib/wx/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2021. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,12 +19,11 @@
#
include ./vsn.mk
+include ./config.mk
ifdef TERTIARY_BOOTSTRAP
- INSIDE_ERLSRC = true
SUBDIRS = src
else # Normal build
- include ./config.mk
SUBDIRS = src
ifeq ($(CAN_BUILD_DRIVER), true)
SUBDIRS += c_src
@@ -41,4 +40,6 @@ SUB_DIRECTORIES=$(SUBDIRS)
include $(ERL_TOP)/make/otp_subdir.mk
+TEST_NEEDS_RELEASE=true
+
include $(ERL_TOP)/make/app_targets.mk
diff --git a/lib/wx/api_gen/README b/lib/wx/api_gen/README
index 394469030c..364dbdd9f2 100644
--- a/lib/wx/api_gen/README
+++ b/lib/wx/api_gen/README
@@ -15,7 +15,7 @@ CONFIGURATION:
Adding/changing stuff/classes should be done by updating wxapi.conf
and running make. Sometimes the code generator will require changes,
- I havn't thought of everything yet.
+ I haven't thought of everything yet.
RUNNING:
I use the following alias wxgen='make GL_DIR=/home/dgud/opengl WX_DIR=/home/dgud/src/wxWidgets'
diff --git a/lib/wx/api_gen/apidiff.escript b/lib/wx/api_gen/apidiff.escript
index 952c5453de..61328e6e3e 100644
--- a/lib/wx/api_gen/apidiff.escript
+++ b/lib/wx/api_gen/apidiff.escript
@@ -207,7 +207,7 @@ write([{#f{c=wxShowEvent,f=getShow},_}|Rest], P, K) ->
write([{#f{c=wxSingleChoiceDialog,f=singleChoiceDialog, a=[]},_}|Rest], P, K) ->
write(Rest, P, K+1);
write([{#f{c=wxSizer,f=recalcSizes},_}|Rest], P, K) ->
- io:format("Removed wxSizer:recalcSizer() was an wxWidgets internal function now deprected~n", []),
+ io:format("Removed wxSizer:recalcSizer() was an wxWidgets internal function now deprecated~n", []),
write(Rest, P, K+1);
write([{#f{c=wxSizerItem,f=setWindow},_}|Rest], P, K) ->
io:format("Removed depr wxSizerItem:setWindow() use assignWindow~n", []),
diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl
index fa5ce4a91f..b2c3ae2112 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -89,6 +89,7 @@ gl_api(Fs, _GluNifs) ->
w("-on_load(init_nif/0).~n",[]),
w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]),
w("-export([get_interface/0, rec/1, lookup_func/0]).\n",[]),
+ w("-nifs([lookup_func/0]).\n",[]),
w("-define(nif_stub,nif_stub_error(?LINE)).~n", []),
w("%% @hidden~n", []),
w("nif_stub_error(Line) ->~n"
@@ -149,7 +150,7 @@ glu_api(Fs) ->
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"
+ "%% vertex positions. Returned is a list of indices of the vertices~n"
"%% and a binary (64bit native float) containing an array of~n"
"%% vertex positions, it starts with the vertices in Vs and~n"
"%% may contain newly created vertices in the end.~n", []),
diff --git a/lib/wx/api_gen/wx_doxygen.conf b/lib/wx/api_gen/wx_doxygen.conf
index b50e1b8af3..74041c819a 100644
--- a/lib/wx/api_gen/wx_doxygen.conf
+++ b/lib/wx/api_gen/wx_doxygen.conf
@@ -80,7 +80,7 @@ ALIASES += beginFlagTable="<div>"
ALIASES += flag{1}="</div>\li <span class='flag'>\1</span>:<div class='flagDesc'>"
ALIASES += endFlagTable="</div>\n"
-# apperance
+# appearance
ALIASES += appearance{1}="\htmlonly \1 \endhtmlonly"
ALIASES += genericAppearance{1}="\htmlonly \1 \endhtmlonly"
diff --git a/lib/wx/api_gen/wx_extra/added_func.h b/lib/wx/api_gen/wx_extra/added_func.h
index 654cc8b430..d3d8527976 100644
--- a/lib/wx/api_gen/wx_extra/added_func.h
+++ b/lib/wx/api_gen/wx_extra/added_func.h
@@ -28,7 +28,7 @@ class WXDLLIMPEXP_ADV wxTreeCtrlBase : public wxControl
static bool IsTreeItemIdOk(wxTreeItemId id);
};
-// The generater needs constructors (is this still valid?)
+// The generator needs constructors (is this still valid?)
class WXDLLIMPEXP_ADV wxGridCellBoolRenderer : public wxGridCellRenderer
{
public:
@@ -49,7 +49,7 @@ class wxMenuBar {
static bool GetAutoWindowMenu() { return s_macAutoWindowMenu ; }
};
-// Deprectated functions in 3.1
+// Deprecated functions in 3.1
class wxWindow {
public:
diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
index 8d0d97e8f0..628e22aa9e 100644
--- a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
+++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl
@@ -13,10 +13,10 @@
%% (in another process) to handle the event. The callback should be of
%% arity 2. fun(EventRecord::wx(), EventObject::wxObject()).
%%
-%% Beware that the callback will be in executed in new process each time.
+%% Beware that the callback will be executed in a new process each time.
%%
%% <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html">
-%% The orginal documentation</a>.
+%% The original documentation</a>.
%%
%%
-module(wxEvtHandler).
@@ -51,8 +51,9 @@ connect(This, EventType) ->
%% {skip, boolean()}, If skip is true further event_handlers will be called.
%% This is not used if the 'callback' option is used.
%% Default false.
+%% callback Use `wx_object' callback `handle_sync_event/3'.
%% {callback, function()} Use a callback fun(EventRecord::wx(), EventObject::wxObject())
-%% to process the event. Default not specfied i.e. a message will
+%% to process the event. Default not specified 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
diff --git a/lib/wx/api_gen/wx_extra/wxe_evth.h b/lib/wx/api_gen/wx_extra/wxe_evth.h
index 2d4d7276a8..7b9b189381 100644
--- a/lib/wx/api_gen/wx_extra/wxe_evth.h
+++ b/lib/wx/api_gen/wx_extra/wxe_evth.h
@@ -55,7 +55,7 @@ class wxeEvtHandler : public wxObject
callback: @verbatim {callback,function()} @endverbatim
Use a callback @verbatim fun(EventRecord::wx(),EventObject::wxObject()) @endverbatim
- to process the event. Default not specfied i.e. a message will
+ to process the event. Default not specified i.e. a message will
be delivered to the process calling this function.
userData: @verbatim {userData,term()} @endverbatim
diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl
index 3fabcd9e2a..477e09d318 100644
--- a/lib/wx/api_gen/wx_gen.erl
+++ b/lib/wx/api_gen/wx_gen.erl
@@ -649,7 +649,7 @@ parse_param(#xmlElement{name=declname,content=[C]},_Opts,T) ->
parse_param(#xmlElement{name=defval,content=[#xmlText{value=Def}]},_Opts,T) ->
T#param{def=string:strip(Def)};
parse_param(#xmlElement{name=defval,content=Other},_Opts,T) ->
- %% For defaults = (modifer wxType *) NULL
+ %% For defaults = (modifier wxType *) NULL
Def0 = foldr(fun(#xmlText{value=V}, Acc) -> V ++ Acc;
(#xmlElement{content=[#xmlText{value=V}]},Acc) ->
V ++ Acc
@@ -1523,7 +1523,7 @@ enum_file(File) ->
parse_enums(Files) ->
DontSearch = ["wxchar","filefn", "platform", "strconv", "filename",
"buffer", "string", "debug", "platinfo"],
- %% Arg need to patch some specials, atleast for wx-2.6
+ %% Arg need to patch some specials, at least for wx-2.6
ExtraSearch = ["layout", "utils", "added__func"],
io:format("~nParse Enums~n~n", []),
parse_enums(Files ++ ExtraSearch,gb_sets:from_list(DontSearch)).
diff --git a/lib/wx/api_gen/wx_gen.hrl b/lib/wx/api_gen/wx_gen.hrl
index 252de3d0c9..c7d1ee8022 100644
--- a/lib/wx/api_gen/wx_gen.hrl
+++ b/lib/wx/api_gen/wx_gen.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
file = undefined,
options = undefined,
abstract = false,
- id, % Unique integer identifer
+ id, % Unique integer identifier
doc
}).
diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl
index 28b357f331..6b07689a1e 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1016,7 +1016,8 @@ gen_enums_ints() ->
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"
+ " altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean(),~n"
+ " aux1Down :: boolean(), aux2Down :: boolean()~n"
" }).~n", []),
w("-record(wxHtmlLinkInfo, {~n"
" href :: unicode:chardata(), target :: unicode:chardata()~n"
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index 544ea869b7..5d0365da5d 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -653,6 +653,8 @@
{'SetAutoWindowMenu', [{test_if, "defined(__WXMAC__)"}]},
{'GetAutoWindowMenu', [{test_if, "defined(__WXMAC__)"}]},
{'OSXGetAppleMenu', [{test_if, "defined(__WXMAC__)"}]},
+ {'MacGetCommonMenuBar', [{test_if, "defined(__WXMAC__)"}]},
+ {'MacSetCommonMenuBar', [{test_if, "defined(__WXMAC__)"}]},
'IsEnabled',%'Refresh',
'Remove','Replace','SetHelpString',
'SetLabel',
@@ -1473,7 +1475,7 @@
'RightDockable','Row','SafeSet','SetFlag','Show','ToolbarPane',
'Top','TopDockable','Window',
%% Extended func
- %% These are not initilized by default and thus cause crashes
+ %% These are not initialized by default and thus cause crashes
%% {'GetName',
%% [{pre_hook, [{c, "#if 0\n"}]},
%% {post_hook, [{c, "#endif\n if(!This) throw wxe_badarg(0);\n wxString Result = This->name"}]}]},
@@ -1655,17 +1657,19 @@
%%, wxEVT_MAGNIFY % 3.1
]}],
['AltDown','Button','ButtonDClick','ButtonDown','ButtonUp','CmdDown','ControlDown',
- 'Dragging', 'Entering', 'GetButton', 'GetPosition',
+ 'Dragging', 'Entering', 'GetButton', 'GetPosition',
'GetLogicalPosition',
'GetLinesPerAction', 'GetWheelRotation', 'GetWheelDelta', 'GetX', 'GetY',
'IsButton', 'IsPageScroll', 'Leaving',
- 'LeftDClick', 'LeftDown', 'LeftIsDown', 'LeftUp',
- 'MetaDown',
- 'MiddleDClick', 'MiddleDown', 'MiddleIsDown', 'MiddleUp',
- 'Moving',
- 'RightDClick', 'RightDown', 'RightIsDown', 'RightUp',
+ 'LeftDClick', 'LeftDown', 'LeftIsDown', 'LeftUp',
+ 'MetaDown',
+ 'MiddleDClick', 'MiddleDown', 'MiddleIsDown', 'MiddleUp',
+ 'Moving',
+ 'RightDClick', 'RightDown', 'RightIsDown', 'RightUp',
'ShiftDown',
- 'GetWheelAxis'
+ 'GetWheelAxis',
+ 'Aux1DClick', 'Aux1Down', 'Aux1Up',
+ 'Aux2DClick', 'Aux2Down', 'Aux2Up'
]}.
{class, wxSetCursorEvent, wxEvent,
@@ -2236,7 +2240,7 @@
{class, wxTaskBarIcon, wxEvtHandler, [],
[{wxTaskBarIcon, [{where, taylormade}]},'~wxTaskBarIcon',
- %%'CreatePopupMenu', virtual overrided is a callback
+ %%'CreatePopupMenu', virtual overridden is a callback
%% 'IsIconInstalled', 'IsOk', not available on mac
'PopupMenu','RemoveIcon','SetIcon']}.
diff --git a/lib/wx/autoconf/config.guess b/lib/wx/autoconf/config.guess
deleted file mode 100755
index 1972fda8eb..0000000000
--- a/lib/wx/autoconf/config.guess
+++ /dev/null
@@ -1,1700 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-# Copyright 1992-2021 Free Software Foundation, Inc.
-
-timestamp='2021-01-25'
-
-# 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 3 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, see <https://www.gnu.org/licenses/>.
-#
-# 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. This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-#
-# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
-#
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-#
-# Please send patches to <config-patches@gnu.org>.
-
-
-me=$(echo "$0" | sed -e 's,.*/,,')
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Options:
- -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 <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright 1992-2021 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
-
-# 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.
-
-tmp=
-# shellcheck disable=SC2172
-trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
-
-set_cc_for_build() {
- # prevent multiple calls if $tmp is already set
- test "$tmp" && return 0
- : "${TMPDIR=/tmp}"
- # shellcheck disable=SC2039
- { 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" 2>/dev/null) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
- dummy=$tmp/dummy
- case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
- ,,) echo "int x;" > "$dummy.c"
- for driver in cc gcc c89 c99 ; do
- if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$driver"
- 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
-}
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if test -f /.attbin/uname ; 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
-
-case "$UNAME_SYSTEM" in
-Linux|GNU|GNU/*)
- LIBC=unknown
-
- set_cc_for_build
- cat <<-EOF > "$dummy.c"
- #include <features.h>
- #if defined(__UCLIBC__)
- LIBC=uclibc
- #elif defined(__dietlibc__)
- LIBC=dietlibc
- #elif defined(__GLIBC__)
- LIBC=gnu
- #else
- #include <stdarg.h>
- /* First heuristic to detect musl libc. */
- #ifdef __DEFINED_va_list
- LIBC=musl
- #endif
- #endif
- EOF
- eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
-
- # Second heuristic to detect musl libc.
- if [ "$LIBC" = unknown ] &&
- command -v ldd >/dev/null &&
- ldd --version 2>&1 | grep -q ^musl; then
- LIBC=musl
- fi
-
- # If the system lacks a compiler, then just pick glibc.
- # We could probably try harder.
- if [ "$LIBC" = unknown ]; then
- LIBC=gnu
- fi
- ;;
-esac
-
-# 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 tuples: *-*-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".
- UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
- /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
- /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
- echo unknown))
- case "$UNAME_MACHINE_ARCH" in
- aarch64eb) machine=aarch64_be-unknown ;;
- armeb) machine=armeb-unknown ;;
- arm*) machine=arm-unknown ;;
- sh3el) machine=shl-unknown ;;
- sh3eb) machine=sh-unknown ;;
- sh5el) machine=sh5le-unknown ;;
- earmv*)
- arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
- endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
- machine="${arch}${endian}"-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) and ABI.
- case "$UNAME_MACHINE_ARCH" in
- earm*)
- os=netbsdelf
- ;;
- arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- set_cc_for_build
- if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ELF__
- 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
- # Determine ABI tags.
- case "$UNAME_MACHINE_ARCH" in
- earm*)
- expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
- ;;
- 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/[-_].*//' | cut -d. -f1,2)
- ;;
- 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}${abi-}"
- exit ;;
- *:Bitrig:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
- exit ;;
- *:OpenBSD:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
- exit ;;
- *:LibertyBSD:*:*)
- UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
- echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
- exit ;;
- *:MidnightBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
- exit ;;
- *:ekkoBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
- exit ;;
- *:SolidBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
- exit ;;
- *:OS108:*:*)
- echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
- exit ;;
- macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
- exit ;;
- *:MirBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
- exit ;;
- *:Sortix:*:*)
- echo "$UNAME_MACHINE"-unknown-sortix
- exit ;;
- *:Twizzler:*:*)
- echo "$UNAME_MACHINE"-unknown-twizzler
- exit ;;
- *:Redox:*:*)
- echo "$UNAME_MACHINE"-unknown-redox
- exit ;;
- mips:OSF1:*.*)
- echo mips-dec-osf1
- 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)"
- # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
- exitcode=$?
- trap '' 0
- exit $exitcode ;;
- 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*:*:*)
- # akee@wpdis03.wpafb.af.mil (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 ;;
- s390x:SunOS:*:*)
- echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
- exit ;;
- 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:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux"$UNAME_RELEASE"
- exit ;;
- i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- set_cc_for_build
- SUN_ARCH=i386
- # If there is a compiler, see if it is configured for 64-bit objects.
- # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
- # This test works for both compilers.
- if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- SUN_ARCH=x86_64
- fi
- fi
- echo "$SUN_ARCH"-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)
- 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 test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
- then
- if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
- test "$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 test -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
- 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:*:[4567])
- 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 test -x /usr/bin/lslpp ; then
- IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
- awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
- 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:4.4BSD:*)
- 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 test -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 test "$HP_ARCH" = ""; then
- 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 test "$HP_ARCH" = hppa2.0w
- then
- 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 -q __LP64__
- 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:*:*)
- 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 test -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 ;;
- arm:FreeBSD:*:*)
- UNAME_PROCESSOR=$(uname -p)
- set_cc_for_build
- if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_PCS_VFP
- then
- echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
- else
- echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
- fi
- exit ;;
- *:FreeBSD:*:*)
- UNAME_PROCESSOR=$(/usr/bin/uname -p)
- case "$UNAME_PROCESSOR" in
- amd64)
- UNAME_PROCESSOR=x86_64 ;;
- i386)
- UNAME_PROCESSOR=i586 ;;
- esac
- echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
- exit ;;
- i*:CYGWIN*:*)
- echo "$UNAME_MACHINE"-pc-cygwin
- exit ;;
- *:MINGW64*:*)
- echo "$UNAME_MACHINE"-pc-mingw64
- exit ;;
- *:MINGW*:*)
- echo "$UNAME_MACHINE"-pc-mingw32
- exit ;;
- *:MSYS*:*)
- echo "$UNAME_MACHINE"-pc-msys
- exit ;;
- i*:PW*:*)
- echo "$UNAME_MACHINE"-pc-pw32
- exit ;;
- *:Interix*:*)
- case "$UNAME_MACHINE" in
- x86)
- echo i586-pc-interix"$UNAME_RELEASE"
- exit ;;
- authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix"$UNAME_RELEASE"
- exit ;;
- IA64)
- echo ia64-unknown-interix"$UNAME_RELEASE"
- exit ;;
- esac ;;
- i*:UWIN*:*)
- echo "$UNAME_MACHINE"-pc-uwin
- exit ;;
- amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-pc-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-$LIBC$(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 "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
- exit ;;
- *:Minix:*:*)
- echo "$UNAME_MACHINE"-unknown-minix
- exit ;;
- aarch64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- aarch64_be:Linux:*:*)
- UNAME_MACHINE=aarch64_be
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- alpha:Linux:*:*)
- case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) 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 -q ld.so.1
- if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- arc:Linux:*:* | arceb:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- arm*:Linux:*:*)
- set_cc_for_build
- if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_EABI__
- then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- else
- if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep -q __ARM_PCS_VFP
- then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
- else
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
- fi
- fi
- exit ;;
- avr32*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- cris:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
- exit ;;
- crisv32:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
- exit ;;
- e2k:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- frv:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- hexagon:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- i*86:Linux:*:*)
- echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
- exit ;;
- ia64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- k1om:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- m32r*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- m68*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- mips:Linux:*:* | mips64:Linux:*:*)
- set_cc_for_build
- IS_GLIBC=0
- test x"${LIBC}" = xgnu && IS_GLIBC=1
- sed 's/^ //' << EOF > "$dummy.c"
- #undef CPU
- #undef mips
- #undef mipsel
- #undef mips64
- #undef mips64el
- #if ${IS_GLIBC} && defined(_ABI64)
- LIBCABI=gnuabi64
- #else
- #if ${IS_GLIBC} && defined(_ABIN32)
- LIBCABI=gnuabin32
- #else
- LIBCABI=${LIBC}
- #endif
- #endif
-
- #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
- CPU=mipsisa64r6
- #else
- #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
- CPU=mipsisa32r6
- #else
- #if defined(__mips64)
- CPU=mips64
- #else
- CPU=mips
- #endif
- #endif
- #endif
-
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- MIPS_ENDIAN=el
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- MIPS_ENDIAN=
- #else
- MIPS_ENDIAN=
- #endif
- #endif
-EOF
- eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
- test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
- ;;
- mips64el:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- openrisc*:Linux:*:*)
- echo or1k-unknown-linux-"$LIBC"
- exit ;;
- or32:Linux:*:* | or1k*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- padre:Linux:*:*)
- echo sparc-unknown-linux-"$LIBC"
- exit ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-"$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-"$LIBC" ;;
- PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
- *) echo hppa-unknown-linux-"$LIBC" ;;
- esac
- exit ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-"$LIBC"
- exit ;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-"$LIBC"
- exit ;;
- ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-"$LIBC"
- exit ;;
- ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-"$LIBC"
- exit ;;
- riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- s390:Linux:*:* | s390x:Linux:*:*)
- echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
- exit ;;
- sh64*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- sh*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- sparc:Linux:*:* | sparc64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- tile*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
- vax:Linux:*:*)
- echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
- exit ;;
- x86_64:Linux:*:*)
- set_cc_for_build
- LIBCABI=$LIBC
- if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_X32 >/dev/null
- then
- LIBCABI="$LIBC"x32
- fi
- fi
- echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
- exit ;;
- xtensa*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- 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.[02]*:*)
- echo i386-unknown-lynxos"$UNAME_RELEASE"
- exit ;;
- i*86:*DOS:*:*)
- echo "$UNAME_MACHINE"-pc-msdosdjgpp
- exit ;;
- i*86:*: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 i586.
- # Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configure will decide that
- # this is a cross-build.
- echo i586-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; } ;;
- NCR*:*:4.2:* | MPRAS*:*:4.2:*)
- OS_REL='.3'
- 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; }
- /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3"$OS_REL"; 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.[02]*:*)
- 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
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit ;;
- *:UNIX_System_V:4*:FTX*)
- # From Gerald Hewes <hewes@openmarket.com>.
- # How about differentiating between stratus architectures? -djm
- echo hppa1.1-stratus-sysv4
- exit ;;
- *:*:*:FTX*)
- # From seanf@swdc.stratus.com.
- echo i860-stratus-sysv4
- exit ;;
- i*86:VOS:*:*)
- # From Paul.Green@stratus.com.
- echo "$UNAME_MACHINE"-stratus-vos
- exit ;;
- *:VOS:*:*)
- # From Paul.Green@stratus.com.
- 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 test -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 ;;
- BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
- echo i586-pc-haiku
- exit ;;
- x86_64:Haiku:*:*)
- echo x86_64-unknown-haiku
- 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 ;;
- SX-ACE:SUPER-UX:*:*)
- echo sxace-nec-superux"$UNAME_RELEASE"
- exit ;;
- Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody"$UNAME_RELEASE"
- exit ;;
- *:Rhapsody:*:*)
- echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
- exit ;;
- arm64:Darwin:*:*)
- echo aarch64-apple-darwin"$UNAME_RELEASE"
- exit ;;
- *:Darwin:*:*)
- UNAME_PROCESSOR=$(uname -p)
- case $UNAME_PROCESSOR in
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
- if command -v xcode-select > /dev/null 2> /dev/null && \
- ! xcode-select --print-path > /dev/null 2> /dev/null ; then
- # Avoid executing cc if there is no toolchain installed as
- # cc will be a stub that puts up a graphical alert
- # prompting the user to install developer tools.
- CC_FOR_BUILD=no_compiler_found
- else
- set_cc_for_build
- fi
- if test "$CC_FOR_BUILD" != no_compiler_found; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
- # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
- if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_PPC >/dev/null
- then
- UNAME_PROCESSOR=powerpc
- fi
- elif test "$UNAME_PROCESSOR" = i386 ; then
- # uname -m returns i386 or x86_64
- UNAME_PROCESSOR=$UNAME_MACHINE
- fi
- 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 ;;
- NEO-*:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSR-*:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSV-*:NONSTOP_KERNEL:*:*)
- echo nsv-tandem-nsk"$UNAME_RELEASE"
- exit ;;
- NSX-*:NONSTOP_KERNEL:*:*)
- echo nsx-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.
- # shellcheck disable=SC2154
- 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 ;;
- *:AROS:*:*)
- echo "$UNAME_MACHINE"-unknown-aros
- exit ;;
- x86_64:VMkernel:*:*)
- echo "$UNAME_MACHINE"-unknown-esx
- exit ;;
- amd64:Isilon\ OneFS:*:*)
- echo x86_64-unknown-onefs
- exit ;;
- *:Unleashed:*:*)
- echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
- exit ;;
-esac
-
-# No uname command or uname output not recognized.
-set_cc_for_build
-cat > "$dummy.c" <<EOF
-#ifdef _SEQUENT_
-#include <sys/types.h>
-#include <sys/utsname.h>
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
-#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#include <signal.h>
-#if defined(_SIZE_T_) || defined(SIGLOST)
-#include <sys/utsname.h>
-#endif
-#endif
-#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 (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
-#if defined(_SIZE_T_) || defined(SIGLOST)
- struct utsname un;
- uname (&un);
- printf ("vax-dec-ultrix%s\n", un.release); exit (0);
-#else
- printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
-#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#if defined(_SIZE_T_) || defined(SIGLOST)
- struct utsname *un;
- uname (&un);
- printf ("mips-dec-ultrix%s\n", un.release); exit (0);
-#else
- printf ("mips-dec-ultrix\n"); exit (0);
-#endif
-#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; }
-
-echo "$0: unable to guess system type" >&2
-
-case "$UNAME_MACHINE:$UNAME_SYSTEM" in
- mips:Linux | mips64:Linux)
- # If we got here on MIPS GNU/Linux, output extra information.
- cat >&2 <<EOF
-
-NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
-the system type. Please install a C compiler and try again.
-EOF
- ;;
-esac
-
-cat >&2 <<EOF
-
-This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite *all*
-copies of config.guess and config.sub with the latest versions from:
-
- https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-and
- https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-EOF
-
-year=$(echo $timestamp | sed 's,-.*,,')
-# shellcheck disable=SC2003
-if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
- cat >&2 <<EOF
-
-If $0 has already been updated, send the following data and any
-information you think might be pertinent to config-patches@gnu.org to
-provide the necessary 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
-fi
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/lib/wx/autoconf/config.sub b/lib/wx/autoconf/config.sub
deleted file mode 100755
index 63c1f1c8b5..0000000000
--- a/lib/wx/autoconf/config.sub
+++ /dev/null
@@ -1,1860 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-# Copyright 1992-2021 Free Software Foundation, Inc.
-
-timestamp='2021-01-08'
-
-# 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 3 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, see <https://www.gnu.org/licenses/>.
-#
-# 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. This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-
-
-# Please send patches to <config-patches@gnu.org>.
-#
-# 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.
-
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-
-# 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 or ALIAS
-
-Canonicalize a configuration name.
-
-Options:
- -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 <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright 1992-2021 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 ;;
-
- *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
-
-# Split fields of configuration type
-# shellcheck disable=SC2162
-IFS="-" read field1 field2 field3 field4 <<EOF
-$1
-EOF
-
-# Separate into logical components for further validation
-case $1 in
- *-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
- exit 1
- ;;
- *-*-*-*)
- basic_machine=$field1-$field2
- basic_os=$field3-$field4
- ;;
- *-*-*)
- # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
- # parts
- maybe_os=$field2-$field3
- case $maybe_os in
- nto-qnx* | linux-* | uclinux-uclibc* \
- | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
- | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova*)
- basic_machine=$field1
- basic_os=$maybe_os
- ;;
- android-linux)
- basic_machine=$field1-unknown
- basic_os=linux-android
- ;;
- *)
- basic_machine=$field1-$field2
- basic_os=$field3
- ;;
- esac
- ;;
- *-*)
- # A lone config we happen to match not fitting any pattern
- case $field1-$field2 in
- decstation-3100)
- basic_machine=mips-dec
- basic_os=
- ;;
- *-*)
- # Second component is usually, but not always the OS
- case $field2 in
- # Prevent following clause from handling this valid os
- sun*os*)
- basic_machine=$field1
- basic_os=$field2
- ;;
- # Manufacturers
- dec* | mips* | sequent* | encore* | pc533* | 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 \
- | microblaze* | sim | cisco \
- | oki | wec | wrs | winbond)
- basic_machine=$field1-$field2
- basic_os=
- ;;
- *)
- basic_machine=$field1
- basic_os=$field2
- ;;
- esac
- ;;
- esac
- ;;
- *)
- # Convert single-component short-hands not valid as part of
- # multi-component configurations.
- case $field1 in
- 386bsd)
- basic_machine=i386-pc
- basic_os=bsd
- ;;
- a29khif)
- basic_machine=a29k-amd
- basic_os=udi
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- basic_os=scout
- ;;
- alliant)
- basic_machine=fx80-alliant
- basic_os=
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- basic_os=
- ;;
- am29k)
- basic_machine=a29k-none
- basic_os=bsd
- ;;
- amdahl)
- basic_machine=580-amdahl
- basic_os=sysv
- ;;
- amiga)
- basic_machine=m68k-unknown
- basic_os=
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- basic_os=amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- basic_os=sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- basic_os=sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- basic_os=bsd
- ;;
- aros)
- basic_machine=i386-pc
- basic_os=aros
- ;;
- aux)
- basic_machine=m68k-apple
- basic_os=aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- basic_os=dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- basic_os=linux
- ;;
- cegcc)
- basic_machine=arm-unknown
- basic_os=cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- basic_os=bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- basic_os=bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- basic_os=bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- basic_os=bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- basic_os=bsd
- ;;
- cray)
- basic_machine=j90-cray
- basic_os=unicos
- ;;
- crds | unos)
- basic_machine=m68k-crds
- basic_os=
- ;;
- da30)
- basic_machine=m68k-da30
- basic_os=
- ;;
- decstation | pmax | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
- basic_os=
- ;;
- delta88)
- basic_machine=m88k-motorola
- basic_os=sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- basic_os=dicos
- ;;
- djgpp)
- basic_machine=i586-pc
- basic_os=msdosdjgpp
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- basic_os=ebmon
- ;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- basic_os=ose
- ;;
- gmicro)
- basic_machine=tron-gmicro
- basic_os=sysv
- ;;
- go32)
- basic_machine=i386-pc
- basic_os=go32
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- basic_os=hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- basic_os=xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- basic_os=hms
- ;;
- harris)
- basic_machine=m88k-harris
- basic_os=sysv3
- ;;
- hp300 | hp300hpux)
- basic_machine=m68k-hp
- basic_os=hpux
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- basic_os=bsd
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- basic_os=osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- basic_os=proelf
- ;;
- i386mach)
- basic_machine=i386-mach
- basic_os=mach
- ;;
- isi68 | isi)
- basic_machine=m68k-isi
- basic_os=sysv
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- basic_os=linux
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- basic_os=sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- basic_os=sysv
- ;;
- mingw64)
- basic_machine=x86_64-pc
- basic_os=mingw64
- ;;
- mingw32)
- basic_machine=i686-pc
- basic_os=mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- basic_os=mingw32ce
- ;;
- monitor)
- basic_machine=m68k-rom68k
- basic_os=coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- basic_os=morphos
- ;;
- moxiebox)
- basic_machine=moxie-unknown
- basic_os=moxiebox
- ;;
- msdos)
- basic_machine=i386-pc
- basic_os=msdos
- ;;
- msys)
- basic_machine=i686-pc
- basic_os=msys
- ;;
- mvs)
- basic_machine=i370-ibm
- basic_os=mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- basic_os=nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- basic_os=sysv4
- ;;
- netbsd386)
- basic_machine=i386-pc
- basic_os=netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- basic_os=linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- basic_os=newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- basic_os=newsos
- ;;
- necv70)
- basic_machine=v70-nec
- basic_os=sysv
- ;;
- nh3000)
- basic_machine=m68k-harris
- basic_os=cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- basic_os=cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- basic_os=nindy
- ;;
- mon960)
- basic_machine=i960-intel
- basic_os=mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- basic_os=nonstopux
- ;;
- os400)
- basic_machine=powerpc-ibm
- basic_os=os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- basic_os=ose
- ;;
- os68k)
- basic_machine=m68k-none
- basic_os=os68k
- ;;
- paragon)
- basic_machine=i860-intel
- basic_os=osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- basic_os=linux
- ;;
- psp)
- basic_machine=mipsallegrexel-sony
- basic_os=psp
- ;;
- pw32)
- basic_machine=i586-unknown
- basic_os=pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- basic_os=rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- basic_os=rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- basic_os=coff
- ;;
- sa29200)
- basic_machine=a29k-amd
- basic_os=udi
- ;;
- sei)
- basic_machine=mips-sei
- basic_os=seiux
- ;;
- sequent)
- basic_machine=i386-sequent
- basic_os=
- ;;
- sps7)
- basic_machine=m68k-bull
- basic_os=sysv2
- ;;
- st2000)
- basic_machine=m68k-tandem
- basic_os=
- ;;
- stratus)
- basic_machine=i860-stratus
- basic_os=sysv4
- ;;
- sun2)
- basic_machine=m68000-sun
- basic_os=
- ;;
- sun2os3)
- basic_machine=m68000-sun
- basic_os=sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- basic_os=sunos4
- ;;
- sun3)
- basic_machine=m68k-sun
- basic_os=
- ;;
- sun3os3)
- basic_machine=m68k-sun
- basic_os=sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- basic_os=sunos4
- ;;
- sun4)
- basic_machine=sparc-sun
- basic_os=
- ;;
- sun4os3)
- basic_machine=sparc-sun
- basic_os=sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- basic_os=sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- basic_os=solaris2
- ;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
- basic_os=
- ;;
- sv1)
- basic_machine=sv1-cray
- basic_os=unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- basic_os=dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- basic_os=unicos
- ;;
- t90)
- basic_machine=t90-cray
- basic_os=unicos
- ;;
- toad1)
- basic_machine=pdp10-xkl
- basic_os=tops20
- ;;
- tpf)
- basic_machine=s390x-ibm
- basic_os=tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- basic_os=udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- basic_os=sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- basic_os=none
- ;;
- vaxv)
- basic_machine=vax-dec
- basic_os=sysv
- ;;
- vms)
- basic_machine=vax-dec
- basic_os=vms
- ;;
- vsta)
- basic_machine=i386-pc
- basic_os=vsta
- ;;
- vxworks960)
- basic_machine=i960-wrs
- basic_os=vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- basic_os=vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- basic_os=vxworks
- ;;
- xbox)
- basic_machine=i686-pc
- basic_os=mingw32
- ;;
- ymp)
- basic_machine=ymp-cray
- basic_os=unicos
- ;;
- *)
- basic_machine=$1
- basic_os=
- ;;
- esac
- ;;
-esac
-
-# Decode 1-component or ad-hoc basic machines
-case $basic_machine in
- # 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)
- cpu=hppa1.1
- vendor=winbond
- ;;
- op50n)
- cpu=hppa1.1
- vendor=oki
- ;;
- op60c)
- cpu=hppa1.1
- vendor=oki
- ;;
- ibm*)
- cpu=i370
- vendor=ibm
- ;;
- orion105)
- cpu=clipper
- vendor=highlevel
- ;;
- mac | mpw | mac-mpw)
- cpu=m68k
- vendor=apple
- ;;
- pmac | pmac-mpw)
- cpu=powerpc
- vendor=apple
- ;;
-
- # Recognize the various machine names and aliases which stand
- # for a CPU type and a company and sometimes even an OS.
- 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- cpu=m68000
- vendor=att
- ;;
- 3b*)
- cpu=we32k
- vendor=att
- ;;
- bluegene*)
- cpu=powerpc
- vendor=ibm
- basic_os=cnk
- ;;
- decsystem10* | dec10*)
- cpu=pdp10
- vendor=dec
- basic_os=tops10
- ;;
- decsystem20* | dec20*)
- cpu=pdp10
- vendor=dec
- basic_os=tops20
- ;;
- delta | 3300 | motorola-3300 | motorola-delta \
- | 3300-motorola | delta-motorola)
- cpu=m68k
- vendor=motorola
- ;;
- dpx2*)
- cpu=m68k
- vendor=bull
- basic_os=sysv3
- ;;
- encore | umax | mmax)
- cpu=ns32k
- vendor=encore
- ;;
- elxsi)
- cpu=elxsi
- vendor=elxsi
- basic_os=${basic_os:-bsd}
- ;;
- fx2800)
- cpu=i860
- vendor=alliant
- ;;
- genix)
- cpu=ns32k
- vendor=ns
- ;;
- h3050r* | hiux*)
- cpu=hppa1.1
- vendor=hitachi
- basic_os=hiuxwe2
- ;;
- hp3k9[0-9][0-9] | hp9[0-9][0-9])
- cpu=hppa1.0
- vendor=hp
- ;;
- hp9k2[0-9][0-9] | hp9k31[0-9])
- cpu=m68000
- vendor=hp
- ;;
- hp9k3[2-9][0-9])
- cpu=m68k
- vendor=hp
- ;;
- hp9k6[0-9][0-9] | hp6[0-9][0-9])
- cpu=hppa1.0
- vendor=hp
- ;;
- hp9k7[0-79][0-9] | hp7[0-79][0-9])
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k78[0-9] | hp78[0-9])
- # FIXME: really hppa2.0-hp
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
- # FIXME: really hppa2.0-hp
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k8[0-9][13679] | hp8[0-9][13679])
- cpu=hppa1.1
- vendor=hp
- ;;
- hp9k8[0-9][0-9] | hp8[0-9][0-9])
- cpu=hppa1.0
- vendor=hp
- ;;
- i*86v32)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=sysv32
- ;;
- i*86v4*)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=sysv4
- ;;
- i*86v)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=sysv
- ;;
- i*86sol2)
- cpu=$(echo "$1" | sed -e 's/86.*/86/')
- vendor=pc
- basic_os=solaris2
- ;;
- j90 | j90-cray)
- cpu=j90
- vendor=cray
- basic_os=${basic_os:-unicos}
- ;;
- iris | iris4d)
- cpu=mips
- vendor=sgi
- case $basic_os in
- irix*)
- ;;
- *)
- basic_os=irix4
- ;;
- esac
- ;;
- miniframe)
- cpu=m68000
- vendor=convergent
- ;;
- *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
- cpu=m68k
- vendor=atari
- basic_os=mint
- ;;
- news-3600 | risc-news)
- cpu=mips
- vendor=sony
- basic_os=newsos
- ;;
- next | m*-next)
- cpu=m68k
- vendor=next
- case $basic_os in
- openstep*)
- ;;
- nextstep*)
- ;;
- ns2*)
- basic_os=nextstep2
- ;;
- *)
- basic_os=nextstep3
- ;;
- esac
- ;;
- np1)
- cpu=np1
- vendor=gould
- ;;
- op50n-* | op60c-*)
- cpu=hppa1.1
- vendor=oki
- basic_os=proelf
- ;;
- pa-hitachi)
- cpu=hppa1.1
- vendor=hitachi
- basic_os=hiuxwe2
- ;;
- pbd)
- cpu=sparc
- vendor=tti
- ;;
- pbb)
- cpu=m68k
- vendor=tti
- ;;
- pc532)
- cpu=ns32k
- vendor=pc532
- ;;
- pn)
- cpu=pn
- vendor=gould
- ;;
- power)
- cpu=power
- vendor=ibm
- ;;
- ps2)
- cpu=i386
- vendor=ibm
- ;;
- rm[46]00)
- cpu=mips
- vendor=siemens
- ;;
- rtpc | rtpc-*)
- cpu=romp
- vendor=ibm
- ;;
- sde)
- cpu=mipsisa32
- vendor=sde
- basic_os=${basic_os:-elf}
- ;;
- simso-wrs)
- cpu=sparclite
- vendor=wrs
- basic_os=vxworks
- ;;
- tower | tower-32)
- cpu=m68k
- vendor=ncr
- ;;
- vpp*|vx|vx-*)
- cpu=f301
- vendor=fujitsu
- ;;
- w65)
- cpu=w65
- vendor=wdc
- ;;
- w89k-*)
- cpu=hppa1.1
- vendor=winbond
- basic_os=proelf
- ;;
- none)
- cpu=none
- vendor=none
- ;;
- leon|leon[3-9])
- cpu=sparc
- vendor=$basic_machine
- ;;
- leon-*|leon[3-9]-*)
- cpu=sparc
- vendor=$(echo "$basic_machine" | sed 's/-.*//')
- ;;
-
- *-*)
- # shellcheck disable=SC2162
- IFS="-" read cpu vendor <<EOF
-$basic_machine
-EOF
- ;;
- # 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)
- cpu=$basic_machine
- vendor=pc
- ;;
- # These rules are duplicated from below for sake of the special case above;
- # i.e. things that normalized to x86 arches should also default to "pc"
- pc98)
- cpu=i386
- vendor=pc
- ;;
- x64 | amd64)
- cpu=x86_64
- vendor=pc
- ;;
- # Recognize the basic CPU types without company name.
- *)
- cpu=$basic_machine
- vendor=unknown
- ;;
-esac
-
-unset -v basic_machine
-
-# Decode basic machines in the full and proper CPU-Company form.
-case $cpu-$vendor in
- # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
- # some cases the only manufacturer, in others, it is the most popular.
- craynv-unknown)
- vendor=cray
- basic_os=${basic_os:-unicosmp}
- ;;
- c90-unknown | c90-cray)
- vendor=cray
- basic_os=${Basic_os:-unicos}
- ;;
- fx80-unknown)
- vendor=alliant
- ;;
- romp-unknown)
- vendor=ibm
- ;;
- mmix-unknown)
- vendor=knuth
- ;;
- microblaze-unknown | microblazeel-unknown)
- vendor=xilinx
- ;;
- rs6000-unknown)
- vendor=ibm
- ;;
- vax-unknown)
- vendor=dec
- ;;
- pdp11-unknown)
- vendor=dec
- ;;
- we32k-unknown)
- vendor=att
- ;;
- cydra-unknown)
- vendor=cydrome
- ;;
- i370-ibm*)
- vendor=ibm
- ;;
- orion-unknown)
- vendor=highlevel
- ;;
- xps-unknown | xps100-unknown)
- cpu=xps100
- vendor=honeywell
- ;;
-
- # Here we normalize CPU types with a missing or matching vendor
- dpx20-unknown | dpx20-bull)
- cpu=rs6000
- vendor=bull
- basic_os=${basic_os:-bosx}
- ;;
-
- # Here we normalize CPU types irrespective of the vendor
- amd64-*)
- cpu=x86_64
- ;;
- blackfin-*)
- cpu=bfin
- basic_os=linux
- ;;
- c54x-*)
- cpu=tic54x
- ;;
- c55x-*)
- cpu=tic55x
- ;;
- c6x-*)
- cpu=tic6x
- ;;
- e500v[12]-*)
- cpu=powerpc
- basic_os=${basic_os}"spe"
- ;;
- mips3*-*)
- cpu=mips64
- ;;
- ms1-*)
- cpu=mt
- ;;
- m68knommu-*)
- cpu=m68k
- basic_os=linux
- ;;
- m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
- cpu=s12z
- ;;
- openrisc-*)
- cpu=or32
- ;;
- parisc-*)
- cpu=hppa
- basic_os=linux
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- cpu=i586
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
- cpu=i686
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- cpu=i686
- ;;
- pentium4-*)
- cpu=i786
- ;;
- pc98-*)
- cpu=i386
- ;;
- ppc-* | ppcbe-*)
- cpu=powerpc
- ;;
- ppcle-* | powerpclittle-*)
- cpu=powerpcle
- ;;
- ppc64-*)
- cpu=powerpc64
- ;;
- ppc64le-* | powerpc64little-*)
- cpu=powerpc64le
- ;;
- sb1-*)
- cpu=mipsisa64sb1
- ;;
- sb1el-*)
- cpu=mipsisa64sb1el
- ;;
- sh5e[lb]-*)
- cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/')
- ;;
- spur-*)
- cpu=spur
- ;;
- strongarm-* | thumb-*)
- cpu=arm
- ;;
- tx39-*)
- cpu=mipstx39
- ;;
- tx39el-*)
- cpu=mipstx39el
- ;;
- x64-*)
- cpu=x86_64
- ;;
- xscale-* | xscalee[bl]-*)
- cpu=$(echo "$cpu" | sed 's/^xscale/arm/')
- ;;
- arm64-*)
- cpu=aarch64
- ;;
-
- # Recognize the canonical CPU Types that limit and/or modify the
- # company names they are paired with.
- cr16-*)
- basic_os=${basic_os:-elf}
- ;;
- crisv32-* | etraxfs*-*)
- cpu=crisv32
- vendor=axis
- ;;
- cris-* | etrax*-*)
- cpu=cris
- vendor=axis
- ;;
- crx-*)
- basic_os=${basic_os:-elf}
- ;;
- neo-tandem)
- cpu=neo
- vendor=tandem
- ;;
- nse-tandem)
- cpu=nse
- vendor=tandem
- ;;
- nsr-tandem)
- cpu=nsr
- vendor=tandem
- ;;
- nsv-tandem)
- cpu=nsv
- vendor=tandem
- ;;
- nsx-tandem)
- cpu=nsx
- vendor=tandem
- ;;
- mipsallegrexel-sony)
- cpu=mipsallegrexel
- vendor=sony
- ;;
- tile*-*)
- basic_os=${basic_os:-linux-gnu}
- ;;
-
- *)
- # Recognize the canonical CPU types that are allowed with any
- # company name.
- case $cpu in
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | abacus \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
- | alphapca5[67] | alpha64pca5[67] \
- | am33_2.0 \
- | amdgcn \
- | arc | arceb \
- | arm | arm[lb]e | arme[lb] | armv* \
- | avr | avr32 \
- | asmjs \
- | ba \
- | be32 | be64 \
- | bfin | bpf | bs2000 \
- | c[123]* | c30 | [cjt]90 | c4x \
- | c8051 | clipper | craynv | csky | cydra \
- | d10v | d30v | dlx | dsp16xx \
- | e2k | elxsi | epiphany \
- | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
- | h8300 | h8500 \
- | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i*86 | i860 | i960 | ia16 | ia64 \
- | ip2k | iq2000 \
- | k1om \
- | le32 | le64 \
- | lm32 \
- | loongarch32 | loongarch64 | loongarchx32 \
- | m32c | m32r | m32rle \
- | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
- | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
- | m88110 | m88k | maxq | mb | mcore | mep | metag \
- | microblaze | microblazeel \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64eb | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
- | mmix \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nfp \
- | nios | nios2 | nios2eb | nios2el \
- | none | np1 | ns16k | ns32k | nvptx \
- | open8 \
- | or1k* \
- | or32 \
- | orion \
- | picochip \
- | pdp10 | pdp11 | pj | pjl | pn | power \
- | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
- | pru \
- | pyramid \
- | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
- | rl78 | romp | rs6000 | rx \
- | s390 | s390x \
- | score \
- | sh | shl \
- | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
- | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
- | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
- | spu \
- | tahoe \
- | thumbv7* \
- | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
- | tron \
- | ubicom32 \
- | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
- | vax \
- | visium \
- | w65 \
- | wasm32 | wasm64 \
- | we32k \
- | x86 | x86_64 | xc16x | xgate | xps100 \
- | xstormy16 | xtensa* \
- | ymp \
- | z8k | z80)
- ;;
-
- *)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
- exit 1
- ;;
- esac
- ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $vendor in
- digital*)
- vendor=dec
- ;;
- commodore*)
- vendor=cbm
- ;;
- *)
- ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if test x$basic_os != x
-then
-
-# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
-# set os.
-case $basic_os in
- gnu/linux*)
- kernel=linux
- os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
- ;;
- os2-emx)
- kernel=os2
- os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
- ;;
- nto-qnx*)
- kernel=nto
- os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|')
- ;;
- *-*)
- # shellcheck disable=SC2162
- IFS="-" read kernel os <<EOF
-$basic_os
-EOF
- ;;
- # Default OS when just kernel was specified
- nto*)
- kernel=nto
- os=$(echo $basic_os | sed -e 's|nto|qnx|')
- ;;
- linux*)
- kernel=linux
- os=$(echo $basic_os | sed -e 's|linux|gnu|')
- ;;
- *)
- kernel=
- os=$basic_os
- ;;
-esac
-
-# Now, normalize the OS (knowing we just have one component, it's not a kernel,
-# etc.)
-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.
- auroraux)
- os=auroraux
- ;;
- bluegene*)
- os=cnk
- ;;
- solaris1 | solaris1.*)
- os=$(echo $os | sed -e 's|solaris1|sunos4|')
- ;;
- solaris)
- os=solaris2
- ;;
- unixware*)
- os=sysv4.2uw
- ;;
- # es1800 is here to avoid being matched by es* (a different OS)
- es1800*)
- os=ose
- ;;
- # Some version numbers need modification
- chorusos*)
- os=chorusos
- ;;
- isc)
- os=isc2.2
- ;;
- sco6)
- os=sco5v6
- ;;
- sco5)
- os=sco3.2v5
- ;;
- sco4)
- os=sco3.2v4
- ;;
- sco3.2.[4-9]*)
- os=$(echo $os | sed -e 's/sco3.2./sco3.2v/')
- ;;
- sco*v* | scout)
- # Don't match below
- ;;
- sco*)
- os=sco3.2v2
- ;;
- psos*)
- os=psos
- ;;
- qnx*)
- os=qnx
- ;;
- hiux*)
- os=hiuxwe2
- ;;
- lynx*178)
- os=lynxos178
- ;;
- lynx*5)
- os=lynxos5
- ;;
- lynxos*)
- # don't get caught up in next wildcard
- ;;
- lynx*)
- os=lynxos
- ;;
- mac[0-9]*)
- os=$(echo "$os" | sed -e 's|mac|macos|')
- ;;
- opened*)
- os=openedition
- ;;
- os400*)
- os=os400
- ;;
- sunos5*)
- os=$(echo "$os" | sed -e 's|sunos5|solaris2|')
- ;;
- sunos6*)
- os=$(echo "$os" | sed -e 's|sunos6|solaris3|')
- ;;
- wince*)
- os=wince
- ;;
- 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
- ;;
- # 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
- ;;
- ose*)
- os=ose
- ;;
- *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
- os=mint
- ;;
- dicos*)
- os=dicos
- ;;
- pikeos*)
- # Until real need of OS specific support for
- # particular features comes up, bare metal
- # configurations are quite functional.
- case $cpu in
- arm*)
- os=eabi
- ;;
- *)
- os=elf
- ;;
- esac
- ;;
- *)
- # No normalization, but not necessarily accepted, that comes below.
- ;;
-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.
-
-kernel=
-case $cpu-$vendor in
- score-*)
- os=elf
- ;;
- spu-*)
- os=elf
- ;;
- *-acorn)
- os=riscix1.2
- ;;
- arm*-rebel)
- kernel=linux
- os=gnu
- ;;
- arm*-semi)
- os=aout
- ;;
- c4x-* | tic4x-*)
- os=coff
- ;;
- c8051-*)
- os=elf
- ;;
- clipper-intergraph)
- os=clix
- ;;
- hexagon-*)
- os=elf
- ;;
- tic54x-*)
- os=coff
- ;;
- tic55x-*)
- os=coff
- ;;
- tic6x-*)
- 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
- ;;
- 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
- ;;
- pru-*)
- os=elf
- ;;
- *-be)
- os=beos
- ;;
- *-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
- ;;
- *-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
- ;;
- *-wrs)
- os=vxworks
- ;;
- *)
- os=none
- ;;
-esac
-
-fi
-
-# Now, validate our (potentially fixed-up) OS.
-case $os in
- # Sometimes we do "kernel-libc", so those need to count as OSes.
- musl* | newlib* | uclibc*)
- ;;
- # Likewise for "kernel-abi"
- eabi* | gnueabi*)
- ;;
- # VxWorks passes extra cpu info in the 4th filed.
- simlinux | simwindows | spe)
- ;;
- # Now accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST end in a * to match a version number.
- gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
- | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
- | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
- | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
- | hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* \
- | mpw* | magic* | mmixware* | mon960* | lnews* \
- | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
- | aos* | aros* | cloudabi* | sortix* | twizzler* \
- | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
- | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
- | mirbsd* | netbsd* | dicos* | openedition* | ose* \
- | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
- | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
- | udi* | lites* | ieee* | go32* | aux* | hcos* \
- | chorusrdb* | cegcc* | glidix* \
- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
- | midipix* | mingw32* | mingw64* | mint* \
- | uxpv* | beos* | mpeix* | udk* | moxiebox* \
- | interix* | uwin* | mks* | rhapsody* | darwin* \
- | openstep* | oskit* | conix* | pw32* | nonstopux* \
- | storm-chaos* | tops10* | tenex* | tops20* | its* \
- | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
- | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
- | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
- | skyos* | haiku* | rdos* | toppers* | drops* | es* \
- | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
- | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
- ;;
- # This one is extra strict with allowed versions
- sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- ;;
- none)
- ;;
- *)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
- exit 1
- ;;
-esac
-
-# As a final step for OS-related things, validate the OS-kernel combination
-# (given a valid OS), if there is a kernel.
-case $kernel-$os in
- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
- ;;
- uclinux-uclibc* )
- ;;
- -dietlibc* | -newlib* | -musl* | -uclibc* )
- # These are just libc implementations, not actual OSes, and thus
- # require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
- exit 1
- ;;
- kfreebsd*-gnu* | kopensolaris*-gnu*)
- ;;
- vxworks-simlinux | vxworks-simwindows | vxworks-spe)
- ;;
- nto-qnx*)
- ;;
- os2-emx)
- ;;
- *-eabi* | *-gnueabi*)
- ;;
- -*)
- # Blank kernel with real OS is always fine.
- ;;
- *-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
- exit 1
- ;;
-esac
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer. We pick the logical manufacturer.
-case $vendor in
- unknown)
- case $cpu-$os in
- *-riscix*)
- vendor=acorn
- ;;
- *-sunos*)
- vendor=sun
- ;;
- *-cnk* | *-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
- ;;
- *-clix*)
- vendor=intergraph
- ;;
- *-mvs* | *-opened*)
- vendor=ibm
- ;;
- *-os400*)
- vendor=ibm
- ;;
- s390-* | s390x-*)
- 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
- ;;
-esac
-
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
-exit
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/lib/wx/autoconf/install-sh b/lib/wx/autoconf/install-sh
deleted file mode 100755
index ec298b5374..0000000000
--- a/lib/wx/autoconf/install-sh
+++ /dev/null
@@ -1,541 +0,0 @@
-#!/bin/sh
-# install - install a program, script, or datafile
-
-scriptversion=2020-11-14.01; # UTC
-
-# 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.
-
-tab=' '
-nl='
-'
-IFS=" $tab$nl"
-
-# Set DOITPROG to "echo" to test this script.
-
-doit=${DOITPROG-}
-doit_exec=${doit:-exec}
-
-# 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_mkdir=
-
-# Desired mode of installed file.
-mode=0755
-
-# Create dirs (including intermediate dirs) using mode 755.
-# This is like GNU 'install' as of coreutils 8.32 (2020).
-mkdir_umask=22
-
-backupsuffix=
-chgrpcmd=
-chmodcmd=$chmodprog
-chowncmd=
-mvcmd=$mvprog
-rmcmd="$rmprog -f"
-stripcmd=
-
-src=
-dst=
-dir_arg=
-dst_arg=
-
-copy_on_change=false
-is_target_a_directory=possibly
-
-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 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.
- -p pass -p to $cpprog.
- -s $stripprog installed files.
- -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
- -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
-
-By default, rm is invoked with -f; when overridden with RMPROG,
-it's up to you to specify -f if you want it.
-
-If -S is not specified, no backups are attempted.
-
-Email bug reports to bug-automake@gnu.org.
-Automake home page: https://www.gnu.org/software/automake/
-"
-
-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
- *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
- echo "$0: invalid mode: $mode" >&2
- exit 1;;
- esac
- shift;;
-
- -o) chowncmd="$chownprog $2"
- shift;;
-
- -p) cpprog="$cpprog -p";;
-
- -s) stripcmd=$stripprog;;
-
- -S) backupsuffix="$2"
- shift;;
-
- -t)
- is_target_a_directory=always
- dst_arg=$2
- # Protect names problematic for 'test' and other utilities.
- case $dst_arg in
- -* | [=\(\)!]) dst_arg=./$dst_arg;;
- esac
- shift;;
-
- -T) is_target_a_directory=never;;
-
- --version) echo "$0 $scriptversion"; exit $?;;
-
- --) shift
- break;;
-
- -*) echo "$0: invalid option: $1" >&2
- exit 1;;
-
- *) break;;
- esac
- shift
-done
-
-# We allow the use of options -d and -T together, by making -d
-# take the precedence; this is for compatibility with GNU install.
-
-if test -n "$dir_arg"; then
- if test -n "$dst_arg"; then
- echo "$0: target directory not allowed when installing a directory." >&2
- exit 1
- fi
-fi
-
-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
- # Protect names problematic for 'test' and other utilities.
- case $dst_arg in
- -* | [=\(\)!]) dst_arg=./$dst_arg;;
- esac
- 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
- if test $# -gt 1 || test "$is_target_a_directory" = always; then
- if test ! -d "$dst_arg"; then
- echo "$0: $dst_arg: Is not a directory." >&2
- exit 1
- fi
- fi
-fi
-
-if test -z "$dir_arg"; then
- do_exit='(exit $ret); exit $ret'
- trap "ret=129; $do_exit" 1
- trap "ret=130; $do_exit" 2
- trap "ret=141; $do_exit" 13
- trap "ret=143; $do_exit" 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 problematic for 'test' and other utilities.
- case $src in
- -* | [=\(\)!]) src=./$src;;
- esac
-
- if test -n "$dir_arg"; then
- dst=$src
- dstdir=$dst
- test -d "$dstdir"
- dstdir_status=$?
- # Don't chown directories that already exist.
- if test $dstdir_status = 0; then
- chowncmd=""
- fi
- 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
-
- # If destination is a directory, append the input filename.
- if test -d "$dst"; then
- if test "$is_target_a_directory" = never; then
- echo "$0: $dst_arg: Is a directory" >&2
- exit 1
- fi
- dstdir=$dst
- dstbase=`basename "$src"`
- case $dst in
- */) dst=$dst$dstbase;;
- *) dst=$dst/$dstbase;;
- esac
- dstdir_status=0
- else
- dstdir=`dirname "$dst"`
- test -d "$dstdir"
- dstdir_status=$?
- fi
- fi
-
- case $dstdir in
- */) dstdirslash=$dstdir;;
- *) dstdirslash=$dstdir/;;
- esac
-
- obsolete_mkdir_used=false
-
- if test $dstdir_status != 0; then
- case $posix_mkdir in
- '')
- # 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
- # The $RANDOM variable is not portable (e.g., dash). Use it
- # here however when possible just to lower collision chance.
- tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
-
- trap '
- ret=$?
- rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
- exit $ret
- ' 0
-
- # Because "mkdir -p" follows existing symlinks and we likely work
- # directly in world-writeable /tmp, make sure that the '$tmpdir'
- # directory is successfully created first before we actually test
- # 'mkdir -p'.
- if (umask $mkdir_umask &&
- $mkdirprog $mkdir_mode "$tmpdir" &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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-writable bit of parent directory when it shouldn't.
- # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- test_tmpdir="$tmpdir/a"
- ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
- case $ls_ld_tmpdir in
- d????-?r-*) different_mode=700;;
- d????-?--*) different_mode=755;;
- *) false;;
- esac &&
- $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
- test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
- }
- }
- then posix_mkdir=:
- fi
- rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
- else
- # Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
- fi
- trap '' 0;;
- esac
-
- if
- $posix_mkdir && (
- umask $mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
- )
- then :
- else
-
- # 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
-
- oIFS=$IFS
- IFS=/
- set -f
- set fnord $dstdir
- shift
- set +f
- IFS=$oIFS
-
- prefixes=
-
- for d
- do
- test X"$d" = X && 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=${dstdirslash}_inst.$$_
- rmtmp=${dstdirslash}_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 &&
- { test -z "$stripcmd" || {
- # Create $dsttmp read-write so that cp doesn't create it read-only,
- # which would cause strip to fail.
- if test -z "$doit"; then
- : >"$dsttmp" # No need to fork-exec 'touch'.
- else
- $doit touch "$dsttmp"
- fi
- }
- } &&
- $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` &&
- set -f &&
- set X $old && old=:$2:$4:$5:$6 &&
- set X $new && new=:$2:$4:$5:$6 &&
- set +f &&
- test "$old" = "$new" &&
- $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
- then
- rm -f "$dsttmp"
- else
- # If $backupsuffix is set, and the file being installed
- # already exists, attempt a backup. Don't worry if it fails,
- # e.g., if mv doesn't support -f.
- if test -n "$backupsuffix" && test -f "$dst"; then
- $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
- fi
-
- # 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 "$dst" 2>/dev/null ||
- { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
- { $doit $rmcmd "$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 'before-save-hook 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC0"
-# time-stamp-end: "; # UTC"
-# End:
diff --git a/lib/wx/c_src/Makefile.in b/lib/wx/c_src/Makefile.in
index 8a638b740a..87fc0354b6 100644
--- a/lib/wx/c_src/Makefile.in
+++ b/lib/wx/c_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2021. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -97,25 +97,25 @@ RESCOMP = @WX_RESCOMP@
ifeq (@WX_HAVE_STATIC_LIBS@,true)
OPT_WX_LIBS = @WX_LIBS_STATIC@
-DEBUG_WX_LIBS = @DEBUG_WX_LIBS_STATIC@
+DEBUG_WX_LIBS = @DEBUG_WX_LIBS_STATIC@ @GLIB_LIBS@
else
-OPT_WX_LIBS = @WX_LIBS@
-DEBUG_WX_LIBS = @DEBUG_WX_LIBS@
+OPT_WX_LIBS = @WX_LIBS@ @GLIB_LIBS@
+DEBUG_WX_LIBS = @DEBUG_WX_LIBS@ @GLIB_LIBS@
endif
ifeq ($(TYPE),debug)
WX_CFLAGS = @DEBUG_WX_CFLAGS@
CFLAGS = @DEBUG_CFLAGS@
WX_CXX_FLAGS = @DEBUG_WX_CXXFLAGS@
-CXX_FLAGS = @DEBUG_CXXFLAGS@
-CXX_NO_OPT_FLAGS = @DEBUG_CXXFLAGS@
+CXX_FLAGS = @DEBUG_CXXFLAGS@ @GLIB_CFLAGS@
+CXX_NO_OPT_FLAGS = @DEBUG_CXXFLAGS@ @GLIB_CFLAGS@
WX_LIBS = $(DEBUG_WX_LIBS)
else
WX_CFLAGS = @WX_CFLAGS@
CFLAGS = @CFLAGS@
WX_CXX_FLAGS = @WX_CXXFLAGS@
-CXX_FLAGS = @CXXFLAGS@
-CXX_NO_OPT_FLAGS = @CXXNOOPTFLAGS@
+CXX_FLAGS = @CXXFLAGS@ @GLIB_CFLAGS@
+CXX_NO_OPT_FLAGS = @CXXNOOPTFLAGS@ @GLIB_CFLAGS@
WX_LIBS = $(OPT_WX_LIBS)
endif
@@ -130,8 +130,8 @@ CXX_O_NO_OPT = $(V_CXX) -c $(CXX_NO_OPT_FLAGS) $(WX_CXX_FLAGS) $(COMMON_CFLA
opt: $(TARGET_DIR)/wxe_driver$(SO_EXT) $(TARGET_DIR)/erl_gl$(SO_EXT) $(WEBVIEW_LOADER_DLL_DEST)
-debug:
- @${MAKE} TYPE=debug
+$(filter-out opt, $(TYPES)):
+ @${MAKE} TYPE=$@ opt
clean:
rm -f $(OBJECTS)
diff --git a/lib/wx/c_src/egl_impl.c b/lib/wx/c_src/egl_impl.c
index 2703f55408..7fe58a040d 100644
--- a/lib/wx/c_src/egl_impl.c
+++ b/lib/wx/c_src/egl_impl.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2011-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2011-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -279,7 +279,7 @@ int egl_load_functions() {
}
/* *******************************************************************************
- * GLU Tesselation special
+ * GLU Tessellation special
* ******************************************************************************/
static GLUtesselator* tess;
@@ -355,7 +355,7 @@ egl_ogla_error(GLenum errorCode)
{
// const GLubyte *err;
// err = gluErrorString(errorCode);
- // fprintf(stderr, "Tesselation error: %d: %s\r\n", (int) errorCode, err);
+ // fprintf(stderr, "Tessellation error: %d: %s\r\n", (int) errorCode, err);
}
void init_tess()
diff --git a/lib/wx/c_src/egl_impl.h b/lib/wx/c_src/egl_impl.h
index 21bcf69644..5a7c76b289 100644
--- a/lib/wx/c_src/egl_impl.h
+++ b/lib/wx/c_src/egl_impl.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,10 +29,10 @@
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
-#elif defined(HAVE_GL_GL_H)
+#elif defined(HAVE_GL_GL_H) && defined(HAVE_GL_GLU_H)
#include <GL/gl.h>
# include <GL/glu.h>
-#elif defined(HAVE_OPENGL_GL_H)
+#elif defined(HAVE_OPENGL_GL_H) && defined(HAVE_OPENGL_GLU_H)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#endif
diff --git a/lib/wx/c_src/gen/wxe_func_table.cpp b/lib/wx/c_src/gen/wxe_func_table.cpp
index 6538bf4f2a..3a1d343c53 100644
--- a/lib/wx/c_src/gen/wxe_func_table.cpp
+++ b/lib/wx/c_src/gen/wxe_func_table.cpp
@@ -964,6 +964,12 @@ extern void wxMenuBar_GetAutoWindowMenu(WxeApp *app, wxeMemEnv *memenv, wxeComma
#if defined(__WXMAC__)
extern void wxMenuBar_OSXGetAppleMenu(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
#endif // defined(__WXMAC__)
+#if defined(__WXMAC__)
+extern void wxMenuBar_MacGetCommonMenuBar(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+#endif // defined(__WXMAC__)
+#if defined(__WXMAC__)
+extern void wxMenuBar_MacSetCommonMenuBar(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+#endif // defined(__WXMAC__)
extern void wxMenuBar_IsEnabled(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxMenuBar_Remove(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxMenuBar_Replace(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
@@ -2983,6 +2989,12 @@ extern void wxMouseEvent_RightIsDown(WxeApp *app, wxeMemEnv *memenv, wxeCommand&
extern void wxMouseEvent_RightUp(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxMouseEvent_ShiftDown(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxMouseEvent_GetWheelAxis(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+extern void wxMouseEvent_Aux1DClick(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+extern void wxMouseEvent_Aux1Down(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+extern void wxMouseEvent_Aux1Up(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+extern void wxMouseEvent_Aux2DClick(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+extern void wxMouseEvent_Aux2Down(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
+extern void wxMouseEvent_Aux2Up(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxSetCursorEvent_GetCursor(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxSetCursorEvent_GetX(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
extern void wxSetCursorEvent_GetY(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd);
@@ -5362,3714 +5374,3730 @@ wxe_fns_t wxe_fns[] =
#else
{NULL, "wxMenuBar", "oSXGetAppleMenu", 0}, // 873
#endif // defined(__WXMAC__)
- {wxMenuBar_IsEnabled, "wxMenuBar", "isEnabled", 2}, // 874
- {wxMenuBar_Remove, "wxMenuBar", "remove", 2}, // 875
- {wxMenuBar_Replace, "wxMenuBar", "replace", 4}, // 876
- {wxMenuBar_SetHelpString, "wxMenuBar", "setHelpString", 3}, // 877
- {wxMenuBar_SetLabel, "wxMenuBar", "setLabel", 3}, // 878
- {wxMenuBar_SetMenuLabel, "wxMenuBar", "setMenuLabel", 3}, // 879
- {wxControl_GetLabel, "wxControl", "getLabel", 1}, // 880
- {wxControl_SetLabel, "wxControl", "setLabel", 2}, // 881
- {wxControlWithItems_Append_1, "wxControlWithItems", "append", 2}, // 882
- {wxControlWithItems_Append_2, "wxControlWithItems", "append", 3}, // 883
- {wxControlWithItems_appendStrings_1, "wxControlWithItems", "appendStrings", 2}, // 884
- {wxControlWithItems_appendStrings_2, "wxControlWithItems", "appendStrings", 3}, // 885
- {wxControlWithItems_Clear, "wxControlWithItems", "clear", 1}, // 886
- {wxControlWithItems_Delete, "wxControlWithItems", "delete", 2}, // 887
- {wxControlWithItems_FindString, "wxControlWithItems", "findString", 3}, // 888
- {wxControlWithItems_getClientData, "wxControlWithItems", "getClientData", 2}, // 889
- {wxControlWithItems_setClientData, "wxControlWithItems", "setClientData", 3}, // 890
- {wxControlWithItems_GetCount, "wxControlWithItems", "getCount", 1}, // 891
- {wxControlWithItems_GetSelection, "wxControlWithItems", "getSelection", 1}, // 892
- {wxControlWithItems_GetString, "wxControlWithItems", "getString", 2}, // 893
- {wxControlWithItems_GetStringSelection, "wxControlWithItems", "getStringSelection", 1}, // 894
- {wxControlWithItems_Insert_2, "wxControlWithItems", "insert", 3}, // 895
- {wxControlWithItems_Insert_3, "wxControlWithItems", "insert", 4}, // 896
- {wxControlWithItems_insertStrings_2, "wxControlWithItems", "insertStrings", 3}, // 897
- {wxControlWithItems_insertStrings_3, "wxControlWithItems", "insertStrings", 4}, // 898
- {wxControlWithItems_IsEmpty, "wxControlWithItems", "isEmpty", 1}, // 899
- {wxControlWithItems_Select, "wxControlWithItems", "select", 2}, // 900
- {wxControlWithItems_SetSelection, "wxControlWithItems", "setSelection", 2}, // 901
- {wxControlWithItems_SetString, "wxControlWithItems", "setString", 3}, // 902
- {wxControlWithItems_SetStringSelection, "wxControlWithItems", "setStringSelection", 2}, // 903
- {wxMenu_new_0, "wxMenu", "new", 0}, // 904
- {wxMenu_new_1, "wxMenu", "new", 1}, // 905
- {wxMenu_new_2, "wxMenu", "new", 2}, // 906
- {NULL, "wxMenu", "destroy", 1}, // 907 obj destructor wxMenu_destruct
- {wxMenu_Append_3, "wxMenu", "append", 4}, // 908
- {wxMenu_Append_4, "wxMenu", "append", 5}, // 909
- {wxMenu_Append_1, "wxMenu", "append", 2}, // 910
- {wxMenu_AppendCheckItem, "wxMenu", "appendCheckItem", 4}, // 911
- {wxMenu_AppendRadioItem, "wxMenu", "appendRadioItem", 4}, // 912
- {wxMenu_AppendSeparator, "wxMenu", "appendSeparator", 1}, // 913
- {wxMenu_Break, "wxMenu", "break", 1}, // 914
- {wxMenu_Check, "wxMenu", "check", 3}, // 915
- {wxMenu_Delete_1_0, "wxMenu", "delete", 2}, // 916
- {wxMenu_Delete_1_1, "wxMenu", "delete", 2}, // 917
- {wxMenu_Destroy_1_0, "wxMenu", "'Destroy'", 2}, // 918
- {wxMenu_Destroy_1_1, "wxMenu", "'Destroy'", 2}, // 919
- {wxMenu_Enable, "wxMenu", "enable", 3}, // 920
- {wxMenu_FindItem_1, "wxMenu", "findItem", 2}, // 921
- {wxMenu_FindItem_2, "wxMenu", "findItem", 2}, // 922
- {wxMenu_FindItemByPosition, "wxMenu", "findItemByPosition", 2}, // 923
- {wxMenu_GetHelpString, "wxMenu", "getHelpString", 2}, // 924
- {wxMenu_GetLabel, "wxMenu", "getLabel", 2}, // 925
- {wxMenu_GetMenuItemCount, "wxMenu", "getMenuItemCount", 1}, // 926
- {NULL, "", "", 0}, // 927
- {wxMenu_GetMenuItems, "wxMenu", "getMenuItems", 1}, // 928
- {wxMenu_GetTitle, "wxMenu", "getTitle", 1}, // 929
- {wxMenu_Insert_2, "wxMenu", "insert", 3}, // 930
- {wxMenu_Insert_3, "wxMenu", "insert", 4}, // 931
- {wxMenu_Insert_5, "wxMenu", "insert", 6}, // 932
- {wxMenu_InsertCheckItem, "wxMenu", "insertCheckItem", 5}, // 933
- {wxMenu_InsertRadioItem, "wxMenu", "insertRadioItem", 5}, // 934
- {wxMenu_InsertSeparator, "wxMenu", "insertSeparator", 2}, // 935
- {wxMenu_IsChecked, "wxMenu", "isChecked", 2}, // 936
- {wxMenu_IsEnabled, "wxMenu", "isEnabled", 2}, // 937
- {wxMenu_Prepend_1, "wxMenu", "prepend", 2}, // 938
- {wxMenu_Prepend_2, "wxMenu", "prepend", 3}, // 939
- {wxMenu_Prepend_4, "wxMenu", "prepend", 5}, // 940
- {wxMenu_PrependCheckItem, "wxMenu", "prependCheckItem", 4}, // 941
- {wxMenu_PrependRadioItem, "wxMenu", "prependRadioItem", 4}, // 942
- {wxMenu_PrependSeparator, "wxMenu", "prependSeparator", 1}, // 943
- {wxMenu_Remove_1_0, "wxMenu", "remove", 2}, // 944
- {wxMenu_Remove_1_1, "wxMenu", "remove", 2}, // 945
- {wxMenu_SetHelpString, "wxMenu", "setHelpString", 3}, // 946
- {wxMenu_SetLabel, "wxMenu", "setLabel", 3}, // 947
- {wxMenu_SetTitle, "wxMenu", "setTitle", 2}, // 948
- {wxMenuItem_new, "wxMenuItem", "new", 1}, // 949
- {NULL, "wxMenuItem", "destroy", 1}, // 950 obj destructor wxMenuItem_destruct
- {wxMenuItem_Check, "wxMenuItem", "check", 2}, // 951
- {wxMenuItem_Enable, "wxMenuItem", "enable", 2}, // 952
- {wxMenuItem_GetBitmap, "wxMenuItem", "getBitmap", 1}, // 953
- {wxMenuItem_GetHelp, "wxMenuItem", "getHelp", 1}, // 954
- {wxMenuItem_GetId, "wxMenuItem", "getId", 1}, // 955
- {wxMenuItem_GetKind, "wxMenuItem", "getKind", 1}, // 956
- {wxMenuItem_GetLabelText, "wxMenuItem", "getLabelText", 1}, // 957
- {wxMenuItem_GetItemLabel, "wxMenuItem", "getItemLabel", 1}, // 958
- {wxMenuItem_GetItemLabelText, "wxMenuItem", "getItemLabelText", 1}, // 959
- {wxMenuItem_GetMenu, "wxMenuItem", "getMenu", 1}, // 960
- {wxMenuItem_GetSubMenu, "wxMenuItem", "getSubMenu", 1}, // 961
- {wxMenuItem_IsCheckable, "wxMenuItem", "isCheckable", 1}, // 962
- {wxMenuItem_IsChecked, "wxMenuItem", "isChecked", 1}, // 963
- {wxMenuItem_IsEnabled, "wxMenuItem", "isEnabled", 1}, // 964
- {wxMenuItem_IsSeparator, "wxMenuItem", "isSeparator", 1}, // 965
- {wxMenuItem_IsSubMenu, "wxMenuItem", "isSubMenu", 1}, // 966
- {wxMenuItem_SetBitmap, "wxMenuItem", "setBitmap", 2}, // 967
- {wxMenuItem_SetHelp, "wxMenuItem", "setHelp", 2}, // 968
- {wxMenuItem_SetMenu, "wxMenuItem", "setMenu", 2}, // 969
- {wxMenuItem_SetSubMenu, "wxMenuItem", "setSubMenu", 2}, // 970
- {wxMenuItem_SetItemLabel, "wxMenuItem", "setItemLabel", 2}, // 971
- {wxToolBar_AddControl, "wxToolBar", "addControl", 3}, // 972
- {wxToolBar_AddSeparator, "wxToolBar", "addSeparator", 1}, // 973
- {wxToolBar_AddTool_1, "wxToolBar", "addTool", 2}, // 974
- {wxToolBar_AddTool_4, "wxToolBar", "addTool", 5}, // 975
- {wxToolBar_AddTool_5, "wxToolBar", "addTool", 6}, // 976
- {wxToolBar_AddCheckTool, "wxToolBar", "addCheckTool", 5}, // 977
- {wxToolBar_AddRadioTool, "wxToolBar", "addRadioTool", 5}, // 978
- {wxToolBar_AddStretchableSpace, "wxToolBar", "addStretchableSpace", 1}, // 979
- {wxToolBar_InsertStretchableSpace, "wxToolBar", "insertStretchableSpace", 2}, // 980
- {wxToolBar_DeleteTool, "wxToolBar", "deleteTool", 2}, // 981
- {wxToolBar_DeleteToolByPos, "wxToolBar", "deleteToolByPos", 2}, // 982
- {wxToolBar_EnableTool, "wxToolBar", "enableTool", 3}, // 983
- {wxToolBar_FindById, "wxToolBar", "findById", 2}, // 984
- {wxToolBar_FindControl, "wxToolBar", "findControl", 2}, // 985
- {wxToolBar_FindToolForPosition, "wxToolBar", "findToolForPosition", 3}, // 986
- {wxToolBar_GetToolSize, "wxToolBar", "getToolSize", 1}, // 987
- {wxToolBar_GetToolBitmapSize, "wxToolBar", "getToolBitmapSize", 1}, // 988
- {wxToolBar_GetMargins, "wxToolBar", "getMargins", 1}, // 989
- {wxToolBar_GetToolEnabled, "wxToolBar", "getToolEnabled", 2}, // 990
- {wxToolBar_GetToolLongHelp, "wxToolBar", "getToolLongHelp", 2}, // 991
- {wxToolBar_GetToolPacking, "wxToolBar", "getToolPacking", 1}, // 992
- {wxToolBar_GetToolPos, "wxToolBar", "getToolPos", 2}, // 993
- {wxToolBar_GetToolSeparation, "wxToolBar", "getToolSeparation", 1}, // 994
- {wxToolBar_GetToolShortHelp, "wxToolBar", "getToolShortHelp", 2}, // 995
- {wxToolBar_GetToolState, "wxToolBar", "getToolState", 2}, // 996
- {wxToolBar_InsertControl, "wxToolBar", "insertControl", 4}, // 997
- {wxToolBar_InsertSeparator, "wxToolBar", "insertSeparator", 2}, // 998
- {wxToolBar_InsertTool_5, "wxToolBar", "insertTool", 6}, // 999
- {wxToolBar_InsertTool_2, "wxToolBar", "insertTool", 3}, // 1000
- {wxToolBar_Realize, "wxToolBar", "realize", 1}, // 1001
- {wxToolBar_RemoveTool, "wxToolBar", "removeTool", 2}, // 1002
- {wxToolBar_SetMargins, "wxToolBar", "setMargins", 3}, // 1003
- {wxToolBar_SetToolBitmapSize, "wxToolBar", "setToolBitmapSize", 2}, // 1004
- {wxToolBar_SetToolLongHelp, "wxToolBar", "setToolLongHelp", 3}, // 1005
- {wxToolBar_SetToolPacking, "wxToolBar", "setToolPacking", 2}, // 1006
- {wxToolBar_SetToolShortHelp, "wxToolBar", "setToolShortHelp", 3}, // 1007
- {wxToolBar_SetToolSeparation, "wxToolBar", "setToolSeparation", 2}, // 1008
- {wxToolBar_ToggleTool, "wxToolBar", "toggleTool", 3}, // 1009
- {wxStatusBar_new_0, "wxStatusBar", "new", 0}, // 1010
- {wxStatusBar_new_2, "wxStatusBar", "new", 2}, // 1011
- {NULL, "wxStatusBar", "destroy", 1}, // 1012 obj destructor wxStatusBar_destruct
- {wxStatusBar_Create, "wxStatusBar", "create", 3}, // 1013
- {wxStatusBar_GetFieldRect, "wxStatusBar", "getFieldRect", 2}, // 1014
- {wxStatusBar_GetFieldsCount, "wxStatusBar", "getFieldsCount", 1}, // 1015
- {wxStatusBar_GetStatusText, "wxStatusBar", "getStatusText", 2}, // 1016
- {wxStatusBar_PopStatusText, "wxStatusBar", "popStatusText", 2}, // 1017
- {wxStatusBar_PushStatusText, "wxStatusBar", "pushStatusText", 3}, // 1018
- {wxStatusBar_SetFieldsCount, "wxStatusBar", "setFieldsCount", 3}, // 1019
- {wxStatusBar_SetMinHeight, "wxStatusBar", "setMinHeight", 2}, // 1020
- {wxStatusBar_SetStatusText, "wxStatusBar", "setStatusText", 3}, // 1021
- {wxStatusBar_SetStatusWidths, "wxStatusBar", "setStatusWidths", 2}, // 1022
- {wxStatusBar_SetStatusStyles, "wxStatusBar", "setStatusStyles", 2}, // 1023
- {wxBitmap_new_0, "wxBitmap", "new", 0}, // 1024
- {NULL, "", "", 0}, // 1025
- {wxBitmap_new_4, "wxBitmap", "new", 4}, // 1026
- {wxBitmap_new_3, "wxBitmap", "new", 3}, // 1027
- {wxBitmap_new_2_1, "wxBitmap", "new", 2}, // 1028
- {wxBitmap_new_2_0, "wxBitmap", "new", 2}, // 1029
- {wxBitmap_new_2_2, "wxBitmap", "new", 2}, // 1030
- {wxBitmap_new_2_3, "wxBitmap", "new", 1}, // 1031
- {NULL, "wxBitmap", "destroy", 1}, // 1032 obj destructor wxBitmap_destruct
- {wxBitmap_ConvertToImage, "wxBitmap", "convertToImage", 1}, // 1033
- {wxBitmap_CopyFromIcon, "wxBitmap", "copyFromIcon", 2}, // 1034
- {wxBitmap_Create_3_0, "wxBitmap", "create", 4}, // 1035
- {wxBitmap_Create_2, "wxBitmap", "create", 3}, // 1036
- {wxBitmap_Create_3_1, "wxBitmap", "create", 4}, // 1037
- {wxBitmap_GetDepth, "wxBitmap", "getDepth", 1}, // 1038
- {wxBitmap_GetHeight, "wxBitmap", "getHeight", 1}, // 1039
- {wxBitmap_GetPalette, "wxBitmap", "getPalette", 1}, // 1040
- {wxBitmap_GetMask, "wxBitmap", "getMask", 1}, // 1041
- {wxBitmap_GetWidth, "wxBitmap", "getWidth", 1}, // 1042
- {wxBitmap_GetSubBitmap, "wxBitmap", "getSubBitmap", 2}, // 1043
- {wxBitmap_LoadFile, "wxBitmap", "loadFile", 3}, // 1044
- {wxBitmap_IsOk, "wxBitmap", "isOk", 1}, // 1045
- {wxBitmap_SaveFile, "wxBitmap", "saveFile", 4}, // 1046
- {wxBitmap_SetDepth, "wxBitmap", "setDepth", 2}, // 1047
- {wxBitmap_SetHeight, "wxBitmap", "setHeight", 2}, // 1048
- {wxBitmap_SetMask, "wxBitmap", "setMask", 2}, // 1049
- {wxBitmap_SetPalette, "wxBitmap", "setPalette", 2}, // 1050
- {wxBitmap_SetWidth, "wxBitmap", "setWidth", 2}, // 1051
- {wxIcon_new_0, "wxIcon", "new", 0}, // 1052
- {wxIcon_new_1, "wxIcon", "new", 1}, // 1053
- {wxIcon_new_2, "wxIcon", "new", 2}, // 1054
- {wxIcon_CopyFromBitmap, "wxIcon", "copyFromBitmap", 2}, // 1055
- {NULL, "wxIcon", "destroy", 1}, // 1056 obj destructor wxIcon_destruct
- {wxIconBundle_new_0, "wxIconBundle", "new", 0}, // 1057
- {wxIconBundle_new_1_1, "wxIconBundle", "new", 1}, // 1058
- {wxIconBundle_new_2, "wxIconBundle", "new", 2}, // 1059
- {NULL, "", "", 0}, // 1060
- {wxIconBundle_new_1_0, "wxIconBundle", "new", 1}, // 1061
- {wxIconBundle_destruct, "wxIconBundle", "destroy", 1}, // 1062
- {wxIconBundle_AddIcon_1_0, "wxIconBundle", "addIcon", 2}, // 1063
- {wxIconBundle_AddIcon_2, "wxIconBundle", "addIcon", 3}, // 1064
- {wxIconBundle_AddIcon_1_1, "wxIconBundle", "addIcon", 2}, // 1065
- {wxIconBundle_GetIcon_2, "wxIconBundle", "getIcon", 3}, // 1066
- {wxIconBundle_GetIcon_1, "wxIconBundle", "getIcon", 2}, // 1067
- {wxCursor_new_0, "wxCursor", "new", 0}, // 1068
- {wxCursor_new_2, "wxCursor", "new", 2}, // 1069
- {wxCursor_new_1_1, "wxCursor", "new", 1}, // 1070
- {wxCursor_new_1_0, "wxCursor", "new", 1}, // 1071
- {NULL, "", "", 0}, // 1072
- {NULL, "wxCursor", "destroy", 1}, // 1073 obj destructor wxCursor_destruct
- {wxCursor_IsOk, "wxCursor", "isOk", 1}, // 1074
- {wxMask_new_0, "wxMask", "new", 0}, // 1075
- {wxMask_new_2_0, "wxMask", "new", 2}, // 1076
- {wxMask_new_1, "wxMask", "new", 1}, // 1077
- {wxMask_new_2_1, "wxMask", "new", 2}, // 1078
- {NULL, "wxMask", "destroy", 1}, // 1079 obj destructor wxMask_destruct
- {wxMask_Create_2_0, "wxMask", "create", 3}, // 1080
- {wxMask_Create_1, "wxMask", "create", 2}, // 1081
- {wxMask_Create_2_1, "wxMask", "create", 3}, // 1082
- {wxImage_new_0, "wxImage", "new", 0}, // 1083
- {wxImage_new_3_1, "wxImage", "new", 3}, // 1084
- {wxImage_new_2_2, "wxImage", "new", 2}, // 1085
- {wxImage_new_3_0, "wxImage", "new", 3}, // 1086
- {wxImage_new_2_1, "wxImage", "new", 2}, // 1087
- {wxImage_new_4, "wxImage", "new", 4}, // 1088
- {wxImage_new_3_3, "wxImage", "new", 3}, // 1089
- {wxImage_new_2_0, "wxImage", "new", 2}, // 1090
- {wxImage_new_3_2, "wxImage", "new", 3}, // 1091
- {NULL, "wxImage", "destroy", 1}, // 1092 obj destructor wxImage_destruct
- {wxImage_Blur, "wxImage", "blur", 2}, // 1093
- {wxImage_BlurHorizontal, "wxImage", "blurHorizontal", 2}, // 1094
- {wxImage_BlurVertical, "wxImage", "blurVertical", 2}, // 1095
- {wxImage_ConvertAlphaToMask_1, "wxImage", "convertAlphaToMask", 2}, // 1096
- {wxImage_ConvertAlphaToMask_4, "wxImage", "convertAlphaToMask", 5}, // 1097
- {wxImage_ConvertToGreyscale_3, "wxImage", "convertToGreyscale", 4}, // 1098
- {wxImage_ConvertToGreyscale_0, "wxImage", "convertToGreyscale", 1}, // 1099
- {wxImage_ConvertToMono, "wxImage", "convertToMono", 4}, // 1100
- {wxImage_Copy, "wxImage", "copy", 1}, // 1101
- {wxImage_Create_3_1, "wxImage", "create", 4}, // 1102
- {wxImage_Create_2_1, "wxImage", "create", 3}, // 1103
- {wxImage_Create_3_0, "wxImage", "create", 4}, // 1104
- {wxImage_Create_2_0, "wxImage", "create", 3}, // 1105
- {wxImage_Create_4, "wxImage", "create", 5}, // 1106
- {wxImage_Create_3_2, "wxImage", "create", 4}, // 1107
- {wxImage_Destroy, "wxImage", "'Destroy'", 1}, // 1108
- {wxImage_FindFirstUnusedColour, "wxImage", "findFirstUnusedColour", 2}, // 1109
- {wxImage_GetImageExtWildcard, "wxImage", "getImageExtWildcard", 0}, // 1110
- {wxImage_GetAlpha_0, "wxImage", "getAlpha", 1}, // 1111
- {wxImage_GetAlpha_2, "wxImage", "getAlpha", 3}, // 1112
- {wxImage_GetBlue, "wxImage", "getBlue", 3}, // 1113
- {wxImage_GetData, "wxImage", "getData", 1}, // 1114
- {wxImage_GetGreen, "wxImage", "getGreen", 3}, // 1115
- {wxImage_GetImageCount, "wxImage", "getImageCount", 2}, // 1116
- {wxImage_GetHeight, "wxImage", "getHeight", 1}, // 1117
- {wxImage_GetMaskBlue, "wxImage", "getMaskBlue", 1}, // 1118
- {wxImage_GetMaskGreen, "wxImage", "getMaskGreen", 1}, // 1119
- {wxImage_GetMaskRed, "wxImage", "getMaskRed", 1}, // 1120
- {wxImage_GetOrFindMaskColour, "wxImage", "getOrFindMaskColour", 1}, // 1121
- {wxImage_GetPalette, "wxImage", "getPalette", 1}, // 1122
- {wxImage_GetRed, "wxImage", "getRed", 3}, // 1123
- {wxImage_GetSubImage, "wxImage", "getSubImage", 2}, // 1124
- {wxImage_GetWidth, "wxImage", "getWidth", 1}, // 1125
- {wxImage_HasAlpha, "wxImage", "hasAlpha", 1}, // 1126
- {wxImage_HasMask, "wxImage", "hasMask", 1}, // 1127
- {wxImage_GetOption, "wxImage", "getOption", 2}, // 1128
- {wxImage_GetOptionInt, "wxImage", "getOptionInt", 2}, // 1129
- {wxImage_HasOption, "wxImage", "hasOption", 2}, // 1130
- {wxImage_InitAlpha, "wxImage", "initAlpha", 1}, // 1131
- {wxImage_InitStandardHandlers, "wxImage", "initStandardHandlers", 0}, // 1132
- {wxImage_IsTransparent, "wxImage", "isTransparent", 4}, // 1133
- {wxImage_LoadFile_2, "wxImage", "loadFile", 3}, // 1134
- {wxImage_LoadFile_3, "wxImage", "loadFile", 4}, // 1135
- {wxImage_IsOk, "wxImage", "isOk", 1}, // 1136
- {wxImage_RemoveHandler, "wxImage", "removeHandler", 1}, // 1137
- {wxImage_Mirror, "wxImage", "mirror", 2}, // 1138
- {wxImage_Replace, "wxImage", "replace", 7}, // 1139
- {wxImage_Rescale, "wxImage", "rescale", 4}, // 1140
- {wxImage_Resize, "wxImage", "resize", 4}, // 1141
- {wxImage_Rotate, "wxImage", "rotate", 4}, // 1142
- {wxImage_RotateHue, "wxImage", "rotateHue", 2}, // 1143
- {wxImage_Rotate90, "wxImage", "rotate90", 2}, // 1144
- {wxImage_SaveFile_2_0, "wxImage", "saveFile", 3}, // 1145
- {wxImage_SaveFile_2_1, "wxImage", "saveFile", 3}, // 1146
- {wxImage_SaveFile_1, "wxImage", "saveFile", 2}, // 1147
- {wxImage_Scale, "wxImage", "scale", 4}, // 1148
- {wxImage_Size, "wxImage", "size", 4}, // 1149
- {wxImage_SetAlpha_1, "wxImage", "setAlpha", 2}, // 1150
- {wxImage_SetAlpha_3, "wxImage", "setAlpha", 4}, // 1151
- {wxImage_SetData_1, "wxImage", "setData", 2}, // 1152
- {wxImage_SetData_3, "wxImage", "setData", 4}, // 1153
- {wxImage_SetMask, "wxImage", "setMask", 2}, // 1154
- {wxImage_SetMaskColour, "wxImage", "setMaskColour", 4}, // 1155
- {wxImage_SetMaskFromImage, "wxImage", "setMaskFromImage", 5}, // 1156
- {wxImage_SetOption_2_1, "wxImage", "setOption", 3}, // 1157
- {wxImage_SetOption_2_0, "wxImage", "setOption", 3}, // 1158
- {wxImage_SetPalette, "wxImage", "setPalette", 2}, // 1159
- {wxImage_SetRGB_5, "wxImage", "setRGB", 6}, // 1160
- {wxImage_SetRGB_4, "wxImage", "setRGB", 5}, // 1161
- {wxBrush_new_0, "wxBrush", "new", 0}, // 1162
- {wxBrush_new_2, "wxBrush", "new", 2}, // 1163
- {NULL, "", "", 0}, // 1164
- {wxBrush_new_1, "wxBrush", "new", 1}, // 1165
- {NULL, "wxBrush", "destroy", 1}, // 1166 obj destructor wxBrush_destruct
- {wxBrush_GetColour, "wxBrush", "getColour", 1}, // 1167
- {wxBrush_GetStipple, "wxBrush", "getStipple", 1}, // 1168
- {wxBrush_GetStyle, "wxBrush", "getStyle", 1}, // 1169
- {wxBrush_IsHatch, "wxBrush", "isHatch", 1}, // 1170
- {wxBrush_IsOk, "wxBrush", "isOk", 1}, // 1171
- {wxBrush_SetColour_1, "wxBrush", "setColour", 2}, // 1172
- {wxBrush_SetColour_3, "wxBrush", "setColour", 4}, // 1173
- {wxBrush_SetStipple, "wxBrush", "setStipple", 2}, // 1174
- {wxBrush_SetStyle, "wxBrush", "setStyle", 2}, // 1175
- {wxPen_new_0, "wxPen", "new", 0}, // 1176
- {wxPen_new_2, "wxPen", "new", 2}, // 1177
- {wxPen_new_1, "wxPen", "new", 1}, // 1178
- {NULL, "wxPen", "destroy", 1}, // 1179 obj destructor wxPen_destruct
- {wxPen_GetCap, "wxPen", "getCap", 1}, // 1180
- {wxPen_GetColour, "wxPen", "getColour", 1}, // 1181
- {wxPen_GetJoin, "wxPen", "getJoin", 1}, // 1182
- {wxPen_GetStyle, "wxPen", "getStyle", 1}, // 1183
- {wxPen_GetWidth, "wxPen", "getWidth", 1}, // 1184
- {wxPen_IsOk, "wxPen", "isOk", 1}, // 1185
- {wxPen_SetCap, "wxPen", "setCap", 2}, // 1186
- {wxPen_SetColour_1, "wxPen", "setColour", 2}, // 1187
- {wxPen_SetColour_3, "wxPen", "setColour", 4}, // 1188
- {wxPen_SetJoin, "wxPen", "setJoin", 2}, // 1189
- {wxPen_SetStyle, "wxPen", "setStyle", 2}, // 1190
- {wxPen_SetWidth, "wxPen", "setWidth", 2}, // 1191
- {wxRegion_new_0, "wxRegion", "new", 0}, // 1192
- {wxRegion_new_4, "wxRegion", "new", 4}, // 1193
- {wxRegion_new_2, "wxRegion", "new", 2}, // 1194
- {wxRegion_new_1_0, "wxRegion", "new", 1}, // 1195
- {NULL, "", "", 0}, // 1196
- {wxRegion_new_1_1, "wxRegion", "new", 1}, // 1197
+#if defined(__WXMAC__)
+ {wxMenuBar_MacGetCommonMenuBar, "wxMenuBar", "macGetCommonMenuBar", 0}, // 874
+#else
+ {NULL, "wxMenuBar", "macGetCommonMenuBar", 0}, // 874
+#endif // defined(__WXMAC__)
+#if defined(__WXMAC__)
+ {wxMenuBar_MacSetCommonMenuBar, "wxMenuBar", "macSetCommonMenuBar", 1}, // 875
+#else
+ {NULL, "wxMenuBar", "macSetCommonMenuBar", 0}, // 875
+#endif // defined(__WXMAC__)
+ {wxMenuBar_IsEnabled, "wxMenuBar", "isEnabled", 2}, // 876
+ {wxMenuBar_Remove, "wxMenuBar", "remove", 2}, // 877
+ {wxMenuBar_Replace, "wxMenuBar", "replace", 4}, // 878
+ {wxMenuBar_SetHelpString, "wxMenuBar", "setHelpString", 3}, // 879
+ {wxMenuBar_SetLabel, "wxMenuBar", "setLabel", 3}, // 880
+ {wxMenuBar_SetMenuLabel, "wxMenuBar", "setMenuLabel", 3}, // 881
+ {wxControl_GetLabel, "wxControl", "getLabel", 1}, // 882
+ {wxControl_SetLabel, "wxControl", "setLabel", 2}, // 883
+ {wxControlWithItems_Append_1, "wxControlWithItems", "append", 2}, // 884
+ {wxControlWithItems_Append_2, "wxControlWithItems", "append", 3}, // 885
+ {wxControlWithItems_appendStrings_1, "wxControlWithItems", "appendStrings", 2}, // 886
+ {wxControlWithItems_appendStrings_2, "wxControlWithItems", "appendStrings", 3}, // 887
+ {wxControlWithItems_Clear, "wxControlWithItems", "clear", 1}, // 888
+ {wxControlWithItems_Delete, "wxControlWithItems", "delete", 2}, // 889
+ {wxControlWithItems_FindString, "wxControlWithItems", "findString", 3}, // 890
+ {wxControlWithItems_getClientData, "wxControlWithItems", "getClientData", 2}, // 891
+ {wxControlWithItems_setClientData, "wxControlWithItems", "setClientData", 3}, // 892
+ {wxControlWithItems_GetCount, "wxControlWithItems", "getCount", 1}, // 893
+ {wxControlWithItems_GetSelection, "wxControlWithItems", "getSelection", 1}, // 894
+ {wxControlWithItems_GetString, "wxControlWithItems", "getString", 2}, // 895
+ {wxControlWithItems_GetStringSelection, "wxControlWithItems", "getStringSelection", 1}, // 896
+ {wxControlWithItems_Insert_2, "wxControlWithItems", "insert", 3}, // 897
+ {wxControlWithItems_Insert_3, "wxControlWithItems", "insert", 4}, // 898
+ {wxControlWithItems_insertStrings_2, "wxControlWithItems", "insertStrings", 3}, // 899
+ {wxControlWithItems_insertStrings_3, "wxControlWithItems", "insertStrings", 4}, // 900
+ {wxControlWithItems_IsEmpty, "wxControlWithItems", "isEmpty", 1}, // 901
+ {wxControlWithItems_Select, "wxControlWithItems", "select", 2}, // 902
+ {wxControlWithItems_SetSelection, "wxControlWithItems", "setSelection", 2}, // 903
+ {wxControlWithItems_SetString, "wxControlWithItems", "setString", 3}, // 904
+ {wxControlWithItems_SetStringSelection, "wxControlWithItems", "setStringSelection", 2}, // 905
+ {wxMenu_new_0, "wxMenu", "new", 0}, // 906
+ {wxMenu_new_1, "wxMenu", "new", 1}, // 907
+ {wxMenu_new_2, "wxMenu", "new", 2}, // 908
+ {NULL, "wxMenu", "destroy", 1}, // 909 obj destructor wxMenu_destruct
+ {wxMenu_Append_3, "wxMenu", "append", 4}, // 910
+ {wxMenu_Append_4, "wxMenu", "append", 5}, // 911
+ {wxMenu_Append_1, "wxMenu", "append", 2}, // 912
+ {wxMenu_AppendCheckItem, "wxMenu", "appendCheckItem", 4}, // 913
+ {wxMenu_AppendRadioItem, "wxMenu", "appendRadioItem", 4}, // 914
+ {wxMenu_AppendSeparator, "wxMenu", "appendSeparator", 1}, // 915
+ {wxMenu_Break, "wxMenu", "break", 1}, // 916
+ {wxMenu_Check, "wxMenu", "check", 3}, // 917
+ {wxMenu_Delete_1_0, "wxMenu", "delete", 2}, // 918
+ {wxMenu_Delete_1_1, "wxMenu", "delete", 2}, // 919
+ {wxMenu_Destroy_1_0, "wxMenu", "'Destroy'", 2}, // 920
+ {wxMenu_Destroy_1_1, "wxMenu", "'Destroy'", 2}, // 921
+ {wxMenu_Enable, "wxMenu", "enable", 3}, // 922
+ {wxMenu_FindItem_1, "wxMenu", "findItem", 2}, // 923
+ {wxMenu_FindItem_2, "wxMenu", "findItem", 2}, // 924
+ {wxMenu_FindItemByPosition, "wxMenu", "findItemByPosition", 2}, // 925
+ {wxMenu_GetHelpString, "wxMenu", "getHelpString", 2}, // 926
+ {wxMenu_GetLabel, "wxMenu", "getLabel", 2}, // 927
+ {wxMenu_GetMenuItemCount, "wxMenu", "getMenuItemCount", 1}, // 928
+ {NULL, "", "", 0}, // 929
+ {wxMenu_GetMenuItems, "wxMenu", "getMenuItems", 1}, // 930
+ {wxMenu_GetTitle, "wxMenu", "getTitle", 1}, // 931
+ {wxMenu_Insert_2, "wxMenu", "insert", 3}, // 932
+ {wxMenu_Insert_3, "wxMenu", "insert", 4}, // 933
+ {wxMenu_Insert_5, "wxMenu", "insert", 6}, // 934
+ {wxMenu_InsertCheckItem, "wxMenu", "insertCheckItem", 5}, // 935
+ {wxMenu_InsertRadioItem, "wxMenu", "insertRadioItem", 5}, // 936
+ {wxMenu_InsertSeparator, "wxMenu", "insertSeparator", 2}, // 937
+ {wxMenu_IsChecked, "wxMenu", "isChecked", 2}, // 938
+ {wxMenu_IsEnabled, "wxMenu", "isEnabled", 2}, // 939
+ {wxMenu_Prepend_1, "wxMenu", "prepend", 2}, // 940
+ {wxMenu_Prepend_2, "wxMenu", "prepend", 3}, // 941
+ {wxMenu_Prepend_4, "wxMenu", "prepend", 5}, // 942
+ {wxMenu_PrependCheckItem, "wxMenu", "prependCheckItem", 4}, // 943
+ {wxMenu_PrependRadioItem, "wxMenu", "prependRadioItem", 4}, // 944
+ {wxMenu_PrependSeparator, "wxMenu", "prependSeparator", 1}, // 945
+ {wxMenu_Remove_1_0, "wxMenu", "remove", 2}, // 946
+ {wxMenu_Remove_1_1, "wxMenu", "remove", 2}, // 947
+ {wxMenu_SetHelpString, "wxMenu", "setHelpString", 3}, // 948
+ {wxMenu_SetLabel, "wxMenu", "setLabel", 3}, // 949
+ {wxMenu_SetTitle, "wxMenu", "setTitle", 2}, // 950
+ {wxMenuItem_new, "wxMenuItem", "new", 1}, // 951
+ {NULL, "wxMenuItem", "destroy", 1}, // 952 obj destructor wxMenuItem_destruct
+ {wxMenuItem_Check, "wxMenuItem", "check", 2}, // 953
+ {wxMenuItem_Enable, "wxMenuItem", "enable", 2}, // 954
+ {wxMenuItem_GetBitmap, "wxMenuItem", "getBitmap", 1}, // 955
+ {wxMenuItem_GetHelp, "wxMenuItem", "getHelp", 1}, // 956
+ {wxMenuItem_GetId, "wxMenuItem", "getId", 1}, // 957
+ {wxMenuItem_GetKind, "wxMenuItem", "getKind", 1}, // 958
+ {wxMenuItem_GetLabelText, "wxMenuItem", "getLabelText", 1}, // 959
+ {wxMenuItem_GetItemLabel, "wxMenuItem", "getItemLabel", 1}, // 960
+ {wxMenuItem_GetItemLabelText, "wxMenuItem", "getItemLabelText", 1}, // 961
+ {wxMenuItem_GetMenu, "wxMenuItem", "getMenu", 1}, // 962
+ {wxMenuItem_GetSubMenu, "wxMenuItem", "getSubMenu", 1}, // 963
+ {wxMenuItem_IsCheckable, "wxMenuItem", "isCheckable", 1}, // 964
+ {wxMenuItem_IsChecked, "wxMenuItem", "isChecked", 1}, // 965
+ {wxMenuItem_IsEnabled, "wxMenuItem", "isEnabled", 1}, // 966
+ {wxMenuItem_IsSeparator, "wxMenuItem", "isSeparator", 1}, // 967
+ {wxMenuItem_IsSubMenu, "wxMenuItem", "isSubMenu", 1}, // 968
+ {wxMenuItem_SetBitmap, "wxMenuItem", "setBitmap", 2}, // 969
+ {wxMenuItem_SetHelp, "wxMenuItem", "setHelp", 2}, // 970
+ {wxMenuItem_SetMenu, "wxMenuItem", "setMenu", 2}, // 971
+ {wxMenuItem_SetSubMenu, "wxMenuItem", "setSubMenu", 2}, // 972
+ {wxMenuItem_SetItemLabel, "wxMenuItem", "setItemLabel", 2}, // 973
+ {wxToolBar_AddControl, "wxToolBar", "addControl", 3}, // 974
+ {wxToolBar_AddSeparator, "wxToolBar", "addSeparator", 1}, // 975
+ {wxToolBar_AddTool_1, "wxToolBar", "addTool", 2}, // 976
+ {wxToolBar_AddTool_4, "wxToolBar", "addTool", 5}, // 977
+ {wxToolBar_AddTool_5, "wxToolBar", "addTool", 6}, // 978
+ {wxToolBar_AddCheckTool, "wxToolBar", "addCheckTool", 5}, // 979
+ {wxToolBar_AddRadioTool, "wxToolBar", "addRadioTool", 5}, // 980
+ {wxToolBar_AddStretchableSpace, "wxToolBar", "addStretchableSpace", 1}, // 981
+ {wxToolBar_InsertStretchableSpace, "wxToolBar", "insertStretchableSpace", 2}, // 982
+ {wxToolBar_DeleteTool, "wxToolBar", "deleteTool", 2}, // 983
+ {wxToolBar_DeleteToolByPos, "wxToolBar", "deleteToolByPos", 2}, // 984
+ {wxToolBar_EnableTool, "wxToolBar", "enableTool", 3}, // 985
+ {wxToolBar_FindById, "wxToolBar", "findById", 2}, // 986
+ {wxToolBar_FindControl, "wxToolBar", "findControl", 2}, // 987
+ {wxToolBar_FindToolForPosition, "wxToolBar", "findToolForPosition", 3}, // 988
+ {wxToolBar_GetToolSize, "wxToolBar", "getToolSize", 1}, // 989
+ {wxToolBar_GetToolBitmapSize, "wxToolBar", "getToolBitmapSize", 1}, // 990
+ {wxToolBar_GetMargins, "wxToolBar", "getMargins", 1}, // 991
+ {wxToolBar_GetToolEnabled, "wxToolBar", "getToolEnabled", 2}, // 992
+ {wxToolBar_GetToolLongHelp, "wxToolBar", "getToolLongHelp", 2}, // 993
+ {wxToolBar_GetToolPacking, "wxToolBar", "getToolPacking", 1}, // 994
+ {wxToolBar_GetToolPos, "wxToolBar", "getToolPos", 2}, // 995
+ {wxToolBar_GetToolSeparation, "wxToolBar", "getToolSeparation", 1}, // 996
+ {wxToolBar_GetToolShortHelp, "wxToolBar", "getToolShortHelp", 2}, // 997
+ {wxToolBar_GetToolState, "wxToolBar", "getToolState", 2}, // 998
+ {wxToolBar_InsertControl, "wxToolBar", "insertControl", 4}, // 999
+ {wxToolBar_InsertSeparator, "wxToolBar", "insertSeparator", 2}, // 1000
+ {wxToolBar_InsertTool_5, "wxToolBar", "insertTool", 6}, // 1001
+ {wxToolBar_InsertTool_2, "wxToolBar", "insertTool", 3}, // 1002
+ {wxToolBar_Realize, "wxToolBar", "realize", 1}, // 1003
+ {wxToolBar_RemoveTool, "wxToolBar", "removeTool", 2}, // 1004
+ {wxToolBar_SetMargins, "wxToolBar", "setMargins", 3}, // 1005
+ {wxToolBar_SetToolBitmapSize, "wxToolBar", "setToolBitmapSize", 2}, // 1006
+ {wxToolBar_SetToolLongHelp, "wxToolBar", "setToolLongHelp", 3}, // 1007
+ {wxToolBar_SetToolPacking, "wxToolBar", "setToolPacking", 2}, // 1008
+ {wxToolBar_SetToolShortHelp, "wxToolBar", "setToolShortHelp", 3}, // 1009
+ {wxToolBar_SetToolSeparation, "wxToolBar", "setToolSeparation", 2}, // 1010
+ {wxToolBar_ToggleTool, "wxToolBar", "toggleTool", 3}, // 1011
+ {wxStatusBar_new_0, "wxStatusBar", "new", 0}, // 1012
+ {wxStatusBar_new_2, "wxStatusBar", "new", 2}, // 1013
+ {NULL, "wxStatusBar", "destroy", 1}, // 1014 obj destructor wxStatusBar_destruct
+ {wxStatusBar_Create, "wxStatusBar", "create", 3}, // 1015
+ {wxStatusBar_GetFieldRect, "wxStatusBar", "getFieldRect", 2}, // 1016
+ {wxStatusBar_GetFieldsCount, "wxStatusBar", "getFieldsCount", 1}, // 1017
+ {wxStatusBar_GetStatusText, "wxStatusBar", "getStatusText", 2}, // 1018
+ {wxStatusBar_PopStatusText, "wxStatusBar", "popStatusText", 2}, // 1019
+ {wxStatusBar_PushStatusText, "wxStatusBar", "pushStatusText", 3}, // 1020
+ {wxStatusBar_SetFieldsCount, "wxStatusBar", "setFieldsCount", 3}, // 1021
+ {wxStatusBar_SetMinHeight, "wxStatusBar", "setMinHeight", 2}, // 1022
+ {wxStatusBar_SetStatusText, "wxStatusBar", "setStatusText", 3}, // 1023
+ {wxStatusBar_SetStatusWidths, "wxStatusBar", "setStatusWidths", 2}, // 1024
+ {wxStatusBar_SetStatusStyles, "wxStatusBar", "setStatusStyles", 2}, // 1025
+ {wxBitmap_new_0, "wxBitmap", "new", 0}, // 1026
+ {NULL, "", "", 0}, // 1027
+ {wxBitmap_new_4, "wxBitmap", "new", 4}, // 1028
+ {wxBitmap_new_3, "wxBitmap", "new", 3}, // 1029
+ {wxBitmap_new_2_1, "wxBitmap", "new", 2}, // 1030
+ {wxBitmap_new_2_0, "wxBitmap", "new", 2}, // 1031
+ {wxBitmap_new_2_2, "wxBitmap", "new", 2}, // 1032
+ {wxBitmap_new_2_3, "wxBitmap", "new", 1}, // 1033
+ {NULL, "wxBitmap", "destroy", 1}, // 1034 obj destructor wxBitmap_destruct
+ {wxBitmap_ConvertToImage, "wxBitmap", "convertToImage", 1}, // 1035
+ {wxBitmap_CopyFromIcon, "wxBitmap", "copyFromIcon", 2}, // 1036
+ {wxBitmap_Create_3_0, "wxBitmap", "create", 4}, // 1037
+ {wxBitmap_Create_2, "wxBitmap", "create", 3}, // 1038
+ {wxBitmap_Create_3_1, "wxBitmap", "create", 4}, // 1039
+ {wxBitmap_GetDepth, "wxBitmap", "getDepth", 1}, // 1040
+ {wxBitmap_GetHeight, "wxBitmap", "getHeight", 1}, // 1041
+ {wxBitmap_GetPalette, "wxBitmap", "getPalette", 1}, // 1042
+ {wxBitmap_GetMask, "wxBitmap", "getMask", 1}, // 1043
+ {wxBitmap_GetWidth, "wxBitmap", "getWidth", 1}, // 1044
+ {wxBitmap_GetSubBitmap, "wxBitmap", "getSubBitmap", 2}, // 1045
+ {wxBitmap_LoadFile, "wxBitmap", "loadFile", 3}, // 1046
+ {wxBitmap_IsOk, "wxBitmap", "isOk", 1}, // 1047
+ {wxBitmap_SaveFile, "wxBitmap", "saveFile", 4}, // 1048
+ {wxBitmap_SetDepth, "wxBitmap", "setDepth", 2}, // 1049
+ {wxBitmap_SetHeight, "wxBitmap", "setHeight", 2}, // 1050
+ {wxBitmap_SetMask, "wxBitmap", "setMask", 2}, // 1051
+ {wxBitmap_SetPalette, "wxBitmap", "setPalette", 2}, // 1052
+ {wxBitmap_SetWidth, "wxBitmap", "setWidth", 2}, // 1053
+ {wxIcon_new_0, "wxIcon", "new", 0}, // 1054
+ {wxIcon_new_1, "wxIcon", "new", 1}, // 1055
+ {wxIcon_new_2, "wxIcon", "new", 2}, // 1056
+ {wxIcon_CopyFromBitmap, "wxIcon", "copyFromBitmap", 2}, // 1057
+ {NULL, "wxIcon", "destroy", 1}, // 1058 obj destructor wxIcon_destruct
+ {wxIconBundle_new_0, "wxIconBundle", "new", 0}, // 1059
+ {wxIconBundle_new_1_1, "wxIconBundle", "new", 1}, // 1060
+ {wxIconBundle_new_2, "wxIconBundle", "new", 2}, // 1061
+ {NULL, "", "", 0}, // 1062
+ {wxIconBundle_new_1_0, "wxIconBundle", "new", 1}, // 1063
+ {wxIconBundle_destruct, "wxIconBundle", "destroy", 1}, // 1064
+ {wxIconBundle_AddIcon_1_0, "wxIconBundle", "addIcon", 2}, // 1065
+ {wxIconBundle_AddIcon_2, "wxIconBundle", "addIcon", 3}, // 1066
+ {wxIconBundle_AddIcon_1_1, "wxIconBundle", "addIcon", 2}, // 1067
+ {wxIconBundle_GetIcon_2, "wxIconBundle", "getIcon", 3}, // 1068
+ {wxIconBundle_GetIcon_1, "wxIconBundle", "getIcon", 2}, // 1069
+ {wxCursor_new_0, "wxCursor", "new", 0}, // 1070
+ {wxCursor_new_2, "wxCursor", "new", 2}, // 1071
+ {wxCursor_new_1_1, "wxCursor", "new", 1}, // 1072
+ {wxCursor_new_1_0, "wxCursor", "new", 1}, // 1073
+ {NULL, "", "", 0}, // 1074
+ {NULL, "wxCursor", "destroy", 1}, // 1075 obj destructor wxCursor_destruct
+ {wxCursor_IsOk, "wxCursor", "isOk", 1}, // 1076
+ {wxMask_new_0, "wxMask", "new", 0}, // 1077
+ {wxMask_new_2_0, "wxMask", "new", 2}, // 1078
+ {wxMask_new_1, "wxMask", "new", 1}, // 1079
+ {wxMask_new_2_1, "wxMask", "new", 2}, // 1080
+ {NULL, "wxMask", "destroy", 1}, // 1081 obj destructor wxMask_destruct
+ {wxMask_Create_2_0, "wxMask", "create", 3}, // 1082
+ {wxMask_Create_1, "wxMask", "create", 2}, // 1083
+ {wxMask_Create_2_1, "wxMask", "create", 3}, // 1084
+ {wxImage_new_0, "wxImage", "new", 0}, // 1085
+ {wxImage_new_3_1, "wxImage", "new", 3}, // 1086
+ {wxImage_new_2_2, "wxImage", "new", 2}, // 1087
+ {wxImage_new_3_0, "wxImage", "new", 3}, // 1088
+ {wxImage_new_2_1, "wxImage", "new", 2}, // 1089
+ {wxImage_new_4, "wxImage", "new", 4}, // 1090
+ {wxImage_new_3_3, "wxImage", "new", 3}, // 1091
+ {wxImage_new_2_0, "wxImage", "new", 2}, // 1092
+ {wxImage_new_3_2, "wxImage", "new", 3}, // 1093
+ {NULL, "wxImage", "destroy", 1}, // 1094 obj destructor wxImage_destruct
+ {wxImage_Blur, "wxImage", "blur", 2}, // 1095
+ {wxImage_BlurHorizontal, "wxImage", "blurHorizontal", 2}, // 1096
+ {wxImage_BlurVertical, "wxImage", "blurVertical", 2}, // 1097
+ {wxImage_ConvertAlphaToMask_1, "wxImage", "convertAlphaToMask", 2}, // 1098
+ {wxImage_ConvertAlphaToMask_4, "wxImage", "convertAlphaToMask", 5}, // 1099
+ {wxImage_ConvertToGreyscale_3, "wxImage", "convertToGreyscale", 4}, // 1100
+ {wxImage_ConvertToGreyscale_0, "wxImage", "convertToGreyscale", 1}, // 1101
+ {wxImage_ConvertToMono, "wxImage", "convertToMono", 4}, // 1102
+ {wxImage_Copy, "wxImage", "copy", 1}, // 1103
+ {wxImage_Create_3_1, "wxImage", "create", 4}, // 1104
+ {wxImage_Create_2_1, "wxImage", "create", 3}, // 1105
+ {wxImage_Create_3_0, "wxImage", "create", 4}, // 1106
+ {wxImage_Create_2_0, "wxImage", "create", 3}, // 1107
+ {wxImage_Create_4, "wxImage", "create", 5}, // 1108
+ {wxImage_Create_3_2, "wxImage", "create", 4}, // 1109
+ {wxImage_Destroy, "wxImage", "'Destroy'", 1}, // 1110
+ {wxImage_FindFirstUnusedColour, "wxImage", "findFirstUnusedColour", 2}, // 1111
+ {wxImage_GetImageExtWildcard, "wxImage", "getImageExtWildcard", 0}, // 1112
+ {wxImage_GetAlpha_0, "wxImage", "getAlpha", 1}, // 1113
+ {wxImage_GetAlpha_2, "wxImage", "getAlpha", 3}, // 1114
+ {wxImage_GetBlue, "wxImage", "getBlue", 3}, // 1115
+ {wxImage_GetData, "wxImage", "getData", 1}, // 1116
+ {wxImage_GetGreen, "wxImage", "getGreen", 3}, // 1117
+ {wxImage_GetImageCount, "wxImage", "getImageCount", 2}, // 1118
+ {wxImage_GetHeight, "wxImage", "getHeight", 1}, // 1119
+ {wxImage_GetMaskBlue, "wxImage", "getMaskBlue", 1}, // 1120
+ {wxImage_GetMaskGreen, "wxImage", "getMaskGreen", 1}, // 1121
+ {wxImage_GetMaskRed, "wxImage", "getMaskRed", 1}, // 1122
+ {wxImage_GetOrFindMaskColour, "wxImage", "getOrFindMaskColour", 1}, // 1123
+ {wxImage_GetPalette, "wxImage", "getPalette", 1}, // 1124
+ {wxImage_GetRed, "wxImage", "getRed", 3}, // 1125
+ {wxImage_GetSubImage, "wxImage", "getSubImage", 2}, // 1126
+ {wxImage_GetWidth, "wxImage", "getWidth", 1}, // 1127
+ {wxImage_HasAlpha, "wxImage", "hasAlpha", 1}, // 1128
+ {wxImage_HasMask, "wxImage", "hasMask", 1}, // 1129
+ {wxImage_GetOption, "wxImage", "getOption", 2}, // 1130
+ {wxImage_GetOptionInt, "wxImage", "getOptionInt", 2}, // 1131
+ {wxImage_HasOption, "wxImage", "hasOption", 2}, // 1132
+ {wxImage_InitAlpha, "wxImage", "initAlpha", 1}, // 1133
+ {wxImage_InitStandardHandlers, "wxImage", "initStandardHandlers", 0}, // 1134
+ {wxImage_IsTransparent, "wxImage", "isTransparent", 4}, // 1135
+ {wxImage_LoadFile_2, "wxImage", "loadFile", 3}, // 1136
+ {wxImage_LoadFile_3, "wxImage", "loadFile", 4}, // 1137
+ {wxImage_IsOk, "wxImage", "isOk", 1}, // 1138
+ {wxImage_RemoveHandler, "wxImage", "removeHandler", 1}, // 1139
+ {wxImage_Mirror, "wxImage", "mirror", 2}, // 1140
+ {wxImage_Replace, "wxImage", "replace", 7}, // 1141
+ {wxImage_Rescale, "wxImage", "rescale", 4}, // 1142
+ {wxImage_Resize, "wxImage", "resize", 4}, // 1143
+ {wxImage_Rotate, "wxImage", "rotate", 4}, // 1144
+ {wxImage_RotateHue, "wxImage", "rotateHue", 2}, // 1145
+ {wxImage_Rotate90, "wxImage", "rotate90", 2}, // 1146
+ {wxImage_SaveFile_2_0, "wxImage", "saveFile", 3}, // 1147
+ {wxImage_SaveFile_2_1, "wxImage", "saveFile", 3}, // 1148
+ {wxImage_SaveFile_1, "wxImage", "saveFile", 2}, // 1149
+ {wxImage_Scale, "wxImage", "scale", 4}, // 1150
+ {wxImage_Size, "wxImage", "size", 4}, // 1151
+ {wxImage_SetAlpha_1, "wxImage", "setAlpha", 2}, // 1152
+ {wxImage_SetAlpha_3, "wxImage", "setAlpha", 4}, // 1153
+ {wxImage_SetData_1, "wxImage", "setData", 2}, // 1154
+ {wxImage_SetData_3, "wxImage", "setData", 4}, // 1155
+ {wxImage_SetMask, "wxImage", "setMask", 2}, // 1156
+ {wxImage_SetMaskColour, "wxImage", "setMaskColour", 4}, // 1157
+ {wxImage_SetMaskFromImage, "wxImage", "setMaskFromImage", 5}, // 1158
+ {wxImage_SetOption_2_1, "wxImage", "setOption", 3}, // 1159
+ {wxImage_SetOption_2_0, "wxImage", "setOption", 3}, // 1160
+ {wxImage_SetPalette, "wxImage", "setPalette", 2}, // 1161
+ {wxImage_SetRGB_5, "wxImage", "setRGB", 6}, // 1162
+ {wxImage_SetRGB_4, "wxImage", "setRGB", 5}, // 1163
+ {wxBrush_new_0, "wxBrush", "new", 0}, // 1164
+ {wxBrush_new_2, "wxBrush", "new", 2}, // 1165
+ {NULL, "", "", 0}, // 1166
+ {wxBrush_new_1, "wxBrush", "new", 1}, // 1167
+ {NULL, "wxBrush", "destroy", 1}, // 1168 obj destructor wxBrush_destruct
+ {wxBrush_GetColour, "wxBrush", "getColour", 1}, // 1169
+ {wxBrush_GetStipple, "wxBrush", "getStipple", 1}, // 1170
+ {wxBrush_GetStyle, "wxBrush", "getStyle", 1}, // 1171
+ {wxBrush_IsHatch, "wxBrush", "isHatch", 1}, // 1172
+ {wxBrush_IsOk, "wxBrush", "isOk", 1}, // 1173
+ {wxBrush_SetColour_1, "wxBrush", "setColour", 2}, // 1174
+ {wxBrush_SetColour_3, "wxBrush", "setColour", 4}, // 1175
+ {wxBrush_SetStipple, "wxBrush", "setStipple", 2}, // 1176
+ {wxBrush_SetStyle, "wxBrush", "setStyle", 2}, // 1177
+ {wxPen_new_0, "wxPen", "new", 0}, // 1178
+ {wxPen_new_2, "wxPen", "new", 2}, // 1179
+ {wxPen_new_1, "wxPen", "new", 1}, // 1180
+ {NULL, "wxPen", "destroy", 1}, // 1181 obj destructor wxPen_destruct
+ {wxPen_GetCap, "wxPen", "getCap", 1}, // 1182
+ {wxPen_GetColour, "wxPen", "getColour", 1}, // 1183
+ {wxPen_GetJoin, "wxPen", "getJoin", 1}, // 1184
+ {wxPen_GetStyle, "wxPen", "getStyle", 1}, // 1185
+ {wxPen_GetWidth, "wxPen", "getWidth", 1}, // 1186
+ {wxPen_IsOk, "wxPen", "isOk", 1}, // 1187
+ {wxPen_SetCap, "wxPen", "setCap", 2}, // 1188
+ {wxPen_SetColour_1, "wxPen", "setColour", 2}, // 1189
+ {wxPen_SetColour_3, "wxPen", "setColour", 4}, // 1190
+ {wxPen_SetJoin, "wxPen", "setJoin", 2}, // 1191
+ {wxPen_SetStyle, "wxPen", "setStyle", 2}, // 1192
+ {wxPen_SetWidth, "wxPen", "setWidth", 2}, // 1193
+ {wxRegion_new_0, "wxRegion", "new", 0}, // 1194
+ {wxRegion_new_4, "wxRegion", "new", 4}, // 1195
+ {wxRegion_new_2, "wxRegion", "new", 2}, // 1196
+ {wxRegion_new_1_0, "wxRegion", "new", 1}, // 1197
{NULL, "", "", 0}, // 1198
- {NULL, "wxRegion", "destroy", 1}, // 1199 obj destructor wxRegion_destruct
- {wxRegion_Clear, "wxRegion", "clear", 1}, // 1200
- {wxRegion_Contains_2, "wxRegion", "contains", 3}, // 1201
- {wxRegion_Contains_1_0, "wxRegion", "contains", 2}, // 1202
- {wxRegion_Contains_4, "wxRegion", "contains", 5}, // 1203
- {wxRegion_Contains_1_1, "wxRegion", "contains", 2}, // 1204
- {wxRegion_ConvertToBitmap, "wxRegion", "convertToBitmap", 1}, // 1205
- {wxRegion_GetBox, "wxRegion", "getBox", 1}, // 1206
- {wxRegion_Intersect_4, "wxRegion", "intersect", 5}, // 1207
- {wxRegion_Intersect_1_0, "wxRegion", "intersect", 2}, // 1208
- {wxRegion_Intersect_1_1, "wxRegion", "intersect", 2}, // 1209
- {wxRegion_IsEmpty, "wxRegion", "isEmpty", 1}, // 1210
- {wxRegion_Subtract_1_0, "wxRegion", "subtract", 2}, // 1211
- {wxRegion_Subtract_1_1, "wxRegion", "subtract", 2}, // 1212
- {wxRegion_Offset_2, "wxRegion", "offset", 3}, // 1213
- {wxRegion_Offset_1, "wxRegion", "offset", 2}, // 1214
- {wxRegion_Union_4, "wxRegion", "union", 5}, // 1215
- {wxRegion_Union_1_1, "wxRegion", "union", 2}, // 1216
- {wxRegion_Union_1_0, "wxRegion", "union", 2}, // 1217
- {NULL, "", "", 0}, // 1218
- {wxRegion_Union_3, "wxRegion", "union", 4}, // 1219
- {wxRegion_Xor_4, "wxRegion", "'Xor'", 5}, // 1220
- {wxRegion_Xor_1_0, "wxRegion", "'Xor'", 2}, // 1221
- {wxRegion_Xor_1_1, "wxRegion", "'Xor'", 2}, // 1222
- {wxAcceleratorTable_new_0, "wxAcceleratorTable", "new", 0}, // 1223
- {wxAcceleratorTable_new_2, "wxAcceleratorTable", "new", 2}, // 1224
- {NULL, "", "", 0}, // 1225
- {NULL, "wxAcceleratorTable", "destroy", 1}, // 1226 obj destructor wxAcceleratorTable_destruct
- {wxAcceleratorTable_IsOk, "wxAcceleratorTable", "isOk", 1}, // 1227
- {wxAcceleratorEntry_new_1_0, "wxAcceleratorEntry", "new", 1}, // 1228
- {wxAcceleratorEntry_new_1_1, "wxAcceleratorEntry", "new", 1}, // 1229
- {wxAcceleratorEntry_GetCommand, "wxAcceleratorEntry", "getCommand", 1}, // 1230
- {wxAcceleratorEntry_GetFlags, "wxAcceleratorEntry", "getFlags", 1}, // 1231
- {wxAcceleratorEntry_GetKeyCode, "wxAcceleratorEntry", "getKeyCode", 1}, // 1232
- {wxAcceleratorEntry_Set, "wxAcceleratorEntry", "set", 5}, // 1233
- {wxAcceleratorEntry_destroy, "wxAcceleratorEntry", "'Destroy'", 1}, // 1234
- {NULL, "", "", 0}, // 1235
- {wxCaret_new_3, "wxCaret", "new", 3}, // 1236
- {wxCaret_new_2, "wxCaret", "new", 2}, // 1237
- {wxCaret_Create_3, "wxCaret", "create", 4}, // 1238
- {wxCaret_Create_2, "wxCaret", "create", 3}, // 1239
- {wxCaret_GetBlinkTime, "wxCaret", "getBlinkTime", 0}, // 1240
- {NULL, "", "", 0}, // 1241
- {wxCaret_GetPosition, "wxCaret", "getPosition", 1}, // 1242
+ {wxRegion_new_1_1, "wxRegion", "new", 1}, // 1199
+ {NULL, "", "", 0}, // 1200
+ {NULL, "wxRegion", "destroy", 1}, // 1201 obj destructor wxRegion_destruct
+ {wxRegion_Clear, "wxRegion", "clear", 1}, // 1202
+ {wxRegion_Contains_2, "wxRegion", "contains", 3}, // 1203
+ {wxRegion_Contains_1_0, "wxRegion", "contains", 2}, // 1204
+ {wxRegion_Contains_4, "wxRegion", "contains", 5}, // 1205
+ {wxRegion_Contains_1_1, "wxRegion", "contains", 2}, // 1206
+ {wxRegion_ConvertToBitmap, "wxRegion", "convertToBitmap", 1}, // 1207
+ {wxRegion_GetBox, "wxRegion", "getBox", 1}, // 1208
+ {wxRegion_Intersect_4, "wxRegion", "intersect", 5}, // 1209
+ {wxRegion_Intersect_1_0, "wxRegion", "intersect", 2}, // 1210
+ {wxRegion_Intersect_1_1, "wxRegion", "intersect", 2}, // 1211
+ {wxRegion_IsEmpty, "wxRegion", "isEmpty", 1}, // 1212
+ {wxRegion_Subtract_1_0, "wxRegion", "subtract", 2}, // 1213
+ {wxRegion_Subtract_1_1, "wxRegion", "subtract", 2}, // 1214
+ {wxRegion_Offset_2, "wxRegion", "offset", 3}, // 1215
+ {wxRegion_Offset_1, "wxRegion", "offset", 2}, // 1216
+ {wxRegion_Union_4, "wxRegion", "union", 5}, // 1217
+ {wxRegion_Union_1_1, "wxRegion", "union", 2}, // 1218
+ {wxRegion_Union_1_0, "wxRegion", "union", 2}, // 1219
+ {NULL, "", "", 0}, // 1220
+ {wxRegion_Union_3, "wxRegion", "union", 4}, // 1221
+ {wxRegion_Xor_4, "wxRegion", "'Xor'", 5}, // 1222
+ {wxRegion_Xor_1_0, "wxRegion", "'Xor'", 2}, // 1223
+ {wxRegion_Xor_1_1, "wxRegion", "'Xor'", 2}, // 1224
+ {wxAcceleratorTable_new_0, "wxAcceleratorTable", "new", 0}, // 1225
+ {wxAcceleratorTable_new_2, "wxAcceleratorTable", "new", 2}, // 1226
+ {NULL, "", "", 0}, // 1227
+ {NULL, "wxAcceleratorTable", "destroy", 1}, // 1228 obj destructor wxAcceleratorTable_destruct
+ {wxAcceleratorTable_IsOk, "wxAcceleratorTable", "isOk", 1}, // 1229
+ {wxAcceleratorEntry_new_1_0, "wxAcceleratorEntry", "new", 1}, // 1230
+ {wxAcceleratorEntry_new_1_1, "wxAcceleratorEntry", "new", 1}, // 1231
+ {wxAcceleratorEntry_GetCommand, "wxAcceleratorEntry", "getCommand", 1}, // 1232
+ {wxAcceleratorEntry_GetFlags, "wxAcceleratorEntry", "getFlags", 1}, // 1233
+ {wxAcceleratorEntry_GetKeyCode, "wxAcceleratorEntry", "getKeyCode", 1}, // 1234
+ {wxAcceleratorEntry_Set, "wxAcceleratorEntry", "set", 5}, // 1235
+ {wxAcceleratorEntry_destroy, "wxAcceleratorEntry", "'Destroy'", 1}, // 1236
+ {NULL, "", "", 0}, // 1237
+ {wxCaret_new_3, "wxCaret", "new", 3}, // 1238
+ {wxCaret_new_2, "wxCaret", "new", 2}, // 1239
+ {wxCaret_Create_3, "wxCaret", "create", 4}, // 1240
+ {wxCaret_Create_2, "wxCaret", "create", 3}, // 1241
+ {wxCaret_GetBlinkTime, "wxCaret", "getBlinkTime", 0}, // 1242
{NULL, "", "", 0}, // 1243
- {wxCaret_GetSize, "wxCaret", "getSize", 1}, // 1244
- {wxCaret_GetWindow, "wxCaret", "getWindow", 1}, // 1245
- {wxCaret_Hide, "wxCaret", "hide", 1}, // 1246
- {wxCaret_IsOk, "wxCaret", "isOk", 1}, // 1247
- {wxCaret_IsVisible, "wxCaret", "isVisible", 1}, // 1248
- {wxCaret_Move_2, "wxCaret", "move", 3}, // 1249
- {wxCaret_Move_1, "wxCaret", "move", 2}, // 1250
- {wxCaret_SetBlinkTime, "wxCaret", "setBlinkTime", 1}, // 1251
- {wxCaret_SetSize_2, "wxCaret", "setSize", 3}, // 1252
- {wxCaret_SetSize_1, "wxCaret", "setSize", 2}, // 1253
- {wxCaret_Show, "wxCaret", "show", 2}, // 1254
- {wxCaret_destroy, "wxCaret", "'Destroy'", 1}, // 1255
- {wxSizer_Add_2_0, "wxSizer", "add", 3}, // 1256
- {wxSizer_Add_2_1, "wxSizer", "add", 3}, // 1257
- {NULL, "", "", 0}, // 1258
- {NULL, "", "", 0}, // 1259
- {wxSizer_Add_3_0, "wxSizer", "add", 4}, // 1260
- {wxSizer_Add_3_1, "wxSizer", "add", 4}, // 1261
- {wxSizer_AddSpacer, "wxSizer", "addSpacer", 2}, // 1262
- {wxSizer_AddStretchSpacer, "wxSizer", "addStretchSpacer", 2}, // 1263
- {wxSizer_CalcMin, "wxSizer", "calcMin", 1}, // 1264
- {wxSizer_Clear, "wxSizer", "clear", 2}, // 1265
- {wxSizer_Detach_1_0, "wxSizer", "detach", 2}, // 1266
- {NULL, "", "", 0}, // 1267
- {wxSizer_Detach_1_1, "wxSizer", "detach", 2}, // 1268
- {wxSizer_Fit, "wxSizer", "fit", 2}, // 1269
- {wxSizer_FitInside, "wxSizer", "fitInside", 2}, // 1270
- {NULL, "", "", 0}, // 1271
- {wxSizer_GetChildren, "wxSizer", "getChildren", 1}, // 1272
- {wxSizer_GetItem_2, "wxSizer", "getItem", 3}, // 1273
- {NULL, "", "", 0}, // 1274
- {wxSizer_GetItem_1, "wxSizer", "getItem", 2}, // 1275
- {wxSizer_GetSize, "wxSizer", "getSize", 1}, // 1276
- {wxSizer_GetPosition, "wxSizer", "getPosition", 1}, // 1277
- {wxSizer_GetMinSize, "wxSizer", "getMinSize", 1}, // 1278
- {wxSizer_Hide_2, "wxSizer", "hide", 3}, // 1279
- {NULL, "", "", 0}, // 1280
- {wxSizer_Hide_1, "wxSizer", "hide", 2}, // 1281
- {wxSizer_Insert_3_0, "wxSizer", "insert", 4}, // 1282
- {wxSizer_Insert_3_1, "wxSizer", "insert", 4}, // 1283
- {NULL, "", "", 0}, // 1284
- {NULL, "", "", 0}, // 1285
- {wxSizer_Insert_4_0, "wxSizer", "insert", 5}, // 1286
- {wxSizer_Insert_4_1, "wxSizer", "insert", 5}, // 1287
- {wxSizer_Insert_2, "wxSizer", "insert", 3}, // 1288
- {wxSizer_InsertSpacer, "wxSizer", "insertSpacer", 3}, // 1289
- {wxSizer_InsertStretchSpacer, "wxSizer", "insertStretchSpacer", 3}, // 1290
- {wxSizer_IsShown_1_0, "wxSizer", "isShown", 2}, // 1291
- {NULL, "", "", 0}, // 1292
- {wxSizer_IsShown_1_1, "wxSizer", "isShown", 2}, // 1293
- {wxSizer_Layout, "wxSizer", "layout", 1}, // 1294
- {wxSizer_Prepend_2_0, "wxSizer", "prepend", 3}, // 1295
- {wxSizer_Prepend_2_1, "wxSizer", "prepend", 3}, // 1296
- {NULL, "", "", 0}, // 1297
- {NULL, "", "", 0}, // 1298
- {wxSizer_Prepend_3_0, "wxSizer", "prepend", 4}, // 1299
- {wxSizer_Prepend_3_1, "wxSizer", "prepend", 4}, // 1300
- {wxSizer_Prepend_1, "wxSizer", "prepend", 2}, // 1301
- {wxSizer_PrependSpacer, "wxSizer", "prependSpacer", 2}, // 1302
- {wxSizer_PrependStretchSpacer, "wxSizer", "prependStretchSpacer", 2}, // 1303
- {wxSizer_Remove_1_1, "wxSizer", "remove", 2}, // 1304
- {wxSizer_Remove_1_0, "wxSizer", "remove", 2}, // 1305
- {wxSizer_Replace_3, "wxSizer", "replace", 4}, // 1306
- {NULL, "", "", 0}, // 1307
- {wxSizer_Replace_2, "wxSizer", "replace", 3}, // 1308
- {wxSizer_SetDimension_4, "wxSizer", "setDimension", 5}, // 1309
- {wxSizer_SetDimension_2, "wxSizer", "setDimension", 3}, // 1310
- {wxSizer_SetMinSize_1, "wxSizer", "setMinSize", 2}, // 1311
- {wxSizer_SetMinSize_2, "wxSizer", "setMinSize", 3}, // 1312
- {wxSizer_SetItemMinSize_3_0, "wxSizer", "setItemMinSize", 4}, // 1313
- {wxSizer_SetItemMinSize_2_0, "wxSizer", "setItemMinSize", 3}, // 1314
- {NULL, "", "", 0}, // 1315
- {NULL, "", "", 0}, // 1316
- {wxSizer_SetItemMinSize_3_1, "wxSizer", "setItemMinSize", 4}, // 1317
- {wxSizer_SetItemMinSize_2_1, "wxSizer", "setItemMinSize", 3}, // 1318
- {wxSizer_SetSizeHints, "wxSizer", "setSizeHints", 2}, // 1319
- {wxSizer_Show_2_0, "wxSizer", "show", 3}, // 1320
- {NULL, "", "", 0}, // 1321
- {wxSizer_Show_2_1, "wxSizer", "show", 3}, // 1322
- {wxSizer_Show_1, "wxSizer", "show", 2}, // 1323
- {wxSizer_ShowItems, "wxSizer", "showItems", 2}, // 1324
- {wxSizerFlags_new, "wxSizerFlags", "new", 1}, // 1325
- {wxSizerFlags_Align, "wxSizerFlags", "align", 2}, // 1326
- {wxSizerFlags_Border_2, "wxSizerFlags", "border", 3}, // 1327
- {wxSizerFlags_Border_1, "wxSizerFlags", "border", 2}, // 1328
- {wxSizerFlags_Center, "wxSizerFlags", "center", 1}, // 1329
- {wxSizerFlags_Expand, "wxSizerFlags", "expand", 1}, // 1330
- {wxSizerFlags_Left, "wxSizerFlags", "left", 1}, // 1331
- {wxSizerFlags_Proportion, "wxSizerFlags", "proportion", 2}, // 1332
- {wxSizerFlags_Right, "wxSizerFlags", "right", 1}, // 1333
- {wxSizerFlags_destroy, "wxSizerFlags", "'Destroy'", 1}, // 1334
- {wxSizerItem_new_3, "wxSizerItem", "new", 3}, // 1335
- {wxSizerItem_new_2_0, "wxSizerItem", "new", 2}, // 1336
- {wxSizerItem_new_2_1, "wxSizerItem", "new", 2}, // 1337
- {NULL, "", "", 0}, // 1338
- {NULL, "", "", 0}, // 1339
- {NULL, "wxSizerItem", "destroy", 1}, // 1340 obj destructor wxSizerItem_destruct
- {wxSizerItem_CalcMin, "wxSizerItem", "calcMin", 1}, // 1341
- {wxSizerItem_DeleteWindows, "wxSizerItem", "deleteWindows", 1}, // 1342
- {wxSizerItem_DetachSizer, "wxSizerItem", "detachSizer", 1}, // 1343
- {wxSizerItem_GetBorder, "wxSizerItem", "getBorder", 1}, // 1344
- {wxSizerItem_GetFlag, "wxSizerItem", "getFlag", 1}, // 1345
- {wxSizerItem_GetMinSize, "wxSizerItem", "getMinSize", 1}, // 1346
- {wxSizerItem_GetPosition, "wxSizerItem", "getPosition", 1}, // 1347
- {wxSizerItem_GetProportion, "wxSizerItem", "getProportion", 1}, // 1348
- {wxSizerItem_GetRatio, "wxSizerItem", "getRatio", 1}, // 1349
- {wxSizerItem_GetRect, "wxSizerItem", "getRect", 1}, // 1350
- {wxSizerItem_GetSize, "wxSizerItem", "getSize", 1}, // 1351
- {wxSizerItem_GetSizer, "wxSizerItem", "getSizer", 1}, // 1352
- {wxSizerItem_GetSpacer, "wxSizerItem", "getSpacer", 1}, // 1353
- {wxSizerItem_GetUserData, "wxSizerItem", "getUserData", 1}, // 1354
- {wxSizerItem_GetWindow, "wxSizerItem", "getWindow", 1}, // 1355
- {wxSizerItem_IsSizer, "wxSizerItem", "isSizer", 1}, // 1356
- {wxSizerItem_IsShown, "wxSizerItem", "isShown", 1}, // 1357
- {wxSizerItem_IsSpacer, "wxSizerItem", "isSpacer", 1}, // 1358
- {wxSizerItem_IsWindow, "wxSizerItem", "isWindow", 1}, // 1359
- {wxSizerItem_SetBorder, "wxSizerItem", "setBorder", 2}, // 1360
- {wxSizerItem_SetDimension, "wxSizerItem", "setDimension", 3}, // 1361
- {wxSizerItem_SetFlag, "wxSizerItem", "setFlag", 2}, // 1362
- {wxSizerItem_SetInitSize, "wxSizerItem", "setInitSize", 3}, // 1363
- {wxSizerItem_SetMinSize_1, "wxSizerItem", "setMinSize", 2}, // 1364
- {wxSizerItem_SetMinSize_2, "wxSizerItem", "setMinSize", 3}, // 1365
- {wxSizerItem_SetProportion, "wxSizerItem", "setProportion", 2}, // 1366
- {wxSizerItem_SetRatio_2, "wxSizerItem", "setRatio", 3}, // 1367
- {wxSizerItem_SetRatio_1_1, "wxSizerItem", "setRatio", 2}, // 1368
- {wxSizerItem_SetRatio_1_0, "wxSizerItem", "setRatio", 2}, // 1369
- {wxSizerItem_AssignSizer, "wxSizerItem", "assignSizer", 2}, // 1370
- {wxSizerItem_AssignSpacer_1, "wxSizerItem", "assignSpacer", 2}, // 1371
- {wxSizerItem_AssignSpacer_2, "wxSizerItem", "assignSpacer", 3}, // 1372
- {wxSizerItem_AssignWindow, "wxSizerItem", "assignWindow", 2}, // 1373
- {wxSizerItem_Show, "wxSizerItem", "show", 2}, // 1374
- {wxBoxSizer_new, "wxBoxSizer", "new", 1}, // 1375
- {wxBoxSizer_GetOrientation, "wxBoxSizer", "getOrientation", 1}, // 1376
- {NULL, "wxBoxSizer", "'Destroy'", 1}, // 1377 obj destructor wxBoxSizer_destroy
- {wxStaticBoxSizer_new_2, "wxStaticBoxSizer", "new", 2}, // 1378
- {wxStaticBoxSizer_new_3, "wxStaticBoxSizer", "new", 3}, // 1379
- {wxStaticBoxSizer_GetStaticBox, "wxStaticBoxSizer", "getStaticBox", 1}, // 1380
- {NULL, "wxStaticBoxSizer", "'Destroy'", 1}, // 1381 obj destructor wxStaticBoxSizer_destroy
- {wxGridSizer_new_3_0, "wxGridSizer", "new", 3}, // 1382
- {wxGridSizer_new_2, "wxGridSizer", "new", 2}, // 1383
- {wxGridSizer_new_4, "wxGridSizer", "new", 4}, // 1384
- {wxGridSizer_new_3_1, "wxGridSizer", "new", 3}, // 1385
- {wxGridSizer_GetCols, "wxGridSizer", "getCols", 1}, // 1386
- {wxGridSizer_GetHGap, "wxGridSizer", "getHGap", 1}, // 1387
- {wxGridSizer_GetRows, "wxGridSizer", "getRows", 1}, // 1388
- {wxGridSizer_GetVGap, "wxGridSizer", "getVGap", 1}, // 1389
- {wxGridSizer_SetCols, "wxGridSizer", "setCols", 2}, // 1390
- {wxGridSizer_SetHGap, "wxGridSizer", "setHGap", 2}, // 1391
- {wxGridSizer_SetRows, "wxGridSizer", "setRows", 2}, // 1392
- {wxGridSizer_SetVGap, "wxGridSizer", "setVGap", 2}, // 1393
- {NULL, "wxGridSizer", "'Destroy'", 1}, // 1394 obj destructor wxGridSizer_destroy
- {wxFlexGridSizer_new_3_0, "wxFlexGridSizer", "new", 3}, // 1395
- {wxFlexGridSizer_new_2, "wxFlexGridSizer", "new", 2}, // 1396
- {wxFlexGridSizer_new_4, "wxFlexGridSizer", "new", 4}, // 1397
- {wxFlexGridSizer_new_3_1, "wxFlexGridSizer", "new", 3}, // 1398
- {wxFlexGridSizer_AddGrowableCol, "wxFlexGridSizer", "addGrowableCol", 3}, // 1399
- {wxFlexGridSizer_AddGrowableRow, "wxFlexGridSizer", "addGrowableRow", 3}, // 1400
- {wxFlexGridSizer_GetFlexibleDirection, "wxFlexGridSizer", "getFlexibleDirection", 1}, // 1401
- {wxFlexGridSizer_GetNonFlexibleGrowMode, "wxFlexGridSizer", "getNonFlexibleGrowMode", 1}, // 1402
- {wxFlexGridSizer_RemoveGrowableCol, "wxFlexGridSizer", "removeGrowableCol", 2}, // 1403
- {wxFlexGridSizer_RemoveGrowableRow, "wxFlexGridSizer", "removeGrowableRow", 2}, // 1404
- {wxFlexGridSizer_SetFlexibleDirection, "wxFlexGridSizer", "setFlexibleDirection", 2}, // 1405
- {wxFlexGridSizer_SetNonFlexibleGrowMode, "wxFlexGridSizer", "setNonFlexibleGrowMode", 2}, // 1406
- {NULL, "wxFlexGridSizer", "'Destroy'", 1}, // 1407 obj destructor wxFlexGridSizer_destroy
- {wxGridBagSizer_new, "wxGridBagSizer", "new", 1}, // 1408
- {wxGridBagSizer_Add_3, "wxGridBagSizer", "add", 4}, // 1409
- {NULL, "", "", 0}, // 1410
- {wxGridBagSizer_Add_1, "wxGridBagSizer", "add", 2}, // 1411
- {wxGridBagSizer_Add_4, "wxGridBagSizer", "add", 5}, // 1412
- {wxGridBagSizer_CalcMin, "wxGridBagSizer", "calcMin", 1}, // 1413
- {wxGridBagSizer_CheckForIntersection_2, "wxGridBagSizer", "checkForIntersection", 3}, // 1414
- {wxGridBagSizer_CheckForIntersection_3, "wxGridBagSizer", "checkForIntersection", 4}, // 1415
- {wxGridBagSizer_FindItem, "wxGridBagSizer", "findItem", 2}, // 1416
- {NULL, "", "", 0}, // 1417
- {wxGridBagSizer_FindItemAtPoint, "wxGridBagSizer", "findItemAtPoint", 2}, // 1418
- {wxGridBagSizer_FindItemAtPosition, "wxGridBagSizer", "findItemAtPosition", 2}, // 1419
- {wxGridBagSizer_FindItemWithData, "wxGridBagSizer", "findItemWithData", 2}, // 1420
- {wxGridBagSizer_GetCellSize, "wxGridBagSizer", "getCellSize", 3}, // 1421
- {wxGridBagSizer_GetEmptyCellSize, "wxGridBagSizer", "getEmptyCellSize", 1}, // 1422
- {wxGridBagSizer_GetItemPosition_1_0, "wxGridBagSizer", "getItemPosition", 2}, // 1423
- {NULL, "", "", 0}, // 1424
- {wxGridBagSizer_GetItemPosition_1_1, "wxGridBagSizer", "getItemPosition", 2}, // 1425
- {wxGridBagSizer_GetItemSpan_1_0, "wxGridBagSizer", "getItemSpan", 2}, // 1426
- {NULL, "", "", 0}, // 1427
- {wxGridBagSizer_GetItemSpan_1_1, "wxGridBagSizer", "getItemSpan", 2}, // 1428
- {wxGridBagSizer_SetEmptyCellSize, "wxGridBagSizer", "setEmptyCellSize", 2}, // 1429
- {wxGridBagSizer_SetItemPosition_2_0, "wxGridBagSizer", "setItemPosition", 3}, // 1430
- {NULL, "", "", 0}, // 1431
- {wxGridBagSizer_SetItemPosition_2_1, "wxGridBagSizer", "setItemPosition", 3}, // 1432
- {wxGridBagSizer_SetItemSpan_2_0, "wxGridBagSizer", "setItemSpan", 3}, // 1433
- {NULL, "", "", 0}, // 1434
- {wxGridBagSizer_SetItemSpan_2_1, "wxGridBagSizer", "setItemSpan", 3}, // 1435
- {NULL, "wxGridBagSizer", "'Destroy'", 1}, // 1436 obj destructor wxGridBagSizer_destroy
- {wxStdDialogButtonSizer_new, "wxStdDialogButtonSizer", "new", 0}, // 1437
- {wxStdDialogButtonSizer_AddButton, "wxStdDialogButtonSizer", "addButton", 2}, // 1438
- {wxStdDialogButtonSizer_Realize, "wxStdDialogButtonSizer", "realize", 1}, // 1439
- {wxStdDialogButtonSizer_SetAffirmativeButton, "wxStdDialogButtonSizer", "setAffirmativeButton", 2}, // 1440
- {wxStdDialogButtonSizer_SetCancelButton, "wxStdDialogButtonSizer", "setCancelButton", 2}, // 1441
- {wxStdDialogButtonSizer_SetNegativeButton, "wxStdDialogButtonSizer", "setNegativeButton", 2}, // 1442
- {NULL, "wxStdDialogButtonSizer", "'Destroy'", 1}, // 1443 obj destructor wxStdDialogButtonSizer_destroy
- {wxFont_new_0, "wxFont", "new", 0}, // 1444
- {wxFont_new_1_1, "wxFont", "new", 1}, // 1445
- {wxFont_new_5_0, "wxFont", "new", 5}, // 1446
- {wxFont_new_5_1, "wxFont", "new", 5}, // 1447
- {wxFont_new_1_0, "wxFont", "new", 1}, // 1448
- {NULL, "wxFont", "destroy", 1}, // 1449 obj destructor wxFont_destruct
- {wxFont_IsFixedWidth, "wxFont", "isFixedWidth", 1}, // 1450
- {wxFont_GetDefaultEncoding, "wxFont", "getDefaultEncoding", 0}, // 1451
- {wxFont_GetFaceName, "wxFont", "getFaceName", 1}, // 1452
- {wxFont_GetFamily, "wxFont", "getFamily", 1}, // 1453
- {wxFont_GetNativeFontInfoDesc, "wxFont", "getNativeFontInfoDesc", 1}, // 1454
- {wxFont_GetNativeFontInfoUserDesc, "wxFont", "getNativeFontInfoUserDesc", 1}, // 1455
- {wxFont_GetPointSize, "wxFont", "getPointSize", 1}, // 1456
- {wxFont_GetStyle, "wxFont", "getStyle", 1}, // 1457
- {wxFont_GetUnderlined, "wxFont", "getUnderlined", 1}, // 1458
- {wxFont_GetWeight, "wxFont", "getWeight", 1}, // 1459
- {wxFont_IsOk, "wxFont", "isOk", 1}, // 1460
- {wxFont_SetDefaultEncoding, "wxFont", "setDefaultEncoding", 1}, // 1461
- {wxFont_SetFaceName, "wxFont", "setFaceName", 2}, // 1462
- {wxFont_SetFamily, "wxFont", "setFamily", 2}, // 1463
- {wxFont_SetPointSize, "wxFont", "setPointSize", 2}, // 1464
- {wxFont_SetStyle, "wxFont", "setStyle", 2}, // 1465
- {wxFont_SetUnderlined, "wxFont", "setUnderlined", 2}, // 1466
- {wxFont_SetWeight, "wxFont", "setWeight", 2}, // 1467
- {wxToolTip_Enable, "wxToolTip", "enable", 1}, // 1468
- {wxToolTip_SetDelay, "wxToolTip", "setDelay", 1}, // 1469
- {wxToolTip_new, "wxToolTip", "new", 1}, // 1470
- {wxToolTip_SetTip, "wxToolTip", "setTip", 2}, // 1471
- {wxToolTip_GetTip, "wxToolTip", "getTip", 1}, // 1472
- {wxToolTip_GetWindow, "wxToolTip", "getWindow", 1}, // 1473
- {NULL, "wxToolTip", "'Destroy'", 1}, // 1474 obj destructor wxToolTip_destroy
- {wxButton_new_0, "wxButton", "new", 0}, // 1475
- {wxButton_new_3, "wxButton", "new", 3}, // 1476
- {wxButton_Create, "wxButton", "create", 4}, // 1477
- {wxButton_GetDefaultSize_STAT_0, "wxButton", "getDefaultSize", 0}, // 1478
+ {wxCaret_GetPosition, "wxCaret", "getPosition", 1}, // 1244
+ {NULL, "", "", 0}, // 1245
+ {wxCaret_GetSize, "wxCaret", "getSize", 1}, // 1246
+ {wxCaret_GetWindow, "wxCaret", "getWindow", 1}, // 1247
+ {wxCaret_Hide, "wxCaret", "hide", 1}, // 1248
+ {wxCaret_IsOk, "wxCaret", "isOk", 1}, // 1249
+ {wxCaret_IsVisible, "wxCaret", "isVisible", 1}, // 1250
+ {wxCaret_Move_2, "wxCaret", "move", 3}, // 1251
+ {wxCaret_Move_1, "wxCaret", "move", 2}, // 1252
+ {wxCaret_SetBlinkTime, "wxCaret", "setBlinkTime", 1}, // 1253
+ {wxCaret_SetSize_2, "wxCaret", "setSize", 3}, // 1254
+ {wxCaret_SetSize_1, "wxCaret", "setSize", 2}, // 1255
+ {wxCaret_Show, "wxCaret", "show", 2}, // 1256
+ {wxCaret_destroy, "wxCaret", "'Destroy'", 1}, // 1257
+ {wxSizer_Add_2_0, "wxSizer", "add", 3}, // 1258
+ {wxSizer_Add_2_1, "wxSizer", "add", 3}, // 1259
+ {NULL, "", "", 0}, // 1260
+ {NULL, "", "", 0}, // 1261
+ {wxSizer_Add_3_0, "wxSizer", "add", 4}, // 1262
+ {wxSizer_Add_3_1, "wxSizer", "add", 4}, // 1263
+ {wxSizer_AddSpacer, "wxSizer", "addSpacer", 2}, // 1264
+ {wxSizer_AddStretchSpacer, "wxSizer", "addStretchSpacer", 2}, // 1265
+ {wxSizer_CalcMin, "wxSizer", "calcMin", 1}, // 1266
+ {wxSizer_Clear, "wxSizer", "clear", 2}, // 1267
+ {wxSizer_Detach_1_0, "wxSizer", "detach", 2}, // 1268
+ {NULL, "", "", 0}, // 1269
+ {wxSizer_Detach_1_1, "wxSizer", "detach", 2}, // 1270
+ {wxSizer_Fit, "wxSizer", "fit", 2}, // 1271
+ {wxSizer_FitInside, "wxSizer", "fitInside", 2}, // 1272
+ {NULL, "", "", 0}, // 1273
+ {wxSizer_GetChildren, "wxSizer", "getChildren", 1}, // 1274
+ {wxSizer_GetItem_2, "wxSizer", "getItem", 3}, // 1275
+ {NULL, "", "", 0}, // 1276
+ {wxSizer_GetItem_1, "wxSizer", "getItem", 2}, // 1277
+ {wxSizer_GetSize, "wxSizer", "getSize", 1}, // 1278
+ {wxSizer_GetPosition, "wxSizer", "getPosition", 1}, // 1279
+ {wxSizer_GetMinSize, "wxSizer", "getMinSize", 1}, // 1280
+ {wxSizer_Hide_2, "wxSizer", "hide", 3}, // 1281
+ {NULL, "", "", 0}, // 1282
+ {wxSizer_Hide_1, "wxSizer", "hide", 2}, // 1283
+ {wxSizer_Insert_3_0, "wxSizer", "insert", 4}, // 1284
+ {wxSizer_Insert_3_1, "wxSizer", "insert", 4}, // 1285
+ {NULL, "", "", 0}, // 1286
+ {NULL, "", "", 0}, // 1287
+ {wxSizer_Insert_4_0, "wxSizer", "insert", 5}, // 1288
+ {wxSizer_Insert_4_1, "wxSizer", "insert", 5}, // 1289
+ {wxSizer_Insert_2, "wxSizer", "insert", 3}, // 1290
+ {wxSizer_InsertSpacer, "wxSizer", "insertSpacer", 3}, // 1291
+ {wxSizer_InsertStretchSpacer, "wxSizer", "insertStretchSpacer", 3}, // 1292
+ {wxSizer_IsShown_1_0, "wxSizer", "isShown", 2}, // 1293
+ {NULL, "", "", 0}, // 1294
+ {wxSizer_IsShown_1_1, "wxSizer", "isShown", 2}, // 1295
+ {wxSizer_Layout, "wxSizer", "layout", 1}, // 1296
+ {wxSizer_Prepend_2_0, "wxSizer", "prepend", 3}, // 1297
+ {wxSizer_Prepend_2_1, "wxSizer", "prepend", 3}, // 1298
+ {NULL, "", "", 0}, // 1299
+ {NULL, "", "", 0}, // 1300
+ {wxSizer_Prepend_3_0, "wxSizer", "prepend", 4}, // 1301
+ {wxSizer_Prepend_3_1, "wxSizer", "prepend", 4}, // 1302
+ {wxSizer_Prepend_1, "wxSizer", "prepend", 2}, // 1303
+ {wxSizer_PrependSpacer, "wxSizer", "prependSpacer", 2}, // 1304
+ {wxSizer_PrependStretchSpacer, "wxSizer", "prependStretchSpacer", 2}, // 1305
+ {wxSizer_Remove_1_1, "wxSizer", "remove", 2}, // 1306
+ {wxSizer_Remove_1_0, "wxSizer", "remove", 2}, // 1307
+ {wxSizer_Replace_3, "wxSizer", "replace", 4}, // 1308
+ {NULL, "", "", 0}, // 1309
+ {wxSizer_Replace_2, "wxSizer", "replace", 3}, // 1310
+ {wxSizer_SetDimension_4, "wxSizer", "setDimension", 5}, // 1311
+ {wxSizer_SetDimension_2, "wxSizer", "setDimension", 3}, // 1312
+ {wxSizer_SetMinSize_1, "wxSizer", "setMinSize", 2}, // 1313
+ {wxSizer_SetMinSize_2, "wxSizer", "setMinSize", 3}, // 1314
+ {wxSizer_SetItemMinSize_3_0, "wxSizer", "setItemMinSize", 4}, // 1315
+ {wxSizer_SetItemMinSize_2_0, "wxSizer", "setItemMinSize", 3}, // 1316
+ {NULL, "", "", 0}, // 1317
+ {NULL, "", "", 0}, // 1318
+ {wxSizer_SetItemMinSize_3_1, "wxSizer", "setItemMinSize", 4}, // 1319
+ {wxSizer_SetItemMinSize_2_1, "wxSizer", "setItemMinSize", 3}, // 1320
+ {wxSizer_SetSizeHints, "wxSizer", "setSizeHints", 2}, // 1321
+ {wxSizer_Show_2_0, "wxSizer", "show", 3}, // 1322
+ {NULL, "", "", 0}, // 1323
+ {wxSizer_Show_2_1, "wxSizer", "show", 3}, // 1324
+ {wxSizer_Show_1, "wxSizer", "show", 2}, // 1325
+ {wxSizer_ShowItems, "wxSizer", "showItems", 2}, // 1326
+ {wxSizerFlags_new, "wxSizerFlags", "new", 1}, // 1327
+ {wxSizerFlags_Align, "wxSizerFlags", "align", 2}, // 1328
+ {wxSizerFlags_Border_2, "wxSizerFlags", "border", 3}, // 1329
+ {wxSizerFlags_Border_1, "wxSizerFlags", "border", 2}, // 1330
+ {wxSizerFlags_Center, "wxSizerFlags", "center", 1}, // 1331
+ {wxSizerFlags_Expand, "wxSizerFlags", "expand", 1}, // 1332
+ {wxSizerFlags_Left, "wxSizerFlags", "left", 1}, // 1333
+ {wxSizerFlags_Proportion, "wxSizerFlags", "proportion", 2}, // 1334
+ {wxSizerFlags_Right, "wxSizerFlags", "right", 1}, // 1335
+ {wxSizerFlags_destroy, "wxSizerFlags", "'Destroy'", 1}, // 1336
+ {wxSizerItem_new_3, "wxSizerItem", "new", 3}, // 1337
+ {wxSizerItem_new_2_0, "wxSizerItem", "new", 2}, // 1338
+ {wxSizerItem_new_2_1, "wxSizerItem", "new", 2}, // 1339
+ {NULL, "", "", 0}, // 1340
+ {NULL, "", "", 0}, // 1341
+ {NULL, "wxSizerItem", "destroy", 1}, // 1342 obj destructor wxSizerItem_destruct
+ {wxSizerItem_CalcMin, "wxSizerItem", "calcMin", 1}, // 1343
+ {wxSizerItem_DeleteWindows, "wxSizerItem", "deleteWindows", 1}, // 1344
+ {wxSizerItem_DetachSizer, "wxSizerItem", "detachSizer", 1}, // 1345
+ {wxSizerItem_GetBorder, "wxSizerItem", "getBorder", 1}, // 1346
+ {wxSizerItem_GetFlag, "wxSizerItem", "getFlag", 1}, // 1347
+ {wxSizerItem_GetMinSize, "wxSizerItem", "getMinSize", 1}, // 1348
+ {wxSizerItem_GetPosition, "wxSizerItem", "getPosition", 1}, // 1349
+ {wxSizerItem_GetProportion, "wxSizerItem", "getProportion", 1}, // 1350
+ {wxSizerItem_GetRatio, "wxSizerItem", "getRatio", 1}, // 1351
+ {wxSizerItem_GetRect, "wxSizerItem", "getRect", 1}, // 1352
+ {wxSizerItem_GetSize, "wxSizerItem", "getSize", 1}, // 1353
+ {wxSizerItem_GetSizer, "wxSizerItem", "getSizer", 1}, // 1354
+ {wxSizerItem_GetSpacer, "wxSizerItem", "getSpacer", 1}, // 1355
+ {wxSizerItem_GetUserData, "wxSizerItem", "getUserData", 1}, // 1356
+ {wxSizerItem_GetWindow, "wxSizerItem", "getWindow", 1}, // 1357
+ {wxSizerItem_IsSizer, "wxSizerItem", "isSizer", 1}, // 1358
+ {wxSizerItem_IsShown, "wxSizerItem", "isShown", 1}, // 1359
+ {wxSizerItem_IsSpacer, "wxSizerItem", "isSpacer", 1}, // 1360
+ {wxSizerItem_IsWindow, "wxSizerItem", "isWindow", 1}, // 1361
+ {wxSizerItem_SetBorder, "wxSizerItem", "setBorder", 2}, // 1362
+ {wxSizerItem_SetDimension, "wxSizerItem", "setDimension", 3}, // 1363
+ {wxSizerItem_SetFlag, "wxSizerItem", "setFlag", 2}, // 1364
+ {wxSizerItem_SetInitSize, "wxSizerItem", "setInitSize", 3}, // 1365
+ {wxSizerItem_SetMinSize_1, "wxSizerItem", "setMinSize", 2}, // 1366
+ {wxSizerItem_SetMinSize_2, "wxSizerItem", "setMinSize", 3}, // 1367
+ {wxSizerItem_SetProportion, "wxSizerItem", "setProportion", 2}, // 1368
+ {wxSizerItem_SetRatio_2, "wxSizerItem", "setRatio", 3}, // 1369
+ {wxSizerItem_SetRatio_1_1, "wxSizerItem", "setRatio", 2}, // 1370
+ {wxSizerItem_SetRatio_1_0, "wxSizerItem", "setRatio", 2}, // 1371
+ {wxSizerItem_AssignSizer, "wxSizerItem", "assignSizer", 2}, // 1372
+ {wxSizerItem_AssignSpacer_1, "wxSizerItem", "assignSpacer", 2}, // 1373
+ {wxSizerItem_AssignSpacer_2, "wxSizerItem", "assignSpacer", 3}, // 1374
+ {wxSizerItem_AssignWindow, "wxSizerItem", "assignWindow", 2}, // 1375
+ {wxSizerItem_Show, "wxSizerItem", "show", 2}, // 1376
+ {wxBoxSizer_new, "wxBoxSizer", "new", 1}, // 1377
+ {wxBoxSizer_GetOrientation, "wxBoxSizer", "getOrientation", 1}, // 1378
+ {NULL, "wxBoxSizer", "'Destroy'", 1}, // 1379 obj destructor wxBoxSizer_destroy
+ {wxStaticBoxSizer_new_2, "wxStaticBoxSizer", "new", 2}, // 1380
+ {wxStaticBoxSizer_new_3, "wxStaticBoxSizer", "new", 3}, // 1381
+ {wxStaticBoxSizer_GetStaticBox, "wxStaticBoxSizer", "getStaticBox", 1}, // 1382
+ {NULL, "wxStaticBoxSizer", "'Destroy'", 1}, // 1383 obj destructor wxStaticBoxSizer_destroy
+ {wxGridSizer_new_3_0, "wxGridSizer", "new", 3}, // 1384
+ {wxGridSizer_new_2, "wxGridSizer", "new", 2}, // 1385
+ {wxGridSizer_new_4, "wxGridSizer", "new", 4}, // 1386
+ {wxGridSizer_new_3_1, "wxGridSizer", "new", 3}, // 1387
+ {wxGridSizer_GetCols, "wxGridSizer", "getCols", 1}, // 1388
+ {wxGridSizer_GetHGap, "wxGridSizer", "getHGap", 1}, // 1389
+ {wxGridSizer_GetRows, "wxGridSizer", "getRows", 1}, // 1390
+ {wxGridSizer_GetVGap, "wxGridSizer", "getVGap", 1}, // 1391
+ {wxGridSizer_SetCols, "wxGridSizer", "setCols", 2}, // 1392
+ {wxGridSizer_SetHGap, "wxGridSizer", "setHGap", 2}, // 1393
+ {wxGridSizer_SetRows, "wxGridSizer", "setRows", 2}, // 1394
+ {wxGridSizer_SetVGap, "wxGridSizer", "setVGap", 2}, // 1395
+ {NULL, "wxGridSizer", "'Destroy'", 1}, // 1396 obj destructor wxGridSizer_destroy
+ {wxFlexGridSizer_new_3_0, "wxFlexGridSizer", "new", 3}, // 1397
+ {wxFlexGridSizer_new_2, "wxFlexGridSizer", "new", 2}, // 1398
+ {wxFlexGridSizer_new_4, "wxFlexGridSizer", "new", 4}, // 1399
+ {wxFlexGridSizer_new_3_1, "wxFlexGridSizer", "new", 3}, // 1400
+ {wxFlexGridSizer_AddGrowableCol, "wxFlexGridSizer", "addGrowableCol", 3}, // 1401
+ {wxFlexGridSizer_AddGrowableRow, "wxFlexGridSizer", "addGrowableRow", 3}, // 1402
+ {wxFlexGridSizer_GetFlexibleDirection, "wxFlexGridSizer", "getFlexibleDirection", 1}, // 1403
+ {wxFlexGridSizer_GetNonFlexibleGrowMode, "wxFlexGridSizer", "getNonFlexibleGrowMode", 1}, // 1404
+ {wxFlexGridSizer_RemoveGrowableCol, "wxFlexGridSizer", "removeGrowableCol", 2}, // 1405
+ {wxFlexGridSizer_RemoveGrowableRow, "wxFlexGridSizer", "removeGrowableRow", 2}, // 1406
+ {wxFlexGridSizer_SetFlexibleDirection, "wxFlexGridSizer", "setFlexibleDirection", 2}, // 1407
+ {wxFlexGridSizer_SetNonFlexibleGrowMode, "wxFlexGridSizer", "setNonFlexibleGrowMode", 2}, // 1408
+ {NULL, "wxFlexGridSizer", "'Destroy'", 1}, // 1409 obj destructor wxFlexGridSizer_destroy
+ {wxGridBagSizer_new, "wxGridBagSizer", "new", 1}, // 1410
+ {wxGridBagSizer_Add_3, "wxGridBagSizer", "add", 4}, // 1411
+ {NULL, "", "", 0}, // 1412
+ {wxGridBagSizer_Add_1, "wxGridBagSizer", "add", 2}, // 1413
+ {wxGridBagSizer_Add_4, "wxGridBagSizer", "add", 5}, // 1414
+ {wxGridBagSizer_CalcMin, "wxGridBagSizer", "calcMin", 1}, // 1415
+ {wxGridBagSizer_CheckForIntersection_2, "wxGridBagSizer", "checkForIntersection", 3}, // 1416
+ {wxGridBagSizer_CheckForIntersection_3, "wxGridBagSizer", "checkForIntersection", 4}, // 1417
+ {wxGridBagSizer_FindItem, "wxGridBagSizer", "findItem", 2}, // 1418
+ {NULL, "", "", 0}, // 1419
+ {wxGridBagSizer_FindItemAtPoint, "wxGridBagSizer", "findItemAtPoint", 2}, // 1420
+ {wxGridBagSizer_FindItemAtPosition, "wxGridBagSizer", "findItemAtPosition", 2}, // 1421
+ {wxGridBagSizer_FindItemWithData, "wxGridBagSizer", "findItemWithData", 2}, // 1422
+ {wxGridBagSizer_GetCellSize, "wxGridBagSizer", "getCellSize", 3}, // 1423
+ {wxGridBagSizer_GetEmptyCellSize, "wxGridBagSizer", "getEmptyCellSize", 1}, // 1424
+ {wxGridBagSizer_GetItemPosition_1_0, "wxGridBagSizer", "getItemPosition", 2}, // 1425
+ {NULL, "", "", 0}, // 1426
+ {wxGridBagSizer_GetItemPosition_1_1, "wxGridBagSizer", "getItemPosition", 2}, // 1427
+ {wxGridBagSizer_GetItemSpan_1_0, "wxGridBagSizer", "getItemSpan", 2}, // 1428
+ {NULL, "", "", 0}, // 1429
+ {wxGridBagSizer_GetItemSpan_1_1, "wxGridBagSizer", "getItemSpan", 2}, // 1430
+ {wxGridBagSizer_SetEmptyCellSize, "wxGridBagSizer", "setEmptyCellSize", 2}, // 1431
+ {wxGridBagSizer_SetItemPosition_2_0, "wxGridBagSizer", "setItemPosition", 3}, // 1432
+ {NULL, "", "", 0}, // 1433
+ {wxGridBagSizer_SetItemPosition_2_1, "wxGridBagSizer", "setItemPosition", 3}, // 1434
+ {wxGridBagSizer_SetItemSpan_2_0, "wxGridBagSizer", "setItemSpan", 3}, // 1435
+ {NULL, "", "", 0}, // 1436
+ {wxGridBagSizer_SetItemSpan_2_1, "wxGridBagSizer", "setItemSpan", 3}, // 1437
+ {NULL, "wxGridBagSizer", "'Destroy'", 1}, // 1438 obj destructor wxGridBagSizer_destroy
+ {wxStdDialogButtonSizer_new, "wxStdDialogButtonSizer", "new", 0}, // 1439
+ {wxStdDialogButtonSizer_AddButton, "wxStdDialogButtonSizer", "addButton", 2}, // 1440
+ {wxStdDialogButtonSizer_Realize, "wxStdDialogButtonSizer", "realize", 1}, // 1441
+ {wxStdDialogButtonSizer_SetAffirmativeButton, "wxStdDialogButtonSizer", "setAffirmativeButton", 2}, // 1442
+ {wxStdDialogButtonSizer_SetCancelButton, "wxStdDialogButtonSizer", "setCancelButton", 2}, // 1443
+ {wxStdDialogButtonSizer_SetNegativeButton, "wxStdDialogButtonSizer", "setNegativeButton", 2}, // 1444
+ {NULL, "wxStdDialogButtonSizer", "'Destroy'", 1}, // 1445 obj destructor wxStdDialogButtonSizer_destroy
+ {wxFont_new_0, "wxFont", "new", 0}, // 1446
+ {wxFont_new_1_1, "wxFont", "new", 1}, // 1447
+ {wxFont_new_5_0, "wxFont", "new", 5}, // 1448
+ {wxFont_new_5_1, "wxFont", "new", 5}, // 1449
+ {wxFont_new_1_0, "wxFont", "new", 1}, // 1450
+ {NULL, "wxFont", "destroy", 1}, // 1451 obj destructor wxFont_destruct
+ {wxFont_IsFixedWidth, "wxFont", "isFixedWidth", 1}, // 1452
+ {wxFont_GetDefaultEncoding, "wxFont", "getDefaultEncoding", 0}, // 1453
+ {wxFont_GetFaceName, "wxFont", "getFaceName", 1}, // 1454
+ {wxFont_GetFamily, "wxFont", "getFamily", 1}, // 1455
+ {wxFont_GetNativeFontInfoDesc, "wxFont", "getNativeFontInfoDesc", 1}, // 1456
+ {wxFont_GetNativeFontInfoUserDesc, "wxFont", "getNativeFontInfoUserDesc", 1}, // 1457
+ {wxFont_GetPointSize, "wxFont", "getPointSize", 1}, // 1458
+ {wxFont_GetStyle, "wxFont", "getStyle", 1}, // 1459
+ {wxFont_GetUnderlined, "wxFont", "getUnderlined", 1}, // 1460
+ {wxFont_GetWeight, "wxFont", "getWeight", 1}, // 1461
+ {wxFont_IsOk, "wxFont", "isOk", 1}, // 1462
+ {wxFont_SetDefaultEncoding, "wxFont", "setDefaultEncoding", 1}, // 1463
+ {wxFont_SetFaceName, "wxFont", "setFaceName", 2}, // 1464
+ {wxFont_SetFamily, "wxFont", "setFamily", 2}, // 1465
+ {wxFont_SetPointSize, "wxFont", "setPointSize", 2}, // 1466
+ {wxFont_SetStyle, "wxFont", "setStyle", 2}, // 1467
+ {wxFont_SetUnderlined, "wxFont", "setUnderlined", 2}, // 1468
+ {wxFont_SetWeight, "wxFont", "setWeight", 2}, // 1469
+ {wxToolTip_Enable, "wxToolTip", "enable", 1}, // 1470
+ {wxToolTip_SetDelay, "wxToolTip", "setDelay", 1}, // 1471
+ {wxToolTip_new, "wxToolTip", "new", 1}, // 1472
+ {wxToolTip_SetTip, "wxToolTip", "setTip", 2}, // 1473
+ {wxToolTip_GetTip, "wxToolTip", "getTip", 1}, // 1474
+ {wxToolTip_GetWindow, "wxToolTip", "getWindow", 1}, // 1475
+ {NULL, "wxToolTip", "'Destroy'", 1}, // 1476 obj destructor wxToolTip_destroy
+ {wxButton_new_0, "wxButton", "new", 0}, // 1477
+ {wxButton_new_3, "wxButton", "new", 3}, // 1478
+ {wxButton_Create, "wxButton", "create", 4}, // 1479
+ {wxButton_GetDefaultSize_STAT_0, "wxButton", "getDefaultSize", 0}, // 1480
#if wxCHECK_VERSION(3,1,3)
- {wxButton_GetDefaultSize_STAT_1, "wxButton", "getDefaultSize", 1}, // 1479
+ {wxButton_GetDefaultSize_STAT_1, "wxButton", "getDefaultSize", 1}, // 1481
#else
- {NULL, "wxButton", "getDefaultSize", 0}, // 1479
+ {NULL, "wxButton", "getDefaultSize", 0}, // 1481
#endif // wxCHECK_VERSION(3,1,3)
- {wxButton_SetDefault, "wxButton", "setDefault", 1}, // 1480
- {wxButton_SetLabel, "wxButton", "setLabel", 2}, // 1481
- {wxButton_GetBitmapDisabled, "wxButton", "getBitmapDisabled", 1}, // 1482
- {wxButton_GetBitmapFocus, "wxButton", "getBitmapFocus", 1}, // 1483
- {wxButton_GetBitmapLabel, "wxButton", "getBitmapLabel", 1}, // 1484
- {wxButton_SetBitmapDisabled, "wxButton", "setBitmapDisabled", 2}, // 1485
- {wxButton_SetBitmapFocus, "wxButton", "setBitmapFocus", 2}, // 1486
- {wxButton_SetBitmapLabel, "wxButton", "setBitmapLabel", 2}, // 1487
- {NULL, "wxButton", "'Destroy'", 1}, // 1488 obj destructor wxButton_destroy
- {wxBitmapButton_new_0, "wxBitmapButton", "new", 0}, // 1489
- {wxBitmapButton_new_4, "wxBitmapButton", "new", 4}, // 1490
- {wxBitmapButton_Create, "wxBitmapButton", "create", 5}, // 1491
- {wxBitmapButton_NewCloseButton, "wxBitmapButton", "newCloseButton", 2}, // 1492
- {NULL, "wxBitmapButton", "'Destroy'", 1}, // 1493 obj destructor wxBitmapButton_destroy
- {wxToggleButton_new_0, "wxToggleButton", "new", 0}, // 1494
- {wxToggleButton_new_4, "wxToggleButton", "new", 4}, // 1495
- {NULL, "wxToggleButton", "destroy", 1}, // 1496 obj destructor wxToggleButton_destruct
- {wxToggleButton_Create, "wxToggleButton", "create", 5}, // 1497
- {wxToggleButton_GetValue, "wxToggleButton", "getValue", 1}, // 1498
- {wxToggleButton_SetValue, "wxToggleButton", "setValue", 2}, // 1499
- {wxCalendarCtrl_new_0, "wxCalendarCtrl", "new", 0}, // 1500
- {wxCalendarCtrl_new_3, "wxCalendarCtrl", "new", 3}, // 1501
- {wxCalendarCtrl_Create, "wxCalendarCtrl", "create", 4}, // 1502
- {NULL, "wxCalendarCtrl", "destroy", 1}, // 1503 obj destructor wxCalendarCtrl_destruct
- {wxCalendarCtrl_SetDate, "wxCalendarCtrl", "setDate", 2}, // 1504
- {wxCalendarCtrl_GetDate, "wxCalendarCtrl", "getDate", 1}, // 1505
+ {wxButton_SetDefault, "wxButton", "setDefault", 1}, // 1482
+ {wxButton_SetLabel, "wxButton", "setLabel", 2}, // 1483
+ {wxButton_GetBitmapDisabled, "wxButton", "getBitmapDisabled", 1}, // 1484
+ {wxButton_GetBitmapFocus, "wxButton", "getBitmapFocus", 1}, // 1485
+ {wxButton_GetBitmapLabel, "wxButton", "getBitmapLabel", 1}, // 1486
+ {wxButton_SetBitmapDisabled, "wxButton", "setBitmapDisabled", 2}, // 1487
+ {wxButton_SetBitmapFocus, "wxButton", "setBitmapFocus", 2}, // 1488
+ {wxButton_SetBitmapLabel, "wxButton", "setBitmapLabel", 2}, // 1489
+ {NULL, "wxButton", "'Destroy'", 1}, // 1490 obj destructor wxButton_destroy
+ {wxBitmapButton_new_0, "wxBitmapButton", "new", 0}, // 1491
+ {wxBitmapButton_new_4, "wxBitmapButton", "new", 4}, // 1492
+ {wxBitmapButton_Create, "wxBitmapButton", "create", 5}, // 1493
+ {wxBitmapButton_NewCloseButton, "wxBitmapButton", "newCloseButton", 2}, // 1494
+ {NULL, "wxBitmapButton", "'Destroy'", 1}, // 1495 obj destructor wxBitmapButton_destroy
+ {wxToggleButton_new_0, "wxToggleButton", "new", 0}, // 1496
+ {wxToggleButton_new_4, "wxToggleButton", "new", 4}, // 1497
+ {NULL, "wxToggleButton", "destroy", 1}, // 1498 obj destructor wxToggleButton_destruct
+ {wxToggleButton_Create, "wxToggleButton", "create", 5}, // 1499
+ {wxToggleButton_GetValue, "wxToggleButton", "getValue", 1}, // 1500
+ {wxToggleButton_SetValue, "wxToggleButton", "setValue", 2}, // 1501
+ {wxCalendarCtrl_new_0, "wxCalendarCtrl", "new", 0}, // 1502
+ {wxCalendarCtrl_new_3, "wxCalendarCtrl", "new", 3}, // 1503
+ {wxCalendarCtrl_Create, "wxCalendarCtrl", "create", 4}, // 1504
+ {NULL, "wxCalendarCtrl", "destroy", 1}, // 1505 obj destructor wxCalendarCtrl_destruct
+ {wxCalendarCtrl_SetDate, "wxCalendarCtrl", "setDate", 2}, // 1506
+ {wxCalendarCtrl_GetDate, "wxCalendarCtrl", "getDate", 1}, // 1507
#if !wxCHECK_VERSION(2,9,0)
- {wxCalendarCtrl_EnableYearChange, "wxCalendarCtrl", "enableYearChange", 2}, // 1506
+ {wxCalendarCtrl_EnableYearChange, "wxCalendarCtrl", "enableYearChange", 2}, // 1508
#else
- {NULL, "wxCalendarCtrl", "enableYearChange", 0}, // 1506
+ {NULL, "wxCalendarCtrl", "enableYearChange", 0}, // 1508
#endif // !wxCHECK_VERSION(2,9,0)
- {wxCalendarCtrl_EnableMonthChange, "wxCalendarCtrl", "enableMonthChange", 2}, // 1507
- {wxCalendarCtrl_EnableHolidayDisplay, "wxCalendarCtrl", "enableHolidayDisplay", 2}, // 1508
- {wxCalendarCtrl_SetHeaderColours, "wxCalendarCtrl", "setHeaderColours", 3}, // 1509
- {wxCalendarCtrl_GetHeaderColourFg, "wxCalendarCtrl", "getHeaderColourFg", 1}, // 1510
- {wxCalendarCtrl_GetHeaderColourBg, "wxCalendarCtrl", "getHeaderColourBg", 1}, // 1511
- {wxCalendarCtrl_SetHighlightColours, "wxCalendarCtrl", "setHighlightColours", 3}, // 1512
- {wxCalendarCtrl_GetHighlightColourFg, "wxCalendarCtrl", "getHighlightColourFg", 1}, // 1513
- {wxCalendarCtrl_GetHighlightColourBg, "wxCalendarCtrl", "getHighlightColourBg", 1}, // 1514
- {wxCalendarCtrl_SetHolidayColours, "wxCalendarCtrl", "setHolidayColours", 3}, // 1515
- {wxCalendarCtrl_GetHolidayColourFg, "wxCalendarCtrl", "getHolidayColourFg", 1}, // 1516
- {wxCalendarCtrl_GetHolidayColourBg, "wxCalendarCtrl", "getHolidayColourBg", 1}, // 1517
- {wxCalendarCtrl_GetAttr, "wxCalendarCtrl", "getAttr", 2}, // 1518
- {wxCalendarCtrl_SetAttr, "wxCalendarCtrl", "setAttr", 3}, // 1519
- {wxCalendarCtrl_SetHoliday, "wxCalendarCtrl", "setHoliday", 2}, // 1520
- {wxCalendarCtrl_ResetAttr, "wxCalendarCtrl", "resetAttr", 2}, // 1521
- {wxCalendarCtrl_HitTest, "wxCalendarCtrl", "hitTest", 2}, // 1522
- {wxCalendarDateAttr_new_1, "wxCalendarDateAttr", "new", 1}, // 1523
- {wxCalendarDateAttr_new_2, "wxCalendarDateAttr", "new", 2}, // 1524
- {wxCalendarDateAttr_SetTextColour, "wxCalendarDateAttr", "setTextColour", 2}, // 1525
- {wxCalendarDateAttr_SetBackgroundColour, "wxCalendarDateAttr", "setBackgroundColour", 2}, // 1526
- {wxCalendarDateAttr_SetBorderColour, "wxCalendarDateAttr", "setBorderColour", 2}, // 1527
- {wxCalendarDateAttr_SetFont, "wxCalendarDateAttr", "setFont", 2}, // 1528
- {wxCalendarDateAttr_SetBorder, "wxCalendarDateAttr", "setBorder", 2}, // 1529
- {wxCalendarDateAttr_SetHoliday, "wxCalendarDateAttr", "setHoliday", 2}, // 1530
- {wxCalendarDateAttr_HasTextColour, "wxCalendarDateAttr", "hasTextColour", 1}, // 1531
- {wxCalendarDateAttr_HasBackgroundColour, "wxCalendarDateAttr", "hasBackgroundColour", 1}, // 1532
- {wxCalendarDateAttr_HasBorderColour, "wxCalendarDateAttr", "hasBorderColour", 1}, // 1533
- {wxCalendarDateAttr_HasFont, "wxCalendarDateAttr", "hasFont", 1}, // 1534
- {wxCalendarDateAttr_HasBorder, "wxCalendarDateAttr", "hasBorder", 1}, // 1535
- {wxCalendarDateAttr_IsHoliday, "wxCalendarDateAttr", "isHoliday", 1}, // 1536
- {wxCalendarDateAttr_GetTextColour, "wxCalendarDateAttr", "getTextColour", 1}, // 1537
- {wxCalendarDateAttr_GetBackgroundColour, "wxCalendarDateAttr", "getBackgroundColour", 1}, // 1538
- {wxCalendarDateAttr_GetBorderColour, "wxCalendarDateAttr", "getBorderColour", 1}, // 1539
- {wxCalendarDateAttr_GetFont, "wxCalendarDateAttr", "getFont", 1}, // 1540
- {wxCalendarDateAttr_GetBorder, "wxCalendarDateAttr", "getBorder", 1}, // 1541
- {wxCalendarDateAttr_destroy, "wxCalendarDateAttr", "'Destroy'", 1}, // 1542
- {wxCheckBox_new_0, "wxCheckBox", "new", 0}, // 1543
- {wxCheckBox_new_4, "wxCheckBox", "new", 4}, // 1544
- {NULL, "wxCheckBox", "destroy", 1}, // 1545 obj destructor wxCheckBox_destruct
- {wxCheckBox_Create, "wxCheckBox", "create", 5}, // 1546
- {wxCheckBox_GetValue, "wxCheckBox", "getValue", 1}, // 1547
- {wxCheckBox_Get3StateValue, "wxCheckBox", "get3StateValue", 1}, // 1548
- {wxCheckBox_Is3rdStateAllowedForUser, "wxCheckBox", "is3rdStateAllowedForUser", 1}, // 1549
- {wxCheckBox_Is3State, "wxCheckBox", "is3State", 1}, // 1550
- {wxCheckBox_IsChecked, "wxCheckBox", "isChecked", 1}, // 1551
- {wxCheckBox_SetValue, "wxCheckBox", "setValue", 2}, // 1552
- {wxCheckBox_Set3StateValue, "wxCheckBox", "set3StateValue", 2}, // 1553
- {wxCheckListBox_new_0, "wxCheckListBox", "new", 0}, // 1554
- {NULL, "", "", 0}, // 1555
- {wxCheckListBox_new_3, "wxCheckListBox", "new", 3}, // 1556
- {NULL, "wxCheckListBox", "destroy", 1}, // 1557 obj destructor wxCheckListBox_destruct
- {wxCheckListBox_Check, "wxCheckListBox", "check", 3}, // 1558
- {wxCheckListBox_IsChecked, "wxCheckListBox", "isChecked", 2}, // 1559
- {wxChoice_new_0, "wxChoice", "new", 0}, // 1560
- {NULL, "", "", 0}, // 1561
- {wxChoice_new_3, "wxChoice", "new", 3}, // 1562
- {NULL, "wxChoice", "destroy", 1}, // 1563 obj destructor wxChoice_destruct
- {NULL, "", "", 0}, // 1564
- {wxChoice_Create, "wxChoice", "create", 7}, // 1565
- {wxChoice_Delete, "wxChoice", "delete", 2}, // 1566
- {wxChoice_GetColumns, "wxChoice", "getColumns", 1}, // 1567
- {wxChoice_SetColumns, "wxChoice", "setColumns", 2}, // 1568
- {wxComboBox_new_0, "wxComboBox", "new", 0}, // 1569
- {NULL, "", "", 0}, // 1570
- {wxComboBox_new_3, "wxComboBox", "new", 3}, // 1571
- {NULL, "wxComboBox", "destroy", 1}, // 1572 obj destructor wxComboBox_destruct
- {NULL, "", "", 0}, // 1573
- {wxComboBox_Create, "wxComboBox", "create", 8}, // 1574
- {wxComboBox_CanCopy, "wxComboBox", "canCopy", 1}, // 1575
- {wxComboBox_CanCut, "wxComboBox", "canCut", 1}, // 1576
- {wxComboBox_CanPaste, "wxComboBox", "canPaste", 1}, // 1577
- {wxComboBox_CanRedo, "wxComboBox", "canRedo", 1}, // 1578
- {wxComboBox_CanUndo, "wxComboBox", "canUndo", 1}, // 1579
- {wxComboBox_Copy, "wxComboBox", "copy", 1}, // 1580
- {wxComboBox_Cut, "wxComboBox", "cut", 1}, // 1581
- {wxComboBox_GetInsertionPoint, "wxComboBox", "getInsertionPoint", 1}, // 1582
- {wxComboBox_GetLastPosition, "wxComboBox", "getLastPosition", 1}, // 1583
- {wxComboBox_GetValue, "wxComboBox", "getValue", 1}, // 1584
- {wxComboBox_Paste, "wxComboBox", "paste", 1}, // 1585
- {wxComboBox_Redo, "wxComboBox", "redo", 1}, // 1586
- {wxComboBox_Replace, "wxComboBox", "replace", 4}, // 1587
- {wxComboBox_Remove, "wxComboBox", "remove", 3}, // 1588
- {wxComboBox_SetInsertionPoint, "wxComboBox", "setInsertionPoint", 2}, // 1589
- {wxComboBox_SetInsertionPointEnd, "wxComboBox", "setInsertionPointEnd", 1}, // 1590
- {wxComboBox_SetSelection_2, "wxComboBox", "setSelection", 3}, // 1591
- {wxComboBox_SetSelection_1, "wxComboBox", "setSelection", 2}, // 1592
- {wxComboBox_SetValue, "wxComboBox", "setValue", 2}, // 1593
- {wxComboBox_Undo, "wxComboBox", "undo", 1}, // 1594
- {wxGauge_new_0, "wxGauge", "new", 0}, // 1595
- {wxGauge_new_4, "wxGauge", "new", 4}, // 1596
- {NULL, "wxGauge", "destroy", 1}, // 1597 obj destructor wxGauge_destruct
- {wxGauge_Create, "wxGauge", "create", 5}, // 1598
- {wxGauge_GetRange, "wxGauge", "getRange", 1}, // 1599
- {wxGauge_GetValue, "wxGauge", "getValue", 1}, // 1600
- {wxGauge_IsVertical, "wxGauge", "isVertical", 1}, // 1601
- {wxGauge_SetRange, "wxGauge", "setRange", 2}, // 1602
- {wxGauge_SetValue, "wxGauge", "setValue", 2}, // 1603
- {wxGauge_Pulse, "wxGauge", "pulse", 1}, // 1604
- {wxGenericDirCtrl_new_0, "wxGenericDirCtrl", "new", 0}, // 1605
- {wxGenericDirCtrl_new_2, "wxGenericDirCtrl", "new", 2}, // 1606
- {NULL, "wxGenericDirCtrl", "destroy", 1}, // 1607 obj destructor wxGenericDirCtrl_destruct
- {wxGenericDirCtrl_Create, "wxGenericDirCtrl", "create", 3}, // 1608
- {wxGenericDirCtrl_Init, "wxGenericDirCtrl", "init", 1}, // 1609
- {wxGenericDirCtrl_CollapseTree, "wxGenericDirCtrl", "collapseTree", 1}, // 1610
- {wxGenericDirCtrl_ExpandPath, "wxGenericDirCtrl", "expandPath", 2}, // 1611
- {wxGenericDirCtrl_GetDefaultPath, "wxGenericDirCtrl", "getDefaultPath", 1}, // 1612
- {wxGenericDirCtrl_GetPath_0, "wxGenericDirCtrl", "getPath", 1}, // 1613
- {wxGenericDirCtrl_GetPath_1, "wxGenericDirCtrl", "getPath", 2}, // 1614
- {wxGenericDirCtrl_GetFilePath, "wxGenericDirCtrl", "getFilePath", 1}, // 1615
- {wxGenericDirCtrl_GetFilter, "wxGenericDirCtrl", "getFilter", 1}, // 1616
- {wxGenericDirCtrl_GetFilterIndex, "wxGenericDirCtrl", "getFilterIndex", 1}, // 1617
- {wxGenericDirCtrl_GetRootId, "wxGenericDirCtrl", "getRootId", 1}, // 1618
- {wxGenericDirCtrl_GetTreeCtrl, "wxGenericDirCtrl", "getTreeCtrl", 1}, // 1619
- {wxGenericDirCtrl_ReCreateTree, "wxGenericDirCtrl", "reCreateTree", 1}, // 1620
- {wxGenericDirCtrl_SetDefaultPath, "wxGenericDirCtrl", "setDefaultPath", 2}, // 1621
- {wxGenericDirCtrl_SetFilter, "wxGenericDirCtrl", "setFilter", 2}, // 1622
- {wxGenericDirCtrl_SetFilterIndex, "wxGenericDirCtrl", "setFilterIndex", 2}, // 1623
- {wxGenericDirCtrl_SetPath, "wxGenericDirCtrl", "setPath", 2}, // 1624
- {wxStaticBox_new_0, "wxStaticBox", "new", 0}, // 1625
- {wxStaticBox_new_4, "wxStaticBox", "new", 4}, // 1626
- {NULL, "wxStaticBox", "destroy", 1}, // 1627 obj destructor wxStaticBox_destruct
- {wxStaticBox_Create, "wxStaticBox", "create", 5}, // 1628
- {wxStaticLine_new_0, "wxStaticLine", "new", 0}, // 1629
- {wxStaticLine_new_2, "wxStaticLine", "new", 2}, // 1630
- {wxStaticLine_Create, "wxStaticLine", "create", 3}, // 1631
- {wxStaticLine_IsVertical, "wxStaticLine", "isVertical", 1}, // 1632
- {wxStaticLine_GetDefaultSize, "wxStaticLine", "getDefaultSize", 0}, // 1633
- {NULL, "wxStaticLine", "'Destroy'", 1}, // 1634 obj destructor wxStaticLine_destroy
- {wxListBox_new_0, "wxListBox", "new", 0}, // 1635
- {NULL, "", "", 0}, // 1636
- {wxListBox_new_3, "wxListBox", "new", 3}, // 1637
- {NULL, "wxListBox", "destroy", 1}, // 1638 obj destructor wxListBox_destruct
- {NULL, "", "", 0}, // 1639
- {wxListBox_Create, "wxListBox", "create", 7}, // 1640
- {wxListBox_Deselect, "wxListBox", "deselect", 2}, // 1641
- {wxListBox_GetSelections, "wxListBox", "getSelections", 1}, // 1642
- {wxListBox_InsertItems, "wxListBox", "insertItems", 3}, // 1643
- {wxListBox_IsSelected, "wxListBox", "isSelected", 2}, // 1644
- {NULL, "", "", 0}, // 1645
- {NULL, "", "", 0}, // 1646
- {wxListBox_Set, "wxListBox", "set", 2}, // 1647
- {wxListBox_HitTest_1, "wxListBox", "hitTest", 2}, // 1648
- {wxListBox_HitTest_2, "wxListBox", "hitTest", 3}, // 1649
- {wxListBox_SetFirstItem_1_0, "wxListBox", "setFirstItem", 2}, // 1650
- {wxListBox_SetFirstItem_1_1, "wxListBox", "setFirstItem", 2}, // 1651
- {wxListCtrl_new_0, "wxListCtrl", "new", 0}, // 1652
- {NULL, "wxListCtrl", "new", 2}, // 1653 TaylorMade erl only wxListCtrl_new_2
- {NULL, "wxListCtrl", "destroy", 1}, // 1654 obj destructor wxListCtrl_destruct
- {wxListCtrl_Arrange, "wxListCtrl", "arrange", 2}, // 1655
- {wxListCtrl_AssignImageList, "wxListCtrl", "assignImageList", 3}, // 1656
- {wxListCtrl_ClearAll, "wxListCtrl", "clearAll", 1}, // 1657
- {wxListCtrl_Create, "wxListCtrl", "create", 3}, // 1658
- {wxListCtrl_DeleteAllItems, "wxListCtrl", "deleteAllItems", 1}, // 1659
- {wxListCtrl_DeleteColumn, "wxListCtrl", "deleteColumn", 2}, // 1660
- {wxListCtrl_DeleteItem, "wxListCtrl", "deleteItem", 2}, // 1661
- {wxListCtrl_EditLabel, "wxListCtrl", "editLabel", 2}, // 1662
- {wxListCtrl_EnsureVisible, "wxListCtrl", "ensureVisible", 2}, // 1663
- {wxListCtrl_FindItem_3_0, "wxListCtrl", "findItem", 4}, // 1664
- {wxListCtrl_FindItem_3_1, "wxListCtrl", "findItem", 4}, // 1665
- {wxListCtrl_GetColumn, "wxListCtrl", "getColumn", 3}, // 1666
- {wxListCtrl_GetColumnCount, "wxListCtrl", "getColumnCount", 1}, // 1667
- {wxListCtrl_GetColumnWidth, "wxListCtrl", "getColumnWidth", 2}, // 1668
- {wxListCtrl_GetCountPerPage, "wxListCtrl", "getCountPerPage", 1}, // 1669
- {wxListCtrl_GetEditControl, "wxListCtrl", "getEditControl", 1}, // 1670
- {wxListCtrl_GetImageList, "wxListCtrl", "getImageList", 2}, // 1671
- {wxListCtrl_GetItem, "wxListCtrl", "getItem", 2}, // 1672
- {wxListCtrl_GetItemBackgroundColour, "wxListCtrl", "getItemBackgroundColour", 2}, // 1673
- {wxListCtrl_GetItemCount, "wxListCtrl", "getItemCount", 1}, // 1674
- {wxListCtrl_GetItemData, "wxListCtrl", "getItemData", 2}, // 1675
- {wxListCtrl_GetItemFont, "wxListCtrl", "getItemFont", 2}, // 1676
- {wxListCtrl_GetItemPosition, "wxListCtrl", "getItemPosition", 2}, // 1677
- {wxListCtrl_GetItemRect, "wxListCtrl", "getItemRect", 3}, // 1678
- {wxListCtrl_GetItemSpacing, "wxListCtrl", "getItemSpacing", 1}, // 1679
- {wxListCtrl_GetItemState, "wxListCtrl", "getItemState", 3}, // 1680
- {wxListCtrl_GetItemText, "wxListCtrl", "getItemText", 3}, // 1681
- {wxListCtrl_GetItemTextColour, "wxListCtrl", "getItemTextColour", 2}, // 1682
- {wxListCtrl_GetNextItem, "wxListCtrl", "getNextItem", 3}, // 1683
- {wxListCtrl_GetSelectedItemCount, "wxListCtrl", "getSelectedItemCount", 1}, // 1684
- {wxListCtrl_GetTextColour, "wxListCtrl", "getTextColour", 1}, // 1685
- {wxListCtrl_GetTopItem, "wxListCtrl", "getTopItem", 1}, // 1686
- {wxListCtrl_GetViewRect, "wxListCtrl", "getViewRect", 1}, // 1687
- {wxListCtrl_HitTest, "wxListCtrl", "hitTest", 2}, // 1688
- {wxListCtrl_InsertColumn_2, "wxListCtrl", "insertColumn", 3}, // 1689
- {wxListCtrl_InsertColumn_3, "wxListCtrl", "insertColumn", 4}, // 1690
- {wxListCtrl_InsertItem_1, "wxListCtrl", "insertItem", 2}, // 1691
- {wxListCtrl_InsertItem_2_1, "wxListCtrl", "insertItem", 3}, // 1692
- {wxListCtrl_InsertItem_2_0, "wxListCtrl", "insertItem", 3}, // 1693
- {wxListCtrl_InsertItem_3, "wxListCtrl", "insertItem", 4}, // 1694
- {wxListCtrl_RefreshItem, "wxListCtrl", "refreshItem", 2}, // 1695
- {wxListCtrl_RefreshItems, "wxListCtrl", "refreshItems", 3}, // 1696
- {wxListCtrl_ScrollList, "wxListCtrl", "scrollList", 3}, // 1697
- {wxListCtrl_SetBackgroundColour, "wxListCtrl", "setBackgroundColour", 2}, // 1698
- {wxListCtrl_SetColumn, "wxListCtrl", "setColumn", 3}, // 1699
- {wxListCtrl_SetColumnWidth, "wxListCtrl", "setColumnWidth", 3}, // 1700
- {wxListCtrl_SetImageList, "wxListCtrl", "setImageList", 3}, // 1701
- {wxListCtrl_SetItem_1, "wxListCtrl", "setItem", 2}, // 1702
- {wxListCtrl_SetItem_4, "wxListCtrl", "setItem", 5}, // 1703
- {wxListCtrl_SetItemBackgroundColour, "wxListCtrl", "setItemBackgroundColour", 3}, // 1704
- {wxListCtrl_SetItemCount, "wxListCtrl", "setItemCount", 2}, // 1705
- {wxListCtrl_SetItemData, "wxListCtrl", "setItemData", 3}, // 1706
- {wxListCtrl_SetItemFont, "wxListCtrl", "setItemFont", 3}, // 1707
- {wxListCtrl_SetItemImage, "wxListCtrl", "setItemImage", 4}, // 1708
- {wxListCtrl_SetItemColumnImage, "wxListCtrl", "setItemColumnImage", 4}, // 1709
- {wxListCtrl_SetItemPosition, "wxListCtrl", "setItemPosition", 3}, // 1710
- {wxListCtrl_SetItemState, "wxListCtrl", "setItemState", 4}, // 1711
- {wxListCtrl_SetItemText, "wxListCtrl", "setItemText", 3}, // 1712
- {wxListCtrl_SetItemTextColour, "wxListCtrl", "setItemTextColour", 3}, // 1713
- {wxListCtrl_SetSingleStyle, "wxListCtrl", "setSingleStyle", 3}, // 1714
- {wxListCtrl_SetTextColour, "wxListCtrl", "setTextColour", 2}, // 1715
- {wxListCtrl_SetWindowStyleFlag, "wxListCtrl", "setWindowStyleFlag", 2}, // 1716
- {wxListCtrl_SortItems, "wxListCtrl", "sortItems", 2}, // 1717
- {wxListView_ClearColumnImage, "wxListView", "clearColumnImage", 2}, // 1718
- {wxListView_Focus, "wxListView", "focus", 2}, // 1719
- {wxListView_GetFirstSelected, "wxListView", "getFirstSelected", 1}, // 1720
- {wxListView_GetFocusedItem, "wxListView", "getFocusedItem", 1}, // 1721
- {wxListView_GetNextSelected, "wxListView", "getNextSelected", 2}, // 1722
- {wxListView_IsSelected, "wxListView", "isSelected", 2}, // 1723
- {wxListView_Select, "wxListView", "select", 3}, // 1724
- {wxListView_SetColumnImage, "wxListView", "setColumnImage", 3}, // 1725
- {wxListItem_new_0, "wxListItem", "new", 0}, // 1726
- {wxListItem_new_1, "wxListItem", "new", 1}, // 1727
- {wxListItem_Clear, "wxListItem", "clear", 1}, // 1728
- {wxListItem_GetAlign, "wxListItem", "getAlign", 1}, // 1729
- {wxListItem_GetBackgroundColour, "wxListItem", "getBackgroundColour", 1}, // 1730
- {wxListItem_GetColumn, "wxListItem", "getColumn", 1}, // 1731
- {wxListItem_GetFont, "wxListItem", "getFont", 1}, // 1732
- {wxListItem_GetId, "wxListItem", "getId", 1}, // 1733
- {wxListItem_GetImage, "wxListItem", "getImage", 1}, // 1734
- {wxListItem_GetMask, "wxListItem", "getMask", 1}, // 1735
- {wxListItem_GetState, "wxListItem", "getState", 1}, // 1736
- {wxListItem_GetText, "wxListItem", "getText", 1}, // 1737
- {wxListItem_GetTextColour, "wxListItem", "getTextColour", 1}, // 1738
- {wxListItem_GetWidth, "wxListItem", "getWidth", 1}, // 1739
- {wxListItem_SetAlign, "wxListItem", "setAlign", 2}, // 1740
- {wxListItem_SetBackgroundColour, "wxListItem", "setBackgroundColour", 2}, // 1741
- {wxListItem_SetColumn, "wxListItem", "setColumn", 2}, // 1742
- {wxListItem_SetFont, "wxListItem", "setFont", 2}, // 1743
- {wxListItem_SetId, "wxListItem", "setId", 2}, // 1744
- {wxListItem_SetImage, "wxListItem", "setImage", 2}, // 1745
- {wxListItem_SetMask, "wxListItem", "setMask", 2}, // 1746
- {wxListItem_SetState, "wxListItem", "setState", 2}, // 1747
- {wxListItem_SetStateMask, "wxListItem", "setStateMask", 2}, // 1748
- {wxListItem_SetText, "wxListItem", "setText", 2}, // 1749
- {wxListItem_SetTextColour, "wxListItem", "setTextColour", 2}, // 1750
- {wxListItem_SetWidth, "wxListItem", "setWidth", 2}, // 1751
- {NULL, "wxListItem", "'Destroy'", 1}, // 1752 obj destructor wxListItem_destroy
- {wxListItemAttr_new_0, "wxListItemAttr", "new", 0}, // 1753
- {wxListItemAttr_new_3, "wxListItemAttr", "new", 3}, // 1754
- {wxListItemAttr_GetBackgroundColour, "wxListItemAttr", "getBackgroundColour", 1}, // 1755
- {wxListItemAttr_GetFont, "wxListItemAttr", "getFont", 1}, // 1756
- {wxListItemAttr_GetTextColour, "wxListItemAttr", "getTextColour", 1}, // 1757
- {wxListItemAttr_HasBackgroundColour, "wxListItemAttr", "hasBackgroundColour", 1}, // 1758
- {wxListItemAttr_HasFont, "wxListItemAttr", "hasFont", 1}, // 1759
- {wxListItemAttr_HasTextColour, "wxListItemAttr", "hasTextColour", 1}, // 1760
- {wxListItemAttr_SetBackgroundColour, "wxListItemAttr", "setBackgroundColour", 2}, // 1761
- {wxListItemAttr_SetFont, "wxListItemAttr", "setFont", 2}, // 1762
- {wxListItemAttr_SetTextColour, "wxListItemAttr", "setTextColour", 2}, // 1763
- {wxListItemAttr_destroy, "wxListItemAttr", "'Destroy'", 1}, // 1764
- {wxImageList_new_0, "wxImageList", "new", 0}, // 1765
- {wxImageList_new_3, "wxImageList", "new", 3}, // 1766
- {wxImageList_Add_2_0, "wxImageList", "add", 3}, // 1767
- {NULL, "", "", 0}, // 1768
- {wxImageList_Add_2_1, "wxImageList", "add", 3}, // 1769
- {wxImageList_Add_1, "wxImageList", "add", 2}, // 1770
- {wxImageList_Create, "wxImageList", "create", 4}, // 1771
- {wxImageList_Draw, "wxImageList", "draw", 6}, // 1772
- {wxImageList_GetBitmap, "wxImageList", "getBitmap", 2}, // 1773
- {wxImageList_GetIcon, "wxImageList", "getIcon", 2}, // 1774
- {wxImageList_GetImageCount, "wxImageList", "getImageCount", 1}, // 1775
- {wxImageList_GetSize, "wxImageList", "getSize", 2}, // 1776
- {NULL, "", "", 0}, // 1777
- {wxImageList_Remove, "wxImageList", "remove", 2}, // 1778
- {wxImageList_RemoveAll, "wxImageList", "removeAll", 1}, // 1779
- {wxImageList_Replace_3, "wxImageList", "replace", 4}, // 1780
- {NULL, "", "", 0}, // 1781
- {wxImageList_Replace_2, "wxImageList", "replace", 3}, // 1782
- {NULL, "wxImageList", "'Destroy'", 1}, // 1783 obj destructor wxImageList_destroy
- {wxTextAttr_new_0, "wxTextAttr", "new", 0}, // 1784
- {wxTextAttr_new_2, "wxTextAttr", "new", 2}, // 1785
- {wxTextAttr_new_1, "wxTextAttr", "new", 1}, // 1786
- {wxTextAttr_GetAlignment, "wxTextAttr", "getAlignment", 1}, // 1787
- {wxTextAttr_GetBackgroundColour, "wxTextAttr", "getBackgroundColour", 1}, // 1788
- {wxTextAttr_GetFont, "wxTextAttr", "getFont", 1}, // 1789
- {wxTextAttr_GetFontEncoding, "wxTextAttr", "getFontEncoding", 1}, // 1790
- {wxTextAttr_GetFontFaceName, "wxTextAttr", "getFontFaceName", 1}, // 1791
- {wxTextAttr_GetFontSize, "wxTextAttr", "getFontSize", 1}, // 1792
- {wxTextAttr_GetFontStyle, "wxTextAttr", "getFontStyle", 1}, // 1793
- {wxTextAttr_GetFontUnderlined, "wxTextAttr", "getFontUnderlined", 1}, // 1794
- {wxTextAttr_GetFontWeight, "wxTextAttr", "getFontWeight", 1}, // 1795
- {wxTextAttr_GetLeftIndent, "wxTextAttr", "getLeftIndent", 1}, // 1796
- {wxTextAttr_GetLeftSubIndent, "wxTextAttr", "getLeftSubIndent", 1}, // 1797
- {wxTextAttr_GetRightIndent, "wxTextAttr", "getRightIndent", 1}, // 1798
- {wxTextAttr_GetTabs, "wxTextAttr", "getTabs", 1}, // 1799
- {wxTextAttr_GetTextColour, "wxTextAttr", "getTextColour", 1}, // 1800
- {wxTextAttr_HasBackgroundColour, "wxTextAttr", "hasBackgroundColour", 1}, // 1801
- {wxTextAttr_HasFont, "wxTextAttr", "hasFont", 1}, // 1802
- {wxTextAttr_HasTextColour, "wxTextAttr", "hasTextColour", 1}, // 1803
- {wxTextAttr_GetFlags, "wxTextAttr", "getFlags", 1}, // 1804
- {wxTextAttr_IsDefault, "wxTextAttr", "isDefault", 1}, // 1805
- {wxTextAttr_SetAlignment, "wxTextAttr", "setAlignment", 2}, // 1806
- {wxTextAttr_SetBackgroundColour, "wxTextAttr", "setBackgroundColour", 2}, // 1807
- {wxTextAttr_SetFlags, "wxTextAttr", "setFlags", 2}, // 1808
- {wxTextAttr_SetFont, "wxTextAttr", "setFont", 3}, // 1809
- {wxTextAttr_SetFontEncoding, "wxTextAttr", "setFontEncoding", 2}, // 1810
- {wxTextAttr_SetFontFaceName, "wxTextAttr", "setFontFaceName", 2}, // 1811
- {wxTextAttr_SetFontFamily, "wxTextAttr", "setFontFamily", 2}, // 1812
- {wxTextAttr_SetFontSize, "wxTextAttr", "setFontSize", 2}, // 1813
- {wxTextAttr_SetFontPointSize, "wxTextAttr", "setFontPointSize", 2}, // 1814
- {wxTextAttr_SetFontPixelSize, "wxTextAttr", "setFontPixelSize", 2}, // 1815
- {wxTextAttr_SetFontStyle, "wxTextAttr", "setFontStyle", 2}, // 1816
- {wxTextAttr_SetFontUnderlined, "wxTextAttr", "setFontUnderlined", 2}, // 1817
- {wxTextAttr_SetFontWeight, "wxTextAttr", "setFontWeight", 2}, // 1818
- {wxTextAttr_SetLeftIndent, "wxTextAttr", "setLeftIndent", 3}, // 1819
- {wxTextAttr_SetRightIndent, "wxTextAttr", "setRightIndent", 2}, // 1820
- {wxTextAttr_SetTabs, "wxTextAttr", "setTabs", 2}, // 1821
- {wxTextAttr_SetTextColour, "wxTextAttr", "setTextColour", 2}, // 1822
- {wxTextAttr_destroy, "wxTextAttr", "'Destroy'", 1}, // 1823
- {wxTextCtrl_new_0, "wxTextCtrl", "new", 0}, // 1824
- {wxTextCtrl_new_3, "wxTextCtrl", "new", 3}, // 1825
- {NULL, "wxTextCtrl", "destroy", 1}, // 1826 obj destructor wxTextCtrl_destruct
- {wxTextCtrl_AppendText, "wxTextCtrl", "appendText", 2}, // 1827
- {wxTextCtrl_CanCopy, "wxTextCtrl", "canCopy", 1}, // 1828
- {wxTextCtrl_CanCut, "wxTextCtrl", "canCut", 1}, // 1829
- {wxTextCtrl_CanPaste, "wxTextCtrl", "canPaste", 1}, // 1830
- {wxTextCtrl_CanRedo, "wxTextCtrl", "canRedo", 1}, // 1831
- {wxTextCtrl_CanUndo, "wxTextCtrl", "canUndo", 1}, // 1832
- {wxTextCtrl_Clear, "wxTextCtrl", "clear", 1}, // 1833
- {wxTextCtrl_Copy, "wxTextCtrl", "copy", 1}, // 1834
- {wxTextCtrl_Create, "wxTextCtrl", "create", 4}, // 1835
- {wxTextCtrl_Cut, "wxTextCtrl", "cut", 1}, // 1836
- {wxTextCtrl_DiscardEdits, "wxTextCtrl", "discardEdits", 1}, // 1837
- {wxTextCtrl_ChangeValue, "wxTextCtrl", "changeValue", 2}, // 1838
- {wxTextCtrl_EmulateKeyPress, "wxTextCtrl", "emulateKeyPress", 2}, // 1839
- {wxTextCtrl_GetDefaultStyle, "wxTextCtrl", "getDefaultStyle", 1}, // 1840
- {wxTextCtrl_GetInsertionPoint, "wxTextCtrl", "getInsertionPoint", 1}, // 1841
- {wxTextCtrl_GetLastPosition, "wxTextCtrl", "getLastPosition", 1}, // 1842
- {wxTextCtrl_GetLineLength, "wxTextCtrl", "getLineLength", 2}, // 1843
- {wxTextCtrl_GetLineText, "wxTextCtrl", "getLineText", 2}, // 1844
- {wxTextCtrl_GetNumberOfLines, "wxTextCtrl", "getNumberOfLines", 1}, // 1845
- {wxTextCtrl_GetRange, "wxTextCtrl", "getRange", 3}, // 1846
- {wxTextCtrl_GetSelection, "wxTextCtrl", "getSelection", 1}, // 1847
- {wxTextCtrl_GetStringSelection, "wxTextCtrl", "getStringSelection", 1}, // 1848
- {wxTextCtrl_GetStyle, "wxTextCtrl", "getStyle", 3}, // 1849
- {wxTextCtrl_GetValue, "wxTextCtrl", "getValue", 1}, // 1850
- {wxTextCtrl_IsEditable, "wxTextCtrl", "isEditable", 1}, // 1851
- {wxTextCtrl_IsModified, "wxTextCtrl", "isModified", 1}, // 1852
- {wxTextCtrl_IsMultiLine, "wxTextCtrl", "isMultiLine", 1}, // 1853
- {wxTextCtrl_IsSingleLine, "wxTextCtrl", "isSingleLine", 1}, // 1854
- {wxTextCtrl_LoadFile, "wxTextCtrl", "loadFile", 3}, // 1855
- {wxTextCtrl_MarkDirty, "wxTextCtrl", "markDirty", 1}, // 1856
- {wxTextCtrl_Paste, "wxTextCtrl", "paste", 1}, // 1857
- {wxTextCtrl_PositionToXY, "wxTextCtrl", "positionToXY", 2}, // 1858
- {wxTextCtrl_Redo, "wxTextCtrl", "redo", 1}, // 1859
- {wxTextCtrl_Remove, "wxTextCtrl", "remove", 3}, // 1860
- {wxTextCtrl_Replace, "wxTextCtrl", "replace", 4}, // 1861
- {wxTextCtrl_SaveFile, "wxTextCtrl", "saveFile", 2}, // 1862
- {wxTextCtrl_SetDefaultStyle, "wxTextCtrl", "setDefaultStyle", 2}, // 1863
- {wxTextCtrl_SetEditable, "wxTextCtrl", "setEditable", 2}, // 1864
- {wxTextCtrl_SetInsertionPoint, "wxTextCtrl", "setInsertionPoint", 2}, // 1865
- {wxTextCtrl_SetInsertionPointEnd, "wxTextCtrl", "setInsertionPointEnd", 1}, // 1866
- {wxTextCtrl_SetMaxLength, "wxTextCtrl", "setMaxLength", 2}, // 1867
- {wxTextCtrl_SetSelection, "wxTextCtrl", "setSelection", 3}, // 1868
- {wxTextCtrl_SetStyle, "wxTextCtrl", "setStyle", 4}, // 1869
- {wxTextCtrl_SetValue, "wxTextCtrl", "setValue", 2}, // 1870
- {wxTextCtrl_ShowPosition, "wxTextCtrl", "showPosition", 2}, // 1871
- {wxTextCtrl_Undo, "wxTextCtrl", "undo", 1}, // 1872
- {wxTextCtrl_WriteText, "wxTextCtrl", "writeText", 2}, // 1873
- {wxTextCtrl_XYToPosition, "wxTextCtrl", "xYToPosition", 3}, // 1874
- {wxBookCtrlBase_AddPage, "wxBookCtrlBase", "addPage", 4}, // 1875
- {wxBookCtrlBase_InsertPage, "wxBookCtrlBase", "insertPage", 5}, // 1876
- {wxBookCtrlBase_DeletePage, "wxBookCtrlBase", "deletePage", 2}, // 1877
- {wxBookCtrlBase_RemovePage, "wxBookCtrlBase", "removePage", 2}, // 1878
- {wxBookCtrlBase_DeleteAllPages, "wxBookCtrlBase", "deleteAllPages", 1}, // 1879
- {wxBookCtrlBase_GetPage, "wxBookCtrlBase", "getPage", 2}, // 1880
- {wxBookCtrlBase_GetPageCount, "wxBookCtrlBase", "getPageCount", 1}, // 1881
- {wxBookCtrlBase_GetCurrentPage, "wxBookCtrlBase", "getCurrentPage", 1}, // 1882
- {wxBookCtrlBase_AdvanceSelection, "wxBookCtrlBase", "advanceSelection", 2}, // 1883
- {wxBookCtrlBase_SetSelection, "wxBookCtrlBase", "setSelection", 2}, // 1884
- {wxBookCtrlBase_GetSelection, "wxBookCtrlBase", "getSelection", 1}, // 1885
- {wxBookCtrlBase_ChangeSelection, "wxBookCtrlBase", "changeSelection", 2}, // 1886
- {wxBookCtrlBase_HitTest, "wxBookCtrlBase", "hitTest", 2}, // 1887
- {wxBookCtrlBase_GetPageText, "wxBookCtrlBase", "getPageText", 2}, // 1888
- {wxBookCtrlBase_SetPageText, "wxBookCtrlBase", "setPageText", 3}, // 1889
- {wxNotebook_new_0, "wxNotebook", "new", 0}, // 1890
- {wxNotebook_new_3, "wxNotebook", "new", 3}, // 1891
- {NULL, "wxNotebook", "destroy", 1}, // 1892 obj destructor wxNotebook_destruct
- {wxNotebook_AssignImageList, "wxNotebook", "assignImageList", 2}, // 1893
- {wxNotebook_Create, "wxNotebook", "create", 4}, // 1894
- {wxNotebook_GetImageList, "wxNotebook", "getImageList", 1}, // 1895
- {wxNotebook_GetPageImage, "wxNotebook", "getPageImage", 2}, // 1896
- {wxNotebook_GetRowCount, "wxNotebook", "getRowCount", 1}, // 1897
- {wxNotebook_GetThemeBackgroundColour, "wxNotebook", "getThemeBackgroundColour", 1}, // 1898
- {wxNotebook_SetImageList, "wxNotebook", "setImageList", 2}, // 1899
- {wxNotebook_SetPadding, "wxNotebook", "setPadding", 2}, // 1900
- {wxNotebook_SetPageSize, "wxNotebook", "setPageSize", 2}, // 1901
- {wxNotebook_SetPageImage, "wxNotebook", "setPageImage", 3}, // 1902
- {wxChoicebook_new_0, "wxChoicebook", "new", 0}, // 1903
- {wxChoicebook_new_3, "wxChoicebook", "new", 3}, // 1904
- {wxChoicebook_AddPage, "wxChoicebook", "addPage", 4}, // 1905
- {wxChoicebook_AdvanceSelection, "wxChoicebook", "advanceSelection", 2}, // 1906
- {wxChoicebook_AssignImageList, "wxChoicebook", "assignImageList", 2}, // 1907
- {wxChoicebook_Create, "wxChoicebook", "create", 4}, // 1908
- {wxChoicebook_DeleteAllPages, "wxChoicebook", "deleteAllPages", 1}, // 1909
- {wxChoicebook_GetCurrentPage, "wxChoicebook", "getCurrentPage", 1}, // 1910
- {wxChoicebook_GetImageList, "wxChoicebook", "getImageList", 1}, // 1911
- {wxChoicebook_GetPage, "wxChoicebook", "getPage", 2}, // 1912
- {wxChoicebook_GetPageCount, "wxChoicebook", "getPageCount", 1}, // 1913
- {wxChoicebook_GetPageImage, "wxChoicebook", "getPageImage", 2}, // 1914
- {wxChoicebook_GetPageText, "wxChoicebook", "getPageText", 2}, // 1915
- {wxChoicebook_GetSelection, "wxChoicebook", "getSelection", 1}, // 1916
- {wxChoicebook_HitTest, "wxChoicebook", "hitTest", 2}, // 1917
- {wxChoicebook_InsertPage, "wxChoicebook", "insertPage", 5}, // 1918
- {wxChoicebook_SetImageList, "wxChoicebook", "setImageList", 2}, // 1919
- {wxChoicebook_SetPageSize, "wxChoicebook", "setPageSize", 2}, // 1920
- {wxChoicebook_SetPageImage, "wxChoicebook", "setPageImage", 3}, // 1921
- {wxChoicebook_SetPageText, "wxChoicebook", "setPageText", 3}, // 1922
- {wxChoicebook_SetSelection, "wxChoicebook", "setSelection", 2}, // 1923
- {wxChoicebook_ChangeSelection, "wxChoicebook", "changeSelection", 2}, // 1924
- {NULL, "wxChoicebook", "'Destroy'", 1}, // 1925 obj destructor wxChoicebook_destroy
- {wxToolbook_new_0, "wxToolbook", "new", 0}, // 1926
- {wxToolbook_new_3, "wxToolbook", "new", 3}, // 1927
- {wxToolbook_AddPage, "wxToolbook", "addPage", 4}, // 1928
- {wxToolbook_AdvanceSelection, "wxToolbook", "advanceSelection", 2}, // 1929
- {wxToolbook_AssignImageList, "wxToolbook", "assignImageList", 2}, // 1930
- {wxToolbook_Create, "wxToolbook", "create", 4}, // 1931
- {wxToolbook_DeleteAllPages, "wxToolbook", "deleteAllPages", 1}, // 1932
- {wxToolbook_GetCurrentPage, "wxToolbook", "getCurrentPage", 1}, // 1933
- {wxToolbook_GetImageList, "wxToolbook", "getImageList", 1}, // 1934
- {wxToolbook_GetPage, "wxToolbook", "getPage", 2}, // 1935
- {wxToolbook_GetPageCount, "wxToolbook", "getPageCount", 1}, // 1936
- {wxToolbook_GetPageImage, "wxToolbook", "getPageImage", 2}, // 1937
- {wxToolbook_GetPageText, "wxToolbook", "getPageText", 2}, // 1938
- {wxToolbook_GetSelection, "wxToolbook", "getSelection", 1}, // 1939
- {wxToolbook_HitTest, "wxToolbook", "hitTest", 2}, // 1940
- {wxToolbook_InsertPage, "wxToolbook", "insertPage", 5}, // 1941
- {wxToolbook_SetImageList, "wxToolbook", "setImageList", 2}, // 1942
- {wxToolbook_SetPageSize, "wxToolbook", "setPageSize", 2}, // 1943
- {wxToolbook_SetPageImage, "wxToolbook", "setPageImage", 3}, // 1944
- {wxToolbook_SetPageText, "wxToolbook", "setPageText", 3}, // 1945
- {wxToolbook_SetSelection, "wxToolbook", "setSelection", 2}, // 1946
- {wxToolbook_ChangeSelection, "wxToolbook", "changeSelection", 2}, // 1947
- {NULL, "wxToolbook", "'Destroy'", 1}, // 1948 obj destructor wxToolbook_destroy
- {wxListbook_new_0, "wxListbook", "new", 0}, // 1949
- {wxListbook_new_3, "wxListbook", "new", 3}, // 1950
- {wxListbook_AddPage, "wxListbook", "addPage", 4}, // 1951
- {wxListbook_AdvanceSelection, "wxListbook", "advanceSelection", 2}, // 1952
- {wxListbook_AssignImageList, "wxListbook", "assignImageList", 2}, // 1953
- {wxListbook_Create, "wxListbook", "create", 4}, // 1954
- {wxListbook_DeleteAllPages, "wxListbook", "deleteAllPages", 1}, // 1955
- {wxListbook_GetCurrentPage, "wxListbook", "getCurrentPage", 1}, // 1956
- {wxListbook_GetImageList, "wxListbook", "getImageList", 1}, // 1957
- {wxListbook_GetPage, "wxListbook", "getPage", 2}, // 1958
- {wxListbook_GetPageCount, "wxListbook", "getPageCount", 1}, // 1959
- {wxListbook_GetPageImage, "wxListbook", "getPageImage", 2}, // 1960
- {wxListbook_GetPageText, "wxListbook", "getPageText", 2}, // 1961
- {wxListbook_GetSelection, "wxListbook", "getSelection", 1}, // 1962
- {wxListbook_HitTest, "wxListbook", "hitTest", 2}, // 1963
- {wxListbook_InsertPage, "wxListbook", "insertPage", 5}, // 1964
- {wxListbook_SetImageList, "wxListbook", "setImageList", 2}, // 1965
- {wxListbook_SetPageSize, "wxListbook", "setPageSize", 2}, // 1966
- {wxListbook_SetPageImage, "wxListbook", "setPageImage", 3}, // 1967
- {wxListbook_SetPageText, "wxListbook", "setPageText", 3}, // 1968
- {wxListbook_SetSelection, "wxListbook", "setSelection", 2}, // 1969
- {wxListbook_ChangeSelection, "wxListbook", "changeSelection", 2}, // 1970
- {NULL, "wxListbook", "'Destroy'", 1}, // 1971 obj destructor wxListbook_destroy
- {wxTreebook_new_0, "wxTreebook", "new", 0}, // 1972
- {wxTreebook_new_3, "wxTreebook", "new", 3}, // 1973
- {NULL, "wxTreebook", "destroy", 1}, // 1974 obj destructor wxTreebook_destruct
- {wxTreebook_AddPage, "wxTreebook", "addPage", 4}, // 1975
- {wxTreebook_AdvanceSelection, "wxTreebook", "advanceSelection", 2}, // 1976
- {wxTreebook_AssignImageList, "wxTreebook", "assignImageList", 2}, // 1977
- {wxTreebook_Create, "wxTreebook", "create", 4}, // 1978
- {wxTreebook_DeleteAllPages, "wxTreebook", "deleteAllPages", 1}, // 1979
- {wxTreebook_GetCurrentPage, "wxTreebook", "getCurrentPage", 1}, // 1980
- {wxTreebook_GetImageList, "wxTreebook", "getImageList", 1}, // 1981
- {wxTreebook_GetPage, "wxTreebook", "getPage", 2}, // 1982
- {wxTreebook_GetPageCount, "wxTreebook", "getPageCount", 1}, // 1983
- {wxTreebook_GetPageImage, "wxTreebook", "getPageImage", 2}, // 1984
- {wxTreebook_GetPageText, "wxTreebook", "getPageText", 2}, // 1985
- {wxTreebook_GetSelection, "wxTreebook", "getSelection", 1}, // 1986
- {wxTreebook_ExpandNode, "wxTreebook", "expandNode", 3}, // 1987
- {wxTreebook_IsNodeExpanded, "wxTreebook", "isNodeExpanded", 2}, // 1988
- {wxTreebook_HitTest, "wxTreebook", "hitTest", 2}, // 1989
- {wxTreebook_InsertPage, "wxTreebook", "insertPage", 5}, // 1990
- {wxTreebook_InsertSubPage, "wxTreebook", "insertSubPage", 5}, // 1991
- {wxTreebook_SetImageList, "wxTreebook", "setImageList", 2}, // 1992
- {wxTreebook_SetPageSize, "wxTreebook", "setPageSize", 2}, // 1993
- {wxTreebook_SetPageImage, "wxTreebook", "setPageImage", 3}, // 1994
- {wxTreebook_SetPageText, "wxTreebook", "setPageText", 3}, // 1995
- {wxTreebook_SetSelection, "wxTreebook", "setSelection", 2}, // 1996
- {wxTreebook_ChangeSelection, "wxTreebook", "changeSelection", 2}, // 1997
- {wxTreeCtrl_new_0, "wxTreeCtrl", "new", 0}, // 1998
- {wxTreeCtrl_new_2, "wxTreeCtrl", "new", 2}, // 1999
- {NULL, "wxTreeCtrl", "destroy", 1}, // 2000 obj destructor wxTreeCtrl_destruct
- {wxTreeCtrl_AddRoot, "wxTreeCtrl", "addRoot", 3}, // 2001
- {wxTreeCtrl_AppendItem, "wxTreeCtrl", "appendItem", 4}, // 2002
- {wxTreeCtrl_AssignImageList, "wxTreeCtrl", "assignImageList", 2}, // 2003
- {wxTreeCtrl_AssignStateImageList, "wxTreeCtrl", "assignStateImageList", 2}, // 2004
- {wxTreeCtrl_Collapse, "wxTreeCtrl", "collapse", 2}, // 2005
- {wxTreeCtrl_CollapseAndReset, "wxTreeCtrl", "collapseAndReset", 2}, // 2006
- {wxTreeCtrl_Create, "wxTreeCtrl", "create", 3}, // 2007
- {wxTreeCtrl_Delete, "wxTreeCtrl", "delete", 2}, // 2008
- {wxTreeCtrl_DeleteAllItems, "wxTreeCtrl", "deleteAllItems", 1}, // 2009
- {wxTreeCtrl_DeleteChildren, "wxTreeCtrl", "deleteChildren", 2}, // 2010
- {wxTreeCtrl_EditLabel, "wxTreeCtrl", "editLabel", 2}, // 2011
- {wxTreeCtrl_EnsureVisible, "wxTreeCtrl", "ensureVisible", 2}, // 2012
- {wxTreeCtrl_Expand, "wxTreeCtrl", "expand", 2}, // 2013
- {wxTreeCtrl_GetBoundingRect, "wxTreeCtrl", "getBoundingRect", 3}, // 2014
- {wxTreeCtrl_GetChildrenCount, "wxTreeCtrl", "getChildrenCount", 3}, // 2015
- {wxTreeCtrl_GetCount, "wxTreeCtrl", "getCount", 1}, // 2016
- {wxTreeCtrl_GetEditControl, "wxTreeCtrl", "getEditControl", 1}, // 2017
- {wxTreeCtrl_GetFirstChild, "wxTreeCtrl", "getFirstChild", 2}, // 2018
- {wxTreeCtrl_GetNextChild, "wxTreeCtrl", "getNextChild", 3}, // 2019
- {wxTreeCtrl_GetFirstVisibleItem, "wxTreeCtrl", "getFirstVisibleItem", 1}, // 2020
- {wxTreeCtrl_GetImageList, "wxTreeCtrl", "getImageList", 1}, // 2021
- {wxTreeCtrl_GetIndent, "wxTreeCtrl", "getIndent", 1}, // 2022
- {wxTreeCtrl_GetItemBackgroundColour, "wxTreeCtrl", "getItemBackgroundColour", 2}, // 2023
- {wxTreeCtrl_GetItemData, "wxTreeCtrl", "getItemData", 2}, // 2024
- {wxTreeCtrl_GetItemFont, "wxTreeCtrl", "getItemFont", 2}, // 2025
- {wxTreeCtrl_GetItemImage, "wxTreeCtrl", "getItemImage", 3}, // 2026
- {wxTreeCtrl_GetItemText, "wxTreeCtrl", "getItemText", 2}, // 2027
- {wxTreeCtrl_GetItemTextColour, "wxTreeCtrl", "getItemTextColour", 2}, // 2028
- {wxTreeCtrl_GetLastChild, "wxTreeCtrl", "getLastChild", 2}, // 2029
- {wxTreeCtrl_GetNextSibling, "wxTreeCtrl", "getNextSibling", 2}, // 2030
- {wxTreeCtrl_GetNextVisible, "wxTreeCtrl", "getNextVisible", 2}, // 2031
- {wxTreeCtrl_GetItemParent, "wxTreeCtrl", "getItemParent", 2}, // 2032
- {wxTreeCtrl_GetPrevSibling, "wxTreeCtrl", "getPrevSibling", 2}, // 2033
- {wxTreeCtrl_GetPrevVisible, "wxTreeCtrl", "getPrevVisible", 2}, // 2034
- {wxTreeCtrl_GetRootItem, "wxTreeCtrl", "getRootItem", 1}, // 2035
- {wxTreeCtrl_GetSelection, "wxTreeCtrl", "getSelection", 1}, // 2036
- {wxTreeCtrl_GetSelections, "wxTreeCtrl", "getSelections", 1}, // 2037
- {wxTreeCtrl_GetStateImageList, "wxTreeCtrl", "getStateImageList", 1}, // 2038
- {wxTreeCtrl_HitTest, "wxTreeCtrl", "hitTest", 2}, // 2039
- {wxTreeCtrl_InsertItem, "wxTreeCtrl", "insertItem", 5}, // 2040
- {NULL, "", "", 0}, // 2041
- {wxTreeCtrl_IsBold, "wxTreeCtrl", "isBold", 2}, // 2042
- {wxTreeCtrl_IsExpanded, "wxTreeCtrl", "isExpanded", 2}, // 2043
- {wxTreeCtrl_IsSelected, "wxTreeCtrl", "isSelected", 2}, // 2044
- {wxTreeCtrl_IsVisible, "wxTreeCtrl", "isVisible", 2}, // 2045
- {wxTreeCtrl_ItemHasChildren, "wxTreeCtrl", "itemHasChildren", 2}, // 2046
- {wxTreeCtrl_IsTreeItemIdOk, "wxTreeCtrl", "isTreeItemIdOk", 1}, // 2047
- {wxTreeCtrl_PrependItem, "wxTreeCtrl", "prependItem", 4}, // 2048
- {wxTreeCtrl_ScrollTo, "wxTreeCtrl", "scrollTo", 2}, // 2049
- {wxTreeCtrl_SelectItem, "wxTreeCtrl", "selectItem", 3}, // 2050
- {wxTreeCtrl_SetIndent, "wxTreeCtrl", "setIndent", 2}, // 2051
- {wxTreeCtrl_SetImageList, "wxTreeCtrl", "setImageList", 2}, // 2052
- {wxTreeCtrl_SetItemBackgroundColour, "wxTreeCtrl", "setItemBackgroundColour", 3}, // 2053
- {wxTreeCtrl_SetItemBold, "wxTreeCtrl", "setItemBold", 3}, // 2054
- {wxTreeCtrl_SetItemData, "wxTreeCtrl", "setItemData", 3}, // 2055
- {wxTreeCtrl_SetItemDropHighlight, "wxTreeCtrl", "setItemDropHighlight", 3}, // 2056
- {wxTreeCtrl_SetItemFont, "wxTreeCtrl", "setItemFont", 3}, // 2057
- {wxTreeCtrl_SetItemHasChildren, "wxTreeCtrl", "setItemHasChildren", 3}, // 2058
- {wxTreeCtrl_SetItemImage, "wxTreeCtrl", "setItemImage", 4}, // 2059
- {wxTreeCtrl_SetItemText, "wxTreeCtrl", "setItemText", 3}, // 2060
- {wxTreeCtrl_SetItemTextColour, "wxTreeCtrl", "setItemTextColour", 3}, // 2061
- {wxTreeCtrl_SetStateImageList, "wxTreeCtrl", "setStateImageList", 2}, // 2062
- {wxTreeCtrl_SetWindowStyle, "wxTreeCtrl", "setWindowStyle", 2}, // 2063
- {wxTreeCtrl_SortChildren, "wxTreeCtrl", "sortChildren", 2}, // 2064
- {wxTreeCtrl_Toggle, "wxTreeCtrl", "toggle", 2}, // 2065
- {wxTreeCtrl_ToggleItemSelection, "wxTreeCtrl", "toggleItemSelection", 2}, // 2066
- {wxTreeCtrl_Unselect, "wxTreeCtrl", "unselect", 1}, // 2067
- {wxTreeCtrl_UnselectAll, "wxTreeCtrl", "unselectAll", 1}, // 2068
- {wxTreeCtrl_UnselectItem, "wxTreeCtrl", "unselectItem", 2}, // 2069
- {wxScrollBar_new_0, "wxScrollBar", "new", 0}, // 2070
- {wxScrollBar_new_3, "wxScrollBar", "new", 3}, // 2071
- {NULL, "wxScrollBar", "destroy", 1}, // 2072 obj destructor wxScrollBar_destruct
- {wxScrollBar_Create, "wxScrollBar", "create", 4}, // 2073
- {wxScrollBar_GetRange, "wxScrollBar", "getRange", 1}, // 2074
- {wxScrollBar_GetPageSize, "wxScrollBar", "getPageSize", 1}, // 2075
- {wxScrollBar_GetThumbPosition, "wxScrollBar", "getThumbPosition", 1}, // 2076
- {wxScrollBar_GetThumbSize, "wxScrollBar", "getThumbSize", 1}, // 2077
- {wxScrollBar_SetThumbPosition, "wxScrollBar", "setThumbPosition", 2}, // 2078
- {wxScrollBar_SetScrollbar, "wxScrollBar", "setScrollbar", 6}, // 2079
- {wxSpinButton_new_0, "wxSpinButton", "new", 0}, // 2080
- {wxSpinButton_new_2, "wxSpinButton", "new", 2}, // 2081
- {NULL, "wxSpinButton", "destroy", 1}, // 2082 obj destructor wxSpinButton_destruct
- {wxSpinButton_Create, "wxSpinButton", "create", 3}, // 2083
- {wxSpinButton_GetMax, "wxSpinButton", "getMax", 1}, // 2084
- {wxSpinButton_GetMin, "wxSpinButton", "getMin", 1}, // 2085
- {wxSpinButton_GetValue, "wxSpinButton", "getValue", 1}, // 2086
- {wxSpinButton_SetRange, "wxSpinButton", "setRange", 3}, // 2087
- {wxSpinButton_SetValue, "wxSpinButton", "setValue", 2}, // 2088
- {wxSpinCtrl_new_0, "wxSpinCtrl", "new", 0}, // 2089
- {wxSpinCtrl_new_2, "wxSpinCtrl", "new", 2}, // 2090
- {wxSpinCtrl_Create, "wxSpinCtrl", "create", 3}, // 2091
- {wxSpinCtrl_SetValue_1_1, "wxSpinCtrl", "setValue", 2}, // 2092
- {wxSpinCtrl_SetValue_1_0, "wxSpinCtrl", "setValue", 2}, // 2093
- {wxSpinCtrl_GetValue, "wxSpinCtrl", "getValue", 1}, // 2094
- {wxSpinCtrl_SetRange, "wxSpinCtrl", "setRange", 3}, // 2095
- {wxSpinCtrl_SetSelection, "wxSpinCtrl", "setSelection", 3}, // 2096
- {wxSpinCtrl_GetMin, "wxSpinCtrl", "getMin", 1}, // 2097
- {wxSpinCtrl_GetMax, "wxSpinCtrl", "getMax", 1}, // 2098
- {NULL, "wxSpinCtrl", "'Destroy'", 1}, // 2099 obj destructor wxSpinCtrl_destroy
- {wxStaticText_new_0, "wxStaticText", "new", 0}, // 2100
- {wxStaticText_new_4, "wxStaticText", "new", 4}, // 2101
- {wxStaticText_Create, "wxStaticText", "create", 5}, // 2102
- {wxStaticText_GetLabel, "wxStaticText", "getLabel", 1}, // 2103
- {wxStaticText_SetLabel, "wxStaticText", "setLabel", 2}, // 2104
- {wxStaticText_Wrap, "wxStaticText", "wrap", 2}, // 2105
- {NULL, "wxStaticText", "'Destroy'", 1}, // 2106 obj destructor wxStaticText_destroy
- {wxStaticBitmap_new_0, "wxStaticBitmap", "new", 0}, // 2107
- {wxStaticBitmap_new_4, "wxStaticBitmap", "new", 4}, // 2108
- {wxStaticBitmap_Create, "wxStaticBitmap", "create", 5}, // 2109
- {wxStaticBitmap_GetBitmap, "wxStaticBitmap", "getBitmap", 1}, // 2110
- {wxStaticBitmap_SetBitmap, "wxStaticBitmap", "setBitmap", 2}, // 2111
- {NULL, "wxStaticBitmap", "'Destroy'", 1}, // 2112 obj destructor wxStaticBitmap_destroy
- {wxRadioBox_new, "wxRadioBox", "new", 7}, // 2113
- {NULL, "wxRadioBox", "destroy", 1}, // 2114 obj destructor wxRadioBox_destruct
- {wxRadioBox_Create, "wxRadioBox", "create", 8}, // 2115
- {wxRadioBox_Enable_1, "wxRadioBox", "enable", 2}, // 2116
- {wxRadioBox_Enable_2, "wxRadioBox", "enable", 3}, // 2117
- {wxRadioBox_GetSelection, "wxRadioBox", "getSelection", 1}, // 2118
- {wxRadioBox_GetString, "wxRadioBox", "getString", 2}, // 2119
- {wxRadioBox_SetSelection, "wxRadioBox", "setSelection", 2}, // 2120
- {wxRadioBox_Show, "wxRadioBox", "show", 3}, // 2121
- {wxRadioBox_GetColumnCount, "wxRadioBox", "getColumnCount", 1}, // 2122
- {wxRadioBox_GetItemHelpText, "wxRadioBox", "getItemHelpText", 2}, // 2123
- {wxRadioBox_GetItemToolTip, "wxRadioBox", "getItemToolTip", 2}, // 2124
- {wxRadioBox_GetItemFromPoint, "wxRadioBox", "getItemFromPoint", 2}, // 2125
- {wxRadioBox_GetRowCount, "wxRadioBox", "getRowCount", 1}, // 2126
- {wxRadioBox_IsItemEnabled, "wxRadioBox", "isItemEnabled", 2}, // 2127
- {wxRadioBox_IsItemShown, "wxRadioBox", "isItemShown", 2}, // 2128
- {wxRadioBox_SetItemHelpText, "wxRadioBox", "setItemHelpText", 3}, // 2129
- {wxRadioBox_SetItemToolTip, "wxRadioBox", "setItemToolTip", 3}, // 2130
- {wxRadioButton_new_0, "wxRadioButton", "new", 0}, // 2131
- {wxRadioButton_new_4, "wxRadioButton", "new", 4}, // 2132
- {NULL, "wxRadioButton", "destroy", 1}, // 2133 obj destructor wxRadioButton_destruct
- {wxRadioButton_Create, "wxRadioButton", "create", 5}, // 2134
- {wxRadioButton_GetValue, "wxRadioButton", "getValue", 1}, // 2135
- {wxRadioButton_SetValue, "wxRadioButton", "setValue", 2}, // 2136
- {wxSlider_new_0, "wxSlider", "new", 0}, // 2137
- {wxSlider_new_6, "wxSlider", "new", 6}, // 2138
- {NULL, "wxSlider", "destroy", 1}, // 2139 obj destructor wxSlider_destruct
- {wxSlider_Create, "wxSlider", "create", 7}, // 2140
- {wxSlider_GetLineSize, "wxSlider", "getLineSize", 1}, // 2141
- {wxSlider_GetMax, "wxSlider", "getMax", 1}, // 2142
- {wxSlider_GetMin, "wxSlider", "getMin", 1}, // 2143
- {wxSlider_GetPageSize, "wxSlider", "getPageSize", 1}, // 2144
- {wxSlider_GetThumbLength, "wxSlider", "getThumbLength", 1}, // 2145
- {wxSlider_GetValue, "wxSlider", "getValue", 1}, // 2146
- {wxSlider_SetLineSize, "wxSlider", "setLineSize", 2}, // 2147
- {wxSlider_SetPageSize, "wxSlider", "setPageSize", 2}, // 2148
- {wxSlider_SetRange, "wxSlider", "setRange", 3}, // 2149
- {wxSlider_SetThumbLength, "wxSlider", "setThumbLength", 2}, // 2150
- {wxSlider_SetValue, "wxSlider", "setValue", 2}, // 2151
- {wxDialog_new_0, "wxDialog", "new", 0}, // 2152
- {wxDialog_new_4, "wxDialog", "new", 4}, // 2153
- {NULL, "wxDialog", "destroy", 1}, // 2154 obj destructor wxDialog_destruct
- {wxDialog_Create, "wxDialog", "create", 5}, // 2155
- {wxDialog_CreateButtonSizer, "wxDialog", "createButtonSizer", 2}, // 2156
- {wxDialog_CreateStdDialogButtonSizer, "wxDialog", "createStdDialogButtonSizer", 2}, // 2157
- {wxDialog_EndModal, "wxDialog", "endModal", 2}, // 2158
- {wxDialog_GetAffirmativeId, "wxDialog", "getAffirmativeId", 1}, // 2159
- {wxDialog_GetReturnCode, "wxDialog", "getReturnCode", 1}, // 2160
- {wxDialog_IsModal, "wxDialog", "isModal", 1}, // 2161
- {wxDialog_SetAffirmativeId, "wxDialog", "setAffirmativeId", 2}, // 2162
- {wxDialog_SetReturnCode, "wxDialog", "setReturnCode", 2}, // 2163
- {wxDialog_Show, "wxDialog", "show", 2}, // 2164
- {wxDialog_ShowModal, "wxDialog", "showModal", 1}, // 2165
- {wxColourDialog_new_0, "wxColourDialog", "new", 0}, // 2166
- {wxColourDialog_new_2, "wxColourDialog", "new", 2}, // 2167
- {NULL, "wxColourDialog", "destroy", 1}, // 2168 obj destructor wxColourDialog_destruct
- {wxColourDialog_Create, "wxColourDialog", "create", 3}, // 2169
- {wxColourDialog_GetColourData, "wxColourDialog", "getColourData", 1}, // 2170
- {wxColourData_new, "wxColourData", "new", 0}, // 2171
- {NULL, "wxColourData", "destroy", 1}, // 2172 obj destructor wxColourData_destruct
- {wxColourData_GetChooseFull, "wxColourData", "getChooseFull", 1}, // 2173
- {wxColourData_GetColour, "wxColourData", "getColour", 1}, // 2174
- {wxColourData_GetCustomColour, "wxColourData", "getCustomColour", 2}, // 2175
- {wxColourData_SetChooseFull, "wxColourData", "setChooseFull", 2}, // 2176
- {wxColourData_SetColour, "wxColourData", "setColour", 2}, // 2177
- {wxColourData_SetCustomColour, "wxColourData", "setCustomColour", 3}, // 2178
- {wxPalette_new_0, "wxPalette", "new", 0}, // 2179
- {wxPalette_new_1, "wxPalette", "new", 1}, // 2180
- {wxPalette_new_4, "wxPalette", "new", 3}, // 2181
- {NULL, "wxPalette", "destroy", 1}, // 2182 obj destructor wxPalette_destruct
- {wxPalette_Create, "wxPalette", "create", 4}, // 2183
- {wxPalette_GetColoursCount, "wxPalette", "getColoursCount", 1}, // 2184
- {wxPalette_GetPixel, "wxPalette", "getPixel", 4}, // 2185
- {wxPalette_GetRGB, "wxPalette", "getRGB", 2}, // 2186
- {wxPalette_IsOk, "wxPalette", "isOk", 1}, // 2187
- {wxDirDialog_new, "wxDirDialog", "new", 2}, // 2188
- {NULL, "wxDirDialog", "destroy", 1}, // 2189 obj destructor wxDirDialog_destruct
- {wxDirDialog_GetPath, "wxDirDialog", "getPath", 1}, // 2190
- {wxDirDialog_GetMessage, "wxDirDialog", "getMessage", 1}, // 2191
- {wxDirDialog_SetMessage, "wxDirDialog", "setMessage", 2}, // 2192
- {wxDirDialog_SetPath, "wxDirDialog", "setPath", 2}, // 2193
- {wxFileDialog_new, "wxFileDialog", "new", 2}, // 2194
- {NULL, "wxFileDialog", "destroy", 1}, // 2195 obj destructor wxFileDialog_destruct
- {wxFileDialog_GetDirectory, "wxFileDialog", "getDirectory", 1}, // 2196
- {wxFileDialog_GetFilename, "wxFileDialog", "getFilename", 1}, // 2197
- {wxFileDialog_GetFilenames, "wxFileDialog", "getFilenames", 1}, // 2198
- {wxFileDialog_GetFilterIndex, "wxFileDialog", "getFilterIndex", 1}, // 2199
- {wxFileDialog_GetMessage, "wxFileDialog", "getMessage", 1}, // 2200
- {wxFileDialog_GetPath, "wxFileDialog", "getPath", 1}, // 2201
- {wxFileDialog_GetPaths, "wxFileDialog", "getPaths", 1}, // 2202
- {wxFileDialog_GetWildcard, "wxFileDialog", "getWildcard", 1}, // 2203
- {wxFileDialog_SetDirectory, "wxFileDialog", "setDirectory", 2}, // 2204
- {wxFileDialog_SetFilename, "wxFileDialog", "setFilename", 2}, // 2205
- {wxFileDialog_SetFilterIndex, "wxFileDialog", "setFilterIndex", 2}, // 2206
- {wxFileDialog_SetMessage, "wxFileDialog", "setMessage", 2}, // 2207
- {wxFileDialog_SetPath, "wxFileDialog", "setPath", 2}, // 2208
- {wxFileDialog_SetWildcard, "wxFileDialog", "setWildcard", 2}, // 2209
- {wxPickerBase_SetInternalMargin, "wxPickerBase", "setInternalMargin", 2}, // 2210
- {wxPickerBase_GetInternalMargin, "wxPickerBase", "getInternalMargin", 1}, // 2211
- {wxPickerBase_SetTextCtrlProportion, "wxPickerBase", "setTextCtrlProportion", 2}, // 2212
- {wxPickerBase_SetPickerCtrlProportion, "wxPickerBase", "setPickerCtrlProportion", 2}, // 2213
- {wxPickerBase_GetTextCtrlProportion, "wxPickerBase", "getTextCtrlProportion", 1}, // 2214
- {wxPickerBase_GetPickerCtrlProportion, "wxPickerBase", "getPickerCtrlProportion", 1}, // 2215
- {wxPickerBase_HasTextCtrl, "wxPickerBase", "hasTextCtrl", 1}, // 2216
- {wxPickerBase_GetTextCtrl, "wxPickerBase", "getTextCtrl", 1}, // 2217
- {wxPickerBase_IsTextCtrlGrowable, "wxPickerBase", "isTextCtrlGrowable", 1}, // 2218
- {wxPickerBase_SetPickerCtrlGrowable, "wxPickerBase", "setPickerCtrlGrowable", 2}, // 2219
- {wxPickerBase_SetTextCtrlGrowable, "wxPickerBase", "setTextCtrlGrowable", 2}, // 2220
- {wxPickerBase_IsPickerCtrlGrowable, "wxPickerBase", "isPickerCtrlGrowable", 1}, // 2221
- {wxFilePickerCtrl_new_0, "wxFilePickerCtrl", "new", 0}, // 2222
- {wxFilePickerCtrl_new_3, "wxFilePickerCtrl", "new", 3}, // 2223
- {wxFilePickerCtrl_Create, "wxFilePickerCtrl", "create", 4}, // 2224
- {wxFilePickerCtrl_GetPath, "wxFilePickerCtrl", "getPath", 1}, // 2225
- {wxFilePickerCtrl_SetPath, "wxFilePickerCtrl", "setPath", 2}, // 2226
- {NULL, "wxFilePickerCtrl", "'Destroy'", 1}, // 2227 obj destructor wxFilePickerCtrl_destroy
- {wxDirPickerCtrl_new_0, "wxDirPickerCtrl", "new", 0}, // 2228
- {wxDirPickerCtrl_new_3, "wxDirPickerCtrl", "new", 3}, // 2229
- {wxDirPickerCtrl_Create, "wxDirPickerCtrl", "create", 4}, // 2230
- {wxDirPickerCtrl_GetPath, "wxDirPickerCtrl", "getPath", 1}, // 2231
- {wxDirPickerCtrl_SetPath, "wxDirPickerCtrl", "setPath", 2}, // 2232
- {NULL, "wxDirPickerCtrl", "'Destroy'", 1}, // 2233 obj destructor wxDirPickerCtrl_destroy
- {wxColourPickerCtrl_new_0, "wxColourPickerCtrl", "new", 0}, // 2234
- {wxColourPickerCtrl_new_3, "wxColourPickerCtrl", "new", 3}, // 2235
- {wxColourPickerCtrl_Create, "wxColourPickerCtrl", "create", 4}, // 2236
- {wxColourPickerCtrl_GetColour, "wxColourPickerCtrl", "getColour", 1}, // 2237
- {wxColourPickerCtrl_SetColour_1_1, "wxColourPickerCtrl", "setColour", 2}, // 2238
- {wxColourPickerCtrl_SetColour_1_0, "wxColourPickerCtrl", "setColour", 2}, // 2239
- {NULL, "wxColourPickerCtrl", "'Destroy'", 1}, // 2240 obj destructor wxColourPickerCtrl_destroy
- {wxDatePickerCtrl_new_0, "wxDatePickerCtrl", "new", 0}, // 2241
- {wxDatePickerCtrl_new_3, "wxDatePickerCtrl", "new", 3}, // 2242
- {wxDatePickerCtrl_GetRange, "wxDatePickerCtrl", "getRange", 3}, // 2243
- {wxDatePickerCtrl_GetValue, "wxDatePickerCtrl", "getValue", 1}, // 2244
- {wxDatePickerCtrl_SetRange, "wxDatePickerCtrl", "setRange", 3}, // 2245
- {wxDatePickerCtrl_SetValue, "wxDatePickerCtrl", "setValue", 2}, // 2246
- {NULL, "wxDatePickerCtrl", "'Destroy'", 1}, // 2247 obj destructor wxDatePickerCtrl_destroy
- {wxFontPickerCtrl_new_0, "wxFontPickerCtrl", "new", 0}, // 2248
- {wxFontPickerCtrl_new_3, "wxFontPickerCtrl", "new", 3}, // 2249
- {wxFontPickerCtrl_Create, "wxFontPickerCtrl", "create", 4}, // 2250
- {wxFontPickerCtrl_GetSelectedFont, "wxFontPickerCtrl", "getSelectedFont", 1}, // 2251
- {wxFontPickerCtrl_SetSelectedFont, "wxFontPickerCtrl", "setSelectedFont", 2}, // 2252
- {wxFontPickerCtrl_GetMaxPointSize, "wxFontPickerCtrl", "getMaxPointSize", 1}, // 2253
- {wxFontPickerCtrl_SetMaxPointSize, "wxFontPickerCtrl", "setMaxPointSize", 2}, // 2254
- {NULL, "wxFontPickerCtrl", "'Destroy'", 1}, // 2255 obj destructor wxFontPickerCtrl_destroy
- {wxFindReplaceDialog_new_0, "wxFindReplaceDialog", "new", 0}, // 2256
- {wxFindReplaceDialog_new_4, "wxFindReplaceDialog", "new", 4}, // 2257
- {NULL, "wxFindReplaceDialog", "destroy", 1}, // 2258 obj destructor wxFindReplaceDialog_destruct
- {wxFindReplaceDialog_Create, "wxFindReplaceDialog", "create", 5}, // 2259
- {wxFindReplaceDialog_GetData, "wxFindReplaceDialog", "getData", 1}, // 2260
- {wxFindReplaceData_new, "wxFindReplaceData", "new", 1}, // 2261
- {wxFindReplaceData_GetFindString, "wxFindReplaceData", "getFindString", 1}, // 2262
- {wxFindReplaceData_GetReplaceString, "wxFindReplaceData", "getReplaceString", 1}, // 2263
- {wxFindReplaceData_GetFlags, "wxFindReplaceData", "getFlags", 1}, // 2264
- {wxFindReplaceData_SetFlags, "wxFindReplaceData", "setFlags", 2}, // 2265
- {wxFindReplaceData_SetFindString, "wxFindReplaceData", "setFindString", 2}, // 2266
- {wxFindReplaceData_SetReplaceString, "wxFindReplaceData", "setReplaceString", 2}, // 2267
- {NULL, "wxFindReplaceData", "'Destroy'", 1}, // 2268 obj destructor wxFindReplaceData_destroy
- {NULL, "", "", 0}, // 2269
- {wxMultiChoiceDialog_new, "wxMultiChoiceDialog", "new", 5}, // 2270
- {wxMultiChoiceDialog_GetSelections, "wxMultiChoiceDialog", "getSelections", 1}, // 2271
- {wxMultiChoiceDialog_SetSelections, "wxMultiChoiceDialog", "setSelections", 2}, // 2272
- {NULL, "wxMultiChoiceDialog", "'Destroy'", 1}, // 2273 obj destructor wxMultiChoiceDialog_destroy
- {NULL, "", "", 0}, // 2274
- {wxSingleChoiceDialog_new, "wxSingleChoiceDialog", "new", 5}, // 2275
- {wxSingleChoiceDialog_GetSelection, "wxSingleChoiceDialog", "getSelection", 1}, // 2276
- {wxSingleChoiceDialog_GetStringSelection, "wxSingleChoiceDialog", "getStringSelection", 1}, // 2277
- {wxSingleChoiceDialog_SetSelection, "wxSingleChoiceDialog", "setSelection", 2}, // 2278
- {NULL, "wxSingleChoiceDialog", "'Destroy'", 1}, // 2279 obj destructor wxSingleChoiceDialog_destroy
- {wxTextEntryDialog_new_0, "wxTextEntryDialog", "new", 0}, // 2280
- {wxTextEntryDialog_new_3, "wxTextEntryDialog", "new", 3}, // 2281
- {NULL, "wxTextEntryDialog", "destroy", 1}, // 2282 obj destructor wxTextEntryDialog_destruct
- {wxTextEntryDialog_GetValue, "wxTextEntryDialog", "getValue", 1}, // 2283
- {wxTextEntryDialog_SetValue, "wxTextEntryDialog", "setValue", 2}, // 2284
- {wxPasswordEntryDialog_new, "wxPasswordEntryDialog", "new", 3}, // 2285
- {NULL, "wxPasswordEntryDialog", "'Destroy'", 1}, // 2286 obj destructor wxPasswordEntryDialog_destroy
- {wxFontData_new_0, "wxFontData", "new", 0}, // 2287
- {wxFontData_new_1, "wxFontData", "new", 1}, // 2288
- {wxFontData_EnableEffects, "wxFontData", "enableEffects", 2}, // 2289
- {wxFontData_GetAllowSymbols, "wxFontData", "getAllowSymbols", 1}, // 2290
- {wxFontData_GetColour, "wxFontData", "getColour", 1}, // 2291
- {wxFontData_GetChosenFont, "wxFontData", "getChosenFont", 1}, // 2292
- {wxFontData_GetEnableEffects, "wxFontData", "getEnableEffects", 1}, // 2293
- {wxFontData_GetInitialFont, "wxFontData", "getInitialFont", 1}, // 2294
- {wxFontData_GetShowHelp, "wxFontData", "getShowHelp", 1}, // 2295
- {wxFontData_SetAllowSymbols, "wxFontData", "setAllowSymbols", 2}, // 2296
- {wxFontData_SetChosenFont, "wxFontData", "setChosenFont", 2}, // 2297
- {wxFontData_SetColour, "wxFontData", "setColour", 2}, // 2298
- {wxFontData_SetInitialFont, "wxFontData", "setInitialFont", 2}, // 2299
- {wxFontData_SetRange, "wxFontData", "setRange", 3}, // 2300
- {wxFontData_SetShowHelp, "wxFontData", "setShowHelp", 2}, // 2301
- {NULL, "wxFontData", "'Destroy'", 1}, // 2302 obj destructor wxFontData_destroy
- {wxFontDialog_new_0, "wxFontDialog", "new", 0}, // 2303
- {NULL, "", "", 0}, // 2304
- {wxFontDialog_new_2, "wxFontDialog", "new", 2}, // 2305
+ {wxCalendarCtrl_EnableMonthChange, "wxCalendarCtrl", "enableMonthChange", 2}, // 1509
+ {wxCalendarCtrl_EnableHolidayDisplay, "wxCalendarCtrl", "enableHolidayDisplay", 2}, // 1510
+ {wxCalendarCtrl_SetHeaderColours, "wxCalendarCtrl", "setHeaderColours", 3}, // 1511
+ {wxCalendarCtrl_GetHeaderColourFg, "wxCalendarCtrl", "getHeaderColourFg", 1}, // 1512
+ {wxCalendarCtrl_GetHeaderColourBg, "wxCalendarCtrl", "getHeaderColourBg", 1}, // 1513
+ {wxCalendarCtrl_SetHighlightColours, "wxCalendarCtrl", "setHighlightColours", 3}, // 1514
+ {wxCalendarCtrl_GetHighlightColourFg, "wxCalendarCtrl", "getHighlightColourFg", 1}, // 1515
+ {wxCalendarCtrl_GetHighlightColourBg, "wxCalendarCtrl", "getHighlightColourBg", 1}, // 1516
+ {wxCalendarCtrl_SetHolidayColours, "wxCalendarCtrl", "setHolidayColours", 3}, // 1517
+ {wxCalendarCtrl_GetHolidayColourFg, "wxCalendarCtrl", "getHolidayColourFg", 1}, // 1518
+ {wxCalendarCtrl_GetHolidayColourBg, "wxCalendarCtrl", "getHolidayColourBg", 1}, // 1519
+ {wxCalendarCtrl_GetAttr, "wxCalendarCtrl", "getAttr", 2}, // 1520
+ {wxCalendarCtrl_SetAttr, "wxCalendarCtrl", "setAttr", 3}, // 1521
+ {wxCalendarCtrl_SetHoliday, "wxCalendarCtrl", "setHoliday", 2}, // 1522
+ {wxCalendarCtrl_ResetAttr, "wxCalendarCtrl", "resetAttr", 2}, // 1523
+ {wxCalendarCtrl_HitTest, "wxCalendarCtrl", "hitTest", 2}, // 1524
+ {wxCalendarDateAttr_new_1, "wxCalendarDateAttr", "new", 1}, // 1525
+ {wxCalendarDateAttr_new_2, "wxCalendarDateAttr", "new", 2}, // 1526
+ {wxCalendarDateAttr_SetTextColour, "wxCalendarDateAttr", "setTextColour", 2}, // 1527
+ {wxCalendarDateAttr_SetBackgroundColour, "wxCalendarDateAttr", "setBackgroundColour", 2}, // 1528
+ {wxCalendarDateAttr_SetBorderColour, "wxCalendarDateAttr", "setBorderColour", 2}, // 1529
+ {wxCalendarDateAttr_SetFont, "wxCalendarDateAttr", "setFont", 2}, // 1530
+ {wxCalendarDateAttr_SetBorder, "wxCalendarDateAttr", "setBorder", 2}, // 1531
+ {wxCalendarDateAttr_SetHoliday, "wxCalendarDateAttr", "setHoliday", 2}, // 1532
+ {wxCalendarDateAttr_HasTextColour, "wxCalendarDateAttr", "hasTextColour", 1}, // 1533
+ {wxCalendarDateAttr_HasBackgroundColour, "wxCalendarDateAttr", "hasBackgroundColour", 1}, // 1534
+ {wxCalendarDateAttr_HasBorderColour, "wxCalendarDateAttr", "hasBorderColour", 1}, // 1535
+ {wxCalendarDateAttr_HasFont, "wxCalendarDateAttr", "hasFont", 1}, // 1536
+ {wxCalendarDateAttr_HasBorder, "wxCalendarDateAttr", "hasBorder", 1}, // 1537
+ {wxCalendarDateAttr_IsHoliday, "wxCalendarDateAttr", "isHoliday", 1}, // 1538
+ {wxCalendarDateAttr_GetTextColour, "wxCalendarDateAttr", "getTextColour", 1}, // 1539
+ {wxCalendarDateAttr_GetBackgroundColour, "wxCalendarDateAttr", "getBackgroundColour", 1}, // 1540
+ {wxCalendarDateAttr_GetBorderColour, "wxCalendarDateAttr", "getBorderColour", 1}, // 1541
+ {wxCalendarDateAttr_GetFont, "wxCalendarDateAttr", "getFont", 1}, // 1542
+ {wxCalendarDateAttr_GetBorder, "wxCalendarDateAttr", "getBorder", 1}, // 1543
+ {wxCalendarDateAttr_destroy, "wxCalendarDateAttr", "'Destroy'", 1}, // 1544
+ {wxCheckBox_new_0, "wxCheckBox", "new", 0}, // 1545
+ {wxCheckBox_new_4, "wxCheckBox", "new", 4}, // 1546
+ {NULL, "wxCheckBox", "destroy", 1}, // 1547 obj destructor wxCheckBox_destruct
+ {wxCheckBox_Create, "wxCheckBox", "create", 5}, // 1548
+ {wxCheckBox_GetValue, "wxCheckBox", "getValue", 1}, // 1549
+ {wxCheckBox_Get3StateValue, "wxCheckBox", "get3StateValue", 1}, // 1550
+ {wxCheckBox_Is3rdStateAllowedForUser, "wxCheckBox", "is3rdStateAllowedForUser", 1}, // 1551
+ {wxCheckBox_Is3State, "wxCheckBox", "is3State", 1}, // 1552
+ {wxCheckBox_IsChecked, "wxCheckBox", "isChecked", 1}, // 1553
+ {wxCheckBox_SetValue, "wxCheckBox", "setValue", 2}, // 1554
+ {wxCheckBox_Set3StateValue, "wxCheckBox", "set3StateValue", 2}, // 1555
+ {wxCheckListBox_new_0, "wxCheckListBox", "new", 0}, // 1556
+ {NULL, "", "", 0}, // 1557
+ {wxCheckListBox_new_3, "wxCheckListBox", "new", 3}, // 1558
+ {NULL, "wxCheckListBox", "destroy", 1}, // 1559 obj destructor wxCheckListBox_destruct
+ {wxCheckListBox_Check, "wxCheckListBox", "check", 3}, // 1560
+ {wxCheckListBox_IsChecked, "wxCheckListBox", "isChecked", 2}, // 1561
+ {wxChoice_new_0, "wxChoice", "new", 0}, // 1562
+ {NULL, "", "", 0}, // 1563
+ {wxChoice_new_3, "wxChoice", "new", 3}, // 1564
+ {NULL, "wxChoice", "destroy", 1}, // 1565 obj destructor wxChoice_destruct
+ {NULL, "", "", 0}, // 1566
+ {wxChoice_Create, "wxChoice", "create", 7}, // 1567
+ {wxChoice_Delete, "wxChoice", "delete", 2}, // 1568
+ {wxChoice_GetColumns, "wxChoice", "getColumns", 1}, // 1569
+ {wxChoice_SetColumns, "wxChoice", "setColumns", 2}, // 1570
+ {wxComboBox_new_0, "wxComboBox", "new", 0}, // 1571
+ {NULL, "", "", 0}, // 1572
+ {wxComboBox_new_3, "wxComboBox", "new", 3}, // 1573
+ {NULL, "wxComboBox", "destroy", 1}, // 1574 obj destructor wxComboBox_destruct
+ {NULL, "", "", 0}, // 1575
+ {wxComboBox_Create, "wxComboBox", "create", 8}, // 1576
+ {wxComboBox_CanCopy, "wxComboBox", "canCopy", 1}, // 1577
+ {wxComboBox_CanCut, "wxComboBox", "canCut", 1}, // 1578
+ {wxComboBox_CanPaste, "wxComboBox", "canPaste", 1}, // 1579
+ {wxComboBox_CanRedo, "wxComboBox", "canRedo", 1}, // 1580
+ {wxComboBox_CanUndo, "wxComboBox", "canUndo", 1}, // 1581
+ {wxComboBox_Copy, "wxComboBox", "copy", 1}, // 1582
+ {wxComboBox_Cut, "wxComboBox", "cut", 1}, // 1583
+ {wxComboBox_GetInsertionPoint, "wxComboBox", "getInsertionPoint", 1}, // 1584
+ {wxComboBox_GetLastPosition, "wxComboBox", "getLastPosition", 1}, // 1585
+ {wxComboBox_GetValue, "wxComboBox", "getValue", 1}, // 1586
+ {wxComboBox_Paste, "wxComboBox", "paste", 1}, // 1587
+ {wxComboBox_Redo, "wxComboBox", "redo", 1}, // 1588
+ {wxComboBox_Replace, "wxComboBox", "replace", 4}, // 1589
+ {wxComboBox_Remove, "wxComboBox", "remove", 3}, // 1590
+ {wxComboBox_SetInsertionPoint, "wxComboBox", "setInsertionPoint", 2}, // 1591
+ {wxComboBox_SetInsertionPointEnd, "wxComboBox", "setInsertionPointEnd", 1}, // 1592
+ {wxComboBox_SetSelection_2, "wxComboBox", "setSelection", 3}, // 1593
+ {wxComboBox_SetSelection_1, "wxComboBox", "setSelection", 2}, // 1594
+ {wxComboBox_SetValue, "wxComboBox", "setValue", 2}, // 1595
+ {wxComboBox_Undo, "wxComboBox", "undo", 1}, // 1596
+ {wxGauge_new_0, "wxGauge", "new", 0}, // 1597
+ {wxGauge_new_4, "wxGauge", "new", 4}, // 1598
+ {NULL, "wxGauge", "destroy", 1}, // 1599 obj destructor wxGauge_destruct
+ {wxGauge_Create, "wxGauge", "create", 5}, // 1600
+ {wxGauge_GetRange, "wxGauge", "getRange", 1}, // 1601
+ {wxGauge_GetValue, "wxGauge", "getValue", 1}, // 1602
+ {wxGauge_IsVertical, "wxGauge", "isVertical", 1}, // 1603
+ {wxGauge_SetRange, "wxGauge", "setRange", 2}, // 1604
+ {wxGauge_SetValue, "wxGauge", "setValue", 2}, // 1605
+ {wxGauge_Pulse, "wxGauge", "pulse", 1}, // 1606
+ {wxGenericDirCtrl_new_0, "wxGenericDirCtrl", "new", 0}, // 1607
+ {wxGenericDirCtrl_new_2, "wxGenericDirCtrl", "new", 2}, // 1608
+ {NULL, "wxGenericDirCtrl", "destroy", 1}, // 1609 obj destructor wxGenericDirCtrl_destruct
+ {wxGenericDirCtrl_Create, "wxGenericDirCtrl", "create", 3}, // 1610
+ {wxGenericDirCtrl_Init, "wxGenericDirCtrl", "init", 1}, // 1611
+ {wxGenericDirCtrl_CollapseTree, "wxGenericDirCtrl", "collapseTree", 1}, // 1612
+ {wxGenericDirCtrl_ExpandPath, "wxGenericDirCtrl", "expandPath", 2}, // 1613
+ {wxGenericDirCtrl_GetDefaultPath, "wxGenericDirCtrl", "getDefaultPath", 1}, // 1614
+ {wxGenericDirCtrl_GetPath_0, "wxGenericDirCtrl", "getPath", 1}, // 1615
+ {wxGenericDirCtrl_GetPath_1, "wxGenericDirCtrl", "getPath", 2}, // 1616
+ {wxGenericDirCtrl_GetFilePath, "wxGenericDirCtrl", "getFilePath", 1}, // 1617
+ {wxGenericDirCtrl_GetFilter, "wxGenericDirCtrl", "getFilter", 1}, // 1618
+ {wxGenericDirCtrl_GetFilterIndex, "wxGenericDirCtrl", "getFilterIndex", 1}, // 1619
+ {wxGenericDirCtrl_GetRootId, "wxGenericDirCtrl", "getRootId", 1}, // 1620
+ {wxGenericDirCtrl_GetTreeCtrl, "wxGenericDirCtrl", "getTreeCtrl", 1}, // 1621
+ {wxGenericDirCtrl_ReCreateTree, "wxGenericDirCtrl", "reCreateTree", 1}, // 1622
+ {wxGenericDirCtrl_SetDefaultPath, "wxGenericDirCtrl", "setDefaultPath", 2}, // 1623
+ {wxGenericDirCtrl_SetFilter, "wxGenericDirCtrl", "setFilter", 2}, // 1624
+ {wxGenericDirCtrl_SetFilterIndex, "wxGenericDirCtrl", "setFilterIndex", 2}, // 1625
+ {wxGenericDirCtrl_SetPath, "wxGenericDirCtrl", "setPath", 2}, // 1626
+ {wxStaticBox_new_0, "wxStaticBox", "new", 0}, // 1627
+ {wxStaticBox_new_4, "wxStaticBox", "new", 4}, // 1628
+ {NULL, "wxStaticBox", "destroy", 1}, // 1629 obj destructor wxStaticBox_destruct
+ {wxStaticBox_Create, "wxStaticBox", "create", 5}, // 1630
+ {wxStaticLine_new_0, "wxStaticLine", "new", 0}, // 1631
+ {wxStaticLine_new_2, "wxStaticLine", "new", 2}, // 1632
+ {wxStaticLine_Create, "wxStaticLine", "create", 3}, // 1633
+ {wxStaticLine_IsVertical, "wxStaticLine", "isVertical", 1}, // 1634
+ {wxStaticLine_GetDefaultSize, "wxStaticLine", "getDefaultSize", 0}, // 1635
+ {NULL, "wxStaticLine", "'Destroy'", 1}, // 1636 obj destructor wxStaticLine_destroy
+ {wxListBox_new_0, "wxListBox", "new", 0}, // 1637
+ {NULL, "", "", 0}, // 1638
+ {wxListBox_new_3, "wxListBox", "new", 3}, // 1639
+ {NULL, "wxListBox", "destroy", 1}, // 1640 obj destructor wxListBox_destruct
+ {NULL, "", "", 0}, // 1641
+ {wxListBox_Create, "wxListBox", "create", 7}, // 1642
+ {wxListBox_Deselect, "wxListBox", "deselect", 2}, // 1643
+ {wxListBox_GetSelections, "wxListBox", "getSelections", 1}, // 1644
+ {wxListBox_InsertItems, "wxListBox", "insertItems", 3}, // 1645
+ {wxListBox_IsSelected, "wxListBox", "isSelected", 2}, // 1646
+ {NULL, "", "", 0}, // 1647
+ {NULL, "", "", 0}, // 1648
+ {wxListBox_Set, "wxListBox", "set", 2}, // 1649
+ {wxListBox_HitTest_1, "wxListBox", "hitTest", 2}, // 1650
+ {wxListBox_HitTest_2, "wxListBox", "hitTest", 3}, // 1651
+ {wxListBox_SetFirstItem_1_0, "wxListBox", "setFirstItem", 2}, // 1652
+ {wxListBox_SetFirstItem_1_1, "wxListBox", "setFirstItem", 2}, // 1653
+ {wxListCtrl_new_0, "wxListCtrl", "new", 0}, // 1654
+ {NULL, "wxListCtrl", "new", 2}, // 1655 TaylorMade erl only wxListCtrl_new_2
+ {NULL, "wxListCtrl", "destroy", 1}, // 1656 obj destructor wxListCtrl_destruct
+ {wxListCtrl_Arrange, "wxListCtrl", "arrange", 2}, // 1657
+ {wxListCtrl_AssignImageList, "wxListCtrl", "assignImageList", 3}, // 1658
+ {wxListCtrl_ClearAll, "wxListCtrl", "clearAll", 1}, // 1659
+ {wxListCtrl_Create, "wxListCtrl", "create", 3}, // 1660
+ {wxListCtrl_DeleteAllItems, "wxListCtrl", "deleteAllItems", 1}, // 1661
+ {wxListCtrl_DeleteColumn, "wxListCtrl", "deleteColumn", 2}, // 1662
+ {wxListCtrl_DeleteItem, "wxListCtrl", "deleteItem", 2}, // 1663
+ {wxListCtrl_EditLabel, "wxListCtrl", "editLabel", 2}, // 1664
+ {wxListCtrl_EnsureVisible, "wxListCtrl", "ensureVisible", 2}, // 1665
+ {wxListCtrl_FindItem_3_0, "wxListCtrl", "findItem", 4}, // 1666
+ {wxListCtrl_FindItem_3_1, "wxListCtrl", "findItem", 4}, // 1667
+ {wxListCtrl_GetColumn, "wxListCtrl", "getColumn", 3}, // 1668
+ {wxListCtrl_GetColumnCount, "wxListCtrl", "getColumnCount", 1}, // 1669
+ {wxListCtrl_GetColumnWidth, "wxListCtrl", "getColumnWidth", 2}, // 1670
+ {wxListCtrl_GetCountPerPage, "wxListCtrl", "getCountPerPage", 1}, // 1671
+ {wxListCtrl_GetEditControl, "wxListCtrl", "getEditControl", 1}, // 1672
+ {wxListCtrl_GetImageList, "wxListCtrl", "getImageList", 2}, // 1673
+ {wxListCtrl_GetItem, "wxListCtrl", "getItem", 2}, // 1674
+ {wxListCtrl_GetItemBackgroundColour, "wxListCtrl", "getItemBackgroundColour", 2}, // 1675
+ {wxListCtrl_GetItemCount, "wxListCtrl", "getItemCount", 1}, // 1676
+ {wxListCtrl_GetItemData, "wxListCtrl", "getItemData", 2}, // 1677
+ {wxListCtrl_GetItemFont, "wxListCtrl", "getItemFont", 2}, // 1678
+ {wxListCtrl_GetItemPosition, "wxListCtrl", "getItemPosition", 2}, // 1679
+ {wxListCtrl_GetItemRect, "wxListCtrl", "getItemRect", 3}, // 1680
+ {wxListCtrl_GetItemSpacing, "wxListCtrl", "getItemSpacing", 1}, // 1681
+ {wxListCtrl_GetItemState, "wxListCtrl", "getItemState", 3}, // 1682
+ {wxListCtrl_GetItemText, "wxListCtrl", "getItemText", 3}, // 1683
+ {wxListCtrl_GetItemTextColour, "wxListCtrl", "getItemTextColour", 2}, // 1684
+ {wxListCtrl_GetNextItem, "wxListCtrl", "getNextItem", 3}, // 1685
+ {wxListCtrl_GetSelectedItemCount, "wxListCtrl", "getSelectedItemCount", 1}, // 1686
+ {wxListCtrl_GetTextColour, "wxListCtrl", "getTextColour", 1}, // 1687
+ {wxListCtrl_GetTopItem, "wxListCtrl", "getTopItem", 1}, // 1688
+ {wxListCtrl_GetViewRect, "wxListCtrl", "getViewRect", 1}, // 1689
+ {wxListCtrl_HitTest, "wxListCtrl", "hitTest", 2}, // 1690
+ {wxListCtrl_InsertColumn_2, "wxListCtrl", "insertColumn", 3}, // 1691
+ {wxListCtrl_InsertColumn_3, "wxListCtrl", "insertColumn", 4}, // 1692
+ {wxListCtrl_InsertItem_1, "wxListCtrl", "insertItem", 2}, // 1693
+ {wxListCtrl_InsertItem_2_1, "wxListCtrl", "insertItem", 3}, // 1694
+ {wxListCtrl_InsertItem_2_0, "wxListCtrl", "insertItem", 3}, // 1695
+ {wxListCtrl_InsertItem_3, "wxListCtrl", "insertItem", 4}, // 1696
+ {wxListCtrl_RefreshItem, "wxListCtrl", "refreshItem", 2}, // 1697
+ {wxListCtrl_RefreshItems, "wxListCtrl", "refreshItems", 3}, // 1698
+ {wxListCtrl_ScrollList, "wxListCtrl", "scrollList", 3}, // 1699
+ {wxListCtrl_SetBackgroundColour, "wxListCtrl", "setBackgroundColour", 2}, // 1700
+ {wxListCtrl_SetColumn, "wxListCtrl", "setColumn", 3}, // 1701
+ {wxListCtrl_SetColumnWidth, "wxListCtrl", "setColumnWidth", 3}, // 1702
+ {wxListCtrl_SetImageList, "wxListCtrl", "setImageList", 3}, // 1703
+ {wxListCtrl_SetItem_1, "wxListCtrl", "setItem", 2}, // 1704
+ {wxListCtrl_SetItem_4, "wxListCtrl", "setItem", 5}, // 1705
+ {wxListCtrl_SetItemBackgroundColour, "wxListCtrl", "setItemBackgroundColour", 3}, // 1706
+ {wxListCtrl_SetItemCount, "wxListCtrl", "setItemCount", 2}, // 1707
+ {wxListCtrl_SetItemData, "wxListCtrl", "setItemData", 3}, // 1708
+ {wxListCtrl_SetItemFont, "wxListCtrl", "setItemFont", 3}, // 1709
+ {wxListCtrl_SetItemImage, "wxListCtrl", "setItemImage", 4}, // 1710
+ {wxListCtrl_SetItemColumnImage, "wxListCtrl", "setItemColumnImage", 4}, // 1711
+ {wxListCtrl_SetItemPosition, "wxListCtrl", "setItemPosition", 3}, // 1712
+ {wxListCtrl_SetItemState, "wxListCtrl", "setItemState", 4}, // 1713
+ {wxListCtrl_SetItemText, "wxListCtrl", "setItemText", 3}, // 1714
+ {wxListCtrl_SetItemTextColour, "wxListCtrl", "setItemTextColour", 3}, // 1715
+ {wxListCtrl_SetSingleStyle, "wxListCtrl", "setSingleStyle", 3}, // 1716
+ {wxListCtrl_SetTextColour, "wxListCtrl", "setTextColour", 2}, // 1717
+ {wxListCtrl_SetWindowStyleFlag, "wxListCtrl", "setWindowStyleFlag", 2}, // 1718
+ {wxListCtrl_SortItems, "wxListCtrl", "sortItems", 2}, // 1719
+ {wxListView_ClearColumnImage, "wxListView", "clearColumnImage", 2}, // 1720
+ {wxListView_Focus, "wxListView", "focus", 2}, // 1721
+ {wxListView_GetFirstSelected, "wxListView", "getFirstSelected", 1}, // 1722
+ {wxListView_GetFocusedItem, "wxListView", "getFocusedItem", 1}, // 1723
+ {wxListView_GetNextSelected, "wxListView", "getNextSelected", 2}, // 1724
+ {wxListView_IsSelected, "wxListView", "isSelected", 2}, // 1725
+ {wxListView_Select, "wxListView", "select", 3}, // 1726
+ {wxListView_SetColumnImage, "wxListView", "setColumnImage", 3}, // 1727
+ {wxListItem_new_0, "wxListItem", "new", 0}, // 1728
+ {wxListItem_new_1, "wxListItem", "new", 1}, // 1729
+ {wxListItem_Clear, "wxListItem", "clear", 1}, // 1730
+ {wxListItem_GetAlign, "wxListItem", "getAlign", 1}, // 1731
+ {wxListItem_GetBackgroundColour, "wxListItem", "getBackgroundColour", 1}, // 1732
+ {wxListItem_GetColumn, "wxListItem", "getColumn", 1}, // 1733
+ {wxListItem_GetFont, "wxListItem", "getFont", 1}, // 1734
+ {wxListItem_GetId, "wxListItem", "getId", 1}, // 1735
+ {wxListItem_GetImage, "wxListItem", "getImage", 1}, // 1736
+ {wxListItem_GetMask, "wxListItem", "getMask", 1}, // 1737
+ {wxListItem_GetState, "wxListItem", "getState", 1}, // 1738
+ {wxListItem_GetText, "wxListItem", "getText", 1}, // 1739
+ {wxListItem_GetTextColour, "wxListItem", "getTextColour", 1}, // 1740
+ {wxListItem_GetWidth, "wxListItem", "getWidth", 1}, // 1741
+ {wxListItem_SetAlign, "wxListItem", "setAlign", 2}, // 1742
+ {wxListItem_SetBackgroundColour, "wxListItem", "setBackgroundColour", 2}, // 1743
+ {wxListItem_SetColumn, "wxListItem", "setColumn", 2}, // 1744
+ {wxListItem_SetFont, "wxListItem", "setFont", 2}, // 1745
+ {wxListItem_SetId, "wxListItem", "setId", 2}, // 1746
+ {wxListItem_SetImage, "wxListItem", "setImage", 2}, // 1747
+ {wxListItem_SetMask, "wxListItem", "setMask", 2}, // 1748
+ {wxListItem_SetState, "wxListItem", "setState", 2}, // 1749
+ {wxListItem_SetStateMask, "wxListItem", "setStateMask", 2}, // 1750
+ {wxListItem_SetText, "wxListItem", "setText", 2}, // 1751
+ {wxListItem_SetTextColour, "wxListItem", "setTextColour", 2}, // 1752
+ {wxListItem_SetWidth, "wxListItem", "setWidth", 2}, // 1753
+ {NULL, "wxListItem", "'Destroy'", 1}, // 1754 obj destructor wxListItem_destroy
+ {wxListItemAttr_new_0, "wxListItemAttr", "new", 0}, // 1755
+ {wxListItemAttr_new_3, "wxListItemAttr", "new", 3}, // 1756
+ {wxListItemAttr_GetBackgroundColour, "wxListItemAttr", "getBackgroundColour", 1}, // 1757
+ {wxListItemAttr_GetFont, "wxListItemAttr", "getFont", 1}, // 1758
+ {wxListItemAttr_GetTextColour, "wxListItemAttr", "getTextColour", 1}, // 1759
+ {wxListItemAttr_HasBackgroundColour, "wxListItemAttr", "hasBackgroundColour", 1}, // 1760
+ {wxListItemAttr_HasFont, "wxListItemAttr", "hasFont", 1}, // 1761
+ {wxListItemAttr_HasTextColour, "wxListItemAttr", "hasTextColour", 1}, // 1762
+ {wxListItemAttr_SetBackgroundColour, "wxListItemAttr", "setBackgroundColour", 2}, // 1763
+ {wxListItemAttr_SetFont, "wxListItemAttr", "setFont", 2}, // 1764
+ {wxListItemAttr_SetTextColour, "wxListItemAttr", "setTextColour", 2}, // 1765
+ {wxListItemAttr_destroy, "wxListItemAttr", "'Destroy'", 1}, // 1766
+ {wxImageList_new_0, "wxImageList", "new", 0}, // 1767
+ {wxImageList_new_3, "wxImageList", "new", 3}, // 1768
+ {wxImageList_Add_2_0, "wxImageList", "add", 3}, // 1769
+ {NULL, "", "", 0}, // 1770
+ {wxImageList_Add_2_1, "wxImageList", "add", 3}, // 1771
+ {wxImageList_Add_1, "wxImageList", "add", 2}, // 1772
+ {wxImageList_Create, "wxImageList", "create", 4}, // 1773
+ {wxImageList_Draw, "wxImageList", "draw", 6}, // 1774
+ {wxImageList_GetBitmap, "wxImageList", "getBitmap", 2}, // 1775
+ {wxImageList_GetIcon, "wxImageList", "getIcon", 2}, // 1776
+ {wxImageList_GetImageCount, "wxImageList", "getImageCount", 1}, // 1777
+ {wxImageList_GetSize, "wxImageList", "getSize", 2}, // 1778
+ {NULL, "", "", 0}, // 1779
+ {wxImageList_Remove, "wxImageList", "remove", 2}, // 1780
+ {wxImageList_RemoveAll, "wxImageList", "removeAll", 1}, // 1781
+ {wxImageList_Replace_3, "wxImageList", "replace", 4}, // 1782
+ {NULL, "", "", 0}, // 1783
+ {wxImageList_Replace_2, "wxImageList", "replace", 3}, // 1784
+ {NULL, "wxImageList", "'Destroy'", 1}, // 1785 obj destructor wxImageList_destroy
+ {wxTextAttr_new_0, "wxTextAttr", "new", 0}, // 1786
+ {wxTextAttr_new_2, "wxTextAttr", "new", 2}, // 1787
+ {wxTextAttr_new_1, "wxTextAttr", "new", 1}, // 1788
+ {wxTextAttr_GetAlignment, "wxTextAttr", "getAlignment", 1}, // 1789
+ {wxTextAttr_GetBackgroundColour, "wxTextAttr", "getBackgroundColour", 1}, // 1790
+ {wxTextAttr_GetFont, "wxTextAttr", "getFont", 1}, // 1791
+ {wxTextAttr_GetFontEncoding, "wxTextAttr", "getFontEncoding", 1}, // 1792
+ {wxTextAttr_GetFontFaceName, "wxTextAttr", "getFontFaceName", 1}, // 1793
+ {wxTextAttr_GetFontSize, "wxTextAttr", "getFontSize", 1}, // 1794
+ {wxTextAttr_GetFontStyle, "wxTextAttr", "getFontStyle", 1}, // 1795
+ {wxTextAttr_GetFontUnderlined, "wxTextAttr", "getFontUnderlined", 1}, // 1796
+ {wxTextAttr_GetFontWeight, "wxTextAttr", "getFontWeight", 1}, // 1797
+ {wxTextAttr_GetLeftIndent, "wxTextAttr", "getLeftIndent", 1}, // 1798
+ {wxTextAttr_GetLeftSubIndent, "wxTextAttr", "getLeftSubIndent", 1}, // 1799
+ {wxTextAttr_GetRightIndent, "wxTextAttr", "getRightIndent", 1}, // 1800
+ {wxTextAttr_GetTabs, "wxTextAttr", "getTabs", 1}, // 1801
+ {wxTextAttr_GetTextColour, "wxTextAttr", "getTextColour", 1}, // 1802
+ {wxTextAttr_HasBackgroundColour, "wxTextAttr", "hasBackgroundColour", 1}, // 1803
+ {wxTextAttr_HasFont, "wxTextAttr", "hasFont", 1}, // 1804
+ {wxTextAttr_HasTextColour, "wxTextAttr", "hasTextColour", 1}, // 1805
+ {wxTextAttr_GetFlags, "wxTextAttr", "getFlags", 1}, // 1806
+ {wxTextAttr_IsDefault, "wxTextAttr", "isDefault", 1}, // 1807
+ {wxTextAttr_SetAlignment, "wxTextAttr", "setAlignment", 2}, // 1808
+ {wxTextAttr_SetBackgroundColour, "wxTextAttr", "setBackgroundColour", 2}, // 1809
+ {wxTextAttr_SetFlags, "wxTextAttr", "setFlags", 2}, // 1810
+ {wxTextAttr_SetFont, "wxTextAttr", "setFont", 3}, // 1811
+ {wxTextAttr_SetFontEncoding, "wxTextAttr", "setFontEncoding", 2}, // 1812
+ {wxTextAttr_SetFontFaceName, "wxTextAttr", "setFontFaceName", 2}, // 1813
+ {wxTextAttr_SetFontFamily, "wxTextAttr", "setFontFamily", 2}, // 1814
+ {wxTextAttr_SetFontSize, "wxTextAttr", "setFontSize", 2}, // 1815
+ {wxTextAttr_SetFontPointSize, "wxTextAttr", "setFontPointSize", 2}, // 1816
+ {wxTextAttr_SetFontPixelSize, "wxTextAttr", "setFontPixelSize", 2}, // 1817
+ {wxTextAttr_SetFontStyle, "wxTextAttr", "setFontStyle", 2}, // 1818
+ {wxTextAttr_SetFontUnderlined, "wxTextAttr", "setFontUnderlined", 2}, // 1819
+ {wxTextAttr_SetFontWeight, "wxTextAttr", "setFontWeight", 2}, // 1820
+ {wxTextAttr_SetLeftIndent, "wxTextAttr", "setLeftIndent", 3}, // 1821
+ {wxTextAttr_SetRightIndent, "wxTextAttr", "setRightIndent", 2}, // 1822
+ {wxTextAttr_SetTabs, "wxTextAttr", "setTabs", 2}, // 1823
+ {wxTextAttr_SetTextColour, "wxTextAttr", "setTextColour", 2}, // 1824
+ {wxTextAttr_destroy, "wxTextAttr", "'Destroy'", 1}, // 1825
+ {wxTextCtrl_new_0, "wxTextCtrl", "new", 0}, // 1826
+ {wxTextCtrl_new_3, "wxTextCtrl", "new", 3}, // 1827
+ {NULL, "wxTextCtrl", "destroy", 1}, // 1828 obj destructor wxTextCtrl_destruct
+ {wxTextCtrl_AppendText, "wxTextCtrl", "appendText", 2}, // 1829
+ {wxTextCtrl_CanCopy, "wxTextCtrl", "canCopy", 1}, // 1830
+ {wxTextCtrl_CanCut, "wxTextCtrl", "canCut", 1}, // 1831
+ {wxTextCtrl_CanPaste, "wxTextCtrl", "canPaste", 1}, // 1832
+ {wxTextCtrl_CanRedo, "wxTextCtrl", "canRedo", 1}, // 1833
+ {wxTextCtrl_CanUndo, "wxTextCtrl", "canUndo", 1}, // 1834
+ {wxTextCtrl_Clear, "wxTextCtrl", "clear", 1}, // 1835
+ {wxTextCtrl_Copy, "wxTextCtrl", "copy", 1}, // 1836
+ {wxTextCtrl_Create, "wxTextCtrl", "create", 4}, // 1837
+ {wxTextCtrl_Cut, "wxTextCtrl", "cut", 1}, // 1838
+ {wxTextCtrl_DiscardEdits, "wxTextCtrl", "discardEdits", 1}, // 1839
+ {wxTextCtrl_ChangeValue, "wxTextCtrl", "changeValue", 2}, // 1840
+ {wxTextCtrl_EmulateKeyPress, "wxTextCtrl", "emulateKeyPress", 2}, // 1841
+ {wxTextCtrl_GetDefaultStyle, "wxTextCtrl", "getDefaultStyle", 1}, // 1842
+ {wxTextCtrl_GetInsertionPoint, "wxTextCtrl", "getInsertionPoint", 1}, // 1843
+ {wxTextCtrl_GetLastPosition, "wxTextCtrl", "getLastPosition", 1}, // 1844
+ {wxTextCtrl_GetLineLength, "wxTextCtrl", "getLineLength", 2}, // 1845
+ {wxTextCtrl_GetLineText, "wxTextCtrl", "getLineText", 2}, // 1846
+ {wxTextCtrl_GetNumberOfLines, "wxTextCtrl", "getNumberOfLines", 1}, // 1847
+ {wxTextCtrl_GetRange, "wxTextCtrl", "getRange", 3}, // 1848
+ {wxTextCtrl_GetSelection, "wxTextCtrl", "getSelection", 1}, // 1849
+ {wxTextCtrl_GetStringSelection, "wxTextCtrl", "getStringSelection", 1}, // 1850
+ {wxTextCtrl_GetStyle, "wxTextCtrl", "getStyle", 3}, // 1851
+ {wxTextCtrl_GetValue, "wxTextCtrl", "getValue", 1}, // 1852
+ {wxTextCtrl_IsEditable, "wxTextCtrl", "isEditable", 1}, // 1853
+ {wxTextCtrl_IsModified, "wxTextCtrl", "isModified", 1}, // 1854
+ {wxTextCtrl_IsMultiLine, "wxTextCtrl", "isMultiLine", 1}, // 1855
+ {wxTextCtrl_IsSingleLine, "wxTextCtrl", "isSingleLine", 1}, // 1856
+ {wxTextCtrl_LoadFile, "wxTextCtrl", "loadFile", 3}, // 1857
+ {wxTextCtrl_MarkDirty, "wxTextCtrl", "markDirty", 1}, // 1858
+ {wxTextCtrl_Paste, "wxTextCtrl", "paste", 1}, // 1859
+ {wxTextCtrl_PositionToXY, "wxTextCtrl", "positionToXY", 2}, // 1860
+ {wxTextCtrl_Redo, "wxTextCtrl", "redo", 1}, // 1861
+ {wxTextCtrl_Remove, "wxTextCtrl", "remove", 3}, // 1862
+ {wxTextCtrl_Replace, "wxTextCtrl", "replace", 4}, // 1863
+ {wxTextCtrl_SaveFile, "wxTextCtrl", "saveFile", 2}, // 1864
+ {wxTextCtrl_SetDefaultStyle, "wxTextCtrl", "setDefaultStyle", 2}, // 1865
+ {wxTextCtrl_SetEditable, "wxTextCtrl", "setEditable", 2}, // 1866
+ {wxTextCtrl_SetInsertionPoint, "wxTextCtrl", "setInsertionPoint", 2}, // 1867
+ {wxTextCtrl_SetInsertionPointEnd, "wxTextCtrl", "setInsertionPointEnd", 1}, // 1868
+ {wxTextCtrl_SetMaxLength, "wxTextCtrl", "setMaxLength", 2}, // 1869
+ {wxTextCtrl_SetSelection, "wxTextCtrl", "setSelection", 3}, // 1870
+ {wxTextCtrl_SetStyle, "wxTextCtrl", "setStyle", 4}, // 1871
+ {wxTextCtrl_SetValue, "wxTextCtrl", "setValue", 2}, // 1872
+ {wxTextCtrl_ShowPosition, "wxTextCtrl", "showPosition", 2}, // 1873
+ {wxTextCtrl_Undo, "wxTextCtrl", "undo", 1}, // 1874
+ {wxTextCtrl_WriteText, "wxTextCtrl", "writeText", 2}, // 1875
+ {wxTextCtrl_XYToPosition, "wxTextCtrl", "xYToPosition", 3}, // 1876
+ {wxBookCtrlBase_AddPage, "wxBookCtrlBase", "addPage", 4}, // 1877
+ {wxBookCtrlBase_InsertPage, "wxBookCtrlBase", "insertPage", 5}, // 1878
+ {wxBookCtrlBase_DeletePage, "wxBookCtrlBase", "deletePage", 2}, // 1879
+ {wxBookCtrlBase_RemovePage, "wxBookCtrlBase", "removePage", 2}, // 1880
+ {wxBookCtrlBase_DeleteAllPages, "wxBookCtrlBase", "deleteAllPages", 1}, // 1881
+ {wxBookCtrlBase_GetPage, "wxBookCtrlBase", "getPage", 2}, // 1882
+ {wxBookCtrlBase_GetPageCount, "wxBookCtrlBase", "getPageCount", 1}, // 1883
+ {wxBookCtrlBase_GetCurrentPage, "wxBookCtrlBase", "getCurrentPage", 1}, // 1884
+ {wxBookCtrlBase_AdvanceSelection, "wxBookCtrlBase", "advanceSelection", 2}, // 1885
+ {wxBookCtrlBase_SetSelection, "wxBookCtrlBase", "setSelection", 2}, // 1886
+ {wxBookCtrlBase_GetSelection, "wxBookCtrlBase", "getSelection", 1}, // 1887
+ {wxBookCtrlBase_ChangeSelection, "wxBookCtrlBase", "changeSelection", 2}, // 1888
+ {wxBookCtrlBase_HitTest, "wxBookCtrlBase", "hitTest", 2}, // 1889
+ {wxBookCtrlBase_GetPageText, "wxBookCtrlBase", "getPageText", 2}, // 1890
+ {wxBookCtrlBase_SetPageText, "wxBookCtrlBase", "setPageText", 3}, // 1891
+ {wxNotebook_new_0, "wxNotebook", "new", 0}, // 1892
+ {wxNotebook_new_3, "wxNotebook", "new", 3}, // 1893
+ {NULL, "wxNotebook", "destroy", 1}, // 1894 obj destructor wxNotebook_destruct
+ {wxNotebook_AssignImageList, "wxNotebook", "assignImageList", 2}, // 1895
+ {wxNotebook_Create, "wxNotebook", "create", 4}, // 1896
+ {wxNotebook_GetImageList, "wxNotebook", "getImageList", 1}, // 1897
+ {wxNotebook_GetPageImage, "wxNotebook", "getPageImage", 2}, // 1898
+ {wxNotebook_GetRowCount, "wxNotebook", "getRowCount", 1}, // 1899
+ {wxNotebook_GetThemeBackgroundColour, "wxNotebook", "getThemeBackgroundColour", 1}, // 1900
+ {wxNotebook_SetImageList, "wxNotebook", "setImageList", 2}, // 1901
+ {wxNotebook_SetPadding, "wxNotebook", "setPadding", 2}, // 1902
+ {wxNotebook_SetPageSize, "wxNotebook", "setPageSize", 2}, // 1903
+ {wxNotebook_SetPageImage, "wxNotebook", "setPageImage", 3}, // 1904
+ {wxChoicebook_new_0, "wxChoicebook", "new", 0}, // 1905
+ {wxChoicebook_new_3, "wxChoicebook", "new", 3}, // 1906
+ {wxChoicebook_AddPage, "wxChoicebook", "addPage", 4}, // 1907
+ {wxChoicebook_AdvanceSelection, "wxChoicebook", "advanceSelection", 2}, // 1908
+ {wxChoicebook_AssignImageList, "wxChoicebook", "assignImageList", 2}, // 1909
+ {wxChoicebook_Create, "wxChoicebook", "create", 4}, // 1910
+ {wxChoicebook_DeleteAllPages, "wxChoicebook", "deleteAllPages", 1}, // 1911
+ {wxChoicebook_GetCurrentPage, "wxChoicebook", "getCurrentPage", 1}, // 1912
+ {wxChoicebook_GetImageList, "wxChoicebook", "getImageList", 1}, // 1913
+ {wxChoicebook_GetPage, "wxChoicebook", "getPage", 2}, // 1914
+ {wxChoicebook_GetPageCount, "wxChoicebook", "getPageCount", 1}, // 1915
+ {wxChoicebook_GetPageImage, "wxChoicebook", "getPageImage", 2}, // 1916
+ {wxChoicebook_GetPageText, "wxChoicebook", "getPageText", 2}, // 1917
+ {wxChoicebook_GetSelection, "wxChoicebook", "getSelection", 1}, // 1918
+ {wxChoicebook_HitTest, "wxChoicebook", "hitTest", 2}, // 1919
+ {wxChoicebook_InsertPage, "wxChoicebook", "insertPage", 5}, // 1920
+ {wxChoicebook_SetImageList, "wxChoicebook", "setImageList", 2}, // 1921
+ {wxChoicebook_SetPageSize, "wxChoicebook", "setPageSize", 2}, // 1922
+ {wxChoicebook_SetPageImage, "wxChoicebook", "setPageImage", 3}, // 1923
+ {wxChoicebook_SetPageText, "wxChoicebook", "setPageText", 3}, // 1924
+ {wxChoicebook_SetSelection, "wxChoicebook", "setSelection", 2}, // 1925
+ {wxChoicebook_ChangeSelection, "wxChoicebook", "changeSelection", 2}, // 1926
+ {NULL, "wxChoicebook", "'Destroy'", 1}, // 1927 obj destructor wxChoicebook_destroy
+ {wxToolbook_new_0, "wxToolbook", "new", 0}, // 1928
+ {wxToolbook_new_3, "wxToolbook", "new", 3}, // 1929
+ {wxToolbook_AddPage, "wxToolbook", "addPage", 4}, // 1930
+ {wxToolbook_AdvanceSelection, "wxToolbook", "advanceSelection", 2}, // 1931
+ {wxToolbook_AssignImageList, "wxToolbook", "assignImageList", 2}, // 1932
+ {wxToolbook_Create, "wxToolbook", "create", 4}, // 1933
+ {wxToolbook_DeleteAllPages, "wxToolbook", "deleteAllPages", 1}, // 1934
+ {wxToolbook_GetCurrentPage, "wxToolbook", "getCurrentPage", 1}, // 1935
+ {wxToolbook_GetImageList, "wxToolbook", "getImageList", 1}, // 1936
+ {wxToolbook_GetPage, "wxToolbook", "getPage", 2}, // 1937
+ {wxToolbook_GetPageCount, "wxToolbook", "getPageCount", 1}, // 1938
+ {wxToolbook_GetPageImage, "wxToolbook", "getPageImage", 2}, // 1939
+ {wxToolbook_GetPageText, "wxToolbook", "getPageText", 2}, // 1940
+ {wxToolbook_GetSelection, "wxToolbook", "getSelection", 1}, // 1941
+ {wxToolbook_HitTest, "wxToolbook", "hitTest", 2}, // 1942
+ {wxToolbook_InsertPage, "wxToolbook", "insertPage", 5}, // 1943
+ {wxToolbook_SetImageList, "wxToolbook", "setImageList", 2}, // 1944
+ {wxToolbook_SetPageSize, "wxToolbook", "setPageSize", 2}, // 1945
+ {wxToolbook_SetPageImage, "wxToolbook", "setPageImage", 3}, // 1946
+ {wxToolbook_SetPageText, "wxToolbook", "setPageText", 3}, // 1947
+ {wxToolbook_SetSelection, "wxToolbook", "setSelection", 2}, // 1948
+ {wxToolbook_ChangeSelection, "wxToolbook", "changeSelection", 2}, // 1949
+ {NULL, "wxToolbook", "'Destroy'", 1}, // 1950 obj destructor wxToolbook_destroy
+ {wxListbook_new_0, "wxListbook", "new", 0}, // 1951
+ {wxListbook_new_3, "wxListbook", "new", 3}, // 1952
+ {wxListbook_AddPage, "wxListbook", "addPage", 4}, // 1953
+ {wxListbook_AdvanceSelection, "wxListbook", "advanceSelection", 2}, // 1954
+ {wxListbook_AssignImageList, "wxListbook", "assignImageList", 2}, // 1955
+ {wxListbook_Create, "wxListbook", "create", 4}, // 1956
+ {wxListbook_DeleteAllPages, "wxListbook", "deleteAllPages", 1}, // 1957
+ {wxListbook_GetCurrentPage, "wxListbook", "getCurrentPage", 1}, // 1958
+ {wxListbook_GetImageList, "wxListbook", "getImageList", 1}, // 1959
+ {wxListbook_GetPage, "wxListbook", "getPage", 2}, // 1960
+ {wxListbook_GetPageCount, "wxListbook", "getPageCount", 1}, // 1961
+ {wxListbook_GetPageImage, "wxListbook", "getPageImage", 2}, // 1962
+ {wxListbook_GetPageText, "wxListbook", "getPageText", 2}, // 1963
+ {wxListbook_GetSelection, "wxListbook", "getSelection", 1}, // 1964
+ {wxListbook_HitTest, "wxListbook", "hitTest", 2}, // 1965
+ {wxListbook_InsertPage, "wxListbook", "insertPage", 5}, // 1966
+ {wxListbook_SetImageList, "wxListbook", "setImageList", 2}, // 1967
+ {wxListbook_SetPageSize, "wxListbook", "setPageSize", 2}, // 1968
+ {wxListbook_SetPageImage, "wxListbook", "setPageImage", 3}, // 1969
+ {wxListbook_SetPageText, "wxListbook", "setPageText", 3}, // 1970
+ {wxListbook_SetSelection, "wxListbook", "setSelection", 2}, // 1971
+ {wxListbook_ChangeSelection, "wxListbook", "changeSelection", 2}, // 1972
+ {NULL, "wxListbook", "'Destroy'", 1}, // 1973 obj destructor wxListbook_destroy
+ {wxTreebook_new_0, "wxTreebook", "new", 0}, // 1974
+ {wxTreebook_new_3, "wxTreebook", "new", 3}, // 1975
+ {NULL, "wxTreebook", "destroy", 1}, // 1976 obj destructor wxTreebook_destruct
+ {wxTreebook_AddPage, "wxTreebook", "addPage", 4}, // 1977
+ {wxTreebook_AdvanceSelection, "wxTreebook", "advanceSelection", 2}, // 1978
+ {wxTreebook_AssignImageList, "wxTreebook", "assignImageList", 2}, // 1979
+ {wxTreebook_Create, "wxTreebook", "create", 4}, // 1980
+ {wxTreebook_DeleteAllPages, "wxTreebook", "deleteAllPages", 1}, // 1981
+ {wxTreebook_GetCurrentPage, "wxTreebook", "getCurrentPage", 1}, // 1982
+ {wxTreebook_GetImageList, "wxTreebook", "getImageList", 1}, // 1983
+ {wxTreebook_GetPage, "wxTreebook", "getPage", 2}, // 1984
+ {wxTreebook_GetPageCount, "wxTreebook", "getPageCount", 1}, // 1985
+ {wxTreebook_GetPageImage, "wxTreebook", "getPageImage", 2}, // 1986
+ {wxTreebook_GetPageText, "wxTreebook", "getPageText", 2}, // 1987
+ {wxTreebook_GetSelection, "wxTreebook", "getSelection", 1}, // 1988
+ {wxTreebook_ExpandNode, "wxTreebook", "expandNode", 3}, // 1989
+ {wxTreebook_IsNodeExpanded, "wxTreebook", "isNodeExpanded", 2}, // 1990
+ {wxTreebook_HitTest, "wxTreebook", "hitTest", 2}, // 1991
+ {wxTreebook_InsertPage, "wxTreebook", "insertPage", 5}, // 1992
+ {wxTreebook_InsertSubPage, "wxTreebook", "insertSubPage", 5}, // 1993
+ {wxTreebook_SetImageList, "wxTreebook", "setImageList", 2}, // 1994
+ {wxTreebook_SetPageSize, "wxTreebook", "setPageSize", 2}, // 1995
+ {wxTreebook_SetPageImage, "wxTreebook", "setPageImage", 3}, // 1996
+ {wxTreebook_SetPageText, "wxTreebook", "setPageText", 3}, // 1997
+ {wxTreebook_SetSelection, "wxTreebook", "setSelection", 2}, // 1998
+ {wxTreebook_ChangeSelection, "wxTreebook", "changeSelection", 2}, // 1999
+ {wxTreeCtrl_new_0, "wxTreeCtrl", "new", 0}, // 2000
+ {wxTreeCtrl_new_2, "wxTreeCtrl", "new", 2}, // 2001
+ {NULL, "wxTreeCtrl", "destroy", 1}, // 2002 obj destructor wxTreeCtrl_destruct
+ {wxTreeCtrl_AddRoot, "wxTreeCtrl", "addRoot", 3}, // 2003
+ {wxTreeCtrl_AppendItem, "wxTreeCtrl", "appendItem", 4}, // 2004
+ {wxTreeCtrl_AssignImageList, "wxTreeCtrl", "assignImageList", 2}, // 2005
+ {wxTreeCtrl_AssignStateImageList, "wxTreeCtrl", "assignStateImageList", 2}, // 2006
+ {wxTreeCtrl_Collapse, "wxTreeCtrl", "collapse", 2}, // 2007
+ {wxTreeCtrl_CollapseAndReset, "wxTreeCtrl", "collapseAndReset", 2}, // 2008
+ {wxTreeCtrl_Create, "wxTreeCtrl", "create", 3}, // 2009
+ {wxTreeCtrl_Delete, "wxTreeCtrl", "delete", 2}, // 2010
+ {wxTreeCtrl_DeleteAllItems, "wxTreeCtrl", "deleteAllItems", 1}, // 2011
+ {wxTreeCtrl_DeleteChildren, "wxTreeCtrl", "deleteChildren", 2}, // 2012
+ {wxTreeCtrl_EditLabel, "wxTreeCtrl", "editLabel", 2}, // 2013
+ {wxTreeCtrl_EnsureVisible, "wxTreeCtrl", "ensureVisible", 2}, // 2014
+ {wxTreeCtrl_Expand, "wxTreeCtrl", "expand", 2}, // 2015
+ {wxTreeCtrl_GetBoundingRect, "wxTreeCtrl", "getBoundingRect", 3}, // 2016
+ {wxTreeCtrl_GetChildrenCount, "wxTreeCtrl", "getChildrenCount", 3}, // 2017
+ {wxTreeCtrl_GetCount, "wxTreeCtrl", "getCount", 1}, // 2018
+ {wxTreeCtrl_GetEditControl, "wxTreeCtrl", "getEditControl", 1}, // 2019
+ {wxTreeCtrl_GetFirstChild, "wxTreeCtrl", "getFirstChild", 2}, // 2020
+ {wxTreeCtrl_GetNextChild, "wxTreeCtrl", "getNextChild", 3}, // 2021
+ {wxTreeCtrl_GetFirstVisibleItem, "wxTreeCtrl", "getFirstVisibleItem", 1}, // 2022
+ {wxTreeCtrl_GetImageList, "wxTreeCtrl", "getImageList", 1}, // 2023
+ {wxTreeCtrl_GetIndent, "wxTreeCtrl", "getIndent", 1}, // 2024
+ {wxTreeCtrl_GetItemBackgroundColour, "wxTreeCtrl", "getItemBackgroundColour", 2}, // 2025
+ {wxTreeCtrl_GetItemData, "wxTreeCtrl", "getItemData", 2}, // 2026
+ {wxTreeCtrl_GetItemFont, "wxTreeCtrl", "getItemFont", 2}, // 2027
+ {wxTreeCtrl_GetItemImage, "wxTreeCtrl", "getItemImage", 3}, // 2028
+ {wxTreeCtrl_GetItemText, "wxTreeCtrl", "getItemText", 2}, // 2029
+ {wxTreeCtrl_GetItemTextColour, "wxTreeCtrl", "getItemTextColour", 2}, // 2030
+ {wxTreeCtrl_GetLastChild, "wxTreeCtrl", "getLastChild", 2}, // 2031
+ {wxTreeCtrl_GetNextSibling, "wxTreeCtrl", "getNextSibling", 2}, // 2032
+ {wxTreeCtrl_GetNextVisible, "wxTreeCtrl", "getNextVisible", 2}, // 2033
+ {wxTreeCtrl_GetItemParent, "wxTreeCtrl", "getItemParent", 2}, // 2034
+ {wxTreeCtrl_GetPrevSibling, "wxTreeCtrl", "getPrevSibling", 2}, // 2035
+ {wxTreeCtrl_GetPrevVisible, "wxTreeCtrl", "getPrevVisible", 2}, // 2036
+ {wxTreeCtrl_GetRootItem, "wxTreeCtrl", "getRootItem", 1}, // 2037
+ {wxTreeCtrl_GetSelection, "wxTreeCtrl", "getSelection", 1}, // 2038
+ {wxTreeCtrl_GetSelections, "wxTreeCtrl", "getSelections", 1}, // 2039
+ {wxTreeCtrl_GetStateImageList, "wxTreeCtrl", "getStateImageList", 1}, // 2040
+ {wxTreeCtrl_HitTest, "wxTreeCtrl", "hitTest", 2}, // 2041
+ {wxTreeCtrl_InsertItem, "wxTreeCtrl", "insertItem", 5}, // 2042
+ {NULL, "", "", 0}, // 2043
+ {wxTreeCtrl_IsBold, "wxTreeCtrl", "isBold", 2}, // 2044
+ {wxTreeCtrl_IsExpanded, "wxTreeCtrl", "isExpanded", 2}, // 2045
+ {wxTreeCtrl_IsSelected, "wxTreeCtrl", "isSelected", 2}, // 2046
+ {wxTreeCtrl_IsVisible, "wxTreeCtrl", "isVisible", 2}, // 2047
+ {wxTreeCtrl_ItemHasChildren, "wxTreeCtrl", "itemHasChildren", 2}, // 2048
+ {wxTreeCtrl_IsTreeItemIdOk, "wxTreeCtrl", "isTreeItemIdOk", 1}, // 2049
+ {wxTreeCtrl_PrependItem, "wxTreeCtrl", "prependItem", 4}, // 2050
+ {wxTreeCtrl_ScrollTo, "wxTreeCtrl", "scrollTo", 2}, // 2051
+ {wxTreeCtrl_SelectItem, "wxTreeCtrl", "selectItem", 3}, // 2052
+ {wxTreeCtrl_SetIndent, "wxTreeCtrl", "setIndent", 2}, // 2053
+ {wxTreeCtrl_SetImageList, "wxTreeCtrl", "setImageList", 2}, // 2054
+ {wxTreeCtrl_SetItemBackgroundColour, "wxTreeCtrl", "setItemBackgroundColour", 3}, // 2055
+ {wxTreeCtrl_SetItemBold, "wxTreeCtrl", "setItemBold", 3}, // 2056
+ {wxTreeCtrl_SetItemData, "wxTreeCtrl", "setItemData", 3}, // 2057
+ {wxTreeCtrl_SetItemDropHighlight, "wxTreeCtrl", "setItemDropHighlight", 3}, // 2058
+ {wxTreeCtrl_SetItemFont, "wxTreeCtrl", "setItemFont", 3}, // 2059
+ {wxTreeCtrl_SetItemHasChildren, "wxTreeCtrl", "setItemHasChildren", 3}, // 2060
+ {wxTreeCtrl_SetItemImage, "wxTreeCtrl", "setItemImage", 4}, // 2061
+ {wxTreeCtrl_SetItemText, "wxTreeCtrl", "setItemText", 3}, // 2062
+ {wxTreeCtrl_SetItemTextColour, "wxTreeCtrl", "setItemTextColour", 3}, // 2063
+ {wxTreeCtrl_SetStateImageList, "wxTreeCtrl", "setStateImageList", 2}, // 2064
+ {wxTreeCtrl_SetWindowStyle, "wxTreeCtrl", "setWindowStyle", 2}, // 2065
+ {wxTreeCtrl_SortChildren, "wxTreeCtrl", "sortChildren", 2}, // 2066
+ {wxTreeCtrl_Toggle, "wxTreeCtrl", "toggle", 2}, // 2067
+ {wxTreeCtrl_ToggleItemSelection, "wxTreeCtrl", "toggleItemSelection", 2}, // 2068
+ {wxTreeCtrl_Unselect, "wxTreeCtrl", "unselect", 1}, // 2069
+ {wxTreeCtrl_UnselectAll, "wxTreeCtrl", "unselectAll", 1}, // 2070
+ {wxTreeCtrl_UnselectItem, "wxTreeCtrl", "unselectItem", 2}, // 2071
+ {wxScrollBar_new_0, "wxScrollBar", "new", 0}, // 2072
+ {wxScrollBar_new_3, "wxScrollBar", "new", 3}, // 2073
+ {NULL, "wxScrollBar", "destroy", 1}, // 2074 obj destructor wxScrollBar_destruct
+ {wxScrollBar_Create, "wxScrollBar", "create", 4}, // 2075
+ {wxScrollBar_GetRange, "wxScrollBar", "getRange", 1}, // 2076
+ {wxScrollBar_GetPageSize, "wxScrollBar", "getPageSize", 1}, // 2077
+ {wxScrollBar_GetThumbPosition, "wxScrollBar", "getThumbPosition", 1}, // 2078
+ {wxScrollBar_GetThumbSize, "wxScrollBar", "getThumbSize", 1}, // 2079
+ {wxScrollBar_SetThumbPosition, "wxScrollBar", "setThumbPosition", 2}, // 2080
+ {wxScrollBar_SetScrollbar, "wxScrollBar", "setScrollbar", 6}, // 2081
+ {wxSpinButton_new_0, "wxSpinButton", "new", 0}, // 2082
+ {wxSpinButton_new_2, "wxSpinButton", "new", 2}, // 2083
+ {NULL, "wxSpinButton", "destroy", 1}, // 2084 obj destructor wxSpinButton_destruct
+ {wxSpinButton_Create, "wxSpinButton", "create", 3}, // 2085
+ {wxSpinButton_GetMax, "wxSpinButton", "getMax", 1}, // 2086
+ {wxSpinButton_GetMin, "wxSpinButton", "getMin", 1}, // 2087
+ {wxSpinButton_GetValue, "wxSpinButton", "getValue", 1}, // 2088
+ {wxSpinButton_SetRange, "wxSpinButton", "setRange", 3}, // 2089
+ {wxSpinButton_SetValue, "wxSpinButton", "setValue", 2}, // 2090
+ {wxSpinCtrl_new_0, "wxSpinCtrl", "new", 0}, // 2091
+ {wxSpinCtrl_new_2, "wxSpinCtrl", "new", 2}, // 2092
+ {wxSpinCtrl_Create, "wxSpinCtrl", "create", 3}, // 2093
+ {wxSpinCtrl_SetValue_1_1, "wxSpinCtrl", "setValue", 2}, // 2094
+ {wxSpinCtrl_SetValue_1_0, "wxSpinCtrl", "setValue", 2}, // 2095
+ {wxSpinCtrl_GetValue, "wxSpinCtrl", "getValue", 1}, // 2096
+ {wxSpinCtrl_SetRange, "wxSpinCtrl", "setRange", 3}, // 2097
+ {wxSpinCtrl_SetSelection, "wxSpinCtrl", "setSelection", 3}, // 2098
+ {wxSpinCtrl_GetMin, "wxSpinCtrl", "getMin", 1}, // 2099
+ {wxSpinCtrl_GetMax, "wxSpinCtrl", "getMax", 1}, // 2100
+ {NULL, "wxSpinCtrl", "'Destroy'", 1}, // 2101 obj destructor wxSpinCtrl_destroy
+ {wxStaticText_new_0, "wxStaticText", "new", 0}, // 2102
+ {wxStaticText_new_4, "wxStaticText", "new", 4}, // 2103
+ {wxStaticText_Create, "wxStaticText", "create", 5}, // 2104
+ {wxStaticText_GetLabel, "wxStaticText", "getLabel", 1}, // 2105
+ {wxStaticText_SetLabel, "wxStaticText", "setLabel", 2}, // 2106
+ {wxStaticText_Wrap, "wxStaticText", "wrap", 2}, // 2107
+ {NULL, "wxStaticText", "'Destroy'", 1}, // 2108 obj destructor wxStaticText_destroy
+ {wxStaticBitmap_new_0, "wxStaticBitmap", "new", 0}, // 2109
+ {wxStaticBitmap_new_4, "wxStaticBitmap", "new", 4}, // 2110
+ {wxStaticBitmap_Create, "wxStaticBitmap", "create", 5}, // 2111
+ {wxStaticBitmap_GetBitmap, "wxStaticBitmap", "getBitmap", 1}, // 2112
+ {wxStaticBitmap_SetBitmap, "wxStaticBitmap", "setBitmap", 2}, // 2113
+ {NULL, "wxStaticBitmap", "'Destroy'", 1}, // 2114 obj destructor wxStaticBitmap_destroy
+ {wxRadioBox_new, "wxRadioBox", "new", 7}, // 2115
+ {NULL, "wxRadioBox", "destroy", 1}, // 2116 obj destructor wxRadioBox_destruct
+ {wxRadioBox_Create, "wxRadioBox", "create", 8}, // 2117
+ {wxRadioBox_Enable_1, "wxRadioBox", "enable", 2}, // 2118
+ {wxRadioBox_Enable_2, "wxRadioBox", "enable", 3}, // 2119
+ {wxRadioBox_GetSelection, "wxRadioBox", "getSelection", 1}, // 2120
+ {wxRadioBox_GetString, "wxRadioBox", "getString", 2}, // 2121
+ {wxRadioBox_SetSelection, "wxRadioBox", "setSelection", 2}, // 2122
+ {wxRadioBox_Show, "wxRadioBox", "show", 3}, // 2123
+ {wxRadioBox_GetColumnCount, "wxRadioBox", "getColumnCount", 1}, // 2124
+ {wxRadioBox_GetItemHelpText, "wxRadioBox", "getItemHelpText", 2}, // 2125
+ {wxRadioBox_GetItemToolTip, "wxRadioBox", "getItemToolTip", 2}, // 2126
+ {wxRadioBox_GetItemFromPoint, "wxRadioBox", "getItemFromPoint", 2}, // 2127
+ {wxRadioBox_GetRowCount, "wxRadioBox", "getRowCount", 1}, // 2128
+ {wxRadioBox_IsItemEnabled, "wxRadioBox", "isItemEnabled", 2}, // 2129
+ {wxRadioBox_IsItemShown, "wxRadioBox", "isItemShown", 2}, // 2130
+ {wxRadioBox_SetItemHelpText, "wxRadioBox", "setItemHelpText", 3}, // 2131
+ {wxRadioBox_SetItemToolTip, "wxRadioBox", "setItemToolTip", 3}, // 2132
+ {wxRadioButton_new_0, "wxRadioButton", "new", 0}, // 2133
+ {wxRadioButton_new_4, "wxRadioButton", "new", 4}, // 2134
+ {NULL, "wxRadioButton", "destroy", 1}, // 2135 obj destructor wxRadioButton_destruct
+ {wxRadioButton_Create, "wxRadioButton", "create", 5}, // 2136
+ {wxRadioButton_GetValue, "wxRadioButton", "getValue", 1}, // 2137
+ {wxRadioButton_SetValue, "wxRadioButton", "setValue", 2}, // 2138
+ {wxSlider_new_0, "wxSlider", "new", 0}, // 2139
+ {wxSlider_new_6, "wxSlider", "new", 6}, // 2140
+ {NULL, "wxSlider", "destroy", 1}, // 2141 obj destructor wxSlider_destruct
+ {wxSlider_Create, "wxSlider", "create", 7}, // 2142
+ {wxSlider_GetLineSize, "wxSlider", "getLineSize", 1}, // 2143
+ {wxSlider_GetMax, "wxSlider", "getMax", 1}, // 2144
+ {wxSlider_GetMin, "wxSlider", "getMin", 1}, // 2145
+ {wxSlider_GetPageSize, "wxSlider", "getPageSize", 1}, // 2146
+ {wxSlider_GetThumbLength, "wxSlider", "getThumbLength", 1}, // 2147
+ {wxSlider_GetValue, "wxSlider", "getValue", 1}, // 2148
+ {wxSlider_SetLineSize, "wxSlider", "setLineSize", 2}, // 2149
+ {wxSlider_SetPageSize, "wxSlider", "setPageSize", 2}, // 2150
+ {wxSlider_SetRange, "wxSlider", "setRange", 3}, // 2151
+ {wxSlider_SetThumbLength, "wxSlider", "setThumbLength", 2}, // 2152
+ {wxSlider_SetValue, "wxSlider", "setValue", 2}, // 2153
+ {wxDialog_new_0, "wxDialog", "new", 0}, // 2154
+ {wxDialog_new_4, "wxDialog", "new", 4}, // 2155
+ {NULL, "wxDialog", "destroy", 1}, // 2156 obj destructor wxDialog_destruct
+ {wxDialog_Create, "wxDialog", "create", 5}, // 2157
+ {wxDialog_CreateButtonSizer, "wxDialog", "createButtonSizer", 2}, // 2158
+ {wxDialog_CreateStdDialogButtonSizer, "wxDialog", "createStdDialogButtonSizer", 2}, // 2159
+ {wxDialog_EndModal, "wxDialog", "endModal", 2}, // 2160
+ {wxDialog_GetAffirmativeId, "wxDialog", "getAffirmativeId", 1}, // 2161
+ {wxDialog_GetReturnCode, "wxDialog", "getReturnCode", 1}, // 2162
+ {wxDialog_IsModal, "wxDialog", "isModal", 1}, // 2163
+ {wxDialog_SetAffirmativeId, "wxDialog", "setAffirmativeId", 2}, // 2164
+ {wxDialog_SetReturnCode, "wxDialog", "setReturnCode", 2}, // 2165
+ {wxDialog_Show, "wxDialog", "show", 2}, // 2166
+ {wxDialog_ShowModal, "wxDialog", "showModal", 1}, // 2167
+ {wxColourDialog_new_0, "wxColourDialog", "new", 0}, // 2168
+ {wxColourDialog_new_2, "wxColourDialog", "new", 2}, // 2169
+ {NULL, "wxColourDialog", "destroy", 1}, // 2170 obj destructor wxColourDialog_destruct
+ {wxColourDialog_Create, "wxColourDialog", "create", 3}, // 2171
+ {wxColourDialog_GetColourData, "wxColourDialog", "getColourData", 1}, // 2172
+ {wxColourData_new, "wxColourData", "new", 0}, // 2173
+ {NULL, "wxColourData", "destroy", 1}, // 2174 obj destructor wxColourData_destruct
+ {wxColourData_GetChooseFull, "wxColourData", "getChooseFull", 1}, // 2175
+ {wxColourData_GetColour, "wxColourData", "getColour", 1}, // 2176
+ {wxColourData_GetCustomColour, "wxColourData", "getCustomColour", 2}, // 2177
+ {wxColourData_SetChooseFull, "wxColourData", "setChooseFull", 2}, // 2178
+ {wxColourData_SetColour, "wxColourData", "setColour", 2}, // 2179
+ {wxColourData_SetCustomColour, "wxColourData", "setCustomColour", 3}, // 2180
+ {wxPalette_new_0, "wxPalette", "new", 0}, // 2181
+ {wxPalette_new_1, "wxPalette", "new", 1}, // 2182
+ {wxPalette_new_4, "wxPalette", "new", 3}, // 2183
+ {NULL, "wxPalette", "destroy", 1}, // 2184 obj destructor wxPalette_destruct
+ {wxPalette_Create, "wxPalette", "create", 4}, // 2185
+ {wxPalette_GetColoursCount, "wxPalette", "getColoursCount", 1}, // 2186
+ {wxPalette_GetPixel, "wxPalette", "getPixel", 4}, // 2187
+ {wxPalette_GetRGB, "wxPalette", "getRGB", 2}, // 2188
+ {wxPalette_IsOk, "wxPalette", "isOk", 1}, // 2189
+ {wxDirDialog_new, "wxDirDialog", "new", 2}, // 2190
+ {NULL, "wxDirDialog", "destroy", 1}, // 2191 obj destructor wxDirDialog_destruct
+ {wxDirDialog_GetPath, "wxDirDialog", "getPath", 1}, // 2192
+ {wxDirDialog_GetMessage, "wxDirDialog", "getMessage", 1}, // 2193
+ {wxDirDialog_SetMessage, "wxDirDialog", "setMessage", 2}, // 2194
+ {wxDirDialog_SetPath, "wxDirDialog", "setPath", 2}, // 2195
+ {wxFileDialog_new, "wxFileDialog", "new", 2}, // 2196
+ {NULL, "wxFileDialog", "destroy", 1}, // 2197 obj destructor wxFileDialog_destruct
+ {wxFileDialog_GetDirectory, "wxFileDialog", "getDirectory", 1}, // 2198
+ {wxFileDialog_GetFilename, "wxFileDialog", "getFilename", 1}, // 2199
+ {wxFileDialog_GetFilenames, "wxFileDialog", "getFilenames", 1}, // 2200
+ {wxFileDialog_GetFilterIndex, "wxFileDialog", "getFilterIndex", 1}, // 2201
+ {wxFileDialog_GetMessage, "wxFileDialog", "getMessage", 1}, // 2202
+ {wxFileDialog_GetPath, "wxFileDialog", "getPath", 1}, // 2203
+ {wxFileDialog_GetPaths, "wxFileDialog", "getPaths", 1}, // 2204
+ {wxFileDialog_GetWildcard, "wxFileDialog", "getWildcard", 1}, // 2205
+ {wxFileDialog_SetDirectory, "wxFileDialog", "setDirectory", 2}, // 2206
+ {wxFileDialog_SetFilename, "wxFileDialog", "setFilename", 2}, // 2207
+ {wxFileDialog_SetFilterIndex, "wxFileDialog", "setFilterIndex", 2}, // 2208
+ {wxFileDialog_SetMessage, "wxFileDialog", "setMessage", 2}, // 2209
+ {wxFileDialog_SetPath, "wxFileDialog", "setPath", 2}, // 2210
+ {wxFileDialog_SetWildcard, "wxFileDialog", "setWildcard", 2}, // 2211
+ {wxPickerBase_SetInternalMargin, "wxPickerBase", "setInternalMargin", 2}, // 2212
+ {wxPickerBase_GetInternalMargin, "wxPickerBase", "getInternalMargin", 1}, // 2213
+ {wxPickerBase_SetTextCtrlProportion, "wxPickerBase", "setTextCtrlProportion", 2}, // 2214
+ {wxPickerBase_SetPickerCtrlProportion, "wxPickerBase", "setPickerCtrlProportion", 2}, // 2215
+ {wxPickerBase_GetTextCtrlProportion, "wxPickerBase", "getTextCtrlProportion", 1}, // 2216
+ {wxPickerBase_GetPickerCtrlProportion, "wxPickerBase", "getPickerCtrlProportion", 1}, // 2217
+ {wxPickerBase_HasTextCtrl, "wxPickerBase", "hasTextCtrl", 1}, // 2218
+ {wxPickerBase_GetTextCtrl, "wxPickerBase", "getTextCtrl", 1}, // 2219
+ {wxPickerBase_IsTextCtrlGrowable, "wxPickerBase", "isTextCtrlGrowable", 1}, // 2220
+ {wxPickerBase_SetPickerCtrlGrowable, "wxPickerBase", "setPickerCtrlGrowable", 2}, // 2221
+ {wxPickerBase_SetTextCtrlGrowable, "wxPickerBase", "setTextCtrlGrowable", 2}, // 2222
+ {wxPickerBase_IsPickerCtrlGrowable, "wxPickerBase", "isPickerCtrlGrowable", 1}, // 2223
+ {wxFilePickerCtrl_new_0, "wxFilePickerCtrl", "new", 0}, // 2224
+ {wxFilePickerCtrl_new_3, "wxFilePickerCtrl", "new", 3}, // 2225
+ {wxFilePickerCtrl_Create, "wxFilePickerCtrl", "create", 4}, // 2226
+ {wxFilePickerCtrl_GetPath, "wxFilePickerCtrl", "getPath", 1}, // 2227
+ {wxFilePickerCtrl_SetPath, "wxFilePickerCtrl", "setPath", 2}, // 2228
+ {NULL, "wxFilePickerCtrl", "'Destroy'", 1}, // 2229 obj destructor wxFilePickerCtrl_destroy
+ {wxDirPickerCtrl_new_0, "wxDirPickerCtrl", "new", 0}, // 2230
+ {wxDirPickerCtrl_new_3, "wxDirPickerCtrl", "new", 3}, // 2231
+ {wxDirPickerCtrl_Create, "wxDirPickerCtrl", "create", 4}, // 2232
+ {wxDirPickerCtrl_GetPath, "wxDirPickerCtrl", "getPath", 1}, // 2233
+ {wxDirPickerCtrl_SetPath, "wxDirPickerCtrl", "setPath", 2}, // 2234
+ {NULL, "wxDirPickerCtrl", "'Destroy'", 1}, // 2235 obj destructor wxDirPickerCtrl_destroy
+ {wxColourPickerCtrl_new_0, "wxColourPickerCtrl", "new", 0}, // 2236
+ {wxColourPickerCtrl_new_3, "wxColourPickerCtrl", "new", 3}, // 2237
+ {wxColourPickerCtrl_Create, "wxColourPickerCtrl", "create", 4}, // 2238
+ {wxColourPickerCtrl_GetColour, "wxColourPickerCtrl", "getColour", 1}, // 2239
+ {wxColourPickerCtrl_SetColour_1_1, "wxColourPickerCtrl", "setColour", 2}, // 2240
+ {wxColourPickerCtrl_SetColour_1_0, "wxColourPickerCtrl", "setColour", 2}, // 2241
+ {NULL, "wxColourPickerCtrl", "'Destroy'", 1}, // 2242 obj destructor wxColourPickerCtrl_destroy
+ {wxDatePickerCtrl_new_0, "wxDatePickerCtrl", "new", 0}, // 2243
+ {wxDatePickerCtrl_new_3, "wxDatePickerCtrl", "new", 3}, // 2244
+ {wxDatePickerCtrl_GetRange, "wxDatePickerCtrl", "getRange", 3}, // 2245
+ {wxDatePickerCtrl_GetValue, "wxDatePickerCtrl", "getValue", 1}, // 2246
+ {wxDatePickerCtrl_SetRange, "wxDatePickerCtrl", "setRange", 3}, // 2247
+ {wxDatePickerCtrl_SetValue, "wxDatePickerCtrl", "setValue", 2}, // 2248
+ {NULL, "wxDatePickerCtrl", "'Destroy'", 1}, // 2249 obj destructor wxDatePickerCtrl_destroy
+ {wxFontPickerCtrl_new_0, "wxFontPickerCtrl", "new", 0}, // 2250
+ {wxFontPickerCtrl_new_3, "wxFontPickerCtrl", "new", 3}, // 2251
+ {wxFontPickerCtrl_Create, "wxFontPickerCtrl", "create", 4}, // 2252
+ {wxFontPickerCtrl_GetSelectedFont, "wxFontPickerCtrl", "getSelectedFont", 1}, // 2253
+ {wxFontPickerCtrl_SetSelectedFont, "wxFontPickerCtrl", "setSelectedFont", 2}, // 2254
+ {wxFontPickerCtrl_GetMaxPointSize, "wxFontPickerCtrl", "getMaxPointSize", 1}, // 2255
+ {wxFontPickerCtrl_SetMaxPointSize, "wxFontPickerCtrl", "setMaxPointSize", 2}, // 2256
+ {NULL, "wxFontPickerCtrl", "'Destroy'", 1}, // 2257 obj destructor wxFontPickerCtrl_destroy
+ {wxFindReplaceDialog_new_0, "wxFindReplaceDialog", "new", 0}, // 2258
+ {wxFindReplaceDialog_new_4, "wxFindReplaceDialog", "new", 4}, // 2259
+ {NULL, "wxFindReplaceDialog", "destroy", 1}, // 2260 obj destructor wxFindReplaceDialog_destruct
+ {wxFindReplaceDialog_Create, "wxFindReplaceDialog", "create", 5}, // 2261
+ {wxFindReplaceDialog_GetData, "wxFindReplaceDialog", "getData", 1}, // 2262
+ {wxFindReplaceData_new, "wxFindReplaceData", "new", 1}, // 2263
+ {wxFindReplaceData_GetFindString, "wxFindReplaceData", "getFindString", 1}, // 2264
+ {wxFindReplaceData_GetReplaceString, "wxFindReplaceData", "getReplaceString", 1}, // 2265
+ {wxFindReplaceData_GetFlags, "wxFindReplaceData", "getFlags", 1}, // 2266
+ {wxFindReplaceData_SetFlags, "wxFindReplaceData", "setFlags", 2}, // 2267
+ {wxFindReplaceData_SetFindString, "wxFindReplaceData", "setFindString", 2}, // 2268
+ {wxFindReplaceData_SetReplaceString, "wxFindReplaceData", "setReplaceString", 2}, // 2269
+ {NULL, "wxFindReplaceData", "'Destroy'", 1}, // 2270 obj destructor wxFindReplaceData_destroy
+ {NULL, "", "", 0}, // 2271
+ {wxMultiChoiceDialog_new, "wxMultiChoiceDialog", "new", 5}, // 2272
+ {wxMultiChoiceDialog_GetSelections, "wxMultiChoiceDialog", "getSelections", 1}, // 2273
+ {wxMultiChoiceDialog_SetSelections, "wxMultiChoiceDialog", "setSelections", 2}, // 2274
+ {NULL, "wxMultiChoiceDialog", "'Destroy'", 1}, // 2275 obj destructor wxMultiChoiceDialog_destroy
+ {NULL, "", "", 0}, // 2276
+ {wxSingleChoiceDialog_new, "wxSingleChoiceDialog", "new", 5}, // 2277
+ {wxSingleChoiceDialog_GetSelection, "wxSingleChoiceDialog", "getSelection", 1}, // 2278
+ {wxSingleChoiceDialog_GetStringSelection, "wxSingleChoiceDialog", "getStringSelection", 1}, // 2279
+ {wxSingleChoiceDialog_SetSelection, "wxSingleChoiceDialog", "setSelection", 2}, // 2280
+ {NULL, "wxSingleChoiceDialog", "'Destroy'", 1}, // 2281 obj destructor wxSingleChoiceDialog_destroy
+ {wxTextEntryDialog_new_0, "wxTextEntryDialog", "new", 0}, // 2282
+ {wxTextEntryDialog_new_3, "wxTextEntryDialog", "new", 3}, // 2283
+ {NULL, "wxTextEntryDialog", "destroy", 1}, // 2284 obj destructor wxTextEntryDialog_destruct
+ {wxTextEntryDialog_GetValue, "wxTextEntryDialog", "getValue", 1}, // 2285
+ {wxTextEntryDialog_SetValue, "wxTextEntryDialog", "setValue", 2}, // 2286
+ {wxPasswordEntryDialog_new, "wxPasswordEntryDialog", "new", 3}, // 2287
+ {NULL, "wxPasswordEntryDialog", "'Destroy'", 1}, // 2288 obj destructor wxPasswordEntryDialog_destroy
+ {wxFontData_new_0, "wxFontData", "new", 0}, // 2289
+ {wxFontData_new_1, "wxFontData", "new", 1}, // 2290
+ {wxFontData_EnableEffects, "wxFontData", "enableEffects", 2}, // 2291
+ {wxFontData_GetAllowSymbols, "wxFontData", "getAllowSymbols", 1}, // 2292
+ {wxFontData_GetColour, "wxFontData", "getColour", 1}, // 2293
+ {wxFontData_GetChosenFont, "wxFontData", "getChosenFont", 1}, // 2294
+ {wxFontData_GetEnableEffects, "wxFontData", "getEnableEffects", 1}, // 2295
+ {wxFontData_GetInitialFont, "wxFontData", "getInitialFont", 1}, // 2296
+ {wxFontData_GetShowHelp, "wxFontData", "getShowHelp", 1}, // 2297
+ {wxFontData_SetAllowSymbols, "wxFontData", "setAllowSymbols", 2}, // 2298
+ {wxFontData_SetChosenFont, "wxFontData", "setChosenFont", 2}, // 2299
+ {wxFontData_SetColour, "wxFontData", "setColour", 2}, // 2300
+ {wxFontData_SetInitialFont, "wxFontData", "setInitialFont", 2}, // 2301
+ {wxFontData_SetRange, "wxFontData", "setRange", 3}, // 2302
+ {wxFontData_SetShowHelp, "wxFontData", "setShowHelp", 2}, // 2303
+ {NULL, "wxFontData", "'Destroy'", 1}, // 2304 obj destructor wxFontData_destroy
+ {wxFontDialog_new_0, "wxFontDialog", "new", 0}, // 2305
{NULL, "", "", 0}, // 2306
- {wxFontDialog_Create, "wxFontDialog", "create", 3}, // 2307
- {wxFontDialog_GetFontData, "wxFontDialog", "getFontData", 1}, // 2308
- {NULL, "", "", 0}, // 2309
- {NULL, "wxFontDialog", "'Destroy'", 1}, // 2310 obj destructor wxFontDialog_destroy
- {wxProgressDialog_new, "wxProgressDialog", "new", 3}, // 2311
- {wxProgressDialog_Resume, "wxProgressDialog", "resume", 1}, // 2312
- {wxProgressDialog_Update, "wxProgressDialog", "update", 3}, // 2313
- {NULL, "wxProgressDialog", "'Destroy'", 1}, // 2314 obj destructor wxProgressDialog_destroy
- {wxMessageDialog_new, "wxMessageDialog", "new", 3}, // 2315
- {NULL, "wxMessageDialog", "'Destroy'", 1}, // 2316 obj destructor wxMessageDialog_destroy
- {wxPageSetupDialog_new, "wxPageSetupDialog", "new", 2}, // 2317
- {NULL, "wxPageSetupDialog", "destroy", 1}, // 2318 obj destructor wxPageSetupDialog_destruct
- {wxPageSetupDialog_GetPageSetupData, "wxPageSetupDialog", "getPageSetupData", 1}, // 2319
- {wxPageSetupDialog_ShowModal, "wxPageSetupDialog", "showModal", 1}, // 2320
- {wxPageSetupDialogData_new_0, "wxPageSetupDialogData", "new", 0}, // 2321
- {NULL, "", "", 0}, // 2322
- {wxPageSetupDialogData_new_1, "wxPageSetupDialogData", "new", 1}, // 2323
- {NULL, "wxPageSetupDialogData", "destroy", 1}, // 2324 obj destructor wxPageSetupDialogData_destruct
- {wxPageSetupDialogData_EnableHelp, "wxPageSetupDialogData", "enableHelp", 2}, // 2325
- {wxPageSetupDialogData_EnableMargins, "wxPageSetupDialogData", "enableMargins", 2}, // 2326
- {wxPageSetupDialogData_EnableOrientation, "wxPageSetupDialogData", "enableOrientation", 2}, // 2327
- {wxPageSetupDialogData_EnablePaper, "wxPageSetupDialogData", "enablePaper", 2}, // 2328
- {wxPageSetupDialogData_EnablePrinter, "wxPageSetupDialogData", "enablePrinter", 2}, // 2329
- {wxPageSetupDialogData_GetDefaultMinMargins, "wxPageSetupDialogData", "getDefaultMinMargins", 1}, // 2330
- {wxPageSetupDialogData_GetEnableMargins, "wxPageSetupDialogData", "getEnableMargins", 1}, // 2331
- {wxPageSetupDialogData_GetEnableOrientation, "wxPageSetupDialogData", "getEnableOrientation", 1}, // 2332
- {wxPageSetupDialogData_GetEnablePaper, "wxPageSetupDialogData", "getEnablePaper", 1}, // 2333
- {wxPageSetupDialogData_GetEnablePrinter, "wxPageSetupDialogData", "getEnablePrinter", 1}, // 2334
- {wxPageSetupDialogData_GetEnableHelp, "wxPageSetupDialogData", "getEnableHelp", 1}, // 2335
- {wxPageSetupDialogData_GetDefaultInfo, "wxPageSetupDialogData", "getDefaultInfo", 1}, // 2336
- {wxPageSetupDialogData_GetMarginTopLeft, "wxPageSetupDialogData", "getMarginTopLeft", 1}, // 2337
- {wxPageSetupDialogData_GetMarginBottomRight, "wxPageSetupDialogData", "getMarginBottomRight", 1}, // 2338
- {wxPageSetupDialogData_GetMinMarginTopLeft, "wxPageSetupDialogData", "getMinMarginTopLeft", 1}, // 2339
- {wxPageSetupDialogData_GetMinMarginBottomRight, "wxPageSetupDialogData", "getMinMarginBottomRight", 1}, // 2340
- {wxPageSetupDialogData_GetPaperId, "wxPageSetupDialogData", "getPaperId", 1}, // 2341
- {wxPageSetupDialogData_GetPaperSize, "wxPageSetupDialogData", "getPaperSize", 1}, // 2342
- {NULL, "", "", 0}, // 2343
- {wxPageSetupDialogData_GetPrintData, "wxPageSetupDialogData", "getPrintData", 1}, // 2344
- {wxPageSetupDialogData_IsOk, "wxPageSetupDialogData", "isOk", 1}, // 2345
- {wxPageSetupDialogData_SetDefaultInfo, "wxPageSetupDialogData", "setDefaultInfo", 2}, // 2346
- {wxPageSetupDialogData_SetDefaultMinMargins, "wxPageSetupDialogData", "setDefaultMinMargins", 2}, // 2347
- {wxPageSetupDialogData_SetMarginTopLeft, "wxPageSetupDialogData", "setMarginTopLeft", 2}, // 2348
- {wxPageSetupDialogData_SetMarginBottomRight, "wxPageSetupDialogData", "setMarginBottomRight", 2}, // 2349
- {wxPageSetupDialogData_SetMinMarginTopLeft, "wxPageSetupDialogData", "setMinMarginTopLeft", 2}, // 2350
- {wxPageSetupDialogData_SetMinMarginBottomRight, "wxPageSetupDialogData", "setMinMarginBottomRight", 2}, // 2351
- {wxPageSetupDialogData_SetPaperId, "wxPageSetupDialogData", "setPaperId", 2}, // 2352
- {wxPageSetupDialogData_SetPaperSize, "wxPageSetupDialogData", "setPaperSize", 2}, // 2353
- {wxPageSetupDialogData_SetPrintData, "wxPageSetupDialogData", "setPrintData", 2}, // 2354
- {wxPrintDialog_new_2_0, "wxPrintDialog", "new", 2}, // 2355
- {wxPrintDialog_new_2_1, "wxPrintDialog", "new", 2}, // 2356
- {NULL, "wxPrintDialog", "destroy", 1}, // 2357 obj destructor wxPrintDialog_destruct
- {wxPrintDialog_GetPrintDialogData, "wxPrintDialog", "getPrintDialogData", 1}, // 2358
- {wxPrintDialog_GetPrintDC, "wxPrintDialog", "getPrintDC", 1}, // 2359
- {wxPrintDialogData_new_0, "wxPrintDialogData", "new", 0}, // 2360
- {wxPrintDialogData_new_1, "wxPrintDialogData", "new", 1}, // 2361
- {NULL, "", "", 0}, // 2362
- {NULL, "wxPrintDialogData", "destroy", 1}, // 2363 obj destructor wxPrintDialogData_destruct
- {wxPrintDialogData_EnableHelp, "wxPrintDialogData", "enableHelp", 2}, // 2364
- {wxPrintDialogData_EnablePageNumbers, "wxPrintDialogData", "enablePageNumbers", 2}, // 2365
- {wxPrintDialogData_EnablePrintToFile, "wxPrintDialogData", "enablePrintToFile", 2}, // 2366
- {wxPrintDialogData_EnableSelection, "wxPrintDialogData", "enableSelection", 2}, // 2367
- {wxPrintDialogData_GetAllPages, "wxPrintDialogData", "getAllPages", 1}, // 2368
- {wxPrintDialogData_GetCollate, "wxPrintDialogData", "getCollate", 1}, // 2369
- {wxPrintDialogData_GetFromPage, "wxPrintDialogData", "getFromPage", 1}, // 2370
- {wxPrintDialogData_GetMaxPage, "wxPrintDialogData", "getMaxPage", 1}, // 2371
- {wxPrintDialogData_GetMinPage, "wxPrintDialogData", "getMinPage", 1}, // 2372
- {wxPrintDialogData_GetNoCopies, "wxPrintDialogData", "getNoCopies", 1}, // 2373
- {wxPrintDialogData_GetPrintData, "wxPrintDialogData", "getPrintData", 1}, // 2374
- {wxPrintDialogData_GetPrintToFile, "wxPrintDialogData", "getPrintToFile", 1}, // 2375
- {wxPrintDialogData_GetSelection, "wxPrintDialogData", "getSelection", 1}, // 2376
- {wxPrintDialogData_GetToPage, "wxPrintDialogData", "getToPage", 1}, // 2377
- {wxPrintDialogData_IsOk, "wxPrintDialogData", "isOk", 1}, // 2378
- {wxPrintDialogData_SetCollate, "wxPrintDialogData", "setCollate", 2}, // 2379
- {wxPrintDialogData_SetFromPage, "wxPrintDialogData", "setFromPage", 2}, // 2380
- {wxPrintDialogData_SetMaxPage, "wxPrintDialogData", "setMaxPage", 2}, // 2381
- {wxPrintDialogData_SetMinPage, "wxPrintDialogData", "setMinPage", 2}, // 2382
- {wxPrintDialogData_SetNoCopies, "wxPrintDialogData", "setNoCopies", 2}, // 2383
- {wxPrintDialogData_SetPrintData, "wxPrintDialogData", "setPrintData", 2}, // 2384
- {wxPrintDialogData_SetPrintToFile, "wxPrintDialogData", "setPrintToFile", 2}, // 2385
- {wxPrintDialogData_SetSelection, "wxPrintDialogData", "setSelection", 2}, // 2386
- {wxPrintDialogData_SetToPage, "wxPrintDialogData", "setToPage", 2}, // 2387
- {wxPrintData_new_0, "wxPrintData", "new", 0}, // 2388
- {wxPrintData_new_1, "wxPrintData", "new", 1}, // 2389
- {NULL, "wxPrintData", "destroy", 1}, // 2390 obj destructor wxPrintData_destruct
- {wxPrintData_GetCollate, "wxPrintData", "getCollate", 1}, // 2391
- {wxPrintData_GetBin, "wxPrintData", "getBin", 1}, // 2392
- {wxPrintData_GetColour, "wxPrintData", "getColour", 1}, // 2393
- {wxPrintData_GetDuplex, "wxPrintData", "getDuplex", 1}, // 2394
- {wxPrintData_GetNoCopies, "wxPrintData", "getNoCopies", 1}, // 2395
- {wxPrintData_GetOrientation, "wxPrintData", "getOrientation", 1}, // 2396
- {wxPrintData_GetPaperId, "wxPrintData", "getPaperId", 1}, // 2397
- {wxPrintData_GetPrinterName, "wxPrintData", "getPrinterName", 1}, // 2398
- {wxPrintData_GetQuality, "wxPrintData", "getQuality", 1}, // 2399
- {wxPrintData_IsOk, "wxPrintData", "isOk", 1}, // 2400
- {wxPrintData_SetBin, "wxPrintData", "setBin", 2}, // 2401
- {wxPrintData_SetCollate, "wxPrintData", "setCollate", 2}, // 2402
- {wxPrintData_SetColour, "wxPrintData", "setColour", 2}, // 2403
- {wxPrintData_SetDuplex, "wxPrintData", "setDuplex", 2}, // 2404
- {wxPrintData_SetNoCopies, "wxPrintData", "setNoCopies", 2}, // 2405
- {wxPrintData_SetOrientation, "wxPrintData", "setOrientation", 2}, // 2406
- {wxPrintData_SetPaperId, "wxPrintData", "setPaperId", 2}, // 2407
- {wxPrintData_SetPrinterName, "wxPrintData", "setPrinterName", 2}, // 2408
- {wxPrintData_SetQuality, "wxPrintData", "setQuality", 2}, // 2409
- {wxPrintPreview_new_2, "wxPrintPreview", "new", 2}, // 2410
- {wxPrintPreview_new_3, "wxPrintPreview", "new", 3}, // 2411
- {NULL, "wxPrintPreview", "destroy", 1}, // 2412 obj destructor wxPrintPreview_destruct
- {wxPrintPreview_GetCanvas, "wxPrintPreview", "getCanvas", 1}, // 2413
- {wxPrintPreview_GetCurrentPage, "wxPrintPreview", "getCurrentPage", 1}, // 2414
- {wxPrintPreview_GetFrame, "wxPrintPreview", "getFrame", 1}, // 2415
- {wxPrintPreview_GetMaxPage, "wxPrintPreview", "getMaxPage", 1}, // 2416
- {wxPrintPreview_GetMinPage, "wxPrintPreview", "getMinPage", 1}, // 2417
- {wxPrintPreview_GetPrintout, "wxPrintPreview", "getPrintout", 1}, // 2418
- {wxPrintPreview_GetPrintoutForPrinting, "wxPrintPreview", "getPrintoutForPrinting", 1}, // 2419
- {wxPrintPreview_IsOk, "wxPrintPreview", "isOk", 1}, // 2420
- {wxPrintPreview_PaintPage, "wxPrintPreview", "paintPage", 3}, // 2421
- {wxPrintPreview_Print, "wxPrintPreview", "print", 2}, // 2422
- {wxPrintPreview_RenderPage, "wxPrintPreview", "renderPage", 2}, // 2423
- {wxPrintPreview_SetCanvas, "wxPrintPreview", "setCanvas", 2}, // 2424
- {wxPrintPreview_SetCurrentPage, "wxPrintPreview", "setCurrentPage", 2}, // 2425
- {wxPrintPreview_SetFrame, "wxPrintPreview", "setFrame", 2}, // 2426
- {wxPrintPreview_SetPrintout, "wxPrintPreview", "setPrintout", 2}, // 2427
- {wxPrintPreview_SetZoom, "wxPrintPreview", "setZoom", 2}, // 2428
- {wxPreviewFrame_new, "wxPreviewFrame", "new", 3}, // 2429
- {NULL, "wxPreviewFrame", "destroy", 1}, // 2430 obj destructor wxPreviewFrame_destruct
- {wxPreviewFrame_CreateControlBar, "wxPreviewFrame", "createControlBar", 1}, // 2431
- {wxPreviewFrame_CreateCanvas, "wxPreviewFrame", "createCanvas", 1}, // 2432
- {wxPreviewFrame_Initialize, "wxPreviewFrame", "initialize", 1}, // 2433
- {wxPreviewFrame_OnCloseWindow, "wxPreviewFrame", "onCloseWindow", 2}, // 2434
- {wxPreviewControlBar_new, "wxPreviewControlBar", "new", 4}, // 2435
- {NULL, "wxPreviewControlBar", "destroy", 1}, // 2436 obj destructor wxPreviewControlBar_destruct
- {wxPreviewControlBar_CreateButtons, "wxPreviewControlBar", "createButtons", 1}, // 2437
- {wxPreviewControlBar_GetPrintPreview, "wxPreviewControlBar", "getPrintPreview", 1}, // 2438
- {wxPreviewControlBar_GetZoomControl, "wxPreviewControlBar", "getZoomControl", 1}, // 2439
- {wxPreviewControlBar_SetZoomControl, "wxPreviewControlBar", "setZoomControl", 2}, // 2440
- {wxPrinter_new, "wxPrinter", "new", 1}, // 2441
- {wxPrinter_CreateAbortWindow, "wxPrinter", "createAbortWindow", 3}, // 2442
- {wxPrinter_GetAbort, "wxPrinter", "getAbort", 1}, // 2443
- {wxPrinter_GetLastError, "wxPrinter", "getLastError", 0}, // 2444
- {wxPrinter_GetPrintDialogData, "wxPrinter", "getPrintDialogData", 1}, // 2445
- {wxPrinter_Print, "wxPrinter", "print", 4}, // 2446
- {wxPrinter_PrintDialog, "wxPrinter", "printDialog", 2}, // 2447
- {wxPrinter_ReportError, "wxPrinter", "reportError", 4}, // 2448
- {wxPrinter_Setup, "wxPrinter", "setup", 2}, // 2449
- {NULL, "wxPrinter", "'Destroy'", 1}, // 2450 obj destructor wxPrinter_destroy
- {wxXmlResource_new_2, "wxXmlResource", "new", 2}, // 2451
- {wxXmlResource_new_1, "wxXmlResource", "new", 1}, // 2452
- {NULL, "wxXmlResource", "destroy", 1}, // 2453 obj destructor wxXmlResource_destruct
- {wxXmlResource_AttachUnknownControl, "wxXmlResource", "attachUnknownControl", 4}, // 2454
- {wxXmlResource_ClearHandlers, "wxXmlResource", "clearHandlers", 1}, // 2455
- {wxXmlResource_CompareVersion, "wxXmlResource", "compareVersion", 5}, // 2456
- {wxXmlResource_Get, "wxXmlResource", "get", 0}, // 2457
- {wxXmlResource_GetFlags, "wxXmlResource", "getFlags", 1}, // 2458
- {wxXmlResource_GetVersion, "wxXmlResource", "getVersion", 1}, // 2459
- {wxXmlResource_GetXRCID, "wxXmlResource", "getXRCID", 2}, // 2460
- {wxXmlResource_InitAllHandlers, "wxXmlResource", "initAllHandlers", 1}, // 2461
- {wxXmlResource_Load, "wxXmlResource", "load", 2}, // 2462
- {wxXmlResource_LoadBitmap, "wxXmlResource", "loadBitmap", 2}, // 2463
- {wxXmlResource_LoadDialog_2, "wxXmlResource", "loadDialog", 3}, // 2464
- {wxXmlResource_LoadDialog_3, "wxXmlResource", "loadDialog", 4}, // 2465
- {wxXmlResource_LoadFrame_2, "wxXmlResource", "loadFrame", 3}, // 2466
- {wxXmlResource_LoadFrame_3, "wxXmlResource", "loadFrame", 4}, // 2467
- {wxXmlResource_LoadIcon, "wxXmlResource", "loadIcon", 2}, // 2468
- {wxXmlResource_LoadMenu, "wxXmlResource", "loadMenu", 2}, // 2469
- {wxXmlResource_LoadMenuBar_2, "wxXmlResource", "loadMenuBar", 3}, // 2470
- {wxXmlResource_LoadMenuBar_1, "wxXmlResource", "loadMenuBar", 2}, // 2471
- {wxXmlResource_LoadPanel_2, "wxXmlResource", "loadPanel", 3}, // 2472
- {wxXmlResource_LoadPanel_3, "wxXmlResource", "loadPanel", 4}, // 2473
- {wxXmlResource_LoadToolBar, "wxXmlResource", "loadToolBar", 3}, // 2474
- {wxXmlResource_Set, "wxXmlResource", "set", 1}, // 2475
- {wxXmlResource_SetFlags, "wxXmlResource", "setFlags", 2}, // 2476
- {wxXmlResource_Unload, "wxXmlResource", "unload", 2}, // 2477
- {NULL, "wxXmlResource", "xrcctrl", 3}, // 2478 TaylorMade erl only wxXmlResource_xrcctrl
- {wxHtmlEasyPrinting_new, "wxHtmlEasyPrinting", "new", 1}, // 2479
- {wxHtmlEasyPrinting_GetPrintData, "wxHtmlEasyPrinting", "getPrintData", 1}, // 2480
- {wxHtmlEasyPrinting_GetPageSetupData, "wxHtmlEasyPrinting", "getPageSetupData", 1}, // 2481
- {wxHtmlEasyPrinting_PreviewFile, "wxHtmlEasyPrinting", "previewFile", 2}, // 2482
- {wxHtmlEasyPrinting_PreviewText, "wxHtmlEasyPrinting", "previewText", 3}, // 2483
- {wxHtmlEasyPrinting_PrintFile, "wxHtmlEasyPrinting", "printFile", 2}, // 2484
- {wxHtmlEasyPrinting_PrintText, "wxHtmlEasyPrinting", "printText", 3}, // 2485
- {wxHtmlEasyPrinting_PageSetup, "wxHtmlEasyPrinting", "pageSetup", 1}, // 2486
- {wxHtmlEasyPrinting_SetFonts, "wxHtmlEasyPrinting", "setFonts", 4}, // 2487
- {wxHtmlEasyPrinting_SetHeader, "wxHtmlEasyPrinting", "setHeader", 3}, // 2488
- {wxHtmlEasyPrinting_SetFooter, "wxHtmlEasyPrinting", "setFooter", 3}, // 2489
- {NULL, "wxHtmlEasyPrinting", "'Destroy'", 1}, // 2490 obj destructor wxHtmlEasyPrinting_destroy
+ {wxFontDialog_new_2, "wxFontDialog", "new", 2}, // 2307
+ {NULL, "", "", 0}, // 2308
+ {wxFontDialog_Create, "wxFontDialog", "create", 3}, // 2309
+ {wxFontDialog_GetFontData, "wxFontDialog", "getFontData", 1}, // 2310
+ {NULL, "", "", 0}, // 2311
+ {NULL, "wxFontDialog", "'Destroy'", 1}, // 2312 obj destructor wxFontDialog_destroy
+ {wxProgressDialog_new, "wxProgressDialog", "new", 3}, // 2313
+ {wxProgressDialog_Resume, "wxProgressDialog", "resume", 1}, // 2314
+ {wxProgressDialog_Update, "wxProgressDialog", "update", 3}, // 2315
+ {NULL, "wxProgressDialog", "'Destroy'", 1}, // 2316 obj destructor wxProgressDialog_destroy
+ {wxMessageDialog_new, "wxMessageDialog", "new", 3}, // 2317
+ {NULL, "wxMessageDialog", "'Destroy'", 1}, // 2318 obj destructor wxMessageDialog_destroy
+ {wxPageSetupDialog_new, "wxPageSetupDialog", "new", 2}, // 2319
+ {NULL, "wxPageSetupDialog", "destroy", 1}, // 2320 obj destructor wxPageSetupDialog_destruct
+ {wxPageSetupDialog_GetPageSetupData, "wxPageSetupDialog", "getPageSetupData", 1}, // 2321
+ {wxPageSetupDialog_ShowModal, "wxPageSetupDialog", "showModal", 1}, // 2322
+ {wxPageSetupDialogData_new_0, "wxPageSetupDialogData", "new", 0}, // 2323
+ {NULL, "", "", 0}, // 2324
+ {wxPageSetupDialogData_new_1, "wxPageSetupDialogData", "new", 1}, // 2325
+ {NULL, "wxPageSetupDialogData", "destroy", 1}, // 2326 obj destructor wxPageSetupDialogData_destruct
+ {wxPageSetupDialogData_EnableHelp, "wxPageSetupDialogData", "enableHelp", 2}, // 2327
+ {wxPageSetupDialogData_EnableMargins, "wxPageSetupDialogData", "enableMargins", 2}, // 2328
+ {wxPageSetupDialogData_EnableOrientation, "wxPageSetupDialogData", "enableOrientation", 2}, // 2329
+ {wxPageSetupDialogData_EnablePaper, "wxPageSetupDialogData", "enablePaper", 2}, // 2330
+ {wxPageSetupDialogData_EnablePrinter, "wxPageSetupDialogData", "enablePrinter", 2}, // 2331
+ {wxPageSetupDialogData_GetDefaultMinMargins, "wxPageSetupDialogData", "getDefaultMinMargins", 1}, // 2332
+ {wxPageSetupDialogData_GetEnableMargins, "wxPageSetupDialogData", "getEnableMargins", 1}, // 2333
+ {wxPageSetupDialogData_GetEnableOrientation, "wxPageSetupDialogData", "getEnableOrientation", 1}, // 2334
+ {wxPageSetupDialogData_GetEnablePaper, "wxPageSetupDialogData", "getEnablePaper", 1}, // 2335
+ {wxPageSetupDialogData_GetEnablePrinter, "wxPageSetupDialogData", "getEnablePrinter", 1}, // 2336
+ {wxPageSetupDialogData_GetEnableHelp, "wxPageSetupDialogData", "getEnableHelp", 1}, // 2337
+ {wxPageSetupDialogData_GetDefaultInfo, "wxPageSetupDialogData", "getDefaultInfo", 1}, // 2338
+ {wxPageSetupDialogData_GetMarginTopLeft, "wxPageSetupDialogData", "getMarginTopLeft", 1}, // 2339
+ {wxPageSetupDialogData_GetMarginBottomRight, "wxPageSetupDialogData", "getMarginBottomRight", 1}, // 2340
+ {wxPageSetupDialogData_GetMinMarginTopLeft, "wxPageSetupDialogData", "getMinMarginTopLeft", 1}, // 2341
+ {wxPageSetupDialogData_GetMinMarginBottomRight, "wxPageSetupDialogData", "getMinMarginBottomRight", 1}, // 2342
+ {wxPageSetupDialogData_GetPaperId, "wxPageSetupDialogData", "getPaperId", 1}, // 2343
+ {wxPageSetupDialogData_GetPaperSize, "wxPageSetupDialogData", "getPaperSize", 1}, // 2344
+ {NULL, "", "", 0}, // 2345
+ {wxPageSetupDialogData_GetPrintData, "wxPageSetupDialogData", "getPrintData", 1}, // 2346
+ {wxPageSetupDialogData_IsOk, "wxPageSetupDialogData", "isOk", 1}, // 2347
+ {wxPageSetupDialogData_SetDefaultInfo, "wxPageSetupDialogData", "setDefaultInfo", 2}, // 2348
+ {wxPageSetupDialogData_SetDefaultMinMargins, "wxPageSetupDialogData", "setDefaultMinMargins", 2}, // 2349
+ {wxPageSetupDialogData_SetMarginTopLeft, "wxPageSetupDialogData", "setMarginTopLeft", 2}, // 2350
+ {wxPageSetupDialogData_SetMarginBottomRight, "wxPageSetupDialogData", "setMarginBottomRight", 2}, // 2351
+ {wxPageSetupDialogData_SetMinMarginTopLeft, "wxPageSetupDialogData", "setMinMarginTopLeft", 2}, // 2352
+ {wxPageSetupDialogData_SetMinMarginBottomRight, "wxPageSetupDialogData", "setMinMarginBottomRight", 2}, // 2353
+ {wxPageSetupDialogData_SetPaperId, "wxPageSetupDialogData", "setPaperId", 2}, // 2354
+ {wxPageSetupDialogData_SetPaperSize, "wxPageSetupDialogData", "setPaperSize", 2}, // 2355
+ {wxPageSetupDialogData_SetPrintData, "wxPageSetupDialogData", "setPrintData", 2}, // 2356
+ {wxPrintDialog_new_2_0, "wxPrintDialog", "new", 2}, // 2357
+ {wxPrintDialog_new_2_1, "wxPrintDialog", "new", 2}, // 2358
+ {NULL, "wxPrintDialog", "destroy", 1}, // 2359 obj destructor wxPrintDialog_destruct
+ {wxPrintDialog_GetPrintDialogData, "wxPrintDialog", "getPrintDialogData", 1}, // 2360
+ {wxPrintDialog_GetPrintDC, "wxPrintDialog", "getPrintDC", 1}, // 2361
+ {wxPrintDialogData_new_0, "wxPrintDialogData", "new", 0}, // 2362
+ {wxPrintDialogData_new_1, "wxPrintDialogData", "new", 1}, // 2363
+ {NULL, "", "", 0}, // 2364
+ {NULL, "wxPrintDialogData", "destroy", 1}, // 2365 obj destructor wxPrintDialogData_destruct
+ {wxPrintDialogData_EnableHelp, "wxPrintDialogData", "enableHelp", 2}, // 2366
+ {wxPrintDialogData_EnablePageNumbers, "wxPrintDialogData", "enablePageNumbers", 2}, // 2367
+ {wxPrintDialogData_EnablePrintToFile, "wxPrintDialogData", "enablePrintToFile", 2}, // 2368
+ {wxPrintDialogData_EnableSelection, "wxPrintDialogData", "enableSelection", 2}, // 2369
+ {wxPrintDialogData_GetAllPages, "wxPrintDialogData", "getAllPages", 1}, // 2370
+ {wxPrintDialogData_GetCollate, "wxPrintDialogData", "getCollate", 1}, // 2371
+ {wxPrintDialogData_GetFromPage, "wxPrintDialogData", "getFromPage", 1}, // 2372
+ {wxPrintDialogData_GetMaxPage, "wxPrintDialogData", "getMaxPage", 1}, // 2373
+ {wxPrintDialogData_GetMinPage, "wxPrintDialogData", "getMinPage", 1}, // 2374
+ {wxPrintDialogData_GetNoCopies, "wxPrintDialogData", "getNoCopies", 1}, // 2375
+ {wxPrintDialogData_GetPrintData, "wxPrintDialogData", "getPrintData", 1}, // 2376
+ {wxPrintDialogData_GetPrintToFile, "wxPrintDialogData", "getPrintToFile", 1}, // 2377
+ {wxPrintDialogData_GetSelection, "wxPrintDialogData", "getSelection", 1}, // 2378
+ {wxPrintDialogData_GetToPage, "wxPrintDialogData", "getToPage", 1}, // 2379
+ {wxPrintDialogData_IsOk, "wxPrintDialogData", "isOk", 1}, // 2380
+ {wxPrintDialogData_SetCollate, "wxPrintDialogData", "setCollate", 2}, // 2381
+ {wxPrintDialogData_SetFromPage, "wxPrintDialogData", "setFromPage", 2}, // 2382
+ {wxPrintDialogData_SetMaxPage, "wxPrintDialogData", "setMaxPage", 2}, // 2383
+ {wxPrintDialogData_SetMinPage, "wxPrintDialogData", "setMinPage", 2}, // 2384
+ {wxPrintDialogData_SetNoCopies, "wxPrintDialogData", "setNoCopies", 2}, // 2385
+ {wxPrintDialogData_SetPrintData, "wxPrintDialogData", "setPrintData", 2}, // 2386
+ {wxPrintDialogData_SetPrintToFile, "wxPrintDialogData", "setPrintToFile", 2}, // 2387
+ {wxPrintDialogData_SetSelection, "wxPrintDialogData", "setSelection", 2}, // 2388
+ {wxPrintDialogData_SetToPage, "wxPrintDialogData", "setToPage", 2}, // 2389
+ {wxPrintData_new_0, "wxPrintData", "new", 0}, // 2390
+ {wxPrintData_new_1, "wxPrintData", "new", 1}, // 2391
+ {NULL, "wxPrintData", "destroy", 1}, // 2392 obj destructor wxPrintData_destruct
+ {wxPrintData_GetCollate, "wxPrintData", "getCollate", 1}, // 2393
+ {wxPrintData_GetBin, "wxPrintData", "getBin", 1}, // 2394
+ {wxPrintData_GetColour, "wxPrintData", "getColour", 1}, // 2395
+ {wxPrintData_GetDuplex, "wxPrintData", "getDuplex", 1}, // 2396
+ {wxPrintData_GetNoCopies, "wxPrintData", "getNoCopies", 1}, // 2397
+ {wxPrintData_GetOrientation, "wxPrintData", "getOrientation", 1}, // 2398
+ {wxPrintData_GetPaperId, "wxPrintData", "getPaperId", 1}, // 2399
+ {wxPrintData_GetPrinterName, "wxPrintData", "getPrinterName", 1}, // 2400
+ {wxPrintData_GetQuality, "wxPrintData", "getQuality", 1}, // 2401
+ {wxPrintData_IsOk, "wxPrintData", "isOk", 1}, // 2402
+ {wxPrintData_SetBin, "wxPrintData", "setBin", 2}, // 2403
+ {wxPrintData_SetCollate, "wxPrintData", "setCollate", 2}, // 2404
+ {wxPrintData_SetColour, "wxPrintData", "setColour", 2}, // 2405
+ {wxPrintData_SetDuplex, "wxPrintData", "setDuplex", 2}, // 2406
+ {wxPrintData_SetNoCopies, "wxPrintData", "setNoCopies", 2}, // 2407
+ {wxPrintData_SetOrientation, "wxPrintData", "setOrientation", 2}, // 2408
+ {wxPrintData_SetPaperId, "wxPrintData", "setPaperId", 2}, // 2409
+ {wxPrintData_SetPrinterName, "wxPrintData", "setPrinterName", 2}, // 2410
+ {wxPrintData_SetQuality, "wxPrintData", "setQuality", 2}, // 2411
+ {wxPrintPreview_new_2, "wxPrintPreview", "new", 2}, // 2412
+ {wxPrintPreview_new_3, "wxPrintPreview", "new", 3}, // 2413
+ {NULL, "wxPrintPreview", "destroy", 1}, // 2414 obj destructor wxPrintPreview_destruct
+ {wxPrintPreview_GetCanvas, "wxPrintPreview", "getCanvas", 1}, // 2415
+ {wxPrintPreview_GetCurrentPage, "wxPrintPreview", "getCurrentPage", 1}, // 2416
+ {wxPrintPreview_GetFrame, "wxPrintPreview", "getFrame", 1}, // 2417
+ {wxPrintPreview_GetMaxPage, "wxPrintPreview", "getMaxPage", 1}, // 2418
+ {wxPrintPreview_GetMinPage, "wxPrintPreview", "getMinPage", 1}, // 2419
+ {wxPrintPreview_GetPrintout, "wxPrintPreview", "getPrintout", 1}, // 2420
+ {wxPrintPreview_GetPrintoutForPrinting, "wxPrintPreview", "getPrintoutForPrinting", 1}, // 2421
+ {wxPrintPreview_IsOk, "wxPrintPreview", "isOk", 1}, // 2422
+ {wxPrintPreview_PaintPage, "wxPrintPreview", "paintPage", 3}, // 2423
+ {wxPrintPreview_Print, "wxPrintPreview", "print", 2}, // 2424
+ {wxPrintPreview_RenderPage, "wxPrintPreview", "renderPage", 2}, // 2425
+ {wxPrintPreview_SetCanvas, "wxPrintPreview", "setCanvas", 2}, // 2426
+ {wxPrintPreview_SetCurrentPage, "wxPrintPreview", "setCurrentPage", 2}, // 2427
+ {wxPrintPreview_SetFrame, "wxPrintPreview", "setFrame", 2}, // 2428
+ {wxPrintPreview_SetPrintout, "wxPrintPreview", "setPrintout", 2}, // 2429
+ {wxPrintPreview_SetZoom, "wxPrintPreview", "setZoom", 2}, // 2430
+ {wxPreviewFrame_new, "wxPreviewFrame", "new", 3}, // 2431
+ {NULL, "wxPreviewFrame", "destroy", 1}, // 2432 obj destructor wxPreviewFrame_destruct
+ {wxPreviewFrame_CreateControlBar, "wxPreviewFrame", "createControlBar", 1}, // 2433
+ {wxPreviewFrame_CreateCanvas, "wxPreviewFrame", "createCanvas", 1}, // 2434
+ {wxPreviewFrame_Initialize, "wxPreviewFrame", "initialize", 1}, // 2435
+ {wxPreviewFrame_OnCloseWindow, "wxPreviewFrame", "onCloseWindow", 2}, // 2436
+ {wxPreviewControlBar_new, "wxPreviewControlBar", "new", 4}, // 2437
+ {NULL, "wxPreviewControlBar", "destroy", 1}, // 2438 obj destructor wxPreviewControlBar_destruct
+ {wxPreviewControlBar_CreateButtons, "wxPreviewControlBar", "createButtons", 1}, // 2439
+ {wxPreviewControlBar_GetPrintPreview, "wxPreviewControlBar", "getPrintPreview", 1}, // 2440
+ {wxPreviewControlBar_GetZoomControl, "wxPreviewControlBar", "getZoomControl", 1}, // 2441
+ {wxPreviewControlBar_SetZoomControl, "wxPreviewControlBar", "setZoomControl", 2}, // 2442
+ {wxPrinter_new, "wxPrinter", "new", 1}, // 2443
+ {wxPrinter_CreateAbortWindow, "wxPrinter", "createAbortWindow", 3}, // 2444
+ {wxPrinter_GetAbort, "wxPrinter", "getAbort", 1}, // 2445
+ {wxPrinter_GetLastError, "wxPrinter", "getLastError", 0}, // 2446
+ {wxPrinter_GetPrintDialogData, "wxPrinter", "getPrintDialogData", 1}, // 2447
+ {wxPrinter_Print, "wxPrinter", "print", 4}, // 2448
+ {wxPrinter_PrintDialog, "wxPrinter", "printDialog", 2}, // 2449
+ {wxPrinter_ReportError, "wxPrinter", "reportError", 4}, // 2450
+ {wxPrinter_Setup, "wxPrinter", "setup", 2}, // 2451
+ {NULL, "wxPrinter", "'Destroy'", 1}, // 2452 obj destructor wxPrinter_destroy
+ {wxXmlResource_new_2, "wxXmlResource", "new", 2}, // 2453
+ {wxXmlResource_new_1, "wxXmlResource", "new", 1}, // 2454
+ {NULL, "wxXmlResource", "destroy", 1}, // 2455 obj destructor wxXmlResource_destruct
+ {wxXmlResource_AttachUnknownControl, "wxXmlResource", "attachUnknownControl", 4}, // 2456
+ {wxXmlResource_ClearHandlers, "wxXmlResource", "clearHandlers", 1}, // 2457
+ {wxXmlResource_CompareVersion, "wxXmlResource", "compareVersion", 5}, // 2458
+ {wxXmlResource_Get, "wxXmlResource", "get", 0}, // 2459
+ {wxXmlResource_GetFlags, "wxXmlResource", "getFlags", 1}, // 2460
+ {wxXmlResource_GetVersion, "wxXmlResource", "getVersion", 1}, // 2461
+ {wxXmlResource_GetXRCID, "wxXmlResource", "getXRCID", 2}, // 2462
+ {wxXmlResource_InitAllHandlers, "wxXmlResource", "initAllHandlers", 1}, // 2463
+ {wxXmlResource_Load, "wxXmlResource", "load", 2}, // 2464
+ {wxXmlResource_LoadBitmap, "wxXmlResource", "loadBitmap", 2}, // 2465
+ {wxXmlResource_LoadDialog_2, "wxXmlResource", "loadDialog", 3}, // 2466
+ {wxXmlResource_LoadDialog_3, "wxXmlResource", "loadDialog", 4}, // 2467
+ {wxXmlResource_LoadFrame_2, "wxXmlResource", "loadFrame", 3}, // 2468
+ {wxXmlResource_LoadFrame_3, "wxXmlResource", "loadFrame", 4}, // 2469
+ {wxXmlResource_LoadIcon, "wxXmlResource", "loadIcon", 2}, // 2470
+ {wxXmlResource_LoadMenu, "wxXmlResource", "loadMenu", 2}, // 2471
+ {wxXmlResource_LoadMenuBar_2, "wxXmlResource", "loadMenuBar", 3}, // 2472
+ {wxXmlResource_LoadMenuBar_1, "wxXmlResource", "loadMenuBar", 2}, // 2473
+ {wxXmlResource_LoadPanel_2, "wxXmlResource", "loadPanel", 3}, // 2474
+ {wxXmlResource_LoadPanel_3, "wxXmlResource", "loadPanel", 4}, // 2475
+ {wxXmlResource_LoadToolBar, "wxXmlResource", "loadToolBar", 3}, // 2476
+ {wxXmlResource_Set, "wxXmlResource", "set", 1}, // 2477
+ {wxXmlResource_SetFlags, "wxXmlResource", "setFlags", 2}, // 2478
+ {wxXmlResource_Unload, "wxXmlResource", "unload", 2}, // 2479
+ {NULL, "wxXmlResource", "xrcctrl", 3}, // 2480 TaylorMade erl only wxXmlResource_xrcctrl
+ {wxHtmlEasyPrinting_new, "wxHtmlEasyPrinting", "new", 1}, // 2481
+ {wxHtmlEasyPrinting_GetPrintData, "wxHtmlEasyPrinting", "getPrintData", 1}, // 2482
+ {wxHtmlEasyPrinting_GetPageSetupData, "wxHtmlEasyPrinting", "getPageSetupData", 1}, // 2483
+ {wxHtmlEasyPrinting_PreviewFile, "wxHtmlEasyPrinting", "previewFile", 2}, // 2484
+ {wxHtmlEasyPrinting_PreviewText, "wxHtmlEasyPrinting", "previewText", 3}, // 2485
+ {wxHtmlEasyPrinting_PrintFile, "wxHtmlEasyPrinting", "printFile", 2}, // 2486
+ {wxHtmlEasyPrinting_PrintText, "wxHtmlEasyPrinting", "printText", 3}, // 2487
+ {wxHtmlEasyPrinting_PageSetup, "wxHtmlEasyPrinting", "pageSetup", 1}, // 2488
+ {wxHtmlEasyPrinting_SetFonts, "wxHtmlEasyPrinting", "setFonts", 4}, // 2489
+ {wxHtmlEasyPrinting_SetHeader, "wxHtmlEasyPrinting", "setHeader", 3}, // 2490
+ {wxHtmlEasyPrinting_SetFooter, "wxHtmlEasyPrinting", "setFooter", 3}, // 2491
+ {NULL, "wxHtmlEasyPrinting", "'Destroy'", 1}, // 2492 obj destructor wxHtmlEasyPrinting_destroy
#if wxUSE_GLCANVAS
- {wxGLCanvas_new, "wxGLCanvas", "new", 2}, // 2491
+ {wxGLCanvas_new, "wxGLCanvas", "new", 2}, // 2493
#else
- {NULL, "wxGLCanvas", "new", 0}, // 2491
+ {NULL, "wxGLCanvas", "new", 0}, // 2493
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {wxGLCanvas_SetCurrent, "wxGLCanvas", "setCurrent", 2}, // 2492
+ {wxGLCanvas_SetCurrent, "wxGLCanvas", "setCurrent", 2}, // 2494
#else
- {NULL, "wxGLCanvas", "setCurrent", 0}, // 2492
+ {NULL, "wxGLCanvas", "setCurrent", 0}, // 2494
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {wxGLCanvas_SwapBuffers, "wxGLCanvas", "swapBuffers", 1}, // 2493
+ {wxGLCanvas_SwapBuffers, "wxGLCanvas", "swapBuffers", 1}, // 2495
#else
- {NULL, "wxGLCanvas", "swapBuffers", 0}, // 2493
+ {NULL, "wxGLCanvas", "swapBuffers", 0}, // 2495
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {NULL, "wxGLCanvas", "'Destroy'", 1}, // 2494 obj destructor wxGLCanvas_destroy
+ {NULL, "wxGLCanvas", "'Destroy'", 1}, // 2496 obj destructor wxGLCanvas_destroy
#else
- {NULL, "wxGLCanvas", "'Destroy'", 0}, // 2494
+ {NULL, "wxGLCanvas", "'Destroy'", 0}, // 2496
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {wxGLContext_new, "wxGLContext", "new", 2}, // 2495
+ {wxGLContext_new, "wxGLContext", "new", 2}, // 2497
#else
- {NULL, "wxGLContext", "new", 0}, // 2495
+ {NULL, "wxGLContext", "new", 0}, // 2497
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {wxGLContext_SetCurrent, "wxGLContext", "setCurrent", 2}, // 2496
+ {wxGLContext_SetCurrent, "wxGLContext", "setCurrent", 2}, // 2498
#else
- {NULL, "wxGLContext", "setCurrent", 0}, // 2496
+ {NULL, "wxGLContext", "setCurrent", 0}, // 2498
#endif // wxUSE_GLCANVAS
#if wxUSE_GLCANVAS
- {NULL, "wxGLContext", "'Destroy'", 1}, // 2497 obj destructor wxGLContext_destroy
+ {NULL, "wxGLContext", "'Destroy'", 1}, // 2499 obj destructor wxGLContext_destroy
#else
- {NULL, "wxGLContext", "'Destroy'", 0}, // 2497
+ {NULL, "wxGLContext", "'Destroy'", 0}, // 2499
#endif // wxUSE_GLCANVAS
#if wxUSE_AUI
- {wxAuiManager_new, "wxAuiManager", "new", 1}, // 2498
+ {wxAuiManager_new, "wxAuiManager", "new", 1}, // 2500
#else
- {NULL, "wxAuiManager", "new", 0}, // 2498
+ {NULL, "wxAuiManager", "new", 0}, // 2500
#endif // wxUSE_AUI
#if wxUSE_AUI
- {NULL, "wxAuiManager", "destroy", 1}, // 2499 obj destructor wxAuiManager_destruct
+ {NULL, "wxAuiManager", "destroy", 1}, // 2501 obj destructor wxAuiManager_destruct
#else
- {NULL, "wxAuiManager", "destroy", 0}, // 2499
+ {NULL, "wxAuiManager", "destroy", 0}, // 2501
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_AddPane_2_1, "wxAuiManager", "addPane", 3}, // 2500
+ {wxAuiManager_AddPane_2_1, "wxAuiManager", "addPane", 3}, // 2502
#else
- {NULL, "wxAuiManager", "addPane", 0}, // 2500
+ {NULL, "wxAuiManager", "addPane", 0}, // 2502
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_AddPane_2_0, "wxAuiManager", "addPane", 3}, // 2501
+ {wxAuiManager_AddPane_2_0, "wxAuiManager", "addPane", 3}, // 2503
#else
- {NULL, "wxAuiManager", "addPane", 0}, // 2501
+ {NULL, "wxAuiManager", "addPane", 0}, // 2503
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_AddPane_3, "wxAuiManager", "addPane", 4}, // 2502
+ {wxAuiManager_AddPane_3, "wxAuiManager", "addPane", 4}, // 2504
#else
- {NULL, "wxAuiManager", "addPane", 0}, // 2502
+ {NULL, "wxAuiManager", "addPane", 0}, // 2504
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_DetachPane, "wxAuiManager", "detachPane", 2}, // 2503
+ {wxAuiManager_DetachPane, "wxAuiManager", "detachPane", 2}, // 2505
#else
- {NULL, "wxAuiManager", "detachPane", 0}, // 2503
+ {NULL, "wxAuiManager", "detachPane", 0}, // 2505
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetAllPanes, "wxAuiManager", "getAllPanes", 1}, // 2504
+ {wxAuiManager_GetAllPanes, "wxAuiManager", "getAllPanes", 1}, // 2506
#else
- {NULL, "wxAuiManager", "getAllPanes", 0}, // 2504
+ {NULL, "wxAuiManager", "getAllPanes", 0}, // 2506
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetArtProvider, "wxAuiManager", "getArtProvider", 1}, // 2505
+ {wxAuiManager_GetArtProvider, "wxAuiManager", "getArtProvider", 1}, // 2507
#else
- {NULL, "wxAuiManager", "getArtProvider", 0}, // 2505
+ {NULL, "wxAuiManager", "getArtProvider", 0}, // 2507
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetDockSizeConstraint, "wxAuiManager", "getDockSizeConstraint", 1}, // 2506
+ {wxAuiManager_GetDockSizeConstraint, "wxAuiManager", "getDockSizeConstraint", 1}, // 2508
#else
- {NULL, "wxAuiManager", "getDockSizeConstraint", 0}, // 2506
+ {NULL, "wxAuiManager", "getDockSizeConstraint", 0}, // 2508
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetFlags, "wxAuiManager", "getFlags", 1}, // 2507
+ {wxAuiManager_GetFlags, "wxAuiManager", "getFlags", 1}, // 2509
#else
- {NULL, "wxAuiManager", "getFlags", 0}, // 2507
+ {NULL, "wxAuiManager", "getFlags", 0}, // 2509
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetManagedWindow, "wxAuiManager", "getManagedWindow", 1}, // 2508
+ {wxAuiManager_GetManagedWindow, "wxAuiManager", "getManagedWindow", 1}, // 2510
#else
- {NULL, "wxAuiManager", "getManagedWindow", 0}, // 2508
+ {NULL, "wxAuiManager", "getManagedWindow", 0}, // 2510
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetManager, "wxAuiManager", "getManager", 1}, // 2509
+ {wxAuiManager_GetManager, "wxAuiManager", "getManager", 1}, // 2511
#else
- {NULL, "wxAuiManager", "getManager", 0}, // 2509
+ {NULL, "wxAuiManager", "getManager", 0}, // 2511
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetPane_1_1, "wxAuiManager", "getPane", 2}, // 2510
+ {wxAuiManager_GetPane_1_1, "wxAuiManager", "getPane", 2}, // 2512
#else
- {NULL, "wxAuiManager", "getPane", 0}, // 2510
+ {NULL, "wxAuiManager", "getPane", 0}, // 2512
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_GetPane_1_0, "wxAuiManager", "getPane", 2}, // 2511
+ {wxAuiManager_GetPane_1_0, "wxAuiManager", "getPane", 2}, // 2513
#else
- {NULL, "wxAuiManager", "getPane", 0}, // 2511
+ {NULL, "wxAuiManager", "getPane", 0}, // 2513
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_HideHint, "wxAuiManager", "hideHint", 1}, // 2512
+ {wxAuiManager_HideHint, "wxAuiManager", "hideHint", 1}, // 2514
#else
- {NULL, "wxAuiManager", "hideHint", 0}, // 2512
+ {NULL, "wxAuiManager", "hideHint", 0}, // 2514
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_InsertPane, "wxAuiManager", "insertPane", 4}, // 2513
+ {wxAuiManager_InsertPane, "wxAuiManager", "insertPane", 4}, // 2515
#else
- {NULL, "wxAuiManager", "insertPane", 0}, // 2513
+ {NULL, "wxAuiManager", "insertPane", 0}, // 2515
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_LoadPaneInfo, "wxAuiManager", "loadPaneInfo", 3}, // 2514
+ {wxAuiManager_LoadPaneInfo, "wxAuiManager", "loadPaneInfo", 3}, // 2516
#else
- {NULL, "wxAuiManager", "loadPaneInfo", 0}, // 2514
+ {NULL, "wxAuiManager", "loadPaneInfo", 0}, // 2516
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_LoadPerspective, "wxAuiManager", "loadPerspective", 3}, // 2515
+ {wxAuiManager_LoadPerspective, "wxAuiManager", "loadPerspective", 3}, // 2517
#else
- {NULL, "wxAuiManager", "loadPerspective", 0}, // 2515
+ {NULL, "wxAuiManager", "loadPerspective", 0}, // 2517
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SavePaneInfo, "wxAuiManager", "savePaneInfo", 2}, // 2516
+ {wxAuiManager_SavePaneInfo, "wxAuiManager", "savePaneInfo", 2}, // 2518
#else
- {NULL, "wxAuiManager", "savePaneInfo", 0}, // 2516
+ {NULL, "wxAuiManager", "savePaneInfo", 0}, // 2518
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SavePerspective, "wxAuiManager", "savePerspective", 1}, // 2517
+ {wxAuiManager_SavePerspective, "wxAuiManager", "savePerspective", 1}, // 2519
#else
- {NULL, "wxAuiManager", "savePerspective", 0}, // 2517
+ {NULL, "wxAuiManager", "savePerspective", 0}, // 2519
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetArtProvider, "wxAuiManager", "setArtProvider", 2}, // 2518
+ {wxAuiManager_SetArtProvider, "wxAuiManager", "setArtProvider", 2}, // 2520
#else
- {NULL, "wxAuiManager", "setArtProvider", 0}, // 2518
+ {NULL, "wxAuiManager", "setArtProvider", 0}, // 2520
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetDockSizeConstraint, "wxAuiManager", "setDockSizeConstraint", 3}, // 2519
+ {wxAuiManager_SetDockSizeConstraint, "wxAuiManager", "setDockSizeConstraint", 3}, // 2521
#else
- {NULL, "wxAuiManager", "setDockSizeConstraint", 0}, // 2519
+ {NULL, "wxAuiManager", "setDockSizeConstraint", 0}, // 2521
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetFlags, "wxAuiManager", "setFlags", 2}, // 2520
+ {wxAuiManager_SetFlags, "wxAuiManager", "setFlags", 2}, // 2522
#else
- {NULL, "wxAuiManager", "setFlags", 0}, // 2520
+ {NULL, "wxAuiManager", "setFlags", 0}, // 2522
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_SetManagedWindow, "wxAuiManager", "setManagedWindow", 2}, // 2521
+ {wxAuiManager_SetManagedWindow, "wxAuiManager", "setManagedWindow", 2}, // 2523
#else
- {NULL, "wxAuiManager", "setManagedWindow", 0}, // 2521
+ {NULL, "wxAuiManager", "setManagedWindow", 0}, // 2523
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_ShowHint, "wxAuiManager", "showHint", 2}, // 2522
+ {wxAuiManager_ShowHint, "wxAuiManager", "showHint", 2}, // 2524
#else
- {NULL, "wxAuiManager", "showHint", 0}, // 2522
+ {NULL, "wxAuiManager", "showHint", 0}, // 2524
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_UnInit, "wxAuiManager", "unInit", 1}, // 2523
+ {wxAuiManager_UnInit, "wxAuiManager", "unInit", 1}, // 2525
#else
- {NULL, "wxAuiManager", "unInit", 0}, // 2523
+ {NULL, "wxAuiManager", "unInit", 0}, // 2525
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiManager_Update, "wxAuiManager", "update", 1}, // 2524
+ {wxAuiManager_Update, "wxAuiManager", "update", 1}, // 2526
#else
- {NULL, "wxAuiManager", "update", 0}, // 2524
+ {NULL, "wxAuiManager", "update", 0}, // 2526
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_new_0, "wxAuiPaneInfo", "new", 0}, // 2525
+ {wxAuiPaneInfo_new_0, "wxAuiPaneInfo", "new", 0}, // 2527
#else
- {NULL, "wxAuiPaneInfo", "new", 0}, // 2525
+ {NULL, "wxAuiPaneInfo", "new", 0}, // 2527
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_new_1, "wxAuiPaneInfo", "new", 1}, // 2526
+ {wxAuiPaneInfo_new_1, "wxAuiPaneInfo", "new", 1}, // 2528
#else
- {NULL, "wxAuiPaneInfo", "new", 0}, // 2526
+ {NULL, "wxAuiPaneInfo", "new", 0}, // 2528
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_BestSize_1, "wxAuiPaneInfo", "bestSize", 2}, // 2527
+ {wxAuiPaneInfo_BestSize_1, "wxAuiPaneInfo", "bestSize", 2}, // 2529
#else
- {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2527
+ {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2529
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_BestSize_2, "wxAuiPaneInfo", "bestSize", 3}, // 2528
+ {wxAuiPaneInfo_BestSize_2, "wxAuiPaneInfo", "bestSize", 3}, // 2530
#else
- {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2528
+ {NULL, "wxAuiPaneInfo", "bestSize", 0}, // 2530
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Bottom, "wxAuiPaneInfo", "bottom", 1}, // 2529
+ {wxAuiPaneInfo_Bottom, "wxAuiPaneInfo", "bottom", 1}, // 2531
#else
- {NULL, "wxAuiPaneInfo", "bottom", 0}, // 2529
+ {NULL, "wxAuiPaneInfo", "bottom", 0}, // 2531
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_BottomDockable, "wxAuiPaneInfo", "bottomDockable", 2}, // 2530
+ {wxAuiPaneInfo_BottomDockable, "wxAuiPaneInfo", "bottomDockable", 2}, // 2532
#else
- {NULL, "wxAuiPaneInfo", "bottomDockable", 0}, // 2530
+ {NULL, "wxAuiPaneInfo", "bottomDockable", 0}, // 2532
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Caption, "wxAuiPaneInfo", "caption", 2}, // 2531
+ {wxAuiPaneInfo_Caption, "wxAuiPaneInfo", "caption", 2}, // 2533
#else
- {NULL, "wxAuiPaneInfo", "caption", 0}, // 2531
+ {NULL, "wxAuiPaneInfo", "caption", 0}, // 2533
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_CaptionVisible, "wxAuiPaneInfo", "captionVisible", 2}, // 2532
+ {wxAuiPaneInfo_CaptionVisible, "wxAuiPaneInfo", "captionVisible", 2}, // 2534
#else
- {NULL, "wxAuiPaneInfo", "captionVisible", 0}, // 2532
+ {NULL, "wxAuiPaneInfo", "captionVisible", 0}, // 2534
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Centre, "wxAuiPaneInfo", "centre", 1}, // 2533
+ {wxAuiPaneInfo_Centre, "wxAuiPaneInfo", "centre", 1}, // 2535
#else
- {NULL, "wxAuiPaneInfo", "centre", 0}, // 2533
+ {NULL, "wxAuiPaneInfo", "centre", 0}, // 2535
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_CentrePane, "wxAuiPaneInfo", "centrePane", 1}, // 2534
+ {wxAuiPaneInfo_CentrePane, "wxAuiPaneInfo", "centrePane", 1}, // 2536
#else
- {NULL, "wxAuiPaneInfo", "centrePane", 0}, // 2534
+ {NULL, "wxAuiPaneInfo", "centrePane", 0}, // 2536
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_CloseButton, "wxAuiPaneInfo", "closeButton", 2}, // 2535
+ {wxAuiPaneInfo_CloseButton, "wxAuiPaneInfo", "closeButton", 2}, // 2537
#else
- {NULL, "wxAuiPaneInfo", "closeButton", 0}, // 2535
+ {NULL, "wxAuiPaneInfo", "closeButton", 0}, // 2537
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_DefaultPane, "wxAuiPaneInfo", "defaultPane", 1}, // 2536
+ {wxAuiPaneInfo_DefaultPane, "wxAuiPaneInfo", "defaultPane", 1}, // 2538
#else
- {NULL, "wxAuiPaneInfo", "defaultPane", 0}, // 2536
+ {NULL, "wxAuiPaneInfo", "defaultPane", 0}, // 2538
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_DestroyOnClose, "wxAuiPaneInfo", "destroyOnClose", 2}, // 2537
+ {wxAuiPaneInfo_DestroyOnClose, "wxAuiPaneInfo", "destroyOnClose", 2}, // 2539
#else
- {NULL, "wxAuiPaneInfo", "destroyOnClose", 0}, // 2537
+ {NULL, "wxAuiPaneInfo", "destroyOnClose", 0}, // 2539
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Direction, "wxAuiPaneInfo", "direction", 2}, // 2538
+ {wxAuiPaneInfo_Direction, "wxAuiPaneInfo", "direction", 2}, // 2540
#else
- {NULL, "wxAuiPaneInfo", "direction", 0}, // 2538
+ {NULL, "wxAuiPaneInfo", "direction", 0}, // 2540
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Dock, "wxAuiPaneInfo", "dock", 1}, // 2539
+ {wxAuiPaneInfo_Dock, "wxAuiPaneInfo", "dock", 1}, // 2541
#else
- {NULL, "wxAuiPaneInfo", "dock", 0}, // 2539
+ {NULL, "wxAuiPaneInfo", "dock", 0}, // 2541
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Dockable, "wxAuiPaneInfo", "dockable", 2}, // 2540
+ {wxAuiPaneInfo_Dockable, "wxAuiPaneInfo", "dockable", 2}, // 2542
#else
- {NULL, "wxAuiPaneInfo", "dockable", 0}, // 2540
+ {NULL, "wxAuiPaneInfo", "dockable", 0}, // 2542
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Fixed, "wxAuiPaneInfo", "fixed", 1}, // 2541
+ {wxAuiPaneInfo_Fixed, "wxAuiPaneInfo", "fixed", 1}, // 2543
#else
- {NULL, "wxAuiPaneInfo", "fixed", 0}, // 2541
+ {NULL, "wxAuiPaneInfo", "fixed", 0}, // 2543
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Float, "wxAuiPaneInfo", "float", 1}, // 2542
+ {wxAuiPaneInfo_Float, "wxAuiPaneInfo", "float", 1}, // 2544
#else
- {NULL, "wxAuiPaneInfo", "float", 0}, // 2542
+ {NULL, "wxAuiPaneInfo", "float", 0}, // 2544
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Floatable, "wxAuiPaneInfo", "floatable", 2}, // 2543
+ {wxAuiPaneInfo_Floatable, "wxAuiPaneInfo", "floatable", 2}, // 2545
#else
- {NULL, "wxAuiPaneInfo", "floatable", 0}, // 2543
+ {NULL, "wxAuiPaneInfo", "floatable", 0}, // 2545
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingPosition_1, "wxAuiPaneInfo", "floatingPosition", 2}, // 2544
+ {wxAuiPaneInfo_FloatingPosition_1, "wxAuiPaneInfo", "floatingPosition", 2}, // 2546
#else
- {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2544
+ {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2546
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingPosition_2, "wxAuiPaneInfo", "floatingPosition", 3}, // 2545
+ {wxAuiPaneInfo_FloatingPosition_2, "wxAuiPaneInfo", "floatingPosition", 3}, // 2547
#else
- {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2545
+ {NULL, "wxAuiPaneInfo", "floatingPosition", 0}, // 2547
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingSize_1, "wxAuiPaneInfo", "floatingSize", 2}, // 2546
+ {wxAuiPaneInfo_FloatingSize_1, "wxAuiPaneInfo", "floatingSize", 2}, // 2548
#else
- {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2546
+ {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2548
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_FloatingSize_2, "wxAuiPaneInfo", "floatingSize", 3}, // 2547
+ {wxAuiPaneInfo_FloatingSize_2, "wxAuiPaneInfo", "floatingSize", 3}, // 2549
#else
- {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2547
+ {NULL, "wxAuiPaneInfo", "floatingSize", 0}, // 2549
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Gripper, "wxAuiPaneInfo", "gripper", 2}, // 2548
+ {wxAuiPaneInfo_Gripper, "wxAuiPaneInfo", "gripper", 2}, // 2550
#else
- {NULL, "wxAuiPaneInfo", "gripper", 0}, // 2548
+ {NULL, "wxAuiPaneInfo", "gripper", 0}, // 2550
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GripperTop, "wxAuiPaneInfo", "gripperTop", 2}, // 2549
+ {wxAuiPaneInfo_GripperTop, "wxAuiPaneInfo", "gripperTop", 2}, // 2551
#else
- {NULL, "wxAuiPaneInfo", "gripperTop", 0}, // 2549
+ {NULL, "wxAuiPaneInfo", "gripperTop", 0}, // 2551
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasBorder, "wxAuiPaneInfo", "hasBorder", 1}, // 2550
+ {wxAuiPaneInfo_HasBorder, "wxAuiPaneInfo", "hasBorder", 1}, // 2552
#else
- {NULL, "wxAuiPaneInfo", "hasBorder", 0}, // 2550
+ {NULL, "wxAuiPaneInfo", "hasBorder", 0}, // 2552
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasCaption, "wxAuiPaneInfo", "hasCaption", 1}, // 2551
+ {wxAuiPaneInfo_HasCaption, "wxAuiPaneInfo", "hasCaption", 1}, // 2553
#else
- {NULL, "wxAuiPaneInfo", "hasCaption", 0}, // 2551
+ {NULL, "wxAuiPaneInfo", "hasCaption", 0}, // 2553
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasCloseButton, "wxAuiPaneInfo", "hasCloseButton", 1}, // 2552
+ {wxAuiPaneInfo_HasCloseButton, "wxAuiPaneInfo", "hasCloseButton", 1}, // 2554
#else
- {NULL, "wxAuiPaneInfo", "hasCloseButton", 0}, // 2552
+ {NULL, "wxAuiPaneInfo", "hasCloseButton", 0}, // 2554
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasFlag, "wxAuiPaneInfo", "hasFlag", 2}, // 2553
+ {wxAuiPaneInfo_HasFlag, "wxAuiPaneInfo", "hasFlag", 2}, // 2555
#else
- {NULL, "wxAuiPaneInfo", "hasFlag", 0}, // 2553
+ {NULL, "wxAuiPaneInfo", "hasFlag", 0}, // 2555
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasGripper, "wxAuiPaneInfo", "hasGripper", 1}, // 2554
+ {wxAuiPaneInfo_HasGripper, "wxAuiPaneInfo", "hasGripper", 1}, // 2556
#else
- {NULL, "wxAuiPaneInfo", "hasGripper", 0}, // 2554
+ {NULL, "wxAuiPaneInfo", "hasGripper", 0}, // 2556
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasGripperTop, "wxAuiPaneInfo", "hasGripperTop", 1}, // 2555
+ {wxAuiPaneInfo_HasGripperTop, "wxAuiPaneInfo", "hasGripperTop", 1}, // 2557
#else
- {NULL, "wxAuiPaneInfo", "hasGripperTop", 0}, // 2555
+ {NULL, "wxAuiPaneInfo", "hasGripperTop", 0}, // 2557
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasMaximizeButton, "wxAuiPaneInfo", "hasMaximizeButton", 1}, // 2556
+ {wxAuiPaneInfo_HasMaximizeButton, "wxAuiPaneInfo", "hasMaximizeButton", 1}, // 2558
#else
- {NULL, "wxAuiPaneInfo", "hasMaximizeButton", 0}, // 2556
+ {NULL, "wxAuiPaneInfo", "hasMaximizeButton", 0}, // 2558
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasMinimizeButton, "wxAuiPaneInfo", "hasMinimizeButton", 1}, // 2557
+ {wxAuiPaneInfo_HasMinimizeButton, "wxAuiPaneInfo", "hasMinimizeButton", 1}, // 2559
#else
- {NULL, "wxAuiPaneInfo", "hasMinimizeButton", 0}, // 2557
+ {NULL, "wxAuiPaneInfo", "hasMinimizeButton", 0}, // 2559
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_HasPinButton, "wxAuiPaneInfo", "hasPinButton", 1}, // 2558
+ {wxAuiPaneInfo_HasPinButton, "wxAuiPaneInfo", "hasPinButton", 1}, // 2560
#else
- {NULL, "wxAuiPaneInfo", "hasPinButton", 0}, // 2558
+ {NULL, "wxAuiPaneInfo", "hasPinButton", 0}, // 2560
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Hide, "wxAuiPaneInfo", "hide", 1}, // 2559
+ {wxAuiPaneInfo_Hide, "wxAuiPaneInfo", "hide", 1}, // 2561
#else
- {NULL, "wxAuiPaneInfo", "hide", 0}, // 2559
+ {NULL, "wxAuiPaneInfo", "hide", 0}, // 2561
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsBottomDockable, "wxAuiPaneInfo", "isBottomDockable", 1}, // 2560
+ {wxAuiPaneInfo_IsBottomDockable, "wxAuiPaneInfo", "isBottomDockable", 1}, // 2562
#else
- {NULL, "wxAuiPaneInfo", "isBottomDockable", 0}, // 2560
+ {NULL, "wxAuiPaneInfo", "isBottomDockable", 0}, // 2562
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsDocked, "wxAuiPaneInfo", "isDocked", 1}, // 2561
+ {wxAuiPaneInfo_IsDocked, "wxAuiPaneInfo", "isDocked", 1}, // 2563
#else
- {NULL, "wxAuiPaneInfo", "isDocked", 0}, // 2561
+ {NULL, "wxAuiPaneInfo", "isDocked", 0}, // 2563
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsFixed, "wxAuiPaneInfo", "isFixed", 1}, // 2562
+ {wxAuiPaneInfo_IsFixed, "wxAuiPaneInfo", "isFixed", 1}, // 2564
#else
- {NULL, "wxAuiPaneInfo", "isFixed", 0}, // 2562
+ {NULL, "wxAuiPaneInfo", "isFixed", 0}, // 2564
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsFloatable, "wxAuiPaneInfo", "isFloatable", 1}, // 2563
+ {wxAuiPaneInfo_IsFloatable, "wxAuiPaneInfo", "isFloatable", 1}, // 2565
#else
- {NULL, "wxAuiPaneInfo", "isFloatable", 0}, // 2563
+ {NULL, "wxAuiPaneInfo", "isFloatable", 0}, // 2565
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsFloating, "wxAuiPaneInfo", "isFloating", 1}, // 2564
+ {wxAuiPaneInfo_IsFloating, "wxAuiPaneInfo", "isFloating", 1}, // 2566
#else
- {NULL, "wxAuiPaneInfo", "isFloating", 0}, // 2564
+ {NULL, "wxAuiPaneInfo", "isFloating", 0}, // 2566
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsLeftDockable, "wxAuiPaneInfo", "isLeftDockable", 1}, // 2565
+ {wxAuiPaneInfo_IsLeftDockable, "wxAuiPaneInfo", "isLeftDockable", 1}, // 2567
#else
- {NULL, "wxAuiPaneInfo", "isLeftDockable", 0}, // 2565
+ {NULL, "wxAuiPaneInfo", "isLeftDockable", 0}, // 2567
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsMovable, "wxAuiPaneInfo", "isMovable", 1}, // 2566
+ {wxAuiPaneInfo_IsMovable, "wxAuiPaneInfo", "isMovable", 1}, // 2568
#else
- {NULL, "wxAuiPaneInfo", "isMovable", 0}, // 2566
+ {NULL, "wxAuiPaneInfo", "isMovable", 0}, // 2568
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsOk, "wxAuiPaneInfo", "isOk", 1}, // 2567
+ {wxAuiPaneInfo_IsOk, "wxAuiPaneInfo", "isOk", 1}, // 2569
#else
- {NULL, "wxAuiPaneInfo", "isOk", 0}, // 2567
+ {NULL, "wxAuiPaneInfo", "isOk", 0}, // 2569
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsResizable, "wxAuiPaneInfo", "isResizable", 1}, // 2568
+ {wxAuiPaneInfo_IsResizable, "wxAuiPaneInfo", "isResizable", 1}, // 2570
#else
- {NULL, "wxAuiPaneInfo", "isResizable", 0}, // 2568
+ {NULL, "wxAuiPaneInfo", "isResizable", 0}, // 2570
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsRightDockable, "wxAuiPaneInfo", "isRightDockable", 1}, // 2569
+ {wxAuiPaneInfo_IsRightDockable, "wxAuiPaneInfo", "isRightDockable", 1}, // 2571
#else
- {NULL, "wxAuiPaneInfo", "isRightDockable", 0}, // 2569
+ {NULL, "wxAuiPaneInfo", "isRightDockable", 0}, // 2571
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsShown, "wxAuiPaneInfo", "isShown", 1}, // 2570
+ {wxAuiPaneInfo_IsShown, "wxAuiPaneInfo", "isShown", 1}, // 2572
#else
- {NULL, "wxAuiPaneInfo", "isShown", 0}, // 2570
+ {NULL, "wxAuiPaneInfo", "isShown", 0}, // 2572
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsToolbar, "wxAuiPaneInfo", "isToolbar", 1}, // 2571
+ {wxAuiPaneInfo_IsToolbar, "wxAuiPaneInfo", "isToolbar", 1}, // 2573
#else
- {NULL, "wxAuiPaneInfo", "isToolbar", 0}, // 2571
+ {NULL, "wxAuiPaneInfo", "isToolbar", 0}, // 2573
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_IsTopDockable, "wxAuiPaneInfo", "isTopDockable", 1}, // 2572
+ {wxAuiPaneInfo_IsTopDockable, "wxAuiPaneInfo", "isTopDockable", 1}, // 2574
#else
- {NULL, "wxAuiPaneInfo", "isTopDockable", 0}, // 2572
+ {NULL, "wxAuiPaneInfo", "isTopDockable", 0}, // 2574
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Layer, "wxAuiPaneInfo", "layer", 2}, // 2573
+ {wxAuiPaneInfo_Layer, "wxAuiPaneInfo", "layer", 2}, // 2575
#else
- {NULL, "wxAuiPaneInfo", "layer", 0}, // 2573
+ {NULL, "wxAuiPaneInfo", "layer", 0}, // 2575
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Left, "wxAuiPaneInfo", "left", 1}, // 2574
+ {wxAuiPaneInfo_Left, "wxAuiPaneInfo", "left", 1}, // 2576
#else
- {NULL, "wxAuiPaneInfo", "left", 0}, // 2574
+ {NULL, "wxAuiPaneInfo", "left", 0}, // 2576
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_LeftDockable, "wxAuiPaneInfo", "leftDockable", 2}, // 2575
+ {wxAuiPaneInfo_LeftDockable, "wxAuiPaneInfo", "leftDockable", 2}, // 2577
#else
- {NULL, "wxAuiPaneInfo", "leftDockable", 0}, // 2575
+ {NULL, "wxAuiPaneInfo", "leftDockable", 0}, // 2577
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MaxSize_1, "wxAuiPaneInfo", "maxSize", 2}, // 2576
+ {wxAuiPaneInfo_MaxSize_1, "wxAuiPaneInfo", "maxSize", 2}, // 2578
#else
- {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2576
+ {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2578
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MaxSize_2, "wxAuiPaneInfo", "maxSize", 3}, // 2577
+ {wxAuiPaneInfo_MaxSize_2, "wxAuiPaneInfo", "maxSize", 3}, // 2579
#else
- {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2577
+ {NULL, "wxAuiPaneInfo", "maxSize", 0}, // 2579
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MaximizeButton, "wxAuiPaneInfo", "maximizeButton", 2}, // 2578
+ {wxAuiPaneInfo_MaximizeButton, "wxAuiPaneInfo", "maximizeButton", 2}, // 2580
#else
- {NULL, "wxAuiPaneInfo", "maximizeButton", 0}, // 2578
+ {NULL, "wxAuiPaneInfo", "maximizeButton", 0}, // 2580
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MinSize_1, "wxAuiPaneInfo", "minSize", 2}, // 2579
+ {wxAuiPaneInfo_MinSize_1, "wxAuiPaneInfo", "minSize", 2}, // 2581
#else
- {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2579
+ {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2581
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MinSize_2, "wxAuiPaneInfo", "minSize", 3}, // 2580
+ {wxAuiPaneInfo_MinSize_2, "wxAuiPaneInfo", "minSize", 3}, // 2582
#else
- {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2580
+ {NULL, "wxAuiPaneInfo", "minSize", 0}, // 2582
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_MinimizeButton, "wxAuiPaneInfo", "minimizeButton", 2}, // 2581
+ {wxAuiPaneInfo_MinimizeButton, "wxAuiPaneInfo", "minimizeButton", 2}, // 2583
#else
- {NULL, "wxAuiPaneInfo", "minimizeButton", 0}, // 2581
+ {NULL, "wxAuiPaneInfo", "minimizeButton", 0}, // 2583
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Movable, "wxAuiPaneInfo", "movable", 2}, // 2582
+ {wxAuiPaneInfo_Movable, "wxAuiPaneInfo", "movable", 2}, // 2584
#else
- {NULL, "wxAuiPaneInfo", "movable", 0}, // 2582
+ {NULL, "wxAuiPaneInfo", "movable", 0}, // 2584
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Name, "wxAuiPaneInfo", "name", 2}, // 2583
+ {wxAuiPaneInfo_Name, "wxAuiPaneInfo", "name", 2}, // 2585
#else
- {NULL, "wxAuiPaneInfo", "name", 0}, // 2583
+ {NULL, "wxAuiPaneInfo", "name", 0}, // 2585
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_PaneBorder, "wxAuiPaneInfo", "paneBorder", 2}, // 2584
+ {wxAuiPaneInfo_PaneBorder, "wxAuiPaneInfo", "paneBorder", 2}, // 2586
#else
- {NULL, "wxAuiPaneInfo", "paneBorder", 0}, // 2584
+ {NULL, "wxAuiPaneInfo", "paneBorder", 0}, // 2586
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_PinButton, "wxAuiPaneInfo", "pinButton", 2}, // 2585
+ {wxAuiPaneInfo_PinButton, "wxAuiPaneInfo", "pinButton", 2}, // 2587
#else
- {NULL, "wxAuiPaneInfo", "pinButton", 0}, // 2585
+ {NULL, "wxAuiPaneInfo", "pinButton", 0}, // 2587
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Position, "wxAuiPaneInfo", "position", 2}, // 2586
+ {wxAuiPaneInfo_Position, "wxAuiPaneInfo", "position", 2}, // 2588
#else
- {NULL, "wxAuiPaneInfo", "position", 0}, // 2586
+ {NULL, "wxAuiPaneInfo", "position", 0}, // 2588
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Resizable, "wxAuiPaneInfo", "resizable", 2}, // 2587
+ {wxAuiPaneInfo_Resizable, "wxAuiPaneInfo", "resizable", 2}, // 2589
#else
- {NULL, "wxAuiPaneInfo", "resizable", 0}, // 2587
+ {NULL, "wxAuiPaneInfo", "resizable", 0}, // 2589
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Right, "wxAuiPaneInfo", "right", 1}, // 2588
+ {wxAuiPaneInfo_Right, "wxAuiPaneInfo", "right", 1}, // 2590
#else
- {NULL, "wxAuiPaneInfo", "right", 0}, // 2588
+ {NULL, "wxAuiPaneInfo", "right", 0}, // 2590
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_RightDockable, "wxAuiPaneInfo", "rightDockable", 2}, // 2589
+ {wxAuiPaneInfo_RightDockable, "wxAuiPaneInfo", "rightDockable", 2}, // 2591
#else
- {NULL, "wxAuiPaneInfo", "rightDockable", 0}, // 2589
+ {NULL, "wxAuiPaneInfo", "rightDockable", 0}, // 2591
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Row, "wxAuiPaneInfo", "row", 2}, // 2590
+ {wxAuiPaneInfo_Row, "wxAuiPaneInfo", "row", 2}, // 2592
#else
- {NULL, "wxAuiPaneInfo", "row", 0}, // 2590
+ {NULL, "wxAuiPaneInfo", "row", 0}, // 2592
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_SafeSet, "wxAuiPaneInfo", "safeSet", 2}, // 2591
+ {wxAuiPaneInfo_SafeSet, "wxAuiPaneInfo", "safeSet", 2}, // 2593
#else
- {NULL, "wxAuiPaneInfo", "safeSet", 0}, // 2591
+ {NULL, "wxAuiPaneInfo", "safeSet", 0}, // 2593
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_SetFlag, "wxAuiPaneInfo", "setFlag", 3}, // 2592
+ {wxAuiPaneInfo_SetFlag, "wxAuiPaneInfo", "setFlag", 3}, // 2594
#else
- {NULL, "wxAuiPaneInfo", "setFlag", 0}, // 2592
+ {NULL, "wxAuiPaneInfo", "setFlag", 0}, // 2594
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Show, "wxAuiPaneInfo", "show", 2}, // 2593
+ {wxAuiPaneInfo_Show, "wxAuiPaneInfo", "show", 2}, // 2595
#else
- {NULL, "wxAuiPaneInfo", "show", 0}, // 2593
+ {NULL, "wxAuiPaneInfo", "show", 0}, // 2595
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_ToolbarPane, "wxAuiPaneInfo", "toolbarPane", 1}, // 2594
+ {wxAuiPaneInfo_ToolbarPane, "wxAuiPaneInfo", "toolbarPane", 1}, // 2596
#else
- {NULL, "wxAuiPaneInfo", "toolbarPane", 0}, // 2594
+ {NULL, "wxAuiPaneInfo", "toolbarPane", 0}, // 2596
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Top, "wxAuiPaneInfo", "top", 1}, // 2595
+ {wxAuiPaneInfo_Top, "wxAuiPaneInfo", "top", 1}, // 2597
#else
- {NULL, "wxAuiPaneInfo", "top", 0}, // 2595
+ {NULL, "wxAuiPaneInfo", "top", 0}, // 2597
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_TopDockable, "wxAuiPaneInfo", "topDockable", 2}, // 2596
+ {wxAuiPaneInfo_TopDockable, "wxAuiPaneInfo", "topDockable", 2}, // 2598
#else
- {NULL, "wxAuiPaneInfo", "topDockable", 0}, // 2596
+ {NULL, "wxAuiPaneInfo", "topDockable", 0}, // 2598
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_Window, "wxAuiPaneInfo", "window", 2}, // 2597
+ {wxAuiPaneInfo_Window, "wxAuiPaneInfo", "window", 2}, // 2599
#else
- {NULL, "wxAuiPaneInfo", "window", 0}, // 2597
+ {NULL, "wxAuiPaneInfo", "window", 0}, // 2599
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetWindow, "wxAuiPaneInfo", "getWindow", 1}, // 2598
+ {wxAuiPaneInfo_GetWindow, "wxAuiPaneInfo", "getWindow", 1}, // 2600
#else
- {NULL, "wxAuiPaneInfo", "getWindow", 0}, // 2598
+ {NULL, "wxAuiPaneInfo", "getWindow", 0}, // 2600
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetFrame, "wxAuiPaneInfo", "getFrame", 1}, // 2599
+ {wxAuiPaneInfo_GetFrame, "wxAuiPaneInfo", "getFrame", 1}, // 2601
#else
- {NULL, "wxAuiPaneInfo", "getFrame", 0}, // 2599
+ {NULL, "wxAuiPaneInfo", "getFrame", 0}, // 2601
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetDirection, "wxAuiPaneInfo", "getDirection", 1}, // 2600
+ {wxAuiPaneInfo_GetDirection, "wxAuiPaneInfo", "getDirection", 1}, // 2602
#else
- {NULL, "wxAuiPaneInfo", "getDirection", 0}, // 2600
+ {NULL, "wxAuiPaneInfo", "getDirection", 0}, // 2602
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetLayer, "wxAuiPaneInfo", "getLayer", 1}, // 2601
+ {wxAuiPaneInfo_GetLayer, "wxAuiPaneInfo", "getLayer", 1}, // 2603
#else
- {NULL, "wxAuiPaneInfo", "getLayer", 0}, // 2601
+ {NULL, "wxAuiPaneInfo", "getLayer", 0}, // 2603
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetRow, "wxAuiPaneInfo", "getRow", 1}, // 2602
+ {wxAuiPaneInfo_GetRow, "wxAuiPaneInfo", "getRow", 1}, // 2604
#else
- {NULL, "wxAuiPaneInfo", "getRow", 0}, // 2602
+ {NULL, "wxAuiPaneInfo", "getRow", 0}, // 2604
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetPosition, "wxAuiPaneInfo", "getPosition", 1}, // 2603
+ {wxAuiPaneInfo_GetPosition, "wxAuiPaneInfo", "getPosition", 1}, // 2605
#else
- {NULL, "wxAuiPaneInfo", "getPosition", 0}, // 2603
+ {NULL, "wxAuiPaneInfo", "getPosition", 0}, // 2605
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetFloatingPosition, "wxAuiPaneInfo", "getFloatingPosition", 1}, // 2604
+ {wxAuiPaneInfo_GetFloatingPosition, "wxAuiPaneInfo", "getFloatingPosition", 1}, // 2606
#else
- {NULL, "wxAuiPaneInfo", "getFloatingPosition", 0}, // 2604
+ {NULL, "wxAuiPaneInfo", "getFloatingPosition", 0}, // 2606
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_GetFloatingSize, "wxAuiPaneInfo", "getFloatingSize", 1}, // 2605
+ {wxAuiPaneInfo_GetFloatingSize, "wxAuiPaneInfo", "getFloatingSize", 1}, // 2607
#else
- {NULL, "wxAuiPaneInfo", "getFloatingSize", 0}, // 2605
+ {NULL, "wxAuiPaneInfo", "getFloatingSize", 0}, // 2607
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiPaneInfo_destroy, "wxAuiPaneInfo", "'Destroy'", 1}, // 2606
+ {wxAuiPaneInfo_destroy, "wxAuiPaneInfo", "'Destroy'", 1}, // 2608
#else
- {NULL, "wxAuiPaneInfo", "'Destroy'", 0}, // 2606
+ {NULL, "wxAuiPaneInfo", "'Destroy'", 0}, // 2608
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_new_0, "wxAuiNotebook", "new", 0}, // 2607
+ {wxAuiNotebook_new_0, "wxAuiNotebook", "new", 0}, // 2609
#else
- {NULL, "wxAuiNotebook", "new", 0}, // 2607
+ {NULL, "wxAuiNotebook", "new", 0}, // 2609
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_new_2, "wxAuiNotebook", "new", 2}, // 2608
+ {wxAuiNotebook_new_2, "wxAuiNotebook", "new", 2}, // 2610
#else
- {NULL, "wxAuiNotebook", "new", 0}, // 2608
+ {NULL, "wxAuiNotebook", "new", 0}, // 2610
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_AddPage_3, "wxAuiNotebook", "addPage", 4}, // 2609
+ {wxAuiNotebook_AddPage_3, "wxAuiNotebook", "addPage", 4}, // 2611
#else
- {NULL, "wxAuiNotebook", "addPage", 0}, // 2609
+ {NULL, "wxAuiNotebook", "addPage", 0}, // 2611
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_AddPage_4, "wxAuiNotebook", "addPage", 5}, // 2610
+ {wxAuiNotebook_AddPage_4, "wxAuiNotebook", "addPage", 5}, // 2612
#else
- {NULL, "wxAuiNotebook", "addPage", 0}, // 2610
+ {NULL, "wxAuiNotebook", "addPage", 0}, // 2612
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_Create_2, "wxAuiNotebook", "create", 3}, // 2611
+ {wxAuiNotebook_Create_2, "wxAuiNotebook", "create", 3}, // 2613
#else
- {NULL, "wxAuiNotebook", "create", 0}, // 2611
+ {NULL, "wxAuiNotebook", "create", 0}, // 2613
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_Create_3, "wxAuiNotebook", "create", 4}, // 2612
+ {wxAuiNotebook_Create_3, "wxAuiNotebook", "create", 4}, // 2614
#else
- {NULL, "wxAuiNotebook", "create", 0}, // 2612
+ {NULL, "wxAuiNotebook", "create", 0}, // 2614
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_DeletePage, "wxAuiNotebook", "deletePage", 2}, // 2613
+ {wxAuiNotebook_DeletePage, "wxAuiNotebook", "deletePage", 2}, // 2615
#else
- {NULL, "wxAuiNotebook", "deletePage", 0}, // 2613
+ {NULL, "wxAuiNotebook", "deletePage", 0}, // 2615
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetArtProvider, "wxAuiNotebook", "getArtProvider", 1}, // 2614
+ {wxAuiNotebook_GetArtProvider, "wxAuiNotebook", "getArtProvider", 1}, // 2616
#else
- {NULL, "wxAuiNotebook", "getArtProvider", 0}, // 2614
+ {NULL, "wxAuiNotebook", "getArtProvider", 0}, // 2616
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPage, "wxAuiNotebook", "getPage", 2}, // 2615
+ {wxAuiNotebook_GetPage, "wxAuiNotebook", "getPage", 2}, // 2617
#else
- {NULL, "wxAuiNotebook", "getPage", 0}, // 2615
+ {NULL, "wxAuiNotebook", "getPage", 0}, // 2617
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageBitmap, "wxAuiNotebook", "getPageBitmap", 2}, // 2616
+ {wxAuiNotebook_GetPageBitmap, "wxAuiNotebook", "getPageBitmap", 2}, // 2618
#else
- {NULL, "wxAuiNotebook", "getPageBitmap", 0}, // 2616
+ {NULL, "wxAuiNotebook", "getPageBitmap", 0}, // 2618
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageCount, "wxAuiNotebook", "getPageCount", 1}, // 2617
+ {wxAuiNotebook_GetPageCount, "wxAuiNotebook", "getPageCount", 1}, // 2619
#else
- {NULL, "wxAuiNotebook", "getPageCount", 0}, // 2617
+ {NULL, "wxAuiNotebook", "getPageCount", 0}, // 2619
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageIndex, "wxAuiNotebook", "getPageIndex", 2}, // 2618
+ {wxAuiNotebook_GetPageIndex, "wxAuiNotebook", "getPageIndex", 2}, // 2620
#else
- {NULL, "wxAuiNotebook", "getPageIndex", 0}, // 2618
+ {NULL, "wxAuiNotebook", "getPageIndex", 0}, // 2620
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetPageText, "wxAuiNotebook", "getPageText", 2}, // 2619
+ {wxAuiNotebook_GetPageText, "wxAuiNotebook", "getPageText", 2}, // 2621
#else
- {NULL, "wxAuiNotebook", "getPageText", 0}, // 2619
+ {NULL, "wxAuiNotebook", "getPageText", 0}, // 2621
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_GetSelection, "wxAuiNotebook", "getSelection", 1}, // 2620
+ {wxAuiNotebook_GetSelection, "wxAuiNotebook", "getSelection", 1}, // 2622
#else
- {NULL, "wxAuiNotebook", "getSelection", 0}, // 2620
+ {NULL, "wxAuiNotebook", "getSelection", 0}, // 2622
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_InsertPage_4, "wxAuiNotebook", "insertPage", 5}, // 2621
+ {wxAuiNotebook_InsertPage_4, "wxAuiNotebook", "insertPage", 5}, // 2623
#else
- {NULL, "wxAuiNotebook", "insertPage", 0}, // 2621
+ {NULL, "wxAuiNotebook", "insertPage", 0}, // 2623
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_InsertPage_5, "wxAuiNotebook", "insertPage", 6}, // 2622
+ {wxAuiNotebook_InsertPage_5, "wxAuiNotebook", "insertPage", 6}, // 2624
#else
- {NULL, "wxAuiNotebook", "insertPage", 0}, // 2622
+ {NULL, "wxAuiNotebook", "insertPage", 0}, // 2624
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_RemovePage, "wxAuiNotebook", "removePage", 2}, // 2623
+ {wxAuiNotebook_RemovePage, "wxAuiNotebook", "removePage", 2}, // 2625
#else
- {NULL, "wxAuiNotebook", "removePage", 0}, // 2623
+ {NULL, "wxAuiNotebook", "removePage", 0}, // 2625
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetArtProvider, "wxAuiNotebook", "setArtProvider", 2}, // 2624
+ {wxAuiNotebook_SetArtProvider, "wxAuiNotebook", "setArtProvider", 2}, // 2626
#else
- {NULL, "wxAuiNotebook", "setArtProvider", 0}, // 2624
+ {NULL, "wxAuiNotebook", "setArtProvider", 0}, // 2626
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetFont, "wxAuiNotebook", "setFont", 2}, // 2625
+ {wxAuiNotebook_SetFont, "wxAuiNotebook", "setFont", 2}, // 2627
#else
- {NULL, "wxAuiNotebook", "setFont", 0}, // 2625
+ {NULL, "wxAuiNotebook", "setFont", 0}, // 2627
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetPageBitmap, "wxAuiNotebook", "setPageBitmap", 3}, // 2626
+ {wxAuiNotebook_SetPageBitmap, "wxAuiNotebook", "setPageBitmap", 3}, // 2628
#else
- {NULL, "wxAuiNotebook", "setPageBitmap", 0}, // 2626
+ {NULL, "wxAuiNotebook", "setPageBitmap", 0}, // 2628
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetPageText, "wxAuiNotebook", "setPageText", 3}, // 2627
+ {wxAuiNotebook_SetPageText, "wxAuiNotebook", "setPageText", 3}, // 2629
#else
- {NULL, "wxAuiNotebook", "setPageText", 0}, // 2627
+ {NULL, "wxAuiNotebook", "setPageText", 0}, // 2629
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetSelection, "wxAuiNotebook", "setSelection", 2}, // 2628
+ {wxAuiNotebook_SetSelection, "wxAuiNotebook", "setSelection", 2}, // 2630
#else
- {NULL, "wxAuiNotebook", "setSelection", 0}, // 2628
+ {NULL, "wxAuiNotebook", "setSelection", 0}, // 2630
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetTabCtrlHeight, "wxAuiNotebook", "setTabCtrlHeight", 2}, // 2629
+ {wxAuiNotebook_SetTabCtrlHeight, "wxAuiNotebook", "setTabCtrlHeight", 2}, // 2631
#else
- {NULL, "wxAuiNotebook", "setTabCtrlHeight", 0}, // 2629
+ {NULL, "wxAuiNotebook", "setTabCtrlHeight", 0}, // 2631
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiNotebook_SetUniformBitmapSize, "wxAuiNotebook", "setUniformBitmapSize", 2}, // 2630
+ {wxAuiNotebook_SetUniformBitmapSize, "wxAuiNotebook", "setUniformBitmapSize", 2}, // 2632
#else
- {NULL, "wxAuiNotebook", "setUniformBitmapSize", 0}, // 2630
+ {NULL, "wxAuiNotebook", "setUniformBitmapSize", 0}, // 2632
#endif // wxUSE_AUI
#if wxUSE_AUI
- {NULL, "wxAuiNotebook", "'Destroy'", 1}, // 2631 obj destructor wxAuiNotebook_destroy
+ {NULL, "wxAuiNotebook", "'Destroy'", 1}, // 2633 obj destructor wxAuiNotebook_destroy
#else
- {NULL, "wxAuiNotebook", "'Destroy'", 0}, // 2631
+ {NULL, "wxAuiNotebook", "'Destroy'", 0}, // 2633
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetFlags, "wxAuiTabArt", "setFlags", 2}, // 2632
+ {wxAuiTabArt_SetFlags, "wxAuiTabArt", "setFlags", 2}, // 2634
#else
- {NULL, "wxAuiTabArt", "setFlags", 0}, // 2632
+ {NULL, "wxAuiTabArt", "setFlags", 0}, // 2634
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetMeasuringFont, "wxAuiTabArt", "setMeasuringFont", 2}, // 2633
+ {wxAuiTabArt_SetMeasuringFont, "wxAuiTabArt", "setMeasuringFont", 2}, // 2635
#else
- {NULL, "wxAuiTabArt", "setMeasuringFont", 0}, // 2633
+ {NULL, "wxAuiTabArt", "setMeasuringFont", 0}, // 2635
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetNormalFont, "wxAuiTabArt", "setNormalFont", 2}, // 2634
+ {wxAuiTabArt_SetNormalFont, "wxAuiTabArt", "setNormalFont", 2}, // 2636
#else
- {NULL, "wxAuiTabArt", "setNormalFont", 0}, // 2634
+ {NULL, "wxAuiTabArt", "setNormalFont", 0}, // 2636
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetSelectedFont, "wxAuiTabArt", "setSelectedFont", 2}, // 2635
+ {wxAuiTabArt_SetSelectedFont, "wxAuiTabArt", "setSelectedFont", 2}, // 2637
#else
- {NULL, "wxAuiTabArt", "setSelectedFont", 0}, // 2635
+ {NULL, "wxAuiTabArt", "setSelectedFont", 0}, // 2637
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetColour, "wxAuiTabArt", "setColour", 2}, // 2636
+ {wxAuiTabArt_SetColour, "wxAuiTabArt", "setColour", 2}, // 2638
#else
- {NULL, "wxAuiTabArt", "setColour", 0}, // 2636
+ {NULL, "wxAuiTabArt", "setColour", 0}, // 2638
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiTabArt_SetActiveColour, "wxAuiTabArt", "setActiveColour", 2}, // 2637
+ {wxAuiTabArt_SetActiveColour, "wxAuiTabArt", "setActiveColour", 2}, // 2639
#else
- {NULL, "wxAuiTabArt", "setActiveColour", 0}, // 2637
+ {NULL, "wxAuiTabArt", "setActiveColour", 0}, // 2639
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_GetColour, "wxAuiDockArt", "getColour", 2}, // 2638
+ {wxAuiDockArt_GetColour, "wxAuiDockArt", "getColour", 2}, // 2640
#else
- {NULL, "wxAuiDockArt", "getColour", 0}, // 2638
+ {NULL, "wxAuiDockArt", "getColour", 0}, // 2640
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_GetFont, "wxAuiDockArt", "getFont", 2}, // 2639
+ {wxAuiDockArt_GetFont, "wxAuiDockArt", "getFont", 2}, // 2641
#else
- {NULL, "wxAuiDockArt", "getFont", 0}, // 2639
+ {NULL, "wxAuiDockArt", "getFont", 0}, // 2641
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_GetMetric, "wxAuiDockArt", "getMetric", 2}, // 2640
+ {wxAuiDockArt_GetMetric, "wxAuiDockArt", "getMetric", 2}, // 2642
#else
- {NULL, "wxAuiDockArt", "getMetric", 0}, // 2640
+ {NULL, "wxAuiDockArt", "getMetric", 0}, // 2642
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_SetColour, "wxAuiDockArt", "setColour", 3}, // 2641
+ {wxAuiDockArt_SetColour, "wxAuiDockArt", "setColour", 3}, // 2643
#else
- {NULL, "wxAuiDockArt", "setColour", 0}, // 2641
+ {NULL, "wxAuiDockArt", "setColour", 0}, // 2643
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_SetFont, "wxAuiDockArt", "setFont", 3}, // 2642
+ {wxAuiDockArt_SetFont, "wxAuiDockArt", "setFont", 3}, // 2644
#else
- {NULL, "wxAuiDockArt", "setFont", 0}, // 2642
+ {NULL, "wxAuiDockArt", "setFont", 0}, // 2644
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiDockArt_SetMetric, "wxAuiDockArt", "setMetric", 3}, // 2643
+ {wxAuiDockArt_SetMetric, "wxAuiDockArt", "setMetric", 3}, // 2645
#else
- {NULL, "wxAuiDockArt", "setMetric", 0}, // 2643
+ {NULL, "wxAuiDockArt", "setMetric", 0}, // 2645
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiSimpleTabArt_new, "wxAuiSimpleTabArt", "new", 0}, // 2644
+ {wxAuiSimpleTabArt_new, "wxAuiSimpleTabArt", "new", 0}, // 2646
#else
- {NULL, "wxAuiSimpleTabArt", "new", 0}, // 2644
+ {NULL, "wxAuiSimpleTabArt", "new", 0}, // 2646
#endif // wxUSE_AUI
#if wxUSE_AUI
- {wxAuiSimpleTabArt_destroy, "wxAuiSimpleTabArt", "'Destroy'", 1}, // 2645
+ {wxAuiSimpleTabArt_destroy, "wxAuiSimpleTabArt", "'Destroy'", 1}, // 2647
#else
- {NULL, "wxAuiSimpleTabArt", "'Destroy'", 0}, // 2645
+ {NULL, "wxAuiSimpleTabArt", "'Destroy'", 0}, // 2647
#endif // wxUSE_AUI
- {wxMDIParentFrame_new_0, "wxMDIParentFrame", "new", 0}, // 2646
- {wxMDIParentFrame_new_4, "wxMDIParentFrame", "new", 4}, // 2647
- {NULL, "wxMDIParentFrame", "destroy", 1}, // 2648 obj destructor wxMDIParentFrame_destruct
- {wxMDIParentFrame_ActivateNext, "wxMDIParentFrame", "activateNext", 1}, // 2649
- {wxMDIParentFrame_ActivatePrevious, "wxMDIParentFrame", "activatePrevious", 1}, // 2650
- {wxMDIParentFrame_ArrangeIcons, "wxMDIParentFrame", "arrangeIcons", 1}, // 2651
- {wxMDIParentFrame_Cascade, "wxMDIParentFrame", "cascade", 1}, // 2652
- {wxMDIParentFrame_Create, "wxMDIParentFrame", "create", 5}, // 2653
- {wxMDIParentFrame_GetActiveChild, "wxMDIParentFrame", "getActiveChild", 1}, // 2654
- {wxMDIParentFrame_GetClientWindow, "wxMDIParentFrame", "getClientWindow", 1}, // 2655
- {wxMDIParentFrame_Tile, "wxMDIParentFrame", "tile", 2}, // 2656
- {wxMDIChildFrame_new_0, "wxMDIChildFrame", "new", 0}, // 2657
- {wxMDIChildFrame_new_4, "wxMDIChildFrame", "new", 4}, // 2658
- {NULL, "wxMDIChildFrame", "destroy", 1}, // 2659 obj destructor wxMDIChildFrame_destruct
- {wxMDIChildFrame_Activate, "wxMDIChildFrame", "activate", 1}, // 2660
- {wxMDIChildFrame_Create, "wxMDIChildFrame", "create", 5}, // 2661
- {wxMDIChildFrame_Maximize, "wxMDIChildFrame", "maximize", 2}, // 2662
- {wxMDIChildFrame_Restore, "wxMDIChildFrame", "restore", 1}, // 2663
- {wxMDIClientWindow_new, "wxMDIClientWindow", "new", 0}, // 2664
- {wxMDIClientWindow_CreateClient, "wxMDIClientWindow", "createClient", 3}, // 2665
- {NULL, "wxMDIClientWindow", "'Destroy'", 1}, // 2666 obj destructor wxMDIClientWindow_destroy
- {wxLayoutAlgorithm_new, "wxLayoutAlgorithm", "new", 0}, // 2667
- {NULL, "wxLayoutAlgorithm", "destroy", 1}, // 2668 obj destructor wxLayoutAlgorithm_destruct
- {wxLayoutAlgorithm_LayoutFrame, "wxLayoutAlgorithm", "layoutFrame", 3}, // 2669
- {wxLayoutAlgorithm_LayoutMDIFrame, "wxLayoutAlgorithm", "layoutMDIFrame", 3}, // 2670
- {wxLayoutAlgorithm_LayoutWindow, "wxLayoutAlgorithm", "layoutWindow", 3}, // 2671
- {wxEvent_GetId, "wxEvent", "getId", 1}, // 2672
- {wxEvent_GetSkipped, "wxEvent", "getSkipped", 1}, // 2673
- {wxEvent_GetTimestamp, "wxEvent", "getTimestamp", 1}, // 2674
- {wxEvent_IsCommandEvent, "wxEvent", "isCommandEvent", 1}, // 2675
- {wxEvent_ResumePropagation, "wxEvent", "resumePropagation", 2}, // 2676
- {wxEvent_ShouldPropagate, "wxEvent", "shouldPropagate", 1}, // 2677
- {wxEvent_Skip, "wxEvent", "skip", 2}, // 2678
- {wxEvent_StopPropagation, "wxEvent", "stopPropagation", 1}, // 2679
- {wxCommandEvent_getClientData, "wxCommandEvent", "getClientData", 1}, // 2680
- {wxCommandEvent_GetExtraLong, "wxCommandEvent", "getExtraLong", 1}, // 2681
- {wxCommandEvent_GetInt, "wxCommandEvent", "getInt", 1}, // 2682
- {wxCommandEvent_GetSelection, "wxCommandEvent", "getSelection", 1}, // 2683
- {wxCommandEvent_GetString, "wxCommandEvent", "getString", 1}, // 2684
- {wxCommandEvent_IsChecked, "wxCommandEvent", "isChecked", 1}, // 2685
- {wxCommandEvent_IsSelection, "wxCommandEvent", "isSelection", 1}, // 2686
- {wxCommandEvent_SetInt, "wxCommandEvent", "setInt", 2}, // 2687
- {wxCommandEvent_SetString, "wxCommandEvent", "setString", 2}, // 2688
- {wxScrollEvent_GetOrientation, "wxScrollEvent", "getOrientation", 1}, // 2689
- {wxScrollEvent_GetPosition, "wxScrollEvent", "getPosition", 1}, // 2690
- {wxScrollWinEvent_GetOrientation, "wxScrollWinEvent", "getOrientation", 1}, // 2691
- {wxScrollWinEvent_GetPosition, "wxScrollWinEvent", "getPosition", 1}, // 2692
- {wxMouseEvent_AltDown, "wxMouseEvent", "altDown", 1}, // 2693
- {wxMouseEvent_Button, "wxMouseEvent", "button", 2}, // 2694
- {wxMouseEvent_ButtonDClick, "wxMouseEvent", "buttonDClick", 2}, // 2695
- {wxMouseEvent_ButtonDown, "wxMouseEvent", "buttonDown", 2}, // 2696
- {wxMouseEvent_ButtonUp, "wxMouseEvent", "buttonUp", 2}, // 2697
- {wxMouseEvent_CmdDown, "wxMouseEvent", "cmdDown", 1}, // 2698
- {wxMouseEvent_ControlDown, "wxMouseEvent", "controlDown", 1}, // 2699
- {wxMouseEvent_Dragging, "wxMouseEvent", "dragging", 1}, // 2700
- {wxMouseEvent_Entering, "wxMouseEvent", "entering", 1}, // 2701
- {wxMouseEvent_GetButton, "wxMouseEvent", "getButton", 1}, // 2702
- {wxMouseEvent_GetPosition, "wxMouseEvent", "getPosition", 1}, // 2703
- {NULL, "", "", 0}, // 2704
- {wxMouseEvent_GetLogicalPosition, "wxMouseEvent", "getLogicalPosition", 2}, // 2705
- {wxMouseEvent_GetLinesPerAction, "wxMouseEvent", "getLinesPerAction", 1}, // 2706
- {wxMouseEvent_GetWheelRotation, "wxMouseEvent", "getWheelRotation", 1}, // 2707
- {wxMouseEvent_GetWheelDelta, "wxMouseEvent", "getWheelDelta", 1}, // 2708
- {wxMouseEvent_GetX, "wxMouseEvent", "getX", 1}, // 2709
- {wxMouseEvent_GetY, "wxMouseEvent", "getY", 1}, // 2710
- {wxMouseEvent_IsButton, "wxMouseEvent", "isButton", 1}, // 2711
- {wxMouseEvent_IsPageScroll, "wxMouseEvent", "isPageScroll", 1}, // 2712
- {wxMouseEvent_Leaving, "wxMouseEvent", "leaving", 1}, // 2713
- {wxMouseEvent_LeftDClick, "wxMouseEvent", "leftDClick", 1}, // 2714
- {wxMouseEvent_LeftDown, "wxMouseEvent", "leftDown", 1}, // 2715
- {wxMouseEvent_LeftIsDown, "wxMouseEvent", "leftIsDown", 1}, // 2716
- {wxMouseEvent_LeftUp, "wxMouseEvent", "leftUp", 1}, // 2717
- {wxMouseEvent_MetaDown, "wxMouseEvent", "metaDown", 1}, // 2718
- {wxMouseEvent_MiddleDClick, "wxMouseEvent", "middleDClick", 1}, // 2719
- {wxMouseEvent_MiddleDown, "wxMouseEvent", "middleDown", 1}, // 2720
- {wxMouseEvent_MiddleIsDown, "wxMouseEvent", "middleIsDown", 1}, // 2721
- {wxMouseEvent_MiddleUp, "wxMouseEvent", "middleUp", 1}, // 2722
- {wxMouseEvent_Moving, "wxMouseEvent", "moving", 1}, // 2723
- {wxMouseEvent_RightDClick, "wxMouseEvent", "rightDClick", 1}, // 2724
- {wxMouseEvent_RightDown, "wxMouseEvent", "rightDown", 1}, // 2725
- {wxMouseEvent_RightIsDown, "wxMouseEvent", "rightIsDown", 1}, // 2726
- {wxMouseEvent_RightUp, "wxMouseEvent", "rightUp", 1}, // 2727
- {wxMouseEvent_ShiftDown, "wxMouseEvent", "shiftDown", 1}, // 2728
- {wxMouseEvent_GetWheelAxis, "wxMouseEvent", "getWheelAxis", 1}, // 2729
- {wxSetCursorEvent_GetCursor, "wxSetCursorEvent", "getCursor", 1}, // 2730
- {wxSetCursorEvent_GetX, "wxSetCursorEvent", "getX", 1}, // 2731
- {wxSetCursorEvent_GetY, "wxSetCursorEvent", "getY", 1}, // 2732
- {wxSetCursorEvent_HasCursor, "wxSetCursorEvent", "hasCursor", 1}, // 2733
- {wxSetCursorEvent_SetCursor, "wxSetCursorEvent", "setCursor", 2}, // 2734
- {wxKeyEvent_AltDown, "wxKeyEvent", "altDown", 1}, // 2735
- {wxKeyEvent_CmdDown, "wxKeyEvent", "cmdDown", 1}, // 2736
- {wxKeyEvent_ControlDown, "wxKeyEvent", "controlDown", 1}, // 2737
- {wxKeyEvent_GetKeyCode, "wxKeyEvent", "getKeyCode", 1}, // 2738
- {wxKeyEvent_GetModifiers, "wxKeyEvent", "getModifiers", 1}, // 2739
- {wxKeyEvent_GetPosition, "wxKeyEvent", "getPosition", 1}, // 2740
- {NULL, "", "", 0}, // 2741
- {wxKeyEvent_GetRawKeyCode, "wxKeyEvent", "getRawKeyCode", 1}, // 2742
- {wxKeyEvent_GetRawKeyFlags, "wxKeyEvent", "getRawKeyFlags", 1}, // 2743
- {wxKeyEvent_GetUnicodeKey, "wxKeyEvent", "getUnicodeKey", 1}, // 2744
- {wxKeyEvent_GetX, "wxKeyEvent", "getX", 1}, // 2745
- {wxKeyEvent_GetY, "wxKeyEvent", "getY", 1}, // 2746
- {wxKeyEvent_HasModifiers, "wxKeyEvent", "hasModifiers", 1}, // 2747
- {wxKeyEvent_MetaDown, "wxKeyEvent", "metaDown", 1}, // 2748
- {wxKeyEvent_ShiftDown, "wxKeyEvent", "shiftDown", 1}, // 2749
- {wxSizeEvent_GetSize, "wxSizeEvent", "getSize", 1}, // 2750
- {wxSizeEvent_GetRect, "wxSizeEvent", "getRect", 1}, // 2751
- {wxMoveEvent_GetPosition, "wxMoveEvent", "getPosition", 1}, // 2752
- {wxMoveEvent_GetRect, "wxMoveEvent", "getRect", 1}, // 2753
- {wxEraseEvent_GetDC, "wxEraseEvent", "getDC", 1}, // 2754
- {wxFocusEvent_GetWindow, "wxFocusEvent", "getWindow", 1}, // 2755
- {wxChildFocusEvent_GetWindow, "wxChildFocusEvent", "getWindow", 1}, // 2756
- {wxMenuEvent_GetMenu, "wxMenuEvent", "getMenu", 1}, // 2757
- {wxMenuEvent_GetMenuId, "wxMenuEvent", "getMenuId", 1}, // 2758
- {wxMenuEvent_IsPopup, "wxMenuEvent", "isPopup", 1}, // 2759
- {wxCloseEvent_CanVeto, "wxCloseEvent", "canVeto", 1}, // 2760
- {wxCloseEvent_GetLoggingOff, "wxCloseEvent", "getLoggingOff", 1}, // 2761
- {wxCloseEvent_SetCanVeto, "wxCloseEvent", "setCanVeto", 2}, // 2762
- {wxCloseEvent_SetLoggingOff, "wxCloseEvent", "setLoggingOff", 2}, // 2763
- {wxCloseEvent_Veto, "wxCloseEvent", "veto", 2}, // 2764
- {wxShowEvent_SetShow, "wxShowEvent", "setShow", 2}, // 2765
- {wxShowEvent_IsShown, "wxShowEvent", "isShown", 1}, // 2766
- {wxIconizeEvent_IsIconized, "wxIconizeEvent", "isIconized", 1}, // 2767
- {wxJoystickEvent_ButtonDown, "wxJoystickEvent", "buttonDown", 2}, // 2768
- {wxJoystickEvent_ButtonIsDown, "wxJoystickEvent", "buttonIsDown", 2}, // 2769
- {wxJoystickEvent_ButtonUp, "wxJoystickEvent", "buttonUp", 2}, // 2770
- {wxJoystickEvent_GetButtonChange, "wxJoystickEvent", "getButtonChange", 1}, // 2771
- {wxJoystickEvent_GetButtonState, "wxJoystickEvent", "getButtonState", 1}, // 2772
- {wxJoystickEvent_GetJoystick, "wxJoystickEvent", "getJoystick", 1}, // 2773
- {wxJoystickEvent_GetPosition, "wxJoystickEvent", "getPosition", 1}, // 2774
- {wxJoystickEvent_GetZPosition, "wxJoystickEvent", "getZPosition", 1}, // 2775
- {wxJoystickEvent_IsButton, "wxJoystickEvent", "isButton", 1}, // 2776
- {wxJoystickEvent_IsMove, "wxJoystickEvent", "isMove", 1}, // 2777
- {wxJoystickEvent_IsZMove, "wxJoystickEvent", "isZMove", 1}, // 2778
- {wxUpdateUIEvent_CanUpdate, "wxUpdateUIEvent", "canUpdate", 1}, // 2779
- {wxUpdateUIEvent_Check, "wxUpdateUIEvent", "check", 2}, // 2780
- {wxUpdateUIEvent_Enable, "wxUpdateUIEvent", "enable", 2}, // 2781
- {wxUpdateUIEvent_Show, "wxUpdateUIEvent", "show", 2}, // 2782
- {wxUpdateUIEvent_GetChecked, "wxUpdateUIEvent", "getChecked", 1}, // 2783
- {wxUpdateUIEvent_GetEnabled, "wxUpdateUIEvent", "getEnabled", 1}, // 2784
- {wxUpdateUIEvent_GetShown, "wxUpdateUIEvent", "getShown", 1}, // 2785
- {wxUpdateUIEvent_GetSetChecked, "wxUpdateUIEvent", "getSetChecked", 1}, // 2786
- {wxUpdateUIEvent_GetSetEnabled, "wxUpdateUIEvent", "getSetEnabled", 1}, // 2787
- {wxUpdateUIEvent_GetSetShown, "wxUpdateUIEvent", "getSetShown", 1}, // 2788
- {wxUpdateUIEvent_GetSetText, "wxUpdateUIEvent", "getSetText", 1}, // 2789
- {wxUpdateUIEvent_GetText, "wxUpdateUIEvent", "getText", 1}, // 2790
- {wxUpdateUIEvent_GetMode, "wxUpdateUIEvent", "getMode", 0}, // 2791
- {wxUpdateUIEvent_GetUpdateInterval, "wxUpdateUIEvent", "getUpdateInterval", 0}, // 2792
- {wxUpdateUIEvent_ResetUpdateTime, "wxUpdateUIEvent", "resetUpdateTime", 0}, // 2793
- {wxUpdateUIEvent_SetMode, "wxUpdateUIEvent", "setMode", 1}, // 2794
- {wxUpdateUIEvent_SetText, "wxUpdateUIEvent", "setText", 2}, // 2795
- {wxUpdateUIEvent_SetUpdateInterval, "wxUpdateUIEvent", "setUpdateInterval", 1}, // 2796
- {wxMouseCaptureChangedEvent_GetCapturedWindow, "wxMouseCaptureChangedEvent", "getCapturedWindow", 1}, // 2797
- {wxPaletteChangedEvent_SetChangedWindow, "wxPaletteChangedEvent", "setChangedWindow", 2}, // 2798
- {wxPaletteChangedEvent_GetChangedWindow, "wxPaletteChangedEvent", "getChangedWindow", 1}, // 2799
- {wxQueryNewPaletteEvent_SetPaletteRealized, "wxQueryNewPaletteEvent", "setPaletteRealized", 2}, // 2800
- {wxQueryNewPaletteEvent_GetPaletteRealized, "wxQueryNewPaletteEvent", "getPaletteRealized", 1}, // 2801
- {wxNavigationKeyEvent_GetDirection, "wxNavigationKeyEvent", "getDirection", 1}, // 2802
- {wxNavigationKeyEvent_SetDirection, "wxNavigationKeyEvent", "setDirection", 2}, // 2803
- {wxNavigationKeyEvent_IsWindowChange, "wxNavigationKeyEvent", "isWindowChange", 1}, // 2804
- {wxNavigationKeyEvent_SetWindowChange, "wxNavigationKeyEvent", "setWindowChange", 2}, // 2805
- {wxNavigationKeyEvent_IsFromTab, "wxNavigationKeyEvent", "isFromTab", 1}, // 2806
- {wxNavigationKeyEvent_SetFromTab, "wxNavigationKeyEvent", "setFromTab", 2}, // 2807
- {wxNavigationKeyEvent_GetCurrentFocus, "wxNavigationKeyEvent", "getCurrentFocus", 1}, // 2808
- {wxNavigationKeyEvent_SetCurrentFocus, "wxNavigationKeyEvent", "setCurrentFocus", 2}, // 2809
- {wxHelpEvent_GetOrigin, "wxHelpEvent", "getOrigin", 1}, // 2810
- {wxHelpEvent_GetPosition, "wxHelpEvent", "getPosition", 1}, // 2811
- {wxHelpEvent_SetOrigin, "wxHelpEvent", "setOrigin", 2}, // 2812
- {wxHelpEvent_SetPosition, "wxHelpEvent", "setPosition", 2}, // 2813
- {wxContextMenuEvent_GetPosition, "wxContextMenuEvent", "getPosition", 1}, // 2814
- {wxContextMenuEvent_SetPosition, "wxContextMenuEvent", "setPosition", 2}, // 2815
- {wxIdleEvent_GetMode, "wxIdleEvent", "getMode", 0}, // 2816
- {wxIdleEvent_RequestMore, "wxIdleEvent", "requestMore", 2}, // 2817
- {wxIdleEvent_MoreRequested, "wxIdleEvent", "moreRequested", 1}, // 2818
- {wxIdleEvent_SetMode, "wxIdleEvent", "setMode", 1}, // 2819
- {wxGridEvent_AltDown, "wxGridEvent", "altDown", 1}, // 2820
- {wxGridEvent_ControlDown, "wxGridEvent", "controlDown", 1}, // 2821
- {wxGridEvent_GetCol, "wxGridEvent", "getCol", 1}, // 2822
- {wxGridEvent_GetPosition, "wxGridEvent", "getPosition", 1}, // 2823
- {wxGridEvent_GetRow, "wxGridEvent", "getRow", 1}, // 2824
- {wxGridEvent_MetaDown, "wxGridEvent", "metaDown", 1}, // 2825
- {wxGridEvent_Selecting, "wxGridEvent", "selecting", 1}, // 2826
- {wxGridEvent_ShiftDown, "wxGridEvent", "shiftDown", 1}, // 2827
- {wxNotifyEvent_Allow, "wxNotifyEvent", "allow", 1}, // 2828
- {wxNotifyEvent_IsAllowed, "wxNotifyEvent", "isAllowed", 1}, // 2829
- {wxNotifyEvent_Veto, "wxNotifyEvent", "veto", 1}, // 2830
- {wxSashEvent_GetEdge, "wxSashEvent", "getEdge", 1}, // 2831
- {wxSashEvent_GetDragRect, "wxSashEvent", "getDragRect", 1}, // 2832
- {wxSashEvent_GetDragStatus, "wxSashEvent", "getDragStatus", 1}, // 2833
- {wxListEvent_GetCacheFrom, "wxListEvent", "getCacheFrom", 1}, // 2834
- {wxListEvent_GetCacheTo, "wxListEvent", "getCacheTo", 1}, // 2835
- {wxListEvent_GetKeyCode, "wxListEvent", "getKeyCode", 1}, // 2836
- {wxListEvent_GetIndex, "wxListEvent", "getIndex", 1}, // 2837
- {wxListEvent_GetColumn, "wxListEvent", "getColumn", 1}, // 2838
- {wxListEvent_GetPoint, "wxListEvent", "getPoint", 1}, // 2839
- {wxListEvent_GetLabel, "wxListEvent", "getLabel", 1}, // 2840
- {wxListEvent_GetText, "wxListEvent", "getText", 1}, // 2841
- {wxListEvent_GetImage, "wxListEvent", "getImage", 1}, // 2842
- {wxListEvent_GetData, "wxListEvent", "getData", 1}, // 2843
- {wxListEvent_GetMask, "wxListEvent", "getMask", 1}, // 2844
- {wxListEvent_GetItem, "wxListEvent", "getItem", 1}, // 2845
- {wxListEvent_IsEditCancelled, "wxListEvent", "isEditCancelled", 1}, // 2846
- {wxDateEvent_GetDate, "wxDateEvent", "getDate", 1}, // 2847
- {wxCalendarEvent_GetWeekDay, "wxCalendarEvent", "getWeekDay", 1}, // 2848
- {wxCalendarEvent_GetDate, "wxCalendarEvent", "getDate", 1}, // 2849
- {wxFileDirPickerEvent_GetPath, "wxFileDirPickerEvent", "getPath", 1}, // 2850
- {wxColourPickerEvent_GetColour, "wxColourPickerEvent", "getColour", 1}, // 2851
- {wxFontPickerEvent_GetFont, "wxFontPickerEvent", "getFont", 1}, // 2852
- {wxStyledTextEvent_GetPosition, "wxStyledTextEvent", "getPosition", 1}, // 2853
- {wxStyledTextEvent_GetKey, "wxStyledTextEvent", "getKey", 1}, // 2854
- {wxStyledTextEvent_GetModifiers, "wxStyledTextEvent", "getModifiers", 1}, // 2855
- {wxStyledTextEvent_GetModificationType, "wxStyledTextEvent", "getModificationType", 1}, // 2856
- {wxStyledTextEvent_GetText, "wxStyledTextEvent", "getText", 1}, // 2857
- {wxStyledTextEvent_GetLength, "wxStyledTextEvent", "getLength", 1}, // 2858
- {wxStyledTextEvent_GetLinesAdded, "wxStyledTextEvent", "getLinesAdded", 1}, // 2859
- {wxStyledTextEvent_GetLine, "wxStyledTextEvent", "getLine", 1}, // 2860
- {wxStyledTextEvent_GetFoldLevelNow, "wxStyledTextEvent", "getFoldLevelNow", 1}, // 2861
- {wxStyledTextEvent_GetFoldLevelPrev, "wxStyledTextEvent", "getFoldLevelPrev", 1}, // 2862
- {wxStyledTextEvent_GetMargin, "wxStyledTextEvent", "getMargin", 1}, // 2863
- {wxStyledTextEvent_GetMessage, "wxStyledTextEvent", "getMessage", 1}, // 2864
- {wxStyledTextEvent_GetWParam, "wxStyledTextEvent", "getWParam", 1}, // 2865
- {wxStyledTextEvent_GetLParam, "wxStyledTextEvent", "getLParam", 1}, // 2866
- {wxStyledTextEvent_GetListType, "wxStyledTextEvent", "getListType", 1}, // 2867
- {wxStyledTextEvent_GetX, "wxStyledTextEvent", "getX", 1}, // 2868
- {wxStyledTextEvent_GetY, "wxStyledTextEvent", "getY", 1}, // 2869
- {wxStyledTextEvent_GetDragText, "wxStyledTextEvent", "getDragText", 1}, // 2870
- {wxStyledTextEvent_GetDragAllowMove, "wxStyledTextEvent", "getDragAllowMove", 1}, // 2871
- {wxStyledTextEvent_GetDragResult, "wxStyledTextEvent", "getDragResult", 1}, // 2872
- {wxStyledTextEvent_GetShift, "wxStyledTextEvent", "getShift", 1}, // 2873
- {wxStyledTextEvent_GetControl, "wxStyledTextEvent", "getControl", 1}, // 2874
- {wxStyledTextEvent_GetAlt, "wxStyledTextEvent", "getAlt", 1}, // 2875
- {utils_wxGetKeyState, "utils", "getKeyState", 1}, // 2876
- {utils_wxGetMousePosition, "utils", "getMousePosition", 0}, // 2877
- {utils_wxGetMouseState, "utils", "getMouseState", 0}, // 2878
- {utils_wxSetDetectableAutoRepeat, "utils", "setDetectableAutoRepeat", 1}, // 2879
- {utils_wxBell, "utils", "bell", 0}, // 2880
- {utils_wxFindMenuItemId, "utils", "findMenuItemId", 3}, // 2881
- {utils_wxFindWindowAtPoint, "utils", "findWindowAtPoint", 1}, // 2882
- {utils_wxBeginBusyCursor, "utils", "beginBusyCursor", 1}, // 2883
- {utils_wxEndBusyCursor, "utils", "endBusyCursor", 0}, // 2884
- {utils_wxIsBusy, "utils", "isBusy", 0}, // 2885
- {utils_wxShutdown, "utils", "shutdown", 1}, // 2886
- {utils_wxShell, "utils", "shell", 1}, // 2887
- {utils_wxLaunchDefaultBrowser, "utils", "launchDefaultBrowser", 2}, // 2888
- {utils_wxGetEmailAddress, "utils", "getEmailAddress", 0}, // 2889
- {utils_wxGetUserId, "utils", "getUserId", 0}, // 2890
- {utils_wxGetHomeDir, "utils", "getHomeDir", 0}, // 2891
- {utils_wxNewId, "utils", "newId", 0}, // 2892
- {utils_wxRegisterId, "utils", "registerId", 1}, // 2893
- {utils_wxGetCurrentId, "utils", "getCurrentId", 0}, // 2894
- {utils_wxGetOsDescription, "utils", "getOsDescription", 0}, // 2895
- {utils_wxIsPlatformLittleEndian, "utils", "isPlatformLittleEndian", 0}, // 2896
- {utils_wxIsPlatform64Bit, "utils", "isPlatform64Bit", 0}, // 2897
- {gdicmn_wxDisplaySize, "gdicmn", "displaySize", 0}, // 2898
- {gdicmn_wxSetCursor, "gdicmn", "setCursor", 1}, // 2899
- {wxPrintout_new, "wxPrintout", "new", 3}, // 2900
- {NULL, "wxPrintout", "destroy", 1}, // 2901 obj destructor wxPrintout_destruct
- {wxPrintout_GetDC, "wxPrintout", "getDC", 1}, // 2902
- {wxPrintout_GetPageSizeMM, "wxPrintout", "getPageSizeMM", 1}, // 2903
- {wxPrintout_GetPageSizePixels, "wxPrintout", "getPageSizePixels", 1}, // 2904
- {wxPrintout_GetPaperRectPixels, "wxPrintout", "getPaperRectPixels", 1}, // 2905
- {wxPrintout_GetPPIPrinter, "wxPrintout", "getPPIPrinter", 1}, // 2906
- {wxPrintout_GetPPIScreen, "wxPrintout", "getPPIScreen", 1}, // 2907
- {wxPrintout_GetTitle, "wxPrintout", "getTitle", 1}, // 2908
- {wxPrintout_IsPreview, "wxPrintout", "isPreview", 1}, // 2909
- {wxPrintout_FitThisSizeToPaper, "wxPrintout", "fitThisSizeToPaper", 2}, // 2910
- {wxPrintout_FitThisSizeToPage, "wxPrintout", "fitThisSizeToPage", 2}, // 2911
- {wxPrintout_FitThisSizeToPageMargins, "wxPrintout", "fitThisSizeToPageMargins", 3}, // 2912
- {wxPrintout_MapScreenSizeToPaper, "wxPrintout", "mapScreenSizeToPaper", 1}, // 2913
- {wxPrintout_MapScreenSizeToPage, "wxPrintout", "mapScreenSizeToPage", 1}, // 2914
- {wxPrintout_MapScreenSizeToPageMargins, "wxPrintout", "mapScreenSizeToPageMargins", 2}, // 2915
- {wxPrintout_MapScreenSizeToDevice, "wxPrintout", "mapScreenSizeToDevice", 1}, // 2916
- {wxPrintout_GetLogicalPaperRect, "wxPrintout", "getLogicalPaperRect", 1}, // 2917
- {wxPrintout_GetLogicalPageRect, "wxPrintout", "getLogicalPageRect", 1}, // 2918
- {wxPrintout_GetLogicalPageMarginsRect, "wxPrintout", "getLogicalPageMarginsRect", 2}, // 2919
- {wxPrintout_SetLogicalOrigin, "wxPrintout", "setLogicalOrigin", 3}, // 2920
- {wxPrintout_OffsetLogicalOrigin, "wxPrintout", "offsetLogicalOrigin", 3}, // 2921
- {wxStyledTextCtrl_new_2, "wxStyledTextCtrl", "new", 2}, // 2922
- {wxStyledTextCtrl_new_0, "wxStyledTextCtrl", "new", 0}, // 2923
- {NULL, "wxStyledTextCtrl", "destroy", 1}, // 2924 obj destructor wxStyledTextCtrl_destruct
- {wxStyledTextCtrl_Create, "wxStyledTextCtrl", "create", 3}, // 2925
- {wxStyledTextCtrl_AddText, "wxStyledTextCtrl", "addText", 2}, // 2926
- {wxStyledTextCtrl_InsertText, "wxStyledTextCtrl", "insertText", 3}, // 2927
- {wxStyledTextCtrl_ClearAll, "wxStyledTextCtrl", "clearAll", 1}, // 2928
- {wxStyledTextCtrl_ClearDocumentStyle, "wxStyledTextCtrl", "clearDocumentStyle", 1}, // 2929
- {wxStyledTextCtrl_GetLength, "wxStyledTextCtrl", "getLength", 1}, // 2930
- {wxStyledTextCtrl_GetCharAt, "wxStyledTextCtrl", "getCharAt", 2}, // 2931
- {wxStyledTextCtrl_GetCurrentPos, "wxStyledTextCtrl", "getCurrentPos", 1}, // 2932
- {wxStyledTextCtrl_GetAnchor, "wxStyledTextCtrl", "getAnchor", 1}, // 2933
- {wxStyledTextCtrl_GetStyleAt, "wxStyledTextCtrl", "getStyleAt", 2}, // 2934
- {wxStyledTextCtrl_Redo, "wxStyledTextCtrl", "redo", 1}, // 2935
- {wxStyledTextCtrl_SetUndoCollection, "wxStyledTextCtrl", "setUndoCollection", 2}, // 2936
- {wxStyledTextCtrl_SelectAll, "wxStyledTextCtrl", "selectAll", 1}, // 2937
- {wxStyledTextCtrl_SetSavePoint, "wxStyledTextCtrl", "setSavePoint", 1}, // 2938
- {wxStyledTextCtrl_CanRedo, "wxStyledTextCtrl", "canRedo", 1}, // 2939
- {wxStyledTextCtrl_MarkerLineFromHandle, "wxStyledTextCtrl", "markerLineFromHandle", 2}, // 2940
- {wxStyledTextCtrl_MarkerDeleteHandle, "wxStyledTextCtrl", "markerDeleteHandle", 2}, // 2941
- {wxStyledTextCtrl_GetUndoCollection, "wxStyledTextCtrl", "getUndoCollection", 1}, // 2942
- {wxStyledTextCtrl_GetViewWhiteSpace, "wxStyledTextCtrl", "getViewWhiteSpace", 1}, // 2943
- {wxStyledTextCtrl_SetViewWhiteSpace, "wxStyledTextCtrl", "setViewWhiteSpace", 2}, // 2944
- {wxStyledTextCtrl_PositionFromPoint, "wxStyledTextCtrl", "positionFromPoint", 2}, // 2945
- {wxStyledTextCtrl_PositionFromPointClose, "wxStyledTextCtrl", "positionFromPointClose", 3}, // 2946
- {wxStyledTextCtrl_GotoLine, "wxStyledTextCtrl", "gotoLine", 2}, // 2947
- {wxStyledTextCtrl_GotoPos, "wxStyledTextCtrl", "gotoPos", 2}, // 2948
- {wxStyledTextCtrl_SetAnchor, "wxStyledTextCtrl", "setAnchor", 2}, // 2949
- {wxStyledTextCtrl_GetCurLine, "wxStyledTextCtrl", "getCurLine", 1}, // 2950
- {wxStyledTextCtrl_GetEndStyled, "wxStyledTextCtrl", "getEndStyled", 1}, // 2951
- {wxStyledTextCtrl_ConvertEOLs, "wxStyledTextCtrl", "convertEOLs", 2}, // 2952
- {wxStyledTextCtrl_GetEOLMode, "wxStyledTextCtrl", "getEOLMode", 1}, // 2953
- {wxStyledTextCtrl_SetEOLMode, "wxStyledTextCtrl", "setEOLMode", 2}, // 2954
- {wxStyledTextCtrl_StartStyling, "wxStyledTextCtrl", "startStyling", 2}, // 2955
- {wxStyledTextCtrl_SetStyling, "wxStyledTextCtrl", "setStyling", 3}, // 2956
- {wxStyledTextCtrl_GetBufferedDraw, "wxStyledTextCtrl", "getBufferedDraw", 1}, // 2957
- {wxStyledTextCtrl_SetBufferedDraw, "wxStyledTextCtrl", "setBufferedDraw", 2}, // 2958
- {wxStyledTextCtrl_SetTabWidth, "wxStyledTextCtrl", "setTabWidth", 2}, // 2959
- {wxStyledTextCtrl_GetTabWidth, "wxStyledTextCtrl", "getTabWidth", 1}, // 2960
- {wxStyledTextCtrl_SetCodePage, "wxStyledTextCtrl", "setCodePage", 2}, // 2961
- {wxStyledTextCtrl_MarkerDefine, "wxStyledTextCtrl", "markerDefine", 4}, // 2962
- {wxStyledTextCtrl_MarkerSetForeground, "wxStyledTextCtrl", "markerSetForeground", 3}, // 2963
- {wxStyledTextCtrl_MarkerSetBackground, "wxStyledTextCtrl", "markerSetBackground", 3}, // 2964
- {wxStyledTextCtrl_MarkerAdd, "wxStyledTextCtrl", "markerAdd", 3}, // 2965
- {wxStyledTextCtrl_MarkerDelete, "wxStyledTextCtrl", "markerDelete", 3}, // 2966
- {wxStyledTextCtrl_MarkerDeleteAll, "wxStyledTextCtrl", "markerDeleteAll", 2}, // 2967
- {wxStyledTextCtrl_MarkerGet, "wxStyledTextCtrl", "markerGet", 2}, // 2968
- {wxStyledTextCtrl_MarkerNext, "wxStyledTextCtrl", "markerNext", 3}, // 2969
- {wxStyledTextCtrl_MarkerPrevious, "wxStyledTextCtrl", "markerPrevious", 3}, // 2970
- {wxStyledTextCtrl_MarkerDefineBitmap, "wxStyledTextCtrl", "markerDefineBitmap", 3}, // 2971
- {wxStyledTextCtrl_MarkerAddSet, "wxStyledTextCtrl", "markerAddSet", 3}, // 2972
- {wxStyledTextCtrl_MarkerSetAlpha, "wxStyledTextCtrl", "markerSetAlpha", 3}, // 2973
- {wxStyledTextCtrl_SetMarginType, "wxStyledTextCtrl", "setMarginType", 3}, // 2974
- {wxStyledTextCtrl_GetMarginType, "wxStyledTextCtrl", "getMarginType", 2}, // 2975
- {wxStyledTextCtrl_SetMarginWidth, "wxStyledTextCtrl", "setMarginWidth", 3}, // 2976
- {wxStyledTextCtrl_GetMarginWidth, "wxStyledTextCtrl", "getMarginWidth", 2}, // 2977
- {wxStyledTextCtrl_SetMarginMask, "wxStyledTextCtrl", "setMarginMask", 3}, // 2978
- {wxStyledTextCtrl_GetMarginMask, "wxStyledTextCtrl", "getMarginMask", 2}, // 2979
- {wxStyledTextCtrl_SetMarginSensitive, "wxStyledTextCtrl", "setMarginSensitive", 3}, // 2980
- {wxStyledTextCtrl_GetMarginSensitive, "wxStyledTextCtrl", "getMarginSensitive", 2}, // 2981
- {wxStyledTextCtrl_StyleClearAll, "wxStyledTextCtrl", "styleClearAll", 1}, // 2982
- {wxStyledTextCtrl_StyleSetForeground, "wxStyledTextCtrl", "styleSetForeground", 3}, // 2983
- {wxStyledTextCtrl_StyleSetBackground, "wxStyledTextCtrl", "styleSetBackground", 3}, // 2984
- {wxStyledTextCtrl_StyleSetBold, "wxStyledTextCtrl", "styleSetBold", 3}, // 2985
- {wxStyledTextCtrl_StyleSetItalic, "wxStyledTextCtrl", "styleSetItalic", 3}, // 2986
- {wxStyledTextCtrl_StyleSetSize, "wxStyledTextCtrl", "styleSetSize", 3}, // 2987
- {wxStyledTextCtrl_StyleSetFaceName, "wxStyledTextCtrl", "styleSetFaceName", 3}, // 2988
- {wxStyledTextCtrl_StyleSetEOLFilled, "wxStyledTextCtrl", "styleSetEOLFilled", 3}, // 2989
- {wxStyledTextCtrl_StyleResetDefault, "wxStyledTextCtrl", "styleResetDefault", 1}, // 2990
- {wxStyledTextCtrl_StyleSetUnderline, "wxStyledTextCtrl", "styleSetUnderline", 3}, // 2991
- {wxStyledTextCtrl_StyleSetCase, "wxStyledTextCtrl", "styleSetCase", 3}, // 2992
- {wxStyledTextCtrl_StyleSetHotSpot, "wxStyledTextCtrl", "styleSetHotSpot", 3}, // 2993
- {wxStyledTextCtrl_SetSelForeground, "wxStyledTextCtrl", "setSelForeground", 3}, // 2994
- {wxStyledTextCtrl_SetSelBackground, "wxStyledTextCtrl", "setSelBackground", 3}, // 2995
- {wxStyledTextCtrl_GetSelAlpha, "wxStyledTextCtrl", "getSelAlpha", 1}, // 2996
- {wxStyledTextCtrl_SetSelAlpha, "wxStyledTextCtrl", "setSelAlpha", 2}, // 2997
- {wxStyledTextCtrl_SetCaretForeground, "wxStyledTextCtrl", "setCaretForeground", 2}, // 2998
- {wxStyledTextCtrl_CmdKeyAssign, "wxStyledTextCtrl", "cmdKeyAssign", 4}, // 2999
- {wxStyledTextCtrl_CmdKeyClear, "wxStyledTextCtrl", "cmdKeyClear", 3}, // 3000
- {wxStyledTextCtrl_CmdKeyClearAll, "wxStyledTextCtrl", "cmdKeyClearAll", 1}, // 3001
- {wxStyledTextCtrl_SetStyleBytes, "wxStyledTextCtrl", "setStyleBytes", 2}, // 3002
- {wxStyledTextCtrl_StyleSetVisible, "wxStyledTextCtrl", "styleSetVisible", 3}, // 3003
- {wxStyledTextCtrl_GetCaretPeriod, "wxStyledTextCtrl", "getCaretPeriod", 1}, // 3004
- {wxStyledTextCtrl_SetCaretPeriod, "wxStyledTextCtrl", "setCaretPeriod", 2}, // 3005
- {wxStyledTextCtrl_SetWordChars, "wxStyledTextCtrl", "setWordChars", 2}, // 3006
- {wxStyledTextCtrl_BeginUndoAction, "wxStyledTextCtrl", "beginUndoAction", 1}, // 3007
- {wxStyledTextCtrl_EndUndoAction, "wxStyledTextCtrl", "endUndoAction", 1}, // 3008
- {wxStyledTextCtrl_IndicatorSetStyle, "wxStyledTextCtrl", "indicatorSetStyle", 3}, // 3009
- {wxStyledTextCtrl_IndicatorGetStyle, "wxStyledTextCtrl", "indicatorGetStyle", 2}, // 3010
- {wxStyledTextCtrl_IndicatorSetForeground, "wxStyledTextCtrl", "indicatorSetForeground", 3}, // 3011
- {wxStyledTextCtrl_IndicatorGetForeground, "wxStyledTextCtrl", "indicatorGetForeground", 2}, // 3012
- {wxStyledTextCtrl_SetWhitespaceForeground, "wxStyledTextCtrl", "setWhitespaceForeground", 3}, // 3013
- {wxStyledTextCtrl_SetWhitespaceBackground, "wxStyledTextCtrl", "setWhitespaceBackground", 3}, // 3014
- {wxStyledTextCtrl_GetStyleBits, "wxStyledTextCtrl", "getStyleBits", 1}, // 3015
- {wxStyledTextCtrl_SetLineState, "wxStyledTextCtrl", "setLineState", 3}, // 3016
- {wxStyledTextCtrl_GetLineState, "wxStyledTextCtrl", "getLineState", 2}, // 3017
- {wxStyledTextCtrl_GetMaxLineState, "wxStyledTextCtrl", "getMaxLineState", 1}, // 3018
- {wxStyledTextCtrl_GetCaretLineVisible, "wxStyledTextCtrl", "getCaretLineVisible", 1}, // 3019
- {wxStyledTextCtrl_SetCaretLineVisible, "wxStyledTextCtrl", "setCaretLineVisible", 2}, // 3020
- {wxStyledTextCtrl_GetCaretLineBackground, "wxStyledTextCtrl", "getCaretLineBackground", 1}, // 3021
- {wxStyledTextCtrl_SetCaretLineBackground, "wxStyledTextCtrl", "setCaretLineBackground", 2}, // 3022
- {wxStyledTextCtrl_AutoCompShow, "wxStyledTextCtrl", "autoCompShow", 3}, // 3023
- {wxStyledTextCtrl_AutoCompCancel, "wxStyledTextCtrl", "autoCompCancel", 1}, // 3024
- {wxStyledTextCtrl_AutoCompActive, "wxStyledTextCtrl", "autoCompActive", 1}, // 3025
- {wxStyledTextCtrl_AutoCompPosStart, "wxStyledTextCtrl", "autoCompPosStart", 1}, // 3026
- {wxStyledTextCtrl_AutoCompComplete, "wxStyledTextCtrl", "autoCompComplete", 1}, // 3027
- {wxStyledTextCtrl_AutoCompStops, "wxStyledTextCtrl", "autoCompStops", 2}, // 3028
- {wxStyledTextCtrl_AutoCompSetSeparator, "wxStyledTextCtrl", "autoCompSetSeparator", 2}, // 3029
- {wxStyledTextCtrl_AutoCompGetSeparator, "wxStyledTextCtrl", "autoCompGetSeparator", 1}, // 3030
- {wxStyledTextCtrl_AutoCompSelect, "wxStyledTextCtrl", "autoCompSelect", 2}, // 3031
- {wxStyledTextCtrl_AutoCompSetCancelAtStart, "wxStyledTextCtrl", "autoCompSetCancelAtStart", 2}, // 3032
- {wxStyledTextCtrl_AutoCompGetCancelAtStart, "wxStyledTextCtrl", "autoCompGetCancelAtStart", 1}, // 3033
- {wxStyledTextCtrl_AutoCompSetFillUps, "wxStyledTextCtrl", "autoCompSetFillUps", 2}, // 3034
- {wxStyledTextCtrl_AutoCompSetChooseSingle, "wxStyledTextCtrl", "autoCompSetChooseSingle", 2}, // 3035
- {wxStyledTextCtrl_AutoCompGetChooseSingle, "wxStyledTextCtrl", "autoCompGetChooseSingle", 1}, // 3036
- {wxStyledTextCtrl_AutoCompSetIgnoreCase, "wxStyledTextCtrl", "autoCompSetIgnoreCase", 2}, // 3037
- {wxStyledTextCtrl_AutoCompGetIgnoreCase, "wxStyledTextCtrl", "autoCompGetIgnoreCase", 1}, // 3038
- {wxStyledTextCtrl_UserListShow, "wxStyledTextCtrl", "userListShow", 3}, // 3039
- {wxStyledTextCtrl_AutoCompSetAutoHide, "wxStyledTextCtrl", "autoCompSetAutoHide", 2}, // 3040
- {wxStyledTextCtrl_AutoCompGetAutoHide, "wxStyledTextCtrl", "autoCompGetAutoHide", 1}, // 3041
- {wxStyledTextCtrl_AutoCompSetDropRestOfWord, "wxStyledTextCtrl", "autoCompSetDropRestOfWord", 2}, // 3042
- {wxStyledTextCtrl_AutoCompGetDropRestOfWord, "wxStyledTextCtrl", "autoCompGetDropRestOfWord", 1}, // 3043
- {wxStyledTextCtrl_RegisterImage, "wxStyledTextCtrl", "registerImage", 3}, // 3044
- {wxStyledTextCtrl_ClearRegisteredImages, "wxStyledTextCtrl", "clearRegisteredImages", 1}, // 3045
- {wxStyledTextCtrl_AutoCompGetTypeSeparator, "wxStyledTextCtrl", "autoCompGetTypeSeparator", 1}, // 3046
- {wxStyledTextCtrl_AutoCompSetTypeSeparator, "wxStyledTextCtrl", "autoCompSetTypeSeparator", 2}, // 3047
- {wxStyledTextCtrl_AutoCompSetMaxWidth, "wxStyledTextCtrl", "autoCompSetMaxWidth", 2}, // 3048
- {wxStyledTextCtrl_AutoCompGetMaxWidth, "wxStyledTextCtrl", "autoCompGetMaxWidth", 1}, // 3049
- {wxStyledTextCtrl_AutoCompSetMaxHeight, "wxStyledTextCtrl", "autoCompSetMaxHeight", 2}, // 3050
- {wxStyledTextCtrl_AutoCompGetMaxHeight, "wxStyledTextCtrl", "autoCompGetMaxHeight", 1}, // 3051
- {wxStyledTextCtrl_SetIndent, "wxStyledTextCtrl", "setIndent", 2}, // 3052
- {wxStyledTextCtrl_GetIndent, "wxStyledTextCtrl", "getIndent", 1}, // 3053
- {wxStyledTextCtrl_SetUseTabs, "wxStyledTextCtrl", "setUseTabs", 2}, // 3054
- {wxStyledTextCtrl_GetUseTabs, "wxStyledTextCtrl", "getUseTabs", 1}, // 3055
- {wxStyledTextCtrl_SetLineIndentation, "wxStyledTextCtrl", "setLineIndentation", 3}, // 3056
- {wxStyledTextCtrl_GetLineIndentation, "wxStyledTextCtrl", "getLineIndentation", 2}, // 3057
- {wxStyledTextCtrl_GetLineIndentPosition, "wxStyledTextCtrl", "getLineIndentPosition", 2}, // 3058
- {wxStyledTextCtrl_GetColumn, "wxStyledTextCtrl", "getColumn", 2}, // 3059
- {wxStyledTextCtrl_SetUseHorizontalScrollBar, "wxStyledTextCtrl", "setUseHorizontalScrollBar", 2}, // 3060
- {wxStyledTextCtrl_GetUseHorizontalScrollBar, "wxStyledTextCtrl", "getUseHorizontalScrollBar", 1}, // 3061
- {wxStyledTextCtrl_SetIndentationGuides, "wxStyledTextCtrl", "setIndentationGuides", 2}, // 3062
- {wxStyledTextCtrl_GetIndentationGuides, "wxStyledTextCtrl", "getIndentationGuides", 1}, // 3063
- {wxStyledTextCtrl_SetHighlightGuide, "wxStyledTextCtrl", "setHighlightGuide", 2}, // 3064
- {wxStyledTextCtrl_GetHighlightGuide, "wxStyledTextCtrl", "getHighlightGuide", 1}, // 3065
- {wxStyledTextCtrl_GetLineEndPosition, "wxStyledTextCtrl", "getLineEndPosition", 2}, // 3066
- {wxStyledTextCtrl_GetCodePage, "wxStyledTextCtrl", "getCodePage", 1}, // 3067
- {wxStyledTextCtrl_GetCaretForeground, "wxStyledTextCtrl", "getCaretForeground", 1}, // 3068
- {wxStyledTextCtrl_GetReadOnly, "wxStyledTextCtrl", "getReadOnly", 1}, // 3069
- {wxStyledTextCtrl_SetCurrentPos, "wxStyledTextCtrl", "setCurrentPos", 2}, // 3070
- {wxStyledTextCtrl_SetSelectionStart, "wxStyledTextCtrl", "setSelectionStart", 2}, // 3071
- {wxStyledTextCtrl_GetSelectionStart, "wxStyledTextCtrl", "getSelectionStart", 1}, // 3072
- {wxStyledTextCtrl_SetSelectionEnd, "wxStyledTextCtrl", "setSelectionEnd", 2}, // 3073
- {wxStyledTextCtrl_GetSelectionEnd, "wxStyledTextCtrl", "getSelectionEnd", 1}, // 3074
- {wxStyledTextCtrl_SetPrintMagnification, "wxStyledTextCtrl", "setPrintMagnification", 2}, // 3075
- {wxStyledTextCtrl_GetPrintMagnification, "wxStyledTextCtrl", "getPrintMagnification", 1}, // 3076
- {wxStyledTextCtrl_SetPrintColourMode, "wxStyledTextCtrl", "setPrintColourMode", 2}, // 3077
- {wxStyledTextCtrl_GetPrintColourMode, "wxStyledTextCtrl", "getPrintColourMode", 1}, // 3078
- {wxStyledTextCtrl_FindText, "wxStyledTextCtrl", "findText", 5}, // 3079
- {wxStyledTextCtrl_FormatRange, "wxStyledTextCtrl", "formatRange", 8}, // 3080
- {wxStyledTextCtrl_GetFirstVisibleLine, "wxStyledTextCtrl", "getFirstVisibleLine", 1}, // 3081
- {wxStyledTextCtrl_GetLine, "wxStyledTextCtrl", "getLine", 2}, // 3082
- {wxStyledTextCtrl_GetLineCount, "wxStyledTextCtrl", "getLineCount", 1}, // 3083
- {wxStyledTextCtrl_SetMarginLeft, "wxStyledTextCtrl", "setMarginLeft", 2}, // 3084
- {wxStyledTextCtrl_GetMarginLeft, "wxStyledTextCtrl", "getMarginLeft", 1}, // 3085
- {wxStyledTextCtrl_SetMarginRight, "wxStyledTextCtrl", "setMarginRight", 2}, // 3086
- {wxStyledTextCtrl_GetMarginRight, "wxStyledTextCtrl", "getMarginRight", 1}, // 3087
- {wxStyledTextCtrl_GetModify, "wxStyledTextCtrl", "getModify", 1}, // 3088
- {wxStyledTextCtrl_SetSelection, "wxStyledTextCtrl", "setSelection", 3}, // 3089
- {wxStyledTextCtrl_GetSelectedText, "wxStyledTextCtrl", "getSelectedText", 1}, // 3090
- {wxStyledTextCtrl_GetTextRange, "wxStyledTextCtrl", "getTextRange", 3}, // 3091
- {wxStyledTextCtrl_HideSelection, "wxStyledTextCtrl", "hideSelection", 2}, // 3092
- {wxStyledTextCtrl_LineFromPosition, "wxStyledTextCtrl", "lineFromPosition", 2}, // 3093
- {wxStyledTextCtrl_PositionFromLine, "wxStyledTextCtrl", "positionFromLine", 2}, // 3094
- {wxStyledTextCtrl_LineScroll, "wxStyledTextCtrl", "lineScroll", 3}, // 3095
- {wxStyledTextCtrl_EnsureCaretVisible, "wxStyledTextCtrl", "ensureCaretVisible", 1}, // 3096
- {wxStyledTextCtrl_ReplaceSelection, "wxStyledTextCtrl", "replaceSelection", 2}, // 3097
- {wxStyledTextCtrl_SetReadOnly, "wxStyledTextCtrl", "setReadOnly", 2}, // 3098
- {wxStyledTextCtrl_CanPaste, "wxStyledTextCtrl", "canPaste", 1}, // 3099
- {wxStyledTextCtrl_CanUndo, "wxStyledTextCtrl", "canUndo", 1}, // 3100
- {wxStyledTextCtrl_EmptyUndoBuffer, "wxStyledTextCtrl", "emptyUndoBuffer", 1}, // 3101
- {wxStyledTextCtrl_Undo, "wxStyledTextCtrl", "undo", 1}, // 3102
- {wxStyledTextCtrl_Cut, "wxStyledTextCtrl", "cut", 1}, // 3103
- {wxStyledTextCtrl_Copy, "wxStyledTextCtrl", "copy", 1}, // 3104
- {wxStyledTextCtrl_Paste, "wxStyledTextCtrl", "paste", 1}, // 3105
- {wxStyledTextCtrl_Clear, "wxStyledTextCtrl", "clear", 1}, // 3106
- {wxStyledTextCtrl_SetText, "wxStyledTextCtrl", "setText", 2}, // 3107
- {wxStyledTextCtrl_GetText, "wxStyledTextCtrl", "getText", 1}, // 3108
- {wxStyledTextCtrl_GetTextLength, "wxStyledTextCtrl", "getTextLength", 1}, // 3109
- {wxStyledTextCtrl_GetOvertype, "wxStyledTextCtrl", "getOvertype", 1}, // 3110
- {wxStyledTextCtrl_SetCaretWidth, "wxStyledTextCtrl", "setCaretWidth", 2}, // 3111
- {wxStyledTextCtrl_GetCaretWidth, "wxStyledTextCtrl", "getCaretWidth", 1}, // 3112
- {wxStyledTextCtrl_SetTargetStart, "wxStyledTextCtrl", "setTargetStart", 2}, // 3113
- {wxStyledTextCtrl_GetTargetStart, "wxStyledTextCtrl", "getTargetStart", 1}, // 3114
- {wxStyledTextCtrl_SetTargetEnd, "wxStyledTextCtrl", "setTargetEnd", 2}, // 3115
- {wxStyledTextCtrl_GetTargetEnd, "wxStyledTextCtrl", "getTargetEnd", 1}, // 3116
- {wxStyledTextCtrl_ReplaceTarget, "wxStyledTextCtrl", "replaceTarget", 2}, // 3117
- {wxStyledTextCtrl_SearchInTarget, "wxStyledTextCtrl", "searchInTarget", 2}, // 3118
- {wxStyledTextCtrl_SetSearchFlags, "wxStyledTextCtrl", "setSearchFlags", 2}, // 3119
- {wxStyledTextCtrl_GetSearchFlags, "wxStyledTextCtrl", "getSearchFlags", 1}, // 3120
- {wxStyledTextCtrl_CallTipShow, "wxStyledTextCtrl", "callTipShow", 3}, // 3121
- {wxStyledTextCtrl_CallTipCancel, "wxStyledTextCtrl", "callTipCancel", 1}, // 3122
- {wxStyledTextCtrl_CallTipActive, "wxStyledTextCtrl", "callTipActive", 1}, // 3123
- {wxStyledTextCtrl_CallTipPosAtStart, "wxStyledTextCtrl", "callTipPosAtStart", 1}, // 3124
- {wxStyledTextCtrl_CallTipSetHighlight, "wxStyledTextCtrl", "callTipSetHighlight", 3}, // 3125
- {wxStyledTextCtrl_CallTipSetBackground, "wxStyledTextCtrl", "callTipSetBackground", 2}, // 3126
- {wxStyledTextCtrl_CallTipSetForeground, "wxStyledTextCtrl", "callTipSetForeground", 2}, // 3127
- {wxStyledTextCtrl_CallTipSetForegroundHighlight, "wxStyledTextCtrl", "callTipSetForegroundHighlight", 2}, // 3128
- {wxStyledTextCtrl_CallTipUseStyle, "wxStyledTextCtrl", "callTipUseStyle", 2}, // 3129
- {wxStyledTextCtrl_VisibleFromDocLine, "wxStyledTextCtrl", "visibleFromDocLine", 2}, // 3130
- {wxStyledTextCtrl_DocLineFromVisible, "wxStyledTextCtrl", "docLineFromVisible", 2}, // 3131
- {wxStyledTextCtrl_WrapCount, "wxStyledTextCtrl", "wrapCount", 2}, // 3132
- {wxStyledTextCtrl_SetFoldLevel, "wxStyledTextCtrl", "setFoldLevel", 3}, // 3133
- {wxStyledTextCtrl_GetFoldLevel, "wxStyledTextCtrl", "getFoldLevel", 2}, // 3134
- {wxStyledTextCtrl_GetLastChild, "wxStyledTextCtrl", "getLastChild", 3}, // 3135
- {wxStyledTextCtrl_GetFoldParent, "wxStyledTextCtrl", "getFoldParent", 2}, // 3136
- {wxStyledTextCtrl_ShowLines, "wxStyledTextCtrl", "showLines", 3}, // 3137
- {wxStyledTextCtrl_HideLines, "wxStyledTextCtrl", "hideLines", 3}, // 3138
- {wxStyledTextCtrl_GetLineVisible, "wxStyledTextCtrl", "getLineVisible", 2}, // 3139
- {wxStyledTextCtrl_SetFoldExpanded, "wxStyledTextCtrl", "setFoldExpanded", 3}, // 3140
- {wxStyledTextCtrl_GetFoldExpanded, "wxStyledTextCtrl", "getFoldExpanded", 2}, // 3141
- {wxStyledTextCtrl_ToggleFold, "wxStyledTextCtrl", "toggleFold", 2}, // 3142
- {wxStyledTextCtrl_EnsureVisible, "wxStyledTextCtrl", "ensureVisible", 2}, // 3143
- {wxStyledTextCtrl_SetFoldFlags, "wxStyledTextCtrl", "setFoldFlags", 2}, // 3144
- {wxStyledTextCtrl_EnsureVisibleEnforcePolicy, "wxStyledTextCtrl", "ensureVisibleEnforcePolicy", 2}, // 3145
- {wxStyledTextCtrl_SetTabIndents, "wxStyledTextCtrl", "setTabIndents", 2}, // 3146
- {wxStyledTextCtrl_GetTabIndents, "wxStyledTextCtrl", "getTabIndents", 1}, // 3147
- {wxStyledTextCtrl_SetBackSpaceUnIndents, "wxStyledTextCtrl", "setBackSpaceUnIndents", 2}, // 3148
- {wxStyledTextCtrl_GetBackSpaceUnIndents, "wxStyledTextCtrl", "getBackSpaceUnIndents", 1}, // 3149
- {wxStyledTextCtrl_SetMouseDwellTime, "wxStyledTextCtrl", "setMouseDwellTime", 2}, // 3150
- {wxStyledTextCtrl_GetMouseDwellTime, "wxStyledTextCtrl", "getMouseDwellTime", 1}, // 3151
- {wxStyledTextCtrl_WordStartPosition, "wxStyledTextCtrl", "wordStartPosition", 3}, // 3152
- {wxStyledTextCtrl_WordEndPosition, "wxStyledTextCtrl", "wordEndPosition", 3}, // 3153
- {wxStyledTextCtrl_SetWrapMode, "wxStyledTextCtrl", "setWrapMode", 2}, // 3154
- {wxStyledTextCtrl_GetWrapMode, "wxStyledTextCtrl", "getWrapMode", 1}, // 3155
- {wxStyledTextCtrl_SetWrapVisualFlags, "wxStyledTextCtrl", "setWrapVisualFlags", 2}, // 3156
- {wxStyledTextCtrl_GetWrapVisualFlags, "wxStyledTextCtrl", "getWrapVisualFlags", 1}, // 3157
- {wxStyledTextCtrl_SetWrapVisualFlagsLocation, "wxStyledTextCtrl", "setWrapVisualFlagsLocation", 2}, // 3158
- {wxStyledTextCtrl_GetWrapVisualFlagsLocation, "wxStyledTextCtrl", "getWrapVisualFlagsLocation", 1}, // 3159
- {wxStyledTextCtrl_SetWrapStartIndent, "wxStyledTextCtrl", "setWrapStartIndent", 2}, // 3160
- {wxStyledTextCtrl_GetWrapStartIndent, "wxStyledTextCtrl", "getWrapStartIndent", 1}, // 3161
- {wxStyledTextCtrl_SetLayoutCache, "wxStyledTextCtrl", "setLayoutCache", 2}, // 3162
- {wxStyledTextCtrl_GetLayoutCache, "wxStyledTextCtrl", "getLayoutCache", 1}, // 3163
- {wxStyledTextCtrl_SetScrollWidth, "wxStyledTextCtrl", "setScrollWidth", 2}, // 3164
- {wxStyledTextCtrl_GetScrollWidth, "wxStyledTextCtrl", "getScrollWidth", 1}, // 3165
- {wxStyledTextCtrl_TextWidth, "wxStyledTextCtrl", "textWidth", 3}, // 3166
- {wxStyledTextCtrl_GetEndAtLastLine, "wxStyledTextCtrl", "getEndAtLastLine", 1}, // 3167
- {wxStyledTextCtrl_TextHeight, "wxStyledTextCtrl", "textHeight", 2}, // 3168
- {wxStyledTextCtrl_SetUseVerticalScrollBar, "wxStyledTextCtrl", "setUseVerticalScrollBar", 2}, // 3169
- {wxStyledTextCtrl_GetUseVerticalScrollBar, "wxStyledTextCtrl", "getUseVerticalScrollBar", 1}, // 3170
- {wxStyledTextCtrl_AppendText, "wxStyledTextCtrl", "appendText", 2}, // 3171
- {wxStyledTextCtrl_GetTwoPhaseDraw, "wxStyledTextCtrl", "getTwoPhaseDraw", 1}, // 3172
- {wxStyledTextCtrl_SetTwoPhaseDraw, "wxStyledTextCtrl", "setTwoPhaseDraw", 2}, // 3173
- {wxStyledTextCtrl_TargetFromSelection, "wxStyledTextCtrl", "targetFromSelection", 1}, // 3174
- {wxStyledTextCtrl_LinesJoin, "wxStyledTextCtrl", "linesJoin", 1}, // 3175
- {wxStyledTextCtrl_LinesSplit, "wxStyledTextCtrl", "linesSplit", 2}, // 3176
- {wxStyledTextCtrl_SetFoldMarginColour, "wxStyledTextCtrl", "setFoldMarginColour", 3}, // 3177
- {wxStyledTextCtrl_SetFoldMarginHiColour, "wxStyledTextCtrl", "setFoldMarginHiColour", 3}, // 3178
- {wxStyledTextCtrl_LineDown, "wxStyledTextCtrl", "lineDown", 1}, // 3179
- {wxStyledTextCtrl_LineDownExtend, "wxStyledTextCtrl", "lineDownExtend", 1}, // 3180
- {wxStyledTextCtrl_LineUp, "wxStyledTextCtrl", "lineUp", 1}, // 3181
- {wxStyledTextCtrl_LineUpExtend, "wxStyledTextCtrl", "lineUpExtend", 1}, // 3182
- {wxStyledTextCtrl_CharLeft, "wxStyledTextCtrl", "charLeft", 1}, // 3183
- {wxStyledTextCtrl_CharLeftExtend, "wxStyledTextCtrl", "charLeftExtend", 1}, // 3184
- {wxStyledTextCtrl_CharRight, "wxStyledTextCtrl", "charRight", 1}, // 3185
- {wxStyledTextCtrl_CharRightExtend, "wxStyledTextCtrl", "charRightExtend", 1}, // 3186
- {wxStyledTextCtrl_WordLeft, "wxStyledTextCtrl", "wordLeft", 1}, // 3187
- {wxStyledTextCtrl_WordLeftExtend, "wxStyledTextCtrl", "wordLeftExtend", 1}, // 3188
- {wxStyledTextCtrl_WordRight, "wxStyledTextCtrl", "wordRight", 1}, // 3189
- {wxStyledTextCtrl_WordRightExtend, "wxStyledTextCtrl", "wordRightExtend", 1}, // 3190
- {wxStyledTextCtrl_Home, "wxStyledTextCtrl", "home", 1}, // 3191
- {wxStyledTextCtrl_HomeExtend, "wxStyledTextCtrl", "homeExtend", 1}, // 3192
- {wxStyledTextCtrl_LineEnd, "wxStyledTextCtrl", "lineEnd", 1}, // 3193
- {wxStyledTextCtrl_LineEndExtend, "wxStyledTextCtrl", "lineEndExtend", 1}, // 3194
- {wxStyledTextCtrl_DocumentStart, "wxStyledTextCtrl", "documentStart", 1}, // 3195
- {wxStyledTextCtrl_DocumentStartExtend, "wxStyledTextCtrl", "documentStartExtend", 1}, // 3196
- {wxStyledTextCtrl_DocumentEnd, "wxStyledTextCtrl", "documentEnd", 1}, // 3197
- {wxStyledTextCtrl_DocumentEndExtend, "wxStyledTextCtrl", "documentEndExtend", 1}, // 3198
- {wxStyledTextCtrl_PageUp, "wxStyledTextCtrl", "pageUp", 1}, // 3199
- {wxStyledTextCtrl_PageUpExtend, "wxStyledTextCtrl", "pageUpExtend", 1}, // 3200
- {wxStyledTextCtrl_PageDown, "wxStyledTextCtrl", "pageDown", 1}, // 3201
- {wxStyledTextCtrl_PageDownExtend, "wxStyledTextCtrl", "pageDownExtend", 1}, // 3202
- {wxStyledTextCtrl_EditToggleOvertype, "wxStyledTextCtrl", "editToggleOvertype", 1}, // 3203
- {wxStyledTextCtrl_Cancel, "wxStyledTextCtrl", "cancel", 1}, // 3204
- {wxStyledTextCtrl_DeleteBack, "wxStyledTextCtrl", "deleteBack", 1}, // 3205
- {wxStyledTextCtrl_Tab, "wxStyledTextCtrl", "tab", 1}, // 3206
- {wxStyledTextCtrl_BackTab, "wxStyledTextCtrl", "backTab", 1}, // 3207
- {wxStyledTextCtrl_NewLine, "wxStyledTextCtrl", "newLine", 1}, // 3208
- {wxStyledTextCtrl_FormFeed, "wxStyledTextCtrl", "formFeed", 1}, // 3209
- {wxStyledTextCtrl_VCHome, "wxStyledTextCtrl", "vCHome", 1}, // 3210
- {wxStyledTextCtrl_VCHomeExtend, "wxStyledTextCtrl", "vCHomeExtend", 1}, // 3211
- {wxStyledTextCtrl_ZoomIn, "wxStyledTextCtrl", "zoomIn", 1}, // 3212
- {wxStyledTextCtrl_ZoomOut, "wxStyledTextCtrl", "zoomOut", 1}, // 3213
- {wxStyledTextCtrl_DelWordLeft, "wxStyledTextCtrl", "delWordLeft", 1}, // 3214
- {wxStyledTextCtrl_DelWordRight, "wxStyledTextCtrl", "delWordRight", 1}, // 3215
- {wxStyledTextCtrl_LineCut, "wxStyledTextCtrl", "lineCut", 1}, // 3216
- {wxStyledTextCtrl_LineDelete, "wxStyledTextCtrl", "lineDelete", 1}, // 3217
- {wxStyledTextCtrl_LineTranspose, "wxStyledTextCtrl", "lineTranspose", 1}, // 3218
- {wxStyledTextCtrl_LineDuplicate, "wxStyledTextCtrl", "lineDuplicate", 1}, // 3219
- {wxStyledTextCtrl_LowerCase, "wxStyledTextCtrl", "lowerCase", 1}, // 3220
- {wxStyledTextCtrl_UpperCase, "wxStyledTextCtrl", "upperCase", 1}, // 3221
- {wxStyledTextCtrl_LineScrollDown, "wxStyledTextCtrl", "lineScrollDown", 1}, // 3222
- {wxStyledTextCtrl_LineScrollUp, "wxStyledTextCtrl", "lineScrollUp", 1}, // 3223
- {wxStyledTextCtrl_DeleteBackNotLine, "wxStyledTextCtrl", "deleteBackNotLine", 1}, // 3224
- {wxStyledTextCtrl_HomeDisplay, "wxStyledTextCtrl", "homeDisplay", 1}, // 3225
- {wxStyledTextCtrl_HomeDisplayExtend, "wxStyledTextCtrl", "homeDisplayExtend", 1}, // 3226
- {wxStyledTextCtrl_LineEndDisplay, "wxStyledTextCtrl", "lineEndDisplay", 1}, // 3227
- {wxStyledTextCtrl_LineEndDisplayExtend, "wxStyledTextCtrl", "lineEndDisplayExtend", 1}, // 3228
- {wxStyledTextCtrl_HomeWrapExtend, "wxStyledTextCtrl", "homeWrapExtend", 1}, // 3229
- {wxStyledTextCtrl_LineEndWrap, "wxStyledTextCtrl", "lineEndWrap", 1}, // 3230
- {wxStyledTextCtrl_LineEndWrapExtend, "wxStyledTextCtrl", "lineEndWrapExtend", 1}, // 3231
- {wxStyledTextCtrl_VCHomeWrap, "wxStyledTextCtrl", "vCHomeWrap", 1}, // 3232
- {wxStyledTextCtrl_VCHomeWrapExtend, "wxStyledTextCtrl", "vCHomeWrapExtend", 1}, // 3233
- {wxStyledTextCtrl_LineCopy, "wxStyledTextCtrl", "lineCopy", 1}, // 3234
- {wxStyledTextCtrl_MoveCaretInsideView, "wxStyledTextCtrl", "moveCaretInsideView", 1}, // 3235
- {wxStyledTextCtrl_LineLength, "wxStyledTextCtrl", "lineLength", 2}, // 3236
- {wxStyledTextCtrl_BraceHighlight, "wxStyledTextCtrl", "braceHighlight", 3}, // 3237
- {wxStyledTextCtrl_BraceBadLight, "wxStyledTextCtrl", "braceBadLight", 2}, // 3238
- {wxStyledTextCtrl_BraceMatch, "wxStyledTextCtrl", "braceMatch", 2}, // 3239
- {wxStyledTextCtrl_GetViewEOL, "wxStyledTextCtrl", "getViewEOL", 1}, // 3240
- {wxStyledTextCtrl_SetViewEOL, "wxStyledTextCtrl", "setViewEOL", 2}, // 3241
- {wxStyledTextCtrl_SetModEventMask, "wxStyledTextCtrl", "setModEventMask", 2}, // 3242
- {wxStyledTextCtrl_GetEdgeColumn, "wxStyledTextCtrl", "getEdgeColumn", 1}, // 3243
- {wxStyledTextCtrl_SetEdgeColumn, "wxStyledTextCtrl", "setEdgeColumn", 2}, // 3244
- {wxStyledTextCtrl_SetEdgeMode, "wxStyledTextCtrl", "setEdgeMode", 2}, // 3245
- {wxStyledTextCtrl_GetEdgeMode, "wxStyledTextCtrl", "getEdgeMode", 1}, // 3246
- {wxStyledTextCtrl_GetEdgeColour, "wxStyledTextCtrl", "getEdgeColour", 1}, // 3247
- {wxStyledTextCtrl_SetEdgeColour, "wxStyledTextCtrl", "setEdgeColour", 2}, // 3248
- {wxStyledTextCtrl_SearchAnchor, "wxStyledTextCtrl", "searchAnchor", 1}, // 3249
- {wxStyledTextCtrl_SearchNext, "wxStyledTextCtrl", "searchNext", 3}, // 3250
- {wxStyledTextCtrl_SearchPrev, "wxStyledTextCtrl", "searchPrev", 3}, // 3251
- {wxStyledTextCtrl_LinesOnScreen, "wxStyledTextCtrl", "linesOnScreen", 1}, // 3252
- {wxStyledTextCtrl_UsePopUp, "wxStyledTextCtrl", "usePopUp", 2}, // 3253
- {wxStyledTextCtrl_SelectionIsRectangle, "wxStyledTextCtrl", "selectionIsRectangle", 1}, // 3254
- {wxStyledTextCtrl_SetZoom, "wxStyledTextCtrl", "setZoom", 2}, // 3255
- {wxStyledTextCtrl_GetZoom, "wxStyledTextCtrl", "getZoom", 1}, // 3256
- {wxStyledTextCtrl_GetModEventMask, "wxStyledTextCtrl", "getModEventMask", 1}, // 3257
- {wxStyledTextCtrl_SetSTCFocus, "wxStyledTextCtrl", "setSTCFocus", 2}, // 3258
- {wxStyledTextCtrl_GetSTCFocus, "wxStyledTextCtrl", "getSTCFocus", 1}, // 3259
- {wxStyledTextCtrl_SetStatus, "wxStyledTextCtrl", "setStatus", 2}, // 3260
- {wxStyledTextCtrl_GetStatus, "wxStyledTextCtrl", "getStatus", 1}, // 3261
- {wxStyledTextCtrl_SetMouseDownCaptures, "wxStyledTextCtrl", "setMouseDownCaptures", 2}, // 3262
- {wxStyledTextCtrl_GetMouseDownCaptures, "wxStyledTextCtrl", "getMouseDownCaptures", 1}, // 3263
- {wxStyledTextCtrl_SetSTCCursor, "wxStyledTextCtrl", "setSTCCursor", 2}, // 3264
- {wxStyledTextCtrl_GetSTCCursor, "wxStyledTextCtrl", "getSTCCursor", 1}, // 3265
- {wxStyledTextCtrl_SetControlCharSymbol, "wxStyledTextCtrl", "setControlCharSymbol", 2}, // 3266
- {wxStyledTextCtrl_GetControlCharSymbol, "wxStyledTextCtrl", "getControlCharSymbol", 1}, // 3267
- {wxStyledTextCtrl_WordPartLeft, "wxStyledTextCtrl", "wordPartLeft", 1}, // 3268
- {wxStyledTextCtrl_WordPartLeftExtend, "wxStyledTextCtrl", "wordPartLeftExtend", 1}, // 3269
- {wxStyledTextCtrl_WordPartRight, "wxStyledTextCtrl", "wordPartRight", 1}, // 3270
- {wxStyledTextCtrl_WordPartRightExtend, "wxStyledTextCtrl", "wordPartRightExtend", 1}, // 3271
- {wxStyledTextCtrl_SetVisiblePolicy, "wxStyledTextCtrl", "setVisiblePolicy", 3}, // 3272
- {wxStyledTextCtrl_DelLineLeft, "wxStyledTextCtrl", "delLineLeft", 1}, // 3273
- {wxStyledTextCtrl_DelLineRight, "wxStyledTextCtrl", "delLineRight", 1}, // 3274
- {wxStyledTextCtrl_GetXOffset, "wxStyledTextCtrl", "getXOffset", 1}, // 3275
- {wxStyledTextCtrl_ChooseCaretX, "wxStyledTextCtrl", "chooseCaretX", 1}, // 3276
- {wxStyledTextCtrl_SetXCaretPolicy, "wxStyledTextCtrl", "setXCaretPolicy", 3}, // 3277
- {wxStyledTextCtrl_SetYCaretPolicy, "wxStyledTextCtrl", "setYCaretPolicy", 3}, // 3278
- {wxStyledTextCtrl_GetPrintWrapMode, "wxStyledTextCtrl", "getPrintWrapMode", 1}, // 3279
- {wxStyledTextCtrl_SetHotspotActiveForeground, "wxStyledTextCtrl", "setHotspotActiveForeground", 3}, // 3280
- {wxStyledTextCtrl_SetHotspotActiveBackground, "wxStyledTextCtrl", "setHotspotActiveBackground", 3}, // 3281
- {wxStyledTextCtrl_SetHotspotActiveUnderline, "wxStyledTextCtrl", "setHotspotActiveUnderline", 2}, // 3282
- {wxStyledTextCtrl_SetHotspotSingleLine, "wxStyledTextCtrl", "setHotspotSingleLine", 2}, // 3283
- {wxStyledTextCtrl_ParaDownExtend, "wxStyledTextCtrl", "paraDownExtend", 1}, // 3284
- {wxStyledTextCtrl_ParaUp, "wxStyledTextCtrl", "paraUp", 1}, // 3285
- {wxStyledTextCtrl_ParaUpExtend, "wxStyledTextCtrl", "paraUpExtend", 1}, // 3286
- {wxStyledTextCtrl_PositionBefore, "wxStyledTextCtrl", "positionBefore", 2}, // 3287
- {wxStyledTextCtrl_PositionAfter, "wxStyledTextCtrl", "positionAfter", 2}, // 3288
- {wxStyledTextCtrl_CopyRange, "wxStyledTextCtrl", "copyRange", 3}, // 3289
- {wxStyledTextCtrl_CopyText, "wxStyledTextCtrl", "copyText", 3}, // 3290
- {wxStyledTextCtrl_SetSelectionMode, "wxStyledTextCtrl", "setSelectionMode", 2}, // 3291
- {wxStyledTextCtrl_GetSelectionMode, "wxStyledTextCtrl", "getSelectionMode", 1}, // 3292
- {wxStyledTextCtrl_LineDownRectExtend, "wxStyledTextCtrl", "lineDownRectExtend", 1}, // 3293
- {wxStyledTextCtrl_LineUpRectExtend, "wxStyledTextCtrl", "lineUpRectExtend", 1}, // 3294
- {wxStyledTextCtrl_CharLeftRectExtend, "wxStyledTextCtrl", "charLeftRectExtend", 1}, // 3295
- {wxStyledTextCtrl_CharRightRectExtend, "wxStyledTextCtrl", "charRightRectExtend", 1}, // 3296
- {wxStyledTextCtrl_HomeRectExtend, "wxStyledTextCtrl", "homeRectExtend", 1}, // 3297
- {wxStyledTextCtrl_VCHomeRectExtend, "wxStyledTextCtrl", "vCHomeRectExtend", 1}, // 3298
- {wxStyledTextCtrl_LineEndRectExtend, "wxStyledTextCtrl", "lineEndRectExtend", 1}, // 3299
- {wxStyledTextCtrl_PageUpRectExtend, "wxStyledTextCtrl", "pageUpRectExtend", 1}, // 3300
- {wxStyledTextCtrl_PageDownRectExtend, "wxStyledTextCtrl", "pageDownRectExtend", 1}, // 3301
- {wxStyledTextCtrl_StutteredPageUp, "wxStyledTextCtrl", "stutteredPageUp", 1}, // 3302
- {wxStyledTextCtrl_StutteredPageUpExtend, "wxStyledTextCtrl", "stutteredPageUpExtend", 1}, // 3303
- {wxStyledTextCtrl_StutteredPageDown, "wxStyledTextCtrl", "stutteredPageDown", 1}, // 3304
- {wxStyledTextCtrl_StutteredPageDownExtend, "wxStyledTextCtrl", "stutteredPageDownExtend", 1}, // 3305
- {wxStyledTextCtrl_WordLeftEnd, "wxStyledTextCtrl", "wordLeftEnd", 1}, // 3306
- {wxStyledTextCtrl_WordLeftEndExtend, "wxStyledTextCtrl", "wordLeftEndExtend", 1}, // 3307
- {wxStyledTextCtrl_WordRightEnd, "wxStyledTextCtrl", "wordRightEnd", 1}, // 3308
- {wxStyledTextCtrl_WordRightEndExtend, "wxStyledTextCtrl", "wordRightEndExtend", 1}, // 3309
- {wxStyledTextCtrl_SetWhitespaceChars, "wxStyledTextCtrl", "setWhitespaceChars", 2}, // 3310
- {wxStyledTextCtrl_SetCharsDefault, "wxStyledTextCtrl", "setCharsDefault", 1}, // 3311
- {wxStyledTextCtrl_AutoCompGetCurrent, "wxStyledTextCtrl", "autoCompGetCurrent", 1}, // 3312
- {wxStyledTextCtrl_Allocate, "wxStyledTextCtrl", "allocate", 2}, // 3313
- {wxStyledTextCtrl_FindColumn, "wxStyledTextCtrl", "findColumn", 3}, // 3314
- {wxStyledTextCtrl_GetCaretSticky, "wxStyledTextCtrl", "getCaretSticky", 1}, // 3315
- {wxStyledTextCtrl_SetCaretSticky, "wxStyledTextCtrl", "setCaretSticky", 2}, // 3316
- {wxStyledTextCtrl_ToggleCaretSticky, "wxStyledTextCtrl", "toggleCaretSticky", 1}, // 3317
- {wxStyledTextCtrl_SetPasteConvertEndings, "wxStyledTextCtrl", "setPasteConvertEndings", 2}, // 3318
- {wxStyledTextCtrl_GetPasteConvertEndings, "wxStyledTextCtrl", "getPasteConvertEndings", 1}, // 3319
- {wxStyledTextCtrl_SelectionDuplicate, "wxStyledTextCtrl", "selectionDuplicate", 1}, // 3320
- {wxStyledTextCtrl_SetCaretLineBackAlpha, "wxStyledTextCtrl", "setCaretLineBackAlpha", 2}, // 3321
- {wxStyledTextCtrl_GetCaretLineBackAlpha, "wxStyledTextCtrl", "getCaretLineBackAlpha", 1}, // 3322
- {wxStyledTextCtrl_StartRecord, "wxStyledTextCtrl", "startRecord", 1}, // 3323
- {wxStyledTextCtrl_StopRecord, "wxStyledTextCtrl", "stopRecord", 1}, // 3324
- {wxStyledTextCtrl_SetLexer, "wxStyledTextCtrl", "setLexer", 2}, // 3325
- {wxStyledTextCtrl_GetLexer, "wxStyledTextCtrl", "getLexer", 1}, // 3326
- {wxStyledTextCtrl_Colourise, "wxStyledTextCtrl", "colourise", 3}, // 3327
- {wxStyledTextCtrl_SetProperty, "wxStyledTextCtrl", "setProperty", 3}, // 3328
- {wxStyledTextCtrl_SetKeyWords, "wxStyledTextCtrl", "setKeyWords", 3}, // 3329
- {wxStyledTextCtrl_SetLexerLanguage, "wxStyledTextCtrl", "setLexerLanguage", 2}, // 3330
- {wxStyledTextCtrl_GetProperty, "wxStyledTextCtrl", "getProperty", 2}, // 3331
- {wxStyledTextCtrl_GetStyleBitsNeeded, "wxStyledTextCtrl", "getStyleBitsNeeded", 1}, // 3332
- {wxStyledTextCtrl_GetCurrentLine, "wxStyledTextCtrl", "getCurrentLine", 1}, // 3333
- {wxStyledTextCtrl_StyleSetSpec, "wxStyledTextCtrl", "styleSetSpec", 3}, // 3334
- {wxStyledTextCtrl_StyleSetFont, "wxStyledTextCtrl", "styleSetFont", 3}, // 3335
- {wxStyledTextCtrl_StyleSetFontAttr, "wxStyledTextCtrl", "styleSetFontAttr", 8}, // 3336
- {wxStyledTextCtrl_StyleSetCharacterSet, "wxStyledTextCtrl", "styleSetCharacterSet", 3}, // 3337
- {wxStyledTextCtrl_StyleSetFontEncoding, "wxStyledTextCtrl", "styleSetFontEncoding", 3}, // 3338
- {wxStyledTextCtrl_CmdKeyExecute, "wxStyledTextCtrl", "cmdKeyExecute", 2}, // 3339
- {wxStyledTextCtrl_SetMargins, "wxStyledTextCtrl", "setMargins", 3}, // 3340
- {wxStyledTextCtrl_GetSelection, "wxStyledTextCtrl", "getSelection", 1}, // 3341
- {wxStyledTextCtrl_PointFromPosition, "wxStyledTextCtrl", "pointFromPosition", 2}, // 3342
- {wxStyledTextCtrl_ScrollToLine, "wxStyledTextCtrl", "scrollToLine", 2}, // 3343
- {wxStyledTextCtrl_ScrollToColumn, "wxStyledTextCtrl", "scrollToColumn", 2}, // 3344
- {wxStyledTextCtrl_SetVScrollBar, "wxStyledTextCtrl", "setVScrollBar", 2}, // 3345
- {wxStyledTextCtrl_SetHScrollBar, "wxStyledTextCtrl", "setHScrollBar", 2}, // 3346
- {wxStyledTextCtrl_GetLastKeydownProcessed, "wxStyledTextCtrl", "getLastKeydownProcessed", 1}, // 3347
- {wxStyledTextCtrl_SetLastKeydownProcessed, "wxStyledTextCtrl", "setLastKeydownProcessed", 2}, // 3348
- {wxStyledTextCtrl_SaveFile, "wxStyledTextCtrl", "saveFile", 2}, // 3349
- {wxStyledTextCtrl_LoadFile, "wxStyledTextCtrl", "loadFile", 2}, // 3350
- {wxStyledTextCtrl_DoDragOver, "wxStyledTextCtrl", "doDragOver", 4}, // 3351
- {wxStyledTextCtrl_DoDropText, "wxStyledTextCtrl", "doDropText", 4}, // 3352
- {wxStyledTextCtrl_GetUseAntiAliasing, "wxStyledTextCtrl", "getUseAntiAliasing", 1}, // 3353
- {wxStyledTextCtrl_AddTextRaw, "wxStyledTextCtrl", "addTextRaw", 3}, // 3354
- {wxStyledTextCtrl_InsertTextRaw, "wxStyledTextCtrl", "insertTextRaw", 3}, // 3355
- {wxStyledTextCtrl_GetCurLineRaw, "wxStyledTextCtrl", "getCurLineRaw", 1}, // 3356
- {wxStyledTextCtrl_GetLineRaw, "wxStyledTextCtrl", "getLineRaw", 2}, // 3357
- {wxStyledTextCtrl_GetSelectedTextRaw, "wxStyledTextCtrl", "getSelectedTextRaw", 1}, // 3358
- {wxStyledTextCtrl_GetTextRangeRaw, "wxStyledTextCtrl", "getTextRangeRaw", 3}, // 3359
- {wxStyledTextCtrl_SetTextRaw, "wxStyledTextCtrl", "setTextRaw", 2}, // 3360
- {wxStyledTextCtrl_GetTextRaw, "wxStyledTextCtrl", "getTextRaw", 1}, // 3361
- {wxStyledTextCtrl_AppendTextRaw, "wxStyledTextCtrl", "appendTextRaw", 3}, // 3362
- {wxArtProvider_GetBitmap, "wxArtProvider", "getBitmap", 2}, // 3363
- {wxArtProvider_GetIcon, "wxArtProvider", "getIcon", 2}, // 3364
- {wxTreeEvent_GetKeyCode, "wxTreeEvent", "getKeyCode", 1}, // 3365
- {wxTreeEvent_GetItem, "wxTreeEvent", "getItem", 1}, // 3366
- {wxTreeEvent_GetKeyEvent, "wxTreeEvent", "getKeyEvent", 1}, // 3367
- {wxTreeEvent_GetLabel, "wxTreeEvent", "getLabel", 1}, // 3368
- {wxTreeEvent_GetOldItem, "wxTreeEvent", "getOldItem", 1}, // 3369
- {wxTreeEvent_GetPoint, "wxTreeEvent", "getPoint", 1}, // 3370
- {wxTreeEvent_IsEditCancelled, "wxTreeEvent", "isEditCancelled", 1}, // 3371
- {wxTreeEvent_SetToolTip, "wxTreeEvent", "setToolTip", 2}, // 3372
- {wxBookCtrlEvent_GetOldSelection, "wxBookCtrlEvent", "getOldSelection", 1}, // 3373
- {wxBookCtrlEvent_GetSelection, "wxBookCtrlEvent", "getSelection", 1}, // 3374
- {wxBookCtrlEvent_SetOldSelection, "wxBookCtrlEvent", "setOldSelection", 2}, // 3375
- {wxBookCtrlEvent_SetSelection, "wxBookCtrlEvent", "setSelection", 2}, // 3376
- {wxFileDataObject_new, "wxFileDataObject", "new", 0}, // 3377
- {wxFileDataObject_AddFile, "wxFileDataObject", "addFile", 2}, // 3378
- {wxFileDataObject_GetFilenames, "wxFileDataObject", "getFilenames", 1}, // 3379
- {wxFileDataObject_destroy, "wxFileDataObject", "'Destroy'", 1}, // 3380
- {wxTextDataObject_new, "wxTextDataObject", "new", 1}, // 3381
- {wxTextDataObject_GetTextLength, "wxTextDataObject", "getTextLength", 1}, // 3382
- {wxTextDataObject_GetText, "wxTextDataObject", "getText", 1}, // 3383
- {wxTextDataObject_SetText, "wxTextDataObject", "setText", 2}, // 3384
- {wxTextDataObject_destroy, "wxTextDataObject", "'Destroy'", 1}, // 3385
- {wxBitmapDataObject_new_1_1, "wxBitmapDataObject", "new", 1}, // 3386
- {wxBitmapDataObject_new_1_0, "wxBitmapDataObject", "new", 1}, // 3387
- {wxBitmapDataObject_GetBitmap, "wxBitmapDataObject", "getBitmap", 1}, // 3388
- {wxBitmapDataObject_SetBitmap, "wxBitmapDataObject", "setBitmap", 2}, // 3389
- {wxBitmapDataObject_destroy, "wxBitmapDataObject", "'Destroy'", 1}, // 3390
- {wxClipboard_new, "wxClipboard", "new", 0}, // 3391
- {NULL, "wxClipboard", "destroy", 1}, // 3392 obj destructor wxClipboard_destruct
- {wxClipboard_AddData, "wxClipboard", "addData", 2}, // 3393
- {wxClipboard_Clear, "wxClipboard", "clear", 1}, // 3394
- {wxClipboard_Close, "wxClipboard", "close", 1}, // 3395
- {wxClipboard_Flush, "wxClipboard", "flush", 1}, // 3396
- {wxClipboard_GetData, "wxClipboard", "getData", 2}, // 3397
- {wxClipboard_IsOpened, "wxClipboard", "isOpened", 1}, // 3398
- {wxClipboard_Open, "wxClipboard", "open", 1}, // 3399
- {wxClipboard_SetData, "wxClipboard", "setData", 2}, // 3400
- {wxClipboard_UsePrimarySelection, "wxClipboard", "usePrimarySelection", 2}, // 3401
- {wxClipboard_IsSupported, "wxClipboard", "isSupported", 2}, // 3402
- {wxClipboard_Get, "wxClipboard", "get", 0}, // 3403
- {wxSpinEvent_GetPosition, "wxSpinEvent", "getPosition", 1}, // 3404
- {wxSpinEvent_SetPosition, "wxSpinEvent", "setPosition", 2}, // 3405
- {wxSplitterWindow_new_0, "wxSplitterWindow", "new", 0}, // 3406
- {wxSplitterWindow_new_2, "wxSplitterWindow", "new", 2}, // 3407
- {NULL, "wxSplitterWindow", "destroy", 1}, // 3408 obj destructor wxSplitterWindow_destruct
- {wxSplitterWindow_Create, "wxSplitterWindow", "create", 3}, // 3409
- {wxSplitterWindow_GetMinimumPaneSize, "wxSplitterWindow", "getMinimumPaneSize", 1}, // 3410
- {wxSplitterWindow_GetSashGravity, "wxSplitterWindow", "getSashGravity", 1}, // 3411
- {wxSplitterWindow_GetSashPosition, "wxSplitterWindow", "getSashPosition", 1}, // 3412
- {wxSplitterWindow_GetSplitMode, "wxSplitterWindow", "getSplitMode", 1}, // 3413
- {wxSplitterWindow_GetWindow1, "wxSplitterWindow", "getWindow1", 1}, // 3414
- {wxSplitterWindow_GetWindow2, "wxSplitterWindow", "getWindow2", 1}, // 3415
- {wxSplitterWindow_Initialize, "wxSplitterWindow", "initialize", 2}, // 3416
- {wxSplitterWindow_IsSplit, "wxSplitterWindow", "isSplit", 1}, // 3417
- {wxSplitterWindow_ReplaceWindow, "wxSplitterWindow", "replaceWindow", 3}, // 3418
- {wxSplitterWindow_SetSashGravity, "wxSplitterWindow", "setSashGravity", 2}, // 3419
- {wxSplitterWindow_SetSashPosition, "wxSplitterWindow", "setSashPosition", 3}, // 3420
- {wxSplitterWindow_SetMinimumPaneSize, "wxSplitterWindow", "setMinimumPaneSize", 2}, // 3421
- {wxSplitterWindow_SetSplitMode, "wxSplitterWindow", "setSplitMode", 2}, // 3422
- {wxSplitterWindow_SplitHorizontally, "wxSplitterWindow", "splitHorizontally", 4}, // 3423
- {wxSplitterWindow_SplitVertically, "wxSplitterWindow", "splitVertically", 4}, // 3424
- {wxSplitterWindow_Unsplit, "wxSplitterWindow", "unsplit", 2}, // 3425
- {wxSplitterWindow_UpdateSize, "wxSplitterWindow", "updateSize", 1}, // 3426
- {wxSplitterEvent_GetSashPosition, "wxSplitterEvent", "getSashPosition", 1}, // 3427
- {wxSplitterEvent_GetX, "wxSplitterEvent", "getX", 1}, // 3428
- {wxSplitterEvent_GetY, "wxSplitterEvent", "getY", 1}, // 3429
- {wxSplitterEvent_GetWindowBeingRemoved, "wxSplitterEvent", "getWindowBeingRemoved", 1}, // 3430
- {wxSplitterEvent_SetSashPosition, "wxSplitterEvent", "setSashPosition", 2}, // 3431
- {wxHtmlWindow_new_0, "wxHtmlWindow", "new", 0}, // 3432
- {wxHtmlWindow_new_2, "wxHtmlWindow", "new", 2}, // 3433
- {wxHtmlWindow_AppendToPage, "wxHtmlWindow", "appendToPage", 2}, // 3434
- {wxHtmlWindow_GetOpenedAnchor, "wxHtmlWindow", "getOpenedAnchor", 1}, // 3435
- {wxHtmlWindow_GetOpenedPage, "wxHtmlWindow", "getOpenedPage", 1}, // 3436
- {wxHtmlWindow_GetOpenedPageTitle, "wxHtmlWindow", "getOpenedPageTitle", 1}, // 3437
- {wxHtmlWindow_GetRelatedFrame, "wxHtmlWindow", "getRelatedFrame", 1}, // 3438
- {wxHtmlWindow_HistoryBack, "wxHtmlWindow", "historyBack", 1}, // 3439
- {wxHtmlWindow_HistoryCanBack, "wxHtmlWindow", "historyCanBack", 1}, // 3440
- {wxHtmlWindow_HistoryCanForward, "wxHtmlWindow", "historyCanForward", 1}, // 3441
- {wxHtmlWindow_HistoryClear, "wxHtmlWindow", "historyClear", 1}, // 3442
- {wxHtmlWindow_HistoryForward, "wxHtmlWindow", "historyForward", 1}, // 3443
- {wxHtmlWindow_LoadFile, "wxHtmlWindow", "loadFile", 2}, // 3444
- {wxHtmlWindow_LoadPage, "wxHtmlWindow", "loadPage", 2}, // 3445
- {wxHtmlWindow_SelectAll, "wxHtmlWindow", "selectAll", 1}, // 3446
- {wxHtmlWindow_SelectionToText, "wxHtmlWindow", "selectionToText", 1}, // 3447
- {wxHtmlWindow_SelectLine, "wxHtmlWindow", "selectLine", 2}, // 3448
- {wxHtmlWindow_SelectWord, "wxHtmlWindow", "selectWord", 2}, // 3449
- {wxHtmlWindow_SetBorders, "wxHtmlWindow", "setBorders", 2}, // 3450
- {wxHtmlWindow_SetFonts, "wxHtmlWindow", "setFonts", 4}, // 3451
- {wxHtmlWindow_SetPage, "wxHtmlWindow", "setPage", 2}, // 3452
- {wxHtmlWindow_SetRelatedFrame, "wxHtmlWindow", "setRelatedFrame", 3}, // 3453
- {wxHtmlWindow_SetRelatedStatusBar_1, "wxHtmlWindow", "setRelatedStatusBar", 2}, // 3454
- {wxHtmlWindow_SetRelatedStatusBar_2, "wxHtmlWindow", "setRelatedStatusBar", 3}, // 3455
- {wxHtmlWindow_ToText, "wxHtmlWindow", "toText", 1}, // 3456
- {NULL, "wxHtmlWindow", "'Destroy'", 1}, // 3457 obj destructor wxHtmlWindow_destroy
- {wxHtmlLinkEvent_GetLinkInfo, "wxHtmlLinkEvent", "getLinkInfo", 1}, // 3458
- {wxSystemSettings_GetColour, "wxSystemSettings", "getColour", 1}, // 3459
- {wxSystemSettings_GetFont, "wxSystemSettings", "getFont", 1}, // 3460
- {wxSystemSettings_GetMetric, "wxSystemSettings", "getMetric", 2}, // 3461
- {wxSystemSettings_GetScreenType, "wxSystemSettings", "getScreenType", 0}, // 3462
- {wxSystemOptions_GetOption, "wxSystemOptions", "getOption", 1}, // 3463
- {wxSystemOptions_GetOptionInt, "wxSystemOptions", "getOptionInt", 1}, // 3464
- {wxSystemOptions_HasOption, "wxSystemOptions", "hasOption", 1}, // 3465
- {wxSystemOptions_IsFalse, "wxSystemOptions", "isFalse", 1}, // 3466
- {wxSystemOptions_SetOption_2_1, "wxSystemOptions", "setOption", 2}, // 3467
- {wxSystemOptions_SetOption_2_0, "wxSystemOptions", "setOption", 2}, // 3468
- {wxAuiNotebookEvent_SetSelection, "wxAuiNotebookEvent", "setSelection", 2}, // 3469
- {wxAuiNotebookEvent_GetSelection, "wxAuiNotebookEvent", "getSelection", 1}, // 3470
- {wxAuiNotebookEvent_SetOldSelection, "wxAuiNotebookEvent", "setOldSelection", 2}, // 3471
- {wxAuiNotebookEvent_GetOldSelection, "wxAuiNotebookEvent", "getOldSelection", 1}, // 3472
- {wxAuiNotebookEvent_SetDragSource, "wxAuiNotebookEvent", "setDragSource", 2}, // 3473
- {wxAuiNotebookEvent_GetDragSource, "wxAuiNotebookEvent", "getDragSource", 1}, // 3474
- {wxAuiManagerEvent_SetManager, "wxAuiManagerEvent", "setManager", 2}, // 3475
- {wxAuiManagerEvent_GetManager, "wxAuiManagerEvent", "getManager", 1}, // 3476
- {wxAuiManagerEvent_SetPane, "wxAuiManagerEvent", "setPane", 2}, // 3477
- {wxAuiManagerEvent_GetPane, "wxAuiManagerEvent", "getPane", 1}, // 3478
- {wxAuiManagerEvent_SetButton, "wxAuiManagerEvent", "setButton", 2}, // 3479
- {wxAuiManagerEvent_GetButton, "wxAuiManagerEvent", "getButton", 1}, // 3480
- {wxAuiManagerEvent_SetDC, "wxAuiManagerEvent", "setDC", 2}, // 3481
- {wxAuiManagerEvent_GetDC, "wxAuiManagerEvent", "getDC", 1}, // 3482
- {wxAuiManagerEvent_Veto, "wxAuiManagerEvent", "veto", 2}, // 3483
- {wxAuiManagerEvent_GetVeto, "wxAuiManagerEvent", "getVeto", 1}, // 3484
- {wxAuiManagerEvent_SetCanVeto, "wxAuiManagerEvent", "setCanVeto", 2}, // 3485
- {wxAuiManagerEvent_CanVeto, "wxAuiManagerEvent", "canVeto", 1}, // 3486
- {wxLogNull_new, "wxLogNull", "new", 0}, // 3487
- {wxLogNull_destruct, "wxLogNull", "destroy", 1}, // 3488
- {wxTaskBarIcon_new, "wxTaskBarIcon", "new", 1}, // 3489
- {NULL, "wxTaskBarIcon", "destroy", 1}, // 3490 obj destructor wxTaskBarIcon_destruct
- {wxTaskBarIcon_PopupMenu, "wxTaskBarIcon", "popupMenu", 2}, // 3491
- {wxTaskBarIcon_RemoveIcon, "wxTaskBarIcon", "removeIcon", 1}, // 3492
- {wxTaskBarIcon_SetIcon, "wxTaskBarIcon", "setIcon", 3}, // 3493
- {wxLocale_new_0, "wxLocale", "new", 0}, // 3494
- {wxLocale_new_2_0, "wxLocale", "new", 2}, // 3495
- {wxLocale_new_2_1, "wxLocale", "new", 2}, // 3496
- {wxLocale_destruct, "wxLocale", "destroy", 1}, // 3497
- {wxLocale_Init_1, "wxLocale", "init", 2}, // 3498
- {wxLocale_Init_2, "wxLocale", "init", 3}, // 3499
- {wxLocale_AddCatalog_1, "wxLocale", "addCatalog", 2}, // 3500
- {wxLocale_AddCatalog_2, "wxLocale", "addCatalog", 3}, // 3501
- {wxLocale_AddCatalog_3, "wxLocale", "addCatalog", 4}, // 3502
- {wxLocale_AddCatalogLookupPathPrefix, "wxLocale", "addCatalogLookupPathPrefix", 1}, // 3503
- {wxLocale_GetCanonicalName, "wxLocale", "getCanonicalName", 1}, // 3504
- {wxLocale_GetLanguage, "wxLocale", "getLanguage", 1}, // 3505
- {wxLocale_GetLanguageName, "wxLocale", "getLanguageName", 1}, // 3506
- {wxLocale_GetLocale, "wxLocale", "getLocale", 1}, // 3507
- {wxLocale_GetName, "wxLocale", "getName", 1}, // 3508
- {wxLocale_GetString_2, "wxLocale", "getString", 3}, // 3509
- {wxLocale_GetString_4, "wxLocale", "getString", 5}, // 3510
- {wxLocale_GetHeaderValue, "wxLocale", "getHeaderValue", 3}, // 3511
- {wxLocale_GetSysName, "wxLocale", "getSysName", 1}, // 3512
- {wxLocale_GetSystemEncoding, "wxLocale", "getSystemEncoding", 0}, // 3513
- {wxLocale_GetSystemEncodingName, "wxLocale", "getSystemEncodingName", 0}, // 3514
- {wxLocale_GetSystemLanguage, "wxLocale", "getSystemLanguage", 0}, // 3515
- {wxLocale_IsLoaded, "wxLocale", "isLoaded", 2}, // 3516
- {wxLocale_IsOk, "wxLocale", "isOk", 1}, // 3517
- {wxActivateEvent_GetActive, "wxActivateEvent", "getActive", 1}, // 3518
+ {wxMDIParentFrame_new_0, "wxMDIParentFrame", "new", 0}, // 2648
+ {wxMDIParentFrame_new_4, "wxMDIParentFrame", "new", 4}, // 2649
+ {NULL, "wxMDIParentFrame", "destroy", 1}, // 2650 obj destructor wxMDIParentFrame_destruct
+ {wxMDIParentFrame_ActivateNext, "wxMDIParentFrame", "activateNext", 1}, // 2651
+ {wxMDIParentFrame_ActivatePrevious, "wxMDIParentFrame", "activatePrevious", 1}, // 2652
+ {wxMDIParentFrame_ArrangeIcons, "wxMDIParentFrame", "arrangeIcons", 1}, // 2653
+ {wxMDIParentFrame_Cascade, "wxMDIParentFrame", "cascade", 1}, // 2654
+ {wxMDIParentFrame_Create, "wxMDIParentFrame", "create", 5}, // 2655
+ {wxMDIParentFrame_GetActiveChild, "wxMDIParentFrame", "getActiveChild", 1}, // 2656
+ {wxMDIParentFrame_GetClientWindow, "wxMDIParentFrame", "getClientWindow", 1}, // 2657
+ {wxMDIParentFrame_Tile, "wxMDIParentFrame", "tile", 2}, // 2658
+ {wxMDIChildFrame_new_0, "wxMDIChildFrame", "new", 0}, // 2659
+ {wxMDIChildFrame_new_4, "wxMDIChildFrame", "new", 4}, // 2660
+ {NULL, "wxMDIChildFrame", "destroy", 1}, // 2661 obj destructor wxMDIChildFrame_destruct
+ {wxMDIChildFrame_Activate, "wxMDIChildFrame", "activate", 1}, // 2662
+ {wxMDIChildFrame_Create, "wxMDIChildFrame", "create", 5}, // 2663
+ {wxMDIChildFrame_Maximize, "wxMDIChildFrame", "maximize", 2}, // 2664
+ {wxMDIChildFrame_Restore, "wxMDIChildFrame", "restore", 1}, // 2665
+ {wxMDIClientWindow_new, "wxMDIClientWindow", "new", 0}, // 2666
+ {wxMDIClientWindow_CreateClient, "wxMDIClientWindow", "createClient", 3}, // 2667
+ {NULL, "wxMDIClientWindow", "'Destroy'", 1}, // 2668 obj destructor wxMDIClientWindow_destroy
+ {wxLayoutAlgorithm_new, "wxLayoutAlgorithm", "new", 0}, // 2669
+ {NULL, "wxLayoutAlgorithm", "destroy", 1}, // 2670 obj destructor wxLayoutAlgorithm_destruct
+ {wxLayoutAlgorithm_LayoutFrame, "wxLayoutAlgorithm", "layoutFrame", 3}, // 2671
+ {wxLayoutAlgorithm_LayoutMDIFrame, "wxLayoutAlgorithm", "layoutMDIFrame", 3}, // 2672
+ {wxLayoutAlgorithm_LayoutWindow, "wxLayoutAlgorithm", "layoutWindow", 3}, // 2673
+ {wxEvent_GetId, "wxEvent", "getId", 1}, // 2674
+ {wxEvent_GetSkipped, "wxEvent", "getSkipped", 1}, // 2675
+ {wxEvent_GetTimestamp, "wxEvent", "getTimestamp", 1}, // 2676
+ {wxEvent_IsCommandEvent, "wxEvent", "isCommandEvent", 1}, // 2677
+ {wxEvent_ResumePropagation, "wxEvent", "resumePropagation", 2}, // 2678
+ {wxEvent_ShouldPropagate, "wxEvent", "shouldPropagate", 1}, // 2679
+ {wxEvent_Skip, "wxEvent", "skip", 2}, // 2680
+ {wxEvent_StopPropagation, "wxEvent", "stopPropagation", 1}, // 2681
+ {wxCommandEvent_getClientData, "wxCommandEvent", "getClientData", 1}, // 2682
+ {wxCommandEvent_GetExtraLong, "wxCommandEvent", "getExtraLong", 1}, // 2683
+ {wxCommandEvent_GetInt, "wxCommandEvent", "getInt", 1}, // 2684
+ {wxCommandEvent_GetSelection, "wxCommandEvent", "getSelection", 1}, // 2685
+ {wxCommandEvent_GetString, "wxCommandEvent", "getString", 1}, // 2686
+ {wxCommandEvent_IsChecked, "wxCommandEvent", "isChecked", 1}, // 2687
+ {wxCommandEvent_IsSelection, "wxCommandEvent", "isSelection", 1}, // 2688
+ {wxCommandEvent_SetInt, "wxCommandEvent", "setInt", 2}, // 2689
+ {wxCommandEvent_SetString, "wxCommandEvent", "setString", 2}, // 2690
+ {wxScrollEvent_GetOrientation, "wxScrollEvent", "getOrientation", 1}, // 2691
+ {wxScrollEvent_GetPosition, "wxScrollEvent", "getPosition", 1}, // 2692
+ {wxScrollWinEvent_GetOrientation, "wxScrollWinEvent", "getOrientation", 1}, // 2693
+ {wxScrollWinEvent_GetPosition, "wxScrollWinEvent", "getPosition", 1}, // 2694
+ {wxMouseEvent_AltDown, "wxMouseEvent", "altDown", 1}, // 2695
+ {wxMouseEvent_Button, "wxMouseEvent", "button", 2}, // 2696
+ {wxMouseEvent_ButtonDClick, "wxMouseEvent", "buttonDClick", 2}, // 2697
+ {wxMouseEvent_ButtonDown, "wxMouseEvent", "buttonDown", 2}, // 2698
+ {wxMouseEvent_ButtonUp, "wxMouseEvent", "buttonUp", 2}, // 2699
+ {wxMouseEvent_CmdDown, "wxMouseEvent", "cmdDown", 1}, // 2700
+ {wxMouseEvent_ControlDown, "wxMouseEvent", "controlDown", 1}, // 2701
+ {wxMouseEvent_Dragging, "wxMouseEvent", "dragging", 1}, // 2702
+ {wxMouseEvent_Entering, "wxMouseEvent", "entering", 1}, // 2703
+ {wxMouseEvent_GetButton, "wxMouseEvent", "getButton", 1}, // 2704
+ {wxMouseEvent_GetPosition, "wxMouseEvent", "getPosition", 1}, // 2705
+ {NULL, "", "", 0}, // 2706
+ {wxMouseEvent_GetLogicalPosition, "wxMouseEvent", "getLogicalPosition", 2}, // 2707
+ {wxMouseEvent_GetLinesPerAction, "wxMouseEvent", "getLinesPerAction", 1}, // 2708
+ {wxMouseEvent_GetWheelRotation, "wxMouseEvent", "getWheelRotation", 1}, // 2709
+ {wxMouseEvent_GetWheelDelta, "wxMouseEvent", "getWheelDelta", 1}, // 2710
+ {wxMouseEvent_GetX, "wxMouseEvent", "getX", 1}, // 2711
+ {wxMouseEvent_GetY, "wxMouseEvent", "getY", 1}, // 2712
+ {wxMouseEvent_IsButton, "wxMouseEvent", "isButton", 1}, // 2713
+ {wxMouseEvent_IsPageScroll, "wxMouseEvent", "isPageScroll", 1}, // 2714
+ {wxMouseEvent_Leaving, "wxMouseEvent", "leaving", 1}, // 2715
+ {wxMouseEvent_LeftDClick, "wxMouseEvent", "leftDClick", 1}, // 2716
+ {wxMouseEvent_LeftDown, "wxMouseEvent", "leftDown", 1}, // 2717
+ {wxMouseEvent_LeftIsDown, "wxMouseEvent", "leftIsDown", 1}, // 2718
+ {wxMouseEvent_LeftUp, "wxMouseEvent", "leftUp", 1}, // 2719
+ {wxMouseEvent_MetaDown, "wxMouseEvent", "metaDown", 1}, // 2720
+ {wxMouseEvent_MiddleDClick, "wxMouseEvent", "middleDClick", 1}, // 2721
+ {wxMouseEvent_MiddleDown, "wxMouseEvent", "middleDown", 1}, // 2722
+ {wxMouseEvent_MiddleIsDown, "wxMouseEvent", "middleIsDown", 1}, // 2723
+ {wxMouseEvent_MiddleUp, "wxMouseEvent", "middleUp", 1}, // 2724
+ {wxMouseEvent_Moving, "wxMouseEvent", "moving", 1}, // 2725
+ {wxMouseEvent_RightDClick, "wxMouseEvent", "rightDClick", 1}, // 2726
+ {wxMouseEvent_RightDown, "wxMouseEvent", "rightDown", 1}, // 2727
+ {wxMouseEvent_RightIsDown, "wxMouseEvent", "rightIsDown", 1}, // 2728
+ {wxMouseEvent_RightUp, "wxMouseEvent", "rightUp", 1}, // 2729
+ {wxMouseEvent_ShiftDown, "wxMouseEvent", "shiftDown", 1}, // 2730
+ {wxMouseEvent_GetWheelAxis, "wxMouseEvent", "getWheelAxis", 1}, // 2731
+ {wxMouseEvent_Aux1DClick, "wxMouseEvent", "aux1DClick", 1}, // 2732
+ {wxMouseEvent_Aux1Down, "wxMouseEvent", "aux1Down", 1}, // 2733
+ {wxMouseEvent_Aux1Up, "wxMouseEvent", "aux1Up", 1}, // 2734
+ {wxMouseEvent_Aux2DClick, "wxMouseEvent", "aux2DClick", 1}, // 2735
+ {wxMouseEvent_Aux2Down, "wxMouseEvent", "aux2Down", 1}, // 2736
+ {wxMouseEvent_Aux2Up, "wxMouseEvent", "aux2Up", 1}, // 2737
+ {wxSetCursorEvent_GetCursor, "wxSetCursorEvent", "getCursor", 1}, // 2738
+ {wxSetCursorEvent_GetX, "wxSetCursorEvent", "getX", 1}, // 2739
+ {wxSetCursorEvent_GetY, "wxSetCursorEvent", "getY", 1}, // 2740
+ {wxSetCursorEvent_HasCursor, "wxSetCursorEvent", "hasCursor", 1}, // 2741
+ {wxSetCursorEvent_SetCursor, "wxSetCursorEvent", "setCursor", 2}, // 2742
+ {wxKeyEvent_AltDown, "wxKeyEvent", "altDown", 1}, // 2743
+ {wxKeyEvent_CmdDown, "wxKeyEvent", "cmdDown", 1}, // 2744
+ {wxKeyEvent_ControlDown, "wxKeyEvent", "controlDown", 1}, // 2745
+ {wxKeyEvent_GetKeyCode, "wxKeyEvent", "getKeyCode", 1}, // 2746
+ {wxKeyEvent_GetModifiers, "wxKeyEvent", "getModifiers", 1}, // 2747
+ {wxKeyEvent_GetPosition, "wxKeyEvent", "getPosition", 1}, // 2748
+ {NULL, "", "", 0}, // 2749
+ {wxKeyEvent_GetRawKeyCode, "wxKeyEvent", "getRawKeyCode", 1}, // 2750
+ {wxKeyEvent_GetRawKeyFlags, "wxKeyEvent", "getRawKeyFlags", 1}, // 2751
+ {wxKeyEvent_GetUnicodeKey, "wxKeyEvent", "getUnicodeKey", 1}, // 2752
+ {wxKeyEvent_GetX, "wxKeyEvent", "getX", 1}, // 2753
+ {wxKeyEvent_GetY, "wxKeyEvent", "getY", 1}, // 2754
+ {wxKeyEvent_HasModifiers, "wxKeyEvent", "hasModifiers", 1}, // 2755
+ {wxKeyEvent_MetaDown, "wxKeyEvent", "metaDown", 1}, // 2756
+ {wxKeyEvent_ShiftDown, "wxKeyEvent", "shiftDown", 1}, // 2757
+ {wxSizeEvent_GetSize, "wxSizeEvent", "getSize", 1}, // 2758
+ {wxSizeEvent_GetRect, "wxSizeEvent", "getRect", 1}, // 2759
+ {wxMoveEvent_GetPosition, "wxMoveEvent", "getPosition", 1}, // 2760
+ {wxMoveEvent_GetRect, "wxMoveEvent", "getRect", 1}, // 2761
+ {wxEraseEvent_GetDC, "wxEraseEvent", "getDC", 1}, // 2762
+ {wxFocusEvent_GetWindow, "wxFocusEvent", "getWindow", 1}, // 2763
+ {wxChildFocusEvent_GetWindow, "wxChildFocusEvent", "getWindow", 1}, // 2764
+ {wxMenuEvent_GetMenu, "wxMenuEvent", "getMenu", 1}, // 2765
+ {wxMenuEvent_GetMenuId, "wxMenuEvent", "getMenuId", 1}, // 2766
+ {wxMenuEvent_IsPopup, "wxMenuEvent", "isPopup", 1}, // 2767
+ {wxCloseEvent_CanVeto, "wxCloseEvent", "canVeto", 1}, // 2768
+ {wxCloseEvent_GetLoggingOff, "wxCloseEvent", "getLoggingOff", 1}, // 2769
+ {wxCloseEvent_SetCanVeto, "wxCloseEvent", "setCanVeto", 2}, // 2770
+ {wxCloseEvent_SetLoggingOff, "wxCloseEvent", "setLoggingOff", 2}, // 2771
+ {wxCloseEvent_Veto, "wxCloseEvent", "veto", 2}, // 2772
+ {wxShowEvent_SetShow, "wxShowEvent", "setShow", 2}, // 2773
+ {wxShowEvent_IsShown, "wxShowEvent", "isShown", 1}, // 2774
+ {wxIconizeEvent_IsIconized, "wxIconizeEvent", "isIconized", 1}, // 2775
+ {wxJoystickEvent_ButtonDown, "wxJoystickEvent", "buttonDown", 2}, // 2776
+ {wxJoystickEvent_ButtonIsDown, "wxJoystickEvent", "buttonIsDown", 2}, // 2777
+ {wxJoystickEvent_ButtonUp, "wxJoystickEvent", "buttonUp", 2}, // 2778
+ {wxJoystickEvent_GetButtonChange, "wxJoystickEvent", "getButtonChange", 1}, // 2779
+ {wxJoystickEvent_GetButtonState, "wxJoystickEvent", "getButtonState", 1}, // 2780
+ {wxJoystickEvent_GetJoystick, "wxJoystickEvent", "getJoystick", 1}, // 2781
+ {wxJoystickEvent_GetPosition, "wxJoystickEvent", "getPosition", 1}, // 2782
+ {wxJoystickEvent_GetZPosition, "wxJoystickEvent", "getZPosition", 1}, // 2783
+ {wxJoystickEvent_IsButton, "wxJoystickEvent", "isButton", 1}, // 2784
+ {wxJoystickEvent_IsMove, "wxJoystickEvent", "isMove", 1}, // 2785
+ {wxJoystickEvent_IsZMove, "wxJoystickEvent", "isZMove", 1}, // 2786
+ {wxUpdateUIEvent_CanUpdate, "wxUpdateUIEvent", "canUpdate", 1}, // 2787
+ {wxUpdateUIEvent_Check, "wxUpdateUIEvent", "check", 2}, // 2788
+ {wxUpdateUIEvent_Enable, "wxUpdateUIEvent", "enable", 2}, // 2789
+ {wxUpdateUIEvent_Show, "wxUpdateUIEvent", "show", 2}, // 2790
+ {wxUpdateUIEvent_GetChecked, "wxUpdateUIEvent", "getChecked", 1}, // 2791
+ {wxUpdateUIEvent_GetEnabled, "wxUpdateUIEvent", "getEnabled", 1}, // 2792
+ {wxUpdateUIEvent_GetShown, "wxUpdateUIEvent", "getShown", 1}, // 2793
+ {wxUpdateUIEvent_GetSetChecked, "wxUpdateUIEvent", "getSetChecked", 1}, // 2794
+ {wxUpdateUIEvent_GetSetEnabled, "wxUpdateUIEvent", "getSetEnabled", 1}, // 2795
+ {wxUpdateUIEvent_GetSetShown, "wxUpdateUIEvent", "getSetShown", 1}, // 2796
+ {wxUpdateUIEvent_GetSetText, "wxUpdateUIEvent", "getSetText", 1}, // 2797
+ {wxUpdateUIEvent_GetText, "wxUpdateUIEvent", "getText", 1}, // 2798
+ {wxUpdateUIEvent_GetMode, "wxUpdateUIEvent", "getMode", 0}, // 2799
+ {wxUpdateUIEvent_GetUpdateInterval, "wxUpdateUIEvent", "getUpdateInterval", 0}, // 2800
+ {wxUpdateUIEvent_ResetUpdateTime, "wxUpdateUIEvent", "resetUpdateTime", 0}, // 2801
+ {wxUpdateUIEvent_SetMode, "wxUpdateUIEvent", "setMode", 1}, // 2802
+ {wxUpdateUIEvent_SetText, "wxUpdateUIEvent", "setText", 2}, // 2803
+ {wxUpdateUIEvent_SetUpdateInterval, "wxUpdateUIEvent", "setUpdateInterval", 1}, // 2804
+ {wxMouseCaptureChangedEvent_GetCapturedWindow, "wxMouseCaptureChangedEvent", "getCapturedWindow", 1}, // 2805
+ {wxPaletteChangedEvent_SetChangedWindow, "wxPaletteChangedEvent", "setChangedWindow", 2}, // 2806
+ {wxPaletteChangedEvent_GetChangedWindow, "wxPaletteChangedEvent", "getChangedWindow", 1}, // 2807
+ {wxQueryNewPaletteEvent_SetPaletteRealized, "wxQueryNewPaletteEvent", "setPaletteRealized", 2}, // 2808
+ {wxQueryNewPaletteEvent_GetPaletteRealized, "wxQueryNewPaletteEvent", "getPaletteRealized", 1}, // 2809
+ {wxNavigationKeyEvent_GetDirection, "wxNavigationKeyEvent", "getDirection", 1}, // 2810
+ {wxNavigationKeyEvent_SetDirection, "wxNavigationKeyEvent", "setDirection", 2}, // 2811
+ {wxNavigationKeyEvent_IsWindowChange, "wxNavigationKeyEvent", "isWindowChange", 1}, // 2812
+ {wxNavigationKeyEvent_SetWindowChange, "wxNavigationKeyEvent", "setWindowChange", 2}, // 2813
+ {wxNavigationKeyEvent_IsFromTab, "wxNavigationKeyEvent", "isFromTab", 1}, // 2814
+ {wxNavigationKeyEvent_SetFromTab, "wxNavigationKeyEvent", "setFromTab", 2}, // 2815
+ {wxNavigationKeyEvent_GetCurrentFocus, "wxNavigationKeyEvent", "getCurrentFocus", 1}, // 2816
+ {wxNavigationKeyEvent_SetCurrentFocus, "wxNavigationKeyEvent", "setCurrentFocus", 2}, // 2817
+ {wxHelpEvent_GetOrigin, "wxHelpEvent", "getOrigin", 1}, // 2818
+ {wxHelpEvent_GetPosition, "wxHelpEvent", "getPosition", 1}, // 2819
+ {wxHelpEvent_SetOrigin, "wxHelpEvent", "setOrigin", 2}, // 2820
+ {wxHelpEvent_SetPosition, "wxHelpEvent", "setPosition", 2}, // 2821
+ {wxContextMenuEvent_GetPosition, "wxContextMenuEvent", "getPosition", 1}, // 2822
+ {wxContextMenuEvent_SetPosition, "wxContextMenuEvent", "setPosition", 2}, // 2823
+ {wxIdleEvent_GetMode, "wxIdleEvent", "getMode", 0}, // 2824
+ {wxIdleEvent_RequestMore, "wxIdleEvent", "requestMore", 2}, // 2825
+ {wxIdleEvent_MoreRequested, "wxIdleEvent", "moreRequested", 1}, // 2826
+ {wxIdleEvent_SetMode, "wxIdleEvent", "setMode", 1}, // 2827
+ {wxGridEvent_AltDown, "wxGridEvent", "altDown", 1}, // 2828
+ {wxGridEvent_ControlDown, "wxGridEvent", "controlDown", 1}, // 2829
+ {wxGridEvent_GetCol, "wxGridEvent", "getCol", 1}, // 2830
+ {wxGridEvent_GetPosition, "wxGridEvent", "getPosition", 1}, // 2831
+ {wxGridEvent_GetRow, "wxGridEvent", "getRow", 1}, // 2832
+ {wxGridEvent_MetaDown, "wxGridEvent", "metaDown", 1}, // 2833
+ {wxGridEvent_Selecting, "wxGridEvent", "selecting", 1}, // 2834
+ {wxGridEvent_ShiftDown, "wxGridEvent", "shiftDown", 1}, // 2835
+ {wxNotifyEvent_Allow, "wxNotifyEvent", "allow", 1}, // 2836
+ {wxNotifyEvent_IsAllowed, "wxNotifyEvent", "isAllowed", 1}, // 2837
+ {wxNotifyEvent_Veto, "wxNotifyEvent", "veto", 1}, // 2838
+ {wxSashEvent_GetEdge, "wxSashEvent", "getEdge", 1}, // 2839
+ {wxSashEvent_GetDragRect, "wxSashEvent", "getDragRect", 1}, // 2840
+ {wxSashEvent_GetDragStatus, "wxSashEvent", "getDragStatus", 1}, // 2841
+ {wxListEvent_GetCacheFrom, "wxListEvent", "getCacheFrom", 1}, // 2842
+ {wxListEvent_GetCacheTo, "wxListEvent", "getCacheTo", 1}, // 2843
+ {wxListEvent_GetKeyCode, "wxListEvent", "getKeyCode", 1}, // 2844
+ {wxListEvent_GetIndex, "wxListEvent", "getIndex", 1}, // 2845
+ {wxListEvent_GetColumn, "wxListEvent", "getColumn", 1}, // 2846
+ {wxListEvent_GetPoint, "wxListEvent", "getPoint", 1}, // 2847
+ {wxListEvent_GetLabel, "wxListEvent", "getLabel", 1}, // 2848
+ {wxListEvent_GetText, "wxListEvent", "getText", 1}, // 2849
+ {wxListEvent_GetImage, "wxListEvent", "getImage", 1}, // 2850
+ {wxListEvent_GetData, "wxListEvent", "getData", 1}, // 2851
+ {wxListEvent_GetMask, "wxListEvent", "getMask", 1}, // 2852
+ {wxListEvent_GetItem, "wxListEvent", "getItem", 1}, // 2853
+ {wxListEvent_IsEditCancelled, "wxListEvent", "isEditCancelled", 1}, // 2854
+ {wxDateEvent_GetDate, "wxDateEvent", "getDate", 1}, // 2855
+ {wxCalendarEvent_GetWeekDay, "wxCalendarEvent", "getWeekDay", 1}, // 2856
+ {wxCalendarEvent_GetDate, "wxCalendarEvent", "getDate", 1}, // 2857
+ {wxFileDirPickerEvent_GetPath, "wxFileDirPickerEvent", "getPath", 1}, // 2858
+ {wxColourPickerEvent_GetColour, "wxColourPickerEvent", "getColour", 1}, // 2859
+ {wxFontPickerEvent_GetFont, "wxFontPickerEvent", "getFont", 1}, // 2860
+ {wxStyledTextEvent_GetPosition, "wxStyledTextEvent", "getPosition", 1}, // 2861
+ {wxStyledTextEvent_GetKey, "wxStyledTextEvent", "getKey", 1}, // 2862
+ {wxStyledTextEvent_GetModifiers, "wxStyledTextEvent", "getModifiers", 1}, // 2863
+ {wxStyledTextEvent_GetModificationType, "wxStyledTextEvent", "getModificationType", 1}, // 2864
+ {wxStyledTextEvent_GetText, "wxStyledTextEvent", "getText", 1}, // 2865
+ {wxStyledTextEvent_GetLength, "wxStyledTextEvent", "getLength", 1}, // 2866
+ {wxStyledTextEvent_GetLinesAdded, "wxStyledTextEvent", "getLinesAdded", 1}, // 2867
+ {wxStyledTextEvent_GetLine, "wxStyledTextEvent", "getLine", 1}, // 2868
+ {wxStyledTextEvent_GetFoldLevelNow, "wxStyledTextEvent", "getFoldLevelNow", 1}, // 2869
+ {wxStyledTextEvent_GetFoldLevelPrev, "wxStyledTextEvent", "getFoldLevelPrev", 1}, // 2870
+ {wxStyledTextEvent_GetMargin, "wxStyledTextEvent", "getMargin", 1}, // 2871
+ {wxStyledTextEvent_GetMessage, "wxStyledTextEvent", "getMessage", 1}, // 2872
+ {wxStyledTextEvent_GetWParam, "wxStyledTextEvent", "getWParam", 1}, // 2873
+ {wxStyledTextEvent_GetLParam, "wxStyledTextEvent", "getLParam", 1}, // 2874
+ {wxStyledTextEvent_GetListType, "wxStyledTextEvent", "getListType", 1}, // 2875
+ {wxStyledTextEvent_GetX, "wxStyledTextEvent", "getX", 1}, // 2876
+ {wxStyledTextEvent_GetY, "wxStyledTextEvent", "getY", 1}, // 2877
+ {wxStyledTextEvent_GetDragText, "wxStyledTextEvent", "getDragText", 1}, // 2878
+ {wxStyledTextEvent_GetDragAllowMove, "wxStyledTextEvent", "getDragAllowMove", 1}, // 2879
+ {wxStyledTextEvent_GetDragResult, "wxStyledTextEvent", "getDragResult", 1}, // 2880
+ {wxStyledTextEvent_GetShift, "wxStyledTextEvent", "getShift", 1}, // 2881
+ {wxStyledTextEvent_GetControl, "wxStyledTextEvent", "getControl", 1}, // 2882
+ {wxStyledTextEvent_GetAlt, "wxStyledTextEvent", "getAlt", 1}, // 2883
+ {utils_wxGetKeyState, "utils", "getKeyState", 1}, // 2884
+ {utils_wxGetMousePosition, "utils", "getMousePosition", 0}, // 2885
+ {utils_wxGetMouseState, "utils", "getMouseState", 0}, // 2886
+ {utils_wxSetDetectableAutoRepeat, "utils", "setDetectableAutoRepeat", 1}, // 2887
+ {utils_wxBell, "utils", "bell", 0}, // 2888
+ {utils_wxFindMenuItemId, "utils", "findMenuItemId", 3}, // 2889
+ {utils_wxFindWindowAtPoint, "utils", "findWindowAtPoint", 1}, // 2890
+ {utils_wxBeginBusyCursor, "utils", "beginBusyCursor", 1}, // 2891
+ {utils_wxEndBusyCursor, "utils", "endBusyCursor", 0}, // 2892
+ {utils_wxIsBusy, "utils", "isBusy", 0}, // 2893
+ {utils_wxShutdown, "utils", "shutdown", 1}, // 2894
+ {utils_wxShell, "utils", "shell", 1}, // 2895
+ {utils_wxLaunchDefaultBrowser, "utils", "launchDefaultBrowser", 2}, // 2896
+ {utils_wxGetEmailAddress, "utils", "getEmailAddress", 0}, // 2897
+ {utils_wxGetUserId, "utils", "getUserId", 0}, // 2898
+ {utils_wxGetHomeDir, "utils", "getHomeDir", 0}, // 2899
+ {utils_wxNewId, "utils", "newId", 0}, // 2900
+ {utils_wxRegisterId, "utils", "registerId", 1}, // 2901
+ {utils_wxGetCurrentId, "utils", "getCurrentId", 0}, // 2902
+ {utils_wxGetOsDescription, "utils", "getOsDescription", 0}, // 2903
+ {utils_wxIsPlatformLittleEndian, "utils", "isPlatformLittleEndian", 0}, // 2904
+ {utils_wxIsPlatform64Bit, "utils", "isPlatform64Bit", 0}, // 2905
+ {gdicmn_wxDisplaySize, "gdicmn", "displaySize", 0}, // 2906
+ {gdicmn_wxSetCursor, "gdicmn", "setCursor", 1}, // 2907
+ {wxPrintout_new, "wxPrintout", "new", 3}, // 2908
+ {NULL, "wxPrintout", "destroy", 1}, // 2909 obj destructor wxPrintout_destruct
+ {wxPrintout_GetDC, "wxPrintout", "getDC", 1}, // 2910
+ {wxPrintout_GetPageSizeMM, "wxPrintout", "getPageSizeMM", 1}, // 2911
+ {wxPrintout_GetPageSizePixels, "wxPrintout", "getPageSizePixels", 1}, // 2912
+ {wxPrintout_GetPaperRectPixels, "wxPrintout", "getPaperRectPixels", 1}, // 2913
+ {wxPrintout_GetPPIPrinter, "wxPrintout", "getPPIPrinter", 1}, // 2914
+ {wxPrintout_GetPPIScreen, "wxPrintout", "getPPIScreen", 1}, // 2915
+ {wxPrintout_GetTitle, "wxPrintout", "getTitle", 1}, // 2916
+ {wxPrintout_IsPreview, "wxPrintout", "isPreview", 1}, // 2917
+ {wxPrintout_FitThisSizeToPaper, "wxPrintout", "fitThisSizeToPaper", 2}, // 2918
+ {wxPrintout_FitThisSizeToPage, "wxPrintout", "fitThisSizeToPage", 2}, // 2919
+ {wxPrintout_FitThisSizeToPageMargins, "wxPrintout", "fitThisSizeToPageMargins", 3}, // 2920
+ {wxPrintout_MapScreenSizeToPaper, "wxPrintout", "mapScreenSizeToPaper", 1}, // 2921
+ {wxPrintout_MapScreenSizeToPage, "wxPrintout", "mapScreenSizeToPage", 1}, // 2922
+ {wxPrintout_MapScreenSizeToPageMargins, "wxPrintout", "mapScreenSizeToPageMargins", 2}, // 2923
+ {wxPrintout_MapScreenSizeToDevice, "wxPrintout", "mapScreenSizeToDevice", 1}, // 2924
+ {wxPrintout_GetLogicalPaperRect, "wxPrintout", "getLogicalPaperRect", 1}, // 2925
+ {wxPrintout_GetLogicalPageRect, "wxPrintout", "getLogicalPageRect", 1}, // 2926
+ {wxPrintout_GetLogicalPageMarginsRect, "wxPrintout", "getLogicalPageMarginsRect", 2}, // 2927
+ {wxPrintout_SetLogicalOrigin, "wxPrintout", "setLogicalOrigin", 3}, // 2928
+ {wxPrintout_OffsetLogicalOrigin, "wxPrintout", "offsetLogicalOrigin", 3}, // 2929
+ {wxStyledTextCtrl_new_2, "wxStyledTextCtrl", "new", 2}, // 2930
+ {wxStyledTextCtrl_new_0, "wxStyledTextCtrl", "new", 0}, // 2931
+ {NULL, "wxStyledTextCtrl", "destroy", 1}, // 2932 obj destructor wxStyledTextCtrl_destruct
+ {wxStyledTextCtrl_Create, "wxStyledTextCtrl", "create", 3}, // 2933
+ {wxStyledTextCtrl_AddText, "wxStyledTextCtrl", "addText", 2}, // 2934
+ {wxStyledTextCtrl_InsertText, "wxStyledTextCtrl", "insertText", 3}, // 2935
+ {wxStyledTextCtrl_ClearAll, "wxStyledTextCtrl", "clearAll", 1}, // 2936
+ {wxStyledTextCtrl_ClearDocumentStyle, "wxStyledTextCtrl", "clearDocumentStyle", 1}, // 2937
+ {wxStyledTextCtrl_GetLength, "wxStyledTextCtrl", "getLength", 1}, // 2938
+ {wxStyledTextCtrl_GetCharAt, "wxStyledTextCtrl", "getCharAt", 2}, // 2939
+ {wxStyledTextCtrl_GetCurrentPos, "wxStyledTextCtrl", "getCurrentPos", 1}, // 2940
+ {wxStyledTextCtrl_GetAnchor, "wxStyledTextCtrl", "getAnchor", 1}, // 2941
+ {wxStyledTextCtrl_GetStyleAt, "wxStyledTextCtrl", "getStyleAt", 2}, // 2942
+ {wxStyledTextCtrl_Redo, "wxStyledTextCtrl", "redo", 1}, // 2943
+ {wxStyledTextCtrl_SetUndoCollection, "wxStyledTextCtrl", "setUndoCollection", 2}, // 2944
+ {wxStyledTextCtrl_SelectAll, "wxStyledTextCtrl", "selectAll", 1}, // 2945
+ {wxStyledTextCtrl_SetSavePoint, "wxStyledTextCtrl", "setSavePoint", 1}, // 2946
+ {wxStyledTextCtrl_CanRedo, "wxStyledTextCtrl", "canRedo", 1}, // 2947
+ {wxStyledTextCtrl_MarkerLineFromHandle, "wxStyledTextCtrl", "markerLineFromHandle", 2}, // 2948
+ {wxStyledTextCtrl_MarkerDeleteHandle, "wxStyledTextCtrl", "markerDeleteHandle", 2}, // 2949
+ {wxStyledTextCtrl_GetUndoCollection, "wxStyledTextCtrl", "getUndoCollection", 1}, // 2950
+ {wxStyledTextCtrl_GetViewWhiteSpace, "wxStyledTextCtrl", "getViewWhiteSpace", 1}, // 2951
+ {wxStyledTextCtrl_SetViewWhiteSpace, "wxStyledTextCtrl", "setViewWhiteSpace", 2}, // 2952
+ {wxStyledTextCtrl_PositionFromPoint, "wxStyledTextCtrl", "positionFromPoint", 2}, // 2953
+ {wxStyledTextCtrl_PositionFromPointClose, "wxStyledTextCtrl", "positionFromPointClose", 3}, // 2954
+ {wxStyledTextCtrl_GotoLine, "wxStyledTextCtrl", "gotoLine", 2}, // 2955
+ {wxStyledTextCtrl_GotoPos, "wxStyledTextCtrl", "gotoPos", 2}, // 2956
+ {wxStyledTextCtrl_SetAnchor, "wxStyledTextCtrl", "setAnchor", 2}, // 2957
+ {wxStyledTextCtrl_GetCurLine, "wxStyledTextCtrl", "getCurLine", 1}, // 2958
+ {wxStyledTextCtrl_GetEndStyled, "wxStyledTextCtrl", "getEndStyled", 1}, // 2959
+ {wxStyledTextCtrl_ConvertEOLs, "wxStyledTextCtrl", "convertEOLs", 2}, // 2960
+ {wxStyledTextCtrl_GetEOLMode, "wxStyledTextCtrl", "getEOLMode", 1}, // 2961
+ {wxStyledTextCtrl_SetEOLMode, "wxStyledTextCtrl", "setEOLMode", 2}, // 2962
+ {wxStyledTextCtrl_StartStyling, "wxStyledTextCtrl", "startStyling", 2}, // 2963
+ {wxStyledTextCtrl_SetStyling, "wxStyledTextCtrl", "setStyling", 3}, // 2964
+ {wxStyledTextCtrl_GetBufferedDraw, "wxStyledTextCtrl", "getBufferedDraw", 1}, // 2965
+ {wxStyledTextCtrl_SetBufferedDraw, "wxStyledTextCtrl", "setBufferedDraw", 2}, // 2966
+ {wxStyledTextCtrl_SetTabWidth, "wxStyledTextCtrl", "setTabWidth", 2}, // 2967
+ {wxStyledTextCtrl_GetTabWidth, "wxStyledTextCtrl", "getTabWidth", 1}, // 2968
+ {wxStyledTextCtrl_SetCodePage, "wxStyledTextCtrl", "setCodePage", 2}, // 2969
+ {wxStyledTextCtrl_MarkerDefine, "wxStyledTextCtrl", "markerDefine", 4}, // 2970
+ {wxStyledTextCtrl_MarkerSetForeground, "wxStyledTextCtrl", "markerSetForeground", 3}, // 2971
+ {wxStyledTextCtrl_MarkerSetBackground, "wxStyledTextCtrl", "markerSetBackground", 3}, // 2972
+ {wxStyledTextCtrl_MarkerAdd, "wxStyledTextCtrl", "markerAdd", 3}, // 2973
+ {wxStyledTextCtrl_MarkerDelete, "wxStyledTextCtrl", "markerDelete", 3}, // 2974
+ {wxStyledTextCtrl_MarkerDeleteAll, "wxStyledTextCtrl", "markerDeleteAll", 2}, // 2975
+ {wxStyledTextCtrl_MarkerGet, "wxStyledTextCtrl", "markerGet", 2}, // 2976
+ {wxStyledTextCtrl_MarkerNext, "wxStyledTextCtrl", "markerNext", 3}, // 2977
+ {wxStyledTextCtrl_MarkerPrevious, "wxStyledTextCtrl", "markerPrevious", 3}, // 2978
+ {wxStyledTextCtrl_MarkerDefineBitmap, "wxStyledTextCtrl", "markerDefineBitmap", 3}, // 2979
+ {wxStyledTextCtrl_MarkerAddSet, "wxStyledTextCtrl", "markerAddSet", 3}, // 2980
+ {wxStyledTextCtrl_MarkerSetAlpha, "wxStyledTextCtrl", "markerSetAlpha", 3}, // 2981
+ {wxStyledTextCtrl_SetMarginType, "wxStyledTextCtrl", "setMarginType", 3}, // 2982
+ {wxStyledTextCtrl_GetMarginType, "wxStyledTextCtrl", "getMarginType", 2}, // 2983
+ {wxStyledTextCtrl_SetMarginWidth, "wxStyledTextCtrl", "setMarginWidth", 3}, // 2984
+ {wxStyledTextCtrl_GetMarginWidth, "wxStyledTextCtrl", "getMarginWidth", 2}, // 2985
+ {wxStyledTextCtrl_SetMarginMask, "wxStyledTextCtrl", "setMarginMask", 3}, // 2986
+ {wxStyledTextCtrl_GetMarginMask, "wxStyledTextCtrl", "getMarginMask", 2}, // 2987
+ {wxStyledTextCtrl_SetMarginSensitive, "wxStyledTextCtrl", "setMarginSensitive", 3}, // 2988
+ {wxStyledTextCtrl_GetMarginSensitive, "wxStyledTextCtrl", "getMarginSensitive", 2}, // 2989
+ {wxStyledTextCtrl_StyleClearAll, "wxStyledTextCtrl", "styleClearAll", 1}, // 2990
+ {wxStyledTextCtrl_StyleSetForeground, "wxStyledTextCtrl", "styleSetForeground", 3}, // 2991
+ {wxStyledTextCtrl_StyleSetBackground, "wxStyledTextCtrl", "styleSetBackground", 3}, // 2992
+ {wxStyledTextCtrl_StyleSetBold, "wxStyledTextCtrl", "styleSetBold", 3}, // 2993
+ {wxStyledTextCtrl_StyleSetItalic, "wxStyledTextCtrl", "styleSetItalic", 3}, // 2994
+ {wxStyledTextCtrl_StyleSetSize, "wxStyledTextCtrl", "styleSetSize", 3}, // 2995
+ {wxStyledTextCtrl_StyleSetFaceName, "wxStyledTextCtrl", "styleSetFaceName", 3}, // 2996
+ {wxStyledTextCtrl_StyleSetEOLFilled, "wxStyledTextCtrl", "styleSetEOLFilled", 3}, // 2997
+ {wxStyledTextCtrl_StyleResetDefault, "wxStyledTextCtrl", "styleResetDefault", 1}, // 2998
+ {wxStyledTextCtrl_StyleSetUnderline, "wxStyledTextCtrl", "styleSetUnderline", 3}, // 2999
+ {wxStyledTextCtrl_StyleSetCase, "wxStyledTextCtrl", "styleSetCase", 3}, // 3000
+ {wxStyledTextCtrl_StyleSetHotSpot, "wxStyledTextCtrl", "styleSetHotSpot", 3}, // 3001
+ {wxStyledTextCtrl_SetSelForeground, "wxStyledTextCtrl", "setSelForeground", 3}, // 3002
+ {wxStyledTextCtrl_SetSelBackground, "wxStyledTextCtrl", "setSelBackground", 3}, // 3003
+ {wxStyledTextCtrl_GetSelAlpha, "wxStyledTextCtrl", "getSelAlpha", 1}, // 3004
+ {wxStyledTextCtrl_SetSelAlpha, "wxStyledTextCtrl", "setSelAlpha", 2}, // 3005
+ {wxStyledTextCtrl_SetCaretForeground, "wxStyledTextCtrl", "setCaretForeground", 2}, // 3006
+ {wxStyledTextCtrl_CmdKeyAssign, "wxStyledTextCtrl", "cmdKeyAssign", 4}, // 3007
+ {wxStyledTextCtrl_CmdKeyClear, "wxStyledTextCtrl", "cmdKeyClear", 3}, // 3008
+ {wxStyledTextCtrl_CmdKeyClearAll, "wxStyledTextCtrl", "cmdKeyClearAll", 1}, // 3009
+ {wxStyledTextCtrl_SetStyleBytes, "wxStyledTextCtrl", "setStyleBytes", 2}, // 3010
+ {wxStyledTextCtrl_StyleSetVisible, "wxStyledTextCtrl", "styleSetVisible", 3}, // 3011
+ {wxStyledTextCtrl_GetCaretPeriod, "wxStyledTextCtrl", "getCaretPeriod", 1}, // 3012
+ {wxStyledTextCtrl_SetCaretPeriod, "wxStyledTextCtrl", "setCaretPeriod", 2}, // 3013
+ {wxStyledTextCtrl_SetWordChars, "wxStyledTextCtrl", "setWordChars", 2}, // 3014
+ {wxStyledTextCtrl_BeginUndoAction, "wxStyledTextCtrl", "beginUndoAction", 1}, // 3015
+ {wxStyledTextCtrl_EndUndoAction, "wxStyledTextCtrl", "endUndoAction", 1}, // 3016
+ {wxStyledTextCtrl_IndicatorSetStyle, "wxStyledTextCtrl", "indicatorSetStyle", 3}, // 3017
+ {wxStyledTextCtrl_IndicatorGetStyle, "wxStyledTextCtrl", "indicatorGetStyle", 2}, // 3018
+ {wxStyledTextCtrl_IndicatorSetForeground, "wxStyledTextCtrl", "indicatorSetForeground", 3}, // 3019
+ {wxStyledTextCtrl_IndicatorGetForeground, "wxStyledTextCtrl", "indicatorGetForeground", 2}, // 3020
+ {wxStyledTextCtrl_SetWhitespaceForeground, "wxStyledTextCtrl", "setWhitespaceForeground", 3}, // 3021
+ {wxStyledTextCtrl_SetWhitespaceBackground, "wxStyledTextCtrl", "setWhitespaceBackground", 3}, // 3022
+ {wxStyledTextCtrl_GetStyleBits, "wxStyledTextCtrl", "getStyleBits", 1}, // 3023
+ {wxStyledTextCtrl_SetLineState, "wxStyledTextCtrl", "setLineState", 3}, // 3024
+ {wxStyledTextCtrl_GetLineState, "wxStyledTextCtrl", "getLineState", 2}, // 3025
+ {wxStyledTextCtrl_GetMaxLineState, "wxStyledTextCtrl", "getMaxLineState", 1}, // 3026
+ {wxStyledTextCtrl_GetCaretLineVisible, "wxStyledTextCtrl", "getCaretLineVisible", 1}, // 3027
+ {wxStyledTextCtrl_SetCaretLineVisible, "wxStyledTextCtrl", "setCaretLineVisible", 2}, // 3028
+ {wxStyledTextCtrl_GetCaretLineBackground, "wxStyledTextCtrl", "getCaretLineBackground", 1}, // 3029
+ {wxStyledTextCtrl_SetCaretLineBackground, "wxStyledTextCtrl", "setCaretLineBackground", 2}, // 3030
+ {wxStyledTextCtrl_AutoCompShow, "wxStyledTextCtrl", "autoCompShow", 3}, // 3031
+ {wxStyledTextCtrl_AutoCompCancel, "wxStyledTextCtrl", "autoCompCancel", 1}, // 3032
+ {wxStyledTextCtrl_AutoCompActive, "wxStyledTextCtrl", "autoCompActive", 1}, // 3033
+ {wxStyledTextCtrl_AutoCompPosStart, "wxStyledTextCtrl", "autoCompPosStart", 1}, // 3034
+ {wxStyledTextCtrl_AutoCompComplete, "wxStyledTextCtrl", "autoCompComplete", 1}, // 3035
+ {wxStyledTextCtrl_AutoCompStops, "wxStyledTextCtrl", "autoCompStops", 2}, // 3036
+ {wxStyledTextCtrl_AutoCompSetSeparator, "wxStyledTextCtrl", "autoCompSetSeparator", 2}, // 3037
+ {wxStyledTextCtrl_AutoCompGetSeparator, "wxStyledTextCtrl", "autoCompGetSeparator", 1}, // 3038
+ {wxStyledTextCtrl_AutoCompSelect, "wxStyledTextCtrl", "autoCompSelect", 2}, // 3039
+ {wxStyledTextCtrl_AutoCompSetCancelAtStart, "wxStyledTextCtrl", "autoCompSetCancelAtStart", 2}, // 3040
+ {wxStyledTextCtrl_AutoCompGetCancelAtStart, "wxStyledTextCtrl", "autoCompGetCancelAtStart", 1}, // 3041
+ {wxStyledTextCtrl_AutoCompSetFillUps, "wxStyledTextCtrl", "autoCompSetFillUps", 2}, // 3042
+ {wxStyledTextCtrl_AutoCompSetChooseSingle, "wxStyledTextCtrl", "autoCompSetChooseSingle", 2}, // 3043
+ {wxStyledTextCtrl_AutoCompGetChooseSingle, "wxStyledTextCtrl", "autoCompGetChooseSingle", 1}, // 3044
+ {wxStyledTextCtrl_AutoCompSetIgnoreCase, "wxStyledTextCtrl", "autoCompSetIgnoreCase", 2}, // 3045
+ {wxStyledTextCtrl_AutoCompGetIgnoreCase, "wxStyledTextCtrl", "autoCompGetIgnoreCase", 1}, // 3046
+ {wxStyledTextCtrl_UserListShow, "wxStyledTextCtrl", "userListShow", 3}, // 3047
+ {wxStyledTextCtrl_AutoCompSetAutoHide, "wxStyledTextCtrl", "autoCompSetAutoHide", 2}, // 3048
+ {wxStyledTextCtrl_AutoCompGetAutoHide, "wxStyledTextCtrl", "autoCompGetAutoHide", 1}, // 3049
+ {wxStyledTextCtrl_AutoCompSetDropRestOfWord, "wxStyledTextCtrl", "autoCompSetDropRestOfWord", 2}, // 3050
+ {wxStyledTextCtrl_AutoCompGetDropRestOfWord, "wxStyledTextCtrl", "autoCompGetDropRestOfWord", 1}, // 3051
+ {wxStyledTextCtrl_RegisterImage, "wxStyledTextCtrl", "registerImage", 3}, // 3052
+ {wxStyledTextCtrl_ClearRegisteredImages, "wxStyledTextCtrl", "clearRegisteredImages", 1}, // 3053
+ {wxStyledTextCtrl_AutoCompGetTypeSeparator, "wxStyledTextCtrl", "autoCompGetTypeSeparator", 1}, // 3054
+ {wxStyledTextCtrl_AutoCompSetTypeSeparator, "wxStyledTextCtrl", "autoCompSetTypeSeparator", 2}, // 3055
+ {wxStyledTextCtrl_AutoCompSetMaxWidth, "wxStyledTextCtrl", "autoCompSetMaxWidth", 2}, // 3056
+ {wxStyledTextCtrl_AutoCompGetMaxWidth, "wxStyledTextCtrl", "autoCompGetMaxWidth", 1}, // 3057
+ {wxStyledTextCtrl_AutoCompSetMaxHeight, "wxStyledTextCtrl", "autoCompSetMaxHeight", 2}, // 3058
+ {wxStyledTextCtrl_AutoCompGetMaxHeight, "wxStyledTextCtrl", "autoCompGetMaxHeight", 1}, // 3059
+ {wxStyledTextCtrl_SetIndent, "wxStyledTextCtrl", "setIndent", 2}, // 3060
+ {wxStyledTextCtrl_GetIndent, "wxStyledTextCtrl", "getIndent", 1}, // 3061
+ {wxStyledTextCtrl_SetUseTabs, "wxStyledTextCtrl", "setUseTabs", 2}, // 3062
+ {wxStyledTextCtrl_GetUseTabs, "wxStyledTextCtrl", "getUseTabs", 1}, // 3063
+ {wxStyledTextCtrl_SetLineIndentation, "wxStyledTextCtrl", "setLineIndentation", 3}, // 3064
+ {wxStyledTextCtrl_GetLineIndentation, "wxStyledTextCtrl", "getLineIndentation", 2}, // 3065
+ {wxStyledTextCtrl_GetLineIndentPosition, "wxStyledTextCtrl", "getLineIndentPosition", 2}, // 3066
+ {wxStyledTextCtrl_GetColumn, "wxStyledTextCtrl", "getColumn", 2}, // 3067
+ {wxStyledTextCtrl_SetUseHorizontalScrollBar, "wxStyledTextCtrl", "setUseHorizontalScrollBar", 2}, // 3068
+ {wxStyledTextCtrl_GetUseHorizontalScrollBar, "wxStyledTextCtrl", "getUseHorizontalScrollBar", 1}, // 3069
+ {wxStyledTextCtrl_SetIndentationGuides, "wxStyledTextCtrl", "setIndentationGuides", 2}, // 3070
+ {wxStyledTextCtrl_GetIndentationGuides, "wxStyledTextCtrl", "getIndentationGuides", 1}, // 3071
+ {wxStyledTextCtrl_SetHighlightGuide, "wxStyledTextCtrl", "setHighlightGuide", 2}, // 3072
+ {wxStyledTextCtrl_GetHighlightGuide, "wxStyledTextCtrl", "getHighlightGuide", 1}, // 3073
+ {wxStyledTextCtrl_GetLineEndPosition, "wxStyledTextCtrl", "getLineEndPosition", 2}, // 3074
+ {wxStyledTextCtrl_GetCodePage, "wxStyledTextCtrl", "getCodePage", 1}, // 3075
+ {wxStyledTextCtrl_GetCaretForeground, "wxStyledTextCtrl", "getCaretForeground", 1}, // 3076
+ {wxStyledTextCtrl_GetReadOnly, "wxStyledTextCtrl", "getReadOnly", 1}, // 3077
+ {wxStyledTextCtrl_SetCurrentPos, "wxStyledTextCtrl", "setCurrentPos", 2}, // 3078
+ {wxStyledTextCtrl_SetSelectionStart, "wxStyledTextCtrl", "setSelectionStart", 2}, // 3079
+ {wxStyledTextCtrl_GetSelectionStart, "wxStyledTextCtrl", "getSelectionStart", 1}, // 3080
+ {wxStyledTextCtrl_SetSelectionEnd, "wxStyledTextCtrl", "setSelectionEnd", 2}, // 3081
+ {wxStyledTextCtrl_GetSelectionEnd, "wxStyledTextCtrl", "getSelectionEnd", 1}, // 3082
+ {wxStyledTextCtrl_SetPrintMagnification, "wxStyledTextCtrl", "setPrintMagnification", 2}, // 3083
+ {wxStyledTextCtrl_GetPrintMagnification, "wxStyledTextCtrl", "getPrintMagnification", 1}, // 3084
+ {wxStyledTextCtrl_SetPrintColourMode, "wxStyledTextCtrl", "setPrintColourMode", 2}, // 3085
+ {wxStyledTextCtrl_GetPrintColourMode, "wxStyledTextCtrl", "getPrintColourMode", 1}, // 3086
+ {wxStyledTextCtrl_FindText, "wxStyledTextCtrl", "findText", 5}, // 3087
+ {wxStyledTextCtrl_FormatRange, "wxStyledTextCtrl", "formatRange", 8}, // 3088
+ {wxStyledTextCtrl_GetFirstVisibleLine, "wxStyledTextCtrl", "getFirstVisibleLine", 1}, // 3089
+ {wxStyledTextCtrl_GetLine, "wxStyledTextCtrl", "getLine", 2}, // 3090
+ {wxStyledTextCtrl_GetLineCount, "wxStyledTextCtrl", "getLineCount", 1}, // 3091
+ {wxStyledTextCtrl_SetMarginLeft, "wxStyledTextCtrl", "setMarginLeft", 2}, // 3092
+ {wxStyledTextCtrl_GetMarginLeft, "wxStyledTextCtrl", "getMarginLeft", 1}, // 3093
+ {wxStyledTextCtrl_SetMarginRight, "wxStyledTextCtrl", "setMarginRight", 2}, // 3094
+ {wxStyledTextCtrl_GetMarginRight, "wxStyledTextCtrl", "getMarginRight", 1}, // 3095
+ {wxStyledTextCtrl_GetModify, "wxStyledTextCtrl", "getModify", 1}, // 3096
+ {wxStyledTextCtrl_SetSelection, "wxStyledTextCtrl", "setSelection", 3}, // 3097
+ {wxStyledTextCtrl_GetSelectedText, "wxStyledTextCtrl", "getSelectedText", 1}, // 3098
+ {wxStyledTextCtrl_GetTextRange, "wxStyledTextCtrl", "getTextRange", 3}, // 3099
+ {wxStyledTextCtrl_HideSelection, "wxStyledTextCtrl", "hideSelection", 2}, // 3100
+ {wxStyledTextCtrl_LineFromPosition, "wxStyledTextCtrl", "lineFromPosition", 2}, // 3101
+ {wxStyledTextCtrl_PositionFromLine, "wxStyledTextCtrl", "positionFromLine", 2}, // 3102
+ {wxStyledTextCtrl_LineScroll, "wxStyledTextCtrl", "lineScroll", 3}, // 3103
+ {wxStyledTextCtrl_EnsureCaretVisible, "wxStyledTextCtrl", "ensureCaretVisible", 1}, // 3104
+ {wxStyledTextCtrl_ReplaceSelection, "wxStyledTextCtrl", "replaceSelection", 2}, // 3105
+ {wxStyledTextCtrl_SetReadOnly, "wxStyledTextCtrl", "setReadOnly", 2}, // 3106
+ {wxStyledTextCtrl_CanPaste, "wxStyledTextCtrl", "canPaste", 1}, // 3107
+ {wxStyledTextCtrl_CanUndo, "wxStyledTextCtrl", "canUndo", 1}, // 3108
+ {wxStyledTextCtrl_EmptyUndoBuffer, "wxStyledTextCtrl", "emptyUndoBuffer", 1}, // 3109
+ {wxStyledTextCtrl_Undo, "wxStyledTextCtrl", "undo", 1}, // 3110
+ {wxStyledTextCtrl_Cut, "wxStyledTextCtrl", "cut", 1}, // 3111
+ {wxStyledTextCtrl_Copy, "wxStyledTextCtrl", "copy", 1}, // 3112
+ {wxStyledTextCtrl_Paste, "wxStyledTextCtrl", "paste", 1}, // 3113
+ {wxStyledTextCtrl_Clear, "wxStyledTextCtrl", "clear", 1}, // 3114
+ {wxStyledTextCtrl_SetText, "wxStyledTextCtrl", "setText", 2}, // 3115
+ {wxStyledTextCtrl_GetText, "wxStyledTextCtrl", "getText", 1}, // 3116
+ {wxStyledTextCtrl_GetTextLength, "wxStyledTextCtrl", "getTextLength", 1}, // 3117
+ {wxStyledTextCtrl_GetOvertype, "wxStyledTextCtrl", "getOvertype", 1}, // 3118
+ {wxStyledTextCtrl_SetCaretWidth, "wxStyledTextCtrl", "setCaretWidth", 2}, // 3119
+ {wxStyledTextCtrl_GetCaretWidth, "wxStyledTextCtrl", "getCaretWidth", 1}, // 3120
+ {wxStyledTextCtrl_SetTargetStart, "wxStyledTextCtrl", "setTargetStart", 2}, // 3121
+ {wxStyledTextCtrl_GetTargetStart, "wxStyledTextCtrl", "getTargetStart", 1}, // 3122
+ {wxStyledTextCtrl_SetTargetEnd, "wxStyledTextCtrl", "setTargetEnd", 2}, // 3123
+ {wxStyledTextCtrl_GetTargetEnd, "wxStyledTextCtrl", "getTargetEnd", 1}, // 3124
+ {wxStyledTextCtrl_ReplaceTarget, "wxStyledTextCtrl", "replaceTarget", 2}, // 3125
+ {wxStyledTextCtrl_SearchInTarget, "wxStyledTextCtrl", "searchInTarget", 2}, // 3126
+ {wxStyledTextCtrl_SetSearchFlags, "wxStyledTextCtrl", "setSearchFlags", 2}, // 3127
+ {wxStyledTextCtrl_GetSearchFlags, "wxStyledTextCtrl", "getSearchFlags", 1}, // 3128
+ {wxStyledTextCtrl_CallTipShow, "wxStyledTextCtrl", "callTipShow", 3}, // 3129
+ {wxStyledTextCtrl_CallTipCancel, "wxStyledTextCtrl", "callTipCancel", 1}, // 3130
+ {wxStyledTextCtrl_CallTipActive, "wxStyledTextCtrl", "callTipActive", 1}, // 3131
+ {wxStyledTextCtrl_CallTipPosAtStart, "wxStyledTextCtrl", "callTipPosAtStart", 1}, // 3132
+ {wxStyledTextCtrl_CallTipSetHighlight, "wxStyledTextCtrl", "callTipSetHighlight", 3}, // 3133
+ {wxStyledTextCtrl_CallTipSetBackground, "wxStyledTextCtrl", "callTipSetBackground", 2}, // 3134
+ {wxStyledTextCtrl_CallTipSetForeground, "wxStyledTextCtrl", "callTipSetForeground", 2}, // 3135
+ {wxStyledTextCtrl_CallTipSetForegroundHighlight, "wxStyledTextCtrl", "callTipSetForegroundHighlight", 2}, // 3136
+ {wxStyledTextCtrl_CallTipUseStyle, "wxStyledTextCtrl", "callTipUseStyle", 2}, // 3137
+ {wxStyledTextCtrl_VisibleFromDocLine, "wxStyledTextCtrl", "visibleFromDocLine", 2}, // 3138
+ {wxStyledTextCtrl_DocLineFromVisible, "wxStyledTextCtrl", "docLineFromVisible", 2}, // 3139
+ {wxStyledTextCtrl_WrapCount, "wxStyledTextCtrl", "wrapCount", 2}, // 3140
+ {wxStyledTextCtrl_SetFoldLevel, "wxStyledTextCtrl", "setFoldLevel", 3}, // 3141
+ {wxStyledTextCtrl_GetFoldLevel, "wxStyledTextCtrl", "getFoldLevel", 2}, // 3142
+ {wxStyledTextCtrl_GetLastChild, "wxStyledTextCtrl", "getLastChild", 3}, // 3143
+ {wxStyledTextCtrl_GetFoldParent, "wxStyledTextCtrl", "getFoldParent", 2}, // 3144
+ {wxStyledTextCtrl_ShowLines, "wxStyledTextCtrl", "showLines", 3}, // 3145
+ {wxStyledTextCtrl_HideLines, "wxStyledTextCtrl", "hideLines", 3}, // 3146
+ {wxStyledTextCtrl_GetLineVisible, "wxStyledTextCtrl", "getLineVisible", 2}, // 3147
+ {wxStyledTextCtrl_SetFoldExpanded, "wxStyledTextCtrl", "setFoldExpanded", 3}, // 3148
+ {wxStyledTextCtrl_GetFoldExpanded, "wxStyledTextCtrl", "getFoldExpanded", 2}, // 3149
+ {wxStyledTextCtrl_ToggleFold, "wxStyledTextCtrl", "toggleFold", 2}, // 3150
+ {wxStyledTextCtrl_EnsureVisible, "wxStyledTextCtrl", "ensureVisible", 2}, // 3151
+ {wxStyledTextCtrl_SetFoldFlags, "wxStyledTextCtrl", "setFoldFlags", 2}, // 3152
+ {wxStyledTextCtrl_EnsureVisibleEnforcePolicy, "wxStyledTextCtrl", "ensureVisibleEnforcePolicy", 2}, // 3153
+ {wxStyledTextCtrl_SetTabIndents, "wxStyledTextCtrl", "setTabIndents", 2}, // 3154
+ {wxStyledTextCtrl_GetTabIndents, "wxStyledTextCtrl", "getTabIndents", 1}, // 3155
+ {wxStyledTextCtrl_SetBackSpaceUnIndents, "wxStyledTextCtrl", "setBackSpaceUnIndents", 2}, // 3156
+ {wxStyledTextCtrl_GetBackSpaceUnIndents, "wxStyledTextCtrl", "getBackSpaceUnIndents", 1}, // 3157
+ {wxStyledTextCtrl_SetMouseDwellTime, "wxStyledTextCtrl", "setMouseDwellTime", 2}, // 3158
+ {wxStyledTextCtrl_GetMouseDwellTime, "wxStyledTextCtrl", "getMouseDwellTime", 1}, // 3159
+ {wxStyledTextCtrl_WordStartPosition, "wxStyledTextCtrl", "wordStartPosition", 3}, // 3160
+ {wxStyledTextCtrl_WordEndPosition, "wxStyledTextCtrl", "wordEndPosition", 3}, // 3161
+ {wxStyledTextCtrl_SetWrapMode, "wxStyledTextCtrl", "setWrapMode", 2}, // 3162
+ {wxStyledTextCtrl_GetWrapMode, "wxStyledTextCtrl", "getWrapMode", 1}, // 3163
+ {wxStyledTextCtrl_SetWrapVisualFlags, "wxStyledTextCtrl", "setWrapVisualFlags", 2}, // 3164
+ {wxStyledTextCtrl_GetWrapVisualFlags, "wxStyledTextCtrl", "getWrapVisualFlags", 1}, // 3165
+ {wxStyledTextCtrl_SetWrapVisualFlagsLocation, "wxStyledTextCtrl", "setWrapVisualFlagsLocation", 2}, // 3166
+ {wxStyledTextCtrl_GetWrapVisualFlagsLocation, "wxStyledTextCtrl", "getWrapVisualFlagsLocation", 1}, // 3167
+ {wxStyledTextCtrl_SetWrapStartIndent, "wxStyledTextCtrl", "setWrapStartIndent", 2}, // 3168
+ {wxStyledTextCtrl_GetWrapStartIndent, "wxStyledTextCtrl", "getWrapStartIndent", 1}, // 3169
+ {wxStyledTextCtrl_SetLayoutCache, "wxStyledTextCtrl", "setLayoutCache", 2}, // 3170
+ {wxStyledTextCtrl_GetLayoutCache, "wxStyledTextCtrl", "getLayoutCache", 1}, // 3171
+ {wxStyledTextCtrl_SetScrollWidth, "wxStyledTextCtrl", "setScrollWidth", 2}, // 3172
+ {wxStyledTextCtrl_GetScrollWidth, "wxStyledTextCtrl", "getScrollWidth", 1}, // 3173
+ {wxStyledTextCtrl_TextWidth, "wxStyledTextCtrl", "textWidth", 3}, // 3174
+ {wxStyledTextCtrl_GetEndAtLastLine, "wxStyledTextCtrl", "getEndAtLastLine", 1}, // 3175
+ {wxStyledTextCtrl_TextHeight, "wxStyledTextCtrl", "textHeight", 2}, // 3176
+ {wxStyledTextCtrl_SetUseVerticalScrollBar, "wxStyledTextCtrl", "setUseVerticalScrollBar", 2}, // 3177
+ {wxStyledTextCtrl_GetUseVerticalScrollBar, "wxStyledTextCtrl", "getUseVerticalScrollBar", 1}, // 3178
+ {wxStyledTextCtrl_AppendText, "wxStyledTextCtrl", "appendText", 2}, // 3179
+ {wxStyledTextCtrl_GetTwoPhaseDraw, "wxStyledTextCtrl", "getTwoPhaseDraw", 1}, // 3180
+ {wxStyledTextCtrl_SetTwoPhaseDraw, "wxStyledTextCtrl", "setTwoPhaseDraw", 2}, // 3181
+ {wxStyledTextCtrl_TargetFromSelection, "wxStyledTextCtrl", "targetFromSelection", 1}, // 3182
+ {wxStyledTextCtrl_LinesJoin, "wxStyledTextCtrl", "linesJoin", 1}, // 3183
+ {wxStyledTextCtrl_LinesSplit, "wxStyledTextCtrl", "linesSplit", 2}, // 3184
+ {wxStyledTextCtrl_SetFoldMarginColour, "wxStyledTextCtrl", "setFoldMarginColour", 3}, // 3185
+ {wxStyledTextCtrl_SetFoldMarginHiColour, "wxStyledTextCtrl", "setFoldMarginHiColour", 3}, // 3186
+ {wxStyledTextCtrl_LineDown, "wxStyledTextCtrl", "lineDown", 1}, // 3187
+ {wxStyledTextCtrl_LineDownExtend, "wxStyledTextCtrl", "lineDownExtend", 1}, // 3188
+ {wxStyledTextCtrl_LineUp, "wxStyledTextCtrl", "lineUp", 1}, // 3189
+ {wxStyledTextCtrl_LineUpExtend, "wxStyledTextCtrl", "lineUpExtend", 1}, // 3190
+ {wxStyledTextCtrl_CharLeft, "wxStyledTextCtrl", "charLeft", 1}, // 3191
+ {wxStyledTextCtrl_CharLeftExtend, "wxStyledTextCtrl", "charLeftExtend", 1}, // 3192
+ {wxStyledTextCtrl_CharRight, "wxStyledTextCtrl", "charRight", 1}, // 3193
+ {wxStyledTextCtrl_CharRightExtend, "wxStyledTextCtrl", "charRightExtend", 1}, // 3194
+ {wxStyledTextCtrl_WordLeft, "wxStyledTextCtrl", "wordLeft", 1}, // 3195
+ {wxStyledTextCtrl_WordLeftExtend, "wxStyledTextCtrl", "wordLeftExtend", 1}, // 3196
+ {wxStyledTextCtrl_WordRight, "wxStyledTextCtrl", "wordRight", 1}, // 3197
+ {wxStyledTextCtrl_WordRightExtend, "wxStyledTextCtrl", "wordRightExtend", 1}, // 3198
+ {wxStyledTextCtrl_Home, "wxStyledTextCtrl", "home", 1}, // 3199
+ {wxStyledTextCtrl_HomeExtend, "wxStyledTextCtrl", "homeExtend", 1}, // 3200
+ {wxStyledTextCtrl_LineEnd, "wxStyledTextCtrl", "lineEnd", 1}, // 3201
+ {wxStyledTextCtrl_LineEndExtend, "wxStyledTextCtrl", "lineEndExtend", 1}, // 3202
+ {wxStyledTextCtrl_DocumentStart, "wxStyledTextCtrl", "documentStart", 1}, // 3203
+ {wxStyledTextCtrl_DocumentStartExtend, "wxStyledTextCtrl", "documentStartExtend", 1}, // 3204
+ {wxStyledTextCtrl_DocumentEnd, "wxStyledTextCtrl", "documentEnd", 1}, // 3205
+ {wxStyledTextCtrl_DocumentEndExtend, "wxStyledTextCtrl", "documentEndExtend", 1}, // 3206
+ {wxStyledTextCtrl_PageUp, "wxStyledTextCtrl", "pageUp", 1}, // 3207
+ {wxStyledTextCtrl_PageUpExtend, "wxStyledTextCtrl", "pageUpExtend", 1}, // 3208
+ {wxStyledTextCtrl_PageDown, "wxStyledTextCtrl", "pageDown", 1}, // 3209
+ {wxStyledTextCtrl_PageDownExtend, "wxStyledTextCtrl", "pageDownExtend", 1}, // 3210
+ {wxStyledTextCtrl_EditToggleOvertype, "wxStyledTextCtrl", "editToggleOvertype", 1}, // 3211
+ {wxStyledTextCtrl_Cancel, "wxStyledTextCtrl", "cancel", 1}, // 3212
+ {wxStyledTextCtrl_DeleteBack, "wxStyledTextCtrl", "deleteBack", 1}, // 3213
+ {wxStyledTextCtrl_Tab, "wxStyledTextCtrl", "tab", 1}, // 3214
+ {wxStyledTextCtrl_BackTab, "wxStyledTextCtrl", "backTab", 1}, // 3215
+ {wxStyledTextCtrl_NewLine, "wxStyledTextCtrl", "newLine", 1}, // 3216
+ {wxStyledTextCtrl_FormFeed, "wxStyledTextCtrl", "formFeed", 1}, // 3217
+ {wxStyledTextCtrl_VCHome, "wxStyledTextCtrl", "vCHome", 1}, // 3218
+ {wxStyledTextCtrl_VCHomeExtend, "wxStyledTextCtrl", "vCHomeExtend", 1}, // 3219
+ {wxStyledTextCtrl_ZoomIn, "wxStyledTextCtrl", "zoomIn", 1}, // 3220
+ {wxStyledTextCtrl_ZoomOut, "wxStyledTextCtrl", "zoomOut", 1}, // 3221
+ {wxStyledTextCtrl_DelWordLeft, "wxStyledTextCtrl", "delWordLeft", 1}, // 3222
+ {wxStyledTextCtrl_DelWordRight, "wxStyledTextCtrl", "delWordRight", 1}, // 3223
+ {wxStyledTextCtrl_LineCut, "wxStyledTextCtrl", "lineCut", 1}, // 3224
+ {wxStyledTextCtrl_LineDelete, "wxStyledTextCtrl", "lineDelete", 1}, // 3225
+ {wxStyledTextCtrl_LineTranspose, "wxStyledTextCtrl", "lineTranspose", 1}, // 3226
+ {wxStyledTextCtrl_LineDuplicate, "wxStyledTextCtrl", "lineDuplicate", 1}, // 3227
+ {wxStyledTextCtrl_LowerCase, "wxStyledTextCtrl", "lowerCase", 1}, // 3228
+ {wxStyledTextCtrl_UpperCase, "wxStyledTextCtrl", "upperCase", 1}, // 3229
+ {wxStyledTextCtrl_LineScrollDown, "wxStyledTextCtrl", "lineScrollDown", 1}, // 3230
+ {wxStyledTextCtrl_LineScrollUp, "wxStyledTextCtrl", "lineScrollUp", 1}, // 3231
+ {wxStyledTextCtrl_DeleteBackNotLine, "wxStyledTextCtrl", "deleteBackNotLine", 1}, // 3232
+ {wxStyledTextCtrl_HomeDisplay, "wxStyledTextCtrl", "homeDisplay", 1}, // 3233
+ {wxStyledTextCtrl_HomeDisplayExtend, "wxStyledTextCtrl", "homeDisplayExtend", 1}, // 3234
+ {wxStyledTextCtrl_LineEndDisplay, "wxStyledTextCtrl", "lineEndDisplay", 1}, // 3235
+ {wxStyledTextCtrl_LineEndDisplayExtend, "wxStyledTextCtrl", "lineEndDisplayExtend", 1}, // 3236
+ {wxStyledTextCtrl_HomeWrapExtend, "wxStyledTextCtrl", "homeWrapExtend", 1}, // 3237
+ {wxStyledTextCtrl_LineEndWrap, "wxStyledTextCtrl", "lineEndWrap", 1}, // 3238
+ {wxStyledTextCtrl_LineEndWrapExtend, "wxStyledTextCtrl", "lineEndWrapExtend", 1}, // 3239
+ {wxStyledTextCtrl_VCHomeWrap, "wxStyledTextCtrl", "vCHomeWrap", 1}, // 3240
+ {wxStyledTextCtrl_VCHomeWrapExtend, "wxStyledTextCtrl", "vCHomeWrapExtend", 1}, // 3241
+ {wxStyledTextCtrl_LineCopy, "wxStyledTextCtrl", "lineCopy", 1}, // 3242
+ {wxStyledTextCtrl_MoveCaretInsideView, "wxStyledTextCtrl", "moveCaretInsideView", 1}, // 3243
+ {wxStyledTextCtrl_LineLength, "wxStyledTextCtrl", "lineLength", 2}, // 3244
+ {wxStyledTextCtrl_BraceHighlight, "wxStyledTextCtrl", "braceHighlight", 3}, // 3245
+ {wxStyledTextCtrl_BraceBadLight, "wxStyledTextCtrl", "braceBadLight", 2}, // 3246
+ {wxStyledTextCtrl_BraceMatch, "wxStyledTextCtrl", "braceMatch", 2}, // 3247
+ {wxStyledTextCtrl_GetViewEOL, "wxStyledTextCtrl", "getViewEOL", 1}, // 3248
+ {wxStyledTextCtrl_SetViewEOL, "wxStyledTextCtrl", "setViewEOL", 2}, // 3249
+ {wxStyledTextCtrl_SetModEventMask, "wxStyledTextCtrl", "setModEventMask", 2}, // 3250
+ {wxStyledTextCtrl_GetEdgeColumn, "wxStyledTextCtrl", "getEdgeColumn", 1}, // 3251
+ {wxStyledTextCtrl_SetEdgeColumn, "wxStyledTextCtrl", "setEdgeColumn", 2}, // 3252
+ {wxStyledTextCtrl_SetEdgeMode, "wxStyledTextCtrl", "setEdgeMode", 2}, // 3253
+ {wxStyledTextCtrl_GetEdgeMode, "wxStyledTextCtrl", "getEdgeMode", 1}, // 3254
+ {wxStyledTextCtrl_GetEdgeColour, "wxStyledTextCtrl", "getEdgeColour", 1}, // 3255
+ {wxStyledTextCtrl_SetEdgeColour, "wxStyledTextCtrl", "setEdgeColour", 2}, // 3256
+ {wxStyledTextCtrl_SearchAnchor, "wxStyledTextCtrl", "searchAnchor", 1}, // 3257
+ {wxStyledTextCtrl_SearchNext, "wxStyledTextCtrl", "searchNext", 3}, // 3258
+ {wxStyledTextCtrl_SearchPrev, "wxStyledTextCtrl", "searchPrev", 3}, // 3259
+ {wxStyledTextCtrl_LinesOnScreen, "wxStyledTextCtrl", "linesOnScreen", 1}, // 3260
+ {wxStyledTextCtrl_UsePopUp, "wxStyledTextCtrl", "usePopUp", 2}, // 3261
+ {wxStyledTextCtrl_SelectionIsRectangle, "wxStyledTextCtrl", "selectionIsRectangle", 1}, // 3262
+ {wxStyledTextCtrl_SetZoom, "wxStyledTextCtrl", "setZoom", 2}, // 3263
+ {wxStyledTextCtrl_GetZoom, "wxStyledTextCtrl", "getZoom", 1}, // 3264
+ {wxStyledTextCtrl_GetModEventMask, "wxStyledTextCtrl", "getModEventMask", 1}, // 3265
+ {wxStyledTextCtrl_SetSTCFocus, "wxStyledTextCtrl", "setSTCFocus", 2}, // 3266
+ {wxStyledTextCtrl_GetSTCFocus, "wxStyledTextCtrl", "getSTCFocus", 1}, // 3267
+ {wxStyledTextCtrl_SetStatus, "wxStyledTextCtrl", "setStatus", 2}, // 3268
+ {wxStyledTextCtrl_GetStatus, "wxStyledTextCtrl", "getStatus", 1}, // 3269
+ {wxStyledTextCtrl_SetMouseDownCaptures, "wxStyledTextCtrl", "setMouseDownCaptures", 2}, // 3270
+ {wxStyledTextCtrl_GetMouseDownCaptures, "wxStyledTextCtrl", "getMouseDownCaptures", 1}, // 3271
+ {wxStyledTextCtrl_SetSTCCursor, "wxStyledTextCtrl", "setSTCCursor", 2}, // 3272
+ {wxStyledTextCtrl_GetSTCCursor, "wxStyledTextCtrl", "getSTCCursor", 1}, // 3273
+ {wxStyledTextCtrl_SetControlCharSymbol, "wxStyledTextCtrl", "setControlCharSymbol", 2}, // 3274
+ {wxStyledTextCtrl_GetControlCharSymbol, "wxStyledTextCtrl", "getControlCharSymbol", 1}, // 3275
+ {wxStyledTextCtrl_WordPartLeft, "wxStyledTextCtrl", "wordPartLeft", 1}, // 3276
+ {wxStyledTextCtrl_WordPartLeftExtend, "wxStyledTextCtrl", "wordPartLeftExtend", 1}, // 3277
+ {wxStyledTextCtrl_WordPartRight, "wxStyledTextCtrl", "wordPartRight", 1}, // 3278
+ {wxStyledTextCtrl_WordPartRightExtend, "wxStyledTextCtrl", "wordPartRightExtend", 1}, // 3279
+ {wxStyledTextCtrl_SetVisiblePolicy, "wxStyledTextCtrl", "setVisiblePolicy", 3}, // 3280
+ {wxStyledTextCtrl_DelLineLeft, "wxStyledTextCtrl", "delLineLeft", 1}, // 3281
+ {wxStyledTextCtrl_DelLineRight, "wxStyledTextCtrl", "delLineRight", 1}, // 3282
+ {wxStyledTextCtrl_GetXOffset, "wxStyledTextCtrl", "getXOffset", 1}, // 3283
+ {wxStyledTextCtrl_ChooseCaretX, "wxStyledTextCtrl", "chooseCaretX", 1}, // 3284
+ {wxStyledTextCtrl_SetXCaretPolicy, "wxStyledTextCtrl", "setXCaretPolicy", 3}, // 3285
+ {wxStyledTextCtrl_SetYCaretPolicy, "wxStyledTextCtrl", "setYCaretPolicy", 3}, // 3286
+ {wxStyledTextCtrl_GetPrintWrapMode, "wxStyledTextCtrl", "getPrintWrapMode", 1}, // 3287
+ {wxStyledTextCtrl_SetHotspotActiveForeground, "wxStyledTextCtrl", "setHotspotActiveForeground", 3}, // 3288
+ {wxStyledTextCtrl_SetHotspotActiveBackground, "wxStyledTextCtrl", "setHotspotActiveBackground", 3}, // 3289
+ {wxStyledTextCtrl_SetHotspotActiveUnderline, "wxStyledTextCtrl", "setHotspotActiveUnderline", 2}, // 3290
+ {wxStyledTextCtrl_SetHotspotSingleLine, "wxStyledTextCtrl", "setHotspotSingleLine", 2}, // 3291
+ {wxStyledTextCtrl_ParaDownExtend, "wxStyledTextCtrl", "paraDownExtend", 1}, // 3292
+ {wxStyledTextCtrl_ParaUp, "wxStyledTextCtrl", "paraUp", 1}, // 3293
+ {wxStyledTextCtrl_ParaUpExtend, "wxStyledTextCtrl", "paraUpExtend", 1}, // 3294
+ {wxStyledTextCtrl_PositionBefore, "wxStyledTextCtrl", "positionBefore", 2}, // 3295
+ {wxStyledTextCtrl_PositionAfter, "wxStyledTextCtrl", "positionAfter", 2}, // 3296
+ {wxStyledTextCtrl_CopyRange, "wxStyledTextCtrl", "copyRange", 3}, // 3297
+ {wxStyledTextCtrl_CopyText, "wxStyledTextCtrl", "copyText", 3}, // 3298
+ {wxStyledTextCtrl_SetSelectionMode, "wxStyledTextCtrl", "setSelectionMode", 2}, // 3299
+ {wxStyledTextCtrl_GetSelectionMode, "wxStyledTextCtrl", "getSelectionMode", 1}, // 3300
+ {wxStyledTextCtrl_LineDownRectExtend, "wxStyledTextCtrl", "lineDownRectExtend", 1}, // 3301
+ {wxStyledTextCtrl_LineUpRectExtend, "wxStyledTextCtrl", "lineUpRectExtend", 1}, // 3302
+ {wxStyledTextCtrl_CharLeftRectExtend, "wxStyledTextCtrl", "charLeftRectExtend", 1}, // 3303
+ {wxStyledTextCtrl_CharRightRectExtend, "wxStyledTextCtrl", "charRightRectExtend", 1}, // 3304
+ {wxStyledTextCtrl_HomeRectExtend, "wxStyledTextCtrl", "homeRectExtend", 1}, // 3305
+ {wxStyledTextCtrl_VCHomeRectExtend, "wxStyledTextCtrl", "vCHomeRectExtend", 1}, // 3306
+ {wxStyledTextCtrl_LineEndRectExtend, "wxStyledTextCtrl", "lineEndRectExtend", 1}, // 3307
+ {wxStyledTextCtrl_PageUpRectExtend, "wxStyledTextCtrl", "pageUpRectExtend", 1}, // 3308
+ {wxStyledTextCtrl_PageDownRectExtend, "wxStyledTextCtrl", "pageDownRectExtend", 1}, // 3309
+ {wxStyledTextCtrl_StutteredPageUp, "wxStyledTextCtrl", "stutteredPageUp", 1}, // 3310
+ {wxStyledTextCtrl_StutteredPageUpExtend, "wxStyledTextCtrl", "stutteredPageUpExtend", 1}, // 3311
+ {wxStyledTextCtrl_StutteredPageDown, "wxStyledTextCtrl", "stutteredPageDown", 1}, // 3312
+ {wxStyledTextCtrl_StutteredPageDownExtend, "wxStyledTextCtrl", "stutteredPageDownExtend", 1}, // 3313
+ {wxStyledTextCtrl_WordLeftEnd, "wxStyledTextCtrl", "wordLeftEnd", 1}, // 3314
+ {wxStyledTextCtrl_WordLeftEndExtend, "wxStyledTextCtrl", "wordLeftEndExtend", 1}, // 3315
+ {wxStyledTextCtrl_WordRightEnd, "wxStyledTextCtrl", "wordRightEnd", 1}, // 3316
+ {wxStyledTextCtrl_WordRightEndExtend, "wxStyledTextCtrl", "wordRightEndExtend", 1}, // 3317
+ {wxStyledTextCtrl_SetWhitespaceChars, "wxStyledTextCtrl", "setWhitespaceChars", 2}, // 3318
+ {wxStyledTextCtrl_SetCharsDefault, "wxStyledTextCtrl", "setCharsDefault", 1}, // 3319
+ {wxStyledTextCtrl_AutoCompGetCurrent, "wxStyledTextCtrl", "autoCompGetCurrent", 1}, // 3320
+ {wxStyledTextCtrl_Allocate, "wxStyledTextCtrl", "allocate", 2}, // 3321
+ {wxStyledTextCtrl_FindColumn, "wxStyledTextCtrl", "findColumn", 3}, // 3322
+ {wxStyledTextCtrl_GetCaretSticky, "wxStyledTextCtrl", "getCaretSticky", 1}, // 3323
+ {wxStyledTextCtrl_SetCaretSticky, "wxStyledTextCtrl", "setCaretSticky", 2}, // 3324
+ {wxStyledTextCtrl_ToggleCaretSticky, "wxStyledTextCtrl", "toggleCaretSticky", 1}, // 3325
+ {wxStyledTextCtrl_SetPasteConvertEndings, "wxStyledTextCtrl", "setPasteConvertEndings", 2}, // 3326
+ {wxStyledTextCtrl_GetPasteConvertEndings, "wxStyledTextCtrl", "getPasteConvertEndings", 1}, // 3327
+ {wxStyledTextCtrl_SelectionDuplicate, "wxStyledTextCtrl", "selectionDuplicate", 1}, // 3328
+ {wxStyledTextCtrl_SetCaretLineBackAlpha, "wxStyledTextCtrl", "setCaretLineBackAlpha", 2}, // 3329
+ {wxStyledTextCtrl_GetCaretLineBackAlpha, "wxStyledTextCtrl", "getCaretLineBackAlpha", 1}, // 3330
+ {wxStyledTextCtrl_StartRecord, "wxStyledTextCtrl", "startRecord", 1}, // 3331
+ {wxStyledTextCtrl_StopRecord, "wxStyledTextCtrl", "stopRecord", 1}, // 3332
+ {wxStyledTextCtrl_SetLexer, "wxStyledTextCtrl", "setLexer", 2}, // 3333
+ {wxStyledTextCtrl_GetLexer, "wxStyledTextCtrl", "getLexer", 1}, // 3334
+ {wxStyledTextCtrl_Colourise, "wxStyledTextCtrl", "colourise", 3}, // 3335
+ {wxStyledTextCtrl_SetProperty, "wxStyledTextCtrl", "setProperty", 3}, // 3336
+ {wxStyledTextCtrl_SetKeyWords, "wxStyledTextCtrl", "setKeyWords", 3}, // 3337
+ {wxStyledTextCtrl_SetLexerLanguage, "wxStyledTextCtrl", "setLexerLanguage", 2}, // 3338
+ {wxStyledTextCtrl_GetProperty, "wxStyledTextCtrl", "getProperty", 2}, // 3339
+ {wxStyledTextCtrl_GetStyleBitsNeeded, "wxStyledTextCtrl", "getStyleBitsNeeded", 1}, // 3340
+ {wxStyledTextCtrl_GetCurrentLine, "wxStyledTextCtrl", "getCurrentLine", 1}, // 3341
+ {wxStyledTextCtrl_StyleSetSpec, "wxStyledTextCtrl", "styleSetSpec", 3}, // 3342
+ {wxStyledTextCtrl_StyleSetFont, "wxStyledTextCtrl", "styleSetFont", 3}, // 3343
+ {wxStyledTextCtrl_StyleSetFontAttr, "wxStyledTextCtrl", "styleSetFontAttr", 8}, // 3344
+ {wxStyledTextCtrl_StyleSetCharacterSet, "wxStyledTextCtrl", "styleSetCharacterSet", 3}, // 3345
+ {wxStyledTextCtrl_StyleSetFontEncoding, "wxStyledTextCtrl", "styleSetFontEncoding", 3}, // 3346
+ {wxStyledTextCtrl_CmdKeyExecute, "wxStyledTextCtrl", "cmdKeyExecute", 2}, // 3347
+ {wxStyledTextCtrl_SetMargins, "wxStyledTextCtrl", "setMargins", 3}, // 3348
+ {wxStyledTextCtrl_GetSelection, "wxStyledTextCtrl", "getSelection", 1}, // 3349
+ {wxStyledTextCtrl_PointFromPosition, "wxStyledTextCtrl", "pointFromPosition", 2}, // 3350
+ {wxStyledTextCtrl_ScrollToLine, "wxStyledTextCtrl", "scrollToLine", 2}, // 3351
+ {wxStyledTextCtrl_ScrollToColumn, "wxStyledTextCtrl", "scrollToColumn", 2}, // 3352
+ {wxStyledTextCtrl_SetVScrollBar, "wxStyledTextCtrl", "setVScrollBar", 2}, // 3353
+ {wxStyledTextCtrl_SetHScrollBar, "wxStyledTextCtrl", "setHScrollBar", 2}, // 3354
+ {wxStyledTextCtrl_GetLastKeydownProcessed, "wxStyledTextCtrl", "getLastKeydownProcessed", 1}, // 3355
+ {wxStyledTextCtrl_SetLastKeydownProcessed, "wxStyledTextCtrl", "setLastKeydownProcessed", 2}, // 3356
+ {wxStyledTextCtrl_SaveFile, "wxStyledTextCtrl", "saveFile", 2}, // 3357
+ {wxStyledTextCtrl_LoadFile, "wxStyledTextCtrl", "loadFile", 2}, // 3358
+ {wxStyledTextCtrl_DoDragOver, "wxStyledTextCtrl", "doDragOver", 4}, // 3359
+ {wxStyledTextCtrl_DoDropText, "wxStyledTextCtrl", "doDropText", 4}, // 3360
+ {wxStyledTextCtrl_GetUseAntiAliasing, "wxStyledTextCtrl", "getUseAntiAliasing", 1}, // 3361
+ {wxStyledTextCtrl_AddTextRaw, "wxStyledTextCtrl", "addTextRaw", 3}, // 3362
+ {wxStyledTextCtrl_InsertTextRaw, "wxStyledTextCtrl", "insertTextRaw", 3}, // 3363
+ {wxStyledTextCtrl_GetCurLineRaw, "wxStyledTextCtrl", "getCurLineRaw", 1}, // 3364
+ {wxStyledTextCtrl_GetLineRaw, "wxStyledTextCtrl", "getLineRaw", 2}, // 3365
+ {wxStyledTextCtrl_GetSelectedTextRaw, "wxStyledTextCtrl", "getSelectedTextRaw", 1}, // 3366
+ {wxStyledTextCtrl_GetTextRangeRaw, "wxStyledTextCtrl", "getTextRangeRaw", 3}, // 3367
+ {wxStyledTextCtrl_SetTextRaw, "wxStyledTextCtrl", "setTextRaw", 2}, // 3368
+ {wxStyledTextCtrl_GetTextRaw, "wxStyledTextCtrl", "getTextRaw", 1}, // 3369
+ {wxStyledTextCtrl_AppendTextRaw, "wxStyledTextCtrl", "appendTextRaw", 3}, // 3370
+ {wxArtProvider_GetBitmap, "wxArtProvider", "getBitmap", 2}, // 3371
+ {wxArtProvider_GetIcon, "wxArtProvider", "getIcon", 2}, // 3372
+ {wxTreeEvent_GetKeyCode, "wxTreeEvent", "getKeyCode", 1}, // 3373
+ {wxTreeEvent_GetItem, "wxTreeEvent", "getItem", 1}, // 3374
+ {wxTreeEvent_GetKeyEvent, "wxTreeEvent", "getKeyEvent", 1}, // 3375
+ {wxTreeEvent_GetLabel, "wxTreeEvent", "getLabel", 1}, // 3376
+ {wxTreeEvent_GetOldItem, "wxTreeEvent", "getOldItem", 1}, // 3377
+ {wxTreeEvent_GetPoint, "wxTreeEvent", "getPoint", 1}, // 3378
+ {wxTreeEvent_IsEditCancelled, "wxTreeEvent", "isEditCancelled", 1}, // 3379
+ {wxTreeEvent_SetToolTip, "wxTreeEvent", "setToolTip", 2}, // 3380
+ {wxBookCtrlEvent_GetOldSelection, "wxBookCtrlEvent", "getOldSelection", 1}, // 3381
+ {wxBookCtrlEvent_GetSelection, "wxBookCtrlEvent", "getSelection", 1}, // 3382
+ {wxBookCtrlEvent_SetOldSelection, "wxBookCtrlEvent", "setOldSelection", 2}, // 3383
+ {wxBookCtrlEvent_SetSelection, "wxBookCtrlEvent", "setSelection", 2}, // 3384
+ {wxFileDataObject_new, "wxFileDataObject", "new", 0}, // 3385
+ {wxFileDataObject_AddFile, "wxFileDataObject", "addFile", 2}, // 3386
+ {wxFileDataObject_GetFilenames, "wxFileDataObject", "getFilenames", 1}, // 3387
+ {wxFileDataObject_destroy, "wxFileDataObject", "'Destroy'", 1}, // 3388
+ {wxTextDataObject_new, "wxTextDataObject", "new", 1}, // 3389
+ {wxTextDataObject_GetTextLength, "wxTextDataObject", "getTextLength", 1}, // 3390
+ {wxTextDataObject_GetText, "wxTextDataObject", "getText", 1}, // 3391
+ {wxTextDataObject_SetText, "wxTextDataObject", "setText", 2}, // 3392
+ {wxTextDataObject_destroy, "wxTextDataObject", "'Destroy'", 1}, // 3393
+ {wxBitmapDataObject_new_1_1, "wxBitmapDataObject", "new", 1}, // 3394
+ {wxBitmapDataObject_new_1_0, "wxBitmapDataObject", "new", 1}, // 3395
+ {wxBitmapDataObject_GetBitmap, "wxBitmapDataObject", "getBitmap", 1}, // 3396
+ {wxBitmapDataObject_SetBitmap, "wxBitmapDataObject", "setBitmap", 2}, // 3397
+ {wxBitmapDataObject_destroy, "wxBitmapDataObject", "'Destroy'", 1}, // 3398
+ {wxClipboard_new, "wxClipboard", "new", 0}, // 3399
+ {NULL, "wxClipboard", "destroy", 1}, // 3400 obj destructor wxClipboard_destruct
+ {wxClipboard_AddData, "wxClipboard", "addData", 2}, // 3401
+ {wxClipboard_Clear, "wxClipboard", "clear", 1}, // 3402
+ {wxClipboard_Close, "wxClipboard", "close", 1}, // 3403
+ {wxClipboard_Flush, "wxClipboard", "flush", 1}, // 3404
+ {wxClipboard_GetData, "wxClipboard", "getData", 2}, // 3405
+ {wxClipboard_IsOpened, "wxClipboard", "isOpened", 1}, // 3406
+ {wxClipboard_Open, "wxClipboard", "open", 1}, // 3407
+ {wxClipboard_SetData, "wxClipboard", "setData", 2}, // 3408
+ {wxClipboard_UsePrimarySelection, "wxClipboard", "usePrimarySelection", 2}, // 3409
+ {wxClipboard_IsSupported, "wxClipboard", "isSupported", 2}, // 3410
+ {wxClipboard_Get, "wxClipboard", "get", 0}, // 3411
+ {wxSpinEvent_GetPosition, "wxSpinEvent", "getPosition", 1}, // 3412
+ {wxSpinEvent_SetPosition, "wxSpinEvent", "setPosition", 2}, // 3413
+ {wxSplitterWindow_new_0, "wxSplitterWindow", "new", 0}, // 3414
+ {wxSplitterWindow_new_2, "wxSplitterWindow", "new", 2}, // 3415
+ {NULL, "wxSplitterWindow", "destroy", 1}, // 3416 obj destructor wxSplitterWindow_destruct
+ {wxSplitterWindow_Create, "wxSplitterWindow", "create", 3}, // 3417
+ {wxSplitterWindow_GetMinimumPaneSize, "wxSplitterWindow", "getMinimumPaneSize", 1}, // 3418
+ {wxSplitterWindow_GetSashGravity, "wxSplitterWindow", "getSashGravity", 1}, // 3419
+ {wxSplitterWindow_GetSashPosition, "wxSplitterWindow", "getSashPosition", 1}, // 3420
+ {wxSplitterWindow_GetSplitMode, "wxSplitterWindow", "getSplitMode", 1}, // 3421
+ {wxSplitterWindow_GetWindow1, "wxSplitterWindow", "getWindow1", 1}, // 3422
+ {wxSplitterWindow_GetWindow2, "wxSplitterWindow", "getWindow2", 1}, // 3423
+ {wxSplitterWindow_Initialize, "wxSplitterWindow", "initialize", 2}, // 3424
+ {wxSplitterWindow_IsSplit, "wxSplitterWindow", "isSplit", 1}, // 3425
+ {wxSplitterWindow_ReplaceWindow, "wxSplitterWindow", "replaceWindow", 3}, // 3426
+ {wxSplitterWindow_SetSashGravity, "wxSplitterWindow", "setSashGravity", 2}, // 3427
+ {wxSplitterWindow_SetSashPosition, "wxSplitterWindow", "setSashPosition", 3}, // 3428
+ {wxSplitterWindow_SetMinimumPaneSize, "wxSplitterWindow", "setMinimumPaneSize", 2}, // 3429
+ {wxSplitterWindow_SetSplitMode, "wxSplitterWindow", "setSplitMode", 2}, // 3430
+ {wxSplitterWindow_SplitHorizontally, "wxSplitterWindow", "splitHorizontally", 4}, // 3431
+ {wxSplitterWindow_SplitVertically, "wxSplitterWindow", "splitVertically", 4}, // 3432
+ {wxSplitterWindow_Unsplit, "wxSplitterWindow", "unsplit", 2}, // 3433
+ {wxSplitterWindow_UpdateSize, "wxSplitterWindow", "updateSize", 1}, // 3434
+ {wxSplitterEvent_GetSashPosition, "wxSplitterEvent", "getSashPosition", 1}, // 3435
+ {wxSplitterEvent_GetX, "wxSplitterEvent", "getX", 1}, // 3436
+ {wxSplitterEvent_GetY, "wxSplitterEvent", "getY", 1}, // 3437
+ {wxSplitterEvent_GetWindowBeingRemoved, "wxSplitterEvent", "getWindowBeingRemoved", 1}, // 3438
+ {wxSplitterEvent_SetSashPosition, "wxSplitterEvent", "setSashPosition", 2}, // 3439
+ {wxHtmlWindow_new_0, "wxHtmlWindow", "new", 0}, // 3440
+ {wxHtmlWindow_new_2, "wxHtmlWindow", "new", 2}, // 3441
+ {wxHtmlWindow_AppendToPage, "wxHtmlWindow", "appendToPage", 2}, // 3442
+ {wxHtmlWindow_GetOpenedAnchor, "wxHtmlWindow", "getOpenedAnchor", 1}, // 3443
+ {wxHtmlWindow_GetOpenedPage, "wxHtmlWindow", "getOpenedPage", 1}, // 3444
+ {wxHtmlWindow_GetOpenedPageTitle, "wxHtmlWindow", "getOpenedPageTitle", 1}, // 3445
+ {wxHtmlWindow_GetRelatedFrame, "wxHtmlWindow", "getRelatedFrame", 1}, // 3446
+ {wxHtmlWindow_HistoryBack, "wxHtmlWindow", "historyBack", 1}, // 3447
+ {wxHtmlWindow_HistoryCanBack, "wxHtmlWindow", "historyCanBack", 1}, // 3448
+ {wxHtmlWindow_HistoryCanForward, "wxHtmlWindow", "historyCanForward", 1}, // 3449
+ {wxHtmlWindow_HistoryClear, "wxHtmlWindow", "historyClear", 1}, // 3450
+ {wxHtmlWindow_HistoryForward, "wxHtmlWindow", "historyForward", 1}, // 3451
+ {wxHtmlWindow_LoadFile, "wxHtmlWindow", "loadFile", 2}, // 3452
+ {wxHtmlWindow_LoadPage, "wxHtmlWindow", "loadPage", 2}, // 3453
+ {wxHtmlWindow_SelectAll, "wxHtmlWindow", "selectAll", 1}, // 3454
+ {wxHtmlWindow_SelectionToText, "wxHtmlWindow", "selectionToText", 1}, // 3455
+ {wxHtmlWindow_SelectLine, "wxHtmlWindow", "selectLine", 2}, // 3456
+ {wxHtmlWindow_SelectWord, "wxHtmlWindow", "selectWord", 2}, // 3457
+ {wxHtmlWindow_SetBorders, "wxHtmlWindow", "setBorders", 2}, // 3458
+ {wxHtmlWindow_SetFonts, "wxHtmlWindow", "setFonts", 4}, // 3459
+ {wxHtmlWindow_SetPage, "wxHtmlWindow", "setPage", 2}, // 3460
+ {wxHtmlWindow_SetRelatedFrame, "wxHtmlWindow", "setRelatedFrame", 3}, // 3461
+ {wxHtmlWindow_SetRelatedStatusBar_1, "wxHtmlWindow", "setRelatedStatusBar", 2}, // 3462
+ {wxHtmlWindow_SetRelatedStatusBar_2, "wxHtmlWindow", "setRelatedStatusBar", 3}, // 3463
+ {wxHtmlWindow_ToText, "wxHtmlWindow", "toText", 1}, // 3464
+ {NULL, "wxHtmlWindow", "'Destroy'", 1}, // 3465 obj destructor wxHtmlWindow_destroy
+ {wxHtmlLinkEvent_GetLinkInfo, "wxHtmlLinkEvent", "getLinkInfo", 1}, // 3466
+ {wxSystemSettings_GetColour, "wxSystemSettings", "getColour", 1}, // 3467
+ {wxSystemSettings_GetFont, "wxSystemSettings", "getFont", 1}, // 3468
+ {wxSystemSettings_GetMetric, "wxSystemSettings", "getMetric", 2}, // 3469
+ {wxSystemSettings_GetScreenType, "wxSystemSettings", "getScreenType", 0}, // 3470
+ {wxSystemOptions_GetOption, "wxSystemOptions", "getOption", 1}, // 3471
+ {wxSystemOptions_GetOptionInt, "wxSystemOptions", "getOptionInt", 1}, // 3472
+ {wxSystemOptions_HasOption, "wxSystemOptions", "hasOption", 1}, // 3473
+ {wxSystemOptions_IsFalse, "wxSystemOptions", "isFalse", 1}, // 3474
+ {wxSystemOptions_SetOption_2_1, "wxSystemOptions", "setOption", 2}, // 3475
+ {wxSystemOptions_SetOption_2_0, "wxSystemOptions", "setOption", 2}, // 3476
+ {wxAuiNotebookEvent_SetSelection, "wxAuiNotebookEvent", "setSelection", 2}, // 3477
+ {wxAuiNotebookEvent_GetSelection, "wxAuiNotebookEvent", "getSelection", 1}, // 3478
+ {wxAuiNotebookEvent_SetOldSelection, "wxAuiNotebookEvent", "setOldSelection", 2}, // 3479
+ {wxAuiNotebookEvent_GetOldSelection, "wxAuiNotebookEvent", "getOldSelection", 1}, // 3480
+ {wxAuiNotebookEvent_SetDragSource, "wxAuiNotebookEvent", "setDragSource", 2}, // 3481
+ {wxAuiNotebookEvent_GetDragSource, "wxAuiNotebookEvent", "getDragSource", 1}, // 3482
+ {wxAuiManagerEvent_SetManager, "wxAuiManagerEvent", "setManager", 2}, // 3483
+ {wxAuiManagerEvent_GetManager, "wxAuiManagerEvent", "getManager", 1}, // 3484
+ {wxAuiManagerEvent_SetPane, "wxAuiManagerEvent", "setPane", 2}, // 3485
+ {wxAuiManagerEvent_GetPane, "wxAuiManagerEvent", "getPane", 1}, // 3486
+ {wxAuiManagerEvent_SetButton, "wxAuiManagerEvent", "setButton", 2}, // 3487
+ {wxAuiManagerEvent_GetButton, "wxAuiManagerEvent", "getButton", 1}, // 3488
+ {wxAuiManagerEvent_SetDC, "wxAuiManagerEvent", "setDC", 2}, // 3489
+ {wxAuiManagerEvent_GetDC, "wxAuiManagerEvent", "getDC", 1}, // 3490
+ {wxAuiManagerEvent_Veto, "wxAuiManagerEvent", "veto", 2}, // 3491
+ {wxAuiManagerEvent_GetVeto, "wxAuiManagerEvent", "getVeto", 1}, // 3492
+ {wxAuiManagerEvent_SetCanVeto, "wxAuiManagerEvent", "setCanVeto", 2}, // 3493
+ {wxAuiManagerEvent_CanVeto, "wxAuiManagerEvent", "canVeto", 1}, // 3494
+ {wxLogNull_new, "wxLogNull", "new", 0}, // 3495
+ {wxLogNull_destruct, "wxLogNull", "destroy", 1}, // 3496
+ {wxTaskBarIcon_new, "wxTaskBarIcon", "new", 1}, // 3497
+ {NULL, "wxTaskBarIcon", "destroy", 1}, // 3498 obj destructor wxTaskBarIcon_destruct
+ {wxTaskBarIcon_PopupMenu, "wxTaskBarIcon", "popupMenu", 2}, // 3499
+ {wxTaskBarIcon_RemoveIcon, "wxTaskBarIcon", "removeIcon", 1}, // 3500
+ {wxTaskBarIcon_SetIcon, "wxTaskBarIcon", "setIcon", 3}, // 3501
+ {wxLocale_new_0, "wxLocale", "new", 0}, // 3502
+ {wxLocale_new_2_0, "wxLocale", "new", 2}, // 3503
+ {wxLocale_new_2_1, "wxLocale", "new", 2}, // 3504
+ {wxLocale_destruct, "wxLocale", "destroy", 1}, // 3505
+ {wxLocale_Init_1, "wxLocale", "init", 2}, // 3506
+ {wxLocale_Init_2, "wxLocale", "init", 3}, // 3507
+ {wxLocale_AddCatalog_1, "wxLocale", "addCatalog", 2}, // 3508
+ {wxLocale_AddCatalog_2, "wxLocale", "addCatalog", 3}, // 3509
+ {wxLocale_AddCatalog_3, "wxLocale", "addCatalog", 4}, // 3510
+ {wxLocale_AddCatalogLookupPathPrefix, "wxLocale", "addCatalogLookupPathPrefix", 1}, // 3511
+ {wxLocale_GetCanonicalName, "wxLocale", "getCanonicalName", 1}, // 3512
+ {wxLocale_GetLanguage, "wxLocale", "getLanguage", 1}, // 3513
+ {wxLocale_GetLanguageName, "wxLocale", "getLanguageName", 1}, // 3514
+ {wxLocale_GetLocale, "wxLocale", "getLocale", 1}, // 3515
+ {wxLocale_GetName, "wxLocale", "getName", 1}, // 3516
+ {wxLocale_GetString_2, "wxLocale", "getString", 3}, // 3517
+ {wxLocale_GetString_4, "wxLocale", "getString", 5}, // 3518
+ {wxLocale_GetHeaderValue, "wxLocale", "getHeaderValue", 3}, // 3519
+ {wxLocale_GetSysName, "wxLocale", "getSysName", 1}, // 3520
+ {wxLocale_GetSystemEncoding, "wxLocale", "getSystemEncoding", 0}, // 3521
+ {wxLocale_GetSystemEncodingName, "wxLocale", "getSystemEncodingName", 0}, // 3522
+ {wxLocale_GetSystemLanguage, "wxLocale", "getSystemLanguage", 0}, // 3523
+ {wxLocale_IsLoaded, "wxLocale", "isLoaded", 2}, // 3524
+ {wxLocale_IsOk, "wxLocale", "isOk", 1}, // 3525
+ {wxActivateEvent_GetActive, "wxActivateEvent", "getActive", 1}, // 3526
#if wxUSE_POPUPWIN
- {wxPopupWindow_new_0, "wxPopupWindow", "new", 0}, // 3519
+ {wxPopupWindow_new_0, "wxPopupWindow", "new", 0}, // 3527
#else
- {NULL, "wxPopupWindow", "new", 0}, // 3519
+ {NULL, "wxPopupWindow", "new", 0}, // 3527
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupWindow_new_2, "wxPopupWindow", "new", 2}, // 3520
+ {wxPopupWindow_new_2, "wxPopupWindow", "new", 2}, // 3528
#else
- {NULL, "wxPopupWindow", "new", 0}, // 3520
+ {NULL, "wxPopupWindow", "new", 0}, // 3528
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupWindow_Create, "wxPopupWindow", "create", 3}, // 3521
+ {wxPopupWindow_Create, "wxPopupWindow", "create", 3}, // 3529
#else
- {NULL, "wxPopupWindow", "create", 0}, // 3521
+ {NULL, "wxPopupWindow", "create", 0}, // 3529
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupWindow_Position, "wxPopupWindow", "position", 3}, // 3522
+ {wxPopupWindow_Position, "wxPopupWindow", "position", 3}, // 3530
#else
- {NULL, "wxPopupWindow", "position", 0}, // 3522
+ {NULL, "wxPopupWindow", "position", 0}, // 3530
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {NULL, "wxPopupWindow", "'Destroy'", 1}, // 3523 obj destructor wxPopupWindow_destroy
+ {NULL, "wxPopupWindow", "'Destroy'", 1}, // 3531 obj destructor wxPopupWindow_destroy
#else
- {NULL, "wxPopupWindow", "'Destroy'", 0}, // 3523
+ {NULL, "wxPopupWindow", "'Destroy'", 0}, // 3531
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_new_0, "wxPopupTransientWindow", "new", 0}, // 3524
+ {wxPopupTransientWindow_new_0, "wxPopupTransientWindow", "new", 0}, // 3532
#else
- {NULL, "wxPopupTransientWindow", "new", 0}, // 3524
+ {NULL, "wxPopupTransientWindow", "new", 0}, // 3532
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_new_2, "wxPopupTransientWindow", "new", 2}, // 3525
+ {wxPopupTransientWindow_new_2, "wxPopupTransientWindow", "new", 2}, // 3533
#else
- {NULL, "wxPopupTransientWindow", "new", 0}, // 3525
+ {NULL, "wxPopupTransientWindow", "new", 0}, // 3533
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_Popup, "wxPopupTransientWindow", "popup", 2}, // 3526
+ {wxPopupTransientWindow_Popup, "wxPopupTransientWindow", "popup", 2}, // 3534
#else
- {NULL, "wxPopupTransientWindow", "popup", 0}, // 3526
+ {NULL, "wxPopupTransientWindow", "popup", 0}, // 3534
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {wxPopupTransientWindow_Dismiss, "wxPopupTransientWindow", "dismiss", 1}, // 3527
+ {wxPopupTransientWindow_Dismiss, "wxPopupTransientWindow", "dismiss", 1}, // 3535
#else
- {NULL, "wxPopupTransientWindow", "dismiss", 0}, // 3527
+ {NULL, "wxPopupTransientWindow", "dismiss", 0}, // 3535
#endif // wxUSE_POPUPWIN
#if wxUSE_POPUPWIN
- {NULL, "wxPopupTransientWindow", "'Destroy'", 1}, // 3528 obj destructor wxPopupTransientWindow_destroy
+ {NULL, "wxPopupTransientWindow", "'Destroy'", 1}, // 3536 obj destructor wxPopupTransientWindow_destroy
#else
- {NULL, "wxPopupTransientWindow", "'Destroy'", 0}, // 3528
+ {NULL, "wxPopupTransientWindow", "'Destroy'", 0}, // 3536
#endif // wxUSE_POPUPWIN
- {wxOverlay_new, "wxOverlay", "new", 0}, // 3529
- {wxOverlay_destruct, "wxOverlay", "destroy", 1}, // 3530
- {wxOverlay_Reset, "wxOverlay", "reset", 1}, // 3531
- {wxDCOverlay_new_6, "wxDCOverlay", "new", 6}, // 3532
- {wxDCOverlay_new_2, "wxDCOverlay", "new", 2}, // 3533
- {wxDCOverlay_destruct, "wxDCOverlay", "destroy", 1}, // 3534
- {wxDCOverlay_Clear, "wxDCOverlay", "clear", 1}, // 3535
- {wxDropFilesEvent_GetPosition, "wxDropFilesEvent", "getPosition", 1}, // 3536
- {wxDropFilesEvent_GetNumberOfFiles, "wxDropFilesEvent", "getNumberOfFiles", 1}, // 3537
- {wxDropFilesEvent_GetFiles, "wxDropFilesEvent", "getFiles", 1}, // 3538
+ {wxOverlay_new, "wxOverlay", "new", 0}, // 3537
+ {wxOverlay_destruct, "wxOverlay", "destroy", 1}, // 3538
+ {wxOverlay_Reset, "wxOverlay", "reset", 1}, // 3539
+ {wxDCOverlay_new_6, "wxDCOverlay", "new", 6}, // 3540
+ {wxDCOverlay_new_2, "wxDCOverlay", "new", 2}, // 3541
+ {wxDCOverlay_destruct, "wxDCOverlay", "destroy", 1}, // 3542
+ {wxDCOverlay_Clear, "wxDCOverlay", "clear", 1}, // 3543
+ {wxDropFilesEvent_GetPosition, "wxDropFilesEvent", "getPosition", 1}, // 3544
+ {wxDropFilesEvent_GetNumberOfFiles, "wxDropFilesEvent", "getNumberOfFiles", 1}, // 3545
+ {wxDropFilesEvent_GetFiles, "wxDropFilesEvent", "getFiles", 1}, // 3546
#if wxUSE_DISPLAY
- {wxDisplay_new_0, "wxDisplay", "new", 0}, // 3539
+ {wxDisplay_new_0, "wxDisplay", "new", 0}, // 3547
#else
- {NULL, "wxDisplay", "new", 0}, // 3539
+ {NULL, "wxDisplay", "new", 0}, // 3547
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_new_1_0, "wxDisplay", "new", 1}, // 3540
+ {wxDisplay_new_1_0, "wxDisplay", "new", 1}, // 3548
#else
- {NULL, "wxDisplay", "new", 0}, // 3540
+ {NULL, "wxDisplay", "new", 0}, // 3548
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY && wxCHECK_VERSION(3,1,3)
- {wxDisplay_new_1_1, "wxDisplay", "new", 1}, // 3541
+ {wxDisplay_new_1_1, "wxDisplay", "new", 1}, // 3549
#else
- {NULL, "wxDisplay", "new", 0}, // 3541
+ {NULL, "wxDisplay", "new", 0}, // 3549
#endif // wxUSE_DISPLAY && wxCHECK_VERSION(3,1,3)
#if wxUSE_DISPLAY
- {wxDisplay_destruct, "wxDisplay", "destroy", 1}, // 3542
+ {wxDisplay_destruct, "wxDisplay", "destroy", 1}, // 3550
#else
- {NULL, "wxDisplay", "destroy", 0}, // 3542
+ {NULL, "wxDisplay", "destroy", 0}, // 3550
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_IsOk, "wxDisplay", "isOk", 1}, // 3543
+ {wxDisplay_IsOk, "wxDisplay", "isOk", 1}, // 3551
#else
- {NULL, "wxDisplay", "isOk", 0}, // 3543
+ {NULL, "wxDisplay", "isOk", 0}, // 3551
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetClientArea, "wxDisplay", "getClientArea", 1}, // 3544
+ {wxDisplay_GetClientArea, "wxDisplay", "getClientArea", 1}, // 3552
#else
- {NULL, "wxDisplay", "getClientArea", 0}, // 3544
+ {NULL, "wxDisplay", "getClientArea", 0}, // 3552
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetGeometry, "wxDisplay", "getGeometry", 1}, // 3545
+ {wxDisplay_GetGeometry, "wxDisplay", "getGeometry", 1}, // 3553
#else
- {NULL, "wxDisplay", "getGeometry", 0}, // 3545
+ {NULL, "wxDisplay", "getGeometry", 0}, // 3553
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetName, "wxDisplay", "getName", 1}, // 3546
+ {wxDisplay_GetName, "wxDisplay", "getName", 1}, // 3554
#else
- {NULL, "wxDisplay", "getName", 0}, // 3546
+ {NULL, "wxDisplay", "getName", 0}, // 3554
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_IsPrimary, "wxDisplay", "isPrimary", 1}, // 3547
+ {wxDisplay_IsPrimary, "wxDisplay", "isPrimary", 1}, // 3555
#else
- {NULL, "wxDisplay", "isPrimary", 0}, // 3547
+ {NULL, "wxDisplay", "isPrimary", 0}, // 3555
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetCount, "wxDisplay", "getCount", 0}, // 3548
+ {wxDisplay_GetCount, "wxDisplay", "getCount", 0}, // 3556
#else
- {NULL, "wxDisplay", "getCount", 0}, // 3548
+ {NULL, "wxDisplay", "getCount", 0}, // 3556
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetFromPoint, "wxDisplay", "getFromPoint", 1}, // 3549
+ {wxDisplay_GetFromPoint, "wxDisplay", "getFromPoint", 1}, // 3557
#else
- {NULL, "wxDisplay", "getFromPoint", 0}, // 3549
+ {NULL, "wxDisplay", "getFromPoint", 0}, // 3557
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY
- {wxDisplay_GetFromWindow, "wxDisplay", "getFromWindow", 1}, // 3550
+ {wxDisplay_GetFromWindow, "wxDisplay", "getFromWindow", 1}, // 3558
#else
- {NULL, "wxDisplay", "getFromWindow", 0}, // 3550
+ {NULL, "wxDisplay", "getFromWindow", 0}, // 3558
#endif // wxUSE_DISPLAY
#if wxUSE_DISPLAY && wxCHECK_VERSION(3,1,2)
- {wxDisplay_GetPPI, "wxDisplay", "getPPI", 1}, // 3551
+ {wxDisplay_GetPPI, "wxDisplay", "getPPI", 1}, // 3559
#else
- {NULL, "wxDisplay", "getPPI", 0}, // 3551
+ {NULL, "wxDisplay", "getPPI", 0}, // 3559
#endif // wxUSE_DISPLAY && wxCHECK_VERSION(3,1,2)
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_new_1, "wxGCDC", "new", 1}, // 3552
+ {wxGCDC_new_1, "wxGCDC", "new", 1}, // 3560
#else
- {NULL, "wxGCDC", "new", 0}, // 3552
+ {NULL, "wxGCDC", "new", 0}, // 3560
#endif // wxUSE_GRAPHICS_CONTEXT
- {NULL, "", "", 0}, // 3553
- {NULL, "", "", 0}, // 3554
+ {NULL, "", "", 0}, // 3561
+ {NULL, "", "", 0}, // 3562
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_new_0, "wxGCDC", "new", 0}, // 3555
+ {wxGCDC_new_0, "wxGCDC", "new", 0}, // 3563
#else
- {NULL, "wxGCDC", "new", 0}, // 3555
+ {NULL, "wxGCDC", "new", 0}, // 3563
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_GRAPHICS_CONTEXT
- {NULL, "wxGCDC", "destroy", 1}, // 3556 obj destructor wxGCDC_destruct
+ {NULL, "wxGCDC", "destroy", 1}, // 3564 obj destructor wxGCDC_destruct
#else
- {NULL, "wxGCDC", "destroy", 0}, // 3556
+ {NULL, "wxGCDC", "destroy", 0}, // 3564
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_GetGraphicsContext, "wxGCDC", "getGraphicsContext", 1}, // 3557
+ {wxGCDC_GetGraphicsContext, "wxGCDC", "getGraphicsContext", 1}, // 3565
#else
- {NULL, "wxGCDC", "getGraphicsContext", 0}, // 3557
+ {NULL, "wxGCDC", "getGraphicsContext", 0}, // 3565
#endif // wxUSE_GRAPHICS_CONTEXT
#if wxUSE_GRAPHICS_CONTEXT
- {wxGCDC_SetGraphicsContext, "wxGCDC", "setGraphicsContext", 2}, // 3558
+ {wxGCDC_SetGraphicsContext, "wxGCDC", "setGraphicsContext", 2}, // 3566
#else
- {NULL, "wxGCDC", "setGraphicsContext", 0}, // 3558
+ {NULL, "wxGCDC", "setGraphicsContext", 0}, // 3566
#endif // wxUSE_GRAPHICS_CONTEXT
- {wxNotificationMessage_new_0, "wxNotificationMessage", "new", 0}, // 3559
- {wxNotificationMessage_new_2, "wxNotificationMessage", "new", 2}, // 3560
- {NULL, "wxNotificationMessage", "destroy", 1}, // 3561 obj destructor wxNotificationMessage_destruct
+ {wxNotificationMessage_new_0, "wxNotificationMessage", "new", 0}, // 3567
+ {wxNotificationMessage_new_2, "wxNotificationMessage", "new", 2}, // 3568
+ {NULL, "wxNotificationMessage", "destroy", 1}, // 3569 obj destructor wxNotificationMessage_destruct
#if wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_AddAction, "wxNotificationMessage", "addAction", 3}, // 3562
+ {wxNotificationMessage_AddAction, "wxNotificationMessage", "addAction", 3}, // 3570
#else
- {NULL, "wxNotificationMessage", "addAction", 0}, // 3562
+ {NULL, "wxNotificationMessage", "addAction", 0}, // 3570
#endif // wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_Close, "wxNotificationMessage", "close", 1}, // 3563
- {wxNotificationMessage_SetFlags, "wxNotificationMessage", "setFlags", 2}, // 3564
+ {wxNotificationMessage_Close, "wxNotificationMessage", "close", 1}, // 3571
+ {wxNotificationMessage_SetFlags, "wxNotificationMessage", "setFlags", 2}, // 3572
#if wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_SetIcon, "wxNotificationMessage", "setIcon", 2}, // 3565
+ {wxNotificationMessage_SetIcon, "wxNotificationMessage", "setIcon", 2}, // 3573
#else
- {NULL, "wxNotificationMessage", "setIcon", 0}, // 3565
+ {NULL, "wxNotificationMessage", "setIcon", 0}, // 3573
#endif // wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_SetMessage, "wxNotificationMessage", "setMessage", 2}, // 3566
- {wxNotificationMessage_SetParent, "wxNotificationMessage", "setParent", 2}, // 3567
- {wxNotificationMessage_SetTitle, "wxNotificationMessage", "setTitle", 2}, // 3568
- {wxNotificationMessage_Show, "wxNotificationMessage", "show", 2}, // 3569
+ {wxNotificationMessage_SetMessage, "wxNotificationMessage", "setMessage", 2}, // 3574
+ {wxNotificationMessage_SetParent, "wxNotificationMessage", "setParent", 2}, // 3575
+ {wxNotificationMessage_SetTitle, "wxNotificationMessage", "setTitle", 2}, // 3576
+ {wxNotificationMessage_Show, "wxNotificationMessage", "show", 2}, // 3577
#if __WXMSW__
- {wxNotificationMessage_UseTaskBarIcon, "wxNotificationMessage", "useTaskBarIcon", 1}, // 3570
+ {wxNotificationMessage_UseTaskBarIcon, "wxNotificationMessage", "useTaskBarIcon", 1}, // 3578
#else
- {NULL, "wxNotificationMessage", "useTaskBarIcon", 0}, // 3570
+ {NULL, "wxNotificationMessage", "useTaskBarIcon", 0}, // 3578
#endif // __WXMSW__
#if __WXMSW__ && wxCHECK_VERSION(3,1,0)
- {wxNotificationMessage_MSWUseToasts, "wxNotificationMessage", "mSWUseToasts", 1}, // 3571
+ {wxNotificationMessage_MSWUseToasts, "wxNotificationMessage", "mSWUseToasts", 1}, // 3579
#else
- {NULL, "wxNotificationMessage", "mSWUseToasts", 0}, // 3571
+ {NULL, "wxNotificationMessage", "mSWUseToasts", 0}, // 3579
#endif // __WXMSW__ && wxCHECK_VERSION(3,1,0)
- {NULL, "", "", 0}, // 3572
+ {NULL, "", "", 0}, // 3580
#if WXE_WEBVIEW
- {wxWebView_New, "wxWebView", "new", 3}, // 3573
+ {wxWebView_New, "wxWebView", "new", 3}, // 3581
#else
- {NULL, "wxWebView", "new", 0}, // 3573
+ {NULL, "wxWebView", "new", 0}, // 3581
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetCurrentTitle, "wxWebView", "getCurrentTitle", 1}, // 3574
+ {wxWebView_GetCurrentTitle, "wxWebView", "getCurrentTitle", 1}, // 3582
#else
- {NULL, "wxWebView", "getCurrentTitle", 0}, // 3574
+ {NULL, "wxWebView", "getCurrentTitle", 0}, // 3582
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetCurrentURL, "wxWebView", "getCurrentURL", 1}, // 3575
+ {wxWebView_GetCurrentURL, "wxWebView", "getCurrentURL", 1}, // 3583
#else
- {NULL, "wxWebView", "getCurrentURL", 0}, // 3575
+ {NULL, "wxWebView", "getCurrentURL", 0}, // 3583
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetPageSource, "wxWebView", "getPageSource", 1}, // 3576
+ {wxWebView_GetPageSource, "wxWebView", "getPageSource", 1}, // 3584
#else
- {NULL, "wxWebView", "getPageSource", 0}, // 3576
+ {NULL, "wxWebView", "getPageSource", 0}, // 3584
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetPageText, "wxWebView", "getPageText", 1}, // 3577
+ {wxWebView_GetPageText, "wxWebView", "getPageText", 1}, // 3585
#else
- {NULL, "wxWebView", "getPageText", 0}, // 3577
+ {NULL, "wxWebView", "getPageText", 0}, // 3585
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_IsBusy, "wxWebView", "isBusy", 1}, // 3578
+ {wxWebView_IsBusy, "wxWebView", "isBusy", 1}, // 3586
#else
- {NULL, "wxWebView", "isBusy", 0}, // 3578
+ {NULL, "wxWebView", "isBusy", 0}, // 3586
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_IsEditable, "wxWebView", "isEditable", 1}, // 3579
+ {wxWebView_IsEditable, "wxWebView", "isEditable", 1}, // 3587
#else
- {NULL, "wxWebView", "isEditable", 0}, // 3579
+ {NULL, "wxWebView", "isEditable", 0}, // 3587
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_LoadURL, "wxWebView", "loadURL", 2}, // 3580
+ {wxWebView_LoadURL, "wxWebView", "loadURL", 2}, // 3588
#else
- {NULL, "wxWebView", "loadURL", 0}, // 3580
+ {NULL, "wxWebView", "loadURL", 0}, // 3588
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Print, "wxWebView", "print", 1}, // 3581
+ {wxWebView_Print, "wxWebView", "print", 1}, // 3589
#else
- {NULL, "wxWebView", "print", 0}, // 3581
+ {NULL, "wxWebView", "print", 0}, // 3589
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Reload, "wxWebView", "reload", 2}, // 3582
+ {wxWebView_Reload, "wxWebView", "reload", 2}, // 3590
#else
- {NULL, "wxWebView", "reload", 0}, // 3582
+ {NULL, "wxWebView", "reload", 0}, // 3590
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,1)
- {wxWebView_RunScript, "wxWebView", "runScript", 2}, // 3583
+ {wxWebView_RunScript, "wxWebView", "runScript", 2}, // 3591
#else
- {NULL, "wxWebView", "runScript", 0}, // 3583
+ {NULL, "wxWebView", "runScript", 0}, // 3591
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,1)
#if WXE_WEBVIEW
- {wxWebView_SetEditable, "wxWebView", "setEditable", 2}, // 3584
+ {wxWebView_SetEditable, "wxWebView", "setEditable", 2}, // 3592
#else
- {NULL, "wxWebView", "setEditable", 0}, // 3584
+ {NULL, "wxWebView", "setEditable", 0}, // 3592
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SetPage, "wxWebView", "setPage", 3}, // 3585
+ {wxWebView_SetPage, "wxWebView", "setPage", 3}, // 3593
#else
- {NULL, "wxWebView", "setPage", 0}, // 3585
+ {NULL, "wxWebView", "setPage", 0}, // 3593
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Stop, "wxWebView", "stop", 1}, // 3586
+ {wxWebView_Stop, "wxWebView", "stop", 1}, // 3594
#else
- {NULL, "wxWebView", "stop", 0}, // 3586
+ {NULL, "wxWebView", "stop", 0}, // 3594
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanCopy, "wxWebView", "canCopy", 1}, // 3587
+ {wxWebView_CanCopy, "wxWebView", "canCopy", 1}, // 3595
#else
- {NULL, "wxWebView", "canCopy", 0}, // 3587
+ {NULL, "wxWebView", "canCopy", 0}, // 3595
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanCut, "wxWebView", "canCut", 1}, // 3588
+ {wxWebView_CanCut, "wxWebView", "canCut", 1}, // 3596
#else
- {NULL, "wxWebView", "canCut", 0}, // 3588
+ {NULL, "wxWebView", "canCut", 0}, // 3596
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanPaste, "wxWebView", "canPaste", 1}, // 3589
+ {wxWebView_CanPaste, "wxWebView", "canPaste", 1}, // 3597
#else
- {NULL, "wxWebView", "canPaste", 0}, // 3589
+ {NULL, "wxWebView", "canPaste", 0}, // 3597
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Copy, "wxWebView", "copy", 1}, // 3590
+ {wxWebView_Copy, "wxWebView", "copy", 1}, // 3598
#else
- {NULL, "wxWebView", "copy", 0}, // 3590
+ {NULL, "wxWebView", "copy", 0}, // 3598
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Cut, "wxWebView", "cut", 1}, // 3591
+ {wxWebView_Cut, "wxWebView", "cut", 1}, // 3599
#else
- {NULL, "wxWebView", "cut", 0}, // 3591
+ {NULL, "wxWebView", "cut", 0}, // 3599
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Paste, "wxWebView", "paste", 1}, // 3592
+ {wxWebView_Paste, "wxWebView", "paste", 1}, // 3600
#else
- {NULL, "wxWebView", "paste", 0}, // 3592
+ {NULL, "wxWebView", "paste", 0}, // 3600
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_EnableContextMenu, "wxWebView", "enableContextMenu", 2}, // 3593
+ {wxWebView_EnableContextMenu, "wxWebView", "enableContextMenu", 2}, // 3601
#else
- {NULL, "wxWebView", "enableContextMenu", 0}, // 3593
+ {NULL, "wxWebView", "enableContextMenu", 0}, // 3601
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_IsContextMenuEnabled, "wxWebView", "isContextMenuEnabled", 1}, // 3594
+ {wxWebView_IsContextMenuEnabled, "wxWebView", "isContextMenuEnabled", 1}, // 3602
#else
- {NULL, "wxWebView", "isContextMenuEnabled", 0}, // 3594
+ {NULL, "wxWebView", "isContextMenuEnabled", 0}, // 3602
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanGoBack, "wxWebView", "canGoBack", 1}, // 3595
+ {wxWebView_CanGoBack, "wxWebView", "canGoBack", 1}, // 3603
#else
- {NULL, "wxWebView", "canGoBack", 0}, // 3595
+ {NULL, "wxWebView", "canGoBack", 0}, // 3603
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanGoForward, "wxWebView", "canGoForward", 1}, // 3596
+ {wxWebView_CanGoForward, "wxWebView", "canGoForward", 1}, // 3604
#else
- {NULL, "wxWebView", "canGoForward", 0}, // 3596
+ {NULL, "wxWebView", "canGoForward", 0}, // 3604
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_ClearHistory, "wxWebView", "clearHistory", 1}, // 3597
+ {wxWebView_ClearHistory, "wxWebView", "clearHistory", 1}, // 3605
#else
- {NULL, "wxWebView", "clearHistory", 0}, // 3597
+ {NULL, "wxWebView", "clearHistory", 0}, // 3605
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_EnableHistory, "wxWebView", "enableHistory", 2}, // 3598
+ {wxWebView_EnableHistory, "wxWebView", "enableHistory", 2}, // 3606
#else
- {NULL, "wxWebView", "enableHistory", 0}, // 3598
+ {NULL, "wxWebView", "enableHistory", 0}, // 3606
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GoBack, "wxWebView", "goBack", 1}, // 3599
+ {wxWebView_GoBack, "wxWebView", "goBack", 1}, // 3607
#else
- {NULL, "wxWebView", "goBack", 0}, // 3599
+ {NULL, "wxWebView", "goBack", 0}, // 3607
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GoForward, "wxWebView", "goForward", 1}, // 3600
+ {wxWebView_GoForward, "wxWebView", "goForward", 1}, // 3608
#else
- {NULL, "wxWebView", "goForward", 0}, // 3600
+ {NULL, "wxWebView", "goForward", 0}, // 3608
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_ClearSelection, "wxWebView", "clearSelection", 1}, // 3601
+ {wxWebView_ClearSelection, "wxWebView", "clearSelection", 1}, // 3609
#else
- {NULL, "wxWebView", "clearSelection", 0}, // 3601
+ {NULL, "wxWebView", "clearSelection", 0}, // 3609
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_DeleteSelection, "wxWebView", "deleteSelection", 1}, // 3602
+ {wxWebView_DeleteSelection, "wxWebView", "deleteSelection", 1}, // 3610
#else
- {NULL, "wxWebView", "deleteSelection", 0}, // 3602
+ {NULL, "wxWebView", "deleteSelection", 0}, // 3610
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetSelectedSource, "wxWebView", "getSelectedSource", 1}, // 3603
+ {wxWebView_GetSelectedSource, "wxWebView", "getSelectedSource", 1}, // 3611
#else
- {NULL, "wxWebView", "getSelectedSource", 0}, // 3603
+ {NULL, "wxWebView", "getSelectedSource", 0}, // 3611
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetSelectedText, "wxWebView", "getSelectedText", 1}, // 3604
+ {wxWebView_GetSelectedText, "wxWebView", "getSelectedText", 1}, // 3612
#else
- {NULL, "wxWebView", "getSelectedText", 0}, // 3604
+ {NULL, "wxWebView", "getSelectedText", 0}, // 3612
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_HasSelection, "wxWebView", "hasSelection", 1}, // 3605
+ {wxWebView_HasSelection, "wxWebView", "hasSelection", 1}, // 3613
#else
- {NULL, "wxWebView", "hasSelection", 0}, // 3605
+ {NULL, "wxWebView", "hasSelection", 0}, // 3613
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SelectAll, "wxWebView", "selectAll", 1}, // 3606
+ {wxWebView_SelectAll, "wxWebView", "selectAll", 1}, // 3614
#else
- {NULL, "wxWebView", "selectAll", 0}, // 3606
+ {NULL, "wxWebView", "selectAll", 0}, // 3614
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanRedo, "wxWebView", "canRedo", 1}, // 3607
+ {wxWebView_CanRedo, "wxWebView", "canRedo", 1}, // 3615
#else
- {NULL, "wxWebView", "canRedo", 0}, // 3607
+ {NULL, "wxWebView", "canRedo", 0}, // 3615
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanUndo, "wxWebView", "canUndo", 1}, // 3608
+ {wxWebView_CanUndo, "wxWebView", "canUndo", 1}, // 3616
#else
- {NULL, "wxWebView", "canUndo", 0}, // 3608
+ {NULL, "wxWebView", "canUndo", 0}, // 3616
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Redo, "wxWebView", "redo", 1}, // 3609
+ {wxWebView_Redo, "wxWebView", "redo", 1}, // 3617
#else
- {NULL, "wxWebView", "redo", 0}, // 3609
+ {NULL, "wxWebView", "redo", 0}, // 3617
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Undo, "wxWebView", "undo", 1}, // 3610
+ {wxWebView_Undo, "wxWebView", "undo", 1}, // 3618
#else
- {NULL, "wxWebView", "undo", 0}, // 3610
+ {NULL, "wxWebView", "undo", 0}, // 3618
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_Find, "wxWebView", "find", 3}, // 3611
+ {wxWebView_Find, "wxWebView", "find", 3}, // 3619
#else
- {NULL, "wxWebView", "find", 0}, // 3611
+ {NULL, "wxWebView", "find", 0}, // 3619
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_CanSetZoomType, "wxWebView", "canSetZoomType", 2}, // 3612
+ {wxWebView_CanSetZoomType, "wxWebView", "canSetZoomType", 2}, // 3620
#else
- {NULL, "wxWebView", "canSetZoomType", 0}, // 3612
+ {NULL, "wxWebView", "canSetZoomType", 0}, // 3620
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetZoom, "wxWebView", "getZoom", 1}, // 3613
+ {wxWebView_GetZoom, "wxWebView", "getZoom", 1}, // 3621
#else
- {NULL, "wxWebView", "getZoom", 0}, // 3613
+ {NULL, "wxWebView", "getZoom", 0}, // 3621
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_GetZoomType, "wxWebView", "getZoomType", 1}, // 3614
+ {wxWebView_GetZoomType, "wxWebView", "getZoomType", 1}, // 3622
#else
- {NULL, "wxWebView", "getZoomType", 0}, // 3614
+ {NULL, "wxWebView", "getZoomType", 0}, // 3622
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SetZoom, "wxWebView", "setZoom", 2}, // 3615
+ {wxWebView_SetZoom, "wxWebView", "setZoom", 2}, // 3623
#else
- {NULL, "wxWebView", "setZoom", 0}, // 3615
+ {NULL, "wxWebView", "setZoom", 0}, // 3623
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebView_SetZoomType, "wxWebView", "setZoomType", 2}, // 3616
+ {wxWebView_SetZoomType, "wxWebView", "setZoomType", 2}, // 3624
#else
- {NULL, "wxWebView", "setZoomType", 0}, // 3616
+ {NULL, "wxWebView", "setZoomType", 0}, // 3624
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
- {wxWebView_GetZoomFactor, "wxWebView", "getZoomFactor", 1}, // 3617
+ {wxWebView_GetZoomFactor, "wxWebView", "getZoomFactor", 1}, // 3625
#else
- {NULL, "wxWebView", "getZoomFactor", 0}, // 3617
+ {NULL, "wxWebView", "getZoomFactor", 0}, // 3625
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
- {wxWebView_SetZoomFactor, "wxWebView", "setZoomFactor", 2}, // 3618
+ {wxWebView_SetZoomFactor, "wxWebView", "setZoomFactor", 2}, // 3626
#else
- {NULL, "wxWebView", "setZoomFactor", 0}, // 3618
+ {NULL, "wxWebView", "setZoomFactor", 0}, // 3626
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
#if WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
- {wxWebView_IsBackendAvailable, "wxWebView", "isBackendAvailable", 1}, // 3619
+ {wxWebView_IsBackendAvailable, "wxWebView", "isBackendAvailable", 1}, // 3627
#else
- {NULL, "wxWebView", "isBackendAvailable", 0}, // 3619
+ {NULL, "wxWebView", "isBackendAvailable", 0}, // 3627
#endif // WXE_WEBVIEW && wxCHECK_VERSION(3,1,4)
#if WXE_WEBVIEW
- {wxWebViewEvent_GetString, "wxWebViewEvent", "getString", 1}, // 3620
+ {wxWebViewEvent_GetString, "wxWebViewEvent", "getString", 1}, // 3628
#else
- {NULL, "wxWebViewEvent", "getString", 0}, // 3620
+ {NULL, "wxWebViewEvent", "getString", 0}, // 3628
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebViewEvent_GetInt, "wxWebViewEvent", "getInt", 1}, // 3621
+ {wxWebViewEvent_GetInt, "wxWebViewEvent", "getInt", 1}, // 3629
#else
- {NULL, "wxWebViewEvent", "getInt", 0}, // 3621
+ {NULL, "wxWebViewEvent", "getInt", 0}, // 3629
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebViewEvent_GetTarget, "wxWebViewEvent", "getTarget", 1}, // 3622
+ {wxWebViewEvent_GetTarget, "wxWebViewEvent", "getTarget", 1}, // 3630
#else
- {NULL, "wxWebViewEvent", "getTarget", 0}, // 3622
+ {NULL, "wxWebViewEvent", "getTarget", 0}, // 3630
#endif // WXE_WEBVIEW
#if WXE_WEBVIEW
- {wxWebViewEvent_GetURL, "wxWebViewEvent", "getURL", 1}, // 3623
+ {wxWebViewEvent_GetURL, "wxWebViewEvent", "getURL", 1}, // 3631
#else
- {NULL, "wxWebViewEvent", "getURL", 0}, // 3623
+ {NULL, "wxWebViewEvent", "getURL", 0}, // 3631
#endif // WXE_WEBVIEW
};
diff --git a/lib/wx/c_src/gen/wxe_init.cpp b/lib/wx/c_src/gen/wxe_init.cpp
index 12b0b418b0..4153f1e2b9 100644
--- a/lib/wx/c_src/gen/wxe_init.cpp
+++ b/lib/wx/c_src/gen/wxe_init.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -6664,6 +6664,12 @@ void WxeApp::init_consts(wxeMetaCommand& event) {
{ enif_make_atom(rt.env,"wxStandardID"), "wxID_MDI_WINDOW_PREV", rt.make_int(wxID_MDI_WINDOW_PREV) },
{ enif_make_atom(rt.env,"wxStandardID"), "wxID_MDI_WINDOW_NEXT", rt.make_int(wxID_MDI_WINDOW_NEXT) },
{ enif_make_atom(rt.env,"wxStandardID"), "wxID_MDI_WINDOW_LAST", rt.make_int(wxID_MDI_WINDOW_LAST) },
+ { enif_make_atom(rt.env,"wxStandardID"), "wxID_OSX_MENU_FIRST", rt.make_int(wxID_OSX_MENU_FIRST) },
+ { enif_make_atom(rt.env,"wxStandardID"), "wxID_OSX_HIDE", rt.make_int(wxID_OSX_HIDE) },
+ { enif_make_atom(rt.env,"wxStandardID"), "wxID_OSX_HIDEOTHERS", rt.make_int(wxID_OSX_HIDEOTHERS) },
+ { enif_make_atom(rt.env,"wxStandardID"), "wxID_OSX_SHOWALL", rt.make_int(wxID_OSX_SHOWALL) },
+ { enif_make_atom(rt.env,"wxStandardID"), "wxID_OSX_SERVICES", rt.make_int(wxID_OSX_SERVICES) },
+ { enif_make_atom(rt.env,"wxStandardID"), "wxID_OSX_MENU_LAST", rt.make_int(wxID_OSX_MENU_LAST) },
{ enif_make_atom(rt.env,"wxStandardID"), "wxID_FILEDLGG", rt.make_int(wxID_FILEDLGG) },
{ enif_make_atom(rt.env,"wxStandardID"), "wxID_FILECTRL", rt.make_int(wxID_FILECTRL) },
{ enif_make_atom(rt.env,"wxStandardID"), "wxID_HIGHEST", rt.make_int(wxID_HIGHEST) },
diff --git a/lib/wx/c_src/gen/wxe_wrapper_5.cpp b/lib/wx/c_src/gen/wxe_wrapper_5.cpp
index d9d7248a84..b2616e151e 100644
--- a/lib/wx/c_src/gen/wxe_wrapper_5.cpp
+++ b/lib/wx/c_src/gen/wxe_wrapper_5.cpp
@@ -1910,6 +1910,30 @@ void wxMenuBar_OSXGetAppleMenu(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
}
#endif
+#if defined(__WXMAC__)
+// wxMenuBar::MacGetCommonMenuBar
+void wxMenuBar_MacGetCommonMenuBar(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ wxMenuBar * Result = (wxMenuBar*)wxMenuBar::MacGetCommonMenuBar();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_ref(app->getRef((void *)Result,memenv), "wxMenuBar"));
+
+}
+
+#endif
+#if defined(__WXMAC__)
+// wxMenuBar::MacSetCommonMenuBar
+void wxMenuBar_MacSetCommonMenuBar(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMenuBar *menubar;
+ menubar = (wxMenuBar *) memenv->getPtr(env, argv[0], "menubar");
+ wxMenuBar::MacSetCommonMenuBar(menubar);
+
+}
+
+#endif
// wxMenuBar::IsEnabled
void wxMenuBar_IsEnabled(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
{
@@ -3166,6 +3190,90 @@ void wxMouseEvent_GetWheelAxis(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
}
+// wxMouseEvent::Aux1DClick
+void wxMouseEvent_Aux1DClick(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMouseEvent *This;
+ This = (wxMouseEvent *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->Aux1DClick();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+// wxMouseEvent::Aux1Down
+void wxMouseEvent_Aux1Down(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMouseEvent *This;
+ This = (wxMouseEvent *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->Aux1Down();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+// wxMouseEvent::Aux1Up
+void wxMouseEvent_Aux1Up(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMouseEvent *This;
+ This = (wxMouseEvent *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->Aux1Up();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+// wxMouseEvent::Aux2DClick
+void wxMouseEvent_Aux2DClick(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMouseEvent *This;
+ This = (wxMouseEvent *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->Aux2DClick();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+// wxMouseEvent::Aux2Down
+void wxMouseEvent_Aux2Down(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMouseEvent *This;
+ This = (wxMouseEvent *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->Aux2Down();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
+// wxMouseEvent::Aux2Up
+void wxMouseEvent_Aux2Up(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
+{
+ ErlNifEnv *env = Ecmd.env;
+ ERL_NIF_TERM * argv = Ecmd.args;
+ wxMouseEvent *This;
+ This = (wxMouseEvent *) memenv->getPtr(env, argv[0], "This");
+ if(!This) throw wxe_badarg("This");
+ bool Result = This->Aux2Up();
+ wxeReturn rt = wxeReturn(memenv, Ecmd.caller, true);
+ rt.send( rt.make_bool(Result));
+
+}
+
// wxMoveEvent::GetPosition
void wxMoveEvent_GetPosition(WxeApp *app, wxeMemEnv *memenv, wxeCommand& Ecmd)
{
diff --git a/lib/wx/c_src/wxe_callback_impl.cpp b/lib/wx/c_src/wxe_callback_impl.cpp
index 50f6c0166c..16458f6fa6 100644
--- a/lib/wx/c_src/wxe_callback_impl.cpp
+++ b/lib/wx/c_src/wxe_callback_impl.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ wxeEvtListener::wxeEvtListener(ErlNifPid caller, int req, ERL_NIF_TERM req_type,
}
wxeEvtListener::~wxeEvtListener() {
- // enif_fprintf(stderr, "CBD Deleteing %p %T\r\n", this, class_name); fflush(stderr);
+ // enif_fprintf(stderr, "CBD Deleting %p %T\r\n", this, class_name); fflush(stderr);
if(user_data) {
delete user_data;
}
diff --git a/lib/wx/c_src/wxe_helpers.cpp b/lib/wx/c_src/wxe_helpers.cpp
index 69a9c65c27..d8cca31654 100644
--- a/lib/wx/c_src/wxe_helpers.cpp
+++ b/lib/wx/c_src/wxe_helpers.cpp
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,7 +107,7 @@ void wxeFifo::DelQueue(unsigned int i)
void wxeFifo::DeleteCmd(wxeCommand *orig)
{
- orig->op = -2; // Assert: will crash if op is negativ
+ orig->op = -2; // Assert: will crash if op is negative
enif_clear_env(orig->env);
free.push_back(orig);
}
@@ -136,6 +136,6 @@ void wxeFifo::Append(wxeCommand *orig)
curr->env = orig->env;
orig->env = temp;
curr->me_ref = orig->me_ref;
- orig->op = -1; // Assert: will crash if op is negativ
+ orig->op = -1; // Assert: will crash if op is negative
m_q.push_back(curr);
}
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index fd71fed4aa..a32e09db01 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -33,6 +33,10 @@
#include <wx/dcbuffer.h>
#undef private
+#ifdef HAVE_GLIB
+ #include <glib.h>
+#endif
+
#include "wxe_impl.h"
#include "wxe_events.h"
#include "wxe_return.h"
@@ -135,6 +139,23 @@ void print_cmd(wxeCommand& event)
* Init WxeApp the application emulator
* ************************************************************/
+#ifdef HAVE_GLIB
+static GLogWriterOutput wxe_log_glib(GLogLevelFlags log_level,
+ const GLogField *fields,
+ gsize n_fields,
+ gpointer user_data)
+{
+ for (gsize i = 0; i < n_fields; i++) {
+ if(strcmp(fields[i].key, "MESSAGE") == 0) {
+ wxString msg;
+ msg.Printf(wxT("GTK: %s"), (char *) fields[i].value);
+ send_msg("debug", &msg);
+ }
+ }
+ return G_LOG_WRITER_HANDLED;
+}
+#endif
+
bool WxeApp::OnInit()
{
@@ -167,6 +188,10 @@ bool WxeApp::OnInit()
(wxObjectEventFunction) (wxEventFunction) &WxeApp::dummy_close);
#endif
+#ifdef HAVE_GLIB
+ g_log_set_writer_func(wxe_log_glib, NULL, NULL);
+#endif
+
SetExitOnFrameDelete(false);
enif_mutex_lock(wxe_status_m);
@@ -199,6 +224,18 @@ void WxeApp::MacReopenApp() {
wxString empty;
send_msg("reopen_app", &empty);
}
+
+// See: https://github.com/wxWidgets/wxWidgets/blob/v3.1.5/src/osx/cocoa/utils.mm#L76:L93
+bool WxeApp::OSXIsGUIApplication() {
+ char val_buf[8];
+ size_t val_len = 7;
+ int res = enif_getenv("WX_MACOS_NON_GUI_APP", val_buf, &val_len);
+ if (res == 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
#endif
void WxeApp::shutdown(wxeMetaCommand& Ecmd) {
@@ -634,7 +671,7 @@ void WxeApp::destroyMemEnv(wxeMetaCommand &Ecmd)
delete refd;
ptr2ref.erase(it);
} // overridden allocs deletes meta-data in clearPtr
- } else { // Not alloced in erl just delete references
+ } else { // Not allocated in erl just delete references
if(refd->ref >= global_me->next) { // if it is not part of global ptrs
delete refd;
ptr2ref.erase(it);
diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h
index 16487f3c0d..ee8654d1ef 100644
--- a/lib/wx/c_src/wxe_impl.h
+++ b/lib/wx/c_src/wxe_impl.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,6 +64,7 @@ public:
virtual void MacOpenURL(const wxString &url);
virtual void MacNewFile();
virtual void MacReopenApp();
+ virtual bool OSXIsGUIApplication();
#endif
void init_consts(wxeMetaCommand& event);
diff --git a/lib/wx/c_src/wxe_nif.c b/lib/wx/c_src/wxe_nif.c
index eaab733807..6f6251e482 100644
--- a/lib/wx/c_src/wxe_nif.c
+++ b/lib/wx/c_src/wxe_nif.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2017-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2017-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -197,6 +197,7 @@ static ErlNifFunc nif_funcs[] =
{"queue_cmd",12, wx_setup_cmd},
{"queue_cmd",13, wx_setup_cmd},
{"queue_cmd",14, wx_setup_cmd},
+ {"queue_cmd",15, wx_setup_cmd},
{"init_opengl", 1, wx_init_opengl},
{"make_env", 0, wxe_make_env},
{"delete_env", 1, wxe_delete_env},
diff --git a/lib/wx/c_src/wxe_nif.h b/lib/wx/c_src/wxe_nif.h
index 3e934bdd6b..e466182ccf 100644
--- a/lib/wx/c_src/wxe_nif.h
+++ b/lib/wx/c_src/wxe_nif.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2019-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2019-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ extern ERL_NIF_TERM WXE_ATOM__wx_invoke_cb_;
extern ERL_NIF_TERM WXE_ATOM_define;
extern ERL_NIF_TERM WXE_ATOM_global;
-/* Used for comparsions */
+/* Used for comparisons */
extern ERL_NIF_TERM WXE_ATOM_wxWindow;
extern ERL_NIF_TERM WXE_ATOM_wxSizer;
@@ -116,3 +116,7 @@ void stop_native_gui(ErlNifEnv *);
/* wxe_ps_init */
void * wxe_ps_init();
void * wxe_ps_init2();
+
+#ifdef _MACOSX
+int is_packaged_app();
+#endif
diff --git a/lib/wx/c_src/wxe_return.cpp b/lib/wx/c_src/wxe_return.cpp
index b86df17933..7d2e072561 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-2021. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2022. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -409,7 +409,7 @@ ERL_NIF_TERM wxeReturn::make(wxGBSpan val) {
INLINE
ERL_NIF_TERM wxeReturn::make(wxMouseState val) {
- return enif_make_tuple(env, 11,
+ return enif_make_tuple(env, 13,
enif_make_atom(env, "wxMouseState"),
// TODO not int?
enif_make_uint(env, val.GetX()),
@@ -421,7 +421,9 @@ ERL_NIF_TERM wxeReturn::make(wxMouseState val) {
make_bool(val.ShiftDown()),
make_bool(val.AltDown()),
make_bool(val.MetaDown()),
- make_bool(val.CmdDown())
+ make_bool(val.CmdDown()),
+ make_bool(val.Aux1IsDown()),
+ make_bool(val.Aux2IsDown())
);
}
diff --git a/lib/wx/config.mk.in b/lib/wx/config.mk.in
index 2fa09209d2..51bab82ea4 100644
--- a/lib/wx/config.mk.in
+++ b/lib/wx/config.mk.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2021. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,20 +17,12 @@
#
# %CopyrightEnd%
#
-INSIDE_ERLSRC = @WX_BUILDING_INSIDE_ERLSRC@
SYS_TYPE = @WXERL_SYS_TYPE@
CAN_BUILD_DRIVER = @WXERL_CAN_BUILD_DRIVER@
VSN = $(WX_VSN)
-ifeq ($(INSIDE_ERLSRC), true)
-
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
RELSYSDIR = $(RELEASE_PATH)/lib/wx-$(VSN)
-
-else
-INSTALLDIR=@ERLANG_ROOT_DIR@/lib
-endif
-
diff --git a/lib/wx/configure b/lib/wx/configure
index 6cb5ce03b4..d3dc12b32a 100755
--- a/lib/wx/configure
+++ b/lib/wx/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +430,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +459,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +503,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +517,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +534,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,49 +606,45 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
WXERL_SYS_TYPE
@@ -649,15 +676,14 @@ WX_CFLAGS
WX_CPPFLAGS
WX_CONFIG_PATH
ERLANG_ROOT_DIR
-WX_BUILDING_INSIDE_ERLSRC
ERLC
DEBUG_CXXFLAGS
DEBUG_CFLAGS
GL_LIBS
OBJC_CFLAGS
OBJC_CC
-EGREP
-GREP
+GLIB_LIBS
+GLIB_CFLAGS
MIXED_MINGW
MIXED_VC
CPP
@@ -673,6 +699,10 @@ LDFLAGS
CFLAGS
CC
TARGET
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -810,8 +840,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -852,9 +880,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -878,9 +906,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1091,9 +1119,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1107,9 +1135,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1153,9 +1181,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1171,7 +1199,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1235,7 +1263,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1353,6 +1381,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1410,9 +1439,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1440,7 +1469,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1448,7 +1478,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1458,9 +1488,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1477,14 +1507,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1492,14 +1522,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1515,14 +1546,14 @@ fi
ac_fn_cxx_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1530,14 +1561,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1559,7 +1591,7 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1567,14 +1599,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1586,8 +1619,8 @@ fi
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
@@ -1597,25 +1630,26 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
@@ -1640,7 +1674,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -1650,14 +1684,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1667,9 +1702,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -1677,14 +1713,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -1694,14 +1730,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -1711,9 +1748,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -1721,14 +1759,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -1736,7 +1774,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -1746,12 +1784,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -1761,12 +1800,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -1794,9 +1833,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -1816,131 +1856,46 @@ rm -f conftest.val
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
# ac_fn_cxx_try_link LINENO
# -------------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_cxx_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1948,17 +1903,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1980,17 +1936,18 @@ fi
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof ($2))
return 0;
@@ -1998,12 +1955,13 @@ if (sizeof ($2))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof (($2)))
return 0;
@@ -2011,29 +1969,50 @@ if (sizeof (($2)))
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
eval "$3=yes"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2066,8 +2045,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2102,7 +2085,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2137,11 +2120,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2152,8 +2137,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2177,7 +2162,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2185,14 +2170,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2200,15 +2185,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2216,8 +2201,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2231,63 +2216,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2297,19 +2267,650 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+# Test code for whether the C++ compiler supports C++98 (global declarations)
+ac_cxx_conftest_cxx98_globals='
+// Does the compiler advertise C++98 conformance?
+#if !defined __cplusplus || __cplusplus < 199711L
+# error "Compiler does not advertise C++98 conformance"
+#endif
+
+// These inclusions are to reject old compilers that
+// lack the unsuffixed header files.
+#include <cstdlib>
+#include <exception>
+
+// <cassert> and <cstring> are *not* freestanding headers in C++98.
+extern void assert (int);
+namespace std {
+ extern int strcmp (const char *, const char *);
+}
+
+// Namespaces, exceptions, and templates were all added after "C++ 2.0".
+using std::exception;
+using std::strcmp;
+
+namespace {
+
+void test_exception_syntax()
+{
+ try {
+ throw "test";
+ } catch (const char *s) {
+ // Extra parentheses suppress a warning when building autoconf itself,
+ // due to lint rules shared with more typical C programs.
+ assert (!(strcmp) (s, "test"));
+ }
+}
+
+template <typename T> struct test_template
+{
+ T const val;
+ explicit test_template(T t) : val(t) {}
+ template <typename U> T add(U u) { return static_cast<T>(u) + val; }
+};
+
+} // anonymous namespace
+'
+
+# Test code for whether the C++ compiler supports C++98 (body of main)
+ac_cxx_conftest_cxx98_main='
+ assert (argc);
+ assert (! argv[0]);
+{
+ test_exception_syntax ();
+ test_template<double> tt (2.0);
+ assert (tt.add (4) == 6.0);
+ assert (true && !false);
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (global declarations)
+ac_cxx_conftest_cxx11_globals='
+// Does the compiler advertise C++ 2011 conformance?
+#if !defined __cplusplus || __cplusplus < 201103L
+# error "Compiler does not advertise C++11 conformance"
+#endif
+
+namespace cxx11test
+{
+ constexpr int get_val() { return 20; }
+
+ struct testinit
+ {
+ int i;
+ double d;
+ };
+
+ class delegate
+ {
+ public:
+ delegate(int n) : n(n) {}
+ delegate(): delegate(2354) {}
+
+ virtual int getval() { return this->n; };
+ protected:
+ int n;
+ };
+
+ class overridden : public delegate
+ {
+ public:
+ overridden(int n): delegate(n) {}
+ virtual int getval() override final { return this->n * 2; }
+ };
+
+ class nocopy
+ {
+ public:
+ nocopy(int i): i(i) {}
+ nocopy() = default;
+ nocopy(const nocopy&) = delete;
+ nocopy & operator=(const nocopy&) = delete;
+ private:
+ int i;
+ };
+
+ // for testing lambda expressions
+ template <typename Ret, typename Fn> Ret eval(Fn f, Ret v)
+ {
+ return f(v);
+ }
+
+ // for testing variadic templates and trailing return types
+ template <typename V> auto sum(V first) -> V
+ {
+ return first;
+ }
+ template <typename V, typename... Args> auto sum(V first, Args... rest) -> V
+ {
+ return first + sum(rest...);
+ }
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (body of main)
+ac_cxx_conftest_cxx11_main='
+{
+ // Test auto and decltype
+ auto a1 = 6538;
+ auto a2 = 48573953.4;
+ auto a3 = "String literal";
+
+ int total = 0;
+ for (auto i = a3; *i; ++i) { total += *i; }
+
+ decltype(a2) a4 = 34895.034;
+}
+{
+ // Test constexpr
+ short sa[cxx11test::get_val()] = { 0 };
+}
+{
+ // Test initializer lists
+ cxx11test::testinit il = { 4323, 435234.23544 };
+}
+{
+ // Test range-based for
+ int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
+ 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
+ for (auto &x : array) { x += 23; }
+}
+{
+ // Test lambda expressions
+ using cxx11test::eval;
+ assert (eval ([](int x) { return x*2; }, 21) == 42);
+ double d = 2.0;
+ assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
+ assert (d == 5.0);
+ assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
+ assert (d == 5.0);
+}
+{
+ // Test use of variadic templates
+ using cxx11test::sum;
+ auto a = sum(1);
+ auto b = sum(1, 2);
+ auto c = sum(1.0, 2.0, 3.0);
+}
+{
+ // Test constructor delegation
+ cxx11test::delegate d1;
+ cxx11test::delegate d2();
+ cxx11test::delegate d3(45);
+}
+{
+ // Test override and final
+ cxx11test::overridden o1(55464);
+}
+{
+ // Test nullptr
+ char *c = nullptr;
+}
+{
+ // Test template brackets
+ test_template<::test_template<int>> v(test_template<int>(12));
+}
+{
+ // Unicode literals
+ char const *utf8 = u8"UTF-8 string \u2500";
+ char16_t const *utf16 = u"UTF-8 string \u2500";
+ char32_t const *utf32 = U"UTF-32 string \u2500";
+}
+'
+
+# Test code for whether the C compiler supports C++11 (complete).
+ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
+${ac_cxx_conftest_cxx11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ ${ac_cxx_conftest_cxx11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C++98 (complete).
+ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2320,12 +2921,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2334,24 +2935,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2361,11 +2962,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2379,110 +2981,140 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in $srcdir/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in $srcdir/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-## Delete previous failed configure results
-if test -f ./CONF_INFO; then
- rm ./CONF_INFO
-fi
-if test -z "$ERL_TOP" || test ! -d $ERL_TOP ; then
- as_fn_error $? "ERL_TOP is not set" "$LINENO" 5
-else
- erl_top=${ERL_TOP}
- ac_aux_dir=
-for ac_dir in $erl_top/erts/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in $erl_top/erts/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
- WX_BUILDING_INSIDE_ERLSRC=true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Delete previous failed configure results
+if test -f ./CONF_INFO; then
+ rm ./CONF_INFO
fi
+
+
# Check whether --with-wx was given.
-if test "${with_wx+set}" = set; then :
+if test ${with_wx+y}
+then :
withval=$with_wx;
fi
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2501,21 +3133,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2534,10 +3167,108 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=win32
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
fi
+
case $host_os in
mingw32)
if test "X$host" = "X"; then
@@ -2551,6 +3282,15 @@ esac
TARGET=$host
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2559,11 +3299,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2571,11 +3312,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2586,11 +3331,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2599,11 +3344,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2611,11 +3357,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2626,11 +3376,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2638,8 +3388,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2652,11 +3402,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2664,11 +3415,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2679,11 +3434,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2692,11 +3447,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2705,15 +3461,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2729,18 +3489,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2751,11 +3511,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2763,11 +3524,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2778,11 +3543,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2795,11 +3560,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2807,11 +3573,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2822,11 +3592,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2838,8 +3608,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2847,25 +3617,129 @@ esac
fi
fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -2875,7 +3749,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -2883,7 +3757,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -2895,9 +3769,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -2918,11 +3792,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -2939,7 +3814,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -2955,44 +3830,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -3006,15 +3883,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -3023,7 +3900,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3035,8 +3912,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -3044,10 +3921,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -3055,39 +3932,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3101,11 +3979,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -3114,31 +3993,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3148,29 +4028,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3179,57 +4063,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3244,94 +4131,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3340,6 +4277,12 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3350,15 +4293,16 @@ if test -z "$CXX"; then
CXX=$CCC
else
if test -n "$ac_tool_prefix"; then
- for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CXX"; then
ac_cv_prog_CXX="$CXX" # Let the user override the test.
else
@@ -3366,11 +4310,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3381,11 +4329,11 @@ fi
fi
CXX=$ac_cv_prog_CXX
if test -n "$CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
-$as_echo "$CXX" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+printf "%s\n" "$CXX" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3394,15 +4342,16 @@ fi
fi
if test -z "$CXX"; then
ac_ct_CXX=$CXX
- for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CXX"; then
ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
else
@@ -3410,11 +4359,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CXX="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3425,11 +4378,11 @@ fi
fi
ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
if test -n "$ac_ct_CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
-$as_echo "$ac_ct_CXX" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+printf "%s\n" "$ac_ct_CXX" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3441,8 +4394,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CXX=$ac_ct_CXX
@@ -3452,7 +4405,7 @@ fi
fi
fi
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
@@ -3462,7 +4415,7 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -3472,20 +4425,21 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
-$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if ${ac_cv_cxx_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
+printf %s "checking whether the compiler supports GNU C++... " >&6; }
+if test ${ac_cv_cxx_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3495,29 +4449,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
-$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GXX=yes
else
GXX=
fi
-ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_test_CXXFLAGS=${CXXFLAGS+y}
ac_save_CXXFLAGS=$CXXFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
-$as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if ${ac_cv_prog_cxx_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+printf %s "checking whether $CXX accepts -g... " >&6; }
+if test ${ac_cv_prog_cxx_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_cxx_werror_flag=$ac_cxx_werror_flag
ac_cxx_werror_flag=yes
ac_cv_prog_cxx_g=no
@@ -3526,57 +4484,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
ac_cv_prog_cxx_g=yes
-else
+else $as_nop
CXXFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_cxx_werror_flag=$ac_save_cxx_werror_flag
CXXFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
ac_cv_prog_cxx_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cxx_werror_flag=$ac_save_cxx_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
-$as_echo "$ac_cv_prog_cxx_g" >&6; }
-if test "$ac_test_CXXFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
+if test $ac_test_CXXFLAGS; then
CXXFLAGS=$ac_save_CXXFLAGS
elif test $ac_cv_prog_cxx_g = yes; then
if test "$GXX" = yes; then
@@ -3591,6 +4552,100 @@ else
CXXFLAGS=
fi
fi
+ac_prog_cxx_stdcxx=no
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
+printf %s "checking for $CXX option to enable C++11 features... " >&6; }
+if test ${ac_cv_prog_cxx_11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_11=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx11_program
+_ACEOF
+for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx11"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
+ ac_prog_cxx_stdcxx=cxx11
+fi
+fi
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
+printf %s "checking for $CXX option to enable C++98 features... " >&6; }
+if test ${ac_cv_prog_cxx_98+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_98=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx98_program
+_ACEOF
+for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx98=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx98" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx98" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx98"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
+ ac_prog_cxx_stdcxx=cxx98
+fi
+fi
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3600,11 +4655,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
@@ -3612,11 +4668,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3627,11 +4687,11 @@ fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3640,11 +4700,12 @@ if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
@@ -3652,11 +4713,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3667,11 +4732,11 @@ fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_RANLIB" = x; then
@@ -3679,8 +4744,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
@@ -3694,40 +4759,36 @@ ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+#include <limits.h>
Syntax error
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
-else
+else $as_nop
# Broken: fails on valid input.
continue
fi
@@ -3739,10 +4800,11 @@ rm -f conftest.err conftest.i conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
# Broken: success on invalid input.
continue
-else
+else $as_nop
# Passes both tests.
ac_preproc_ok=:
break
@@ -3752,7 +4814,8 @@ rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
+if $ac_preproc_ok
+then :
break
fi
@@ -3764,29 +4827,24 @@ fi
else
ac_cv_prog_CPP=$CPP
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+#include <limits.h>
Syntax error
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
-else
+else $as_nop
# Broken: fails on valid input.
continue
fi
@@ -3798,10 +4856,11 @@ rm -f conftest.err conftest.i conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
+if ac_fn_c_try_cpp "$LINENO"
+then :
# Broken: success on invalid input.
continue
-else
+else $as_nop
# Passes both tests.
ac_preproc_ok=:
break
@@ -3811,11 +4870,12 @@ rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
+if $ac_preproc_ok
+then :
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -3840,19 +4900,20 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#error "broken C++"
#endif
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
-else
+else $as_nop
CXX=;
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3865,15 +4926,15 @@ if test "X$CXX" = X ; then
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "Can not find C++ compiler" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not find C++ compiler" >&5
-$as_echo "$as_me: WARNING: Can not find C++ compiler" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Can not find C++ compiler" >&5
+printf "%s\n" "$as_me: WARNING: Can not find C++ compiler" >&2;}
fi
fi
WXERL_CAN_BUILD_DRIVER=false
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Building for $host_os" >&5
-$as_echo "$as_me: Building for $host_os" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Building for $host_os" >&5
+printf "%s\n" "$as_me: Building for $host_os" >&6;}
WXERL_CAN_BUILD_DRIVER=true
@@ -3887,111 +4948,111 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -4004,281 +5065,52 @@ if test X"$MIXED_VC" = X"yes" ; then
fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
+done
-fi
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -4287,14 +5119,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
@@ -4303,44 +5133,46 @@ PTHR_CFLAGS="-D_THREAD_SAFE -D_REENTRANT"
OBJC_CC=$CC
OBJC_CFLAGS=""
CXXFLAGS=""
-case $host_os in
- darwin*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking Checking wxWidgets for min version:" >&5
-$as_echo_n "checking Checking wxWidgets for min version:... " >&6; }
+case $host_os in #(
+ darwin*) :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking Checking wxWidgets for min version:" >&5
+printf %s "checking Checking wxWidgets for min version:... " >&6; }
WX_CC=`wx-config --cc`
MAC_MIN=`echo "$WX_CC" | sed 's/^[^ ]*\ *//'`
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAC_MIN" >&5
-$as_echo "$MAC_MIN" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAC_MIN" >&5
+printf "%s\n" "$MAC_MIN" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -ObjC" >&5
-$as_echo_n "checking if compiler accepts -ObjC... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -ObjC" >&5
+printf %s "checking if compiler accepts -ObjC... " >&6; }
CFLAGS="$CFLAGS -ObjC"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
accept_objc_flag=true
-else
+else $as_nop
accept_objc_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
if test "X$accept_objc_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
C_ONLY_FLAGS="-ObjC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Cocoa compliant Objective C compiler" >&5
-$as_echo_n "checking for a Cocoa compliant Objective C compiler... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a Cocoa compliant Objective C compiler" >&5
+printf %s "checking for a Cocoa compliant Objective C compiler... " >&6; }
SEARCHFOR=""
SEARCHFORXX=""
save_IFS=$IFS
@@ -4369,20 +5201,20 @@ $as_echo_n "checking for a Cocoa compliant Objective C compiler... " >&6; }
done
IFS=$save_IFS
if test X$APPLE_CC = X -o X$APPLE_CXX = X; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
echo "Can not find compiler to compile Cocoa applications" >> ./CONF_INFO
WXERL_CAN_BUILD_DRIVER=false
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "Can not find compiler to compile Cocoa applications" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not find compiler to compile Cocoa applications" >&5
-$as_echo "$as_me: WARNING: Can not find compiler to compile Cocoa applications" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Can not find compiler to compile Cocoa applications" >&5
+printf "%s\n" "$as_me: WARNING: Can not find compiler to compile Cocoa applications" >&2;}
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $APPLE_CC ($APPLE_CXX)" >&5
-$as_echo "$APPLE_CC ($APPLE_CXX)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $APPLE_CC ($APPLE_CXX)" >&5
+printf "%s\n" "$APPLE_CC ($APPLE_CXX)" >&6; }
CC=$APPLE_CC
CXX=$APPLE_CXX
#CXXFLAGS="-x c++ $CXXFLAGS"
@@ -4392,27 +5224,38 @@ $as_echo "$APPLE_CC ($APPLE_CXX)" >&6; }
fi
CFLAGS="$USER_CFLAGS $MAC_MIN -Wno-deprecated-declarations"
CPPFLAGS="$CPPFLAGS -D_MACOSX $PTHR_CFLAGS"
- ;;
- mingw32)
+ ;; #(
+ mingw32) :
+
CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE"
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Reverting to 32-bit time_t" >&5
-$as_echo "$as_me: WARNING: Reverting to 32-bit time_t" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Reverting to 32-bit time_t" >&5
+printf "%s\n" "$as_me: WARNING: Reverting to 32-bit time_t" >&2;}
CPPFLAGS="$CPPFLAGS -D_USE_32BIT_TIME_T"
- ;;
- win32)
+ ;; #(
+ win32) :
+
CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE"
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
- ;;
- *)
- CFLAGS="$CFLAGS -Wno-deprecated-declarations"
- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE $PTHR_CFLAGS"
- ;;
+ ;; #(
+ *) :
+
+ GLIB_CFLAGS=`pkg-config --silence-errors --cflags glib-2.0`
+ GLIB_LIBS=`pkg-config --silence-errors --libs glib-2.0`
+ if test X"$GLIB_CFLAGS" != X ; then
+ HAVE_GLIB="-DHAVE_GLIB=1"
+ fi
+ CFLAGS="$CFLAGS -Wno-deprecated-declarations"
+ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE $PTHR_CFLAGS $HAVE_GLIB"
+ ;;
esac
+
+
+
case $host_os in
darwin*)
LDFLAGS="$MAC_MIN -bundle -flat_namespace -undefined warning -fPIC $LDFLAGS"
@@ -4458,198 +5301,202 @@ case $host_os in
esac
-if test "x$GCC" = xyes -a X"$host_os" != X"win32" ; then
+if test "x$GCC" = xyes -a X"$host_os" != X"win32"
+then :
+
CXXNOOPT="-O1"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-move-loop-invariants to CXXNOOPT (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-move-loop-invariants to CXXNOOPT (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-move-loop-invariants to CXXNOOPT (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-move-loop-invariants to CXXNOOPT (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-move-loop-invariants $CXXNOOPT";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CXXNOOPT="-fno-move-loop-invariants $CXXNOOPT"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-var-tracking-assignments to CXXNOOPT (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-var-tracking-assignments to CXXNOOPT (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-var-tracking-assignments to CXXNOOPT (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-var-tracking-assignments to CXXNOOPT (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-var-tracking-assignments $CXXNOOPT";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CXXNOOPT="-fno-var-tracking-assignments $CXXNOOPT"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-if test X"$host_os" != X"win32" ; then
- for ac_header in GL/gl.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
-if test "x$ac_cv_header_GL_gl_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GL_GL_H 1
-_ACEOF
+fi
-else
- for ac_header in OpenGL/gl.h
+
+if test X"$host_os" != X"win32"
+then :
+
+ for ac_header in GL/gl.h
do :
- ac_fn_c_check_header_mongrel "$LINENO" "OpenGL/gl.h" "ac_cv_header_OpenGL_gl_h" "$ac_includes_default"
-if test "x$ac_cv_header_OpenGL_gl_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENGL_GL_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
+if test "x$ac_cv_header_GL_gl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GL_GL_H 1" >>confdefs.h
-fi
+else $as_nop
+ ac_fn_c_check_header_compile "$LINENO" "OpenGL/gl.h" "ac_cv_header_OpenGL_gl_h" "$ac_includes_default"
+if test "x$ac_cv_header_OpenGL_gl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_OPENGL_GL_H 1" >>confdefs.h
-done
+fi
fi
done
+ if test X"$ac_cv_header_GL_gl_h" != Xyes && test X"$ac_cv_header_OpenGL_gl_h" != Xyes
+then :
- if test X"$ac_cv_header_GL_gl_h" != Xyes &&
- test X"$ac_cv_header_OpenGL_gl_h" != Xyes
- then
saved_CPPFLAGS="$CPPFLAGS"
- { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for OpenGL headers in /usr/X11R6" >&5
-$as_echo "$as_me: Checking for OpenGL headers in /usr/X11R6" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Checking for OpenGL headers in /usr/X11R6" >&5
+printf "%s\n" "$as_me: Checking for OpenGL headers in /usr/X11R6" >&6;}
CPPFLAGS="-isystem /usr/X11R6/include $CPPFLAGS"
$as_unset ac_cv_header_GL_gl_h
- for ac_header in GL/gl.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
-if test "x$ac_cv_header_GL_gl_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GL_GL_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
+if test "x$ac_cv_header_GL_gl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GL_GL_H 1" >>confdefs.h
fi
-done
+ if test X"$ac_cv_header_GL_gl_h" != Xyes
+then :
- if test X"$ac_cv_header_GL_gl_h" != Xyes ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for OpenGL headers in /usr/local" >&5
-$as_echo "$as_me: Checking for OpenGL headers in /usr/local" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Checking for OpenGL headers in /usr/local" >&5
+printf "%s\n" "$as_me: Checking for OpenGL headers in /usr/local" >&6;}
CPPFLAGS="-isystem /usr/local/include $saved_CPPFLAGS"
$as_unset ac_cv_header_GL_gl_h
- for ac_header in GL/gl.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
-if test "x$ac_cv_header_GL_gl_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GL_GL_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default"
+if test "x$ac_cv_header_GL_gl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GL_GL_H 1" >>confdefs.h
fi
-done
+ if test X"$ac_cv_header_GL_gl_h" != Xyes
+then :
- if test X"$ac_cv_header_GL_gl_h" != Xyes ; then
echo "No OpenGL headers found, wx will NOT be usable" >> ./CONF_INFO
WXERL_CAN_BUILD_DRIVER=false
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "No OpenGL headers found, wx will NOT be usable" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No OpenGL headers found, wx will NOT be usable" >&5
-$as_echo "$as_me: WARNING: No OpenGL headers found, wx will NOT be usable" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No OpenGL headers found, wx will NOT be usable" >&5
+printf "%s\n" "$as_me: WARNING: No OpenGL headers found, wx will NOT be usable" >&2;}
fi
CPPFLAGS="$saved_CPPFLAGS"
- else
+
+else $as_nop
+
GL_LIBS="-L/usr/local/lib $GL_LIBS"
- fi
- else
+
+fi
+
+else $as_nop
+
GL_LIBS="-L/usr/X11R6/lib $GL_LIBS"
- fi
- fi
-else
- for ac_header in gl/gl.h
-do :
- ac_fn_c_check_header_compile "$LINENO" "gl/gl.h" "ac_cv_header_gl_gl_h" "#include <windows.h>
+
+fi
+
+fi
+
+else $as_nop
+
+ ac_fn_c_check_header_compile "$LINENO" "gl/gl.h" "ac_cv_header_gl_gl_h" "#include <windows.h>
"
-if test "x$ac_cv_header_gl_gl_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GL_GL_H 1
-_ACEOF
+if test "x$ac_cv_header_gl_gl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GL_GL_H 1" >>confdefs.h
fi
-done
fi
-if test X"$host_os" != X"win32" ; then
- for ac_header in GL/glu.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "GL/glu.h" "ac_cv_header_GL_glu_h" "$ac_includes_default"
-if test "x$ac_cv_header_GL_glu_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GL_GLU_H 1
-_ACEOF
+if test X"$host_os" != X"win32"
+then :
-else
- for ac_header in OpenGL/glu.h
+ for ac_header in GL/glu.h
do :
- ac_fn_c_check_header_mongrel "$LINENO" "OpenGL/glu.h" "ac_cv_header_OpenGL_glu_h" "$ac_includes_default"
-if test "x$ac_cv_header_OpenGL_glu_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENGL_GLU_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "GL/glu.h" "ac_cv_header_GL_glu_h" "$ac_includes_default"
+if test "x$ac_cv_header_GL_glu_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GL_GLU_H 1" >>confdefs.h
-fi
+else $as_nop
+ ac_fn_c_check_header_compile "$LINENO" "OpenGL/glu.h" "ac_cv_header_OpenGL_glu_h" "$ac_includes_default"
+if test "x$ac_cv_header_OpenGL_glu_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_OPENGL_GLU_H 1" >>confdefs.h
-done
+fi
fi
done
-
if test X"$ac_cv_header_GL_glu_h" != Xyes &&
test X"$ac_cv_header_OpenGL_glu_h" != Xyes
then
@@ -4658,24 +5505,22 @@ done
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "No GLU headers found, wx will NOT be usable" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No GLU headers found, wx will NOT be usable" >&5
-$as_echo "$as_me: WARNING: No GLU headers found, wx will NOT be usable" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: No GLU headers found, wx will NOT be usable" >&5
+printf "%s\n" "$as_me: WARNING: No GLU headers found, wx will NOT be usable" >&2;}
fi
fi
-else
- for ac_header in gl/glu.h
-do :
- ac_fn_c_check_header_compile "$LINENO" "gl/glu.h" "ac_cv_header_gl_glu_h" "#include <windows.h>
+
+else $as_nop
+
+ ac_fn_c_check_header_compile "$LINENO" "gl/glu.h" "ac_cv_header_gl_glu_h" "#include <windows.h>
"
-if test "x$ac_cv_header_gl_glu_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GL_GLU_H 1
-_ACEOF
+if test "x$ac_cv_header_gl_glu_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GL_GLU_H 1" >>confdefs.h
fi
-done
fi
@@ -4698,18 +5543,22 @@ ERLANG_ROOT_DIR=$ERL_TOP
+if test "$cross_compiling" = "yes"
+then :
-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
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "Cross compilation of the wx driver is not supported yet, wx will NOT be usable" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cross compilation of the wx driver is not supported yet, wx will NOT be usable" >&5
-$as_echo "$as_me: WARNING: Cross compilation of the wx driver is not supported yet, wx will NOT be usable" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cross compilation of the wx driver is not supported yet, wx will NOT be usable" >&5
+printf "%s\n" "$as_me: WARNING: Cross compilation of the wx driver is not supported yet, wx will NOT be usable" >&2;}
fi
-elif test X"$MIXED_VC" = X"no"; then
+
+elif test X"$MIXED_VC" = X"no"
+then :
+
@@ -4763,30 +5612,34 @@ elif test X"$MIXED_VC" = X"no"; then
# Check whether --with-wxdir was given.
-if test "${with_wxdir+set}" = set; then :
+if test ${with_wxdir+y}
+then :
withval=$with_wxdir; wx_config_name="$withval/wx-config"
wx_config_args="--inplace"
fi
# Check whether --with-wx-config was given.
-if test "${with_wx_config+set}" = set; then :
+if test ${with_wx_config+y}
+then :
withval=$with_wx_config; wx_config_name="$withval"
fi
# Check whether --with-wx-prefix was given.
-if test "${with_wx_prefix+set}" = set; then :
+if test ${with_wx_prefix+y}
+then :
withval=$with_wx_prefix; wx_config_prefix="$withval"
-else
+else $as_nop
wx_config_prefix=""
fi
# Check whether --with-wx-exec-prefix was given.
-if test "${with_wx_exec_prefix+set}" = set; then :
+if test ${with_wx_exec_prefix+y}
+then :
withval=$with_wx_exec_prefix; wx_config_exec_prefix="$withval"
-else
+else $as_nop
wx_config_exec_prefix=""
fi
@@ -4815,19 +5668,20 @@ fi
fi
if test -x "$WX_CONFIG_NAME" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5
-$as_echo_n "checking for wx-config... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5
+printf %s "checking for wx-config... " >&6; }
WX_CONFIG_PATH="$WX_CONFIG_NAME"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
-$as_echo "$WX_CONFIG_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
+printf "%s\n" "$WX_CONFIG_PATH" >&6; }
else
# Extract the first word of "$WX_CONFIG_NAME", so it can be a program name with args.
set dummy $WX_CONFIG_NAME; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_WX_CONFIG_PATH+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_WX_CONFIG_PATH+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $WX_CONFIG_PATH in
[\\/]* | ?:[\\/]*)
ac_cv_path_WX_CONFIG_PATH="$WX_CONFIG_PATH" # Let the user override the test with a path.
@@ -4838,11 +5692,15 @@ as_dummy=""$WX_LOOKUP_PATH:$PATH""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_WX_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_WX_CONFIG_PATH="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4855,11 +5713,11 @@ esac
fi
WX_CONFIG_PATH=$ac_cv_path_WX_CONFIG_PATH
if test -n "$WX_CONFIG_PATH"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
-$as_echo "$WX_CONFIG_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
+printf "%s\n" "$WX_CONFIG_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4870,11 +5728,11 @@ fi
min_wx_version=$reqwx
if test -z "--unicode" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5
-$as_echo_n "checking for wxWidgets version >= $min_wx_version... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5
+printf %s "checking for wxWidgets version >= $min_wx_version... " >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version (--unicode)" >&5
-$as_echo_n "checking for wxWidgets version >= $min_wx_version (--unicode)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version (--unicode)" >&5
+printf %s "checking for wxWidgets version >= $min_wx_version (--unicode)... " >&6; }
fi
WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args --unicode"
@@ -4916,19 +5774,19 @@ $as_echo_n "checking for wxWidgets version >= $min_wx_version (--unicode)... " >
if test -n "$wx_ver_ok"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5
-$as_echo "yes (version $WX_VERSION)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5
+printf "%s\n" "yes (version $WX_VERSION)" >&6; }
WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs core,base,html,webview`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5
-$as_echo_n "checking for wxWidgets static library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5
+printf %s "checking for wxWidgets static library... " >&6; }
WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs core,base,html,webview 2>/dev/null`
if test "x$WX_LIBS_STATIC" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
fi
wx_has_cppflags=""
@@ -4985,11 +5843,11 @@ $as_echo "yes" >&6; }
else
if test "x$WX_VERSION" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5
-$as_echo "no (version $WX_VERSION is not new enough)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5
+printf "%s\n" "no (version $WX_VERSION is not new enough)" >&6; }
fi
WX_CFLAGS=""
@@ -5022,8 +5880,8 @@ $as_echo "no (version $WX_VERSION is not new enough)" >&6; }
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "$wx_error_message" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $wx_error_message" >&5
-$as_echo "$as_me: WARNING: $wx_error_message" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $wx_error_message" >&5
+printf "%s\n" "$as_me: WARNING: $wx_error_message" >&2;}
fi
@@ -5059,8 +5917,8 @@ $as_echo "$as_me: WARNING: $wx_error_message" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxwidgets webview" >&5
-$as_echo_n "checking for wxwidgets webview... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxwidgets webview" >&5
+printf %s "checking for wxwidgets webview... " >&6; }
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5079,7 +5937,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
#include "wx/webview.h"
int
-main ()
+main (void)
{
wxWebView::New();
@@ -5088,12 +5946,13 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
+if ac_fn_cxx_try_link "$LINENO"
+then :
HAVE_WEBVIEW_SUPPORT=yes
-else
+else $as_nop
HAVE_WEBVIEW_SUPPORT=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CXXFLAGS=$saved_CXXFLAGS
@@ -5104,15 +5963,15 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_WEBVIEW_SUPPORT" >&5
-$as_echo "$HAVE_WEBVIEW_SUPPORT" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $HAVE_WEBVIEW_SUPPORT" >&5
+printf "%s\n" "$HAVE_WEBVIEW_SUPPORT" >&6; }
if test X"$HAVE_WEBVIEW_SUPPORT" != X"yes" ; then
WXELIBS=stc,xrc,html,adv,xml,core,base,gl,aui
echo "wxWidgets was not compiled with --enable-webview or wxWebView developer package is not installed, wxWebView will NOT be available" >> ./CONF_INFO
else
WXELIBS=stc,xrc,html,adv,xml,core,base,gl,aui,webview
- $as_echo "#define WXE_WEBVIEW 1" >>confdefs.h
+ printf "%s\n" "#define WXE_WEBVIEW 1" >>confdefs.h
fi
@@ -5140,19 +5999,20 @@ $as_echo "$HAVE_WEBVIEW_SUPPORT" >&6; }
fi
if test -x "$WX_CONFIG_NAME" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5
-$as_echo_n "checking for wx-config... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5
+printf %s "checking for wx-config... " >&6; }
WX_CONFIG_PATH="$WX_CONFIG_NAME"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
-$as_echo "$WX_CONFIG_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
+printf "%s\n" "$WX_CONFIG_PATH" >&6; }
else
# Extract the first word of "$WX_CONFIG_NAME", so it can be a program name with args.
set dummy $WX_CONFIG_NAME; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_WX_CONFIG_PATH+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_WX_CONFIG_PATH+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $WX_CONFIG_PATH in
[\\/]* | ?:[\\/]*)
ac_cv_path_WX_CONFIG_PATH="$WX_CONFIG_PATH" # Let the user override the test with a path.
@@ -5163,11 +6023,15 @@ as_dummy=""$WX_LOOKUP_PATH:$PATH""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_WX_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_WX_CONFIG_PATH="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5180,11 +6044,11 @@ esac
fi
WX_CONFIG_PATH=$ac_cv_path_WX_CONFIG_PATH
if test -n "$WX_CONFIG_PATH"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
-$as_echo "$WX_CONFIG_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
+printf "%s\n" "$WX_CONFIG_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5195,11 +6059,11 @@ fi
min_wx_version=$reqwx
if test -z "--unicode --debug=yes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5
-$as_echo_n "checking for wxWidgets version >= $min_wx_version... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5
+printf %s "checking for wxWidgets version >= $min_wx_version... " >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version (--unicode --debug=yes)" >&5
-$as_echo_n "checking for wxWidgets version >= $min_wx_version (--unicode --debug=yes)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version (--unicode --debug=yes)" >&5
+printf %s "checking for wxWidgets version >= $min_wx_version (--unicode --debug=yes)... " >&6; }
fi
WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args --unicode --debug=yes"
@@ -5241,19 +6105,19 @@ $as_echo_n "checking for wxWidgets version >= $min_wx_version (--unicode --debug
if test -n "$wx_ver_ok"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5
-$as_echo "yes (version $WX_VERSION)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5
+printf "%s\n" "yes (version $WX_VERSION)" >&6; }
WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $WXELIBS`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5
-$as_echo_n "checking for wxWidgets static library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5
+printf %s "checking for wxWidgets static library... " >&6; }
WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $WXELIBS 2>/dev/null`
if test "x$WX_LIBS_STATIC" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
fi
wx_has_cppflags=""
@@ -5310,11 +6174,11 @@ $as_echo "yes" >&6; }
else
if test "x$WX_VERSION" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5
-$as_echo "no (version $WX_VERSION is not new enough)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5
+printf "%s\n" "no (version $WX_VERSION is not new enough)" >&6; }
fi
WX_CFLAGS=""
@@ -5377,14 +6241,14 @@ $as_echo "no (version $WX_VERSION is not new enough)" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for debug build of wxWidgets" >&5
-$as_echo_n "checking for debug build of wxWidgets... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for debug build of wxWidgets" >&5
+printf %s "checking for debug build of wxWidgets... " >&6; }
if test "$wxWinWithGLDBG" = 1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; };
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; };
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; };
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; };
fi
DEBUG_WX_CFLAGS=$WX_CFLAGS
@@ -5419,19 +6283,20 @@ $as_echo "no" >&6; };
fi
if test -x "$WX_CONFIG_NAME" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5
-$as_echo_n "checking for wx-config... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5
+printf %s "checking for wx-config... " >&6; }
WX_CONFIG_PATH="$WX_CONFIG_NAME"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
-$as_echo "$WX_CONFIG_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
+printf "%s\n" "$WX_CONFIG_PATH" >&6; }
else
# Extract the first word of "$WX_CONFIG_NAME", so it can be a program name with args.
set dummy $WX_CONFIG_NAME; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_WX_CONFIG_PATH+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_WX_CONFIG_PATH+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $WX_CONFIG_PATH in
[\\/]* | ?:[\\/]*)
ac_cv_path_WX_CONFIG_PATH="$WX_CONFIG_PATH" # Let the user override the test with a path.
@@ -5442,11 +6307,15 @@ as_dummy=""$WX_LOOKUP_PATH:$PATH""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_WX_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_WX_CONFIG_PATH="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5459,11 +6328,11 @@ esac
fi
WX_CONFIG_PATH=$ac_cv_path_WX_CONFIG_PATH
if test -n "$WX_CONFIG_PATH"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
-$as_echo "$WX_CONFIG_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5
+printf "%s\n" "$WX_CONFIG_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5474,11 +6343,11 @@ fi
min_wx_version=$reqwx
if test -z "--unicode --debug=no" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5
-$as_echo_n "checking for wxWidgets version >= $min_wx_version... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5
+printf %s "checking for wxWidgets version >= $min_wx_version... " >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version (--unicode --debug=no)" >&5
-$as_echo_n "checking for wxWidgets version >= $min_wx_version (--unicode --debug=no)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version (--unicode --debug=no)" >&5
+printf %s "checking for wxWidgets version >= $min_wx_version (--unicode --debug=no)... " >&6; }
fi
WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args --unicode --debug=no"
@@ -5520,19 +6389,19 @@ $as_echo_n "checking for wxWidgets version >= $min_wx_version (--unicode --debug
if test -n "$wx_ver_ok"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5
-$as_echo "yes (version $WX_VERSION)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5
+printf "%s\n" "yes (version $WX_VERSION)" >&6; }
WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $WXELIBS`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5
-$as_echo_n "checking for wxWidgets static library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5
+printf %s "checking for wxWidgets static library... " >&6; }
WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $WXELIBS 2>/dev/null`
if test "x$WX_LIBS_STATIC" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
fi
wx_has_cppflags=""
@@ -5589,11 +6458,11 @@ $as_echo "yes" >&6; }
else
if test "x$WX_VERSION" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5
-$as_echo "no (version $WX_VERSION is not new enough)" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5
+printf "%s\n" "no (version $WX_VERSION is not new enough)" >&6; }
fi
WX_CFLAGS=""
@@ -5656,14 +6525,14 @@ $as_echo "no (version $WX_VERSION is not new enough)" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for standard build of wxWidgets" >&5
-$as_echo_n "checking for standard build of wxWidgets... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for standard build of wxWidgets" >&5
+printf %s "checking for standard build of wxWidgets... " >&6; }
if test "$wxWinWithGL" = 1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; };
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; };
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; };
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; };
fi
if test "x$WX_LIBS_STATIC" = "x"; then
@@ -5713,7 +6582,7 @@ $as_echo "no" >&6; };
is in LD_LIBRARY_PATH or equivalent variable and
wxWidgets version is $reqwx or above." "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING:
wxWidgets must be installed on your system.
Please check that wx-config is in path, the directory
@@ -5721,7 +6590,7 @@ $as_echo "no" >&6; };
'wx-config --libs' or 'wx-config --static --libs' command)
is in LD_LIBRARY_PATH or equivalent variable and
wxWidgets version is $reqwx or above." >&5
-$as_echo "$as_me: WARNING:
+printf "%s\n" "$as_me: WARNING:
wxWidgets must be installed on your system.
Please check that wx-config is in path, the directory
@@ -5732,13 +6601,15 @@ $as_echo "$as_me: WARNING:
fi
fi
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets in standard locations" >&5
-$as_echo_n "checking for wxWidgets in standard locations... " >&6; }
+
+else $as_nop
+ #else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxWidgets in standard locations" >&5
+printf %s "checking for wxWidgets in standard locations... " >&6; }
echo
# Check whether --with-wxdir was given.
- { $as_echo "$as_me:${as_lineno-$LINENO}: OptionCheck: $with_wxdir $with_wx_prefix" >&5
-$as_echo "$as_me: OptionCheck: $with_wxdir $with_wx_prefix" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OptionCheck: $with_wxdir $with_wx_prefix" >&5
+printf "%s\n" "$as_me: OptionCheck: $with_wxdir $with_wx_prefix" >&6;}
if test "${with_wxdir+set}" = set; then :
withval=$with_wxdir; CWXWIN0=$withval
@@ -5791,8 +6662,8 @@ $as_echo "$as_me: OptionCheck: $with_wxdir $with_wx_prefix" >&6;}
CWXPATH="$CWXWIN0 $CWXWIN1 $CWXWIN2 $CWX_DOCUMENTED $CWXWIN3 $CWXWIN4"
for dir in $CWXPATH; do
- { $as_echo "$as_me:${as_lineno-$LINENO}: Checking: $dir" >&5
-$as_echo "$as_me: Checking: $dir" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Checking: $dir" >&5
+printf "%s\n" "$as_me: Checking: $dir" >&6;}
if test -f $dir/include/wx/wx.h; then
WXINCLUDE_MSVC=$dir/include/msvc
WXINCLUDE_PLAIN=$dir/include
@@ -5815,37 +6686,37 @@ $as_echo "$as_me: Checking: $dir" >&6;}
WX_LIBS_STATIC="$WX_LIBS_STATIC -l$lib"
done
WXDIR=$dir
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Found: $dir" >&5
-$as_echo "Found: $dir" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Found: $dir" >&5
+printf "%s\n" "Found: $dir" >&6; }
break
fi
fi
done
if test -z "$WX_LIBS_STATIC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
-$as_echo "failed" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+printf "%s\n" "failed" >&6; }
echo "Cannot find core lib version for wxWidgets" >> ./CONF_INFO
WXERL_CAN_BUILD_DRIVER=false
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "Cannot find core lib version for wxWidgets" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find core lib version for wxWidgets" >&5
-$as_echo "$as_me: WARNING: Cannot find core lib version for wxWidgets" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find core lib version for wxWidgets" >&5
+printf "%s\n" "$as_me: WARNING: Cannot find core lib version for wxWidgets" >&2;}
fi
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for edge webview loader" >&5
-$as_echo_n "checking for edge webview loader... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for edge webview loader" >&5
+printf %s "checking for edge webview loader... " >&6; }
WEBVIEW_DLL=$WXDIR/3rdparty/webview2/build/native/$WX_ARCH/WebView2Loader.dll
if test -f "$WEBVIEW_DLL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WEBVIEW_DLL" >&5
-$as_echo "$WEBVIEW_DLL" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WEBVIEW_DLL" >&5
+printf "%s\n" "$WEBVIEW_DLL" >&6; }
WX_WEBVIEW_DLL=$WEBVIEW_DLL
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found in $WEBVIEW_DLL" >&5
-$as_echo "not found in $WEBVIEW_DLL" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found in $WEBVIEW_DLL" >&5
+printf "%s\n" "not found in $WEBVIEW_DLL" >&6; }
WX_WEBVIEW_DLL=
fi
@@ -5856,17 +6727,20 @@ $as_echo "not found in $WEBVIEW_DLL" >&6; }
- $as_echo "#define WXE_WEBVIEW 1" >>confdefs.h
+ printf "%s\n" "#define WXE_WEBVIEW 1" >>confdefs.h
+
fi
-if test "$WXERL_CAN_BUILD_DRIVER" != "false"; then
+if test "$WXERL_CAN_BUILD_DRIVER" != "false"
+then :
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxwidgets 3.0 compatibility " >&5
-$as_echo_n "checking for wxwidgets 3.0 compatibility ... " >&6; }
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxwidgets 3.0 compatibility " >&5
+printf %s "checking for wxwidgets 3.0 compatibility ... " >&6; }
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5882,7 +6756,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include "wx/wx.h"
int
-main ()
+main (void)
{
#if wxMAJOR_VERSION > 2 && (wxMINOR_VERSION == 0 || WXWIN_COMPATIBILITY_3_0 == 1)
@@ -5895,12 +6769,13 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
HAVE_COMPAT30_SUPPORT=yes
-else
+else $as_nop
HAVE_COMPAT30_SUPPORT=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CXXFLAGS=$saved_CXXFLAGS
ac_ext=c
@@ -5909,8 +6784,8 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_COMPAT30_SUPPORT" >&5
-$as_echo "$HAVE_COMPAT30_SUPPORT" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $HAVE_COMPAT30_SUPPORT" >&5
+printf "%s\n" "$HAVE_COMPAT30_SUPPORT" >&6; }
if test X"$HAVE_COMPAT30_SUPPORT" != X"yes" ; then
echo "wxWidgets was not compiled with --enable-compat30, wx will NOT be useable" >> ./CONF_INFO
@@ -5918,14 +6793,14 @@ if test X"$HAVE_COMPAT30_SUPPORT" != X"yes" ; then
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "wxWidgets was not compiled with --enable-compat30, wx will NOT be useable" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: wxWidgets was not compiled with --enable-compat30, wx will NOT be useable" >&5
-$as_echo "$as_me: WARNING: wxWidgets was not compiled with --enable-compat30, wx will NOT be useable" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: wxWidgets was not compiled with --enable-compat30, wx will NOT be useable" >&5
+printf "%s\n" "$as_me: WARNING: wxWidgets was not compiled with --enable-compat30, wx will NOT be useable" >&2;}
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxwidgets opengl support" >&5
-$as_echo_n "checking for wxwidgets opengl support... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wxwidgets opengl support" >&5
+printf %s "checking for wxwidgets opengl support... " >&6; }
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5941,7 +6816,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include "wx/wx.h"
int
-main ()
+main (void)
{
#if wxUSE_GLCANVAS
@@ -5954,15 +6829,16 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
HAVE_GL_SUPPORT=yes
-$as_echo "#define HAVE_GL_SUPPORT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_GL_SUPPORT 1" >>confdefs.h
-else
+else $as_nop
HAVE_GL_SUPPORT=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CXXFLAGS=$saved_CXXFLAGS
ac_ext=c
@@ -5971,8 +6847,8 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_GL_SUPPORT" >&5
-$as_echo "$HAVE_GL_SUPPORT" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $HAVE_GL_SUPPORT" >&5
+printf "%s\n" "$HAVE_GL_SUPPORT" >&6; }
if test X"$HAVE_GL_SUPPORT" != X"yes" ; then
@@ -5981,8 +6857,8 @@ if test X"$HAVE_GL_SUPPORT" != X"yes" ; then
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "wxWidgets don't have gl support, wx will NOT be useable" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: wxWidgets don't have gl support, wx will NOT be useable" >&5
-$as_echo "$as_me: WARNING: wxWidgets don't have gl support, wx will NOT be useable" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: wxWidgets don't have gl support, wx will NOT be useable" >&5
+printf "%s\n" "$as_me: WARNING: wxWidgets don't have gl support, wx will NOT be useable" >&2;}
fi
fi
@@ -5998,11 +6874,10 @@ ac_fn_c_check_type "$LINENO" "GLintptr" "ac_cv_type_GLintptr" "#ifdef WIN32
#endif
"
-if test "x$ac_cv_type_GLintptr" = xyes; then :
+if test "x$ac_cv_type_GLintptr" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_GLINTPTR 1
-_ACEOF
+printf "%s\n" "#define HAVE_GLINTPTR 1" >>confdefs.h
fi
@@ -6016,11 +6891,10 @@ ac_fn_c_check_type "$LINENO" "GLintptrARB" "ac_cv_type_GLintptrARB" "#ifdef WIN3
#endif
"
-if test "x$ac_cv_type_GLintptrARB" = xyes; then :
+if test "x$ac_cv_type_GLintptrARB" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_GLINTPTRARB 1
-_ACEOF
+printf "%s\n" "#define HAVE_GLINTPTRARB 1" >>confdefs.h
fi
@@ -6034,11 +6908,10 @@ ac_fn_c_check_type "$LINENO" "GLchar" "ac_cv_type_GLchar" "#ifdef WIN32
#endif
"
-if test "x$ac_cv_type_GLchar" = xyes; then :
+if test "x$ac_cv_type_GLchar" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_GLCHAR 1
-_ACEOF
+printf "%s\n" "#define HAVE_GLCHAR 1" >>confdefs.h
fi
@@ -6052,11 +6925,10 @@ ac_fn_c_check_type "$LINENO" "GLcharARB" "ac_cv_type_GLcharARB" "#ifdef WIN32
#endif
"
-if test "x$ac_cv_type_GLcharARB" = xyes; then :
+if test "x$ac_cv_type_GLcharARB" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_GLCHARARB 1
-_ACEOF
+printf "%s\n" "#define HAVE_GLCHARARB 1" >>confdefs.h
fi
@@ -6070,11 +6942,10 @@ ac_fn_c_check_type "$LINENO" "GLhalfARB" "ac_cv_type_GLhalfARB" "#ifdef WIN32
#endif
"
-if test "x$ac_cv_type_GLhalfARB" = xyes; then :
+if test "x$ac_cv_type_GLhalfARB" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_GLHALFARB 1
-_ACEOF
+printf "%s\n" "#define HAVE_GLHALFARB 1" >>confdefs.h
fi
@@ -6088,18 +6959,17 @@ ac_fn_c_check_type "$LINENO" "GLint64EXT" "ac_cv_type_GLint64EXT" "#ifdef WIN32
#endif
"
-if test "x$ac_cv_type_GLint64EXT" = xyes; then :
+if test "x$ac_cv_type_GLint64EXT" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_GLINT64EXT 1
-_ACEOF
+printf "%s\n" "#define HAVE_GLINT64EXT 1" >>confdefs.h
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking GLU Callbacks uses Tiger Style" >&5
-$as_echo_n "checking GLU Callbacks uses Tiger Style... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking GLU Callbacks uses Tiger Style" >&5
+printf %s "checking GLU Callbacks uses Tiger Style... " >&6; }
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -6126,7 +6996,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
void CALLBACK foo() {};
int
-main ()
+main (void)
{
GLUtesselator* tess;
@@ -6136,22 +7006,23 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
TESS_CB_TIGER_STYLE=yes
-$as_echo "#define TESS_CB_TIGER_STYLE 1" >>confdefs.h
+printf "%s\n" "#define TESS_CB_TIGER_STYLE 1" >>confdefs.h
-else
+else $as_nop
TESS_CB_TIGER_STYLE=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TESS_CB_TIGER_STYLE" >&5
-$as_echo "$TESS_CB_TIGER_STYLE" >&6; }
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TESS_CB_TIGER_STYLE" >&5
+printf "%s\n" "$TESS_CB_TIGER_STYLE" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can link wxwidgets programs" >&5
-$as_echo_n "checking if we can link wxwidgets programs... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can link wxwidgets programs" >&5
+printf %s "checking if we can link wxwidgets programs... " >&6; }
saved_LIBS=$LIBS
if test X"$WX_HAVE_STATIC_LIBS" = X"true" ; then
@@ -6178,16 +7049,17 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
IMPLEMENT_APP(MyApp)
_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
+if ac_fn_cxx_try_link "$LINENO"
+then :
CAN_LINK_WX=yes
-else
+else $as_nop
CAN_LINK_WX=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CXXFLAGS=$saved_CXXFLAGS
@@ -6198,8 +7070,8 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAN_LINK_WX" >&5
-$as_echo "$CAN_LINK_WX" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CAN_LINK_WX" >&5
+printf "%s\n" "$CAN_LINK_WX" >&6; }
if test X"$CAN_LINK_WX" != X"yes" ; then
echo "Can not link wx program are all developer packages installed?" >> ./CONF_INFO
@@ -6207,87 +7079,104 @@ if test X"$CAN_LINK_WX" != X"yes" ; then
if test X"$with_wx" = X"yes" ; then
as_fn_error $? "Can not link wx program are all developer packages installed?" "$LINENO" 5
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not link wx program are all developer packages installed?" >&5
-$as_echo "$as_me: WARNING: Can not link wx program are all developer packages installed?" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Can not link wx program are all developer packages installed?" >&5
+printf "%s\n" "$as_me: WARNING: Can not link wx program are all developer packages installed?" >&2;}
fi
fi
+
fi
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Treat certain GCC warnings as errors
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="-Werror=return-type $CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CXXFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to CXXFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to CXXFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to CXXFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $CXXFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CXXFLAGS="-Werror=return-type $CXXFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
fi
# Check whether --enable-sanitizers was given.
-if test "${enable_sanitizers+set}" = set; then :
+if test ${enable_sanitizers+y}
+then :
enableval=$enable_sanitizers;
case "$enableval" in
no) sanitizers= ;;
@@ -6317,12 +7206,7 @@ esac
-
-if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then
- WXERL_SYS_TYPE=`erl -noshell -eval 'io:format("~s~n",[erlang:system_info(system_architecture)])' -s erlang halt`
-else
- WXERL_SYS_TYPE=$TARGET
-fi
+WXERL_SYS_TYPE=$TARGET
@@ -6360,8 +7244,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -6391,15 +7275,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -6413,8 +7297,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -6467,7 +7351,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -6483,8 +7367,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -6507,14 +7391,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -6524,46 +7410,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -6572,13 +7458,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -6587,8 +7466,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -6600,30 +7483,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -6636,13 +7499,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -6669,18 +7533,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -6692,12 +7558,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -6728,7 +7595,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -6750,6 +7617,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -6763,6 +7634,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -6804,7 +7681,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -6813,7 +7690,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6876,7 +7753,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -6925,14 +7802,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -6969,21 +7848,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -7011,7 +7890,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -7025,7 +7904,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -7051,7 +7930,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -7279,7 +8158,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -7287,17 +8166,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -7314,7 +8193,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -7338,9 +8217,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -7393,8 +8272,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -7436,9 +8315,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -7485,8 +8364,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
@@ -7497,3 +8376,4 @@ fi
+
diff --git a/lib/wx/configure.in b/lib/wx/configure.ac
index 4d1e331ea3..d49399c540 100644
--- a/lib/wx/configure.in
+++ b/lib/wx/configure.ac
@@ -18,11 +18,13 @@ dnl limitations under the License.
dnl
dnl %CopyrightEnd%
-AC_INIT()
+AC_INIT
-AC_CONFIG_AUX_DIRS($srcdir/autoconf)
+m4_include([otp.m4])
-AC_PREREQ(2.59)
+AC_CONFIG_AUX_DIR([${ERL_TOP}/make/autoconf])
+
+AC_PREREQ([2.71])
## Delete previous failed configure results
if test -f ./CONF_INFO; then
@@ -39,25 +41,12 @@ AC_DEFUN([WX_MSG_ERROR],
fi
])
-
-if test -z "$ERL_TOP" || test ! -d $ERL_TOP ; then
- AC_MSG_ERROR([ERL_TOP is not set])
-else
- erl_top=${ERL_TOP}
- AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf)
- WX_BUILDING_INSIDE_ERLSRC=true
-fi
-
AC_ARG_WITH(wx,
[ --with-wxdir=PATH specify location of wxWidgets include and lib
--with-wx use wxWidgets (default)
--without-wx don't use wxWidgets])
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
-else
- host_os=win32
-fi
+ERL_CANONICAL_SYSTEM_TYPE
case $host_os in
mingw32)
@@ -108,8 +97,10 @@ OBJC_CC=$CC
OBJC_CFLAGS=""
CXXFLAGS=""
dnl NOTE: CPPFLAGS will be included in CFLAGS at the end
-case $host_os in
- darwin*)
+AS_CASE([$host_os],
+
+ [darwin*],
+ [
AC_MSG_CHECKING([Checking wxWidgets for min version:])
WX_CC=`wx-config --cc`
MAC_MIN=`echo "$WX_CC" | sed 's/^[[^ ]]*\ *//'`
@@ -117,7 +108,7 @@ case $host_os in
AC_MSG_CHECKING([if compiler accepts -ObjC])
CFLAGS="$CFLAGS -ObjC"
- AC_TRY_COMPILE([],[;], accept_objc_flag=true, accept_objc_flag=false)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[;]])],[accept_objc_flag=true],[accept_objc_flag=false])
if test "X$accept_objc_flag" = "Xtrue"; then
AC_MSG_RESULT([yes])
C_ONLY_FLAGS="-ObjC"
@@ -177,22 +168,34 @@ case $host_os in
fi
CFLAGS="$USER_CFLAGS $MAC_MIN -Wno-deprecated-declarations"
CPPFLAGS="$CPPFLAGS -D_MACOSX $PTHR_CFLAGS"
- ;;
- mingw32)
+ ],
+
+ [mingw32],
+ [
CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE"
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
AC_MSG_WARN([Reverting to 32-bit time_t])
CPPFLAGS="$CPPFLAGS -D_USE_32BIT_TIME_T"
- ;;
- win32)
+ ],
+
+ [win32],
+ [
CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE"
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
- ;;
- *)
- CFLAGS="$CFLAGS -Wno-deprecated-declarations"
- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE $PTHR_CFLAGS"
- ;;
-esac
+ ],
+
+ [
+ GLIB_CFLAGS=`pkg-config --silence-errors --cflags glib-2.0`
+ GLIB_LIBS=`pkg-config --silence-errors --libs glib-2.0`
+ if test X"$GLIB_CFLAGS" != X ; then
+ HAVE_GLIB="-DHAVE_GLIB=1"
+ fi
+ CFLAGS="$CFLAGS -Wno-deprecated-declarations"
+ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE $PTHR_CFLAGS $HAVE_GLIB"
+ ])
+
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBS)
AC_SUBST(OBJC_CC)
AC_SUBST(OBJC_CFLAGS)
@@ -249,47 +252,54 @@ dnl Use -O1 -fno-move-loop-invariants for wxe_funcs.cpp to reduce
dnl compilation time
dnl
-if test "x$GCC" = xyes -a X"$host_os" != X"win32" ; then
+AS_IF([test "x$GCC" = xyes -a X"$host_os" != X"win32"],
+ [
CXXNOOPT="-O1"
LM_TRY_ENABLE_CFLAG([-fno-move-loop-invariants], [CXXNOOPT])
LM_TRY_ENABLE_CFLAG([-fno-var-tracking-assignments], [CXXNOOPT])
-fi
+ ])
dnl
dnl Opengl tests
dnl
-if test X"$host_os" != X"win32" ; then
+AS_IF([test X"$host_os" != X"win32"],
+ [
AC_CHECK_HEADERS([GL/gl.h], [],
[AC_CHECK_HEADERS([OpenGL/gl.h])])
- if test X"$ac_cv_header_GL_gl_h" != Xyes &&
- test X"$ac_cv_header_OpenGL_gl_h" != Xyes
- then
+ AS_IF([test X"$ac_cv_header_GL_gl_h" != Xyes && test X"$ac_cv_header_OpenGL_gl_h" != Xyes],
+ [
saved_CPPFLAGS="$CPPFLAGS"
AC_MSG_NOTICE(Checking for OpenGL headers in /usr/X11R6)
CPPFLAGS="-isystem /usr/X11R6/include $CPPFLAGS"
$as_unset ac_cv_header_GL_gl_h
AC_CHECK_HEADERS([GL/gl.h])
- if test X"$ac_cv_header_GL_gl_h" != Xyes ; then
+ AS_IF([test X"$ac_cv_header_GL_gl_h" != Xyes],
+ [
AC_MSG_NOTICE(Checking for OpenGL headers in /usr/local)
CPPFLAGS="-isystem /usr/local/include $saved_CPPFLAGS"
$as_unset ac_cv_header_GL_gl_h
AC_CHECK_HEADERS([GL/gl.h])
- if test X"$ac_cv_header_GL_gl_h" != Xyes ; then
+ AS_IF([test X"$ac_cv_header_GL_gl_h" != Xyes],
+ [
WX_MSG_ERROR([No OpenGL headers found, wx will NOT be usable])
CPPFLAGS="$saved_CPPFLAGS"
- else
+ ],
+ [
GL_LIBS="-L/usr/local/lib $GL_LIBS"
- fi
- else
+ ])
+ ],
+ [
GL_LIBS="-L/usr/X11R6/lib $GL_LIBS"
- fi
- fi
-else
+ ])
+ ])
+ ],
+ [
AC_CHECK_HEADERS([gl/gl.h],[],[],[#include <windows.h>])
-fi
+ ])
-if test X"$host_os" != X"win32" ; then
+AS_IF([test X"$host_os" != X"win32"],
+ [
AC_CHECK_HEADERS([GL/glu.h], [],
[AC_CHECK_HEADERS([OpenGL/glu.h])])
if test X"$ac_cv_header_GL_glu_h" != Xyes &&
@@ -297,9 +307,10 @@ if test X"$host_os" != X"win32" ; then
then
WX_MSG_ERROR([No GLU headers found, wx will NOT be usable])
fi
-else
+ ],
+ [
AC_CHECK_HEADERS([gl/glu.h],[],[],[#include <windows.h>])
-fi
+ ])
AC_SUBST(GL_LIBS)
@@ -318,15 +329,19 @@ ERL=erl
ERLANG_ROOT_DIR=$ERL_TOP
AC_SUBST(ERLC)
-AC_SUBST(WX_BUILDING_INSIDE_ERLSRC)
AC_SUBST(ERLANG_ROOT_DIR)
dnl
dnl Check for wxwidgets
dnl
-if test "$cross_compiling" = "yes"; then
+AS_IF(
+ [test "$cross_compiling" = "yes"],
+ [
WX_MSG_ERROR([Cross compilation of the wx driver is not supported yet, wx will NOT be usable])
-elif test X"$MIXED_VC" = X"no"; then
+ ],
+
+ [test X"$MIXED_VC" = X"no"],
+ [
m4_include(wxwin-nothrow.m4)
AM_OPTIONS_WXCONFIG
@@ -426,7 +441,9 @@ elif test X"$MIXED_VC" = X"no"; then
is in LD_LIBRARY_PATH or equivalent variable and
wxWidgets version is $reqwx or above.])
fi
-else
+ ],
+
+ [ #else
AC_MSG_CHECKING(for wxWidgets in standard locations)
echo
# Check whether --with-wxdir was given.
@@ -535,9 +552,10 @@ else
AC_SUBST(WX_RESCOMP)
AC_SUBST(WX_WEBVIEW_DLL)
AC_DEFINE([WXE_WEBVIEW])
-fi
+ ])
-if test "$WXERL_CAN_BUILD_DRIVER" != "false"; then
+AS_IF([test "$WXERL_CAN_BUILD_DRIVER" != "false"],
+[
AC_SUBST(WX_HAVE_STATIC_LIBS)
AC_SUBST(RC_FILE_TYPE)
@@ -618,7 +636,7 @@ AC_LANG_PUSH(C++)
saved_CXXFLAGS=$CXXFLAGS
CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS"
-AC_TRY_COMPILE([
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#ifdef WIN32
# include <windows.h>
# include <gl/glu.h>
@@ -631,14 +649,11 @@ AC_TRY_COMPILE([
# define CALLBACK
#endif
void CALLBACK foo() {};
- ],
- [
+ ]], [[
GLUtesselator* tess;
gluTessCallback(tess,GLU_TESS_VERTEX,(GLvoid (*)(...)) foo);
- ],
- [TESS_CB_TIGER_STYLE=yes
- AC_DEFINE(TESS_CB_TIGER_STYLE, [1], [GLU Callbacks are Tiger style])],
- TESS_CB_TIGER_STYLE=no)
+ ]])],[TESS_CB_TIGER_STYLE=yes
+ AC_DEFINE(TESS_CB_TIGER_STYLE, [1], [GLU Callbacks are Tiger style])],[TESS_CB_TIGER_STYLE=no])
AC_MSG_RESULT($TESS_CB_TIGER_STYLE)
AC_SUBST(TESS_CB_TIGER_STYLE)
@@ -653,10 +668,10 @@ if test X"$WX_HAVE_STATIC_LIBS" = X"true" ; then
LIBS=$WX_LIBS_STATIC
fi
-AC_LINK_IFELSE([AC_LANG_SOURCE([
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
#include "wx/wx.h"
#include "wx/stc/stc.h"
- ])
+
class MyApp : public wxApp
{
@@ -669,7 +684,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
};
};
IMPLEMENT_APP(MyApp)
- ],
+ ]])],
[
CAN_LINK_WX=yes
],
@@ -686,15 +701,16 @@ if test X"$CAN_LINK_WX" != X"yes" ; then
WX_MSG_ERROR([Can not link wx program are all developer packages installed?])
fi
-fi dnl - if test "$WXERL_CAN_BUILD_DRIVER" != "false"
+]) dnl - if test "$WXERL_CAN_BUILD_DRIVER" != "false"
AC_SUBST(WXERL_CAN_BUILD_DRIVER)
-if test "x$GCC" = xyes; then
+AS_IF([test "x$GCC" = xyes],
+ [
# Treat certain GCC warnings as errors
LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS])
LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CXXFLAGS])
-fi
+ ])
dnl ----------------------------------------------------------------------
dnl Enable -fsanitize= flags.
@@ -734,13 +750,7 @@ AC_SUBST(SO_EXT)
AC_SUBST(RUN_ERL)
AC_SUBST(CXXNOOPTFLAGS)
-
-if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then
- dnl Find driver directory name according to erlang
- WXERL_SYS_TYPE=`erl -noshell -eval 'io:format("~s~n",[[erlang:system_info(system_architecture)]])' -s erlang halt`
-else
- WXERL_SYS_TYPE=$TARGET
-fi
+WXERL_SYS_TYPE=$TARGET
AC_SUBST(WXERL_SYS_TYPE)
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index cab451fa19..f155b7a551 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2009</year><year>2021</year>
+ <year>2009</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,55 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 2.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Added environment variable <c>WX_MACOS_NON_GUI_APP</c> to
+ allow user to override <c>OSXIsGUIApplication</c>
+ behavior.</p>
+ <p>
+ Own Id: OTP-18213 Aux Id: PR-6113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Wx 2.2</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Input for <c>configure</c> scripts adapted to
+ <c>autoconf</c> 2.71.</p>
+ <p>
+ Own Id: OTP-17414 Aux Id: PR-4967 </p>
+ </item>
+ <item>
+ <p>
+ Added <c>aux1Down</c> and <c>aux2Down</c> fields to the
+ <c>wxMouseState</c> record. Since one record have been
+ changed a recompilation of user code might be required.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-17950</p>
+ </item>
+ <item>
+ <p>
+ Add mac specific menubar functions.</p>
+ <p>
+ Own Id: OTP-18008 Aux Id: PR-5816 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 2.1.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -281,7 +330,7 @@
<item>
<p>
Fixed wx initialization on mac, top level menus did not
- always work on newer MacOS versions. The menues will not
+ always work on newer MacOS versions. The menus will not
work until wxWidgets-3.1.5 is released and used on these
MacOS versions.</p>
<p>
@@ -1061,7 +1110,7 @@
<item>
<p>
Wx on MacOS X generated complains on stderr about certain
- cocoa functions not beeing called from the "Main thread".
+ cocoa functions not being called from the "Main thread".
This is now corrected.</p>
<p>
Own Id: OTP-9081</p>
@@ -1239,7 +1288,7 @@
<list>
<item>
<p>wxHtmlWindow class implemented.</p> <p>All exceptions
- from callbacks are now catched and written to the
+ from callbacks are now caught and written to the
log.</p> <p>Some defines where wrong in 'wx.hrl'.</p>
<p><c>wx:batch/1</c> and friends could hang forever if
for instance a breakpoint was set inside the fun. That
diff --git a/lib/wx/doc/src/wx.xml b/lib/wx/doc/src/wx.xml
index 982343cda4..a405b0a274 100644
--- a/lib/wx/doc/src/wx.xml
+++ b/lib/wx/doc/src/wx.xml
@@ -141,6 +141,47 @@ wxGBPosition={r,c},wxGBSpan={rs,cs},wxGridCellCoords={r,c}.</p>
another process wx environment.</p>
</desc></func>
<func>
+<name since="">subscribe_events() -&gt; ok</name>
+<fsummary>Adds the calling process to the list of of processes that are
+listening to wx application events.</fsummary>
+
+<desc><marker id="subscribe_events-0"/>
+<p>
+ Adds the calling process to the list of of processes that are listening to
+ wx application events.
+</p>
+
+<p>
+ At the moment these are all MacOSX specific events corresponding to
+ <c>MacNewFile()</c>
+ and friends from wxWidgets
+ <url href="https://docs.wxwidgets.org/trunk/classwx_app.html">wxApp</url>:
+</p>
+
+<list>
+ <item>
+ <p><c>{new_file, ""}</c></p>
+ </item>
+ <item>
+ <p><c>{open_file, Filename}</c></p>
+ </item>
+ <item>
+ <p><c>{print_file, Filename}</c></p>
+ </item>
+ <item>
+ <p><c>{open_url, Url}</c></p>
+ </item>
+ <item>
+ <p><c>{reopen_app, ""}</c></p>
+ </item>
+</list>
+
+<p>
+ The call always returns ok but will have sent any already received
+ events to the calling process.
+</p>
+</desc></func>
+<func>
<name since="">null() -&gt; <seeerl marker="#type-wx_object">wx_object()</seeerl></name>
<fsummary>Returns the null object.</fsummary>
@@ -287,4 +328,4 @@ library.</p>
<authors>
<aname> </aname>
-<email> </email></authors></erlref> \ No newline at end of file
+<email> </email></authors></erlref>
diff --git a/lib/wx/doc/src/wxEvtHandler.xml b/lib/wx/doc/src/wxEvtHandler.xml
index c38da3e127..fdc96971ca 100644
--- a/lib/wx/doc/src/wxEvtHandler.xml
+++ b/lib/wx/doc/src/wxEvtHandler.xml
@@ -7,7 +7,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2022</year>
<holder>wxWidgets team.</holder></copyright>
<legalnotice>Licensed under the wxWindows Free Documentation Licence, Version 3
</legalnotice>
@@ -48,7 +48,7 @@
</p><p>id:<c>{id, integer()} </c> The identifier (or first of the identifier range) to be associated with this event handler. Default is ?wxID_ANY
</p><p>lastid:<c>{lastId,integer()} </c> The second part of the identifier range. If used 'id' must be set as the starting identifier range. Default is ?wxID_ANY
</p><p>skip:<c>{skip,boolean()} </c> If skip is true further event_handlers will be called. This is not used if the 'callback' option is used. Default is <c>false</c>.
- </p><p>callback:<c>{callback,function()} </c> Use a callback<c>fun(EventRecord::wx(),EventObject::wxObject()) </c> to process the event. Default not specfied i.e. a message will be delivered to the process calling this function.
+ </p><p>callback:<c>{callback,function()} </c> Use a callback<c>fun(EventRecord::wx(),EventObject::wxObject()) </c> to process the event. Default not specified i.e. a message will be delivered to the process calling this function.
</p><p>userData:<c>{userData,term()} </c> An erlang term that will be sent with the event. Default: [].
</p></desc>
</func>
diff --git a/lib/wx/doc/src/wxMenuBar.xml b/lib/wx/doc/src/wxMenuBar.xml
index 2b81729978..0f4431dc32 100644
--- a/lib/wx/doc/src/wxMenuBar.xml
+++ b/lib/wx/doc/src/wxMenuBar.xml
@@ -7,7 +7,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2022</year>
<holder>wxWidgets team.</holder></copyright>
<legalnotice>Licensed under the wxWindows Free Documentation Licence, Version 3
</legalnotice>
@@ -208,6 +208,23 @@
</func>
<func>
+ <name name="macGetCommonMenuBar" arity="0" clause_i="1" since=""/>
+ <fsummary>Enables you to get the global menubar on Mac, that is, the menubar displayed when the app is running without any frames open. </fsummary>
+ <desc><p>Enables you to get the global menubar on Mac, that is, the menubar displayed when the app is running without any frames open.
+ </p><p>Return: The global menubar.
+ </p><p>Remark: Only exists on Mac, other platforms do not have this method.
+ </p><p>Only for:wxosx</p></desc>
+ </func>
+
+ <func>
+ <name name="macSetCommonMenuBar" arity="1" clause_i="1" since=""/>
+ <fsummary>Enables you to set the global menubar on Mac, that is, the menubar displayed when the app is running without any frames open. </fsummary>
+ <desc><p>Enables you to set the global menubar on Mac, that is, the menubar displayed when the app is running without any frames open.
+ </p><p>Remark: Only exists on Mac, other platforms do not have this method.
+ </p><p>Only for:wxosx</p></desc>
+ </func>
+
+ <func>
<name name="isEnabled" arity="2" clause_i="1" since=""/>
<fsummary>Determines whether an item is enabled. </fsummary>
<desc><p>Determines whether an item is enabled.
diff --git a/lib/wx/doc/src/wxMouseEvent.xml b/lib/wx/doc/src/wxMouseEvent.xml
index 5c690102e4..2f9297be83 100644
--- a/lib/wx/doc/src/wxMouseEvent.xml
+++ b/lib/wx/doc/src/wxMouseEvent.xml
@@ -7,7 +7,7 @@
<erlref>
<header>
<copyright>
- <year>2020</year><year>2021</year>
+ <year>2020</year><year>2022</year>
<holder>wxWidgets team.</holder></copyright>
<legalnotice>Licensed under the wxWindows Free Documentation Licence, Version 3
</legalnotice>
@@ -322,5 +322,47 @@
</p><p>Notice that before wxWidgets 2.9.4 this method returned <c>int</c>.
</p></desc>
</func>
+
+ <func>
+ <name name="aux1DClick" arity="1" clause_i="1" since=""/>
+ <fsummary>Returns true if the event was a first extra button double click. </fsummary>
+ <desc><p>Returns true if the event was a first extra button double click.
+ </p></desc>
+ </func>
+
+ <func>
+ <name name="aux1Down" arity="1" clause_i="1" since=""/>
+ <fsummary>Returns true if the first extra button mouse button changed to down. </fsummary>
+ <desc><p>Returns true if the first extra button mouse button changed to down.
+ </p></desc>
+ </func>
+
+ <func>
+ <name name="aux1Up" arity="1" clause_i="1" since=""/>
+ <fsummary>Returns true if the first extra button mouse button changed to up. </fsummary>
+ <desc><p>Returns true if the first extra button mouse button changed to up.
+ </p></desc>
+ </func>
+
+ <func>
+ <name name="aux2DClick" arity="1" clause_i="1" since=""/>
+ <fsummary>Returns true if the event was a second extra button double click. </fsummary>
+ <desc><p>Returns true if the event was a second extra button double click.
+ </p></desc>
+ </func>
+
+ <func>
+ <name name="aux2Down" arity="1" clause_i="1" since=""/>
+ <fsummary>Returns true if the second extra button mouse button changed to down. </fsummary>
+ <desc><p>Returns true if the second extra button mouse button changed to down.
+ </p></desc>
+ </func>
+
+ <func>
+ <name name="aux2Up" arity="1" clause_i="1" since=""/>
+ <fsummary>Returns true if the second extra button mouse button changed to up. </fsummary>
+ <desc><p>Returns true if the second extra button mouse button changed to up.
+ </p></desc>
+ </func>
</funcs>
</erlref>
diff --git a/lib/wx/examples/demo/Makefile b/lib/wx/examples/demo/Makefile
index d1c2d23a71..123c54580f 100644
--- a/lib/wx/examples/demo/Makefile
+++ b/lib/wx/examples/demo/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ TESTTARGETS = $(TESTMODS:%=%.beam)
TESTSRC = $(TESTMODS:%=%.erl)
# Targets
-opt debug: $(TESTTARGETS)
+$(TYPES): $(TESTTARGETS)
clean:
rm -f $(TESTTARGETS)
rm -f *~ core erl_crash.dump
diff --git a/lib/wx/examples/demo/demo.erl b/lib/wx/examples/demo/demo.erl
index 6e1465973a..dfcec2ef1c 100644
--- a/lib/wx/examples/demo/demo.erl
+++ b/lib/wx/examples/demo/demo.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -82,7 +82,7 @@ init(Options) ->
wxMenuBar:append(MB, Help, "&Help"),
wxFrame:setMenuBar(Frame,MB),
- wxFrame:connect(Frame, command_menu_selected),
+ wxFrame:connect(Frame, command_menu_selected, [{skip, true}]),
wxFrame:connect(Frame, close_window),
_SB = wxFrame:createStatusBar(Frame,[]),
diff --git a/lib/wx/examples/demo/demo_html_tagger.erl b/lib/wx/examples/demo/demo_html_tagger.erl
index cc24cbaa67..08f42820a3 100644
--- a/lib/wx/examples/demo/demo_html_tagger.erl
+++ b/lib/wx/examples/demo/demo_html_tagger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
%% That's because this program uses some pretty dodgy techniques to
%% get at the data it requires.
-%% I use epp_dodger to parse the file and the new imporved erl_scan
+%% I use epp_dodger to parse the file and the new improved erl_scan
%% find the exact values of the tokens
%% epp_dodger returns an objects of type erl_syntax which are pretty
diff --git a/lib/wx/examples/demo/ex_sashWindow.erl b/lib/wx/examples/demo/ex_sashWindow.erl
index 63528f65d1..80d0364482 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,7 +65,7 @@ do_init(Config) ->
Win2 = wxPanel:new(BottomSash, []),
wxStaticText:new(Win2, ?wxID_ANY, "This is the bottom sash", []),
- %% Make the bottom edge of the top sash dragable
+ %% Make the bottom edge of the top sash draggable
wxSashWindow:setSashVisible(TopSash, ?wxSASH_BOTTOM, true),
wxPanel:connect(Panel, sash_dragged),
wxPanel:connect(Panel, size),
diff --git a/lib/wx/examples/demo/ex_sizers.erl b/lib/wx/examples/demo/ex_sizers.erl
index 800f17f014..8b0baf4b16 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ do_init(Config) ->
"Weighting Factor",
"Edge Affinity",
"Spacer",
- "Centering In Avalible Space",
+ "Centering In Available Space",
"Simple Border",
"East And West Border",
"North And South Border",
@@ -149,7 +149,7 @@ create_example(Parent, Example) ->
north_and_south_border(Panel);
"Simple Border" ->
simple_border(Panel);
- "Centering In Avalible Space" ->
+ "Centering In Available Space" ->
centering_in_avalible_space(Panel);
"Spacer" ->
spacer(Panel);
diff --git a/lib/wx/examples/demo/ex_splitterWindow.erl b/lib/wx/examples/demo/ex_splitterWindow.erl
index 14f63600a3..153a0da61a 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -54,14 +54,14 @@ do_init(Config) ->
Splitter = wxSplitterWindow:new(Panel, []),
- Win1 = wxTextCtrl:new(Splitter, 1, [{value, "Splitted Window 1"},
+ Win1 = wxTextCtrl:new(Splitter, 1, [{value, "Split Window 1"},
{style, ?wxDEFAULT bor ?wxTE_MULTILINE}]),
- Win2 = wxTextCtrl:new(Splitter, 1, [{value, "Splitted Window 1"},
+ Win2 = wxTextCtrl:new(Splitter, 1, [{value, "Split Window 1"},
{style, ?wxDEFAULT bor ?wxTE_MULTILINE}]),
wxSplitterWindow:splitVertically(Splitter, Win1, Win2),
wxSplitterWindow:setSashGravity(Splitter, 0.5),
- %% Set pane-size =/= 0 to not unsplit on doubleclick
+ %% Set pane-size =/= 0 to not unsplit on double-click
%% on the splitter
wxSplitterWindow:setMinimumPaneSize(Splitter,50),
diff --git a/lib/wx/examples/simple/Makefile b/lib/wx/examples/simple/Makefile
index 075528533a..16ac01d40d 100644
--- a/lib/wx/examples/simple/Makefile
+++ b/lib/wx/examples/simple/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2021. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ TESTTARGETS = $(TESTMODS:%=%.beam)
TESTSRC = $(TESTMODS:%=%.erl)
# Targets
-opt debug: $(TESTTARGETS)
+$(TYPES): $(TESTTARGETS)
clean:
rm -f $(TESTTARGETS)
rm -f *~ core erl_crash.dump
diff --git a/lib/wx/examples/simple/menu.erl b/lib/wx/examples/simple/menu.erl
index 829c88a3d5..4a5e9b4729 100644
--- a/lib/wx/examples/simple/menu.erl
+++ b/lib/wx/examples/simple/menu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -309,7 +309,7 @@ create_help_menu() ->
HelpMenu = wxMenu:new(),
% unlike wxwidgets the stock menu items still need text to be given,
% although help text does appear
- % Note the keybord accelerator
+ % Note the keyboard accelerator
wxMenu:append(HelpMenu, wxMenuItem:new([
{id, ?menuID_HELP_ABOUT},
%{text, "&About\tF1"},
diff --git a/lib/wx/examples/simple/minimal.erl b/lib/wx/examples/simple/minimal.erl
index 45efc06462..5741243530 100644
--- a/lib/wx/examples/simple/minimal.erl
+++ b/lib/wx/examples/simple/minimal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ create_window(Wx) ->
% unlike wxwidgets the stock menu items still need text to be given,
% although help text does appear
_QuitMenuItem = wxMenu:append(FileM, ?wxID_EXIT, "&Quit"),
- % Note the keybord accelerator
+ % Note the keyboard accelerator
_AboutMenuItem = wxMenu:append(HelpM, ?wxID_ABOUT, "&About...\tF1"),
wxMenu:appendSeparator(HelpM),
diff --git a/lib/wx/examples/sudoku/Makefile b/lib/wx/examples/sudoku/Makefile
index e6f35c689a..ccdcb7cd9f 100644
--- a/lib/wx/examples/sudoku/Makefile
+++ b/lib/wx/examples/sudoku/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ TESTTARGETS = $(TESTMODS:%=%.beam)
TESTSRC = $(TESTMODS:%=%.erl)
# Targets
-opt debug: $(TESTTARGETS)
+$(TYPES): $(TESTTARGETS)
clean:
rm -f $(TESTTARGETS)
rm -f *~ core erl_crash.dump
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index c2e918bb2d..38ba71c5f7 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -315,7 +315,8 @@
-record(wxMouseState, {x :: integer(), y :: integer(),
leftDown :: boolean(), middleDown :: boolean(), rightDown :: boolean(),
controlDown :: boolean(), shiftDown :: boolean(),
- altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean()
+ altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean(),
+ aux1Down :: boolean(), aux2Down :: boolean()
}).
-record(wxHtmlLinkInfo, {
href :: unicode:chardata(), target :: unicode:chardata()
@@ -1432,6 +1433,12 @@
-define(wxID_MDI_WINDOW_PREV, (?wxID_MDI_WINDOW_FIRST+4)).
-define(wxID_MDI_WINDOW_NEXT, (?wxID_MDI_WINDOW_FIRST+5)).
-define(wxID_MDI_WINDOW_LAST, ?wxID_MDI_WINDOW_NEXT).
+-define(wxID_OSX_MENU_FIRST, 5250).
+-define(wxID_OSX_HIDE, ?wxID_OSX_MENU_FIRST).
+-define(wxID_OSX_HIDEOTHERS, (?wxID_OSX_MENU_FIRST+1)).
+-define(wxID_OSX_SHOWALL, (?wxID_OSX_MENU_FIRST+2)).
+-define(wxID_OSX_SERVICES, (?wxID_OSX_MENU_FIRST+3)).
+-define(wxID_OSX_MENU_LAST, ?wxID_OSX_SERVICES).
-define(wxID_FILEDLGG, 5900).
-define(wxID_FILECTRL, 5950).
-define(wxID_HIGHEST, 5999).
diff --git a/lib/wx/src/Makefile b/lib/wx/src/Makefile
index 7e2eb38f2f..ce14c0b6df 100644
--- a/lib/wx/src/Makefile
+++ b/lib/wx/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2021. All Rights Reserved.
+# Copyright Ericsson AB 2008-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -75,7 +75,7 @@ APPUP_TARGET = $(EBIN)/$(APPUP_FILE)
ifdef TERTIARY_BOOTSTRAP
opt: $(EBIN)/wx_object.beam
else
- debug opt: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ $(TYPES): $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
endif
clean:
diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl
index 87e25efaa5..d1c6e76937 100644
--- a/lib/wx/src/gen/gl.erl
+++ b/lib/wx/src/gen/gl.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -300,6 +300,7 @@
blendBarrierKHR/0,maxShaderCompilerThreadsKHR/1,depthBoundsEXT/2]).
-export([get_interface/0, rec/1, lookup_func/0]).
+-nifs([lookup_func/0]).
-define(nif_stub,nif_stub_error(?LINE)).
%% @hidden
nif_stub_error(Line) ->
diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl
index 6d4d390205..15a80237fa 100644
--- a/lib/wx/src/gen/glu.erl
+++ b/lib/wx/src/gen/glu.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@
%% @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
+%% vertex positions. Returned is a list of indices 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.
diff --git a/lib/wx/src/gen/wxEvtHandler.erl b/lib/wx/src/gen/wxEvtHandler.erl
index 824ff62133..bafd91ee51 100644
--- a/lib/wx/src/gen/wxEvtHandler.erl
+++ b/lib/wx/src/gen/wxEvtHandler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,10 +33,10 @@
%% (in another process) to handle the event. The callback should be of
%% arity 2. fun(EventRecord::wx(), EventObject::wxObject()).
%%
-%% Beware that the callback will be in executed in new process each time.
+%% Beware that the callback will be executed in a new process each time.
%%
%% <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html">
-%% The orginal documentation</a>.
+%% The original documentation</a>.
%%
%%
-module(wxEvtHandler).
@@ -71,8 +71,9 @@ connect(This, EventType) ->
%% {skip, boolean()}, If skip is true further event_handlers will be called.
%% This is not used if the 'callback' option is used.
%% Default false.
+%% callback Use `wx_object' callback `handle_sync_event/3'.
%% {callback, function()} Use a callback fun(EventRecord::wx(), EventObject::wxObject())
-%% to process the event. Default not specfied i.e. a message will
+%% to process the event. Default not specified 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
diff --git a/lib/wx/src/gen/wxMenuBar.erl b/lib/wx/src/gen/wxMenuBar.erl
index b151def69d..ca637e9053 100644
--- a/lib/wx/src/gen/wxMenuBar.erl
+++ b/lib/wx/src/gen/wxMenuBar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,8 +23,9 @@
-export([append/3,check/3,destroy/1,enable/3,enableTop/3,findItem/2,findMenu/2,
findMenuItem/3,getAutoWindowMenu/0,getHelpString/2,getLabel/2,getLabelTop/2,
getMenu/2,getMenuCount/1,getMenuLabel/2,getMenuLabelText/2,insert/4,
- isChecked/2,isEnabled/2,new/0,new/1,oSXGetAppleMenu/1,remove/2,replace/4,
- setAutoWindowMenu/1,setHelpString/3,setLabel/3,setLabelTop/3,setMenuLabel/3]).
+ isChecked/2,isEnabled/2,macGetCommonMenuBar/0,macSetCommonMenuBar/1,
+ new/0,new/1,oSXGetAppleMenu/1,remove/2,replace/4,setAutoWindowMenu/1,
+ setHelpString/3,setLabel/3,setLabelTop/3,setMenuLabel/3]).
%% inherited exports
-export([cacheBestSize/2,canSetTransparent/1,captureMouse/1,center/1,center/2,
@@ -253,6 +254,19 @@ oSXGetAppleMenu(#wx_ref{type=ThisT}=This) ->
wxe_util:queue_cmd(This,?get_env(),?wxMenuBar_OSXGetAppleMenu),
wxe_util:rec(?wxMenuBar_OSXGetAppleMenu).
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmenubar.html#wxmenubarmacgetcommonmenubar">external documentation</a>.
+-spec macGetCommonMenuBar() -> wxMenuBar().
+macGetCommonMenuBar() ->
+ wxe_util:queue_cmd(?get_env(), ?wxMenuBar_MacGetCommonMenuBar),
+ wxe_util:rec(?wxMenuBar_MacGetCommonMenuBar).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmenubar.html#wxmenubarmacsetcommonmenubar">external documentation</a>.
+-spec macSetCommonMenuBar(Menubar) -> 'ok' when
+ Menubar::wxMenuBar().
+macSetCommonMenuBar(#wx_ref{type=MenubarT}=Menubar) ->
+ ?CLASS(MenubarT,wxMenuBar),
+ wxe_util:queue_cmd(Menubar,?get_env(),?wxMenuBar_MacSetCommonMenuBar).
+
%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmenubar.html#wxmenubarisenabled">external documentation</a>.
-spec isEnabled(This, Id) -> boolean() when
This::wxMenuBar(), Id::integer().
diff --git a/lib/wx/src/gen/wxMouseEvent.erl b/lib/wx/src/gen/wxMouseEvent.erl
index 897db7f29d..85f1852117 100644
--- a/lib/wx/src/gen/wxMouseEvent.erl
+++ b/lib/wx/src/gen/wxMouseEvent.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@
-module(wxMouseEvent).
-include("wxe.hrl").
--export([altDown/1,button/2,buttonDClick/1,buttonDClick/2,buttonDown/1,buttonDown/2,
+-export([altDown/1,aux1DClick/1,aux1Down/1,aux1Up/1,aux2DClick/1,aux2Down/1,
+ aux2Up/1,button/2,buttonDClick/1,buttonDClick/2,buttonDown/1,buttonDown/2,
buttonUp/1,buttonUp/2,cmdDown/1,controlDown/1,dragging/1,entering/1,
getButton/1,getLinesPerAction/1,getLogicalPosition/2,getPosition/1,
getWheelAxis/1,getWheelDelta/1,getWheelRotation/1,getX/1,getY/1,isButton/1,
@@ -374,6 +375,54 @@ getWheelAxis(#wx_ref{type=ThisT}=This) ->
wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_GetWheelAxis),
wxe_util:rec(?wxMouseEvent_GetWheelAxis).
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmouseevent.html#wxmouseeventaux1dclick">external documentation</a>.
+-spec aux1DClick(This) -> boolean() when
+ This::wxMouseEvent().
+aux1DClick(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxMouseEvent),
+ wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_Aux1DClick),
+ wxe_util:rec(?wxMouseEvent_Aux1DClick).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmouseevent.html#wxmouseeventaux1down">external documentation</a>.
+-spec aux1Down(This) -> boolean() when
+ This::wxMouseEvent().
+aux1Down(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxMouseEvent),
+ wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_Aux1Down),
+ wxe_util:rec(?wxMouseEvent_Aux1Down).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmouseevent.html#wxmouseeventaux1up">external documentation</a>.
+-spec aux1Up(This) -> boolean() when
+ This::wxMouseEvent().
+aux1Up(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxMouseEvent),
+ wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_Aux1Up),
+ wxe_util:rec(?wxMouseEvent_Aux1Up).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmouseevent.html#wxmouseeventaux2dclick">external documentation</a>.
+-spec aux2DClick(This) -> boolean() when
+ This::wxMouseEvent().
+aux2DClick(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxMouseEvent),
+ wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_Aux2DClick),
+ wxe_util:rec(?wxMouseEvent_Aux2DClick).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmouseevent.html#wxmouseeventaux2down">external documentation</a>.
+-spec aux2Down(This) -> boolean() when
+ This::wxMouseEvent().
+aux2Down(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxMouseEvent),
+ wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_Aux2Down),
+ wxe_util:rec(?wxMouseEvent_Aux2Down).
+
+%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxmouseevent.html#wxmouseeventaux2up">external documentation</a>.
+-spec aux2Up(This) -> boolean() when
+ This::wxMouseEvent().
+aux2Up(#wx_ref{type=ThisT}=This) ->
+ ?CLASS(ThisT,wxMouseEvent),
+ wxe_util:queue_cmd(This,?get_env(),?wxMouseEvent_Aux2Up),
+ wxe_util:rec(?wxMouseEvent_Aux2Up).
+
%% From wxEvent
%% @hidden
stopPropagation(This) -> wxEvent:stopPropagation(This).
diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl
index bf21c05605..e20f2699f7 100644
--- a/lib/wx/src/gen/wxe_funcs.hrl
+++ b/lib/wx/src/gen/wxe_funcs.hrl
@@ -757,2692 +757,2700 @@
-define(wxMenuBar_SetAutoWindowMenu, 871).
-define(wxMenuBar_GetAutoWindowMenu, 872).
-define(wxMenuBar_OSXGetAppleMenu, 873).
--define(wxMenuBar_IsEnabled, 874).
--define(wxMenuBar_Remove, 875).
--define(wxMenuBar_Replace, 876).
--define(wxMenuBar_SetHelpString, 877).
--define(wxMenuBar_SetLabel, 878).
--define(wxMenuBar_SetMenuLabel, 879).
--define(wxControl_GetLabel, 880).
--define(wxControl_SetLabel, 881).
--define(wxControlWithItems_Append_1, 882).
--define(wxControlWithItems_Append_2, 883).
--define(wxControlWithItems_appendStrings_1, 884).
--define(wxControlWithItems_appendStrings_2, 885).
--define(wxControlWithItems_Clear, 886).
--define(wxControlWithItems_Delete, 887).
--define(wxControlWithItems_FindString, 888).
--define(wxControlWithItems_getClientData, 889).
--define(wxControlWithItems_setClientData, 890).
--define(wxControlWithItems_GetCount, 891).
--define(wxControlWithItems_GetSelection, 892).
--define(wxControlWithItems_GetString, 893).
--define(wxControlWithItems_GetStringSelection, 894).
--define(wxControlWithItems_Insert_2, 895).
--define(wxControlWithItems_Insert_3, 896).
--define(wxControlWithItems_insertStrings_2, 897).
--define(wxControlWithItems_insertStrings_3, 898).
--define(wxControlWithItems_IsEmpty, 899).
--define(wxControlWithItems_Select, 900).
--define(wxControlWithItems_SetSelection, 901).
--define(wxControlWithItems_SetString, 902).
--define(wxControlWithItems_SetStringSelection, 903).
--define(wxMenu_new_0, 904).
--define(wxMenu_new_1, 905).
--define(wxMenu_new_2, 906).
--define(wxMenu_destruct, 907).
--define(wxMenu_Append_3, 908).
--define(wxMenu_Append_4, 909).
--define(wxMenu_Append_1, 910).
--define(wxMenu_AppendCheckItem, 911).
--define(wxMenu_AppendRadioItem, 912).
--define(wxMenu_AppendSeparator, 913).
--define(wxMenu_Break, 914).
--define(wxMenu_Check, 915).
--define(wxMenu_Delete_1_0, 916).
--define(wxMenu_Delete_1_1, 917).
--define(wxMenu_Destroy_1_0, 918).
--define(wxMenu_Destroy_1_1, 919).
--define(wxMenu_Enable, 920).
--define(wxMenu_FindItem_1, 921).
--define(wxMenu_FindItem_2, 922).
--define(wxMenu_FindItemByPosition, 923).
--define(wxMenu_GetHelpString, 924).
--define(wxMenu_GetLabel, 925).
--define(wxMenu_GetMenuItemCount, 926).
--define(wxMenu_GetMenuItems, 928).
--define(wxMenu_GetTitle, 929).
--define(wxMenu_Insert_2, 930).
--define(wxMenu_Insert_3, 931).
--define(wxMenu_Insert_5, 932).
--define(wxMenu_InsertCheckItem, 933).
--define(wxMenu_InsertRadioItem, 934).
--define(wxMenu_InsertSeparator, 935).
--define(wxMenu_IsChecked, 936).
--define(wxMenu_IsEnabled, 937).
--define(wxMenu_Prepend_1, 938).
--define(wxMenu_Prepend_2, 939).
--define(wxMenu_Prepend_4, 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, 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_GetLabelText, 957).
--define(wxMenuItem_GetItemLabel, 958).
--define(wxMenuItem_GetItemLabelText, 959).
--define(wxMenuItem_GetMenu, 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_SetItemLabel, 971).
--define(wxToolBar_AddControl, 972).
--define(wxToolBar_AddSeparator, 973).
--define(wxToolBar_AddTool_1, 974).
--define(wxToolBar_AddTool_4, 975).
--define(wxToolBar_AddTool_5, 976).
--define(wxToolBar_AddCheckTool, 977).
--define(wxToolBar_AddRadioTool, 978).
--define(wxToolBar_AddStretchableSpace, 979).
--define(wxToolBar_InsertStretchableSpace, 980).
--define(wxToolBar_DeleteTool, 981).
--define(wxToolBar_DeleteToolByPos, 982).
--define(wxToolBar_EnableTool, 983).
--define(wxToolBar_FindById, 984).
--define(wxToolBar_FindControl, 985).
--define(wxToolBar_FindToolForPosition, 986).
--define(wxToolBar_GetToolSize, 987).
--define(wxToolBar_GetToolBitmapSize, 988).
--define(wxToolBar_GetMargins, 989).
--define(wxToolBar_GetToolEnabled, 990).
--define(wxToolBar_GetToolLongHelp, 991).
--define(wxToolBar_GetToolPacking, 992).
--define(wxToolBar_GetToolPos, 993).
--define(wxToolBar_GetToolSeparation, 994).
--define(wxToolBar_GetToolShortHelp, 995).
--define(wxToolBar_GetToolState, 996).
--define(wxToolBar_InsertControl, 997).
--define(wxToolBar_InsertSeparator, 998).
--define(wxToolBar_InsertTool_5, 999).
--define(wxToolBar_InsertTool_2, 1000).
--define(wxToolBar_Realize, 1001).
--define(wxToolBar_RemoveTool, 1002).
--define(wxToolBar_SetMargins, 1003).
--define(wxToolBar_SetToolBitmapSize, 1004).
--define(wxToolBar_SetToolLongHelp, 1005).
--define(wxToolBar_SetToolPacking, 1006).
--define(wxToolBar_SetToolShortHelp, 1007).
--define(wxToolBar_SetToolSeparation, 1008).
--define(wxToolBar_ToggleTool, 1009).
--define(wxStatusBar_new_0, 1010).
--define(wxStatusBar_new_2, 1011).
--define(wxStatusBar_destruct, 1012).
--define(wxStatusBar_Create, 1013).
--define(wxStatusBar_GetFieldRect, 1014).
--define(wxStatusBar_GetFieldsCount, 1015).
--define(wxStatusBar_GetStatusText, 1016).
--define(wxStatusBar_PopStatusText, 1017).
--define(wxStatusBar_PushStatusText, 1018).
--define(wxStatusBar_SetFieldsCount, 1019).
--define(wxStatusBar_SetMinHeight, 1020).
--define(wxStatusBar_SetStatusText, 1021).
--define(wxStatusBar_SetStatusWidths, 1022).
--define(wxStatusBar_SetStatusStyles, 1023).
--define(wxBitmap_new_0, 1024).
--define(wxBitmap_new_4, 1026).
--define(wxBitmap_new_3, 1027).
--define(wxBitmap_new_2_1, 1028).
--define(wxBitmap_new_2_0, 1029).
--define(wxBitmap_new_2_2, 1030).
--define(wxBitmap_new_2_3, 1031).
--define(wxBitmap_destruct, 1032).
--define(wxBitmap_ConvertToImage, 1033).
--define(wxBitmap_CopyFromIcon, 1034).
--define(wxBitmap_Create_3_0, 1035).
--define(wxBitmap_Create_2, 1036).
--define(wxBitmap_Create_3_1, 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_IsOk, 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_1, 1053).
--define(wxIcon_new_2, 1054).
--define(wxIcon_CopyFromBitmap, 1055).
--define(wxIcon_destruct, 1056).
--define(wxIconBundle_new_0, 1057).
--define(wxIconBundle_new_1_1, 1058).
--define(wxIconBundle_new_2, 1059).
--define(wxIconBundle_new_1_0, 1061).
--define(wxIconBundle_destruct, 1062).
--define(wxIconBundle_AddIcon_1_0, 1063).
--define(wxIconBundle_AddIcon_2, 1064).
--define(wxIconBundle_AddIcon_1_1, 1065).
--define(wxIconBundle_GetIcon_2, 1066).
--define(wxIconBundle_GetIcon_1, 1067).
--define(wxCursor_new_0, 1068).
--define(wxCursor_new_2, 1069).
--define(wxCursor_new_1_1, 1070).
--define(wxCursor_new_1_0, 1071).
--define(wxCursor_destruct, 1073).
--define(wxCursor_IsOk, 1074).
--define(wxMask_new_0, 1075).
--define(wxMask_new_2_0, 1076).
--define(wxMask_new_1, 1077).
--define(wxMask_new_2_1, 1078).
--define(wxMask_destruct, 1079).
--define(wxMask_Create_2_0, 1080).
--define(wxMask_Create_1, 1081).
--define(wxMask_Create_2_1, 1082).
--define(wxImage_new_0, 1083).
--define(wxImage_new_3_1, 1084).
--define(wxImage_new_2_2, 1085).
--define(wxImage_new_3_0, 1086).
--define(wxImage_new_2_1, 1087).
--define(wxImage_new_4, 1088).
--define(wxImage_new_3_3, 1089).
--define(wxImage_new_2_0, 1090).
--define(wxImage_new_3_2, 1091).
--define(wxImage_destruct, 1092).
--define(wxImage_Blur, 1093).
--define(wxImage_BlurHorizontal, 1094).
--define(wxImage_BlurVertical, 1095).
--define(wxImage_ConvertAlphaToMask_1, 1096).
--define(wxImage_ConvertAlphaToMask_4, 1097).
--define(wxImage_ConvertToGreyscale_3, 1098).
--define(wxImage_ConvertToGreyscale_0, 1099).
--define(wxImage_ConvertToMono, 1100).
--define(wxImage_Copy, 1101).
--define(wxImage_Create_3_1, 1102).
--define(wxImage_Create_2_1, 1103).
--define(wxImage_Create_3_0, 1104).
--define(wxImage_Create_2_0, 1105).
--define(wxImage_Create_4, 1106).
--define(wxImage_Create_3_2, 1107).
--define(wxImage_Destroy, 1108).
--define(wxImage_FindFirstUnusedColour, 1109).
--define(wxImage_GetImageExtWildcard, 1110).
--define(wxImage_GetAlpha_0, 1111).
--define(wxImage_GetAlpha_2, 1112).
--define(wxImage_GetBlue, 1113).
--define(wxImage_GetData, 1114).
--define(wxImage_GetGreen, 1115).
--define(wxImage_GetImageCount, 1116).
--define(wxImage_GetHeight, 1117).
--define(wxImage_GetMaskBlue, 1118).
--define(wxImage_GetMaskGreen, 1119).
--define(wxImage_GetMaskRed, 1120).
--define(wxImage_GetOrFindMaskColour, 1121).
--define(wxImage_GetPalette, 1122).
--define(wxImage_GetRed, 1123).
--define(wxImage_GetSubImage, 1124).
--define(wxImage_GetWidth, 1125).
--define(wxImage_HasAlpha, 1126).
--define(wxImage_HasMask, 1127).
--define(wxImage_GetOption, 1128).
--define(wxImage_GetOptionInt, 1129).
--define(wxImage_HasOption, 1130).
--define(wxImage_InitAlpha, 1131).
--define(wxImage_InitStandardHandlers, 1132).
--define(wxImage_IsTransparent, 1133).
--define(wxImage_LoadFile_2, 1134).
--define(wxImage_LoadFile_3, 1135).
--define(wxImage_IsOk, 1136).
--define(wxImage_RemoveHandler, 1137).
--define(wxImage_Mirror, 1138).
--define(wxImage_Replace, 1139).
--define(wxImage_Rescale, 1140).
--define(wxImage_Resize, 1141).
--define(wxImage_Rotate, 1142).
--define(wxImage_RotateHue, 1143).
--define(wxImage_Rotate90, 1144).
--define(wxImage_SaveFile_2_0, 1145).
--define(wxImage_SaveFile_2_1, 1146).
--define(wxImage_SaveFile_1, 1147).
--define(wxImage_Scale, 1148).
--define(wxImage_Size, 1149).
--define(wxImage_SetAlpha_1, 1150).
--define(wxImage_SetAlpha_3, 1151).
--define(wxImage_SetData_1, 1152).
--define(wxImage_SetData_3, 1153).
--define(wxImage_SetMask, 1154).
--define(wxImage_SetMaskColour, 1155).
--define(wxImage_SetMaskFromImage, 1156).
--define(wxImage_SetOption_2_1, 1157).
--define(wxImage_SetOption_2_0, 1158).
--define(wxImage_SetPalette, 1159).
--define(wxImage_SetRGB_5, 1160).
--define(wxImage_SetRGB_4, 1161).
--define(wxBrush_new_0, 1162).
--define(wxBrush_new_2, 1163).
--define(wxBrush_new_1, 1165).
--define(wxBrush_destruct, 1166).
--define(wxBrush_GetColour, 1167).
--define(wxBrush_GetStipple, 1168).
--define(wxBrush_GetStyle, 1169).
--define(wxBrush_IsHatch, 1170).
--define(wxBrush_IsOk, 1171).
--define(wxBrush_SetColour_1, 1172).
--define(wxBrush_SetColour_3, 1173).
--define(wxBrush_SetStipple, 1174).
--define(wxBrush_SetStyle, 1175).
--define(wxPen_new_0, 1176).
--define(wxPen_new_2, 1177).
--define(wxPen_new_1, 1178).
--define(wxPen_destruct, 1179).
--define(wxPen_GetCap, 1180).
--define(wxPen_GetColour, 1181).
--define(wxPen_GetJoin, 1182).
--define(wxPen_GetStyle, 1183).
--define(wxPen_GetWidth, 1184).
--define(wxPen_IsOk, 1185).
--define(wxPen_SetCap, 1186).
--define(wxPen_SetColour_1, 1187).
--define(wxPen_SetColour_3, 1188).
--define(wxPen_SetJoin, 1189).
--define(wxPen_SetStyle, 1190).
--define(wxPen_SetWidth, 1191).
--define(wxRegion_new_0, 1192).
--define(wxRegion_new_4, 1193).
--define(wxRegion_new_2, 1194).
--define(wxRegion_new_1_0, 1195).
--define(wxRegion_new_1_1, 1197).
--define(wxRegion_destruct, 1199).
--define(wxRegion_Clear, 1200).
--define(wxRegion_Contains_2, 1201).
--define(wxRegion_Contains_1_0, 1202).
--define(wxRegion_Contains_4, 1203).
--define(wxRegion_Contains_1_1, 1204).
--define(wxRegion_ConvertToBitmap, 1205).
--define(wxRegion_GetBox, 1206).
--define(wxRegion_Intersect_4, 1207).
--define(wxRegion_Intersect_1_0, 1208).
--define(wxRegion_Intersect_1_1, 1209).
--define(wxRegion_IsEmpty, 1210).
--define(wxRegion_Subtract_1_0, 1211).
--define(wxRegion_Subtract_1_1, 1212).
--define(wxRegion_Offset_2, 1213).
--define(wxRegion_Offset_1, 1214).
--define(wxRegion_Union_4, 1215).
--define(wxRegion_Union_1_1, 1216).
--define(wxRegion_Union_1_0, 1217).
--define(wxRegion_Union_3, 1219).
--define(wxRegion_Xor_4, 1220).
--define(wxRegion_Xor_1_0, 1221).
--define(wxRegion_Xor_1_1, 1222).
--define(wxAcceleratorTable_new_0, 1223).
--define(wxAcceleratorTable_new_2, 1224).
--define(wxAcceleratorTable_destruct, 1226).
--define(wxAcceleratorTable_IsOk, 1227).
--define(wxAcceleratorEntry_new_1_0, 1228).
--define(wxAcceleratorEntry_new_1_1, 1229).
--define(wxAcceleratorEntry_GetCommand, 1230).
--define(wxAcceleratorEntry_GetFlags, 1231).
--define(wxAcceleratorEntry_GetKeyCode, 1232).
--define(wxAcceleratorEntry_Set, 1233).
--define(wxAcceleratorEntry_destroy, 1234).
--define(wxCaret_new_3, 1236).
--define(wxCaret_new_2, 1237).
--define(wxCaret_Create_3, 1238).
--define(wxCaret_Create_2, 1239).
--define(wxCaret_GetBlinkTime, 1240).
--define(wxCaret_GetPosition, 1242).
--define(wxCaret_GetSize, 1244).
--define(wxCaret_GetWindow, 1245).
--define(wxCaret_Hide, 1246).
--define(wxCaret_IsOk, 1247).
--define(wxCaret_IsVisible, 1248).
--define(wxCaret_Move_2, 1249).
--define(wxCaret_Move_1, 1250).
--define(wxCaret_SetBlinkTime, 1251).
--define(wxCaret_SetSize_2, 1252).
--define(wxCaret_SetSize_1, 1253).
--define(wxCaret_Show, 1254).
--define(wxCaret_destroy, 1255).
--define(wxSizer_Add_2_0, 1256).
--define(wxSizer_Add_2_1, 1257).
--define(wxSizer_Add_3_0, 1260).
--define(wxSizer_Add_3_1, 1261).
--define(wxSizer_AddSpacer, 1262).
--define(wxSizer_AddStretchSpacer, 1263).
--define(wxSizer_CalcMin, 1264).
--define(wxSizer_Clear, 1265).
--define(wxSizer_Detach_1_0, 1266).
--define(wxSizer_Detach_1_1, 1268).
--define(wxSizer_Fit, 1269).
--define(wxSizer_FitInside, 1270).
--define(wxSizer_GetChildren, 1272).
--define(wxSizer_GetItem_2, 1273).
--define(wxSizer_GetItem_1, 1275).
--define(wxSizer_GetSize, 1276).
--define(wxSizer_GetPosition, 1277).
--define(wxSizer_GetMinSize, 1278).
--define(wxSizer_Hide_2, 1279).
--define(wxSizer_Hide_1, 1281).
--define(wxSizer_Insert_3_0, 1282).
--define(wxSizer_Insert_3_1, 1283).
--define(wxSizer_Insert_4_0, 1286).
--define(wxSizer_Insert_4_1, 1287).
--define(wxSizer_Insert_2, 1288).
--define(wxSizer_InsertSpacer, 1289).
--define(wxSizer_InsertStretchSpacer, 1290).
--define(wxSizer_IsShown_1_0, 1291).
--define(wxSizer_IsShown_1_1, 1293).
--define(wxSizer_Layout, 1294).
--define(wxSizer_Prepend_2_0, 1295).
--define(wxSizer_Prepend_2_1, 1296).
--define(wxSizer_Prepend_3_0, 1299).
--define(wxSizer_Prepend_3_1, 1300).
--define(wxSizer_Prepend_1, 1301).
--define(wxSizer_PrependSpacer, 1302).
--define(wxSizer_PrependStretchSpacer, 1303).
--define(wxSizer_Remove_1_1, 1304).
--define(wxSizer_Remove_1_0, 1305).
--define(wxSizer_Replace_3, 1306).
--define(wxSizer_Replace_2, 1308).
--define(wxSizer_SetDimension_4, 1309).
--define(wxSizer_SetDimension_2, 1310).
--define(wxSizer_SetMinSize_1, 1311).
--define(wxSizer_SetMinSize_2, 1312).
--define(wxSizer_SetItemMinSize_3_0, 1313).
--define(wxSizer_SetItemMinSize_2_0, 1314).
--define(wxSizer_SetItemMinSize_3_1, 1317).
--define(wxSizer_SetItemMinSize_2_1, 1318).
--define(wxSizer_SetSizeHints, 1319).
--define(wxSizer_Show_2_0, 1320).
--define(wxSizer_Show_2_1, 1322).
--define(wxSizer_Show_1, 1323).
--define(wxSizer_ShowItems, 1324).
--define(wxSizerFlags_new, 1325).
--define(wxSizerFlags_Align, 1326).
--define(wxSizerFlags_Border_2, 1327).
--define(wxSizerFlags_Border_1, 1328).
--define(wxSizerFlags_Center, 1329).
--define(wxSizerFlags_Expand, 1330).
--define(wxSizerFlags_Left, 1331).
--define(wxSizerFlags_Proportion, 1332).
--define(wxSizerFlags_Right, 1333).
--define(wxSizerFlags_destroy, 1334).
--define(wxSizerItem_new_3, 1335).
--define(wxSizerItem_new_2_0, 1336).
--define(wxSizerItem_new_2_1, 1337).
--define(wxSizerItem_destruct, 1340).
--define(wxSizerItem_CalcMin, 1341).
--define(wxSizerItem_DeleteWindows, 1342).
--define(wxSizerItem_DetachSizer, 1343).
--define(wxSizerItem_GetBorder, 1344).
--define(wxSizerItem_GetFlag, 1345).
--define(wxSizerItem_GetMinSize, 1346).
--define(wxSizerItem_GetPosition, 1347).
--define(wxSizerItem_GetProportion, 1348).
--define(wxSizerItem_GetRatio, 1349).
--define(wxSizerItem_GetRect, 1350).
--define(wxSizerItem_GetSize, 1351).
--define(wxSizerItem_GetSizer, 1352).
--define(wxSizerItem_GetSpacer, 1353).
--define(wxSizerItem_GetUserData, 1354).
--define(wxSizerItem_GetWindow, 1355).
--define(wxSizerItem_IsSizer, 1356).
--define(wxSizerItem_IsShown, 1357).
--define(wxSizerItem_IsSpacer, 1358).
--define(wxSizerItem_IsWindow, 1359).
--define(wxSizerItem_SetBorder, 1360).
--define(wxSizerItem_SetDimension, 1361).
--define(wxSizerItem_SetFlag, 1362).
--define(wxSizerItem_SetInitSize, 1363).
--define(wxSizerItem_SetMinSize_1, 1364).
--define(wxSizerItem_SetMinSize_2, 1365).
--define(wxSizerItem_SetProportion, 1366).
--define(wxSizerItem_SetRatio_2, 1367).
--define(wxSizerItem_SetRatio_1_1, 1368).
--define(wxSizerItem_SetRatio_1_0, 1369).
--define(wxSizerItem_AssignSizer, 1370).
--define(wxSizerItem_AssignSpacer_1, 1371).
--define(wxSizerItem_AssignSpacer_2, 1372).
--define(wxSizerItem_AssignWindow, 1373).
--define(wxSizerItem_Show, 1374).
--define(wxBoxSizer_new, 1375).
--define(wxBoxSizer_GetOrientation, 1376).
--define(wxBoxSizer_destroy, 1377).
--define(wxStaticBoxSizer_new_2, 1378).
--define(wxStaticBoxSizer_new_3, 1379).
--define(wxStaticBoxSizer_GetStaticBox, 1380).
--define(wxStaticBoxSizer_destroy, 1381).
--define(wxGridSizer_new_3_0, 1382).
--define(wxGridSizer_new_2, 1383).
--define(wxGridSizer_new_4, 1384).
--define(wxGridSizer_new_3_1, 1385).
--define(wxGridSizer_GetCols, 1386).
--define(wxGridSizer_GetHGap, 1387).
--define(wxGridSizer_GetRows, 1388).
--define(wxGridSizer_GetVGap, 1389).
--define(wxGridSizer_SetCols, 1390).
--define(wxGridSizer_SetHGap, 1391).
--define(wxGridSizer_SetRows, 1392).
--define(wxGridSizer_SetVGap, 1393).
--define(wxGridSizer_destroy, 1394).
--define(wxFlexGridSizer_new_3_0, 1395).
--define(wxFlexGridSizer_new_2, 1396).
--define(wxFlexGridSizer_new_4, 1397).
--define(wxFlexGridSizer_new_3_1, 1398).
--define(wxFlexGridSizer_AddGrowableCol, 1399).
--define(wxFlexGridSizer_AddGrowableRow, 1400).
--define(wxFlexGridSizer_GetFlexibleDirection, 1401).
--define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1402).
--define(wxFlexGridSizer_RemoveGrowableCol, 1403).
--define(wxFlexGridSizer_RemoveGrowableRow, 1404).
--define(wxFlexGridSizer_SetFlexibleDirection, 1405).
--define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1406).
--define(wxFlexGridSizer_destroy, 1407).
--define(wxGridBagSizer_new, 1408).
--define(wxGridBagSizer_Add_3, 1409).
--define(wxGridBagSizer_Add_1, 1411).
--define(wxGridBagSizer_Add_4, 1412).
--define(wxGridBagSizer_CalcMin, 1413).
--define(wxGridBagSizer_CheckForIntersection_2, 1414).
--define(wxGridBagSizer_CheckForIntersection_3, 1415).
--define(wxGridBagSizer_FindItem, 1416).
--define(wxGridBagSizer_FindItemAtPoint, 1418).
--define(wxGridBagSizer_FindItemAtPosition, 1419).
--define(wxGridBagSizer_FindItemWithData, 1420).
--define(wxGridBagSizer_GetCellSize, 1421).
--define(wxGridBagSizer_GetEmptyCellSize, 1422).
--define(wxGridBagSizer_GetItemPosition_1_0, 1423).
--define(wxGridBagSizer_GetItemPosition_1_1, 1425).
--define(wxGridBagSizer_GetItemSpan_1_0, 1426).
--define(wxGridBagSizer_GetItemSpan_1_1, 1428).
--define(wxGridBagSizer_SetEmptyCellSize, 1429).
--define(wxGridBagSizer_SetItemPosition_2_0, 1430).
--define(wxGridBagSizer_SetItemPosition_2_1, 1432).
--define(wxGridBagSizer_SetItemSpan_2_0, 1433).
--define(wxGridBagSizer_SetItemSpan_2_1, 1435).
--define(wxGridBagSizer_destroy, 1436).
--define(wxStdDialogButtonSizer_new, 1437).
--define(wxStdDialogButtonSizer_AddButton, 1438).
--define(wxStdDialogButtonSizer_Realize, 1439).
--define(wxStdDialogButtonSizer_SetAffirmativeButton, 1440).
--define(wxStdDialogButtonSizer_SetCancelButton, 1441).
--define(wxStdDialogButtonSizer_SetNegativeButton, 1442).
--define(wxStdDialogButtonSizer_destroy, 1443).
--define(wxFont_new_0, 1444).
--define(wxFont_new_1_1, 1445).
--define(wxFont_new_5_0, 1446).
--define(wxFont_new_5_1, 1447).
--define(wxFont_new_1_0, 1448).
--define(wxFont_destruct, 1449).
--define(wxFont_IsFixedWidth, 1450).
--define(wxFont_GetDefaultEncoding, 1451).
--define(wxFont_GetFaceName, 1452).
--define(wxFont_GetFamily, 1453).
--define(wxFont_GetNativeFontInfoDesc, 1454).
--define(wxFont_GetNativeFontInfoUserDesc, 1455).
--define(wxFont_GetPointSize, 1456).
--define(wxFont_GetStyle, 1457).
--define(wxFont_GetUnderlined, 1458).
--define(wxFont_GetWeight, 1459).
--define(wxFont_IsOk, 1460).
--define(wxFont_SetDefaultEncoding, 1461).
--define(wxFont_SetFaceName, 1462).
--define(wxFont_SetFamily, 1463).
--define(wxFont_SetPointSize, 1464).
--define(wxFont_SetStyle, 1465).
--define(wxFont_SetUnderlined, 1466).
--define(wxFont_SetWeight, 1467).
--define(wxToolTip_Enable, 1468).
--define(wxToolTip_SetDelay, 1469).
--define(wxToolTip_new, 1470).
--define(wxToolTip_SetTip, 1471).
--define(wxToolTip_GetTip, 1472).
--define(wxToolTip_GetWindow, 1473).
--define(wxToolTip_destroy, 1474).
--define(wxButton_new_0, 1475).
--define(wxButton_new_3, 1476).
--define(wxButton_Create, 1477).
--define(wxButton_GetDefaultSize_STAT_0, 1478).
--define(wxButton_GetDefaultSize_STAT_1, 1479).
--define(wxButton_SetDefault, 1480).
--define(wxButton_SetLabel, 1481).
--define(wxButton_GetBitmapDisabled, 1482).
--define(wxButton_GetBitmapFocus, 1483).
--define(wxButton_GetBitmapLabel, 1484).
--define(wxButton_SetBitmapDisabled, 1485).
--define(wxButton_SetBitmapFocus, 1486).
--define(wxButton_SetBitmapLabel, 1487).
--define(wxButton_destroy, 1488).
--define(wxBitmapButton_new_0, 1489).
--define(wxBitmapButton_new_4, 1490).
--define(wxBitmapButton_Create, 1491).
--define(wxBitmapButton_NewCloseButton, 1492).
--define(wxBitmapButton_destroy, 1493).
--define(wxToggleButton_new_0, 1494).
--define(wxToggleButton_new_4, 1495).
--define(wxToggleButton_destruct, 1496).
--define(wxToggleButton_Create, 1497).
--define(wxToggleButton_GetValue, 1498).
--define(wxToggleButton_SetValue, 1499).
--define(wxCalendarCtrl_new_0, 1500).
--define(wxCalendarCtrl_new_3, 1501).
--define(wxCalendarCtrl_Create, 1502).
--define(wxCalendarCtrl_destruct, 1503).
--define(wxCalendarCtrl_SetDate, 1504).
--define(wxCalendarCtrl_GetDate, 1505).
--define(wxCalendarCtrl_EnableYearChange, 1506).
--define(wxCalendarCtrl_EnableMonthChange, 1507).
--define(wxCalendarCtrl_EnableHolidayDisplay, 1508).
--define(wxCalendarCtrl_SetHeaderColours, 1509).
--define(wxCalendarCtrl_GetHeaderColourFg, 1510).
--define(wxCalendarCtrl_GetHeaderColourBg, 1511).
--define(wxCalendarCtrl_SetHighlightColours, 1512).
--define(wxCalendarCtrl_GetHighlightColourFg, 1513).
--define(wxCalendarCtrl_GetHighlightColourBg, 1514).
--define(wxCalendarCtrl_SetHolidayColours, 1515).
--define(wxCalendarCtrl_GetHolidayColourFg, 1516).
--define(wxCalendarCtrl_GetHolidayColourBg, 1517).
--define(wxCalendarCtrl_GetAttr, 1518).
--define(wxCalendarCtrl_SetAttr, 1519).
--define(wxCalendarCtrl_SetHoliday, 1520).
--define(wxCalendarCtrl_ResetAttr, 1521).
--define(wxCalendarCtrl_HitTest, 1522).
--define(wxCalendarDateAttr_new_1, 1523).
--define(wxCalendarDateAttr_new_2, 1524).
--define(wxCalendarDateAttr_SetTextColour, 1525).
--define(wxCalendarDateAttr_SetBackgroundColour, 1526).
--define(wxCalendarDateAttr_SetBorderColour, 1527).
--define(wxCalendarDateAttr_SetFont, 1528).
--define(wxCalendarDateAttr_SetBorder, 1529).
--define(wxCalendarDateAttr_SetHoliday, 1530).
--define(wxCalendarDateAttr_HasTextColour, 1531).
--define(wxCalendarDateAttr_HasBackgroundColour, 1532).
--define(wxCalendarDateAttr_HasBorderColour, 1533).
--define(wxCalendarDateAttr_HasFont, 1534).
--define(wxCalendarDateAttr_HasBorder, 1535).
--define(wxCalendarDateAttr_IsHoliday, 1536).
--define(wxCalendarDateAttr_GetTextColour, 1537).
--define(wxCalendarDateAttr_GetBackgroundColour, 1538).
--define(wxCalendarDateAttr_GetBorderColour, 1539).
--define(wxCalendarDateAttr_GetFont, 1540).
--define(wxCalendarDateAttr_GetBorder, 1541).
--define(wxCalendarDateAttr_destroy, 1542).
--define(wxCheckBox_new_0, 1543).
--define(wxCheckBox_new_4, 1544).
--define(wxCheckBox_destruct, 1545).
--define(wxCheckBox_Create, 1546).
--define(wxCheckBox_GetValue, 1547).
--define(wxCheckBox_Get3StateValue, 1548).
--define(wxCheckBox_Is3rdStateAllowedForUser, 1549).
--define(wxCheckBox_Is3State, 1550).
--define(wxCheckBox_IsChecked, 1551).
--define(wxCheckBox_SetValue, 1552).
--define(wxCheckBox_Set3StateValue, 1553).
--define(wxCheckListBox_new_0, 1554).
--define(wxCheckListBox_new_3, 1556).
--define(wxCheckListBox_destruct, 1557).
--define(wxCheckListBox_Check, 1558).
--define(wxCheckListBox_IsChecked, 1559).
--define(wxChoice_new_0, 1560).
--define(wxChoice_new_3, 1562).
--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_2, 1591).
--define(wxComboBox_SetSelection_1, 1592).
--define(wxComboBox_SetValue, 1593).
--define(wxComboBox_Undo, 1594).
--define(wxGauge_new_0, 1595).
--define(wxGauge_new_4, 1596).
--define(wxGauge_destruct, 1597).
--define(wxGauge_Create, 1598).
--define(wxGauge_GetRange, 1599).
--define(wxGauge_GetValue, 1600).
--define(wxGauge_IsVertical, 1601).
--define(wxGauge_SetRange, 1602).
--define(wxGauge_SetValue, 1603).
--define(wxGauge_Pulse, 1604).
--define(wxGenericDirCtrl_new_0, 1605).
--define(wxGenericDirCtrl_new_2, 1606).
--define(wxGenericDirCtrl_destruct, 1607).
--define(wxGenericDirCtrl_Create, 1608).
--define(wxGenericDirCtrl_Init, 1609).
--define(wxGenericDirCtrl_CollapseTree, 1610).
--define(wxGenericDirCtrl_ExpandPath, 1611).
--define(wxGenericDirCtrl_GetDefaultPath, 1612).
--define(wxGenericDirCtrl_GetPath_0, 1613).
--define(wxGenericDirCtrl_GetPath_1, 1614).
--define(wxGenericDirCtrl_GetFilePath, 1615).
--define(wxGenericDirCtrl_GetFilter, 1616).
--define(wxGenericDirCtrl_GetFilterIndex, 1617).
--define(wxGenericDirCtrl_GetRootId, 1618).
--define(wxGenericDirCtrl_GetTreeCtrl, 1619).
--define(wxGenericDirCtrl_ReCreateTree, 1620).
--define(wxGenericDirCtrl_SetDefaultPath, 1621).
--define(wxGenericDirCtrl_SetFilter, 1622).
--define(wxGenericDirCtrl_SetFilterIndex, 1623).
--define(wxGenericDirCtrl_SetPath, 1624).
--define(wxStaticBox_new_0, 1625).
--define(wxStaticBox_new_4, 1626).
--define(wxStaticBox_destruct, 1627).
--define(wxStaticBox_Create, 1628).
--define(wxStaticLine_new_0, 1629).
--define(wxStaticLine_new_2, 1630).
--define(wxStaticLine_Create, 1631).
--define(wxStaticLine_IsVertical, 1632).
--define(wxStaticLine_GetDefaultSize, 1633).
--define(wxStaticLine_destroy, 1634).
--define(wxListBox_new_0, 1635).
--define(wxListBox_new_3, 1637).
--define(wxListBox_destruct, 1638).
--define(wxListBox_Create, 1640).
--define(wxListBox_Deselect, 1641).
--define(wxListBox_GetSelections, 1642).
--define(wxListBox_InsertItems, 1643).
--define(wxListBox_IsSelected, 1644).
--define(wxListBox_Set, 1647).
--define(wxListBox_HitTest_1, 1648).
--define(wxListBox_HitTest_2, 1649).
--define(wxListBox_SetFirstItem_1_0, 1650).
--define(wxListBox_SetFirstItem_1_1, 1651).
--define(wxListCtrl_new_0, 1652).
--define(wxListCtrl_new_2, 1653).
--define(wxListCtrl_destruct, 1654).
--define(wxListCtrl_Arrange, 1655).
--define(wxListCtrl_AssignImageList, 1656).
--define(wxListCtrl_ClearAll, 1657).
--define(wxListCtrl_Create, 1658).
--define(wxListCtrl_DeleteAllItems, 1659).
--define(wxListCtrl_DeleteColumn, 1660).
--define(wxListCtrl_DeleteItem, 1661).
--define(wxListCtrl_EditLabel, 1662).
--define(wxListCtrl_EnsureVisible, 1663).
--define(wxListCtrl_FindItem_3_0, 1664).
--define(wxListCtrl_FindItem_3_1, 1665).
--define(wxListCtrl_GetColumn, 1666).
--define(wxListCtrl_GetColumnCount, 1667).
--define(wxListCtrl_GetColumnWidth, 1668).
--define(wxListCtrl_GetCountPerPage, 1669).
--define(wxListCtrl_GetEditControl, 1670).
--define(wxListCtrl_GetImageList, 1671).
--define(wxListCtrl_GetItem, 1672).
--define(wxListCtrl_GetItemBackgroundColour, 1673).
--define(wxListCtrl_GetItemCount, 1674).
--define(wxListCtrl_GetItemData, 1675).
--define(wxListCtrl_GetItemFont, 1676).
--define(wxListCtrl_GetItemPosition, 1677).
--define(wxListCtrl_GetItemRect, 1678).
--define(wxListCtrl_GetItemSpacing, 1679).
--define(wxListCtrl_GetItemState, 1680).
--define(wxListCtrl_GetItemText, 1681).
--define(wxListCtrl_GetItemTextColour, 1682).
--define(wxListCtrl_GetNextItem, 1683).
--define(wxListCtrl_GetSelectedItemCount, 1684).
--define(wxListCtrl_GetTextColour, 1685).
--define(wxListCtrl_GetTopItem, 1686).
--define(wxListCtrl_GetViewRect, 1687).
--define(wxListCtrl_HitTest, 1688).
--define(wxListCtrl_InsertColumn_2, 1689).
--define(wxListCtrl_InsertColumn_3, 1690).
--define(wxListCtrl_InsertItem_1, 1691).
--define(wxListCtrl_InsertItem_2_1, 1692).
--define(wxListCtrl_InsertItem_2_0, 1693).
--define(wxListCtrl_InsertItem_3, 1694).
--define(wxListCtrl_RefreshItem, 1695).
--define(wxListCtrl_RefreshItems, 1696).
--define(wxListCtrl_ScrollList, 1697).
--define(wxListCtrl_SetBackgroundColour, 1698).
--define(wxListCtrl_SetColumn, 1699).
--define(wxListCtrl_SetColumnWidth, 1700).
--define(wxListCtrl_SetImageList, 1701).
--define(wxListCtrl_SetItem_1, 1702).
--define(wxListCtrl_SetItem_4, 1703).
--define(wxListCtrl_SetItemBackgroundColour, 1704).
--define(wxListCtrl_SetItemCount, 1705).
--define(wxListCtrl_SetItemData, 1706).
--define(wxListCtrl_SetItemFont, 1707).
--define(wxListCtrl_SetItemImage, 1708).
--define(wxListCtrl_SetItemColumnImage, 1709).
--define(wxListCtrl_SetItemPosition, 1710).
--define(wxListCtrl_SetItemState, 1711).
--define(wxListCtrl_SetItemText, 1712).
--define(wxListCtrl_SetItemTextColour, 1713).
--define(wxListCtrl_SetSingleStyle, 1714).
--define(wxListCtrl_SetTextColour, 1715).
--define(wxListCtrl_SetWindowStyleFlag, 1716).
--define(wxListCtrl_SortItems, 1717).
--define(wxListView_ClearColumnImage, 1718).
--define(wxListView_Focus, 1719).
--define(wxListView_GetFirstSelected, 1720).
--define(wxListView_GetFocusedItem, 1721).
--define(wxListView_GetNextSelected, 1722).
--define(wxListView_IsSelected, 1723).
--define(wxListView_Select, 1724).
--define(wxListView_SetColumnImage, 1725).
--define(wxListItem_new_0, 1726).
--define(wxListItem_new_1, 1727).
--define(wxListItem_Clear, 1728).
--define(wxListItem_GetAlign, 1729).
--define(wxListItem_GetBackgroundColour, 1730).
--define(wxListItem_GetColumn, 1731).
--define(wxListItem_GetFont, 1732).
--define(wxListItem_GetId, 1733).
--define(wxListItem_GetImage, 1734).
--define(wxListItem_GetMask, 1735).
--define(wxListItem_GetState, 1736).
--define(wxListItem_GetText, 1737).
--define(wxListItem_GetTextColour, 1738).
--define(wxListItem_GetWidth, 1739).
--define(wxListItem_SetAlign, 1740).
--define(wxListItem_SetBackgroundColour, 1741).
--define(wxListItem_SetColumn, 1742).
--define(wxListItem_SetFont, 1743).
--define(wxListItem_SetId, 1744).
--define(wxListItem_SetImage, 1745).
--define(wxListItem_SetMask, 1746).
--define(wxListItem_SetState, 1747).
--define(wxListItem_SetStateMask, 1748).
--define(wxListItem_SetText, 1749).
--define(wxListItem_SetTextColour, 1750).
--define(wxListItem_SetWidth, 1751).
--define(wxListItem_destroy, 1752).
--define(wxListItemAttr_new_0, 1753).
--define(wxListItemAttr_new_3, 1754).
--define(wxListItemAttr_GetBackgroundColour, 1755).
--define(wxListItemAttr_GetFont, 1756).
--define(wxListItemAttr_GetTextColour, 1757).
--define(wxListItemAttr_HasBackgroundColour, 1758).
--define(wxListItemAttr_HasFont, 1759).
--define(wxListItemAttr_HasTextColour, 1760).
--define(wxListItemAttr_SetBackgroundColour, 1761).
--define(wxListItemAttr_SetFont, 1762).
--define(wxListItemAttr_SetTextColour, 1763).
--define(wxListItemAttr_destroy, 1764).
--define(wxImageList_new_0, 1765).
--define(wxImageList_new_3, 1766).
--define(wxImageList_Add_2_0, 1767).
--define(wxImageList_Add_2_1, 1769).
--define(wxImageList_Add_1, 1770).
--define(wxImageList_Create, 1771).
--define(wxImageList_Draw, 1772).
--define(wxImageList_GetBitmap, 1773).
--define(wxImageList_GetIcon, 1774).
--define(wxImageList_GetImageCount, 1775).
--define(wxImageList_GetSize, 1776).
--define(wxImageList_Remove, 1778).
--define(wxImageList_RemoveAll, 1779).
--define(wxImageList_Replace_3, 1780).
--define(wxImageList_Replace_2, 1782).
--define(wxImageList_destroy, 1783).
--define(wxTextAttr_new_0, 1784).
--define(wxTextAttr_new_2, 1785).
--define(wxTextAttr_new_1, 1786).
--define(wxTextAttr_GetAlignment, 1787).
--define(wxTextAttr_GetBackgroundColour, 1788).
--define(wxTextAttr_GetFont, 1789).
--define(wxTextAttr_GetFontEncoding, 1790).
--define(wxTextAttr_GetFontFaceName, 1791).
--define(wxTextAttr_GetFontSize, 1792).
--define(wxTextAttr_GetFontStyle, 1793).
--define(wxTextAttr_GetFontUnderlined, 1794).
--define(wxTextAttr_GetFontWeight, 1795).
--define(wxTextAttr_GetLeftIndent, 1796).
--define(wxTextAttr_GetLeftSubIndent, 1797).
--define(wxTextAttr_GetRightIndent, 1798).
--define(wxTextAttr_GetTabs, 1799).
--define(wxTextAttr_GetTextColour, 1800).
--define(wxTextAttr_HasBackgroundColour, 1801).
--define(wxTextAttr_HasFont, 1802).
--define(wxTextAttr_HasTextColour, 1803).
--define(wxTextAttr_GetFlags, 1804).
--define(wxTextAttr_IsDefault, 1805).
--define(wxTextAttr_SetAlignment, 1806).
--define(wxTextAttr_SetBackgroundColour, 1807).
--define(wxTextAttr_SetFlags, 1808).
--define(wxTextAttr_SetFont, 1809).
--define(wxTextAttr_SetFontEncoding, 1810).
--define(wxTextAttr_SetFontFaceName, 1811).
--define(wxTextAttr_SetFontFamily, 1812).
--define(wxTextAttr_SetFontSize, 1813).
--define(wxTextAttr_SetFontPointSize, 1814).
--define(wxTextAttr_SetFontPixelSize, 1815).
--define(wxTextAttr_SetFontStyle, 1816).
--define(wxTextAttr_SetFontUnderlined, 1817).
--define(wxTextAttr_SetFontWeight, 1818).
--define(wxTextAttr_SetLeftIndent, 1819).
--define(wxTextAttr_SetRightIndent, 1820).
--define(wxTextAttr_SetTabs, 1821).
--define(wxTextAttr_SetTextColour, 1822).
--define(wxTextAttr_destroy, 1823).
--define(wxTextCtrl_new_0, 1824).
--define(wxTextCtrl_new_3, 1825).
--define(wxTextCtrl_destruct, 1826).
--define(wxTextCtrl_AppendText, 1827).
--define(wxTextCtrl_CanCopy, 1828).
--define(wxTextCtrl_CanCut, 1829).
--define(wxTextCtrl_CanPaste, 1830).
--define(wxTextCtrl_CanRedo, 1831).
--define(wxTextCtrl_CanUndo, 1832).
--define(wxTextCtrl_Clear, 1833).
--define(wxTextCtrl_Copy, 1834).
--define(wxTextCtrl_Create, 1835).
--define(wxTextCtrl_Cut, 1836).
--define(wxTextCtrl_DiscardEdits, 1837).
--define(wxTextCtrl_ChangeValue, 1838).
--define(wxTextCtrl_EmulateKeyPress, 1839).
--define(wxTextCtrl_GetDefaultStyle, 1840).
--define(wxTextCtrl_GetInsertionPoint, 1841).
--define(wxTextCtrl_GetLastPosition, 1842).
--define(wxTextCtrl_GetLineLength, 1843).
--define(wxTextCtrl_GetLineText, 1844).
--define(wxTextCtrl_GetNumberOfLines, 1845).
--define(wxTextCtrl_GetRange, 1846).
--define(wxTextCtrl_GetSelection, 1847).
--define(wxTextCtrl_GetStringSelection, 1848).
--define(wxTextCtrl_GetStyle, 1849).
--define(wxTextCtrl_GetValue, 1850).
--define(wxTextCtrl_IsEditable, 1851).
--define(wxTextCtrl_IsModified, 1852).
--define(wxTextCtrl_IsMultiLine, 1853).
--define(wxTextCtrl_IsSingleLine, 1854).
--define(wxTextCtrl_LoadFile, 1855).
--define(wxTextCtrl_MarkDirty, 1856).
--define(wxTextCtrl_Paste, 1857).
--define(wxTextCtrl_PositionToXY, 1858).
--define(wxTextCtrl_Redo, 1859).
--define(wxTextCtrl_Remove, 1860).
--define(wxTextCtrl_Replace, 1861).
--define(wxTextCtrl_SaveFile, 1862).
--define(wxTextCtrl_SetDefaultStyle, 1863).
--define(wxTextCtrl_SetEditable, 1864).
--define(wxTextCtrl_SetInsertionPoint, 1865).
--define(wxTextCtrl_SetInsertionPointEnd, 1866).
--define(wxTextCtrl_SetMaxLength, 1867).
--define(wxTextCtrl_SetSelection, 1868).
--define(wxTextCtrl_SetStyle, 1869).
--define(wxTextCtrl_SetValue, 1870).
--define(wxTextCtrl_ShowPosition, 1871).
--define(wxTextCtrl_Undo, 1872).
--define(wxTextCtrl_WriteText, 1873).
--define(wxTextCtrl_XYToPosition, 1874).
--define(wxBookCtrlBase_AddPage, 1875).
--define(wxBookCtrlBase_InsertPage, 1876).
--define(wxBookCtrlBase_DeletePage, 1877).
--define(wxBookCtrlBase_RemovePage, 1878).
--define(wxBookCtrlBase_DeleteAllPages, 1879).
--define(wxBookCtrlBase_GetPage, 1880).
--define(wxBookCtrlBase_GetPageCount, 1881).
--define(wxBookCtrlBase_GetCurrentPage, 1882).
--define(wxBookCtrlBase_AdvanceSelection, 1883).
--define(wxBookCtrlBase_SetSelection, 1884).
--define(wxBookCtrlBase_GetSelection, 1885).
--define(wxBookCtrlBase_ChangeSelection, 1886).
--define(wxBookCtrlBase_HitTest, 1887).
--define(wxBookCtrlBase_GetPageText, 1888).
--define(wxBookCtrlBase_SetPageText, 1889).
--define(wxNotebook_new_0, 1890).
--define(wxNotebook_new_3, 1891).
--define(wxNotebook_destruct, 1892).
--define(wxNotebook_AssignImageList, 1893).
--define(wxNotebook_Create, 1894).
--define(wxNotebook_GetImageList, 1895).
--define(wxNotebook_GetPageImage, 1896).
--define(wxNotebook_GetRowCount, 1897).
--define(wxNotebook_GetThemeBackgroundColour, 1898).
--define(wxNotebook_SetImageList, 1899).
--define(wxNotebook_SetPadding, 1900).
--define(wxNotebook_SetPageSize, 1901).
--define(wxNotebook_SetPageImage, 1902).
--define(wxChoicebook_new_0, 1903).
--define(wxChoicebook_new_3, 1904).
--define(wxChoicebook_AddPage, 1905).
--define(wxChoicebook_AdvanceSelection, 1906).
--define(wxChoicebook_AssignImageList, 1907).
--define(wxChoicebook_Create, 1908).
--define(wxChoicebook_DeleteAllPages, 1909).
--define(wxChoicebook_GetCurrentPage, 1910).
--define(wxChoicebook_GetImageList, 1911).
--define(wxChoicebook_GetPage, 1912).
--define(wxChoicebook_GetPageCount, 1913).
--define(wxChoicebook_GetPageImage, 1914).
--define(wxChoicebook_GetPageText, 1915).
--define(wxChoicebook_GetSelection, 1916).
--define(wxChoicebook_HitTest, 1917).
--define(wxChoicebook_InsertPage, 1918).
--define(wxChoicebook_SetImageList, 1919).
--define(wxChoicebook_SetPageSize, 1920).
--define(wxChoicebook_SetPageImage, 1921).
--define(wxChoicebook_SetPageText, 1922).
--define(wxChoicebook_SetSelection, 1923).
--define(wxChoicebook_ChangeSelection, 1924).
--define(wxChoicebook_destroy, 1925).
--define(wxToolbook_new_0, 1926).
--define(wxToolbook_new_3, 1927).
--define(wxToolbook_AddPage, 1928).
--define(wxToolbook_AdvanceSelection, 1929).
--define(wxToolbook_AssignImageList, 1930).
--define(wxToolbook_Create, 1931).
--define(wxToolbook_DeleteAllPages, 1932).
--define(wxToolbook_GetCurrentPage, 1933).
--define(wxToolbook_GetImageList, 1934).
--define(wxToolbook_GetPage, 1935).
--define(wxToolbook_GetPageCount, 1936).
--define(wxToolbook_GetPageImage, 1937).
--define(wxToolbook_GetPageText, 1938).
--define(wxToolbook_GetSelection, 1939).
--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_GetCurrentPage, 1956).
--define(wxListbook_GetImageList, 1957).
--define(wxListbook_GetPage, 1958).
--define(wxListbook_GetPageCount, 1959).
--define(wxListbook_GetPageImage, 1960).
--define(wxListbook_GetPageText, 1961).
--define(wxListbook_GetSelection, 1962).
--define(wxListbook_HitTest, 1963).
--define(wxListbook_InsertPage, 1964).
--define(wxListbook_SetImageList, 1965).
--define(wxListbook_SetPageSize, 1966).
--define(wxListbook_SetPageImage, 1967).
--define(wxListbook_SetPageText, 1968).
--define(wxListbook_SetSelection, 1969).
--define(wxListbook_ChangeSelection, 1970).
--define(wxListbook_destroy, 1971).
--define(wxTreebook_new_0, 1972).
--define(wxTreebook_new_3, 1973).
--define(wxTreebook_destruct, 1974).
--define(wxTreebook_AddPage, 1975).
--define(wxTreebook_AdvanceSelection, 1976).
--define(wxTreebook_AssignImageList, 1977).
--define(wxTreebook_Create, 1978).
--define(wxTreebook_DeleteAllPages, 1979).
--define(wxTreebook_GetCurrentPage, 1980).
--define(wxTreebook_GetImageList, 1981).
--define(wxTreebook_GetPage, 1982).
--define(wxTreebook_GetPageCount, 1983).
--define(wxTreebook_GetPageImage, 1984).
--define(wxTreebook_GetPageText, 1985).
--define(wxTreebook_GetSelection, 1986).
--define(wxTreebook_ExpandNode, 1987).
--define(wxTreebook_IsNodeExpanded, 1988).
--define(wxTreebook_HitTest, 1989).
--define(wxTreebook_InsertPage, 1990).
--define(wxTreebook_InsertSubPage, 1991).
--define(wxTreebook_SetImageList, 1992).
--define(wxTreebook_SetPageSize, 1993).
--define(wxTreebook_SetPageImage, 1994).
--define(wxTreebook_SetPageText, 1995).
--define(wxTreebook_SetSelection, 1996).
--define(wxTreebook_ChangeSelection, 1997).
--define(wxTreeCtrl_new_0, 1998).
--define(wxTreeCtrl_new_2, 1999).
--define(wxTreeCtrl_destruct, 2000).
--define(wxTreeCtrl_AddRoot, 2001).
--define(wxTreeCtrl_AppendItem, 2002).
--define(wxTreeCtrl_AssignImageList, 2003).
--define(wxTreeCtrl_AssignStateImageList, 2004).
--define(wxTreeCtrl_Collapse, 2005).
--define(wxTreeCtrl_CollapseAndReset, 2006).
--define(wxTreeCtrl_Create, 2007).
--define(wxTreeCtrl_Delete, 2008).
--define(wxTreeCtrl_DeleteAllItems, 2009).
--define(wxTreeCtrl_DeleteChildren, 2010).
--define(wxTreeCtrl_EditLabel, 2011).
--define(wxTreeCtrl_EnsureVisible, 2012).
--define(wxTreeCtrl_Expand, 2013).
--define(wxTreeCtrl_GetBoundingRect, 2014).
--define(wxTreeCtrl_GetChildrenCount, 2015).
--define(wxTreeCtrl_GetCount, 2016).
--define(wxTreeCtrl_GetEditControl, 2017).
--define(wxTreeCtrl_GetFirstChild, 2018).
--define(wxTreeCtrl_GetNextChild, 2019).
--define(wxTreeCtrl_GetFirstVisibleItem, 2020).
--define(wxTreeCtrl_GetImageList, 2021).
--define(wxTreeCtrl_GetIndent, 2022).
--define(wxTreeCtrl_GetItemBackgroundColour, 2023).
--define(wxTreeCtrl_GetItemData, 2024).
--define(wxTreeCtrl_GetItemFont, 2025).
--define(wxTreeCtrl_GetItemImage, 2026).
--define(wxTreeCtrl_GetItemText, 2027).
--define(wxTreeCtrl_GetItemTextColour, 2028).
--define(wxTreeCtrl_GetLastChild, 2029).
--define(wxTreeCtrl_GetNextSibling, 2030).
--define(wxTreeCtrl_GetNextVisible, 2031).
--define(wxTreeCtrl_GetItemParent, 2032).
--define(wxTreeCtrl_GetPrevSibling, 2033).
--define(wxTreeCtrl_GetPrevVisible, 2034).
--define(wxTreeCtrl_GetRootItem, 2035).
--define(wxTreeCtrl_GetSelection, 2036).
--define(wxTreeCtrl_GetSelections, 2037).
--define(wxTreeCtrl_GetStateImageList, 2038).
--define(wxTreeCtrl_HitTest, 2039).
--define(wxTreeCtrl_InsertItem, 2040).
--define(wxTreeCtrl_IsBold, 2042).
--define(wxTreeCtrl_IsExpanded, 2043).
--define(wxTreeCtrl_IsSelected, 2044).
--define(wxTreeCtrl_IsVisible, 2045).
--define(wxTreeCtrl_ItemHasChildren, 2046).
--define(wxTreeCtrl_IsTreeItemIdOk, 2047).
--define(wxTreeCtrl_PrependItem, 2048).
--define(wxTreeCtrl_ScrollTo, 2049).
--define(wxTreeCtrl_SelectItem, 2050).
--define(wxTreeCtrl_SetIndent, 2051).
--define(wxTreeCtrl_SetImageList, 2052).
--define(wxTreeCtrl_SetItemBackgroundColour, 2053).
--define(wxTreeCtrl_SetItemBold, 2054).
--define(wxTreeCtrl_SetItemData, 2055).
--define(wxTreeCtrl_SetItemDropHighlight, 2056).
--define(wxTreeCtrl_SetItemFont, 2057).
--define(wxTreeCtrl_SetItemHasChildren, 2058).
--define(wxTreeCtrl_SetItemImage, 2059).
--define(wxTreeCtrl_SetItemText, 2060).
--define(wxTreeCtrl_SetItemTextColour, 2061).
--define(wxTreeCtrl_SetStateImageList, 2062).
--define(wxTreeCtrl_SetWindowStyle, 2063).
--define(wxTreeCtrl_SortChildren, 2064).
--define(wxTreeCtrl_Toggle, 2065).
--define(wxTreeCtrl_ToggleItemSelection, 2066).
--define(wxTreeCtrl_Unselect, 2067).
--define(wxTreeCtrl_UnselectAll, 2068).
--define(wxTreeCtrl_UnselectItem, 2069).
--define(wxScrollBar_new_0, 2070).
--define(wxScrollBar_new_3, 2071).
--define(wxScrollBar_destruct, 2072).
--define(wxScrollBar_Create, 2073).
--define(wxScrollBar_GetRange, 2074).
--define(wxScrollBar_GetPageSize, 2075).
--define(wxScrollBar_GetThumbPosition, 2076).
--define(wxScrollBar_GetThumbSize, 2077).
--define(wxScrollBar_SetThumbPosition, 2078).
--define(wxScrollBar_SetScrollbar, 2079).
--define(wxSpinButton_new_0, 2080).
--define(wxSpinButton_new_2, 2081).
--define(wxSpinButton_destruct, 2082).
--define(wxSpinButton_Create, 2083).
--define(wxSpinButton_GetMax, 2084).
--define(wxSpinButton_GetMin, 2085).
--define(wxSpinButton_GetValue, 2086).
--define(wxSpinButton_SetRange, 2087).
--define(wxSpinButton_SetValue, 2088).
--define(wxSpinCtrl_new_0, 2089).
--define(wxSpinCtrl_new_2, 2090).
--define(wxSpinCtrl_Create, 2091).
--define(wxSpinCtrl_SetValue_1_1, 2092).
--define(wxSpinCtrl_SetValue_1_0, 2093).
--define(wxSpinCtrl_GetValue, 2094).
--define(wxSpinCtrl_SetRange, 2095).
--define(wxSpinCtrl_SetSelection, 2096).
--define(wxSpinCtrl_GetMin, 2097).
--define(wxSpinCtrl_GetMax, 2098).
--define(wxSpinCtrl_destroy, 2099).
--define(wxStaticText_new_0, 2100).
--define(wxStaticText_new_4, 2101).
--define(wxStaticText_Create, 2102).
--define(wxStaticText_GetLabel, 2103).
--define(wxStaticText_SetLabel, 2104).
--define(wxStaticText_Wrap, 2105).
--define(wxStaticText_destroy, 2106).
--define(wxStaticBitmap_new_0, 2107).
--define(wxStaticBitmap_new_4, 2108).
--define(wxStaticBitmap_Create, 2109).
--define(wxStaticBitmap_GetBitmap, 2110).
--define(wxStaticBitmap_SetBitmap, 2111).
--define(wxStaticBitmap_destroy, 2112).
--define(wxRadioBox_new, 2113).
--define(wxRadioBox_destruct, 2114).
--define(wxRadioBox_Create, 2115).
--define(wxRadioBox_Enable_1, 2116).
--define(wxRadioBox_Enable_2, 2117).
--define(wxRadioBox_GetSelection, 2118).
--define(wxRadioBox_GetString, 2119).
--define(wxRadioBox_SetSelection, 2120).
--define(wxRadioBox_Show, 2121).
--define(wxRadioBox_GetColumnCount, 2122).
--define(wxRadioBox_GetItemHelpText, 2123).
--define(wxRadioBox_GetItemToolTip, 2124).
--define(wxRadioBox_GetItemFromPoint, 2125).
--define(wxRadioBox_GetRowCount, 2126).
--define(wxRadioBox_IsItemEnabled, 2127).
--define(wxRadioBox_IsItemShown, 2128).
--define(wxRadioBox_SetItemHelpText, 2129).
--define(wxRadioBox_SetItemToolTip, 2130).
--define(wxRadioButton_new_0, 2131).
--define(wxRadioButton_new_4, 2132).
--define(wxRadioButton_destruct, 2133).
--define(wxRadioButton_Create, 2134).
--define(wxRadioButton_GetValue, 2135).
--define(wxRadioButton_SetValue, 2136).
--define(wxSlider_new_0, 2137).
--define(wxSlider_new_6, 2138).
--define(wxSlider_destruct, 2139).
--define(wxSlider_Create, 2140).
--define(wxSlider_GetLineSize, 2141).
--define(wxSlider_GetMax, 2142).
--define(wxSlider_GetMin, 2143).
--define(wxSlider_GetPageSize, 2144).
--define(wxSlider_GetThumbLength, 2145).
--define(wxSlider_GetValue, 2146).
--define(wxSlider_SetLineSize, 2147).
--define(wxSlider_SetPageSize, 2148).
--define(wxSlider_SetRange, 2149).
--define(wxSlider_SetThumbLength, 2150).
--define(wxSlider_SetValue, 2151).
--define(wxDialog_new_0, 2152).
--define(wxDialog_new_4, 2153).
--define(wxDialog_destruct, 2154).
--define(wxDialog_Create, 2155).
--define(wxDialog_CreateButtonSizer, 2156).
--define(wxDialog_CreateStdDialogButtonSizer, 2157).
--define(wxDialog_EndModal, 2158).
--define(wxDialog_GetAffirmativeId, 2159).
--define(wxDialog_GetReturnCode, 2160).
--define(wxDialog_IsModal, 2161).
--define(wxDialog_SetAffirmativeId, 2162).
--define(wxDialog_SetReturnCode, 2163).
--define(wxDialog_Show, 2164).
--define(wxDialog_ShowModal, 2165).
--define(wxColourDialog_new_0, 2166).
--define(wxColourDialog_new_2, 2167).
--define(wxColourDialog_destruct, 2168).
--define(wxColourDialog_Create, 2169).
--define(wxColourDialog_GetColourData, 2170).
--define(wxColourData_new, 2171).
--define(wxColourData_destruct, 2172).
--define(wxColourData_GetChooseFull, 2173).
--define(wxColourData_GetColour, 2174).
--define(wxColourData_GetCustomColour, 2175).
--define(wxColourData_SetChooseFull, 2176).
--define(wxColourData_SetColour, 2177).
--define(wxColourData_SetCustomColour, 2178).
--define(wxPalette_new_0, 2179).
--define(wxPalette_new_1, 2180).
--define(wxPalette_new_4, 2181).
--define(wxPalette_destruct, 2182).
--define(wxPalette_Create, 2183).
--define(wxPalette_GetColoursCount, 2184).
--define(wxPalette_GetPixel, 2185).
--define(wxPalette_GetRGB, 2186).
--define(wxPalette_IsOk, 2187).
--define(wxDirDialog_new, 2188).
--define(wxDirDialog_destruct, 2189).
--define(wxDirDialog_GetPath, 2190).
--define(wxDirDialog_GetMessage, 2191).
--define(wxDirDialog_SetMessage, 2192).
--define(wxDirDialog_SetPath, 2193).
--define(wxFileDialog_new, 2194).
--define(wxFileDialog_destruct, 2195).
--define(wxFileDialog_GetDirectory, 2196).
--define(wxFileDialog_GetFilename, 2197).
--define(wxFileDialog_GetFilenames, 2198).
--define(wxFileDialog_GetFilterIndex, 2199).
--define(wxFileDialog_GetMessage, 2200).
--define(wxFileDialog_GetPath, 2201).
--define(wxFileDialog_GetPaths, 2202).
--define(wxFileDialog_GetWildcard, 2203).
--define(wxFileDialog_SetDirectory, 2204).
--define(wxFileDialog_SetFilename, 2205).
--define(wxFileDialog_SetFilterIndex, 2206).
--define(wxFileDialog_SetMessage, 2207).
--define(wxFileDialog_SetPath, 2208).
--define(wxFileDialog_SetWildcard, 2209).
--define(wxPickerBase_SetInternalMargin, 2210).
--define(wxPickerBase_GetInternalMargin, 2211).
--define(wxPickerBase_SetTextCtrlProportion, 2212).
--define(wxPickerBase_SetPickerCtrlProportion, 2213).
--define(wxPickerBase_GetTextCtrlProportion, 2214).
--define(wxPickerBase_GetPickerCtrlProportion, 2215).
--define(wxPickerBase_HasTextCtrl, 2216).
--define(wxPickerBase_GetTextCtrl, 2217).
--define(wxPickerBase_IsTextCtrlGrowable, 2218).
--define(wxPickerBase_SetPickerCtrlGrowable, 2219).
--define(wxPickerBase_SetTextCtrlGrowable, 2220).
--define(wxPickerBase_IsPickerCtrlGrowable, 2221).
--define(wxFilePickerCtrl_new_0, 2222).
--define(wxFilePickerCtrl_new_3, 2223).
--define(wxFilePickerCtrl_Create, 2224).
--define(wxFilePickerCtrl_GetPath, 2225).
--define(wxFilePickerCtrl_SetPath, 2226).
--define(wxFilePickerCtrl_destroy, 2227).
--define(wxDirPickerCtrl_new_0, 2228).
--define(wxDirPickerCtrl_new_3, 2229).
--define(wxDirPickerCtrl_Create, 2230).
--define(wxDirPickerCtrl_GetPath, 2231).
--define(wxDirPickerCtrl_SetPath, 2232).
--define(wxDirPickerCtrl_destroy, 2233).
--define(wxColourPickerCtrl_new_0, 2234).
--define(wxColourPickerCtrl_new_3, 2235).
--define(wxColourPickerCtrl_Create, 2236).
--define(wxColourPickerCtrl_GetColour, 2237).
--define(wxColourPickerCtrl_SetColour_1_1, 2238).
--define(wxColourPickerCtrl_SetColour_1_0, 2239).
--define(wxColourPickerCtrl_destroy, 2240).
--define(wxDatePickerCtrl_new_0, 2241).
--define(wxDatePickerCtrl_new_3, 2242).
--define(wxDatePickerCtrl_GetRange, 2243).
--define(wxDatePickerCtrl_GetValue, 2244).
--define(wxDatePickerCtrl_SetRange, 2245).
--define(wxDatePickerCtrl_SetValue, 2246).
--define(wxDatePickerCtrl_destroy, 2247).
--define(wxFontPickerCtrl_new_0, 2248).
--define(wxFontPickerCtrl_new_3, 2249).
--define(wxFontPickerCtrl_Create, 2250).
--define(wxFontPickerCtrl_GetSelectedFont, 2251).
--define(wxFontPickerCtrl_SetSelectedFont, 2252).
--define(wxFontPickerCtrl_GetMaxPointSize, 2253).
--define(wxFontPickerCtrl_SetMaxPointSize, 2254).
--define(wxFontPickerCtrl_destroy, 2255).
--define(wxFindReplaceDialog_new_0, 2256).
--define(wxFindReplaceDialog_new_4, 2257).
--define(wxFindReplaceDialog_destruct, 2258).
--define(wxFindReplaceDialog_Create, 2259).
--define(wxFindReplaceDialog_GetData, 2260).
--define(wxFindReplaceData_new, 2261).
--define(wxFindReplaceData_GetFindString, 2262).
--define(wxFindReplaceData_GetReplaceString, 2263).
--define(wxFindReplaceData_GetFlags, 2264).
--define(wxFindReplaceData_SetFlags, 2265).
--define(wxFindReplaceData_SetFindString, 2266).
--define(wxFindReplaceData_SetReplaceString, 2267).
--define(wxFindReplaceData_destroy, 2268).
--define(wxMultiChoiceDialog_new, 2270).
--define(wxMultiChoiceDialog_GetSelections, 2271).
--define(wxMultiChoiceDialog_SetSelections, 2272).
--define(wxMultiChoiceDialog_destroy, 2273).
--define(wxSingleChoiceDialog_new, 2275).
--define(wxSingleChoiceDialog_GetSelection, 2276).
--define(wxSingleChoiceDialog_GetStringSelection, 2277).
--define(wxSingleChoiceDialog_SetSelection, 2278).
--define(wxSingleChoiceDialog_destroy, 2279).
--define(wxTextEntryDialog_new_0, 2280).
--define(wxTextEntryDialog_new_3, 2281).
--define(wxTextEntryDialog_destruct, 2282).
--define(wxTextEntryDialog_GetValue, 2283).
--define(wxTextEntryDialog_SetValue, 2284).
--define(wxPasswordEntryDialog_new, 2285).
--define(wxPasswordEntryDialog_destroy, 2286).
--define(wxFontData_new_0, 2287).
--define(wxFontData_new_1, 2288).
--define(wxFontData_EnableEffects, 2289).
--define(wxFontData_GetAllowSymbols, 2290).
--define(wxFontData_GetColour, 2291).
--define(wxFontData_GetChosenFont, 2292).
--define(wxFontData_GetEnableEffects, 2293).
--define(wxFontData_GetInitialFont, 2294).
--define(wxFontData_GetShowHelp, 2295).
--define(wxFontData_SetAllowSymbols, 2296).
--define(wxFontData_SetChosenFont, 2297).
--define(wxFontData_SetColour, 2298).
--define(wxFontData_SetInitialFont, 2299).
--define(wxFontData_SetRange, 2300).
--define(wxFontData_SetShowHelp, 2301).
--define(wxFontData_destroy, 2302).
--define(wxFontDialog_new_0, 2303).
--define(wxFontDialog_new_2, 2305).
--define(wxFontDialog_Create, 2307).
--define(wxFontDialog_GetFontData, 2308).
--define(wxFontDialog_destroy, 2310).
--define(wxProgressDialog_new, 2311).
--define(wxProgressDialog_Resume, 2312).
--define(wxProgressDialog_Update, 2313).
--define(wxProgressDialog_destroy, 2314).
--define(wxMessageDialog_new, 2315).
--define(wxMessageDialog_destroy, 2316).
--define(wxPageSetupDialog_new, 2317).
--define(wxPageSetupDialog_destruct, 2318).
--define(wxPageSetupDialog_GetPageSetupData, 2319).
--define(wxPageSetupDialog_ShowModal, 2320).
--define(wxPageSetupDialogData_new_0, 2321).
--define(wxPageSetupDialogData_new_1, 2323).
--define(wxPageSetupDialogData_destruct, 2324).
--define(wxPageSetupDialogData_EnableHelp, 2325).
--define(wxPageSetupDialogData_EnableMargins, 2326).
--define(wxPageSetupDialogData_EnableOrientation, 2327).
--define(wxPageSetupDialogData_EnablePaper, 2328).
--define(wxPageSetupDialogData_EnablePrinter, 2329).
--define(wxPageSetupDialogData_GetDefaultMinMargins, 2330).
--define(wxPageSetupDialogData_GetEnableMargins, 2331).
--define(wxPageSetupDialogData_GetEnableOrientation, 2332).
--define(wxPageSetupDialogData_GetEnablePaper, 2333).
--define(wxPageSetupDialogData_GetEnablePrinter, 2334).
--define(wxPageSetupDialogData_GetEnableHelp, 2335).
--define(wxPageSetupDialogData_GetDefaultInfo, 2336).
--define(wxPageSetupDialogData_GetMarginTopLeft, 2337).
--define(wxPageSetupDialogData_GetMarginBottomRight, 2338).
--define(wxPageSetupDialogData_GetMinMarginTopLeft, 2339).
--define(wxPageSetupDialogData_GetMinMarginBottomRight, 2340).
--define(wxPageSetupDialogData_GetPaperId, 2341).
--define(wxPageSetupDialogData_GetPaperSize, 2342).
--define(wxPageSetupDialogData_GetPrintData, 2344).
--define(wxPageSetupDialogData_IsOk, 2345).
--define(wxPageSetupDialogData_SetDefaultInfo, 2346).
--define(wxPageSetupDialogData_SetDefaultMinMargins, 2347).
--define(wxPageSetupDialogData_SetMarginTopLeft, 2348).
--define(wxPageSetupDialogData_SetMarginBottomRight, 2349).
--define(wxPageSetupDialogData_SetMinMarginTopLeft, 2350).
--define(wxPageSetupDialogData_SetMinMarginBottomRight, 2351).
--define(wxPageSetupDialogData_SetPaperId, 2352).
--define(wxPageSetupDialogData_SetPaperSize, 2353).
--define(wxPageSetupDialogData_SetPrintData, 2354).
--define(wxPrintDialog_new_2_0, 2355).
--define(wxPrintDialog_new_2_1, 2356).
--define(wxPrintDialog_destruct, 2357).
--define(wxPrintDialog_GetPrintDialogData, 2358).
--define(wxPrintDialog_GetPrintDC, 2359).
--define(wxPrintDialogData_new_0, 2360).
--define(wxPrintDialogData_new_1, 2361).
--define(wxPrintDialogData_destruct, 2363).
--define(wxPrintDialogData_EnableHelp, 2364).
--define(wxPrintDialogData_EnablePageNumbers, 2365).
--define(wxPrintDialogData_EnablePrintToFile, 2366).
--define(wxPrintDialogData_EnableSelection, 2367).
--define(wxPrintDialogData_GetAllPages, 2368).
--define(wxPrintDialogData_GetCollate, 2369).
--define(wxPrintDialogData_GetFromPage, 2370).
--define(wxPrintDialogData_GetMaxPage, 2371).
--define(wxPrintDialogData_GetMinPage, 2372).
--define(wxPrintDialogData_GetNoCopies, 2373).
--define(wxPrintDialogData_GetPrintData, 2374).
--define(wxPrintDialogData_GetPrintToFile, 2375).
--define(wxPrintDialogData_GetSelection, 2376).
--define(wxPrintDialogData_GetToPage, 2377).
--define(wxPrintDialogData_IsOk, 2378).
--define(wxPrintDialogData_SetCollate, 2379).
--define(wxPrintDialogData_SetFromPage, 2380).
--define(wxPrintDialogData_SetMaxPage, 2381).
--define(wxPrintDialogData_SetMinPage, 2382).
--define(wxPrintDialogData_SetNoCopies, 2383).
--define(wxPrintDialogData_SetPrintData, 2384).
--define(wxPrintDialogData_SetPrintToFile, 2385).
--define(wxPrintDialogData_SetSelection, 2386).
--define(wxPrintDialogData_SetToPage, 2387).
--define(wxPrintData_new_0, 2388).
--define(wxPrintData_new_1, 2389).
--define(wxPrintData_destruct, 2390).
--define(wxPrintData_GetCollate, 2391).
--define(wxPrintData_GetBin, 2392).
--define(wxPrintData_GetColour, 2393).
--define(wxPrintData_GetDuplex, 2394).
--define(wxPrintData_GetNoCopies, 2395).
--define(wxPrintData_GetOrientation, 2396).
--define(wxPrintData_GetPaperId, 2397).
--define(wxPrintData_GetPrinterName, 2398).
--define(wxPrintData_GetQuality, 2399).
--define(wxPrintData_IsOk, 2400).
--define(wxPrintData_SetBin, 2401).
--define(wxPrintData_SetCollate, 2402).
--define(wxPrintData_SetColour, 2403).
--define(wxPrintData_SetDuplex, 2404).
--define(wxPrintData_SetNoCopies, 2405).
--define(wxPrintData_SetOrientation, 2406).
--define(wxPrintData_SetPaperId, 2407).
--define(wxPrintData_SetPrinterName, 2408).
--define(wxPrintData_SetQuality, 2409).
--define(wxPrintPreview_new_2, 2410).
--define(wxPrintPreview_new_3, 2411).
--define(wxPrintPreview_destruct, 2412).
--define(wxPrintPreview_GetCanvas, 2413).
--define(wxPrintPreview_GetCurrentPage, 2414).
--define(wxPrintPreview_GetFrame, 2415).
--define(wxPrintPreview_GetMaxPage, 2416).
--define(wxPrintPreview_GetMinPage, 2417).
--define(wxPrintPreview_GetPrintout, 2418).
--define(wxPrintPreview_GetPrintoutForPrinting, 2419).
--define(wxPrintPreview_IsOk, 2420).
--define(wxPrintPreview_PaintPage, 2421).
--define(wxPrintPreview_Print, 2422).
--define(wxPrintPreview_RenderPage, 2423).
--define(wxPrintPreview_SetCanvas, 2424).
--define(wxPrintPreview_SetCurrentPage, 2425).
--define(wxPrintPreview_SetFrame, 2426).
--define(wxPrintPreview_SetPrintout, 2427).
--define(wxPrintPreview_SetZoom, 2428).
--define(wxPreviewFrame_new, 2429).
--define(wxPreviewFrame_destruct, 2430).
--define(wxPreviewFrame_CreateControlBar, 2431).
--define(wxPreviewFrame_CreateCanvas, 2432).
--define(wxPreviewFrame_Initialize, 2433).
--define(wxPreviewFrame_OnCloseWindow, 2434).
--define(wxPreviewControlBar_new, 2435).
--define(wxPreviewControlBar_destruct, 2436).
--define(wxPreviewControlBar_CreateButtons, 2437).
--define(wxPreviewControlBar_GetPrintPreview, 2438).
--define(wxPreviewControlBar_GetZoomControl, 2439).
--define(wxPreviewControlBar_SetZoomControl, 2440).
--define(wxPrinter_new, 2441).
--define(wxPrinter_CreateAbortWindow, 2442).
--define(wxPrinter_GetAbort, 2443).
--define(wxPrinter_GetLastError, 2444).
--define(wxPrinter_GetPrintDialogData, 2445).
--define(wxPrinter_Print, 2446).
--define(wxPrinter_PrintDialog, 2447).
--define(wxPrinter_ReportError, 2448).
--define(wxPrinter_Setup, 2449).
--define(wxPrinter_destroy, 2450).
--define(wxXmlResource_new_2, 2451).
--define(wxXmlResource_new_1, 2452).
--define(wxXmlResource_destruct, 2453).
--define(wxXmlResource_AttachUnknownControl, 2454).
--define(wxXmlResource_ClearHandlers, 2455).
--define(wxXmlResource_CompareVersion, 2456).
--define(wxXmlResource_Get, 2457).
--define(wxXmlResource_GetFlags, 2458).
--define(wxXmlResource_GetVersion, 2459).
--define(wxXmlResource_GetXRCID, 2460).
--define(wxXmlResource_InitAllHandlers, 2461).
--define(wxXmlResource_Load, 2462).
--define(wxXmlResource_LoadBitmap, 2463).
--define(wxXmlResource_LoadDialog_2, 2464).
--define(wxXmlResource_LoadDialog_3, 2465).
--define(wxXmlResource_LoadFrame_2, 2466).
--define(wxXmlResource_LoadFrame_3, 2467).
--define(wxXmlResource_LoadIcon, 2468).
--define(wxXmlResource_LoadMenu, 2469).
--define(wxXmlResource_LoadMenuBar_2, 2470).
--define(wxXmlResource_LoadMenuBar_1, 2471).
--define(wxXmlResource_LoadPanel_2, 2472).
--define(wxXmlResource_LoadPanel_3, 2473).
--define(wxXmlResource_LoadToolBar, 2474).
--define(wxXmlResource_Set, 2475).
--define(wxXmlResource_SetFlags, 2476).
--define(wxXmlResource_Unload, 2477).
--define(wxXmlResource_xrcctrl, 2478).
--define(wxHtmlEasyPrinting_new, 2479).
--define(wxHtmlEasyPrinting_GetPrintData, 2480).
--define(wxHtmlEasyPrinting_GetPageSetupData, 2481).
--define(wxHtmlEasyPrinting_PreviewFile, 2482).
--define(wxHtmlEasyPrinting_PreviewText, 2483).
--define(wxHtmlEasyPrinting_PrintFile, 2484).
--define(wxHtmlEasyPrinting_PrintText, 2485).
--define(wxHtmlEasyPrinting_PageSetup, 2486).
--define(wxHtmlEasyPrinting_SetFonts, 2487).
--define(wxHtmlEasyPrinting_SetHeader, 2488).
--define(wxHtmlEasyPrinting_SetFooter, 2489).
--define(wxHtmlEasyPrinting_destroy, 2490).
--define(wxGLCanvas_new, 2491).
--define(wxGLCanvas_SetCurrent, 2492).
--define(wxGLCanvas_SwapBuffers, 2493).
--define(wxGLCanvas_destroy, 2494).
--define(wxGLContext_new, 2495).
--define(wxGLContext_SetCurrent, 2496).
--define(wxGLContext_destroy, 2497).
--define(wxAuiManager_new, 2498).
--define(wxAuiManager_destruct, 2499).
--define(wxAuiManager_AddPane_2_1, 2500).
--define(wxAuiManager_AddPane_2_0, 2501).
--define(wxAuiManager_AddPane_3, 2502).
--define(wxAuiManager_DetachPane, 2503).
--define(wxAuiManager_GetAllPanes, 2504).
--define(wxAuiManager_GetArtProvider, 2505).
--define(wxAuiManager_GetDockSizeConstraint, 2506).
--define(wxAuiManager_GetFlags, 2507).
--define(wxAuiManager_GetManagedWindow, 2508).
--define(wxAuiManager_GetManager, 2509).
--define(wxAuiManager_GetPane_1_1, 2510).
--define(wxAuiManager_GetPane_1_0, 2511).
--define(wxAuiManager_HideHint, 2512).
--define(wxAuiManager_InsertPane, 2513).
--define(wxAuiManager_LoadPaneInfo, 2514).
--define(wxAuiManager_LoadPerspective, 2515).
--define(wxAuiManager_SavePaneInfo, 2516).
--define(wxAuiManager_SavePerspective, 2517).
--define(wxAuiManager_SetArtProvider, 2518).
--define(wxAuiManager_SetDockSizeConstraint, 2519).
--define(wxAuiManager_SetFlags, 2520).
--define(wxAuiManager_SetManagedWindow, 2521).
--define(wxAuiManager_ShowHint, 2522).
--define(wxAuiManager_UnInit, 2523).
--define(wxAuiManager_Update, 2524).
--define(wxAuiPaneInfo_new_0, 2525).
--define(wxAuiPaneInfo_new_1, 2526).
--define(wxAuiPaneInfo_BestSize_1, 2527).
--define(wxAuiPaneInfo_BestSize_2, 2528).
--define(wxAuiPaneInfo_Bottom, 2529).
--define(wxAuiPaneInfo_BottomDockable, 2530).
--define(wxAuiPaneInfo_Caption, 2531).
--define(wxAuiPaneInfo_CaptionVisible, 2532).
--define(wxAuiPaneInfo_Centre, 2533).
--define(wxAuiPaneInfo_CentrePane, 2534).
--define(wxAuiPaneInfo_CloseButton, 2535).
--define(wxAuiPaneInfo_DefaultPane, 2536).
--define(wxAuiPaneInfo_DestroyOnClose, 2537).
--define(wxAuiPaneInfo_Direction, 2538).
--define(wxAuiPaneInfo_Dock, 2539).
--define(wxAuiPaneInfo_Dockable, 2540).
--define(wxAuiPaneInfo_Fixed, 2541).
--define(wxAuiPaneInfo_Float, 2542).
--define(wxAuiPaneInfo_Floatable, 2543).
--define(wxAuiPaneInfo_FloatingPosition_1, 2544).
--define(wxAuiPaneInfo_FloatingPosition_2, 2545).
--define(wxAuiPaneInfo_FloatingSize_1, 2546).
--define(wxAuiPaneInfo_FloatingSize_2, 2547).
--define(wxAuiPaneInfo_Gripper, 2548).
--define(wxAuiPaneInfo_GripperTop, 2549).
--define(wxAuiPaneInfo_HasBorder, 2550).
--define(wxAuiPaneInfo_HasCaption, 2551).
--define(wxAuiPaneInfo_HasCloseButton, 2552).
--define(wxAuiPaneInfo_HasFlag, 2553).
--define(wxAuiPaneInfo_HasGripper, 2554).
--define(wxAuiPaneInfo_HasGripperTop, 2555).
--define(wxAuiPaneInfo_HasMaximizeButton, 2556).
--define(wxAuiPaneInfo_HasMinimizeButton, 2557).
--define(wxAuiPaneInfo_HasPinButton, 2558).
--define(wxAuiPaneInfo_Hide, 2559).
--define(wxAuiPaneInfo_IsBottomDockable, 2560).
--define(wxAuiPaneInfo_IsDocked, 2561).
--define(wxAuiPaneInfo_IsFixed, 2562).
--define(wxAuiPaneInfo_IsFloatable, 2563).
--define(wxAuiPaneInfo_IsFloating, 2564).
--define(wxAuiPaneInfo_IsLeftDockable, 2565).
--define(wxAuiPaneInfo_IsMovable, 2566).
--define(wxAuiPaneInfo_IsOk, 2567).
--define(wxAuiPaneInfo_IsResizable, 2568).
--define(wxAuiPaneInfo_IsRightDockable, 2569).
--define(wxAuiPaneInfo_IsShown, 2570).
--define(wxAuiPaneInfo_IsToolbar, 2571).
--define(wxAuiPaneInfo_IsTopDockable, 2572).
--define(wxAuiPaneInfo_Layer, 2573).
--define(wxAuiPaneInfo_Left, 2574).
--define(wxAuiPaneInfo_LeftDockable, 2575).
--define(wxAuiPaneInfo_MaxSize_1, 2576).
--define(wxAuiPaneInfo_MaxSize_2, 2577).
--define(wxAuiPaneInfo_MaximizeButton, 2578).
--define(wxAuiPaneInfo_MinSize_1, 2579).
--define(wxAuiPaneInfo_MinSize_2, 2580).
--define(wxAuiPaneInfo_MinimizeButton, 2581).
--define(wxAuiPaneInfo_Movable, 2582).
--define(wxAuiPaneInfo_Name, 2583).
--define(wxAuiPaneInfo_PaneBorder, 2584).
--define(wxAuiPaneInfo_PinButton, 2585).
--define(wxAuiPaneInfo_Position, 2586).
--define(wxAuiPaneInfo_Resizable, 2587).
--define(wxAuiPaneInfo_Right, 2588).
--define(wxAuiPaneInfo_RightDockable, 2589).
--define(wxAuiPaneInfo_Row, 2590).
--define(wxAuiPaneInfo_SafeSet, 2591).
--define(wxAuiPaneInfo_SetFlag, 2592).
--define(wxAuiPaneInfo_Show, 2593).
--define(wxAuiPaneInfo_ToolbarPane, 2594).
--define(wxAuiPaneInfo_Top, 2595).
--define(wxAuiPaneInfo_TopDockable, 2596).
--define(wxAuiPaneInfo_Window, 2597).
--define(wxAuiPaneInfo_GetWindow, 2598).
--define(wxAuiPaneInfo_GetFrame, 2599).
--define(wxAuiPaneInfo_GetDirection, 2600).
--define(wxAuiPaneInfo_GetLayer, 2601).
--define(wxAuiPaneInfo_GetRow, 2602).
--define(wxAuiPaneInfo_GetPosition, 2603).
--define(wxAuiPaneInfo_GetFloatingPosition, 2604).
--define(wxAuiPaneInfo_GetFloatingSize, 2605).
--define(wxAuiPaneInfo_destroy, 2606).
--define(wxAuiNotebook_new_0, 2607).
--define(wxAuiNotebook_new_2, 2608).
--define(wxAuiNotebook_AddPage_3, 2609).
--define(wxAuiNotebook_AddPage_4, 2610).
--define(wxAuiNotebook_Create_2, 2611).
--define(wxAuiNotebook_Create_3, 2612).
--define(wxAuiNotebook_DeletePage, 2613).
--define(wxAuiNotebook_GetArtProvider, 2614).
--define(wxAuiNotebook_GetPage, 2615).
--define(wxAuiNotebook_GetPageBitmap, 2616).
--define(wxAuiNotebook_GetPageCount, 2617).
--define(wxAuiNotebook_GetPageIndex, 2618).
--define(wxAuiNotebook_GetPageText, 2619).
--define(wxAuiNotebook_GetSelection, 2620).
--define(wxAuiNotebook_InsertPage_4, 2621).
--define(wxAuiNotebook_InsertPage_5, 2622).
--define(wxAuiNotebook_RemovePage, 2623).
--define(wxAuiNotebook_SetArtProvider, 2624).
--define(wxAuiNotebook_SetFont, 2625).
--define(wxAuiNotebook_SetPageBitmap, 2626).
--define(wxAuiNotebook_SetPageText, 2627).
--define(wxAuiNotebook_SetSelection, 2628).
--define(wxAuiNotebook_SetTabCtrlHeight, 2629).
--define(wxAuiNotebook_SetUniformBitmapSize, 2630).
--define(wxAuiNotebook_destroy, 2631).
--define(wxAuiTabArt_SetFlags, 2632).
--define(wxAuiTabArt_SetMeasuringFont, 2633).
--define(wxAuiTabArt_SetNormalFont, 2634).
--define(wxAuiTabArt_SetSelectedFont, 2635).
--define(wxAuiTabArt_SetColour, 2636).
--define(wxAuiTabArt_SetActiveColour, 2637).
--define(wxAuiDockArt_GetColour, 2638).
--define(wxAuiDockArt_GetFont, 2639).
--define(wxAuiDockArt_GetMetric, 2640).
--define(wxAuiDockArt_SetColour, 2641).
--define(wxAuiDockArt_SetFont, 2642).
--define(wxAuiDockArt_SetMetric, 2643).
--define(wxAuiSimpleTabArt_new, 2644).
--define(wxAuiSimpleTabArt_destroy, 2645).
--define(wxMDIParentFrame_new_0, 2646).
--define(wxMDIParentFrame_new_4, 2647).
--define(wxMDIParentFrame_destruct, 2648).
--define(wxMDIParentFrame_ActivateNext, 2649).
--define(wxMDIParentFrame_ActivatePrevious, 2650).
--define(wxMDIParentFrame_ArrangeIcons, 2651).
--define(wxMDIParentFrame_Cascade, 2652).
--define(wxMDIParentFrame_Create, 2653).
--define(wxMDIParentFrame_GetActiveChild, 2654).
--define(wxMDIParentFrame_GetClientWindow, 2655).
--define(wxMDIParentFrame_Tile, 2656).
--define(wxMDIChildFrame_new_0, 2657).
--define(wxMDIChildFrame_new_4, 2658).
--define(wxMDIChildFrame_destruct, 2659).
--define(wxMDIChildFrame_Activate, 2660).
--define(wxMDIChildFrame_Create, 2661).
--define(wxMDIChildFrame_Maximize, 2662).
--define(wxMDIChildFrame_Restore, 2663).
--define(wxMDIClientWindow_new, 2664).
--define(wxMDIClientWindow_CreateClient, 2665).
--define(wxMDIClientWindow_destroy, 2666).
--define(wxLayoutAlgorithm_new, 2667).
--define(wxLayoutAlgorithm_destruct, 2668).
--define(wxLayoutAlgorithm_LayoutFrame, 2669).
--define(wxLayoutAlgorithm_LayoutMDIFrame, 2670).
--define(wxLayoutAlgorithm_LayoutWindow, 2671).
--define(wxEvent_GetId, 2672).
--define(wxEvent_GetSkipped, 2673).
--define(wxEvent_GetTimestamp, 2674).
--define(wxEvent_IsCommandEvent, 2675).
--define(wxEvent_ResumePropagation, 2676).
--define(wxEvent_ShouldPropagate, 2677).
--define(wxEvent_Skip, 2678).
--define(wxEvent_StopPropagation, 2679).
--define(wxCommandEvent_getClientData, 2680).
--define(wxCommandEvent_GetExtraLong, 2681).
--define(wxCommandEvent_GetInt, 2682).
--define(wxCommandEvent_GetSelection, 2683).
--define(wxCommandEvent_GetString, 2684).
--define(wxCommandEvent_IsChecked, 2685).
--define(wxCommandEvent_IsSelection, 2686).
--define(wxCommandEvent_SetInt, 2687).
--define(wxCommandEvent_SetString, 2688).
--define(wxScrollEvent_GetOrientation, 2689).
--define(wxScrollEvent_GetPosition, 2690).
--define(wxScrollWinEvent_GetOrientation, 2691).
--define(wxScrollWinEvent_GetPosition, 2692).
--define(wxMouseEvent_AltDown, 2693).
--define(wxMouseEvent_Button, 2694).
--define(wxMouseEvent_ButtonDClick, 2695).
--define(wxMouseEvent_ButtonDown, 2696).
--define(wxMouseEvent_ButtonUp, 2697).
--define(wxMouseEvent_CmdDown, 2698).
--define(wxMouseEvent_ControlDown, 2699).
--define(wxMouseEvent_Dragging, 2700).
--define(wxMouseEvent_Entering, 2701).
--define(wxMouseEvent_GetButton, 2702).
--define(wxMouseEvent_GetPosition, 2703).
--define(wxMouseEvent_GetLogicalPosition, 2705).
--define(wxMouseEvent_GetLinesPerAction, 2706).
--define(wxMouseEvent_GetWheelRotation, 2707).
--define(wxMouseEvent_GetWheelDelta, 2708).
--define(wxMouseEvent_GetX, 2709).
--define(wxMouseEvent_GetY, 2710).
--define(wxMouseEvent_IsButton, 2711).
--define(wxMouseEvent_IsPageScroll, 2712).
--define(wxMouseEvent_Leaving, 2713).
--define(wxMouseEvent_LeftDClick, 2714).
--define(wxMouseEvent_LeftDown, 2715).
--define(wxMouseEvent_LeftIsDown, 2716).
--define(wxMouseEvent_LeftUp, 2717).
--define(wxMouseEvent_MetaDown, 2718).
--define(wxMouseEvent_MiddleDClick, 2719).
--define(wxMouseEvent_MiddleDown, 2720).
--define(wxMouseEvent_MiddleIsDown, 2721).
--define(wxMouseEvent_MiddleUp, 2722).
--define(wxMouseEvent_Moving, 2723).
--define(wxMouseEvent_RightDClick, 2724).
--define(wxMouseEvent_RightDown, 2725).
--define(wxMouseEvent_RightIsDown, 2726).
--define(wxMouseEvent_RightUp, 2727).
--define(wxMouseEvent_ShiftDown, 2728).
--define(wxMouseEvent_GetWheelAxis, 2729).
--define(wxSetCursorEvent_GetCursor, 2730).
--define(wxSetCursorEvent_GetX, 2731).
--define(wxSetCursorEvent_GetY, 2732).
--define(wxSetCursorEvent_HasCursor, 2733).
--define(wxSetCursorEvent_SetCursor, 2734).
--define(wxKeyEvent_AltDown, 2735).
--define(wxKeyEvent_CmdDown, 2736).
--define(wxKeyEvent_ControlDown, 2737).
--define(wxKeyEvent_GetKeyCode, 2738).
--define(wxKeyEvent_GetModifiers, 2739).
--define(wxKeyEvent_GetPosition, 2740).
--define(wxKeyEvent_GetRawKeyCode, 2742).
--define(wxKeyEvent_GetRawKeyFlags, 2743).
--define(wxKeyEvent_GetUnicodeKey, 2744).
--define(wxKeyEvent_GetX, 2745).
--define(wxKeyEvent_GetY, 2746).
--define(wxKeyEvent_HasModifiers, 2747).
--define(wxKeyEvent_MetaDown, 2748).
--define(wxKeyEvent_ShiftDown, 2749).
--define(wxSizeEvent_GetSize, 2750).
--define(wxSizeEvent_GetRect, 2751).
--define(wxMoveEvent_GetPosition, 2752).
--define(wxMoveEvent_GetRect, 2753).
--define(wxEraseEvent_GetDC, 2754).
--define(wxFocusEvent_GetWindow, 2755).
--define(wxChildFocusEvent_GetWindow, 2756).
--define(wxMenuEvent_GetMenu, 2757).
--define(wxMenuEvent_GetMenuId, 2758).
--define(wxMenuEvent_IsPopup, 2759).
--define(wxCloseEvent_CanVeto, 2760).
--define(wxCloseEvent_GetLoggingOff, 2761).
--define(wxCloseEvent_SetCanVeto, 2762).
--define(wxCloseEvent_SetLoggingOff, 2763).
--define(wxCloseEvent_Veto, 2764).
--define(wxShowEvent_SetShow, 2765).
--define(wxShowEvent_IsShown, 2766).
--define(wxIconizeEvent_IsIconized, 2767).
--define(wxJoystickEvent_ButtonDown, 2768).
--define(wxJoystickEvent_ButtonIsDown, 2769).
--define(wxJoystickEvent_ButtonUp, 2770).
--define(wxJoystickEvent_GetButtonChange, 2771).
--define(wxJoystickEvent_GetButtonState, 2772).
--define(wxJoystickEvent_GetJoystick, 2773).
--define(wxJoystickEvent_GetPosition, 2774).
--define(wxJoystickEvent_GetZPosition, 2775).
--define(wxJoystickEvent_IsButton, 2776).
--define(wxJoystickEvent_IsMove, 2777).
--define(wxJoystickEvent_IsZMove, 2778).
--define(wxUpdateUIEvent_CanUpdate, 2779).
--define(wxUpdateUIEvent_Check, 2780).
--define(wxUpdateUIEvent_Enable, 2781).
--define(wxUpdateUIEvent_Show, 2782).
--define(wxUpdateUIEvent_GetChecked, 2783).
--define(wxUpdateUIEvent_GetEnabled, 2784).
--define(wxUpdateUIEvent_GetShown, 2785).
--define(wxUpdateUIEvent_GetSetChecked, 2786).
--define(wxUpdateUIEvent_GetSetEnabled, 2787).
--define(wxUpdateUIEvent_GetSetShown, 2788).
--define(wxUpdateUIEvent_GetSetText, 2789).
--define(wxUpdateUIEvent_GetText, 2790).
--define(wxUpdateUIEvent_GetMode, 2791).
--define(wxUpdateUIEvent_GetUpdateInterval, 2792).
--define(wxUpdateUIEvent_ResetUpdateTime, 2793).
--define(wxUpdateUIEvent_SetMode, 2794).
--define(wxUpdateUIEvent_SetText, 2795).
--define(wxUpdateUIEvent_SetUpdateInterval, 2796).
--define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2797).
--define(wxPaletteChangedEvent_SetChangedWindow, 2798).
--define(wxPaletteChangedEvent_GetChangedWindow, 2799).
--define(wxQueryNewPaletteEvent_SetPaletteRealized, 2800).
--define(wxQueryNewPaletteEvent_GetPaletteRealized, 2801).
--define(wxNavigationKeyEvent_GetDirection, 2802).
--define(wxNavigationKeyEvent_SetDirection, 2803).
--define(wxNavigationKeyEvent_IsWindowChange, 2804).
--define(wxNavigationKeyEvent_SetWindowChange, 2805).
--define(wxNavigationKeyEvent_IsFromTab, 2806).
--define(wxNavigationKeyEvent_SetFromTab, 2807).
--define(wxNavigationKeyEvent_GetCurrentFocus, 2808).
--define(wxNavigationKeyEvent_SetCurrentFocus, 2809).
--define(wxHelpEvent_GetOrigin, 2810).
--define(wxHelpEvent_GetPosition, 2811).
--define(wxHelpEvent_SetOrigin, 2812).
--define(wxHelpEvent_SetPosition, 2813).
--define(wxContextMenuEvent_GetPosition, 2814).
--define(wxContextMenuEvent_SetPosition, 2815).
--define(wxIdleEvent_GetMode, 2816).
--define(wxIdleEvent_RequestMore, 2817).
--define(wxIdleEvent_MoreRequested, 2818).
--define(wxIdleEvent_SetMode, 2819).
--define(wxGridEvent_AltDown, 2820).
--define(wxGridEvent_ControlDown, 2821).
--define(wxGridEvent_GetCol, 2822).
--define(wxGridEvent_GetPosition, 2823).
--define(wxGridEvent_GetRow, 2824).
--define(wxGridEvent_MetaDown, 2825).
--define(wxGridEvent_Selecting, 2826).
--define(wxGridEvent_ShiftDown, 2827).
--define(wxNotifyEvent_Allow, 2828).
--define(wxNotifyEvent_IsAllowed, 2829).
--define(wxNotifyEvent_Veto, 2830).
--define(wxSashEvent_GetEdge, 2831).
--define(wxSashEvent_GetDragRect, 2832).
--define(wxSashEvent_GetDragStatus, 2833).
--define(wxListEvent_GetCacheFrom, 2834).
--define(wxListEvent_GetCacheTo, 2835).
--define(wxListEvent_GetKeyCode, 2836).
--define(wxListEvent_GetIndex, 2837).
--define(wxListEvent_GetColumn, 2838).
--define(wxListEvent_GetPoint, 2839).
--define(wxListEvent_GetLabel, 2840).
--define(wxListEvent_GetText, 2841).
--define(wxListEvent_GetImage, 2842).
--define(wxListEvent_GetData, 2843).
--define(wxListEvent_GetMask, 2844).
--define(wxListEvent_GetItem, 2845).
--define(wxListEvent_IsEditCancelled, 2846).
--define(wxDateEvent_GetDate, 2847).
--define(wxCalendarEvent_GetWeekDay, 2848).
--define(wxCalendarEvent_GetDate, 2849).
--define(wxFileDirPickerEvent_GetPath, 2850).
--define(wxColourPickerEvent_GetColour, 2851).
--define(wxFontPickerEvent_GetFont, 2852).
--define(wxStyledTextEvent_GetPosition, 2853).
--define(wxStyledTextEvent_GetKey, 2854).
--define(wxStyledTextEvent_GetModifiers, 2855).
--define(wxStyledTextEvent_GetModificationType, 2856).
--define(wxStyledTextEvent_GetText, 2857).
--define(wxStyledTextEvent_GetLength, 2858).
--define(wxStyledTextEvent_GetLinesAdded, 2859).
--define(wxStyledTextEvent_GetLine, 2860).
--define(wxStyledTextEvent_GetFoldLevelNow, 2861).
--define(wxStyledTextEvent_GetFoldLevelPrev, 2862).
--define(wxStyledTextEvent_GetMargin, 2863).
--define(wxStyledTextEvent_GetMessage, 2864).
--define(wxStyledTextEvent_GetWParam, 2865).
--define(wxStyledTextEvent_GetLParam, 2866).
--define(wxStyledTextEvent_GetListType, 2867).
--define(wxStyledTextEvent_GetX, 2868).
--define(wxStyledTextEvent_GetY, 2869).
--define(wxStyledTextEvent_GetDragText, 2870).
--define(wxStyledTextEvent_GetDragAllowMove, 2871).
--define(wxStyledTextEvent_GetDragResult, 2872).
--define(wxStyledTextEvent_GetShift, 2873).
--define(wxStyledTextEvent_GetControl, 2874).
--define(wxStyledTextEvent_GetAlt, 2875).
--define(utils_wxGetKeyState, 2876).
--define(utils_wxGetMousePosition, 2877).
--define(utils_wxGetMouseState, 2878).
--define(utils_wxSetDetectableAutoRepeat, 2879).
--define(utils_wxBell, 2880).
--define(utils_wxFindMenuItemId, 2881).
--define(utils_wxFindWindowAtPoint, 2882).
--define(utils_wxBeginBusyCursor, 2883).
--define(utils_wxEndBusyCursor, 2884).
--define(utils_wxIsBusy, 2885).
--define(utils_wxShutdown, 2886).
--define(utils_wxShell, 2887).
--define(utils_wxLaunchDefaultBrowser, 2888).
--define(utils_wxGetEmailAddress, 2889).
--define(utils_wxGetUserId, 2890).
--define(utils_wxGetHomeDir, 2891).
--define(utils_wxNewId, 2892).
--define(utils_wxRegisterId, 2893).
--define(utils_wxGetCurrentId, 2894).
--define(utils_wxGetOsDescription, 2895).
--define(utils_wxIsPlatformLittleEndian, 2896).
--define(utils_wxIsPlatform64Bit, 2897).
--define(gdicmn_wxDisplaySize, 2898).
--define(gdicmn_wxSetCursor, 2899).
--define(wxPrintout_new, 2900).
--define(wxPrintout_destruct, 2901).
--define(wxPrintout_GetDC, 2902).
--define(wxPrintout_GetPageSizeMM, 2903).
--define(wxPrintout_GetPageSizePixels, 2904).
--define(wxPrintout_GetPaperRectPixels, 2905).
--define(wxPrintout_GetPPIPrinter, 2906).
--define(wxPrintout_GetPPIScreen, 2907).
--define(wxPrintout_GetTitle, 2908).
--define(wxPrintout_IsPreview, 2909).
--define(wxPrintout_FitThisSizeToPaper, 2910).
--define(wxPrintout_FitThisSizeToPage, 2911).
--define(wxPrintout_FitThisSizeToPageMargins, 2912).
--define(wxPrintout_MapScreenSizeToPaper, 2913).
--define(wxPrintout_MapScreenSizeToPage, 2914).
--define(wxPrintout_MapScreenSizeToPageMargins, 2915).
--define(wxPrintout_MapScreenSizeToDevice, 2916).
--define(wxPrintout_GetLogicalPaperRect, 2917).
--define(wxPrintout_GetLogicalPageRect, 2918).
--define(wxPrintout_GetLogicalPageMarginsRect, 2919).
--define(wxPrintout_SetLogicalOrigin, 2920).
--define(wxPrintout_OffsetLogicalOrigin, 2921).
--define(wxStyledTextCtrl_new_2, 2922).
--define(wxStyledTextCtrl_new_0, 2923).
--define(wxStyledTextCtrl_destruct, 2924).
--define(wxStyledTextCtrl_Create, 2925).
--define(wxStyledTextCtrl_AddText, 2926).
--define(wxStyledTextCtrl_InsertText, 2927).
--define(wxStyledTextCtrl_ClearAll, 2928).
--define(wxStyledTextCtrl_ClearDocumentStyle, 2929).
--define(wxStyledTextCtrl_GetLength, 2930).
--define(wxStyledTextCtrl_GetCharAt, 2931).
--define(wxStyledTextCtrl_GetCurrentPos, 2932).
--define(wxStyledTextCtrl_GetAnchor, 2933).
--define(wxStyledTextCtrl_GetStyleAt, 2934).
--define(wxStyledTextCtrl_Redo, 2935).
--define(wxStyledTextCtrl_SetUndoCollection, 2936).
--define(wxStyledTextCtrl_SelectAll, 2937).
--define(wxStyledTextCtrl_SetSavePoint, 2938).
--define(wxStyledTextCtrl_CanRedo, 2939).
--define(wxStyledTextCtrl_MarkerLineFromHandle, 2940).
--define(wxStyledTextCtrl_MarkerDeleteHandle, 2941).
--define(wxStyledTextCtrl_GetUndoCollection, 2942).
--define(wxStyledTextCtrl_GetViewWhiteSpace, 2943).
--define(wxStyledTextCtrl_SetViewWhiteSpace, 2944).
--define(wxStyledTextCtrl_PositionFromPoint, 2945).
--define(wxStyledTextCtrl_PositionFromPointClose, 2946).
--define(wxStyledTextCtrl_GotoLine, 2947).
--define(wxStyledTextCtrl_GotoPos, 2948).
--define(wxStyledTextCtrl_SetAnchor, 2949).
--define(wxStyledTextCtrl_GetCurLine, 2950).
--define(wxStyledTextCtrl_GetEndStyled, 2951).
--define(wxStyledTextCtrl_ConvertEOLs, 2952).
--define(wxStyledTextCtrl_GetEOLMode, 2953).
--define(wxStyledTextCtrl_SetEOLMode, 2954).
--define(wxStyledTextCtrl_StartStyling, 2955).
--define(wxStyledTextCtrl_SetStyling, 2956).
--define(wxStyledTextCtrl_GetBufferedDraw, 2957).
--define(wxStyledTextCtrl_SetBufferedDraw, 2958).
--define(wxStyledTextCtrl_SetTabWidth, 2959).
--define(wxStyledTextCtrl_GetTabWidth, 2960).
--define(wxStyledTextCtrl_SetCodePage, 2961).
--define(wxStyledTextCtrl_MarkerDefine, 2962).
--define(wxStyledTextCtrl_MarkerSetForeground, 2963).
--define(wxStyledTextCtrl_MarkerSetBackground, 2964).
--define(wxStyledTextCtrl_MarkerAdd, 2965).
--define(wxStyledTextCtrl_MarkerDelete, 2966).
--define(wxStyledTextCtrl_MarkerDeleteAll, 2967).
--define(wxStyledTextCtrl_MarkerGet, 2968).
--define(wxStyledTextCtrl_MarkerNext, 2969).
--define(wxStyledTextCtrl_MarkerPrevious, 2970).
--define(wxStyledTextCtrl_MarkerDefineBitmap, 2971).
--define(wxStyledTextCtrl_MarkerAddSet, 2972).
--define(wxStyledTextCtrl_MarkerSetAlpha, 2973).
--define(wxStyledTextCtrl_SetMarginType, 2974).
--define(wxStyledTextCtrl_GetMarginType, 2975).
--define(wxStyledTextCtrl_SetMarginWidth, 2976).
--define(wxStyledTextCtrl_GetMarginWidth, 2977).
--define(wxStyledTextCtrl_SetMarginMask, 2978).
--define(wxStyledTextCtrl_GetMarginMask, 2979).
--define(wxStyledTextCtrl_SetMarginSensitive, 2980).
--define(wxStyledTextCtrl_GetMarginSensitive, 2981).
--define(wxStyledTextCtrl_StyleClearAll, 2982).
--define(wxStyledTextCtrl_StyleSetForeground, 2983).
--define(wxStyledTextCtrl_StyleSetBackground, 2984).
--define(wxStyledTextCtrl_StyleSetBold, 2985).
--define(wxStyledTextCtrl_StyleSetItalic, 2986).
--define(wxStyledTextCtrl_StyleSetSize, 2987).
--define(wxStyledTextCtrl_StyleSetFaceName, 2988).
--define(wxStyledTextCtrl_StyleSetEOLFilled, 2989).
--define(wxStyledTextCtrl_StyleResetDefault, 2990).
--define(wxStyledTextCtrl_StyleSetUnderline, 2991).
--define(wxStyledTextCtrl_StyleSetCase, 2992).
--define(wxStyledTextCtrl_StyleSetHotSpot, 2993).
--define(wxStyledTextCtrl_SetSelForeground, 2994).
--define(wxStyledTextCtrl_SetSelBackground, 2995).
--define(wxStyledTextCtrl_GetSelAlpha, 2996).
--define(wxStyledTextCtrl_SetSelAlpha, 2997).
--define(wxStyledTextCtrl_SetCaretForeground, 2998).
--define(wxStyledTextCtrl_CmdKeyAssign, 2999).
--define(wxStyledTextCtrl_CmdKeyClear, 3000).
--define(wxStyledTextCtrl_CmdKeyClearAll, 3001).
--define(wxStyledTextCtrl_SetStyleBytes, 3002).
--define(wxStyledTextCtrl_StyleSetVisible, 3003).
--define(wxStyledTextCtrl_GetCaretPeriod, 3004).
--define(wxStyledTextCtrl_SetCaretPeriod, 3005).
--define(wxStyledTextCtrl_SetWordChars, 3006).
--define(wxStyledTextCtrl_BeginUndoAction, 3007).
--define(wxStyledTextCtrl_EndUndoAction, 3008).
--define(wxStyledTextCtrl_IndicatorSetStyle, 3009).
--define(wxStyledTextCtrl_IndicatorGetStyle, 3010).
--define(wxStyledTextCtrl_IndicatorSetForeground, 3011).
--define(wxStyledTextCtrl_IndicatorGetForeground, 3012).
--define(wxStyledTextCtrl_SetWhitespaceForeground, 3013).
--define(wxStyledTextCtrl_SetWhitespaceBackground, 3014).
--define(wxStyledTextCtrl_GetStyleBits, 3015).
--define(wxStyledTextCtrl_SetLineState, 3016).
--define(wxStyledTextCtrl_GetLineState, 3017).
--define(wxStyledTextCtrl_GetMaxLineState, 3018).
--define(wxStyledTextCtrl_GetCaretLineVisible, 3019).
--define(wxStyledTextCtrl_SetCaretLineVisible, 3020).
--define(wxStyledTextCtrl_GetCaretLineBackground, 3021).
--define(wxStyledTextCtrl_SetCaretLineBackground, 3022).
--define(wxStyledTextCtrl_AutoCompShow, 3023).
--define(wxStyledTextCtrl_AutoCompCancel, 3024).
--define(wxStyledTextCtrl_AutoCompActive, 3025).
--define(wxStyledTextCtrl_AutoCompPosStart, 3026).
--define(wxStyledTextCtrl_AutoCompComplete, 3027).
--define(wxStyledTextCtrl_AutoCompStops, 3028).
--define(wxStyledTextCtrl_AutoCompSetSeparator, 3029).
--define(wxStyledTextCtrl_AutoCompGetSeparator, 3030).
--define(wxStyledTextCtrl_AutoCompSelect, 3031).
--define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3032).
--define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3033).
--define(wxStyledTextCtrl_AutoCompSetFillUps, 3034).
--define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3035).
--define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3036).
--define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3037).
--define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3038).
--define(wxStyledTextCtrl_UserListShow, 3039).
--define(wxStyledTextCtrl_AutoCompSetAutoHide, 3040).
--define(wxStyledTextCtrl_AutoCompGetAutoHide, 3041).
--define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3042).
--define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3043).
--define(wxStyledTextCtrl_RegisterImage, 3044).
--define(wxStyledTextCtrl_ClearRegisteredImages, 3045).
--define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3046).
--define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3047).
--define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3048).
--define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3049).
--define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3050).
--define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3051).
--define(wxStyledTextCtrl_SetIndent, 3052).
--define(wxStyledTextCtrl_GetIndent, 3053).
--define(wxStyledTextCtrl_SetUseTabs, 3054).
--define(wxStyledTextCtrl_GetUseTabs, 3055).
--define(wxStyledTextCtrl_SetLineIndentation, 3056).
--define(wxStyledTextCtrl_GetLineIndentation, 3057).
--define(wxStyledTextCtrl_GetLineIndentPosition, 3058).
--define(wxStyledTextCtrl_GetColumn, 3059).
--define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3060).
--define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3061).
--define(wxStyledTextCtrl_SetIndentationGuides, 3062).
--define(wxStyledTextCtrl_GetIndentationGuides, 3063).
--define(wxStyledTextCtrl_SetHighlightGuide, 3064).
--define(wxStyledTextCtrl_GetHighlightGuide, 3065).
--define(wxStyledTextCtrl_GetLineEndPosition, 3066).
--define(wxStyledTextCtrl_GetCodePage, 3067).
--define(wxStyledTextCtrl_GetCaretForeground, 3068).
--define(wxStyledTextCtrl_GetReadOnly, 3069).
--define(wxStyledTextCtrl_SetCurrentPos, 3070).
--define(wxStyledTextCtrl_SetSelectionStart, 3071).
--define(wxStyledTextCtrl_GetSelectionStart, 3072).
--define(wxStyledTextCtrl_SetSelectionEnd, 3073).
--define(wxStyledTextCtrl_GetSelectionEnd, 3074).
--define(wxStyledTextCtrl_SetPrintMagnification, 3075).
--define(wxStyledTextCtrl_GetPrintMagnification, 3076).
--define(wxStyledTextCtrl_SetPrintColourMode, 3077).
--define(wxStyledTextCtrl_GetPrintColourMode, 3078).
--define(wxStyledTextCtrl_FindText, 3079).
--define(wxStyledTextCtrl_FormatRange, 3080).
--define(wxStyledTextCtrl_GetFirstVisibleLine, 3081).
--define(wxStyledTextCtrl_GetLine, 3082).
--define(wxStyledTextCtrl_GetLineCount, 3083).
--define(wxStyledTextCtrl_SetMarginLeft, 3084).
--define(wxStyledTextCtrl_GetMarginLeft, 3085).
--define(wxStyledTextCtrl_SetMarginRight, 3086).
--define(wxStyledTextCtrl_GetMarginRight, 3087).
--define(wxStyledTextCtrl_GetModify, 3088).
--define(wxStyledTextCtrl_SetSelection, 3089).
--define(wxStyledTextCtrl_GetSelectedText, 3090).
--define(wxStyledTextCtrl_GetTextRange, 3091).
--define(wxStyledTextCtrl_HideSelection, 3092).
--define(wxStyledTextCtrl_LineFromPosition, 3093).
--define(wxStyledTextCtrl_PositionFromLine, 3094).
--define(wxStyledTextCtrl_LineScroll, 3095).
--define(wxStyledTextCtrl_EnsureCaretVisible, 3096).
--define(wxStyledTextCtrl_ReplaceSelection, 3097).
--define(wxStyledTextCtrl_SetReadOnly, 3098).
--define(wxStyledTextCtrl_CanPaste, 3099).
--define(wxStyledTextCtrl_CanUndo, 3100).
--define(wxStyledTextCtrl_EmptyUndoBuffer, 3101).
--define(wxStyledTextCtrl_Undo, 3102).
--define(wxStyledTextCtrl_Cut, 3103).
--define(wxStyledTextCtrl_Copy, 3104).
--define(wxStyledTextCtrl_Paste, 3105).
--define(wxStyledTextCtrl_Clear, 3106).
--define(wxStyledTextCtrl_SetText, 3107).
--define(wxStyledTextCtrl_GetText, 3108).
--define(wxStyledTextCtrl_GetTextLength, 3109).
--define(wxStyledTextCtrl_GetOvertype, 3110).
--define(wxStyledTextCtrl_SetCaretWidth, 3111).
--define(wxStyledTextCtrl_GetCaretWidth, 3112).
--define(wxStyledTextCtrl_SetTargetStart, 3113).
--define(wxStyledTextCtrl_GetTargetStart, 3114).
--define(wxStyledTextCtrl_SetTargetEnd, 3115).
--define(wxStyledTextCtrl_GetTargetEnd, 3116).
--define(wxStyledTextCtrl_ReplaceTarget, 3117).
--define(wxStyledTextCtrl_SearchInTarget, 3118).
--define(wxStyledTextCtrl_SetSearchFlags, 3119).
--define(wxStyledTextCtrl_GetSearchFlags, 3120).
--define(wxStyledTextCtrl_CallTipShow, 3121).
--define(wxStyledTextCtrl_CallTipCancel, 3122).
--define(wxStyledTextCtrl_CallTipActive, 3123).
--define(wxStyledTextCtrl_CallTipPosAtStart, 3124).
--define(wxStyledTextCtrl_CallTipSetHighlight, 3125).
--define(wxStyledTextCtrl_CallTipSetBackground, 3126).
--define(wxStyledTextCtrl_CallTipSetForeground, 3127).
--define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3128).
--define(wxStyledTextCtrl_CallTipUseStyle, 3129).
--define(wxStyledTextCtrl_VisibleFromDocLine, 3130).
--define(wxStyledTextCtrl_DocLineFromVisible, 3131).
--define(wxStyledTextCtrl_WrapCount, 3132).
--define(wxStyledTextCtrl_SetFoldLevel, 3133).
--define(wxStyledTextCtrl_GetFoldLevel, 3134).
--define(wxStyledTextCtrl_GetLastChild, 3135).
--define(wxStyledTextCtrl_GetFoldParent, 3136).
--define(wxStyledTextCtrl_ShowLines, 3137).
--define(wxStyledTextCtrl_HideLines, 3138).
--define(wxStyledTextCtrl_GetLineVisible, 3139).
--define(wxStyledTextCtrl_SetFoldExpanded, 3140).
--define(wxStyledTextCtrl_GetFoldExpanded, 3141).
--define(wxStyledTextCtrl_ToggleFold, 3142).
--define(wxStyledTextCtrl_EnsureVisible, 3143).
--define(wxStyledTextCtrl_SetFoldFlags, 3144).
--define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3145).
--define(wxStyledTextCtrl_SetTabIndents, 3146).
--define(wxStyledTextCtrl_GetTabIndents, 3147).
--define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3148).
--define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3149).
--define(wxStyledTextCtrl_SetMouseDwellTime, 3150).
--define(wxStyledTextCtrl_GetMouseDwellTime, 3151).
--define(wxStyledTextCtrl_WordStartPosition, 3152).
--define(wxStyledTextCtrl_WordEndPosition, 3153).
--define(wxStyledTextCtrl_SetWrapMode, 3154).
--define(wxStyledTextCtrl_GetWrapMode, 3155).
--define(wxStyledTextCtrl_SetWrapVisualFlags, 3156).
--define(wxStyledTextCtrl_GetWrapVisualFlags, 3157).
--define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3158).
--define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3159).
--define(wxStyledTextCtrl_SetWrapStartIndent, 3160).
--define(wxStyledTextCtrl_GetWrapStartIndent, 3161).
--define(wxStyledTextCtrl_SetLayoutCache, 3162).
--define(wxStyledTextCtrl_GetLayoutCache, 3163).
--define(wxStyledTextCtrl_SetScrollWidth, 3164).
--define(wxStyledTextCtrl_GetScrollWidth, 3165).
--define(wxStyledTextCtrl_TextWidth, 3166).
--define(wxStyledTextCtrl_GetEndAtLastLine, 3167).
--define(wxStyledTextCtrl_TextHeight, 3168).
--define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3169).
--define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3170).
--define(wxStyledTextCtrl_AppendText, 3171).
--define(wxStyledTextCtrl_GetTwoPhaseDraw, 3172).
--define(wxStyledTextCtrl_SetTwoPhaseDraw, 3173).
--define(wxStyledTextCtrl_TargetFromSelection, 3174).
--define(wxStyledTextCtrl_LinesJoin, 3175).
--define(wxStyledTextCtrl_LinesSplit, 3176).
--define(wxStyledTextCtrl_SetFoldMarginColour, 3177).
--define(wxStyledTextCtrl_SetFoldMarginHiColour, 3178).
--define(wxStyledTextCtrl_LineDown, 3179).
--define(wxStyledTextCtrl_LineDownExtend, 3180).
--define(wxStyledTextCtrl_LineUp, 3181).
--define(wxStyledTextCtrl_LineUpExtend, 3182).
--define(wxStyledTextCtrl_CharLeft, 3183).
--define(wxStyledTextCtrl_CharLeftExtend, 3184).
--define(wxStyledTextCtrl_CharRight, 3185).
--define(wxStyledTextCtrl_CharRightExtend, 3186).
--define(wxStyledTextCtrl_WordLeft, 3187).
--define(wxStyledTextCtrl_WordLeftExtend, 3188).
--define(wxStyledTextCtrl_WordRight, 3189).
--define(wxStyledTextCtrl_WordRightExtend, 3190).
--define(wxStyledTextCtrl_Home, 3191).
--define(wxStyledTextCtrl_HomeExtend, 3192).
--define(wxStyledTextCtrl_LineEnd, 3193).
--define(wxStyledTextCtrl_LineEndExtend, 3194).
--define(wxStyledTextCtrl_DocumentStart, 3195).
--define(wxStyledTextCtrl_DocumentStartExtend, 3196).
--define(wxStyledTextCtrl_DocumentEnd, 3197).
--define(wxStyledTextCtrl_DocumentEndExtend, 3198).
--define(wxStyledTextCtrl_PageUp, 3199).
--define(wxStyledTextCtrl_PageUpExtend, 3200).
--define(wxStyledTextCtrl_PageDown, 3201).
--define(wxStyledTextCtrl_PageDownExtend, 3202).
--define(wxStyledTextCtrl_EditToggleOvertype, 3203).
--define(wxStyledTextCtrl_Cancel, 3204).
--define(wxStyledTextCtrl_DeleteBack, 3205).
--define(wxStyledTextCtrl_Tab, 3206).
--define(wxStyledTextCtrl_BackTab, 3207).
--define(wxStyledTextCtrl_NewLine, 3208).
--define(wxStyledTextCtrl_FormFeed, 3209).
--define(wxStyledTextCtrl_VCHome, 3210).
--define(wxStyledTextCtrl_VCHomeExtend, 3211).
--define(wxStyledTextCtrl_ZoomIn, 3212).
--define(wxStyledTextCtrl_ZoomOut, 3213).
--define(wxStyledTextCtrl_DelWordLeft, 3214).
--define(wxStyledTextCtrl_DelWordRight, 3215).
--define(wxStyledTextCtrl_LineCut, 3216).
--define(wxStyledTextCtrl_LineDelete, 3217).
--define(wxStyledTextCtrl_LineTranspose, 3218).
--define(wxStyledTextCtrl_LineDuplicate, 3219).
--define(wxStyledTextCtrl_LowerCase, 3220).
--define(wxStyledTextCtrl_UpperCase, 3221).
--define(wxStyledTextCtrl_LineScrollDown, 3222).
--define(wxStyledTextCtrl_LineScrollUp, 3223).
--define(wxStyledTextCtrl_DeleteBackNotLine, 3224).
--define(wxStyledTextCtrl_HomeDisplay, 3225).
--define(wxStyledTextCtrl_HomeDisplayExtend, 3226).
--define(wxStyledTextCtrl_LineEndDisplay, 3227).
--define(wxStyledTextCtrl_LineEndDisplayExtend, 3228).
--define(wxStyledTextCtrl_HomeWrapExtend, 3229).
--define(wxStyledTextCtrl_LineEndWrap, 3230).
--define(wxStyledTextCtrl_LineEndWrapExtend, 3231).
--define(wxStyledTextCtrl_VCHomeWrap, 3232).
--define(wxStyledTextCtrl_VCHomeWrapExtend, 3233).
--define(wxStyledTextCtrl_LineCopy, 3234).
--define(wxStyledTextCtrl_MoveCaretInsideView, 3235).
--define(wxStyledTextCtrl_LineLength, 3236).
--define(wxStyledTextCtrl_BraceHighlight, 3237).
--define(wxStyledTextCtrl_BraceBadLight, 3238).
--define(wxStyledTextCtrl_BraceMatch, 3239).
--define(wxStyledTextCtrl_GetViewEOL, 3240).
--define(wxStyledTextCtrl_SetViewEOL, 3241).
--define(wxStyledTextCtrl_SetModEventMask, 3242).
--define(wxStyledTextCtrl_GetEdgeColumn, 3243).
--define(wxStyledTextCtrl_SetEdgeColumn, 3244).
--define(wxStyledTextCtrl_SetEdgeMode, 3245).
--define(wxStyledTextCtrl_GetEdgeMode, 3246).
--define(wxStyledTextCtrl_GetEdgeColour, 3247).
--define(wxStyledTextCtrl_SetEdgeColour, 3248).
--define(wxStyledTextCtrl_SearchAnchor, 3249).
--define(wxStyledTextCtrl_SearchNext, 3250).
--define(wxStyledTextCtrl_SearchPrev, 3251).
--define(wxStyledTextCtrl_LinesOnScreen, 3252).
--define(wxStyledTextCtrl_UsePopUp, 3253).
--define(wxStyledTextCtrl_SelectionIsRectangle, 3254).
--define(wxStyledTextCtrl_SetZoom, 3255).
--define(wxStyledTextCtrl_GetZoom, 3256).
--define(wxStyledTextCtrl_GetModEventMask, 3257).
--define(wxStyledTextCtrl_SetSTCFocus, 3258).
--define(wxStyledTextCtrl_GetSTCFocus, 3259).
--define(wxStyledTextCtrl_SetStatus, 3260).
--define(wxStyledTextCtrl_GetStatus, 3261).
--define(wxStyledTextCtrl_SetMouseDownCaptures, 3262).
--define(wxStyledTextCtrl_GetMouseDownCaptures, 3263).
--define(wxStyledTextCtrl_SetSTCCursor, 3264).
--define(wxStyledTextCtrl_GetSTCCursor, 3265).
--define(wxStyledTextCtrl_SetControlCharSymbol, 3266).
--define(wxStyledTextCtrl_GetControlCharSymbol, 3267).
--define(wxStyledTextCtrl_WordPartLeft, 3268).
--define(wxStyledTextCtrl_WordPartLeftExtend, 3269).
--define(wxStyledTextCtrl_WordPartRight, 3270).
--define(wxStyledTextCtrl_WordPartRightExtend, 3271).
--define(wxStyledTextCtrl_SetVisiblePolicy, 3272).
--define(wxStyledTextCtrl_DelLineLeft, 3273).
--define(wxStyledTextCtrl_DelLineRight, 3274).
--define(wxStyledTextCtrl_GetXOffset, 3275).
--define(wxStyledTextCtrl_ChooseCaretX, 3276).
--define(wxStyledTextCtrl_SetXCaretPolicy, 3277).
--define(wxStyledTextCtrl_SetYCaretPolicy, 3278).
--define(wxStyledTextCtrl_GetPrintWrapMode, 3279).
--define(wxStyledTextCtrl_SetHotspotActiveForeground, 3280).
--define(wxStyledTextCtrl_SetHotspotActiveBackground, 3281).
--define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3282).
--define(wxStyledTextCtrl_SetHotspotSingleLine, 3283).
--define(wxStyledTextCtrl_ParaDownExtend, 3284).
--define(wxStyledTextCtrl_ParaUp, 3285).
--define(wxStyledTextCtrl_ParaUpExtend, 3286).
--define(wxStyledTextCtrl_PositionBefore, 3287).
--define(wxStyledTextCtrl_PositionAfter, 3288).
--define(wxStyledTextCtrl_CopyRange, 3289).
--define(wxStyledTextCtrl_CopyText, 3290).
--define(wxStyledTextCtrl_SetSelectionMode, 3291).
--define(wxStyledTextCtrl_GetSelectionMode, 3292).
--define(wxStyledTextCtrl_LineDownRectExtend, 3293).
--define(wxStyledTextCtrl_LineUpRectExtend, 3294).
--define(wxStyledTextCtrl_CharLeftRectExtend, 3295).
--define(wxStyledTextCtrl_CharRightRectExtend, 3296).
--define(wxStyledTextCtrl_HomeRectExtend, 3297).
--define(wxStyledTextCtrl_VCHomeRectExtend, 3298).
--define(wxStyledTextCtrl_LineEndRectExtend, 3299).
--define(wxStyledTextCtrl_PageUpRectExtend, 3300).
--define(wxStyledTextCtrl_PageDownRectExtend, 3301).
--define(wxStyledTextCtrl_StutteredPageUp, 3302).
--define(wxStyledTextCtrl_StutteredPageUpExtend, 3303).
--define(wxStyledTextCtrl_StutteredPageDown, 3304).
--define(wxStyledTextCtrl_StutteredPageDownExtend, 3305).
--define(wxStyledTextCtrl_WordLeftEnd, 3306).
--define(wxStyledTextCtrl_WordLeftEndExtend, 3307).
--define(wxStyledTextCtrl_WordRightEnd, 3308).
--define(wxStyledTextCtrl_WordRightEndExtend, 3309).
--define(wxStyledTextCtrl_SetWhitespaceChars, 3310).
--define(wxStyledTextCtrl_SetCharsDefault, 3311).
--define(wxStyledTextCtrl_AutoCompGetCurrent, 3312).
--define(wxStyledTextCtrl_Allocate, 3313).
--define(wxStyledTextCtrl_FindColumn, 3314).
--define(wxStyledTextCtrl_GetCaretSticky, 3315).
--define(wxStyledTextCtrl_SetCaretSticky, 3316).
--define(wxStyledTextCtrl_ToggleCaretSticky, 3317).
--define(wxStyledTextCtrl_SetPasteConvertEndings, 3318).
--define(wxStyledTextCtrl_GetPasteConvertEndings, 3319).
--define(wxStyledTextCtrl_SelectionDuplicate, 3320).
--define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3321).
--define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3322).
--define(wxStyledTextCtrl_StartRecord, 3323).
--define(wxStyledTextCtrl_StopRecord, 3324).
--define(wxStyledTextCtrl_SetLexer, 3325).
--define(wxStyledTextCtrl_GetLexer, 3326).
--define(wxStyledTextCtrl_Colourise, 3327).
--define(wxStyledTextCtrl_SetProperty, 3328).
--define(wxStyledTextCtrl_SetKeyWords, 3329).
--define(wxStyledTextCtrl_SetLexerLanguage, 3330).
--define(wxStyledTextCtrl_GetProperty, 3331).
--define(wxStyledTextCtrl_GetStyleBitsNeeded, 3332).
--define(wxStyledTextCtrl_GetCurrentLine, 3333).
--define(wxStyledTextCtrl_StyleSetSpec, 3334).
--define(wxStyledTextCtrl_StyleSetFont, 3335).
--define(wxStyledTextCtrl_StyleSetFontAttr, 3336).
--define(wxStyledTextCtrl_StyleSetCharacterSet, 3337).
--define(wxStyledTextCtrl_StyleSetFontEncoding, 3338).
--define(wxStyledTextCtrl_CmdKeyExecute, 3339).
--define(wxStyledTextCtrl_SetMargins, 3340).
--define(wxStyledTextCtrl_GetSelection, 3341).
--define(wxStyledTextCtrl_PointFromPosition, 3342).
--define(wxStyledTextCtrl_ScrollToLine, 3343).
--define(wxStyledTextCtrl_ScrollToColumn, 3344).
--define(wxStyledTextCtrl_SetVScrollBar, 3345).
--define(wxStyledTextCtrl_SetHScrollBar, 3346).
--define(wxStyledTextCtrl_GetLastKeydownProcessed, 3347).
--define(wxStyledTextCtrl_SetLastKeydownProcessed, 3348).
--define(wxStyledTextCtrl_SaveFile, 3349).
--define(wxStyledTextCtrl_LoadFile, 3350).
--define(wxStyledTextCtrl_DoDragOver, 3351).
--define(wxStyledTextCtrl_DoDropText, 3352).
--define(wxStyledTextCtrl_GetUseAntiAliasing, 3353).
--define(wxStyledTextCtrl_AddTextRaw, 3354).
--define(wxStyledTextCtrl_InsertTextRaw, 3355).
--define(wxStyledTextCtrl_GetCurLineRaw, 3356).
--define(wxStyledTextCtrl_GetLineRaw, 3357).
--define(wxStyledTextCtrl_GetSelectedTextRaw, 3358).
--define(wxStyledTextCtrl_GetTextRangeRaw, 3359).
--define(wxStyledTextCtrl_SetTextRaw, 3360).
--define(wxStyledTextCtrl_GetTextRaw, 3361).
--define(wxStyledTextCtrl_AppendTextRaw, 3362).
--define(wxArtProvider_GetBitmap, 3363).
--define(wxArtProvider_GetIcon, 3364).
--define(wxTreeEvent_GetKeyCode, 3365).
--define(wxTreeEvent_GetItem, 3366).
--define(wxTreeEvent_GetKeyEvent, 3367).
--define(wxTreeEvent_GetLabel, 3368).
--define(wxTreeEvent_GetOldItem, 3369).
--define(wxTreeEvent_GetPoint, 3370).
--define(wxTreeEvent_IsEditCancelled, 3371).
--define(wxTreeEvent_SetToolTip, 3372).
--define(wxBookCtrlEvent_GetOldSelection, 3373).
--define(wxBookCtrlEvent_GetSelection, 3374).
--define(wxBookCtrlEvent_SetOldSelection, 3375).
--define(wxBookCtrlEvent_SetSelection, 3376).
--define(wxFileDataObject_new, 3377).
--define(wxFileDataObject_AddFile, 3378).
--define(wxFileDataObject_GetFilenames, 3379).
--define(wxFileDataObject_destroy, 3380).
--define(wxTextDataObject_new, 3381).
--define(wxTextDataObject_GetTextLength, 3382).
--define(wxTextDataObject_GetText, 3383).
--define(wxTextDataObject_SetText, 3384).
--define(wxTextDataObject_destroy, 3385).
--define(wxBitmapDataObject_new_1_1, 3386).
--define(wxBitmapDataObject_new_1_0, 3387).
--define(wxBitmapDataObject_GetBitmap, 3388).
--define(wxBitmapDataObject_SetBitmap, 3389).
--define(wxBitmapDataObject_destroy, 3390).
--define(wxClipboard_new, 3391).
--define(wxClipboard_destruct, 3392).
--define(wxClipboard_AddData, 3393).
--define(wxClipboard_Clear, 3394).
--define(wxClipboard_Close, 3395).
--define(wxClipboard_Flush, 3396).
--define(wxClipboard_GetData, 3397).
--define(wxClipboard_IsOpened, 3398).
--define(wxClipboard_Open, 3399).
--define(wxClipboard_SetData, 3400).
--define(wxClipboard_UsePrimarySelection, 3401).
--define(wxClipboard_IsSupported, 3402).
--define(wxClipboard_Get, 3403).
--define(wxSpinEvent_GetPosition, 3404).
--define(wxSpinEvent_SetPosition, 3405).
--define(wxSplitterWindow_new_0, 3406).
--define(wxSplitterWindow_new_2, 3407).
--define(wxSplitterWindow_destruct, 3408).
--define(wxSplitterWindow_Create, 3409).
--define(wxSplitterWindow_GetMinimumPaneSize, 3410).
--define(wxSplitterWindow_GetSashGravity, 3411).
--define(wxSplitterWindow_GetSashPosition, 3412).
--define(wxSplitterWindow_GetSplitMode, 3413).
--define(wxSplitterWindow_GetWindow1, 3414).
--define(wxSplitterWindow_GetWindow2, 3415).
--define(wxSplitterWindow_Initialize, 3416).
--define(wxSplitterWindow_IsSplit, 3417).
--define(wxSplitterWindow_ReplaceWindow, 3418).
--define(wxSplitterWindow_SetSashGravity, 3419).
--define(wxSplitterWindow_SetSashPosition, 3420).
--define(wxSplitterWindow_SetMinimumPaneSize, 3421).
--define(wxSplitterWindow_SetSplitMode, 3422).
--define(wxSplitterWindow_SplitHorizontally, 3423).
--define(wxSplitterWindow_SplitVertically, 3424).
--define(wxSplitterWindow_Unsplit, 3425).
--define(wxSplitterWindow_UpdateSize, 3426).
--define(wxSplitterEvent_GetSashPosition, 3427).
--define(wxSplitterEvent_GetX, 3428).
--define(wxSplitterEvent_GetY, 3429).
--define(wxSplitterEvent_GetWindowBeingRemoved, 3430).
--define(wxSplitterEvent_SetSashPosition, 3431).
--define(wxHtmlWindow_new_0, 3432).
--define(wxHtmlWindow_new_2, 3433).
--define(wxHtmlWindow_AppendToPage, 3434).
--define(wxHtmlWindow_GetOpenedAnchor, 3435).
--define(wxHtmlWindow_GetOpenedPage, 3436).
--define(wxHtmlWindow_GetOpenedPageTitle, 3437).
--define(wxHtmlWindow_GetRelatedFrame, 3438).
--define(wxHtmlWindow_HistoryBack, 3439).
--define(wxHtmlWindow_HistoryCanBack, 3440).
--define(wxHtmlWindow_HistoryCanForward, 3441).
--define(wxHtmlWindow_HistoryClear, 3442).
--define(wxHtmlWindow_HistoryForward, 3443).
--define(wxHtmlWindow_LoadFile, 3444).
--define(wxHtmlWindow_LoadPage, 3445).
--define(wxHtmlWindow_SelectAll, 3446).
--define(wxHtmlWindow_SelectionToText, 3447).
--define(wxHtmlWindow_SelectLine, 3448).
--define(wxHtmlWindow_SelectWord, 3449).
--define(wxHtmlWindow_SetBorders, 3450).
--define(wxHtmlWindow_SetFonts, 3451).
--define(wxHtmlWindow_SetPage, 3452).
--define(wxHtmlWindow_SetRelatedFrame, 3453).
--define(wxHtmlWindow_SetRelatedStatusBar_1, 3454).
--define(wxHtmlWindow_SetRelatedStatusBar_2, 3455).
--define(wxHtmlWindow_ToText, 3456).
--define(wxHtmlWindow_destroy, 3457).
--define(wxHtmlLinkEvent_GetLinkInfo, 3458).
--define(wxSystemSettings_GetColour, 3459).
--define(wxSystemSettings_GetFont, 3460).
--define(wxSystemSettings_GetMetric, 3461).
--define(wxSystemSettings_GetScreenType, 3462).
--define(wxSystemOptions_GetOption, 3463).
--define(wxSystemOptions_GetOptionInt, 3464).
--define(wxSystemOptions_HasOption, 3465).
--define(wxSystemOptions_IsFalse, 3466).
--define(wxSystemOptions_SetOption_2_1, 3467).
--define(wxSystemOptions_SetOption_2_0, 3468).
--define(wxAuiNotebookEvent_SetSelection, 3469).
--define(wxAuiNotebookEvent_GetSelection, 3470).
--define(wxAuiNotebookEvent_SetOldSelection, 3471).
--define(wxAuiNotebookEvent_GetOldSelection, 3472).
--define(wxAuiNotebookEvent_SetDragSource, 3473).
--define(wxAuiNotebookEvent_GetDragSource, 3474).
--define(wxAuiManagerEvent_SetManager, 3475).
--define(wxAuiManagerEvent_GetManager, 3476).
--define(wxAuiManagerEvent_SetPane, 3477).
--define(wxAuiManagerEvent_GetPane, 3478).
--define(wxAuiManagerEvent_SetButton, 3479).
--define(wxAuiManagerEvent_GetButton, 3480).
--define(wxAuiManagerEvent_SetDC, 3481).
--define(wxAuiManagerEvent_GetDC, 3482).
--define(wxAuiManagerEvent_Veto, 3483).
--define(wxAuiManagerEvent_GetVeto, 3484).
--define(wxAuiManagerEvent_SetCanVeto, 3485).
--define(wxAuiManagerEvent_CanVeto, 3486).
--define(wxLogNull_new, 3487).
--define(wxLogNull_destruct, 3488).
--define(wxTaskBarIcon_new, 3489).
--define(wxTaskBarIcon_destruct, 3490).
--define(wxTaskBarIcon_PopupMenu, 3491).
--define(wxTaskBarIcon_RemoveIcon, 3492).
--define(wxTaskBarIcon_SetIcon, 3493).
--define(wxLocale_new_0, 3494).
--define(wxLocale_new_2_0, 3495).
--define(wxLocale_new_2_1, 3496).
--define(wxLocale_destruct, 3497).
--define(wxLocale_Init_1, 3498).
--define(wxLocale_Init_2, 3499).
--define(wxLocale_AddCatalog_1, 3500).
--define(wxLocale_AddCatalog_2, 3501).
--define(wxLocale_AddCatalog_3, 3502).
--define(wxLocale_AddCatalogLookupPathPrefix, 3503).
--define(wxLocale_GetCanonicalName, 3504).
--define(wxLocale_GetLanguage, 3505).
--define(wxLocale_GetLanguageName, 3506).
--define(wxLocale_GetLocale, 3507).
--define(wxLocale_GetName, 3508).
--define(wxLocale_GetString_2, 3509).
--define(wxLocale_GetString_4, 3510).
--define(wxLocale_GetHeaderValue, 3511).
--define(wxLocale_GetSysName, 3512).
--define(wxLocale_GetSystemEncoding, 3513).
--define(wxLocale_GetSystemEncodingName, 3514).
--define(wxLocale_GetSystemLanguage, 3515).
--define(wxLocale_IsLoaded, 3516).
--define(wxLocale_IsOk, 3517).
--define(wxActivateEvent_GetActive, 3518).
--define(wxPopupWindow_new_0, 3519).
--define(wxPopupWindow_new_2, 3520).
--define(wxPopupWindow_Create, 3521).
--define(wxPopupWindow_Position, 3522).
--define(wxPopupWindow_destroy, 3523).
--define(wxPopupTransientWindow_new_0, 3524).
--define(wxPopupTransientWindow_new_2, 3525).
--define(wxPopupTransientWindow_Popup, 3526).
--define(wxPopupTransientWindow_Dismiss, 3527).
--define(wxPopupTransientWindow_destroy, 3528).
--define(wxOverlay_new, 3529).
--define(wxOverlay_destruct, 3530).
--define(wxOverlay_Reset, 3531).
--define(wxDCOverlay_new_6, 3532).
--define(wxDCOverlay_new_2, 3533).
--define(wxDCOverlay_destruct, 3534).
--define(wxDCOverlay_Clear, 3535).
--define(wxDropFilesEvent_GetPosition, 3536).
--define(wxDropFilesEvent_GetNumberOfFiles, 3537).
--define(wxDropFilesEvent_GetFiles, 3538).
--define(wxDisplay_new_0, 3539).
--define(wxDisplay_new_1_0, 3540).
--define(wxDisplay_new_1_1, 3541).
--define(wxDisplay_destruct, 3542).
--define(wxDisplay_IsOk, 3543).
--define(wxDisplay_GetClientArea, 3544).
--define(wxDisplay_GetGeometry, 3545).
--define(wxDisplay_GetName, 3546).
--define(wxDisplay_IsPrimary, 3547).
--define(wxDisplay_GetCount, 3548).
--define(wxDisplay_GetFromPoint, 3549).
--define(wxDisplay_GetFromWindow, 3550).
--define(wxDisplay_GetPPI, 3551).
--define(wxGCDC_new_1, 3552).
--define(wxGCDC_new_0, 3555).
--define(wxGCDC_destruct, 3556).
--define(wxGCDC_GetGraphicsContext, 3557).
--define(wxGCDC_SetGraphicsContext, 3558).
--define(wxNotificationMessage_new_0, 3559).
--define(wxNotificationMessage_new_2, 3560).
--define(wxNotificationMessage_destruct, 3561).
--define(wxNotificationMessage_AddAction, 3562).
--define(wxNotificationMessage_Close, 3563).
--define(wxNotificationMessage_SetFlags, 3564).
--define(wxNotificationMessage_SetIcon, 3565).
--define(wxNotificationMessage_SetMessage, 3566).
--define(wxNotificationMessage_SetParent, 3567).
--define(wxNotificationMessage_SetTitle, 3568).
--define(wxNotificationMessage_Show, 3569).
--define(wxNotificationMessage_UseTaskBarIcon, 3570).
--define(wxNotificationMessage_MSWUseToasts, 3571).
--define(wxWebView_New, 3573).
--define(wxWebView_GetCurrentTitle, 3574).
--define(wxWebView_GetCurrentURL, 3575).
--define(wxWebView_GetPageSource, 3576).
--define(wxWebView_GetPageText, 3577).
--define(wxWebView_IsBusy, 3578).
--define(wxWebView_IsEditable, 3579).
--define(wxWebView_LoadURL, 3580).
--define(wxWebView_Print, 3581).
--define(wxWebView_Reload, 3582).
--define(wxWebView_RunScript, 3583).
--define(wxWebView_SetEditable, 3584).
--define(wxWebView_SetPage, 3585).
--define(wxWebView_Stop, 3586).
--define(wxWebView_CanCopy, 3587).
--define(wxWebView_CanCut, 3588).
--define(wxWebView_CanPaste, 3589).
--define(wxWebView_Copy, 3590).
--define(wxWebView_Cut, 3591).
--define(wxWebView_Paste, 3592).
--define(wxWebView_EnableContextMenu, 3593).
--define(wxWebView_IsContextMenuEnabled, 3594).
--define(wxWebView_CanGoBack, 3595).
--define(wxWebView_CanGoForward, 3596).
--define(wxWebView_ClearHistory, 3597).
--define(wxWebView_EnableHistory, 3598).
--define(wxWebView_GoBack, 3599).
--define(wxWebView_GoForward, 3600).
--define(wxWebView_ClearSelection, 3601).
--define(wxWebView_DeleteSelection, 3602).
--define(wxWebView_GetSelectedSource, 3603).
--define(wxWebView_GetSelectedText, 3604).
--define(wxWebView_HasSelection, 3605).
--define(wxWebView_SelectAll, 3606).
--define(wxWebView_CanRedo, 3607).
--define(wxWebView_CanUndo, 3608).
--define(wxWebView_Redo, 3609).
--define(wxWebView_Undo, 3610).
--define(wxWebView_Find, 3611).
--define(wxWebView_CanSetZoomType, 3612).
--define(wxWebView_GetZoom, 3613).
--define(wxWebView_GetZoomType, 3614).
--define(wxWebView_SetZoom, 3615).
--define(wxWebView_SetZoomType, 3616).
--define(wxWebView_GetZoomFactor, 3617).
--define(wxWebView_SetZoomFactor, 3618).
--define(wxWebView_IsBackendAvailable, 3619).
--define(wxWebViewEvent_GetString, 3620).
--define(wxWebViewEvent_GetInt, 3621).
--define(wxWebViewEvent_GetTarget, 3622).
--define(wxWebViewEvent_GetURL, 3623).
+-define(wxMenuBar_MacGetCommonMenuBar, 874).
+-define(wxMenuBar_MacSetCommonMenuBar, 875).
+-define(wxMenuBar_IsEnabled, 876).
+-define(wxMenuBar_Remove, 877).
+-define(wxMenuBar_Replace, 878).
+-define(wxMenuBar_SetHelpString, 879).
+-define(wxMenuBar_SetLabel, 880).
+-define(wxMenuBar_SetMenuLabel, 881).
+-define(wxControl_GetLabel, 882).
+-define(wxControl_SetLabel, 883).
+-define(wxControlWithItems_Append_1, 884).
+-define(wxControlWithItems_Append_2, 885).
+-define(wxControlWithItems_appendStrings_1, 886).
+-define(wxControlWithItems_appendStrings_2, 887).
+-define(wxControlWithItems_Clear, 888).
+-define(wxControlWithItems_Delete, 889).
+-define(wxControlWithItems_FindString, 890).
+-define(wxControlWithItems_getClientData, 891).
+-define(wxControlWithItems_setClientData, 892).
+-define(wxControlWithItems_GetCount, 893).
+-define(wxControlWithItems_GetSelection, 894).
+-define(wxControlWithItems_GetString, 895).
+-define(wxControlWithItems_GetStringSelection, 896).
+-define(wxControlWithItems_Insert_2, 897).
+-define(wxControlWithItems_Insert_3, 898).
+-define(wxControlWithItems_insertStrings_2, 899).
+-define(wxControlWithItems_insertStrings_3, 900).
+-define(wxControlWithItems_IsEmpty, 901).
+-define(wxControlWithItems_Select, 902).
+-define(wxControlWithItems_SetSelection, 903).
+-define(wxControlWithItems_SetString, 904).
+-define(wxControlWithItems_SetStringSelection, 905).
+-define(wxMenu_new_0, 906).
+-define(wxMenu_new_1, 907).
+-define(wxMenu_new_2, 908).
+-define(wxMenu_destruct, 909).
+-define(wxMenu_Append_3, 910).
+-define(wxMenu_Append_4, 911).
+-define(wxMenu_Append_1, 912).
+-define(wxMenu_AppendCheckItem, 913).
+-define(wxMenu_AppendRadioItem, 914).
+-define(wxMenu_AppendSeparator, 915).
+-define(wxMenu_Break, 916).
+-define(wxMenu_Check, 917).
+-define(wxMenu_Delete_1_0, 918).
+-define(wxMenu_Delete_1_1, 919).
+-define(wxMenu_Destroy_1_0, 920).
+-define(wxMenu_Destroy_1_1, 921).
+-define(wxMenu_Enable, 922).
+-define(wxMenu_FindItem_1, 923).
+-define(wxMenu_FindItem_2, 924).
+-define(wxMenu_FindItemByPosition, 925).
+-define(wxMenu_GetHelpString, 926).
+-define(wxMenu_GetLabel, 927).
+-define(wxMenu_GetMenuItemCount, 928).
+-define(wxMenu_GetMenuItems, 930).
+-define(wxMenu_GetTitle, 931).
+-define(wxMenu_Insert_2, 932).
+-define(wxMenu_Insert_3, 933).
+-define(wxMenu_Insert_5, 934).
+-define(wxMenu_InsertCheckItem, 935).
+-define(wxMenu_InsertRadioItem, 936).
+-define(wxMenu_InsertSeparator, 937).
+-define(wxMenu_IsChecked, 938).
+-define(wxMenu_IsEnabled, 939).
+-define(wxMenu_Prepend_1, 940).
+-define(wxMenu_Prepend_2, 941).
+-define(wxMenu_Prepend_4, 942).
+-define(wxMenu_PrependCheckItem, 943).
+-define(wxMenu_PrependRadioItem, 944).
+-define(wxMenu_PrependSeparator, 945).
+-define(wxMenu_Remove_1_0, 946).
+-define(wxMenu_Remove_1_1, 947).
+-define(wxMenu_SetHelpString, 948).
+-define(wxMenu_SetLabel, 949).
+-define(wxMenu_SetTitle, 950).
+-define(wxMenuItem_new, 951).
+-define(wxMenuItem_destruct, 952).
+-define(wxMenuItem_Check, 953).
+-define(wxMenuItem_Enable, 954).
+-define(wxMenuItem_GetBitmap, 955).
+-define(wxMenuItem_GetHelp, 956).
+-define(wxMenuItem_GetId, 957).
+-define(wxMenuItem_GetKind, 958).
+-define(wxMenuItem_GetLabelText, 959).
+-define(wxMenuItem_GetItemLabel, 960).
+-define(wxMenuItem_GetItemLabelText, 961).
+-define(wxMenuItem_GetMenu, 962).
+-define(wxMenuItem_GetSubMenu, 963).
+-define(wxMenuItem_IsCheckable, 964).
+-define(wxMenuItem_IsChecked, 965).
+-define(wxMenuItem_IsEnabled, 966).
+-define(wxMenuItem_IsSeparator, 967).
+-define(wxMenuItem_IsSubMenu, 968).
+-define(wxMenuItem_SetBitmap, 969).
+-define(wxMenuItem_SetHelp, 970).
+-define(wxMenuItem_SetMenu, 971).
+-define(wxMenuItem_SetSubMenu, 972).
+-define(wxMenuItem_SetItemLabel, 973).
+-define(wxToolBar_AddControl, 974).
+-define(wxToolBar_AddSeparator, 975).
+-define(wxToolBar_AddTool_1, 976).
+-define(wxToolBar_AddTool_4, 977).
+-define(wxToolBar_AddTool_5, 978).
+-define(wxToolBar_AddCheckTool, 979).
+-define(wxToolBar_AddRadioTool, 980).
+-define(wxToolBar_AddStretchableSpace, 981).
+-define(wxToolBar_InsertStretchableSpace, 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_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, 1012).
+-define(wxStatusBar_new_2, 1013).
+-define(wxStatusBar_destruct, 1014).
+-define(wxStatusBar_Create, 1015).
+-define(wxStatusBar_GetFieldRect, 1016).
+-define(wxStatusBar_GetFieldsCount, 1017).
+-define(wxStatusBar_GetStatusText, 1018).
+-define(wxStatusBar_PopStatusText, 1019).
+-define(wxStatusBar_PushStatusText, 1020).
+-define(wxStatusBar_SetFieldsCount, 1021).
+-define(wxStatusBar_SetMinHeight, 1022).
+-define(wxStatusBar_SetStatusText, 1023).
+-define(wxStatusBar_SetStatusWidths, 1024).
+-define(wxStatusBar_SetStatusStyles, 1025).
+-define(wxBitmap_new_0, 1026).
+-define(wxBitmap_new_4, 1028).
+-define(wxBitmap_new_3, 1029).
+-define(wxBitmap_new_2_1, 1030).
+-define(wxBitmap_new_2_0, 1031).
+-define(wxBitmap_new_2_2, 1032).
+-define(wxBitmap_new_2_3, 1033).
+-define(wxBitmap_destruct, 1034).
+-define(wxBitmap_ConvertToImage, 1035).
+-define(wxBitmap_CopyFromIcon, 1036).
+-define(wxBitmap_Create_3_0, 1037).
+-define(wxBitmap_Create_2, 1038).
+-define(wxBitmap_Create_3_1, 1039).
+-define(wxBitmap_GetDepth, 1040).
+-define(wxBitmap_GetHeight, 1041).
+-define(wxBitmap_GetPalette, 1042).
+-define(wxBitmap_GetMask, 1043).
+-define(wxBitmap_GetWidth, 1044).
+-define(wxBitmap_GetSubBitmap, 1045).
+-define(wxBitmap_LoadFile, 1046).
+-define(wxBitmap_IsOk, 1047).
+-define(wxBitmap_SaveFile, 1048).
+-define(wxBitmap_SetDepth, 1049).
+-define(wxBitmap_SetHeight, 1050).
+-define(wxBitmap_SetMask, 1051).
+-define(wxBitmap_SetPalette, 1052).
+-define(wxBitmap_SetWidth, 1053).
+-define(wxIcon_new_0, 1054).
+-define(wxIcon_new_1, 1055).
+-define(wxIcon_new_2, 1056).
+-define(wxIcon_CopyFromBitmap, 1057).
+-define(wxIcon_destruct, 1058).
+-define(wxIconBundle_new_0, 1059).
+-define(wxIconBundle_new_1_1, 1060).
+-define(wxIconBundle_new_2, 1061).
+-define(wxIconBundle_new_1_0, 1063).
+-define(wxIconBundle_destruct, 1064).
+-define(wxIconBundle_AddIcon_1_0, 1065).
+-define(wxIconBundle_AddIcon_2, 1066).
+-define(wxIconBundle_AddIcon_1_1, 1067).
+-define(wxIconBundle_GetIcon_2, 1068).
+-define(wxIconBundle_GetIcon_1, 1069).
+-define(wxCursor_new_0, 1070).
+-define(wxCursor_new_2, 1071).
+-define(wxCursor_new_1_1, 1072).
+-define(wxCursor_new_1_0, 1073).
+-define(wxCursor_destruct, 1075).
+-define(wxCursor_IsOk, 1076).
+-define(wxMask_new_0, 1077).
+-define(wxMask_new_2_0, 1078).
+-define(wxMask_new_1, 1079).
+-define(wxMask_new_2_1, 1080).
+-define(wxMask_destruct, 1081).
+-define(wxMask_Create_2_0, 1082).
+-define(wxMask_Create_1, 1083).
+-define(wxMask_Create_2_1, 1084).
+-define(wxImage_new_0, 1085).
+-define(wxImage_new_3_1, 1086).
+-define(wxImage_new_2_2, 1087).
+-define(wxImage_new_3_0, 1088).
+-define(wxImage_new_2_1, 1089).
+-define(wxImage_new_4, 1090).
+-define(wxImage_new_3_3, 1091).
+-define(wxImage_new_2_0, 1092).
+-define(wxImage_new_3_2, 1093).
+-define(wxImage_destruct, 1094).
+-define(wxImage_Blur, 1095).
+-define(wxImage_BlurHorizontal, 1096).
+-define(wxImage_BlurVertical, 1097).
+-define(wxImage_ConvertAlphaToMask_1, 1098).
+-define(wxImage_ConvertAlphaToMask_4, 1099).
+-define(wxImage_ConvertToGreyscale_3, 1100).
+-define(wxImage_ConvertToGreyscale_0, 1101).
+-define(wxImage_ConvertToMono, 1102).
+-define(wxImage_Copy, 1103).
+-define(wxImage_Create_3_1, 1104).
+-define(wxImage_Create_2_1, 1105).
+-define(wxImage_Create_3_0, 1106).
+-define(wxImage_Create_2_0, 1107).
+-define(wxImage_Create_4, 1108).
+-define(wxImage_Create_3_2, 1109).
+-define(wxImage_Destroy, 1110).
+-define(wxImage_FindFirstUnusedColour, 1111).
+-define(wxImage_GetImageExtWildcard, 1112).
+-define(wxImage_GetAlpha_0, 1113).
+-define(wxImage_GetAlpha_2, 1114).
+-define(wxImage_GetBlue, 1115).
+-define(wxImage_GetData, 1116).
+-define(wxImage_GetGreen, 1117).
+-define(wxImage_GetImageCount, 1118).
+-define(wxImage_GetHeight, 1119).
+-define(wxImage_GetMaskBlue, 1120).
+-define(wxImage_GetMaskGreen, 1121).
+-define(wxImage_GetMaskRed, 1122).
+-define(wxImage_GetOrFindMaskColour, 1123).
+-define(wxImage_GetPalette, 1124).
+-define(wxImage_GetRed, 1125).
+-define(wxImage_GetSubImage, 1126).
+-define(wxImage_GetWidth, 1127).
+-define(wxImage_HasAlpha, 1128).
+-define(wxImage_HasMask, 1129).
+-define(wxImage_GetOption, 1130).
+-define(wxImage_GetOptionInt, 1131).
+-define(wxImage_HasOption, 1132).
+-define(wxImage_InitAlpha, 1133).
+-define(wxImage_InitStandardHandlers, 1134).
+-define(wxImage_IsTransparent, 1135).
+-define(wxImage_LoadFile_2, 1136).
+-define(wxImage_LoadFile_3, 1137).
+-define(wxImage_IsOk, 1138).
+-define(wxImage_RemoveHandler, 1139).
+-define(wxImage_Mirror, 1140).
+-define(wxImage_Replace, 1141).
+-define(wxImage_Rescale, 1142).
+-define(wxImage_Resize, 1143).
+-define(wxImage_Rotate, 1144).
+-define(wxImage_RotateHue, 1145).
+-define(wxImage_Rotate90, 1146).
+-define(wxImage_SaveFile_2_0, 1147).
+-define(wxImage_SaveFile_2_1, 1148).
+-define(wxImage_SaveFile_1, 1149).
+-define(wxImage_Scale, 1150).
+-define(wxImage_Size, 1151).
+-define(wxImage_SetAlpha_1, 1152).
+-define(wxImage_SetAlpha_3, 1153).
+-define(wxImage_SetData_1, 1154).
+-define(wxImage_SetData_3, 1155).
+-define(wxImage_SetMask, 1156).
+-define(wxImage_SetMaskColour, 1157).
+-define(wxImage_SetMaskFromImage, 1158).
+-define(wxImage_SetOption_2_1, 1159).
+-define(wxImage_SetOption_2_0, 1160).
+-define(wxImage_SetPalette, 1161).
+-define(wxImage_SetRGB_5, 1162).
+-define(wxImage_SetRGB_4, 1163).
+-define(wxBrush_new_0, 1164).
+-define(wxBrush_new_2, 1165).
+-define(wxBrush_new_1, 1167).
+-define(wxBrush_destruct, 1168).
+-define(wxBrush_GetColour, 1169).
+-define(wxBrush_GetStipple, 1170).
+-define(wxBrush_GetStyle, 1171).
+-define(wxBrush_IsHatch, 1172).
+-define(wxBrush_IsOk, 1173).
+-define(wxBrush_SetColour_1, 1174).
+-define(wxBrush_SetColour_3, 1175).
+-define(wxBrush_SetStipple, 1176).
+-define(wxBrush_SetStyle, 1177).
+-define(wxPen_new_0, 1178).
+-define(wxPen_new_2, 1179).
+-define(wxPen_new_1, 1180).
+-define(wxPen_destruct, 1181).
+-define(wxPen_GetCap, 1182).
+-define(wxPen_GetColour, 1183).
+-define(wxPen_GetJoin, 1184).
+-define(wxPen_GetStyle, 1185).
+-define(wxPen_GetWidth, 1186).
+-define(wxPen_IsOk, 1187).
+-define(wxPen_SetCap, 1188).
+-define(wxPen_SetColour_1, 1189).
+-define(wxPen_SetColour_3, 1190).
+-define(wxPen_SetJoin, 1191).
+-define(wxPen_SetStyle, 1192).
+-define(wxPen_SetWidth, 1193).
+-define(wxRegion_new_0, 1194).
+-define(wxRegion_new_4, 1195).
+-define(wxRegion_new_2, 1196).
+-define(wxRegion_new_1_0, 1197).
+-define(wxRegion_new_1_1, 1199).
+-define(wxRegion_destruct, 1201).
+-define(wxRegion_Clear, 1202).
+-define(wxRegion_Contains_2, 1203).
+-define(wxRegion_Contains_1_0, 1204).
+-define(wxRegion_Contains_4, 1205).
+-define(wxRegion_Contains_1_1, 1206).
+-define(wxRegion_ConvertToBitmap, 1207).
+-define(wxRegion_GetBox, 1208).
+-define(wxRegion_Intersect_4, 1209).
+-define(wxRegion_Intersect_1_0, 1210).
+-define(wxRegion_Intersect_1_1, 1211).
+-define(wxRegion_IsEmpty, 1212).
+-define(wxRegion_Subtract_1_0, 1213).
+-define(wxRegion_Subtract_1_1, 1214).
+-define(wxRegion_Offset_2, 1215).
+-define(wxRegion_Offset_1, 1216).
+-define(wxRegion_Union_4, 1217).
+-define(wxRegion_Union_1_1, 1218).
+-define(wxRegion_Union_1_0, 1219).
+-define(wxRegion_Union_3, 1221).
+-define(wxRegion_Xor_4, 1222).
+-define(wxRegion_Xor_1_0, 1223).
+-define(wxRegion_Xor_1_1, 1224).
+-define(wxAcceleratorTable_new_0, 1225).
+-define(wxAcceleratorTable_new_2, 1226).
+-define(wxAcceleratorTable_destruct, 1228).
+-define(wxAcceleratorTable_IsOk, 1229).
+-define(wxAcceleratorEntry_new_1_0, 1230).
+-define(wxAcceleratorEntry_new_1_1, 1231).
+-define(wxAcceleratorEntry_GetCommand, 1232).
+-define(wxAcceleratorEntry_GetFlags, 1233).
+-define(wxAcceleratorEntry_GetKeyCode, 1234).
+-define(wxAcceleratorEntry_Set, 1235).
+-define(wxAcceleratorEntry_destroy, 1236).
+-define(wxCaret_new_3, 1238).
+-define(wxCaret_new_2, 1239).
+-define(wxCaret_Create_3, 1240).
+-define(wxCaret_Create_2, 1241).
+-define(wxCaret_GetBlinkTime, 1242).
+-define(wxCaret_GetPosition, 1244).
+-define(wxCaret_GetSize, 1246).
+-define(wxCaret_GetWindow, 1247).
+-define(wxCaret_Hide, 1248).
+-define(wxCaret_IsOk, 1249).
+-define(wxCaret_IsVisible, 1250).
+-define(wxCaret_Move_2, 1251).
+-define(wxCaret_Move_1, 1252).
+-define(wxCaret_SetBlinkTime, 1253).
+-define(wxCaret_SetSize_2, 1254).
+-define(wxCaret_SetSize_1, 1255).
+-define(wxCaret_Show, 1256).
+-define(wxCaret_destroy, 1257).
+-define(wxSizer_Add_2_0, 1258).
+-define(wxSizer_Add_2_1, 1259).
+-define(wxSizer_Add_3_0, 1262).
+-define(wxSizer_Add_3_1, 1263).
+-define(wxSizer_AddSpacer, 1264).
+-define(wxSizer_AddStretchSpacer, 1265).
+-define(wxSizer_CalcMin, 1266).
+-define(wxSizer_Clear, 1267).
+-define(wxSizer_Detach_1_0, 1268).
+-define(wxSizer_Detach_1_1, 1270).
+-define(wxSizer_Fit, 1271).
+-define(wxSizer_FitInside, 1272).
+-define(wxSizer_GetChildren, 1274).
+-define(wxSizer_GetItem_2, 1275).
+-define(wxSizer_GetItem_1, 1277).
+-define(wxSizer_GetSize, 1278).
+-define(wxSizer_GetPosition, 1279).
+-define(wxSizer_GetMinSize, 1280).
+-define(wxSizer_Hide_2, 1281).
+-define(wxSizer_Hide_1, 1283).
+-define(wxSizer_Insert_3_0, 1284).
+-define(wxSizer_Insert_3_1, 1285).
+-define(wxSizer_Insert_4_0, 1288).
+-define(wxSizer_Insert_4_1, 1289).
+-define(wxSizer_Insert_2, 1290).
+-define(wxSizer_InsertSpacer, 1291).
+-define(wxSizer_InsertStretchSpacer, 1292).
+-define(wxSizer_IsShown_1_0, 1293).
+-define(wxSizer_IsShown_1_1, 1295).
+-define(wxSizer_Layout, 1296).
+-define(wxSizer_Prepend_2_0, 1297).
+-define(wxSizer_Prepend_2_1, 1298).
+-define(wxSizer_Prepend_3_0, 1301).
+-define(wxSizer_Prepend_3_1, 1302).
+-define(wxSizer_Prepend_1, 1303).
+-define(wxSizer_PrependSpacer, 1304).
+-define(wxSizer_PrependStretchSpacer, 1305).
+-define(wxSizer_Remove_1_1, 1306).
+-define(wxSizer_Remove_1_0, 1307).
+-define(wxSizer_Replace_3, 1308).
+-define(wxSizer_Replace_2, 1310).
+-define(wxSizer_SetDimension_4, 1311).
+-define(wxSizer_SetDimension_2, 1312).
+-define(wxSizer_SetMinSize_1, 1313).
+-define(wxSizer_SetMinSize_2, 1314).
+-define(wxSizer_SetItemMinSize_3_0, 1315).
+-define(wxSizer_SetItemMinSize_2_0, 1316).
+-define(wxSizer_SetItemMinSize_3_1, 1319).
+-define(wxSizer_SetItemMinSize_2_1, 1320).
+-define(wxSizer_SetSizeHints, 1321).
+-define(wxSizer_Show_2_0, 1322).
+-define(wxSizer_Show_2_1, 1324).
+-define(wxSizer_Show_1, 1325).
+-define(wxSizer_ShowItems, 1326).
+-define(wxSizerFlags_new, 1327).
+-define(wxSizerFlags_Align, 1328).
+-define(wxSizerFlags_Border_2, 1329).
+-define(wxSizerFlags_Border_1, 1330).
+-define(wxSizerFlags_Center, 1331).
+-define(wxSizerFlags_Expand, 1332).
+-define(wxSizerFlags_Left, 1333).
+-define(wxSizerFlags_Proportion, 1334).
+-define(wxSizerFlags_Right, 1335).
+-define(wxSizerFlags_destroy, 1336).
+-define(wxSizerItem_new_3, 1337).
+-define(wxSizerItem_new_2_0, 1338).
+-define(wxSizerItem_new_2_1, 1339).
+-define(wxSizerItem_destruct, 1342).
+-define(wxSizerItem_CalcMin, 1343).
+-define(wxSizerItem_DeleteWindows, 1344).
+-define(wxSizerItem_DetachSizer, 1345).
+-define(wxSizerItem_GetBorder, 1346).
+-define(wxSizerItem_GetFlag, 1347).
+-define(wxSizerItem_GetMinSize, 1348).
+-define(wxSizerItem_GetPosition, 1349).
+-define(wxSizerItem_GetProportion, 1350).
+-define(wxSizerItem_GetRatio, 1351).
+-define(wxSizerItem_GetRect, 1352).
+-define(wxSizerItem_GetSize, 1353).
+-define(wxSizerItem_GetSizer, 1354).
+-define(wxSizerItem_GetSpacer, 1355).
+-define(wxSizerItem_GetUserData, 1356).
+-define(wxSizerItem_GetWindow, 1357).
+-define(wxSizerItem_IsSizer, 1358).
+-define(wxSizerItem_IsShown, 1359).
+-define(wxSizerItem_IsSpacer, 1360).
+-define(wxSizerItem_IsWindow, 1361).
+-define(wxSizerItem_SetBorder, 1362).
+-define(wxSizerItem_SetDimension, 1363).
+-define(wxSizerItem_SetFlag, 1364).
+-define(wxSizerItem_SetInitSize, 1365).
+-define(wxSizerItem_SetMinSize_1, 1366).
+-define(wxSizerItem_SetMinSize_2, 1367).
+-define(wxSizerItem_SetProportion, 1368).
+-define(wxSizerItem_SetRatio_2, 1369).
+-define(wxSizerItem_SetRatio_1_1, 1370).
+-define(wxSizerItem_SetRatio_1_0, 1371).
+-define(wxSizerItem_AssignSizer, 1372).
+-define(wxSizerItem_AssignSpacer_1, 1373).
+-define(wxSizerItem_AssignSpacer_2, 1374).
+-define(wxSizerItem_AssignWindow, 1375).
+-define(wxSizerItem_Show, 1376).
+-define(wxBoxSizer_new, 1377).
+-define(wxBoxSizer_GetOrientation, 1378).
+-define(wxBoxSizer_destroy, 1379).
+-define(wxStaticBoxSizer_new_2, 1380).
+-define(wxStaticBoxSizer_new_3, 1381).
+-define(wxStaticBoxSizer_GetStaticBox, 1382).
+-define(wxStaticBoxSizer_destroy, 1383).
+-define(wxGridSizer_new_3_0, 1384).
+-define(wxGridSizer_new_2, 1385).
+-define(wxGridSizer_new_4, 1386).
+-define(wxGridSizer_new_3_1, 1387).
+-define(wxGridSizer_GetCols, 1388).
+-define(wxGridSizer_GetHGap, 1389).
+-define(wxGridSizer_GetRows, 1390).
+-define(wxGridSizer_GetVGap, 1391).
+-define(wxGridSizer_SetCols, 1392).
+-define(wxGridSizer_SetHGap, 1393).
+-define(wxGridSizer_SetRows, 1394).
+-define(wxGridSizer_SetVGap, 1395).
+-define(wxGridSizer_destroy, 1396).
+-define(wxFlexGridSizer_new_3_0, 1397).
+-define(wxFlexGridSizer_new_2, 1398).
+-define(wxFlexGridSizer_new_4, 1399).
+-define(wxFlexGridSizer_new_3_1, 1400).
+-define(wxFlexGridSizer_AddGrowableCol, 1401).
+-define(wxFlexGridSizer_AddGrowableRow, 1402).
+-define(wxFlexGridSizer_GetFlexibleDirection, 1403).
+-define(wxFlexGridSizer_GetNonFlexibleGrowMode, 1404).
+-define(wxFlexGridSizer_RemoveGrowableCol, 1405).
+-define(wxFlexGridSizer_RemoveGrowableRow, 1406).
+-define(wxFlexGridSizer_SetFlexibleDirection, 1407).
+-define(wxFlexGridSizer_SetNonFlexibleGrowMode, 1408).
+-define(wxFlexGridSizer_destroy, 1409).
+-define(wxGridBagSizer_new, 1410).
+-define(wxGridBagSizer_Add_3, 1411).
+-define(wxGridBagSizer_Add_1, 1413).
+-define(wxGridBagSizer_Add_4, 1414).
+-define(wxGridBagSizer_CalcMin, 1415).
+-define(wxGridBagSizer_CheckForIntersection_2, 1416).
+-define(wxGridBagSizer_CheckForIntersection_3, 1417).
+-define(wxGridBagSizer_FindItem, 1418).
+-define(wxGridBagSizer_FindItemAtPoint, 1420).
+-define(wxGridBagSizer_FindItemAtPosition, 1421).
+-define(wxGridBagSizer_FindItemWithData, 1422).
+-define(wxGridBagSizer_GetCellSize, 1423).
+-define(wxGridBagSizer_GetEmptyCellSize, 1424).
+-define(wxGridBagSizer_GetItemPosition_1_0, 1425).
+-define(wxGridBagSizer_GetItemPosition_1_1, 1427).
+-define(wxGridBagSizer_GetItemSpan_1_0, 1428).
+-define(wxGridBagSizer_GetItemSpan_1_1, 1430).
+-define(wxGridBagSizer_SetEmptyCellSize, 1431).
+-define(wxGridBagSizer_SetItemPosition_2_0, 1432).
+-define(wxGridBagSizer_SetItemPosition_2_1, 1434).
+-define(wxGridBagSizer_SetItemSpan_2_0, 1435).
+-define(wxGridBagSizer_SetItemSpan_2_1, 1437).
+-define(wxGridBagSizer_destroy, 1438).
+-define(wxStdDialogButtonSizer_new, 1439).
+-define(wxStdDialogButtonSizer_AddButton, 1440).
+-define(wxStdDialogButtonSizer_Realize, 1441).
+-define(wxStdDialogButtonSizer_SetAffirmativeButton, 1442).
+-define(wxStdDialogButtonSizer_SetCancelButton, 1443).
+-define(wxStdDialogButtonSizer_SetNegativeButton, 1444).
+-define(wxStdDialogButtonSizer_destroy, 1445).
+-define(wxFont_new_0, 1446).
+-define(wxFont_new_1_1, 1447).
+-define(wxFont_new_5_0, 1448).
+-define(wxFont_new_5_1, 1449).
+-define(wxFont_new_1_0, 1450).
+-define(wxFont_destruct, 1451).
+-define(wxFont_IsFixedWidth, 1452).
+-define(wxFont_GetDefaultEncoding, 1453).
+-define(wxFont_GetFaceName, 1454).
+-define(wxFont_GetFamily, 1455).
+-define(wxFont_GetNativeFontInfoDesc, 1456).
+-define(wxFont_GetNativeFontInfoUserDesc, 1457).
+-define(wxFont_GetPointSize, 1458).
+-define(wxFont_GetStyle, 1459).
+-define(wxFont_GetUnderlined, 1460).
+-define(wxFont_GetWeight, 1461).
+-define(wxFont_IsOk, 1462).
+-define(wxFont_SetDefaultEncoding, 1463).
+-define(wxFont_SetFaceName, 1464).
+-define(wxFont_SetFamily, 1465).
+-define(wxFont_SetPointSize, 1466).
+-define(wxFont_SetStyle, 1467).
+-define(wxFont_SetUnderlined, 1468).
+-define(wxFont_SetWeight, 1469).
+-define(wxToolTip_Enable, 1470).
+-define(wxToolTip_SetDelay, 1471).
+-define(wxToolTip_new, 1472).
+-define(wxToolTip_SetTip, 1473).
+-define(wxToolTip_GetTip, 1474).
+-define(wxToolTip_GetWindow, 1475).
+-define(wxToolTip_destroy, 1476).
+-define(wxButton_new_0, 1477).
+-define(wxButton_new_3, 1478).
+-define(wxButton_Create, 1479).
+-define(wxButton_GetDefaultSize_STAT_0, 1480).
+-define(wxButton_GetDefaultSize_STAT_1, 1481).
+-define(wxButton_SetDefault, 1482).
+-define(wxButton_SetLabel, 1483).
+-define(wxButton_GetBitmapDisabled, 1484).
+-define(wxButton_GetBitmapFocus, 1485).
+-define(wxButton_GetBitmapLabel, 1486).
+-define(wxButton_SetBitmapDisabled, 1487).
+-define(wxButton_SetBitmapFocus, 1488).
+-define(wxButton_SetBitmapLabel, 1489).
+-define(wxButton_destroy, 1490).
+-define(wxBitmapButton_new_0, 1491).
+-define(wxBitmapButton_new_4, 1492).
+-define(wxBitmapButton_Create, 1493).
+-define(wxBitmapButton_NewCloseButton, 1494).
+-define(wxBitmapButton_destroy, 1495).
+-define(wxToggleButton_new_0, 1496).
+-define(wxToggleButton_new_4, 1497).
+-define(wxToggleButton_destruct, 1498).
+-define(wxToggleButton_Create, 1499).
+-define(wxToggleButton_GetValue, 1500).
+-define(wxToggleButton_SetValue, 1501).
+-define(wxCalendarCtrl_new_0, 1502).
+-define(wxCalendarCtrl_new_3, 1503).
+-define(wxCalendarCtrl_Create, 1504).
+-define(wxCalendarCtrl_destruct, 1505).
+-define(wxCalendarCtrl_SetDate, 1506).
+-define(wxCalendarCtrl_GetDate, 1507).
+-define(wxCalendarCtrl_EnableYearChange, 1508).
+-define(wxCalendarCtrl_EnableMonthChange, 1509).
+-define(wxCalendarCtrl_EnableHolidayDisplay, 1510).
+-define(wxCalendarCtrl_SetHeaderColours, 1511).
+-define(wxCalendarCtrl_GetHeaderColourFg, 1512).
+-define(wxCalendarCtrl_GetHeaderColourBg, 1513).
+-define(wxCalendarCtrl_SetHighlightColours, 1514).
+-define(wxCalendarCtrl_GetHighlightColourFg, 1515).
+-define(wxCalendarCtrl_GetHighlightColourBg, 1516).
+-define(wxCalendarCtrl_SetHolidayColours, 1517).
+-define(wxCalendarCtrl_GetHolidayColourFg, 1518).
+-define(wxCalendarCtrl_GetHolidayColourBg, 1519).
+-define(wxCalendarCtrl_GetAttr, 1520).
+-define(wxCalendarCtrl_SetAttr, 1521).
+-define(wxCalendarCtrl_SetHoliday, 1522).
+-define(wxCalendarCtrl_ResetAttr, 1523).
+-define(wxCalendarCtrl_HitTest, 1524).
+-define(wxCalendarDateAttr_new_1, 1525).
+-define(wxCalendarDateAttr_new_2, 1526).
+-define(wxCalendarDateAttr_SetTextColour, 1527).
+-define(wxCalendarDateAttr_SetBackgroundColour, 1528).
+-define(wxCalendarDateAttr_SetBorderColour, 1529).
+-define(wxCalendarDateAttr_SetFont, 1530).
+-define(wxCalendarDateAttr_SetBorder, 1531).
+-define(wxCalendarDateAttr_SetHoliday, 1532).
+-define(wxCalendarDateAttr_HasTextColour, 1533).
+-define(wxCalendarDateAttr_HasBackgroundColour, 1534).
+-define(wxCalendarDateAttr_HasBorderColour, 1535).
+-define(wxCalendarDateAttr_HasFont, 1536).
+-define(wxCalendarDateAttr_HasBorder, 1537).
+-define(wxCalendarDateAttr_IsHoliday, 1538).
+-define(wxCalendarDateAttr_GetTextColour, 1539).
+-define(wxCalendarDateAttr_GetBackgroundColour, 1540).
+-define(wxCalendarDateAttr_GetBorderColour, 1541).
+-define(wxCalendarDateAttr_GetFont, 1542).
+-define(wxCalendarDateAttr_GetBorder, 1543).
+-define(wxCalendarDateAttr_destroy, 1544).
+-define(wxCheckBox_new_0, 1545).
+-define(wxCheckBox_new_4, 1546).
+-define(wxCheckBox_destruct, 1547).
+-define(wxCheckBox_Create, 1548).
+-define(wxCheckBox_GetValue, 1549).
+-define(wxCheckBox_Get3StateValue, 1550).
+-define(wxCheckBox_Is3rdStateAllowedForUser, 1551).
+-define(wxCheckBox_Is3State, 1552).
+-define(wxCheckBox_IsChecked, 1553).
+-define(wxCheckBox_SetValue, 1554).
+-define(wxCheckBox_Set3StateValue, 1555).
+-define(wxCheckListBox_new_0, 1556).
+-define(wxCheckListBox_new_3, 1558).
+-define(wxCheckListBox_destruct, 1559).
+-define(wxCheckListBox_Check, 1560).
+-define(wxCheckListBox_IsChecked, 1561).
+-define(wxChoice_new_0, 1562).
+-define(wxChoice_new_3, 1564).
+-define(wxChoice_destruct, 1565).
+-define(wxChoice_Create, 1567).
+-define(wxChoice_Delete, 1568).
+-define(wxChoice_GetColumns, 1569).
+-define(wxChoice_SetColumns, 1570).
+-define(wxComboBox_new_0, 1571).
+-define(wxComboBox_new_3, 1573).
+-define(wxComboBox_destruct, 1574).
+-define(wxComboBox_Create, 1576).
+-define(wxComboBox_CanCopy, 1577).
+-define(wxComboBox_CanCut, 1578).
+-define(wxComboBox_CanPaste, 1579).
+-define(wxComboBox_CanRedo, 1580).
+-define(wxComboBox_CanUndo, 1581).
+-define(wxComboBox_Copy, 1582).
+-define(wxComboBox_Cut, 1583).
+-define(wxComboBox_GetInsertionPoint, 1584).
+-define(wxComboBox_GetLastPosition, 1585).
+-define(wxComboBox_GetValue, 1586).
+-define(wxComboBox_Paste, 1587).
+-define(wxComboBox_Redo, 1588).
+-define(wxComboBox_Replace, 1589).
+-define(wxComboBox_Remove, 1590).
+-define(wxComboBox_SetInsertionPoint, 1591).
+-define(wxComboBox_SetInsertionPointEnd, 1592).
+-define(wxComboBox_SetSelection_2, 1593).
+-define(wxComboBox_SetSelection_1, 1594).
+-define(wxComboBox_SetValue, 1595).
+-define(wxComboBox_Undo, 1596).
+-define(wxGauge_new_0, 1597).
+-define(wxGauge_new_4, 1598).
+-define(wxGauge_destruct, 1599).
+-define(wxGauge_Create, 1600).
+-define(wxGauge_GetRange, 1601).
+-define(wxGauge_GetValue, 1602).
+-define(wxGauge_IsVertical, 1603).
+-define(wxGauge_SetRange, 1604).
+-define(wxGauge_SetValue, 1605).
+-define(wxGauge_Pulse, 1606).
+-define(wxGenericDirCtrl_new_0, 1607).
+-define(wxGenericDirCtrl_new_2, 1608).
+-define(wxGenericDirCtrl_destruct, 1609).
+-define(wxGenericDirCtrl_Create, 1610).
+-define(wxGenericDirCtrl_Init, 1611).
+-define(wxGenericDirCtrl_CollapseTree, 1612).
+-define(wxGenericDirCtrl_ExpandPath, 1613).
+-define(wxGenericDirCtrl_GetDefaultPath, 1614).
+-define(wxGenericDirCtrl_GetPath_0, 1615).
+-define(wxGenericDirCtrl_GetPath_1, 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_0, 1627).
+-define(wxStaticBox_new_4, 1628).
+-define(wxStaticBox_destruct, 1629).
+-define(wxStaticBox_Create, 1630).
+-define(wxStaticLine_new_0, 1631).
+-define(wxStaticLine_new_2, 1632).
+-define(wxStaticLine_Create, 1633).
+-define(wxStaticLine_IsVertical, 1634).
+-define(wxStaticLine_GetDefaultSize, 1635).
+-define(wxStaticLine_destroy, 1636).
+-define(wxListBox_new_0, 1637).
+-define(wxListBox_new_3, 1639).
+-define(wxListBox_destruct, 1640).
+-define(wxListBox_Create, 1642).
+-define(wxListBox_Deselect, 1643).
+-define(wxListBox_GetSelections, 1644).
+-define(wxListBox_InsertItems, 1645).
+-define(wxListBox_IsSelected, 1646).
+-define(wxListBox_Set, 1649).
+-define(wxListBox_HitTest_1, 1650).
+-define(wxListBox_HitTest_2, 1651).
+-define(wxListBox_SetFirstItem_1_0, 1652).
+-define(wxListBox_SetFirstItem_1_1, 1653).
+-define(wxListCtrl_new_0, 1654).
+-define(wxListCtrl_new_2, 1655).
+-define(wxListCtrl_destruct, 1656).
+-define(wxListCtrl_Arrange, 1657).
+-define(wxListCtrl_AssignImageList, 1658).
+-define(wxListCtrl_ClearAll, 1659).
+-define(wxListCtrl_Create, 1660).
+-define(wxListCtrl_DeleteAllItems, 1661).
+-define(wxListCtrl_DeleteColumn, 1662).
+-define(wxListCtrl_DeleteItem, 1663).
+-define(wxListCtrl_EditLabel, 1664).
+-define(wxListCtrl_EnsureVisible, 1665).
+-define(wxListCtrl_FindItem_3_0, 1666).
+-define(wxListCtrl_FindItem_3_1, 1667).
+-define(wxListCtrl_GetColumn, 1668).
+-define(wxListCtrl_GetColumnCount, 1669).
+-define(wxListCtrl_GetColumnWidth, 1670).
+-define(wxListCtrl_GetCountPerPage, 1671).
+-define(wxListCtrl_GetEditControl, 1672).
+-define(wxListCtrl_GetImageList, 1673).
+-define(wxListCtrl_GetItem, 1674).
+-define(wxListCtrl_GetItemBackgroundColour, 1675).
+-define(wxListCtrl_GetItemCount, 1676).
+-define(wxListCtrl_GetItemData, 1677).
+-define(wxListCtrl_GetItemFont, 1678).
+-define(wxListCtrl_GetItemPosition, 1679).
+-define(wxListCtrl_GetItemRect, 1680).
+-define(wxListCtrl_GetItemSpacing, 1681).
+-define(wxListCtrl_GetItemState, 1682).
+-define(wxListCtrl_GetItemText, 1683).
+-define(wxListCtrl_GetItemTextColour, 1684).
+-define(wxListCtrl_GetNextItem, 1685).
+-define(wxListCtrl_GetSelectedItemCount, 1686).
+-define(wxListCtrl_GetTextColour, 1687).
+-define(wxListCtrl_GetTopItem, 1688).
+-define(wxListCtrl_GetViewRect, 1689).
+-define(wxListCtrl_HitTest, 1690).
+-define(wxListCtrl_InsertColumn_2, 1691).
+-define(wxListCtrl_InsertColumn_3, 1692).
+-define(wxListCtrl_InsertItem_1, 1693).
+-define(wxListCtrl_InsertItem_2_1, 1694).
+-define(wxListCtrl_InsertItem_2_0, 1695).
+-define(wxListCtrl_InsertItem_3, 1696).
+-define(wxListCtrl_RefreshItem, 1697).
+-define(wxListCtrl_RefreshItems, 1698).
+-define(wxListCtrl_ScrollList, 1699).
+-define(wxListCtrl_SetBackgroundColour, 1700).
+-define(wxListCtrl_SetColumn, 1701).
+-define(wxListCtrl_SetColumnWidth, 1702).
+-define(wxListCtrl_SetImageList, 1703).
+-define(wxListCtrl_SetItem_1, 1704).
+-define(wxListCtrl_SetItem_4, 1705).
+-define(wxListCtrl_SetItemBackgroundColour, 1706).
+-define(wxListCtrl_SetItemCount, 1707).
+-define(wxListCtrl_SetItemData, 1708).
+-define(wxListCtrl_SetItemFont, 1709).
+-define(wxListCtrl_SetItemImage, 1710).
+-define(wxListCtrl_SetItemColumnImage, 1711).
+-define(wxListCtrl_SetItemPosition, 1712).
+-define(wxListCtrl_SetItemState, 1713).
+-define(wxListCtrl_SetItemText, 1714).
+-define(wxListCtrl_SetItemTextColour, 1715).
+-define(wxListCtrl_SetSingleStyle, 1716).
+-define(wxListCtrl_SetTextColour, 1717).
+-define(wxListCtrl_SetWindowStyleFlag, 1718).
+-define(wxListCtrl_SortItems, 1719).
+-define(wxListView_ClearColumnImage, 1720).
+-define(wxListView_Focus, 1721).
+-define(wxListView_GetFirstSelected, 1722).
+-define(wxListView_GetFocusedItem, 1723).
+-define(wxListView_GetNextSelected, 1724).
+-define(wxListView_IsSelected, 1725).
+-define(wxListView_Select, 1726).
+-define(wxListView_SetColumnImage, 1727).
+-define(wxListItem_new_0, 1728).
+-define(wxListItem_new_1, 1729).
+-define(wxListItem_Clear, 1730).
+-define(wxListItem_GetAlign, 1731).
+-define(wxListItem_GetBackgroundColour, 1732).
+-define(wxListItem_GetColumn, 1733).
+-define(wxListItem_GetFont, 1734).
+-define(wxListItem_GetId, 1735).
+-define(wxListItem_GetImage, 1736).
+-define(wxListItem_GetMask, 1737).
+-define(wxListItem_GetState, 1738).
+-define(wxListItem_GetText, 1739).
+-define(wxListItem_GetTextColour, 1740).
+-define(wxListItem_GetWidth, 1741).
+-define(wxListItem_SetAlign, 1742).
+-define(wxListItem_SetBackgroundColour, 1743).
+-define(wxListItem_SetColumn, 1744).
+-define(wxListItem_SetFont, 1745).
+-define(wxListItem_SetId, 1746).
+-define(wxListItem_SetImage, 1747).
+-define(wxListItem_SetMask, 1748).
+-define(wxListItem_SetState, 1749).
+-define(wxListItem_SetStateMask, 1750).
+-define(wxListItem_SetText, 1751).
+-define(wxListItem_SetTextColour, 1752).
+-define(wxListItem_SetWidth, 1753).
+-define(wxListItem_destroy, 1754).
+-define(wxListItemAttr_new_0, 1755).
+-define(wxListItemAttr_new_3, 1756).
+-define(wxListItemAttr_GetBackgroundColour, 1757).
+-define(wxListItemAttr_GetFont, 1758).
+-define(wxListItemAttr_GetTextColour, 1759).
+-define(wxListItemAttr_HasBackgroundColour, 1760).
+-define(wxListItemAttr_HasFont, 1761).
+-define(wxListItemAttr_HasTextColour, 1762).
+-define(wxListItemAttr_SetBackgroundColour, 1763).
+-define(wxListItemAttr_SetFont, 1764).
+-define(wxListItemAttr_SetTextColour, 1765).
+-define(wxListItemAttr_destroy, 1766).
+-define(wxImageList_new_0, 1767).
+-define(wxImageList_new_3, 1768).
+-define(wxImageList_Add_2_0, 1769).
+-define(wxImageList_Add_2_1, 1771).
+-define(wxImageList_Add_1, 1772).
+-define(wxImageList_Create, 1773).
+-define(wxImageList_Draw, 1774).
+-define(wxImageList_GetBitmap, 1775).
+-define(wxImageList_GetIcon, 1776).
+-define(wxImageList_GetImageCount, 1777).
+-define(wxImageList_GetSize, 1778).
+-define(wxImageList_Remove, 1780).
+-define(wxImageList_RemoveAll, 1781).
+-define(wxImageList_Replace_3, 1782).
+-define(wxImageList_Replace_2, 1784).
+-define(wxImageList_destroy, 1785).
+-define(wxTextAttr_new_0, 1786).
+-define(wxTextAttr_new_2, 1787).
+-define(wxTextAttr_new_1, 1788).
+-define(wxTextAttr_GetAlignment, 1789).
+-define(wxTextAttr_GetBackgroundColour, 1790).
+-define(wxTextAttr_GetFont, 1791).
+-define(wxTextAttr_GetFontEncoding, 1792).
+-define(wxTextAttr_GetFontFaceName, 1793).
+-define(wxTextAttr_GetFontSize, 1794).
+-define(wxTextAttr_GetFontStyle, 1795).
+-define(wxTextAttr_GetFontUnderlined, 1796).
+-define(wxTextAttr_GetFontWeight, 1797).
+-define(wxTextAttr_GetLeftIndent, 1798).
+-define(wxTextAttr_GetLeftSubIndent, 1799).
+-define(wxTextAttr_GetRightIndent, 1800).
+-define(wxTextAttr_GetTabs, 1801).
+-define(wxTextAttr_GetTextColour, 1802).
+-define(wxTextAttr_HasBackgroundColour, 1803).
+-define(wxTextAttr_HasFont, 1804).
+-define(wxTextAttr_HasTextColour, 1805).
+-define(wxTextAttr_GetFlags, 1806).
+-define(wxTextAttr_IsDefault, 1807).
+-define(wxTextAttr_SetAlignment, 1808).
+-define(wxTextAttr_SetBackgroundColour, 1809).
+-define(wxTextAttr_SetFlags, 1810).
+-define(wxTextAttr_SetFont, 1811).
+-define(wxTextAttr_SetFontEncoding, 1812).
+-define(wxTextAttr_SetFontFaceName, 1813).
+-define(wxTextAttr_SetFontFamily, 1814).
+-define(wxTextAttr_SetFontSize, 1815).
+-define(wxTextAttr_SetFontPointSize, 1816).
+-define(wxTextAttr_SetFontPixelSize, 1817).
+-define(wxTextAttr_SetFontStyle, 1818).
+-define(wxTextAttr_SetFontUnderlined, 1819).
+-define(wxTextAttr_SetFontWeight, 1820).
+-define(wxTextAttr_SetLeftIndent, 1821).
+-define(wxTextAttr_SetRightIndent, 1822).
+-define(wxTextAttr_SetTabs, 1823).
+-define(wxTextAttr_SetTextColour, 1824).
+-define(wxTextAttr_destroy, 1825).
+-define(wxTextCtrl_new_0, 1826).
+-define(wxTextCtrl_new_3, 1827).
+-define(wxTextCtrl_destruct, 1828).
+-define(wxTextCtrl_AppendText, 1829).
+-define(wxTextCtrl_CanCopy, 1830).
+-define(wxTextCtrl_CanCut, 1831).
+-define(wxTextCtrl_CanPaste, 1832).
+-define(wxTextCtrl_CanRedo, 1833).
+-define(wxTextCtrl_CanUndo, 1834).
+-define(wxTextCtrl_Clear, 1835).
+-define(wxTextCtrl_Copy, 1836).
+-define(wxTextCtrl_Create, 1837).
+-define(wxTextCtrl_Cut, 1838).
+-define(wxTextCtrl_DiscardEdits, 1839).
+-define(wxTextCtrl_ChangeValue, 1840).
+-define(wxTextCtrl_EmulateKeyPress, 1841).
+-define(wxTextCtrl_GetDefaultStyle, 1842).
+-define(wxTextCtrl_GetInsertionPoint, 1843).
+-define(wxTextCtrl_GetLastPosition, 1844).
+-define(wxTextCtrl_GetLineLength, 1845).
+-define(wxTextCtrl_GetLineText, 1846).
+-define(wxTextCtrl_GetNumberOfLines, 1847).
+-define(wxTextCtrl_GetRange, 1848).
+-define(wxTextCtrl_GetSelection, 1849).
+-define(wxTextCtrl_GetStringSelection, 1850).
+-define(wxTextCtrl_GetStyle, 1851).
+-define(wxTextCtrl_GetValue, 1852).
+-define(wxTextCtrl_IsEditable, 1853).
+-define(wxTextCtrl_IsModified, 1854).
+-define(wxTextCtrl_IsMultiLine, 1855).
+-define(wxTextCtrl_IsSingleLine, 1856).
+-define(wxTextCtrl_LoadFile, 1857).
+-define(wxTextCtrl_MarkDirty, 1858).
+-define(wxTextCtrl_Paste, 1859).
+-define(wxTextCtrl_PositionToXY, 1860).
+-define(wxTextCtrl_Redo, 1861).
+-define(wxTextCtrl_Remove, 1862).
+-define(wxTextCtrl_Replace, 1863).
+-define(wxTextCtrl_SaveFile, 1864).
+-define(wxTextCtrl_SetDefaultStyle, 1865).
+-define(wxTextCtrl_SetEditable, 1866).
+-define(wxTextCtrl_SetInsertionPoint, 1867).
+-define(wxTextCtrl_SetInsertionPointEnd, 1868).
+-define(wxTextCtrl_SetMaxLength, 1869).
+-define(wxTextCtrl_SetSelection, 1870).
+-define(wxTextCtrl_SetStyle, 1871).
+-define(wxTextCtrl_SetValue, 1872).
+-define(wxTextCtrl_ShowPosition, 1873).
+-define(wxTextCtrl_Undo, 1874).
+-define(wxTextCtrl_WriteText, 1875).
+-define(wxTextCtrl_XYToPosition, 1876).
+-define(wxBookCtrlBase_AddPage, 1877).
+-define(wxBookCtrlBase_InsertPage, 1878).
+-define(wxBookCtrlBase_DeletePage, 1879).
+-define(wxBookCtrlBase_RemovePage, 1880).
+-define(wxBookCtrlBase_DeleteAllPages, 1881).
+-define(wxBookCtrlBase_GetPage, 1882).
+-define(wxBookCtrlBase_GetPageCount, 1883).
+-define(wxBookCtrlBase_GetCurrentPage, 1884).
+-define(wxBookCtrlBase_AdvanceSelection, 1885).
+-define(wxBookCtrlBase_SetSelection, 1886).
+-define(wxBookCtrlBase_GetSelection, 1887).
+-define(wxBookCtrlBase_ChangeSelection, 1888).
+-define(wxBookCtrlBase_HitTest, 1889).
+-define(wxBookCtrlBase_GetPageText, 1890).
+-define(wxBookCtrlBase_SetPageText, 1891).
+-define(wxNotebook_new_0, 1892).
+-define(wxNotebook_new_3, 1893).
+-define(wxNotebook_destruct, 1894).
+-define(wxNotebook_AssignImageList, 1895).
+-define(wxNotebook_Create, 1896).
+-define(wxNotebook_GetImageList, 1897).
+-define(wxNotebook_GetPageImage, 1898).
+-define(wxNotebook_GetRowCount, 1899).
+-define(wxNotebook_GetThemeBackgroundColour, 1900).
+-define(wxNotebook_SetImageList, 1901).
+-define(wxNotebook_SetPadding, 1902).
+-define(wxNotebook_SetPageSize, 1903).
+-define(wxNotebook_SetPageImage, 1904).
+-define(wxChoicebook_new_0, 1905).
+-define(wxChoicebook_new_3, 1906).
+-define(wxChoicebook_AddPage, 1907).
+-define(wxChoicebook_AdvanceSelection, 1908).
+-define(wxChoicebook_AssignImageList, 1909).
+-define(wxChoicebook_Create, 1910).
+-define(wxChoicebook_DeleteAllPages, 1911).
+-define(wxChoicebook_GetCurrentPage, 1912).
+-define(wxChoicebook_GetImageList, 1913).
+-define(wxChoicebook_GetPage, 1914).
+-define(wxChoicebook_GetPageCount, 1915).
+-define(wxChoicebook_GetPageImage, 1916).
+-define(wxChoicebook_GetPageText, 1917).
+-define(wxChoicebook_GetSelection, 1918).
+-define(wxChoicebook_HitTest, 1919).
+-define(wxChoicebook_InsertPage, 1920).
+-define(wxChoicebook_SetImageList, 1921).
+-define(wxChoicebook_SetPageSize, 1922).
+-define(wxChoicebook_SetPageImage, 1923).
+-define(wxChoicebook_SetPageText, 1924).
+-define(wxChoicebook_SetSelection, 1925).
+-define(wxChoicebook_ChangeSelection, 1926).
+-define(wxChoicebook_destroy, 1927).
+-define(wxToolbook_new_0, 1928).
+-define(wxToolbook_new_3, 1929).
+-define(wxToolbook_AddPage, 1930).
+-define(wxToolbook_AdvanceSelection, 1931).
+-define(wxToolbook_AssignImageList, 1932).
+-define(wxToolbook_Create, 1933).
+-define(wxToolbook_DeleteAllPages, 1934).
+-define(wxToolbook_GetCurrentPage, 1935).
+-define(wxToolbook_GetImageList, 1936).
+-define(wxToolbook_GetPage, 1937).
+-define(wxToolbook_GetPageCount, 1938).
+-define(wxToolbook_GetPageImage, 1939).
+-define(wxToolbook_GetPageText, 1940).
+-define(wxToolbook_GetSelection, 1941).
+-define(wxToolbook_HitTest, 1942).
+-define(wxToolbook_InsertPage, 1943).
+-define(wxToolbook_SetImageList, 1944).
+-define(wxToolbook_SetPageSize, 1945).
+-define(wxToolbook_SetPageImage, 1946).
+-define(wxToolbook_SetPageText, 1947).
+-define(wxToolbook_SetSelection, 1948).
+-define(wxToolbook_ChangeSelection, 1949).
+-define(wxToolbook_destroy, 1950).
+-define(wxListbook_new_0, 1951).
+-define(wxListbook_new_3, 1952).
+-define(wxListbook_AddPage, 1953).
+-define(wxListbook_AdvanceSelection, 1954).
+-define(wxListbook_AssignImageList, 1955).
+-define(wxListbook_Create, 1956).
+-define(wxListbook_DeleteAllPages, 1957).
+-define(wxListbook_GetCurrentPage, 1958).
+-define(wxListbook_GetImageList, 1959).
+-define(wxListbook_GetPage, 1960).
+-define(wxListbook_GetPageCount, 1961).
+-define(wxListbook_GetPageImage, 1962).
+-define(wxListbook_GetPageText, 1963).
+-define(wxListbook_GetSelection, 1964).
+-define(wxListbook_HitTest, 1965).
+-define(wxListbook_InsertPage, 1966).
+-define(wxListbook_SetImageList, 1967).
+-define(wxListbook_SetPageSize, 1968).
+-define(wxListbook_SetPageImage, 1969).
+-define(wxListbook_SetPageText, 1970).
+-define(wxListbook_SetSelection, 1971).
+-define(wxListbook_ChangeSelection, 1972).
+-define(wxListbook_destroy, 1973).
+-define(wxTreebook_new_0, 1974).
+-define(wxTreebook_new_3, 1975).
+-define(wxTreebook_destruct, 1976).
+-define(wxTreebook_AddPage, 1977).
+-define(wxTreebook_AdvanceSelection, 1978).
+-define(wxTreebook_AssignImageList, 1979).
+-define(wxTreebook_Create, 1980).
+-define(wxTreebook_DeleteAllPages, 1981).
+-define(wxTreebook_GetCurrentPage, 1982).
+-define(wxTreebook_GetImageList, 1983).
+-define(wxTreebook_GetPage, 1984).
+-define(wxTreebook_GetPageCount, 1985).
+-define(wxTreebook_GetPageImage, 1986).
+-define(wxTreebook_GetPageText, 1987).
+-define(wxTreebook_GetSelection, 1988).
+-define(wxTreebook_ExpandNode, 1989).
+-define(wxTreebook_IsNodeExpanded, 1990).
+-define(wxTreebook_HitTest, 1991).
+-define(wxTreebook_InsertPage, 1992).
+-define(wxTreebook_InsertSubPage, 1993).
+-define(wxTreebook_SetImageList, 1994).
+-define(wxTreebook_SetPageSize, 1995).
+-define(wxTreebook_SetPageImage, 1996).
+-define(wxTreebook_SetPageText, 1997).
+-define(wxTreebook_SetSelection, 1998).
+-define(wxTreebook_ChangeSelection, 1999).
+-define(wxTreeCtrl_new_0, 2000).
+-define(wxTreeCtrl_new_2, 2001).
+-define(wxTreeCtrl_destruct, 2002).
+-define(wxTreeCtrl_AddRoot, 2003).
+-define(wxTreeCtrl_AppendItem, 2004).
+-define(wxTreeCtrl_AssignImageList, 2005).
+-define(wxTreeCtrl_AssignStateImageList, 2006).
+-define(wxTreeCtrl_Collapse, 2007).
+-define(wxTreeCtrl_CollapseAndReset, 2008).
+-define(wxTreeCtrl_Create, 2009).
+-define(wxTreeCtrl_Delete, 2010).
+-define(wxTreeCtrl_DeleteAllItems, 2011).
+-define(wxTreeCtrl_DeleteChildren, 2012).
+-define(wxTreeCtrl_EditLabel, 2013).
+-define(wxTreeCtrl_EnsureVisible, 2014).
+-define(wxTreeCtrl_Expand, 2015).
+-define(wxTreeCtrl_GetBoundingRect, 2016).
+-define(wxTreeCtrl_GetChildrenCount, 2017).
+-define(wxTreeCtrl_GetCount, 2018).
+-define(wxTreeCtrl_GetEditControl, 2019).
+-define(wxTreeCtrl_GetFirstChild, 2020).
+-define(wxTreeCtrl_GetNextChild, 2021).
+-define(wxTreeCtrl_GetFirstVisibleItem, 2022).
+-define(wxTreeCtrl_GetImageList, 2023).
+-define(wxTreeCtrl_GetIndent, 2024).
+-define(wxTreeCtrl_GetItemBackgroundColour, 2025).
+-define(wxTreeCtrl_GetItemData, 2026).
+-define(wxTreeCtrl_GetItemFont, 2027).
+-define(wxTreeCtrl_GetItemImage, 2028).
+-define(wxTreeCtrl_GetItemText, 2029).
+-define(wxTreeCtrl_GetItemTextColour, 2030).
+-define(wxTreeCtrl_GetLastChild, 2031).
+-define(wxTreeCtrl_GetNextSibling, 2032).
+-define(wxTreeCtrl_GetNextVisible, 2033).
+-define(wxTreeCtrl_GetItemParent, 2034).
+-define(wxTreeCtrl_GetPrevSibling, 2035).
+-define(wxTreeCtrl_GetPrevVisible, 2036).
+-define(wxTreeCtrl_GetRootItem, 2037).
+-define(wxTreeCtrl_GetSelection, 2038).
+-define(wxTreeCtrl_GetSelections, 2039).
+-define(wxTreeCtrl_GetStateImageList, 2040).
+-define(wxTreeCtrl_HitTest, 2041).
+-define(wxTreeCtrl_InsertItem, 2042).
+-define(wxTreeCtrl_IsBold, 2044).
+-define(wxTreeCtrl_IsExpanded, 2045).
+-define(wxTreeCtrl_IsSelected, 2046).
+-define(wxTreeCtrl_IsVisible, 2047).
+-define(wxTreeCtrl_ItemHasChildren, 2048).
+-define(wxTreeCtrl_IsTreeItemIdOk, 2049).
+-define(wxTreeCtrl_PrependItem, 2050).
+-define(wxTreeCtrl_ScrollTo, 2051).
+-define(wxTreeCtrl_SelectItem, 2052).
+-define(wxTreeCtrl_SetIndent, 2053).
+-define(wxTreeCtrl_SetImageList, 2054).
+-define(wxTreeCtrl_SetItemBackgroundColour, 2055).
+-define(wxTreeCtrl_SetItemBold, 2056).
+-define(wxTreeCtrl_SetItemData, 2057).
+-define(wxTreeCtrl_SetItemDropHighlight, 2058).
+-define(wxTreeCtrl_SetItemFont, 2059).
+-define(wxTreeCtrl_SetItemHasChildren, 2060).
+-define(wxTreeCtrl_SetItemImage, 2061).
+-define(wxTreeCtrl_SetItemText, 2062).
+-define(wxTreeCtrl_SetItemTextColour, 2063).
+-define(wxTreeCtrl_SetStateImageList, 2064).
+-define(wxTreeCtrl_SetWindowStyle, 2065).
+-define(wxTreeCtrl_SortChildren, 2066).
+-define(wxTreeCtrl_Toggle, 2067).
+-define(wxTreeCtrl_ToggleItemSelection, 2068).
+-define(wxTreeCtrl_Unselect, 2069).
+-define(wxTreeCtrl_UnselectAll, 2070).
+-define(wxTreeCtrl_UnselectItem, 2071).
+-define(wxScrollBar_new_0, 2072).
+-define(wxScrollBar_new_3, 2073).
+-define(wxScrollBar_destruct, 2074).
+-define(wxScrollBar_Create, 2075).
+-define(wxScrollBar_GetRange, 2076).
+-define(wxScrollBar_GetPageSize, 2077).
+-define(wxScrollBar_GetThumbPosition, 2078).
+-define(wxScrollBar_GetThumbSize, 2079).
+-define(wxScrollBar_SetThumbPosition, 2080).
+-define(wxScrollBar_SetScrollbar, 2081).
+-define(wxSpinButton_new_0, 2082).
+-define(wxSpinButton_new_2, 2083).
+-define(wxSpinButton_destruct, 2084).
+-define(wxSpinButton_Create, 2085).
+-define(wxSpinButton_GetMax, 2086).
+-define(wxSpinButton_GetMin, 2087).
+-define(wxSpinButton_GetValue, 2088).
+-define(wxSpinButton_SetRange, 2089).
+-define(wxSpinButton_SetValue, 2090).
+-define(wxSpinCtrl_new_0, 2091).
+-define(wxSpinCtrl_new_2, 2092).
+-define(wxSpinCtrl_Create, 2093).
+-define(wxSpinCtrl_SetValue_1_1, 2094).
+-define(wxSpinCtrl_SetValue_1_0, 2095).
+-define(wxSpinCtrl_GetValue, 2096).
+-define(wxSpinCtrl_SetRange, 2097).
+-define(wxSpinCtrl_SetSelection, 2098).
+-define(wxSpinCtrl_GetMin, 2099).
+-define(wxSpinCtrl_GetMax, 2100).
+-define(wxSpinCtrl_destroy, 2101).
+-define(wxStaticText_new_0, 2102).
+-define(wxStaticText_new_4, 2103).
+-define(wxStaticText_Create, 2104).
+-define(wxStaticText_GetLabel, 2105).
+-define(wxStaticText_SetLabel, 2106).
+-define(wxStaticText_Wrap, 2107).
+-define(wxStaticText_destroy, 2108).
+-define(wxStaticBitmap_new_0, 2109).
+-define(wxStaticBitmap_new_4, 2110).
+-define(wxStaticBitmap_Create, 2111).
+-define(wxStaticBitmap_GetBitmap, 2112).
+-define(wxStaticBitmap_SetBitmap, 2113).
+-define(wxStaticBitmap_destroy, 2114).
+-define(wxRadioBox_new, 2115).
+-define(wxRadioBox_destruct, 2116).
+-define(wxRadioBox_Create, 2117).
+-define(wxRadioBox_Enable_1, 2118).
+-define(wxRadioBox_Enable_2, 2119).
+-define(wxRadioBox_GetSelection, 2120).
+-define(wxRadioBox_GetString, 2121).
+-define(wxRadioBox_SetSelection, 2122).
+-define(wxRadioBox_Show, 2123).
+-define(wxRadioBox_GetColumnCount, 2124).
+-define(wxRadioBox_GetItemHelpText, 2125).
+-define(wxRadioBox_GetItemToolTip, 2126).
+-define(wxRadioBox_GetItemFromPoint, 2127).
+-define(wxRadioBox_GetRowCount, 2128).
+-define(wxRadioBox_IsItemEnabled, 2129).
+-define(wxRadioBox_IsItemShown, 2130).
+-define(wxRadioBox_SetItemHelpText, 2131).
+-define(wxRadioBox_SetItemToolTip, 2132).
+-define(wxRadioButton_new_0, 2133).
+-define(wxRadioButton_new_4, 2134).
+-define(wxRadioButton_destruct, 2135).
+-define(wxRadioButton_Create, 2136).
+-define(wxRadioButton_GetValue, 2137).
+-define(wxRadioButton_SetValue, 2138).
+-define(wxSlider_new_0, 2139).
+-define(wxSlider_new_6, 2140).
+-define(wxSlider_destruct, 2141).
+-define(wxSlider_Create, 2142).
+-define(wxSlider_GetLineSize, 2143).
+-define(wxSlider_GetMax, 2144).
+-define(wxSlider_GetMin, 2145).
+-define(wxSlider_GetPageSize, 2146).
+-define(wxSlider_GetThumbLength, 2147).
+-define(wxSlider_GetValue, 2148).
+-define(wxSlider_SetLineSize, 2149).
+-define(wxSlider_SetPageSize, 2150).
+-define(wxSlider_SetRange, 2151).
+-define(wxSlider_SetThumbLength, 2152).
+-define(wxSlider_SetValue, 2153).
+-define(wxDialog_new_0, 2154).
+-define(wxDialog_new_4, 2155).
+-define(wxDialog_destruct, 2156).
+-define(wxDialog_Create, 2157).
+-define(wxDialog_CreateButtonSizer, 2158).
+-define(wxDialog_CreateStdDialogButtonSizer, 2159).
+-define(wxDialog_EndModal, 2160).
+-define(wxDialog_GetAffirmativeId, 2161).
+-define(wxDialog_GetReturnCode, 2162).
+-define(wxDialog_IsModal, 2163).
+-define(wxDialog_SetAffirmativeId, 2164).
+-define(wxDialog_SetReturnCode, 2165).
+-define(wxDialog_Show, 2166).
+-define(wxDialog_ShowModal, 2167).
+-define(wxColourDialog_new_0, 2168).
+-define(wxColourDialog_new_2, 2169).
+-define(wxColourDialog_destruct, 2170).
+-define(wxColourDialog_Create, 2171).
+-define(wxColourDialog_GetColourData, 2172).
+-define(wxColourData_new, 2173).
+-define(wxColourData_destruct, 2174).
+-define(wxColourData_GetChooseFull, 2175).
+-define(wxColourData_GetColour, 2176).
+-define(wxColourData_GetCustomColour, 2177).
+-define(wxColourData_SetChooseFull, 2178).
+-define(wxColourData_SetColour, 2179).
+-define(wxColourData_SetCustomColour, 2180).
+-define(wxPalette_new_0, 2181).
+-define(wxPalette_new_1, 2182).
+-define(wxPalette_new_4, 2183).
+-define(wxPalette_destruct, 2184).
+-define(wxPalette_Create, 2185).
+-define(wxPalette_GetColoursCount, 2186).
+-define(wxPalette_GetPixel, 2187).
+-define(wxPalette_GetRGB, 2188).
+-define(wxPalette_IsOk, 2189).
+-define(wxDirDialog_new, 2190).
+-define(wxDirDialog_destruct, 2191).
+-define(wxDirDialog_GetPath, 2192).
+-define(wxDirDialog_GetMessage, 2193).
+-define(wxDirDialog_SetMessage, 2194).
+-define(wxDirDialog_SetPath, 2195).
+-define(wxFileDialog_new, 2196).
+-define(wxFileDialog_destruct, 2197).
+-define(wxFileDialog_GetDirectory, 2198).
+-define(wxFileDialog_GetFilename, 2199).
+-define(wxFileDialog_GetFilenames, 2200).
+-define(wxFileDialog_GetFilterIndex, 2201).
+-define(wxFileDialog_GetMessage, 2202).
+-define(wxFileDialog_GetPath, 2203).
+-define(wxFileDialog_GetPaths, 2204).
+-define(wxFileDialog_GetWildcard, 2205).
+-define(wxFileDialog_SetDirectory, 2206).
+-define(wxFileDialog_SetFilename, 2207).
+-define(wxFileDialog_SetFilterIndex, 2208).
+-define(wxFileDialog_SetMessage, 2209).
+-define(wxFileDialog_SetPath, 2210).
+-define(wxFileDialog_SetWildcard, 2211).
+-define(wxPickerBase_SetInternalMargin, 2212).
+-define(wxPickerBase_GetInternalMargin, 2213).
+-define(wxPickerBase_SetTextCtrlProportion, 2214).
+-define(wxPickerBase_SetPickerCtrlProportion, 2215).
+-define(wxPickerBase_GetTextCtrlProportion, 2216).
+-define(wxPickerBase_GetPickerCtrlProportion, 2217).
+-define(wxPickerBase_HasTextCtrl, 2218).
+-define(wxPickerBase_GetTextCtrl, 2219).
+-define(wxPickerBase_IsTextCtrlGrowable, 2220).
+-define(wxPickerBase_SetPickerCtrlGrowable, 2221).
+-define(wxPickerBase_SetTextCtrlGrowable, 2222).
+-define(wxPickerBase_IsPickerCtrlGrowable, 2223).
+-define(wxFilePickerCtrl_new_0, 2224).
+-define(wxFilePickerCtrl_new_3, 2225).
+-define(wxFilePickerCtrl_Create, 2226).
+-define(wxFilePickerCtrl_GetPath, 2227).
+-define(wxFilePickerCtrl_SetPath, 2228).
+-define(wxFilePickerCtrl_destroy, 2229).
+-define(wxDirPickerCtrl_new_0, 2230).
+-define(wxDirPickerCtrl_new_3, 2231).
+-define(wxDirPickerCtrl_Create, 2232).
+-define(wxDirPickerCtrl_GetPath, 2233).
+-define(wxDirPickerCtrl_SetPath, 2234).
+-define(wxDirPickerCtrl_destroy, 2235).
+-define(wxColourPickerCtrl_new_0, 2236).
+-define(wxColourPickerCtrl_new_3, 2237).
+-define(wxColourPickerCtrl_Create, 2238).
+-define(wxColourPickerCtrl_GetColour, 2239).
+-define(wxColourPickerCtrl_SetColour_1_1, 2240).
+-define(wxColourPickerCtrl_SetColour_1_0, 2241).
+-define(wxColourPickerCtrl_destroy, 2242).
+-define(wxDatePickerCtrl_new_0, 2243).
+-define(wxDatePickerCtrl_new_3, 2244).
+-define(wxDatePickerCtrl_GetRange, 2245).
+-define(wxDatePickerCtrl_GetValue, 2246).
+-define(wxDatePickerCtrl_SetRange, 2247).
+-define(wxDatePickerCtrl_SetValue, 2248).
+-define(wxDatePickerCtrl_destroy, 2249).
+-define(wxFontPickerCtrl_new_0, 2250).
+-define(wxFontPickerCtrl_new_3, 2251).
+-define(wxFontPickerCtrl_Create, 2252).
+-define(wxFontPickerCtrl_GetSelectedFont, 2253).
+-define(wxFontPickerCtrl_SetSelectedFont, 2254).
+-define(wxFontPickerCtrl_GetMaxPointSize, 2255).
+-define(wxFontPickerCtrl_SetMaxPointSize, 2256).
+-define(wxFontPickerCtrl_destroy, 2257).
+-define(wxFindReplaceDialog_new_0, 2258).
+-define(wxFindReplaceDialog_new_4, 2259).
+-define(wxFindReplaceDialog_destruct, 2260).
+-define(wxFindReplaceDialog_Create, 2261).
+-define(wxFindReplaceDialog_GetData, 2262).
+-define(wxFindReplaceData_new, 2263).
+-define(wxFindReplaceData_GetFindString, 2264).
+-define(wxFindReplaceData_GetReplaceString, 2265).
+-define(wxFindReplaceData_GetFlags, 2266).
+-define(wxFindReplaceData_SetFlags, 2267).
+-define(wxFindReplaceData_SetFindString, 2268).
+-define(wxFindReplaceData_SetReplaceString, 2269).
+-define(wxFindReplaceData_destroy, 2270).
+-define(wxMultiChoiceDialog_new, 2272).
+-define(wxMultiChoiceDialog_GetSelections, 2273).
+-define(wxMultiChoiceDialog_SetSelections, 2274).
+-define(wxMultiChoiceDialog_destroy, 2275).
+-define(wxSingleChoiceDialog_new, 2277).
+-define(wxSingleChoiceDialog_GetSelection, 2278).
+-define(wxSingleChoiceDialog_GetStringSelection, 2279).
+-define(wxSingleChoiceDialog_SetSelection, 2280).
+-define(wxSingleChoiceDialog_destroy, 2281).
+-define(wxTextEntryDialog_new_0, 2282).
+-define(wxTextEntryDialog_new_3, 2283).
+-define(wxTextEntryDialog_destruct, 2284).
+-define(wxTextEntryDialog_GetValue, 2285).
+-define(wxTextEntryDialog_SetValue, 2286).
+-define(wxPasswordEntryDialog_new, 2287).
+-define(wxPasswordEntryDialog_destroy, 2288).
+-define(wxFontData_new_0, 2289).
+-define(wxFontData_new_1, 2290).
+-define(wxFontData_EnableEffects, 2291).
+-define(wxFontData_GetAllowSymbols, 2292).
+-define(wxFontData_GetColour, 2293).
+-define(wxFontData_GetChosenFont, 2294).
+-define(wxFontData_GetEnableEffects, 2295).
+-define(wxFontData_GetInitialFont, 2296).
+-define(wxFontData_GetShowHelp, 2297).
+-define(wxFontData_SetAllowSymbols, 2298).
+-define(wxFontData_SetChosenFont, 2299).
+-define(wxFontData_SetColour, 2300).
+-define(wxFontData_SetInitialFont, 2301).
+-define(wxFontData_SetRange, 2302).
+-define(wxFontData_SetShowHelp, 2303).
+-define(wxFontData_destroy, 2304).
+-define(wxFontDialog_new_0, 2305).
+-define(wxFontDialog_new_2, 2307).
+-define(wxFontDialog_Create, 2309).
+-define(wxFontDialog_GetFontData, 2310).
+-define(wxFontDialog_destroy, 2312).
+-define(wxProgressDialog_new, 2313).
+-define(wxProgressDialog_Resume, 2314).
+-define(wxProgressDialog_Update, 2315).
+-define(wxProgressDialog_destroy, 2316).
+-define(wxMessageDialog_new, 2317).
+-define(wxMessageDialog_destroy, 2318).
+-define(wxPageSetupDialog_new, 2319).
+-define(wxPageSetupDialog_destruct, 2320).
+-define(wxPageSetupDialog_GetPageSetupData, 2321).
+-define(wxPageSetupDialog_ShowModal, 2322).
+-define(wxPageSetupDialogData_new_0, 2323).
+-define(wxPageSetupDialogData_new_1, 2325).
+-define(wxPageSetupDialogData_destruct, 2326).
+-define(wxPageSetupDialogData_EnableHelp, 2327).
+-define(wxPageSetupDialogData_EnableMargins, 2328).
+-define(wxPageSetupDialogData_EnableOrientation, 2329).
+-define(wxPageSetupDialogData_EnablePaper, 2330).
+-define(wxPageSetupDialogData_EnablePrinter, 2331).
+-define(wxPageSetupDialogData_GetDefaultMinMargins, 2332).
+-define(wxPageSetupDialogData_GetEnableMargins, 2333).
+-define(wxPageSetupDialogData_GetEnableOrientation, 2334).
+-define(wxPageSetupDialogData_GetEnablePaper, 2335).
+-define(wxPageSetupDialogData_GetEnablePrinter, 2336).
+-define(wxPageSetupDialogData_GetEnableHelp, 2337).
+-define(wxPageSetupDialogData_GetDefaultInfo, 2338).
+-define(wxPageSetupDialogData_GetMarginTopLeft, 2339).
+-define(wxPageSetupDialogData_GetMarginBottomRight, 2340).
+-define(wxPageSetupDialogData_GetMinMarginTopLeft, 2341).
+-define(wxPageSetupDialogData_GetMinMarginBottomRight, 2342).
+-define(wxPageSetupDialogData_GetPaperId, 2343).
+-define(wxPageSetupDialogData_GetPaperSize, 2344).
+-define(wxPageSetupDialogData_GetPrintData, 2346).
+-define(wxPageSetupDialogData_IsOk, 2347).
+-define(wxPageSetupDialogData_SetDefaultInfo, 2348).
+-define(wxPageSetupDialogData_SetDefaultMinMargins, 2349).
+-define(wxPageSetupDialogData_SetMarginTopLeft, 2350).
+-define(wxPageSetupDialogData_SetMarginBottomRight, 2351).
+-define(wxPageSetupDialogData_SetMinMarginTopLeft, 2352).
+-define(wxPageSetupDialogData_SetMinMarginBottomRight, 2353).
+-define(wxPageSetupDialogData_SetPaperId, 2354).
+-define(wxPageSetupDialogData_SetPaperSize, 2355).
+-define(wxPageSetupDialogData_SetPrintData, 2356).
+-define(wxPrintDialog_new_2_0, 2357).
+-define(wxPrintDialog_new_2_1, 2358).
+-define(wxPrintDialog_destruct, 2359).
+-define(wxPrintDialog_GetPrintDialogData, 2360).
+-define(wxPrintDialog_GetPrintDC, 2361).
+-define(wxPrintDialogData_new_0, 2362).
+-define(wxPrintDialogData_new_1, 2363).
+-define(wxPrintDialogData_destruct, 2365).
+-define(wxPrintDialogData_EnableHelp, 2366).
+-define(wxPrintDialogData_EnablePageNumbers, 2367).
+-define(wxPrintDialogData_EnablePrintToFile, 2368).
+-define(wxPrintDialogData_EnableSelection, 2369).
+-define(wxPrintDialogData_GetAllPages, 2370).
+-define(wxPrintDialogData_GetCollate, 2371).
+-define(wxPrintDialogData_GetFromPage, 2372).
+-define(wxPrintDialogData_GetMaxPage, 2373).
+-define(wxPrintDialogData_GetMinPage, 2374).
+-define(wxPrintDialogData_GetNoCopies, 2375).
+-define(wxPrintDialogData_GetPrintData, 2376).
+-define(wxPrintDialogData_GetPrintToFile, 2377).
+-define(wxPrintDialogData_GetSelection, 2378).
+-define(wxPrintDialogData_GetToPage, 2379).
+-define(wxPrintDialogData_IsOk, 2380).
+-define(wxPrintDialogData_SetCollate, 2381).
+-define(wxPrintDialogData_SetFromPage, 2382).
+-define(wxPrintDialogData_SetMaxPage, 2383).
+-define(wxPrintDialogData_SetMinPage, 2384).
+-define(wxPrintDialogData_SetNoCopies, 2385).
+-define(wxPrintDialogData_SetPrintData, 2386).
+-define(wxPrintDialogData_SetPrintToFile, 2387).
+-define(wxPrintDialogData_SetSelection, 2388).
+-define(wxPrintDialogData_SetToPage, 2389).
+-define(wxPrintData_new_0, 2390).
+-define(wxPrintData_new_1, 2391).
+-define(wxPrintData_destruct, 2392).
+-define(wxPrintData_GetCollate, 2393).
+-define(wxPrintData_GetBin, 2394).
+-define(wxPrintData_GetColour, 2395).
+-define(wxPrintData_GetDuplex, 2396).
+-define(wxPrintData_GetNoCopies, 2397).
+-define(wxPrintData_GetOrientation, 2398).
+-define(wxPrintData_GetPaperId, 2399).
+-define(wxPrintData_GetPrinterName, 2400).
+-define(wxPrintData_GetQuality, 2401).
+-define(wxPrintData_IsOk, 2402).
+-define(wxPrintData_SetBin, 2403).
+-define(wxPrintData_SetCollate, 2404).
+-define(wxPrintData_SetColour, 2405).
+-define(wxPrintData_SetDuplex, 2406).
+-define(wxPrintData_SetNoCopies, 2407).
+-define(wxPrintData_SetOrientation, 2408).
+-define(wxPrintData_SetPaperId, 2409).
+-define(wxPrintData_SetPrinterName, 2410).
+-define(wxPrintData_SetQuality, 2411).
+-define(wxPrintPreview_new_2, 2412).
+-define(wxPrintPreview_new_3, 2413).
+-define(wxPrintPreview_destruct, 2414).
+-define(wxPrintPreview_GetCanvas, 2415).
+-define(wxPrintPreview_GetCurrentPage, 2416).
+-define(wxPrintPreview_GetFrame, 2417).
+-define(wxPrintPreview_GetMaxPage, 2418).
+-define(wxPrintPreview_GetMinPage, 2419).
+-define(wxPrintPreview_GetPrintout, 2420).
+-define(wxPrintPreview_GetPrintoutForPrinting, 2421).
+-define(wxPrintPreview_IsOk, 2422).
+-define(wxPrintPreview_PaintPage, 2423).
+-define(wxPrintPreview_Print, 2424).
+-define(wxPrintPreview_RenderPage, 2425).
+-define(wxPrintPreview_SetCanvas, 2426).
+-define(wxPrintPreview_SetCurrentPage, 2427).
+-define(wxPrintPreview_SetFrame, 2428).
+-define(wxPrintPreview_SetPrintout, 2429).
+-define(wxPrintPreview_SetZoom, 2430).
+-define(wxPreviewFrame_new, 2431).
+-define(wxPreviewFrame_destruct, 2432).
+-define(wxPreviewFrame_CreateControlBar, 2433).
+-define(wxPreviewFrame_CreateCanvas, 2434).
+-define(wxPreviewFrame_Initialize, 2435).
+-define(wxPreviewFrame_OnCloseWindow, 2436).
+-define(wxPreviewControlBar_new, 2437).
+-define(wxPreviewControlBar_destruct, 2438).
+-define(wxPreviewControlBar_CreateButtons, 2439).
+-define(wxPreviewControlBar_GetPrintPreview, 2440).
+-define(wxPreviewControlBar_GetZoomControl, 2441).
+-define(wxPreviewControlBar_SetZoomControl, 2442).
+-define(wxPrinter_new, 2443).
+-define(wxPrinter_CreateAbortWindow, 2444).
+-define(wxPrinter_GetAbort, 2445).
+-define(wxPrinter_GetLastError, 2446).
+-define(wxPrinter_GetPrintDialogData, 2447).
+-define(wxPrinter_Print, 2448).
+-define(wxPrinter_PrintDialog, 2449).
+-define(wxPrinter_ReportError, 2450).
+-define(wxPrinter_Setup, 2451).
+-define(wxPrinter_destroy, 2452).
+-define(wxXmlResource_new_2, 2453).
+-define(wxXmlResource_new_1, 2454).
+-define(wxXmlResource_destruct, 2455).
+-define(wxXmlResource_AttachUnknownControl, 2456).
+-define(wxXmlResource_ClearHandlers, 2457).
+-define(wxXmlResource_CompareVersion, 2458).
+-define(wxXmlResource_Get, 2459).
+-define(wxXmlResource_GetFlags, 2460).
+-define(wxXmlResource_GetVersion, 2461).
+-define(wxXmlResource_GetXRCID, 2462).
+-define(wxXmlResource_InitAllHandlers, 2463).
+-define(wxXmlResource_Load, 2464).
+-define(wxXmlResource_LoadBitmap, 2465).
+-define(wxXmlResource_LoadDialog_2, 2466).
+-define(wxXmlResource_LoadDialog_3, 2467).
+-define(wxXmlResource_LoadFrame_2, 2468).
+-define(wxXmlResource_LoadFrame_3, 2469).
+-define(wxXmlResource_LoadIcon, 2470).
+-define(wxXmlResource_LoadMenu, 2471).
+-define(wxXmlResource_LoadMenuBar_2, 2472).
+-define(wxXmlResource_LoadMenuBar_1, 2473).
+-define(wxXmlResource_LoadPanel_2, 2474).
+-define(wxXmlResource_LoadPanel_3, 2475).
+-define(wxXmlResource_LoadToolBar, 2476).
+-define(wxXmlResource_Set, 2477).
+-define(wxXmlResource_SetFlags, 2478).
+-define(wxXmlResource_Unload, 2479).
+-define(wxXmlResource_xrcctrl, 2480).
+-define(wxHtmlEasyPrinting_new, 2481).
+-define(wxHtmlEasyPrinting_GetPrintData, 2482).
+-define(wxHtmlEasyPrinting_GetPageSetupData, 2483).
+-define(wxHtmlEasyPrinting_PreviewFile, 2484).
+-define(wxHtmlEasyPrinting_PreviewText, 2485).
+-define(wxHtmlEasyPrinting_PrintFile, 2486).
+-define(wxHtmlEasyPrinting_PrintText, 2487).
+-define(wxHtmlEasyPrinting_PageSetup, 2488).
+-define(wxHtmlEasyPrinting_SetFonts, 2489).
+-define(wxHtmlEasyPrinting_SetHeader, 2490).
+-define(wxHtmlEasyPrinting_SetFooter, 2491).
+-define(wxHtmlEasyPrinting_destroy, 2492).
+-define(wxGLCanvas_new, 2493).
+-define(wxGLCanvas_SetCurrent, 2494).
+-define(wxGLCanvas_SwapBuffers, 2495).
+-define(wxGLCanvas_destroy, 2496).
+-define(wxGLContext_new, 2497).
+-define(wxGLContext_SetCurrent, 2498).
+-define(wxGLContext_destroy, 2499).
+-define(wxAuiManager_new, 2500).
+-define(wxAuiManager_destruct, 2501).
+-define(wxAuiManager_AddPane_2_1, 2502).
+-define(wxAuiManager_AddPane_2_0, 2503).
+-define(wxAuiManager_AddPane_3, 2504).
+-define(wxAuiManager_DetachPane, 2505).
+-define(wxAuiManager_GetAllPanes, 2506).
+-define(wxAuiManager_GetArtProvider, 2507).
+-define(wxAuiManager_GetDockSizeConstraint, 2508).
+-define(wxAuiManager_GetFlags, 2509).
+-define(wxAuiManager_GetManagedWindow, 2510).
+-define(wxAuiManager_GetManager, 2511).
+-define(wxAuiManager_GetPane_1_1, 2512).
+-define(wxAuiManager_GetPane_1_0, 2513).
+-define(wxAuiManager_HideHint, 2514).
+-define(wxAuiManager_InsertPane, 2515).
+-define(wxAuiManager_LoadPaneInfo, 2516).
+-define(wxAuiManager_LoadPerspective, 2517).
+-define(wxAuiManager_SavePaneInfo, 2518).
+-define(wxAuiManager_SavePerspective, 2519).
+-define(wxAuiManager_SetArtProvider, 2520).
+-define(wxAuiManager_SetDockSizeConstraint, 2521).
+-define(wxAuiManager_SetFlags, 2522).
+-define(wxAuiManager_SetManagedWindow, 2523).
+-define(wxAuiManager_ShowHint, 2524).
+-define(wxAuiManager_UnInit, 2525).
+-define(wxAuiManager_Update, 2526).
+-define(wxAuiPaneInfo_new_0, 2527).
+-define(wxAuiPaneInfo_new_1, 2528).
+-define(wxAuiPaneInfo_BestSize_1, 2529).
+-define(wxAuiPaneInfo_BestSize_2, 2530).
+-define(wxAuiPaneInfo_Bottom, 2531).
+-define(wxAuiPaneInfo_BottomDockable, 2532).
+-define(wxAuiPaneInfo_Caption, 2533).
+-define(wxAuiPaneInfo_CaptionVisible, 2534).
+-define(wxAuiPaneInfo_Centre, 2535).
+-define(wxAuiPaneInfo_CentrePane, 2536).
+-define(wxAuiPaneInfo_CloseButton, 2537).
+-define(wxAuiPaneInfo_DefaultPane, 2538).
+-define(wxAuiPaneInfo_DestroyOnClose, 2539).
+-define(wxAuiPaneInfo_Direction, 2540).
+-define(wxAuiPaneInfo_Dock, 2541).
+-define(wxAuiPaneInfo_Dockable, 2542).
+-define(wxAuiPaneInfo_Fixed, 2543).
+-define(wxAuiPaneInfo_Float, 2544).
+-define(wxAuiPaneInfo_Floatable, 2545).
+-define(wxAuiPaneInfo_FloatingPosition_1, 2546).
+-define(wxAuiPaneInfo_FloatingPosition_2, 2547).
+-define(wxAuiPaneInfo_FloatingSize_1, 2548).
+-define(wxAuiPaneInfo_FloatingSize_2, 2549).
+-define(wxAuiPaneInfo_Gripper, 2550).
+-define(wxAuiPaneInfo_GripperTop, 2551).
+-define(wxAuiPaneInfo_HasBorder, 2552).
+-define(wxAuiPaneInfo_HasCaption, 2553).
+-define(wxAuiPaneInfo_HasCloseButton, 2554).
+-define(wxAuiPaneInfo_HasFlag, 2555).
+-define(wxAuiPaneInfo_HasGripper, 2556).
+-define(wxAuiPaneInfo_HasGripperTop, 2557).
+-define(wxAuiPaneInfo_HasMaximizeButton, 2558).
+-define(wxAuiPaneInfo_HasMinimizeButton, 2559).
+-define(wxAuiPaneInfo_HasPinButton, 2560).
+-define(wxAuiPaneInfo_Hide, 2561).
+-define(wxAuiPaneInfo_IsBottomDockable, 2562).
+-define(wxAuiPaneInfo_IsDocked, 2563).
+-define(wxAuiPaneInfo_IsFixed, 2564).
+-define(wxAuiPaneInfo_IsFloatable, 2565).
+-define(wxAuiPaneInfo_IsFloating, 2566).
+-define(wxAuiPaneInfo_IsLeftDockable, 2567).
+-define(wxAuiPaneInfo_IsMovable, 2568).
+-define(wxAuiPaneInfo_IsOk, 2569).
+-define(wxAuiPaneInfo_IsResizable, 2570).
+-define(wxAuiPaneInfo_IsRightDockable, 2571).
+-define(wxAuiPaneInfo_IsShown, 2572).
+-define(wxAuiPaneInfo_IsToolbar, 2573).
+-define(wxAuiPaneInfo_IsTopDockable, 2574).
+-define(wxAuiPaneInfo_Layer, 2575).
+-define(wxAuiPaneInfo_Left, 2576).
+-define(wxAuiPaneInfo_LeftDockable, 2577).
+-define(wxAuiPaneInfo_MaxSize_1, 2578).
+-define(wxAuiPaneInfo_MaxSize_2, 2579).
+-define(wxAuiPaneInfo_MaximizeButton, 2580).
+-define(wxAuiPaneInfo_MinSize_1, 2581).
+-define(wxAuiPaneInfo_MinSize_2, 2582).
+-define(wxAuiPaneInfo_MinimizeButton, 2583).
+-define(wxAuiPaneInfo_Movable, 2584).
+-define(wxAuiPaneInfo_Name, 2585).
+-define(wxAuiPaneInfo_PaneBorder, 2586).
+-define(wxAuiPaneInfo_PinButton, 2587).
+-define(wxAuiPaneInfo_Position, 2588).
+-define(wxAuiPaneInfo_Resizable, 2589).
+-define(wxAuiPaneInfo_Right, 2590).
+-define(wxAuiPaneInfo_RightDockable, 2591).
+-define(wxAuiPaneInfo_Row, 2592).
+-define(wxAuiPaneInfo_SafeSet, 2593).
+-define(wxAuiPaneInfo_SetFlag, 2594).
+-define(wxAuiPaneInfo_Show, 2595).
+-define(wxAuiPaneInfo_ToolbarPane, 2596).
+-define(wxAuiPaneInfo_Top, 2597).
+-define(wxAuiPaneInfo_TopDockable, 2598).
+-define(wxAuiPaneInfo_Window, 2599).
+-define(wxAuiPaneInfo_GetWindow, 2600).
+-define(wxAuiPaneInfo_GetFrame, 2601).
+-define(wxAuiPaneInfo_GetDirection, 2602).
+-define(wxAuiPaneInfo_GetLayer, 2603).
+-define(wxAuiPaneInfo_GetRow, 2604).
+-define(wxAuiPaneInfo_GetPosition, 2605).
+-define(wxAuiPaneInfo_GetFloatingPosition, 2606).
+-define(wxAuiPaneInfo_GetFloatingSize, 2607).
+-define(wxAuiPaneInfo_destroy, 2608).
+-define(wxAuiNotebook_new_0, 2609).
+-define(wxAuiNotebook_new_2, 2610).
+-define(wxAuiNotebook_AddPage_3, 2611).
+-define(wxAuiNotebook_AddPage_4, 2612).
+-define(wxAuiNotebook_Create_2, 2613).
+-define(wxAuiNotebook_Create_3, 2614).
+-define(wxAuiNotebook_DeletePage, 2615).
+-define(wxAuiNotebook_GetArtProvider, 2616).
+-define(wxAuiNotebook_GetPage, 2617).
+-define(wxAuiNotebook_GetPageBitmap, 2618).
+-define(wxAuiNotebook_GetPageCount, 2619).
+-define(wxAuiNotebook_GetPageIndex, 2620).
+-define(wxAuiNotebook_GetPageText, 2621).
+-define(wxAuiNotebook_GetSelection, 2622).
+-define(wxAuiNotebook_InsertPage_4, 2623).
+-define(wxAuiNotebook_InsertPage_5, 2624).
+-define(wxAuiNotebook_RemovePage, 2625).
+-define(wxAuiNotebook_SetArtProvider, 2626).
+-define(wxAuiNotebook_SetFont, 2627).
+-define(wxAuiNotebook_SetPageBitmap, 2628).
+-define(wxAuiNotebook_SetPageText, 2629).
+-define(wxAuiNotebook_SetSelection, 2630).
+-define(wxAuiNotebook_SetTabCtrlHeight, 2631).
+-define(wxAuiNotebook_SetUniformBitmapSize, 2632).
+-define(wxAuiNotebook_destroy, 2633).
+-define(wxAuiTabArt_SetFlags, 2634).
+-define(wxAuiTabArt_SetMeasuringFont, 2635).
+-define(wxAuiTabArt_SetNormalFont, 2636).
+-define(wxAuiTabArt_SetSelectedFont, 2637).
+-define(wxAuiTabArt_SetColour, 2638).
+-define(wxAuiTabArt_SetActiveColour, 2639).
+-define(wxAuiDockArt_GetColour, 2640).
+-define(wxAuiDockArt_GetFont, 2641).
+-define(wxAuiDockArt_GetMetric, 2642).
+-define(wxAuiDockArt_SetColour, 2643).
+-define(wxAuiDockArt_SetFont, 2644).
+-define(wxAuiDockArt_SetMetric, 2645).
+-define(wxAuiSimpleTabArt_new, 2646).
+-define(wxAuiSimpleTabArt_destroy, 2647).
+-define(wxMDIParentFrame_new_0, 2648).
+-define(wxMDIParentFrame_new_4, 2649).
+-define(wxMDIParentFrame_destruct, 2650).
+-define(wxMDIParentFrame_ActivateNext, 2651).
+-define(wxMDIParentFrame_ActivatePrevious, 2652).
+-define(wxMDIParentFrame_ArrangeIcons, 2653).
+-define(wxMDIParentFrame_Cascade, 2654).
+-define(wxMDIParentFrame_Create, 2655).
+-define(wxMDIParentFrame_GetActiveChild, 2656).
+-define(wxMDIParentFrame_GetClientWindow, 2657).
+-define(wxMDIParentFrame_Tile, 2658).
+-define(wxMDIChildFrame_new_0, 2659).
+-define(wxMDIChildFrame_new_4, 2660).
+-define(wxMDIChildFrame_destruct, 2661).
+-define(wxMDIChildFrame_Activate, 2662).
+-define(wxMDIChildFrame_Create, 2663).
+-define(wxMDIChildFrame_Maximize, 2664).
+-define(wxMDIChildFrame_Restore, 2665).
+-define(wxMDIClientWindow_new, 2666).
+-define(wxMDIClientWindow_CreateClient, 2667).
+-define(wxMDIClientWindow_destroy, 2668).
+-define(wxLayoutAlgorithm_new, 2669).
+-define(wxLayoutAlgorithm_destruct, 2670).
+-define(wxLayoutAlgorithm_LayoutFrame, 2671).
+-define(wxLayoutAlgorithm_LayoutMDIFrame, 2672).
+-define(wxLayoutAlgorithm_LayoutWindow, 2673).
+-define(wxEvent_GetId, 2674).
+-define(wxEvent_GetSkipped, 2675).
+-define(wxEvent_GetTimestamp, 2676).
+-define(wxEvent_IsCommandEvent, 2677).
+-define(wxEvent_ResumePropagation, 2678).
+-define(wxEvent_ShouldPropagate, 2679).
+-define(wxEvent_Skip, 2680).
+-define(wxEvent_StopPropagation, 2681).
+-define(wxCommandEvent_getClientData, 2682).
+-define(wxCommandEvent_GetExtraLong, 2683).
+-define(wxCommandEvent_GetInt, 2684).
+-define(wxCommandEvent_GetSelection, 2685).
+-define(wxCommandEvent_GetString, 2686).
+-define(wxCommandEvent_IsChecked, 2687).
+-define(wxCommandEvent_IsSelection, 2688).
+-define(wxCommandEvent_SetInt, 2689).
+-define(wxCommandEvent_SetString, 2690).
+-define(wxScrollEvent_GetOrientation, 2691).
+-define(wxScrollEvent_GetPosition, 2692).
+-define(wxScrollWinEvent_GetOrientation, 2693).
+-define(wxScrollWinEvent_GetPosition, 2694).
+-define(wxMouseEvent_AltDown, 2695).
+-define(wxMouseEvent_Button, 2696).
+-define(wxMouseEvent_ButtonDClick, 2697).
+-define(wxMouseEvent_ButtonDown, 2698).
+-define(wxMouseEvent_ButtonUp, 2699).
+-define(wxMouseEvent_CmdDown, 2700).
+-define(wxMouseEvent_ControlDown, 2701).
+-define(wxMouseEvent_Dragging, 2702).
+-define(wxMouseEvent_Entering, 2703).
+-define(wxMouseEvent_GetButton, 2704).
+-define(wxMouseEvent_GetPosition, 2705).
+-define(wxMouseEvent_GetLogicalPosition, 2707).
+-define(wxMouseEvent_GetLinesPerAction, 2708).
+-define(wxMouseEvent_GetWheelRotation, 2709).
+-define(wxMouseEvent_GetWheelDelta, 2710).
+-define(wxMouseEvent_GetX, 2711).
+-define(wxMouseEvent_GetY, 2712).
+-define(wxMouseEvent_IsButton, 2713).
+-define(wxMouseEvent_IsPageScroll, 2714).
+-define(wxMouseEvent_Leaving, 2715).
+-define(wxMouseEvent_LeftDClick, 2716).
+-define(wxMouseEvent_LeftDown, 2717).
+-define(wxMouseEvent_LeftIsDown, 2718).
+-define(wxMouseEvent_LeftUp, 2719).
+-define(wxMouseEvent_MetaDown, 2720).
+-define(wxMouseEvent_MiddleDClick, 2721).
+-define(wxMouseEvent_MiddleDown, 2722).
+-define(wxMouseEvent_MiddleIsDown, 2723).
+-define(wxMouseEvent_MiddleUp, 2724).
+-define(wxMouseEvent_Moving, 2725).
+-define(wxMouseEvent_RightDClick, 2726).
+-define(wxMouseEvent_RightDown, 2727).
+-define(wxMouseEvent_RightIsDown, 2728).
+-define(wxMouseEvent_RightUp, 2729).
+-define(wxMouseEvent_ShiftDown, 2730).
+-define(wxMouseEvent_GetWheelAxis, 2731).
+-define(wxMouseEvent_Aux1DClick, 2732).
+-define(wxMouseEvent_Aux1Down, 2733).
+-define(wxMouseEvent_Aux1Up, 2734).
+-define(wxMouseEvent_Aux2DClick, 2735).
+-define(wxMouseEvent_Aux2Down, 2736).
+-define(wxMouseEvent_Aux2Up, 2737).
+-define(wxSetCursorEvent_GetCursor, 2738).
+-define(wxSetCursorEvent_GetX, 2739).
+-define(wxSetCursorEvent_GetY, 2740).
+-define(wxSetCursorEvent_HasCursor, 2741).
+-define(wxSetCursorEvent_SetCursor, 2742).
+-define(wxKeyEvent_AltDown, 2743).
+-define(wxKeyEvent_CmdDown, 2744).
+-define(wxKeyEvent_ControlDown, 2745).
+-define(wxKeyEvent_GetKeyCode, 2746).
+-define(wxKeyEvent_GetModifiers, 2747).
+-define(wxKeyEvent_GetPosition, 2748).
+-define(wxKeyEvent_GetRawKeyCode, 2750).
+-define(wxKeyEvent_GetRawKeyFlags, 2751).
+-define(wxKeyEvent_GetUnicodeKey, 2752).
+-define(wxKeyEvent_GetX, 2753).
+-define(wxKeyEvent_GetY, 2754).
+-define(wxKeyEvent_HasModifiers, 2755).
+-define(wxKeyEvent_MetaDown, 2756).
+-define(wxKeyEvent_ShiftDown, 2757).
+-define(wxSizeEvent_GetSize, 2758).
+-define(wxSizeEvent_GetRect, 2759).
+-define(wxMoveEvent_GetPosition, 2760).
+-define(wxMoveEvent_GetRect, 2761).
+-define(wxEraseEvent_GetDC, 2762).
+-define(wxFocusEvent_GetWindow, 2763).
+-define(wxChildFocusEvent_GetWindow, 2764).
+-define(wxMenuEvent_GetMenu, 2765).
+-define(wxMenuEvent_GetMenuId, 2766).
+-define(wxMenuEvent_IsPopup, 2767).
+-define(wxCloseEvent_CanVeto, 2768).
+-define(wxCloseEvent_GetLoggingOff, 2769).
+-define(wxCloseEvent_SetCanVeto, 2770).
+-define(wxCloseEvent_SetLoggingOff, 2771).
+-define(wxCloseEvent_Veto, 2772).
+-define(wxShowEvent_SetShow, 2773).
+-define(wxShowEvent_IsShown, 2774).
+-define(wxIconizeEvent_IsIconized, 2775).
+-define(wxJoystickEvent_ButtonDown, 2776).
+-define(wxJoystickEvent_ButtonIsDown, 2777).
+-define(wxJoystickEvent_ButtonUp, 2778).
+-define(wxJoystickEvent_GetButtonChange, 2779).
+-define(wxJoystickEvent_GetButtonState, 2780).
+-define(wxJoystickEvent_GetJoystick, 2781).
+-define(wxJoystickEvent_GetPosition, 2782).
+-define(wxJoystickEvent_GetZPosition, 2783).
+-define(wxJoystickEvent_IsButton, 2784).
+-define(wxJoystickEvent_IsMove, 2785).
+-define(wxJoystickEvent_IsZMove, 2786).
+-define(wxUpdateUIEvent_CanUpdate, 2787).
+-define(wxUpdateUIEvent_Check, 2788).
+-define(wxUpdateUIEvent_Enable, 2789).
+-define(wxUpdateUIEvent_Show, 2790).
+-define(wxUpdateUIEvent_GetChecked, 2791).
+-define(wxUpdateUIEvent_GetEnabled, 2792).
+-define(wxUpdateUIEvent_GetShown, 2793).
+-define(wxUpdateUIEvent_GetSetChecked, 2794).
+-define(wxUpdateUIEvent_GetSetEnabled, 2795).
+-define(wxUpdateUIEvent_GetSetShown, 2796).
+-define(wxUpdateUIEvent_GetSetText, 2797).
+-define(wxUpdateUIEvent_GetText, 2798).
+-define(wxUpdateUIEvent_GetMode, 2799).
+-define(wxUpdateUIEvent_GetUpdateInterval, 2800).
+-define(wxUpdateUIEvent_ResetUpdateTime, 2801).
+-define(wxUpdateUIEvent_SetMode, 2802).
+-define(wxUpdateUIEvent_SetText, 2803).
+-define(wxUpdateUIEvent_SetUpdateInterval, 2804).
+-define(wxMouseCaptureChangedEvent_GetCapturedWindow, 2805).
+-define(wxPaletteChangedEvent_SetChangedWindow, 2806).
+-define(wxPaletteChangedEvent_GetChangedWindow, 2807).
+-define(wxQueryNewPaletteEvent_SetPaletteRealized, 2808).
+-define(wxQueryNewPaletteEvent_GetPaletteRealized, 2809).
+-define(wxNavigationKeyEvent_GetDirection, 2810).
+-define(wxNavigationKeyEvent_SetDirection, 2811).
+-define(wxNavigationKeyEvent_IsWindowChange, 2812).
+-define(wxNavigationKeyEvent_SetWindowChange, 2813).
+-define(wxNavigationKeyEvent_IsFromTab, 2814).
+-define(wxNavigationKeyEvent_SetFromTab, 2815).
+-define(wxNavigationKeyEvent_GetCurrentFocus, 2816).
+-define(wxNavigationKeyEvent_SetCurrentFocus, 2817).
+-define(wxHelpEvent_GetOrigin, 2818).
+-define(wxHelpEvent_GetPosition, 2819).
+-define(wxHelpEvent_SetOrigin, 2820).
+-define(wxHelpEvent_SetPosition, 2821).
+-define(wxContextMenuEvent_GetPosition, 2822).
+-define(wxContextMenuEvent_SetPosition, 2823).
+-define(wxIdleEvent_GetMode, 2824).
+-define(wxIdleEvent_RequestMore, 2825).
+-define(wxIdleEvent_MoreRequested, 2826).
+-define(wxIdleEvent_SetMode, 2827).
+-define(wxGridEvent_AltDown, 2828).
+-define(wxGridEvent_ControlDown, 2829).
+-define(wxGridEvent_GetCol, 2830).
+-define(wxGridEvent_GetPosition, 2831).
+-define(wxGridEvent_GetRow, 2832).
+-define(wxGridEvent_MetaDown, 2833).
+-define(wxGridEvent_Selecting, 2834).
+-define(wxGridEvent_ShiftDown, 2835).
+-define(wxNotifyEvent_Allow, 2836).
+-define(wxNotifyEvent_IsAllowed, 2837).
+-define(wxNotifyEvent_Veto, 2838).
+-define(wxSashEvent_GetEdge, 2839).
+-define(wxSashEvent_GetDragRect, 2840).
+-define(wxSashEvent_GetDragStatus, 2841).
+-define(wxListEvent_GetCacheFrom, 2842).
+-define(wxListEvent_GetCacheTo, 2843).
+-define(wxListEvent_GetKeyCode, 2844).
+-define(wxListEvent_GetIndex, 2845).
+-define(wxListEvent_GetColumn, 2846).
+-define(wxListEvent_GetPoint, 2847).
+-define(wxListEvent_GetLabel, 2848).
+-define(wxListEvent_GetText, 2849).
+-define(wxListEvent_GetImage, 2850).
+-define(wxListEvent_GetData, 2851).
+-define(wxListEvent_GetMask, 2852).
+-define(wxListEvent_GetItem, 2853).
+-define(wxListEvent_IsEditCancelled, 2854).
+-define(wxDateEvent_GetDate, 2855).
+-define(wxCalendarEvent_GetWeekDay, 2856).
+-define(wxCalendarEvent_GetDate, 2857).
+-define(wxFileDirPickerEvent_GetPath, 2858).
+-define(wxColourPickerEvent_GetColour, 2859).
+-define(wxFontPickerEvent_GetFont, 2860).
+-define(wxStyledTextEvent_GetPosition, 2861).
+-define(wxStyledTextEvent_GetKey, 2862).
+-define(wxStyledTextEvent_GetModifiers, 2863).
+-define(wxStyledTextEvent_GetModificationType, 2864).
+-define(wxStyledTextEvent_GetText, 2865).
+-define(wxStyledTextEvent_GetLength, 2866).
+-define(wxStyledTextEvent_GetLinesAdded, 2867).
+-define(wxStyledTextEvent_GetLine, 2868).
+-define(wxStyledTextEvent_GetFoldLevelNow, 2869).
+-define(wxStyledTextEvent_GetFoldLevelPrev, 2870).
+-define(wxStyledTextEvent_GetMargin, 2871).
+-define(wxStyledTextEvent_GetMessage, 2872).
+-define(wxStyledTextEvent_GetWParam, 2873).
+-define(wxStyledTextEvent_GetLParam, 2874).
+-define(wxStyledTextEvent_GetListType, 2875).
+-define(wxStyledTextEvent_GetX, 2876).
+-define(wxStyledTextEvent_GetY, 2877).
+-define(wxStyledTextEvent_GetDragText, 2878).
+-define(wxStyledTextEvent_GetDragAllowMove, 2879).
+-define(wxStyledTextEvent_GetDragResult, 2880).
+-define(wxStyledTextEvent_GetShift, 2881).
+-define(wxStyledTextEvent_GetControl, 2882).
+-define(wxStyledTextEvent_GetAlt, 2883).
+-define(utils_wxGetKeyState, 2884).
+-define(utils_wxGetMousePosition, 2885).
+-define(utils_wxGetMouseState, 2886).
+-define(utils_wxSetDetectableAutoRepeat, 2887).
+-define(utils_wxBell, 2888).
+-define(utils_wxFindMenuItemId, 2889).
+-define(utils_wxFindWindowAtPoint, 2890).
+-define(utils_wxBeginBusyCursor, 2891).
+-define(utils_wxEndBusyCursor, 2892).
+-define(utils_wxIsBusy, 2893).
+-define(utils_wxShutdown, 2894).
+-define(utils_wxShell, 2895).
+-define(utils_wxLaunchDefaultBrowser, 2896).
+-define(utils_wxGetEmailAddress, 2897).
+-define(utils_wxGetUserId, 2898).
+-define(utils_wxGetHomeDir, 2899).
+-define(utils_wxNewId, 2900).
+-define(utils_wxRegisterId, 2901).
+-define(utils_wxGetCurrentId, 2902).
+-define(utils_wxGetOsDescription, 2903).
+-define(utils_wxIsPlatformLittleEndian, 2904).
+-define(utils_wxIsPlatform64Bit, 2905).
+-define(gdicmn_wxDisplaySize, 2906).
+-define(gdicmn_wxSetCursor, 2907).
+-define(wxPrintout_new, 2908).
+-define(wxPrintout_destruct, 2909).
+-define(wxPrintout_GetDC, 2910).
+-define(wxPrintout_GetPageSizeMM, 2911).
+-define(wxPrintout_GetPageSizePixels, 2912).
+-define(wxPrintout_GetPaperRectPixels, 2913).
+-define(wxPrintout_GetPPIPrinter, 2914).
+-define(wxPrintout_GetPPIScreen, 2915).
+-define(wxPrintout_GetTitle, 2916).
+-define(wxPrintout_IsPreview, 2917).
+-define(wxPrintout_FitThisSizeToPaper, 2918).
+-define(wxPrintout_FitThisSizeToPage, 2919).
+-define(wxPrintout_FitThisSizeToPageMargins, 2920).
+-define(wxPrintout_MapScreenSizeToPaper, 2921).
+-define(wxPrintout_MapScreenSizeToPage, 2922).
+-define(wxPrintout_MapScreenSizeToPageMargins, 2923).
+-define(wxPrintout_MapScreenSizeToDevice, 2924).
+-define(wxPrintout_GetLogicalPaperRect, 2925).
+-define(wxPrintout_GetLogicalPageRect, 2926).
+-define(wxPrintout_GetLogicalPageMarginsRect, 2927).
+-define(wxPrintout_SetLogicalOrigin, 2928).
+-define(wxPrintout_OffsetLogicalOrigin, 2929).
+-define(wxStyledTextCtrl_new_2, 2930).
+-define(wxStyledTextCtrl_new_0, 2931).
+-define(wxStyledTextCtrl_destruct, 2932).
+-define(wxStyledTextCtrl_Create, 2933).
+-define(wxStyledTextCtrl_AddText, 2934).
+-define(wxStyledTextCtrl_InsertText, 2935).
+-define(wxStyledTextCtrl_ClearAll, 2936).
+-define(wxStyledTextCtrl_ClearDocumentStyle, 2937).
+-define(wxStyledTextCtrl_GetLength, 2938).
+-define(wxStyledTextCtrl_GetCharAt, 2939).
+-define(wxStyledTextCtrl_GetCurrentPos, 2940).
+-define(wxStyledTextCtrl_GetAnchor, 2941).
+-define(wxStyledTextCtrl_GetStyleAt, 2942).
+-define(wxStyledTextCtrl_Redo, 2943).
+-define(wxStyledTextCtrl_SetUndoCollection, 2944).
+-define(wxStyledTextCtrl_SelectAll, 2945).
+-define(wxStyledTextCtrl_SetSavePoint, 2946).
+-define(wxStyledTextCtrl_CanRedo, 2947).
+-define(wxStyledTextCtrl_MarkerLineFromHandle, 2948).
+-define(wxStyledTextCtrl_MarkerDeleteHandle, 2949).
+-define(wxStyledTextCtrl_GetUndoCollection, 2950).
+-define(wxStyledTextCtrl_GetViewWhiteSpace, 2951).
+-define(wxStyledTextCtrl_SetViewWhiteSpace, 2952).
+-define(wxStyledTextCtrl_PositionFromPoint, 2953).
+-define(wxStyledTextCtrl_PositionFromPointClose, 2954).
+-define(wxStyledTextCtrl_GotoLine, 2955).
+-define(wxStyledTextCtrl_GotoPos, 2956).
+-define(wxStyledTextCtrl_SetAnchor, 2957).
+-define(wxStyledTextCtrl_GetCurLine, 2958).
+-define(wxStyledTextCtrl_GetEndStyled, 2959).
+-define(wxStyledTextCtrl_ConvertEOLs, 2960).
+-define(wxStyledTextCtrl_GetEOLMode, 2961).
+-define(wxStyledTextCtrl_SetEOLMode, 2962).
+-define(wxStyledTextCtrl_StartStyling, 2963).
+-define(wxStyledTextCtrl_SetStyling, 2964).
+-define(wxStyledTextCtrl_GetBufferedDraw, 2965).
+-define(wxStyledTextCtrl_SetBufferedDraw, 2966).
+-define(wxStyledTextCtrl_SetTabWidth, 2967).
+-define(wxStyledTextCtrl_GetTabWidth, 2968).
+-define(wxStyledTextCtrl_SetCodePage, 2969).
+-define(wxStyledTextCtrl_MarkerDefine, 2970).
+-define(wxStyledTextCtrl_MarkerSetForeground, 2971).
+-define(wxStyledTextCtrl_MarkerSetBackground, 2972).
+-define(wxStyledTextCtrl_MarkerAdd, 2973).
+-define(wxStyledTextCtrl_MarkerDelete, 2974).
+-define(wxStyledTextCtrl_MarkerDeleteAll, 2975).
+-define(wxStyledTextCtrl_MarkerGet, 2976).
+-define(wxStyledTextCtrl_MarkerNext, 2977).
+-define(wxStyledTextCtrl_MarkerPrevious, 2978).
+-define(wxStyledTextCtrl_MarkerDefineBitmap, 2979).
+-define(wxStyledTextCtrl_MarkerAddSet, 2980).
+-define(wxStyledTextCtrl_MarkerSetAlpha, 2981).
+-define(wxStyledTextCtrl_SetMarginType, 2982).
+-define(wxStyledTextCtrl_GetMarginType, 2983).
+-define(wxStyledTextCtrl_SetMarginWidth, 2984).
+-define(wxStyledTextCtrl_GetMarginWidth, 2985).
+-define(wxStyledTextCtrl_SetMarginMask, 2986).
+-define(wxStyledTextCtrl_GetMarginMask, 2987).
+-define(wxStyledTextCtrl_SetMarginSensitive, 2988).
+-define(wxStyledTextCtrl_GetMarginSensitive, 2989).
+-define(wxStyledTextCtrl_StyleClearAll, 2990).
+-define(wxStyledTextCtrl_StyleSetForeground, 2991).
+-define(wxStyledTextCtrl_StyleSetBackground, 2992).
+-define(wxStyledTextCtrl_StyleSetBold, 2993).
+-define(wxStyledTextCtrl_StyleSetItalic, 2994).
+-define(wxStyledTextCtrl_StyleSetSize, 2995).
+-define(wxStyledTextCtrl_StyleSetFaceName, 2996).
+-define(wxStyledTextCtrl_StyleSetEOLFilled, 2997).
+-define(wxStyledTextCtrl_StyleResetDefault, 2998).
+-define(wxStyledTextCtrl_StyleSetUnderline, 2999).
+-define(wxStyledTextCtrl_StyleSetCase, 3000).
+-define(wxStyledTextCtrl_StyleSetHotSpot, 3001).
+-define(wxStyledTextCtrl_SetSelForeground, 3002).
+-define(wxStyledTextCtrl_SetSelBackground, 3003).
+-define(wxStyledTextCtrl_GetSelAlpha, 3004).
+-define(wxStyledTextCtrl_SetSelAlpha, 3005).
+-define(wxStyledTextCtrl_SetCaretForeground, 3006).
+-define(wxStyledTextCtrl_CmdKeyAssign, 3007).
+-define(wxStyledTextCtrl_CmdKeyClear, 3008).
+-define(wxStyledTextCtrl_CmdKeyClearAll, 3009).
+-define(wxStyledTextCtrl_SetStyleBytes, 3010).
+-define(wxStyledTextCtrl_StyleSetVisible, 3011).
+-define(wxStyledTextCtrl_GetCaretPeriod, 3012).
+-define(wxStyledTextCtrl_SetCaretPeriod, 3013).
+-define(wxStyledTextCtrl_SetWordChars, 3014).
+-define(wxStyledTextCtrl_BeginUndoAction, 3015).
+-define(wxStyledTextCtrl_EndUndoAction, 3016).
+-define(wxStyledTextCtrl_IndicatorSetStyle, 3017).
+-define(wxStyledTextCtrl_IndicatorGetStyle, 3018).
+-define(wxStyledTextCtrl_IndicatorSetForeground, 3019).
+-define(wxStyledTextCtrl_IndicatorGetForeground, 3020).
+-define(wxStyledTextCtrl_SetWhitespaceForeground, 3021).
+-define(wxStyledTextCtrl_SetWhitespaceBackground, 3022).
+-define(wxStyledTextCtrl_GetStyleBits, 3023).
+-define(wxStyledTextCtrl_SetLineState, 3024).
+-define(wxStyledTextCtrl_GetLineState, 3025).
+-define(wxStyledTextCtrl_GetMaxLineState, 3026).
+-define(wxStyledTextCtrl_GetCaretLineVisible, 3027).
+-define(wxStyledTextCtrl_SetCaretLineVisible, 3028).
+-define(wxStyledTextCtrl_GetCaretLineBackground, 3029).
+-define(wxStyledTextCtrl_SetCaretLineBackground, 3030).
+-define(wxStyledTextCtrl_AutoCompShow, 3031).
+-define(wxStyledTextCtrl_AutoCompCancel, 3032).
+-define(wxStyledTextCtrl_AutoCompActive, 3033).
+-define(wxStyledTextCtrl_AutoCompPosStart, 3034).
+-define(wxStyledTextCtrl_AutoCompComplete, 3035).
+-define(wxStyledTextCtrl_AutoCompStops, 3036).
+-define(wxStyledTextCtrl_AutoCompSetSeparator, 3037).
+-define(wxStyledTextCtrl_AutoCompGetSeparator, 3038).
+-define(wxStyledTextCtrl_AutoCompSelect, 3039).
+-define(wxStyledTextCtrl_AutoCompSetCancelAtStart, 3040).
+-define(wxStyledTextCtrl_AutoCompGetCancelAtStart, 3041).
+-define(wxStyledTextCtrl_AutoCompSetFillUps, 3042).
+-define(wxStyledTextCtrl_AutoCompSetChooseSingle, 3043).
+-define(wxStyledTextCtrl_AutoCompGetChooseSingle, 3044).
+-define(wxStyledTextCtrl_AutoCompSetIgnoreCase, 3045).
+-define(wxStyledTextCtrl_AutoCompGetIgnoreCase, 3046).
+-define(wxStyledTextCtrl_UserListShow, 3047).
+-define(wxStyledTextCtrl_AutoCompSetAutoHide, 3048).
+-define(wxStyledTextCtrl_AutoCompGetAutoHide, 3049).
+-define(wxStyledTextCtrl_AutoCompSetDropRestOfWord, 3050).
+-define(wxStyledTextCtrl_AutoCompGetDropRestOfWord, 3051).
+-define(wxStyledTextCtrl_RegisterImage, 3052).
+-define(wxStyledTextCtrl_ClearRegisteredImages, 3053).
+-define(wxStyledTextCtrl_AutoCompGetTypeSeparator, 3054).
+-define(wxStyledTextCtrl_AutoCompSetTypeSeparator, 3055).
+-define(wxStyledTextCtrl_AutoCompSetMaxWidth, 3056).
+-define(wxStyledTextCtrl_AutoCompGetMaxWidth, 3057).
+-define(wxStyledTextCtrl_AutoCompSetMaxHeight, 3058).
+-define(wxStyledTextCtrl_AutoCompGetMaxHeight, 3059).
+-define(wxStyledTextCtrl_SetIndent, 3060).
+-define(wxStyledTextCtrl_GetIndent, 3061).
+-define(wxStyledTextCtrl_SetUseTabs, 3062).
+-define(wxStyledTextCtrl_GetUseTabs, 3063).
+-define(wxStyledTextCtrl_SetLineIndentation, 3064).
+-define(wxStyledTextCtrl_GetLineIndentation, 3065).
+-define(wxStyledTextCtrl_GetLineIndentPosition, 3066).
+-define(wxStyledTextCtrl_GetColumn, 3067).
+-define(wxStyledTextCtrl_SetUseHorizontalScrollBar, 3068).
+-define(wxStyledTextCtrl_GetUseHorizontalScrollBar, 3069).
+-define(wxStyledTextCtrl_SetIndentationGuides, 3070).
+-define(wxStyledTextCtrl_GetIndentationGuides, 3071).
+-define(wxStyledTextCtrl_SetHighlightGuide, 3072).
+-define(wxStyledTextCtrl_GetHighlightGuide, 3073).
+-define(wxStyledTextCtrl_GetLineEndPosition, 3074).
+-define(wxStyledTextCtrl_GetCodePage, 3075).
+-define(wxStyledTextCtrl_GetCaretForeground, 3076).
+-define(wxStyledTextCtrl_GetReadOnly, 3077).
+-define(wxStyledTextCtrl_SetCurrentPos, 3078).
+-define(wxStyledTextCtrl_SetSelectionStart, 3079).
+-define(wxStyledTextCtrl_GetSelectionStart, 3080).
+-define(wxStyledTextCtrl_SetSelectionEnd, 3081).
+-define(wxStyledTextCtrl_GetSelectionEnd, 3082).
+-define(wxStyledTextCtrl_SetPrintMagnification, 3083).
+-define(wxStyledTextCtrl_GetPrintMagnification, 3084).
+-define(wxStyledTextCtrl_SetPrintColourMode, 3085).
+-define(wxStyledTextCtrl_GetPrintColourMode, 3086).
+-define(wxStyledTextCtrl_FindText, 3087).
+-define(wxStyledTextCtrl_FormatRange, 3088).
+-define(wxStyledTextCtrl_GetFirstVisibleLine, 3089).
+-define(wxStyledTextCtrl_GetLine, 3090).
+-define(wxStyledTextCtrl_GetLineCount, 3091).
+-define(wxStyledTextCtrl_SetMarginLeft, 3092).
+-define(wxStyledTextCtrl_GetMarginLeft, 3093).
+-define(wxStyledTextCtrl_SetMarginRight, 3094).
+-define(wxStyledTextCtrl_GetMarginRight, 3095).
+-define(wxStyledTextCtrl_GetModify, 3096).
+-define(wxStyledTextCtrl_SetSelection, 3097).
+-define(wxStyledTextCtrl_GetSelectedText, 3098).
+-define(wxStyledTextCtrl_GetTextRange, 3099).
+-define(wxStyledTextCtrl_HideSelection, 3100).
+-define(wxStyledTextCtrl_LineFromPosition, 3101).
+-define(wxStyledTextCtrl_PositionFromLine, 3102).
+-define(wxStyledTextCtrl_LineScroll, 3103).
+-define(wxStyledTextCtrl_EnsureCaretVisible, 3104).
+-define(wxStyledTextCtrl_ReplaceSelection, 3105).
+-define(wxStyledTextCtrl_SetReadOnly, 3106).
+-define(wxStyledTextCtrl_CanPaste, 3107).
+-define(wxStyledTextCtrl_CanUndo, 3108).
+-define(wxStyledTextCtrl_EmptyUndoBuffer, 3109).
+-define(wxStyledTextCtrl_Undo, 3110).
+-define(wxStyledTextCtrl_Cut, 3111).
+-define(wxStyledTextCtrl_Copy, 3112).
+-define(wxStyledTextCtrl_Paste, 3113).
+-define(wxStyledTextCtrl_Clear, 3114).
+-define(wxStyledTextCtrl_SetText, 3115).
+-define(wxStyledTextCtrl_GetText, 3116).
+-define(wxStyledTextCtrl_GetTextLength, 3117).
+-define(wxStyledTextCtrl_GetOvertype, 3118).
+-define(wxStyledTextCtrl_SetCaretWidth, 3119).
+-define(wxStyledTextCtrl_GetCaretWidth, 3120).
+-define(wxStyledTextCtrl_SetTargetStart, 3121).
+-define(wxStyledTextCtrl_GetTargetStart, 3122).
+-define(wxStyledTextCtrl_SetTargetEnd, 3123).
+-define(wxStyledTextCtrl_GetTargetEnd, 3124).
+-define(wxStyledTextCtrl_ReplaceTarget, 3125).
+-define(wxStyledTextCtrl_SearchInTarget, 3126).
+-define(wxStyledTextCtrl_SetSearchFlags, 3127).
+-define(wxStyledTextCtrl_GetSearchFlags, 3128).
+-define(wxStyledTextCtrl_CallTipShow, 3129).
+-define(wxStyledTextCtrl_CallTipCancel, 3130).
+-define(wxStyledTextCtrl_CallTipActive, 3131).
+-define(wxStyledTextCtrl_CallTipPosAtStart, 3132).
+-define(wxStyledTextCtrl_CallTipSetHighlight, 3133).
+-define(wxStyledTextCtrl_CallTipSetBackground, 3134).
+-define(wxStyledTextCtrl_CallTipSetForeground, 3135).
+-define(wxStyledTextCtrl_CallTipSetForegroundHighlight, 3136).
+-define(wxStyledTextCtrl_CallTipUseStyle, 3137).
+-define(wxStyledTextCtrl_VisibleFromDocLine, 3138).
+-define(wxStyledTextCtrl_DocLineFromVisible, 3139).
+-define(wxStyledTextCtrl_WrapCount, 3140).
+-define(wxStyledTextCtrl_SetFoldLevel, 3141).
+-define(wxStyledTextCtrl_GetFoldLevel, 3142).
+-define(wxStyledTextCtrl_GetLastChild, 3143).
+-define(wxStyledTextCtrl_GetFoldParent, 3144).
+-define(wxStyledTextCtrl_ShowLines, 3145).
+-define(wxStyledTextCtrl_HideLines, 3146).
+-define(wxStyledTextCtrl_GetLineVisible, 3147).
+-define(wxStyledTextCtrl_SetFoldExpanded, 3148).
+-define(wxStyledTextCtrl_GetFoldExpanded, 3149).
+-define(wxStyledTextCtrl_ToggleFold, 3150).
+-define(wxStyledTextCtrl_EnsureVisible, 3151).
+-define(wxStyledTextCtrl_SetFoldFlags, 3152).
+-define(wxStyledTextCtrl_EnsureVisibleEnforcePolicy, 3153).
+-define(wxStyledTextCtrl_SetTabIndents, 3154).
+-define(wxStyledTextCtrl_GetTabIndents, 3155).
+-define(wxStyledTextCtrl_SetBackSpaceUnIndents, 3156).
+-define(wxStyledTextCtrl_GetBackSpaceUnIndents, 3157).
+-define(wxStyledTextCtrl_SetMouseDwellTime, 3158).
+-define(wxStyledTextCtrl_GetMouseDwellTime, 3159).
+-define(wxStyledTextCtrl_WordStartPosition, 3160).
+-define(wxStyledTextCtrl_WordEndPosition, 3161).
+-define(wxStyledTextCtrl_SetWrapMode, 3162).
+-define(wxStyledTextCtrl_GetWrapMode, 3163).
+-define(wxStyledTextCtrl_SetWrapVisualFlags, 3164).
+-define(wxStyledTextCtrl_GetWrapVisualFlags, 3165).
+-define(wxStyledTextCtrl_SetWrapVisualFlagsLocation, 3166).
+-define(wxStyledTextCtrl_GetWrapVisualFlagsLocation, 3167).
+-define(wxStyledTextCtrl_SetWrapStartIndent, 3168).
+-define(wxStyledTextCtrl_GetWrapStartIndent, 3169).
+-define(wxStyledTextCtrl_SetLayoutCache, 3170).
+-define(wxStyledTextCtrl_GetLayoutCache, 3171).
+-define(wxStyledTextCtrl_SetScrollWidth, 3172).
+-define(wxStyledTextCtrl_GetScrollWidth, 3173).
+-define(wxStyledTextCtrl_TextWidth, 3174).
+-define(wxStyledTextCtrl_GetEndAtLastLine, 3175).
+-define(wxStyledTextCtrl_TextHeight, 3176).
+-define(wxStyledTextCtrl_SetUseVerticalScrollBar, 3177).
+-define(wxStyledTextCtrl_GetUseVerticalScrollBar, 3178).
+-define(wxStyledTextCtrl_AppendText, 3179).
+-define(wxStyledTextCtrl_GetTwoPhaseDraw, 3180).
+-define(wxStyledTextCtrl_SetTwoPhaseDraw, 3181).
+-define(wxStyledTextCtrl_TargetFromSelection, 3182).
+-define(wxStyledTextCtrl_LinesJoin, 3183).
+-define(wxStyledTextCtrl_LinesSplit, 3184).
+-define(wxStyledTextCtrl_SetFoldMarginColour, 3185).
+-define(wxStyledTextCtrl_SetFoldMarginHiColour, 3186).
+-define(wxStyledTextCtrl_LineDown, 3187).
+-define(wxStyledTextCtrl_LineDownExtend, 3188).
+-define(wxStyledTextCtrl_LineUp, 3189).
+-define(wxStyledTextCtrl_LineUpExtend, 3190).
+-define(wxStyledTextCtrl_CharLeft, 3191).
+-define(wxStyledTextCtrl_CharLeftExtend, 3192).
+-define(wxStyledTextCtrl_CharRight, 3193).
+-define(wxStyledTextCtrl_CharRightExtend, 3194).
+-define(wxStyledTextCtrl_WordLeft, 3195).
+-define(wxStyledTextCtrl_WordLeftExtend, 3196).
+-define(wxStyledTextCtrl_WordRight, 3197).
+-define(wxStyledTextCtrl_WordRightExtend, 3198).
+-define(wxStyledTextCtrl_Home, 3199).
+-define(wxStyledTextCtrl_HomeExtend, 3200).
+-define(wxStyledTextCtrl_LineEnd, 3201).
+-define(wxStyledTextCtrl_LineEndExtend, 3202).
+-define(wxStyledTextCtrl_DocumentStart, 3203).
+-define(wxStyledTextCtrl_DocumentStartExtend, 3204).
+-define(wxStyledTextCtrl_DocumentEnd, 3205).
+-define(wxStyledTextCtrl_DocumentEndExtend, 3206).
+-define(wxStyledTextCtrl_PageUp, 3207).
+-define(wxStyledTextCtrl_PageUpExtend, 3208).
+-define(wxStyledTextCtrl_PageDown, 3209).
+-define(wxStyledTextCtrl_PageDownExtend, 3210).
+-define(wxStyledTextCtrl_EditToggleOvertype, 3211).
+-define(wxStyledTextCtrl_Cancel, 3212).
+-define(wxStyledTextCtrl_DeleteBack, 3213).
+-define(wxStyledTextCtrl_Tab, 3214).
+-define(wxStyledTextCtrl_BackTab, 3215).
+-define(wxStyledTextCtrl_NewLine, 3216).
+-define(wxStyledTextCtrl_FormFeed, 3217).
+-define(wxStyledTextCtrl_VCHome, 3218).
+-define(wxStyledTextCtrl_VCHomeExtend, 3219).
+-define(wxStyledTextCtrl_ZoomIn, 3220).
+-define(wxStyledTextCtrl_ZoomOut, 3221).
+-define(wxStyledTextCtrl_DelWordLeft, 3222).
+-define(wxStyledTextCtrl_DelWordRight, 3223).
+-define(wxStyledTextCtrl_LineCut, 3224).
+-define(wxStyledTextCtrl_LineDelete, 3225).
+-define(wxStyledTextCtrl_LineTranspose, 3226).
+-define(wxStyledTextCtrl_LineDuplicate, 3227).
+-define(wxStyledTextCtrl_LowerCase, 3228).
+-define(wxStyledTextCtrl_UpperCase, 3229).
+-define(wxStyledTextCtrl_LineScrollDown, 3230).
+-define(wxStyledTextCtrl_LineScrollUp, 3231).
+-define(wxStyledTextCtrl_DeleteBackNotLine, 3232).
+-define(wxStyledTextCtrl_HomeDisplay, 3233).
+-define(wxStyledTextCtrl_HomeDisplayExtend, 3234).
+-define(wxStyledTextCtrl_LineEndDisplay, 3235).
+-define(wxStyledTextCtrl_LineEndDisplayExtend, 3236).
+-define(wxStyledTextCtrl_HomeWrapExtend, 3237).
+-define(wxStyledTextCtrl_LineEndWrap, 3238).
+-define(wxStyledTextCtrl_LineEndWrapExtend, 3239).
+-define(wxStyledTextCtrl_VCHomeWrap, 3240).
+-define(wxStyledTextCtrl_VCHomeWrapExtend, 3241).
+-define(wxStyledTextCtrl_LineCopy, 3242).
+-define(wxStyledTextCtrl_MoveCaretInsideView, 3243).
+-define(wxStyledTextCtrl_LineLength, 3244).
+-define(wxStyledTextCtrl_BraceHighlight, 3245).
+-define(wxStyledTextCtrl_BraceBadLight, 3246).
+-define(wxStyledTextCtrl_BraceMatch, 3247).
+-define(wxStyledTextCtrl_GetViewEOL, 3248).
+-define(wxStyledTextCtrl_SetViewEOL, 3249).
+-define(wxStyledTextCtrl_SetModEventMask, 3250).
+-define(wxStyledTextCtrl_GetEdgeColumn, 3251).
+-define(wxStyledTextCtrl_SetEdgeColumn, 3252).
+-define(wxStyledTextCtrl_SetEdgeMode, 3253).
+-define(wxStyledTextCtrl_GetEdgeMode, 3254).
+-define(wxStyledTextCtrl_GetEdgeColour, 3255).
+-define(wxStyledTextCtrl_SetEdgeColour, 3256).
+-define(wxStyledTextCtrl_SearchAnchor, 3257).
+-define(wxStyledTextCtrl_SearchNext, 3258).
+-define(wxStyledTextCtrl_SearchPrev, 3259).
+-define(wxStyledTextCtrl_LinesOnScreen, 3260).
+-define(wxStyledTextCtrl_UsePopUp, 3261).
+-define(wxStyledTextCtrl_SelectionIsRectangle, 3262).
+-define(wxStyledTextCtrl_SetZoom, 3263).
+-define(wxStyledTextCtrl_GetZoom, 3264).
+-define(wxStyledTextCtrl_GetModEventMask, 3265).
+-define(wxStyledTextCtrl_SetSTCFocus, 3266).
+-define(wxStyledTextCtrl_GetSTCFocus, 3267).
+-define(wxStyledTextCtrl_SetStatus, 3268).
+-define(wxStyledTextCtrl_GetStatus, 3269).
+-define(wxStyledTextCtrl_SetMouseDownCaptures, 3270).
+-define(wxStyledTextCtrl_GetMouseDownCaptures, 3271).
+-define(wxStyledTextCtrl_SetSTCCursor, 3272).
+-define(wxStyledTextCtrl_GetSTCCursor, 3273).
+-define(wxStyledTextCtrl_SetControlCharSymbol, 3274).
+-define(wxStyledTextCtrl_GetControlCharSymbol, 3275).
+-define(wxStyledTextCtrl_WordPartLeft, 3276).
+-define(wxStyledTextCtrl_WordPartLeftExtend, 3277).
+-define(wxStyledTextCtrl_WordPartRight, 3278).
+-define(wxStyledTextCtrl_WordPartRightExtend, 3279).
+-define(wxStyledTextCtrl_SetVisiblePolicy, 3280).
+-define(wxStyledTextCtrl_DelLineLeft, 3281).
+-define(wxStyledTextCtrl_DelLineRight, 3282).
+-define(wxStyledTextCtrl_GetXOffset, 3283).
+-define(wxStyledTextCtrl_ChooseCaretX, 3284).
+-define(wxStyledTextCtrl_SetXCaretPolicy, 3285).
+-define(wxStyledTextCtrl_SetYCaretPolicy, 3286).
+-define(wxStyledTextCtrl_GetPrintWrapMode, 3287).
+-define(wxStyledTextCtrl_SetHotspotActiveForeground, 3288).
+-define(wxStyledTextCtrl_SetHotspotActiveBackground, 3289).
+-define(wxStyledTextCtrl_SetHotspotActiveUnderline, 3290).
+-define(wxStyledTextCtrl_SetHotspotSingleLine, 3291).
+-define(wxStyledTextCtrl_ParaDownExtend, 3292).
+-define(wxStyledTextCtrl_ParaUp, 3293).
+-define(wxStyledTextCtrl_ParaUpExtend, 3294).
+-define(wxStyledTextCtrl_PositionBefore, 3295).
+-define(wxStyledTextCtrl_PositionAfter, 3296).
+-define(wxStyledTextCtrl_CopyRange, 3297).
+-define(wxStyledTextCtrl_CopyText, 3298).
+-define(wxStyledTextCtrl_SetSelectionMode, 3299).
+-define(wxStyledTextCtrl_GetSelectionMode, 3300).
+-define(wxStyledTextCtrl_LineDownRectExtend, 3301).
+-define(wxStyledTextCtrl_LineUpRectExtend, 3302).
+-define(wxStyledTextCtrl_CharLeftRectExtend, 3303).
+-define(wxStyledTextCtrl_CharRightRectExtend, 3304).
+-define(wxStyledTextCtrl_HomeRectExtend, 3305).
+-define(wxStyledTextCtrl_VCHomeRectExtend, 3306).
+-define(wxStyledTextCtrl_LineEndRectExtend, 3307).
+-define(wxStyledTextCtrl_PageUpRectExtend, 3308).
+-define(wxStyledTextCtrl_PageDownRectExtend, 3309).
+-define(wxStyledTextCtrl_StutteredPageUp, 3310).
+-define(wxStyledTextCtrl_StutteredPageUpExtend, 3311).
+-define(wxStyledTextCtrl_StutteredPageDown, 3312).
+-define(wxStyledTextCtrl_StutteredPageDownExtend, 3313).
+-define(wxStyledTextCtrl_WordLeftEnd, 3314).
+-define(wxStyledTextCtrl_WordLeftEndExtend, 3315).
+-define(wxStyledTextCtrl_WordRightEnd, 3316).
+-define(wxStyledTextCtrl_WordRightEndExtend, 3317).
+-define(wxStyledTextCtrl_SetWhitespaceChars, 3318).
+-define(wxStyledTextCtrl_SetCharsDefault, 3319).
+-define(wxStyledTextCtrl_AutoCompGetCurrent, 3320).
+-define(wxStyledTextCtrl_Allocate, 3321).
+-define(wxStyledTextCtrl_FindColumn, 3322).
+-define(wxStyledTextCtrl_GetCaretSticky, 3323).
+-define(wxStyledTextCtrl_SetCaretSticky, 3324).
+-define(wxStyledTextCtrl_ToggleCaretSticky, 3325).
+-define(wxStyledTextCtrl_SetPasteConvertEndings, 3326).
+-define(wxStyledTextCtrl_GetPasteConvertEndings, 3327).
+-define(wxStyledTextCtrl_SelectionDuplicate, 3328).
+-define(wxStyledTextCtrl_SetCaretLineBackAlpha, 3329).
+-define(wxStyledTextCtrl_GetCaretLineBackAlpha, 3330).
+-define(wxStyledTextCtrl_StartRecord, 3331).
+-define(wxStyledTextCtrl_StopRecord, 3332).
+-define(wxStyledTextCtrl_SetLexer, 3333).
+-define(wxStyledTextCtrl_GetLexer, 3334).
+-define(wxStyledTextCtrl_Colourise, 3335).
+-define(wxStyledTextCtrl_SetProperty, 3336).
+-define(wxStyledTextCtrl_SetKeyWords, 3337).
+-define(wxStyledTextCtrl_SetLexerLanguage, 3338).
+-define(wxStyledTextCtrl_GetProperty, 3339).
+-define(wxStyledTextCtrl_GetStyleBitsNeeded, 3340).
+-define(wxStyledTextCtrl_GetCurrentLine, 3341).
+-define(wxStyledTextCtrl_StyleSetSpec, 3342).
+-define(wxStyledTextCtrl_StyleSetFont, 3343).
+-define(wxStyledTextCtrl_StyleSetFontAttr, 3344).
+-define(wxStyledTextCtrl_StyleSetCharacterSet, 3345).
+-define(wxStyledTextCtrl_StyleSetFontEncoding, 3346).
+-define(wxStyledTextCtrl_CmdKeyExecute, 3347).
+-define(wxStyledTextCtrl_SetMargins, 3348).
+-define(wxStyledTextCtrl_GetSelection, 3349).
+-define(wxStyledTextCtrl_PointFromPosition, 3350).
+-define(wxStyledTextCtrl_ScrollToLine, 3351).
+-define(wxStyledTextCtrl_ScrollToColumn, 3352).
+-define(wxStyledTextCtrl_SetVScrollBar, 3353).
+-define(wxStyledTextCtrl_SetHScrollBar, 3354).
+-define(wxStyledTextCtrl_GetLastKeydownProcessed, 3355).
+-define(wxStyledTextCtrl_SetLastKeydownProcessed, 3356).
+-define(wxStyledTextCtrl_SaveFile, 3357).
+-define(wxStyledTextCtrl_LoadFile, 3358).
+-define(wxStyledTextCtrl_DoDragOver, 3359).
+-define(wxStyledTextCtrl_DoDropText, 3360).
+-define(wxStyledTextCtrl_GetUseAntiAliasing, 3361).
+-define(wxStyledTextCtrl_AddTextRaw, 3362).
+-define(wxStyledTextCtrl_InsertTextRaw, 3363).
+-define(wxStyledTextCtrl_GetCurLineRaw, 3364).
+-define(wxStyledTextCtrl_GetLineRaw, 3365).
+-define(wxStyledTextCtrl_GetSelectedTextRaw, 3366).
+-define(wxStyledTextCtrl_GetTextRangeRaw, 3367).
+-define(wxStyledTextCtrl_SetTextRaw, 3368).
+-define(wxStyledTextCtrl_GetTextRaw, 3369).
+-define(wxStyledTextCtrl_AppendTextRaw, 3370).
+-define(wxArtProvider_GetBitmap, 3371).
+-define(wxArtProvider_GetIcon, 3372).
+-define(wxTreeEvent_GetKeyCode, 3373).
+-define(wxTreeEvent_GetItem, 3374).
+-define(wxTreeEvent_GetKeyEvent, 3375).
+-define(wxTreeEvent_GetLabel, 3376).
+-define(wxTreeEvent_GetOldItem, 3377).
+-define(wxTreeEvent_GetPoint, 3378).
+-define(wxTreeEvent_IsEditCancelled, 3379).
+-define(wxTreeEvent_SetToolTip, 3380).
+-define(wxBookCtrlEvent_GetOldSelection, 3381).
+-define(wxBookCtrlEvent_GetSelection, 3382).
+-define(wxBookCtrlEvent_SetOldSelection, 3383).
+-define(wxBookCtrlEvent_SetSelection, 3384).
+-define(wxFileDataObject_new, 3385).
+-define(wxFileDataObject_AddFile, 3386).
+-define(wxFileDataObject_GetFilenames, 3387).
+-define(wxFileDataObject_destroy, 3388).
+-define(wxTextDataObject_new, 3389).
+-define(wxTextDataObject_GetTextLength, 3390).
+-define(wxTextDataObject_GetText, 3391).
+-define(wxTextDataObject_SetText, 3392).
+-define(wxTextDataObject_destroy, 3393).
+-define(wxBitmapDataObject_new_1_1, 3394).
+-define(wxBitmapDataObject_new_1_0, 3395).
+-define(wxBitmapDataObject_GetBitmap, 3396).
+-define(wxBitmapDataObject_SetBitmap, 3397).
+-define(wxBitmapDataObject_destroy, 3398).
+-define(wxClipboard_new, 3399).
+-define(wxClipboard_destruct, 3400).
+-define(wxClipboard_AddData, 3401).
+-define(wxClipboard_Clear, 3402).
+-define(wxClipboard_Close, 3403).
+-define(wxClipboard_Flush, 3404).
+-define(wxClipboard_GetData, 3405).
+-define(wxClipboard_IsOpened, 3406).
+-define(wxClipboard_Open, 3407).
+-define(wxClipboard_SetData, 3408).
+-define(wxClipboard_UsePrimarySelection, 3409).
+-define(wxClipboard_IsSupported, 3410).
+-define(wxClipboard_Get, 3411).
+-define(wxSpinEvent_GetPosition, 3412).
+-define(wxSpinEvent_SetPosition, 3413).
+-define(wxSplitterWindow_new_0, 3414).
+-define(wxSplitterWindow_new_2, 3415).
+-define(wxSplitterWindow_destruct, 3416).
+-define(wxSplitterWindow_Create, 3417).
+-define(wxSplitterWindow_GetMinimumPaneSize, 3418).
+-define(wxSplitterWindow_GetSashGravity, 3419).
+-define(wxSplitterWindow_GetSashPosition, 3420).
+-define(wxSplitterWindow_GetSplitMode, 3421).
+-define(wxSplitterWindow_GetWindow1, 3422).
+-define(wxSplitterWindow_GetWindow2, 3423).
+-define(wxSplitterWindow_Initialize, 3424).
+-define(wxSplitterWindow_IsSplit, 3425).
+-define(wxSplitterWindow_ReplaceWindow, 3426).
+-define(wxSplitterWindow_SetSashGravity, 3427).
+-define(wxSplitterWindow_SetSashPosition, 3428).
+-define(wxSplitterWindow_SetMinimumPaneSize, 3429).
+-define(wxSplitterWindow_SetSplitMode, 3430).
+-define(wxSplitterWindow_SplitHorizontally, 3431).
+-define(wxSplitterWindow_SplitVertically, 3432).
+-define(wxSplitterWindow_Unsplit, 3433).
+-define(wxSplitterWindow_UpdateSize, 3434).
+-define(wxSplitterEvent_GetSashPosition, 3435).
+-define(wxSplitterEvent_GetX, 3436).
+-define(wxSplitterEvent_GetY, 3437).
+-define(wxSplitterEvent_GetWindowBeingRemoved, 3438).
+-define(wxSplitterEvent_SetSashPosition, 3439).
+-define(wxHtmlWindow_new_0, 3440).
+-define(wxHtmlWindow_new_2, 3441).
+-define(wxHtmlWindow_AppendToPage, 3442).
+-define(wxHtmlWindow_GetOpenedAnchor, 3443).
+-define(wxHtmlWindow_GetOpenedPage, 3444).
+-define(wxHtmlWindow_GetOpenedPageTitle, 3445).
+-define(wxHtmlWindow_GetRelatedFrame, 3446).
+-define(wxHtmlWindow_HistoryBack, 3447).
+-define(wxHtmlWindow_HistoryCanBack, 3448).
+-define(wxHtmlWindow_HistoryCanForward, 3449).
+-define(wxHtmlWindow_HistoryClear, 3450).
+-define(wxHtmlWindow_HistoryForward, 3451).
+-define(wxHtmlWindow_LoadFile, 3452).
+-define(wxHtmlWindow_LoadPage, 3453).
+-define(wxHtmlWindow_SelectAll, 3454).
+-define(wxHtmlWindow_SelectionToText, 3455).
+-define(wxHtmlWindow_SelectLine, 3456).
+-define(wxHtmlWindow_SelectWord, 3457).
+-define(wxHtmlWindow_SetBorders, 3458).
+-define(wxHtmlWindow_SetFonts, 3459).
+-define(wxHtmlWindow_SetPage, 3460).
+-define(wxHtmlWindow_SetRelatedFrame, 3461).
+-define(wxHtmlWindow_SetRelatedStatusBar_1, 3462).
+-define(wxHtmlWindow_SetRelatedStatusBar_2, 3463).
+-define(wxHtmlWindow_ToText, 3464).
+-define(wxHtmlWindow_destroy, 3465).
+-define(wxHtmlLinkEvent_GetLinkInfo, 3466).
+-define(wxSystemSettings_GetColour, 3467).
+-define(wxSystemSettings_GetFont, 3468).
+-define(wxSystemSettings_GetMetric, 3469).
+-define(wxSystemSettings_GetScreenType, 3470).
+-define(wxSystemOptions_GetOption, 3471).
+-define(wxSystemOptions_GetOptionInt, 3472).
+-define(wxSystemOptions_HasOption, 3473).
+-define(wxSystemOptions_IsFalse, 3474).
+-define(wxSystemOptions_SetOption_2_1, 3475).
+-define(wxSystemOptions_SetOption_2_0, 3476).
+-define(wxAuiNotebookEvent_SetSelection, 3477).
+-define(wxAuiNotebookEvent_GetSelection, 3478).
+-define(wxAuiNotebookEvent_SetOldSelection, 3479).
+-define(wxAuiNotebookEvent_GetOldSelection, 3480).
+-define(wxAuiNotebookEvent_SetDragSource, 3481).
+-define(wxAuiNotebookEvent_GetDragSource, 3482).
+-define(wxAuiManagerEvent_SetManager, 3483).
+-define(wxAuiManagerEvent_GetManager, 3484).
+-define(wxAuiManagerEvent_SetPane, 3485).
+-define(wxAuiManagerEvent_GetPane, 3486).
+-define(wxAuiManagerEvent_SetButton, 3487).
+-define(wxAuiManagerEvent_GetButton, 3488).
+-define(wxAuiManagerEvent_SetDC, 3489).
+-define(wxAuiManagerEvent_GetDC, 3490).
+-define(wxAuiManagerEvent_Veto, 3491).
+-define(wxAuiManagerEvent_GetVeto, 3492).
+-define(wxAuiManagerEvent_SetCanVeto, 3493).
+-define(wxAuiManagerEvent_CanVeto, 3494).
+-define(wxLogNull_new, 3495).
+-define(wxLogNull_destruct, 3496).
+-define(wxTaskBarIcon_new, 3497).
+-define(wxTaskBarIcon_destruct, 3498).
+-define(wxTaskBarIcon_PopupMenu, 3499).
+-define(wxTaskBarIcon_RemoveIcon, 3500).
+-define(wxTaskBarIcon_SetIcon, 3501).
+-define(wxLocale_new_0, 3502).
+-define(wxLocale_new_2_0, 3503).
+-define(wxLocale_new_2_1, 3504).
+-define(wxLocale_destruct, 3505).
+-define(wxLocale_Init_1, 3506).
+-define(wxLocale_Init_2, 3507).
+-define(wxLocale_AddCatalog_1, 3508).
+-define(wxLocale_AddCatalog_2, 3509).
+-define(wxLocale_AddCatalog_3, 3510).
+-define(wxLocale_AddCatalogLookupPathPrefix, 3511).
+-define(wxLocale_GetCanonicalName, 3512).
+-define(wxLocale_GetLanguage, 3513).
+-define(wxLocale_GetLanguageName, 3514).
+-define(wxLocale_GetLocale, 3515).
+-define(wxLocale_GetName, 3516).
+-define(wxLocale_GetString_2, 3517).
+-define(wxLocale_GetString_4, 3518).
+-define(wxLocale_GetHeaderValue, 3519).
+-define(wxLocale_GetSysName, 3520).
+-define(wxLocale_GetSystemEncoding, 3521).
+-define(wxLocale_GetSystemEncodingName, 3522).
+-define(wxLocale_GetSystemLanguage, 3523).
+-define(wxLocale_IsLoaded, 3524).
+-define(wxLocale_IsOk, 3525).
+-define(wxActivateEvent_GetActive, 3526).
+-define(wxPopupWindow_new_0, 3527).
+-define(wxPopupWindow_new_2, 3528).
+-define(wxPopupWindow_Create, 3529).
+-define(wxPopupWindow_Position, 3530).
+-define(wxPopupWindow_destroy, 3531).
+-define(wxPopupTransientWindow_new_0, 3532).
+-define(wxPopupTransientWindow_new_2, 3533).
+-define(wxPopupTransientWindow_Popup, 3534).
+-define(wxPopupTransientWindow_Dismiss, 3535).
+-define(wxPopupTransientWindow_destroy, 3536).
+-define(wxOverlay_new, 3537).
+-define(wxOverlay_destruct, 3538).
+-define(wxOverlay_Reset, 3539).
+-define(wxDCOverlay_new_6, 3540).
+-define(wxDCOverlay_new_2, 3541).
+-define(wxDCOverlay_destruct, 3542).
+-define(wxDCOverlay_Clear, 3543).
+-define(wxDropFilesEvent_GetPosition, 3544).
+-define(wxDropFilesEvent_GetNumberOfFiles, 3545).
+-define(wxDropFilesEvent_GetFiles, 3546).
+-define(wxDisplay_new_0, 3547).
+-define(wxDisplay_new_1_0, 3548).
+-define(wxDisplay_new_1_1, 3549).
+-define(wxDisplay_destruct, 3550).
+-define(wxDisplay_IsOk, 3551).
+-define(wxDisplay_GetClientArea, 3552).
+-define(wxDisplay_GetGeometry, 3553).
+-define(wxDisplay_GetName, 3554).
+-define(wxDisplay_IsPrimary, 3555).
+-define(wxDisplay_GetCount, 3556).
+-define(wxDisplay_GetFromPoint, 3557).
+-define(wxDisplay_GetFromWindow, 3558).
+-define(wxDisplay_GetPPI, 3559).
+-define(wxGCDC_new_1, 3560).
+-define(wxGCDC_new_0, 3563).
+-define(wxGCDC_destruct, 3564).
+-define(wxGCDC_GetGraphicsContext, 3565).
+-define(wxGCDC_SetGraphicsContext, 3566).
+-define(wxNotificationMessage_new_0, 3567).
+-define(wxNotificationMessage_new_2, 3568).
+-define(wxNotificationMessage_destruct, 3569).
+-define(wxNotificationMessage_AddAction, 3570).
+-define(wxNotificationMessage_Close, 3571).
+-define(wxNotificationMessage_SetFlags, 3572).
+-define(wxNotificationMessage_SetIcon, 3573).
+-define(wxNotificationMessage_SetMessage, 3574).
+-define(wxNotificationMessage_SetParent, 3575).
+-define(wxNotificationMessage_SetTitle, 3576).
+-define(wxNotificationMessage_Show, 3577).
+-define(wxNotificationMessage_UseTaskBarIcon, 3578).
+-define(wxNotificationMessage_MSWUseToasts, 3579).
+-define(wxWebView_New, 3581).
+-define(wxWebView_GetCurrentTitle, 3582).
+-define(wxWebView_GetCurrentURL, 3583).
+-define(wxWebView_GetPageSource, 3584).
+-define(wxWebView_GetPageText, 3585).
+-define(wxWebView_IsBusy, 3586).
+-define(wxWebView_IsEditable, 3587).
+-define(wxWebView_LoadURL, 3588).
+-define(wxWebView_Print, 3589).
+-define(wxWebView_Reload, 3590).
+-define(wxWebView_RunScript, 3591).
+-define(wxWebView_SetEditable, 3592).
+-define(wxWebView_SetPage, 3593).
+-define(wxWebView_Stop, 3594).
+-define(wxWebView_CanCopy, 3595).
+-define(wxWebView_CanCut, 3596).
+-define(wxWebView_CanPaste, 3597).
+-define(wxWebView_Copy, 3598).
+-define(wxWebView_Cut, 3599).
+-define(wxWebView_Paste, 3600).
+-define(wxWebView_EnableContextMenu, 3601).
+-define(wxWebView_IsContextMenuEnabled, 3602).
+-define(wxWebView_CanGoBack, 3603).
+-define(wxWebView_CanGoForward, 3604).
+-define(wxWebView_ClearHistory, 3605).
+-define(wxWebView_EnableHistory, 3606).
+-define(wxWebView_GoBack, 3607).
+-define(wxWebView_GoForward, 3608).
+-define(wxWebView_ClearSelection, 3609).
+-define(wxWebView_DeleteSelection, 3610).
+-define(wxWebView_GetSelectedSource, 3611).
+-define(wxWebView_GetSelectedText, 3612).
+-define(wxWebView_HasSelection, 3613).
+-define(wxWebView_SelectAll, 3614).
+-define(wxWebView_CanRedo, 3615).
+-define(wxWebView_CanUndo, 3616).
+-define(wxWebView_Redo, 3617).
+-define(wxWebView_Undo, 3618).
+-define(wxWebView_Find, 3619).
+-define(wxWebView_CanSetZoomType, 3620).
+-define(wxWebView_GetZoom, 3621).
+-define(wxWebView_GetZoomType, 3622).
+-define(wxWebView_SetZoom, 3623).
+-define(wxWebView_SetZoomType, 3624).
+-define(wxWebView_GetZoomFactor, 3625).
+-define(wxWebView_SetZoomFactor, 3626).
+-define(wxWebView_IsBackendAvailable, 3627).
+-define(wxWebViewEvent_GetString, 3628).
+-define(wxWebViewEvent_GetInt, 3629).
+-define(wxWebViewEvent_GetTarget, 3630).
+-define(wxWebViewEvent_GetURL, 3631).
diff --git a/lib/wx/src/wx.app.src b/lib/wx/src/wx.app.src
index 92984f13b5..91ee7a7589 100644
--- a/lib/wx/src/wx.app.src
+++ b/lib/wx/src/wx.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,5 +35,5 @@
{registered, []},
{applications, [stdlib, kernel]},
{env, []},
- {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-6.0"]}
+ {runtime_dependencies, ["stdlib-3.15","kernel-8.0","erts-12.0"]}
]}.
diff --git a/lib/wx/src/wx.erl b/lib/wx/src/wx.erl
index b04d39de8a..22fcf1f57b 100644
--- a/lib/wx/src/wx.erl
+++ b/lib/wx/src/wx.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -149,14 +149,14 @@ set_env(#wx_env{sv=Pid} = Env) ->
%% all MacOSX specific events corresponding to MacNewFile() and friends
%% from wxWidgets wxApp https://docs.wxwidgets.org/trunk/classwx_app.html
%%
-%% * `{file_new, ""}`
-%% * `{file_open, Filename}`
-%% * `{file_print, Filename}`
-%% * `{url_open, Url}`
+%% * `{new_file, ""}`
+%% * `{open_file, Filename}`
+%% * `{print_file, Filename}`
+%% * `{open_url, Url}`
%% * `{reopen_app, ""}`
%%
%% The call always returns ok but will have sent any already received
-%% events to the calling process.
+%% events to the calling process.
-spec subscribe_events() -> 'ok'.
subscribe_events() ->
gen_server:call(wxe_master, subscribe_msgs, infinity).
diff --git a/lib/wx/src/wxe_master.erl b/lib/wx/src/wxe_master.erl
index c3496a0026..5724457ae7 100644
--- a/lib/wx/src/wxe_master.erl
+++ b/lib/wx/src/wxe_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ init_env(SilentStart) ->
%%--------------------------------------------------------------------
-%% Initalizes the opengl library
+%% Initializes the opengl library
%%--------------------------------------------------------------------
init_opengl() ->
case get(wx_init_opengl) of
@@ -123,7 +123,8 @@ init([SilentStart]) ->
wxe_util:setup_consts(),
{ok, #state{}}
catch _:Error:ST ->
- io:format("Error: ~p @ ~p~n",[Error, ST]),
+ Str = io_lib:format("Error: ~p @ ~p~n",[Error, ST]),
+ logger:log(error, Str, #{domain => [wx]}),
error({error, {Error, "Could not initiate graphics"}})
end.
@@ -167,13 +168,13 @@ handle_cast(_Msg, State) ->
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info({wxe_driver, error, Msg}, State) ->
- error_logger:error_report([{wx, error}, {message, lists:flatten(Msg)}]),
+ logger:log(error, "wx: ~s", [Msg], #{domain => [wx]}),
{noreply, State};
handle_info({wxe_driver, internal_error, Msg}, State) ->
- error_logger:error_report([{wx, internal_error}, {message, lists:flatten(Msg)}]),
+ logger:log(error, "wx: ~s", [Msg], #{domain => [wx]}),
{noreply, State};
handle_info({wxe_driver, debug, Msg}, State) ->
- io:format("WX DBG: ~s~n", [Msg]),
+ logger:log(notice, "wx: ~s", [Msg], #{domain => [wx]}),
{noreply, State};
handle_info({wxe_driver, Cmd, File}, State = #state{subscribers=Subs, msgs=Msgs})
when Cmd =:= open_file; Cmd =:= new_file; Cmd =:= print_file;
@@ -183,8 +184,8 @@ handle_info({wxe_driver, Cmd, File}, State = #state{subscribers=Subs, msgs=Msgs}
handle_info({'DOWN', _Ref, process, Pid, _Info}, State) ->
Subs = State#state.subscribers -- [Pid],
{noreply, State#state{subscribers=Subs}};
-handle_info(_Info, State) ->
- io:format("Unknown message ~p sent to ~p~n",[_Info, ?MODULE]),
+handle_info(Info, State) ->
+ logger:log(notice, "wx: Unexpected Msg: ~p", [Info], #{domain => [wx], line=>?LINE, file=>?MODULE_STRING}),
{noreply, State}.
%%--------------------------------------------------------------------
diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl
index 4cef311bb3..4d3de165fd 100644
--- a/lib/wx/src/wxe_server.erl
+++ b/lib/wx/src/wxe_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@
%%-record(event, {object, callback, cb_handler}).
-define(APPLICATION, wxe).
--define(log(S,A), log(?MODULE,?LINE,S,A)).
+-define(log(S,A), log(?MODULE_STRING,?LINE,S,A)).
-include("wxe.hrl").
-include("../include/wx.hrl").
@@ -210,7 +210,7 @@ code_change(_OldVsn, State, _Extra) ->
%%--------------------------------------------------------------------
log(Mod,Line,Str,Args) ->
- error_logger:format("~p:~p: " ++ Str, [Mod,Line|Args]).
+ logger:log(error, Str, Args, #{domain => [wx], file=>Mod, line=>Line}).
handle_connect(Object, #evh{handler=undefined, cb=Callback} = EvData0,
From, State0) ->
diff --git a/lib/wx/src/wxe_util.erl b/lib/wx/src/wxe_util.erl
index 1e72f39057..1d5f15f131 100644
--- a/lib/wx/src/wxe_util.erl
+++ b/lib/wx/src/wxe_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,6 +40,13 @@
init_opengl/1
]).
+-nifs([queue_cmd/1,queue_cmd/2,queue_cmd/3,queue_cmd/4,queue_cmd/5,
+ queue_cmd/6,queue_cmd/7,queue_cmd/8,queue_cmd/9,queue_cmd/10,
+ queue_cmd/11,queue_cmd/12,queue_cmd/13,queue_cmd/14,queue_cmd/15,
+ make_env/0, delete_env/1, debug_driver/1, get_consts_impl/0,
+ init_opengl/1
+ ]).
+
-export([priv_dir/2, opt_error_log/3, init_nif/1]).
-include("wxe.hrl").
@@ -190,6 +197,6 @@ strip([H|R], Src) ->
[H| strip(R, Src)].
opt_error_log(false, Format, Args) ->
- error_logger:format(Format, Args);
+ logger:log(error, Format, Args, #{domain => [wx]});
opt_error_log(true, _Format, _Args) ->
ok.
diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl
index fc88558a46..170738aa30 100644
--- a/lib/wx/test/wx_basic_SUITE.erl
+++ b/lib/wx/test/wx_basic_SUITE.erl
@@ -607,7 +607,7 @@ 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
+ case Async > 0 of %% Test sync explicitly
true -> ok;
false -> {Async, Sync}
end.
diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl
index c21a916133..7cab2d85fa 100644
--- a/lib/wx/test/wx_class_SUITE.erl
+++ b/lib/wx/test/wx_class_SUITE.erl
@@ -87,7 +87,7 @@ calendarCtrl(Config) ->
true ->
?log("DateAttr is null~n",[]);
false ->
- ?log("DateAttr is useable~n",[]),
+ ?log("DateAttr is usable~n",[]),
DateAttr = ?mt(wxCalendarDateAttr, wxCalendarDateAttr:new()),
wxCalendarDateAttr:setBackgroundColour(DateAttr, {0,243,0}),
wxCalendarCtrl:setAttr(Cal, Day, DateAttr),
diff --git a/lib/wx/test/wx_opengl_SUITE.erl b/lib/wx/test/wx_opengl_SUITE.erl
index 28c5b70383..3ec75c662a 100644
--- a/lib/wx/test/wx_opengl_SUITE.erl
+++ b/lib/wx/test/wx_opengl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -88,7 +88,7 @@ end_per_group(_GroupName, Config) ->
{{7,8,3,2},{0.0,-1.0,0.0}}]).
-%% Test we can create a glCanvas and that functions are loaded dynamicly
+%% Test we can create a glCanvas and that functions are loaded dynamically
canvas(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
canvas(Config) ->
WX = ?mr(wx_ref, wx:new()),
diff --git a/lib/wx/test/wx_xtra_SUITE.erl b/lib/wx/test/wx_xtra_SUITE.erl
index a87f4a83b1..b60b8b81f7 100644
--- a/lib/wx/test/wx_xtra_SUITE.erl
+++ b/lib/wx/test/wx_xtra_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -68,7 +68,7 @@ end_per_group(_GroupName, Config) ->
%% before wx:destroy is called.
destroy_app(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
destroy_app(_Config) ->
- %% This is timing releated but we test a couple of times
+ %% This is timing related but we test a couple of times
wx_test_lib:flush(),
?m(ok, destroy_app_test(15)).
@@ -102,7 +102,7 @@ destroy_app2(_Config) ->
ok.
-%% This should work, and does but not when run automaticly on windows
+%% This should work, and does but not when run automatically on windows
%% for some strange reason (it just hangs), run it last.
app_dies(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
app_dies(_Config) ->
@@ -160,7 +160,7 @@ oops(Die, Line) when (Die =:= last) orelse (Die =< Line) ->
oops(_,_) -> ok.
-%% This have happend often enough that I have special code to handle
+%% This have happened often enough that I have special code to handle
%% this user error (i.e. using the a window twice in an sizer).
multiple_add_in_sizer(TestInfo) when is_atom(TestInfo) -> wx_test_lib:tc_info(TestInfo);
multiple_add_in_sizer(Config) ->
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 51279f250b..e7144bd6a2 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 2.1.4
+WX_VSN = 2.2.1
diff --git a/lib/xmerl/doc/examples/test_html.erl b/lib/xmerl/doc/examples/test_html.erl
index cb8088833c..4fe3fe42b4 100644
--- a/lib/xmerl/doc/examples/test_html.erl
+++ b/lib/xmerl/doc/examples/test_html.erl
@@ -134,14 +134,14 @@ col(Data, Attrs, [{row,_}, {table,_} | _], E) ->
["<td>", nbsp_if_empty(Data), "</td>\n"].
-tuple_list(List, Attrs, Parents, E) ->
+tuple_list(List, Attrs, _Parents, _E) ->
Elems = case find_attribute(elements, Attrs) of
{value, Es} ->
Es;
false ->
case List of
[H|_] ->
- lists:seq(1,size(H));
+ lists:seq(1,tuple_size(H));
[] ->
[]
end
diff --git a/lib/xmerl/doc/examples/xml/xmerl.xml b/lib/xmerl/doc/examples/xml/xmerl.xml
index f02282dbef..983a0bfde1 100644
--- a/lib/xmerl/doc/examples/xml/xmerl.xml
+++ b/lib/xmerl/doc/examples/xml/xmerl.xml
@@ -127,7 +127,7 @@ xmerl_scan:file(Filename [ , Options ]) -> #xmlElement{}. </programlisting>
e.g. <computeroutput>xmerl_eventp.erl</computeroutput>) is for
customization functions to share one of the local states (in
<computeroutput>xmerl_eventp.erl</computeroutput>, the
- continuation function and the fetch function both acces the
+ continuation function and the fetch function both access the
<computeroutput>cont_state</computeroutput>.)</para>
<para>Functions to access user state:</para>
@@ -357,7 +357,7 @@ Occurrence ::= '*' | '?' | '+'
<para>The accumulator function is called to accumulate the
contents of an entity.When parsing very large files, it may
- not be desireable to do so.In this case, an acc function can
+ not be desirable to do so.In this case, an acc function can
be provided that simply doesn't accumulate.</para>
<para>Note that it is possible to even modify the parsed
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index fc8f686462..6f73749ecc 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -32,6 +32,75 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.3.31</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Replace size/1 with either tuple_size/1 or byte_size/1</p>
+ <p>
+ The <c>size/1</c> BIF is not optimized by the JIT, and
+ its use can result in worse types for Dialyzer.</p>
+ <p>
+ When one knows that the value being tested must be a
+ tuple, <c>tuple_size/1</c> should always be preferred.</p>
+ <p>
+ When one knows that the value being tested must be a
+ binary, <c>byte_size/1</c> should be preferred. However,
+ <c>byte_size/1</c> also accepts a bitstring (rounding up
+ size to a whole number of bytes), so one must make sure
+ that the call to <c>byte_size/</c> is preceded by a call
+ to <c>is_binary/1</c> to ensure that bitstrings are
+ rejected. Note that the compiler removes redundant calls
+ to <c>is_binary/1</c>, so if one is not sure whether
+ previous code had made sure that the argument is a
+ binary, it does not harm to add an <c>is_binary/1</c>
+ test immediately before the call to <c>byte_size/1</c>.</p>
+ <p>
+ Own Id: OTP-18432 Aux Id:
+ GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.30</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>There is a new configure option,
+ <c>--enable-deterministic-build</c>, which will apply the
+ <c>deterministic</c> compiler option when building
+ Erlang/OTP. The <c>deterministic</c> option has been
+ improved to eliminate more sources of non-determinism in
+ several applications.</p>
+ <p>
+ Own Id: OTP-18165 Aux Id: PR-5965 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Xmerl 1.3.29</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Fixed misspellings in both documentation, comments and
+ code (internal data structures).</p>
+ <p>
+ Own Id: OTP-17935 Aux Id: PR-5590 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.3.28</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/doc/src/xmerl_examples.html b/lib/xmerl/doc/src/xmerl_examples.html
index 1305f59d4a..7c8ef3d4bb 100644
--- a/lib/xmerl/doc/src/xmerl_examples.html
+++ b/lib/xmerl/doc/src/xmerl_examples.html
@@ -71,7 +71,7 @@
e.g. <tt>xmerl_eventp.erl</tt>) is for
customization functions to share one of the local states (in
<tt>xmerl_eventp.erl</tt>, the
- continuation function and the fetch function both acces the
+ continuation function and the fetch function both access the
<tt>cont_state</tt>.)</p>
<p>Functions to access user state:</p>
@@ -310,7 +310,7 @@
<p>The accumulator function is called to accumulate the
contents of an entity.When parsing very large files, it may
- not be desireable to do so.In this case, an acc function can
+ not be desirable to do so.In this case, an acc function can
be provided that simply doesn't accumulate.</p>
<p>Note that it is possible to even modify the parsed
diff --git a/lib/xmerl/include/xmerl.hrl b/lib/xmerl/include/xmerl.hrl
index 1e13255a49..7c032df379 100644
--- a/lib/xmerl/include/xmerl.hrl
+++ b/lib/xmerl/include/xmerl.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,13 +18,13 @@
%% %CopyrightEnd%
%%
%% Contributor(s):
-%% <michael.remond@IDEALX.com>: suggested #xmlDocument{}
+%% Michael.Remond: suggested #xmlDocument{}
%%
%%----------------------------------------------------------------------
%% #0. BASIC INFORMATION
%%----------------------------------------------------------------------
%% File: xmerl.hrl
-%% Author : Ulf Wiger <ulf.wiger@ericsson.com>
+%% Author : Ulf Wiger
%% Date : 00-09-22
%% Description : Record and macro definitions for xmerl
%%----------------------------------------------------------------------
diff --git a/lib/xmerl/include/xmerl_xpath.hrl b/lib/xmerl/include/xmerl_xpath.hrl
index e5d697eea5..0775bf3e3c 100644
--- a/lib/xmerl/include/xmerl_xpath.hrl
+++ b/lib/xmerl/include/xmerl_xpath.hrl
@@ -22,7 +22,7 @@
%%% #0. BASIC INFORMATION
%%%----------------------------------------------------------------------
%%% File: xmerl.hrl
-%%% Author : Ulf Wiger <ulf.wiger@ericsson.com>
+%%% Author : Ulf Wiger
%%% Date : 00-09-22
%%% Description : Record and macro definitions for xmerl_xpath
%%%----------------------------------------------------------------------
diff --git a/lib/xmerl/include/xmerl_xsd.hrl b/lib/xmerl/include/xmerl_xsd.hrl
index e3ee8efd40..31633d01da 100644
--- a/lib/xmerl/include/xmerl_xsd.hrl
+++ b/lib/xmerl/include/xmerl_xsd.hrl
@@ -51,7 +51,7 @@
global_namespace_nodes=[],
checked_namespace_nodes=[{"xml",[],'http://www.w3.org/XML/1998/namespace'}],
table,
- tab2file=false, %% for debuging of abstract syntax
+ tab2file=false, %% for debugging of abstract syntax
redefine=false,
finalDefault, %% undefined | '#all' | [atom()]
%% atom() -> extension |
@@ -89,7 +89,7 @@
scope,
form, %% unqualified | qualified
id,
- occurance={1,1}, %% {minOccurs,maxOccurs}
+ occurrence={1,1}, %% {minOccurs,maxOccurs}
value_constraint, %% undefined | {default,Value} | {fixed,Value}
nillable=false, %% true | false
abstract=false, %% true | false
@@ -153,7 +153,7 @@
id,
ref, %% in this case no name or content
content=[],
- occurance={1,1}
+ occurrence={1,1}
}).
-record(schema_extension,{
base,
@@ -189,9 +189,9 @@
%% alterantive, a collection of objects of which only one is chosen.
-record(chain,{
content,
- occurance={1,1}
+ occurrence={1,1}
}).
-record(alternative,{
content,
- occurance={0,1}
+ occurrence={0,1}
}).
diff --git a/lib/xmerl/src/Makefile b/lib/xmerl/src/Makefile
index 51d9190797..e7e7c8e978 100644
--- a/lib/xmerl/src/Makefile
+++ b/lib/xmerl/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2016. All Rights Reserved.
+# Copyright Ericsson AB 2003-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -127,11 +127,16 @@ ERL_COMPILE_FLAGS += \
# +bin_opt_info
+ifeq ($(ERL_DETERMINISTIC),yes)
+ DETERMINISM_FLAG = +deterministic
+else
+ DETERMINISM_FLAG =
+endif
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-debug opt: $(TARGET_FILES)
+$(TYPES): $(TARGET_FILES)
docs:
#docs: $(DOC_TARGET_FILES)
@@ -173,10 +178,10 @@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
$(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
xmerl_xpath_parse.erl: xmerl_xpath_parse.yrl
- $(yecc_verbose)$(ERLC) -o $(ESRC) $<
+ $(yecc_verbose)$(ERLC) -o $(ESRC) $(DETERMINISM_FLAG) $<
xmerl_b64Bin.erl: xmerl_b64Bin.yrl
- $(yecc_verbose)$(ERLC) -o $(ESRC) $<
+ $(yecc_verbose)$(ERLC) -o $(ESRC) $(DETERMINISM_FLAG) $<
xmerl_sax_parser_list.erl: xmerl_sax_parser_list.erlsrc xmerl_sax_parser_base.erlsrc
$(gen_verbose)cat xmerl_sax_parser_list.erlsrc xmerl_sax_parser_base.erlsrc >$@
diff --git a/lib/xmerl/src/xmerl_eventp.erl b/lib/xmerl/src/xmerl_eventp.erl
index 8d7ea25e24..96bcd49766 100644
--- a/lib/xmerl/src/xmerl_eventp.erl
+++ b/lib/xmerl/src/xmerl_eventp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -295,8 +295,8 @@ read_chunk(Fd, _Fname, _Sofar) ->
-ifndef(no_bitsyntax).
-find_good_split(Bin, F, Exception, Fd, Fname, T, S) ->
- find_good_split(size(Bin)-1, Bin, F, Exception, Fd, Fname, T, S).
+find_good_split(Bin, F, Exception, Fd, Fname, T, S) when is_binary(Bin) ->
+ find_good_split(byte_size(Bin)-1, Bin, F, Exception, Fd, Fname, T, S).
find_good_split(0, B, F, Exception, Fd, Fname, T, S) ->
cont2(F, Exception, B, Fd, Fname, T, S);
@@ -312,8 +312,8 @@ find_good_split(Size, B, F, Exception, Fd, Fname, T, S) ->
-else.
-find_good_split(Bin, F, Exception, Fd, Fname, T, S) ->
- find_good_split(size(Bin), Bin, F, Exception, Fd, Fname, T, S).
+find_good_split(Bin, F, Exception, Fd, Fname, T, S) when is_binary(Bin) ->
+ find_good_split(byte_size(Bin), Bin, F, Exception, Fd, Fname, T, S).
find_good_split(0, B, F, Exception, Fd, Fname, T, S) ->
cont2(F, Exception, B, Fd, Fname, T, S);
diff --git a/lib/xmerl/src/xmerl_regexp.erl b/lib/xmerl/src/xmerl_regexp.erl
index 1bf8496673..46d01ca9fb 100644
--- a/lib/xmerl/src/xmerl_regexp.erl
+++ b/lib/xmerl/src/xmerl_regexp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -510,7 +510,7 @@ gsub_comp([], _P, _RE, _Bef, _Rep) -> no.
%% split(String, RegExp) -> {ok,[SubString]} | {error,E}.
%% Split a string into substrings where the RegExp describes the
-%% field seperator. The RegExp " " is specially treated.
+%% field separator. The RegExp " " is specially treated.
split(String, " ") -> %This is really special
{ok,{regexp,RE}} = parse("[ \t]+"),
@@ -1289,7 +1289,7 @@ accept([], _NFA) -> no.
%% minimise_dfa(DFA, StartState, FirstState) -> {DFA,StartState}.
%% Minimise the DFA by removing equivalent states. We consider a
%% state if both the transitions and the their accept state is the
-%% same. First repeatedly run throught the DFA state list removing
+%% same. First repeatedly run through the DFA state list removing
%% equivalent states and updating remaining transitions with
%% remaining equivalent state numbers. When no more reductions are
%% possible then pack the remaining state numbers to get consecutive
diff --git a/lib/xmerl/src/xmerl_sax_parser.erl b/lib/xmerl/src/xmerl_sax_parser.erl
index 1b17b1d5cb..c119223470 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -158,7 +158,7 @@ parse_binary(Xml, #xmerl_sax_parser_state{encoding={utf16,big}}=State, F) ->
parse_binary(Xml, #xmerl_sax_parser_state{encoding=latin1}=State, F) ->
xmerl_sax_parser_latin1:F(Xml, State);
parse_binary(_, #xmerl_sax_parser_state{encoding=Enc}, State) ->
- ?fatal_error(State, lists:flatten(io_lib:format("Charcter set ~p not supported", [Enc]))).
+ ?fatal_error(State, lists:flatten(io_lib:format("Character set ~p not supported", [Enc]))).
%%----------------------------------------------------------------------
%% Function: initial_state/0
diff --git a/lib/xmerl/src/xmerl_sax_parser.hrl b/lib/xmerl/src/xmerl_sax_parser.hrl
index aac155ac63..a34bc7a6ab 100644
--- a/lib/xmerl/src/xmerl_sax_parser.hrl
+++ b/lib/xmerl/src/xmerl_sax_parser.hrl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@
-define(is_hex_digit(C), $0 =< C, C =< $9; $a =< C, C =< $f; $A =< C, C =< $F).
%%----------------------------------------------------------------------
-%% Definition of XML charcters
+%% Definition of XML characters
%%
%% [2] Char #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
%%----------------------------------------------------------------------
@@ -82,7 +82,7 @@
current_tag = [], % Current tag
end_tags = [], % Stack of tags used for end tag matching
match_end_tags = true, % Flag which defines if the parser should match on end tags
- ref_table, % Table containing entitity definitions
+ ref_table, % Table containing entity definitions
standalone = no, % yes if the document is standalone and don't need an external DTD.
file_type = normal, % Can be normal, dtd and entity
current_location, % Location of the currently parsed XML entity
diff --git a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc
index 49a9a6ada6..67fdec560e 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-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1727,7 +1727,7 @@ parse_reference(?STRING_UNBOUND_REST(C, Rest), State, HaveToExist) ->
end;
parse_reference(Bytes, State, HaveToExist) ->
unicode_incomplete_check([Bytes, State, HaveToExist, fun parse_reference/3],
- underfined).
+ undefined).
parse_reference_1(?STRING_EMPTY, State, HaveToExist, Name) ->
@@ -1799,7 +1799,7 @@ parse_pe_reference(?STRING_UNBOUND_REST(C, Rest), State) ->
end;
parse_pe_reference(Bytes, State) ->
unicode_incomplete_check([Bytes, State, fun parse_pe_reference/2],
- underfined).
+ undefined).
parse_pe_reference_1(?STRING_EMPTY, State, Name) ->
@@ -2028,7 +2028,7 @@ normalize_whitespace([], Acc) ->
%% State = #xmerl_sax_parser_state{}
%% Result : {Rest, State}
%% Description: This function starts an parsing of the DTD
-%% that sends apropriate events.
+%% that sends appropriate events.
%% [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
%% ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
%%----------------------------------------------------------------------
@@ -2057,7 +2057,7 @@ parse_doctype(Bytes, State) ->
%% Name = string()
%% Definition = true |false
%% Result : {Rest, State}
-%% Description: Gets the DTD name as a parameter and contine parse the DOCTYPE
+%% Description: Gets the DTD name as a parameter and continue parse the DOCTYPE
%% directive
%%----------------------------------------------------------------------
parse_doctype_1(?STRING_EMPTY, State, Name, Definition) ->
@@ -3829,7 +3829,7 @@ parse_notation_decl_1(Bytes, State) ->
%% PubId = string()
%% SysId = string()
%% Description: Parse a NOTATION identity. The public id case is a special
-%% variant of extenal id where just the public part is allowed.
+%% variant of external id where just the public part is allowed.
%% This is allowed if the third parameter in parse_external_id/3
%% is true.
%% [83] PublicID ::= 'PUBLIC' S PubidLiteral
diff --git a/lib/xmerl/src/xmerl_sax_parser_list.erlsrc b/lib/xmerl/src/xmerl_sax_parser_list.erlsrc
index ac89896215..bb9213bff1 100644
--- a/lib/xmerl/src/xmerl_sax_parser_list.erlsrc
+++ b/lib/xmerl/src/xmerl_sax_parser_list.erlsrc
@@ -2,7 +2,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
-define(APPEND_STRING(Rest, New), Rest ++ New).
-define(TO_INPUT_FORMAT(Val), Val).
-%% In the list case we can't use a '++' when matchin against an unbound variable
+%% In the list case we can't use a '++' when matching against an unbound variable
-define(STRING_UNBOUND_REST(MatchChar, Rest), [MatchChar | Rest]).
-define(PARSE_BYTE_ORDER_MARK(Bytes, State),
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index 270d5b4962..2285ce0d06 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -3637,7 +3637,7 @@ scan_entity_value("%" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) ->
ExpRef ->
{string_to_char_set(S1#xmerl_scanner.encoding, ExpRef) ,S1}
end,
- %% single or duoble qoutes are not treated as delimeters
+ %% single or duoble quotes are not treated as delimiters
%% in passages "included in literal"
S3 = S2#xmerl_scanner{col=S2#xmerl_scanner.col+1},
{Acc2,_,S4} = scan_entity_value(ExpandedRef,S3,no_delim,Acc,
@@ -3678,32 +3678,32 @@ scan_entity_value("&" ++ T, S0, Delim, Acc, PEName,Namespace,PENesting) ->
scan_entity_value(T2,S2,Delim,[";",atom_to_list(Name),"&"|Acc],PEName,Namespace,PENesting)
end;
%% The following clauses is for PE Nesting VC constraint
-%% Start delimeter for ConditionalSection
+%% Start delimiter for ConditionalSection
scan_entity_value("<!["++T,S0,Delim,Acc,PEName,parameter=NS,PENesting)->
?bump_col(3),
scan_entity_value(T,S,Delim,["<!["|Acc],PEName,NS,
pe_push("<![",PENesting,S));
-%% Start delimeter for ConditionalSection (2)
+%% Start delimiter for ConditionalSection (2)
scan_entity_value("["++T,S0,Delim,Acc,PEName,parameter=NS,PENesting)->
?bump_col(1),
scan_entity_value(T,S,Delim,["["|Acc],PEName,NS,
pe_push("[",PENesting,S));
-%% Start delimeter for comment
+%% Start delimiter for comment
scan_entity_value("<!--"++T,S0,Delim,Acc,PEName,parameter=NS,PENesting)->
?bump_col(4),
scan_entity_value(T,S,Delim,["<!--"|Acc],PEName,NS,
pe_push("<!--",PENesting,S));
-%% Start delimeter for ElementDecl, AttListDecl,EntityDecl,NotationDecl
+%% Start delimiter for ElementDecl, AttListDecl,EntityDecl,NotationDecl
scan_entity_value("<!"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(2),
scan_entity_value(T,S,Delim,["<!"|Acc],PEName,NS,
pe_push("<!",PENesting,S));
-%% Start delimeter for PI
+%% Start delimiter for PI
scan_entity_value("<?"++T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(2),
scan_entity_value(T,S,Delim,["<?"|Acc],PEName,NS,
pe_push("<?",PENesting,S));
-%% Start delimeter for elements that matches the proper stop delimeter
+%% Start delimiter for elements that matches the proper stop delimiter
%% for a markupdecl
scan_entity_value("</"++T,S0,Delim,Acc,PEName,parameter=NS,PENesting)->
?bump_col(2),
@@ -3713,32 +3713,32 @@ scan_entity_value("<"++T,S0,Delim,Acc,PEName,parameter=NS,PENesting)->
?bump_col(1),
scan_entity_value(T,S,Delim,["<"|Acc],PEName,NS,
pe_push("<",PENesting,S));
-%% Delimeter for contentspecs
+%% Delimiter for contentspecs
scan_entity_value("("++T,S0,Delim,Acc,PEName,parameter=NS,PENesting)->
?bump_col(1),
scan_entity_value(T,S,Delim,["("|Acc],PEName,NS,
pe_push("(",PENesting,S));
-%% Stop delimeter for ElementDecl, AttListDecl,EntityDecl,NotationDecl
+%% Stop delimiter for ElementDecl, AttListDecl,EntityDecl,NotationDecl
scan_entity_value(">"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(1),
scan_entity_value(T,S,Delim,[">"|Acc],PEName,NS,
pe_pop(">",PENesting,S));
-%% Stop delimeter for PI
+%% Stop delimiter for PI
scan_entity_value("?>"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(2),
scan_entity_value(T,S,Delim,["?>"|Acc],PEName,NS,
pe_pop("?>",PENesting,S));
-%% Stop delimeter for comment
+%% Stop delimiter for comment
scan_entity_value("-->"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(3),
scan_entity_value(T,S,Delim,["-->"|Acc],PEName,NS,
pe_pop("-->",PENesting,S));
-%% Stop delimeter for ConditionalSection
+%% Stop delimiter for ConditionalSection
scan_entity_value("]]>"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(3),
scan_entity_value(T,S,Delim,["]]>"|Acc],PEName,NS,
pe_pop("]]>",PENesting,S));
-%% Stop delimeter added to match a content start delimeter included
+%% Stop delimiter added to match a content start delimiter included
scan_entity_value("/>"++ T,S0,Delim,Acc,PEName, parameter=NS,PENesting) ->
?bump_col(2),
scan_entity_value(T,S,Delim,["/>"|Acc],PEName,NS,
diff --git a/lib/xmerl/src/xmerl_ucs.erl b/lib/xmerl/src/xmerl_ucs.erl
index 4b1fc30089..cbe9736999 100644
--- a/lib/xmerl/src/xmerl_ucs.erl
+++ b/lib/xmerl/src/xmerl_ucs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -423,7 +423,7 @@ char_to_utf8(Ch) when is_integer(Ch), Ch >= 0 ->
%% expand_utf8([Byte]) -> {[UnicodeChar],NumberOfBadBytes}
%% Expand UTF8 byte sequences to ISO 10646/Unicode
-%% charactes. Any illegal bytes are removed and the number of
+%% characters. Any illegal bytes are removed and the number of
%% bad bytes are returned.
%%
%% Reference:
diff --git a/lib/xmerl/src/xmerl_validate.erl b/lib/xmerl/src/xmerl_validate.erl
index 8b4f5b91a2..c6b03a0d91 100644
--- a/lib/xmerl/src/xmerl_validate.erl
+++ b/lib/xmerl/src/xmerl_validate.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -509,7 +509,7 @@ choice([CH|CHS],[_XML|_T]=XMLS,Rules,WSaction,S)->
{[],XMLS1} -> %% Maybe a sequence with * or ? elements that
%% didn't match
case CHS of
- [] -> % choice has succeded but without matching XMLS1
+ [] -> % choice has succeeded but without matching XMLS1
{[],XMLS1};
_ -> % there are more choice alternatives to try with
choice(CHS,XMLS1,Rules,WSaction,S)
diff --git a/lib/xmerl/src/xmerl_xpath.erl b/lib/xmerl/src/xmerl_xpath.erl
index 6146feba49..2354f9d6cd 100644
--- a/lib/xmerl/src/xmerl_xpath.erl
+++ b/lib/xmerl/src/xmerl_xpath.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -601,7 +601,7 @@ match_preceding_sibling(Tok, N, Acc, Context) ->
%% "The 'preceding' axis contains all nodes in the same document as the context
-%% node that are before the context node in document order, exluding any
+%% node that are before the context node in document order, excluding any
%% ancestors and excluding attribute nodes and namespace nodes."
match_preceding(Tok, N, Acc, Context) ->
#xmlNode{parents = Ps, node = Node} = N,
diff --git a/lib/xmerl/src/xmerl_xsd.erl b/lib/xmerl/src/xmerl_xsd.erl
index 2836bb0e5b..10ea8df66e 100644
--- a/lib/xmerl/src/xmerl_xsd.erl
+++ b/lib/xmerl/src/xmerl_xsd.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
%% XML Schema study <a href="http://www.w3.org/TR/xmlschema-0/">part 0.</a>
%% An XML structure is validated by xmerl_xsd:validate/[2,3].
%% @type global_state(). <p>The global state of the validator. It is
-%% representated by the <code>#xsd_state{}</code> record.
+%% represented by the <code>#xsd_state{}</code> record.
%% </p>
%% @type option_list(). <p>Options allow to customize the behaviour of the
%% validation.
@@ -400,7 +400,7 @@ new_state(Opts) ->
%% information as defined elements and types.
validate_schema(E=#xmlElement{},
S) ->
- %% namespace is always a xmlNamespace record, attributs a list of
+ %% namespace is always a xmlNamespace record, attributes a list of
%% #xmlAttributes and content a list of #xmlElements|#xmlText|...
%% Have to save namespace nodes. Use of namespace in paths for
@@ -563,7 +563,7 @@ element_content({element,S},El,Env) ->
case qualify_NCName(El,S) of
no_name ->
Ref = particle_ref(El),
- {Occ,S2} = occurance(El,{1,1},S),
+ {Occ,S2} = occurrence(El,{1,1},S),
%% 3.3.3 bullet 2.2
S3 = element_forbidden_properties(El,S2),
S4 = element_forbidden_content(El#xmlElement.content,S3),
@@ -578,7 +578,7 @@ element_content({element,S},El,Env) ->
Type2 = remove_annotation(Type),
Unique = [X||X={unique,_} <- Type2],
Key = [X||X={K,_} <- Type2,K == key orelse K==keyref],
- {Occur,S4} = occurance(El,{1,1},S3),
+ {Occur,S4} = occurrence(El,{1,1},S3),
{SE,S5} = element_properties(El#xmlElement.attributes,
#schema_element{},El,S4),
CM = remove_attributes([X||X={Y,_}<-Type2,
@@ -586,14 +586,14 @@ element_content({element,S},El,Env) ->
keyref=/=Y,annotation=/=Y]),
%% take care of key/keyref later
SE2 = SE#schema_element{name=Name,type=CM,uniqueness=Unique,
- key=Key, occurance=Occur,
+ key=Key, occurrence=Occur,
scope=S5#xsd_state.scope},
S6 = insert_substitutionGroup(SE2,S5),
S7 = save_object({element,SE2},S6),
{{element,{Name,Occur}},S7}
end;
element_content({complexType,S},CT,Env) ->
- %% complex type definition without a name is returnd and added to
+ %% complex type definition without a name is returned and added to
%% the content model at this level. A complex type may also contain
%% attributes or attribute group references in the end of its content.
%%?debug("complexType content: ~p~nenv: ~p~n",[CT,Env]),
@@ -677,7 +677,7 @@ element_content({group,S},G,Env) ->
%% "Schema Representation Constraint: Individual Component
%% Redefinition"
Ref = particle_ref(G),
- {Occur,S2} = occurance(G,{1,1},S),
+ {Occur,S2} = occurrence(G,{1,1},S),
GRef =
{group,
{get_QName(Ref,G#xmlElement.namespace,reset_scope(S2)),%%QQQ
@@ -694,16 +694,16 @@ element_content({group,S},G,Env) ->
end;
element_content({all,S},All,Env) ->
%% each element occurs 0 or 1 times in any order
- %% {all,[{element_name,occurance}]}
+ %% {all,[{element_name,occurrence}]}
%% CM = content_model(Seq#xmlElement.content,S,[all|Env]),
- {Occur,S1} = occurance(All,{1,1},S),
+ {Occur,S1} = occurrence(All,{1,1},S),
{CM,S2} = type(All#xmlElement.content,S1,[all|Env]),
S3 = check_cm(all,allowed_content(all,Env),CM,S2),
{{all,{[X||X = {element,_} <- CM],Occur}},S3};
element_content({sequence,S},Seq,Env) ->
- %% {sequence,[{element_name,occurance}]}
+ %% {sequence,[{element_name,occurrence}]}
%% CM = content_model(Seq#xmlElement.content,S,[sequence|Env]),
- {Occur,S1} = occurance(Seq,{1,1},S),
+ {Occur,S1} = occurrence(Seq,{1,1},S),
{CM,S2} = type(Seq#xmlElement.content,S1,[sequence|Env]),
S3 = check_cm(sequence,allowed_content(sequence,Env),CM,S2),
{{sequence,{remove_annotation(CM),Occur}},S3};
@@ -712,12 +712,12 @@ element_content({choice,S},Choice,Env) ->
%% (element | group | choice | sequence | any)*)
%% returns: {choice,[element_name]}
%% CM = content_model(Choice#xmlElement.content,S,[choice|Env]),
- {Occur,S1} = occurance(Choice,{1,1},S),
+ {Occur,S1} = occurrence(Choice,{1,1},S),
{CM,S2} = type(Choice#xmlElement.content,S1,[choice|Env]),
S3 = check_cm(choice,allowed_content(choice,Env),CM,S2),
{{choice,{remove_annotation(CM),Occur}},S3};
element_content({any,S},Any,_Env) ->
- {Occur,S1} = occurance(Any,{1,1},S),
+ {Occur,S1} = occurrence(Any,{1,1},S),
NameSpace = wildcard_namespace(Any,S1),
PC = processor_contents(Any),
?debug("element_content, any: Any content:~p~n",[Any#xmlElement.content]),
@@ -1426,7 +1426,7 @@ check_cm(Kind,S4SCM,ContentModel,S) ->
exit({error,{[],?MODULE,{internal_error,Err}}})
end.
-check_cm2(Kind,#chain{content=S4SCM,occurance=Occ},
+check_cm2(Kind,#chain{content=S4SCM,occurrence=Occ},
ContentModel,S) ->
case occurance_loop(Occ,fun check_chain/1,
[S4SCM,ContentModel,Kind,S],0) of
@@ -1445,7 +1445,7 @@ check_cm2(Kind,#chain{content=S4SCM,occurance=Occ},
Err = {[],?MODULE,{illegal_content,Reason,Kind}},
{ContentModel,acc_errs(S,Err)}
end;
-check_cm2(Kind,#alternative{content=S4SCM,occurance=Occ},
+check_cm2(Kind,#alternative{content=S4SCM,occurrence=Occ},
ContentModel,S) ->
case occurance_loop(Occ,fun check_alternative/1,
[S4SCM,ContentModel,Kind,S],0) of
@@ -1621,9 +1621,9 @@ optional({_,{_,{0,_}}}) ->
true; %% sequence, all or choice
optional({any,{_,{0,_},_}}) ->
true;
-optional(#chain{occurance={0,_}}) ->
+optional(#chain{occurrence={0,_}}) ->
true;
-optional(#alternative{occurance={0,_}}) ->
+optional(#alternative{occurrence={0,_}}) ->
true;
optional(#chain{content=Content}) ->
catch is_optional_content(Content);
@@ -1671,10 +1671,10 @@ allowed_content(element,_Parents) ->
#chain{content=
[#alternative{content=
[{simpleType,{1,1}},{complexType,{1,1}}],
- occurance={0,1}},
+ occurrence={0,1}},
#alternative{content=
[{unique,{1,1}},{key,{1,1}},{keyref,{1,1}}],
- occurance={0,unbounded}}]
+ occurrence={0,unbounded}}]
}]
};
allowed_content(attribute,_Parents) ->
@@ -1689,12 +1689,12 @@ allowed_content(complexType,Parents) ->
[#alternative{content=
[{group,{1,1}},{all,{1,1}},
{choice,{1,1}},{sequence,{1,1}}],
- occurance={0,1}},
+ occurrence={0,1}},
#chain{content=
[#alternative{content=
[{attribute,{1,1}},
{attributeGroup,{1,1}}],
- occurance={0,unbounded}},
+ occurrence={0,unbounded}},
{anyAttribute,{0,1}}]
}
]
@@ -1714,7 +1714,7 @@ allowed_content(attributeGroup,Parents) ->
[#alternative{content=
[{attribute,{1,1}},
{attributeGroup,{1,1}}],
- occurance={0,unbounded}},
+ occurrence={0,unbounded}},
{anyAttribute,{0,1}}]}]}
end;
allowed_content(group,_Parents) ->
@@ -1722,7 +1722,7 @@ allowed_content(group,_Parents) ->
[{annotation,{0,1}},
#alternative{content=
[{all,{1,1}},{choice,{1,1}},{sequence,{1,1}}],
- occurance={0,1}}]};
+ occurrence={0,1}}]};
allowed_content(all,_Parents) ->
#chain{content=[{annotation,{0,1}},{element,{0,unbounded}}]};
allowed_content(SorC,_Parents) when SorC==sequence;SorC==choice ->
@@ -1732,7 +1732,7 @@ allowed_content(SorC,_Parents) when SorC==sequence;SorC==choice ->
[{element,{1,1}},{group,{1,1}},
{choice,{1,1}},{sequence,{1,1}},
{any,{1,1}}],
- occurance={0,unbounded}}]};
+ occurrence={0,unbounded}}]};
%% allowed_content(E,_Parents)
%% when E==any;E==selector;E==field;E==notation;E==include;E==import;
%% E==anyAttribute ->
@@ -1744,7 +1744,7 @@ allowed_content(SorC,_Parents) when SorC==sequence;SorC==choice ->
%% [{selector,{1,1}},{selector,{1,unbounded}}]}]};
%% allowed_content(annotation,_Parents) ->
%% #alternative{content=[{appinfo,{1,1}},{documentation,{1,1}}],
-%% occurance={0,unbounded}};
+%% occurrence={0,unbounded}};
%% allowed_content(E,_Parents) when E==appinfo;E==documentation ->
%% {any,{0,unbounded}};
allowed_content(simpleType,_Parents) ->
@@ -1771,7 +1771,7 @@ allowed_content(LU,_Parent) when LU==list;LU==union ->
%% [#alternative{content=
%% [{include,{1,1}},{import,{1,1}},
%% {redefine,{1,1}},{annotation,{1,1}}],
-%% occurance={0,1}},
+%% occurrence={0,1}},
%% #chain{content=
%% [#alternative{content=
%% [#alternative{content=
@@ -1781,14 +1781,14 @@ allowed_content(LU,_Parent) when LU==list;LU==union ->
%% {attribute,{1,1}},
%% {notation,{1,1}}]},
%% {annotation,{0,unbounded}}],
-%% occurance={0,unbounded}}]};
+%% occurrence={0,unbounded}}]};
allowed_content(redefine,_Parents) ->
#alternative{content=
[{annotation,{1,1}},
#alternative{content=
[{simpleType,{1,1}},{complexType,{1,1}},
{group,{1,1}},{attributeGroup,{1,1}}]}],
- occurance={0,unbounded}};
+ occurrence={0,unbounded}};
allowed_content(E,_Parents) when E==simpleContent;
E==complexContent ->
#chain{content=
@@ -1842,7 +1842,7 @@ allowed_content2(restriction,simpleType) ->
{length,{1,1}},{minLength,{1,1}},
{maxLength,{1,1}},{enumeration,{1,1}},
{whiteSpace,{1,1}},{pattern,{1,1}}],
- occurance={0,unbounded}}]}]};
+ occurrence={0,unbounded}}]}]};
allowed_content2(restriction,simpleContent) ->
#chain{content=
[{annotation,{0,1}},
@@ -1855,12 +1855,12 @@ allowed_content2(restriction,simpleContent) ->
{length,{1,1}},{minLength,{1,1}},
{maxLength,{1,1}},{enumeration,{1,1}},
{whiteSpace,{1,1}},{pattern,{1,1}}],
- occurance={0,unbounded}}],
- occurance={0,1}},
+ occurrence={0,unbounded}}],
+ occurrence={0,1}},
#chain{content=
[#alternative{content=
[{attribute,{1,1}},{attributeGroup,{1,1}}],
- occurance={0,unbounded}},
+ occurrence={0,unbounded}},
{anyAttribute,{0,1}}]}]};
allowed_content2(restriction,complexContent) ->
#chain{content=
@@ -1868,11 +1868,11 @@ allowed_content2(restriction,complexContent) ->
#alternative{content=
[{group,{1,1}},{all,{1,1}},{choice,{1,1}},
{sequence,{1,1}}],
- occurance={0,1}},
+ occurrence={0,1}},
#chain{content=
[#alternative{content=
[{attribute,{1,1}},{attributeGroup,{1,1}}],
- occurance={0,unbounded}},
+ occurrence={0,unbounded}},
{anyAttribute,{0,1}}]}]};
allowed_content2(extension,simpleContent) ->
#chain{content=
@@ -1880,7 +1880,7 @@ allowed_content2(extension,simpleContent) ->
#chain{content=
[#alternative{content=
[{attribute,{1,1}},{attributeGroup,{1,1}}],
- occurance={0,unbounded}},
+ occurrence={0,unbounded}},
{anyAttribute,{0,1}}]}]};
allowed_content2(extension,complexContent) ->
#chain{content=
@@ -1889,19 +1889,19 @@ allowed_content2(extension,complexContent) ->
[#alternative{content=
[{group,{1,1}},{all,{1,1}},{choice,{1,1}},
{sequence,{1,1}}],
- occurance={0,1}},
+ occurrence={0,1}},
#chain{content=
[#alternative{content=
[{attribute,{1,1}},
{attributeGroup,{1,1}}],
- occurance={0,1}},
+ occurrence={0,1}},
{anyAttribute,{0,1}}]}]}]}.
set_occurance(Ch = #chain{},Occ) ->
- Ch#chain{occurance=Occ};
+ Ch#chain{occurrence=Occ};
set_occurance(Alt = #alternative{},Occ) ->
- Alt#alternative{occurance=Occ};
+ Alt#alternative{occurrence=Occ};
set_occurance({Name,_},Occ) when is_atom(Name) ->
{Name,Occ}.
%% set_occurance(CM,_) ->
@@ -1992,7 +1992,7 @@ save_namespace_definition(NameSpace,
checked_namespace_nodes=CNS}) ->
%% 1) Have to find a matching namespace in the global list for
%% this schema, and get the associated prefix. 2) Then check
- %% whether a schema with this prefix - namespace combinaton
+ %% whether a schema with this prefix - namespace combination
%% already is checked, if so do nothing. 3a) If this namespace is
%% checked but with another prefix only add the prefix - namespace
%% pair to the checked namespace list. 3b) Otherwise add the
@@ -2275,7 +2275,7 @@ set_num_el(S=#xsd_state{},#xsd_state{num_el=I}) ->
S#xsd_state{num_el=I}.
-occurance(El=#xmlElement{attributes=Atts},{Min,Max},S) ->
+occurrence(El=#xmlElement{attributes=Atts},{Min,Max},S) ->
AttVal=fun(#xmlAttribute{value=V},Sin) ->
case catch mk_int_or_atom(V) of
{'EXIT',_} ->
@@ -2470,7 +2470,7 @@ check_element_type(XML=[#xmlElement{}|_],[{all,{CM,Occ}}|_CMRest],
%% 3 often. CMEL may be ((simpleType | complexType)?, (unique | key | keyref)*))
check_element_type(XML=[XMLEl=#xmlElement{}|_],[CMEl|CMRest],Env,
Block,S,Checked) ->
- %% Three possible releations between XMLEl - CMEl:
+ %% Three possible relations between XMLEl - CMEl:
%% (1) XMLEl matches CMEl.
%% (2) XMLEl don't matches CMEl and CMEl is optional.
%% (3) XMLEl don't matches CMEl, CMEl mandatory, - error.
@@ -2563,12 +2563,12 @@ check_element_type(XML=[XMLEl=#xmlElement{name=Name}|RestXML],
CMEl=#schema_element{name=CMName,type=Type},
Env,Block,S,Checked) ->
ElName = mk_EII_QName(Name,XMLEl,S#xsd_state{scope=element(2,CMName)}),
- {Min,Max} = CMEl#schema_element.occurance,
+ {Min,Max} = CMEl#schema_element.occurrence,
case cmp_name(ElName,CMName,S) of %% substitutionGroup
true when S#xsd_state.num_el =< Max ->
S1 = id_constraints(CMEl,XMLEl,S),
%% If CMEl element has a substitutionGroup we have to
- %% switch to the rigth element and type here.
+ %% switch to the right element and type here.
{CMEl2,Type2,S2} =
if
ElName =:= CMName ->
@@ -2705,7 +2705,7 @@ check_element_type(XML=[E=#xmlElement{name=Name}|Rest],
end;
check_element_type([],CM,_Env,_Block,S,Checked) ->
%% #schema_complex_type, any, #schema_group, anyType and lists are
- %% catched above.
+ %% caught above.
case CM of
#schema_simple_type{} ->
{NewVal,S2} = check_type(CM,[],unapplied,S),
@@ -2777,7 +2777,7 @@ check_sequence(Seq=[_InstEl=#xmlElement{}|_],[El|Els],Occ={_Min,_Max},Env,S,Chec
%% Err;
{Ret,UnValRest,S3} ->
%% must also take care of more elements of same name
- %% decrease occurance in El for the optional measurements
+ %% decrease occurrence in El for the optional measurements
%% when Seq is empty.
check_sequence(UnValRest,[decrease_occurance(El)|Els],Occ,Env,
count_num_el(set_num_el(S3,S2)),
@@ -2835,7 +2835,7 @@ check_choice(XML,[],{0,_},_,S,Checked) ->
%% Choice is optional
{Checked,XML,set_num_el(S,0)};
check_choice(XML,[],_,_,S,Checked) ->
- %% Choice has already matched something, the rest is for somthing
+ %% Choice has already matched something, the rest is for something
%% else to match.
case S#xsd_state.num_el > 0 of
true ->
@@ -3965,7 +3965,7 @@ resolve(E,S) ->
load_object(E,S).
%% explicit_type checks whether the instance element is of an explicit
-%% type pointed out by xsi:type. A type refernced by xsi:type must be
+%% type pointed out by xsi:type. A type referenced by xsi:type must be
%% the same as, or derived from the instance element's type. Concluded
%% from 3.4.6 section "Schema Component Constraint: Type Derivation OK
%% (Complex)".
@@ -5080,7 +5080,7 @@ load_redefine_object({Kind,Name},S) ->
load_object({element,{QN,Occ={Min,_}}},S) when is_integer(Min) ->
case load_object({element,QN},S) of
- {SE=#schema_element{},S1} -> {SE#schema_element{occurance=Occ},S1};
+ {SE=#schema_element{},S1} -> {SE#schema_element{occurrence=Occ},S1};
Other -> Other
end;
load_object({group,{QN,_Occ={Min,_}}},S) when is_integer(Min) ->
@@ -5439,11 +5439,11 @@ format_error({unvalidated_rest,UR}) ->
format_error({no_schemas_provided}) ->
"Schema: Validator found no schema. A schema must be provided for validation.";
format_error({internal_error,Reason}) ->
- io_lib:format("An error occured that was unforeseen, due to ~p.",[Reason]);
+ io_lib:format("An error occurred that was unforeseen, due to ~p.",[Reason]);
format_error({internal_error,Reason,Info}) ->
- io_lib:format("An error occured that was unforeseen, due to ~p: ~p.",[Reason,Info]);
+ io_lib:format("An error occurred that was unforeseen, due to ~p: ~p.",[Reason,Info]);
format_error({internal_error,Function,Info1,Info2}) ->
- io_lib:format("An internal error occured in function ~p with args: ~p,~p.",[Function,Info1,Info2]);
+ io_lib:format("An internal error occurred in function ~p with args: ~p,~p.",[Function,Info1,Info2]);
format_error({illegal_content,Reason,Kind}) ->
io_lib:format("Schema: The schema violates the content model allowed for schemas.~nReason: ~p,~nkind of schema element: ~p.",[Reason,Kind]);
format_error({no_match,Kind}) ->
@@ -5473,7 +5473,7 @@ format_error({no_element_expected_in_group,XML}) ->
format_error({element_bad_match,E,Any,_Env}) ->
io_lib:format("XML: XML element ~p didn't match into the namespace of schema type any ~p.",[E,Any]);
format_error({match_failure,_XML,_CM,_S}) ->
- "XML: A combination of XML element(s) and schema definitions that is not known has occured. The implementation doesn't support this structure.";
+ "XML: A combination of XML element(s) and schema definitions that is not known has occurred. The implementation doesn't support this structure.";
format_error({cannot_contain_text,_XMLTxt,CMEl}) ->
io_lib:format("XML: The schema structure: ~p doesn't allow text",[CMEl]);
format_error({missing_mandatory_elements,MandatoryEls}) ->
@@ -5489,7 +5489,7 @@ format_error({element_not_in_all,ElName,E,_CM}) ->
format_error({missing_mandatory_elements_in_all,MandatoryEls}) ->
io_lib:format("XML: The schema elements ~p were missed in the XML file.",[MandatoryEls]);
format_error({failed_validating,E,Any}) ->
- io_lib:format("XML: The element ~p at location ~p failed validation. It should hav been matched by an any schema element ~p",[E#xmlElement.name,error_path(E,undefined),Any]);
+ io_lib:format("XML: The element ~p at location ~p failed validation. It should have been matched by an any schema element ~p",[E#xmlElement.name,error_path(E,undefined),Any]);
format_error({schemaLocation_list_failure,Paths}) ->
io_lib:format("XML: schemaLocation values consists of one or more pairs of URI references, separated by white space. The first is a namespace name the second a reference to a schema: ~p.",[Paths]);
format_error({element_content_not_nil,XMLEl}) ->
@@ -5502,7 +5502,7 @@ format_error({default_and_fixed_attributes_mutual_exclusive,
Name,Default,Fix}) ->
io_lib:format("Schema: It is an error in the schema to assign values for both default and fix for an attribute. Attribute: ~p, default: ~p, fix: ~p.",[Name,Default,Fix]);
format_error({schema_error,unexpected_object,_SA,_Err}) ->
- "Schema: An unforeseen error case occured, maybee due to an unimplemented feature.";
+ "Schema: An unforeseen error case occurred, maybe due to an unimplemented feature.";
format_error({attribute_not_defined_in_schema,Name}) ->
io_lib:format("XML: The attribute ~p is not defined in the provided schema.",[Name]);
format_error({disallowed_namespace,Namespace,NS,Name}) ->
@@ -5530,9 +5530,9 @@ format_error({key_value_not_unique,KS}) ->
format_error({keyref_missed_matching_key,Refer}) ->
io_lib:format("Schema: This keyref had no matching key ~p.",[Refer]);
format_error({keyref_unexpected_object,_Other}) ->
- "Schema: An unforeseen error case occured, unknown failure cause.";
+ "Schema: An unforeseen error case occurred, unknown failure cause.";
format_error({cardinality_of_fields_not_equal,KR,K}) ->
- io_lib:format("Schema: keyref and the corresponding key must have same cardinality of their fields. Missmatch in this case keyref: ~p, key: ~p.",[KR,K]);
+ io_lib:format("Schema: keyref and the corresponding key must have same cardinality of their fields. Mismatch in this case keyref: ~p, key: ~p.",[KR,K]);
format_error({could_not_load_keyref,Name}) ->
io_lib:format("Schema: The schema didn't define a keyref with the name ~p.",[Name]);
format_error({reference_undeclared,Kind,Ref}) ->
@@ -5542,7 +5542,7 @@ format_error({cyclic_substitutionGroup,SGs}) ->
format_error({substitutionGroup_error,Head,SG}) ->
io_lib:format("Schema: Either of substitutionGroup members ~p or ~p is not defined in the provided schema.",[Head,SG]);
format_error({cyclic_definition,CA}) ->
- io_lib:format("Schema: A forbidden cicular definition was detected ~p.",[CA]);
+ io_lib:format("Schema: A forbidden circular definition was detected ~p.",[CA]);
format_error({type_of_element_not_derived,MemT,HeadT}) ->
io_lib:format("Schema: Type in substitutionGroup members should be simpleType or complexType. In this case ~p and ~p were found.",[MemT, HeadT]);
format_error({derivation_blocked,BlockTag,Derivation}) ->
diff --git a/lib/xmerl/src/xmerl_xsd_type.erl b/lib/xmerl/src/xmerl_xsd_type.erl
index 8b73c3af3b..af4ede8ba4 100644
--- a/lib/xmerl/src/xmerl_xsd_type.erl
+++ b/lib/xmerl/src/xmerl_xsd_type.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1499,7 +1499,7 @@ get_digit([],_,[],_Str) ->
get_digit([],_,_,Str) ->
{"0",Str};
get_digit(_,_,_,Str) ->
- %% this matches both the case when reaching another delimeter and
+ %% this matches both the case when reaching another delimiter and
%% when the string already are emptied.
{"0",Str}.
diff --git a/lib/xmerl/test/Makefile b/lib/xmerl/test/Makefile
index b90ca772af..97180d8051 100644
--- a/lib/xmerl/test/Makefile
+++ b/lib/xmerl/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2004-2021. All Rights Reserved.
+# Copyright Ericsson AB 2004-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -86,13 +86,14 @@ RELSYSDIR = $(RELEASE_PATH)/xmerl_test
# ----------------------------------------------------
ERL_COMPILE_FLAGS +=
+ERL_COMPILE_FLAGS := $(filter-out +deterministic,$(ERL_COMPILE_FLAGS))
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-tests debug opt: xmerl_test.erl
+tests $(TYPES): xmerl_test.erl
info:
@echo "HRL_FILES: $(HRL_FILES)"
diff --git a/lib/xmerl/test/xmerl_SUITE.erl b/lib/xmerl/test/xmerl_SUITE.erl
index bc133558d6..360c675d26 100644
--- a/lib/xmerl/test/xmerl_SUITE.erl
+++ b/lib/xmerl/test/xmerl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -445,7 +445,7 @@ generate_heading_col(N) ->
%% ticket_5998
%%
%% A Kleene Closure child in a sequence consumed all following
-%% childs. This problem has been fixed.
+%% child's. This problem has been fixed.
%%
ticket_5998(Config) ->
DataDir = datadir(Config),
@@ -477,7 +477,7 @@ ticket_5998(Config) ->
%% ticket_7211
%%
%% A Kleene Closure child in a sequence consumed all following
-%% childs. This problem has been fixed.
+%% child's. This problem has been fixed.
%%
ticket_7211(Config) ->
DataDir = datadir(Config),
@@ -507,7 +507,7 @@ ticket_7211(Config) ->
%% ticket_7214
%%
%% Now validating xhtml1-transitional.dtd.
-%% A certain contentspec with a succeding choice, that didn't match
+%% A certain contentspec with a succeeding choice, that didn't match
%% all content, followed by other child elements caused a
%% failure. This is now corrected.
%%
@@ -607,7 +607,7 @@ ticket_9457_cont(Continue, Exception, GlobalState) ->
end.
-%% Test that comments are handled correct whith
+%% Test that comments are handled correct with
ticket_9664_schema(Config) ->
{E, _} = xmerl_scan:file(datadir_join(Config,[misc,"ticket_9664_schema.xml"]),[]),
{ok, S} = xmerl_xsd:process_schema(datadir_join(Config,[misc,"motorcycles.xsd"])),
@@ -620,7 +620,7 @@ ticket_9664_schema(Config) ->
{validation, schema}]),
ok.
-%% Test that comments are handled correct whith
+%% Test that comments are handled correct with
ticket_9664_dtd(Config) ->
{E, _} = xmerl_scan:file(datadir_join(Config,[misc,"ticket_9664_dtd.xml"]),[]),
{E, _} = xmerl_scan:file(datadir_join(Config,[misc,"ticket_9664_dtd.xml"]),[{validation, true}]),
diff --git a/lib/xmerl/test/xmerl_sax_std_SUITE.erl b/lib/xmerl/test/xmerl_sax_std_SUITE.erl
index c1e78887c6..54fee16317 100644
--- a/lib/xmerl/test/xmerl_sax_std_SUITE.erl
+++ b/lib/xmerl/test/xmerl_sax_std_SUITE.erl
@@ -1,7 +1,7 @@
%%----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -3183,7 +3183,7 @@ end_per_testcase(_Func,_Config) ->
%% Sections: 3.1 [40]
%% Output: valid/sa/out/011.xml
%% Description:
-%% Test demonstrates mutliple Attibutes within the Start-tag.
+%% Test demonstrates multiple Attributes within the Start-tag.
'valid-sa-011'(Config) ->
file:set_cwd(datadir(Config)),
Path = filename:join([datadir(Config),"xmltest","valid/sa/011.xml"]),
@@ -3343,7 +3343,7 @@ end_per_testcase(_Func,_Config) ->
%% Output: valid/sa/out/020.xml
%% Description:
%% Test demonstractes that CDATA sections are valid element content and that
-%% everyting between the CDStart and CDEnd is recognized as character data not
+%% everything between the CDStart and CDEnd is recognized as character data not
%% markup.
'valid-sa-020'(Config) ->
file:set_cwd(datadir(Config)),
@@ -3486,7 +3486,7 @@ end_per_testcase(_Func,_Config) ->
%% Sections: 2.8 [24]
%% Output: valid/sa/out/028.xml
%% Description:
-%% Test demonstrates a valid prolog that uses double quotes as delimeters
+%% Test demonstrates a valid prolog that uses double quotes as delimiters
%% around the VersionNum.
'valid-sa-028'(Config) ->
file:set_cwd(datadir(Config)),
@@ -3504,7 +3504,7 @@ end_per_testcase(_Func,_Config) ->
%% Sections: 2.8 [24]
%% Output: valid/sa/out/029.xml
%% Description:
-%% Test demonstrates a valid prolog that uses single quotes as delimters
+%% Test demonstrates a valid prolog that uses single quotes as delimiter
%% around the VersionNum.
'valid-sa-029'(Config) ->
file:set_cwd(datadir(Config)),
@@ -4675,7 +4675,7 @@ end_per_testcase(_Func,_Config) ->
%% Sections: 2.3 2.10
%% Output: valid/sa/out/092.xml
%% Description:
-%% Test demostrates that extra whitespace is normalized into a single space
+%% Test demonstrates that extra whitespace is normalized into a single space
%% character.
'valid-sa-092'(Config) ->
file:set_cwd(datadir(Config)),
@@ -5450,7 +5450,7 @@ end_per_testcase(_Func,_Config) ->
%% Entities: both
%% Output: valid/not-sa/out/015.xml
%% Description:
-%% Test demonstrates the use of the conditonal section IGNORE the will ignore
+%% Test demonstrates the use of the conditional section IGNORE the will ignore
%% its content from being part of the DTD. The keyword is a parameter-entity
%% reference.
'valid-not-sa-015'(Config) ->
@@ -5697,7 +5697,7 @@ end_per_testcase(_Func,_Config) ->
%% Entities: both
%% Output: valid/not-sa/out/029.xml
%% Description:
-%% Test demonstrates the use of the conditonal section IGNORE the will ignore
+%% Test demonstrates the use of the conditional section IGNORE the will ignore
%% its content from being used.
'valid-not-sa-029'(Config) ->
file:set_cwd(datadir(Config)),
@@ -5716,7 +5716,7 @@ end_per_testcase(_Func,_Config) ->
%% Entities: both
%% Output: valid/not-sa/out/030.xml
%% Description:
-%% Test demonstrates the use of the conditonal section IGNORE the will ignore
+%% Test demonstrates the use of the conditional section IGNORE the will ignore
%% its content from being used.
'valid-not-sa-030'(Config) ->
file:set_cwd(datadir(Config)),
@@ -7446,7 +7446,7 @@ optional21(Config) ->
%% Description:
%% Tests the Element Valid VC (clause 2) for one instance of "children"
%% content model, providing no children where one or more are required (an
-%% eigth construction of that model).
+%% eighth construction of that model).
optional22(Config) ->
file:set_cwd(datadir(Config)),
Path = filename:join([datadir(Config),"sun","invalid/optional22.xml"]),
@@ -8910,7 +8910,7 @@ uri01(Config) ->
%% Entities: parameter
%% Description:
%% Valid doctypedecl with EXternalID as Enternal Entity. The external entity
-%% contains a parameter entity reference and condtional sections.
+%% contains a parameter entity reference and conditional sections.
'o-p31pass2'(Config) ->
file:set_cwd(datadir(Config)),
Path = filename:join([datadir(Config),"oasis","p31pass2.xml"]),
@@ -9812,7 +9812,7 @@ uri01(Config) ->
%% Type: invalid
%% Sections: 2.9 [32]
%% Description:
-%% Double quotes can be used as delimeters for the value of a Standalone
+%% Double quotes can be used as delimiters for the value of a Standalone
%% Document Declaration.
'o-p32pass1'(Config) ->
file:set_cwd(datadir(Config)),
@@ -9827,7 +9827,7 @@ uri01(Config) ->
%% Type: invalid
%% Sections: 2.9 [32]
%% Description:
-%% Single quotes can be used as delimeters for the value of a Standalone
+%% Single quotes can be used as delimiters for the value of a Standalone
%% Document Declaration.
'o-p32pass2'(Config) ->
file:set_cwd(datadir(Config)),
@@ -12578,7 +12578,7 @@ uri01(Config) ->
%% Type: not-wf
%% Sections: 3.3 [53]
%% Description:
-%% name is requried
+%% name is required
'o-p53fail5'(Config) ->
file:set_cwd(datadir(Config)),
Path = filename:join([datadir(Config),"oasis","p53fail5.xml"]),
@@ -12662,7 +12662,7 @@ uri01(Config) ->
%% Type: not-wf
%% Sections: 3.3.1 [56]
%% Description:
-%% no ENTITYS type - types must be upper case
+%% no ENTITIES type - types must be upper case
'o-p56fail4'(Config) ->
file:set_cwd(datadir(Config)),
Path = filename:join([datadir(Config),"oasis","p56fail4.xml"]),
@@ -27736,7 +27736,7 @@ uri01(Config) ->
%% Sections: 3.3.1
%% Output: valid/P58/out/ibm58v01.xml
%% Description:
-%% Tests NotationType for P58. It shows different patterns fro the NOTATION
+%% Tests NotationType for P58. It shows different patterns from the NOTATION
%% attribute "attr".
'ibm-valid-P58-ibm58v01'(Config) ->
file:set_cwd(datadir(Config)),
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 562e38ebc0..e3edce14f5 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.3.28
+XMERL_VSN = 1.3.31
diff --git a/make/app_targets.mk b/make/app_targets.mk
index 468bb6de3c..2bf1421f80 100644
--- a/make/app_targets.mk
+++ b/make/app_targets.mk
@@ -23,7 +23,8 @@ APPLICATION ?= $(basename $(notdir $(PWD)))
.PHONY: test info gclean dialyzer dialyzer_plt dclean
test:
- $(ERL_TOP)/make/test_target_script.sh $(ERL_TOP)
+ TEST_NEEDS_RELEASE=$(TEST_NEEDS_RELEASE) TYPE=$(TYPE) \
+ $(ERL_TOP)/make/test_target_script.sh $(ERL_TOP)
info:
@echo "$(APPLICATION)_VSN: $(VSN)"
diff --git a/lib/common_test/priv/auxdir/config.guess b/make/autoconf/config.guess
index 1972fda8eb..1972fda8eb 100755
--- a/lib/common_test/priv/auxdir/config.guess
+++ b/make/autoconf/config.guess
diff --git a/lib/common_test/priv/auxdir/config.sub b/make/autoconf/config.sub
index 63c1f1c8b5..63c1f1c8b5 100755
--- a/lib/common_test/priv/auxdir/config.sub
+++ b/make/autoconf/config.sub
diff --git a/lib/common_test/priv/auxdir/install-sh b/make/autoconf/install-sh
index ec298b5374..ec298b5374 100755
--- a/lib/common_test/priv/auxdir/install-sh
+++ b/make/autoconf/install-sh
diff --git a/erts/aclocal.m4 b/make/autoconf/otp.m4
index c50c05f1c6..98b8ea5f61 100644
--- a/erts/aclocal.m4
+++ b/make/autoconf/otp.m4
@@ -1,7 +1,7 @@
-dnl
+dnl -*-Autoconf-*-
dnl %CopyrightBegin%
dnl
-dnl Copyright Ericsson AB 1998-2022. All Rights Reserved.
+dnl Copyright Ericsson AB 1998-2023. All Rights Reserved.
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
@@ -19,13 +19,69 @@ dnl %CopyrightEnd%
dnl
dnl
-dnl aclocal.m4
+dnl otp.m4
+dnl
+dnl Local macros that can be used in `configure.ac` files in OTP. To use
+dnl any of the macros your `configure.ac` file should include this file
+dnl using `m4_include([otp.m4])` after AC_INIT.
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 The Local Macros which could be part of autoconf are prefixed LM_,
+dnl macros specific dnl to the Erlang system are prefixed ERL_ (this is
+dnl not always consistently made...).
dnl
+AC_DEFUN([ERL_CANONICAL_SYSTEM_TYPE],
+[
+ AC_CANONICAL_HOST
+ # Adjust for local legacy windows hack...
+ AS_CASE([$host],
+ [local-*-windows],
+ [
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ])
+
+ AC_CANONICAL_BUILD
+ # Adjust for local legacy windows hack...
+ AS_CASE([$build],
+ [local-*-windows],
+ [
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ])
+
+ AC_CANONICAL_TARGET
+ # Adjust for local legacy windows hack...
+ AS_CASE([$target],
+ [local-*-windows],
+ [
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ])
+
+ AS_IF([test "$cross_compiling" = "yes" -a "$build" = "$host"],
+ [AC_MSG_ERROR([
+ Cross compiling with the same canonicalized 'host' value
+ as the canonicalized 'build' value.
+
+ We are cross compiling since the '--host=$host_alias'
+ and the '--build=$build_alias' arguments differ. When
+ cross compiling Erlang/OTP, also the canonicalized values of
+ the '--build' and the '--host' arguments *must* differ. The
+ canonicalized values of these arguments however both equals:
+ $host
+
+ You can check the canonical value by passing a value as
+ argument to the 'make/autoconf/config.sub' script.
+ ])])
+])
+
AC_DEFUN(LM_PRECIOUS_VARS,
[
@@ -90,14 +146,19 @@ fi
AC_DEFUN(LM_CHECK_GETCONF,
[
-if test "$cross_compiling" != "yes"; then
+AS_IF(
+ [test "$cross_compiling" != "yes"],
+ [
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
+ AS_IF(
+ [test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""],
+ [
+ dnl We should perhaps give up if we haven't 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
@@ -107,8 +168,8 @@ else
prfx="$erl_xcomp_sysroot"
AC_PATH_TOOL([GETCONF], [getconf], [false],
["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"])
- fi
-fi
+ ])
+ ])
])
dnl ----------------------------------------------------------------------
@@ -235,7 +296,7 @@ AC_DEFUN(LM_FIND_EMU_CC,
[AC_CACHE_CHECK(for a compiler that handles jumptables,
ac_cv_prog_emu_cc,
[
-AC_TRY_COMPILE([],[
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
#if defined(__clang_major__) && __clang_major__ >= 3
/* clang 3.x or later is fine */
#elif defined(__llvm__)
@@ -254,7 +315,7 @@ lbl1:
return 1;
lbl2:
return 2;
-],ac_cv_prog_emu_cc="$CC",ac_cv_prog_emu_cc=no)
+]])],[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
@@ -274,14 +335,15 @@ if test "$ac_cv_prog_emu_cc" = no; then
done
fi
-if test "$ac_cv_prog_emu_cc" != no; then
+AS_IF([test "$ac_cv_prog_emu_cc" != no],
+ [
save_CC="$CC"
save_CFLAGS=$CFLAGS
save_CPPFLAGS=$CPPFLAGS
CC="$ac_cv_prog_emu_cc"
CFLAGS=""
CPPFLAGS=""
- AC_TRY_COMPILE([],[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
#if defined(__clang_major__) && __clang_major__ >= 3
/* clang 3.x or later is fine */
#elif defined(__llvm__)
@@ -300,11 +362,11 @@ if test "$ac_cv_prog_emu_cc" != no; then
return 1;
lbl2:
return 2;
- ],ac_cv_prog_emu_cc="$CC",ac_cv_prog_emu_cc=no)
+ ]])],[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])
@@ -383,9 +445,7 @@ 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))
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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,[],
@@ -405,31 +465,28 @@ 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)
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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
+AS_IF(
+ [test ${ac_cv_decl_inaddr_loopback} = no],
+ [
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))
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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" )
+ AS_IF(
+ [test "${ac_cv_decl_inaddr_loopback_rpc}" = "yes"],
+ [
AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[],
- [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;;
- * )
+ [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))
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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,[],
@@ -438,9 +495,9 @@ if test ${ac_cv_decl_inaddr_loopback} = no; then
# 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
+ esac
+ ])
+ ])
])
@@ -454,9 +511,8 @@ 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))
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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
@@ -470,35 +526,35 @@ 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 (early linux used in_addr6 instead 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>
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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)
+#endif]], [[struct in6_addr a6; struct sockaddr_in6 s6;]])],[ok_so_far=yes],[ok_so_far=no])
-if test $ok_so_far = yes; then
+AS_IF(
+ [test $ok_so_far = yes],
+ [
ac_cv_sys_ipv6_support=yes
-else
- AC_TRY_COMPILE([#include <sys/types.h>
+ ],
+ [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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
+#endif]], [[struct in_addr6 a6; struct sockaddr_in6 s6;]])],[ac_cv_sys_ipv6_support=in_addr6],[ac_cv_sys_ipv6_support=no])
+ ])
])dnl
dnl
@@ -533,7 +589,8 @@ dnl
AC_DEFUN(LM_SYS_MULTICAST,
[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support,
-[AC_EGREP_CPP(^yes$,
+[
+AC_EGREP_CPP(^yes$,
[#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -559,9 +616,8 @@ 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)])
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#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])
@@ -586,10 +642,10 @@ 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
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
+$3]], [[$2
char *c = (char *)$1;
-], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")])
+]])],[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])
@@ -695,7 +751,7 @@ case $ac_cv_c_double_middle_endian in
[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 # AC_C_DOUBLE_MIDDLE_ENDIAN
AC_DEFUN(ERL_MONOTONIC_CLOCK,
@@ -759,57 +815,52 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK,
AC_CACHE_CHECK([for clock_gettime(CLOCK_MONOTONIC_RAW, _)], erl_cv_clock_gettime_monotonic_raw,
[
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <time.h>
$trust_test
- ],
- [
+ ]], [[
struct timespec ts;
long long result;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
result = ((long long) ts.tv_sec) * 1000000000LL +
((long long) ts.tv_nsec);
- ],
- erl_cv_clock_gettime_monotonic_raw=yes,
- erl_cv_clock_gettime_monotonic_raw=no)
+ ]])],[erl_cv_clock_gettime_monotonic_raw=yes],[erl_cv_clock_gettime_monotonic_raw=no])
])
AC_CACHE_CHECK([for clock_gettime() with ${check_msg}monotonic clock type], erl_cv_clock_gettime_monotonic_$1,
[
for clock_type in $prefer_resolution_clock_gettime_monotonic $default_resolution_clock_gettime_monotonic $high_resolution_clock_gettime_monotonic $low_resolution_clock_gettime_monotonic; do
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <time.h>
$trust_test
- ],
- [
+ ]], [[
struct timespec ts;
long long result;
clock_gettime($clock_type,&ts);
result = ((long long) ts.tv_sec) * 1000000000LL +
((long long) ts.tv_nsec);
- ],
- erl_cv_clock_gettime_monotonic_$1=$clock_type,
- erl_cv_clock_gettime_monotonic_$1=no)
+ ]])],[erl_cv_clock_gettime_monotonic_$1=$clock_type],[erl_cv_clock_gettime_monotonic_$1=no])
test $erl_cv_clock_gettime_monotonic_$1 = no || break
done
])
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
+ AS_IF(
+ [test "$LD_MAY_BE_WEAK" != "no"],
+ [
AC_CHECK_FUNCS([clock_get_attributes gethrtime])
- else
+ ],
+ [
AC_CHECK_FUNCS([clock_getres clock_get_attributes gethrtime])
- fi
-
+ ])
AC_CACHE_CHECK([for mach clock_get_time() with monotonic clock type], erl_cv_mach_clock_get_time_monotonic,
[
- AC_TRY_COMPILE([
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <mach/clock.h>
#include <mach/mach.h>
- ],
- [
+ ]], [[
kern_return_t res;
clock_serv_t clk_srv;
mach_timespec_t time_spec;
@@ -817,9 +868,7 @@ $trust_test
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clk_srv);
res = clock_get_time(clk_srv, &time_spec);
mach_port_deallocate(mach_task_self(), clk_srv);
- ],
- erl_cv_mach_clock_get_time_monotonic=yes,
- erl_cv_mach_clock_get_time_monotonic=no)
+ ]])],[erl_cv_mach_clock_get_time_monotonic=yes],[erl_cv_mach_clock_get_time_monotonic=no])
])
erl_corrected_monotonic_clock=no
@@ -924,40 +973,35 @@ AC_DEFUN(ERL_WALL_CLOCK,
AC_CACHE_CHECK([for clock_gettime() with ${check_msg}wall clock type], erl_cv_clock_gettime_wall_$1,
[
for clock_type in $prefer_resolution_clock_gettime_wall $default_resolution_clock_gettime_wall $high_resolution_clock_gettime_wall $low_resolution_clock_gettime_wall; do
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <time.h>
$trust_test
- ],
- [
+ ]], [[
struct timespec ts;
long long result;
clock_gettime($clock_type,&ts);
result = ((long long) ts.tv_sec) * 1000000000LL +
((long long) ts.tv_nsec);
- ],
- erl_cv_clock_gettime_wall_$1=$clock_type,
- erl_cv_clock_gettime_wall_$1=no)
+ ]])],[erl_cv_clock_gettime_wall_$1=$clock_type],[erl_cv_clock_gettime_wall_$1=no])
test $erl_cv_clock_gettime_wall_$1 = no || break
done
])
LIBS="$save_LIBS"
- if test "$LD_MAY_BE_WEAK" != "no"; then
- check_for_clock_getres=
- else
- check_for_clock_getres=clock_getres
- fi
+ AS_IF([test "$LD_MAY_BE_WEAK" = "no"],
+ [
+ AC_CHECK_FUNCS([clock_getres])
+ ])
- AC_CHECK_FUNCS([$check_for_clock_getres clock_get_attributes gettimeofday])
+ AC_CHECK_FUNCS([clock_get_attributes gettimeofday])
AC_CACHE_CHECK([for mach clock_get_time() with wall clock type], erl_cv_mach_clock_get_time_wall,
[
- AC_TRY_COMPILE([
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <mach/clock.h>
#include <mach/mach.h>
- ],
- [
+ ]], [[
kern_return_t res;
clock_serv_t clk_srv;
mach_timespec_t time_spec;
@@ -965,9 +1009,7 @@ $trust_test
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk_srv);
res = clock_get_time(clk_srv, &time_spec);
mach_port_deallocate(mach_task_self(), clk_srv);
- ],
- erl_cv_mach_clock_get_time_wall=yes,
- erl_cv_mach_clock_get_time_wall=no)
+ ]])],[erl_cv_mach_clock_get_time_wall=yes],[erl_cv_mach_clock_get_time_wall=no])
])
erl_wall_clock_lib=
@@ -1019,13 +1061,16 @@ NEED_NPTL_PTHREAD_H=no
dnl win32?
AC_MSG_CHECKING([for native win32 threads])
-if test "X$host_os" = "Xwin32"; then
+AS_IF(
+ [test "X$host_os" = "Xwin32"],
+ [
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=
@@ -1038,42 +1083,50 @@ dnl The usual pthread lib...
AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread")
dnl Very old versions of FreeBSD have 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
+ AS_IF([test "x$THR_LIBS" = "x"],
+ [
+ AC_CHECK_LIB([c_r], [pthread_create], [THR_LIBS="-lc_r"])
+ ])
dnl QNX has pthreads in standard C library
- if test "x$THR_LIBS" = "x"; then
- AC_CHECK_FUNC(pthread_create, THR_LIBS="none_needed")
- fi
+ AS_IF([test "x$THR_LIBS" = "x"],
+ [
+ AC_CHECK_FUNC([pthread_create], [THR_LIBS="none_needed"])
+ ])
dnl On ofs1 the '-pthread' switch should be used
- if test "x$THR_LIBS" = "x"; then
+ AS_IF(
+ [test "x$THR_LIBS" = "x"],
+ [
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"])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#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
+ AS_IF(
+ [test "x$THR_LIBS" != "x"],
+ [
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ AS_CASE(
+ [$host_os],
+ [solaris*],
+ [
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ],
+ [linux*],
+ [
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
LM_CHECK_GETCONF
@@ -1098,13 +1151,17 @@ dnl On ofs1 the '-pthread' switch should be used
nptl=yes
AC_MSG_WARN([result yes guessed because of cross compilation])
fi
- if test $nptl = yes; then
+ AS_IF(
+ [test $nptl = yes],
+ [
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- AC_CHECK_HEADER(nptl/pthread.h,
+ AC_CHECK_HEADER([nptl/pthread.h],
[need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes])
- if test $need_nptl_incldir = yes; then
+ AS_IF(
+ [test $need_nptl_incldir = yes],
+ [
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -1125,8 +1182,8 @@ dnl On ofs1 the '-pthread' switch should be used
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- AC_CHECK_HEADER($dir/nptl/pthread.h,
- nptl_incldir=$dir/nptl)
+ 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
@@ -1135,11 +1192,9 @@ dnl On ofs1 the '-pthread' switch should be used
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).
@@ -1162,8 +1217,8 @@ dnl On ofs1 the '-pthread' switch should be used
dnl restore CPPFLAGS
CPPFLAGS=$saved_cppflags
- fi
-fi
+ ])
+ ])
])
@@ -1220,17 +1275,17 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OP__,
AC_CACHE_CHECK([for 32-bit $1()], ethr_cv_32bit_$1,
[
ethr_cv_32bit_$1=no
- AC_TRY_LINK([], [$atomic32_call], [ethr_cv_32bit_$1=yes])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[$atomic32_call]])],[ethr_cv_32bit_$1=yes],[])
])
AC_CACHE_CHECK([for 64-bit $1()], ethr_cv_64bit_$1,
[
ethr_cv_64bit_$1=no
- AC_TRY_LINK([], [$atomic64_call], [ethr_cv_64bit_$1=yes])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[$atomic64_call]])],[ethr_cv_64bit_$1=yes],[])
])
AC_CACHE_CHECK([for 128-bit $1()], ethr_cv_128bit_$1,
[
ethr_cv_128bit_$1=no
- AC_TRY_LINK([], [$atomic128_call], [ethr_cv_128bit_$1=yes])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[$atomic128_call]])],[ethr_cv_128bit_$1=yes],[])
])
case $ethr_cv_128bit_$1-$ethr_cv_64bit_$1-$ethr_cv_32bit_$1 in
@@ -1319,9 +1374,7 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
AC_CACHE_CHECK([for a working __sync_synchronize()], ethr_cv___sync_synchronize,
[
ethr_cv___sync_synchronize=no
- AC_TRY_LINK([],
- [ __sync_synchronize(); ],
- [ethr_cv___sync_synchronize=yes])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ __sync_synchronize(); ]])],[ethr_cv___sync_synchronize=yes],[])
if test $ethr_cv___sync_synchronize = yes; then
#
# Old gcc versions on at least x86 have a buggy
@@ -1362,16 +1415,19 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
ethr_arm_dbm_sy_instr_val=0
ethr_arm_dbm_st_instr_val=0
ethr_arm_dbm_ld_instr_val=0
- case "$GCC-$host_cpu" in
- yes-arm*|yes-aarch*)
+ ethr_arm_isb_sy_instr_val=0
+ ethr_arm_dc_cvau_instr_val=0
+ ethr_arm_ic_ivau_instr_val=0
+ AS_CASE(
+ ["$GCC-$host_cpu"],
+ [yes-arm*|yes-aarch*],
+ [
AC_CACHE_CHECK([for ARM 'dmb sy' instruction], ethr_cv_arm_dbm_sy_instr,
[
ethr_cv_arm_dbm_sy_instr=no
- AC_TRY_LINK([],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
__asm__ __volatile__("dmb sy" : : : "memory");
- ],
- [ethr_cv_arm_dbm_sy_instr=yes])
+ ]])],[ethr_cv_arm_dbm_sy_instr=yes],[])
])
if test $ethr_cv_arm_dbm_sy_instr = yes; then
ethr_arm_dbm_sy_instr_val=1
@@ -1381,11 +1437,9 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
AC_CACHE_CHECK([for ARM 'dmb st' instruction], ethr_cv_arm_dbm_st_instr,
[
ethr_cv_arm_dbm_st_instr=no
- AC_TRY_LINK([],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
__asm__ __volatile__("dmb st" : : : "memory");
- ],
- [ethr_cv_arm_dbm_st_instr=yes])
+ ]])],[ethr_cv_arm_dbm_st_instr=yes],[])
])
if test $ethr_cv_arm_dbm_st_instr = yes; then
ethr_arm_dbm_st_instr_val=1
@@ -1393,21 +1447,52 @@ AC_DEFUN(ETHR_CHK_GCC_ATOMIC_OPS,
AC_CACHE_CHECK([for ARM 'dmb ld' instruction], ethr_cv_arm_dbm_ld_instr,
[
ethr_cv_arm_dbm_ld_instr=no
- AC_TRY_LINK([],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
__asm__ __volatile__("dmb ld" : : : "memory");
- ],
- [ethr_cv_arm_dbm_ld_instr=yes])
+ ]])],[ethr_cv_arm_dbm_ld_instr=yes],[])
])
if test $ethr_cv_arm_dbm_ld_instr = yes; then
ethr_arm_dbm_ld_instr_val=1
- fi;;
- *)
- ;;
- esac
+ fi
+ AC_CACHE_CHECK([for ARM 'isb sy' instruction], ethr_cv_arm_isb_sy_instr,
+ [
+ ethr_cv_arm_isb_sy_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ __asm__ __volatile__("isb sy" : : : "memory");
+ ]])],[ethr_cv_arm_isb_sy_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_isb_sy_instr = yes; then
+ ethr_arm_isb_sy_instr_val=1
+ fi
+ AC_CACHE_CHECK([for ARM 'dc cvau' instruction], ethr_cv_arm_dc_cvau_instr,
+ [
+ ethr_cv_arm_dc_cvau_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char data[512]; __asm__ __volatile__("dc cvau, %0" : "r" (data) : : "memory");
+ ]])],[ethr_cv_arm_dc_cvau_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_dc_cvau_instr = yes; then
+ ethr_arm_dc_cvau_instr_val=1
+ fi
+ AC_CACHE_CHECK([for ARM 'ic ivau' instruction], ethr_cv_arm_ic_ivau_instr,
+ [
+ ethr_cv_arm_ic_ivau_instr=no
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+ char data[512]; __asm__ __volatile__("ic ivau, %0" : "r" (data) : : "memory");
+ ]])],[ethr_cv_arm_ic_ivau_instr=yes],[])
+ ])
+ if test $ethr_cv_arm_ic_ivau_instr = yes; then
+ ethr_arm_ic_ivau_instr_val=1
+ fi
+ ])
+
AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DMB_INSTRUCTION], [$ethr_arm_dbm_sy_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dmb sy' instruction, and are compiling for an ARM processor with ARM DMB instruction support, or not])
AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DMB_ST_INSTRUCTION], [$ethr_arm_dbm_st_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dmb st' instruction, and are compiling for an ARM processor with ARM DMB instruction support, or not])
AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DMB_LD_INSTRUCTION], [$ethr_arm_dbm_ld_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dmb ld' instruction, and are compiling for an ARM processor with ARM DMB instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_ISB_SY_INSTRUCTION], [$ethr_arm_isb_sy_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'isb sy' instruction, and are compiling for an ARM processor with ARM ISB instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_DC_CVAU_INSTRUCTION], [$ethr_arm_dc_cvau_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'dc cvau' instruction, and are compiling for an ARM processor with ARM DC instruction support, or not])
+ AC_DEFINE_UNQUOTED([ETHR_HAVE_GCC_ASM_ARM_IC_IVAU_INSTRUCTION], [$ethr_arm_ic_ivau_instr_val], [Define as a boolean indicating whether you have a gcc compatible compiler capable of generating the ARM 'ic ivau' instruction, and are compiling for an ARM processor with ARM IC instruction support, or not])
+
test $ethr_cv_32bit___sync_val_compare_and_swap = yes &&
ethr_have_gcc_native_atomics=yes
test $ethr_cv_64bit___sync_val_compare_and_swap = yes &&
@@ -1440,20 +1525,17 @@ AC_DEFUN(ETHR_CHK_INTERLOCKED,
"4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";;
esac
have_interlocked_op=no
- AC_TRY_LINK(
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#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])
+ ]])],[have_interlocked_op=yes],[])
test $have_interlocked_op = yes && $4
AC_MSG_RESULT([$have_interlocked_op])
])
@@ -1596,9 +1678,10 @@ AS_HELP_STRING([--without-threadnames],
dnl Name of lib where ethread implementation is located
ethr_lib_name=ethread
-case "$THR_LIB_NAME" in
-
- win32_threads)
+AS_CASE(
+ ["$THR_LIB_NAME"],
+ [win32_threads],
+ [
ETHR_THR_LIB_BASE_DIR=win
# * _WIN32_WINNT >= 0x0400 is needed for
# TryEnterCriticalSection
@@ -1670,9 +1753,9 @@ case "$THR_LIB_NAME" in
ethr_native_atomic_implementation=windows
ethr_have_native_spinlock=yes
fi
- ;;
-
- pthread)
+ ],
+ [pthread],
+ [
ETHR_THR_LIB_BASE_DIR=pthread
AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads])
case $host_os in
@@ -1767,15 +1850,9 @@ case "$THR_LIB_NAME" in
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>.]))
-
AC_MSG_CHECKING([for usable PTHREAD_STACK_MIN])
pthread_stack_min=no
- AC_TRY_COMPILE([
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <limits.h>
#if defined(ETHR_NEED_NPTL_PTHREAD_H)
#include <nptl/pthread.h>
@@ -1784,9 +1861,7 @@ case "$THR_LIB_NAME" in
#elif defined(ETHR_HAVE_PTHREAD_H)
#include <pthread.h>
#endif
- ],
- [return PTHREAD_STACK_MIN;],
- [pthread_stack_min=yes])
+ ]], [[return PTHREAD_STACK_MIN;]])],[pthread_stack_min=yes],[])
AC_MSG_RESULT([$pthread_stack_min])
test $pthread_stack_min != yes || {
@@ -1796,43 +1871,47 @@ case "$THR_LIB_NAME" in
dnl
dnl Check for functions
dnl
- AC_CHECK_FUNC(pthread_spin_lock, \
+ 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,
+ AC_CHECK_FUNC([sched_yield], [have_sched_yield=yes])
+ AS_IF(
+ [test $have_sched_yield = no],
+ [
+ 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
+ ])
+ AS_IF(
+ [test $have_sched_yield = yes || test $have_librt_sched_yield = yes],
+ [
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_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#ifdef ETHR_HAVE_SCHED_H
#include <sched.h>
#endif
- ],
- [int sched_yield();],
- [sched_yield_ret_int=yes])
+ ]], [[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_CHECK_FUNC([pthread_yield], [have_pthread_yield=yes])
+ AS_IF(
+ [test $have_pthread_yield = yes],
+ [
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_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if defined(ETHR_NEED_NPTL_PTHREAD_H)
#include <nptl/pthread.h>
#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
@@ -1840,30 +1919,31 @@ case "$THR_LIB_NAME" in
#elif defined(ETHR_HAVE_PTHREAD_H)
#include <pthread.h>
#endif
- ],
- [int pthread_yield();],
- [pthread_yield_ret_int=yes])
+ ]], [[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
-
+ AS_IF(
+ [test $have_pthread_rwlock_init = yes],
+ [
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
+ AS_IF(
+ [test $ethr_have_pthread_rwlockattr_setkind_np = yes],
+ [
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([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if defined(ETHR_NEED_NPTL_PTHREAD_H)
#include <nptl/pthread.h>
#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
@@ -1871,20 +1951,18 @@ case "$THR_LIB_NAME" in
#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])
+ ]])],[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
@@ -1902,10 +1980,12 @@ case "$THR_LIB_NAME" in
AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \
[Define if you have the pthread_attr_setguardsize function.]))
- if test "x$erl_monotonic_clock_id" != "x"; then
+ AS_IF(
+ [test "x$erl_monotonic_clock_id" != "x"],
+ [
AC_MSG_CHECKING(whether pthread_cond_timedwait() can use the monotonic clock $erl_monotonic_clock_id for timeout)
pthread_cond_timedwait_monotonic=no
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if defined(ETHR_NEED_NPTL_PTHREAD_H)
# include <nptl/pthread.h>
#elif defined(ETHR_HAVE_MIT_PTHREAD_H)
@@ -1913,22 +1993,15 @@ case "$THR_LIB_NAME" in
#elif defined(ETHR_HAVE_PTHREAD_H)
# include <pthread.h>
#endif
- #ifdef ETHR_TIME_WITH_SYS_TIME
- # include <time.h>
+ #include <time.h>
+ #ifdef ETHR_HAVE_SYS_TIME_H
# include <sys/time.h>
- #else
- # ifdef ETHR_HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
#endif
#if defined(ETHR_HAVE_MACH_CLOCK_GET_TIME)
# include <mach/clock.h>
# include <mach/mach.h>
#endif
- ],
- [
+ ]], [[
int res;
pthread_condattr_t attr;
pthread_cond_t cond;
@@ -1938,31 +2011,28 @@ case "$THR_LIB_NAME" in
res = pthread_condattr_setclock(&attr, ETHR_MONOTONIC_CLOCK_ID);
res = pthread_cond_init(&cond, &attr);
res = pthread_cond_timedwait(&cond, &mutex, &cond_timeout);
- ],
- [pthread_cond_timedwait_monotonic=yes])
+ ]])],[pthread_cond_timedwait_monotonic=yes],[])
AC_MSG_RESULT([$pthread_cond_timedwait_monotonic])
if test $pthread_cond_timedwait_monotonic = yes; then
AC_DEFINE(ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC, [1], [Define if pthread_cond_timedwait() can be used with a monotonic clock])
fi
- fi
+ ])
linux_futex=no
AC_MSG_CHECKING([for Linux futexes])
- AC_TRY_LINK([
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#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)
+ ]])],[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.])
@@ -1970,18 +2040,12 @@ case "$THR_LIB_NAME" in
AC_MSG_CHECKING([for pthread_setname_np])
old_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -Werror"
- AC_TRY_LINK([#define __USE_GNU
- #include <pthread.h>],
- [pthread_setname_np(pthread_self(), "name");],
- pthread_setname=linux)
- AC_TRY_LINK([#define __USE_GNU
- #include <pthread.h>],
- [pthread_set_name_np(pthread_self(), "name");],
- pthread_setname=bsd)
- AC_TRY_LINK([#define _DARWIN_C_SOURCE
- #include <pthread.h>],
- [pthread_setname_np("name");],
- pthread_setname=darwin)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
+ #include <pthread.h>]], [[pthread_setname_np(pthread_self(), "name");]])],[pthread_setname=linux],[])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
+ #include <pthread.h>]], [[pthread_set_name_np(pthread_self(), "name");]])],[pthread_setname=bsd],[])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define _DARWIN_C_SOURCE
+ #include <pthread.h>]], [[pthread_setname_np("name");]])],[pthread_setname=darwin],[])
AC_MSG_RESULT([$pthread_setname])
case $with_threadnames-$pthread_setname in
yes-linux) AC_DEFINE(ETHR_HAVE_PTHREAD_SETNAME_NP_2, 1,
@@ -1995,16 +2059,12 @@ case "$THR_LIB_NAME" in
pthread_getname=no
AC_MSG_CHECKING([for pthread_getname_np])
- AC_TRY_LINK([#define __USE_GNU
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
#define _DARWIN_C_SOURCE
- #include <pthread.h>],
- [char buff[256]; pthread_getname_np(pthread_self(), buff, 256);],
- pthread_getname=linux)
- AC_TRY_LINK([#define __USE_GNU
+ #include <pthread.h>]], [[char buff[256]; pthread_getname_np(pthread_self(), buff, 256);]])],[pthread_getname=linux],[])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define __USE_GNU
#define _DARWIN_C_SOURCE
- #include <pthread.h>],
- [char buff[256]; pthread_getname_np(pthread_self(), buff);],
- pthread_getname=ibm)
+ #include <pthread.h>]], [[char buff[256]; pthread_getname_np(pthread_self(), buff);]])],[pthread_getname=ibm],[])
AC_MSG_RESULT([$pthread_getname])
case $pthread_getname in
linux) AC_DEFINE(ETHR_HAVE_PTHREAD_GETNAME_NP_3, 1,
@@ -2015,10 +2075,12 @@ case "$THR_LIB_NAME" in
esac
CFLAGS=$old_CFLAGS
- if test "X$disable_native_ethr_impls" = "Xyes"; then
+ AS_IF(
+ [test "X$disable_native_ethr_impls" = "Xyes"],
+ [
ethr_have_native_atomics=no
- else
-
+ ],
+ [
ETHR_CHK_GCC_ATOMIC_OPS([])
AC_MSG_CHECKING([for a usable libatomic_ops implementation])
@@ -2035,8 +2097,7 @@ case "$THR_LIB_NAME" in
fi;;
esac
ethr_have_libatomic_ops=no
- AC_TRY_LINK([#include "atomic_ops.h"],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "atomic_ops.h"]], [[
volatile AO_t x;
AO_t y;
int z;
@@ -2067,12 +2128,13 @@ case "$THR_LIB_NAME" in
#else
#error No compare_and_swap
#endif
- ],
- [ethr_have_native_atomics=yes
+ ]])],[ethr_have_native_atomics=yes
ethr_native_atomic_implementation=libatomic_ops
- ethr_have_libatomic_ops=yes])
+ ethr_have_libatomic_ops=yes],[])
AC_MSG_RESULT([$ethr_have_libatomic_ops])
- if test $ethr_have_libatomic_ops = yes; then
+ AS_IF(
+ [test $ethr_have_libatomic_ops = yes],
+ [
AC_CHECK_SIZEOF(AO_t, ,
[
#include <stdio.h>
@@ -2085,9 +2147,11 @@ case "$THR_LIB_NAME" in
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
+ ],
+ [test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"],
+ [
AC_MSG_ERROR([No usable libatomic_ops implementation found])
- fi
+ ])
case "$host_cpu" in
sparc | sun4u | sparc64 | sun4v)
@@ -2119,7 +2183,7 @@ case "$THR_LIB_NAME" in
;;
esac
- fi
+ ])
test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes
@@ -2128,10 +2192,7 @@ case "$THR_LIB_NAME" in
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
@@ -2183,32 +2244,30 @@ esac
AC_C_DOUBLE_MIDDLE_ENDIAN
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)
+AS_CASE(
+ ["$GCC-$ac_cv_sizeof_void_p-$host_cpu"],
+ [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([],
- [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
long long x, *y;
__asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory");
- ],
- [gcc_sse2_asm=yes])
+ ]])],[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)
+ ])
+AS_CASE(
+ ["$GCC-$host_cpu"],
+ [yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64],
+ [
if test $ac_cv_sizeof_void_p = 4; then
dw_cmpxchg="cmpxchg8b"
else
@@ -2237,8 +2296,7 @@ case "$GCC-$host_cpu" in
AC_MSG_CHECKING([for gcc $pic_text$dw_cmpxchg plain asm support])
plain_cmpxchg=no
- AC_TRY_COMPILE([],
- [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
char xchgd;
long new[2], xchg[2], *p;
__asm__ __volatile__(
@@ -2251,8 +2309,7 @@ case "$GCC-$host_cpu" in
: "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=q"(xchgd)
: "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "c"(new[1]), "b"(new[0])
: "cc", "memory");
- ],
- [plain_cmpxchg=yes])
+ ]])],[plain_cmpxchg=yes],[])
AC_MSG_RESULT([$plain_cmpxchg])
@@ -2271,15 +2328,12 @@ case "$GCC-$host_cpu" in
# as input to the asm on 32-bit x86 and old gcc
# compilers (gcc vsn < 5).
- AC_TRY_COMPILE([],
- [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
#if !defined(__PIC__) || !__PIC__
# error no pic
#endif
- ],
- [pic_cmpxchg=yes
- gcc_cflags_pic=yes],
- [pic_cmpxchg=no])
+ ]])],[pic_cmpxchg=yes
+ gcc_cflags_pic=yes],[pic_cmpxchg=no])
if test $pic_cmpxchg = yes; then
gcc_pic_dw_cmpxchg_asm=$gcc_dw_cmpxchg_asm
@@ -2291,15 +2345,16 @@ case "$GCC-$host_cpu" in
done
- if test $gcc_pic_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then
+ AS_IF(
+ [test $gcc_pic_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4],
+ [
AC_MSG_CHECKING([for gcc pic cmpxchg8b asm support with EBX workaround])
# Check if we can work around it by managing the ebx
# register explicitly in the asm...
- AC_TRY_COMPILE([],
- [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
char xchgd;
long new[2], xchg[2], *p;
__asm__ __volatile__(
@@ -2311,21 +2366,21 @@ case "$GCC-$host_cpu" in
: "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=q"(xchgd)
: "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "c"(new[1]), "r"(new[0])
: "cc", "memory");
- ],
- [gcc_pic_dw_cmpxchg_asm=yes
- gcc_cmpxchg8b_pic_no_clobber_ebx=yes])
+ ]])],[gcc_pic_dw_cmpxchg_asm=yes
+ gcc_cmpxchg8b_pic_no_clobber_ebx=yes],[])
AC_MSG_RESULT([$gcc_pic_dw_cmpxchg_asm])
- if test $gcc_pic_dw_cmpxchg_asm = no; then
+ AS_IF(
+ [test $gcc_pic_dw_cmpxchg_asm = no],
+ [
AC_MSG_CHECKING([for gcc pic cmpxchg8b asm support with EBX and register shortage workarounds])
# If no optimization is enabled we sometimes get a
# register shortage. Check if we can work around
# this...
- AC_TRY_COMPILE([],
- [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
char xchgd;
long new[2], xchg[2], *p;
__asm__ __volatile__(
@@ -2339,34 +2394,30 @@ case "$GCC-$host_cpu" in
: "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "r"(new)
: "cc", "memory");
- ],
- [gcc_pic_dw_cmpxchg_asm=yes
+ ]])],[gcc_pic_dw_cmpxchg_asm=yes
gcc_cmpxchg8b_pic_no_clobber_ebx=yes
- gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=yes])
+ gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage=yes],[])
AC_MSG_RESULT([$gcc_pic_dw_cmpxchg_asm])
- fi
+ ])
if test $gcc_cflags_pic = yes; then
gcc_dw_cmpxchg_asm=$gcc_pic_dw_cmpxchg_asm
fi
-
- fi
+ ])
CFLAGS="$save_CFLAGS"
if test "$gcc_cmpxchg8b_pic_no_clobber_ebx" = "yes"; then
- AC_DEFINE(ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX, 1, [Define if gcc wont let you clobber ebx with cmpxchg8b and position independent code])
+ AC_DEFINE(ETHR_CMPXCHG8B_PIC_NO_CLOBBER_EBX, 1, [Define if gcc won't let you clobber ebx with cmpxchg8b and position independent code])
fi
if test "$gcc_cmpxchg8b_pic_no_clobber_ebx_register_shortage" = "yes"; then
AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code])
fi
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
+ fi
+ ])
AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \
[Define if you have all ethread defines])
@@ -2433,7 +2484,9 @@ case "$with_clock_resolution" in
;;
esac
-if test "$force_gettimeofday_os_system_time" = "yes"; then
+AS_IF(
+ [test "$force_gettimeofday_os_system_time" = "yes"],
+ [
AC_CHECK_FUNCS([gettimeofday])
if test "$ac_cv_func_gettimeofday" = "yes"; then
@@ -2441,8 +2494,9 @@ if test "$force_gettimeofday_os_system_time" = "yes"; then
else
AC_MSG_ERROR([No gettimeofday() available])
fi
-
-else # $force_gettimeofday_os_system_time != yes
+ ],
+ [
+ # $force_gettimeofday_os_system_time != yes
case "$with_clock_gettime_realtime_id" in
""|no)
@@ -2461,16 +2515,22 @@ case "$with_clock_gettime_realtime_id" in
;;
esac
-case "$with_clock_resolution-$with_clock_gettime_realtime_id" in
- high-no)
- ERL_WALL_CLOCK(high_resolution);;
- low-no)
- ERL_WALL_CLOCK(low_resolution);;
- default-no)
- ERL_WALL_CLOCK(default_resolution);;
- *)
- ERL_WALL_CLOCK(custom_resolution, $with_clock_gettime_realtime_id);;
-esac
+AS_CASE(["$with_clock_resolution-$with_clock_gettime_realtime_id"],
+ [high-no],
+ [
+ ERL_WALL_CLOCK([high_resolution])
+ ],
+ [low-no],
+ [
+ ERL_WALL_CLOCK([low_resolution])
+ ],
+ [default-no],
+ [
+ ERL_WALL_CLOCK([default_resolution])
+ ],
+ [
+ ERL_WALL_CLOCK([custom_resolution], [$with_clock_gettime_realtime_id])
+ ])
case "$erl_wall_clock_func-$erl_wall_clock_id-$with_clock_gettime_realtime_id" in
*-*-no)
@@ -2504,7 +2564,7 @@ if test "x$erl_wall_clock_id" != "x"; then
AC_DEFINE_UNQUOTED(WALL_CLOCK_ID, [$erl_wall_clock_id], [Define to wall clock id to use])
fi
-fi # $force_gettimeofday_os_system_time != yes
+ ]) # $force_gettimeofday_os_system_time != yes
case "$with_clock_gettime_monotonic_id" in
""|no)
@@ -2532,16 +2592,22 @@ case "$with_clock_gettime_monotonic_id" in
;;
esac
-case "$with_clock_resolution-$with_clock_gettime_monotonic_id" in
- high-no)
- ERL_MONOTONIC_CLOCK(high_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
- low-no)
- ERL_MONOTONIC_CLOCK(low_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
- default-no)
- ERL_MONOTONIC_CLOCK(default_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
- *)
- ERL_MONOTONIC_CLOCK(custom_resolution, $with_clock_gettime_monotonic_id, $prefer_elapsed_monotonic_time_during_suspend);;
-esac
+AS_CASE(["$with_clock_resolution-$with_clock_gettime_monotonic_id"],
+ [high-no],
+ [
+ ERL_MONOTONIC_CLOCK([high_resolution], [undefined], [$prefer_elapsed_monotonic_time_during_suspend])
+ ],
+ [low-no],
+ [
+ ERL_MONOTONIC_CLOCK([low_resolution], [undefined], [$prefer_elapsed_monotonic_time_during_suspend])
+ ],
+ [default-no],
+ [
+ ERL_MONOTONIC_CLOCK([default_resolution], [undefined], [$prefer_elapsed_monotonic_time_during_suspend])
+ ],
+ [
+ ERL_MONOTONIC_CLOCK([custom_resolution], [$with_clock_gettime_monotonic_id], [$prefer_elapsed_monotonic_time_during_suspend])
+ ])
case "$erl_monotonic_clock_func-$erl_monotonic_clock_id-$with_clock_gettime_monotonic_id" in
*-*-no)
@@ -2594,7 +2660,7 @@ if test $erl_cv_clock_gettime_monotonic_raw = yes; then
AC_DEFINE(HAVE_CLOCK_GETTIME_MONOTONIC_RAW, [1], [Define if you have clock_gettime(CLOCK_MONOTONIC_RAW, _)])
fi
-ERL_MONOTONIC_CLOCK(high_resolution, undefined, no)
+ERL_MONOTONIC_CLOCK([high_resolution], [undefined], [no])
case $erl_monotonic_clock_low_resolution-$erl_monotonic_clock_func in
no-mach_clock_get_time)
@@ -2630,7 +2696,7 @@ 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([
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
/* gethrvtime procfs ioctl test */
/* These need to be undef:ed to not break activation of
* micro level process accounting on /proc/self
@@ -2678,10 +2744,7 @@ int main() {
exit(5);
exit(0); return 0;
}
-],
-erl_gethrvtime=procfs_ioctl,
-erl_gethrvtime=false,
-[
+]])],[erl_gethrvtime=procfs_ioctl],[erl_gethrvtime=false],[
case X$erl_xcomp_gethrvtime_procfs_ioctl in
X)
erl_gethrvtime=cross;;
@@ -2697,13 +2760,13 @@ esac
])
LIBRT=$xrtlib
-case $erl_gethrvtime in
- procfs_ioctl)
+AS_IF([test "$erl_gethrvtime" = "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)
@@ -2719,7 +2782,7 @@ case $erl_gethrvtime in
AC_MSG_CHECKING([if clock_gettime can be used to get thread CPU time])
save_libs=$LIBS
LIBS="-lrt"
- AC_TRY_RUN([
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -2742,10 +2805,7 @@ case $erl_gethrvtime in
exit(5);
exit(0); return 0;
}
- ],
- erl_clock_gettime_cpu_time=yes,
- erl_clock_gettime_cpu_time=no,
- [
+ ]])],[erl_clock_gettime_cpu_time=yes],[erl_clock_gettime_cpu_time=no],[
case X$erl_xcomp_clock_gettime_cpu_time in
X) erl_clock_gettime_cpu_time=cross;;
Xyes|Xno) erl_clock_gettime_cpu_time=$erl_xcomp_clock_gettime_cpu_time;;
@@ -2767,8 +2827,7 @@ case $erl_gethrvtime in
*)
;;
esac
- ;;
-esac
+ ])
AC_SUBST(LIBRT)
])dnl
@@ -2787,29 +2846,35 @@ AC_DEFUN([LM_TRY_ENABLE_CFLAG], [
AC_MSG_CHECKING([if we can add $1 to $2 (via CFLAGS)])
saved_CFLAGS=$CFLAGS;
CFLAGS="$1 $$2";
- AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[can_enable_flag=true],[can_enable_flag=false])
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ AS_IF(
+ [test "X$can_enable_flag" = "Xtrue"],
+ [
AC_MSG_RESULT([yes])
AS_VAR_SET($2, "$1 $$2")
- else
+ ],
+ [
AC_MSG_RESULT([no])
- fi
+ ])
])
AC_DEFUN([LM_CHECK_ENABLE_CFLAG], [
AC_MSG_CHECKING([whether $CC accepts $1...])
saved_CFLAGS=$CFLAGS;
CFLAGS="$1 $CFLAGS";
- AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[return 0;]])],[can_enable_flag=true],[can_enable_flag=false])
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ AS_IF(
+ [test "X$can_enable_flag" = "Xtrue"],
+ [
AS_VAR_SET($2, true)
AC_MSG_RESULT([yes])
- else
+ ],
+ [
AS_VAR_SET($2, false)
AC_MSG_RESULT([no])
- fi
+ ])
])
dnl
@@ -2823,23 +2888,26 @@ AC_DEFUN([LM_CHECK_RUN_CFLAG], [
AC_MSG_CHECKING([whether $CC accepts $1...])
saved_CFLAGS=$CFLAGS;
CFLAGS="$1 $CFLAGS";
- AC_TRY_RUN([],[return 0;],can_enable_flag=true,can_enable_flag=false)
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[]])],[return 0;],[can_enable_flag=true],[can_enable_flag=false])
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
+ AS_IF(
+ [test "X$can_enable_flag" = "Xtrue"],
+ [
AS_VAR_SET($2, true)
AC_MSG_RESULT([yes])
- else
+ ],
+ [
AS_VAR_SET($2, false)
AC_MSG_RESULT([no])
- fi
+ ])
])
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 Freely inspired by AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[],[]). (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'
+[java_link='$JAVAC conftest.java 1>&AS_MESSAGE_LOG_FD'
changequote(, )dnl
cat > conftest.java <<EOF
$1
@@ -2848,20 +2916,24 @@ class conftest { public static void main(String[] args) {
; return; }}
EOF
changequote([, ])dnl
-if AC_TRY_EVAL(java_link) && test -s conftest.class; then
+AS_IF(
+ [AC_TRY_EVAL(java_link) && test -s conftest.class],
+ [
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
+
+ ],
+ [
+ echo "configure: failed program was:" 1>&AS_MESSAGE_LOG_FD
+ cat conftest.java 1>&AS_MESSAGE_LOG_FD
+ echo "configure: PATH was $PATH" 1>&AS_MESSAGE_LOG_FD
ifelse([$4], , , [ rm -rf conftest*
$4
])dnl
-fi
-rm -f conftest*])
-#define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
+ ])
+rm -f conftest*])
+dnl #define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */
dnl ----------------------------------------------------------------------
dnl
@@ -3037,18 +3109,22 @@ DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${E
DED_INCLUDE=$DED_SYS_INCLUDE
DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
-if test "x$GCC" = xyes; then
+AS_IF(
+ [test "x$GCC" = xyes],
+ [
# Use -fno-common for gcc, that is link error if multiple definitions of
# global variables are encountered. This is ISO C compliant.
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
LM_TRY_ENABLE_CFLAG([-fno-common], [DED_CFLAGS])
+ LM_TRY_ENABLE_CFLAG([-fno-strict-aliasing], [DED_CFLAGS])
+
DED_STATIC_CFLAGS="$DED_CFLAGS"
DED_CFLAGS="$DED_CFLAGS -fPIC"
# Remove -fPIE and -fno-PIE
DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
-fi
+ ])
DED_EXT=so
case $host_os in
diff --git a/erts/autoconf/win32.config.cache.static b/make/autoconf/win32.config.cache.static
index b3328e5414..790ea9ab00 100755
--- a/erts/autoconf/win32.config.cache.static
+++ b/make/autoconf/win32.config.cache.static
@@ -36,11 +36,11 @@ 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_build_alias_value=local-x86-pc-windows
ac_cv_env_host_alias_set=set
-ac_cv_env_host_alias_value=win32
+ac_cv_env_host_alias_value=local-x86-pc-windows
ac_cv_env_target_alias_set=set
-ac_cv_env_target_alias_value=win32
+ac_cv_env_target_alias_value=local-x86-pc-windows
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}
diff --git a/erts/autoconf/win64.config.cache.static b/make/autoconf/win64.config.cache.static
index c7d92c7000..73146cbb86 100755
--- a/erts/autoconf/win64.config.cache.static
+++ b/make/autoconf/win64.config.cache.static
@@ -40,11 +40,11 @@ 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_build_alias_value=local-x86_64-pc-windows
ac_cv_env_host_alias_set=set
-ac_cv_env_host_alias_value=win32
+ac_cv_env_host_alias_value=local-x86_64-pc-windows
ac_cv_env_target_alias_set=set
-ac_cv_env_target_alias_value=win32
+ac_cv_env_target_alias_value=local-x86_64-pc-windows
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}
diff --git a/make/configure b/make/configure
index c44049816c..169ae15fe6 100755
--- a/make/configure
+++ b/make/configure
@@ -1,9 +1,10 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69.
+# Generated by GNU Autoconf 2.71.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
@@ -14,14 +15,16 @@
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -31,46 +34,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -79,13 +82,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -94,8 +90,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -107,30 +107,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
@@ -152,20 +132,22 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
@@ -185,42 +167,53 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
@@ -228,14 +221,21 @@ fi
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
@@ -253,18 +253,19 @@ esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
@@ -291,6 +292,7 @@ as_fn_unset ()
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -308,6 +310,14 @@ as_fn_exit ()
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
@@ -322,7 +332,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -331,7 +341,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -370,12 +380,13 @@ as_fn_executable_p ()
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -387,18 +398,27 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
@@ -410,9 +430,9 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
@@ -439,7 +459,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -483,7 +503,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
@@ -497,6 +517,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -510,6 +534,13 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -575,49 +606,45 @@ MFLAGS=
MAKEFLAGS=
# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-PACKAGE_URL=
+PACKAGE_NAME=''
+PACKAGE_TARNAME=''
+PACKAGE_VERSION=''
+PACKAGE_STRING=''
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
LIBOBJS
DED_OSTYPE
@@ -633,8 +660,6 @@ DED_EXT
DED_GCC
DED_CC
DED_THR_DEFS
-EGREP
-GREP
DEFAULT_VERBOSITY
OTP_VSN
OTP_REL
@@ -655,6 +680,10 @@ ac_ct_CC
BOOTSTRAP_ONLY
CROSS_COMPILING
TARGET
+target_os
+target_vendor
+target_cpu
+target
host_os
host_vendor
host_cpu
@@ -879,8 +908,6 @@ do
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
@@ -921,9 +948,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -947,9 +974,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
@@ -1160,9 +1187,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1176,9 +1203,9 @@ do
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
@@ -1222,9 +1249,9 @@ Try \`$0 --help' for more information"
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
@@ -1240,7 +1267,7 @@ if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
@@ -1304,7 +1331,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -1422,6 +1449,7 @@ _ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
@@ -1609,9 +1637,9 @@ if test "$ac_init_help" = "recursive"; then
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -1639,7 +1667,8 @@ esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
@@ -1647,7 +1676,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
@@ -1657,9 +1686,9 @@ test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
configure
-generated by GNU Autoconf 2.69
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
@@ -1676,14 +1705,14 @@ fi
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1691,14 +1720,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1714,14 +1744,14 @@ fi
ac_fn_cxx_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1729,14 +1759,15 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1752,14 +1783,14 @@ fi
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -1767,17 +1798,18 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
- }; then :
+ }
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
@@ -1798,11 +1830,12 @@ fi
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
@@ -1810,16 +1843,9 @@ else
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
+ which can conflict with char $2 (); below. */
+#include <limits.h>
#undef $2
/* Override any GCC internal prototype to avoid an error.
@@ -1837,156 +1863,66 @@ choke me
#endif
int
-main ()
+main (void)
{
return $2 ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-} # ac_fn_c_check_header_mongrel
+} # ac_fn_c_check_header_compile
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
@@ -1996,25 +1932,26 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
@@ -2025,37 +1962,6 @@ fi
} # ac_fn_c_try_run
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
-
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
@@ -2070,7 +1976,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
@@ -2080,14 +1986,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2097,9 +2004,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid; break
-else
+else $as_nop
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
@@ -2107,14 +2015,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
@@ -2124,14 +2032,15 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
@@ -2141,9 +2050,10 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
@@ -2151,14 +2061,14 @@ else
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
@@ -2166,7 +2076,7 @@ while test "x$ac_lo" != "x$ac_hi"; do
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
@@ -2176,12 +2086,13 @@ return test_array [0];
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
@@ -2191,12 +2102,12 @@ esac
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
@@ -2224,9 +2135,10 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
@@ -2238,14 +2150,34 @@ rm -f conftest.val
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
@@ -2278,8 +2210,12 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
@@ -2314,7 +2250,7 @@ do
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
@@ -2349,11 +2285,13 @@ done
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
@@ -2364,8 +2302,8 @@ trap 'exit_status=$?
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -2389,7 +2327,7 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
@@ -2397,14 +2335,14 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
@@ -2412,15 +2350,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
@@ -2428,8 +2366,8 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
@@ -2443,63 +2381,48 @@ ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
@@ -2509,19 +2432,650 @@ if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+# Test code for whether the C++ compiler supports C++98 (global declarations)
+ac_cxx_conftest_cxx98_globals='
+// Does the compiler advertise C++98 conformance?
+#if !defined __cplusplus || __cplusplus < 199711L
+# error "Compiler does not advertise C++98 conformance"
+#endif
+
+// These inclusions are to reject old compilers that
+// lack the unsuffixed header files.
+#include <cstdlib>
+#include <exception>
+
+// <cassert> and <cstring> are *not* freestanding headers in C++98.
+extern void assert (int);
+namespace std {
+ extern int strcmp (const char *, const char *);
+}
+
+// Namespaces, exceptions, and templates were all added after "C++ 2.0".
+using std::exception;
+using std::strcmp;
+
+namespace {
+
+void test_exception_syntax()
+{
+ try {
+ throw "test";
+ } catch (const char *s) {
+ // Extra parentheses suppress a warning when building autoconf itself,
+ // due to lint rules shared with more typical C programs.
+ assert (!(strcmp) (s, "test"));
+ }
+}
+
+template <typename T> struct test_template
+{
+ T const val;
+ explicit test_template(T t) : val(t) {}
+ template <typename U> T add(U u) { return static_cast<T>(u) + val; }
+};
+
+} // anonymous namespace
+'
+
+# Test code for whether the C++ compiler supports C++98 (body of main)
+ac_cxx_conftest_cxx98_main='
+ assert (argc);
+ assert (! argv[0]);
+{
+ test_exception_syntax ();
+ test_template<double> tt (2.0);
+ assert (tt.add (4) == 6.0);
+ assert (true && !false);
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (global declarations)
+ac_cxx_conftest_cxx11_globals='
+// Does the compiler advertise C++ 2011 conformance?
+#if !defined __cplusplus || __cplusplus < 201103L
+# error "Compiler does not advertise C++11 conformance"
+#endif
+
+namespace cxx11test
+{
+ constexpr int get_val() { return 20; }
+
+ struct testinit
+ {
+ int i;
+ double d;
+ };
+
+ class delegate
+ {
+ public:
+ delegate(int n) : n(n) {}
+ delegate(): delegate(2354) {}
+
+ virtual int getval() { return this->n; };
+ protected:
+ int n;
+ };
+
+ class overridden : public delegate
+ {
+ public:
+ overridden(int n): delegate(n) {}
+ virtual int getval() override final { return this->n * 2; }
+ };
+
+ class nocopy
+ {
+ public:
+ nocopy(int i): i(i) {}
+ nocopy() = default;
+ nocopy(const nocopy&) = delete;
+ nocopy & operator=(const nocopy&) = delete;
+ private:
+ int i;
+ };
+
+ // for testing lambda expressions
+ template <typename Ret, typename Fn> Ret eval(Fn f, Ret v)
+ {
+ return f(v);
+ }
+
+ // for testing variadic templates and trailing return types
+ template <typename V> auto sum(V first) -> V
+ {
+ return first;
+ }
+ template <typename V, typename... Args> auto sum(V first, Args... rest) -> V
+ {
+ return first + sum(rest...);
+ }
+}
+'
+
+# Test code for whether the C++ compiler supports C++11 (body of main)
+ac_cxx_conftest_cxx11_main='
+{
+ // Test auto and decltype
+ auto a1 = 6538;
+ auto a2 = 48573953.4;
+ auto a3 = "String literal";
+
+ int total = 0;
+ for (auto i = a3; *i; ++i) { total += *i; }
+
+ decltype(a2) a4 = 34895.034;
+}
+{
+ // Test constexpr
+ short sa[cxx11test::get_val()] = { 0 };
+}
+{
+ // Test initializer lists
+ cxx11test::testinit il = { 4323, 435234.23544 };
+}
+{
+ // Test range-based for
+ int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
+ 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
+ for (auto &x : array) { x += 23; }
+}
+{
+ // Test lambda expressions
+ using cxx11test::eval;
+ assert (eval ([](int x) { return x*2; }, 21) == 42);
+ double d = 2.0;
+ assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
+ assert (d == 5.0);
+ assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
+ assert (d == 5.0);
+}
+{
+ // Test use of variadic templates
+ using cxx11test::sum;
+ auto a = sum(1);
+ auto b = sum(1, 2);
+ auto c = sum(1.0, 2.0, 3.0);
+}
+{
+ // Test constructor delegation
+ cxx11test::delegate d1;
+ cxx11test::delegate d2();
+ cxx11test::delegate d3(45);
+}
+{
+ // Test override and final
+ cxx11test::overridden o1(55464);
+}
+{
+ // Test nullptr
+ char *c = nullptr;
+}
+{
+ // Test template brackets
+ test_template<::test_template<int>> v(test_template<int>(12));
+}
+{
+ // Unicode literals
+ char const *utf8 = u8"UTF-8 string \u2500";
+ char16_t const *utf16 = u"UTF-8 string \u2500";
+ char32_t const *utf32 = U"UTF-32 string \u2500";
+}
+'
+
+# Test code for whether the C compiler supports C++11 (complete).
+ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
+${ac_cxx_conftest_cxx11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ ${ac_cxx_conftest_cxx11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C++98 (complete).
+ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_cxx_conftest_cxx98_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="install-sh config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${ERL_TOP}/make/autoconf"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2532,12 +3086,12 @@ for ac_var in $ac_precious_vars; do
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
@@ -2546,24 +3100,24 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
@@ -2573,11 +3127,12 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
@@ -2636,6 +3191,97 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
default_cache_file=./config.cache
if test "x$no_recursion" != "xyes" -a "x$OVERRIDE_CONFIG_CACHE" = "x"; then
@@ -2690,58 +3336,32 @@ esac
test "X$ERL_TOP" != "X" || as_fn_error $? "ERL_TOP not set" "$LINENO" 5
-ac_aux_dir=
-for ac_dir in ${ERL_TOP}/erts/autoconf "$srcdir"/${ERL_TOP}/erts/autoconf; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in ${ERL_TOP}/erts/autoconf \"$srcdir\"/${ERL_TOP}/erts/autoconf" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
@@ -2760,21 +3380,22 @@ IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
@@ -2793,31 +3414,112 @@ IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+printf %s "checking target system type... " >&6; }
+if test ${ac_cv_target+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
else
- host_os=$host
+ ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
fi
-TARGET=$host
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+printf "%s\n" "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
-if test "$cross_compiling" = "yes"; then
- if test "$build" = "$host"; then
- as_fn_error $? "
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ # Adjust for local legacy windows hack...
+ case $host in #(
+ local-*-windows) :
+
+ host=win32
+ host_os=win32
+ host_vendor=
+ host_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $build in #(
+ local-*-windows) :
+
+ build=win32
+ build_os=win32
+ build_vendor=
+ build_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+
+ # Adjust for local legacy windows hack...
+ case $target in #(
+ local-*-windows) :
+
+ target=win32
+ target_os=win32
+ target_vendor=
+ target_cpu=
+ ;; #(
+ *) :
+ ;;
+esac
+
+ if test "$cross_compiling" = "yes" -a "$build" = "$host"
+then :
+ as_fn_error $? "
Cross compiling with the same canonicalized 'host' value
as the canonicalized 'build' value.
We are cross compiling since the '--host=$host_alias'
and the '--build=$build_alias' arguments differ. When
- cross compiling Erlang/OTP also the canonicalized values of
+ cross compiling Erlang/OTP, also the canonicalized values of
the '--build' and the '--host' arguments *must* differ. The
canonicalized values of these arguments however both equals:
$host
You can check the canonical value by passing a value as
- argument to the 'erts/autoconf/config.sub' script.
- " "$LINENO" 5
- fi
+ argument to the 'make/autoconf/config.sub' script.
+ " "$LINENO" 5
+fi
+
+
+TARGET=$host
+
+
+if test "$cross_compiling" = "yes"; then
CROSS_COMPILING=yes
else
CROSS_COMPILING=no
@@ -2825,14 +3527,15 @@ fi
# Check whether --enable-bootstrap-only was given.
-if test "${enable_bootstrap_only+set}" = set; then :
+if test ${enable_bootstrap_only+y}
+then :
enableval=$enable_bootstrap_only; if test "X$enableval" = "Xyes"; then
BOOTSTRAP_ONLY=yes
else
BOOTSTRAP_ONLY=no
fi
-else
+else $as_nop
BOOTSTRAP_ONLY=no
fi
@@ -2844,6 +3547,15 @@ if test $CROSS_COMPILING = yes -a $BOOTSTRAP_ONLY = yes; then
fi
+
+
+
+
+
+
+
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2852,11 +3564,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2864,11 +3577,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2879,11 +3596,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2892,11 +3609,12 @@ if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -2904,11 +3622,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2919,11 +3641,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
@@ -2931,8 +3653,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
@@ -2945,11 +3667,12 @@ if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2957,11 +3680,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -2972,11 +3699,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -2985,11 +3712,12 @@ fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -2998,15 +3726,19 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3022,18 +3754,18 @@ if test $ac_prog_rejected = yes; then
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3044,11 +3776,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
@@ -3056,11 +3789,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3071,11 +3808,11 @@ fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3088,11 +3825,12 @@ if test -z "$CC"; then
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
@@ -3100,11 +3838,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3115,11 +3857,11 @@ fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3131,34 +3873,138 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -3168,7 +4014,7 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
@@ -3176,7 +4022,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3188,9 +4034,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
@@ -3211,11 +4057,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
@@ -3232,7 +4079,7 @@ do
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
@@ -3248,44 +4095,46 @@ do
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
@@ -3299,15 +4148,15 @@ for ac_file in conftest.exe conftest conftest.*; do
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
@@ -3316,7 +4165,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
@@ -3328,8 +4177,8 @@ _ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
@@ -3337,10 +4186,10 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
@@ -3348,39 +4197,40 @@ $as_echo "$ac_try_echo"; } >&5
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
@@ -3394,11 +4244,12 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
@@ -3407,31 +4258,32 @@ $as_echo "$ac_try_echo"; } >&5
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3441,29 +4293,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
@@ -3472,57 +4328,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
@@ -3537,94 +4396,144 @@ else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
@@ -3633,6 +4542,12 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3643,15 +4558,16 @@ if test -z "$CXX"; then
CXX=$CCC
else
if test -n "$ac_tool_prefix"; then
- for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CXX"; then
ac_cv_prog_CXX="$CXX" # Let the user override the test.
else
@@ -3659,11 +4575,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3674,11 +4594,11 @@ fi
fi
CXX=$ac_cv_prog_CXX
if test -n "$CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
-$as_echo "$CXX" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+printf "%s\n" "$CXX" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3687,15 +4607,16 @@ fi
fi
if test -z "$CXX"; then
ac_ct_CXX=$CXX
- for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CXX+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CXX"; then
ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
else
@@ -3703,11 +4624,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CXX="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3718,11 +4643,11 @@ fi
fi
ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
if test -n "$ac_ct_CXX"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
-$as_echo "$ac_ct_CXX" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+printf "%s\n" "$ac_ct_CXX" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3734,8 +4659,8 @@ done
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CXX=$ac_ct_CXX
@@ -3745,7 +4670,7 @@ fi
fi
fi
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
@@ -3755,7 +4680,7 @@ case "(($ac_try" in
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
@@ -3765,20 +4690,21 @@ $as_echo "$ac_try_echo"; } >&5
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
-$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
-if ${ac_cv_cxx_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
+printf %s "checking whether the compiler supports GNU C++... " >&6; }
+if test ${ac_cv_cxx_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
@@ -3788,29 +4714,33 @@ main ()
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
-$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GXX=yes
else
GXX=
fi
-ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_test_CXXFLAGS=${CXXFLAGS+y}
ac_save_CXXFLAGS=$CXXFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
-$as_echo_n "checking whether $CXX accepts -g... " >&6; }
-if ${ac_cv_prog_cxx_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+printf %s "checking whether $CXX accepts -g... " >&6; }
+if test ${ac_cv_prog_cxx_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_cxx_werror_flag=$ac_cxx_werror_flag
ac_cxx_werror_flag=yes
ac_cv_prog_cxx_g=no
@@ -3819,57 +4749,60 @@ else
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
ac_cv_prog_cxx_g=yes
-else
+else $as_nop
CXXFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_cxx_werror_flag=$ac_save_cxx_werror_flag
CXXFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
+if ac_fn_cxx_try_compile "$LINENO"
+then :
ac_cv_prog_cxx_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cxx_werror_flag=$ac_save_cxx_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
-$as_echo "$ac_cv_prog_cxx_g" >&6; }
-if test "$ac_test_CXXFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
+if test $ac_test_CXXFLAGS; then
CXXFLAGS=$ac_save_CXXFLAGS
elif test $ac_cv_prog_cxx_g = yes; then
if test "$GXX" = yes; then
@@ -3884,6 +4817,100 @@ else
CXXFLAGS=
fi
fi
+ac_prog_cxx_stdcxx=no
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
+printf %s "checking for $CXX option to enable C++11 features... " >&6; }
+if test ${ac_cv_prog_cxx_11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_11=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx11_program
+_ACEOF
+for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx11"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
+ ac_prog_cxx_stdcxx=cxx11
+fi
+fi
+if test x$ac_prog_cxx_stdcxx = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
+printf %s "checking for $CXX option to enable C++98 features... " >&6; }
+if test ${ac_cv_prog_cxx_98+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cxx_98=no
+ac_save_CXX=$CXX
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_cxx_conftest_cxx98_program
+_ACEOF
+for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
+do
+ CXX="$ac_save_CXX $ac_arg"
+ if ac_fn_cxx_try_compile "$LINENO"
+then :
+ ac_cv_prog_cxx_cxx98=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CXX=$ac_save_CXX
+fi
+
+if test "x$ac_cv_prog_cxx_cxx98" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cxx_cxx98" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
+ CXX="$CXX $ac_cv_prog_cxx_cxx98"
+fi
+ ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
+ ac_prog_cxx_stdcxx=cxx98
+fi
+fi
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -3893,11 +4920,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$LD"; then
ac_cv_prog_LD="$LD" # Let the user override the test.
else
@@ -3905,11 +4933,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3920,11 +4952,11 @@ fi
fi
LD=$ac_cv_prog_LD
if test -n "$LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -3933,11 +4965,12 @@ if test -z "$ac_cv_prog_LD"; then
ac_ct_LD=$LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_LD"; then
ac_cv_prog_ac_ct_LD="$ac_ct_LD" # Let the user override the test.
else
@@ -3945,11 +4978,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -3960,11 +4997,11 @@ fi
fi
ac_ct_LD=$ac_cv_prog_ac_ct_LD
if test -n "$ac_ct_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5
-$as_echo "$ac_ct_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LD" >&5
+printf "%s\n" "$ac_ct_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_LD" = x; then
@@ -3972,8 +5009,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
LD=$ac_ct_LD
@@ -3994,111 +5031,111 @@ MIXED_VSL=no
MIXED_VC=no
MIXED_MINGW=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
-$as_echo_n "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed mingw-gcc and native VC++ environment" >&5
+printf %s "checking for mixed mingw-gcc and native VC++ environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then
if test -x /usr/bin/msys-?.0.dll; then
CFLAGS="$CFLAGS -O2"
MIXED_MSYS=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
-$as_echo "MSYS and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MSYS and VC" >&5
+printf "%s\n" "MSYS and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
MIXED_CYGWIN=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
-$as_echo "Cygwin and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Cygwin and VC" >&5
+printf "%s\n" "Cygwin and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
elif test -x /bin/wslpath; then
CFLAGS="$CFLAGS -O2"
MIXED_WSL=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
-$as_echo "WSL and VC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: WSL and VC" >&5
+printf "%s\n" "WSL and VC" >&6; }
MIXED_VC=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_VC"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not within any known env" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$MIXED_MSYS" != "xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
-$as_echo_n "checking for mixed cygwin and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed cygwin and native MinGW environment" >&5
+printf %s "checking for mixed cygwin and native MinGW environment... " >&6; }
if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then
if test -x /usr/bin/cygpath; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with cygwin" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
-$as_echo_n "checking for mixed MSYS and native MinGW environment... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mixed MSYS and native MinGW environment" >&5
+printf %s "checking for mixed MSYS and native MinGW environment... " >&6; }
if test "x$GCC" = x"yes"; then
if test -x /usr/bin/msys-=.0.dll; then
CFLAGS="$CFLAGS -O2"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
MIXED_MINGW=yes
CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MINGW"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
-$as_echo "undeterminable" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: undeterminable" >&5
+printf "%s\n" "undeterminable" >&6; }
as_fn_error cannot handle this! "Seems to be mixed windows but not with msys" "$LINENO" 5
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
-$as_echo_n "checking if we mix cygwin with any native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix cygwin with any native compiler" >&5
+printf %s "checking if we mix cygwin with any native compiler... " >&6; }
if test "X$MIXED_CYGWIN" = "Xyes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
-$as_echo_n "checking if we mix msys with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix msys with another native compiler" >&5
+printf %s "checking if we mix msys with another native compiler... " >&6; }
if test "X$MIXED_MSYS" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
-$as_echo_n "checking if we mix WSL with another native compiler... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we mix WSL with another native compiler" >&5
+printf %s "checking if we mix WSL with another native compiler... " >&6; }
if test "X$MIXED_WSL" = "Xyes" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
@@ -4108,11 +5145,12 @@ _search_path=/bin:/usr/bin:/usr/local/bin:$PATH
# Extract the first word of "env", so it can be a program name with args.
set dummy env; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ENV+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ENV+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ENV in
[\\/]* | ?:[\\/]*)
ac_cv_path_ENV="$ENV" # Let the user override the test with a path.
@@ -4122,11 +5160,15 @@ else
for as_dir in $_search_path
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ENV="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ENV="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4139,11 +5181,11 @@ esac
fi
ENV=$ac_cv_path_ENV
if test -n "$ENV"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENV" >&5
-$as_echo "$ENV" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ENV" >&5
+printf "%s\n" "$ENV" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4154,8 +5196,8 @@ fi
#
# We need GNU make, complain if we can't find it
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU make" >&5
-$as_echo_n "checking for GNU make... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU make" >&5
+printf %s "checking for GNU make... " >&6; }
# If there is a Makefile created we don't want make to start making, run
# in a subdirectory and -f /dev/null
MAKE_PROG=x
@@ -4184,17 +5226,18 @@ if test X"$MAKE_PROG" = X"x"; then
fi
rm -rf conftestmake
case $MAKE_PROG in
- x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ x) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
as_fn_error $? "GNU make is required!" "$LINENO" 5
;;
- *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($MAKE_PROG)" >&5
-$as_echo "yes ($MAKE_PROG)" >&6; }
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes ($MAKE_PROG)" >&5
+printf "%s\n" "yes ($MAKE_PROG)" >&6; }
;;
esac
-# Find a good install program. We prefer a C program (faster),
+
+ # Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
@@ -4208,20 +5251,25 @@ esac
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test ${ac_cv_path_install+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+ ./ | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
@@ -4231,13 +5279,13 @@ case $as_dir/ in #((
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# program-specific install script used by HP pwplus--don't use.
:
else
@@ -4245,12 +5293,12 @@ case $as_dir/ in #((
echo one > conftest.one
echo two > conftest.two
mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
test -s conftest.one && test -s conftest.two &&
test -s conftest.dir/conftest.one &&
test -s conftest.dir/conftest.two
then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
break 3
fi
fi
@@ -4266,7 +5314,7 @@ IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
fi
- if test "${ac_cv_path_install+set}" = set; then
+ if test ${ac_cv_path_install+y}; then
INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. Don't cache a
@@ -4276,8 +5324,8 @@ fi
INSTALL=$ac_install_sh
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
@@ -4294,25 +5342,26 @@ if test X"${INSTALL}" = "X${ac_aux_dir}/install-sh -c" && test -f /usr/ucb/insta
esac
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+printf %s "checking whether ln -s works... " >&6; }
LN_S=$as_ln_s
if test "$LN_S" = "ln -s"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+printf "%s\n" "no, using $LN_S" >&6; }
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
@@ -4320,11 +5369,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4335,11 +5388,11 @@ fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4348,11 +5401,12 @@ if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
@@ -4360,11 +5414,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4375,11 +5433,11 @@ fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_RANLIB" = x; then
@@ -4387,8 +5445,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
@@ -4401,11 +5459,12 @@ for ac_prog in perl5 perl
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PERL+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PERL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $PERL in
[\\/]* | ?:[\\/]*)
ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
@@ -4416,11 +5475,15 @@ as_dummy="/usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH}"
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PERL="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -4432,11 +5495,11 @@ esac
fi
PERL=$ac_cv_path_PERL
if test -n "$PERL"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
-$as_echo "$PERL" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
+printf "%s\n" "$PERL" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -4456,209 +5519,236 @@ fi
#
# Get erts version from erts/vsn.mk
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking ERTS version" >&5
-$as_echo_n "checking ERTS version... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking ERTS version" >&5
+printf %s "checking ERTS version... " >&6; }
ERTS_VSN=`sed -n "s/^VSN[ ]*=[ ]*\(.*\)/\1/p" < $ERL_TOP/erts/vsn.mk`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERTS_VSN" >&5
-$as_echo "$ERTS_VSN" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ERTS_VSN" >&5
+printf "%s\n" "$ERTS_VSN" >&6; }
#
# Get OTP release and OTP version from $ERL_TOP/OTP_VERSION
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OTP release" >&5
-$as_echo_n "checking OTP release... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OTP release" >&5
+printf %s "checking OTP release... " >&6; }
OTP_REL=`cat $ERL_TOP/OTP_VERSION | sed "s|\([0-9]*\).*|\1|"`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTP_REL" >&5
-$as_echo "$OTP_REL" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTP_REL" >&5
+printf "%s\n" "$OTP_REL" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OTP version" >&5
-$as_echo_n "checking OTP version... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OTP version" >&5
+printf %s "checking OTP version... " >&6; }
OTP_VSN=`cat $ERL_TOP/OTP_VERSION`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTP_VSN" >&5
-$as_echo "$OTP_VSN" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTP_VSN" >&5
+printf "%s\n" "$OTP_VSN" >&6; }
# Check whether --enable-parallel-configure was given.
-if test "${enable_parallel_configure+set}" = set; then :
+if test ${enable_parallel_configure+y}
+then :
enableval=$enable_parallel_configure;
fi
# Check whether --enable-dirty-schedulers was given.
-if test "${enable_dirty_schedulers+set}" = set; then :
+if test ${enable_dirty_schedulers+y}
+then :
enableval=$enable_dirty_schedulers;
fi
# Check whether --enable-plain-emulator was given.
-if test "${enable_plain_emulator+set}" = set; then :
+if test ${enable_plain_emulator+y}
+then :
enableval=$enable_plain_emulator;
fi
# Check whether --with-termcap was given.
-if test "${with_termcap+set}" = set; then :
+if test ${with_termcap+y}
+then :
withval=$with_termcap;
fi
# Check whether --enable-kernel-poll was given.
-if test "${enable_kernel_poll+set}" = set; then :
+if test ${enable_kernel_poll+y}
+then :
enableval=$enable_kernel_poll;
fi
# Check whether --enable-sctp was given.
-if test "${enable_sctp+set}" = set; then :
+if test ${enable_sctp+y}
+then :
enableval=$enable_sctp;
fi
# Check whether --with-dynamic-trace was given.
-if test "${with_dynamic_trace+set}" = set; then :
+if test ${with_dynamic_trace+y}
+then :
withval=$with_dynamic_trace;
fi
# Check whether --enable-vm-probes was given.
-if test "${enable_vm_probes+set}" = set; then :
+if test ${enable_vm_probes+y}
+then :
enableval=$enable_vm_probes;
fi
# Check whether --with-javac was given.
-if test "${with_javac+set}" = set; then :
+if test ${with_javac+y}
+then :
withval=$with_javac;
fi
# Check whether --enable-megaco_flex_scanner_lineno was given.
-if test "${enable_megaco_flex_scanner_lineno+set}" = set; then :
+if test ${enable_megaco_flex_scanner_lineno+y}
+then :
enableval=$enable_megaco_flex_scanner_lineno;
fi
# Check whether --enable-megaco_reentrant_flex_scanner was given.
-if test "${enable_megaco_reentrant_flex_scanner+set}" = set; then :
+if test ${enable_megaco_reentrant_flex_scanner+y}
+then :
enableval=$enable_megaco_reentrant_flex_scanner;
fi
# Check whether --with-ssl was given.
-if test "${with_ssl+set}" = set; then :
+if test ${with_ssl+y}
+then :
withval=$with_ssl;
fi
# Check whether --with-ssl-incl was given.
-if test "${with_ssl_incl+set}" = set; then :
+if test ${with_ssl_incl+y}
+then :
withval=$with_ssl_incl;
fi
# Check whether --with-ssl-zlib was given.
-if test "${with_ssl_zlib+set}" = set; then :
+if test ${with_ssl_zlib+y}
+then :
withval=$with_ssl_zlib;
fi
# Check whether --with-ssl-lib-subdir was given.
-if test "${with_ssl_lib_subdir+set}" = set; then :
+if test ${with_ssl_lib_subdir+y}
+then :
withval=$with_ssl_lib_subdir;
fi
# Check whether --with-ssl-rpath was given.
-if test "${with_ssl_rpath+set}" = set; then :
+if test ${with_ssl_rpath+y}
+then :
withval=$with_ssl_rpath;
fi
# Check whether --enable-dynamic-ssl-lib was given.
-if test "${enable_dynamic_ssl_lib+set}" = set; then :
+if test ${enable_dynamic_ssl_lib+y}
+then :
enableval=$enable_dynamic_ssl_lib;
fi
# Check whether --enable-fips was given.
-if test "${enable_fips+set}" = set; then :
+if test ${enable_fips+y}
+then :
enableval=$enable_fips;
fi
# Check whether --enable-builtin-zlib was given.
-if test "${enable_builtin_zlib+set}" = set; then :
+if test ${enable_builtin_zlib+y}
+then :
enableval=$enable_builtin_zlib;
fi
# Check whether --enable-esock was given.
-if test "${enable_esock+set}" = set; then :
+if test ${enable_esock+y}
+then :
enableval=$enable_esock;
fi
# Check whether --enable-sharing-preserving was given.
-if test "${enable_sharing_preserving+set}" = set; then :
+if test ${enable_sharing_preserving+y}
+then :
enableval=$enable_sharing_preserving;
fi
# Check whether --enable-m64-build was given.
-if test "${enable_m64_build+set}" = set; then :
+if test ${enable_m64_build+y}
+then :
enableval=$enable_m64_build; case "$enableval" in
no) enable_m64_build=no ;;
*) enable_m64_build=yes ;;
esac
-else
+else $as_nop
enable_m64_build=no
fi
# Check whether --enable-m32-build was given.
-if test "${enable_m32_build+set}" = set; then :
+if test ${enable_m32_build+y}
+then :
enableval=$enable_m32_build; case "$enableval" in
no) enable_m32_build=no ;;
*) enable_m32_build=yes ;;
esac
-else
+else $as_nop
enable_m32_build=no
fi
# Check whether --enable-pie was given.
-if test "${enable_pie+set}" = set; then :
+if test ${enable_pie+y}
+then :
enableval=$enable_pie;
fi
# Check whether --with-libatomic_ops was given.
-if test "${with_libatomic_ops+set}" = set; then :
+if test ${with_libatomic_ops+y}
+then :
withval=$with_libatomic_ops;
fi
# Check whether --enable-sanitizers was given.
-if test "${enable_sanitizers+set}" = set; then :
+if test ${enable_sanitizers+y}
+then :
enableval=$enable_sanitizers;
fi
# Check whether --enable-silent-rules was given.
-if test "${enable_silent_rules+set}" = set; then :
+if test ${enable_silent_rules+y}
+then :
enableval=$enable_silent_rules;
fi
@@ -4683,432 +5773,69 @@ if test X${enable_m32_build} = Xyes; then
fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
+done
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-fi
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
fi
-done
-
-
-
NEED_NPTL_PTHREAD_H=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
-$as_echo_n "checking for native win32 threads... " >&6; }
-if test "X$host_os" = "Xwin32"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for native win32 threads" >&5
+printf %s "checking for native win32 threads... " >&6; }
+if test "X$host_os" = "Xwin32"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
THR_DEFS="-DWIN32_THREADS"
THR_LIBS=
THR_LIB_NAME=win32_threads
THR_LIB_TYPE=win32_threads
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
THR_DEFS=
THR_LIBS=
THR_LIB_NAME=
THR_LIB_TYPE=posix_unknown
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+printf %s "checking for pthread_create in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpthread $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5117,40 +5844,42 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pthread_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_pthread_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes
+then :
THR_LIBS="-lpthread"
fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
-$as_echo_n "checking for pthread_create in -lc_r... " >&6; }
-if ${ac_cv_lib_c_r_pthread_create+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5
+printf %s "checking for pthread_create in -lc_r... " >&6; }
+if test ${ac_cv_lib_c_r_pthread_create+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc_r $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5159,96 +5888,112 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char pthread_create ();
int
-main ()
+main (void)
{
return pthread_create ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_c_r_pthread_create=yes
-else
+else $as_nop
ac_cv_lib_c_r_pthread_create=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
-$as_echo "$ac_cv_lib_c_r_pthread_create" >&6; }
-if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5
+printf "%s\n" "$ac_cv_lib_c_r_pthread_create" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_create" = xyes
+then :
THR_LIBS="-lc_r"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
-if test "x$ac_cv_func_pthread_create" = xyes; then :
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes
+then :
THR_LIBS="none_needed"
fi
- fi
- if test "x$THR_LIBS" = "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
-$as_echo_n "checking if the '-pthread' switch can be used... " >&6; }
+fi
+
+ if test "x$THR_LIBS" = "x"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the '-pthread' switch can be used" >&5
+printf %s "checking if the '-pthread' switch can be used... " >&6; }
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -pthread"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pthread.h>
int
-main ()
+main (void)
{
pthread_create((void*)0,(void*)0,(void*)0,(void*)0);
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
THR_DEFS="-pthread"
THR_LIBS="-pthread"
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
CFLAGS=$saved_cflags
if test "x$THR_LIBS" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- fi
- if test "x$THR_LIBS" != "x"; then
+fi
+
+ if test "x$THR_LIBS" != "x"
+then :
+
THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS"
THR_LIB_NAME=pthread
if test "x$THR_LIBS" = "xnone_needed"; then
THR_LIBS=
fi
- case $host_os in
- solaris*)
- THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;;
- linux*)
+ case $host_os in #(
+ solaris*) :
+
+ THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS"
+ ;; #(
+ linux*) :
+
THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS"
-if test "$cross_compiling" != "yes"; then
+if test "$cross_compiling" != "yes"
+then :
+
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -5256,11 +6001,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5272,23 +6021,26 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-else
+
+else $as_nop
+
host_getconf="$host_alias-getconf"
# Extract the first word of "$host_getconf", so it can be a program name with args.
set dummy $host_getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$GETCONF"; then
ac_cv_prog_GETCONF="$GETCONF" # Let the user override the test.
else
@@ -5296,11 +6048,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_GETCONF="$host_getconf"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5312,25 +6068,28 @@ fi
fi
GETCONF=$ac_cv_prog_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
- if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then
+ if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""
+then :
+
GETCONF=
prfx="$erl_xcomp_sysroot"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args.
set dummy ${ac_tool_prefix}getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
@@ -5341,11 +6100,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5357,11 +6120,11 @@ esac
fi
GETCONF=$ac_cv_path_GETCONF
if test -n "$GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
-$as_echo "$GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5
+printf "%s\n" "$GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5370,11 +6133,12 @@ if test -z "$ac_cv_path_GETCONF"; then
ac_pt_GETCONF=$GETCONF
# Extract the first word of "getconf", so it can be a program name with args.
set dummy getconf; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_GETCONF+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_GETCONF+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_GETCONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_GETCONF="$ac_pt_GETCONF" # Let the user override the test with a path.
@@ -5385,11 +6149,15 @@ as_dummy=""$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin""
for as_dir in $as_dummy
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_GETCONF="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_GETCONF="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5401,11 +6169,11 @@ esac
fi
ac_pt_GETCONF=$ac_cv_path_ac_pt_GETCONF
if test -n "$ac_pt_GETCONF"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
-$as_echo "$ac_pt_GETCONF" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_GETCONF" >&5
+printf "%s\n" "$ac_pt_GETCONF" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_GETCONF" = x; then
@@ -5413,8 +6181,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
GETCONF=$ac_pt_GETCONF
@@ -5423,11 +6191,13 @@ else
GETCONF="$ac_cv_path_GETCONF"
fi
- fi
+
+fi
+
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
-$as_echo_n "checking for Native POSIX Thread Library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Native POSIX Thread Library" >&5
+printf %s "checking for Native POSIX Thread Library... " >&6; }
libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null`
if test $? -eq 0; then
case "$libpthr_vsn" in
@@ -5443,24 +6213,28 @@ $as_echo_n "checking for Native POSIX Thread Library... " >&6; }
else
nptl=no
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
-$as_echo "$nptl" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $nptl" >&5
+printf "%s\n" "$nptl" >&6; }
if test $nptl = cross; then
nptl=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: result yes guessed because of cross compilation" >&5
+printf "%s\n" "$as_me: WARNING: result yes guessed because of cross compilation" >&2;}
fi
- if test $nptl = yes; then
+ if test $nptl = yes
+then :
+
THR_LIB_TYPE=posix_nptl
need_nptl_incldir=no
- ac_fn_c_check_header_mongrel "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_nptl_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "nptl/pthread.h" "ac_cv_header_nptl_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_nptl_pthread_h" = xyes
+then :
need_nptl_incldir=yes
NEED_NPTL_PTHREAD_H=yes
fi
+ if test $need_nptl_incldir = yes
+then :
- if test $need_nptl_incldir = yes; then
# Ahh...
nptl_path="$C_INCLUDE_PATH:$CPATH"
if test X$cross_compiling != Xyes; then
@@ -5481,13 +6255,13 @@ fi
IFS=$save_ifs
nptl_incldir=
for dir in $nptl_ws_path; do
- as_ac_Header=`$as_echo "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$dir/nptl/pthread.h" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$dir/nptl/pthread.h" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
nptl_incldir=$dir/nptl
fi
-
if test "x$nptl_incldir" != "x"; then
THR_DEFS="$THR_DEFS -isystem $nptl_incldir"
break
@@ -5496,38 +6270,43 @@ fi
if test "x$nptl_incldir" = "x"; then
as_fn_error $? "Failed to locate nptl system include directory" "$LINENO" 5
fi
- fi
- fi
- ;;
- *) ;;
- esac
+
+fi
+
+fi
+ ;; #(
+ *) :
+ ;;
+esac
saved_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $THR_DEFS"
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
-$as_echo "#define HAVE_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
fi
-
- ac_fn_c_check_header_mongrel "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "pthread/mit/pthread.h" "ac_cv_header_pthread_mit_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_mit_pthread_h" = xyes
+then :
\
-$as_echo "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_MIT_PTHREAD_H 1" >>confdefs.h
fi
-
CPPFLAGS=$saved_cppflags
- fi
+
+fi
+
fi
@@ -5571,181 +6350,253 @@ case "$host_cpu" in
esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Wdeclaration-after-statement to DED_WARN_FLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WARN_FLAGS="-Wdeclaration-after-statement $DED_WARN_FLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=return-type to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=return-type $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=return-type $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=implicit to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=implicit $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=implicit $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -Werror=undef to DED_WERRORFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-Werror=undef $DED_WERRORFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_WERRORFLAGS="-Werror=undef $DED_WERRORFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_SYS_INCLUDE="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$DED_OSTYPE -I${ERL_TOP}/erts/emulator/sys/common"
DED_INCLUDE=$DED_SYS_INCLUDE
DED_CFLAGS="$CFLAGS $CPPFLAGS $DED_CFLAGS"
-if test "x$GCC" = xyes; then
+if test "x$GCC" = xyes
+then :
+
# Use -fno-common for gcc, that is link error if multiple definitions of
# global variables are encountered. This is ISO C compliant.
# Until version 10, gcc has had -fcommon as default, which allows and merges
# such dubious duplicates.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
-$as_echo_n "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-common to DED_CFLAGS (via CFLAGS)... " >&6; }
saved_CFLAGS=$CFLAGS;
CFLAGS="-fno-common $DED_CFLAGS";
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
can_enable_flag=true
-else
+else $as_nop
can_enable_flag=false
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$saved_CFLAGS;
- if test "X$can_enable_flag" = "Xtrue"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
DED_CFLAGS="-fno-common $DED_CFLAGS"
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)" >&5
+printf %s "checking if we can add -fno-strict-aliasing to DED_CFLAGS (via CFLAGS)... " >&6; }
+ saved_CFLAGS=$CFLAGS;
+ CFLAGS="-fno-strict-aliasing $DED_CFLAGS";
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ can_enable_flag=true
+else $as_nop
+ can_enable_flag=false
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$saved_CFLAGS;
+ if test "X$can_enable_flag" = "Xtrue"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ DED_CFLAGS="-fno-strict-aliasing $DED_CFLAGS"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
DED_STATIC_CFLAGS="$DED_CFLAGS"
DED_CFLAGS="$DED_CFLAGS -fPIC"
# Remove -fPIE and -fno-PIE
DED_CFLAGS=`echo $DED_CFLAGS | sed 's/-f\(no-\)\?PIE//g'`
+
fi
DED_EXT=so
@@ -5832,17 +6683,19 @@ case $host_os in
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
@@ -5851,14 +6704,12 @@ See \`config.log' for more details" "$LINENO" 5; }
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
case "$ac_cv_sizeof_void_p" in
@@ -5925,11 +6776,12 @@ test "$DED_LDFLAGS_CONFTEST" != "" || DED_LDFLAGS_CONFTEST="$DED_LDFLAGS"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$DED_LD"; then
ac_cv_prog_DED_LD="$DED_LD" # Let the user override the test.
else
@@ -5937,11 +6789,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_DED_LD="${ac_tool_prefix}ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5952,11 +6808,11 @@ fi
fi
DED_LD=$ac_cv_prog_DED_LD
if test -n "$DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
@@ -5965,11 +6821,12 @@ if test -z "$ac_cv_prog_DED_LD"; then
ac_ct_DED_LD=$DED_LD
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DED_LD+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DED_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_DED_LD"; then
ac_cv_prog_ac_ct_DED_LD="$ac_ct_DED_LD" # Let the user override the test.
else
@@ -5977,11 +6834,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_DED_LD="ld"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
@@ -5992,11 +6853,11 @@ fi
fi
ac_ct_DED_LD=$ac_cv_prog_ac_ct_DED_LD
if test -n "$ac_ct_DED_LD"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
-$as_echo "$ac_ct_DED_LD" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DED_LD" >&5
+printf "%s\n" "$ac_ct_DED_LD" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_DED_LD" = x; then
@@ -6004,8 +6865,8 @@ fi
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
DED_LD=$ac_ct_DED_LD
@@ -6016,37 +6877,37 @@ fi
test "$DED_LD" != "false" || as_fn_error $? "No linker found" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
-$as_echo_n "checking for static compiler flags... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for static compiler flags" >&5
+printf %s "checking for static compiler flags... " >&6; }
DED_STATIC_CFLAGS="$DED_WERRORFLAGS $DED_WFLAGS $DED_THR_DEFS $DED_STATIC_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
-$as_echo "$DED_STATIC_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
-$as_echo_n "checking for basic compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_STATIC_CFLAGS" >&5
+printf "%s\n" "$DED_STATIC_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for basic compiler flags for loadable drivers" >&5
+printf %s "checking for basic compiler flags for loadable drivers... " >&6; }
DED_BASIC_CFLAGS=$DED_CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
-$as_echo_n "checking for compiler flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler flags for loadable drivers" >&5
+printf %s "checking for compiler flags for loadable drivers... " >&6; }
DED_CFLAGS="$DED_WERRORFLAGS $DED_WARN_FLAGS $DED_THR_DEFS $DED_CFLAGS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
-$as_echo "$DED_CFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
-$as_echo_n "checking for linker for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
-$as_echo "$DED_LD" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
-$as_echo_n "checking for linker flags for loadable drivers... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
-$as_echo "$DED_LDFLAGS" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
-$as_echo_n "checking for 'runtime library path' linker flag... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_CFLAGS" >&5
+printf "%s\n" "$DED_CFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker for loadable drivers" >&5
+printf %s "checking for linker for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD" >&5
+printf "%s\n" "$DED_LD" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable drivers" >&5
+printf %s "checking for linker flags for loadable drivers... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LDFLAGS" >&5
+printf "%s\n" "$DED_LDFLAGS" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 'runtime library path' linker flag" >&5
+printf %s "checking for 'runtime library path' linker flag... " >&6; }
if test "x$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" != "x"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
-$as_echo "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&5
+printf "%s\n" "$DED_LD_FLAG_RUNTIME_LIBRARY_PATH" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
fi
@@ -6101,8 +6962,8 @@ _ACEOF
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
@@ -6132,15 +6993,15 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
@@ -6154,8 +7015,8 @@ $as_echo "$as_me: updating cache $cache_file" >&6;}
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
@@ -6208,7 +7069,7 @@ U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
@@ -6224,8 +7085,8 @@ LTLIBOBJS=$ac_ltlibobjs
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
@@ -6248,14 +7109,16 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
@@ -6265,46 +7128,46 @@ esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -6313,13 +7176,6 @@ if test "${PATH_SEPARATOR+set}" != set; then
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
@@ -6328,8 +7184,12 @@ case $0 in #((
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
@@ -6341,30 +7201,10 @@ if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
@@ -6377,13 +7217,14 @@ as_fn_error ()
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
@@ -6410,18 +7251,20 @@ as_fn_unset ()
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
@@ -6433,12 +7276,13 @@ fi # as_fn_append
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
@@ -6469,7 +7313,7 @@ as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
@@ -6491,6 +7335,10 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
@@ -6504,6 +7352,12 @@ case `echo -n x` in #(((((
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
@@ -6545,7 +7399,7 @@ as_fn_mkdir_p ()
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
@@ -6554,7 +7408,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -6617,7 +7471,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# values after options handling.
ac_log="
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
@@ -6666,14 +7520,16 @@ $config_files
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
@@ -6711,21 +7567,21 @@ do
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h | --help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
@@ -6753,7 +7609,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
@@ -6767,7 +7623,7 @@ exec 5>>config.log
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
@@ -6795,7 +7651,7 @@ done
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
fi
# Have a temporary directory for convenience. Make it in the build tree
@@ -7023,7 +7879,7 @@ do
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
@@ -7031,17 +7887,17 @@ do
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
@@ -7058,7 +7914,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
@@ -7082,9 +7938,9 @@ $as_echo X"$ac_file" |
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
@@ -7141,8 +7997,8 @@ ac_sed_dataroot='
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
@@ -7185,9 +8041,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
@@ -7239,7 +8095,8 @@ if test "$no_create" != yes; then
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
+
diff --git a/make/configure.in b/make/configure.ac
index 660c51e363..e0d4103b6e 100644
--- a/make/configure.in
+++ b/make/configure.ac
@@ -18,9 +18,11 @@ dnl limitations under the License.
dnl
dnl %CopyrightEnd%
-AC_PREREQ(2.8)dnl
+AC_PREREQ([2.71])dnl
-AC_INIT()
+AC_INIT
+
+m4_include([otp.m4])
LM_PRECIOUS_VARS
@@ -82,42 +84,14 @@ AC_SUBST(ERL_TOP)
dnl
dnl Aux programs are found in erts/autoconf
dnl
-AC_CONFIG_AUX_DIR(${ERL_TOP}/erts/autoconf)
+AC_CONFIG_AUX_DIRS([${ERL_TOP}/make/autoconf])
-dnl
-dnl Figure out what we are running on. And in violation of autoconf
-dnl style assume that $host is also what we are building for. I would
-dnl like to get cross compiling working, since we actually have
-dnl systems we cross compile for!
-dnl
-
-if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
- AC_CANONICAL_HOST
- AC_CANONICAL_BUILD
-else
- host_os=$host
-fi
+ERL_CANONICAL_SYSTEM_TYPE
TARGET=$host
AC_SUBST(TARGET)
if test "$cross_compiling" = "yes"; then
- if test "$build" = "$host"; then
- AC_MSG_ERROR([
- Cross compiling with the same canonicalized 'host' value
- as the canonicalized 'build' value.
-
- We are cross compiling since the '--host=$host_alias'
- and the '--build=$build_alias' arguments differ. When
- cross compiling Erlang/OTP also the canonicalized values of
- the '--build' and the '--host' arguments *must* differ. The
- canonicalized values of these arguments however both equals:
- $host
-
- You can check the canonical value by passing a value as
- argument to the 'erts/autoconf/config.sub' script.
- ])
- fi
CROSS_COMPILING=yes
else
CROSS_COMPILING=no
diff --git a/make/cross_check_erl b/make/cross_check_erl
index fd9af6bae8..10bad47f98 100755
--- a/make/cross_check_erl
+++ b/make/cross_check_erl
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2021. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -118,7 +118,7 @@ test "X$build_otp" = "X$used_otp" || {
* ERROR: Trying to cross compile an Erlang/$build_otp system with a different
* Erlang/$used_otp system. When cross compiling you should compile
* with an Erlang/OTP system of the same release. It is possible,
-* however not recomended, to force the cross compilation even though
+* however not recommended, to force the cross compilation even though
* the wrong Erlang/OTP system is used. For more information on this,
* and cross compiling Erlang/$build_otp in general, see the
* \$ERL_TOP/xcomp/README file.
diff --git a/make/doc.mk b/make/doc.mk
index 47bb1c62ac..119dc75971 100644
--- a/make/doc.mk
+++ b/make/doc.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ RELCHUNKSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
APP_DIR = $(ERL_TOP)/lib/$(APPLICATION)
APP_SRC_DIR = $(APP_DIR)/src
-APP_EBIN_DIR = $(APP_DIR)/src
+APP_EBIN_DIR = $(APP_DIR)/ebin
# ----------------------------------------------------
HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
@@ -71,7 +71,7 @@ endif
CHUNK_REF3_FILES = $(filter-out $(NO_CHUNKS), $(XML_ALL_REF3_FILES))
CHUNK_FILES = $(CHUNK_REF3_FILES:%.xml=$(CHUNKSDIR)/%.chunk)
-ERL_CHUNK_FILES = $(patsubst $(APP_EBIN_DIR)/%.BEAM,$(CHUNKSDIR)/%.chunk,$(wildcard $(APP_EBIN_DIR)/*.beam))
+ERL_CHUNK_FILES = $(patsubst $(APP_EBIN_DIR)/%.beam,$(CHUNKSDIR)/%.chunk,$(wildcard $(APP_EBIN_DIR)/*.beam))
EMPTY_CHUNK_FILES = $(filter-out $(NO_CHUNKS:%.xml=$(CHUNKSDIR)/%.chunk) $(CHUNK_FILES), $(ERL_CHUNK_FILES))
@@ -129,7 +129,7 @@ info:
@echo "XML_CHAPTER_FILES: $(XML_CHAPTER_FILES)"
@echo "BOOK_FILES: $(BOOK_FILES)"
-debug opt lcnt:
+$(TYPES):
clean clean_docs: clean_xml clean_pdf clean_html clean_man clean_chunks
rm -rf $(EXTRA_FILES)
diff --git a/make/emd2exml.in b/make/emd2exml.in
index faed9ebe69..0180d718bf 100755
--- a/make/emd2exml.in
+++ b/make/emd2exml.in
@@ -5,7 +5,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -317,7 +317,7 @@ parse(#state{line = Line} = S) ->
parse(get_line(put_text(S, Line))).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Auxilary functions
+%%% Auxiliary functions
%%%
%%
diff --git a/make/install_bin b/make/install_bin
index 3337e68a9f..86c453519e 100755
--- a/make/install_bin
+++ b/make/install_bin
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2021. All Rights Reserved.
+# Copyright Ericsson AB 2010-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -681,7 +681,7 @@ EOF
done
# Remove after possible old install (done in a separate pass since I think
-# the output looks nicer than if mixed). Note that we cannot test for existance
+# the output looks nicer than if mixed). Note that we cannot test for existence
# in a portable way, so force remove.
for file in "$@"; do
test "$file" != "" || continue
diff --git a/make/otp.mk.in b/make/otp.mk.in
index 2443c71a08..61654ad5cb 100644
--- a/make/otp.mk.in
+++ b/make/otp.mk.in
@@ -4,7 +4,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -47,14 +47,13 @@ CROSS_COMPILING = @CROSS_COMPILING@
# ----------------------------------------------------
DEFAULT_TARGETS = opt debug release release_docs clean docs
-TYPES = @TYPES@
+TYPES = opt debug lcnt valgrind asan gcov
+DEFAULT_TYPES = @DEFAULT_TYPES@
FLAVORS = @FLAVORS@
PRIMARY_FLAVOR= @PRIMARY_FLAVOR@
USE_PGO = @USE_PGO@
-USE_ESOCK = @USE_ESOCK@
-
# Slash separated list of return values from $(origin VAR)
# that are untrusted - set default in this file instead.
# The list is not space separated since some return values
@@ -93,6 +92,8 @@ BITS64 = @BITS64@
OTP_RELEASE = @OTP_RELEASE@
+ERL_DETERMINISTIC = @ERL_DETERMINISTIC@
+
# ----------------------------------------------------
# Erlang language section
# ----------------------------------------------------
@@ -105,8 +106,10 @@ ifdef BOOTSTRAP
else
ERL_COMPILE_FLAGS += +debug_info
endif
-ifeq ($(USE_ESOCK),yes)
-ERL_COMPILE_FLAGS += -DUSE_ESOCK=true
+ifeq ($(ERL_DETERMINISTIC),yes)
+ ERL_COMPILE_FLAGS += +deterministic
+ YRL_FLAGS += +deterministic
+ XRL_FLAGS += +deterministic
endif
ERLC_WFLAGS = -W
diff --git a/make/otp_patch_solve_forward_merge_version b/make/otp_patch_solve_forward_merge_version
index 98d9bcb75a..d6b24041cf 100644
--- a/make/otp_patch_solve_forward_merge_version
+++ b/make/otp_patch_solve_forward_merge_version
@@ -1 +1 @@
-17
+19
diff --git a/make/otp_subdir.mk b/make/otp_subdir.mk
index 6ccf727c75..12dfc5153d 100644
--- a/make/otp_subdir.mk
+++ b/make/otp_subdir.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,13 +19,13 @@
#
# Make include file for otp
-.PHONY: debug opt lcnt release docs release_docs tests release_tests \
- clean depend valgrind asan static_lib
+.PHONY: $(TYPES) release docs release_docs tests release_tests \
+ clean depend static_lib
#
# Targets that don't affect documentation directories
#
-opt debug lcnt release docs release_docs tests release_tests clean depend valgrind asan static_lib xmllint:
+$(TYPES) release docs release_docs tests release_tests clean depend static_lib xmllint:
@set -e ; \
app_pwd=`pwd` ; \
if test -f vsn.mk; then \
diff --git a/make/otp_version_tickets b/make/otp_version_tickets
index 69c9db2245..23c2246bcb 100644
--- a/make/otp_version_tickets
+++ b/make/otp_version_tickets
@@ -1,18 +1,44 @@
-OTP-17970
-OTP-18027
-OTP-18028
-OTP-18056
-OTP-18061
-OTP-18062
-OTP-18064
-OTP-18065
-OTP-18066
-OTP-18069
-OTP-18071
-OTP-18075
-OTP-18076
-OTP-18077
-OTP-18078
-OTP-18080
-OTP-18081
-OTP-18082
+OTP-16607
+OTP-18316
+OTP-18348
+OTP-18356
+OTP-18366
+OTP-18371
+OTP-18372
+OTP-18373
+OTP-18374
+OTP-18375
+OTP-18378
+OTP-18380
+OTP-18381
+OTP-18382
+OTP-18384
+OTP-18387
+OTP-18390
+OTP-18391
+OTP-18392
+OTP-18393
+OTP-18398
+OTP-18404
+OTP-18406
+OTP-18407
+OTP-18408
+OTP-18411
+OTP-18412
+OTP-18418
+OTP-18426
+OTP-18429
+OTP-18432
+OTP-18434
+OTP-18443
+OTP-18446
+OTP-18454
+OTP-18457
+OTP-18458
+OTP-18460
+OTP-18463
+OTP-18469
+OTP-18470
+OTP-18472
+OTP-18475
+OTP-18496
diff --git a/make/otp_version_tickets_in_merge b/make/otp_version_tickets_in_merge
index 295f43e3ce..e69de29bb2 100644
--- a/make/otp_version_tickets_in_merge
+++ b/make/otp_version_tickets_in_merge
@@ -1,2 +0,0 @@
-OTP-17850
-OTP-17922
diff --git a/make/run_make.mk b/make/run_make.mk
index 4185927f72..271e2e0f36 100644
--- a/make/run_make.mk
+++ b/make/run_make.mk
@@ -29,7 +29,7 @@
include $(ERL_TOP)/make/output.mk
include $(ERL_TOP)/make/target.mk
-.PHONY: valgrind asan
+.PHONY: valgrind asan test
opt debug valgrind asan gcov gprof lcnt frmptr icount:
$(make_verbose)$(MAKE) -f $(TARGET)/Makefile TYPE=$@
diff --git a/make/target.mk b/make/target.mk
index abb586ebee..3c66e94372 100644
--- a/make/target.mk
+++ b/make/target.mk
@@ -24,7 +24,7 @@ ifeq ($(OVERRIDE_TARGET),)
ifeq ($(TARGET),)
-TARGET := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
+TARGET := $(shell $(ERL_TOP)/make/autoconf/config.guess)
else
@@ -55,7 +55,7 @@ endif
ifneq ($(TARGET),)
ifneq ($(TARGET),win32)
-override TARGET := $(shell $(ERL_TOP)/erts/autoconf/config.sub $(TARGET))
+override TARGET := $(shell $(ERL_TOP)/make/autoconf/config.sub $(TARGET))
else
endif
else
diff --git a/make/test_target_script.sh b/make/test_target_script.sh
index df9d06a427..b21185fd06 100755
--- a/make/test_target_script.sh
+++ b/make/test_target_script.sh
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2021. All Rights Reserved.
+# Copyright Ericsson AB 1997-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@
# %CopyrightEnd%
#
-
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
@@ -58,8 +57,13 @@ All tests will require several hours to run. You may want to check the
following text file that describes how to run tests for a specific
application.
+ $ERL_TOP/HOWTO/TESTING.md
+
+You can follow the test results here:
+
+ file://$ERL_TOP/release/tests/test_server/index.html
+
EOM
- echo $ERL_TOP/HOWTO/TESTING.md
}
print_highlighted_msg_with_printer $YELLOW print_msg
}
@@ -90,25 +94,6 @@ EOM
print_highlighted_msg_with_printer $LIGHT_CYAN print_msg
}
-print_c_files_warning () {
- print_msg () {
- cat << EOM
-
-WARNING
-
-The test directory contains .c files which means that some test cases
-will probably not work correctly when run through "make test". The
-text file at the following location describes how one can compile and
-run all test cases:
-
-
-EOM
- echo $ERL_TOP/HOWTO/TESTING.md
- }
- print_highlighted_msg_with_printer $YELLOW print_msg
-}
-
-
print_on_error_note () {
print_msg () {
cat << EOM
@@ -128,6 +113,18 @@ EOM
print_highlighted_msg_with_printer $NC print_msg
}
+release_erlang () {
+ local RELEASE_ROOT=${1}
+ if ! (cd $ERL_TOP && make release RELEASE_ROOT="${RELEASE_ROOT}"); then
+ return 1
+ fi
+ if ! (cd "$RELEASE_ROOT" && ./Install -minimal "`pwd`"); then
+ return 1
+ fi
+ export PATH="${RELEASE_ROOT}/bin:$PATH"
+ return 0
+}
+
# Check ERL_TOP
if [ -d "$1" ]
@@ -150,7 +147,6 @@ fi
export ERL_TOP=$ERL_TOP
-
if [ -z "${ARGS}" ]
then
ARGS="$@"
@@ -160,7 +156,7 @@ fi
DIR=`pwd`
if [ "$DIR" -ef "$ERL_TOP" ]
then
- TARGET_SYS=`$ERL_TOP/erts/autoconf/config.guess`
+ TARGET_SYS=`$ERL_TOP/make/autoconf/config.guess`
REL_DIR="$ERL_TOP/release/$TARGET_SYS"
cd "$REL_DIR"
./Install -minimal "`pwd`"
@@ -182,15 +178,47 @@ then
exit 1
fi
-
APPLICATION="`basename $DIR`"
+
+if [ "$APPLICATION" = "erts" ]; then
+ APPLICATION="system"
+fi
+
CT_RUN="$ERL_TOP/bin/ct_run"
+PATH="${ERL_TOP}/bin/:${PATH}"
MAKE_TEST_DIR="`pwd`/make_test_dir"
MAKE_TEST_REL_DIR="$MAKE_TEST_DIR/${APPLICATION}_test"
MAKE_TEST_CT_LOGS="$MAKE_TEST_DIR/ct_logs"
-RELEASE_TEST_SPEC_LOG="$MAKE_TEST_CT_LOGS/release_tests_spec_log"
+RELEASE_TEST_SPEC_LOG="$MAKE_TEST_DIR/release_tests_spec_log"
+INSTALL_TEST_LOG="$MAKE_TEST_DIR/install_tests_log"
+COMPILE_TEST_LOG="$MAKE_TEST_DIR/compile_tests_log"
+RELEASE_ROOT="${MAKE_TEST_DIR}/otp"
+RELEASE_LOG="$MAKE_TEST_DIR/release_tests_log"
cd test
+
+mkdir -p "$MAKE_TEST_DIR"
+mkdir -p "$MAKE_TEST_CT_LOGS"
+
+# Check that we are running a released erlang when we have to
+if [ "$TEST_NEEDS_RELEASE" = "true" ]; then
+ MSG=$(cat <<EOF
+This application needs to be tested using a released Erlang/OTP.
+Erlang/OTP will now be released to ${RELEASE_ROOT}.
+EOF
+ )
+ print_highlighted_msg $YELLOW "${MSG}"
+ release_erlang "${RELEASE_ROOT}" > "${RELEASE_LOG}" 2>&1
+ if [ $? != 0 ]
+ then
+ print_highlighted_msg $RED "\"make release RELEASE_ROOT=${RELEASE_ROOT}\" failed.\nSee ${RELEASE_LOG} for full logs"
+ tail -30 "${RELEASE_LOG}"
+ exit 1
+ fi
+ CT_RUN="${RELEASE_ROOT}/bin/ct_run"
+ PATH=${RELEASE_ROOT}/bin/:${PATH}
+fi
+
echo "The tests in test directory for $APPLICATION will be executed with ct_run"
if [ -z "${ARGS}" ]
then
@@ -198,44 +226,84 @@ then
then
print_all_tests_for_application_notes
fi
- if find . -type f -name '*.c' | grep -q "."
- then
- print_c_files_warning
- fi
fi
-mkdir -p "$MAKE_TEST_DIR"
-mkdir -p "$MAKE_TEST_REL_DIR"
-mkdir -p "$MAKE_TEST_CT_LOGS"
-make RELSYSDIR=$MAKE_TEST_REL_DIR release_tests_spec > $RELEASE_TEST_SPEC_LOG 2>&1
+make RELEASE_PATH=$MAKE_TEST_DIR release_tests_spec > $RELEASE_TEST_SPEC_LOG 2>&1
if [ $? != 0 ]
then
cat $RELEASE_TEST_SPEC_LOG
- print_highlighted_msg $RED "\"make RELSYSDIR="$MAKE_TEST_REL_DIR" release_tests_spec\" failed."
+ print_highlighted_msg $RED "\"make RELEASE_PATH="$MAKE_TEST_DIR" release_tests_spec\" failed."
exit 1
fi
-SPEC_FLAG=""
-SPEC_FILE=""
if [ -z "${ARGS}" ]
then
- SPEC_FLAG="-spec"
if [ "${WSLcross}" != "true" ] ; then
+ SPEC_FILE_POSTFIX="$MAKE_TEST_REL_DIR/${APPLICATION}_${SPEC_POSTFIX}.spec"
SPEC_FILE="$MAKE_TEST_REL_DIR/$APPLICATION.spec"
else
+ SPEC_FILE_POSTFIX=`w32_path.sh -m "$MAKE_TEST_REL_DIR/${APPLICATION}_${SPEC_POSTFIX}.spec"`
SPEC_FILE=`w32_path.sh -m "$MAKE_TEST_REL_DIR/$APPLICATION.spec"`
fi
- ARGS="$SPEC_FLAG $SPEC_FILE"
+ if [ -f "$SPEC_FILE_POSTFIX" ]; then
+ SPEC_FILE="$SPEC_FILE_POSTFIX"
+ fi
+ ARGS="-spec $SPEC_FILE"
+fi
+
+ARGS="${ARGS} ${EXTRA_ARGS}"
+
+if ([ -n "${TYPE}" ] || [ -n "${FLAVOR}" ]) && [ "${WSLcross}" = "true" ]; then
+ print_highlighted_msg $RED "Setting TYPE or FLAVOR is not implemented yet for WSL"
+ exit 1;
+fi
+
+if [ -n "${TYPE}" ]; then
+ ERL_AFLAGS="${ERL_AFLAGS} -emu_type ${TYPE}"
+fi
+if [ -n "${FLAVOR}" ]; then
+ ERL_AFLAGS="${ERL_AFLAGS} -emu_flavor ${FLAVOR}"
fi
-# Compile test server
-(cd "$ERL_TOP/lib/common_test/test_server" && make)
+
+# Compile test server and configure
+if [ ! -f "$ERL_TOP/lib/common_test/test_server/variables" ]; then
+ cd "$ERL_TOP/lib/common_test/test_server"
+ ( make && erl -noshell -eval "ts:install()." -s init stop ) > "$INSTALL_TEST_LOG" 2>&1
+ if [ $? != 0 ]
+ then
+ cat "$INSTALL_TEST_LOG"
+ print_highlighted_msg $RED "\"make && erl -eval 'ts:install()'\" in common_test/test_server failed."
+ exit 1
+ fi
+fi
+
# Run ct_run
cd $MAKE_TEST_REL_DIR
+erl -sname test -noshell -pa "$ERL_TOP/lib/common_test/test_server" \
+ -eval "ts:compile_datadirs(\"$ERL_TOP/lib/common_test/test_server/variables\",\"*_SUITE_data\")."\
+ -s init stop > "$COMPILE_TEST_LOG" 2>&1
+
+if [ $? != 0 ]
+then
+ cat "$COMPILE_TEST_LOG"
+ print_highlighted_msg $RED "\"erl -eval 'ts:compile_datadirs/2'\" failed."
+ exit 1
+fi
+
+CT_NODENAME=${CT_NODENAME:-test_server}
+
if [ "${WSLcross}" != "true" ]
then
- $CT_RUN -logdir $MAKE_TEST_CT_LOGS\
+ if [ -n "${CTRUN_TIMEOUT}" ]; then
+ CTRUN_TIMEOUT="timeout -s ABRT --foreground --preserve-status $((${CTRUN_TIMEOUT}+5))m timeout -s USR1 --foreground --preserve-status ${CTRUN_TIMEOUT}m"
+ fi
+ ERL_AFLAGS="${ERL_AFLAGS}" $CTRUN_TIMEOUT \
+ $CT_RUN -logdir $MAKE_TEST_CT_LOGS\
-pa "$ERL_TOP/lib/common_test/test_server"\
+ -config "$ERL_TOP/lib/common_test/test_server/ts.config"\
+ -config "$ERL_TOP/lib/common_test/test_server/ts.unix.config"\
+ -exit_status ignore_config \
${ARGS}\
-erl_args\
-env ERL_CRASH_DUMP "$MAKE_TEST_DIR/${APPLICATION}_erl_crash.dump"\
@@ -245,7 +313,7 @@ then
-pz "."\
-ct_test_vars "{net_dir,\"\"}"\
-noshell\
- -sname test_server\
+ -sname ${CT_NODENAME}\
-rsh ssh\
${ERL_ARGS}
else
@@ -254,6 +322,9 @@ else
WIN_ERL_TOP=`w32_path.sh -m "$ERL_TOP"`
$CT_RUN.exe -logdir $WIN_MAKE_TEST_CT_LOGS\
-pa "$WIN_ERL_TOP/lib/common_test/test_server"\
+ -config "$WIN_ERL_TOP/lib/common_test/test_server/ts.config"\
+ -config "$WIN_ERL_TOP/lib/common_test/test_server/ts.win32.config"\
+ -exit_status ignore_config \
${ARGS}\
-erl_args\
-env ERL_CRASH_DUMP "$WIN_MAKE_TEST_DIR/${APPLICATION}_erl_crash.dump"\
@@ -263,7 +334,7 @@ else
-pz "."\
-ct_test_vars "{net_dir,\"\"}"\
-noshell\
- -sname test_server\
+ -sname ${CT_NODENAME}\
-rsh ssh\
${ERL_ARGS}
fi
diff --git a/otp_build b/otp_build
index 324d64f0db..7b35b39fc2 100755
--- a/otp_build
+++ b/otp_build
@@ -19,15 +19,13 @@
# %CopyrightEnd%
#
-USE_AUTOCONF_VERSION=2.69
+USE_AUTOCONF_VERSION=2.71
-aclocal_dirs="make ./lib/crypto ./lib/erl_interface ./lib/odbc ./lib/wx ./lib/megaco"
-autoconf_aux_dirs="./lib/common_test/priv/auxdir ./lib/erl_interface/src/auxdir ./lib/common_test/test_server ./lib/wx/autoconf"
+autoconf_aux_dirs="./erts/autoconf ./lib/common_test/test_server"
-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"
+install_sh_master="./make/autoconf/install-sh"
+config_guess_master="./make/autoconf/config.guess"
+config_sub_master="./make/autoconf/config.sub"
# Global configuration variables
#
@@ -119,7 +117,7 @@ check_erltop ()
{
ERLTOP_FORCED=false
if [ "X$ERL_TOP" = "X" ]; then
- if [ -f ./otp_build -a -f ./erts/autoconf/config.guess ]; then
+ if [ -f ./otp_build -a -f ./make/autoconf/config.guess ]; then
ERLTOP_FORCED=true
ERL_TOP=`pwd`
export ERL_TOP
@@ -171,11 +169,13 @@ set_config_flags ()
# (in the cross compilation case the whole command line as well as
# the cross configuration have been moved here).
- if target_contains free_source; then
- CONFIG_FLAGS="$CONFIG_FLAGS --host=$TARGET"
- fi
if target_contains win32; then
- CONFIG_FLAGS="--build=$BUILDSYS build_alias=win32 --host=win32 --target=win32 $CONFIG_FLAGS"
+ if [ "$CONFIG_SUBTYPE" = "win64" ]; then
+ bht_type=local-x86_64-pc-windows
+ else
+ bht_type=local-x86-pc-windows
+ fi
+ CONFIG_FLAGS="--build=$bht_type --host=$bht_type --target=$bht_type $CONFIG_FLAGS"
fi
@@ -196,7 +196,8 @@ NL="\
do_update_configure ()
{
get_do_commit $1
-
+
+ export AUTOCONF_VERSION="$USE_AUTOCONF_VERSION"
ac_ver_blob=`autoconf --version`
if [ $? -ne 0 ]; then
echo "ERROR: Failed to check autoconf version! You need to have autoconf of version $USE_AUTOCONF_VERSION in path." 1>&2
@@ -213,10 +214,6 @@ do_update_configure ()
out_files=
- for dir in $aclocal_dirs; do
- $install_sh_master -m 644 -t "$dir" "$aclocal_master"
- done
-
install_sh=`basename $install_sh_master`
config_guess=`basename $config_guess_master`
config_sub=`basename $config_sub_master`
@@ -236,7 +233,7 @@ do_update_configure ()
export TARGET
for d in $AUTOCONF_SUBDIRS; do
- file="$d/configure.in"
+ file="$d/configure.ac"
[ -f "$file" ] || continue
echo ""
[ ! -d "$d/autom4te.cache" ] || {
@@ -249,12 +246,12 @@ do_update_configure ()
}
echo "=== running autoconf in $d"
- ( cd "$d" && autoconf ) || exit 1
+ ( cd "$d" && autoconf -B "$ERL_TOP/make/autoconf") || exit 1
out_files="$out_files $d/configure"
chdr=`cat "$file" | sed -n "s|.*\(AC_CONFIG_HEADER\).*|\1|p"`
[ "$chdr" = "AC_CONFIG_HEADER" ] || continue
echo "=== running autoheader in $d"
- ( cd "$d" && autoheader ) || exit 1
+ ( cd "$d" && autoheader -B "$ERL_TOP/make/autoconf") || exit 1
out_files="$out_files $d/config.h.in"
done
@@ -350,8 +347,8 @@ try_cross_configure ()
test "X$build_value" != "X" || build_value="$BUILDSYS"
- build_sys=`"$ERL_TOP/erts/autoconf/config.sub" "$build_value"` || exit 1
- host_sys=`"$ERL_TOP/erts/autoconf/config.sub" "$host_value"` || exit 1
+ build_sys=`"$ERL_TOP/make/autoconf/config.sub" "$build_value"` || exit 1
+ host_sys=`"$ERL_TOP/make/autoconf/config.sub" "$host_value"` || exit 1
test "$host_sys" = "$build_sys" || cross_configure=yes
@@ -655,15 +652,15 @@ echo_env_cygwin ()
echo_setenv AR ar.sh ';'
echo_setenv RANLIB true ';'
if [ X"$X64" = X"true" ]; then
- 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" ';'
+ if [ -f "$ERL_TOP/make/autoconf/win64.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/make/autoconf/win64.config.cache.static" ';'
fi
- echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win64.config.cache" ';'
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/make/autoconf/win64.config.cache" ';'
else
- 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" ';'
+ if [ -f "$ERL_TOP/make/autoconf/win32.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/make/autoconf/win32.config.cache.static" ';'
fi
- echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win32.config.cache" ';'
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/make/autoconf/win32.config.cache" ';'
fi
echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
@@ -720,15 +717,15 @@ echo_env_msys ()
echo_setenv AR ar.sh ';'
echo_setenv RANLIB true ';'
if [ X"$X64" = X"true" ]; then
- 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" ';'
+ if [ -f "$ERL_TOP/make/autoconf/win64.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/make/autoconf/win64.config.cache.static" ';'
fi
- echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win64.config.cache" ';'
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/make/autoconf/win64.config.cache" ';'
else
- 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" ';'
+ if [ -f "$ERL_TOP/make/autoconf/win32.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/make/autoconf/win32.config.cache.static" ';'
fi
- echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win32.config.cache" ';'
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/make/autoconf/win32.config.cache" ';'
fi
echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
echo_setenv PATH "$WIN32_WRAPPER_PATH:$P3" ';'
@@ -769,15 +766,15 @@ echo_env_wsl ()
echo_setenv AR ar.sh ';'
echo_setenv RANLIB true ';'
if [ X"$X64" = X"true" ]; then
- 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" ';'
+ if [ -f "$ERL_TOP/make/autoconf/win64.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/make/autoconf/win64.config.cache.static" ';'
fi
- echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win64.config.cache" ';'
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/make/autoconf/win64.config.cache" ';'
else
- 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" ';'
+ if [ -f "$ERL_TOP/make/autoconf/win32.config.cache.static" ]; then
+ echo_setenv OVERRIDE_CONFIG_CACHE_STATIC "$ERL_TOP/make/autoconf/win32.config.cache.static" ';'
fi
- echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/erts/autoconf/win32.config.cache" ';'
+ echo_setenv OVERRIDE_CONFIG_CACHE "$ERL_TOP/make/autoconf/win32.config.cache" ';'
fi
echo_setenv WIN32_WRAPPER_PATH "$WIN32_WRAPPER_PATH" ';'
echo_setenv PATH "$WIN32_WRAPPER_PATH:$PATH" ';'
@@ -1115,7 +1112,7 @@ unset ${erl_otp_flags}
# Target first guess, won't necessarily hold, may be changed for
# certain parameters.
if [ X"$TARGET" = X"" ]; then
- TARGET=`"$ERL_TOP/erts/autoconf/config.guess"`
+ TARGET=`"$ERL_TOP/make/autoconf/config.guess"`
fi
BUILDSYS=$TARGET
diff --git a/otp_patch_apply b/otp_patch_apply
index bf60622978..b95ce90ddb 100755
--- a/otp_patch_apply
+++ b/otp_patch_apply
@@ -223,7 +223,7 @@ export ERL_TOP="$sdir"
test -f "$sdir/otp_build" || error "$ERL_TOP" $invalid_src
test -f "$sdir/OTP_VERSION" || error "$ERL_TOP" $invalid_src
test -f "$sdir/otp_versions.table" || error "$ERL_TOP" $invalid_src
-test -f "$sdir/erts/autoconf/config.guess" || error "$ERL_TOP" $invalid_src
+test -f "$sdir/make/autoconf/config.guess" || error "$ERL_TOP" $invalid_src
test -f "$sdir/make/verify_runtime_dependencies" || error "$ERL_TOP" $invalid_src
test -x "$sdir/bootstrap/bin/erl" || error $not_built
test -x "$sdir/bootstrap/bin/erlc" || error $not_built
@@ -293,7 +293,7 @@ mkdir=`find_prog mkdir`
# Setup build stuff
if [ "x$TARGET" = "x" ]; then
- TARGET=`$ERL_TOP/erts/autoconf/config.guess`
+ TARGET=`$ERL_TOP/make/autoconf/config.guess`
fi
BUILDSYS=$TARGET
if [ -z "$MAKE" ]; then
diff --git a/otp_versions.table b/otp_versions.table
index 258b1c440b..413efad49c 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,26 @@
+OTP-25.3 : common_test-1.24 compiler-8.2.4 crypto-5.1.3 debugger-5.3.1 dialyzer-5.0.5 erl_interface-5.3.1 erts-13.2 eunit-2.8.2 ftp-1.1.4 inets-8.3 jinterface-1.13.2 kernel-8.5.4 megaco-4.4.3 mnesia-4.21.4 os_mon-2.8.1 public_key-1.13.3 reltool-0.9.1 snmp-5.13.4 ssh-4.15.3 ssl-10.9 stdlib-4.3 syntax_tools-3.0.1 tftp-1.0.4 xmerl-1.3.31 # asn1-5.0.21 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 et-1.6.5 observer-2.14 odbc-2.14 parsetools-2.4.1 runtime_tools-1.19 sasl-4.2 tools-3.5.3 wx-2.2.1 :
+OTP-25.2.3 : erts-13.1.5 inets-8.2.2 ssh-4.15.2 ssl-10.8.7 # asn1-5.0.21 common_test-1.23.3 compiler-8.2.3 crypto-5.1.2 debugger-5.3 dialyzer-5.0.4 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 eunit-2.8.1 ftp-1.1.3 jinterface-1.13.1 kernel-8.5.3 megaco-4.4.2 mnesia-4.21.3 observer-2.14 odbc-2.14 os_mon-2.8 parsetools-2.4.1 public_key-1.13.2 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13.3 stdlib-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2.1 xmerl-1.3.30 :
+OTP-25.2.2 : ftp-1.1.3 # asn1-5.0.21 common_test-1.23.3 compiler-8.2.3 crypto-5.1.2 debugger-5.3 dialyzer-5.0.4 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 erts-13.1.4 et-1.6.5 eunit-2.8.1 inets-8.2.1 jinterface-1.13.1 kernel-8.5.3 megaco-4.4.2 mnesia-4.21.3 observer-2.14 odbc-2.14 os_mon-2.8 parsetools-2.4.1 public_key-1.13.2 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13.3 ssh-4.15.1 ssl-10.8.6 stdlib-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2.1 xmerl-1.3.30 :
+OTP-25.2.1 : common_test-1.23.3 compiler-8.2.3 erts-13.1.4 inets-8.2.1 kernel-8.5.3 snmp-5.13.3 # asn1-5.0.21 crypto-5.1.2 debugger-5.3 dialyzer-5.0.4 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 eunit-2.8.1 ftp-1.1.2 jinterface-1.13.1 megaco-4.4.2 mnesia-4.21.3 observer-2.14 odbc-2.14 os_mon-2.8 parsetools-2.4.1 public_key-1.13.2 reltool-0.9 runtime_tools-1.19 sasl-4.2 ssh-4.15.1 ssl-10.8.6 stdlib-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2.1 xmerl-1.3.30 :
+OTP-25.2 : common_test-1.23.2 compiler-8.2.2 dialyzer-5.0.4 erts-13.1.3 ftp-1.1.2 inets-8.2 kernel-8.5.2 megaco-4.4.2 mnesia-4.21.3 observer-2.14 os_mon-2.8 public_key-1.13.2 snmp-5.13.2 ssh-4.15.1 ssl-10.8.6 stdlib-4.2 wx-2.2.1 # asn1-5.0.21 crypto-5.1.2 debugger-5.3 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 eunit-2.8.1 jinterface-1.13.1 odbc-2.14 parsetools-2.4.1 reltool-0.9 runtime_tools-1.19 sasl-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 xmerl-1.3.30 :
+OTP-25.1.2.1 : erts-13.1.2.1 snmp-5.13.1.1 # asn1-5.0.21 common_test-1.23.1 compiler-8.2.1 crypto-5.1.2 debugger-5.3 dialyzer-5.0.3 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 eunit-2.8.1 ftp-1.1.1 inets-8.1 jinterface-1.13.1 kernel-8.5.1 megaco-4.4.1 mnesia-4.21.2 observer-2.13 odbc-2.14 os_mon-2.7.1 parsetools-2.4.1 public_key-1.13.1 reltool-0.9 runtime_tools-1.19 sasl-4.2 ssh-4.15 ssl-10.8.5 stdlib-4.1.1 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.30 :
+OTP-25.1.2 : erts-13.1.2 mnesia-4.21.2 # asn1-5.0.21 common_test-1.23.1 compiler-8.2.1 crypto-5.1.2 debugger-5.3 dialyzer-5.0.3 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 eunit-2.8.1 ftp-1.1.1 inets-8.1 jinterface-1.13.1 kernel-8.5.1 megaco-4.4.1 observer-2.13 odbc-2.14 os_mon-2.7.1 parsetools-2.4.1 public_key-1.13.1 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13.1 ssh-4.15 ssl-10.8.5 stdlib-4.1.1 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.30 :
+OTP-25.1.1 : asn1-5.0.21 dialyzer-5.0.3 erts-13.1.1 eunit-2.8.1 kernel-8.5.1 ssl-10.8.5 stdlib-4.1.1 # common_test-1.23.1 compiler-8.2.1 crypto-5.1.2 debugger-5.3 diameter-2.2.7 edoc-1.2 eldap-1.2.10 erl_docgen-1.4 erl_interface-5.3 et-1.6.5 ftp-1.1.1 inets-8.1 jinterface-1.13.1 megaco-4.4.1 mnesia-4.21.1 observer-2.13 odbc-2.14 os_mon-2.7.1 parsetools-2.4.1 public_key-1.13.1 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13.1 ssh-4.15 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.30 :
+OTP-25.1 : asn1-5.0.20 common_test-1.23.1 compiler-8.2.1 crypto-5.1.2 dialyzer-5.0.2 diameter-2.2.7 erl_docgen-1.4 erts-13.1 eunit-2.8 inets-8.1 jinterface-1.13.1 kernel-8.5 megaco-4.4.1 observer-2.13 parsetools-2.4.1 public_key-1.13.1 snmp-5.13.1 ssh-4.15 ssl-10.8.4 stdlib-4.1 xmerl-1.3.30 # debugger-5.3 edoc-1.2 eldap-1.2.10 erl_interface-5.3 et-1.6.5 ftp-1.1.1 mnesia-4.21.1 odbc-2.14 os_mon-2.7.1 reltool-0.9 runtime_tools-1.19 sasl-4.2 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 :
+OTP-25.0.4 : erts-13.0.4 kernel-8.4.2 # asn1-5.0.19 common_test-1.23 compiler-8.2 crypto-5.1.1 debugger-5.3 dialyzer-5.0.1 diameter-2.2.6 edoc-1.2 eldap-1.2.10 erl_docgen-1.3 erl_interface-5.3 et-1.6.5 eunit-2.7.1 ftp-1.1.1 inets-8.0 jinterface-1.13 megaco-4.4 mnesia-4.21.1 observer-2.12 odbc-2.14 os_mon-2.7.1 parsetools-2.4 public_key-1.13 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13 ssh-4.14.1 ssl-10.8.3 stdlib-4.0.1 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.29 :
+OTP-25.0.3 : erts-13.0.3 ssl-10.8.3 # asn1-5.0.19 common_test-1.23 compiler-8.2 crypto-5.1.1 debugger-5.3 dialyzer-5.0.1 diameter-2.2.6 edoc-1.2 eldap-1.2.10 erl_docgen-1.3 erl_interface-5.3 et-1.6.5 eunit-2.7.1 ftp-1.1.1 inets-8.0 jinterface-1.13 kernel-8.4.1 megaco-4.4 mnesia-4.21.1 observer-2.12 odbc-2.14 os_mon-2.7.1 parsetools-2.4 public_key-1.13 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13 ssh-4.14.1 stdlib-4.0.1 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.29 :
+OTP-25.0.2 : erts-13.0.2 ssl-10.8.2 # asn1-5.0.19 common_test-1.23 compiler-8.2 crypto-5.1.1 debugger-5.3 dialyzer-5.0.1 diameter-2.2.6 edoc-1.2 eldap-1.2.10 erl_docgen-1.3 erl_interface-5.3 et-1.6.5 eunit-2.7.1 ftp-1.1.1 inets-8.0 jinterface-1.13 kernel-8.4.1 megaco-4.4 mnesia-4.21.1 observer-2.12 odbc-2.14 os_mon-2.7.1 parsetools-2.4 public_key-1.13 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13 ssh-4.14.1 stdlib-4.0.1 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.29 :
+OTP-25.0.1 : crypto-5.1.1 dialyzer-5.0.1 erts-13.0.1 kernel-8.4.1 mnesia-4.21.1 ssh-4.14.1 ssl-10.8.1 stdlib-4.0.1 # asn1-5.0.19 common_test-1.23 compiler-8.2 debugger-5.3 diameter-2.2.6 edoc-1.2 eldap-1.2.10 erl_docgen-1.3 erl_interface-5.3 et-1.6.5 eunit-2.7.1 ftp-1.1.1 inets-8.0 jinterface-1.13 megaco-4.4 observer-2.12 odbc-2.14 os_mon-2.7.1 parsetools-2.4 public_key-1.13 reltool-0.9 runtime_tools-1.19 sasl-4.2 snmp-5.13 syntax_tools-3.0 tftp-1.0.3 tools-3.5.3 wx-2.2 xmerl-1.3.29 :
+OTP-25.0 : asn1-5.0.19 common_test-1.23 compiler-8.2 crypto-5.1 debugger-5.3 dialyzer-5.0 diameter-2.2.6 edoc-1.2 erl_docgen-1.3 erl_interface-5.3 erts-13.0 eunit-2.7.1 inets-8.0 jinterface-1.13 kernel-8.4 megaco-4.4 mnesia-4.21 observer-2.12 odbc-2.14 parsetools-2.4 public_key-1.13 runtime_tools-1.19 sasl-4.2 snmp-5.13 ssh-4.14 ssl-10.8 stdlib-4.0 syntax_tools-3.0 tools-3.5.3 wx-2.2 xmerl-1.3.29 # eldap-1.2.10 et-1.6.5 ftp-1.1.1 os_mon-2.7.1 reltool-0.9 tftp-1.0.3 :
+OTP-24.3.4.9 : compiler-8.1.1.3 erts-12.3.2.9 inets-7.5.3.2 ssh-4.13.2.2 ssl-10.7.3.6 # asn1-5.0.18.1 common_test-1.22.1.1 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 jinterface-1.12.2 kernel-8.3.2.3 megaco-4.3 mnesia-4.20.4.2 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12.0.2 stdlib-3.17.2.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.8 : erts-12.3.2.8 snmp-5.12.0.2 # asn1-5.0.18.1 common_test-1.22.1.1 compiler-8.1.1.2 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3.1 jinterface-1.12.2 kernel-8.3.2.3 megaco-4.3 mnesia-4.20.4.2 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 ssh-4.13.2.1 ssl-10.7.3.5 stdlib-3.17.2.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.7 : common_test-1.22.1.1 compiler-8.1.1.2 erts-12.3.2.7 kernel-8.3.2.3 mnesia-4.20.4.2 snmp-5.12.0.1 stdlib-3.17.2.2 # asn1-5.0.18.1 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3.1 jinterface-1.12.2 megaco-4.3 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 ssh-4.13.2.1 ssl-10.7.3.5 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.6 : asn1-5.0.18.1 dialyzer-4.4.4.1 erts-12.3.2.6 kernel-8.3.2.2 ssl-10.7.3.5 # common_test-1.22.1 compiler-8.1.1.1 crypto-5.0.6.3 debugger-5.2.1 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3.1 jinterface-1.12.2 megaco-4.3 mnesia-4.20.4.1 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2.1 stdlib-3.17.2.1 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.5 : erts-12.3.2.5 ssl-10.7.3.4 stdlib-3.17.2.1 # asn1-5.0.18 common_test-1.22.1 compiler-8.1.1.1 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3.1 jinterface-1.12.2 kernel-8.3.2.1 megaco-4.3 mnesia-4.20.4.1 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2.1 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.4 : erts-12.3.2.4 # asn1-5.0.18 common_test-1.22.1 compiler-8.1.1.1 crypto-5.0.6.3 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3.1 jinterface-1.12.2 kernel-8.3.2.1 megaco-4.3 mnesia-4.20.4.1 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12.0.1 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2.1 ssl-10.7.3.3 stdlib-3.17.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.3 : compiler-8.1.1.1 crypto-5.0.6.3 erts-12.3.2.3 inets-7.5.3.1 kernel-8.3.2.1 public_key-1.12.0.1 ssl-10.7.3.3 # asn1-5.0.18 common_test-1.22.1 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 jinterface-1.12.2 megaco-4.3 mnesia-4.20.4.1 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2.1 stdlib-3.17.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.2 : crypto-5.0.6.2 erts-12.3.2.2 ssl-10.7.3.2 # asn1-5.0.18 common_test-1.22.1 compiler-8.1.1 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3 jinterface-1.12.2 kernel-8.3.2 megaco-4.3 mnesia-4.20.4.1 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2.1 stdlib-3.17.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
+OTP-24.3.4.1 : crypto-5.0.6.1 erts-12.3.2.1 mnesia-4.20.4.1 ssh-4.13.2.1 ssl-10.7.3.1 # asn1-5.0.18 common_test-1.22.1 compiler-8.1.1 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 inets-7.5.3 jinterface-1.12.2 kernel-8.3.2 megaco-4.3 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 stdlib-3.17.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.4 xmerl-1.3.28 :
OTP-24.3.4 : compiler-8.1.1 erts-12.3.2 inets-7.5.3 kernel-8.3.2 mnesia-4.20.4 ssl-10.7.3 stdlib-3.17.2 wx-2.1.4 # asn1-5.0.18 common_test-1.22.1 crypto-5.0.6 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erl_interface-5.2.2 et-1.6.5 eunit-2.7 ftp-1.1.1 jinterface-1.12.2 megaco-4.3 observer-2.11.1 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 xmerl-1.3.28 :
OTP-24.3.3 : erl_interface-5.2.2 erts-12.3.1 ftp-1.1.1 mnesia-4.20.3 observer-2.11.1 ssl-10.7.2 wx-2.1.3 # asn1-5.0.18 common_test-1.22.1 compiler-8.1 crypto-5.0.6 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 et-1.6.5 eunit-2.7 inets-7.5.2 jinterface-1.12.2 kernel-8.3.1 megaco-4.3 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2 stdlib-3.17.1 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 xmerl-1.3.28 :
OTP-24.3.2 : erl_interface-5.2.1 kernel-8.3.1 # asn1-5.0.18 common_test-1.22.1 compiler-8.1 crypto-5.0.6 debugger-5.2.1 dialyzer-4.4.4 diameter-2.2.5 edoc-1.1 eldap-1.2.10 erl_docgen-1.2.1 erts-12.3 et-1.6.5 eunit-2.7 ftp-1.1 inets-7.5.2 jinterface-1.12.2 megaco-4.3 mnesia-4.20.2 observer-2.11 odbc-2.13.5 os_mon-2.7.1 parsetools-2.3.2 public_key-1.12 reltool-0.9 runtime_tools-1.18 sasl-4.1.2 snmp-5.12 ssh-4.13.2 ssl-10.7.1 stdlib-3.17.1 syntax_tools-2.6 tftp-1.0.3 tools-3.5.2 wx-2.1.2 xmerl-1.3.28 :
@@ -21,6 +44,13 @@ OTP-24.0.3 : compiler-8.0.2 dialyzer-4.4.1 erts-12.0.3 inets-7.4.1 ssh-4.12.3 #
OTP-24.0.2 : compiler-8.0.1 crypto-5.0.2 erl_docgen-1.1.1 erts-12.0.2 kernel-8.0.1 ssh-4.12.2 ssl-10.4.1 stdlib-3.15.1 # asn1-5.0.16 common_test-1.20.4 debugger-5.1 dialyzer-4.4 diameter-2.2.4 edoc-1.0 eldap-1.2.9 erl_interface-5.0.1 et-1.6.5 eunit-2.6.1 ftp-1.1 inets-7.4 jinterface-1.12 megaco-4.0.1 mnesia-4.19.1 observer-2.9.6 odbc-2.13.5 os_mon-2.7 parsetools-2.3 public_key-1.11 reltool-0.9 runtime_tools-1.16.2 sasl-4.1 snmp-5.9.1 syntax_tools-2.6 tftp-1.0.3 tools-3.5 wx-2.0.1 xmerl-1.3.28 :
OTP-24.0.1 : common_test-1.20.4 crypto-5.0.1 erl_interface-5.0.1 erts-12.0.1 megaco-4.0.1 odbc-2.13.5 snmp-5.9.1 ssh-4.12.1 wx-2.0.1 # asn1-5.0.16 compiler-8.0 debugger-5.1 dialyzer-4.4 diameter-2.2.4 edoc-1.0 eldap-1.2.9 erl_docgen-1.1 et-1.6.5 eunit-2.6.1 ftp-1.1 inets-7.4 jinterface-1.12 kernel-8.0 mnesia-4.19.1 observer-2.9.6 os_mon-2.7 parsetools-2.3 public_key-1.11 reltool-0.9 runtime_tools-1.16.2 sasl-4.1 ssl-10.4 stdlib-3.15 syntax_tools-2.6 tftp-1.0.3 tools-3.5 xmerl-1.3.28 :
OTP-24.0 : asn1-5.0.16 common_test-1.20.3 compiler-8.0 crypto-5.0 debugger-5.1 dialyzer-4.4 edoc-1.0 erl_docgen-1.1 erl_interface-5.0 erts-12.0 et-1.6.5 eunit-2.6.1 ftp-1.1 inets-7.4 jinterface-1.12 kernel-8.0 megaco-4.0 mnesia-4.19.1 observer-2.9.6 odbc-2.13.4 os_mon-2.7 parsetools-2.3 public_key-1.11 reltool-0.9 runtime_tools-1.16.2 sasl-4.1 snmp-5.9 ssh-4.12 ssl-10.4 stdlib-3.15 syntax_tools-2.6 tftp-1.0.3 tools-3.5 wx-2.0 xmerl-1.3.28 # diameter-2.2.4 eldap-1.2.9 :
+OTP-23.3.4.18 : dialyzer-4.3.1.2 erts-11.2.2.17 kernel-7.3.1.7 # asn1-5.0.15.1 common_test-1.20.2.3 compiler-7.6.9.2 crypto-4.9.0.4 debugger-5.0 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.3 jinterface-1.11.1.1 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.6 ssl-10.3.1.5 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
+OTP-23.3.4.17 : erts-11.2.2.16 inets-7.3.2.3 kernel-7.3.1.6 ssl-10.3.1.5 # asn1-5.0.15.1 common_test-1.20.2.3 compiler-7.6.9.2 crypto-4.9.0.4 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 jinterface-1.11.1.1 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.6 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
+OTP-23.3.4.16 : crypto-4.9.0.4 erts-11.2.2.15 ssl-10.3.1.4 # asn1-5.0.15.1 common_test-1.20.2.3 compiler-7.6.9.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1.1 kernel-7.3.1.5 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.6 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
+OTP-23.3.4.15 : crypto-4.9.0.3 erts-11.2.2.14 ssh-4.11.1.6 ssl-10.3.1.3 # asn1-5.0.15.1 common_test-1.20.2.3 compiler-7.6.9.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1.1 kernel-7.3.1.5 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
+OTP-23.3.4.14 : compiler-7.6.9.2 erts-11.2.2.13 # asn1-5.0.15.1 common_test-1.20.2.3 crypto-4.9.0.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1.1 kernel-7.3.1.5 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.5 ssl-10.3.1.2 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
+OTP-23.3.4.13 : erts-11.2.2.12 # asn1-5.0.15.1 common_test-1.20.2.3 compiler-7.6.9.1 crypto-4.9.0.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1.1 kernel-7.3.1.5 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.5 ssl-10.3.1.2 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
+OTP-23.3.4.12 : common_test-1.20.2.3 erts-11.2.2.11 jinterface-1.11.1.1 kernel-7.3.1.5 # asn1-5.0.15.1 compiler-7.6.9.1 crypto-4.9.0.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.5 ssl-10.3.1.2 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
OTP-23.3.4.11 : erts-11.2.2.10 ssh-4.11.1.5 # asn1-5.0.15.1 common_test-1.20.2.2 compiler-7.6.9.1 crypto-4.9.0.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1 kernel-7.3.1.4 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssl-10.3.1.2 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
OTP-23.3.4.10 : erts-11.2.2.9 # asn1-5.0.15.1 common_test-1.20.2.2 compiler-7.6.9.1 crypto-4.9.0.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1 kernel-7.3.1.4 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.4 ssl-10.3.1.2 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
OTP-23.3.4.9 : erts-11.2.2.8 # asn1-5.0.15.1 common_test-1.20.2.2 compiler-7.6.9.1 crypto-4.9.0.2 debugger-5.0 dialyzer-4.3.1.1 diameter-2.2.4 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.3.1 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2.2 jinterface-1.11.1 kernel-7.3.1.4 megaco-3.19.5.1 mnesia-4.19 observer-2.9.5 odbc-2.13.3.1 os_mon-2.6.1 parsetools-2.2 public_key-1.10.0.1 reltool-0.8 runtime_tools-1.16.1 sasl-4.0.2 snmp-5.8.0.1 ssh-4.11.1.4 ssl-10.3.1.2 stdlib-3.14.2.2 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3.1 xmerl-1.3.27 :
@@ -37,6 +67,7 @@ OTP-23.3.3 : common_test-1.20.2 compiler-7.6.8 erl_interface-4.0.3 kernel-7.3.1
OTP-23.3.2 : asn1-5.0.15 common_test-1.20.1 erts-11.2.1 ssl-10.3.1 stdlib-3.14.2 xmerl-1.3.27 # compiler-7.6.7 crypto-4.9 debugger-5.0 dialyzer-4.3.1 diameter-2.2.3 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.2 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 jinterface-1.11.1 kernel-7.3 megaco-3.19.5 mnesia-4.19 observer-2.9.5 odbc-2.13.3 os_mon-2.6.1 parsetools-2.2 public_key-1.10 reltool-0.8 runtime_tools-1.16 sasl-4.0.2 snmp-5.8 ssh-4.11.1 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3 :
OTP-23.3.1 : ssh-4.11.1 # asn1-5.0.14 common_test-1.20 compiler-7.6.7 crypto-4.9 debugger-5.0 dialyzer-4.3.1 diameter-2.2.3 edoc-0.12 eldap-1.2.9 erl_docgen-1.0.2 erl_interface-4.0.2 erts-11.2 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 jinterface-1.11.1 kernel-7.3 megaco-3.19.5 mnesia-4.19 observer-2.9.5 odbc-2.13.3 os_mon-2.6.1 parsetools-2.2 public_key-1.10 reltool-0.8 runtime_tools-1.16 sasl-4.0.2 snmp-5.8 ssl-10.3 stdlib-3.14.1 syntax_tools-2.5 tftp-1.0.2 tools-3.4.4 wx-1.9.3 xmerl-1.3.26 :
OTP-23.3 : common_test-1.20 compiler-7.6.7 crypto-4.9 dialyzer-4.3.1 eldap-1.2.9 erts-11.2 jinterface-1.11.1 kernel-7.3 mnesia-4.19 odbc-2.13.3 public_key-1.10 runtime_tools-1.16 sasl-4.0.2 snmp-5.8 ssh-4.11 ssl-10.3 stdlib-3.14.1 syntax_tools-2.5 tools-3.4.4 wx-1.9.3 # asn1-5.0.14 debugger-5.0 diameter-2.2.3 edoc-0.12 erl_docgen-1.0.2 erl_interface-4.0.2 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 megaco-3.19.5 observer-2.9.5 os_mon-2.6.1 parsetools-2.2 reltool-0.8 tftp-1.0.2 xmerl-1.3.26 :
+OTP-23.2.7.5 : ssl-10.2.4.4 # asn1-5.0.14 common_test-1.19.1 compiler-7.6.6 crypto-4.8.3 debugger-5.0 dialyzer-4.3 diameter-2.2.3 edoc-0.12 eldap-1.2.8 erl_docgen-1.0.2 erl_interface-4.0.2.1 erts-11.1.8 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 jinterface-1.11 kernel-7.2.1 megaco-3.19.5 mnesia-4.18.1 observer-2.9.5 odbc-2.13.2 os_mon-2.6.1 parsetools-2.2 public_key-1.9.2 reltool-0.8 runtime_tools-1.15.1 sasl-4.0.1 snmp-5.7.3 ssh-4.10.8 stdlib-3.14 syntax_tools-2.4 tftp-1.0.2 tools-3.4.3 wx-1.9.2 xmerl-1.3.26 :
OTP-23.2.7.4 : ssl-10.2.4.3 # asn1-5.0.14 common_test-1.19.1 compiler-7.6.6 crypto-4.8.3 debugger-5.0 dialyzer-4.3 diameter-2.2.3 edoc-0.12 eldap-1.2.8 erl_docgen-1.0.2 erl_interface-4.0.2.1 erts-11.1.8 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 jinterface-1.11 kernel-7.2.1 megaco-3.19.5 mnesia-4.18.1 observer-2.9.5 odbc-2.13.2 os_mon-2.6.1 parsetools-2.2 public_key-1.9.2 reltool-0.8 runtime_tools-1.15.1 sasl-4.0.1 snmp-5.7.3 ssh-4.10.8 stdlib-3.14 syntax_tools-2.4 tftp-1.0.2 tools-3.4.3 wx-1.9.2 xmerl-1.3.26 :
OTP-23.2.7.3 : erl_interface-4.0.2.1 # asn1-5.0.14 common_test-1.19.1 compiler-7.6.6 crypto-4.8.3 debugger-5.0 dialyzer-4.3 diameter-2.2.3 edoc-0.12 eldap-1.2.8 erl_docgen-1.0.2 erts-11.1.8 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 jinterface-1.11 kernel-7.2.1 megaco-3.19.5 mnesia-4.18.1 observer-2.9.5 odbc-2.13.2 os_mon-2.6.1 parsetools-2.2 public_key-1.9.2 reltool-0.8 runtime_tools-1.15.1 sasl-4.0.1 snmp-5.7.3 ssh-4.10.8 ssl-10.2.4.2 stdlib-3.14 syntax_tools-2.4 tftp-1.0.2 tools-3.4.3 wx-1.9.2 xmerl-1.3.26 :
OTP-23.2.7.2 : ssl-10.2.4.2 # asn1-5.0.14 common_test-1.19.1 compiler-7.6.6 crypto-4.8.3 debugger-5.0 dialyzer-4.3 diameter-2.2.3 edoc-0.12 eldap-1.2.8 erl_docgen-1.0.2 erl_interface-4.0.2 erts-11.1.8 et-1.6.4 eunit-2.6 ftp-1.0.5 hipe-4.0.1 inets-7.3.2 jinterface-1.11 kernel-7.2.1 megaco-3.19.5 mnesia-4.18.1 observer-2.9.5 odbc-2.13.2 os_mon-2.6.1 parsetools-2.2 public_key-1.9.2 reltool-0.8 runtime_tools-1.15.1 sasl-4.0.1 snmp-5.7.3 ssh-4.10.8 stdlib-3.14 syntax_tools-2.4 tftp-1.0.2 tools-3.4.3 wx-1.9.2 xmerl-1.3.26 :
@@ -61,6 +92,8 @@ OTP-23.0.3 : compiler-7.6.2 erts-11.0.3 # asn1-5.0.13 common_test-1.19 crypto-4.
OTP-23.0.2 : erts-11.0.2 megaco-3.19.1 # asn1-5.0.13 common_test-1.19 compiler-7.6.1 crypto-4.7 debugger-5.0 dialyzer-4.2 diameter-2.2.3 edoc-0.12 eldap-1.2.8 erl_docgen-1.0 erl_interface-4.0 et-1.6.4 eunit-2.5 ftp-1.0.4 hipe-4.0 inets-7.2 jinterface-1.11 kernel-7.0 mnesia-4.17 observer-2.9.4 odbc-2.13 os_mon-2.5.2 parsetools-2.2 public_key-1.8 reltool-0.8 runtime_tools-1.15 sasl-4.0 snmp-5.6 ssh-4.10 ssl-10.0 stdlib-3.13 syntax_tools-2.3 tftp-1.0.2 tools-3.4 wx-1.9.1 xmerl-1.3.25 :
OTP-23.0.1 : compiler-7.6.1 erts-11.0.1 # asn1-5.0.13 common_test-1.19 crypto-4.7 debugger-5.0 dialyzer-4.2 diameter-2.2.3 edoc-0.12 eldap-1.2.8 erl_docgen-1.0 erl_interface-4.0 et-1.6.4 eunit-2.5 ftp-1.0.4 hipe-4.0 inets-7.2 jinterface-1.11 kernel-7.0 megaco-3.19 mnesia-4.17 observer-2.9.4 odbc-2.13 os_mon-2.5.2 parsetools-2.2 public_key-1.8 reltool-0.8 runtime_tools-1.15 sasl-4.0 snmp-5.6 ssh-4.10 ssl-10.0 stdlib-3.13 syntax_tools-2.3 tftp-1.0.2 tools-3.4 wx-1.9.1 xmerl-1.3.25 :
OTP-23.0 : asn1-5.0.13 common_test-1.19 compiler-7.6 crypto-4.7 debugger-5.0 dialyzer-4.2 edoc-0.12 erl_docgen-1.0 erl_interface-4.0 erts-11.0 eunit-2.5 hipe-4.0 inets-7.2 jinterface-1.11 kernel-7.0 megaco-3.19 mnesia-4.17 observer-2.9.4 odbc-2.13 os_mon-2.5.2 parsetools-2.2 public_key-1.8 runtime_tools-1.15 sasl-4.0 snmp-5.6 ssh-4.10 ssl-10.0 stdlib-3.13 syntax_tools-2.3 tools-3.4 wx-1.9.1 xmerl-1.3.25 # diameter-2.2.3 eldap-1.2.8 et-1.6.4 ftp-1.0.4 reltool-0.8 tftp-1.0.2 :
+OTP-22.3.4.26 : erts-10.7.2.18 # asn1-5.0.12 common_test-1.18.2.2 compiler-7.5.4.3 crypto-4.6.5.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.3 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.2.2 et-1.6.4 eunit-2.4.1 ftp-1.0.4.1 hipe-3.19.3 inets-7.1.3.3 jinterface-1.10.1 kernel-6.5.2.5 megaco-3.18.8.4 mnesia-4.16.3.1 observer-2.9.3 odbc-2.12.4.1 os_mon-2.5.1.1 parsetools-2.1.8 public_key-1.7.2 reltool-0.8 runtime_tools-1.14.0.1 sasl-3.4.2 snmp-5.5.0.5 ssh-4.9.1.4 ssl-9.6.2.3 stdlib-3.12.1.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3.1.1 wx-1.9.0.1 xmerl-1.3.24 :
+OTP-22.3.4.25 : common_test-1.18.2.2 erts-10.7.2.17 kernel-6.5.2.5 # asn1-5.0.12 compiler-7.5.4.3 crypto-4.6.5.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.3 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.2.2 et-1.6.4 eunit-2.4.1 ftp-1.0.4.1 hipe-3.19.3 inets-7.1.3.3 jinterface-1.10.1 megaco-3.18.8.4 mnesia-4.16.3.1 observer-2.9.3 odbc-2.12.4.1 os_mon-2.5.1.1 parsetools-2.1.8 public_key-1.7.2 reltool-0.8 runtime_tools-1.14.0.1 sasl-3.4.2 snmp-5.5.0.5 ssh-4.9.1.4 ssl-9.6.2.3 stdlib-3.12.1.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3.1.1 wx-1.9.0.1 xmerl-1.3.24 :
OTP-22.3.4.24 : erts-10.7.2.16 # asn1-5.0.12 common_test-1.18.2.1 compiler-7.5.4.3 crypto-4.6.5.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.3 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.2.2 et-1.6.4 eunit-2.4.1 ftp-1.0.4.1 hipe-3.19.3 inets-7.1.3.3 jinterface-1.10.1 kernel-6.5.2.4 megaco-3.18.8.4 mnesia-4.16.3.1 observer-2.9.3 odbc-2.12.4.1 os_mon-2.5.1.1 parsetools-2.1.8 public_key-1.7.2 reltool-0.8 runtime_tools-1.14.0.1 sasl-3.4.2 snmp-5.5.0.5 ssh-4.9.1.4 ssl-9.6.2.3 stdlib-3.12.1.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3.1.1 wx-1.9.0.1 xmerl-1.3.24 :
OTP-22.3.4.23 : erts-10.7.2.15 # asn1-5.0.12 common_test-1.18.2.1 compiler-7.5.4.3 crypto-4.6.5.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.3 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.2.2 et-1.6.4 eunit-2.4.1 ftp-1.0.4.1 hipe-3.19.3 inets-7.1.3.3 jinterface-1.10.1 kernel-6.5.2.4 megaco-3.18.8.4 mnesia-4.16.3.1 observer-2.9.3 odbc-2.12.4.1 os_mon-2.5.1.1 parsetools-2.1.8 public_key-1.7.2 reltool-0.8 runtime_tools-1.14.0.1 sasl-3.4.2 snmp-5.5.0.5 ssh-4.9.1.4 ssl-9.6.2.3 stdlib-3.12.1.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3.1.1 wx-1.9.0.1 xmerl-1.3.24 :
OTP-22.3.4.22 : erts-10.7.2.14 ssh-4.9.1.4 # asn1-5.0.12 common_test-1.18.2.1 compiler-7.5.4.3 crypto-4.6.5.4 debugger-4.2.8 dialyzer-4.1.1 diameter-2.2.3 edoc-0.11 eldap-1.2.8 erl_docgen-0.11 erl_interface-3.13.2.2 et-1.6.4 eunit-2.4.1 ftp-1.0.4.1 hipe-3.19.3 inets-7.1.3.3 jinterface-1.10.1 kernel-6.5.2.4 megaco-3.18.8.4 mnesia-4.16.3.1 observer-2.9.3 odbc-2.12.4.1 os_mon-2.5.1.1 parsetools-2.1.8 public_key-1.7.2 reltool-0.8 runtime_tools-1.14.0.1 sasl-3.4.2 snmp-5.5.0.5 ssl-9.6.2.3 stdlib-3.12.1.2 syntax_tools-2.2.1 tftp-1.0.2 tools-3.3.1.1 wx-1.9.0.1 xmerl-1.3.24 :
diff --git a/scripts/build-otp-tar b/scripts/build-otp-tar
index 362d69d508..fc8344c76a 100755
--- a/scripts/build-otp-tar
+++ b/scripts/build-otp-tar
@@ -422,7 +422,7 @@ fi
if [ "x$build_dir" != "x" ]; then
- progress "Using already built OTP distibution in: $build_dir"
+ progress "Using already built OTP distribution in: $build_dir"
else
@@ -541,7 +541,7 @@ if [ ! -d $src_dir -o ! -f $src_dir/otp_build ]; then
fi
progress "Checking target directory name"
-target_dirname=`$prebld_dir/erts/autoconf/config.guess`
+target_dirname=`$prebld_dir/make/autoconf/config.guess`
if [ $? -ne 0 ]; then
error "Failed to check target directory name"
fi
diff --git a/scripts/check_doc_since b/scripts/check_doc_since
index ed13bb8e93..ccdadcec6b 100755
--- a/scripts/check_doc_since
+++ b/scripts/check_doc_since
@@ -608,7 +608,7 @@ sub read_xml_functions {
sub read_edoc_functions {
my($tag, $module) = @_;
- open(FILE, $filename) or die "Cant open erl file \"$filename\"\n";
+ open(FILE, $filename) or die "Can't open erl file \"$filename\"\n";
local $/ = undef;
my $lines = <FILE>;
close(FILE);
@@ -812,7 +812,7 @@ sub seen_it {
}
-# Trim leading and traling whitespace
+# Trim leading and trailing whitespace
sub trim {
my $s = shift;
$s =~ s/^\s+|\s+$//g;
diff --git a/scripts/diffable b/scripts/diffable
index ce192b375b..c127480242 100755
--- a/scripts/diffable
+++ b/scripts/diffable
@@ -7,7 +7,8 @@
-define(LONG_COMPILE_THRESHOLD, 10000).
main(Args0) ->
- DefOpts = #{format=>asm,no_compile=>false,legacy=>false,copts=>[]},
+ DefOpts = #{erltop=>false,format=>asm,no_compile=>false,
+ legacy=>false,copts=>[]},
{Args,Opts} = opts(Args0, DefOpts),
case Args of
[OutDir] ->
@@ -28,6 +29,10 @@ usage() ->
" --asm)\n"
" --co <option> Add <option> to the list of options given to the\n"
" compiler. See compile:file/2 for valid options.\n"
+ " --erltop <path> By default diffable looks for the applications to\n"
+ " compile by looking up the source for the current\n"
+ " runtime. This option allows the user to compile\n"
+ " the source in a different source tree.\n"
"\n"
"DESCRIPTION\n"
"\n"
@@ -85,8 +90,10 @@ opts(["--deterministic"|Args], #{copts:=Copts}=Opts) ->
opts(Args, Opts#{copts:=Copts++[deterministic]});
opts(["--co",Opt|Args], #{copts:=Copts}=Opts) ->
opts(Args, Opts#{copts:=Copts++[list_to_atom(Opt)]});
+opts(["--erltop", Path|Args], Opts) ->
+ opts(Args, Opts#{erltop:=Path});
opts(["--"++Opt|_], _Opts) ->
- io:format("Uknown option: --~ts\n\n", [Opt]),
+ io:format("Unknown option: --~ts\n\n", [Opt]),
usage();
opts(Args, Opts) ->
{Args,Opts}.
@@ -156,16 +163,16 @@ elixir_root() ->
%%%
get_specs(Apps, #{format:=dis,no_compile:=true}=Opts) ->
- Files = get_elixir_beams() ++ get_beams(Apps),
+ Files = get_elixir_beams() ++ get_beams(Apps, Opts),
{Files,Opts};
get_specs(Apps, #{}=Opts) ->
- Inc = make_includes(),
+ Inc = make_includes(Opts),
CompilerOpts = [{d,epmd_dist_high,42},
{d,epmd_dist_low,37},
{d,'VSN',1},
{d,'COMPILER_VSN',1},
{d,erlang_daemon_port,1337}|Inc],
- Files = get_src(Apps),
+ Files = get_src(Apps, Opts),
Specs1 = add_opts(Files, CompilerOpts),
Specs = [{Beam,elixir} || Beam <- get_elixir_beams()] ++ Specs1,
{Specs,Opts}.
@@ -200,31 +207,50 @@ vsn_is_harmful(F) ->
App =:= "ssl"
end.
-get_src(["preloaded"|Apps]) ->
- WC = filename:join(code:root_dir(), "erts/preloaded/src/*.erl"),
- filelib:wildcard(WC) ++ get_src(Apps);
-get_src(["inets"|Apps]) ->
- LibDir = code:lib_dir(inets),
+get_src([A="preloaded"|Apps], Opts) ->
+ WC = filename:join(get_lib_dir(A, Opts), "erts/preloaded/src/*.erl"),
+ filelib:wildcard(WC) ++ get_src(Apps, Opts);
+get_src(["inets"|Apps], Opts) ->
+ LibDir = get_lib_dir(inets, Opts),
WC = filename:join(LibDir, "src/*/*.erl"),
- filelib:wildcard(WC) ++ get_src(Apps);
-get_src(["syntax_tools"|Apps]) ->
- LibDir = code:lib_dir(syntax_tools),
+ filelib:wildcard(WC) ++ get_src(Apps, Opts);
+get_src(["syntax_tools"|Apps], Opts) ->
+ LibDir = get_lib_dir(syntax_tools, Opts),
WC = filename:join(LibDir, "src/*.erl"),
Files0 = filelib:wildcard(WC),
Files = [F || F <- Files0,
filename:basename(F) =/= "merl_tests.erl"],
- Files ++ get_src(Apps);
-get_src(["wx"|Apps]) ->
- LibDir = code:lib_dir(wx),
+ Files ++ get_src(Apps, Opts);
+get_src(["wx"|Apps], Opts) ->
+ LibDir = get_lib_dir(wx, Opts),
WC1 = filename:join(LibDir, "src/gen/*.erl"),
WC2 = filename:join(LibDir, "src/*.erl"),
- filelib:wildcard(WC1) ++ filelib:wildcard(WC2) ++ get_src(Apps);
-get_src([App|Apps]) ->
- WC = filename:join(code:lib_dir(App), "src/*.erl"),
- filelib:wildcard(WC) ++ get_src(Apps);
-get_src([]) -> [].
-
-make_includes() ->
+ filelib:wildcard(WC1) ++ filelib:wildcard(WC2) ++ get_src(Apps, Opts);
+get_src([App|Apps], Opts) ->
+ WC = filename:join(get_lib_dir(App, Opts), "src/*.erl"),
+ filelib:wildcard(WC) ++ get_src(Apps, Opts);
+get_src([], _) -> [].
+
+get_root_dir(#{ erltop := false }) ->
+ code:root_dir();
+get_root_dir(#{ erltop := Root }) ->
+ Root.
+
+get_lib_dir("preloaded", Opts) ->
+ get_root_dir(Opts);
+get_lib_dir(App, #{ erltop := false }) ->
+ code:lib_dir(App);
+get_lib_dir(App, #{ erltop := AltRoot }) ->
+ %% The assumption made here is that we intend to compare either
+ %% two installed runtimes or two source trees, that is, the
+ %% application directory names either both contain the same
+ %% version or have no version at all.
+ RuntimeRoot = code:root_dir(),
+ RuntimeLibDir = code:lib_dir(App),
+ AppWithVersion = lists:nthtail(length(RuntimeRoot) + 1, RuntimeLibDir),
+ AltRoot ++ AppWithVersion.
+
+make_includes(Opts) ->
Is = [{common_test,"include"},
{inets,"include"},
{inets,"src/http_client"},
@@ -242,15 +268,15 @@ make_includes() ->
{wx,"src"},
{wx,"include"},
{xmerl,"include"}],
- [{i,filename:join(code:lib_dir(App), Path)} || {App,Path} <- Is].
-
-get_beams(["preloaded"|Apps]) ->
- WC = filename:join(code:root_dir(), "erts/preloaded/ebin/*.beam"),
- filelib:wildcard(WC) ++ get_beams(Apps);
-get_beams([App|Apps]) ->
- WC = filename:join(code:lib_dir(App), "ebin/*.beam"),
- filelib:wildcard(WC) ++ get_beams(Apps);
-get_beams([]) -> [].
+ [{i,filename:join(get_lib_dir(App, Opts), Path)} || {App,Path} <- Is].
+
+get_beams(["preloaded"|Apps], Opts) ->
+ WC = filename:join(get_root_dir(Opts), "erts/preloaded/ebin/*.beam"),
+ filelib:wildcard(WC) ++ get_beams(Apps, Opts);
+get_beams([App|Apps], Opts) ->
+ WC = filename:join(get_lib_dir(App, Opts), "ebin/*.beam"),
+ filelib:wildcard(WC) ++ get_beams(Apps, Opts);
+get_beams([], _) -> [].
%%%
diff --git a/scripts/otp_html_check b/scripts/otp_html_check
index 3606ed22d4..3b9df7f8c6 100755
--- a/scripts/otp_html_check
+++ b/scripts/otp_html_check
@@ -16,7 +16,7 @@ undef $/; # No record separator reading files
###########################################################################
#
# When we talk about "a page" we mean the actual page/file
-# When we talk about "a link" we mean a referense to a page/file.
+# When we talk about "a link" we mean a reference to a page/file.
# All links/URL's start with an slash except the top link that is
# the empty string.
#
@@ -88,7 +88,7 @@ push(@links,["","/doc/index.html"]) unless @links;
###########################################################################
#
# Traverse all files and directories and put all possible URL's into
-# the set %pages. When we later find a referense to a page that URL
+# the set %pages. When we later find a reference to a page that URL
# is removed from the set. When we have followed all links the set
# contains the pages never visited.
#
@@ -205,7 +205,7 @@ sub get_page_links {
# FIXME: Now we have the raw links, if we want to complain about
# spaces etc this is the time.
- # Remove referenses to the same page FIXME??? Was removed , why...
+ # Remove references to the same page FIXME??? Was removed , why...
# @links = grep {$_ and $_ !~ /^\#/} @links;
# Find the URL to the current directory
@@ -284,7 +284,7 @@ sub normalize_link {
# The empty link is a reference to URL directory
return $rpath;
} elsif ($link =~ /^#(.*)$/s) {
- # Lokal reference to anchor
+ # Local reference to anchor
my $anchor = $1;
$anchor =~ s/%([\da-fA-F]{2})/chr(hex($1))/eg; # Translate hex to char
$anchor =~ s/&lt;/</g; #
@@ -371,16 +371,7 @@ sub expand_link {
#
###########################################################################
-if (keys %missing) {
- print "\n\n\n**** Broken links\n\n";
- foreach (sort keys %missing) {
- my ($page,$link) = split($;);
- print qq(Broken Link: $page -> "$link"\n);
- }
-}
-
-
-# Entrys in %pages that has the value 0 is not visited
+# Entries in %pages that has the value 0 is not visited
if (keys %pages) {
print "\n\n\n**** Files not used (that I can see)\n\n";
foreach my $page (sort keys %pages) {
@@ -396,6 +387,13 @@ if (keys %pages) {
}
}
+if (keys %missing) {
+ print "\n\n\n**** Broken links\n\n";
+ foreach (sort keys %missing) {
+ my ($page,$link) = split($;);
+ print qq(Broken Link: $page -> "$link"\n);
+ }
+}
# Remove all references that has a matching NAME=....
map {delete $anchor_refs{$_}} keys %anchor_defs;
diff --git a/scripts/pre-push b/scripts/pre-push
index 978f8cceef..5759406182 100755
--- a/scripts/pre-push
+++ b/scripts/pre-push
@@ -23,14 +23,14 @@
#
# Bump this version to give users an update notification.
-PRE_PUSH_SCRIPT_VERSION=2
+PRE_PUSH_SCRIPT_VERSION=3
-NEW_RELEASES="23 22 21 20 19 18 17"
+NEW_RELEASES="24 23 22 21 20 19 18 17"
OLD_RELEASES="r16 r15 r14 r13"
RELEASES="$NEW_RELEASES $OLD_RELEASES"
# First commit on master, not allowed in other branches
-MASTER_ONLY=740b29ecc21c73a4bf4ebfc494490865d3c31978
+MASTER_ONLY=a20c39812082068a8b9e3b73276de41fbb0338af
# Number of commits and files allowed in one push by this script
NCOMMITS_MAX=100
diff --git a/scripts/run-dialyzer b/scripts/run-dialyzer
index e50bf16998..cad04a3514 100755
--- a/scripts/run-dialyzer
+++ b/scripts/run-dialyzer
@@ -16,7 +16,7 @@ if [ "X$ERL_TOP" != "X" ] && [ -d $ERL_TOP/lib ]; then
else
LIB_DIR=$(erl -noshell -eval 'io:format("~ts~n",[code:lib_dir()])' -s init stop)
fi
-ALL_APPLICATIONS=$(ls -d -1 $LIB_DIR/*/ | sed "s:^$LIB_DIR/\\([^/\-]\+\\).*$:\1:g")
+ALL_APPLICATIONS=$(ls -d -1 $LIB_DIR/*/ | sed "s:^$LIB_DIR/::g" | sed "s:/$::g")
ALL_APPLICATIONS="erts $ALL_APPLICATIONS"
echo "All applications: $ALL_APPLICATIONS" |tr '\n' ' ' && echo ""
@@ -44,7 +44,7 @@ if [ -f $ERL_TOP/bin/dialyzer ]; then
DIALYZER=$ERL_TOP/bin/dialyzer
fi
-PLT=$(mktemp --suffix=.plt)
+PLT="$(mktemp).plt"
set -x
diff --git a/scripts/run-smoke-tests b/scripts/run-smoke-tests
deleted file mode 100755
index 82231a2b81..0000000000
--- a/scripts/run-smoke-tests
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-set -ev
-
-if [ -d $ERL_TOP/release/tests/test_server ]; then
- cd $ERL_TOP/release/tests/test_server
-elif [ -d test_server ]; then
- cd test_server
-else
- echo "Could not find tests"
- exit 1;
-fi
-
-erl -noshell -s ts install -s ts smoke_test batch -s init stop
-
-if grep -q '=failed *[1-9]' ct_run.test_server@*/*/run.*/suite.log; then
- echo "One or more tests failed."
- exit 1
-fi
-
-rm -rf ct_run.test_server@*
diff --git a/system/doc/design_principles/events.xml b/system/doc/design_principles/events.xml
index acd051d411..4d7b34bc70 100644
--- a/system/doc/design_principles/events.xml
+++ b/system/doc/design_principles/events.xml
@@ -227,7 +227,8 @@ ok</pre>
<c>handle_info(Info, State)</c>
must be implemented to handle them. Examples of other
messages are exit messages, if the <c>gen_event</c> is linked to
- other processes (than the supervisor) and trapping exit signals.</p>
+ other processes (than the supervisor, for example via
+ <c>add_sup_handler</c>) and trapping exit signals.</p>
<code type="none">
handle_info({'EXIT', Pid, Reason}, State) ->
..code to handle exits here..
diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml
index d23e9732fc..167d92d52f 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>2020</year>
+ <year>2003</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -311,7 +311,7 @@
the following instruction is used:</p>
<code type="none">
{apply, {M, F, A}}</code>
- <p>The release handler evalutes <c>apply(M, F, A)</c>.</p>
+ <p>The release handler evaluates <c>apply(M, F, A)</c>.</p>
</section>
<section>
diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index 0610a15a8a..51a1228183 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -274,7 +274,7 @@ init(Parent) ->
<section>
<marker id="debug"></marker>
<title>Debugging</title>
- <p>To support the debug facilites in <c>sys</c>, a
+ <p>To support the debug facilities in <c>sys</c>, a
<em>debug structure</em> is needed. The <c>Deb</c> term is
initialized using <c>sys:debug_options/1</c>:</p>
<code type="none">
diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml
index 2d6ea27635..c53d569c99 100644
--- a/system/doc/design_principles/statem.xml
+++ b/system/doc/design_principles/statem.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2016</year><year>2020</year>
+ <year>2016</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1947,7 +1947,7 @@ do_unlock() ->
<p>
Say you have a state machine specification
that uses state enter actions.
- Allthough you can code this using inserted events
+ Although you can code this using inserted events
(described in the next section), especially if just
one or a few states has got state enter actions,
this is a perfect use case for the built in
diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml
index 4d1b593c92..c9aa52669b 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>2021</year>
+ <year>1997</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -69,7 +69,7 @@ init(_Args) ->
restart => permanent,
shutdown => brutal_kill,
type => worker,
- modules => [cg3]}],
+ modules => [ch3]}],
{ok, {SupFlags, ChildSpecs}}.</code>
<p>The <c>SupFlags</c> variable in the return value
from <c>init/1</c> represents
@@ -374,7 +374,7 @@ child_spec() = #{id => child_id(), % mandatory
<p>Note that this identifier occasionally has been called
"name". As far as possible, the terms "identifier" or "id"
are now used but in order to keep backwards compatibility,
- some occurences of "name" can still be found, for example
+ some occurrences of "name" can still be found, for example
in error messages.</p>
</item>
<item>
diff --git a/system/doc/efficiency_guide/advanced.xml b/system/doc/efficiency_guide/advanced.xml
index c545d22a8a..25899f6821 100644
--- a/system/doc/efficiency_guide/advanced.xml
+++ b/system/doc/efficiency_guide/advanced.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2021</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -39,7 +39,9 @@
<p>The unit of measurement is memory words. There exists both a
32-bit and a 64-bit implementation. A word is therefore 4 bytes or
- 8 bytes, respectively.</p>
+ 8 bytes, respectively. The value for a running system can be
+ determined by calling <seeerl marker="erts:erlang#system_info_wordsize">
+ <c>erlang:system_info(wordsize)</c></seeerl>.</p>
<table>
<row>
<cell><em>Data Type</em></cell>
diff --git a/system/doc/efficiency_guide/bench.erl b/system/doc/efficiency_guide/bench.erl
index a1be24b051..a1e9a71084 100644
--- a/system/doc/efficiency_guide/bench.erl
+++ b/system/doc/efficiency_guide/bench.erl
@@ -424,7 +424,7 @@ create_html_table(File, {Bm, Res}) ->
create_html_row(File, Name, ResultDict)
end, Order),
- %% Tabel end-tags
+ %% Table end-tags
io:put_chars(File, "</table></td></tr></table>\n"),
%% Create link to benchmark source code
@@ -435,7 +435,7 @@ create_html_table(File, {Bm, Res}) ->
%% create_html_row(File, Name, Dict) -> _
%% File = file() - html file to write data to.
%% Name = atom() - Name of benchmark test
-%% Dict = dict() - Dictonary where the relative time measures for
+%% Dict = dict() - Dictionary where the relative time measures for
%% the test can be found.
%%
%% Creates an actual html table-row.
diff --git a/system/doc/efficiency_guide/commoncaveats.xmlsrc b/system/doc/efficiency_guide/commoncaveats.xmlsrc
index 47ce3a014f..6ea8599e94 100644
--- a/system/doc/efficiency_guide/commoncaveats.xmlsrc
+++ b/system/doc/efficiency_guide/commoncaveats.xmlsrc
@@ -39,11 +39,16 @@
marker="erts:erlang#send_after/3">erlang:send_after/3</seemfa>
and
<seemfa marker="erts:erlang#start_timer/3">erlang:start_timer/3</seemfa>,
- is much more efficient than using the timers provided by the
- <seeerl marker="stdlib:timer">timer</seeerl> module in STDLIB.
- The <c>timer</c> module uses a separate process to manage the timers.
- That process can easily become overloaded if many processes
- create and cancel timers frequently.</p>
+ is more efficient than using the timers provided by the
+ <seeerl marker="stdlib:timer">timer</seeerl> module in STDLIB.</p>
+ <p>The <c>timer</c> module uses a separate process to manage the timers.
+ Before OTP 25, this management overhead was substantial and increasing
+ with the number of timers, especially when they were short-lived, so the
+ timer server process could easily become overloaded and unresponsive.
+ In OTP 25, the timer module was improved by removing most of the management
+ overhead and the resulting performance penalty. Still, the timer server
+ remains a single process, and it may at some point become a bottleneck
+ of an application.</p>
<p>The functions in the <c>timer</c> module that do not manage timers
(such as <c>timer:tc/3</c> or <c>timer:sleep/1</c>), do not call the
@@ -85,7 +90,7 @@
<p>a list with 10000 elements (or about 20000 heap words) will be
copied to the newly created process.</p>
- <p>An unncessary copy of 10000 element list can be bad enough, but it
+ <p>An unnecessary copy of 10000 element list can be bad enough, but it
can get even worse if the <c>state</c> record contains <em>shared subterms</em>.
Here is a simple example of a term with a shared subterm:</p>
@@ -192,7 +197,7 @@ multiple_setelement(T0) ->
<p>The two following <c>setelement/3</c> calls modify
the tuple in place.</p>
- <p>For the optimization to be applied, <em>all</em> the followings conditions
+ <p>For the optimization to be applied, <em>all</em> the following conditions
must be true:</p>
<list type="bulleted">
diff --git a/system/doc/efficiency_guide/functions.xml b/system/doc/efficiency_guide/functions.xml
index 0a8ee7eb34..f3d6b59e49 100644
--- a/system/doc/efficiency_guide/functions.xml
+++ b/system/doc/efficiency_guide/functions.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2017</year>
+ <year>2001</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -158,22 +158,23 @@ explicit_map_pairs(Map, Xs0, Ys0) ->
<section>
<title>Function Calls</title>
- <p>This is an intentionally rough guide to the relative costs of
- different calls. It is based on benchmark figures run on
- Solaris/Sparc:</p>
+ <p>This is a rough hierarchy of the performance of the
+ different types of function calls:</p>
<list type="bulleted">
<item>Calls to local or external functions (<c>foo()</c>, <c>m:foo()</c>)
are the fastest calls.</item>
<item>Calling or applying a fun (<c>Fun()</c>, <c>apply(Fun, [])</c>)
- is about <em>three times</em> as expensive as calling a local
- function.</item>
+ is just a little slower than external calls.</item>
<item>Applying an exported function (<c>Mod:Name()</c>,
- <c>apply(Mod, Name, [])</c>) is about twice as expensive as calling
- a fun or about <em>six times</em> as expensive as calling a local
- function.</item>
+ <c>apply(Mod, Name, [])</c>) where the number of arguments is known
+ at compile time is next.</item>
+
+ <item>Applying an exported function (<c>apply(Mod, Name, Args)</c>)
+ where the number of arguments is not known at compile time is the
+ least efficient.</item>
</list>
<section>
@@ -187,25 +188,8 @@ explicit_map_pairs(Map, Xs0, Ys0) ->
in a hash table. It is therefore always slower than a
direct call or a fun call.</p>
- <p>It no longer matters (from a performance point of view)
- whether you write:</p>
-
- <code type="erl">
-Module:Function(Arg1, Arg2)</code>
-
- <p>or:</p>
-
- <code type="erl">
-apply(Module, Function, [Arg1,Arg2])</code>
-
- <p>The compiler internally rewrites the latter code into the
- former.</p>
-
- <p>The following code is slightly slower because the shape of the
- list of arguments is unknown at compile time.</p>
-
- <code type="erl">
-apply(Module, Function, Arguments)</code>
+ <p>Caching callback functions into funs may be more efficient
+ in the long run than apply calls for frequently-used callbacks.</p>
</section>
</section>
diff --git a/system/doc/efficiency_guide/retired_myths.xml b/system/doc/efficiency_guide/retired_myths.xml
index a763770e5a..593e8f5492 100644
--- a/system/doc/efficiency_guide/retired_myths.xml
+++ b/system/doc/efficiency_guide/retired_myths.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2016</year>
- <year>2020</year>
+ <year>2021</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -31,7 +31,7 @@
<file>retired_myths.xml</file>
</header>
- <p>We belive that the truth finally has caught with the following,
+ <p>We believe that the truth finally has caught with the following,
retired myths.</p>
<section>
diff --git a/system/doc/efficiency_guide/tablesDatabases.xml b/system/doc/efficiency_guide/tablesDatabases.xml
index 3f77151e55..ba0d5e2e40 100644
--- a/system/doc/efficiency_guide/tablesDatabases.xml
+++ b/system/doc/efficiency_guide/tablesDatabases.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2016</year>
+ <year>2001</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -137,7 +137,7 @@ print_person(PersonId) ->
io:format("No person with ID = ~p~n", [PersonID])
end.
-%%% Internal functionss
+%%% Internal functions
print_name(PersonID) ->
[Person] = ets:lookup(person, PersonId),
io:format("No person ~p~n", [Person#person.name]).
diff --git a/system/doc/embedded/intro.xml b/system/doc/embedded/intro.xml
index 2b9d35d24c..cec3212481 100644
--- a/system/doc/embedded/intro.xml
+++ b/system/doc/embedded/intro.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1997</year>
- <year>2016</year>
+ <year>2021</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -37,7 +37,7 @@
<p>This manual is a complement to the other manuals and describes how
to install, run and maintain Erlang on an embedded system.
</p>
- <p>For more informaton about how to install and start Erlang read
+ <p>For more information about how to install and start Erlang read
XXXXXXXX.
</p>
diff --git a/system/doc/general_info/DEPRECATIONS b/system/doc/general_info/DEPRECATIONS
index ab304db2a8..2f83cbb9d3 100644
--- a/system/doc/general_info/DEPRECATIONS
+++ b/system/doc/general_info/DEPRECATIONS
@@ -18,13 +18,25 @@
#
#
+# Added in OTP 25.
+#
+slave:_/_ since=25 remove=27
+ct_slave:_/_ since=25 remove=27
+httpd_util:encode_hex/1 since=25 remove=26
+httpd_util:decode_hex/1 since=25 remove=26
+
+crypto:crypto_dyn_iv_init/3 since=25 remove=27
+crypto:crypto_dyn_iv_update/3 since=25 remove=27
+erts_alloc_config:_/_ since=25 remove=26
+
+#
# Added in OTP 24.
#
-public_key:ssh_hostkey_fingerprint/1 since=24 remove=26
-public_key:ssh_hostkey_fingerprint/2 since=24 remove=26
-public_key:ssh_decode/2 since=24 remove=26
-public_key:ssh_encode/2 since=24 remove=26
+public_key:ssh_hostkey_fingerprint/1 since=24 remove=25
+public_key:ssh_hostkey_fingerprint/2 since=24 remove=25
+public_key:ssh_decode/2 since=24 remove=25
+public_key:ssh_encode/2 since=24 remove=25
ftp:start_service/1 since=24 remove=26
ftp:stop_service/1 since=24 remove=26
httpd_util:flatlength/1 since=24 remove=26
@@ -57,8 +69,8 @@ ssl:cipher_suites/0 since=21 remove=24
http_uri:parse/1 since=23 remove=25
http_uri:parse/2 since=23 remove=25
-http_uri:encode/1 since=23 remove=25
-http_uri:decode/1 since=23 remove=25
+http_uri:encode/1 since=23 remove=26
+http_uri:decode/1 since=23 remove=26
http_uri:scheme_defaults/0 since=23 remove=25
httpd:parse_query/1 since=23
pg2:_/_ since=23 remove=24
diff --git a/system/doc/general_info/deprecations_23.inc b/system/doc/general_info/deprecations_23.inc
index ef1c6ff12f..1eb8f3dd5e 100644
--- a/system/doc/general_info/deprecations_23.inc
+++ b/system/doc/general_info/deprecations_23.inc
@@ -18,12 +18,12 @@
<section>
<title>ssh</title>
<p>The public key algorithm <c>'ssh-rsa</c> is regarded as insecure due
- to its usage of SHA1, and is therfore deprecated.
+ to its usage of SHA1, and is therefore deprecated.
It will not be available by default from OTP-24.
</p>
<p>The public key algorithm <c>'ssh-dss</c> is regarded as insecure due
- to its usage of SHA1 and its short key length, and is therfore deprecated.
+ to its usage of SHA1 and its short key length, and is therefore deprecated.
It is not available by default from OTP-23.
</p>
</section>
diff --git a/system/doc/general_info/upcoming_incompatibilities.xml b/system/doc/general_info/upcoming_incompatibilities.xml
index 69a0f6de16..59003d2243 100644
--- a/system/doc/general_info/upcoming_incompatibilities.xml
+++ b/system/doc/general_info/upcoming_incompatibilities.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2021</year>
+ <year>2021</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -132,5 +132,18 @@
</list>
</section>
+ <section>
+ <title>The default timewarp mode will change to multi-time warp mode</title>
+ <p>
+ The default <seeguide marker="erts:time_correction#Time_Warp_Modes">
+ Time Warp Mode</seeguide> will be changed from
+ <seeguide marker="erts:time_correction#No_Time_Warp_Mode">
+ no time warp mode</seeguide> to <seeguide marker="erts:time_correction#Multi_Time_Warp_Mode">
+ multi-time warp mode</seeguide>. See <seeguide marker="erts:time_correction">
+ Time and Time Correction in Erlang</seeguide> for details on how this will
+ effect your system.
+ </p>
+ </section>
+
</section>
</chapter>
diff --git a/system/doc/programming_examples/bit_syntax.xml b/system/doc/programming_examples/bit_syntax.xml
index cc89f3a469..08587ccff3 100644
--- a/system/doc/programming_examples/bit_syntax.xml
+++ b/system/doc/programming_examples/bit_syntax.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2020</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -206,7 +206,7 @@ X:4/little-signed-integer-unit:8</code>
matching, this default value is only valid for the last
element. All other binary elements in matching must have a size
specification.</p>
- <p>The default unit depends on the the type. For <c>integer</c>,
+ <p>The default unit depends on the type. For <c>integer</c>,
<c>float</c>, and <c>bitstring</c> it is 1. For binary it is 8.</p>
<p>The default signedness is <c>unsigned</c>.</p>
<p>The default endianness is <c>big</c>.</p>
@@ -311,8 +311,8 @@ foo(N, Bin) ->
<section>
<title>Binding and Using a Size Variable</title>
<p>There is one exception to the rule that a variable that is
- as size must be previously bound. It is possible to match and
- bind a variable, and use it as a size within the the same
+ used as size must be previously bound. It is possible to match and
+ bind a variable, and use it as a size within the same
binary pattern. For example:</p>
<code type="none"><![CDATA[
diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml
index 15983ebbf9..1a4bdc5680 100644
--- a/system/doc/reference_manual/data_types.xml
+++ b/system/doc/reference_manual/data_types.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -30,7 +30,15 @@
<file>data_types.xml</file>
</header>
<p>Erlang provides a number of data types, which are listed in
- this section.</p>
+ this section.</p>
+
+ <marker id="no_user_types" />
+ <p>Note that Erlang has no user defined types, only composite
+ types (data structures) made of Erlang terms. This means that any
+ function testing for a composite type, typically named
+ <c>is_type/1</c>, might return <c>true</c> for a term
+ that coincides with the chosen representation. The corresponding
+ functions for built in types do not suffer from this.</p>
<section>
<title>Terms</title>
@@ -85,8 +93,8 @@
<p>When working with floats you may not see what you expect when printing or
doing arithmetic operations. This is because floats
are represented by a fixed number of bits in a base-2 system while
- printed floats are represented with a base-10 system. Here are
- examples of this phenomenon:
+ printed floats are represented with a base-10 system. Erlang
+ uses 64-bit floats. Here are examples of this phenomenon:
</p>
<pre>
> <input>0.1+0.2.</input>
diff --git a/system/doc/reference_manual/distributed.xml b/system/doc/reference_manual/distributed.xml
index cc4746825b..f8fb159be3 100644
--- a/system/doc/reference_manual/distributed.xml
+++ b/system/doc/reference_manual/distributed.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -155,7 +155,7 @@ dilbert@uab</pre>
name from the first node it connects to. In addition these
distribution settings will be set:
</p>
- <pre><seeapp marker="kernel:kernel_app#dist_listen">-dist_listen false</seeapp> <seecom marker="erts:erl#hidden">-hidden</seecom> <seeapp marker="kernel:kernel_app#dist_auto_connect">-dist_auto_connect never</seeapp></pre>
+ <pre><seecom marker="erts:erl#dist_listen">-dist_listen false</seecom> <seecom marker="erts:erl#hidden">-hidden</seecom> <seeapp marker="kernel:kernel_app#dist_auto_connect">-kernel dist_auto_connect never</seeapp></pre>
<p>
As <c>-dist_auto_connect</c> is set to <c>never</c>,
<seemfa marker="kernel:net_kernel#connect_node/1"><c>net_kernel:connect_node/1</c></seemfa>
@@ -212,7 +212,7 @@ dilbert@uab</pre>
in the following text is not very unpredictable.
A better one can be generated using primitives
in the <c>crypto</c> module, though this still does not make
- the inital handshake cryptographically secure.
+ the initial handshake cryptographically secure.
And inter-node communication is still in clear text.
</p>
</note>
@@ -230,9 +230,14 @@ dilbert@uab</pre>
<p>At start-up, a node has a random atom assigned as its default
magic cookie and the cookie of other nodes is assumed to be
<c>nocookie</c>. The first action of the Erlang network
- authentication server (<c>auth</c>) is then to read a file named
- <c>$HOME/.erlang.cookie</c>. If the file does not exist, it is
- created. The UNIX permissions mode of the file is set to octal
+ authentication server (<c>auth</c>) is then to search for a file named
+ <c>.erlang.cookie</c> in the <seeerl marker="erts:init#home">
+ user&apos;s home directory</seeerl> and then in
+ <seeerl marker="stdlib:filename#user_config">
+ <c>filename:basedir(user_config, "erlang")</c></seeerl>.
+ If none of the files exist, a <c>.erlang.cooke</c> file is created
+ in the user&apos;s home directory.
+ The UNIX permissions mode of the file is set to octal
400 (read-only by user) and its content is a random string. An
atom <c>Cookie</c> is created from the contents of the file and
the cookie of the local node is set to this using
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 8dbc620bd0..af143ad4d5 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>2021</year>
+ <year>2003</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -395,6 +395,139 @@ is_valid_signal(Signal) ->
</section>
<section>
+ <marker id="maybe"></marker>
+ <title>Maybe</title>
+ <note><p><c>maybe</c> is an experimental new <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ introduced in OTP 25. By default, it is disabled. To enable
+ <c>maybe</c>, either use the <c>-feature(maybe_expr,enable)</c>
+ directive (from within source code), or the compiler option
+ <c>{feature,maybe_expr,enable}</c>. The feature must also be enabled
+ in runtime using the <c>-enable-feature</c> option to <c>erl</c>.</p>
+ </note>
+
+ <code type="erl"><![CDATA[
+maybe
+ Expr1,
+ ...,
+ ExprN
+end]]></code>
+
+ <p>The expressions in a <c>maybe</c> block are evaluated sequentially. If all
+ expressions are evaluated successfully, the return value of the <c>maybe</c>
+ block is <c>ExprN</c>. However, execution can be short-circuited by a
+ conditional match expression:</p>
+
+ <code type="erl"><![CDATA[
+Expr1 ?= Expr2]]></code>
+
+ <p><c>?=</c> is called the conditional match operator. It is only
+ allowed to be used at the top-level of a <c>maybe</c> block. It
+ matches the pattern <c>Expr1</c> against <c>Expr2</c>. If the
+ matching succeeds, any unbound variable in the pattern becomes
+ bound. If the expression is the last expression in the
+ <c>maybe</c> block, it also returns the value of <c>Expr2</c>. If the
+ matching is unsuccessful, the rest of the expressions in the <c>maybe</c>
+ block are skipped and the return value of the <c>maybe</c>
+ block is <c>Expr2</c>.</p>
+
+ <p>None of the variables bound in a <c>maybe</c> block must be
+ used in the code that follows the block.</p>
+
+ <p>Here is an example:</p>
+
+ <code type="erl"><![CDATA[
+maybe
+ {ok, A} ?= a(),
+ true = A >= 0,
+ {ok, B} ?= b(),
+ A + B
+end]]></code>
+
+ <p>Let us first assume that <c>a()</c> returns <c>{ok,42}</c> and
+ <c>b()</c> returns <c>{ok,58}</c>. With those return values, all
+ of the match operators will succeed, and the return value of the
+ <c>maybe</c> block is <c>A + B</c>, which is equal to <c>42 +
+ 58 = 100</c>.</p>
+
+ <p>Now let us assume that <c>a()</c> returns <c>error</c>. The
+ conditional match operator in <c>{ok, A} ?= a()</c> fails to
+ match, and the return value of the <c>maybe</c> block is the
+ value of the expression that failed to match, namely <c>error</c>.
+ Similarly, if <c>b()</c> returns <c>wrong</c>, the return value of
+ the <c>maybe</c> block is <c>wrong</c>.</p>
+
+ <p>Finally, let us assume that <c>a()</c> returns
+ <c>-1</c>. Because <c>true = A >= 0</c> uses the match operator
+ `=`, a <c>{badmatch,false}</c> run-time error occurs when the
+ expression fails to match the pattern.</p>
+
+ <p>The example can be written in a less succient way using nested
+ case expressions:</p>
+
+ <code type="erl"><![CDATA[
+case a() of
+ {ok, A} ->
+ true = A >= 0,
+ case b() of
+ {ok, B} ->
+ A + B;
+ Other1 ->
+ Other1
+ end;
+ Other2 ->
+ Other2
+end]]></code>
+
+ <p>The <c>maybe</c> block can be augmented with <c>else</c> clauses:</p>
+
+ <code type="erl"><![CDATA[
+maybe
+ Expr1,
+ ...,
+ ExprN
+else
+ Pattern1 [when GuardSeq1] ->
+ Body1;
+ ...;
+ PatternN [when GuardSeqN] ->
+ BodyN
+end]]></code>
+
+ <p>If a conditional match operator fails, the failed expression is
+ matched against the patterns in all clauses between the
+ <c>else</c> and <c>end</c> keywords. If a match succeeds and the
+ optional guard sequence <c>GuardSeq</c> is true, the corresponding
+ <c>Body</c> is evaluated. The value returned from the body is the
+ return value of the <c>maybe</c> block.</p>
+
+ <p>If there is no matching pattern with a true guard sequence,
+ an <c>else_clause</c> run-time error occurs.</p>
+
+ <p>None of the variables bound in a <c>maybe</c> block must be used in
+ the <c>else</c> clauses. None of the variables bound in the <c>else</c> clauses
+ must be used in the code that follows the <c>maybe</c> block.</p>
+
+ <p>Here is the previous example augmented with a <c>else</c> clauses:</p>
+
+ <code type="erl"><![CDATA[
+maybe
+ {ok, A} ?= a(),
+ true = A >= 0,
+ {ok, B} ?= b(),
+ A + B
+else
+ error -> error;
+ wrong -> error
+end]]></code>
+
+ <p>The <c>else</c> clauses translate the failing value from
+ the conditional match operators to the value <c>error</c>. If the
+ failing value is not one of the recognized values, a
+ <c>else_clause</c> run-time error occurs.</p>
+ </section>
+
+ <section>
<marker id="send"></marker>
<title>Send</title>
<pre>
@@ -824,7 +957,7 @@ Expr1 -- Expr2</pre>
<p>The list concatenation operator <c>++</c> appends its second
argument to its first and returns the resulting list.</p>
<p>The list subtraction operator <c>--</c> produces a list that
- is a copy of the first argument. The procedure is a follows:
+ is a copy of the first argument. The procedure is as follows:
for each element in the second argument, the first
occurrence of this element (if any) is removed.</p>
<p><em>Example:</em></p>
@@ -1014,7 +1147,7 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code>
<p>
Here keys <c>K1 .. Kn</c> are any expressions with
literals or bound variables. If all key expressions
- evalute successfully and all keys exist in map
+ evaluate successfully and all keys exist in map
<c>M</c>, all variables in <c>V1 .. Vn</c> is
matched to the associated values of their respective
keys.
@@ -1575,7 +1708,11 @@ end</pre>
<c>BitStringExpr</c> must be an expression, which evaluates to a
bitstring.</item>
<item>A <em>filter</em> is an expression, which evaluates to
- <c>true</c> or <c>false</c>.</item>
+ <c>true</c> or <c>false</c>, or a
+ <seeguide marker="#guard_expressions">guard expression</seeguide>.
+ If the filter is not a guard expression and evaluates
+ to a non-Boolean value <c>Val</c>, an exception
+ <c>{bad_filter, Val}</c> is triggered at runtime.</item>
</list>
<p>The variables in the generator patterns shadow previously bound variables,
including variables bound in a previous generator pattern.</p>
@@ -1612,7 +1749,7 @@ end</pre>
the following syntax:</p>
<pre>
&lt;&lt; BitStringExpr || Qualifier1,...,QualifierN &gt;&gt;</pre>
- <p><c>BitStringExpr</c> is an expression that evalutes to a bit
+ <p><c>BitStringExpr</c> is an expression that evaluates to a bit
string. If <c>BitStringExpr</c> is a function call, it must be
enclosed in parentheses. Each <c>Qualifier</c> is either a
generator, a bit string generator or a filter.</p>
@@ -1626,8 +1763,12 @@ end</pre>
&nbsp;&nbsp;<c><![CDATA[BitstringPattern <= BitStringExpr]]></c>. <br></br>
<c>BitStringExpr</c> must be an expression that evaluates to a
bitstring.</item>
- <item>A <em>filter</em> is an expression that evaluates to
- <c>true</c> or <c>false</c>.</item>
+ <item>A <em>filter</em> is an expression, which evaluates to
+ <c>true</c> or <c>false</c>, or a
+ <seeguide marker="#guard_expressions">guard expression</seeguide>.
+ If the filter is not a guard expression and evaluates
+ to a non-Boolean value <c>Val</c>, an exception
+ <c>{bad_filter, Val}</c> is triggered at runtime.</item>
</list>
<p>The variables in the generator patterns shadow previously bound variables,
including variables bound in a previous generator pattern.</p>
@@ -1675,7 +1816,7 @@ end</pre>
<item>Expressions that construct atoms, integer, floats, lists,
tuples, records, binaries, and maps</item>
<item>Expressions that update a map</item>
- <item>The record epxressions <c>Expr#Name.Field</c> and <c>#Name.Field</c></item>
+ <item>The record expressions <c>Expr#Name.Field</c> and <c>#Name.Field</c></item>
<item>Calls to the BIFs specified in tables <em>Type Test BIFs</em> and
<em>Other BIFs Allowed in Guard Expressions</em></item>
<item>Term comparisons</item>
@@ -1854,6 +1995,10 @@ end</pre>
<cell align="left" valign="middle">Right associative</cell>
</row>
<row>
+ <cell align="left" valign="middle">?=</cell>
+ <cell align="left" valign="middle">&nbsp;</cell>
+ </row>
+ <row>
<cell align="left" valign="middle">catch</cell>
<cell align="left" valign="middle">&nbsp;</cell>
</row>
diff --git a/system/doc/reference_manual/features.xml b/system/doc/reference_manual/features.xml
new file mode 100644
index 0000000000..882cdd2582
--- /dev/null
+++ b/system/doc/reference_manual/features.xml
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2022</year><year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Features</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>features.xml</file>
+ </header>
+ <p>
+ <marker id="features"/>
+ Introduced in OTP 25, Erlang has the concept of selectable features.
+ A feature can change, add or remove behaviour of the language and/or
+ runtime system. Examples can include
+ </p>
+ <list>
+ <item>Adding new syntactical constructs to the language</item>
+ <item>Change the semantics of an existing construct</item>
+ <item>Change the behaviour of some runtime aspect</item>
+ </list>
+ <p>
+ A feature will start out with a status of experimental part of OTP,
+ making it possible to try out for users and give feedback. The
+ possibility to try out features is enabled by options to the
+ compiler, directives in a module and options to the runtime system.
+ Even when a feature is not experimental it will still be possible to
+ enable or disable it. This makes it possible to adapt a code base
+ at a suitable pace instead of being forced when changing to a new
+ release.
+ </p>
+ <p>
+ The status of a feature will eventually end up as being either a
+ permanent part of OTP or rejected, being removed and no longer
+ selectable.
+ </p>
+
+ <section>
+ <title>Life cycle of features</title>
+ <p>A feature is in one of four possible states:</p>
+ <taglist>
+ <tag>Experimental</tag>
+ <item>The initial state, is meant for trying out and collecting
+ feedback. The feature can be enabled but is disabled by
+ default.</item>
+ <tag>Approved</tag>
+ <item>The feature has been finalised and is now part of OTP. By
+ default it is enabled, but can be disabled.</item>
+ <tag>Permanent</tag>
+ <item>The feature is now a permanent part of OTP. It can no
+ longer be disabled.</item>
+ <tag>Rejected</tag>
+ <item>The feature never reached the approved state and will not
+ be part of OTP. It cannot be enabled.</item>
+ </taglist>
+ <p>
+ After leaving the experimental state, a feature can enter any of
+ the other three states, and if the next state is approved, the
+ feature will eventually end up in the permanent state. A feature
+ can change state only in connection with a release.
+ </p>
+ <p>
+ A feature may be in the approved state for several releases.
+ </p>
+ <table>
+ <row>
+ <cell>State</cell>
+ <cell>Default</cell>
+ <cell>Configurable</cell>
+ <cell>Available</cell>
+ </row>
+ <row>
+ <cell>Experimental</cell>
+ <cell>disabled</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ </row>
+ <row>
+ <cell>Approved</cell>
+ <cell>enabled</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ </row>
+ <row>
+ <cell>Permanent</cell>
+ <cell>enabled</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ </row>
+ <row>
+ <cell>Rejected</cell>
+ <cell>disabled</cell>
+ <cell>no</cell>
+ <cell>no</cell>
+ </row>
+ <tcaption>Feature States</tcaption>
+ </table>
+ <list>
+ <item>Being configurable means the possibility to enable or
+ disable the feature by means of compiler options and directives
+ in the file being compiled.</item>
+ <item>Being available can be seen using the
+ <c>FEATURE_AVAILABLE</c> macro.</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Enabling and Disabling Features</title>
+ <p>To use a feature that is in the experimental state, it has to
+ be enabled during compilation. This can be done in a number of
+ different ways:
+ </p>
+ <taglist>
+ <tag>Options to <c>erlc</c></tag>
+ <item>Options <seecom
+ marker="erts:erlc#enable-feature"><c>-enable-feature</c></seecom>
+ and <seecom
+ marker="erts:erlc#disable-feature"><c>-disable-feature</c></seecom>
+ can be used to enable or disable individal features.</item>
+ <tag>Compiler options</tag>
+ <item>The compiler option <seeerl
+ marker="compiler:compile#feature-option"><c>{feature,
+ &lt;feature&gt;, enable|disable}</c></seeerl> can be used either
+ as a <c>+&lt;term&gt;</c> option to <c>erlc</c> or in the options
+ argument to functions in the <c>compile</c> module.</item>
+ <tag>The feature directive</tag>
+ <item>Inside a prefix of a module, one can use a <seeguide
+ marker="macros#feature-directive"><c>-feature(&lt;feature&gt;,
+ enable|disable)</c></seeguide> directive. This is the preferred
+ method of enabling and disabling features.</item>
+ </taglist>
+ <p>
+ Note that to load a module compiled with features enabled, the
+ corresponding features must be enabled in the runtime. This
+ is done using options <seecom
+ marker="erts:erl#enable-feature"><c>-enable-feature</c></seecom>
+ and <seecom
+ marker="erts:erl#disable-feature"><c>-disable-feature</c></seecom>
+ to <c>erl</c>. This is to allow the possibility to prevent
+ the use of experimental features in, e.g., production. This
+ will catch experimental features used in both own and third
+ party components. An active choice to use experimental
+ features must be done.
+ </p>
+ </section>
+
+ <section>
+ <title>Preprocessor Additions</title>
+ <p>
+ To allow for conditional compilation during transitioning of a
+ code base and/or trying out experimental features <seeguide
+ marker="system/reference_manual:macros#predefined-macros">feature</seeguide>
+ <c>predefined macros</c> <c>?FEATURE_AVAILABLE(Feature)</c> and
+ <c>?FEATURE_ENABLED(Feature)</c> are available.
+ </p>
+ </section>
+
+ <section>
+ <title>Information about Existing Features</title>
+ <p>
+ The module <c>erl_features</c> <seeerl
+ marker="stdlib:erl_features"><c>erl_features</c></seeerl> exports
+ a number of functions that can be used to obtain information about
+ current features as well as the features used when compiling a
+ module.
+ </p>
+ <p>One can also use the <c>erlc</c> options <seecom
+ marker="erts:erlc#list-features"><c>-list-features</c></seecom>
+ and <seecom
+ marker="erts:erlc#describe-feature"><c>-describe-feature
+ &lt;feature&gt;</c></seecom> to get information about existing
+ features.
+ </p>
+ <p>
+ Additionally, there is the compiler option
+ <seeerl
+ marker="compiler:compile#warn-keywords"><c>warn_keywords</c></seeerl>
+ that can be used to find atoms in the code base that might
+ collide with keywords in features not yet enabled.
+ </p>
+ </section>
+
+ <section>
+ <title>Existing Features</title>
+ <p>
+ The following configurable features exist:
+ </p>
+ <taglist>
+ <tag><c>maybe_expr</c> (experimental)</tag>
+ <item>
+ Implementation of the <seeguide
+ marker="expressions#maybe"><c>maybe</c></seeguide> expression
+ proposed in <url href="https://www.erlang.org/eeps/eep-0049">EEP 49</url>.</item>
+ </taglist>
+ </section>
+</chapter>
diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml
index 0943dbd56d..e54e0e1d30 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>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -134,7 +134,8 @@ bar(X) ->
<section>
<title>Predefined Macros</title>
- <p>The following macros are predefined:</p>
+ <p>
+ The following macros are predefined:</p>
<taglist>
<tag><c>?MODULE</c></tag>
<item>The name of the current module.</item>
@@ -155,6 +156,17 @@ bar(X) ->
application is part of, as an integer. For details, see
<seemfa marker="erts:erlang#system_info/1"><c>erlang:system_info(otp_release)</c></seemfa>.
This macro was introduced in OTP release 21.</item>
+ <tag><c>?FEATURE_AVAILABLE(Feature)</c></tag>
+ <item>Expands to <c>true</c> if the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>Feature</c> is available. The feature might or might not
+ be enabled. This macro was introduced with OTP release
+ 25.</item>
+ <tag><c>?FEATURE_ENABLED(Feature)</c></tag>
+ <item>Expands to <c>true</c> if the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>Feature</c> is enabled. This macro was introduced with OTP
+ release 25.</item>
</taglist>
</section>
@@ -265,6 +277,27 @@ or
</section>
<section>
+ <title>
+ The -feature() directive
+ </title>
+ <marker id="feature-directive"/>
+
+ <p>
+ The directive <c>-feature(FeatureName, enable | disable)</c> can
+ be used to enable or disable the <seeguide
+ marker="system/reference_manual:features#features">feature</seeguide>
+ <c>FeatureName</c>. This is the preferred way of enabling
+ (disabling) features, although it is possible to do it with
+ options to the compiler as well.
+ </p>
+ <p>
+ Note that the <c>-feature(..)</c> directive may only appear
+ before any syntax is used. In practice this means it should
+ appear before any <c>-export(..)</c> or record definitions.
+ </p>
+ </section>
+
+ <section>
<title>-error() and -warning() directives</title>
<p>The directive <c>-error(Term)</c> causes a compilation error.</p>
diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml
index f5ea7d1580..b373e2506b 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>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -129,6 +129,36 @@ fact(0) -> % |
<seeguide marker="code_loading#on_load">
Running a Function When a Module is Loaded</seeguide>.</p>
</item>
+ <tag><marker id="nifs_attribute"/><c>-nifs(Functions).</c></tag>
+ <item>
+ <p>
+ Specifies which of the functions, defined within the module, that
+ may be loaded as NIFs with <seemfa marker="erts:erlang#load_nif/2">
+ <c>erlang:load_nif/2</c></seemfa>.
+ </p>
+ <p>
+ <c>Functions</c> is a list
+ <c>[Name1/Arity1, ..., NameN/ArityN]</c>, where each
+ <c>NameI</c> is an atom and <c>ArityI</c> an integer.
+ </p>
+ <note>
+ <p>
+ The <c>-nifs()</c> attribute was introduced in OTP 25.0. For older
+ Erlang source code without it, any functions in the module may be
+ loaded as NIFs. However, it is recommended to declare the NIFs with
+ the <c>-nifs</c> attribute. This allows the compiler to make better
+ decisions regarding optimizations for example.
+ </p>
+ <p>
+ There is no need to add <c>-nifs([])</c> in modules that do not
+ load NIFs. The lack of any call to
+ <seemfa marker="erts:erlang#load_nif/2"><c>erlang:load_nif/2</c></seemfa>,
+ from within the module, is enough for the compiler to draw the
+ same conclusion.
+ </p>
+ </note>
+ </item>
+
</taglist>
</section>
@@ -221,6 +251,30 @@ behaviour_info(callbacks) -> Callbacks.</pre>
</section>
<section>
+ <title>
+ The feature directive
+ </title>
+
+ <p>
+ While not a module attribute, but rather a directive (since it
+ might affect syntax), there is the <c>-feature(..)</c>
+ directive used for enabling and disabling <seeguide
+ marker="system/reference_manual:features#features">features</seeguide>.
+ </p>
+ <p>
+ The syntax is similar to that of an attribute, but has two
+ arguments:
+ </p>
+ <pre>
+-feature(FeatureName, enable | disable).</pre>
+ <p>
+ Note that the <seeguide
+ marker="macros#feature-directive">feature directive</seeguide>
+ can only appear in a prefix of the module.
+ </p>
+ </section>
+
+ <section>
<title>Comments</title>
<p>Comments can be placed anywhere in a module except within strings
and quoted atoms. A comment begins with the character "%",
diff --git a/system/doc/reference_manual/opaques.xml b/system/doc/reference_manual/opaques.xml
new file mode 100644
index 0000000000..8fa3bae3e5
--- /dev/null
+++ b/system/doc/reference_manual/opaques.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2021</year>
+ <year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Opaques</title>
+ <prepared>Max Heiber</prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>opaques.xml</file>
+ </header>
+
+ <section>
+ <title>Opaque Type Aliases</title>
+ <p>The main use case for opacity in Erlang is to hide the implementation of a data type, enabling evolving the API while minimizing the risk of breaking consumers. The runtime does not check opacity. Dialyzer provides some opacity-checking, but the rest is up to convention.
+ </p>
+ <p>
+ This document explains what Erlang opacity is (and the trade-offs involved) via the example of OTP's
+ <c>sets:set()</c>
+ data type. This type
+ <em>was</em>
+ defined in `sets` module like this:
+ </p>
+ <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)}.</code>
+ <p>OTP 24 changed the definition to the following, in
+ <url href="https://github.com/erlang/otp/commit/e66941e8d7c47b973dff94c0308ea85a6be1958e">this commit</url>
+ </p>
+ <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.</code>
+ <p>
+ And this change was safer and more backwards-compatible than if the type had been defined with
+ <c>-type</c>
+ instead of
+ <c>-opaque</c>
+ . Here's why: when a module defines an
+ <c>-opaque</c>
+ , the contract is that only the defining module should rely on the definition of the type: no other modules should rely on the definition.
+ </p>
+ <p>
+ This means that code that pattern-matched on
+ <c>set</c>
+ as a record/tuple technically broke the contract, and opted in to being potentially broken when the definition of
+ <c>set()</c>
+ changed. Before OTP 24, this code printed
+ <c>ok</c>
+ . In OTP 24 it may error:
+ </p>
+ <code type="erl">
+case sets:new() of
+ Set when is_tuple(Set) -&gt;
+ io:format(&quot;ok&quot;)
+end.
+ </code>
+ <p>
+ <strong>When working with an opaque defined in another module, here are some recommendations:</strong>
+ </p>
+
+ <list type="bulleted">
+ <item>
+ Don't examine the underlying type using pattern-matching, guards, or functions that reveal the type, such as
+ <c>tuple_size/1</c>
+ .
+ </item>
+ <item>
+ Instead, use functions provided by the module for working with the type. For example,
+ <c>sets</c>
+ module provides
+ <c>sets:new/0</c>
+ ,
+ <c>sets:add/2</c>
+ ,
+ <c>sets:is_element/2</c>
+ , etc.
+ </item>
+ <item>
+ <c>sets:set(a)</c>
+ is a subtype of
+ <c>sets:set(a | b)</c>
+ and not the other way around. Generally, you can rely on the property that
+ <c>the_opaque(T)</c>
+ is a subtype of
+ <c>the_opaque(U)</c>
+ when T is a subtype of U.
+ </item>
+ </list>
+ <p>
+ <strong>When defining your own opaques, here are some recommendations:</strong>
+ </p>
+ <list type="bulleted">
+ <item>
+ Since consumers are expected to not rely on the definition of the opaque type, you must provide functions for constructing and querying/deconstructing intances of your opaque type. For example, sets can be constructed with
+ <c>sets:new/0</c>, <c>sets:from_list/1</c>, <c>sets:add/2</c>, queried with <c>sets:is_element/2</c>, and deconstructed with<c>sets:to_list/1</c>.
+ </item>
+ <item>
+ Don't define an opaque with a type variable in parameter position. This breaks the normal and expected behavior that (for example)
+ <c>my_type(a)</c> is a subtype of <c>my_type(a | b)</c>
+ </item>
+ <item>
+ Add <seeguide marker="typespec">specs</seeguide> to exported functions that use the opaque type
+ </item>
+ </list>
+ <p>Note that opaques can be harder to work with for consumers, since the consumer is expected not to pattern-match and must instead use functions that the author of the opaque type provides to use instances of the type.</p>
+ <p>
+ Also, opacity in Erlang is skin-deep: the runtime does not enforce opacity-checking. So now that sets are implemented in terms of maps, an
+ <c>is_map</c>
+ check on a set
+ <em>will</em>
+ pass. The opacity rules are only enforced by convention and by additional tooling such as Dialyzer. And this enforcement is not total: For example, determined consumer of
+ <c>sets</c>
+ can still do things that reveal the structure of the set, such as by printing, serializing, or using a set as
+ <c>term()</c>
+ and then inspecting via functions like
+ <c>is_map</c>
+ or
+ <c>maps:get/2</c>
+ . And Dialyzer must make some
+ <url href="https://github.com/erlang/otp/issues/5118">approximations</url>
+ . Opacity checking has limitations, but is still a vital tool in scalable Erlang development.
+ </p>
+ </section>
+</chapter>
diff --git a/system/doc/reference_manual/part.xml b/system/doc/reference_manual/part.xml
index 3d31157973..ec2e3e0306 100644
--- a/system/doc/reference_manual/part.xml
+++ b/system/doc/reference_manual/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2003</year><year>2016</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -35,10 +35,12 @@
<xi:include href="modules.xml"/>
<xi:include href="functions.xml"/>
<xi:include href="typespec.xml"/>
+ <xi:include href="opaques.xml"/>
<xi:include href="expressions.xml"/>
<xi:include href="macros.xml"/>
<xi:include href="records.xml"/>
<xi:include href="errors.xml"/>
+ <xi:include href="features.xml"/>
<xi:include href="processes.xml"/>
<xi:include href="distributed.xml"/>
<xi:include href="code_loading.xml"/>
diff --git a/system/doc/reference_manual/processes.xml b/system/doc/reference_manual/processes.xml
index 4c8c5f7e3f..92be5b60d3 100644
--- a/system/doc/reference_manual/processes.xml
+++ b/system/doc/reference_manual/processes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2021</year>
+ <year>2003</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -700,7 +700,12 @@ spawn(Module, Name, Args) -> pid()
<seecom marker="erts:erl#+zdbbl"><c>+zdbbl</c></seecom>. Note
that if you do raise the limit like this, you need to take care
of flow control yourself to ensure that you do not get into a
- situation with excessive memory usage.
+ situation with excessive memory usage. As of OTP 25.3 it is
+ also possible to enable <i>fully asynchronous distributed
+ signaling</i> on a per process level using
+ <seeerl marker="erts:erlang#process_flag_async_dist">
+ <c>process_flag(async_dist, Bool)</c></seeerl>. Also in this case
+ you need to take care of flow control yourself.
</p>
</item>
</taglist>
@@ -798,7 +803,7 @@ spawn(Module, Name, Args) -> pid()
<list>
<item><p>
<c>noproc</c> in case no process or port was
- found when setting up a link in a preceeding
+ found when setting up a link in a preceding
call to the
<seemfa marker="erts:erlang#link/1"><c>link(PidOrPort)</c></seemfa>
BIF. The process or port identified as sender
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index 0e3d909099..75482e5be1 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>2021</year>
+ <year>2003</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -160,7 +160,7 @@
]]></pre>
<p>
Integer values are either integer or character literals or expressions
- consisting of possibily nested unary or binary operations that evaluate to
+ consisting of possibly nested unary or binary operations that evaluate to
an integer. Such expressions can also be used in bit strings and ranges.
</p>
<p>
@@ -411,6 +411,7 @@
types are not accessible by other modules anyway - and is
always to be exported.
</p>
+ <p>Read more on <seeguide marker="opaques">Opaques</seeguide></p>
</section>
<section>
@@ -537,8 +538,7 @@
; (T4, T5) -> T6.</pre>
<p>
A current restriction, which currently results in a warning
- (not an error) by the compiler, is that the domains of
- the argument types cannot overlap.
+ by Dialyzer, is that the domains of the argument types cannot overlap.
For example, the following specification results in a warning:
</p>
<pre>
@@ -607,5 +607,13 @@
of the following form:
</p>
<pre> -spec my_error(term()) -> no_return().</pre>
+
+ <note>
+ <p>Erlang uses the shorthand version <c>_</c> as an anonymous type variable
+ equivalent to <c>term()</c> or <c>any()</c>. For example, the following function</p>
+ <pre> -spec Function(string(), _) -> string().</pre>
+ <p>is equivalent to:</p>
+ <pre> -spec Function(string(), any()) -> string().</pre>
+ </note>
</section>
</chapter>
diff --git a/system/doc/reference_manual/xmlfiles.mk b/system/doc/reference_manual/xmlfiles.mk
index 92d232b628..8e2af09699 100644
--- a/system/doc/reference_manual/xmlfiles.mk
+++ b/system/doc/reference_manual/xmlfiles.mk
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2018. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,9 +27,11 @@ REF_MAN_CHAPTER_FILES = \
macros.xml \
records.xml \
errors.xml \
+ features.xml \
processes.xml \
distributed.xml \
code_loading.xml \
ports.xml \
character_set.xml \
- typespec.xml
+ typespec.xml \
+ opaques.xml
diff --git a/system/doc/system_principles/system_principles.xml b/system/doc/system_principles/system_principles.xml
index d0c6f59807..c731e7fb66 100644
--- a/system/doc/system_principles/system_principles.xml
+++ b/system/doc/system_principles/system_principles.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2020</year>
+ <year>1996</year><year>2023</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -107,7 +107,7 @@ init:stop()</pre>
the applications Kernel and STDLIB.</item>
<item><c>start_sasl.boot</c> - Loads the code for and starts
the applications Kernel, STDLIB, and
- SASL).</item>
+ SASL.</item>
<item><c>no_dot_erlang.boot</c> - Loads the code for and
starts the applications Kernel and STDLIB.
Skips loading the file <c>.erlang</c>. Useful for scripts and
diff --git a/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl
index 5942861f0f..d609f35380 100644
--- a/system/doc/top/src/erl_html_tools.erl
+++ b/system/doc/top/src/erl_html_tools.erl
@@ -261,7 +261,7 @@ find_application_infos([{App, Vsn, AppPath, IndexURL} | Paths]) ->
case lists:keysearch("group", 1, Db) of
{value, {_, G0}} ->
% This value may be in two parts,
- % tag and desciption
+ % tag and description
case string:str(G0, " ") of
0 ->
{list_to_atom(G0), ""};
diff --git a/system/doc/tutorial/c_port.xmlsrc b/system/doc/tutorial/c_port.xmlsrc
index d89c87eeac..6646f2298e 100644
--- a/system/doc/tutorial/c_port.xmlsrc
+++ b/system/doc/tutorial/c_port.xmlsrc
@@ -158,7 +158,7 @@ Eshell V4.9.1.2 (abort with ^G)
{ok,complex1}</pre>
<p><em>Step 3.</em> Run the example:</p>
<pre>
-2> <input>complex1:start("extprg").</input>
+2> <input>complex1:start("./extprg").</input>
&lt;0.34.0>
3> <input>complex1:foo(3).</input>
4
diff --git a/system/doc/tutorial/complex6.erl b/system/doc/tutorial/complex6.erl
index a5f51886c8..05aa8e68f1 100644
--- a/system/doc/tutorial/complex6.erl
+++ b/system/doc/tutorial/complex6.erl
@@ -1,5 +1,6 @@
-module(complex6).
-export([foo/1, bar/1]).
+-nifs([foo/1, bar/1]).
-on_load(init/0).
init() ->
diff --git a/system/doc/tutorial/debugging.xml b/system/doc/tutorial/debugging.xml
new file mode 100644
index 0000000000..4439bc6d19
--- /dev/null
+++ b/system/doc/tutorial/debugging.xml
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+<chapter>
+ <header>
+ <copyright>
+ <year>2022</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Debugging NIFs and Port Drivers</title>
+ <prepared/>
+ <docno/>
+ <date/>
+ <rev/>
+ <file>debugging.xml</file>
+ </header>
+
+ <section>
+ <title>With great power comes great responsibilty</title>
+ <p>
+ NIFs and port driver code run inside the Erlang VM OS process (the
+ "Beam"). To maximize performance the code is called directly by the same
+ threads executing Erlang beam code and has full access to all the memory
+ of the OS process. A buggy NIF/driver can thus make severe damage by
+ corrupting memory.
+ </p>
+ <p>
+ In a best case scenario such memory corruption is detected immediately
+ causing the Beam to crash generating a core dump file which can be
+ analyzed to find the bug. However, it is very common for memory corruption
+ bugs to not be immediately detected when the faulty write happens, but
+ instead much later, for example when the calling Erlang process is garbage
+ collected. When that happens it can be very hard to find the root cause of
+ the memory corruption by analysing the core dump. All traces that could
+ have indicated which specific buggy NIF/driver that caused the corruption
+ may be long gone.
+ </p>
+ </section>
+ <section>
+ <title>The debug emulator</title>
+ <p>
+ One way to make debugging easier is to run an emulator built with target
+ <c>debug</c>. It will
+ </p>
+ <list type="bulleted">
+ <item>
+ <p>
+ <em>Increase probability of detecting bugs earlier</em>. It contains a
+ lot more runtime checks to ensure correct use of internal interfaces
+ and data structures.
+ </p>
+ </item>
+ <item>
+ <p>
+ <em>Generate a core dump that is easier to analyze</em>. Compiler
+ optimizations are turned off, which stops the compiler from
+ "optimizing away" variables, thus making it easier/possible to inspect
+ their state.
+ </p>
+ </item>
+ <item>
+ <p>
+ <em>Detect lock order violations</em>. A runtime lock checker will
+ verify that the locks in the
+ <seecref marker="erts:erl_nif"><c>erl_nif</c></seecref> and
+ <seecref marker="erts:erl_driver"><c>erl_driver</c></seecref>
+ APIs are seized in a consistent order that cannot result in deadlock
+ bugs.
+ </p>
+ </item>
+ </list>
+ <p>
+ In fact, we recommend to use the debug emulator as default during
+ development of NIFs and drivers, regardless if you are troubleshooting
+ bugs or not. Some subtle bugs may not be detected by the normal emulator
+ and just happen to work anyway by chance. However, another version of the
+ emulator, or even different circumstances within the same emulator, may
+ cause the bug to later provoke all kinds of problems.
+ </p>
+ <p>
+ The main disadvantage of the <c>debug</c> emulator is its reduced
+ performance. The extra runtime checks and lack of compiler optimizations
+ may result in a slowdown with a factor of two or more depending on
+ load. The memory footprint should be about the same.
+ </p>
+ <p>
+ If the <c>debug</c> emulator is part of the Erlang/OTP installation, it can be
+ started with the <seecom marker="erts:erl#emu_type"><c>-emu_type</c></seecom>
+ option.
+ </p>
+ <pre>
+> <input>erl -emu_type debug</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[type-assertions] [debug-compiled] [lock-checking]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ <p>
+ If the <c>debug</c> emulator is not part of the installation, you need to
+ <seeguide marker="system/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP_Building_How-to-Build-a-Debug-Enabled-Erlang-RunTime-System">
+ build it from the Erlang/OTP source code</seeguide>. After building from source
+ either make an Erlang/OTP installation or you can run the debug emulator
+ directly in the source tree with the <c>cerl</c> script:
+ </p>
+ <pre>
+> <input>$ERL_TOP/bin/cerl -debug</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[type-assertions] [debug-compiled] [lock-checking]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ <p>
+ The <c>cerl</c> script can also be used as a convenient way to start
+ the debugger <c>gdb</c> for core dump analysis:
+ </p>
+ <pre>
+> <input>$ERL_TOP/bin/cerl -debug -core core.12345</input>
+or
+> <input>$ERL_TOP/bin/cerl -debug -rcore core.12345</input>
+</pre>
+ <p>
+ The first variant starts Emacs and runs <c>gdb</c> within, while
+ the other <c>-rcore</c> runs <c>gdb</c> directly in the terminal. Apart
+ from starting <c>gdb</c> with the correct <c>beam.debug.smp</c> executable
+ file it will also read the file <c>$ERL_TOP/erts/etc/unix/etp-commands</c>
+ which contains a lot of <c>gdb</c> command for inspecting a beam core
+ dump. For example, the command <c>etp</c> that will print the content of
+ an Erlang term (<c>Eterm</c>) in plain Erlang syntax.
+ </p>
+ </section>
+ <section>
+ <title>Address Sanitizer</title>
+ <p>
+ <url href="https://clang.llvm.org/docs/AddressSanitizer.html">
+ AddressSanitizer</url> (asan) is an open source programming tool that
+ detects memory corruption bugs such as buffer overflows, use-after-free
+ and memory leaks. AddressSanitizer is based on compiler instrumentation
+ and is supported by both gcc and clang.
+ </p>
+ <p>
+ Similar to the <c>debug</c> emulator, the <c>asan</c> emulator runs slower
+ than normal, about 2-3 times slower. However, it also has a larger memory
+ footprint, about 3 times more memory than normal.
+ </p>
+ <p>
+ To get full effect you should compile both your own NIF/driver code as
+ well as the Erlang emulator with AddressSanitizer instrumentation. Compile
+ your own code by passing option <c>-fsanitize=address</c> to gcc or
+ clang. Other recommended options that will improve the fault
+ identification are <c>-fno-common</c> and <c>-fno-omit-frame-pointer</c>.
+ </p>
+ <p>
+ Build and run the emulator with AddressSanitizer support by using the same
+ procedure as for the debug emulator, except use the <c>asan</c> build
+ target instead of <c>debug</c>.
+ </p>
+ <taglist>
+ <tag>Run in source tree</tag>
+ <item>
+ <p>
+ If you run the <c>asan</c> emulator directly in the source tree with the
+ <c>cerl</c> script you only need to set environment variable
+ <c>ASAN_LOG_DIR</c> to the directory where the error log files will be
+ generated.
+ </p>
+ <pre>
+> <input>export ASAN_LOG_DIR=/my/asan/log/dir</input>
+> <input>$ERL_TOP/bin/cerl -asan</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[address-sanitizer]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ <p>
+ You may however also want to set <c>ASAN_OPTIONS="halt_on_error=true"</c>
+ if you want the emulator to crash when an error is detected.
+ </p>
+ </item>
+ <tag>Run installed Erlang/OTP</tag>
+ <item>
+ <p>
+ If you run the <c>asan</c> emulator in an installed Erlang/OTP with <c>erl
+ -emu_type asan</c> you need to set the path to the error log
+ <em>file</em> with
+ </p>
+ <pre>
+> <input>export ASAN_OPTIONS="log_path=/my/asan/log/file"</input></pre>
+ <p>
+ To avoid false positive memory leak reports from the emulator
+ itself set <c>LSAN_OPTIONS</c> (LSAN=LeakSanitizer):
+ </p>
+ <pre>
+> <input>export LSAN_OPTIONS="suppressions=$ERL_TOP/erts/emulator/asan/suppress"</input></pre>
+ <p>
+ The <c>suppress</c> file is currently not installed but can be copied
+ manually from the source tree to wherever you want it.
+ </p>
+ </item>
+ </taglist>
+ <p>
+ Memory corruption errors are reported by AddressSanitizer when they
+ happen, but memory leaks are only checked and reported by default then the
+ emulator terminates.
+ </p>
+ </section>
+ <section>
+ <title>Valgrind</title>
+ <p>
+ An even more heavy weight debugging tool is <url
+ href="https://valgrind.org">Valgrind</url>. It can also find memory
+ corruption bugs and memory leaks similar to <c>asan</c>. Valgrind is not
+ as good at buffer overflow bugs, but it will find use of undefined data,
+ which is a type of error that <c>asan</c> cannot detect.
+ </p>
+ <p>
+ Valgrind is much slower than <c>asan</c> and it is incapable at
+ exploiting CPU multicore processing. We therefore recommend <c>asan</c> as
+ the first choice before trying valgrind.
+ </p>
+ <p>
+ Valgrind runs as a virtual machine itself, emulating execution of hardware
+ machine instructions. This means you can run almost any program unchanged
+ on valgrind. However, we have found that the beam executable benefits from
+ being compiled with special adaptions for running on valgrind.
+ </p>
+ <p>
+ Build the emulator with <c>valgrind</c> target the same as is done for
+ <c>debug</c> and <c>asan</c>. Note that <c>valgrind</c> needs to be
+ installed on the machine before the build starts.
+ </p>
+ <p>
+ Run the <c>valgrind</c> emulator directly in the source tree with the
+ <c>cerl</c> script. Set environment variable <c>VALGRIND_LOG_DIR</c> to
+ the directory where the error log files will be generated.
+ </p>
+ <pre>
+> <input>export VALGRIND_LOG_DIR=/my/valgrind/log/dir</input>
+> <input>$ERL_TOP/bin/cerl -valgrind</input>
+Erlang/OTP 25 [erts-13.0.2] ... <em>[valgrind-compiled]</em>
+
+Eshell V13.0.2 (abort with ^G)
+1>
+</pre>
+ </section>
+ <section>
+ <title>rr - Record and Replay</title>
+ <p>
+ Last but not least, the fantastic interactive debugging tool <url
+ href="https://rr-project.org/">rr</url>, developed by Mozilla as
+ open source. <c>rr</c> stands for Record and Replay. While a core dump
+ represents only a static snapshot of the OS process when it crashed, with
+ <c>rr</c> you instead record the entire session, from start of the OS
+ process to the end (the crash). You can then replay that session from
+ within <c>gdb</c>. Single step, set breakpoints and watchpoints, and even
+ <em>execute backwards</em>.
+ </p>
+ <p>
+ Considering its powerful utility, <c>rr</c> is remarkably light weight.
+ It runs on Linux with any reasonably modern x86 CPU. You may get a two
+ times slowdown when executing in recording mode. The big weakness is its
+ inability to exploite CPU multicore processing. If the bug is a race
+ condition between concurrently running threads, it may be hard to
+ reproduce with <c>rr</c>.
+ </p>
+ <p>
+ <c>rr</c> does not require any special instrumented compilation. However,
+ if possible, run it together with the <c>debug</c> emulator, as that will
+ result in a much nicer debugging experience. You run <c>rr</c> in the
+ source tree using the <c>cerl</c> script.
+ </p>
+ <p>
+ Here is an example of a typical session. First we catch the crash in an rr
+ recording session:
+ </p>
+ <pre>
+> <input>$ERL_TOP/bin/cerl -debug -rr</input>
+rr: Saving execution to trace directory /home/foobar/.local/share/rr/beam.debug.smp-1.
+Erlang/OTP 25 [erts-13.0.2]
+
+Eshell V13.0.2 (abort with ^G)
+1> <input>mymod:buggy_nif().</input>
+Segmentation fault</pre>
+ <p>
+ Now we can replay that session with <c>rr replay</c>:
+ </p>
+ <pre>
+> <input>rr replay</input>
+GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
+:
+(rr) <input>continue</input>
+:
+Thread 2 received signal SIGSEGV, Segmentation fault.
+(rr) <input>backtrace</input></pre>
+ <p>
+ You get the call stack at the moment of the crash. Bad luck, it is
+ somewhere deep down in the garbage collection of the beam. But you manage
+ to figure out that variable <c>hp</c> points to a broken Erlang term.
+ </p>
+ <p>
+ Set a watch point on that memory position and resume execution
+ <em>backwards</em>. The debugger will then stop at the exact position when
+ that memory position <c>*hp</c> was written.
+ </p>
+ <pre>
+(rr) <input>watch -l *hp</input>
+Hardware watchpoint 1: -location *hp
+(rr) <input>reverse-continue</input>
+Continuing.
+
+Thread 2 received signal SIGSEGV, Segmentation fault.</pre>
+ <p>
+ This is a quirk to be aware about. We started by executing forward until
+ it crashed with SIGSEGV. We are now executing backwards from that point,
+ so we are hitting the same SIGSEGV again but from the other
+ direction. Just continue backwards once more to move past it.
+ </p>
+ <pre>
+(rr) <input>reverse-continue</input>
+Continuing.
+
+Thread 2 hit Hardware watchpoint 1: -location *hp
+
+Old value = 42
+New value = 0</pre>
+ <p>
+ And here we are at the position when someone wrote a broken term on the
+ process heap. Note that "Old value" and "New value" are reversed when we
+ execute backwards. In this case the value 42 was written on the heap.
+ Let's see who the guilty one is:
+ </p>
+ <pre>
+(rr) <input>backtrace</input></pre>
+ </section>
+</chapter>
diff --git a/system/doc/tutorial/nif.xmlsrc b/system/doc/tutorial/nif.xmlsrc
index 5fd94a7946..5f932cd5ba 100644
--- a/system/doc/tutorial/nif.xmlsrc
+++ b/system/doc/tutorial/nif.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2021</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,8 +32,7 @@
<p>This section outlines an example of how to solve the example
problem in <seeguide marker="example">Problem Example</seeguide>
by using Native Implemented Functions (NIFs).</p>
- <p>NIFs were introduced in Erlang/OTP R13B03 as an experimental
- feature. It is a simpler and more efficient way of calling C-code
+ <p>NIFs are a simpler and more efficient way of calling C-code
than using port drivers. NIFs are most suitable for synchronous
functions, such as <c>foo</c> and <c>bar</c> in the example, that
do some relatively short calculations without side effects and
@@ -62,7 +61,7 @@
</list>
<p>Normally these are minimal stub implementations that throw an
exception. But they can also be used as fallback implementations
- for functions that do not have native implemenations on some
+ for functions that do not have native implementations on some
architectures.</p>
<p>NIF libraries are loaded by calling <c>erlang:load_nif/2</c>,
with the name of the shared library as argument. The second
@@ -99,7 +98,7 @@
<codeinclude file="complex6_nif.c" tag="" type="none"></codeinclude>
- <p>Here,<c>ERL_NIF_INIT</c> has the following arguments:</p>
+ <p>Here, <c>ERL_NIF_INIT</c> has the following arguments:</p>
<list type="bulleted">
<item><p>The first argument must be the name of the
Erlang module as a C-identifier. It will be stringified by the
diff --git a/system/doc/tutorial/part.xml b/system/doc/tutorial/part.xml
index 4a66f0cb22..f546890e79 100644
--- a/system/doc/tutorial/part.xml
+++ b/system/doc/tutorial/part.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2022</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,5 +36,6 @@
<xi:include href="c_portdriver.xml"/>
<xi:include href="cnode.xml"/>
<xi:include href="nif.xml"/>
+ <xi:include href="debugging.xml"/>
</part>
diff --git a/system/doc/tutorial/xmlfiles.mk b/system/doc/tutorial/xmlfiles.mk
index 74e174f6d4..a2c024d2dd 100644
--- a/system/doc/tutorial/xmlfiles.mk
+++ b/system/doc/tutorial/xmlfiles.mk
@@ -1,7 +1,8 @@
+
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2018. All Rights Reserved.
+# Copyright Ericsson AB 2009-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,7 +20,8 @@
#
TUTORIAL_CHAPTER_FILES = \
introduction.xml\
- overview.xml
+ overview.xml\
+ debugging.xml
TUTORIAL_CHAPTER_GEN_FILES = \
cnode.xml\
diff --git a/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf b/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
index 6d6f5750e3..3505c8c133 100644
--- a/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
+++ b/xcomp/erl-xcomp-TileraMDE2.0-tilepro.conf
@@ -47,16 +47,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=tile
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-arm-android.conf b/xcomp/erl-xcomp-arm-android.conf
index 361a779716..930781b25d 100644
--- a/xcomp/erl-xcomp-arm-android.conf
+++ b/xcomp/erl-xcomp-arm-android.conf
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2009-2021. All Rights Reserved.
+## Copyright Ericsson AB 2009-2022. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
@@ -46,23 +46,23 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=arm-linux-androideabi
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
# `configure' script.
# Set --enable-builtin-zlib to avoid a inflateGetDictionary missing symbol
erl_xcomp_configure_flags="--without-termcap --without-wx \
- --enable-builtin-zlib"
+ --enable-builtin-zlib --enable-deterministic-build"
## -- Cross Compiler and Other Tools -------------------------------------------
@@ -72,9 +72,13 @@ erl_xcomp_configure_flags="--without-termcap --without-wx \
# Previously with older Android NDK versions before NDK r14, each Android
# API level had a different set of headers, each in its own directory.
#NDK_SYSROOT=$NDK_ROOT/platforms/$NDK_PLAT/arch-arm
-# Starting with Android NDK r14, a single set of headers (called Unified Headers)
-# is provided in one location for every Android API level.
-NDK_SYSROOT=$NDK_ROOT/sysroot
+# Starting with Android NDK r14, a single set of headers (called Unified
+# Headers) is provided in one location for every Android API level.
+#NDK_SYSROOT=$NDK_ROOT/sysroot
+# Starting with Android NDK r19, the actual sysroot path is not needed
+# anymore as the NDK toolchain handles it implicitly.
+# For reference: https://github.com/android/ndk/issues/1407
+#NDK_SYSROOT=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/sysroot
## 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
@@ -187,7 +191,13 @@ LDFLAGS="-march=armv7-a -mfloat-abi=softfp -mthumb"
# 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="$NDK_SYSROOT"
+#
+# Previously for older Android NDK versions before NDK r19.
+#erl_xcomp_sysroot="$NDK_SYSROOT"
+# Starting with Android NDK r19, this path does not matter anymore
+# as the NDK toolchain handles the sysroot directory implicitly.
+# Set a value anyway to enable all applications as described above.
+erl_xcomp_sysroot=/sysroot/path/handled/by/the/Android/NDK
# * `erl_xcomp_isysroot' - The absolute path to the system root for includes
diff --git a/xcomp/erl-xcomp-arm-ios.conf b/xcomp/erl-xcomp-arm-ios.conf
new file mode 100644
index 0000000000..fd2c514f57
--- /dev/null
+++ b/xcomp/erl-xcomp-arm-ios.conf
@@ -0,0 +1,268 @@
+## -*-shell-script-*-
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2009-2021. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+## File: erl-xcomp-arm-ios.conf
+## Author: Dominic Letz
+##
+## -----------------------------------------------------------------------------
+## 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=arm-apple-ios
+
+# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
+# `configure' script.
+erl_xcomp_configure_flags="--without-termcap --without-wx \
+ --without-javac --without-odbc \
+ --without-debugger --without-observer --without-cdv --without-et \
+ --enable-builtin-zlib --enable-static-nifs --enable-static-drivers"
+
+
+## -- 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.
+
+export XCOMP_SDK=iphoneos
+export XCOMP_SDKROOT=`xcrun -sdk $XCOMP_SDK --show-sdk-path`
+export XCOMP_ARCH="-arch armv7"
+
+# * `CC' - C compiler.
+CC="xcrun -sdk $XCOMP_SDK cc $XCOMP_ARCH"
+
+# * `CFLAGS' - C compiler flags.
+CFLAGS="-mios-version-min=7.0.0 -fno-common -Os -D__IOS__=yes"
+
+# * `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="xcrun -sdk $XCOMP_SDK c++ $XCOMP_ARCH"
+
+# * `CXXFLAGS' - C++ compiler flags.
+CXXFLAGS=$CFLAGS
+
+# * `LD' - Linker.
+LD="xcrun -sdk $XCOMP_SDK ld $XCOMP_ARCH"
+
+# * `LDFLAGS' - Linker flags.
+LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -lc++ -v"
+
+# * `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=$LD
+
+# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
+DED_LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -r -v"
+
+# * `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="xcrun -sdk $XCOMP_SDK ranlib"
+
+# * `AR' - `ar' archiving tool.
+AR="xcrun -sdk $XCOMP_SDK 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=$XCOMP_SDKROOT
+
+
+# * `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=
+
+# * `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=
+
+# * `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-arm-linux.conf b/xcomp/erl-xcomp-arm-linux.conf
index 00b3b0b94b..fba73ebf61 100644
--- a/xcomp/erl-xcomp-arm-linux.conf
+++ b/xcomp/erl-xcomp-arm-linux.conf
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=arm-wrs-linux-gnueabi
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-arm64-android.conf b/xcomp/erl-xcomp-arm64-android.conf
index 6efd89a4fc..665dad1d5f 100644
--- a/xcomp/erl-xcomp-arm64-android.conf
+++ b/xcomp/erl-xcomp-arm64-android.conf
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2019-2021. All Rights Reserved.
+## Copyright Ericsson AB 2019-2022. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
@@ -46,23 +46,23 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=aarch64-linux-android
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
# `configure' script.
# Set --enable-builtin-zlib to avoid a inflateGetDictionary missing symbol
erl_xcomp_configure_flags="--without-termcap --without-wx \
- --enable-builtin-zlib"
+ --enable-builtin-zlib --enable-deterministic-build"
## -- Cross Compiler and Other Tools -------------------------------------------
@@ -72,9 +72,13 @@ erl_xcomp_configure_flags="--without-termcap --without-wx \
# Previously with older Android NDK versions before NDK r14, each Android
# API level had a different set of headers, each in its own directory.
#NDK_SYSROOT=$NDK_ROOT/platforms/$NDK_PLAT/arch-arm
-# Starting with Android NDK r14, a single set of headers (called Unified Headers)
-# is provided in one location for every Android API level.
-NDK_SYSROOT=$NDK_ROOT/sysroot
+# Starting with Android NDK r14, a single set of headers (called Unified
+# Headers) is provided in one location for every Android API level.
+#NDK_SYSROOT=$NDK_ROOT/sysroot
+# Starting with Android NDK r19, the actual sysroot path is not needed
+# anymore as the NDK toolchain handles it implicitly.
+# For reference: https://github.com/android/ndk/issues/1407
+#NDK_SYSROOT=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/sysroot
## 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
@@ -123,7 +127,9 @@ CXX="aarch64-linux-$NDK_ABI_PLAT-clang++"
LD="aarch64-linux-android-ld"
# * `LDFLAGS' - Linker flags.
-#LDFLAGS=
+# Use the static version of libc++ provided by the Android NDK
+# when compiling the JIT flavor of the beam.smp executable.
+LDFLAGS="-static-libstdc++"
# * `LIBS' - Libraries.
#LIBS=
@@ -177,7 +183,13 @@ LD="aarch64-linux-android-ld"
# 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="$NDK_SYSROOT"
+#
+# Previously for older Android NDK versions before NDK r19.
+#erl_xcomp_sysroot="$NDK_SYSROOT"
+# Starting with Android NDK r19, this path does not matter anymore
+# as the NDK toolchain handles the sysroot directory implicitly.
+# Set a value anyway to enable all applications as described above.
+erl_xcomp_sysroot=/sysroot/path/handled/by/the/Android/NDK
# * `erl_xcomp_isysroot' - The absolute path to the system root for includes
diff --git a/xcomp/erl-xcomp-arm64-ios.conf b/xcomp/erl-xcomp-arm64-ios.conf
new file mode 100644
index 0000000000..c81004484c
--- /dev/null
+++ b/xcomp/erl-xcomp-arm64-ios.conf
@@ -0,0 +1,269 @@
+## -*-shell-script-*-
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2009-2021. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+## File: erl-xcomp-arm64-ios.conf
+## Author: Dominic Letz
+##
+## -----------------------------------------------------------------------------
+## 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=arm64-apple-ios
+
+# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
+# `configure' script.
+erl_xcomp_configure_flags="--without-termcap --without-wx \
+ --without-javac --without-odbc \
+ --without-debugger --without-observer --without-cdv --without-et \
+ --enable-builtin-zlib --enable-static-nifs --enable-static-drivers \
+ --disable-jit"
+
+
+## -- 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.
+
+export XCOMP_SDK=iphoneos
+export XCOMP_SDKROOT=`xcrun -sdk $XCOMP_SDK --show-sdk-path`
+export XCOMP_ARCH="-arch arm64"
+
+# * `CC' - C compiler.
+CC="xcrun -sdk $XCOMP_SDK cc $XCOMP_ARCH"
+
+# * `CFLAGS' - C compiler flags.
+CFLAGS="-mios-version-min=7.0.0 -fno-common -Os -D__IOS__=yes"
+
+# * `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="xcrun -sdk $XCOMP_SDK c++ $XCOMP_ARCH"
+
+# * `CXXFLAGS' - C++ compiler flags.
+CXXFLAGS=$CFLAGS
+
+# * `LD' - Linker.
+LD="xcrun -sdk $XCOMP_SDK ld $XCOMP_ARCH"
+
+# * `LDFLAGS' - Linker flags.
+LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -lc++ -v"
+
+# * `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=$LD
+
+# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
+DED_LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -r -v"
+
+# * `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="xcrun -sdk $XCOMP_SDK ranlib"
+
+# * `AR' - `ar' archiving tool.
+AR="xcrun -sdk $XCOMP_SDK 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=$XCOMP_SDKROOT
+
+
+# * `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=
+
+# * `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=
+
+# * `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-arm64-iossimulator.conf b/xcomp/erl-xcomp-arm64-iossimulator.conf
new file mode 100644
index 0000000000..097752664a
--- /dev/null
+++ b/xcomp/erl-xcomp-arm64-iossimulator.conf
@@ -0,0 +1,269 @@
+## -*-shell-script-*-
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2009-2021. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+## File: erl-xcomp-arm64-iossimulator.conf
+## Author: Dominic Letz
+##
+## -----------------------------------------------------------------------------
+## 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=arm64-apple-iossimulator
+
+# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
+# `configure' script.
+erl_xcomp_configure_flags="--without-termcap --without-wx \
+ --without-javac --without-odbc \
+ --without-debugger --without-observer --without-cdv --without-et \
+ --enable-builtin-zlib --enable-static-nifs --enable-static-drivers \
+ --disable-jit"
+
+
+## -- 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.
+
+export XCOMP_SDK=iphonesimulator
+export XCOMP_SDKROOT=`xcrun -sdk $XCOMP_SDK --show-sdk-path`
+export XCOMP_ARCH="-arch arm64"
+
+# * `CC' - C compiler.
+CC="xcrun -sdk $XCOMP_SDK cc $XCOMP_ARCH"
+
+# * `CFLAGS' - C compiler flags.
+CFLAGS="-mios-simulator-version-min=7.0.0 -fno-common -Os -D__IOS__=yes"
+
+# * `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="xcrun -sdk $XCOMP_SDK c++ $XCOMP_ARCH"
+
+# * `CXXFLAGS' - C++ compiler flags.
+CXXFLAGS=$CFLAGS
+
+# * `LD' - Linker.
+LD="xcrun -sdk $XCOMP_SDK ld $XCOMP_ARCH"
+
+# * `LDFLAGS' - Linker flags.
+LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -lc++ -v"
+
+# * `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=$LD
+
+# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
+DED_LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -r -v"
+
+# * `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="xcrun -sdk $XCOMP_SDK ranlib"
+
+# * `AR' - `ar' archiving tool.
+AR="xcrun -sdk $XCOMP_SDK 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=$XCOMP_SDKROOT
+
+
+# * `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=
+
+# * `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=
+
+# * `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-armv8-rpi3-linux-gnueabihf.conf b/xcomp/erl-xcomp-armv8-rpi3-linux-gnueabihf.conf
index dffc4a4b56..0e691f416d 100644
--- a/xcomp/erl-xcomp-armv8-rpi3-linux-gnueabihf.conf
+++ b/xcomp/erl-xcomp-armv8-rpi3-linux-gnueabihf.conf
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2009-2018. All Rights Reserved.
+## Copyright Ericsson AB 2009-2021. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
@@ -48,16 +48,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=armv8-rpi3-linux-gnueabihf
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf b/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
index f64de31688..3fae18d26a 100644
--- a/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
+++ b/xcomp/erl-xcomp-avr32-atmel-linux-gnu.conf
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=avr32-atmel-linux-gnu
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-host-iossimulator.conf b/xcomp/erl-xcomp-host-iossimulator.conf
new file mode 100644
index 0000000000..ad7ea077cf
--- /dev/null
+++ b/xcomp/erl-xcomp-host-iossimulator.conf
@@ -0,0 +1,268 @@
+## -*-shell-script-*-
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2009-2021. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+## File: erl-xcomp-host-iossimulator.conf
+## Author: Dominic Letz
+##
+## -----------------------------------------------------------------------------
+## 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=`arch`-apple-iossimulator
+
+# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
+# `configure' script.
+erl_xcomp_configure_flags="--without-termcap --without-wx \
+ --without-javac --without-odbc \
+ --without-debugger --without-observer --without-cdv --without-et \
+ --enable-builtin-zlib --enable-static-nifs --enable-static-drivers"
+
+
+## -- 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.
+
+export XCOMP_SDK=iphonesimulator
+export XCOMP_SDKROOT=`xcrun -sdk $XCOMP_SDK --show-sdk-path`
+export XCOMP_ARCH="-arch `arch`"
+
+# * `CC' - C compiler.
+CC="xcrun -sdk $XCOMP_SDK cc $XCOMP_ARCH"
+
+# * `CFLAGS' - C compiler flags.
+CFLAGS="-mios-simulator-version-min=7.0.0 -fno-common -Os -D__IOS__=yes"
+
+# * `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="xcrun -sdk $XCOMP_SDK c++ $XCOMP_ARCH"
+
+# * `CXXFLAGS' - C++ compiler flags.
+CXXFLAGS=$CFLAGS
+
+# * `LD' - Linker.
+LD="xcrun -sdk $XCOMP_SDK ld $XCOMP_ARCH"
+
+# * `LDFLAGS' - Linker flags.
+LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -lc++ -v"
+
+# * `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=$LD
+
+# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
+DED_LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -r -v"
+
+# * `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="xcrun -sdk $XCOMP_SDK ranlib"
+
+# * `AR' - `ar' archiving tool.
+AR="xcrun -sdk $XCOMP_SDK 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=$XCOMP_SDKROOT
+
+
+# * `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=
+
+# * `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=
+
+# * `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-mips-linux.conf b/xcomp/erl-xcomp-mips-linux.conf
index 2d17aafbcf..f7d52c4c36 100644
--- a/xcomp/erl-xcomp-mips-linux.conf
+++ b/xcomp/erl-xcomp-mips-linux.conf
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=mips-linux
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf b/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf
index eba1110a05..7415e664fa 100644
--- a/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf
+++ b/xcomp/erl-xcomp-powerpc-dso-linux-gnu.conf
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=powerpc-wrs-linux-gnu
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-powerpc64-bgq-linux.conf b/xcomp/erl-xcomp-powerpc64-bgq-linux.conf
index c84a718eb5..9222d349ab 100644
--- a/xcomp/erl-xcomp-powerpc64-bgq-linux.conf
+++ b/xcomp/erl-xcomp-powerpc64-bgq-linux.conf
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=powerpc64-bgq-linux
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp-x86_64-android.conf b/xcomp/erl-xcomp-x86_64-android.conf
index 6c9747353d..91041ae3a8 100644
--- a/xcomp/erl-xcomp-x86_64-android.conf
+++ b/xcomp/erl-xcomp-x86_64-android.conf
@@ -2,7 +2,7 @@
##
## %CopyrightBegin%
##
-## Copyright Ericsson AB 2021. All Rights Reserved.
+## Copyright Ericsson AB 2021-2022. All Rights Reserved.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
@@ -46,22 +46,22 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=x86_64-linux-android
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
# `configure' script.
-erl_xcomp_configure_flags="--disable-hipe --without-termcap --without-wx \
- --enable-builtin-zlib"
+erl_xcomp_configure_flags="--without-termcap --without-wx \
+ --enable-builtin-zlib --enable-deterministic-build"
## -- Cross Compiler and Other Tools -------------------------------------------
@@ -101,7 +101,9 @@ CXX=x86_64-linux-$NDK_ABI_PLAT-clang++
LD=x86_64-linux-android-ld.gold
# * `LDFLAGS' - Linker flags.
-#LDFLAGS=
+# Use the static version of libc++ provided by the Android NDK
+# when compiling the JIT flavor of the beam.smp executable.
+LDFLAGS="-static-libstdc++"
# * `LIBS' - Libraries.
#LIBS=
@@ -155,7 +157,11 @@ LD=x86_64-linux-android-ld.gold
# 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="$NDK_ROOT/sys_root"
+#
+# Starting with Android NDK r19, this path does not matter anymore
+# as the NDK toolchain handles the sysroot directory implicitly.
+# Set a value anyway to enable all applications as described above.
+erl_xcomp_sysroot=/sysroot/path/handled/by/the/Android/NDK
# * `erl_xcomp_isysroot' - The absolute path to the system root for includes
# of the cross compilation environment. If not set, this value defaults
diff --git a/xcomp/erl-xcomp-x86_64-iossimulator.conf b/xcomp/erl-xcomp-x86_64-iossimulator.conf
new file mode 100644
index 0000000000..e62126fd15
--- /dev/null
+++ b/xcomp/erl-xcomp-x86_64-iossimulator.conf
@@ -0,0 +1,269 @@
+## -*-shell-script-*-
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2009-2021. All Rights Reserved.
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+## %CopyrightEnd%
+##
+## File: erl-xcomp-x86_64-iossimulator.conf
+## Author: Dominic Letz
+##
+## -----------------------------------------------------------------------------
+## 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=x86_64-apple-iossimulator
+
+# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
+# `configure' script.
+erl_xcomp_configure_flags="--without-termcap --without-wx \
+ --without-javac --without-odbc \
+ --without-debugger --without-observer --without-cdv --without-et \
+ --enable-builtin-zlib --enable-static-nifs --enable-static-drivers \
+ --disable-jit"
+
+
+## -- 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.
+
+export XCOMP_SDK=iphonesimulator
+export XCOMP_SDKROOT=`xcrun -sdk $XCOMP_SDK --show-sdk-path`
+export XCOMP_ARCH="-arch x86_64"
+
+# * `CC' - C compiler.
+CC="xcrun -sdk $XCOMP_SDK cc $XCOMP_ARCH"
+
+# * `CFLAGS' - C compiler flags.
+CFLAGS="-mios-simulator-version-min=7.0.0 -fno-common -Os -D__IOS__=yes"
+
+# * `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="xcrun -sdk $XCOMP_SDK c++ $XCOMP_ARCH"
+
+# * `CXXFLAGS' - C++ compiler flags.
+CXXFLAGS=$CFLAGS
+
+# * `LD' - Linker.
+LD="xcrun -sdk $XCOMP_SDK ld $XCOMP_ARCH"
+
+# * `LDFLAGS' - Linker flags.
+LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -lc++ -v"
+
+# * `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=$LD
+
+# * `DED_LDFLAGS' - Linker flags to use with `DED_LD'.
+DED_LDFLAGS="-L$XCOMP_SDKROOT/usr/lib/ -r -v"
+
+# * `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="xcrun -sdk $XCOMP_SDK ranlib"
+
+# * `AR' - `ar' archiving tool.
+AR="xcrun -sdk $XCOMP_SDK 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=$XCOMP_SDKROOT
+
+
+# * `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=
+
+# * `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=
+
+# * `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-x86_64-saf-linux-gnu.conf b/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
index 7708ec8c19..b5b5cdb5ad 100644
--- a/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
+++ b/xcomp/erl-xcomp-x86_64-saf-linux-gnu.conf
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
erl_xcomp_host=x86_64-saf-linux-gnu
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the
diff --git a/xcomp/erl-xcomp.conf.template b/xcomp/erl-xcomp.conf.template
index c5f15e89b6..4c9b269111 100644
--- a/xcomp/erl-xcomp.conf.template
+++ b/xcomp/erl-xcomp.conf.template
@@ -46,16 +46,16 @@
# `--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',
+# `$ERL_TOP/make/autoconf/config.sub $erl_xcomp_build'. If set to `guess',
# the build system will be guessed using
-# `$ERL_TOP/erts/autoconf/config.guess'.
+# `$ERL_TOP/make/autoconf/config.guess'.
#erl_xcomp_build=
# * `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_TOP/make/autoconf/config.sub $erl_xcomp_host'.
#erl_xcomp_host=
# * `erl_xcomp_configure_flags' - Extra configure flags to pass to the